pari-2.17.2/0000755000175000017500000000000014760315601011167 5ustar billbillpari-2.17.2/README0000644000175000017500000000670714760123736012067 0ustar billbillThis is PARI/GP, version 2.17.x (*). PARI/GP Number Theory-oriented Computer Algebra System Copyright (C) 2000-2024 The PARI Group, Bordeaux. ========================================================================== To get started, run cd doc; tex INSTALL.tex and have a look at the file INSTALL.dvi, extracted verbatim from Appendix A of the User Manual. (Or pdftex INSTALL.tex if PDF files are more convenient.) If you are in a hurry, look at the ASCII file 'INSTALL' but a lot of information is missing there. Once 'Configure' has been run, 'make doc' typesets separate user's manual for GP and libpari, a tutorial and reference card in directory doc. The file NEW contains new features with respect to previous stable versions. The file COMPAT warns about incompatible changes. See the files CHANGES* for a terse description of successive patches. For the adventurous: to check out bleeding-edge development versions of PARI/GP, see the file README-git. Afterwards, you're on your own. ========================================================================== There are three mailing lists devoted to the PARI/GP package, and most feedback should be directed to those. They are: * pari-announce: to announce major version changes. You can't write to this one, but you should probably subscribe. * pari-dev: for everything related to the development of PARI, including suggestions, technical questions, bug reports or patch submissions. * pari-users: for everything else. To subscribe, send empty messages respectively to pari-announce-request@pari.math.u-bordeaux.fr pari-users-request@pari.math.u-bordeaux.fr pari-dev-request@pari.math.u-bordeaux.fr with a Subject: containing the word "subscribe". If you are not a member of any of those lists and do not want to become one, you can write to us at pari@math.u-bordeaux.fr We may forward your mail to the lists above and will definitely try to correct faulty behaviour, if necessary. But we cannot promise that you will get an individual answer. Last but not least, PARI home page can be found at https://pari.math.u-bordeaux.fr/ Thanks for your support, and have fun ! ======================================================================== PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. (*) Version numbers have the shape: MAJOR.MINOR.patchlevel.status. The status increases through {alpha, beta, release}. New features are introduced during the `alpha' phase, tested during `beta', and declared stable when `release' is reached. The MAJOR version number will not change for a while. The MINOR version number increases by 2 when a new status cycle starts (as soon as a 'release' version is out): odd numbers are reserved for 'released' versions, even ones for alpha/beta phase. The patchlevel goes up each time we feel an upgrade is necessary (improvement or bugfix). 'Release' versions may be updated with further patchlevels if important bugs need to be fixed before the next cycle reaches completion. pari-2.17.2/COMPAT0000644000175000017500000016464614760123736012124 0ustar billbillThis file lists the incompatible changes between Version 2.x and older versions %%%%%%%%%%%%%%%%%%%%%%%%%%%% VERSION 2.16 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - binomial changed to agree with Loeb's definition binomial(n, k) = lim_{t->1} gamma(n+t) / gamma(k+t) / gamma(n-k+t) This is incompatible with the old definition (= 0) when k <= n < 0 are negative integers. - default 'primelimit' is now 2^20 [instead of 500000] - lfunabelianrelinit. Removed: Use lfunfinit([bnr, subgroup]) instead. - change behaviour of Vec(v, n) when n < 0 and |n| < #v Vec([1,2,3], -2) -> [2,3] (was [1,2]) Same for Vecrev, Vecsmall, Col, and Colrev. - alginit: the previous behaviour of alginit(,,,0) (compute Hasse invariants but not a maximal order) is now obtained with alginit(,,,2); the previous behaviour of alginit(,,,1) (compute Hasse invariants and a maximal order) is now obtained with alginit(,,,3). * Specific to the PARI library: =============================== - t_SER: valser, evalvalser, setvalser must be used instead of valp, evalvalp, setvalp - cgetalloc arguments swapped to mirror cgetg's definition and conform to documentation - dirpowerssum: add argument flag 'both' - RgX_halfgcd now only return the matrix. Use RgX_halfgcd_all. - ec_bmodel, ec_phi2 now take a variable number (you can set it to 0). - quadclassnoF_fact and uquadclassnoF_fact now return h(D)/h(d), like quadclassnoF. - ZX_compositum_disjoint: renamed to ZX_composedsum - qfb_apply_ZM renamed to qfb_ZM_apply, qf_apply_RgM renamed to qf_RgM_apply, qf_apply_ZM renamed to qf_ZM_apply - the argument "prec" for precision (returned by realprec) is now a number of bits (but must be multiple of BITS_IN_LONG) - suminf_bitprec: use suminf instead (with same arguments) intnumromb_bitprec: use intnumromb instead (with same arguments) ellL1_bitprec, ellanalyticrank_bitprec: use ellL1, ellanalyticrank - the diffptr low level interface is gone (table of difference of primes), replaced by a table of 32bit primes (pari_PRIMES). The byteptr type and following functions / macros are gone: initprimes, functions and macros are gone: initprimes, init_primepointer_geq, init_primepointer_gt, init_primepointer_leq, init_primepointer_lt NEXT_PRIME_VIADIFF, PREC_PRIME_VIADIFF, NEXT_PRIME_VIADIFF_CHECK. %%%%%%%%%%%%%%%%%%%%%%%%%%%% VERSION 2.14 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - qfbredsl2(q, S): change format of S: was [D,isD], is now isD - elltwist now returns an ellinit, and accepts the same input formats as ellinit ([a1,a2,a3,a4,a6], [a4,a6], Cremona label) - default(debugfiles,) is now obsolete, use setdebug("io",) - system() now return the shell return value - genus2red 3rd component is now a pair [P,Q] such that y^2+Q*y=P is minimal everywhere. * Specific to the PARI library: =============================== - dirpowerssum0 now requires an extra argument f to allow a completely multiplicative function (can be set to NULL, i.e. constant function = 1) - FqV_to_FlxV, FqC_to_FlxC, FqM_to_FlxM: replaced by ZXC_to_FlxC, ZXM_to_FlxM - ZXX_to_Kronecker -> RgXX_to_Kronecker, ZXX_to_Kronecker_spec -> RgXX_to_Kronecker_spec - nbessel -> ybessel (according to the new GP name bessely) - ZC_u_divexact -> ZC_divexactu - removed obsolete functions qfi, qfr, qfi_1, qfr_1, redreal, redrealnod, rhoreal, rhorealnod, qfrsqr, qfrsqrraw, qfrcomp, qfrcompraw, qfisqrraw, qficompraw, qfipowraw, qfipow, redimag - unify real and imaginary binary quadratic forms, include discriminant types t_QFI and t_QFR are replaced by t_QFB - gp_read_stream now returns NULL when EOF is reached (used to be gnil). - gen_search / vecvecsmall_search: remove flag; the result is now positive if the element is found else -i if element should be inserted at position i. - Z_smoothen now uses (and returns) t_VEC arguments. Use Z_lsmoothen to input small primes as a t_VECSMALL. - QXX_QXQ_eval: renamed to QXY_QXQ_evalx - ZX_Zp_root(f,a,p,): assume 0 <= a < p - gen_factorback: require extra parameter 'one'. Use NULL for old behavior. - absZ_factor_limit_strict no longer guarantees that q is composite: this is useless for applications and possibly expensive - the global variable DEBUGFILES is no longer available - nfinitall is now obsolete; use nfinit with the same arguments - renamed normalize -> normalizeser - order is gone: use znorder %%%%%%%%%%%%%%%%%%%%%%%%%%%% VERSION 2.12 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - the member function bnf.futu and .tufu (deprecated since 2.2) have been removed. If needed, write your own helper function using bnf.fu and bnf.tu. - lfunconductor(L, [a,b]) no longer supported to look for conductor in interval [a,b]; implement lfunconductor(L, list of potential N) instead - renamed GP functions Strchr -> strchr (pari_strchr in libpari), Strexpand -> strexpand, Strprintf -> strprintf, Strtex -> strtex - limitnum / asympnum: remove useless optional parameter 'muli/k' [now implicitly set to 1, not to 20]: just extrapolate u(muli*n). - besseln is now obsolete, use bessely - polinterpolate(X,Y,t,&e): e is now more precisely defined and the error estimate is given as a binary exponent; compared to the value dy returned up to this change, we have e = exponent(dy). - suminf is now sensitive to bit precision. In library mode, use suminf_bitprec (precision in bits) rather than the historical suminf (precision in words) - rename libpari function rootsof1 -> nfrootsof1 - rename libpari function isirreducible -> polisirreducible - rename libpari function perf -> qfperfection - remove libpari function rootsof1_kannan: use nfrootsof1 - use the documented semantic for Euclidean division involving real t_QUAD e.g. x % y is x - floor(x/y)*y; for a t_QUAD x and t_INT y, we used to mod out y in "real" and "imaginary" part independently. - rename libpari function rootpadic -> polrootspadic - change definition of lfunhardy for non-self-dual functions: remove rootnumber, which is not well defined since it depends on the choice of dual sequence a^*(n). And the function is not real-valued in any case. - parsum: removed optional argument [allows grouping of subsums => faster] - the function 'bnfcompress' has been removed. That compressed format complicated the code base, prevented planned extensions of the 'bnf' format and was not very useful: the best compression of a number field is the defining polynomial, from which everything can be recomputed. Additionally, compared to a 'writebin' of the 'bnf' structure compressed by gzip, the old 'bnfcompress' typically achieved ~ 75% compression, with compression running times often comparable to the computation of a new bnfinit from scratch, and expensive decompression as well. It was not a useful format for storage. - the 'bnf' structure has changed to allow compact units and principal ideal generators: a new bnf can be read and used in an older pari version, but a bnf from an old version can no longer be used in this version: recompute it ! - matrixqz(,-1 or -2) no longer return result in HNF [often dominant!]. If needed, call explicitly mathnf or mathnfmod with the algorithm adapted to your situation. - bnfisunit and bnfissunit: torsion unit exponent is now a t_INT (used to be a t_INTMOD) - nfgaloisconj(deg 2 pol) now return the identity as the second automorphism to follow nfroots and nfgaloisconj for higher degree. - rnfkummer: removed "all" flag, use bnrclassfield ! - remove zetamultinit and corresponding optional argument in zetamult * Specific to the PARI library: =============================== - remove inferior hash function hash_str2: use hash_str - precision0 / bitprecision0 (meant to implement GP-specific commands, not for library use) are now obsolete. The new equivalent commands (still not meant for library use) are precision00 and bitprecision00. - gen_factorback: change argument order to match other functions. - pari_add_hist now take 3 arguments (data, cpu time, real time) - gp_format_time: remove trailing ".\n" from formatted string - nfbasis prototype changed: 3rd argument listP is gone, use nfbasis(mkvec2(T,listP), &disc). Note that the documentation was incorrect: it is not guaranteed that nfbasis([T, listP]) returns the maximal order even if listP contains all prime divisors of the field discriminant. See ??nfbasis - old gen_ZpM_Dixon renamed to gen_ZpM_Dixon_Wiedemann, new gen_ZpM_Dixon with simpler interface - QXQ_div_ratlift was renamed to QXQ_div - Z_to_F2x(x,v): v is now a shifted variable number - bnrconductor_i is now obsolete, use bnrconductor_raw or bnrconductormod - bnrsurjection now returns [Matrix, cyc(F), cyc(f)] inste of Matrix - zetamultall prototype change: added flag - remove obsolete function checkbnrgen: use bnr_get_gen(bnr) - ZM_lll / ZM_lll_norms: flags LLL_INPLACE and LLL_GRAM are now incompatible (reducing a Gram matrix in place without returning the base change matrix is not useful; supporting it would complicate the code) - the global C variable logstyle was renamed to pari_logstyle - perm_pow prototype was changed to take a GEN exponent. - perm_order and permorder prototypes were changed to return a GEN. * Specific to the pthread interface =================================== - pari_thread_sync is not needed anymore and has been removed. %%%%%%%%%%%%%%%%%%%%%%%%%%%% VERSION 2.10 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - the bid struct from idealstar has changed, the new format is not compatible with pari-2.9 - the rnf struct from rnfinit has changed, the new format is not compatible with pari-2.9 - the bnrdisclist output is now and ordinary vector (not a vector of vectors) - sumnummonieninit(a) for [a,a] did not conform to documentation. Change to sumnummonieninit(b) for [1,b] - lfuncreate() change of format for (p,d)->Lp closure: - Lp here and in bad primes [p,Lp] must now use the actual local factor and not its inverse - d is now the exact number of terms needed (was 1 less), i.e. one need only return Lp + O(x^d) - bad primes are given as a separate 2nd component: [Lp, [[p1,L1],...[pk,Lk]]], not as [Lp, [p1,L1],...[pk,Lk]] - nf struct: nf[7] now stores nf.zk / content(nf.zk). Old format is still supported (to read in data involving old-style nf generated by gp version < 2.10) but incurs a speed penalty. - component(t_POL T, n) used to return polcoeff(T, n-1) for all n >= 1 [ undocumented compatibility behaviour, deprecated since the introduction of polcoeff ], and raised an exception for n <= 0. Now returns a true GEN component whenever it exists and raises an exception when it does not [ n <= 0 or n > polcoeff(T)+1 ]. - For T in Q_p[X], factor (round then compute multiplicity) and issquarefree (assume input is separable) did not agree. Now, factor() repeats irreducible factors according to apparent multiplicity (note that the multiplicity is not well defined for inexact inputs, which are close to being inseparable, i.e. v_p( disc(T) ) is large compared to the input accuracy). OTOH, factorpadic with exact input is able to compute multiplicities reliably. - change polred-type algorithm to return 'x' (no longer 'x-1') for the field of rational numbers (make it consistent with polredabs). The documentation now only guarantees a 'polynomial of degree 1' - ellisomat: ellisomat(E,flag) is now ellisomat(E,,flag) - changed the definition used in polred / polredbest / polredabs to decide what is the "best" polynomial to return. This had never been specified in the documentation; while making explicit the de facto choices made in the code, it was decided to make it mathematically more appealing. There is no efficiency tradeoff involved: we are just replacing an arbitrary definition by another less arbitrary one, with the same implied costs. - ellpadicmatrix now returns a pair of matrices (instead of a matrix whose entries are pairs of values) - ellpadicheight and ellpadicmatrix no longer accept [p,[a,b]] arguments; use * [a,b]~ - msissymbol now returns a GEN (gen_0/gen_1) instead of a long - V=galoisfixedfield(P,,2): return V[1] in the same variable as the coeffs of V[3] instead of P. - numtoperm now returns a t_VECSMALL (so that results can be multiplied as permutations, etc.), no longer a ZV - The functions psdraw, psploth and psplothraw and the default psfile are obsolete. Use one of plotexport, plothexport or plothrawexport with format "ps" and write the result to file. - isprime(n,1) no longer outputs a certificate, use primecert(n) - isprime(n,1) no longer uses APRCL for large prime divisors of n-1 (pure Pocklington-Lehmer-Selfridge); use primecert(n). - removed useless (optional) flag argument in polrootsmod - factorff and polrootsff are now obsolete. Use factormod/polrootsmod - Ser(s, 'x, d) now always return a series with d significant terms. It used to return a t_SER s in 'x verbatim and to use all given coefficients for a t_VEC/t_COL. Only if d is explicitly given, no change for Ser(s,'x) - renamed algsplittingmatrix -> algtomatrix - algleftmultable now always returns the multiplication table on the integral basis - merged algdecomposition + algsimpledec -> algsimpledec - merged algabsdim + algdim -> algdim - merged algleftmultable + algtomatrix -> algtomatrix - ellmoddegree now only returns the modular degree D (divided by c^2), not [D, err] - polcoeff is deprecated and renamed polcoef: it now only applies to scalars, polynomials, series and rational functions; no longer to vector/matrices or quadratic forms (use [] or "component"). - in prettymatrix format, no longer print all 0 x n matrices as [;]: use [;] iff n = 0 and matrix(0,n) otherwise * Specific to the PARI library: =============================== - renamed buchnarrow -> bnfnarrow - removed useless argument nf in ZC_nfval, ZC_nfvalrem, pr_equal, ZC_prdvd - prototype of FlxX_shift has changed - renamed FpX_fromdigits -> FpXV_FpX_fromdigits - renamed FpXQX_fromdigits -> FpXQXV_FpXQX_fromdigits - rename vecbinome -> vecbinomial - rename padic_lindep -> lindep_padic, Xadic_lindep -> lindep_Xadic - keri and ZM_ker_ratlift replaced by ZM_ker - Fl_addmul_pre: change arguments order to follow Fp_addmul convention - removed resultant_all, use RgX_resultant_all - rename {FpXQXQ,FlxqXQ,F2xqXQ}V_aut{sum,trace,pow} -> {FpXQXQ,FlxqXQ,F2xqXQ}_aut{sum,trace,pow} - RgX_type now only handles t_POL. Use RgX_type for other objects. - changed ZM_inv: remove denominator bound and replace by pointer to denominator - changed QM_inv interface: removed second argument (useless) - useless function Flx_roots_naive; rootmod and rootmod2 are now an alias for polrootsmod (both have been deprecated for years). rootmod0 is just as obsolete. - matsolvemod0 is deprecated, use matsolvemod - cmpiu / cmpiu, equaliu / equalui : no longer assume that t_INT argument is non-negative - rename diviu_rem -> absdiviu_rem, udiviu_rem -> uabsdiviu_rem, udivui_rem -> uabsdivui_rem - rename polcoeff0 -> polcoef, truecoeff -> truecoef, polcoeff_i -> polcoef_i - rename constant LOG2 -> M_LN2 (from math.h if available) - rnf_get_nfzk / nf_nfzk / nfeltup interface (czknf was useless, return and use nfzk) %%%%%%%%%%%%%%%%%%%%%%%%%%%% VERSION 2.8 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - removed useless function sumnumalt: use sumalt - replace algorithm behind sumnum / sumnuminit : replace Abel-Plana (slow, imprecise, forced to assume holomorphy and evaluate at complex values, yielding determination problems) by Euler MacLaurin (none of these disadvantages). The interface had to change : the (mandatory) abscissa of integration becomes meaningless, and the initialization possibilities are different. Please read the documentation ??sumnum and ??sumnuminit - t_STR used to compare as larger than any real number via < or > operators. Such a comparison now raises an exception. - valuation(0,p), nfeltval(nf,0,pr), idealval(nf,0) now all return +oo under GP [ used to return LONG_MAX ] - precision(0), bitprecision(0), padicprec(0,p) now all return +oo under GP [ used to return LONG_MAX ] - infinite slopes of newtonpoly replaced by +oo (instead of LONG_MAX) - poldegree(0) now returns -oo [ used to return -LONG_MAX ] - polsturm interface change * polsturm(T, a, b) is still supported but deprecated, use polsturm(T, [a,b]) * polsturm(T, a, b) used to return the number of roots in ]a,b], we now use the closed interval [a,b]: more intuitive given the new syntax, and compatible with polrootsreal() - nfdisc, nfbasis: no longer support the old (T,flag,fa) arguments. Use the generic [T,listP] syntax (see 2.6.0-C105) - factorpadic: no longer support the deprecated (no-op) 'flag' argument - optional flag to ellheight is gone (useless) - ellbil(E,P,Q) is now deprecated, use ellheight(E,P,Q) - default 'strictmatch' has been obsoleted. It is now a no-op. - default 'compatible' has been obsoleted. It is now a no-op. - GP and libpari polynomial variables of arbitrary priority can now be created: 'x' is no longer guaranteed to have maximal priority, nor MAXVARN to have minimal priority. - GP: polynomial variables no longer spring into existence unless a true t_POL/t_SER in the variable is needed. E.g. y = 0 does not create the "variable" y, thereby messing up variable ordering. - genus2red: change syntax. Allow either genus2red(P) or genus2red([P,Q]) instead of mandatory Q (was: genus2red(Q,P) with Q almost always 0). Allow uniformization with hyperellcharpoly - remove useless function intnuminitgen (not very useful and impossible to use reliably together with intnum with boundary conditions) - remove useless function intnumstep: instead of intnum(a,b, intnumstep()+m), use intnum(a,b,m) - remove partially implemented functions intfouriercos / intfouriersin / intfourierexp / intlaplaceinv / intmellininv / intmellinvshort: use intnum (possibly intfuncinit). Make sure to indicate oscillating behaviour when function decrease slowly at oo - remove optional flag to intfuncinit: misleading and only affords a 2 x speedup in an 'init' function (maybe reimplement later in a more general form...) - remove badly implemented functions zetakinit / zetak: the interface did not make sense (it is impossible to initialize for Dedekind zeta without specifying a domain where the function is to be evaluated). Closest equivalent to zetakinit: L = lfuninit(x^2+1, [c, w, h]); to compute zeta_Q(i)(s) for |Re(s - c)| < w, |Im(s)| < h. Then lfun(L, s) as an analog to zetak(). Or directly lfun(x^2+1, s) if a single value is needed. [closes #368, #1647] - rnfconductor now returns [cond, bnr, H] instead of [cond, bnr.clgp, H] - polredabs([T,listP]) no longer returns 0 if the attached order cannot be proven to be maximal: it computes the expected canonical polynomial in all cases, which can be very slow. Always use polredbest() if you don't require a canonical output. - meaning of precision(x, n) no longer depends on the type of x: it now always refers to floating point precision. Before the change: precision([O(2),O(3),O(x)], 10) -> [O(2^10),O(3^10),O(x^10)]. Now in order to truncate a p-adic or series, you have to multiply by 1 + O(t^n); in order to extend it, use truncate. - remove useless flag in idealappr: directly allow factorization - replace qfbil(x,y,{q}) by qfeval({q},x,y) and qfnorm(x,{q}) by qfeval({q},x): it makes more sense to have q first, and a single function for qf+polar form (as in all other qf-like routines: ellheight, etc.) - functions nfeltdivmodpr, nfeltmulmodpr, nfeltpowmodpr, nfeltreducemodpr, nfkermodpr, nfsolvemodpr are obsolete. Use nfmodpr, work in the finite field, then lift back using nfmodprlift. - changed bnf format (allow dynamically adding units): old bnfs will be detected as invalid. Dirty trick to force conversion: bnf[10]=vector(3); - changed idealstar format, to access data more conveniently (and avoid recomputations): old bid and bnr structures from versions up to 2.8.0 are now invalid - gcd(t_VEC/t_COL/t_MAT, ...) is now forbidden, same for lcm * Specific to the PARI library: =============================== - renamed RgX_mullow -> RgXn_mul, RgX_sqrlow -> RgXn_sqr, RgX_modXn_eval -> RgXn_eval, RgX_modXn_shallow -> RgXn_shallow - top and bot are replaced by pari_mainstack->top and pari_mainstack->bot. - allocatemem() is replaced by paristack_resize. - rootpadicfast was renamed to ZpX_roots - mkintn() now handles arguments as 32bit unsigned int on both 64/32 bits. - sturmpart(x, a, b) is deprecated, use RgX_sturmpart(x, ab) or (better) ZX_sturmpart(x, ab) - removed deprecated functions nfbasis0, nfdisc0, factorpadic0 - Flx_pow renamed to Flx_powu - [libpari] rename ghell->ellheight, mathell->ellheightmatrix - Rg_to_RgV renamed to Rg_to_RgC, RgX_to_RgV renamed to RgX_to_RgC - powruvec was replaced by powersr - renamed ZV_gcdext -> ZV_extgcd for consistency with other 'gcdext' methods - comment out libpari function names obsoleted during the 2.3.* cycle See PARI_OLD_NAMES. - ellsea is replaced by Fp_ellcard_SEA - rename PI -> M_PI - renamed row_zm -> zm_row, row_Flm -> Flm_row - nucomp now takes L = floor(|D|^(1/4)) as a 3rd argument. Former nucomp(x,n) is nucomp(x,n,NULL). - divide_conquer_assoc renamed to gen_product, divide_conquer_prod removed - rename concat to gconcat, concat1 to gconcat1 - rename Flc_Fl_mul -> Flv_Fl_mul, Flc_Fl_div -> Flv_Fl_div, RgC_to_Flc to RgV_to_Flv, F2c_to_Flc to F2v_to_Flv - rename leading_term -> leading_coeff, constant_term -> constant_coeff - Z_to_Flx now takes a shifted variable number, as Fl_to_Flx. - rename FlxqX_pow to FlxqX_powu - rename anell -> ellan, anellsmall -> ellanQ_zv - ellsea: the argument p was removed and the interface modified - renamed absi_cmp -> abscmpii, absr_cmp -> abscmprr, absi_equal -> absequalii, absi_factor -> absZ_factor, absi_factor_limit -> absZ_factor_limit, equaliu -> absequaliu, equalui -> absequalui, cmpiu -> abscmpiu, cmpui -> abscmpui - idealappr0 is obsolete: use idealappr - qfbil, qfnorm are obsolete: use qfeval0, qfeval or qfevalb - changed set_sign_mod_divisor prototype: module is now useless (implicitly contained in sarch argument), hence removed. - removed discrayabs, discrayabscond, discrayrel, discrayrelcond, discrayabslistlong: obsoleted since 2.0 - ZpX_liftfact no more handles extensions of Qp, use ZqX_liftfact for that - rename listcreate to mklist %%%%%%%%%%%%%%%%%%%%%%%%%%%% VERSION 2.6 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - eval() no longer evaluates its arguments in "permissive" mode: eval("1a") now produces a syntax error. - '|' is no longer a synonym for '||' (boolean 'or'); '&' for '&&' is still supported but deprecated. - GP set elements are no longer converted to t_STR (requiring "eval" to recover the underlying object). Arbitrary GENs can be stored in a set. - no longer allow 3 arguments in bestappr() [useless], no longer mix Pade approximants and continued fractions [too confusing: must a t_SER be converted to a t_RFRAC or be treated coefficientwise?]. Use bestapprPade() to obtain rational functions, and bestappr() to obtain rational numbers. - [non-Unix systems] the name of the preferences file is now "gprc.txt" (it remains ".gprc" on Unix systems) - removed rootsold() code : polroots(x, 1) is no longer accepted. - format of cached Bernoulli table: now a t_VEC of t_FRAC / t_REALs. Removed bern() macro. The new data must be accessed using bernfrac / bernreal. - forprime loop: no longer allow to modify the loop index ? forprime(p = 2, 10, p = []) *** at top-level: forprime(p=2,10,p=[]) *** ^--- *** prime index read-only: was changed to []. - rename ellpow -> ellmul - polrootsmod(, 4) is no longer accepted. The second argument must be prime. - binary(0) now return [] - arithmetic functions no longer accept vector / matrix arguments [ to later allow passing factorization matrices ]: use apply() - permtonum/numtoperm now use the standadr lexicographic numbering. - ellsigma: removed flags 3 and 4 [ inefficient algorithm using the product formula ] - removed member function 'w' (this is technical, and no longer needed:-) - ellpointtoz(E / Qp, ...), now return phi(P) [ used to return the same result for phi(P) and phi(-P) [ split multiplicative reduction ], resp. phi(P) + 1/phi(P) [ non-split reduction ] - ellinit(E / Qp).tate : the u component is now always a square root of u2, also in the non-split case (in which case it lives in a quadratic extension of Qp) - when timer = 1, no longer print timing if the time is negligible; in particular, no timing should be printed when defining a user function or and alias. - change nfbasis(T, flag, fa) to nfbasis(T, listP). flag was used to invoke round2 instead of round4 (inefficient=> useless) OR to only partially factor poldisc(T), up to primelimit (very dangerous since primelimit is a global variable). Now listP describes a list of primes, and we return a basis of an order which is p-maximal at all those primes: either a vector of primes, a factorisation (as fa before) or an integer B to indicated {p <= B} (a safe and flexible version of nfbasis(T, 1)). nfdisc() was changed similarly. - The proper way to initialize an nf structure when the polynomial discriminant is hard to factor is nfinit([T, listP]), where listP specifies a list of primes (see ??nfinit). nfdisc, nfbasis, all the polred functions allow analogous arguments. This is cleaner and more flexible than optionnal flags relying on the value primelimit (e.g. nfinit([T, nfbasis(T, 1)]), now deprecated). Also, the nfinit function now sees the local specifications directly and can take steps to fix problems. The result can also be certified (nfcertify) - renamed bezout() -> gcdext(), polresultant() -> polresultantext() - the prime table is now computed once and for all on startup and can no longer be increased by modifying primelimit: the dynamic forprime machinery allows fast primes up to primelimit^2 which is more than enough even with a small table. The default value of 500.000 is already larger than necessary - removed optional flag to factorpadic() / factorpadic0() [ enabling Buchman-Lenstra + round2 ] Use the default factorpadic(T, p, r), both under GP and in library mode. - default help text for a user function is now as in \u: ?fun produces fun = (args)->body - after addhelp(f,...), ?f no longer include default help text for a user function (function code). Type 'f' to see the function code. - rnf structure: added new components - lift(x,'v) / centerlift(x,'v) now only lift t_POLMODs in variable v, no longer (most) t_INTMOD / t_PADICs met along the way - rnf.pol (absolute defining polynomial / Q) is now called rnf.polabs, rnf.pol is now the relative polynomial, defining the relative extension over the base. - the prid structure returned by idealprimedec: the anti-uniformizer tau (pr_get_tau / pr[5]) is now stored via its multiplication table * Specific to the PARI library: =============================== - renamed all libpari error codes [ pari_err() arguments ] - ellwp0(): remove precdl argument - rename stackmalloc -> stack_malloc - rename ggval -> gvaluation - simplify init_primepointer(n, p, &pd) interface => init_primepointer(n, &pd). Remove argument 'p', ignore the previous value of pd [ remove assumption that it pointed into a prime table ] and always set pd to a pointer into the private prime table. - powell, addell, subell renamed to ellpow, elladd, ellsub. - last tow arguments of FpX_factorff and FpX_rootsff have been swapped. - rnf_fix_pol() takes an extra argument, the calling function's name - rename leftright_pow_fold -> gen_pow_fold, leftright_pow_fold_i -> gen_pow_fold_i - upowuu(x,n) now returns 0 on overflow. Used to return x^n mod 2^BITS_IN_LONG - rename RgX_check_ZXY -> RgX_check_ZXX, ZXY_max_lg -> to ZXX_max_lg - removed gisfundamental, gkronecker, gbigomega, geulerphi, gissquarefree, gmoebius, gnextprime, gnumbdiv, gomega, gprecprime, gsumdiv, gdumdivk, znprimroot0 - rename zv_cmp0 -> to zv_equal0 - removed obsolete function weipell(). Use ellwpseries() - the prototype of nfbasis() changed [ remove 'flag'; if you needed it, use nfmaxord() ]. The old nfbasis0 / nfdisc0 are deprecated: don't use them. - removed obsolete Polred(): use polred() or polredbest() - rename exp_Ir -> expIr - the *_invimage function no longer accept a t_COL second argument. Use the RgM_RgC_invimage variant. They now return NULL when no solution exist (used to return a t_COL / t_MAT of length 1) - the forvec_start() function has been replaced by a standard iterator: forvec_init() / forvec_next() - renamed rnfelementxxx -> rnfeltxxx, rnfidealhermite -> rnfidealhnf - removed useless wrappers map_proto_GG, map_proto_GL, map_proto_lGG - renamed ZM_hnfremdiv -> ZM_hnfdivrem - removed useless functions gand, gor - removed useless function ratlift [ use Fp_ratlift ] - renamed gcmpX -> gequalX - renamed ordred -> polredord: useless function, use polredbest! - renamed recip -> serreverse - renamed FlxYqQ_pow -> FlxYqq_pow - FpXYQQ_pow/FlxYqq_pow: the order of the moduli S,T have been swapped to match FpXQXQ_pow - renamed gsh -> gsinh, gch -> gcosh, gth -> gtanh, gash -> gasinh, gach -> gacosh, gath -> gatanh, ggamd -> ggammah (follow GP names) %%%%%%%%%%%%%%%%%%%%%%%%%%%% VERSION 2.4 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - The "break loop" is now *on* by default, and no longer controlled by trap(), but by the default 'breakloop'. To get out of a break loop, hit or type 'next', 'return', or 'break' - trap() no longer allows installing default error handlers. - GP's break loop is now *enabled* by default [ set breakloop = 0 in your gprc to disable it ] - random() now uses Brent's XORGEN (replaces congruential linear generator) As a consequence, getrand() returns the FSR internal state array, used by setrand() and the prototypes of both functions changed. To adapt simple library code, replace long seed = getrand(); ...; (void)setrand(seed); by GEN seed = getrand(); ...; setrand(seed); The sequence of generated pseudo-random numbers are completely different. - install(): parser code 'E' and 'I' now refer to closure, not strings: 'I': closure whose value is ignored, like in for() loop 'E': closure whose value is used, like in sum() loop - changevar() [ use substvec ] and reorder() [ use variable() for the list of user variables ] have been removed - The quasi-periods e.eta (and elleta(e)) are now twice the old value, so that e.eta = 2 ellzeta(e,e.omega/2) - Change e.omega so that e.omega[1] / e.omega[2] belongs to the Poincare half plane [ used to be the inverse ]. - indexrank, indexsort and indexlexsort now return t_VECSMALLs - besselk no longer admits a flag, the default implementation caters for all cases - removed (obsolete) optional flag in ellap(), Mod() and gcd() - the weird extra argument to listcreate() [ maximal length ] has disappeared. In fact, listcreate() is now obsolete: juste use List() to create an empty list. It will grow as needed. - listkill() is also obsolete: no need for a specific function to kill old lists floating around. L = List() reclaims memory just as efficiently as listkill(L) would. In most cases, you won't even need that, e.g. local variables are automatically cleared when a user function returns; no need to kill the ones which are lists specifically. - local variables declared implicitly (user function parameters, loop indices) are now lexically-scoped. The keyword 'my' allows to declare lexically-scoped variables explicitly. - global(), being awkward to implement in the new parser model and essentially useless is now a no-op, scheduled for removal. - PariEmacs is now distributed as a separate package, and is no longer included in the PARI distribution - distinction between user functions and user variables has been removed. As a consequence, calling a user function without parentheses no more evaluate it. - syntax errors are no longer trap-ped, only runtime errors are. First, error trapping and compile-time errors are best left unrelated. Second, since the code is first byte-compiled, then evaluated, it made no sense trapping a syntax error that would necessarily occur in the first milliseconds after inputing the command to the interpreter. (Not so in the old evaluator which could notice syntax errors very late, and one was happy to be able to still salvage something when it bombed.) - quadray no longer allows an (optional) 3rd argument: was not properly documented, broke the symmetry between real / imaginary case (was ignored if D > 0), complicated the code, and was rather useless in any case. - the "minimum field width" component of the 'format' default is now ignored (was used only for integers in 'prettyprint' output mode and defaulted to 0 [no effect]). Use printf ! - removed the fieldw "minimum field width" field from the undocumented pariout_t struct - remove obsolete "prettyprint" support: printp / printp1 now act as print/print1 - the conversion style 'g' of the 'format' default now printfs in style 'f' if the decimal exponent is < -4 ( was: if the binary exponent is < -32 ), in order to conform to standard printf specifications. - all LLL variants now use an implementation of NGuyen & Stehle's algorithm The LLL-reduced bases will be different from previous versions. - plotinit: change the way default arguments are evaluated (omit dimension, instead of interpreting 0 in a special way) - nfbasistoalg / nfalgtobasis no longer accept t_VEC/t_COL/t_MAT (not being able to apply nfbasistoalg to nfalgtobasis(nf,x) was awkward and inconsistent; the doc stated that those were inverse functions, but they were not). Use matbasistoalg / matalgtobasis, which now also accept t_VEC/t_COL. - removed obsolete optional argument to quadhilbert(D < 0) - removed obsolete GP functions printp, printp1. Use print. - bittest(x, n) no longer accepts t_VEC arguments n - remove obsolete GP functions bnfclassunit, bnfreg, bnfclgp, bnfunit. Use bnfinit. - remove obsolete GP functions bnrclass. Use bnrinit or bnrclassno. - remove awkward flag '3' for bnfinit. Use bnfcompress(). - remove badly named bnfmake. Use bnfinit(sbnf). - idealmin now returns a number field element, instead of the associated "principal idele" - removed obsolete GP functions idealprincipal. Use number field elements "as is". - Functions quadunit(), quadregulator(), and factor() no longer apply componentwise to vector / matrix arguments. Use apply() - factorback() no longer accepts an optional 3rd argument (nf). Use idealfactorback(). See also nffactorback(). - no longer export private library function incgam2. Remove it also under GP when compatible = 3. Situation is the same as incgam1 (removed long ago), 1.39.15 doc stated both were provided "for debugging only". - Change of behaviour for Set(t_STR): Set("1") used to return ["1"], now it returns ["\"1\""], i.e returns the set whose element evaluates to the character string "1". - Flags 4, 5, 6 (useless) have disappeared in nfinit() - norml2(t_POL) now returns the expected (square of) the polynomial L^2 norm. Use x * conj(x) to get back the old behaviour. norml2 now raises an error on t_POLMOD and t_FFELT components; used to add relative norms as in ? norml2([Mod(Mod(1,3)*x,x^2-2), 2]) %1 = Mod(2, 3) - kill(z) has essentially the same effect as z = 'z [ it also kills addhelp messages attached to z, and works for aliases and installed functions too ] - removed optional flag to rnfconductor, use rnfisabelian. - changed the "zetakinit" format: bnf no longer included - factor(t_INT/t_FRAC, lim) used to trial divide by primes up to min(lim, primelimit). Now we trial divide up to lim and raise an error if lim > primelimit. [ Having the routine return an obviously "wrong" result depending on an invisible parameter was not a good idea. ] - factor(t_INT/t_FRAC, 1) was the same as factor(t_INT/t_FRAC, 0). Now abide by the input value and leave (..., 0) as the single special case (shortcut for "the largest precomputed prime") - listsort(L) no longer returns the list L: it now returns nothing. (No point in sorting in place if we must immediately copy the result.) - ellwp now outputs a number of terms equal to the default seriesprecision, instead of *twice* that number. - inverse trigonometric functions (acos,asin,atan,acosh,asinh,atanh): values on the branch cuts changed to conform to standards, e.g. "implementations shall map a cut so the function is continuous as the cut is approached coming around the finite endpoint of the cut in a counter clockwise direction." (ISO C99) - bnfinit no longer outputs a warning when fundamental units couldn't be computed (annoying and rather useless) [#1166] -[Configure] no longer support a link to an uninstalled readline library in PARI toplevel - thue() no longer outputs a Warning when the result is conditional on the GRH. - addprimes() now includes its argument as-is (used to take gcds, making an insertion linear in the table size instead of O(1); filling an inially empty table was quadratic in the final table size). They must be true primes, otherwise number theoretic routines may return wrong values. [#322] * Specific to the PARI library: =============================== - allocatemoremem() is gone. Use allocatemem(). - rename fprintferr() -> err_printf(). - rename TIMER -> timer_delay, TIMERread -> timer_get, TIMERstart -> timer_start, msgTIMER -> timer_printf - rename gener_Fp -> pgener_Fp, gener_Fl -> pgener_Fp [ contrary to 'gener', these assume that their argument is prime ] - rename Flx_rand -> random_Flx, FpX_rand -> random_FpX - rename cyclo -> polcyclo (GP name), subcyclo -> polsubcyclo (GP name), tchebi -> polchebyshev (GP name), legendre -> pollegendre (GP name) - only scalar types (and vectors/matrices of such) are allowed in gaffect and gaffsg. - pol_x and pol_1 are now functions, not global arrays. Use pol_x(v) instead of pol_x[v]. polvar[] and ordvar[] have disappeared - rename ZY_ZXY_resultant -> ZX_ZXY_resultant, ZY_ZXY_rnfequation -> ZX_ZXY_rnfequation and FpY_FpXY_resultant -> FpX_FpXY_resultant - FpX_ functions no longer accept p==NULL. - Fl_pow renamed to Fl_powu [ exponent may not be negative ] - rename pointch -> ellchangepoint, coordch -> ellchangecurve, ordell -> ellordinate - remove obsolete undocumented functions outerr, outbeauterr, outsor, outtex. Rename voir -> dbgGEN. Functions brute, outbrute, matbrute, outmat, sor, outbeaut are obsoleted and no longer documented. - rename errfile -> pari_errfile, infile -> pari_infile, logfile -> pari_logfile - manage_var obsoleted (kept for backward compatibility, to be removed), use pari_var_init, pari_var_next, pari_var_max_avil, pari_var_create instead. - rename sqred -> qfgaussred, signat -> qfsign - rename gscalmat -> scalarmat, gscalsmat -> scalarmat_s, gscalcol -> scalarcol, gscalcol_i -> scalarcol_shallow - removed obsolete apell2, ellap0. Rename apell -> ellap. - typedef for type col_counter [last argument of unused, undocumented plot_count()] changed (must be malloced since MAX_COLORS is no longer a constant) - rename gissquarerem -> gissquareall, uissquarerem -> uissquareall, Z_issquarerem -> Z_issquareall (analogy with sqrtrem was faulty: we do not store a remainder but the square root) - rename assmat -> matcompanion, polymodrecip -> modreverse - removed obsolete undocumented bruteall() - %Z is no longer a valid conversion specification for PARI formats, since this is now handled as a length modifier. Use %Ps instead. - rename pariprintf -> pari_printf (%Z conversion disappeared, use %Ps) - rename pariputc -> pari_putc, pariputs -> pari_puts, pariflush -> pari_flush - rename gpmalloc -> pari_malloc, gprealloc -> pari_realloc, gpfree -> pari_free - rename derivpol -> RgX_deriv - obsolete library functions roots2 and rootsold are no longer public - rename factorpadic4 -> factorpadic, factorpadic2 now static - the "prec" parameter has disappeared in all floating point LLL various - remove obsolete function factpol() - rename library functions nfhermite -> nfhnf, nfhermitemod -> nfhnfmod, nfsmith -> nfsnf - rename subres -> resultant, subresall -> resultant_all. - remove obsolete discsr. Use RgX_disc (or quad_disc, qfb_disc...) - remove obsolete allbase, base, base2, factoredbase, smallbase, discf2, factoreddiscf, smalldiscf. Use nfbasis0 / nfdisc0 / nfmaxord - rename library functions matrixqz2 -> QM_ImZ_hnf, matrixqz3 -> QM_ImQ_hnf, matrixqz -> QM_minors_coprime - rename library functions hil0->hilbert, hilii->hilbertii - rename library functions srgcd -> RgX_gcd - rename library functions ismonome -> RgX_is_monomial - remove obsolete buchray, buchrayinit, buchrayinitgen: use Buchray. - rename library functions minideal -> idealmin and change prototype - rename library functions element_mulmodpr -> nfmulmodpr, element_powmodpr -> nfpowmodpr, element_val -> nfval, element_add -> nfadd, element_divmodpr -> nfdivmodpr, element_mul -> nfmul, element_pow -> nfpow, element_div -> nfdiv. - remove obsolete library function smallfact; use boundfact or Z_factor_limit - rename mu -> moebius, gmu -> gmoebius, phi -> eulerphi, gphi -> geulerphi, phiu -> eulerphiu, gener -> znprimroot, ggener -> znprimroot0, racine -> sqrtint [ NO COMPATIBILITY #define PROVIDED: too dangerous ] - rename regula -> quadregulator, fundunit -> quadunit - remove obsolete library function gracine - remove obsolete library function ispsp, gispsp. Use ispseudoprime or BPSW_psp. - remove obsolete library function gregula, gfundunit. Use quadregulator and quadunit - removed obsolete 'prec' argument from prototypes of idealmul0, idealmulred, idealpow0, idealpowred, ideallllred, algdep, algdep0, lindep, lindep0 - removed obsolete library functions ideallistunit, ideallistunitgen, ideallistzstar, ideallistzstargen. Use ideallist0. - removed obsolete library function algdep2. Use algdep0 (same arguments). - removed obsolete library function Mod0. Use gmodulo. - factorback() now accepts a single argument. - rename library functions factorback0 -> factorback2, subfields0 -> nfsubfields, ideallllred -> idealred0, zideallog -> ideallog, isunit -> bnfisunit, ideal_two_elt* -> idealtwoelt* - changed prototypes of bnrdisc, bnrconductor, bnrisconductor [ actually renamed bnrdisc0, bnrconductor0, bnrisconductor0 ]. Just use the new prototype, it's more convenient. - removed obsolete library function kerin1. Use kerint or [simpler if LLL reduction of the returned basis is not deisred] ZM_lll(,0.99,LLL_KER) - rename library functions initell -> ellinit, smallinitell -> smallellinit initalg -> nfinit, initalgred -> nfinitred -> initalgred2 -> nfinitred2 primedec -> idealprimedec, powraw -> qfbpowraw, compraw -> qfbcompraw - rename library function u2toi -> uu32toi. - remove obsolete library functions sor, outbrute, outbeaut - basic kernel functions involving a t_INT and a t_REAL now return a t_REAL, e.g. divsr(0, x) or mulir(gen_0,x) return real_0(...) [ used to return gen_0 ] ==> much better control of object types when writing kernel code. Generic functions (gmul, gdiv), as called from gp still return a result as precise as possible given the input: 0 * 1. --> gen_0 - deprecated global constants gi; use mulcxI, gen_I() or mkcomplex(). - deprecated global constants geuler & gpi; use mpeuler() & mppi(). - changed prototype of galoisconj: galoisconj(x) -> galoisconj(x,NULL) - commented out a large section of pariold.h. Define PARI_OLD_NAMES to recover compatibility macros for old friends like 'un' and 'lstoi' - rename greffe -> RgX_to_ser and remove the "use_pari_stack" flag - rename Buchall -> Buchall_param and export a new Buchall with a simplified interface. - rename certifybuchall -> bnfcertify - the bitvec family function was replaced by the new F2v family functions. - prototype change: added a flag to the (mostly useless) function rnfdedekind(), the version with the flag set is more useful. - rename gcmp0 -> gequal0, gcmp1 -> gequal1, gcmp_1 -> gequalm1 - rename ZX_caract -> ZXQ_charpoly and swap arguments. - rename RgXQ_u_pow -> RgXQ_powu - remove function delete_named_var (using kill0 instead). - remove RgM_ishnf (use ZM_ishnf instead). - rename leftright_pow to gen_pow, leftright_pow_u to gen_powu. - remove unused 'prec' argument in rnfinitalg(). Rename rnfinitalg -> rnfinit - remove unused 'prec' argument in bnfisnorm() - add a third precdl argument to gtoser() - the last 2 arguments of ellwp0 (prec and precdl) have been swapped - prototype of "summation" functions (suminf,intnum,prodinf,etc.) now is fun(void *E, GEN call(void*, GEN),...) %%%%%%%%%%%%%%%%%%%%%%%%%%%% VERSION 2.2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * General: [ use GP function names in description ] ========== - Default args for user defined functions now evaluated when function is called (used to be: at definition time) E.g f(x) = local(z = x); z. Before: f(2) -> x Now: f(2) -> 2 - rnfisnorm() input format has changed. Older version was complicated and only worked if rnfequation(bnf, p, 1)[3] == 0 [otherwise, crash]. Use rnfisnorminit() now. - rnfidealreltoabs, rnfidealup: now return a Z-basis as a vector of elements in the relative extension, instead of a meaningless HNF matrix wrt an unknown basis. Was especially dangerous if the extension also existed in nfinit form, since the HNF matrices were _not_ ideals wrt this nf structure. [ also consistent with rnfeltreltoabs ]. Use the following construction instead, referring to an explicit NF structure: \\ return y = rnfidealup(rnf,...) as an ideal in HNF form associated to \\ nf = nfinit(rnf.pol); idealgentoHNF(nf, y) = mathnf( Mat( nfalgtobasis(nf, y) ) ); - the "bit accuracy component" for computations of principal ideal generators (bnfisprincipal), units (bnfunit), and some of the bnf structures has been removed. - the "technical parameter" to bnfinit() has been shortened to 3 components (the others were deprecated / useless): [c, c2, nrpid]. The output format has changed (technical components). - poldegree(0) now returns -VERYBIGINT, not -1. Before using d = poldegree(x), always check for 0 first: either (x == 0) or (d >= 0) as you prefer. Never check for d == -1 or -2^31-1 which is not portable. - ellheight now uses the standard normalization: twice the value it used to return. The values returned by ellbil() and ellheightmatrix are unaffected. In particular, ellheightmatrix() is the polar form of elleight(), and ellbil now satisfies the proper identity B(P, Q) = (h(P+Q)-h(P)-h(Q)) / 2 - ':' no longer allowed as a substitute for ';' if compatible = 0. Use GP2C semantics [ x:int, v:vec ]. For the time being the type information is discarded. - log(x, {flag}): optional flag removed. Decide alone whether to use AGM. - valuation(x, 1) used to return 1, valuation(x, -1) returned 0 if (x >= 0) and 1 otherwise. Not anymore: error message. - bnrdisclist has lost its 4th argument 'flag', and omitting the archimedean component now means that all 2^r1 possible values are substituted (formerly: indicate no ramification at infinity). - 'buffersize' default has disappeared: it is adjusted internally whenever needed. The -b xxx flag to gp is a no-op. - the member function bnr.zkst is deprecated, use bnr.bid.clgp - the member function bnr.futu is deprecated. Please don't use bnr.tufu either. - use \frac instead of \over in TeX output. Define \def\frac#1#2{{#1\over#2}} if you insist on using plain TeX and run into problems. - automatic concatenation for strings: use longest match for expression. print("a"[1]) is not valid since "a" is not a vector print("a", [1]) prints 'a[1]'. - isprime() now guarantees primality, use ispseudoprime() for fast pseudo-primality tests. - default() now always returns the value of the (possibly changed) default. No need for a flag anymore. - semantic of t_SER with inexact coefficients is now the same as for t_POL: the sign is 0 iff all coefficients are zero. Either there are no coefficients, or the leading coefficient is an inexact zero. - No longer assume that part of an object is "permanent" when it is out of the stack (was used by INTMOD/POLMOD/PADIC). Always copy it. As a result, 'gmodulo' and 'forcecopy' become obsolete. Rename gmodulcp -> gmodulo. * Specific to the PARI library: =============================== Incompatible changes: --------------------- - gsize() -> gsizeword() [conflict with gtk] taille2 -> gsizebyte() - hnfhavas removed (didn't work properly, hnflll provides an alternative) - real zeroes are now coded on 2 words. Beware of constructs like t = cgetg(lg(x), t_REAL); gaffect(y, t). If x = 0, so will be t. - polgalois(): old format deprecated. New preferred format for result has 3rd component giving numbering among all transitive subgroups of S_n [ was ad hoc up to 7, as described above for n >= 8 ]. Old format is still the default, but will eventually change. Use default(new_galois_format, 1) or, in library mode, set global variable new_galois_format to 1 to enable the new format. - The nf structure output by nfinit has changed: *) nf.zk is now T2-LLL-reduced, not in HNF wrt the power basis *) the internal components of nf[5] have changed (MC and T2 not needed anymore) - polred & polredabs do not take a 'prec' argument anymore [was unused] - gentimer / genmsgtimer / get_timer have been removed. They are superseded by TIMER and msgTIMER which are fully reentrant and easier to use. - (undocumented) macros buch[gen | genfu | init | iniftu] - rnfisnorm() prototype has changed [ + need to call rnfisnorminit first ] - incgam4 renamed to incgam0, incgam3 renamed to incgamc - prototypes of buchall and smallbuchinit have changed (much simpler) - co8() renamed to quadtoc() - ker_mod_p() renamed to FpM_ker [ and supplemented with many analogous modular routines ] - nfreducemodpr2() removed, use an nfmodpr structure from nfmodprinit() or zkmodprinit() instead - smodsi() removed [ not well defined ]. Use either modsi() or umodui() - Many error codes were removed. It is usually better to use only talker outside libpari. - Macro BITS_IN_RANDOM has been removed. Used to be 32. - mymyrand() has been removed, use pari_rand31() or pari_rand() instead - diviiz(x,y,z), divisz, divsiz and divssz always assign the euclidean quotient [ used to depend on the type of z: if t_REAL computed exact quotient ]. Use rdivii, rdivis, rdivsi, rdivss for analogous functionality (no "z" variant); - mpdivz(x,y,z) assigns the euclidean quotient when x,y are t_INT (used to depend on the type of z) - removed inconsistently named macros mpinv[sir]r [ were "z" functions ] - removed useless routine shifts [ use shifti( stoi() ) ] - library interface of functions intnum, prodeuler, suminf, sumalt, sumalt2, sumpos, sumpos2, prodinf, prodinf1 [ use GEN (*eval)(GEN,void*) everywhere instead of entree * ] - changed the prototype of bnrdisclist0 - removed ideallistarch0, ideallistarchgen, ideallistunitarch, ideallistunitarchgen. Just use ideallistarch. - change the output of ideallist with technical (flag 2,3) [ with units ]: instead of two vectors, output a vector of 2-component vectors. change the input of all list routines (bnrclassnolist, bnrdisclist) accordingly. - rename gtrans_i -> shallowtrans, concatsp -> shallowconcat. - pari_err(warner | warnmem | warnfile | warnprec,) no longer accepted. Use pari_warn. Partially compatible changes: ----------------------------- [ not mandatory for your program to work with 2.3, since compatibility macros support the old names but are likely to become mandatory in 2.4, so we advise you to update soon ] - typecasting macros (e.g. ladd(), lmul() ...) are obsolete and shouldn't be used in new programs. Use accessors gel() and friends. - stack locations used to be of type long or ulong, now they have a dedicated type pari_sp [ pari stack pointer ] - in order to compare variable numbers, use the macro varncmp() instead of < or > operators. - access to the prime numbers table is done via the macros NEXT_PRIME_VIADIFF or NEXT_PRIME_VIADIFF_CHECK. - direct access to the mantissa of t_INT is deprecated. Instead you should use the t_INT API (macros int_MSW, int_LSW, int_precW, int_nextW, int_W). This will ensure your code is compatible with both native and GMP kernels. - the macros lgef / setlgef / evallgef have been removed. t_POLs no longer include an "effective length". One should use lg() for t_POLs as for most other types. Don't use lgef() in new code. lgef() and setlgef() are aliased to lg() and setlg(). They will break on hackish code accessing directly the first component of t_POL objets, e.g x = cgetg(20, t_POL); x[1] = evalsigne(1) | evalvarn(0) | evallgef( 10 ) /* 10, not 20 */ ... setlgef(x, 20); /* now create/use further coefficients */ - types t_FRACN, t_RFRACN and gred() have been removed (complicated, unused, and very inefficient). There are now aliases to t_FRAC, t_RFRAC and gcopy respectively for backward compatibility. - renamed nfdivres -> nfdivrem, poldivres -> poldivrem - renamed permute -> numtoperm, permuteInv -> permtonum - renamed gzero -> gen_0, gun -> gen_1, gdeux -> gen_2, polx -> pol_x, polun -> pol_1 - renamed gegal -> gequal, gegalgs -> gequalgs, gegalsg -> gequalsg, egalii -> equalii - renamed binome -> binomial, chinois -> chinese - renamed apprgen9, apprgen -> padicappr, factmod9 -> factorff - rename resss -> remss, ressi -> remsi, resis -> remis, resii -> remii, gres -> grem - rename divise -> dvdii, gdivise -> gdvd, mpdivis -> dvdiiz, mpdivisis -> dvdisz - rename mpent -> mpfloor - rename isprincipalrayall -> bnrisprincipal, rayclassno -> bnrclassno rayclassnolist -> bnrclassnolist - rename globalreduction -> ellglobalred, localreduction -> elllocalred - taniyama(e) is deprecated. Use elltaniyama(e, prec) instead of old = precdl; precdl = prec; x = taniyama(e); precdl = old; - rename lisexpr -> readexp, lisseq -> readseq - rename flisexpr, flisseq -> gp_read_str - rename lisGEN -> gp_read_stream - rename idmat -> matid - rename coefs_to_col -> mkcoln, coefs_to_int -> mkintn coefs_to_pol -> mkpoln, coefs_to_vec -> mkvecn - rename wf -> weberf, wf1 -> weberf1, wf2 -> weberf2 - rename err -> pari_err, pariputsf -> pariprintf - rename rnfhermitebasis -> rnfhnfbasis - rename gcarreparfait -> gissquare, gcarrecomplet -> gissquarerem - rename lseriesell -> elllseries - gmodulo and forcecopy are obsolete. Use gmodulcp and gcopy. %%%%%%%%%%%%%%%%%%%%%%%%%%%% VERSION 2.1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * The calculator GP: ==================== - most function names have changed (see misc/new.dic or use whatnow under GP) - lowercase / uppercase letters distinguished. - the syntax \var = value is not recognized anymore. Use standard metacommands instead. (setting the compatibility level "compatible" to 3, with "default" will give you those three back). - strict parenthesis matching before executing the command (set strictmatch to 0 to get old behaviour) - functions label / goto have been removed (use break/next/return instead). - conjugation x_ has been removed. '_' can be freely used in identifiers. - \k metacommand removed - result history is now cyclic (older results are erased when the maximal size "histsize" is reached). - the Set() function turns objects into strings (so that set functions are able to treat arbitrary objects). Use eval to turn them back to GENs. - the type() function returns a string and not a number. - sum(X=a,b,...,x) yields x if b 0. * T is a twisting parameter, which satisfies (T|p) == -1. */ typedef struct { GEN faw; /* factor(u*v) */ long D, t, u, v; ulong p, pi, s2, T; } norm_eqn_struct; typedef norm_eqn_struct norm_eqn_t[1]; void norm_eqn_set(norm_eqn_t ne, long D,long t,long u,long v,GEN faw,ulong p); #define zv_to_longptr(v) (&((v)[1])) #define zv_to_ulongptr(v) ((ulong *)&((v)[1])) /* Modular invariants */ #define INV_J 0 #define INV_F 1 #define INV_F2 2 #define INV_F3 3 #define INV_F4 4 #define INV_G2 5 #define INV_W2W3 6 #define INV_F8 8 #define INV_W3W3 9 #define INV_W2W5 10 #define INV_W2W7 14 #define INV_W3W5 15 #define INV_W3W7 21 #define INV_W2W3E2 23 #define INV_W2W5E2 24 #define INV_W2W13 26 #define INV_W2W7E2 27 #define INV_W3W3E2 28 #define INV_W5W7 35 #define INV_W3W13 39 /* Get coefficient of x^d in f, assuming f is nonzero. */ INLINE ulong Flx_coeff(GEN f, long d) { return f[d + 2]; } /* Return the root of f, assuming deg(f) = 1. */ INLINE ulong Flx_deg1_root(GEN f, ulong p) { if (degpol(f) != 1) pari_err_BUG("Flx_deg1_root"); return Fl_div(Fl_neg(Flx_coeff(f, 0), p), Flx_coeff(f, 1), p); } /* Allocation / gerepile */ long getdebugvar(void); void setdebugvar(long n); void debug_stack(void); 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((unsigned char)c) || c=='_'); } /* Interfaces (GP, etc.) */ hashtable *hash_from_link(GEN e, GEN names, int use_stack); void gen_relink(GEN x, hashtable *table); entree* do_alias(entree *ep); char* get_sep(const char *t); long get_int(const char *s, long dflt); void gp_initrc(pari_stack *p_A); void pari_sigint(const char *s); void* get_stack(double fraction, long min); void free_graph(void); void initout(int initerr); void resetout(int initerr); void init_linewrap(long w); void print_functions_hash(const char *s); GEN readbin(const char *name, FILE *f, int *vector); int term_height(void); int term_width(void); /* gp_colors */ void decode_color(long n, long *c); /* defaults */ extern long precreal; void gen_output(GEN x); void fputGEN_pariout(GEN x, pariout_t *T, FILE *out); void parsestate_reset(void); void parsestate_save(struct pari_parsestate *state); void parsestate_restore(struct pari_parsestate *state); void compilestate_reset(void); void compilestate_save(struct pari_compilestate *comp); void compilestate_restore(struct pari_compilestate *comp); void filestate_save(struct pari_filestate *file); void filestate_restore(struct pari_filestate *file); void tmp_restore(pariFILE *F); long evalstate_get_trace(void); void evalstate_set_trace(long lvl); void evalstate_clone(void); void evalstate_reset(void); void evalstate_restore(struct pari_evalstate *state); GEN evalstate_restore_err(struct pari_evalstate *state); void evalstate_save(struct pari_evalstate *state); void varstate_save(struct pari_varstate *s); void varstate_restore(struct pari_varstate *s); void mtstate_save(struct pari_mtstate *s); void mtstate_reset(void); void mtstate_restore(struct pari_mtstate *s); void debug_context(void); typedef struct { const char *s; size_t ls; char **dir; } forpath_t; void forpath_init(forpath_t *T, gp_path *path, const char *s); char *forpath_next(forpath_t *T); /* GP output && output format */ extern char *current_logfile; /* colors */ extern long gp_colors[]; extern int disable_color; /* 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 */ /* 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; Buffer *buf; } filtre_t; void init_filtre(filtre_t *F, Buffer *buf); Buffer *filtered_buffer(filtre_t *F); void kill_buffers_upto_including(Buffer *B); void pop_buffer(void); void kill_buffers_upto(Buffer *B); int gp_read_line(filtre_t *F, const char *PROMPT); void parse_key_val(char *src, char **ps, char **pt); extern int (*cb_pari_get_line_interactive)(const char*, const char*, filtre_t *F); extern char *(*cb_pari_fgets_interactive)(char *s, int n, FILE *f); int get_line_from_file(const char *prompt, filtre_t *F, FILE *file); void pari_skip_space(char **s); void pari_skip_alpha(char **s); char *pari_translate_string(const char *src, char *s, char *entry); gp_data *default_gp_data(void); typedef char *(*fgets_t)(char *, int, void*); typedef struct input_method { /* optional */ fgets_t myfgets; /* like libc fgets() but last argument is (void*) */ /* mandatory */ char * (*getline)(char**, int f, struct input_method*, filtre_t *F); int free; /* boolean: must we free the output of getline() ? */ /* optional */ const char *prompt, *prompt_cont; void *file; /* can be used as last argument for fgets() */ } 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); /* readline */ typedef struct { /* pointers to readline variables/functions */ char **line_buffer; int *point; int *end; char **(*completion_matches)(const char *, char *(*)(const char*, int)); char *(*filename_completion_function)(const char *, int); char *(*username_completion_function)(const char *, int); int (*insert)(int, int); int *completion_append_character; /* PARI-specific */ int back; /* rewind the cursor by this number of chars */ } pari_rl_interface; /* Code which wants to use readline needs to do the following: #include #include pari_rl_interface pari_rl; pari_use_readline(pari_rl); This will initialize the pari_rl structure. A pointer to this structure must be given as first argument to all PARI readline functions. */ /* IMPLEMENTATION NOTE: this really must be a macro (not a function), * since we refer to readline symbols. */ #define pari_use_readline(pari_rl) do {\ (pari_rl).line_buffer = &rl_line_buffer; \ (pari_rl).point = &rl_point; \ (pari_rl).end = &rl_end; \ (pari_rl).completion_matches = &rl_completion_matches; \ (pari_rl).filename_completion_function = &rl_filename_completion_function; \ (pari_rl).username_completion_function = &rl_username_completion_function; \ (pari_rl).insert = &rl_insert; \ (pari_rl).completion_append_character = &rl_completion_append_character; \ (pari_rl).back = 0; } while(0) /* FIXME: EXPORT AND DOCUMENT THE FOLLOWING */ /* PROBABLY NOT IN THE RIGHT FILE, SORT BY THEME */ /* multiprecision */ 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 muliispec(GEN x, GEN y, long nx, long ny); GEN red_montgomery(GEN T, GEN N, ulong inv); GEN sqrispec(GEN x, long nx); ulong *convi(GEN x, long *l); /* powers */ GEN rpowuu(ulong a, ulong n, long prec); /* floats */ double dabs(double s, double t); double darg(double s, double t); void dcxlog(double s, double t, double *a, double *b); double dnorm(double s, double t); double dbllog2(GEN z); double dbllambertW0(double a); double dbllambertW_1(double 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 ZM_hnfmodall_i(GEN x, GEN dm, long flag); GEN LLL_check_progress(GEN Bnorm, long n0, GEN m, int final, long *ti_LLL); /* integer factorization / discrete log */ ulong is_kth_power(GEN x, ulong p, GEN *pt); GEN mpqs(GEN N); /* Polynomials */ /* a) Arithmetic/conversions */ GEN lift_if_rational(GEN x); GEN monomial(GEN a, long degpol, long v); GEN monomialcopy(GEN a, long degpol, long v); GEN ser2pol_i(GEN x, long lx); GEN ser2pol_i_normalize(GEN x, long l, long *v); GEN ser2rfrac_i(GEN x); 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 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 FlxqM_mul_Kronecker(GEN A, GEN B, GEN T, ulong p); GEN FqM_mul_Kronecker(GEN x, GEN y, GEN T, GEN p); /* c) factorization */ 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 ZX_DDF_max(GEN x, long dmax); GEN initgaloisborne(GEN T, GEN dn, long prec, GEN *pL, GEN *pprep, GEN *pdis); /* number fields */ GEN nflist_C3_worker(GEN gv, GEN T); GEN nflist_C4vec_worker(GEN gm, GEN X, GEN Xinf, GEN gs); GEN nflist_V4_worker(GEN D1, GEN X, GEN Xinf, GEN gs); GEN nflist_D4_worker(GEN D, GEN X, GEN Xinf, GEN listarch); GEN nflist_A4S4_worker(GEN P3, GEN X, GEN Xinf, GEN cards); GEN nflist_C5_worker(GEN N, GEN bnfC5); GEN nflist_CL_worker(GEN Fcond, GEN bnf, GEN ellprec); GEN nflist_DL_worker(GEN P2, GEN X1pow, GEN X0pow, GEN X, GEN Xinf, GEN ells); GEN nflist_Mgen_worker(GEN field, GEN X, GEN Xinf, GEN ella); GEN nflist_C6_worker(GEN P3, GEN X, GEN Xinf, GEN M, GEN T); GEN nflist_D612_worker(GEN P3, GEN X, GEN Xinf, GEN limd2s2); GEN nflist_A46S46P_worker(GEN P3, GEN Xinf, GEN sqX, GEN cards); GEN nflist_S46M_worker(GEN P3, GEN X, GEN Xinf, GEN gs); GEN nflist_A462_worker(GEN P3, GEN X, GEN Xinf, GEN listarch, GEN GAL); GEN nflist_S3C3_worker(GEN D2, GEN X, GEN Xinf); GEN nflist_S462_worker(GEN P3, GEN X, GEN Xinf, GEN listarch13, GEN GAL); GEN nflist_S36_worker(GEN pol, GEN X, GEN Xinf); GEN nflist_C32C4_worker(GEN P4, GEN X, GEN Xinf, GEN GAL); GEN nflist_C32D4_worker(GEN P, GEN X, GEN Xinf, GEN gs); GEN nflist_C9_worker(GEN P, GEN X, GEN Xinf); GEN nflist_C3C3_worker(GEN gi, GEN V3, GEN V3D, GEN X); GEN nflist_S3R_worker(GEN ga, GEN ALLCTS); GEN nflist_S3I_worker(GEN ga, GEN ALLCTS); GEN nflist_D9_worker(GEN P2, GEN X, GEN Xinf); GEN nflist_S32_worker(GEN all1, GEN X, GEN Xinf, GEN V3, GEN gs); /* pari_init / pari_close */ void pari_close_compiler(void); void pari_close_evaluator(void); void pari_close_files(void); void pari_close_floats(void); void pari_close_homedir(void); void pari_close_parser(void); void pari_close_paths(void); void pari_close_primes(void); void pari_init_buffers(void); void pari_init_compiler(void); void pari_init_defaults(void); void pari_init_ellcondfile(void); void pari_init_evaluator(void); void pari_init_files(void); void pari_init_floats(void); void pari_close_hgm(void); void pari_init_hgm(void); void pari_init_homedir(void); void pari_init_graphics(void); void pari_init_parser(void); void pari_init_rand(void); void pari_init_paths(void); void pari_init_primetab(void); void pari_init_seadata(void); GEN pari_get_seadata(void); void pari_set_primetab(GEN global_primetab); void pari_set_seadata(GEN seadata); void pari_set_varstate(long *vp, struct pari_varstate *vs); void pari_thread_close_files(void); void export_add(const char *str, GEN val); void export_del(const char *str); GEN export_get(const char *str); void exportall(void); void unexportall(void); /* BY FILES */ /* parinf.h */ GEN coltoalg(GEN nf,GEN x); GEN fincke_pohst(GEN a,GEN BOUND,long stockmax,long PREC, FP_chk_fun *CHECK); void init_zlog(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 make_integral(GEN nf, GEN L0, GEN f, GEN listpr); GEN poltobasis(GEN nf,GEN x); GEN rnfdisc_get_T(GEN nf, GEN P, GEN *lim); GEN rnfallbase(GEN nf, GEN pol, GEN lim, GEN eq, GEN *pD, GEN *pfi, GEN *pdKP); GEN sprk_log_gen_pr(GEN nf, GEN sprk, long e); GEN sprk_log_gen_pr2(GEN nf, GEN sprk, long e); GEN sprk_log_prk1(GEN nf, GEN a, GEN sprk); GEN sprk_to_bid(GEN nf, GEN L, long flag); GEN subgroupcondlist(GEN cyc, GEN bound, GEN listKer); /* Qfb.c */ GEN redimagsl2(GEN q, GEN *U); /* alglin1.c */ typedef long (*pivot_fun)(GEN,GEN,long,GEN); GEN ZM_pivots(GEN x0, long *rr); GEN RgM_pivots(GEN x0, GEN data, long *rr, pivot_fun pivot); void RgMs_structelim_col(GEN M, long nbcol, long nbrow, GEN A, GEN *p_col, GEN *p_lin); /* arith1.c */ int is_gener_Fp(GEN x, GEN p, GEN p_1, GEN L); int is_gener_Fl(ulong x, ulong p, ulong p_1, GEN L); /* arith2.c */ int divisors_init(GEN n, GEN *pP, GEN *pE); long set_optimize(long what, GEN g); /* base1.c */ GEN zk_galoisapplymod(GEN nf, GEN z, GEN S, GEN p); int ZX_canon_neg(GEN z); /* base2.c */ GEN dim1proj(GEN prh); GEN gen_if_principal(GEN bnf, GEN x); /* base3.c */ void check_nfelt(GEN x, GEN *den); GEN zk_ei_mul(GEN nf, GEN x, long i); GEN log_prk(GEN nf, GEN a, GEN sprk, GEN mod); GEN log_prk_units(GEN nf, GEN D, GEN sprk); GEN log_prk_units_init(GEN bnf); GEN veclog_prk(GEN nf, GEN v, GEN sprk); GEN log_prk_init(GEN nf, GEN pr, long k, GEN mod); GEN check_mod_factored(GEN nf, GEN ideal, GEN *fa, GEN *fa2, GEN *archp, GEN MOD); GEN sprk_get_cyc(GEN s); GEN sprk_get_expo(GEN s); GEN sprk_get_gen(GEN s); GEN sprk_get_prk(GEN s); GEN sprk_get_ff(GEN s); GEN sprk_get_pr(GEN s); void sprk_get_AgL2(GEN s, GEN *A, GEN *g, GEN *L2); void sprk_get_U2(GEN s, GEN *U1, GEN *U2); GEN famat_zlog_pr(GEN nf, GEN g, GEN e, GEN sprk, GEN mod); /* base4.c */ GEN factorbackprime(GEN nf, GEN L, GEN e); /* base5.c */ GEN condliftA4(GEN nf); GEN condliftA5(GEN nf); GEN condliftS4(GEN nf); /* bb_group.c */ GEN producttree_scheme(long n); /* bern.c */ long bernbitprec(long N); /* bibli2.c */ GEN sort_factor_pol(GEN y, int (*cmp)(GEN,GEN)); /* buch1.c */ ulong bnf_increase_LIMC(ulong LIMC, ulong LIMCMAX); /* buch2.c */ typedef struct GRHprime_t { ulong p; double logp; GEN dec; } GRHprime_t; typedef struct GRHcheck_t { double cD, cN; GRHprime_t *primes; long clone, nprimes, maxprimes; ulong limp; forprime_t P; } GRHcheck_t; void free_GRHcheck(GRHcheck_t *S); void init_GRHcheck(GRHcheck_t *S, long N, long R1, double LOGD); void GRH_ensure(GRHcheck_t *S, long nb); ulong GRH_last_prime(GRHcheck_t *S); int GRHok(GRHcheck_t *S, double L, double SA, double SB); GEN 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); /* crvwtors.c */ void random_curves_with_m_torsion(ulong *a4, ulong *a6, ulong *tx, ulong *ty, long ncurves, long m, ulong p, ulong pi); /* dirichlet.c */ GEN direuler_factor(GEN s, long n); GEN parsqf_worker(GEN gk, GEN vR, GEN data); GEN parsumprimefun_worker(GEN gk, GEN s, GEN zerf, GEN data, GEN vW, GEN f); /* ellanal.c */ GEN hnaive_max(GEN ell, GEN ht); /* elliptic.c */ GEN ellQ_genreduce(GEN E, GEN G, GEN M, long prec); GEN ellQ_isdivisible(GEN E, GEN P, ulong l); GEN ellminimalbmodel(GEN E, GEN *ptv); GEN ellintegralbmodel(GEN e, GEN *pv); void ellprint(GEN e); /* ellrank.c */ GEN ell2selmer_basis(GEN ell, GEN *cb, long prec); /* es.c */ void killallfiles(void); pariFILE* newfile(FILE *f, const char *name, int type); int popinfile(void); pariFILE* try_pipe(const char *cmd, int flag); /* F2m.c */ GEN F2m_gauss_pivot(GEN x, long *rr); GEN F2m_gauss_sp(GEN a, GEN b); GEN F2m_invimage_i(GEN A, GEN B); /* Fle.c */ void FleV_add_pre_inplace(GEN P, GEN Q, GEN a4, ulong p, ulong pi); void FleV_dbl_pre_inplace(GEN P, GEN a4, ulong p, ulong pi); void FleV_mulu_pre_inplace(GEN P, ulong n, GEN a4, ulong p, ulong pi); void FleV_sub_pre_inplace(GEN P, GEN Q, GEN a4, ulong p, ulong pi); /* Flv.c */ GEN Flm_gauss_sp(GEN a, GEN b, ulong *detp, ulong p); GEN Flm_invimage_i(GEN A, GEN B, ulong p); GEN Flm_inv_sp(GEN a, ulong *detp, ulong p); GEN Flm_pivots(GEN x, ulong p, long *rr, long inplace); /* Flxq_log.c */ GEN Flxq_log_index(GEN a0, GEN b0, GEN m, GEN T0, ulong p); int Flxq_log_use_index(GEN m, GEN T0, ulong p); /* FlxqE.c */ GEN ZpXQ_norm_pcyc(GEN x, GEN T, GEN q, GEN p); long zx_is_pcyc(GEN T); /* FpV.c */ GEN FpMs_leftkernel_elt_col(GEN M, long nbcol, long nbrow, GEN p); GEN FpX_to_mod_raw(GEN z, GEN p); /* FpX.c */ GEN ZlXQXn_expint(GEN h, long e, GEN T, GEN p, ulong pp); /* FpX_factor.c */ GEN ddf_to_ddf2(GEN V); long ddf_to_nbfact(GEN D); GEN vddf_to_simplefact(GEN V, long d); /* FpXQX_factor.c */ GEN FpXQX_factor_Berlekamp(GEN x, GEN T, GEN p); /* forprime.c*/ void init_modular_big(forprime_t *S); void init_modular_small(forprime_t *S); /* galconj.c */ GEN galoiscosets(GEN O, GEN perm); GEN galoisinitfromaut(GEN T, GEN aut, ulong l); GEN matrixnorm(GEN M, long prec); /* gen1.c */ GEN gred_rfrac_simple(GEN n, GEN d); GEN sqr_ser_part(GEN x, long l1, long l2); /* hash.c */ hashtable *hashstr_import_static(hashentry *e, ulong size); /* hyperell.c */ GEN ZlXQX_hyperellpadicfrobenius(GEN H, GEN T, ulong p, long n); GEN hyperellextremalmodels(GEN F, long g, GEN p); /* intnum.c */ GEN contfraceval_inv(GEN CF, GEN tinv, long nlim); GEN contfracinit_i(GEN M, long n); /* lfunlarge.c */ GEN int_h0_worker(GEN j, GEN sel, GEN s, GEN chi, GEN gprec); /* FIXME: delete */ GEN lerchzetalarge(GEN s, GEN a, GEN lam, long prec); GEN lfunloglambdalarge(GEN CHI, GEN s, long bitprec); GEN lfunlambdalarge(GEN CHI, GEN s, long bitprec); GEN lfunlarge(GEN CHI, GEN s, long bitprec); GEN zetahurwitzlarge(GEN s, GEN a, long prec); GEN serh_worker(GEN gk, GEN V, GEN a, GEN ns, GEN gprec); /* mftrace.c */ void pari_close_mf(void); long polishomogeneous(GEN P); GEN sertocol(GEN S); GEN mfrhopol(long n); GEN mfrhopol_u_eval(GEN Q, ulong t2); GEN mfrhopol_eval(GEN Q, GEN t2); /* prime.c */ long BPSW_psp_nosmalldiv(GEN N); int MR_Jaeschke(GEN n); long Z_isanypower_nosmalldiv(GEN N, ulong cutoff, GEN *px); /* perm.c */ long cosets_perm_search(GEN C, GEN p); GEN perm_generate(GEN S, GEN H, long o); long perm_relorder(GEN p, GEN S); GEN vecperm_extendschreier(GEN C, GEN v, long n); /* polclass.c */ GEN polclass0(long D, long inv, long vx, GEN *db); /* polmodular.c */ GEN polmodular0_ZM(long L, long inv, GEN J, GEN Q, int compute_derivs, GEN *db); GEN Flm_Fl_polmodular_evalx(GEN phi, long L, ulong j, ulong p, ulong pi); GEN polmodular_db_init(long inv); void polmodular_db_clear(GEN db); void polmodular_db_add_level(GEN *db, long L, long inv); void polmodular_db_add_levels(GEN *db, long *levels, long k, long inv); GEN polmodular_db_for_inv(GEN db, long inv); GEN polmodular_db_getp(GEN fdb, long L, ulong p); long modinv_level(long inv); long modinv_degree(long *p1, long *p2, long inv); long modinv_ramified(long D, long inv, long *pN); long modinv_j_from_2double_eta(GEN F, long inv, ulong x0, ulong x1, ulong p, ulong pi); GEN double_eta_raw(long inv); ulong modfn_root(ulong j, norm_eqn_t ne, long inv); long modfn_unambiguous_root(ulong *r, long inv, ulong j0, norm_eqn_t ne, GEN jdb); GEN qfb_nform(long D, long n); /* Fle.c */ ulong Flj_order_ufact(GEN P, ulong n, GEN F, ulong a4, ulong p, ulong pi); /* 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 RgXQ_charpoly_i(GEN x, GEN T, long v); ulong ZX_ZXY_ResBound(GEN A, GEN B, GEN dB); GEN ffinit_Artin_Schreier(ulong p, long l); GEN ffinit_rand(GEN p, long n); GEN nf_direct_compositum(GEN nf, GEN A, GEN B); /* nflist.c */ GEN veccond_to_A5(GEN L, long s); long ceilsqrtdiv(GEN x, GEN y); /* nflistQT.c */ GEN nflistQT(long n, long k, long v); /* ramanujantau.c */ GEN ramanujantau_worker(GEN gt, GEN p2_7, GEN p_9, GEN p); GEN taugen_n_worker(GEN t, GEN pol, GEN p4); /* readline.c */ char** pari_completion(pari_rl_interface *pari_rl, char *text, int START, int END); char** pari_completion_matches(pari_rl_interface *pari_rl, const char *s, long pos, long *wordpos); /* subcyclo.c */ GEN galoiscyclo(long n, long v); long subcyclo_nH(const char *fun, GEN N, GEN *psg); GEN znstar_bits(long n, GEN H); long znstar_conductor(GEN H); long znstar_conductor_bits(GEN bits); 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 */ struct abpq { GEN *a, *b, *p, *q; }; struct abpq_res { GEN P, Q, B, T; }; void abpq_init(struct abpq *A, long n); void abpq_sum(struct abpq_res *r, long n1, long n2, struct abpq *A); GEN logagmcx(GEN q, long prec); GEN zellagmcx(GEN a0, GEN b0, GEN r, GEN t, long prec); /* trans2.c */ GEN trans_fix_arg(long *prec, GEN *s0, GEN *sig, GEN *tau, pari_sp *av, GEN *res); /* trans3.c */ GEN double_eta_quotient(GEN a, GEN w, GEN D, long p, long q, GEN pq, GEN sqrtD); GEN inv_szeta_euler(long n, long prec); GEN lerch_worker(GEN t, GEN E); /* volcano.c */ long j_level_in_volcano(GEN phi, ulong j, ulong p, ulong pi, long L, long depth); ulong ascend_volcano(GEN phi, ulong j, ulong p, ulong pi, long level, long L, long depth, long steps); ulong descend_volcano(GEN phi, ulong j, ulong p, ulong pi, long level, long L, long depth, long steps); long next_surface_nbr(ulong *nJ, GEN phi, long L, long h, ulong J, const ulong *pJ, ulong p, ulong pi); GEN enum_roots(ulong j, norm_eqn_t ne, GEN fdb, GEN G, GEN vshape); ENDEXTERN pari-2.17.2/src/headers/paridecl.h0000644000175000017500000077521014760123736015347 0ustar billbill/* Copyright (C) 1999-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; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*******************************************************************/ /* */ /* DECLARATIONS of PUBLIC FUNCTIONS */ /* */ /*******************************************************************/ #include "parinf.h" /* black box groups */ struct bb_group { GEN (*mul)(void *E, GEN, GEN); GEN (*pow)(void *E, GEN, GEN); GEN (*rand)(void *E); ulong (*hash)(GEN); int (*equal)(GEN,GEN); int (*equal1)(GEN); GEN (*easylog)(void *E, GEN, GEN, GEN); }; /* black box fields */ struct bb_field { GEN (*red)(void *E ,GEN); GEN (*add)(void *E ,GEN, GEN); GEN (*mul)(void *E ,GEN, GEN); GEN (*neg)(void *E ,GEN); GEN (*inv)(void *E ,GEN); int (*equal0)(GEN); GEN (*s)(void *E, long); }; /* black box algebra */ struct bb_algebra { GEN (*red)(void *E, GEN x); GEN (*add)(void *E, GEN x, GEN y); GEN (*sub)(void *E, GEN x, GEN y); GEN (*mul)(void *E, GEN x, GEN y); GEN (*sqr)(void *E, GEN x); GEN (*one)(void *E); GEN (*zero)(void *E); }; /* black box ring */ struct bb_ring { GEN (*add)(void *E, GEN x, GEN y); GEN (*mul)(void *E, GEN x, GEN y); GEN (*sqr)(void *E, GEN x); }; /* OBSOLETE */ GEN 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 factmod(GEN f, GEN p); void mpbern(long n, long prec); GEN simplefactmod(GEN f, GEN p); void listkill(GEN list); GEN isprincipalforce(GEN bnf,GEN x); GEN isprincipalgen(GEN bnf, GEN x); GEN isprincipalgenforce(GEN bnf,GEN x); /* F2v.c */ GEN F2Ms_ker(GEN M, long nrows); GEN F2Ms_to_F2m(GEN M, long nrows); GEN F2c_to_ZC(GEN x); GEN F2c_to_mod(GEN x); GEN F2m_F2c_gauss(GEN a, GEN b); GEN F2m_F2c_invimage(GEN A, GEN y); GEN F2m_F2c_mul(GEN x, GEN y); GEN F2m_deplin(GEN x); ulong F2m_det(GEN x); ulong F2m_det_sp(GEN x); GEN F2m_gauss(GEN a, GEN b); GEN F2m_inv(GEN x); GEN F2m_invimage(GEN A, GEN B); GEN F2m_ker(GEN x); GEN F2m_ker_sp(GEN x, long deplin); GEN F2m_mul(GEN x, GEN y); GEN F2m_powu(GEN x, ulong n); long F2m_rank(GEN x); GEN F2m_row(GEN x, long j); GEN F2m_rowslice(GEN x, long a, long b); GEN F2m_to_F2Ms(GEN M); GEN F2m_to_Flm(GEN z); GEN F2m_to_ZM(GEN z); GEN F2m_to_mod(GEN z); GEN F2m_transpose(GEN x); void F2v_add_inplace(GEN x, GEN y); void F2v_and_inplace(GEN x, GEN y); ulong F2v_dotproduct(GEN x, GEN y); int F2v_equal0(GEN a); ulong F2v_hamming(GEN H); void F2v_negimply_inplace(GEN x, GEN y); void F2v_or_inplace(GEN x, GEN y); GEN F2v_slice(GEN x, long a, long b); int F2v_subset(GEN x, GEN y); GEN F2v_to_Flv(GEN x); GEN RgV_F2v_extract_shallow(GEN V, GEN x); GEN matid_F2m(long n); /* F2x.c */ GEN F2x_F2xq_eval(GEN Q, GEN x, GEN T); GEN F2x_F2xqV_eval(GEN P, GEN V, GEN T); GEN F2x_Frobenius(GEN T); GEN F2x_1_add(GEN y); GEN F2x_add(GEN x, GEN y); GEN F2x_deflate(GEN x0, long d); GEN F2x_degfact(GEN f); long F2x_degree(GEN x); GEN F2x_deriv(GEN x); GEN F2x_divrem(GEN x, GEN y, GEN *pr); ulong F2x_eval(GEN P, ulong x); void F2x_even_odd(GEN p, GEN *pe, GEN *po); GEN F2x_extgcd(GEN a, GEN b, GEN *ptu, GEN *ptv); GEN F2x_gcd(GEN a, GEN b); GEN F2x_get_red(GEN T); GEN F2x_halfgcd(GEN a, GEN b); int F2x_issquare(GEN a); GEN F2x_matFrobenius(GEN T); GEN F2x_mul(GEN x, GEN y); GEN F2x_recip(GEN T); GEN F2x_rem(GEN x, GEN y); GEN F2x_shift(GEN y, long d); GEN F2x_sqr(GEN x); GEN F2x_sqrt(GEN x); GEN F2x_to_F2v(GEN x, long n); GEN F2x_to_F2xX(GEN z, long sv); GEN F2x_to_Flx(GEN x); GEN F2x_to_ZX(GEN x); long F2x_valrem(GEN x, GEN *Z); GEN F2xC_to_FlxC(GEN v); GEN F2xC_to_ZXC(GEN x); GEN F2xV_to_F2m(GEN v, long n); void F2xV_to_FlxV_inplace(GEN v); void F2xV_to_ZXV_inplace(GEN v); GEN F2xX_F2x_add(GEN x, GEN y); GEN F2xX_F2x_mul(GEN P, GEN U); GEN F2xX_add(GEN x, GEN y); GEN F2xX_deriv(GEN z); GEN F2xX_renormalize(GEN /*in place*/ x, long lx); GEN F2xX_to_Kronecker(GEN P, long d); GEN F2xX_to_FlxX(GEN B); GEN F2xX_to_ZXX(GEN B); GEN F2xX_to_F2xC(GEN x, long N, long sv); GEN F2xXV_to_F2xM(GEN v, long n, long sv); GEN F2xXC_to_ZXXC(GEN B); GEN F2xY_F2xq_evalx(GEN P, GEN x, GEN T); GEN F2xY_F2xqV_evalx(GEN P, GEN x, GEN T); long F2xY_degreex(GEN b); GEN F2xn_div(GEN g, GEN f, long e); GEN F2xn_inv(GEN f, long e); GEN F2xn_red(GEN a, long n); GEN F2xq_Artin_Schreier(GEN a, GEN T); GEN F2xq_autpow(GEN x, long n, GEN T); GEN F2xq_conjvec(GEN x, GEN T); GEN F2xq_div(GEN x,GEN y,GEN T); GEN F2xq_inv(GEN x, GEN T); GEN F2xq_invsafe(GEN x, GEN T); GEN F2xq_log(GEN a, GEN g, GEN ord, GEN T); GEN F2xq_matrix_pow(GEN y, long n, long m, GEN P); GEN F2xq_mul(GEN x, GEN y, GEN pol); GEN F2xq_order(GEN a, GEN ord, GEN T); GEN F2xq_pow(GEN x, GEN n, GEN pol); GEN F2xq_pow_init(GEN x, GEN n, long k, GEN T); GEN F2xq_pow_table(GEN R, GEN n, GEN T); GEN F2xq_powu(GEN x, ulong n, GEN pol); GEN F2xq_powers(GEN x, long l, GEN T); GEN F2xq_sqr(GEN x,GEN pol); GEN F2xq_sqrt(GEN a, GEN T); GEN F2xq_sqrt_fast(GEN c, GEN sqx, GEN T); GEN F2xq_sqrtn(GEN a, GEN n, GEN T, GEN *zeta); ulong F2xq_trace(GEN x, GEN T); GEN F2xqV_roots_to_pol(GEN V, GEN T, long v); GEN F2xqX_F2xq_mul(GEN P, GEN U, GEN T); GEN F2xqX_F2xq_mul_to_monic(GEN P, GEN U, GEN T); GEN F2xqX_F2xqXQ_eval(GEN Q, GEN x, GEN S, GEN T); GEN F2xqX_F2xqXQV_eval(GEN P, GEN V, GEN S, GEN T); GEN F2xqX_disc(GEN x, GEN T); GEN F2xqX_divrem(GEN x, GEN y, GEN T, GEN *pr); GEN F2xqX_extgcd(GEN x, GEN y, GEN T, GEN *ptu, GEN *ptv); GEN F2xqX_gcd(GEN a, GEN b, GEN T); GEN F2xqX_get_red(GEN S, GEN T); GEN F2xqX_halfgcd(GEN x, GEN y, GEN T); GEN F2xqX_halfgcd_all(GEN x, GEN y, GEN T, GEN *a, GEN *b); GEN F2xqX_invBarrett(GEN T, GEN Q); long F2xqX_ispower(GEN f, long k, GEN T, GEN *pt_r); GEN F2xqX_mul(GEN x, GEN y, GEN T); GEN F2xqX_normalize(GEN z, GEN T); GEN F2xqX_powu(GEN x, ulong n, GEN T); GEN F2xqX_red(GEN z, GEN T); GEN F2xqX_rem(GEN x, GEN S, GEN T); GEN F2xqX_resultant(GEN x, GEN y, GEN T); GEN F2xqX_sqr(GEN x, GEN T); GEN F2xqXQ_inv(GEN x, GEN S, GEN T); GEN F2xqXQ_invsafe(GEN x, GEN S, GEN T); GEN F2xqXQ_mul(GEN x, GEN y, GEN S, GEN T); GEN F2xqXQ_sqr(GEN x, GEN S, GEN T); GEN F2xqXQ_pow(GEN x, GEN n, GEN S, GEN T); GEN F2xqXQ_powers(GEN x, long l, GEN S, GEN T); GEN F2xqXQ_autpow(GEN aut, long n, GEN S, GEN T); GEN F2xqXQ_auttrace(GEN aut, long n, GEN S, GEN T); GEN F2xqXQV_red(GEN z, GEN S, GEN T); GEN F2xqXV_prod(GEN V, GEN T); GEN Flm_to_F2m(GEN x); GEN Flv_to_F2v(GEN x); GEN Flx_to_F2x(GEN x); GEN FlxC_to_F2xC(GEN x); GEN FlxX_to_F2xX(GEN B); GEN FlxXC_to_F2xXC(GEN B); GEN Kronecker_to_F2xqX(GEN z, GEN T); GEN Rg_to_F2xq(GEN x, GEN T); GEN RgM_to_F2m(GEN x); GEN RgV_to_F2v(GEN x); GEN RgX_to_F2x(GEN x); GEN Z_to_F2x(GEN x, long v); GEN ZM_to_F2m(GEN x); GEN ZV_to_F2v(GEN x); GEN ZX_to_F2x(GEN x); GEN ZXX_to_F2xX(GEN B, long v); GEN const_F2v(long m); GEN gener_F2xq(GEN T, GEN *po); const struct bb_field *get_F2xq_field(void **E, GEN T); GEN monomial_F2x(long d, long vs); GEN pol1_F2xX(long v, long sv); GEN polx_F2xX(long v, long sv); GEN random_F2xqX(long d1, long v, GEN T); /* F2xqE.c */ GEN F2x_Teichmuller(GEN P, long n); GEN F2xq_ellcard(GEN a2, GEN a6, GEN T); GEN F2xq_ellgens(GEN a2, GEN a6, GEN ch, GEN D, GEN m, GEN T); GEN F2xq_ellgroup(GEN a2, GEN a6, GEN N, GEN T, GEN *pt_m); void F2xq_elltwist(GEN a, GEN a6, GEN T, GEN *pt_a, GEN *pt_a6); GEN F2xqE_add(GEN P, GEN Q, GEN a2, GEN T); GEN F2xqE_changepoint(GEN x, GEN ch, GEN T); GEN F2xqE_changepointinv(GEN x, GEN ch, GEN T); GEN F2xqE_dbl(GEN P, GEN a2, GEN T); GEN F2xqE_log(GEN a, GEN b, GEN o, GEN a2, GEN T); GEN F2xqE_mul(GEN P, GEN n, GEN a2, GEN T); GEN F2xqE_neg(GEN P, GEN a2, GEN T); GEN F2xqE_order(GEN z, GEN o, GEN a2, GEN T); GEN F2xqE_sub(GEN P, GEN Q, GEN a2, GEN T); GEN F2xqE_tatepairing(GEN t, GEN s, GEN m, GEN a2, GEN T); GEN F2xqE_weilpairing(GEN t, GEN s, GEN m, GEN a2, GEN T); const struct bb_group * get_F2xqE_group(void **E, GEN a2, GEN a6, GEN T); GEN RgE_to_F2xqE(GEN x, GEN T); GEN random_F2xqE(GEN a2, GEN a6, GEN T); /* F3v.c */ GEN F3c_to_mod(GEN x); GEN F3c_to_ZC(GEN x); GEN F3m_ker(GEN x); GEN F3m_ker_sp(GEN x, long deplin); GEN F3m_mul(GEN x, GEN y); GEN F3m_row(GEN x, long j); GEN F3m_to_Flm(GEN z); GEN F3m_to_ZM(GEN z); GEN F3m_to_mod(GEN x); GEN F3m_transpose(GEN x); GEN F3v_to_Flv(GEN x); ulong F3v_coeff(GEN x,long v); void F3v_clear(GEN x, long v); void F3v_set(GEN x, long v, ulong n); GEN Flm_to_F3m(GEN x); GEN Flv_to_F3v(GEN x); GEN RgM_to_F3m(GEN x); GEN RgV_to_F3v(GEN x); GEN ZM_to_F3m(GEN x); GEN ZV_to_F3v(GEN x); GEN zero_F3m_copy(long m, long n); GEN zero_F3v(long m); /* Fle.c */ ulong Fl_elldisc(ulong a4, ulong a6, ulong p); ulong Fl_elldisc_pre(ulong a4, ulong a6, ulong p, ulong pi); ulong Fl_ellj(ulong a4, ulong a6, ulong p); void Fl_ellj_to_a4a6(ulong j, ulong p, ulong *pt_a4, ulong *pt_a6); GEN Fl_ellptors(ulong l, ulong N, ulong a4, ulong a6, ulong p); void Fl_elltwist(ulong a4, ulong a6, ulong p, ulong *pt_a4, ulong *pt_a6); void Fl_elltwist_disc(ulong a4, ulong a6, ulong D, ulong p, ulong *pt_a4, ulong *pt_a6); GEN Fle_add(GEN P, GEN Q, ulong a4, ulong p); GEN Fle_dbl(GEN P, ulong a4, ulong p); GEN Fle_changepoint(GEN x, GEN ch, ulong p); GEN Fle_changepointinv(GEN x, GEN ch, ulong p); GEN Fle_log(GEN a, GEN b, GEN o, ulong a4, ulong p); GEN Fle_mul(GEN P, GEN n, ulong a4, ulong p); GEN Fle_mulu(GEN P, ulong n, ulong a4, ulong p); GEN Fle_order(GEN z, GEN o, ulong a4, ulong p); GEN Fle_sub(GEN P, GEN Q, ulong a4, ulong p); ulong Fle_tatepairing(GEN P, GEN Q, ulong m, ulong a4, ulong p); GEN Fle_to_Flj(GEN P); ulong Fle_weilpairing(GEN P, GEN Q, ulong m, ulong a4, ulong p); GEN Flj_add_pre(GEN P, GEN Q, ulong a4, ulong p, ulong pi); GEN Flj_changepointinv_pre(GEN P, GEN ch, ulong p, ulong pi); GEN Flj_dbl_pre(GEN P, ulong a4, ulong p, ulong pi); GEN Flj_mulu_pre(GEN P, ulong n, ulong a4, ulong p, ulong pi); GEN Flj_neg(GEN Q, ulong p); GEN Flj_to_Fle(GEN P, ulong p); GEN Flj_to_Fle_pre(GEN P, ulong p, ulong pi); GEN FljV_factorback_pre(GEN P, GEN L, ulong a4, ulong p, ulong pi); GEN random_Fle(ulong a4, ulong a6, ulong p); GEN random_Fle_pre(ulong a4, ulong a6, ulong p, ulong pi); GEN random_Flj_pre(ulong a4, ulong a6, ulong p, ulong pi); /* Flv.c */ GEN Flc_to_ZC(GEN z); GEN Flc_to_ZC_inplace(GEN z); GEN Flm_Flc_gauss(GEN a, GEN b, ulong p); GEN Flm_Flc_invimage(GEN mat, GEN y, ulong p); GEN Flm_adjoint(GEN A, ulong p); GEN Flm_deplin(GEN x, ulong p); ulong Flm_det(GEN x, ulong p); ulong Flm_det_sp(GEN x, ulong p); GEN Flm_gauss(GEN a, GEN b, ulong p); GEN Flm_intersect(GEN x, GEN y, ulong p); GEN Flm_intersect_i(GEN x, GEN y, ulong p); GEN Flm_inv(GEN x, ulong p); GEN Flm_invimage(GEN m, GEN v, ulong p); GEN Flm_ker(GEN x, ulong p); GEN Flm_ker_sp(GEN x, ulong p, long deplin); long Flm_rank(GEN x, ulong p); GEN Flm_to_ZM(GEN z); GEN Flm_to_ZM_inplace(GEN z); GEN Flv_to_ZV(GEN z); /* Flx.c */ GEN Fl_to_Flx(ulong x, long sv); int Fl2_equal1(GEN x); GEN Fl2_inv_pre(GEN x, ulong D, ulong p, ulong pi); GEN Fl2_mul_pre(GEN x, GEN y, ulong D, ulong p, ulong pi); ulong Fl2_norm_pre(GEN x, ulong D, ulong p, ulong pi); GEN Fl2_pow_pre(GEN x, GEN n, ulong D, ulong p, ulong pi); GEN Fl2_sqr_pre(GEN x, ulong D, ulong p, ulong pi); GEN Fl2_sqrt_pre(GEN z, ulong D, ulong p, ulong pi); GEN Fl2_sqrtn_pre(GEN a, GEN n, ulong D, ulong p, ulong pi, GEN *zeta); GEN Flm_to_FlxV(GEN x, long sv); GEN Flm_to_FlxX(GEN x, long v,long w); GEN Flv_Flm_polint(GEN xa, GEN ya, ulong p, long vs); GEN Flv_inv(GEN x, ulong p); void Flv_inv_inplace(GEN x, ulong p); void Flv_inv_pre_inplace(GEN x, ulong p, ulong pi); GEN Flv_inv_pre(GEN x, ulong p, ulong pi); GEN Flv_invVandermonde(GEN L, ulong den, ulong p); GEN Flv_polint(GEN xa, GEN ya, ulong p, long vs); ulong Flv_prod(GEN v, ulong p); ulong Flv_prod_pre(GEN x, ulong p, ulong pi); GEN Flv_roots_to_pol(GEN a, ulong p, long vs); GEN Flv_to_Flx(GEN x, long vs); GEN Flx_Fl_add(GEN y, ulong x, ulong p); GEN Flx_Fl_mul(GEN y, ulong x, ulong p); GEN Flx_Fl_mul_pre(GEN y, ulong x, ulong p, ulong pi); GEN Flx_Fl_mul_to_monic(GEN y, ulong x, ulong p); GEN Flx_Fl_sub(GEN y, ulong x, ulong p); GEN Flx_Fl2_eval_pre(GEN x, GEN y, ulong D, ulong p, ulong pi); GEN Flx_Flv_multieval(GEN P, GEN v, ulong p); GEN Flx_Flxq_eval(GEN f,GEN x,GEN T,ulong p); GEN Flx_Flxq_eval_pre(GEN f,GEN x,GEN T,ulong p,ulong pi); GEN Flx_FlxqV_eval(GEN f,GEN x,GEN T,ulong p); GEN Flx_FlxqV_eval_pre(GEN f,GEN x,GEN T,ulong p,ulong pi); GEN Flx_Frobenius(GEN T, ulong p); GEN Flx_Frobenius_pre(GEN T, ulong p, ulong pi); GEN Flx_Laplace(GEN x, ulong p); GEN Flx_Newton(GEN P, long n, ulong p); GEN Flx_add(GEN x, GEN y, ulong p); GEN Flx_blocks(GEN P, long n, long m); GEN Flx_composedprod(GEN P, GEN Q, ulong p); GEN Flx_composedsum(GEN P, GEN Q, ulong p); GEN Flx_convol(GEN x, GEN y, ulong p); GEN Flx_deflate(GEN x0, long d); GEN Flx_deriv(GEN z, ulong p); GEN Flx_diff1(GEN P, ulong p); GEN Flx_digits(GEN x, GEN T, 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); GEN Flx_divrem_pre(GEN x, GEN T, ulong p, ulong pi, GEN *pr); GEN Flx_double(GEN y, ulong p); int Flx_equal(GEN V, GEN W); ulong Flx_eval(GEN x, ulong y, ulong p); ulong Flx_eval_powers_pre(GEN x, GEN y, ulong p, ulong pi); ulong Flx_eval_pre(GEN x, ulong y, ulong p, ulong pi); GEN Flx_extgcd(GEN a, GEN b, ulong p, GEN *ptu, GEN *ptv); GEN Flx_extgcd_pre(GEN x, GEN y, ulong p, ulong pi, GEN *ptu, GEN *ptv); ulong Flx_extresultant(GEN a, GEN b, ulong p, GEN *ptU, GEN *ptV); ulong Flx_extresultant_pre(GEN a, GEN b, ulong p, ulong pi, GEN *ptU, GEN *ptV); GEN Flx_fromNewton(GEN P, ulong p); GEN Flx_gcd(GEN a, GEN b, ulong p); GEN Flx_gcd_pre(GEN x, GEN y, ulong p, ulong pi); GEN Flx_get_red(GEN T, ulong p); GEN Flx_get_red_pre(GEN T, ulong p, ulong pi); GEN Flx_halfgcd(GEN a, GEN b, ulong p); GEN Flx_halfgcd_all(GEN a, GEN b, ulong p, GEN *pU, GEN *pV); GEN Flx_halfgcd_all_pre(GEN a, GEN b, ulong p, ulong pi, GEN *pU, GEN *pV); GEN Flx_halfgcd_pre(GEN x, GEN y, ulong p, ulong pi); GEN Flx_halve(GEN y, ulong p); GEN Flx_inflate(GEN x0, long d); GEN Flx_integ(GEN z, ulong p); GEN Flx_invBarrett(GEN T, ulong p); GEN Flx_invLaplace(GEN x, ulong p); int Flx_is_squarefree(GEN z, ulong p); int Flx_is_smooth(GEN g, long r, ulong p); int Flx_is_smooth_pre(GEN g, long r, ulong p, ulong pi); GEN Flx_matFrobenius(GEN T, ulong p); GEN Flx_matFrobenius_pre(GEN T, ulong p, ulong pi); GEN Flx_mod_Xn1(GEN T, ulong n, ulong p); GEN Flx_mod_Xnm1(GEN T, ulong n, ulong p); GEN Flx_mul(GEN x, GEN y, ulong p); GEN Flx_mul_pre(GEN x, GEN y, ulong p, ulong pi); GEN Flx_neg(GEN x, ulong p); GEN Flx_neg_inplace(GEN x, ulong p); GEN Flx_normalize(GEN z, ulong p); GEN Flx_powu(GEN x, ulong n, ulong p); GEN Flx_powu_pre(GEN x, ulong n, ulong p, ulong pi); GEN Flx_recip(GEN x); GEN Flx_red(GEN z, ulong p); GEN Flx_rem(GEN x, GEN y, ulong p); GEN Flx_rem_pre(GEN x, GEN T, ulong p, ulong pi); GEN Flx_renormalize(GEN x, long l); GEN Flx_rescale(GEN P, ulong h, ulong p); ulong Flx_resultant(GEN a, GEN b, ulong p); ulong Flx_resultant_pre(GEN a, GEN b, ulong p, ulong pi); GEN Flx_shift(GEN a, long n); GEN Flx_splitting(GEN p, long k); GEN Flx_sqr(GEN x, ulong p); GEN Flx_sqr_pre(GEN x, ulong p, ulong pi); GEN Flx_sub(GEN x, GEN y, ulong p); GEN Flx_translate1(GEN P, ulong p); GEN Flx_translate1_basecase(GEN P, ulong p); GEN Flx_to_Flv(GEN x, long N); GEN Flx_to_FlxX(GEN z, long v); GEN Flx_to_ZX(GEN z); GEN Flx_to_ZX_inplace(GEN z); GEN Flx_triple(GEN y, ulong p); long Flx_val(GEN x); long Flx_valrem(GEN x, GEN *Z); GEN FlxC_FlxqV_eval(GEN x, GEN v, GEN T, ulong p); GEN FlxC_FlxqV_eval_pre(GEN x, GEN v, GEN T, ulong p, ulong pi); GEN FlxC_Flxq_eval(GEN x, GEN F, GEN T, ulong p); GEN FlxC_Flxq_eval_pre(GEN x, GEN F, GEN T, ulong p, ulong pi); GEN FlxC_eval_powers_pre(GEN z, GEN x, ulong p, ulong pi); GEN FlxC_neg(GEN x, ulong p); GEN FlxC_sub(GEN x, GEN y, ulong p); GEN FlxC_to_ZXC(GEN x); GEN FlxM_Flx_add_shallow(GEN x, GEN y, ulong p); GEN FlxM_eval_powers_pre(GEN z, GEN x, ulong p, ulong pi); GEN FlxM_neg(GEN x, ulong p); GEN FlxM_sub(GEN x, GEN y, ulong p); GEN FlxM_to_FlxXV(GEN x, long v); GEN FlxM_to_ZXM(GEN z); GEN FlxT_red(GEN z, ulong p); GEN FlxV_Flc_mul(GEN V, GEN W, ulong p); GEN FlxV_Flv_multieval(GEN P, GEN v, ulong p); GEN FlxV_Flx_fromdigits(GEN x, GEN T, ulong p); GEN FlxV_composedsum(GEN V, ulong p); GEN FlxV_prod(GEN V, ulong p); GEN FlxV_red(GEN z, ulong p); GEN FlxV_to_Flm(GEN v, long n); GEN FlxV_to_FlxX(GEN x, long v); GEN FlxV_to_ZXV(GEN x); void FlxV_to_ZXV_inplace(GEN v); GEN Flxn_div(GEN g, GEN f, long e, ulong p); GEN Flxn_div_pre(GEN g, GEN f, long e, ulong p, ulong pi); GEN Flxn_exp(GEN h, long e, ulong p); GEN Flxn_expint(GEN h, long e, ulong p); GEN Flxn_inv(GEN f, long e, ulong p); GEN Flxn_mul(GEN a, GEN b, long n, ulong p); GEN Flxn_mul_pre(GEN a, GEN b, long n, ulong p, ulong pi); GEN Flxn_sqr(GEN a, long n, ulong p); GEN Flxn_sqr_pre(GEN a, long n, ulong p, ulong pi); GEN Flxn_red(GEN a, long n); GEN Flxq_autpow(GEN x, ulong n, GEN T, ulong p); GEN Flxq_autpow_pre(GEN x, ulong n, GEN T, ulong p, ulong pi); GEN Flxq_autpowers(GEN x, ulong n, GEN T, ulong p); GEN Flxq_autsum(GEN x, ulong n, GEN T, ulong p); GEN Flxq_auttrace(GEN x, ulong n, GEN T, ulong p); GEN Flxq_auttrace_pre(GEN x, ulong n, GEN T, ulong p, ulong pi); 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_div_pre(GEN x, GEN y, GEN T, ulong p, ulong pi); GEN Flxq_inv(GEN x,GEN T,ulong p); GEN Flxq_inv_pre(GEN x, GEN T, ulong p, ulong pi); GEN Flxq_invsafe(GEN x, GEN T, ulong p); GEN Flxq_invsafe_pre(GEN x, GEN T, ulong p, ulong pi); int Flxq_issquare(GEN x, GEN T, ulong p); int Flxq_is2npower(GEN x, long n, GEN T, ulong p); GEN Flxq_log(GEN a, GEN g, GEN ord, GEN T, ulong p); GEN Flxq_lroot(GEN a, GEN T, long p); GEN Flxq_lroot_pre(GEN a, GEN T, long p, ulong pi); GEN Flxq_lroot_fast(GEN a, GEN sqx, GEN T, long p); GEN Flxq_lroot_fast_pre(GEN a, GEN sqx, GEN T, long p, ulong pi); GEN Flxq_matrix_pow(GEN y, long n, long m, GEN P, ulong l); GEN Flxq_matrix_pow_pre(GEN y, long n, long m, GEN P, ulong l, ulong li); GEN Flxq_minpoly(GEN x, GEN T, ulong p); GEN Flxq_minpoly_pre(GEN x, GEN T, ulong p, ulong pi); GEN Flxq_mul(GEN x, GEN y, GEN T, ulong p); GEN Flxq_mul_pre(GEN x, GEN y, GEN T, ulong p, ulong pi); 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_pow_pre(GEN x, GEN n, GEN T, ulong p, ulong pi); GEN Flxq_pow_init(GEN x, GEN n, long k, GEN T, ulong p); GEN Flxq_pow_init_pre(GEN x, GEN n, long k, GEN T, ulong p, ulong pi); GEN Flxq_pow_table_pre(GEN R, GEN n, GEN T, ulong p, ulong pi); GEN Flxq_pow_table(GEN R, GEN n, GEN T, ulong p); GEN Flxq_powu(GEN x, ulong n, GEN T, ulong p); GEN Flxq_powu_pre(GEN x, ulong n, GEN T, ulong p, ulong pi); GEN Flxq_powers(GEN x, long l, GEN T, ulong p); GEN Flxq_powers_pre(GEN x, long l, GEN T, ulong p, ulong pi); GEN Flxq_sqr(GEN y,GEN T,ulong p); GEN Flxq_sqr_pre(GEN y,GEN T,ulong p,ulong pi); GEN Flxq_sqrt(GEN a, GEN T, ulong p); GEN Flxq_sqrt_pre(GEN z, GEN T, ulong p, ulong pi); GEN Flxq_sqrtn(GEN a, GEN n, GEN T, ulong p, GEN *zetan); ulong Flxq_trace(GEN x, GEN T, ulong p); GEN FlxqC_Flxq_mul(GEN x, GEN y, GEN T, ulong p); GEN FlxqM_Flxq_mul(GEN x, GEN y, GEN T, ulong p); GEN FlxqV_dotproduct(GEN x, GEN y, GEN T, ulong p); GEN FlxqV_dotproduct_pre(GEN x, GEN y, GEN T, ulong p, ulong pi); ulong Rg_to_F2(GEN x); ulong Rg_to_Fl(GEN x, ulong p); GEN Rg_to_Flxq(GEN x, GEN T, ulong p); GEN RgX_to_Flx(GEN x, ulong p); GEN RgXV_to_FlxV(GEN x, ulong p); GEN Z_to_Flx(GEN x, ulong p, long sv); GEN ZX_to_Flx(GEN x, ulong p); GEN ZXV_to_FlxV(GEN v, ulong p); GEN ZXT_to_FlxT(GEN z, ulong p); GEN gener_Flxq(GEN T, ulong p, GEN *o); const struct bb_field *get_Flxq_field(void **E, GEN T, ulong p); const struct bb_group *get_Flxq_star(void **E, GEN T, ulong p); GEN monomial_Flx(ulong a, long d, long vs); GEN random_Flx(long d1, long v, ulong p); GEN zero_FlxC(long n, long sv); GEN zero_FlxM(long r, long c, long sv); GEN zlx_translate1(GEN P, ulong p, long e); GEN zx_to_Flx(GEN x, ulong p); /* FlxX.c */ GEN FlxX_Fl_mul(GEN x, ulong y, ulong p); GEN FlxX_Flx_add(GEN y, GEN x, ulong p); GEN FlxX_Flx_mul(GEN x, GEN y, ulong p); GEN FlxX_Flx_sub(GEN y, GEN x, ulong p); GEN FlxX_Laplace(GEN x, ulong p); GEN FlxX_add(GEN P, GEN Q, ulong p); GEN FlxX_blocks(GEN P, long n, long m, long vs); GEN FlxX_deriv(GEN z, ulong p); GEN FlxX_double(GEN x, ulong p); GEN FlxX_invLaplace(GEN x, ulong p); GEN FlxX_neg(GEN x, ulong p); GEN FlxX_renormalize(GEN x, long lx); GEN FlxX_shift(GEN a, long n, long vs); GEN FlxX_sub(GEN P, GEN Q, ulong p); GEN FlxX_swap(GEN x, long n, long ws); GEN FlxX_to_Flm(GEN v, long n); GEN FlxX_to_Flx(GEN f); GEN FlxX_to_FlxC(GEN x, long N, long sv); GEN FlxX_to_ZXX(GEN B); GEN FlxX_translate1(GEN P, long p, long n); GEN FlxX_triple(GEN x, ulong p); GEN FlxXC_sub(GEN x, GEN y, ulong p); GEN FlxXC_to_ZXXC(GEN B); GEN FlxXM_to_ZXXM(GEN B); GEN FlxXV_to_FlxM(GEN v, long n, long sv); GEN FlxXn_red(GEN a, long n); GEN FlxY_Flx_div(GEN x, GEN y, ulong p); GEN FlxY_Flx_translate(GEN P, GEN c, ulong p); GEN FlxY_FlxqV_evalx(GEN P, GEN x, GEN T, ulong p); GEN FlxY_FlxqV_evalx_pre(GEN P, GEN x, GEN T, ulong p, ulong pi); GEN FlxY_Flxq_evalx(GEN P, GEN x, GEN T, ulong p); GEN FlxY_Flxq_evalx_pre(GEN P, GEN x, GEN T, ulong p, ulong pi); GEN FlxY_evalx(GEN Q, ulong x, ulong p); GEN FlxY_evalx_powers_pre(GEN pol, GEN ypowers, ulong p, ulong pi); GEN FlxY_evalx_pre(GEN Q, ulong x, ulong p, ulong pi); GEN FlxYqq_pow(GEN x, GEN n, GEN S, GEN T, ulong p); GEN FlxqV_roots_to_pol(GEN V, GEN T, ulong p, long v); GEN FlxqXC_FlxqXQV_eval(GEN x, GEN v, GEN S, GEN T, ulong p); GEN FlxqXC_FlxqXQV_eval_pre(GEN x, GEN v, GEN S, GEN T, ulong p, ulong pi); GEN FlxqXC_FlxqXQ_eval(GEN x, GEN F, GEN S, GEN T, ulong p); GEN FlxqXQ_autpow(GEN x, long n, GEN S, GEN T, ulong p); GEN FlxqXQ_autpow_pre(GEN aut, long n, GEN S, GEN T, ulong p, ulong pi); GEN FlxqXQ_autsum(GEN aut, long n, GEN S, GEN T, ulong p); GEN FlxqXQ_autsum_pre(GEN aut, long n, GEN S, GEN T, ulong p, ulong pi); GEN FlxqXQ_auttrace(GEN x, ulong n, GEN S, GEN T, ulong p); GEN FlxqXQ_auttrace_pre(GEN x, ulong n, GEN S, GEN T, ulong p, ulong pi); GEN FlxqXQ_div(GEN x, GEN y, GEN S, GEN T, ulong p); GEN FlxqXQ_div_pre(GEN x, GEN y, GEN S, GEN T, ulong p, ulong pi); GEN FlxqXQ_inv(GEN x, GEN S, GEN T, ulong p); GEN FlxqXQ_inv_pre(GEN x, GEN S, GEN T, ulong p, ulong pi); GEN FlxqXQ_invsafe(GEN x, GEN S, GEN T, ulong p); GEN FlxqXQ_invsafe_pre(GEN x, GEN S, GEN T, ulong p, ulong pi); GEN FlxqXQ_matrix_pow(GEN x, long n, long m, GEN S, GEN T, ulong p); GEN FlxqXQ_minpoly(GEN x, GEN S, GEN T, ulong p); GEN FlxqXQ_minpoly_pre(GEN x, GEN S, GEN T, ulong p, ulong pi); GEN FlxqXQ_mul(GEN x, GEN y, GEN S, GEN T, ulong p); GEN FlxqXQ_mul_pre(GEN x, GEN y, GEN S, GEN T, ulong p, ulong pi); GEN FlxqXQ_pow(GEN x, GEN n, GEN S, GEN T, ulong p); GEN FlxqXQ_pow_pre(GEN x, GEN n, GEN S, GEN T, ulong p, ulong pi); GEN FlxqXQ_powers(GEN x, long n, GEN S, GEN T, ulong p); GEN FlxqXQ_powers_pre(GEN x, long l, GEN S, GEN T, ulong p, ulong pi); GEN FlxqXQ_powu(GEN x, ulong n, GEN S, GEN T, ulong p); GEN FlxqXQ_powu_pre(GEN x, ulong n, GEN S, GEN T, ulong p, ulong pi); GEN FlxqXQ_sqr(GEN x, GEN S, GEN T, ulong p); GEN FlxqXQ_sqr_pre(GEN x, GEN S, GEN T, ulong p, ulong pi); GEN FlxqXV_prod(GEN V, GEN T, ulong p); GEN FlxqX_FlxqXQV_eval(GEN P, GEN V, GEN S, GEN T, ulong p); GEN FlxqX_FlxqXQV_eval_pre(GEN Q, GEN x, GEN S, GEN T, ulong p, ulong pi); GEN FlxqX_FlxqXQ_eval(GEN Q, GEN x, GEN S, GEN T, ulong p); GEN FlxqX_FlxqXQ_eval_pre(GEN Q, GEN x, GEN S, GEN T, ulong p, ulong pi); GEN FlxqX_Flxq_mul(GEN P, GEN U, GEN T, ulong p); GEN FlxqX_Flxq_mul_pre(GEN P, GEN U, GEN T, ulong p, ulong pi); GEN FlxqX_Flxq_mul_to_monic(GEN P, GEN U, GEN T, ulong p); GEN FlxqX_Flxq_mul_to_monic_pre(GEN P, GEN U, GEN T, ulong p, ulong pi); GEN FlxqX_Newton(GEN P, long n, GEN T, ulong p); GEN FlxqX_Newton_pre(GEN P, long n, GEN T, ulong p, ulong pi); GEN FlxqX_composedsum(GEN P, GEN Q, GEN T, ulong p); GEN FlxqX_disc(GEN x, GEN T, ulong p); GEN FlxqX_div_by_X_x(GEN a, GEN x, GEN T, ulong p, GEN *r); GEN FlxqX_div_by_X_x_pre(GEN a, GEN x, GEN T, ulong p, ulong pi, GEN *r); GEN FlxqX_divrem(GEN x, GEN y, GEN T, ulong p, GEN *pr); GEN FlxqX_divrem_pre(GEN x, GEN S, GEN T, ulong p, long pi, GEN *pr); GEN FlxqX_dotproduct(GEN x, GEN y, GEN T, ulong p); GEN FlxqX_eval(GEN x, GEN y, GEN T, ulong p); GEN FlxqX_extgcd(GEN a, GEN b, GEN T, ulong p, GEN *ptu, GEN *ptv); GEN FlxqX_extgcd_pre(GEN x, GEN y, GEN T, ulong p, ulong pi, GEN *ptu, GEN *ptv); GEN FlxqX_fromNewton(GEN P, GEN T, ulong p); GEN FlxqX_fromNewton_pre(GEN P, GEN T, ulong p, ulong pi); GEN FlxqX_gcd(GEN P, GEN Q, GEN T, ulong p); GEN FlxqX_gcd_pre(GEN x, GEN y, GEN T, ulong p, ulong pi); GEN FlxqX_get_red(GEN S, GEN T, ulong p); GEN FlxqX_get_red_pre(GEN S, GEN T, ulong p, ulong pi); GEN FlxqX_halfgcd(GEN x, GEN y, GEN T, ulong p); GEN FlxqX_halfgcd_all(GEN x, GEN y, GEN T, ulong p, GEN *a, GEN *b); GEN FlxqX_halfgcd_all_pre(GEN x, GEN y, GEN T, ulong p, ulong pi, GEN *a, GEN *b); GEN FlxqX_halfgcd_pre(GEN x, GEN y, GEN T, ulong p, ulong pi); GEN FlxqX_invBarrett(GEN T, GEN Q, ulong p); GEN FlxqX_invBarrett_pre(GEN T, GEN Q, ulong p, ulong pi); GEN FlxqX_mul(GEN x, GEN y, GEN T, ulong p); GEN FlxqX_mul_pre(GEN x, GEN y, GEN T, ulong p, ulong pi); GEN FlxqX_normalize(GEN z, GEN T, ulong p); GEN FlxqX_normalize_pre(GEN z, GEN T, ulong p, ulong pi); GEN FlxqX_powu(GEN V, ulong n, GEN T, ulong p); GEN FlxqX_powu_pre(GEN V, ulong n, GEN T, ulong p, ulong pi); GEN FlxqX_red(GEN z, GEN T, ulong p); GEN FlxqX_red_pre(GEN z, GEN T, ulong p, ulong pi); GEN FlxqX_rem(GEN x, GEN y, GEN T, ulong p); GEN FlxqX_rem_pre(GEN x, GEN S, GEN T, ulong p, ulong pi); GEN FlxqX_resultant(GEN x, GEN y, GEN T, ulong p); GEN FlxqX_resultant_pre(GEN x, GEN y, GEN T, ulong p, ulong pi); GEN FlxqX_safegcd(GEN P, GEN Q, GEN T, ulong p); GEN FlxqX_saferesultant(GEN a, GEN b, GEN T, ulong p); GEN FlxqX_sqr(GEN x, GEN T, ulong p); GEN FlxqX_sqr_pre(GEN x, GEN T, ulong p, ulong pi); GEN FlxqXn_expint(GEN h, long e, GEN T, ulong p); GEN FlxqXn_expint_pre(GEN h, long e, GEN T, ulong p, ulong pi); GEN FlxqXn_inv(GEN f, long e, GEN T, ulong p); GEN FlxqXn_inv_pre(GEN f, long e, GEN T, ulong p, ulong pi); GEN FlxqXn_mul(GEN a, GEN b, long n, GEN T, ulong p); GEN FlxqXn_mul_pre(GEN a, GEN b, long n, GEN T, ulong p, ulong pi); GEN FlxqXn_sqr(GEN a, long n, GEN T, ulong p); GEN FlxqXn_sqr_pre(GEN a, long n, GEN T, ulong p, ulong pi); long FlxY_degreex(GEN b); ulong FlxY_eval_powers_pre(GEN pol, GEN yp, GEN xp, ulong p,ulong pi); GEN Fly_to_FlxY(GEN B, long v); GEN Kronecker_to_FlxqX(GEN z, GEN T, ulong p); GEN Kronecker_to_FlxqX_pre(GEN z, GEN T, ulong p, ulong pi); GEN RgX_to_FlxqX(GEN x, GEN T, ulong p); const struct bb_algebra *get_FlxqXQ_algebra(void **E, GEN S, GEN T, ulong p); GEN pol1_FlxX(long v, long sv); GEN polx_FlxX(long v, long sv); GEN random_FlxqX(long d1, long v, GEN T, ulong p); GEN zlxX_translate1(GEN P, long p, long e, long n); GEN zxX_to_FlxX(GEN B, ulong p); GEN zxX_to_Kronecker(GEN P, GEN Q); /* FlxqE.c */ GEN Flxq_ellcard(GEN a4, GEN a6, GEN T, ulong p); GEN Flxq_ellgens(GEN a4, GEN a6, GEN ch, GEN D, GEN m, GEN T, ulong p); GEN Flxq_ellgroup(GEN a4, GEN a6, GEN N, GEN T, ulong p, GEN *pt_m); void Flxq_elltwist(GEN a, GEN a6, GEN T, ulong p, GEN *pt_a, GEN *pt_a6); GEN Flxq_ellj(GEN a4, GEN a6, GEN T, ulong p); void Flxq_ellj_to_a4a6(GEN j, GEN T, ulong p, GEN *pt_a4, GEN *pt_a6); GEN FlxqE_add(GEN P, GEN Q, GEN a4, GEN T, ulong p); GEN FlxqE_changepoint(GEN x, GEN ch, GEN T, ulong p); GEN FlxqE_changepointinv(GEN x, GEN ch, GEN T, ulong p); GEN FlxqE_dbl(GEN P, GEN a4, GEN T, ulong p); GEN FlxqE_log(GEN a, GEN b, GEN o, GEN a4, GEN T, ulong p); GEN FlxqE_mul(GEN P, GEN n, GEN a4, GEN T, ulong p); GEN FlxqE_neg(GEN P, GEN T, ulong p); GEN FlxqE_order(GEN z, GEN o, GEN a4, GEN T, ulong p); GEN FlxqE_sub(GEN P, GEN Q, GEN a4, GEN T, ulong p); GEN FlxqE_tatepairing(GEN t, GEN s, GEN m, GEN a4, GEN T, ulong p); GEN FlxqE_weilpairing(GEN t, GEN s, GEN m, GEN a4, GEN T, ulong p); GEN FlxqE_weilpairing_pre(GEN P, GEN Q, GEN m, GEN a4, GEN T, ulong p, ulong pi); GEN ZXX_to_FlxX(GEN B, ulong p, long v); GEN ZXXT_to_FlxXT(GEN z, ulong p, long v); GEN ZXXV_to_FlxXV(GEN V, ulong p, long v); const struct bb_group * get_FlxqE_group(void **E, GEN a4, GEN a6, GEN T, ulong p); GEN RgE_to_FlxqE(GEN x, GEN T, ulong p); GEN random_FlxqE(GEN a4, GEN a6, GEN T, ulong p); long polisclass(GEN H); /* FpE.c */ long Fl_elltrace(ulong a4, ulong a6, ulong p); long Fl_elltrace_CM(long CM, ulong a4, ulong a6, ulong p); GEN Fp_ellcard(GEN a4, GEN a6, GEN p); GEN Fp_elldivpol(GEN a4, GEN a6, long n, GEN p); GEN Fp_ellgens(GEN a4, GEN a6, GEN ch, GEN D, GEN m, GEN p); GEN Fp_ellgroup(GEN a4, GEN a6, GEN N, GEN p, GEN *pt_m); GEN Fp_ellj(GEN a4, GEN a6, GEN p); void Fp_ellj_to_a4a6(GEN j, GEN p, GEN *pt_a4, GEN *pt_a6); int Fp_elljissupersingular(GEN j, GEN p); void Fp_elltwist(GEN a4, GEN a6, GEN p, GEN *pt_a4, GEN *pt_a6); GEN Fp_ffellcard(GEN a4, GEN a6, GEN q, long n, GEN p); GEN FpE_add(GEN P, GEN Q, GEN a4, GEN p); GEN FpE_changepoint(GEN x, GEN ch, GEN p); GEN FpE_changepointinv(GEN x, GEN ch, GEN p); GEN FpE_dbl(GEN P, GEN a4, GEN p); GEN FpE_log(GEN a, GEN b, GEN o, GEN a4, GEN p); GEN FpE_mul(GEN P, GEN n, GEN a4, GEN p); GEN FpE_neg(GEN P, GEN p); GEN FpE_order(GEN z, GEN o, GEN a4, GEN p); GEN FpE_sub(GEN P, GEN Q, GEN a4, GEN p); GEN FpE_to_FpJ(GEN P); GEN FpE_to_mod(GEN P, GEN p); GEN FpE_tatepairing(GEN t, GEN s, GEN m, GEN a4, GEN p); GEN FpE_weilpairing(GEN t, GEN s, GEN m, GEN a4, GEN p); GEN FpJ_add(GEN P, GEN Q, GEN a4, GEN p); GEN FpJ_dbl(GEN P, GEN a4, GEN p); GEN FpJ_mul(GEN P, GEN n, GEN a4, GEN p); GEN FpJ_neg(GEN Q, GEN p); GEN FpJ_to_FpE(GEN P, GEN p); GEN FpXQ_ellcard(GEN a4, GEN a6, GEN T, GEN p); GEN FpXQ_ellcard_supersingular(GEN a4, GEN a6, GEN T, GEN p); GEN FpXQ_elldivpol(GEN a4, GEN a6, long n, GEN T, GEN p); GEN FpXQ_ellgens(GEN a4, GEN a6, GEN ch, GEN D, GEN m, GEN T, GEN p); GEN FpXQ_ellgroup(GEN a4, GEN a6, GEN N, GEN T, GEN p, GEN *pt_m); GEN FpXQ_ellj(GEN a4, GEN a6, GEN T, GEN p); int FpXQ_elljissupersingular(GEN j, GEN T, GEN p); void FpXQ_elltwist(GEN a4, GEN a6, GEN T, GEN p, GEN *pt_a4, GEN *pt_a6); GEN FpXQE_add(GEN P, GEN Q, GEN a4, GEN T, GEN p); GEN FpXQE_changepoint(GEN x, GEN ch, GEN T, GEN p); GEN FpXQE_changepointinv(GEN x, GEN ch, GEN T, GEN p); GEN FpXQE_dbl(GEN P, GEN a4, GEN T, GEN p); GEN FpXQE_log(GEN a, GEN b, GEN o, GEN a4, GEN T, GEN p); GEN FpXQE_mul(GEN P, GEN n, GEN a4, GEN T, GEN p); GEN FpXQE_neg(GEN P, GEN T, GEN p); GEN FpXQE_order(GEN z, GEN o, GEN a4, GEN T, GEN p); GEN FpXQE_sub(GEN P, GEN Q, GEN a4, GEN T, GEN p); GEN FpXQE_tatepairing(GEN t, GEN s, GEN m, GEN a4, GEN T, GEN p); GEN FpXQE_weilpairing(GEN t, GEN s, GEN m, GEN a4, GEN T, GEN p); int Fq_elljissupersingular(GEN j, GEN T, GEN p); GEN Fq_ellcard_supersingular(GEN a4, GEN a6, GEN T, GEN p); GEN RgE_to_FpE(GEN x, GEN p); GEN RgE_to_FpXQE(GEN x, GEN T, GEN p); const struct bb_group * get_FpE_group(void **E, GEN a4, GEN a6, GEN p); const struct bb_group * get_FpXQE_group(void **E, GEN a4, GEN a6, GEN T, GEN p); GEN ellsupersingularj_FpXQ(GEN T, GEN p); GEN elltrace_extension(GEN t, long n, GEN p); GEN random_FpE(GEN a4, GEN a6, GEN p); GEN random_FpXQE(GEN a4, GEN a6, GEN T, GEN p); /* FpX.c */ int Fp_issquare(GEN x, GEN p); GEN Fp_FpX_sub(GEN x, GEN y, GEN p); GEN Fp_FpXQ_log(GEN a, GEN g, GEN ord, GEN T, GEN p); GEN FpV_FpM_polint(GEN xa, GEN ya, GEN p, long vs); GEN FpV_inv(GEN x, GEN p); GEN FpV_invVandermonde(GEN L, GEN den, GEN p); GEN FpV_polint(GEN xa, GEN ya, GEN p, long v); 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_div(GEN x, GEN y, GEN p); GEN FpX_Fp_mul(GEN x, GEN y, GEN p); GEN FpX_Fp_mul_to_monic(GEN y,GEN x,GEN p); GEN FpX_Fp_mulspec(GEN y,GEN x,GEN p,long ly); GEN FpX_Fp_sub(GEN x, GEN y, GEN p); GEN FpX_Fp_sub_shallow(GEN y,GEN x,GEN p); GEN FpX_FpV_multieval(GEN P, GEN xa, GEN p); GEN FpX_FpXQ_eval(GEN f,GEN x,GEN T,GEN p); GEN FpX_FpXQV_eval(GEN f,GEN x,GEN T,GEN p); GEN FpX_FpXV_multirem(GEN P, GEN xa, GEN p); GEN FpX_Frobenius(GEN T, GEN p); GEN FpX_Laplace(GEN x, GEN p); GEN FpX_Newton(GEN P, long n, GEN p); GEN FpX_add(GEN x, GEN y, GEN p); GEN FpX_center(GEN x, GEN p, GEN pov2); GEN FpX_center_i(GEN T, GEN p, GEN pov2); GEN FpX_chinese_coprime(GEN x,GEN y,GEN Tx,GEN Ty,GEN Tz,GEN p); GEN FpX_composedprod(GEN P, GEN Q, GEN p); GEN FpX_composedsum(GEN P, GEN Q, GEN p); GEN FpX_convol(GEN x, GEN y, GEN p); GEN FpX_deriv(GEN x, GEN p); GEN FpX_digits(GEN x, GEN y, GEN p); GEN FpX_disc(GEN x, GEN p); GEN FpX_div_by_X_x(GEN a, GEN x, GEN p, GEN *r); GEN FpX_divrem(GEN x, GEN y, GEN p, GEN *pr); GEN FpX_divu(GEN x, ulong y, GEN p); GEN FpX_dotproduct(GEN x, GEN y, GEN p); GEN FpX_eval(GEN x,GEN y,GEN p); GEN FpX_extgcd(GEN x, GEN y, GEN p, GEN *ptu, GEN *ptv); GEN FpX_extresultant(GEN a, GEN b, GEN p, GEN *ptU, GEN *ptV); GEN FpX_fromNewton(GEN P, GEN p); GEN FpX_gcd(GEN x, GEN y, GEN p); GEN FpX_gcd_check(GEN x, GEN y, GEN p); GEN FpX_get_red(GEN T, GEN p); GEN FpX_halve(GEN y, GEN p); GEN FpX_halfgcd(GEN x, GEN y, GEN p); GEN FpX_halfgcd_all(GEN x, GEN y, GEN p, GEN *ptU, GEN *ptV); GEN FpX_integ(GEN x, GEN p); GEN FpX_invBarrett(GEN T, GEN p); GEN FpX_invLaplace(GEN x, GEN p); int FpX_is_squarefree(GEN f, GEN p); GEN FpX_matFrobenius(GEN T, GEN p); GEN FpX_mul(GEN x, GEN y, GEN p); GEN FpX_mulspec(GEN a, GEN b, GEN p, long na, long nb); GEN FpX_mulu(GEN x, ulong y, GEN p); GEN FpX_neg(GEN x, GEN p); GEN FpX_normalize(GEN z, GEN p); GEN FpX_powu(GEN x, ulong n, GEN p); GEN FpX_red(GEN z, GEN p); GEN FpX_rem(GEN x, GEN y, GEN p); GEN FpX_rescale(GEN P, GEN h, GEN p); GEN FpX_resultant(GEN a, GEN b, GEN p); GEN FpX_sqr(GEN x, GEN p); GEN FpX_sub(GEN x, GEN y, GEN p); long FpX_valrem(GEN x0, GEN t, GEN p, GEN *py); GEN FpXC_FpXQ_eval(GEN Q, GEN x, GEN T, GEN p); GEN FpXC_FpXQV_eval(GEN Q, GEN x, GEN T, GEN p); GEN FpXM_FpXQV_eval(GEN Q, GEN x, GEN T, GEN p); GEN FpXQ_autpow(GEN x, ulong n, GEN T, GEN p); GEN FpXQ_autpowers(GEN aut, long f, GEN T, GEN p); GEN FpXQ_autsum(GEN x, ulong n, GEN T, GEN p); GEN FpXQ_auttrace(GEN x, ulong n, GEN T, GEN p); GEN FpXQ_charpoly(GEN x, GEN T, GEN p); GEN FpXQ_conjvec(GEN x, GEN T, GEN p); GEN FpXQ_div(GEN x,GEN y,GEN T,GEN p); GEN FpXQ_inv(GEN x,GEN T,GEN p); GEN FpXQ_invsafe(GEN x, GEN T, GEN p); int FpXQ_issquare(GEN x, GEN T, GEN p); GEN FpXQ_log(GEN a, GEN g, GEN ord, GEN T, GEN p); GEN FpXQ_matrix_pow(GEN y, long n, long m, GEN P, GEN l); GEN FpXQ_minpoly(GEN x, GEN T, GEN p); GEN FpXQ_mul(GEN y,GEN x,GEN T,GEN p); GEN FpXQ_norm(GEN x, GEN T, GEN p); GEN FpXQ_order(GEN a, GEN ord, GEN T, GEN p); GEN FpXQ_pow(GEN x, GEN n, GEN T, GEN p); GEN FpXQ_powu(GEN x, ulong n, GEN T, GEN p); GEN FpXQ_powers(GEN x, long l, GEN T, GEN p); GEN FpXQ_red(GEN x, GEN T, GEN p); GEN FpXQ_sqr(GEN y, GEN T, GEN p); GEN FpXQ_sqrt(GEN a, GEN T, GEN p); GEN FpXQ_sqrtn(GEN a, GEN n, GEN T, GEN p, GEN *zetan); GEN FpXQ_trace(GEN x, GEN T, GEN p); GEN FpXQC_to_mod(GEN z, GEN T, GEN p); GEN FpXQM_autsum(GEN x, ulong n, GEN T, GEN p); GEN FpXT_red(GEN z, GEN p); GEN FpXV_FpX_fromdigits(GEN x, GEN T, GEN p); GEN FpXV_chinese(GEN A, GEN P, GEN p, GEN *pt_mod); GEN FpXV_composedsum(GEN V, GEN p); GEN FpXV_factorback(GEN fa, GEN e, GEN p, long v); GEN FpXV_prod(GEN V, GEN p); GEN FpXV_red(GEN z, GEN p); GEN FpXn_div(GEN g, GEN f, long n, GEN p); GEN FpXn_exp(GEN x, long n, GEN p); GEN FpXn_expint(GEN x, long n, GEN p); GEN FpXn_inv(GEN x, long n, GEN p); GEN FpXn_mul(GEN a, GEN b, long n, GEN p); GEN FpXn_sqr(GEN a, long n, GEN p); int Fq_issquare(GEN x, GEN T, GEN p); long Fq_ispower(GEN x, GEN K, GEN T, GEN p); GEN Fq_log(GEN a, GEN g, GEN ord, GEN T, GEN p); GEN FqC_to_mod(GEN z, GEN T, GEN p); GEN FqM_to_mod(GEN z, GEN T, GEN p); GEN FqV_inv(GEN x, GEN T, GEN p); GEN Z_to_FpX(GEN a, GEN p, long v); GEN gener_FpXQ(GEN T, GEN p, GEN *o); GEN gener_FpXQ_local(GEN T, GEN p, GEN L); const struct bb_group * get_FpXQ_star(void **E, GEN T, GEN p); const struct bb_algebra * get_FpX_algebra(void **E, GEN p, long v); const struct bb_algebra * get_FpXQ_algebra(void **E, GEN T, GEN p); GEN random_FpX(long d, long v, GEN p); /* FpX_factor.c */ GEN F2x_ddf(GEN f); GEN F2x_factor(GEN f); GEN F2x_factor_squarefree(GEN f); int F2x_is_irred(GEN f); GEN Flx_ddf(GEN T, ulong p); GEN Flx_ddf_pre(GEN T, ulong p, ulong pi); int Flx_is_irred(GEN f, ulong p); int Flx_is_totally_split(GEN f, ulong p); long Flx_ispower(GEN f, ulong k, ulong p, GEN *pt_r); GEN Flx_degfact(GEN f, ulong p); GEN Flx_factor(GEN f, ulong p); GEN Flx_factor_squarefree(GEN f, ulong p); GEN Flx_factor_squarefree_pre(GEN f, ulong p, ulong pi); long Flx_nbfact(GEN z, ulong p); long Flx_nbfact_pre(GEN z, ulong p, ulong pi); long Flx_nbfact_Frobenius(GEN T, GEN XP, ulong p); long Flx_nbfact_Frobenius_pre(GEN T, GEN XP, ulong p, ulong pi); GEN Flx_nbfact_by_degree(GEN z, long *nb, ulong p); long Flx_nbroots(GEN f, ulong p); ulong Flx_oneroot(GEN f, ulong p); ulong Flx_oneroot_split(GEN f, ulong p); ulong Flx_oneroot_pre(GEN f, ulong p, ulong pi); ulong Flx_oneroot_split_pre(GEN f, ulong p, ulong pi); GEN Flx_roots(GEN f, ulong p); GEN Flx_roots_pre(GEN f, ulong p, ulong pi); GEN Flx_rootsff(GEN P, GEN T, ulong p); GEN FpX_ddf(GEN f, GEN p); long FpX_ddf_degree(GEN T, GEN XP, GEN p); GEN FpX_degfact(GEN f, GEN p); GEN FpX_factor(GEN f, GEN p); GEN FpX_factor_squarefree(GEN T, GEN p); int FpX_is_irred(GEN f, GEN p); int FpX_is_totally_split(GEN f, GEN p); long FpX_ispower(GEN f, ulong k, GEN p, GEN *pt_r); long FpX_nbfact(GEN f, GEN p); long FpX_nbfact_Frobenius(GEN T, GEN XP, GEN p); long FpX_nbroots(GEN f, GEN p); GEN FpX_oneroot(GEN f, GEN p); GEN FpX_oneroot_split(GEN fact, GEN p); GEN FpX_roots(GEN f, GEN p); GEN FpX_roots_mult(GEN T, long n, GEN p); GEN FpX_rootsff(GEN P, GEN T, GEN p); GEN FpX_split_part(GEN f, GEN p); /* FpXQX_factor.c */ GEN F2xqX_ddf(GEN S, GEN T); GEN F2xqX_degfact(GEN S, GEN T); GEN F2xqX_factor(GEN x, GEN T); GEN F2xqX_factor_squarefree(GEN x, GEN T); GEN F2xqX_roots(GEN x, GEN T); GEN Flx_factorff_irred(GEN P, GEN Q, ulong p); void Flx_ffintersect(GEN P,GEN Q,long n,ulong l,GEN *SP,GEN *SQ,GEN MA,GEN MB); GEN Flx_ffisom(GEN P,GEN Q,ulong l); GEN Flxq_ffisom_inv(GEN S,GEN Tp, ulong p); GEN FlxqX_Frobenius(GEN S, GEN T, ulong p); GEN FlxqX_Frobenius_pre(GEN S, GEN T, ulong p, ulong pi); GEN FlxqX_ddf(GEN S, GEN T, ulong p); long FlxqX_ddf_degree(GEN S, GEN XP, GEN T, ulong p); GEN FlxqX_degfact(GEN S, GEN T, ulong p); GEN FlxqX_factor(GEN x, GEN T, ulong p); GEN FlxqX_factor_squarefree(GEN x, GEN T, ulong p); GEN FlxqX_factor_squarefree_pre(GEN f, GEN T, ulong p, ulong pi); long FlxqX_ispower(GEN f, ulong k, GEN T, ulong p, GEN *pt_r); long FlxqX_is_squarefree(GEN P, GEN T, ulong p); long FlxqX_nbfact(GEN S, GEN T, ulong p); long FlxqX_nbfact_Frobenius(GEN S, GEN Xq, GEN T, ulong p); GEN FlxqX_nbfact_by_degree(GEN f, long *nb, GEN T, ulong p); long FlxqX_nbroots(GEN f, GEN T, ulong p); GEN FlxqX_roots(GEN S, GEN T, ulong p); GEN FlxqXQ_halfFrobenius(GEN a, GEN S, GEN T, ulong p); GEN FpX_factorff(GEN P, GEN T, GEN p); GEN FpX_factorff_irred(GEN P, GEN Q, GEN p); void FpX_ffintersect(GEN P,GEN Q,long n,GEN l,GEN *SP,GEN *SQ,GEN MA,GEN MB); GEN FpX_ffisom(GEN P,GEN Q,GEN l); GEN FpXQ_ffisom_inv(GEN S,GEN Tp, GEN p); GEN FpXQX_Frobenius(GEN S, GEN T, GEN p); GEN FpXQX_ddf(GEN S, GEN T, GEN p); long FpXQX_ddf_degree(GEN S, GEN XP, GEN T, GEN p); GEN FpXQX_degfact(GEN S, GEN T, GEN p); GEN FpXQX_factor(GEN x, GEN T, GEN p); GEN FpXQX_factor_squarefree(GEN x, GEN T, GEN p); long FpXQX_ispower(GEN f, ulong k, GEN T, GEN p, GEN *pt); long FpXQX_nbfact(GEN u, GEN T, GEN p); long FpXQX_nbfact_Frobenius(GEN S, GEN Xq, GEN T, GEN p); long FpXQX_nbroots(GEN f, GEN T, GEN p); GEN FpXQX_roots(GEN f, GEN T, GEN p); GEN FpXQX_roots_mult(GEN f, long n, GEN T, GEN p); GEN FpXQX_split_part(GEN f, GEN T, GEN p); GEN FpXQXQ_halfFrobenius(GEN a, GEN S, GEN T, GEN p); long FqX_is_squarefree(GEN P, GEN T, GEN p); long FqX_ispower(GEN f, ulong k, GEN T, GEN p, GEN *pt); long FqX_nbfact(GEN u, GEN T, GEN p); long FqX_nbroots(GEN f, GEN T, GEN p); GEN factorff(GEN f, GEN p, GEN a); GEN factormod0(GEN f, GEN p,long flag); GEN factormodDDF(GEN f, GEN D); GEN factormodSQF(GEN f, GEN D); int ff_parse_Tp(GEN Tp, GEN *T, GEN *p, long red); GEN polrootsff(GEN f, GEN p, GEN T); GEN polrootsmod(GEN f, GEN p); GEN rootmod0(GEN f, GEN p,long flag); /* FpXX.c */ GEN FpXQX_FpXQ_mul(GEN P, GEN U, GEN T, GEN p); GEN FpXQX_FpXQXQV_eval(GEN P, GEN V, GEN S, GEN T, GEN p); GEN FpXQX_FpXQXQ_eval(GEN P, GEN x, GEN S, GEN T, GEN p); GEN FpXQX_digits(GEN x, GEN B, GEN T, GEN p); GEN FpXQX_disc(GEN x, GEN T, GEN p); GEN FpXQX_div_by_X_x(GEN a, GEN x, GEN T, GEN p, GEN *pr); GEN FpXQX_divrem(GEN x, GEN y, GEN T, GEN p, GEN *pr); GEN FpXQX_dotproduct(GEN x, GEN y, GEN T, GEN p); GEN FpXQX_extgcd(GEN x, GEN y, GEN T, GEN p, GEN *ptu, GEN *ptv); GEN FpXQX_gcd(GEN P, GEN Q, GEN T, GEN p); GEN FpXQX_get_red(GEN S, GEN T, GEN p); GEN FpXQX_halfgcd(GEN x, GEN y, GEN T, GEN p); GEN FpXQX_halfgcd_all(GEN x, GEN y, GEN T, GEN p, GEN *a, GEN *b); GEN FpXQX_invBarrett(GEN S, GEN T, GEN p); GEN FpXQX_mul(GEN x, GEN y, GEN T, GEN p); GEN FpXQX_powu(GEN x, ulong n, GEN T, GEN p); GEN FpXQX_red(GEN z, GEN T, GEN p); GEN FpXQX_rem(GEN x, GEN S, GEN T, GEN p); GEN FpXQX_resultant(GEN a, GEN b, GEN T, GEN p); GEN FpXQX_sqr(GEN x, GEN T, GEN p); GEN FpXQX_to_mod(GEN z, GEN T, GEN p); GEN FpXQXQ_div(GEN x,GEN y,GEN S, GEN T,GEN p); GEN FpXQXQ_inv(GEN x, GEN S, GEN T,GEN p); GEN FpXQXQ_invsafe(GEN x, GEN S, GEN T, GEN p); GEN FpXQXQ_matrix_pow(GEN y, long n, long m, GEN S, GEN T, GEN p); GEN FpXQXQ_minpoly(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_powers(GEN x, long n, GEN S, GEN T, GEN p); GEN FpXQXQ_sqr(GEN x, GEN S, GEN T, GEN p); GEN FpXQXQ_autpow(GEN aut, long n, GEN S, GEN T, GEN p); GEN FpXQXQ_autsum(GEN aut, long n, GEN S, GEN T, GEN p); GEN FpXQXQ_auttrace(GEN aut, long n, GEN S, GEN T, GEN p); GEN FpXQXT_red(GEN x, GEN T, GEN p); GEN FpXQXV_FpXQX_fromdigits(GEN x, GEN B, GEN T, GEN p); GEN FpXQXV_prod(GEN V, GEN Tp, GEN p); GEN FpXQXV_red(GEN x, GEN T, GEN p); GEN FpXQXn_div(GEN g, GEN f, long n, GEN T, GEN p); GEN FpXQXn_exp(GEN x, long n, GEN T, GEN p); GEN FpXQXn_expint(GEN x, long n, GEN T, GEN p); GEN FpXQXn_inv(GEN x, long n, GEN T, GEN p); GEN FpXQXn_mul(GEN x, GEN y, long n, GEN T, GEN p); GEN FpXQXn_sqr(GEN x, long n, GEN T, GEN p); GEN FpXX_Fp_mul(GEN x, GEN y, GEN p); GEN FpXX_FpX_mul(GEN x, GEN y, GEN p); GEN FpXX_add(GEN x, GEN y, GEN p); GEN FpXX_deriv(GEN P, GEN p); GEN FpXX_halve(GEN P, GEN p); GEN FpXX_integ(GEN P, GEN p); GEN FpXX_mulu(GEN P, ulong u, GEN p); GEN FpXX_neg(GEN x, GEN p); GEN FpXX_red(GEN z, GEN p); GEN FpXX_sub(GEN x, GEN y, GEN p); GEN FpXY_FpXQ_evalx(GEN P, GEN x, GEN T, GEN p); GEN FpXY_FpXQV_evalx(GEN P, GEN x, GEN T, GEN p); GEN FpXY_eval(GEN Q, GEN y, GEN x, GEN p); GEN FpXY_evalx(GEN Q, GEN x, GEN p); GEN FpXY_evaly(GEN Q, GEN y, GEN p, long vy); GEN FpXYQQ_pow(GEN x, GEN n, GEN S, GEN T, GEN p); GEN FqXC_to_mod(GEN z, GEN T, GEN p); GEN FqXM_to_mod(GEN z, GEN T, GEN p); GEN Kronecker_to_FpXQX(GEN z, GEN pol, GEN p); const struct bb_algebra * get_FpXQX_algebra(void **E, GEN T, GEN p, long v); const struct bb_algebra * get_FpXQXQ_algebra(void **E, GEN S, GEN T, GEN p); GEN random_FpXQX(long d1, long v, GEN T, GEN p); /* FpV.c */ GEN Flc_Flv_mul(GEN x, GEN y, ulong p); GEN Flc_to_mod(GEN z, ulong p); GEN Flm_Fl_add(GEN x, ulong y, ulong p); GEN Flm_Fl_mul(GEN y, ulong x, ulong p); void Flm_Fl_mul_inplace(GEN y, ulong x, ulong p); GEN Flm_Fl_mul_pre(GEN y, ulong x, ulong p, ulong pi); GEN Flm_Fl_sub(GEN x, ulong y, ulong p); GEN Flm_Flc_mul(GEN x, GEN y, ulong p); GEN Flm_Flc_mul_pre(GEN x, GEN y, ulong p, ulong pi); GEN Flm_Flc_mul_pre_Flx(GEN x, GEN y, ulong p, ulong pi, long sv); GEN Flm_add(GEN x, GEN y, ulong p); GEN Flm_center(GEN z, ulong p, ulong ps2); GEN Flm_mul(GEN x, GEN y, ulong p); GEN Flm_mul_pre(GEN x, GEN y, ulong p, ulong pi); GEN Flm_neg(GEN y, ulong p); GEN Flm_powers(GEN x, ulong n, ulong p); GEN Flm_powu(GEN x, ulong n, ulong p); GEN Flm_sqr(GEN x, ulong p); GEN Flm_sub(GEN x, GEN y, ulong p); GEN Flm_to_mod(GEN z, ulong p); GEN Flm_transpose(GEN x); GEN Flv_Fl_div(GEN x, ulong y, ulong p); void Flv_Fl_div_inplace(GEN x, ulong y, ulong p); GEN Flv_Fl_mul(GEN x, ulong y, ulong p); void Flv_Fl_mul_inplace(GEN x, ulong y, ulong p); void Flv_Fl_mul_part_inplace(GEN x, ulong y, ulong p, long l); GEN Flv_add(GEN x, GEN y, ulong p); void Flv_add_inplace(GEN x, GEN y, ulong p); GEN Flv_center(GEN z, ulong p, ulong ps2); ulong Flv_dotproduct(GEN x, GEN y, ulong p); ulong Flv_dotproduct_pre(GEN x, GEN y, ulong p, ulong pi); GEN Flv_neg(GEN v, ulong p); void Flv_neg_inplace(GEN v, 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); ulong Flx_dotproduct(GEN x, GEN y, ulong p); ulong Flx_dotproduct_pre(GEN x, GEN y, ulong p, ulong pi); GEN Fp_to_mod(GEN z, GEN p); GEN FpC_FpV_mul(GEN x, GEN y, GEN p); GEN FpC_Fp_mul(GEN x, GEN y, GEN p); GEN FpC_center(GEN z, GEN p, GEN pov2); void FpC_center_inplace(GEN z, GEN p, GEN pov2); GEN FpC_red(GEN z, GEN p); GEN FpC_to_mod(GEN z, GEN p); GEN FpM_add(GEN x, GEN y, GEN p); GEN FpM_Fp_mul(GEN X, GEN c, GEN p); GEN FpM_FpC_mul(GEN x, GEN y, GEN p); GEN FpM_FpC_mul_FpX(GEN x, GEN y, GEN p, long v); GEN FpM_center(GEN z, GEN p, GEN pov2); void FpM_center_inplace(GEN z, GEN p, GEN pov2); GEN FpM_mul(GEN x, GEN y, GEN p); GEN FpM_powu(GEN x, ulong n, GEN p); GEN FpM_red(GEN z, GEN p); GEN FpM_sub(GEN x, GEN y, GEN p); GEN FpM_to_mod(GEN z, GEN p); GEN FpMs_FpC_mul(GEN M, GEN B, GEN p); GEN FpMs_FpCs_solve(GEN M, GEN B, long nbrow, GEN p); GEN FpMs_FpCs_solve_safe(GEN M, GEN A, long nbrow, GEN p); GEN FpMs_leftkernel_elt(GEN M, long nbrow, GEN p); GEN FpC_add(GEN x, GEN y, GEN p); GEN FpC_sub(GEN x, GEN y, GEN p); GEN FpV_FpMs_mul(GEN B, GEN M, GEN p); GEN FpV_add(GEN x, GEN y, GEN p); GEN FpV_sub(GEN x, GEN y, GEN p); GEN FpV_dotproduct(GEN x, GEN y, GEN p); GEN FpV_dotsquare(GEN x, GEN p); GEN FpV_red(GEN z, GEN p); GEN FpV_to_mod(GEN z, GEN p); GEN FpVV_to_mod(GEN z, GEN p); GEN FpX_to_mod(GEN z, GEN p); GEN FpXC_to_mod(GEN x, GEN p); GEN FpXM_to_mod(GEN x, GEN p); GEN ZabM_ker(GEN M, GEN P, long n); GEN ZabM_indexrank(GEN M, GEN P, long n); GEN ZabM_inv(GEN M, GEN P, long n, GEN *pden); GEN ZabM_inv_ratlift(GEN M, GEN P, long n, GEN *pden); GEN ZabM_pseudoinv(GEN M, GEN P, long n, GEN *pv, GEN *den); GEN ZV_zMs_mul(GEN B, GEN M); GEN ZpMs_ZpCs_solve(GEN M, GEN B, long nbrow, GEN p, long e); GEN gen_FpM_Wiedemann(void *E, GEN (*f)(void*, GEN), GEN B, GEN p); GEN gen_ZpM_Dixon_Wiedemann(void *E, GEN (*f)(void*, GEN), GEN B, GEN p, long e); GEN gen_matid(long n, void *E, const struct bb_field *S); GEN matid_Flm(long n); GEN matid_F2xqM(long n, GEN T); GEN matid_FlxqM(long n, GEN T, ulong p); GEN random_Flv(long n, ulong p); GEN random_FpC(long d, GEN p); GEN random_FpV(long d, GEN p); GEN scalar_Flm(long s, long n); GEN zCs_to_ZC(GEN C, long nbrow); GEN zMs_to_ZM(GEN M, long nbrow); GEN zMs_ZC_mul(GEN M, GEN B); GEN ZMV_to_FlmV(GEN z, ulong m); /* Zp.c */ GEN Flx_Teichmuller(GEN P, ulong p, long n); GEN Z2_sqrt(GEN x, long e); GEN Zp_div(GEN a, GEN b, GEN p, long e); GEN Zp_exp(GEN arg, GEN p, ulong e); GEN Zp_inv(GEN a, GEN p, long e); GEN Zp_invlift(GEN b, GEN a, GEN p, long e); GEN Zp_log(GEN arg, GEN p, ulong e); GEN Zp_sqrt(GEN x, GEN p, long e); GEN Zp_sqrtlift(GEN b, GEN a, GEN p, long e); GEN Zp_sqrtnlift(GEN b, GEN n, GEN a, GEN p, long e); GEN ZpM_invlift(GEN M, GEN C, GEN p, long n); GEN ZpX_Frobenius(GEN T, GEN p, long e); GEN ZpX_ZpXQ_liftroot(GEN P, GEN S, GEN T, GEN p, long e); GEN ZpX_ZpXQ_liftroot_ea(GEN P, GEN S, GEN T, GEN p, long n, void *E, GEN early(void *E, GEN x, GEN q)); GEN ZpX_liftfact(GEN pol, GEN Q, GEN pe, GEN p, long e); GEN ZpX_liftroot(GEN f, GEN a, GEN p, long e); GEN ZpX_liftroots(GEN f, GEN S, GEN p, long e); GEN ZpX_roots(GEN f, GEN p, long e); GEN ZpXQ_div(GEN a, GEN b, GEN T, GEN q, GEN p, long e); GEN ZpXQ_inv(GEN a, GEN T, GEN p, long e); GEN ZpXQ_invlift(GEN b, GEN a, GEN T, GEN p, long e); GEN ZpXQ_log(GEN a, GEN T, GEN p, long N); GEN ZpXQ_sqrt(GEN a, GEN T, GEN p, long e); GEN ZpXQ_sqrtnlift(GEN b, GEN n, GEN a, GEN T, GEN p, long e); GEN ZpXQM_prodFrobenius(GEN M, GEN T, GEN p, long e); GEN ZpXQX_digits(GEN x, GEN B, GEN T, GEN q, GEN p, long e); GEN ZpXQX_divrem(GEN x, GEN S, GEN T, GEN q, GEN p, long e, GEN *pr); GEN ZpXQX_liftfact(GEN pol, GEN Q, GEN T, GEN pe, GEN p, long e); GEN ZpXQX_liftroot(GEN f, GEN a, GEN T, GEN p, long e); GEN ZpXQX_liftroot_vald(GEN f, GEN a, long v, GEN T, GEN p, long e); GEN ZpXQX_liftroots(GEN f, GEN S, GEN T, GEN p, long e); GEN ZpXQX_roots(GEN F, GEN T, GEN p, long e); GEN ZpXQX_ZpXQXQ_liftroot(GEN P, GEN S, GEN Q, GEN T, GEN p, long e); GEN Zq_sqrtnlift(GEN a, GEN n, GEN x, GEN T, GEN p, long e); GEN ZqX_ZqXQ_liftroot(GEN f, GEN a, GEN S, GEN T, GEN p, long e); GEN ZqX_liftfact(GEN pol, GEN Q, GEN T, GEN pe, GEN p, long e); GEN ZqX_liftroot(GEN f, GEN a, GEN T, GEN p, long e); GEN ZqX_roots(GEN F, GEN T, GEN p, long e); GEN gen_ZpM_Dixon(GEN F, GEN V, GEN q, GEN p, long N, void *E, GEN lin(void *E, GEN F, GEN d, GEN q), GEN invl(void *E, GEN d)); GEN gen_ZpM_Newton(GEN x, GEN p, long n, void *E, GEN eval(void *E, GEN f, GEN q), GEN invd(void *E, GEN V, GEN v, GEN q, long M)); GEN gen_ZpX_Dixon(GEN F, GEN V, GEN q, GEN p, long N, void *E, GEN lin(void *E, GEN F, GEN d, GEN q), GEN invl(void *E, GEN d)); GEN gen_ZpX_Newton(GEN x, GEN p, long n, void *E, GEN eval(void *E, GEN f, GEN q), GEN invd(void *E, GEN V, GEN v, GEN q, long M)); GEN polteichmuller(GEN P, ulong p, long n); GEN polhensellift(GEN pol, GEN fct, GEN p, long exp); ulong quadratic_prec_mask(long n); /* QX_factor.c */ GEN QX_factor(GEN x); GEN ZX_factor(GEN x); long ZX_is_irred(GEN x); GEN ZX_squff(GEN f, GEN *ex); GEN polcyclofactors(GEN f); long poliscyclo(GEN f); long poliscycloprod(GEN f); /* RgV.c */ GEN Rg_RgC_sub(GEN a, GEN x); 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_Rg_sub(GEN x, GEN y); GEN RgC_RgM_mul(GEN x, GEN y); GEN RgC_RgV_mul(GEN x, GEN y); GEN RgC_add(GEN x, GEN y); long RgC_is_ei(GEN x); GEN RgC_neg(GEN x); GEN RgC_sub(GEN x, GEN y); GEN RgM_Rg_add(GEN x, GEN y); GEN RgM_Rg_add_shallow(GEN x, GEN y); GEN RgM_Rg_div(GEN x, GEN y); GEN RgM_Rg_mul(GEN x, GEN y); GEN RgM_Rg_sub(GEN x, GEN y); GEN RgM_Rg_sub_shallow(GEN x, GEN y); GEN RgM_RgC_mul(GEN x, GEN y); GEN RgM_RgV_mul(GEN x, GEN y); GEN RgM_ZM_mul(GEN x, GEN y); GEN RgM_add(GEN x, GEN y); GEN RgM_det_triangular(GEN x); int RgM_is_QM(GEN x); int RgM_is_ZM(GEN x); int RgM_isdiagonal(GEN x); int RgM_isidentity(GEN x); int RgM_isscalar(GEN x, GEN s); GEN RgM_mul(GEN x, GEN y); GEN RgM_multosym(GEN x, GEN y); GEN RgM_neg(GEN x); GEN RgM_powers(GEN x, long l); GEN RgM_sqr(GEN x); GEN RgM_sub(GEN x, GEN y); GEN RgM_sumcol(GEN A); GEN RgM_transmul(GEN x, GEN y); GEN RgM_transmultosym(GEN x, GEN y); GEN RgMrow_zc_mul(GEN x, GEN y, long i); GEN RgM_zc_mul(GEN x, GEN y); GEN RgM_zm_mul(GEN x, GEN y); GEN RgMrow_RgC_mul(GEN x, GEN y, long i); GEN RgV_RgM_mul(GEN x, GEN y); GEN RgV_RgC_mul(GEN x, GEN y); GEN RgV_Rg_mul(GEN x, GEN y); GEN RgV_add(GEN x, GEN y); GEN RgV_dotproduct(GEN x, GEN y); GEN RgV_dotsquare(GEN x); int RgV_is_ZMV(GEN V); GEN RgV_kill0(GEN v); GEN RgV_neg(GEN x); GEN RgV_prod(GEN v); GEN RgV_sub(GEN x, GEN y); GEN RgV_sum(GEN v); GEN RgV_sumpart(GEN v, long n); GEN RgV_sumpart2(GEN v, long m, long n); GEN RgV_zc_mul(GEN x, GEN y); GEN RgV_zm_mul(GEN x, GEN y); GEN RgX_RgM_eval(GEN x, GEN y); GEN RgX_RgMV_eval(GEN x, GEN y); int isdiagonal(GEN x); GEN matid(long n); GEN scalarcol(GEN x, long n); GEN scalarcol_shallow(GEN x, long n); GEN scalarmat(GEN x, long n); GEN scalarmat_shallow(GEN x, long n); GEN scalarmat_s(long x, long n); /* RgX.c */ GEN Kronecker_to_mod(GEN z, GEN pol); GEN QX_ZXQV_eval(GEN P, GEN V, GEN dV); GEN QXQ_charpoly(GEN A, GEN T, long v); GEN QXQ_powers(GEN a, long n, GEN T); GEN QXQ_to_mod_shallow(GEN x, GEN T); GEN QXQC_to_mod_shallow(GEN V, GEN T); GEN QXQM_to_mod_shallow(GEN V, GEN T); GEN QXQV_to_mod(GEN V, GEN T); GEN QXQX_homogenous_evalpow(GEN P, GEN A, GEN B, GEN T); GEN QXQX_to_mod_shallow(GEN z, GEN T); GEN QXQXV_to_mod(GEN V, GEN T); GEN QXV_QXQ_eval(GEN v, GEN a, GEN T); GEN QXY_QXQ_evalx(GEN v, GEN a, GEN T); GEN Rg_RgX_sub(GEN x, GEN y); GEN Rg_get_0(GEN x); GEN Rg_get_1(GEN x); GEN Rg_to_RgC(GEN x, long N); GEN RgM_to_RgXV(GEN x, long v); GEN RgM_to_RgXV_reverse(GEN x, long v); GEN RgM_to_RgXX(GEN x, long v,long w); GEN RgV_to_RgX(GEN x, long v); GEN RgV_to_RgM(GEN v, long n); GEN RgV_to_RgX_reverse(GEN x, long v); GEN RgX_RgXQ_eval(GEN f, GEN x, GEN T); GEN RgX_RgXQV_eval(GEN P, GEN V, GEN T); GEN RgX_RgXn_eval(GEN Q, GEN x, long n); GEN RgX_RgXnV_eval(GEN Q, GEN x, long n); GEN RgX_Rg_add(GEN y, GEN x); GEN RgX_Rg_add_shallow(GEN y, GEN x); GEN RgX_Rg_div(GEN y, GEN x); GEN RgX_Rg_divexact(GEN x, GEN y); GEN RgX_Rg_eval_bk(GEN Q, GEN x); GEN RgX_Rg_mul(GEN y, GEN x); GEN RgX_Rg_sub(GEN y, GEN x); GEN RgX_RgV_eval(GEN Q, GEN x); GEN RgX_add(GEN x, GEN y); GEN RgX_addmulXn_shallow(GEN x, GEN y, long d); GEN RgX_addmulXn(GEN x, GEN y, long d); GEN RgX_addspec(GEN x, GEN y, long nx, long ny); GEN RgX_addspec_shallow(GEN x, GEN y, long nx, long ny); GEN RgX_affine(GEN P, GEN a, GEN b); GEN RgX_blocks(GEN P, long n, long m); GEN RgX_deflate(GEN x0, long d); GEN RgX_deriv(GEN x); GEN RgX_digits(GEN A, GEN B); GEN RgX_div_by_X_x(GEN a, GEN x, GEN *r); GEN RgX_divrem(GEN x,GEN y,GEN *r); GEN RgX_divs(GEN y, long x); long RgX_equal(GEN x, GEN y); void RgX_even_odd(GEN p, GEN *pe, GEN *po); GEN RgX_homogenize(GEN P, long v); GEN RgX_homogenous_evalpow(GEN P, GEN A, GEN B); GEN RgX_inflate(GEN x0, long d); GEN RgX_mul(GEN x,GEN y); GEN RgX_mul_i(GEN x,GEN y); GEN RgX_mul_normalized(GEN A, long a, GEN B, long b); GEN RgX_mul2n(GEN y, long n); GEN RgX_mulXn(GEN x, long d); GEN RgX_mulhigh_i(GEN f, GEN g, long n); GEN RgX_muls(GEN y, long x); GEN RgX_mulspec(GEN a, GEN b, long na, long nb); GEN RgX_neg(GEN x); GEN RgX_normalize(GEN x); GEN RgX_pseudodivrem(GEN x, GEN y, GEN *ptr); GEN RgX_pseudorem(GEN x, GEN y); GEN RgX_recip(GEN x); GEN RgX_recip_i(GEN x); GEN RgX_recip_shallow(GEN x); GEN RgX_rem(GEN x, GEN y); GEN RgX_renormalize_lg(GEN x, long lx); GEN RgX_rescale(GEN P, GEN h); GEN RgX_rotate_shallow(GEN P, long k, long p); GEN RgX_shift(GEN a, long n); GEN RgX_shift_shallow(GEN x, long n); GEN RgX_splitting(GEN p, long k); GEN RgX_sqr(GEN x); GEN RgX_sqr_i(GEN x); GEN RgX_sqrhigh_i(GEN f, long n); GEN RgX_sqrspec(GEN a, long na); GEN RgX_sub(GEN x, GEN y); GEN RgX_to_RgC(GEN x, long N); GEN RgX_translate(GEN P, GEN c); GEN RgX_unscale(GEN P, GEN h); GEN RgXQ_matrix_pow(GEN y, long n, long m, GEN P); GEN RgXQ_norm(GEN x, GEN T); GEN RgXQ_pow(GEN x, GEN n, GEN T); GEN RgXQ_powers(GEN x, long l, GEN T); GEN RgXQ_powu(GEN x, ulong n, GEN T); GEN RgXQ_trace(GEN x, GEN T); GEN RgXQC_red(GEN P, GEN T); GEN RgXQM_mul(GEN P, GEN Q, GEN T); GEN RgXQM_red(GEN P, GEN T); GEN RgXQV_RgXQ_mul(GEN v, GEN x, GEN T); GEN RgXQV_factorback(GEN x, GEN n, 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_powers(GEN P, long n, GEN T); GEN RgXQX_pseudodivrem(GEN x, GEN y, GEN T, GEN *ptr); GEN RgXQX_pseudorem(GEN x, GEN y, GEN T); GEN RgXQX_red(GEN P, GEN T); GEN RgXQX_sqr(GEN x, GEN T); GEN RgXQX_translate(GEN P, GEN c, GEN T); GEN RgXV_RgV_eval(GEN Q, GEN x); GEN RgXV_prod(GEN V); GEN RgXV_rescale(GEN v, GEN h); GEN RgXV_to_RgM(GEN v, long n); GEN RgXV_unscale(GEN v, GEN h); GEN RgXX_to_RgM(GEN v, long n); long RgXY_degreex(GEN bpol); GEN RgXY_derivx(GEN x); GEN RgXY_swap(GEN x, long n, long w); GEN RgXY_swapspec(GEN x, long n, long w, long nx); GEN RgXn_div(GEN g, GEN f, long e); GEN RgXn_div_i(GEN g, GEN f, long e); GEN RgXn_eval(GEN Q, GEN x, long n); GEN RgXn_exp(GEN f, long e); GEN RgXn_expint(GEN f, long e); GEN RgXn_inv(GEN f, long e); GEN RgXn_inv_i(GEN f, long e); GEN RgXn_mul(GEN f, GEN g, long n); GEN RgXn_powers(GEN f, long m, long n); GEN RgXn_recip_shallow(GEN P, long n); GEN RgXn_red_shallow(GEN a, long n); GEN RgXn_reverse(GEN f, long e); GEN RgXn_sqr(GEN f, long n); GEN RgXn_sqrt(GEN f, long n); GEN RgXnV_red_shallow(GEN P, long n); GEN RgXn_powu(GEN x, ulong m, long n); GEN RgXn_powu_i(GEN x, ulong m, long n); GEN ZX_translate(GEN P, GEN c); GEN ZX_unscale2n(GEN P, long n); GEN ZX_unscale(GEN P, GEN h); GEN ZX_unscale_div(GEN P, GEN h); GEN ZX_unscale_divpow(GEN P, GEN h, long k); GEN ZX_z_unscale(GEN P, long h); GEN ZXQ_powers(GEN x, long l, GEN T); GEN ZXQ_powu(GEN x, ulong n, GEN T); int ZXQX_dvd(GEN x, GEN y, GEN T); long brent_kung_optpow(long d, long n, long m); GEN gen_bkeval(GEN Q, long d, GEN x, int use_sqr, void *E, const struct bb_algebra *ff, GEN cmul(void *E, GEN P, long a, GEN x)); GEN gen_bkeval_powers(GEN P, long d, GEN V, void *E, const struct bb_algebra *ff, GEN cmul(void *E, GEN P, long a, GEN x)); const struct bb_algebra * get_Rg_algebra(void); long rfrac_deflate_order(GEN F); GEN rfrac_deflate_max(GEN F, long *m); GEN rfrac_deflate(GEN F, long m); /* ZG.c */ void ZGC_G_mul_inplace(GEN v, GEN x); GEN ZGCs_add(GEN x, GEN y); GEN G_ZGC_mul(GEN x, GEN v); GEN G_ZG_mul(GEN x, GEN y); GEN ZGC_G_mul(GEN v, GEN x); GEN ZGC_Z_mul(GEN v, GEN x); GEN ZG_G_mul(GEN x, GEN y); GEN ZG_Z_mul(GEN x, GEN c); GEN ZG_add(GEN x, GEN y); GEN ZG_mul(GEN x, GEN y); GEN ZG_neg(GEN x); GEN ZG_normalize(GEN x); GEN ZG_sub(GEN x, GEN y); /* ZV.c */ void Flc_lincomb1_inplace(GEN X, GEN Y, ulong v, ulong q); GEN vecsmall_prod(GEN v); GEN QM_QC_mul(GEN x, GEN y); GEN QM_det(GEN x); GEN QM_ker(GEN M); GEN QM_mul(GEN x, GEN y); GEN QM_sqr(GEN x); void RgM_check_ZM(GEN A, const char *s); void RgV_check_ZV(GEN A, const char *s); GEN Z_ZC_sub(GEN a, GEN x); GEN ZV_zc_mul(GEN x, GEN y); GEN ZC_Q_mul(GEN A, GEN z); GEN ZC_Z_add(GEN x, GEN y); GEN ZC_Z_div(GEN x, GEN c); 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_ZV_mul(GEN x, GEN y); GEN ZC_divexactu(GEN x, ulong c); GEN ZC_add(GEN x, GEN y); GEN ZC_copy(GEN x); GEN ZC_hnfremdiv(GEN x, GEN y, GEN *Q); long ZC_is_ei(GEN x); GEN ZC_lincomb(GEN u, GEN v, GEN X, GEN Y); void ZC_lincomb1_inplace(GEN X, GEN Y, GEN v); void ZC_lincomb1_inplace_i(GEN X, GEN Y, GEN v, long n); GEN ZC_neg(GEN M); GEN ZC_reducemodlll(GEN x,GEN y); GEN ZC_reducemodmatrix(GEN v, GEN y); GEN ZC_sub(GEN x, GEN y); GEN ZC_z_mul(GEN X, long c); GEN ZM_Q_mul(GEN A, GEN z); GEN ZM_ZC_mul(GEN x, GEN y); GEN ZM_Z_div(GEN X, GEN c); GEN ZM_Z_divexact(GEN X, GEN c); GEN ZM_Z_mul(GEN X, GEN c); GEN ZM_add(GEN x, GEN y); GEN ZM_copy(GEN x); GEN ZM_det_triangular(GEN mat); GEN ZM_diag_mul(GEN m, GEN d); GEN ZM_divexactu(GEN x, ulong c); int ZM_equal(GEN A, GEN B); int ZM_equal0(GEN A); GEN ZM_hnfdivrem(GEN x, GEN y, GEN *Q); int ZM_ishnf(GEN x); int ZM_isdiagonal(GEN x); int ZM_isidentity(GEN x); int ZM_isscalar(GEN x, GEN s); long ZM_max_expi(GEN x); long ZM_max_lg(GEN x); GEN ZM_mul(GEN x, GEN y); GEN ZM_mul_diag(GEN m, GEN d); GEN ZM_multosym(GEN x, GEN y); GEN ZM_neg(GEN x); GEN ZM_nm_mul(GEN x, GEN y); GEN ZM_pow(GEN x, GEN n); GEN ZM_powu(GEN x, ulong n); GEN ZM_reducemodlll(GEN x,GEN y); GEN ZM_reducemodmatrix(GEN v, GEN y); GEN ZM_sqr(GEN x); GEN ZM_sub(GEN x, GEN y); GEN ZM_supnorm(GEN x); GEN ZM_to_Flm(GEN x, ulong p); GEN ZM_to_zm(GEN z); GEN ZM_transmul(GEN x, GEN y); GEN ZM_transmultosym(GEN x, GEN y); GEN ZMV_to_zmV(GEN z); void ZM_togglesign(GEN M); 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); int ZMrow_equal0(GEN V, long i); GEN ZV_ZM_mul(GEN x, GEN y); int ZV_abscmp(GEN x, GEN y); int ZV_cmp(GEN x, GEN y); GEN ZV_content(GEN x); GEN ZV_dotproduct(GEN x,GEN y); GEN ZV_dotsquare(GEN x); int ZV_equal(GEN V, GEN W); int ZV_equal0(GEN V); long ZV_max_expi(GEN x); long ZV_max_lg(GEN x); void ZV_neg_inplace(GEN M); GEN ZV_prod(GEN v); GEN ZV_sum(GEN v); GEN ZV_to_Flv(GEN x, ulong p); GEN ZV_to_nv(GEN z); void ZV_togglesign(GEN M); GEN gram_matrix(GEN M); GEN nm_Z_mul(GEN X, GEN c); GEN zm_mul(GEN x, GEN y); GEN zm_to_Flm(GEN z, ulong p); GEN zm_to_ZM(GEN z); GEN zm_zc_mul(GEN x, GEN y); GEN zmV_to_ZMV(GEN z); GEN zv_abs(GEN x); long zv_content(GEN x); long zv_dotproduct(GEN x, GEN y); int zv_equal(GEN V, GEN W); int zv_equal0(GEN V); GEN zv_neg(GEN x); GEN zv_neg_inplace(GEN M); long zv_prod(GEN v); GEN zv_prod_Z(GEN v); long zv_sum(GEN v); long zv_sumpart(GEN v, long n); GEN zv_to_Flv(GEN z, ulong p); GEN zv_z_mul(GEN v, long n); GEN zv_ZM_mul(GEN x, GEN y); int zvV_equal(GEN V, GEN W); /* ZX.c */ GEN Kronecker_to_ZXQX(GEN z, GEN T); GEN Kronecker_to_ZXX(GEN z, long N, long v); GEN QX_ZX_rem(GEN x, GEN y); GEN QX_mul(GEN x, GEN y); GEN QX_sqr(GEN x); GEN QXQM_mul(GEN x, GEN y, GEN T); GEN QXQM_sqr(GEN x, GEN T); GEN QXQX_QXQ_mul(GEN P, GEN U, GEN T); GEN QXQX_mul(GEN x, GEN y, GEN T); GEN QXQX_powers(GEN P, long n, GEN T); GEN QXQX_sqr(GEN x, GEN T); void RgX_check_QX(GEN x, const char *s); void RgX_check_ZX(GEN x, const char *s); void RgX_check_ZXX(GEN x, const char *s); GEN Z_ZX_sub(GEN x, GEN y); GEN ZX_Z_add(GEN y,GEN x); GEN ZX_Z_add_shallow(GEN y, GEN x); GEN ZX_Z_divexact(GEN y,GEN x); GEN ZX_Z_eval(GEN x, GEN y); 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_affine(GEN P, GEN a, GEN b); GEN ZX_copy(GEN x); GEN ZX_deriv(GEN x); GEN ZX_digits(GEN x, GEN T); GEN ZXV_ZX_fromdigits(GEN x, GEN T); GEN ZX_div_by_X_1(GEN a, GEN *r); GEN ZX_divuexact(GEN y, ulong x); int ZX_equal(GEN V, GEN W); GEN ZX_eval1(GEN x); long ZX_max_lg(GEN x); GEN ZX_mod_Xnm1(GEN T, ulong n); GEN ZX_mul(GEN x, GEN y); GEN ZX_mulspec(GEN a, GEN b, long na, long nb); GEN ZX_mulu(GEN y, ulong x); GEN ZX_neg(GEN x); GEN ZX_rem(GEN x, GEN y); GEN ZX_remi2n(GEN y, long n); GEN ZX_rescale2n(GEN P, long n); GEN ZX_rescale(GEN P, GEN h); GEN ZX_rescale_lt(GEN P); GEN ZX_shifti(GEN x, long n); 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 ZXC_to_FlxC(GEN x, ulong p, long vs); GEN ZXM_to_FlxM(GEN x, ulong p, long vs); GEN ZXQM_mul(GEN x, GEN y, GEN T); GEN ZXQM_sqr(GEN x, GEN T); GEN ZXQX_ZXQ_mul(GEN P, GEN U, GEN T); GEN ZXQX_sqr(GEN x, GEN T); GEN ZXQX_mul(GEN x, GEN y, GEN T); GEN ZXT_remi2n(GEN z, long n); GEN ZXV_Z_mul(GEN y, GEN x); GEN ZXV_dotproduct(GEN V, GEN W); int ZXV_equal(GEN V, GEN W); GEN ZXV_remi2n(GEN x, long n); GEN ZXX_Z_divexact(GEN y, GEN x); GEN ZXX_Z_mul(GEN y, GEN x); GEN ZXX_Z_add_shallow(GEN x, GEN y); GEN ZXX_evalx0(GEN y); long ZXX_max_lg(GEN x); GEN ZXX_mul_Kronecker(GEN x, GEN y, long n); GEN ZXX_renormalize(GEN x, long lx); GEN ZXX_sqr_Kronecker(GEN x, long n); GEN RgXX_to_Kronecker(GEN P, long n); GEN RgXX_to_Kronecker_spec(GEN P, long lP, long n); GEN ZXn_mul(GEN x, GEN y, long n); GEN ZXn_sqr(GEN x, long n); GEN scalar_ZX(GEN x, long v); GEN scalar_ZX_shallow(GEN x, long v); GEN zx_to_ZX(GEN z); GEN zx_z_divexact(GEN y, long x); /* algebras.c */ GEN alg_centralproj(GEN al, GEN z, long maps); GEN alg_complete(GEN rnf, GEN aut, GEN hi, GEN hf, long flag); GEN alg_csa_table(GEN nf, GEN mt, long v, long flag); GEN alg_cyclic(GEN rnf, GEN aut, GEN b, long flag); long alg_get_absdim(GEN al); GEN alg_get_abssplitting(GEN al); GEN alg_get_aut(GEN al); GEN algaut(GEN al); GEN alg_get_auts(GEN al); GEN alg_get_b(GEN al); GEN algb(GEN al); GEN algcenter(GEN al); GEN alg_get_center(GEN al); GEN alg_get_char(GEN al); GEN algchar(GEN al); long alg_get_degree(GEN al); long algdegree(GEN al); long alg_get_dim(GEN al); long algdim(GEN al, long abs); GEN alg_get_hasse_f(GEN al); GEN alghassef(GEN al); GEN alg_get_hasse_i(GEN al); GEN alghassei(GEN al); GEN alg_get_invbasis(GEN al); GEN alginvbasis(GEN al); GEN alg_get_multable(GEN al); GEN alg_get_basis(GEN al); GEN algbasis(GEN al); GEN alg_get_relmultable(GEN al); GEN algrelmultable(GEN al); GEN alg_get_splitpol(GEN al); GEN alg_get_splittingfield(GEN al); GEN algsplittingfield(GEN al); GEN alg_get_splittingbasis(GEN al); GEN alg_get_splittingbasisinv(GEN al); GEN alg_get_splittingdata(GEN al); GEN algsplittingdata(GEN al); GEN alg_get_tracebasis(GEN al); GEN alg_hasse(GEN nf, long n, GEN hi, GEN hf, long var, long flag); GEN alg_hilbert(GEN nf, GEN a, GEN b, long v, long flag); GEN alg_matrix(GEN nf, long n, long v, long flag); long alg_model(GEN al, GEN x); GEN alg_quotient(GEN al, GEN id, long maps); GEN algradical(GEN al); GEN algsimpledec(GEN al, long maps); GEN algsimpledec_ss(GEN al, long maps); GEN algsubalg(GEN al, GEN basis); long alg_type(GEN al); GEN algadd(GEN al, GEN x, GEN y); GEN algalgtobasis(GEN al, GEN x); GEN algbasistoalg(GEN al, GEN x); GEN algcharpoly(GEN al, GEN x, long v, long abs); GEN algdisc(GEN al); GEN algdivl(GEN al, GEN x, GEN y); GEN algdivr(GEN al, GEN x, GEN y); GEN alggroup(GEN gal, GEN p); GEN alggroupcenter(GEN gal, GEN p, GEN* ptr_conjclasses); GEN alghasse(GEN al, GEN pl); GEN alginit(GEN A, GEN B, long v, long flag); long algindex(GEN al, GEN pl); GEN alginv(GEN al, GEN x); int algisassociative(GEN mt0, GEN p); int algiscommutative(GEN al); int algisdivision(GEN al, GEN pl); int algisramified(GEN al, GEN pl); int algissemisimple(GEN al); int algissimple(GEN al, long ss); int algissplit(GEN al, GEN pl); int algisdivl(GEN al, GEN x, GEN y, GEN* ptz); int algisinv(GEN al, GEN x, GEN* ptix); GEN algmakeintegral(GEN mt0, long maps); GEN algmul(GEN al, GEN x, GEN y); GEN algmultable(GEN al); GEN alglat_get_primbasis(GEN lat); GEN alglat_get_scalar(GEN lat); GEN alglatadd(GEN al, GEN lat1, GEN lat2, GEN* ptinter); int alglatcontains(GEN al, GEN lat, GEN x, GEN* ptc); GEN alglatelement(GEN al, GEN lat, GEN c); GEN alglathnf(GEN al, GEN m, GEN d); GEN alglatindex(GEN al, GEN lat1, GEN lat2); GEN alglatinter(GEN al, GEN lat1, GEN lat2, GEN* ptsum); GEN alglatmul(GEN al, GEN lat1, GEN lat2); GEN alglatlefttransporter(GEN al, GEN lat1, GEN lat2); GEN alglatrighttransporter(GEN al, GEN lat1, GEN lat2); int alglatsubset(GEN al, GEN lat1, GEN lat2, GEN* ptindex); GEN algneg(GEN al, GEN x); GEN algnorm(GEN al, GEN x, long abs); GEN algpoleval(GEN al, GEN pol, GEN x); GEN algpow(GEN al, GEN x, GEN n); GEN algprimesubalg(GEN al); GEN algramifiedplaces(GEN al); GEN algrandom(GEN al, GEN b); GEN algsplit(GEN al, long v); GEN algtomatrix(GEN al, GEN x, long abs); GEN algsqr(GEN al, GEN x); GEN algsub(GEN al, GEN x, GEN y); GEN algtableinit(GEN mt, GEN p); GEN algtensor(GEN al1, GEN al2, long flag); GEN algtrace(GEN al, GEN x, long abs); long algtype(GEN al); GEN bnfgwgeneric(GEN bnf, GEN Lpr, GEN Ld, GEN pl, long var); void checkalg(GEN x); void checkhasse(GEN nf, GEN hi, GEN hf, long n); void checklat(GEN al, GEN lat); GEN conjclasses_algcenter(GEN cc, GEN p); GEN galoischardet(GEN gal, GEN ch, long o); GEN galoischarpoly(GEN gal, GEN ch, long o); GEN galoischartable(GEN gal); GEN nfgrunwaldwang(GEN nf0, GEN Lpr, GEN Ld, GEN pl, long var); GEN nfgwkummer(GEN nf, GEN Lpr, GEN Ld, GEN pl, long var); /* alglin1.c */ GEN F2Ms_colelim(GEN M, long nbrow); GEN F2m_image(GEN x); GEN F2m_indexrank(GEN x); GEN F2m_suppl(GEN x); GEN F2xqM_F2xqC_gauss(GEN a, GEN b, GEN T); GEN F2xqM_F2xqC_invimage(GEN a, GEN b, GEN T); GEN F2xqM_F2xqC_mul(GEN a, GEN b, GEN T); GEN F2xqM_deplin(GEN x, GEN T); GEN F2xqM_det(GEN a, GEN T); GEN F2xqM_gauss(GEN a, GEN b, GEN T); GEN F2xqM_ker(GEN x, GEN T); GEN F2xqM_image(GEN x, GEN T); GEN F2xqM_indexrank(GEN x, GEN T); GEN F2xqM_inv(GEN a, GEN T); GEN F2xqM_invimage(GEN a, GEN b, GEN T); GEN F2xqM_mul(GEN a, GEN b, GEN T); long F2xqM_rank(GEN x, GEN T); GEN F2xqM_suppl(GEN x, GEN T); GEN Flm_image(GEN x, ulong p); GEN Flm_indexrank(GEN x, ulong p); GEN Flm_suppl(GEN x, ulong p); GEN FlxqM_FlxqC_gauss(GEN a, GEN b, GEN T, ulong p); GEN FlxqM_FlxqC_invimage(GEN a, GEN b, GEN T, ulong p); GEN FlxqM_FlxqC_mul(GEN a, GEN b, GEN T, ulong p); GEN FlxqM_deplin(GEN x, GEN T, ulong p); GEN FlxqM_det(GEN a, GEN T, ulong p); GEN FlxqM_gauss(GEN a, GEN b, GEN T, ulong p); GEN FlxqM_ker(GEN x, GEN T, ulong p); GEN FlxqM_image(GEN x, GEN T, ulong p); GEN FlxqM_indexrank(GEN x, GEN T, ulong p); GEN FlxqM_inv(GEN x, GEN T, ulong p); GEN FlxqM_invimage(GEN a, GEN b, GEN T, ulong p); GEN FlxqM_mul(GEN a, GEN b, GEN T, ulong p); long FlxqM_rank(GEN x, GEN T, ulong p); GEN FlxqM_suppl(GEN x, GEN T, ulong p); GEN FpM_FpC_gauss(GEN a, GEN b, GEN p); GEN FpM_FpC_invimage(GEN m, GEN v, GEN p); GEN FpM_deplin(GEN x, GEN p); GEN FpM_det(GEN x, GEN p); GEN FpM_gauss(GEN a, GEN b, GEN p); GEN FpM_image(GEN x, GEN p); GEN FpM_indexrank(GEN x, GEN p); GEN FpM_intersect(GEN x, GEN y, GEN p); GEN FpM_intersect_i(GEN x, GEN y, GEN p); GEN FpM_inv(GEN x, GEN p); GEN FpM_invimage(GEN m, GEN v, GEN p); GEN FpM_ker(GEN x, GEN p); long FpM_rank(GEN x, GEN p); GEN FpM_suppl(GEN x, GEN p); GEN FqM_FqC_gauss(GEN a, GEN b, GEN T, GEN p); GEN FqM_FqC_invimage(GEN a, GEN b, GEN T, GEN p); GEN FqM_FqC_mul(GEN a, GEN b, GEN T, GEN p); GEN FqM_deplin(GEN x, GEN T, GEN p); GEN FqM_det(GEN x, GEN T, GEN p); GEN FqM_gauss(GEN a, GEN b, GEN T, GEN p); GEN FqM_ker(GEN x, GEN T, GEN p); GEN FqM_image(GEN x, GEN T, GEN p); GEN FqM_indexrank(GEN x, GEN T, GEN p); GEN FqM_inv(GEN x, GEN T, GEN p); GEN FqM_invimage(GEN a, GEN b, GEN T, GEN p); GEN FqM_mul(GEN a, GEN b, GEN T, GEN p); long FqM_rank(GEN a, GEN T, GEN p); GEN FqM_suppl(GEN x, GEN T, GEN p); GEN QM_image_shallow(GEN A); GEN QM_image(GEN A); GEN QM_gauss(GEN a, GEN b); GEN QM_gauss_i(GEN M, GEN B, long flag); GEN QM_indexrank(GEN x); GEN QM_inv(GEN M); long QM_rank(GEN x); GEN RgM_Fp_init(GEN a, GEN p, ulong *pp); GEN RgM_Hadamard(GEN a); GEN RgM_RgC_invimage(GEN A, GEN B); GEN RgM_diagonal(GEN m); GEN RgM_diagonal_shallow(GEN m); GEN RgM_div(GEN a, GEN b); GEN RgM_inv(GEN a); GEN RgM_inv_upper(GEN a); GEN RgM_invimage(GEN A, GEN B); GEN RgM_solve(GEN a, GEN b); GEN RgM_solve_realimag(GEN x, GEN y); void RgMs_structelim(GEN M, long nbrow, GEN A, GEN *p_col, GEN *p_lin); GEN ZM_det(GEN a); GEN ZM_detmult(GEN A); GEN ZM_gauss(GEN a, GEN b); GEN ZM_ker(GEN M); GEN ZM_imagecompl(GEN x); GEN ZM_indeximage(GEN x); GEN ZM_indexrank(GEN x); GEN ZM_inv(GEN M, GEN *den); GEN ZM_inv_ratlift(GEN M, GEN *pden); GEN ZM_pseudoinv(GEN M, GEN *pv, GEN *den); long ZM_rank(GEN x); GEN ZlM_gauss(GEN a, GEN b, ulong p, long e, GEN C); GEN closemodinvertible(GEN x, GEN y); GEN deplin(GEN x); GEN det(GEN a); GEN det0(GEN a,long flag); GEN det2(GEN a); GEN detint(GEN x); GEN eigen(GEN x, long prec); GEN gauss(GEN a, GEN b); GEN gaussmodulo(GEN M, GEN D, GEN Y); GEN gaussmodulo2(GEN M, GEN D, GEN Y); GEN gen_Gauss(GEN a, GEN b, void *E, const struct bb_field *ff); GEN gen_Gauss_pivot(GEN x, long *rr, void *E, const struct bb_field *ff); GEN gen_det(GEN a, void *E, const struct bb_field *ff); GEN gen_ker(GEN x, long deplin, void *E, const struct bb_field *ff); GEN gen_matcolinvimage(GEN a, GEN b, void *E, const struct bb_field *ff); GEN gen_matcolmul(GEN a, GEN b, void *E, const struct bb_field *ff); GEN gen_matinvimage(GEN a, GEN b, void *E, const struct bb_field *ff); GEN gen_matmul(GEN a, GEN b, void *E, const struct bb_field *ff); GEN image(GEN x); GEN image2(GEN x); GEN imagecompl(GEN x); GEN indexrank(GEN x); GEN inverseimage(GEN mat, GEN y); GEN ker(GEN x); GEN mateigen(GEN x, long flag, long prec); GEN matimage0(GEN x,long flag); GEN matker0(GEN x, long flag); long rank(GEN x); GEN reducemodinvertible(GEN x, GEN y); GEN reducemodlll(GEN x,GEN y); GEN split_realimag(GEN x, long r1, long r2); GEN suppl(GEN x); /* alglin2.c */ GEN Flm_charpoly(GEN x, ulong p); GEN Flm_hess(GEN x, ulong p); GEN FpM_charpoly(GEN x, GEN p); GEN FpM_hess(GEN x, GEN p); GEN Frobeniusform(GEN V, long n); GEN QM_minors_coprime(GEN x, GEN pp); GEN QM_ImZ(GEN x); GEN QM_ImZ_all(GEN x, GEN *U, long remove, long hnf); GEN QM_ImZ_hnf(GEN x); GEN QM_ImZ_hnfall(GEN x, GEN *U, long remove); GEN QM_ImQ(GEN x); GEN QM_ImQ_all(GEN x, GEN *U, long remove, long hnf); GEN QM_ImQ_hnf(GEN x); GEN QM_ImQ_hnfall(GEN x, GEN *U, long remove); GEN QM_charpoly_ZX(GEN M); GEN QM_charpoly_ZX_bound(GEN M, long bit); GEN RgM_Cholesky(GEN M, long prec); GEN ZM_charpoly(GEN x); GEN adj(GEN x); GEN adjsafe(GEN x); GEN caract(GEN x, long v); GEN caradj(GEN x, long v, GEN *py); GEN carberkowitz(GEN x, long v); GEN carhess(GEN x, long v); GEN charpoly(GEN x, long v); GEN charpoly0(GEN x, long v,long flag); GEN gnorm(GEN x); GEN gnorml1(GEN x,long prec); GEN gnorml1_fake(GEN x); GEN gnormlp(GEN x, GEN p, long prec); GEN gnorml2(GEN x); GEN gsupnorm(GEN x, long prec); void gsupnorm_aux(GEN x, GEN *m, GEN *msq, long prec); GEN gtrace(GEN x); GEN hess(GEN x); GEN intersect(GEN x, GEN y); GEN jacobi(GEN a, long prec); GEN matadjoint0(GEN x, long flag); GEN matcompanion(GEN x); GEN matrixqz0(GEN x, GEN pp); GEN minpoly(GEN x, long v); GEN qfcholesky(GEN a, long prec); GEN qfgaussred(GEN a); GEN qfgaussred_positive(GEN a); GEN qfgaussred0(GEN a, long flag); GEN qfgaussred2(GEN a); GEN qfsign(GEN a); /* alglin3.c */ GEN apply0(GEN f, GEN A); GEN diagonal(GEN x); GEN diagonal_shallow(GEN x); GEN extract0(GEN x, GEN l1, GEN l2); GEN fold0(GEN f, GEN A); GEN genapply(void *E, GEN (*f)(void *E, GEN x), GEN A); GEN genfold(void *E, GEN (*f)(void *E, GEN x, GEN y), GEN A); GEN genindexselect(void *E, long (*f)(void *E, GEN x), GEN A); GEN genselect(void *E, long (*f)(void *E, GEN x), GEN A); GEN gtomat(GEN x); GEN gtrans(GEN x); GEN matmuldiagonal(GEN x, GEN d); GEN matmultodiagonal(GEN x, GEN y); GEN matslice0(GEN A, long x1, long x2, long y1, long y2); GEN parapply(GEN V, GEN C); void parfor(GEN a, GEN b, GEN code, void *E, long call(void*, GEN, GEN)); void parfor_init(parfor_t *T, GEN a, GEN b, GEN code); GEN parfor_next(parfor_t *T); void parfor_stop(parfor_t *T); void parforeach(GEN x, GEN code, void *E, long call(void*, GEN, GEN)); void parforeach_init(parforeach_t *T, GEN x, GEN code); GEN parforeach_next(parforeach_t *T); void parforeach_stop(parforeach_t *T); void parforprime(GEN a, GEN b, GEN code, void *E, long call(void*, GEN, GEN)); void parforprime_init(parforprime_t *T, GEN a, GEN b, GEN code); GEN parforprime_next(parforprime_t *T); void parforprime_stop(parforprime_t *T); void parforprimestep(GEN a, GEN b, GEN q, GEN code, void *E, long call(void*, GEN, GEN)); void parforprimestep_init(parforprime_t *T, GEN a, GEN b, GEN q, GEN code); void parforstep(GEN a, GEN b, GEN s, GEN code, void *E, long call(void*, GEN, GEN)); void parforstep_init(parforstep_t *T, GEN a, GEN b, GEN s, GEN code); GEN parforstep_next(parforstep_t *T); void parforstep_stop(parforstep_t *T); void parforvec(GEN x, GEN code, long flag, void *E, long call(void*, GEN, GEN)); void parforvec_init(parforvec_t *T, GEN x, GEN code, long flag); GEN parforvec_next(parforvec_t *T); void parforvec_stop(parforvec_t *T); GEN parselect(GEN C, GEN D, long flag); GEN select0(GEN A, GEN f, long flag); GEN shallowextract(GEN x, GEN L); GEN shallowmatextract(GEN x, GEN l1, GEN l2); GEN shallowtrans(GEN x); GEN vecapply(void *E, GEN (*f)(void* E, GEN x), GEN x); GEN veccatapply(void *E, GEN (*f)(void* E, GEN x), GEN x); GEN veccatselapply(void *Epred, long (*pred)(void* E, GEN x), void *Efun, GEN (*fun)(void* E, GEN x), GEN A); GEN vecrange(GEN a, GEN b); GEN vecrangess(long a, long b); GEN vecselapply(void *Epred, long (*pred)(void* E, GEN x), void *Efun, GEN (*fun)(void* E, GEN x), GEN A); GEN vecselect(void *E, long (*f)(void* E, GEN x), GEN A); GEN vecslice0(GEN A, long y1, long y2); GEN vecsum(GEN v); GEN zv_diagonal(GEN x); /* anal.c */ void addhelp(const char *e, char *s); GEN arity0(GEN C); void alias0(const char *s, const char *old); GEN compile_str(const char *s); long delete_var(void); long fetch_user_var(const char *s); long fetch_var(void); long fetch_var_higher(void); GEN fetch_var_value(long vx, GEN t); GEN gp_read_str(const char *t); GEN gp_read_str_bitprec(const char *s, long bitprec); GEN gp_read_str_prec(const char *s, long prec); entree* install(void *f, const char *name, const char *code); entree* is_entry(const char *s); void kill0(const char *e); void pari_var_close(void); void pari_var_init(void); long pari_var_next(void); long pari_var_next_temp(void); long pari_var_create(entree *ep); void name_var(long n, const char *s); GEN readseq(char *t); GEN* safegel(GEN x, long l); long* safeel(GEN x, long l); GEN* safelistel(GEN x, long l); GEN* safegcoeff(GEN x, long a, long b); GEN strtoi(const char *s); GEN strtor(const char *s, long prec); GEN varhigher(const char *s, long v); GEN varlower(const char *s, long v); /* aprcl.c */ GEN divisorslenstra(GEN N, GEN r, GEN s); long isprimeAPRCL(GEN N); /* Qfb.c */ GEN Qfb0(GEN x, GEN y, GEN z); 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); long cornacchia2_sqrt(GEN d, GEN p, GEN b, 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 L); GEN primeform(GEN x, GEN p); GEN primeform_u(GEN x, ulong p); GEN qfb_1(GEN x); GEN qfbcomp(GEN x, GEN y); GEN qfbcomp_i(GEN x, GEN y); GEN qfbcompraw(GEN x, GEN y); GEN qfbcompraw_i(GEN x, GEN y); GEN qfbcornacchia(GEN d, GEN p); GEN qfbpow(GEN x, GEN n); GEN qfbpow_i(GEN x, GEN n); GEN qfbpowraw(GEN x, long n); GEN qfbpows(GEN x, long n); GEN qfbred(GEN x); GEN qfbred_i(GEN x); GEN qfbred0(GEN x, long flag, GEN isqrtD, GEN sqrtD); GEN qfbredsl2(GEN q, GEN isD); GEN qfbsolve(GEN Q, GEN n, long flag); GEN qfbsqr(GEN x); GEN qfbsqr_i(GEN x); GEN qfisolvep(GEN Q, GEN p); GEN qfr3_comp(GEN x, GEN y, struct qfr_data *S); GEN qfr3_compraw(GEN x, GEN y); 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 D); GEN qfr5_comp(GEN x, GEN y, struct qfr_data *S); GEN qfr5_compraw(GEN x, GEN y); 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 D, GEN d0); void qfr_data_init(GEN D, long prec, struct qfr_data *S); GEN qfr_to_qfr5(GEN x, long prec); GEN qfrsolvep(GEN Q, GEN p); GEN quadgen(GEN x); GEN quadgen0(GEN x, long v); GEN quadpoly(GEN x); GEN quadpoly_i(GEN D); GEN quadpoly0(GEN x, long v); /* arith1.c */ ulong Fl_2gener_pre(ulong p, ulong pi); ulong Fl_2gener_pre_i(ulong ns, ulong p, ulong pi); ulong Fl_log(ulong a, ulong g, ulong ord, ulong p); ulong Fl_log_pre(ulong a, ulong g, ulong ord, ulong p, ulong pi); ulong Fl_order(ulong a, ulong o, ulong p); GEN Fl_powers(ulong x, long n, ulong p); GEN Fl_powers_pre(ulong x, long n, ulong p, ulong pi); ulong Fl_powu(ulong x, ulong n, ulong p); ulong Fl_powu_pre(ulong x, ulong n, ulong p, ulong pi); ulong Fl_sqrt(ulong a, ulong p); ulong Fl_sqrt_pre(ulong a, ulong p, ulong pi); ulong Fl_sqrt_pre_i(ulong a, ulong s2, ulong p, ulong pi); ulong Fl_sqrtl(ulong a, ulong l, ulong p); ulong Fl_sqrtl_pre(ulong a, ulong l, ulong p, ulong pi); ulong Fl_sqrtn(ulong a, long n, ulong p, ulong *zetan); ulong Fl_sqrtn_pre(ulong a, long n, ulong p, ulong pi, ulong *zetan); GEN Fp_2gener(GEN p); GEN Fp_2gener_i(GEN ns, GEN p); GEN Fp_factored_order(GEN a, GEN o, GEN p); int Fp_ispower(GEN x, GEN K, GEN p); GEN Fp_log(GEN a, GEN g, GEN ord, GEN p); GEN Fp_order(GEN a, GEN o, GEN p); GEN Fp_pow(GEN a, GEN n, GEN m); GEN Fp_pow_init(GEN x, GEN n, long k, GEN p); GEN Fp_pow_table(GEN R, GEN n, GEN p); GEN Fp_powers(GEN x, long n, GEN p); GEN Fp_pows(GEN A, long k, GEN N); GEN Fp_powu(GEN x, ulong k, GEN p); GEN Fp_sqrt(GEN a, GEN p); GEN Fp_sqrt_i(GEN a, GEN y, GEN p); GEN Fp_sqrtn(GEN a, GEN n, GEN p, GEN *zetan); GEN FpV_prod(GEN V, GEN p); GEN Z_ZV_mod(GEN P, GEN xa); GEN Z_ZV_mod_tree(GEN P, GEN xa, GEN T); GEN Z_chinese(GEN a, GEN b, GEN A, GEN B); GEN Z_chinese_all(GEN a, GEN b, GEN A, GEN B, GEN *pC); GEN Z_chinese_coprime(GEN a, GEN b, GEN A, GEN B, GEN C); GEN Z_chinese_post(GEN a, GEN b, GEN C, GEN U, GEN d); void Z_chinese_pre(GEN A, GEN B, GEN *pC, GEN *pU, GEN *pd); GEN Z_factor_listP(GEN N, GEN L); GEN Z_nv_mod(GEN P, GEN xa); GEN ZM_nv_mod_tree(GEN M, GEN xa, GEN T); GEN ZV_allpnqn(GEN x); GEN ZV_chinese(GEN A, GEN P, GEN *pt_mod); GEN ZV_chinese_tree(GEN A, GEN P, GEN T, GEN R); GEN ZV_chinesetree(GEN P, GEN T); GEN ZV_nv_mod_tree(GEN V, GEN xa, GEN T); GEN ZV_producttree(GEN xa); GEN ZX_nv_mod_tree(GEN P, GEN xa, GEN T); GEN ZXC_nv_mod_tree(GEN P, GEN xa, GEN T, long w); GEN ZXM_nv_mod_tree(GEN M, GEN xa, GEN T, long w); GEN ZXX_nv_mod_tree(GEN P, GEN xa, GEN T, long w); GEN Zideallog(GEN bid, GEN x); GEN bestappr(GEN x, GEN k); GEN bestapprPade(GEN x, long B); GEN bestapprPade0(GEN x, long B, long C); GEN chinese(GEN x, GEN y); GEN chinese1(GEN x); GEN chinese1_coprime_Z(GEN x); GEN contfrac0(GEN x, GEN b, long flag); GEN contfracpnqn(GEN x, long n); GEN fibo(long n); GEN gboundcf(GEN x, long k); GEN gcf(GEN x); GEN gcf2(GEN b, GEN x); const struct bb_field *get_Fp_field(void **E, GEN p); long hilbert(GEN x, GEN y, GEN p); long hilbertii(GEN x, GEN y, GEN p); long istotient(GEN n, GEN *px); long krois(GEN x, long y); long kroiu(GEN x, ulong y); long kronecker(GEN x, GEN y); long krosi(long s, GEN x); long kross(long x, long y); long kroui(ulong x, GEN y); long krouu(ulong x, ulong y); GEN lcmii(GEN a, GEN b); GEN Fp_invgen(GEN x, GEN N, GEN *pd); long logint0(GEN B, GEN y, GEN *ptq); long logintall(GEN B, GEN y, GEN *ptq); ulong factorial_Fl(long n, ulong p); GEN factorial_Fp(long n, GEN p); GEN mpfact(long n); GEN mpprimorial(long n); GEN muls_interval(long a, long b); GEN mulu_interval(ulong a, ulong b); GEN mulu_interval_step(ulong a, ulong b, ulong step); GEN ncV_chinese_center(GEN A, GEN P, GEN *pt_mod); GEN ncV_chinese_center_tree(GEN A, GEN P, GEN T, GEN R); GEN nmV_chinese_center(GEN A, GEN P, GEN *pt_mod); GEN nmV_chinese_center_tree(GEN A, GEN P, GEN T, GEN R); ulong nonsquare_Fl(ulong p); GEN nxCV_chinese_center(GEN A, GEN P, GEN *pt_mod); GEN nxCV_chinese_center_tree(GEN A, GEN P, GEN T, GEN R); GEN nxMV_chinese_center(GEN A, GEN P, GEN *pt_mod); GEN nxV_chinese_center(GEN A, GEN P, GEN *pt_mod); GEN nxV_chinese_center_tree(GEN A, GEN P, GEN T, GEN R); GEN ZV_chinese_center(GEN A, GEN P, GEN *pt_mod); GEN odd_prime_divisors(GEN q); ulong pgener_Fl(ulong p); ulong pgener_Fl_local(ulong p, GEN L); GEN pgener_Fp(GEN p); GEN pgener_Fp_local(GEN p, GEN L); ulong pgener_Zl(ulong p); GEN pgener_Zp(GEN p); GEN pnqn(GEN x); GEN ramanujantau(GEN n, long ell); ulong rootsof1_Fl(ulong n, ulong p); GEN rootsof1_Fp(GEN n, GEN p); GEN rootsof1u_Fp(ulong n, GEN p); ulong u_chinese_coprime(ulong a, ulong b, ulong A, ulong B, ulong C); GEN znlog(GEN x, GEN g, GEN o); GEN znorder(GEN x, GEN o); GEN znprimroot(GEN m); GEN znstar(GEN x); GEN znstar0(GEN N, long flag); /* arith2.c */ int RgV_is_ZVpos(GEN v); int RgV_is_ZVnon0(GEN v); int RgV_is_prV(GEN v); long Z_issquarefree_fact(GEN F); GEN Z_lsmoothen(GEN N, GEN L, GEN *pP, GEN *pe); GEN Z_smoothen(GEN N, GEN L, GEN *pP, GEN *pe); long bigomega(GEN n); long bigomegau(ulong n); GEN boundfact(GEN n, ulong lim); GEN check_arith_pos(GEN n, const char *f); GEN check_arith_non0(GEN n, const char *f); GEN check_arith_all(GEN n, const char *f); GEN clean_Z_factor(GEN f); GEN core(GEN n); GEN coredisc2_fact(GEN fa, long s, GEN *pP, GEN *pE); ulong coredisc2u_fact(GEN fa, long s, GEN *pP, GEN *pE); 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); long corediscs(long D, ulong *f); GEN divisors(GEN n); GEN divisors_factored(GEN N); GEN divisors0(GEN N, long flag); GEN divisorsu(ulong n); GEN divisorsu_moebius(GEN P); GEN divisorsu_fact(GEN fa); GEN divisorsu_fact_factored(GEN fa); GEN eulerphi(GEN n); ulong eulerphiu(ulong n); ulong eulerphiu_fact(GEN f); GEN factor_pn_1(GEN p, ulong n); GEN factor_pn_1_limit(GEN p, long n, ulong lim); GEN factoru_pow(ulong n); GEN fuse_Z_factor(GEN f, GEN B); int is_Z_factor(GEN f); int is_Z_factornon0(GEN f); int is_Z_factorpos(GEN f); int is_nf_factor(GEN F); int is_nf_extfactor(GEN F); long issquarefree(GEN x); GEN numdiv(GEN n); long numdivu(long N); long numdivu_fact(GEN fa); long omega(GEN n); long omegau(ulong n); GEN sumdiv(GEN n); GEN sumdivk(GEN n,long k); long uissquarefree(ulong n); long uissquarefree_fact(GEN f); GEN usumdiv_fact(GEN f); GEN usumdivk_fact(GEN f, ulong k); /* base1.c */ GEN FpX_FpC_nfpoleval(GEN nf, GEN pol, GEN a, GEN p); GEN embed_T2(GEN x, long r1); GEN embednorm_T2(GEN x, long r1); GEN embed_norm(GEN x, long r1); int check_ZKmodule_i(GEN M); void check_ZKmodule(GEN x, const char *s); void checkbid(GEN bid); GEN checkbid_i(GEN bid); GEN checkbnf(GEN bnf); GEN checkbnf_i(GEN bnf); void checkbnr(GEN bnr); GEN checkbnr_i(GEN bnr); void checkabgrp(GEN v); void checksqmat(GEN x, long N); GEN checknf(GEN nf); GEN checknf_i(GEN nf); GEN checknfelt_mod(GEN nf, GEN x, const char *s); void checkprid(GEN bid); int checkprid_i(GEN x); void checkrnf(GEN rnf); int checkrnf_i(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 idealfrobenius_aut(GEN nf, GEN gal, GEN pr, GEN aut); GEN idealramfrobenius(GEN nf, GEN gal, GEN pr, GEN ram); GEN idealramfrobenius_aut(GEN nf, GEN gal, GEN pr, GEN ram, GEN aut); GEN idealramgroups(GEN nf, GEN gal, GEN pr); GEN idealramgroups_aut(GEN nf, GEN gal, GEN pr, GEN aut); GEN nf_get_allroots(GEN nf); long nf_get_prec(GEN x); GEN nfmaxord_to_nf(nfmaxord_t *T, GEN ro, long prec); GEN nfcertify(GEN x); GEN nfgaloismatrix(GEN nf, GEN s); GEN nfgaloismatrixapply(GEN nf, GEN M, GEN x); GEN nfgaloispermtobasis(GEN nf, GEN gal); void nfinit_basic(nfmaxord_t *T, GEN x); GEN nfinit_complete(nfmaxord_t *T, long flag, long prec); GEN nfinit(GEN x, long prec); GEN nfinit0(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 nfisincl0(GEN fa, GEN fb, long flag); 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); GEN nfsplitting(GEN T, GEN D); GEN nfsplitting0(GEN T, GEN D, long flag); long nftyp(GEN x); GEN polredord(GEN x); GEN polred(GEN x); GEN polred0(GEN x, long flag, GEN fa); GEN polred2(GEN x); GEN polredabs(GEN x); GEN polredabs0(GEN x, long flag); GEN polredabs2(GEN x); GEN polredabsall(GEN x, long flun); GEN polredbest(GEN x, long flag); GEN poltomonic(GEN T, GEN *L); GEN rnfpolredabs(GEN nf, GEN pol, long flag); GEN rnfpolredbest(GEN nf, GEN R, long flag); GEN rnfnewprec_shallow(GEN rnf, long prec); GEN rnfnewprec(GEN rnf, long prec); GEN smallpolred(GEN x); GEN smallpolred2(GEN x); GEN tschirnhaus(GEN x); GEN ZX_Q_mul(GEN A, GEN z); 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); GEN ZXX_Q_mul(GEN A, GEN z); /* base2.c */ GEN Fq_to_nf(GEN x, GEN modpr); GEN FqM_to_nfM(GEN z, GEN modpr); GEN FqV_to_nfV(GEN z, GEN modpr); GEN FqX_to_nfX(GEN x, GEN modpr); GEN Rg_nffix(const char *f, GEN T, GEN c, int lift); GEN RgV_nffix(const char *f, GEN T, GEN P, int lift); GEN RgX_nffix(const char *s, GEN nf, GEN x, int lift); GEN ZX_composedsum(GEN A, GEN B); GEN ZX_compositum(GEN A, GEN B, long *lambda); long ZpX_disc_val(GEN f, GEN p); GEN ZpX_gcd(GEN f1,GEN f2,GEN p, GEN pm); GEN ZpX_monic_factor(GEN f, GEN p, long prec); GEN ZpX_primedec(GEN T, GEN p); GEN ZpX_reduced_resultant(GEN x, GEN y, GEN p, GEN pm); GEN ZpX_reduced_resultant_fast(GEN f, GEN g, GEN p, long M); long ZpX_resultant_val(GEN f, GEN g, GEN p, long M); void checkmodpr(GEN modpr); GEN compositum(GEN P, GEN Q); GEN compositum2(GEN P, GEN Q); GEN nfdisc(GEN x); GEN get_modpr(GEN x); GEN indexpartial(GEN P, GEN DP); GEN modpr_genFq(GEN modpr); GEN nf_to_Fq_init(GEN nf, GEN *pr, GEN *T, GEN *p); 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 nfX_to_monic(GEN nf, GEN T, GEN *pL); GEN nfbasis(GEN x, GEN *y); GEN nfcompositum(GEN nf, GEN A, GEN B, long flag); GEN nfdiscfactors(GEN x); void nfmaxord(nfmaxord_t *S, GEN T, long flag); GEN nfmodpr(GEN nf, GEN x, GEN pr); GEN nfmodprinit(GEN nf, GEN pr); GEN nfmodprinit0(GEN nf, GEN pr, long v); GEN nfmodprlift(GEN nf, GEN x, 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 idealprimedec_galois(GEN nf, GEN p); GEN idealprimedec_degrees(GEN nf, GEN p); GEN idealprimedec_kummer(GEN nf,GEN pol,long e,GEN p); GEN idealprimedec_limit_f(GEN nf, GEN p, long f); GEN idealprimedec_limit_norm(GEN nf, GEN p, GEN B); GEN poldiscfactors(GEN T, long flag); GEN rnfbasis(GEN bnf, GEN order); GEN rnfdedekind(GEN nf, GEN T, GEN pr, long flag); GEN rnfdet(GEN nf, GEN order); GEN rnfdisc_factored(GEN nf, GEN pol, GEN *pd); GEN rnfdiscf(GEN nf, GEN pol); GEN rnfequation(GEN nf, GEN pol); GEN rnfequation0(GEN nf, GEN pol, long flall); GEN rnfequation2(GEN nf, GEN pol); GEN nf_pV_to_prV(GEN nf, GEN P); GEN nf_rnfeq(GEN nf, GEN R); GEN nf_rnfeqsimple(GEN nf, GEN R); GEN rnfequationall(GEN A, GEN B, long *pk, GEN *pLPRS); GEN rnfhnfbasis(GEN bnf, GEN order); long rnfisfree(GEN bnf, GEN order); GEN rnflllgram(GEN nf, GEN pol, GEN order,long prec); GEN rnfpolred(GEN nf, GEN pol, long prec); GEN rnfpseudobasis(GEN nf, GEN pol); GEN rnfsimplifybasis(GEN bnf, GEN order); GEN rnfsteinitz(GEN nf, GEN order); long factorial_lval(ulong n, ulong p); GEN zk_to_Fq_init(GEN nf, GEN *pr, GEN *T, GEN *p); GEN zk_to_Fq(GEN x, GEN modpr); GEN QXQV_to_FpM(GEN basis, GEN T, GEN p); GEN zkmodprinit(GEN nf, GEN pr); /* base3.c */ GEN Idealstar(GEN nf, GEN x,long flun); GEN Idealstarmod(GEN nf, GEN ideal, long flag, GEN MOD); GEN Idealstarprk(GEN nf, GEN pr, long k, long flag); GEN RgC_to_nfC(GEN nf,GEN x); GEN RgM_RgX_mul(GEN A, GEN x); GEN RgM_to_nfM(GEN nf,GEN x); GEN RgX_to_nfX(GEN nf,GEN pol); long ZC_nfval(GEN x, GEN P); long ZC_nfvalrem(GEN x, GEN P, GEN *t); int ZC_prdvd(GEN x, GEN P); GEN ZM_ZX_mul(GEN A, GEN x); GEN ZV_snf_gcd(GEN x, GEN mod); GEN algtobasis(GEN nf, GEN x); GEN basistoalg(GEN nf, GEN x); GEN ei_multable(GEN nf, long i); const struct bb_field *get_nf_field(void **E, GEN nf); GEN famat_nfvalrem(GEN nf, GEN x, GEN pr, GEN *py); GEN gpnfvalrem(GEN nf, GEN x, GEN pr, GEN *py); GEN idealfactorback(GEN nf, GEN L, GEN e, int red); GEN ideallist(GEN nf,long bound); GEN ideallist0(GEN nf,long bound, long flag); GEN gideallist(GEN nf, GEN bound, long flag); GEN ideallistarch(GEN nf, GEN list, GEN arch); GEN ideallog(GEN nf,GEN x,GEN bid); GEN ideallogmod(GEN nf,GEN x,GEN bid, GEN mod); GEN ideallog_units(GEN bnf, GEN bid); GEN ideallog_units0(GEN bnf, GEN bid, GEN MOD); GEN idealprincipalunits(GEN nf, GEN pr, long e); GEN idealstar0(GEN nf, GEN x,long flag); GEN idealstarmod(GEN nf, GEN ideal, long flag, GEN MOD); GEN indices_to_vec01(GEN archp, long r); GEN matalgtobasis(GEN nf, GEN x); GEN matbasistoalg(GEN nf, GEN x); GEN multable(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 nf_cxlog(GEN nf, GEN x, long prec); GEN nfV_cxlog(GEN nf, GEN x, long prec); GEN nfadd(GEN nf, GEN x, GEN y); int nfchecksigns(GEN nf, GEN x, GEN pl); GEN nfdiv(GEN nf, GEN x, GEN y); GEN nfdiveuc(GEN nf, GEN a, GEN b); GEN nfdivrem(GEN nf, GEN a, GEN b); GEN nfembed(GEN nf, GEN x, long k); GEN nfeltembed(GEN nf, GEN x, GEN ind0, long prec); GEN nfeltembed_i(GEN *pnf, GEN x, GEN ind0, long prec); GEN nfeltsign(GEN nf, GEN x, GEN ind0); GEN nffactorback(GEN nf, GEN L, GEN e); GEN nfinv(GEN nf, GEN x); GEN nfinvmodideal(GEN nf, GEN x, GEN ideal); long nfissquare(GEN nf, GEN z, GEN *px); long nfispower(GEN nf, GEN z, long n, GEN *px); GEN nflogembed(GEN nf, GEN x, GEN *emb, long prec); GEN nfM_det(GEN nf, GEN M); GEN nfM_inv(GEN nf, GEN M); GEN nfM_ker(GEN nf, GEN M); GEN nfM_mul(GEN nf, GEN A, GEN B); GEN nfM_nfC_mul(GEN nf, GEN A, GEN B); 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 nfpolsturm(GEN nf, GEN f, GEN ind0); 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 nfsub(GEN nf, GEN x, GEN y); GEN nftrace(GEN nf, GEN x); long nfval(GEN nf, GEN x, GEN vp); long nfvalrem(GEN nf, GEN x, GEN pr, GEN *py); GEN polmod_nffix(const char *f, GEN rnf, GEN x,int lift); GEN polmod_nffix2(const char *f, GEN T, GEN R, GEN x, int lift); GEN pr_basis_perm(GEN nf, GEN pr); int pr_equal(GEN P, GEN Q); GEN rnfalgtobasis(GEN rnf, GEN x); GEN rnfbasistoalg(GEN rnf, GEN x); GEN rnfeltnorm(GEN rnf, GEN x); GEN rnfelttrace(GEN rnf, GEN x); GEN set_sign_mod_divisor(GEN nf, GEN x, GEN y, GEN sarch); GEN tablemul(GEN M, 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 vec01_to_indices(GEN arch); GEN vecsmall01_to_indices(GEN v); GEN zk_inv(GEN nf, GEN x); GEN zk_multable(GEN nf, GEN x); GEN zk_scalar_or_multable(GEN, GEN x); GEN zkchinese(GEN zkc, GEN x, GEN y); GEN zkchinese1(GEN zkc, GEN x); GEN zkchineseinit(GEN nf, GEN A, GEN B, GEN AB); GEN zkmultable_capZ(GEN mx); GEN zkmultable_inv(GEN mx); /* base4.c */ ulong Fl_invgen(ulong x, ulong p, ulong *pg); GEN Q_to_famat(GEN x); GEN RM_round_maxrank(GEN G); GEN ZM_famat_limit(GEN fa, GEN limit); GEN ZV_cba(GEN v); GEN ZV_cba_extend(GEN P, GEN b); GEN Z_cba(GEN a, GEN b); GEN Z_ppgle(GEN a, GEN b); GEN Z_ppio(GEN a, GEN b); GEN Z_ppo(GEN x, GEN f); GEN Z_to_famat(GEN x); GEN famatV_factorback(GEN v, GEN e); GEN famatV_zv_factorback(GEN v, GEN e); GEN famat_Z_gcd(GEN M, GEN n); GEN famat_div(GEN f, GEN g); GEN famat_div_shallow(GEN f, GEN g); GEN famat_idealfactor(GEN nf, GEN x); GEN famat_inv(GEN f); GEN famat_inv_shallow(GEN f); GEN famat_makecoprime(GEN nf, GEN g, GEN e, GEN pr, GEN prk, GEN EX); GEN famat_mul(GEN f, GEN g); GEN famat_mul_shallow(GEN f, GEN g); GEN famat_mulpow_shallow(GEN f, GEN g, GEN e); GEN famat_mulpows_shallow(GEN f, GEN g, long e); GEN famat_pow(GEN f, GEN n); GEN famat_pow_shallow(GEN f, GEN n); GEN famat_pows_shallow(GEN f, long n); GEN famat_reduce(GEN fa); GEN famat_remove_trivial(GEN fa); GEN famat_sqr(GEN f); GEN famat_to_nf(GEN nf, GEN f); GEN famat_to_nf_moddivisor(GEN nf, GEN g, GEN e, GEN bid); GEN famat_to_nf_modideal_coprime(GEN nf, GEN g, GEN e, GEN id, GEN EX); GEN famatsmall_reduce(GEN fa); GEN gpidealfactor(GEN nf, GEN x, GEN lim); GEN gpidealval(GEN nf, GEN ix, GEN P); GEN idealHNF_Z_factor(GEN x, GEN *pvN, GEN *pvZ); GEN idealHNF_Z_factor_i(GEN x, GEN f, GEN *pvN, GEN *pvZ); GEN idealHNF_inv(GEN nf, GEN id); GEN idealHNF_inv_Z(GEN nf, GEN id); GEN idealHNF_mul(GEN nf, GEN ix, GEN iy); GEN idealadd(GEN nf, GEN x, GEN y); GEN idealaddmultoone(GEN nf, GEN list); GEN idealaddtoone(GEN nf, GEN x, GEN y); GEN idealaddtoone0(GEN nf, GEN x, GEN y); GEN idealaddtoone_i(GEN nf, GEN x, GEN y); GEN idealaddtoone_raw(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 idealdown(GEN nf, GEN x); GEN idealfactor(GEN nf, GEN x); GEN idealfactor_limit(GEN nf, GEN x, ulong lim); GEN idealfactor_partial(GEN nf, GEN x, GEN L); GEN idealhnf(GEN nf, GEN x); GEN idealhnf0(GEN nf, GEN a, GEN b); GEN idealhnf_principal(GEN nf, GEN x); GEN idealhnf_shallow(GEN nf, GEN x); GEN idealhnf_two(GEN nf, GEN vp); GEN idealintersect(GEN nf, GEN x, GEN y); GEN idealinv(GEN nf, GEN ix); GEN idealismaximal(GEN nf, GEN x); long idealispower(GEN nf, GEN A, long n, GEN *pB); GEN idealmin(GEN nf,GEN ix,GEN vdir); GEN idealmul(GEN nf, GEN ix, GEN iy); GEN idealmul0(GEN nf, GEN ix, GEN iy, long flag); GEN idealmulpowprime(GEN nf, GEN x, GEN vp, GEN n); GEN idealmulred(GEN nf, GEN ix, GEN iy); GEN idealnorm(GEN nf, GEN x); GEN idealnumden(GEN nf, GEN x); GEN idealpow(GEN nf, GEN ix, GEN n); GEN idealpow0(GEN nf, GEN ix, GEN n, long flag); GEN idealpowred(GEN nf, GEN ix, GEN n); GEN idealpows(GEN nf, GEN ideal, long iexp); GEN idealprod(GEN nf, GEN id); GEN idealprodprime(GEN nf, GEN L); long idealprodval(GEN nf, GEN id, GEN pr); GEN idealpseudomin(GEN id, GEN G); GEN idealpseudomin_nonscalar(GEN id, GEN G); GEN idealpseudominvec(GEN id, GEN G); GEN idealpseudored(GEN id, GEN G); GEN idealred0(GEN nf, GEN id,GEN vdir); GEN idealred_elt(GEN nf, GEN id); GEN idealredmodpower(GEN nf, GEN x, ulong k, ulong B); GEN idealsqr(GEN nf, GEN x); GEN idealtwoelt(GEN nf, GEN ix); GEN idealtwoelt0(GEN nf, GEN ix, GEN a); GEN idealtwoelt2(GEN nf, GEN x, GEN a); long idealtyp(GEN *ideal, GEN *arch); long idealval(GEN nf,GEN ix,GEN vp); long isideal(GEN nf,GEN x); GEN matreduce(GEN fa); GEN nfC_multable_mul(GEN v, GEN x); GEN nfC_nf_mul(GEN nf, GEN v, GEN x); GEN nf_get_Gtwist(GEN nf, GEN vdir); GEN nf_get_Gtwist1(GEN nf, long i); GEN nf_to_Fp_coprime(GEN nf, GEN x, GEN modpr); GEN nfdetint(GEN nf,GEN pseudo); GEN nfdivmodpr(GEN nf, GEN x, GEN y, GEN modpr); GEN nfhnf(GEN nf, GEN x); GEN nfhnf0(GEN nf, GEN x, long flag); GEN nfhnfmod(GEN nf, GEN x, GEN d); GEN nfkermodpr(GEN nf, GEN x, GEN modpr); GEN nfmulmodpr(GEN nf, GEN x, GEN y, GEN modpr); GEN nfpowmodpr(GEN nf, GEN x, GEN k, GEN modpr); GEN nfreduce(GEN nf, GEN x, GEN ideal); GEN nfsnf(GEN nf, GEN x); GEN nfsnf0(GEN nf, GEN x, long flag); GEN nfsolvemodpr(GEN nf, GEN a, GEN b, GEN modpr); GEN nfweilheight(GEN nf, GEN v, long prec); GEN prV_lcm_capZ(GEN L); GEN prV_primes(GEN v); GEN pr_hnf(GEN nf, GEN pr); GEN pr_inv(GEN pr); GEN pr_inv_p(GEN pr); GEN pr_uniformizer(GEN pr, GEN F); GEN sunits_makecoprime(GEN X, GEN pr, GEN prk); GEN to_famat(GEN x, GEN y); GEN to_famat_shallow(GEN x, GEN y); ulong u_ppo(ulong x, ulong f); GEN vecdiv(GEN x, GEN y); GEN vecinv(GEN x); GEN vecmul(GEN x, GEN y); GEN vecsqr(GEN x); GEN vecpow(GEN x, GEN n); GEN vecsqr(GEN x); GEN zkC_multable_mul(GEN v, GEN x); /* base5.c */ GEN eltreltoabs(GEN rnfeq, GEN x); GEN eltabstorel(GEN eq, GEN P); GEN eltabstorel_lift(GEN rnfeq, GEN P); GEN nf_nfzk(GEN nf, GEN rnfeq); GEN rnf_build_nfabs(GEN rnf, long prec); GEN rnf_zkabs(GEN rnf); GEN nfeltup(GEN nf, GEN x, GEN zknf); void rnfcomplete(GEN rnf); GEN rnfeltabstorel(GEN rnf, GEN x); GEN rnfeltdown(GEN rnf, GEN x); GEN rnfeltdown0(GEN rnf, GEN x, long flag); GEN rnfeltreltoabs(GEN rnf, GEN x); GEN rnfeltup(GEN rnf, GEN x); GEN rnfeltup0(GEN rnf, GEN x, long flag); GEN rnfidealabstorel(GEN rnf, GEN x); GEN rnfidealdown(GEN rnf, GEN x); GEN rnfidealfactor(GEN rnf, GEN x); GEN rnfidealhnf(GEN rnf, GEN x); GEN rnfidealmul(GEN rnf,GEN x,GEN y); GEN rnfidealnormabs(GEN rnf, GEN x); GEN rnfidealnormrel(GEN rnf, GEN x); GEN rnfidealprimedec(GEN rnf, GEN pr); GEN rnfidealreltoabs(GEN rnf, GEN x); GEN rnfidealreltoabs0(GEN rnf, GEN x, long flag); GEN rnfidealtwoelement(GEN rnf,GEN x); GEN rnfidealup(GEN rnf, GEN x); GEN rnfidealup0(GEN rnf,GEN x, long flag); GEN rnfinit(GEN nf,GEN pol); GEN rnfinit0(GEN nf,GEN pol,long flag); /* bb_group.c */ GEN get_arith_ZZM(GEN o); GEN get_arith_Z(GEN o); GEN gen_PH_log(GEN a, GEN g, GEN ord, void *E, const struct bb_group *grp); GEN gen_Shanks_init(GEN g, long n, void *E, const struct bb_group *grp); GEN gen_Shanks(GEN T, GEN x, ulong N, void *E, const struct bb_group *grp); GEN gen_Shanks_sqrtn(GEN a, GEN n, GEN q, GEN *zetan, void *E, const struct bb_group *grp); GEN gen_gener(GEN o, void *E, const struct bb_group *grp); GEN gen_ellgens(GEN d1, GEN d2, GEN m, void *E, const struct bb_group *grp, GEN pairorder(void *E, GEN P, GEN Q, GEN m, GEN F)); GEN gen_ellgroup(GEN N, GEN F, GEN *pt_m, void *E, const struct bb_group *grp, GEN pairorder(void *E, GEN P, GEN Q, GEN m, GEN F)); GEN gen_factored_order(GEN a, GEN o, void *E, const struct bb_group *grp); GEN gen_order(GEN x, GEN o, void *E, const struct bb_group *grp); GEN gen_select_order(GEN o, void *E, const struct bb_group *grp); GEN gen_plog(GEN x,GEN g0,GEN q, void *E, const struct bb_group *grp); GEN gen_pow(GEN x, GEN n, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN)); GEN gen_pow_fold(GEN x, GEN n, void *E, GEN (*sqr)(void*,GEN), GEN (*msqr)(void*,GEN)); GEN gen_pow_fold_i(GEN x, GEN n, void *E, GEN (*sqr)(void*,GEN), GEN (*msqr)(void*,GEN)); GEN gen_pow_i(GEN x, GEN n, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN)); GEN gen_pow_init(GEN x, GEN n, long k, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN)); GEN gen_pow_table(GEN R, GEN n, void *E, GEN (*one)(void*), GEN (*mul)(void*,GEN,GEN)); GEN gen_powers(GEN x, long l, int use_sqr, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN), GEN (*one)(void*)); GEN gen_powu(GEN x, ulong n, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN)); GEN gen_powu_fold(GEN x, ulong n, void *E, GEN (*sqr)(void*,GEN), GEN (*msqr)(void*,GEN)); GEN gen_powu_fold_i(GEN x, ulong n, void *E, GEN (*sqr)(void*,GEN), GEN (*msqr)(void*,GEN)); GEN gen_powu_i(GEN x, ulong n, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN)); GEN gen_product(GEN x, void *data, GEN (*mul)(void*,GEN,GEN)); /* bb_hnf.c */ GEN matdetmod(GEN A, GEN d); GEN matimagemod(GEN A, GEN d, GEN* U); GEN matinvmod(GEN A, GEN d); GEN matkermod(GEN A, GEN d, GEN* im); GEN matsolvemod(GEN M, GEN D, GEN Y, long flag); /* bern.c */ GEN bernfrac(long n); GEN bernpol(long k, long v); GEN bernpol_eval(long k, GEN x); GEN bernreal(long n, long prec); GEN bernvec(long nomb); void constbern(long n); GEN eulerfrac(long k); GEN eulerpol(long k, long v); GEN eulerreal(long n, long prec); GEN eulervec(long n); GEN harmonic(ulong n); GEN harmonic0(ulong n, GEN k); /* bibli1.c */ int QR_init(GEN x, GEN *pB, GEN *pQ, GEN *pL, long prec); GEN R_from_QR(GEN x, long prec); GEN RgM_Babai(GEN B, GEN t); int RgM_QR_init(GEN x, GEN *pB, GEN *pQ, GEN *pL, long prec); GEN RgM_gram_schmidt(GEN e, GEN *ptB); GEN algdep(GEN x, long n); GEN algdep0(GEN x, long n, long bit); GEN bestapprnf(GEN x, GEN T, GEN rootsT, long prec); void forqfvec(void *E, long (*fun)(void *, GEN, GEN, double), GEN a, GEN BORNE); void forqfvec0(GEN a, GEN BORNE, GEN code); void forqfvec1(void *E, long (*fun)(void *, GEN), GEN a, GEN BORNE); GEN gaussred_from_QR(GEN x, long prec); GEN lindep(GEN x); GEN lindep_Xadic(GEN x); GEN lindep_bit(GEN x, long bit); GEN lindep_padic(GEN x); GEN lindep0(GEN x, long flag); GEN lindep2(GEN x, long bit); GEN lindepfull_bit(GEN x, long bit); GEN mathouseholder(GEN Q, GEN v); GEN matqr(GEN x, long flag, long prec); GEN minim(GEN a, GEN borne, GEN stockmax); GEN minim_raw(GEN a, GEN borne, GEN stockmax); GEN minim_zm(GEN a, GEN borne, GEN stockmax); GEN minim2(GEN a, GEN borne, GEN stockmax); GEN qfcvp0(GEN a, GEN target, GEN borne, GEN stockmax,long flag); GEN qfminim0(GEN a, GEN borne, GEN stockmax,long flag, long prec); GEN qfperfection(GEN a); GEN qfrep0(GEN a, GEN borne, long flag); GEN seralgdep(GEN s, long p, long r); GEN serdiffdep(GEN s, long p, long r); GEN vandermondeinverse(GEN L, GEN T, GEN den, GEN prep); GEN vandermondeinverseinit(GEN L); GEN zncoppersmith(GEN P0, GEN N, GEN X, GEN B); /* bibli2.c */ GEN QXQ_reverse(GEN a, GEN T); GEN vec_equiv(GEN F); GEN RgV_polint(GEN X, GEN Y, long v); GEN vec_reduce(GEN v, GEN *pE); GEN RgXQ_reverse(GEN a, GEN T); GEN ZC_union_shallow(GEN x, GEN y); GEN ZM_merge_factor(GEN A, GEN B); GEN ZV_indexsort(GEN L); long ZV_search(GEN x, GEN y); GEN ZV_sort(GEN L); void ZV_sort_inplace(GEN L); GEN ZV_sort_shallow(GEN L); GEN ZV_sort_uniq(GEN L); GEN ZV_sort_uniq_shallow(GEN L); GEN ZV_union_shallow(GEN x, GEN y); GEN binomial(GEN x, long k); GEN binomial0(GEN x, GEN k); GEN binomialuu(ulong n, ulong k); int cmp_Flx(GEN x, GEN y); int cmp_RgX(GEN x, GEN y); 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_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 eulerianpol(long N, long v); GEN gprec_wensure(GEN x, long pr); 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, 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_shallow(GEN x, void *E, int (*cmp)(void*,GEN,GEN)); GEN gen_sort_uniq(GEN x, void *E, int (*cmp)(void*,GEN,GEN)); long getstack(void); long gettime(void); long getabstime(void); GEN getwalltime(void); GEN gprec(GEN x, long l); GEN gprec_wtrunc(GEN x, long pr); GEN gprec_w(GEN x, long pr); GEN gtoset(GEN x); GEN indexlexsort(GEN x); GEN indexsort(GEN x); GEN indexvecsort(GEN x, GEN k); GEN laplace(GEN x); GEN lexsort(GEN x); GEN mathilbert(long n); GEN matqpascal(long n, GEN q); GEN merge_factor(GEN fx, GEN fy, void *data, int (*cmp)(void *,GEN,GEN)); GEN merge_sort_uniq(GEN x, GEN y, void *data, int (*cmp)(void *,GEN,GEN)); GEN modreverse(GEN x); GEN polhermite(long n, long v); GEN polhermite_eval0(long n, GEN x, long flag); GEN polhermite_eval(long n, GEN x); GEN pollaguerre(long n, GEN a, long v); GEN pollaguerre_eval(long n, GEN a, GEN x); GEN pollaguerre_eval0(long n, GEN a, GEN x, long flag); GEN pollegendre(long n, long v); GEN pollegendre_reduced(long n, long v); GEN pollegendre_eval(long n, GEN x); GEN pollegendre_eval0(long n, GEN x, long flag); GEN polint(GEN xa, GEN ya, GEN x, GEN *pe); GEN polint_i(GEN X, GEN Y, GEN t, long *pe); GEN polintspec(GEN xa, GEN ya, GEN x, long n, long *pe); GEN polchebyshev(long n, long kind, long v); GEN polchebyshev_eval(long n, long kind, GEN x); GEN polchebyshev1(long n, long v); GEN polchebyshev2(long n, long v); GEN polrecip(GEN x); GEN setbinop(GEN f, GEN x, GEN y); GEN setdelta(GEN x, GEN y); GEN setintersect(GEN x, GEN y); long setisset(GEN x); GEN setminus(GEN x, GEN y); long setsearch(GEN x, GEN y, long flag); GEN setunion(GEN x, GEN y); GEN setunion_i(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 vecbinomial(long n); long vecsearch(GEN v, GEN x, GEN k); GEN vecsort(GEN x, GEN k); GEN vecsort0(GEN x, GEN k, long flag); long zv_search(GEN x, long y); /* bit.c */ GEN bits_to_int(GEN x, long l); ulong bits_to_u(GEN v, long l); GEN binaire(GEN x); GEN binary_2k(GEN x, long k); GEN binary_2k_nv(GEN x, long k); GEN binary_zv(GEN x); long bittest(GEN x, long n); GEN fromdigits_2k(GEN x, long k); GEN gbitand(GEN x, GEN y); GEN gbitneg(GEN x, long n); GEN gbitnegimply(GEN x, GEN y); GEN gbitor(GEN x, GEN y); GEN gbittest(GEN x, long n); GEN gbitxor(GEN x, GEN y); long hammingl(ulong w); long hammingweight(GEN n); GEN ibitand(GEN x, GEN y); GEN ibitnegimply(GEN x, GEN y); GEN ibitor(GEN x, GEN y); GEN ibitxor(GEN x, GEN y); GEN nv_fromdigits_2k(GEN x, long k); /* bnflog.c */ GEN bnflogef(GEN bnf, GEN pr); GEN bnflog(GEN bnf, GEN l); GEN bnflogdegree(GEN bnf, GEN A, GEN ell); long nfislocalpower(GEN nf, GEN pr, GEN a, GEN n); long rnfislocalcyclo(GEN rnf); /* bnfunits.c */ GEN bnfisunit(GEN bnf, GEN x); GEN bnfissunit(GEN bnf,GEN suni,GEN x); GEN bnfsunit(GEN bnf,GEN s,long PREC); GEN bnfunits(GEN bnf, GEN S); GEN bnfisunit0(GEN bnf, GEN x, GEN U); GEN sunits_mod_units(GEN bnf, GEN S); /* buch1.c */ GEN Buchquad(GEN D, double c1, double c2, long prec); GEN quadclassno(GEN x); long quadclassnos(long x); GEN quadclassunit0(GEN x, long flag,GEN data, long prec); /* buch2.c */ GEN Buchall(GEN P, long flag, long prec); GEN Buchall_param(GEN P, double bach, double bach2, long nbrelpid, long flun, long prec); GEN bnf_build_cheapfu(GEN bnf); GEN bnf_build_cycgen(GEN bnf); GEN bnf_build_matalpha(GEN bnf); GEN bnf_build_units(GEN bnf); GEN bnf_compactfu(GEN bnf); GEN bnf_compactfu_mat(GEN bnf); GEN bnf_has_fu(GEN bnf); GEN bnfinit0(GEN P,long flag,GEN data,long prec); GEN bnfisprincipal0(GEN bnf, GEN x,long flall); GEN bnfnewprec(GEN nf, long prec); GEN bnfnewprec_shallow(GEN nf, long prec); void bnftestprimes(GEN bnf, GEN bound); GEN bnrnewprec(GEN bnr, long prec); GEN bnrnewprec_shallow(GEN bnr, long prec); 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 isprincipal(GEN bnf, GEN x); GEN nf_cxlog_normalize(GEN nf, GEN x, long prec); GEN nfcyclotomicunits(GEN nf, GEN zu); GEN nfsign_units(GEN bnf, GEN archp, int add_zu); GEN nfsign_tu(GEN bnf, GEN archp); GEN nfsign_fu(GEN bnf, GEN archp); GEN signunits(GEN bnf); /* buch3.c */ GEN Hermite_bound(long n, long prec); void bnr_subgroup_sanitize(GEN *pbnr, GEN *pH); void bnr_char_sanitize(GEN *pbnr, GEN *pchi); GEN ABC_to_bnr(GEN A, GEN B, GEN C, GEN *H, int gen); GEN Buchray(GEN bnf, GEN module, long flag); GEN Buchraymod(GEN bnf, GEN f, long flag, GEN MOD); GEN bnrautmatrix(GEN bnr, GEN aut); GEN bnr_subgroup_check(GEN bnr, GEN H, GEN *pdeg); GEN bnrchar(GEN bnr, GEN g, GEN v); GEN bnrchar_primitive(GEN bnr, GEN chi, GEN bnrc); GEN bnrclassno(GEN bnf,GEN ideal); GEN bnrclassno0(GEN A,GEN B,GEN C); GEN bnrclassnolist(GEN bnf,GEN listes); GEN bnrchar_primitive_raw(GEN bnr, GEN bnrc, GEN chi); GEN bnrconductor_factored(GEN bnr, GEN H); GEN bnrconductor_raw(GEN bnr, GEN H); GEN bnrconductormod(GEN bnr, GEN H0, GEN MOD); GEN bnrconductor0(GEN A, GEN B, GEN C, long flag); GEN bnrconductor(GEN bnr, GEN H0, long flag); GEN bnrconductor_i(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 bnrgaloismatrix(GEN bnr, GEN aut); GEN bnrgaloisapply(GEN bnr, GEN mat, GEN x); GEN bnrinit0(GEN bnf,GEN ideal,long flag); GEN bnrinitmod(GEN bnf, GEN ideal, long flag, GEN MOD); long bnrisconductor0(GEN A, GEN B, GEN C); long bnrisconductor(GEN bnr, GEN H); long bnrisgalois(GEN bnr, GEN M, GEN H); GEN bnrisprincipalmod(GEN bnf, GEN x, GEN mod, long flag); GEN bnrisprincipal(GEN bnf, GEN x,long flag); GEN bnrmap(GEN A, GEN B); GEN bnrsurjection(GEN bnr1, GEN bnr2); GEN bnfnarrow(GEN bnf); long bnfcertify(GEN bnf); long bnfcertify0(GEN bnf, long flag); GEN bnrcompositum(GEN fH1, GEN fH2); GEN decodemodule(GEN nf, GEN fa); GEN discrayabslist(GEN bnf,GEN listes); GEN discrayabslistarch(GEN bnf, GEN arch, ulong bound); GEN idealmoddivisor(GEN bnr, GEN x); GEN isprincipalray(GEN bnf, GEN x); GEN isprincipalraygen(GEN bnf, GEN x); GEN nf_deg1_prime(GEN nf); GEN nfarchstar(GEN nf,GEN x,GEN arch); GEN rnfconductor(GEN bnf, GEN polrel); GEN rnfconductor0(GEN bnf, GEN T, long flag); 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 R, int galois); /* char.c */ GEN coprimes_zv(ulong N); int char_check(GEN cyc, GEN chi); GEN charconj(GEN cyc, GEN chi); GEN charconj0(GEN cyc, GEN chi); GEN chardiv(GEN x, GEN a, GEN b); GEN chardiv0(GEN x, GEN a, GEN b); GEN chareval(GEN G, GEN chi, GEN n, GEN z); GEN chargalois(GEN G, GEN ORD); GEN charker(GEN cyc, GEN chi); GEN charker0(GEN cyc, GEN chi); GEN charmul(GEN x, GEN a, GEN b); GEN charmul0(GEN x, GEN a, GEN b); GEN charorder(GEN cyc, GEN x); GEN charorder0(GEN x, GEN chi); GEN charpow(GEN cyc, GEN a, GEN N); GEN charpow0(GEN x, GEN a, GEN N); GEN char_denormalize(GEN cyc, GEN D, GEN chic); GEN char_normalize(GEN chi, GEN ncyc); GEN char_simplify(GEN D, GEN C); int checkznstar_i(GEN G); GEN cyc_normalize(GEN c); GEN ncharvecexpo(GEN G, GEN nchi); GEN znchar(GEN D); GEN znchar_quad(GEN G, GEN D); int zncharcheck(GEN G, GEN chi); GEN zncharconductor(GEN G, GEN chi); GEN zncharconj(GEN G, GEN chi); GEN znchardecompose(GEN G, GEN chi, GEN Q); GEN znchardiv(GEN G, GEN a, GEN b); GEN znchareval(GEN G, GEN chi, GEN n, GEN z); GEN zncharinduce(GEN G, GEN chi, GEN N); long zncharisodd(GEN G, GEN chi); GEN zncharker(GEN G, GEN chi); GEN zncharmul(GEN G, GEN a, GEN b); GEN zncharorder(GEN G, GEN chi); GEN zncharpow(GEN G, GEN a, GEN n); GEN znchartokronecker(GEN G, GEN chi, long flag); GEN znchartoprimitive(GEN G, GEN chi); int znconrey_check(GEN cyc, GEN chi); GEN znconrey_normalized(GEN G, GEN chi); GEN znconreychar(GEN bid, GEN m); GEN znconreyfromchar_normalized(GEN bid, GEN chi); GEN znconreyconductor(GEN bid, GEN co, GEN *pm); GEN znconreyexp(GEN bid, GEN x); GEN znconreyfromchar(GEN bid, GEN chi); GEN znconreylog(GEN bid, GEN x); GEN znconreylog_normalize(GEN G, GEN m); GEN znlog0(GEN h, GEN g, GEN o); long zv_cyc_minimal(GEN cyc, GEN g, GEN coprime); long zv_cyc_minimize(GEN cyc, GEN g, GEN coprime); /* compile.c */ GEN closure_deriv(GEN G); GEN closure_derivn(GEN G, long k); 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 gconcat(GEN x, GEN y); GEN gconcat1(GEN x); GEN matconcat(GEN v); GEN shallowconcat(GEN x, GEN y); GEN shallowconcat1(GEN x); GEN shallowmatconcat(GEN v); GEN vconcat(GEN A, GEN B); /* default.c */ enum { d_SILENT = 0, d_ACKNOWLEDGE, d_INITRC, d_RETURN }; GEN default0(const char *a, const char *b); long getrealprecision(void); entree *pari_is_default(const char *s); GEN sd_TeXstyle(const char *v, long flag); GEN sd_colors(const char *v, long flag); GEN sd_compatible(const char *v, long flag); 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_factorlimit(const char *v, long flag); GEN sd_format(const char *v, long flag); GEN sd_histsize(const char *v, long flag); GEN sd_log(const char *v, long flag); GEN sd_logfile(const char *v, long flag); GEN sd_nbthreads(const char *v, long flag); GEN sd_new_galois_format(const char *v, long flag); GEN sd_output(const char *v, long flag); GEN sd_parisize(const char *v, long flag); GEN sd_parisizemax(const char *v, long flag); GEN sd_path(const char *v, long flag); GEN sd_plothsizes(const char *v, long flag); GEN sd_prettyprinter(const char *v, long flag); GEN sd_primelimit(const char *v, long flag); GEN sd_realbitprecision(const char *v, long flag); GEN sd_realprecision(const char *v, long flag); GEN sd_secure(const char *v, long flag); GEN sd_seriesprecision(const char *v, long flag); GEN sd_simplify(const char *v, long flag); GEN sd_sopath(char *v, int flag); GEN sd_strictargs(const char *v, long flag); GEN sd_strictmatch(const char *v, long flag); GEN sd_string(const char *v, long flag, const char *s, char **f); GEN sd_threadsize(const char *v, long flag); GEN sd_threadsizemax(const char *v, long flag); GEN sd_intarray(const char *v, long flag, GEN *pz, const char *s); GEN sd_toggle(const char *v, long flag, const char *s, int *ptn); GEN sd_ulong(const char *v, long flag, const char *s, ulong *ptn, ulong Min, ulong Max, const char **msg); GEN setdefault(const char *s, const char *v, long flag); long setrealprecision(long n, long *prec); /* digits.c */ GEN digits(GEN N, GEN B); GEN fromdigits(GEN x, GEN B); GEN fromdigitsu(GEN x, GEN B); GEN gen_digits(GEN x, GEN B, long n, void *E, struct bb_ring *r, GEN (*div)(void *E, GEN x, GEN y, GEN *r)); GEN gen_fromdigits(GEN x, GEN B, void *E, struct bb_ring *r); GEN sumdigits(GEN n); GEN sumdigits0(GEN n, GEN B); ulong sumdigitsu(ulong n); /* ecpp.c */ GEN ecpp(GEN N); GEN ecpp0(GEN N, long stopat); GEN ecppexport(GEN cert, long flag); long ecppisvalid(GEN cert); long isprimeECPP(GEN N); /* gplib.c */ GEN sd_breakloop(const char *v, long flag); GEN sd_echo(const char *v, long flag); GEN sd_graphcolormap(const char *v, long flag); GEN sd_graphcolors(const char *v, long flag); GEN sd_help(const char *v, long flag); GEN sd_histfile(const char *v, long flag); GEN sd_lines(const char *v, long flag); GEN sd_linewrap(const char *v, long flag); GEN sd_prompt(const char *v, long flag); GEN sd_prompt_cont(const char *v, long flag); GEN sd_psfile(const char *v, long flag); GEN sd_readline(const char *v, long flag); GEN sd_recover(const char *v, long flag); GEN sd_timer(const char *v, long flag); void pari_hit_return(void); void gp_display_hist(long n); void str_display_hist(pari_str *S, long n); void gp_load_gprc(void); int gp_meta(const char *buf, int ismain); const char **gphelp_keyword_list(void); void pari_breakpoint(void); void pari_center(const char *s); long pari_community(void); void pari_print_version(void); const char *gp_format_time(long delay); const char *gp_format_prompt(const char *p); void pari_alarm(long s); GEN gp_alarm(long s, GEN code); GEN gp_input(void); void gp_allocatemem(GEN z); int gp_handle_exception(long numerr); void gp_alarm_handler(int sig); void gp_sigint_fun(void); enum { h_REGULAR=0, h_LONG=1, h_APROPOS=2, h_RL=4 }; void gp_help(const char *s, long flag); void gp_echo_and_log(const char *prompt, const char *s); void print_fun_list(char **list, long nbli); GEN strtime(long t); /* dirichlet.c */ GEN direuler(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, GEN c); GEN dirpowers(long n, GEN x, long prec); GEN dirpowerssum(ulong N, GEN s, long both, long prec); GEN dirpowerssumfun(ulong N, GEN s, void *E, GEN (*f)(void *,ulong,long), long both, long prec); GEN pardirpowerssumfun(GEN f, ulong N, GEN s, long both, long prec); GEN pardirpowerssum(ulong N, GEN s, long prec); GEN pardirpowerssum0(GEN N, GEN s, GEN f, long both, long prec); GEN vecpowuu(long N, ulong B); GEN vecpowug(long N, GEN B, long prec); /* ellanal.c */ GEN ellanalyticrank(GEN e, GEN eps, long prec); GEN ellanal_globalred_all(GEN e, GEN *N, GEN *cb, GEN *tam); GEN ellheegner(GEN e); GEN ellL1(GEN E, long r, long prec); /* elldata.c */ GEN ellconvertname(GEN s); GEN elldatagenerators(GEN E); GEN ellidentify(GEN E); GEN ellsearch(GEN A); GEN ellsearchcurve(GEN name); void forell(void *E, long call(void*, GEN), long a, long b, long flag); /* ellfromeqn.c */ GEN ellfromeqn(GEN s); /* elliptic.c */ enum { t_ELL_Rg = 0, t_ELL_Q, t_ELL_Qp, t_ELL_Fp, t_ELL_Fq, t_ELL_NF }; GEN akell(GEN e, GEN n); GEN bilhell(GEN e, GEN z1, GEN z2, long prec); void checkell(GEN e); void checkell_Fq(GEN e); void checkell_Q(GEN e); void checkell_Qp(GEN e); void checkellisog(GEN v); void checkellpt(GEN z); void checkell5(GEN e); GEN cxredsl2(GEN t, GEN *U); GEN cxredsl2_i(GEN z, GEN *pU, GEN *czd); GEN ec_2divpol_evalx(GEN E, GEN x); GEN ec_3divpol_evalx(GEN E, GEN x); GEN ec_bmodel(GEN e, long v); GEN ec_f_evalx(GEN E, GEN x); GEN ec_h_evalx(GEN e, GEN x); GEN ec_dFdx_evalQ(GEN E, GEN Q); GEN ec_dFdy_evalQ(GEN E, GEN Q); GEN ec_dmFdy_evalQ(GEN e, GEN Q); GEN ec_half_deriv_2divpol(GEN E, long vx); GEN ec_half_deriv_2divpol_evalx(GEN E, GEN x); GEN ec_phi2(GEN e, long v); int ell_is_integral(GEN E); long ellQ_get_CM(GEN e); GEN ellQ_get_N(GEN e); void ellQ_get_Nfa(GEN e, GEN *N, GEN *faN); GEN ellQp_Tate_uniformization(GEN E, long prec); GEN ellQp_AGM(GEN E, long prec); GEN ellQp_u(GEN E, long prec); GEN ellQp_u2(GEN E, long prec); GEN ellQp_q(GEN E, long prec); GEN ellQp_ab(GEN E, long prec); GEN ellQp_L(GEN E, long prec); GEN ellQp_root(GEN E, long prec); GEN ellQtwist_bsdperiod(GEN E, long s); GEN ellR_area(GEN E, long prec); GEN ellR_ab(GEN E, long prec); GEN ellR_eta(GEN E, long prec); GEN ellR_omega(GEN x, long prec); GEN ellR_roots(GEN E, long prec); GEN elladd(GEN e, GEN z1, GEN z2); GEN ellan(GEN e, long n); GEN ellanQ_zv(GEN e, long n); GEN ellanal_globalred(GEN e, GEN *gr); GEN ellap(GEN e, GEN p); long ellap_CM_fast(GEN E, ulong p, long CM); GEN ellbasechar(GEN E); GEN ellbsd(GEN e, long prec); GEN ellcard(GEN E, GEN p); GEN ellchangecurve(GEN e, GEN ch); GEN ellchangeinvert(GEN w); GEN ellchangepoint(GEN x, GEN ch); GEN ellchangepointinv(GEN x, GEN ch); GEN elldivpol(GEN e, long n, long v); GEN elleisnum(GEN om, long k, long flag, long prec); GEN elleta(GEN om, long prec); GEN elleulerf(GEN e, GEN p); GEN ellff_get_card(GEN E); GEN ellff_get_gens(GEN E); GEN ellff_get_group(GEN E); GEN ellff_get_o(GEN x); GEN ellff_get_p(GEN E); GEN ellff_get_m(GEN E); GEN ellff_get_D(GEN E); GEN ellfromj(GEN j); GEN ellgenerators(GEN E); GEN ellglobalred(GEN e1); GEN ellgroup(GEN E, GEN p); GEN ellgroup0(GEN E, GEN p, long flag); GEN ellheight0(GEN e, GEN a, GEN b, long prec); GEN ellheight(GEN e, GEN a, long prec); GEN ellheightmatrix(GEN E, GEN x, long n); GEN ellheightoo(GEN e, GEN z, long prec); GEN ellinit(GEN x, GEN p, long prec); GEN ellintegralmodel(GEN e, GEN *pv); GEN ellintegralmodel_i(GEN e, GEN *pv); long elliscm(GEN e); GEN ellisisom(GEN e, GEN f); GEN ellisoncurve(GEN e, GEN z); GEN ellisotree(GEN e); int ellissupersingular(GEN x, GEN p); int elljissupersingular(GEN x); GEN elllseries(GEN e, GEN s, GEN A, long prec); GEN elllocalred(GEN e, GEN p1); GEN elllog(GEN e, GEN a, GEN g, GEN o); GEN ellminimaldisc(GEN E); GEN ellminimalmodel(GEN E, GEN *ptv); GEN ellminimaltwist(GEN e); GEN ellminimaltwist0(GEN e, long fl); GEN ellminimaltwistcond(GEN e); GEN ellmul(GEN e, GEN z, GEN n); GEN ellnf_vecarea(GEN E, long prec); GEN ellnf_veceta(GEN E, long prec); GEN ellnf_vecomega(GEN E, long prec); GEN ellneg(GEN e, GEN z); GEN ellorder(GEN e, GEN p, GEN o); long ellorder_Q(GEN E, GEN P); GEN ellordinate(GEN e, GEN x, long prec); GEN ellpadicheight0(GEN e, GEN p, long n, GEN P, GEN Q); GEN ellpadicheightmatrix(GEN e, GEN p, long n, GEN P); GEN ellperiods(GEN w, long flag, long prec); GEN ellrandom(GEN e); long ellrootno(GEN e, GEN p); long ellrootno_global(GEN e); GEN ellsaturation(GEN E, GEN P, long B, long prec); GEN ellsea(GEN E, long smallfact); GEN ellsigma(GEN om, GEN z, long flag, long prec); GEN ellsub(GEN e, GEN z1, GEN z2); GEN ellsupersingularj(GEN a); GEN elltamagawa(GEN e); GEN elltaniyama(GEN e, long prec); GEN elltatepairing(GEN E, GEN t, GEN s, GEN m); GEN elltors(GEN e); GEN elltors0(GEN e, long flag); GEN elltors_psylow(GEN e, ulong p); GEN elltrace(GEN e, GEN P); GEN elltwist(GEN E, GEN D); GEN ellweilpairing(GEN E, GEN t, GEN s, GEN m); GEN ellwp(GEN w, GEN z, long prec); GEN ellwp0(GEN w, GEN z, long flag, long prec); GEN ellwpseries(GEN e, long v, long PRECDL); GEN ellxn(GEN e, long n, long v); GEN ellzeta(GEN om, GEN z, long prec); int oncurve(GEN e, GEN z); GEN orderell(GEN e, GEN p); GEN pointell(GEN e, GEN z, long prec); GEN point_to_a4a6(GEN E, GEN P, GEN p, GEN *pa4); GEN point_to_a4a6_Fl(GEN E, GEN P, ulong p, ulong *pa4); GEN zell(GEN e, GEN z, long prec); /* ellpadic.c */ GEN Qp_agm2_sequence(GEN a1, GEN b1); void Qp_ascending_Landen(GEN AB, GEN *ptx, GEN *pty); void Qp_descending_Landen(GEN AB, GEN *ptx, GEN *pty); GEN ellformaldifferential(GEN e, long n, long v); GEN ellformalexp(GEN e, long n, long v); GEN ellformallog(GEN e, long n, long v); GEN ellformalpoint(GEN e, long n, long v); GEN ellformalw(GEN e, long n, long v); GEN ellnonsingularmultiple(GEN e, GEN P); GEN ellpadicL(GEN E, GEN p, long n, GEN s, long r, GEN D); GEN ellpadicbsd(GEN E, GEN p, long n, GEN D); GEN ellpadicfrobenius(GEN E, ulong p, long n); GEN ellpadicheight(GEN e, GEN p, long n, GEN P); GEN ellpadiclog(GEN E, GEN p, long n, GEN P); GEN ellpadicregulator(GEN E, GEN p, long n, GEN S); GEN ellpadics2(GEN E, GEN p, long n); /* ellrank.c*/ GEN ell2cover(GEN ell, long prec); GEN ellrank(GEN ell, long effort, GEN help, long prec); GEN ellrankinit(GEN ell, long prec); long hyperell_locally_soluble(GEN pol,GEN p); long nf_hyperell_locally_soluble(GEN nf,GEN pol,GEN p); long nfhilbert(GEN bnf,GEN a,GEN b); long nfhilbert0(GEN bnf,GEN a,GEN b,GEN p); /* elltors.c */ long ellisdivisible(GEN E, GEN P, GEN n, GEN *Q); /* ellisog.c */ GEN ellisogenyapply(GEN f, GEN P); GEN ellisogeny(GEN e, GEN G, long only_image, long vx, long vy); GEN ellisomat(GEN E, long p, long flag); GEN ellmaninconstant(GEN E); GEN ellweilcurve(GEN E, GEN *pm); /* ellsea.c */ GEN Flxq_elldivpolmod(GEN a4, GEN a6, long n, GEN h, GEN T, ulong p); GEN Fp_ellcard_SEA(GEN a4, GEN a6, GEN p, long smallfact); GEN Fq_ellcard_SEA(GEN a4, GEN a6, GEN q, GEN T, GEN p, long smallfact); GEN Fq_elldivpolmod(GEN a4, GEN a6, long n, GEN h, GEN T, GEN p); GEN ellmodulareqn(long l, long vx, long vy); /* es.c */ GEN externstr(const char *cmd); char *gp_filter(const char *s); GEN gpextern(const char *cmd); long gpsystem(const char *s); void gpwritebin(const char *s, GEN x); GEN readstr(const char *s); GEN GENtoGENstr_nospace(GEN x); GEN GENtoGENstr(GEN x); char* GENtoTeXstr(GEN x); char* GENtostr(GEN x); char* GENtostr_raw(GEN x); char* GENtostr_unquoted(GEN x); GEN Str(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, ...); long gp_embedded(const char *s); void gp_embedded_init(long rsize, long vsize); void gp_fileclose(long n); long gp_fileextern(char *s); void gp_fileflush(long n); void gp_fileflush0(GEN n); long gp_fileopen(char *s, char *mode); GEN gp_fileread(long n); GEN gp_filereadstr(long n); void gp_filewrite(long n, const char *s); void gp_filewrite1(long n, const char *s); GEN gp_getenv(const char *s); GEN gp_read_file(const char *s); GEN gp_read_str_multiline(const char *s, char *last); GEN gp_read_stream(FILE *f); GEN gp_readvec_file(char *s); GEN gp_readvec_stream(FILE *f); void gpinstall(const char *s, const char *code, const char *gpname, const char *lib); GEN gsprintf(const char *fmt, ...); GEN gvsprintf(const char *fmt, va_list ap); char* itostr(GEN x); void matbrute(GEN g, char format, long dec); char* os_getenv(const char *s); char* uordinal(ulong i); void outmat(GEN x); void output(GEN x); char* RgV_to_str(GEN g, long flag); void pari_add_hist(GEN z, long t, long r); void pari_ask_confirm(const char *s); void pari_fclose(pariFILE *f); void pari_flush(void); pariFILE* pari_fopen(const char *s, const char *mode); pariFILE* pari_fopen_or_fail(const char *s, const char *mode); pariFILE* pari_fopengz(const char *s); void pari_fprintf(FILE *file, const char *fmt, ...); void pari_fread_chars(void *b, size_t n, FILE *f); GEN pari_get_hist(long p); long pari_get_histrtime(long p); long pari_get_histtime(long p); char* pari_get_homedir(const char *user); GEN pari_histtime(long p); 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_unique_dir(const char *s); char* pari_unique_filename(const char *s); char* pari_unique_filename_suffix(const char *s, const char *suf); void pari_unlink(const char *s); void pari_vfprintf(FILE *file, const char *fmt, va_list ap); void pari_vprintf(const char *fmt, va_list ap); char* pari_vsprintf(const char *fmt, va_list ap); char* path_expand(const char *s); void out_print0(PariOUT *out, const char *sep, GEN g, long flag); void out_print1(PariOUT *out, const char *sep, GEN g, long flag); void out_printf(PariOUT *out, const char *fmt, ...); void out_putc(PariOUT *out, char c); void out_puts(PariOUT *out, const char *s); void out_term_color(PariOUT *out, long c); void out_vprintf(PariOUT *out, const char *fmt, va_list ap); char* pari_sprint0(const char *msg, GEN g, long flag); void print(GEN g); void printp(GEN g); enum { f_RAW = 0, f_PRETTYMAT = 1, f_PRETTY = 3, f_TEX = 4 }; void print1(GEN g); void printf0(const char *fmt, GEN args); void printsep(const char *s, GEN g); void printsep1(const char *s, GEN g); void printtex(GEN g); char* stack_sprintf(const char *fmt, ...); void str_init(pari_str *S, int use_stack); void str_printf(pari_str *S, const char *fmt, ...); void str_putc(pari_str *S, char c); void str_puts(pari_str *S, 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); void warning0(GEN g); void write0(const char *s, GEN g); void write1(const char *s, GEN g); void writebin(const char *name, GEN x); void writetex(const char *s, GEN g); /* eval.c */ enum { br_NONE = 0, br_BREAK, br_NEXT, br_MULTINEXT, br_RETURN }; void bincopy_relink(GEN C, GEN vi); GEN bitprecision0(GEN x,long n); GEN bitprecision00(GEN x,GEN n); GEN break0(long n); GEN call0(GEN fun, GEN args); GEN closure_callgen0prec(GEN C, long prec); GEN closure_callgen0(GEN C); GEN closure_callgen1(GEN C, GEN x); GEN closure_callgen1prec(GEN C, GEN x, long prec); GEN closure_callgen2(GEN C, GEN x, GEN y); GEN closure_callgenall(GEN C, long n, ...); GEN closure_callgenvec(GEN C, GEN args); GEN closure_callgenvecdef(GEN C, GEN args, GEN def); GEN closure_callgenvecdefprec(GEN C, GEN args, GEN def, long prec); GEN closure_callgenvecprec(GEN C, GEN args, long prec); void closure_callvoid1(GEN C, GEN x); long closure_context(long start, long level); void closure_disassemble(GEN n); void closure_err(long level); GEN closure_evalbrk(GEN C, long *status); GEN closure_evalgen(GEN C); GEN closure_evalnobrk(GEN C); GEN closure_evalres(GEN C); void closure_evalvoid(GEN C); const char * closure_func_err(void); GEN closure_trapgen(GEN C, long numerr); GEN copybin_unlink(GEN C); long getlocalprec(long prec); long getlocalbitprec(long bit); GEN get_lex(long vn); long get_localprec(void); long get_localbitprec(void); GEN gp_call(void *E, GEN x); GEN gp_callprec(void *E, GEN x, long prec); GEN gp_call2(void *E, GEN x, GEN y); long gp_callbool(void *E, GEN x); long gp_callvoid(void *E, GEN x); GEN gp_eval(void *E, GEN x); long gp_evalbool(void *E, GEN x); GEN gp_evalprec(void *E, GEN x, long prec); GEN gp_evalupto(void *E, GEN x); long gp_evalvoid(void *E, GEN x); void localprec(GEN p); void localbitprec(GEN p); long loop_break(void); GEN next0(long n); GEN pareval(GEN C); GEN pari_self(void); GEN parsum(GEN a, GEN b, GEN code); GEN parvector(long n, GEN code); void pop_lex(long n); void pop_localprec(void); GEN precision0(GEN x,long n); GEN precision00(GEN x, GEN n); void push_lex(GEN a, GEN C); void push_localbitprec(long p); void push_localprec(long p); GEN return0(GEN x); void set_lex(long vn, GEN x); /* forprime.c */ int forcomposite_init(forcomposite_t *C, GEN a, GEN b); GEN forcomposite_next(forcomposite_t *C); GEN forprime_next(forprime_t *T); int forprime_init(forprime_t *T, GEN a, GEN b); int forprimestep_init(forprime_t *T, GEN a, GEN b, GEN q); void initprimetable(ulong maxnum); ulong maxprime(void); ulong maxprimeN(void); void maxprime_check(ulong c); ulong maxprimelim(void); void pari_init_primes(ulong maxprime); GEN prodprimes(void); ulong u_forprime_next(forprime_t *T); int u_forprime_init(forprime_t *T, ulong a, ulong b); void u_forprime_restrict(forprime_t *T, ulong c); int u_forprime_arith_init(forprime_t *T, ulong a, ulong b, ulong c, ulong q); /* FF.c */ GEN FF_1(GEN a); GEN FF_Frobenius(GEN x, long e); GEN FF_Z_Z_muldiv(GEN x, GEN y, GEN z); GEN FF_Q_add(GEN x, GEN y); GEN FF_Z_add(GEN a, GEN b); GEN FF_Z_mul(GEN a, GEN b); GEN FF_add(GEN a, GEN b); GEN FF_charpoly(GEN x); GEN FF_conjvec(GEN x); GEN FF_div(GEN a, GEN b); GEN FF_ellcard(GEN E); GEN FF_ellcard_SEA(GEN E, long smallfact); GEN FF_ellgens(GEN E); GEN FF_ellgroup(GEN E, GEN *m); GEN FF_elllog(GEN E, GEN P, GEN Q, GEN o); GEN FF_ellmul(GEN E, GEN P, GEN n); GEN FF_ellorder(GEN E, GEN P, GEN o); GEN FF_elltwist(GEN E); GEN FF_ellrandom(GEN E); GEN FF_elltatepairing(GEN E, GEN P, GEN Q, GEN m); GEN FF_ellweilpairing(GEN E, GEN P, GEN Q, GEN m); int FF_equal(GEN a, GEN b); int FF_equal0(GEN x); int FF_equal1(GEN x); int FF_equalm1(GEN x); long FF_f(GEN x); GEN FF_gen(GEN x); GEN FF_inv(GEN a); long FF_issquare(GEN x); long FF_issquareall(GEN x, GEN *pt); long FF_ispower(GEN x, GEN K, GEN *pt); GEN FF_log(GEN a, GEN b, GEN o); GEN FF_map(GEN m, GEN x); GEN FF_minpoly(GEN x); GEN FF_mod(GEN x); GEN FF_mul(GEN a, GEN b); GEN FF_mul2n(GEN a, long n); GEN FF_neg(GEN a); GEN FF_neg_i(GEN a); GEN FF_norm(GEN x); GEN FF_order(GEN x, GEN o); GEN FF_p(GEN x); GEN FF_p_i(GEN x); GEN FF_pow(GEN x, GEN n); GEN FF_primroot(GEN x, GEN *o); GEN FF_q(GEN x); int FF_samefield(GEN x, GEN y); GEN FF_sqr(GEN a); GEN FF_sqrt(GEN a); GEN FF_sqrtn(GEN x, GEN n, GEN *zetan); GEN FF_sub(GEN x, GEN y); GEN FF_to_F2xq(GEN x); GEN FF_to_F2xq_i(GEN x); GEN FF_to_Flxq(GEN x); GEN FF_to_Flxq_i(GEN x); GEN FF_to_FpXQ(GEN x); GEN FF_to_FpXQ_i(GEN x); GEN FF_trace(GEN x); long FF_var(GEN x); GEN FF_zero(GEN a); GEN FFM_FFC_invimage(GEN M, GEN C, GEN ff); GEN FFM_FFC_gauss(GEN M, GEN C, GEN ff); GEN FFM_FFC_mul(GEN M, GEN C, GEN ff); GEN FFM_deplin(GEN M, GEN ff); GEN FFM_det(GEN M, GEN ff); GEN FFM_gauss(GEN M, GEN N, GEN ff); GEN FFM_image(GEN M, GEN ff); GEN FFM_indexrank(GEN M, GEN ff); GEN FFM_inv(GEN M, GEN ff); GEN FFM_invimage(GEN M, GEN N, GEN ff); GEN FFM_ker(GEN M, GEN ff); GEN FFM_mul(GEN M, GEN N, GEN ff); long FFM_rank(GEN M, GEN ff); GEN FFM_suppl(GEN M, GEN ff); GEN FFV_roots_to_pol(GEN V, GEN ff, long v); GEN FFX_add(GEN Pf, GEN Qf, GEN ff); GEN FFX_ddf(GEN f, GEN x); GEN FFX_degfact(GEN Pf, GEN ff); GEN FFX_disc(GEN Pf, GEN ff); GEN FFX_extgcd(GEN Pf, GEN Qf, GEN ff, GEN *pt_Uf, GEN *pt_Vf); GEN FFX_factor(GEN f, GEN x); GEN FFX_factor_squarefree(GEN f, GEN x); GEN FFX_gcd(GEN Pf, GEN Qf, GEN ff); GEN FFX_halfgcd(GEN Pf, GEN Qf, GEN ff); GEN FFX_halfgcd_all(GEN Pf, GEN Qf, GEN ff, GEN *a, GEN *b); long FFX_ispower(GEN Pf, long k, GEN ff, GEN *pt_r); GEN FFX_mul(GEN Pf, GEN Qf, GEN ff); GEN FFX_preimage(GEN x, GEN F, GEN y); GEN FFX_preimagerel(GEN x, GEN F, GEN y); GEN FFX_rem(GEN Pf, GEN Qf, GEN ff); GEN FFX_resultant(GEN Pf, GEN Qf, GEN ff); GEN FFX_roots(GEN f, GEN x); GEN FFX_sqr(GEN Pf, GEN ff); GEN FFXQ_inv(GEN Pf, GEN Qf, GEN ff); GEN FFXQ_minpoly(GEN Pf, GEN Qf, GEN ff); GEN FFXQ_mul(GEN Pf, GEN Qf, GEN Sf, GEN ff); GEN FFXQ_sqr(GEN Pf, GEN Qf, GEN ff); GEN FqX_to_FFX(GEN x, GEN ff); GEN Fq_to_FF(GEN x, GEN ff); GEN Z_FF_div(GEN a, GEN b); GEN ffembed(GEN a, GEN b); GEN ffextend(GEN a, GEN P, long v); GEN fffrobenius(GEN m, long n); GEN ffgen(GEN T, long v); GEN ffinvmap(GEN m); GEN fflog(GEN x, GEN g, GEN o); GEN ffmap(GEN m, GEN x); GEN ffmaprel(GEN m, GEN x); GEN ffcompomap(GEN m, GEN n); GEN fforder(GEN x, GEN o); GEN ffprimroot(GEN x, GEN *o); GEN ffrandom(GEN ff); int Rg_is_FF(GEN c, GEN *ff); int RgC_is_FFC(GEN x, GEN *ff); int RgM_is_FFM(GEN x, GEN *ff); GEN p_to_FF(GEN p, long v); GEN Tp_to_FF(GEN T, GEN p); /* factcyclo.c */ GEN Flx_factcyclo(ulong n, ulong p, ulong m); GEN FpX_factcyclo(ulong n, GEN p, ulong m); GEN factormodcyclo(long n, GEN p, long m, long v); /* galconj.c */ GEN checkgal(GEN gal); GEN checkgroup(GEN g, GEN *S); GEN checkgroupelts(GEN gal); GEN embed_disc(GEN r, long r1, long prec); GEN embed_roots(GEN r, long r1); GEN galois_group(GEN gal); GEN galoisconj(GEN nf, GEN d); GEN galoisconj0(GEN nf, long flag, GEN d, long prec); GEN galoisconjclasses(GEN gal); 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 galoissplittinginit(GEN nf, GEN deg); GEN galoissubgroups(GEN G); GEN galoissubfields(GEN G, long flag, long v); long numberofconjugates(GEN T, long pdepart); /* galois.c */ GEN polgalois(GEN x, long prec); /* galpol.c */ GEN galoisnbpol(long a); GEN galoisgetgroup(long a, long b); GEN galoisgetname(long a, long b); GEN galoisgetpol(long a, long b, long s); /* gen1.c */ GEN conj_i(GEN x); GEN conjvec(GEN x,long prec); GEN divrunextu(GEN x, ulong i); 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 gdivgu(GEN x, ulong s); GEN gdivgunextu(GEN x, ulong i); GEN ginv(GEN x); GEN gmul(GEN x, GEN y); GEN gmul2n(GEN x, long n); GEN gmulsg(long s, GEN y); GEN gmulug(ulong s, GEN y); GEN gsqr(GEN x); GEN gsub(GEN x, GEN y); GEN gsubsg(long x, GEN y); GEN mulcxI(GEN x); GEN mulcxmI(GEN x); GEN mulcxpowIs(GEN x, long k); GEN Qdivii(GEN x1, GEN x2); GEN Qdiviu(GEN x, ulong y); GEN Qdivis(GEN x, long y); GEN ser_normalize(GEN x); /* gen2.c */ GEN gassoc_proto(GEN f(GEN,GEN),GEN,GEN); GEN map_proto_G(GEN f(GEN), GEN x); GEN map_proto_lG(long f(GEN), GEN x); GEN map_proto_lGL(long f(GEN,long), GEN x, long y); long Q_lval(GEN x, ulong p); long Q_lvalrem(GEN x, ulong p, GEN *y); long Q_pval(GEN x, GEN p); long Q_pvalrem(GEN x, GEN p, GEN *y); long RgX_val(GEN x); long RgX_valrem(GEN x, GEN *z); long RgX_valrem_inexact(GEN x, GEN *Z); long RgXV_maxdegree(GEN x); long Z_lval(GEN n, ulong p); long Z_lvalrem(GEN n, ulong p, GEN *py); long Z_lvalrem_stop(GEN *n, ulong p, int *stop); long Z_pval(GEN n, GEN p); long Z_pvalrem(GEN x, GEN p, GEN *py); int ZV_Z_dvd(GEN v, GEN p); long ZV_pval(GEN x, GEN p); long ZV_pvalrem(GEN x, GEN p, GEN *px); long ZV_lval(GEN x, ulong p); long ZV_lvalrem(GEN x, ulong p, GEN *px); long ZX_lvalrem(GEN x, ulong p, GEN *px); long ZX_lval(GEN x, ulong p); long ZX_pval(GEN x, GEN p); long ZX_pvalrem(GEN x, GEN p, GEN *px); long ZXV_pvalrem(GEN x, GEN p, GEN *px); long ZXX_pvalrem(GEN x, GEN p, GEN *px); GEN cgetp(GEN x); GEN cvstop2(long s, GEN y); GEN cvtop(GEN x, GEN p, long l); GEN cvtop2(GEN x, GEN y); int cx_approx_equal(GEN a, GEN b); int cx_approx0(GEN x, GEN y); GEN gabs(GEN x, long prec); void gaffect(GEN x, GEN y); void gaffsg(long s, GEN x); int gcmp(GEN x, GEN y); int gequal0(GEN x); int gequal1(GEN x); int gequalX(GEN x); int gequalm1(GEN x); int gcmpsg(long x, GEN y); GEN gcvtop(GEN x, GEN p, long r); int gequal(GEN x, GEN y); int gequalsg(long s, GEN x); long gexpo(GEN x); long gexpo_safe(GEN x); GEN gpexponent(GEN x); GEN gpvaluation(GEN x, GEN p); long gvaluation(GEN x, GEN p); int gidentical(GEN x, GEN y); long glength(GEN x); GEN gmax(GEN x, GEN y); GEN gmaxgs(GEN x, long y); GEN gmin(GEN x, GEN y); GEN gmings(GEN x, long y); GEN gneg(GEN x); GEN gneg_i(GEN x); int gsigne(GEN x); GEN gtolist(GEN x); long gtolong(GEN x); long gtranslength(GEN x); int lexcmp(GEN x, GEN y); GEN listinsert(GEN list, GEN object, long index); GEN listinsert0(GEN list, GEN object, long index); void listpop(GEN L, long index); void listpop0(GEN L, long index); GEN listput(GEN list, GEN object, long index); GEN listput0(GEN list, GEN object, long index); void listsort(GEN list, long flag); GEN matsize(GEN x); GEN mklist(void); GEN mklist_typ(long t); GEN mklistcopy(GEN x); GEN mkmap(void); GEN normalizeser(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_lvalrem_stop(ulong *n, ulong p, int *stop); long u_pval(ulong x, GEN p); long u_pvalrem(ulong x, GEN p, ulong *py); long vecindexmax(GEN x); long vecindexmin(GEN x); GEN vecmax0(GEN x, GEN *pv); GEN vecmax(GEN x); GEN vecmin0(GEN x, GEN *pv); GEN vecmin(GEN x); long z_lval(long s, ulong p); long z_lvalrem(long s, ulong p, long *py); long z_pval(long n, GEN p); long z_pvalrem(long n, GEN p, long *py); long zx_lval(GEN f, long p); /* hgm.c */ GEN hgmcyclo(GEN hgm); GEN hgmalpha(GEN hgm); GEN hgmgamma(GEN hgm); GEN hgminit(GEN val, GEN vbe); GEN hgmparams(GEN hgm); GEN hgmeulerfactor(GEN hgm, GEN t, long p, GEN* ptcondexpo); GEN hgmcoef(GEN hgm, GEN t, GEN n); GEN hgmcoefs(GEN hgm, GEN t, long n); GEN hgmtwist(GEN hgm); long hgmissymmetrical(GEN hgm); GEN hgmbydegree(long n); GEN lfunhgm(GEN hgm, GEN t, GEN hint, long bit); /* lerch.c */ GEN Qp_zeta(GEN s); GEN Qp_zetahurwitz(GEN s, GEN x, long k); GEN lerchphi(GEN z, GEN s, GEN a, long bitprec); GEN lerchzeta(GEN s, GEN a, GEN lam, long bitprec); GEN zetahurwitz(GEN s, GEN x, long der, long bitprec); /* Ser.c */ GEN RgX_to_ser(GEN x, long l); GEN RgX_to_ser_inexact(GEN x, long l); GEN gtoser(GEN x, long v, long d); GEN gtoser_prec(GEN x, long v, long d); GEN rfrac_to_ser(GEN x, long l); GEN rfrac_to_ser_i(GEN x, long); GEN rfracrecip_to_ser_absolute(GEN R, long l); long rfracrecip(GEN *pn, GEN *pd); GEN scalarser(GEN x, long v, long prec); GEN sertoser(GEN x, long prec); GEN toser_i(GEN x); GEN RgV_to_ser(GEN x, long v, long l); GEN Ser0(GEN x, long v, GEN d, long prec); /* gen3.c */ GEN padic_to_Q(GEN x); GEN padic_to_Q_shallow(GEN x); GEN QpV_to_QV(GEN v); GEN RgC_RgV_mulrealsym(GEN x, GEN y); GEN RgM_mulreal(GEN x, GEN y); GEN RgX_cxeval(GEN T, GEN u, GEN ui); GEN RgX_deflate_max(GEN x0, long *m); long RgX_deflate_order(GEN x); long RgX_degree(GEN x,long v); GEN RgX_integ(GEN x); GEN RgXY_cxevalx(GEN T, GEN u, GEN ui); long ZX_deflate_order(GEN x); GEN ZX_deflate_max(GEN x, 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); GEN deg2pol_shallow(GEN x2, GEN x1, GEN x0,long v); long degree(GEN x); GEN denom(GEN x); GEN denom_i(GEN x); GEN denominator(GEN x, GEN D); GEN deriv(GEN x, long v); GEN derivn(GEN x, long n, long v); GEN derivser(GEN x); GEN diffop(GEN x, GEN v, GEN dv); GEN diffop0(GEN x, GEN v, GEN dv, long n); GEN diviiround(GEN x, GEN y); GEN divrem(GEN x, GEN y, long v); GEN floor_safe(GEN x); GEN gceil(GEN x); GEN gcvtoi(GEN x, long *e); GEN gdeflate(GEN x, long v, long d); GEN gdivent(GEN x, GEN y); GEN gdiventgs(GEN x, long y); GEN gdiventsg(long x, GEN y); GEN gdiventres(GEN x, GEN y); GEN gdivmod(GEN x, GEN y, GEN *pr); GEN gdivround(GEN x, GEN y); int gdvd(GEN x, GEN y); GEN geq(GEN x, GEN y); GEN geval(GEN x); GEN gfloor(GEN x); GEN gtrunc2n(GEN x, long s); GEN gfrac(GEN x); GEN gge(GEN x, GEN y); GEN ggrando(GEN x, long n); GEN ggt(GEN x, GEN y); GEN gimag(GEN x); GEN gisexactzero(GEN g); GEN gle(GEN x, GEN y); GEN glt(GEN x, GEN y); GEN gmod(GEN x, GEN y); GEN gmodgs(GEN x, long y); GEN gmodsg(long x, GEN y); GEN gmodulo(GEN x,GEN y); GEN gmodulsg(long x, GEN y); GEN gmodulss(long x, long y); GEN gne(GEN x, GEN y); GEN gnot(GEN x); GEN gpolvar(GEN y); GEN gppadicprec(GEN x, GEN p); GEN gppoldegree(GEN x, long v); long gprecision(GEN x); GEN gpserprec(GEN x, long v); GEN greal(GEN x); GEN grndtoi(GEN x, long *e); GEN ground(GEN x); GEN gshift(GEN x, long n); GEN gsubst(GEN x, long v, GEN y); GEN gsubstpol(GEN x, GEN v, GEN y); GEN gsubstvec(GEN x, GEN v, GEN y); GEN gtocol(GEN x); GEN gtocol0(GEN x, long n); GEN gtocolrev(GEN x); GEN gtocolrev0(GEN x, long n); GEN gtopoly(GEN x, long v); GEN gtopolyrev(GEN x, long v); GEN gtovec(GEN x); GEN gtovec0(GEN x, long n); GEN gtovecrev(GEN x); GEN gtovecrev0(GEN x, long n); GEN gtovecsmall(GEN x); GEN gtovecsmall0(GEN x, long n); GEN gtrunc(GEN x); long gvar(GEN x); long gvar2(GEN x); GEN hqfeval(GEN q, GEN x); GEN imag_i(GEN x); GEN integ(GEN x, long v); GEN integser(GEN x); GEN ser_inv(GEN b); 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 lift_shallow(GEN x); GEN lift0(GEN x,long v); GEN liftall(GEN x); GEN liftall_shallow(GEN x); GEN liftint(GEN x); GEN liftint_shallow(GEN x); GEN liftpol(GEN x); GEN liftpol_shallow(GEN x); GEN mkcoln(long n, ...); GEN mkintn(long n, ...); GEN mkpoln(long n, ...); GEN mkvecn(long n, ...); GEN mkvecsmalln(long n, ...); GEN modRr_safe(GEN x, GEN y); GEN modRr_i(GEN x, GEN y, GEN iy); GEN mulreal(GEN x, GEN y); GEN numer(GEN x); GEN numer_i(GEN x); GEN numerator(GEN x, GEN D); long padicprec(GEN x, GEN p); long padicprec_relative(GEN x); GEN polcoef(GEN x, long n, long v); GEN polcoef_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 qf_RgM_apply(GEN q, GEN M); GEN qf_ZM_apply(GEN q, GEN M); GEN qfb_ZM_apply(GEN q, GEN M); GEN qfbil(GEN x, GEN y, GEN q); GEN qfeval(GEN q, GEN x); GEN qfeval0(GEN q, GEN x, GEN y); GEN qfevalb(GEN q, GEN x, GEN y); GEN qfnorm(GEN x, GEN q); GEN real_i(GEN x); GEN round0(GEN x, GEN *pte); GEN roundr(GEN x); GEN roundr_safe(GEN x); GEN scalarpol(GEN x, long v); GEN scalarpol_shallow(GEN x, long v); GEN ser_unscale(GEN P, GEN h); long serprec(GEN x, long v); GEN serreverse(GEN x); GEN simplify(GEN x); GEN simplify_shallow(GEN x); GEN tayl(GEN x, long v, long precdl); GEN trunc0(GEN x, GEN *pte); GEN uu32toi(ulong a, ulong b); GEN uu32toineg(ulong a, ulong b); GEN vars_sort_inplace(GEN z); GEN vars_to_RgXV(GEN h); GEN variables_vecsmall(GEN x); GEN variables_vec(GEN x); /* genus2red.c */ GEN genus2red(GEN PQ, GEN p); GEN genus2igusa(GEN P, long n); /* grossenchar.c */ GEN gchar_conductor(GEN gc, GEN chi); GEN gchar_identify(GEN gc, GEN Lv, GEN Lchiv, long prec); GEN gcharalgebraic(GEN gc, GEN type); GEN gcharduallog(GEN gc, GEN chi); GEN gchareval(GEN gc, GEN chi, GEN x, long flag); GEN gchari_lfun(GEN gc, GEN chi, GEN w); GEN gcharinit(GEN bnf, GEN mod, long prec); int gcharisalgebraic(GEN gc, GEN chi, GEN *pq); GEN gcharlocal(GEN gc, GEN chi, GEN v, long prec, GEN *ptbid); GEN gcharlog(GEN gc, GEN x, long prec); GEN gcharnewprec(GEN gc, long prec); int is_gchar_group(GEN gc); GEN lfungchar(GEN gc, GEN chi); GEN vecan_gchar(GEN an, long n, long prec); GEN eulerf_gchar(GEN an, GEN p, long prec); /* groupid.c */ long group_ident(GEN G, GEN S); long group_ident_trans(GEN G, GEN S); /* hash.c */ hashtable *hash_create_ulong(ulong s, long stack); hashtable *hash_create_str(ulong s, long stack); hashtable *hash_create(ulong minsize, ulong (*hash)(void*), int (*eq)(void*,void*), int use_stack); void hash_dbg(hashtable *h); GEN hash_haskey_GEN(hashtable *h, void *k); int hash_haskey_long(hashtable *h, void *k, long *v); void hash_init(hashtable *h, ulong minsize, ulong (*hash)(void*), int (*eq)(void*,void*), int use_stack); void hash_init_GEN(hashtable *h, ulong minsize, int (*eq)(GEN,GEN), int use_stack); void hash_init_ulong(hashtable *h, ulong minsize, int use_stack); void hash_insert(hashtable *h, void *k, void *v); void hash_insert_long(hashtable *h, void *k, long v); void hash_insert2(hashtable *h, void *k, void *v, ulong hash); GEN hash_keys(hashtable *h); GEN hash_keys_GEN(hashtable *h); GEN hash_values(hashtable *h); hashentry *hash_search(hashtable *h, void *k); hashentry *hash_search2(hashtable *h, void *k, ulong hash); hashentry *hash_select(hashtable *h, void *k, void *E,int(*select)(void *,hashentry *)); hashentry *hash_remove(hashtable *h, void *k); hashentry *hash_remove_select(hashtable *h, void *k, void *E, int (*select)(void*,hashentry*)); void hash_destroy(hashtable *h); ulong hash_GEN(GEN x); ulong hash_zv(GEN x); /* hyperell.c */ GEN ZX_hyperellred(GEN P, GEN *pM); GEN hyperellcharpoly(GEN x); GEN hyperellchangecurve(GEN C, GEN m); GEN hyperelldisc(GEN x); int hyperellisoncurve(GEN W, GEN P); GEN hyperellminimaldisc(GEN x, GEN pr); GEN hyperellminimalmodel(GEN x, GEN *pM, GEN pr); GEN hyperellordinate(GEN W, GEN x); GEN hyperellpadicfrobenius0(GEN x, GEN p, long e); GEN hyperellpadicfrobenius(GEN x, ulong p, long e); GEN hyperellred(GEN P, GEN *pM); GEN nfhyperellpadicfrobenius(GEN H, GEN T, ulong p, long n); /* hypergeom.c */ GEN hypergeom(GEN vnum, GEN vden, GEN z, long prec); GEN airy(GEN z, long prec); /* hnf_snf.c */ GEN RgM_hnfall(GEN A, GEN *pB, long remove); GEN ZM_hnf(GEN x); GEN ZM_hnf_knapsack(GEN x); GEN ZM_hnfall(GEN A, GEN *ptB, long remove); GEN ZM_hnfall_i(GEN A, GEN *ptB, long remove); GEN ZM_hnfcenter(GEN M); GEN ZM_hnflll(GEN A, GEN *ptB, int remove); GEN ZV_extgcd(GEN A); GEN ZV_snfall(GEN D, GEN *pU, GEN *pV); GEN ZV_snf_group(GEN d, GEN *newU, GEN *newUi); long ZV_snf_rank(GEN D, GEN p); long ZV_snf_rank_u(GEN D, ulong p); void ZV_snf_trunc(GEN D); GEN ZM_hnfmod(GEN x, GEN d); GEN ZM_hnfmodall(GEN x, GEN dm, long flag); GEN ZM_hnfmodall_i(GEN x, GEN dm, long flag); GEN ZM_hnfmodid(GEN x, GEN d); GEN ZM_hnfmodprime(GEN x, GEN p); 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, long flag); GEN ZV_snfclean(GEN d); GEN ZpM_echelon(GEN x, long early_abort, GEN p, GEN pm); GEN gsmith(GEN x); GEN gsmithall(GEN x); GEN hnf(GEN x); GEN hnf_divscale(GEN A, GEN B,GEN t); GEN hnf_invscale(GEN A, 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); long snfrank(GEN D, GEN p); GEN zlm_echelon(GEN x, long early_abort, ulong p, ulong pm); long zv_snf_rank(GEN D, ulong p); /* ifactor1.c */ GEN Z_ECM(GEN N, long rounds, long seed, ulong B1); GEN Z_factor(GEN n); GEN Z_factor_limit(GEN n, ulong all); GEN Z_factor_until(GEN n, GEN limit); long Z_issmooth(GEN m, ulong lim); GEN Z_issmooth_fact(GEN m, ulong lim); long Z_issquarefree(GEN x); GEN Z_pollardbrent(GEN n, long rounds, long seed); GEN absZ_factor(GEN n); GEN absZ_factor_limit(GEN n, ulong all); GEN absZ_factor_limit_strict(GEN n, ulong all, GEN *pU); ulong coreu(ulong n); ulong coreu_fact(GEN f); GEN factorint(GEN n, long flag); GEN factoru(ulong n); ulong tridiv_boundu(ulong n); int ifac_isprime(GEN x); int ifac_next(GEN *part, GEN *p, long *e); int ifac_read(GEN part, GEN *p, long *e); void ifac_skip(GEN part); GEN ifac_start(GEN n, int moebius); int is_357_power(GEN x, GEN *pt, ulong *mask); int is_pth_power(GEN x, GEN *pt, forprime_t *T, ulong cutoffbits); long ispowerful(GEN n); long maxomegau(ulong x); long maxomegaoddu(ulong x); long moebius(GEN n); long moebiusu(ulong n); long moebiusu_fact(GEN f); GEN nextprime(GEN n); GEN precprime(GEN n); ulong radicalu(ulong n); ulong tridiv_bound(GEN n); int uis_357_power(ulong x, ulong *pt, ulong *mask); int uis_357_powermod(ulong x, ulong *mask); ulong unextprime(ulong n); ulong uprecprime(ulong n); GEN vecfactorsquarefreeu(ulong a, ulong b); GEN vecfactorsquarefreeu_coprime(ulong a, ulong b, GEN P); GEN vecfactoru_i(ulong a, ulong b); GEN vecfactoru(ulong a, ulong b); GEN vecfactoroddu_i(ulong a, ulong b); GEN vecfactoroddu(ulong a, ulong b); GEN vecsquarefreeu(ulong a, ulong b); /* init.c */ int chk_gerepileupto(GEN x); GENbin* copy_bin(GEN x); GENbin* copy_bin_canon(GEN x); void dbg_fill_stack(void); void dbg_gerepile(pari_sp av); void dbg_gerepileupto(GEN q); GEN errname(GEN err); GEN gclone(GEN x); GEN gcloneref(GEN x); void gclone_refc(GEN x); GEN gcopy(GEN x); GEN gcopy_avma(GEN x, pari_sp *AVMA); GEN gcopy_lg(GEN x, long lx); GEN gerepile(pari_sp ltop, pari_sp lbot, GEN q); void gerepileallsp(pari_sp av, pari_sp tetpil, int n, ...); void gerepilecoeffssp(pari_sp av, pari_sp tetpil, long *g, int n); void gerepilemanysp(pari_sp av, pari_sp tetpil, GEN* g[], int n); GEN getheap(void); void gp_context_save(struct gp_context* rec); void gp_context_restore(struct gp_context* rec); long gsizeword(GEN x); long gsizebyte(GEN x); void gunclone(GEN x); void gunclone_deep(GEN x); GEN listcopy(GEN x); GEN listinit(GEN x); void msgtimer(const char *format, ...); long name_numerr(const char *s); void new_chunk_resize(size_t x); GEN newblock(size_t n); const char * numerr_name(long errnum); GEN obj_check(GEN S, long K); GEN obj_checkbuild(GEN S, long tag, GEN (*build)(GEN)); GEN obj_checkbuild_padicprec(GEN S, long tag, GEN (*build)(GEN,long), long prec); GEN obj_checkbuild_realprec(GEN S, long tag, GEN (*build)(GEN,long), long prec); GEN obj_checkbuild_prec(GEN S, long tag, GEN (*build)(GEN,long), long (*pr)(GEN), long prec); void obj_free(GEN S); GEN obj_init(long d, long n); GEN obj_insert(GEN S, long K, GEN O); GEN obj_insert_shallow(GEN S, long K, GEN O); GEN obj_reinit(GEN S); void (*os_signal(int sig, void (*f)(int)))(int); void pari_add_function(entree *ep); void pari_add_module(entree *ep); void pari_add_defaults_module(entree *ep); void pari_close(void); void pari_close_opts(ulong init_opts); GEN pari_compile_str(const char *lex); int pari_daemon(void); void pari_err(int numerr, ...); int pari_err_display(GEN err); GEN pari_err_last(void); char * pari_err2str(GEN err); void pari_init_opts(size_t parisize, ulong maxprime, ulong init_opts); void pari_init(size_t parisize, ulong maxprime); void pari_stackcheck_init(void *pari_stack_base); void pari_sighandler(int sig); 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); void pari_thread_valloc(struct pari_thread *t, size_t s, size_t v, GEN arg); GEN pari_version(void); void pari_warn(int numerr, ...); void paristack_newrsize(ulong newsize); void paristack_resize(ulong newsize); void paristack_setsize(size_t rsize, size_t vsize); void parivstack_resize(ulong newsize); void parivstack_reset(void); void setalldebug(long lvl); GEN setdebug(const char *s, long lvl); void shiftaddress(GEN x, long dec); void shiftaddress_canon(GEN x, long dec); long timer(void); long timer_delay(pari_timer *T); long timer_get(pari_timer *T); void timer_printf(pari_timer *T, const char *format, ...); void timer_start(pari_timer *T); long timer2(void); GEN trap0(const char *e, GEN f, GEN r); void traverseheap( void(*f)(GEN, void *), void *data ); void walltimer_start(pari_timer *ti); long walltimer_delay(pari_timer *ti); long walltimer_get(pari_timer *ti); /* intnum.c */ GEN contfraceval(GEN CF, GEN t, long nlim); GEN contfracinit(GEN M, long lim); GEN intcirc(void *E, GEN (*eval) (void *, GEN), GEN a, GEN R, GEN tab, long prec); GEN intfuncinit(void *E, GEN (*eval) (void *, GEN), GEN a, GEN b, long m, long prec); GEN intnum(void *E, GEN (*eval) (void *, GEN), GEN a, GEN b, GEN tab, long prec); GEN intnumgauss(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN tab, long prec); GEN intnumgaussinit(long n, long prec); GEN intnuminit(GEN a, GEN b, long m, long prec); GEN intnumosc(void *E, GEN (*f)(void*, GEN), GEN a, GEN H, long flag, GEN tab, long prec); GEN intnumromb(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, long flag, long prec); GEN prodeulerrat(GEN F, GEN s, long a, long prec); GEN prodnumrat(GEN F, long a, long prec); GEN quodif(GEN M, long n); GEN sumeulerrat(GEN F, GEN s, long a, long prec); GEN sumnum(void *E, GEN (*eval)(void*, GEN), GEN a, GEN tab, long prec); GEN sumnumap(void *E, GEN (*eval)(void*,GEN), GEN a, GEN tab, long prec); GEN sumnumapinit(GEN fast, long prec); GEN sumnuminit(GEN fast, long prec); GEN sumnumlagrangeinit(GEN al, GEN c1, long prec); GEN sumnumlagrange(void *E, GEN (*eval)(void*,GEN,long), GEN a, GEN tab, long prec); GEN sumnummonien(void *E, GEN (*eval)(void*, GEN), GEN a, GEN tab, long prec); GEN sumnummonieninit(GEN asymp, GEN w, GEN n0, long prec); GEN sumnumrat(GEN F, GEN a, long prec); GEN sumnumsidi(void *E, GEN (*f)(void*, GEN, long), GEN a, double mu, long prec); /* ispower.c */ long Z_isanypower(GEN x, GEN *y); long Z_ispow2(GEN x); long Z_ispowerall(GEN x, ulong k, GEN *pt); long Z_issquareall(GEN x, GEN *pt); long Zn_ispower(GEN a, GEN q, GEN K, GEN *pt); long Zn_issquare(GEN x, GEN n); long Zp_issquare(GEN a, GEN p); long gisanypower(GEN x, GEN *pty); GEN gissquare(GEN x); GEN gissquareall(GEN x, GEN *pt); long ispolygonal(GEN x, GEN S, GEN *N); long ispower(GEN x, GEN k, GEN *pty); long isprimepower(GEN x, GEN *pty); long ispseudoprimepower(GEN n, GEN *pt); long issquare(GEN x); long issquareall(GEN x, GEN *pt); GEN sqrtint(GEN a); GEN sqrtint0(GEN a, GEN *r); long uisprimepower(ulong n, ulong *p); long uissquare(ulong A); long uissquareall(ulong A, ulong *sqrtA); long ulogintall(ulong B, ulong y, ulong *ptq); /* krasner.c */ GEN padicfields0(GEN p, GEN n, long flag); GEN padicfields(GEN p, long m, long d, long flag); /* kummer.c */ GEN bnrclassfield(GEN bnr, GEN subgroup, long flag, long prec); GEN rnfkummer(GEN bnr, GEN subgroup, long prec); /* lfun.c */ long is_linit(GEN data); GEN ldata_get_an(GEN ldata); GEN ldata_get_dual(GEN ldata); GEN ldata_get_gammavec(GEN ldata); long ldata_get_degree(GEN ldata); GEN ldata_get_k(GEN ldata); GEN ldata_get_k1(GEN ldata); GEN ldata_get_conductor(GEN ldata); GEN ldata_get_rootno(GEN ldata); GEN ldata_get_residue(GEN ldata); long ldata_get_type(GEN ldata); long ldata_isreal(GEN ldata); long linit_get_type(GEN linit); GEN linit_get_ldata(GEN linit); GEN linit_get_tech(GEN linit); GEN lfun_get_domain(GEN tech); GEN lfun_get_dom(GEN tech); long lfun_get_bitprec(GEN tech); GEN lfun_get_factgammavec(GEN tech); GEN lfun_get_step(GEN tech); GEN lfun_get_pol(GEN tech); GEN lfun_get_Residue(GEN tech); GEN lfun_get_k2(GEN tech); GEN lfun_get_w2(GEN tech); GEN lfun_get_expot(GEN tech); long lfun_get_bitprec(GEN tech); GEN lfun(GEN ldata, GEN s, long bitprec); GEN lfun0(GEN ldata, GEN s, long der, long bitprec); GEN lfunan(GEN ldata, long L, long prec); long lfuncheckfeq(GEN data, GEN t0, long bitprec); GEN lfunconductor(GEN data, GEN maxcond, long flag, long bitprec); GEN lfuncost(GEN lmisc, GEN dom, long der, long bitprec); GEN lfuncost0(GEN L, GEN dom, long der, long bitprec); GEN lfuncreate(GEN obj); GEN lfundual(GEN L, long bitprec); GEN lfuneuler(GEN ldata, GEN p, long prec); GEN lfunparams(GEN ldata, long prec); GEN lfunan(GEN ldata, long L, long prec); GEN lfunhardy(GEN ldata, GEN t, long bitprec); GEN lfuninit(GEN ldata, GEN dom, long der, long bitprec); GEN lfuninit0(GEN ldata, GEN dom, long der, long bitprec); GEN lfuninit_make(long t, GEN ldata, GEN tech, GEN domain); GEN lfunlambda(GEN ldata, GEN s, long bitprec); GEN lfunlambda0(GEN ldata, GEN s, long der, long bitprec); GEN lfunmisc_to_ldata(GEN ldata); GEN lfunmisc_to_ldata_shallow(GEN ldata); GEN lfunmisc_to_ldata_shallow_i(GEN ldata); long lfunorderzero(GEN ldata, long m, long bitprec); GEN lfunprod_get_fact(GEN tech); GEN lfunrootno(GEN data, long bitprec); GEN lfunrootres(GEN data, long bitprec); GEN lfunrtopoles(GEN r); GEN lfunshift(GEN ldata, GEN s, long flag, long bitprec); GEN lfuntwist(GEN ldata1, GEN ldata2, long bitprec); GEN lfuntheta(GEN data, GEN t, long m, long bitprec); long lfunthetacost0(GEN L, GEN tdom, long m, long bitprec); long lfunthetacost(GEN ldata, GEN tdom, long m, long bitprec); GEN lfunthetainit(GEN ldata, GEN tdom, long m, long bitprec); GEN lfunthetacheckinit(GEN data, GEN tinf, long m, long bitprec); GEN lfunzeros(GEN ldata, GEN lim, long divz, long bitprec); int sdomain_isincl(double k, GEN dom, GEN dom0); GEN theta_get_an(GEN tdata); GEN theta_get_K(GEN tdata); GEN theta_get_R(GEN tdata); long theta_get_bitprec(GEN tdata); long theta_get_m(GEN tdata); GEN theta_get_tdom(GEN tdata); GEN theta_get_isqrtN(GEN tdata); int Vgaeasytheta(GEN Vga); GEN znchargauss(GEN G, GEN chi, GEN a, long bitprec); /* lfunutils.c */ GEN dirzetak(GEN nf, GEN b); GEN ellmoddegree(GEN e); GEN eta_ZXn(long v, long L); GEN eta_product_ZXn(GEN eta, long L); long etaquotype(GEN *eta, GEN *pN, GEN *pk, GEN *CHI, long *pv, long *sd, long *cusp); GEN galois_get_conj(GEN G); /* TODO move somewhere else? */ GEN ldata_vecan(GEN ldata, long L, long prec); GEN ldata_newprec(GEN ldata, long prec); GEN lfunabelianrelinit(GEN bnr, GEN H, GEN dom, long der, long bitprec); GEN lfunartin(GEN N, GEN G, GEN M, long o, long bitprec); GEN lfundiv(GEN ldata1, GEN ldata2, long bitprec); GEN lfunellmfpeters(GEN E, long bitprec); GEN lfunetaquo(GEN eta); GEN lfungenus2(GEN PS); GEN lfunmfspec(GEN lmisc, long bitprec); GEN lfunmul(GEN ldata1, GEN ldata2, long bitprec); GEN lfunqf(GEN ldata, long prec); GEN lfunsympow(GEN E, ulong m); GEN lfunzetakinit(GEN pol, GEN dom, long der, long bitprec); long qfiseven(GEN M); /* lfunquad */ GEN lfunquadneg(long D, long k); /* 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); /* map.c */ GEN gtomap(GEN M); void mapdelete(GEN T, GEN a); GEN mapdomain(GEN T); GEN mapdomain_shallow(GEN T); GEN mapget(GEN T, GEN a); int mapisdefined(GEN T, GEN a, GEN *pt_z); void mapput(GEN T, GEN a, GEN b); GEN mapselect_shallow(void *E, long (*f)(void* E, GEN x), GEN T); GEN maptomat(GEN T); GEN maptomat_shallow(GEN T); GEN mapapply(GEN T, GEN a, GEN f, GEN u); /* matperm.c */ GEN matpermanent(GEN M); GEN zm_permanent(GEN M); GEN ZM_permanent(GEN M); /* mellininv.c */ double dbllemma526(double a, double b, double c, double B); double dblcoro526(double a, double c, double B); GEN gammamellininv(GEN Vga, GEN s, long m, long bitprec); GEN gammamellininvasymp(GEN Vga, long nlimmax, long m); GEN gammamellininvinit(GEN Vga, long m, long bitprec); GEN gammamellininvrt(GEN K, GEN s, long bitprec); /* 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_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_normfu(GEN x); GEN member_omega(GEN x); GEN member_orders(GEN x); GEN member_p(GEN x); GEN member_pol(GEN x); GEN member_polabs(GEN x); GEN member_reg(GEN x); GEN member_r1(GEN x); GEN member_r2(GEN x); GEN member_roots(GEN x); GEN member_sign(GEN x); GEN member_t2(GEN x); GEN member_tate(GEN x); GEN member_tu(GEN x); GEN member_zk(GEN x); GEN member_zkst(GEN bid); /* mftrace.c */ enum { mf_NEW = 0, mf_CUSP, mf_OLD, mf_EISEN, mf_FULL }; enum { /*leaves*/ t_MF_CONST, t_MF_EISEN, t_MF_Ek, t_MF_DELTA, t_MF_ETAQUO, t_MF_ELL, t_MF_DIHEDRAL, t_MF_THETA, t_MF_TRACE, t_MF_NEWTRACE, /**/ t_MF_MUL, t_MF_POW, t_MF_DIV, t_MF_BRACKET, t_MF_LINEAR, t_MF_LINEAR_BHN, t_MF_SHIFT, t_MF_DERIV, t_MF_DERIVE2, t_MF_TWIST, t_MF_HECKE, t_MF_BD, }; GEN MF_get_CHI(GEN mf); GEN MF_get_M(GEN mf); GEN MF_get_Mindex(GEN mf); GEN MF_get_Minv(GEN mf); long MF_get_N(GEN mf); GEN MF_get_basis(GEN mf); long MF_get_dim(GEN mf); GEN MF_get_E(GEN mf); GEN MF_get_fields(GEN mf); GEN MF_get_gN(GEN mf); GEN MF_get_gk(GEN mf); long MF_get_k(GEN mf); GEN MF_get_newforms(GEN mf); long MF_get_r(GEN mf); long MF_get_space(GEN mf); GEN MF_get_S(GEN mf); GEN MFcusp_get_vMjd(GEN mf); GEN MFnew_get_vj(GEN mf); GEN Qab_tracerel(GEN v, long t, GEN a); GEN QabM_tracerel(GEN v, long t, GEN x); GEN QabV_tracerel(GEN v, long t, GEN x); GEN Qab_trace_init(long n, long m, GEN Pn, GEN Pm); GEN checkMF(GEN mf); GEN checkMF_i(GEN mf); int checkmf_i(GEN mf); GEN getcache(void); ulong hclassno6u(ulong d); ulong hclassno6u_no_cache(ulong D); GEN lfunmf(GEN mf, GEN F, long bitprec); GEN mfDelta(void); GEN mfEH(GEN gk); GEN mfEk(long k); GEN mfTheta(GEN psi); GEN mf_get_CHI(GEN F); long mf_get_N(GEN F); GEN mf_get_NK(GEN F); GEN mf_get_field(GEN F); GEN mf_get_gN(GEN F); GEN mf_get_gk(GEN F); long mf_get_k(GEN F); long mf_get_r(GEN F); long mf_get_type(GEN F); GEN mfatkin(GEN mfa, GEN F); GEN mfatkineigenvalues(GEN mf, long Q, long prec); GEN mfatkininit(GEN mf, long Q, long prec); GEN mfbasis(GEN mf, long space); GEN mfbd(GEN F, long d); GEN mfbracket(GEN F, GEN G, long m); long mfcharorder(GEN CHI); long mfcharmodulus(GEN CHI); GEN mfcharpol(GEN CHI); GEN mfcoef(GEN F, long n); GEN mfcoefs(GEN F, long n, long d); long mfconductor(GEN mf, GEN F); GEN mfcosets(GEN N); long mfcuspdim(long N, long k, GEN CHI); long mfcuspisregular(GEN NK, GEN cusp); GEN mfcusps(GEN gN); GEN mfcuspval(GEN mf, GEN F, GEN cusp, long bitprec); long mfcuspwidth(GEN gN, GEN cusp); GEN mfderiv(GEN F, long m); GEN mfderivE2(GEN F, long k); GEN mfdescribe(GEN F, GEN *PTU); GEN mfdim(GEN NK, long codespace); GEN mfdiv(GEN F, GEN G); GEN mfdiv_val(GEN F, GEN G, long vG); GEN mfeigenbasis(GEN mf); GEN mfeigensearch(GEN nklim, GEN vmod); GEN mfeisenstein(long k, GEN CHI1, GEN CHI2); long mfeisensteindim(long N, long k, GEN CHI); GEN mfembed(GEN E, GEN f); GEN mfembed0(GEN E, GEN v, long prec); GEN mfeval(GEN mf, GEN F, GEN vtau, long bitprec); GEN mffields(GEN mf); GEN mffromell(GEN E); GEN mffrometaquo(GEN eta, long flag); GEN mffromlfun(GEN L, long prec); GEN mffromqf(GEN Q, GEN P); long mffulldim(long N, long k, GEN CHI); GEN mfgaloisprojrep(GEN mf, GEN F, long prec); GEN mfgaloistype(GEN NK, GEN F); GEN mfhecke(GEN mf, GEN F, long n); GEN mfheckemat(GEN mf, GEN vecn); GEN mfinit(GEN NK, long space); GEN mfisCM(GEN F); long mfiscuspidal(GEN mf, GEN F); long mfisequal(GEN F, GEN G, long lim); GEN mfisetaquo(GEN F, long flag); GEN mfkohnenbasis(GEN mf); GEN mfkohnenbijection(GEN mf); GEN mfkohneneigenbasis(GEN mf, GEN bij); GEN mflinear(GEN vF, GEN vla); GEN mfmanin(GEN F, long bitprec); GEN mfmatembed(GEN E, GEN f); GEN mfmul(GEN F, GEN G); long mfnewdim(long N, long k, GEN CHI); long mfolddim(long N, long k, GEN CHI); GEN mfparams(GEN F); GEN mfperiodpol(GEN mf, GEN F, long flag, long prec); GEN mfperiodpolbasis(long k, long flag); GEN mfpetersson(GEN FS, GEN GS); GEN mfpow(GEN F, long n); GEN mfsearch(GEN nklim, GEN V, long space); GEN mfshift(GEN F, long sh); GEN mfshimura(GEN mf, GEN F, long t); GEN mfslashexpansion(GEN mf, GEN F, GEN gamma, long n, long flrat, GEN *param, long prec); long mfspace(GEN mf, GEN f); GEN mfsplit(GEN mf, long dimlim, long flag); long mfsturm(GEN A); long mfsturmNgk(long N, GEN k); long mfsturmNk(long N, long k); long mfsturm_mf(GEN mf); GEN mfsymboleval(GEN F, GEN path, GEN ga, long bitprec); GEN mfsymbol(GEN mf, GEN F, long bitprec); GEN mftaylor(GEN F, long n, long flreal, long prec); GEN mftobasis(GEN mf, GEN F, long flag); GEN mftobasisES(GEN mf, GEN F); GEN mftocol(GEN F, long lim, long d); GEN mftocoset(ulong N, GEN M, GEN listcosets); GEN mftonew(GEN mf, GEN F); GEN mftraceform(GEN NK, long coderat); GEN mftwist(GEN F, GEN D); GEN mfvecembed(GEN E, GEN v); GEN mfvectomat(GEN vF, long lim, long d); /* mpker.c */ ulong Fl_inv(ulong x, ulong p); ulong Fl_invsafe(ulong x, ulong p); int Fp_ratlift(GEN x, GEN m, GEN amax, GEN bmax, GEN *a, GEN *b); GEN ZM2_mul(GEN A, GEN B); GEN ZM2_sqr(GEN A); int abscmpii(GEN x, GEN y); int abscmprr(GEN x, GEN y); int absequalii(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 addmulii(GEN x, GEN y, GEN z); GEN addmulii_inplace(GEN x, GEN y, GEN z); 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 addui_sign(ulong x, GEN y, long sy); 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); long cgcd(long a,long b); long clcm(long a,long b); 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 absdiviu_rem(GEN y, ulong x, ulong *rem); GEN diviuuexact(GEN x, ulong y, ulong z); GEN diviuexact(GEN x, ulong y); GEN divri(GEN x, GEN y); GEN divrr(GEN x, GEN y); GEN divrs(GEN x, long y); GEN divru(GEN x, ulong y); GEN divsi(long x, GEN y); GEN divsr(long x, GEN y); GEN divur(ulong x, GEN y); GEN dvmdii(GEN x, GEN y, GEN *z); int equalii(GEN x, GEN y); int equalrr(GEN x, GEN y); GEN floorr(GEN x); GEN gcdii(GEN x, GEN y); GEN halfgcdii(GEN x, GEN y); GEN int2n(long n); GEN int2u(ulong n); GEN int2um1(ulong n); GEN int_normalize(GEN x, long known_zero_words); int invmod(GEN a, GEN b, GEN *res); ulong invmod2BIL(ulong b); GEN invr(GEN b); GEN mantissa_real(GEN x, long *e); GEN modii(GEN x, GEN y); void modiiz(GEN x, GEN y, GEN z); GEN mulii(GEN x, GEN y); GEN mulir(GEN x, GEN y); GEN mulrr(GEN x, GEN y); GEN mulsi(long x, GEN y); GEN mulsr(long x, GEN y); GEN mulss(long x, long y); GEN mului(ulong x, GEN y); GEN mulur(ulong x, GEN y); GEN muluu(ulong x, ulong y); GEN muluui(ulong x, ulong y, GEN z); void pari_kernel_close(void); void pari_kernel_init(void); const char * pari_kernel_version(void); GEN remi2n(GEN x, long n); double rtodbl(GEN x); GEN shifti(GEN x, long n); GEN sqri(GEN x); GEN sqrr(GEN x); GEN sqrs(long x); GEN sqrtr_abs(GEN x); GEN sqrtremi(GEN S, GEN *R); GEN sqru(ulong x); GEN subsr(long x, GEN y); GEN truedvmdii(GEN x, GEN y, GEN *z); GEN truedvmdis(GEN x, long y, GEN *z); GEN truedvmdsi(long x, GEN y, GEN *z); GEN trunc2nr(GEN x, long n); GEN mantissa2nr(GEN x, long n); GEN truncr(GEN x); ulong ugcd(ulong a,ulong b); ulong ulcm(ulong a, ulong b); ulong umodiu(GEN y, ulong x); long vals(ulong x); /* nffactor.c */ GEN FpC_ratlift(GEN P, GEN mod, GEN amax, GEN bmax, GEN denom); GEN FpM_ratlift(GEN M, GEN mod, GEN amax, GEN bmax, GEN denom); GEN FpX_ratlift(GEN P, GEN mod, GEN amax, GEN bmax, GEN denom); GEN QXQX_gcd(GEN P, GEN Q, GEN T); GEN ZXQX_gcd(GEN P, GEN Q, GEN T); GEN nffactor(GEN nf,GEN x); GEN nffactormod(GEN nf,GEN pol,GEN pr); GEN nfgcd(GEN P, GEN Q, GEN nf, GEN den); GEN nfgcd_all(GEN P, GEN Q, GEN T, GEN den, GEN *Pnew); int nfissquarefree(GEN nf, GEN x); GEN nfroots(GEN nf,GEN pol); GEN nfroots_if_split(GEN *pnf, GEN pol); GEN nfrootsof1(GEN x); GEN polfnf(GEN a, GEN t); GEN rnfabelianconjgen(GEN nf, GEN P); long rnfisabelian(GEN nf, GEN pol); /* paricfg.c */ extern const char *paricfg_datadir; extern const char *paricfg_version; extern const char *paricfg_buildinfo; extern const long paricfg_version_code; extern const char *paricfg_vcsversion; extern const char *paricfg_compiledate; extern const char *paricfg_mt_engine; extern const char *paricfg_gphelp; /* part.c */ void forpart(void *E, long call(void*,GEN), long k, GEN nbound, GEN abound); void forpart_init(forpart_t *T, long k, GEN abound, GEN nbound); GEN forpart_next(forpart_t *T); GEN forpart_prev(forpart_t *T); GEN numbpart(GEN x); GEN partitions(long k, GEN nbound, GEN abound); /* forperm.c */ void forperm(void *E, long call(void *, GEN), GEN k); void forperm_init(forperm_t *T, GEN k); GEN forperm_next(forperm_t *T); /* forsubset.c */ void forallsubset_init(forsubset_t *T, long n); void forksubset_init(forsubset_t *T, long n, long k); GEN forsubset_next(forsubset_t *T); void forsubset_init(forsubset_t *T, GEN nk); /* lambert.c */ GEN glambertW(GEN y, long branch, long prec); GEN mplambertW(GEN y, long prec); GEN mplambertX(GEN y, long bit); GEN mplambertx_logx(GEN a, GEN b, long bit); GEN mplambertxlogx_x(GEN a, GEN b, long bit); /* perm.c */ GEN Z_to_perm(long n, GEN x); GEN abelian_group(GEN G); GEN conjclasses_repr(GEN conj, long nb); GEN cyc_pow(GEN cyc, long exp); GEN cyc_pow_perm(GEN cyc, long exp); GEN cyclicgroup(GEN g, long s); 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); GEN group_export_GAP(GEN G); GEN group_export_MAGMA(GEN G); 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); int group_subgroup_is_faithful(GEN G, GEN H); long group_subgroup_isnormal(GEN G, GEN H); GEN group_subgroups(GEN G); GEN groupelts_solvablesubgroups(GEN G); GEN group_to_cc(GEN G); GEN groupelts_abelian_group(GEN S); GEN groupelts_center(GEN S); GEN groupelts_conj_set(GEN elts, GEN p); GEN groupelts_conjclasses(GEN elts, long *nbcl); long groupelts_exponent(GEN G); GEN groupelts_quotient(GEN G, GEN H); GEN groupelts_set(GEN G, long n); GEN groupelts_to_group(GEN G); GEN numtoperm(long n, GEN x); int perm_commute(GEN p, GEN q); GEN perm_cycles(GEN v); GEN perm_order(GEN perm); ulong perm_orderu(GEN perm); GEN perm_pow(GEN perm, GEN exp); GEN perm_powu(GEN perm, ulong exp); long perm_sign(GEN perm); GEN perm_to_GAP(GEN v); GEN perm_to_Z(GEN v); GEN permcycles(GEN perm); GEN permorder(GEN perm); long permsign(GEN perm); GEN permtonum(GEN x); GEN quotient_group(GEN C, GEN G); GEN quotient_groupelts(GEN C); 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 vec_insert(GEN v, long n, GEN x); int vec_is1to1(GEN v); int vec_isconst(GEN v); GEN vecperm_orbits(GEN v, long n); long vecsmall_duplicate(GEN x); long vecsmall_duplicate_sorted(GEN x); GEN vecsmall_indexsort(GEN V); int vecsmall_is1to1(GEN v); int vecsmall_isconst(GEN v); void vecsmall_sort(GEN V); GEN vecsmall_uniq(GEN V); GEN vecsmall_uniq_sorted(GEN V); GEN vecsmall_counting_indexsort(GEN v, long M); void vecsmall_counting_sort(GEN v, long M); GEN vecsmall_counting_uniq(GEN v, long M); GEN vecvecsmall_indexsort(GEN x); long vecvecsmall_max(GEN x); long vecvecsmall_search(GEN x, GEN y); GEN vecvecsmall_sort(GEN x); void vecvecsmall_sort_inplace(GEN x, GEN *perm); GEN vecvecsmall_sort_shallow(GEN x); GEN vecvecsmall_sort_uniq(GEN x); /* mt.c */ void mt_broadcast(GEN code); long mt_nbthreads(void); void mt_queue_end(struct pari_mt *pt); GEN mt_queue_get(struct pari_mt *pt, long *jobid, long *pending); void mt_queue_start(struct pari_mt *pt, GEN worker); void mt_queue_start_lim(struct pari_mt *pt, GEN worker, long lim); void mt_queue_submit(struct pari_mt *pt, long jobid, GEN work); void mt_sigint_block(void); void mt_sigint_unblock(void); void pari_mt_init(void); void pari_mt_close(void); /* pclgp.c */ GEN subcyclopclgp(GEN fH, GEN p, long flag); GEN subcycloiwasawa(GEN fH, GEN p, long n); GEN subcyclohminus(GEN fH, GEN p); /* plotport.c */ void color_to_rgb(GEN c, int *r, int *g, int *b); void colorname_to_rgb(const char *s, int *r, int *g, int *b); void long_to_rgb(long c, int *r, int *g, int *b); void pari_plot_by_file(const char *env, const char *suf, const char *img); void pari_set_plot_engine(void (*plot)(PARI_plot *)); void pari_kill_plot_engine(void); GEN parploth(GEN a, GEN b, GEN code, long flags,long n, long prec); GEN parplothexport(GEN fmt, GEN a, GEN b, GEN code, long flags, long n, long prec); void plotarc(long ne, GEN gx2, GEN gy2, long fl); void plotbox(long ne, GEN gx2, GEN gy2, long fl); void plotclip(long rect); GEN plotcolor(long ne, GEN c); void plotcopy(long source, long dest, GEN xoff, GEN yoff, long flag); GEN plotcursor(long ne); void plotdraw(GEN list, long flag); GEN plotexport(GEN fmt, GEN wxy, long flag); GEN ploth(void *E, GEN(*f)(void*,GEN), GEN a, GEN b, long flags,long n, long prec); GEN plothexport(GEN fmt, void *E, GEN(*f)(void*,GEN), GEN a,GEN b, long flags, long n, long prec); GEN plothraw(GEN listx, GEN listy, long flag); GEN plothrawexport(GEN fmt, GEN X, GEN Y, long flags); GEN plothsizes(long flag); void plotinit(long ne, GEN x, GEN y, long flag); void plotkill(long ne); void plotline(long ne, GEN gx2, GEN gy2); void plotlines(long ne, GEN listx, GEN listy, long flag); void plotlinetype(long ne, long t); void plotmove(long ne, GEN x, GEN y); void plotpoints(long ne, GEN listx, GEN listy); void plotpointsize(long ne, GEN size); void plotpointtype(long ne, long t); void plotrbox(long ne, GEN x2, GEN y2, long fl); GEN plotrecth(void *E, GEN(*f)(void*,GEN), long ne, GEN a,GEN b, ulong flags,long n, long prec); GEN plotrecthraw(long ne, GEN data, long flags); void plotrline(long ne, GEN x2, GEN y2); void plotrmove(long ne, GEN x, GEN y); void plotrpoint(long ne, GEN x, GEN y); void plotscale(long ne, GEN x1, GEN x2, GEN y1, GEN y2); void plotstring(long ne, char *x, long dir); void psdraw(GEN list, long flag); GEN psploth(void *E, GEN(*f)(void*,GEN), GEN a, GEN b, long flags, long n, long prec); GEN psplothraw(GEN listx, GEN listy, long flag); char* rect2ps(GEN w, GEN x, GEN y, PARI_plot *T); char* rect2ps_i(GEN w, GEN x, GEN y, PARI_plot *T, int plotps); char* rect2svg(GEN w, GEN x, GEN y, PARI_plot *T); /* plottty.c */ void pariplot(void* E, GEN (*fun)(void *E, GEN x), GEN a, GEN b, GEN ysmlu,GEN ybigu, long prec); /* polarit1.c */ GEN ZX_Zp_root(GEN f, GEN a, GEN p, long prec); GEN Zp_appr(GEN f, GEN a); int cmp_padic(GEN x, GEN y); 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 polrootspadic(GEN f, GEN p, long r); /* polarit2.c */ ulong Flv_factorback(GEN L, GEN e, ulong p); GEN FlxqV_factorback(GEN L, GEN e, GEN Tp, ulong p); GEN FpV_factorback(GEN L, GEN e, GEN p); GEN FqV_factorback(GEN L, GEN e, GEN Tp, GEN p); GEN Q_content(GEN x); GEN Q_content_safe(GEN x); GEN Q_denom(GEN x); GEN Q_denom_safe(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 Q_factor(GEN x); GEN Q_factor_limit(GEN x, ulong lim); long Rg_type(GEN x, GEN *ptp, GEN *ptpol, long *ptpa); long RgM_RgC_type(GEN x, GEN y, GEN *p, GEN *pol, long *pa); GEN RgM_rescale_to_int(GEN x); long RgM_type(GEN x, GEN *p, GEN *pol, long *pa); long RgM_type2(GEN x, GEN y, GEN *p, GEN *pol, long *pa); long RgV_type(GEN x, GEN *p, GEN *pol, long *pa); long RgV_type2(GEN x, GEN y, GEN *p, GEN *pol, long *pa); long RgX_Rg_type(GEN x, GEN y, GEN *p, GEN *pol, long *pa); GEN RgX_chinese_coprime(GEN x, GEN y, GEN Tx, GEN Ty, GEN Tz); 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); GEN RgX_halfgcd(GEN x, GEN y); GEN RgX_halfgcd_all(GEN x, GEN y, GEN *a, GEN *b); GEN RgX_rescale_to_int(GEN x); GEN RgX_resultant_all(GEN P, GEN Q, GEN *sol); long RgX_sturmpart(GEN x, GEN ab); GEN RgX_sylvestermatrix(GEN x, GEN y); long RgX_type(GEN x, GEN *ptp, GEN *ptpol, long *ptpa); long RgX_type2(GEN x, GEN y, GEN *ptp, GEN *ptpol, long *ptpa); long RgX_type3(GEN x, GEN y, GEN z, GEN *ptp, GEN *ptpol, long *ptpa); void RgX_type_decode(long x, long *t1, long *t2); int RgX_type_is_composite(long t); GEN RgXQ_charpoly(GEN x, GEN T, long v); GEN RgXQ_inv(GEN x, GEN y); GEN RgXQ_minpoly(GEN x, GEN T, long v); GEN RgXQ_mul(GEN x, GEN y, GEN T); int RgXQ_ratlift(GEN y, GEN x, long amax, long bmax, GEN *P, GEN *Q); GEN RgXQ_sqr(GEN x, GEN y); GEN Z_content(GEN x); 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 content0(GEN x, GEN D); GEN deg1_from_roots(GEN L, long v); GEN factor(GEN x); GEN factor0(GEN x, GEN flag); GEN factorback(GEN fa); GEN factorback2(GEN fa,GEN e); GEN gbezout(GEN x, GEN y, GEN *u, GEN *v); GEN gdivexact(GEN x, GEN y); GEN gen_factorback(GEN L, GEN e, void *E, GEN (*_mul)(void*,GEN,GEN), GEN (*_pow)(void*,GEN,GEN), GEN (*_one)(void*)); GEN ggcd(GEN x, GEN y); GEN ggcd0(GEN x, GEN y); GEN ghalfgcd(GEN x, GEN y); GEN ginvmod(GEN x, GEN y); GEN glcm(GEN x, GEN y); GEN glcm0(GEN x, GEN y); GEN newtonpoly(GEN x, GEN p); GEN nfrootsQ(GEN x); GEN poldisc0(GEN x, long v); GEN polfromroots(GEN a, long v); long polisirreducible(GEN x); 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(GEN u, GEN v); GEN rnfcharpoly(GEN nf, GEN T, GEN alpha, long v); GEN roots_from_deg1(GEN x); GEN roots_to_pol(GEN a, long v); GEN roots_to_pol_r1(GEN a, long v, long r1); long sturmpart(GEN x, GEN a, GEN b); GEN subresext(GEN x, GEN y, GEN *U, GEN *V); GEN sylvestermatrix(GEN x,GEN y); GEN trivial_fact(void); GEN gcdext0(GEN x, GEN y); GEN polresultantext0(GEN x, GEN y, long v); GEN polresultantext(GEN x, GEN y); GEN prime_fact(GEN x); GEN row_Q_primpart(GEN M); GEN vec_Q_primpart(GEN M); GEN vecprod(GEN v); GEN ZV_lcm(GEN x); /* polarit3.c */ GEN Flx_FlxY_resultant(GEN a, GEN b, ulong p); GEN FlxX_resultant(GEN u, GEN v, ulong p, long sx); GEN FpX_FpXY_resultant(GEN a, GEN b0, GEN p); GEN FpX_translate(GEN P, GEN c, GEN p); GEN FpXQX_normalize(GEN z, GEN T, GEN p); GEN FpXV_FpC_mul(GEN V, GEN W, GEN p); GEN FpXY_FpXQ_evaly(GEN Q, GEN y, GEN T, GEN p, long vx); GEN FpXC_center(GEN C, GEN p, GEN pov2); GEN FpXM_center(GEN M, GEN p, GEN pov2); GEN Fq_Fp_mul(GEN x, GEN y, GEN T, GEN p); GEN Fq_add(GEN x, GEN y, GEN T/*unused*/, GEN p); GEN Fq_div(GEN x, GEN y, GEN T, GEN p); GEN Fq_halve(GEN x, GEN T/*unused*/, GEN p); GEN Fq_inv(GEN x, GEN T, GEN p); GEN Fq_invsafe(GEN x, GEN T, GEN p); GEN Fq_mul(GEN x, GEN y, GEN T, GEN p); GEN Fq_mulu(GEN x, ulong y, /*unused*/GEN T, GEN p); GEN Fq_neg(GEN x, GEN T, GEN p); GEN Fq_neg_inv(GEN x, GEN T, GEN p); GEN Fq_pow(GEN x, GEN n, GEN T, GEN p); GEN Fq_powu(GEN x, ulong n, GEN pol, GEN p); GEN Fq_sqr(GEN x, GEN T, GEN p); GEN Fq_sqrt(GEN x, GEN T, GEN p); GEN Fq_sqrtn(GEN x, GEN n, GEN T, GEN p, GEN *zeta); GEN Fq_sub(GEN x, GEN y, GEN T/*unused*/, GEN p); GEN FqC_Fq_mul(GEN x, GEN y, GEN T, GEN p); GEN FqC_FqV_mul(GEN x, GEN y, GEN T, GEN p); GEN FqC_add(GEN x, GEN y, GEN T, GEN p); GEN FqC_sub(GEN x, GEN y, GEN T, GEN p); GEN FqV_red(GEN z, GEN T, GEN p); GEN FqV_roots_to_pol(GEN V, GEN T, GEN p, long v); GEN FqX_Fq_add(GEN y, GEN x, GEN T, GEN p); GEN FqX_Fq_mul_to_monic(GEN P, GEN U, GEN T, GEN p); GEN FqX_Fq_sub(GEN y, GEN x, GEN T, GEN p); GEN FqX_eval(GEN x, GEN y, GEN T, GEN p); GEN FqX_translate(GEN P, GEN c, GEN T, GEN p); GEN FqXQ_matrix_pow(GEN y, long n, long m, GEN S, GEN T, GEN p); GEN FqXQ_powers(GEN x, long l, GEN S, GEN T, GEN p); GEN FqXY_eval(GEN Q, GEN y, GEN x, GEN T, GEN p); GEN FqXY_evalx(GEN Q, GEN x, GEN T, GEN p); GEN QX_disc(GEN x); GEN QX_gcd(GEN a,GEN b); GEN QX_resultant(GEN A, GEN B); GEN QXQ_div(GEN A, GEN B, GEN C); GEN QXQ_intnorm(GEN A, GEN B); GEN QXQ_inv(GEN A, GEN B); GEN QXQ_mul(GEN A, GEN B, GEN T); GEN QXQ_norm(GEN A, GEN B); GEN QXQ_sqr(GEN A, GEN B); int Rg_is_Fp(GEN x, GEN *p); int Rg_is_FpXQ(GEN x, GEN *pT, GEN *pp); GEN Rg_to_Fp(GEN x, GEN p); GEN Rg_to_FpXQ(GEN x, GEN T, GEN p); GEN RgC_to_FpC(GEN x, GEN p); GEN RgC_to_FqC(GEN x, GEN T, GEN p); int RgM_is_FpM(GEN x, GEN *p); GEN RgM_to_Flm(GEN x, ulong p); GEN RgM_to_FpM(GEN x, GEN p); GEN RgM_to_FqM(GEN x, GEN T, GEN p); int RgV_is_FpV(GEN x, GEN *p); GEN RgV_to_Flv(GEN x, ulong 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); int Z_incremental_CRT(GEN *H, ulong Hp, GEN *q, ulong p); GEN Z_init_CRT(ulong Hp, ulong p); int ZM_incremental_CRT(GEN *H, GEN Hp, GEN *q, ulong p); GEN ZM_init_CRT(GEN Hp, ulong p); GEN ZX_ZXY_resultant(GEN a, GEN b); GEN ZX_ZXY_rnfequation(GEN A, GEN B, long *lambda); GEN ZX_disc(GEN x); GEN ZX_gcd(GEN A, GEN B); GEN ZX_gcd_all(GEN A, GEN B, GEN *Anew); int ZX_incremental_CRT(GEN *ptH, GEN Hp, GEN *q, ulong p); GEN ZX_init_CRT(GEN Hp, ulong p, long v); int ZX_is_squarefree(GEN x); GEN ZX_radical(GEN A); GEN ZX_resultant(GEN A, GEN B); int ZXM_incremental_CRT(GEN *pH, GEN Hp, GEN *ptq, ulong p); GEN ZXM_init_CRT(GEN Hp, long deg, ulong p); GEN ZXQ_minpoly(GEN A, GEN T, long d, ulong b); GEN ZXQ_charpoly(GEN A, GEN T, long v); GEN characteristic(GEN x); GEN ffinit(GEN p, long n, long v); GEN ffnbirred(GEN p, long n); GEN ffnbirred0(GEN p, long n, long flag); GEN ffsumnbirred(GEN p, long n); const struct bb_field *get_Fq_field(void **E, GEN T, GEN p); GEN init_Flxq(ulong p, long n, long v); GEN init_Fq(GEN p, long n, long v); GEN nfX_disc(GEN nf, GEN x); GEN nfX_resultant(GEN nf, GEN x, GEN y); GEN pol_x_powers(long N, long v); GEN residual_characteristic(GEN x); /* polclass.c */ GEN polclass(GEN D, long inv, long vx); /* polmodular.c */ GEN Fp_modinv_to_j(GEN x, long inv, GEN p); GEN Fp_polmodular_evalx(long L, long inv, GEN J, GEN P, long v, int compute_derivs); void check_modinv(long inv); long disc_best_modinv(long D); long modinv_height_factor(long inv); int modinv_good_disc(long inv, long D); int modinv_good_prime(long inv, long p); int modinv_is_Weber(long inv); int modinv_is_double_eta(long inv); GEN polmodular(long L, long inv, GEN x, long vy, long compute_derivs); GEN polmodular_ZM(long L, long inv); GEN polmodular_ZXX(long L, long inv, long vx, long vy); /* prime.c */ long BPSW_isprime(GEN x); long BPSW_psp(GEN N); GEN addprimes(GEN primes); long check_ecppcert(GEN c); GEN gisprime(GEN x, long flag); GEN gispseudoprime(GEN x, long flag); GEN gprimepi_upper_bound(GEN x); GEN gprimepi_lower_bound(GEN x); long isprime(GEN x); long ispseudoprime(GEN x, long flag); long millerrabin(GEN n, long k); GEN prime(long n); long PRIMES_search(ulong x); GEN primecert(GEN x, long flag); GEN primecert0(GEN x, long flag, long stopat); GEN primecertexport(GEN cert, long flag); long primecertisvalid(GEN x); GEN primepi(GEN x); double primepi_upper_bound(double x); double primepi_lower_bound(double x); GEN primes(long n); GEN primes_interval(GEN a, GEN b); GEN primes_interval_zv(ulong a, ulong b); GEN primes_upto_zv(ulong b); GEN primes0(GEN n); GEN primes_zv(long m); GEN randomprime(GEN N); GEN randomprime0(GEN N, GEN q); GEN removeprimes(GEN primes); int uis2psp(ulong n); int uispsp(ulong a, ulong n); int uislucaspsp(ulong n); int uisprime(ulong n); int uisprime_101(ulong n); int uisprime_661(ulong n); ulong uprime(long n); ulong uprimepi(ulong n); /* qfisom.c */ GEN qfauto(GEN g, GEN flags); GEN qfauto0(GEN g, GEN flags); GEN qfautoexport(GEN g, long flag); GEN qfisom(GEN g, GEN h, GEN flags, GEN G); GEN qfisom0(GEN g, GEN h, GEN flags, GEN G); GEN qfisominit(GEN g, GEN flags, GEN minvec); GEN qfisominit0(GEN g, GEN flags, GEN minvec); GEN qforbits(GEN G, GEN V); /* qfparam.c */ GEN qfminimize(GEN G); GEN qfparam(GEN G, GEN sol, long fl); GEN qfsolve(GEN G); /* quad.c */ long Z_isfundamental(GEN x); GEN classno(GEN x); GEN classno2(GEN x); GEN hclassnoF_fact(GEN P, GEN E, GEN D); GEN hclassno(GEN x); GEN hclassno6(GEN x); long isfundamental(GEN x); int qfb_equal1(GEN f); GEN qfbclassno0(GEN x,long flag); GEN qfi_Shanks(GEN a, GEN g, long n); GEN qfi_log(GEN a, GEN g, GEN o); GEN qfi_order(GEN q, GEN o); GEN quadclassnoF(GEN x, GEN *pD); GEN quadclassnoF_fact(GEN D, GEN P, GEN E); GEN quaddisc(GEN x); GEN quadregulator(GEN x, long prec); GEN quadunit(GEN x); GEN quadunit0(GEN x, long v); GEN quadunitindex(GEN x, GEN N); long quadunitnorm(GEN x); long sisfundamental(long x); long uhclassnoF_fact(GEN faF, long D); long unegisfundamental(ulong x); ulong unegquadclassnoF(ulong x, ulong *pD); long uposisfundamental(ulong x); ulong uposquadclassnoF(ulong x, ulong *pD); ulong uquadclassnoF_fact(ulong d, long s, GEN P, GEN E); GEN Zn_quad_roots(GEN N, GEN B, GEN C); /* random.c */ GEN genrand(GEN N); GEN getrand(void); ulong pari_rand(void); GEN randomi(GEN x); GEN randomr(long prec); GEN random_F2x(long d, long vs); ulong random_Fl(ulong n); long random_bits(long k); GEN random_zv(long n); void setrand(GEN seed); /* ratpoints.c */ GEN ellratpoints(GEN E, GEN h, long flag); GEN hyperellratpoints(GEN P, GEN h, long flag); /* rootpol.c */ GEN QX_complex_roots(GEN p, long l); GEN FFT(GEN W, GEN x); GEN FFTinv(GEN W, GEN x); GEN cleanroots(GEN x,long l); double fujiwara_bound(GEN p); double fujiwara_bound_real(GEN p, long sign); int isrealappr(GEN x, long l); GEN polgraeffe(GEN p); GEN polmod_to_embed(GEN x, long prec); GEN polrootsbound(GEN p, GEN tau); GEN roots(GEN x,long l); GEN realroots(GEN P, GEN ab, long prec); GEN ZX_graeffe(GEN p); GEN ZX_realroots_irred(GEN P, long prec); long ZX_sturm(GEN P); long ZX_sturm_irred(GEN P); long ZX_sturmpart(GEN P, GEN ab); GEN ZX_Uspensky(GEN P, GEN ab, long flag, long prec); /* subcyclo.c */ GEN factor_Aurifeuille(GEN p, long n); GEN factor_Aurifeuille_prime(GEN p, long n); GEN galoissubcyclo(GEN N, GEN sg, long flag, long v); GEN polsubcyclo(long n, long d, long v); GEN polsubcyclofast(GEN n, long ell, long s, long fli); GEN znsubgroupgenerators(GEN H, long flag); /* subfield.c */ GEN nfsubfields(GEN nf, long d); GEN nfsubfields0(GEN nf, long d, long flag); GEN nfsubfieldscm(GEN nf, long flag); GEN nfsubfieldsmax(GEN nf, long flag); /* nflist.c */ GEN nflist(GEN GP, GEN V, long s, GEN field); GEN nfresolvent(GEN pol, long flag); /* subgroup.c */ GEN subgrouplist(GEN cyc, GEN bound); void forsubgroup(void *E, long fun(void*,GEN), GEN cyc, GEN B); /* stark.c */ GEN abmap_kernel(GEN S); GEN abmap_subgroup_image(GEN S, GEN H); 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); GEN bnrstarkunit(GEN bnr, GEN subgroup); GEN cyc2elts(GEN cyc); GEN qfbforms(GEN D); GEN quadhilbert(GEN D, long prec); GEN quadray(GEN bnf, GEN f, long prec); /* str.c */ GEN chartoGENstr(char c); GEN pari_base64(const char *s); char* pari_strdup(const char *s); char* pari_strndup(const char *s, long n); GEN pari_strchr(GEN g); char* stack_strcat(const char *s, const char *t); char* stack_strdup(const char *s); GEN strjoin(GEN v, GEN p); GEN strntoGENstr(const char *s, long n0); GEN strsplit(GEN x, GEN p); GEN strtoGENstr(const char *s); const char* type_name(long t); GEN type0(GEN x); /* sumiter.c */ GEN asympnum(void *E, GEN (*f)(void *,GEN,long), GEN alpha, long prec); GEN asympnumraw(void *E, GEN (*f)(void *,GEN,long), long LIM, GEN alpha, long prec); GEN derivnum(void *E, GEN (*eval)(void *, GEN, long prec), GEN x, long prec); GEN derivnumk(void *E, GEN (*eval)(void *, GEN, long), GEN x, GEN ind0, long prec); GEN derivfun(void *E, GEN (*eval)(void *, GEN, long prec), GEN x, long prec); GEN derivfunk(void *E, GEN (*eval)(void *, GEN, long), GEN x, GEN ind0, long prec); int forvec_init(forvec_t *T, GEN x, long flag); GEN forvec_next(forvec_t *T); GEN laurentseries(void *E, GEN (*f)(void*,GEN x, long), long M, long v, long prec); GEN limitnum(void *E, GEN (*f)(void *,GEN,long), GEN alpha, long prec); 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 solvestep(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, GEN step, long flag, 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 sumdivmultexpr(void *D, GEN (*fun)(void*, GEN), GEN num); GEN zbrent(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, long prec); /* thue.c */ GEN bnfisintnorm(GEN x, GEN y); GEN bnfisintnorm0(GEN x, GEN y, long flag); GEN bnfisintnormabs(GEN bnf, GEN a); GEN bnfisintnormabs0(GEN bnf, GEN a, long flag); GEN ideals_by_norm(GEN nf, 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); long Qp_exp_prec(GEN x); GEN Qp_log(GEN x); GEN Qp_sqrt(GEN x); GEN Qp_sqrtn(GEN x, GEN n, GEN *zetan); GEN Zn_sqrt(GEN x, GEN n); GEN Zp_teichmuller(GEN x, GEN p, long n, GEN q); GEN agm(GEN x, GEN y, long prec); GEN constcatalan(long prec); GEN consteuler(long prec); GEN constlog2(long prec); GEN constpi(long prec); GEN cxexpm1(GEN z, long prec); GEN ellE(GEN k, long prec); GEN ellK(GEN k, long prec); GEN expIr(GEN x); GEN exp1r_abs(GEN x); GEN gcos(GEN x, long prec); GEN gcotan(GEN x, long prec); GEN gcotanh(GEN x, long prec); GEN gexp(GEN x, long prec); GEN gexpm1(GEN x, long prec); GEN glog(GEN x, long prec); GEN glog1p(GEN x, long prec); GEN gpow(GEN x, GEN n, long prec); GEN gpowers(GEN x, long n); GEN gpowers0(GEN x, long n, GEN x0); GEN gpowgs(GEN x, long n); GEN grootsof1(long N, long prec); GEN gsin(GEN x, long prec); GEN gsinc(GEN x, long prec); void gsincos(GEN x, GEN *s, GEN *c, long prec); GEN gsqrpowers(GEN q, long n); GEN gsqrt(GEN x, long prec); GEN gsqrtn(GEN x, GEN n, GEN *zetan, long prec); GEN gtan(GEN x, long prec); GEN logr_abs(GEN x); GEN mpcos(GEN x); GEN mpeuler(long prec); GEN mpcatalan(long prec); void mpsincosm1(GEN x, GEN *s, GEN *c); GEN mpexp(GEN x); GEN mpexpm1(GEN x); GEN mplog(GEN x); GEN mplog2(long prec); GEN mppi(long prec); GEN mpsin(GEN x); void mpsincos(GEN x, GEN *s, GEN *c); GEN pow2Pis(GEN s, long prec); GEN powPis(GEN s, long prec); GEN powcx(GEN x, GEN logx, GEN n, long prec); long powcx_prec(long ex, GEN n, long prec); GEN powersr(GEN a, long n); GEN powis(GEN x, long n); GEN powiu(GEN p, ulong k); GEN powrfrac(GEN x, long n, long d); 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 rootsof1_cx(GEN d, long prec); GEN rootsof1u_cx(ulong d, long prec); GEN rootsof1q_cx(long a, long b, long prec); GEN rootsof1powinit(long a, long b, long prec); GEN rootsof1pow(GEN T, long c); GEN serchop(GEN s, long n); GEN serchop_i(GEN s, long n); GEN serchop0(GEN s); GEN sqrtnint(GEN a, long n); GEN sqrtnr_abs(GEN x, long n); GEN teich(GEN x); GEN teichmullerinit(long p, long n); GEN teichmuller(GEN x, GEN tab); GEN trans_eval(const char *fun, GEN (*f) (GEN, long), GEN x, long prec); GEN trans_evalgen(const char *fun, void *E, GEN (*f) (void*,GEN,long), GEN x, long prec); ulong upowuu(ulong p, ulong k); GEN upowers(ulong x, long n); ulong usqrtn(ulong a, ulong n); ulong usqrt(ulong a); /* trans2.c */ GEN Qp_gamma(GEN x); GEN Qp_psi(GEN x, long k); GEN atanhuu(ulong u, ulong v, long prec); GEN atanhui(ulong u, GEN v, long prec); GEN gacosh(GEN x, long prec); GEN gacos(GEN x, long prec); GEN garg(GEN x, long prec); GEN gasinh(GEN x, long prec); GEN gasin(GEN x, long prec); GEN gatan(GEN x, long prec); GEN gatanh(GEN x, long prec); GEN gcosh(GEN x, long prec); GEN ggammah(GEN x, long prec); GEN ggamma(GEN x, long prec); GEN ggamma1m1(GEN x, long prec); GEN glngamma(GEN x, long prec); GEN gpsi(GEN x, long prec); GEN gpsi_der(GEN x, long k, long prec); GEN gsinh(GEN x, long prec); GEN gtanh(GEN x, long prec); GEN mpfactr(long n, long prec); void mpsinhcosh(GEN x, GEN *s, GEN *c); GEN psi1series(long n, long v, long prec); GEN sumformal(GEN T, long v); /* trans3.c */ int RgV_is_arithprog(GEN v, GEN *a, GEN *b); GEN besseljzero(GEN nu, long n, long b); GEN besselyzero(GEN nu, long n, long b); GEN constzeta(long n, long prec); GEN cxEk(GEN tau, long k, long prec); double dblmodulus(GEN x); GEN dilog(GEN x, long prec); GEN eint1(GEN x, long prec); GEN expIPiR(GEN x, long prec); GEN expIPiC(GEN z, long prec); GEN expIxy(GEN x, GEN y, 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 hbessel1(GEN n, GEN z, long prec); GEN hbessel2(GEN n, GEN z, long prec); GEN hyperu(GEN a, GEN b, GEN gx, long prec); GEN ibessel(GEN n, GEN z, long prec); GEN incgam(GEN a, GEN x, long prec); GEN incgam0(GEN a, GEN x, GEN z,long prec); GEN incgamc(GEN a, GEN x, long prec); GEN jbessel(GEN n, GEN z, long prec); GEN jbesselh(GEN n, GEN z, long prec); GEN jell(GEN x, long prec); GEN kbessel(GEN nu, GEN gx, long prec); GEN mpeint1(GEN x, GEN expx); GEN mpveceint1(GEN C, GEN eC, long n); GEN polylog0(long m, GEN x, long flag, long prec); GEN sumdedekind(GEN h, GEN k); GEN sumdedekind_coprime(GEN h, GEN k); GEN szeta(long x, long prec); GEN theta(GEN q, GEN z, long prec); GEN thetanullk(GEN q, long k, long prec); GEN trueeta(GEN x, long prec); GEN u_sumdedekind_coprime(long h, long k); GEN upper_to_cx(GEN x, long *prec); GEN veceint1(GEN nmax, GEN C, long prec); GEN vecthetanullk(GEN q, long k, long prec); GEN vecthetanullk_tau(GEN tau, long k, long prec); GEN veczeta(GEN a, GEN b, long N, long prec); GEN weber0(GEN x, long flag,long prec); GEN weberf(GEN x, long prec); GEN weberf1(GEN x, long prec); GEN weberf2(GEN x, long prec); GEN ybessel(GEN n, GEN z, long prec); /* modsym.c */ GEN SL2_inv_shallow(GEN M); GEN Qevproj_apply(GEN T, GEN pro); GEN Qevproj_apply_vecei(GEN T, GEN pro, long k); GEN Qevproj_down(GEN T, GEN pro); GEN Qevproj_init(GEN M); GEN RgX_act_Gl2Q(GEN g, long k); GEN RgX_act_ZGl2Q(GEN z, long k); void checkms(GEN W); void checkmspadic(GEN W); GEN ellpadiclambdamu(GEN E, long p, long D, long R); GEN mfnumcusps(GEN n); GEN mfnumcusps_fact(GEN fa); ulong mfnumcuspsu_fact(GEN fa); ulong mfnumcuspsu(ulong n); GEN msfromcusp(GEN W, GEN c); GEN msfromell(GEN E, long signe); GEN msfromhecke(GEN W, GEN v, GEN H); long msdim(GEN W); GEN mseval2_ooQ(GEN W, GEN xpm, GEN c); long msgetlevel(GEN W); long msgetsign(GEN W); long msgetweight(GEN W); GEN msatkinlehner(GEN W, long Q, GEN); GEN mscuspidal(GEN W, long flag); GEN mseisenstein(GEN W); GEN mseval(GEN W, GEN s, GEN p); GEN mshecke(GEN W, long p, GEN H); GEN msinit(GEN N, GEN k, long sign); GEN msissymbol(GEN W, GEN s); GEN mslattice(GEN M, GEN F); GEN msomseval(GEN W, GEN phi, GEN path); void mspadic_parse_chi(GEN s, GEN *s1, GEN *s2); GEN mspadic_unit_eigenvalue(GEN ap, long k, GEN p, long n); GEN mspadicinit(GEN W, long p, long n, long flag); GEN mspadicL(GEN oms, GEN s, long r); GEN mspadicmoments(GEN W, GEN phi, long D); GEN mspadicseries(GEN M, long teichi); GEN mspathgens(GEN W); GEN mspathlog(GEN W, GEN path); GEN msnew(GEN W); GEN mspetersson(GEN W, GEN F1, GEN F2); GEN mspolygon(GEN M, long flag); GEN msstar(GEN W, GEN); GEN msqexpansion(GEN W, GEN proV, ulong B); GEN mssplit(GEN W, GEN H, long deglim); GEN mstooms(GEN W, GEN phi); /* mscosets.c */ GEN mscosets0(GEN V, GEN code); GEN mscosets(GEN V, void *E, long (*in)(void *, GEN)); GEN msfarey(GEN F, void *E, long (*in)(void *, GEN), GEN *pCM); GEN msfarey0(GEN F, GEN code, GEN *pCM); int checkfarey_i(GEN F); /* zetamult.c */ GEN polylogmult(GEN avec, GEN zvec, long prec); GEN polylogmult_interpolate(GEN avec, GEN zvec, GEN t, long prec); GEN zetamult(GEN avec, long prec); GEN zetamultdual(GEN s); GEN zetamult_interpolate(GEN avec, GEN t, long prec); GEN zetamultall(long k, long flag, long prec); GEN zetamultconvert(GEN a, long fl); /* level1.h */ INLINE ulong Fl_add(ulong a, ulong b, ulong p); INLINE ulong Fl_addmul_pre(ulong x0, ulong x1, ulong y0, ulong p, ulong pi); INLINE ulong Fl_addmulmul_pre(ulong x0, ulong y0, ulong x1, ulong y1, ulong p, ulong pi); INLINE long Fl_center(ulong u, ulong p, ulong ps2); INLINE ulong Fl_div(ulong a, ulong b, ulong p); INLINE ulong Fl_double(ulong a, ulong p); INLINE ulong Fl_ellj_pre(ulong a4, ulong a6, ulong p, ulong pi); INLINE ulong Fl_halve(ulong y, ulong p); INLINE ulong Fl_mul(ulong a, ulong b, ulong p); INLINE ulong Fl_mul_pre(ulong a, ulong b, ulong p, ulong pi); INLINE ulong Fl_neg(ulong x, ulong p); INLINE ulong Fl_sqr(ulong a, ulong p); INLINE ulong Fl_sqr_pre(ulong a, ulong p, ulong pi); INLINE ulong Fl_sub(ulong a, ulong b, ulong p); INLINE ulong Fl_triple(ulong a, ulong p); INLINE ulong Mod2(GEN x); INLINE ulong Mod4(GEN x); INLINE ulong Mod8(GEN x); INLINE ulong Mod16(GEN x); INLINE ulong Mod32(GEN x); INLINE ulong Mod64(GEN x); INLINE int abscmpiu(GEN x, ulong y); INLINE int abscmpui(ulong x, GEN y); INLINE int absequaliu(GEN x, ulong y); INLINE GEN absi(GEN x); INLINE GEN absi_shallow(GEN x); INLINE GEN absr(GEN x); INLINE int absrnz_equal1(GEN x); INLINE int absrnz_equal2n(GEN x); INLINE GEN addii(GEN x, GEN y); INLINE void addiiz(GEN x, GEN y, GEN z); INLINE GEN addir(GEN x, GEN y); INLINE void addirz(GEN x, GEN y, GEN z); INLINE GEN addis(GEN x, long s); INLINE GEN addri(GEN x, GEN y); INLINE void addriz(GEN x, GEN y, GEN z); INLINE GEN addrr(GEN x, GEN y); INLINE void addrrz(GEN x, GEN y, GEN z); INLINE GEN addrs(GEN x, long s); INLINE GEN addsi(long x, GEN y); INLINE void addsiz(long s, GEN y, GEN z); INLINE void addsrz(long s, GEN y, GEN z); INLINE GEN addss(long x, long y); INLINE void addssz(long s, long y, GEN z); INLINE GEN adduu(ulong x, ulong y); INLINE void affgr(GEN x, GEN y); INLINE void affii(GEN x, GEN y); INLINE void affiz(GEN x, GEN y); INLINE void affrr_fixlg(GEN y, GEN z); INLINE void affsi(long s, GEN x); INLINE void affsr(long s, GEN x); INLINE void affsz(long x, GEN y); INLINE void affui(ulong s, GEN x); INLINE void affur(ulong s, GEN x); INLINE GEN cgetg(long x, long y); INLINE GEN cgetg_block(long x, long y); INLINE GEN cgetg_copy(GEN x, long *plx); INLINE GEN cgeti(long x); INLINE GEN cgetineg(long x); INLINE GEN cgetipos(long x); INLINE GEN cgetr(long x); INLINE GEN cgetr_block(long prec); INLINE int cmpir(GEN x, GEN y); INLINE int cmpis(GEN x, long y); INLINE int cmpiu(GEN x, ulong y); INLINE int cmpri(GEN x, GEN y); INLINE int cmprs(GEN x, long y); INLINE int cmpsi(long x, GEN y); INLINE int cmpsr(long x, GEN y); INLINE int cmpss(long a, long b); INLINE int cmpui(ulong x, GEN y); INLINE int cmpuu(ulong a, ulong b); 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 equalsi(long x, GEN y); INLINE int equalui(ulong x, GEN y); INLINE int equaliu(GEN x, ulong y); INLINE int absequalui(ulong x, GEN y); INLINE ulong ceildivuu(ulong a, ulong b); INLINE long evalexpo(long x); INLINE long evallg(long x); INLINE long evalprecp(long x); INLINE long evalvalp(long x); INLINE long evalvalser(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 int gc_bool(pari_sp av, int s); INLINE GEN gc_const(pari_sp av, GEN x); INLINE double gc_double(pari_sp av, double d); INLINE int gc_int(pari_sp av, int s); INLINE long gc_long(pari_sp av, long s); INLINE GEN gc_stoi(pari_sp av, long x); INLINE ulong gc_ulong(pari_sp av, ulong s); INLINE GEN gc_utoi(pari_sp av, ulong x); INLINE GEN gc_utoipos(pari_sp av, ulong x); INLINE GEN gc_NULL(pari_sp av); INLINE GEN icopy(GEN x); INLINE GEN icopyspec(GEN x, long nx); INLINE GEN icopy_avma(GEN x, pari_sp av); INLINE ulong int_bit(GEN x, long n); INLINE GEN itor(GEN x, long prec); INLINE long itos(GEN x); INLINE long itos_or_0(GEN x); INLINE ulong itou(GEN x); INLINE ulong itou_or_0(GEN x); INLINE GEN leafcopy(GEN x); INLINE GEN leafcopy_avma(GEN x, pari_sp av); INLINE long lg2prec(long 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 mpabs_shallow(GEN x); INLINE GEN mpadd(GEN x, GEN y); INLINE void mpaddz(GEN x, GEN y, GEN z); INLINE void mpaff(GEN x, GEN y); INLINE GEN mpceil(GEN x); INLINE int mpcmp(GEN x, GEN y); INLINE GEN mpcopy(GEN x); INLINE GEN mpdiv(GEN x, GEN y); INLINE long mpexpo(GEN x); INLINE GEN mpfloor(GEN x); INLINE GEN mpmul(GEN x, GEN y); INLINE void mpmulz(GEN x, GEN y, GEN z); INLINE GEN mpneg(GEN x); INLINE int mpodd(GEN x); INLINE GEN mpround(GEN x); INLINE GEN mpshift(GEN x,long s); INLINE GEN mpsqr(GEN x); INLINE GEN mpsub(GEN x, GEN y); INLINE void mpsubz(GEN x, GEN y, GEN z); INLINE GEN mptrunc(GEN x); INLINE void muliiz(GEN x, GEN y, GEN z); INLINE void mulirz(GEN x, GEN y, GEN z); INLINE GEN mulis(GEN x, long s); INLINE GEN muliu(GEN x, ulong s); INLINE GEN mulri(GEN x, GEN s); INLINE void mulriz(GEN x, GEN y, GEN z); INLINE void mulrrz(GEN x, GEN y, GEN z); INLINE GEN mulrs(GEN x, long s); INLINE GEN mulru(GEN x, ulong s); INLINE void mulsiz(long s, GEN y, GEN z); INLINE void mulsrz(long s, GEN y, GEN z); INLINE void mulssz(long s, long y, GEN z); INLINE long nbits2lg(long x); INLINE GEN negi(GEN x); INLINE GEN negr(GEN x); INLINE GEN new_chunk(size_t x); INLINE GEN rcopy(GEN x); INLINE GEN rdivii(GEN x, GEN y, long prec); INLINE void rdiviiz(GEN x, GEN y, GEN z); INLINE GEN rdivis(GEN x, long y, long prec); INLINE GEN rdivsi(long x, GEN y, long prec); INLINE GEN rdivss(long x, long y, long prec); INLINE GEN real2n(long n, long prec); INLINE GEN real_m2n(long n, long prec); INLINE GEN real_0(long prec); INLINE GEN real_0_bit(long bitprec); INLINE GEN real_1(long prec); INLINE GEN real_1_bit(long bit); 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 ulong remlll_pre(ulong u2, ulong u1, ulong u0, ulong p, ulong pi); INLINE GEN remsi(long x, GEN y); INLINE void remsiz(long s, GEN y, GEN z); INLINE GEN remss(long x, long y); INLINE void remssz(long s, long y, GEN z); INLINE GEN rtor(GEN x, long prec); INLINE long sdivsi(long x, GEN y); INLINE long sdivsi_rem(long x, GEN y, long *rem); INLINE long sdivss_rem(long x, long y, long *rem); INLINE ulong get_avma(void); INLINE void set_avma(ulong av); INLINE ulong uabsdiviu_rem(GEN n, ulong d, ulong *r); INLINE ulong udivuu_rem(ulong x, ulong y, ulong *r); INLINE ulong umodi2n(GEN x, long n); INLINE void setabssign(GEN x); INLINE void shift_left(GEN z2, GEN z1, long min, long M, ulong f, ulong sh); INLINE void shift_right(GEN z2, GEN z1, long min, long M, ulong f, ulong sh); INLINE ulong shiftl(ulong x, ulong y); INLINE ulong shiftlr(ulong x, ulong y); INLINE GEN shiftr(GEN x, long n); INLINE void shiftr_inplace(GEN z, long d); INLINE long smodis(GEN x, long y); INLINE long smodss(long x, long y); INLINE void stackdummy(pari_sp av, pari_sp ltop); INLINE char *stack_malloc(size_t N); INLINE char *stack_malloc_align(size_t N, long k); INLINE char *stack_calloc(size_t N); INLINE char *stack_calloc_align(size_t N, long k); 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 uabsdivui_rem(ulong x, GEN y, ulong *rem); INLINE ulong umodsu(long x, ulong y); INLINE ulong umodui(ulong x, GEN y); INLINE ulong ugcdiu(GEN x, ulong y); INLINE ulong ugcdui(ulong y, GEN x); INLINE ulong umuluu_le(ulong x, ulong y, ulong n); INLINE ulong umuluu_or_0(ulong x, ulong 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); INLINE int varncmp(long x, long y); INLINE long varnmax(long x, long y); INLINE long varnmin(long x, long y); /* pariinl.h */ INLINE GEN ZM_ZV_mod(GEN x, GEN y); INLINE GEN ZV_ZV_mod(GEN x, GEN y); INLINE GEN abgrp_get_cyc(GEN x); INLINE GEN abgrp_get_gen(GEN x); INLINE GEN abgrp_get_no(GEN x); INLINE GEN bid_get_MOD(GEN bid); INLINE GEN bid_get_U(GEN bid); INLINE GEN bid_get_arch(GEN bid); INLINE GEN bid_get_archp(GEN bid); INLINE GEN bid_get_cyc(GEN bid); INLINE GEN bid_get_fact(GEN bid); INLINE GEN bid_get_fact2(GEN bid); INLINE GEN bid_get_gen(GEN bid); INLINE GEN bid_get_gen_nocheck(GEN bid); INLINE GEN bid_get_grp(GEN bid); INLINE GEN bid_get_ideal(GEN bid); INLINE GEN bid_get_mod(GEN bid); INLINE GEN bid_get_no(GEN bid); INLINE GEN bid_get_sarch(GEN bid); INLINE GEN bid_get_sprk(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_sunits(GEN bnf); INLINE GEN bnf_get_tuU(GEN bnf); INLINE GEN bnr_get_bid(GEN bnr); 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_mod(GEN bnr); INLINE GEN bnr_get_nf(GEN bnr); INLINE GEN bnr_get_no(GEN bnr); INLINE GEN cyc_get_expo(GEN c); INLINE GEN ellQp_get_p(GEN E); INLINE GEN ellQp_get_zero(GEN x); 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 ellff_get_a4a6(GEN x); INLINE GEN ellff_get_field(GEN x); INLINE GEN ellinf(void); INLINE GEN ellnf_get_bnf(GEN x); INLINE GEN ellnf_get_nf(GEN x); INLINE GEN gal_get_den(GEN gal); INLINE GEN gal_get_e(GEN gal); INLINE GEN gal_get_gen(GEN gal); INLINE GEN gal_get_group(GEN gal); INLINE GEN gal_get_invvdm(GEN gal); INLINE GEN gal_get_mod(GEN gal); INLINE GEN gal_get_orders(GEN gal); INLINE GEN gal_get_p(GEN gal); INLINE GEN gal_get_pol(GEN gal); INLINE GEN gal_get_roots(GEN gal); INLINE GEN idealchineseinit(GEN nf, GEN x); INLINE GEN idealred(GEN nf, GEN id); INLINE GEN modpr_get_T(GEN x); INLINE GEN modpr_get_p(GEN x); INLINE GEN modpr_get_pr(GEN x); INLINE GEN nfV_to_scalar_or_alg(GEN nf, GEN x); INLINE GEN nf_get_G(GEN nf); INLINE GEN nf_get_M(GEN nf); INLINE GEN nf_get_Tr(GEN nf); INLINE GEN nf_get_diff(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 GEN nf_get_ramified_primes(GEN nf); INLINE GEN nf_get_roots(GEN nf); INLINE GEN nf_get_roundG(GEN nf); INLINE GEN nf_get_zk(GEN nf); INLINE GEN nf_get_zkden(GEN nf); INLINE GEN nf_get_zkprimpart(GEN nf); INLINE GEN pr_get_gen(GEN pr); INLINE GEN pr_get_p(GEN pr); INLINE GEN pr_get_tau(GEN pr); INLINE GEN pr_norm(GEN pr); INLINE GEN rnf_get_alpha(GEN rnf); INLINE GEN rnf_get_disc(GEN rnf); INLINE GEN rnf_get_idealdisc(GEN rnf); INLINE GEN rnf_get_index(GEN rnf); INLINE GEN rnf_get_invzk(GEN rnf); INLINE GEN rnf_get_k(GEN rnf); INLINE GEN rnf_get_map(GEN rnf); INLINE GEN rnf_get_nf(GEN rnf); INLINE GEN rnf_get_nfpol(GEN rnf); INLINE GEN rnf_get_nfzk(GEN rnf); INLINE GEN rnf_get_pol(GEN rnf); INLINE GEN rnf_get_polabs(GEN rnf); INLINE GEN rnf_get_ramified_primes(GEN rnf); INLINE GEN rnf_get_zk(GEN nf); INLINE GEN vecmodii(GEN a, GEN b); INLINE GEN vecmoduu(GEN a, GEN b); INLINE GEN znstar_get_N(GEN G); INLINE GEN znstar_get_U(GEN G); INLINE GEN znstar_get_Ui(GEN G); INLINE GEN znstar_get_conreycyc(GEN G); INLINE GEN znstar_get_conreygen(GEN G); INLINE GEN znstar_get_cyc(GEN G); INLINE GEN znstar_get_faN(GEN G); INLINE GEN znstar_get_gen(GEN G); INLINE GEN znstar_get_no(GEN G); INLINE GEN znstar_get_pe(GEN G); INLINE int checkell_i(GEN e); INLINE int ell_is_inf(GEN z); INLINE int pr_is_inert(GEN P); INLINE long bnf_get_tuN(GEN bnf); INLINE long ellQp_get_prec(GEN E); INLINE long ellR_get_prec(GEN x); INLINE long ellR_get_sign(GEN x); INLINE long ell_get_type(GEN e); INLINE long logint(GEN B, GEN y); INLINE long nf_get_degree(GEN nf); INLINE long nf_get_r1(GEN nf); INLINE long nf_get_r2(GEN nf); INLINE long nf_get_varn(GEN nf); INLINE long pr_get_e(GEN pr); INLINE long pr_get_f(GEN pr); INLINE long rnf_get_absdegree(GEN rnf); INLINE long rnf_get_degree(GEN rnf); INLINE long rnf_get_nfdegree(GEN rnf); INLINE long rnf_get_nfvarn(GEN rnf); INLINE long rnf_get_varn(GEN rnf); INLINE ulong hash_str(const char *str); INLINE ulong hash_str_len(const char *s, long len); INLINE ulong ulogint(ulong B, ulong y); INLINE ulong upr_norm(GEN pr); INLINE void nf_get_sign(GEN nf, long *r1, long *r2); INLINE long closure_arity(GEN C); INLINE const char * closure_codestr(GEN C); INLINE GEN closure_get_code(GEN C); INLINE GEN closure_get_oper(GEN C); INLINE GEN closure_get_data(GEN C); INLINE GEN closure_get_dbg(GEN C); INLINE GEN closure_get_text(GEN C); INLINE GEN closure_get_frame(GEN C); INLINE long closure_is_variadic(GEN C); INLINE GEN addmuliu(GEN x, GEN y, ulong u); INLINE GEN addmuliu_inplace(GEN x, GEN y, ulong u); INLINE GEN lincombii(GEN u, GEN v, GEN x, GEN y); INLINE GEN mulsubii(GEN y, GEN z, GEN x); INLINE GEN submulii(GEN x, GEN y, GEN z); INLINE GEN submuliu(GEN x, GEN y, ulong u); INLINE GEN submuliu_inplace(GEN x, GEN y, ulong u); INLINE GEN FpXQ_add(GEN x,GEN y,GEN T,GEN p); INLINE GEN FpXQ_sub(GEN x,GEN y,GEN T,GEN p); INLINE GEN Flxq_add(GEN x,GEN y,GEN T,ulong p); INLINE GEN Flxq_sub(GEN x,GEN y,GEN T,ulong p); INLINE GEN FpXQX_div(GEN x, GEN y, GEN T, GEN p); INLINE GEN FlxqX_div(GEN x, GEN y, GEN T, ulong p); INLINE GEN FlxqX_div_pre(GEN x, GEN y, GEN T, ulong p, ulong pi); INLINE GEN F2xqX_div(GEN x, GEN y, GEN T); INLINE GEN Rg_to_Fq(GEN x, GEN T, GEN p); INLINE GEN Fq_red(GEN x, GEN T, GEN p); INLINE GEN Fq_to_FpXQ(GEN x, GEN T, GEN p); INLINE GEN gener_Fq_local(GEN T, GEN p, GEN L); INLINE GEN random_Fq(GEN T, GEN p); INLINE GEN FpXY_Fq_evaly(GEN Q, GEN y, GEN T, GEN p, long vx); 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_ddf(GEN f, GEN T, GEN p); INLINE GEN FqX_degfact(GEN f, GEN T, GEN p); INLINE GEN FqX_deriv(GEN f, GEN T, GEN p); INLINE GEN FqX_div(GEN x, GEN y, GEN T, GEN p); INLINE GEN FqX_div_by_X_x(GEN x, GEN y, GEN T, GEN p, GEN *z); INLINE GEN FqX_divrem(GEN x, GEN y, GEN T, GEN p, GEN *z); INLINE GEN FqX_extgcd(GEN P,GEN Q,GEN T,GEN p, GEN *U, GEN *V); INLINE GEN FqX_factor(GEN f, GEN T, GEN p); INLINE GEN FqX_factor_squarefree(GEN f, GEN T, GEN p); INLINE GEN FqX_gcd(GEN P, GEN Q, GEN T, GEN p); INLINE GEN FqX_get_red(GEN S, GEN T, GEN p); INLINE GEN FqX_halfgcd(GEN P,GEN Q,GEN T,GEN p); INLINE GEN FqX_halve(GEN x, GEN T, GEN p); INLINE GEN FqX_integ(GEN f, GEN T, GEN p); INLINE GEN FqX_mul(GEN x, GEN y, GEN T, GEN p); INLINE GEN FqX_mulu(GEN x, ulong y, GEN T, GEN p); INLINE GEN FqX_neg(GEN x, GEN T, GEN p); INLINE GEN FqX_normalize(GEN z, GEN T, GEN p); INLINE GEN FqX_powu(GEN x, ulong n, GEN T, GEN p); INLINE GEN FqX_red(GEN z, GEN T, GEN p); INLINE GEN FqX_rem(GEN x, GEN y, GEN T, GEN p); INLINE GEN FqX_roots(GEN f, 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 FqX_to_mod(GEN f, 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 GEN FqXn_exp(GEN x, long n, GEN T, GEN p); INLINE GEN FqXn_expint(GEN x, long n, GEN T, GEN p); INLINE GEN FqXn_inv(GEN x, long n, GEN T, GEN p); INLINE GEN FqXn_mul(GEN x, GEN y, long n, GEN T, GEN p); INLINE GEN FqXn_sqr(GEN x, long n, GEN T, GEN p); INLINE long get_F2x_degree(GEN T); INLINE GEN get_F2x_mod(GEN T); INLINE long get_F2x_var(GEN T); INLINE long get_F2xqX_degree(GEN T); INLINE GEN get_F2xqX_mod(GEN T); INLINE long get_F2xqX_var(GEN T); INLINE long get_Flx_degree(GEN T); INLINE GEN get_Flx_mod(GEN T); INLINE long get_Flx_var(GEN T); INLINE long get_FlxqX_degree(GEN T); INLINE GEN get_FlxqX_mod(GEN T); INLINE long get_FlxqX_var(GEN T); INLINE long get_FpX_degree(GEN T); INLINE GEN get_FpX_mod(GEN T); INLINE long get_FpX_var(GEN T); INLINE long get_FpXQX_degree(GEN T); INLINE GEN get_FpXQX_mod(GEN T); INLINE long get_FpXQX_var(GEN T); INLINE ulong F2m_coeff(GEN x, long a, long b); INLINE void F2m_clear(GEN x, long a, long b); INLINE void F2m_flip(GEN x, long a, long b); INLINE void F2m_set(GEN x, long a, long b); INLINE void F2v_clear(GEN x,long v); INLINE ulong F2v_coeff(GEN x,long v); INLINE void F2v_flip(GEN x,long v); INLINE GEN F2v_to_F2x(GEN x, long sv); INLINE void F2v_set(GEN x,long v); INLINE void F2x_clear(GEN x,long v); INLINE ulong F2x_coeff(GEN x,long v); INLINE void F2x_flip(GEN x,long v); INLINE void F2x_set(GEN x,long v); INLINE int F2x_equal1(GEN x); INLINE int F2x_equal(GEN V, GEN W); INLINE GEN F2x_div(GEN x, GEN y); INLINE GEN F2x_renormalize(GEN x, long lx); INLINE GEN F2m_copy(GEN x); INLINE GEN F2v_copy(GEN x); INLINE GEN F2x_copy(GEN x); INLINE GEN F2v_ei(long n, long i); INLINE GEN F2xX_shift(GEN a, long n, long vs); INLINE ulong F3m_coeff(GEN x, long a, long b); INLINE void F3m_set(GEN x, long a, long b, ulong c); INLINE GEN F3m_copy(GEN x); INLINE GEN Flm_copy(GEN x); INLINE GEN Flv_copy(GEN x); INLINE int Flx_equal1(GEN x); INLINE ulong Flx_constant(GEN x); INLINE GEN Flx_copy(GEN x); INLINE GEN Flx_div(GEN x, GEN y, ulong p); INLINE GEN Flx_div_pre(GEN x, GEN y, ulong p, ulong pi); INLINE ulong Flx_lead(GEN x); INLINE GEN Flx_mulu(GEN x, ulong a, ulong p); INLINE GEN Fp_divu(GEN x, ulong a, GEN p); INLINE GEN FpV_FpC_mul(GEN x, GEN y, GEN p); INLINE GEN FpXQX_renormalize(GEN x, long lx); INLINE GEN FpXX_renormalize(GEN x, long lx); INLINE GEN FpX_div(GEN x, GEN y, GEN p); INLINE GEN FpX_renormalize(GEN x, long lx); INLINE GEN Fp_add(GEN a, GEN b, GEN m); INLINE GEN Fp_addmul(GEN x, GEN y, GEN z, GEN p); INLINE GEN Fp_center(GEN u, GEN p, GEN ps2); INLINE GEN Fp_center_i(GEN u, GEN p, GEN ps2); INLINE GEN Fp_div(GEN a, GEN b, GEN m); INLINE GEN Fp_double(GEN x, GEN N); INLINE GEN Fp_halve(GEN y, GEN p); INLINE GEN Fp_inv(GEN a, GEN m); INLINE GEN Fp_invsafe(GEN a, GEN m); INLINE GEN Fp_mul(GEN a, GEN b, GEN m); INLINE GEN Fp_muls(GEN a, long b, GEN m); INLINE GEN Fp_mulu(GEN a, ulong b, GEN m); INLINE GEN Fp_neg(GEN b, GEN m); INLINE GEN Fp_red(GEN x, GEN p); INLINE GEN Fp_sqr(GEN a, GEN m); INLINE GEN Fp_sub(GEN a, GEN b, GEN m); INLINE GEN GENbinbase(GENbin *p); INLINE GEN Q_abs(GEN x); INLINE GEN Q_abs_shallow(GEN x); INLINE int QV_isscalar(GEN x); INLINE void Qtoss(GEN q, long *n, long *d); INLINE GEN R_abs(GEN x); INLINE GEN R_abs_shallow(GEN x); INLINE GEN RgC_fpnorml2(GEN x, long prec); INLINE GEN RgC_gtofp(GEN x, long prec); INLINE GEN RgC_gtomp(GEN x, long prec); INLINE void RgM_dimensions(GEN x, long *m, long *n); INLINE GEN RgM_fpnorml2(GEN x, long prec); INLINE GEN RgM_gtofp(GEN x, long prec); INLINE GEN RgM_gtomp(GEN x, long prec); INLINE GEN RgM_minor(GEN a, long i, long j); INLINE GEN RgM_shallowcopy(GEN x); INLINE GEN RgV_gtofp(GEN x, long prec); INLINE int RgV_isscalar(GEN x); INLINE long RgV_isin(GEN v, GEN x); INLINE long RgV_isin_i(GEN v, GEN x, long n); INLINE int RgV_is_ZV(GEN x); INLINE int RgV_is_QV(GEN x); INLINE long RgX_equal_var(GEN x, GEN y); INLINE int RgX_is_monomial(GEN x); INLINE int RgX_is_rational(GEN x); INLINE int RgX_is_QX(GEN x); INLINE int RgX_is_ZX(GEN x); INLINE int RgX_isscalar(GEN x); INLINE GEN RgX_shift_inplace(GEN x, long v); INLINE void RgX_shift_inplace_init(long v); INLINE GEN RgX_to_RgV(GEN x, long N); INLINE GEN RgXQX_div(GEN x, GEN y, GEN T); INLINE GEN RgXQX_rem(GEN x, GEN y, GEN T); INLINE GEN RgX_coeff(GEN x, long n); INLINE GEN RgX_copy(GEN x); INLINE GEN RgX_div(GEN x, GEN y); INLINE GEN RgX_fpnorml2(GEN x, long prec); INLINE GEN RgX_gtofp(GEN x, long prec); INLINE GEN RgX_renormalize(GEN x); INLINE GEN Rg_col_ei(GEN x, long n, long i); INLINE GEN ZC_hnfrem(GEN x, GEN y); INLINE GEN ZM_hnfrem(GEN x, GEN y); INLINE GEN ZM_lll(GEN x, double D, long f); INLINE int ZV_dvd(GEN x, GEN y); INLINE int ZV_isscalar(GEN x); INLINE GEN ZV_to_zv(GEN x); INLINE int ZX_equal1(GEN x); INLINE int ZX_is_monic(GEN x); INLINE GEN ZX_renormalize(GEN x, long lx); INLINE GEN ZXQ_mul(GEN x,GEN y,GEN T); INLINE GEN ZXQ_sqr(GEN x,GEN T); INLINE long Z_ispower(GEN x, ulong k); INLINE long Z_issquare(GEN x); INLINE GEN absfrac(GEN x); INLINE GEN absfrac_shallow(GEN x); INLINE GEN affc_fixlg(GEN x, GEN res); INLINE GEN bin_copy(GENbin *p); INLINE long bit_accuracy(long x); INLINE double bit_accuracy_mul(long x, double y); INLINE long bit_prec(GEN x); INLINE int both_odd(long x, long y); INLINE GEN cbrtr(GEN x); INLINE GEN cbrtr_abs(GEN x); INLINE GEN cgetc(long x); INLINE GEN cgetalloc(size_t l, long t); 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_coeff(GEN x); INLINE GEN cxcompotor(GEN z, long prec); INLINE GEN cxnorm(GEN x); INLINE GEN cxtoreal(GEN q); 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 GEN gc_all(pari_sp av, int n, ...); 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 int gisdouble(GEN x, double *g); INLINE GEN gmax_shallow(GEN x, GEN y); INLINE GEN gmaxsg(long s, GEN y); INLINE GEN gmin_shallow(GEN x, 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 GEN gmulgu(GEN y, ulong s); INLINE void gmulz(GEN x, GEN y, GEN z); INLINE void gnegz(GEN x, GEN z); INLINE void gshiftz(GEN x, long s, GEN z); INLINE GEN gsubgs(GEN y, long s); INLINE void gsubz(GEN x, GEN y, GEN z); INLINE double gtodouble(GEN x); INLINE GEN gtofp(GEN z, long prec); INLINE GEN gtomp(GEN z, long prec); INLINE long gtos(GEN x); INLINE ulong gtou(GEN x); INLINE void guncloneNULL(GEN x); INLINE void guncloneNULL_deep(GEN x); INLINE long gval(GEN x, long v); INLINE GEN identity_perm(long l); INLINE GEN identity_zv(long n); INLINE GEN identity_ZV(long n); INLINE int equali1(GEN n); INLINE int equalim1(GEN n); INLINE long inf_get_sign(GEN x); INLINE GEN inv_content(GEN c); 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_qfb_t(long t); INLINE int is_rational_t(long t); INLINE int is_real_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_coeff(GEN x); INLINE void lg_increase(GEN x); INLINE long lgcols(GEN x); INLINE long lgpol(GEN x); INLINE GEN div_content(GEN cx, GEN cy); INLINE GEN matpascal(long n); INLINE GEN matslice(GEN A, long x1, long x2, long y1, long y2); INLINE GEN mkcol(GEN x); INLINE GEN mkcol2(GEN x, GEN y); INLINE GEN mkcol2s(long x, long y); INLINE GEN mkcol3(GEN x, GEN y, GEN z); INLINE GEN mkcol3s(long x, long y, long z); INLINE GEN mkcol4(GEN x, GEN y, GEN z, GEN t); INLINE GEN mkcol4s(long x, long y, long z, long t); INLINE GEN mkcol5(GEN x, GEN y, GEN z, GEN t, GEN u); INLINE GEN mkcol6(GEN x, GEN y, GEN z, GEN t, GEN u, GEN v); INLINE GEN mkcolcopy(GEN x); INLINE GEN mkcols(long x); INLINE GEN mkcomplex(GEN x, GEN y); INLINE GEN mkerr(long n); INLINE GEN mkmoo(void); INLINE GEN mkoo(void); INLINE GEN mkfrac(GEN x, GEN y); INLINE GEN mkfracss(long x, long 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 mkmat22(GEN a, GEN b, GEN c, GEN d); INLINE GEN mkmat22s(long a, long b, long c, long d); INLINE GEN mkmat3(GEN x, GEN y, GEN z); INLINE GEN mkmat4(GEN x, GEN y, GEN z, GEN t); INLINE GEN mkmat5(GEN x, GEN y, GEN z, GEN t, GEN u); INLINE GEN mkmatcopy(GEN x); INLINE GEN mkpolmod(GEN x, GEN y); INLINE GEN mkqfb(GEN x, GEN y, GEN z, GEN d); INLINE GEN mkquad(GEN n, GEN x, GEN y); INLINE GEN mkrfrac(GEN x, GEN y); INLINE GEN mkrfraccopy(GEN x, GEN y); INLINE GEN mkvec(GEN x); INLINE GEN mkvec2(GEN x, GEN y); INLINE GEN mkvec2copy(GEN x, GEN y); INLINE GEN mkvec2s(long x, long y); INLINE GEN mkvec3(GEN x, GEN y, GEN z); INLINE GEN mkvec3s(long x, long y, long z); INLINE GEN mkvec4(GEN x, GEN y, GEN z, GEN t); INLINE GEN mkvec4s(long x, long y, long z, long t); INLINE GEN mkvec5(GEN x, GEN y, GEN z, GEN t, GEN u); INLINE GEN mkveccopy(GEN x); INLINE GEN mkvecs(long x); INLINE GEN mkvecsmall(long x); INLINE GEN mkvecsmall2(long x,long y); INLINE GEN mkvecsmall3(long x,long y,long z); INLINE GEN mkvecsmall4(long x,long y,long z,long t); INLINE GEN mkvecsmall5(long x,long y,long z,long t,long u); INLINE void mpcosz(GEN x, GEN z); INLINE void mpexpz(GEN x, GEN z); INLINE void mplogz(GEN x, GEN z); INLINE void mpsinz(GEN x, GEN z); INLINE GEN mul_content(GEN cx, GEN cy); INLINE GEN mul_denom(GEN cx, GEN cy); INLINE long nbits2nlong(long x); INLINE long nbits2extraprec(long x); INLINE long nbits2ndec(long x); INLINE long nbits2prec(long x); INLINE long nbrows(GEN x); INLINE long nchar2nlong(long x); INLINE long ndec2nbits(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 void pari_realloc_ip(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 perm_sqr(GEN s); INLINE GEN pol_0(long v); INLINE GEN pol_1(long v); INLINE GEN pol_x(long v); INLINE GEN pol_xn(long n, long v); INLINE GEN pol_xnall(long n, long v); INLINE GEN pol0_F2x(long sv); INLINE GEN pol0_Flx(long sv); INLINE GEN pol1_F2x(long sv); INLINE GEN pol1_Flx(long sv); INLINE GEN polx_Flx(long sv); INLINE GEN polx_F2x(long sv); INLINE GEN polx_zx(long sv); INLINE GEN polxn_Flx(long n, long sv); INLINE GEN powii(GEN x, GEN n); INLINE GEN powIs(long n); INLINE long prec2lg(long x); INLINE long prec2nbits(long x); INLINE double prec2nbits_mul(long x, double y); INLINE long prec2ndec(long x); INLINE long precdbl(long x); INLINE GEN quad_disc(GEN x); INLINE GEN qfb_disc(GEN x); INLINE GEN qfb_disc3(GEN x, GEN y, GEN z); INLINE GEN quadnorm(GEN q); INLINE long remsBIL(long n); INLINE GEN row(GEN A, long x1); INLINE GEN Flm_row(GEN A, long x0); INLINE GEN row_i(GEN A, long x0, long x1, long x2); INLINE GEN zm_row(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 rowsplice(GEN a, long j); INLINE int ser_isexactzero(GEN x); 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 GEN sstoQ(long n, long d); INLINE GEN uutoQ(ulong n, ulong d); INLINE void pari_stack_alloc(pari_stack *s, long nb); INLINE void** pari_stack_base(pari_stack *s); INLINE void pari_stack_delete(pari_stack *s); INLINE void pari_stack_init(pari_stack *s, size_t size, void **data); INLINE long pari_stack_new(pari_stack *s); INLINE void pari_stack_pushp(pari_stack *s, void *u); INLINE long sturm(GEN x); INLINE GEN truecoef(GEN x, long n); INLINE GEN trunc_safe(GEN x); INLINE GEN vec_ei(long n, long i); INLINE GEN vec_append(GEN v, GEN s); INLINE GEN vec_lengthen(GEN v, long n); INLINE GEN vec_prepend(GEN v, GEN s); 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 veclast(GEN A); INLINE GEN vecpermute(GEN A, GEN p); INLINE GEN vecreverse(GEN A); INLINE void vecreverse_inplace(GEN y); INLINE GEN vecsmallpermute(GEN A, GEN p); INLINE GEN vecslice(GEN A, long y1, long y2); INLINE GEN vecslicepermute(GEN A, GEN p, long y1, long y2); INLINE GEN vecsplice(GEN a, long j); INLINE GEN vecsmall_append(GEN V, long s); INLINE long vecsmall_coincidence(GEN u, GEN v); INLINE GEN vecsmall_concat(GEN u, GEN v); INLINE GEN vecsmall_copy(GEN x); INLINE GEN vecsmall_ei(long n, long i); INLINE long vecsmall_indexmax(GEN x); INLINE long vecsmall_indexmin(GEN x); INLINE long vecsmall_isin(GEN v, long x); INLINE GEN vecsmall_lengthen(GEN v, long n); INLINE int vecsmall_lexcmp(GEN x, GEN y); INLINE long vecsmall_max(GEN v); INLINE long vecsmall_min(GEN v); INLINE long vecsmall_pack(GEN V, long base, long mod); INLINE int vecsmall_prefixcmp(GEN x, GEN y); INLINE GEN vecsmall_prepend(GEN V, long s); INLINE GEN vecsmall_reverse(GEN A); INLINE GEN vecsmall_shorten(GEN v, long n); INLINE GEN vecsmall_to_col(GEN z); INLINE GEN vecsmall_to_vec(GEN z); INLINE GEN vecsmall_to_vec_inplace(GEN z); INLINE void vecsmalltrunc_append(GEN x, long t); INLINE GEN vecsmalltrunc_init(long l); INLINE void vectrunc_append(GEN x, GEN t); INLINE void vectrunc_append_batch(GEN x, GEN y); INLINE GEN vectrunc_init(long l); INLINE GEN coltrunc_init(long l); INLINE GEN zc_to_ZC(GEN x); INLINE GEN zero_F2m(long n, long m); INLINE GEN zero_F2m_copy(long n, long m); INLINE GEN zero_F2v(long m); INLINE GEN zero_F2x(long sv); INLINE GEN zero_Flm(long m, long n); INLINE GEN zero_Flm_copy(long m, long n); INLINE GEN zero_Flv(long n); INLINE GEN zero_Flx(long sv); INLINE GEN zero_zm(long x, long y); INLINE GEN zero_zv(long x); INLINE GEN zero_zx(long sv); INLINE GEN zerocol(long n); INLINE GEN zeromat(long m, long n); INLINE GEN zeromatcopy(long m, long n); INLINE GEN zeropadic(GEN p, long e); INLINE GEN zeropadic_shallow(GEN p, long e); INLINE GEN zeropol(long v); INLINE GEN zeroser(long v, long e); INLINE GEN zerovec(long n); INLINE GEN zerovec_block(long len); INLINE GEN zm_copy(GEN x); INLINE GEN zm_to_zxV(GEN x, long sv); INLINE GEN zm_transpose(GEN x); INLINE GEN zv_copy(GEN x); INLINE GEN zv_to_ZV(GEN x); INLINE GEN zv_to_zx(GEN x, long sv); INLINE GEN zx_renormalize(GEN x, long l); INLINE GEN zx_shift(GEN x, long n); INLINE GEN zx_to_zv(GEN x, long N); INLINE GEN err_get_compo(GEN e, long i); INLINE long err_get_num(GEN e); INLINE void pari_err_BUG(const char *f); INLINE void pari_err_COMPONENT(const char *f, const char *op, GEN l, GEN x); INLINE void pari_err_CONSTPOL(const char *f); INLINE void pari_err_COPRIME(const char *f, GEN x, GEN y); INLINE void pari_err_DIM(const char *f); INLINE void pari_err_DOMAIN(const char *f, const char *v, const char *op, GEN l, GEN x); INLINE void pari_err_FILE(const char *f, const char *g); INLINE void pari_err_FILEDESC(const char *f, long n); INLINE void pari_err_FLAG(const char *f); INLINE void pari_err_IMPL(const char *f); INLINE void pari_err_INV(const char *f, GEN x); INLINE void pari_err_IRREDPOL(const char *f, GEN x); INLINE void pari_err_MAXPRIME(ulong c); INLINE void pari_err_MODULUS(const char *f, GEN x, GEN y); INLINE void pari_err_OP(const char *f, GEN x, GEN y); INLINE void pari_err_OVERFLOW(const char *f); INLINE void pari_err_PACKAGE(const char *f); INLINE void pari_err_PREC(const char *f); INLINE void pari_err_PRIME(const char *f, GEN x); INLINE void pari_err_PRIORITY(const char *f, GEN x, const char *op, long v); INLINE void pari_err_SQRTN(const char *f, GEN x); INLINE void pari_err_TYPE(const char *f, GEN x); INLINE void pari_err_TYPE2(const char *f, GEN x, GEN y); INLINE void pari_err_VAR(const char *f, GEN x, GEN y); INLINE void pari_err_ROOTS0(const char *f); pari-2.17.2/src/headers/paricom.h0000644000175000017500000001223114760123736015201 0ustar billbill/* Copyright (C) 2004 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /******************************************************************/ /* */ /* PARI header file (common to all versions) */ /* */ /******************************************************************/ #ifdef STMT_START /* perl headers */ # undef STMT_START #endif #ifdef STMT_END # undef STMT_END #endif /* STMT_START { statements; } STMT_END; * can be used as a single statement, as in * if (x) STMT_START { ... } STMT_END; else ... * [ avoid "dangling else" problem in macros ] */ #define STMT_START do #define STMT_END while (0) /*=====================================================================*/ /* pari_CATCH(numer) { * recovery * } pari_TRY { * code * } pari_ENDCATCH * will execute 'code', then 'recovery' if exception 'numer' is thrown * [ any exception if numer == CATCH_ALL ]. * pari_RETRY = as pari_TRY, but execute 'recovery', then 'code' again [still catching] */ extern THREAD jmp_buf *iferr_env; extern const long CATCH_ALL; #define pari_CATCH2(var,err) { \ jmp_buf *var=iferr_env; \ jmp_buf __env; \ iferr_env = &__env; \ if (setjmp(*iferr_env)) \ { \ GEN __iferr_data = pari_err_last(); \ iferr_env = var; \ if (err!=CATCH_ALL && err_get_num(__iferr_data) != err) \ pari_err(0, __iferr_data); #define pari_CATCH2_reset(var) (iferr_env = var) #define pari_ENDCATCH2(var) iferr_env = var; } } #define pari_CATCH(err) pari_CATCH2(__iferr_old,err) #define pari_RETRY } iferr_env = &__env; { #define pari_TRY } else { #define pari_CATCH_reset() pari_CATCH2_reset(__iferr_old) #define pari_ENDCATCH pari_ENDCATCH2(__iferr_old) #define pari_APPLY_same(EXPR)\ { \ long i, _l; \ GEN _y = cgetg_copy(x, &_l);\ for (i=1; i<_l; i++) gel(_y,i) = EXPR;\ return _y;\ } #define pari_APPLY_pol(EXPR)\ { \ long i, _l; \ GEN _y = cgetg_copy(x, &_l); _y[1] = x[1];\ if (_l == 2) return _y;\ for (i=2; i<_l; i++) gel(_y,i) = EXPR;\ return normalizepol_lg(_y, _l);\ } #define pari_APPLY_ser(EXPR)\ { \ long i, _l; \ GEN _y = cgetg_copy(x, &_l); _y[1] = x[1];\ if (_l == 2) return _y;\ for (i=2; i<_l; i++) gel(_y,i) = EXPR;\ return normalizeser(_y);\ } #define pari_APPLY_type(TYPE, EXPR)\ { \ long i, _l = lg(x); \ GEN _y = cgetg(_l, TYPE);\ for (i=1; i<_l; i++) gel(_y,i) = EXPR;\ return _y;\ } #define pari_APPLY_long(EXPR)\ { \ long i, _l = lg(x); \ GEN _y = cgetg(_l, t_VECSMALL);\ for (i=1; i<_l; i++) _y[i] = EXPR;\ return _y;\ } #define pari_APPLY_ulong(EXPR)\ { \ long i, _l = lg(x); \ GEN _y = cgetg(_l, t_VECSMALL);\ for (i=1; i<_l; i++) ((ulong*)_y)[i] = EXPR;\ return _y;\ } extern const double LOG10_2, LOG2_10; #ifndef M_PI # define M_PI 3.14159265358979323846264338327950288 #endif #ifndef M_LN2 # define M_LN2 0.693147180559945309417232121458176568 #endif #ifndef M_E #define M_E 2.7182818284590452354 #endif /* Common global variables: */ extern int new_galois_format, factor_add_primes, factor_proven; extern ulong DEBUGLEVEL, DEBUGMEM, precdl; extern THREAD long DEBUGVAR; extern ulong pari_mt_nbthreads; extern THREAD GEN zetazone, bernzone, eulerzone, primetab; extern GEN gen_m1,gen_1,gen_2,gen_m2,ghalf,gen_0,gnil,err_e_STACK; extern THREAD VOLATILE int PARI_SIGINT_block, PARI_SIGINT_pending; extern const long lontyp[]; extern void (*cb_pari_display_hist)(long n); extern void (*cb_pari_ask_confirm)(const char *); extern void (*cb_pari_init_histfile)(void); extern int (*cb_pari_whatnow)(PariOUT *out, const char *, int); extern void (*cb_pari_quit)(long); extern void (*cb_pari_sigint)(void); extern int (*cb_pari_handle_exception)(long); extern int (*cb_pari_err_handle)(GEN); extern void (*cb_pari_pre_recover)(long); extern void (*cb_pari_err_recover)(long); extern int (*cb_pari_break_loop)(int); extern int (*cb_pari_is_interactive)(void); extern void (*cb_pari_start_output)(void); extern void (*cb_pari_long_help)(const char *s, long num); extern const char *pari_library_path; extern THREAD long *varpriority; /* pari_init_opts */ enum { INIT_JMPm = 1, INIT_SIGm = 2, INIT_DFTm = 4, INIT_noPRIMEm = 8, INIT_noIMTm = 16, INIT_noINTGMPm = 32 }; #ifndef HAS_EXP2 # undef exp2 # define exp2(x) (exp((double)(x)*M_LN2)) #endif #ifndef HAS_LOG2 # undef log2 # define log2(x) (log((double)(x))/M_LN2) #endif #define ONLY_REM ((GEN*)0x1L) #define ONLY_DIVIDES ((GEN*)0x2L) pari-2.17.2/src/headers/parierr.h0000644000175000017500000000221314567450071015212 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ enum err_list { /* Force errors into non-0 */ e_SYNTAX = 1, e_BUG, e_ALARM, e_FILE, e_MISC, e_FLAG, e_IMPL, e_ARCH, e_PACKAGE, e_NOTFUNC, e_PREC, e_TYPE, e_DIM, e_VAR, e_PRIORITY, e_USER, e_STACK, e_STACKTHREAD, e_OVERFLOW, e_DOMAIN, e_COMPONENT, e_MAXPRIME, e_CONSTPOL, e_IRREDPOL, e_COPRIME, e_PRIME, e_MODULUS, e_ROOTS0, e_OP, e_TYPE2, e_INV, e_MEM, e_SQRTN, e_FILEDESC, /* NO ERROR */ e_NONE }; enum { warner, warnprec, warnfile, warnmem, warnuser, warnstack, warnstackthread }; pari-2.17.2/src/headers/pariinl.h0000644000175000017500000025332514760123736015220 0ustar billbill/* Copyright (C) 2000-2010 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*********************************************************************/ /* MALLOC/FREE WRAPPERS */ /*********************************************************************/ #define BLOCK_SIGALRM_START \ { \ int block=PARI_SIGINT_block; \ PARI_SIGINT_block = 2; \ MT_SIGINT_BLOCK(block); #define BLOCK_SIGINT_START \ { \ int block=PARI_SIGINT_block; \ PARI_SIGINT_block = 1; \ MT_SIGINT_BLOCK(block); #define BLOCK_SIGINT_END \ PARI_SIGINT_block = block; \ MT_SIGINT_UNBLOCK(block); \ if (!block && PARI_SIGINT_pending) \ { \ int sig = PARI_SIGINT_pending; \ PARI_SIGINT_pending = 0; \ raise(sig); \ } \ } /*******************************************************************/ /* */ /* CONSTRUCTORS */ /* */ /*******************************************************************/ #define retmkfrac(x,y)\ do { GEN _v = cgetg(3, t_FRAC);\ gel(_v,1) = (x);\ gel(_v,2) = (y); return _v; } while(0) #define retmkrfrac(x,y)\ do { GEN _v = cgetg(3, t_RFRAC);\ gel(_v,1) = (x);\ gel(_v,2) = (y); return _v; } while(0) #define retmkintmod(x,y)\ do { GEN _v = cgetg(3, t_INTMOD);\ gel(_v,1) = (y);\ gel(_v,2) = (x); return _v; } while(0) #define retmkcomplex(x,y)\ do { GEN _v = cgetg(3, t_COMPLEX);\ gel(_v,1) = (x);\ gel(_v,2) = (y); return _v; } while(0) #define retmkpolmod(x,y)\ do { GEN _v = cgetg(3, t_POLMOD);\ gel(_v,1) = (y);\ gel(_v,2) = (x); return _v; } while(0) #define retmkvec(x)\ do { GEN _v = cgetg(2, t_VEC);\ gel(_v,1) = (x); return _v; } while(0) #define retmkvec2(x,y)\ do { GEN _v = cgetg(3, t_VEC);\ gel(_v,1) = (x);\ gel(_v,2) = (y); return _v; } while(0) #define retmkvec3(x,y,z)\ do { GEN _v = cgetg(4, t_VEC);\ gel(_v,1) = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z); return _v; } while(0) #define retmkqfb(x,y,z,d)\ do { GEN _v = cgetg(5, t_QFB);\ gel(_v,1) = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z);\ gel(_v,4) = (d); return _v; } while(0) #define retmkquad(x,y,z)\ do { GEN _v = cgetg(4, t_QUAD);\ gel(_v,1) = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z); return _v; } while(0) #define retmkvec4(x,y,z,t)\ do { GEN _v = cgetg(5, t_VEC);\ gel(_v,1) = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z);\ gel(_v,4) = (t); return _v; } while(0) #define retmkvec5(x,y,z,t,u)\ do { GEN _v = cgetg(6, t_VEC);\ gel(_v,1) = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z);\ gel(_v,4) = (t);\ gel(_v,5) = (u); return _v; } while(0) #define retmkcol(x)\ do { GEN _v = cgetg(2, t_COL);\ gel(_v,1) = (x); return _v; } while(0) #define retmkcol2(x,y)\ do { GEN _v = cgetg(3, t_COL);\ gel(_v,1) = (x);\ gel(_v,2) = (y); return _v; } while(0) #define retmkcol3(x,y,z)\ do { GEN _v = cgetg(4, t_COL);\ gel(_v,1) = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z); return _v; } while(0) #define retmkcol4(x,y,z,t)\ do { GEN _v = cgetg(5, t_COL);\ gel(_v,1) = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z);\ gel(_v,4) = (t); return _v; } while(0) #define retmkcol5(x,y,z,t,u)\ do { GEN _v = cgetg(6, t_COL);\ gel(_v,1) = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z);\ gel(_v,4) = (t);\ gel(_v,5) = (u); return _v; } while(0) #define retmkcol6(x,y,z,t,u,v)\ do { GEN _v = cgetg(7, t_COL);\ gel(_v,1) = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z);\ gel(_v,4) = (t);\ gel(_v,5) = (u);\ gel(_v,6) = (v); return _v; } while(0) #define retmkmat(x)\ do { GEN _v = cgetg(2, t_MAT);\ gel(_v,1) = (x); return _v; } while(0) #define retmkmat2(x,y)\ do { GEN _v = cgetg(3, t_MAT);\ gel(_v,1) = (x);\ gel(_v,2) = (y); return _v; } while(0) #define retmkmat3(x,y,z)\ do { GEN _v = cgetg(4, t_MAT);\ gel(_v,1) = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z); return _v; } while(0) #define retmkmat4(x,y,z,t)\ do { GEN _v = cgetg(5, t_MAT);\ gel(_v,1) = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z);\ gel(_v,4) = (t); return _v; } while(0) #define retmkmat5(x,y,z,t,u)\ do { GEN _v = cgetg(6, t_MAT);\ gel(_v,1) = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z);\ gel(_v,4) = (t);\ gel(_v,5) = (u); return _v; } while(0) #define retmkmat22(a,b,c,d)\ do { GEN _v = cgetg(3, t_MAT);\ gel(_v,1) = mkcol2(a,c);\ gel(_v,2) = mkcol2(b,d); return _v; } while(0) INLINE GEN mkintmod(GEN x, GEN y) { retmkintmod(x,y); } INLINE GEN mkintmodu(ulong x, ulong y) { GEN v = cgetg(3,t_INTMOD); gel(v,1) = utoipos(y); gel(v,2) = utoi(x); return v; } INLINE GEN mkpolmod(GEN x, GEN y) { retmkpolmod(x,y); } INLINE GEN mkfrac(GEN x, GEN y) { retmkfrac(x,y); } INLINE GEN mkfracss(long x, long y) { retmkfrac(stoi(x),utoipos(y)); } /* q = n/d a t_FRAC or t_INT; recover (n,d) */ INLINE void Qtoss(GEN q, long *n, long *d) { if (typ(q) == t_INT) { *n = itos(q); *d = 1; } else { *n = itos(gel(q,1)); *d = itou(gel(q,2)); } } INLINE GEN sstoQ(long n, long d) { ulong r; long g, q; if (!n) { if (!d) pari_err_INV("sstoQ",gen_0); return gen_0; } if (d < 0) { d = -d; n = -n; } if (d == 1) return stoi(n); r = labs(n); if (r == 1) retmkfrac(n > 0? gen_1: gen_m1, utoipos(d)); q = udivuu_rem(r, d, &r); if (!r) return n > 0? utoipos(q): utoineg(q); g = ugcd(d,r); /* gcd(n,d) */ if (g != 1) { n /= g; d /= g; } retmkfrac(stoi(n), utoipos(d)); } INLINE GEN uutoQ(ulong n, ulong d) { ulong r; long g, q; if (!n) { if (!d) pari_err_INV("uutoQ",gen_0); return gen_0; } if (d == 1) return utoipos(n); if (n == 1) retmkfrac(gen_1, utoipos(d)); q = udivuu_rem(n,d,&r); if (!r) return utoipos(q); g = ugcd(d,r); /* gcd(n,d) */ if (g != 1) { n /= g; d /= g; } retmkfrac(utoipos(n), utoipos(d)); } INLINE GEN mkfraccopy(GEN x, GEN y) { retmkfrac(icopy(x), icopy(y)); } INLINE GEN mkrfrac(GEN x, GEN y) { GEN v = cgetg(3, t_RFRAC); gel(v,1) = x; gel(v,2) = y; return v; } INLINE GEN mkrfraccopy(GEN x, GEN y) { GEN v = cgetg(3, t_RFRAC); gel(v,1) = gcopy(x); gel(v,2) = gcopy(y); return v; } INLINE GEN mkcomplex(GEN x, GEN y) { retmkcomplex(x,y); } INLINE GEN gen_I(void) { return mkcomplex(gen_0, gen_1); } INLINE GEN cgetc(long l) { retmkcomplex(cgetr(l), cgetr(l)); } INLINE GEN mkquad(GEN n, GEN x, GEN y) { GEN v = cgetg(4, t_QUAD); gel(v,1) = n; gel(v,2) = x; gel(v,3) = y; return v; } /* vecsmall */ INLINE GEN mkvecsmall(long x) { GEN v = cgetg(2, t_VECSMALL); v[1] = x; return v; } INLINE GEN mkvecsmall2(long x,long y) { GEN v = cgetg(3, t_VECSMALL); v[1]=x; v[2]=y; return v; } INLINE GEN mkvecsmall3(long x,long y,long z) { GEN v = cgetg(4, t_VECSMALL); v[1]=x; v[2]=y; v[3]=z; return v; } INLINE GEN mkvecsmall4(long x,long y,long z,long t) { GEN v = cgetg(5, t_VECSMALL); v[1]=x; v[2]=y; v[3]=z; v[4]=t; return v; } INLINE GEN mkvecsmall5(long x,long y,long z,long t,long u) { GEN v = cgetg(6, t_VECSMALL); v[1]=x; v[2]=y; v[3]=z; v[4]=t; v[5]=u; return v; } INLINE GEN mkqfb(GEN x, GEN y, GEN z, GEN d) { retmkqfb(x,y,z,d); } /* vec */ INLINE GEN mkvec(GEN x) { retmkvec(x); } INLINE GEN mkvec2(GEN x, GEN y) { retmkvec2(x,y); } INLINE GEN mkvec3(GEN x, GEN y, GEN z) { retmkvec3(x,y,z); } INLINE GEN mkvec4(GEN x, GEN y, GEN z, GEN t) { retmkvec4(x,y,z,t); } INLINE GEN mkvec5(GEN x, GEN y, GEN z, GEN t, GEN u) { retmkvec5(x,y,z,t,u); } INLINE GEN mkvecs(long x) { retmkvec(stoi(x)); } INLINE GEN mkvec2s(long x, long y) { retmkvec2(stoi(x),stoi(y)); } INLINE GEN mkvec3s(long x, long y, long z) { retmkvec3(stoi(x),stoi(y),stoi(z)); } INLINE GEN mkvec4s(long x, long y, long z, long t) { retmkvec4(stoi(x),stoi(y),stoi(z),stoi(t)); } INLINE GEN mkveccopy(GEN x) { GEN v = cgetg(2, t_VEC); gel(v,1) = gcopy(x); return v; } INLINE GEN mkvec2copy(GEN x, GEN y) { GEN v = cgetg(3,t_VEC); gel(v,1) = gcopy(x); gel(v,2) = gcopy(y); return v; } /* col */ INLINE GEN mkcol(GEN x) { retmkcol(x); } INLINE GEN mkcol2(GEN x, GEN y) { retmkcol2(x,y); } INLINE GEN mkcol3(GEN x, GEN y, GEN z) { retmkcol3(x,y,z); } INLINE GEN mkcol4(GEN x, GEN y, GEN z, GEN t) { retmkcol4(x,y,z,t); } INLINE GEN mkcol5(GEN x, GEN y, GEN z, GEN t, GEN u) { retmkcol5(x,y,z,t,u); } INLINE GEN mkcol6(GEN x, GEN y, GEN z, GEN t, GEN u, GEN v) { retmkcol6(x,y,z,t,u,v); } INLINE GEN mkcols(long x) { retmkcol(stoi(x)); } INLINE GEN mkcol2s(long x, long y) { retmkcol2(stoi(x),stoi(y)); } INLINE GEN mkcol3s(long x, long y, long z) { retmkcol3(stoi(x),stoi(y),stoi(z)); } INLINE GEN mkcol4s(long x, long y, long z, long t) { retmkcol4(stoi(x),stoi(y),stoi(z),stoi(t)); } INLINE GEN mkcolcopy(GEN x) { GEN v = cgetg(2, t_COL); gel(v,1) = gcopy(x); return v; } /* mat */ INLINE GEN mkmat(GEN x) { retmkmat(x); } INLINE GEN mkmat2(GEN x, GEN y) { retmkmat2(x,y); } INLINE GEN mkmat3(GEN x, GEN y, GEN z) { retmkmat3(x,y,z); } INLINE GEN mkmat4(GEN x, GEN y, GEN z, GEN t) { retmkmat4(x,y,z,t); } INLINE GEN mkmat5(GEN x, GEN y, GEN z, GEN t, GEN u) { retmkmat5(x,y,z,t,u); } INLINE GEN mkmatcopy(GEN x) { GEN v = cgetg(2, t_MAT); gel(v,1) = gcopy(x); return v; } INLINE GEN mkerr(long x) { GEN v = cgetg(2, t_ERROR); v[1] = x; return v; } INLINE GEN mkoo(void) { GEN v = cgetg(2, t_INFINITY); gel(v,1) = gen_1; return v; } INLINE GEN mkmoo(void) { GEN v = cgetg(2, t_INFINITY); gel(v,1) = gen_m1; return v; } INLINE long inf_get_sign(GEN x) { return signe(gel(x,1)); } INLINE GEN mkmat22s(long a, long b, long c, long d) {retmkmat2(mkcol2s(a,c),mkcol2s(b,d));} INLINE GEN mkmat22(GEN a, GEN b, GEN c, GEN d) { retmkmat2(mkcol2(a,c),mkcol2(b,d)); } /* 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; } /* x^n, assume n >= 0 */ INLINE GEN pol_xn(long n, long v) { long i, a = n+2; GEN p = cgetg(a+1, t_POL); p[1] = evalsigne(1)|evalvarn(v); for (i = 2; i < a; i++) gel(p,i) = gen_0; gel(p,a) = gen_1; return p; } /* x^n, no assumption on n */ INLINE GEN pol_xnall(long n, long v) { if (n < 0) retmkrfrac(gen_1, pol_xn(-n,v)); return pol_xn(n, v); } /* x^n, assume n >= 0 */ INLINE GEN polxn_Flx(long n, long sv) { long i, a = n+2; GEN p = cgetg(a+1, t_VECSMALL); p[1] = sv; for (i = 2; i < a; i++) p[i] = 0; p[a] = 1; return p; } INLINE GEN pol_1(long v) { GEN p = cgetg(3, t_POL); p[1] = evalsigne(1)|evalvarn(v); gel(p,2) = gen_1; return p; } INLINE GEN pol_0(long v) { GEN x = cgetg(2,t_POL); x[1] = evalvarn(v); return x; } #define retconst_vec(n,x)\ do { long _i, _n = (n);\ GEN _v = cgetg(_n+1, t_VEC), _x = (x);\ for (_i = 1; _i <= _n; _i++) gel(_v,_i) = _x;\ return _v; } while(0) INLINE GEN const_vec(long n, GEN x) { retconst_vec(n, x); } #define retconst_col(n,x)\ do { long _i, _n = (n);\ GEN _v = cgetg(_n+1, t_COL), _x = (x);\ for (_i = 1; _i <= _n; _i++) gel(_v,_i) = _x;\ return _v; } while(0) INLINE GEN const_col(long n, GEN x) { retconst_col(n, x); } INLINE GEN const_vecsmall(long n, long c) { long i; GEN V = cgetg(n+1,t_VECSMALL); for(i=1;i<=n;i++) V[i] = c; return V; } /*** ZERO ***/ /* O(p^e) */ INLINE GEN zeropadic(GEN p, long e) { GEN y = cgetg(5,t_PADIC); gel(y,4) = gen_0; gel(y,3) = gen_1; gel(y,2) = icopy(p); y[1] = evalvalp(e) | _evalprecp(0); return y; } INLINE GEN zeropadic_shallow(GEN p, long e) { GEN y = cgetg(5,t_PADIC); gel(y,4) = gen_0; gel(y,3) = gen_1; gel(y,2) = p; y[1] = evalvalp(e) | _evalprecp(0); return y; } /* O(pol_x(v)^e) */ INLINE GEN zeroser(long v, long e) { GEN x = cgetg(2, t_SER); x[1] = evalvalser(e) | evalvarn(v); return x; } INLINE int ser_isexactzero(GEN x) { if (!signe(x)) switch(lg(x)) { case 2: return 1; case 3: return isexactzero(gel(x,2)); } return 0; } /* 0 * pol_x(v) */ INLINE GEN zeropol(long v) { return pol_0(v); } /* vector(n) */ INLINE GEN zerocol(long n) { GEN y = cgetg(n+1,t_COL); long i; for (i=1; i<=n; i++) gel(y,i) = gen_0; return y; } /* vectorv(n) */ INLINE GEN zerovec(long n) { GEN y = cgetg(n+1,t_VEC); long i; for (i=1; i<=n; i++) gel(y,i) = gen_0; return y; } /* matrix(m, n) */ INLINE GEN zeromat(long m, long n) { GEN y = cgetg(n+1,t_MAT); GEN v = zerocol(m); long i; for (i=1; i<=n; i++) gel(y,i) = v; return y; } /* = zero_zx, sv is a evalvarn()*/ INLINE GEN zero_Flx(long sv) { return pol0_Flx(sv); } INLINE GEN zero_Flv(long n) { GEN y = cgetg(n+1,t_VECSMALL); long i; for (i=1; i<=n; i++) y[i] = 0; return y; } /* matrix(m, n) */ INLINE GEN zero_Flm(long m, long n) { GEN y = cgetg(n+1,t_MAT); GEN v = zero_Flv(m); long i; for (i=1; i<=n; i++) gel(y,i) = v; return y; } /* matrix(m, n) */ INLINE GEN zero_Flm_copy(long m, long n) { GEN y = cgetg(n+1,t_MAT); long i; for (i=1; i<=n; i++) gel(y,i) = zero_Flv(m); return y; } INLINE GEN zero_F2v(long m) { long l = nbits2nlong(m); GEN v = zero_Flv(l+1); v[1] = m; return v; } INLINE GEN zero_F2m(long m, long n) { long i; GEN M = cgetg(n+1, t_MAT); GEN v = zero_F2v(m); for (i = 1; i <= n; i++) gel(M,i) = v; return M; } INLINE GEN zero_F2m_copy(long m, long n) { long i; GEN M = cgetg(n+1, t_MAT); for (i = 1; i <= n; i++) gel(M,i)= zero_F2v(m); return M; } /* matrix(m, n) */ INLINE GEN zeromatcopy(long m, long n) { GEN y = cgetg(n+1,t_MAT); long i; for (i=1; i<=n; i++) gel(y,i) = zerocol(m); return y; } INLINE GEN zerovec_block(long len) { long i; GEN blk = cgetg_block(len + 1, t_VEC); for (i = 1; i <= len; ++i) gel(blk, i) = gen_0; return blk; } /* i-th vector in the standard basis */ INLINE GEN col_ei(long n, long i) { GEN e = zerocol(n); gel(e,i) = gen_1; return e; } INLINE GEN vec_ei(long n, long i) { GEN e = zerovec(n); gel(e,i) = gen_1; return e; } INLINE GEN F2v_ei(long n, long i) { GEN e = zero_F2v(n); F2v_set(e,i); return e; } INLINE GEN vecsmall_ei(long n, long i) { GEN e = zero_zv(n); e[i] = 1; return e; } INLINE GEN Rg_col_ei(GEN x, long n, long i) { GEN e = zerocol(n); gel(e,i) = x; return e; } INLINE GEN shallowcopy(GEN x) { return typ(x) == t_MAT ? RgM_shallowcopy(x): leafcopy(x); } /* routines for naive growarrays */ INLINE GEN vectrunc_init(long l) { GEN z = new_chunk(l); z[0] = evaltyp(t_VEC) | _evallg(1); return z; } INLINE GEN coltrunc_init(long l) { GEN z = new_chunk(l); z[0] = evaltyp(t_COL) | _evallg(1); return z; } INLINE void lg_increase(GEN x) { x[0]++; } INLINE void vectrunc_append(GEN x, GEN t) { gel(x, lg(x)) = t; lg_increase(x); } INLINE void vectrunc_append_batch(GEN x, GEN y) { long i, l = lg(x), ly = lg(y); GEN z = x + l-1; for (i = 1; i < ly; i++) gel(z,i) = gel(y,i); setlg(x, l+ly-1); } INLINE GEN vecsmalltrunc_init(long l) { GEN z = new_chunk(l); z[0] = evaltyp(t_VECSMALL) | _evallg(1); return z; } INLINE void vecsmalltrunc_append(GEN x, long t) { x[ lg(x) ] = t; lg_increase(x); } /*******************************************************************/ /* */ /* STRING HASH FUNCTIONS */ /* */ /*******************************************************************/ INLINE ulong hash_str(const char *str) { ulong hash = 5381UL, c; while ( (c = (ulong)*str++) ) hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ return hash; } INLINE ulong hash_str_len(const char *str, long len) { ulong hash = 5381UL; long i; for (i = 0; i < len; i++) { ulong c = (ulong)*str++; hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ } return hash; } /*******************************************************************/ /* */ /* VEC / COL / VECSMALL */ /* */ /*******************************************************************/ /* shallow*/ INLINE GEN vec_shorten(GEN v, long n) { GEN V = cgetg(n+1, t_VEC); long i; for(i = 1; i <= n; i++) gel(V,i) = gel(v,i); return V; } /* shallow*/ INLINE GEN vec_lengthen(GEN v, long n) { GEN V = cgetg(n+1, t_VEC); long i, l = lg(v); for(i = 1; i < l; i++) gel(V,i) = gel(v,i); return V; } /* shallow*/ INLINE GEN vec_append(GEN V, GEN s) { long i, l2 = lg(V); GEN res = cgetg(l2+1, typ(V)); for (i = 1; i < l2; i++) gel(res, i) = gel(V,i); gel(res,l2) = s; return res; } /* shallow*/ INLINE GEN vec_prepend(GEN v, GEN s) { long i, l = lg(v); GEN w = cgetg(l+1, typ(v)); gel(w,1) = s; for (i = 2; i <= l; i++) gel(w,i) = gel(v,i-1); return w; } /* shallow*/ INLINE GEN vec_setconst(GEN v, GEN x) { long i, l = lg(v); for (i = 1; i < l; i++) gel(v,i) = x; return v; } INLINE GEN vecsmall_shorten(GEN v, long n) { GEN V = cgetg(n+1,t_VECSMALL); long i; for(i = 1; i <= n; i++) V[i] = v[i]; return V; } INLINE GEN vecsmall_lengthen(GEN v, long n) { long i, l = lg(v); GEN V = cgetg(n+1,t_VECSMALL); for(i = 1; i < l; i++) V[i] = v[i]; return V; } INLINE GEN vec_to_vecsmall(GEN x) { pari_APPLY_long(itos(gel(x,i))) } INLINE GEN vecsmall_to_vec(GEN x) { pari_APPLY_type(t_VEC, stoi(x[i])) } INLINE GEN vecsmall_to_vec_inplace(GEN z) { long i, l = lg(z); for (i=1; i t) t = x[i0=i]; return i0; } INLINE long vecsmall_max(GEN x) { long i, t = x[1], lx = lg(x); for (i=2; i t) t = x[i]; return t; } INLINE long vecsmall_indexmin(GEN x) { long i, i0 = 1, t = x[1], lx =lg(x); for (i=2; i 1) if (signe(gel(x, l))) return 0; return 1; } INLINE int QV_isscalar(GEN x) { long lx = lg(x),i; for (i=2; i2; i--) if (!gequal0(gel(x, i))) return 0; return 1; } INLINE long RgX_equal_var(GEN x, GEN y) { return varn(x) == varn(y) && RgX_equal(x,y); } INLINE GEN RgX_to_RgV(GEN x, long N) { x = RgX_to_RgC(x, N); settyp(x, t_VEC); return x; } INLINE int RgX_is_rational(GEN x) { long i; for (i = lg(x)-1; i > 1; i--) if (!is_rational_t(typ(gel(x,i)))) return 0; return 1; } INLINE int RgX_is_ZX(GEN x) { long i; for (i = lg(x)-1; i > 1; i--) if (typ(gel(x,i)) != t_INT) return 0; return 1; } INLINE int RgX_is_QX(GEN x) { long k = lg(x)-1; for ( ; k>1; k--) if (!is_rational_t(typ(gel(x,k)))) return 0; return 1; } INLINE int RgX_is_monomial(GEN x) { long i; if (!signe(x)) return 0; for (i=lg(x)-2; i>1; i--) if (!isexactzero(gel(x,i))) return 0; return 1; } INLINE int RgV_is_ZV(GEN x) { long i; for (i = lg(x)-1; i > 0; i--) if (typ(gel(x,i)) != t_INT) return 0; return 1; } INLINE int RgV_is_QV(GEN x) { long i; for (i = lg(x)-1; i > 0; i--) if (!is_rational_t(typ(gel(x,i)))) return 0; return 1; } INLINE long RgV_isin_i(GEN v, GEN x, long n) { long i; for (i = 1; i <= n; i++) if (gequal(gel(v,i), x)) return i; return 0; } INLINE long RgV_isin(GEN v, GEN x) { return RgV_isin_i(v, x, lg(v)-1); } /********************************************************************/ /** **/ /** Dynamic arrays implementation **/ /** **/ /********************************************************************/ INLINE void ** pari_stack_base(pari_stack *s) { return s->data; } INLINE void pari_stack_init(pari_stack *s, size_t size, void **data) { s->data = data; *data = NULL; s->n = 0; s->alloc = 0; s->size = size; } INLINE void pari_stack_alloc(pari_stack *s, long nb) { void **sdat = pari_stack_base(s); long alloc = s->alloc; if (s->n+nb <= alloc) return; if (!alloc) alloc = nb; else { while (s->n+nb > alloc) alloc <<= 1; } pari_realloc_ip(sdat,alloc*s->size); s->alloc = alloc; } INLINE long pari_stack_new(pari_stack *s) { pari_stack_alloc(s, 1); return s->n++; } INLINE void pari_stack_delete(pari_stack *s) { void **sdat = pari_stack_base(s); if (*sdat) pari_free(*sdat); } INLINE void pari_stack_pushp(pari_stack *s, void *u) { long n = pari_stack_new(s); void **sdat =(void**) *pari_stack_base(s); sdat[n] = u; } /*******************************************************************/ /* */ /* EXTRACT */ /* */ /*******************************************************************/ INLINE GEN vecslice(GEN A, long y1, long y2) { long i,lB = y2 - y1 + 2; GEN B = cgetg(lB, typ(A)); for (i=1; i>1, i; for (i = 1; i <= lim; i++) { GEN z = gel(y,i); gel(y,i) = gel(y,l-i); gel(y,l-i) = z; } } INLINE GEN vecsmallpermute(GEN A, GEN p) { return perm_mul(A, p); } INLINE GEN vecpermute(GEN A, GEN x) { pari_APPLY_type(typ(A), gel(A, x[i])) } INLINE GEN veclast(GEN A) { return gel(A, lg(A)-1); } INLINE GEN rowpermute(GEN x, GEN p) { pari_APPLY_same(typ(gel(x,i)) == t_VECSMALL ? vecsmallpermute(gel(x, i), p) : vecpermute(gel(x, i), p)) } /*******************************************************************/ /* */ /* PERMUTATIONS */ /* */ /*******************************************************************/ INLINE GEN identity_zv(long n) { GEN v = cgetg(n+1, t_VECSMALL); long i; for (i = 1; i <= n; i++) v[i] = i; return v; } INLINE GEN identity_ZV(long n) { GEN v = cgetg(n+1, t_VEC); long i; for (i = 1; i <= n; i++) gel(v,i) = utoipos(i); return v; } /* identity permutation */ INLINE GEN identity_perm(long n) { return identity_zv(n); } /* assume d <= n */ INLINE GEN cyclic_perm(long n, long d) { GEN perm = cgetg(n+1, t_VECSMALL); long i; for (i = 1; i <= n-d; i++) perm[i] = i+d; for ( ; i <= n; i++) perm[i] = i-n+d; return perm; } /* Multiply (compose) two permutations */ INLINE GEN perm_mul(GEN s, GEN x) { pari_APPLY_long(s[x[i]]) } INLINE GEN perm_sqr(GEN x) { pari_APPLY_long(x[x[i]]) } /* Compute the inverse (reciprocal) of a permutation. */ INLINE GEN perm_inv(GEN x) { long i, lx; GEN y = cgetg_copy(x, &lx); for (i=1; i 0) y[i] = x[i]; y[0] = evaltyp(t_INT)|evallg(lx); return y; } /* copy leaf x as if we had set_avma(av) */ INLINE GEN leafcopy_avma(GEN x, pari_sp av) { long i = lg(x); GEN y = ((GEN)av) - i; while (--i > 0) y[i] = x[i]; y[0] = x[0] & (~CLONEBIT); return y; } INLINE GEN gerepileuptoleaf(pari_sp av, GEN x) { long lx; GEN q; if (!isonstack(x) || (GEN)av<=x) return gc_const(av,x); lx = lg(x); q = ((GEN)av) - lx; set_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) return gc_const(av,x); set_avma((pari_sp)icopy_avma(x, av)); return (GEN)avma; } INLINE GEN gerepileupto(pari_sp av, GEN x) { if (!isonstack(x) || (GEN)av<=x) return gc_const(av,x); switch(typ(x)) { /* non-default = !is_recursive_t(tq) */ case t_INT: return gerepileuptoint(av, x); case t_REAL: case t_STR: case t_VECSMALL: return gerepileuptoleaf(av,x); default: /* NB: x+i --> ((long)x) + i*sizeof(long) */ return gerepile(av, (pari_sp) (x+lg(x)), x); } } /* gerepileupto(av, gcopy(x)) */ INLINE GEN gerepilecopy(pari_sp av, GEN x) { if (is_recursive_t(typ(x))) { GENbin *p = copy_bin(x); set_avma(av); return bin_copy(p); } else { set_avma(av); if (x < (GEN)av) { if (x < (GEN)pari_mainstack->bot) new_chunk(lg(x)); x = leafcopy_avma(x, av); set_avma((pari_sp)x); } else x = leafcopy(x); return x; } } INLINE void guncloneNULL(GEN x) { if (x) gunclone(x); } INLINE void guncloneNULL_deep(GEN x) { if (x) gunclone_deep(x); } /* Takes an array of pointers to GENs, of length n. Copies all * objects to contiguous locations and cleans up the stack between * av and avma. */ INLINE void gerepilemany(pari_sp av, GEN* gptr[], int n) { int i; for (i=0; i=0; i--) *gptr[i] = bin_copy((GENbin*)*gptr[i]); } else { GEN **gptr = (GEN**) pari_malloc(n*sizeof(GEN*)); for (i=0; i=0; i--) *gptr[i] = bin_copy((GENbin*)*gptr[i]); pari_free(gptr); } va_end(a); } /* assume 1 <= n < 10 */ INLINE GEN gc_all(pari_sp av, int n, ...) { int i; GEN *v[10]; va_list a; va_start(a, n); 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; p->rebase(y, ((ulong)y-(ulong)x)); 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)) set_avma(av); } INLINE void killblock(GEN x) { gunclone(x); } INLINE int is_universal_constant(GEN x) { return (x >= gen_0 && x <= ghalf); } /*******************************************************************/ /* */ /* CONVERSION / ASSIGNMENT */ /* */ /*******************************************************************/ /* z is a type which may be a t_COMPLEX component (not a t_QUAD) */ INLINE GEN cxcompotor(GEN z, long prec) { switch(typ(z)) { case t_INT: return itor(z, prec); case t_FRAC: return fractor(z, prec); case t_REAL: return rtor(z, prec); default: pari_err_TYPE("cxcompotor",z); return NULL; /* LCOV_EXCL_LINE */ } } INLINE GEN cxtofp(GEN x, long prec) { retmkcomplex(cxcompotor(gel(x,1),prec), cxcompotor(gel(x,2),prec)); } INLINE GEN cxtoreal(GEN q) { return (typ(q) == t_COMPLEX && gequal0(gel(q,2)))? gel(q,1): q; } INLINE double gtodouble(GEN x) { if (typ(x)!=t_REAL) { pari_sp av = avma; x = gtofp(x, DEFAULTPREC); if (typ(x)!=t_REAL) pari_err_TYPE("gtodouble [t_REAL expected]", x); set_avma(av); } return rtodbl(x); } INLINE int gisdouble(GEN x, double *g) { if (typ(x)!=t_REAL) { pari_sp av = avma; x = gtofp(x, DEFAULTPREC); if (typ(x)!=t_REAL) pari_err_TYPE("gisdouble [t_REAL expected]", x); set_avma(av); } if (expo(x) >= 0x3ff) return 0; *g = rtodbl(x); return 1; } INLINE long gtos(GEN x) { if (typ(x) != t_INT) pari_err_TYPE("gtos [integer expected]",x); return itos(x); } INLINE ulong gtou(GEN x) { if (typ(x) != t_INT || signe(x)<0) pari_err_TYPE("gtou [integer >=0 expected]",x); return itou(x); } INLINE GEN absfrac(GEN x) { GEN y = cgetg(3, t_FRAC); gel(y,1) = absi(gel(x,1)); gel(y,2) = icopy(gel(x,2)); return y; } INLINE GEN absfrac_shallow(GEN x) { return signe(gel(x,1))>0? x: mkfrac(negi(gel(x,1)), gel(x,2)); } INLINE GEN Q_abs(GEN x) { return (typ(x) == t_INT)? absi(x): absfrac(x); } INLINE GEN Q_abs_shallow(GEN x) { return (typ(x) == t_INT)? absi_shallow(x): absfrac_shallow(x); } INLINE GEN R_abs_shallow(GEN x) { return (typ(x) == t_FRAC)? absfrac_shallow(x): mpabs_shallow(x); } INLINE GEN R_abs(GEN x) { return (typ(x) == t_FRAC)? absfrac(x): mpabs(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) - prec); gel(y,2) = b; return y; } return cxtofp(z, prec); } case t_QUAD: return quadtofp(z, prec); default: pari_err_TYPE("gtofp",z); return NULL; /* LCOV_EXCL_LINE */ } } /* Force z to be of type real / int */ INLINE GEN gtomp(GEN z, long prec) { switch(typ(z)) { case t_INT: return z; case t_FRAC: return fractor(z, prec); case t_REAL: return rtor(z, prec); case t_QUAD: z = quadtofp(z, prec); if (typ(z) == t_REAL) return z; default: pari_err_TYPE("gtomp",z); return NULL; /* LCOV_EXCL_LINE */ } } 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) { pari_APPLY_type(t_COL, gtofp(gel(x,i), prec)) } INLINE GEN RgV_gtofp(GEN x, long prec) { pari_APPLY_type(t_VEC, gtofp(gel(x,i), prec)) } INLINE GEN RgM_gtofp(GEN x, long prec) { pari_APPLY_same(RgC_gtofp(gel(x,i), prec)) } INLINE GEN RgC_gtomp(GEN x, long prec) { pari_APPLY_type(t_COL, gtomp(gel(x,i), prec)) } INLINE GEN RgM_gtomp(GEN x, long prec) { pari_APPLY_same(RgC_gtomp(gel(x,i), prec)) } INLINE GEN RgX_fpnorml2(GEN x, long prec) { pari_sp av = avma; return gerepileupto(av, gnorml2(RgX_gtofp(x, prec))); } INLINE GEN RgC_fpnorml2(GEN x, long prec) { pari_sp av = avma; return gerepileupto(av, gnorml2(RgC_gtofp(x, prec))); } INLINE GEN RgM_fpnorml2(GEN x, long prec) { pari_sp av = avma; return gerepileupto(av, gnorml2(RgM_gtofp(x, prec))); } /* y a t_REAL */ INLINE void affgr(GEN x, GEN y) { pari_sp av; switch(typ(x)) { case t_INT: affir(x,y); break; case t_REAL: affrr(x,y); break; case t_FRAC: rdiviiz(gel(x,1),gel(x,2), y); break; case t_QUAD: av = avma; affgr(quadtofp(x,realprec(y)), y); set_avma(av); break; default: pari_err_TYPE2("=",x,y); } } INLINE GEN affc_fixlg(GEN x, GEN res) { if (typ(x) == t_COMPLEX) { affrr_fixlg(gel(x,1), gel(res,1)); affrr_fixlg(gel(x,2), gel(res,2)); } else { set_avma((pari_sp)(res+3)); res = cgetr(realprec(gel(res,1))); affrr_fixlg(x, res); } return res; } INLINE GEN trunc_safe(GEN x) { long e; return gcvtoi(x,&e); } /*******************************************************************/ /* */ /* LENGTH CONVERSIONS */ /* */ /*******************************************************************/ INLINE long ndec2nlong(long x) { return 1 + (long)((x)*(LOG2_10/BITS_IN_LONG)); } INLINE long ndec2prec(long x) { return ndec2nlong(x) << TWOPOTBITS_IN_LONG; } INLINE long ndec2nbits(long x) { return ndec2nlong(x) << TWOPOTBITS_IN_LONG; } /* Fast implementation of ceil(x / (8*sizeof(long))); typecast to (ulong) * to avoid overflow. Faster than 1 + ((x-1)>>TWOPOTBITS_IN_LONG)) : * addl, shrl instead of subl, sarl, addl */ INLINE long nbits2nlong(long x) { return (long)(((ulong)x+BITS_IN_LONG-1) >> TWOPOTBITS_IN_LONG); } INLINE long nbits2extraprec(long x) { return (((ulong)x+BITS_IN_LONG-1)>>TWOPOTBITS_IN_LONG) << TWOPOTBITS_IN_LONG; } INLINE long nbits2prec(long x) { return (((ulong)x+BITS_IN_LONG-1)>>TWOPOTBITS_IN_LONG) << TWOPOTBITS_IN_LONG; } INLINE long prec2lg(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 prec2nbits(long x) { return x; } INLINE double bit_accuracy_mul(long x, double y) { return (x-2) * (BITS_IN_LONG*y); } INLINE double prec2nbits_mul(long x, double y) { return x * y; } INLINE long bit_prec(GEN x) { return realprec(x); } INLINE long bit_accuracy(long x) { return (x-2) * BITS_IN_LONG; } INLINE long prec2ndec(long x) { return (long)(x * LOG10_2); } INLINE long nbits2ndec(long x) { return prec2ndec(x); } INLINE long precdbl(long x) {return x << 1;} INLINE long divsBIL(long n) { return n >> TWOPOTBITS_IN_LONG; } INLINE long remsBIL(long n) { return n & (BITS_IN_LONG-1); } /*********************************************************************/ /** **/ /** OPERATIONS MODULO m **/ /** **/ /*********************************************************************/ /* Assume m > 0, more efficient if 0 <= a, b < m */ INLINE GEN Fp_red(GEN a, GEN m) { return modii(a, m); } INLINE GEN Fp_add(GEN a, GEN b, GEN m) { pari_sp av=avma; GEN p = addii(a,b); long s = signe(p); if (!s) return p; /* = gen_0 */ if (s > 0) /* general case */ { GEN t = subii(p, m); s = signe(t); if (!s) return gc_const(av, gen_0); if (s < 0) return gc_const((pari_sp)p, 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_double(GEN x, GEN N) { GEN z = shifti(x, 1); return cmpii(z, N) >= 0? subii(z, N): z; } 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) return gc_const(av, 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); } INLINE GEN Fp_halve(GEN a, GEN p) { if (mpodd(a)) a = addii(a,p); return shifti(a,-1); } /* assume 0 <= u < p and ps2 = p>>1 */ INLINE GEN Fp_center(GEN u, GEN p, GEN ps2) { return abscmpii(u,ps2)<=0? icopy(u): subii(u,p); } /* same without copy */ INLINE GEN Fp_center_i(GEN u, GEN p, GEN ps2) { return abscmpii(u,ps2)<=0? u: subii(u,p); } /* x + y*z mod p */ INLINE GEN Fp_addmul(GEN x, GEN y, GEN z, GEN p) { pari_sp av; if (!signe(y) || !signe(z)) return Fp_red(x, p); if (!signe(x)) return Fp_mul(z,y, p); av = avma; return gerepileuptoint(av, modii(addii(x, mulii(y,z)), p)); } INLINE GEN Fp_mul(GEN a, GEN b, GEN m) { pari_sp av=avma; GEN p; /*HACK: assume modii use <=lg(p)+(lg(m)<<1) space*/ (void)new_chunk(lg(a)+lg(b)+(lg(m)<<1)); p = mulii(a,b); set_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); set_avma(av); return remii(p,m); /*Use remii: p >= 0 */ } 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); set_avma(av); return modii(p,m); } } INLINE GEN Fp_muls(GEN a, long b, GEN m) { long l = lgefint(m); if (l == 3) { ulong mm = m[2]; if (b < 0) { ulong t = Fl_mul(umodiu(a, mm), -b, mm); return t? utoipos(mm - t): gen_0; } else return utoi( Fl_mul(umodiu(a, mm), b, mm) ); } else { pari_sp av = avma; GEN p; /*HACK: assume modii use <=lg(p)+(lg(m)<<1) space*/ (void)new_chunk(lg(a)+1+(l<<1)); p = mulis(a,b); set_avma(av); return modii(p,m); } } INLINE GEN Fp_inv(GEN a, GEN m) { GEN res; if (! invmod(a,m,&res)) pari_err_INV("Fp_inv", mkintmod(res,m)); return res; } INLINE GEN Fp_invsafe(GEN a, GEN m) { GEN res; if (! invmod(a,m,&res)) return NULL; return res; } INLINE GEN Fp_div(GEN a, GEN b, GEN m) { pari_sp av = avma; GEN p; if (lgefint(b) == 3) { a = Fp_divu(a, b[2], m); if (signe(b) < 0) a = Fp_neg(a, m); return a; } /*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)); set_avma(av); return modii(p,m); } INLINE GEN Fp_divu(GEN x, ulong a, GEN p) { pari_sp av = avma; ulong b; if (lgefint(p) == 3) { ulong pp = p[2], xp = umodiu(x, pp); return xp? utoipos(Fl_div(xp, a % pp, pp)): gen_0; } x = Fp_red(x, p); b = Fl_neg(Fl_div(umodiu(x,a), umodiu(p,a), a), a); /* x + pb = 0 (mod a) */ return gerepileuptoint(av, diviuexact(addmuliu(x, p, b), a)); } INLINE GEN Flx_mulu(GEN x, ulong a, ulong p) { return Flx_Fl_mul(x,a%p,p); } INLINE GEN get_F2x_mod(GEN T) { return typ(T)==t_VEC? gel(T,2): T; } INLINE long get_F2x_var(GEN T) { return typ(T)==t_VEC? mael(T,2,1): T[1]; } INLINE long get_F2x_degree(GEN T) { return typ(T)==t_VEC? F2x_degree(gel(T,2)): F2x_degree(T); } INLINE GEN get_F2xqX_mod(GEN T) { return typ(T)==t_VEC? gel(T,2): T; } INLINE long get_F2xqX_var(GEN T) { return typ(T)==t_VEC? varn(gel(T,2)): varn(T); } INLINE long get_F2xqX_degree(GEN T) { return typ(T)==t_VEC? degpol(gel(T,2)): degpol(T); } INLINE GEN get_Flx_mod(GEN T) { return typ(T)==t_VEC? gel(T,2): T; } INLINE long get_Flx_var(GEN T) { return typ(T)==t_VEC? mael(T,2,1): T[1]; } INLINE long get_Flx_degree(GEN T) { return typ(T)==t_VEC? degpol(gel(T,2)): degpol(T); } INLINE GEN get_FlxqX_mod(GEN T) { return typ(T)==t_VEC? gel(T,2): T; } INLINE long get_FlxqX_var(GEN T) { return typ(T)==t_VEC? varn(gel(T,2)): varn(T); } INLINE long get_FlxqX_degree(GEN T) { return typ(T)==t_VEC? degpol(gel(T,2)): degpol(T); } INLINE GEN get_FpX_mod(GEN T) { return typ(T)==t_VEC? gel(T,2): T; } INLINE long get_FpX_var(GEN T) { return typ(T)==t_VEC? varn(gel(T,2)): varn(T); } INLINE long get_FpX_degree(GEN T) { return typ(T)==t_VEC? degpol(gel(T,2)): degpol(T); } INLINE GEN get_FpXQX_mod(GEN T) { return typ(T)==t_VEC? gel(T,2): T; } INLINE long get_FpXQX_var(GEN T) { return typ(T)==t_VEC? varn(gel(T,2)): varn(T); } INLINE long get_FpXQX_degree(GEN T) { return typ(T)==t_VEC? degpol(gel(T,2)): degpol(T); } /*******************************************************************/ /* */ /* ADDMULII / SUBMULII */ /* */ /*******************************************************************/ /* x - y*z */ INLINE GEN submulii(GEN x, GEN y, GEN z) { long lx = lgefint(x), ly, lz; pari_sp av; GEN t; if (lx == 2) { t = mulii(z,y); togglesign(t); return t; } ly = lgefint(y); if (ly == 2) return icopy(x); lz = lgefint(z); av = avma; (void)new_chunk(lx+ly+lz); /* HACK */ t = mulii(z, y); set_avma(av); return subii(x,t); } /* y*z - x */ INLINE GEN mulsubii(GEN y, GEN z, GEN x) { long lx = lgefint(x), ly, lz; pari_sp av; GEN t; if (lx == 2) return mulii(z,y); ly = lgefint(y); if (ly == 2) return negi(x); lz = lgefint(z); av = avma; (void)new_chunk(lx+ly+lz); /* HACK */ t = mulii(z, y); set_avma(av); return subii(t,x); } /* x - u*y */ INLINE GEN submuliu(GEN x, GEN y, ulong u) { pari_sp av; long ly = lgefint(y); if (ly == 2) return icopy(x); av = avma; (void)new_chunk(3+ly+lgefint(x)); /* HACK */ y = mului(u,y); set_avma(av); return subii(x, y); } /* x + u*y */ INLINE GEN addmuliu(GEN x, GEN y, ulong u) { pari_sp av; long ly = lgefint(y); if (ly == 2) return icopy(x); av = avma; (void)new_chunk(3+ly+lgefint(x)); /* HACK */ y = mului(u,y); set_avma(av); return addii(x, y); } /* x - u*y */ INLINE GEN submuliu_inplace(GEN x, GEN y, ulong u) { pari_sp av; long ly = lgefint(y); if (ly == 2) return x; av = avma; (void)new_chunk(3+ly+lgefint(x)); /* HACK */ y = mului(u,y); set_avma(av); return subii(x, y); } /* x + u*y */ INLINE GEN addmuliu_inplace(GEN x, GEN y, ulong u) { pari_sp av; long ly = lgefint(y); if (ly == 2) return x; av = avma; (void)new_chunk(3+ly+lgefint(x)); /* HACK */ y = mului(u,y); set_avma(av); return addii(x, y); } /* ux + vy */ INLINE GEN lincombii(GEN u, GEN v, GEN x, GEN y) { long lx = lgefint(x), ly; GEN p1, p2; pari_sp av; if (lx == 2) return mulii(v,y); ly = lgefint(y); if (ly == 2) return mulii(u,x); av = avma; (void)new_chunk(lx+ly+lgefint(u)+lgefint(v)); /* HACK */ p1 = mulii(u,x); p2 = mulii(v,y); set_avma(av); return addii(p1,p2); } /*******************************************************************/ /* */ /* GEN SUBTYPES */ /* */ /*******************************************************************/ INLINE int is_const_t(long t) { return (t < t_POLMOD); } INLINE int is_extscalar_t(long t) { return (t <= t_POL); } INLINE int is_intreal_t(long t) { return (t <= t_REAL); } INLINE int is_matvec_t(long t) { return (t >= t_VEC && t <= t_MAT); } INLINE int is_noncalc_t(long tx) { return (tx) >= t_LIST; } INLINE int is_qfb_t(long t) { return (t == t_QFB); } INLINE int is_rational_t(long t) { return (t == t_INT || t == t_FRAC); } INLINE int is_real_t(long t) { return (t == t_INT || t == t_REAL || 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); } INLINE int qfb_is_qfi(GEN q) { return signe(gel(q,4)) < 0; } /*******************************************************************/ /* */ /* TRANSCENDENTAL */ /* */ /*******************************************************************/ INLINE GEN sqrtr(GEN x) { long s = signe(x); if (s == 0) return real_0_bit(expo(x) >> 1); if (s >= 0) return sqrtr_abs(x); retmkcomplex(gen_0, sqrtr_abs(x)); } INLINE GEN cbrtr_abs(GEN x) { return sqrtnr_abs(x, 3); } INLINE GEN cbrtr(GEN x) { long s = signe(x); GEN r; if (s == 0) return real_0_bit(expo(x) / 3); r = cbrtr_abs(x); if (s < 0) togglesign(r); return r; } INLINE GEN sqrtnr(GEN x, long n) { long s = signe(x); GEN r; if (s == 0) return real_0_bit(expo(x) / n); r = sqrtnr_abs(x, n); if (s < 0) pari_err_IMPL("sqrtnr for x < 0"); return r; } INLINE long logint(GEN B, GEN y) { return logintall(B,y,NULL); } INLINE ulong ulogint(ulong B, ulong y) { ulong r; long e; if (y == 2) return expu(B); r = y; for (e=1;; e++) { /* here, r = y^e, r2 = y^(e-1) */ if (r >= B) return r == B? e: e-1; r = umuluu_or_0(y, r); if (!r) return e; } } /*******************************************************************/ /* */ /* 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 >= pari_mainstack->bot && (pari_sp)x < pari_mainstack->top); } /* 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 inv_content(GEN c) { return c? ginv(c): NULL; } INLINE GEN div_content(GEN cx, GEN cy) { if (!cy) return cx; if (!cx) return ginv(cy); return gdiv(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_coeff(GEN x) { return signe(x)? gel(x,2): gen_0; } INLINE GEN leading_coeff(GEN x) { return lg(x) == 2? gen_0: gel(x,lg(x)-1); } INLINE ulong Flx_lead(GEN x) { return lg(x) == 2? 0: x[lg(x)-1]; } INLINE ulong Flx_constant(GEN x) { return lg(x) == 2? 0: x[2]; } INLINE long degpol(GEN x) { return lg(x)-3; } INLINE long lgpol(GEN x) { return lg(x)-2; } INLINE long lgcols(GEN x) { return lg(gel(x,1)); } INLINE long nbrows(GEN x) { return lg(gel(x,1))-1; } INLINE GEN truecoef(GEN x, long n) { return polcoef(x,n,-1); } INLINE GEN ZXQ_mul(GEN y, GEN x, GEN T) { return ZX_rem(ZX_mul(y, x), T); } INLINE GEN ZXQ_sqr(GEN x, GEN T) { return ZX_rem(ZX_sqr(x), T); } INLINE GEN RgX_copy(GEN x) { long lx, i; GEN y = cgetg_copy(x, &lx); y[1] = x[1]; for (i = 2; i l)? gen_0: gel(x,n+2); } INLINE GEN RgX_renormalize(GEN x) { return RgX_renormalize_lg(x, lg(x)); } INLINE GEN RgX_div(GEN x, GEN y) { return RgX_divrem(x,y,NULL); } 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 Flx_div_pre(GEN x, GEN y, ulong p, ulong pi) { return Flx_divrem_pre(x,y,p,pi, 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 int F2x_equal(GEN V, GEN W) { return Flx_equal(V,W); } INLINE GEN F2x_copy(GEN x) { return leafcopy(x); } INLINE GEN F2v_copy(GEN x) { return leafcopy(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 int ZX_equal1(GEN x) { return degpol(x)==0 && equali1(gel(x,2)); } INLINE int ZX_is_monic(GEN x) { return equali1(leading_coeff(x)); } INLINE GEN ZX_renormalize(GEN x, long lx) { return ZXX_renormalize(x,lx); } INLINE GEN FpX_renormalize(GEN x, long lx) { return ZXX_renormalize(x,lx); } INLINE GEN FpXX_renormalize(GEN x, long lx) { return ZXX_renormalize(x,lx); } INLINE GEN FpXQX_renormalize(GEN x, long lx) { return ZXX_renormalize(x,lx); } INLINE GEN F2x_renormalize(GEN x, long lx) { return Flx_renormalize(x,lx); } INLINE GEN F2xX_shift(GEN a, long n, long vs) { return FlxX_shift(a, n, vs); } INLINE GEN F2v_to_F2x(GEN x, long sv) { GEN y = leafcopy(x); y[1] = sv; F2x_renormalize(y, lg(y)); return y; } INLINE long sturm(GEN x) { return sturmpart(x, NULL, NULL); } INLINE long gval(GEN x, long v) { pari_sp av = avma; return gc_long(av, gvaluation(x, pol_x(v))); } 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 z; if (!v) return x; lx = lg(x); if (lx == 2) return x; z = x + lx; /* stackdummy's from normalizepol */ while (lg(z) != v) z += lg(z); z += v; for (i = lx-1; i >= 2; i--) gel(--z,0) = gel(x,i); for (i = 0; i < v; i++) gel(--z,0) = gen_0; z -= 2; z[1] = x[1]; z[0] = evaltyp(t_POL) | evallg(lx+v); stackdummy((pari_sp)z, (pari_sp)x); return z; } /* 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 zm_row(GEN x, long i) { return Flm_row(x,i); } INLINE GEN ZC_hnfrem(GEN x, GEN y) { return ZC_hnfremdiv(x,y,NULL); } INLINE GEN ZM_hnfrem(GEN x, GEN y) { return ZM_hnfdivrem(x,y,NULL); } INLINE GEN ZM_lll(GEN x, double D, long f) { return ZM_lll_norms(x,D,f,NULL); } INLINE void RgM_dimensions(GEN x, long *m, long *n) { *n = lg(x)-1; *m = *n? nbrows(x): 0; } INLINE GEN RgM_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 F3m_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; } INLINE GEN ZM_ZV_mod(GEN x, GEN y) { pari_APPLY_same(ZV_ZV_mod(gel(x,i), y)) } INLINE GEN ZV_ZV_mod(GEN x, GEN y) { pari_APPLY_same(modii(gel(x,i), gel(y,i))) } INLINE GEN vecmodii(GEN x, GEN y) { return ZV_ZV_mod(x,y); } INLINE GEN vecmoduu(GEN x, GEN y) { pari_APPLY_ulong(((ulong*)x)[i] % ((ulong*)y)[i]) } /* 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); } INLINE GEN Fq_to_FpXQ(GEN x, GEN T, GEN p /*unused*/) { (void) p; return typ(x)==t_INT ? scalarpol(x, get_FpX_var(T)): x; } INLINE GEN Rg_to_Fq(GEN x, GEN T, GEN p) { return T? Rg_to_FpXQ(x,T,p): Rg_to_Fp(x,p); } INLINE GEN gener_Fq_local(GEN T, GEN p, GEN L) { return T? gener_FpXQ_local(T,p, L) : pgener_Fp_local(p, L); } INLINE GEN random_Fq(GEN T, GEN p) { return T ? random_FpX(get_FpX_degree(T), get_FpX_var(T), p): randomi(p); } /* FpXQX */ INLINE GEN FpXQX_div(GEN x, GEN y, GEN T, GEN p) { return FpXQX_divrem(x, y, T, p, NULL); } INLINE GEN FlxqX_div(GEN x, GEN y, GEN T, ulong p) { return FlxqX_divrem(x, y, T, p, NULL); } INLINE GEN FlxqX_div_pre(GEN x, GEN y, GEN T, ulong p, ulong pi) { return FlxqX_divrem_pre(x, y, T, p, pi, NULL); } INLINE GEN F2xqX_div(GEN x, GEN y, GEN T) { return F2xqX_divrem(x, y, T, NULL); } INLINE GEN FpXY_Fq_evaly(GEN Q, GEN y, GEN T, GEN p, long vx) { return T ? FpXY_FpXQ_evaly(Q, y, T, p, vx): FpXY_evaly(Q, y, p, vx); } /* FqX */ INLINE GEN FqX_red(GEN z, GEN T, GEN p) { return T? FpXQX_red(z, T, p): FpX_red(z, p); } INLINE GEN FqX_add(GEN x,GEN y,GEN T,GEN p) { return T? FpXX_add(x,y,p): FpX_add(x,y,p); } INLINE GEN FqX_neg(GEN x,GEN T,GEN p) { return T? FpXX_neg(x,p): FpX_neg(x,p); } INLINE GEN FqX_sub(GEN x,GEN y,GEN T,GEN p) { return T? FpXX_sub(x,y,p): FpX_sub(x,y,p); } INLINE GEN FqX_Fp_mul(GEN P, GEN u, GEN T, GEN p) { return T? FpXX_Fp_mul(P, u, p): FpX_Fp_mul(P, u, p); } INLINE GEN FqX_Fq_mul(GEN P, GEN U, GEN T, GEN p) { return typ(U)==t_INT ? FqX_Fp_mul(P, U, T, p): FpXQX_FpXQ_mul(P, U, T, p); } INLINE GEN FqX_mul(GEN x, GEN y, GEN T, GEN p) { return T? FpXQX_mul(x, y, T, p): FpX_mul(x, y, p); } INLINE GEN FqX_mulu(GEN x, ulong y, GEN T, GEN p) { return T? FpXX_mulu(x, y, p): FpX_mulu(x, y, p); } INLINE GEN FqX_sqr(GEN x, GEN T, GEN p) { return T? FpXQX_sqr(x, T, p): FpX_sqr(x, p); } INLINE GEN FqX_powu(GEN x, ulong n, GEN T, GEN p) { return T? FpXQX_powu(x, n, T, p): FpX_powu(x, n, p); } INLINE GEN FqX_halve(GEN x, GEN T, GEN p) { return T? FpXX_halve(x, p): FpX_halve(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_get_red(GEN S, GEN T, GEN p) { return T? FpXQX_get_red(S,T,p): FpX_get_red(S,p); } 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_div_by_X_x(GEN x, GEN y, GEN T, GEN p, GEN *z) { return T? FpXQX_div_by_X_x(x,y,T,p,z): FpX_div_by_X_x(x,y,p,z); } INLINE GEN FqX_halfgcd(GEN P,GEN Q,GEN T,GEN p) {return T? FpXQX_halfgcd(P,Q,T,p): FpX_halfgcd(P,Q,p);} 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); } INLINE GEN FqX_normalize(GEN z, GEN T, GEN p) { return T? FpXQX_normalize(z, T, p): FpX_normalize(z, p); } INLINE GEN FqX_deriv(GEN f, GEN T, GEN p) { return T? FpXX_deriv(f, p): FpX_deriv(f, p); } INLINE GEN FqX_integ(GEN f, GEN T, GEN p) { return T? FpXX_integ(f, p): FpX_integ(f, p); } INLINE GEN FqX_factor(GEN f, GEN T, GEN p) { return T?FpXQX_factor(f, T, p): FpX_factor(f, p); } INLINE GEN FqX_factor_squarefree(GEN f, GEN T, GEN p) { return T ? FpXQX_factor_squarefree(f, T, p): FpX_factor_squarefree(f, p); } INLINE GEN FqX_ddf(GEN f, GEN T, GEN p) { return T ? FpXQX_ddf(f, T, p): FpX_ddf(f, p); } INLINE GEN FqX_degfact(GEN f, GEN T, GEN p) { return T?FpXQX_degfact(f, T, p): FpX_degfact(f, p); } INLINE GEN FqX_roots(GEN f, GEN T, GEN p) { return T?FpXQX_roots(f, T, p): FpX_roots(f, p); } INLINE GEN FqX_to_mod(GEN f, GEN T, GEN p) { return T?FpXQX_to_mod(f, T, p): FpX_to_mod(f, p); } /*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); } /*FqXn*/ INLINE GEN FqXn_expint(GEN x, long n, GEN T, GEN p) { return T? FpXQXn_expint(x,n,T,p): FpXn_expint(x,n,p); } INLINE GEN FqXn_exp(GEN x, long n, GEN T, GEN p) { return T? FpXQXn_exp(x,n,T,p): FpXn_exp(x,n,p); } INLINE GEN FqXn_inv(GEN x, long n, GEN T, GEN p) { return T? FpXQXn_inv(x,n,T,p): FpXn_inv(x,n,p); } INLINE GEN FqXn_mul(GEN x, GEN y, long n, GEN T, GEN p) { return T? FpXQXn_mul(x, y, n, T, p): FpXn_mul(x, y, n, p); } INLINE GEN FqXn_sqr(GEN x, long n, GEN T, GEN p) { return T? FpXQXn_sqr(x,n,T,p): FpXn_sqr(x,n,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); set_avma(av); } INLINE void mplogz(GEN x, GEN z) { pari_sp av = avma; gaffect(mplog(x), z); set_avma(av); } INLINE void mpcosz(GEN x, GEN z) { pari_sp av = avma; gaffect(mpcos(x), z); set_avma(av); } INLINE void mpsinz(GEN x, GEN z) { pari_sp av = avma; gaffect(mpsin(x), z); set_avma(av); } INLINE void gnegz(GEN x, GEN z) { pari_sp av = avma; gaffect(gneg(x), z); set_avma(av); } INLINE void gabsz(GEN x, long prec, GEN z) { pari_sp av = avma; gaffect(gabs(x,prec), z); set_avma(av); } INLINE void gaddz(GEN x, GEN y, GEN z) { pari_sp av = avma; gaffect(gadd(x,y), z); set_avma(av); } INLINE void gsubz(GEN x, GEN y, GEN z) { pari_sp av = avma; gaffect(gsub(x,y), z); set_avma(av); } INLINE void gmulz(GEN x, GEN y, GEN z) { pari_sp av = avma; gaffect(gmul(x,y), z); set_avma(av); } INLINE void gdivz(GEN x, GEN y, GEN z) { pari_sp av = avma; gaffect(gdiv(x,y), z); set_avma(av); } INLINE void gdiventz(GEN x, GEN y, GEN z) { pari_sp av = avma; gaffect(gdivent(x,y), z); set_avma(av); } INLINE void gmodz(GEN x, GEN y, GEN z) { pari_sp av = avma; gaffect(gmod(x,y), z); set_avma(av); } INLINE void gmul2nz(GEN x, long s, GEN z) { pari_sp av = avma; gaffect(gmul2n(x,s), z); set_avma(av); } INLINE void gshiftz(GEN x, long s, GEN z) { pari_sp av = avma; gaffect(gshift(x,s), z); set_avma(av); } /*******************************************************************/ /* */ /* ELLIPTIC CURVES */ /* */ /*******************************************************************/ INLINE GEN ell_get_a1(GEN e) { return gel(e,1); } INLINE GEN ell_get_a2(GEN e) { return gel(e,2); } INLINE GEN ell_get_a3(GEN e) { return gel(e,3); } INLINE GEN ell_get_a4(GEN e) { return gel(e,4); } INLINE GEN ell_get_a6(GEN e) { return gel(e,5); } INLINE GEN ell_get_b2(GEN e) { return gel(e,6); } INLINE GEN ell_get_b4(GEN e) { return gel(e,7); } INLINE GEN ell_get_b6(GEN e) { return gel(e,8); } INLINE GEN ell_get_b8(GEN e) { return gel(e,9); } INLINE GEN ell_get_c4(GEN e) { return gel(e,10); } INLINE GEN ell_get_c6(GEN e) { return gel(e,11); } INLINE GEN ell_get_disc(GEN e) { return gel(e,12); } INLINE GEN ell_get_j(GEN e) { return gel(e,13); } INLINE long ell_get_type(GEN e) { return mael(e,14,1); } INLINE GEN ellff_get_field(GEN x) { return gmael(x, 15, 1); } INLINE GEN ellff_get_a4a6(GEN x) { return gmael(x, 15, 2); } INLINE GEN ellQp_get_zero(GEN x) { return gmael(x, 15, 1); } INLINE long ellQp_get_prec(GEN E) { GEN z = ellQp_get_zero(E); return valp(z); } INLINE GEN ellQp_get_p(GEN E) { GEN z = ellQp_get_zero(E); return gel(z,2); } INLINE long ellR_get_prec(GEN x) { return nbits2prec(mael3(x, 15, 1, 1)); } INLINE long ellR_get_sign(GEN x) { return mael3(x, 15, 1, 2); } INLINE GEN ellnf_get_nf(GEN x) { return checknf_i(gmael(x,15,1)); } INLINE GEN ellnf_get_bnf(GEN x) { return checkbnf_i(gmael(x,15,1)); } INLINE int checkell_i(GEN e) { return typ(e) == t_VEC && lg(e) == 17; } INLINE int ell_is_inf(GEN z) { return lg(z) == 2; } INLINE GEN ellinf(void) { return mkvec(gen_0); } /*******************************************************************/ /* */ /* ALGEBRAIC NUMBER THEORY */ /* */ /*******************************************************************/ INLINE GEN modpr_get_pr(GEN x) { return gel(x,3); } INLINE GEN modpr_get_p(GEN x) { return pr_get_p(modpr_get_pr(x)); } INLINE GEN modpr_get_T(GEN x) { return lg(x) == 4? NULL: gel(x,4); } INLINE GEN pr_get_p(GEN pr) { return gel(pr,1); } INLINE GEN pr_get_gen(GEN pr){ return gel(pr,2); } /* .[2] instead of itos works: e and f are small positive integers */ 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 typ(pr_get_tau(P)) == t_INT; } INLINE GEN pr_norm(GEN pr) { return powiu(pr_get_p(pr), pr_get_f(pr)); } INLINE ulong upr_norm(GEN pr) { return upowuu(pr_get_p(pr)[2], 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_ramified_primes(GEN nf) { return gmael(nf,5,8); } INLINE GEN nf_get_roots(GEN nf) { return gel(nf,6); } INLINE GEN nf_get_zk(GEN nf) { GEN y = gel(nf,7), D = gel(y, 1); if (typ(D) == t_POL) D = gel(D, 2); if (!equali1(D)) y = gdiv(y, D); return y; } INLINE GEN nf_get_zkprimpart(GEN nf) { GEN y = gel(nf,7); /* test for old format of nf.zk: non normalized */ if (!equali1(gel(nf,4)) && gequal1(gel(y,1))) y = Q_remove_denom(y,NULL); return y; } INLINE GEN nf_get_zkden(GEN nf) { GEN y = gel(nf,7), D = gel(y,1); if (typ(D) == t_POL) D = gel(D,2); /* test for old format of nf.zk: non normalized */ if (!equali1(gel(nf,4)) && equali1(D)) D = Q_denom(y); return D; } 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 cyc_get_expo(GEN c) { return lg(c) == 1? gen_1: gel(c,1); } INLINE GEN abgrp_get_no(GEN x) { return gel(x,1); } INLINE GEN abgrp_get_cyc(GEN x) { return gel(x,2); } INLINE GEN abgrp_get_gen(GEN x) { return gel(x,3); } INLINE GEN bnf_get_nf(GEN bnf) { return gel(bnf,7); } INLINE GEN bnf_get_clgp(GEN bnf) { return gmael(bnf,8,1); } INLINE GEN bnf_get_no(GEN bnf) { return abgrp_get_no(bnf_get_clgp(bnf)); } INLINE GEN bnf_get_cyc(GEN bnf) { return abgrp_get_cyc(bnf_get_clgp(bnf)); } INLINE GEN bnf_get_gen(GEN bnf) { return abgrp_get_gen(bnf_get_clgp(bnf)); } INLINE GEN bnf_get_reg(GEN bnf) { return gmael(bnf,8,2); } INLINE GEN bnf_get_logfu(GEN bnf) { return gel(bnf,3); } INLINE GEN bnf_get_sunits(GEN bnf) { GEN s = gmael(bnf,8,3); return typ(s) == t_INT? NULL: s; } 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_nocheck(GEN bnf) { return gmael(bnf,8,5); } INLINE GEN nfV_to_scalar_or_alg(GEN nf, GEN x) { pari_APPLY_same(nf_to_scalar_or_alg(nf, gel(x,i))) } INLINE GEN bnf_get_fu(GEN bnf) { GEN fu = bnf_build_units(bnf), nf = bnf_get_nf(bnf); if (typ(fu) == t_MAT) pari_err(e_MISC,"missing units in bnf"); return nfV_to_scalar_or_alg(nf, vecslice(fu, 2, lg(fu)-1)); } INLINE GEN bnr_get_bnf(GEN bnr) { return gel(bnr,1); } INLINE GEN bnr_get_bid(GEN bnr) { return gel(bnr,2); } INLINE GEN bnr_get_mod(GEN bnr) { return gmael(bnr,2,1); } INLINE GEN bnr_get_nf(GEN bnr) { return gmael(bnr,1,7); } INLINE GEN bnr_get_clgp(GEN bnr) { return gel(bnr,5); } INLINE GEN bnr_get_no(GEN bnr) { return abgrp_get_no(bnr_get_clgp(bnr)); } INLINE GEN bnr_get_cyc(GEN bnr) { return abgrp_get_cyc(bnr_get_clgp(bnr)); } INLINE GEN bnr_get_gen_nocheck(GEN bnr) { return abgrp_get_gen(bnr_get_clgp(bnr)); } INLINE GEN bnr_get_gen(GEN bnr) { GEN G = bnr_get_clgp(bnr); if (lg(G) != 4) pari_err(e_MISC,"missing bnr generators: please use bnrinit(,,1)"); return gel(G,3); } /* localstar, used in gchar */ INLINE GEN locs_get_cyc(GEN locs) { return gel(locs,1); } INLINE GEN locs_get_Lsprk(GEN locs) { return gel(locs,2); } INLINE GEN locs_get_Lgenfil(GEN locs) { return gel(locs,3); } INLINE GEN locs_get_mod(GEN locs) { return gel(locs,4); } /* pr dividing the modulus N of locs, 0 <= i < v_pr(N) * return a t_MAT whose columns are the logs * of generators of U_i(pr)/U_{i+1}(pr). */ INLINE GEN locs_get_famod(GEN locs) { return gmael(locs,4,1); } INLINE GEN locs_get_m_infty(GEN locs) { return gmael(locs,4,2); } /* G a grossenchar group */ INLINE GEN gchar_get_basis(GEN gc) { return gel(gc, 1); } INLINE GEN gchar_get_bnf(GEN gc) { return gel(gc, 2); } INLINE GEN gchar_get_nf(GEN gc) { return gel(gc, 3); } INLINE GEN gchar_get_zm(GEN gc) { return gel(gc, 4); } INLINE GEN gchar_get_mod(GEN gc) { return locs_get_mod(gchar_get_zm(gc)); } INLINE GEN gchar_get_modP(GEN gc) { return gmael(gchar_get_mod(gc),1,1); } INLINE GEN gchar_get_S(GEN gc) { return gel(gc, 5); } INLINE GEN gchar_get_DLdata(GEN gc) { return gel(gc, 6); } INLINE GEN gchar_get_sfu(GEN gc) { return gel(gc, 7); } INLINE GEN gchar_get_cyc(GEN gc) { return gel(gc, 9); } INLINE GEN gchar_get_hnf(GEN gc) { return gmael(gc, 10, 1); } INLINE GEN gchar_get_U(GEN gc) { return gmael(gc, 10, 2); } INLINE GEN gchar_get_Ui(GEN gc) { return gmael(gc, 10, 3); } INLINE GEN gchar_get_m0(GEN gc) { return gel(gc, 11); } INLINE GEN gchar_get_u0(GEN gc) { return gel(gc, 12); } INLINE long gchar_get_r1(GEN gc) { return nf_get_r1(gchar_get_nf(gc)); } INLINE long gchar_get_r2(GEN gc) { return nf_get_r2(gchar_get_nf(gc)); } INLINE GEN gchar_get_loccyc(GEN gc) { return locs_get_cyc(gchar_get_zm(gc)); } INLINE long gchar_get_nc(GEN gc) { return lg(gchar_get_loccyc(gc))-1; } INLINE long gchar_get_ns(GEN gc) { return lg(gchar_get_S(gc))-1; } INLINE long gchar_get_nm(GEN gc) { return lg(gchar_get_basis(gc))-1; } INLINE long gchar_get_evalprec(GEN gc) { return gmael(gc, 8, 1)[1]; } INLINE long gchar_get_prec(GEN gc) { return gmael(gc, 8, 1)[2]; } INLINE long gchar_get_nfprec(GEN gc) { return gmael(gc, 8, 1)[3]; } INLINE void gchar_set_evalprec(GEN gc, long prec) { gmael(gc, 8, 1)[1] = prec; } INLINE void gchar_set_prec(GEN gc, long prec) { gmael(gc, 8, 1)[2] = prec; } INLINE void gchar_copy_precs(GEN gc, GEN gc2) { gel(gc2, 8) = shallowcopy(gel(gc,8)); gmael(gc2, 8, 1) = shallowcopy(gmael(gc, 8, 1)); } INLINE void gchar_set_nfprec(GEN gc, long prec) { gmael(gc, 8, 1)[3] = prec; } INLINE long gchar_get_ntors(GEN gc) { return gmael(gc, 8, 2)[1]; } INLINE long gchar_get_nfree(GEN gc) { return gmael(gc, 8, 2)[2]; } INLINE long gchar_get_nalg(GEN gc) { return gmael(gc, 8, 2)[3]; } INLINE void gchar_set_basis(GEN gc, GEN m_inv) { gel(gc, 1) = m_inv; } INLINE void gchar_set_nf(GEN gc, GEN nf) { gel(gc, 3) = nf; } INLINE void gchar_set_ntors(GEN gc, long n) { gmael(gc, 8, 2)[1] = n; } INLINE void gchar_set_nfree(GEN gc, long n) { gmael(gc, 8, 2)[2] = n; } INLINE void gchar_set_nalg(GEN gc, long n) { gmael(gc, 8, 2)[3] = n; } INLINE void gchar_set_cyc(GEN gc, GEN cyc) { gel(gc, 9) = cyc; } INLINE void gchar_set_HUUi(GEN gc, GEN hnf, GEN U, GEN Ui) { gel(gc, 10) = mkvec3(hnf, U, Ui); } INLINE void gchar_set_m0(GEN gc, GEN m0) { gel(gc, 11) = m0; } INLINE void gchar_set_u0(GEN gc, GEN u0) { gel(gc, 12) = u0; } INLINE GEN bid_get_mod(GEN bid) { return gel(bid,1); } INLINE GEN bid_get_ideal(GEN bid) { return gmael(bid,1,1); } INLINE GEN bid_get_arch(GEN bid) { return gmael(bid,1,2); } INLINE GEN bid_get_grp(GEN bid) { return gel(bid,2); } INLINE GEN bid_get_fact(GEN bid) { return gmael(bid,3,1); } INLINE GEN bid_get_fact2(GEN bid) { return gmael(bid,3,2); } INLINE GEN bid_get_MOD(GEN bid) { GEN y = gel(bid,4); return lg(y) == 4? gel(y,3): NULL; } INLINE GEN bid_get_sprk(GEN bid) { return gmael(bid,4,1); } INLINE GEN bid_get_sarch(GEN bid) { return gmael(bid,4,2); } INLINE GEN bid_get_archp(GEN bid) { return gmael3(bid,4,2,2); } INLINE GEN bid_get_U(GEN bid) { return gel(bid,5); } INLINE GEN bid_get_no(GEN bid) { return abgrp_get_no(bid_get_grp(bid)); } INLINE GEN bid_get_cyc(GEN bid) { return abgrp_get_cyc(bid_get_grp(bid)); } INLINE GEN bid_get_gen_nocheck(GEN bid) { return abgrp_get_gen(bid_get_grp(bid)); } INLINE GEN bid_get_gen(GEN bid) { GEN G = bid_get_grp(bid); if (lg(G) != 4) pari_err(e_MISC,"missing bid generators. Use idealstar(,,2)"); return abgrp_get_gen(G); } INLINE GEN znstar_get_N(GEN G) { return gmael(G,1,1); } INLINE GEN znstar_get_faN(GEN G) { return gel(G,3); } INLINE GEN znstar_get_no(GEN G) { return abgrp_get_no(gel(G,2)); } INLINE GEN znstar_get_cyc(GEN G) { return abgrp_get_cyc(gel(G,2)); } INLINE GEN znstar_get_gen(GEN G) { return abgrp_get_gen(gel(G,2)); } INLINE GEN znstar_get_conreycyc(GEN G) { return gmael(G,4,5); } INLINE GEN znstar_get_conreygen(GEN G) { return gmael(G,4,4); } INLINE GEN znstar_get_Ui(GEN G) { return gmael(G,4,3); } INLINE GEN znstar_get_U(GEN G) { return gel(G,5); } INLINE GEN znstar_get_pe(GEN G) { return gmael(G,4,1); } INLINE GEN gal_get_pol(GEN gal) { return gel(gal,1); } INLINE GEN gal_get_p(GEN gal) { return gmael(gal,2,1); } INLINE GEN gal_get_e(GEN gal) { return gmael(gal,2,2); } INLINE GEN gal_get_mod(GEN gal) { return gmael(gal,2,3); } INLINE GEN gal_get_roots(GEN gal) { return gel(gal,3); } INLINE GEN gal_get_invvdm(GEN gal) { return gel(gal,4); } INLINE GEN gal_get_den(GEN gal) { return gel(gal,5); } INLINE GEN gal_get_group(GEN gal) { return gel(gal,6); } INLINE GEN gal_get_gen(GEN gal) { return gel(gal,7); } INLINE GEN gal_get_orders(GEN gal) { return gel(gal,8); } /* assume rnf a genuine rnf */ INLINE long rnf_get_degree(GEN rnf) { return degpol(rnf_get_pol(rnf)); } INLINE long rnf_get_nfdegree(GEN rnf) { return degpol(nf_get_pol(rnf_get_nf(rnf))); } INLINE long rnf_get_absdegree(GEN rnf) { return degpol(gmael(rnf,11,1)); } INLINE GEN rnf_get_idealdisc(GEN rnf) { return gmael(rnf,3,1); } INLINE GEN rnf_get_k(GEN rnf) { return gmael(rnf,11,3); } INLINE GEN rnf_get_alpha(GEN rnf) { return gmael(rnf, 11, 2); } INLINE GEN rnf_get_nf(GEN rnf) { return gel(rnf,10); } INLINE GEN rnf_get_nfzk(GEN rnf) { return gel(rnf,2); } INLINE GEN rnf_get_polabs(GEN rnf) { return gmael(rnf,11,1); } INLINE GEN rnf_get_pol(GEN rnf) { return gel(rnf,1); } INLINE GEN rnf_get_disc(GEN rnf) { return gel(rnf,3); } INLINE GEN rnf_get_index(GEN rnf) { return gel(rnf,4); } INLINE GEN rnf_get_ramified_primes(GEN rnf) { return gel(rnf,5); } INLINE long rnf_get_varn(GEN rnf) { return varn(gel(rnf,1)); } INLINE GEN rnf_get_nfpol(GEN rnf) { return gmael(rnf,10,1); } INLINE long rnf_get_nfvarn(GEN rnf) { return varn(gmael(rnf,10,1)); } INLINE GEN rnf_get_zk(GEN rnf) { return gel(rnf,7); } INLINE GEN rnf_get_map(GEN rnf) { return gel(rnf,11); } INLINE GEN rnf_get_invzk(GEN rnf) { return gel(rnf,8); } INLINE GEN idealred(GEN nf, GEN id) { return idealred0(nf, id, NULL); } INLINE GEN idealchineseinit(GEN nf, GEN x) { return idealchinese(nf,x,NULL); } /*******************************************************************/ /* */ /* CLOSURES */ /* */ /*******************************************************************/ INLINE long closure_arity(GEN C) { return ((ulong)C[1])&ARITYBITS; } INLINE long closure_is_variadic(GEN C) { return !!(((ulong)C[1])&VARARGBITS); } INLINE const char *closure_codestr(GEN C) { return GSTR(gel(C,2))-1; } INLINE GEN closure_get_code(GEN C) { return gel(C,2); } INLINE GEN closure_get_oper(GEN C) { return gel(C,3); } INLINE GEN closure_get_data(GEN C) { return gel(C,4); } INLINE GEN closure_get_dbg(GEN C) { return gel(C,5); } INLINE GEN closure_get_text(GEN C) { return gel(C,6); } INLINE GEN closure_get_frame(GEN C) { return gel(C,7); } /*******************************************************************/ /* */ /* ERRORS */ /* */ /*******************************************************************/ INLINE long err_get_num(GEN e) { return e[1]; } INLINE GEN err_get_compo(GEN e, long i) { return gel(e, i+1); } INLINE void pari_err_BUG(const char *f) { pari_err(e_BUG,f); } INLINE void pari_err_CONSTPOL(const char *f) { pari_err(e_CONSTPOL, f); } INLINE void pari_err_COPRIME(const char *f, GEN x, GEN y) { pari_err(e_COPRIME, f,x,y); } INLINE void pari_err_DIM(const char *f) { pari_err(e_DIM, f); } INLINE void pari_err_FILE(const char *f, const char *g) { pari_err(e_FILE, f,g); } INLINE void pari_err_FILEDESC(const char *f, long n) { pari_err(e_FILEDESC, f,n); } INLINE void pari_err_FLAG(const char *f) { pari_err(e_FLAG,f); } INLINE void pari_err_IMPL(const char *f) { pari_err(e_IMPL,f); } INLINE void pari_err_INV(const char *f, GEN x) { pari_err(e_INV,f,x); } INLINE void pari_err_IRREDPOL(const char *f, GEN x) { pari_err(e_IRREDPOL, f,x); } INLINE void pari_err_DOMAIN(const char *f, const char *v, const char *op, GEN l, GEN x) { pari_err(e_DOMAIN, f,v,op,l,x); } INLINE void pari_err_COMPONENT(const char *f, const char *op, GEN l, GEN x) { pari_err(e_COMPONENT, f,op,l,x); } INLINE void pari_err_MAXPRIME(ulong c) { pari_err(e_MAXPRIME, c); } INLINE void pari_err_OP(const char *f, GEN x, GEN y) { pari_err(e_OP, f,x,y); } INLINE void pari_err_OVERFLOW(const char *f) { pari_err(e_OVERFLOW, f); } INLINE void pari_err_PREC(const char *f) { pari_err(e_PREC,f); } INLINE void pari_err_PACKAGE(const char *f) { pari_err(e_PACKAGE,f); } INLINE void pari_err_PRIME(const char *f, GEN x) { pari_err(e_PRIME, f,x); } INLINE void pari_err_MODULUS(const char *f, GEN x, GEN y) { pari_err(e_MODULUS, f,x,y); } INLINE void pari_err_ROOTS0(const char *f) { pari_err(e_ROOTS0, f); } INLINE void pari_err_SQRTN(const char *f, GEN x) { pari_err(e_SQRTN, f,x); } INLINE void pari_err_TYPE(const char *f, GEN x) { pari_err(e_TYPE, f,x); } INLINE void pari_err_TYPE2(const char *f, GEN x, GEN y) { pari_err(e_TYPE2, f,x,y); } INLINE void pari_err_VAR(const char *f, GEN x, GEN y) { pari_err(e_VAR, f,x,y); } INLINE void pari_err_PRIORITY(const char *f, GEN x, const char *op, long v) { pari_err(e_PRIORITY, f,x,op,v); } pari-2.17.2/src/headers/pariold.h0000644000175000017500000003251714760123736015212 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* For compatibility with older PARI versions */ #define nfinitall nfinit0 #define nbessel ybessel #define ZXX_to_Kronecker RgXX_to_Kronecker #define ZXX_to_Kronecker_spec RgXX_to_Kronecker_spec #define perf qfperfection #define rootpadic polrootspadic #define rootsof1 nfrootsof1 #define rootsof1_kannan nfrootsof1 #define hash_str2 hash_str #define Strtex strtex #define Strprintf strprintf #define Strchr pari_strchr #define Strexpand strexpand #define LOG2 M_LN2 #define truecoeff truecoef #define polcoeff0 polcoef #define polcoeff_i polcoef_i #define factorcantor0 factormod0 #define factcantor factmod #define matsolvemod0 matsolvemod #define rootmod2 polrootsmod #define rootmod polrootsmod #define resultant_all RgX_resultant_all #define vecbinome vecbinomial #define Xadic_lindep lindep_Xadic #define padic_lindep lindep_padic #define ZM_ker_ratlift ZM_ker #define keri ZM_ker /* Following obsoleted in 2.16.* (2024) */ #define ZX_compositum_disjoint ZX_composedsum /* Following obsoleted in 2.9.* (2016) */ #define absi_factor absZ_factor #define absi_factor_limit absZ_factor_limit #define absi_cmp abscmpii #define absr_cmp abscmprr #define absi_equal absequalii #define anell ellan #define anellsmall ellanQ_zv #define leading_term leading_coeff #define constant_term constant_coeff #define concat gconcat #define concat1 gconcat1 #define mathell ellheightmatrix #define ghell ellheight /* Following obsoleted in 2.7.* (2014) */ #define mpexp1 mpexpm1 #define ggamd ggammah #define gach gacosh #define gash gasinh #define gath gatanh #define gch gcosh #define gsh gsinh #define gth gtanh #define recip serreverse #define gcmpX gequalX #define ZM_hnfremdiv ZM_hnfdivrem #define rnfidealhermite rnfidealhnf #define rnfelementabstorel rnfeltabstorel #define rnfelementreltoabs rnfeltreltoabs #define rnfelementdown rnfeltdown #define rnfelementup rnfeltup #define exp_Ir expIr #define vecbezout gcdext0 #define vecbezoutres polresultantext #define init_primepointer init_primepointer_geq #define ellap0(e,p,flag) ellap(e,p) #define apell2(e,p) ellap(e,p) #define geulerphi eulerphi #define numbdiv numdiv #define gnumbdiv numdiv #define gsumdivk sumdivk #define gnextprime nextprime #define gprecprime precprime #define leftright_pow_fold gen_pow_fold #define leftright_pow_u_fold gen_powu_fold #define subell ellsub #define addell elladd #define powell ellmul #define ggval gvaluation #define stackmalloc stack_malloc #define listcreate mklist /* Following obsoleted in 2.5.* (2011) */ #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 gsizebyte #define taille gsizeword #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 discf(x) nfdisc(x) #define discsr(x) poldisc0((x),-1) #define factorpadic4 factorpadic #define smith2 smithall #define gsmith2 gsmithall #define derivpol RgX_deriv #define gpmalloc pari_malloc #define gprealloc pari_realloc #define gpfree pari_free #define pariprintf pari_printf #define pariputc pari_putc #define pariputs pari_puts #define pariflush pari_flush /* Following deprecated for a long time now, obsoleted in 2.3.* (2007) */ #ifdef PARI_OLD_NAMES #define apell ellap #define gscalsmat scalarmat_s #define sqred qfgaussred #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)) #define err pari_err #define init pari_init #define zero (long)gen_0 #define un (long)gen_1 #define deux (long)gen_2 #define lhalf (long)ghalf /* removed GEN subtypes */ #define t_FRACN t_FRAC #define t_RFRACN t_RFRAC #define is_frac_t(t) ( (t) == t_FRAC ) #define is_rfrac_t(t) ( (t) == t_RFRAC ) /*casts*/ #define labsi (long)absi #define labsr (long)absr #define lach (long)gacosh #define lacos (long)gacos #define ladd (long)gadd #define laddgs (long)gaddgs #define laddii (long)addii #define laddir (long)addir #define laddis (long)addis #define laddrr (long)addrr #define laddsg (long)gaddsg #define laddsi (long)addsi #define laddrs (long)addrs #define laddsr (long)addsr #define ladj (long)adj #define larg (long)garg #define lash (long)gasinh #define lasin (long)gasin #define lassmat (long)matcompanion #define latan (long)gatan #define lath (long)gatanh #define lbezout (long)bezout #define lbinome (long)binomial #define lcaract (long)caract #define lcaradj (long)caradj #define lceil (long)gceil #define lch (long)gcosh #define lchangevar (long)changevar #define lclone (long)gclone #define lconcat (long)gconcat #define lconj (long)gconj #define lcontent (long)content #define lcopy (long)gcopy #define lcos (long)gcos #define lcvtoi (long)gcvtoi #define lderiv (long)deriv #define ldet2 (long)det2 #define ldet (long)det #define ldeuc (long)gdeuc #define ldiscsr (long)discsr #define ldiventgs (long)gdiventgs #define ldiventsg (long)gdiventsg #define ldivgs (long)gdivgs #define ldivii (long)divii #define ldivir (long)divir #define ldivis (long)divis #define ldivmod (long)gdivmod #define ldivri (long)divri #define ldivrr (long)divrr #define ldivrs (long)divrs #define ldivsg (long)gdivsg #define ldivsi (long)divsi #define ldivsr (long)divsr #define ldvmdii (long)dvmdii #define ldvmdis (long)dvmdis #define ldvmdsi (long)dvmdsi #define lexp (long)gexp #define lfibo (long)fibo #define lfloor (long)gfloor #define lfrac (long)gfrac #define lgamd (long)ggammah #define lgamma (long)ggamma #define lgauss (long)gauss #define lgcd (long)ggcd #define lgetg (long)cgetg #define lgeti (long)cgeti #define lgetp (long)cgetp #define lgetr (long)cgetr #define licopy (long)icopy #define limag (long)gimag #define linteg (long)integ #define linv (long)ginv #define linvmat (long)RgM_inv #define linvmod (long)ginvmod #define llegendre (long)legendre #define llift (long)lift #define llngamma (long)glngamma #define llog (long)glog #define lmaxgs (long)gmaxgs #define lmax (long)gmax #define lmaxsg (long)gmaxsg #define lmings (long)gmings #define lmin (long)gmin #define lminsg (long)gminsg #define lmodgs (long)gmodgs #define lmodii (long)modii #define lmod (long)gmod #define lmodsg (long)gmodsg #define lmodsi (long)modsi #define lmodulcp (long)gmodulo #define lmodulo (long)gmodulo #define lmpabs (long)mpabs #define lmpadd (long)mpadd #define lmpcos (long)mpcos #define lmpdiv (long)mpdiv #define lmpent (long)mpent #define lmpeuler (long)mpeuler #define lmpexp1 (long)mpexpm1 #define lmpexp (long)mpexp #define lmpfact (long)mpfact #define lmplog (long)mplog #define lmpmul (long)mpmul #define lmpneg (long)mpneg #define lmppgcd (long)mppgcd #define lmppi (long)mppi #define lmpshift (long)mpshift #define lmpsin (long)mpsin #define lmpsqrt (long)mpsqrt #define lmpsub (long)mpsub #define lmptrunc (long)mptrunc #define lmul2n (long)gmul2n #define lmulgs (long)gmulgs #define lmulii (long)mulii #define lmulir (long)mulir #define lmulis (long)mulis #define lmul (long)gmul #define lmulri (long)mulri #define lmulrr (long)mulrr #define lmulrs (long)mulrs #define lmulsg (long)gmulsg #define lmulsi (long)mulsi #define lmulsr (long)mulsr #define lmulss (long)mulss #define lnegi (long)negi #define lneg (long)gneg #define lnegr (long)negr #define lnorml2 (long)gnorml2 #define lnorm (long)gnorm #define lpile (long)gerepile #define lpilecopy (long)gerepilecopy #define lpileupto (long)gerepileupto #define lpileuptoint (long)gerepileuptoint #define lpileuptoleaf (long)gerepileuptoleaf #define lpoleval (long)poleval #define lpowgs (long)gpowgs #define lprec (long)gprec #define lpsi (long)gpsi #define lpuigs (long)gpuigs #define lpui (long)gpui #define lquadgen (long)quadgen #define lquadpoly (long)quadpoly #define lracine (long)sqrtint #define lrcopy (long)rcopy #define lreal (long)greal #define lrecip (long)recip #define lred (long)gred #define lremii (long)remii #define lrem (long)grem #define lrndtoi (long)grndtoi #define lroots (long)roots #define lscalmat (long)scalarmat #define lscalsmat (long)scalarmat_s #define lsh (long)gsinh #define lshifti (long)shifti #define lshift (long)gshift #define lshiftr (long)shiftr #define lsin (long)gsin #define lsqri (long)sqri #define lsqr (long)gsqr #define lsqrt (long)gsqrt #define lstoi (long)stoi #define lsub (long)gsub #define lsubgs (long)gsubgs #define lsubii (long)subii #define lsubir (long)subir #define lsubis (long)subis #define lsubres (long)resultant #define lsubri (long)subri #define lsubrr (long)subrr #define lsubrs (long)subrs #define lsubst (long)gsubst #define lsubsg (long)gsubsg #define lsubsi (long)subsi #define lsubsr (long)subsr #define ltan (long)gtan #define ltchebi (long)polchebyshev #define lth (long)gtanh #define ltrace (long)gtrace #define ltrans (long)gtrans #define ltrunc (long)gtrunc #define lutoi (long)utoi #define lround (long)ground #define ldiv (long)gdiv #endif pari-2.17.2/src/headers/parigen.h0000644000175000017500000001455114760123736015203 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* This file defines the parameters of the GEN type */ #ifdef _WIN64 typedef unsigned long long pari_ulong; #define long long long #define labs llabs #else typedef unsigned long pari_ulong; #endif #define ulong pari_ulong typedef unsigned int pari_prime; typedef long *GEN; #undef ULONG_MAX #undef LONG_MAX #ifdef LONG_IS_64BIT # define BITS_IN_LONG 64 # define TWOPOTBITS_IN_LONG 6 # define LONG_MAX (9223372036854775807L) /* 2^63-1 */ # define SMALL_ULONG(p) ((ulong)p <= 3037000493UL) #else # define BITS_IN_LONG 32 # define TWOPOTBITS_IN_LONG 5 # define LONG_MAX (2147483647L) /* 2^31-1 */ # define SMALL_ULONG(p) ((ulong)p <= 46337UL) /* 2p^2 < 2^BITS_IN_LONG */ #endif #define ULONG_MAX (~0x0UL) #define DEFAULTPREC 64 #define MEDDEFAULTPREC 128 #define BIGDEFAULTPREC 192 #define LOWDEFAULTPREC BITS_IN_LONG #define EXTRAPRECWORD BITS_IN_LONG #define EXTRAPREC64 64 #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, VALSERBITS * 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 VALSERnumBITS (BITS_IN_LONG - SIGNnumBITS - VARNnumBITS) #define VALPnumBITS (BITS_IN_LONG - SIGNnumBITS - VARNnumBITS) #define EXPOnumBITS (BITS_IN_LONG - SIGNnumBITS) #define PRECPSHIFT VALPnumBITS #define VARNSHIFT VALSERnumBITS #define TYPSHIFT (BITS_IN_LONG - TYPnumBITS) #define SIGNSHIFT (BITS_IN_LONG - SIGNnumBITS) #define EXPOBITS ((1UL<> TYPSHIFT)) #define settyp(x,s) (((ulong*)(x))[0]=\ (((ulong*)(x))[0]&(~TYPBITS)) | evaltyp(s)) #define isclone(x) (((ulong*) (x))[0] & CLONEBIT) #define setisclone(x) (((ulong*) (x))[0] |= CLONEBIT) #define unsetisclone(x) (((ulong*) (x))[0] &= (~CLONEBIT)) #define lg(x) ((long)(((ulong)((x)[0])) & LGBITS)) #define setlg(x,s) (((ulong*)(x))[0]=\ (((ulong*)(x))[0]&(~LGBITS)) | evallg(s)) #define signe(x) (((long)((x)[1])) >> SIGNSHIFT) #define setsigne(x,s) (((ulong*)(x))[1]=\ (((ulong*)(x))[1]&(~SIGNBITS)) | (ulong)evalsigne(s)) #define lgefint(x) ((long)(((ulong)((x)[1])) & LGBITS)) #define setlgefint(x,s) (((ulong*)(x))[1]=\ (((ulong*)(x))[1]&(~LGBITS)) | (ulong)evallgefint(s)) #define realprec(x) (((long)(((ulong)((x)[0])) & LGBITS)-2)<>TWOPOTBITS_IN_LONG)+2)) #define incrprec(x) ((x += EXTRAPREC64)) #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 valser(x) ((long) ((((ulong)((x)[1])) & VALSERBITS) - HIGHVALSERBIT)) #define setvalser(x,s) (((ulong*)(x))[1]=\ (((ulong*)(x))[1]&(~VALSERBITS)) | (ulong)evalvalser(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)) /* t_LIST */ #define list_typ(x) ((long)(((ulong)((x)[1])) >> TYPSHIFT)) #define list_nmax(x) ((long)(((ulong)((x)[1])) & LGBITS)) #define list_data(x) ((GEN*)x)[2] enum { t_LIST_RAW = 0, t_LIST_MAP = 1 }; /* 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_QFB = 15, t_VEC = 17, t_COL = 18, t_MAT = 19, t_LIST = 20, t_STR = 21, t_VECSMALL= 22, t_CLOSURE = 23, t_ERROR = 24, t_INFINITY= 25 }; pari-2.17.2/src/headers/parinf.h0000644000175000017500000000707614760123736015041 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* output of get_nf and get_bnf */ enum { typ_NULL = 0, typ_POL, typ_Q, typ_QFB, typ_NF, typ_BNF, typ_BNR, typ_GCHAR, /* group of Hecke grossenchars */ typ_ELL, /* elliptic curve */ typ_QUA, /* quadclassunit */ typ_GAL, /* galoisinit */ typ_BID, typ_BIDZ, typ_PRID, typ_MODPR, typ_RNF }; /* types of algebras */ enum { al_NULL = 0, al_TABLE, al_CSA, al_CYCLIC, al_REAL }; /* models for elements of algebras */ enum { al_INVALID = 0, al_TRIVIAL, al_ALGEBRAIC, al_BASIS, al_MATRIX }; /* flags for alginit */ enum { al_MAXORD = 1, al_FACTOR = 2 }; /* models for elements of M_n(Hamilton quaternions) */ enum { H_INVALID = 0, H_SCALAR, H_QUATERNION, H_MATRIX }; /* idealtyp */ enum { id_PRINCIPAL = 0, id_PRIME, id_MAT }; typedef struct { GEN T, dT; /* defining polynomial (monic ZX), disc(T) */ GEN T0; /* original defining polynomial (ZX) */ GEN unscale; /* T = C*T0(x / unscale), rational */ GEN dK; /* disc(K) */ GEN index; /* [O_K : Z[X]/(T)] */ GEN basis; /* Z-basis of O_K (t_VEC of t_POL) */ long r1; /* number of real places of K */ GEN basden; /* [nums(bas), dens(bas)] */ GEN dTP, dTE; /* (possibly partial) factorization of dT, primes / exponents */ GEN dKP, dKE; /* (possibly partial) factorization of dK, primes / exponents */ long certify; /* must we certify at the end */ } nfmaxord_t; /* qfr3 / qfr5 */ struct qfr_data { GEN D, sqrtD, isqrtD; }; /* various flags for nf/bnf routines */ enum { nf_ORIG = 1, nf_GEN = 1, nf_ABSOLUTE = 2, nf_FORCE = 2, nf_RED = 2, nf_ALL = 4, nf_NOLLL = 4, nf_GENMAT = 4, nf_INIT = 4, nf_RAW = 8, nf_PARTIALFACT = 16, nf_ROUND2 = 64, /* obsolete */ 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, LLL_COMPATIBLE = 0x800, /* attempt same behavior on 32/64bit kernels */ LLL_UPPER = 0x1000, /* upper triangular matrix */ LLL_NOCERTIFY = 0x2000, /* allow to return not fully LLL-reduced basis */ LLL_NOFLATTER = 0x4000 /* disable flatter */ }; /* HNF */ enum { hnf_MODID = 1, hnf_PART = 2, hnf_CENTER = 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 bid; GEN P, k; GEN sprk; /* sprk[i] = sprkinit(P[i]^k[i])*/ GEN archp; /* archimedean part of conductor, in permutation form */ GEN mod; GEN U; /* base change matrix blocks from (Z_K/P^k)^* and (Z/2)^#f_oo * to bid.gen */ long hU; /* #bid.gen */ int no2; /* 1 iff fa2 = fa, i.e. no prime of norm 2 divide exactly bid.mod */ } zlog_S; pari-2.17.2/src/headers/pari.h0000644000175000017500000000267014567450071014510 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef __GENPARI__ #define __GENPARI__ #include "paricfg.h" #include /* malloc, free, atoi */ #ifdef UNIX # define _INCLUDE_POSIX_SOURCE /* for HPUX */ # include /* size_t */ #endif #include #include #include #include #include #if !defined(_WIN32) # include #else # include #endif #include #include #include #include "parisys.h" #include "parigen.h" #include "paricast.h" #include "paristio.h" #include "paricom.h" #include "parierr.h" #include "paridbglvl.h" BEGINEXTERN #include "paridecl.h" #include "paritune.h" #include "parimt.h" #ifndef PARI_NO_MPINL_H # include "mpinl.h" #endif #ifndef PARI_NO_PARIINL_H # include "pariinl.h" #endif ENDEXTERN #include "pariold.h" #endif pari-2.17.2/src/headers/paridbglvl.h0000644000175000017500000000346514567450071015706 0ustar billbill/* Copyright (C) 2021 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ BEGINEXTERN #define PARI_DBG_ID(s) DEBUGLEVEL_##s #define PARI_DBG_LIST(ID) \ ID(alg), ID(arith), \ ID(bern), ID(bnf), ID(bnr), ID(bnrclassfield), ID(bb_group), \ ID(compiler), \ ID(ell), ID(ellanal), ID(ellcard), ID(ellisogeny), ID(ellrank), \ ID(ellsea), ID(factcyclo),\ ID(factor), ID(factorff), ID(factorint), ID(factormod), ID(fflog), \ ID(galois), ID(gammamellininv), ID(gchar), ID(genus2red), \ ID(hensel), ID(hgm), ID(hyperell), \ ID(intnum), ID(io), ID(isprime), \ ID(lfun), \ ID(mat), ID(mathnf), ID(mf), ID(mod), ID(mpqs), ID(ms), ID(mt),\ ID(nf), ID(nffactor), ID(nflist), ID(nfsubfields), \ ID(padicfields), \ ID(pol), ID(polclass), ID(polgalois), ID(polmodular), ID(polroots),\ ID(qf), ID(qflll), ID(qfsolve), ID(qfisom), ID(quadclassunit),\ ID(rnf), \ ID(stark), ID(subcyclo), ID(subgrouplist), \ ID(thue), ID(trans), \ ID(zetamult) #ifndef PARI_INIT extern #endif ulong PARI_DBG_LIST(PARI_DBG_ID); #ifdef PARI_INIT #define PARI_DBG_PTR(s) &DEBUGLEVEL_##s #define PARI_DBG_STR(s) #s ulong * const pari_DEBUGLEVEL_ptr[] = { PARI_DBG_LIST(PARI_DBG_PTR) }; const char * pari_DEBUGLEVEL_str[] = { PARI_DBG_LIST(PARI_DBG_STR) }; #endif ENDEXTERN pari-2.17.2/src/headers/parisys.h0000644000175000017500000000340514567450071015244 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* This files contains macros depending on system and compiler */ #ifdef __cplusplus # define BEGINEXTERN extern "C" { # define ENDEXTERN } #else # 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, win32alrm; void dowin32ctrlc(void); ENDEXTERN #define CHECK_CTRLC if (win32ctrlc) dowin32ctrlc(); #else #define CHECK_CTRLC #endif pari-2.17.2/src/headers/paricast.h0000644000175000017500000000262714567450071015365 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #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.17.2/src/headers/paritune.h0000644000175000017500000001552714676526175015423 0ustar billbill#define PARI_TUNE #ifdef PARI_TUNE extern long AGM_ATAN_LIMIT; extern long DIVRR_GMP_LIMIT; extern long EXPNEWTON_LIMIT; extern long EXTGCD_HALFGCD_LIMIT; extern long F2x_MUL_KARATSUBA_LIMIT; extern long F2x_MUL_MULII_LIMIT; extern long F2xqX_BARRETT_LIMIT; extern long F2xqX_DIVREM_BARRETT_LIMIT; extern long F2xqX_EXTGCD_LIMIT; extern long F2xqX_GCD_LIMIT; extern long F2xqX_HALFGCD_LIMIT; extern long F2xqX_INVBARRETT_LIMIT; extern long F2xqX_REM_BARRETT_LIMIT; extern long Flx_BARRETT2_LIMIT; extern long Flx_BARRETT_LIMIT; extern long Flx_DIVREM2_BARRETT_LIMIT; extern long Flx_DIVREM_BARRETT_LIMIT; extern long Flx_EXTGCD2_LIMIT; extern long Flx_EXTGCD_LIMIT; extern long Flx_GCD2_LIMIT; extern long Flx_GCD_LIMIT; extern long Flx_HALFGCD2_LIMIT; extern long Flx_HALFGCD_LIMIT; extern long Flx_INVBARRETT2_LIMIT; extern long Flx_INVBARRETT_LIMIT; extern long Flx_MUL2_KARATSUBA_LIMIT; extern long Flx_MUL2_MULII_LIMIT; extern long Flx_MUL_KARATSUBA_LIMIT; extern long Flx_MUL_MULII_LIMIT; extern long Flx_REM2_BARRETT_LIMIT; extern long Flx_REM_BARRETT_LIMIT; extern long Flx_SQR2_KARATSUBA_LIMIT; extern long Flx_SQR2_SQRI_LIMIT; extern long Flx_SQR_KARATSUBA_LIMIT; extern long Flx_SQR_SQRI_LIMIT; extern long FlxqX_BARRETT_LIMIT; extern long FlxqX_DIVREM_BARRETT_LIMIT; extern long FlxqX_EXTGCD_LIMIT; extern long FlxqX_GCD_LIMIT; extern long FlxqX_HALFGCD_LIMIT; extern long FlxqX_INVBARRETT_LIMIT; extern long FlxqX_REM_BARRETT_LIMIT; extern long FpXQX_BARRETT_LIMIT; extern long FpXQX_DIVREM_BARRETT_LIMIT; extern long FpXQX_EXTGCD_LIMIT; extern long FpXQX_GCD_LIMIT; extern long FpXQX_HALFGCD_LIMIT; extern long FpXQX_INVBARRETT_LIMIT; extern long FpXQX_REM_BARRETT_LIMIT; extern long FpX_BARRETT_LIMIT; extern long FpX_DIVREM_BARRETT_LIMIT; extern long FpX_EXTGCD_LIMIT; extern long FpX_GCD_LIMIT; extern long FpX_HALFGCD_LIMIT; extern long FpX_INVBARRETT_LIMIT; extern long FpX_REM_BARRETT_LIMIT; extern long Fp_POW_BARRETT_LIMIT; extern long Fp_POW_REDC_LIMIT; extern long GCD_HALFGCD_LIMIT; extern long HALFGCD_LIMIT; extern long INVMOD_GMP_LIMIT; extern long INVNEWTON_LIMIT; extern long LOGAGMCX_LIMIT; extern long LOGAGM_LIMIT; extern long MULII_FFT_LIMIT; extern long MULII_KARATSUBA_LIMIT; extern long MULRR_MULII_LIMIT; extern long RgX_MUL_LIMIT; extern long RgX_SQR_LIMIT; extern long SQRI_FFT_LIMIT; extern long SQRI_KARATSUBA_LIMIT; extern long SQRR_SQRI_LIMIT; extern long ZM2_MUL_LIMIT; #else # define AGM_ATAN_LIMIT __AGM_ATAN_LIMIT # define DIVRR_GMP_LIMIT __DIVRR_GMP_LIMIT # define EXPNEWTON_LIMIT __EXPNEWTON_LIMIT # define EXTGCD_HALFGCD_LIMIT __EXTGCD_HALFGCD_LIMIT # define F2x_MUL_KARATSUBA_LIMIT __F2x_MUL_KARATSUBA_LIMIT # define F2x_MUL_MULII_LIMIT __F2x_MUL_MULII_LIMIT # define F2xqX_BARRETT_LIMIT __F2xqX_BARRETT_LIMIT # define F2xqX_DIVREM_BARRETT_LIMIT __F2xqX_DIVREM_BARRETT_LIMIT # define F2xqX_EXTGCD_LIMIT __F2xqX_EXTGCD_LIMIT # define F2xqX_GCD_LIMIT __F2xqX_GCD_LIMIT # define F2xqX_HALFGCD_LIMIT __F2xqX_HALFGCD_LIMIT # define F2xqX_INVBARRETT_LIMIT __F2xqX_INVBARRETT_LIMIT # define F2xqX_REM_BARRETT_LIMIT __F2xqX_REM_BARRETT_LIMIT # define Flx_BARRETT2_LIMIT __Flx_BARRETT2_LIMIT # define Flx_BARRETT_LIMIT __Flx_BARRETT_LIMIT # define Flx_DIVREM2_BARRETT_LIMIT __Flx_DIVREM2_BARRETT_LIMIT # define Flx_DIVREM_BARRETT_LIMIT __Flx_DIVREM_BARRETT_LIMIT # define Flx_EXTGCD2_LIMIT __Flx_EXTGCD2_LIMIT # define Flx_EXTGCD_LIMIT __Flx_EXTGCD_LIMIT # define Flx_GCD2_LIMIT __Flx_GCD2_LIMIT # define Flx_GCD_LIMIT __Flx_GCD_LIMIT # define Flx_HALFGCD2_LIMIT __Flx_HALFGCD2_LIMIT # define Flx_HALFGCD_LIMIT __Flx_HALFGCD_LIMIT # define Flx_INVBARRETT2_LIMIT __Flx_INVBARRETT2_LIMIT # define Flx_INVBARRETT_LIMIT __Flx_INVBARRETT_LIMIT # define Flx_MUL2_KARATSUBA_LIMIT __Flx_MUL2_KARATSUBA_LIMIT # define Flx_MUL2_MULII_LIMIT __Flx_MUL2_MULII_LIMIT # define Flx_MUL_KARATSUBA_LIMIT __Flx_MUL_KARATSUBA_LIMIT # define Flx_MUL_MULII_LIMIT __Flx_MUL_MULII_LIMIT # define Flx_REM2_BARRETT_LIMIT __Flx_REM2_BARRETT_LIMIT # define Flx_REM_BARRETT_LIMIT __Flx_REM_BARRETT_LIMIT # define Flx_SQR2_KARATSUBA_LIMIT __Flx_SQR2_KARATSUBA_LIMIT # define Flx_SQR2_SQRI_LIMIT __Flx_SQR2_SQRI_LIMIT # define Flx_SQR_KARATSUBA_LIMIT __Flx_SQR_KARATSUBA_LIMIT # define Flx_SQR_SQRI_LIMIT __Flx_SQR_SQRI_LIMIT # define FlxqX_BARRETT_LIMIT __FlxqX_BARRETT_LIMIT # define FlxqX_DIVREM_BARRETT_LIMIT __FlxqX_DIVREM_BARRETT_LIMIT # define FlxqX_EXTGCD_LIMIT __FlxqX_EXTGCD_LIMIT # define FlxqX_GCD_LIMIT __FlxqX_GCD_LIMIT # define FlxqX_HALFGCD_LIMIT __FlxqX_HALFGCD_LIMIT # define FlxqX_INVBARRETT_LIMIT __FlxqX_INVBARRETT_LIMIT # define FlxqX_REM_BARRETT_LIMIT __FlxqX_REM_BARRETT_LIMIT # define FpXQX_BARRETT_LIMIT __FpXQX_BARRETT_LIMIT # define FpXQX_DIVREM_BARRETT_LIMIT __FpXQX_DIVREM_BARRETT_LIMIT # define FpXQX_EXTGCD_LIMIT __FpXQX_EXTGCD_LIMIT # define FpXQX_GCD_LIMIT __FpXQX_GCD_LIMIT # define FpXQX_HALFGCD_LIMIT __FpXQX_HALFGCD_LIMIT # define FpXQX_INVBARRETT_LIMIT __FpXQX_INVBARRETT_LIMIT # define FpXQX_REM_BARRETT_LIMIT __FpXQX_REM_BARRETT_LIMIT # define FpX_BARRETT_LIMIT __FpX_BARRETT_LIMIT # define FpX_DIVREM_BARRETT_LIMIT __FpX_DIVREM_BARRETT_LIMIT # define FpX_EXTGCD_LIMIT __FpX_EXTGCD_LIMIT # define FpX_GCD_LIMIT __FpX_GCD_LIMIT # define FpX_HALFGCD_LIMIT __FpX_HALFGCD_LIMIT # define FpX_INVBARRETT_LIMIT __FpX_INVBARRETT_LIMIT # define FpX_REM_BARRETT_LIMIT __FpX_REM_BARRETT_LIMIT # define Fp_POW_BARRETT_LIMIT __Fp_POW_BARRETT_LIMIT # define Fp_POW_REDC_LIMIT __Fp_POW_REDC_LIMIT # define GCD_HALFGCD_LIMIT __GCD_HALFGCD_LIMIT # define HALFGCD_LIMIT __HALFGCD_LIMIT # define INVMOD_GMP_LIMIT __INVMOD_GMP_LIMIT # define INVNEWTON_LIMIT __INVNEWTON_LIMIT # define LOGAGMCX_LIMIT __LOGAGMCX_LIMIT # define LOGAGM_LIMIT __LOGAGM_LIMIT # define MULII_FFT_LIMIT __MULII_FFT_LIMIT # define MULII_KARATSUBA_LIMIT __MULII_KARATSUBA_LIMIT # define MULRR_MULII_LIMIT __MULRR_MULII_LIMIT # define RgX_MUL_LIMIT __RgX_MUL_LIMIT # define RgX_SQR_LIMIT __RgX_SQR_LIMIT # define SQRI_FFT_LIMIT __SQRI_FFT_LIMIT # define SQRI_KARATSUBA_LIMIT __SQRI_KARATSUBA_LIMIT # define SQRR_SQRI_LIMIT __SQRR_SQRI_LIMIT # define ZM2_MUL_LIMIT __ZM2_MUL_LIMIT #endif pari-2.17.2/src/headers/paristio.h0000644000175000017500000002226214760123736015406 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* This file contains memory and I/O management definitions */ typedef struct { long s, us; } pari_timer; typedef struct pari_str { char *string; /* start of the output buffer */ char *end; /* end of the output buffer */ char *cur; /* current writing place in the output buffer */ size_t size; /* buffer size */ int use_stack; /* use stack_malloc instead of malloc ? */ } pari_str; typedef ulong pari_sp; struct pari_sieve { ulong start, end, maxpos; ulong c, q; unsigned char* sieve; }; /* iterator over primes */ typedef struct { int strategy; /* 1 to 4 */ GEN bb; /* iterate through primes <= bb */ ulong c, q; /* congruent to c (mod q) */ GEN qq; /* strategy 1: private prime table */ ulong n; /* 1 <= n <= pari_PRIMES[0] */ ulong p; /* current p = n-th prime */ ulong b; /* min(bb, ULONG_MAX) */ /* strategy 2: sieve, use p */ struct pari_sieve *psieve; unsigned char *sieve, *isieve; ulong cache[9]; /* look-ahead primes already computed */ ulong chunk; /* # of odd integers in sieve */ ulong a, end, sieveb; /* [a,end] interval currently being sieved, * end <= sieveb = min(bb, maxprime^2, ULONG_MAX) */ ulong pos, maxpos; /* current cell and max cell */ /* strategy 3: unextprime, use p */ /* strategy 4: nextprime */ GEN pp; } forprime_t; typedef struct { int first; GEN b, n, p; forprime_t T; } forcomposite_t; typedef struct forvec_t { long first; GEN *a, *m, *M; /* current n-uplet, minima, Maxima */ long n; /* length */ GEN (*next)(struct forvec_t *); } forvec_t; /* Iterate over partitions */ typedef struct { long k; long amax, amin, nmin, nmax, strip; GEN v; } forpart_t; /* Iterate over permutations */ typedef struct { long k, first; GEN v; } forperm_t; /* Iterate over subsets */ typedef struct { long n, k, all, first; GEN v; } forsubset_t; /* Plot engines */ typedef struct PARI_plot { void (*draw)(struct PARI_plot *T, GEN w, GEN x, GEN y); long width; long height; long hunit; long vunit; long fwidth; long fheight; long dwidth; long dheight; } PARI_plot; /* binary I/O */ typedef struct GENbin { size_t len; /* gsizeword(x) */ GEN x; /* binary copy of x */ GEN base; /* base address of p->x */ void (*rebase)(GEN,long); } GENbin; struct pari_mainstack { pari_sp top, bot, vbot; size_t size, rsize, vsize, memused; }; 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; ulong hash; struct entree *next; } entree; struct pari_parsestate { long node; int once; long discarded; const char *lex_start; GEN lasterror; }; struct pari_compilestate { long opcode, operand, accesslex, data, localvars, frames, dbginfo; long offset, nblex; const char *dbgstart; }; struct pari_mtstate { long pending_threads; long is_thread; long trace_level; }; struct pari_evalstate { pari_sp avma; long sp; long rp; long var; long lvars; long locks; long prec; long trace; struct pari_mtstate mt; struct pari_compilestate comp; }; struct pari_varstate { long nvar, max_avail, min_priority, max_priority; }; struct pari_filestate { pariFILE *file; long serial; }; struct gp_context { long listloc; long prettyp; struct pari_varstate var; struct pari_evalstate eval; struct pari_parsestate parse; struct pari_filestate file; jmp_buf *iferr_env; GEN err_data; }; extern THREAD struct pari_mainstack *pari_mainstack; struct pari_global_state { long debugvar; long bitprec; GEN primetab; GEN seadata; long *varpriority; struct pari_varstate varstate; }; struct pari_thread { struct pari_mainstack st; struct pari_global_state gs; GEN data; }; struct mt_state { GEN worker; GEN pending; long workid; }; struct pari_mt { struct mt_state mt; GEN (*get)(struct mt_state *mt, long *workid, long *pending); void (*submit)(struct mt_state *mt, long workid, GEN work); void (*end)(void); }; struct parfor_iter { long pending; GEN worker; struct pari_mt pt; }; typedef struct { GEN a, b; struct parfor_iter iter; } parfor_t; typedef struct { GEN a, b, s; long i; int (*cmp)(GEN,GEN); struct parfor_iter iter; } parforstep_t; typedef struct { GEN x, W; long i, l; struct parfor_iter iter; } parforeach_t; typedef struct { GEN v; forprime_t forprime; struct parfor_iter iter; } parforprime_t; typedef struct { GEN v; forvec_t forvec; struct parfor_iter iter; } parforvec_t; typedef struct PariOUT { void (*putch)(char); void (*puts)(const char*); void (*flush)(void); } PariOUT; /* hashtables */ typedef struct hashentry { void *key, *val; ulong hash; /* hash(key) */ struct hashentry *next; } hashentry; typedef struct hashtable { ulong len; /* table length */ hashentry **table; /* the table */ ulong nb, maxnb; /* number of entries stored and max nb before enlarging */ ulong pindex; /* prime index */ ulong (*hash) (void *k); /* hash function */ int (*eq) (void *k1, void *k2); /* equality test */ int use_stack; /* use stack_malloc instead of malloc ? */ } hashtable; typedef struct { void **data; long n; long alloc; size_t size; } pari_stack; /* GP_DATA */ typedef struct { GEN z; /* result */ time_t t; /* time to obtain result */ time_t r; /* realtime to obtain result */ } gp_hist_cell; typedef struct { gp_hist_cell *v; /* array of previous results, FIFO */ size_t size; /* # res */ ulong total; /* # of results computed since big bang */ } gp_hist; /* history */ typedef struct { pariFILE *file; char *cmd; } gp_pp; /* prettyprinter */ typedef struct { char *PATH; char **dirs; } gp_path; /* path */ typedef struct { char format; /* e,f,g */ long sigd; /* -1 (all) or number of significant digits printed */ int sp; /* 0 = suppress whitespace from output */ int prettyp; /* output style: raw, prettyprint, etc */ int TeXstyle; } pariout_t; /* output format */ enum { gpd_QUIET=1, gpd_TEST=2, gpd_EMACS=256, gpd_TEXMACS=512}; enum { DO_MATCHED_INSERT = 2, DO_ARGS_COMPLETE = 4 }; typedef struct { gp_hist *hist; gp_pp *pp; gp_path *path, *sopath; pariout_t *fmt; ulong lim_lines, flags, linewrap, readline_state, echo; int breakloop, recover, use_readline; char *help, *histfile, *prompt, *prompt_cont, *prompt_comment; GEN colormap, graphcolors, plothsizes; int secure, simplify, strictmatch, strictargs, chrono; pari_timer *T, *Tw; ulong primelimit; /* deprecated */ ulong factorlimit; ulong threadsizemax, threadsize; } gp_data; extern gp_data *GP_DATA; /* Common global variables: */ extern PariOUT *pariOut, *pariErr; extern FILE *pari_outfile, *pari_logfile, *pari_infile, *pari_errfile; extern ulong pari_logstyle; enum pari_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; #define DISABLE_MEMUSED (size_t)-1 extern pari_prime *pari_PRIMES; extern char *current_psfile, *pari_datadir; #define gcopyifstack(x,y) STMT_START {pari_sp _t=(pari_sp)(x); \ (y)=(_t>=pari_mainstack->bot &&_ttop)? \ gcopy((GEN)_t): (GEN)_t;} STMT_END #define copyifstack(x,y) STMT_START {pari_sp _t=(pari_sp)(x); \ (y)=(_t>=pari_mainstack->bot &&_ttop)? \ gcopy((GEN)_t): (GEN)_t;} STMT_END #define icopyifstack(x,y) STMT_START {pari_sp _t=(pari_sp)(x); \ (y)=(_t>=pari_mainstack->bot &&_ttop)? \ icopy((GEN)_t): (GEN)_t;} STMT_END #define DEBUG_TUNE_SYSTEM(var,s) \ {\ static long _once, _lastt;\ if(_lastt!=var) { _lastt=var; _once=0; }\ if (_once==0) {_once=1; err_printf("t=%ld s=%ld\n",var,s); }\ } /* Define this to thoroughly check "random" garbage collecting */ #ifdef DEBUG_LOWSTACK # define low_stack(x,l) 1 # define gc_needed(av,n) ((void)av,1) #else # define low_stack(x,l) ((void)(x),avma < (pari_sp)(l)) # define gc_needed(av,n) (avma < (pari_sp)stack_lim(av,n) && (av) > ((pari_mainstack->bot >> 1) + (pari_mainstack->top >> 1))) #endif #define stack_lim(av,n) (pari_mainstack->bot+(((av)-pari_mainstack->bot)>>(n))) #ifndef SIG_IGN # define SIG_IGN (void(*)())1 #endif #ifndef SIGINT # define SIGINT 2 #endif pari-2.17.2/src/systems/0000755000175000017500000000000014760315601013465 5ustar billbillpari-2.17.2/src/systems/win32/0000755000175000017500000000000014760315601014427 5ustar billbillpari-2.17.2/src/systems/win32/pariinl.h0000644000175000017500000000025514567450071016246 0ustar billbill/* This file contains declarations/definitions of functions that * _can_ be inlined. */ #include "../src/kernel/ix86/level0.h" #include "../src/kernel/none/level1.h" pari-2.17.2/src/systems/win32/README.MSVC0000644000175000017500000000614114557721031016062 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.17.2/src/systems/emscripten/0000755000175000017500000000000014760315601015636 5ustar billbillpari-2.17.2/src/systems/emscripten/emscripten.c0000644000175000017500000000410314676526175020171 0ustar billbill/* Copyright (C) 2016 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include "pari.h" #include "../src/graph/rect.h" void pari_emscripten_wget(const char *s) { const char *name = stack_sprintf("/gpjs/root/%s",s); emscripten_wget(name,s); } void pari_emscripten_help(const char *s, long n) { const char *url = "https://pari.math.u-bordeaux.fr/dochtml"; char *t; (void) n; #if ((PARI_VERSION_CODE>>PARI_VERSION_SHIFT)&1) t = pari_sprintf("%s/help-stable/%s\n",url,s); #else t = pari_sprintf("%s/help/%s\n",url,s); #endif EM_ASM(window.open(UTF8ToString($0)),t); pari_free(t); } static void emscripten_draw(PARI_plot *T, GEN w, GEN x, GEN y) { pari_sp av = avma; GEN svg = pari_base64(rect2svg(w,x,y,NULL)); EM_ASM(rawPrint=true);(void)T; pari_printf("\n", svg); EM_ASM(rawPrint=false); set_avma(av); } static long plot_width, plot_height; static void pari_emscripten_get_plot(PARI_plot *T) { T->width = plot_width; T->height = plot_height; T->hunit = 3; T->vunit = 3; T->fwidth = 9; T->fheight = 12; gp_get_ploth_default_sizes(T); T->dwidth = 0; T->dheight = 0; T->draw = &emscripten_draw; } void pari_emscripten_plot_init(long width, long height) { plot_width = width; plot_height = height; pari_set_plot_engine(pari_emscripten_get_plot); } void pari_emscripten_init(long rsize, long vsize) { gp_embedded_init(rsize, vsize); cb_pari_long_help = &pari_emscripten_help; } pari-2.17.2/src/systems/emscripten/emscripten.h0000644000175000017500000000154314676526175020203 0ustar billbill/* Copyright (C) 2016 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ BEGINEXTERN void pari_emscripten_help(const char *s, long n); void pari_emscripten_wget(const char *s); void pari_emscripten_plot_init(long width, long height); void pari_emscripten_init(long rsize, long vsize); ENDEXTERN pari-2.17.2/src/systems/darwin/0000755000175000017500000000000014760315601014751 5ustar billbillpari-2.17.2/src/systems/darwin/dlfcn.h0000644000175000017500000000436714567450071016230 0ustar billbill/* Copyright (c) 2002 Jorge Acereda & Peter O'Gorman Portions may be copyright others, see the AUTHORS file included with this distribution. Maintained by Peter O'Gorman Bug Reports and other queries should go to Permission is hereby granted, free of charge, to any person obtaining a copy of this software and attached 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.17.2/src/systems/darwin/darwin.c0000644000175000017500000001417514567450071016417 0ustar billbill/* Copyright (c) 2002 Peter O'Gorman Permission is hereby granted, free of charge, to any person obtaining a copy of this software and attached 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.17.2/src/systems/mingw/0000755000175000017500000000000014760315601014606 5ustar billbillpari-2.17.2/src/systems/mingw/mingw.h0000644000175000017500000000170714567450071016113 0ustar billbill/* Copyright (C) 2009 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ const char* win32_basedir(void); char* win32_datadir(void); void win32_ansi_fputs(const char* s, void* f); int win32_terminal_width(void); int win32_terminal_height(void); void win32_set_codepage(void); void win32_set_pdf_viewer(void); void win32_alarm(unsigned int s); long win32_timer(void); long win32_nbthreads(void); pari-2.17.2/src/systems/mingw/mingw.c0000644000175000017500000001207514567450071016106 0ustar billbill/* Copyright (C) 2009 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* Originally written by Vasili Burdo */ #include "pwinver.h" #include #include #include "mingw.h" static const char * pariwin32_basedir = NULL; const char* win32_basedir(void) { if (!pariwin32_basedir) { char basedir[1024]; char* slash; GetModuleFileNameA(0, basedir, sizeof(basedir) ); slash = strrchr(basedir, '\\'); if (slash) slash[1] = 0; pariwin32_basedir = strdup(basedir); } return pariwin32_basedir; } char* win32_datadir(void) { char datadir[1029]; const char * basedir = win32_basedir(); sprintf(datadir, "%sdata", basedir); return strdup(datadir); } static WORD win32_console_color(unsigned long c) { int shift, intense = 0; if( c >= 30 && c <= 37 ) { shift = 0; c -= 30; } else if( c >= 40 && c <= 47 ) { shift = 4; c -= 40; } else if( c >= 90 && c <= 97 ) { shift = 0; intense = 8; c -= 90; } else if(c >= 100 && c <= 107) { shift = 4; intense = 8; c -= 100; } else return 0; WORD w = 0; switch(c) { case 0: w = 0; break; /* black */ case 1: w = 4; break; /* red */ case 2: w = 2; break; /* green */ case 3: w = 6; break; /* yellow RG */ case 4: w = 1; break; /* blue */ case 5: w = 5; break; /* magenta RB */ case 6: w = 3; break; /* cyan GB */ case 7: w = 7; break; /* white RGB */ } return (w|intense) << shift; } void win32_ansi_fputs(const char* s, void* f) { WORD color; unsigned long c[3]; long nbarg; if( !(f == stdout || f == stderr) ) { fputs(s,f); return; } while(1) { char *p; p = strstr(s, "\x1b["); if( p > s ) fwrite(s,p-s,1,f); if( p ) p += 2; else { fputs(s,f); return; } nbarg = 0; c[nbarg++] = strtoul(p,&p,10); if( *p == ';' ) c[nbarg++] = strtoul(p+1,&p,10); if( *p == ';' ) c[nbarg++] = strtoul(p+1,&p,10); if( *p++ == 'm' ) { switch(nbarg) { case 1: color = 7; break; case 2: color = win32_console_color(c[1]); if (c[0]&4) color |= 0x8000; break; case 3: color = win32_console_color(c[1]) | win32_console_color(c[2]); if (c[0]&4) color |= 0x8000; } fflush(f); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),color); } s = p; } } int win32_terminal_width(void) { CONSOLE_SCREEN_BUFFER_INFO sbi; if (!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &sbi)) return 0; return sbi.srWindow.Right - sbi.srWindow.Left + 1; } int win32_terminal_height(void) { CONSOLE_SCREEN_BUFFER_INFO sbi; if (!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &sbi)) return 0; return sbi.srWindow.Bottom - sbi.srWindow.Top + 1; } void win32_set_codepage(void) { SetConsoleCP( GetACP() ); SetConsoleOutputCP( GetACP() ); } void win32_set_pdf_viewer(void) { char *s = getenv("GP_PDF_VIEWER"); if (!s) { HKEY handle; const char *key = "AcroExch.Document\\shell\\open\\command"; const long SZ = 512; char str[SZ], *buf; int status; DWORD L = SZ; (void)RegOpenKeyEx(HKEY_CLASSES_ROOT, key, 0, KEY_READ, &handle); status = RegQueryValueEx(handle, NULL, 0, NULL, (LPBYTE)str, &L); RegCloseKey(handle); if (status) return; buf = malloc(strlen(str)+16); /*must not be freed*/ sprintf(buf,"GP_PDF_VIEWER=%s",str); putenv(buf); } } extern int win32ctrlc, win32alrm; static HANDLE hTimerQueue = NULL; static void CALLBACK win32_cb_alarm(void *lpParam, BOOLEAN TimerOrWaitFired) { (void) lpParam; (void) TimerOrWaitFired; win32ctrlc++; win32alrm = 1; } void win32_alarm(unsigned int s) { if (hTimerQueue) { HANDLE oldhTimerQueue = hTimerQueue; hTimerQueue = NULL; DeleteTimerQueue(oldhTimerQueue); } if (s) { void *arg = NULL; HANDLE hTimer = NULL; hTimerQueue = CreateTimerQueue(); CreateTimerQueueTimer( &hTimer, hTimerQueue, (WAITORTIMERCALLBACK)win32_cb_alarm, &arg , s*1000, 0, 0); } } #define WIN32_FILETIME_PER_MILLISECOND 10000 long win32_timer(void) { FILETIME lpCreation, lpExit, lpKernel, lpUser; LARGE_INTEGER time; GetProcessTimes( GetCurrentProcess(), &lpCreation, &lpExit, &lpKernel, &lpUser ); time.HighPart = lpUser.dwHighDateTime; time.LowPart = lpUser.dwLowDateTime; time.QuadPart /= WIN32_FILETIME_PER_MILLISECOND; return time.LowPart; } long win32_nbthreads(void) { SYSTEM_INFO system_info; GetSystemInfo(&system_info); return system_info.dwNumberOfProcessors; } pari-2.17.2/src/systems/mingw/pwinver.h0000644000175000017500000000002514567450071016454 0ustar billbill#define WINVER 0x501 pari-2.17.2/src/systems/os2/0000755000175000017500000000000014760315601014170 5ustar billbillpari-2.17.2/src/systems/os2/README0000644000175000017500000000416314557721031015056 0ustar billbillOn OS/2 the build goes the same way as on Unix, e.g., sh Configure make gp make bench With the current implementation of install(), one can load the functions from the PARI library only if the GP executable is build for dynamic linking. By default, the build will go to an AOUT-type executables (to simplify the logic of Configure, and enable restricted binary compatibility with DOS/Windows). Unfortunately, AOUT-type DLLs are very restricted; thus the build of dynamically linked target fails. To build with OMF-type target cd Oos2-ix86 make _O=.obj _A=.lib CC_FLAVOR="-Zomf -Zcrtdll -Zstack 8192" RLLIBS=-lreadline_import DLLD_IGNORE= AR=emxomfar bench This build constructs a working DLL. Both -Zomf and -Zcrtdll are crucial to have a functioning DLL (see EMX documentation for details). -Zstack 8192 forces the same C stack size as for AOUT build (and the same - 8M - as on many Unices, so you get fewer surprises when things work on Unix, but core on OS/2 due only to shorter C stack). (The standard Configure adds -Zsysv-signals option; in fact, this option is not needed - as checked with v2.3.5.) Use of the the readline-DLL (via the readline_import.lib library) is not only a convenience, but also statically linked readline library are often broken; sigh... To use the gnuplot-engine DLL gnpltdrw.DLL, one can give Configure the option --graphic=gnuplot-dynamic,gnpltdrw (requires linking with -Zcrtdll for graphics to work). Add -DOLD_SET_FEEDBACK_RECTANGLE gcc option if gnpltdrw.DLL supports mousing, but is an old build, so it won't report this capability. Thus the build process may look like this: sh Configure --graphic=gnuplot-dynamic,gnpltdrw make gp cd Oos2-ix86 make _O=.obj _A=.lib CC_FLAVOR="-Zomf -Zcrtdll -Zstack 8192 -DUSE_SET_FEEDBACK_RECTANGLE" RLLIBS=-lreadline_import DLLD_IGNORE= AR=emxomfar bench cd .. The statically build PARI library is in a file named similar to libpari-2_2.a, the library for linking with the PARI DLL is named as pari-2_2.a (or pari-2_2.lib). As a debugging tool, the constructed DLL reports its build options via the standard OS/2 way: bldlevel FULL_NAME_OF_THE_DLL pari-2.17.2/src/systems/os2/pari.def.base0000644000175000017500000000040111636712103016504 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.17.2/src/systems/os2/os2.c0000644000175000017500000001121314567450071015043 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 = 0; 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, 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, ", 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.17.2/src/systems/os2/dlfcn.h0000644000175000017500000000021411636712103015421 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.17.2/src/systems/cygwin/0000755000175000017500000000000014760315601014765 5ustar billbillpari-2.17.2/src/systems/cygwin/cygwin.c0000644000175000017500000000166514567450071016447 0ustar billbill/* Copyright (C) 2009 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* Written by Vasili Burdo */ #include #include char* win32_datadir(void) { char datadir[1024]; char* slash; GetModuleFileNameA(0, datadir, sizeof(datadir)); slash = strrchr(datadir, '\\'); if (slash) slash[1] = 0; strcat(datadir, "data"); return strdup(datadir); } pari-2.17.2/src/graph/0000755000175000017500000000000014760315601013057 5ustar billbillpari-2.17.2/src/graph/plotps.c0000644000175000017500000000245014567450071014553 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*******************************************************************/ /* HIGH RESOLUTION PLOT VIA POSTSCRIPT FILE */ /*******************************************************************/ #include "pari.h" #include "rect.h" static void draw(PARI_plot *T, GEN w, GEN x, GEN y) { if (pari_daemon()) return; /* parent process returns */ pari_plot_by_file("GP_POSTSCRIPT_VIEWER", ".ps", rect2ps_i(w,x,y,T,1)); exit(0); } void gp_get_plot(PARI_plot *T) { T->width = 400; T->height = 300; T->fheight= 9; T->fwidth = 5; T->hunit = 3; T->vunit = 3; gp_get_ploth_default_sizes(T); T->dwidth = 0; T->dheight= 0; T->draw = &draw; } pari-2.17.2/src/graph/plotsvg.c0000644000175000017500000000231614567450071014731 0ustar billbill/* Copyright (C) 2017 The PARI group. This file is part of the PARI/GP package. 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. */ #include "pari.h" #include "rect.h" static void draw(PARI_plot *T, GEN w, GEN x, GEN y) { if (pari_daemon()) return; /* parent process returns */ pari_plot_by_file("GP_SVG_VIEWER", ".svg", rect2svg(w,x,y,T)); exit(0); } void gp_get_plot(PARI_plot *T) { T->width = 480; T->height = 320; T->fheight = 12; T->fwidth = 6; T->hunit = 3; T->vunit = 3; gp_get_ploth_default_sizes(T); T->dwidth = 0; T->dheight = 0; T->draw = &draw; } pari-2.17.2/src/graph/plotport.c0000644000175000017500000025604714760123736015132 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*******************************************************************/ /* */ /* PLOT ROUTINES */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" #include "rect.h" static void (*pari_get_plot)(PARI_plot *); /* no need for THREAD: OK to share this */ static hashtable *rgb_colors = NULL; THREAD PariRect rectgraph[18]; /*NUMRECT*/ static THREAD long current_color[18]; /*NUMRECT*/ static long plotpoint_itype = 0, rectline_itype = 0; const long NUMRECT = 18; const long RECUR_MAXDEPTH = 10; const double RECUR_PREC = 0.001; const long DEFAULT_COLOR = 1, AXIS_COLOR = 2; enum { ROt_MV = 1, /* Move */ ROt_PT, /* Point */ ROt_LN, /* Line */ ROt_AC, /* Arc */ ROt_FAC, /* Filled Arc */ ROt_BX, /* Box */ ROt_FBX, /* Filled Box */ ROt_MP, /* Multiple point */ ROt_ML, /* Multiple lines */ ROt_ST, /* String */ ROt_PTT, /* Point type change */ ROt_LNT, /* Line type change */ ROt_PTS, /* Point size change */ ROt_NULL, /* To be the start of the chain */ }; /* string justification */ #define RoSTdirLEFT 0x00 #define RoSTdirRIGHT 0x02 #define RoSTdirHPOS_mask 0x03 #define RoSTdirBOTTOM 0x00 #define RoSTdirTOP 0x08 #define RoSTdirVPOS_mask 0x0c #define RoSTdirHGAP 0x10 #define RoSTdirVGAP 0x20 /* ploth flags */ #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_NOMINMAX 0x02000 #define PLOT_PARA 0x80000 INLINE long DTOL(double t) { return (long)(t + 0.5); } static const long PS_WIDTH = 1120 - 60; /* 1400 - 60 for hi-res */ static const long PS_HEIGH = 800 - 40; /* 1120 - 60 for hi-res */ static const long PS_SCALE = 1000; /* Allowing 64x zoom on 500ppi */ static void _psdraw_scale(PARI_plot *T, GEN w, GEN x, GEN y) { pari_sp av = avma; FILE *F = fopen(current_psfile, "a"); if (!F) pari_err_FILE("postscript file",current_psfile); fputs(rect2ps(w,x,y,T), F); fclose(F); set_avma(av); } static void _psdraw(PARI_plot *T, GEN w, GEN x, GEN y) { (void)T; _psdraw_scale(NULL,w,x,y); } static void pari_get_psplot(PARI_plot *T) { T->width = PS_WIDTH; T->height = PS_HEIGH; T->fheight= 15; T->fwidth = 6; T->hunit = 5; T->vunit = 5; T->dwidth = 0; T->dheight= 0; T->draw = NULL; } static void pari_get_svgplot(PARI_plot *T) { T->width = 480; T->height = 320; T->fheight = 12; T->fwidth = 6; T->hunit = 3; T->vunit = 3; T->dwidth = 0; T->dheight = 0; T->draw = NULL; } /********************************************************************/ /** **/ /** RECTPLOT FUNCTIONS **/ /** **/ /********************************************************************/ void pari_init_graphics(void) { pari_get_plot = &pari_get_svgplot; } void pari_set_plot_engine(void (*plot)(PARI_plot *)) { long n; pari_get_plot = plot; for (n = 0; n < NUMRECT; n++) { PariRect *e = &rectgraph[n]; RHead(e) = RTail(e) = NULL; RXsize(e) = RYsize(e) = 0; } } void pari_kill_plot_engine(void) { int i; for (i=0; itable); pari_free((void*)rgb_colors); } } static PariRect * check_rect(long ne) { const char *f = "graphic function"; const long m = NUMRECT-1; if (ne < 0) pari_err_DOMAIN(f, "rectwindow", "<", gen_0, stoi(ne)); else if (ne > m) pari_err_DOMAIN(f, "rectwindow", ">", stoi(m), stoi(ne)); else return &rectgraph[ne]; return NULL;/*LCOV_EXCL_LINE*/ } static PariRect * check_rect_init(long ne) { PariRect *e = check_rect(ne); if (!RHead(e)) pari_err_TYPE("graphic function [use plotinit()]", stoi(ne)); return e; } static void Rchain(PariRect *e, RectObj *z) { if (!RHead(e)) RHead(e) = z; else RoNext(RTail(e)) = z; RTail(e) = z; RoNext(z) = NULL; } static long rgb_to_long(long r, long g, long b) { return (r << 16) | (g << 8) | b; } /* c from graphcolormap */ static long colormap_to_color(long i) { GEN c = GP_DATA->colormap; long k = i+1, l = lg(c)-1; int r, g, b; if (k > l) pari_err_COMPONENT("graphcolormap",">", stoi(l), stoi(k)); color_to_rgb(gel(c, k), &r,&g,&b); return rgb_to_long(r, g, b); } static void initrect_i(long ne, long x, long y) { PariRect *e; RectObj *z; if (x <= 1) pari_err_DOMAIN("plotinit", "x", "<=", gen_1, stoi(x)); if (y <= 1) pari_err_DOMAIN("plotinit", "y", "<=", gen_1, stoi(y)); e = check_rect(ne); if (RHead(e)) plotkill(ne); current_color[ne] = colormap_to_color(DEFAULT_COLOR); z = (RectObj*) pari_malloc(sizeof(RectObj)); RoType(z) = ROt_NULL; Rchain(e, z); RXsize(e) = x; RXcursor(e) = 0; RXscale(e) = 1; RXshift(e) = 0; RYsize(e) = y; RYcursor(e) = 0; RYscale(e) = 1; RYshift(e) = 0; } static long initrect_get_arg(GEN x, long dft) { if (!x) return dft; if (typ(x) != t_INT) pari_err_TYPE("plotinit",x); return itos(x); } void plotinit(long ne, GEN x, GEN y, long flag) { const long m = NUMRECT-3; long xi, yi; PARI_plot T; if (flag) { pari_get_plot(&T); xi = T.width -1; if (x) xi = DTOL(xi * gtodouble(x)); yi = T.height-1; if (y) yi = DTOL(yi * gtodouble(y)); } else { if (!x || !y) pari_get_plot(&T); xi = initrect_get_arg(x, T.width -1); yi = initrect_get_arg(y, T.height-1); } if (ne > m) pari_err_DOMAIN("plotinit", "rectwindow", ">", stoi(m), stoi(ne)); initrect_i(ne, xi, yi); } GEN plotcursor(long ne) { PariRect *e = check_rect_init(ne); return mkvec2s((long)RXcursor(e), (long)RYcursor(e)); } static void plotscale0(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 plotscale(long ne, GEN x1, GEN x2, GEN y1, GEN y2) { plotscale0(ne, gtodouble(x1), gtodouble(x2), gtodouble(y1), gtodouble(y2)); } static void plotmove0(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); } static void _move(long ne, double x, double y) { plotmove0(ne,x,y,0); } void plotmove(long ne, GEN x, GEN y) { plotmove0(ne,gtodouble(x),gtodouble(y),0); } void plotrmove(long ne, GEN x, GEN y) { plotmove0(ne,gtodouble(x),gtodouble(y),1); } /* ROt_MV/ROt_PT */ static void plotpoint0(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; } 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]; } static void plotpoint(long ne, GEN x, GEN y) { plotpoint0(ne,gtodouble(x),gtodouble(y),0); } void plotrpoint(long ne, GEN x, GEN y) { plotpoint0(ne,gtodouble(x),gtodouble(y),1); } GEN plotcolor(long ne, GEN c) { long t = typ(c), n = lg(GP_DATA->colormap)-2; int r, g, b; check_rect(ne); if (t == t_INT) { long i = itos(c); if (i < 0) pari_err_DOMAIN("plotcolor", "color", "<", gen_0, c); if (i > n) pari_err_DOMAIN("plotcolor", "color", ">", stoi(n), c); c = gel(GP_DATA->colormap,i+1); } else { if (t == t_VEC) { c = ZV_to_zv(c); t = typ(c); } if (t != t_VECSMALL && t != t_STR) pari_err_TYPE("plotcolor",c); } color_to_rgb(c, &r,&g,&b); current_color[ne] = rgb_to_long(r,g,b); return mkvec3s(r, g, b); } /* ROt_MV/ROt_LN */ static void rectline0(long ne, double gx2, double gy2, long relative) { 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) { double a = (dxy + RYsize(e)*dx) / dy, b = dxy / dy; if (dx*dy < 0) { xmin=maxdd(xmin,a); xmax=mindd(xmax,b); } else { xmin=maxdd(xmin,b); xmax=mindd(xmax,a); } } if (dx) { double a = (RXsize(e)*dy - dxy) / dx, b = -dxy / dx; if (dx*dy < 0) { ymin=maxdd(ymin,a); ymax=mindd(ymax,b); } else { ymin=maxdd(ymin,b); ymax=mindd(ymax,a); } } 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]; } static void _line(long ne, double x, double y) { rectline0(ne, x, y, 0); } void plotline(long ne, GEN gx2, GEN gy2) { rectline0(ne, gtodouble(gx2), gtodouble(gy2),0); } void plotrline(long ne, GEN gx2, GEN gy2) { rectline0(ne, gtodouble(gx2), gtodouble(gy2),1); } enum { TICKS_CLOCKW = 1, /* Draw in clockwise direction */ TICKS_ACLOCKW = 2, /* Draw in anticlockwise direction */ TICKS_ENDSTOO = 4, /* Draw at endspoints if needed */ TICKS_NODOUBLE = 8 /* Do not draw double-length ticks */ }; /* 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; if (dx < 0) dx = -dx; dy = y2 - y1; 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 = usqrt(dx*dx + dy*dy); nticks = (long) ((dxy + 2.5)/4); if (!nticks) return; /* Find nticks (or less) "round" numbers between l1 and l2. For our purpose * round numbers have "last significant" decimal 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; /* -Wall */ 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++, x += ddx, y += ddy) { 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; double x1, x2, y1, y2; x1 = x2 = x*RXscale(e) + RXshift(e); y1 = y2 = y*RYscale(e) + RYshift(e); if (flags & TICKS_CLOCKW) { x1 += dtx*l; y1 -= dty*l; } if (flags & TICKS_ACLOCKW) { x2 -= dtx*l; y2 += dty*l; } RoLNx1(z) = x1; RoLNy1(z) = y1; RoLNx2(z) = x2; RoLNy2(z) = y2; RoType(z) = ROt_LN; Rchain(e, z); RoCol(z) = current_color[ne]; } } static void rectbox0(long ne, double gx2, double gy2, long relative, long filled) { double xx, yy, x1, y1, x2, y2, xmin, ymin, xmax, ymax; 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(mindd(x1,x2),RXsize(e)),0); xmax = maxdd(mindd(maxdd(x1,x2),RXsize(e)),0); ymin = maxdd(mindd(mindd(y1,y2),RYsize(e)),0); ymax = maxdd(mindd(maxdd(y1,y2),RYsize(e)),0); RoType(z) = filled ? ROt_FBX: ROt_BX; RoBXx1(z) = xmin; RoBXy1(z) = ymin; RoBXx2(z) = xmax; RoBXy2(z) = ymax; Rchain(e, z); RoCol(z) = current_color[ne]; } static void _box(long ne, double x, double y) { rectbox0(ne, x, y, 0, 0); } void plotbox(long ne, GEN gx2, GEN gy2, long f) { rectbox0(ne, gtodouble(gx2), gtodouble(gy2), 0, f); } void plotrbox(long ne, GEN gx2, GEN gy2, long f) { rectbox0(ne, gtodouble(gx2), gtodouble(gy2), 1, f); } static void rectarc0(long ne, double gx2, double gy2, long relative, long filled) { double xx, yy, x1, y1, x2, y2, xmin, ymin, xmax, ymax; 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(mindd(x1,x2),RXsize(e)),0); xmax = maxdd(mindd(maxdd(x1,x2),RXsize(e)),0); ymin = maxdd(mindd(mindd(y1,y2),RYsize(e)),0); ymax = maxdd(mindd(maxdd(y1,y2),RYsize(e)),0); RoType(z) = filled ? ROt_FAC: ROt_AC; RoACx1(z) = xmin; RoACy1(z) = ymin; RoACx2(z) = xmax; RoACy2(z) = ymax; Rchain(e, z); RoCol(z) = current_color[ne]; } void plotarc(long ne, GEN gx2, GEN gy2, long f) { rectarc0(ne, gtodouble(gx2), gtodouble(gy2), 0, f); } 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 plotkill(long ne) { RectObj *z, *t; PariRect *e = check_rect_init(ne); 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; } } /* ROt_MP */ static void plotpoints0(long ne, double *X, double *Y, long lx) { double *px, *py; long i, cp=0; PariRect *e = check_rect_init(ne); RectObj *z = (RectObj*) pari_malloc(sizeof(RectObjMP)); RoMPxs(z) = px = (double*) pari_malloc(lx*sizeof(double)); RoMPys(z) = py = (double*) pari_malloc(lx*sizeof(double)); for (i=0; i= 0 && y >= 0 && x <= RXsize(e) && y <= RYsize(e)) { px[cp] = x; py[cp] = y; cp++; } } RoType(z) = ROt_MP; RoMPcnt(z) = cp; Rchain(e, z); RoCol(z) = current_color[ne]; } void plotpoints(long ne, GEN X, GEN Y) { pari_sp av = avma; double *px, *py; long i, lx; if (!is_vec_t(typ(X)) || !is_vec_t(typ(Y))) { plotpoint(ne, X, Y); return; } lx = lg(X); if (lg(Y) != lx) pari_err_DIM("plotpoints"); lx--; if (!lx) return; px = (double*)stack_malloc_align(lx*sizeof(double), sizeof(double)); X++; py = (double*)stack_malloc_align(lx*sizeof(double), sizeof(double)); Y++; for (i=0; i 1) pari_err_DOMAIN("plotcopy","dx",">",gen_1,xoff); if (xd < 0) pari_err_DOMAIN("plotcopy","dx","<",gen_0,xoff); if (yd > 1) pari_err_DOMAIN("plotcopy","dy",">",gen_1,yoff); if (yd < 0) pari_err_DOMAIN("plotcopy","dy","<",gen_0,yoff); pari_get_plot(&T); x = DTOL(xd * (T.width-1)); y = DTOL(yd * (T.height-1)); } else { if (typ(xoff) != t_INT) pari_err_TYPE("plotcopy",xoff); if (typ(yoff) != t_INT) pari_err_TYPE("plotcopy",yoff); x = itos(xoff); y = itos(yoff); } switch (flag & ~RECT_CP_RELATIVE) { case RECT_CP_NW: break; case RECT_CP_SW: y = RYsize(d) - RYsize(s) - y; break; case RECT_CP_SE: y = RYsize(d) - RYsize(s) - y; /* fall through */ case RECT_CP_NE: x = RXsize(d) - RXsize(s) - x; break; } for (R = RHead(s); R; R = RoNext(R)) { RectObj *o; switch(RoType(R)) { case ROt_PT: o = (RectObj*)cp(R, sizeof(RectObj1P)); RoPTx(o) += x; RoPTy(o) += y; break; case ROt_LN: case ROt_BX: case ROt_FBX: o = (RectObj*)cp(R, sizeof(RectObj2P)); RoLNx1(o) += x; RoLNy1(o) += y; RoLNx2(o) += x; RoLNy2(o) += y; break; case ROt_MP: case ROt_ML: o = (RectObj*)cp(R, sizeof(RectObjMP)); RoMPxs(o) = (double*)cp(RoMPxs(R), sizeof(double)*RoMPcnt(o)); RoMPys(o) = (double*)cp(RoMPys(R), sizeof(double)*RoMPcnt(o)); for (i=0; i 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 plotclip(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: case ROt_FBX: 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) = cpd(RoMPxs(R) + f, c-f); RoMLys(n) = cpd(RoMPys(R) + f, 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 **/ /** **/ /********************************************************************/ static void set_xrange(dblPointList *f, double x) { if (x < f->xsml) f->xsml = x; if (x > f->xbig) f->xbig = x; } static void Appendx(dblPointList *f, dblPointList *l, double x) { (l->d)[l->nb++] = x; set_xrange(f,x); } static void set_yrange(dblPointList *f, double y) { if (y < f->ysml) f->ysml = y; if (y > f->ybig) f->ybig = y; } static void Appendy(dblPointList *f, dblPointList *l, double y) { (l->d)[l->nb++] = y; set_yrange(f,y); } static void get_xy(long cplx, GEN t, double *x, double *y) { GEN a, b; if (cplx) { if (typ(t) == t_VEC) { if (lg(t) != 2) pari_err_DIM("get_xy"); t = gel(t,1); } a = real_i(t); b = imag_i(t); } else { if (typ(t) != t_VEC || lg(t) != 3) pari_err_DIM("get_xy"); a = gel(t,1); b = gel(t,2); } *x = gtodouble(a); *y = gtodouble(b); } /* t a t_VEC (possibly a scalar if cplx), get next (x,y) coordinate starting * at index *i [update i] */ static void get_xy_from_vec(long cplx, GEN t, long *i, double *x, double *y) { GEN a, b; if (cplx) { if (typ(t) == t_VEC) t = gel(t,*i); a = real_i(t); b = imag_i(t); (*i)++; } else { a = gel(t, (*i)++); b = gel(t, (*i)++); } *x = gtodouble(a); *y = gtodouble(b); } static void dblV_from_RgV(dblPointList *L, GEN x) { long j, l = lg(x); double *X = (double*)pari_malloc(l*sizeof(double)); for (j = 1; j < l; j++) X[j-1] = gtodouble(gel(x,j)); L->d = X; L->nb = l-1; } /* Convert data from GEN to double before we call plotrecthrawin. */ static dblPointList* gtodblList(GEN data, long flags) { dblPointList *l, *L; double *X, *Y; long nl = lg(data)-1, i, j; const long param = (flags & (PLOT_PARAMETRIC|PLOT_COMPLEX)); const long cplx = (flags & PLOT_COMPLEX); if (! is_vec_t(typ(data))) pari_err_TYPE("gtodblList",data); if (!nl) return NULL; if (nl == 1 && !cplx) pari_err_DIM("gtodblList"); for (i = 1; i <= nl; i++) { /* Check input first */ GEN x = gel(data,i); if (!is_vec_t(typ(x))) pari_err_TYPE("gtodblList",x); } if (flags & PLOT_PARAMETRIC) { if (odd(nl)) pari_err_TYPE("gtodbllist [odd #components in parametric plot]", data); for (i = 1; i < nl; i += 2) { GEN x = gel(data,i), y = gel(data,i+1); if (lg(y) != lg(x)) pari_err_DIM("gtodblList"); } } else if (!cplx) { long l1 = lg(gel(data,1)); if (l1 == 1) return NULL; for (i = 2; i <= nl; i++) if (lg(gel(data,i)) != l1) pari_err_DIM("gtodblList"); } /* Now allocate memory and convert coord. to double */ if (cplx) { l = (dblPointList*)pari_malloc((2*nl)*sizeof(dblPointList)); for (i = 0; i < nl; i++) { pari_sp av = avma; GEN x = gel(data,i+1); dblV_from_RgV(&l[2*i], real_i(x)); dblV_from_RgV(&l[2*i+1], imag_i(x)); set_avma(av); } } else if (param) { l = (dblPointList*)pari_malloc(nl*sizeof(dblPointList)); for (i = 1; i < nl; i += 2) { dblV_from_RgV(&l[i-1], gel(data,i)); dblV_from_RgV(&l[i], gel(data,i+1)); } } else { l = (dblPointList*)pari_malloc(nl*sizeof(dblPointList)); dblV_from_RgV(&l[0], gel(data,1)); for (i = 2; i <= nl; i++) dblV_from_RgV(&l[i-1], gel(data, i)); } /* Compute extremas */ L = &l[0]; if (param) { L->nb = cplx? nl: nl/2; for (i=0; i < L->nb; i+=2) if (l[i+1].nb) break; if (i >= L->nb) { pari_free(l); return NULL; } L->xsml = L->xbig = l[i ].d[0]; L->ysml = L->ybig = l[i+1].d[0]; for (; i < L->nb; i+=2) { long nbi = l[i+1].nb; X = l[i].d; Y = l[i+1].d; for (j = 0; j < nbi; j++) { set_xrange(L, X[j]); set_yrange(L, Y[j]); } } } else { L->nb = nl-1; X = L->d; L->xsml = L->xbig = X[0]; Y = l[1].d; L->ysml = L->ybig = Y[0]; for (j=0; j < l[1].nb; j++) set_xrange(L, X[j]); for (i=1; i <= L->nb; i++) { long nbi = l[i].nb; Y = l[i].d; for (j = 0; j < nbi; j++) set_yrange(L, Y[j]); } } return l; } /* x,y t_REAL; return (x+y)/2, */ static GEN rmiddle(GEN x, GEN y) { GEN z = addrr(x,y); shiftr_inplace(z,-1); return z; } static void single_recursion(void *E, GEN(*eval)(void*,GEN), dblPointList *pl, GEN xl,double yl, GEN xr,double yr,long depth) { GEN xx; pari_sp av = avma; double yy, dy=pl[0].ybig - pl[0].ysml; if (depth==RECUR_MAXDEPTH) return; xx = rmiddle(xl,xr); yy = gtodouble(eval(E,xx)); if (dy && fabs(yl+yr-2*yy) < dy*RECUR_PREC) return; single_recursion(E,eval, pl,xl,yl, xx,yy, depth+1); Appendx(&pl[0],&pl[0],rtodbl(xx)); Appendy(&pl[0],&pl[1],yy); single_recursion(E,eval, pl,xx,yy, xr,yr, depth+1); set_avma(av); } static void param_recursion(void *E,GEN(*eval)(void*,GEN), long cplx, dblPointList *pl, GEN tl,double xl, double yl, GEN tr,double xr,double yr, long depth) { GEN t; pari_sp av = avma; double xx, dy=pl[0].ybig - pl[0].ysml; double yy, dx=pl[0].xbig - pl[0].xsml; if (depth==RECUR_MAXDEPTH) return; t = rmiddle(tl,tr); get_xy(cplx, eval(E,t), &xx,&yy); if (dx && dy && fabs(xl+xr-2*xx) < dx*RECUR_PREC && fabs(yl+yr-2*yy) < dy*RECUR_PREC) return; param_recursion(E,eval, cplx, pl, tl,xl,yl, t,xx,yy, depth+1); Appendx(&pl[0],&pl[0],xx); Appendy(&pl[0],&pl[1],yy); param_recursion(E,eval,cplx, pl, t,xx,yy, tr,xr,yr, depth+1); set_avma(av); } /* Graph 'code' for parameter values in [a,b], using 'N' sample points * (0 = use a default value); code is either a t_CLOSURE or a t_POL or a * t_VEC of two t_POLs from rectsplines. Returns a dblPointList of * (absolute) coordinates. */ static dblPointList * plotrecthin(void *E, GEN(*eval)(void*, GEN), GEN a, GEN b, ulong flags, long N, long prec) { const double INF = 1.0/0.0; const long param = flags & (PLOT_PARAMETRIC|PLOT_COMPLEX); const long recur = flags & PLOT_RECURSIVE; const long cplx = flags & PLOT_COMPLEX; GEN t, dx, x; dblPointList *pl; long tx, i, j, sig, nc, nl, ncoords, nbpoints, non_vec = 0; sig = gcmp(b,a); if (!sig) return NULL; if (sig < 0) swap(a, b); if (N == 1) pari_err_DOMAIN("ploth", "#points", "<", gen_2, stoi(N)); if (!N) N = recur? 8: (param? 1500: 1000); /* compute F(a) to determine nc = #curves; nl = #coord. lists */ x = gtofp(a, prec); t = eval(E, x); tx = typ(t); if (cplx) nc = nl = (tx == t_VEC)? lg(t)-1: 1; else if (param) { if (tx != t_VEC) pari_err_TYPE("ploth [not a t_VEC in parametric plot]", t); nl = lg(t)-1; nc = nl >> 1; if (odd(nl)) pari_err_TYPE("ploth [odd #components in parametric plot]",t); } else if (!is_matvec_t(tx)) { nl = 2; non_vec = 1; nc = 1; } else { if (tx != t_VEC) pari_err_TYPE("ploth [not a t_VEC]",t); nl = lg(t); nc = nl-1; } if (!nc) return NULL; if (recur && nc > 1) pari_err_TYPE("ploth [multi-curves + recursive]",t); ncoords = cplx? 2*nl: nl; nbpoints = recur? N << RECUR_MAXDEPTH: N; pl=(dblPointList*) pari_malloc(ncoords*sizeof(dblPointList)); /* set [xy]sml,[xy]big to default values */ if (param) { pl[0].xsml = INF; pl[0].xbig =-INF; } else { pl[0].xsml = gtodouble(a); pl[0].xbig = gtodouble(b); } pl[0].ysml = INF; pl[0].ybig =-INF; for (i = 0; i < ncoords; i++) { pl[i].d = (double*)pari_malloc((nbpoints+1)*sizeof(double)); pl[i].nb=0; } dx = divru(gtofp(gsub(b,a),prec), N-1); if (recur) { /* recursive plot */ double yl, yr = 0; if (param) { GEN tl = cgetr(prec), tr = cgetr(prec); double xl, xr = 0; pari_sp av2 = avma; affgr(a, tl); t = eval(E, tl); get_xy(cplx,t, &xl,&yl); for (i=0; idraw) pari_err(e_MISC,"high resolution graphics disabled"); T->draw(T, w,x,y); } static void set_range(double m, double M, double *sml, double *big) { if (M - m < 1.e-9) { double d = fabs(m)/10; if (!d) d = 0.1; M += d; m -= d; } *sml = m; *big = M; } /* Plot a dblPointList. Complete with axes, bounding box, etc. * * data is an array of structs. Its meaning depends on flags : * * + data[0] contains global extremas, the number of curves to plot * (data[0].nb) and a list of doubles (first set of x-coordinates). * * + data[i].nb (i>0) contains the number of points in the list * data[i].d (hopefully, data[2i].nb=data[2i+1].nb when i>0...) * * + If flags contain PLOT_PARAMETRIC, the array length should be * even, and successive pairs (data[2i].d, data[2i+1].d) represent * curves to plot. * * + If there is no such flag, the first element is an array with * x-coordinates and the following ones contain y-coordinates. * If W != NULL, output wrt this PARI_plot using two drawing rectangles: * one for labels, another for graphs. Else draw to rectwindow ne without * labels. * If fmt != NULL (requires W != NULL), output is a t_STR containing the * converted picture, else a bounding box */ static GEN plotrecthrawin(GEN fmt, PARI_plot *W, long ne, dblPointList *data, long flags) { const long param = flags & (PLOT_PARAMETRIC|PLOT_COMPLEX); const long max_graphcolors = lg(GP_DATA->graphcolors)-1; const pari_sp av = avma; dblPointList x, y; double xsml, xbig, ysml, ybig; long ltype, i, nc, w[3], wx[3], wy[3]; if (!data) return cgetg(1,t_VEC); x = data[0]; nc = x.nb; set_range(x.xsml, x.xbig, &xsml, &xbig); set_range(x.ysml, x.ybig, &ysml, &ybig); if (W) { /* actual output; else output to rectwindow: no labels */ char YBIG[16], YSML[16], XSML[16], XBIG[16]; long lm = W->hunit-1, rm = W->hunit-1, tm = W->vunit-1; long bm = W->vunit+W->fheight-1; /* left/right/top/bottom margin */ if (!(flags&PLOT_NOMINMAX)) { sprintf(YSML,"%.5g", ysml); sprintf(YBIG,"%.5g", ybig); sprintf(XSML,"%.5g", xsml); sprintf(XBIG,"%.5g", xbig); /* left margin has y labels with hgap on both sides of text */ lm = maxss(strlen(YSML), strlen(YBIG)) * W->fwidth + 2*W->hunit-1; } w[0] = evaltyp(t_VECSMALL) | _evallg((flags&PLOT_NOMINMAX)? 2: 3); wx[0] = wy[0] = w[0]; w[1] = ne; wx[1] = lm; wy[1] = tm; /* Window (width x height) is given in pixels, correct pixels are 0..n-1, * whereas rect functions work with windows whose pixel range is [0,n] */ initrect_i(ne, W->width - (lm+rm) - 1, W->height - (tm+bm) - 1); if (!(flags&PLOT_NOMINMAX)) { /* draw labels on se */ const long se = NUMRECT-2; w[2] = se; wx[2] = 0; wy[2] = 0; initrect_i(se, W->width - 1, W->height - 1); _move(se,lm,0); plotstring(se, YBIG, RoSTdirRIGHT|RoSTdirHGAP|RoSTdirTOP); _move(se,lm,W->height-bm); plotstring(se,YSML, RoSTdirRIGHT|RoSTdirHGAP|RoSTdirVGAP); _move(se,lm,W->height-bm); plotstring(se, XSML, RoSTdirLEFT|RoSTdirTOP); _move(se,W->width-rm-1, W->height-bm); plotstring(se, XBIG, RoSTdirRIGHT|RoSTdirTOP); } } if (!(flags & PLOT_NO_RESCALE)) plotscale0(ne, xsml, xbig, ysml, ybig); if (!(flags & PLOT_NO_FRAME)) { long fl = (flags & PLOT_NODOUBLETICK)? TICKS_CLOCKW|TICKS_NODOUBLE : TICKS_CLOCKW; PARI_plot T, *pl; if (W) pl = W; else { pl = &T; pari_get_plot(pl); } plotlinetype(ne, -2); /* frame */ current_color[ne] = colormap_to_color(DEFAULT_COLOR); _move(ne,xsml,ysml); _box(ne,xbig,ybig); if (!(flags & PLOT_NO_TICK_X)) { rectticks(pl, ne, xsml, ysml, xbig, ysml, xsml, xbig, fl); rectticks(pl, ne, xbig, ybig, xsml, ybig, xbig, xsml, fl); } if (!(flags & PLOT_NO_TICK_Y)) { rectticks(pl, ne, xbig, ysml, xbig, ybig, ysml, ybig, fl); rectticks(pl, ne, xsml, ybig, xsml, ysml, ybig, ysml, fl); } } if (!(flags & PLOT_NO_AXE_Y) && (xsml<=0 && xbig >=0)) { plotlinetype(ne, -1); /* axes */ current_color[ne] = colormap_to_color(AXIS_COLOR); _move(ne,0.0,ysml); _line(ne,0.0,ybig); } if (!(flags & PLOT_NO_AXE_X) && (ysml<=0 && ybig >=0)) { plotlinetype(ne, -1); /* axes */ current_color[ne] = colormap_to_color(AXIS_COLOR); _move(ne,xsml,0.0); _line(ne,xbig,0.0); } if (param) { i = 0; flags |= PLOT_PARAMETRIC; flags &= (~PLOT_COMPLEX); /* turn COMPLEX to PARAMETRIC*/ } else i = 1; for (ltype = 0; ltype < nc; ltype++) { long c = GP_DATA->graphcolors[1+(ltype%max_graphcolors)]; current_color[ne] = colormap_to_color(c); if (param) x = data[i++]; y = data[i++]; if (flags & (PLOT_POINTS_LINES|PLOT_POINTS)) { plotlinetype(ne, plotpoint_itype + ltype); /* Graphs */ plotpointtype(ne,plotpoint_itype + ltype); /* Graphs */ plotpoints0(ne, x.d, y.d, y.nb); 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(ne, x.d, y.d, y.nb, flags); rectline_itype = old; } else { plotlinetype(ne, rectline_itype + ltype); /* Graphs */ rectlines0(ne, x.d, y.d, y.nb, 0); } } for (i--; i>=0; i--) pari_free(data[i].d); pari_free(data); if (W) { GEN s = NULL; if (fmt) s = fmt_convert(fmt, w, wx, wy, W); else Draw(W, w,wx,wy); for (i = 1; i < lg(w); i++) plotkill(w[i]); if (fmt) return s; } set_avma(av); retmkvec4(dbltor(xsml), dbltor(xbig), dbltor(ysml), dbltor(ybig)); } /*************************************************************************/ /* */ /* HI-RES FUNCTIONS */ /* */ /*************************************************************************/ /* If T != NULL, draw using the attached graphic (using rectwindow ne as a temp) * Else write to rectwindow 'ne'. * Graph y=f(x), x=a..b, use n points */ static GEN plotrecth_i(GEN fmt, void *E, GEN(*f)(void*,GEN), PARI_plot *T, long ne, GEN a,GEN b, ulong flags,long n, long prec) { pari_sp av = avma; dblPointList *pl = plotrecthin(E,f, a,b, flags, n, prec); set_avma(av); return plotrecthrawin(fmt, T, ne, pl, flags); } GEN plotrecth(void *E, GEN(*f)(void*,GEN), long ne, GEN a,GEN b, ulong flags, long n, long prec) { return plotrecth_i(NULL, E,f, NULL, ne, a,b, flags&~PLOT_PARA, n, prec); } GEN plotrecth0(long ne, GEN a,GEN b,GEN code,ulong flags,long n, long prec) { EXPR_WRAP(code, plotrecth(EXPR_ARG, ne, a,b, flags, n, prec)); } static GEN _ploth(void *E, GEN(*f)(void*,GEN), GEN a, GEN b,long flags, long n, long prec) { PARI_plot T; pari_get_plot(&T); return plotrecth_i(NULL, E,f, &T, NUMRECT-1, a,b, flags,n, prec); } GEN ploth(void *E, GEN(*f)(void*,GEN), GEN a, GEN b,long flags, long n, long prec) { return _ploth(E, f, a, b, flags&~PLOT_PARA, n, prec); } GEN parploth(GEN a, GEN b, GEN code, long flags, long n, long prec) { return _ploth(code, gp_call, a, b, flags|PLOT_PARA, n, prec); } GEN ploth0(GEN a, GEN b, GEN code, long flags,long n, long prec) { EXPR_WRAP(code, ploth(EXPR_ARG, a,b,flags,n, prec)); } GEN psploth(void *E, GEN(*f)(void*,GEN), GEN a,GEN b, long flags, long n, long prec) { PARI_plot T; pari_get_psplot(&T); T.draw = &_psdraw; return plotrecth_i(NULL, E,f, &T, NUMRECT-1, a,b, flags&~PLOT_PARA,n, prec); } GEN psploth0(GEN a, GEN b, GEN code, long flags, long n, long prec) { EXPR_WRAP(code, psploth(EXPR_ARG, a, b, flags, n, prec)); } static GEN _plothexport(GEN fmt, void *E, GEN(*f)(void*,GEN), GEN a,GEN b, long flags, long n, long prec) { pari_sp av = avma; GEN s; PARI_plot T; pari_get_fmtplot(fmt, &T); s = plotrecth_i(fmt, E,f, &T, NUMRECT-1, a,b, flags,n, prec); return gerepileuptoleaf(av, s); } GEN plothexport(GEN fmt, void *E, GEN(*f)(void*,GEN), GEN a,GEN b, long flags, long n, long prec) { return _plothexport(fmt, E, f, a, b, flags&~PLOT_PARA, n, prec); } GEN plothexport0(GEN fmt, GEN a, GEN b, GEN code, long flags, long n, long prec) { EXPR_WRAP(code, plothexport(fmt, EXPR_ARG, a, b, flags, n, prec)); } GEN parplothexport(GEN fmt, GEN a, GEN b, GEN code, long flags, long n, long prec) { return _plothexport(fmt, code, gp_call, a, b, flags|PLOT_PARA, n, prec); } /* Draw list of points */ static GEN plotrecthraw_i(GEN fmt, PARI_plot *T, long ne, GEN data, long flags) { dblPointList *pl = gtodblList(data,flags); return plotrecthrawin(fmt, T, ne, pl, flags); } static GEN plothraw_i(GEN fmt, PARI_plot *T, GEN X, GEN Y, long flag) { pari_sp av = avma; switch (flag) { case 0: flag = PLOT_PARAMETRIC|PLOT_POINTS; break; case 1: flag = PLOT_PARAMETRIC; break; default: flag |= PLOT_PARAMETRIC; break; } return gerepileupto(av, plotrecthraw_i(fmt, T, NUMRECT-1, mkvec2(X,Y), flag)); } GEN plothraw(GEN X, GEN Y, long flags) { PARI_plot T; pari_get_plot(&T); return plothraw_i(NULL,&T,X,Y,flags); } GEN psplothraw(GEN X, GEN Y, long flags) { PARI_plot T; pari_get_psplot(&T); T.draw = &_psdraw; return plothraw_i(NULL,&T,X,Y,flags); } GEN plotrecthraw(long ne, GEN data, long flags) { return plotrecthraw_i(NULL, NULL, ne, data, flags); } GEN plothrawexport(GEN fmt, GEN X, GEN Y, long flags) { PARI_plot T; pari_get_fmtplot(fmt,&T); return plothraw_i(fmt,&T,X,Y,flags); } GEN plothsizes(long flag) { GEN vect = cgetg(1+8,t_VEC); PARI_plot T; pari_get_plot(&T); gel(vect,1) = stoi(T.width); gel(vect,2) = stoi(T.height); if (flag) { gel(vect,3) = dbltor(T.hunit*1.0/T.width); gel(vect,4) = dbltor(T.vunit*1.0/T.height); gel(vect,5) = dbltor(T.fwidth*1.0/T.width); gel(vect,6) = dbltor(T.fheight*1.0/T.height); } else { gel(vect,3) = stoi(T.hunit); gel(vect,4) = stoi(T.vunit); gel(vect,5) = stoi(T.fwidth); gel(vect,6) = stoi(T.fheight); } gel(vect,7) = stoi(T.dwidth); gel(vect,8) = stoi(T.dheight); return vect; } /*************************************************************************/ /* */ /* POSTSCRIPT OUTPUT */ /* */ /*************************************************************************/ static long wxy_n(GEN wxy) { long n; switch(typ(wxy)) { case t_INT: return 1; case t_VEC: n = lg(wxy)-1; if (n%3) pari_err_DIM("plotdraw"); return n/3; } pari_err_TYPE("plotdraw",wxy); return 0;/*LCOV_EXCL_LINE*/ } static void wxy_init(GEN wxy, GEN *pW, GEN *pX, GEN *pY, PARI_plot *T) { long i, n = wxy_n(wxy); GEN W, X, Y; *pW = W = cgetg(n+1, t_VECSMALL); /* win number */ *pX = X = cgetg(n+1, t_VECSMALL); *pY = Y = cgetg(n+1, t_VECSMALL); /* (x,y)-offset */ if (typ(wxy) == t_INT) { W[1] = itos(wxy); check_rect_init(W[1]); X[1] = 0; Y[1] = 0; return; } for (i = 1; i <= n; i++) { GEN w = gel(wxy,3*i-2), x = gel(wxy,3*i-1), y = gel(wxy,3*i); if (typ(w) != t_INT) pari_err_TYPE("plotdraw",w); W[i] = itos(w); check_rect_init(W[i]); if (T) { X[i] = DTOL(gtodouble(x)*(T->width - 1)); Y[i] = DTOL(gtodouble(y)*(T->height - 1)); } else { X[i] = gtos(x); Y[i] = gtos(y); } } } /* if flag is set, rescale wrt T */ static void gendraw(PARI_plot *T, GEN wxy, long flag) { GEN w, x, y, W, X, Y; long i, l; wxy_init(wxy, &w,&x,&y, flag? T: NULL); l = lg(w); /* malloc mandatory in case draw() forks then pari_close(). Done after * wxy_init to avoid leak on error */ W = cgetalloc(l, t_VECSMALL); X = cgetalloc(l, t_VECSMALL); Y = cgetalloc(l, t_VECSMALL); for (i = 1; i < l; i++) { W[i] = w[i]; X[i] = x[i]; Y[i] = y[i]; } Draw(T,W,X,Y); pari_free(W); pari_free(X); pari_free(Y); } void psdraw(GEN wxy, long flag) { PARI_plot T; pari_get_psplot(&T); T.draw = flag? &_psdraw: &_psdraw_scale; gendraw(&T, wxy, flag); } void plotdraw(GEN wxy, long flag) { PARI_plot T; pari_get_plot(&T); gendraw(&T, wxy, flag); } GEN plotexport(GEN fmt, GEN wxy, long flag) { pari_sp av = avma; GEN w, x, y; PARI_plot _T, *T = flag? &_T: NULL; if (T) pari_get_plot(T); wxy_init(wxy, &w, &x, &y, T); return gerepileuptoleaf(av, fmt_convert(fmt, w, x, y, T)); } /* may be called after pari_close(): don't use the PARI stack */ void gen_draw(struct plot_eng *eng, GEN w, GEN x, GEN y, double xs, double ys) { void *data = eng->data; long i, j, lw = lg(w); long hgapsize = eng->pl->hunit, fheight = eng->pl->fheight; long vgapsize = eng->pl->vunit, fwidth = eng->pl->fwidth; for(i = 1; i < lw; i++) { PariRect *e = &rectgraph[w[i]]; RectObj *R; long x0 = x[i], y0 = y[i]; for (R = RHead(e); R; R = RoNext(R)) { long col = RoCol(R); switch(RoType(R)) { case ROt_PT: eng->sc(data,col); eng->pt(data, DTOL((RoPTx(R)+x0)*xs), DTOL((RoPTy(R)+y0)*ys)); break; case ROt_LN: eng->sc(data,col); 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_AC: eng->sc(data,col); eng->ac(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_FAC: eng->sc(data,col); eng->fa(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_BX: eng->sc(data,col); 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_FBX: eng->sc(data,col); eng->fb(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,col); 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,col); eng->ml(data, nb, points); pari_free(points); break; } case ROt_ST: { long dir = RoSTdir(R); long h = dir & RoSTdirHPOS_mask, hgap = 0; long v = dir & RoSTdirVPOS_mask, vgap = 0; long x, y, l = RoSTl(R); long shift = (h == RoSTdirLEFT ? 0 : (h == RoSTdirRIGHT? 2: 1)); long vshift= (v == RoSTdirBOTTOM? 0: (v == RoSTdirTOP? 2: 1)); if (dir & RoSTdirHGAP) hgap = (h == RoSTdirLEFT) ? hgapsize : -hgapsize; if (dir & RoSTdirVGAP) vgap = (v == RoSTdirBOTTOM) ? 2*vgapsize : -2*vgapsize; x = DTOL(xs * (RoSTx(R) + x0 + hgap - (l * fwidth * shift)/2)); y = DTOL(ys * (RoSTy(R) + y0 - (vgap - vshift*(fheight-1))/2)); eng->sc(data,col); eng->st(data, x, y, RoSTs(R), l); break; } default: break; } } } } /*************************************************************************/ /* SVG */ /*************************************************************************/ struct svg_data { pari_str str; char hexcolor[8]; /* "#rrggbb\0" */ }; #define data_str(d) (&((struct svg_data*)(d))->str) #define data_hexcolor(d) (((struct svg_data*)(d))->hexcolor) /* Work with precision 1/scale */ static const float SVG_SCALE = 1024.0; static float svg_rescale(float x) { return x / SVG_SCALE; } static void svg_point(void *data, long x, long y) { pari_str *S = data_str(data); str_printf(S, "", data_hexcolor(data)); } static void svg_line(void *data, long x1, long y1, long x2, long y2) { pari_str *S = data_str(data); str_printf(S, "", data_hexcolor(data)); } static void svg_ell(void *data, long x, long y, long w, long h) { pari_str *S = data_str(data); float sx = svg_rescale(x), sy = svg_rescale(y), sw = svg_rescale(w), sh = svg_rescale(h); str_printf(S, "", data_hexcolor(data)); } static void svg_fillell(void *data, long x, long y, long w, long h) { pari_str *S = data_str(data); const char * color = data_hexcolor(data); float sx = svg_rescale(x), sy = svg_rescale(y), sw = svg_rescale(w), sh = svg_rescale(h); str_printf(S, "", color, color); } static void svg_rect(void *data, long x, long y, long w, long h) { pari_str *S = data_str(data); str_printf(S, "", data_hexcolor(data)); } static void svg_fillrect(void *data, long x, long y, long w, long h) { pari_str *S = data_str(data); const char * color = data_hexcolor(data); str_printf(S, "", color, color); } static void svg_points(void *data, long nb, struct plot_points *p) { long i; for (i = 0; i < nb; i++) svg_point(data, p[i].x, p[i].y); } static void svg_color(void *data, long col) { static const char hex[] = "0123456789abcdef"; char *c = data_hexcolor(data); int r, g, b; long_to_rgb(col, &r, &g, &b); c[0] = '#'; c[1] = hex[r / 16]; c[2] = hex[r & 15]; c[3] = hex[g / 16]; c[4] = hex[g & 15]; c[5] = hex[b / 16]; c[6] = hex[b & 15]; c[7] = '\0'; } static void svg_lines(void *data, long nb, struct plot_points *p) { long i; pari_str *S = data_str(data); str_printf(S, "", data_hexcolor(data)); } static void svg_text(void *data, long x, long y, char *text, long numtext) { pari_str *S = data_str(data); (void)numtext; str_printf(S, "%s", svg_rescale(x),svg_rescale(y), 12, data_hexcolor(data), text); } static void svg_head(PARI_plot *T, pari_str *S) { str_printf(S, "", T->width, T->height); } static void svg_tail(pari_str *S) { str_printf(S, ""); } char * rect2svg(GEN w, GEN x, GEN y, PARI_plot *T) { struct plot_eng pl; struct svg_data data; PARI_plot U; str_init(&data.str, 1); svg_color(&data, 0); if (!T) { long i, l = lg(w), xmax = 0, ymax = 0; T = &U; pari_get_svgplot(T); for (i = 1; i < l; i++) { PariRect *e = check_rect_init(w[i]); xmax = maxss(xmax, RXsize(e) + x[i]); ymax = maxss(ymax, RYsize(e) + y[i]); } T->width = xmax; T->height = ymax; } pl.data = &data; pl.sc = &svg_color; pl.pt = &svg_point; pl.ln = &svg_line; pl.ac = &svg_ell; pl.fa = &svg_fillell; pl.bx = &svg_rect; pl.fb = &svg_fillrect; pl.mp = &svg_points; pl.ml = &svg_lines; pl.st = &svg_text; pl.pl = T; svg_head(T, &data.str); gen_draw(&pl, w, x, y, SVG_SCALE, SVG_SCALE); svg_tail(&data.str); return data.str.string; } /*************************************************************************/ /* POSTSCRIPT */ /*************************************************************************/ static void ps_sc(void *data, long col) { pari_str *S = (pari_str*)data; int r, g, b; long_to_rgb(col, &r, &g, &b); if (!r && !g && !b) str_puts(S,"c0\n"); else str_printf(S,"%.6f %.6f %.6f c\n", r/255., g/255., b/255.); } static void ps_point(void *data, long x, long y) { pari_str *S = (pari_str*)data; str_printf(S,"%ld %ld p\n",y,x); } static void ps_line(void *data, long x1, long y1, long x2, long y2) { pari_str *S = (pari_str*)data; str_printf(S,"%ld %ld m %ld %ld l\n",y1,x1,y2,x2); str_printf(S,"stroke\n"); } static void ps_arc(void *data, long x, long y, long w, long h) { pari_str *S = (pari_str*)data; str_printf(S,"matrix currentmatrix %ld %ld translate %ld %ld scale 1 0 moveto 0 0 1 0 360 arc closepath setmatrix currentlinejoin 0 setlinejoin stroke setlinejoin\n", y+h/2,x+w/2,h/2,w/2); } static void ps_fillarc(void *data, long x, long y, long w, long h) { pari_str *S = (pari_str*)data; str_printf(S,"matrix currentmatrix %ld %ld translate %ld %ld scale 1 0 moveto 0 0 1 0 360 arc closepath setmatrix currentlinejoin 0 setlinejoin fill setlinejoin\n", y+h/2,x+w/2,h/2,w/2); } static void ps_rect(void *data, long x, long y, long w, long h) { pari_str *S = (pari_str*)data; str_printf(S,"%ld %ld m %ld %ld l %ld %ld l %ld %ld l closepath currentlinejoin 0 setlinejoin stroke setlinejoin\n", y,x, y,x+w, y+h,x+w, y+h,x); } static void ps_fillrect(void *data, long x, long y, long w, long h) { pari_str *S = (pari_str*)data; str_printf(S,"%ld %ld m %ld %ld l %ld %ld l %ld %ld l closepath currentlinejoin 0 setlinejoin fill setlinejoin\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; iwidth; ys *= ((double)PS_HEIGH) / T->height; } } else { T = &U; pari_get_psplot(T); } str_init(&S, 1); /* Definitions taken from post terminal of Gnuplot. */ str_printf(&S, "%%!\n\ 50 50 translate\n\ 1 %d div 1 %d div scale\n\ 1 setlinejoin\n\ /p {moveto 0 2 rlineto 2 0 rlineto 0 -2 rlineto closepath fill} def\n\ /c0 {0 0 0 setrgbcolor} def\n\ /c {setrgbcolor} def\n\ /l {lineto} def\n\ /m {moveto} def\n" "/Times-Roman findfont %ld scalefont setfont\n", PS_SCALE, PS_SCALE, DTOL(T->fheight * xs)); pl.sc = &ps_sc; pl.pt = &ps_point; pl.ln = &ps_line; pl.ac = &ps_arc; pl.fa = &ps_fillarc; pl.bx = &ps_rect; pl.fb = &ps_fillrect; pl.mp = &ps_points; pl.ml = &ps_lines; pl.st = &ps_string; pl.pl = T; pl.data = (void*)&S; if (plotps) str_printf(&S,"0 %ld translate -90 rotate\n", (T->height - 50)*PS_SCALE); gen_draw(&pl, w, x, y, xs, ys); str_puts(&S,"stroke showpage\n"); *S.cur = 0; return S.string; } char * rect2ps(GEN w, GEN x, GEN y, PARI_plot *T) { return rect2ps_i(w,x,y,T,0); } void pari_plot_by_file(const char *env, const char *suf, const char *img) { const char *cmd, *s = pari_unique_filename_suffix("plotfile", suf); FILE *f = fopen(s, "w"); pari_timer ti; if (!f) pari_err_FILE("image file", s); fputs(img, f); (void)fclose(f); cmd = os_getenv(env); #ifdef GP_MIME_OPEN if (!cmd) cmd = GP_MIME_OPEN; #else if (!cmd) cmd = "open -W"; #endif cmd = pari_sprintf("%s \"%s\" 2>/dev/null", cmd, s); walltimer_start(&ti); gpsystem(cmd); /* Some image viewers will return immediately and will not display files that have been deleted. In that case we have to leak the file. */ if (walltimer_delay(&ti)>1000) pari_unlink(s); pari_free((char*)s); } /*************************************************************************/ /* */ /* RGB COLORS */ /* */ /*************************************************************************/ /* generated from /etc/X11/rgb.txt by the following perl script #!/usr/bin/perl while(<>) { ($hex, $name) = split(/\t\t/, $_); $hex =~ s/^ +//; chomp($name); $name =~ s, *,,g; $hex = sprintf("0x%02x%02x%02x", split(/\s+/, $hex)); $name = lc($name); next if ($done{$name}); $done{$name} = 1; print "COL(\"$name\", $hex),\n"; } */ #define COL(x,y) {(void*)x,(void*)y,0,NULL} static hashentry col_list[] = { COL("", 0x000000), COL("snow", 0xfffafa), COL("ghostwhite", 0xf8f8ff), COL("whitesmoke", 0xf5f5f5), COL("gainsboro", 0xdcdcdc), COL("floralwhite", 0xfffaf0), COL("oldlace", 0xfdf5e6), COL("linen", 0xfaf0e6), COL("antiquewhite", 0xfaebd7), COL("papayawhip", 0xffefd5), COL("blanchedalmond", 0xffebcd), COL("bisque", 0xffe4c4), COL("peachpuff", 0xffdab9), COL("navajowhite", 0xffdead), COL("moccasin", 0xffe4b5), COL("cornsilk", 0xfff8dc), COL("ivory", 0xfffff0), COL("lemonchiffon", 0xfffacd), COL("seashell", 0xfff5ee), COL("honeydew", 0xf0fff0), COL("mintcream", 0xf5fffa), COL("azure", 0xf0ffff), COL("aliceblue", 0xf0f8ff), COL("lavender", 0xe6e6fa), COL("lavenderblush", 0xfff0f5), COL("mistyrose", 0xffe4e1), COL("white", 0xffffff), COL("black", 0x000000), COL("darkslategray", 0x2f4f4f), COL("darkslategrey", 0x2f4f4f), COL("dimgray", 0x696969), COL("dimgrey", 0x696969), COL("slategray", 0x708090), COL("slategrey", 0x708090), COL("lightslategray", 0x778899), COL("lightslategrey", 0x778899), COL("gray", 0xbebebe), COL("grey", 0xbebebe), COL("lightgrey", 0xd3d3d3), COL("lightgray", 0xd3d3d3), COL("midnightblue", 0x191970), COL("navy", 0x000080), COL("navyblue", 0x000080), COL("cornflowerblue", 0x6495ed), COL("darkslateblue", 0x483d8b), COL("slateblue", 0x6a5acd), COL("mediumslateblue", 0x7b68ee), COL("lightslateblue", 0x8470ff), COL("mediumblue", 0x0000cd), COL("royalblue", 0x4169e1), COL("blue", 0x0000ff), COL("dodgerblue", 0x1e90ff), COL("deepskyblue", 0x00bfff), COL("skyblue", 0x87ceeb), COL("lightskyblue", 0x87cefa), COL("steelblue", 0x4682b4), COL("lightsteelblue", 0xb0c4de), COL("lightblue", 0xadd8e6), COL("powderblue", 0xb0e0e6), COL("paleturquoise", 0xafeeee), COL("darkturquoise", 0x00ced1), COL("mediumturquoise", 0x48d1cc), COL("turquoise", 0x40e0d0), COL("cyan", 0x00ffff), COL("lightcyan", 0xe0ffff), COL("cadetblue", 0x5f9ea0), COL("mediumaquamarine", 0x66cdaa), COL("aquamarine", 0x7fffd4), COL("darkgreen", 0x006400), COL("darkolivegreen", 0x556b2f), COL("darkseagreen", 0x8fbc8f), COL("seagreen", 0x2e8b57), COL("mediumseagreen", 0x3cb371), COL("lightseagreen", 0x20b2aa), COL("palegreen", 0x98fb98), COL("springgreen", 0x00ff7f), COL("lawngreen", 0x7cfc00), COL("green", 0x00ff00), COL("chartreuse", 0x7fff00), COL("mediumspringgreen", 0x00fa9a), COL("greenyellow", 0xadff2f), COL("limegreen", 0x32cd32), COL("yellowgreen", 0x9acd32), COL("forestgreen", 0x228b22), COL("olivedrab", 0x6b8e23), COL("darkkhaki", 0xbdb76b), COL("khaki", 0xf0e68c), COL("palegoldenrod", 0xeee8aa), COL("lightgoldenrodyellow", 0xfafad2), COL("lightyellow", 0xffffe0), COL("yellow", 0xffff00), COL("gold", 0xffd700), COL("lightgoldenrod", 0xeedd82), COL("goldenrod", 0xdaa520), COL("darkgoldenrod", 0xb8860b), COL("rosybrown", 0xbc8f8f), COL("indianred", 0xcd5c5c), COL("saddlebrown", 0x8b4513), COL("sienna", 0xa0522d), COL("peru", 0xcd853f), COL("burlywood", 0xdeb887), COL("beige", 0xf5f5dc), COL("wheat", 0xf5deb3), COL("sandybrown", 0xf4a460), COL("tan", 0xd2b48c), COL("chocolate", 0xd2691e), COL("firebrick", 0xb22222), COL("brown", 0xa52a2a), COL("darksalmon", 0xe9967a), COL("salmon", 0xfa8072), COL("lightsalmon", 0xffa07a), COL("orange", 0xffa500), COL("darkorange", 0xff8c00), COL("coral", 0xff7f50), COL("lightcoral", 0xf08080), COL("tomato", 0xff6347), COL("orangered", 0xff4500), COL("red", 0xff0000), COL("hotpink", 0xff69b4), COL("deeppink", 0xff1493), COL("pink", 0xffc0cb), COL("lightpink", 0xffb6c1), COL("palevioletred", 0xdb7093), COL("maroon", 0xb03060), COL("mediumvioletred", 0xc71585), COL("violetred", 0xd02090), COL("magenta", 0xff00ff), COL("violet", 0xee82ee), COL("plum", 0xdda0dd), COL("orchid", 0xda70d6), COL("mediumorchid", 0xba55d3), COL("darkorchid", 0x9932cc), COL("darkviolet", 0x9400d3), COL("blueviolet", 0x8a2be2), COL("purple", 0xa020f0), COL("mediumpurple", 0x9370db), COL("thistle", 0xd8bfd8), COL("snow1", 0xfffafa), COL("snow2", 0xeee9e9), COL("snow3", 0xcdc9c9), COL("snow4", 0x8b8989), COL("seashell1", 0xfff5ee), COL("seashell2", 0xeee5de), COL("seashell3", 0xcdc5bf), COL("seashell4", 0x8b8682), COL("antiquewhite1", 0xffefdb), COL("antiquewhite2", 0xeedfcc), COL("antiquewhite3", 0xcdc0b0), COL("antiquewhite4", 0x8b8378), COL("bisque1", 0xffe4c4), COL("bisque2", 0xeed5b7), COL("bisque3", 0xcdb79e), COL("bisque4", 0x8b7d6b), COL("peachpuff1", 0xffdab9), COL("peachpuff2", 0xeecbad), COL("peachpuff3", 0xcdaf95), COL("peachpuff4", 0x8b7765), COL("navajowhite1", 0xffdead), COL("navajowhite2", 0xeecfa1), COL("navajowhite3", 0xcdb38b), COL("navajowhite4", 0x8b795e), COL("lemonchiffon1", 0xfffacd), COL("lemonchiffon2", 0xeee9bf), COL("lemonchiffon3", 0xcdc9a5), COL("lemonchiffon4", 0x8b8970), COL("cornsilk1", 0xfff8dc), COL("cornsilk2", 0xeee8cd), COL("cornsilk3", 0xcdc8b1), COL("cornsilk4", 0x8b8878), COL("ivory1", 0xfffff0), COL("ivory2", 0xeeeee0), COL("ivory3", 0xcdcdc1), COL("ivory4", 0x8b8b83), COL("honeydew1", 0xf0fff0), COL("honeydew2", 0xe0eee0), COL("honeydew3", 0xc1cdc1), COL("honeydew4", 0x838b83), COL("lavenderblush1", 0xfff0f5), COL("lavenderblush2", 0xeee0e5), COL("lavenderblush3", 0xcdc1c5), COL("lavenderblush4", 0x8b8386), COL("mistyrose1", 0xffe4e1), COL("mistyrose2", 0xeed5d2), COL("mistyrose3", 0xcdb7b5), COL("mistyrose4", 0x8b7d7b), COL("azure1", 0xf0ffff), COL("azure2", 0xe0eeee), COL("azure3", 0xc1cdcd), COL("azure4", 0x838b8b), COL("slateblue1", 0x836fff), COL("slateblue2", 0x7a67ee), COL("slateblue3", 0x6959cd), COL("slateblue4", 0x473c8b), COL("royalblue1", 0x4876ff), COL("royalblue2", 0x436eee), COL("royalblue3", 0x3a5fcd), COL("royalblue4", 0x27408b), COL("blue1", 0x0000ff), COL("blue2", 0x0000ee), COL("blue3", 0x0000cd), COL("blue4", 0x00008b), COL("dodgerblue1", 0x1e90ff), COL("dodgerblue2", 0x1c86ee), COL("dodgerblue3", 0x1874cd), COL("dodgerblue4", 0x104e8b), COL("steelblue1", 0x63b8ff), COL("steelblue2", 0x5cacee), COL("steelblue3", 0x4f94cd), COL("steelblue4", 0x36648b), COL("deepskyblue1", 0x00bfff), COL("deepskyblue2", 0x00b2ee), COL("deepskyblue3", 0x009acd), COL("deepskyblue4", 0x00688b), COL("skyblue1", 0x87ceff), COL("skyblue2", 0x7ec0ee), COL("skyblue3", 0x6ca6cd), COL("skyblue4", 0x4a708b), COL("lightskyblue1", 0xb0e2ff), COL("lightskyblue2", 0xa4d3ee), COL("lightskyblue3", 0x8db6cd), COL("lightskyblue4", 0x607b8b), COL("slategray1", 0xc6e2ff), COL("slategray2", 0xb9d3ee), COL("slategray3", 0x9fb6cd), COL("slategray4", 0x6c7b8b), COL("lightsteelblue1", 0xcae1ff), COL("lightsteelblue2", 0xbcd2ee), COL("lightsteelblue3", 0xa2b5cd), COL("lightsteelblue4", 0x6e7b8b), COL("lightblue1", 0xbfefff), COL("lightblue2", 0xb2dfee), COL("lightblue3", 0x9ac0cd), COL("lightblue4", 0x68838b), COL("lightcyan1", 0xe0ffff), COL("lightcyan2", 0xd1eeee), COL("lightcyan3", 0xb4cdcd), COL("lightcyan4", 0x7a8b8b), COL("paleturquoise1", 0xbbffff), COL("paleturquoise2", 0xaeeeee), COL("paleturquoise3", 0x96cdcd), COL("paleturquoise4", 0x668b8b), COL("cadetblue1", 0x98f5ff), COL("cadetblue2", 0x8ee5ee), COL("cadetblue3", 0x7ac5cd), COL("cadetblue4", 0x53868b), COL("turquoise1", 0x00f5ff), COL("turquoise2", 0x00e5ee), COL("turquoise3", 0x00c5cd), COL("turquoise4", 0x00868b), COL("cyan1", 0x00ffff), COL("cyan2", 0x00eeee), COL("cyan3", 0x00cdcd), COL("cyan4", 0x008b8b), COL("darkslategray1", 0x97ffff), COL("darkslategray2", 0x8deeee), COL("darkslategray3", 0x79cdcd), COL("darkslategray4", 0x528b8b), COL("aquamarine1", 0x7fffd4), COL("aquamarine2", 0x76eec6), COL("aquamarine3", 0x66cdaa), COL("aquamarine4", 0x458b74), COL("darkseagreen1", 0xc1ffc1), COL("darkseagreen2", 0xb4eeb4), COL("darkseagreen3", 0x9bcd9b), COL("darkseagreen4", 0x698b69), COL("seagreen1", 0x54ff9f), COL("seagreen2", 0x4eee94), COL("seagreen3", 0x43cd80), COL("seagreen4", 0x2e8b57), COL("palegreen1", 0x9aff9a), COL("palegreen2", 0x90ee90), COL("palegreen3", 0x7ccd7c), COL("palegreen4", 0x548b54), COL("springgreen1", 0x00ff7f), COL("springgreen2", 0x00ee76), COL("springgreen3", 0x00cd66), COL("springgreen4", 0x008b45), COL("green1", 0x00ff00), COL("green2", 0x00ee00), COL("green3", 0x00cd00), COL("green4", 0x008b00), COL("chartreuse1", 0x7fff00), COL("chartreuse2", 0x76ee00), COL("chartreuse3", 0x66cd00), COL("chartreuse4", 0x458b00), COL("olivedrab1", 0xc0ff3e), COL("olivedrab2", 0xb3ee3a), COL("olivedrab3", 0x9acd32), COL("olivedrab4", 0x698b22), COL("darkolivegreen1", 0xcaff70), COL("darkolivegreen2", 0xbcee68), COL("darkolivegreen3", 0xa2cd5a), COL("darkolivegreen4", 0x6e8b3d), COL("khaki1", 0xfff68f), COL("khaki2", 0xeee685), COL("khaki3", 0xcdc673), COL("khaki4", 0x8b864e), COL("lightgoldenrod1", 0xffec8b), COL("lightgoldenrod2", 0xeedc82), COL("lightgoldenrod3", 0xcdbe70), COL("lightgoldenrod4", 0x8b814c), COL("lightyellow1", 0xffffe0), COL("lightyellow2", 0xeeeed1), COL("lightyellow3", 0xcdcdb4), COL("lightyellow4", 0x8b8b7a), COL("yellow1", 0xffff00), COL("yellow2", 0xeeee00), COL("yellow3", 0xcdcd00), COL("yellow4", 0x8b8b00), COL("gold1", 0xffd700), COL("gold2", 0xeec900), COL("gold3", 0xcdad00), COL("gold4", 0x8b7500), COL("goldenrod1", 0xffc125), COL("goldenrod2", 0xeeb422), COL("goldenrod3", 0xcd9b1d), COL("goldenrod4", 0x8b6914), COL("darkgoldenrod1", 0xffb90f), COL("darkgoldenrod2", 0xeead0e), COL("darkgoldenrod3", 0xcd950c), COL("darkgoldenrod4", 0x8b6508), COL("rosybrown1", 0xffc1c1), COL("rosybrown2", 0xeeb4b4), COL("rosybrown3", 0xcd9b9b), COL("rosybrown4", 0x8b6969), COL("indianred1", 0xff6a6a), COL("indianred2", 0xee6363), COL("indianred3", 0xcd5555), COL("indianred4", 0x8b3a3a), COL("sienna1", 0xff8247), COL("sienna2", 0xee7942), COL("sienna3", 0xcd6839), COL("sienna4", 0x8b4726), COL("burlywood1", 0xffd39b), COL("burlywood2", 0xeec591), COL("burlywood3", 0xcdaa7d), COL("burlywood4", 0x8b7355), COL("wheat1", 0xffe7ba), COL("wheat2", 0xeed8ae), COL("wheat3", 0xcdba96), COL("wheat4", 0x8b7e66), COL("tan1", 0xffa54f), COL("tan2", 0xee9a49), COL("tan3", 0xcd853f), COL("tan4", 0x8b5a2b), COL("chocolate1", 0xff7f24), COL("chocolate2", 0xee7621), COL("chocolate3", 0xcd661d), COL("chocolate4", 0x8b4513), COL("firebrick1", 0xff3030), COL("firebrick2", 0xee2c2c), COL("firebrick3", 0xcd2626), COL("firebrick4", 0x8b1a1a), COL("brown1", 0xff4040), COL("brown2", 0xee3b3b), COL("brown3", 0xcd3333), COL("brown4", 0x8b2323), COL("salmon1", 0xff8c69), COL("salmon2", 0xee8262), COL("salmon3", 0xcd7054), COL("salmon4", 0x8b4c39), COL("lightsalmon1", 0xffa07a), COL("lightsalmon2", 0xee9572), COL("lightsalmon3", 0xcd8162), COL("lightsalmon4", 0x8b5742), COL("orange1", 0xffa500), COL("orange2", 0xee9a00), COL("orange3", 0xcd8500), COL("orange4", 0x8b5a00), COL("darkorange1", 0xff7f00), COL("darkorange2", 0xee7600), COL("darkorange3", 0xcd6600), COL("darkorange4", 0x8b4500), COL("coral1", 0xff7256), COL("coral2", 0xee6a50), COL("coral3", 0xcd5b45), COL("coral4", 0x8b3e2f), COL("tomato1", 0xff6347), COL("tomato2", 0xee5c42), COL("tomato3", 0xcd4f39), COL("tomato4", 0x8b3626), COL("orangered1", 0xff4500), COL("orangered2", 0xee4000), COL("orangered3", 0xcd3700), COL("orangered4", 0x8b2500), COL("red1", 0xff0000), COL("red2", 0xee0000), COL("red3", 0xcd0000), COL("red4", 0x8b0000), COL("debianred", 0xd70751), COL("deeppink1", 0xff1493), COL("deeppink2", 0xee1289), COL("deeppink3", 0xcd1076), COL("deeppink4", 0x8b0a50), COL("hotpink1", 0xff6eb4), COL("hotpink2", 0xee6aa7), COL("hotpink3", 0xcd6090), COL("hotpink4", 0x8b3a62), COL("pink1", 0xffb5c5), COL("pink2", 0xeea9b8), COL("pink3", 0xcd919e), COL("pink4", 0x8b636c), COL("lightpink1", 0xffaeb9), COL("lightpink2", 0xeea2ad), COL("lightpink3", 0xcd8c95), COL("lightpink4", 0x8b5f65), COL("palevioletred1", 0xff82ab), COL("palevioletred2", 0xee799f), COL("palevioletred3", 0xcd6889), COL("palevioletred4", 0x8b475d), COL("maroon1", 0xff34b3), COL("maroon2", 0xee30a7), COL("maroon3", 0xcd2990), COL("maroon4", 0x8b1c62), COL("violetred1", 0xff3e96), COL("violetred2", 0xee3a8c), COL("violetred3", 0xcd3278), COL("violetred4", 0x8b2252), COL("magenta1", 0xff00ff), COL("magenta2", 0xee00ee), COL("magenta3", 0xcd00cd), COL("magenta4", 0x8b008b), COL("orchid1", 0xff83fa), COL("orchid2", 0xee7ae9), COL("orchid3", 0xcd69c9), COL("orchid4", 0x8b4789), COL("plum1", 0xffbbff), COL("plum2", 0xeeaeee), COL("plum3", 0xcd96cd), COL("plum4", 0x8b668b), COL("mediumorchid1", 0xe066ff), COL("mediumorchid2", 0xd15fee), COL("mediumorchid3", 0xb452cd), COL("mediumorchid4", 0x7a378b), COL("darkorchid1", 0xbf3eff), COL("darkorchid2", 0xb23aee), COL("darkorchid3", 0x9a32cd), COL("darkorchid4", 0x68228b), COL("purple1", 0x9b30ff), COL("purple2", 0x912cee), COL("purple3", 0x7d26cd), COL("purple4", 0x551a8b), COL("mediumpurple1", 0xab82ff), COL("mediumpurple2", 0x9f79ee), COL("mediumpurple3", 0x8968cd), COL("mediumpurple4", 0x5d478b), COL("thistle1", 0xffe1ff), COL("thistle2", 0xeed2ee), COL("thistle3", 0xcdb5cd), COL("thistle4", 0x8b7b8b), COL("gray0", 0x000000), COL("grey0", 0x000000), COL("gray1", 0x030303), COL("grey1", 0x030303), COL("gray2", 0x050505), COL("grey2", 0x050505), COL("gray3", 0x080808), COL("grey3", 0x080808), COL("gray4", 0x0a0a0a), COL("grey4", 0x0a0a0a), COL("gray5", 0x0d0d0d), COL("grey5", 0x0d0d0d), COL("gray6", 0x0f0f0f), COL("grey6", 0x0f0f0f), COL("gray7", 0x121212), COL("grey7", 0x121212), COL("gray8", 0x141414), COL("grey8", 0x141414), COL("gray9", 0x171717), COL("grey9", 0x171717), COL("gray10", 0x1a1a1a), COL("grey10", 0x1a1a1a), COL("gray11", 0x1c1c1c), COL("grey11", 0x1c1c1c), COL("gray12", 0x1f1f1f), COL("grey12", 0x1f1f1f), COL("gray13", 0x212121), COL("grey13", 0x212121), COL("gray14", 0x242424), COL("grey14", 0x242424), COL("gray15", 0x262626), COL("grey15", 0x262626), COL("gray16", 0x292929), COL("grey16", 0x292929), COL("gray17", 0x2b2b2b), COL("grey17", 0x2b2b2b), COL("gray18", 0x2e2e2e), COL("grey18", 0x2e2e2e), COL("gray19", 0x303030), COL("grey19", 0x303030), COL("gray20", 0x333333), COL("grey20", 0x333333), COL("gray21", 0x363636), COL("grey21", 0x363636), COL("gray22", 0x383838), COL("grey22", 0x383838), COL("gray23", 0x3b3b3b), COL("grey23", 0x3b3b3b), COL("gray24", 0x3d3d3d), COL("grey24", 0x3d3d3d), COL("gray25", 0x404040), COL("grey25", 0x404040), COL("gray26", 0x424242), COL("grey26", 0x424242), COL("gray27", 0x454545), COL("grey27", 0x454545), COL("gray28", 0x474747), COL("grey28", 0x474747), COL("gray29", 0x4a4a4a), COL("grey29", 0x4a4a4a), COL("gray30", 0x4d4d4d), COL("grey30", 0x4d4d4d), COL("gray31", 0x4f4f4f), COL("grey31", 0x4f4f4f), COL("gray32", 0x525252), COL("grey32", 0x525252), COL("gray33", 0x545454), COL("grey33", 0x545454), COL("gray34", 0x575757), COL("grey34", 0x575757), COL("gray35", 0x595959), COL("grey35", 0x595959), COL("gray36", 0x5c5c5c), COL("grey36", 0x5c5c5c), COL("gray37", 0x5e5e5e), COL("grey37", 0x5e5e5e), COL("gray38", 0x616161), COL("grey38", 0x616161), COL("gray39", 0x636363), COL("grey39", 0x636363), COL("gray40", 0x666666), COL("grey40", 0x666666), COL("gray41", 0x696969), COL("grey41", 0x696969), COL("gray42", 0x6b6b6b), COL("grey42", 0x6b6b6b), COL("gray43", 0x6e6e6e), COL("grey43", 0x6e6e6e), COL("gray44", 0x707070), COL("grey44", 0x707070), COL("gray45", 0x737373), COL("grey45", 0x737373), COL("gray46", 0x757575), COL("grey46", 0x757575), COL("gray47", 0x787878), COL("grey47", 0x787878), COL("gray48", 0x7a7a7a), COL("grey48", 0x7a7a7a), COL("gray49", 0x7d7d7d), COL("grey49", 0x7d7d7d), COL("gray50", 0x7f7f7f), COL("grey50", 0x7f7f7f), COL("gray51", 0x828282), COL("grey51", 0x828282), COL("gray52", 0x858585), COL("grey52", 0x858585), COL("gray53", 0x878787), COL("grey53", 0x878787), COL("gray54", 0x8a8a8a), COL("grey54", 0x8a8a8a), COL("gray55", 0x8c8c8c), COL("grey55", 0x8c8c8c), COL("gray56", 0x8f8f8f), COL("grey56", 0x8f8f8f), COL("gray57", 0x919191), COL("grey57", 0x919191), COL("gray58", 0x949494), COL("grey58", 0x949494), COL("gray59", 0x969696), COL("grey59", 0x969696), COL("gray60", 0x999999), COL("grey60", 0x999999), COL("gray61", 0x9c9c9c), COL("grey61", 0x9c9c9c), COL("gray62", 0x9e9e9e), COL("grey62", 0x9e9e9e), COL("gray63", 0xa1a1a1), COL("grey63", 0xa1a1a1), COL("gray64", 0xa3a3a3), COL("grey64", 0xa3a3a3), COL("gray65", 0xa6a6a6), COL("grey65", 0xa6a6a6), COL("gray66", 0xa8a8a8), COL("grey66", 0xa8a8a8), COL("gray67", 0xababab), COL("grey67", 0xababab), COL("gray68", 0xadadad), COL("grey68", 0xadadad), COL("gray69", 0xb0b0b0), COL("grey69", 0xb0b0b0), COL("gray70", 0xb3b3b3), COL("grey70", 0xb3b3b3), COL("gray71", 0xb5b5b5), COL("grey71", 0xb5b5b5), COL("gray72", 0xb8b8b8), COL("grey72", 0xb8b8b8), COL("gray73", 0xbababa), COL("grey73", 0xbababa), COL("gray74", 0xbdbdbd), COL("grey74", 0xbdbdbd), COL("gray75", 0xbfbfbf), COL("grey75", 0xbfbfbf), COL("gray76", 0xc2c2c2), COL("grey76", 0xc2c2c2), COL("gray77", 0xc4c4c4), COL("grey77", 0xc4c4c4), COL("gray78", 0xc7c7c7), COL("grey78", 0xc7c7c7), COL("gray79", 0xc9c9c9), COL("grey79", 0xc9c9c9), COL("gray80", 0xcccccc), COL("grey80", 0xcccccc), COL("gray81", 0xcfcfcf), COL("grey81", 0xcfcfcf), COL("gray82", 0xd1d1d1), COL("grey82", 0xd1d1d1), COL("gray83", 0xd4d4d4), COL("grey83", 0xd4d4d4), COL("gray84", 0xd6d6d6), COL("grey84", 0xd6d6d6), COL("gray85", 0xd9d9d9), COL("grey85", 0xd9d9d9), COL("gray86", 0xdbdbdb), COL("grey86", 0xdbdbdb), COL("gray87", 0xdedede), COL("grey87", 0xdedede), COL("gray88", 0xe0e0e0), COL("grey88", 0xe0e0e0), COL("gray89", 0xe3e3e3), COL("grey89", 0xe3e3e3), COL("gray90", 0xe5e5e5), COL("grey90", 0xe5e5e5), COL("gray91", 0xe8e8e8), COL("grey91", 0xe8e8e8), COL("gray92", 0xebebeb), COL("grey92", 0xebebeb), COL("gray93", 0xededed), COL("grey93", 0xededed), COL("gray94", 0xf0f0f0), COL("grey94", 0xf0f0f0), COL("gray95", 0xf2f2f2), COL("grey95", 0xf2f2f2), COL("gray96", 0xf5f5f5), COL("grey96", 0xf5f5f5), COL("gray97", 0xf7f7f7), COL("grey97", 0xf7f7f7), COL("gray98", 0xfafafa), COL("grey98", 0xfafafa), COL("gray99", 0xfcfcfc), COL("grey99", 0xfcfcfc), COL("gray100", 0xffffff), COL("grey100", 0xffffff), COL("darkgrey", 0xa9a9a9), COL("darkgray", 0xa9a9a9), COL("darkblue", 0x00008b), COL("darkcyan", 0x008b8b), COL("darkmagenta", 0x8b008b), COL("darkred", 0x8b0000), COL("lightgreen", 0x90ee90), COL(NULL,0) /* sentinel */ }; #undef COL void long_to_rgb(long c, int *r, int *g, int *b) { *b = c & 0xff; c >>= 8; *g = c & 0xff; c >>= 8; *r = c; } static int hex2(const char *s) { int m = 0, c = 0, i; for (i = 0; i < 2; i++, s++) { if (*s >= '0' && *s <= '9') c = *s - '0'; else if (*s >= 'A' && *s <= 'F') c = *s - 'A' + 10; else if (*s >= 'a' && *s <= 'f') c = *s - 'a' + 10; else pari_err(e_MISC,"incorrect hexadecimal number: %s", s); m = 16*m + c; } return m; } void colorname_to_rgb(const char *s, int *r, int *g, int *b) { if (!rgb_colors) rgb_colors = hashstr_import_static(col_list, 1000); if (*s == '#' && strlen(s) == 7) { *r = hex2(s+1); *g = hex2(s+3); *b = hex2(s+5); } else { hashentry *ep = hash_search(rgb_colors, (void*)s); if (!ep) pari_err(e_MISC, "unknown color %s", s); long_to_rgb((long)ep->val, r,g,b); } } static void chk_8bit(int v, GEN c) { if (v & ~0xff) pari_err(e_MISC, "invalid RGB code: %Ps", c); } 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]; chk_8bit(*r, c); *g = c[2]; chk_8bit(*g, c); *b = c[3]; chk_8bit(*b, c); break; } } pari-2.17.2/src/graph/plotWin32.c0000644000175000017500000000761014676526175015050 0ustar billbill/* Copyright (C) 2009 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* Written by Vasili Burdo */ #include "../systems/mingw/pwinver.h" #include #include #include "pari.h" #include "rect.h" static void SetForeground(void *data, long col) { int r, g, b; long_to_rgb(col, &r, &g, &b); SelectObject((HDC)data, GetStockObject(DC_PEN)); SetDCPenColor((HDC)data,RGB(r,g,b)); SelectObject((HDC)data, GetStockObject(DC_BRUSH)); SetDCBrushColor((HDC)data,RGB(r,g,b)); } static void DrawPoint(void *data, long x, long y) { SelectObject((HDC)data, GetStockObject(DC_BRUSH)); Ellipse((HDC)data,x-1,y-1,x+1,y+1); } static void DrawArc(void *data, long x, long y, long w, long h) { SelectObject((HDC)data, GetStockObject(HOLLOW_BRUSH)); Ellipse((HDC)data,x,y,x+w,y+h); } static void FillArc(void *data, long x, long y, long w, long h) { SelectObject((HDC)data, GetStockObject(DC_BRUSH)); Ellipse((HDC)data,x,y,x+w,y+h); } 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) { SelectObject((HDC)data, GetStockObject(HOLLOW_BRUSH)); Rectangle((HDC)data,x,y,x+w,y+h); } static void FillRectangle(void *data, long x, long y, long w, long h) { SelectObject((HDC)data, GetStockObject(DC_BRUSH)); Rectangle((HDC)data,x,y,x+w,y+h); } static void DrawPoints(void *data, long nb, struct plot_points *p) { long i; for (i=0; icolormap,1), &r,&g,&b); SetBkColor(hEmf, RGB(r,g,b)); SetBkMode(hEmf, OPAQUE); plotWin32.sc=&SetForeground; plotWin32.pt=&DrawPoint; plotWin32.ln=&DrawLine; plotWin32.ac=&DrawArc; plotWin32.fa=&FillArc; plotWin32.bx=&DrawRectangle; plotWin32.fb=&FillRectangle; plotWin32.mp=&DrawPoints; plotWin32.ml=&DrawLines; plotWin32.st=&DrawString; plotWin32.pl=T; plotWin32.data=(void*)hEmf; gen_draw(&plotWin32, w, x, y, 1, 1); DeleteEnhMetaFile(CloseEnhMetaFile(hEmf)); ShellExecute(NULL,NULL,fname,NULL,NULL,SW_SHOWDEFAULT); } INLINE void gp_get_display_sizes(long *dwidth, long *dheight, long *fwidth, long *fheight) { HDC hdc; TEXTMETRIC tm; *dwidth = GetSystemMetrics(SM_CXSCREEN); *dheight = GetSystemMetrics(SM_CYSCREEN); hdc = GetDC(0); SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT)); GetTextMetrics(hdc, &tm); ReleaseDC(0,hdc); *fwidth = tm.tmAveCharWidth; *fheight = tm.tmHeight; } void gp_get_plot(PARI_plot *T) { gp_get_plot_generic(T,gp_get_display_sizes); T->draw = &draw; } pari-2.17.2/src/graph/plotfltk.c0000644000175000017500000001130714751735502015072 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ ///////////////////////////////////////////////////////////////////////////// // // High resolution plot using FLTK library // Bill Allombert 2003 // // Based on plotQt by Nils-Peter Skoruppa (www.countnumber.de) ///////////////////////////////////////////////////////////////////////////// #include #include #include extern "C" { #include "pari.h" #include "paripriv.h" #include "rect.h" } class Plotter: public Fl_Window { public: Plotter(PARI_plot *T, GEN w, GEN x, GEN y); private: void draw(); int handle(int event); private: PARI_plot *T; GEN my_w, my_x, my_y; }; static Fl_Color rgb_color(long c) { int r, g, b; long_to_rgb(c, &r, &g, &b); return fl_color_cube(r*FL_NUM_RED/256, g*FL_NUM_GREEN/256, b*FL_NUM_BLUE/256); } Plotter::Plotter(PARI_plot *T, GEN w, GEN x, GEN y) : Fl_Window(T->width, T->height, "PARI/GP") { this->T = T; this->my_w = w; this->my_x = x; this->my_y = y; } 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 DrawArc(void *data, long x, long y, long w, long h) { (void)data; fl_arc(x,y,w,h,0,360); } static void FillArc(void *data, long x, long y, long w, long h) { (void)data; fl_pie(x,y,w,h,0,360); } static void DrawRectangle(void *data, long x, long y, long w, long h) { (void)data; fl_rect(x,y,w,h); } static void FillRectangle(void *data, long x, long y, long w, long h) { (void)data; fl_rectf(x,y,w,h); } static void DrawPoints(void *data, long nb, struct plot_points *p) { long i; (void)data; for (i=0; iw()) / T->width; double ys = double(this->h()) / T->height; fl_font(FL_COURIER, int(T->fheight * xs)); fl_color(rgb_color(0xffffff)); // transparent window on Windows otherwise fl_rectf(0, 0, this->w(), this->h()); pl.sc = &SetForeground; pl.pt = &DrawPoint; pl.ln = &DrawLine; pl.ac = &DrawArc; pl.fa = &FillArc; pl.bx = &DrawRectangle; pl.fb = &FillRectangle; pl.mp = &DrawPoints; pl.ml = &DrawLines; pl.st = &DrawString; pl.pl = T; pl.data = NULL; gen_draw(&pl, my_w, my_x, my_y, 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, my_x, my_y, my_w, 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; } } static void draw(PARI_plot *T, GEN w, GEN x, GEN y) { Plotter *win; if (pari_daemon()) return; // parent process returns if (mt_is_thread()) pari_thread_close(); else pari_close(); Fl::visual(FL_DOUBLE|FL_INDEX); win = new Plotter(T, w, x, y); win->size_range(1,1); win->box(FL_FLAT_BOX); win->end(); win->show(); Fl::run(); exit(0); } INLINE void gp_get_display_sizes(long *dwidth, long *dheight, long *fwidth, long *fheight) { *dwidth = 800; *dheight = 600; *fwidth = 6; *fheight = 9; } void gp_get_plot(PARI_plot *T) { gp_get_plot_generic(T,gp_get_display_sizes); T->draw = &draw; } pari-2.17.2/src/graph/plotX.c0000644000175000017500000002077514676526175014364 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*******************************************************************/ /* */ /* 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; struct data_x { Display *display; Window win; int numcolors; GC gc; }; /* after fork(), we don't want the child to recover but to exit */ static void exiterr(const char *str) { term_color(c_ERR); err_printf("\n *** X fatal error: %s\n",str); term_color(c_NONE); _exit(1); } static long rgb_to_pixel(Display *display, int r, int g, int b) { XColor X; X.red = r*65535/255; X.green = g*65535/255; X.blue = b*65535/255; X.flags = DoRed | DoGreen | DoBlue; if (!XAllocColor(display,PARI_Colormap,&X)) exiterr("cannot allocate color"); return X.pixel; } static long colormapindex_to_pixel(Display *display, long i) { GEN c = gel(GP_DATA->colormap, i+1); int r,g,b; color_to_rgb(c, &r,&g,&b); return rgb_to_pixel(display, r, g, b); } static long rgb_color(Display *display, long c) { int r,g,b; long_to_rgb(c, &r, &g, &b); return rgb_to_pixel(display, r, g, b); } static void SetForeground(void *data, long col) { struct data_x *dx = (struct data_x *) data; XSetForeground(dx->display,dx->gc, rgb_color(dx->display,col)); } 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 DrawArc(void *data, long x, long y, long w, long h) { struct data_x *dx = (struct data_x *) data; XDrawArc(dx->display,dx->win,dx->gc, x,y, w,h, 0, 64*360); } static void FillArc(void *data, long x, long y, long w, long h) { struct data_x *dx = (struct data_x *) data; XFillArc(dx->display,dx->win,dx->gc, x,y, w,h, 0, 64*360); } 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 FillRectangle(void *data, long x, long y, long w, long h) { struct data_x *dx = (struct data_x *) data; XFillRectangle(dx->display,dx->win,dx->gc, x,y, w,h); } static void DrawPoints(void *data, long nb, struct plot_points *p) { struct data_x *dx = (struct data_x *) data; XPoint *xp=(XPoint*)pari_malloc(sizeof(xp)*nb); long i; for (i=0;idisplay,dx->win,dx->gc, xp, nb, 0); pari_free(xp); } static void DrawLines(void *data, long nb, struct plot_points *p) { struct data_x *dx = (struct data_x *) data; XPoint *xp=(XPoint*)pari_malloc(sizeof(xp)*nb); long i; for (i=0;idisplay,dx->win,dx->gc, xp, nb, 0); pari_free(xp); } static void DrawString(void *data, long x, long y, char *text, long numtext) { struct data_x *dx = (struct data_x *) data; XDrawString(dx->display,dx->win,dx->gc, x,y, text, numtext); } #define MAX_BUF 256 static int Xerror(Display *d, XErrorEvent *pari_err) { char buf[MAX_BUF]; XGetErrorText(d,pari_err->error_code,buf,MAX_BUF); exiterr(buf); return 0; } static int IOerror(Display *d) { char buf[MAX_BUF]; sprintf(buf, "lost display on %s", DisplayString(d)); exiterr(buf); return 0; } static void draw(PARI_plot *T, GEN w, GEN x, GEN y) { 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 */ display = XOpenDisplay(NULL); if (!display) exiterr("cannot open Display"); font_info = XLoadQueryFont(display, "7x13"); if (!font_info) exiterr("cannot open 7x13 font"); XSetErrorHandler(Xerror); XSetIOErrorHandler(IOerror); PARI_Colormap = DefaultColormap(display, 0); screen = DefaultScreen(display); win = XCreateSimpleWindow (display, RootWindow(display, screen), 0, 0, T->width, T->height, 4, colormapindex_to_pixel(display, 1), colormapindex_to_pixel(display, 0)); size_hints.flags = PPosition | PSize; size_hints.x = 0; size_hints.y = 0; size_hints.width = T->width; size_hints.height = T->height; XSetStandardProperties (display, win, "PARI plot", 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 = T->width; oldheight = T->height; dx.display= display; dx.win = win; dx.numcolors = lg(GP_DATA->colormap)-1; dx.gc = gc; plotX.sc = &SetForeground; plotX.pt = &DrawPoint; plotX.ln = &DrawLine; plotX.ac = &DrawArc; plotX.fa = &FillArc; plotX.bx = &DrawRectangle; plotX.fb = &FillRectangle; plotX.mp = &DrawPoints; plotX.ml = &DrawLines; plotX.st = &DrawString; plotX.pl = T; plotX.data = (void*)&dx; if (mt_is_thread()) pari_thread_close(); else pari_close(); 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)/T->width; ys = ((double)height)/T->height; XClearWindow(display, win); } case Expose: gen_draw(&plotX, w, x, y, xs, ys); } } } INLINE void gp_get_display_sizes(long *dwidth, long *dheight, long *fwidth, long *fheight) { Display *display; display = XOpenDisplay(NULL); if (display) { int screen = DefaultScreen(display); *dwidth = DisplayWidth(display, screen); *dheight = DisplayHeight(display, screen); XCloseDisplay(display); } else { /* Situation looks grim */ *dwidth = 0; *dheight = 0; } *fwidth = 7; *fheight = 13; } void gp_get_plot(PARI_plot *T) { gp_get_plot_generic(T,gp_get_display_sizes); T->draw = &draw; } pari-2.17.2/src/graph/plotnone.c0000644000175000017500000000201514567450071015065 0ustar billbill/* Copyright (C) 2017 The PARI group. This file is part of the PARI/GP package. 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. */ #include "pari.h" #include "rect.h" void gp_get_plot(PARI_plot *T) { T->width = 480; T->height = 320; T->fheight = 12; T->fwidth = 6; T->hunit = 3; T->vunit = 3; gp_get_ploth_default_sizes(T); T->dwidth = 0; T->dheight = 0; T->draw = NULL; } pari-2.17.2/src/graph/rect.h0000644000175000017500000001340614676526175014211 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ BEGINEXTERN 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; } PariRect; /* The structures below are "subclasses" of RectObj. */ typedef struct RectObj1P { struct RectObj *next; long code,color; double x,y; } RectObj1P; typedef struct RectObj2P { struct RectObj *next; long code,color; double x1,y1; double x2,y2; } RectObj2P; typedef struct RectObjMP { struct RectObj *next; long code,color; long count; double *xs,*ys; } RectObjMP; typedef struct RectObjST { struct RectObj *next; long code,color; long length; char *s; double x,y; long dir; } RectObjST; typedef struct RectObjPN { struct RectObj *next; long code,color; long pen; } RectObjPN; typedef struct RectObjPS { struct RectObj *next; long code,color; double size; } RectObjPS; struct plot_points { long x, y; }; struct plot_eng { PARI_plot *pl; void *data; void (*sc)(void *data, long col); void (*pt)(void *data, long x, long y); void (*ln)(void *data, long x1, long y1, long x2, long y2); void (*ac)(void *data, long x, long y, long w, long h); void (*fa)(void *data, long x, long y, long w, long h); void (*bx)(void *data, long x, long y, long w, long h); void (*fb)(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); }; /* Pointer conversion. */ #define RoMV(rop) ((RectObj1P*)rop) #define RoPT(rop) ((RectObj1P*)rop) #define RoLN(rop) ((RectObj2P*)rop) #define RoAC(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) /* All the access to the rectangle data 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 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 RoACx1(rop) (RoAC(rop)->x1) #define RoACy1(rop) (RoAC(rop)->y1) #define RoACx2(rop) (RoAC(rop)->x2) #define RoACy2(rop) (RoAC(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 RoPTTpen(rop) (RoPTT(rop)->pen) #define RoLNTpen(rop) (RoLNT(rop)->pen) #define RoPTSsize(rop) (RoPTS(rop)->size) void gen_draw(struct plot_eng *eng, GEN w, GEN x, GEN y, double xs, double ys); void gp_get_plot(PARI_plot *T); #define gp_get_ploth_default_sizes(S) \ { PARI_plot *_T = (PARI_plot *)S; \ GEN D = GP_DATA->plothsizes; \ if (D) switch(lg(D)) { \ case 5: if (D[4]) _T->vunit = D[4]; \ case 4: if (D[3]) _T->hunit = D[3]; \ case 3: if (D[2]) _T->height = D[2]; \ case 2: if (D[1]) _T->width = D[1]; \ } \ } #define gp_get_plot_generic(S,gp_get_display_sizes) \ { PARI_plot *_T = (PARI_plot *)S; \ gp_get_display_sizes(&_T->dwidth, &_T->dheight, &_T->fwidth, &_T->fheight);\ _T->width = _T->dwidth? _T->dwidth*4/5: 640; \ _T->height= _T->dheight?_T->dheight*4/5: 480; \ _T->hunit = maxss(_T->height/100,3); \ _T->vunit = maxss(_T->height/100,3); \ gp_get_ploth_default_sizes(S); \ } ENDEXTERN pari-2.17.2/src/graph/plottty.c0000644000175000017500000001057114567450071014754 0ustar billbill/* Copyright (C) 2016 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" /********************************************************************/ /** **/ /** LOW-RES PLOT **/ /** **/ /********************************************************************/ #define ISCR 64 #define JSCR 22 INLINE long DTOL(double t) { return (long)(t + 0.5); } static char PICT(long j) { switch(j%3) { case 0: return '_'; case 1: return 'x'; default: return '"'; } } static char PICTZERO(long j) { switch(j%3) { case 0: return ','; case 1: return '-'; default: return '`'; } } static char * dsprintf9(double d, char *buf) { int i = 10; while (--i >= 0) { sprintf(buf, "%9.*g", i, d); if (strlen(buf) <= 9) break; } return buf; } typedef unsigned char screen[ISCR+1][JSCR+1]; static void fill_gap(screen scr, long i, int jnew, int jpre) { int mid, i_up, i_lo, up, lo; if (jpre < jnew - 2) { up = jnew - 1; i_up = i; lo = jpre + 1; i_lo = i - 1; } else if (jnew < jpre - 2) { up = jpre - 1; i_up = i - 1; lo = jnew + 1; i_lo = i; } else return; /* if gap < 2, leave it as it is. */ mid = (jpre+jnew)/2; if (mid>JSCR) mid=JSCR; else if (mid<0) mid=0; if (lo<0) lo=0; if (lo<=JSCR) while (lo <= mid) scr[i_lo][lo++] = ':'; if (up>JSCR) up=JSCR; if (up>=0) while (up > mid) scr[i_up][up--] = ':'; } static double todbl(GEN x) { return rtodbl(gtofp(x, LOWDEFAULTPREC)); } void pariplot(void* E, GEN (*fun)(void *E, GEN x), GEN a, GEN b, GEN ysmlu,GEN ybigu, long prec) { const char BLANK = ' ', YY = '|', XX_UPPER = '\'', XX_LOWER = '.'; long jz, j, i, sig; pari_sp av = avma; 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); dx = divru(gtofp(gsub(b,a),prec), ISCR-1); for (j=1; j<=JSCR; j++) scr[1][j]=scr[ISCR][j]=YY; for (i=2; i ybig) ybig = y[i]; } x = addrr(x,dx); } set_avma(av); if (ysmlu) ysml = gtodouble(ysmlu); if (ybigu) ybig = gtodouble(ybigu); diff = ybig - ysml; if (!diff) { ybig += 1; diff= 1.; } dyj = ((JSCR-1)*3+2) / diff; /* work around bug in gcc-4.8 (32bit): plot(x=-5,5,sin(x)))) */ jz = 3 - (long)(ysml*dyj + 0.5); /* 3 - DTOL(ysml*dyj) */ z = PICTZERO(jz); jz /= 3; for (i=1; i<=ISCR; i++) { 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); } } void pariplot0(GEN a, GEN b, GEN code, GEN ysmlu,GEN ybigu, long prec) { push_lex(gen_0, code); pariplot((void*)code, &gp_eval, a, b, ysmlu, ybigu, prec); pop_lex(1); } pari-2.17.2/src/funclist0000644000175000017500000021015114760125067013535 0ustar billbill1577835232 7381 ../functions/algebras/HEADER 4192641900 615 ../functions/algebras/algadd 2059206215 615 ../functions/algebras/algalgtobasis 4131825566 462 ../functions/algebras/algaut 3647549794 434 ../functions/algebras/algb 4050433086 509 ../functions/algebras/algbasis 4100607966 637 ../functions/algebras/algbasistoalg 3679242706 950 ../functions/algebras/algcenter 3321640631 1061 ../functions/algebras/algcentralproj 1368933465 371 ../functions/algebras/algchar 1737098719 1486 ../functions/algebras/algcharpoly 419788237 329 ../functions/algebras/algdegree 585799553 642 ../functions/algebras/algdim 4292104488 735 ../functions/algebras/algdisc 1339996038 751 ../functions/algebras/algdivl 3956303260 310 ../functions/algebras/algdivr 3320957384 652 ../functions/algebras/alggroup 2351357025 1801 ../functions/algebras/alggroupcenter 503110574 775 ../functions/algebras/alghasse 3299470328 806 ../functions/algebras/alghassef 3790515900 549 ../functions/algebras/alghassei 2185516854 935 ../functions/algebras/algindex 1796287680 7343 ../functions/algebras/alginit 169069771 573 ../functions/algebras/alginv 3763251124 501 ../functions/algebras/alginvbasis 2680904733 870 ../functions/algebras/algisassociative 129389649 583 ../functions/algebras/algiscommutative 2055123029 940 ../functions/algebras/algisdivision 3948002876 667 ../functions/algebras/algisdivl 195194404 597 ../functions/algebras/algisinv 234251723 1011 ../functions/algebras/algisramified 2458125155 705 ../functions/algebras/algissemisimple 4237044151 1017 ../functions/algebras/algissimple 1565686379 967 ../functions/algebras/algissplit 2205365426 670 ../functions/algebras/alglatadd 4011442037 650 ../functions/algebras/alglatcontains 2006314610 589 ../functions/algebras/alglatelement 3756719573 917 ../functions/algebras/alglathnf 1041235201 555 ../functions/algebras/alglatindex 2927979722 673 ../functions/algebras/alglatinter 3881391307 760 ../functions/algebras/alglatlefttransporter 3790212975 872 ../functions/algebras/alglatmul 3736349937 786 ../functions/algebras/alglatrighttransporter 952558383 737 ../functions/algebras/alglatsubset 1869042376 1077 ../functions/algebras/algmakeintegral 542126088 561 ../functions/algebras/algmul 2292324981 991 ../functions/algebras/algmultable 2700982877 418 ../functions/algebras/algneg 2294876111 1031 ../functions/algebras/algnorm 3963005415 1025 ../functions/algebras/algpoleval 4172839959 569 ../functions/algebras/algpow 2586805729 687 ../functions/algebras/algprimesubalg 413949787 721 ../functions/algebras/algquotient 3247593680 832 ../functions/algebras/algradical 1925292482 640 ../functions/algebras/algramifiedplaces 568773931 688 ../functions/algebras/algrandom 4270922456 832 ../functions/algebras/algrelmultable 907726650 1215 ../functions/algebras/algsimpledec 4000638684 1836 ../functions/algebras/algsplit 2114429201 1390 ../functions/algebras/algsplittingdata 97897885 768 ../functions/algebras/algsplittingfield 354260212 506 ../functions/algebras/algsqr 1450786509 555 ../functions/algebras/algsub 1033983103 898 ../functions/algebras/algsubalg 2044746518 1770 ../functions/algebras/algtableinit 2991400026 400 ../functions/algebras/algtensor 3059750225 1454 ../functions/algebras/algtomatrix 590119197 1071 ../functions/algebras/algtrace 2294819390 1316 ../functions/algebras/algtype 1284844525 707 ../functions/combinatorics/HEADER 4078127317 623 ../functions/combinatorics/bernfrac 3275605797 859 ../functions/combinatorics/bernpol 2110336155 566 ../functions/combinatorics/bernreal 3621517921 1180 ../functions/combinatorics/bernvec 1925818224 1735 ../functions/combinatorics/binomial 3937272674 514 ../functions/combinatorics/eulerfrac 3340482895 408 ../functions/combinatorics/eulerianpol 4051451759 370 ../functions/combinatorics/eulerpol 406434451 564 ../functions/combinatorics/eulerreal 3983120963 912 ../functions/combinatorics/eulervec 3907450247 157 ../functions/combinatorics/fibonacci 1993153926 551 ../functions/combinatorics/hammingweight 4015630053 947 ../functions/combinatorics/harmonic 827537864 519 ../functions/combinatorics/numbpart 2218855117 536 ../functions/combinatorics/numtoperm 2919690681 2229 ../functions/combinatorics/partitions 3191959678 475 ../functions/combinatorics/permcycles 2816060205 326 ../functions/combinatorics/permorder 2294776331 287 ../functions/combinatorics/permsign 3014137573 364 ../functions/combinatorics/permtonum 366954449 1577 ../functions/combinatorics/stirling 3207344411 1532 ../functions/conversions/Col 844182789 589 ../functions/conversions/Colrev 502505451 506 ../functions/conversions/HEADER 1553998502 528 ../functions/conversions/List 1011755784 869 ../functions/conversions/Map 1094831741 990 ../functions/conversions/Mat 3725864825 1660 ../functions/conversions/Mod 1108612879 1779 ../functions/conversions/Pol 990585572 916 ../functions/conversions/Polrev 2759190759 483 ../functions/conversions/Qfb 2232239674 2223 ../functions/conversions/Ser 1244914425 745 ../functions/conversions/Set 2107459280 982 ../functions/conversions/Str 40448383 2815 ../functions/conversions/Vec 1545016376 551 ../functions/conversions/Vecrev 3161838538 784 ../functions/conversions/Vecsmall 412785269 664 ../functions/conversions/binary 3091587880 898 ../functions/conversions/bitand 748759108 617 ../functions/conversions/bitneg 4248473339 712 ../functions/conversions/bitnegimply 2997192793 622 ../functions/conversions/bitor 3421621600 1688 ../functions/conversions/bitprecision 956117494 1052 ../functions/conversions/bittest 2782641720 639 ../functions/conversions/bitxor 1456424929 513 ../functions/conversions/ceil 3010088276 1033 ../functions/conversions/centerlift 3152283863 478 ../functions/conversions/characteristic 3610246152 1748 ../functions/conversions/component 2027282389 401 ../functions/conversions/conj 4156090058 842 ../functions/conversions/conjvec 3190949018 1817 ../functions/conversions/denominator 589417591 1130 ../functions/conversions/digits 877853428 1535 ../functions/conversions/exponent 2072628265 514 ../functions/conversions/floor 689569802 220 ../functions/conversions/frac 2581638496 796 ../functions/conversions/fromdigits 2582971266 439 ../functions/conversions/imag 4211773840 1268 ../functions/conversions/length 2930632048 1936 ../functions/conversions/lift 774441096 775 ../functions/conversions/liftall 4056484149 764 ../functions/conversions/liftint 1007160287 718 ../functions/conversions/liftpol 1686560015 435 ../functions/conversions/norm 1306659348 1036 ../functions/conversions/numerator 3087492945 385 ../functions/conversions/oo 2584337134 1101 ../functions/conversions/padicprec 836166759 1497 ../functions/conversions/precision 570027322 4269 ../functions/conversions/random 613587742 424 ../functions/conversions/real 1222937070 1561 ../functions/conversions/round 2032952940 460 ../functions/conversions/serchop 3427968276 678 ../functions/conversions/serprec 1581212202 1010 ../functions/conversions/simplify 2803792228 343 ../functions/conversions/sizebyte 64112871 727 ../functions/conversions/sizedigit 3505995884 1713 ../functions/conversions/truncate 1635305205 1185 ../functions/conversions/valuation 3395959447 2556 ../functions/conversions/varhigher 827271423 1865 ../functions/conversions/variable 4119912783 1294 ../functions/conversions/variables 2504491136 3296 ../functions/conversions/varlower 2616236005 284 ../functions/default/HEADER 4007521616 665 ../functions/default/TeXstyle 1744298337 288 ../functions/default/breakloop 1552827507 2203 ../functions/default/colors 2202570829 162 ../functions/default/compatible 290664126 552 ../functions/default/datadir 3061739873 376 ../functions/default/debug 2925926903 339 ../functions/default/debugfiles 600909082 967 ../functions/default/debugmem 3540920433 673 ../functions/default/echo 3269179051 776 ../functions/default/factor_add_primes 3740185017 672 ../functions/default/factor_proven 2532649096 3545 ../functions/default/factorlimit 3412943342 1339 ../functions/default/format 3895529277 1601 ../functions/default/graphcolormap 779275016 622 ../functions/default/graphcolors 2025412279 581 ../functions/default/help 1201299674 713 ../functions/default/histfile 3654358528 443 ../functions/default/histsize 804309020 553 ../functions/default/lines 1037801881 237 ../functions/default/linewrap 4230119730 1193 ../functions/default/log 4131263332 249 ../functions/default/logfile 3419520588 738 ../functions/default/nbthreads 3548328759 468 ../functions/default/new_galois_format 852419531 1403 ../functions/default/output 3451585978 987 ../functions/default/parisize 3854806981 1223 ../functions/default/parisizemax 2366699578 712 ../functions/default/path 754000989 226 ../functions/default/plothsizes 1991406625 395 ../functions/default/prettyprinter 654973086 2767 ../functions/default/primelimit 3806881294 1449 ../functions/default/prompt 576684223 347 ../functions/default/prompt_cont 1573027332 235 ../functions/default/psfile 1224291797 435 ../functions/default/readline 96211455 1685 ../functions/default/realbitprecision 586134349 1267 ../functions/default/realprecision 1281891849 309 ../functions/default/recover 1228873450 456 ../functions/default/secure 699347451 257 ../functions/default/seriesprecision 4068861417 868 ../functions/default/simplify 3166076333 826 ../functions/default/sopath 3837614417 832 ../functions/default/strictargs 1483099468 163 ../functions/default/strictmatch 1676639539 1156 ../functions/default/threadsize 2794059589 890 ../functions/default/threadsizemax 1378378011 1265 ../functions/default/timer 2793303779 10597 ../functions/elliptic_curves/HEADER 3164460909 1257 ../functions/elliptic_curves/ell2cover 2395121593 1323 ../functions/elliptic_curves/ellL1 1093349276 227 ../functions/elliptic_curves/elladd 2487372530 1313 ../functions/elliptic_curves/ellak 2552229870 860 ../functions/elliptic_curves/ellan 2971845769 1266 ../functions/elliptic_curves/ellanalyticrank 1237269041 3961 ../functions/elliptic_curves/ellap 45445857 207 ../functions/elliptic_curves/ellbil 1695859666 1152 ../functions/elliptic_curves/ellbsd 3741060784 1772 ../functions/elliptic_curves/ellcard 4087265952 605 ../functions/elliptic_curves/ellchangecurve 3384877004 751 ../functions/elliptic_curves/ellchangepoint 4066931748 731 ../functions/elliptic_curves/ellchangepointinv 1622337703 620 ../functions/elliptic_curves/ellconvertname 3352201214 1285 ../functions/elliptic_curves/elldivpol 3297659175 1462 ../functions/elliptic_curves/elleisnum 430322815 603 ../functions/elliptic_curves/elleta 139557889 951 ../functions/elliptic_curves/ellformaldifferential 2752093191 715 ../functions/elliptic_curves/ellformalexp 3925400834 674 ../functions/elliptic_curves/ellformallog 2864452304 996 ../functions/elliptic_curves/ellformalpoint 1309233974 762 ../functions/elliptic_curves/ellformalw 2924283481 1857 ../functions/elliptic_curves/ellfromeqn 1322134257 1222 ../functions/elliptic_curves/ellfromj 1120422287 1547 ../functions/elliptic_curves/ellgenerators 2750879689 1971 ../functions/elliptic_curves/ellglobalred 1752340507 3665 ../functions/elliptic_curves/ellgroup 2517509974 1081 ../functions/elliptic_curves/ellheegner 1863543431 1084 ../functions/elliptic_curves/ellheight 634335038 816 ../functions/elliptic_curves/ellheightmatrix 1800430023 717 ../functions/elliptic_curves/ellidentify 2392968086 4998 ../functions/elliptic_curves/ellinit 745723331 724 ../functions/elliptic_curves/ellintegralmodel 4084727907 801 ../functions/elliptic_curves/elliscm 3699549550 1215 ../functions/elliptic_curves/ellisdivisible 3803332233 915 ../functions/elliptic_curves/ellisisom 1097316797 1048 ../functions/elliptic_curves/ellisogeny 3134864760 963 ../functions/elliptic_curves/ellisogenyapply 212261337 2531 ../functions/elliptic_curves/ellisomat 240812548 602 ../functions/elliptic_curves/ellisoncurve 2904529346 1428 ../functions/elliptic_curves/ellisotree 739252725 1268 ../functions/elliptic_curves/ellissupersingular 3064568940 281 ../functions/elliptic_curves/ellj 1949671120 1365 ../functions/elliptic_curves/elllocalred 498541802 1167 ../functions/elliptic_curves/elllog 3097115102 742 ../functions/elliptic_curves/elllseries 749408130 794 ../functions/elliptic_curves/ellmaninconstant 1915877597 362 ../functions/elliptic_curves/ellminimaldisc 3053189669 2103 ../functions/elliptic_curves/ellminimalmodel 2998208851 1431 ../functions/elliptic_curves/ellminimaltwist 2752993362 1310 ../functions/elliptic_curves/ellmoddegree 317251862 2282 ../functions/elliptic_curves/ellmodulareqn 2371457085 1054 ../functions/elliptic_curves/ellmul 2235217918 190 ../functions/elliptic_curves/ellneg 3326292124 874 ../functions/elliptic_curves/ellnonsingularmultiple 2709102639 1873 ../functions/elliptic_curves/ellorder 712202039 307 ../functions/elliptic_curves/ellordinate 4052880865 4641 ../functions/elliptic_curves/ellpadicL 2756931713 3407 ../functions/elliptic_curves/ellpadicbsd 820535213 922 ../functions/elliptic_curves/ellpadicfrobenius 2222150219 3399 ../functions/elliptic_curves/ellpadicheight 2859193712 1074 ../functions/elliptic_curves/ellpadicheightmatrix 1944920008 2402 ../functions/elliptic_curves/ellpadiclambdamu 1014857547 1078 ../functions/elliptic_curves/ellpadiclog 2170160799 2127 ../functions/elliptic_curves/ellpadicregulator 3555934165 1391 ../functions/elliptic_curves/ellpadics2 1874602164 1498 ../functions/elliptic_curves/ellperiods 683750487 3189 ../functions/elliptic_curves/ellpointtoz 1928877975 183 ../functions/elliptic_curves/ellpow 2361165505 4174 ../functions/elliptic_curves/ellrank 3276446358 587 ../functions/elliptic_curves/ellrankinit 1626886641 842 ../functions/elliptic_curves/ellratpoints 4215486523 901 ../functions/elliptic_curves/ellrootno 640029200 1704 ../functions/elliptic_curves/ellsaturation 4269707140 3186 ../functions/elliptic_curves/ellsea 4215222441 1838 ../functions/elliptic_curves/ellsearch 819897465 1154 ../functions/elliptic_curves/ellsigma 3595576828 241 ../functions/elliptic_curves/ellsub 2063048303 1034 ../functions/elliptic_curves/ellsupersingularj 1645380465 673 ../functions/elliptic_curves/elltamagawa 967274 1090 ../functions/elliptic_curves/elltaniyama 3658902126 599 ../functions/elliptic_curves/elltatepairing 349862474 807 ../functions/elliptic_curves/elltors 3027065048 1628 ../functions/elliptic_curves/elltrace 3326196788 1565 ../functions/elliptic_curves/elltwist 3311570917 2701 ../functions/elliptic_curves/ellweilcurve 1653549921 851 ../functions/elliptic_curves/ellweilpairing 174849219 1912 ../functions/elliptic_curves/ellwp 53062724 974 ../functions/elliptic_curves/ellxn 1470667492 1502 ../functions/elliptic_curves/ellzeta 1029341635 2039 ../functions/elliptic_curves/ellztopoint 3936301959 1708 ../functions/elliptic_curves/genus2igusa 2017669736 6063 ../functions/elliptic_curves/genus2red 3022693353 863 ../functions/elliptic_curves/hyperellchangecurve 2030825574 735 ../functions/elliptic_curves/hyperellcharpoly 1024499030 831 ../functions/elliptic_curves/hyperelldisc 2534028655 827 ../functions/elliptic_curves/hyperellisoncurve 1571190394 1114 ../functions/elliptic_curves/hyperellminimaldisc 4079732805 1555 ../functions/elliptic_curves/hyperellminimalmodel 2401423286 327 ../functions/elliptic_curves/hyperellordinate 494430689 2227 ../functions/elliptic_curves/hyperellpadicfrobenius 470354325 1365 ../functions/elliptic_curves/hyperellratpoints 1497735351 1422 ../functions/elliptic_curves/hyperellred 1668730040 123 ../functions/gp2c/DEBUGLEVEL 673657102 528 ../functions/gp2c/clone 369541074 432 ../functions/gp2c/copy 3783251634 108 ../functions/gp2c/unclone 1891743718 82 ../functions/gp2c_internal/_avma 2383149381 809 ../functions/gp2c_internal/_badtype 2699637784 3362 ../functions/gp2c_internal/_cast 2617906549 160 ../functions/gp2c_internal/_cgetg 3976907664 521 ../functions/gp2c_internal/_const 2070064080 281 ../functions/gp2c_internal/_formatcode 1852686017 103 ../functions/gp2c_internal/_gc_needed 2727635652 193 ../functions/gp2c_internal/_gerepileall 1155278703 344 ../functions/gp2c_internal/_gerepileupto 2948757155 90 ../functions/gp2c_internal/_maxprime 151582740 76 ../functions/gp2c_internal/_norange 1798325487 181 ../functions/gp2c_internal/_prec 1600216421 227 ../functions/gp2c_internal/_stack_lim 667601403 171 ../functions/gp2c_internal/_strtoclosure 2356500495 894 ../functions/gp2c_internal/_tovec 1951489479 2718 ../functions/gp2c_internal/_typedef 915156773 521 ../functions/gp2c_internal/_wrap 2374239873 3976 ../functions/graphic/HEADER 2568396321 804 ../functions/graphic/plot 746613041 684 ../functions/graphic/plotarc 822504979 594 ../functions/graphic/plotbox 1957444111 434 ../functions/graphic/plotclip 4240951733 1598 ../functions/graphic/plotcolor 3345268327 865 ../functions/graphic/plotcopy 3696833048 259 ../functions/graphic/plotcursor 115836096 934 ../functions/graphic/plotdraw 3915673161 745 ../functions/graphic/plotexport 1605992861 5768 ../functions/graphic/ploth 4097218642 1156 ../functions/graphic/plothexport 1489229104 699 ../functions/graphic/plothraw 91878787 978 ../functions/graphic/plothrawexport 1134520510 948 ../functions/graphic/plothsizes 3709651595 1254 ../functions/graphic/plotinit 2952824737 413 ../functions/graphic/plotkill 3848799833 1230 ../functions/graphic/plotlines 700464643 463 ../functions/graphic/plotlinetype 3932741970 209 ../functions/graphic/plotmove 2000809460 1181 ../functions/graphic/plotpoints 3889451499 374 ../functions/graphic/plotpointsize 2487467433 454 ../functions/graphic/plotpointtype 2964473589 588 ../functions/graphic/plotrbox 2408927251 711 ../functions/graphic/plotrecth 848474344 941 ../functions/graphic/plotrecthraw 2759585312 462 ../functions/graphic/plotrline 3182540771 381 ../functions/graphic/plotrmove 4187634454 792 ../functions/graphic/plotrpoint 2564988267 726 ../functions/graphic/plotscale 50707378 903 ../functions/graphic/plotstring 2532812660 214 ../functions/graphic/psdraw 2965181765 553 ../functions/graphic/psploth 2051997768 237 ../functions/graphic/psplothraw 4064573955 6584 ../functions/hypergeometric_motives/HEADER 2201973449 406 ../functions/hypergeometric_motives/hgmalpha 3127835714 423 ../functions/hypergeometric_motives/hgmbydegree 3693989828 386 ../functions/hypergeometric_motives/hgmcoef 1292207120 833 ../functions/hypergeometric_motives/hgmcoefs 3358292523 507 ../functions/hypergeometric_motives/hgmcyclo 1442119425 1822 ../functions/hypergeometric_motives/hgmeulerfactor 4289962695 327 ../functions/hypergeometric_motives/hgmgamma 1271628860 1678 ../functions/hypergeometric_motives/hgminit 3812691460 684 ../functions/hypergeometric_motives/hgmissymmetrical 279540316 667 ../functions/hypergeometric_motives/hgmparams 878400648 535 ../functions/hypergeometric_motives/hgmtwist 3246594676 1736 ../functions/hypergeometric_motives/lfunhgm 2922408488 17164 ../functions/l_functions/HEADER 14139887 1941 ../functions/l_functions/lfun 1088202124 545 ../functions/l_functions/lfunan 2494053294 3179 ../functions/l_functions/lfunartin 2018781086 3766 ../functions/l_functions/lfuncheckfeq 4102847679 3437 ../functions/l_functions/lfunconductor 745504424 4621 ../functions/l_functions/lfuncost 2720060726 8080 ../functions/l_functions/lfuncreate 2439500948 555 ../functions/l_functions/lfundiv 4187481602 757 ../functions/l_functions/lfundual 2553933243 830 ../functions/l_functions/lfunetaquo 3929246084 654 ../functions/l_functions/lfuneuler 1475932671 668 ../functions/l_functions/lfungenus2 2027093440 1790 ../functions/l_functions/lfunhardy 3024123035 3356 ../functions/l_functions/lfuninit 1264553451 708 ../functions/l_functions/lfunlambda 1961812567 497 ../functions/l_functions/lfunlarge 1678756043 1479 ../functions/l_functions/lfunmfspec 2085012415 375 ../functions/l_functions/lfunmul 3979974256 956 ../functions/l_functions/lfunorderzero 2943347259 680 ../functions/l_functions/lfunparams 3717006344 845 ../functions/l_functions/lfunqf 1705669038 1542 ../functions/l_functions/lfunrootres 3553020805 991 ../functions/l_functions/lfunshift 514260304 534 ../functions/l_functions/lfunsympow 688750868 1270 ../functions/l_functions/lfuntheta 1116857530 1567 ../functions/l_functions/lfunthetacost 3291974018 1622 ../functions/l_functions/lfunthetainit 3173814062 609 ../functions/l_functions/lfuntwist 2403936520 1728 ../functions/l_functions/lfunzeros 971546508 913 ../functions/linear_algebra/HEADER 1726809161 2987 ../functions/linear_algebra/algdep 2158697995 2916 ../functions/linear_algebra/charpoly 2524905496 2578 ../functions/linear_algebra/concat 545812203 456 ../functions/linear_algebra/dirpowers 3468198776 1399 ../functions/linear_algebra/forqfvec 3377770560 2163 ../functions/linear_algebra/lindep 1791287332 1143 ../functions/linear_algebra/matadjoint 8398014 201 ../functions/linear_algebra/matcompanion 1233798593 2112 ../functions/linear_algebra/matconcat 4244789632 1300 ../functions/linear_algebra/matdet 717898806 1048 ../functions/linear_algebra/matdetint 3064778752 690 ../functions/linear_algebra/matdetmod 3118559761 594 ../functions/linear_algebra/matdiagonal 3298866236 1470 ../functions/linear_algebra/mateigen 3187933742 710 ../functions/linear_algebra/matfrobenius 1006778180 243 ../functions/linear_algebra/mathess 944253601 327 ../functions/linear_algebra/mathilbert 1961953847 3971 ../functions/linear_algebra/mathnf 1672341167 792 ../functions/linear_algebra/mathnfmod 1752167290 637 ../functions/linear_algebra/mathnfmodid 934145709 1552 ../functions/linear_algebra/mathouseholder 229723112 196 ../functions/linear_algebra/matid 3939387398 716 ../functions/linear_algebra/matimage 1659013314 551 ../functions/linear_algebra/matimagecompl 276605640 1016 ../functions/linear_algebra/matimagemod 1349303897 623 ../functions/linear_algebra/matindexrank 702550626 676 ../functions/linear_algebra/matintersect 1920196350 820 ../functions/linear_algebra/matinverseimage 3639348887 580 ../functions/linear_algebra/matinvmod 543305113 230 ../functions/linear_algebra/matisdiagonal 2838509711 1028 ../functions/linear_algebra/matker 2394284545 628 ../functions/linear_algebra/matkerint 2106323687 657 ../functions/linear_algebra/matkermod 1800646688 424 ../functions/linear_algebra/matmuldiagonal 2929869545 432 ../functions/linear_algebra/matmultodiagonal 3703545803 453 ../functions/linear_algebra/matpascal 3040530420 480 ../functions/linear_algebra/matpermanent 1550537839 952 ../functions/linear_algebra/matqr 4135328056 138 ../functions/linear_algebra/matrank 901802592 1611 ../functions/linear_algebra/matreduce 1540818694 689 ../functions/linear_algebra/matrix 3298561708 1611 ../functions/linear_algebra/matrixqz 2001534037 349 ../functions/linear_algebra/matsize 2980711687 2077 ../functions/linear_algebra/matsnf 2093097767 1727 ../functions/linear_algebra/matsolve 4053393855 1675 ../functions/linear_algebra/matsolvemod 3658421602 866 ../functions/linear_algebra/matsupplement 4081660555 207 ../functions/linear_algebra/mattranspose 2014071113 444 ../functions/linear_algebra/minpoly 928651325 883 ../functions/linear_algebra/norml2 2948798077 1470 ../functions/linear_algebra/normlp 2145426771 821 ../functions/linear_algebra/powers 2068726983 1297 ../functions/linear_algebra/qfauto 2469955322 783 ../functions/linear_algebra/qfautoexport 3369354527 202 ../functions/linear_algebra/qfbil 3539754947 311 ../functions/linear_algebra/qfcholesky 2255163178 2542 ../functions/linear_algebra/qfcvp 359818893 2659 ../functions/linear_algebra/qfeval 4185569529 1926 ../functions/linear_algebra/qfgaussred 2734886298 1267 ../functions/linear_algebra/qfisom 2710066504 1332 ../functions/linear_algebra/qfisominit 4164538816 878 ../functions/linear_algebra/qfjacobi 959685629 4276 ../functions/linear_algebra/qflll 3207814281 1828 ../functions/linear_algebra/qflllgram 569672782 6455 ../functions/linear_algebra/qfminim 3536494997 834 ../functions/linear_algebra/qfminimize 222278825 202 ../functions/linear_algebra/qfnorm 1719594423 821 ../functions/linear_algebra/qforbits 1443326811 918 ../functions/linear_algebra/qfparam 1316237961 642 ../functions/linear_algebra/qfperfection 3388145892 1110 ../functions/linear_algebra/qfrep 857968549 361 ../functions/linear_algebra/qfsign 1765905185 1188 ../functions/linear_algebra/qfsolve 3338722377 634 ../functions/linear_algebra/setbinop 2147124489 522 ../functions/linear_algebra/setdelta 2553744756 320 ../functions/linear_algebra/setintersect 2037144827 574 ../functions/linear_algebra/setisset 2943622176 366 ../functions/linear_algebra/setminus 2196969855 1684 ../functions/linear_algebra/setsearch 1510185044 290 ../functions/linear_algebra/setunion 2779027999 1334 ../functions/linear_algebra/snfrank 1447667609 396 ../functions/linear_algebra/trace 1002136033 2825 ../functions/linear_algebra/vecextract 2885474784 303 ../functions/linear_algebra/vecprod 275922367 1949 ../functions/linear_algebra/vecsearch 2038837655 4760 ../functions/linear_algebra/vecsort 3875591212 290 ../functions/linear_algebra/vecsum 435091307 1141 ../functions/linear_algebra/vector 326818666 444 ../functions/linear_algebra/vectorsmall 864292486 288 ../functions/linear_algebra/vectorv 2163373123 136 ../functions/member_functions/a1 3140155039 136 ../functions/member_functions/a2 2912778027 136 ../functions/member_functions/a3 3432772391 136 ../functions/member_functions/a4 1592124589 137 ../functions/member_functions/a6 3865780186 90 ../functions/member_functions/area 2455216452 137 ../functions/member_functions/b2 3948972502 136 ../functions/member_functions/b4 1332019359 143 ../functions/member_functions/b6 67273382 136 ../functions/member_functions/b8 3822771829 195 ../functions/member_functions/bid 2143476547 221 ../functions/member_functions/bnf 175549204 136 ../functions/member_functions/c4 655992956 136 ../functions/member_functions/c6 2702710967 266 ../functions/member_functions/clgp 1828862026 96 ../functions/member_functions/codiff 3653427790 286 ../functions/member_functions/cyc 71312838 199 ../functions/member_functions/diff 3827599499 249 ../functions/member_functions/disc 979383943 128 ../functions/member_functions/e 958863332 87 ../functions/member_functions/eta 1589707435 127 ../functions/member_functions/f 550066264 360 ../functions/member_functions/fu 892584628 335 ../functions/member_functions/gen 3330284290 203 ../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 859336903 96 ../functions/member_functions/normfu 22232489 93 ../functions/member_functions/omega 3263892110 151 ../functions/member_functions/orders 3555377828 230 ../functions/member_functions/p 1896741290 242 ../functions/member_functions/pol 1365247405 96 ../functions/member_functions/polabs 2389381105 189 ../functions/member_functions/r1 2681820181 189 ../functions/member_functions/r2 3310137925 236 ../functions/member_functions/reg 4264971167 254 ../functions/member_functions/roots 3731349347 194 ../functions/member_functions/sign 131338638 142 ../functions/member_functions/t2 482533715 90 ../functions/member_functions/tate 2008126926 133 ../functions/member_functions/tu 1665968088 171 ../functions/member_functions/zk 2924685257 142 ../functions/member_functions/zkst 2172758540 3597 ../functions/modular_forms/HEADER 2764705628 1387 ../functions/modular_forms/lfunmf 914924959 279 ../functions/modular_forms/mfDelta 3659793160 759 ../functions/modular_forms/mfEH 1757907359 370 ../functions/modular_forms/mfEk 506308813 827 ../functions/modular_forms/mfTheta 123344340 1125 ../functions/modular_forms/mfatkin 3650681655 1575 ../functions/modular_forms/mfatkineigenvalues 631472513 2609 ../functions/modular_forms/mfatkininit 2196174734 1289 ../functions/modular_forms/mfbasis 1585751440 396 ../functions/modular_forms/mfbd 1532842251 500 ../functions/modular_forms/mfbracket 1925309334 441 ../functions/modular_forms/mfcoef 3285616545 947 ../functions/modular_forms/mfcoefs 805528622 713 ../functions/modular_forms/mfconductor 3760954120 1053 ../functions/modular_forms/mfcosets 1727459882 485 ../functions/modular_forms/mfcuspisregular 972989511 542 ../functions/modular_forms/mfcusps 14625505 1440 ../functions/modular_forms/mfcuspval 3647183767 547 ../functions/modular_forms/mfcuspwidth 4292175409 563 ../functions/modular_forms/mfderiv 3838792512 653 ../functions/modular_forms/mfderivE2 3418216024 1160 ../functions/modular_forms/mfdescribe 2098612262 2827 ../functions/modular_forms/mfdim 1390846585 764 ../functions/modular_forms/mfdiv 267837459 2630 ../functions/modular_forms/mfeigenbasis 2050332233 1960 ../functions/modular_forms/mfeigensearch 3890174746 2414 ../functions/modular_forms/mfeisenstein 2521642861 3949 ../functions/modular_forms/mfembed 1406308623 1627 ../functions/modular_forms/mfeval 3713725971 1142 ../functions/modular_forms/mffields 1083308212 872 ../functions/modular_forms/mffromell 3763638024 1421 ../functions/modular_forms/mffrometaquo 2147771240 1866 ../functions/modular_forms/mffromlfun 1335679345 1625 ../functions/modular_forms/mffromqf 1685490775 1546 ../functions/modular_forms/mfgaloisprojrep 64268493 1590 ../functions/modular_forms/mfgaloistype 423810536 1838 ../functions/modular_forms/mfhecke 3574427693 651 ../functions/modular_forms/mfheckemat 2215792195 2856 ../functions/modular_forms/mfinit 925592325 950 ../functions/modular_forms/mfisCM 1038248754 564 ../functions/modular_forms/mfisequal 3200144333 855 ../functions/modular_forms/mfisetaquo 1051301032 1167 ../functions/modular_forms/mfkohnenbasis 3721057810 3135 ../functions/modular_forms/mfkohnenbijection 882754188 1355 ../functions/modular_forms/mfkohneneigenbasis 3217915747 1729 ../functions/modular_forms/mflinear 501483316 1408 ../functions/modular_forms/mfmanin 126187896 371 ../functions/modular_forms/mfmul 1494577808 272 ../functions/modular_forms/mfnumcusps 2159920547 2145 ../functions/modular_forms/mfparams 2435295308 982 ../functions/modular_forms/mfperiodpol 412069474 501 ../functions/modular_forms/mfperiodpolbasis 2347910057 2952 ../functions/modular_forms/mfpetersson 760307957 295 ../functions/modular_forms/mfpow 1737096900 2272 ../functions/modular_forms/mfsearch 3971986179 504 ../functions/modular_forms/mfshift 1183148343 1399 ../functions/modular_forms/mfshimura 1582351652 4035 ../functions/modular_forms/mfslashexpansion 2587544279 1076 ../functions/modular_forms/mfspace 4080458181 2616 ../functions/modular_forms/mfsplit 3219757938 794 ../functions/modular_forms/mfsturm 2870498029 1896 ../functions/modular_forms/mfsymbol 720730392 2951 ../functions/modular_forms/mfsymboleval 2943941359 887 ../functions/modular_forms/mftaylor 420545656 2946 ../functions/modular_forms/mftobasis 1271157075 661 ../functions/modular_forms/mftocoset 610324591 1032 ../functions/modular_forms/mftonew 2178723675 805 ../functions/modular_forms/mftraceform 3801097537 895 ../functions/modular_forms/mftwist 691237760 1585 ../functions/modular_symbols/HEADER 3868722818 858 ../functions/modular_symbols/msatkinlehner 2018839675 1701 ../functions/modular_symbols/mscosets 3421150940 1016 ../functions/modular_symbols/mscuspidal 2227159634 748 ../functions/modular_symbols/msdim 380662322 786 ../functions/modular_symbols/mseisenstein 2715169440 2295 ../functions/modular_symbols/mseval 86096288 2168 ../functions/modular_symbols/msfarey 4094635010 1604 ../functions/modular_symbols/msfromcusp 1352338764 2910 ../functions/modular_symbols/msfromell 3794680561 1203 ../functions/modular_symbols/msfromhecke 3907684130 270 ../functions/modular_symbols/msgetlevel 3236382025 389 ../functions/modular_symbols/msgetsign 4113320004 338 ../functions/modular_symbols/msgetweight 703025111 993 ../functions/modular_symbols/mshecke 3091640837 1757 ../functions/modular_symbols/msinit 3165782166 877 ../functions/modular_symbols/msissymbol 2559363212 1799 ../functions/modular_symbols/mslattice 1896035057 623 ../functions/modular_symbols/msnew 4010431783 562 ../functions/modular_symbols/msomseval 543748717 4231 ../functions/modular_symbols/mspadicL 3864084128 1980 ../functions/modular_symbols/mspadicinit 3031654940 1732 ../functions/modular_symbols/mspadicmoments 3483221821 3218 ../functions/modular_symbols/mspadicseries 513268602 2108 ../functions/modular_symbols/mspathgens 649423386 1384 ../functions/modular_symbols/mspathlog 1526805043 2016 ../functions/modular_symbols/mspetersson 2080319626 5975 ../functions/modular_symbols/mspolygon 779280992 1532 ../functions/modular_symbols/msqexpansion 2916281460 1482 ../functions/modular_symbols/mssplit 2452679244 571 ../functions/modular_symbols/msstar 1043779860 2550 ../functions/modular_symbols/mstooms 1681188692 23874 ../functions/number_fields/HEADER 1618809688 1482 ../functions/number_fields/bnfcertify 1133957 591 ../functions/number_fields/bnfdecodemodule 1775119394 6975 ../functions/number_fields/bnfinit 448074491 2205 ../functions/number_fields/bnfisintnorm 3338366683 1533 ../functions/number_fields/bnfisnorm 3556154536 3757 ../functions/number_fields/bnfisprincipal 137133072 223 ../functions/number_fields/bnfissunit 160222347 3395 ../functions/number_fields/bnfisunit 482552423 1371 ../functions/number_fields/bnflog 472132427 1172 ../functions/number_fields/bnflogdegree 1004410891 1000 ../functions/number_fields/bnflogef 418375524 841 ../functions/number_fields/bnfnarrow 1663077903 1019 ../functions/number_fields/bnfsignunit 116062908 1173 ../functions/number_fields/bnfsunit 2607099734 2518 ../functions/number_fields/bnfunits 1616726859 2874 ../functions/number_fields/bnrL1 637200104 1573 ../functions/number_fields/bnrchar 4133304516 2474 ../functions/number_fields/bnrclassfield 1191782344 1213 ../functions/number_fields/bnrclassno 826486578 1183 ../functions/number_fields/bnrclassnolist 643045254 917 ../functions/number_fields/bnrcompositum 1899346380 3002 ../functions/number_fields/bnrconductor 1271781537 250 ../functions/number_fields/bnrconductorofchar 3449216991 1501 ../functions/number_fields/bnrdisc 323813835 2631 ../functions/number_fields/bnrdisclist 4267484219 452 ../functions/number_fields/bnrgaloisapply 270546262 1929 ../functions/number_fields/bnrgaloismatrix 904190898 3539 ../functions/number_fields/bnrinit 4177597782 643 ../functions/number_fields/bnrisconductor 1212205629 1416 ../functions/number_fields/bnrisgalois 2929958103 3810 ../functions/number_fields/bnrisprincipal 2462557378 2249 ../functions/number_fields/bnrmap 654557403 1442 ../functions/number_fields/bnrrootnumber 4098166091 2248 ../functions/number_fields/bnrstark 1515941352 1216 ../functions/number_fields/bnrstarkunit 653819746 346 ../functions/number_fields/dirzetak 4174209850 1345 ../functions/number_fields/factornf 2931446518 1164 ../functions/number_fields/galoischardet 1065248769 1211 ../functions/number_fields/galoischarpoly 1429596676 2425 ../functions/number_fields/galoischartable 3534833210 1088 ../functions/number_fields/galoisconjclasses 1651383721 1335 ../functions/number_fields/galoisexport 1032866056 2011 ../functions/number_fields/galoisfixedfield 1159282924 852 ../functions/number_fields/galoisgetgroup 2070427432 1067 ../functions/number_fields/galoisgetname 2597143066 1600 ../functions/number_fields/galoisgetpol 690345336 1105 ../functions/number_fields/galoisidentify 677122357 4132 ../functions/number_fields/galoisinit 152362248 596 ../functions/number_fields/galoisisabelian 3491431523 559 ../functions/number_fields/galoisisnormal 667275024 865 ../functions/number_fields/galoispermtopol 1632911029 770 ../functions/number_fields/galoissplittinginit 797996563 2888 ../functions/number_fields/galoissubcyclo 591428712 418 ../functions/number_fields/galoissubfields 4103273387 814 ../functions/number_fields/galoissubgroups 2913140267 3962 ../functions/number_fields/gcharalgebraic 3937739836 1124 ../functions/number_fields/gcharconductor 1772759337 1877 ../functions/number_fields/gcharduallog 4189012887 830 ../functions/number_fields/gchareval 1748583524 2580 ../functions/number_fields/gcharidentify 100992195 3091 ../functions/number_fields/gcharinit 2084769224 1068 ../functions/number_fields/gcharisalgebraic 3013903078 2304 ../functions/number_fields/gcharlocal 4024357892 2096 ../functions/number_fields/gcharlog 1787519463 483 ../functions/number_fields/gcharnewprec 1377257741 1330 ../functions/number_fields/idealadd 3203583785 870 ../functions/number_fields/idealaddtoone 4018048897 1162 ../functions/number_fields/idealappr 861219273 2782 ../functions/number_fields/idealchinese 37252988 457 ../functions/number_fields/idealcoprime 1461034956 1112 ../functions/number_fields/idealdiv 2303980023 617 ../functions/number_fields/idealdown 3835115311 1180 ../functions/number_fields/idealfactor 2452548187 1824 ../functions/number_fields/idealfactorback 1035558903 967 ../functions/number_fields/idealfrobenius 1462460968 2141 ../functions/number_fields/idealhnf 2234579433 753 ../functions/number_fields/idealintersect 3755090162 414 ../functions/number_fields/idealinv 2698591307 1274 ../functions/number_fields/idealismaximal 1152325356 664 ../functions/number_fields/idealispower 2738792554 2896 ../functions/number_fields/ideallist 1707051004 1740 ../functions/number_fields/ideallistarch 3785296161 1619 ../functions/number_fields/ideallog 1577350712 385 ../functions/number_fields/idealmin 2984649330 1274 ../functions/number_fields/idealmul 2213617432 214 ../functions/number_fields/idealnorm 2339372410 393 ../functions/number_fields/idealnumden 1329404601 899 ../functions/number_fields/idealpow 1219598786 2183 ../functions/number_fields/idealprimedec 1631431866 780 ../functions/number_fields/idealprincipalunits 2435461408 1717 ../functions/number_fields/idealramgroups 990814423 2852 ../functions/number_fields/idealred 3147262865 1509 ../functions/number_fields/idealredmodpower 2608487038 3480 ../functions/number_fields/idealstar 222050625 2027 ../functions/number_fields/idealtwoelt 3391906004 542 ../functions/number_fields/idealval 2539008470 399 ../functions/number_fields/matalgtobasis 696298796 399 ../functions/number_fields/matbasistoalg 3113562104 1555 ../functions/number_fields/modreverse 701681069 478 ../functions/number_fields/newtonpoly 3047290607 580 ../functions/number_fields/nfalgtobasis 3664825099 6861 ../functions/number_fields/nfbasis 2678625060 569 ../functions/number_fields/nfbasistoalg 951961803 996 ../functions/number_fields/nfcertify 331184327 3369 ../functions/number_fields/nfcompositum 2724012169 341 ../functions/number_fields/nfdetint 2551476644 1873 ../functions/number_fields/nfdisc 920646811 1519 ../functions/number_fields/nfdiscfactors 1077247876 307 ../functions/number_fields/nfeltadd 1566392102 226 ../functions/number_fields/nfeltdiv 1658402628 406 ../functions/number_fields/nfeltdiveuc 1949924137 556 ../functions/number_fields/nfeltdivmodpr 4187029147 345 ../functions/number_fields/nfeltdivrem 453610871 1176 ../functions/number_fields/nfeltembed 2463674392 460 ../functions/number_fields/nfeltispower 1861534204 429 ../functions/number_fields/nfeltissquare 3820883555 423 ../functions/number_fields/nfeltmod 2424990877 225 ../functions/number_fields/nfeltmul 181341284 553 ../functions/number_fields/nfeltmulmodpr 1405889410 145 ../functions/number_fields/nfeltnorm 956877673 356 ../functions/number_fields/nfeltpow 487414851 546 ../functions/number_fields/nfeltpowmodpr 3760170244 359 ../functions/number_fields/nfeltreduce 3031199494 553 ../functions/number_fields/nfeltreducemodpr 4169492108 1200 ../functions/number_fields/nfeltsign 2932345806 150 ../functions/number_fields/nfelttrace 2871107810 1872 ../functions/number_fields/nfeltval 1517313719 1986 ../functions/number_fields/nffactor 3359409450 818 ../functions/number_fields/nffactorback 1780496781 1191 ../functions/number_fields/nffactormod 190387166 2202 ../functions/number_fields/nfgaloisapply 3820524320 2291 ../functions/number_fields/nfgaloisconj 1368256906 1925 ../functions/number_fields/nfgrunwaldwang 2796471532 785 ../functions/number_fields/nfhilbert 1790675536 798 ../functions/number_fields/nfhnf 868333029 539 ../functions/number_fields/nfhnfmod 3712705818 9997 ../functions/number_fields/nfinit 1575169407 243 ../functions/number_fields/nfisideal 3572420998 3773 ../functions/number_fields/nfisincl 2647928966 1623 ../functions/number_fields/nfisisom 2329778617 859 ../functions/number_fields/nfislocalpower 316659770 477 ../functions/number_fields/nfkermodpr 1958084487 12747 ../functions/number_fields/nflist 1930207446 1241 ../functions/number_fields/nfmodpr 2626564829 1299 ../functions/number_fields/nfmodprinit 2098480345 1024 ../functions/number_fields/nfmodprlift 2320135892 872 ../functions/number_fields/nfnewprec 3326201528 1431 ../functions/number_fields/nfpolsturm 2178630001 2293 ../functions/number_fields/nfresolvent 1867397709 1691 ../functions/number_fields/nfroots 1284874084 1236 ../functions/number_fields/nfrootsof1 167080484 1484 ../functions/number_fields/nfsnf 1591394803 825 ../functions/number_fields/nfsolvemodpr 3943942550 3020 ../functions/number_fields/nfsplitting 2665037414 1948 ../functions/number_fields/nfsubfields 212968194 1254 ../functions/number_fields/nfsubfieldscm 4186307171 519 ../functions/number_fields/nfsubfieldsmax 3922090884 831 ../functions/number_fields/nfweilheight 1693978776 4302 ../functions/number_fields/polcompositum 854365889 4433 ../functions/number_fields/polgalois 2083233566 1852 ../functions/number_fields/polred 1250646130 5419 ../functions/number_fields/polredabs 3443347329 2294 ../functions/number_fields/polredbest 2662778201 206 ../functions/number_fields/polredord 467085165 465 ../functions/number_fields/poltschirnhaus 963192925 481 ../functions/number_fields/rnfalgtobasis 853177983 1095 ../functions/number_fields/rnfbasis 2039453614 422 ../functions/number_fields/rnfbasistoalg 1430816044 577 ../functions/number_fields/rnfcharpoly 1433324071 2448 ../functions/number_fields/rnfconductor 2402783777 3538 ../functions/number_fields/rnfdedekind 2250737713 235 ../functions/number_fields/rnfdet 1017214625 1075 ../functions/number_fields/rnfdisc 3204583425 1377 ../functions/number_fields/rnfeltabstorel 453349198 1644 ../functions/number_fields/rnfeltdown 1886742098 506 ../functions/number_fields/rnfeltnorm 751825725 953 ../functions/number_fields/rnfeltreltoabs 2843220200 486 ../functions/number_fields/rnfelttrace 2399278483 1161 ../functions/number_fields/rnfeltup 925750965 2279 ../functions/number_fields/rnfequation 1364558493 692 ../functions/number_fields/rnfhnfbasis 988404631 1827 ../functions/number_fields/rnfidealabstorel 3524519381 482 ../functions/number_fields/rnfidealdown 1102145604 999 ../functions/number_fields/rnfidealfactor 1159049258 471 ../functions/number_fields/rnfidealhnf 2972910198 410 ../functions/number_fields/rnfidealmul 1270402441 572 ../functions/number_fields/rnfidealnormabs 190446714 445 ../functions/number_fields/rnfidealnormrel 901668763 1368 ../functions/number_fields/rnfidealprimedec 1672894403 1653 ../functions/number_fields/rnfidealreltoabs 3607329528 465 ../functions/number_fields/rnfidealtwoelt 3902195974 1427 ../functions/number_fields/rnfidealup 1505958724 5651 ../functions/number_fields/rnfinit 3000009520 440 ../functions/number_fields/rnfisabelian 982401208 542 ../functions/number_fields/rnfisfree 3322682039 856 ../functions/number_fields/rnfislocalcyclo 2423458846 2354 ../functions/number_fields/rnfisnorm 2615116728 1060 ../functions/number_fields/rnfisnorminit 3130773408 235 ../functions/number_fields/rnfkummer 1089289418 648 ../functions/number_fields/rnflllgram 2677163276 1247 ../functions/number_fields/rnfnormgroup 3652803496 794 ../functions/number_fields/rnfpolred 2256606757 2082 ../functions/number_fields/rnfpolredabs 190120013 1967 ../functions/number_fields/rnfpolredbest 856485954 1954 ../functions/number_fields/rnfpseudobasis 1343463579 1090 ../functions/number_fields/rnfsteinitz 3884469918 3966 ../functions/number_fields/subcyclohminus 1205378073 9899 ../functions/number_fields/subcycloiwasawa 3200996679 8807 ../functions/number_fields/subcyclopclgp 2853957401 2603 ../functions/number_fields/subgrouplist 958766459 7206 ../functions/number_theoretical/HEADER 319433823 1118 ../functions/number_theoretical/addprimes 2530633408 2149 ../functions/number_theoretical/bestappr 3301826492 2808 ../functions/number_theoretical/bestapprPade 4094208100 1565 ../functions/number_theoretical/bestapprnf 798602991 183 ../functions/number_theoretical/bezout 3857964875 371 ../functions/number_theoretical/bigomega 2120475524 1590 ../functions/number_theoretical/charconj 2515377567 1835 ../functions/number_theoretical/chardiv 2250104283 3300 ../functions/number_theoretical/chareval 954408128 1382 ../functions/number_theoretical/chargalois 1947336649 1649 ../functions/number_theoretical/charker 1881117649 1835 ../functions/number_theoretical/charmul 3663193423 1430 ../functions/number_theoretical/charorder 1803084616 1747 ../functions/number_theoretical/charpow 1030355832 2323 ../functions/number_theoretical/chinese 1326553114 1774 ../functions/number_theoretical/content 511520010 2970 ../functions/number_theoretical/contfrac 3111182226 1548 ../functions/number_theoretical/contfracpnqn 2499936007 663 ../functions/number_theoretical/core 2382430166 1130 ../functions/number_theoretical/coredisc 4003493065 334 ../functions/number_theoretical/dirdiv 1567149522 1594 ../functions/number_theoretical/direuler 3248385615 696 ../functions/number_theoretical/dirmul 2243617241 2260 ../functions/number_theoretical/dirpowerssum 602142895 2013 ../functions/number_theoretical/divisors 2873598316 914 ../functions/number_theoretical/divisorslenstra 1170752562 529 ../functions/number_theoretical/eulerphi 1028656049 11680 ../functions/number_theoretical/factor 3674214786 1156 ../functions/number_theoretical/factorback 553502735 216 ../functions/number_theoretical/factorcantor 281252418 217 ../functions/number_theoretical/factorff 4089779703 347 ../functions/number_theoretical/factorial 4071279235 2086 ../functions/number_theoretical/factorint 2497115143 2517 ../functions/number_theoretical/factormod 3993275197 1946 ../functions/number_theoretical/factormodDDF 3485920492 1715 ../functions/number_theoretical/factormodSQF 945288923 2527 ../functions/number_theoretical/factormodcyclo 3955182425 706 ../functions/number_theoretical/ffcompomap 1803100425 550 ../functions/number_theoretical/ffembed 4235280246 1140 ../functions/number_theoretical/ffextend 3434862096 486 ../functions/number_theoretical/fffrobenius 132000441 2257 ../functions/number_theoretical/ffgen 768122628 705 ../functions/number_theoretical/ffinit 1385673258 546 ../functions/number_theoretical/ffinvmap 2671651824 1853 ../functions/number_theoretical/fflog 3346756452 739 ../functions/number_theoretical/ffmap 3380876000 972 ../functions/number_theoretical/ffmaprel 3536314595 659 ../functions/number_theoretical/ffnbirred 3573775947 860 ../functions/number_theoretical/fforder 2513176948 1119 ../functions/number_theoretical/ffprimroot 2364146333 2420 ../functions/number_theoretical/gcd 80527233 1123 ../functions/number_theoretical/gcdext 3795182337 996 ../functions/number_theoretical/halfgcd 514753190 536 ../functions/number_theoretical/hilbert 1454102710 751 ../functions/number_theoretical/isfundamental 4121111175 479 ../functions/number_theoretical/ispolygonal 1821027022 1305 ../functions/number_theoretical/ispower 2327997766 484 ../functions/number_theoretical/ispowerful 2623979849 2465 ../functions/number_theoretical/isprime 1296292670 473 ../functions/number_theoretical/isprimepower 2741429874 1783 ../functions/number_theoretical/ispseudoprime 2253778002 892 ../functions/number_theoretical/ispseudoprimepower 2145272082 1852 ../functions/number_theoretical/issquare 2416987201 1505 ../functions/number_theoretical/issquarefree 3038253040 442 ../functions/number_theoretical/istotient 756622456 758 ../functions/number_theoretical/kronecker 1213553243 1521 ../functions/number_theoretical/lcm 3438528644 1088 ../functions/number_theoretical/logint 3545414909 192 ../functions/number_theoretical/moebius 1760766114 893 ../functions/number_theoretical/nextprime 1077510865 221 ../functions/number_theoretical/numdiv 3812027075 362 ../functions/number_theoretical/omega 1410087852 914 ../functions/number_theoretical/precprime 2133349761 466 ../functions/number_theoretical/prime 4107496435 5553 ../functions/number_theoretical/primecert 3351612942 1686 ../functions/number_theoretical/primecertexport 2108644896 994 ../functions/number_theoretical/primecertisvalid 2667350565 508 ../functions/number_theoretical/primepi 530053972 619 ../functions/number_theoretical/primes 331153143 2872 ../functions/number_theoretical/qfbclassno 3095522958 409 ../functions/number_theoretical/qfbcomp 3625849896 709 ../functions/number_theoretical/qfbcompraw 2574501538 1886 ../functions/number_theoretical/qfbcornacchia 2391602383 510 ../functions/number_theoretical/qfbhclassno 2791455274 868 ../functions/number_theoretical/qfbnucomp 558791724 559 ../functions/number_theoretical/qfbnupow 3990771123 263 ../functions/number_theoretical/qfbpow 1772003685 337 ../functions/number_theoretical/qfbpowraw 3733007031 515 ../functions/number_theoretical/qfbprimeform 2782618505 980 ../functions/number_theoretical/qfbred 1073154760 804 ../functions/number_theoretical/qfbredsl2 385331812 2567 ../functions/number_theoretical/qfbsolve 1242582706 3304 ../functions/number_theoretical/quadclassunit 193928221 546 ../functions/number_theoretical/quaddisc 3224357765 927 ../functions/number_theoretical/quadgen 1926712746 577 ../functions/number_theoretical/quadhilbert 4097923580 630 ../functions/number_theoretical/quadpoly 296258046 614 ../functions/number_theoretical/quadray 1354104147 527 ../functions/number_theoretical/quadregulator 1721973451 1511 ../functions/number_theoretical/quadunit 825092283 1239 ../functions/number_theoretical/quadunitindex 3253928125 2736 ../functions/number_theoretical/quadunitnorm 4273519065 1869 ../functions/number_theoretical/ramanujantau 89022859 1788 ../functions/number_theoretical/randomprime 3397278150 476 ../functions/number_theoretical/removeprimes 405726717 467 ../functions/number_theoretical/sigma 171740624 864 ../functions/number_theoretical/sqrtint 2690659814 547 ../functions/number_theoretical/sqrtnint 2974277127 329 ../functions/number_theoretical/sumdedekind 45823112 646 ../functions/number_theoretical/sumdigits 3908097898 1794 ../functions/number_theoretical/znchar 1917301301 672 ../functions/number_theoretical/zncharconductor 1943510786 1235 ../functions/number_theoretical/znchardecompose 2561623165 858 ../functions/number_theoretical/znchargauss 1624891559 1771 ../functions/number_theoretical/zncharinduce 3052952462 799 ../functions/number_theoretical/zncharisodd 1672199863 1265 ../functions/number_theoretical/znchartokronecker 2105254873 1111 ../functions/number_theoretical/znchartoprimitive 162654972 2973 ../functions/number_theoretical/znconreychar 3388554123 1656 ../functions/number_theoretical/znconreyconductor 3039326590 1151 ../functions/number_theoretical/znconreyexp 283352914 3112 ../functions/number_theoretical/znconreylog 1371955527 3342 ../functions/number_theoretical/zncoppersmith 3670773598 2809 ../functions/number_theoretical/znlog 1064531178 653 ../functions/number_theoretical/znorder 3798044820 713 ../functions/number_theoretical/znprimroot 3411767478 1497 ../functions/number_theoretical/znstar 572010617 3259 ../functions/number_theoretical/znsubgroupgenerators 2996965796 14547 ../functions/operators/HEADER 864331270 1381 ../functions/operators/cmp 3774435241 1121 ../functions/operators/divrem 3296351109 1061 ../functions/operators/lex 1135166453 549 ../functions/operators/max 3564597594 549 ../functions/operators/min 436724662 554 ../functions/operators/shift 1951617964 427 ../functions/operators/shiftmul 7811629 371 ../functions/operators/sign 389485380 1135 ../functions/operators/vecmax 188138455 1164 ../functions/operators/vecmin 2841547568 364 ../functions/polynomials/HEADER 3791116713 864 ../functions/polynomials/O 3011886622 215 ../functions/polynomials/bezoutres 16562608 1543 ../functions/polynomials/deriv 3681490931 1528 ../functions/polynomials/derivn 358483601 1976 ../functions/polynomials/diffop 739426567 1572 ../functions/polynomials/eval 1158623582 1497 ../functions/polynomials/factorpadic 42420981 866 ../functions/polynomials/fft 3353070706 948 ../functions/polynomials/fftinv 1249194359 1397 ../functions/polynomials/intformal 1789061079 1002 ../functions/polynomials/padicappr 1004474463 1847 ../functions/polynomials/padicfields 1224768464 1253 ../functions/polynomials/polchebyshev 267560605 4439 ../functions/polynomials/polclass 256565163 953 ../functions/polynomials/polcoef 200036886 415 ../functions/polynomials/polcoeff 2744430592 906 ../functions/polynomials/polcyclo 3980671021 912 ../functions/polynomials/polcyclofactors 2708846191 739 ../functions/polynomials/poldegree 1164468517 761 ../functions/polynomials/poldisc 1442110150 1388 ../functions/polynomials/poldiscfactors 1885087402 528 ../functions/polynomials/poldiscreduced 2364763803 495 ../functions/polynomials/polfromroots 2115316789 253 ../functions/polynomials/polgraeffe 2496200914 1138 ../functions/polynomials/polhensellift 4116895175 966 ../functions/polynomials/polhermite 2063139150 4332 ../functions/polynomials/polinterpolate 3088205224 702 ../functions/polynomials/polisclass 2307608903 439 ../functions/polynomials/poliscyclo 4075425120 497 ../functions/polynomials/poliscycloprod 556665398 461 ../functions/polynomials/polisirreducible 1482292260 763 ../functions/polynomials/pollaguerre 1042964227 610 ../functions/polynomials/pollead 1345451495 734 ../functions/polynomials/pollegendre 1587746623 1706 ../functions/polynomials/polmodular 2411229890 389 ../functions/polynomials/polrecip 2322201769 2275 ../functions/polynomials/polresultant 3717931312 827 ../functions/polynomials/polresultantext 4265729483 1168 ../functions/polynomials/polroots 4183027327 1172 ../functions/polynomials/polrootsbound 3035207304 220 ../functions/polynomials/polrootsff 355568271 1154 ../functions/polynomials/polrootsmod 841390103 1743 ../functions/polynomials/polrootspadic 984343485 1837 ../functions/polynomials/polrootsreal 1729570334 1651 ../functions/polynomials/polsturm 1589296745 1374 ../functions/polynomials/polsubcyclo 3730730276 2325 ../functions/polynomials/polsubcyclofast 2574219514 654 ../functions/polynomials/polsylvestermatrix 368684839 285 ../functions/polynomials/polsym 1394365540 206 ../functions/polynomials/poltchebi 2139889059 1139 ../functions/polynomials/polteichmuller 2681566361 1235 ../functions/polynomials/poltomonic 3167722811 1047 ../functions/polynomials/polzagier 958579215 819 ../functions/polynomials/seralgdep 3289616872 347 ../functions/polynomials/serconvol 870122772 1069 ../functions/polynomials/serdiffdep 1994069365 355 ../functions/polynomials/serlaplace 1323530505 398 ../functions/polynomials/serreverse 3042221738 1156 ../functions/polynomials/subst 1375279982 1105 ../functions/polynomials/substpol 823911739 954 ../functions/polynomials/substvec 3054066516 1042 ../functions/polynomials/sumformal 3932378219 704 ../functions/polynomials/taylor 888039775 3201 ../functions/polynomials/thue 252434491 3723 ../functions/polynomials/thueinit 1483431287 2352 ../functions/programming/HEADER 3300553752 136 ../functions/programming/_eval_mnemonic 3140964717 1110 ../functions/programming/addhelp 493900223 2255 ../functions/programming/alarm 783261713 1839 ../functions/programming/alias 1026484244 4578 ../functions/programming/allocatemem 2067385586 1806 ../functions/programming/apply 3879478973 414 ../functions/programming/arity 1649867724 490 ../functions/programming/break 3771928985 675 ../functions/programming/breakpoint 1823031531 1591 ../functions/programming/call 2216268478 1471 ../functions/programming/dbg_down 2271483609 697 ../functions/programming/dbg_err 1432496240 1501 ../functions/programming/dbg_up 2402371989 460 ../functions/programming/dbg_x 3392358724 1795 ../functions/programming/default 1793335746 399 ../functions/programming/errname 603005284 748 ../functions/programming/error 2474340705 705 ../functions/programming/export 1194109331 484 ../functions/programming/exportall 3990237234 391 ../functions/programming/extern 81173858 448 ../functions/programming/externstr 1065557842 2156 ../functions/programming/fileclose 2542719211 670 ../functions/programming/fileextern 1676029392 1174 ../functions/programming/fileflush 1400882701 1511 ../functions/programming/fileopen 2104785430 1126 ../functions/programming/fileread 271526954 643 ../functions/programming/filereadstr 753917633 1930 ../functions/programming/filewrite 4009707671 434 ../functions/programming/filewrite1 488356218 721 ../functions/programming/fold 3226933152 505 ../functions/programming/for 1954918890 1492 ../functions/programming/forcomposite 2479540670 1115 ../functions/programming/fordiv 1291061302 1398 ../functions/programming/fordivfactored 695416760 410 ../functions/programming/foreach 1871912845 1240 ../functions/programming/forell 2396477606 2103 ../functions/programming/forfactored 3926056354 2639 ../functions/programming/forpart 1214097269 1355 ../functions/programming/forperm 3988325140 2443 ../functions/programming/forprime 249901433 1797 ../functions/programming/forprimestep 3981882691 3461 ../functions/programming/forsquarefree 3133784800 1264 ../functions/programming/forstep 3772915069 2071 ../functions/programming/forsubgroup 4218503910 1900 ../functions/programming/forsubset 1926104899 2945 ../functions/programming/forvec 1330788876 424 ../functions/programming/getabstime 848335686 1748 ../functions/programming/getcache 748638207 252 ../functions/programming/getenv 1277212506 377 ../functions/programming/getheap 2430171541 221 ../functions/programming/getlocalbitprec 1919323846 243 ../functions/programming/getlocalprec 3575456435 442 ../functions/programming/getrand 4109487323 285 ../functions/programming/getstack 321312975 460 ../functions/programming/gettime 1949647775 352 ../functions/programming/getwalltime 3405041162 186 ../functions/programming/global 3826315804 2391 ../functions/programming/if 2634821475 10245 ../functions/programming/iferr 2484595388 542 ../functions/programming/inline 132054800 746 ../functions/programming/input 48605405 3591 ../functions/programming/install 728681860 1461 ../functions/programming/kill 2457647283 400 ../functions/programming/listcreate 3182242847 989 ../functions/programming/listinsert 995454973 396 ../functions/programming/listkill 934093209 835 ../functions/programming/listpop 1161671186 1420 ../functions/programming/listput 3477779139 1200 ../functions/programming/listsort 3065531026 125 ../functions/programming/local 980090815 2712 ../functions/programming/localbitprec 605742576 2248 ../functions/programming/localprec 3283018625 1831 ../functions/programming/mapapply 2224027908 296 ../functions/programming/mapdelete 1070089863 515 ../functions/programming/mapget 1176031438 902 ../functions/programming/mapisdefined 4099077580 460 ../functions/programming/mapput 2557836032 115 ../functions/programming/my 1218387207 521 ../functions/programming/next 462093051 794 ../functions/programming/parapply 63325746 1647 ../functions/programming/pareval 3796072151 3350 ../functions/programming/parfor 2609287920 1421 ../functions/programming/parforeach 1368851928 1756 ../functions/programming/parforprime 2294808388 1650 ../functions/programming/parforprimestep 2024608162 1815 ../functions/programming/parforstep 2749632765 1369 ../functions/programming/parforvec 514508727 2709 ../functions/programming/parploth 1330440243 1550 ../functions/programming/parplothexport 1371166073 589 ../functions/programming/parselect 628313012 1215 ../functions/programming/parsum 3003736710 744 ../functions/programming/parvector 1444530435 523 ../functions/programming/print 3789576485 502 ../functions/programming/print1 2618318352 7946 ../functions/programming/printf 1358563963 545 ../functions/programming/printp 3111049586 448 ../functions/programming/printsep 2335454252 480 ../functions/programming/printsep1 2009192526 698 ../functions/programming/printtex 140826310 446 ../functions/programming/quit 2739616152 1071 ../functions/programming/read 1942540668 384 ../functions/programming/readstr 2278186691 967 ../functions/programming/readvec 1182439920 287 ../functions/programming/return 1551258894 2793 ../functions/programming/select 1322415785 464 ../functions/programming/self 130403798 1245 ../functions/programming/setdebug 2998711322 1179 ../functions/programming/setrand 3763351284 720 ../functions/programming/strchr 3702191002 896 ../functions/programming/strexpand 2297074237 404 ../functions/programming/strjoin 1705797358 843 ../functions/programming/strprintf 2070897358 746 ../functions/programming/strsplit 392034217 1692 ../functions/programming/strtex 2125678549 507 ../functions/programming/strtime 2763502895 708 ../functions/programming/system 2048671112 2337 ../functions/programming/trap 722695522 608 ../functions/programming/type 741533573 254 ../functions/programming/unexport 4195192425 232 ../functions/programming/unexportall 3745664244 248 ../functions/programming/uninline 3467212281 421 ../functions/programming/until 2159054194 2381 ../functions/programming/version 1726224819 474 ../functions/programming/warning 3388937499 932 ../functions/programming/whatnow 746214195 394 ../functions/programming/while 2121888344 607 ../functions/programming/write 3017938263 302 ../functions/programming/write1 1005368995 1973 ../functions/programming/writebin 862293014 382 ../functions/programming/writetex 2486050372 5671 ../functions/sums/HEADER 1621644360 3280 ../functions/sums/asympnum 2291482599 2042 ../functions/sums/asympnumraw 2283401931 538 ../functions/sums/contfraceval 3679057495 1104 ../functions/sums/contfracinit 1962684901 2415 ../functions/sums/derivnum 4129426728 853 ../functions/sums/intcirc 3572524183 3374 ../functions/sums/intfuncinit 807254804 14208 ../functions/sums/intnum 909253658 1452 ../functions/sums/intnumgauss 643348599 2047 ../functions/sums/intnumgaussinit 2297386156 2511 ../functions/sums/intnuminit 2127132606 7148 ../functions/sums/intnumosc 1413128883 2957 ../functions/sums/intnumromb 2304554308 1899 ../functions/sums/laurentseries 1111706963 6651 ../functions/sums/limitnum 4108257086 1434 ../functions/sums/prod 2233145501 1163 ../functions/sums/prodeuler 1726594371 460 ../functions/sums/prodeulerrat 2982733825 958 ../functions/sums/prodinf 480693658 390 ../functions/sums/prodnumrat 4097258167 1172 ../functions/sums/solve 2451756291 1254 ../functions/sums/solvestep 2514999189 612 ../functions/sums/sum 3684625915 3355 ../functions/sums/sumalt 138855 447 ../functions/sums/sumdiv 4040523349 557 ../functions/sums/sumdivmult 1539062858 449 ../functions/sums/sumeulerrat 3723450792 2092 ../functions/sums/suminf 4097333435 5960 ../functions/sums/sumnum 2329697884 5281 ../functions/sums/sumnumap 852512804 1056 ../functions/sums/sumnumapinit 179885008 999 ../functions/sums/sumnuminit 2665781031 1972 ../functions/sums/sumnumlagrange 926065207 2359 ../functions/sums/sumnumlagrangeinit 1474809527 961 ../functions/sums/sumnummonien 3862465646 3213 ../functions/sums/sumnummonieninit 3123675574 830 ../functions/sums/sumnumrat 90058678 1443 ../functions/sums/sumnumsidi 1651328906 2985 ../functions/sums/sumpos 655643124 1286 ../functions/symbolic_operators/add 3353925834 892 ../functions/symbolic_operators/adde 2541595476 175 ../functions/symbolic_operators/and 2032936095 312 ../functions/symbolic_operators/call 506843558 1213 ../functions/symbolic_operators/coeff 2209173128 720 ../functions/symbolic_operators/compr 127902765 330 ../functions/symbolic_operators/concat 1071666145 433 ../functions/symbolic_operators/deriv 2771382347 1134 ../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 3256172146 1404 ../functions/symbolic_operators/eq 57471919 155 ../functions/symbolic_operators/fact 2828464303 790 ../functions/symbolic_operators/ge 4062103410 781 ../functions/symbolic_operators/gt 1241340661 226 ../functions/symbolic_operators/hist 3054781206 139 ../functions/symbolic_operators/id 541828836 846 ../functions/symbolic_operators/le 551395660 778 ../functions/symbolic_operators/lt 308195135 531 ../functions/symbolic_operators/mm 1539470791 566 ../functions/symbolic_operators/mod 481421093 476 ../functions/symbolic_operators/mode 2256836712 2240 ../functions/symbolic_operators/mul 328650357 839 ../functions/symbolic_operators/mule 3480119288 1183 ../functions/symbolic_operators/ne 2046019002 426 ../functions/symbolic_operators/neg 2872656097 196 ../functions/symbolic_operators/not 38177253 185 ../functions/symbolic_operators/or 2690812802 323 ../functions/symbolic_operators/pl 1215908021 440 ../functions/symbolic_operators/pound 4022455874 1765 ../functions/symbolic_operators/pow 3316274994 547 ../functions/symbolic_operators/pp 584520199 165 ../functions/symbolic_operators/prim 350299153 195 ../functions/symbolic_operators/range 4292091533 259 ../functions/symbolic_operators/shiftl 2222950945 363 ../functions/symbolic_operators/shiftle 996959190 322 ../functions/symbolic_operators/shiftr 3408057925 372 ../functions/symbolic_operators/shiftre 3157788552 440 ../functions/symbolic_operators/slice 3090980148 1152 ../functions/symbolic_operators/sub 3687286192 892 ../functions/symbolic_operators/sube 3333748126 198 ../functions/symbolic_operators/trans 1446727822 377 ../functions/transcendental/Catalan 3531045925 324 ../functions/transcendental/Euler 1513866586 6609 ../functions/transcendental/HEADER 4128767667 143 ../functions/transcendental/I 1222736203 302 ../functions/transcendental/Pi 3738391333 842 ../functions/transcendental/abs 2339613425 479 ../functions/transcendental/acos 592137614 351 ../functions/transcendental/acosh 186570540 526 ../functions/transcendental/agm 2556575741 313 ../functions/transcendental/airy 3152531199 197 ../functions/transcendental/arg 668572464 481 ../functions/transcendental/asin 3156798169 375 ../functions/transcendental/asinh 3981886920 470 ../functions/transcendental/atan 1569300605 336 ../functions/transcendental/atanh 3530878593 210 ../functions/transcendental/besselh1 2048100008 210 ../functions/transcendental/besselh2 2126874998 366 ../functions/transcendental/besseli 450143907 366 ../functions/transcendental/besselj 797914394 445 ../functions/transcendental/besseljh 3129693820 1205 ../functions/transcendental/besseljzero 2577688153 201 ../functions/transcendental/besselk 3434416903 186 ../functions/transcendental/besseln 2615660860 201 ../functions/transcendental/bessely 2767697159 1185 ../functions/transcendental/besselyzero 1895190969 570 ../functions/transcendental/cos 2528223261 226 ../functions/transcendental/cosh 4095583565 215 ../functions/transcendental/cotan 1065986826 242 ../functions/transcendental/cotanh 1523019734 244 ../functions/transcendental/dilog 2372227520 1237 ../functions/transcendental/eint1 1654893041 520 ../functions/transcendental/ellE 2440317000 324 ../functions/transcendental/ellK 2407436017 803 ../functions/transcendental/erfc 2405880717 1111 ../functions/transcendental/eta 492867808 389 ../functions/transcendental/exp 2543012091 994 ../functions/transcendental/expm1 1261150765 1242 ../functions/transcendental/gamma 2489052783 171 ../functions/transcendental/gammah 3059793509 693 ../functions/transcendental/gammamellininv 2650659893 1168 ../functions/transcendental/gammamellininvasymp 1577006853 1662 ../functions/transcendental/gammamellininvinit 4181646734 3620 ../functions/transcendental/hypergeom 1286907864 412 ../functions/transcendental/hyperu 2245224633 631 ../functions/transcendental/incgam 365056377 413 ../functions/transcendental/incgamc 1486022150 1110 ../functions/transcendental/lambertw 2623693756 335 ../functions/transcendental/lerchphi 3971412717 529 ../functions/transcendental/lerchzeta 1692552864 1581 ../functions/transcendental/lngamma 920776823 1095 ../functions/transcendental/log 3710999345 881 ../functions/transcendental/log1p 2306425294 1656 ../functions/transcendental/polylog 4274799556 2029 ../functions/transcendental/polylogmult 1865129753 583 ../functions/transcendental/psi 790594428 540 ../functions/transcendental/rootsof1 4206765734 566 ../functions/transcendental/sin 3853852547 389 ../functions/transcendental/sinc 2962576545 222 ../functions/transcendental/sinh 457651119 1134 ../functions/transcendental/sqr 1089254052 820 ../functions/transcendental/sqrt 215829221 1523 ../functions/transcendental/sqrtn 609352200 201 ../functions/transcendental/tan 1423729606 228 ../functions/transcendental/tanh 925526747 2375 ../functions/transcendental/teichmuller 526496096 235 ../functions/transcendental/theta 2416355895 480 ../functions/transcendental/thetanullk 4055211105 1021 ../functions/transcendental/weber 1470425465 1325 ../functions/transcendental/zeta 1518592193 1974 ../functions/transcendental/zetahurwitz 3914074715 1784 ../functions/transcendental/zetamult 2648343084 3003 ../functions/transcendental/zetamultall 4149901674 945 ../functions/transcendental/zetamultconvert 811137904 839 ../functions/transcendental/zetamultdual pari-2.17.2/src/test/0000755000175000017500000000000014760315601012735 5ustar billbillpari-2.17.2/src/test/32/0000755000175000017500000000000014760315601013161 5ustar billbillpari-2.17.2/src/test/32/equal0000644000175000017500000000134414760137411014216 0ustar billbill[1, 0, 1, 0] [0, 0] [1, 0] [0, 1] [1, 0] [0, 1] [0, 0, 1] [0, 0, 1] [0, 0, 1] [0, 0, 0, 1, 1] 1 0 [0, 0, 0, 1] 0 [0, 1] [0, 0, 0, 1] [1, 1] 1 1 0 [0, 1] [0, 1] 1 0 [0, 1] [0, 1] 1 0 0 1 0 1 *** _+_: Warning: normalizing a series with 0 leading term. *** _+_: Warning: normalizing a series with 0 leading term. [0, 0] [1, 1] [1, 1] [0, 0] [1, 0] [0, 1] [0, 0] [1, 0] [0, 1] [0, 0] [0, 0] [1, 0] [0, 1] [1, 0] [0, 0] [1, 0] [0, 0] [1, 0] [0, 1] [0, 0] [0, 0] [0, 0] [0, 0] [1, 0] [0, 0] [0, 0] [1, 0] [0, 1] [1, 1] [1, 0] [0, 0] [1, 0] [0, 0] [0, 0] [0, 1] 1 1 0 1 0 1 [[1, 1], [1, 1], [0, 0]] [1, 1] [1, 1] *** _+_: Warning: normalizing a series with 0 leading term. [0, 0] [1, 1] [1, 1] [0, 0] [1, 1] [1, 1] 0 1 1 Total time spent: 5 pari-2.17.2/src/test/32/valuation0000644000175000017500000000166614567450071015125 0ustar billbill+oo +oo +oo +oo 0 0 0 0 0 -1 0 0 ERROR ERROR 0 0 0 ERROR 0 0 ERROR 0 0 0 ERROR ERROR 0 0 1 0 0 0 ERROR 1 0 0 0 0 ERROR 0 1 0 0 0 0 1 1 ERROR *** at top-level: valuation(0,1) *** ^-------------- *** valuation: domain error in gvaluation: p = 1 *** at top-level: valuation(0,-1) *** ^--------------- *** valuation: domain error in gvaluation: p = -1 *** at top-level: valuation(0,0) *** ^-------------- *** valuation: domain error in gvaluation: p = 0 *** at top-level: valuation(0,I) *** ^-------------- *** valuation: domain error in gvaluation: p = I 2 0 2 1.0000000000000000000000000000000000000 - 1.00000000000000000000000000000000 00000*x + O(x^2) 1 O(x) -oo -oo -oo 2 2 2 1 1 +oo +oo +oo *** at top-level: valuation(Pi) *** ^------------- *** valuation: incorrect type in gvaluation (t_REAL). Total time spent: 1 pari-2.17.2/src/test/32/ranges0000644000175000017500000000455014567450071014375 0ustar billbill[1267650600228229401496703205376, 1267650600228229401496703205377, 126765060 0228229401496703205378, 1267650600228229401496703205379] [5, 10, 26, 50, 122, 170, 290, 362, 530, 842, 962, 1370] [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173] [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37] [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37] [2, 5, 10, 17, 26, 37, 50, 65, 82, 101, 5, 13, 29, 53, 85, 10, 13, 25, 34, 5 8, 73, 109, 17, 25, 41, 65, 97, 26, 29, 34, 41, 61, 74, 89, 106, 37, 61, 85, 50, 53, 58, 65, 74, 85, 113, 130, 149, 65, 73, 89, 113, 145, 82, 85, 97, 10 6, 130, 145, 181, 101, 109, 149, 181] [13, 29, 53, 13, 34, 58, 29, 34, 74, 53, 58, 74] [[1, 1, 1], [2, 1, 1], [2, 2, 1], [2, 2, 2], [3, 1, 1], [3, 2, 1], [3, 2, 2] , [3, 3, 1], [3, 3, 2], [3, 3, 3], [4, 1, 1], [4, 2, 1], [4, 2, 2], [4, 3, 1 ], [4, 3, 2], [4, 3, 3], [4, 4, 1], [4, 4, 2], [4, 4, 3], [4, 4, 4], [5, 1, 1], [5, 2, 1], [5, 2, 2], [5, 3, 1], [5, 3, 2], [5, 3, 3], [5, 4, 1], [5, 4, 2], [5, 4, 3], [5, 4, 4], [5, 5, 1], [5, 5, 2], [5, 5, 3], [5, 5, 4], [5, 5 , 5]] [7, 11, 13, 17] [2, 3] [1, 2, 3, 4] [3, 4, 5] [1, 2, 4, 5] [] [] [] [] [] List([2, 3]) List([1, 2, 3, 4]) List([3, 4, 5]) List([1, 2, 4, 5]) List([]) List([]) List([]) List([]) List([]) Vecsmall([2, 3]) Vecsmall([1, 2, 3, 4]) Vecsmall([3, 4, 5]) Vecsmall([1, 2, 4, 5]) [7 12] [8 13] [1, 2]~ [1, 6, 11, 16] [1 6 11 16 21] [2 7 12 17 22] [3 8 13 18 23] [1 6 11] [2 7 12] [3 8 13] [4 9 14] [5 10 15] [1 6 11 16] [2 7 12 17] [3 8 13 18] [4 9 14 19] [5 10 15 20] [1 6 11 16] [2 7 12 17] [3 8 13 18] [4 9 14 19] [13 18 23] [14 19 24] [15 20 25] [ 6 11] [ 7 12] [ 9 14] [10 15] [1, 3, 4, 5]~ [1, 6, 11, 21] [1 6 11 16 21] [2 7 12 17 22] [4 9 14 19 24] [5 10 15 20 25] [1 6 16 21] [2 7 17 22] [3 8 18 23] [4 9 19 24] [5 10 20 25] [1 6 11 16] [2 7 12 17] [3 8 13 18] [4 9 14 19] [1 6 11 21] [2 7 12 22] [3 8 13 23] [4 9 14 24] [13 18 23] [14 19 24] [15 20 25] [;] [1, [2, 2]] [3, [1, 4]] [0, 3, 4, [3, 4], 0, I] [0, 3, 4, [3, 4], 0, I] [1, 4] [2, 4] [1, 3] [] [2, 3, 3, 4, 4, 4, 5, 5, 5, 5] [2, 3, 3, 4, 4, 4, 5, 5, 5, 5] [0, 1, 2, 3, 4, 5] 123 *** this should be a small integer: vector(3)[1..2]! *** ^---------------- Total time spent: 0 pari-2.17.2/src/test/32/bnrmap0000644000175000017500000000275014567450071014375 0ustar billbill[Mat([4, 3]), [12, 4], [6]] [3] [2] [2] [4]~ [Mat(6), Mat(2), Mat(6), Mat(2), Mat(6), Mat(2), Mat(6), Mat(2), Mat(3), Mat (1), Mat(6), Mat(2), Mat(3), Mat(1), Mat(6), Mat(2), Mat(3), Mat(1), Mat(3), Mat(1), Mat(6), Mat(2), Mat(3), Mat(1), Mat(6), Mat(2), Mat(3), Mat(1), Mat (3), Mat(1)] *** at top-level: bnrmap(1,2) *** ^----------- *** bnrmap: incorrect type in bnrmap [not a map] (t_INT). *** at top-level: bnrmap(bnr,bnrinit(x,1)) *** ^------------- *** bnrinit: incorrect type in checkbnf [please apply bnfinit()] (t_POL). *** at top-level: bnrmap(S,[1,2,3]) *** ^----------------- *** bnrmap: incorrect type in bnrmap [not a character mod mA] (t_VEC). *** at top-level: bnrmap(S,[1,2]/2) *** ^----------------- *** bnrmap: incorrect type in bnrmap [not a character mod mA] (t_VEC). *** at top-level: bnrmap(S,[1,2,3]~) *** ^------------------ *** bnrmap: incorrect type in bnrmap [not a discrete log] (t_COL). *** at top-level: bnrmap(S,[1,2]~/2) *** ^------------------ *** bnrmap: incorrect type in bnrmap [not a discrete log] (t_COL). *** at top-level: bnrmap(S,matid(3)) *** ^------------------ *** bnrmap: inconsistent dimensions in ZM_hnfmod. *** at top-level: bnrmap(S,matid(2)/2) *** ^-------------------- *** bnrmap: incorrect type in bnrmap [not a subgroup] (t_MAT). Total time spent: 1 pari-2.17.2/src/test/32/nflistQT0000644000175000017500000000136414567450071014662 0ustar billbill1: [20] 2: [19] 3: [20, 20] 4: [19, 18, 19, 20, 19] 5: [20, 20, 17, 20, 19] 6: [19, 19, 16, 20, 20, 20, 19, 19, 16, 20, 17, 20, 16, 18, 20, 19] 7: [20, 16, 20, 19, 20, 20, 20] x^25 + t*x + 1 x^25 + 625*t*x^24 + x + 529*t x^24 - 24*x^23 + (t^2 + 20880467999847912034355032910567) x^23 + 529*t*x^22 - x - 441*t x^22 - 22*x^21 + (-t^2 + 5842587018385982521381124421) x^47 + t*x + 1 x^47 + 2209*t*x^46 - x - 2025*t x x^2 - t*x + 1 x^3 + 9*t*x^2 - x - t *** at top-level: nflist([4,6]) *** ^------------- *** nflist: incorrect group 4Tk with k = 6 not in [1,5]. *** at top-level: nflist([18,100000]) *** ^------------------- *** nflist: incorrect group 18Tk with k = 100000 not in [1,983]. Total time spent: 1062 pari-2.17.2/src/test/32/factorint0000644000175000017500000000263014676526175015116 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] *** factorint: Warning: MPQS: number too big to be factored with MPQS, giving up. [17 1] [588235294117647058823529411764705882352941176470588235294117647058823529411 76470588235294117647058823529411764705882353 1] [ 10000019 2] [ 10000000019 1] [100000000003 1] [ 10000019 1] [ 10000000019 2] [100000000003 1] [ 10000019 1] [ 10000000019 1] [100000000003 2] [ 10000019 3] [100000000003 1] [ 10000019 4] [100000000003 1] [ 10000019 5] [100000000003 1] [1000000000000003 1] [14902357 1] [67103479 1] [59571877 1] [78857659 4] [147597991521418023508489862273738173631206614533316977514777121647857029787 8078949377407337049389289382748507531496480477281264838760259191814463365330 2695404969612011134301569023960939890902262593269350252814096149834993882228 3144859860183431853623092377264139020949023183644689960821079548296376309423 6630945410832793769905399982457186322944729636418890623372171723742105636440 3682184596496329485386969058726504869144346374575072804418236768135178520993 4866084717257940842231667809767022401199028017047489448742692474210882353680 8485072502240519452587542875349976558572670229633962575212637477897785501552 646522609988869914013540483809865681250419497686697771007 1] Total time spent: 290 pari-2.17.2/src/test/32/programming0000644000175000017500000002515314676526175015454 0ustar billbill 0.9999836 |'''''xx'''''''''''''''''''''''''"''''''''''''"_'''''''''''''''| | " " x : | | " " : : | | : : " _ _ | | _ : x : : | | : : : _ : : | | : x : : " : | | " : : : : | | : : " x x | | " : x _ : | |x : : __" : | "---------x--------""x--------:-------------------:-------_""--- | : x : : " | | : " : _ x _| | : " x : :| | : " : : x : | _ _ : : : " | : : _ : : : | | : : : : x " | | : " : " : | | " " : x | -0.996405 |............_"..........._x........................"_.........| 0 10 plotrecth: [-0.9999983407361126009, 0.9999991516154969062, -0.99994514927518 22990, 1.0000000000000000000] alarm: [7, 1; 13, 1] forqfvec: [0, 0, 0, 1]~ [0, 0, 1, 0]~ [0, 1, 0, 0]~ [1, 0, 0, 0]~ matrix: [[1, 1], [1, 2], [1, 3]; [2, 1], [2, 2], [2, 3]] vector: [2, 3, 4] vectorsmall: Vecsmall([4, 5, 6]) vectorv: [3, 4, 5]~ direuler: [1, 0, -1, 0, 1, 0, -1, 0, 1, 0] for: 1 2 3 forcomposite: 4 6 8 9 10 fordiv: 1 2 3 5 6 10 15 30 fordivfactored: [1, matrix(0,2)] [2, Mat([2, 1])] [3, Mat([3, 1])] [5, Mat([ 5, 1])] [6, [2, 1; 3, 1]] [10, [2, 1; 5, 1]] [15, [3, 1; 5, 1]] [30, [2, 1; 3, 1; 5, 1]] foreach: 2 3 5 7 forell: 11a1 14a1 15a1 17a1 19a1 20a1 21a1 24a1 26a1 26b1 27a1 30a1 32a1 33a 1 34a1 35a1 36a1 37a1 37b1 38a1 38b1 39a1 40a1 42a1 43a1 44a1 45a1 46a1 48a1 49a1 50a1 50b1 51a1 52a1 53a1 54a1 54b1 55a1 56a1 56b1 57a1 57b1 57c1 58a1 58b1 61a1 62a1 63a1 64a1 65a1 66a1 66b1 66c1 67a1 69a1 70a1 72a1 73a1 75a1 7 5b1 75c1 76a1 77a1 77b1 77c1 78a1 79a1 80a1 80b1 82a1 83a1 84a1 84b1 85a1 88 a1 89a1 89b1 90a1 90b1 90c1 91a1 91b1 92a1 92b1 94a1 96a1 96b1 98a1 99a1 99b 1 99c1 99d1 100a1 forfactored: unsupported forpart: Vecsmall([5]) Vecsmall([1, 4]) Vecsmall([2, 3]) Vecsmall([1, 1, 3]) Vecsmall([1, 2, 2]) Vecsmall([1, 1, 1, 2]) Vecsmall([1, 1, 1, 1, 1]) forpart: Vecsmall([5]) Vecsmall([1, 4]) Vecsmall([2, 3]) Vecsmall([1, 1, 3]) Vecsmall([1, 2, 2]) forprime: 2 3 5 7 forprimestep: 7 13 19 forsquarefree: unsupported forstep: 1 4 7 10 13 16 19 forstep(vec): 1 3 7 9 13 15 19 21 forsubgroup: [0, 0] [0, 1] [0, 1] [0, 1] [0, 1] [0, 1] [0, 1] [1, 1] forsubset: Vecsmall([]) Vecsmall([1]) Vecsmall([2]) Vecsmall([3]) Vecsmall([ 4]) Vecsmall([5]) Vecsmall([1, 2]) Vecsmall([1, 3]) Vecsmall([1, 4]) Vecsmal l([1, 5]) Vecsmall([2, 3]) Vecsmall([2, 4]) Vecsmall([2, 5]) Vecsmall([3, 4] ) Vecsmall([3, 5]) Vecsmall([4, 5]) Vecsmall([1, 2, 3]) Vecsmall([1, 2, 4]) Vecsmall([1, 2, 5]) Vecsmall([1, 3, 4]) Vecsmall([1, 3, 5]) Vecsmall([1, 4, 5]) Vecsmall([2, 3, 4]) Vecsmall([2, 3, 5]) Vecsmall([2, 4, 5]) Vecsmall([3, 4, 5]) Vecsmall([1, 2, 3, 4]) Vecsmall([1, 2, 3, 5]) Vecsmall([1, 2, 4, 5]) Vecsmall([1, 3, 4, 5]) Vecsmall([2, 3, 4, 5]) Vecsmall([1, 2, 3, 4, 5]) forvec: [1, 1] [1, 2] [2, 1] [2, 2] [3, 1] [3, 2] iferr: error("domain error in zeta: argument = 1") parfor: [2, 6, 20, 70, 252, 924, 3432, 12870, 48620, 184756] parforeach: [0, 6, 20, 0, 252, 0, 3432, 0, 0, 0, 705432, 0, 10400600, 0, 0, 0, 2333606220, 0, 35345263800, 0] parforprime: [0, 6, 20, 0, 252, 0, 3432, 0, 0, 0, 705432, 0, 10400600, 0, 0, 0, 2333606220, 0, 35345263800, 0] parforprimestep: [0, 0, 0, 0, 0, 0, 3432, 0, 0, 0, 0, 0, 10400600, 0, 0, 0, 0, 0, 35345263800, 0] parforstep: [2, 0, 0, 70, 0, 0, 3432, 0, 0, 184756, 0, 0, 10400600, 0, 0, 60 1080390, 0, 0, 35345263800, 0, 0, 2104098963720, 0, 0, 126410606437752, 0, 0 , 7648690600760440, 0, 0, 465428353255261088, 0, 0, 28453041475240576740, 0, 0, 1746130564335626209832, 0, 0, 107507208733336176461620, 0, 0, 6637553085 023755473070800, 0, 0, 410795449442059149332177040, 0, 0, 254776122589808569 02730428600, 0, 0, 1583065848125949175357548128136, 0, 0, 985272185300938567 75578873054432, 0, 0, 6141219157058215937976400809912720, 0, 0, 383291933432 261050330199012527412832, 0, 0, 23951146041928082866135587776380551750, 0, 0 , 1498293301493043187508381577755872596600, 0, 0, 93820969697840041204785894 580506297666600, 0, 0, 5880298213015725960249409584793845897453000, 0, 0, 36 8861487637974401172285738046404563498888040, 0, 0, 2315600649402119195634270 7682359261381151378400, 0, 0, 1454706556296192477283016662986999417820887445 240, 0, 0, 91448418451315549893681152591738975450186892788720, 0, 0, 5752360 192132899378974200736267010150178656638229000, 0, 0, 36204872548972843105844 2528694228154899210914562189600, 0, 0, 2279936782421731549104699877923028868 5596678611381812000, 0, 0, 1436477076900698392827654028972389210647869585188 175999800, 0, 0, 90548514656103281165404177077484163874504589675413336841320 ] parforstep: [2, 0, 0, 70, 0, 0, 3432, 0, 0, 184756, 0, 0, 10400600, 0, 0, 60 1080390, 0, 0, 35345263800, 0, 0, 2104098963720, 0, 0, 126410606437752, 0, 0 , 7648690600760440, 0, 0, 465428353255261088, 0, 0, 28453041475240576740, 0, 0, 1746130564335626209832, 0, 0, 107507208733336176461620, 0, 0, 6637553085 023755473070800, 0, 0, 410795449442059149332177040, 0, 0, 254776122589808569 02730428600, 0, 0, 1583065848125949175357548128136, 0, 0, 985272185300938567 75578873054432, 0, 0, 6141219157058215937976400809912720, 0, 0, 383291933432 261050330199012527412832, 0, 0, 23951146041928082866135587776380551750, 0, 0 , 1498293301493043187508381577755872596600, 0, 0, 93820969697840041204785894 580506297666600, 0, 0, 5880298213015725960249409584793845897453000, 0, 0, 36 8861487637974401172285738046404563498888040, 0, 0, 2315600649402119195634270 7682359261381151378400, 0, 0, 1454706556296192477283016662986999417820887445 240, 0, 0, 91448418451315549893681152591738975450186892788720, 0, 0, 5752360 192132899378974200736267010150178656638229000, 0, 0, 36204872548972843105844 2528694228154899210914562189600, 0, 0, 2279936782421731549104699877923028868 5596678611381812000, 0, 0, 1436477076900698392827654028972389210647869585188 175999800, 0, 0, 90548514656103281165404177077484163874504589675413336841320 ] parforstep: [2, 0, 0, 70, 252, 0, 3432, 12870, 0, 184756, 705432, 0, 1040060 0, 40116600, 0, 601080390, 2333606220, 0, 35345263800, 137846528820, 0, 2104 098963720, 8233430727600, 0, 126410606437752, 495918532948104, 0, 7648690600 760440, 30067266499541040, 0, 465428353255261088, 1832624140942590534, 0, 28 453041475240576740, 112186277816662845432, 0, 1746130564335626209832, 689262 0648693261354600, 0, 107507208733336176461620, 424784580848791721628840, 0, 6637553085023755473070800, 26248505381684851188961800, 0, 410795449442059149 332177040, 1625701140345170250548615520, 0, 25477612258980856902730428600, 1 00891344545564193334812497256, 0, 1583065848125949175357548128136, 627252505 8612251449529907677520, 0, 98527218530093856775578873054432, 390590044887157 789360330532465784, 0, 6141219157058215937976400809912720, 24356699707654619 143838606602026720, 0, 383291933432261050330199012527412832, 152080347781187 4490019821888415218656, 0, 23951146041928082866135587776380551750, 950676258 27960698145584333020095113100, 0, 1498293301493043187508381577755872596600, 5949105755928259715106809205795376486500, 0, 9382096969784004120478589458050 6297666600, 372641034574519600278163693967644731577200, 0, 58802982130157259 60249409584793845897453000, 23362265873332749085315221863910685052043000, 0, 368861487637974401172285738046404563498888040, 1465865132691170996866486179 768828525073503120, 0, 23156006494021191956342707682359261381151378400, 9204 5125813734238026462263037378063990076729140, 0, 1454706556296192477283016662 986999417820887445240, 5783773055153536355462596370912166360010757312400, 0, 91448418451315549893681152591738975450186892788720, 36366696639941765190277 8537050868948883301364345840, 0, 5752360192132899378974200736267010150178656 638229000, 22880174247360071687155809670095748237789263482394000, 0, 3620487 25489728431058442528694228154899210914562189600, 144032427749174571486293440 7631385920577295594888710800, 0, 2279936782421731549104699877923028868559667 8611381812000, 90717484605833107953850163563674201296374152790550788800, 0, 1436477076900698392827654028972389210647869585188175999800, 5716592448890534 420436582360196242777068052430850904489000, 0, 0] parforvec: [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]] parforvec: [[0, 0], [0, 1], [0, 2], 0, [1, 1], [1, 2], 0, 0, [2, 2]] parforvec: [0, [0, 1], [0, 2], 0, 0, [1, 2], 0, 0, 0] parsum:6 parvector: [2, 3, 4] derivnum: -0.060000000000000000000000000000000000000 intcirc: 1.0000000003834650205392024121352628410 + 0.E-59*I intfuncinit: 1.0916613635090773890740687217432928561 intnum: 0.78539816339744830961566084581987572105 intnumgauss: 0.78539816339744830961566084581987572105 intnumromb: 0.78539816339744830961566084581987553429 prod: 3628800 prodeuler: 210.00000000000000000000000000000000000 prodinf: 0.28878809508660242127889972192923078009 solve: 4.4934094579090641753078809272803220822 solvestep [1.7724538509055160272981674833411451828, 2.5066282746310005024157 652848110452530, 3.0699801238394654654386548746677945821, 7.5198848238930015 072472958544331357590, 8.5003900517896968140560669406685714434] solvestep [1.7724538509055160272981674833411451828, 2.5066282746310005024157 652848110452530, 3.0699801238394654654386548746677945821, 7.5198848238930015 072472958544331357590, 8.5003900517896968140560669406685714434]1 sum: 55 sumalt: 0.82246703342411321823620758332301259461 sumdiv: 72 sumdivmult: 30 suminf: 0.10201133481780999545662780292332172394 sumnum : 1.6449340668482264364724151666460251892 sumnumap : 1.6449340668482264364724151666460251892 sumnumlagrange : 1.6449340668482264364724151666460251892 sumnummonien : 1.6449340668482264364724151666460251892 sumpos : 1.6449340668482264364724151666460251892 compr: [5, 10, 26, 50, 122, 170, 290, 362, 530, 842] compr: [5, 10, 26, 50] Total time spent: 151 pari-2.17.2/src/test/32/prime0000644000175000017500000000260314567450071014227 0ustar billbill500009 8161 17863 38873 84017 180503 386093 821641 1742537 3681131 7754077 16290047 172 309 564 1028 1900 3512 6542 12251 23000 43390 82025 155611 295947 56416 3 1077871 2063689 3957809 8161 17863 38873 84017 180503 386093 821641 1742537 3681131 7754077 16290047 172 309 564 1028 1900 3512 6542 12251 23000 43390 82025 155611 295947 56416 3 1077871 2063689 3957809 203280221 0 200000 [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229] [2, 3, 5] [2, 3, 5] [11, 13, 17, 19] [4294967197, 4294967231, 4294967279, 4294967291, 4294967311, 4294967357, 429 4967371, 4294967377, 4294967387, 4294967389] [18446744073709551521, 18446744073709551533, 18446744073709551557, 184467440 73709551629, 18446744073709551653, 18446744073709551667, 1844674407370955169 7, 18446744073709551709] 5758 61938 2 4294967311 18446744073709551629 3 2 *** at top-level: primes([1,Pol(2)]) *** ^------------------ *** primes: incorrect type in primes_interval (t_POL). *** at top-level: nextprime(x) *** ^------------ *** nextprime: incorrect type in nextprime (t_POL). *** at top-level: precprime(x) *** ^------------ *** precprime: incorrect type in nextprime (t_POL). Total time spent: 446 pari-2.17.2/src/test/32/aurifeuille0000644000175000017500000000031311636712103015404 0ustar billbill2818034765526617919871 13851033738067865242961762796990508103341 2818034765526617919871 48975219025052205901 288943522443730350379346314566889 73194743542229 97 13 818201 13 1741 31 Total time spent: 16 pari-2.17.2/src/test/32/ellsea0000644000175000017500000000170214676526175014371 0ustar billbill *** Warning: new stack size = 12000000 (11.444 Mbytes). 1: -18627161351017007203 2: 18827282990304904850 3: -311256626765211726406998 4: -1156815323986765479761266 5: 8021839135157401454666601928 6: 69384671472347162238655401774 7: -28652256072001057705168347198 8: 1271547588042840381566950172346 9: 1854715558584444 10: 20420247695 11: -4742075250 1:896615193897208487551655423042 2:1160030981035862058695525039892 3:529656639561669286549173325490 4:817701636704152445708337225413 5:983440823277044783790077069060 6:383857664397975740685677977539 7:72057594489895556 -40969318 -110835623989511 1117171998037413284268510092133116644930606283206233885810244262747345986 0 1048845330393999479019082 0 1237940049661719722719792298 486 1267650600228229268303269105757 1267650600228228204181264322228 0 0 0 1048845330396436420140511 0 1048845330395135782279169 1048845330395135782279169 1048845330396436420140511 1048845330396436420140511 Total time spent: 3302 pari-2.17.2/src/test/32/nfweilheight0000644000175000017500000000005614676526175015602 0ustar billbill1 1 1 1 1 1 1 1 1 1 1 1 Total time spent: 114 pari-2.17.2/src/test/32/gammamellininv0000644000175000017500000000167214567450071016120 0ustar billbill2.9297691204814688720898602967358431836 E-19976 2.0000000000000000000000000000000000000 -115 -131 -192 -189 -192 -184 -188 [1] [1, -3/64, 105/8192, -3465/524288, 675675/134217728, -43648605/8589934592, 7 027425405/1099511627776, -677644592625/70368744177664, 609202488769875/36028 797018963968, -78180986058800625/2305843009213693952] [1] 0.086427836527544499548835474343456022551 0.086427836527544499548835474343456022551 *** at top-level: gammamellininvasymp([]) *** ^----------------------- *** gammamellininvasymp: incorrect type in gammamellininvasymp (t_VEC). *** at top-level: gammamellininvinit([]) *** ^---------------------- *** gammamellininvinit: incorrect type in gammamellininvinit (t_VEC). *** at top-level: gammamellininvinit(x,-2) *** ^------------------------ *** gammamellininvinit: domain error in gammamellininvinit: derivation order < 0 Total time spent: 1870 pari-2.17.2/src/test/32/rnf0000644000175000017500000016245014760123736013707 0ustar billbill[[1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [6, 6, 6, 6]] [[1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [6, 6, 6, 6]] [] [[1, 0, 0, 0, 0, [-361894/1129, 99/1129]~, [-724429/1129, 1480/1129]~, [-929 3266/21451, 168/1129]~, [-18602992/21451, 39304/21451]~; 0, 1, 0, 0, 0, [167 146/1129, -108/1129]~, [334588/1129, -808/1129]~, [15473737/21451, 392/1129] ~, [30974892/21451, -39940/21451]~; 0, 0, 1, 0, 0, [-253060/1129, 328/1129]~ , [-506568/1129, 1552/1129]~, [-5866950/21451, -227/1129]~, [-11744297/21451 , 12168/21451]~; 0, 0, 0, 1, 0, [-68390/1129, 171/1129]~, [-136901/1129, 584 /1129]~, [486725/21451, 165/1129]~, [974315/21451, 4540/21451]~; 0, 0, 0, 0, 1, [90512/1129, -384/1129]~, [181184/1129, -1088/1129]~, [-5551416/21451, - 403/1129]~, [-11112673/21451, 4368/21451]~; 0, 0, 0, 0, 0, [-564/1129, -1/11 29]~, -1, 9/19, [20340/21451, -36/21451]~; 0, 0, 0, 0, 0, 1, [2260/1129, -4/ 1129]~, 7/19, [15820/21451, -28/21451]~; 0, 0, 0, 0, 0, 0, 0, [-18619/21451, -1/1129]~, [-37271/21451, 28/21451]~; 0, 0, 0, 0, 0, 0, 0, 1/19, [2260/2145 1, -4/21451]~], [1, 1, 1, 1, 1, 1, 1, 1, [1, 0; 0, 1]], 1, 1] [[[1, 0, 0; 0, 1, 0; 0, 0, 1], [1, 1, 1]], [1, 0, 0; 0, 1, 0; 0, 0, 1]] [[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 1; 0, 0, 0, 1, 0, 0, 0, 0, -1, -1, 1; 0, 0, 0, 0, 1, 0, 0, 0, 1, -1, 1; 0, 0, 0, 0, 0, 1, 0, 0, -1, 1, 0; 0, 0, 0, 0, 0, 0, 1, 0, 1, -1, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, -1; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 ; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1/3, 1/3, 1/3], 6487513772307278389925284499624661, 648751 3772307278389925284499624661] [[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 1; 0, 0, 0, 1, 0, 0, 0, 0, -1, -1, 1; 0, 0, 0, 0, 1, 0, 0, 0, 1, -1, 1; 0, 0, 0, 0, 0, 1, 0, 0, -1, 1, 0; 0, 0, 0, 0, 0, 0, 1, 0, 1, -1, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, -1; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 ; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1/3, 1/3, 1/3], 6487513772307278389925284499624661, 648751 3772307278389925284499624661] [[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 1; 0, 0, 0, 1, 0, 0, 0, 0, -1, -1, 1; 0, 0, 0, 0, 1, 0, 0, 0, 1, -1, 1; 0, 0, 0, 0, 0, 1, 0, 0, -1, 1, 0; 0, 0, 0, 0, 0, 0, 1, 0, 1, -1, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, -1; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 ; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1/3, 1/3, 1/3], 6487513772307278389925284499624661, 648751 3772307278389925284499624661] [[1, -2018006054; 0, 1], [1, [1/1009003027, 3/4036012108; 0, 1/4036012108]], [4036, 3027; 0, 1009], [0, -1009]~] [[1, -2018006054; 0, 1], [1, [1/1009003027, 3/4036012108; 0, 1/4036012108]], [4036, 3027; 0, 1009], [0, -1009]~] [[1, -2018006054; 0, 1], [1, [1/1009003027, 3/4036012108; 0, 1/4036012108]], [4036, 3027; 0, 1009], [0, -1009]~] [[1, -2018006054; 0, 1], [1, [1/1009003027, 3/4036012108; 0, 1/4036012108]], [4036, 3027; 0, 1009], [0, -1009]~] [[4036, 3027; 0, 1009], [0, -1009]~] [[4, 3; 0, 1], [0, -1009]~] [[4036, 3027; 0, 1009], [0, -1009]~] [[1, -2018006054; 0, 1], [1, [1/1009003027, 3/4036012108; 0, 1/4036012108]], [4036, 3027; 0, 1009], [0, -1009]~] [[1, -2018006054; 0, 1], [1, [1/1009003027, 3/4036012108; 0, 1/4036012108]], [4036, 3027; 0, 1009], [0, -1009]~] [[Mat(861), [1]], [[[;], [;], [;], [;], []~, 0, [y, [1, 0], 1, 1, [Mat(1), M at(1), Mat(16), Mat(1), 1, Mat(1), [1, 0], []], [0.E-57], [1], Mat(1), Mat(1 )], [[1, [], []], 1, 1, [2, -1], []], [[;], [;], [;], [], [;], [;]], [0, 0, 0]], [[Mat(861), [1]], [960, [120, 2, 2, 2], [808, 286, 575, [-860]~]], [[[3 , [3]~, 1, 1, 1], 1; [7, [7]~, 1, 1, 1], 1; [41, [41]~, 1, 1, 1], 1], [[3, [ 3]~, 1, 1, 1], 1; [7, [7]~, 1, 1, 1], 1; [41, [41]~, 1, 1, 1], 1]], [[[[2], [-286], Mat(3), [[1, [1], [3, [3]~, 1, 1, 1]]~, 2, [2, Mat([2, 1])]]], [[6], [493], Mat(7), [[1, [1], [7, [7]~, 1, 1, 1]]~, 3, [6, [2, 1; 3, 1]]]], [[40 ], [211], Mat(41), [[1, [1], [41, [41]~, 1, 1, 1]]~, 6, [40, [2, 3; 5, 1]]]] ], [[2], Vecsmall([1]), Mat(1/861), 861861/2000, Mat(861)]], [[0; 0; 1; 0], [-20; 1; 0; 0], [3; -1; 0; 0], [0; 0; 0; 1]]], [], [[;], [1, 0, 0, 0; 0, 1, 0, -1; 0, 0, 1, -1], [1, 0, 0; 0, -1, 0; 0, 0, -1; 0, 0, 0]], [480, [120, 2, 2], [808, 286, 575]], [Mat([0, 0, 0, 1]), Mat(-2), 1]], [1, 0, 0; 0, 2, 0; 0, 0, 2]] [[Mat(861), [1]], [[3, [3]~, 1, 1, 1], 1; [7, [7]~, 1, 1, 1], 1; [41, [41]~, 1, 1, 1], 1]] [[Mat(861), [1]], [[3, [3]~, 1, 1, 1], 1; [7, [7]~, 1, 1, 1], 1; [41, [41]~, 1, 1, 1], 1]] [[Mat(861), [1]], [[3, [3]~, 1, 1, 1], 1; [7, [7]~, 1, 1, 1], 1; [41, [41]~, 1, 1, 1], 1]] [[Mat(117), [0]], [[3, [3]~, 1, 1, 1], 2; [13, [13]~, 1, 1, 1], 1]] [Mat(3), Mat(1)] [[Mat(3), Mat(1)], [0, -1; 1, 1], [1, 1; -1/3, 0]] [Mat(4), Mat(4)] [[Mat(4), Mat(4)], [1, 0; 0, 1], [1/2, 0; 0, 1/2]] [3 1] [0 1] [[8, 2; 0, 1], [2, 0; 0, 1], [1, 0; 0, 1]] 1 1 1 0 1 1 [1, y] [1, 2] [1, 2] [x, -1] [1, 2] -28124/93*x^3 + 14062/31*x^2 + 562480/93*x + 166769/31 Mod(x^5 + x^2 + 2, x^6 + x^5 + x^4 + x^3 + x^2 + x + 1) Mod(z^2, z^3 + z^2 - 2*z - 1) [[1, 0, 0; 0, 1, 0; 0, 0, 1], [1, 1, 1]] [[-7299, -3342, -2170]~ [28944, 9855, -18888]~ [-403109721, -130243536, 3134 63442]~ [14327960067, -6668848710, -6564138180]~] [[-8931, -7002, -4889]~ [1757, 2965, 3850]~ [37941889, 4175158, -24594320]~ [-6449565004, 4002663648, -4747437435]~] [[1582, 287, -979]~ [-22620, -7713, 17845]~ [345203944, 119358263, -27416790 8]~ [-12604280171, -1376229454, 7984127400]~] [[16328, 10812, 8737]~ [-12774, -6624, -161]~ [81698859, 24909626, -61460862 ]~ [2425192175, 6514839743, 3707931485]~] [0 1 0 0] [0 0 1 0] [0 0 0 1] [[2148564093, 1880231385, 101485359; 0, 87, 9; 0, 0, 3], [1, 0, 0; 0, 1, 0; 0, 0, 1], [1, 0, 0; 0, 1, 0; 0, 0, 1]] [1 [-1335, -25, 865]~ [15231, -65250, -69787]~] [0 1 [-389, -202, -196]~] [0 0 1] [[122218751/716188031, 92116373/716188031, -100209652/716188031]~ [358, 179, -331]~ 0] [[-51524140/716188031, -1828617/716188031, 31588281/716188031]~ [-169, -40, 121]~ [-2, -11, 6]~] [[-4650644/24696139, -2252334/24696139, 2933316/24696139]~ [-377, -145, 319] ~ [4, 0, 7]~] [1 0 0] [0 1 0] [0 0 1] [[1, -1/2; 0, 1], [1, 1]] [Mod(1/6*y - 2/3, y^2 - 40), -3] [Mod(-1/2*y + 4, y^2 - 40), 1] [Mod(-224*y^2 - 618*y - 1705, y^3 - 21), -2] [Mod(54*y^2 + 149*y + 411, y^3 - 21), 1] rnfalgtobasis(L,2): [2, 0]~ rnfalgtobasis(M,2): [2]~ rnfbasistoalg(L,2): Mod(2, x^2 + Mod(-y, y^3 - 21)) rnfbasistoalg(M,2): Mod(2, x) rnfeltabstorel(L,2): 2 rnfeltabstorel(M,2): 2 rnfeltreltoabs(L,2): 2 rnfeltreltoabs(M,2): 2 rnfeltup(L,2): 2 rnfeltup(M,2): 2 rnfeltdown(L,2): 2 rnfeltdown(M,2): 2 rnfelttrace(L,2): 4 rnfelttrace(M,2): 2 rnfeltnorm(L,2): 4 rnfeltnorm(M,2): 2 rnfalgtobasis(L,1/2): [1/2, 0]~ rnfalgtobasis(M,1/2): [1/2]~ rnfbasistoalg(L,1/2): Mod(1/2, x^2 + Mod(-y, y^3 - 21)) rnfbasistoalg(M,1/2): Mod(1/2, x) rnfeltabstorel(L,1/2): 1/2 rnfeltabstorel(M,1/2): 1/2 rnfeltreltoabs(L,1/2): 1/2 rnfeltreltoabs(M,1/2): 1/2 rnfeltup(L,1/2): 1/2 rnfeltup(M,1/2): 1/2 rnfeltdown(L,1/2): 1/2 rnfeltdown(M,1/2): 1/2 rnfelttrace(L,1/2): 1 rnfelttrace(M,1/2): 1/2 rnfeltnorm(L,1/2): 1/4 rnfeltnorm(M,1/2): 1/2 rnfalgtobasis(L,x + y): [Mod(y^2 + y, y^3 - 21), Mod(1, y^3 - 21)]~ rnfalgtobasis(M,x + y): [Mod(y, y^3 - 21)]~ rnfbasistoalg(L,x + y): Mod(x + Mod(y, y^3 - 21), x^2 + Mod(-y, y^3 - 21)) rnfbasistoalg(M,x + y): Mod(Mod(y, y^3 - 21), x) rnfeltabstorel(L,x + y): error("incorrect type in rnfeltabstorel [not in Q[X ]] (t_POL).") rnfeltabstorel(M,x + y): error("incorrect type in rnfeltabstorel [not in Q[X ]] (t_POL).") rnfeltreltoabs(L,x + y): Mod(x^2 + x, x^6 - 21) rnfeltreltoabs(M,x + y): Mod(-x, x^3 + 21) rnfeltup(L,x + y): error("inconsistent variables in nf_to_scalar_or_basis, x != y.") rnfeltup(M,x + y): error("inconsistent variables in nf_to_scalar_or_basis, x != y.") rnfeltdown(L,x + y): error("incorrect type in rnfeltabstorel [not in Q[X]] ( t_POL).") rnfeltdown(M,x + y): error("incorrect type in rnfeltabstorel [not in Q[X]] ( t_POL).") rnfelttrace(L,x + y): Mod(2*y, y^3 - 21) rnfelttrace(M,x + y): Mod(y, y^3 - 21) rnfeltnorm(L,x + y): Mod(y^2 - y, y^3 - 21) rnfeltnorm(M,x + y): Mod(y, y^3 - 21) rnfalgtobasis(L,Mod(1, y^3 - 21)): [1, 0]~ rnfalgtobasis(M,Mod(1, y^3 - 21)): [1]~ rnfbasistoalg(L,Mod(1, y^3 - 21)): Mod(1, x^2 + Mod(-y, y^3 - 21)) rnfbasistoalg(M,Mod(1, y^3 - 21)): Mod(1, x) rnfeltabstorel(L,Mod(1, y^3 - 21)): Mod(1, x^2 + Mod(-y, y^3 - 21)) rnfeltabstorel(M,Mod(1, y^3 - 21)): Mod(1, x) rnfeltreltoabs(L,Mod(1, y^3 - 21)): Mod(1, x^6 - 21) rnfeltreltoabs(M,Mod(1, y^3 - 21)): Mod(1, x^3 + 21) rnfeltup(L,Mod(1, y^3 - 21)): 1 rnfeltup(M,Mod(1, y^3 - 21)): 1 rnfeltdown(L,Mod(1, y^3 - 21)): 1 rnfeltdown(M,Mod(1, y^3 - 21)): 1 rnfelttrace(L,Mod(1, y^3 - 21)): 2 rnfelttrace(M,Mod(1, y^3 - 21)): 1 rnfeltnorm(L,Mod(1, y^3 - 21)): 1 rnfeltnorm(M,Mod(1, y^3 - 21)): 1 rnfalgtobasis(L,Mod(1/2, y^3 - 21)): [1/2, 0]~ rnfalgtobasis(M,Mod(1/2, y^3 - 21)): [1/2]~ rnfbasistoalg(L,Mod(1/2, y^3 - 21)): Mod(1/2, x^2 + Mod(-y, y^3 - 21)) rnfbasistoalg(M,Mod(1/2, y^3 - 21)): Mod(1/2, x) rnfeltabstorel(L,Mod(1/2, y^3 - 21)): Mod(1/2, x^2 + Mod(-y, y^3 - 21)) rnfeltabstorel(M,Mod(1/2, y^3 - 21)): Mod(1/2, x) rnfeltreltoabs(L,Mod(1/2, y^3 - 21)): Mod(1/2, x^6 - 21) rnfeltreltoabs(M,Mod(1/2, y^3 - 21)): Mod(1/2, x^3 + 21) rnfeltup(L,Mod(1/2, y^3 - 21)): 1/2 rnfeltup(M,Mod(1/2, y^3 - 21)): 1/2 rnfeltdown(L,Mod(1/2, y^3 - 21)): 1/2 rnfeltdown(M,Mod(1/2, y^3 - 21)): 1/2 rnfelttrace(L,Mod(1/2, y^3 - 21)): 1 rnfelttrace(M,Mod(1/2, y^3 - 21)): 1/2 rnfeltnorm(L,Mod(1/2, y^3 - 21)): 1/4 rnfeltnorm(M,Mod(1/2, y^3 - 21)): 1/2 rnfalgtobasis(L,Mod(y, y^3 - 21)): [Mod(y, y^3 - 21), 0]~ rnfalgtobasis(M,Mod(y, y^3 - 21)): [Mod(y, y^3 - 21)]~ rnfbasistoalg(L,Mod(y, y^3 - 21)): Mod(Mod(y, y^3 - 21), x^2 + Mod(-y, y^3 - 21)) rnfbasistoalg(M,Mod(y, y^3 - 21)): Mod(Mod(y, y^3 - 21), x) rnfeltabstorel(L,Mod(y, y^3 - 21)): Mod(Mod(y, y^3 - 21), x^2 + Mod(-y, y^3 - 21)) rnfeltabstorel(M,Mod(y, y^3 - 21)): Mod(Mod(y, y^3 - 21), x) rnfeltreltoabs(L,Mod(y, y^3 - 21)): Mod(x^2, x^6 - 21) rnfeltreltoabs(M,Mod(y, y^3 - 21)): Mod(-x, x^3 + 21) rnfeltup(L,Mod(y, y^3 - 21)): Mod(x^2, x^6 - 21) rnfeltup(M,Mod(y, y^3 - 21)): Mod(-x, x^3 + 21) rnfeltdown(L,Mod(y, y^3 - 21)): Mod(y, y^3 - 21) rnfeltdown(M,Mod(y, y^3 - 21)): Mod(y, y^3 - 21) rnfelttrace(L,Mod(y, y^3 - 21)): Mod(2*y, y^3 - 21) rnfelttrace(M,Mod(y, y^3 - 21)): Mod(y, y^3 - 21) rnfeltnorm(L,Mod(y, y^3 - 21)): Mod(y^2, y^3 - 21) rnfeltnorm(M,Mod(y, y^3 - 21)): Mod(y, y^3 - 21) rnfalgtobasis(L,Mod(1, x^6 - 21)): error("inconsistent moduli in rnfalgtobas is: x^6 - 21 != y^3 - 21") rnfalgtobasis(M,Mod(1, x^6 - 21)): error("inconsistent moduli in rnfalgtobas is: x^6 - 21 != y^3 - 21") rnfbasistoalg(L,Mod(1, x^6 - 21)): error("inconsistent moduli in rnfbasistoa lg: x^6 - 21 != y^3 - 21") rnfbasistoalg(M,Mod(1, x^6 - 21)): error("inconsistent moduli in rnfbasistoa lg: x^6 - 21 != y^3 - 21") rnfeltabstorel(L,Mod(1, x^6 - 21)): 1 rnfeltabstorel(M,Mod(1, x^6 - 21)): error("inconsistent moduli in rnfeltabst orel: x^6 - 21 != x^3 + 21") rnfeltreltoabs(L,Mod(1, x^6 - 21)): Mod(1, x^6 - 21) rnfeltreltoabs(M,Mod(1, x^6 - 21)): error("inconsistent moduli in rnfeltrelt oabs: x^6 - 21 != y^3 - 21") rnfeltup(L,Mod(1, x^6 - 21)): Mod(1, x^6 - 21) rnfeltup(M,Mod(1, x^6 - 21)): error("inconsistent moduli in nf_to_scalar_or_ basis: x^6 - 21 != y^3 - 21") rnfeltdown(L,Mod(1, x^6 - 21)): 1 rnfeltdown(M,Mod(1, x^6 - 21)): error("inconsistent moduli in rnfeltdown: x^ 6 - 21 != y^3 - 21") rnfelttrace(L,Mod(1, x^6 - 21)): 2 rnfelttrace(M,Mod(1, x^6 - 21)): error("inconsistent moduli in rnfeltabstore l: x^6 - 21 != x^3 + 21") rnfeltnorm(L,Mod(1, x^6 - 21)): 1 rnfeltnorm(M,Mod(1, x^6 - 21)): error("inconsistent moduli in rnfeltabstorel : x^6 - 21 != x^3 + 21") rnfalgtobasis(L,Mod(1/2, x^6 - 21)): error("inconsistent moduli in rnfalgtob asis: x^6 - 21 != y^3 - 21") rnfalgtobasis(M,Mod(1/2, x^6 - 21)): error("inconsistent moduli in rnfalgtob asis: x^6 - 21 != y^3 - 21") rnfbasistoalg(L,Mod(1/2, x^6 - 21)): error("inconsistent moduli in rnfbasist oalg: x^6 - 21 != y^3 - 21") rnfbasistoalg(M,Mod(1/2, x^6 - 21)): error("inconsistent moduli in rnfbasist oalg: x^6 - 21 != y^3 - 21") rnfeltabstorel(L,Mod(1/2, x^6 - 21)): 1/2 rnfeltabstorel(M,Mod(1/2, x^6 - 21)): error("inconsistent moduli in rnfeltab storel: x^6 - 21 != x^3 + 21") rnfeltreltoabs(L,Mod(1/2, x^6 - 21)): Mod(1/2, x^6 - 21) rnfeltreltoabs(M,Mod(1/2, x^6 - 21)): error("inconsistent moduli in rnfeltre ltoabs: x^6 - 21 != y^3 - 21") rnfeltup(L,Mod(1/2, x^6 - 21)): Mod(1/2, x^6 - 21) rnfeltup(M,Mod(1/2, x^6 - 21)): error("inconsistent moduli in nf_to_scalar_o r_basis: x^6 - 21 != y^3 - 21") rnfeltdown(L,Mod(1/2, x^6 - 21)): 1/2 rnfeltdown(M,Mod(1/2, x^6 - 21)): error("inconsistent moduli in rnfeltdown: x^6 - 21 != y^3 - 21") rnfelttrace(L,Mod(1/2, x^6 - 21)): 1 rnfelttrace(M,Mod(1/2, x^6 - 21)): error("inconsistent moduli in rnfeltabsto rel: x^6 - 21 != x^3 + 21") rnfeltnorm(L,Mod(1/2, x^6 - 21)): 1/4 rnfeltnorm(M,Mod(1/2, x^6 - 21)): error("inconsistent moduli in rnfeltabstor el: x^6 - 21 != x^3 + 21") rnfalgtobasis(L,Mod(x, x^6 - 21)): error("inconsistent moduli in rnfalgtobas is: x^6 - 21 != y^3 - 21") rnfalgtobasis(M,Mod(x, x^6 - 21)): error("inconsistent moduli in rnfalgtobas is: x^6 - 21 != y^3 - 21") rnfbasistoalg(L,Mod(x, x^6 - 21)): error("inconsistent moduli in rnfbasistoa lg: x^6 - 21 != y^3 - 21") rnfbasistoalg(M,Mod(x, x^6 - 21)): error("inconsistent moduli in rnfbasistoa lg: x^6 - 21 != y^3 - 21") rnfeltabstorel(L,Mod(x, x^6 - 21)): Mod(x, x^2 + Mod(-y, y^3 - 21)) rnfeltabstorel(M,Mod(x, x^6 - 21)): error("inconsistent moduli in rnfeltabst orel: x^6 - 21 != x^3 + 21") rnfeltreltoabs(L,Mod(x, x^6 - 21)): Mod(x, x^6 - 21) rnfeltreltoabs(M,Mod(x, x^6 - 21)): error("inconsistent moduli in rnfeltrelt oabs: x^6 - 21 != y^3 - 21") rnfeltup(L,Mod(x, x^6 - 21)): Mod(x, x^6 - 21) rnfeltup(M,Mod(x, x^6 - 21)): error("inconsistent moduli in nf_to_scalar_or_ basis: x^6 - 21 != y^3 - 21") rnfeltdown(L,Mod(x, x^6 - 21)): error("domain error in rnfeltdown: element n ot in the base field") rnfeltdown(M,Mod(x, x^6 - 21)): error("inconsistent moduli in rnfeltdown: x^ 6 - 21 != y^3 - 21") rnfelttrace(L,Mod(x, x^6 - 21)): 0 rnfelttrace(M,Mod(x, x^6 - 21)): error("inconsistent moduli in rnfeltabstore l: x^6 - 21 != x^3 + 21") rnfeltnorm(L,Mod(x, x^6 - 21)): Mod(-y, y^3 - 21) rnfeltnorm(M,Mod(x, x^6 - 21)): error("inconsistent moduli in rnfeltabstorel : x^6 - 21 != x^3 + 21") rnfalgtobasis(L,Mod(x + 1/2*y, x^2 - y)): [Mod(y^2 + 1/2*y, y^3 - 21), Mod(1 , y^3 - 21)]~ rnfalgtobasis(M,Mod(x + 1/2*y, x^2 - y)): error("inconsistent moduli in rnfa lgtobasis: x^2 - y != y^3 - 21") rnfbasistoalg(L,Mod(x + 1/2*y, x^2 - y)): Mod(x + Mod(1/2*y, y^3 - 21), x^2 + Mod(-y, y^3 - 21)) rnfbasistoalg(M,Mod(x + 1/2*y, x^2 - y)): error("inconsistent moduli in rnfb asistoalg: x^2 - y != y^3 - 21") rnfeltabstorel(L,Mod(x + 1/2*y, x^2 - y)): Mod(x + Mod(1/2*y, y^3 - 21), x^2 + Mod(-y, y^3 - 21)) rnfeltabstorel(M,Mod(x + 1/2*y, x^2 - y)): error("inconsistent moduli in rnf eltabstorel: x^2 - y != x^3 + 21") rnfeltreltoabs(L,Mod(x + 1/2*y, x^2 - y)): Mod(1/2*x^2 + x, x^6 - 21) rnfeltreltoabs(M,Mod(x + 1/2*y, x^2 - y)): error("inconsistent moduli in rnf eltreltoabs: x^2 - y != y^3 - 21") rnfeltup(L,Mod(x + 1/2*y, x^2 - y)): error("inconsistent moduli in nf_to_sca lar_or_basis: x^2 - y != y^3 - 21") rnfeltup(M,Mod(x + 1/2*y, x^2 - y)): error("inconsistent moduli in nf_to_sca lar_or_basis: x^2 - y != y^3 - 21") rnfeltdown(L,Mod(x + 1/2*y, x^2 - y)): error("domain error in rnfeltdown: el ement not in the base field") rnfeltdown(M,Mod(x + 1/2*y, x^2 - y)): error("inconsistent moduli in rnfeltd own: x^2 - y != y^3 - 21") rnfelttrace(L,Mod(x + 1/2*y, x^2 - y)): Mod(y, y^3 - 21) rnfelttrace(M,Mod(x + 1/2*y, x^2 - y)): error("inconsistent moduli in rnfelt abstorel: x^2 - y != x^3 + 21") rnfeltnorm(L,Mod(x + 1/2*y, x^2 - y)): Mod(1/4*y^2 - y, y^3 - 21) rnfeltnorm(M,Mod(x + 1/2*y, x^2 - y)): error("inconsistent moduli in rnfelta bstorel: x^2 - y != x^3 + 21") rnfalgtobasis(L,y): [Mod(y, y^3 - 21), 0]~ rnfalgtobasis(M,y): [Mod(y, y^3 - 21)]~ rnfbasistoalg(L,y): Mod(Mod(y, y^3 - 21), x^2 + Mod(-y, y^3 - 21)) rnfbasistoalg(M,y): Mod(Mod(y, y^3 - 21), x) rnfeltabstorel(L,y): Mod(Mod(y, y^3 - 21), x^2 + Mod(-y, y^3 - 21)) rnfeltabstorel(M,y): Mod(Mod(y, y^3 - 21), x) rnfeltreltoabs(L,y): Mod(x^2, x^6 - 21) rnfeltreltoabs(M,y): Mod(-x, x^3 + 21) rnfeltup(L,y): Mod(x^2, x^6 - 21) rnfeltup(M,y): Mod(-x, x^3 + 21) rnfeltdown(L,y): Mod(y, y^3 - 21) rnfeltdown(M,y): Mod(y, y^3 - 21) rnfelttrace(L,y): Mod(2*y, y^3 - 21) rnfelttrace(M,y): Mod(y, y^3 - 21) rnfeltnorm(L,y): Mod(y^2, y^3 - 21) rnfeltnorm(M,y): Mod(y, y^3 - 21) rnfalgtobasis(L,z): error("incorrect priority in rnfalgtobasis: variable z > = y") rnfalgtobasis(M,z): error("incorrect priority in rnfalgtobasis: variable z > = y") rnfbasistoalg(L,z): error("inconsistent variables in rnfbasistoalg, z != x." ) rnfbasistoalg(M,z): error("inconsistent variables in rnfbasistoalg, z != x." ) rnfeltabstorel(L,z): error("inconsistent variables in rnfeltabstorel, z != x .") rnfeltabstorel(M,z): error("inconsistent variables in rnfeltabstorel, z != x .") rnfeltreltoabs(L,z): error("inconsistent variables in eltreltoabs, z != y.") rnfeltreltoabs(M,z): error("inconsistent variables in eltreltoabs, z != y.") rnfeltup(L,z): error("inconsistent variables in nf_to_scalar_or_basis, z != y.") rnfeltup(M,z): error("inconsistent variables in nf_to_scalar_or_basis, z != y.") rnfeltdown(L,z): error("inconsistent variables in rnfeltabstorel, z != x.") rnfeltdown(M,z): error("inconsistent variables in rnfeltabstorel, z != x.") rnfelttrace(L,z): error("inconsistent variables in rnfeltabstorel, z != x.") rnfelttrace(M,z): error("inconsistent variables in rnfeltabstorel, z != x.") rnfeltnorm(L,z): error("inconsistent variables in rnfeltabstorel, z != x.") rnfeltnorm(M,z): error("inconsistent variables in rnfeltabstorel, z != x.") rnfalgtobasis(L,Mod(y + 1/2, y^2 + 1)): error("inconsistent moduli in rnfalg tobasis: y^2 + 1 != y^3 - 21") rnfalgtobasis(M,Mod(y + 1/2, y^2 + 1)): error("inconsistent moduli in rnfalg tobasis: y^2 + 1 != y^3 - 21") rnfbasistoalg(L,Mod(y + 1/2, y^2 + 1)): error("inconsistent moduli in rnfbas istoalg: y^2 + 1 != y^3 - 21") rnfbasistoalg(M,Mod(y + 1/2, y^2 + 1)): error("inconsistent moduli in rnfbas istoalg: y^2 + 1 != y^3 - 21") rnfeltabstorel(L,Mod(y + 1/2, y^2 + 1)): error("inconsistent moduli in rnfel tabstorel: y^2 + 1 != x^6 - 21") rnfeltabstorel(M,Mod(y + 1/2, y^2 + 1)): error("inconsistent moduli in rnfel tabstorel: y^2 + 1 != x^3 + 21") rnfeltreltoabs(L,Mod(y + 1/2, y^2 + 1)): error("inconsistent moduli in rnfel treltoabs: y^2 + 1 != y^3 - 21") rnfeltreltoabs(M,Mod(y + 1/2, y^2 + 1)): error("inconsistent moduli in rnfel treltoabs: y^2 + 1 != y^3 - 21") rnfeltup(L,Mod(y + 1/2, y^2 + 1)): error("inconsistent moduli in nf_to_scala r_or_basis: y^2 + 1 != y^3 - 21") rnfeltup(M,Mod(y + 1/2, y^2 + 1)): error("inconsistent moduli in nf_to_scala r_or_basis: y^2 + 1 != y^3 - 21") rnfeltdown(L,Mod(y + 1/2, y^2 + 1)): error("inconsistent moduli in rnfeltdow n: y^2 + 1 != y^3 - 21") rnfeltdown(M,Mod(y + 1/2, y^2 + 1)): error("inconsistent moduli in rnfeltdow n: y^2 + 1 != y^3 - 21") rnfelttrace(L,Mod(y + 1/2, y^2 + 1)): error("inconsistent moduli in rnfeltab storel: y^2 + 1 != x^6 - 21") rnfelttrace(M,Mod(y + 1/2, y^2 + 1)): error("inconsistent moduli in rnfeltab storel: y^2 + 1 != x^3 + 21") rnfeltnorm(L,Mod(y + 1/2, y^2 + 1)): error("inconsistent moduli in rnfeltabs torel: y^2 + 1 != x^6 - 21") rnfeltnorm(M,Mod(y + 1/2, y^2 + 1)): error("inconsistent moduli in rnfeltabs torel: y^2 + 1 != x^3 + 21") rnfalgtobasis(L,[1]~): error("inconsistent dimensions in rnfalgtobasis.") rnfalgtobasis(M,[1]~): [1]~ rnfbasistoalg(L,[1]~): error("inconsistent operation 'RgV_RgC_mul' t_VEC (2 elts) , t_COL (1 elts).") rnfbasistoalg(M,[1]~): Mod(1, x) rnfeltabstorel(L,[1]~): error("incorrect type in rnfeltabstorel, apply nfini t(rnf) (t_COL).") rnfeltabstorel(M,[1]~): error("incorrect type in rnfeltabstorel, apply nfini t(rnf) (t_COL).") rnfeltreltoabs(L,[1]~): error("incorrect type in rnfeltreltoabs (t_COL).") rnfeltreltoabs(M,[1]~): error("incorrect type in rnfeltreltoabs (t_COL).") rnfeltup(L,[1]~): error("incorrect type in nf_to_scalar_or_basis (t_COL).") rnfeltup(M,[1]~): error("incorrect type in nf_to_scalar_or_basis (t_COL).") rnfeltdown(L,[1]~): error("incorrect type in rnfeltdown (t_COL).") rnfeltdown(M,[1]~): error("incorrect type in rnfeltdown (t_COL).") rnfelttrace(L,[1]~): error("incorrect type in rnfeltabstorel, apply nfinit(r nf) (t_COL).") rnfelttrace(M,[1]~): error("incorrect type in rnfeltabstorel, apply nfinit(r nf) (t_COL).") rnfeltnorm(L,[1]~): error("incorrect type in rnfeltabstorel, apply nfinit(rn f) (t_COL).") rnfeltnorm(M,[1]~): error("incorrect type in rnfeltabstorel, apply nfinit(rn f) (t_COL).") rnfalgtobasis(L,[1, 2]~): [1, 2]~ rnfalgtobasis(M,[1, 2]~): error("inconsistent dimensions in rnfalgtobasis.") rnfbasistoalg(L,[1, 2]~): Mod(2*x + Mod(-2*y^2 + 1, y^3 - 21), x^2 + Mod(-y, y^3 - 21)) rnfbasistoalg(M,[1, 2]~): error("inconsistent operation 'RgV_RgC_mul' t_VEC (1 elts) , t_COL (2 elts).") rnfeltabstorel(L,[1, 2]~): error("incorrect type in rnfeltabstorel, apply nf init(rnf) (t_COL).") rnfeltabstorel(M,[1, 2]~): error("incorrect type in rnfeltabstorel, apply nf init(rnf) (t_COL).") rnfeltreltoabs(L,[1, 2]~): error("incorrect type in rnfeltreltoabs (t_COL)." ) rnfeltreltoabs(M,[1, 2]~): error("incorrect type in rnfeltreltoabs (t_COL)." ) rnfeltup(L,[1, 2]~): error("incorrect type in nf_to_scalar_or_basis (t_COL). ") rnfeltup(M,[1, 2]~): error("incorrect type in nf_to_scalar_or_basis (t_COL). ") rnfeltdown(L,[1, 2]~): error("incorrect type in rnfeltdown (t_COL).") rnfeltdown(M,[1, 2]~): error("incorrect type in rnfeltdown (t_COL).") rnfelttrace(L,[1, 2]~): error("incorrect type in rnfeltabstorel, apply nfini t(rnf) (t_COL).") rnfelttrace(M,[1, 2]~): error("incorrect type in rnfeltabstorel, apply nfini t(rnf) (t_COL).") rnfeltnorm(L,[1, 2]~): error("incorrect type in rnfeltabstorel, apply nfinit (rnf) (t_COL).") rnfeltnorm(M,[1, 2]~): error("incorrect type in rnfeltabstorel, apply nfinit (rnf) (t_COL).") rnfalgtobasis(L,[1, y]~): [1, Mod(y, y^3 - 21)]~ rnfalgtobasis(M,[1, y]~): error("inconsistent dimensions in rnfalgtobasis.") rnfbasistoalg(L,[1, y]~): Mod(Mod(y, y^3 - 21)*x - 20, x^2 + Mod(-y, y^3 - 2 1)) rnfbasistoalg(M,[1, y]~): error("inconsistent operation 'RgV_RgC_mul' t_VEC (1 elts) , t_COL (2 elts).") rnfeltabstorel(L,[1, y]~): error("incorrect type in rnfeltabstorel, apply nf init(rnf) (t_COL).") rnfeltabstorel(M,[1, y]~): error("incorrect type in rnfeltabstorel, apply nf init(rnf) (t_COL).") rnfeltreltoabs(L,[1, y]~): error("incorrect type in rnfeltreltoabs (t_COL)." ) rnfeltreltoabs(M,[1, y]~): error("incorrect type in rnfeltreltoabs (t_COL)." ) rnfeltup(L,[1, y]~): error("incorrect type in nf_to_scalar_or_basis (t_COL). ") rnfeltup(M,[1, y]~): error("incorrect type in nf_to_scalar_or_basis (t_COL). ") rnfeltdown(L,[1, y]~): error("incorrect type in rnfeltdown (t_COL).") rnfeltdown(M,[1, y]~): error("incorrect type in rnfeltdown (t_COL).") rnfelttrace(L,[1, y]~): error("incorrect type in rnfeltabstorel, apply nfini t(rnf) (t_COL).") rnfelttrace(M,[1, y]~): error("incorrect type in rnfeltabstorel, apply nfini t(rnf) (t_COL).") rnfeltnorm(L,[1, y]~): error("incorrect type in rnfeltabstorel, apply nfinit (rnf) (t_COL).") rnfeltnorm(M,[1, y]~): error("incorrect type in rnfeltabstorel, apply nfinit (rnf) (t_COL).") rnfalgtobasis(L,[1, I]~): error("incorrect type in rnfalgtobasis (t_COMPLEX) .") rnfalgtobasis(M,[1, I]~): error("inconsistent dimensions in rnfalgtobasis.") rnfbasistoalg(L,[1, I]~): error("incorrect type in nf_to_scalar_or_alg (t_CO MPLEX).") rnfbasistoalg(M,[1, I]~): error("incorrect type in nf_to_scalar_or_alg (t_CO MPLEX).") rnfeltabstorel(L,[1, I]~): error("incorrect type in rnfeltabstorel, apply nf init(rnf) (t_COL).") rnfeltabstorel(M,[1, I]~): error("incorrect type in rnfeltabstorel, apply nf init(rnf) (t_COL).") rnfeltreltoabs(L,[1, I]~): error("incorrect type in rnfeltreltoabs (t_COL)." ) rnfeltreltoabs(M,[1, I]~): error("incorrect type in rnfeltreltoabs (t_COL)." ) rnfeltup(L,[1, I]~): error("incorrect type in nf_to_scalar_or_basis (t_COL). ") rnfeltup(M,[1, I]~): error("incorrect type in nf_to_scalar_or_basis (t_COL). ") rnfeltdown(L,[1, I]~): error("incorrect type in rnfeltdown (t_COL).") rnfeltdown(M,[1, I]~): error("incorrect type in rnfeltdown (t_COL).") rnfelttrace(L,[1, I]~): error("incorrect type in rnfeltabstorel, apply nfini t(rnf) (t_COL).") rnfelttrace(M,[1, I]~): error("incorrect type in rnfeltabstorel, apply nfini t(rnf) (t_COL).") rnfeltnorm(L,[1, I]~): error("incorrect type in rnfeltabstorel, apply nfinit (rnf) (t_COL).") rnfeltnorm(M,[1, I]~): error("incorrect type in rnfeltabstorel, apply nfinit (rnf) (t_COL).") rnfalgtobasis(L,y + I): error("incorrect type in rnfalgtobasis [not in Q[X]] (t_POL).") rnfalgtobasis(M,y + I): error("incorrect type in rnfalgtobasis [not in Q[X]] (t_POL).") rnfbasistoalg(L,y + I): error("incorrect type in rnfbasistoalg [not in Q[X]] (t_POL).") rnfbasistoalg(M,y + I): error("incorrect type in rnfbasistoalg [not in Q[X]] (t_POL).") rnfeltabstorel(L,y + I): error("incorrect type in rnfeltabstorel [not in Q[X ]] (t_POL).") rnfeltabstorel(M,y + I): error("incorrect type in rnfeltabstorel [not in Q[X ]] (t_POL).") rnfeltreltoabs(L,y + I): error("incorrect type in poltobasis (t_POL).") rnfeltreltoabs(M,y + I): error("incorrect type in poltobasis (t_POL).") rnfeltup(L,y + I): error("incorrect type in poltobasis (t_POL).") rnfeltup(M,y + I): error("incorrect type in poltobasis (t_POL).") rnfeltdown(L,y + I): error("incorrect type in rnfeltdown [not in Q[X]] (t_PO L).") rnfeltdown(M,y + I): error("incorrect type in rnfeltdown [not in Q[X]] (t_PO L).") rnfelttrace(L,y + I): error("incorrect type in rnfeltabstorel [not in Q[X]] (t_POL).") rnfelttrace(M,y + I): error("incorrect type in rnfeltabstorel [not in Q[X]] (t_POL).") rnfeltnorm(L,y + I): error("incorrect type in rnfeltabstorel [not in Q[X]] ( t_POL).") rnfeltnorm(M,y + I): error("incorrect type in rnfeltabstorel [not in Q[X]] ( t_POL).") rnfalgtobasis(L,x^2): [y, 0]~ rnfalgtobasis(M,x^2): [0]~ rnfbasistoalg(L,x^2): Mod(Mod(y, y^3 - 21), x^2 + Mod(-y, y^3 - 21)) rnfbasistoalg(M,x^2): Mod(0, x) rnfeltabstorel(L,x^2): Mod(Mod(y, y^3 - 21), x^2 + Mod(-y, y^3 - 21)) rnfeltabstorel(M,x^2): Mod(Mod(y^2, y^3 - 21), x) rnfeltreltoabs(L,x^2): Mod(x^2, x^6 - 21) rnfeltreltoabs(M,x^2): Mod(0, x^3 + 21) rnfeltup(L,x^2): error("inconsistent variables in nf_to_scalar_or_basis, x ! = y.") rnfeltup(M,x^2): error("inconsistent variables in nf_to_scalar_or_basis, x ! = y.") rnfeltdown(L,x^2): Mod(y, y^3 - 21) rnfeltdown(M,x^2): Mod(y^2, y^3 - 21) rnfelttrace(L,x^2): Mod(2*y, y^3 - 21) rnfelttrace(M,x^2): 0 rnfeltnorm(L,x^2): Mod(y^2, y^3 - 21) rnfeltnorm(M,x^2): 0 1: x^2 - 4*x + 4 2: x^2 - x + 1/4 3: x^2 + Mod(-2*y, y^3 - 21)*x + Mod(y^2 - y, y^3 - 21) 4: x^2 - 2*x + 1 5: x^2 - x + 1/4 6: Mod(1, y^3 - 21)*x^2 + Mod(-2*y, y^3 - 21)*x + Mod(y^2, y^3 - 21) 7: error("inconsistent moduli in rnfcharpoly: x^6 - 21 != y^3 - 21") 8: error("inconsistent moduli in rnfcharpoly: x^6 - 21 != y^3 - 21") 9: error("inconsistent moduli in rnfcharpoly: x^6 - 21 != y^3 - 21") 10: x^2 + Mod(-y, y^3 - 21)*x + Mod(1/4*y^2 - y, y^3 - 21) 11: Mod(1, y^3 - 21)*x^2 + Mod(-2*y, y^3 - 21)*x + Mod(y^2, y^3 - 21) 12: error("incorrect priority in rnfcharpoly: variable z >= y") 13: error("inconsistent moduli in rnfcharpoly: y^2 + 1 != y^3 - 21") 14: error("incorrect type in rnfcharpoly (t_COL).") 15: error("incorrect type in rnfcharpoly (t_COL).") 16: error("incorrect type in rnfcharpoly (t_COL).") 17: error("incorrect type in rnfcharpoly (t_COL).") 18: error("incorrect type in rnfcharpoly [not in Q[X]] (t_POL).") 19: x^2 + Mod(-2*y, y^3 - 21)*x + Mod(y^2, y^3 - 21) rnfalgtobasis(L,2): [2, 0]~ rnfalgtobasis(M,2): [2]~ rnfbasistoalg(L,2): Mod(2, x^2 + 1) rnfbasistoalg(M,2): Mod(2, x) rnfeltabstorel(L,2): 2 rnfeltabstorel(M,2): 2 rnfeltreltoabs(L,2): 2 rnfeltreltoabs(M,2): 2 rnfeltup(L,2): 2 rnfeltup(M,2): 2 rnfeltdown(L,2): 2 rnfeltdown(M,2): 2 rnfelttrace(L,2): 4 rnfelttrace(M,2): 2 rnfeltnorm(L,2): 4 rnfeltnorm(M,2): 2 rnfalgtobasis(L,1/2): [1/2, 0]~ rnfalgtobasis(M,1/2): [1/2]~ rnfbasistoalg(L,1/2): Mod(1/2, x^2 + 1) rnfbasistoalg(M,1/2): Mod(1/2, x) rnfeltabstorel(L,1/2): 1/2 rnfeltabstorel(M,1/2): 1/2 rnfeltreltoabs(L,1/2): 1/2 rnfeltreltoabs(M,1/2): 1/2 rnfeltup(L,1/2): 1/2 rnfeltup(M,1/2): 1/2 rnfeltdown(L,1/2): 1/2 rnfeltdown(M,1/2): 1/2 rnfelttrace(L,1/2): 1 rnfelttrace(M,1/2): 1/2 rnfeltnorm(L,1/2): 1/4 rnfeltnorm(M,1/2): 1/2 rnfalgtobasis(L,x + y): [-1, 1]~ rnfalgtobasis(M,x + y): [Mod(y, y^3 - 21)]~ rnfbasistoalg(L,x + y): Mod(x - 1, x^2 + 1) rnfbasistoalg(M,x + y): Mod(Mod(y, y^3 - 21), x) rnfeltabstorel(L,x + y): error("incorrect type in rnfeltabstorel [not in Q[X ]] (t_POL).") rnfeltabstorel(M,x + y): error("incorrect type in rnfeltabstorel [not in Q[X ]] (t_POL).") rnfeltreltoabs(L,x + y): Mod(x - 1, x^2 + 1) rnfeltreltoabs(M,x + y): Mod(-x, x^3 + 21) rnfeltup(L,x + y): error("inconsistent variables in nf_to_scalar_or_basis, x != y.") rnfeltup(M,x + y): error("inconsistent variables in nf_to_scalar_or_basis, x != y.") rnfeltdown(L,x + y): error("incorrect type in rnfeltabstorel [not in Q[X]] ( t_POL).") rnfeltdown(M,x + y): error("incorrect type in rnfeltabstorel [not in Q[X]] ( t_POL).") rnfelttrace(L,x + y): -2 rnfelttrace(M,x + y): Mod(y, y^3 - 21) rnfeltnorm(L,x + y): 2 rnfeltnorm(M,x + y): Mod(y, y^3 - 21) rnfalgtobasis(L,Mod(1/2, y + 1)): [1/2, 0]~ rnfalgtobasis(M,Mod(1/2, y + 1)): error("inconsistent moduli in rnfalgtobasi s: y + 1 != y^3 - 21") rnfbasistoalg(L,Mod(1/2, y + 1)): Mod(1/2, x^2 + 1) rnfbasistoalg(M,Mod(1/2, y + 1)): error("inconsistent moduli in rnfbasistoal g: y + 1 != y^3 - 21") rnfeltabstorel(L,Mod(1/2, y + 1)): Mod(1/2, x^2 + 1) rnfeltabstorel(M,Mod(1/2, y + 1)): error("inconsistent moduli in rnfeltabsto rel: y + 1 != x^3 + 21") rnfeltreltoabs(L,Mod(1/2, y + 1)): Mod(1/2, x^2 + 1) rnfeltreltoabs(M,Mod(1/2, y + 1)): error("inconsistent moduli in rnfeltrelto abs: y + 1 != y^3 - 21") rnfeltup(L,Mod(1/2, y + 1)): 1/2 rnfeltup(M,Mod(1/2, y + 1)): error("inconsistent moduli in nf_to_scalar_or_b asis: y + 1 != y^3 - 21") rnfeltdown(L,Mod(1/2, y + 1)): 1/2 rnfeltdown(M,Mod(1/2, y + 1)): error("inconsistent moduli in rnfeltdown: y + 1 != y^3 - 21") rnfelttrace(L,Mod(1/2, y + 1)): 1 rnfelttrace(M,Mod(1/2, y + 1)): error("inconsistent moduli in rnfeltabstorel : y + 1 != x^3 + 21") rnfeltnorm(L,Mod(1/2, y + 1)): 1/4 rnfeltnorm(M,Mod(1/2, y + 1)): error("inconsistent moduli in rnfeltabstorel: y + 1 != x^3 + 21") rnfalgtobasis(L,y): [Mod(-1, y + 1), 0]~ rnfalgtobasis(M,y): [Mod(y, y^3 - 21)]~ rnfbasistoalg(L,y): Mod(Mod(-1, y + 1), x^2 + 1) rnfbasistoalg(M,y): Mod(Mod(y, y^3 - 21), x) rnfeltabstorel(L,y): Mod(-1, x^2 + 1) rnfeltabstorel(M,y): Mod(Mod(y, y^3 - 21), x) rnfeltreltoabs(L,y): -1 rnfeltreltoabs(M,y): Mod(-x, x^3 + 21) rnfeltup(L,y): -1 rnfeltup(M,y): Mod(-x, x^3 + 21) rnfeltdown(L,y): -1 rnfeltdown(M,y): Mod(y, y^3 - 21) rnfelttrace(L,y): -2 rnfelttrace(M,y): Mod(y, y^3 - 21) rnfeltnorm(L,y): 1 rnfeltnorm(M,y): Mod(y, y^3 - 21) rnfalgtobasis(L,Mod(1/2*x + 1, x^2 + 1)): [1, 1/2]~ rnfalgtobasis(M,Mod(1/2*x + 1, x^2 + 1)): error("inconsistent moduli in rnfa lgtobasis: x^2 + 1 != y^3 - 21") rnfbasistoalg(L,Mod(1/2*x + 1, x^2 + 1)): Mod(1/2*x + 1, x^2 + 1) rnfbasistoalg(M,Mod(1/2*x + 1, x^2 + 1)): error("inconsistent moduli in rnfb asistoalg: x^2 + 1 != y^3 - 21") rnfeltabstorel(L,Mod(1/2*x + 1, x^2 + 1)): Mod(1/2*x + 1, x^2 + 1) rnfeltabstorel(M,Mod(1/2*x + 1, x^2 + 1)): error("inconsistent moduli in rnf eltabstorel: x^2 + 1 != x^3 + 21") rnfeltreltoabs(L,Mod(1/2*x + 1, x^2 + 1)): Mod(1/2*x + 1, x^2 + 1) rnfeltreltoabs(M,Mod(1/2*x + 1, x^2 + 1)): error("inconsistent moduli in rnf eltreltoabs: x^2 + 1 != y^3 - 21") rnfeltup(L,Mod(1/2*x + 1, x^2 + 1)): Mod(1/2*x + 1, x^2 + 1) rnfeltup(M,Mod(1/2*x + 1, x^2 + 1)): error("inconsistent moduli in nf_to_sca lar_or_basis: x^2 + 1 != y^3 - 21") rnfeltdown(L,Mod(1/2*x + 1, x^2 + 1)): error("domain error in rnfeltdown: el ement not in the base field") rnfeltdown(M,Mod(1/2*x + 1, x^2 + 1)): error("inconsistent moduli in rnfeltd own: x^2 + 1 != y^3 - 21") rnfelttrace(L,Mod(1/2*x + 1, x^2 + 1)): 2 rnfelttrace(M,Mod(1/2*x + 1, x^2 + 1)): error("inconsistent moduli in rnfelt abstorel: x^2 + 1 != x^3 + 21") rnfeltnorm(L,Mod(1/2*x + 1, x^2 + 1)): 5/4 rnfeltnorm(M,Mod(1/2*x + 1, x^2 + 1)): error("inconsistent moduli in rnfelta bstorel: x^2 + 1 != x^3 + 21") rnfalgtobasis(L,Mod(x, x^2 + 1)): [0, 1]~ rnfalgtobasis(M,Mod(x, x^2 + 1)): error("inconsistent moduli in rnfalgtobasi s: x^2 + 1 != y^3 - 21") rnfbasistoalg(L,Mod(x, x^2 + 1)): Mod(x, x^2 + 1) rnfbasistoalg(M,Mod(x, x^2 + 1)): error("inconsistent moduli in rnfbasistoal g: x^2 + 1 != y^3 - 21") rnfeltabstorel(L,Mod(x, x^2 + 1)): Mod(x, x^2 + 1) rnfeltabstorel(M,Mod(x, x^2 + 1)): error("inconsistent moduli in rnfeltabsto rel: x^2 + 1 != x^3 + 21") rnfeltreltoabs(L,Mod(x, x^2 + 1)): Mod(x, x^2 + 1) rnfeltreltoabs(M,Mod(x, x^2 + 1)): error("inconsistent moduli in rnfeltrelto abs: x^2 + 1 != y^3 - 21") rnfeltup(L,Mod(x, x^2 + 1)): Mod(x, x^2 + 1) rnfeltup(M,Mod(x, x^2 + 1)): error("inconsistent moduli in nf_to_scalar_or_b asis: x^2 + 1 != y^3 - 21") rnfeltdown(L,Mod(x, x^2 + 1)): error("domain error in rnfeltdown: element no t in the base field") rnfeltdown(M,Mod(x, x^2 + 1)): error("inconsistent moduli in rnfeltdown: x^2 + 1 != y^3 - 21") rnfelttrace(L,Mod(x, x^2 + 1)): 0 rnfelttrace(M,Mod(x, x^2 + 1)): error("inconsistent moduli in rnfeltabstorel : x^2 + 1 != x^3 + 21") rnfeltnorm(L,Mod(x, x^2 + 1)): 1 rnfeltnorm(M,Mod(x, x^2 + 1)): error("inconsistent moduli in rnfeltabstorel: x^2 + 1 != x^3 + 21") rnfalgtobasis(L,Mod(x, x^2 + 1)): [0, 1]~ rnfalgtobasis(M,Mod(x, x^2 + 1)): error("inconsistent moduli in rnfalgtobasi s: x^2 + 1 != y^3 - 21") rnfbasistoalg(L,Mod(x, x^2 + 1)): Mod(x, x^2 + 1) rnfbasistoalg(M,Mod(x, x^2 + 1)): error("inconsistent moduli in rnfbasistoal g: x^2 + 1 != y^3 - 21") rnfeltabstorel(L,Mod(x, x^2 + 1)): Mod(x, x^2 + 1) rnfeltabstorel(M,Mod(x, x^2 + 1)): error("inconsistent moduli in rnfeltabsto rel: x^2 + 1 != x^3 + 21") rnfeltreltoabs(L,Mod(x, x^2 + 1)): Mod(x, x^2 + 1) rnfeltreltoabs(M,Mod(x, x^2 + 1)): error("inconsistent moduli in rnfeltrelto abs: x^2 + 1 != y^3 - 21") rnfeltup(L,Mod(x, x^2 + 1)): Mod(x, x^2 + 1) rnfeltup(M,Mod(x, x^2 + 1)): error("inconsistent moduli in nf_to_scalar_or_b asis: x^2 + 1 != y^3 - 21") rnfeltdown(L,Mod(x, x^2 + 1)): error("domain error in rnfeltdown: element no t in the base field") rnfeltdown(M,Mod(x, x^2 + 1)): error("inconsistent moduli in rnfeltdown: x^2 + 1 != y^3 - 21") rnfelttrace(L,Mod(x, x^2 + 1)): 0 rnfelttrace(M,Mod(x, x^2 + 1)): error("inconsistent moduli in rnfeltabstorel : x^2 + 1 != x^3 + 21") rnfeltnorm(L,Mod(x, x^2 + 1)): 1 rnfeltnorm(M,Mod(x, x^2 + 1)): error("inconsistent moduli in rnfeltabstorel: x^2 + 1 != x^3 + 21") rnfalgtobasis(L,Mod(x + 1/2*y, x^2 - y)): error("inconsistent moduli in rnfa lgtobasis: x^2 - y != y + 1") rnfalgtobasis(M,Mod(x + 1/2*y, x^2 - y)): error("inconsistent moduli in rnfa lgtobasis: x^2 - y != y^3 - 21") rnfbasistoalg(L,Mod(x + 1/2*y, x^2 - y)): error("inconsistent moduli in rnfb asistoalg: x^2 - y != y + 1") rnfbasistoalg(M,Mod(x + 1/2*y, x^2 - y)): error("inconsistent moduli in rnfb asistoalg: x^2 - y != y^3 - 21") rnfeltabstorel(L,Mod(x + 1/2*y, x^2 - y)): error("inconsistent moduli in rnf eltabstorel: x^2 - y != x^2 + 1") rnfeltabstorel(M,Mod(x + 1/2*y, x^2 - y)): error("inconsistent moduli in rnf eltabstorel: x^2 - y != x^3 + 21") rnfeltreltoabs(L,Mod(x + 1/2*y, x^2 - y)): error("inconsistent moduli in rnf eltreltoabs: x^2 - y != y + 1") rnfeltreltoabs(M,Mod(x + 1/2*y, x^2 - y)): error("inconsistent moduli in rnf eltreltoabs: x^2 - y != y^3 - 21") rnfeltup(L,Mod(x + 1/2*y, x^2 - y)): error("inconsistent moduli in nf_to_sca lar_or_basis: x^2 - y != y + 1") rnfeltup(M,Mod(x + 1/2*y, x^2 - y)): error("inconsistent moduli in nf_to_sca lar_or_basis: x^2 - y != y^3 - 21") rnfeltdown(L,Mod(x + 1/2*y, x^2 - y)): error("inconsistent moduli in rnfeltd own: x^2 - y != y + 1") rnfeltdown(M,Mod(x + 1/2*y, x^2 - y)): error("inconsistent moduli in rnfeltd own: x^2 - y != y^3 - 21") rnfelttrace(L,Mod(x + 1/2*y, x^2 - y)): error("inconsistent moduli in rnfelt abstorel: x^2 - y != x^2 + 1") rnfelttrace(M,Mod(x + 1/2*y, x^2 - y)): error("inconsistent moduli in rnfelt abstorel: x^2 - y != x^3 + 21") rnfeltnorm(L,Mod(x + 1/2*y, x^2 - y)): error("inconsistent moduli in rnfelta bstorel: x^2 - y != x^2 + 1") rnfeltnorm(M,Mod(x + 1/2*y, x^2 - y)): error("inconsistent moduli in rnfelta bstorel: x^2 - y != x^3 + 21") rnfalgtobasis(L,x): [0, 1]~ rnfalgtobasis(M,x): [0]~ rnfbasistoalg(L,x): Mod(x, x^2 + 1) rnfbasistoalg(M,x): Mod(0, x) rnfeltabstorel(L,x): Mod(x, x^2 + 1) rnfeltabstorel(M,x): Mod(Mod(-y, y^3 - 21), x) rnfeltreltoabs(L,x): Mod(x, x^2 + 1) rnfeltreltoabs(M,x): Mod(0, x^3 + 21) rnfeltup(L,x): error("inconsistent variables in nf_to_scalar_or_basis, x != y.") rnfeltup(M,x): error("inconsistent variables in nf_to_scalar_or_basis, x != y.") rnfeltdown(L,x): error("domain error in rnfeltdown: element not in the base field") rnfeltdown(M,x): Mod(-y, y^3 - 21) rnfelttrace(L,x): 0 rnfelttrace(M,x): 0 rnfeltnorm(L,x): 1 rnfeltnorm(M,x): 0 rnfalgtobasis(L,[1]~): error("inconsistent dimensions in rnfalgtobasis.") rnfalgtobasis(M,[1]~): [1]~ rnfbasistoalg(L,[1]~): error("inconsistent operation 'RgV_RgC_mul' t_VEC (2 elts) , t_COL (1 elts).") rnfbasistoalg(M,[1]~): Mod(1, x) rnfeltabstorel(L,[1]~): error("incorrect type in rnfeltabstorel, apply nfini t(rnf) (t_COL).") rnfeltabstorel(M,[1]~): error("incorrect type in rnfeltabstorel, apply nfini t(rnf) (t_COL).") rnfeltreltoabs(L,[1]~): error("incorrect type in rnfeltreltoabs (t_COL).") rnfeltreltoabs(M,[1]~): error("incorrect type in rnfeltreltoabs (t_COL).") rnfeltup(L,[1]~): 1 rnfeltup(M,[1]~): error("incorrect type in nf_to_scalar_or_basis (t_COL).") rnfeltdown(L,[1]~): 1 rnfeltdown(M,[1]~): error("incorrect type in rnfeltdown (t_COL).") rnfelttrace(L,[1]~): error("incorrect type in rnfeltabstorel, apply nfinit(r nf) (t_COL).") rnfelttrace(M,[1]~): error("incorrect type in rnfeltabstorel, apply nfinit(r nf) (t_COL).") rnfeltnorm(L,[1]~): error("incorrect type in rnfeltabstorel, apply nfinit(rn f) (t_COL).") rnfeltnorm(M,[1]~): error("incorrect type in rnfeltabstorel, apply nfinit(rn f) (t_COL).") rnfalgtobasis(L,[1, 2]~): [1, 2]~ rnfalgtobasis(M,[1, 2]~): error("inconsistent dimensions in rnfalgtobasis.") rnfbasistoalg(L,[1, 2]~): Mod(2*x + 1, x^2 + 1) rnfbasistoalg(M,[1, 2]~): error("inconsistent operation 'RgV_RgC_mul' t_VEC (1 elts) , t_COL (2 elts).") rnfeltabstorel(L,[1, 2]~): error("incorrect type in rnfeltabstorel, apply nf init(rnf) (t_COL).") rnfeltabstorel(M,[1, 2]~): error("incorrect type in rnfeltabstorel, apply nf init(rnf) (t_COL).") rnfeltreltoabs(L,[1, 2]~): error("incorrect type in rnfeltreltoabs (t_COL)." ) rnfeltreltoabs(M,[1, 2]~): error("incorrect type in rnfeltreltoabs (t_COL)." ) rnfeltup(L,[1, 2]~): error("incorrect type in nf_to_scalar_or_basis (t_COL). ") rnfeltup(M,[1, 2]~): error("incorrect type in nf_to_scalar_or_basis (t_COL). ") rnfeltdown(L,[1, 2]~): error("incorrect type in rnfeltdown (t_COL).") rnfeltdown(M,[1, 2]~): error("incorrect type in rnfeltdown (t_COL).") rnfelttrace(L,[1, 2]~): error("incorrect type in rnfeltabstorel, apply nfini t(rnf) (t_COL).") rnfelttrace(M,[1, 2]~): error("incorrect type in rnfeltabstorel, apply nfini t(rnf) (t_COL).") rnfeltnorm(L,[1, 2]~): error("incorrect type in rnfeltabstorel, apply nfinit (rnf) (t_COL).") rnfeltnorm(M,[1, 2]~): error("incorrect type in rnfeltabstorel, apply nfinit (rnf) (t_COL).") rnfalgtobasis(L,[y]~): error("inconsistent dimensions in rnfalgtobasis.") rnfalgtobasis(M,[y]~): [Mod(y, y^3 - 21)]~ rnfbasistoalg(L,[y]~): error("inconsistent operation 'RgV_RgC_mul' t_VEC (2 elts) , t_COL (1 elts).") rnfbasistoalg(M,[y]~): Mod(Mod(y, y^3 - 21), x) rnfeltabstorel(L,[y]~): error("incorrect type in rnfeltabstorel, apply nfini t(rnf) (t_COL).") rnfeltabstorel(M,[y]~): error("incorrect type in rnfeltabstorel, apply nfini t(rnf) (t_COL).") rnfeltreltoabs(L,[y]~): error("incorrect type in rnfeltreltoabs (t_COL).") rnfeltreltoabs(M,[y]~): error("incorrect type in rnfeltreltoabs (t_COL).") rnfeltup(L,[y]~): Mod(y, x^2 + 1) rnfeltup(M,[y]~): error("incorrect type in nf_to_scalar_or_basis (t_COL).") rnfeltdown(L,[y]~): error("incorrect type in rnfeltdown (t_COL).") rnfeltdown(M,[y]~): error("incorrect type in rnfeltdown (t_COL).") rnfelttrace(L,[y]~): error("incorrect type in rnfeltabstorel, apply nfinit(r nf) (t_COL).") rnfelttrace(M,[y]~): error("incorrect type in rnfeltabstorel, apply nfinit(r nf) (t_COL).") rnfeltnorm(L,[y]~): error("incorrect type in rnfeltabstorel, apply nfinit(rn f) (t_COL).") rnfeltnorm(M,[y]~): error("incorrect type in rnfeltabstorel, apply nfinit(rn f) (t_COL).") 1: x^2 - 4*x + 4 2: x^2 - x + 1/4 3: x^2 + 2*x + 2 4: x^2 - x + 1/4 5: x^2 + 2*x + 1 6: x^2 - 2*x + 5/4 7: x^2 + 1 8: x^2 + 1 9: error("inconsistent moduli in rnfcharpoly: x^2 - y != y + 1") 10: x^2 + 1 11: error("incorrect type in rnfcharpoly (t_COL).") 12: error("incorrect type in rnfcharpoly (t_COL).") 13: error("incorrect type in rnfcharpoly (t_COL).") Mod(1, x^2 - 2) 0 [[1, -66328; 0, 1], [[280970, 12259, 35869; 0, 1, 0; 0, 0, 1], [1, 1/2, 1/2; 0, 1/2, 0; 0, 0, 1/2]]] 1 [280970, x^2 + 12259, x^4 + 35869, -x^4 + x - 66328, -1/2*x^4 + 1/2*x^3 - 33 164*x^2 + 1/2*x - 66349/2, 1/2*x^5 - 66329/2*x^4 - 21/2*x^2 + 1/2*x - 33164] 1 [[3, [0, 1, 0, 0, 0, 0]~, 6, 1]] [[[7, [0, 1, 0]~, 3, 1]], [[7, [0, 1, 0, 0, 0, 0]~, 6, 1]]] [[89, [-21, 1, 0]~, 1, 1, [17, 1, 22; 21, -4, 1; 1, 21, 17]]] [[7, [0, 1, 0, 0, 0, 0]~, 6, 1] 6] [[3, [0, 1, 0, 0, 0, 0]~, 6, 1] 1] [[7, [0, 1, 0, 0, 0, 0]~, 6, 1] 1] [[3, [0, 1, 0, 0, 0, 0]~, 6, 1] 2] [[7, [0, 1, 0, 0, 0, 0]~, 6, 1] 2] 1 [18416, x^2 + 6979, x^4 + 3879, -9208*x^4 + 9208*x, -6979/2*x^4 + 1/2*x^3 + 6979/2*x - 21/2, 1/2*x^5 - 3879/2*x^4 - 21/2*x^2 + 3879/2*x] 1 1 1 [280970 12259 35869] [ 0 1 0] [ 0 0 1] [280970, x^2 + 12259, x^4 + 35869, -140485*x^4 + 140485*x, -12259/2*x^4 + 1/ 2*x^3 + 12259/2*x - 21/2, 1/2*x^5 - 35869/2*x^4 - 21/2*x^2 + 35869/2*x] 1 1: [[1, 0; 0, 1], [2, 1]] [2, 2*x^2, 2*x^4, -x^4 + x, x^3 - 21, x^5 - 21*x^2] error("incorrect type in rnfidealabstorel (t_INT).") 2 [2, 2*x^2, 2*x^4, -x^4 + x, x^3 - 21, x^5 - 21*x^2] [4, 0, 0; 0, 4, 0; 0, 0, 4] 64 [2, 0] 2: [[1, 0; 0, 1], [1/2, 1/4]] [1/2, 1/2*x^2, 1/2*x^4, -1/4*x^4 + 1/4*x, 1/4*x^3 - 21/4, 1/4*x^5 - 21/4*x^2 ] error("incorrect type in rnfidealabstorel (t_FRAC).") 1/2 [1/2, 1/2*x^2, 1/2*x^4, -1/4*x^4 + 1/4*x, 1/4*x^3 - 21/4, 1/4*x^5 - 21/4*x^2 ] [1/4, 0, 0; 0, 1/4, 0; 0, 0, 1/4] 1/64 [1/2, 0] 3: [[1, 42; 0, 1], [[210, 189, 189; 0, 1, 0; 0, 0, 1], [1, 1/2, 1/2; 0, 1/2, 0; 0, 0, 1/2]]] [210, x^2 + 189, x^4 + 189, -x^4 + x + 42, -1/2*x^4 + 1/2*x^3 + 21*x^2 + 1/2 *x + 21/2, 1/2*x^5 + 41/2*x^4 - 21/2*x^2 + 1/2*x + 21] error("incorrect type in rnfidealabstorel (t_POL).") [210, 189, 189; 0, 1, 0; 0, 0, 1] error("inconsistent variables in nf_to_scalar_or_basis, x != y.") [420, 399, 399; 0, 1, 0; 0, 0, 1] 420 [210, Mod(x + Mod(105*y - 84, y^3 - 21), x^2 + Mod(-y, y^3 - 21))] 4: [[1, 0; 0, 1], [1, 1/2]] [1, x^2, x^4, -1/2*x^4 + 1/2*x, 1/2*x^3 - 21/2, 1/2*x^5 - 21/2*x^2] error("incorrect type in rnfidealabstorel (t_POLMOD).") 1 [1, x^2, x^4, -1/2*x^4 + 1/2*x, 1/2*x^3 - 21/2, 1/2*x^5 - 21/2*x^2] [1, 0, 0; 0, 1, 0; 0, 0, 1] 1 [1, 0] 5: [[1, 0; 0, 1], [1/2, 1/4]] [1/2, 1/2*x^2, 1/2*x^4, -1/4*x^4 + 1/4*x, 1/4*x^3 - 21/4, 1/4*x^5 - 21/4*x^2 ] error("incorrect type in rnfidealabstorel (t_POLMOD).") 1/2 [1/2, 1/2*x^2, 1/2*x^4, -1/4*x^4 + 1/4*x, 1/4*x^3 - 21/4, 1/4*x^5 - 21/4*x^2 ] [1/4, 0, 0; 0, 1/4, 0; 0, 0, 1/4] 1/64 [1/2, 0] 6: [[1, 0; 0, 1], [[21, 0, 0; 0, 1, 0; 0, 0, 1], [21/2, 0, 0; 0, 1/2, 0; 0, 0, 1/2]]] [21, x^2, x^4, -21/2*x^4 + 21/2*x, 1/2*x^3 - 21/2, 1/2*x^5 - 21/2*x^2] error("incorrect type in rnfidealabstorel (t_POLMOD).") [21, 0, 0; 0, 1, 0; 0, 0, 1] [21, x^2, x^4, -21/2*x^4 + 21/2*x, 1/2*x^3 - 21/2, 1/2*x^5 - 21/2*x^2] [21, 0, 0; 0, 21, 0; 0, 0, 1] 441 [21, Mod(Mod(y, y^3 - 21), x^2 + Mod(-y, y^3 - 21))] 7: error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("incorrect type in rnfidealabstorel (t_POLMOD).") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("inconsistent moduli in nf_to_scalar_or_basis: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") 8: error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("incorrect type in rnfidealabstorel (t_POLMOD).") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("inconsistent moduli in nf_to_scalar_or_basis: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") 9: error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("incorrect type in rnfidealabstorel (t_POLMOD).") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("inconsistent moduli in nf_to_scalar_or_basis: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: x^6 - 21 != y^3 - 21") 10: [[1, -756; 0, 1], [[903/2, 84, 336; 0, 1/2, 0; 0, 0, 1/2], 1/4]] [903/2, 1/2*x^2 + 84, 1/2*x^4 + 336, -1/4*x^4 + 1/4*x - 189, 1/4*x^3 - 189*x ^2 - 21/4, 1/4*x^5 - 189*x^4 - 21/4*x^2] error("incorrect type in rnfidealabstorel (t_POLMOD).") [903/2, 84, 336; 0, 1/2, 0; 0, 0, 1/2] error("inconsistent moduli in nf_to_scalar_or_basis: x^2 - y != y^3 - 21") [903/4, 42, 168; 0, 1/4, 0; 0, 0, 1/4] 903/64 [903/2, Mod(1/2*x - 42, x^2 + Mod(-y, y^3 - 21))] 11: [[1, 0; 0, 1], [[21, 0, 0; 0, 1, 0; 0, 0, 1], [21/2, 0, 0; 0, 1/2, 0; 0, 0, 1/2]]] [21, x^2, x^4, -21/2*x^4 + 21/2*x, 1/2*x^3 - 21/2, 1/2*x^5 - 21/2*x^2] error("incorrect type in rnfidealabstorel (t_POL).") [21, 0, 0; 0, 1, 0; 0, 0, 1] [21, x^2, x^4, -21/2*x^4 + 21/2*x, 1/2*x^3 - 21/2, 1/2*x^5 - 21/2*x^2] [21, 0, 0; 0, 21, 0; 0, 0, 1] 441 [21, Mod(Mod(y, y^3 - 21), x^2 + Mod(-y, y^3 - 21))] 12: error("inconsistent variables in rnfbasistoalg, z != x.") error("inconsistent variables in rnfbasistoalg, z != x.") error("incorrect type in rnfidealabstorel (t_POL).") error("inconsistent variables in rnfbasistoalg, z != x.") error("inconsistent variables in nf_to_scalar_or_basis, z != y.") error("inconsistent variables in rnfbasistoalg, z != x.") error("inconsistent variables in rnfbasistoalg, z != x.") error("inconsistent variables in rnfbasistoalg, z != x.") 13: error("inconsistent moduli in rnfbasistoalg: y^2 + 1 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: y^2 + 1 != y^3 - 21") error("incorrect type in rnfidealabstorel (t_POLMOD).") error("inconsistent moduli in rnfbasistoalg: y^2 + 1 != y^3 - 21") error("inconsistent moduli in nf_to_scalar_or_basis: y^2 + 1 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: y^2 + 1 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: y^2 + 1 != y^3 - 21") error("inconsistent moduli in rnfbasistoalg: y^2 + 1 != y^3 - 21") 14: error("inconsistent operation 'RgV_RgC_mul' t_VEC (2 elts) , t_COL (1 elts). ") error("inconsistent operation 'RgV_RgC_mul' t_VEC (2 elts) , t_COL (1 elts). ") error("incorrect type in rnfidealabstorel (t_COL).") error("inconsistent operation 'RgV_RgC_mul' t_VEC (2 elts) , t_COL (1 elts). ") error("incorrect type in nf_to_scalar_or_basis (t_COL).") error("inconsistent operation 'RgV_RgC_mul' t_VEC (2 elts) , t_COL (1 elts). ") error("inconsistent operation 'RgV_RgC_mul' t_VEC (2 elts) , t_COL (1 elts). ") error("inconsistent operation 'RgV_RgC_mul' t_VEC (2 elts) , t_COL (1 elts). ") 15: [[1, -5371968; 0, 1], [[10743937, 8099895, 3524829; 0, 1, 0; 0, 0, 1], 1/2]] [10743937, x^2 + 8099895, x^4 + 3524829, -1/2*x^4 + 1/2*x - 2685984, 1/2*x^3 - 2685984*x^2 - 21/2, 1/2*x^5 - 2685984*x^4 - 21/2*x^2] error("incorrect type in rnfidealabstorel (t_COL).") [10743937, 8099895, 3524829; 0, 1, 0; 0, 0, 1] error("incorrect type in nf_to_scalar_or_basis (t_COL).") [10743937, 8099895, 3524829; 0, 1, 0; 0, 0, 1] 10743937 [10743937, Mod(x - 1847139, x^2 + Mod(-y, y^3 - 21))] 16: [[1, [0, 0, -18]~; 0, 1], [379, 1/2]] [379, 379*x^2, 379*x^4, -19/2*x^4 + 1/2*x, 1/2*x^3 - 399/2, 1/2*x^5 - 399/2* x^2] error("incorrect type in rnfidealabstorel (t_COL).") 379 error("incorrect type in nf_to_scalar_or_basis (t_COL).") [379, 0, 0; 0, 379, 0; 0, 0, 379] 54439939 [379, Mod(Mod(1/2*y, y^3 - 21)*x + 359/2, x^2 + Mod(-y, y^3 - 21))] 17: error("incorrect type in nf_to_scalar_or_alg (t_COMPLEX).") error("incorrect type in nf_to_scalar_or_alg (t_COMPLEX).") error("incorrect type in rnfidealabstorel (t_COL).") error("incorrect type in nf_to_scalar_or_alg (t_COMPLEX).") error("incorrect type in nf_to_scalar_or_basis (t_COL).") error("incorrect type in nf_to_scalar_or_alg (t_COMPLEX).") error("incorrect type in nf_to_scalar_or_alg (t_COMPLEX).") error("incorrect type in nf_to_scalar_or_alg (t_COMPLEX).") 18: error("incorrect type in rnfbasistoalg [not in Q[X]] (t_POL).") error("incorrect type in rnfbasistoalg [not in Q[X]] (t_POL).") error("incorrect type in rnfidealabstorel (t_POL).") error("incorrect type in rnfbasistoalg [not in Q[X]] (t_POL).") error("incorrect type in poltobasis (t_POL).") error("incorrect type in rnfbasistoalg [not in Q[X]] (t_POL).") error("incorrect type in rnfbasistoalg [not in Q[X]] (t_POL).") error("incorrect type in rnfbasistoalg [not in Q[X]] (t_POL).") 19: [[1, 0; 0, 1], [[21, 0, 0; 0, 1, 0; 0, 0, 1], [21/2, 0, 0; 0, 1/2, 0; 0, 0, 1/2]]] [21, x^2, x^4, -21/2*x^4 + 21/2*x, 1/2*x^3 - 21/2, 1/2*x^5 - 21/2*x^2] error("incorrect type in rnfidealabstorel (t_POL).") [21, 0, 0; 0, 1, 0; 0, 0, 1] error("inconsistent variables in nf_to_scalar_or_basis, x != y.") [21, 0, 0; 0, 21, 0; 0, 0, 1] 441 [21, Mod(Mod(y, y^3 - 21), x^2 + Mod(-y, y^3 - 21))] 20: [[;], []] [] [[;], []] [;] [] [;] 0 [0, 0] 21: [[;], []] [] [[;], []] [;] error("incorrect type in idealtyp [fake prime ideal] (t_VEC).") [;] 0 [0, 0] 22: [[;], []] [] error("incorrect type in rnfidealabstorel (t_INT).") [;] [] [;] 0 [0, 0] 23: [[;], []] [] error("inconsistent dimensions in rnfidealabstorel.") [;] [] [;] 0 [0, 0] 24: error("inconsistent dimensions in rnfidealabstorel.") error("inconsistent dimensions in rnfidealabstorel.") error("inconsistent dimensions in rnfidealabstorel.") error("inconsistent dimensions in rnfidealabstorel.") [2, x^2 + 1, x^4 + 1, -x^4 + x, -1/2*x^4 + 1/2*x^3 + 1/2*x - 21/2, 1/2*x^5 - 1/2*x^4 - 21/2*x^2 + 1/2*x] error("inconsistent dimensions in rnfidealabstorel.") error("inconsistent dimensions in rnfidealabstorel.") error("inconsistent dimensions in rnfidealabstorel.") 25: error("inconsistent dimensions in rnfidealabstorel.") error("inconsistent dimensions in rnfidealabstorel.") error("inconsistent dimensions in rnfidealabstorel.") error("incorrect type in idealhnf [wrong dimension] (t_MAT).") [18416, x^2 + 6979, x^4 + 3879, -9208*x^4 + 9208*x, -6979/2*x^4 + 1/2*x^3 + 6979/2*x - 21/2, 1/2*x^5 - 3879/2*x^4 - 21/2*x^2 + 3879/2*x] error("inconsistent dimensions in rnfidealabstorel.") error("inconsistent dimensions in rnfidealabstorel.") error("inconsistent dimensions in rnfidealabstorel.") 26: [[1, -66328; 0, 1], [[280970, 12259, 35869; 0, 1, 0; 0, 0, 1], [1, 1/2, 1/2; 0, 1/2, 0; 0, 0, 1/2]]] [280970, x^2 + 12259, x^4 + 35869, -x^4 + x - 66328, -1/2*x^4 + 1/2*x^3 - 33 164*x^2 + 1/2*x - 66349/2, 1/2*x^5 - 66329/2*x^4 - 21/2*x^2 + 1/2*x - 33164] [[1, -66328; 0, 1], [[280970, 12259, 35869; 0, 1, 0; 0, 0, 1], [1, 1/2, 1/2; 0, 1/2, 0; 0, 0, 1/2]]] [280970, 12259, 35869; 0, 1, 0; 0, 0, 1] error("inconsistent dimensions in idealtwoelt.") [561940, 12259, 316839; 0, 1, 0; 0, 0, 1] 561940 [280970, Mod(x + Mod(-140485*y + 110026, y^3 - 21), x^2 + Mod(-y, y^3 - 21)) ] 27: [[1, -66328; 0, 1], [[280970, 12259, 35869; 0, 1, 0; 0, 0, 1], [1, 1/2, 1/2; 0, 1/2, 0; 0, 0, 1/2]]] [280970, x^2 + 12259, x^4 + 35869, -x^4 + x - 66328, -1/2*x^4 + 1/2*x^3 - 33 164*x^2 + 1/2*x - 66349/2, 1/2*x^5 - 66329/2*x^4 - 21/2*x^2 + 1/2*x - 33164] [[1, -66328; 0, 1], [[280970, 12259, 35869; 0, 1, 0; 0, 0, 1], [1, 1/2, 1/2; 0, 1/2, 0; 0, 0, 1/2]]] [280970, 12259, 35869; 0, 1, 0; 0, 0, 1] error("incorrect type in idealtyp [fake prime ideal] (t_VEC).") [561940, 12259, 316839; 0, 1, 0; 0, 0, 1] 561940 [280970, Mod(x + Mod(-140485*y + 110026, y^3 - 21), x^2 + Mod(-y, y^3 - 21)) ] 28: [[1, -66328; 0, 1], [[280970, 12259, 35869; 0, 1, 0; 0, 0, 1], [1, 1/2, 1/2; 0, 1/2, 0; 0, 0, 1/2]]] [280970, x^2 + 12259, x^4 + 35869, -x^4 + x - 66328, -1/2*x^4 + 1/2*x^3 - 33 164*x^2 + 1/2*x - 66349/2, 1/2*x^5 - 66329/2*x^4 - 21/2*x^2 + 1/2*x - 33164] error("inconsistent dimensions in rnfidealabstorel.") [280970, 12259, 35869; 0, 1, 0; 0, 0, 1] error("inconsistent dimensions in idealtwoelt.") [561940, 12259, 316839; 0, 1, 0; 0, 0, 1] 561940 [280970, Mod(x + Mod(-140485*y + 110026, y^3 - 21), x^2 + Mod(-y, y^3 - 21)) ] [[;], []] [[;], []] [[1, 0; 0, 1], [[21, 0, 0; 0, 21, 0; 0, 0, 1], [21/2, 0, 0; 0, 1/2, 0; 0, 0, 1/2]]] [[1, 0; 0, 1], [[21, 0, 0; 0, 21, 0; 0, 0, 1], [21/2, 0, 0; 0, 1/2, 0; 0, 0, 1/2]]] [[1, -347298; 0, 1], [[5900370, 2821959, 5374299; 0, 1, 0; 0, 0, 1], [1, 1/2 , 1/2; 0, 1/2, 0; 0, 0, 1/2]]] [[1, -347298; 0, 1], [[5900370, 2821959, 5374299; 0, 1, 0; 0, 0, 1], [1, 1/2 , 1/2; 0, 1/2, 0; 0, 0, 1/2]]] [1 0 0] [0 1 0] [0 0 1] [280970 12259/2 316839/2] [ 0 1/2 0] [ 0 0 1/2] [1 -1 [-1/2, -1/2]~] [0 1 [1/2, 1/2]~] 1 [1/2, -1/12*x^3 - 1/12*x, -1/12*x^3 + 5/12*x, -1/24*x^3 - 1/8*x^2 + 5/24*x + 1/8] 0 [[[205009, 37462, 127633; 0, 1, 0; 0, 0, 1], [0, 0, 0]], Mat(3)] [[[1163, 141, 32; 0, 1, 0; 0, 0, 1], [1, 0, 0]], Mat(2)] 0 [[1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], []] [[[36, 0; 0, 36], []], [[2, [2, 0]~, 1, 2, 1], 2; [3, [-1, 1]~, 2, 1, [-1, - 1; 1, -2]], 4]] 0 1 1 1 [0, [[1, 0, -1; 0, 1, [0, -1]~; 0, 0, 1], [1, 1, 1/3]], 5] [0, [[1, 0, 0; 0, 1, 0; 0, 0, 1], [1, 1, [1, 1/2; 0, 1/2]]], 2] [1, [[1, 0, 0; 0, 1, 0; 0, 0, 1], [1, 1, 1]], 8] 0 1 0 0 1 [[433, 318, 322, 1318/17; 0, 1, 0, 5/17; 0, 0, 1, 12/17; 0, 0, 0, 1/17], [25 /17, 12/17, -12/17, 16/17]~] [1, -1] [[12, 0, 0, 0; 0, 12, 4, 0; 0, 0, 4, 0; 0, 0, 0, 4], [6, 5, -1, 2]~] *** Warning: new stack size = 12000000 (11.444 Mbytes). [1, [-1, 0, -5, 0, 4, 0, 2, 0, -2, 0, -3, 0, 3, 0, 1, 0, -2, 0, -2, 0, 4, 0, 3, 0, -7, 0, 4, 0, -1, 0, 5, 0, -8, 2, 5, 1, -4, -1, 5, 0, -4, -1, 5, -2, - 3, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]~] *** at top-level: rnfdedekind(nf,P,pr2,1) *** ^----------------------- *** rnfdedekind: sorry, Dedekind in the difficult case is not yet implemented. *** at top-level: rnfdedekind(nf,P) *** ^----------------- *** rnfdedekind: sorry, Dedekind in the difficult case is not yet implemented. *** at top-level: rnfdedekind(nf,P,[pr2,pr3]) *** ^--------------------------- *** rnfdedekind: sorry, Dedekind in the difficult case is not yet implemented. *** at top-level: rnfdedekind(nf,x^2) *** ^------------------- *** rnfdedekind: domain error in rnfdedekind: issquarefree(pol) = 0 *** at top-level: rnfconductor(nf,x^2) *** ^-------------------- *** rnfconductor: incorrect type in checkbnf [please apply bnfinit()] (t_VEC). *** at top-level: rnfconductor(nf,[x^2,1]) *** ^------------------------ *** rnfconductor: incorrect type in checkbnf [please apply bnfinit()] (t_VEC). *** at top-level: rnfpseudobasis(nf,x^2/2+1) *** ^-------------------------- *** rnfpseudobasis: sorry, nonmonic relative polynomials in rnfallbase is not yet implemented. *** at top-level: rnfpseudobasis(nf,x^2+1/2) *** ^-------------------------- *** rnfpseudobasis: impossible inverse in Fl_inv: Mod(0, 2). *** at top-level: rnfpseudobasis(nf,x^2) *** ^---------------------- *** rnfpseudobasis: domain error in rnfpseudobasis: issquarefree(pol) = 0 *** at top-level: rnfeltnorm(x,x) *** ^--------------- *** rnfeltnorm: incorrect type in checkrnf (t_POL). *** at top-level: rnfelttrace(x,x) *** ^---------------- *** rnfelttrace: incorrect type in checkrnf (t_POL). *** at top-level: rnfislocalcyclo(rnfinit(K,x^6-y+1)) *** ^----------------------------------- *** rnfislocalcyclo: sorry, rnfislocalcyclo for non-l-extensions is not yet implemented. *** at top-level: rnfidealtwoelt(L,[[1;0],[1/104]]) *** ^--------------------------------- *** rnfidealtwoelt: incorrect type in idealtyp [nonsquare t_MAT] (t_MAT). *** at top-level: bnfinit(rnf) *** ^------------ *** bnfinit: incorrect type in checknf [please apply nfinit()] (t_VEC). [[13752104408392050085222299912837424016744346918215907754003059659430226886 5203518397679148347720654316386840367785157190137487454547848, 2959570140384 0008752126889275684782087998403235378132669994230963941569723600340025047099 92462649028358180476038782378726113404321956; 0, 371584220729649394547077712 6096031739262741319686634426034412234116662922714846511467163377330801518008 56981442689032724], [-177846162678347392861779010175300647931976968103167121 4616746896704286594334662045803530653683643332613227600515985901534558021, - 1756839977043712272060233380581107042236141123409211618384398509656714409036 54196479376831010271529801027728469404407277067209]~] Total time spent: 1334 pari-2.17.2/src/test/32/galoisinit0000644000175000017500000001703114676526175015270 0ustar billbill *** Warning: new stack size = 16000000 (15.259 Mbytes). [2, 1] [16, 10] [20, 3] [24, 12] [4, 2] [4, 2] [4, 2] [4, 2] [12, 3] [24, 12] [36, 9] [54, 11] [54, 14] [64, 66] [8, 5] [4, 2] [14, 1] *** at top-level: do(x^48+688253440*x^36+64889579202*x^24+688253 *** ^---------------------------------------------- *** in function do: galoisidentify(galoisinit(p)) *** ^----------------------------- *** galoisidentify: incorrect type in checkgal (t_INT). [-x + 3, x]~ [x]~ [-x, x]~ [-x, x, -x^3, x^3]~ [11 0 0 10 7 1] [ 0 11 0 6 1 1] [ 0 0 11 7 1 5] [ 0 0 0 1 0 0] [ 0 0 0 0 1 0] [ 0 0 0 0 0 1] [11, [9, 10, 5, 10, 6, 10]~, 1, 3, [10, 0, 0, -1, -4, 1; 4, 10, 0, -1, -5, - 3; 5, 4, 10, -1, -5, -4; 1, 5, 4, 9, -5, -4; 0, 1, 5, 3, 5, -4; 0, 0, 1, 4, -1, 6]] Mod(x^4 + x^2, x^6 + x^5 + x^4 + x^3 + x^2 + x + 1) 1/2 [1, 1] [1, 1/2] [1, Mod(x^2, x^6 + x^5 + x^4 + x^3 + x^2 + x + 1)] [1, Mod(x^2, x^6 + x^5 + x^4 + x^3 + x^2 + x + 1)] [1, [0, 0, 0, 0, 0, 0]~] [1, [;]] [1, [1, 2; Mod(x^2, x^6 + x^5 + x^4 + x^3 + x^2 + x + 1), 3]] [25343300/14121030321*x^11 + 162850/4707010107*x^9 - 251993549/4707010107*x^ 7 - 9261852590/14121030321*x^5 + 13704094421/4707010107*x^3 + 21375212764/52 3001123*x, -25343300/14121030321*x^11 - 162850/4707010107*x^9 + 251993549/47 07010107*x^7 + 9261852590/14121030321*x^5 - 13704094421/4707010107*x^3 - 213 75212764/523001123*x, -6335825/14121030321*x^11 - 174397/1046002246*x^10 - 8 1425/9414020214*x^9 + 2174305/3138006738*x^8 + 251993549/18828040428*x^7 + 2 776168/523001123*x^6 + 4630926295/28242060642*x^5 + 33788356/523001123*x^4 - 13704094421/18828040428*x^3 - 645447089/1569003369*x^2 - 20852211641/209200 4492*x - 2869448765/1046002246] "Group((1, 5)(2, 10)(3, 11)(4, 6)(7, 9)(8, 12), (1, 8)(2, 3)(4, 7)(5, 12)(6, 9)(10, 11), (1, 2, 7)(3, 9, 12)(4, 5, 11)(6, 8, 10))" "PermutationGroup<12|[5, 10, 11, 6, 1, 4, 9, 12, 7, 2, 3, 8], [8, 3, 2, 7, 1 2, 9, 4, 1, 6, 11, 10, 5], [2, 7, 9, 5, 11, 8, 1, 10, 12, 6, 4, 3]>" [[[Vecsmall([10, 7, 11, 9, 6, 5, 2, 12, 4, 1, 3, 8]), Vecsmall([12, 1, 9, 5, 3, 11, 10, 2, 6, 8, 4, 7]), Vecsmall([3, 9, 10, 2, 8, 12, 4, 6, 7, 11, 1, 5 ])], Vecsmall([2, 3, 2])], [[Vecsmall([10, 7, 11, 9, 6, 5, 2, 12, 4, 1, 3, 8 ]), Vecsmall([12, 1, 9, 5, 3, 11, 10, 2, 6, 8, 4, 7])], Vecsmall([2, 3])], [ [Vecsmall([10, 7, 11, 9, 6, 5, 2, 12, 4, 1, 3, 8]), Vecsmall([3, 9, 10, 2, 8 , 12, 4, 6, 7, 11, 1, 5])], Vecsmall([2, 2])], [[Vecsmall([10, 7, 11, 9, 6, 5, 2, 12, 4, 1, 3, 8]), Vecsmall([6, 11, 2, 12, 1, 10, 3, 4, 8, 5, 7, 9])], Vecsmall([2, 2])], [[Vecsmall([10, 7, 11, 9, 6, 5, 2, 12, 4, 1, 3, 8]), Vecs mall([9, 6, 8, 1, 2, 7, 5, 11, 10, 4, 12, 3])], Vecsmall([2, 2])], [[Vecsmal l([10, 7, 11, 9, 6, 5, 2, 12, 4, 1, 3, 8])], Vecsmall([2])], [[Vecsmall([8, 10, 4, 6, 11, 3, 1, 7, 5, 12, 9, 2])], Vecsmall([3])], [[], Vecsmall([])]] [1, 1, 0, 0, 0, 1, 1, 1] [0, [2, 1; 0, 3], [2, 1; 0, 2], [2, 1; 0, 2], [2, 1; 0, 2], Mat(2), Mat(3), [;]] [0, 1, 1, 1, 1, 1, 1, 1] [0, [6], [4], [4], [4], [2], [3], []] [[Vecsmall([1]), Vecsmall([2]), Vecsmall([3]), Vecsmall([4]), Vecsmall([5]), Vecsmall([6]), Vecsmall([7]), Vecsmall([8]), Vecsmall([9]), Vecsmall([10]), Vecsmall([11]), Vecsmall([12])], [Vecsmall([1, 12, 7, 10, 8, 2]), Vecsmall( [3, 9, 6, 11, 4, 5])], [Vecsmall([1, 7, 8]), Vecsmall([2, 12, 10]), Vecsmall ([3, 6, 4]), Vecsmall([5, 9, 11])], [Vecsmall([1, 10]), Vecsmall([2, 7]), Ve csmall([3, 11]), Vecsmall([4, 9]), Vecsmall([5, 6]), Vecsmall([8, 12])], [Ve csmall([1, 8, 7]), Vecsmall([2, 10, 12]), Vecsmall([3, 4, 6]), Vecsmall([5, 11, 9])], [Vecsmall([1, 2, 8, 10, 7, 12]), Vecsmall([3, 5, 4, 11, 6, 9])], [ Vecsmall([1, 3, 10, 11]), Vecsmall([2, 9, 7, 4]), Vecsmall([5, 8, 6, 12])], [Vecsmall([1, 9, 10, 4]), Vecsmall([2, 6, 7, 5]), Vecsmall([3, 8, 11, 12])], [Vecsmall([1, 6, 10, 5]), Vecsmall([2, 11, 7, 3]), Vecsmall([4, 12, 9, 8])] , [Vecsmall([1, 11, 10, 3]), Vecsmall([2, 4, 7, 9]), Vecsmall([5, 12, 6, 8]) ], [Vecsmall([1, 4, 10, 9]), Vecsmall([2, 5, 7, 6]), Vecsmall([3, 12, 11, 8] )], [Vecsmall([1, 5, 10, 6]), Vecsmall([2, 3, 7, 11]), Vecsmall([4, 8, 9, 12 ])]] [1, 6, 3, 2, 3, 6, 4, 4, 4, 4, 4, 4] [1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1] [x^12 - 24*x^10 - 10*x^9 + 216*x^8 + 180*x^7 - 844*x^6 - 1080*x^5 + 1056*x^4 + 2200*x^3 + 720*x^2 - 240*x - 80, x^2 - 30*x + 180, x^4 - 30*x^3 + 180*x^2 + 1080*x - 6480, x^6 - 18*x^4 + 20*x^3 + 36*x^2 - 60*x + 20, x^4 - 30*x^3 + 180*x^2 + 1080*x - 6480, x^2 - 30*x + 180, x^3 - 30*x + 50, x^3 - 12*x + 14 , x^3 - 12*x - 4, x^3 - 30*x + 50, x^3 - 12*x + 14, x^3 - 12*x - 4] [x^2 - 30*x + 180, Mod(3/4*x^9 - 27/2*x^7 - 9/2*x^6 + 81*x^5 + 54*x^4 - 162* x^3 - 162*x^2 + 30, x^12 - 24*x^10 - 10*x^9 + 216*x^8 + 180*x^7 - 844*x^6 - 1080*x^5 + 1056*x^4 + 2200*x^3 + 720*x^2 - 240*x - 80)] [y^2 - 30*y + 180, Mod(3/4*x^9 - 27/2*x^7 - 9/2*x^6 + 81*x^5 + 54*x^4 - 162* x^3 - 162*x^2 + 30, x^12 - 24*x^10 - 10*x^9 + 216*x^8 + 180*x^7 - 844*x^6 - 1080*x^5 + 1056*x^4 + 2200*x^3 + 720*x^2 - 240*x - 80), [x^6 - 12*x^4 - 1/3* y*x^3 + 36*x^2 + 2*y*x + (4/3*y - 20), x^6 - 12*x^4 + (1/3*y - 10)*x^3 + 36* x^2 + (-2*y + 60)*x + (-4/3*y + 20)]] [y - 5, Mod(5, x^9 - 5*x^8 - 70*x^7 + 269*x^6 + 1591*x^5 - 4531*x^4 - 11255* x^3 + 29326*x^2 + 7688*x - 29791), [x^9 - 5*x^8 - 70*x^7 + 269*x^6 + 1591*x^ 5 - 4531*x^4 - 11255*x^3 + 29326*x^2 + 7688*x - 29791]] x^2 + x - 4 x - 1 1 [x - 1, 1] x^6 + 21*x^4 + 116*x^2 + 64 [6, 2] x^6 + 21*x^4 + 116*x^2 + 64 x^2 - x - 16 x^2 - x - 16 [x^8 - x^6 + x^4 - x^2 + 1, [101, 2, 10201], [7607, 567, 5596, 6117, 2594, 9 634, 4605, 4084], [2678, 1546, 2875, 8203, 2678, 1546, 2875, 8203; 9382, 964 6, 819, 555, 819, 555, 9382, 9646; 197, 6657, 10004, 3544, 197, 6657, 10004, 3544; 9497, 1523, 9233, 149, 704, 8678, 968, 10052; 4676, 9069, 1329, 5328, 4676, 9069, 1329, 5328; 8870, 8166, 9689, 8721, 1331, 2035, 512, 1480; 9069 , 1329, 5328, 4676, 9069, 1329, 5328, 4676; 10052, 704, 8678, 968, 149, 9497 , 1523, 9233], 1, [Vecsmall([1, 2, 3, 4, 5, 6, 7, 8]), Vecsmall([2, 3, 4, 1, 6, 7, 8, 5]), Vecsmall([3, 4, 1, 2, 7, 8, 5, 6]), Vecsmall([4, 1, 2, 3, 8, 5, 6, 7]), Vecsmall([5, 6, 7, 8, 1, 2, 3, 4]), Vecsmall([6, 7, 8, 5, 2, 3, 4 , 1]), Vecsmall([7, 8, 5, 6, 3, 4, 1, 2]), Vecsmall([8, 5, 6, 7, 4, 1, 2, 3] )], [Vecsmall([2, 3, 4, 1, 6, 7, 8, 5]), Vecsmall([5, 6, 7, 8, 1, 2, 3, 4])] , Vecsmall([4, 2])] [[x, Mod(0, x^8 - x^6 + x^4 - x^2 + 1)], [x^2 + 1, Mod(-x^5, x^8 - x^6 + x^4 - x^2 + 1)], [x^2 - 2*x - 4, Mod(-2*x^6 + 2*x^4 + 2, x^8 - x^6 + x^4 - x^2 + 1)], [x^2 + 5, Mod(2*x^7 - x^5 + 2*x^3, x^8 - x^6 + x^4 - x^2 + 1)], [x^4 + 3*x^2 + 1, Mod(x^7 - x^5 + x^3, x^8 - x^6 + x^4 - x^2 + 1)], [x^4 - 2*x^3 + 4*x^2 - 8*x + 16, Mod(2*x^2, x^8 - x^6 + x^4 - x^2 + 1)], [x^4 - 5*x^2 + 5 , Mod(-x^7 + x^5 - x^3 + 2*x, x^8 - x^6 + x^4 - x^2 + 1)], [x^8 - x^6 + x^4 - x^2 + 1, Mod(x, x^8 - x^6 + x^4 - x^2 + 1)]] [[z, Mod(0, x^6 + 108), [x^6 + 108]], [z^2 + 972, Mod(3*x^3, x^6 + 108), [x^ 3 - 1/3*z, x^3 + 1/3*z]], [z^3 + 54, Mod(1/12*x^4 + 3/2*x, x^6 + 108), [x^2 - z*x + 1/3*z^2, x^2 + 1/3*z^2, x^2 + z*x + 1/3*z^2]], [z^3 + 864, Mod(2*x^2 , x^6 + 108), [x^2 - 1/2*z, x^2 - 1/24*z^2*x - 1/2*z, x^2 + 1/24*z^2*x - 1/2 *z]], [z^3 - 54, Mod(-1/12*x^4 + 3/2*x, x^6 + 108), [x^2 - z*x + 1/3*z^2, x^ 2 + z*x + 1/3*z^2, x^2 + 1/3*z^2]], [z^6 + 108, Mod(x, x^6 + 108), [x - z, x + (-1/12*z^4 + 1/2*z), x + (1/12*z^4 + 1/2*z), x + (-1/12*z^4 - 1/2*z), x + (1/12*z^4 - 1/2*z), x + z]]] [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4] 0 59 59 [60, 5] [108, 15] *** at top-level: galoispermtopol(G,[4,3,6,5,1,2]) *** ^-------------------------------- *** galoispermtopol: incorrect type in galoispermtopol (t_VEC). Total time spent: 2542 pari-2.17.2/src/test/32/elliptic0000644000175000017500000001202214724330077014712 0ustar billbill echo = 1 ? ellinit([-1,0]) [0, 0, 0, -1, 0, 0, -2, 0, -1, 48, 0, 64, 1728, Vecsmall([1]), [Vecsmall([12 8, 1])], [0, 0, 0, 0, 0, 0, 0, 0]] ? ellinit([-17,0],1) [0, 0, 0, -17, 0, 0, -34, 0, -289, 816, 0, 314432, 1728, Vecsmall([1]), [Vec small([128, 1])], [0, 0, 0, 0, 0, 0, 0, 0]] ? ellsub(%,[-1,4],[-4,2]) [9, -24] ? ellj(I) 1728.0000000000000000000000000000000000 ? acurve=ellinit([0,0,1,-1,0]) [0, 0, 1, -1, 0, 0, -2, 1, -1, 48, -216, 37, 110592/37, Vecsmall([1]), [Vecs mall([128, 1])], [0, 0, 0, 0, 0, 0, 0, 0]] ? apoint=[2,2] [2, 2] ? elladd(acurve,apoint,apoint) [21/25, -56/125] ? ellak(acurve,1000000007) 43800 ? ellan(acurve,100) [1, -2, -3, 2, -2, 6, -1, 0, 6, 4, -5, -6, -2, 2, 6, -4, 0, -12, 0, -4, 3, 1 0, 2, 0, -1, 4, -9, -2, 6, -12, -4, 8, 15, 0, 2, 12, -1, 0, 6, 0, -9, -6, 2, -10, -12, -4, -9, 12, -6, 2, 0, -4, 1, 18, 10, 0, 0, -12, 8, 12, -8, 8, -6, -8, 4, -30, 8, 0, -6, -4, 9, 0, -1, 2, 3, 0, 5, -12, 4, 8, 9, 18, -15, 6, 0 , -4, -18, 0, 4, 24, 2, 4, 12, 18, 0, -24, 4, 12, -30, -2] ? ellap(acurve,10007) 66 ? deu=direuler(p=2,100,1/(1-ellap(acurve,p)*x+if(acurve.disc%p,p,0)*x^2)) [1, -2, -3, 2, -2, 6, -1, 0, 6, 4, -5, -6, -2, 2, 6, -4, 0, -12, 0, -4, 3, 1 0, 2, 0, -1, 4, -9, -2, 6, -12, -4, 8, 15, 0, 2, 12, -1, 0, 6, 0, -9, -6, 2, -10, -12, -4, -9, 12, -6, 2, 0, -4, 1, 18, 10, 0, 0, -12, 8, 12, -8, 8, -6, -8, 4, -30, 8, 0, -6, -4, 9, 0, -1, 2, 3, 0, 5, -12, 4, 8, 9, 18, -15, 6, 0 , -4, -18, 0, 4, 24, 2, 4, 12, 18, 0, -24, 4, 12, -30, -2] ? ellan(acurve,100)==deu 1 ? ellisoncurve(acurve,apoint) 1 ? acurve=ellchangecurve(acurve,[-1,1,2,3]) [-4, -1, -7, -12, -12, 12, 4, 1, -1, 48, -216, 37, 110592/37, Vecsmall([1]), [Vecsmall([128, 1])], [0, 0, 0, 0, 0, 0, 0, 0]] ? apoint=ellchangepoint(apoint,[-1,1,2,3]) [1, 3] ? ellisoncurve(acurve,apoint) 1 ? ellglobalred(acurve) [37, [1, -1, 2, 2], 1, Mat([37, 1]), [[1, 5, 0, 1]]] ? ellheight(acurve,apoint) 0.81778253183950144377417759611107234575 ? ellordinate(acurve,1) [8, 3] ? ellpointtoz(acurve,apoint) 0.72491221490962306778878739838332384646 ? ellztopoint(acurve,%) [1.0000000000000000000000000000000000000, 3.00000000000000000000000000000000 00000] ? ellmul(acurve,apoint,10) [-28919032218753260057646013785951999/292736325329248127651484680640160000, 478051489392386968218136375373985436596569736643531551/158385319626308443937 475969221994173751192384064000000] ? ellwp(acurve,x+O(x^33)) x^-2 + 1/5*x^2 - 1/28*x^4 + 1/75*x^6 - 3/1540*x^8 + 1943/3822000*x^10 - 1/11 550*x^12 + 193/10510500*x^14 - 1269/392392000*x^16 + 21859/34684650000*x^18 - 1087/9669660000*x^20 + 22179331/1060517858400000*x^22 - 463/124093970000*x ^24 + 47495017/70175140035000000*x^26 - 34997918161/291117454720092000000*x^ 28 + O(x^30) ? q*Ser(ellan(acurve,100),q) q - 2*q^2 - 3*q^3 + 2*q^4 - 2*q^5 + 6*q^6 - q^7 + 6*q^9 + 4*q^10 - 5*q^11 - 6*q^12 - 2*q^13 + 2*q^14 + 6*q^15 - 4*q^16 - 12*q^18 - 4*q^20 + 3*q^21 + 10* q^22 + 2*q^23 - q^25 + 4*q^26 - 9*q^27 - 2*q^28 + 6*q^29 - 12*q^30 - 4*q^31 + 8*q^32 + 15*q^33 + 2*q^35 + 12*q^36 - q^37 + 6*q^39 - 9*q^41 - 6*q^42 + 2* q^43 - 10*q^44 - 12*q^45 - 4*q^46 - 9*q^47 + 12*q^48 - 6*q^49 + 2*q^50 - 4*q ^52 + q^53 + 18*q^54 + 10*q^55 - 12*q^58 + 8*q^59 + 12*q^60 - 8*q^61 + 8*q^6 2 - 6*q^63 - 8*q^64 + 4*q^65 - 30*q^66 + 8*q^67 - 6*q^69 - 4*q^70 + 9*q^71 - q^73 + 2*q^74 + 3*q^75 + 5*q^77 - 12*q^78 + 4*q^79 + 8*q^80 + 9*q^81 + 18*q ^82 - 15*q^83 + 6*q^84 - 4*q^86 - 18*q^87 + 4*q^89 + 24*q^90 + 2*q^91 + 4*q^ 92 + 12*q^93 + 18*q^94 - 24*q^96 + 4*q^97 + 12*q^98 - 30*q^99 - 2*q^100 + O( q^101) ? bcurve=ellinit([-3,0]) [0, 0, 0, -3, 0, 0, -6, 0, -9, 144, 0, 1728, 1728, Vecsmall([1]), [Vecsmall( [128, 1])], [0, 0, 0, 0, 0, 0, 0, 0]] ? elllocalred(bcurve,2) [6, 2, [1, 0, 0, 0], 1] ? elltaniyama(bcurve) [x^-2 - x^2 + 3*x^6 - 2*x^10 + 7*x^14 + O(x^15), -x^-3 + 3*x - 3*x^5 + 8*x^9 - 9*x^13 + O(x^14)] ? ccurve=ellinit([0,0,-1,-1,0]) [0, 0, -1, -1, 0, 0, -2, 1, -1, 48, -216, 37, 110592/37, Vecsmall([1]), [Vec small([128, 1])], [0, 0, 0, 0, 0, 0, 0, 0]] ? l=elllseries(ccurve,2) 0.38157540826071121129371040958008663668 ? exponent(elllseries(ccurve,2,1.2)-l)<-125 1 ? tcurve=ellinit([1,0,1,-19,26]); ? ellorder(tcurve,[1,2]) 6 ? elltors(tcurve) [12, [6, 2], [[1, 2], [3, -2]]] ? mcurve=ellinit([-17,0]); ? mpoints=[[-1,4],[-4,2]]~; ? mhbi=ellbil(mcurve,mpoints,[9,24]) [-0.72448571035980184146215805860545027440, 1.307328627832055544492943428892 1943056]~ ? ma=ellheightmatrix(mcurve,mpoints) [1.1721830987006970106016415566698834135 0.447697388340895169139483498064433 13906] [0.44769738834089516913948349806443313906 1.75502601617295071363242692695662 74446] ? matsolve(ma,mhbi) [-1.0000000000000000000000000000000000000, 1.0000000000000000000000000000000 000000]~ ? cmcurve=ellinit([0,-3/4,0,-2,-1]) [0, -3/4, 0, -2, -1, -3, -4, -4, -1, 105, 1323, -343, -3375, Vecsmall([1]), [Vecsmall([128, -1])], [0, 0, 0, 0, 0, 0, 0, 0]] ? ellmul(cmcurve,[x,y],quadgen(-7)) [((-2 + 3*w)*x^2 + (6 - w))/((-2 - 5*w)*x + (-4 - 2*w)), ((34 - 11*w)*y*x^2 + (40 - 28*w)*y*x + (22 + 23*w)*y)/((-90 - w)*x^2 + (-136 + 44*w)*x + (-40 + 28*w))] ? if(getheap()!=HEAP,getheap()) ? print("Total time spent: ",gettime); Total time spent: 46 pari-2.17.2/src/test/32/polmodular0000644000175000017500000000012414676526175015277 0ustar billbill *** Warning: new stack size = 18000000 (17.166 Mbytes). Total time spent: 22625 pari-2.17.2/src/test/32/combinat0000644000175000017500000001130714567450071014710 0ustar billbill[3628800, -10628640, 12753576, -8409500, 3416930, -902055, 157773, -18150, 1 320, -55] [-39916800, 120543840, -150917976, 105258076, -45995730, 13339535, -2637558, 357423, -32670, 1925, -66] [1, 1023, 28501, 145750, 246730, 179487, 63987, 11880, 1155, 55] [1, 2047, 86526, 611501, 1379400, 1323652, 627396, 159027, 22275, 1705, 66] [Vecsmall([1, 2, 3, 4, 5]), Vecsmall([1, 2, 3, 5, 4]), Vecsmall([1, 2, 4, 3, 5]), Vecsmall([1, 2, 4, 5, 3]), Vecsmall([1, 2, 5, 3, 4]), Vecsmall([1, 2, 5, 4, 3]), Vecsmall([1, 3, 2, 4, 5]), Vecsmall([1, 3, 2, 5, 4]), Vecsmall([1 , 3, 4, 2, 5]), Vecsmall([1, 3, 4, 5, 2]), Vecsmall([1, 3, 5, 2, 4]), Vecsma ll([1, 3, 5, 4, 2]), Vecsmall([1, 4, 2, 3, 5]), Vecsmall([1, 4, 2, 5, 3]), V ecsmall([1, 4, 3, 2, 5]), Vecsmall([1, 4, 3, 5, 2]), Vecsmall([1, 4, 5, 2, 3 ]), Vecsmall([1, 4, 5, 3, 2]), Vecsmall([1, 5, 2, 3, 4]), Vecsmall([1, 5, 2, 4, 3]), Vecsmall([1, 5, 3, 2, 4]), Vecsmall([1, 5, 3, 4, 2]), Vecsmall([1, 5, 4, 2, 3]), Vecsmall([1, 5, 4, 3, 2]), Vecsmall([2, 1, 3, 4, 5]), Vecsmall ([2, 1, 3, 5, 4]), Vecsmall([2, 1, 4, 3, 5]), Vecsmall([2, 1, 4, 5, 3]), Vec small([2, 1, 5, 3, 4]), Vecsmall([2, 1, 5, 4, 3]), Vecsmall([2, 3, 1, 4, 5]) , Vecsmall([2, 3, 1, 5, 4]), Vecsmall([2, 3, 4, 1, 5]), Vecsmall([2, 3, 4, 5 , 1]), Vecsmall([2, 3, 5, 1, 4]), Vecsmall([2, 3, 5, 4, 1]), Vecsmall([2, 4, 1, 3, 5]), Vecsmall([2, 4, 1, 5, 3]), Vecsmall([2, 4, 3, 1, 5]), Vecsmall([ 2, 4, 3, 5, 1]), Vecsmall([2, 4, 5, 1, 3]), Vecsmall([2, 4, 5, 3, 1]), Vecsm all([2, 5, 1, 3, 4]), Vecsmall([2, 5, 1, 4, 3]), Vecsmall([2, 5, 3, 1, 4]), Vecsmall([2, 5, 3, 4, 1]), Vecsmall([2, 5, 4, 1, 3]), Vecsmall([2, 5, 4, 3, 1]), Vecsmall([3, 1, 2, 4, 5]), Vecsmall([3, 1, 2, 5, 4]), Vecsmall([3, 1, 4 , 2, 5]), Vecsmall([3, 1, 4, 5, 2]), Vecsmall([3, 1, 5, 2, 4]), Vecsmall([3, 1, 5, 4, 2]), Vecsmall([3, 2, 1, 4, 5]), Vecsmall([3, 2, 1, 5, 4]), Vecsmal l([3, 2, 4, 1, 5]), Vecsmall([3, 2, 4, 5, 1]), Vecsmall([3, 2, 5, 1, 4]), Ve csmall([3, 2, 5, 4, 1]), Vecsmall([3, 4, 1, 2, 5]), Vecsmall([3, 4, 1, 5, 2] ), Vecsmall([3, 4, 2, 1, 5]), Vecsmall([3, 4, 2, 5, 1]), Vecsmall([3, 4, 5, 1, 2]), Vecsmall([3, 4, 5, 2, 1]), Vecsmall([3, 5, 1, 2, 4]), Vecsmall([3, 5 , 1, 4, 2]), Vecsmall([3, 5, 2, 1, 4]), Vecsmall([3, 5, 2, 4, 1]), Vecsmall( [3, 5, 4, 1, 2]), Vecsmall([3, 5, 4, 2, 1]), Vecsmall([4, 1, 2, 3, 5]), Vecs mall([4, 1, 2, 5, 3]), Vecsmall([4, 1, 3, 2, 5]), Vecsmall([4, 1, 3, 5, 2]), Vecsmall([4, 1, 5, 2, 3]), Vecsmall([4, 1, 5, 3, 2]), Vecsmall([4, 2, 1, 3, 5]), Vecsmall([4, 2, 1, 5, 3]), Vecsmall([4, 2, 3, 1, 5]), Vecsmall([4, 2, 3, 5, 1]), Vecsmall([4, 2, 5, 1, 3]), Vecsmall([4, 2, 5, 3, 1]), Vecsmall([4 , 3, 1, 2, 5]), Vecsmall([4, 3, 1, 5, 2]), Vecsmall([4, 3, 2, 1, 5]), Vecsma ll([4, 3, 2, 5, 1]), Vecsmall([4, 3, 5, 1, 2]), Vecsmall([4, 3, 5, 2, 1]), V ecsmall([4, 5, 1, 2, 3]), Vecsmall([4, 5, 1, 3, 2]), Vecsmall([4, 5, 2, 1, 3 ]), Vecsmall([4, 5, 2, 3, 1]), Vecsmall([4, 5, 3, 1, 2]), Vecsmall([4, 5, 3, 2, 1]), Vecsmall([5, 1, 2, 3, 4]), Vecsmall([5, 1, 2, 4, 3]), Vecsmall([5, 1, 3, 2, 4]), Vecsmall([5, 1, 3, 4, 2]), Vecsmall([5, 1, 4, 2, 3]), Vecsmall ([5, 1, 4, 3, 2]), Vecsmall([5, 2, 1, 3, 4]), Vecsmall([5, 2, 1, 4, 3]), Vec small([5, 2, 3, 1, 4]), Vecsmall([5, 2, 3, 4, 1]), Vecsmall([5, 2, 4, 1, 3]) , Vecsmall([5, 2, 4, 3, 1]), Vecsmall([5, 3, 1, 2, 4]), Vecsmall([5, 3, 1, 4 , 2]), Vecsmall([5, 3, 2, 1, 4]), Vecsmall([5, 3, 2, 4, 1]), Vecsmall([5, 3, 4, 1, 2]), Vecsmall([5, 3, 4, 2, 1]), Vecsmall([5, 4, 1, 2, 3]), Vecsmall([ 5, 4, 1, 3, 2]), Vecsmall([5, 4, 2, 1, 3]), Vecsmall([5, 4, 2, 3, 1]), Vecsm all([5, 4, 3, 1, 2]), Vecsmall([5, 4, 3, 2, 1])] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 2 1, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 4 0, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 5 9, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 7 8, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 9 7, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 2 1, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 4 0, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 5 9, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 7 8, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 9 7, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119] 0 ["e_TYPE", "permtonum", [1, 3, 0]] *** at top-level: permtonum(1) *** ^------------ *** permtonum: incorrect type in permtonum (t_INT). 0 Vecsmall([]) Total time spent: 4 pari-2.17.2/src/test/32/gchar0000644000175000017500000002435414676526175014220 0ustar billbill *** Warning: new stack size = 10000000 (9.537 Mbytes). one large field [10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] non trivial cm subfield [1 0 0] [0 1 0] [0 0 0] [0 0 0] [0 0 0] [0 0 0] [0 0 0] [0 0 1] 1 [[9, 7], [7, 9], [0, 16], [16, 0]] [-2, 8*I] [2, 8*I] [16, 8*I] [-16, 8*I] 8 1 [[5, 5], [5, 5], [0, 10], [10, 0]] [0, 5*I] [0, 5*I] [10, 5*I] [-10, 5*I] 5 gcharalgebraic 6 2 1 1 [] 1 1 1 [[2, 1], [1, 2]] [1, 2]~ 1 [[4, 0]] gcharisalgebraic r1>0 1 [[0, 0], [0, 0]] 1 [[0, 0], [0, 0]] 0 1 [[1, 0], [1, 0]] 0 1 [[0, 0], [0, 0]] 1 [[0, 0], [0, 0]] 1 [[0, 0], [0, 0]] 0 0 1 [[1, 0], [1, 1]] 0 need to increase prec larger fields r2 = 5, clno = 5 r2 = 4, clno = 3 r2 = 8, clno = 16 gcharidentify 1 1 1 [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]~ [1 0 0] [0 1 0] [0 0 1] [129024, 12, 12, 12, 6, 0, 0, 0, 0, 0, 0] 7 2 1 2 prec increase [444, 12, 2, 2, 0, 0, 0] 1 1 1 1 limit cases [0] [1] [1 0] [0 1] [] [ 0] [ 0] [ 0] [-1] [] [[0, 0, 0, 0]~] [[0, 0, 0, -1]~] [[0, 0, 0]~] [0, -1]~ [[0, 0, -1]~] [] gcharisalgebraic 0 1 0 0 gcharduallog [0, 0, 600000000000000000000, 200000000000000000000, 0] [89110698909568455589, -89110698909568455589, -300000000000000000000, -10000 0000000000000000, 0] 1 gchareval 1 169 169 gcharidentify 2 [0, 0] [5]~ 1 gcharlocal [0, 652850] [0, -652850] [0, 652850] [0, -652850] [100000, 108808] [0, -108808] [100000, 108808 - 300000*I] [0, -108808 + 200000*I] [0, 891192] [6, 2] 6 0 3 0 2 0 [0, 0, 0] [0, 105380] [200000, -52690] [-11811] [6, 2] 6 0 doc gcharidentify [0, 13.057005210545987626926134713745179631] 0.30000006229129706787363344444425752636 1 1 [0, 0] 1 1 1 1 doc gcharinit [0, 0, 0, 0] [5 4 1 4] [0 1 0 0] [0 0 1 0] [0 0 0 1] doc gcharalgebraic [6, 0, 0, 0, 0] 4 2 1 [] -1 doc gcharconductor [8892, 6, 2, 0, 0] [[61009, 7267; 0, 169], [1, 0]] [[4693, 559; 0, 13], [1, 0]] [[247, 65; 0, 13], [1, 0]] [[19, 5; 0, 1], [0, 0]] doc gcharduallog [2, 0, 0, 0] "t_VEC" 1 doc gcharisalgebraic [0, 0, 0, 0] 0 [-3, -0.89110698909568455588720672648627467040] 1 [[6, 0], [2, 4]] [-6, 3*I] doc gcharalgebraic part 2 [2, 2, 0, 0, 0] [1, 0, 0, 4, 5, 0, 0, 0, 9, 0, 16, 0, 0, 0, 0, 16, 0, 0, 16, 20] [1, 0, 0, 4, 5, 0, 0, 0, 9, 0, 16, 0, 0, 0, 0, 16, 0, 0, 16, 20] [1, 0, 0, 4, 5, 0, 0, 0, 9, 0, 16, 0, 0, 0, 0, 16, 0, 0, 16, 20] [1, 0, 0, 4, 5, 0, 0, 0, 9, 0, 16, 0, 0, 0, 0, 16, 0, 0, 16, 20] [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0] [0] [1, 0, 0, -2, 0, 0, -1, 0, 0, 0, 0, 0, 5, 0, 0, 4, 0, 0, -7, 0] [1, 0, 0, -2, 0, 0, -1, 0, 0, 0, 0, 0, 5, 0, 0, 4, 0, 0, -7, 0] [3, 0, 0, 0] 1 [1, 0, -3, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, -6, 0, -3, 0] [1, 0, -3, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, -6, 0, -3, 0] doc gcharlocal [0, 0, 0] [0, -4.8839310048284836274074581373242545693 - 1/3*I] [6, 2.4419655024142418137037290686621272847 - 1/3*I] [0.11546513518429312402440891592110333661 + 0.085383333121129357912721832603 542830928*I] [600, 3, 0, 0] [24, 3] 24 -21/50 [100] 50 -0.30120819117478336291229946188762973702 doc gcharlog [3, 0, 0, 0] "t_COL" 1 doc gchareval -3804107379 - 9248176417*I -3121086862 1 prime sort bug 1 LLL erase bug 1 bestS fix [2, 0, 0] 1 1 bug #2373 over Q [0, 1] [0, 256150*I]~ 1/5 200000 [0, -I] [256150*I] [1] [[-2]~] [1, [0]] 1 [[-1, 0]] [-1]~ [0, 0, 1] [0, 0, 256150*I]~ 1/5 200000 [0, -I] [256150*I] [0, 110318*I] [1] [[-1]~] [1, [0]] 1 [[-1, 0]] [-1]~ bug in length checks [0, -I] bad inputs *** at top-level: gcharinit([],1) *** ^--------------- *** gcharinit: incorrect type in checknf [please apply nfinit()] (t_VEC). *** at top-level: gcharinit(bnfinit(x),[]) *** ^------------------------ *** gcharinit: incorrect type in idealtyp [fake prime ideal] (t_VEC). *** at top-level: gcharinit(bnfinit(x),[1,[]]) *** ^---------------------------- *** gcharinit: incorrect type in Idealstar [incorrect archimedean component] (t_VEC). *** at top-level: gcharidentify([],[1],[[0,0]]) *** ^----------------------------- *** gcharidentify: incorrect type in char group (t_VEC). *** at top-level: gcharidentify('gc,[1],[[0,0]]) *** ^------------------------------ *** gcharidentify: incorrect type in char group (t_POL). *** at top-level: gcharidentify(gc,[1,1],[[0,0],[0,0]]) *** ^------------------------------------- *** gcharidentify: components of Lv must be distinct. *** at top-level: gcharidentify(gc,[1,0],[[0,0],[0,0]]) *** ^------------------------------------- *** gcharidentify: domain error in gcharidentify: v <= 0 *** at top-level: gcharidentify(gc,[1,3],[[0,0],[0,0]]) *** ^------------------------------------- *** gcharidentify: domain error in gcharidentify: v > 2 *** at top-level: gcharidentify(gc,[1,[]],[[0,0],[0,0]]) *** ^-------------------------------------- *** gcharidentify: incorrect type in idealtyp [fake prime ideal] (t_VEC). *** at top-level: gcharidentify(gc,[1,'x],[[0,0],[0,0]]) *** ^-------------------------------------- *** gcharidentify: incorrect type in gcharidentify [ideal] (t_POL). *** at top-level: gcharidentify(gc,[[]],[1.]) *** ^--------------------------- *** gcharidentify: incorrect type in idealtyp [fake prime ideal] (t_VEC). *** at top-level: gcharidentify(gc,[pr],[1+O(3^7)]) *** ^--------------------------------- *** gcharidentify: incorrect type in gcharidentify [character value: should be real or complex] (t_PADIC). *** at top-level: gcharidentify(gc,[pr],['x]) *** ^--------------------------- *** gcharidentify: incorrect type in gcharidentify [character value: should be real or complex] (t_POL). *** at top-level: gcharidentify(gc,[1],['x]) *** ^-------------------------- *** gcharidentify: incorrect type in gcharidentify [character at infinite place: should be a t_VEC] (t_POL). *** at top-level: gcharidentify(gc,[1],[[]]) *** ^-------------------------- *** gcharidentify: inconsistent dimensions in gcharidentify [character at infinite place: should have two components]. *** at top-level: gcharidentify(gc,[1],[[0.1,0]]) *** ^------------------------------- *** gcharidentify: incorrect type in gcharidentify [k parameter at infinite place: should be a t_INT] (t_REAL). *** at top-level: gcharidentify(gc,[1],[[0,O(3^7)]]) *** ^---------------------------------- *** gcharidentify: incorrect type in gcharidentify [phi parameter at infinite place: should be real or complex] (t_PADIC). *** at top-level: gcharidentify(gc,[1],[0,0]) *** ^--------------------------- *** gcharidentify: inconsistent dimensions in gcharidentify [#Lv != #Lchiv]. *** at top-level: gcharidentify(gc,[pr],[0]) *** ^-------------------------- *** gcharidentify: elements not coprime in gcharidentify: [101, [-48, 0, 1, 0]~, 1, 1, [12, 114, -30, 3; 49, 11, 29, -114; -19, -29, -104, -30; 48, -49, -19, 12]] Mat([[101, [-48, 0, 1, 0]~, 1, 1, [12, 114, -30, 3; 49, 11, 29, -114; -19, -29, -104, -30; 48, -49, -19, 12]], 1]) *** at top-level: gcharnewprec(gc) *** ^---------------- *** gcharnewprec: incorrect type in char group (t_INT). *** at top-level: gcharnewprec(gc) *** ^---------------- *** gcharnewprec: incorrect type in gchar group (basis) (t_VEC). *** at top-level: gcharnewprec(gc) *** ^---------------- *** gcharnewprec: incorrect type in gchar group (gc[8]) (t_VEC). *** at top-level: gcharidentify(gc,[],[]) *** ^----------------------- *** gcharidentify: precision too low in gchar group, please call gcharnewprec. *** at top-level: gcharalgebraic(gc,0) *** ^-------------------- *** gcharalgebraic: incorrect type in gcharalgebraic (1) (t_INT). *** at top-level: gcharalgebraic(gc,[1..10]) *** ^-------------------------- *** gcharalgebraic: incorrect type in gcharalgebraic (1) (t_VEC). *** at top-level: gcharalgebraic(gc,[0]) *** ^---------------------- *** gcharalgebraic: incorrect type in gcharalgebraic (2) (t_VEC). *** at top-level: gcharalgebraic(gc,[[]]) *** ^----------------------- *** gcharalgebraic: incorrect type in gcharalgebraic (2) (t_VEC). *** at top-level: gcharalgebraic(gc,[[0,[]]]) *** ^--------------------------- *** gcharalgebraic: incorrect type in gcharalgebraic (2) (t_VEC). *** at top-level: gcharalgebraic(gc,[[[],0]]) *** ^--------------------------- *** gcharalgebraic: incorrect type in gcharalgebraic (2) (t_VEC). *** at top-level: gchareval(gc,O(3^7),1,0) *** ^------------------------ *** gchareval: incorrect type in check_gchar [chi] (t_PADIC). *** at top-level: gchareval(gc,[0,O(3^7)],1,0) *** ^---------------------------- *** gchareval: incorrect type in check_gchar [chi] (t_VEC). *** at top-level: chareval(gc,[0]~,1) *** ^------------------- *** chareval: incorrect type in chareval [use gchareval to evaluate a grossencharacter] (t_VEC). *** at top-level: gcharisalgebraic(gc,[1]) *** ^------------------------ *** gcharisalgebraic: incorrect type in check_gchar [chi] (t_VEC). *** at top-level: gcharalgebraic(gc,[]) *** ^--------------------- *** gcharalgebraic: incorrect type in gcharalgebraic (1) (t_VEC). *** at top-level: gcharalgebraic(gc,[[1,1]]) *** ^-------------------------- *** gcharalgebraic: incorrect type in gcharalgebraic (1) (t_VEC). *** at top-level: gcharlocal(gc,[0,1]~,0) *** ^----------------------- *** gcharlocal: domain error in gcharlocal [index of an infinite place]: v <= 0 *** at top-level: gcharlocal(gc,[0,1]~,3) *** ^----------------------- *** gcharlocal: domain error in gcharlocal [index of an infinite place]: v > 2 *** at top-level: gcharlocal(gc,[0,1,O(5^2)]~,1) *** ^------------------------------ *** gcharlocal: incorrect type in check_gchar_i [s] (t_PADIC). Total time spent: 4230 pari-2.17.2/src/test/32/modpoly0000644000175000017500000000000014567450071014563 0ustar billbillpari-2.17.2/src/test/32/memory0000644000175000017500000000141414676526175014434 0ustar billbill *** Warning: new stack size = 1048576 (1.000 Mbytes). *** at top-level: vector(100000,k,k) *** ^-- *** the PARI stack overflows ! current stack size: 1048576 (1.000 Mbytes) [hint] set 'parisizemax' to a nonzero value in your GPRC *** Warning: new stack size = 102400 (0.098 Mbytes). *** Warning: new stack size = 1048576 (1.000 Mbytes). *** I was expecting an integer here: 1kb *** ^--- *** I was expecting an integer here: 1nB *** ^--- *** I was expecting an integer here: 1gB *** ^--- *** I was expecting an integer here: 1mB *** ^--- Total time spent: 1 pari-2.17.2/src/test/32/export0000644000175000017500000000112214567450071014427 0ustar billbill2 395 *** at top-level: parsum(i=1,10,f(i)) *** ^------------------- *** parsum: mt: attempt to change exported variable 'z'. *** at top-level: parsum(i=1,10,f(i)) *** ^------------------- *** parsum: mt: attempt to change exported variable 'z'. *** at top-level: parsum(i=1,10,f(i)) *** ^------------------- *** parsum: mt: attempt to change exported variable 'z'. "parallel" "sequential" "parallel" "parallel" "parallel" "parallel" "parallel" "parallel" "parallel" "parallel" "sequential" "parallel" Total time spent: 0 pari-2.17.2/src/test/32/ffisom0000644000175000017500000000036314567450071014377 0ustar billbill-------------e=0-------------- -------------e=1-------------- -------------e=2-------------- -------------e=3-------------- -------------e>=4-------------- ----------large p--------------- ----------huge p--------------- Total time spent: 430 pari-2.17.2/src/test/32/subgroup0000644000175000017500000000206614567450071014764 0ustar billbill[53835600, 29] [5, 0; 0, 1] [10, 0; 0, 1] [[12, 0; 0, 1]] [] [] *** at top-level: forsubgroup(h=[2,3],2,print(h)) *** ^--------- *** incorrect type in forsubgroup [not a finite group] (t_VEC). [] group: 1 1 1 1 alpha_lambda(mu,p) = 1 countsub = 1 alpha_lambda(mu,p) = 15 subgroup: 1 countsub = 15 alpha_lambda(mu,p) = 35 subgroup: 1 1 countsub = 35 alpha_lambda(mu,p) = 15 subgroup: 1 1 1 countsub = 15 alpha_lambda(mu,p) = 1 subgroup: 1 1 1 1 countsub = 1 nb subgroup = 67 67 *** at top-level: subgrouplist(1) *** ^--------------- *** subgrouplist: incorrect type in clgp (t_INT). *** at top-level: subgrouplist([2,2],[2]~) *** ^------------------------ *** subgrouplist: sorry, exact type in subgrouplist is not yet implemented. *** at top-level: subgrouplist([2,2],-1) *** ^---------------------- *** subgrouplist: domain error in subgroup: index bound <= 0 [Mat(2), Mat(3), Mat(1)] [Mat(3)] Total time spent: 1 pari-2.17.2/src/test/32/ellisomat0000644000175000017500000002324514676526175015123 0ustar billbill *** Warning: new stack size = 14000000 (13.351 Mbytes). -32768:[1, 11; 11, 1]:[0, 0] -121:[1, 11; 11, 1]:[0, 0] -24729001:[1, 11; 11, 1]:[0, 0] -297756989/2:[1, 17; 17, 1]:[0, 0] -882216989/131072:[1, 17; 17, 1]:[0, 0] -884736:[1, 19; 19, 1]:[0, 0] -9317:[1, 37; 37, 1]:[0, 0] -162677523113838677:[1, 37; 37, 1]:[0, 0] -884736000:[1, 43; 43, 1]:[0, 0] -147197952000:[1, 67; 67, 1]:[0, 0] -262537412640768000:[1, 163; 163, 1]:[0, 0] 0:[1, 3, 2, 6; 3, 1, 6, 2; 2, 6, 1, 3; 6, 2, 3, 1]:[0, 0, 0, 0] 1728:[1, 2, 4, 4; 2, 1, 2, 2; 4, 2, 1, 4; 4, 2, 4, 1]:[0, 0, 0, 0] -3375:[1, 2, 7, 14; 2, 1, 14, 7; 7, 14, 1, 2; 14, 7, 2, 1]:[0, 0, 0, 0] 8000:[1, 2; 2, 1]:[0, 0] 54000:[1, 3, 2, 6; 3, 1, 6, 2; 2, 6, 1, 3; 6, 2, 3, 1]:[0, 0, 0, 0] 287496:[1, 2, 4, 4; 2, 1, 2, 2; 4, 2, 1, 4; 4, 2, 4, 1]:[0, 0, 0, 0] -12288000:[1, 3, 9, 27; 3, 1, 3, 9; 9, 3, 1, 3; 27, 9, 3, 1]:[0, 0, 0, 0] 16581375:[1, 2, 7, 14; 2, 1, 14, 7; 7, 14, 1, 2; 14, 7, 2, 1]:[0, 0, 0, 0] 9938375/21952:[1, 3, 3, 2, 6, 6; 3, 1, 9, 6, 2, 18; 3, 9, 1, 6, 18, 2; 2, 6, 6, 1, 3, 3; 6, 2, 18, 3, 1, 9; 6, 18, 2, 3, 9, 1]:[0, 0, 0, 0, 0, 0] 111284641/50625:[1, 2, 4, 4, 2, 2, 4, 4; 2, 1, 2, 2, 4, 4, 8, 8; 4, 2, 1, 4, 8, 8, 16, 16; 4, 2, 4, 1, 8, 8, 16, 16; 2, 4, 8, 8, 1, 4, 8, 8; 2, 4, 8, 8, 4, 1, 2, 2; 4, 8, 16, 16, 8, 2, 1, 4; 4, 8, 16, 16, 8, 2, 4, 1]:[0, 0, 0, 0 , 0, 0, 0, 0] -10218313/17576:[1, 3, 3; 3, 1, 9; 3, 9, 1]:[0, 0, 0] -25/2:[1, 3, 5, 15; 3, 1, 15, 5; 5, 15, 1, 3; 15, 5, 3, 1]:[0, 0, 0, 0] [[[[-31/3, -2501/108], [x - 1/3, y + 1/2, 1], [x + 1/3, y - 1/2, 1]], [[-234 61/3, -28748141/108], [x^5 - 127/3*x^4 + 2177*x^3 - 91861/3*x^2 + 171618*x - 980197/3, (y + 1/2)*x^6 + (-63*y - 63/2)*x^5 + (y + 1/2)*x^4 + (1977*y + 19 77/2)*x^3 + (7626*y + 3813)*x^2 + (11654*y + 5827)*x + (6682*y + 3341), x^2 - 21*x + 80], [1/25*x^5 + 127/15*x^4 + 30467/45*x^3 + 3309581/135*x^2 + 1445 85559/405*x + 4710599326/6075, (1/125*y - 1/2)*x^6 + (61/25*y - 305/2)*x^5 + (117098/375*y - 290702/15)*x^4 + (72436097/3375*y - 70930739/54)*x^3 + (281 9744498/3375*y - 33802537858/675)*x^2 + (176778054473/10125*y - 824769156301 /810)*x + (13938798626101/91125*y - 1572185782385639/182250), x^2 + 305/3*x + 116279/45]], [[-625/3, 296875/108], [x^5 + 5/3*x^4 + 85/3*x^3 - 935/3*x^2 - 2245/3*x - 3166/3, (y + 1/2)*x^6 + (3*y + 3/2)*x^5 + (-54*y - 27)*x^4 + (6 13*y + 613/2)*x^3 + (1752*y + 876)*x^2 + (8585*y + 8585/2)*x + (6451*y + 645 1/2), x^2 + x - 29/5], [1/25*x^5 - 1/3*x^4 + 325/9*x^3 + 34375/27*x^2 - 1562 500/81*x + 40234375/243, (1/125*y - 1/2)*x^6 + (-1/5*y + 25/2)*x^5 + (-35/3* y + 625/6)*x^4 + (-14375/27*y - 171875/54)*x^3 + (231250/27*y - 390625/27)*x ^2 + (-19062500/81*y + 19531250/81)*x + (792968750/729*y + 976562500/729), x ^2 - 25/3*x - 1250/9]]], [1, 5, 5; 5, 1, 25; 5, 25, 1]] [[[[215/48, -5291/864], [x + 1/12, 1/2*x + (y + 1/2), 1], [x - 1/12, -1/2*x + (y - 11/24), 1]], [[-1705/48, -57707/864], [x^3 - 23/12*x^2 + 53/6*x - 95/ 12, 1/2*x^4 + (y - 1)*x^3 + (-3*y - 4)*x^2 + (-5*y + 1)*x + (7*y + 7/2), x - 1], [1/4*x^3 + x^2 - 291/64*x - 41483/3456, -1/8*x^4 + (1/8*y - 61/48)*x^3 + (13/16*y - 791/384)*x^2 + (1705/384*y + 13429/3456)*x + (48919/6912*y + 32 8367/41472), x + 13/6]]], [1, 2; 2, 1]] [[[[215/48, -5291/864], [x + 1/12, 1/2*x + (y + 1/2), 1], [x - 1/12, -1/2*x + (y - 11/24), 1]], [[-675/16, 6831/32], [x^3 + 3/4*x^2 + 19/2*x - 311/12, 1 /2*x^4 + (y + 1)*x^3 + (y - 4)*x^2 + (-9*y + 23)*x + (55*y + 55/2), x + 1/3] , [1/9*x^3 - 1/4*x^2 - 141/16*x + 5613/64, -1/18*x^4 + (1/27*y - 1/3)*x^3 + (-1/12*y + 87/16)*x^2 + (49/16*y - 48)*x + (-3601/64*y + 16947/512), x - 3/4 ]], [[-8185/48, -742643/864], [x^3 - 47/12*x^2 + 116/3*x - 62/3, 1/2*x^4 + ( y - 5/2)*x^3 + (-6*y - 29/2)*x^2 + (-23*y - 59/2)*x + (-36*y - 18), x - 2], [1/9*x^3 + 47/36*x^2 - 3695/432*x - 1464769/15552, -1/18*x^4 + (1/27*y - 3/2 )*x^3 + (25/36*y - 3965/432)*x^2 + (10745/1296*y + 118411/7776)*x + (2098163 /46656*y + 21431725/124416), x + 25/4]]], [1, 3, 3; 3, 1, 9; 3, 9, 1]] [1, 13; 13, 1] [0, 0] [1, 2, 3, 6, 5, 10, 15, 30; 2, 1, 6, 3, 10, 5, 30, 15; 3, 6, 1, 2, 15, 30, 5 , 10; 6, 3, 2, 1, 30, 15, 10, 5; 5, 10, 15, 30, 1, 2, 3, 6; 10, 5, 30, 15, 2 , 1, 6, 3; 15, 30, 5, 10, 3, 6, 1, 2; 30, 15, 10, 5, 6, 3, 2, 1] [0, 0, 0, 0, 0, 0, 0, 0] [1, 2, 4, 4, 3, 3, 6, 6, 12, 12, 12, 12; 2, 1, 2, 2, 6, 6, 3, 3, 6, 6, 6, 6; 4, 2, 1, 4, 12, 12, 6, 6, 3, 3, 12, 12; 4, 2, 4, 1, 12, 12, 6, 6, 12, 12, 3 , 3; 3, 6, 12, 12, 1, 9, 2, 18, 4, 36, 36, 4; 3, 6, 12, 12, 9, 1, 18, 2, 36, 4, 4, 36; 6, 3, 6, 6, 2, 18, 1, 9, 2, 18, 18, 2; 6, 3, 6, 6, 18, 2, 9, 1, 1 8, 2, 2, 18; 12, 6, 3, 12, 4, 36, 2, 18, 1, 9, 36, 4; 12, 6, 3, 12, 36, 4, 1 8, 2, 9, 1, 4, 36; 12, 6, 12, 3, 36, 4, 18, 2, 36, 4, 1, 9; 12, 6, 12, 3, 4, 36, 2, 18, 4, 36, 9, 1] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [ 1 2 7 14] [ 2 1 14 7] [ 7 14 1 2] [14 7 2 1] [1 2] [2 1] [1 2 4 4] [2 1 2 2] [4 2 1 4] [4 2 4 1] [1 2 2 2] [2 1 4 4] [2 4 1 4] [2 4 4 1] [ 1 23] [23 1] [ 1 5 23 115] [ 5 1 115 23] [ 23 115 1 5] [115 23 5 1] [ 1 5 47 235] [ 5 1 235 47] [ 47 235 1 5] [235 47 5 1] [[[1, 0, 1, 4, -6, 1, 9, -23, -26, -215, 5291, -21952, 9938375/21952, Vecsma ll([1]), [Vecsmall([64, -1])], [0, 0, 0, 0, 0, 0, 0, 0]], [1, 0, 1, -1, 0, 1 , -1, 1, 0, 25, -253, -28, -15625/28, Vecsmall([1]), [Vecsmall([64, -1])], [ 0, 0, 0, 0, 0, 0, 0, 0]], [1, 0, 1, -171, -874, 1, -341, -3495, -29944, 8185 , 742643, -1835008, -548347731625/1835008, Vecsmall([1]), [Vecsmall([64, -1] )], [0, 0, 0, 0, 0, 0, 0, 0]], [1, 0, 1, -36, -70, 1, -71, -279, -1330, 1705 , 57707, 941192, 4956477625/941192, Vecsmall([1]), [Vecsmall([64, 1])], [0, 0, 0, 0, 0, 0, 0, 0]], [1, 0, 1, -11, 12, 1, -21, 49, -98, 505, -11341, 98, 128787625/98, Vecsmall([1]), [Vecsmall([64, 1])], [0, 0, 0, 0, 0, 0, 0, 0]], [1, 0, 1, -2731, -55146, 1, -5461, -220583, -7510776, 131065, 47449331, 250 88, 2251439055699625/25088, Vecsmall([1]), [Vecsmall([64, 1])], [0, 0, 0, 0, 0, 0, 0, 0]]], [0, 0, 3, 2, 0, 0; 3, 0, 0, 0, 2, 0; 0, 0, 0, 0, 0, 2; 0, 0, 0, 0, 0, 3; 0, 0, 0, 3, 0, 0; 0, 0, 0, 0, 0, 0]] [[[1, 0, 1, 4, -6, 1, 9, -23, -26, -215, 5291, -21952, 9938375/21952, Vecsma ll([1]), [Vecsmall([64, -1])], [0, 0, 0, 0, 0, 0, 0, 0]], [1, 0, 1, -36, -70 , 1, -71, -279, -1330, 1705, 57707, 941192, 4956477625/941192, Vecsmall([1]) , [Vecsmall([64, 1])], [0, 0, 0, 0, 0, 0, 0, 0]]], [0, 2; 0, 0]] [[[1, 0, 1, 4, -6, 1, 9, -23, -26, -215, 5291, -21952, 9938375/21952, Vecsma ll([1]), [Vecsmall([64, -1])], [0, 0, 0, 0, 0, 0, 0, 0]], [1, 0, 1, -36, -70 , 1, -71, -279, -1330, 1705, 57707, 941192, 4956477625/941192, Vecsmall([1]) , [Vecsmall([64, 1])], [0, 0, 0, 0, 0, 0, 0, 0]]], [0, 2; 0, 0]] [[[1, 0, 1, 4, -6, 1, 9, -23, -26, -215, 5291, -21952, 9938375/21952, Vecsma ll([1]), [Vecsmall([64, -1])], [0, 0, 0, 0, 0, 0, 0, 0]], [1, 0, 1, -1, 0, 1 , -1, 1, 0, 25, -253, -28, -15625/28, Vecsmall([1]), [Vecsmall([64, -1])], [ 0, 0, 0, 0, 0, 0, 0, 0]], [1, 0, 1, -171, -874, 1, -341, -3495, -29944, 8185 , 742643, -1835008, -548347731625/1835008, Vecsmall([1]), [Vecsmall([64, -1] )], [0, 0, 0, 0, 0, 0, 0, 0]]], [0, 0, 3; 3, 0, 0; 0, 0, 0]] [[[1, 0, 1, 4, -6, 1, 9, -23, -26, -215, 5291, -21952, 9938375/21952, Vecsma ll([1]), [Vecsmall([64, -1])], [0, 0, 0, 0, 0, 0, 0, 0]], [1, 0, 1, -1, 0, 1 , -1, 1, 0, 25, -253, -28, -15625/28, Vecsmall([1]), [Vecsmall([64, -1])], [ 0, 0, 0, 0, 0, 0, 0, 0]], [1, 0, 1, -171, -874, 1, -341, -3495, -29944, 8185 , 742643, -1835008, -548347731625/1835008, Vecsmall([1]), [Vecsmall([64, -1] )], [0, 0, 0, 0, 0, 0, 0, 0]], [1, 0, 1, -36, -70, 1, -71, -279, -1330, 1705 , 57707, 941192, 4956477625/941192, Vecsmall([1]), [Vecsmall([64, 1])], [0, 0, 0, 0, 0, 0, 0, 0]], [1, 0, 1, -11, 12, 1, -21, 49, -98, 505, -11341, 98, 128787625/98, Vecsmall([1]), [Vecsmall([64, 1])], [0, 0, 0, 0, 0, 0, 0, 0]], [1, 0, 1, -2731, -55146, 1, -5461, -220583, -7510776, 131065, 47449331, 250 88, 2251439055699625/25088, Vecsmall([1]), [Vecsmall([64, 1])], [0, 0, 0, 0, 0, 0, 0, 0]]], [0, 0, 3, 2, 0, 0; 3, 0, 0, 0, 2, 0; 0, 0, 0, 0, 0, 2; 0, 0, 0, 0, 0, 3; 0, 0, 0, 3, 0, 0; 0, 0, 0, 0, 0, 0]] -8 [1 2] [2 1] [ 1 2 3 6 5 10 15 30] [ 2 1 6 3 10 5 30 15] [ 3 6 1 2 15 30 5 10] [ 6 3 2 1 30 15 10 5] [ 5 10 15 30 1 2 3 6] [10 5 30 15 2 1 6 3] [15 30 5 10 3 6 1 2] [30 15 10 5 6 3 2 1] [ 1 2 3 6 7 14 21 42] [ 2 1 6 3 14 7 42 21] [ 3 6 1 2 21 42 7 14] [ 6 3 2 1 42 21 14 7] [ 7 14 21 42 1 2 3 6] [14 7 42 21 2 1 6 3] [21 42 7 14 3 6 1 2] [42 21 14 7 6 3 2 1] [ 1 2 4 4 8 8 3 6 12 12 24 24] [ 2 1 2 2 4 4 6 3 6 6 12 12] [ 4 2 1 4 8 8 12 6 3 12 24 24] [ 4 2 4 1 2 2 12 6 12 3 6 6] [ 8 4 8 2 1 4 24 12 24 6 3 12] [ 8 4 8 2 4 1 24 12 24 6 12 3] [ 3 6 12 12 24 24 1 2 4 4 8 8] [ 6 3 6 6 12 12 2 1 2 2 4 4] [12 6 3 12 24 24 4 2 1 4 8 8] [12 6 12 3 6 6 4 2 4 1 2 2] [24 12 24 6 3 12 8 4 8 2 1 4] [24 12 24 6 12 3 8 4 8 2 4 1] [1 2 3 6] [2 1 6 3] [3 6 1 2] [6 3 2 1] [ 1 2 3 6 7 14 21 42] [ 2 1 6 3 14 7 42 21] [ 3 6 1 2 21 42 7 14] [ 6 3 2 1 42 21 14 7] [ 7 14 21 42 1 2 3 6] [14 7 42 21 2 1 6 3] [21 42 7 14 3 6 1 2] [42 21 14 7 6 3 2 1] [ 1 2 4 4 5 10 20 20] [ 2 1 2 2 10 5 10 10] [ 4 2 1 4 20 10 5 20] [ 4 2 4 1 20 10 20 5] [ 5 10 20 20 1 2 4 4] [10 5 10 10 2 1 2 2] [20 10 5 20 4 2 1 4] [20 10 20 5 4 2 4 1] *** at top-level: ellisomat(ellinit([-824740032823875,9115932407 *** ^---------------------------------------------- *** ellisomat: incorrect priority in ellisomat: variable x <= y *** at top-level: ellisomat(ellinit([-824740032823875,9115932407 *** ^---------------------------------------------- *** ellisomat: incorrect priority in ellisomat: variable y <= y Total time spent: 3038 pari-2.17.2/src/test/32/zetahurwitz0000644000175000017500000001105414760123736015513 0ustar billbill-39 -39 -oo -oo -38 -38 -39 -37 0.048770822935203119831536294588381968716 6402373705731389.7030489318955969994839 - 0.03161451804298265316414244332077 7118203*I 7^-1 + 5 + 7 + 6*7^2 + 3*7^3 + O(7^4) 7^-1 + 4 + 7 + 6*7^2 + 3*7^3 + O(7^4) 2^-1 + O(2) 2^-1 + 2 + 2^2 + O(2^3) 2*5^-1 + 4 + 5 + 3*5^2 + O(5^4) -5.1928369229555125820137832704455696057 - 6.1349660138824147237884128986232 049582*I -0.083333333333333333333333333333333333333 - 0.16542114370045092921391966024 278064276*x^2 - 0.12510221205480019464554689634973506093*x^4 - 0.06375525415 3295382246666167409621832044*x^6 - 0.031145268034875919305019134807726637884 *x^8 - 0.015615426994125353615194111434674476549*x^10 - 0.007815030730337130 8864877076428010021454*x^12 - 0.0039060889627778945838882893488620841102*x^1 4 + O(x^16) 1.0000000000000000000000000000000000000*x^-1 - 0.422784335098467139393487909 91759756896 + 0.072815845483676724860586375874901319138*x - 0.00484518159643 61592422651930176062646795*x^2 - 0.00034230573671722431102667442379223071428 *x^3 + 9.6890419394470835727840424063586166704 E-5*x^4 + O(x^5) -0.50000000000000000000000000000000000000 - 1.918938533204672741780329736405 6176399*x - 1.5803938928558252862115621034473826501*x^2 - 0.2511340065366059 1458455559477961793877*x^3 - 1.0420268460244750927971944717696721958*x^4 - 1 .2355192659329334964334864657723974148*x^5 - 0.87257635058071572413411006048 346231123*x^6 - 1.0157624381355636661678145762947417024*x^7 - 1.011397423735 6739590562148571325170411*x^8 - 0.99428399592623009064922131173149736484*x^9 - 1.0001591493497346018358363230868245267*x^10 - 1.001197164231597443144712 3731856234327*x^11 - 0.99896194764310486791418180889565464565*x^12 - 1.00075 70168761786240672304402095851694*x^13 - 0.9994165959675638777241428089233952 4033*x^14 - 1.0004748436041855740380404973564299057*x^15 + O(x^16) -1.5000000000000000000000000000000000000 - 0.9189385332046727417803297364056 1763986*x - 1.0031782279542924256050500133649802191*x^2 - 1.0007851944770424 079601768022277292142*x^3 - 0.99987929950057116495780081365587523591*x^4 - 1 .0000019408963204560377998819816318312*x^5 - 1.00000130114601395962431150487 29797202*x^6 - 0.99999983138417361077993021705801540650*x^7 - 1.000000005764 6759799493944160637416597*x^8 - 1.0000000009110164892314165709218674222*x^9 - 0.99999999985029924058098862647927994292*x^10 - 1.000000000009406895665666 1769096478396*x^11 - 1.0000000000000409258263041583154763659*x^12 - 0.999999 99999993460095194108984774354353*x^13 - 1.0000000000000065439687498919193731 718*x^14 - 0.99999999999999969875751286332132050503*x^15 - 0.999999999999999 99601110529368894450336*x^16 + O(x^17) -0.91893853320467274178032973640561763986 - 2.006356455908584851210100026729 9604382*x - 3.0023555834311272238805304066831876427*x^2 - 3.9995171980022846 598312032546235009436*x^3 - 5.0000097044816022801889994099081591562*x^4 - 6. 0000078068760837577458690292378783213*x^5 - 6.999998819689215275459511519406 1078455*x^6 - 8.0000000461174078395951553285099332772*x^7 - 9.00000000819914 84030827491382968067996*x^8 - 9.9999999985029924058098862647927994293*x^9 - 11.000000000103475852322327946006126236*x^10 - 12.00000000000049110991564989 9785716391*x^11 - 12.999999999999149812375234168020666066*x^12 - 14.00000000 0000091615562498486871224405*x^13 - 14.999999999999995481362692949819807575* x^14 - 15.999999999999999936177684699023112054*x^15 + O(x^16) 2.8912099292003707921756506696066544531 E-19 1.6363644884325755176985906516640281770 E-91 8.4598061243854974109134151861018118228 E-117 -0.083333333333333333333333333333333333333 -0.50000000000000000000000000000000000000 + 0.166666666666666666666666666666 66666667*I 7.2418628815218661725049131054036874135 - 5.73915852494848801001026868102251 71774*I -0.0012500000000000000000000000000000000000 - 0.0499791562313333323211842510 48648972025*I *** at top-level: zetahurwitz(1,Pi) *** ^----------------- *** zetahurwitz: domain error in zetahurwitz: s = 1 *** at top-level: zetahurwitz(1+O(x),1) *** ^--------------------- *** zetahurwitz: domain error in zetahurwitz: s = 1 *** zetahurwitz: Warning: normalizing a series with 0 leading term. *** at top-level: zetahurwitz(O(2)+x,1) *** ^--------------------- *** zetahurwitz: forbidden multiplication t_REAL * t_PADIC. *** at top-level: zetahurwitz(y+x,1) *** ^------------------ *** zetahurwitz: incorrect type in zetahurwitz (t_POL). *** at top-level: zetahurwitz([],[]) *** ^------------------ *** zetahurwitz: incorrect type in zetahurwitz (t_VEC). Total time spent: 45 pari-2.17.2/src/test/32/nf0000644000175000017500000003056214676526175013535 0ustar billbill20915648110955829231381594293324156411897455346679838307589120000 571459344155975480004612560667633185714077696 20/3 -5 13 0 5/2 -1 1024/243 -1 31 -11 1/32 15853839 1736217747 16/9 1 [13, 5, 6, 2, 1]~ [2, 0, 1, 0, 0]~ 1/4 [-1071, -384, -251, -155, 20]~ [3, 6; y, 4] 3/4 -1 [-16/31, 12/31, 4/31, -6/31, 1/31]~ [0, 1/11, 1/11, 0, -1/11]~ 2 [396997/15853839, -123852/5284613, 30975/5284613, -53135/15853839, -19678/15 853839]~ [3, -3; y, -2] Mod(4/3, y^5 - 4*y^3 + 2*y + 11) Mod(-1, y^5 - 4*y^3 + 2*y + 11) Mod(y^2 + y + 1, y^5 - 4*y^3 + 2*y + 11) Mod(y, y^5 - 4*y^3 + 2*y + 11) Mod(1/2, y^5 - 4*y^3 + 2*y + 11) Mod(5*y^4 + 4*y^3 - 12*y^2 - y - 5, y^5 - 4*y^3 + 2*y + 11) [4/3, 0, 0, 0, 0]~ [-1, 0, 0, 0, 0]~ [3, 1, 1, 0, 0]~ [0, 1, 0, 0, 0]~ [1/2, 0, 0, 0, 0]~ [1, 2, 3, 4, 5]~ 8/3 1/3 [13/3, 1, 1, 0, 0]~ [4/3, 1, 0, 0, 0]~ 11/6 [7/3, 2, 3, 4, 5]~ 1/3 -2 [2, 1, 1, 0, 0]~ [-1, 1, 0, 0, 0]~ -1/2 [0, 2, 3, 4, 5]~ [13/3, 1, 1, 0, 0]~ [2, 1, 1, 0, 0]~ [6, 2, 2, 0, 0]~ [3, 2, 1, 0, 0]~ [7/2, 1, 1, 0, 0]~ [4, 3, 4, 4, 5]~ [4/3, 1, 0, 0, 0]~ [-1, 1, 0, 0, 0]~ [3, 2, 1, 0, 0]~ [0, 2, 0, 0, 0]~ [1/2, 1, 0, 0, 0]~ [1, 3, 3, 4, 5]~ 11/6 -1/2 [7/2, 1, 1, 0, 0]~ [1/2, 1, 0, 0, 0]~ 1 [3/2, 2, 3, 4, 5]~ [7/3, 2, 3, 4, 5]~ [0, 2, 3, 4, 5]~ [4, 3, 4, 4, 5]~ [1, 3, 3, 4, 5]~ [3/2, 2, 3, 4, 5]~ [2, 4, 6, 8, 10]~ 1 -4/3 [-64/93, 16/31, 16/93, -8/31, 4/93]~ [0, 4/33, 4/33, 0, -4/33]~ 8/3 [1587988/47561517, -165136/5284613, 41300/5284613, -212540/47561517, -78712/ 47561517]~ [3, 3; y, 2; 4/3, -1] -3/4 1 [16/31, -12/31, -4/31, 6/31, -1/31]~ [0, -1/11, -1/11, 0, 1/11]~ -2 [-396997/15853839, 123852/5284613, -30975/5284613, 53135/15853839, 19678/158 53839]~ [3, 3; y, 2; -1, -1] [9/4, 3/4, 3/4, 0, 0]~ [-3, -1, -1, 0, 0]~ [1, 0, 0, 0, 0]~ [1, 12/11, 1/11, 0, -1/11]~ [6, 2, 2, 0, 0]~ [1249690/15853839, -222317/5284613, 39600/5284613, -477392/15853839, 434/158 53839]~ [3, 3; y, 2; y^2 + y + 1, -1] [0, 3/4, 0, 0, 0]~ [0, -1, 0, 0, 0]~ [3/31, -10/31, 7/31, 5/31, -6/31]~ [1, 0, 0, 0, 0]~ [0, 2, 0, 0, 0]~ [-672280/15853839, 150044/5284613, -148123/5284613, 73247/15853839, -53135/1 5853839]~ [3, 3; y, 2; Mod(y, y^5 - 4*y^3 + 2*y + 11), -1] 3/8 -1/2 [-8/31, 6/31, 2/31, -3/31, 1/62]~ [0, 1/22, 1/22, 0, -1/22]~ 1 [396997/31707678, -61926/5284613, 30975/10569226, -53135/31707678, -9839/158 53839]~ [3, 3; y, 2; Mod(1/2, y^5 - 4*y^3 + 2*y + 11), -1] [3/4, 3/2, 9/4, 3, 15/4]~ [-1, -2, -3, -4, -5]~ [-314/31, -59/31, 311/31, 14/31, -85/31]~ [7, -27/11, 39/11, 5, 5/11]~ [2, 4, 6, 8, 10]~ [1, 0, 0, 0, 0]~ [3, 3; y, 2; [1, 2, 3, 4, 5]~, -1] [3, 3; y, 2; 4/3, -1] [3, 3; y, 2; -1, -1] [3, 3; y, 2; y^2 + y + 1, -1] [3, 3; y, 2; Mod(y, y^5 - 4*y^3 + 2*y + 11), -1] [3, 3; y, 2; Mod(1/2, y^5 - 4*y^3 + 2*y + 11), -1] [3, 3; y, 2; [1, 2, 3, 4, 5]~, -1] [3, 3; y, 2; 3, -3; y, -2] 1 -1 [-1, 1, 0, 0, 0]~ [0, 0, 0, 0, 0]~ 3 [0, 0, 0, 0, 0]~ -1 1 [1, 0, 0, 0, 0]~ [0, 0, 0, 0, 0]~ -2 [0, 0, 0, 0, 0]~ [2, 1, 1, 0, 0]~ [-3, -1, -1, 0, 0]~ [1, 0, 0, 0, 0]~ [1, 1, 0, 0, 0]~ [6, 2, 2, 0, 0]~ [0, 0, 0, 0, 0]~ [0, 1, 0, 0, 0]~ [0, -1, 0, 0, 0]~ [0, 0, 0, 0, 0]~ [1, 0, 0, 0, 0]~ [0, 2, 0, 0, 0]~ [0, 0, 0, 0, 0]~ 0 0 [0, 0, 0, 0, 0]~ [0, 0, 0, 0, 0]~ 1 [0, 0, 0, 0, 0]~ [1, 2, 2, 3, 4]~ [-1, -2, -3, -4, -5]~ [-10, -2, 10, 0, -3]~ [7, -2, 4, 5, 0]~ [2, 4, 6, 8, 10]~ [1, 0, 0, 0, 0]~ [1, 0] [-1, 1/3] [[-1, 1, 0, 0, 0]~, [7/3, -2, 0, -1, 0]~] [[0, 0, 0, 0, 0]~, 4/3] [3, -1/6] [[0, 0, 0, 0, 0]~, 4/3] [-1, 1/3] [1, 0] [[1, 0, 0, 0, 0]~, [-4, -1, -1, 0, 0]~] [[0, 0, 0, 0, 0]~, -1] [-2, 0] [[0, 0, 0, 0, 0]~, -1] [[2, 1, 1, 0, 0]~, [1/3, -1/3, -1/3, 0, 0]~] [[-3, -1, -1, 0, 0]~, [0, 0, 0, 0, 0]~] [[1, 0, 0, 0, 0]~, [0, 0, 0, 0, 0]~] [[1, 1, 0, 0, 0]~, [1, 0, 0, 0, 0]~] [[6, 2, 2, 0, 0]~, [0, 0, 0, 0, 0]~] [[0, 0, 0, 0, 0]~, [3, 1, 1, 0, 0]~] [[0, 1, 0, 0, 0]~, [0, -1/3, 0, 0, 0]~] [[0, -1, 0, 0, 0]~, [0, 0, 0, 0, 0]~] [[0, 0, 0, 0, 0]~, [0, 1, 0, 0, 0]~] [[1, 0, 0, 0, 0]~, [0, 0, 0, 0, 0]~] [[0, 2, 0, 0, 0]~, [0, 0, 0, 0, 0]~] [[0, 0, 0, 0, 0]~, [0, 1, 0, 0, 0]~] [0, 1/2] [0, 1/2] [[0, 0, 0, 0, 0]~, 1/2] [[0, 0, 0, 0, 0]~, 1/2] [1, 0] [[0, 0, 0, 0, 0]~, 1/2] [[1, 2, 2, 3, 4]~, [-1/3, -2/3, 1/3, 0, -1/3]~] [[-1, -2, -3, -4, -5]~, [0, 0, 0, 0, 0]~] [[-10, -2, 10, 0, -3]~, [-6, -2, 1, 2, 1]~] [[7, -2, 4, 5, 0]~, [-5, 0, 0, 0, 0]~] [[2, 4, 6, 8, 10]~, [0, 0, 0, 0, 0]~] [[1, 0, 0, 0, 0]~, [0, 0, 0, 0, 0]~] 0 1/3 [7/3, -2, 0, -1, 0]~ 4/3 -1/6 4/3 1/3 0 [-4, -1, -1, 0, 0]~ -1 0 -1 [1/3, -1/3, -1/3, 0, 0]~ [0, 0, 0, 0, 0]~ [0, 0, 0, 0, 0]~ [1, 0, 0, 0, 0]~ [0, 0, 0, 0, 0]~ [3, 1, 1, 0, 0]~ [0, -1/3, 0, 0, 0]~ [0, 0, 0, 0, 0]~ [0, 1, 0, 0, 0]~ [0, 0, 0, 0, 0]~ [0, 0, 0, 0, 0]~ [0, 1, 0, 0, 0]~ 1/2 1/2 1/2 1/2 0 1/2 [-1/3, -2/3, 1/3, 0, -1/3]~ [0, 0, 0, 0, 0]~ [-6, -2, 1, 2, 1]~ [-5, 0, 0, 0, 0]~ [0, 0, 0, 0, 0]~ [0, 0, 0, 0, 0]~ 16/9 -4/3 [4, 4/3, 4/3, 0, 0]~ [0, 4/3, 0, 0, 0]~ 2/3 [4/3, 8/3, 4, 16/3, 20/3]~ [3, 3; y, 2; 4/3, 1] -4/3 1 [-3, -1, -1, 0, 0]~ [0, -1, 0, 0, 0]~ -1/2 [-1, -2, -3, -4, -5]~ [3, 3; y, 2; -1, 1] [4, 4/3, 4/3, 0, 0]~ [-3, -1, -1, 0, 0]~ [13, 5, 6, 2, 1]~ [2, 3, 1, 1, 0]~ [3/2, 1/2, 1/2, 0, 0]~ [-58, -42, 23, 27, 17]~ [3, 3; y, 2; y^2 + y + 1, 1] [0, 4/3, 0, 0, 0]~ [0, -1, 0, 0, 0]~ [2, 3, 1, 1, 0]~ [2, 0, 1, 0, 0]~ [0, 1/2, 0, 0, 0]~ [-33, -3, 11, 8, 4]~ [3, 3; y, 2; Mod(y, y^5 - 4*y^3 + 2*y + 11), 1] 2/3 -1/2 [3/2, 1/2, 1/2, 0, 0]~ [0, 1/2, 0, 0, 0]~ 1/4 [1/2, 1, 3/2, 2, 5/2]~ [3, 3; y, 2; Mod(1/2, y^5 - 4*y^3 + 2*y + 11), 1] [4/3, 8/3, 4, 16/3, 20/3]~ [-1, -2, -3, -4, -5]~ [-58, -42, 23, 27, 17]~ [-33, -3, 11, 8, 4]~ [1/2, 1, 3/2, 2, 5/2]~ [-1071, -384, -251, -155, 20]~ [3, 3; y, 2; [1, 2, 3, 4, 5]~, 1] [3, 3; y, 2; 4/3, 1] [3, 3; y, 2; -1, 1] [3, 3; y, 2; y^2 + y + 1, 1] [3, 3; y, 2; Mod(y, y^5 - 4*y^3 + 2*y + 11), 1] [3, 3; y, 2; Mod(1/2, y^5 - 4*y^3 + 2*y + 11), 1] [3, 3; y, 2; [1, 2, 3, 4, 5]~, 1] [3, 3; y, 2; 3, 3; y, 2] [1] [1, 1/2*x - 1/2] [1, x, x^2, 1/37*x^3 - 15/37*x^2 + 1/37*x] [1, x, x^2, 1/37*x^3 - 15/37*x^2 + 1/37*x] 1591637628352930672717229 51397 [x^2 + x + 1, [0, 1], -3, 1, [Mat([1, -0.50000000000000000000000000000000000 000 + 0.86602540378443864676372317075293618347*I]), [1, 0.366025403784438646 76372317075293618347; 1, -1.3660254037844386467637231707529361835], [16, 6; 16, -22], [2, -1; -1, -1], [3, 2; 0, 1], [1, -1; -1, -2], [3, [2, -1; 1, 1]] , [3]], [-0.50000000000000000000000000000000000000 + 0.866025403784438646763 72317075293618347*I], [1, x], [1, 0; 0, 1], [1, 0, 0, -1; 0, 1, 1, -1]] 0 2 [6416795761] [x^7 - x^6 + x^5 - x^4 - x^3 - x^2, x^9 + x^8 + x^7 + x^6 + 2*x^4 + 2*x^3 + x^2 + x + 1, x^10 + x^9 - x^8 - x^3 - x^2 - x, x^10 + x^9 + 2*x^7 + x^6 + x^ 5 + x^4 + 2*x^2 + x + 1, -x^11 - 2*x^10 - x^8 - 2*x^7 - x^6 - x^5 - 2*x^4 - x^3 - 2*x^2 - x - 1, -x^11 - x^10 - 2*x^9 - x^8 - 2*x^7 - x^6 - 2*x^5 - x^4 - x^2 - 2*x - 1, -x^11 - x^10 - x^9 + x^8 - x^7 + x^6, -x^11 - x^9 - x^6 + x ^4 - x^3 + x, x^11 - x^10 + x^6 - x^5 - x^2 - x, x^11 - x^8 - x^7 + x^5 - x^ 4 - x, x^11 + x^10 + 2*x^8 + x^7 + x^4 + x^3 + 2*x^2 + x + 1, x^11 + 2*x^10 + x^9 + x^7 + x^5 + x^3 + x^2 + 2*x + 1] [-x^2, x^2] [-x^2, x^2] [-x^2, x^2] 0 [35952239140236636613554193911666/20990466712995598590763903143048989*x^20 + 219201047314343953199542006623468/20990466712995598590763903143048989*x^19 - 544094474369607287844071682948984/20990466712995598590763903143048989*x^18 - 1301738076793130194798253391725406/20990466712995598590763903143048989*x^ 17 + 4323784229146831865769550863399188/20990466712995598590763903143048989* x^16 + 1180785226777964111519743237847228/2099046671299559859076390314304898 9*x^15 - 16009478553791306868545675624906176/2099046671299559859076390314304 8989*x^14 + 11661369832298820433335186698644800/2099046671299559859076390314 3048989*x^13 + 24577904562406269454374516161861844/2099046671299559859076390 3143048989*x^12 - 2841411922644145137800873408789776/12347333360585646229861 11949591117*x^11 + 40513760532585028733891495151094508/209904667129955985907 63903143048989*x^10 + 77137274588135205291798303592401638/209904667129955985 90763903143048989*x^9 - 9612104031689093945033225402487055/12347333360585646 22986111949591117*x^8 + 844775560812208284237807638227260/209904667129955985 90763903143048989*x^7 - 153457335161602039094310022600574514/209904667129955 98590763903143048989*x^6 + 454725983158981264651921915989314030/209904667129 95598590763903143048989*x^5 - 247595736314170743760908290075787460/209904667 12995598590763903143048989*x^4 + 246411488365177430998635983532374564/209904 66712995598590763903143048989*x^3 - 300616800198203967230858561992730353/209 90466712995598590763903143048989*x^2 + 62128367926034523995700779963870389/2 0990466712995598590763903143048989*x + 73920020404088609656492594951950857/2 0990466712995598590763903143048989] 0 [-z^2, z^2] 0 [-1/2*x, 1/2*x] [-2*x, 2*x] [-z, z] x^2 + 1 1 1 [0, -1]~ 0 1 1 -2 1 1 [0, -1]~ 0 1 1 2 0 1 1 2 0 1 1 2 [-1/81*x^4, 1/162*x^4 - 1/2*x, 1/162*x^4 + 1/2*x] [-1/2187*x^4, 1/4374*x^4 - 1/2*x, 1/4374*x^4 + 1/2*x] -1/81*x^4 -1/2187*x^4 [x] x [25339, [165, 0, 0, 4]~] Mod(1/2*x - 1/2, x^2 + 23) [1, 2]~ [1, 1/2*x - 1/2] Mod(0, x) Mod(0, x) Mod(-6/5, x) "t_VEC" "t_VEC" *** at top-level: nfinit([y^3+2,[1,x]]) *** ^--------------------- *** nfinit: incorrect type in nfinit_basic (t_VEC). *** at top-level: nfinit([y^3+2,[1,x,x^2]]) *** ^------------------------- *** nfinit: incorrect type in nfinit_basic (t_VEC). *** at top-level: nfinit([y^3+2,[1,y^5,y]]) *** ^------------------------- *** nfinit: incorrect type in nfinit_basic (t_VEC). *** at top-level: nfdisc([y^2+2,matid(3)]) *** ^------------------------ *** nfdisc: incorrect type in nfmaxord (t_MAT). *** at top-level: nfdisc([2*y^2+1,matid(3)]) *** ^-------------------------- *** nfdisc: incorrect type in nfbasis [factorization expected] (t_MAT). *** at top-level: nfdisc([y^2+2,""]) *** ^------------------ *** nfdisc: incorrect type in nfmaxord (t_STR). *** at top-level: nfnewprec(x) *** ^------------ *** nfnewprec: incorrect type in nfnewprec (t_POL). *** at top-level: nfnewprec(quadgen(5)) *** ^--------------------- *** nfnewprec: incorrect type in nfnewprec (t_QUAD). *** at top-level: nfnewprec(vector(5)) *** ^-------------------- *** nfnewprec: incorrect type in nfnewprec (t_VEC). *** at top-level: nfnewprec(vector(6)) *** ^-------------------- *** nfnewprec: incorrect type in nfnewprec (t_VEC). *** at top-level: nfnewprec(vector(8)) *** ^-------------------- *** nfnewprec: incorrect type in nfnewprec (t_VEC). *** at top-level: nfnewprec(vector(9)) *** ^-------------------- *** nfnewprec: incorrect type in nfnewprec (t_VEC). *** at top-level: nfnewprec(vector(12)) *** ^--------------------- *** nfnewprec: incorrect type in nfnewprec (t_VEC). *** at top-level: nfnewprec(vector(16)) *** ^--------------------- *** nfnewprec: incorrect type in nfnewprec (t_VEC). *** at top-level: nfisincl(y^2+1,z^4+z^2+1) *** ^------------------------- *** nfisincl: not an irreducible polynomial in nfisincl: z^4 + z^2 + 1. *** at top-level: nfisisom(x,x^0) *** ^--------------- *** nfisisom: not an irreducible polynomial in nfisincl: 1. *** at top-level: idealhnf(nf,3,('a^2+1)*Mod(1,3)) *** ^-------------------------------- *** idealhnf: incorrect type in nf_to_scalar_or_basis (t_INTMOD). *** at top-level: nfalgtobasis(nf,['a,'a]~) *** ^------------------------- *** nfalgtobasis: incorrect type in nfalgtobasis (t_COL). [-4*x^2, 4*x^2] [-77/171*x^16 + 28/19*x^13 - 1222/171*x^10 - 1205/171*x^7 - 734/57*x^4 + 161 /171*x, -73/171*x^16 + 232/171*x^13 - 1141/171*x^10 - 1249/171*x^7 - 2210/17 1*x^4 - 274/171*x, -4/19*x^16 + 104/171*x^13 - 520/171*x^10 - 89/19*x^7 - 12 01/171*x^4 - 151/171*x, -32/171*x^16 + 28/57*x^13 - 439/171*x^10 - 845/171*x ^7 - 403/57*x^4 - 586/171*x, 5/171*x^16 - 2/57*x^13 + 49/171*x^10 + 230/171* x^7 + 136/57*x^4 + 202/171*x, 3/19*x^16 - 26/57*x^13 + 130/57*x^10 + 205/57* x^7 + 89/19*x^4 + 128/57*x, 31/171*x^16 - 98/171*x^13 + 157/57*x^10 + 571/17 1*x^7 + 793/171*x^4 - 17/57*x, 46/171*x^16 - 154/171*x^13 + 751/171*x^10 + 6 34/171*x^7 + 1409/171*x^4 - 110/171*x, 109/171*x^16 - 112/57*x^13 + 1661/171 *x^10 + 2050/171*x^7 + 379/19*x^4 + 425/171*x] *** at top-level: ...tispower(nfinit(x^4-2),x,2^64-100) *** ^--------- *** overflow in t_INT-->long assignment. 1/10 1/10 16 999529 1 11250 -4 1 Total time spent: 253 pari-2.17.2/src/test/32/character0000644000175000017500000000263614567450071015055 0ustar billbill [15 12] [ 0 1] [14, 4] 15 [20 0] [ 0 1] [20 0] [ 0 1] [20 0] [ 0 1] [0, 0] [0, 0]~ 1 [18, 0] [0, 18]~ 69 [3, 0] [0, 3]~ 33 [19, 0] [0, 19]~ [0, 19]~ 20 20 20 67 [13, 1] [1, 13]~ [1, 13]~ [1, 13]~ [1, 13]~ 23 [9, 1] [1, 9]~ [1, 9]~ [1, 9]~ [1, 9]~ * 100 1: [100, 1] 49: [20, 5] 51: [-100, -4] 99: [-20, -20] * 8 1: [4, 1] 3: [-8, -8] 5: [8, 8] 7: [-4, -4] * 5 1: [25, 1] 4: [5, 5] * 1 1: [1, 1] [[]~, []~, 0, 1] [[2]~, [2]~, 4, 2] [[0]~, [0]~, 1, 1] [[3]~, [3]~, 3, 4] [13, [0, 19]~, 13, 20] [[0, 19]~, [1, 0]~, 51, 20] [[10, 1], [1, 10]~, 99, 2] *** at top-level: znchar(0) *** ^--------- *** znchar: incorrect type in znchar (t_INT). *** at top-level: znchar(2) *** ^--------- *** znchar: incorrect type in znchar (t_INT). *** at top-level: znchar(3) *** ^--------- *** znchar: incorrect type in znchar (t_INT). *** at top-level: znchar([]~) *** ^----------- *** znchar: incorrect type in znchar (t_COL). *** at top-level: znchar([1,2,3]) *** ^--------------- *** znchar: incorrect type in znchar (t_VEC). *** at top-level: znchar([1,2]) *** ^------------- *** znchar: incorrect type in znchar (t_VEC). *** at top-level: znchar([znstar(100,1),[1,2,3]]) *** ^------------------------------- *** znchar: incorrect type in znchar (t_VEC). Total time spent: 0 pari-2.17.2/src/test/32/krasner0000644000175000017500000002007314567450071014561 0ustar billbill[[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, 75, 0], [50, 3, 25, 50], [60, 5, 15, 60], [70, 15, 5, 70], [72, 25, 3, 72], [74, 75, 1, 74]] [[0, 1, 18, 0], [9, 2, 9, 9], [9, 2, 9, 9], [12, 3, 6, 12], [12, 3, 6, 12], [15, 6, 3, 15], [15, 6, 3, 15], [16, 9, 2, 16], [16, 9, 2, 16], [17, 18, 1, 17], [17, 18, 1, 17]] [[12, 2, 4, 12], [12, 2, 4, 12], [12, 2, 4, 12], [12, 2, 4, 12], [12, 2, 4, 12], [12, 2, 4, 12], [12, 2, 4, 12], [12, 2, 4, 12], [12, 2, 4, 12], [12, 2, 4, 12], [12, 2, 4, 12], [12, 2, 4, 12], [12, 4, 2, 12], [12, 4, 2, 12], [12 , 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]] [[0, 1, 30, 0], [15, 2, 15, 15], [15, 2, 15, 15], [20, 3, 10, 20], [20, 3, 1 0, 20], [20, 3, 10, 20], [24, 5, 6, 24], [24, 5, 6, 24], [24, 5, 6, 24], [25 , 6, 5, 25], [25, 6, 5, 25], [25, 6, 5, 25], [25, 6, 5, 25], [25, 6, 5, 25], [25, 6, 5, 25], [27, 10, 3, 27], [27, 10, 3, 27], [28, 15, 2, 28], [28, 15, 2, 28], [28, 15, 2, 28], [28, 15, 2, 28], [28, 15, 2, 28], [28, 15, 2, 28], [28, 15, 2, 28], [28, 15, 2, 28], [28, 15, 2, 28], [29, 30, 1, 29], [29, 30 , 1, 29], [29, 30, 1, 29], [29, 30, 1, 29], [29, 30, 1, 29], [29, 30, 1, 29] ] [[0, 1, 8, 0], [4, 2, 4, 4], [4, 2, 4, 4], [6, 4, 2, 6], [6, 4, 2, 6], [6, 4 , 2, 6], [6, 4, 2, 6], [7, 8, 1, 7], [7, 8, 1, 7], [7, 8, 1, 7], [7, 8, 1, 7 ]] [[0, 1, 2, 0], [1, 2, 1, 1], [1, 2, 1, 1]] 15 [[0, 1, 4, 0], [4, 2, 2, 4], [4, 2, 2, 4], [4, 2, 2, 4], [4, 2, 2, 4], [4, 4 , 1, 4], [6, 2, 2, 6], [6, 2, 2, 6], [6, 2, 2, 6], [6, 2, 2, 6], [6, 2, 2, 6 ], [6, 2, 2, 6], [6, 4, 1, 6], [6, 4, 1, 6], [6, 4, 1, 6], [8, 4, 1, 8], [8, 4, 1, 8], [8, 4, 1, 8], [8, 4, 1, 8], [8, 4, 1, 8], [8, 4, 1, 8], [8, 4, 1, 8], [8, 4, 1, 8], [9, 4, 1, 9], [9, 4, 1, 9], [9, 4, 1, 9], [9, 4, 1, 9], [ 9, 4, 1, 9], [9, 4, 1, 9], [9, 4, 1, 9], [9, 4, 1, 9], [10, 4, 1, 10], [10, 4, 1, 10], [10, 4, 1, 10], [10, 4, 1, 10], [10, 4, 1, 10], [10, 4, 1, 10], [ 10, 4, 1, 10], [10, 4, 1, 10], [11, 4, 1, 11], [11, 4, 1, 11], [11, 4, 1, 11 ], [11, 4, 1, 11], [11, 4, 1, 11], [11, 4, 1, 11], [11, 4, 1, 11], [11, 4, 1 , 11], [11, 4, 1, 11], [11, 4, 1, 11], [11, 4, 1, 11], [11, 4, 1, 11], [11, 4, 1, 11], [11, 4, 1, 11], [11, 4, 1, 11], [11, 4, 1, 11], [11, 4, 1, 11], [ 11, 4, 1, 11], [11, 4, 1, 11], [11, 4, 1, 11]] [0, 2] [x^3 + 9*x^2 + 29*x + 35, x^3 + 6*x + 24, x^3 + 18*x^2 + 12*x + 12, x^3 + 24 *x^2 + 15, x^3 + 75*x^2 + 63*x + 60, x^3 + 12*x^2 + 36*x + 51, x^3 + 6*x^2 + 18*x + 66, x^3 + 54*x^2 + 18*x + 3, x^3 + 18*x + 69, x^3 + 18*x^2 + 72*x + 48] [x^5 + 25*x^4 + 250*x^3 + 4*x + 24, x^5 + 10*x^4 + 5*x^3 + 5*x^2 + 20*x + 5, x^5 + 15*x^4 + 10*x^3 + 20*x^2 + 15*x + 15, x^5 + 15*x^4 + 10*x^3 + 10*x^2 + 10*x + 20, x^5 + 10*x^3 + 5*x + 10, x^5 + 75*x^4 + 80*x^3 + 45*x^2 + 50*x + 30, x^5 + 70*x^4 + 100*x^3 + 115*x^2 + 100*x + 45, x^5 + 45*x^4 + 50*x^3 + 115*x^2 + 50*x + 80, x^5 + 85*x^4 + 45*x^3 + 60*x^2 + 75*x + 15, x^5 + 60*x ^4 + 5*x^3 + 75*x^2 + 100*x + 45, x^5 + 55*x^4 + 90*x^3 + 100*x + 85, x^5 + 45*x^4 + 30*x^3 + 25*x^2 + 100*x + 115, x^5 + 55*x^4 + 115*x^3 + 75*x^2 + 25 *x + 45, x^5 + 80*x^4 + 225*x^3 + 250*x^2 + 600*x + 415, x^5 + 570*x^4 + 50* x^3 + 225*x^2 + 475*x + 180, x^5 + 355*x^4 + 275*x^3 + 575*x^2 + 150*x + 360 , x^5 + 585*x^4 + 600*x^3 + 175*x^2 + 575*x + 265, x^5 + 65*x^4 + 175*x^3 + 275*x^2 + 325*x + 215, x^5 + 15*x^4 + 500*x^3 + 175*x^2 + 425*x + 310, x^5 + 535*x^4 + 375*x^3 + 175*x^2 + 375*x + 340, x^5 + 180*x^4 + 475*x^3 + 450*x^ 2 + 125*x + 95, x^5 + 275*x^4 + 25*x^3 + 50*x^2 + 25*x + 460, x^5 + 525*x^4 + 550*x^3 + 125*x^2 + 125*x + 395, x^5 + 525*x^4 + 25*x^3 + 300*x^2 + 75*x + 570, x^5 + 525*x^3 + 100*x^2 + 475*x + 20, x^5 + 300*x^4 + 400*x^3 + 400*x^ 2 + 150*x + 90] Total time spent: 1456 pari-2.17.2/src/test/32/classpoly0000644000175000017500000000000014567450071015111 0ustar billbillpari-2.17.2/src/test/32/mf0000644000175000017500000023414014724303552013514 0ustar billbill *** Warning: new stack size = 64000000 (61.035 Mbytes). [ "Factors" 0 0 0 0] [ "Divisors" 0 0 0 0] [ "H" 0 0 0 0] ["CorediscF" 0 0 0 0] [ "Dihedral" 0 0 0 0] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [Mod(-1/5*t - 2/5, t^2 + 1), Mod(1, t^2 + 1), Mod(4*t + 1, t^2 + 1), Mod(-9* t + 1, t^2 + 1), Mod(4*t - 15, t^2 + 1), Mod(1, t^2 + 1), Mod(-5*t + 37, t^2 + 1), Mod(49*t + 1, t^2 + 1), Mod(-60*t - 15, t^2 + 1), Mod(-9*t - 80, t^2 + 1), Mod(4*t + 1, t^2 + 1), Mod(122, t^2 + 1), Mod(139*t + 21, t^2 + 1), Mo d(-169*t + 1, t^2 + 1), Mod(53*t - 195, t^2 + 1), Mod(-9*t + 1, t^2 + 1)] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 1, 0, 8, 0, -26, 0, -48, 0, 73, 0, 120, 0, -170, 0, -208] 5 23 40000 20000 0 [0, 8]~ [16, -4]~ [16, -32, 256]~ [64/5, 4/5, 32/5]~ [ 0] [ 1] [ 0] [ -516] [ 0] [-10530] [ 0] [ 49304] [ 0] [ 89109] [ 0] [ 0 0 0 0] [ 1 0 0 1] [ -24 1 0 0] [ 252 0 0 -516] [ -1472 -24 1 0] [ 4830 0 0 -10530] [ -6048 252 0 0] [ -16744 0 0 49304] [ 84480 -1472 -24 0] [-113643 0 0 89109] [-115920 4830 0 0] [ 0 0 0 0] [ -24 1 0 0] [ -1472 -24 1 0] [ -6048 252 0 0] [ 84480 -1472 -24 0] [-115920 4830 0 0] [[43/64, 129/8, 1376, 21/64]~, [0, 1, 0; 768, 24, 0; 18432, 2048, 768; 0, -1 , 0]] [[43/64, -63/8, 800, 21/64]~, [1, 0; 24, 0; 2048, 768; -1, 0]] [[1, 0, 1472, 0]~, [0; 0; 768; 0]] [1, 0, 0, 0]~ [1, [1, 1]] [1, 0, 0, 0]~ [1, 0, 0, 0]~ [] [1] [] [] [0, 0] [] [0, 0] 0 10 0 1 0 0 0 1 [] [[1, Mod(0, 1), 0, 0]] 0 1 0 0 [[0, 0], [0, 0], [0, 0], [0, 0]] [[1, 0], [0, 0], [0, 0], [1, 0]] 77291 29586 65034 [[11/32, 1/64, 1/32; 1/32, -9/64, -5/32; -1/8, 3/16, 1/8; -5/32, 1/64, 1/32; -5/32, -7/64, 1/32; -1/8, 1/16, 1/8; -3/32, 3/64, -1/32; -1/16, 3/32, 1/16; -1/32, -3/64, -3/32; -1/32, 5/64, -3/32; 0, 0, 0], [y, y, y, y^4 - y^3 - 5* y^2 + 3*y + 4, y^4 - y^3 - 8*y^2 + 4*y + 12]] [y, y, y] [y, y, y] [y, y, y] [y, y, y, y^4 - y^3 - 5*y^2 + 3*y + 4, y^4 - y^3 - 8*y^2 + 4*y + 12] [y^40 + y^38 - 22*y^36 - 488*y^34 + 200*y^32 + 61712*y^30 + 53952*y^28 - 211 6352*y^26 - 23962624*y^24 + 95379456*y^22 + 2793799680*y^20 + 6104285184*y^1 8 - 98150907904*y^16 - 554788978688*y^14 + 905164357632*y^12 + 6626275544268 8*y^10 + 13743895347200*y^8 - 2146246697418752*y^6 - 6192449487634432*y^4 + 18014398509481984*y^2 + 1152921504606846976] [y, y^2 + Mod(-2*t, t^2 + t + 1), y^5 + Mod(t + 1, t^2 + t + 1)*y^4 + Mod(-3 7*t, t^2 + t + 1)*y^3 + 21*y^2 + Mod(-288*t - 288, t^2 + t + 1)*y + Mod(64*t , t^2 + t + 1)] [1, 1] 1 [[2, Mod(22, 23), 1, 0], [22, Mod(5, 23), 1, 0]] [] 0 6 2 [0, 3, -1, 0, 3, 1, -8, -1, -9, 1, -1, -2, 4, 10, 1, -2, 7, -2, 7, -4] [0, -1, 9, -8, -11, -1, 4, 1, 13, 7, 9, 8, -20, 6, -9, -8, -27, -6, 5, 20] [0, 2, 8, -8, -8, 0, -4, 0, 4, 8, 8, 6, -16, 16, -8, -10] [0, 0, -3, 28, -33, -28, 34, 6, -113, 88, 33, 128, 108, -62, -17, 6] [0, 1, 17, -16, -19, -1, 0, 1, 17, 15, 17, 14, -36, 22, -17, -18] [0, 3, -1, 0, 3, 1, -8, -1, -9, 1, -1, -2, 4, 10, 1, -2, 7, -2, 7, -4, 7, 2, 8, -8, -4, 3, 6, -12, -7, 4, -8, -4, -9, -12, -6, -3, 3, 14, 20, -6, -9, -1 0, 8, 0, 0, 5, -16, 4, 28, 3] [0, -8, 4, 4, -20, -8, 32, 8, 36, -12, 4, -4, -24, -20, -4, 4] [0, 0, 3, 0, -1, 0, 0, 0, 3, 0, 1, 0, -8, 0, -1, 0] [0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, -1, 0, 0, 0] [0, 3, -1, 0, 3, -1, 8, 0, -9, 1, 1, -2, -4, -10, 0, -2] [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 1/2, 1/3, 1/4, 3/4, 1/6, 1/8, 3/8, 1/12, 7/12, 1/16, 1/24, 7/24, 1/32, 1 /48, 1/96] [96, 24, 32, 6, 6, 8, 3, 3, 2, 2, 3, 1, 1, 3, 1, 1] [1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1] [1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1] 16 6442450944 15917322219892801768783872 96 10 88 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] "TR([96, 6, 1, y, t - 1])" "CONST([])" [-2, -4] [0, 72, -2, -4, -12, -16, -90, -8, 424, -8, -300, -8, -396, -16, 944, -976] [0, 0] [0, 10, 0, 0, 0, -76, 0, 0, 0, 810, 0, 0, 0, 12, 0, 0] [0, 1, -1, -1, 0, 0, 1, 0, 1, 0, 0, 0, 0, -1, 0, 0] [Mod(0, t^2 - t + 1), Mod(1, t^2 - t + 1), Mod(-t, t^2 - t + 1), Mod(0, t^2 - t + 1), Mod(t - 1, t^2 - t + 1), Mod(-1, t^2 - t + 1), Mod(0, t^2 - t + 1) , Mod(0, t^2 - t + 1), Mod(1, t^2 - t + 1), Mod(t - 1, t^2 - t + 1), Mod(t, t^2 - t + 1), Mod(0, t^2 - t + 1), Mod(0, t^2 - t + 1), Mod(-t, t^2 - t + 1) , Mod(0, t^2 - t + 1), Mod(0, t^2 - t + 1)] [Mod(0, t^4 - t^3 + t^2 - t + 1), Mod(1, t^4 - t^3 + t^2 - t + 1), Mod(-t, t ^4 - t^3 + t^2 - t + 1), Mod(t^3 + t - 1, t^4 - t^3 + t^2 - t + 1), Mod(t^2, t^4 - t^3 + t^2 - t + 1), Mod(0, t^4 - t^3 + t^2 - t + 1), Mod(-t^3 + 1, t^ 4 - t^3 + t^2 - t + 1), Mod(0, t^4 - t^3 + t^2 - t + 1), Mod(-t^3, t^4 - t^3 + t^2 - t + 1), Mod(-t^2 - 1, t^4 - t^3 + t^2 - t + 1), Mod(0, t^4 - t^3 + t^2 - t + 1), Mod(-t^3, t^4 - t^3 + t^2 - t + 1), Mod(t^3 - t^2 - 1, t^4 - t ^3 + t^2 - t + 1), Mod(0, t^4 - t^3 + t^2 - t + 1), Mod(0, t^4 - t^3 + t^2 - t + 1), Mod(0, t^4 - t^3 + t^2 - t + 1)] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 2, 0, -2, 0, -2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2] [0, 2, -2, 0, -12, 0, 28, -16, 40, -2, -56, 0, -56, 0, 16, 112] [0, 1, -1, -1, -1, 1, 1, 0, 3, 1, -1, -4, 1, -2, 0, -1] [0, 2, 4, 0, -6, 0, -6, -4, -36, 18, -10, 28, -24, 96, 36, 30] [15, 4, 1, y, t - 1] 8 [4, 1, [0, 4, 0, -48, 0, 216, 0, -352, 0, -396]] [4, 2, [0, 7, 0, -84, 0, 378, 0, -616, 0, -693]] 1 72 [3, 1, [0, 4, -24, 36, 16, 24, -216, -160, 672, 324]] [3, 2, [0, 7, -42, 63, 28, 42, -378, -280, 1176, 567]] 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] 6 62 16 10 [[2717/14336, 3993/28672, 185/14336, 2717/14336, 3993/28672, 185/14336; -103 /4608, 65/3072, -7/4608, 103/4608, -65/3072, 7/4608; 225/57344, -95/114688, -123/57344, 225/57344, -95/114688, -123/57344; 5/1024, -49/18432, 13/9216, - 5/1024, 49/18432, -13/9216; 1/2048, -5/12288, -1/6144, -1/2048, 5/12288, 1/6 144; 31/57344, -33/114688, -5/57344, 31/57344, -33/114688, -5/57344; -7/9216 , 1/18432, -1/3072, 7/9216, -1/18432, 1/3072; -5/28672, -1/57344, -1/28672, -5/28672, -1/57344, -1/28672; 1/2048, -1/36864, 1/18432, -1/2048, 1/36864, - 1/18432; -11/57344, -115/1032192, 9/57344, -11/57344, -115/1032192, 9/57344] , [y, y, y, y, y, y, y^2 - 31, y^2 - 31]] [[2717/14336, 3993/28672, 185/14336, 2717/14336, 3993/28672, 185/14336, Mod( -4227/888832*y + 4539/57344, y^2 - 31), Mod(-4227/888832*y + 4539/57344, y^2 - 31); -103/4608, 65/3072, -7/4608, 103/4608, -65/3072, 7/4608, Mod(-29/952 32*y + 179/6144, y^2 - 31), Mod(29/95232*y - 179/6144, y^2 - 31); 225/57344, -95/114688, -123/57344, 225/57344, -95/114688, -123/57344, Mod(785/3555328* y - 109/229376, y^2 - 31), Mod(785/3555328*y - 109/229376, y^2 - 31); 5/1024 , -49/18432, 13/9216, -5/1024, 49/18432, -13/9216, Mod(13/571392*y - 67/3686 4, y^2 - 31), Mod(-13/571392*y + 67/36864, y^2 - 31); 1/2048, -5/12288, -1/6 144, -1/2048, 5/12288, 1/6144, Mod(-13/380928*y + 1/24576, y^2 - 31), Mod(13 /380928*y - 1/24576, y^2 - 31); 31/57344, -33/114688, -5/57344, 31/57344, -3 3/114688, -5/57344, Mod(-81/3555328*y - 19/229376, y^2 - 31), Mod(-81/355532 8*y - 19/229376, y^2 - 31); -7/9216, 1/18432, -1/3072, 7/9216, -1/18432, 1/3 072, Mod(17/571392*y + 19/36864, y^2 - 31), Mod(-17/571392*y - 19/36864, y^2 - 31); -5/28672, -1/57344, -1/28672, -5/28672, -1/57344, -1/28672, Mod(-5/1 777664*y + 13/114688, y^2 - 31), Mod(-5/1777664*y + 13/114688, y^2 - 31); 1/ 2048, -1/36864, 1/18432, -1/2048, 1/36864, -1/18432, Mod(1/1142784*y - 19/73 728, y^2 - 31), Mod(-1/1142784*y + 19/73728, y^2 - 31); -11/57344, -115/1032 192, 9/57344, -11/57344, -115/1032192, 9/57344, Mod(461/31997952*y + 151/206 4384, y^2 - 31), Mod(461/31997952*y + 151/2064384, y^2 - 31)], [y, y, y, y, y, y, y^2 - 31, y^2 - 31]] [1, 1, 1, 1, 1, 1, 2, 2] [[2717/14336, 3993/28672, 185/14336, 2717/14336, 3993/28672, 185/14336; -103 /4608, 65/3072, -7/4608, 103/4608, -65/3072, 7/4608; 225/57344, -95/114688, -123/57344, 225/57344, -95/114688, -123/57344; 5/1024, -49/18432, 13/9216, - 5/1024, 49/18432, -13/9216; 1/2048, -5/12288, -1/6144, -1/2048, 5/12288, 1/6 144; 31/57344, -33/114688, -5/57344, 31/57344, -33/114688, -5/57344; -7/9216 , 1/18432, -1/3072, 7/9216, -1/18432, 1/3072; -5/28672, -1/57344, -1/28672, -5/28672, -1/57344, -1/28672; 1/2048, -1/36864, 1/18432, -1/2048, 1/36864, - 1/18432; -11/57344, -115/1032192, 9/57344, -11/57344, -115/1032192, 9/57344] , [y, y, y, y, y, y]] [[2717/14336, 3993/28672, 185/14336, 2717/14336, 3993/28672, 185/14336, Mod( -4227/888832*y + 4539/57344, y^2 - 31), Mod(-4227/888832*y + 4539/57344, y^2 - 31); -103/4608, 65/3072, -7/4608, 103/4608, -65/3072, 7/4608, Mod(-29/952 32*y + 179/6144, y^2 - 31), Mod(29/95232*y - 179/6144, y^2 - 31); 225/57344, -95/114688, -123/57344, 225/57344, -95/114688, -123/57344, Mod(785/3555328* y - 109/229376, y^2 - 31), Mod(785/3555328*y - 109/229376, y^2 - 31); 5/1024 , -49/18432, 13/9216, -5/1024, 49/18432, -13/9216, Mod(13/571392*y - 67/3686 4, y^2 - 31), Mod(-13/571392*y + 67/36864, y^2 - 31); 1/2048, -5/12288, -1/6 144, -1/2048, 5/12288, 1/6144, Mod(-13/380928*y + 1/24576, y^2 - 31), Mod(13 /380928*y - 1/24576, y^2 - 31); 31/57344, -33/114688, -5/57344, 31/57344, -3 3/114688, -5/57344, Mod(-81/3555328*y - 19/229376, y^2 - 31), Mod(-81/355532 8*y - 19/229376, y^2 - 31); -7/9216, 1/18432, -1/3072, 7/9216, -1/18432, 1/3 072, Mod(17/571392*y + 19/36864, y^2 - 31), Mod(-17/571392*y - 19/36864, y^2 - 31); -5/28672, -1/57344, -1/28672, -5/28672, -1/57344, -1/28672, Mod(-5/1 777664*y + 13/114688, y^2 - 31), Mod(-5/1777664*y + 13/114688, y^2 - 31); 1/ 2048, -1/36864, 1/18432, -1/2048, 1/36864, -1/18432, Mod(1/1142784*y - 19/73 728, y^2 - 31), Mod(-1/1142784*y + 19/73728, y^2 - 31); -11/57344, -115/1032 192, 9/57344, -11/57344, -115/1032192, 9/57344, Mod(461/31997952*y + 151/206 4384, y^2 - 31), Mod(461/31997952*y + 151/2064384, y^2 - 31)], [y, y, y, y, y, y, y^2 - 31, y^2 - 31]] [0, 1, 0, 9, 0, 26, 0, 36, 0, 81, y] [0, 1, 0, 9, 0, -14, 0, -100, 0, 81, y] [0, 1, 0, 9, 0, -86, 0, 180, 0, 81, y] [0, 1, 0, -9, 0, 26, 0, -36, 0, 81, y] [0, 1, 0, -9, 0, -14, 0, 100, 0, 81, y] [0, 1, 0, -9, 0, -86, 0, -180, 0, 81, y] [Mod(0, y^2 - 31), Mod(1, y^2 - 31), Mod(0, y^2 - 31), Mod(9, y^2 - 31), Mod (0, y^2 - 31), Mod(16*y + 18, y^2 - 31), Mod(0, y^2 - 31), Mod(16*y + 60, y^ 2 - 31), Mod(0, y^2 - 31), Mod(81, y^2 - 31), y^2 - 31] [Mod(0, y^2 - 31), Mod(1, y^2 - 31), Mod(0, y^2 - 31), Mod(-9, y^2 - 31), Mo d(0, y^2 - 31), Mod(16*y + 18, y^2 - 31), Mod(0, y^2 - 31), Mod(-16*y - 60, y^2 - 31), Mod(0, y^2 - 31), Mod(81, y^2 - 31), y^2 - 31] [Mod(0, y^2 - 31), Mod(0, y^2 - 31), Mod(1, y^2 - 31), Mod(0, y^2 - 31), Mod (-18, y^2 - 31), Mod(0, y^2 - 31), Mod(32*y + 117, y^2 - 31), Mod(0, y^2 - 3 1), Mod(-320*y - 444, y^2 - 31), Mod(0, y^2 - 31), Mod(864*y + 9502, y^2 - 3 1), Mod(0, y^2 - 31), Mod(-2304*y - 19690, y^2 - 31), Mod(0, y^2 - 31), Mod( 2592*y + 16536, y^2 - 31), 0] 21 [4, -7, 11, 0, 0, 0, 0, 0, 0, 0]~ [0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0 0 0] [0 81 0 0 4887/7 0 0 0 45522/7 0] [1 0 0 0 0 -264 0 1422 0 0] [0 0 0 0 477/28 0 81 0 1269/7 0] [0 0 0 0 0 61 0 -152 0 81] [0 0 0 0 0 12 0 12 0 0] [0 0 0 0 171/28 0 0 0 27/7 0] [0 0 1 0 0 -7 0 40 0 0] [0 0 0 0 9/14 0 0 0 -27/7 0] [0 0 0 0 0 2 0 -19 0 0] [0 0 0 1 -95/28 0 0 0 -71/7 0] [[81, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 81, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 81, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 81, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 81, 0, 0, 0, 0 , 0; 0, 0, 0, 0, 0, 81, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 81, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 81, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 81, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 81], [0, 0, 0, 155223/7, -647676/7, 0, 1574721/7, 0, 2180790/7, 0; 0, 0, 8068, 0, 0, -45888, 0, -25888, 0, 86508; 0, 81, 0, 22293/28, -8640/7, 0, -6 0507/28, 0, -63009/14, 0; 0, 0, -288, 0, 0, 2656, 0, 4468, 0, -8424; 0, 0, - 27, 0, 0, -42, 0, -1482, 0, 81; 0, 0, 0, -909/28, 540/7, 0, -11421/28, 0, -1 791/14, 0; 1, 0, 120, 0, 0, -808, 0, -550, 0, 2592; 0, 0, 0, 549/14, -1674/7 , 0, 3159/14, 0, 801/7, 0; 0, 0, -63, 0, 0, 467, 0, 266, 0, -810; 0, 0, 0, - 167/28, 148/7, 0, 12393/28, 0, 8891/14, 0], [-2434/7, 0, 300738/7, 0, 0, 229 0482/7, 0, 16881306/7, 0, 11792304/7; 0, 4943, 0, 78792, -67632, 0, 416424, 0, 265872, 0; -747/28, 0, 39517/14, 0, 0, -329463/14, 0, 567081/14, 0, -1517 13/7; 0, -288, 0, -4237, -8472, 0, -39276, 0, -47928, 0; 0, -27, 0, -972, 16 43, 0, -2754, 0, 108, 0; -141/28, 0, -5811/14, 0, 0, -12575/14, 0, -11937/14 , 0, -58239/7; 0, 120, 0, 1320, -1440, 0, 13151, 0, 18000, 0; 39/14, 0, 1299 /7, 0, 0, -1269/7, 0, 15800/7, 0, 12312/7; 0, -63, 0, -618, 408, 0, -4356, 0 , -6337, 0; 153/28, 0, 2463/14, 0, 0, -13443/14, 0, -22899/14, 0, 37304/7]] 0.43212772973212385449512289817170941384 0.065367804723930579823031060437204674226 -3.2767866024378219074845099715117890907 0.34284913090478965797177570867964351435 -0.76125796339716986841247525017762663821 0.49159382167950494101715310718716918355 -0.49676146954567727676850448728844180078 -52.340285691058552832964253754168105742 1.0398936863409539900708802050121051862 183.58598430613706225199581706089347024 5.1579000625428403504184801623630511110 E-16 3.4870504895354529381700292194184810754 E-6 [1, 1] [1/23, 1/23] [1/23, 1/23] [12709844797213685207966660148549, 12709878029020295059028381417601] [0, -4186596901512170847892276510318430 - 1173029439813149005414471837402481 *I, (-3714866976289080663253111389348917 - 225906065232797207883913483184255 5*I)*y + (3714866976289080663253111389348917 + 22590606523279720788391348318 42555*I)] [0, 1, -24, 252, -1472, 4830, -6048, -16744, 84480, -113643, -115920, 534612 , -370944, -577738, 401856, 1217160] [0] [633/1792 351/1024 10819/896 67047/1792 267993/1792 102867/896 5265/3584 -14 7319/896 -906249/1792 81] [19/256 -3/8 267/128 -17/16 -81/8 7013/128 -205/16 24615/128 -497/8 6117/64] [87/7168 -9/4096 -591/3584 1135/7168 -22815/7168 12357/3584 49113/14336 -457 77/3584 48943/7168 1215/128] [-1/512 1/16 -41/256 -5/32 59/16 -1447/256 143/32 -3613/256 283/16 -1063/128 ] [1/1024 3/256 -39/512 3/32 -3/64 -121/512 -3/128 -3/512 39/64 -321/256] [9/7168 9/4096 47/3584 -879/7168 799/7168 1371/3584 -7641/14336 -3407/3584 2 769/7168 81/128] [1/512 -1/128 25/256 1/16 -23/32 7/256 -55/64 637/256 -101/32 223/128] [-1/3584 9/2048 -27/1792 65/3584 255/3584 -171/1792 135/7168 111/1792 -79/35 84 0] [-1/1024 1/128 -9/512 1/64 1/4 -103/512 5/16 -733/512 23/16 -151/256] [-5/7168 19/4096 61/3584 171/7168 -1371/7168 -687/3584 3965/14336 2963/3584 4267/7168 -81/128] [1 0 0] [0 1 0] [0 0 1] [0, 0, 0, 18, 0, 224, 0, 440, 0, 0, 0, 840, 0, 192, 0, 900] [1] [17.981439237735731033658522362934698192, -14.465932470400861049133659073570 007347, -14.173043447523315720648161399342292854, -12.8444792338479425607250 88799397162586, -12.673296763439189428830632012708642221, 11.313822387102528 758430335085165159676, 15.809242390926312020182669681356476477, 19.952518856 726468490501784413242971475, 12.164217722077195145237910274949933293, 15.381 272600128290391693466194368971580] [149.32003336233083380416740549931024313, -145.22528341237431879984196577788 550379, -144.05206065368915254369133157416377264, -137.368077052425797668068 45719565543525, -136.68537976117761802503641918389974975, 132.33498216866595 894851650979950974707, 144.81477270149742577794938046771306641, 153.37574451 331022295236625862817598070, 133.99393725109713614517615928616029184, 140.82 191407690427938490321804273819109] [1750.8612976244284982995145051957076323, -1743.4610846371885006840699908522 210646, -1739.3285039438314041396755906212872382, -1706.54568655078571155570 67243660579136, -1704.1559309139961646459809162176700473, 1693.2006899626197 396492113391602468661, 1739.6937549158404780145317707347222603, 1760.8038249 508416117204235666645232767, 1696.9537629837898396249480554755379813, 1714.4 123077300799878900824934093074081] [-25289.463103882493149683693231641947547, 25271.306252281313102094765195122 776006, 25256.284246728344311859481152424676239, 25079.367724015404662920284 476322170148, 25070.741444350281949178792195757223585, -25040.19987820531753 6042355830671301459, -25256.861209437637891371256419970666372, -25318.141977 898178949067363044347232866, -25050.025763197973566457964437905037423, -2510 2.674289656622081201236099263608944] 0.15111211321192334885298629517871164534 -0.029981366891420022975489657187955538024 1 [0, 1, -4, 2, 8, -5, -8, 6, 0, -23] [0, t, -4*t^2, 2*t^3, -8*t^3 - 8*t^2 - 8*t - 8, -5, -8*t, 6*t^2, 0, 23*t^3 + 23*t^2 + 23*t + 23, 20] [0, 5, [1, 0; 0, 1]] [0, 1, -2, -1, 2, 1] [0, 1, [1, 0; 0, 1]] [1/4, 0, 0, 0, 0] [1/2, 11, [1, 0; 0, 1]] [0, 0.0083160068527003923763819239796690829909 + 0.0186369836048978260765912 63978546433841*I, 0.040773714507830673270468368068835601812 - 0.001864595582 8220482074272494197134258868*I, 0.046062126409693852745000230038901860300 - 0.13522737805608561952910766786281685190*I, -0.07682530715670062861328778204 2554261374 + 0.027600040327739509297577443995295764559*I, -0.125743903939079 05970350003436207154063 + 0.067798479979021507423866878355650878641*I] [0, 7, [1, 0; 0, 1]] [0, 0, 0, 0.66666666666666666666666666666666666667 + 0.E-38*I, 0, -4.0000000 000000000000000000000000000000 + 6.9282032302755091741097853660234894676*I, 0, -12.000000000000000000000000000000000000 - 20.784609690826527522329356098 070468402*I, 0, 0, 0, 20.000000000000000000000000000000000018 - 34.641016151 377545870548926830117447370*I, 0] [Mod(0, t^2 + t + 1), Mod(0, t^2 + t + 1), Mod(0, t^2 + t + 1), Mod(2/3, t^2 + t + 1), Mod(0, t^2 + t + 1), Mod(8*t, t^2 + t + 1), Mod(0, t^2 + t + 1), Mod(-24*t - 24, t^2 + t + 1), Mod(0, t^2 + t + 1), Mod(0, t^2 + t + 1), Mod( 0, t^2 + t + 1), Mod(-40*t, t^2 + t + 1), Mod(0, t^2 + t + 1)] [-5/32, 81/32, 21/16, -597/8, 1215/32, 1689/8, -14813/16, -14337/16] [1/2, 1, [1, 0; 0, 1]] [Mod(0, t^2 + t + 1), Mod(0, t^2 + t + 1), Mod(2/3*t, t^2 + t + 1), Mod(-2/3 , t^2 + t + 1), Mod(4/3*t + 4/3, t^2 + t + 1)] 1 [Mod(61/256*t, t^2 + 1), Mod(-1/64*t, t^2 + 1), Mod(-1/64*t, t^2 + 1), Mod(9 1/8*t, t^2 + 1), Mod(-1/64*t, t^2 + 1), Mod(-7813/32*t, t^2 + 1)] [0, 1, [1, 0; 0, 1]] [Mod(0, t^2 + 1), Mod(-t, t^2 + 1), Mod(0, t^2 + 1), Mod(2*t, t^2 + 1)*y] [0, 1, [1, 0; 0, 1]] [0, 0, -0.026871677793768185811758182803469159206 - 0.0427660302192192146895 36937410383070596*I, 0, -0.016681611742316464491440499523538796306 - 0.04767 3307393570615953995380441278707349*I, 0] [ 0 1] [-1 0] 1 [1/4 1/4] [1/4 -1/4] 0.35355339059327376220042218105242451964 [x + Mod(-t, t^2 + 1) 2] [ x + Mod(t, t^2 + 1) 2] 1 [[I, -I, -I, I, I, -I]] [[0.33333333333333333333333333333333333333 + 0.94280904158206336586779248280 646538571*I, -0.33333333333333333333333333333333333333 + 0.94280904158206336 586779248280646538571*I]] [[-1, -1, -1, -1, -1, -1, -1, -1, -1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] [1, 0, 240, 0, 2160, 0, 6720, 0, 17520, 0, 30240] [0, -1, -1, 1, -1, -1, 1, 2, -1, 2, -1] [5/2*x, x, 2*x, 0, 3*x, 2*x] [ 3 3] [-1/3 -3] [1/4, -1/4]~ [0, 1, 0, -3, 0, -2, 0, -4, 0, 6, 0, 2, 0, -5, 0, 6] [0, 0, 0, 0, 0, 0, 0] [64/5, 4/5, 32/5]~ [1, 20, 180, 960, 3380, 8424, 16320, 28800, 52020, 88660, 129064, 175680, 26 2080, 386920, 489600, 600960] [1, 180, 3380, 16320, 52020, 129064, 262080] [0, 4, -16, 0, 64, -56, 0, 0, -256, 324, 224, 0, 0, -952, 0, 0] [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [3, 12, 12, 0, 12, 24, 0, 0, 12, 12, 24, 0, 0, 24, 0, 0] 23: [[22, [[0, 1, -1, -1, 0, 0, 1, 0, 1, 0, 0, 0, 0, -1, 0, 0]]]] 31: [[30, [[0, 1, -1, 0, 0, -1, 0, -1, 1, 1, 1, 0, 0, 0, 1, 0]]]] 39: [[38, [[0, 1, 0, -1, -1, 0, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0]]]] 44: [[21, [[0, 1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1]]]] 46: [[45, [[0, 1, 0, -1, -1, 0, 0, 0, 1, 0, 0, 0, 1, -1, 0, 0], [0, 0, 1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0]]]] 47: [[46, [[0, 1, 0, -1, 0, 0, -1, 0, -1, 1, 0, 0, 1, 0, 1, 0], [0, 0, 1, -1 , -1, 0, 0, 1, 0, 1, 0, 0, 0, 0, -1, 0]]]] 52: [[3, [[0, 1, -t, 0, t - 1, -1, 0, 0, 1, t - 1, t, 0, 0, -t, 0, 0]]]] 55: [[54, [[0, 1, 0, 0, -1, -1, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0]]]] 56: [[13, [[0, 1, -1, 0, 1, 0, 0, -1, -1, -1, 0, 0, 0, 0, 1, 0]]]] 57: [[26, [[0, 1, 0, -t, t - 1, 0, 0, -1, 0, t - 1, 0, 0, 1, -t + 1, 0, 0]]] ] 59: [[58, [[0, 1, 0, -1, 1, -1, 0, -1, 0, 0, 0, 0, -1, 0, 0, 1]]]] 62: [[61, [[0, 1, 0, 0, -1, -1, 0, -1, 1, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0]]]] 63: [[55, [[0, 1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0]]]] 68: [[67, [[0, 1, -1, 0, 1, 0, 0, 0, -1, -1, 0, 0, 0, -2, 0, 0]]], [47, [[0, 1, t, 0, -1, -t - 1, 0, 0, -t, t, -t + 1, 0, 0, 0, 0, 0]]]] 69: [[22, [[0, 1, -1, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, -1, 0, 0], [0, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0]]]] 71: [[70, [[0, 1, 0, 0, 0, -1, -1, 0, 0, 1, 0, 0, -1, 0, 0, -1], [0, 0, 1, 0 , -1, -1, -1, 0, 1, 1, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, -1, -1, 0, 0, 1, 0, 1 , 0, 0, 0, 0, -1]]]] 72: [[67, [[0, 1, -t, -t, t - 1, 0, t - 1, 0, 1, t - 1, 0, t, 1, 0, 0, 0]]]] 76: [[37, [[0, 1, 0, 0, 0, -1, 0, -1, 0, 1, 0, -1, 0, 0, 0, 0]]]] 77: [[69, [[0, 1, t^2 - t, 0, t - 1, 0, 0, -t^3, -t^2, t^3 - t^2 + t - 1, 0, -t, 0, 0, t^3 - t^2 + t, 0]]]] 78: [[77, [[0, 1, 0, -1, -1, 0, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0], [0, 0, 1, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0]]]] 79: [[78, [[0, 1, 0, 0, 0, -1, 0, 0, -1, 1, -1, 0, 0, 0, 0, 0], [0, 0, 1, 0, -1, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0]]]] 80: [[79, [[0, 1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0]]]] 83: [[82, [[0, 1, 0, -1, 1, 0, 0, -1, 0, 0, 0, -1, -1, 0, 0, 0]]]] 84: [[65, [[0, 1, 0, -t, 0, 0, 0, t - 1, 0, t - 1, 0, 0, 0, -1, 0, 0]]]] 87: [[86, [[0, 1, 0, 0, 0, 0, -1, -1, 0, 1, 0, 0, 0, -1, 0, 0], [0, 0, 1, -1 , 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, -1, 0]]]] 88: [[65, [[0, 1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1], [0, 0, 1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, 0, 0]]], [59, [[0, 1, -t, t^3 + t - 1, t^2, 0, -t^3 + 1, 0, -t^3, -t^2 - 1, 0, -t^3, t^3 - t^2 - 1, 0, 0, 0]]]] 92: [[45, [[0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0], [0, 0, 1, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0]]]] 93: [[61, [[0, 1, -1, 0, 0, -1, 0, -1, 1, 1, 1, 0, 0, 0, 1, 0], [0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1]]], [47, [[0, 1, 0, -t, -t^3, 0, 0, t^ 3 + t - 1, 0, t^2, 0, 0, t^3 - t^2 + t - 1, -t^2 + t - 1, 0, 0]]]] 94: [[93, [[0, 1, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, -1, 1, -1, 0, 0 , -1, 0, 0, 0], [0, 0, 0, 0, 1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 1, 0]]]] 95: [[94, [[0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0], [0, 0, 1, -1, 0, 0, 0, 0, 0, 0, -1, 0, -1, 1, 0, 1], [0, 0, 0, 0, 1, -1, -1, 0, 0, 1, 0, 1, 0, 0, 0, 0]]]] 99: [[76, [[0, 1, 0, t - 1, t - 1, -t + 1, 0, 0, 0, -t, 0, -t, -t, 0, 0, t]] ]] 100: [[91, [[0, 1, -t, 0, t^2, -t^3, 0, 0, -t^3, t^3 - t^2 + t - 1, t^3 - t^ 2 + t - 1, 0, 0, t^2 - t, 0, 0]]]] 103: [[102, [[0, 1, 0, 0, 0, 0, 0, -1, -1, 1, 0, 0, 0, 0, -1, 0], [0, 0, 1, 0, -1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0]]]] 104: [[51, [[0, 1, 0, -1, 1, 0, 0, 0, 0, 0, -1, 0, -1, 0, -1, 0], [0, 0, 1, 0, 0, -1, -1, -1, 1, 0, 0, 0, 0, 1, 0, 1]]], [55, [[0, 1, 0, 0, 0, -1, 0, 0, 0, t - 1, 0, 0, 0, -t, 0, 0], [0, 0, 1, 0, -t, 0, 0, 0, t - 1, 0, -1, 0, 0, 0, 0, 0]]]] 107: [[106, [[0, 1, 0, -1, 1, 0, 0, 0, 0, 0, 0, -1, -1, -1, 0, 0]]]] 108: [[53, [[0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 0, 0]]]] 110: [[109, [[0, 1, 0, 0, -1, -1, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0]]]] 111: [[110, [[0, 1, 0, 0, 0, 0, 0, -1, 0, 1, -1, 0, -1, 0, 0, 0], [0, 0, 1, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 1, -1, 0, 0, -1, 0, 0, 1 , 0, 0, 0, 0, 0]]], [101, [[0, 1, 0, -t, t, 0, 0, -t, 0, t - 1, 0, 0, -t + 1 , t - 2, 0, 0]]], [26, [[0, 1, 0, t - 1, t - 1, 0, 0, -t + 1, 0, -t, 0, 0, - t, -t + 1, 0, 0]]]] 112: [[41, [[0, 1, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0]]], [69, [[0, 1, t, 0, -1, 0, 0, t, -t , -t, 0, -t - 1, 0, 0, -1, 0]]]] 114: [[83, [[0, 1, 0, -t, t - 1, 0, 0, -1, 0, t - 1, 0, 0, 1, -t + 1, 0, 0], [0, 0, 1, 0, 0, 0, -t, 0, t - 1, 0, 0, 0, 0, 0, -1, 0]]]] 115: [[91, [[0, 1, -1, -1, 0, 0, 1, 0, 1, 0, 0, 0, 0, -1, 0, 0], [0, 0, 0, 0 , 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1]]]] 116: [[115, [[0, 1, 0, 0, 1, -1, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0], [0, 0, 1, -1, 0, 0, 0, 0, 1, 0, -1, -1, -1, 0, 0, 1]]], [103, [[0, 1, -t, 0, t^2, -t^5 + t^4, 0, 0, -t^3, -t^3, -t^4 + t^3 - t^2 + t - 1, 0, 0, t^5 - t^4 + t^3 + t - 1, 0, 0]]]] 117: [[116, [[0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0], [0, 0, 0, 1 , 0, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, 0]]], [73, [[0, 1, 0, 0, -t, 0, 0, t - 1, 0, 0, 0, 0, 0, t, 0, 0]]]] 118: [[117, [[0, 1, 0, -1, 1, -1, 0, -1, 0, 0, 0, 0, -1, 0, 0, 1], [0, 0, 1, 0, 0, 0, -1, 0, 1, 0, -1, 0, 0, 0, -1, 0]]]] 119: [[118, [[0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1], [0, 0, 1, 0 , -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, -2, -1, 0, 0, 1, 0, 2, 0, 1, 0], [0, 0, 0, 0, 0, 1, -1, -1, 0, 0, 1, 0, 1, 0, 0, 0]]]] 120: [[29, [[0, 1, 0, 0, -1, 0, -1, 0, 0, -1, 1, 0, 0, 0, 0, 1], [0, 0, 1, 1 , 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0]]]] 124: [[61, [[0, 1, 0, 0, 0, -1, 0, -1, 0, 1, 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, 0, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0]]], [87, [[0, 1, 0, 0, -1, t - 1, -t, 0, 0, 0, 0, 0, 0, -t + 1 , t, 0], [0, 0, 1, t, 0, 0, 0, -t, -1, 0, t - 1, -t + 1, -t, 0, 0, -1]]]] 126: [[55, [[0, 1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 0]]]] 127: [[126, [[0, 1, 0, 0, 0, 0, 0, 0, -1, 1, 0, -1, 0, -1, 0, 0], [0, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0]]]] 128: [[63, [[0, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0]]]] 129: [[41, [[0, 1, 0, -t, -t^5, 0, 0, t^4 - t^3, 0, t^2, 0, 0, t^5 - t^4 + t ^3 - t^2 + t - 1, t^5 - t^4 + t^3 + t - 1, 0, 0]]]] 131: [[130, [[0, 1, 0, 0, 1, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1], [0, 0, 0, 1, 0, -1, 0, -1, 0, -1, 0, 1, 1, 1, 0, 0]]]] 132: [[109, [[0, 1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1 , 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1]]]] 133: [[83, [[0, 1, -t, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, t - 1], [0, 0, 0 , 1, 0, -1, -t, t - 1, 0, 0, t, 0, 0, -t, 1, 0]]], [37, [[0, 1, 0, 0, -t, -t + 1, 0, t - 1, 0, t - 1, 0, t, 0, 0, 0, 0]]]] 135: [[134, [[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0]]]] 136: [[135, [[0, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -2, 0, 0], [0, 0, 1, 0 , -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]]], [67, [[0, 1, -1, 0, 1, 0, 0, 0, -1 , 1, 0, 0, 0, 0, 0, 0]]], [47, [[0, 1, 0, 0, 0, -t - 1, 0, 0, 0, t, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, t, 0, 0, 0, -1, 0, -t - 1, 0, 0, 0, 0, 0]]], [115, [ [0, 1, -t, -t - 1, -1, 0, t - 1, 0, t, t, 0, -t + 1, t + 1, 0, 0, 0]]], [43, [[0, 1, t^3, -t^3 + t^2, -t^2, 0, t^2 - t, 0, t, -t^2 + t - 1, 0, t^3 - 1, -t + 1, 0, 0, 0]]]] 138: [[91, [[0, 1, 0, 0, -1, 0, 0, 0, 1, -1, 0, 0, 0, -1, 0, 0], [0, 0, 1, 0 , -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0 , -1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0]]]] 139: [[138, [[0, 1, 0, 0, 1, -1, 0, -1, 0, 1, 0, -1, 0, -1, 0, 0]]]] 140: [[69, [[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1], [0, 0, 0, 1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0]]], [79, [[0, 1, 0, 0, -t, t - 1, -1, 0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 1, -t + 1, 0, 0, 0, t - 1, -t, 0, t - 1, 0, -1, 0, 0, t]]]] 141: [[46, [[0, 1, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 1, 0], [0, 0, 1, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0 , 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, 0]]]] 142: [[141, [[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, -1], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 1, -1, 0, 0, -1, 0, 0, -1], [0, 0, 0, 0, 1, 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0, -1, 0, -1, 0, 0, 0, 0, 0]]]] 143: [[142, [[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0], [0, 0, 1, 0 , 0, 0, 0, -2, -1, 0, 0, 1, 0, 1, 0, 0], [0, 0, 0, 1, -1, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, -1, -1, 0, 0, 1, 0, 1, 0, 0]]]] 144: [[127, [[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, 0]]], [103, [[0, 1, 0, -t, 0, 0, 0, 0, 0, t - 1, 0, t, 0, 0, 0, 0], [0, 0, 1, 0, -t, 0, -t, 0, t - 1, 0, 0, 0, t - 1, 0, 0, 0]]]] 145: [[99, [[0, 1, 0, 0, t, -t, 0, 0, 0, t, 0, -t - 1, 0, 0, 0, 0]]], [57, [ [0, 1, 0, 0, t, t, 0, -t - 1, 0, -t, 0, 0, 0, -t + 1, 0, 0]]]] 147: [[92, [[0, 1, 0, -t, -t^3, 0, 0, -t^5, 0, t^2, 0, 0, t^4, t^5 + t^3 - t ^2 + t - 1, 0, 0]]]] 148: [[105, [[0, 1, 0, -t, 0, 0, 0, -1, 0, 0, 0, t, 0, 0, 0, 0]]], [63, [[0, 1, -t, 0, t - 1, -t + 1, 0, 0, 1, -t, -1, 0, 0, 2*t - 2, 0, 0]]], [127, [[0 , 1, -t, 0, t^2, t^4 + t^3 - 1, 0, 0, -t^3, -t^4 + t, -t^5 - t^4 + t, 0, 0, -t^2, 0, 0]]]] [1, 0, 0] [2, 0, 0] [3, 0, 0] [4, 0, 0] [5, 0, 0] [6, 0, 0] [7, 0, 0] [8, 0, 0] [9, 0, 0] [10, 0, 0] [11, 0, 0] [12, 0, 0] [13, 0, 0] [14, 0, 0] [15, 0, 0] [16, 0, 0] [17, 0, 0] [18, 0, 0] [19, 0, 0] [20, 0, 0] [21, 0, 0] [22, 0 , 0] [23, 1, 1] [24, 0, 0] [25, 0, 0] [26, 0, 0] [27, 0, 0] [28, 0, 0] [29, 0, 0] [30, 0, 0] [31, 1, 1] [32, 0, 0] [33, 0, 0] [34, 0, 0] [35, 0, 0] [36, 0, 0] [37, 0, 0] [38, 0, 0] [39, 1, 1] [40, 0, 0] [41, 0, 0] [42, 0, 0] [43 , 0, 0] [44, 1, 1] [45, 0, 0] [46, 2, 0] [47, 2, 2] [48, 0, 0] [49, 0, 0] [5 0, 0, 0] [51, 0, 0] [52, 2, 2] [53, 0, 0] [54, 0, 0] [55, 1, 1] [56, 1, 1] [ 57, 2, 2] [58, 0, 0] [59, 1, 1] [60, 0, 0] [61, 0, 0] [62, 2, 0] [63, 1, 1] [64, 0, 0] [65, 0, 0] [66, 0, 0] [67, 0, 0] [68, 3, 3] [69, 2, 0] [70, 0, 0] [71, 3, 3] [72, 2, 2] [73, 0, 0] [74, 0, 0] [75, 0, 0] [76, 1, 1] [77, 4, 4 ] [78, 2, 0] [79, 2, 2] [80, 1, 1] [81, 0, 0] [82, 0, 0] [83, 1, 1] [84, 2, 2] [85, 0, 0] [86, 0, 0] [87, 2, 2] [88, 6, 4] [89, 0, 0] [90, 0, 0] [91, 0, 0] [92, 3, 0] [93, 6, 4] [94, 4, 0] [95, 3, 3] [96, 0, 0] [97, 0, 0] [98, 0 , 0] [99, 2, 2] [100, 4, 4] [101, 0, 0] [102, 0, 0] [103, 2, 2] [104, 6, 2] [105, 0, 0] [106, 0, 0] [107, 1, 1] [108, 1, 1] [109, 0, 0] [110, 2, 0] [111 , 7, 7] [112, 4, 2] [113, 0, 0] [114, 4, 0] [115, 2, 0] [116, 8, 8] [117, 4, 2] [118, 2, 0] [119, 4, 4] [120, 2, 2] [121, 0, 0] [122, 0, 0] [123, 0, 0] [124, 7, 4] [125, 0, 0] [126, 2, 0] [127, 2, 2] [128, 1, 1] [129, 6, 6] [130 , 0, 0] [131, 2, 2] [132, 2, 0] [133, 6, 6] [134, 0, 0] [135, 2, 2] [136, 13 , 7] [137, 0, 0] [138, 4, 0] [139, 1, 1] [140, 6, 6] [141, 4, 0] [142, 6, 0] [143, 4, 4] [144, 5, 1] [145, 4, 4] [146, 0, 0] [147, 6, 6] [148, 10, 10] [ 149, 0, 0] [150, 0, 0] [[22, Mod(5, 23), 1, 0], [2, Mod(22, 23), 2, 1]] [[2, Mod(22, 23), 1, 1]] [[2, Mod(22, 23), 1, 1]] [] [[2, Mod(22, 23), 1, 0], [22, Mod(5, 23), 1, 0]] [[2, Mod(45, 46), 2, -1]] [[0, 0], [0, 0], [0, 0], [1, 1]] [[0, 0], [0, 0], [0, 0], [1, 1]] [[0, 0], [0, 0], [0, 0], [0, 0]] 98 193 95 127 320 [[1, Mod(1, 96), 2, 0], [2, Mod(95, 96), 4, 0], [2, Mod(49, 96), 2, 0], [2, Mod(47, 96), 2, 0], [8, Mod(37, 96), 8, 0], [8, Mod(59, 96), 14, 0]] [[1, Mod(1, 96), 9, 0], [2, Mod(95, 96), 8, 0], [2, Mod(49, 96), 8, 0], [2, Mod(47, 96), 8, 0], [4, Mod(25, 96), 12, 0], [4, Mod(71, 96), 12, 0], [8, Mo d(37, 96), 14, 0], [8, Mod(59, 96), 14, 0]] [[1, Mod(1, 96), 7, 0], [2, Mod(95, 96), 4, 0], [2, Mod(49, 96), 6, 0], [2, Mod(47, 96), 6, 0], [4, Mod(25, 96), 12, 0], [4, Mod(71, 96), 12, 0], [8, Mo d(37, 96), 6, 0]] [[1, Mod(1, 96), 15, 0], [2, Mod(95, 96), 16, 0], [2, Mod(49, 96), 16, 0], [ 2, Mod(47, 96), 16, 0], [4, Mod(25, 96), 8, 0], [4, Mod(71, 96), 8, 0], [8, Mod(37, 96), 4, 0], [8, Mod(59, 96), 4, 0]] [[1, Mod(1, 96), 24, 0], [2, Mod(95, 96), 24, 0], [2, Mod(49, 96), 24, 0], [ 2, Mod(47, 96), 24, 0], [4, Mod(25, 96), 20, 0], [4, Mod(71, 96), 20, 0], [8 , Mod(37, 96), 18, 0], [8, Mod(59, 96), 18, 0]] [[2, 0], [0, 0], [0, 0], [4, 0], [8, 0], [0, 0], [0, 0], [14, 0], [0, 0], [0 , 0], [0, 0], [0, 0], [2, 0], [0, 0], [0, 0], [2, 0]] [[9, 0], [0, 0], [0, 0], [8, 0], [14, 0], [0, 0], [0, 0], [14, 0], [12, 0], [0, 0], [0, 0], [12, 0], [8, 0], [0, 0], [0, 0], [8, 0]] [[7, 0], [0, 0], [0, 0], [4, 0], [6, 0], [0, 0], [0, 0], [0, 0], [12, 0], [0 , 0], [0, 0], [12, 0], [6, 0], [0, 0], [0, 0], [6, 0]] [[15, 0], [0, 0], [0, 0], [16, 0], [4, 0], [0, 0], [0, 0], [4, 0], [8, 0], [ 0, 0], [0, 0], [8, 0], [16, 0], [0, 0], [0, 0], [16, 0]] [[24, 0], [0, 0], [0, 0], [24, 0], [18, 0], [0, 0], [0, 0], [18, 0], [20, 0] , [0, 0], [0, 0], [20, 0], [24, 0], [0, 0], [0, 0], [24, 0]] 10 2 0 5 3 2 [1, 2, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0] [1/2 - 1/2*I, 0, 1/2 - 1/2*I, 1, 1.2548652488804080851212455162477386227 + 0 .13774935502057657907313538946599934252*I] [0, 2, 0, 0, Mod(-2*t - 2, t^2 + t + 1), 0, 0, 0, 0, Mod(2*t, t^2 + t + 1), 0, 0, 0, 0, 0, 0] [196, 1/2, Mod(2, 7), y, t^2 + t + 1] [0, 2, 0, 0, Mod(4*t, t^2 + 1), 0, 0, 0, 0, Mod(-6*t, t^2 + 1), 0, 0, 0, 0, 0, 0] [100, 3/2, Mod(7, 20), y, t^2 + 1] [1, -264, -135432, -5196576, -69341448, -515625264, -2665843488, -1065335251 2, -35502821640, -102284205672, -264515760432, -622498190688, -1364917062432 , -2799587834736, -5465169838656, -10149567696576] [0, 1, -24, 252, -1472, 4830, -6048, -16744, 84480, -113643, -115920, 534612 , -370944, -577738, 401856, 1217160] [1, 12, 1, 1, t - 1] [1, -24, 252, -1472, 4830, -6048, -16744, 84480, -113643, -115920, 534612, - 370944, -577738, 401856, 1217160, 987136] [1/1728, 0, -1/20736, 0, 1/165888, 0, 1/497664, 0, -11/3981312, 0, 7/1592524 8] [0.0017853698506421519043430549603422623106, 0, -0.0171012292073417293156314 59010992410421, 0, 0.040951184469824320600328376773822139547, 0, 0.104600637 48004752177296678887319501733, 0, -0.59041770925463104960248994945766228175, 0, 0.23992339736027093580525099155844404883] 1 [1728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 1728, -41472, 435456, -2543616, 8346240, -10450944, -28933632, 145981440 , -196375104, -200309760, 923809536, -640991232, -998331264, 694407168, 2103 252480] [0, -504, -33264, -368928, -2130912, -7877520, -24349248] [0, -504, -8316, -40992, -133182, -1575504/5, -676368] [-1/2, -240, -30960, -525120, -3963120, -18750240, -67740480] [Mod(21/19*t^5 - 4/19*t^4 - 68/19*t^3 + 24/19*t^2 - 29/19*t - 37/19, t^6 + t ^3 + 1), Mod(-9/19*t^5 + 18/19*t^4 + 40/19*t^3 + 6/19*t^2 + 7/19*t - 14/19, t^6 + t^3 + 1), Mod(-21/19*t^5 - 34/19*t^4 + 106/19*t^3 - 24/19*t^2 + 67/19* t + 75/19, t^6 + t^3 + 1), Mod(-27/19*t^5 + 73/19*t^4 + 101/19*t^3 - 39/19*t ^2 + 59/19*t + 91/19, t^6 + t^3 + 1), Mod(-37/19*t^5 - 40/19*t^4 - 129/19*t^ 3 - 140/19*t^2 + 14/19*t + 10/19, t^6 + t^3 + 1), Mod(37/19*t^5 - 188/19*t^4 + 148/19*t^3 - 69/19*t^2 - 261/19*t + 104/19, t^6 + t^3 + 1), Mod(13/19*t^5 - 7/19*t^4 - 157/19*t^3 + 251/19*t^2 + 11/19*t + 16/19, t^6 + t^3 + 1)] [0, -8, 0, 0, 448, -960, 0, 0, 1920, -72, 0, 0, -11520, 10560, 0, 0] [0] [1, 2, 0, 0, 242, 480, 0, 0, 2640, 4322, 0, 0, 11040, 13920, 0, 0] [1] [0, -1, 24, -252, 1472, -4830, 6048, 16744, -84480, 113643, 115920] [[1, 1], 0.16568457302248264542066459293908431501] [y, y^2 + Mod(-t, t^2 + 1)*y + 32] [t^2 + 1, [1, I, -1, -I]~] [0, 1, -4 - 4*I, -23 + 23*I, 32*I] [t^2 + 1, [1, I, -1, -I]~] 2 [0, 1, 4 + 4*I, 23.894541729001368054461689919961782206 - 23.894541729001368 054461689919961782206*I, 32*I] [0, 1, 4 + 4*I, -32.894541729001368054461689919961782206 + 32.89454172900136 8054461689919961782206*I, 32*I] [ 1 I] [0.E-38 - 5.1789083458002736108923379839923564411*I 1/2] (-0.42032884322677921722469742108951886443 - 0.36665141119210363722276336624 357748307*I)*x^5 + (-0.18897096195310015252637690454628340018 + 0.2334775315 3997872645748275207133555666*I)*x^4 + (0.05669894077036206721138027675869498 5766 + 0.019851987390139195033288439780776993730*I)*x^3 + (-0.01778807113146 0726637976503215205801403 - 0.0066687070863864346224329592313502928776*I)*x^ 2 + (-0.00014285107000277589442425212918179977119 + 0.0094974404850612698333 714635028430975514*I)*x + (0.0017634098246564914212887661127367171167 - 3.84 93221223953106272210521959657558937 E-5*I) (-0.42032884322677921722469742108951886443 - 0.36665141119210363722276336624 357748307*I)*x^5 + (-0.18897096195310015252637690454628340018 + 0.2334775315 3997872645748275207133555666*I)*x^4 + (0.05669894077036206721138027675869498 5766 + 0.019851987390139195033288439780776993730*I)*x^3 + (-0.01778807113146 0726637976503215205801403 - 0.0066687070863864346224329592313502928776*I)*x^ 2 + (-0.00014285107000277589442425212918179977119 + 0.0094974404850612698333 714635028430975514*I)*x + (0.0017634098246564914212887661127367171167 - 3.84 93221223953106272210521959657558937 E-5*I) [(-0.11978968330084743941034336902296121263 + 0.6675712441890031614835686639 3309199760*I)*x^5 + (0.47459258827123214210389409418585137394 + 0.0738116455 79858397157878143011696499169*I)*x^4 + (0.0239881015411315413733797131896244 63396 - 0.19195836968288495139427189581460315486*I)*x^3 + (-0.06091879582539 5161943853589975161158104 - 0.0055897035583019227181012364528570531811*I)*x^ 2 + (-0.00093396277153707022978325343297000205630 + 0.0151596173238831031064 47349960285186585*I)*x + (0.0021431928592073859680903512704736845544 + 8.205 9193124110226533224704061362634241 E-5*I), (-0.62739345285811739127778056884 021600097 - 0.087390135179795679398135448226837566631*I)*x^5 + (0.0071366457 725152534775841805760933396780 + 0.40397833014354552911285996147380482698*I) *x^4 + (0.12891258393984629705652072463003358643 - 0.05228352106134393940156 8419229621475946*I)*x^3 + (-0.035464631571369665466140174106504828211 - 0.02 6028100099104453183586604526392274925*I)*x^2 + (-0.0033524403603294024998684 552942059280440 + 0.012329256529445897292427816673749766245*I)*x + (0.001991 1655001689021405322834054755664714 + 0.0002187595828686439236664039723449641 6014*I)] (-0.42032884322677921722469742108951886443 - 0.36665141119210363722276336624 357748307*I)*x^5 + (-0.18897096195310015252637690454628340018 + 0.2334775315 3997872645748275207133555666*I)*x^4 + (0.05669894077036206721138027675869498 5766 + 0.019851987390139195033288439780776993730*I)*x^3 + (-0.01778807113146 0726637976503215205801403 - 0.0066687070863864346224329592313502928776*I)*x^ 2 + (-0.00014285107000277589442425212918179977119 + 0.0094974404850612698333 714635028430975514*I)*x + (0.0017634098246564914212887661127367171167 - 3.84 93221223953106272210521959657558937 E-5*I) (0.63503857136548153723243364047328438986 + 3.514572428867635055012606515575 9628731*I)*x^5 + (-0.55372847947444593258698788340168966082 - 9.108921742882 8235118512107360613470523*I)*x^4 + (-0.5736853636153969172965804481164446308 3 + 9.3350094980459189288929480268625379486*I)*x^3 + (0.92067030358191022593 055872189272950582 - 4.7134500726338769290757263902171115959*I)*x^2 + (-0.40 943867072608376472339177571526455001 + 1.15651384868088764032207293563713484 07*I)*x + (0.059036856826078966302068066654747180072 - 0.1074704942638566941 6527151515690888886*I) (0.50591569408594293044173544719087511946 + 2.117281275622317566448200088099 4098275*I)*x^5 + (-0.50329189412202947783246908444432161292 - 5.590428274519 0468676320341127315401960*I)*x^4 + (-0.3497080814333576092739419971721942705 1 + 5.8131984654812768380493298366830104987*I)*x^3 + (0.67136183809998279160 852888055285137912 - 2.9619446659820968460170467417907610716*I)*x^2 + (-0.31 298236313441943447438431991727961780 + 0.72375422627359354753058812996616936 826*I)*x + (0.046021296425325344919105451970096214097 - 0.064981133287689249 704701491873473271745*I) (0.50591569408757962384361452599497966291 + 2.117281275639064594489871762594 8918260*I)*x^5 + (-0.50329189412193445432675932972323847027 - 5.590428274561 3236110866820457378951587*I)*x^4 + (-0.3497080814376803071251059760080492944 6 + 5.8131984655235440791534068179731335741*I)*x^3 + (0.67136183810425750258 930943563014705872 - 2.9619446660030143316765275738312612505*I)*x^2 + (-0.31 298236313601104936106517214476233040 + 0.72375422627871605117093909126879831 832*I)*x + (0.046021296425535731444176918743279766645 - 0.064981133288185583 919869819271833506431*I) (164.35262898335787004106106716673677130 + 27.238600223902468333759517924304 610904*I)*x^5 + (-271.95434178285557919428732408774729971 - 54.8341728611807 65120958234414937486873*I)*x^4 + (180.19514127347078229995469690124466357 + 41.691669235812561554783086959210566385*I)*x^3 + (-59.9543068680018830870208 43160703944761 - 15.111269706996669294559216350864552013*I)*x^2 + (10.065256 240339619831161098072464760373 + 2.6184808251354815164522274491363646980*I)* x + (-0.68672917564913976846740362654117485201 - 0.1732219127234492275765682 9146590865136*I) [(-37.400871663494856516636401987243309210 - 123.329800340743528756196753860 76255844*I)*x^5 + (53.268246125228312340154821977677892221 + 207.67678245211 016109263953978319052970*I)*x^4 + (-28.666898066293079278659311038421188987 - 139.64875858061674710101939900539440561*I)*x^3 + (6.8676880960045824324968 267496774844483 + 46.814934586818559059649732674905180429*I)*x^2 + (-0.59643 957211173608030883172017086163757 - 7.8046112726147121874007178376101555939* I)*x + (-0.0064055991688804413829736007101014212258 + 0.51526489380605352673 507681658732620789*I), (140.09242210378463676125436253030190949 - 46.3393403 38148920959200393601425458778*I)*x^5 + (-239.1537304828094629201233858532011 7138 + 64.836449022531128110429287661758992831*I)*x^4 + (162.744445131511330 16860078839933141537 - 33.558240643220739258219626272248254402*I)*x^3 + (-55 .079528297804953230956818685769222608 + 7.3487498203155016127222453918267226 450*I)*x^2 + (9.2420957758989707670959015639234112401 - 0.450495026534426142 94207267772156672859*I)*x + (-0.61189800800168155000144831291875936999 - 0.0 33316392602605981857006660342857673457*I)] [0, 0] 1.0024642466164642932880429736720212519 E-5 [1.0616767679426667234166859887525352956 E-5 0] [0 1.3579771881756813076319839557062773447 E-5] 1 1 [[((61893*t - 42501)*y + (-301056*t + 307452))*x^5 + ((-1166160*t + 897220)* y + (5999170*t - 11970090))*x^3 + ((2722848*t - 2437636)*y + (-14350096*t + 127683672))*x, ((-1556688*t + 1540416)*y + (8350926*t - 115713582))*x^5 + (( 775632*t - 254024)*y + (-3647414*t - 91773402))*x^4 + ((2332320*t - 1794440) *y + (-11998340*t + 23940180))*x^3 + ((-2332320*t + 1794440)*y + (11998340*t - 23940180))*x^2 + ((-775632*t + 254024)*y + (3647414*t + 91773402))*x + (( 1556688*t - 1540416)*y + (-8350926*t + 115713582)), ((-2034*t + 387138)*y + (-13420332*t - 9981516))*x^5 + ((-64862*t + 64184)*y + (-22679326*t - 186377 68))*x^4 + ((593250*t - 2384300)*y + (8836600*t + 627150))*x^3 + ((648620*t - 641840)*y + (5731360*t - 34684220))*x^2 + ((-1562112*t + 2572784)*y + (940 7024*t + 27149832))*x + 176849520, ((2034*t - 387138)*y + (-163429188*t + 99 81516))*x^5 + ((-2637646*t - 1497928)*y + (-49829158*t - 9230744))*x^4 + ((4 8590*t + 3032920)*y + (25847620*t + 5104210))*x^3 + ((3032920*t - 48590)*y + (5104210*t - 25847620))*x^2 + ((1497928*t - 2637646)*y + (9230744*t - 49829 158))*x + ((-387138*t - 2034)*y + (9981516*t + 163429188)), (-22106190*t + 2 2106190)*x^5 + ((1033724*t - 252668)*y + (4435702*t - 9139214))*x^4 + ((6452 30*t + 3390)*y + (20207790*t - 14476430))*x^3 + ((-2977550*t + 1791050)*y + (-8209450*t - 9463750))*x^2 + ((-258092*t - 1356)*y + (-8083116*t - 82634188 ))*x + ((1556688*t - 1540416)*y + (13755264*t + 93607392)), ((355683*t + 120 069)*y + (-2132976*t - 281868))*x^5 + ((-897220*t - 1166160)*y + (11970090*t + 5999170))*x^3 + ((-1432727*t + 2508939)*y + (-21158346*t - 99350278))*x, (-22106190*t + 22106190)*x^5 + ((-1033724*t + 252668)*y + (-4435702*t + 9139 214))*x^4 + ((645230*t + 3390)*y + (20207790*t - 14476430))*x^3 + ((2977550* t - 1791050)*y + (8209450*t + 9463750))*x^2 + ((-258092*t - 1356)*y + (-8083 116*t - 82634188))*x + ((-1556688*t + 1540416)*y + (-13755264*t - 93607392)) , ((2034*t - 387138)*y + (-163429188*t + 9981516))*x^5 + ((2637646*t + 14979 28)*y + (49829158*t + 9230744))*x^4 + ((48590*t + 3032920)*y + (25847620*t + 5104210))*x^3 + ((-3032920*t + 48590)*y + (-5104210*t + 25847620))*x^2 + (( 1497928*t - 2637646)*y + (9230744*t - 49829158))*x + ((387138*t + 2034)*y + (-9981516*t - 163429188)), ((-2034*t + 387138)*y + (-13420332*t - 9981516))* x^5 + ((64862*t - 64184)*y + (22679326*t + 18637768))*x^4 + ((593250*t - 238 4300)*y + (8836600*t + 627150))*x^3 + ((-648620*t + 641840)*y + (-5731360*t + 34684220))*x^2 + ((-1562112*t + 2572784)*y + (9407024*t + 27149832))*x - 1 76849520, ((-1556688*t + 1540416)*y + (8350926*t - 115713582))*x^5 + ((-7756 32*t + 254024)*y + (3647414*t + 91773402))*x^4 + ((2332320*t - 1794440)*y + (-11998340*t + 23940180))*x^3 + ((2332320*t - 1794440)*y + (-11998340*t + 23 940180))*x^2 + ((-775632*t + 254024)*y + (3647414*t + 91773402))*x + ((-1556 688*t + 1540416)*y + (8350926*t - 115713582)), ((-77568*t + 417576)*y + (-25 584*t - 2434032))*x^5 + ((268940*t - 2063380)*y + (5970920*t + 17969260))*x^ 3 + ((-71303*t + 1290121)*y + (-28333394*t - 35508442))*x, -176849520*x^5 + ((1562112*t - 2572784)*y + (-9407024*t - 27149832))*x^4 + ((-648620*t + 6418 40)*y + (-5731360*t + 34684220))*x^3 + ((-593250*t + 2384300)*y + (-8836600* t - 627150))*x^2 + ((64862*t - 64184)*y + (22679326*t + 18637768))*x + ((203 4*t - 387138)*y + (13420332*t + 9981516)), ((-1540416*t - 1556688)*y + (9360 7392*t - 13755264))*x^5 + ((1356*t - 258092)*y + (82634188*t - 8083116))*x^4 + ((1791050*t + 2977550)*y + (-9463750*t + 8209450))*x^3 + ((-3390*t + 6452 30)*y + (14476430*t + 20207790))*x^2 + ((-252668*t - 1033724)*y + (-9139214* t - 4435702))*x + (-22106190*t - 22106190), ((-1540416*t - 1556688)*y + (936 07392*t - 13755264))*x^5 + ((-1356*t + 258092)*y + (-82634188*t + 8083116))* x^4 + ((1791050*t + 2977550)*y + (-9463750*t + 8209450))*x^3 + ((3390*t - 64 5230)*y + (-14476430*t - 20207790))*x^2 + ((-252668*t - 1033724)*y + (-91392 14*t - 4435702))*x + (22106190*t + 22106190), -176849520*x^5 + ((-1562112*t + 2572784)*y + (9407024*t + 27149832))*x^4 + ((-648620*t + 641840)*y + (-573 1360*t + 34684220))*x^3 + ((593250*t - 2384300)*y + (8836600*t + 627150))*x^ 2 + ((64862*t - 64184)*y + (22679326*t + 18637768))*x + ((-2034*t + 387138)* y + (-13420332*t - 9981516)), ((71303*t - 1290121)*y + (28333394*t + 3550844 2))*x^4 + ((-268940*t + 2063380)*y + (-5970920*t - 17969260))*x^2 + ((77568* t - 417576)*y + (25584*t + 2434032)), ((1432727*t - 2508939)*y + (21158346*t + 99350278))*x^4 + ((897220*t + 1166160)*y + (-11970090*t - 5999170))*x^2 + ((-355683*t - 120069)*y + (2132976*t + 281868)), ((-2722848*t + 2437636)*y + (14350096*t - 127683672))*x^4 + ((1166160*t - 897220)*y + (-5999170*t + 11 970090))*x^2 + ((-61893*t + 42501)*y + (301056*t - 307452))], [((52*t - 46)* y + (-316*t + 398))*x^4 + ((-250*t + 250)*y + (1750*t - 7250))*x^2 + 30000, ((-198*t + 204)*y + (1434*t + 23148))*x^5 + ((-240*t + 270)*y + (1920*t - 12 510))*x^4 + ((270*t - 210)*y + (-1410*t - 3270))*x^3 + ((270*t - 210)*y + (- 1410*t - 3270))*x^2 + ((-240*t + 270)*y + (1920*t - 12510))*x + ((-198*t + 2 04)*y + (1434*t + 23148)), ((6*t + 42)*y + (3012*t + 2484))*x^5 + ((-25*t + 165)*y + (-2595*t - 1355))*x^4 + ((-65*t + 15)*y + (-2115*t - 325))*x^3 + (( 190*t - 510)*y + (-450*t - 1210))*x^2 + ((260*t - 300)*y + (-420*t - 18020)) *x + ((-168*t + 264)*y + (1944*t + 7368)), ((270*t + 210)*y + (10380*t + 540 ))*x^5 + ((-275*t - 425)*y + (-15425*t + 1775))*x^4 + ((-575*t - 175)*y + (- 3325*t + 125))*x^3 + ((-175*t + 575)*y + (125*t + 3325))*x^2 + ((425*t - 275 )*y + (-1775*t - 15425))*x + ((210*t - 270)*y + (540*t - 10380)), ((-54*t + 12)*y + (-678*t + 1164))*x^5 + ((-140*t + 10)*y + (-4400*t + 4610))*x^4 + (( 350*t - 160)*y + (380*t - 830))*x^3 + ((80*t + 50)*y + (1790*t + 2440))*x^2 + ((-380*t + 280)*y + (-2480*t - 7900))*x + ((144*t - 192)*y + (-2112*t - 21 984)), ((144*t + 58)*y + (-1112*t - 234))*x^4 + (-250*y + (2750*t + 4500))*x ^2 + (-3750*t - 26250), ((54*t - 12)*y + (678*t - 1164))*x^5 + ((-140*t + 10 )*y + (-4400*t + 4610))*x^4 + ((-350*t + 160)*y + (-380*t + 830))*x^3 + ((80 *t + 50)*y + (1790*t + 2440))*x^2 + ((380*t - 280)*y + (2480*t + 7900))*x + ((144*t - 192)*y + (-2112*t - 21984)), ((-270*t - 210)*y + (-10380*t - 540)) *x^5 + ((-275*t - 425)*y + (-15425*t + 1775))*x^4 + ((575*t + 175)*y + (3325 *t - 125))*x^3 + ((-175*t + 575)*y + (125*t + 3325))*x^2 + ((-425*t + 275)*y + (1775*t + 15425))*x + ((210*t - 270)*y + (540*t - 10380)), ((-6*t - 42)*y + (-3012*t - 2484))*x^5 + ((-25*t + 165)*y + (-2595*t - 1355))*x^4 + ((65*t - 15)*y + (2115*t + 325))*x^3 + ((190*t - 510)*y + (-450*t - 1210))*x^2 + ( (-260*t + 300)*y + (420*t + 18020))*x + ((-168*t + 264)*y + (1944*t + 7368)) , ((198*t - 204)*y + (-1434*t - 23148))*x^5 + ((-240*t + 270)*y + (1920*t - 12510))*x^4 + ((-270*t + 210)*y + (1410*t + 3270))*x^3 + ((270*t - 210)*y + (-1410*t - 3270))*x^2 + ((240*t - 270)*y + (-1920*t + 12510))*x + ((-198*t + 204)*y + (1434*t + 23148)), ((-12*t + 196)*y + (-164*t - 1428))*x^4 + (-250 *y + (2750*t + 4500))*x^2 + (-3750*t - 3750), ((-168*t + 264)*y + (1944*t + 7368))*x^5 + ((260*t - 300)*y + (-420*t - 18020))*x^4 + ((190*t - 510)*y + ( -450*t - 1210))*x^3 + ((-65*t + 15)*y + (-2115*t - 325))*x^2 + ((-25*t + 165 )*y + (-2595*t - 1355))*x + ((6*t + 42)*y + (3012*t + 2484)), ((-192*t - 144 )*y + (-21984*t + 2112))*x^5 + ((-280*t - 380)*y + (7900*t - 2480))*x^4 + (( 50*t - 80)*y + (2440*t - 1790))*x^3 + ((160*t + 350)*y + (830*t + 380))*x^2 + ((10*t + 140)*y + (4610*t + 4400))*x + ((-12*t - 54)*y + (-1164*t - 678)), ((192*t + 144)*y + (21984*t - 2112))*x^5 + ((-280*t - 380)*y + (7900*t - 24 80))*x^4 + ((-50*t + 80)*y + (-2440*t + 1790))*x^3 + ((160*t + 350)*y + (830 *t + 380))*x^2 + ((-10*t - 140)*y + (-4610*t - 4400))*x + ((-12*t - 54)*y + (-1164*t - 678)), ((168*t - 264)*y + (-1944*t - 7368))*x^5 + ((260*t - 300)* y + (-420*t - 18020))*x^4 + ((-190*t + 510)*y + (450*t + 1210))*x^3 + ((-65* t + 15)*y + (-2115*t - 325))*x^2 + ((25*t - 165)*y + (2595*t + 1355))*x + (( 6*t + 42)*y + (3012*t + 2484)), (-3750*t - 3750)*x^5 + (-250*y + (2750*t + 4 500))*x^3 + ((-12*t + 196)*y + (-164*t - 1428))*x, (-3750*t - 26250)*x^5 + ( -250*y + (2750*t + 4500))*x^3 + ((144*t + 58)*y + (-1112*t - 234))*x, 30000* x^5 + ((-250*t + 250)*y + (1750*t - 7250))*x^3 + ((52*t - 46)*y + (-316*t + 398))*x]] Mod(-904583688/27200667365, y^2 + Mod(-t, t^2 + 1)*y + 32)*y^2 + Mod(-485238 4244/5440133473, y^2 + Mod(-t, t^2 + 1)*y + 32) 0.0011925695879998878380848926233233473256*x^3 - 0.0034461762994896503999275 399407078201462*I*x^2 - 0.0029814239699997195952122315583083683139*x (0.0011925695879998878380848926233233473256*x^4 + 0.001788854381999831757127 3389349850209884*x^3 + 0.0011925695879998878380848926233233473255*x^2 + 0.00 17888543819998317571273389349850209884*x + 0.0011925695879998878380848926233 233473256)/x (0.0011925695879998878380848926233233473256*x^4 + 0.001788854381999831757127 3389349850209884*x^3 + 0.0017888543819998317571273389349850209884*x - 0.0011 925695879998878380848926233233473256)/x (0.0011925695879998878380848926233233473256*x^4 - 0.001788854381999831757127 3389349850209884*x^3 - 0.0017888543819998317571273389349850209884*x - 0.0011 925695879998878380848926233233473256)/x (0.0011925695879998878380848926233233473256*x^4 - 0.001788854381999831757127 3389349850209884*x^3 + 0.0011925695879998878380848926233233473255*x^2 - 0.00 17888543819998317571273389349850209884*x + 0.0011925695879998878380848926233 233473256)/x (-0.0029814239699997195952122315583083683139*x^2 + 0.00344617629948965039992 75399407078201462*I*x + 0.0011925695879998878380848926233233473256)/x (-0.0029814239699997195952122315583083683139*x^2 + 0.00344617629948965039992 75399407078201462*I*x + 0.0011925695879998878380848926233233473256)/x (0.13416407864998738178455042012387657413 - 0.086154407487241259998188498517 695503654*I)*x^2 + (-0.089442719099991587856366946749251049416 + 0.034461762 994896503999275399407078201462*I)*x + 0.017888543819998317571273389349850209 883 -0.062500000000000000000000000000000000000*I*x^2 - 0.00390625000000000000000 00000000000000000*I (-0.029076134702187599205839917739040862356*x^3 + (0.02180710102664069940437 9938304280646767 + 0.020833333333333333333333333333333333302*I)*x^2 + (-0.00 54517752566601748510949845760701616916 - 0.010416666666666666666666666666666 666659*I)*x + (0.00045431460472168123759124871467251347431 + 0.0039062500000 000000000000000000000000000*I))/(4*x - 1) -10.687500000000000000000000000000000000*I*x^2 + 8.0000000000000000000000000 000000000000*I*x - 2.0000000000000000000000000000000000000*I 0.023437500000000000000000000000000000000*I*x^2 + 0.031250000000000000000000 000000000000000*I*x + 0.093750000000000000000000000000000000000*I [[1], [1, 1]] [[0.70710678118654752440084436210484903928 + 0.70710678118654752440084436210 484903928*I], [-0.70710678118654752440084436210484903928 - 0.707106781186547 52440084436210484903928*I, -0.70710678118654752440084436210484903928 - 0.707 10678118654752440084436210484903928*I]] [[0.99595931395311210936063384855913482216 - 0.08980559531591707448838903035 9505357517*I], [0.53927595283868673281600574405026404173 + 0.842129115213294 66664554619540652632773*I, -0.85895466516104552261001111734173629157 + 0.512 05164114381683048538165804971399484*I]] [[-0.76775173011852704509198454449006172342 - 0.6407474392457674209160837770 1764443336*I], [-0.21414952481887583992521740447795630385 + 0.97680089118502 020368501019184890743540*I, -0.96944785623768905552448638076096150649 - 0.24 529748069670216936666745500978951117*I]] [10, 7, Mod(2, 5), 0, t^2 + 1] 3 [0, 3, 4*t + 4, 32*t - 32, 96*t, 155*t + 90, 112, -348*t - 348, 128*t - 128, -2177*t] 2 [0, 1, -4*t - 4, 23*t - 23, 32*t, 100*t - 75, 184, -247*t - 247, -128*t + 12 8, -329*t] [0, 1, 4*t + 4, (5*t + 5)*y + (2*t - 2), 32*t, (-5*t - 15)*y + (35*t + 80), 40*t*y - 16, (-55*t + 55)*y + (-78*t - 78), 128*t - 128, -90*y - 879*t] [0, 1, -2, -1, 2, 1, 2, -2, 0, -2, -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, 1] [-1/12, -3/2, 16/3, -1/12, -27/4, 1/6, 4/3]~ [0, 0, -2399/5121840000, -479/13111910400000, 1/307310400000]~ [1, 0, 0, 0, 0, 0] 8 [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]~ 12 x^12 + Mod(-4*t - 4, t^2 + t + 1)*x^11 + Mod(-4*t, t^2 + t + 1)*x^10 + Mod(- 40, t^2 + t + 1)*x^9 + Mod(27*t + 27, t^2 + t + 1)*x^8 + Mod(150*t, t^2 + t + 1)*x^7 + Mod(216, t^2 + t + 1)*x^6 + Mod(270*t + 270, t^2 + t + 1)*x^5 + M od(-675*t, t^2 + t + 1)*x^4 + Mod(54, t^2 + t + 1)*x^3 + Mod(-972*t - 972, t ^2 + t + 1)*x^2 + Mod(648*t, t^2 + t + 1)*x 0 [] [-24] [14] [14] [[], 1] [-12] [[33, 2, 1, y, t - 1], [0, 1, 1, -1, -1, -2, -1, 4, -3, 1, -2]] [[38, 2, 1, y, t - 1], [0, 1, 1, -1, 1, -4, -1, 3, 1, -2, -4]] [[39, 2, 1, y, t - 1], [0, 1, 1, -1, -1, 2, -1, -4, -3, 1, 2]] [[34, 2, 1, y, t - 1], [0, 1, 1, -2, 1, 0, -2, -4, 1, 1, 0]] [[38, 2, 1, y, t - 1], [0, 1, -1, 1, 1, 0, -1, -1, -1, -2, 0]] [[11, 3, -11, y, t + 1], [0, 1, 0, -5, 4, -1, 0, 0, 0, 16, 0]] [[12, 3, -3, y, t + 1], [0, 1, 0, -3, 0, 0, 0, 2, 0, 9, 0]] [[16, 3, -4, y, t + 1], [0, 1, 0, 0, 0, -6, 0, 0, 0, 9, 0]] [[38, 2, 1], [0, 1, 2, 3, 4, -5, -8, 1, -7, -5, 7]] [[40, 2, 8], [0, 1, 2, 3, 4, -4, -6, -1, -10, -1, 2]] [[40, 2, 40], [0, 1, 2, 3, 4, -8, -6, -7, 6, -1, -2]] 3 [0, 1, 2, 3, 4, 5] 1 1 x^12 + 2*x^11 + 4*x^10 + 4*x^9 + 4*x^8 + 2*x^7 - 8*x^5 - 17*x^4 - 16*x^3 - 8 *x^2 + 16*x + 16 [2, 40, 20, 10, 8, 10, 4, 2] [[0, 0], [0, 0], [0, 0], [1, 1], [0, 0], [1, 1], [0, 0], [3, 3]] [[3, 3]] [[5, 5]] [[2, 2]] [[6, 6]] [[4, 4]] [[0, -1; 1, 0], [1, 0; 1, 1], [0, -1; 1, 2], [0, -1; 1, 3], [1, 0; 2, 1], [1 , 0; 4, 1]] [[-1, 1; -4, 3], 5] [[0, -1; 1, 0], [1, 0; 1, 1], [0, -1; 1, 2], [0, -1; 1, 3], [0, -1; 1, 4], [ 0, -1; 1, 5], [0, -1; 1, 6], [0, -1; 1, 7], [0, -1; 1, 8], [0, -1; 1, 9], [0 , -1; 1, 10], [0, -1; 1, 11], [0, -1; 1, 12], [0, -1; 1, 13], [0, -1; 1, 14] , [0, -1; 1, 15], [0, -1; 1, 16], [0, -1; 1, 17], [0, -1; 1, 18], [0, -1; 1, 19], [0, -1; 1, 20], [0, -1; 1, 21], [0, -1; 1, 22], [1, 0; 23, 1]] [0, 1, t^3 + t - 1, 0, -t^2 - 1, 0, 0, -t, -t^3 + t^2 - t + 1, -t^3, 0] [10] 1 [0, 1, 0, 0, t - 1, t - 1, 0, 0, 0, 0, 0] [6] 6 10 3 [[0, 0, 0; 0, 0, 1; 0, -2, 0], [0, 0, 0; 0, 0, -1; 0, 2, 0]] [12] [12] 1.4557628922687093224624220035988692874 10000.000000000000000000001237896015010 1.9689399767614335374830916735439946588 [-1, -60.000000000000000000000000000000000000, 240.0000000000000000000000000 0000000000*x^-1 + O(x^0)] [-1, -378.00000000000000000000000000000000000, -504.000000000000000000000000 00000000001*x^-1 + O(x^0)] 0.0050835121083932868604942901374387473226 [1620/691, 1, 9/14, 9/14, 1, 1620/691] 0.0074154209298961305890064277459002287248 [1, 25/48, 5/12, 25/48, 1] [270000/43867, 1, 75/364, 15/308, 0, -15/308, -75/364, -1, -270000/43867] -0.43965042620884602281482782769927016562 [1, 11/60, 1/24, 1/120, -1/120, -1/24, -11/60, -1] 1.3407636701883001534150257403529284807 - 0.09169347814648177113546620833059 8109326*I 3.1415926535897932384626433832795028842*x^-1 + O(x^0) 6.0268120396919401235462601927282855839 -125 0.037077104649480652945032138729501143624 x^9 - 25/4*x^7 + 21/2*x^5 - 25/4*x^3 + x -0.0059589649895782378538355644158109773247*I -x^10 + 691/36*x^8 - 691/12*x^6 + 691/12*x^4 - 691/36*x^2 + 1 1.0353620568043209223478168122251645932 E-6 [[4*x^9 - 25*x^7 + 42*x^5 - 25*x^3 + 4*x], [-36*x^10 + 691*x^8 - 2073*x^6 + 2073*x^4 - 691*x^2 + 36]] 4096/691 -691/4096 0.0039083456561245989852473854813821138618 [[0, 0, 0, 1, 1, 0, 0, -1, -1, 0, 0, 0], [2, 0, 10, 5, -5, -10, -10, -5, 5, 10, 0, -2]] 24/5 0.00036417018656710457295477514743042437729 0.00049190307191092718531081143004073999661 0.11655892584877731533791261543544162961*x + 0.03444188571581440474103881572 3936163594 0.0010890395470223995019083365452957049165 (-1.3193074979773231773661743756435007224 - 0.047852089878877215068678875180 019315601*I)*x + (0.55369913164712442515829589611646024395 + 0.1378560105941 2197357057720849196966097*I) 2.7088661559067092169467726322243151834*x^4 + 10.836695978514012215743285363 808371991*x^3 + 25.296899951502000988317286862612207702*x^2 + 41.46298040535 0911775127337547706905296*x + 36.867636355501616095737218901200295353 0.68152665510891372423521870628322971562 (-23183.009401346887106321839878457037987 + 10141.03198768851019292105517715 0961372*I)*x^4 + (36768.014815457253142184985512097903984 - 15843.6719474121 59422532108270646842468*I)*x^3 + (-21653.185479189712080795697797411393243 + 9383.4655370867720981173021992677296843*I)*x^2 + (5567.82157171174936497454 45772875483392 - 2529.1579539358590353355113445052491948*I)*x + (-519.290436 33066550788943723994543165137 + 267.97049309982710940044149283381067824*I) 0 -7.5483533093124615800482309272746852303 E-5*I*x^4 - 0.000325960230614461968 18766920427560516720*x^3 + 0.00053071372195845519650854381590103954823*I*x^2 + 0.00038639246231107851592899900012773026572*x - 0.00010622771569710146301 261452001204110433*I -159.28538078371628604726626677227374955*I*x^4 - 37.413371571061889095904737 694744717500*x^3 + 4.0605244955720177153253400611368714530*I*x^2 + 0.2512588 6591932202962812257047290475386*x - 0.00775320874361027409750103740193487763 58*I -1.0529510950884198373348191584869623207 E-9*I*x^4 - 4.379386751919803419760 5690442523726760 E-9*x^3 + 6.8404573572594165822427167063489824371 E-9*I*x^2 + 4.7561506807037037564779077168765701622 E-9*x - 1.24219231762730610575003 87331529713560 E-9*I [x^8 - 3*x^6 + 3*x^4 - x^2, 4*x^9 - 25*x^7 + 42*x^5 - 25*x^3 + 4*x, x^10 - 1 ] [x^8 - 3*x^6 + 3*x^4 - x^2, x^10 - 1] [4*x^9 - 25*x^7 + 42*x^5 - 25*x^3 + 4*x] [] [] [0.027225824587703356565506853506344987169 + 0.00514822234043271905508741860 26406789724*I, 0.027225198325372166661822373393404529520 + 0.005147912007675 1226908071569776979202336*I, 0.027225932797583197568370599484048729605 + 0.0 051482759611568609455954291851306519097*I, 0.0272255959592292808469822068846 79062876 + 0.0051481090481140853554894307306409710466*I] 1.5962359833107661839072302449298089223 E-51 0.00013137888540468962216778728275879264699 [-0.18301094584078802657926809374210173153 - 0.16521381176364244182058910079 630288304*I, 0.20268307954768284090024947338093896987 - 0.104259952378620313 78581599450677685109*I] [0, 1, y - 1, -2*y + 1, -y, 2*y - 2] [[[0, 0, 0, 1, y + 1, y, y + 1, 1, 1, -y, 1, 0, 0, -1, y, -1, -1, -y - 1, -y , -y - 1, -1, 0, 0, 0], [2*y + 6, 0, 22, 11*y + 11, 11*y, 11, -11*y, -11*y + 11, -11*y - 11, -11, 11*y - 11, -22, -22, 11*y - 11, -11, -11*y - 11, -11*y + 11, -11*y, 11, 11*y, 11*y + 11, 22, 0, -2*y - 6]], [[0, 0, 0, y + 1, 1, - y, 1, y + 1, y + 1, y, y + 1, 0, 0, -y - 1, -y, -y - 1, -y - 1, -1, y, -1, - y - 1, 0, 0, 0], [4*y + 6, 0, 22*y + 22, 11, -11*y, 11*y + 11, 11*y, 22*y + 11, -11, -11*y - 11, -22*y - 11, -22*y - 22, -22*y - 22, -22*y - 11, -11*y - 11, -11, 22*y + 11, 11*y, 11*y + 11, -11*y, 11, 22*y + 22, 0, -4*y - 6]]] [-48/55*y + 144/55, -192/55*y + 336/55] [[[x, x^2 + 2*x + 1, Mod(t, t^2 + t + 1)*x^2 + Mod(2*t + 1, t^2 + t + 1)*x + 2, Mod(-2*t, t^2 + t + 1)*x^2 + Mod(-t - 2, t^2 + t + 1)*x + Mod(t + 1, t^2 + t + 1), Mod(2*t, t^2 + t + 1)*x^2 + Mod(-t - 2, t^2 + t + 1)*x + Mod(-t - 1, t^2 + t + 1), Mod(-t, t^2 + t + 1)*x^2 + Mod(2*t + 1, t^2 + t + 1)*x - 2 , -x^2 + 2*x - 1, x], [Mod(47*t - 528, t^2 + t + 1)*x^2 + 3871, -3871*x^2 + 3871, Mod(-5293*t - 3792, t^2 + t + 1)*x^2 + Mod(2054*t - 3555, t^2 + t + 1) *x + Mod(2054*t + 316, t^2 + t + 1), Mod(1738*t + 2054, t^2 + t + 1)*x^2 + M od(-5609*t - 2054, t^2 + t + 1)*x + Mod(-1501*t - 5293, t^2 + t + 1), Mod(17 38*t + 2054, t^2 + t + 1)*x^2 + Mod(5609*t + 2054, t^2 + t + 1)*x + Mod(-150 1*t - 5293, t^2 + t + 1), Mod(-5293*t - 3792, t^2 + t + 1)*x^2 + Mod(-2054*t + 3555, t^2 + t + 1)*x + Mod(2054*t + 316, t^2 + t + 1), -3871*x^2 + 3871, -3871*x^2 + Mod(-47*t + 528, t^2 + t + 1)]], [0.0600760389692829045137557605 79766793352 + 0.0076557040727195254011353573267975581651*I, 3.80684584829863 11431726029948424993484 E-6 - 2.3063284341262122716050386345503232003 E-5*I, 3008/305809]] [0, 1/7] 0.012348139466200861797970297067148459977 [0, 1/2, 1/3, 1/4, 1/6, 1/12] [0, 1/2, 1/3, 1/4, 1/6, 1/12] [12, 3, 4, 3, 1, 1] [1, 0, 1, 1, 0, 1] [1, 0, 1, 1, 0, 1] [0, 1/4, 0, 0, 1/4, 0] [1/12, 1/6, 1/2, 2/3, 1/2, 2] [1/12, 1/6, 1/4, 2/3, 1/2, 1] 1 [3, 7, -3, y, t + 1, 3, "F_7(-3)"] [15, 7, -15, y, t + 1, 3, "F_7(-3, 5)"] [1, 4, 1, y, t - 1, 3, "E_4"] [11, 1, -11, y, t + 1, 3, "LIN([F_1(1, -11)], [2]~)", "F_1(1, -11)"] [4, 1/2, 1, y, t - 1, 3, "THETA(1)"] [4, 1/2, 1, y, t - 1, 1, "T_4(9)(THETA(1))", "THETA(1)"] [1, 12, 1, y, t - 1, 0, "DELTA"] [11, 2, 1, y, t - 1, 0, "ETAQUO([Vecsmall([1, 11]), Vecsmall([2, 2])], 1)"] [35, 2, 1, y, t - 1, 0, "ELL([0, 1, 1, 9, 1])"] [385, 2, 1, y, t - 1, -1, "LIN([ETAQUO([Vecsmall([1, 11]), Vecsmall([2, 2])] , 1), ELL([0, 1, 1, 9, 1])], [1, 1])", "ETAQUO([Vecsmall([1, 11]), Vecsmall( [2, 2])], 1)", "ELL([0, 1, 1, 9, 1])"] [3, 21, -3, y, t + 1, -1, "POW(F_7(-3), 3)", "F_7(-3)"] [15, 14, 5, y, t + 1, -1, "MUL(F_7(-3), F_7(-3, 5))", "F_7(-3)", "F_7(-3, 5) "] [1, 12, 1, y, t - 1, 0, "MULRC_2(E_4, E_4)", "E_4", "E_4"] [385, 2, 1, y, t - 1, -1, "LIN([ETAQUO([Vecsmall([1, 11]), Vecsmall([2, 2])] , 1), ELL([0, 1, 1, 9, 1])], [1, -1])", "ETAQUO([Vecsmall([1, 11]), Vecsmall ([2, 2])], 1)", "ELL([0, 1, 1, 9, 1])"] [15, 0, 5, y, t + 1, -1, "DIV(F_7(-3, 5), F_7(-3))", "F_7(-3, 5)", "F_7(-3)" ] [1, 12, 1, y, t - 1, -1, "SHIFT(DELTA, 1)", "DELTA"] [1, 6, 1, y, t - 1, -1, "DER^1(E_4)", "E_4"] [1, 12, 1, y, t - 1, -1, "DERE2^4(E_4)", "E_4"] [25, 4, 1, y, t - 1, -1, "TWIST(E_4, 5)", "E_4"] [1, 12, 1, y, t - 1, 0, "T_1(5)(DELTA)", "DELTA"] [3, 4, 1, y, t - 1, 3, "B(3)(E_4)", "E_4"] [2, 2, 1, y, t - 1, 3, "LIN([F_2(1), B(2)(F_2(1))], [1, -2])", "F_2(1)", "B( 2)(F_2(1))"] [3, 2, 1, y, t - 1, 3, "LIN([F_2(1), B(3)(F_2(1))], [1, -3])", "F_2(1)", "B( 3)(F_2(1))"] [6, 2, 1, y, t - 1, 3, "LIN([F_2(1), B(6)(F_2(1))], [1, -6])", "F_2(1)", "B( 6)(F_2(1))"] [1, 4, 1, y, t - 1, 3, "F_4(1, 1)"] [2, 4, 1, y, t - 1, 3, "B(2)(F_4(1, 1))", "F_4(1, 1)"] [3, 4, 1, y, t - 1, 3, "B(3)(F_4(1, 1))", "F_4(1, 1)"] [4, 4, 1, y, t - 1, 3, "B(4)(F_4(1, 1))", "F_4(1, 1)"] [6, 4, 1, y, t - 1, 3, "B(6)(F_4(1, 1))", "F_4(1, 1)"] [8, 4, 1, y, t - 1, 3, "B(8)(F_4(1, 1))", "F_4(1, 1)"] [12, 4, 1, y, t - 1, 3, "B(12)(F_4(1, 1))", "F_4(1, 1)"] [24, 4, 1, y, t - 1, 3, "B(24)(F_4(1, 1))", "F_4(1, 1)"] [6, 4, 1, y, t - 1, 2, "TR^new([6, 4, 1, y, t - 1])"] [12, 4, 1, y, t - 1, 2, "B(2)(TR^new([6, 4, 1, y, t - 1]))", "TR^new([6, 4, 1, y, t - 1])"] [24, 4, 1, y, t - 1, 1, "B(4)(TR^new([6, 4, 1, y, t - 1]))", "TR^new([6, 4, 1, y, t - 1])"] [8, 4, 1, y, t - 1, 2, "TR^new([8, 4, 1, y, t - 1])"] [24, 4, 1, y, t - 1, 1, "B(3)(TR^new([8, 4, 1, y, t - 1]))", "TR^new([8, 4, 1, y, t - 1])"] [12, 4, 1, y, t - 1, 2, "TR^new([12, 4, 1, y, t - 1])"] [24, 4, 1, y, t - 1, 1, "B(2)(TR^new([12, 4, 1, y, t - 1]))", "TR^new([12, 4 , 1, y, t - 1])"] [24, 4, 1, y, t - 1, 0, "TR^new([24, 4, 1, y, t - 1])"] [1, 2, 3, 4, 6, 8, 12, 24, 6, 12, 24, 8, 24, 12, 24, 24] [23, 1, -23, y, t + 1, 1, "LIN([DIH(-23, [1, 0; 0, 1], [3], [1])], [1]~)", " DIH(-23, [1, 0; 0, 1], [3], [1])"] 0.035149946790370230814006345508484787440 23 []~ [[4, 1, -4], 4, [0.25000000000000000000000000000000000000, 1, 1, 0]] [[4, 3/2, 1], 4, [1, 6, 12, 8]] [[11, 2, 1], 1, [0, 1, -2, -1, 2, 1]] -3 [-3, -39] [1 24] [ 1 1] [23 1] [ 1 12] [193 12] 0 [1 -24] 0 [1 480] [Mod(575, 576), 1] [Mod(593, 900), 1] [Mod(575, 1152), 1] [Mod(1151, 1152), 1] 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 2 2 2 1 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 3 3 4 3 2 3 3 4 5 5 5 5 3 3 4 4 6 6 4 2 6 7 4 4 5 5 5 5 6 6 1 2 2 3 3 4 3 2 3 3 4 5 5 5 5 4 4 4 4 6 6 4 3 6 8 5 5 6 6 6 6 6 6 1 1 1 2 3 3 2 3 3 3 3 4 4 4 4 2 2 4 5 6 4 7 7 6 6 6 6 6 6 2 3 3 4 4 6 4 2 4 4 4 6 6 6 6 4 4 4 4 8 8 4 2 8 8 4 4 6 6 6 6 6 6 2 3 3 5 5 6 5 4 7 7 6 9 9 9 9 8 8 8 8 10 10 8 7 14 12 11 11 12 12 12 12 12 12 1 1 3 3 2 3 4 5 5 6 7 7 7 7 8 8 8 8 6 6 8 9 10 12 13 13 12 12 12 12 12 12 2 3 3 4 4 6 4 2 4 4 4 6 6 6 6 4 4 4 4 8 8 4 2 8 8 4 4 6 6 6 6 6 6 2 4 4 7 7 8 7 6 9 9 10 13 13 13 13 12 12 12 12 14 14 12 11 18 20 17 17 18 18 18 18 18 18 0 2 6 13 22 28 48 64 74 96 2 6 8 14 16 24 24 32 32 48 2 8 14 27 38 52 72 96 106 144 [[[0, 1, 0, 0, -4, 0, -6, 8, 0, 9, 4, 0, 12, -20, 0, -24], [0, 0, 1, 0, -2, -4, 3, 2, 4, 0, 0, 2, -6, 0, -8, -6], [0, 0, 0, 1, -2, 0, 0, 2, 0, 0, 0, 0, -2, 0, 0, -6]], [[0, 1, 0, 0, -2, -6, 0, 0, 12, 9, 0, 0, -18, 12, 0, 0], [0, 0, 1, 0, -2, -2, -3, 4, 8, 6, -2, -16, -6, 4, 14, 12], [0, 0, 0, 1, 0, -4, -2, 4, 8, 4, -8, -12, -8, 8, 24, 8]]] [ 0 0 0] [ 1 0 0] [ 0 1 0] [ 0 0 1] [-2 0 0] [ 0 0 0] [0 0 0 0] [1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1] [0 0 -1 0] [0, 1, 0, 0, 0, 0, 0, -3, -2, 1, 0, -6, 0, 0, 6, 12] [0, 0, 1, 0, 0, 0, 0, -3, -4, 4, 0, 0, 0, 0, -1, 2] [0, 0, 0, 1, 0, -1, 0, -1, 0, 0, -2, 0, 2, 1, 2, 0] [0, 0, 0, 0, 1, 0, 0, -1, -3, 2, 0, -2, 0, 0, 2, 4] [2]~ [0, 2]~ [Mod(-1/49*t^11 + 1/49*t^10 + 1/98*t^9 - 5/196*t^8 - 1/196*t^7 - 5/196*t^4 + 5/196*t^3 - 1/196*t^2 - 1/196*t + 1/49, t^12 - t^11 + t^9 - t^8 + t^6 - t^4 + t^3 - t + 1), Mod(-6/49*t^11 + 13/196*t^10 - 13/196*t^8 + 2/49*t^7 + 13/1 96*t^6 - 11/196*t^5 - 11/196*t^4 + 6/49*t^3 - 11/196*t^2 - 13/196*t + 4/49, t^12 - t^11 + t^9 - t^8 + t^6 - t^4 + t^3 - t + 1), Mod(1/196*t^11 - 5/196*t ^10 - 1/98*t^9 + 3/98*t^8 - 5/196*t^7 - 1/196*t^6 + 3/196*t^5 + 1/196*t^4 - 1/98*t^3 + 1/49*t^2 + 1/98*t - 1/98, t^12 - t^11 + t^9 - t^8 + t^6 - t^4 + t ^3 - t + 1), Mod(9/196*t^10 - 15/196*t^9 - 3/49*t^8 - 3/196*t^6 - 3/49*t^5 + 15/196*t^4 + 3/196*t^3 - 15/196*t^2 - 3/196, t^12 - t^11 + t^9 - t^8 + t^6 - t^4 + t^3 - t + 1), Mod(15/196*t^11 - 15/196*t^9 + 9/98*t^8 - 3/49*t^7 - 3 /49*t^6 + 15/196*t^5 - 3/49*t^3 + 3/49*t^2 + 9/196*t - 27/196, t^12 - t^11 + t^9 - t^8 + t^6 - t^4 + t^3 - t + 1), Mod(3/49*t^11 + 3/98*t^10 - 15/196*t^ 9 + 3/49*t^8 + 3/196*t^7 - 3/98*t^6 - 3/196*t^5 + 3/196*t^4 - 9/196*t^3 - 3/ 98*t^2 + 3/196*t + 3/196, t^12 - t^11 + t^9 - t^8 + t^6 - t^4 + t^3 - t + 1) ] [Mod(0, t^2 + t + 1) Mod(0, t^2 + t + 1) Mod(0, t^2 + t + 1) Mod(1, t^2 + t + 1)] [Mod(-2, t^2 + t + 1) Mod(-2*t - 2, t^2 + t + 1) Mod(0, t^2 + t + 1) Mod(0, t^2 + t + 1)] [Mod(2*t + 4, t^2 + t + 1) Mod(4*t + 2, t^2 + t + 1) Mod(4*t + 4, t^2 + t + 1) Mod(-t + 1, t^2 + t + 1)] [Mod(-8*t, t^2 + t + 1) Mod(4, t^2 + t + 1) Mod(-4*t + 4, t^2 + t + 1) Mod(- 4*t - 4, t^2 + t + 1)] [0, 1, 0, 0, 0, -t - 2, 0, 0, -2, 4*t, 0, 0, 2*t + 4, -4*t - 2, 0, 0] [0, 0, 1, 0, 0, 0, t - 1, 0, -2*t - 2, -2, -t - 2, 0, 4*t + 2, -2*t + 2, -2* t + 1, 4*t + 4] [0, 0, 0, 1, 0, -2*t - 2, 0, 3*t + 2, 0, 2*t - 2, -2, -2*t - 1, 4*t + 4, -2* t, -6*t - 4, t + 2] [0, 0, 0, 0, 1, t - 1, -t - 2, -2*t + 1, 0, t + 1, 4*t + 2, 1, -t + 1, -t - 2, -t - 3, t] [4, 1, -4, y, t + 1] [1, 0, 0, 2, 0, 0, 0, 6, 6, 0, 0, 0, 8, 0, 0, 6] [0, 1, 0, -1, 1, 2, 4, -3, -3, 5, 2, 4, -4, 0, 8, -3] [0, 0, 1, 1, 0, 1, 0, 1, 2, 0, 1, 0, 2, 2, 0, 1] 2 [1, 12, 1, y, t - 1] [4, 6, 1, y, t - 1] [9, 4, 1, y, t - 1] [16, 3, -4, y, t + 1] [36, 2, 1, y, t - 1] [144, 1, -4, y, t + 1] [576, 1/2, 12, y, t + 1] [64, 3/2, 1, y, t - 1] [0, 1, 0, 0, 0, 0, 0, 0, -3, 0]~ [[0, 64, [1, 0; 0, 1]], [0, -0.031250000000000000000000000000000000000 - 0.0 31250000000000000000000000000000000000*I, 0, 0, 0, 0, 0, 0, 0, 0.09375000000 0000000000000000000000000000 + 0.093750000000000000000000000000000000000*I, 0]] [Mod(0, t^2 + 1), Mod(-1/32*t - 1/32, t^2 + 1), Mod(0, t^2 + 1), Mod(0, t^2 + 1), Mod(0, t^2 + 1), Mod(0, t^2 + 1), Mod(0, t^2 + 1), Mod(0, t^2 + 1), Mo d(0, t^2 + 1), Mod(3/32*t + 3/32, t^2 + 1), Mod(0, t^2 + 1)] [[0, 16, [1, 0; 0, 1]], [0, 0.10393370153781815463484854720223821959 + 0.069 446279127450278092853851743566609297*I, 0, 0, 0, 0, 0, 0, 0, -0.208338837382 35083427856155523069982789 + 0.31180110461345446390454564160671465878*I, 0]] [Mod(0, t^16 + 1), Mod(1/8*t^3, t^16 + 1), Mod(0, t^16 + 1), Mod(0, t^16 + 1 ), Mod(0, t^16 + 1), Mod(0, t^16 + 1), Mod(0, t^16 + 1), Mod(0, t^16 + 1), M od(0, t^16 + 1), Mod(3/8*t^11, t^16 + 1), Mod(0, t^16 + 1)] 0.0018674427317079888144293843310939736875 [Mod(-t, t^2 + 1), Mod(-2*t, t^2 + 1), Mod(0, t^2 + 1)] [Mod(2*t, t^2 + 1), Mod(0, t^2 + 1), Mod(2*t, t^2 + 1), Mod(0, t^2 + 1)] [2, 0, 2, 0] [Mod(1/2*t + 1/2, t^2 + 1), Mod(t + 1, t^2 + 1), Mod(0, t^2 + 1)] [Mod(-1/2*t + 1/2, t^2 + 1), Mod(-t + 1, t^2 + 1), Mod(0, t^2 + 1)] [Mod(1/2*t + 1/2, t^2 + 1), Mod(t - 1, t^2 + 1), Mod(0, t^2 + 1)] [1, 2, 0] [36, 5/2, 1, y, t - 1] 2 [-1 0 0 2 0 0] [ 0 0 0 0 1 0] [9, 4, 1, y, t - 1] [9, 4, 1, y, t - 1] [0 -1 0 0 2 0 0 0 0 0 0 0 0 -6 0 0 8 0 0 0 0] [0 0 0 0 0 1 0 0 -2 0 0 0 0 0 0 0 0 1 0 0 2] [-3 0 5/2 7/2] [ 1 -1/2 -7 -7] [ 1 1/2 0 -3] [ 0 0 5/2 5/2] [[1, 1], [2, 1]] [[2, 4; 0, 0; 0, 0; 5, 7; -14, -14; 0, 0; 0, 0; -5, -5; 0, -6; 0, 0; 0, 0; 1 5, 15; 0, 0; 0, 0], [1, 1; 0, 0; 0, 0; 1, 4; 0, -14; 0, 0; 0, 0; 0, -5; -3, 3; 0, 0; 0, 0; 0, 15; 0, 0; 0, 0]] [Mat(Mod(1, t^4 - t^2 + 1)), [1; 0], [[1, 1]]] [12, 12, 12, 12, 12] 4 0.0018371115455019092538663990739211073913 3.7500000000000000000000000000000000004 [4, 1/2, 1, y, t - 1] [16, 1/2, 1, y, t - 1] [1, -2]~ "F_4(-3, -4)" "F_3(5, -7)" "DERE2^3(MUL(F_4(-3, -4), F_3(5, -7)))" "DELTA" "E_2" "T_1(3)(E_2)" ["S_4^new(G_0(37, 1))", "S_4(G_0(37, 1))", "S_4^old(G_0(37, 1))", "E_4(G_0(3 7, 1))", "M_4(G_0(37, 1))"] ["S_3/2(G_0(16, 1))", "M_3/2(G_0(16, 1))"] ["F_4(-3, -4)", "F_3(1, -3)"] 1/72 [1/4, 6, 6, 24, 6, 36, 24, 48, 6, 78, 36] [1/24, 10, 90, 280, 730, 1260, 2520, 3440, 5850, 7570, 11340] [10]~ [0, 1, 0, 0, 0, -2, 0, 0, 0, -3, 0, 0, 0, 6, 0, 0, 0, 2, 0, 0, 0] -125832074732008 -3268080304426/13 [691/32760, 0, -2017/252, 0, -361, 0, -3362, 0, -4130785/252, 0, -278854/5, 0, -152166, 0, -355688, 0] [-1/12, 9375/2, 14055] [-1/12, 1702, 0] [-1/12, 0, 0, 1/3, 1/2, 0, 0, 1, 1, 0, 0, 1, 4/3, 0, 0, 2] [1/120, -1/12, 0, 0, -7/12, -2/5, 0, 0, -1, -25/12, 0, 0, -2, -2, 0, 0] [-1/252, 0, 0, -2/9, -1/2, 0, 0, -16/7, -3, 0, 0, -6, -74/9, 0, 0, -16] [1/240, 1/120, 0, 0, 121/120, 2, 0, 0, 11, 2161/120, 0, 0, 46, 58, 0, 0] [-1/132, 0, 0, 2/3, 5/2, 0, 0, 32, 57, 0, 0, 2550/11, 1058/3, 0, 0, 992] [691/32760, -1/252, 0, 0, -2017/252, -134/5, 0, 0, -361, -176905/252, 0, 0, -3362, -66926/13, 0, 0] [-1/12, 0, 0, -14/3, -61/2, 0, 0, -1168, -2763, 0, 0, -21726, -115598/3, 0, 0, -165616] [-43867/14364, 0, 0, 1618/27, 1385/2, 0, 0, 565184/7, 250737, 0, 0, 3749250, 212490322/27, 0, 0, 52548032] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [-1/12, 1/2, 1, 4/3, 3/2, 2, 2, 2, 3, 5/2, 2, 4, 10/3, 2, 4, 4] [-1/12, 1/2, 1, 4/3, 3/2, 2, 2, 2, 3, 5/2, 2, 4, 10/3, 2, 4, 4] [-1/3, 0, 0, 4/3, 2, 0, 0, 4, 4, 0, 0, 4, 16/3, 0, 0, 8] [-1/12, 0, 0, 4/3, 5/2, 0, 0, 5, 3, 0, 0, 3, 16/3, 0, 0, 8] [-1/2, 0, 0, 2, 3, 0, 0, 6, 6, 0, 0, 6, 8, 0, 0, 12] [-10/3, 0, 0, 40/3, 20, 0, 0, 40, 40, 0, 0, 40, 160/3, 0, 0, 80] [-1/2, 0, 0, 2, 3, 0, 0, 6, 6, 0, 0, 6, 8, 0, 0, 12] [1, 2, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0] [4/3, 8/3, 0, 0, 8/3, 0, 0, 0, 0, 8/3, 0, 0, 0, 0, 0, 0] [0, -4, -8, 0, 0, 0, 16, 0, 0, 28, 16, 0, 0, 0, -32, 0] 4.7568284600108842668699998822419036612 + 4.75682846001088426686999988224190 36612*I 0 [16 0 0] [ 0 16 0] [ 0 0 16] 0.0061538599016729274239549224845781815123 0 +oo 0 [1, 24, 324, 3200, 25650, 176256, 1073720] 0.0067751374633700320670755869090304807506 [0, 1, 0, 28, 0, 126, 0, 344, 0, 757, 0, 1332, 0, 2198, 0, 3528] 1/13824000 [ "Factors" 50000 18 1000000000] [ "Divisors" 50000 5 1000000000] [ "H" 50000 3 200000000] ["CorediscF" 122572 3 200000000] [ "Dihedral" 1000 2 1099] *** at top-level: mftobasis(mf0,L[1]) *** ^------------------- *** mftobasis: domain error in mftobasis: form does not belong to space *** at top-level: mfdim([4,1/2],0) *** ^---------------- *** mfdim: incorrect type in half-integral weight [new/old spaces] (t_INT). *** at top-level: mfdim([4,1/2],2) *** ^---------------- *** mfdim: incorrect type in half-integral weight [new/old spaces] (t_INT). *** at top-level: mfdim([4,1/2],5) *** ^---------------- *** mfdim: incorrect type in half-integral weight [incorrect space] (t_INT). *** at top-level: mfeisenstein(2,1.0) *** ^------------------- *** mfeisenstein: incorrect type in znchar (t_REAL). *** at top-level: mfeisenstein(2,[0,0]) *** ^--------------------- *** mfeisenstein: incorrect type in checkNF [chi] (t_VEC). *** at top-level: mfeisenstein(6,Mod(7,9),Mod(4,9)) *** ^--------------------------------- *** mfeisenstein: sorry, mfeisenstein for these characters is not yet implemented. *** at top-level: mfinit([1,1.0]) *** ^--------------- *** mfinit: incorrect type in checkNF [k] (t_VEC). *** at top-level: ...nit([14,6,Mod(9,14)],0));mfmul(L[1],L[2]) *** ^---------------- *** mfmul: incorrect type in mfsamefield [different fields] (t_VEC). *** at top-level: mfcuspwidth(0,0) *** ^---------------- *** mfcuspwidth: domain error in mfcuspwidth: N <= 0 *** at top-level: mfparams(mfadd(F2,F3)) *** ^------------- *** in function mfadd: mflinear([F,G],[1,1]) *** ^--------------------- *** mflinear: incorrect type in mflinear [different characters] (t_VEC). *** at top-level: mfparams(mfadd(F4,F6)) *** ^------------- *** in function mfadd: mflinear([F,G],[1,1]) *** ^--------------------- *** mflinear: incorrect type in mflinear [different weights] (t_VEC). *** at top-level: mfinit([23,1,Mod(22,45)],0) *** ^--------------------------- *** mfinit: incorrect type in checkNF [chi] (t_VEC). *** at top-level: mfinit([23,2,Mod(22,45)],0) *** ^--------------------------- *** mfinit: incorrect type in checkNF [chi] (t_VEC). *** at top-level: mfinit([7,1,-7],2) *** ^------------------ *** mfinit: sorry, mfinit in weight 1 for old space is not yet implemented. *** at top-level: mfinit([7,1,-7],5) *** ^------------------ *** mfinit: invalid flag in mfinit. *** at top-level: mfinit([1,2],5) *** ^--------------- *** mfinit: invalid flag in mfinit. *** at top-level: mfgaloistype([11,1,Mod(2,11)],mfeisenstein(1,1 *** ^---------------------------------------------- *** mfgaloistype: domain error in mfgaloistype: form not a cuspidal eigenform *** at top-level: mfdiv(D,mfpow(D,2)) *** ^------------------- *** mfdiv: domain error in mfdiv: ord(G) > ord(F) *** at top-level: mfeval(mfD,D,-I) *** ^---------------- *** mfeval: domain error in mfeval: imag(tau) <= 0 *** at top-level: mfslashexpansion(mfD,D,[1,2;3,4],1,1) *** ^------------------------------------- *** mfslashexpansion: incorrect type in GL2toSL2 (t_MAT). *** at top-level: mftonew(mfD,1) *** ^-------------- *** mftonew: incorrect type in mftobasis (t_INT). *** at top-level: T=mftraceform([96,6],4) *** ^--------------------- *** mftraceform: domain error in mftraceform: space = 4 *** at top-level: mfshimura(mfinit(T5),T5,4) *** ^-------------------------- *** mfshimura: incorrect type in mfshimura [t] (t_INT). *** at top-level: mftonew(mf,E4) *** ^-------------- *** mftonew: incorrect type in mftonew [not a full or cuspidal space] (t_VEC). *** at top-level: mffields(mf) *** ^------------ *** mffields: incorrect type in mfsplit [space does not contain newspace] (t_VEC). *** at top-level: mfdiv(1,mfTheta()) *** ^------------------ *** mfdiv: incorrect type in mfdiv (t_INT). *** at top-level: mfdiv(D,mftraceform([1,3])) *** ^--------------------------- *** mfdiv: domain error in mfdiv: ord(G) > ord(F) *** at top-level: mfcosets(1.) *** ^------------ *** mfcosets: incorrect type in mfcosets (t_REAL). *** at top-level: ...([1,0]);F=mfbasis(mf)[1];mfsymbol(mf,F) *** ^-------------- *** mfsymbol: incorrect type in mfsymbol [k <= 0] (t_VEC). *** at top-level: mfmanin(FSbug) *** ^-------------- *** mfmanin: incorrect type in mfmanin [need integral k > 1] (t_VEC). *** at top-level: mfsymboleval(FSbug,[0,1]) *** ^------------------------- *** mfsymboleval: incorrect type in mfsymboleval [need integral k > 1] (t_VEC). *** at top-level: mfgaloistype([4,1,-4],x) *** ^------------------------ *** mfgaloistype: incorrect type in mfgaloistype (t_POL). *** at top-level: mfdiv(E,f) *** ^---------- *** mfdiv: sorry, changing cyclotomic fields in mf is not yet implemented. *** at top-level: ...,0);[F]=mfeigenbasis(mf);mfpow(F,3) *** ^---------- *** mfpow: sorry, changing cyclotomic fields in mf is not yet implemented. *** at top-level: mffromqf(Mat(2),x*y) *** ^-------------------- *** mffromqf: too many variables in mffromqf. *** at top-level: mffromqf(2*matid(2),x*y^2) *** ^-------------------------- *** mffromqf: incorrect type in mffromqf [not a spherical t_POL] (t_POL). [0, 1, 2, 0, 2, -1, 0, -2, 0, 0, -2, -1, 0, 4, -4, 0, -4, 2, 0, 0, -2] [0, 1, 2, 0, 2, -1, 0, -2, 0, 0, -2, -1, 0, 4, -4, 0, -4, 2, 0, 0, -2] Mod(1/24, t^2 + t + 1) 1 Total time spent: 11255 pari-2.17.2/src/test/32/polyser0000644000175000017500000001426014760123736014612 0ustar billbill echo = 1 ? apol=y^3+5*y+1 y^3 + 5*y + 1 ? deriv((x+y)^5,y) 5*x^4 + 20*y*x^3 + 30*y^2*x^2 + 20*y^3*x + 5*y^4 ? ((x+y)^5)' 5*x^4 + 20*y*x^3 + 30*y^2*x^2 + 20*y^3*x + 5*y^4 ? dz=vector(30,k,1);dd=vector(30,k,k==1);dm=dirdiv(dd,dz) [1, -1, -1, 0, -1, 1, -1, 0, 0, 1, -1, 0, -1, 1, 1, 0, -1, 0, -1, 0, 1, 1, - 1, 0, 0, 1, 0, 0, -1, -1] ? direuler(s=1,40,1+s*X+s^2*X) [1, 6, 12, 0, 30, 72, 56, 0, 0, 180, 132, 0, 182, 336, 360, 0, 306, 0, 380, 0, 672, 792, 552, 0, 0, 1092, 0, 0, 870, 2160, 992, 0, 1584, 1836, 1680, 0, 1406, 2280, 2184, 0] ? dirmul(abs(dm),dz) [1, 2, 2, 2, 2, 4, 2, 2, 2, 4, 2, 4, 2, 4, 4, 2, 2, 4, 2, 4, 4, 4, 2, 4, 2, 4, 2, 4, 2, 8] ? zz=yy;yy=xx;eval(zz) xx ? factorpadic(apol,7,8) [(1 + O(7^8))*y + (6 + 2*7^2 + 2*7^3 + 3*7^4 + 2*7^5 + 6*7^6 + O(7^8)) 1] [(1 + O(7^8))*y^2 + (1 + 6*7 + 4*7^2 + 4*7^3 + 3*7^4 + 4*7^5 + 6*7^7 + O(7^8 ))*y + (6 + 5*7 + 3*7^2 + 6*7^3 + 7^4 + 3*7^5 + 2*7^6 + 5*7^7 + O(7^8)) 1] ? intformal(sin(x)) 1/2*x^2 - 1/24*x^4 + 1/720*x^6 - 1/40320*x^8 + 1/3628800*x^10 - 1/479001600* x^12 + 1/87178291200*x^14 - 1/20922789888000*x^16 + O(x^18) ? intformal((-x^2-2*a*x+8*a)/(x^4-14*x^3+(2*a+49)*x^2-14*a*x+a^2)) (x + a)/(x^2 - 7*x + a) ? newtonpoly(x^4+3*x^3+27*x^2+9*x+81,3) [2, 2/3, 2/3, 2/3] ? padicappr(apol,1+O(7^8)) [1 + 6*7 + 4*7^2 + 4*7^3 + 3*7^4 + 4*7^5 + 6*7^7 + O(7^8)]~ ? padicappr(x^3+5*x+1,Mod(x*(1+O(7^8)),x^2+x-1)) [Mod((1 + 3*7 + 3*7^2 + 4*7^3 + 4*7^4 + 4*7^5 + 2*7^6 + 3*7^7 + O(7^8))*x + (2*7 + 6*7^2 + 6*7^3 + 3*7^4 + 3*7^5 + 4*7^6 + 5*7^7 + O(7^8)), x^2 + x - 1) ]~ ? Pol(sin(x)) -1/1307674368000*x^15 + 1/6227020800*x^13 - 1/39916800*x^11 + 1/362880*x^9 - 1/5040*x^7 + 1/120*x^5 - 1/6*x^3 + x ? Pol([1,2,3,4,5]) x^4 + 2*x^3 + 3*x^2 + 4*x + 5 ? Polrev([1,2,3,4,5]) 5*x^4 + 4*x^3 + 3*x^2 + 2*x + 1 ? polcoeff(sin(x),7) -1/5040 ? polcyclo(105) x^48 + x^47 + x^46 - x^43 - x^42 - 2*x^41 - x^40 - x^39 + x^36 + x^35 + x^34 + x^33 + x^32 + x^31 - x^28 - x^26 - x^24 - x^22 - x^20 + x^17 + x^16 + x^1 5 + x^14 + x^13 + x^12 - x^9 - x^8 - 2*x^7 - x^6 - x^5 + x^2 + x + 1 ? pcy=polcyclo(405) x^216 - x^189 + x^135 - x^108 + x^81 - x^27 + 1 ? pcy*pcy x^432 - 2*x^405 + x^378 + 2*x^351 - 4*x^324 + 4*x^297 - x^270 - 4*x^243 + 7* x^216 - 4*x^189 - x^162 + 4*x^135 - 4*x^108 + 2*x^81 + x^54 - 2*x^27 + 1 ? poldegree(x^3/(x-1)) 2 ? poldisc(x^3+4*x+12) -4144 ? poldiscreduced(x^3+4*x+12) [1036, 4, 1] ? polinterpolate([0,2,3],[0,4,9],5) 25 ? polisirreducible(x^5+3*x^3+5*x^2+15) 0 ? pollegendre(10) 46189/256*x^10 - 109395/256*x^8 + 45045/128*x^6 - 15015/128*x^4 + 3465/256*x ^2 - 63/256 ? zpol=0.3+pollegendre(10) 46189/256*x^10 - 109395/256*x^8 + 45045/128*x^6 - 15015/128*x^4 + 3465/256*x ^2 + 0.053906250000000000000000000000000000001 ? polrecip(3*x^7-5*x^3+6*x-9) -9*x^7 + 6*x^6 - 5*x^4 + 3 ? polresultant(x^3-1,x^3+1) 8 ? polresultant(x^3-1.,x^3+1.,,1) 8.0000000000000000000000000000000000000 ? polroots(x^5-5*x^2-5*x-5) [2.0509134529831982130058170163696514536 + 0.E-38*I, -0.67063790319207539268 663382582902335603 - 0.84813118358634026680538906224199030918*I, -0.67063790 319207539268663382582902335603 + 0.84813118358634026680538906224199030918*I, -0.35481882329952371381627468235580237078 - 1.39980287391035466982975228340 62081965*I, -0.35481882329952371381627468235580237078 + 1.399802873910354669 8297522834062081965*I]~ ? polroots(x^4-1000000000000000000000) [-177827.94100389228012254211951926848447 + 0.E-38*I, 177827.941003892280122 54211951926848447 + 0.E-38*I, 0.E-38 - 177827.941003892280122542119519268484 47*I, 0.E-38 + 177827.94100389228012254211951926848447*I]~ ? polrootsmod(x^16-1,41) [Mod(1, 41), Mod(3, 41), Mod(9, 41), Mod(14, 41), Mod(27, 41), Mod(32, 41), Mod(38, 41), Mod(40, 41)]~ ? polrootspadic(x^4+1,41,6) [3 + 22*41 + 27*41^2 + 15*41^3 + 27*41^4 + 33*41^5 + O(41^6), 14 + 20*41 + 2 5*41^2 + 24*41^3 + 4*41^4 + 18*41^5 + O(41^6), 27 + 20*41 + 15*41^2 + 16*41^ 3 + 36*41^4 + 22*41^5 + O(41^6), 38 + 18*41 + 13*41^2 + 25*41^3 + 13*41^4 + 7*41^5 + O(41^6)]~ ? polsturm(zpol) 4 ? polsturm(zpol,0.91,1) 1 ? polsylvestermatrix(a2*x^2+a1*x+a0,b1*x+b0) [a2 b1 0] [a1 b0 b1] [a0 0 b0] ? polsym(x^17-1,17) [17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17]~ ? poltchebi(10) 512*x^10 - 1280*x^8 + 1120*x^6 - 400*x^4 + 50*x^2 - 1 ? polzagier(6,3) 4608*x^6 - 13824*x^5 + 46144/3*x^4 - 23168/3*x^3 + 5032/3*x^2 - 120*x + 1 ? serconvol(sin(x),x*cos(x)) x + 1/12*x^3 + 1/2880*x^5 + 1/3628800*x^7 + 1/14631321600*x^9 + 1/1448500838 40000*x^11 + 1/2982752926433280000*x^13 + 1/114000816848279961600000*x^15 + O(x^17) ? serlaplace(x*exp(x*y)/(exp(x)-1)) 1 + (y - 1/2)*x + (y^2 - y + 1/6)*x^2 + (y^3 - 3/2*y^2 + 1/2*y)*x^3 + (y^4 - 2*y^3 + y^2 - 1/30)*x^4 + (y^5 - 5/2*y^4 + 5/3*y^3 - 1/6*y)*x^5 + (y^6 - 3* y^5 + 5/2*y^4 - 1/2*y^2 + 1/42)*x^6 + (y^7 - 7/2*y^6 + 7/2*y^5 - 7/6*y^3 + 1 /6*y)*x^7 + (y^8 - 4*y^7 + 14/3*y^6 - 7/3*y^4 + 2/3*y^2 - 1/30)*x^8 + (y^9 - 9/2*y^8 + 6*y^7 - 21/5*y^5 + 2*y^3 - 3/10*y)*x^9 + (y^10 - 5*y^9 + 15/2*y^8 - 7*y^6 + 5*y^4 - 3/2*y^2 + 5/66)*x^10 + (y^11 - 11/2*y^10 + 55/6*y^9 - 11* y^7 + 11*y^5 - 11/2*y^3 + 5/6*y)*x^11 + (y^12 - 6*y^11 + 11*y^10 - 33/2*y^8 + 22*y^6 - 33/2*y^4 + 5*y^2 - 691/2730)*x^12 + (y^13 - 13/2*y^12 + 13*y^11 - 143/6*y^9 + 286/7*y^7 - 429/10*y^5 + 65/3*y^3 - 691/210*y)*x^13 + (y^14 - 7 *y^13 + 91/6*y^12 - 1001/30*y^10 + 143/2*y^8 - 1001/10*y^6 + 455/6*y^4 - 691 /30*y^2 + 7/6)*x^14 + (y^15 - 15/2*y^14 + 35/2*y^13 - 91/2*y^11 + 715/6*y^9 - 429/2*y^7 + 455/2*y^5 - 691/6*y^3 + 35/2*y)*x^15 + O(x^16) ? serreverse(tan(x)) x - 1/3*x^3 + 1/5*x^5 - 1/7*x^7 + 1/9*x^9 - 1/11*x^11 + 1/13*x^13 - 1/15*x^1 5 + O(x^17) ? subst(sin(x),x,y) y - 1/6*y^3 + 1/120*y^5 - 1/5040*y^7 + 1/362880*y^9 - 1/39916800*y^11 + 1/62 27020800*y^13 - 1/1307674368000*y^15 + O(y^17) ? subst(sin(x),x,x+x^2) x + x^2 - 1/6*x^3 - 1/2*x^4 - 59/120*x^5 - 1/8*x^6 + 419/5040*x^7 + 59/720*x ^8 + 13609/362880*x^9 + 19/13440*x^10 - 273241/39916800*x^11 - 14281/3628800 *x^12 - 6495059/6227020800*x^13 + 69301/479001600*x^14 + 26537089/1188794880 00*x^15 + 1528727/17435658240*x^16 + O(x^17) ? taylor(y/(x-y),y) (O(y^16)*x^15 + y*x^14 + y^2*x^13 + y^3*x^12 + y^4*x^11 + y^5*x^10 + y^6*x^9 + y^7*x^8 + y^8*x^7 + y^9*x^6 + y^10*x^5 + y^11*x^4 + y^12*x^3 + y^13*x^2 + y^14*x + y^15)/x^15 ? variable(name^4-other) name ? if(getheap()!=HEAP,getheap()) ? print("Total time spent: ",gettime); Total time spent: 5 pari-2.17.2/src/test/32/number0000644000175000017500000001357714676526175014431 0ustar billbill echo = 1 ? addprimes([nextprime(10^9),nextprime(10^10)]) [1000000007, 10000000019] ? localbitprec(1024);bestappr(Pi,10000) 355/113 ? gcdext(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(factormod(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) ? qfbcomp(Qfb(5,3,-1),Qfb(7,1,-1)) Qfb(1, 5, -1) ? qfbcomp([Qfb(5,3,-1),0.],[Qfb(7,1,-1),1.]) [Qfb(1, 5, -1), 1.8164729589747058776211821169142495558] ? qfbcompraw(Qfb(5,3,-1),Qfb(7,1,-1)) Qfb(35, 43, 13) ? qfbcompraw([Qfb(5,3,-1),0.],[Qfb(7,1,-1),1.]) [Qfb(35, 43, 13), 1.0000000000000000000000000000000000000] ? 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) ? qfbpow([Qfb(5,3,-1),0.],3) [Qfb(1, 5, -1), 0.23856259352947494119218423539636536431] ? 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), 2.1074451073987839947135880252731470616] ? 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(2497, 3120), Mod(2341, 3120), Mod(1951, 3120), Mod(2081, 3120)]] ? if(getheap()!=HEAP,getheap()) ? print("Total time spent: ",gettime); Total time spent: 5 pari-2.17.2/src/test/32/sumnumrat0000644000175000017500000000555214676526175015166 0ustar billbill realprecision = 115 significant digits 0.E-115 3.28986813369645287294483033329205037843789980241359687547111645874001494080 6401747667257801239517410608008637924674 0.45224742004106549850654336483224793417323134323989242173641893035116502736 39108744489575443549068582228062276669206*y 0.30683697542290869391786213828290734801742482783565174497642694808825913036 03651451009491129226235190125664092098724 1.26136274645318147698799551222314132362637346328706942198906377178189999150 1230866228427233973980799199951451197768 3.67607791037497772069569749202826066650715634682763027747800359355744732411 1022073213255926590323023528755113952481 0.38905955531696837171041438969249635813838671424662604898213163770917329090 28320667369090321673956106194704282531996 0.38905955531696837171041438969249635813838671424662604898213163770917329090 28320667369090321673956106194704282531996 -383 -383 0.47168061361299786807523563308048208742592638200698688363573725541773211675 96827440962100273769490230313011322456824 -383 0.E-115 1.00000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000 1.00000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000 0.E-115 -383 0.14465275683805964915170506228112951785909958471772136547398491616634499865 27445984873295867753636930661164748046781 1 1 1.00000000003455714882589776991578586241344576868248838364476436375813494006 9816721677621808292508510275513147053341 *** at top-level: sumnumrat(1/x^2,oo) *** ^------------------- *** sumnumrat: incorrect type in sumnumrat (t_INFINITY). *** at top-level: sumnumrat(1.0,1) *** ^---------------- *** sumnumrat: incorrect type in sumnumrat (t_REAL). *** at top-level: sumnumrat(1/x,10) *** ^----------------- *** sumnumrat: sum diverges in sumnumrat. *** at top-level: prodnumrat(1+1/x,10) *** ^-------------------- *** prodnumrat: product diverges in prodnumrat. *** at top-level: prodnumrat(2,1) *** ^--------------- *** prodnumrat: incorrect type in prodnumrat (t_INT). *** at top-level: sumeulerrat(1) *** ^-------------- *** sumeulerrat: incorrect type in sumeulerrat (t_INT). *** at top-level: sumeulerrat(1/p) *** ^---------------- *** sumeulerrat: domain error in sumeulerrat: real(s) <= 1.0000000000000000000 *** at top-level: prodeulerrat(2) *** ^--------------- *** prodeulerrat: incorrect type in prodeulerrat (t_INT). *** at top-level: prodeulerrat(1+1/p) *** ^------------------- *** prodeulerrat: product diverges in prodeulerrat. *** at top-level: sumeulerrat(x^2/(1+x),2) *** ^------------------------ *** sumeulerrat: sum diverges in sumeulerrat. Total time spent: 1532 pari-2.17.2/src/test/32/ellweilpairing0000644000175000017500000001555614567450071016135 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]] [1, 3, [6]] [1, 2, [3, 3]] 1 t^5 + t^3 + t^2 t^5 + t^4 + 1 t^4 + t^2 + 1 t^5 + t 2*t^5 + t^4 + t^3 + t t^3 + 2*t^2 + 2 2*t^5 + 2*t^4 + 2*t^3 + 2*t^2 2*t^5 + 2*t^2 + 1 3*t^5 + 3*t^4 + 2*t^3 + t^2 + 2*t + 3 2*t^4 + t^3 + 3*t 2*t^5 + t^4 + t^3 + 2*t^2 3*t^5 + 4*t^4 + 4*t^3 + 3*t^2 + 4 1 84*t^5 + 80*t^4 + 95*t^3 + 91*t^2 + 74*t + 37 t 2*t^4 + 2*t^2 + 2*t + 1 4*t^3 + t + 1 [36893488147419103362, 36893488147419103362] 9688432087730133707 9688432087730133707 [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: 100 pari-2.17.2/src/test/32/hgm0000644000175000017500000002056114676526175013703 0ustar billbill1061520150601*x^4 - 1163209829*x^3 + 985356*x^2 - 1129*x + 1 832972004929*x^4 - 1428333245*x^3 + 2086470*x^2 - 1565*x + 1 [1, -1, -5, -5, 0, 5, -25, -5, -20, 0, 14, 25, 15, 25, 0, 51, -15, 20, 120, 0, 125, -14, 60, 25, 0, -15, 190, 125, -45, 0, 259, 59, -70, 15, 0, 100] x + 1 1 x^8 + x^5 + x^3 + 1 0 1 1 1 2 0 0 3 1 2 1 1 6 6 4 [2, 1, [x + 1, 1], 1/16] [2, 0, [2, 0], 16] [6, 3, [x^3 + 2*x^2 + 2*x + 1, 2], 3125/729] [14, 5, [x^5 + 3*x^4 + 3*x^3 + 3*x^2 + 3*x + 1, 2], 1024/3125] 729/4096 256 3125 1 [[0], [1/2]] Vecsmall([2, -1]) 1 [Vecsmall([3]), Vecsmall([1, 2])] [[1/3, 2/3], [0, 1/2]] Vecsmall([-1, -1, 1]) [2, 3] [2, 4] 15625*x^4 + 500*x^3 - 130*x^2 + 4*x + 1 125*x^3 + 20*x^2 + 4*x + 1 343*x^3 - 42*x^2 - 6*x + 1 -1331*x^3 - 22*x^2 + 2*x + 1 -2197*x^3 - 156*x^2 + 12*x + 1 4913*x^3 + 323*x^2 + 19*x + 1 6859*x^3 - 57*x^2 - 3*x + 1 -14641*x^4 - 1210*x^3 + 10*x + 1 -28561*x^4 - 2704*x^3 + 16*x + 1 -83521*x^4 - 4046*x^3 + 14*x + 1 130321*x^4 + 14440*x^3 + 969*x^2 + 40*x + 1 279841*x^4 - 25392*x^3 + 1242*x^2 - 48*x + 1 707281*x^4 - 7569*x^3 + 696*x^2 - 9*x + 1 27*x^3 + 3*x^2 + x + 1 [[[2, 0.73729299618559624017642619780229369794*x^-1 + O(x^0)]], [[2, 0.44822 039438838143211638545001748524956*x^-1 + O(x^0)], [1, -0.4482203943883814321 1638545001748524956*x^-1 + O(x^0)]]~, 1] 27*x^3 + 3*x^2 + x + 1 16807*x^5 - 686*x^4 - 105*x^3 - 15*x^2 - 2*x + 1 [1, 0, 0, 0, -4, 0, 0, 0, -6, 0, 0, 0, -84, 0, 0, 0, 36, 0, 0, 0] [1, 0, 0, 0, -4, 0, 0, 0, -6, 0, 0, 0, -84, 0, 0, 0, 36, 0, 0, 0] [1, 0, 0, 0, 1, 0, 8, 0, -6, 0, -8, 0, -20, 0, 0, 0, 68, 0, 104, 0] 0: [[[4], [1, 2]], [[6], [1, 2]], [[3], [1, 2]]] 1: [[[4], [6]], [[3], [4]], [[2, 2], [4]], [[4], [1, 1]], [[3], [6]], [[2, 2 ], [6]], [[6], [1, 1]], [[2, 2], [3]], [[3], [1, 1]], [[2, 2], [1, 1]]] [51, 1001, 1234, 3247, 894, 1450, 204, 363] [13, 0, 1836, 0, 2878, 0, 1263, 0, 363] [[Vecsmall([19]), [[[1/6, 5/6], [0, 1/2], [Vecsmall([0, 0, 0, 0, 0, 1]), Vec small([1, 1])], Vecsmall([0, 1]), Vecsmall([1, 2]), 108, Vecsmall([1, -2, -1 , 0, 0, 1]), -6, Vecsmall([0, 2]), [12, 36], -3, Vecsmall([1, 0, 0])], [-1, [[2, 1/(x + 1)], [3, 1]]]]], 0, [0, 1], 1, 216, 1] 1/(x + 1) 1 [[Vecsmall([19]), [[[1/2, 1/2, 1/2], [0, 0, 0], [Vecsmall([0, 3]), Vecsmall( [3])], Vecsmall([0, 0, 0]), Vecsmall([1, 1, 1]), 64, Vecsmall([-6, 3]), -2, Vecsmall([0, 1, 1, 1]), [-4, -4], 1, Vecsmall([3, 0, 0])], [1/4, [[2, -1/(2* x - 1)]]]]], 0, [-1, 0, 1], 3, 12, 1, [[2, 0.7372929961855962401764261978022 9369794*x^-1 + O(x^0)]]] 5 -30 906 12835 -1500 117649 12835 -9*x^2 + 1 27*x^3 + 3*x^2 + x + 1 27*x^3 - 9*x^2 - 3*x + 1 -x + 1 [-27*x^3 - 9*x^2 + 3*x + 1, 0] [-9*x^2 + 1, 1] [-x + 1, 2] 3 x + 1 -8*x^3 - 2*x^2 + x + 1 -8*x^3 - 2*x^2 + x + 1 1/64 -127 [-1, -1, 0, 1] x + 1 [-3, 3456] -823543*x^5 + 98441*x^4 + 2009*x^3 + 49*x^2 + x + 1 19487171*x^5 + 1566587*x^4 - 18392*x^3 - 132*x^2 - 3*x + 1 [-8, -288] 282475249*x^5 + 1529437*x^4 + 48706*x^3 + 994*x^2 + 13*x + 1 -25937424601*x^5 + 278135077*x^4 - 2063050*x^3 + 17050*x^2 - 157*x + 1 [-24, 2332800] -4826809*x^6 + 114244*x^5 + 2197*x^4 - 13*x^2 - 4*x + 1 1771561*x^4 - 118459*x^3 + 3861*x^2 - 89*x + 1 -1 -x + 1 49*x^2 + 13*x + 1 2 117649*x^4 + 2744*x^3 + 252*x^2 + 8*x + 1 0 399 -468 -x^2 + 1 x^2 + x + 1 49*x^2 - 11*x + 1 -3*x + 1 -9468276082626847201*x^5 - 1594410620762239*x^4 - 12386125758*x^3 + 1984638* x^2 + 6559*x + 1 -4096*x^5 + 384*x^4 + 760*x^3 - 170*x^2 + x + 1 [[1/7, 1/5, 1/4, 2/7, 1/3, 2/5, 3/7, 4/7, 3/5, 2/3, 5/7, 3/4, 4/5, 6/7], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [Vecsmall([0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0]), Vecsmall([14])], Vecsmall([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), Vecsmall([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]), 44471 32200000, Vecsmall([-17, -1, 1, 1, 1, 0, 1]), -420, Vecsmall([0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]), [-840, 1680], 1, Vecsmall([14, 0, 1])] 1331*x^2 + 43*x + 1 [1, 1, 7, -7, 0, 7, 6, -15, 22, 0, -43, -49] 357911*x^2 + 388*x + 1 1 0 [[[2, 1]], [0, [0, 0, 1], 3, 80, 1]] [[[2, -1/(2*x - 1)]], [0, [0, 0, 1], 3, 432, 1]] [[[2, -1/(2*x - 1)], [3, 1/(3*x + 1)]], [0, [-1, 0, 1], 3, 1152, 1]] [[[2, -1/(4*x^2 - 1)], [3, 1/(3*x + 1)]], [0, [0, 0, 1], 3, 72, 1]] [[[2, -1/(4*x^2 - 1)]], [0, [-1, 0, 1], 3, 8, 1, [[2, 0.5287494555957661831* x^-1 + O(x^0)]]]] 0 0 [[[2, 1/(4*x^2 + 2*x + 1)], [3, 1]], [0, [-1, 0, 1], 3, 324, 1]] [1/(8*x^3 + 6*x^2 + x + 1), -1/(81*x^3 - 15*x^2 - x - 1), -1/(625*x^3 - 115* x^2 + 3*x - 1), 1/(117649*x^4 + 5488*x^3 + 238*x^2 + 16*x + 1), 1/(1771561*x ^4 - 31944*x^3 - 330*x^2 - 24*x + 1), 1/(4826809*x^4 - 26364*x^3 + 78*x^2 - 12*x + 1), -1/(83521*x^3 - 5763*x^2 + 67*x - 1), 1/(47045881*x^4 - 54872*x^3 + 8550*x^2 - 8*x + 1)] 15625*x^4 + 625*x^3 - 75*x^2 + 5*x + 1 15625*x^4 - 1875*x^3 + 200*x^2 - 15*x + 1 *** at top-level: hgminit([0]) *** ^------------ *** hgminit: incorrect type in hgmgammatocyclo (t_VECSMALL). *** at top-level: H=hgminit(2,Vecsmall(1)) *** ^---------------------- *** hgminit: incorrect type in hgminit (t_INT). *** at top-level: H=hgminit([2],Vecsmall(1)) *** ^------------------------ *** hgminit: incorrect type in hgminit (t_VECSMALL). *** at top-level: lfunhgm(1,1) *** ^------------ *** lfunhgm: incorrect type in lfunhgm (t_INT). *** at top-level: hgminit([1,1],[0]) *** ^------------------ *** hgminit: incorrect type in hgmcyclotoalpha (t_VECSMALL). *** at top-level: hgmcoef(H,1.,1) *** ^--------------- *** hgmcoef: incorrect type in hgmcoef (t_REAL). *** at top-level: hgmcoefs(H,1.,1) *** ^---------------- *** hgmcoefs: incorrect type in hgmcoefs (t_REAL). *** at top-level: hgmeulerfactor(H,1.,3) *** ^---------------------- *** hgmeulerfactor: incorrect type in hgmeulerfactor (t_REAL). *** at top-level: hgminit([1/2],[1/2]) *** ^-------------------- *** hgminit: incorrect type in hgminit [not a Q motive] (t_VEC). *** at top-level: hgminit([1.0],[1/2]) *** ^-------------------- *** hgminit: incorrect type in hgminit [not rational params] (t_REAL). *** at top-level: hgminit([1/2],[0.]) *** ^------------------- *** hgminit: incorrect type in hgminit [not rational params] (t_REAL). *** at top-level: hgminit([1],[1]) *** ^---------------- *** hgminit: incorrect type in hgminit [nonempty intersection] (t_VEC). *** at top-level: hgminit([]) *** ^----------- *** hgminit: incorrect type in hgminit [#al = 0] (t_VEC). *** at top-level: hgminit([],[]) *** ^-------------- *** hgminit: incorrect type in hgminit [#al = 0] (t_VEC). *** at top-level: ...t([2,2,2,2,2,2,2,2,2,2]);hgmeulerfactor(H,1,p) *** ^--------------------- *** hgmeulerfactor: overflow in hgmprecomp. *** at top-level: hgmeulerfactor(HCAN,1,p) *** ^------------------------ *** hgmeulerfactor: overflow in hgmCallmodp2. *** at top-level: hgmalpha(Pi) *** ^------------ *** hgmalpha: incorrect type in hgmalpha (t_REAL). *** at top-level: hgmgamma(Pi) *** ^------------ *** hgmgamma: incorrect type in hgmgamma (t_REAL). Total time spent: 2529 pari-2.17.2/src/test/32/ellglobalred0000644000175000017500000000214014567450071015537 0ustar billbill[["496a1", [0, 0, 0, 1, 1], [[0, 1]]], [1, 0, 0, 0]] ["11a1", [0, -1, 1, -10, -20], []] [["11a1", [0, -1, 1, -10, -20], []], ["11a2", [0, -1, 1, -7820, -263580], [] ], ["11a3", [0, -1, 1, 0, 0], []]] [] [["11a1", [0, -1, 1, -10, -20], []], ["11a2", [0, -1, 1, -7820, -263580], [] ], ["11a3", [0, -1, 1, 0, 0], []]] ["11a1", [0, -1, 1, -10, -20], []] [["11a1", [0, -1, 1, -10, -20], []], ["11a2", [0, -1, 1, -7820, -263580], [] ], ["11a3", [0, -1, 1, 0, 0], []]] [["11a1", [0, -1, 1, -10, -20], []], ["11a2", [0, -1, 1, -7820, -263580], [] ], ["11a3", [0, -1, 1, 0, 0], []]] [["11a1", [0, -1, 1, -10, -20], []], ["11a2", [0, -1, 1, -7820, -263580], [] ], ["11a3", [0, -1, 1, 0, 0], []]] -122023936/161051 error("incorrect type in ellsearch (t_VEC).") error("domain error in ellsearch: conductor <= 0") error("incorrect type in ellsearch (t_STR).") error("incorrect type in ellsearch (t_COMPLEX).") 306 93 *** at top-level: ellidentify(ellinit([1,1],nfinit('a^2-5))) *** ^------------------------------------------ *** ellidentify: incorrect type in checkell over Q (t_VEC). Total time spent: 1107 pari-2.17.2/src/test/32/ser0000644000175000017500000001501514676526175013717 0ustar billbillx + x^2 + O(x^5) x + x^2 - 1/3*x^3 - x^4 + O(x^5) O(x^5) [0.78539816339744830961566084581987572105 + O(x^16)] x + x^2 + 1/6*x^3 + 1/2*x^4 + O(x^5) O(x^5) [1.5707963267948966192313216916397514421 + O(x^8)] 1.5707963267948966192313216916397514421 - x - x^2 - 1/6*x^3 - 1/2*x^4 + O(x^ 5) 1.5707963267948966192313216916397514421 + O(x^5) [O(x^8)] 1 + 1/2*x^2 + x^3 + 13/24*x^4 + 1/6*x^5 + O(x^6) 1 + O(x^5) [1.5430806348152437784779056207570616826 + O(x^16)] x + x^2 + 1/6*x^3 + 1/2*x^4 + O(x^5) O(x^5) [1.1752011936438014568823818505956008152 + O(x^16)] x + x^2 - 1/3*x^3 - x^4 + O(x^5) O(x^5) [0.76159415595576488811945828260479359041 + O(x^16)] x^-1 - 1 + 4/3*x - 2/3*x^2 + O(x^3) O(x^5) [1.3130352854993313036361612469308478329 + O(x^16)] 1.5707963267948966192313216916397514421*I - 1.000000000000000000000000000000 0000000*I*x - 1.0000000000000000000000000000000000000*I*x^2 - 0.166666666666 66666666666666666666666667*I*x^3 - 0.50000000000000000000000000000000000000* I*x^4 + O(x^5) 1.5707963267948966192313216916397514421*I + O(x^5) [O(x^8)] x + x^2 - 1/6*x^3 - 1/2*x^4 + O(x^5) O(x^5) [0.88137358701954302523260932497979230903 + O(x^16)] x + x^2 + 1/3*x^3 + x^4 + O(x^5) O(x^5) *** at top-level: ...rint(f[i](O(x^5)));print(f[i]([Pol(1)]));) *** ^----------------- *** in function f: atanh *** ^----- *** atanh: impossible inverse in div_ser: O(x^16). O(x^-2) O(x^-2) 2 + O(x^2) 1 + O(x^2) 1 O(x^0) 2*x + O(x^2) 2*x - 8/3*x^3 + 32/5*x^5 - 128/7*x^7 + 512/9*x^9 - 2048/11*x^11 + 8192/13*x^ 13 - 32768/15*x^15 + O(x^17) error("domain error in sqrtn: valuation != Mod(0, 2)") ((1 + O(y^4))*x + y^3)/(y^3*x) x + 2*x^2 + O(x^3) 2*x^2 + O(x^3) O(x^100) Mod(1, 3)*x + O(x^2) Mod(1, 3)*x + O(x^2) Mod(0, 3)*x + O(x^2) Mod(0, 3)*x + O(x^2) Mod(0, 3)*x + O(x^2) 0 [0, 0] [Mod(0, 3), Mod(0, 3)] [Mod(0, 3), Mod(0, 3)] [0.E-38 + O(x), 0.E-38 + O(x)] 1 + 2*x + 3*x^2 + O(x^3) 1 + 2*x + 3*x^2 + O(x^6) 1 + 2*x - 5*x^2 + O(x^3) 1 + 2*y + O(y^2) 1 + 2*y + 3*y^2 + O(y^5) 1 + 2*y + 3*y^2 + O(y^5) O(x^3) 1 + 2*y + 3*y^2 + O(y^5) x + O(x^4) O(x^3) x + x^2 + O(x^3) O(x^2) O(x^0) O(x^0) O(x^-1) O(x^0) y + x + O(x^2) (y + O(y^17)) + (1 + O(y^16))*x + O(x^2) Mod(0, 7)*x^15 + O(x^16) Mod(1, 7)*x^2 + Mod(1, 7)*x^4 + O(x^5) Mod(0, 7)*x^15 + O(x^16) Mod(1, 7) + O(x^16) Mod(1, 7)*x + O(x^16) Mod(0, 7)*x^14 + O(x^15) Mod(0, 7)*x^14 + O(x^15) Mod(0, 7)*x^15 + O(x^16) Mod(0, 7)*x^15 + O(x^16) Mod(0, 7)*x^15 + O(x^16) Mod(0, 7)*x^15 + O(x^16) O(x^16) Mod(0, 7)*x^15 + O(x^16) O(x^16) 0 Mod(0, 4)*x + O(x^2) (1 + O(y^2))*x^3 (Mod(1, 3) + O(y^2))*x^3 O(x) O(3) + O(x) O(3^2) + O(x) O(3^3) + O(x) 1 + O(x) *** _+_: Warning: normalizing a series with 0 leading term. 1.0000000000000000000000000000000000000*x^-1 + O(x^2) *** _+_: Warning: normalizing a series with 0 leading term. 1.0000000000000000000000000000000000000*x^-2 + O(x^2) [0, 1, 1, 0, 1] [0, 1, 1, 0, 1] [0, 1, 1, 0, 1] Mod(0, 9)*x + O(x^2) 0.E-38*x^-1 + O(x^0) O(x^0) Mod(0, 2)*x^-1 + O(x^0) Mod(0, 5) Mod(0, 5)*x^-1 + O(x^0) Mod(0, 5)*x^-1 + O(x^0) 1 + O(y) 1 + y^2 + O(y^4) 1 1 0 0 0 1 Mod(0, 2)*x^-1 + O(x^0) O(11)*x^-2 + O(x^-1) *** _+_: Warning: normalizing a series with 0 leading term. O(23^0)*x^-2 + O(x^-1) O(23)*x^-1 + O(x^0) O(23)*x^-2 + O(x^-1) O(23)*x^-2 + O(x^-1) Mod(0, 2) 1 1 1 1 1 + O(x^200) 1 1 + x^3 + O(x^6) 1 + x^2 + O(x^4) 1 + x^3 + 4*x^4 + O(x^5) 0 Mod(0, 3) O(3^2)*x^2 + O(x^3) 1 Mod(1, 3) 1 + O(3)*x + O(x^2) 1 + z^2 + O(z^3) y^2 + (1 + z^2 + O(z^3)) x^-1 - 1/6*x + 1/120*x^3 + O(x^4) t^-1 - 1/6*t + 1/120*t^3 + O(t^4) -1/2*x + 1/24*x^3 - 1/720*x^5 + 1/40320*x^7 - 1/3628800*x^9 + 1/479001600*x^ 11 - 1/87178291200*x^13 + 1/20922789888000*x^15 - 1/6402373705728000*x^17 + O(x^18) 1 + 4*q^2 + 4*q^4 + O(q^6) q^32000 + O(q^32001) q^32000 + O(q^32001) 1 + 1.0000000000000000000000000000000000000*x + O(x^2) *** exp: Warning: normalizing a series with 0 leading term. 1 + 0.E-38*x^2 + O(x^18) *** _+_: Warning: normalizing a series with 0 leading term. 1.0000000000000000000000000000000000000*x^-1 + O(x^2) 0.E-38 0 1 Mod(0, 1)*v1 + O(v1^2) (1 + y + y^2 + y^3 + y^4 + O(y^5)) + (y^4 + y^3 + y^2 + y + 1)*x + (y^4 + y^ 3 + y^2 + y + 1)*x^2 + (y^4 + y^3 + y^2 + y + 1)*x^3 + (y^4 + y^3 + y^2 + y + 1)*x^4 + O(x^5) Mod(0, 2) + O(x) *** at top-level: polcoef(0.+O(x),1) *** ^------------------ *** polcoef: domain error in polcoef: degree > 0 *** at top-level: polcoef(Mod(0,2)+O(x),1) *** ^------------------------ *** polcoef: domain error in polcoef: degree > 0 *** at top-level: subst(x^-1+O(x),x,Mod(0,3)) *** ^--------------------------- *** subst: impossible inverse in gsubst: Mod(0, 3). *** at top-level: subst(O(x^-1),x,Mod(0,3)) *** ^------------------------- *** subst: impossible inverse in gsubst: Mod(0, 3). *** at top-level: subst(x^-1+O(x),x,0*x) *** ^---------------------- *** subst: impossible inverse in gsubst: 0. *** at top-level: subst(O(x^-1),x,0*x) *** ^-------------------- *** subst: impossible inverse in gsubst: 0. *** at top-level: Ser(1/x,y) *** ^---------- *** Ser: incorrect priority in Ser: variable x < y *** at top-level: Ser(x,y) *** ^-------- *** Ser: incorrect priority in Ser: variable x < y *** at top-level: Ser([x],y) *** ^---------- *** Ser: incorrect priority in Ser: variable x <= y *** at top-level: Ser(x,,-5) *** ^---------- *** Ser: domain error in Ser: precision < 0 *** at top-level: Ser("") *** ^------- *** Ser: incorrect type in Ser (t_STR). *** _/_: Warning: normalizing a series with 0 leading term. *** at top-level: O(13^-5)/Mat(Mod(2,26)*y*x+(Mod(1,2)*y^-1+O(y^ *** ^-------------------------------------- *** _/_: impossible inverse in gdiv: O(13^0) + O(13^0)*y + O(13^0)*y^2 + O(13^0)*y^3 + O(y^4). *** at top-level: laurentseries(1) *** ^---------------- *** laurentseries: incorrect type in laurentseries (t_INT). *** at top-level: laurentseries((x,y)->1) *** ^----------------------- *** laurentseries: incorrect type in laurentseries (t_CLOSURE). *** at top-level: O(x)/Mod(0,5) *** ^--------- *** _/_: impossible inverse in gdiv: Mod(0, 5). *** at top-level: O(x)/O(y) *** ^----- *** _/_: impossible inverse in gdiv: O(y). *** at top-level: O(y)/O(x) *** ^----- *** _/_: impossible inverse in RgXn_inv: 0. Total time spent: 3 pari-2.17.2/src/test/32/env0000644000175000017500000000006614567450071013704 0ustar billbill"/root" 1 "XXX, YYY, XXX" "XXX" 0 Total time spent: 0 pari-2.17.2/src/test/32/vararg0000644000175000017500000000157114567450071014400 0ustar billbill(s,v[..])->if(#v>0,print1(v[1]);for(i=2,#v,print1(s,v[i])));print() myprintsep = (s,v[..])->if(#v>0,print1(v[1]);for(i=2,#v,print1(s,v[i])));print() 2 : : a, b, c, d a, 0, c, 0 a0b0c0d x=5 x=5 y=7 x=5 y=7 z=9 2 0 2 : *** at top-level: print1(":");myprintsep() *** ^------------ *** in function myprintsep: s,v[..] *** ^------- *** missing mandatory argument 's' in user function. : a, b, c, d *** at top-level: myprintsep(,a,b,c,d) *** ^-------------------- *** in function myprintsep: s,v[..] *** ^------- *** missing mandatory argument 's' in user function. a, 0, c, 0 *** at top-level: f(1) *** ^---- *** in function f: b,c *** ^--- *** missing mandatory argument 'c' in user function. Total time spent: 0 pari-2.17.2/src/test/32/extract0000644000175000017500000002555014676526175014605 0ustar billbill[36][37][38][39][40][41][42][43][44][45][46][47][48][49][50][51][52][53][54] [55][56][57][58][59][60][61][62][63][64][65][66][67][68][69][70][71][72][73] [74][75][76][77][78][79][80][81][82][83][84][85][86][87][88][89][90][91][92] [93][94][95][96][97][98][99][100] [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100] [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100] [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100] [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100] [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100] [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100] [2, 3, 4] [99, 98, 97] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100] [1, 100] [100, 1] [3, 5] [0 1 0] [0 0 1] [0] [1] [0, 2] [0, 2] [0, 0] [0, 0] [0, 0] [0, 0] Vec [1] [1, 0] [1/x] [5, 4, 3, 2, 1] [1, 2] [1, 2] [1, 2, 3] [1, 2] [1, 2, 3] [1, 2, 3, 4, 5] ["a", "b", "c", "d", "e", "f"] ["a", "b"] [[1, 3]~, [2, 4]~, [3, 5]~] ["e_INV", "gdiv", 0] (x)->my(f=Vec);f(x,4) [1, 0, 0, 0] [1, 0, 0, 0] [1/x, 0, 0, 0] [5, 4, 3, 2] [1, 2, 0, 0] [1, 2, 0, 0] [1, 2, 3, 0] [1, 2, 0, 0] [1, 2, 3, 0] [1, 2, 3, 4] ["a", "b", "c", "d"] ["a", "b", 0, 0] error("incorrect type in gtovec (t_MAT).") error("incorrect type in gtovec (t_ERROR).") (x)->my(f=Vec);f(x,-4) [0, 0, 0, 1] [0, 0, 1, 0] [0, 0, 0, 1/x] [4, 3, 2, 1] [0, 0, 1, 2] [0, 0, 1, 2] [0, 1, 2, 3] [0, 0, 1, 2] [0, 1, 2, 3] [2, 3, 4, 5] ["c", "d", "e", "f"] ["a", "b", 0, 0] error("incorrect type in gtovec (t_MAT).") error("incorrect type in gtovec (t_ERROR).") Vecrev [1] [0, 1] [1/x] [1, 2, 3, 4, 5] [2, 1] [2, 1] [3, 2, 1] [2, 1] [3, 2, 1] [5, 4, 3, 2, 1] ["f", "e", "d", "c", "b", "a"] ["b", "a"] [[3, 5]~, [2, 4]~, [1, 3]~] [0, "gdiv", "e_INV"] (x)->my(f=Vecrev);f(x,4) [1, 0, 0, 0] [0, 1, 0, 0] [1/x, 0, 0, 0] [1, 2, 3, 4] [2, 1, 0, 0] [2, 1, 0, 0] [3, 2, 1, 0] [2, 1, 0, 0] [3, 2, 1, 0] [5, 4, 3, 2] ["f", "e", "d", "c"] [0, 0, "b", "a"] error("incorrect type in gtovec (t_MAT).") error("incorrect type in gtovec (t_ERROR).") (x)->my(f=Vecrev);f(x,-4) [0, 0, 0, 1] [0, 0, 0, 1] [0, 0, 0, 1/x] [2, 3, 4, 5] [0, 0, 2, 1] [0, 0, 2, 1] [0, 3, 2, 1] [0, 0, 2, 1] [0, 3, 2, 1] [4, 3, 2, 1] ["d", "c", "b", "a"] [0, 0, "b", "a"] error("incorrect type in gtovec (t_MAT).") error("incorrect type in gtovec (t_ERROR).") Col [1]~ [1, 0]~ [1/x]~ [5, 4, 3, 2, 1]~ [1, 2]~ [1, 2]~ [1, 2, 3]~ [1, 2]~ [1, 2, 3]~ [1, 2, 3, 4, 5]~ ["a", "b", "c", "d", "e", "f"]~ ["a", "b"]~ [[1, 2, 3], [3, 4, 5]]~ ["e_INV", "gdiv", 0]~ (x)->my(f=Col);f(x,4) [1, 0, 0, 0]~ [1, 0, 0, 0]~ [1/x, 0, 0, 0]~ [5, 4, 3, 2]~ [1, 2, 0, 0]~ [1, 2, 0, 0]~ [1, 2, 3, 0]~ [1, 2, 0, 0]~ [1, 2, 3, 0]~ [1, 2, 3, 4]~ ["a", "b", "c", "d"]~ ["a", "b", 0, 0]~ error("incorrect type in gtovec (t_MAT).") error("incorrect type in gtovec (t_ERROR).") (x)->my(f=Col);f(x,-4) [0, 0, 0, 1]~ [0, 0, 1, 0]~ [0, 0, 0, 1/x]~ [4, 3, 2, 1]~ [0, 0, 1, 2]~ [0, 0, 1, 2]~ [0, 1, 2, 3]~ [0, 0, 1, 2]~ [0, 1, 2, 3]~ [2, 3, 4, 5]~ ["c", "d", "e", "f"]~ ["a", "b", 0, 0]~ error("incorrect type in gtovec (t_MAT).") error("incorrect type in gtovec (t_ERROR).") Colrev [1]~ [0, 1]~ [1/x]~ [1, 2, 3, 4, 5]~ [2, 1]~ [2, 1]~ [3, 2, 1]~ [2, 1]~ [3, 2, 1]~ [5, 4, 3, 2, 1]~ ["f", "e", "d", "c", "b", "a"]~ ["b", "a"]~ [[3, 4, 5], [1, 2, 3]]~ [0, "gdiv", "e_INV"]~ (x)->my(f=Colrev);f(x,4) [1, 0, 0, 0]~ [0, 1, 0, 0]~ [1/x, 0, 0, 0]~ [1, 2, 3, 4]~ [2, 1, 0, 0]~ [2, 1, 0, 0]~ [3, 2, 1, 0]~ [2, 1, 0, 0]~ [3, 2, 1, 0]~ [5, 4, 3, 2]~ ["f", "e", "d", "c"]~ [0, 0, "b", "a"]~ error("incorrect type in gtovec (t_MAT).") error("incorrect type in gtovec (t_ERROR).") (x)->my(f=Colrev);f(x,-4) [0, 0, 0, 1]~ [0, 0, 0, 1]~ [0, 0, 0, 1/x]~ [2, 3, 4, 5]~ [0, 0, 2, 1]~ [0, 0, 2, 1]~ [0, 3, 2, 1]~ [0, 0, 2, 1]~ [0, 3, 2, 1]~ [4, 3, 2, 1]~ ["d", "c", "b", "a"]~ [0, 0, "b", "a"]~ error("incorrect type in gtovec (t_MAT).") error("incorrect type in gtovec (t_ERROR).") Vecsmall Vecsmall([1]) Vecsmall([1, 0]) error("incorrect type in vectosmall (t_RFRAC).") Vecsmall([5, 4, 3, 2, 1]) Vecsmall([1, 2]) Vecsmall([1, 2]) error("incorrect type in vectosmall (t_QFB).") Vecsmall([1, 2]) Vecsmall([1, 2, 3]) Vecsmall([1, 2, 3, 4, 5]) Vecsmall([97, 98, 99, 100, 101, 102]) Vecsmall([97, 98]) error("incorrect type in vectosmall (t_MAT).") error("incorrect type in vectosmall (t_ERROR).") (x)->my(f=Vecsmall);f(x,4) Vecsmall([1, 0, 0, 0]) Vecsmall([1, 0, 0, 0]) error("incorrect type in gtovecsmall (t_RFRAC).") Vecsmall([5, 4, 3, 2]) Vecsmall([1, 2, 0, 0]) Vecsmall([1, 2, 0, 0]) error("incorrect type in gtovecsmall (t_QFB).") Vecsmall([1, 2, 0, 0]) Vecsmall([1, 2, 3, 0]) Vecsmall([1, 2, 3, 4]) Vecsmall([97, 98, 99, 100]) Vecsmall([97, 98, 0, 0]) error("incorrect type in gtovecsmall (t_MAT).") error("incorrect type in gtovecsmall (t_ERROR).") (x)->my(f=Vecsmall);f(x,-4) Vecsmall([0, 0, 0, 1]) Vecsmall([0, 0, 1, 0]) error("incorrect type in gtovecsmall (t_RFRAC).") Vecsmall([4, 3, 2, 1]) Vecsmall([0, 0, 1, 2]) Vecsmall([0, 0, 1, 2]) error("incorrect type in gtovecsmall (t_QFB).") Vecsmall([0, 0, 1, 2]) Vecsmall([0, 1, 2, 3]) Vecsmall([2, 3, 4, 5]) Vecsmall([99, 100, 101, 102]) Vecsmall([0, 0, 97, 98]) error("incorrect type in gtovecsmall (t_MAT).") error("incorrect type in gtovecsmall (t_ERROR).") (x)->component(x,2) error("incorrect type in component [leaf] (t_INT).") 1 x 2 2 2 2 2 2 2 error("incorrect type in component [leaf] (t_STR).") error("incorrect type in component [leaf] (t_STR).") [2, 4]~ 0 (x)->component(x,10) error("incorrect type in component [leaf] (t_INT).") error("nonexistent component: index > 2") error("nonexistent component: index > 2") error("nonexistent component: index > 5") error("nonexistent component: index > 2") error("nonexistent component: index > 2") error("nonexistent component: index > 4") error("nonexistent component: index > 2") error("nonexistent component: index > 3") error("nonexistent component: index > 5") error("incorrect type in component [leaf] (t_STR).") error("incorrect type in component [leaf] (t_STR).") error("nonexistent component: index > 3") error("nonexistent component: index > 2") (x)->polcoef(x,-1) 0 0 1 0 0 error("incorrect type in polcoef (t_VEC).") error("incorrect type in polcoef (t_QFB).") error("incorrect type in polcoef (t_VECSMALL).") error("incorrect type in polcoef (t_LIST).") error("incorrect type in polcoef (t_LIST).") error("incorrect type in polcoef (t_STR).") error("incorrect type in polcoef (t_STR).") error("incorrect type in polcoef (t_MAT).") error("incorrect type in polcoef (t_ERROR).") (x)->polcoef(x,2) 0 0 0 3 2 error("incorrect type in polcoef (t_VEC).") error("incorrect type in polcoef (t_QFB).") error("incorrect type in polcoef (t_VECSMALL).") error("incorrect type in polcoef (t_LIST).") error("incorrect type in polcoef (t_LIST).") error("incorrect type in polcoef (t_STR).") error("incorrect type in polcoef (t_STR).") error("incorrect type in polcoef (t_MAT).") error("incorrect type in polcoef (t_ERROR).") (x)->polcoef(x,10) 0 0 0 0 error("domain error in polcoef: degree > 2") error("incorrect type in polcoef (t_VEC).") error("incorrect type in polcoef (t_QFB).") error("incorrect type in polcoef (t_VECSMALL).") error("incorrect type in polcoef (t_LIST).") error("incorrect type in polcoef (t_LIST).") error("incorrect type in polcoef (t_STR).") error("incorrect type in polcoef (t_STR).") error("incorrect type in polcoef (t_MAT).") error("incorrect type in polcoef (t_ERROR).") 0 O(x^2) 1 + x + O(x^2) y + O(y^2) 0 9 + 18*x + 36*x^2 + O(x^3) Vecsmall([4, 5, 3]) *** at top-level: vecextract([1],11) *** ^------------------ *** vecextract: incorrect type in vecextract [mask too large] (t_INT). *** at top-level: vecextract([1],"1..2") *** ^---------------------- *** vecextract: incorrect type in vecextract [incorrect range] (t_STR). *** at top-level: vecextract([1],1/2) *** ^------------------- *** vecextract: incorrect type in vecextract [mask] (t_FRAC). *** at top-level: vecextract(1,1) *** ^--------------- *** vecextract: incorrect type in extract (t_INT). *** at top-level: vecextract(matid(2),[3],[]) *** ^--------------------------- *** vecextract: incorrect type in vecextract [incorrect mask] (t_VEC). *** at top-level: [1][2..3] *** ^--------- *** _[_.._]: inconsistent dimensions in _[..]. *** at top-level: [1][-10..3] *** ^----------- *** _[_.._]: inconsistent dimensions in _[..]. *** at top-level: 1[1..2] *** ^------- *** _[_.._]: incorrect type in _[_.._] (t_INT). *** at top-level: [1/2..1] *** ^---- *** [_.._]: incorrect type in [_.._] (t_FRAC). *** at top-level: [1..1/2] *** ^------ *** [_.._]: incorrect type in [_.._] (t_FRAC). Total time spent: 2 pari-2.17.2/src/test/32/select0000644000175000017500000000065114567450071014373 0ustar billbill[2, 5, 17, 37, 101, 197, 257, 401, 577, 677, 1297, 1601] Vecsmall([2, 3, 5]) List([2, 3, 5]) List([2, 3, 5]) [1 2] [2 0] [0] [0] [] [1, 3] *** at top-level: select(x->x,v,1) *** ^---------------- *** select: incorrect type in select (t_VECSMALL). *** at top-level: select(x->x,v) *** ^-------------- *** select: incorrect type in select (t_VECSMALL). Total time spent: 0 pari-2.17.2/src/test/32/ellpadic0000644000175000017500000000607014760123736014672 0ustar billbill *** Warning: new stack size = 12000000 (11.444 Mbytes). [[0, 0, 0, -11, -890], [1/2, 0, 0, 0]] [0, 1, [1/2, 0, 0, 0], 1] [0, 1, [1/6, 0, 0, 0], 1] [0, 1, [3/2, 0, 0, 0], 1] [2^-2 + 2^-1 + 1 + 2 + O(2^2), 1 + 2 + 2^2 + 2^3 + O(2^4)] [3 + 2*3^2 + 3^4 + O(3^5), 2*3^4 + 3^5 + O(3^8)] [3*5 + 5^2 + 2*5^3 + 3*5^4 + O(5^5), 5^2 + 4*5^4 + O(5^6)] [0, 0] *** at top-level: ellpadicheight(E,19,0,P) *** ^------------------------ *** ellpadicheight: domain error in ellpadicheight: precision <= 0 [1, 1] [10, 10] [[10], [10]] [0, 0] 6 + 9*11 + 6*11^3 + 11^4 + O(11^5) 1 [1930 1588] [ 65 1195] [1, [], []] [2, [2], [[0, 0]]] [3, [3], [[0, 1]]] [2, [2], [[0, 1]]] [3, [3], [[0, 0]]] [4, [4], [[1, 2]]] [4, [4], [[0, 3]]] [5, [5], [[4, 3]]] [6, [6], [[4, 2]]] [2*3^2 + 2*3^3 + 3^4 + 3^5 + 3^6 + O(3^7), 2*3^2 + 3^4 + 2*3^5 + 3^6 + O(3^7 )] *** at top-level: ellpadiclog(E,3,5,P) *** ^-------------------- *** ellpadiclog: domain error in ellpadiclog: P not in the kernel of reduction at 3 2*3 + 2*3^2 + 3^5 + O(3^6) [2^3 + 2^5 + O(2^7), 2^5 + 2^6 + O(2^7)] [2^3 + 2^5 + O(2^6), O(2^5)] [[2364, 3100, 759; 3100, 3119, 902; 759, 902, 19675], [25225, 46975, 36525; 46975, 61850, 20400; 36525, 20400, 60475]] 3 + 3^2 + 3^3 + 3^4 + 3^5 + O(3^6) 2*3^2 + 3^4 + O(3^6) 5 + 5^2 + 4*5^3 + 2*5^4 + O(5^5) O(5^7) 2 + 4*43 + 19*43^2 + 15*43^3 + 35*43^4 + 3*43^5 + O(43^6) 4 + 3*5^2 + 4*5^3 + 5^4 + 2*5^5 + O(5^6) 4 + 3*5 + 3*5^3 + 3*5^4 + 4*5^5 + O(5^6) [1, 7 + 7^2 + 3*7^3 + 7^4 + 6*7^5 + 2*7^6 + 4*7^7 + 5*7^8 + O(7^9)] [1, 37 + 9*37^2 + 29*37^3 + 35*37^4 + 16*37^5 + 29*37^6 + 16*37^7 + 18*37^8 + 31*37^9 + O(37^10)] [2, 2*7 + 7^2 + 5*7^3 + O(7^4)] 2*7 + 7^2 + 5*7^3 + 6*7^4 + 2*7^5 + O(7^6) [1, 7 + 7^2 + 2*7^3 + 4*7^4 + O(7^5)] [4*5 + 4*5^2 + 2*5^3 + 5^4 + 2*5^5 + 3*5^6 + O(5^7) 4 + 5^2 + 2*5^4 + 5^5 + 5^6 + O(5^7)] [5 + 2*5^2 + 3*5^3 + 4*5^4 + 5^5 + 5^6 + O(5^7) 5 + 2*5^3 + 3*5^4 + 2*5^5 + 5^6 + O(5^7)] [ 2*3^4 + O(3^5) 1 + 3 + 2*3^2 + 3^3 + 3^4 + O(3^5)] [2*3 + 3^3 + 3^4 + O(3^5) 3^4 + O(3^5)] *** at top-level: ellap(Ep,2) *** ^----------- *** ellap: inconsistent moduli in ellap: 2 != 11 *** at top-level: ellpadics2(Ep,2,5) *** ^------------------ *** ellpadics2: incorrect type in ellpadicfrobenius (t_VEC). *** at top-level: ellcard(Ep,2) *** ^------------- *** ellcard: inconsistent moduli in ellcard: 2 != 11 *** at top-level: ellgroup(Ep,2) *** ^-------------- *** ellgroup: inconsistent moduli in ellgroup: 2 != 11 *** at top-level: ellissupersingular(Ep,2) *** ^------------------------ *** ellissupersingular: inconsistent moduli in ellissupersingular: 2 != 11 *** at top-level: elllocalred(Ep,2) *** ^----------------- *** elllocalred: inconsistent moduli in elllocalred: 2 != 11 *** at top-level: ellgroup(ellinit([5^6,5^6]),5,1) *** ^-------------------------------- *** ellgroup: incorrect type in ellgroup [not a p-minimal curve] (t_VEC). Total time spent: 193 pari-2.17.2/src/test/32/lfunlarge0000644000175000017500000000574114723631245015076 0ustar billbill *** Warning: new stack size = 20000000 (19.073 Mbytes). 0.23958595950719973070833622504463570961 - 0.5041411916090098348916896372313 2327642*I 0.065235778762888976273773201444761083696 - 1.201994418864119944017979049152 5853613*I 1 1.7358460022008574001618925255928837612 + 0.58543323592998782501393347478429 518364*I 0.049607901137329198047667556254964778577 + 0.014485754653383986954511687511 952911791*I 1 -1.5131862500082280763797125336624298485 [1000000.1666388335691352075574126835736, 1000000.34122144715793575857838503 19295] 1 1 1 0.076089069738227100005564558379927322311 + 2.805102101019298955393836716564 9402365*I 0.35680023085607338253958791048419572104 + 0.2865058490958361032920930146630 7416106*I 2.8779618092784033552510785741350134852 - 3.20677107131839892349341182891067 85713*I 13.984136743052297859345288988593372806 [10000000000.060634346791852395529419686, 10000000000.2802888360631074507330 42071, 10000000000.706504823144940410068588999] -3.3628394875307279431468068941674059969522623227893924898762756706441687515 8819106852623169915859128980009964067917531298554248969488287720283539487138 8543655825172651469920831519548333876150450097514939775374495 + 1.4072345596 4644788597958345449042453953433814808264924606940806402759094591362213545397 6152349595886342743572827458569832031767124277015278973838180351157007785818 804527980391484513559518570029483903463331055993*I 1 2.87796180927840335525107857413501348521557766481787105464676053932551251013 7616712547593855783896859877673917990256648173190595961624700476582721268164 944058782596478765928958201301365228450329863062081287181514 - 3.20677107131 8398923493411828910678571268820710905051633042442235171857024788297021860034 9936904240515182308339314409380625565273153189823978600670227223840065075972 39376037223094497325610395017987063951532653360*I 9999999999.87045283720585036281979993246841066068865757621348928085251420319 8336184844654380593530617154043979229824398282672196298319600882759917195579 807525605847121652433142642149083167876322539670234730609681 -670 -0.24452956450059646211756764506374152336 + 0.177502224994834086574778142027 93579271*I -0.16174255689109486582810946079811517860 - 0.150343680121932832206370006185 18048616*I 0.35680023085607338253958791048419572104 + 0.2865058490958361032920930146630 7416106*I 5.6893586210266321006968470587696024024 + 5.45718211686616499470392530022579 88908*I -0.16174255689109486582810946079811517860 - 0.150343680121932832206370006185 18048616*I 1.5904730146408154358014826984773095425 + 3.18461240739082232717075088411728 10146*I 1.5904730147039050392643197795700858739 + 3.18461240613211320693078227868605 86928*I 0.80951559114176240190748342625727921182 + 0.5718391494453004505140740052681 5400941*I 0.80951559108432602486455475557719284577 + 0.5718391488777221855336789280388 6630411*I -0.31012268957597578584514782373814764042 - 0.278848346403810481375951506963 74114403*I -0.31012268895497010300278766022539157486 - 0.278848346828259563922200496219 08028760*I Total time spent: 20143 pari-2.17.2/src/test/32/pol0000644000175000017500000001406614676526175013725 0ustar billbillMod(0, 3) Mod(0, 3) Mod(0, 3) Mod(0, 3)*y^15 + O(y^16) Mod(0, 3)*x^15 + O(x^16) Mod(0, 3)*x^4 + O(x^5) y x x y + O(y^17) y + O(x^16) y + O(x^5) 0 0 0 y^-1 + O(y^15) 1/y + O(x^16) 1/y + O(x^5) y x x y^-1 + y + O(y^15) ((y^2 + 1)/y) + O(x^16) ((y^2 + 1)/y) + O(x^5) y^2 + 2*y + 3 x^2 + 2*x + 3 3*x^2 + 2*x + 1 1 + 2*y + 3*y^2 + O(y^3) 1 + 2*x + 3*x^2 + O(x^3) 1 + 2*x + 3*x^2 + O(x^5) y^2 + 2*y x^2 + 2*x 2*x + 1 1 + 2*y + O(y^3) 1 + 2*x + O(x^3) 1 + 2*x + O(x^5) y^2 + 2*y + 4 x^2 + 2*x + 4 4*x^2 + 2*x + 1 1 + 2*y + 4*y^2 + O(y^3) 1 + 2*x + 4*x^2 + O(x^3) 1 + 2*x + 4*x^2 + O(x^5) y^2 + 2*y - 4 x^2 + 2*x - 4 -4*x^2 + 2*x + 1 1 + 2*y - 4*y^2 + O(y^3) 1 + 2*x - 4*x^2 + O(x^3) 1 + 2*x - 4*x^2 + O(x^5) 2*y^2 + y 2*x^2 + x 2*x^2 + x y + 2*y^2 + O(y^4) (y + 2*y^2 + O(y^4)) + O(x^16) (y + 2*y^2 + O(y^4)) + O(x ^5) 2 2 3 y + 2 y + 2 2 + x + O(x^2) 1 1 x + 2 1 z y x^2 + x + 1 -x^3 - 2*x^2 - x + 1 [4, 0, 0, 0, -2]~ x^2 - 2 [x^2 - 2, 6] x^2 + 1 [x^2 + 1, 1/2] 1 x^2 + 1 1 1 1 2 0 0 0 [0 -1/2] [1 0] 2*x^2 + x + 1 6*x^3 + 2*x^2 1 1:x^8 + 14*x^7 + 49*x^6 + 24*x^5 + 178*x^4 + 70*x^3 + 144*x^2 + 120*x + 25 2:x^8 + 7*x^7 + 49/4*x^6 + 24/7*x^5 + 29/2*x^4 + 35/4*x^3 + 144/49*x^2 + 30/ 7*x + 25/16 3:Mod(1, 11)*x^8 + Mod(3, 11)*x^7 + Mod(5, 11)*x^6 + Mod(2, 11)*x^5 + Mod(2, 11)*x^4 + Mod(4, 11)*x^3 + Mod(1, 11)*x^2 + Mod(10, 11)*x + Mod(3, 11) 4:x^8 + (8*a + 3)*x^7 + (6*a^2 + 10*a + 5)*x^6 + (a^3 + 8*a^2 + 8*a + 2)*x^5 + (4*a^4 + 6*a^3 + 9*a^2 + 10*a + 2)*x^4 + (5*a^4 + 2*a^3 + 8*a^2 + 7*a + 1 0)*x^3 + (2*a^4 + 5*a^3 + 4*a^2 + 2*a + 2)*x^2 + (a^4 + a^3 + 6)*x + (4*a^4 + 3*a^3 + 10*a^2 + 2*a + 8) 5:x^8 + x^6 + b^2*x^4 + b^4*x^2 + (b^8 + b^6 + 1) 6:Mod(1, y^3 - y - 1)*x^8 + Mod(8*y + 14, y^3 - y - 1)*x^7 + Mod(28*y^2 + 98 *y + 49, y^3 - y - 1)*x^6 + Mod(294*y^2 + 350*y + 80, y^3 - y - 1)*x^5 + Mod (805*y^2 + 680*y + 668, y^3 - y - 1)*x^4 + Mod(786*y^2 + 2238*y + 1106, y^3 - y - 1)*x^3 + Mod(2125*y^2 + 1535*y + 706, y^3 - y - 1)*x^2 + Mod(738*y^2 + 1626*y + 1232, y^3 - y - 1)*x + Mod(425*y^2 + 521*y + 184, y^3 - y - 1) 7:Mod(1, 7*y^3 - y - 1)*x^8 + Mod(8*y + 14, 7*y^3 - y - 1)*x^7 + Mod(28*y^2 + 98*y + 49, 7*y^3 - y - 1)*x^6 + Mod(294*y^2 + 302*y + 32, 7*y^3 - y - 1)*x ^5 + Mod(745*y^2 + 200*y + 248, 7*y^3 - y - 1)*x^4 + Mod(318*y^2 + 6462/7*y + 1478/7, 7*y^3 - y - 1)*x^3 + Mod(8509/7*y^2 + 2495/7*y + 1294/7, 7*y^3 - y - 1)*x^2 + Mod(13302/49*y^2 + 143046/343*y + 78800/343, 7*y^3 - y - 1)*x + Mod(59837/343*y^2 + 54281/343*y + 12532/343, 7*y^3 - y - 1) 8:Mod(1, y^3 - y - 1)*x^8 + Mod(8/3*y + 14, y^3 - y - 1)*x^7 + Mod(28/9*y^2 + 98/3*y + 49, y^3 - y - 1)*x^6 + Mod(98/3*y^2 + 2702/27*y + 704/27, y^3 - y - 1)*x^5 + Mod(6685/81*y^2 + 4780/81*y + 5296/27, y^3 - y - 1)*x^4 + Mod(80 06/243*y^2 + 68018/243*y + 25886/243, y^3 - y - 1)*x^3 + Mod(94033/729*y^2 + 65063/729*y + 112366/729, y^3 - y - 1)*x^2 + Mod(57226/2187*y^2 + 274114/21 87*y + 323060/2187, y^3 - y - 1)*x + Mod(120569/6561*y^2 + 98495/2187*y + 18 2168/6561, y^3 - y - 1) 9:Mod(1, 7*y^3 - y - 1)*x^8 + Mod(8/3*y + 14, 7*y^3 - y - 1)*x^7 + Mod(28/9* y^2 + 98/3*y + 49, 7*y^3 - y - 1)*x^6 + Mod(98/3*y^2 + 2654/27*y + 656/27, 7 *y^3 - y - 1)*x^5 + Mod(6625/81*y^2 + 3460/81*y + 4876/27, 7*y^3 - y - 1)*x^ 4 + Mod(6698/243*y^2 + 414002/1701*y + 127898/1701, 7*y^3 - y - 1)*x^3 + Mod (613057/5103*y^2 + 370439/5103*y + 741442/5103, 7*y^3 - y - 1)*x^2 + Mod(254 1982/107163*y^2 + 75020926/750141*y + 92863436/750141, 7*y^3 - y - 1)*x + Mo d(36748685/2250423*y^2 + 30522647/750141*y + 57101732/2250423, 7*y^3 - y - 1 ) 10:Mod(Mod(1, 11), Mod(7, 11)*y^3 + Mod(10, 11)*y + Mod(10, 11))*x^8 + Mod(M od(8, 11)*y + Mod(3, 11), Mod(7, 11)*y^3 + Mod(10, 11)*y + Mod(10, 11))*x^7 + Mod(Mod(6, 11)*y^2 + Mod(10, 11)*y + Mod(5, 11), Mod(7, 11)*y^3 + Mod(10, 11)*y + Mod(10, 11))*x^6 + Mod(Mod(8, 11)*y^2 + Mod(5, 11)*y + Mod(10, 11), Mod(7, 11)*y^3 + Mod(10, 11)*y + Mod(10, 11))*x^5 + Mod(Mod(8, 11)*y^2 + Mod (2, 11)*y + Mod(6, 11), Mod(7, 11)*y^3 + Mod(10, 11)*y + Mod(10, 11))*x^4 + Mod(Mod(10, 11)*y^2 + Mod(7, 11)*y + Mod(10, 11), Mod(7, 11)*y^3 + Mod(10, 1 1)*y + Mod(10, 11))*x^3 + Mod(Mod(4, 11)*y^2 + Mod(6, 11)*y + Mod(1, 11), Mo d(7, 11)*y^3 + Mod(10, 11)*y + Mod(10, 11))*x^2 + Mod(Mod(5, 11)*y^2 + Mod(1 , 11)*y + Mod(9, 11), Mod(7, 11)*y^3 + Mod(10, 11)*y + Mod(10, 11))*x + Mod( Mod(4, 11)*y^2 + Mod(9, 11)*y + Mod(7, 11), Mod(7, 11)*y^3 + Mod(10, 11)*y + Mod(10, 11)) done Mod(-6, y^2 - 2)*x^2 + Mod(48*z, y^2 - 2)*x + Mod(480*z + 600, y^2 - 2) 1.4284266449676411750 1.4142277045794296914 "t_INT" [1.6967749516455178867147127964496742725 E-78 + 6.27680359220261705581969849 48534498009 E-40*I, 1.5000000000000000000000000000000000000 + 1.593167581732 6095290002105566876736750 E39*I]~ 130 0 [-33.101587848499262154605410574994530421 + 0.E-38*I, -10.736573227507425745 631075405481359740 + 0.E-38*I, -9.7213331444556232538183293505003978082 + 0. E-38*I, 26.466020671197515570740051488474260276 + 0.E-38*I, 27.0934735492647 95583314763842502027693 + 0.E-38*I]~ [0.E-38 + 0.E-38*I, 0.E-38 + 0.E-38*I, 0.E-38 + 0.E-38*I, 0.E-38 + 0.E-38*I, -0.50000000000000000000000000000000000000 - 6.30476010645924576561431291726 65561499*I, -0.50000000000000000000000000000000000000 + 6.304760106459245765 6143129172665561499*I]~ [-2.8894111933973646917594759197737980990 + 0.E-38*I, 0.94470559669868234587 973795988689904951 - 3.4010023796961396823552931254901620587*I, 0.9447055966 9868234587973795988689904951 + 3.4010023796961396823552931254901620587*I]~ 0 Mod(Mod(1, 3), Mod(1, 3)*a^2 + Mod(2, 3))*x^3 Mod(Mod(0, 3), Mod(1, 3)*a^2 + Mod(2, 3))*x^-2 + O(x^-1) *** at top-level: polrootsbound(Pol(0)) *** ^--------------------- *** polrootsbound: zero polynomial in roots. *** at top-level: polrootsbound(1) *** ^---------------- *** polrootsbound: incorrect type in polrootsbound (t_INT). *** at top-level: Pol("") *** ^------- *** Pol: incorrect type in gtopoly (t_STR). *** at top-level: (1/x)%x *** ^-- *** _%_: impossible inverse in QXQ_inv: Mod(0, x). *** at top-level: poltomonic(Pol(0)) *** ^------------------ *** poltomonic: zero polynomial in poltomonic. Total time spent: 10 pari-2.17.2/src/test/32/concat0000644000175000017500000000255414567450071014367 0ustar billbill [1 2 5] [3 4 6] [1 2] [3 4] [7 8] [1 2 5] [3 4 6] [7 8 9] [1 2 4] [0 3 5] [0 0 6] [1 0 0] [2 3 0] [4 5 6] [5 0 7 8] [6 0 0 0] [1 2 9 0] [3 4 0 9] [;] "x2" [1] [;] *** at top-level: concat([;],[1]) *** ^--------------- *** concat: inconsistent concatenation t_MAT (0 x 0) , t_VEC (1 elts). [1] [;] *** at top-level: concat([1],[;]) *** ^--------------- *** concat: inconsistent concatenation t_VEC (1 elts) , t_MAT (0 x 0). [1, 2] [1, 2] [1 2] *** at top-level: concat(1,A) *** ^----------- *** concat: inconsistent concatenation t_INT , t_MAT (2 x 2). [2 1] *** at top-level: concat(A,1) *** ^----------- *** concat: inconsistent concatenation t_MAT (2 x 2) , t_INT. [1, 2] [1, 2, 1] *** at top-level: concat([1,2],[1,2]~) *** ^-------------------- *** concat: inconsistent concatenation t_VEC (2 elts) , t_COL (2 elts). [2 3] [1 0] [0 1] [1, 2] [3, 1, 2] [2, 3]~ [2, 3, 1]~ *** at top-level: concat([2,3]~,[1,2]) *** ^-------------------- *** concat: inconsistent concatenation t_COL (2 elts) , t_VEC (2 elts). [;] [1 2] [3 4] [1 2] [1, 2] [1 2] *** at top-level: concat(List([])) *** ^---------------- *** concat: domain error in concat: vector = List([]) Total time spent: 0 pari-2.17.2/src/test/32/graph0000644000175000017500000000544114567450071014217 0ustar billbill echo = 1 ? plotinit(0,500,500) ? plotmove(0,0,0);plotbox(0,500,500) ? plotmove(0,200,150) ? plotcursor(0) [200, 150] ? write("pari.ps",plotexport("ps",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)) ? write("pari.ps",plotexport("ps",[0,20,20])) ? write("pari.ps",plothexport("ps",x=-5,5,sin(x))) ? write("pari.ps",plothexport("ps",t=0,2*Pi,[sin(5*t),sin(7*t)],1,100)) ? write("pari.ps",plothrawexport("ps",vector(100,k,k),vector(100,k,k*k/100))) ? 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)") ? write("pari.ps",plotexport("ps",[0,10,10])) ? if(getheap()!=HEAP,getheap()) ? print("Total time spent: ",gettime); Total time spent: 5 pari-2.17.2/src/test/32/hyperell0000644000175000017500000012040514567450071014740 0ustar billbill[665, -3419; -1691, -661] 1:1:x - 4 [-551, -685; -665, 555] 1:2:x - 4 [-3249, -456, 1482, 1194; -1824, 2926, -986, 2427; 1007, 342, 2972, 3051; -9 69, 779, -2532, -2648] 2:1:x^2 - x - 20 [-2052, -2204, 2169, 1721; 3021, 57, 1328, 505; -399, 1805, 615, 1230; 1387, 2128, 1724, 1385] 2:2:x^2 - 5*x - 20 [1387, -1748, -2161, 3145; -2166, 1729, -1313, -3395; -3002, -3401, 3039, 47 8; 2128, 2318, 3338, 705] 2:3:x^2 - x - 60 [-3420, 1197, -2807, 3377; 2717, 1520, 968, 3285; 2888, 3249, 1622, 3139; -1 9, -2261, -358, 273] 2:4:x^2 + 5*x - 20 [-1406, -2793, -874, 800, 2523, 763; -1957, -1273, -2508, 2679, -1763, 967; 779, 285, 2280, -1577, 2489, 989; 931, 1691, 2166, -2755, -3283, -197; 1292, 2071, -2128, -1938, -3060, -2115; -228, 2318, -760, -620, -2389, -645] 3:1:x^3 - 55*x - 68 [-2451, -2679, -874, -131, -3342, -574; 1862, -3230, 1539, -2546, 1633, 3333 ; 1558, -1121, 3363, 163, -3132, 1408; -1045, 247, 1102, 2812, -2759, -930; -2907, -1919, -1159, 2774, 332, -2658; 855, -304, 3211, -881, -1835, -821] 3:2:x^3 - 5*x^2 - 26*x + 128 [3173, -1368, 1425, 1919, 3223, 2152; -3059, 1653, -3249, -2314, 1090, -2749 ; -608, 1444, -2318, -627, -3127, -3265; 3021, -1539, -1045, -3249, 1285, -3 347; 2812, -684, -2660, 2950, -136, 519; -3135, 779, -3268, 278, -1326, 875] 3:3:x^3 + 2*x^2 - 51*x + 48 [1976, 2337, -2717, -1463, -2992, 2863; 931, -2850, -779, 836, 1223, -2256; 1273, -1900, -1596, -538, -1697, -2200; 2375, 2698, 722, 145, 580, 1205; 159 6, 1482, 2964, 2280, 2476, 2166; 1045, -3230, 2318, 1071, -106, -143] 3:4:x^3 - 8*x^2 + 7*x + 30 [3287, -114, 1995, -950, 396, -700; -703, -1634, 266, -2267, 134, 1704; -275 5, -2964, -2584, -855, 2259, 2148; -1406, 874, -342, 999, 1210, 1613; -1577, -627, -1919, -659, -1850, 1372; 2603, -1083, -589, 2268, 3092, 1783] 3:5:x^3 - x^2 - 38*x + 72 [1824, -3059, -418, -1911, 465, -715; -3116, 152, 1254, -217, 2763, 2332; -3 135, -1368, -2109, -2485, 1768, 1039; 722, 988, -722, -2995, 2187, 3408; -15 96, 3306, -2755, -808, 2074, -212; 2508, -2166, -874, 1648, -1452, 1048] 3:6:x^3 + 6*x^2 - 13*x - 42 [-3040, 2242, 3249, 1083, 3040, 1053, 1868, 3210; 19, -38, -2451, -779, 665, -1767, 1823, 1493; -3287, 1121, 1577, -3420, -190, 1349, -2373, -1299; 2812 , -1007, 988, 1064, 1064, -912, -1041, -1686; 2812, 171, 2280, 1805, -3392, -2299, -1425, 2551; -779, -2280, -893, -171, 1941, -3393, 3325, 1335; 3021, 589, -1824, 2907, -361, 1098, 2444, -2727; -2204, 2147, 1121, 3287, 3287, -1 885, -2961, -2073] 4:1:x^4 - 8*x^3 - 36*x^2 + 360*x - 464 [1919, -209, -2299, 2299, 1425, 1793, 847, 2972; -1539, 1729, -2299, 1292, 5 32, 3135, -983, 1940; 2660, 228, -3363, -2546, 665, -23, -1754, 2617; 1976, -152, 1900, -266, 2508, -2755, 124, -946; 1805, 209, 874, 513, -2422, -2401, 1938, 1792; -1387, 1938, 2660, -171, 2546, -1262, -2368, 1298; -3154, 2223, -1862, -152, 2541, -361, -1342, 115; -855, -1748, 3097, -1121, 3135, 1176, 220, -1842] 4:2:x^4 - 10*x^3 + x^2 + 144*x - 136 [-1520, 0, 0, -2850, 0, 0, -101, 0; 0, 1197, 0, 0, -3287, 0, 0, -1523; 0, 0, -665, 0, 0, 3419, 0, 0; 2964, 0, 0, -950, 0, 0, -2792, 0; 0, -2869, 0, 0, - 2061, 0, 0, 1572; 0, 0, 1691, 0, 0, 661, 0, 0; -1729, 0, 0, -1197, 0, 0, 246 8, 0; 0, 703, 0, 0, 164, 0, 0, 862] 4:3:x^4 + 8*x^3 - 21*x^2 - 116*x + 128 [1102, 722, 456, 703, 361, -2590, -3212, 962; 1425, 988, -3268, -1026, -1026 , 608, -265, 2342; 1805, -3268, -323, -2508, 2869, -3249, -1697, 1078; -2147 , 950, -3002, 2375, -3184, 2910, 2596, -475; 3135, 2603, -399, -2926, -2309, 628, 1410, -1843; -2489, -1387, 2736, 475, -3344, -2120, -3151, -732; 703, -2584, 1406, 665, 1596, 589, 735, -2130; 2413, 874, 2223, 2166, 1159, 1536, 1720, -458] 4:4:x^4 + 10*x^3 - 5*x^2 - 200*x - 208 [-342, -456, -57, -209, -382, 1444, 3159, -2685; 133, -3344, 1311, -2527, -2 375, 1413, 1763, -361; -817, 513, 3287, -1292, 2622, 3048, -388, -589; 285, -1786, 2166, 3325, 1121, 1708, -3101, -2844; 1159, -2489, -2090, 646, -2309, 1333, -349, 778; -3382, 1805, -1254, -1539, 926, 1642, -1070, -2014; -1197, -1235, 0, -1463, 2318, 1677, 715, -2014; -2907, 1216, 399, 2850, -988, -140 8, 1679, -2966] 4:5:x^4 - 8*x^3 - 41*x^2 + 246*x + 584 [-2698, 0, 0, -1007, 0, 0, -197, 0; 0, -475, 0, 0, 2314, 0, 0, -1232; 0, 0, 551, 0, 0, 685, 0, 0; 1292, 0, 0, -57, 0, 0, 1259, 0; 0, -1995, 0, 0, 522, 0 , 0, 608; 0, 0, 665, 0, 0, -555, 0, 0; 1121, 0, 0, 2926, 0, 0, -2887, 0; 0, -2926, 0, 0, 2205, 0, 0, -1270] 4:6:x^4 + 10*x^3 - 51*x^2 - 764*x - 1856 [76, 2831, 437, 2090, -3062, -2634, -1721, 1093; -2508, -171, 2812, -152, -2 907, -3177, 1368, 1388; 1824, 2280, -1007, 836, 1837, -3262, -1708, 3111; 19 95, 171, -3135, 2793, 3211, 3149, 1001, -1778; -2033, 1843, -2831, -2755, 21 56, -941, -1387, 971; -323, 2679, 2109, -1672, 2603, 42, 768, 506; 2641, 144 4, 2394, -3287, -2356, -2557, 2691, -1134; -1596, 19, -1900, 627, 1281, 455, 2885, 287] 4:7:x^4 - 8*x^3 - 17*x^2 + 156*x + 24 [2736, 1577, -1406, -2793, 289, 325, -1285, 2368; 2812, 3116, 1045, 1634, 71 3, 1294, -2128, 2717; 912, -2242, -2755, -646, 2422, 1759, 858, 2619; 1938, 475, 2755, -3116, 2478, -3091, -2712, -1620; -3173, 1767, 3192, -684, -712, 2526, 1555, 1133; -1843, -1482, 2907, -2850, -3173, 2044, -2064, -3086; -741 , -342, -589, -133, 1805, 1841, -2964, -723; 2071, 532, -1748, -3382, -1836, 134, -1887, 1661] 4:8:x^4 - 10*x^3 - 18*x^2 + 320*x - 430 [2280, 950, 2052, 2337, 931, -209, -119, 2583, 69, -77; 3268, 19, -133, 1596 , 1786, 1007, 1309, 1715, 295, -19; 3135, -2261, 1653, -608, -475, 2508, 196 8, 118, 3040, -1772; 1634, -608, -1881, 532, -1216, -1243, -3318, -665, -218 5, -2175; -2090, -1349, -3230, 2812, 76, 2260, 475, -1159, -266, 971; -2945, 1121, -874, 1482, 2147, 3078, 1558, -1672, -995, 3048; -475, 2964, 779, 437 , 2812, 2185, -3021, -1539, 2912, -516; 456, -3325, 1273, 1824, 1805, -1463, -1102, -2584, 997, -3184; 1387, -399, 760, 1881, -2147, 2850, 2527, -823, - 748, -1535; -1311, -874, -1235, 703, -133, -2014, -3363, 2073, 517, -1293] 5:1:x^5 + 8*x^4 - 47*x^3 - 356*x^2 + 361*x + 1596 [-2945, -1748, -2337, -2147, -912, -2698, 347, -1083, -819, -3230; -2223, -1 52, 779, 2261, -2945, 494, 475, -1855, -1596, -1749; -1121, -3382, -323, -16 15, 1938, -2166, -2455, -988, -1655, 1278; -2299, -1634, -2546, -1995, -3287 , -2728, -323, 963, 1596, 1203; -3382, 285, 3154, -1900, 684, 1824, -2286, - 2337, 325, 2036; -95, 1767, -2166, 2622, 2318, 1500, -3192, 1708, -1532, -31 93; -988, -3401, -190, 171, -2565, -323, 1071, -2869, -281, 6; -2299, -665, 1843, 1672, 703, 190, -2603, 612, -3213, -1109; 779, 2850, -1672, 1900, -307 8, 1596, 1729, 1146, -2156, -3305; 361, 2166, -1007, 1007, 1368, 2698, -475, -1387, -1160, -3155] 5:2:x^5 - 99*x^3 + 72*x^2 + 2085*x - 2968 [3382, 1045, -1653, -2964, 1273, -1273, -1401, 1778, -2778, 320; 2622, 437, 1672, 1520, 152, -38, 1140, 1722, 3117, 1714; -665, 2774, 2090, -2850, -2622 , -152, -1007, -2907, 475, 689; 1444, -437, 1957, 1881, -2717, 597, -1359, 1 17, 2140, 938; -2242, -3420, 1691, 171, 1615, 760, -342, -3177, 2212, -741; -760, -247, 456, -1482, 1881, -2698, -1406, -779, 1774, 111; 722, 2014, -222 3, -209, 1463, -953, -2167, 291, -2123, 1211; -2185, -3325, -1311, 266, -285 0, -2983, 2128, -931, -142, -190; 3268, 1748, 893, -2280, 1919, 1178, 703, 8 61, -1747, -1848; -3002, -2185, 1083, 1539, 817, -1330, 971, -2830, -1139, - 1861] 5:3:x^5 - x^4 - 103*x^3 + 40*x^2 + 2464*x + 1536 [-2812, 1425, -1767, -2907, -285, 1254, -1107, -684, 2568, 212; 133, 437, -5 13, -1482, -1007, 152, -3227, -1618, 1026, 19; 2945, -1140, 2166, -1349, 779 , -2375, -3230, -2786, 12, 3282; 2109, -209, -2527, 703, -2812, 3279, -2945, -1115, -232, 737; 1862, 114, 0, 1159, 3344, -1577, 2809, 570, -2183, 247; - 741, 114, -1729, -1102, -3154, 1805, 425, 2547, 373, 2318; 1026, 931, -456, -2375, 1045, -2774, 2394, 2506, -1318, -1853; -646, -2888, 1691, -1330, -127 3, 404, 304, 2793, -2027, 2906; 627, 1691, -171, 1881, -608, -1539, 699, -29 32, -1063, -1463; -3306, 589, 2736, -1216, 2128, 779, 2109, -341, -2455, -29 07] 5:4:x^5 - x^4 - 91*x^3 + 114*x^2 + 1761*x - 1496 [-988, 494, 1159, -817, -2052, -1273, 2769, -746, 1406, 3352; 3344, -171, -3 382, 437, 646, -2679, -2527, 1775, 464, -2196; -912, -969, -2394, 285, -1026 , 2755, -513, 3216, 1129, -3026; -532, -2318, 209, -1767, -3116, -3162, 2090 , 152, -1380, 836; -133, -2907, 285, -2432, -2318, -836, 1211, -2680, 594, - 551; 931, 1444, 817, 437, 1406, -1748, -149, 2705, -1926, -741; 2774, -2413, -2451, -171, 494, -399, 2565, -577, -1292, -224; 2546, 1596, 836, 1216, 167 2, -3401, 2660, 2893, -2640, -2569; -2052, 2223, -3306, 2793, -3097, -1760, -3230, -1697, 1010, -2546; 2926, -1805, -1653, -3287, 1634, -1710, -2141, -2 584, -2795, 2926] 5:5:x^5 - 8*x^4 - 68*x^3 + 500*x^2 + 1084*x - 6160 [-2869, -2793, -2242, 2565, -2831, 1216, -2703, 2285, 2188, 3021; -76, -2451 , 1311, -3059, 95, -95, -907, -1410, 2036, -76; -3268, 2603, 1672, 1843, -15 20, 19, -593, -3382, 1949, 1287; 133, 3078, 3268, -3401, 3192, 2234, -2584, -2647, -108, 700; -1615, -1843, 1596, -361, -2128, -38, 2812, 2186, -2508, 5 53; 2299, -874, 1254, 1368, -893, 1311, 323, 2830, 2121, -323; 3325, -988, - 3249, -1957, -2242, 228, -2689, 26, 935, -456; -931, 2698, 2546, 1330, 494, 1634, -3167, -1386, 2754, -1197; 2204, 2660, -3344, -513, 3040, 608, 2961, - 1469, -571, -2031; -437, -2736, -1045, 513, -836, 959, -2926, 294, -1805, -1 204] 5:6:x^5 - 2*x^4 - 62*x^3 + 36*x^2 + 838*x + 616 [-2147, 1957, 1805, -1824, 2907, 2185, -537, 948, -885, 437; -1007, 1767, -8 74, -3173, -2394, 3040, -1957, 1045, -849, -1538; -1938, 2109, 3363, -779, 2 394, -2812, 2687, 1221, -1957, 1021; -3192, -589, -1596, 2033, -2033, -1566, -1263, 3046, -1318, 3162; 323, 1672, -2679, -1938, -418, -2318, 1121, -2544 , 2525, -1786; -2052, -2090, 1273, -475, 2432, 1634, -1729, 2194, -2515, -26 55; -2679, 817, 152, -1387, -1862, 451, -123, 97, 1007, 195; 152, -2660, 171 0, 2907, -228, -152, -2132, -3104, -2861, -893; 2204, 1273, 1995, -1748, 513 , -1292, 646, -2324, 98, 1045; 1634, -1843, -3021, -1444, 1596, 3116, -2169, -2708, -342, -3108] 5:7:x^5 + 5*x^4 - 75*x^3 - 250*x^2 + 1321*x + 852 [-1121, -2622, -1691, -1311, -323, 743, -1401, -3097, 1354, 3224; 2679, 1881 , 950, -285, 2261, 2052, 1437, -1853, 14, 2410; 2375, 2660, -988, 608, -1406 , -3211, -2687, 2628, 390, 387; 2983, -1634, 2964, -3287, 1881, -581, 2926, -3173, 837, 2774; 1539, 456, -3249, 1064, -3363, -494, -2771, 769, 226, -295 3; 3002, 2774, 893, 304, 2546, -266, -1744, 2289, -601, 1120; -3211, 1710, - 2394, -1520, -3268, -152, 2109, -43, 171, -1368; 304, 38, -2964, -2147, -608 , 475, 1971, 2393, 2158, -2506; -266, 3078, -1767, 1672, -2223, 474, -2852, 139, -620, 238; 1786, 76, -2565, 456, -285, 2755, -2580, 3381, -2907, 3267] 5:8:x^5 - 5*x^4 - 57*x^3 + 254*x^2 + 372*x - 1168 [2736, -2014, -1710, -1596, -2679, 380, 1230, -1927, 1103, 598; 1767, 2546, -95, -589, -969, -3082, -2873, -2034, 2335, 617; 931, 1387, 1596, -2698, 305 9, 1007, 2850, -1428, -3097, -1821; -190, -1577, 646, -2204, -2052, 2652, 25 51, -135, -293, -2585; 1881, -1729, 285, -1083, -722, -171, 2359, 427, -2748 , 128; -532, 2432, 1672, -1045, -418, -1767, -630, 1354, 3102, 1000; -1786, 1216, -760, -779, 494, 2755, -758, -2756, 855, 503; -1406, 1995, 2717, 1235, -1539, 1292, -2393, -2335, -954, 1981; -3230, 2508, 2945, 2413, 2546, -524, -794, 2846, 2304, -1845; -456, 3116, 3382, -2945, -3249, -285, 2136, 2806, -3167, -1398] 5:9:x^5 + 2*x^4 - 65*x^3 - 162*x^2 + 509*x + 986 [2736, -2869, -665, -1102, 817, 1525, 2355, -1020, -2647, 984; 1938, 2090, - 3097, 3116, -437, -2806, -1987, 1415, -3189, -103; -247, 3325, -2869, -1558, -2584, 842, 3428, 3405, 2335, -691; -3344, -2945, -3078, -323, -703, -2082, 2437, -2936, -3374, -1757; -1672, -1425, 1957, 152, 2394, -1520, 1561, 2967 , -455, -3110; 1786, -1159, -1843, -1045, 3306, -2565, 2040, -359, -109, 117 0; -1083, 2508, -3078, 1520, 988, 437, 2997, -70, 222, 78; 2242, -1159, -330 6, 2451, -1330, -2394, -219, -4, 1904, 366; -342, 323, 874, -1482, -2109, -1 14, 2978, -40, -2981, -2838; 3154, 893, -1026, 703, 361, -952, 1844, 1229, - 3319, -1465] 5:10:x^5 - 10*x^4 - 25*x^3 + 398*x^2 - 443*x - 1482 [2603, 228, -589, -3363, 1805, -3021, -1767, -2261, 3002, 1698, 2616, -2384; 2318, 2375, -380, -1634, 1254, 798, 2147, -494, -2351, -1026, 2860, 27; 136 8, -1083, -1463, -513, -1178, 38, -2438, 722, 389, -494, -604, -2234; 2337, -475, 2166, -3097, -3059, 931, 736, -2356, 1517, -38, 2427, 2470; 2850, 513, 3040, 2546, -2755, 1102, -2223, 228, -598, -57, -1039, -893; 1843, -2185, 5 70, 1349, 1026, -2546, 893, -1539, 2006, -1995, 2536, 2394; -855, -2793, 294 5, -1216, -1805, -2204, -19, 3135, 2641, -2546, -1039, 2856; -1007, 2641, 13 87, 475, 418, -2945, -1577, 570, 19, 1954, -1669, -2397; 893, 2147, 3382, 28 88, -1862, 1482, 2584, -2771, 3230, -83, 2451, -2872; -1824, 1406, -1900, 28 88, -836, -1406, -969, -2103, -38, -1382, -2318, 2065; -418, -608, 2698, 152 , -1330, 1786, -76, -2152, 3268, -1674, 2717, -1878; -1539, 532, 2147, -2850 , -285, -2565, -1710, -1520, -1444, 2711, -437, -225] 6:1:x^6 - 8*x^5 - 83*x^4 + 742*x^3 + 547*x^2 - 11058*x + 10184 [-2812, 399, -2261, 1121, -1824, 2299, -1577, -855, -893, 597, 785, 2584; 24 13, 133, -1672, 2717, -608, -988, -2736, 2164, -2342, -1482, -495, 2995; 912 , 2071, 285, 608, -2204, -3287, 3369, 912, -2888, -455, -2615, -3135; -1957, -2831, 3116, -893, 2223, -114, -418, -1881, 1994, 532, 957, 3109; 2717, -33 44, -684, -2185, 2090, 1159, -2429, 1539, -2774, -1345, -2279, -1330; 2793, 1938, 1007, -3287, -1463, 2394, -665, -2774, -2705, 228, 779, 2368; 1083, -2 147, -1824, -2071, -2945, -152, 1862, 190, -3154, 1246, -628, -709; -2109, - 2964, 209, -3420, 1805, -3021, -1501, 1387, 2081, -2714, -1387, 2870; -1938, -1425, -969, 1178, 684, -3268, -2660, -269, -2261, 399, -902, -1591; -2052, 2736, 2584, 19, -1805, -1311, -3363, -2280, 2965, -2711, -2413, -1917; 1976 , 2869, -3059, 266, 1406, 3287, 1995, -2969, 2774, -3135, -1629, -3312; 323, -2242, -1425, -76, 2831, 2869, -3344, -2318, -2660, 79, -2242, 2165] 6:2:x^6 - 10*x^5 - 71*x^4 + 900*x^3 - 193*x^2 - 14820*x + 25460 [2280, 2926, 1102, -2736, 1995, 893, -3154, 3325, 624, 2295, -2008, -1121; 1 729, -323, -1938, 1634, -3420, -2261, -2793, 838, 1610, -1045, -760, 1620; 1 444, 817, -570, 494, -2470, -2147, 1887, -551, 3192, 66, 53, -3060; 2622, -1 976, 2527, 1178, -1672, 1178, 2774, -1007, -2360, 2807, 1335, -1995; 2546, - 1615, 2337, 1672, -2451, 1881, -1596, 12, -1874, -2508, 2489, 1691; 2413, -2 717, -266, -2926, -76, -3173, 1977, -1710, 247, 247, 2172, 2199; -2983, 95, 171, -1729, -1463, -2014, 2508, -2223, -2603, -1208, -2597, 1723; -2337, 456 , -1653, -1634, -817, 1520, 152, -2071, 3213, -415, -285, -703; -722, 1691, 874, -3344, -2527, 2888, 1729, -2302, 2527, -1197, 1928, -1570; -190, -1976, -1102, 1957, 2128, 342, 2489, 3135, -3401, -3062, 2919, -1266; 2774, 2185, 912, 1615, -855, -646, -1729, -1957, -1756, -2541, -3230, 1862; 2755, 1957, -437, -76, -2432, -1805, 1710, 718, 3420, -228, 604, -474] 6:3:x^6 + 2*x^5 - 118*x^4 - 184*x^3 + 4023*x^2 + 4302*x - 35264 [646, 532, -1292, 684, 684, -437, 2223, 228, -2229, -2584, 602, 303; 1691, 3 002, -1843, -779, -2774, 76, 190, -2565, 556, 1635, -969, -408; -2223, -2318 , 0, 912, 1900, 1406, -1355, -2204, 2451, 2710, 2781, 2527; -3097, 1387, -30 4, -1311, 532, -2793, -2565, -1243, -3154, -2622, 214, -532; -2508, -266, -1 52, 2489, -1615, -2128, -1653, -684, 298, 1805, -22, 475; 152, 3325, 2926, - 285, 2432, 3230, -1900, -152, -623, -1221, -1786, 3089; 228, -2546, -1140, 1 102, 3211, 1748, -721, 2033, -1292, 1823, -2613, 2590; -95, 418, 589, -2109, -304, -2508, -608, 2406, 1178, -1979, 875, 2489; -2090, -893, -1672, -1083, -3363, 2622, 2432, -3075, 2390, -1634, 2858, -988; -2584, 152, -3173, -3097 , -1634, 646, 3420, -2831, -2994, -1891, -1767, 1447; -475, -2033, 912, -332 5, 2907, 2261, 1387, -1140, -1558, 2759, -3039, -1586; 1292, -418, -3135, 22 04, 513, 3230, -2318, 285, 2698, 3416, -2556, -3097] 6:4:x^6 - 95*x^4 - 2*x^3 + 1927*x^2 - 720*x - 2992 [2603, -646, -3325, -1387, 1786, 2337, -1368, 3060, -2476, -190, -728, -503; -1254, -1805, 2888, -1691, 1102, -1102, 1007, -1900, -3206, 1970, 2130, -74 1; 1957, -1197, -817, 1026, 323, -3192, 1039, 969, 2071, -2641, 3357, -2109; 855, 2679, 779, -1748, 2983, -2603, 1862, -1520, -1221, -2217, -2261, 2357; 627, -646, -2907, 2527, 2660, -1045, 3325, 475, -855, 234, 70, 1349; -1653, 95, -2622, -1957, -2337, -2166, -1558, -279, 3291, -1596, 2640, 2052; -1482 , -3230, 3135, 1216, -2375, -608, 722, -1197, 775, 1408, 2945, -944; 3325, 2 85, -3230, -912, -1463, 1976, -3284, 2280, 3135, -744, 3303, 3059; -2489, 26 22, 1482, 3401, -475, 57, 304, 934, -1168, 1339, -665, 1256; -2356, 2318, -2 204, 722, 2793, -323, 1235, -1938, 1178, 1038, 1166, 1254; -3173, 836, 1311, 2470, 1824, -3078, -1026, -439, -114, -1349, -339, 361; -2584, -323, -2052, 1330, 323, -133, 1805, 874, -1008, -895, 1691, -1265] 6:5:x^6 + 5*x^5 - 112*x^4 - 583*x^3 + 2693*x^2 + 16639*x + 17196 [2318, 2166, 2147, -1957, 779, -817, -3268, 2348, -3235, 3134, -671, 171; -1 349, -2736, 190, -1045, 3287, 1938, -2147, 3137, -2180, 703, 2622, 399; 3059 , -722, -2926, -1444, -133, -247, -2495, -2166, 2185, 836, 1159, 798; -2109, 1805, -1330, 114, 57, 1672, -1178, 437, 3135, -193, 2500, 2337; 1520, 684, 3116, 456, -2869, -684, 2698, -2470, -3040, -1855, -2277, 810; 247, 247, 266 0, 2166, 1140, -1197, -2147, -95, 159, -2405, -2934, -3117; 1406, 2850, 2964 , 133, 1007, 2888, 399, 2724, 2886, -2358, -3229, -3281; -2014, 551, 1843, 7 98, 2147, 1919, 2584, -778, -943, -2872, -1007, -1387; 703, -798, -931, 2223 , 2698, -1881, 62, -1213, 1368, 1501, -3135, 3325; 2451, -513, 2546, 2527, 1 425, -1919, -1805, 2622, 228, -1215, -3230, -2109; 1862, -1615, 2337, -76, 1 520, 2831, 3192, 2508, -209, -1524, -1046, 2793; 3040, -2166, -361, 608, 893 , -741, -1653, -1919, -1203, 1637, -2025, 1703] 6:6:x^6 + 6*x^5 - 76*x^4 - 405*x^3 + 1226*x^2 + 6194*x + 3960 [-1197, -1064, -2147, 3344, 1520, -1577, -2185, 209, 855, 2546, 925, 2035; 5 32, -247, 2584, 684, -1083, 3192, 2394, 2508, 2361, -1180, 2228, -2863; 1672 , -1140, -893, 380, -1843, 3344, 1115, -1802, 1524, -1134, 2685, 1786; 2869, -551, 2413, 3249, 2888, 1235, 2964, -2559, -662, -2011, -2505, -1064; -1862 , 2964, 3173, -2356, 2356, 57, -1083, -2090, -3247, 2960, 1197, 3363; -2641, 1786, 1805, 380, -3040, -1520, -1292, 2014, 494, 2300, -2166, -1102; 2185, 2166, -1026, 1083, 646, -2223, -1064, -2242, 1786, 2090, -2698, -355; -1748, 1615, 988, 988, -494, -2261, 2052, 2660, 1786, -2454, -1042, 1428; -3287, - 342, 1805, 2451, -3287, 3344, 646, -1118, 626, -865, -1005, -3420; 2508, -57 , 19, -1273, 3059, -1368, 3066, -2322, -2275, 2661, 1063, 2565; 399, -1064, 2261, 2394, -38, 798, 2109, 2609, -1526, 3047, -2660, 1786; -1938, -304, 475 , -1330, 1083, 1501, 3325, -912, 890, -2701, 190, 2888] 6:7:x^6 - 114*x^4 + 27*x^3 + 3176*x^2 - 1940*x - 16768 [-1976, 3059, -418, -722, 361, -2622, -2926, -2755, -1974, -415, -2616, -252 7; 741, 760, 247, -570, -2318, -152, -2375, 788, 109, 2147, 2977, -61; 1520, 2185, -627, 532, 874, -3211, -2616, 133, -1847, 174, 323, 1891; 3021, 760, 2641, -114, 323, -3192, -2033, 737, 1577, -1290, -1264, -1786; 1634, 2147, - 2109, -228, -3002, -798, 475, 190, -1989, -456, 665, 2341; 2850, 817, -1444, 3287, 2375, -3420, -3306, 3211, 1116, -2349, 247, -2565; -3306, -2052, -304 0, -3287, 1349, -2204, -3420, -989, -2546, 2613, -622, 3205; 1425, 760, -104 5, -2679, -2033, -874, 3002, 323, 2667, -1726, 1140, 475; -570, 2470, -2090, -2413, -1102, -95, -1425, -3233, -210, 272, -2589, -570; -3363, 1387, -1691 , 1710, -3154, -2850, -2128, 3024, 3011, 1273, 3306, -900; -1596, 2546, -212 8, -2945, 1862, -1767, -997, 323, -2742, -1236, -2166, 2227; -1007, -2622, 2 109, 304, -2679, -855, 3154, -2746, -1292, 1495, 2477, -1140] 6:8:x^6 + x^5 - 116*x^4 - 39*x^3 + 3557*x^2 - 849*x - 19852 [-1767, -3192, 1596, -1463, 779, 665, 1216, -2439, 2641, 428, -3103, -2681; 2736, -1520, -1520, 2109, 1064, -2318, 1577, -2775, 1829, 1216, -2635, -2891 ; 95, -1672, -2337, 342, -2128, 1843, -2381, -1140, -1451, 2584, -1229, -108 ; -380, -2736, -2489, -1691, 2109, -1596, -2869, -475, 2452, 2599, -2109, 38 ; 1178, -1064, 1368, 2717, 133, 2413, -3097, 24, 3038, 2417, -1406, -2835; - 76, 3420, -2014, 76, -931, 304, 1824, -597, 266, 1491, -1543, 793; 817, -475 , -361, -1672, 2356, -646, -399, 3325, -1194, 2584, -530, 1982; -2869, -2470 , 418, 589, -2470, 3154, 2622, -1748, 530, 453, 2033, -2940; 57, 1843, -190, -1501, 1159, 2204, -38, 1637, 1449, 1692, 3135, -86; -2242, 2166, -2318, -2 280, 893, 2584, 3420, -2511, -399, -723, 539, 3050; -3306, -1121, -2432, -14 06, 2926, 3173, 2033, 1099, -3247, -1235, -1594, -2973; 2508, 2033, 627, 340 1, 836, 2850, -3143, -950, 2476, 1672, 1661, 3032] 6:9:x^6 + 2*x^5 - 115*x^4 - 108*x^3 + 3251*x^2 - 2214*x - 7692 [-1311, 1900, 817, 3363, 1102, -2565, 532, -1552, -494, 57, -784, 3099; -218 5, 2185, -2945, 2204, 1881, -3382, 2337, -2299, 3377, -274, 478, -541; 209, 1843, -836, 1197, -2375, -1216, 2818, 1446, 613, 2552, 2669, 2859; 0, -2071, -1520, -2242, -3097, -494, -1387, 732, 1129, 1520, 691, 2788; 3325, 2033, 2 337, 190, -1786, 247, -456, 1558, -1577, 1905, 859, 2470; -380, 684, -1292, -3268, -2698, 2337, 1995, 1951, -2589, 1897, -274, 447; 1444, 0, -1900, -165 3, -3002, 1805, -1672, -139, -3248, 931, -2953, 3013; -1729, -1900, -912, 15 2, -988, -3059, -2451, -532, -665, 1884, -381, 1938; 2318, 2147, 798, -190, 817, -1178, -2793, 2429, 2116, -391, 2523, 2247; -2850, 3097, 3268, 2337, -3 059, 209, -856, 2, -562, -3014, -67, 896; 2812, 1463, -190, -2641, 2850, 119 7, 2166, -3131, -1121, -2242, -1188, -209; -1216, -722, -1311, -1349, -1425, 1026, 2261, 779, 2647, 1628, 2660, -924] 6:10:x^6 + 8*x^5 - 84*x^4 - 640*x^3 + 1637*x^2 + 10084*x - 11062 [-1729, -2223, 1387, -1311, 2812, 1444, -192, 1488, -2970, 2028, -313, -2625 ; -266, -2850, -798, 2356, 646, -3040, 1102, 722, 1392, 2701, -1052, -1636; 1995, -722, -969, 1501, 2679, 1273, 3224, -847, -2124, 614, -2278, 731; 1102 , -304, 2603, 703, 2242, 2204, -2261, 713, -2736, 1952, -627, -3309; -38, 39 9, -1710, -3078, -3230, 1634, 1976, -3189, 466, 1432, 2741, -3022; -2299, -7 22, 703, -1501, 874, 608, 3116, 2412, -1064, 834, 2955, -2323; -1786, 2204, -1539, 3135, 3230, -1672, 3116, -1076, -702, -1054, 314, 506; 133, 1083, -30 78, -2014, 2242, 2470, -2052, -1720, -171, 2203, -1534, 2401; 513, 1501, 315 4, 2907, -2185, -2527, 2964, 1827, 3000, 2238, 854, -409; -228, -2147, -323, -2451, 1311, -2793, -1045, -2362, 1254, -166, 3179, -1441; 2698, -342, 1843 , -2793, -1140, 2584, 494, -1216, 2916, -2011, 2769, -2814; -513, 684, 190, -3040, 931, 2679, -506, -2801, 2676, 2692, -2641, 460] 6:11:x^6 + 8*x^5 - 89*x^4 - 750*x^3 + 1343*x^2 + 14698*x + 9316 [0, 2128, 3344, 2014, 38, 418, -1384, -3229, -1401, 1363, 679, 725; 171, 210 9, -722, 1349, -171, 1140, -851, 3367, 693, 447, -3170, 192; -2128, 95, -342 , 76, 3135, -228, 500, 2871, -2444, -689, 160, 2412; -1767, 285, -2926, -178 6, -1615, 2983, 1786, -505, 2346, -2986, -1899, 1090; -2869, 608, 209, 1634, 1330, 779, -228, 2345, 2365, -1565, -745, -75; -38, 1919, -1805, 95, 2926, 2546, 931, 2169, 2775, -1887, -2335, 3289; 2489, 418, -361, 1672, -1425, -23 37, -3325, 2462, 2328, -1295, -2013, 2604; -665, 2470, -475, 2945, 608, -296 4, 969, -920, 2201, -906, -3023, 1981; 2204, 722, 2299, 665, 988, -3116, 817 , -1637, -2098, 2041, 1853, -253; -1425, -1748, -1710, 1957, 2185, 1767, 228 0, 475, -2015, -2260, -3095, 527; 1786, 3116, 2508, -2318, 570, -2489, 494, 3154, -1090, -943, -808, -887; -1140, -3420, -2660, 437, 2242, 2717, -288, - 2645, 3011, 922, -2426, -1307] 6:12:x^6 + 2*x^5 - 117*x^4 - 240*x^3 + 3607*x^2 + 6492*x - 17696 [1972, 10034, -9344; 0, 29, 0; 9686, 8787, -1978] 1:1:x + 6 [9860, 0, 4428; 0, -29, 0; 6409, 0, -9858] 1:2:x - 2 [-1972, 9831, 11896; -9860, 3480, 2253; -9686, -10469, -1531] 1:3:x - 6 [-3451, -6003, -2987, -7284, 3268; 1943, 10846, -1624, 3009, 2180; 0, 0, 29, 0, 0; -9947, -10933, -10034, -2375, 9032; -11629, 2726, -4756, 8798, -5028] 2:1:x^2 + 8*x - 2 [9164, 0, -12006, 0, -4525; 0, -11455, 0, 6750, 0; 0, 0, -29, 0, 0; 0, -3770 , 0, 11464, 0; 7540, 0, -9135, 0, -9155] 2:2:x^2 - 18*x + 81 [0, 3741, 0, 0, -10909; 8990, 0, 0, 2580, 0; 0, 0, -29, 0, 0; 0, -11629, 0, 0, -4498; 1131, 0, 0, -7494, 0] 2:3:x^2 - 36 [11455, 0, 6264, 0, 6021; 0, -9164, 0, 9050, 0; -11310, 0, -5974, 0, 8235; 0 , -3770, 0, 9155, 0; 7540, 0, 4002, 0, -5461] 2:4:x^2 + 18*x + 81 [10846, 1943, -10875, 242, 2049; -6003, -3451, -3248, 1664, 102; 10150, -957 0, 5133, 3047, -8638; -10411, -9831, 6728, -3057, 665; 2523, 4495, -9019, 10 405, -9450] 2:5:x^2 + 8*x - 2 [1914, 10237, 725, 4727, -4482, -4486, 9083; 8700, 1653, 11861, -3016, 2332, -4735, 10177; -6119, -11426, 8584, -11049, -578, -7513, 3833; 0, 0, 0, 29, 0, 0, 0; -8265, -9918, -2088, 9889, -10008, -10802, -23; 7337, 5597, -10991, 11107, -4379, -8723, 7506; -12006, 6032, -2059, 1189, -10237, 10096, 6577] 3:1:x^3 + 3*x^2 - 74*x - 48 [3074, 0, 9454, 0, -12138, 0, -2046; 0, -1972, 0, -10034, 0, 9344, 0; -8265, 0, -7801, 0, -3323, 0, -7779; 0, 0, 0, -29, 0, 0, 0; -8294, 0, -6757, 0, 11 312, 0, 10746; 0, -9686, 0, -8787, 0, 1978, 0; -2639, 0, 4437, 0, 5759, 0, - 6589] 3:2:x^3 - 2*x^2 - 76*x + 312 [-8555, -3306, 377, -3538, -1057, -5334, -7485; -8932, 3451, 8294, 11397, -4 052, -1355, 2578; -1450, -10933, 1653, 6525, 1311, -7610, -7710; 0, 0, 0, -2 9, 0, 0, 0; -2059, -9019, -7192, -8439, 1190, 3361, 9815; 1392, -9106, -1798 , 87, -3103, 3066, -7087; -1653, 2581, 8236, -2900, 11345, -4764, -793] 3:3:x^3 - 12*x^2 - 17*x + 346 [5684, 0, 0, 0, 10972, 0, 0; 0, -9860, 0, 0, 0, -4428, 0; 0, 0, -5278, 0, 0, 0, -12194; 0, 0, 0, 29, 0, 0, 0; 3654, 0, 0, 0, -5686, 0, 0; 0, -6409, 0, 0 , 0, 9858, 0; 0, 0, 10962, 0, 0, 0, 5276] 3:4:x^3 + 6*x^2 + 12*x + 8 [-1653, 10933, 1450, -11658, -5464, -3497, 6465; 11977, 7453, -2436, -261, 6 665, 1910, 7198; 10469, 8671, 9599, -6235, -400, -3459, 4451; -7975, -4002, 2929, 11426, 4366, 11224, -5465; -10875, -8990, 551, -7163, -10111, -4096, 1 1029; 1798, 9106, -1392, 638, 7602, -4110, 10121; -2813, 2668, 6177, -7598, 5219, 647, 11802] 3:5:x^3 + 12*x^2 - 17*x - 346 [7801, 0, 8265, 0, -1052, 0, -9126; 0, 1972, 0, -9831, 0, -11896, 0; -9454, 0, -3074, 0, 6138, 0, -8067; 0, 9860, 0, -3480, 0, -2253, 0; 6757, 0, -8236, 0, 4905, 0, 10115; 0, 9686, 0, 10469, 0, 1531, 0; -4118, 0, 493, 0, 842, 0, -9628] 3:6:x^3 + 2*x^2 - 76*x - 312 [8584, -11426, -6119, 10237, -9729, 1083, -1550; 11861, 1653, 8700, -8787, 5 156, 6866, 1683; 725, 10237, 1914, -8787, 1874, 11925, -8265; -11165, -3016, 6003, 3741, -4254, -2425, 11903; -2378, 11774, 9976, -10643, -11275, 5753, 11787; 4669, 6815, 8352, -4408, 4229, 2543, 1464; -6264, -5365, -406, -4553, 5158, -8606, -7134] 3:7:x^3 + 3*x^2 - 74*x - 48 [6003, -5452, 5278, 8961, -8004, 6206, 11484, -9343, 8773; 1421, -9599, 1827 , 7424, -8642, 9889, -8555, 3027, 1344; -10556, 8497, 4408, -4872, 3248, -49 88, -11790, -4883, -2702; -7830, -4930, -5133, 3538, -10730, 11700, -8672, - 7184, -11176; 0, 0, 0, 0, 29, 0, 0, 0, 0; -8845, -3306, -2262, -12035, 2581, 2520, -3363, -8430, 6310; -1334, 11484, -3857, 4002, -2204, 2007, -8226, -8 174, 7769; -11484, -8410, -986, -3248, 10092, -8265, 4999, 742, -3630; -3509 , 4321, 6293, 2958, -3161, 232, 10771, 6268, 607] 4:1:x^4 + 7*x^3 - 69*x^2 - 314*x + 927 [7482, 0, -8120, 0, 4872, 0, -7477, 0, 212; 0, 11890, 0, -4959, 0, -2387, 0, 10515, 0; 3973, 0, 1798, 0, -7395, 0, 1853, 0, 1253; 0, -10034, 0, 6612, 0, -8510, 0, -5285, 0; 0, 0, 0, 0, -29, 0, 0, 0, 0; 0, 4205, 0, -5655, 0, 9134 , 0, 2684, 0; 7830, 0, 11107, 0, 9831, 0, -9145, 0, 5674; 0, -6264, 0, -5046 , 0, -9126, 0, -3240, 0; 8207, 0, 8584, 0, -10382, 0, 8000, 0, -136] 4:2:x^4 - 6*x^3 - 115*x^2 + 468*x + 2592 [2871, 754, 6090, 4640, -10382, -10701, 8782, -5686, 4206; -2320, 2842, 8555 , -3190, -2465, 11049, 3540, -7426, 1349; -9541, 12122, 2871, 3596, 11745, 1 980, 3757, 7466, -3756; 11339, -7395, -9454, -10469, -1827, 3612, -4422, -25 88, -12071; 0, 0, 0, 0, -29, 0, 0, 0, 0; 7105, 2262, -6989, -2639, 4756, -11 655, -9687, -1317, 7021; 9802, -1015, 174, 6844, 11571, -89, 4586, -2266, 67 29; 2842, -1276, 8526, 1653, 7830, 725, -6453, 8573, 9071; -841, -783, -1044 , 9425, -406, -3248, 2118, 10227, 387] 4:3:x^4 - 6*x^3 - 54*x^2 + 221*x - 70 [-8584, 0, 11339, 0, 1305, 0, 10563, 0, 6379; 0, -5220, 0, -5162, 0, 3660, 0 , 11962, 0; -2610, 0, 9773, 0, 4263, 0, -2699, 0, 626; 0, -8062, 0, -8033, 0 , 10145, 0, -11396, 0; 0, 0, 0, 0, 29, 0, 0, 0, 0; 0, 8294, 0, -3886, 0, 684 8, 0, 3691, 0; -986, 0, -9019, 0, 4466, 0, 8638, 0, 3726; 0, 5365, 0, -7772, 0, -4318, 0, 6409, 0; -406, 0, -290, 0, -10440, 0, -5866, 0, -9837] 4:4:x^4 + 6*x^3 - 44*x^2 - 320*x - 480 [0, 0, 0, -10759, 0, 0, 0, 0, 1612; 0, 0, 3596, 0, 0, 0, 0, 337, 0; 0, -8584 , 0, 0, 0, 0, -5466, 0, 0; 1624, 0, 0, 0, 0, -6546, 0, 0, 0; 0, 0, 0, 0, 29, 0, 0, 0, 0; 0, 0, 0, 2668, 0, 0, 0, 0, -2394; 0, 0, -8149, 0, 0, 0, 0, 2901 , 0; 0, -29, 0, 0, 0, 0, 6549, 0, 0; 10672, 0, 0, 0, 0, 11228, 0, 0, 0] 4:5:x^4 - 60*x^2 + 400 [-8033, 0, -8062, 0, -6438, 0, 7295, 0, 11171; 0, -2639, 0, 9280, 0, 5299, 0 , -3582, 0; -5162, 0, -5220, 0, -10295, 0, -6446, 0, -2333; 0, -11716, 0, -7 105, 0, -10470, 0, -8701, 0; -1073, 0, -986, 0, -3219, 0, -8830, 0, -2906; 0 , 12122, 0, 12093, 0, 2575, 0, -5144, 0; 11078, 0, -4553, 0, -5162, 0, 6409, 0, -333; 0, -1334, 0, -1479, 0, 1969, 0, 7159, 0; 8845, 0, 8787, 0, 10295, 0, -2243, 0, 10096] 4:6:x^4 + 6*x^3 - 44*x^2 - 320*x - 480 [10469, 9454, 7395, -11339, -7163, 608, 1475, 4398, 237; -3596, -2871, -1212 2, 9541, -2378, 8818, 2054, 2058, -2253; -3393, 4031, -5597, 5684, 9860, 241 9, 8125, -294, -7068; 8381, -1827, -1392, -1450, -145, 3406, 7774, 12101, -6 091; -8990, -11803, -8381, 9860, -11890, 12160, -6350, -10956, -6212; -3857, 8816, -1131, 10817, -8062, 4633, -7490, -12103, -6866; -1102, -5684, -7279, 6235, -1218, -9206, -9994, 1041, -7220; -10266, -261, -10672, 9686, 7946, 2 3, -12026, 7333, -12118; 10556, 3567, -9048, -4031, -4727, -1208, 10976, 654 7, 9390] 4:7:x^4 + 6*x^3 - 54*x^2 - 221*x - 70 [6612, 0, -10034, 0, -8584, 0, -8609, 0, -3206; 0, 1798, 0, 3973, 0, 5012, 0 , -5000, 0; -4959, 0, 11890, 0, 6351, 0, 910, 0, 7548; 0, -8120, 0, 7482, 0, 848, 0, 4841, 0; 5046, 0, 6264, 0, -9976, 0, -10104, 0, -8258; 0, -6786, 0, 9048, 0, 4943, 0, -11139, 0; -1247, 0, 6757, 0, -10208, 0, -6008, 0, 993; 0 , 4466, 0, 11745, 0, 9655, 0, 10165, 0; 1769, 0, -7569, 0, -5162, 0, 8361, 0 , -2540] 4:8:x^4 - 6*x^3 - 115*x^2 + 468*x + 2592 [3538, -5133, -4930, -7830, 4988, 11556, -9164, 11957, -5320; -4872, 4408, 8 497, -10556, 5075, 8999, 6826, 9205, 7673; 7424, 1827, -9599, 1421, 10730, - 2918, -2025, -6701, -5972; 8961, 5278, -5452, 6003, 5800, -4986, -844, 5546, -2182; 4988, 6786, -4669, -7830, -4959, -8349, 2078, -3595, -6410; -6583, - 3045, 7598, -1943, 6032, 7046, 4340, 11711, 3369; 11281, 11774, 8236, 9541, 1247, 9795, 7787, 251, 8070; -1769, 5771, 3161, 5510, -754, -36, -7645, 8397 , -2112; 638, -9048, 11165, -10991, -10788, 11611, 6031, -6085, 1790] 4:9:x^4 + 7*x^3 - 69*x^2 - 314*x + 927 [2639, 11426, -5394, 2465, 5336, 10237, -1667, -1769, -777, 6071, 706; 11252 , 12064, 11890, -4437, -812, -5510, 3816, 4089, 8018, 7699, 4065; 9222, 8265 , -4002, -9831, 11165, 7105, 8961, 9918, -10608, -402, 3651; -2204, -2552, 1 1948, 5162, 7917, -1479, -4727, 8409, 4446, -11433, 7176; -4379, -4727, -661 2, -667, -2059, 1856, 5510, 10114, -163, 6698, 636; 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, 0; -5365, -667, -11745, 9193, -8555, 2465, 4292, 8420, 1624, 2336, 96 ; 5423, 8062, -7888, 10440, 2378, 9164, -6641, -1538, 11194, 3313, -1324; 87 0, 928, 11745, 4437, 1827, 1798, -10208, -9195, 1721, 4071, 2545; 10962, 353 8, 5423, -7685, 8178, 7308, 10266, 11281, 7898, -10645, -680; -2059, -9541, -928, -3277, 11078, 493, 1760, -3132, 1294, 3878, -7646] 5:1:x^5 + 12*x^4 - 81*x^3 - 1217*x^2 - 15*x + 19944 [2929, 0, 3074, 0, -8787, 0, 3456, 0, 11320, 0, 2651; 0, 3451, 0, 6003, 0, 2 987, 0, 7284, 0, -3268, 0; 7395, 0, -6641, 0, -6148, 0, 7937, 0, 6353, 0, 27 53; 0, -1943, 0, -10846, 0, 1624, 0, -3009, 0, -2180, 0; 10063, 0, 9019, 0, -7975, 0, -9741, 0, -4531, 0, 10610; 0, 0, 0, 0, 0, -29, 0, 0, 0, 0, 0; 1044 0, 0, -11136, 0, -9454, 0, 7888, 0, 4571, 0, -5626; 0, 9947, 0, 10933, 0, 10 034, 0, 2375, 0, -9032, 0; 7888, 0, 7859, 0, 6960, 0, -3944, 0, 3853, 0, -10 734; 0, 11629, 0, -2726, 0, 4756, 0, -8798, 0, 5028, 0; 10063, 0, -1566, 0, 1943, 0, 8709, 0, -3209, 0, -60] 5:2:x^5 - 2*x^4 - 118*x^3 + 136*x^2 + 3304*x + 792 [0, 3509, 0, 0, -11049, 0, 0, 1953, 0, 0, -2870; 3973, 0, 0, 6902, 0, 0, 560 7, 0, 0, -3179, 0; 0, 0, -1972, 0, 0, -10034, 0, 0, 9344, 0, 0; 0, 11223, 0, 0, 8526, 0, 0, -8544, 0, 0, -7366; 9425, 0, 0, -6206, 0, 0, -1337, 0, 0, -8 220, 0; 0, 0, 0, 0, 0, -29, 0, 0, 0, 0, 0; 0, -3306, 0, 0, -6873, 0, 0, -736 7, 0, 0, -8752; 9860, 0, 0, 5481, 0, 0, 5794, 0, 0, -2691, 0; 0, 0, -9686, 0 , 0, -8787, 0, 0, 1978, 0, 0; 0, -6322, 0, 0, 6380, 0, 0, -5441, 0, 0, 1290; -5510, 0, 0, -9744, 0, 0, 11058, 0, 0, -8500, 0] 5:3:x^5 - 6*x^4 - 84*x^3 + 504*x^2 + 9*x - 54 [-8584, 0, 0, 0, 10846, 0, 0, 0, -790, 0, 0; 0, -9164, 0, 0, 0, 12006, 0, 0, 0, 4525, 0; 0, 0, 3625, 0, 0, 0, -6975, 0, 0, 0, -3185; 0, 0, 0, 11455, 0, 0, 0, -6750, 0, 0, 0; 6177, 0, 0, 0, 7047, 0, 0, 0, -7800, 0, 0; 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, 0; 0, 0, -6264, 0, 0, 0, 780, 0, 0, 0, -1366; 0, 0, 0, 3 770, 0, 0, 0, -11464, 0, 0, 0; -2726, 0, 0, 0, -4582, 0, 0, 0, 5658, 0, 0; 0 , -7540, 0, 0, 0, 9135, 0, 0, 0, 9155, 0; 0, 0, 3190, 0, 0, 0, 876, 0, 0, 0, -8530] 5:4:x^5 + 22*x^4 + 46*x^3 - 2156*x^2 - 18639*x - 44874 [-783, 2030, 6409, -4118, 116, 5307, 6235, 5162, -4359, -10651, -3371; 8468, -11252, -6844, 5858, -2494, 3161, -760, 10814, -9343, 2128, -3683; -7569, 6 670, 5307, -8120, -9628, -6351, 5307, -661, -365, -2845, -5521; 1421, -5510, -7366, -29, -957, -7598, 6012, 6147, -28, -6216, -9280; 5336, 29, 7047, -87 58, 7047, -7163, -551, 6172, 11504, 4103, -2041; 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, 0; 8323, 9251, 7511, -3422, -2552, 9657, 8784, -8148, 2562, 3701, 10058; -2117, 9860, -10527, -3712, -2639, -9599, 12151, -8356, 11613, -6934, -4743 ; 7946, -5974, -2378, 4988, 638, 10904, 5762, 4893, 4946, 4750, 5713; 5945, -3886, 11165, -8874, 7656, 11977, -2552, -11185, -1181, -2767, -4225; -6003, 7250, 1015, 1624, -5510, -2581, 4022, 4060, -11274, -8302, -2900] 5:5:x^5 + 3*x^4 - 115*x^3 - 123*x^2 + 3194*x - 2760 [0, 0, 0, 0, 2262, 0, 0, 0, 0, 0, 4444; 0, 0, 0, -3741, 0, 0, 0, 0, 0, 10909 , 0; 0, 0, -9860, 0, 0, 0, 0, 0, -4428, 0, 0; 0, -8990, 0, 0, 0, 0, 0, -2580 , 0, 0, 0; -11687, 0, 0, 0, 0, 0, -2157, 0, 0, 0, 0; 0, 0, 0, 0, 0, 29, 0, 0 , 0, 0, 0; 0, 0, 0, 0, -1740, 0, 0, 0, 0, 0, 2337; 0, 0, 0, 11629, 0, 0, 0, 0, 0, 4498, 0; 0, 0, -6409, 0, 0, 0, 0, 0, 9858, 0, 0; 0, -1131, 0, 0, 0, 0, 0, 7494, 0, 0, 0; -8700, 0, 0, 0, 0, 0, -11320, 0, 0, 0, 0] 5:6:x^5 + 2*x^4 - 40*x^3 - 80*x^2 + 144*x + 288 [7047, -8758, 7047, 29, 5336, -1566, 4817, 9018, -676, 9089, -7337; -5916, - 8323, 5742, 1015, 3335, 4988, -9802, -9732, -12106, 11701, 3555; -6757, 6844 , 348, 11310, -2291, 870, -8401, -1929, -10396, -9578, 2175; -2813, 3364, -5 655, -8265, 4495, 3915, -11252, -2350, -3754, 6192, -11928; 12151, 4234, 118 03, 4234, -2117, -8932, -841, 7146, 2115, 454, -4205; -5249, 1276, 4640, -84 10, -1450, -8236, 7307, -10217, 969, 10632, -1141; -1102, -4553, 203, 1450, 8555, -4263, 5394, 7502, 3348, -11310, 7912; 3828, -4437, -6612, -1943, -922 2, -10730, 9404, 2192, -1562, 11218, 3161; 638, 4988, -2378, -5974, 7946, 52 2, 6119, -911, 1959, -6906, 11691; -5278, -7424, 3335, -4669, -4234, 5597, 1 0367, 249, 8697, -7022, 10817; 11629, 7279, -11223, -2523, -7163, 5510, 1138 8, -9448, -646, -7088, -7340] 5:7:x^5 + 3*x^4 - 115*x^3 - 123*x^2 + 3194*x - 2760 [-7047, 0, 0, 0, -6177, 0, 0, 0, 1623, 0, 0; 0, -11455, 0, 0, 0, -6264, 0, 0 , 0, -6021, 0; 0, 0, -5539, 0, 0, 0, 9354, 0, 0, 0, 567; 0, 0, 0, 9164, 0, 0 , 0, -9050, 0, 0, 0; 8961, 0, 0, 0, 5858, 0, 0, 0, -12083, 0, 0; 0, 11310, 0 , 0, 0, 5974, 0, 0, 0, -8235, 0; 0, 0, -8236, 0, 0, 0, -3843, 0, 0, 0, -6524 ; 0, 0, 0, 3770, 0, 0, 0, -9155, 0, 0, 0; 4582, 0, 0, 0, 2726, 0, 0, 0, -293 2, 0, 0; 0, -7540, 0, 0, 0, -4002, 0, 0, 0, 5461, 0; 0, 0, 6931, 0, 0, 0, -1 1032, 0, 0, 0, -10882] 5:8:x^5 - 22*x^4 + 46*x^3 + 2156*x^2 - 18639*x + 44874 [0, 6206, 0, 0, -9425, 0, 0, 3274, 0, 0, 2265; -8526, 0, 0, -11223, 0, 0, -7 308, 0, 0, 2764, 0; 0, 0, 1972, 0, 0, -9831, 0, 0, -11896, 0, 0; 0, 899, 0, 0, -2320, 0, 0, 9718, 0, 0, 11794; 1247, 0, 0, -11977, 0, 0, 4248, 0, 0, 444 4, 0; 0, 0, 9860, 0, 0, -3480, 0, 0, -2253, 0, 0; 0, -667, 0, 0, -10701, 0, 0, 5678, 0, 0, -4172; 10005, 0, 0, -7163, 0, 0, -764, 0, 0, 10029, 0; 0, 0, 9686, 0, 0, 10469, 0, 0, 1531, 0, 0; 0, -10962, 0, 0, 4669, 0, 0, -4026, 0, 0, 8739; 9976, 0, 0, -7859, 0, 0, -1107, 0, 0, 7196, 0] 5:9:x^5 + 6*x^4 - 84*x^3 - 504*x^2 + 9*x + 54 [-7975, 0, 9019, 0, 10063, 0, 4272, 0, 4013, 0, 7683; 0, -10846, 0, -1943, 0 , 10875, 0, -242, 0, -2049, 0; -6148, 0, -6641, 0, 7395, 0, -10624, 0, 9494, 0, -16; 0, 6003, 0, 3451, 0, 3248, 0, -1664, 0, -102, 0; -8787, 0, 3074, 0, 2929, 0, -11134, 0, -10948, 0, -1195; 0, -10150, 0, 9570, 0, -5133, 0, -304 7, 0, 8638, 0; 1102, 0, 3480, 0, 870, 0, 9724, 0, -8411, 0, 5153; 0, 10411, 0, 9831, 0, -6728, 0, 3057, 0, -665, 0; -1537, 0, -4843, 0, 4553, 0, -8778, 0, 4612, 0, 10860; 0, -2523, 0, -4495, 0, 9019, 0, -10405, 0, 9450, 0; 1508, 0, -6902, 0, 3422, 0, 5684, 0, 9834, 0, -2655] 5:10:x^5 - 2*x^4 - 118*x^3 + 136*x^2 + 3304*x + 792 [2059, 667, 6612, 4727, 4379, 6235, -6022, 9638, -131, 3745, -3185; -7917, - 5162, -11948, 2552, 2204, 7801, -11984, -4098, 9698, 2961, 11379; -11165, 98 31, 4002, -8265, -9222, -4872, -1174, 10357, -83, 3969, 11363; 812, 4437, -1 1890, -12064, -11252, -8990, -9421, -6109, -11096, 5412, -5662; -5336, -2465 , 5394, -11426, -2639, -4089, 2531, -350, -98, -5470, -4680; -11310, -3422, -10034, -10179, 6699, -2204, 9614, 6886, -1908, 11594, -7613; 10643, 4814, 1 1774, 4669, 1769, 8236, -8214, -6181, 4149, -437, 2279; -11716, -9454, 2262, 551, -3306, -6380, 11748, 8655, -2398, -2317, -192; -1537, 1595, -4379, 481 4, 9309, -3741, 7881, 1696, 315, 10533, 2777; -10498, -6525, -8642, 11455, 2 088, 464, -3973, -1800, -4964, 8759, -8445; -6003, 2813, 9947, 3335, 2436, - 5046, -9969, 9085, 2398, -8658, 6476] 5:11:x^5 - 12*x^4 - 81*x^3 + 1217*x^2 - 15*x - 19944 [-6, 9, -6, 7, 9; 12, -9, 6, 9, 12; 0, 0, 3, 0, 0; 0, -6, 0, 3, -10; 9, 3, - 9, 6, 9] x^2 + 3*x [20, 20, -40, 25, -16; -10, 30, 35, 3, -31; 0, 0, 5, 0, 0; 0, 15, -30, -30, -35; 5, 20, 5, 20, -20] x^2 - 5 [-91, 49, 28, 21, -129; -105, -63, 168, 77, -151; 0, 0, 7, 0, 0; 49, -63, 16 1, -74, -28; 77, 119, -49, -43, -116] x^2 + x - 5 [0, 0, -3, 0, 0, -9, -8, 0, 3; 0, 0, 6, 4, 0, -6, -5, 0, -3; -3, 0, 0, -6, 0 , 0, -3, 0, 0; -6, 0, -9, 12, 0, -9, -9, -5, -9; -3, 0, 9, -6, 1, 9, -3, -5, 0; 0, -9, 0, 0, 9, 0, 0, -9, 0; 0, 9, 0, 0, 0, 0, 0, -9, 7; 0, -9, 0, 0, -9 , 7, 0, 0, 13; 0, 0, 12, 0, 0, -12, 0, 0, 12] x^4 + 3*x^3 - 3*x^2 - 9*x [-20, -50, -60, 25, 55, 2, -15, 14, 15; -15, 50, 20, 50, -55, -50, 35, -31, -25; -45, 50, -30, -50, 55, 50, -30, -50, 5; 0, 50, -10, 0, -55, -50, -5, -2 5, 40; 0, 0, 0, 0, 5, 0, 0, 0, 0; -25, -20, -25, 15, 25, 30, 56, -40, -52; 0 , 60, 0, 20, 0, -5, 0, 35, -32; -50, -20, 50, 45, -50, 55, 50, 45, -50; -25, 0, -25, -10, -50, -5, 0, -5, 50] x^4 - 20*x^2 - 10*x + 50 [0, 70, -154, 63, 98, 70, 106, 133, -112; -119, -154, 133, 98, -168, -30, -1 33, 14, -49; 14, -168, -42, -168, 77, 43, 42, 21, 10; -105, 133, -98, 140, 1 61, -21, -147, 140, 50; 0, 0, 0, 0, 7, 0, 0, 0, 0; 133, 21, -140, 70, 42, 7, -42, -76, 100; 56, 49, -21, -56, 35, 98, -168, -164, 161; -154, -49, 70, -5 6, -84, 147, 70, 52, 35; 0, -119, -105, 84, 49, -70, 90, 14, 161] x^4 + 4*x^3 - 14*x^2 - 42*x + 14 [165, -275, -55, 649, 407, -187, -418, 494, 155; 429, -242, -66, -539, 22, - 506, 528, -247, -79; -660, -451, 539, 308, 275, 352, 572, -187, 531; -550, 5 72, 308, -451, -638, -352, -209, 429, -333; 0, 0, 0, 0, 11, 0, 0, 0, 0; -517 , -198, -176, -286, 396, -50, -275, 407, 154; 649, -528, 550, 660, 616, 461, 131, -649, 242; 539, -594, 330, -517, 110, 374, 569, 208, -154; 462, 253, - 572, 363, -649, -165, 592, 502, -303] x^4 + 3*x^3 - 27*x^2 - 26*x + 47 x^2 - 27 x^2 + 25*x + 125 x^2 + 23*x - 265 x^4 - 9*x^2 - 2*x + 12 x^5 + 2*x^4 - 10*x^3 - 20*x^2 x^6 + 2*x^5 - 15*x^4 - 26*x^3 + 62*x^2 + 84*x - 51 x^2 - 47*x - 5490 x^2 + 47*x - 5490 x^2 - 47*x - 5490 x^2 - 42*x - 2356 x^2 + 42*x - 2356 x^3 + 4*x^2 - 164*x - 180 x^3 - 10*x^2 - 154*x + 1508 x^2 + 9*x - 135 x + 6 x^2 - x - 2 x^2 - 2*x - 1 x^2 - 2 x^2 - x - 4 x^2 - x - 2 x^2 - 2*x - 2 x^2 - 2 x^2 - 4 x^2 - 2 x^2 - 686 [48107*a + 38874 9222*a + 54290 41941*a + 8931 39672*a + 28651] [ 21458*a + 4763 3652*a + 22205 31111*a + 42559 39834*a + 40207] [ 13329*a + 4140 45270*a + 25803 1377*a + 32931 55980*a + 21267] [15086*a + 26714 33424*a + 4898 41830*a + 48013 5913*a + 24088] *** at top-level: hyperellcharpoly((256*a^5+5)*Mod(1,5)) *** ^-------------------------------------- *** hyperellcharpoly: domain error in hyperellpadicfrobenius: H is singular at 5 *** at top-level: hyperellcharpoly((256*a^5+5)*ffgen(5^2)) *** ^---------------------------------------- *** hyperellcharpoly: domain error in hyperellpadicfrobenius: H is singular at 5 Total time spent: 2568 pari-2.17.2/src/test/32/matsnf0000644000175000017500000001760514676526175014425 0ustar billbillx^2 + 10*x + 27 x^2 + 10/3*x + 3 x^2 + 10/a*x + 27/a^2 x^2 + 10*a*x + 27*a^2 [2, 1] [X^2 + 10*X + 27, X^2 + 10*X + 27, 1, 1] x^2 - 2*a*x + (a^2 - d^2) 3 2 0 2 3 3 1 3 4 2 3 1 0 2 2 2 2 2 (M)->my([F,B]=matfrobenius(M,2));if(M!=B^-1*F*B,error("matfrobenius:",M));F Mat(1) [0, -1; 1, 2] [0, 0, 1; 1, 0, -3; 0, 1, 3] [0, 0, 0, -1; 1, 0, 0, 4; 0, 1, 0, -6; 0, 0, 1, 4] [0, 0, 0, 0, 1; 1, 0, 0, 0, -5; 0, 1, 0, 0, 10; 0, 0, 1, 0, -10; 0, 0, 0, 1, 5] [0, 0, 0, 0, 0, -1; 1, 0, 0, 0, 0, 6; 0, 1, 0, 0, 0, -15; 0, 0, 1, 0, 0, 20; 0, 0, 0, 1, 0, -15; 0, 0, 0, 0, 1, 6] [0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, -7; 0, 1, 0, 0, 0, 0, 21; 0, 0, 1, 0 , 0, 0, -35; 0, 0, 0, 1, 0, 0, 35; 0, 0, 0, 0, 1, 0, -21; 0, 0, 0, 0, 0, 1, 7] [0, 0, 0, 0, 0, 0, 0, -1; 1, 0, 0, 0, 0, 0, 0, 8; 0, 1, 0, 0, 0, 0, 0, -28; 0, 0, 1, 0, 0, 0, 0, 56; 0, 0, 0, 1, 0, 0, 0, -70; 0, 0, 0, 0, 1, 0, 0, 56; 0, 0, 0, 0, 0, 1, 0, -28; 0, 0, 0, 0, 0, 0, 1, 8] [0, 0, 0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, 0, 0, -9; 0, 1, 0, 0, 0, 0, 0, 0, 36; 0, 0, 1, 0, 0, 0, 0, 0, -84; 0, 0, 0, 1, 0, 0, 0, 0, 126; 0, 0, 0, 0 , 1, 0, 0, 0, -126; 0, 0, 0, 0, 0, 1, 0, 0, 84; 0, 0, 0, 0, 0, 0, 1, 0, -36; 0, 0, 0, 0, 0, 0, 0, 1, 9] [0, 0, 0, 0, 0, 0, 0, 0, 0, -1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 10; 0, 1, 0, 0, 0 , 0, 0, 0, 0, -45; 0, 0, 1, 0, 0, 0, 0, 0, 0, 120; 0, 0, 0, 1, 0, 0, 0, 0, 0 , -210; 0, 0, 0, 0, 1, 0, 0, 0, 0, 252; 0, 0, 0, 0, 0, 1, 0, 0, 0, -210; 0, 0, 0, 0, 0, 0, 1, 0, 0, 120; 0, 0, 0, 0, 0, 0, 0, 1, 0, -45; 0, 0, 0, 0, 0, 0, 0, 0, 1, 10] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -11; 0, 1, 0 , 0, 0, 0, 0, 0, 0, 0, 55; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -165; 0, 0, 0, 1, 0 , 0, 0, 0, 0, 0, 330; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -462; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 462; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -330; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 165; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -55; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 11] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12; 0 , 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -66; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 220; 0 , 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -495; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 792; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -924; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 792; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -495; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 220 ; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -66; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 12] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -13; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 , 0, -286; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 715; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -1287; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1716; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1716; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1287; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -715; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 286; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -78; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 , 13] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -91; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 364; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1001; 0, 0, 0 , 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2002; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -3003; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3432; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -3003; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2002; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -1001; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 364; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -91; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 14] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -15; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -455; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 1365; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3003; 0, 0, 0, 0, 0, 1, 0 , 0, 0, 0, 0, 0, 0, 0, 5005; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -6435 ; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 6435; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -5005; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 3003; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -1365; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 455; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -105; 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 1, 15] [0, -1; 1, 2] [0, 0, 1; 1, 0, -3; 0, 1, 3] [0, 0, 0, -1; 1, 0, 0, 4; 0, 1, 0, -6; 0, 0, 1, 4] [0, 0, 0, 0, 1; 1, 0, 0, 0, -5; 0, 1, 0, 0, 10; 0, 0, 1, 0, -10; 0, 0, 0, 1, 5] [0, 0, 0, 0, 0, -1; 1, 0, 0, 0, 0, 6; 0, 1, 0, 0, 0, -15; 0, 0, 1, 0, 0, 20; 0, 0, 0, 1, 0, -15; 0, 0, 0, 0, 1, 6] [0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, -7; 0, 1, 0, 0, 0, 0, 21; 0, 0, 1, 0 , 0, 0, -35; 0, 0, 0, 1, 0, 0, 35; 0, 0, 0, 0, 1, 0, -21; 0, 0, 0, 0, 0, 1, 7] [0, 0, 0, 0, 0, 0, 0, -1; 1, 0, 0, 0, 0, 0, 0, 8; 0, 1, 0, 0, 0, 0, 0, -28; 0, 0, 1, 0, 0, 0, 0, 56; 0, 0, 0, 1, 0, 0, 0, -70; 0, 0, 0, 0, 1, 0, 0, 56; 0, 0, 0, 0, 0, 1, 0, -28; 0, 0, 0, 0, 0, 0, 1, 8] [0, 0, 0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, 0, 0, -9; 0, 1, 0, 0, 0, 0, 0, 0, 36; 0, 0, 1, 0, 0, 0, 0, 0, -84; 0, 0, 0, 1, 0, 0, 0, 0, 126; 0, 0, 0, 0 , 1, 0, 0, 0, -126; 0, 0, 0, 0, 0, 1, 0, 0, 84; 0, 0, 0, 0, 0, 0, 1, 0, -36; 0, 0, 0, 0, 0, 0, 0, 1, 9] [0, 0, 0, 0, 0, 0, 0, 0, 0, -1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 10; 0, 1, 0, 0, 0 , 0, 0, 0, 0, -45; 0, 0, 1, 0, 0, 0, 0, 0, 0, 120; 0, 0, 0, 1, 0, 0, 0, 0, 0 , -210; 0, 0, 0, 0, 1, 0, 0, 0, 0, 252; 0, 0, 0, 0, 0, 1, 0, 0, 0, -210; 0, 0, 0, 0, 0, 0, 1, 0, 0, 120; 0, 0, 0, 0, 0, 0, 0, 1, 0, -45; 0, 0, 0, 0, 0, 0, 0, 0, 1, 10] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -11; 0, 1, 0 , 0, 0, 0, 0, 0, 0, 0, 55; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -165; 0, 0, 0, 1, 0 , 0, 0, 0, 0, 0, 330; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -462; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 462; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -330; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 165; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -55; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 11] Mat(1) [0, -1/12; 1, 4/3] [0, 0, 1/2160; 1, 0, -127/720; 0, 1, 23/15] [0, 0, 0, -1/6048000; 1, 0, 0, 41/23625; 0, 1, 0, -3341/12600; 0, 0, 1, 176/ 105] [0, 0, 0, 0, 1/266716800000; 1, 0, 0, 0, -61501/53343360000; 0, 1, 0, 0, 852 401/222264000; 0, 0, 1, 0, -735781/2116800; 0, 0, 0, 1, 563/315] [0, 0, 0, 0, 0, -1/186313420339200000; 1, 0, 0, 0, 0, 3529/70573265280000; 0 , 1, 0, 0, 0, -10828423/2688505344000; 0, 0, 1, 0, 0, 18344719/2750517000; 0 , 0, 0, 1, 0, -14806217/34927200; 0, 0, 0, 0, 1, 6508/3465] [0, 0, 0, 0, 0, 0, 1/2067909047925770649600000; 1, 0, 0, 0, 0, 0, -8237351/5 9083115655022018560000; 0, 1, 0, 0, 0, 0, 509709971/1758426061161369600; 0, 0, 1, 0, 0, 0, -126867217979/12687056718336000; 0, 0, 0, 1, 0, 0, 2804123885 /276900047424; 0, 0, 0, 0, 1, 0, -197708437/399567168; 0, 0, 0, 0, 0, 1, 880 69/45045] [0, 0, 0, 0, 0, 0, 0, -1/365356847125734485878112256000000; 1, 0, 0, 0, 0, 0 , 0, 442037/17839689801061254193267200000; 0, 1, 0, 0, 0, 0, 0, -12581527408 69/906142974022158943150080000; 0, 0, 1, 0, 0, 0, 0, 725120398661/6688626213 66980040000; 0, 0, 0, 1, 0, 0, 0, -3571285252517/176488178798131200; 0, 0, 0 , 0, 1, 0, 0, 85934726089/6093243231075; 0, 0, 0, 0, 0, 1, 0, -6070382321/10 821610800; 0, 0, 0, 0, 0, 0, 1, 91072/45045] [0, x, x] [0, x^2 + x, 1] [0, 0] [[1, 0, 0; 0, -2, 1], [;], [;]] [] [matrix(0,1), [1, 0; 0, -2; 0, 1], matrix(0,2)] [Mod(1, 3)*x^4 + Mod(2, 3)*x + Mod(2, 3), 1, 1] [0 0 0 0 0 0 0 0 0] [1 0 0 0 0 0 0 0 -8] [0 1 0 0 0 0 0 0 2] [0 0 1 0 0 0 0 0 4] [0 0 0 1 0 0 0 0 5] [0 0 0 0 1 0 0 0 4] [0 0 0 0 0 1 0 0 13] [0 0 0 0 0 0 1 0 5] [0 0 0 0 0 0 0 1 2] x^9 - 2*x^8 - 5*x^7 - 13*x^6 - 4*x^5 - 5*x^4 - 4*x^3 - 2*x^2 + 8*x [[0, 0, 0, 1; 1, 9, -27, 0; 0, 1, 0, 0], [-1; 1], [0; 0; 3]] 3 [[0, 0, 0, 1; 1, 9, -27, 0; 0, 1, 0, 0; 0, 0, 1, 0], [-1, 1; 1, 0], [0, 0; 0 , 0; 3, 0; 0, 1]] 3 [64, 32, 32, 32, 32, 16, 16, 16, 16, 16, 16, 16, 16, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 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] *** Warning: new stack size = 88000000 (83.923 Mbytes). 1 Total time spent: 14194 pari-2.17.2/src/test/32/ellmanin0000644000175000017500000000053414676526175014725 0ustar billbill *** Warning: new stack size = 10000000 (9.537 Mbytes). 11a3:5 14a4:3 14a6:3 15a3:2 15a7:2 15a8:4 17a2:2 17a3:2 17a4:4 19a3:3 20a2:2 20a4:2 21a4:2 24a4:2 26a3:3 27a3:3 27a4:3 32a2:2 32a3:2 32a4:2 33a2:2 35a3:3 37b3:3 38a3:3 39a4:2 40a3:2 48a4:2 52a2:2 54a3:3 55a4:2 57b2:2 64a4:2 73a2:2 77b3:3 80a2:2 80b2:2 80b4:2 89b2:2 Total time spent: 1022 pari-2.17.2/src/test/32/deriv0000644000175000017500000001076314567450071014232 0ustar billbill-0.65364362086361191463916818309775038142 0.83373002513114904888388539433509447981 - 0.9888977057628650963821295408926 8618864*I 1 - 1/2*x^2 + 1/24*x^4 - 1/720*x^6 + 1/40320*x^8 - 1/3628800*x^10 + 1/479001 600*x^12 - 1/87178291200*x^14 + 1/20922789888000*x^16 + O(x^17) -0.65364362086361191463916818309775038142 1 + O(t^2) 1 - 1/2*t^2 + 1/24*t^4 - 1/720*t^6 + 1/40320*t^8 - 1/3628800*t^10 + 1/479001 600*t^12 - 1/87178291200*t^14 + 1/20922789888000*t^16 + O(t^17) 0.54030230586813971740093660744297660373 + 0.8414709848078965066525023216302 9899962*t - 1.1116221377419663653529706253517873015*t^2 + 1.2415281265413868 062780218754682257701*t^3 - 1.2086763551283186745359503800028237136*t^4 + 0. 99756648563165528612382129965904293175*t^5 - 0.60046085825628373309052750421 982407285*t^6 + 0.017967952623614463202494741978235548225*t^7 + 0.7405545097 7142910348016232166472688835*t^8 - 1.6567879034733145514106563113137871196*t ^9 + 2.7034410910737658601008510753655794709*t^10 - 3.8444448874661633307934 331097517525113*t^11 + 5.0353559133209458942259649372731155821*t^12 - 6.2239 703711772098957775971680803734805*t^13 + 7.351145435617212277584406723929509 9587*t^14 - 8.3518230734703734024304578550750879236*t^15 + O(t^16) 3.5962749997291581980860017516463603814 0 Mod(x, x^2 + 1) 0 Mod(x, x^2 + 1) Mod(0, x^2 + 1) error("incorrect priority in intformal: variable x = x") Mod(1/2*y^2*x + y, x^2 + 1) Mod(0, 3) Mod(0, 3) Mod(0, 3) Mod(0, 3) Mod(0, 3) Mod(1, 3)*x Mod(1, 3)*y 0 0 0 0 0 t*x t*y y + O(x^2) y + O(x^2) O(x) x + O(x^3) O(x^3) x + 1/2*y*x^2 + O(x^4) y + 1/2*y^2*x + O(x^3) y/(x^2 + 2*y*x + y^2) y/(x^2 + 2*y*x + y^2) -2*y/(x^3 + 3*y*x^2 + 3*y^2*x + y^3) -x/(x^2 + 2*y*x + y^2) 2*x/(x^3 + 3*y*x^2 + 3*y^2*x + y^3) error("domain error in intformal: residue(series, pole) != 0") error("domain error in intformal: residue(series, pole) != 0") (-x^4 - 6*x^2 - 12*x + 3)/(3*x^6 + 9*x^4 + 9*x^2 + 3) (-x^4 - 6*x^2 - 12*x + 3)/(3*x^6 + 9*x^4 + 9*x^2 + 3) (2*x^5 + 20*x^3 + 60*x^2 - 30*x - 12)/(3*x^8 + 12*x^6 + 18*x^4 + 12*x^2 + 3) 0 0 error("domain error in intformal: residue(series, pole) != 0") (y*x^3 + 3*y*x + 3*y)/(3*x^4 + 6*x^2 + 3) [y] [y] [0] [x] [0] [1/2*y*x^2] [1/2*y^2*x] Mat(y) Mat(y) Mat(0) Mat(x) Mat(0) Mat(1/2*y*x^2) Mat(1/2*y^2*x) -Y*A + Y 0 0 x x O(x) O(x) x x 3.0000000000000000000000000000000000000*y 2.0000000000000000000000000000000000000*y 2.0000000000000000000000000000000000000*y -2.0000000000000000000000000000000000000 0.17600000000000000000000000000000000000 -0.016000000000000000000000000000000000000 - 1.08800000000000000000000000000 00000000*I -2 + 12*t^2 - 30*t^4 + 56*t^6 - 90*t^8 + 132*t^10 - 182*t^12 + 240*t^14 - 30 6*t^16 + O(t^18) 6*t^4 - 20*t^6 + 42*t^8 - 72*t^10 + 110*t^12 - 156*t^14 + 210*t^16 + O(t^18) -52635599.000000000000000000000000000000 [1, 1, 1, 0, -3, -8, -3, 56, 217, 64, -2951, -12672, 5973, 309376] [] 1 + x^2 + 1/2*x^4 + 1/6*x^6 + 1/24*x^8 + 1/120*x^10 + 1/720*x^12 + 1/5040*x^ 14 + 1/40320*x^16 + O(x^18) 1 + x^2 + 1/2*x^4 + 1/6*x^6 + 1/24*x^8 + 1/120*x^10 + O(x^12) 0 -16*x/(16*x^4 + 8*x^2 + 1) *** at top-level: derivnum(z=0,0,[0,-1]) *** ^--------- *** domain error in derivnumk: derivation order < 0 *** at top-level: derivnum(z=0,0,[1,-1]) *** ^--------- *** domain error in derivnumk: derivation order < 0 *** at top-level: derivnum(z=0,0,x) *** ^---- *** incorrect type in derivnum (t_POL). *** at top-level: derivn(cos,-1) *** ^-------------- *** derivn: domain error in derivn: n < 0 *** at top-level: derivn(cos,1,'x) *** ^---------------- *** derivn: incorrect type in derivn (t_CLOSURE). *** at top-level: sin'("") *** ^-------- *** in function sin: sin' *** ^---- *** _derivfun: incorrect type in numerical derivation (t_STR). *** at top-level: sin''("") *** ^--------- *** in function sin: derivn(sin,2) *** ^------------- *** _derivfun: incorrect type in numerical derivation (t_STR). *** at top-level: (x->x)'("") *** ^----------- *** in anonymous function: ((x)->x)' *** ^--------- *** _derivfun: incorrect type in numerical derivation (t_STR). *** at top-level: (x->x)''("") *** ^------------ *** in anonymous function: derivn((x)->x,2) *** ^---------------- *** _derivfun: incorrect type in numerical derivation (t_STR). Total time spent: 3 pari-2.17.2/src/test/32/dirmul0000644000175000017500000000202114567450071014401 0ustar billbill[0, 0, 0, 1] [0, 1] [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] [1, 4, 6, 12] [1, 0, 0, 0] [1/2, 0, 0, 0] [1, 3, 4, 7, 6, 12, 8, 15, 13, 18] [] [1] [1, 3] [1, 3, 4] [1, 0, 0, 1, 0, 0, 0, 0, 1, 0] [1, 1, 1, 0, 1, 1, 1, 1, 0, 1] *** at top-level: direuler(p=I,10.5,1/((1-X)*(1-p*X))) *** ^------------------ *** incorrect type in gceil (t_COMPLEX). *** at top-level: direuler(p=2.5,I,1/((1-X)*(1-p*X))) *** ^------------------ *** incorrect type in gfloor (t_COMPLEX). *** at top-level: direuler(p=2,10,1/((1-X)*(1-p*X)),I) *** ^-------------------- *** incorrect type in gfloor (t_COMPLEX). [1] [1, 3] [1, 3, 0, 7, 0] *** at top-level: direuler(p=2,10,1/2) *** ^---- *** domain error in direuler: constant term != 1 *** at top-level: direuler(p=2,10,1/(x-2)) *** ^-------- *** domain error in direuler: constant term != 1 Total time spent: 0 pari-2.17.2/src/test/32/alghasse0000644000175000017500000001127014760124241014672 0ustar billbill *** Warning: new stack size = 12000000 (11.444 Mbytes). Suite: all Suite: hasse sum to 0 cyclo construction: [[x^2 + x + 1, [1], [3, -3], 1, [3], [], [[1, x], [1, 1] ], [1, 0; 0, 1], 1, [y, [1, 0], 1, 1, [Mat(1), Mat(1), Mat(16), Mat(1), 1, M at(1), [1, 0], []], [0.E-57], [1], Mat(1), Mat(1)], [x^2 + x + 1, 0, 0, y, x ^2 + x + 1], [[x^2 + x + 1, [0, 1], -3, 1, [Mat([1, -0.500000000000000000000 00000000000000000 + 0.86602540378443864676372317075293618347*I]), [1, 0.3660 2540378443864676372317075293618347; 1, -1.3660254037844386467637231707529361 835], [16, 6; 16, -22], [2, -1; -1, -1], [3, 2; 0, 1], [1, -1; -1, -2], [3, [2, -1; 1, 1]], [3]], [-0.50000000000000000000000000000000000000 + 0.8660254 0378443864676372317075293618347*I], [1, x], [1, 0; 0, 1], [1, 0, 0, -1; 0, 1 , 1, -1]], [[1; 0], Mat(1), 1, Vecsmall([1])]]], [-x - 1], Mod(-175624635, y ), Vecsmall([1]), [[[3, [3]~, 1, 1, 1], [5, [5]~, 1, 1, 1], [11708309, [1170 8309]~, 1, 1, 1]], Vecsmall([1, 1, 1])], 0, [1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1 , 2/3; 0, 0, 0, 1/3], [1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, -2; 0, 0, 0, 3], [[1 , 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [0, -1, 0, 0; 1, -1, 0, 0; 0 , 0, 1, 1; 0, 0, -3, -2], [0, 0, -175624635, -117083090; 0, 0, 0, -58541545; 1, -2, 0, 0; 0, 3, 0, 0], [0, 0, -58541545, -58541545; 0, 0, 58541545, 0; 0 , -1, 0, 0; 1, 1, 0, 0]], 0, [4, -2, 0, 0]] cyclo ramified at infinity: 1 cyclo unramified at infinity: 1 cyclo 5: 1 cyclo 5 bis: 1 cyclo 7 bis no mo: 1 cyclo 11 no mo: 1 quat -1,-1 over Q: 1 quat -1,-1 over Q(sqrt(2)): 1 quat -1,-1 over Q(sqrt(60)): 1 Suite: algebra from Hasse invariants matrix algebra invariants: 1 algebra 1 invariants: 1 algebra 2 invariants: 1 test: [[J^2 + 5, [1], [20, -5], 1, [2, 5], [], [[1, J], [1, 1]], [1, 0; 0, 1 ], 1, [y, [1, 0], 1, 1, [Mat(1), Mat(1), Mat(16), Mat(1), 1, Mat(1), [1, 0], []], [0.E-57], [1], Mat(1), Mat(1)], [J^2 + 5, 0, 0, y, J^2 + 5], [[J^2 + 5 , [0, 1], -20, 1, [Mat([1, 0.E-77 + 2.2360679774997896964091736687312762354* I]), [1, 2.2360679774997896964091736687312762354; 1, -2.23606797749978969640 91736687312762354], [16, 36; 16, -36], [2, 0; 0, -10], [10, 0; 0, 2], [5, 0; 0, -1], [5, [0, -5; 1, 0]], [2, 5]], [0.E-77 + 2.23606797749978969640917366 87312762354*I], [1, J], [1, 0; 0, 1], [1, 0, 0, -5; 0, 1, 1, 0]], [[1; 0], M at(1), 1, Vecsmall([1])]]], [-J], Mod(-39, y), Vecsmall([1]), [[[13, [13]~, 1, 1, 1], [2, [2]~, 1, 1, 1], [5, [5]~, 1, 1, 1], [3, [3]~, 1, 1, 1]], Vecsm all([1, 0, 0, 0])], 0, [1, 0, 1/2, 1; 0, 1, 0, 3/10; 0, 0, 1/2, 1/3; 0, 0, 0 , 1/30], [1, 0, -1, -20; 0, 1, 0, -9; 0, 0, 2, -20; 0, 0, 0, 30], [[1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [0, -5, 10, 5; 1, 0, 5, 4; 0, 0, 10 , 7; 0, 0, -15, -10], [0, -10, -10, -10; 0, -4, 0, -2; 1, -10, 1, -2; 0, 15, 0, 5], [0, -8, -4, -6; 0, -2, 2, 0; 0, -7, 4, 0; 1, 10, -4, 2]], 0, [4, 0, 2, 4]] degree 6 algebra over Q: 1 trivial finite conditions: [Vecsmall([1, 1]), [[[3, [3, 0]~, 1, 2, 1], [5, [ 1, 2]~, 2, 1, [1, 2; 2, -1]]], Vecsmall([0, 0])]] better accessors 1/2 0 3/4 0 1/4 1/2 2 1 4 1 4 2 4 0 0 1 0 1 0 1 0 1 0 1 0 0 0 1 0 1 0 1 1 1 [1, [2, [2, 0, 0]~, 1, 3, 1], [5, [2, 0, 1]~, 1, 1, [-1, 2, -3; 1, -2, -2; - 2, -1, -1]], [5, [-1, 1, -2]~, 1, 2, [2, -1, 1; 0, 2, 1; 1, 0, 2]]] 1/2 0 0 1/2 0 2 1 1 2 1 2 0 0 0 0 0 0 0 1 1 0 1 0 1 0 0 1 0 1 [1, [5, [2, 0, 1]~, 1, 1, [-1, 2, -3; 1, -2, -2; -2, -1, -1]]] 0 0 0 0 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 [] Hasse inv 0 bug 3 9 1 0 [2, 0, 0, 2, 0, 0, 3, 0, 0]~ [0, 0, 0, -2, 0, 0, -3, 0, 0]~ [0, 0, 0, 0, 0, 0, 0, 0, 0]~ tests with splitting field that does not descend [1, [2, [2, 0]~, 1, 2, 1]] [1, 2] [1, [5, [1, 2]~, 2, 1, [1, 2; 2, -1]]] [1, 4, [3, [0, -1, -1, 0]~, 2, 2, [0, -3, -3, 0; -1, 0, 0, -3; -1, 0, 0, 3; 0, -1, 1, 0]], [5, [-2, 2, 2, 0]~, 1, 2, [2, 6, 6, 0; 2, 2, 0, 6; 2, 0, 2, - 6; 0, 2, -2, 2]]] [2, [3, [0, -1, -1, 0]~, 2, 2, [0, -3, -3, 0; -1, 0, 0, -3; -1, 0, 0, 3; 0, -1, 1, 0]]] [1, 4, 5, [3, [-1, 0, 1, 0, 0, 1, -1, 1]~, 2, 2, [0, 0, 3, 3, 0, 0, -3, 3; 0 , 0, 0, 0, 0, -3, -3, 6; 1, 1, -2, -4, 1, 6, 3, -3; 1, -1, 0, 3, -1, -5, 0, 3; 0, 1, -1, -2, 1, 4, 0, -3; 0, -2, 2, 1, 1, -2, 0, 3; -1, -1, 2, 1, -1, 0, 0, 0; 1, 2, 0, 0, -1, 1, 0, 0]]] degree bug *** at top-level: al=alginit(nf,[4,[[p2,p3],[1/2,1/2]],[0]]);alg *** ^------------------------------------------- *** alginit: sorry, nfgrunwaldwang for nonprime degree is not yet implemented. 2 2 2 2 2 2 2 2 2 2 *** at top-level: al=alginit(nf,[4,[[p2,p3],[0,0]],[0]]);algdegr *** ^------------------------------------------- *** alginit: sorry, nfgrunwaldwang for nonprime degree is not yet implemented. 2 2 2 2 2 2 2 2 2 2 infinite loop in GW inefficiency in backtrackfacto bug: alg_complete at ramified primes Total time spent: 1990 pari-2.17.2/src/test/32/lll0000644000175000017500000000444514676526175013716 0ustar billbill [1 0] [0 1] [ 0 0 -8 5] [ 8 -5 26 -16] [ 13 -8 -5 3] [-21 13 8 -5] [1126210459758 -1822246802353 438668626759 709780747796] [ 5645342155 -9134355499 3372346191216 5456570759107] [1148588801119 709866918189 2349699119200 -1452193919001] [-965010535345 -596409310345 3157022227130 -1951147039605] [;] [;] [;] [[;], [;]] [[;], [;]] [;] Mat(1) Mat(1) Mat(1) [[;], Mat(1)] [[;], Mat(1)] Mat(1) [;] [;] Mat(1) [Mat(1), [;]] [Mat(1), [;]] [;] [1; 0] [1; 0] error("impossible inverse in dvmdii: 0.") [[-2; 1], [1; 0]] [[-2; 1], [1; 0]] [1; 0] error("incorrect type in rescale_to_int (t_POL).") error("incorrect type in rescale_to_int (t_POL).") error("incorrect type in qflll [integer matrix] (t_MAT).") error("incorrect type in qflll [integer matrix] (t_MAT).") [[x + 1; -x], [-1; 1]] [-1; 1] error("incorrect type in rescale_to_int (t_POL).") error("incorrect type in rescale_to_int (t_POL).") error("incorrect type in qflll [integer matrix] (t_MAT).") error("incorrect type in qflll [integer matrix] (t_MAT).") [[;], [-x^2 + 852*x + 833561, x^5 + 1052503*x^4 - 898292021*x^3 - 8780356471 55*x^2 + 1; 1, -x^3 - 1053355*x^2]] [-x^2 + 852*x + 833561, x^5 + 1052503*x^4 - 898292021*x^3 - 878035647155*x^2 + 1; 1, -x^3 - 1053355*x^2] [;] [;] [[;], [;]] [[;], [;]] [;] Mat(1) Mat(1) [[;], Mat(1)] [[;], Mat(1)] Mat(1) [;] [;] [Mat(1), [;]] [Mat(1), [;]] [;] [1; 0] [1; 0] [[-2; 1], [1; 0]] [[-2; 1], [1; 0]] [1; 0] error("incorrect type in rescale_to_int (t_POL).") error("incorrect type in rescale_to_int (t_POL).") error("incorrect type in qflllgram [integer matrix] (t_MAT).") [[x + 1; -x], [-1; 1]] [-1; 1] error("incorrect type in rescale_to_int (t_POL).") error("incorrect type in rescale_to_int (t_POL).") error("incorrect type in qflllgram [integer matrix] (t_MAT).") [[;], [-x^2 + 852*x + 833561, x^5 + 1052503*x^4 - 898292021*x^3 - 8780356471 55*x^2 + 1; 1, -x^3 - 1053355*x^2]] [-x^2 + 852*x + 833561, x^5 + 1052503*x^4 - 898292021*x^3 - 878035647155*x^2 + 1; 1, -x^3 - 1053355*x^2] *** at top-level: qflllgram([1,2,3;4,5,6]) *** ^------------------------ *** qflllgram: inconsistent dimensions in qflllgram. *** at top-level: qfminim([1,2,3;4,5,6],,,2) *** ^-------------------------- *** qfminim: inconsistent dimensions in qflllgram. Total time spent: 0 pari-2.17.2/src/test/32/nfeltembed0000644000175000017500000000147114567450071015222 0ustar billbill[1.2599210498948731647672106072782283506, -0.6299605249474365823836053036391 1417529 + 1.0911236359717214035600726141898088813*I] [-0.62996052494743658238360530363911417529 + 1.09112363597172140356007261418 98088813*I] [1.2599210498948731647672106072782283506, -0.6299605249474365823836053036391 1417529 + 1.0911236359717214035600726141898088813*I] *** at top-level: nfeltembed(nf,2,[1..3]) *** ^----------------------- *** nfeltembed: domain error in nfeltembed: index > 2 [-1.3160740129524924608192189017969990552, 1.3160740129524924608192189017969 990552, 0.E-57 + 1.3160740129524924608192189017969990552*I] *** at top-level: nfeltembed(nf,y,[1,2,4]) *** ^------------------------ *** nfeltembed: inconsistent variables in nf_to_scalar_or_basis, y != x. Total time spent: 0 pari-2.17.2/src/test/32/ellfromeqn0000644000175000017500000000407114760123736015260 0ustar billbill[r1, -q1*s1 + (-q2*s0 - r0*r2), (9*q0*q3 - q1*q2)*t0 + ((-q0*r2 - q2*r0)*s1 + (-q1*r2 - q3*r0)*s0), ((-3*q0*q2 + q1^2)*r2 + (-3*q1*q3 + q2^2)*r0)*t0 + ( q0*q2*s1^2 + ((-3*q0*q3 + q1*q2)*s0 + (q1*r0*r2 + q3*r0^2))*s1 + (q1*q3*s0^2 + (q0*r2^2 + q2*r0*r2)*s0)), (-27*q0^2*q3^2 + (9*q0*q1*q2 - q1^3)*q3 - q0*q 2^3)*t0^2 + (((9*q0^2*q3 - q0*q1*q2)*r2 + ((-3*q0*q1*q3 + q0*q2^2)*r1 + ((3* q0*q2 + 2*q1^2)*q3 - q1*q2^2)*r0))*s1 + (((3*q0*q1*q3 + (2*q0*q2^2 - q1^2*q2 ))*r2 + ((-3*q0*q2 + q1^2)*q3*r1 + (9*q0*q3^2 - q1*q2*q3)*r0))*s0 + (-q0^2*r 2^3 + (q0*q1*r1 + (2*q0*q2 - q1^2)*r0)*r2^2 + (-q0*q2*r1^2 + (-3*q0*q3 + q1* q2)*r0*r1 + (2*q1*q3 - q2^2)*r0^2)*r2 + (q0*q3*r1^3 - q1*q3*r0*r1^2 + q2*q3* r0^2*r1 - q3^2*r0^3))))*t0 + (-q0^2*q3*s1^3 + ((2*q0*q1*q3 - q0*q2^2)*s0 + ( -q0*q2*r0*r2 + (q0*q3*r0*r1 - q1*q3*r0^2)))*s1^2 + ((2*q0*q2 - q1^2)*q3*s0^2 + (-q0*q1*r2^2 + (q0*q2*r1 + (-q0*q3 - q1*q2)*r0)*r2 + (-q0*q3*r1^2 + q1*q3 *r0*r1 - q2*q3*r0^2))*s0)*s1 + (-q0*q3^2*s0^3 + (-q0*q2*r2^2 + (q0*q3*r1 - q 1*q3*r0)*r2)*s0^2))] [s1, -r2*t0 - s2*s0, (-r3*s0 - s2*r1)*t0, (r3*r1 - 4*r4*r0)*t0^2 + (r4*s0^2 + s2*r2*s0 + s2^2*r0)*t0, (4*r4*r0*r2 + (-r4*r1^2 - r3^2*r0))*t0^3 + (-r4*r0 *s1^2 + (r4*r1*s0 + r3*s2*r0)*s1 + (-r4*r2*s0^2 - r3*s2*r1*s0 - s2^2*r0*r2)) *t0^2] [s1, -r2*t0 - s2*s0, (-r3*s0 - s2*r1)*t0, (r3*r1 - 4*r4*r0)*t0^2 + (r4*s0^2 + s2*r2*s0 + s2^2*r0)*t0, (4*r4*r0*r2 + (-r4*r1^2 - r3^2*r0))*t0^3 + (-r4*r0 *s1^2 + (r4*r1*s0 + r3*s2*r0)*s1 + (-r4*r2*s0^2 - r3*s2*r1*s0 - s2^2*r0*r2)) *t0^2] [r1, -s2*t0 + (-t1*s1 + (-t2*s0 - r0*r2)), -r2*s1*t0 + (-t2*r0*s1 + (-t1*r2* s0 - t1*s2*r0)), (t2*s1^2 + t1*s2*s1 + ((r2^2 - 4*t2*s2)*s0 + s2*r0*r2))*t0 + ((t2*t1*s0 + t1*r0*r2)*s1 + ((t2*r0*r2 + t1^2*s2)*s0 + t2*s2*r0^2)), (-t2* s2*s1^2 + (-s2*r2^2 + 4*t2*s2^2)*s0)*t0^2 + ((-t2^2*s0 - t2*r0*r2)*s1^2 + (( -t1*r2^2 + t2*r1*r2)*s0 + (-t1*s2*r0*r2 + t2*s2*r0*r1))*s1 + ((-t2*r2^2 + 4* t2^2*s2)*s0^2 + (t1*s2*r1*r2 + (-t2*s2*r1^2 - t1^2*s2^2))*s0 - t2*s2^2*r0^2) )*t0 + ((-t2*t1*r0*r2*s0 - t2*t1*s2*r0^2)*s1 + (-t2*t1^2*s2*s0^2 + (-t1^2*s2 *r0*r2 + (t2*t1*s2*r0*r1 - t2^2*s2*r0^2))*s0))] Total time spent: 0 pari-2.17.2/src/test/32/ellanal0000644000175000017500000000172714676526175014543 0ustar billbill[0, 0.25384186085591068433775892335090946104] [1, 0.30599977383405230182048368332167647445] [2, 1.5186330005768535404603852157894440381] [3, 10.391099400715804138751850510360917070] [5, 9997.0334671722554999496820788093288459] [-339/16, 691/64] [-3, 12] [69648970982596494254458225/166136231668185267540804, 5389624350896046150780 04307258785218335/67716816556077455999228495435742408] [553/17424, 25469/2299968] [0, 2] 35 [2235340800, 70815596544000] 0 2.8053554406276820682921020105298729343 98.900778292211279593460469548777701095 1.5186330005768535404603852157894440381 0 2.80535544062768206829210201052987293427393419289431401051573873877896370606 9444052334712747100820315923332165307854 98.9007782922112795934604695487777010937256627866976192105130347193178645983 4656024843050255154457301289878660746148 1.51863300057685354046038521578944403815619503298984870317161018509598214549 5561104880431870004657718333754298413639 2 2 4 8 1 2 72 1/5 3/2 138240 Total time spent: 1261 pari-2.17.2/src/test/32/mat0000644000175000017500000004273614710152352013676 0ustar billbillerror("inconsistent addition t_MAT (1 x 1) + t_MAT (0 x 1).") error("impossible inverse in gdiv: [Mod(0, 2), Mod(0, 2); Mod(0, 2), Mod(0, 2)].") [0, 2] 1 1 [[;], [;]] [[], [;]] [-3.3612877988091253174761851599065654319, -3.976856899758389008450416890680 9665041, 2.9389389601206943824942150128578581054, 1.772259568771888526939788 0627029321445, -0.93302137188052358042404010605293659373, -0.441231719485000 70444920875205386881091, -0.19040285081078176048183742278228946814, 0.075729 288512033916496344069514741014185, 0.027956052637213235642340429324234659900 , 0.0096284368977104218404148935213290063312, -0.003106198327161964249988204 5902715205667, -0.00094157426540918912117035392430195067794, -0.000268854775 30463015261353875607132041931, -7.2459011321751905080067220992031631462 E-5, 1.8462089149768956890169300433744512910 E-5, 4.4528901897458304967947732271 708068875 E-6, 1.0176789800383226364895152347151747510 E-6, 2.20552412091014 57554655197057289803706 E-7, -4.5349036687475247266974601071424129857 E-8, - 8.8492541140723057133731328535614376294 E-9, -1.6389333061355481368271925736 504820724 E-9, -2.8805272156166119158730325675280896976 E-10, -4.80266664969 65909745773739693929989064 E-11, 7.5916176882374260025503147422014772958 E-1 2, -1.1367331397963498149955520074031835155 E-12, -1.61050664103939094109404 49194291021230 E-13, 2.1558223640276402145487596709860808075 E-14, 2.7214689 692178509667012624472480322726 E-15, -3.232659043848202709644832083123995151 3 E-16, -2.9855883849239760043478182416536329854 E-17, -1.664898755959816497 7470350196661697536 E-17, 2.8771625420725328021428672070297279667 E-18, -1.0 319233712195941381068955784281641143 E-18, 1.6356182814790027911170768841203 266890 E-18, 8.0811640833543317283367798799396420333 E-19, -1.05792311976124 33100847548785453343223 E-19, 3.1212834491595151717446703076475681855 E-20, -6.2236951167032034426610950988624421246 E-20, -4.30278526231190452813726222 95990239750 E-20, -2.7525464198315767914815519496564758696 E-20]~ [;] [1] [Mat(2)] Mat([Mat(2)]) [1 2 3] [2 3 4] [1 1] [1 5] [1 0] [0 1] error("incorrect type in diagonal (t_MAT).") [1 0 0 0 0] [1 1 0 0 0] [1 3/2 1 0 0] [1 7/4 7/4 1 0] [1 15/8 35/16 15/8 1] [ 4 6] [10 12] [0 -2] [2 4] [0 0] [Mod(0, 2) Mod(0, 2)] [Mod(0, 2) Mod(0, 2)] [Mod(0, 2) Mod(0, 2)] [Mod(0, 7) Mod(5, 7)] [Mod(2, 7) Mod(4, 7)] [Mod(0, 7) Mod(0, 7)] [Mod(0, 18446744073709551629) Mod(18446744073709551627, 18446744073709551629 )] [Mod(2, 18446744073709551629) Mod(4, 18446744073709551629 )] [Mod(0, 18446744073709551629) Mod(0, 18446744073709551629 )] [Mod(0, 3037000507) Mod(3037000505, 3037000507)] [Mod(2, 3037000507) Mod(4, 3037000507)] [Mod(0, 3037000507) Mod(0, 3037000507)] [Mod(0, 2), Mod(0, 2), Mod(0, 2)]~ [Mod(0, 7), Mod(2, 7), Mod(0, 7)]~ [Mod(0, 18446744073709551629), Mod(2, 18446744073709551629), Mod(0, 18446744 073709551629)]~ [Mod(0, 3037000507), Mod(2, 3037000507), Mod(0, 3037000507)]~ matdet: Mod(1, 2) Mod(1, 7) Mod(29, 3037000507) Mod(29, 18446744073709551629) 29 + O(101^3) matrank: 3 3 3 3 3 matadjoint: [Mod(1, 2), Mod(0, 2), Mod(0, 2); Mod(0, 2), Mod(1, 2), Mod(1, 2); Mod(0, 2) , Mod(1, 2), Mod(0, 2)] [Mod(6, 7), Mod(0, 7), Mod(1, 7); Mod(6, 7), Mod(3, 7), Mod(1, 7); Mod(1, 7) , Mod(2, 7), Mod(1, 7)] [Mod(69, 3037000507), Mod(14, 3037000507), Mod(3037000473, 3037000507); Mod( 3037000499, 3037000507), Mod(3, 3037000507), Mod(1, 3037000507); Mod(3037000 501, 3037000507), Mod(3037000502, 3037000507), Mod(8, 3037000507)] [Mod(69, 18446744073709551629), Mod(14, 18446744073709551629), Mod(184467440 73709551595, 18446744073709551629); Mod(18446744073709551621, 18446744073709 551629), Mod(3, 18446744073709551629), Mod(1, 18446744073709551629); Mod(184 46744073709551623, 18446744073709551629), Mod(18446744073709551624, 18446744 073709551629), Mod(8, 18446744073709551629)] [69 + O(101^3), 14 + O(101^3), 67 + 100*101 + 100*101^2 + O(101^3); 93 + 100 *101 + 100*101^2 + O(101^3), 3 + O(101^3), 1 + O(101^3); 95 + 100*101 + 100* 101^2 + O(101^3), 96 + 100*101 + 100*101^2 + O(101^3), 8 + O(101^3)] matimage: [Mod(1, 2), Mod(0, 2), Mod(0, 2); Mod(0, 2), Mod(0, 2), Mod(1, 2); Mod(0, 2) , Mod(1, 2), Mod(1, 2)] [Mod(1, 7), Mod(2, 7), Mod(4, 7); Mod(2, 7), Mod(5, 7), Mod(0, 7); Mod(2, 7) , Mod(2, 7), Mod(4, 7)] [Mod(1, 3037000507), Mod(2, 3037000507), Mod(4, 3037000507); Mod(2, 30370005 07), Mod(12, 3037000507), Mod(7, 3037000507); Mod(2, 3037000507), Mod(9, 303 7000507), Mod(11, 3037000507)] [Mod(1, 18446744073709551629), Mod(2, 18446744073709551629), Mod(4, 18446744 073709551629); Mod(2, 18446744073709551629), Mod(12, 18446744073709551629), Mod(7, 18446744073709551629); Mod(2, 18446744073709551629), Mod(9, 184467440 73709551629), Mod(11, 18446744073709551629)] [1 + O(101^3), 2 + O(101^3), 4 + O(101^3); 2 + O(101^3), 12 + O(101^3), 7 + O(101^3); 2 + O(101^3), 9 + O(101^3), 11 + O(101^3)] matimagecompl: Vecsmall([]) Vecsmall([]) Vecsmall([]) Vecsmall([]) Vecsmall([]) matindexrank: [Vecsmall([1, 2, 3]), Vecsmall([1, 2, 3])] [Vecsmall([1, 2, 3]), Vecsmall([1, 2, 3])] [Vecsmall([1, 2, 3]), Vecsmall([1, 2, 3])] [Vecsmall([1, 2, 3]), Vecsmall([1, 2, 3])] [Vecsmall([1, 2, 3]), Vecsmall([1, 2, 3])] matker: [;] [;] [;] [;] [;] lindep: []~ []~ []~ []~ []~ (x)->matsolve(x,vectorv(#x,i,i)): [Mod(1, 2), Mod(1, 2), Mod(0, 2)]~ [Mod(2, 7), Mod(1, 7), Mod(1, 7)]~ [Mod(2827552196, 3037000507), Mod(1256689865, 3037000507), Mod(942517399, 30 37000507)]~ [Mod(16538460204015460081, 18446744073709551629), Mod(11449703218164549287, 18446744073709551629), Mod(17810649450478187780, 18446744073709551629)]~ [66 + 69*101 + 62*101^2 + O(101^3), 7 + 87*101 + 27*101^2 + O(101^3), 56 + 9 0*101 + 20*101^2 + O(101^3)]~ (x)->matsolve(x,matrix(#x,#x,i,j,i+j)): [Mod(0, 2), Mod(1, 2), Mod(0, 2); Mod(1, 2), Mod(1, 2), Mod(1, 2); Mod(1, 2) , Mod(0, 2), Mod(1, 2)] [Mod(2, 7), Mod(2, 7), Mod(2, 7); Mod(4, 7), Mod(0, 7), Mod(3, 7); Mod(5, 7) , Mod(2, 7), Mod(6, 7)] [Mod(628344934, 3037000507), Mod(1466138179, 3037000507), Mod(2303931424, 30 37000507); Mod(2303931419, 3037000507), Mod(314172466, 3037000507), Mod(1361 414020, 3037000507); Mod(209448311, 3037000507), Mod(2513379730, 3037000507) , Mod(1780310642, 3037000507)] [Mod(5724851609082274645, 18446744073709551629), Mod(13357987087858640838, 1 8446744073709551629), Mod(2544378492925455402, 18446744073709551629); Mod(25 44378492925455397, 18446744073709551629), Mod(12085797841395913136, 18446744 073709551629), Mod(3180473116156819246, 18446744073709551629); Mod(190828386 9694091548, 18446744073709551629), Mod(4452662362619546945, 1844674407370955 1629), Mod(6997040855545002342, 18446744073709551629)] [5 + 94*101 + 13*101^2 + O(101^3), 45 + 17*101 + 66*101^2 + O(101^3), 85 + 4 1*101 + 17*101^2 + O(101^3); 80 + 41*101 + 17*101^2 + O(101^3), 52 + 97*101 + 6*101^2 + O(101^3), 24 + 52*101 + 97*101^2 + O(101^3); 35 + 31*101 + 38*10 1^2 + O(101^3), 14 + 73*101 + 55*101^2 + O(101^3), 94 + 13*101 + 73*101^2 + O(101^3)] (x)->x^(-1): [Mod(1, 2), Mod(0, 2), Mod(0, 2); Mod(0, 2), Mod(1, 2), Mod(1, 2); Mod(0, 2) , Mod(1, 2), Mod(0, 2)] [Mod(6, 7), Mod(0, 7), Mod(1, 7); Mod(6, 7), Mod(3, 7), Mod(1, 7); Mod(1, 7) , Mod(2, 7), Mod(1, 7)] [Mod(1675586489, 3037000507), Mod(2408655575, 3037000507), Mod(2827552195, 3 037000507); Mod(2094483108, 3037000507), Mod(733069088, 3037000507), Mod(125 6689865, 3037000507); Mod(1570862331, 3037000507), Mod(2827552196, 303700050 7), Mod(942517399, 3037000507)] [Mod(15266270957552732385, 18446744073709551629), Mod(12721892464627276986, 18446744073709551629), Mod(16538460204015460080, 18446744073709551629); Mod( 636094623231363849, 18446744073709551629), Mod(15902365580784096232, 1844674 4073709551629), Mod(11449703218164549287, 18446744073709551629); Mod(5088756 985850910794, 18446744073709551629), Mod(16538460204015460081, 1844674407370 9551629), Mod(17810649450478187780, 18446744073709551629)] [79 + 48*101 + 3*101^2 + O(101^3), 98 + 6*101 + 87*101^2 + O(101^3), 65 + 69 *101 + 62*101^2 + O(101^3); 45 + 10*101 + 80*101^2 + O(101^3), 21 + 59*101 + 83*101^2 + O(101^3), 7 + 87*101 + 27*101^2 + O(101^3); 59 + 83*101 + 34*101 ^2 + O(101^3), 66 + 69*101 + 62*101^2 + O(101^3), 56 + 90*101 + 20*101^2 + O (101^3)] (x)->x^2: [Mod(1, 2), Mod(0, 2), Mod(0, 2); Mod(0, 2), Mod(1, 2), Mod(1, 2); Mod(0, 2) , Mod(1, 2), Mod(0, 2)] [Mod(6, 7), Mod(6, 7), Mod(6, 7); Mod(5, 7), Mod(1, 7), Mod(1, 7); Mod(0, 7) , Mod(1, 7), Mod(3, 7)] [Mod(13, 3037000507), Mod(62, 3037000507), Mod(62, 3037000507); Mod(40, 3037 000507), Mod(211, 3037000507), Mod(169, 3037000507); Mod(42, 3037000507), Mo d(211, 3037000507), Mod(192, 3037000507)] [Mod(13, 18446744073709551629), Mod(62, 18446744073709551629), Mod(62, 18446 744073709551629); Mod(40, 18446744073709551629), Mod(211, 184467440737095516 29), Mod(169, 18446744073709551629); Mod(42, 18446744073709551629), Mod(211, 18446744073709551629), Mod(192, 18446744073709551629)] [13 + O(101^3), 62 + O(101^3), 62 + O(101^3); 40 + O(101^3), 9 + 2*101 + O(1 01^3), 68 + 101 + O(101^3); 42 + O(101^3), 9 + 2*101 + O(101^3), 91 + 101 + O(101^3)] (x)->A*x: [Mod(1, 2), Mod(0, 2), Mod(0, 2); Mod(0, 2), Mod(1, 2), Mod(1, 2); Mod(0, 2) , Mod(1, 2), Mod(0, 2)] [Mod(6, 7), Mod(6, 7), Mod(6, 7); Mod(5, 7), Mod(1, 7), Mod(1, 7); Mod(0, 7) , Mod(1, 7), Mod(3, 7)] [Mod(13, 3037000507), Mod(62, 3037000507), Mod(62, 3037000507); Mod(40, 3037 000507), Mod(211, 3037000507), Mod(169, 3037000507); Mod(42, 3037000507), Mo d(211, 3037000507), Mod(192, 3037000507)] [Mod(13, 18446744073709551629), Mod(62, 18446744073709551629), Mod(62, 18446 744073709551629); Mod(40, 18446744073709551629), Mod(211, 184467440737095516 29), Mod(169, 18446744073709551629); Mod(42, 18446744073709551629), Mod(211, 18446744073709551629), Mod(192, 18446744073709551629)] [13 + O(101^3), 62 + O(101^3), 62 + O(101^3); 40 + O(101^3), 9 + 2*101 + O(1 01^3), 68 + 101 + O(101^3); 42 + O(101^3), 9 + 2*101 + O(101^3), 91 + 101 + O(101^3)] [;] matdet: 1 1 1 1 1 matrank: 0 0 0 0 0 matadjoint: [;] [;] [;] [;] [;] matimage: [;] [;] [;] [;] [;] matimagecompl: Vecsmall([]) Vecsmall([]) Vecsmall([]) Vecsmall([]) Vecsmall([]) matindexrank: [Vecsmall([]), Vecsmall([])] [Vecsmall([]), Vecsmall([])] [Vecsmall([]), Vecsmall([])] [Vecsmall([]), Vecsmall([])] [Vecsmall([]), Vecsmall([])] matker: [;] [;] [;] [;] [;] lindep: []~ []~ []~ []~ []~ (x)->matsolve(x,vectorv(#x,i,i)): []~ []~ []~ []~ []~ (x)->matsolve(x,matrix(#x,#x,i,j,i+j)): [;] [;] [;] [;] [;] (x)->x^(-1): [;] [;] [;] [;] [;] (x)->x^2: [;] [;] [;] [;] [;] (x)->A*x: [;] [;] [;] [;] [;] Mod(3037000506, 3037000507) Mod(18446744073709551628, 18446744073709551629) [Mod(3, 18446744073709551629), Mod(1, 18446744073709551629), Mod(18446744073 709551628, 18446744073709551629)]~ [1 2] [3 4] [2 4] [6 8] [Mod(1, 2) Mod(0, 2)] [Mod(1, 2) Mod(0, 2)] [Mod(1, 3) Mod(2, 3)] [Mod(0, 3) Mod(1, 3)] [Mod(1, 18446744073709551629) Mod(2, 18446744073709551629)] [Mod(3, 18446744073709551629) Mod(4, 18446744073709551629)] [1 0] [1 0] [1/2] [ -2] [ 1] [-1.0000000000000000000000000000000000000*I] [ 1] [-1] [ 1] 3 0 error("inconsistent dimensions in gtrace.") [1 0] [0 1] [;] 19009323 [2 0] [0 2] [1 0] [0 1] [2 0] [0 2] [1 0] [0 1] [1] [0] [1] [0] [;] [1 0 0] [0 1 0] [0 0 1] [2958 2373] [1785 1440] [ 812 666] [ 0 20] [1 0] [0 0] [0 1] [ 266 -43 -104 -46] [-183 30 72 31] [ -22 2 8 5] [ 314 -49 -123 -55] [ 100 -15 -39 -18] lindep: [1, 0, 1]~ [1, -2, 1]~ [1, -2, 1]~ [1, -2, 1]~ [3 + O(101^3), 95 + 100*101 + 100*101^2 + O(101^3), 3 + O(101^3)]~ matsupplement: [Mod(1, 2), Mod(0, 2), Mod(0, 2); Mod(0, 2), Mod(1, 2), Mod(0, 2); Mod(1, 2) , Mod(0, 2), Mod(1, 2)] [Mod(1, 7), Mod(2, 7), Mod(0, 7); Mod(4, 7), Mod(5, 7), Mod(0, 7); Mod(0, 7) , Mod(1, 7), Mod(1, 7)] [Mod(1, 3037000507), Mod(2, 3037000507), Mod(0, 3037000507); Mod(4, 30370005 07), Mod(5, 3037000507), Mod(0, 3037000507); Mod(7, 3037000507), Mod(8, 3037 000507), Mod(1, 3037000507)] [Mod(1, 18446744073709551629), Mod(2, 18446744073709551629), Mod(0, 18446744 073709551629); Mod(4, 18446744073709551629), Mod(5, 18446744073709551629), M od(0, 18446744073709551629); Mod(7, 18446744073709551629), Mod(8, 1844674407 3709551629), Mod(1, 18446744073709551629)] [1 + O(101^3), 2 + O(101^3), 0; 4 + O(101^3), 5 + O(101^3), 0; 7 + O(101^3), 8 + O(101^3), 1] matsupplement: [Mod(1, 2), Mod(0, 2), Mod(0, 2), Mod(0, 2), Mod(0, 2); Mod(0, 2), Mod(1, 2) , Mod(0, 2), Mod(0, 2), Mod(0, 2); Mod(0, 2), Mod(0, 2), Mod(1, 2), Mod(0, 2 ), Mod(0, 2); Mod(0, 2), Mod(0, 2), Mod(0, 2), Mod(1, 2), Mod(0, 2); Mod(0, 2), Mod(0, 2), Mod(0, 2), Mod(0, 2), Mod(1, 2)] [Mod(1, 7), Mod(0, 7), Mod(0, 7), Mod(0, 7), Mod(0, 7); Mod(0, 7), Mod(1, 7) , Mod(0, 7), Mod(0, 7), Mod(0, 7); Mod(0, 7), Mod(0, 7), Mod(1, 7), Mod(0, 7 ), Mod(0, 7); Mod(0, 7), Mod(0, 7), Mod(0, 7), Mod(1, 7), Mod(0, 7); Mod(0, 7), Mod(0, 7), Mod(0, 7), Mod(0, 7), Mod(1, 7)] [Mod(1, 3037000507), Mod(0, 3037000507), Mod(0, 3037000507), Mod(0, 30370005 07), Mod(0, 3037000507); Mod(0, 3037000507), Mod(1, 3037000507), Mod(0, 3037 000507), Mod(0, 3037000507), Mod(0, 3037000507); Mod(0, 3037000507), Mod(0, 3037000507), Mod(1, 3037000507), Mod(0, 3037000507), Mod(0, 3037000507); Mod (0, 3037000507), Mod(0, 3037000507), Mod(0, 3037000507), Mod(1, 3037000507), Mod(0, 3037000507); Mod(0, 3037000507), Mod(0, 3037000507), Mod(0, 30370005 07), Mod(0, 3037000507), Mod(1, 3037000507)] [Mod(1, 18446744073709551629), Mod(0, 18446744073709551629), Mod(0, 18446744 073709551629), Mod(0, 18446744073709551629), Mod(0, 18446744073709551629); M od(0, 18446744073709551629), Mod(1, 18446744073709551629), Mod(0, 1844674407 3709551629), Mod(0, 18446744073709551629), Mod(0, 18446744073709551629); Mod (0, 18446744073709551629), Mod(0, 18446744073709551629), Mod(1, 184467440737 09551629), Mod(0, 18446744073709551629), Mod(0, 18446744073709551629); Mod(0 , 18446744073709551629), Mod(0, 18446744073709551629), Mod(0, 18446744073709 551629), Mod(1, 18446744073709551629), Mod(0, 18446744073709551629); Mod(0, 18446744073709551629), Mod(0, 18446744073709551629), Mod(0, 1844674407370955 1629), Mod(0, 18446744073709551629), Mod(1, 18446744073709551629)] [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] *** Warning: new stack size = 1000000 (0.954 Mbytes). 68 2 68 68 [-6 -6] [-7 -7] [ 9 0] [ 0 9] 0 2 17 1 6 0 0 0 Vecsmall([0, 0, 0]) Vecsmall([3, 12, 27]) 3 0 Vecsmall([2, 2, 0, -4, -10]) 2 [1 0 0] [0 0 1] [1 0 0] [0 0 1] [1 0 0] [0 0 1] [1 0] [1 0] [1 2] [0 1] [1 2] [3 4] [1 0 0] [0 0 1] [1 0 0] [0 0 1] [1 0 0] [0 0 1] [1, 2, 3] [1 2 3] [1 2 3] [2, 4, 6] [2 4 6] [1 2 3] [;] [;] [;] [;] [;] *** Warning: new stack size = 16000000 (15.259 Mbytes). [0 -1 0] [0 1 1] [ -2 1 0] [3/2 -1/2 0] [;] 30 [[100, 100], [200, 200]] [3 4] [y 7] matrix(0,2) matrix(0,2) [1 4] [2 2] [3 1] [1 1] [2 1] [1 1] *** at top-level: 1/Mat([0,0]~) *** ^------------ *** _/_: impossible inverse in ginv: 0. *** at top-level: mathouseholder(1,1) *** ^------------------- *** mathouseholder: incorrect type in mathouseholder (t_INT). *** at top-level: [q,r]=matqr(matid(2),1);mathouseholder(q,1) *** ^------------------- *** mathouseholder: incorrect type in mathouseholder (t_INT). *** at top-level: matsolve([1,0;0,0]*Mod(1,2),[1,1]~) *** ^----------------------------------- *** matsolve: impossible inverse in gauss: [Mod(1, 2), Mod(0, 2); Mod(0, 2), Mod(0, 2)]. *** at top-level: matsolve([1,0;0,0]*Mod(1,3),[1,1]~) *** ^----------------------------------- *** matsolve: impossible inverse in gauss: [Mod(1, 3), Mod(0, 3); Mod(0, 3), Mod(0, 3)]. *** at top-level: vecsum(1) *** ^--------- *** vecsum: incorrect type in vecsum (t_INT). *** at top-level: 1~ *** ^-- *** _~: incorrect type in gtrans (t_INT). *** at top-level: vectorsmall(3,i,i^100) *** ^------ *** overflow in t_INT-->long assignment. *** at top-level: m[1,]=[1,2] *** ^----------- *** inconsistent dimensions in matrix row assignment. *** at top-level: m[1,]=[1,2,3,4] *** ^--------------- *** inconsistent dimensions in matrix row assignment. *** at top-level: m[1,]=[1,2,3]~ *** ^-------------- *** incorrect type in matrix row assignment (t_COL). *** at top-level: [1,2,3;4,5,6]^-1 *** ^--- *** _inv: impossible inverse in ginv: [1, 2, 3; 4, 5, 6]. *** at top-level: [1,2,3;4,5,6;7,8,9]^-1 *** ^--- *** _inv: impossible inverse in ginv: 0. *** at top-level: matrixqz(matrix(2,2)) *** ^--------------------- *** matrixqz: domain error in QM_minors_coprime: rank(A) < 2 *** at top-level: matrixqz([;],-3) *** ^---------------- *** matrixqz: invalid flag in QM_minors_coprime. *** at top-level: matreduce(1) *** ^------------ *** matreduce: incorrect type in matreduce (t_INT). *** at top-level: matreduce([;]) *** ^-------------- *** matreduce: incorrect type in matreduce (t_MAT). *** at top-level: matreduce([1,x;1,y]) *** ^-------------------- *** matreduce: incorrect type in matreduce (t_MAT). *** at top-level: [[1,2;1,3],[2,1]]^-1 *** ^--- *** _inv: incorrect type in inverse (t_VEC). *** at top-level: Mat(0)/Mat(0) *** ^------- *** _/_: impossible inverse in gdiv: Mat(0). Total time spent: 788 pari-2.17.2/src/test/32/binomial0000644000175000017500000000117314676526175014720 0ustar billbill *** Warning: new stack size = 34000000 (32.425 Mbytes). 1/2*x^2 - 1/2*x 20 [1, 6, 15, 20, 15, 6, 1] 4824670384888174806699998652284212509450915553158197754113741817487466430465 0 1 1487335486 3 0 3 -1 -4 Mod(0, 3) Mod(0, 3) Mod(1, 3) *** at top-level: binomial(1,2.) *** ^-------------- *** binomial: incorrect type in binomial (t_REAL). *** at top-level: binomial(-1) *** ^------------ *** binomial: incorrect type in binomial (t_INT). *** at top-level: binomial(1.) *** ^------------ *** binomial: incorrect type in binomial (t_REAL). Total time spent: 211 pari-2.17.2/src/test/32/qf0000644000175000017500000000412714676526175013536 0ustar billbill[] [7/2 1 8/7 11/7] [ -1 -7/2 -4/7 -5/7] [ 0 0 -24/7 -29/24] [ 0 0 0 -311/168] [12, 1] 266 Vecsmall([0, 0, 0, 0, 0, 0, 0, 133, 0, 165, 0, 638, 0, 396, 0, 4268]) Vecsmall([0, 0, 0, 133, 165, 638, 396, 4268]) [8, [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]~] [8, [2, 2, -1, -1, 1, 1, -2, 0, -1, -1, -1, -1]~] [] [] [0, 0, [;]] [2, 1.0000000000000000000000000000000000000, Mat(1)] [0, 0, [;]] [] [0, 0, [;]] -124 *** at top-level: qfminim(L~*L,10^16)[2] *** ^---------------------- *** qfminim: precision too low in qfminim. 10000000000000000.000 [1, 0]~ [0, 1]~ [1, -1]~ [1, -1]~ [0, 0, [;]] [0, 0, [;]] 14 23 2 -13 [66 78 90] [78 93 108] [90 108 126] [35 67 99] [67 110 153] [99 153 207] *** at top-level: qfeval(,1) *** ^---------- *** qfeval: incorrect type in qfeval (t_INT). *** at top-level: qfeval(,1,1) *** ^------------ *** qfeval: incorrect type in qfeval (t_INT). *** at top-level: qfeval(Mat(1),x) *** ^---------------- *** qfeval: inconsistent dimensions in qfeval. *** at top-level: qfeval(Mat(x~),x) *** ^----------------- *** qfeval: inconsistent dimensions in qfeval. *** at top-level: qfeval(,1,1) *** ^------------ *** qfeval: incorrect type in qfeval (t_INT). *** at top-level: qfeval(,[1],[1,2]) *** ^------------------ *** qfeval: inconsistent dimensions in qfeval. *** at top-level: qfeval(q,[1,2],[1,2]) *** ^--------------------- *** qfeval: inconsistent dimensions in qfevalb. *** at top-level: qfeval(Mat([1,2]),[1,2],[1,2]) *** ^------------------------------ *** qfeval: inconsistent operation 'RgV_RgM_mul' t_VEC (2 elts) , t_MAT (1 x 2). *** at top-level: qfeval(1,1) *** ^----------- *** qfeval: incorrect type in qfeval (t_INT). *** at top-level: ...forqfvec(v,Q,N,if(qfeval(Q,v)>N,error(v))) *** ^----------------- *** precision too low in forqfvec. Total time spent: 7 pari-2.17.2/src/test/32/forsubset0000644000175000017500000000067414567450071015135 0ustar billbillVecsmall([]) Vecsmall([1]) Vecsmall([2]) Vecsmall([3]) Vecsmall([4]) Vecsmall([1, 2]) Vecsmall([1, 3]) Vecsmall([1, 4]) Vecsmall([2, 3]) Vecsmall([2, 4]) Vecsmall([3, 4]) Vecsmall([1, 2, 3]) Vecsmall([1, 2, 4]) Vecsmall([1, 3, 4]) Vecsmall([2, 3, 4]) Vecsmall([1, 2, 3, 4]) Vecsmall([]) Vecsmall([]) *** at top-level: forsubset('x,s,) *** ^---------------- *** incorrect type in forsubset (t_POL). Total time spent: 0 pari-2.17.2/src/test/32/div0000644000175000017500000007117714676526175013723 0ustar billbill* [1, 1] 1 1 0 1 [1, 0]~ * [1, 2] 3/4 0 3 1 [0, 3]~ * [1, 3] 0.96774193548387096774193548387096774194 0 3 1 [0, 3]~ * [1, 4] 6 6 0 6 [6, 0]~ * [1, 5] 3/(x^2 + 1) 0 3 0 [0, 3]~ * [1, 6] Mod(-3*x, x^2 + 1) error("forbidden division t_INT \\ t_POLMOD.") error("forbidden division t_INT % t_POLMOD.") error("forbidden division t_INT \\ t_POLMOD.") error("forbidden division t_INT \\ t_POLMOD.") * [1, 7] 0 error("forbidden division t_INT \\ t_FFELT.") error("forbidden division t_INT % t_FFELT.") error("forbidden division t_INT \\ t_FFELT.") error("forbidden division t_INT \\ t_FFELT.") * [1, 8] -3 + 3*w 1 3 - w 2 [1, 3 - w]~ * [1, 9] -3/2*w error("forbidden division t_INT \\ t_QUAD.") error("forbidden division t_INT % t_QUAD.") error("forbidden division t_INT \\ t_QUAD.") error("forbidden division t_INT \\ t_QUAD.") * [1, 10] 2*3 + 3^2 + 3^3 + O(3^4) error("forbidden division t_INT \\ t_PADIC.") error("forbidden division t_INT % t_PADIC.") error("forbidden division t_INT \\ t_PADIC.") error("forbidden division t_INT \\ t_PADIC.") * [1, 11] Mod(0, 3) error("forbidden division t_INT \\ t_INTMOD.") error("forbidden division t_INT % t_INTMOD.") error("forbidden division t_INT \\ t_INTMOD.") error("forbidden division t_INT \\ t_INTMOD.") * [1, 12] 3/18446744073709551617 0 3 0 [0, 3]~ * [2, 1] 4/3 1 1 1 [1, 1]~ * [2, 2] 1 1 0 1 [1, 0]~ * [2, 3] 1.2903225806451612903225806451612903226 1 0.90000000000000000000000000000000000000 1 [1, 0.90000000000000000000000000000000000000]~ * [2, 4] 8 8 0 8 [8, 0]~ * [2, 5] 4/(x^2 + 1) 0 4 0 [0, 4]~ * [2, 6] Mod(-4*x, x^2 + 1) error("forbidden division t_INT \\ t_POLMOD.") error("forbidden division t_INT % t_POLMOD.") error("forbidden division t_INT \\ t_POLMOD.") error("forbidden division t_INT \\ t_POLMOD.") * [2, 7] 2*t^4 + 2*t^3 + t^2 error("forbidden division t_INT \\ t_FFELT.") error("forbidden division t_INT % t_FFELT.") error("forbidden division t_INT \\ t_FFELT.") error("forbidden division t_INT \\ t_FFELT.") * [2, 8] -4 + 4*w 2 4 - 2*w 2 [2, 4 - 2*w]~ * [2, 9] -2*w error("forbidden division t_INT \\ t_QUAD.") error("forbidden division t_INT % t_QUAD.") error("forbidden division t_INT \\ t_QUAD.") error("forbidden division t_INT \\ t_QUAD.") * [2, 10] 2 + O(3^3) error("forbidden division t_INT \\ t_PADIC.") error("forbidden division t_INT % t_PADIC.") error("forbidden division t_INT \\ t_PADIC.") error("forbidden division t_INT \\ t_PADIC.") * [2, 11] Mod(2, 3) error("forbidden division t_INT \\ t_INTMOD.") error("forbidden division t_INT % t_INTMOD.") error("forbidden division t_INT \\ t_INTMOD.") error("forbidden division t_INT \\ t_INTMOD.") * [2, 12] 4/18446744073709551617 0 4 0 [0, 4]~ * [3, 1] 1.0333333333333333333333333333333333333 1 0.099999999999999999999999999999999999995 1 [1, 0.099999999999999999999999999999999999995]~ * [3, 2] 0.77500000000000000000000000000000000000 0 3.1000000000000000000000000000000000000 1 [0, 3.1000000000000000000000000000000000000]~ * [3, 3] 1.0000000000000000000000000000000000000 1 0.E-37 1 [1, 0.E-37]~ * [3, 4] 6.2000000000000000000000000000000000000 6 0.099999999999999999999999999999999999995 6 [6, 0.099999999999999999999999999999999999995]~ * [3, 5] 3.1000000000000000000000000000000000000/(x^2 + 1) 0 3.1000000000000000000000000000000000000 0 [0, 3.1000000000000000000000000000000000000]~ * [3, 6] Mod(-3.1000000000000000000000000000000000000*x, x^2 + 1) error("forbidden division t_REAL \\ t_POLMOD.") error("forbidden division t_REAL % t_POLMOD.") error("forbidden division t_REAL \\ t_POLMOD.") error("forbidden division t_REAL \\ t_POLMOD.") * [3, 7] error("forbidden division t_REAL / t_FFELT.") error("forbidden division t_REAL \\ t_FFELT.") error("forbidden division t_REAL % t_FFELT.") error("forbidden division t_REAL \\ t_FFELT.") error("forbidden division t_REAL \\ t_FFELT.") * [3, 8] 1.9159053651246740294342191865334781649 1 1.4819660112501051517954131656343618823 2 [1, 1.4819660112501051517954131656343618823]~ * [3, 9] 0.E-38 - 2.1920310216782973256426175225250320218*I error("forbidden division t_REAL \\ t_QUAD.") error("forbidden division t_REAL % t_QUAD.") error("forbidden division t_REAL \\ t_QUAD.") error("forbidden division t_REAL \\ t_QUAD.") * [3, 10] error("forbidden division t_REAL / t_PADIC.") error("forbidden division t_REAL \\ t_PADIC.") error("forbidden division t_REAL % t_PADIC.") error("forbidden division t_REAL \\ t_PADIC.") error("forbidden division t_REAL \\ t_PADIC.") * [3, 11] error("forbidden division t_REAL / t_INTMOD.") error("forbidden division t_REAL \\ t_INTMOD.") error("forbidden division t_REAL % t_INTMOD.") error("forbidden division t_REAL \\ t_INTMOD.") error("forbidden division t_REAL \\ t_INTMOD.") * [3, 12] 1.6805133673525318726204510291596823708 E-19 0 3.1000000000000000000000000000000000000 0 [0, 3.1000000000000000000000000000000000000]~ * [4, 1] 1/6 0 2 0 [0, 1/2]~ * [4, 2] 1/8 0 error("impossible inverse in Fl_inv: Mod(2, 4).") 0 [0, 1/2]~ * [4, 3] 0.16129032258064516129032258064516129032 0 1/2 0 [0, 1/2]~ * [4, 4] 1 1 0 1 [1, 0]~ * [4, 5] 1/(2*x^2 + 2) 0 1/2 0 [0, 1/2]~ * [4, 6] Mod(-1/2*x, x^2 + 1) error("forbidden division t_FRAC \\ t_POLMOD.") error("forbidden division t_FRAC % t_POLMOD.") error("forbidden division t_FRAC \\ t_POLMOD.") error("forbidden division t_FRAC \\ t_POLMOD.") * [4, 7] t^4 + t^3 + 2*t^2 error("forbidden division t_FRAC \\ t_FFELT.") error("forbidden division t_FRAC % t_FFELT.") error("forbidden division t_FRAC \\ t_FFELT.") error("forbidden division t_FRAC \\ t_FFELT.") * [4, 8] -1/2 + 1/2*w 0 1/2 0 [0, 1/2]~ * [4, 9] -1/4*w error("forbidden division t_FRAC \\ t_QUAD.") error("forbidden division t_FRAC % t_QUAD.") error("forbidden division t_FRAC \\ t_QUAD.") error("forbidden division t_FRAC \\ t_QUAD.") * [4, 10] 1 + 2*3 + O(3^3) error("forbidden division t_FRAC \\ t_PADIC.") error("forbidden division t_FRAC % t_PADIC.") error("forbidden division t_FRAC \\ t_PADIC.") error("forbidden division t_FRAC \\ t_PADIC.") * [4, 11] Mod(1, 3) error("forbidden division t_FRAC \\ t_INTMOD.") error("forbidden division t_FRAC % t_INTMOD.") error("forbidden division t_FRAC \\ t_INTMOD.") error("forbidden division t_FRAC \\ t_INTMOD.") * [4, 12] 1/36893488147419103234 0 9223372036854775809 0 [0, 1/2]~ * [5, 1] 1/3*x^2 + 1/3 1/3*x^2 + 1/3 0 1/3*x^2 + 1/3 [1/3*x^2 + 1/3, 0]~ * [5, 2] 1/4*x^2 + 1/4 1/4*x^2 + 1/4 0 1/4*x^2 + 1/4 [1/4*x^2 + 1/4, 0]~ * [5, 3] 0.32258064516129032258064516129032258065*x^2 + 0.322580645161290322580645161 29032258065 0.32258064516129032258064516129032258065*x^2 + 0.322580645161290322580645161 29032258065 0 0.32258064516129032258064516129032258065*x^2 + 0.322580645161290322580645161 29032258065 [0.32258064516129032258064516129032258065*x^2 + 0.32258064516129032258064516 129032258065, 0]~ * [5, 4] 2*x^2 + 2 2*x^2 + 2 0 2*x^2 + 2 [2*x^2 + 2, 0]~ * [5, 5] 1 1 0 1 [1, 0]~ * [5, 6] Mod(0, x^2 + 1) error("forbidden euclidean division t_POL , t_POLMOD.") error("forbidden euclidean division t_POL , t_POLMOD.") error("forbidden euclidean division t_POL , t_POLMOD.") error("forbidden euclidean division t_POL , t_POLMOD.") * [5, 7] (2*t^4 + 2*t^3 + t^2)*x^2 + (2*t^4 + 2*t^3 + t^2) (2*t^4 + 2*t^3 + t^2)*x^2 + (2*t^4 + 2*t^3 + t^2) 0 (2*t^4 + 2*t^3 + t^2)*x^2 + (2*t^4 + 2*t^3 + t^2) [(2*t^4 + 2*t^3 + t^2)*x^2 + (2*t^4 + 2*t^3 + t^2), 0]~ * [5, 8] (-1 + w)*x^2 + (-1 + w) (-1 + w)*x^2 + (-1 + w) 0 (-1 + w)*x^2 + (-1 + w) [(-1 + w)*x^2 + (-1 + w), 0]~ * [5, 9] -1/2*w*x^2 - 1/2*w -1/2*w*x^2 - 1/2*w 0 -1/2*w*x^2 - 1/2*w [-1/2*w*x^2 - 1/2*w, 0]~ * [5, 10] (2 + 3 + 3^2 + O(3^3))*x^2 + (2 + 3 + 3^2 + O(3^3)) (2 + 3 + 3^2 + O(3^3))*x^2 + (2 + 3 + 3^2 + O(3^3)) 0 (2 + 3 + 3^2 + O(3^3))*x^2 + (2 + 3 + 3^2 + O(3^3)) [(2 + 3 + 3^2 + O(3^3))*x^2 + (2 + 3 + 3^2 + O(3^3)), 0]~ * [5, 11] Mod(2, 3)*x^2 + Mod(2, 3) Mod(2, 3)*x^2 + Mod(2, 3) Mod(0, 3) Mod(2, 3)*x^2 + Mod(2, 3) [Mod(2, 3)*x^2 + Mod(2, 3), Mod(0, 3)]~ * [5, 12] 1/18446744073709551617*x^2 + 1/18446744073709551617 1/18446744073709551617*x^2 + 1/18446744073709551617 0 1/18446744073709551617*x^2 + 1/18446744073709551617 [1/18446744073709551617*x^2 + 1/18446744073709551617, 0]~ * [6, 1] Mod(1/3*x, x^2 + 1) error("forbidden division t_POLMOD \\ t_INT.") Mod(0, x^2 + 1) error("forbidden division t_POLMOD \\ t_INT.") error("forbidden division t_POLMOD \\ t_INT.") * [6, 2] Mod(1/4*x, x^2 + 1) error("forbidden division t_POLMOD \\ t_INT.") Mod(0, x^2 + 1) error("forbidden division t_POLMOD \\ t_INT.") error("forbidden division t_POLMOD \\ t_INT.") * [6, 3] Mod(0.32258064516129032258064516129032258065*x, x^2 + 1) error("incorrect type in gfloor (t_POLMOD).") error("forbidden division t_POLMOD % t_REAL.") error("incorrect type in gfloor (t_POLMOD).") error("incorrect type in gfloor (t_POLMOD).") * [6, 4] Mod(2*x, x^2 + 1) error("incorrect type in gfloor (t_POLMOD).") error("forbidden division t_POLMOD % t_FRAC.") error("incorrect type in gfloor (t_POLMOD).") error("incorrect type in gfloor (t_POLMOD).") * [6, 5] error("impossible inverse in QXQ_inv: Mod(0, x^2 + 1).") error("forbidden euclidean division t_POLMOD , t_POL.") Mod(x, x^2 + 1) error("forbidden euclidean division t_POLMOD , t_POL.") error("forbidden euclidean division t_POLMOD , t_POL.") * [6, 6] Mod(1, x^2 + 1) error("forbidden division t_POLMOD \\ t_POLMOD.") error("forbidden division t_POLMOD % t_POLMOD.") error("forbidden division t_POLMOD \\ t_POLMOD.") error("forbidden division t_POLMOD \\ t_POLMOD.") * [6, 7] Mod((2*t^4 + 2*t^3 + t^2)*x, x^2 + 1) error("forbidden division t_POLMOD \\ t_FFELT.") error("forbidden division t_POLMOD % t_FFELT.") error("forbidden division t_POLMOD \\ t_FFELT.") error("forbidden division t_POLMOD \\ t_FFELT.") * [6, 8] Mod((-1 + w)*x, x^2 + 1) error("forbidden division t_POLMOD \\ t_QUAD.") error("forbidden division t_POLMOD % t_QUAD.") error("forbidden division t_POLMOD \\ t_QUAD.") error("forbidden division t_POLMOD \\ t_QUAD.") * [6, 9] Mod(-1/2*w*x, x^2 + 1) error("forbidden division t_POLMOD \\ t_QUAD.") error("forbidden division t_POLMOD % t_QUAD.") error("forbidden division t_POLMOD \\ t_QUAD.") error("forbidden division t_POLMOD \\ t_QUAD.") * [6, 10] Mod((2 + 3 + 3^2 + O(3^3))*x, x^2 + 1) error("forbidden division t_POLMOD \\ t_PADIC.") error("forbidden division t_POLMOD % t_PADIC.") error("forbidden division t_POLMOD \\ t_PADIC.") error("forbidden division t_POLMOD \\ t_PADIC.") * [6, 11] Mod(Mod(2, 3)*x, x^2 + 1) error("forbidden division t_POLMOD \\ t_INTMOD.") error("forbidden division t_POLMOD % t_INTMOD.") error("forbidden division t_POLMOD \\ t_INTMOD.") error("forbidden division t_POLMOD \\ t_INTMOD.") * [6, 12] Mod(1/18446744073709551617*x, x^2 + 1) error("forbidden division t_POLMOD \\ t_INT.") error("forbidden division t_POLMOD % t_INT.") error("forbidden division t_POLMOD \\ t_INT.") error("forbidden division t_POLMOD \\ t_INT.") * [7, 1] error("impossible inverse in Fl_inv: Mod(0, 3).") error("forbidden division t_FFELT \\ t_INT.") error("forbidden division t_FFELT % t_INT.") error("forbidden division t_FFELT \\ t_INT.") error("forbidden division t_FFELT \\ t_INT.") * [7, 2] t error("forbidden division t_FFELT \\ t_INT.") error("forbidden division t_FFELT % t_INT.") error("forbidden division t_FFELT \\ t_INT.") error("forbidden division t_FFELT \\ t_INT.") * [7, 3] error("forbidden division t_FFELT / t_REAL.") error("forbidden division t_FFELT / t_REAL.") error("forbidden division t_FFELT % t_REAL.") error("forbidden division t_FFELT / t_REAL.") error("forbidden division t_FFELT / t_REAL.") * [7, 4] 2*t error("incorrect type in gfloor (t_FFELT).") error("forbidden division t_FFELT % t_FRAC.") error("incorrect type in gfloor (t_FFELT).") error("incorrect type in gfloor (t_FFELT).") * [7, 5] t/(x^2 + 1) 0 t 0 [0, t]~ * [7, 6] Mod(2*t*x, x^2 + 1) error("forbidden division t_FFELT \\ t_POLMOD.") error("forbidden division t_FFELT % t_POLMOD.") error("forbidden division t_FFELT \\ t_POLMOD.") error("forbidden division t_FFELT \\ t_POLMOD.") * [7, 7] 1 error("forbidden division t_FFELT \\ t_FFELT.") error("forbidden division t_FFELT % t_FFELT.") error("forbidden division t_FFELT \\ t_FFELT.") error("forbidden division t_FFELT \\ t_FFELT.") * [7, 8] error("forbidden division t_FFELT / t_QUAD.") error("forbidden division t_FFELT \\ t_QUAD.") error("forbidden division t_FFELT % t_QUAD.") error("forbidden division t_FFELT \\ t_QUAD.") error("forbidden division t_FFELT \\ t_QUAD.") * [7, 9] error("forbidden division t_FFELT / t_QUAD.") error("forbidden division t_FFELT \\ t_QUAD.") error("forbidden division t_FFELT % t_QUAD.") error("forbidden division t_FFELT \\ t_QUAD.") error("forbidden division t_FFELT \\ t_QUAD.") * [7, 10] error("forbidden division t_FFELT / t_PADIC.") error("forbidden division t_FFELT \\ t_PADIC.") error("forbidden division t_FFELT % t_PADIC.") error("forbidden division t_FFELT \\ t_PADIC.") error("forbidden division t_FFELT \\ t_PADIC.") * [7, 11] 2*t error("forbidden division t_FFELT \\ t_INTMOD.") error("forbidden division t_FFELT % t_INTMOD.") error("forbidden division t_FFELT \\ t_INTMOD.") error("forbidden division t_FFELT \\ t_INTMOD.") * [7, 12] 2*t error("forbidden division t_FFELT \\ t_INT.") error("forbidden division t_FFELT % t_INT.") error("forbidden division t_FFELT \\ t_INT.") error("forbidden division t_FFELT \\ t_INT.") * [8, 1] 1/3*w 0 w 1 [0, w]~ * [8, 2] 1/4*w 0 w 0 [0, w]~ * [8, 3] 0.52194644798383704780793123689214132830 0 w 1 [0, w]~ * [8, 4] 2*w 3 -3/2 + w 3 [3, -3/2 + w]~ * [8, 5] w/(x^2 + 1) 0 w 0 [0, w]~ * [8, 6] Mod(-w*x, x^2 + 1) error("forbidden division t_QUAD \\ t_POLMOD.") error("forbidden division t_QUAD % t_POLMOD.") error("forbidden division t_QUAD \\ t_POLMOD.") error("forbidden division t_QUAD \\ t_POLMOD.") * [8, 7] error("forbidden division t_QUAD / t_FFELT.") error("forbidden division t_QUAD \\ t_FFELT.") error("forbidden division t_QUAD % t_FFELT.") error("forbidden division t_QUAD \\ t_FFELT.") error("forbidden division t_QUAD \\ t_FFELT.") * [8, 8] 1 1 0 1 [1, 0]~ * [8, 9] error("inconsistent division t_QUAD / t_QUAD.") error("forbidden division t_QUAD \\ t_QUAD.") error("forbidden division t_QUAD % t_QUAD.") error("forbidden division t_QUAD \\ t_QUAD.") error("forbidden division t_QUAD \\ t_QUAD.") * [8, 10] error("not an n-th power residue in Qp_sqrt: 5.") error("forbidden division t_QUAD \\ t_PADIC.") error("forbidden division t_QUAD % t_PADIC.") error("forbidden division t_QUAD \\ t_PADIC.") error("forbidden division t_QUAD \\ t_PADIC.") * [8, 11] Mod(0, 3) + Mod(2, 3)*w error("forbidden division t_QUAD \\ t_INTMOD.") error("forbidden division t_QUAD % t_INTMOD.") error("forbidden division t_QUAD \\ t_INTMOD.") error("forbidden division t_QUAD \\ t_INTMOD.") * [8, 12] 1/18446744073709551617*w 0 w 0 [0, w]~ * [9, 1] 1/3*w error("forbidden division t_QUAD \\ t_INT.") error("forbidden division t_QUAD % t_INT.") error("forbidden division t_QUAD \\ t_INT.") error("forbidden division t_QUAD \\ t_INT.") * [9, 2] 1/4*w error("forbidden division t_QUAD \\ t_INT.") error("forbidden division t_QUAD % t_INT.") error("forbidden division t_QUAD \\ t_INT.") error("forbidden division t_QUAD \\ t_INT.") * [9, 3] 0.E-38 + 0.45619792334615969316183507232570905760*I error("incorrect type in gfloor (t_COMPLEX).") error("forbidden division t_QUAD % t_REAL.") error("incorrect type in gfloor (t_COMPLEX).") error("incorrect type in gfloor (t_COMPLEX).") * [9, 4] 2*w error("incorrect type in gfloor (t_QUAD).") error("forbidden division t_QUAD % t_FRAC.") error("incorrect type in gfloor (t_QUAD).") error("incorrect type in gfloor (t_QUAD).") * [9, 5] w/(x^2 + 1) 0 w 0 [0, w]~ * [9, 6] Mod(-w*x, x^2 + 1) error("forbidden division t_QUAD \\ t_POLMOD.") error("forbidden division t_QUAD % t_POLMOD.") error("forbidden division t_QUAD \\ t_POLMOD.") error("forbidden division t_QUAD \\ t_POLMOD.") * [9, 7] error("forbidden division t_QUAD / t_FFELT.") error("forbidden division t_QUAD \\ t_FFELT.") error("forbidden division t_QUAD % t_FFELT.") error("forbidden division t_QUAD \\ t_FFELT.") error("forbidden division t_QUAD \\ t_FFELT.") * [9, 8] error("inconsistent division t_QUAD / t_QUAD.") error("forbidden division t_QUAD \\ t_QUAD.") error("forbidden division t_QUAD % t_QUAD.") error("forbidden division t_QUAD \\ t_QUAD.") error("forbidden division t_QUAD \\ t_QUAD.") * [9, 9] 1 error("forbidden division t_QUAD \\ t_QUAD.") error("forbidden division t_QUAD % t_QUAD.") error("forbidden division t_QUAD \\ t_QUAD.") error("forbidden division t_QUAD \\ t_QUAD.") * [9, 10] 1 + 2*3 + 3^2 + O(3^3) error("forbidden division t_QUAD \\ t_PADIC.") error("forbidden division t_QUAD % t_PADIC.") error("forbidden division t_QUAD \\ t_PADIC.") error("forbidden division t_QUAD \\ t_PADIC.") * [9, 11] Mod(0, 3) + Mod(2, 3)*w error("forbidden division t_QUAD \\ t_INTMOD.") error("forbidden division t_QUAD % t_INTMOD.") error("forbidden division t_QUAD \\ t_INTMOD.") error("forbidden division t_QUAD \\ t_INTMOD.") * [9, 12] 1/18446744073709551617*w error("forbidden division t_QUAD \\ t_INT.") error("forbidden division t_QUAD % t_INT.") error("forbidden division t_QUAD \\ t_INT.") error("forbidden division t_QUAD \\ t_INT.") * [10, 1] 2*3^-1 + O(3^2) error("forbidden division t_PADIC \\ t_INT.") 2 error("forbidden division t_PADIC \\ t_INT.") error("forbidden division t_PADIC \\ t_INT.") * [10, 2] 2 + 3 + 3^2 + O(3^3) error("forbidden division t_PADIC \\ t_INT.") error("inconsistent t_PADIC , t_INTMOD.") error("forbidden division t_PADIC \\ t_INT.") error("forbidden division t_PADIC \\ t_INT.") * [10, 3] error("forbidden division t_PADIC / t_REAL.") error("forbidden division t_PADIC / t_REAL.") error("forbidden division t_PADIC % t_REAL.") error("forbidden division t_PADIC / t_REAL.") error("forbidden division t_PADIC / t_REAL.") * [10, 4] 1 + 3 + O(3^3) error("incorrect type in gfloor (t_PADIC).") error("forbidden division t_PADIC % t_FRAC.") error("incorrect type in gfloor (t_PADIC).") error("incorrect type in gfloor (t_PADIC).") * [10, 5] (2 + O(3^3))/(x^2 + 1) 0 2 + O(3^3) 0 [0, 2 + O(3^3)]~ * [10, 6] Mod((1 + 2*3 + 2*3^2 + O(3^3))*x, x^2 + 1) error("forbidden division t_PADIC \\ t_POLMOD.") error("forbidden division t_PADIC % t_POLMOD.") error("forbidden division t_PADIC \\ t_POLMOD.") error("forbidden division t_PADIC \\ t_POLMOD.") * [10, 7] error("forbidden division t_PADIC / t_FFELT.") error("forbidden division t_PADIC \\ t_FFELT.") error("forbidden division t_PADIC % t_FFELT.") error("forbidden division t_PADIC \\ t_FFELT.") error("forbidden division t_PADIC \\ t_FFELT.") * [10, 8] 1 + 2*3 + 2*3^2 + O(3^3) + (2 + O(3^3))*w error("forbidden division t_PADIC \\ t_QUAD.") error("forbidden division t_PADIC % t_QUAD.") error("forbidden division t_PADIC \\ t_QUAD.") error("forbidden division t_PADIC \\ t_QUAD.") * [10, 9] 1 + 3 + 2*3^2 + O(3^3) error("forbidden division t_PADIC \\ t_QUAD.") error("forbidden division t_PADIC % t_QUAD.") error("forbidden division t_PADIC \\ t_QUAD.") error("forbidden division t_PADIC \\ t_QUAD.") * [10, 10] 1 + O(3^3) error("forbidden division t_PADIC \\ t_PADIC.") error("forbidden division t_PADIC % t_PADIC.") error("forbidden division t_PADIC \\ t_PADIC.") error("forbidden division t_PADIC \\ t_PADIC.") * [10, 11] Mod(1, 3) error("forbidden division t_PADIC \\ t_INTMOD.") error("forbidden division t_PADIC % t_INTMOD.") error("forbidden division t_PADIC \\ t_INTMOD.") error("forbidden division t_PADIC \\ t_INTMOD.") * [10, 12] 1 + 2*3 + 2*3^2 + O(3^3) error("forbidden division t_PADIC \\ t_INT.") error("inconsistent t_PADIC , t_INTMOD.") error("forbidden division t_PADIC \\ t_INT.") error("forbidden division t_PADIC \\ t_INT.") * [11, 1] error("impossible inverse in Fl_inv: Mod(0, 3).") error("forbidden division t_INTMOD \\ t_INT.") Mod(2, 3) error("forbidden division t_INTMOD \\ t_INT.") error("forbidden division t_INTMOD \\ t_INT.") * [11, 2] Mod(2, 3) error("forbidden division t_INTMOD \\ t_INT.") Mod(0, 1) error("forbidden division t_INTMOD \\ t_INT.") error("forbidden division t_INTMOD \\ t_INT.") * [11, 3] error("forbidden division t_INTMOD / t_REAL.") error("forbidden division t_INTMOD / t_REAL.") error("forbidden division t_INTMOD % t_REAL.") error("forbidden division t_INTMOD / t_REAL.") error("forbidden division t_INTMOD / t_REAL.") * [11, 4] Mod(1, 3) error("incorrect type in gfloor (t_INTMOD).") error("forbidden division t_INTMOD % t_FRAC.") error("incorrect type in gfloor (t_INTMOD).") error("incorrect type in gfloor (t_INTMOD).") * [11, 5] Mod(2, 3)/(Mod(1, 3)*x^2 + Mod(1, 3)) 0 Mod(2, 3) 0 [0, Mod(2, 3)]~ * [11, 6] Mod(Mod(1, 3)*x, x^2 + 1) error("forbidden division t_INTMOD \\ t_POLMOD.") error("forbidden division t_INTMOD % t_POLMOD.") error("forbidden division t_INTMOD \\ t_POLMOD.") error("forbidden division t_INTMOD \\ t_POLMOD.") * [11, 7] t^4 + t^3 + 2*t^2 error("forbidden division t_INTMOD \\ t_FFELT.") error("forbidden division t_INTMOD % t_FFELT.") error("forbidden division t_INTMOD \\ t_FFELT.") error("forbidden division t_INTMOD \\ t_FFELT.") * [11, 8] Mod(1, 3) + Mod(2, 3)*w error("forbidden division t_INTMOD \\ t_QUAD.") error("forbidden division t_INTMOD % t_QUAD.") error("forbidden division t_INTMOD \\ t_QUAD.") error("forbidden division t_INTMOD \\ t_QUAD.") * [11, 9] Mod(0, 3) + Mod(2, 3)*w error("forbidden division t_INTMOD \\ t_QUAD.") error("forbidden division t_INTMOD % t_QUAD.") error("forbidden division t_INTMOD \\ t_QUAD.") error("forbidden division t_INTMOD \\ t_QUAD.") * [11, 10] Mod(1, 3) error("forbidden division t_INTMOD \\ t_PADIC.") error("forbidden division t_INTMOD % t_PADIC.") error("forbidden division t_INTMOD \\ t_PADIC.") error("forbidden division t_INTMOD \\ t_PADIC.") * [11, 11] Mod(1, 3) error("forbidden division t_INTMOD \\ t_INTMOD.") error("forbidden division t_INTMOD % t_INTMOD.") error("forbidden division t_INTMOD \\ t_INTMOD.") error("forbidden division t_INTMOD \\ t_INTMOD.") * [11, 12] Mod(1, 3) error("forbidden division t_INTMOD \\ t_INT.") Mod(0, 1) error("forbidden division t_INTMOD \\ t_INT.") error("forbidden division t_INTMOD \\ t_INT.") * [12, 1] 18446744073709551617/3 6148914691236517205 2 6148914691236517206 [6148914691236517205, 2]~ * [12, 2] 18446744073709551617/4 4611686018427387904 1 4611686018427387904 [4611686018427387904, 1]~ * [12, 3] 5950562604422436005.4838709677419354839 5950562604422436005 1.5000000000000000001 5950562604422436005 [5950562604422436005, 1.5000000000000000001]~ * [12, 4] 36893488147419103234 36893488147419103234 0 36893488147419103234 [36893488147419103234, 0]~ * [12, 5] 18446744073709551617/(x^2 + 1) 0 18446744073709551617 0 [0, 18446744073709551617]~ * [12, 6] Mod(-18446744073709551617*x, x^2 + 1) error("forbidden division t_INT \\ t_POLMOD.") error("forbidden division t_INT % t_POLMOD.") error("forbidden division t_INT \\ t_POLMOD.") error("forbidden division t_INT \\ t_POLMOD.") * [12, 7] t^4 + t^3 + 2*t^2 error("forbidden division t_INT \\ t_FFELT.") error("forbidden division t_INT % t_FFELT.") error("forbidden division t_INT \\ t_FFELT.") error("forbidden division t_INT \\ t_FFELT.") * [12, 8] -18446744073709551617 + 18446744073709551617*w 11400714819323198486 18446744073709551617 - 11400714819323198486*w 11400714819323198487 [11400714819323198486, 18446744073709551617 - 11400714819323198486*w]~ * [12, 9] -18446744073709551617/2*w error("forbidden division t_INT \\ t_QUAD.") error("forbidden division t_INT % t_QUAD.") error("forbidden division t_INT \\ t_QUAD.") error("forbidden division t_INT \\ t_QUAD.") * [12, 10] 1 + 3 + 3^2 + O(3^3) error("forbidden division t_INT \\ t_PADIC.") error("forbidden division t_INT % t_PADIC.") error("forbidden division t_INT \\ t_PADIC.") error("forbidden division t_INT \\ t_PADIC.") * [12, 11] Mod(1, 3) error("forbidden division t_INT \\ t_INTMOD.") error("forbidden division t_INT % t_INTMOD.") error("forbidden division t_INT \\ t_INTMOD.") error("forbidden division t_INT \\ t_INTMOD.") * [12, 12] 1 1 0 1 [1, 0]~ * [1, 1] 1/3*x + O(x^2) error("forbidden division t_SER \\ t_INT.") error("forbidden division t_SER % t_INT.") error("forbidden division t_SER \\ t_INT.") * [1, 2] 1/4*x + O(x^2) error("forbidden division t_SER \\ t_INT.") error("forbidden division t_SER % t_INT.") error("forbidden division t_SER \\ t_INT.") * [1, 3] 0.32258064516129032258064516129032258065*x + O(x^2) error("incorrect type in gfloor (t_SER).") error("forbidden division t_SER % t_REAL.") error("incorrect type in gfloor (t_SER).") * [1, 4] 2*x + O(x^2) error("incorrect type in gfloor (t_SER).") error("forbidden division t_SER % t_FRAC.") error("incorrect type in gfloor (t_SER).") * [1, 5] x + O(x^2) error("forbidden euclidean division t_SER , t_POL.") error("forbidden division t_SER % t_POL.") error("forbidden euclidean division t_SER , t_POL.") * [1, 6] error("forbidden division t_SER % t_POL.") error("forbidden division t_SER \\ t_POLMOD.") error("forbidden division t_SER % t_POLMOD.") error("forbidden division t_SER \\ t_POLMOD.") * [1, 7] (2*t^4 + 2*t^3 + t^2)*x + O(x^2) error("forbidden division t_SER \\ t_FFELT.") error("forbidden division t_SER % t_FFELT.") error("forbidden division t_SER \\ t_FFELT.") * [1, 8] (-1 + w)*x + O(x^2) error("forbidden division t_SER \\ t_QUAD.") error("forbidden division t_SER % t_QUAD.") error("forbidden division t_SER \\ t_QUAD.") * [1, 9] -1/2*w*x + O(x^2) error("forbidden division t_SER \\ t_QUAD.") error("forbidden division t_SER % t_QUAD.") error("forbidden division t_SER \\ t_QUAD.") * [1, 10] (2 + 3 + 3^2 + O(3^3))*x + O(x^2) error("forbidden division t_SER \\ t_PADIC.") error("forbidden division t_SER % t_PADIC.") error("forbidden division t_SER \\ t_PADIC.") * [1, 11] Mod(2, 3)*x + O(x^2) error("forbidden division t_SER \\ t_INTMOD.") error("forbidden division t_SER % t_INTMOD.") error("forbidden division t_SER \\ t_INTMOD.") * [1, 12] 1/18446744073709551617*x + O(x^2) error("forbidden division t_SER \\ t_INT.") error("forbidden division t_SER % t_INT.") error("forbidden division t_SER \\ t_INT.") * [2, 1] [2/3, 1] [0, 1] [2, 0] [1, 1] * [2, 2] [1/2, 3/4] [0, 0] [2, 3] [1, 1] * [2, 3] [0.64516129032258064516129032258064516129, 0.9677419354838709677419354838709 6774194] [0, 0] [2, 3] [1, 1] * [2, 4] [4, 6] [4, 6] [0, 0] [4, 6] * [2, 5] [2/(x^2 + 1), 3/(x^2 + 1)] [0, 0] [2, 3] [0, 0] * [2, 6] [Mod(-2*x, x^2 + 1), Mod(-3*x, x^2 + 1)] error("forbidden division t_INT \\ t_POLMOD.") error("forbidden division t_INT % t_POLMOD.") error("forbidden division t_INT \\ t_POLMOD.") * [2, 7] [t^4 + t^3 + 2*t^2, 0] error("forbidden division t_INT \\ t_FFELT.") error("forbidden division t_INT % t_FFELT.") error("forbidden division t_INT \\ t_FFELT.") * [2, 8] [-2 + 2*w, -3 + 3*w] [1, 1] [2 - w, 3 - w] [1, 2] * [2, 9] [-w, -3/2*w] error("forbidden division t_INT \\ t_QUAD.") error("forbidden division t_INT % t_QUAD.") error("forbidden division t_INT \\ t_QUAD.") * [2, 10] [1 + O(3^3), 2*3 + 3^2 + 3^3 + O(3^4)] error("forbidden division t_INT \\ t_PADIC.") error("forbidden division t_INT % t_PADIC.") error("forbidden division t_INT \\ t_PADIC.") * [2, 11] [Mod(1, 3), Mod(0, 3)] error("forbidden division t_INT \\ t_INTMOD.") error("forbidden division t_INT % t_INTMOD.") error("forbidden division t_INT \\ t_INTMOD.") * [2, 12] [2/18446744073709551617, 3/18446744073709551617] [0, 0] [2, 3] [0, 0] * [3, 1] Mat(2/3) Mat(0) Mat(2) Mat(1) * [3, 2] Mat(1/2) Mat(0) Mat(2) Mat(1) * [3, 3] Mat(0.64516129032258064516129032258064516129) Mat(0) Mat(2) Mat(1) * [3, 4] Mat(4) Mat(4) Mat(0) Mat(4) * [3, 5] Mat(2/(x^2 + 1)) Mat(0) Mat(2) Mat(0) * [3, 6] Mat(Mod(-2*x, x^2 + 1)) error("forbidden division t_INT \\ t_POLMOD.") error("forbidden division t_INT % t_POLMOD.") error("forbidden division t_INT \\ t_POLMOD.") * [3, 7] Mat(t^4 + t^3 + 2*t^2) error("forbidden division t_INT \\ t_FFELT.") error("forbidden division t_INT % t_FFELT.") error("forbidden division t_INT \\ t_FFELT.") * [3, 8] Mat(-2 + 2*w) Mat(1) Mat(2 - w) Mat(1) * [3, 9] Mat(-w) error("forbidden division t_INT \\ t_QUAD.") error("forbidden division t_INT % t_QUAD.") error("forbidden division t_INT \\ t_QUAD.") * [3, 10] Mat(1 + O(3^3)) error("forbidden division t_INT \\ t_PADIC.") error("forbidden division t_INT % t_PADIC.") error("forbidden division t_INT \\ t_PADIC.") * [3, 11] Mat(Mod(1, 3)) error("forbidden division t_INT \\ t_INTMOD.") error("forbidden division t_INT % t_INTMOD.") error("forbidden division t_INT \\ t_INTMOD.") * [3, 12] Mat(2/18446744073709551617) Mat(0) Mat(2) Mat(0) [0, 1] Mat(0) [1, 1] Mat(1) [-x + y, x^2 + x]~ [[1, 1]~, [2, 1]~] [0, 1]~ [1, 0]~ *** at top-level: divrem(1,"a") *** ^------------- *** divrem: forbidden division t_INT \ t_STR. 2 x -1/(y*x - 1) 1/(y*x - 1) [ 53/29 20/29 -32/29] [193/29 40/29 -93/29] [] []~ [;] *** at top-level: [1]/0 *** ^-- *** _/_: impossible inverse in gdiv: 0. Mod(Mod(2, 3)*a + Mod(1, 3), Mod(1, 3)*a^3 + Mod(2, 3)*a + Mod(2, 3))*x^4 + Mod(Mod(2, 3)*a^2 + Mod(2, 3), Mod(1, 3)*a^3 + Mod(2, 3)*a + Mod(2, 3))*x^3 + Mod(Mod(2, 3)*a, Mod(1, 3)*a^3 + Mod(2, 3)*a + Mod(2, 3))*x^2 + Mod(Mod(1, 3)*a^2 + Mod(2, 3), Mod(1, 3)*a^3 + Mod(2, 3)*a + Mod(2, 3))*x + Mod(Mod(1, 3)*a, Mod(1, 3)*a^3 + Mod(2, 3)*a + Mod(2, 3)) Mod(1, 2)*x^3 + Mod(1, 2)*x Mod(1, 2) Mod(1, 2) + O(x^2) Mod(1, 2)*x + Mod(1, 2) Mod(1, 2)*x Total time spent: 0 pari-2.17.2/src/test/32/polred0000644000175000017500000001144314676526175014414 0ustar billbill *** Warning: new stack size = 12000000 (11.444 Mbytes). x^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(-5265231366756*y - 11544453645457, y^2 - y - 7)*x^7 + Mod(28411458 5416607426786*y + 622944640581258439174, y^2 - y - 7)*x^6 + Mod(-88698486784 831757442657946*y - 194478741347464554095950854, y^2 - y - 7)*x^5 + Mod(1457 861838374320941446687517087*y + 3196482213651741289611519839129, y^2 - y - 7 )*x^4 + Mod(-3466536016262523445329224834043387*y - 760066587058933027706659 6588522840, y^2 - y - 7)*x^3 + Mod(500059251848756466420835983321373618*y + 1096421116344588264250099626740668170, y^2 - y - 7)*x^2 + Mod(-1916208944621 5341153510282273347908836*y - 42014460135353505823787366140454468112, y^2 - y - 7)*x + Mod(100691810991091652032034511974871062155*y + 22077509296238717 8747302102119022589688, y^2 - y - 7) x^8 + Mod(-8*y + 1, y^2 - y - 7)*x^7 + Mod(21*y + 189, y^2 - y - 7)*x^6 + Mo d(-385*y - 251, y^2 - y - 7)*x^5 + Mod(695*y + 2955, y^2 - y - 7)*x^4 + Mod( -2451*y - 3350, y^2 - y - 7)*x^3 + Mod(2402*y + 6871, y^2 - y - 7)*x^2 + Mod (-2050*y - 3861, y^2 - y - 7)*x + Mod(565*y + 1331, y^2 - y - 7) [[[[17, 0; 0, 17], [0, 0]], Mat([[17, [17, 0]~, 1, 2, 1], 1])], 168377826559 400929] [[[[17, 0; 0, 17], [0, 0]], Mat([[17, [17, 0]~, 1, 2, 1], 1])], 168377826559 400929] [[[[17, 0; 0, 17], [0, 0]], Mat([[17, [17, 0]~, 1, 2, 1], 1])], 168377826559 400929] x^3 + Mod(y^2 - 2, y^3 - y - 1)*x^2 + Mod(-y + 1, y^3 - y - 1)*x + Mod(y - 1 , y^3 - y - 1) x^9 - 4*x^8 + 8*x^7 - 9*x^6 + 7*x^5 - 3*x^4 - x^3 + 4*x^2 - 3*x + 1 0 0 Mod(0, x^9 - 4*x^8 + 8*x^7 - 9*x^6 + 7*x^5 - 3*x^4 - x^3 + 4*x^2 - 3*x + 1) *** nfinit: Warning: nonmonic polynomial. Result of the form [nf,c]. x^2 - 3646554366 x^4 + 1000000000000000000000*x^2 + 1 x^4 + 146077*x^2 + 2629386 [y^4 - 2*y^3 - 16*y^2 - 5*y + 4, Mod(-2/3*y^3 + 5/3*y^2 + 28/3*y + 2/3, y^4 - 2*y^3 - 16*y^2 - 5*y + 4)] x^9 - 4*x^7 - 3*x^6 + 9*x^5 + 8*x^4 - 6*x^3 - 9*x^2 - 4*x - 1 x^5 - 13*x^3 - 3*x^2 + 5*x + 1 x^6 + 21471450*x^2 + 71643071500 x^6 - 12*x^4 - 24*x^3 + 21651666*x^2 - 257657256*x + 71814482884 x^4 + 146077*x^2 + 10517544 x [x, Mod(-1/2, x)] *** at top-level: polred([x,[1]]) *** ^--------------- *** polred: domain error in gvaluation: p = 1 [x] [x] [ 0 x] [2*x x^2 + 1] x + 1 [x + 1, Mod(-1/2, x + 1)] [x^2 + 1, Mod(1/2*x, x^2 + 1)] [2*x + 1] [x, x^2 + 1] [x^8 - 4*x^7 + 24*x^6 - 58*x^5 + 156*x^4 - 220*x^3 + 290*x^2 - 189*x + 46, M od(4/15*x^7 - 14/15*x^6 + 28/5*x^5 - 12*x^4 + 454/15*x^3 - 548/15*x^2 + 596/ 15*x - 248/15, x^8 - 4*x^7 + 24*x^6 - 58*x^5 + 156*x^4 - 220*x^3 + 290*x^2 - 189*x + 46)] x^16 - 4*x^15 - 334*x^14 + 264*x^13 + 32231*x^12 + 57392*x^11 - 1031422*x^10 - 3628868*x^9 + 7185297*x^8 + 42417784*x^7 + 11283472*x^6 - 137773504*x^5 - 127243504*x^4 + 69059728*x^3 + 56307944*x^2 - 6264432*x + 6436 x^5 + 5*x - 1 [x^12 - 2*x^11 - 11*x^9 + 13*x^8 + 5, Mod(0, x^12 - 2*x^11 - 11*x^9 + 13*x^8 + 5)] x^15 - 15*x^13 - 2*x^12 + 78*x^11 - 10*x^10 - 393*x^9 + 81*x^8 + 939*x^7 - 3 73*x^6 - 822*x^5 + 723*x^4 - 1588*x^3 - 57*x^2 + 127*x - 13 1 x^4 + Mod(-1/24*z^3 - 1/8*z^2 - 59/24*z - 27/8, z^4 + 50*z^2 + 45)*x^3 + Mod (1/12*z^3 + 41/12*z + 5/2, z^4 + 50*z^2 + 45)*x^2 + Mod(-1/24*z^3 - 1/8*z^2 - 59/24*z - 27/8, z^4 + 50*z^2 + 45)*x + 1 x^4 + Mod(-1/24*z^3 - 1/8*z^2 - 59/24*z - 27/8, z^4 + 50*z^2 + 45)*x^3 + Mod (1/12*z^3 + 41/12*z + 5/2, z^4 + 50*z^2 + 45)*x^2 + Mod(-1/24*z^3 - 1/8*z^2 - 59/24*z - 27/8, z^4 + 50*z^2 + 45)*x + 1 y^2 + Mod(t^3, t^4 + t^3 + t^2 + t + 1)*y + Mod(8*t^2 - 46*t + 8, t^4 + t^3 + t^2 + t + 1) [x^6 - 2*x^3 + 2, Mod(1/2*x^4 - x, x^6 - 2*x^3 + 2)] [y^4 - 2*y^2 - 2*y + 1, Mod(-1/2*y^3 + 1/2*y + 1, y^4 - 2*y^2 - 2*y + 1)] x^4 + Mod(y, y^4 - 18*y^2 + 82)*x^3 + Mod(2*y^2 - 15, y^4 - 18*y^2 + 82)*x^2 + Mod(y^3 - 9*y, y^4 - 18*y^2 + 82)*x + Mod(y^2 - 10, y^4 - 18*y^2 + 82) x^4 + Mod(y, y^4 - 18*y^2 + 82)*x^3 + Mod(2*y^2 - 15, y^4 - 18*y^2 + 82)*x^2 + Mod(y^3 - 9*y, y^4 - 18*y^2 + 82)*x + Mod(y^2 - 10, y^4 - 18*y^2 + 82) x^4 + Mod(y, y^4 - 18*y^2 + 82)*x^3 + Mod(2*y^2 - 15, y^4 - 18*y^2 + 82)*x^2 + Mod(y^3 - 9*y, y^4 - 18*y^2 + 82)*x + Mod(y^2 - 10, y^4 - 18*y^2 + 82) x^4 + Mod(y, y^4 - 18*y^2 + 82)*x^3 + Mod(2*y^2 - 15, y^4 - 18*y^2 + 82)*x^2 + Mod(y^3 - 9*y, y^4 - 18*y^2 + 82)*x + Mod(y^2 - 10, y^4 - 18*y^2 + 82) x^4 + Mod(y, y^4 - 18*y^2 + 82)*x^3 + Mod(2*y^2 - 15, y^4 - 18*y^2 + 82)*x^2 + Mod(y^3 - 9*y, y^4 - 18*y^2 + 82)*x + Mod(y^2 - 10, y^4 - 18*y^2 + 82) *** at top-level: polredbest(x^6+30*x^5+133*x^4-2340*x^3-12284*x *** ^---------------------------------------------- *** polredbest: not an irreducible polynomial in set_LLL_basis: x^6 + 30*x^5 + 133*x^4 - 2340*x^3 - 12284*x^2 + 29519*x - 3856. Total time spent: 4020 pari-2.17.2/src/test/32/polclass0000644000175000017500000000016014676526175014741 0ustar billbill *** Warning: new stack size = 10000000 (9.537 Mbytes). x - 20 16712144634643335347 0 Total time spent: 6563 pari-2.17.2/src/test/32/bbhnf0000644000175000017500000001346714676526175014216 0ustar billbillbb hermite Z/NZ imagemod [900 130 117 275 85] [ 0 4 0 0 0] [ 0 0 9 0 0] [ 0 0 0 25 0] [ 0 0 0 0 10] [870 11 1603 1016] [ 15 2 1 8] [ 0 5 3 0] [ 0 0 8 3] [ 0 0 0 3] kermod [1] [;] [3] [;] [3] [1] [2] [;] [3] [;] [;] [3] [0] [1] [1] [0] [3 0] [0 1] [3] [1] [1 0] [0 2] [3 0] [0 2] [0] [1] [3 0] [0 2] [;] [3 2] [0 2] [3 1] [0 1] [2] [1] invmod [12 4 10] [ 0 1 0] [ 0 0 1] [3 0 2] [0 3 1] [0 0 1] [30 29 2] [ 0 1 0] [ 0 0 1] [4 2 1 1] [0 1 0 0] [0 0 1 0] [0 0 0 1] [30 11] [ 0 1] [512 0 38 89] [ 0 512 414 178] [ 0 0 1 0] [ 0 0 0 1] 0 [1]~ []~ []~ 0 []~ []~ 0 0 [1]~ [-1, 1]~ [;] 0 0 [;] [0 0] [0 0] [0 0 0] [0 0 0] [[0]~, Mat(1)] [1 0] [0 2] [5 1] [3 4] [1 0] [0 2] [1 2 3] [5 1 4] [2 1] [2 1] [0 3] [0 0] [0 0] [1 1 3] [2 3 5] [1 0 5] [1 0 0] [0 1 0] [0 0 1] 18 8 8 6 [2 1] [0 2] [2 1] [0 4] [0 0] [2 1] []~ []~ []~ [[]~, [;]] [0]~ [0]~ [[0]~, [;]] 0 [[21, -4]~, [-110; 21]] 1 1 *** at top-level: matimagemod([],1) *** ^----------------- *** matimagemod: incorrect type in matimagemod (t_VEC). *** at top-level: matimagemod([;],'x) *** ^------------------- *** matimagemod: incorrect type in matimagemod (t_POL). *** at top-level: matimagemod([0,'x;1,0],1) *** ^------------------------- *** matimagemod: incorrect type in matimagemod (t_MAT). *** at top-level: matkermod([],1) *** ^--------------- *** matkermod: incorrect type in matkermod (t_VEC). *** at top-level: matkermod([;],'x) *** ^----------------- *** matkermod: incorrect type in matkermod (t_POL). *** at top-level: matkermod([0,'x;1,0],1) *** ^----------------------- *** matkermod: incorrect type in matkermod (t_MAT). *** at top-level: matinvmod([],1) *** ^--------------- *** matinvmod: incorrect type in matinvmod (t_VEC). *** at top-level: matinvmod([;],'x) *** ^----------------- *** matinvmod: incorrect type in matinvmod (t_POL). *** at top-level: matinvmod([0,'x;1,0],1) *** ^----------------------- *** matinvmod: incorrect type in matinvmod (t_MAT). *** at top-level: matdetmod([],1) *** ^--------------- *** matdetmod: incorrect type in matdetmod (t_VEC). *** at top-level: matdetmod(Mat([1,2]),1) *** ^----------------------- *** matdetmod: inconsistent dimensions in matdetmod. *** at top-level: matdetmod(Mat(1/2),3) *** ^--------------------- *** matdetmod: incorrect type in matdetmod (t_MAT). *** at top-level: matimagemod(Mat(1),-1) *** ^---------------------- *** matimagemod: domain error in matimagemod: d <= 0 *** at top-level: matdetmod(Mat(1),0) *** ^------------------- *** matdetmod: domain error in matdetmod: d <= 0 *** at top-level: matkermod(Mat(1),0) *** ^------------------- *** matkermod: domain error in makermod: d <= 0 *** at top-level: matinvmod(Mat(1),0) *** ^------------------- *** matinvmod: domain error in matinvmod: d <= 0 *** at top-level: matinvmod([1,2,3;4,5,6],1) *** ^-------------------------- *** matinvmod: impossible inverse in matinvmod: [1, 2, 3; 4, 5, 6]. *** at top-level: matsolvemod([;],[2,2]~,[1,2,3]~) *** ^-------------------------------- *** matsolvemod: inconsistent dimensions in matsolvemod [2]. *** at top-level: matsolvemod(Mat(1),[1,2]~,1) *** ^---------------------------- *** matsolvemod: inconsistent dimensions in matsolvemod [1]. *** at top-level: matsolvemod(Mat(1),2,[1,2]~) *** ^---------------------------- *** matsolvemod: inconsistent dimensions in matsolvemod [3]. *** at top-level: matsolvemod(Mat(1),[2],1) *** ^------------------------- *** matsolvemod: incorrect type in matsolvemod (D) (t_VEC). *** at top-level: matsolvemod(Mat(1),2,[1]) *** ^------------------------- *** matsolvemod: incorrect type in matsolvemod (Y) (t_VEC). *** at top-level: matsolvemod("a",2,1) *** ^-------------------- *** matsolvemod: incorrect type in matsolvemod (M) (t_STR). *** at top-level: matsolvemod(Mat(1),-2,1) *** ^------------------------ *** matsolvemod: domain error in matsolvemod: D < 0 *** at top-level: matsolvemod([1,2;3,4],[2,-3]~,1) *** ^-------------------------------- *** matsolvemod: domain error in matsolvemod: D[i] < 0 *** at top-level: matsolvemod(Mat(1/2),1,1) *** ^------------------------- *** matsolvemod: incorrect type in matsolvemod (M) (t_MAT). *** at top-level: matsolvemod(Mat(1),1/2,1) *** ^------------------------- *** matsolvemod: incorrect type in matsolvemod (D) (t_FRAC). *** at top-level: matsolvemod(Mat(1),1,1/2) *** ^------------------------- *** matsolvemod: incorrect type in matsolvemod (Y) (t_FRAC). *** at top-level: matsolvemod(Mat(1),[1/2]~,1) *** ^---------------------------- *** matsolvemod: incorrect type in matsolvemod (D) (t_COL). *** at top-level: matsolvemod(Mat(1),1,[1/2]~) *** ^---------------------------- *** matsolvemod: incorrect type in matsolvemod (Y) (t_COL). *** at top-level: matsolvemod([;],[]~,[0]~) *** ^------------------------- *** matsolvemod: inconsistent dimensions in matsolvemod [2]. *** at top-level: matsolvemod([;],[1]~,[1,2]~) *** ^---------------------------- *** matsolvemod: inconsistent dimensions in matsolvemod [2]. Total time spent: 298 pari-2.17.2/src/test/32/str0000644000175000017500000000250014567450071013717 0ustar billbillVecsmall([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33]) "hello world!" "hello world!" "\\frac{x^3\n + 3\\*y\\*x^2\n + 3\\*y^2\\*x\n + y^3}{x^2\n - 2\\*y\\*x\n + y ^2}" "1 mod 2" "t" "1\n + 2\\*I" "2\n + w" "2+O(3^2)" "x\n + x^2+ O(x^3)" "\\pmatrix{ 1&2\\cr}\n" "\\pmatrix{\n 0&1\\cr\n 1&0\\cr\n }" "\\pmatrix{ 1&2\\cr}\n" "\\pmatrix{ 1&2\\cr}\n" "\\pmatrix{ 1\\cr\n2\\cr\n}" "\\pmatrix{\n 1&0\\cr\n 0&1\\cr\n }" "\\pmatrix{\n \\frac{1}{2}\\cr\n }" "ab" "(x)\\mapsto x+1" "-\\infty" "+\\infty" "x" "1/2" "ab1" 1 ["", "a", "b", "", ""] ["a", "b", "", "", "", "cc"] ["a", "b", "c"] ["a", "b", "c"] ["", "b", ""] ["", "", ""] "a/1/cc" "a1cc" "" "a" "1" "3h, 25min, 45,678 ms" *** at top-level: strchr(-1) *** ^---------- *** strchr: out of range in integer -> character conversion (-1). *** at top-level: strsplit(1,1) *** ^------------- *** strsplit: incorrect type in strsplit (t_INT). *** at top-level: strsplit("1",'x) *** ^---------------- *** strsplit: incorrect type in strsplit (t_POL). *** at top-level: strjoin(1,"/") *** ^-------------- *** strjoin: incorrect type in strjoin (t_INT). *** at top-level: strjoin([],1) *** ^------------- *** strjoin: incorrect type in strjoin (t_INT). Total time spent: 0 pari-2.17.2/src/test/32/mscosets0000644000175000017500000001604214567450071014755 0ustar billbill[[[1, 0; 0, 1], [0, 1; -1, 2], [-1, 1; -2, 1], [-1, 1; -1, 0]], Vecsmall([4, 2, 3, 1]), [[1, -1; 0, 1], [-2, 1; -5, 2], [-3, 2; -5, 3], [1, 1; 0, 1]]] [[[1, 0; 0, 1], [0, -1; 1, -1], [-1, 1; -1, 0], [1, 0; 1, 1], [0, -1; 1, -2] , [-1, 1; -2, 1]], [Vecsmall([3, 2]), Vecsmall([4, 3]), Vecsmall([1, 1]), Ve csmall([2, 5]), Vecsmall([5, 6]), Vecsmall([6, 4])]] [[[1, 0; 0, 1]], [Vecsmall([1, 1, 1, 1])]] [[[1, 0; 0, 1], [0, 1; -1, 3], [-1, 2; -3, 5], [-2, 1; -5, 2], [-1, 1; -2, 1 ], [-1, 1; -1, 0]], Vecsmall([6, 5, 4, 3, 2, 1]), [[1, -1; 0, 1], [-1, 1; -5 , 4], [-9, 4; -25, 11], [-11, 4; -25, 9], [-4, 1; -5, 1], [1, 1; 0, 1]]] [[[1, 0; 0, 1], [0, 1; -1, 3], [-1, 1; -3, 2], [-1, 2; -2, 3], [-2, 1; -3, 1 ], [-1, 1; -1, 0]], Vecsmall([2, 1, 4, 3, 6, 5]), [[1, 0; -3, 1], [1, 0; 3, 1], [-5, 3; -12, 7], [-7, 3; -12, 5], [-2, 3; -3, 4], [-4, 3; -3, 2]]] [[[1, 0; 0, 1], [0, 1; -1, 3], [-1, 1; -3, 2], [-1, 2; -2, 3], [-2, 1; -3, 1 ], [-1, 1; -1, 0]], Vecsmall([2, 1, 4, 3, 6, 5]), [[1, 0; -3, 1], [1, 0; 3, 1], [-5, 3; -12, 7], [-7, 3; -12, 5], [-2, 3; -3, 4], [-4, 3; -3, 2]]] [[[1, -2; 0, 1], [2, -1; -1, 1], [1, 0; -1, 1], [0, 1; -1, 2], [-1, 2; -2, 3 ], [-2, 1; -3, 1], [-1, 4; -1, 3], [-4, 3; -3, 2], [-3, 2; -2, 1], [-2, 1; - 1, 0]], Vecsmall([10, 9, 4, 3, 6, 5, 8, 7, 2, 1]), [[1, -4; 0, 1], [5, -8; - 3, 5], [1, 0; -3, 1], [1, 0; 3, 1], [-5, 4; -9, 7], [-7, 4; -9, 5], [-11, 16 ; -9, 13], [-13, 16; -9, 11], [5, 8; 3, 5], [1, 4; 0, 1]]] [[[1, -6; 0, 1], [6, -11; -1, 2], [11, -5; -2, 1], [5, -14; -1, 3], [14, -9; -3, 2], [9, -4; -2, 1], [4, -11; -1, 3], [11, -18; -3, 5], [18, -7; -5, 2], [7, -3; -2, 1], [3, -11; -1, 4], [11, -8; -4, 3], [8, -21; -3, 8], [21, -13 ; -8, 5], [13, -5; -5, 2], [5, -2; -2, 1], [2, -11; -1, 6], [11, -9; -6, 5], [9, -7; -5, 4], [7, -5; -4, 3], [5, -18; -3, 11], [18, -13; -11, 8], [13, - 8; -8, 5], [8, -3; -5, 2], [3, -4; -2, 3], [4, -5; -3, 4], [5, -6; -4, 5], [ 6, -7; -5, 6], [7, -1; -6, 1], [1, -5; -1, 6], [5, -9; -6, 11], [9, -4; -11, 5], [4, -7; -5, 9], [7, -3; -9, 4], [3, -2; -4, 3], [2, -7; -3, 11], [7, -5 ; -11, 8], [5, -8; -8, 13], [8, -3; -13, 5], [3, -1; -5, 2], [1, -2; -2, 5], [2, -7; -5, 18], [7, -5; -18, 13], [5, -3; -13, 8], [3, -1; -8, 3], [1, -1; -3, 4], [1, -1; -4, 5], [1, -1; -5, 6], [1, 0; -6, 1], [0, 1; -1, 6], [-1, 2; -6, 11], [-2, 1; -11, 5], [-1, 3; -5, 14], [-3, 2; -14, 9], [-2, 1; -9, 4 ], [-1, 3; -4, 11], [-3, 5; -11, 18], [-5, 2; -18, 7], [-2, 1; -7, 3], [-1, 4; -3, 11], [-4, 3; -11, 8], [-3, 8; -8, 21], [-8, 5; -21, 13], [-5, 2; -13, 5], [-2, 1; -5, 2], [-1, 6; -2, 11], [-6, 5; -11, 9], [-5, 4; -9, 7], [-4, 3; -7, 5], [-3, 11; -5, 18], [-11, 8; -18, 13], [-8, 5; -13, 8], [-5, 2; -8, 3], [-2, 3; -3, 4], [-3, 4; -4, 5], [-4, 5; -5, 6], [-5, 6; -6, 7], [-6, 1; -7, 1], [-1, 6; -1, 5], [-6, 11; -5, 9], [-11, 5; -9, 4], [-5, 9; -4, 7], [ -9, 4; -7, 3], [-4, 3; -3, 2], [-3, 11; -2, 7], [-11, 8; -7, 5], [-8, 13; -5 , 8], [-13, 5; -8, 3], [-5, 2; -3, 1], [-2, 5; -1, 2], [-5, 18; -2, 7], [-18 , 13; -7, 5], [-13, 8; -5, 3], [-8, 3; -3, 1], [-3, 4; -1, 1], [-4, 5; -1, 1 ], [-5, 6; -1, 1], [-6, 1; -1, 0]], Vecsmall([98, 66, 15, 36, 54, 24, 60, 80 , 91, 40, 56, 26, 62, 44, 3, 65, 51, 70, 82, 46, 67, 27, 72, 6, 84, 12, 22, 77, 30, 29, 57, 39, 68, 45, 74, 4, 47, 87, 32, 10, 90, 58, 48, 14, 34, 20, 3 7, 43, 50, 49, 17, 64, 85, 5, 73, 11, 31, 42, 89, 7, 75, 13, 93, 52, 16, 2, 21, 33, 95, 18, 76, 23, 55, 35, 61, 71, 28, 79, 78, 8, 88, 19, 94, 25, 53, 9 6, 38, 81, 59, 41, 9, 97, 63, 83, 69, 86, 92, 1]), [[1, -12; 0, 1], [133, -7 2; -24, 13], [-65, -168; 12, 31], [-169, -108; 36, 23], [277, -60; -60, 13], [-53, -84; 12, 19], [133, -48; -36, 13], [217, -264; -60, 73], [85, -216; - 24, 61], [-41, -24; 12, 7], [133, -36; -48, 13], [-65, -84; 24, 31], [505, - 192; -192, 73], [-377, -144; 144, 55], [-31, -168; 12, 65], [29, -12; -12, 5 ], [133, -24; -72, 13], [217, -132; -120, 73], [85, -108; -48, 61], [-41, -1 2; 24, 7], [217, -120; -132, 73], [-137, -168; 84, 103], [233, -144; -144, 8 9], [-19, -84; 12, 53], [17, -24; -12, 17], [-31, -84; 24, 65], [-103, -168; 84, 137], [85, -72; -72, 61], [-13, -12; 12, 11], [-11, -12; 12, 13], [217, -60; -264, 73], [-137, -84; 168, 103], [85, -48; -108, 61], [-65, -24; 84, 31], [17, -12; -24, 17], [-23, -108; 36, 169], [-53, -12; 84, 19], [89, -144 ; -144, 233], [-103, -84; 168, 137], [-7, -24; 12, 41], [5, -12; -12, 29], [ 85, -24; -216, 61], [-65, -12; 168, 31], [-55, -144; 144, 377], [-31, -24; 8 4, 65], [-7, -12; 24, 41], [-19, -12; 84, 53], [-31, -12; 168, 65], [1, 0; - 12, 1], [1, 0; 12, 1], [13, 24; 72, 133], [-31, 12; -168, 65], [-23, 36; -10 8, 169], [13, 60; 60, 277], [-19, 12; -84, 53], [13, 36; 48, 133], [73, 60; 264, 217], [61, 24; 216, 85], [-7, 12; -24, 41], [13, 48; 36, 133], [-31, 24 ; -84, 65], [73, 192; 192, 505], [-55, 144; -144, 377], [-65, 12; -168, 31], [5, 12; 12, 29], [13, 72; 24, 133], [73, 120; 132, 217], [61, 48; 108, 85], [-7, 24; -12, 41], [73, 132; 120, 217], [-103, 84; -168, 137], [89, 144; 14 4, 233], [-53, 12; -84, 19], [17, 12; 24, 17], [-65, 24; -84, 31], [-137, 84 ; -168, 103], [61, 72; 72, 85], [-11, 12; -12, 13], [-13, 12; -12, 11], [73, 264; 60, 217], [-103, 168; -84, 137], [61, 108; 48, 85], [-31, 84; -24, 65] , [17, 24; 12, 17], [-169, 36; -108, 23], [-19, 84; -12, 53], [233, 144; 144 , 89], [-137, 168; -84, 103], [-41, 12; -24, 7], [29, 12; 12, 5], [61, 216; 24, 85], [-31, 168; -12, 65], [-377, 144; -144, 55], [-65, 84; -24, 31], [-4 1, 24; -12, 7], [-53, 84; -12, 19], [-65, 168; -12, 31], [1, 12; 0, 1]]] [[[1, 0; 0, 1], [0, 1; -1, 7], [-1, 3; -7, 20], [-3, 2; -20, 13], [-2, 3; -1 3, 19], [-3, 4; -19, 25], [-4, 1; -25, 6], [-1, 1; -6, 5], [-1, 1; -5, 4], [ -1, 4; -4, 15], [-4, 3; -15, 11], [-3, 2; -11, 7], [-2, 3; -7, 10], [-3, 1; -10, 3], [-1, 2; -3, 5], [-2, 3; -5, 7], [-3, 4; -7, 9], [-4, 9; -9, 20], [- 9, 5; -20, 11], [-5, 6; -11, 13], [-6, 7; -13, 15], [-7, 1; -15, 2], [-1, 3; -2, 5], [-3, 2; -5, 3], [-2, 1; -3, 1], [-1, 1; -1, 0]], Vecsmall([26, 12, 19, 13, 20, 16, 8, 7, 23, 22, 21, 2, 4, 18, 24, 6, 25, 14, 3, 5, 11, 10, 9, 15, 17, 1]), [[1, -1; 0, 1], [-7, 2; -60, 17], [-53, 24; -360, 163], [-41, 1 2; -270, 79], [-61, 28; -390, 179], [-43, 18; -270, 113], [-29, 5; -180, 31] , [-31, 5; -180, 29], [-7, 4; -30, 17], [-23, 11; -90, 43], [-97, 45; -360, 167], [-17, 2; -60, 7], [-79, 12; -270, 41], [-47, 21; -150, 67], [-11, 7; - 30, 19], [-113, 18; -270, 43], [-13, 10; -30, 23], [-67, 21; -150, 47], [-16 3, 24; -360, 53], [-179, 28; -390, 61], [-167, 45; -360, 97], [-43, 11; -90, 23], [-17, 4; -30, 7], [-19, 7; -30, 11], [-23, 10; -30, 13], [1, 1; 0, 1]] ] 1 [[Vecsmall([1, 2, 3]), Vecsmall([2, 1, 3])], [Vecsmall([2, 1]), Vecsmall([1, 2])]] *** at top-level: mscosets([],x->1) *** ^----------------- *** mscosets: incorrect type in mscosets [trivial group] (t_VEC). *** at top-level: mscosets([1],(x,y)->1) *** ^---------------------- *** mscosets: incorrect type in mscosets (t_CLOSURE). *** at top-level: N=24;G0=mspolygon(N);msfarey(G0,g->a=g[1,1]%N; *** ^------------------------- *** msfarey: msfarey: H is not a subgroup of PSL_2(Z). Total time spent: 76 pari-2.17.2/src/test/32/gp0000644000175000017500000000000014567450071013506 0ustar billbillpari-2.17.2/src/test/32/disc0000644000175000017500000000443514567450071014042 0ustar billbillMod(1, 2) Mod(1, 3) Mod(1, 3) -27*d^2*a^2 + (18*d*c*b - 4*c^3)*a + (-4*d*b^3 + c^2*b^2) Mod(2, 3)*c^3*a + (Mod(2, 3)*d*b^3 + Mod(1, 3)*c^2*b^2) Mod(2, 3)*c^3*a -4/x 0 0:1 0:1 0:1 Mod(Mod(0, 2), Mod(1, 2)*a^5 + Mod(1, 2)*a^4 + Mod(1, 2)*a^2 + Mod(1, 2)*a + Mod(1, 2)):Mod(Mod(1, 2), Mod(1, 2)*a^5 + Mod(1, 2)*a^4 + Mod(1, 2)*a^2 + M od(1, 2)*a + Mod(1, 2)) Mod(Mod(0, 3), Mod(1, 3)*a^5 + Mod(1, 3)*a^4 + Mod(2, 3)*a^3 + Mod(1, 3)):Mo d(Mod(1, 3), Mod(1, 3)*a^5 + Mod(1, 3)*a^4 + Mod(2, 3)*a^3 + Mod(1, 3)) Mod(Mod(0, 1267650600228229401496703205653), Mod(1, 126765060022822940149670 3205653)*a^3 + Mod(1, 1267650600228229401496703205653)*a^2 + Mod(12676506002 28229401496703205649, 1267650600228229401496703205653)*a + Mod(1, 1267650600 228229401496703205653)):Mod(Mod(1, 1267650600228229401496703205653), Mod(1, 1267650600228229401496703205653)*a^3 + Mod(1, 126765060022822940149670320565 3)*a^2 + Mod(1267650600228229401496703205649, 126765060022822940149670320565 3)*a + Mod(1, 1267650600228229401496703205653)) -146651015482972629339265779949471898228001932467822308156964313865094187865 0737725517311213972696938502546040565323278550679151618571557171893805575874 8427882056024408462365432062266407566752265468717307291 [0, Mat([0, 1])] [1, matrix(0,2)] [-4, Mat([2, 2])] [590696737518324963052366967566873816746861391761774240121952378042565253754 9745139928713041938024683034295373144229922138673743670575043095617043762369 710294827008, [2, 20; 3, 6; 19, 2; 29, 2; 37, 2; 47, 4; 83, 4; 2153, 4; 1038 43, 2; 4596226147103257, 3; 1889060957497626097155386071807, 2]] [590696737518324963052366967566873816746861391761774240121952378042565253754 9745139928713041938024683034295373144229922138673743670575043095617043762369 710294827008, [2, 20; 3, 6; 19, 2; 29, 2; 37, 2; 47, 4; 83, 4; 2153, 4; 1038 43, 2; 606528662981, 2; 4596226147103257, 3; 3114545235526325747, 2]] [374863741084558898826492744180004639816476168031283822100788706103545903812 8391139862076816170261639908101111519233533818009116577269022156451759608638 2788345856, [2, 66; 3, 6; 13, 20; 131, 2; 233, 4; 547, 2; 4441, 4; 60527, 4; 163561, 2; 647113, 4; 314542445630843, 2]] 2*a + 1 0 -110592/y^4 *** at top-level: poldisc(x^2/y^2,y) *** ^------------------ *** poldisc: incorrect type in polresultant (t_RFRAC). Total time spent: 92 pari-2.17.2/src/test/32/ff0000644000175000017500000004750014760123736013513 0ustar billbill? test(2,20) [a, 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 + Mo d(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^2 0 + 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 + M od(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, a^12 + a^9 + a^6 + a^4 + a^3 + a^2 + a + 1]~, [x^3 + (a^17 + a^16 + a^10 + a^7 + a^3), 1; x^3 + (a^17 + a^16 + a^10 + a^7 + a^3 + a), 1], [], a/x, 1, a^18 + a^17 + a^16 + a^15 + a^12 + a^8 + a^ 2, 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, a^2 + 3*a + 1, 6*a^6 + a^5 + 6*a^4 + a^3 + 6*a^2 + a + 1, 3*a + 3, a + 3 , 2*a^6 + 5*a^5 + 2*a^4 + 5*a^3 + 2*a^2 + 5*a, 2*a + 2, 2*a + 2, 4*a + 4, a^ 6 + 6, 6*a, a^2, 4*a^6 + a^5 + 3*a^4 + 3*a^3 + 5*a^2 + 2*a + 5, a^2 + a + 1, a^2 + a + 1, 4, a^6 + 2*a^5 + 3*a^4 + a^2 + a + 6, Mod(5, 7), Mod(0, 7), Mo d(1, 7)*x^7 + Mod(6, 7)*x + Mod(6, 7), Mod(1, 7)*x^7 + Mod(6, 7)*x + Mod(6, 7), [a, a + 1, a + 2, a + 3, a + 4, a + 5, a + 6]~, [x^3 + (2*a^6 + 6*a^5 + 2*a^4 + a^2 + 4*a + 2), 1; x^3 + (5*a^6 + a^5 + 5*a^4 + 6*a^2 + 2*a + 5), 1] , a^6 + 5*a^5 + 4*a^4 + 2*a^3 + 3*a^2 + a + 2, a/x, (x + a)/(x + 6*a), a^6 + a^4 + 2*a^3 + 3*a^2 + a, 137257, a, Mat([x^2 + x + a, 1]), []~] ? test(precprime(2^32),3) [a, 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, 429496 7290*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 (4294967290, 4294967291), Mod(1, 4294967291)*x^3 + Mod(1, 4294967291)*x^2 + Mod(4294967287, 4294967291)*x + Mod(1, 4294967291), Mod(1, 4294967291)*x^3 + Mod(1, 4294967291)*x^2 + Mod(4294967287, 4294967291)*x + Mod(1, 4294967291) , [a, a^2 + a + 4294967288, 4294967290*a^2 + 4294967289*a + 2]~, [x + (34444 7023*a^2 + 1616586690*a + 252460086), 1; x + (3340051543*a^2 + 1627577691*a + 2021233148), 1; x^2 + (954915748*a^2 + 2667389600*a + 2273734143)*x + (816 322992*a^2 + 830924795*a + 1995175223), 1; x^2 + (3950520268*a^2 + 267838060 1*a + 4042507205)*x + (1642837480*a^2 + 2548350348*a + 1670376662), 1], 3618 892287*a^2 + 1482857269*a + 1021597254, a/x, (x + a)/(x + 4294967290*a), 349 0383416*a^2 + 1759576229*a + 3092551593, 36893488070109691946, a, [x + (1365 670490*a^2 + 3373566631*a + 4083593885), 1; x + (2929296801*a^2 + 921400660* a + 211373407), 1], [1365670490*a^2 + 3373566631*a + 4083593884, 2929296801* a^2 + 921400660*a + 211373406]~] ? test(nextprime(2^32),3) [a, a^2 + 3*a + 1, a^2 + 4294967310, 1431655771*a + 1431655771, a + 34359738 49, 3579139425*a^2 + 1431655772, 715827886*a + 715827886, 1024*a + 1024, 114 5044996*a + 1145044996, a^2 + a + 4294967309, 4294967310*a, a^2, 264190711*a ^2 + 2629464558*a + 2494776416, 2086193154*a^2 + 2086193154*a + 2086193154, 2208774156*a^2 + 2208774156*a + 2208774156, 2086193154, 996804783*a^2 + 2908 221018*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 + 4294967309, 4294967310*a^2 + 4294967310*a + 1]~, [x^2 + (2086193155*a^2 + 1 22581001)*x + 2086193154, 1; x^2 + (2208774157*a^2 + 4172386308)*x + 2208774 156, 1; x^2 + (4294967310*a^2 + 2)*x + 1, 1], 1484088443*a^2 + 1141114953*a + 4283364322, a/x, (x + a)/(x + 4294967310*a), 1892124804*a^2 + 446887574*a + 1010425087, 6148914735617846011, a, [x + (268392743*a^2 + 2459390605*a + 1 304316255), 1; x + (4026574568*a^2 + 1835576706*a + 2990651057), 1], [268392 743*a^2 + 2459390605*a + 1304316254, 4026574568*a^2 + 1835576706*a + 2990651 056]~] ? default(echo,0); ? stest(2,1005); ? stest(17,2); ? stest(17,3); ? stest(17,4); ? stest(nextprime(2^31),2); ? stest(nextprime(2^31),3); ? stest(nextprime(2^31),4); ? stest(nextprime(2^63),2); ? stest(nextprime(2^63),3); ? stest(nextprime(2^63),4); ? stest(nextprime(2^65),2); ? stest(nextprime(2^65),3); ? stest(nextprime(2^65),4); ? ftest(2,1005,7); ? ffgen(ffinit(2^32-5,101),'a)^10000 2904925334*a^100 + 700105542*a^99 + 1727200511*a^98 + 1173808205*a^97 + 9542 0994*a^96 + 3202419959*a^95 + 2481924190*a^94 + 3126863204*a^93 + 2955970830 *a^92 + 2548647191*a^91 + 1047527349*a^90 + 1607847794*a^89 + 1136036718*a^8 8 + 2224103182*a^87 + 234809824*a^86 + 1334629770*a^85 + 3694521682*a^84 + 2 888958800*a^83 + 2981717284*a^82 + 3586954794*a^81 + 956529198*a^80 + 193357 785*a^79 + 2461870083*a^78 + 2884929899*a^77 + 2136433918*a^76 + 3711607228* a^75 + 332814573*a^74 + 2094440266*a^73 + 933657478*a^72 + 2778340755*a^71 + 3169750773*a^70 + 2171979949*a^69 + 1221433421*a^68 + 901860002*a^67 + 2970 90232*a^66 + 3539970492*a^65 + 2076910613*a^64 + 2401092275*a^63 + 171183351 4*a^62 + 3584831951*a^61 + 2855998596*a^60 + 347617911*a^59 + 2423948087*a^5 8 + 2221962383*a^57 + 2749975174*a^56 + 1550735992*a^55 + 2529466701*a^54 + 2598855843*a^53 + 4023905766*a^52 + 1486945524*a^51 + 2441781373*a^50 + 1138 122930*a^49 + 2066584358*a^48 + 1722922056*a^47 + 3744247345*a^46 + 29285190 73*a^45 + 1223452975*a^44 + 2713760803*a^43 + 2142407081*a^42 + 756824586*a^ 41 + 3732788422*a^40 + 1164553813*a^39 + 771729217*a^38 + 3634297024*a^37 + 2421113272*a^36 + 2598325671*a^35 + 3513778816*a^34 + 1539027125*a^33 + 3689 734857*a^32 + 4188593390*a^31 + 2825758998*a^30 + 3192363801*a^29 + 36501544 35*a^28 + 1334480978*a^27 + 2009094380*a^26 + 151875699*a^25 + 3435707889*a^ 24 + 661453301*a^23 + 416421795*a^22 + 3246563523*a^21 + 985317917*a^20 + 33 10261776*a^19 + 4234321367*a^18 + 380085156*a^17 + 1049653093*a^16 + 6266755 65*a^15 + 1603594749*a^14 + 3130157282*a^13 + 844750099*a^12 + 3495279283*a^ 11 + 1036502501*a^10 + 576151557*a^9 + 1040168751*a^8 + 1714788152*a^7 + 234 0199159*a^6 + 4175283296*a^5 + 2975302344*a^4 + 2428563952*a^3 + 443574314*a ^2 + 3215614405*a + 2183237283 ? ffgen(ffinit(2^64-59,101),'a)^10000 11357361951151958121*a^100 + 5792035517727999732*a^99 + 7489923161672088612* a^98 + 198291789480115765*a^97 + 7027135568582861768*a^96 + 7299386875942518 369*a^95 + 10681924511986429849*a^94 + 14721409711812770068*a^93 + 177845253 02221024156*a^92 + 7804341282953434235*a^91 + 6253292858501893536*a^90 + 375 2205311837838488*a^89 + 12205965799946763222*a^88 + 7579185967234550243*a^87 + 7660231629286376323*a^86 + 8927589722637637677*a^85 + 6783475681455269614 *a^84 + 11968255844292754829*a^83 + 5819238353489370105*a^82 + 6918133330273 010048*a^81 + 8900778062932659277*a^80 + 15250824442906974876*a^79 + 2484274 759583929736*a^78 + 12662494501202465352*a^77 + 1658627870779087936*a^76 + 1 3011592420351927994*a^75 + 1429162280240510446*a^74 + 8085544061123262008*a^ 73 + 12999730205733779276*a^72 + 14782490105219029716*a^71 + 970562341709006 1989*a^70 + 10676813376503700642*a^69 + 13433094161603852463*a^68 + 17199289 874783012603*a^67 + 4285333119776358644*a^66 + 16021251868058308047*a^65 + 1 5495498503350376322*a^64 + 5966197018829209744*a^63 + 12345332784539353625*a ^62 + 14865549204004875095*a^61 + 8272995682833482264*a^60 + 121032254702015 79677*a^59 + 17479835254811511245*a^58 + 3057285969116272639*a^57 + 14559795 162132711775*a^56 + 13046944472429221491*a^55 + 1019495020975929944*a^54 + 1 6803291081324517730*a^53 + 17710829803474400119*a^52 + 2594650197306879903*a ^51 + 12847996295434431851*a^50 + 9729674550253550622*a^49 + 109429518884359 53217*a^48 + 508631243443378452*a^47 + 4416164175737874514*a^46 + 4138550054 669964040*a^45 + 91535476336245596*a^44 + 11254247175995051473*a^43 + 336718 1085033412978*a^42 + 11302910178987761836*a^41 + 14219471129414354857*a^40 + 3472640334363308855*a^39 + 44279726220391285*a^38 + 8772473950884549985*a^3 7 + 6773120702751407339*a^36 + 6996688466561413845*a^35 + 546584401725025696 5*a^34 + 7818703010175000236*a^33 + 13304920141834573258*a^32 + 114357960485 84276*a^31 + 4331469251417299625*a^30 + 17686902244060347692*a^29 + 17607783 19947200401*a^28 + 3012511890706784509*a^27 + 18319341252918336566*a^26 + 10 018340880050704466*a^25 + 3681292000887380307*a^24 + 6241896558174496327*a^2 3 + 9334414729239110374*a^22 + 14900454697774091776*a^21 + 77193581568725477 10*a^20 + 7957196232563221737*a^19 + 14008909657978711585*a^18 + 43480361564 79613902*a^17 + 1768274872694937073*a^16 + 6926632468462411736*a^15 + 138466 31025657876514*a^14 + 16445358444805977559*a^13 + 3015896265596741617*a^12 + 3099427746327195442*a^11 + 7091419183460950797*a^10 + 13541704365745256080* a^9 + 9319609099157088592*a^8 + 3845681432811214920*a^7 + 380965757660125686 6*a^6 + 14250915374958368396*a^5 + 5948030384875855137*a^4 + 434385110189972 4971*a^3 + 16736030436363202463*a^2 + 11764704170600631014*a + 1394491261297 3941130 ? for(i=1,10,print(ffnbirred(11,i))); 11 55 440 3630 32208 295020 2783880 26793030 261994040 2593726344 ? for(i=1,10,print(ffnbirred(11,i,1))); 11 66 506 4136 36344 331364 3115244 29908274 291902314 2885628658 ? t=ffgen(2^64)^((2^64-1)\5);1/t x^58 + x^57 + x^56 + x^52 + x^51 + x^49 + x^46 + x^45 + x^42 + x^39 + x^36 + x^35 + x^32 + x^30 + x^29 + x^25 + x^23 + x^22 + x^21 + x^20 + x^19 + x^12 + x^8 + x^7 + x^6 + x^2 ? sqrt(Mod(-1,4296540161)) Mod(1086811600, 4296540161) ? sqrt(Mod(-1,18446744073944432641)) Mod(6687681666819568403, 18446744073944432641) ? centerlift(factorcantor(prod(i=-10,10,(x^2-i)),2^64+13)[,1]) [x, x + 1, x + 2, x + 3, x + 248527397336721375, x + 2370518075556110396, x + 2888582621843189425, x + 4741036151112220792, x + 5193293969518580612, x + 6494187761904104278, x + 7111554226668331188, x + 7312212166335540022, x + 7562574061564804959, x - 7562574061564804959, x - 7312212166335540022, x - 7 111554226668331188, x - 6494187761904104278, x - 5193293969518580612, x - 47 41036151112220792, x - 2888582621843189425, x - 2370518075556110396, x - 248 527397336721375, x - 3, x - 2, x - 1, x^2 + 2, x^2 + 3, x^2 + 8, x^2 + 10, x ^2 - 10, x^2 - 8, x^2 - 3, x^2 - 2]~ ? conjvec(Mod(x,x^2+Mod(1,3))) [Mod(Mod(1, 3)*x, Mod(1, 3)*x^2 + Mod(1, 3)), Mod(Mod(2, 3)*x, Mod(1, 3)*x^2 + Mod(1, 3))]~ ? default(echo,0); ? test(2^5) [t^4 + t^3; t^4 + t^3; 1] [t, t^2; t + 1, t^2 + 1] 2 t^4 + t^2 [1, 0, 0; 0, 1, 0; 0, 0, 1] [t^2 + t, t^4 + t^3 + 1, t^4 + t^3 + t]~ 1 1 1 1 [0, 1]~ []~ [;] [Vecsmall([1]), Vecsmall([2])] [0, 1; t, 0] []~ [1, 1]~ ? test(7^5) [3*t^4 + 5*t^3 + 6*t^2 + 2*t; 4*t^4 + 2*t^3 + t^2 + 5*t; 1] [t, t^2; t + 1, t^2 + 1] 2 6*t^4 + 2*t^3 + 4*t^2 + 2*t + 2 [1, 0, 0; 0, 1, 0; 0, 0, 1] [3*t^2 + 3*t, 6*t^4 + 5*t^3 + 4*t^2 + 5*t + 6, 6*t^4 + 5*t^3 + 4*t^2 + 6*t]~ 1 1 1 1 [0, 1]~ []~ [;] [Vecsmall([1]), Vecsmall([2])] [0, 1; t, 0] []~ [6, 1]~ ? test((2^64+13)^5) [3*t^4 + 5*t^3 + 18446744073709551621*t^2 + 18446744073709551617*t; 18446744 073709551626*t^4 + 18446744073709551624*t^3 + 8*t^2 + 12*t; 1] [t, t^2; t + 1, t^2 + 1] 2 18446744073709551628*t^4 + 2*t^3 + 18446744073709551626*t^2 + 2*t + 2 [1, 0, 0; 0, 1, 0; 0, 0, 1] [3*t^2 + 3*t, 18446744073709551628*t^4 + 5*t^3 + 4*t^2 + 1844674407370955162 7*t + 18446744073709551628, 18446744073709551628*t^4 + 5*t^3 + 4*t^2 + 18446 744073709551628*t]~ 1 1 1 1 [0, 1]~ []~ [;] [Vecsmall([1]), Vecsmall([2])] [0, 1; t, 0] []~ [18446744073709551628, 1]~ ? default(echo,0); ? test(nextprime(2^7)^5) ? test(nextprime(2^15)^5) ? test(nextprime(2^31)^5) ? test(nextprime(2^63)^5) ? test(nextprime(2^80)^5) ? test(nextprime(2^7)^5,27) ? test(nextprime(2^15)^5,27) ? test(nextprime(2^31)^5,27) ? test(nextprime(2^63)^5,27) ? test(nextprime(2^80)^2,27) ? my(a=ffgen([2,100]));(0*a*x)*x 0 ? default(echo,0); ? test(2,1,5,3) error("domain error in ffcompomap: m domain does not contain codomain of [b, c^12 + c^10 + c^9 + c^5 + c^3 + c^2]") error("domain error in ffcompomap: m domain does not contain codomain of [b, b^5 + b^4 + b^2 + b + 1]") error("domain error in ffmap: m domain does not contain b^4 + b^3 + 1") error("domain error in ffmap: m domain does not contain c^12 + c^10 + c^9 + c^5 + c^3 + c^2") error("incorrect type in ffextend (t_POL).") ? test(2,5,5,3) error("domain error in ffcompomap: m domain does not contain codomain of [b, c^70 + c^69 + c^67 + c^66 + c^64 + c^60 + c^58 + c^57 + c^56 + c^54 + c^51 + c^50 + c^48 + c^47 + c^45 + c^44 + c^42 + c^40 + c^39 + c^37 + c^34 + c^32 + c^31 + c^30 + c^29 + c^28 + c^24 + c^20 + c^18 + c^15 + c^13 + c^9 + c^8 + c^7 + c^4 + c^3 + c^2 + c + 1]") error("domain error in ffcompomap: m domain does not contain codomain of [b, b^5 + (a^4 + a^3 + a^2 + 1)*b^4 + (a^4 + a^3 + a^2)*b^3 + (a^4 + a^2 + a + 1)*b^2 + (a^3 + a^2)*b + (a^4 + a^3)]") error("domain error in ffmap: m domain does not contain b^23 + b^22 + b^20 + b^19 + b^18 + b^14 + b^13 + b^12 + b^9 + b^8 + b^7 + b^4 + b + 1") error("domain error in ffmap: m domain does not contain c^70 + c^69 + c^67 + c^66 + c^64 + c^60 + c^58 + c^57 + c^56 + c^54 + c^51 + c^50 + c^48 + c^47 + c^45 + c^44 + c^42 + c^40 + c^39 + c^37 + c^34 + c^32 + c^31 + c^30 + c^29 + c^28 + c^24 + c^20 + c^18 + c^15 + c^13 + c^9 + c^8 + c^7 + c^4 + c^3 + c ^2 + c + 1") error("incorrect type in ffextend (t_POL).") ? test(3,1,2,3) error("domain error in ffcompomap: m domain does not contain codomain of [b, c^4 + c^2 + c]") error("domain error in ffcompomap: m domain does not contain codomain of [b, b^2 + b + 2]") error("domain error in ffmap: m domain does not contain 2") error("domain error in ffmap: m domain does not contain c^4 + c^2 + c") error("incorrect type in ffextend (t_POL).") ? test(3,10,2,3) error("domain error in ffcompomap: m domain does not contain codomain of [b, c^51 + c^49 + c^47 + 2*c^45 + c^43 + 2*c^42 + c^41 + 2*c^40 + c^39 + 2*c^38 + 2*c^37 + c^35 + c^34 + 2*c^33 + c^32 + 2*c^31 + c^28 + 2*c^25 + 2*c^23 + 2*c^21 + c^19 + 2*c^18 + 2*c^17 + c^16 + 2*c^15 + c^14 + 2*c^13 + 2*c^12 + c ^11 + c^10 + c^9 + 2*c^8 + c^7 + c^5 + c^3 + 1]") error("domain error in ffcompomap: m domain does not contain codomain of [b, b^2 + (2*a^9 + 2*a^7 + 2*a^6)*b + (2*a^9 + 2*a^2)]") error("domain error in ffmap: m domain does not contain b^19 + b^17 + b^16 + b^14 + b^12 + b^11 + 2*b^10 + 2*b^8 + b^7 + 2*b^6 + b^4 + b^2 + 2*b") error("domain error in ffmap: m domain does not contain c^51 + c^49 + c^47 + 2*c^45 + c^43 + 2*c^42 + c^41 + 2*c^40 + c^39 + 2*c^38 + 2*c^37 + c^35 + c^ 34 + 2*c^33 + c^32 + 2*c^31 + c^28 + 2*c^25 + 2*c^23 + 2*c^21 + c^19 + 2*c^1 8 + 2*c^17 + c^16 + 2*c^15 + c^14 + 2*c^13 + 2*c^12 + c^11 + c^10 + c^9 + 2* c^8 + c^7 + c^5 + c^3 + 1") error("incorrect type in ffextend (t_POL).") ? test(nextprime(2^100),1,3,2) error("domain error in ffcompomap: m domain does not contain codomain of [b, 568210514509985430766932066568*c^5 + 227284205803994172306772826627*c^4 + 4 66744351204630889558551340395*c^3 + 82525812821688360182816323954*c^2 + 4153 34828463251255346305105801*c + 117700749434211267801721642361]") error("domain error in ffcompomap: m domain does not contain codomain of [b, b^3 + b^2 + 1267650600228229401496703205649*b + 1]") error("domain error in ffmap: m domain does not contain b^2 + 12676506002282 29401496703205652*b + 1") error("domain error in ffmap: m domain does not contain 56821051450998543076 6932066568*c^5 + 227284205803994172306772826627*c^4 + 4667443512046308895585 51340395*c^3 + 82525812821688360182816323954*c^2 + 4153348284632512553463051 05801*c + 117700749434211267801721642361") error("incorrect type in ffextend (t_POL).") ? test(nextprime(2^100),3,3,2) error("domain error in ffcompomap: m domain does not contain codomain of [b, 46484092795487340755616362656*c^17 + 1055644262063180547422327045544*c^16 + 346641065720009000378954983294*c^15 + 639520333054888837052043648112*c^14 + 957675960342270992241528178704*c^13 + 696402750970714831280062285793*c^12 + 1102408057754003899068126760036*c^11 + 767540362444860636247634715531*c^10 + 1149362134291872086981828566611*c^9 + 430243837953824360545080751371*c^8 + 789576238369354582328704492347*c^7 + 602440036890400798835137474014*c^6 + 5 80523431234345594424300815049*c^5 + 604254505049932046775583257110*c^4 + 105 6639807179138440960522156332*c^3 + 565071891011786154985459862809*c^2 + 2007 4844311373213928728633027*c + 370341892320446299776532835998]") error("domain error in ffcompomap: m domain does not contain codomain of [b, b^3 + (1137416257572846559662200662715*a^2 + 503912325036190431090267314273 *a + 558673802978212002533596733572)*b^2 + (633503932536656128571933348442*a ^2 + 1136773522417929415309364153946*a + 168613510166980621382925613526)*b + (633503932536656128571933348442*a^2 + 1136773522417929415309364153946*a + 1 68613510166980621382925613525)]") error("domain error in ffmap: m domain does not contain b^8 + b^7 + 12676506 00228229401496703205646*b^6 + 1267650600228229401496703205647*b^5 + 15*b^4 + 10*b^3 + 1267650600228229401496703205643*b^2 + 1267650600228229401496703205 650*b + 4") error("domain error in ffmap: m domain does not contain 46484092795487340755 616362656*c^17 + 1055644262063180547422327045544*c^16 + 34664106572000900037 8954983294*c^15 + 639520333054888837052043648112*c^14 + 95767596034227099224 1528178704*c^13 + 696402750970714831280062285793*c^12 + 11024080577540038990 68126760036*c^11 + 767540362444860636247634715531*c^10 + 1149362134291872086 981828566611*c^9 + 430243837953824360545080751371*c^8 + 78957623836935458232 8704492347*c^7 + 602440036890400798835137474014*c^6 + 5805234312343455944243 00815049*c^5 + 604254505049932046775583257110*c^4 + 105663980717913844096052 2156332*c^3 + 565071891011786154985459862809*c^2 + 2007484431137321392872863 3027*c + 370341892320446299776532835998") error("incorrect type in ffextend (t_POL).") ? ffinit(1,1) *** at top-level: ffinit(1,1) *** ^----------- *** ffinit: not a prime number in ffinit: 1. ? ffinit(4,2) *** at top-level: ffinit(4,2) *** ^----------- *** ffinit: not a prime number in ffinit: 4. ? ffinit(2^64,2) *** at top-level: ffinit(2^64,2) *** ^-------------- *** ffinit: not a prime number in ffinit: 18446744073709551616. ? ffgen(x^2+x+Mod(1,3)) *** at top-level: ffgen(x^2+x+Mod(1,3)) *** ^--------------------- *** ffgen: not an irreducible polynomial in ffgen: x^2 + x + 1. ? ffembed(ffgen([3,5],'b),ffgen([3,6],'a)); *** at top-level: ffembed(ffgen([3,5],'b),ffgen([3,6],'a)) *** ^---------------------------------------- *** ffembed: domain error in ffembed: b is not a subfield of a ? a=ffgen(3^3,'a);ffinvmap(ffextend(a,x^2+x+a)); *** at top-level: a=ffgen(3^3,'a);ffinvmap(ffextend(a,x^2+x+a)) *** ^----------------------------- *** ffinvmap: incorrect type in ffinvmap (t_VEC). ? fforder(ffgen(8)*0) *** at top-level: fforder(ffgen(8)*0) *** ^------------------- *** fforder: domain error in fforder: x = 0 ? print("Total time spent: ",gettime); Total time spent: 980 pari-2.17.2/src/test/32/print0000644000175000017500000000022314567450071014243 0ustar billbill1:2:3:4 0 0 1:2:3:40 0 [1, 0; 0, 1] 0 [1, 0; 0, 1]0 [1 0] [0 1] w 2 2 z z 2\*z 2*z 2 + 3\*z 2 + 3*z 2 + 3\*I 2 + 3*I 1 1 Total time spent: 0 pari-2.17.2/src/test/32/minmax0000644000175000017500000000171614676526175014422 0ustar billbill1: [1, 1, 0, 0, 1, 1] 2: [11, -3, 1, 4, 11, 3] 3: [11, -3, 1, 4, 11, 3] 4: [11, -3, 1, 4, 11, 3] 5: [11, -3, [1, 1], [2, 2], 11, 3] 6: [+oo, -oo, 1, 4, +oo, +oo] *** at top-level: vecmin([]) *** ^---------- *** vecmin: domain error in vecmin: empty argument = [] *** at top-level: vecmin(Mat()) *** ^------------- *** vecmin: domain error in vecmin: empty argument = [;] *** at top-level: vecmin(List()) *** ^-------------- *** vecmin: domain error in vecmin: empty argument = List([]) *** at top-level: vecmax([]) *** ^---------- *** vecmax: domain error in vecmax: empty argument = [] *** at top-level: vecmax(Mat()) *** ^------------- *** vecmax: domain error in vecmax: empty argument = [;] *** at top-level: vecmax(List()) *** ^-------------- *** vecmax: domain error in vecmax: empty argument = List([]) Total time spent: 0 pari-2.17.2/src/test/32/bnrL10000644000175000017500000000740414676526175014107 0ustar billbill[[1, 0.38224508584003564132935849918485739023 + 0.E-38*I], [1, 0.38224508584 003564132935849918485739023 + 0.E-38*I], [0, -3/2]] [[[1], 0.69082574035845153597174938200391860974 - 0.141771150359113754753792 96778414429232*I], [[3], 0.69082574035845153597174938200391860974 + 0.141771 15035911375475379296778414429232*I], [[2], 0.4586241066277198818606957964954 7270634]] [[[1], 0.86715515057683562588616895054751987122 - 0.645139937243558470804545 79289618230201*I], [[7], 0.86715515057683562588616895054751987122 + 0.645139 93724355847080454579289618230201*I], [[2], 0.6908257403584515359717493820039 1860974 - 0.14177115035911375475379296778414429232*I], [[6], 0.6908257403584 5153597174938200391860974 + 0.14177115035911375475379296778414429232*I], [[3 ], 0.74706478772303241588174336102451164904 - 0.3960165280615765170140247358 8976342836*I], [[5], 0.74706478772303241588174336102451164904 + 0.3960165280 6157651701402473588976342836*I], [[4], 0.45862410662771988186069579649547270 634]] [[[1, 0], 0.74706478772303241588174336102451164905 + 0.396016528061576517014 02473588976342836*I], [[7, 0], 0.74706478772303241588174336102451164905 - 0. 39601652806157651701402473588976342836*I], [[2, 0], 0.6908257403584515359717 4938200391860974 - 0.14177115035911375475379296778414429232*I], [[6, 0], 0.6 9082574035845153597174938200391860974 + 0.1417711503591137547537929677841442 9232*I], [[3, 0], 0.86715515057683562588616895054751987122 + 0.6451399372435 5847080454579289618230201*I], [[5, 0], 0.86715515057683562588616895054751987 122 - 0.64513993724355847080454579289618230201*I], [[4, 0], 0.45862410662771 988186069579649547270634], [[0, 1], 0.47485156314700469763174924587287075804 ], [[1, 1], 0.86715515057683562588616895054751987122 - 0.6451399372435584708 0454579289618230201*I], [[7, 1], 0.86715515057683562588616895054751987122 + 0.64513993724355847080454579289618230201*I], [[2, 1], 1.01932835944198700777 04818539447783577], [[6, 1], 1.0193283594419870077704818539447783577], [[3, 1], 0.74706478772303241588174336102451164905 - 0.396016528061576517014024735 88976342836*I], [[5, 1], 0.74706478772303241588174336102451164905 + 0.396016 52806157651701402473588976342836*I], [[4, 1], 2.2792875031056225486323963801 897796381]] [[[1, 0, 0], 0.83081832012833464173087318604481930961 - 0.514580721717982992 96449819908970897243*I], [[3, 0, 0], 0.8308183201283346417308731860448193096 1 + 0.51458072171798299296449819908970897243*I], [[2, 0, 0], 0.4261659362390 8292986022313898378274379], [[0, 1, 0], 1.5229130218886938349135426110563214 049], [[1, 1, 0], 0.83081832012833464173087318604481930961 - 0.5145807217179 8299296449819908970897243*I], [[3, 1, 0], 0.83081832012833464173087318604481 930961 + 0.51458072171798299296449819908970897243*I], [[2, 1, 0], 1.01527534 79257958899423617407042142699], [[0, 0, 1], 0.690934605743077428616891036337 62202463], [[1, 0, 1], 0.84199935117030392785882419071906079523 - 0.22082664 344725718899163157856471416929*I], [[3, 0, 1], 0.841999351170303927858824190 71906079523 + 0.22082664344725718899163157856471416929*I], [[2, 0, 1], 0.979 35756850988202871462966877232278323], [[0, 1, 1], 1.522913021888693834913542 6110563214049], [[1, 1, 1], 0.84199935117030392785882419071906079523 - 0.220 82664344725718899163157856471416929*I], [[3, 1, 1], 0.8419993511703039278588 2419071906079523 + 0.22082664344725718899163157856471416929*I], [[2, 1, 1], 0.76145651094434691745677130552816070246]] [0.90088685686467725961014440212013594076, 0.9008868568646772596101444021201 3594076, 0.40635806401553767970961532642051751587, 0.40635806401553767970961 532642051751587] [0, 0.6000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000 + 0.20000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000*I] Total time spent: 219 pari-2.17.2/src/test/32/rfrac0000644000175000017500000000042614567450071014211 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 + O(3^5))*x + (1 + O(3^5)))/((1 + O(3^5))*x + (2 + O(3^5))) [1, 0] -1 0 0.E-38/x "t_POL" "t_POL" Mod(0, 2) Total time spent: 3282 pari-2.17.2/src/test/32/ellnf0000644000175000017500000002071314760301046014205 0ustar billbill *** Warning: new stack size = 16000000 (15.259 Mbytes). 1 [Mod(5/2*t^2 - 3/8*t + 7/4, t^3 - 2), Mod(3/8*t^2 - 67/16*t - 123/16, t^3 - 2)] [Mod(21112/25281*t^2 + 33953/25281*t + 54736/25281, t^3 - 2), Mod(2829824/13 39893*t^2 + 5014079/1339893*t + 5473088/1339893, t^3 - 2)] [Mod(-t, t^3 - 2), Mod(t, t^3 - 2)] [] 3*x^4 + Mod(6*t + 6, t^3 - 2)*x^2 + Mod(-12*t - 24, t^3 - 2)*x + Mod(-t^2 - 2*t - 1, t^3 - 2) [0, 0, 0, Mod(-3*t^2 + 5184*t, t^3 - 2), Mod(-6912*t^2 + 5971968*t + 4, t^3 - 2)] [] [Mod(0, 5), Mod(0, 5), Mod(0, 5), Mod(4, 5), Mod(0, 5), Mod(0, 5), Mod(3, 5) , Mod(0, 5), Mod(4, 5), Mod(3, 5), Mod(0, 5), Mod(4, 5), Mod(3, 5), Vecsmall ([3]), [5, [4, 0, [1, 0, 0, 0]]], [0, 0, 0, 0]] [0, 1, [1/289, 0, 0, 0], 1] -1.0176096077975699654301625084525458834 [-1, -4, 6] [6, 18, 12] [[6], [18], [6, 2]] 6 [1, 0, 0, -2, -1, 0, 0, 0, -2, 0, 0, 0, -3, 0, 0, 4, 6, 0, 0, 2] [1, 0, 0, -2, -1, 0, 0, 0, -2, 0, 0, 0, -3, 0, 0, 4, 6, 0, 0, 2] [[65, 18; 0, 1], [1, 0, 0, 0], 2, [[5, [-2, 1]~, 1, 1, [2, -1; 1, 2]], 1; [1 3, [5, 1]~, 1, 1, [-5, -1; 1, -5]], 1], [[1, 5, [1, 0, 0, 0], 1], [1, 6, [1, 0, 0, 0], 2]]] [[65, 18; 0, 1], [1/17, 0, 0, 0], 2, [[5, [-2, 1]~, 1, 1, [2, -1; 1, 2]], 1; [13, [5, 1]~, 1, 1, [-5, -1; 1, -5]], 1], [[1, 5, [1, 0, 0, 0], 1], [1, 6, [1, 0, 0, 0], 2]]] [[65, 18; 0, 1], [1, 0, 0, 0], 2, [[5, [-2, 1]~, 1, 1, [2, -1; 1, 2]], 1; [1 3, [5, 1]~, 1, 1, [-5, -1; 1, -5]], 1], [[1, 5, [1, 0, 0, 0], 1], [1, 6, [1, 0, 0, 0], 2]]] [-1, [5]] [0, [10]] [-4, [30]] [5, [5], [[0, x + 1]]] [8, [8], [[x + 2, 1]]] [209844281664738990, [209844281664738990]] [Mod(4*a + 29580, a^2 - 870), Mod(-56550*a - 218426550, a^2 - 870), Mod(5220 *a + 24220800, a^2 - 870), Mod(433703700*a - 321905785500, a^2 - 870), Mod(3 0478152852000*a + 1290691561617000, a^2 - 870)] [Mod(4*a + 29580, a^2 - 870), Mod(-56550*a - 218426550, a^2 - 870), Mod(5220 *a + 24220800, a^2 - 870), Mod(433703700*a - 321905785500, a^2 - 870), Mod(3 0478152852000*a + 1290691561617000, a^2 - 870)] [1/20880, 0, 0, 0] [Mod(0, a^2 - 870), Mod(0, a^2 - 870), Mod(0, a^2 - 870), Mod(a, a^2 - 870), Mod(1, a^2 - 870)] [Mod(1/20880*a, a^2 - 870), Mod(-1/501120*a - 41/167040, a^2 - 870), Mod(-1/ 10440*a - 17/24, a^2 - 870), Mod(5011/3487795200*a + 2077/12026880, a^2 - 87 0)] [0, 1]~ [1/30, 0, 0, 0] 1 1:12.829972218867343164701716427521360348 2:12.829972218867343164701716427521360348 3:12.829972218867343164701716427521360348 [1, 0, 0, 0] [[64000001644800020229280152976800751644426376663403572812780612976355750337 16572028, 0; 0, 640000016448000202292801529768007516444263766634035728127806 1297635575033716572028], [1, 0, 0, 0], 6, [[2, [0, 1]~, 2, 1, [0, 870; 1, 0] ], 4; [10000000019, [10000000019, 0]~, 1, 2, 1], 2; [20000000089, [200000000 89, 0]~, 1, 2, 1], 2; [40000000520000003750000013929460019555447, [400000005 20000003750000013929460019555447, 0]~, 1, 2, 1], 1], [[4, -1, [1, 1, 1, Mod( 1/435*a + 1, a^2 - 870)], 1], [2, -4, [1, 0, 0, 0], 3], [2, -3, [1, 0, 0, 0] , 2], [1, 5, [1, 0, 0, 0], 1]]] 39.851140182843701620954357795663570393 [[16000000182400000866400002194880003127714802377096080752773084, 0; 0, 1600 0000182400000866400002194880003127714802377096080752773084], [1, 0, 0, 0], 3 , [[2, [0, 1]~, 2, 1, [0, 870; 1, 0]], 4; [7, [-3, 1]~, 1, 1, [3, 870; 1, 3] ], 1; [7, [3, 1]~, 1, 1, [-3, 870; 1, -3]], 1; [103, [-47, 1]~, 1, 1, [47, 8 70; 1, 47]], 1; [103, [47, 1]~, 1, 1, [-47, 870; 1, -47]], 1; [1993, [-685, 1]~, 1, 1, [685, 870; 1, 685]], 1; [1993, [685, 1]~, 1, 1, [-685, 870; 1, -6 85]], 1; [10000000019, [10000000019, 0]~, 1, 2, 1], 2; [27836679629744327661 656297107448887, [27836679629744327661656297107448887, 0]~, 1, 2, 1], 1], [[ 4, -1, [1, 1, 1, Mod(1/435*a + 1, a^2 - 870)], 1], [1, 5, [1, 0, 0, 0], 1], [1, 5, [1, 0, 0, 0], 1], [1, 5, [1, 0, 0, 0], 1], [1, 5, [1, 0, 0, 0], 1], [ 1, 5, [1, 0, 0, 0], 1], [1, 5, [1, 0, 0, 0], 1], [2, -4, [1, 0, 0, 0], 3], [ 1, 5, [1, 0, 0, 0], 1]]] [1]~ [1]~ [1, [1, 0, 0, 0], 1, matrix(0,2), []] [[28, 0, 20; 0, 28, 20; 0, 0, 4], [1, 0, 0, 0], 6, [[2, [2, 0, 0]~, 1, 3, 1] , 2; [7, [1, -3, 0]~, 3, 1, [3, 1, 1; 3, 8, 1; 2, 3, 3]], 2], [[2, -4, [1, M od(1/8*z^2 + 3/4*z + 2, z^3 - 4*z^2 - 32*z + 64), Mod(1/16*z^2 + 1/4*z, z^3 - 4*z^2 - 32*z + 64), Mod(7/8*z^2 + 3*z - 4, z^3 - 4*z^2 - 32*z + 64)], 3], [2, -1, [1, 0, 0, 0], 2]]] [Mod(1, a^2 - 17), Mod(2, a^2 - 17), Mod(1, a^2 - 17), Mod(-66585651*a - 274 539700, a^2 - 17), Mod(-600624098797*a - 2476436600713, a^2 - 17)] [Mod(4*a - 32, a^2 - 17), Mod(-192*a + 972, a^2 - 17), Mod(2*a - 16, a^2 - 1 7), Mod(6688*a - 29440, a^2 - 17)] [Mod(a, a^2 - 7), Mod(0, a^2 - 7), Mod(0, a^2 - 7), Mod(-9, a^2 - 7), Mod(0, a^2 - 7)] [2, -9, Mod(a, a^2 - 7), 0] 2268 2268 54 54 1 1 [9, [3, 3], [[Mod(-2, a^2 - a + 1), Mod(-3*a + 2, a^2 - a + 1)], [Mod(0, a^2 - a + 1), Mod(-a + 2, a^2 - a + 1)]]] [9, [3, 3], [[Mod(-9/4, a^2 - a + 1), Mod(-3*a + 1, a^2 - a + 1)], [Mod(-1/4 , a^2 - a + 1), Mod(-a + 2, a^2 - a + 1)]]] 1.3211372891561117704694923724477608437 1.3211372891561117704694923724477608437 [[3.2454018605082579620032350562420879904 + 1.111397817128820959029052707850 2348351*I, 1.6668632098170830019533312582971884208 - 0.486801726858514320058 78432460464226233*I]] [[3.2454018605082579620032350562420879904 + 1.111397817128820959029052707850 2348351*I, 1.6668632098170830019533312582971884208 - 0.486801726858514320058 78432460464226233*I]] [[3.3428093839915903612041140523628625748 - 0.475484699340869907792393249264 58939281*I, 1.8377117333570711477796051427229973887 + 0.56107170810617604791 234131325616570861*I]] [[3.3428093839915903612041140523628625748 - 0.475484699340869907792393249264 58939281*I, 1.8377117333570711477796051427229973887 + 0.56107170810617604791 234131325616570861*I]] [3.4324153628883011196857987711414818098] [3.4324153628883011196857987711414818098] [[1.4331498327481794699384519990689978958 E-7, -8.90022802078150157827725183 62365500525 E-8*I], [0.14948961573271587735193776533155518448 - 0.0364920854 87651217049327378480123927290*I, 0.025252400424922004835631005650622494292 - 0.077154497013473286414108150293274820223*I], [71131.7121340703744044981170 95975388071 + 31444.727244680220552887076625190441805*I, 19527.9820807200880 34284003590898052213 - 44174.617547686477264962272970191397890*I]] 81 2 1 [3, [3], [[Mod(75, a^2 - a - 22), Mod(-53*a + 276, a^2 - a - 22)]]] 0.029243259302535776270985513029724899123 0.029243259302535776270985513029724899123 0.029243259302535776270985513029724899123 [[0.36275979223366389123527228531236021016, 0.181379896116831945617636142656 18010508 - 0.98792397441408998992096074875409751608*I], [3.42226903540115887 19775751832202902106, 1.7111345177005794359887875916101451053 - 0.1047197318 4863928069787984196947537734*I]] [[9.0690068978198926646497340170387502852, 4.5345034489099463323248670085193 751426 - 7.3776203664257126727668408543261959548*I], [-196.67027839726644769 316107917450672666, -98.335139198633223846580539587253363331 + 7.85398337930 14079898062379028921755190*I]] [0.35837909570111076671922166110255577349, 0.3583790957011107667192216611025 5577349] 89 4 1 [10, [10], [[Mod(a^2, a^3 - a^2 + 1), Mod(-2*a^2 + 1, a^3 - a^2 + 1)]]] 0.33753547062081148560344962283967451355 [[3.5491769254598924808129220481653238934, -2.542655659111084982919736837317 6365643*I], [1.9499083977009059175943781181149776030 + 2.8338954531694537916 413166973195484122*I, 3.3837615464515224781027253345320644787 - 0.9298685032 8561627019201162339975284811*I]] [[0.67178899867737769984191766676172801075, 1.289047377476443975073193849195 0519406*I], [0.59569675561968713991027058840738833243 - 0.784496667533226302 75597445878594696512*I, 0.94830798409984778856147508826172748052 + 0.1986300 0529303555671904142603584000601*I]] [9.0243347947070770520143614245496848016, 11.4023848644128046507836413961968 47706] [4 0] [0 4] [1 0] [0 1] 10351 [27 0] [ 0 27] 0 2.6776858460184521884180352812357212922 -1 2.4789169415611595631185019889765914992 -1 2.7983467075796708218369484107296525132 -1 0.94644710225720189761360064296904262845 1.1306942438544073283221551692300185759 1 1.9118646495040059117224489068629589287 2.3989895152878390668263655479635937156 1 1.1553619177287290907122191262256779900 1.8108719765738961774239981105279304803 1 0.21953076079603813973615927742358668806 -1 0.047510692468775579593867285193171421984 -1 0.35764851040087134693652331655969825373 -1 0.092936445769006934770949560984704427787 -1 0 1 -1 -127 1 *** at top-level: ellinit([Mod(-5*a+12,a^2-a-1),Mod(-10,a^2-a-1) *** ^---------------------------------------------- *** ellinit: inconsistent moduli in ellinit: a^2 - a - 1 != a^2 - 11*a - 1 Total time spent: 2144 pari-2.17.2/src/test/32/pow0000644000175000017500000000602014676526175013727 0ustar billbillMod(1, 3) Mod(1, 3) 1 [;] [1] Mod(0, 1) Mod(1, 3) Qfb(1, 2, -1) Qfb(-1, 2, 1) [Qfb(1, 2, -1), 0.E-38] [Qfb(-1, 2, 1), 1.0000000000000000000000000000000000000] [Qfb(1, 2, -1), 2.0000000000000000000000000000000000000] Vecsmall([1, 2, 3]) Vecsmall([3, 2, 1]) O(2) *** at top-level: O(2)^-2 *** ^--- *** _^s: impossible inverse in powps: O(2). 4 9/4 1/2*I 0.25000000000000000000000000000000000000 + 0.4330127018922193233818615853764 6809174*I 2*I 1.0000000000000000000000000000000000000 + 1.73205080756887729352744634150587 23669*I 1 1 -1 *** at top-level: 2^n *** ^-- *** _^_: overflow in lg(). *** at top-level: (1/2)^n *** ^-- *** _^_: overflow in lg(). Qfb(2, 0, -1) Mod(x^2, x^6 + x^5 + x^4 + x^3 + x^2 + x + 1) O(x^0) x + O(x^4) [8.0000000000000000000000000000000000000, 27.0000000000000000000000000000000 00000] [8.0000000000000000000000000000000000000, 27.0000000000000000000000000000000 00000]~ [8.0000000000000000000000000000000000000] O(x^0) 0.E-19 Mod(2, 3) Mod(4, 5) *** at top-level: Mod(2,3)^(1/2) *** ^------ *** _^_: not an n-th power residue in gpow: Mod(2, 3). Mod(2, 3) *** at top-level: Mod(1,4)^(1/2) *** ^------ *** _^_: not a prime number in gpow: 4. 3 + 7 + 2*7^2 + 6*7^3 + 7^4 + O(7^5) *** at top-level: (3+O(7^5))^(1/2) *** ^------ *** _^_: not an n-th power residue in gpow: 3 + O(7^5). 1 + 3*7 + 5*7^2 + O(7^3) 1 + O(2) 1 + O(2) *** at top-level: sqrt(Mod(2,4)) *** ^-------------- *** sqrt: not a prime number in Fl_sqrt [modulus]: 4. [[0, 0], [1.0000000000000000000000000000000000000, 1.00000000000000000000000 00000000000000]] [[0, 0]~, [1.0000000000000000000000000000000000000, 1.0000000000000000000000 000000000000000]~] [[0, 0; 0, 0], [1.0000000000000000000000000000000000000, 1.00000000000000000 00000000000000000000; 1.0000000000000000000000000000000000000, 1.00000000000 00000000000000000000000000]] Mod(0, 1) 0.49999999965342640984014059874318224111 [4.0000000000000000000000000000000000000]~ 1 + 2*3 + 2*3^2 + 2*3^3 + O(3^4) I -I [Mod(1, 11), Mod(2, 11), Mod(4, 11), Mod(8, 11), Mod(5, 11), Mod(10, 11), Mo d(9, 11), Mod(7, 11), Mod(3, 11), Mod(6, 11), Mod(1, 11)] [1, 3.1415926535897932384626433832795028842, 9.86960440108935861883449099987 61511353, 31.006276680299820175476315067101395202, 97.4090910340024372364403 32688705111249, 306.01968478528145326274131004343560648, 961.389193575304437 03021944365241989886, 3020.2932277767920675142064930720418319] [2, 6, 18, 54, 162, 486] [] [1] *** at top-level: [1]^2 *** ^-- *** sqr: forbidden multiplication t_VEC (1 elts) * t_VEC (1 elts). *** at top-level: [1]^1 *** ^-- *** _^s: incorrect type in gpow (t_VEC). *** at top-level: [1]^0 *** ^-- *** _^s: incorrect type in gpow (t_VEC). *** at top-level: List()^1 *** ^-- *** _^s: incorrect type in gpow (t_LIST). Total time spent: 1 pari-2.17.2/src/test/32/det0000644000175000017500000000071014567450071013664 0ustar billbill2645450238786014260762195151127593140777050579745670159192807728014078750989 2064506631325 2645450238786014260762195151127593140777050579745670159192807728014078750989 2064506631325 2645450238786014260762195151127593140777050579745670159192807728014078750989 2064506631325 2645450238786014260762195151127593140777050579745670159192807728014078750989 2064506631325 ((-y + 1)*x^2 + (y^2 - 1)*x + (-y^2 + y))/(y*x) 1235506763578759280760 Total time spent: 89 pari-2.17.2/src/test/32/lfun0000644000175000017500000004130414676526175014072 0ustar billbill *** Warning: new stack size = 16000000 (15.259 Mbytes). [688, 201] 371 1:-0.33333333333333333333333333333333333333 2:0 3:19.233333333333333333333333333333333333 4:0 5:-52083.825396825396825396825396825396826 6:0 7:1357464617.6166666666666666666666666667 8:0 9:-179843066266647.30303030303030303030303 10:0 1:0.33063066328223158676532076242927218282 2:0.65737655586117037348678949547515310666 3:0.83891994700224752688923802043332022788 4:0.92491465281539828015714800144878813258 5:0.96452286982609889100272493876597162334 6:0.98297145977262401505413785166918148202 7:0.99172249343786354566494479026158994548 8:0.99593957135944435652980046461493771761 9:0.99799568488420794431041938185291613541 10:0.99900642043725868624437550798777108358 [441, 365] 0.65054897266021897189117007748600082035 + 0.3797872612825021141546006883142 4264193*I 1.0197948617829165568371172783583479161 + 0.01753787982678033377468853770967 0993444*x - 0.30423568247445724453438996641387297306*x^2 + O(x^3) -1.0000000000000000000000000000000000000*x^-2 + 0.07281584548367672486058637 5874901319146 + O(x) 2.0000000000000000000000000000000000000*x^-3 + O(x^0) -0.93754825431584375370257409456786497789 + 1.989280234298901023420858687421 5163815*x^2 - 3.0000729014215224328219706087689241919*x^4 + O(x^6) 1.9892802342989010234208586874215163815 - 6.00014580284304486564394121753784 83837*x^2 + 12.000743196868230785490141705105642696*x^4 + O(x^6) -2.15800131645680564826065544584339217*x - 2.1019724905481294182200201711445 8153*x^2 - 0.529685033171161239709892386112460416*x^3 - 4.738573771869464928 37424643722475375*x^4 - 3.21952194221326633226406870366478753*x^5 + O(x^6) -2.15800131645680564826065544584339217 - 4.203944981096258836440040342289163 06*x - 1.58905509951348371912967715833738125*x^2 - 18.9542950874778597134969 857488990150*x^3 - 16.0976097110663316613203435183239376*x^4 - 21.4034953961 473607584436264229933443*x^5 + O(x^6) *** lfuncreate: Warning: nonmonic polynomial. Result of the form [nf,c]. 1.1179816853477385178979715038469170225 [1, [0, 1], 1, 5] 1.0000000000000000000000000000000000000*x^-2 + 1.154431329803065721213024180 1648048621*x^-1 + O(x^0) 0.61685027506808491367715568749225944596*x^-2 + 1.01511996319472488016374193 63106928091*x^-1 + O(x^0) 1.0000000000000000000000000000000000000*x^-1 + O(x^0) 0.72399875382322394120054853672842760345*x^-1 + O(x^0) 246.96037648704266640450758953126840719 246.96037648704266640450758953126840719 -2.0063564559085848512101000267299604382 1.00000000000000000000000000000000000000000000000000000*x^-1 + O(x^0) 4.59057737496905265921181053582421504989219703475223909 - 3.1894012475791441 3416113592649224080101489871517943905*I 4.59057737496905265921181053582421504989219703475223909 - 3.1894012475791441 3416113592649224080101489871517943905*I -0.918938533204672741780329736405617639861397473637783413 -0.500000000000000000000000000000000000000000000000000000 - 0.91893853320467 2741780329736405617639861397473637783413*x - 1.00317822795429242560505001336 498021909949745508045994*x^2 - 1.0007851944770424079601768022277292142436346 1138266336*x^3 - 0.999879299500571164957800813655875235912130830621737643*x^ 4 - 1.00000194089632045603779988198163183123243380977058752*x^5 - 1.00000130 114601395962431150487297972022050535126287236*x^6 - 0.9999998313841736107799 30217058015406504287266515799803*x^7 - 1.00000000576467597994939441606374165 964458982012538704*x^8 - 1.0000000009110164892314165709218674221759786407713 7178*x^9 - 0.999999999850299240580988626479279942923194971996409274*x^10 - 1 .00000000000940689566566617690964783960902526136635510*x^11 - 1.000000000000 04092582630415831547636589331713210684094*x^12 - 0.9999999999999346009519410 89847743543530991534013594552*x^13 - 1.0000000000000065439687498919193731717 8549879786061140*x^14 - 0.99999999999999969875751286332132050502895615410010 3971*x^15 + O(x^16) [14.1347251417346937904572519835624702707842571156992432] [14.1347251417346937904572519835624702707842571156992432] [14.1347251417346937904572519835624702707842571156992432, 21.022039638771554 9926284795938969027773343405249027818, 25.0108575801456887632137909925628218 186595496725579967] [-14.1347251417346937904572519835624702707842571156992432, 14.13472514173469 37904572519835624702707842571156992432] 1.64493406684822643647241516664602518921894990120679844 0.E-57 0.E-57 + 0.E-57*I 1.08642943411465667904756436036751417209703758075237284 + 0.5814393878814690 50796952624011344061904995756625692378*I [0, 0, 0, 2.05247285847993976968922276314372344628278531045671612, 3.2624435 5597875746635580364385504003255536470999182746, 4.47055151331009795091782387 950075730310480986858048883, 4.754431515963405864151635593968863195363908404 79441418, 6.01192275298639519014642522248844223795049139992228727, 6.6225046 1340770678139848771792480632419572890704427238, 7.34281497953964814691434021 056204069773310740821664643, 7.706794648113253444646515057103424471764811099 99985019, 8.47680194262350037741231085806780599121287634323800435, 9.3821789 1117193954907921307162820430752270478042951828, 10.2034632426606570779547130 495062951265229955572895373, 10.49585360108396305215840613479582203063682050 06846644, 11.0334412351426994365984023609574093781284435634924994, 11.686948 0908853117520467071200624951073279924875106987, 12.2872289038249291759599430 438941349597652754843369265, 12.97272258207285515566187612538460946756424085 17308260, 13.1516366031527298638457029894321422485191693385770427, 14.941560 3295484662604761276988412262910822900346167548, 15.5153470765360805167423831 611671659141843411546141532, 15.89479293723708546650440371159237688468390847 47857619, 16.4404849010636539204980820326139388267735297782205584, 16.643129 4008115360154817747496027260477191373350164541, 17.4115213614943714989213104 465137362699445863767902588, 18.07306090799612896897975201392338100448825380 23845260, 18.5597395171897437816282533768115505690861265963563642, 19.031282 9499859520841448378360117311970316861384451388, 19.4973491720207997554477267 895497007883582413152228914, 19.97454966422489875085184165206182695782541275 69183433] [0, 0, 0, 2.05247285847993976968922276314372344628278531045671612] [-2.05247285847993976968922276314372344628278531045671612] [2.05247285847993976968922276314372344628278531045671612] [-2.05247285847993976968922276314372344628278531045671612, 0, 0, 0, 2.052472 85847993976968922276314372344628278531045671612] [[1, 25/48, 5/12, 25/48, 1], [1620/691, 1, 9/14, 9/14, 1, 1620/691], 0.00741 542092989613058900642774590022872478364665364735552, 0.005083512108393286860 49429013743874732263404552491812001] [[1, 10/21, 5/18, 5/24, 5/24, 5/18, 10/21, 1], 1.130264319203497485238782258 42414006077270696235995422] 2.99829512187626747049837118353413149411569186966170254 - 0.0193445925339772 841452384712897772364256641021849529530*I 2.99829512187626747049837118353413149411569186966170254 - 0.0193445925339772 841452384712897772364256641021849529530*I 2.99829512187626747049837118353413149411569186966170254 - 0.0193445925339772 841452384712897772364256641021849529530*I 997 0.177455993247329238699202652214156646711252940222106816 [0.201954787411261026528684690029341772176043691915844168, 0] 0.97906557276284488612288786018111182197046845456987142630213045542848319630 07533965134607035430513178949168014263879 -189 -189 -191 -191 1.97848884347766873530779261857994032392637450942515837 + 0.0609239674747025 097814469640574145327771779577841455860*I 1.30351764627548230978276542627689204122406359796082825 - 0.0344294367015510 576149187463564582588308663091234952457*I *** lfunzeros: Warning: lfuninit: insufficient initialization. [1.76524528537434114004961734014687322242921043467451418, 2.9001948143989959 3853720458684428845871417117642020713, 4.80912824766302432457595530706768541 000593962088321171, 6.05385187632329316110398877826905838861120455439163616, 7.03104718941202758893296505461247399284219178321418886, 8.0611446646958964 5370426023193369987671312157987402508, 10.4138094136894319447888631663520554 801158568510225716, 11.5429326942529531377771432204175144625871573059960913, 12.2634871694527156193695773489858842238381199251462399, 13.523913779157256 8249199285782562251878941627912318795, 14.6267210920659865269412411659252020 114704423226886093, 15.2588679023455946128303693291132825994525235298638847, 17.1471665979791684669746630513532371198945899053737963, 17.924261776515709 3404867459600570383531919623979762348, 19.2057886412953906115542482837931510 878888441286200350] -189 1.97848884347766873530779261857994032392637450942515837 + 0.0609239674747025 097814469640574145327771779577841455860*I -191 x^3 - x - 1 Curve y^2+(x^3+x^2+1)*y = x^2+x -58 Curve y^2+(x^3+1)*y = x^2+x Curve y^2+(x^2+x)*y = x^6+3*x^5+6*x^4+7*x^3+6*x^2+3*x+1 *** lfungenus2: Warning: unknown valuation of conductor at 2. -58 Curve y^2=x^5 + x -142 [0, 0, -1] 2.1541265970381460760215439978358922308 Curve y^2=x^5 + 1 -139 [0, 0, 1] 1.0314071041733177562983179141216861078 *** lfungenus2: Warning: unknown valuation of conductor at 2. [[Vecsmall([15]), [12*x^5 + 12, [[2, 1], [3, 1], [5, 1]]]], 0, [0, 0, 1, 1], 2, 50625, 0] Elliptic curves over number fields -136 1.3894051168795718563026565631765059398 -135 1.7561367497808959311966399691482152395 -135 2.7749792286446646504296418681816946545 -132 4.4552267729872870508917049939747968543 -140 8.2306621809152393859013012963081422203 -2 -22 Grossencharacter -139 1.0000000000000000000000000000000000000 tensor product realbitprecision = 64 significant bits (19 decimal digits displayed) -65 1.774264741132682166 check all formats -195 -195 -195 -195 [1, -2, -3, 2, -2, 6, -1, 0, 6, 4] [1, -1, 1, 1, -1, -1, -1, -1, 1, 1] [1, -1, 0, 1, 1, 0, 0, -1, 0, -1] [1, 1, [0]] [1, 1, [0]] [496, 2, [0, 1]] [1, 1, [0]] -191 1/240 -1/504 1/480 -1/264 691/65520 -1/24 3617/16320 -43867/28728 1.00000000000000000000000000000000000000000000000000000 -1.07637023438345995368832251445133621778701931610742695 0.661475187921069742727520633979626889791045796292710056 0.146374542091265989413000913274996215907067384190621201 0.934830053608610054115427799558087197935200286533499400 0.661475187921069742727520633979626889791045796292710056 [0] -190 -189 -57 0 0.953260474794660686250509013566383496014986229687151072 + 16.29021572039039 07929631726451921643054665845864660536*I 0 1.00000000000000000000000000000000000000000000000000000 -183 1.00000000000000000000000000000000000000000000000000000 -177 zeta(s-a) -189 1.00000000000000000000000000000000000000000000000000000*x^-1 + O(x^0) 1.64493406684822643647241516664602518921894990120679844 -189 -0.500000000000000000000000000000000000000000000000000000 1.00000000000000000000000000000000000000000000000000000*x^-1 + O(x^0) zeta(s)*zeta(s-a) -185 1.64493406684822643647241516664602518921894990120679844*x^-1 + O(x^0) 1.97730435029729611819708544148512557208215146666013421 -186 -0.822467033424113218236207583323012594609474950603399219 1.20205690315959428539973816151144999076498629234049888*x^-1 + O(x^0) *** lfunconductor: Warning: #an = 598 < 1519, results may be imprecise. 61 1.01542133944024439298806668944681826497337332941038810 [[147, 202], [147, 202]] -189 [[6, 195], [11, 195]] 1 [1171561, 3339] 1 4 857 120 [8, 2108] [] [[[1, 0.54657288114990636157071248041210027618*x^-1 + O(x^0)]], [[1, 6.64934 60830715850476062965515423576672*x^-1 + O(x^0)], [0, -6.64934608307158504760 62965515423576672*x^-1 + O(x^0)]]~, 1] 1 5077 725.0000000000000000 [725, -52] 24217.00000000000000 28614069.00000000000 -64 -57 [1, 0, 1, 0, 1, 0, 2, 0, -2, 0] [1, 1 + 1.732050807568877294*I, 1/2 - 0.8660254037844386468*I, -1 + 1.732050 807568877294*I, -1/2 - 0.8660254037844386468*I, 2, 0, 0, 1 + 1.7320508075688 77294*I, 1 - 1.732050807568877294*I] [1, -1 - 1.732050807568877294*I, 0.5000000000000000001 + 0.86602540378443864 68*I, -1.000000000000000000 + 1.732050807568877294*I, -1, 1.0000000000000000 00 - 1.732050807568877294*I, -1 + 1.732050807568877294*I, 0, 0.9999999999999 999999 - 1.732050807568877294*I, 1 + 1.732050807568877294*I] 1 [6, 186] [[5, 124], [11, 125], [12, 125]] 1.000000000000000000 0.83214280825734611779852282418300471522 + 0.0378612661512960987252330268197 96281464*I 0.83214280825734611779852282418300471522 + 0.0378612661512960987252330268197 96281464*I -125 [1, -127] 1.6449340668482264364724151666460251892 1:-56 2:-35 3:-43 4:-31 5:-38 6:-25 7:-22 0 *** lfun: Warning: #an = 1 < 5, results may be imprecise. 1.6449321944727952165464885195862083681 0.97075234252284168437606085418663108405 + 0.0794201340278726639136259197680 22884149*I -125 -123 -122 -147 -124 -125 O(x) O(x^2) -0.50000000000000000000000000000000000000 O(x^2) [0.90384905518988545678200390170972794465 - 2.372435185361247117269703583348 5504030*I, 2.1076105368263265781937945304702732642 + 2.778690871419041003781 6785866162988408*I] 1.3957117832136846124125242709765990227 + 0.19841375090717971815217149623689 183815*I [1.3957117832136846124125242709765990227 + 0.1984137509071797181521714962368 9183815*I] [0.98840426632758622164719972283433390539, 0.9884042663275862216471997228343 3390539] 0 *** at top-level: lfuntheta(1,0) *** ^-------------- *** lfuntheta: domain error in lfunthetainit: t = 0 *** at top-level: lfunhardy(1,I) *** ^-------------- *** lfunhardy: incorrect type in lfunhardy (t_COMPLEX). *** at top-level: lfun(1,2,-1) *** ^------------ *** lfun: domain error in lfun: D <= 0 *** at top-level: lfunan(lfuncreate([1,0,[0],1,1,1,1]),10) *** ^---------------------------------------- *** lfunan: incorrect type in vecan_closure (t_INT). *** at top-level: ...t(x^2+1);G=galoisinit(N);lfunartin(N,G,[1]~,2) *** ^--------------------- *** lfunartin: inconsistent dimensions in lfunartin. *** at top-level: ...t(x^2+1);G=galoisinit(N);lfunartin(N,G,[1,1,1] *** ^--------------------- *** lfunartin: inconsistent dimensions in lfunartin. *** at top-level: localbitprec(16);lfun(Lt,12) *** ^----------- *** lfun: incorrect type in vecan_closure (t_INT). *** at top-level: lfun(L,1) *** ^--------- *** lfun: incorrect type in direuler [bad primes] (t_VEC). *** at top-level: lfunzeros(1,[3,1]) *** ^------------------ *** lfunzeros: incorrect type in lfunzeros (t_VEC). *** at top-level: lfuncreate([errbnr,[[1],[2]]]) *** ^------------------------------ *** lfuncreate: incorrect type in lfuncreate [different conductors] (t_VEC). *** at top-level: lfuncreate([errG,[[1],[2]]]) *** ^---------------------------- *** lfuncreate: incorrect type in lfunchiZ (t_VEC). *** at top-level: lfuncreate([errG,[[1,8]~,[1,7]~]]) *** ^---------------------------------- *** lfuncreate: incorrect type in lfuncreate [different conductors] (t_VEC). *** at top-level: lfuncreate([errG,[[1,8]~,[0,1]~]]) *** ^---------------------------------- *** lfuncreate: incorrect type in lfuncreate [different conductors] (t_VEC). *** at top-level: ...z)->1,1],0,[0],1,1,1,1]);lfunan(L,5) *** ^----------- *** lfunan: incorrect type in vecan_closure (t_VEC). *** at top-level: ...->1,[1]],0,[0],1,1,1,1]);lfunan(L,5) *** ^----------- *** lfunan: incorrect type in vecan_closure [wrong arity] (t_CLOSURE). *** at top-level: ...->1,[1]],0,[0],1,1,1,1]);lfunan(L,5) *** ^----------- *** lfunan: incorrect type in vecan_closure (t_INT). *** at top-level: ...1,[2,3]],0,[0],1,1,1,1]);lfunan(L,5) *** ^----------- *** lfunan: incorrect type in direuler [bad primes] (t_INT). *** at top-level: ...[[2,3]]],0,[0],1,1,1,1]);lfunan(L,5) *** ^----------- *** lfunan: domain error in direuler: constant term != 1 *** at top-level: ...["",3]]],0,[0],1,1,1,1]);lfunan(L,5) *** ^----------- *** lfunan: incorrect type in gtou [integer >=0 expected] (t_STR). *** at top-level: ...[2,""]]],0,[0],1,1,1,1]);lfunan(L,5) *** ^----------- *** lfunan: incorrect type in direuler (t_STR). *** at top-level: lfun([[],[""]],1) *** ^----------------- *** lfun: incorrect type in lfunmisc_to_ldata (t_VEC). *** at top-level: lfuneuler(x^2+1,Pi) *** ^------------------- *** lfuneuler: incorrect type in lfuneuler (t_REAL). *** at top-level: lfunthetacost(polcyclo(43)) *** ^--------------------------- *** lfunthetacost: overflow in lfunthetacost. *** at top-level: lfuncheckfeq(1,I) *** ^----------------- *** lfuncheckfeq: domain error in lfunthetaneed: arg t > 0.7853981633974482790 Total time spent: 5900 pari-2.17.2/src/test/32/arith0000644000175000017500000000004414557721031014213 0ustar billbill0 4162330905307 Total time spent: 4 pari-2.17.2/src/test/32/printf0000644000175000017500000003003514676526175014427 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 argument to format\n") *** ^--------------------------------------- *** printf: invalid conversion or specification m in format `%missing argument to format '. *** at top-level: printf("%d missing argument to format\n") *** ^----------------------------------------- *** 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 0.000000 [ 1 2 3] [ 4 5 6] [ 7 8 9] [ 1.00 2.00 3.00] [ 4.00 5.00 6.00] [ 7.00 8.00 9.00] b b a a [1.00 2.00] *** at top-level: printf("%c",'x) *** ^--------------- *** printf: incorrect type in gtolong (t_POL). -0.0000000000000000000000000000000000000029387 [2 1] [3 1] [5 1] [7 1] -1+ 1*I -1 -1*I 1 -1*I 1+ 1*I -0001+00001*I -0001-0001*I 00001-0001*I 00001+00001*I -1.0000+1.0000I -1.0000-1.0000I 1.0000-1.0000I 1.0000+1.0000I [1.0000+1.0000I,1.0000-1.0000I] Total time spent: 1 pari-2.17.2/src/test/32/zeta0000644000175000017500000000417014567450071014057 0ustar billbill *** Warning: new stack size = 20000000 (19.073 Mbytes). 2*5^-1 + 2*5 + 3*5^2 + 3*5^4 + 3*5^5 + 2*5^6 + 5^7 + 4*5^8 + O(5^9) 0.57721614942066140874800424251188396262 - 99.999271841202858157138397118797 159155*I 1.0000000000000000000000000000000000000 1.0000000000000000000000000000000000000 1.0000000000000000000000000000007888609 1.0000000004656629065033784072989233251 1.0000000000000000000000000000007731864 - 1.56474806799752292404311992386390 49803 E-31*I 1.0000000000000000006672083904260744090 - 5.54210563151691387135805391417775 67374 E-19*I -1.8236338315400224657144248914124703369 E1769 + 6.8223788001755144705322033 655798283794 E1768*I 2^-1 + 1 + 2^2 + 2^3 + 2^5 + 2^6 + 2^7 + O(2^9) 1.0000000000000000000000000000000000000 0.E-38 error("overflow in zeta [large negative argument].") 1.6449340668482264364724151666460251892 - 9.37548254315843753702574094567864 97790 E-102*I 100.57794333849687249028215428579024415 -0.50000000000000000000000000000000918939 1.0000000000000006280369842777336909811 0.0085169287778503305423585670283444869361 -0.50000000000000000000000000000000000000 + O(x) 1.0000000000000000000000000000000000000*x^-1 + 0.577215664901532860606512090 08240243104 + O(x) -1.4603545088095868128894991525152980125 - 3.9226461392091517274715314467145 995137*I*x + O(x^2) -2.0063564559085848512101000267299604382 [1.6449340668482264364724151666460251892, 1.20205690315959428539973816151144 99908, 1.0823232337111381915160036965411679028] [2.6123753486854883433485675679240716306, 1.34148725725091717975676969334861 21366, 1.1267338673170566464278124918549842722] [1.6449340668482264364724151666460251892] 0.0033002236853241028787385710594281869587 - 0.41815544914132167671675047169 990486888*I -0.50000000000000000000000000000000000000 + O(x) *** at top-level: zeta(1) *** ^------- *** zeta: domain error in zeta: argument = 1 *** at top-level: zeta(1+O(3)) *** ^------------ *** zeta: domain error in zeta: argument = 1 seriesprecision = 1 significant terms *** at top-level: zeta(1+t) *** ^--------- *** zeta: domain error in zeta: argument = 1 Total time spent: 7 pari-2.17.2/src/test/32/sort0000644000175000017500000000221314760123736014077 0ustar billbill[[1, 3/2], [1, 2], [5/2, 1.0000000000000000000000000000000000000], [3, 4], [ 4, 1]] 2 0 [[1, 2], [1, 3/2], [5/2, 1.0000000000000000000000000000000000000], [3, 4], [ 4, 1]] 1 0 [[4, 1], [5/2, 1.0000000000000000000000000000000000000], [1, 3/2], [1, 2], [ 3, 4]] 4 4 error("incorrect type in lexicographic vecsort, index too large (t_INT).") [[5/2, 1.0000000000000000000000000000000000000], [4, 1], [1, 3/2], [1, 2], [ 3, 4]] 4 0 error("incorrect type in lexicographic vecsort, index too large (t_INT).") [[1, 2], [1, 3/2], [5/2, 1.0000000000000000000000000000000000000], [3, 4], [ 4, 1]] 1 0 [x^3 - 2, x^2 + 27, x^2 + 1, x + 1] Vecsmall([2, 4, 1, 3]) Vecsmall([3, 1, 4, 2]) Vecsmall([3, 1, 2]) 3 Vecsmall([1, 2, 3, 4]) 0 0 3 List([1, 2, 3, 4]) 0 3 0 [1, 2, 3, 4] Vecsmall([4, 6, 2, 1]) [4, 3, 2, 1] Vecsmall([1, 2, 6, 4]) List([]) *** at top-level: vecsearch(Vecsmall(1),1,1) *** ^-------------------------- *** vecsearch: incorrect type in sort_function (t_VECSMALL). *** at top-level: vecsort(Vecsmall(1),1) *** ^---------------------- *** vecsort: incorrect type in sort_function (t_VECSMALL). Total time spent: 0 pari-2.17.2/src/test/32/factorback0000644000175000017500000000131114724330232015174 0ustar billbill *** at top-level: factorback(Vecsmall([1,2]),[3,4]) *** ^--------------------------------- *** factorback: incorrect type in factorback [not a vector] (t_VECSMALL). *** at top-level: factorback('x,[3,4]) *** ^-------------------- *** factorback: incorrect type in factorback [not a vector] (t_POL). *** at top-level: factorback([1,2,3],[3,4]) *** ^------------------------- *** factorback: incorrect type in factorback [not an exponent vector] (t_VEC). *** at top-level: factorback([1,2],'x) *** ^-------------------- *** factorback: incorrect type in factorback [not an exponent vector] (t_POL). Total time spent: 0 pari-2.17.2/src/test/32/linear0000644000175000017500000003771414676526175014412 0ustar billbill echo = 1 ? algdep(2*cos(2*Pi/13),6) x^6 + x^5 - 5*x^4 - 4*x^3 + 6*x^2 + 3*x - 1 ? algdep(2*cos(2*Pi/13),6,15) x^6 + x^5 - 5*x^4 - 4*x^3 + 6*x^2 + 3*x - 1 ? charpoly([1,2;3,4],z) z^2 - 5*z - 2 ? charpoly(Mod(x^2+x+1,x^3+5*x+1),z) z^3 + 7*z^2 + 16*z - 19 ? charpoly([1,2;3,4],z,1) z^2 - 5*z - 2 ? charpoly(Mod(1,8191)*[1,2;3,4],z,2) z^2 + Mod(8186, 8191)*z + Mod(8189, 8191) ? lindep(Mod(1,7)*[2,-1;1,3]) [-3, 1]~ ? lindep([(1-3*sqrt(2))/(3-2*sqrt(3)),1,sqrt(2),sqrt(3),sqrt(6)]) [-3, -3, 9, -2, 6]~ ? lindep([(1-3*sqrt(2))/(3-2*sqrt(3)),1,sqrt(2),sqrt(3),sqrt(6)],14) [-3, -3, 9, -2, 6]~ ? matadjoint([1,2;3,4]) [ 4 -2] [-3 1] ? matcompanion(x^5-12*x^3+0.0005) [0 0 0 0 -0.00050000000000000000000000000000000000000] [1 0 0 0 0] [0 1 0 0 0] [0 0 1 0 12] [0 0 0 1 0] ? matdet([1,2,3;1,5,6;9,8,7]) -30 ? matdet([1,2,3;1,5,6;9,8,7],1) -30 ? matdetint([1,2,3;4,5,6]) 3 ? matdiagonal([2,4,6]) [2 0 0] [0 4 0] [0 0 6] ? mateigen([1,2,3;4,5,6;7,8,9]) [1 -1.2833494518006402717978106547571267252 0.283349451800640271797810654757 12672521] [-2 -0.14167472590032013589890532737856336261 0.6416747259003201358989053273 7856336260] [1 1 1] ? mathess(mathilbert(7)) [1 90281/58800 -1919947/4344340 4858466341/1095033030 -77651417539/819678732 6 3386888964/106615355 1/2] [1/3 43/48 38789/5585580 268214641/109503303 -581330123627/126464718744 4365 450643/274153770 1/4] [0 217/2880 442223/7447440 53953931/292008808 -32242849453/168619624992 1475 457901/1827691800 1/80] [0 0 1604444/264539275 24208141/149362505292 847880210129/47916076768560 -45 44407141/103873817300 -29/40920] [0 0 0 9773092581/35395807550620 -24363634138919/107305824577186620 72118203 606917/60481351061158500 55899/3088554700] [0 0 0 0 67201501179065/8543442888354179988 -9970556426629/74082861999267660 0 -3229/13661312210] [0 0 0 0 0 -258198800769/9279048099409000 -13183/38381527800] ? mathilbert(5) [ 1 1/2 1/3 1/4 1/5] [1/2 1/3 1/4 1/5 1/6] [1/3 1/4 1/5 1/6 1/7] [1/4 1/5 1/6 1/7 1/8] [1/5 1/6 1/7 1/8 1/9] ? amat=1/mathilbert(7) [ 49 -1176 8820 -29400 48510 -38808 12012] [ -1176 37632 -317520 1128960 -1940400 1596672 -504504] [ 8820 -317520 2857680 -10584000 18711000 -15717240 5045040] [-29400 1128960 -10584000 40320000 -72765000 62092800 -20180160] [ 48510 -1940400 18711000 -72765000 133402500 -115259760 37837800] [-38808 1596672 -15717240 62092800 -115259760 100590336 -33297264] [ 12012 -504504 5045040 -20180160 37837800 -33297264 11099088] ? mathnf(amat) [420 0 0 0 210 168 175] [ 0 840 0 0 0 0 504] [ 0 0 2520 0 0 0 1260] [ 0 0 0 2520 0 0 840] [ 0 0 0 0 13860 0 6930] [ 0 0 0 0 0 5544 0] [ 0 0 0 0 0 0 12012] ? mathnf(amat,1) [[420, 0, 0, 0, 210, 168, 175; 0, 840, 0, 0, 0, 0, 504; 0, 0, 2520, 0, 0, 0, 1260; 0, 0, 0, 2520, 0, 0, 840; 0, 0, 0, 0, 13860, 0, 6930; 0, 0, 0, 0, 0, 5544, 0; 0, 0, 0, 0, 0, 0, 12012], [420, 420, 840, 630, 2982, 1092, 4159; 21 0, 280, 630, 504, 2415, 876, 3395; 140, 210, 504, 420, 2050, 749, 2901; 105, 168, 420, 360, 1785, 658, 2542; 84, 140, 360, 315, 1582, 588, 2266; 70, 120 , 315, 280, 1421, 532, 2046; 60, 105, 280, 252, 1290, 486, 1866]] ? mathnf(amat,4) [[420, 0, 0, 0, 210, 168, 175; 0, 840, 0, 0, 0, 0, 504; 0, 0, 2520, 0, 0, 0, 1260; 0, 0, 0, 2520, 0, 0, 840; 0, 0, 0, 0, 13860, 0, 6930; 0, 0, 0, 0, 0, 5544, 0; 0, 0, 0, 0, 0, 0, 12012], [420, 420, 840, 630, 2982, 1092, 4159; 21 0, 280, 630, 504, 2415, 876, 3395; 140, 210, 504, 420, 2050, 749, 2901; 105, 168, 420, 360, 1785, 658, 2542; 84, 140, 360, 315, 1582, 588, 2266; 70, 120 , 315, 280, 1421, 532, 2046; 60, 105, 280, 252, 1290, 486, 1866]] ? mathnf(amat,5) [[360360, 0, 0, 0, 0, 144144, 300300; 0, 27720, 0, 0, 0, 0, 22176; 0, 0, 277 20, 0, 0, 0, 6930; 0, 0, 0, 2520, 0, 0, 840; 0, 0, 0, 0, 2520, 0, 1260; 0, 0 , 0, 0, 0, 168, 0; 0, 0, 0, 0, 0, 0, 7], [51480, 4620, 5544, 630, 840, 20676 , 48619; 45045, 3960, 4620, 504, 630, 18074, 42347; 40040, 3465, 3960, 420, 504, 16058, 37523; 36036, 3080, 3465, 360, 420, 14448, 33692; 32760, 2772, 3 080, 315, 360, 13132, 30574; 30030, 2520, 2772, 280, 315, 12036, 27986; 2772 0, 2310, 2520, 252, 280, 11109, 25803], Vecsmall([7, 6, 5, 4, 3, 2, 1])] ? mathnfmod(amat,matdetint(amat)) [420 0 0 0 210 168 175] [ 0 840 0 0 0 0 504] [ 0 0 2520 0 0 0 1260] [ 0 0 0 2520 0 0 840] [ 0 0 0 0 13860 0 6930] [ 0 0 0 0 0 5544 0] [ 0 0 0 0 0 0 12012] ? mathnfmodid(amat,123456789*10^100) [60 0 0 0 30 24 35] [ 0 120 0 0 0 0 24] [ 0 0 360 0 0 0 180] [ 0 0 0 360 0 0 240] [ 0 0 0 0 180 0 90] [ 0 0 0 0 0 72 0] [ 0 0 0 0 0 0 12] ? matid(5) [1 0 0 0 0] [0 1 0 0 0] [0 0 1 0 0] [0 0 0 1 0] [0 0 0 0 1] ? matimage([1,3,5;2,4,6;3,5,7]) [1 3] [2 4] [3 5] ? matimage([1,3,5;2,4,6;3,5,7],1) [3 5] [4 6] [5 7] ? matimage(Pi*[1,3,5;2,4,6;3,5,7]) [3.1415926535897932384626433832795028842 9.424777960769379715387930149838508 6526] [6.2831853071795864769252867665590057684 12.56637061435917295385057353311801 1537] [9.4247779607693797153879301498385086526 15.70796326794896619231321691639751 4421] ? matimagecompl([1,3,5;2,4,6;3,5,7]) Vecsmall([3]) ? matimagecompl(Pi*[1,3,5;2,4,6;3,5,7]) Vecsmall([3]) ? matindexrank([1,1,1;1,1,1;1,1,2]) [Vecsmall([1, 3]), Vecsmall([1, 3])] ? matintersect([1,2;3,4;5,6],[2,3;7,8;8,9]) [-1] [-1] [-1] ? matinverseimage([1,1;2,3;5,7],[2,2,6]~) [4, -2]~ ? matisdiagonal([1,0,0;0,5,0;0,0,0]) 1 ? matker(matrix(4,4,x,y,x/y)) [-1 -1 -1] [ 2 0 0] [ 0 3 0] [ 0 0 4] ? 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] ? mathnf(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] ? mathnf(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]~) [25, 0]~ ? matsolvemod([2,3;5,4],[7,11]~,[1,4]~,1) [[25, 0]~, [77, 30; 0, 1]] ? matsupplement([1,3;2,4;3,6]) [1 3 0] [2 4 0] [3 6 1] ? mattranspose(vector(2,x,x)) [1, 2]~ ? %*%~ [1 2] [2 4] ? norml2(vector(10,x,x)) 385 ? qfgaussred(mathilbert(5)) [1 1/2 1/3 1/4 1/5] [0 1/12 1 9/10 4/5] [0 0 1/180 3/2 12/7] [0 0 0 1/2800 2] [0 0 0 0 1/44100] ? qfjacobi(mathilbert(6)) [[1.0827994845655497685388772372251778091 E-7, 1.257075712262519492298239799 6498755378 E-5, 0.00061574835418265769764919938428527140434, 0.0163215213198 75822124345079564191505890, 0.24236087057520955213572841585070114077, 1.6188 998589243390969705881471257800713]~, [-0.00124819408408217511693981630463878 36342, 0.011144320930724710530678340374220998345, -0.06222658815019768177515 2126611810492941, 0.24032536934252330399154228873240534569, -0.6145448282925 8676899320019644273870646, 0.74871921887909485900280109200517845109; 0.03560 6642944287635266122848131812051370, -0.1797327572407600375877689780374064077 9, 0.49083920971092436297498316169060045043, -0.6976513752773701229620833504 6678265583, 0.21108248167867048675227675845247769095, 0.44071750324351206127 160083580231701802; -0.24067907958842295837736719558855680218, 0.60421220675 295973004426567844103061740, -0.53547692162107486593474491750949545605, -0.2 3138937333290388042251363554209048307, 0.36589360730302614149086554211117169 623, 0.32069686982225190106359024326699463107; 0.625460386549227244577534410 39459331707, -0.44357471627623954554460416705180104473, -0.41703769221897886 840494514780771076351, 0.13286315850933553530333839628101576048, 0.394706776 09501756783094636145991581709, 0.25431138634047419251788312792590944672; -0. 68980719929383668419801738006926828754, -0.441536641012289662221436497529772 04448, 0.047034018933115649705614518466541245344, 0.362714921464871475252994 57604461742112, 0.38819043387388642863111448825992418974, 0.2115308400789652 4664213667673977991960; 0.27160545336631286930015536176213646338, 0.45911481 681642960284551392793050867151, 0.54068156310385293880022293448123781988, 0. 50276286675751538489260566368647786274, 0.3706959077673628086177550108480739 4603, 0.18144297664876947372217005457727093716]] ? m=1/mathilbert(7) [ 49 -1176 8820 -29400 48510 -38808 12012] [ -1176 37632 -317520 1128960 -1940400 1596672 -504504] [ 8820 -317520 2857680 -10584000 18711000 -15717240 5045040] [-29400 1128960 -10584000 40320000 -72765000 62092800 -20180160] [ 48510 -1940400 18711000 -72765000 133402500 -115259760 37837800] [-38808 1596672 -15717240 62092800 -115259760 100590336 -33297264] [ 12012 -504504 5045040 -20180160 37837800 -33297264 11099088] ? mp=concat(m,matid(7)) [49 -1176 8820 -29400 48510 -38808 12012 1 0 0 0 0 0 0] [-1176 37632 -317520 1128960 -1940400 1596672 -504504 0 1 0 0 0 0 0] [8820 -317520 2857680 -10584000 18711000 -15717240 5045040 0 0 1 0 0 0 0] [-29400 1128960 -10584000 40320000 -72765000 62092800 -20180160 0 0 0 1 0 0 0] [48510 -1940400 18711000 -72765000 133402500 -115259760 37837800 0 0 0 0 1 0 0] [-38808 1596672 -15717240 62092800 -115259760 100590336 -33297264 0 0 0 0 0 1 0] [12012 -504504 5045040 -20180160 37837800 -33297264 11099088 0 0 0 0 0 0 1] ? qflll(m) [420 420 840 -630 -1092 -83 2562] [210 280 630 -504 -876 70 2205] [140 210 504 -420 -749 137 1910] [105 168 420 -360 -658 169 1680] [ 84 140 360 -315 -588 184 1498] [ 70 120 315 -280 -532 190 1351] [ 60 105 280 -252 -486 191 1230] ? qflllgram(m) [1 1 27 -27 69 0 141] [0 1 5 -23 35 -42 92] [0 1 4 -22 19 -42 66] [0 1 4 -21 11 -36 50] [0 1 4 -20 7 -30 39] [0 1 4 -19 5 -25 31] [0 1 4 -18 4 -21 25] ? qflllgram(m,1) [1 1 27 -27 69 0 141] [0 1 5 -23 35 -42 92] [0 1 4 -22 19 -42 66] [0 1 4 -21 11 -36 50] [0 1 4 -20 7 -30 39] [0 1 4 -19 5 -25 31] [0 1 4 -18 4 -21 25] ? qflllgram(mp~*mp,4) [[-420, -420, 840, 630, 2562, -1092, -83; -210, -280, 630, 504, 2205, -876, 70; -140, -210, 504, 420, 1910, -749, 137; -105, -168, 420, 360, 1680, -658, 169; -84, -140, 360, 315, 1498, -588, 184; -70, -120, 315, 280, 1351, -532, 190; -60, -105, 280, 252, 1230, -486, 191; 420, 0, 0, 0, 210, 168, 35; 0, 8 40, 0, 0, 0, 0, 336; 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, -120 12], [0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0; 0, 0, 0 , 0, 0, 0, 0; 0, 0, 0, 0, 0, 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 2562] [-210 -280 630 504 -876 700 2205] [-140 -210 504 420 -749 641 1910] [-105 -168 420 360 -658 589 1680] [ -84 -140 360 315 -588 544 1498] [ -70 -120 315 280 -532 505 1351] [ -60 -105 280 252 -486 471 1230] ? 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, 2562, -1092, 757; -210, -280, 630, 504, 2205, -876, 700; -140, -210, 504, 420, 1910, -749, 641; -105, -168, 420, 360, 1680, -658 , 589; -84, -140, 360, 315, 1498, -588, 544; -70, -120, 315, 280, 1351, -532 , 505; -60, -105, 280, 252, 1230, -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, -84 0; 0, 0, 0, 0, -13860, 0, 6930; 0, 0, 0, 0, 0, 5544, 0; 0, 0, 0, 0, 0, 0, -1 2012], [0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0; 1, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 1 , 0, 0, 0; 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 1]] ? qfminim([2,1;1,2],4,6) [6, 2, [0, 1, 1; 1, -1, 0]] ? qfperfection([2,0,1;0,2,1;1,1,2]) 6 ? qfsign(mathilbert(5)-0.11*matid(5)) [2, 3] ? trace(1+I) 2 ? trace(Mod(x+5,x^3+x+1)) 15 ? Vec(sin(x)) [1, 0, -1/6, 0, 1/120, 0, -1/5040, 0, 1/362880, 0, -1/39916800, 0, 1/6227020 800, 0, -1/1307674368000, 0] ? vecmax([-3,7,-2,11]) 11 ? vecmin([-3,7,-2,11]) -3 ? concat([1,2],[3,4]) [1, 2, 3, 4] ? concat(Mat(vector(4,x,x)~),vector(4,x,10+x)~) [1 11] [2 12] [3 13] [4 14] ? vecextract([1,2,3,4,5,6,7,8,9,10],1000) [4, 6, 7, 8, 9, 10] ? vecextract(matrix(15,15,x,y,x+y),vector(5,x,3*x),vector(3,y,3*y)) [ 6 9 12] [ 9 12 15] [12 15 18] [15 18 21] [18 21 24] ? round((1.*mathilbert(7))^(-1)<<77)/2^77 [49 -1176 8820 -29400 48510 -38808 12012] [-1176 37632 -317520 1128960 -1940400 1596672 -504504] [8820 -317520 2857680 -10584000 18711000 -15717240 5045040] [-29400 1128960 -10584000 6092986130857731040519127040001/151115727451828646 838272 -10995935908032311487186862080001/151115727451828646838272 9383198641 520905802399455641601/151115727451828646838272 -20180160] [48510 -1940400 18711000 -10995935908032311487186862080001/15111572745182864 6838272 10079607915696285529921290240001/75557863725914323419136 -8708781239 161590697851994767361/75557863725914323419136 37837800] [-38808 1596672 -15717240 9383198641520905802399455641601/151115727451828646 838272 -8708781239161590697851994767361/75557863725914323419136 152007817992 63867399887118139393/151115727451828646838272 -33297264] [12012 -504504 5045040 -20180160 37837800 -33297264 11099088] ? vecsort([8,7,6,5],,1) Vecsmall([4, 3, 2, 1]) ? vecsort([[1,5],[2,4],[1,5,1],[1,4,2]]) [[1, 4, 2], [1, 5], [1, 5, 1], [2, 4]] ? vecsort(vector(17,x,5*x%17)) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] ? vecsort([[1,8,5],[2,5,8],[3,6,-6],[4,8,6]],2) [[2, 5, 8], [3, 6, -6], [1, 8, 5], [4, 8, 6]] ? vecsort([[1,8,5],[2,5,8],[3,6,-6],[4,8,6]],[2,1]) [[2, 5, 8], [3, 6, -6], [1, 8, 5], [4, 8, 6]] ? vector(10,x,1/x) [1, 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9, 1/10] ? if(getheap()!=HEAP,getheap()) ? print("Total time spent: ",gettime); Total time spent: 5 pari-2.17.2/src/test/32/ellrank0000644000175000017500000001200714706137543014543 0ustar billbill *** Warning: new stack size = 24000000 (22.888 Mbytes). [15, 15, 0, [[-371275234790651694575894893228995/67985120505481, 29841973496 411982726963485149672630808627086898788/560558325969927038629], [-1603337425 27568795647163538495/13215571681, 476154847671996755147706413015113140423946 88/1519248904876079], [-1502834322531862057572315/139129, 204532749519476647 1439370272169048204/51895117], [95305619892520703562286230/900601, 933089059 567960106470811014291917836503/854670349], [364863100216654157088070620/1621 6729, 8089857995168780652955684544051036638801/65304767683], [49756326142642 03322727077615/1352621284, 2883761389341454582866282108874009364824209/49746 705582952], [14650083259946560568745333945/481934209, 1901969168247516799100 036566571590407428744/10579901690177], [68289081876192760070618181630/175324 081, 17847924661041527234655195197643713840731262/2321466156521], [140506312 8959926387032396410505/3623087640481, 38997800460106529617143730270797780819 5844906712/6896333561484795121], [5383824726956012402472116476160/2784493484 89, 15463736284961069697381244175905231633451967564/146932987558720987], [81 6019555882177369094357637721745/5674462344769, 23342260401674070537971066142 221977408552890517584/13517210519484716897], [185477291861431148044988912741 8755/19714781057689, 80186645110394863184628606858709375087484746177684/8753 6249962019832637], [41190576046247631758309579341376459023845/42331256678297 44362769, 18351229342347683584445005922551778623329031895150767353658534/275 417633413374247323810106267897], [514206634655664752607908696286471115552230 /12704550451389956991001, 38123312053608156840810090098967394777696462994893 7035382572697/1431986597678219220522609743205251]]] 271644039764740504 [2, 2, 0, [[7022075863304320648/46580625, 18607939018892654292592616672/3179 12765625]]] 15 W:1:[5, 5] W:2:[5, 5] W:3:[5, 5] W:4:[5, 5] W:5:[5, 5] W:6:[6, 6] W:7:[6, 6] W:8:[6, 6] W:9:[6, 6] W:10:[6, 6] W:11:[7, 7] W:12:[7, 7] W:13:[7, 7] W:14:[7, 7] W:15:[7, 7] W:16:[8, 8] W:17:[8, 8] W:18:[8, 8] W:19:[8, 8] W:20:[8, 8] W:21:[9, 9] W:22:[9, 9] W:23:[9, 9] W:24:[9, 9] W:25:[9, 9] W:26:[10, 10] W:27:[10, 10] W:28:[10, 10] W:29:[10, 10] W:30:[10, 10] W:31:[11, 11] W:32:[11, 11] W:33:[11, 11] W:34:[11, 11] D:1:[12, 12] D:2:[12, 12] D:3:[11, 11] D:4:[11, 11] D:5:[11, 11] D:6:[6, 6] D:7:[6, 6] D:8:[5, 5] D:9:[5, 5] D:10:[5, 5] D:11:[0, 4] D:12:[3, 3] D:13:[3, 3] D:14:[3, 3] D:15:[3, 3] D:16:[15, 15] D:17:[14, 14] D:18:[12, 12] D:19:[12, 12] D:20:[11, 11] D:21:[9, 9] D:22:[8, 8] D:23:[8, 8] D:24:[8, 8] D:25:[8, 8] D:26:[6, 6] D:27:[6, 6] D:28:[5, 5] D:29:[5, 5] D:30:[5, 5] D:31:[3, 3] D:32:[3, 3] D:33:[3, 3] D:34:[3, 3] D:35:[1, 3] Q:1:[2, 2] Q:2:[4, 4] Q:3:[6, 6] Q:4:[8, 8] [1, 1, 0, [[15863997051157551291/644043543828169, -5003144836231515256038734 47206/16344545427837342648197]]] [1, 1, 0, [[16, -504]]] [1, 1, 0, [[8, -168]]] [0, 0, 0, []] [3, 3, 0, [[369/4, -2753/8], [601/4, -12149/8], [2609/4, -132127/8]]] [0, 2, 0, []] [-23*x^4 - 24*x^3 + 180*x^2 - 56*x - 24, [726/y^2*x^4 - 1004/y^2*x^3 + 1980/ y^2*x^2 - 1128/y^2*x + 916/y^2, 10129/y^3*x^6 - 88110/y^3*x^5 + 83250/y^3*x^ 4 - 18220/y^3*x^3 - 57600/y^3*x^2 + 106200/y^3*x - 19592/y^3]] [-15/62, 2259/3844] [19526976286/5103081, -2728611384254603/11527859979] 1 [x^4 + 126*x^2 + 441, [-21/y^2*x^4 + 882/y^2*x^2 - 9261/y^2, -1764/y^3*x^5 + 777924/y^3*x]] [-2, 31] [-6069/961, -1499400/29791] 1 [0, 0, 2, []] [0, 0, 2, []] [1, 1, 0, []] [1, 1, 0, [[-6, 10]]] [2, 2, 0, [[-228, 312], [492, 4752]]] [1, 1, 0, [[301/9, 5203/27]]] [1, 1, 2, [[27, 102]]] [3, 3, 2, [[-7056, 84], [-1, 592704], [1, 592704]]] [0, 0, 2, []] [0, 0, 2, []] [0, 0, 2, []] [0, 0, 2, []] [0, 0, 2, []] [2, 2, 0, [[-28, 54], [-22, 33]]] [0, 0, 2, []] [0, 0, 0, []] [0, 2, 2, []] [1, 5, 0, []] *** at top-level: checktwist([1,2],[1,3]) *** ^----------------------- *** in function checktwist: ...d(1);rk=ellrankinit(E);R= *** ellrank([rk,F],,v);pr *** ^--------------------- *** ellrank: incorrect type in ellrank (t_VEC). *** at top-level: checktwist([1,0],[2,0]) *** ^----------------------- *** in function checktwist: ...d(1);rk=ellrankinit(E);R= *** ellrank([rk,F],,v);pr *** ^--------------------- *** ellrank: incorrect type in ellrank (t_VEC). *** at top-level: checktwist([0,1],[0,3]) *** ^----------------------- *** in function checktwist: ...d(1);rk=ellrankinit(E);R= *** ellrank([rk,F],,v);pr *** ^--------------------- *** ellrank: incorrect type in ellrank (t_VEC). *** at top-level: ellrank([ellinit([1/2]),1,1]) *** ^----------------------------- *** ellrank: incorrect type in ellrank [nonintegral model] (t_VEC). *** at top-level: ellrank([ellinit([1,1,1,1,1]),1,1]) *** ^----------------------------------- *** ellrank: incorrect type in ellrank [a1 != 0] (t_VEC). *** at top-level: ellrank([ellinit([0,1,1,1,1]),1,1]) *** ^----------------------------------- *** ellrank: incorrect type in ell2rank [a3 != 0] (t_VEC). Total time spent: 10121 pari-2.17.2/src/test/32/subfields0000644000175000017500000003532414567450071015101 0ustar billbill *** Warning: new stack size = 32000000 (30.518 Mbytes). 1:[1, 2, 3, 3, 3, 6] 2:[1, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 8] 3:[1, 2, 2, 2, 4, 4, 4, 8] 4:[1, 2, 4, 8] 5:[1, 3, 3, 3, 3, 9] 6:[1, 5, 10] 7:[1, 5, 10] 8:[1, 2, 10] 9:[1, 3, 4, 12] 10:[1, 2, 3, 4, 6, 12] 11:[1, 3, 4, 4, 4, 4, 6, 6, 6, 12] 12:[1, 3, 15] 13:[1, 2, 4, 8, 16, 32] 14:[1, 3, 3, 3, 3, 9, 9, 9, 9, 27] 15:[1, 2, 4, 6, 6, 6, 12] 16:[1, 2, 3, 3, 3, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8, 12, 12, 12, 12, 12, 12, 12, 12, 12, 24] 17:[1, 2, 2, 2, 4, 6, 6, 6, 12] [[x, 0]] [[x^7 - x - 1, x]] [] [[x, 0]] [[x^6 - 3*x^5 + 5*x^4 - 5*x^3 + 5*x^2 - 3*x + 1, x]] [[x^3 - 3*x^2 + 2*x - 1, -x^5 + 2*x^4 - 3*x^3 + 2*x^2 - 2*x + 1], [x^3 - 3*x ^2 + 2*x + 1, -x^5 + 3*x^4 - 5*x^3 + 5*x^2 - 4*x + 3], [x^3 + x^2 + 7*x - 1, 2*x^2 - 2*x + 1]] [x] [x^7 - x - 1] [] [x] [x^6 - 3*x^5 + 5*x^4 - 5*x^3 + 5*x^2 - 3*x + 1] [x^3 - 3*x^2 + 2*x - 1, x^3 - 3*x^2 + 2*x + 1, x^3 + x^2 + 7*x - 1] P=x^2 + 2*x + 7 fl=0 [[1, 1], [2], [1, 1], [1, 1], [1, 1], [2], [1, 1], [1, 1], [2], [1, 1]] [x^2 + 6, x + 1] P=x^2 + x + 7 fl=0 [[1, 1], [2], [2], [1, 1], [1, 1], [2], [1, 1], [1, 1], [1, 1], [2]] [x^2 + 27, 2*x + 1] P=x fl=0 0 P=x^2 - 2 fl=0 0 P=x^3 - x - 1 fl=0 0 P=x^2 + 3 fl=1 [[1, 1], [2], [2], [1, 1], [1, 1], [2], [1, 1], [1, 1], [1, 1], [2]] [x^2 + 3, x] P=x^4 + 3 fl=0 [[1, 1], [2], [2], [1, 1], [1, 1], [2], [1, 1], [1, 1], [1, 1], [2]] [x^2 + 3, x^2] P=x^6 + 3 fl=1 [[1, 1], [2], [2], [1, 1], [1, 1], [2], [1, 1], [1, 1], [1, 1], [2]] [x^2 + 27, 3*x^3] P=y^6 - 2*y^3 + 7*y^2 + 28*y + 29 fl=0 [[2], [2], [2], [2], [1, 1], [1, 1], [2], [2], [1, 1], [1, 1]] [y^2 + 567, y^5 - 2*y^4 + 4*y^3 - y^2 + 9*y + 10] P=x^6 + 2*x^4 + x^2 + 3 fl=0 [[1, 1], [2], [2], [1, 1], [1, 1], [2], [1, 1], [1, 1], [1, 1], [2]] [x^2 + 3, x^3 + x] P=x^4 - x + 1 fl=1 0 P=x^3 - x + 1 fl=0 0 P=x^4 - x^3 + 2*x - 1 fl=0 0 P=x^4 + 10*x^2 + 81 fl=1 [[2, 2], [2, 2], [2, 2], [2, 2], [1, 1, 1, 1], [1, 1, 1, 1], [2, 2], [2, 2], [2, 2], [2, 2]] [x^4 + 585144*x^2 + 82964737296, -x^3 - 72*x^2 - 19*x - 360] P=y^4 - y^3 + 3*y^2 - 2*y + 4 fl=0 [[1, 1, 2], [2, 2], [1, 1, 2], [2, 2], [2, 2], [4], [2, 2], [2, 2], [1, 1, 1 , 1], [1, 1, 1, 1]] [y^4 + 22*y^2 + 41, 2*y^2 - 2*y + 3] P=x^4 + 4*x^2 + 2 fl=1 [[1, 1, 1, 1], [1, 1, 1, 1], [4], [2, 2], [2, 2], [2, 2], [1, 1, 1, 1], [1, 1, 1, 1], [4], [4]] [x^4 + 4*x^2 + 2, x] P=y^4 - 2*y^3 + 5*y^2 - 4*y + 2 fl=1 [[1, 1, 2], [1, 1, 2], [4], [1, 1, 2], [1, 1, 2], [1, 1, 2], [2, 2], [1, 1, 2], [4], [4]] [y^4 + 14*y^2 + 17, 2*y - 1] P=x^8 - 4*x^7 + 6*x^6 - 4*x^5 + 11*x^4 - 20*x^3 + 10*x^2 + 81 fl=1 [[2, 2], [2, 2], [2, 2], [2, 2], [1, 1, 1, 1], [1, 1, 1, 1], [2, 2], [2, 2], [2, 2], [2, 2]] [x^4 + 5544*x^2 + 3111696, x^6 - 3*x^5 + 5*x^3 + 16*x^2 - 19*x - 15] with factorisation given, P=x^12 - 4*x^10 + 6*x^8 + 6*x^6 - 19*x^4 + 10*x^2 + 81 [[2, 2], [2, 2], [2, 2], [2, 2], [1, 1, 1, 1], [1, 1, 1, 1], [2, 2], [2, 2], [2, 2], [2, 2]] [x^4 + 23632*x^2 + 40043584, 2*x^9 - 6*x^7 + 7*x^6 + 6*x^5 - 14*x^4 + 36*x^3 + 7*x^2 - 38*x + 35] P=x^8 + 8*x^6 - 16*x^5 + 32*x^4 - 48*x^3 + 88*x^2 - 80*x + 49 fl=1 [[1, 1, 1, 1], [1, 1, 1, 1], [4], [2, 2], [2, 2], [2, 2], [1, 1, 1, 1], [1, 1, 1, 1], [4], [4]] [x^4 + 252500*x^2 + 4875781250, 4*x^6 + 11*x^5 + 50*x^4 + 57*x^3 + 166*x^2 + 4*x + 164] P=x^12 + 4*x^9 + 4*x^8 + 6*x^6 + 8*x^5 + 2*x^4 + 4*x^3 + 4*x^2 + 1 fl=1 [[1, 1, 1, 1], [1, 1, 1, 1], [4], [2, 2], [2, 2], [2, 2], [1, 1, 1, 1], [1, 1, 1, 1], [4], [4]] [x^4 + 8*x^2 + 8, x^9 + 3*x^6 + 4*x^5 + 3*x^3 + 4*x^2 + 2*x + 1] P=x^16 - 8*x^14 + 1108*x^12 + 3704*x^10 + 31142*x^8 + 104712*x^6 + 151252*x^ 4 + 101000*x^2 + 25921 fl=1 [[1, 1, 1, 1], [1, 1, 1, 1], [4], [2, 2], [2, 2], [2, 2], [1, 1, 1, 1], [1, 1, 1, 1], [4], [4]] [x^4 + 2651479710058184704*x^2 + 223513174382580601289821330784387072, 94353 *x^12 - 773884*x^10 + 104482077*x^8 + 330631992*x^6 + 2625478423*x^4 + 90781 20580*x^2 + 6619009291] P=x^32 + 64*x^30 + 6784*x^28 + 313984*x^26 + 7747040*x^24 + 108163584*x^22 + 981706752*x^20 + 10666873856*x^18 + 162128298368*x^16 + 1744771198976*x^14 + 10419948331008*x^12 + 43184187432960*x^10 + 220661237381120*x^8 + 59807789 1510272*x^6 + 1432066821718016*x^4 + 4527791925035008*x^2 + 5903913504477184 fl=0 [[1, 1, 1, 1], [1, 1, 1, 1], [4], [2, 2], [2, 2], [2, 2], [1, 1, 1, 1], [1, 1, 1, 1], [4], [4]] [x^4 + 139041579268565380883418276039032760612218618025438807657067393743211 98072621905741489908128376615677753665535958448271755867998729892003840*x^2 + 99748888313452660014951846097421320725695962182552919728625536100765600170 6371447435589516305554158325627091997137974907362770213425399232583142854481 5996431492550994540266130798464091006325413534505261985416821107368460111830 33854424661100240184285692922766883142212840849408, 217970128631376752544070 1494715282393359996285013607292*x^28 + 1307384881410051942873583744158666067 98430067635787629535*x^26 + 142060585329095352580206930304182763668092537381 68261677468*x^24 + 623685985340949204007508608104247778861088358056652851151 392*x^22 + 14001954299223518065299487355826221992711449666191232371466688*x^ 20 + 161856551359077216448203547286682944538019321746809143621766328*x^18 + 1058471459865572603751503071816658503212421301364877007331193696*x^16 + 1316 6530131200735561904067609894872669131740861050566425065631744*x^14 + 2519627 97432887897300680633992041154132751887915626467320032976640*x^12 + 227512801 8781712873240079273034533763083620003815901804837847145792*x^10 + 5173018466 432072655786996690040356259647974206630517630730807088384*x^8 - 153599606760 25344458674548798131743872291726245959891200380698970112*x^6 + 9718075080323 1235672537578860249267228497152688667596870906689396736*x^4 + 17545318315182 597719237276183962753864318237163043248549338952641024*x^2 - 709876976322039 788061484792228455868053475906177232711049863352465408] with factorisation given, P=x^12 + 16*x^10 - 2*x^9 - 23*x^8 - 354*x^7 + 78*x ^6 - 12*x^5 + 1468*x^4 + 1120*x^3 + 1808*x^2 + 768*x + 576 [[1, 1], [1, 1], [2], [1, 1], [2], [2], [2], [1, 1], [1, 1], [1, 1]] [x^2 + 378675200000, 1137*x^11 - 2641*x^10 + 19146*x^9 - 43578*x^8 - 7901*x^ 7 - 327487*x^6 + 963210*x^5 - 569734*x^4 + 1489388*x^3 - 1923236*x^2 - 1416* x - 1369264] P=x^4 + 12*x^3 + 256*x^2 + 3336*x + 12604 fl=1 [[2, 2], [2, 2], [2, 2], [2, 2], [1, 1, 1, 1], [1, 1, 1, 1], [2, 2], [2, 2], [2, 2], [2, 2]] [x^4 + 105566328*x^2 + 9640354331664, -x^3 - 23*x^2 - 842*x - 5272] P=y^2 + y + 1 fl=1 [[1, 1], [2], [2], [1, 1], [1, 1], [2], [1, 1], [1, 1], [1, 1], [2]] [y^2 + 3, 2*y + 1] P=x^6 - 3*x^5 + 10*x^4 - 15*x^3 + 19*x^2 - 12*x + 3 fl=1 [[1, 1, 1, 1, 1, 1], [6], [2, 2, 2], [1, 1, 2, 2], [3, 3], [2, 2, 2], [3, 3] , [1, 1, 1, 1, 1, 1], [1, 1, 2, 2], [2, 2, 2]] [x^6 + 25*x^4 + 139*x^2 + 27, 2*x - 1] P=x^6 - 2*x^5 + 5*x^4 - 7*x^3 + 10*x^2 - 8*x + 8 fl=0 [[1, 1, 2, 2], [1, 1, 1, 1, 2], [1, 1, 1, 1, 2], [1, 1, 1, 1, 2], [6], [6], [1, 1, 1, 1, 1, 1], [6], [3, 3], [3, 3]] [x^6 + 277*x^4 + 16467*x^2 + 280727, 2*x^3 - 4*x^2 + 10*x - 7] P=x^6 - 3*x^5 + 9*x^4 - 13*x^3 + 14*x^2 - 8*x + 2 fl=0 [[6], [2, 4], [1, 1, 1, 1, 2], [2, 4], [3, 3], [1, 1, 4], [2, 4], [1, 1, 4], [2, 4], [1, 1, 4]] [x^6 + 21*x^4 + 83*x^2 + 23, 2*x - 1] P=x^6 - x^5 + 3*x^4 + 5*x^2 - 2*x + 1 fl=0 [[1, 1, 1, 1, 1, 1], [2, 2, 2], [2, 2, 2], [1, 1, 1, 1, 1, 1], [3, 3], [6], [1, 1, 1, 1, 1, 1], [3, 3], [3, 3], [6]] [x^6 + 2535*x^4 + 1542294*x^2 + 130323843, -x^5 + 3*x^4 - 9*x^3 + 5*x^2 - 28 *x + 6] P=a^32 - 325413*a^30 + 65270233310*a^28 + 1500863526264933*a^26 + 2137697804 8106811144*a^24 + 5551736480851565829015*a^22 + 133169745322757800314805500* a^20 + 63038687459374293832889074215*a^18 + 25776888432592621074643880185020 0*a^16 + 106388222008795550711265556291586085*a^14 + 77117030842561455372903 634633528375614*a^12 + 89909431142768246830844916641035661283*a^10 + 4334872 90591291262458414346008665504185*a^8 - 43302983359912417821332209228814088*a ^6 + 3368895127412412772163639959696*a^4 + 2707609737271108248140094720*a^2 + 255851012946831041433600 fl=0 [[2, 2], [2, 2], [1, 1, 1, 1], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2 ], [2, 2]] P=x^6 - 3*x^5 + 4*x^4 - 3*x^3 + 4*x^2 - 3*x + 1 fl=0 [[1, 1], [2], [1, 1], [2], [2], [2], [1, 1], [1, 1], [1, 1], [1, 1]] [x^4 + 4480*x^2 + 3612672, 3*x^5 + 58*x^3 + 5*x] [[2, 2], [1, 1, 1, 1], [1, 1, 2], [1, 1, 1, 1], [2, 2], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 2], [1, 1, 2]] [x^4 + 4480*x^2 + 3612672, 3*x^5 + 58*x^3 + 5*x] [y^8 + 2947248*y^6 + 1948587410376*y^4 + 198766091481796800*y^2 + 5091771542 036490090000, 10*y^15 + 6*y^14 + 18*y^13 + 4*y^12 - 376*y^11 - 49*y^10 + 145 0*y^9 + 30*y^8 - 2696*y^7 - 107*y^6 + 2600*y^5 + 282*y^4 - 588*y^3 - 169*y^2 - 554*y - 23] [[1, 1, 1, 1, 1, 1, 1, 1], [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]] [y^8 + 24563592*y^6 + 149350874596866*y^4 + 32853587695539625800*y^2 + 11516 68054276654424900625, 16*y^15 + 18*y^14 + 10*y^13 + 12*y^12 - 470*y^11 - 147 *y^10 + 1897*y^9 + 90*y^8 - 3571*y^7 - 321*y^6 + 3455*y^5 + 846*y^4 - 781*y^ 3 - 507*y^2 - 736*y - 69] [] [[x, 0]] [[x^2 + x - 1, x^3 + x^2]] [[x^2 + x + 2, x^4 + x^2 + x], [x^3 + x^2 - 2*x - 1, x^4 + x^3]] [[x^2 + 1, x^5 + x], [x^3 + x^2 + 2*x + 1, x^2]] [[x^4 - 4*x^3 + 11*x^2 - 14*x + 11, x^8 - x^7 + 2*x^6 - 2*x^5 + 2*x^4 + x^3 + 2*x], [x^6 + 7*x^5 - 52*x^4 + 11*x^3 - 20*x^2 - x - 1, x^8 - x^7 + x^3]] [[x^6 - 8*x^5 - 20*x^4 + 664*x^3 - 21440*x^2 + 23680*x + 1563136, 2*x^13 - 3 *x^10 + 3*x^9 - 6*x^8 + 6*x^7 + 6*x^6 + 12*x^5 - 12*x^4 - 3*x^3 - 3*x^2 - 6* x], [x^6 - 34*x^5 + 2240*x^4 - 1592*x^3 + 672*x^2 - 768*x + 512, x^13 - x^12 - 2*x^10 + x^6 + x^5], [x^9 + 10*x^8 - 240*x^7 - 1048*x^6 + 464*x^5 - 2976* x^4 - 576*x^3 - 3328*x^2 + 1024*x - 512, x^8 + 2*x^6 - x]] [[x, 0]] [[x, 0]] [[x^4 + 3*x^3 + 4*x^2 + 7*x + 1, x^4 - 2*x^3 + 2*x^2 - 3*x], [x^4 - 3*x^3 + 5*x^2 - x - 1, x^4 - x^3 + x^2], [x^4 - 3*x^3 + 4*x^2 - 2*x + 1, x^3 - x^2 + x]] [[x^4 + 5*x^3 + 10*x^2 + 8*x + 3, x^4 - 2*x^3 + 2*x^2 - 2*x], [x^6 - 4*x^5 + 11*x^4 - 12*x^3 + 11*x^2 - 4*x + 1, x^7 - 3*x^6 + 5*x^5 - 6*x^4 + 6*x^3 - 4 *x^2 + x]] [] [x] [x^2 + x - 1] [x^2 + x + 2, x^3 + x^2 - 2*x - 1] [x^2 + 1, x^3 + x^2 + 2*x + 1] [x^4 - 4*x^3 + 11*x^2 - 14*x + 11, x^6 + 7*x^5 - 52*x^4 + 11*x^3 - 20*x^2 - x - 1] [x^6 - 8*x^5 - 20*x^4 + 664*x^3 - 21440*x^2 + 23680*x + 1563136, x^6 - 34*x^ 5 + 2240*x^4 - 1592*x^3 + 672*x^2 - 768*x + 512, x^9 + 10*x^8 - 240*x^7 - 10 48*x^6 + 464*x^5 - 2976*x^4 - 576*x^3 - 3328*x^2 + 1024*x - 512] [x] [x] [x^4 + 3*x^3 + 4*x^2 + 7*x + 1, x^4 - 3*x^3 + 5*x^2 - x - 1, x^4 - 3*x^3 + 4 *x^2 - 2*x + 1] [x^4 + 5*x^3 + 10*x^2 + 8*x + 3, x^6 - 4*x^5 + 11*x^4 - 12*x^3 + 11*x^2 - 4* x + 1] [[x, 0], [x^2 + 1, x]] [[x, 0], [x^2 - x - 1, -x^3 - x^2], [x^4 + x^3 + x^2 + x + 1, x]] [[x, 0], [x^2 - x + 2, -x^4 - x^2 - x], [x^3 - x^2 - 2*x + 1, -x^4 - x^3], [ x^6 + x^5 + x^4 + x^3 + x^2 + x + 1, x]] [1, 2, 3, 3, 3, 6] [1, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 8] [1, 2, 2, 2, 4, 4, 4, 8] [1, 2, 4, 8] [1, 3, 3, 3, 3, 9] [1, 5, 10] [1, 5, 10] [1, 2, 10] [1, 3, 4, 12] [1, 2, 3, 4, 6, 12] [1, 3, 4, 4, 4, 4, 6, 6, 6, 12] [1, 3, 15] [1, 2, 4, 8, 16, 32] [1, 3, 3, 3, 3, 9, 9, 9, 9, 27] [1, 2, 4, 6, 6, 6, 12] [1, 2, 3, 3, 3, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8, 12, 12, 12, 12, 12, 12, 12, 12, 12, 24] [1, 2, 2, 2, 4, 6, 6, 6, 12] [[x, 0]] [[x^7 - x - 1, x]] [] [[x, 0], [x^7 - x - 1, x]] [[x, 0]] [[x^6 - 3*x^5 + 5*x^4 - 5*x^3 + 5*x^2 - 3*x + 1, x]] [[x^3 - 2*x^2 + 3*x - 1, -x^2 + x], [x^3 - 5*x^2 + 4*x - 1, -x^4 + x^3 - x^2 + x], [x^3 - 5*x^2 + 4*x - 1, -x^4 + 3*x^3 - 4*x^2 + 2*x]] [[x, 0], [x^2 - x - 1, -x^5 + 2*x^4 - 2*x^3 + 2*x^2], [x^4 + 3*x^3 + 4*x^2 + 2*x + 1, -x^3 + x^2 - x], [x^4 + 3*x^3 + 5*x^2 + x - 1, -x^4 + x^3 - x^2], [x^4 - 3*x^3 + 4*x^2 - 7*x + 1, -x^4 + 2*x^3 - 2*x^2 + 3*x], [x^8 - 3*x^7 + 6*x^6 - 9*x^5 + 9*x^4 - 7*x^3 + 4*x^2 - x + 1, x]] [[x, 0], [x^2 + 5*x + 9, -x^11 + 5*x^10 - 13*x^9 + 25*x^8 - 38*x^7 + 47*x^6 - 48*x^5 + 42*x^4 - 31*x^3 + 18*x^2 - 10*x], [x^3 - 11*x^2 + 19*x - 13, -2*x ^9 + 7*x^8 - 12*x^7 + 15*x^6 - 14*x^5 + 8*x^4 + 2*x^3 - 4*x^2 + 4*x], [x^3 - 18*x^2 + 110*x - 214, -3*x^10 + 12*x^9 - 25*x^8 + 41*x^7 - 57*x^6 + 63*x^5 - 55*x^4 + 45*x^3 - 31*x^2 + 13*x], [x^3 - 32*x^2 + 336*x - 1174, -4*x^10 + 20*x^9 - 49*x^8 + 87*x^7 - 126*x^6 + 147*x^5 - 136*x^4 + 106*x^3 - 70*x^2 + 31*x], [x^4 - 5*x^3 + 10*x^2 - 8*x + 3, -x^4 + 2*x^3 - 2*x^2 + 2*x], [x^6 + 4*x^5 + 11*x^4 + 12*x^3 + 11*x^2 + 4*x + 1, -x^7 + 3*x^6 - 5*x^5 + 6*x^4 - 6 *x^3 + 4*x^2 - x], [x^12 - 5*x^11 + 13*x^10 - 25*x^9 + 39*x^8 - 50*x^7 + 53* x^6 - 48*x^5 + 37*x^4 - 23*x^3 + 12*x^2 - 4*x + 1, x]] 11 15 2 2 [y^2 - 2] [y, y^2 - 2, y^4 - 2] [] [[x, 0], [x^2 + 108, -x^3], [x^3 - 93312, -x^4 - 18*x], [x^3 - 108, -x^2], [ x^3 - 93312, -x^4 + 18*x], [x^6 + 108, x]] [[a, 0], [a^2 + 108, -a^3], [a^3 - 93312, -a^4 - 18*a], [a^3 - 108, -a^2], [ a^3 - 93312, -a^4 + 18*a], [a^6 + 108, a]] *** at top-level: ...nffactor(subst(P,x,a),P);nfsubfields([P,F]) *** ^------------------ *** nfsubfields: incorrect priority in nfsubfields_fa: variable x <= x *** at top-level: nfsubfieldscm(1) *** ^---------------- *** nfsubfieldscm: incorrect type in subfields_cleanup (t_INT). *** at top-level: nfsubfieldscm(x^2+1/2) *** ^---------------------- *** nfsubfieldscm: incorrect type in subfields_cleanup [not integral] (t_POL). *** at top-level: nfsubfieldscm([1,matrix(0,2)]) *** ^------------------------------ *** nfsubfieldscm: incorrect type in checknf [please apply nfinit()] (t_INT). *** at top-level: nfsubfieldscm([[],matrix(0,2)]) *** ^------------------------------- *** nfsubfieldscm: incorrect type in checknf [please apply nfinit()] (t_VEC). *** at top-level: nfsubfieldscm([]) *** ^----------------- *** nfsubfieldscm: incorrect type in checknf [please apply nfinit()] (t_VEC). *** at top-level: nfsubfieldscm([x^2+1,1]) *** ^------------------------ *** nfsubfieldscm: incorrect type in subfields_cleanup [fa should be a factorisation matrix] (t_INT). *** at top-level: nfsubfieldscm([nfinit(x^2+1),1]) *** ^-------------------------------- *** nfsubfieldscm: incorrect type in subfields_cleanup [fa should be a factorisation matrix] (t_INT). *** at top-level: nfsubfieldscm(4*x^2+1) *** ^---------------------- *** nfsubfieldscm: incorrect type in subfields_cleanup [not monic] (t_POL). *** at top-level: nfsubfieldscm(x^0) *** ^------------------ *** nfsubfieldscm: incorrect type in subfields_cleanup [constant polynomial] (t_POL). *** at top-level: nfsubfields([x^2-5,[z,1;z,1]]) *** ^------------------------------ *** nfsubfields: incorrect priority in nfsubfields_fa: variable z <= x *** at top-level: nfsubfields([x^2-5,[z-x,1;z+x,1]]) *** ^---------------------------------- *** nfsubfields: incorrect priority in nfsubfields_fa: variable x <= x Total time spent: 11314 pari-2.17.2/src/test/32/qfbclassno0000644000175000017500000000064614567450071015253 0ustar billbill144 64 225 240 10125 11045 4802 1660 2136 2144 1508 2728 15376 7688 15376 76800 7688 8112 32448 [5670, 33453, 14904, 6480, 8748, 76302, 21465, 38880, 10206, 13608, 31752, 4 0500, 47709, 35640, 22032, 21222, 80838, 38394, 13122, 19926, 14742, 24300, 114048, 53379, 28998, 13932, 926316] [100, 25, 1000, 1500, 680000, 14785000] [49, 98, 18522, 329280, 7481900160] 641278838681600 1 2 2 3 2147483647/2 Total time spent: 594 pari-2.17.2/src/test/32/lerch0000644000175000017500000000124014676526175014216 0ustar billbill-3.3414017812339596953683669622752536823 + 1.9011304852318494151244308785011 544211*I 0.55372662302410163972374316161641839303 - 0.1544945549403847536996465230693 6395768*I 0.82246703342411321823620758332301259461 2.4929009605609220535760803210022720106 -123 -0.99977190051257714439055686008318337168 - 0.028989587294862435371591357905 620794798*I -1.4646997018265823406167342377188095157 + 2.5866122066173278434433728603756 565376 E-5*I 15.541098615884207067948173701127909689 -5.6973756028464425482673383466050968227 - 11.095663023831145126562446757342 221826*I -1.8630962037053540025746549780315191119 - 1.2797297863708409263367890660592 854157*I Total time spent: 454 pari-2.17.2/src/test/32/apply0000644000175000017500000000071314676526175014252 0ustar billbill[1, 4, 9, 16] [1 4] [9 16] 16*x^2 + 9*x + 4 4 + 9*x + 16*x^2 + O(x^3) List([1, 4, 9, 16]) List([1, 2]) List([7, 13, 19]) [0, 1, 2] [0, 1, 2] [2, 3] [2, 3] Map([1, 1; 3, 3; 5, 5]) Map(Mat([3, 2])) [1, 3] Map([1, 3; 3, 5; 5, 7]) Map([1, 2; 5, 6]) [1, 5]~ 24 [[[1, 2], 3], 4] 256 -9/19 1: 2, 3 15 *** at top-level: call(strprintf,["%d",10]) *** ^------------------------- *** call: incorrect type in call (t_INT). Total time spent: 0 pari-2.17.2/src/test/32/nflistA50000644000175000017500000001301714676526175014613 0ustar billbill[x^5 - x^4 + 2*x^2 - 2*x + 2, x^5 - x^4 + x^3 + 2*x^2 + x - 1, x^5 - 2*x^3 - 2*x^2 + 3*x + 2, x^5 - 2*x^4 - x^3 + 3*x^2 - x + 2, x^5 - 2*x^4 + 6*x^3 - 8 *x^2 + 10*x - 8, x^5 - x^4 + 3*x^3 - 4*x^2 + 5*x - 1, x^5 - 2*x^3 - 4*x^2 - 6*x - 4, x^5 - 2*x^4 + x^2 + 4*x - 5, x^5 - x^4 + 3*x^3 - 3*x^2 + 5*x - 1, x ^5 - 2*x^4 + x^3 - 5*x^2 + x - 2] [[x^5 - 11*x^3 - 5*x^2 + 18*x + 9, x^5 - 2*x^4 - 7*x^3 + 11*x^2 + 11*x - 11, x^5 - 14*x^3 - 2*x^2 + 24*x + 8, x^5 - x^4 - 13*x^3 + 32*x + 16, x^5 - 2*x^ 4 - 12*x^3 + 17*x^2 + 30*x - 31, x^5 - x^4 - 15*x^3 + 6*x^2 + 58*x + 10, x^5 - x^4 - 9*x^3 + 8*x^2 + 8*x - 4, x^5 - x^4 - 14*x^3 - x^2 + 49*x + 41, x^5 - 2*x^4 - 15*x^3 + 31*x^2 + 6*x - 5, x^5 - x^4 - 20*x^3 + 7*x^2 + 45*x + 17] , [], [x^5 - x^4 + 2*x^2 - 2*x + 2, x^5 - x^4 + x^3 + 2*x^2 + x - 1, x^5 - 2 *x^3 - 2*x^2 + 3*x + 2, x^5 - 2*x^4 - x^3 + 3*x^2 - x + 2, x^5 - 2*x^4 + 6*x ^3 - 8*x^2 + 10*x - 8, x^5 - x^4 + 3*x^3 - 4*x^2 + 5*x - 1, x^5 - 2*x^3 - 4* x^2 - 6*x - 4, x^5 - 2*x^4 + x^2 + 4*x - 5, x^5 - x^4 + 3*x^3 - 3*x^2 + 5*x - 1, x^5 - 2*x^4 + x^3 - 5*x^2 + x - 2]] [] [] [x^5 - x^4 + 2*x^2 - 2*x + 2] [x^5 - x^4 + x^3 + 2*x^2 + x - 1] [x^5 - x^4 + x^3 + 2*x^2 + x - 1, x^5 - 2*x^3 - 2*x^2 + 3*x + 2, x^5 - 2*x^4 - x^3 + 3*x^2 - x + 2] [[], [], [x^5 - x^4 + x^3 + 2*x^2 + x - 1, x^5 - 2*x^3 - 2*x^2 + 3*x + 2, x^ 5 - 2*x^4 - x^3 + 3*x^2 - x + 2]] [[x^5 - 211*x^2 - 1266*x - 1899, 633], [x^5 - 25*x^2 - 75, 675], [x^5 - x^4 - 40*x^3 + 109*x^2 - 21*x + 623, 707], [x^5 - 2*x^4 + 78*x^3 - 184*x^2 + 648 *x - 1152, 764], [x^5 - x^4 - 16*x^3 + 77*x^2 + 267*x + 665, 779], [x^5 + 10 *x^3 - 10*x^2 + 35*x - 18, 800], [x^5 - x^4 + 19*x^3 - 41*x^2 + 32*x - 5, 83 7], [x^5 - x^4 - 12*x^3 - 10*x^2 + 63*x + 119, 868], [x^5 - 15*x^3 - 135*x^2 - 315*x - 243, 975], [x^5 - 2*x^4 + 14*x^3 - 18*x^2 + 47*x - 36, 992]] [[[x^5 - x^4 - 780*x^3 + 9911*x^2 - 24208*x + 15952, 1951], [x^5 - x^4 - 856 *x^3 + 8307*x^2 + 88449*x - 1017173, 2141], [x^5 - x^4 - 280*x^3 - 1346*x^2 + 8827*x + 50175, 2804], [x^5 - 1310*x^3 - 5895*x^2 + 237110*x - 914249, 327 5], [x^5 - x^4 - 26*x^3 + 3*x^2 + 58*x + 32, 3377], [x^5 - x^4 - 184*x^3 - 3 32*x^2 + 4551*x + 13021, 3688], [x^5 - x^4 - 1480*x^3 - 10807*x^2 + 512929*x + 6101529, 3701], [x^5 - x^4 - 1528*x^3 + 5655*x^2 + 543927*x - 5025433, 38 21], [x^5 - 410*x^3 - 2870*x^2 + 6560*x + 62976, 4100], [x^5 - x^4 - 408*x^3 - 1552*x^2 + 5056*x - 2816, 5105]], [], [[x^5 - 211*x^2 - 1266*x - 1899, 63 3], [x^5 - 25*x^2 - 75, 675], [x^5 - x^4 - 40*x^3 + 109*x^2 - 21*x + 623, 70 7], [x^5 - 2*x^4 + 78*x^3 - 184*x^2 + 648*x - 1152, 764], [x^5 - x^4 - 16*x^ 3 + 77*x^2 + 267*x + 665, 779], [x^5 + 10*x^3 - 10*x^2 + 35*x - 18, 800], [x ^5 - x^4 + 19*x^3 - 41*x^2 + 32*x - 5, 837], [x^5 - x^4 - 12*x^3 - 10*x^2 + 63*x + 119, 868], [x^5 - 15*x^3 - 135*x^2 - 315*x - 243, 975], [x^5 - 2*x^4 + 14*x^3 - 18*x^2 + 47*x - 36, 992]]] [] [] [[x^5 - 211*x^2 - 1266*x - 1899, 633]] [[x^5 - 25*x^2 - 75, 675], [x^5 - x^4 - 40*x^3 + 109*x^2 - 21*x + 623, 707], [x^5 - 2*x^4 + 78*x^3 - 184*x^2 + 648*x - 1152, 764], [x^5 - x^4 - 16*x^3 + 77*x^2 + 267*x + 665, 779], [x^5 + 10*x^3 - 10*x^2 + 35*x - 18, 800], [x^5 - x^4 + 19*x^3 - 41*x^2 + 32*x - 5, 837], [x^5 - x^4 - 12*x^3 - 10*x^2 + 63* x + 119, 868], [x^5 - 15*x^3 - 135*x^2 - 315*x - 243, 975], [x^5 - 2*x^4 + 1 4*x^3 - 18*x^2 + 47*x - 36, 992]] [x^6 - 2*x^5 + 3*x^4 - 4*x^3 + 2*x^2 - 2*x - 1, x^6 - 2*x^5 + 4*x^4 - 4*x^3 + 3*x^2 - 2*x - 1, x^6 - 2*x^5 + 2*x^4 - x^3 - 2*x^2 + x - 2, x^6 - 2*x^5 + 2*x^4 - 4*x^3 + x^2 - 2*x - 1, x^6 - 2*x^5 - 2*x^4 + 6*x^3 + x^2 - 6*x + 1, x^6 - 2*x^5 - 5*x^2 - 2*x - 1, x^6 - x^5 + x^4 + 3*x^3 - 5*x^2 + 5*x - 3, x^ 6 - 2*x^5 + x^4 - 4*x^3 - 2*x - 1, x^6 - 2*x^5 - 3*x^4 + 6*x^3 + 2*x^2 - 6*x + 1, x^6 - x^5 + x^4 - 7*x^3 - 7*x^2 - x + 1] [[x^6 - 10*x^4 - 7*x^3 + 15*x^2 + 14*x + 3, x^6 - 9*x^4 - 2*x^3 + 20*x^2 + 8 *x - 1, x^6 - 3*x^5 - 5*x^4 + 14*x^3 + 5*x^2 - 15*x + 4, x^6 - 3*x^5 - 11*x^ 4 + 15*x^3 + 51*x^2 + 29*x + 1, x^6 - x^5 - 13*x^4 + 7*x^3 + 52*x^2 - 7*x - 53, x^6 - 13*x^4 - 2*x^3 + 34*x^2 + 30*x + 7, x^6 - 2*x^5 - 12*x^4 + 21*x^3 + 38*x^2 - 53*x - 10, x^6 - 2*x^5 - 7*x^4 + 12*x^3 + 10*x^2 - 17*x + 4, x^6 - 2*x^5 - 13*x^4 + 16*x^3 + 24*x^2 - 37*x + 12, x^6 - 13*x^4 - 7*x^3 + 44*x^ 2 + 40*x - 9], [], [x^6 - 2*x^5 + 3*x^4 - 4*x^3 + 2*x^2 - 2*x - 1, x^6 - 2*x ^5 + 4*x^4 - 4*x^3 + 3*x^2 - 2*x - 1, x^6 - 2*x^5 + 2*x^4 - x^3 - 2*x^2 + x - 2, x^6 - 2*x^5 + 2*x^4 - 4*x^3 + x^2 - 2*x - 1, x^6 - 2*x^5 - 2*x^4 + 6*x^ 3 + x^2 - 6*x + 1, x^6 - 2*x^5 - 5*x^2 - 2*x - 1, x^6 - x^5 + x^4 + 3*x^3 - 5*x^2 + 5*x - 3, x^6 - 2*x^5 + x^4 - 4*x^3 - 2*x - 1, x^6 - 2*x^5 - 3*x^4 + 6*x^3 + 2*x^2 - 6*x + 1, x^6 - x^5 + x^4 - 7*x^3 - 7*x^2 - x + 1], []] [x^6 - 2*x^5 + 3*x^4 - 4*x^3 + 2*x^2 - 2*x - 1, x^6 - 2*x^5 + 4*x^4 - 4*x^3 + 3*x^2 - 2*x - 1, x^6 - 2*x^5 + 2*x^4 - x^3 - 2*x^2 + x - 2, x^6 - 2*x^5 + 2*x^4 - 4*x^3 + x^2 - 2*x - 1, x^6 - 2*x^5 - 2*x^4 + 6*x^3 + x^2 - 6*x + 1, x^6 - 2*x^5 - 5*x^2 - 2*x - 1, x^6 - x^5 + x^4 + 3*x^3 - 5*x^2 + 5*x - 3, x^ 6 - 2*x^5 + x^4 - 4*x^3 - 2*x - 1, x^6 - 2*x^5 - 3*x^4 + 6*x^3 + 2*x^2 - 6*x + 1, x^6 - x^5 + x^4 - 7*x^3 - 7*x^2 - x + 1] [] [x^6 - 2*x^5 + 3*x^4 - 4*x^3 + 2*x^2 - 2*x - 1] [x^6 - 2*x^5 + 4*x^4 - 4*x^3 + 3*x^2 - 2*x - 1, x^6 - 2*x^5 + 2*x^4 - x^3 - 2*x^2 + x - 2, x^6 - 2*x^5 + 2*x^4 - 4*x^3 + x^2 - 2*x - 1, x^6 - 2*x^5 - 2* x^4 + 6*x^3 + x^2 - 6*x + 1, x^6 - 2*x^5 - 5*x^2 - 2*x - 1] [[], [], [x^6 - 2*x^5 + 4*x^4 - 4*x^3 + 3*x^2 - 2*x - 1, x^6 - 2*x^5 + 2*x^4 - x^3 - 2*x^2 + x - 2, x^6 - 2*x^5 + 2*x^4 - 4*x^3 + x^2 - 2*x - 1, x^6 - 2 *x^5 - 2*x^4 + 6*x^3 + x^2 - 6*x + 1, x^6 - 2*x^5 - 5*x^2 - 2*x - 1]] [x^5 + 2*x^3 - 4*x^2 + 6*x - 4, 1] Total time spent: 1232 pari-2.17.2/src/test/32/matpermanent0000644000175000017500000000150414567450071015605 0ustar billbill1 a 1 (j*e + h*f)*a + ((j*d + g*f)*b + (h*d + g*e)*c) 450 225/4 450.00000000000000000000000000000000000 2432902008176640000 5923651457692698111014016643988523721001231402487426778059781745358246359177 62560000 3083006079469106283548010402121540337574621576466658968216372244601693632059 0710729600180853543474258186192116072131181104815025761774130562338354193365 1962372270527617850320061887552530356998486431159949171842025616672790485876 08238404756881640802750401375601950720000000 *** at top-level: matpermanent(matrix(64)) *** ^------------------------ *** matpermanent: sorry, large matrix permanent is not yet implemented. *** at top-level: matpermanent(matrix(2,3)) *** ^------------------------- *** matpermanent: inconsistent dimensions in matpermanent. Total time spent: 2132 pari-2.17.2/src/test/32/content0000644000175000017500000000240614567450071014566 0ustar billbilldenominator 1 1 1 3 1 6 1 1 3 1 1 x error("incorrect type in denom (t_QFB).") error("incorrect type in denom (t_QFB).") 4 2 1 1 1 1 (x)->denominator(x,1) 1 1 1 3 1 6 8 2 3 2 1 1 1 1 4 2 2 2 2 1 (x)->denominator(x,'y) 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2*y 2*y 2*y 1 numerator 2 1.0000000000000000000000000000000000000 Mod(1, 3) 2 x 3 + 2*I O(2^-3) 2^-1 + O(2^3) w Mod(1/2*x, x^2) 2*x 2 error("incorrect type in numer (t_QFB).") error("incorrect type in numer (t_QFB).") [8, 3] [2, 4; 3, 8] 1/y*x + 1/2 [1/y*x + 1/2] 1/(2*y) + O(x^2) y + O(y^2) (x)->numerator(x,1) 2 1.0000000000000000000000000000000000000 Mod(1, 3) 2 x 3 + 2*I O(2^0) 1 + O(2^4) w Mod(x, x^2) 2*x 2/x Qfb(1, 2, 4) Qfb(-1, 2, 4) [8, 3] [2, 4; 3, 8] 2/y*x + 1 [2/y*x + 1] 1/y + O(x^2) y + O(y^2) (x)->numerator(x,'y) 2 1.0000000000000000000000000000000000000 Mod(1, 3) 2/3 x (1/2 + 1/3*I) O(2^-3) (2^-1 + O(2^3)) 1/3*w Mod(1/2*x, x^2) 2*x 2/x Qfb(1, 2, 4) Qfb(-1, 2, 4) [2, 3/4] [1, 2; 3/2, 4] 2*x + y [2*x + y] 1 + O(x^2) y + O(y^2) content 2 1 Mod(1, 3) 2/3 x 1/2 + 1/3*I 1/8 1/2 1/3*w 1/2 2 2 1 1 1/4 1/2 1/(2*y) 1/y*x + 1/2 1/(2*y) 1 (x)->content(x,1) 2 1 1 2/3 1 1/6 1 1 1 1/2 2 2 1 1 1/4 1/2 1/2 1/2 1 1 (x)->content(x,'y) 1 1 1 1 1 1 1 1 1 1/2 2 2 1 1 1 1 1/2 1/y*x + 1/2 1/2 1 x + y x + y [] [x] Total time spent: 2 pari-2.17.2/src/test/32/agm0000644000175000017500000000065114567450071013660 0ustar billbill *** at top-level: agm(1,2+O(5)) *** ^------------- *** agm: not an n-th power residue in Qp_sqrt: 3 + O(5). 0.59907011736779610371996124614016193911 + 0.5990701173677961037199612461401 6193911*I 0.0052400175398595973401348278731495151168 + 0.00293778732531728227546892438 58414176183*I -0.00028140660159115806090031594700401853703 - 0.000120146984355561255780668 97634319815694*I Total time spent: 52 pari-2.17.2/src/test/32/lfunquad0000644000175000017500000007164714676526175014762 0ustar billbill24611 -3 0 -2/9 0 2/3 0 -14/3 0 1618/27 0 -3694/3 0 111202/3 0 -13842922/9 0 252470402/3 0 -17612343854/3 0 1209690584166433868173617584705996218315856485209242680940294284867422217406 192417053053165057630038560104612393727756986420002/3 2403361924042760961630453858956344496380637547366499164322986812658083865554 1092108853882284391419202986932106199258141059139239875394215584976030325528 7339416036302443757879526332031738861830961968450295133099943113337189366038 2786893757438856044217117190427325855974796041940822279446051618568018438843 90520006/9 2436413300232214252963836869608684422913028244455731115127981606758156885775 3623326739346899844042937895974465871992356429327422403461792108279903769511 4424695157346651145037811697664114508788918417946043074833469019167729441692 7153142698284070906276613456537615488684043181027928687253388184545076569175 7371146405443250976697232444587654376575644643127550184759382175245216138367 8705058972112388391965607592017373433720373053633166317863713166650969536043 903828477816782743735122374584436834487630850581610869431260002/3 -4 0 -1/2 0 5/2 0 -61/2 0 1385/2 0 -50521/2 0 2702765/2 0 -199360981/2 0 19391512145/2 0 -2404879675441/2 0 2903528346661097497054603834764435875077553006646158945080492319146997643370 625023889353447129967354174648294748510553528692457632980625125/2 5995471635010873724749684141880650449267286183694250548680913664554158756801 5079983245957644662666248915403967624790150145358552024787336963366498103916 6488273449468831053594931966683906734130221865944184112020908528590877181590 5437687163670905792742609763070663117774070733128893697501695481964191495049 41815733845016897635621925859625/2 5685256368605058271578985553004208762654649710895792394745630663303745424222 3164692660463310486845949879941738638619394532581064314311727579362078288887 0939367536721050147117801884739232021647113817641879341276385907272403056110 8573804079898187390716554425423866804618155282768677870460466478716368892214 0571977298415638208962689185051347676391981219529503486862975224833150672917 0637472037738104778617507325598287454514286514854708432186711250385340168493 9382247016708774783532349317055425798221934631771270445565838444040505935156 250946905537050798594125/2 -7 0 -16/7 0 32 0 -1168 0 565184/7 0 -9006448 0 1475050592 0 -2332239605296/7 0 99245951007872 0 -37693640601621808 0 3865627192600178114543017841848106823202058340197883528473441467055555404420 3291794345680908057869000817015306372755623184865282289113244490914982657874 11484350752 1124657175835177453549701761397383331906564422949908635436580816797923537710 9821549502905235012069093981124626621696146352246529316447409565982126514000 0923464513883918386737282573831758034097150345468781986457657780401992621991 7091528778741077729084639404517897643024395670268295211801270823070508113416 3452383661488986474426624568991913928413343827378853697730940389002113813241 379264/7 3066575685809273866688420071358695704494967058253153615305102584444987091440 9684555835505865834192760082766298932321311201724130201438834905920101573619 9747036700171479422322523465226596362274133795038126216936534934658467826695 4683476064116982253649716856859047794904702393460374331488464598295261048917 2666991462119049503451628057220600921801945951309282242904299722122158689729 5654590598972688790057834521263411922820235167406637674702634637813795575223 0572056437412913985039314274945780523545774206665446931846700095547231604773 4361526912407768983674769863818302255682324791878788359732540036012674099929 109460286882224614752 5 -2/5 0 2 0 -134/5 0 722 0 -825502/25 0 2301842 0 -1137183686/5 0 30246849362 0 -26049794569478/5 0 1128345029099282 1001295457644387160821786857647641726201287724374796414191383069787474064588 28100582988617091354529884696682243631685340792741752073247385883441682 5074939081686467820245247285014990422287331779491095833205555819238964533458 9634828805651875973205390778324663909839415827183699957421670608032477511515 9481662266974614756532353096477608781998775643209177283464480027582038791540 4068818418601197954961978968562713970701000645678264152654871055217614005645 3304579554032216602941698009950386239229392969682 1574952919809799448001007340521221350319202514644018954340654532973492538337 9627915435096345456016843367531565139872125215711572980427410116793630380158 4029382811705149312132612831619898640428116242235893603642232875845521829988 1225828155969981180543448280434616237359421473770275127160214098790865109869 2719849014445629461259300798121792315858660833634304051072553122794439045896 7985880889388156256906032272139325791350679402066765695748535176212021969309 8003440446053920033489167040539105842595502835632014834977423706186050007700 103583104544934576299138399088263245292113126497682 8 -1 0 11 0 -361 0 24611 0 -2873041 0 512343611 0 -129570724921 0 44110959165011 0 -19450718635716001 0 10784052561125704811 2044092384738221346884415052588174693301410044927367043666625952405685054812 9197839588664620859657189451927778591863876764776001254565116726401387374781 294003758004811 2675268483608548899961618653273170728094149015801416867311227192149036329383 1118815891273893606502658019380458277362463236775517454420787190713912573912 5204953155232477248871034808591506331811938850186670693947446481534316234679 7481278478941116837296830566693068450642187381314393311906861857097131486480 9921237780134392178770335997839433710811739427302644736659403315281782875276 66280093979811 2143889421547176822734369311570295019913889106257397102398568743569325516557 1731757326821306995204010277715517177232718091407779408223005754009968309810 8805195425993218440055822304520826581225590850925420616008236361107833529910 4710339034955161430822285950201060482198707872689758876638906356414520163289 1462710687467682809823157432409551992613378045128722197230456721229637675745 0459046151144256714831171716709792127382409291501512185177484949879009937856 7041701134842429509193315119588369317405543742435267259352373496739115891599 4587583837920442263404574967275632139699735786530742486539782115330678300631 682875301844670735691749334213954811 13 -2 0 58 0 -66926/13 0 935338 0 -289094342 0 136229337418 0 -90991535833382 0 81802590527352298 0 -1238258285030677313486/13 0 139451183898845082019978 1951687897706133311451560072273872335674486005097056279595695541752510761624 7624604315509150520573208173822085057014246465279153499598903959892463733134 212266987036444839409233356958861578 3108950115370917249542541020125979575325330051153716063462070479164465266856 9506826142303110661303676163536252889127676322594453077219206696908326744413 4089068020072889190846095312875480843071308592923005845725040983978577021113 8941115932886443372522647915559376434547407672860139678335421304749115619097 9677458541049851348538094319088577724627131894101101880579249994262253034169 66059013646159046534942339626447138698346286253972113578 3032391657582129036330476247501761534014363882924482045492831080601217297916 1235680776499706945762404715243769411126623785355821597370522967002702711323 2842095596420314145585709109850678187639999456185366021135727209394453633717 9960059722786074781722191922655502675543221788047871768918461427633429343292 9469930179367451631844295867047018650909971295563352097488633956956157532252 0192004537187434617850960630640906198036469810771949333029753639454659197783 4515118966081104554366907216087616672033193901731134272941452900107257423932 3801517824930291834944031088434235325775295334570829010707967033136638673866 1144398767390478736898047410983674145208981524317683436601280020034584217340 32342303092031393365578 -20 0 -30 0 3522 0 -1066590 0 604935042 0 -551609685150 0 737740947722562 0 -1360427147514751710 0 3308161927353377294082 0 -10256718523496425979562270 0 2560834490419865335752039925855509622700588686498300325124284506323137052141 6609520015139018355947082538944419930499567044692990164963545238249557054878 417451002950174279007063211338830400161686991151948888002 4171374926666255045643541652751190414160898606967314854200662896416374697734 5603471152190648637919110172302269163834083900672484742312097206091431020838 6880100286958554872549905159198723462000903742538558160840352162790447051745 2442019886124734588354976383422015455502074550891603200812719476455559452486 8248898170226602096401931063793708834005276997928433464307166182595404705720 7253559358560599532886375925879287810163102424273505234791373336010878250896 46752266795897776002 3120371917188729497236265984425703260691592372097294980484174087670582308720 8944304701336923003262182255421079040871509564004068165041688196117199095287 3646748891275274126924677147419022637431059311880619037144245646755133506236 5922134414479694720707909712034697258789407626820997519530303385305286025701 6496213986087090797450243734496025971311349642726165288243893254470963531338 1377568402071930587987896695354772774333320112273191381128202327617766076258 5144437639127202636806686578826149274692915564302686515353597295753487824452 2599711875908618966018235927836187771496782523484673546701088745154370964191 9081721118689359708553912150864611269127257644073388487086977061093737182625 0265317038401969390013085212312565509866977531814809306784209423052575283846 664002 -24 0 -46 0 7970 0 -3487246 0 2849229890 0 -3741386059246 0 7205584123783010 0 -19133892392367261646 0 67000387673723462963330 0 -299131045427247559446422446 0 2323254238956789601617831166950995129056846012702229125673092861994541935375 2863229576377603563046825898816346274021880096609231821771678863274467063603 20424936676785791473705498826633465108892547723155025322052809250 3134144811193881916349446221367331585522750151555300857549206198166822732737 9848930956315804921528617633783832485326089354378993222876414578416730588833 9526041819671174512969774970829861036210073299828310798601332683876888754038 4694813497699817396905041781164143765962297412414556125283025170464654045174 3615551590413348512117145389316935721526285262188250461212917643318697031034 5668199234399601727942644359771750449339042328297142680401783151301820506060 426816588151390781621666998391837250 1941649333266104896031775740726970018219931584687071138654514439400115097354 5508953688784023177559314379411660860300508829919235005356212375021359193658 9158335023247683634216752190888051515561425600733497573491476020311441559901 9305526289664799966791892116096693444603567452921361516693748074139483250101 7890372852451898795863214547118749874682357174757987773360751174759588936733 7177444800093261872863453387062588411661560526337996227773675297342637346948 4536844908117717089687089965327927689053218619251953925905612951300248734632 0278036287828847165207852237394119430496881662064772471730130006211771509618 4474710942321582795089436099512191268548732144248689765654895107578210737844 6362452524756409975175085110512483984794914586166537290573873554727422941676 218319529221205417329442865250 -51 0 -268 0 229700 0 -464445628 0 1723578263300 0 -10235034907683388 0 89043631039817351300 0 -1067811570359299546588348 0 16884819392120808879317341700 0 -340408931650872149644047668424508 0 1843612500005619802081932775304286746670938909723050911853012087716270214955 1249925725438062218504896263736616654667959204676928564506254963988836995438 5270263296071212867367490067966399698911463505976591390725119216188309842682 9755084676815049562500 1353896306175806970010515365328995398653882940351444193340757584186497658062 5472185683109449876897530355648814263905544348329668808324613797737444025594 5782324759380730616320389480965643936961974305724376664899994944682301642764 3993726488366715956294477433523430811881549962308370941657452865043533530120 5381049252854948210189493866592161943617137224364789532270984885992023487203 0061160802379365721531618445278887812931156110934467804994603484214140506771 2903758053840550379823956595750004562302305176825826141704418055151588053484 83647840569918873471562500 4565944004054980662693603046240578281153687086923216284373935122699824222908 6095002743685165779584451012899892181233083406585581010531421420014835846243 5709167088659528117726946564179190199991827521223684779629335109097634186671 7983827075353630116342502867310531699526057014848871514154802528423170500641 9129377129750719935117343598473788863615191404122064457978680613122451763412 0059655246495767805585416051873978101897837611341116124798048722449623339349 6629449739531736902585248365557537067932175083911500535699397007821834878744 5071003868233165772555086118594289431640495167306665379193301178519911101015 0562568997521626772857773313684894880638764687429978437694984043657095575432 5269352692272175807389161429109992051636289231414927775851787976112961617457 2758382653062165514699365274381783668557136859580990311702167669843097240028 9222729635391196040369372922722749543827480117562500 -56 0 -396 0 362340 0 -860061996 0 3824302352580 0 -27339541106529996 0 286668042859824989220 0 -4144448470243486082277996 0 79012222186129845498564688260 0 -1920578297824486899468413393961996 0 2227222782168745128310114901996287397638776340189107437632706957316024068179 1607381917873677284652665248578097858294200224570118925493058065176933245379 0697951219346718614588235712356747925401730244323231392305543759669546226929 91988095340135830373478500 1885664871052144083371223231620177708735242511168318172880016289336916411329 1729509327154532387440570192487382814747758143069242429841057538065218929825 1840507804087512317535751356066470877789071379278940239584994872462135215717 9522195901476157231318784754818238418212080153959569292909035257740570041855 5617337748839101890364031804549813705729279422634680896935458536797618091824 7492802917815016902037365592981464247940265595549543037831275094526106892129 7007435687273015056390943487051255113377483644958416222397096547850886762920 7326287512333346235262301279394500 7331532751681493659772596265994294828305453222002563552540745830400269418768 8445168286476461696353909943668817056744112838898474358499486974363263385396 7918149882376374322524133053354749360935635417713283052404543058335560015774 6120618947434149230189721083786995262704146099262880913942687075599444359780 4258148257016461003471238630386147219749638279247312122027016494909069005380 1922506990040516568458835827539726343085643056079742745961139301907111096305 7176742791103423985596082629282727836275505351275673594271082343118101674276 6525835716939052898779836529949804171182761180722293671934358359526453540800 3792623317820032969953922336532155854783133744564641016734269932346380044865 9524115587799755748318446221527612855318333479886734020147254319275151212741 2384075249093427842488062508315204659694782027872728198916600654004341193663 4985549070165440739896922629063409195465748023770380829569310500 101 -38 0 74206 0 -405130418 0 4453214119246 0 -83102899216749938 0 2363830110858868417486 0 -95302458446338979986588658 0 5171617184089159964481333806926 0 -363482296891571740330099308154110578 0 32121337767081129252515068963758888527566 7638771268727730393026782503661671855738230084357016685213012412880915786668 1322814230112423244581587498485030879106031140600526302174217839809572724186 9709533771318081769202430124027452768520094538860030498013542219322562049255 168904380706865286211639907374467909838051292366 1327483213730021004299527333174467332912155038605818132855748224827865041057 0324824612751315015615864473846472131537259196616015723452525917765943327483 5950762051341884160843109142413820209292874874551200334107878660233688989130 3475475850967254175468642437764692643780561620428834832935926085183041674229 5837461365626978440871295864990791929409911885572559320793103894785300984343 1254216023345951403029052013382741860206194913708692990741921005146490349084 3789489596688155782567182346802002397990476902347805137378765825707199178919 2410809533117616375041678286431105829930183392412956161042299698639870607953 548366 1412546408280907149085137258543769759086003986621137961846959594667462995553 4200088305571462967899441258114603023386078081562210357076169456204394360231 8754742313135226819222808714176113122540857429745936229468250179493893549229 6777660674319335751238122690347913769187055952077110066190174113333361727206 8427754860910255882565346530125038652000113182922686827407300719037679758430 1919359978080215698450710020734191455093011989287331179020744016030744996726 8775372748857228438909730690080273672086052457776296793274858641143567022841 9331084931945033745713931503156438251324785508602983369599458128425972292310 2153333710523177775882054195834129040932255426711111859204839687056995903020 6411532469678858452692092204950326445541706567453383239707423780222779666491 1487084087678730319224465680980666687957848003510549939350881761026305372558 5976773477594606731960883306832242989159978661023004148424972176186308568123 61074715091380511283451603739319570276052032534090344687804366 104 -50 0 87358 0 -483330770 0 5568092998558 0 -109850934674168690 0 3310624158456705346558 0 -141495342534520445361377810 0 8140825808115856876435533387358 0 -606658541947132742331651408896446130 0 56843049124085540800666343434939055712958 1405607529153069831198975720804957183237721637608661905700118797567314587605 1267531928551514645029272825163220749242764763335897419004252254029994520626 9953537350455995333788952150536092930018764162817916398085422324032895822878 35480258787643544228732681949986463986058170512958 4561063919143267150489917731939852787194853617936203202491600029230446025356 1030932638723223986954744834525365527640948438052068790200011234661183733422 7550174152118362474641321303384684944410912329797064015806447377368507873311 7496031424315669363272142889616134491669119576117502988900676176019668276534 6255207431041108491950632036562553524027006264866061518684112377573008946819 0467638317995664918115801376198145593024920589527984675190381434520021165848 7638450835678282649760699016850657429834352517959692080286018294319530116076 4189497806228821975050216351345801589347629369931902151465397422710540638199 67212958 9062257478418486217129623148462909644454375039935055890081080947623499072951 3929349721960810915639821575579244327776878446195163370590140394042057417304 7164794262618075856580381599746963229550653368013988267451453989414629508524 8650233911098688631861172705380628593546337154609712533457451951428594395635 2224766009090620544298062649163582718356308533210609101149423599002963771098 1266180057208314347029549308022311742350938822244199266483297585057930049512 6959727908768358145856822060226755016778103715487888905941346695753970434667 0117929181382651740835431071072824834201660238014938410872470081393829803437 1498661070122041986306553092043235434846015392423096722798103132057159887468 5865589402805210428837470522754960040477415925489996457460470465752395135156 9579314281832131240109328424249314674434471232167142448963251751313501597247 2254871323506005174118390482603200873193442729835114995296255750140716996744 54584982077906404809379144118811330565159099400916163556011912958 105 -72 0 97416 0 -518217912 0 6006771500616 0 -120425098174516152 0 3696666523221123155016 0 -161017915669028495948772792 0 9442619191282111084312502828616 0 -717257785163287922451169931157755832 0 68504483422605398950828026786630456889416 3642353324710650216594984642332778641680388888088094653056105241561052399613 3228718134307495046692332120080200728100000040236850331965388879353177414093 4465424314690330021925122914313976678320708596901544732070589750588029268095 73272724894882855956185418675685903173023950137416 3077372955930450335434502935210046894926508082906196228291612293501311827326 9397264444929015698550811899640511271745159856969014853256791192293717044253 2575781010402201147337870378810813113217190075040280718386993666683780634460 9407504054064611779585897284340594588205844883183326881634968425141448582311 8661947153616110670515299270655817683353319959923470895243090730656139043088 9584681006843343619912501462252634217111551104777921394242327997581721400617 4375808820498419153719080011181564630255079412872814197097486515179512380872 6380191193673042377473167944723118343073784733667130364113078758917530449114 501497416 1592012043123519211179606365266082419045588961976657245183853792503676378403 9881631251899930040206607002579639802725809095321644454593560799601668194607 3567752497426732150136984258005663909527076585278514411906551524315046747897 1920264408549265719336539524019038605854043264682090777267648150569427194337 4618849207204143704218405276634194418265575591437907870537043435094953134790 8054503394653786935601242266605552803605093900211034354770381632556559389679 3197089155408539692439419118752658778546601306767067587786541737759106949081 0578602432256391474596078162620562532090192648326037390219483843431074908560 1133935404961136260179631898277786733180169954658726566517792926402433044431 6535329983333723471665539451552302700848964020247838109012646878803429398417 9817593394813914509054738792300698932636808220188936962012079333873049315400 5052824972354037126524585190951155774775888962553721295750856517090897558190 6420395365123247691337626712501862612146703273295954806548124857416 -103 0 -1904 0 5754400 0 -45472417424 0 680573287589440 0 -16436713504505650544 0 582836477605259969334880 0 -28503179258089183116179126864 0 1838270191911836424431405104366720 0 -151162129751591682251388044914204334384 0 8810651616728089497007861350511723541930869593999925842788169500632664916149 7939255985476734187941381158107493588042718897055308527383430344169178641284 8156257786661448432485133283687107775317991785694969146695599774686366819111 4948250094372109401095697332059763849872245570729760 2175848480418645743532366449173212221449150636855623826241024982865261386901 9491321706982996206298470389705045519613062475178261623545073623706383595292 2768498858065786647006077910988449888888435049874105333491105003317229814911 5144285773612945540101690261345842528786130922639675028155199979971722869187 1002740172444733210114220612482291004626844913953967794680241836182267510533 4176081624525170398164947906158224665877451340586969855222627758982603586682 6325452368555714409388711786996482324913596016809747530001271278830899021062 8687440166546769543983077395282294674730238154949072618418416852961693219770 48494365760 2467622306949235161898057190734415750039865141253340127675459935240830340332 4943627334565465529532373507859774189396157035600594059547275069580788717804 1695238573047180613344747599091792294184021674973020879240669118620439825437 0541615610996168527478280072447270877479682115210679089099279539704974405207 2767113378910721100453400139761459639216878763714424688140868113770521983637 9465079099090680413939637005511858115712785021223967769358406620687008623638 0667785594176354455022561296168376737037438859957977442103153346291172368062 8842477105347818508218646569323181838382511728592327798155770677974380894782 8690061681657174205883622086895301641001455783182003154675102716439890760098 4250473446285130787514622588758474717167424936375932996445605575042878096478 5420310321266576815402346057542026284947828313236160802581504319040673318956 1443950003986810117376423091042813599462932534697697676951369952220116666866 71677948928112215880461871375638882214046983027207228099210642001760 -107 0 -1746 0 6468966 0 -57399855066 0 937277609128326 0 -24498222724784517786 0 938151879491105688118086 0 -49521281603433351128386713306 0 3446837816749512376750354944618246 0 -305881052814024215363620655080686457626 0 4054493453900697070957455442062558427324101224355840249856516373608056993782 0824949601574478740566179713822312665082097310643417891770263514496756229892 1964928936557597306392569905757790200069253714950235695253553553157685571868 165758872109067733716961950540222526952476119768344006 4520771137782771040047377512886050882586967880508966340916211145265400058896 6089114587965896960629375657837337581691581396698230492443257860111925586038 3272427696479040552221765139110593444979463801614990399894128008949379518984 3810707397134042345621323930638354110184079411051019706487585584712557681476 4793950890390999826085373667803705387210498788672963342993464272219074006837 2274383630710091081399618983884832351849766062433285584980221117889344796979 1593204962639189396927807478440612594892364827502456469790591451011442718419 2415960655048887737605120479804335302453226743715985566446054571356874342501 88472880688006 2314823368855547086235462347354347041589289693668786133723696775426034237430 5600533109767136718172086626454076944420548565326323032277996501689489047432 7114035409806116347106403415392889267359428060494083934698323619696666228882 2380744495383589998718267617933974258607449302922109029470358379925551951978 7670918716141359336278869121059670037264388848770119770949007224315570035180 6433703474720584402925187786502537638470667915460626058185757453854347136854 7278481334588584966833259919861012470302774301268388340158785643149275571654 4404883604838076753899490062340888265208592938514633906571383657807595801092 9224911277234401387697027401018220987476896375459214678095545468744269956432 6011916357787452508187760798241022524314142487735960206043042314549212313442 5695071843843234573495227037008637558861635526057439928405995606042959911339 1770498064043404948957310397772135276941519877164978300339320802561717766938 8245013261453444204835241955854279159490395075825778942813857539337032006 -116 0 -2442 0 9600870 0 -97787654442 0 1865721813153990 0 -57230273815253143242 0 2574861118009005402115110 0 -159728052469332232760521704042 0 13066180487908747755709114533796230 0 -1362781778901400604095440689996592376842 0 1357984658121946365021231937385941265248487845430579607356398026527628644095 1345909527720634030300900837727434633786557434142867986575075208544024106373 3668038927498936120221204357775260058076699091225654647472978915464688579136 5048872970579220702050998558079701993213768468665206171750 4870706221450259643639912646202487775054366546087034087793760480569507407813 7151718353936929754394379783698208317605932386747748208176134252576496805048 9932428354911903886669464480582324364318542131293079195721154872944026985827 3605021359282896023336719961393522519491755097489126348311590204765936651790 6190475516962586882545193844003444734017948784233940507793460228723535849881 2207291709621204735079105021552085111338088347453782845425654721618717081596 9789185462472938464179042594165738884829010464584667625128569268589698946861 7642055786180633575323327151578578227425691562765468250110836054714801431272 363633664752374999750 8022660722724184981189210494386159496886644114817171654819137157622744942095 5972127147773416013856558128102411912097831376619948030329032628130558241295 8918365054264178132610431828648949242546959705747967230645938983512347944239 7257042554374663944435976895840665426447238597140008854183483730433958167737 5279628464215110147458328243907083606531107627698959520661774892206560238524 5266580918334498737797123138536156472835162541415438208369899463604137641627 9160642492172029204183537160772109286474813602033608494741450210772002005128 2187826026388538049701871253364082393871496092723441597882474651493357979737 8096450623281153061354166607398951588181863643317030750854393383194287005215 8324163934644840503890036208811324026916175165835568879864409546052532347713 8623444748451267121735563822082404005949099911213080412490177398828289516627 4516646459937451017866012005680902548382828676928565537215100316233225286032 5948576158587070482570833285363715715146737649433626274597133323744715117878 3827750 1/3 0.60459978807807261686469275254738524410 0.78130241289648629686718742962409235636 0.88402381175007985674305791687101180775 1/2 0.78539816339744830961566084581987572105 0.91596559417721901505460351493238411078 0.96894614625936938048363484584691860007 0 0.43040894096400403888943323295060542542 0.70621140325974096993100317576256402766 0.85482476664854301023569008353813769714 0 0.62322524014023051339402008025056800265 0.87235802495485994176969511702117566124 0.95838045456309456205166940286157781883 2502146816821644066572103377521811161518259314570882356855821321019590757973 4688023914833635960698935198865273952863590798506011596964840284979193880787 6016030709895234350098003915885338598038601598683407010567431843377072759929 3054708456104618989352937229639358936473658844194984422038613614389682268743 2426895567927777863320180168115462180248591380163652328257380120010897175565 9777098313120381049347875469823015934707633319970423054616052055173440574434 833092193426838649459186108684083408835509557640651233313241948898439406000 1501887188795470177731539667813245737858118899667372848476198418979229702060 2265447555396714714408803803334721734705531608430592251214429575165485463861 4399576982571712083031554478603319420614889984478360906805437512460353030004 6729972229464505971489427857605410716371853356725330914538029834607396467386 1517201720255996635113269513935963271501871605172459512196451376218302842008 0094743527785308921162839525712082314563549281531064518286670672397110959171 5840054700034370959917097328729734434083191797017835418590402644235103374346 1972459730203754733063750248364917937331623444053487333559093541366026057091 0216449451142515197113719588768556838372672969341335925335424772529675459881 4626959545510340784455763573896224520033726094136487539570384401678738024864 5229822329473747355404676367702775021572703289751007015790166113461855034695 442344921751497905317670524512793862630484837132809079689093880498773185 Total time spent: 56 pari-2.17.2/src/test/32/galois0000644000175000017500000001454314567450071014377 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.17.2/src/test/32/round0000644000175000017500000000274714567450071014253 0ustar billbill1 1 2 -1 error("incorrect type in gceil (t_INTMOD).") 2 error("incorrect type in gceil (t_POLMOD).") x error("incorrect type in gceil (t_SER).") 0 [2, 2] [1, 0; 0, 1] error("incorrect type in gceil (t_STR).") 1 1 -2 error("incorrect type in gfloor (t_INTMOD).") 1 error("incorrect type in gfloor (t_POLMOD).") x error("incorrect type in gfloor (t_SER).") 0 [1, 2] [0, 0; 0, 0] error("incorrect type in gfloor (t_STR).") 0 0.60000000000000000000000000000000000000 2/3 error("incorrect type in gfrac (t_INTMOD).") -1 + w error("incorrect type in gfrac (t_POLMOD).") 0 error("incorrect type in gfrac (t_SER).") 1/x [1/3, 0] [1/3, 0; 0, 1/3] error("incorrect type in gfrac (t_STR).") 1 2 -1 Mod(1, 3) 2 Mod(x + 1, x^2 + 1/2) x 1 + O(x^2) 1/x [1, 2] [0, 0; 0, 0] error("incorrect type in ground (t_STR).") [1, -oo] [2, -2] [-1, -1] [Mod(1, 3), -oo] [2, 1] [Mod(x + 1, x^2 + 1/2), -1] [x, -oo] [1 + O(x^2), -1] [1/x, -oo] [[1, 2], -1] [[0, 0; 0, 0], -1] error("incorrect type in grndtoi (t_STR).") 1 1 -1 error("incorrect type in gtrunc (t_INTMOD).") error("incorrect type in gtrunc (t_QUAD).") error("incorrect type in gtrunc (t_POLMOD).") x 1/3*x + 4/3 0 [1, 2] [0, 0; 0, 0] error("incorrect type in gtrunc (t_STR).") [1, -oo] [1, -1] [-1, -oo] error("incorrect type in gtrunc (t_INTMOD).") error("incorrect type in gtrunc (t_QUAD).") error("incorrect type in gtrunc (t_POLMOD).") [x, -oo] [1/3*x + 4/3, -oo] [0, -oo] [[1, 2], -oo] [[0, 0; 0, 0], -oo] error("incorrect type in gtrunc (t_STR).") Total time spent: 0 pari-2.17.2/src/test/32/bnr0000644000175000017500000000546114676526175013713 0ustar billbill *** Warning: new stack size = 160000000 (152.588 Mbytes). [] [[4, 0, 0; 0, 2, 0; 0, 0, 2], [4, 0, 2; 0, 2, 1; 0, 0, 1], [4, 2, 0; 0, 1, 0 ; 0, 0, 2], [4, 0, 2; 0, 2, 0; 0, 0, 1], [2, 0, 0; 0, 2, 0; 0, 0, 2], [4, 0, 0; 0, 2, 1; 0, 0, 1], [4, 0, 0; 0, 1, 0; 0, 0, 2], [4, 0, 0; 0, 2, 0; 0, 0, 1], [2, 0, 1; 0, 2, 1; 0, 0, 1], [2, 0, 1; 0, 2, 0; 0, 0, 1], [2, 0, 0; 0, 2, 1; 0, 0, 1], [4, 0, 2; 0, 1, 0; 0, 0, 1], [4, 2, 2; 0, 1, 0; 0, 0, 1], [2 , 0, 0; 0, 1, 0; 0, 0, 2], [4, 2, 0; 0, 1, 0; 0, 0, 1], [2, 0, 0; 0, 2, 0; 0 , 0, 1], [4, 0, 0; 0, 1, 0; 0, 0, 1], [2, 0, 1; 0, 1, 0; 0, 0, 1]] [[2, 0, 1; 0, 1, 0; 0, 0, 1]] [[1, 0, 0; 0, 2, 1; 0, 0, 1], [2, 0, 1; 0, 1, 0; 0, 0, 1], [2, 1, 1; 0, 1, 0 ; 0, 0, 1], [1, 0, 0; 0, 1, 0; 0, 0, 2], [2, 1, 0; 0, 1, 0; 0, 0, 1], [1, 0, 0; 0, 2, 0; 0, 0, 1], [2, 0, 0; 0, 1, 0; 0, 0, 1], [1, 0, 0; 0, 1, 0; 0, 0, 1]] [[1, 0, 0; 0, 1, 0; 0, 0, 1], [0]] [] 0 [32, 0, 27656345068767491604576153420888539136] 0, 12, [24, 12, 40621487921685401825918161408203125] 0, 12, [24, 12, 40621487921685401825918161408203125] 1, 12, [24, 12, 40621487921685401825918161408203125] 1, 6, [12, 12, 18026977100265125] 12 2 12 2 [24, 12, 40621487921685401825918161408203125] [4, 4, 262205] [24, 12, 40621487921685401825918161408203125] [4, 4, 262205] [[5, 3; 0, 1], [1, 0]] [[5, 3; 0, 1], [0, 0]] [[5, 3; 0, 1], [1, 0]] [[5, 3; 0, 1], [0, 0]] [2, 2, [5, 3; 0, 1]] 0 0 [4, 4, 262205] [2, 2, [5, 3; 0, 1]] 6 18 9 9 9 *** at top-level: bnrclassno(bnf,[7,Vecsmall([1,2,3])]) *** ^------------------------------------- *** bnrclassno: incorrect type in Idealstar [incorrect archimedean component] (t_VECSMALL). 1.0000000000000000000000000000000000000 1 [[1, 0; 0, 1], [0, 0]] [[7, 0; 0, 7], [1, 1]] 3 1/3 6 2/3 -1 1/2 *** at top-level: chareval(1,chi,1) *** ^----------------- *** chareval: incorrect type in chareval (t_INT). 0 -1 1/2 1 [4, [2, 2], [[3, 2; 0, 1], [0, -1]~]] [4, [2, 2], [[5, 2, 1, -2, 0, 1]~, [5, 2, -2, 1, -1, -1]~]] [14, [14], [[3, 2; 0, 1]]] [16, [2, 2, 2, 2], [[11, 2; 0, 1], [2, 1; 0, 1], [3, 0; 0, 1], [0, -1]~]] [2, 2, 5] [1, 2, [1, 0; 0, 1]] 0 0 [2, 2, 5] [0, 0]~ 1 1 0.99595931395311210936063384855913482215 - 0.0898055953159170744883890303595 05357518*I 0.089805595315917074488389030359505357526 - 0.995959313953112109360633848559 13482210*I 1 1 0.99595931395311210936063384855913482215 + 0.0898055953159170744883890303595 05357517*I 0.089805595315917074488389030359505357543 + 0.995959313953112109360633848559 13482212*I [72, [12, 6], [[425, 259; 0, 1], [70, 2; 0, 2]]] [1, [], []] [1, []] [[0]~, 1] 3 [2 0] [0 1] [2, 2, 2, 2, 2, 2, 2] [3, 3, 3] [1, 1, 0]~ [3, 3, 3] [1, 1, 0]~ 2 1 [[3, 0, 0]~, Mat([3, 2])] [[3, 0, 0]~, 9] [3, 0, 0]~ [[3, 0, 0]~, [3, 1; 35, -1; 3675, -1; 1/3, 1]] [[3, 0, 0]~, 1/128625] [3, 0, 0]~ [x^2 - 13, x^2 + 7] [14, 3]~ Total time spent: 5149 pari-2.17.2/src/test/32/factor0000644000175000017500000001633514760123736014400 0ustar billbill [x^2 + I 1] [x + 1.0000000000000000000000000000000000000 1] [x - 1.0000000000000000000000000000000000000 1] [x + (0.45508986056222734130435775782246856962 - 1.0986841134678099660398011 952406783785*I) 1] [x + (-0.45508986056222734130435775782246856962 + 1.098684113467809966039801 1952406783785*I) 1] [Mod(1, 5)*x + Mod(2, 5) 1] [Mod(1, 5)*x + Mod(3, 5) 1] [Mod(1, 3)*x^2 + (Mod(1, 3) + Mod(1, 3)*I) 1] *** at top-level: factor(x^2+Mod(1,5)*I) *** ^---------------------- *** factor: sorry, factor for general polynomials is not yet implemented. [(1 + O(5))*x^2 + O(5)*x + (2 + O(5)) 1] *** at top-level: factor(x^2+(1+O(3))+I) *** ^---------------------- *** factor: sorry, factor for general polynomial is not yet implemented. [(1 + O(5))*x + (2 + O(5)) 1] [(1 + O(5))*x + (3 + O(5)) 1] [ x + (1 - w) 1] [x + (-1 + w) 1] *** at top-level: factor(x^2+quadgen(-3)*Mod(1,3)) *** ^-------------------------------- *** factor: sorry, factor for general polynomial is not yet implemented. [Mod(1, 5)*x + (Mod(4, 5) + Mod(1, 5)*w) 1] [Mod(1, 5)*x + (Mod(1, 5) + Mod(4, 5)*w) 1] *** at top-level: factor(x^2+quadgen(-3)*(1+O(5))) *** ^-------------------------------- *** factor: sorry, factor for general polynomial is not yet implemented. *** at top-level: factor(x^2+quadgen(-3)*(1+O(3))) *** ^---------- *** _*_: not an n-th power residue in Qp_sqrt: -3. [x^2 + Mod(y, y^2 + 1) 1] [Mod(Mod(1, 3), Mod(1, 3)*y^2 + Mod(1, 3))*x + Mod(Mod(1, 3)*y + Mod(1, 3), Mod(1, 3)*y^2 + Mod(1, 3)) 1] [Mod(Mod(1, 3), Mod(1, 3)*y^2 + Mod(1, 3))*x + Mod(Mod(2, 3)*y + Mod(2, 3), Mod(1, 3)*y^2 + Mod(1, 3)) 1] *** at top-level: factor(x^2+Mod(y*Mod(1,5),y^2+1)) *** ^--------------------------------- *** factor: sorry, factor for general polynomial is not yet implemented. *** at top-level: factor(x^2+Mod(y*(1+O(3)),y^2+1)) *** ^--------------------------------- *** factor: sorry, factor for general polynomial is not yet implemented. [ I 1] [ 3 -1] [ 1 + I -2] [15 + 2*I 1] [ 1 + I 1] [ 2 + I 4] [1 + 2*I 4] [ -I 1] [ 1 + I 1] [2 + 3*I 1] [ -I 1] [ 3 1] [ 1 + I 1] [2 + 3*I 1] [ -1 1] [1 + I 5] [ -1 1] [1 + 2*I -2] [15 1] [31271192761826143388782348951 1] [31274945109847936339856761591 -1] [ 500009 1] [ 500029 -1] [ 500041 1] [ 500057 -1] [ 500069 1] [ 500083 -1] [250110012091 1] [250115013209 -1] [ 61 2] [263 2] [ x - 2.0000000000000000000000000000000000000 1] [x^2 + 0.E-38*x + 1.0000000000000000000000000000000000000 1] [x - 2 -1] [x + 1 2] [x + 2 -1] [ x -1] [x^2 + 1 1] [ x + Mod(-a, a^2 - 2) 1] [x + Mod(3*a, a^2 - 2) 1] [ 2 1] [ 5 1] [ 11 1] [ 17 1] [ 37 1] [ 67 1] [18084262717 1] [ 2 1] [ 5 1] [ 11 1] [ 17 1] [ 37 1] [ 67 1] [831974948142355246286065325186245612497373357862036849743 1] [ -1 1] [ 3 1] [ 35111 1] [4326169708845601005599113 1] [289*x^4 + 1 8] [19*x^2 + 1 16] [ y -2] [y*x - 1 1] [y*x + 1 1] [y 1] [x -1] [ x + y 2] [x^2 - y*x + y^2 2] [ x^4 + y^4 1] [ x + y 1] [x^2 - y*x + y^2 1] [Mod(1, 7)*x + Mod(6, 7)*y 7] [Mod(1, 7)*x^7 + Mod(6, 7)*y 1] [x^2 + y*x + y^2 1] [x^3 + (y^2 - 1) 1] [Mod(1, 13)*x + Mod(5, 13)*y 1] [Mod(1, 13)*x + Mod(8, 13)*y 1] [ x + I*y 1] [x^2 + (y^2 + I) 1] [Mod(1, 7)*x + (Mod(1, 7)*y + Mod(1, 7)*z) 1] [Mod(1, 7)*x + (Mod(4, 7)*y + Mod(2, 7)*z) 1] [Mod(1, 7)*x + (Mod(2, 7)*y + Mod(4, 7)*z) 1] [ x + (y + 1) 1] [x + (-19*y + 18) 1] [ x + (18*y - 19) 1] [ y 1] [ x 1] [x + y 1] [4*x^3 + (-4*t^2 + 8)*x^2 + (-4*t^3 - 4*t^2 + 4*t + 4)*x + (t^6 + 2*t^5 - t^ 4 - 4*t^3 - t^2 + 2*t + 1) 1] [2*x^6 + (-4*t^2 + 8)*x^5 + (-10*t^3 - 10*t^2 + 10*t + 10)*x^4 + (10*t^6 + 2 0*t^5 - 10*t^4 - 40*t^3 - 10*t^2 + 20*t + 10)*x^3 + (-10*t^8 - 20*t^7 + 20*t ^6 + 60*t^5 - 60*t^3 - 20*t^2 + 20*t + 10)*x^2 + (4*t^10 + 10*t^9 - 10*t^8 - 40*t^7 + 60*t^5 + 20*t^4 - 40*t^3 - 20*t^2 + 10*t + 6)*x + (-t^12 - 2*t^11 + 4*t^10 + 10*t^9 - 5*t^8 - 20*t^7 + 20*t^5 + 5*t^4 - 10*t^3 - 4*t^2 + 2*t + 1) 1] *** factor: Warning: normalizing a polynomial with 0 leading term. [x + 1.0000000000000000000000000000000000000 1] *** factor: Warning: normalizing a polynomial with 0 leading term. [x + (0.E-38 + 1.0000000000000000000000000000000000000*I) 1] [x - I 1] [x + I 1] [x + 1.0000000000000000000000000000000000000 1] [x - 1.0000000000000000000000000000000000000 1] [x + (0.45508986056222734130435775782246856962 - 1.0986841134678099660398011 952406783785*I) 1] [x + (-0.45508986056222734130435775782246856962 + 1.098684113467809966039801 1952406783785*I) 1] [Mod(1, 5)*x + Mod(2, 5) 1] [Mod(1, 5)*x + Mod(3, 5) 1] [Mod(1, 3)*x + (Mod(0, 3) + Mod(1, 3)*I) 1] [Mod(1, 3)*x + (Mod(0, 3) + Mod(2, 3)*I) 1] [(1 + O(5))*x + (2 + O(5)) 1] [(1 + O(5))*x + (3 + O(5)) 1] [(1 + O(5^2))*x + O(5^2) 1] [(1 + O(5^2))*x + O(5^2) 1] *** at top-level: factor(x^2+(1+O(3)),I) *** ^---------------------- *** factor: sorry, factor for general polynomial is not yet implemented. [x + (1 - w) 1] [ x + w 1] [ x + (1 - w) 1] [x + (-1 + w) 1] [ x + (1 - w) 1] [x + (-1 + w) 1] [ x + (1 - w) 1] [x + (-1 + w) 1] [ x + (1 - w) 1] [x + (-1 + w) 1] [x^2 + Mod(y, y^2 + 1) 1] [Mod(Mod(1, 3), Mod(1, 3)*y^2 + Mod(1, 3))*x + Mod(Mod(1, 3)*y + Mod(1, 3), Mod(1, 3)*y^2 + Mod(1, 3)) 1] [Mod(Mod(1, 3), Mod(1, 3)*y^2 + Mod(1, 3))*x + Mod(Mod(2, 3)*y + Mod(2, 3), Mod(1, 3)*y^2 + Mod(1, 3)) 1] *** at top-level: factor(x^2+Mod(y,y^2+1),Mod(1,5)) *** ^--------------------------------- *** factor: sorry, factor for general polynomial is not yet implemented. *** at top-level: factor(x^2+Mod(y,y^2+1),O(3)) *** ^----------------------------- *** factor: sorry, factor for general polynomial is not yet implemented. [ 1 + I -2] [ 2 + I 1] [1 + 2*I 1] [ x + Mod(-a, a^2 - 2) 1] [x + Mod(3*a, a^2 - 2) 1] [ Mod(1, 2)*y 1] [ Mod(1, 2)*x 1] [Mod(1, 2)*y*x + Mod(1, 2) 1] [Mod(1, 2)*z^3 + Mod(1, 2)*z + Mod(1, 2) 1] [Mod(1, 2)*y^2 + Mod(1, 2)*y + Mod(1, 2) 1] [ Mod(1, 2)*x 1] [ Mod(1, 2)*y*x + Mod(1, 2) 1] [ x -2] [x + y -3] [x - y 2] [x - 1 1] [ x + y 1] [x + (-1 + w)*y 1] [ x - w*y 1] [Mod(1, 7)*x + Mod(6, 7)*y 7] [Mod(1, 7)*x^7 + Mod(6, 7)*y 1] [Mod(1, 13)*x + Mod(5, 13)*y 1] [Mod(1, 13)*x + Mod(8, 13)*y 1] [Mod(1, 7)*x + (Mod(1, 7)*y + Mod(1, 7)*z) 1] [Mod(1, 7)*x + (Mod(4, 7)*y + Mod(2, 7)*z) 1] [Mod(1, 7)*x + (Mod(2, 7)*y + Mod(4, 7)*z) 1] 0 [ x 13] [x^2 + (a^3 + a^2 + a + 1) 1] Total time spent: 426 pari-2.17.2/src/test/32/iterator0000644000175000017500000000731414676526175014762 0ustar billbill18446744073709551614 18446744073709551615 18446744073709551616 18446744073709551617 18446744073709551618 -18446744073709551618 -18446744073709551617 -18446744073709551616 -18446744073709551615 -18446744073709551614 2 3 4 5 6 7 8 9 10 4294967279 4294967291 4294967311 9223372036854775837 9223372036854775907 9223372036854775931 9223372036854775939 9223372036854775963 9223372036854776063 9223372036854776077 9223372036854776167 9223372036854776243 9223372036854776257 9223372036854776261 9223372036854776293 9223372036854776299 18446744073709551557 18446744073709551629 18446744073709551653 2 3 5 7 2 3 5 7 1267650600228229401496703205653 1267650600228229401496703205707 1267650600228229401496703205653 1267650600228229401496703205707 2 3 4294967311 18446744073709551557 18446744073709551629 18446744073709551653 2 7 17 2 7 17 1267650600228229401496703205653 1267650600228229401496703205707 1267650600228229401496703205653 1267650600228229401496703205707 18446744073709551533 18446744073709551653 18446744073709551923 600000041 100000007 100000007 1500301459763 21129350719583 60387449239223 109460072388773 2 5 0.50000000000000000000000000000000000000 1.5000000000000000000000000000000000000 2.5000000000000000000000000000000000000 3 6 9 12 5 3 1 1 2 5 6 9 10 2 5 8 2 7 12 17 2 7 12 17 210 *** at top-level: forprime(p=2,10,p=4) *** ^-- *** prime index read-only: was changed to 4. 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 1 2 3 4 5 6 7 8 9 10 [1, 0, 0]~ [0, 1, 0]~ [0, 0, 1]~ 4 10 4 6 8 9 10 6 8 9 10 6 8 9 10 12 6 8 9 6 8 9 6 *** at top-level: forcomposite(a=6,12,print(a);a=1) *** ^------------- *** index read-only: was changed to 1. [1, 5] [1, 6] [1, 7] [1, 8] [2, 5] [2, 7] [2, 8] [3, 5] [4, 5] [100000, [2, 5; 5, 5]] [100001, [11, 1; 9091, 1]] [100002, [2, 1; 3, 1; 7, 1; 2381, 1]] [100003, Mat([100003, 1])] [100004, [2, 2; 23, 1; 1087, 1]] [100005, [3, 1; 5, 1; 59, 1; 113, 1]] [100006, [2, 1; 31, 1; 1613, 1]] [100007, [97, 1; 1031, 1]] [100008, [2, 3; 3, 3; 463, 1]] [100009, [7, 2; 13, 1; 157, 1]] [100010, [2, 1; 5, 1; 73, 1; 137, 1]] [-3, [-1, 1; 3, 1]] [-2, [-1, 1; 2, 1]] [-1, Mat([-1, 1])] [-3, [-1, 1; 3, 1]] [-3, [-1, 1; 3, 1]] [-2, [-1, 1; 2, 1]] [-1, Mat([-1, 1])] [0, Mat([0, 1])] [-3, [-1, 1; 3, 1]] [-2, [-1, 1; 2, 1]] [-3, [-1, 1; 3, 1]] [-2, [-1, 1; 2, 1]] [-1, Mat([-1, 1])] [-3, [-1, 1; 3, 1]] [-2, [-1, 1; 2, 1]] [-1, Mat([-1, 1])] [0, Mat([0, 1])] [1, matrix(0,2)] [2, Mat([2, 1])] [-3, [-1, 1; 3, 1]] [-2, [-1, 1; 2, 1]] [-3, [-1, 1; 3, 1]] [-2, [-1, 1; 2, 1]] [-1, Mat([-1, 1])] [-3, [-1, 1; 3, 1]] [-2, [-1, 1; 2, 1]] [-1, Mat([-1, 1])] [0, Mat([0, 1])] [0, Mat([0, 1])] [1, matrix(0,2)] [2, Mat([2, 1])] [0, Mat([0, 1])] [223092868, [2, 2; 4801, 1; 11617, 1]] [223092869, [37, 1; 131, 1; 46027, 1]] [223092870, [2, 1; 3, 1; 5, 1; 7, 1; 11, 1; 13, 1; 17, 1; 19, 1; 23, 1]] [223092871, [317, 1; 703763, 1]] [-5, [-1, 1; 5, 1]] [-3, [-1, 1; 3, 1]] [-2, [-1, 1; 2, 1]] [-1, Mat([-1, 1])] [1, matrix(0,2)] [2, Mat([2, 1])] [3, Mat([3, 1])] [5, Mat([5, 1])] [100001, [11, 1; 9091, 1]] [100002, [2, 1; 3, 1; 7, 1; 2381, 1]] [100003, Mat([100003, 1])] [100005, [3, 1; 5, 1; 59, 1; 113, 1]] [100006, [2, 1; 31, 1; 1613, 1]] [100007, [97, 1; 1031, 1]] [100010, [2, 1; 5, 1; 73, 1; 137, 1]] [-100010, [-1, 1; 2, 1; 5, 1; 73, 1; 137, 1]] [-100007, [-1, 1; 97, 1; 1031, 1]] [-100006, [-1, 1; 2, 1; 31, 1; 1613, 1]] [-100005, [-1, 1; 3, 1; 5, 1; 59, 1; 113, 1]] [-100003, [-1, 1; 100003, 1]] [-100002, [-1, 1; 2, 1; 3, 1; 7, 1; 2381, 1]] [-100001, [-1, 1; 11, 1; 9091, 1]] 607926 607926 *** at top-level: foreach(x^2+1,x,) *** ^----------------- *** foreach: incorrect type in foreach (t_POL). Total time spent: 2469 pari-2.17.2/src/test/32/polmod0000644000175000017500000000756714567450071014423 0ustar billbillMod(x + 1/3, 2*x^2 + x + 1) Mod(15/16*x + 21/32, 2*x^2 + x + 1) Mod(1/2*x - 1/4, 2*x^2 + x + 1) Mod(-2*x, 2*x^2 + x + 1) Mod(-1/4*x - 3/8, 2*x^2 + x + 1) Mod(1, 2*x^2 + x + 1) Mod(4/3*x^2 - 1/6, 2*x^3 + x + 1) Mod(-39/103*x^2 + 93/103*x + 183/206, 2*x^3 + x + 1) Mod(3/2*x^2 - 1/2*x - 3/4, 2*x^3 + x + 1) Mod(2*x^2 - 2*x + 2, 2*x^3 + x + 1) Mod(-5/4*x^2 - 9/4*x - 7/8, 2*x^3 + x + 1) Mod(1, 2*x^3 + x + 1) Mod(Mod(6, 17)*x^2 + Mod(7, 17)*x + Mod(4, 17), Mod(2, 17)*x^3 + Mod(1, 17)* x + Mod(1, 17)) Mod(Mod(3, 17)*x^2 + Mod(16, 17)*x + Mod(6, 17), Mod(2, 17)*x^3 + Mod(1, 17) *x + Mod(1, 17)) Mod(Mod(15, 17)*x^2 + Mod(13, 17)*x + Mod(8, 17), Mod(2, 17)*x^3 + Mod(1, 17 )*x + Mod(1, 17)) Mod(Mod(8, 17)*x^2 + Mod(13, 17)*x + Mod(1, 17), Mod(2, 17)*x^3 + Mod(1, 17) *x + Mod(1, 17)) Mod(Mod(16, 17)*x^2 + Mod(10, 17), Mod(2, 17)*x^3 + Mod(1, 17)*x + Mod(1, 17 )) Mod(Mod(1, 17), Mod(2, 17)*x^3 + Mod(1, 17)*x + Mod(1, 17)) Mod(Mod(9223372036854775829, 18446744073709551629)*x^2 + Mod(7, 184467440737 09551629)*x + Mod(9223372036854775827, 18446744073709551629), Mod(2, 1844674 4073709551629)*x^3 + Mod(1, 18446744073709551629)*x + Mod(1, 184467440737095 51629)) Mod(Mod(9746969576064872258, 18446744073709551629)*x^2 + Mod(103913973166311 44804, 18446744073709551629)*x + Mod(12445510739686138545, 18446744073709551 629), Mod(2, 18446744073709551629)*x^3 + Mod(1, 18446744073709551629)*x + Mo d(1, 18446744073709551629)) Mod(Mod(9223372036854775821, 18446744073709551629)*x^2 + Mod(922337203685477 5819, 18446744073709551629)*x + Mod(8, 18446744073709551629), Mod(2, 1844674 4073709551629)*x^3 + Mod(1, 18446744073709551629)*x + Mod(1, 184467440737095 51629)) Mod(Mod(11980875016945378893, 18446744073709551629)*x^2 + Mod(95086309658296 65788, 18446744073709551629)*x + Mod(6656041676080766052, 184467440737095516 29), Mod(2, 18446744073709551629)*x^3 + Mod(1, 18446744073709551629)*x + Mod (1, 18446744073709551629)) Mod(Mod(4611686018427387936, 18446744073709551629)*x^2 + Mod(461168601842738 7920, 18446744073709551629)*x + Mod(9223372036854775833, 1844674407370955162 9), Mod(2, 18446744073709551629)*x^3 + Mod(1, 18446744073709551629)*x + Mod( 1, 18446744073709551629)) Mod(Mod(1, 18446744073709551629), Mod(2, 18446744073709551629)*x^3 + Mod(1, 18446744073709551629)*x + Mod(1, 18446744073709551629)) Mod(1/4, t)*x^2 + Mod(1, t)*x + Mod(1, t) Mod(0, 1) Mod(Mod(0, 2), 1) Mod(y, x) Mod(1/y, x) Mod(O(y), x) Mod(1, y)*x Mod(1, y)/(Mod(1, y)*x) Mod(1, y) *** at top-level: Mod(1+O(y),y+1) *** ^--------------- *** Mod: forbidden division t_SER % t_POL. Mod(0, 7) Mod(0, 7) Mod(0, 1) Mod(-1, x - 1) 36893488147419103232 a [Mod(1/2*x, x^2 - 2)] Mod(Mod(0, 7), 7*y + 1) Mod(2*x^2 + 2*x + 3911007273354184253048119277980437655011530975589157021368 1416768227344707964530933664461531432819485063457998863299208897130431601916 9012649397423944130791988683621977066638621129248621055539080279603792825134 3989101528523909571086209505240745482570999208257316363252069036483644403870 3682023744710898497913308693075694000603070229413334049123522930662615362938 1757351574210585100503110888300778749244514626438127612885813990432259580468 018382892565189700020861075312268670454757806930366351117, x^4 + x^3 + x^2 + 2*x + 1) Mod(2*x^2 + 2*x + 1688783551193734882643358005264268224496699289284988569676 8706440336136525976261075318513696652827406883336492943280027486259114788378 6272577895773212769741268090936776870515273462153041660394611531667597848189 7114809059144720018484127517300606465789652185929623897088281175220904636490 3470210964450018878650074591624939506243891584469076776743491709064234887811 66160116888528036738807730709203142810389700524543565487, x^4 + x^3 + x^2 + 2*x + 1) 524287/2*z^21 + 405549*z^20 + 1/2*z^19 + 237477/2*z^18 + 524287/2*z^17 + 524 287/2*z^14 + 237477/2*z^12 + 524287/2*z^11 + 1/2*z^10 + 118739*z^9 + 524287/ 2*z^7 + 1/2*z^4 + 118739*z^3 + 524287/2*z^2 + 286811/2*z + 524287/2 Total time spent: 16 pari-2.17.2/src/test/32/galpol0000644000175000017500000000253314567450071014373 0ustar billbill5 C8:[[Vecsmall([4, 5, 8, 7, 3, 2, 6, 1])], Vecsmall([8])]:[x^8 - x^7 - 7*x^6 + 6*x^5 + 15*x^4 - 10*x^3 - 10*x^2 + 4*x + 1, 1] C4 x C2:[[Vecsmall([3, 1, 5, 7, 2, 4, 8, 6]), Vecsmall([4, 6, 7, 1, 8, 2, 3, 5])], Vecsmall([4, 2])]:[x^8 - 7*x^6 + 14*x^4 - 8*x^2 + 1, 1] D8:[[Vecsmall([6, 1, 5, 2, 7, 4, 8, 3]), Vecsmall([3, 5, 1, 7, 2, 8, 4, 6])] , Vecsmall([4, 2])]:[x^8 - 4*x^7 - 8*x^6 + 24*x^5 + 30*x^4 - 16*x^3 - 20*x^2 + 2, 3] Q8:[[Vecsmall([4, 6, 2, 8, 1, 7, 3, 5]), Vecsmall([2, 8, 5, 3, 6, 4, 1, 7])] , Vecsmall([4, 2])]:[x^8 - 12*x^6 + 36*x^4 - 36*x^2 + 9, 3] C2 x C2 x C2:[[Vecsmall([2, 1, 4, 3, 6, 5, 8, 7]), Vecsmall([5, 6, 7, 8, 1, 2, 3, 4]), Vecsmall([3, 4, 1, 2, 7, 8, 5, 6])], Vecsmall([2, 2, 2])]:[x^8 - 12*x^6 + 23*x^4 - 12*x^2 + 1, 7] [x^8 + 8*x^6 + 20*x^4 + 16*x^2 + 2, 1] [x^8 - x^7 + x^5 - x^4 + x^3 - x + 1, 1] [x^8 + 3*x^4 + 1, 1] [x^8 + 12*x^6 + 36*x^4 + 36*x^2 + 9, 3] [x^8 - x^4 + 1, 1] [96, 161] *** at top-level: galoisgetpol(8,6) *** ^----------------- *** galoisgetpol: domain error in galoisgetpol: group index > 5 *** at top-level: galoisgetpol(3,1,3) *** ^------------------- *** galoisgetpol: invalid flag in galoisgetpol. *** at top-level: galoisgetpol(3,1,2) *** ^------------------- *** galoisgetpol: domain error in galoisgetpol: s > 1 Total time spent: 2728 pari-2.17.2/src/test/32/qfcvp0000644000175000017500000000055614676526175014251 0ustar billbillCases that should fail: *** at top-level: qfcvp(Mat(),[1.5]~,2.25) *** ^------------------------ *** qfcvp: incorrect type in cvp0 [different dimensions] (t_COL). *** at top-level: qfcvp(Q,[1.5,5]~,2.25) *** ^---------------------- *** qfcvp: incorrect type in cvp0 [different dimensions] (t_COL). Total time spent: 2 pari-2.17.2/src/test/32/err0000644000175000017500000007045014760123736013710 0ustar billbill *** at top-level: g(10) *** ^----- *** in function g: for(i=-N,N,f(i)) *** ^----- *** in function f: 1/x *** ^-- *** _/_: impossible inverse in gdiv: 0. *** at top-level: f(Mat(0),Col(1)) *** ^---------------- *** in function f: matsolve *** ^-------- *** matsolve: impossible inverse in gauss: Mat(0). *** at top-level: (matsolve)(Mat(0),Col(1)) *** ^------------------------ *** matsolve: impossible inverse in gauss: Mat(0). *** at top-level: g(I) *** ^---- *** in function g: [x.foo] *** ^---- *** in member function foo: 1/(1+a^2) *** ^-------- *** _/_: impossible inverse in gdiv: 0. *** at top-level: (x->1/x)(0) *** ^---------- *** in anonymous function: 1/x *** ^-- *** _/_: impossible inverse in gdiv: 0. 274177 274177 *** at top-level: ...=2;A=x^2+1;B=[x+t,x+t];r=polhensellift(A,B,[p, *** ^--------------------- *** polhensellift: elements not coprime in BuildTree: x + t x + t *** at top-level: M[,1]=1 *** ^------- *** incorrect type in matrix col assignment (t_INT). *** at top-level: M[,3]=1 *** ^------ *** nonexistent component: index > 2 *** at top-level: M[,1]=[1,2] *** ^----------- *** incorrect type in matrix col assignment (t_VEC). *** at top-level: M[,1]=[1,2,3]~ *** ^-------------- *** inconsistent dimensions in matrix col assignment. *** at top-level: M[1,]=1 *** ^------- *** incorrect type in matrix row assignment (t_INT). *** at top-level: M[3,]=1 *** ^------ *** nonexistent component: index > 2 *** at top-level: M[1,]=[1,2]~ *** ^------------ *** incorrect type in matrix row assignment (t_COL). *** at top-level: M[1,]=[1,2,3] *** ^------------- *** inconsistent dimensions in matrix row assignment. *** at top-level: [;][1,] *** ^---- *** nonexistent component: index > 0 *** at top-level: [;][,1] *** ^---- *** nonexistent component: index > 0 *** at top-level: 1[1] *** ^--- *** incorrect type in _[_] OCcompo1 [not a vector] (t_INT). *** at top-level: issquare(1,&v[1]) *** ^---- *** incorrect type in &_[_] OCcompo1ptr [not a vector] (t_POL). *** at top-level: 1[1,1] *** ^----- *** incorrect type in _[_,_] OCcompo2 [not a matrix] (t_INT). *** at top-level: 1[,1] *** ^---- *** incorrect type in _[,_] OCcompoC [not a matrix] (t_INT). *** at top-level: issquare(1,&v[,1]) *** ^----- *** incorrect type in &_[,_] OCcompoCptr [not a matrix] (t_POL). *** at top-level: 1[1,] *** ^---- *** incorrect type in _[_,] OCcompoL [not a matrix] (t_INT). *** at top-level: issquare(1,&v[1,]) *** ^----- *** incorrect type in &_[_,] OCcompoLptr [not a matrix] (t_POL). *** at top-level: v[2]=1 *** ^----- *** nonexistent component: index > 1 *** at top-level: v[1]=Pi *** ^------- *** incorrect type in t_VECSMALL assignment (t_REAL). *** at top-level: v[1]=2^64 *** ^--------- *** incorrect type in t_VECSMALL assignment (t_INT). *** at top-level: v[Pi]=1 *** ^----- *** incorrect type in gtos [integer expected] (t_REAL). [1 0] [0 1] *** at top-level: addprimes(1.) *** ^------------- *** addprimes: incorrect type in addprimes [integer vector] (t_VEC). *** at top-level: nfalgtobasis(nfinit(t^3-2),Mod(t,t^2+1)) *** ^---------------------------------------- *** nfalgtobasis: inconsistent moduli in algtobasis: t^3 - 2 != t^2 + 1 *** at top-level: vector(-1,i,0) *** ^-------------- *** vector: domain error in vector: dimension < 0 *** at top-level: vectorv(-1,i,0) *** ^--------------- *** vectorv: domain error in vector: dimension < 0 *** at top-level: vectorsmall(-1,i,0) *** ^------------------- *** vectorsmall: domain error in vectorsmall: dimension < 0 *** at top-level: matrix(-1,1,i,j,0) *** ^------------------ *** matrix: domain error in matrix: nbrows < 0 *** at top-level: matrix(1,-1,i,j,0) *** ^------------------ *** matrix: domain error in matrix: nbcols < 0 *** at top-level: next(-1) *** ^-------- *** next: domain error in next: n < 1 *** at top-level: break(-1) *** ^--------- *** break: domain error in break: n < 1 *** at top-level: v[-1] *** ^---- *** nonexistent component: index < 1 *** at top-level: v[#v+1] *** ^------ *** nonexistent component: index > 1 *** variable name expected: subst(x,1,0) *** ^---- *** at top-level: exp(1e40) *** ^--------- *** exp: overflow in expo(). *** at top-level: exp(-1e40) *** ^---------- *** exp: overflow in expo(). *** at top-level: exp(1/x) *** ^-------- *** exp: domain error in exp: valuation < 0 *** at top-level: cos(1/x) *** ^-------- *** cos: domain error in cos: valuation < 0 *** at top-level: sin(1/x) *** ^-------- *** sin: domain error in sin: valuation < 0 *** at top-level: tan(1/x) *** ^-------- *** tan: domain error in tan: valuation < 0 *** at top-level: cotan(1/x) *** ^---------- *** cotan: domain error in cotan: valuation < 0 *** at top-level: atan(1/x) *** ^--------- *** atan: domain error in atan: valuation < 0 *** at top-level: asin(1/x) *** ^--------- *** asin: domain error in asin: valuation < 0 *** at top-level: acos(1/x) *** ^--------- *** acos: domain error in acos: valuation < 0 *** at top-level: asinh(1/x) *** ^---------- *** asinh: domain error in asinh: valuation < 0 *** at top-level: acosh(1/x) *** ^---------- *** acosh: domain error in acosh: valuation < 0 *** at top-level: atanh(1/x) *** ^---------- *** atanh: domain error in atanh: valuation < 0 *** at top-level: lngamma(x) *** ^---------- *** lngamma: domain error in lngamma: valuation != 0 *** at top-level: besselj(2,1/x) *** ^-------------- *** besselj: domain error in besselj: valuation < 0 *** at top-level: besseljh(2,1/x) *** ^--------------- *** besseljh: domain error in besseljh: valuation < 0 *** at top-level: besselk(2,1/x) *** ^-------------- *** besselk: domain error in besselk: valuation < 0 *** at top-level: besselk(1/3,O(x)) *** ^----------------- *** besselk: domain error in besselk: 2n mod Z != 0 *** at top-level: besseln(2,1/x) *** ^-------------- *** besseln: domain error in besseln: valuation < 0 *** at top-level: besseln(1/3,O(x)) *** ^----------------- *** besseln: domain error in besseln: 2n mod Z != 0 *** at top-level: polylog(2,1/x) *** ^-------------- *** polylog: domain error in polylog: valuation < 0 *** at top-level: sqrt(x) *** ^------- *** sqrt: domain error in sqrtn: valuation != Mod(0, 2) *** at top-level: sqrt(2+O(2^2)) *** ^-------------- *** sqrt: not an n-th power residue in Qp_sqrt: 2 + O(2^2). *** at top-level: sqrtn(x,3) *** ^---------- *** sqrtn: domain error in sqrtn: valuation != Mod(0, 3) *** at top-level: sqrtn(2+O(2^2),3) *** ^----------------- *** sqrtn: not an n-th power residue in gsqrtn: 2 + O(2^2). *** at top-level: log(x) *** ^------ *** log: domain error in log: series valuation != 0 *** at top-level: log(0) *** ^------ *** log: domain error in log: argument = 0 *** at top-level: abs(x+O(x^2)) *** ^------------- *** abs: domain error in abs: series valuation != 0 *** at top-level: real(Vecsmall([])) *** ^------------------ *** real: incorrect type in greal/gimag (t_VECSMALL). *** at top-level: imag(Vecsmall([])) *** ^------------------ *** imag: incorrect type in greal/gimag (t_VECSMALL). *** at top-level: vecmax(Vecsmall([])) *** ^-------------------- *** vecmax: domain error in vecmax: empty argument = Vecsmall([]) *** at top-level: vecmax([]) *** ^---------- *** vecmax: domain error in vecmax: empty argument = [] *** at top-level: vecmax([],&i) *** ^------------- *** vecmax: domain error in vecmax: empty argument = [] *** at top-level: vecmin(Vecsmall([])) *** ^-------------------- *** vecmin: domain error in vecmin: empty argument = Vecsmall([]) *** at top-level: vecmin([]) *** ^---------- *** vecmin: domain error in vecmin: empty argument = [] *** unexpected character '&': vecmmin([],&i) *** ^--- *** at top-level: vecmax(matrix(0,2)) *** ^------------------- *** vecmax: domain error in vecmax: empty argument = matrix(0,2) *** at top-level: listput(L,x,-1) *** ^--------------- *** listput: nonexistent component in listput: index < 0 *** at top-level: listinsert(L,x,-1) *** ^------------------ *** listinsert: nonexistent component in listinsert: index <= 0 *** at top-level: ellj(Mod(1,2)) *** ^-------------- *** ellj: incorrect type in modular function (t_INTMOD). *** at top-level: ellj(Qfb(1,1,1)) *** ^---------------- *** ellj: incorrect type in ellj (t_QFB). *** at top-level: eta(1+O(2)) *** ^----------- *** eta: domain error in eta: v_p(q) <= 0 *** at top-level: eta(1/x) *** ^-------- *** eta: domain error in eta: v_p(q) <= 0 *** at top-level: idealhnf(K,Qfb(1,1,1)) *** ^---------------------- *** idealhnf: domain error in idealhnf [Qfb]: disc(q) != -4 *** at top-level: idealfactor(K,[;]) *** ^------------------ *** idealfactor: domain error in idealfactor: ideal = 0 *** at top-level: idealdiv(K,2,0,1) *** ^----------------- *** idealdiv: impossible inverse in idealdivexact: 0. *** at top-level: valuation(Pi,2) *** ^--------------- *** valuation: inconsistent valuation t_REAL , t_INT. *** at top-level: x^Pi *** ^--- *** _^_: domain error in gpow [irrational exponent]: valuation != 0 *** at top-level: x^x *** ^-- *** _^_: domain error in gpow [irrational exponent]: valuation != 0 *** at top-level: 0^0. *** ^--- *** _^_: domain error in gpow(0,n): n <= 0 *** at top-level: agm([],[]) *** ^---------- *** agm: forbidden agm t_VEC (0 elts) , t_VEC (0 elts). *** at top-level: sin(1/2+O(2^1)) *** ^--------------- *** sin: domain error in gsin(t_PADIC): argument out of range *** at top-level: cos(1/9+O(3^1)) *** ^--------------- *** cos: domain error in gcos(t_PADIC): argument out of range *** at top-level: exp(1/9+O(3^1)) *** ^--------------- *** exp: domain error in gexp(t_PADIC): argument out of range *** at top-level: ...],Vecsmall([2,2,2,2,3])];galoissubgroups(G) *** ^------------------ *** galoissubgroups: sorry, group_quotient for a non-WSS group is not yet implemented. *** at top-level: bnrstark(bnrinit(bnfinit(y^2+1),2)) *** ^----------------------------------- *** bnrstark: domain error in bnrstark: r2 != 0 *** at top-level: bnrstark(bnrinit(bnfinit(y^2-2),[4,[1,1]])) *** ^------------------------------------------- *** bnrstark: domain error in bnrstark: r2(class field) != 0 *** at top-level: quadray(-16,1) *** ^-------------- *** quadray: domain error in quadray: isfundamental(D) = 0 *** at top-level: quadray(bnfinit(x^3-2),1) *** ^------------------------- *** quadray: domain error in quadray: degree != 2 *** at top-level: galoissubcyclo(-1) *** ^------------------ *** galoissubcyclo: domain error in galoissubcyclo: degree <= 0 *** at top-level: galoissubcyclo(6,Mod(1,3)) *** ^-------------------------- *** galoissubcyclo: inconsistent moduli in galoissubcyclo: 6 != 3 *** at top-level: galoissubcyclo(6,[;]) *** ^--------------------- *** galoissubcyclo: incorrect type in galoissubcyclo [H not in HNF] (t_MAT). *** at top-level: galoissubcyclo(6,Mat(1)) *** ^------------------------ *** galoissubcyclo: incorrect type in galoissubcyclo [N not a bnrinit or znstar] (t_MAT). *** at top-level: galoissubcyclo(znstar(5),matid(2)) *** ^---------------------------------- *** galoissubcyclo: inconsistent dimensions in galoissubcyclo. *** at top-level: galoissubcyclo([3,[3],[3]],Mat(3)) *** ^---------------------------------- *** galoissubcyclo: incorrect type in galoissubcyclo (t_VEC). *** at top-level: galoissubcyclo(bnrinit(bnfinit(y^2+1),1),2) *** ^------------------------------------------- *** galoissubcyclo: domain error in bnr_to_abgrp: bnr != Q *** at top-level: polsubcyclo(-1,2) *** ^----------------- *** polsubcyclo: domain error in polsubcyclo: n <= 0 *** at top-level: polsubcyclo(2,-1) *** ^----------------- *** polsubcyclo: domain error in polsubcyclo: d <= 0 *** at top-level: random(0) *** ^--------- *** random: domain error in random: N = 0 *** at top-level: znprimroot(0) *** ^------------- *** znprimroot: domain error in znprimroot: argument = 0 *** at top-level: sqrtint(-1) *** ^----------- *** sqrtint: domain error in sqrtint: argument < 0 *** at top-level: sqrtnint(-1,2) *** ^-------------- *** sqrtnint: domain error in sqrtint: argument < 0 *** at top-level: sqrtnint(2,-2) *** ^-------------- *** sqrtnint: domain error in sqrtnint: n <= 0 *** at top-level: znprimroot(8) *** ^------------- *** znprimroot: domain error in znprimroot: n = 8 *** at top-level: polroots(x^2+Mod(1,2)) *** ^---------------------- *** polroots: incorrect type in roots (t_INTMOD). *** at top-level: polroots(0) *** ^----------- *** polroots: zero polynomial in roots. *** at top-level: polroots(Mod(1,2)) *** ^------------------ *** polroots: incorrect type in roots (t_INTMOD). *** at top-level: polrootsmod(x,x) *** ^---------------- *** polrootsmod: incorrect type in factormod (t_POL). *** at top-level: prime(-2) *** ^--------- *** prime: domain error in prime: n <= 0 *** at top-level: addprimes(-1) *** ^------------- *** addprimes: domain error in addprimes: p < 2 *** at top-level: padicappr(x^2+1+O(3^5),1+O(5)) *** ^------------------------------ *** padicappr: inconsistent moduli in Zp_to_Z: 5 != 3 *** at top-level: factorpadic(x^2+1,2,-1) *** ^----------------------- *** factorpadic: domain error in factorpadic: precision <= 0 *** at top-level: polrootspadic(x^2+1,2,-1) *** ^------------------------- *** polrootspadic: domain error in polrootspadic: precision <= 0 *** at top-level: ellinit([1+O(3),1+O(5)]) *** ^------------------------ *** ellinit: inconsistent moduli in ellinit: 3 != 5 *** at top-level: ellwp([1,I],I) *** ^-------------- *** ellwp: domain error in ellwp: argument = 0 *** at top-level: ellsigma([1,I],x,1) *** ^------------------- *** ellsigma: incorrect type in log(ellsigma) (t_SER). *** at top-level: ellsigma([1,I],1,1) *** ^------------------- *** ellsigma: domain error in log(ellsigma): argument = 0 *** at top-level: ellap(E) *** ^-------- *** ellap: incorrect type in ellap [can't determine p] (t_VEC). *** at top-level: ellap(E,1) *** ^---------- *** ellap: domain error in ellap: p < 2 *** at top-level: ellap(E,'x) *** ^----------- *** ellap: incorrect type in ellap (t_POL). *** at top-level: ellissupersingular(x,1) *** ^----------------------- *** ellissupersingular: incorrect type in checkell (t_POL). *** at top-level: elltaniyama(E,-1) *** ^----------------- *** elltaniyama: domain error in elltaniyama: precision < 0 *** at top-level: ellheight(E,[2,2]) *** ^------------------ *** ellheight: domain error in ellheight: point not on E *** at top-level: ellheight(E,,[2,2]) *** ^------------------- *** ellheight: cannot omit P and set Q. *** at top-level: Qfb(0,0,0) *** ^---------- *** Qfb: domain error in Qfb: issquare(disc) = 1 *** at top-level: quadpoly(2) *** ^----------- *** quadpoly: domain error in quadpoly: disc % 4 > 1 *** at top-level: qfbprimeform(2,5) *** ^----------------- *** qfbprimeform: domain error in primeform: disc % 4 > 1 *** at top-level: qfbcomp(Qfb(1,1,1),Qfb(1,0,2)) *** ^------------------------------ *** qfbcomp: inconsistent multiplication t_QFB * t_QFB. *** at top-level: galoisinit(x^2) *** ^--------------- *** galoisinit: domain error in galoisinit: issquarefree(pol) = 0 *** at top-level: galoisinit(2*x) *** ^--------------- *** galoisinit: sorry, galoisinit(nonmonic) is not yet implemented. *** at top-level: ellL1(1,-1) *** ^----------- *** ellL1: domain error in ellL1: derivative order < 0 *** at top-level: ellheegner(ellinit([0,-1,1,-10,-20])) *** ^------------------------------------- *** ellheegner: domain error in ellheegner: (analytic rank)%2 = 0 *** at top-level: ellheegner(ellinit([0,0,1,-7,6])) *** ^--------------------------------- *** ellheegner: domain error in ellheegner: analytic rank > 1 *** at top-level: substpol(x+O(x^2),x^3,x) *** ^------------------------ *** substpol: domain error in gdeflate: valuation(x) % 3 != 0 *** at top-level: intformal(1/(x^2+1)) *** ^-------------------- *** intformal: domain error in intformal: residue(series, pole) != 0 *** at top-level: component(x,-1) *** ^--------------- *** component: nonexistent component: index < 1 *** at top-level: component(O(x),2) *** ^----------------- *** component: nonexistent component: index > 0 *** at top-level: component(Vecsmall([]),1) *** ^------------------------- *** component: nonexistent component: index > 0 *** at top-level: component(x->x,6) *** ^----------------- *** component: nonexistent component: index > 5 *** at top-level: polcoef(O(x),2) *** ^--------------- *** polcoef: domain error in polcoef: t_SER = O(x) *** at top-level: polcoef(x+O(x^2),2) *** ^------------------- *** polcoef: domain error in polcoef: degree > 1 *** at top-level: polcoef([],2) *** ^------------- *** polcoef: incorrect type in polcoef (t_VEC). *** at top-level: matcompanion(0*x) *** ^----------------- *** matcompanion: domain error in matcompanion: polynomial = 0 *** at top-level: matrixqz(Mat([1,2])) *** ^-------------------- *** matrixqz: domain error in QM_minors_coprime: n > m *** at top-level: matrixqz(Mat(0)) *** ^---------------- *** matrixqz: domain error in QM_minors_coprime: rank(A) < 1 *** at top-level: vecextract([1],[-1]) *** ^-------------------- *** vecextract: nonexistent component in vecextract: index <= 0 *** at top-level: vecextract([1],[2]) *** ^------------------- *** vecextract: nonexistent component in vecextract: index >= 2 *** at top-level: idealfrobenius(K,galoisinit(K),idealprimedec(K *** ^---------------------------------------------- *** idealfrobenius: domain error in idealfrobenius: pr.e > 1 *** at top-level: nfisincl(x^2,x^2+1) *** ^------------------- *** nfisincl: not an irreducible polynomial in nfisincl: x^2. *** at top-level: polcompositum(x^2,x) *** ^-------------------- *** polcompositum: domain error in polcompositum: issquarefree(arg) = 0 *** at top-level: rnfdedekind(K,x^2+x-1/3) *** ^------------------------ *** rnfdedekind: incorrect type in rnfdedekind [non integral pol] (t_POL). *** at top-level: hilbert(Mod(1,2),1) *** ^------------------- *** hilbert: precision too low in hilbert. *** at top-level: hilbert(Mod(1,3),Mod(1,5)) *** ^-------------------------- *** hilbert: inconsistent moduli in hilbert: 5 != 3 *** at top-level: hilbert(Mod(1,3),2,0) *** ^--------------------- *** hilbert: inconsistent moduli in hilbert: 3 != "oo" *** at top-level: znorder(0) *** ^---------- *** znorder: incorrect type in znorder [t_INTMOD expected] (t_INT). *** at top-level: znorder(Mod(2,4)) *** ^----------------- *** znorder: elements not coprime in znorder: 2 4 *** at top-level: contfrac(1e100) *** ^--------------- *** contfrac: precision too low in gboundcf. *** at top-level: contfrac(1.,[1],10) *** ^------------------- *** contfrac: inconsistent dimensions in contfrac [too few denominators]. *** at top-level: contfrac(1,,-1) *** ^--------------- *** contfrac: domain error in gboundcf: nmax < 0 *** at top-level: contfracpnqn(matrix(3,1)) *** ^------------------------- *** contfracpnqn: inconsistent dimensions in pnqn [ nbrows != 1,2 ]. *** at top-level: divisors(1/2) *** ^------------- *** divisors: incorrect type in divisors [denominator] (t_FRAC). *** at top-level: idealstar(K,0) *** ^-------------- *** idealstar: domain error in idealfactor: ideal = 0 *** at top-level: idealstar(K,1/2) *** ^---------------- *** idealstar: domain error in Idealstar: denominator(ideal) != 1 *** at top-level: idealaddtoone(K,[[;]]) *** ^---------------------- *** idealaddtoone: domain error in idealaddmultoone: sum(ideals) != 1 *** at top-level: idealdiv(K,1,2,1) *** ^----------------- *** idealdiv: domain error in idealdivexact: denominator(x/y) != 1 *** at top-level: idealred(K,matid(2),[]) *** ^----------------------- *** idealred: inconsistent dimensions in idealred. *** at top-level: idealtwoelt(K,matid(2),1/2) *** ^--------------------------- *** idealtwoelt: domain error in idealtwoelt2: element mod ideal != 0 *** at top-level: rnf=rnfinit(K,x^2-y);rnfeltdown(rnf,x) *** ^----------------- *** rnfeltdown: domain error in rnfeltdown: element not in the base field *** at top-level: matid(-1) *** ^--------- *** matid: domain error in matid: size < 0 *** at top-level: polinterpolate([1,1],[2,3],Pi) *** ^------------------------------ *** polinterpolate: domain error in polinterpolate: X[1] = X[2] *** at top-level: modreverse(Mod(-x^3+9*x,x^4-10*x^2+1)) *** ^-------------------------------------- *** modreverse: domain error in modreverse: deg(minpoly(z)) < 4 [;] *** at top-level: concat([1,2],[3,4]~) *** ^-------------------- *** concat: inconsistent concatenation t_VEC (2 elts) , t_COL (2 elts). *** at top-level: concat([]) *** ^---------- *** concat: domain error in concat: vector = [] *** at top-level: concat(List()) *** ^-------------- *** concat: domain error in concat: vector = List([]) *** at top-level: mathnfmod([1;2],2) *** ^------------------ *** mathnfmod: domain error in ZM_hnfmod: nb lines > nb columns *** at top-level: removeprimes(2) *** ^--------------- *** removeprimes: domain error in removeprimes: prime not in primetable *** at top-level: forstep(a=1,2,0,) *** ^----------------- *** forstep: domain error in forstep: step = 0 *** at top-level: e.omega *** ^----- *** _.omega: incorrect type in omega [not defined over C] (t_VEC). *** at top-level: e.eta *** ^--- *** _.eta: incorrect type in eta [not defined over C] (t_VEC). *** at top-level: e.area *** ^---- *** _.area: incorrect type in area [not defined over C] (t_VEC). *** at top-level: e.tate *** ^---- *** _.tate: incorrect type in tate [not defined over Qp] (t_VEC). *** at top-level: ellorder(e,[0,0]*Mod(1,2)) *** ^-------------------------- *** ellorder: sorry, ellorder for curve with singular reduction is not yet implemented. *** at top-level: thue(x*(x^3-2),0) *** ^----------------- *** thue: domain error in thue: #sols = oo *** at top-level: direuler(p=2,10,2/(1-p*X)) *** ^---------- *** domain error in direuler: constant term != 1 *** at top-level: solve(x=0,1,x^2+1) *** ^------ *** domain error in solve: f(a)f(b) > 0 *** user warning: 1 *** at top-level: iferr(1/0,E,1,errname(E)=="e_DOMAIN") *** ^------------------------------------- *** iferr: impossible inverse in gdiv: 0. 4 *** at top-level: iferr(1/0,E,1,break()) *** ^-------- *** break not allowed here. (x)->trap(e_INV,INFINITY,1/x) 1/2 INFINITY *** at top-level: trap(e_INV,INFINITY,log(0)) *** ^------- *** log: domain error in log: argument = 0 *** at top-level: notafunc('a) *** ^------------ *** not a function in function call 1 *** at top-level: znlog(Mod(1,n),Mod(1,n+1)) *** ^-------------------------- *** znlog: inconsistent moduli in Rg_to_Fp: (...) != (...) *** at top-level: Mod(0,n)^(-1) *** ^----- *** _inv: impossible inverse in Fp_inv: (...). *** at top-level: a*b *** ^-- *** _*_: inconsistent multiplication t_POL * t_POL. *** at top-level: a%b *** ^-- *** _%_: inconsistent division t_POL % t_POL. *** at top-level: (a*x^2+b)^2 *** ^-- *** sqr: inconsistent multiplication t_POL * t_POL. *** at top-level: matrank(M) *** ^---------- *** matrank: inconsistent rank t_MAT (2 x 2) , t_POL. *** at top-level: matimage(M) *** ^----------- *** matimage: inconsistent image t_MAT (2 x 2) , t_POL. *** at top-level: matker(M) *** ^--------- *** matker: inconsistent ker t_MAT (2 x 2) , t_POL. *** incorrect value for plothsizes: [ *** ^ *** incorrect value for plothsizes: 1 *** ^- *** incorrect value for plothsizes: [2, *** ^ *** at top-level: Pol(O(17^-1),v0)/Pol([Mod(9,23),O(23^-3)],v0) *** ^----------------------------- *** _/_: inconsistent t_PADIC , t_INTMOD. Total time spent: 11 pari-2.17.2/src/test/32/bnrclassfield0000644000175000017500000003620614676526175015746 0ustar billbill *** Warning: new stack size = 44000000 (41.962 Mbytes). 1 [x^2 - 2] 2 [x^2 - 5, x^2 + 3] 3 [x^4 + (y - 1)*x^2 - 3] 4 [x^2 + 3, x^3 + 3*x + 5] 5 1 6 [1] 7 [1, 1] 8 1 9 [1] 10 [1, 1, 1] 11 1 12 1 13 [1, 1] 14 [x^3 - 24*x + (-2*y + 1), x^3 + 48*x + (-19838*y + 9919)] 15 [x^2 - 7, x^2 - 3, x^2 + 7] 16 1 17 [1] 18 [1, 1, 1] 19 [x^2 + 3, x^4 + 5*x^2 + 5] 20 [1, 1] 21 [1] 22 [1, 1] 23 [1] 24 [1, 1, 1, 1] sanitize 25 [x] [x^2 - 2] hard DLs (#2228) [1, 2, 1624384359015881850161120870813] [1, 4, 3506795120905895253346115478005586436761515635553951033] [x^2 - 1594287814679644276013] 26 x^128 - 16*x^127 - 228*x^126 + 3064*x^125 + 50832*x^124 - 373432*x^123 - 730 2544*x^122 + 21594104*x^121 + 766204924*x^120 + 212292184*x^119 - 5873995830 4*x^118 - 170760151536*x^117 + 3292940546760*x^116 + 18971984731480*x^115 - 130738025225900*x^114 - 1316726409328216*x^113 + 2722481022140880*x^112 + 66 628399984403736*x^111 + 70008277613389744*x^110 - 2448605526808429704*x^109 - 9803699456259235828*x^108 + 53838762598346919864*x^107 + 50957171970140348 3136*x^106 + 254075334990248880992*x^105 - 14637527708137946256820*x^104 - 8 2475407541976968859112*x^103 + 45236250071657695032468*x^102 + 3625411488337 264192466920*x^101 + 19047985734810262862108592*x^100 - 51654839839203088996 853944*x^99 - 1060248680202979534618904528*x^98 - 27207544920157464328669258 64*x^97 + 26725014150579667173782974092*x^96 + 19757914473019010298014416114 4*x^95 + 5775427032731349814695048096*x^94 - 5620826950775937202910233009296 *x^93 - 23818221235751044035246875238248*x^92 + 2496614995306295123610482085 7784*x^91 + 750726891387392444973679090973956*x^90 + 37147375086824804205965 05666464904*x^89 - 497106667601178868745669332882608*x^88 - 1203747002943352 92351389053807364200*x^87 - 709129635774884867328794466641890960*x^86 + 4123 26888658751452750735135397160664*x^85 + 200020882861408082883303430862775045 40*x^84 + 82076392192873046279185442068541264600*x^83 - 11197303027173639808 826565567784489920*x^82 - 1841801180926720822436446258282461160960*x^81 - 10 030183700183896895709225226641637639434*x^80 - 40114894024601677706207815838 779630108840*x^79 + 113639081842807440941183639728148602277404*x^78 + 208056 1714068783617981510807958428868517624*x^77 + 8648477808065015303280417984426 466684326224*x^76 - 13977243672381414476618634071646029564524840*x^75 - 3463 59684536166319199296580086250957641920176*x^74 - 727961748867164932015370770 728660233835181080*x^73 + 1717923860482517243836554759736687164495626932*x^7 2 + 24359904294168484897951860015092965549304870280*x^71 + 10575198513460925 2182263564468042195662852738336*x^70 - 1388167872993753926293326511222208906 64415590928*x^69 - 421796261315883720303005652296547738830768394568*x^68 - 1 4292464538808527800843067950457992747182734361592*x^67 - 4441096343369261157 2474294078439635971830475099844*x^66 + 2279088059705936850906606672010097638 14913086562424*x^65 + 971259100087919708629231377249287259556648705069296*x^ 64 + 6582296272477549559284659013681893161650584606295304*x^63 - 20374169486 878369498601671633217651563183974568252656*x^62 - 15742408636327472224931001 9540777422010998072707675288*x^61 + 2179076691587906828827288853178237589384 0108314525796*x^60 - 409085348487544025097909090366870748693252973295649112* x^59 + 11214160939459953904143650818217453129050026712649878400*x^58 + 22296 300798438039834285980917256499572223738243739999712*x^57 - 56508793340539842 499223173214412235446756286592155863252*x^56 - 35627697628680065818313696500 397295246478138253827382072*x^55 - 47855343706162800611585190391059239949156 73022413996536356*x^54 - 163626373042716534536887265477095044265283473334938 722568*x^53 + 65609627205723812197719873422598211882647878180289938658064*x^ 52 + 120762952578276747148147579855830128544277445437351118688216*x^51 + 333 139654252335337884194998388810240798260740527219196938256*x^50 - 45209953103 11952161599404870460475590430208940546425355958456*x^49 - 106215697382634281 80004725617803204069082139218843099571927356*x^48 + 359195123165091289340127 20414815262474134493415159250285634728*x^47 + 148355170007444474925481014944 8119204029574370735704736890208*x^46 + 5694032336684635337723325702522943113 31512236498136607444329104*x^45 + 186689731333374814532013452810404989236838 2802981691430873884008*x^44 - 9541505434203575017946662918733542907107797431 464488408844713752*x^43 - 36019061385192245840331828377254240744896373056342 605497727923860*x^42 - 82148994981513000222564844797093963686753511496936351 247177399464*x^41 + 54113815672124705589880573157434023804246393100911053504 4833229296*x^40 + 3530528356737769709970833809021907668366824448875203125924 191397448*x^39 - 57647115473573934652425050271914183392509149889386562110584 17174576*x^38 - 417339291218301808385722381832172388793452164898199064395264 65704888*x^37 + 276600986730497064192503477967431991107982651143397431080359 70148468*x^36 + 210939020396720111436241215041193172108495211082742836025618 811174088*x^35 + 16188015797553562792109859689457248930201913298353840929069 7933391936*x^34 + 5240448974350370534024648076176647940056187176952618051237 46077938368*x^33 - 212189870172806425297829169575435345590047033554026773347 3703481988079*x^32 - 1159509177227105754957521902904551717347142625065522273 7980698241895464*x^31 + 3599335541671289848423606910856624888711418623558031 708113659751896920*x^30 + 49167213976698472654795599831482806141526533402302 533989042273716235312*x^29 + 13842235039218507509644611799411228828414236270 0573969235783804623045984*x^28 + 4157969944186456921978522771536340723295806 90323424144558174610231196864*x^27 - 253546561738984321479986511558935556482 493828842181800871628672316661760*x^26 - 29428206051804640906377385461988765 08164002795140528509564213918973587456*x^25 - 339534137522858795070293460828 6792234866417660378030235826535141672635136*x^24 - 2710078144101079057351653 676915619092403042291138044396960928045894708224*x^23 + 23755753263292782137 54124484749342202226425460305635747239213406105282560*x^22 + 432089291303502 23604642028616396910653697853755963866815658624894864236544*x^21 + 521440910 99438288217897000596923405588384761571305832169553637965743050752*x^20 - 363 32091023462972083028987940063915608669516264102001374265476609415790592*x^19 - 3738926330218988637876369895933730738852887935147128496707888526731437670 4*x^18 - 2670029752986810201510977562976486531511945140603398663257734850306 50544128*x^17 - 366955957834541488814852501802943522123331786988470378964715 255317615804416*x^16 + 13695860696438170890159629473438338587272078872746719 60001875927300078043136*x^15 + 149930367520325586675834311736887015175756753 323932699539430334730698489856*x^14 - 51770235496333086980611199163469054487 80789454331268527681992208132178182144*x^13 + 341630894295684906431328824237 5639586847286808263501256959535184230099189760*x^12 + 1215909219521352940174 1736006314683749960605248853624912233089112000872579072*x^11 - 1177411981769 6539833110428620900605700132320256721016947901679931705522126848*x^10 - 1291 6029944249685444818994980288373229506370481457841888768945030517005221888*x^ 9 + 244610851608111385298633043691532798114946631898672111233073967763514122 56768*x^8 - 1196845932312833943314032394304082677668010256206410736625018216 092234940416*x^7 - 357822607416712182139583675158984320849040966925168233217 56592895954404769792*x^6 + 1562925882226342636316834214779143133430932194953 4586083588473969506116435968*x^5 + 32955478139999974001098488939923392497133 086264874944775778918855896316510208*x^4 - 132810536007060819704886616555158 70329158794863024330775273947298401236287488*x^3 - 1635909273165088428972972 8896250202271717207853591724960951713433577932718080*x^2 + 39143579743733780 60486714724337255682967462150454617722605616725132528582656*x + 366077646690 1881901138804270621171088062544906012468181269894733801933766656 27 x^4 + 8*x^2 + 64 28 1 29 1 30 x^8 - x^6 + 4*x^4 + 3*x^2 + 9 31 x^16 + 2*x^15 + 23*x^14 + 2*x^13 + 241*x^12 - 42*x^11 + 1223*x^10 - 46*x^9 + 2984*x^8 + 174*x^7 + 2919*x^6 + 20*x^5 + 419*x^4 - 378*x^3 - 116*x^2 + 394* x + 131 32 1 correct absolute, incorrect relative extension 1 8 1 8 [x^2 + (-28*y^2 + 36*y - 25), x^2 + (-y^2 + 2*y - 5)] [x^2 + (-5*y^2 + 5*y - 3)] segfault bug with character input 1 bug: relative polynomial instead of absolute 12 examples from doc [4, 2] x^8 - 2*x^7 + Mod(-2*y^2 - 4*y - 27, y^3 + 14*y - 1)*x^6 + Mod(2*y^2 + 6*y + 28, y^3 + 14*y - 1)*x^5 + Mod(18*y^2 + 6*y + 177, y^3 + 14*y - 1)*x^4 + Mod (-8*y^2 - 8*y - 40, y^3 + 14*y - 1)*x^3 + Mod(-35*y^2 + 46*y - 296, y^3 + 14 *y - 1)*x^2 + Mod(8*y^2 - 18*y + 4, y^3 + 14*y - 1)*x + Mod(11*y^2 - 82*y + 116, y^3 + 14*y - 1) 1 [24, 12, 12, 2] [x^2 + (-21*y - 105), x^2 + (-5*y - 25), x^2 + (-y - 5), x^2 + (-y - 1)] 1 tough discrete log [x^3 - 1220909029402133157056664768993*x + 228173780956868462063268259363773 647292715351] tough factorization for structure of k(pr)^* [x^3 - 124605152776383880390723164330780836681247395669702932114626903273810 0335653842887163737345746603468166565713887746845621352923776537140672180761 81167534459523573834583687437400009382330108311817598283*x + 377143528906672 9356539838692927482115948230537325657974061964131050584561046525436227324582 0622952576483473221925056061538198425966101542406349670238672049800945490332 6355918086715061533824316389015991356954063061961914858980761767635379232210 677361394668132952855129411876734922669237206671971928041] tough conductor factorization [x^7 + (-2488690901109897064049863992606012618917666942469541293587644*a - 3 063269196991987310447414268221764697286677021432648792509846)*x^4 + (-642192 118585169200748345356330125311089698298235863825539552157786290050345982204* a - 133365494431207575162435475365485400375764861835188466316100940685901556 1780069519)*x^3 + (340232991495144387468334348532066123240992620566063535109 92561405632363362036584637112116210859170932*a - 263138446490595960628601220 91538769030478902628479463404263936798836164724456179145809571515647166048)* x^2 + (159537922162631362359749173993456969734831474582539482651051736195012 22828101532841688538587642592023261187569184359486658*a - 119532340027417020 0791086853737065481226940343547721428140019378449603681196774484283067574482 1586776703165099355158621752)*x + (17500518530049070055430577944332050955678 8260420556567224467767217256477841710392318226018479914381847995053447485426 9596297096541830710839284*a - 2277818608242330547768173463905672593578106563 2356940539281515239333565833639507075733945268717528354911129285649389681284 8395667994815164491), x^7 + (-2488690901109897064049863992606012618917666942 469541293587644*a + 57457829588209024639755027561575207836901007896310749892 2202)*x^4 + (642192118585169200748345356330125311089698298235863825539552157 786290050345982204*a - 69146282572690655087600939732472869266795032011602083 7621457249072725511434087315)*x^3 + (340232991495144387468334348532066123240 99262056606353510992561405632363362036584637112116210859170932*a + 603371437 9857403480969355694474538135457816468508581691525649820446852808649276378292 1687726506336980)*x^2 + (-15953792216263136235974917399345696973483147458253 948265105173619501222828101532841688538587642592023261187569184359486658*a - 279070262190048382438857859367163517857525508937311625465053674039972596400 69277684519214332464178799964352668539518108410)*x + (1750051853004907005543 0577944332050955678826042055656722446776721725647784171039231822601847991438 18479950534474854269596297096541830710839284*a + 197783371382914006031987514 0823772354925693260529135077637492824565900436753498993939599637486319102029 061827331348166409145492209825526003775), x^7 + (-76153100636760396491647925 4136*a - 17450457279632374082134698072858)*x^4 + (29638579109988460158600391 4706038033921370*a + 865584363186737906459373183630751480733673)*x^3 + (-620 5122555182848676136477906642526198746588841812956*a + 6348799923449844511612 452311190705620451406417652188)*x^2 + (5721072833965395266638810750876372287 9320125120778867080968320*a - 5577140923407444224524941238759279100364694560 45573617674380254)*x + (1786120850509865384579306791433240841633233296604069 006055279495102110194*a + 94766359081620270352777674576571427107130313283685 81445426933931128807729), x^7 + (-761531006367603964916479254136*a + 1668892 6273264770117218218818722)*x^4 + (-29638579109988460158600391470603803392137 0*a + 569198572086853304873369268924713446812303)*x^3 + (-620512255518284867 6136477906642526198746588841812956*a - 1255392247863269318774893021783323181 9197995259465144)*x^2 + (-57210728339653952666388107508763722879320125120778 867080968320*a - 61492482068039837511888223138469163291578958116635248475534 8574)*x + (17861208505098653845793067914332408416332332966040690060552794951 02110194*a - 769051505765216165069846066622390186907979803176451243937165443 6026697535)] vector of subgroups [[-x^3 - 8*x + Mod(-y, y^2 + 3299)], [-x^3 - 26*x + Mod(-y, y^2 + 3299)], [x ^3 - x^2 + Mod(1/2*y + 11/2, y^2 + 3299)*x + Mod(-1/2*y + 25/2, y^2 + 3299)] , [-x^3 - 6*x + Mod(-y, y^2 + 3299)]] [-x^3 - 8*x + Mod(-y, y^2 + 3299), -x^3 - 26*x + Mod(-y, y^2 + 3299), x^3 - x^2 + Mod(1/2*y + 11/2, y^2 + 3299)*x + Mod(-1/2*y + 25/2, y^2 + 3299), -x^3 - 6*x + Mod(-y, y^2 + 3299)] [x^6 + 16*x^4 + 64*x^2 + 3299, x^6 + 52*x^4 + 676*x^2 + 3299, x^6 - 2*x^5 + 12*x^4 + 14*x^3 + 830*x^2 - 1512*x + 981, x^6 + 12*x^4 + 36*x^2 + 3299] [] [[x^3 + 3*x + y]] 1 [x^3 + (-3/10*y^3 - 1/2*y^2 + 1/2*y + 19/5)] [x] x x^3 - 2 [[x], [x]] [x, x] [x^3 - 2, x^3 - 2] [x] bad inputs *** at top-level: bnrclassfield(y^2+6,Mat(2)) *** ^--------------------------- *** bnrclassfield: incorrect type in checkbnr [please apply bnrinit()] (t_POL). *** at top-level: bnrclassfield(bnr,m) *** ^-------------------- *** bnrclassfield: overflow in bnrclassfield [too large degree]. *** at top-level: bnrclassfield(bnr,[m]) *** ^---------------------- *** bnrclassfield: overflow in bnrclassfield [too large degree]. *** at top-level: bnrclassfield(K,Mat(1/2)) *** ^------------------------- *** bnrclassfield: incorrect type in allhnfmod [integer matrix] (t_MAT). *** at top-level: bnrclassfield(K,1/2) *** ^-------------------- *** bnrclassfield: incorrect type in bnr_subroup_sanitize [subgroup] (t_FRAC). *** at top-level: bnrclassfield(K,matid(2)) *** ^------------------------- *** bnrclassfield: inconsistent dimensions in ZM_hnfmod. *** at top-level: bnrclassfield(K,Mat(2),3) *** ^------------------------- *** bnrclassfield: invalid flag in bnrclassfield [must be 0,1 or 2]. *** at top-level: bnrclassfield(K,Mat(2),-1) *** ^-------------------------- *** bnrclassfield: invalid flag in bnrclassfield [must be 0,1 or 2]. *** at top-level: bnrclassfield(vector(6),Mat(2)) *** ^------------------------------- *** bnrclassfield: incorrect type in checkbnr [please apply bnrinit()] (t_VEC). *** at top-level: bnrclassfield(bnrinit(bnfinit(y,1),[7378697629 *** ^---------------------------------------------- *** bnrclassfield: overflow in bnrclassfield [too large degree]. *** at top-level: bnrclassfield(bnfinit(x)) *** ^------------------------- *** bnrclassfield: incorrect priority in bnrclassfield: variable x = x Total time spent: 4906 pari-2.17.2/src/test/32/modsym0000644000175000017500000004342514760123736014432 0ustar billbill *** Warning: new stack size = 40000000 (38.147 Mbytes). 2 1 3 -1 1 0 11 2 [-2] [3 2] [0 -2] [3 1 1] [0 -2 0] [0 0 -2] [1 0] [0 1] 1 12 0 [1 0 0] [0 1 0] [0 0 1] [[0, -691; 1, 0; 0, 36], [0, 691; -1, 0], 691, Vecsmall([1, 2])] 3 [[0; 0; -1], Mat(-1), 1, Vecsmall([3])] [0, 1, 0]~ [4*x^9 - 25*x^7 + 42*x^5 - 25*x^3 + 4*x] -4*x^9 + 25*x^7 - 42*x^5 + 25*x^3 - 4*x [0, 0, -1]~ [0 -691] [1 0] [0 36] [-24 0 0] [ 0 -24 0] [108 0 2049] 1 [ 0 -1/120] [1/630 0] [ 0 3/6910] [[0, -691; 1, 0; 0, 36], [0, 691; -1, 0], 691, Vecsmall([1, 2])] [[[+oo, 0]], [[[[1, 1; [0, 1; -1, 0], 1], 1]], [[[1, 1; [0, -1; 1, -1], 1; [ -1, 1; -1, 0], 1], 1]]]] [Mat([[1, 1; 2, 3], 1])] 0 [[[1, 0; 0, 1], [0, 1; -1, 0]], Vecsmall([1, 2]), [[0, 1; -1, 0], [0, -1; 1, -1]]] [1, -24, 252, -1472, 4830, -6048, -16744, 84480, -113643, -115920, 534612, - 370944, -577738, 401856, 1217160, 987136] [1 0 0] [0 -1 0] [0 0 1] [[[-276468016, -7709321041217; 2789515, 0; 0, 12754465960320], [0, 770932104 1217; -2789515, -276468016], 21505266684290439755, Vecsmall([1, 2])]] 0 0 1/2 [1/4, -1/2, -1/2] -1/2 [[1/6, -1/12, 0, -1/6, -1/3, 1/6, 1/4, 1/12, 0, 1/6, 1/12, -1/12, -1/12]~, [ 0, 1/4, 1/2, 0, 0, 0, -1/4, -1/4, -1/2, 0, 1/4, 1/4, -1/4]~, [1/6, 0; -1/3, 1/2; -1/2, 1; -1/6, 0; -1/3, 0; 1/6, 0; 1/2, -1/2; 1/3, -1/2; 1/2, -1; 1/6, 0; -1/6, 1/2; -1/3, 1/2; 1/6, -1/2]] [[0, 1/2, -1/2, 1/11, -1/2, 0, 3/11, -1/22, 0, 0, -3/22, -1/2, 0, -1/2, 0, - 2/11, -2/11, 0, -3/22, -1/22, -1/2, 3/11, 1/11]~, [0, 1/2, 3/2, -1, -1/2, -1 , 0, -1/2, -1, 1, -1/2, 1/2, 1, 1/2, -2, 0, 0, 1, 1/2, 1/2, 1/2, 0, 1]~, [0, 0; 0, 1; -2, 3; 12/11, -2; 0, -1; 1, -2; 3/11, 0; 5/11, -1; 1, -2; -1, 2; 4 /11, -1; -1, 1; -1, 2; -1, 1; 2, -4; -2/11, 0; -2/11, 0; -1, 2; -7/11, 1; -6 /11, 1; -1, 1; 3/11, 0; -10/11, 2]] [[1/2, -1/2, -1/2, -1/2, 1/2, 1/4, 1/2, 0, -1/4, -1/2, 0, -1/4, 1/4]~, [0, 1 /2, 0, 0, -1/2, 1/8, 0, 1/2, -3/8, -1/2, 0, 3/8, -1/8]~, [1/2, 0; -1, 1; -1/ 2, 0; -1/2, 0; 1, -1; 1/8, 1/4; 1/2, 0; -1/2, 1; 1/8, -3/4; 0, -1; 0, 0; -5/ 8, 3/4; 3/8, -1/4]] [[1, -1, 0, -1/2, 0, -1/2, 1/2, 1, -1/2, -1, 1/2, 0, 0, -1/2, 0, 1/2, -1/2, 1/2, 1/2, -1/2, 1/2, -1/2, -1/2, 1, -1]~, [0, 0, 2/5, 1/10, 0, -1/2, 1/10, 0 , 1/2, 0, -1/2, 0, -2/5, -1/10, 0, 1/2, -1/2, -1/2, -1/10, 1/2, -1/10, 1/2, -1/2, 0, -2/5]~, [1, 0; -1, 0; -2/5, 4/5; -3/5, 1/5; 0, 0; 0, -1; 2/5, 1/5; 1, 0; -1, 1; -1, 0; 1, -1; 0, 0; 2/5, -4/5; -2/5, -1/5; 0, 0; 0, 1; 0, -1; 1 , -1; 3/5, -1/5; -1, 1; 3/5, -1/5; -1, 1; 0, -1; 1, 0; -3/5, -4/5]] [[1/3, -1/2, 1/6, 0, -1/2, 1/6, 0]~, [0, 1/2, -1/6, -1/3, -1/2, 1/6, 1/3]~, [1/3, 0; -1, 1; 1/3, -1/3; 1/3, -2/3; 0, -1; 0, 1/3; -1/3, 2/3]] [[[1/4, -1/2, -1/2]~, [0, 1/2, -1/2]~, [1/4, 0; -1, 1; 0, -1]], [[1/4, -1/2, -1/2]~, [0, 1/2, -1/2]~, [1/4, 0; -1/2, 1/2; -1/2, -1/2]], [[1/2, -1, -1]~, [0, 1/2, -1/2]~, [1/2, 0; -1, 1/2; -1, -1/2]], [[1/8, -1/4, -1/4]~, [0, 1/2 , -1/2]~, [1/8, 0; -1/4, 1/2; -1/4, -1/2]]] [[[-2, -2; -7, -1; -8, 4; -1, -1; 4, 1; -6, 0; -2, 1; 4, 1; 2, -1; -1, -1; 1 1, -1; 9, -3; 8, -4; 5, 2; 8, 2; -2, 1; 4, 1; -8, 1; 1, 1; -1, -1], [1, -2; -7, 2], 12, Vecsmall([1, 2])], [[0, 0; 0, 0; 0, 0; -2, 3; 2, -3; 0, 0; 2, -3 ; 1, -5; 0, 0; -1, 5; -1, 5; -2, 3; -1, -2; -1, 5; -1, 5; 0, 0; -1, 5; 1, -5 ; -1, 5; 1, -5], [-5, -3; -1, -2], 7, Vecsmall([4, 8])], [[0, -4; 0, 2; 0, 4 ; 0, -6; -1, 3; 0, -4; -1, 3; 1, -3; 1, 1; 0, 2; 0, 2; 0, 2; 0, -4; 1, 3; 0, 4; 1, 1; -1, 3; 1, 1; -2, 0; 0, -2], [-3, -4; -1, 0], 4, Vecsmall([1, 5])], [[0, 0, 0; -14, -1, 2; -11, -1, -6; 2, -2, 6; 11, -5, -1; -28, -2, 4; -2, 2 , -6; 10, 2, 3; -1, -8, 7; 16, 8, -6; 16, 8, -6; 17, 7, -3; 1, -1, 3; 16, 8, -6; 4, -1, -5; 12, 9, -1; 15, 0, 1; -15, 0, -1; 3, -9, 2; -1, 1, -3], [-18, 2, 8; 54, -88, -106; 24, -30, 3], 246, Vecsmall([2, 3, 4])], [[0, 2, -4, -2 , -6, -6, -2, -2, 10, 2; -1, 3, 1, -3, 9, 11, 13, 5, 3, -2; 0, 2, -1, -2, 8, 20, 20, 10, -16, 0; 0, -6, 5, 6, -6, -24, -32, -14, 12, 0; 3, 0, 0, -2, -4, -6, -2, -2, -6, 0; 0, 5, -8, -5, -11, -7, 3, -1, 17, 3; -3, -1, 4, 5, 7, 5, -1, 1, -7, -2; -1, -3, -3, -1, 1, 23, 17, 9, 3, 2; 1, 0, 1, 2, -10, -32, -2 8, -14, 12, 0; -1, -2, 3, 6, 8, 16, 8, 8, -32, 0; -1, 0, 7, 4, 18, 18, 10, 8 , -30, -4; 2, -5, 2, 1, -1, -1, -3, -1, -5, 0; 1, 5, -7, -5, -5, 3, 13, 5, - 1, 2; 1, -2, 4, -2, 6, 2, -6, 0, -6, -2; 0, -4, 2, 4, -6, -10, -14, -6, 2, 0 ; 1, 2, 2, 0, 2, -12, -4, -2, -4, -2; 0, 0, -3, -4, -4, -4, -16, 0, 4, 2; 0, 0, 1, 4, 0, 4, 12, -2, -4, 0; 1, 0, 1, 2, 0, -2, -2, 0, -18, 0; 1, 2, -2, - 2, -4, -6, 2, 0, 2, -1], [7524, 1520, -4256, -1824, 2432, -3192, 608, 1216, 912, 912; 1794, 824, -1016, 24, 1112, -60, 368, 496, 408, 504; -2808, 640, 1 088, 1152, -128, 1680, -272, -208, 432, -432; 6696, 1280, -3752, -1800, 2024 , -3024, 824, 952, 864, 504; 1368, 0, -456, -456, 0, -912, 0, 0, 0, 0; 531, 68, -44, 168, 488, 150, 296, 280, -108, 336; 1746, 364, -772, -576, 520, -10 68, 364, 104, 240, -240; -3744, -312, 792, 624, -1488, 1632, -1224, -480, 12 0, -120; 753, 248, -536, -192, 224, -318, 20, 136, 156, 72; -324, 752, 640, 624, 32, 264, -160, -176, 576, -576], 912, Vecsmall([1, 2, 3, 4, 5, 6, 7, 8, 10, 11])]] 0 3 4 [] [[[480; -333; -869; 5082; 20933; 19965], Mat(1), 480, Vecsmall([1])], [[1868 80, -809440, 2610920; -45395, 179585, -543430; -931532, 3896816, -12312388; -5482620, 23280510, -74291580; -12944096, 55235048, -176685289; -10864953, 4 6410639, -148395852], [-311578267, 693784960, -96693630; -175661395, 4373882 00, -56555050; -32022627, 85940960, -10612280], 351095745000, Vecsmall([1, 2 , 3])]] [154, 24] x^2 - 9*x + 8 x^4 - 54*x^3 + 333*x^2 + 10692*x + 39204 x^3 - 84*x^2 + 2352*x - 21952 x^6 - 22*x^5 + 153*x^4 - 316*x^3 - 140*x^2 + 576*x + 324 x^4 - 113*x^3 - 1872*x^2 - 6208*x + 8192 [[[+oo, 0], [0, 1]], [[[[1, 1; [1, 1; 0, 1], -1], 1], [1, 2]], [[[1, 1; [1, -1; 2, -1], 1], 2]]]] [Mat([[1, 0; 0, 1], 1]), 0] [0, Mat([[1, 0; 0, 1], 1])] [Mat([[1, 1; 2, 3], -1]), 0] [0, 0] [8*x^6 - 34*x^4 + 17*x^2 - 1, 48*x^5 + 120*x^4 + 24*x^3 - 84*x^2 - 54*x - 9] 0 [] [2800*x^6 + 7704*x^5 + 8098*x^4 + 4272*x^3 + 1207*x^2 + 174*x + 10, 2800*x^6 + 7704*x^5 + 8098*x^4 + 4272*x^3 + 1207*x^2 + 174*x + 10] 8*x^6 - 34*x^4 + 17*x^2 - 1 48*x^5 + 120*x^4 + 24*x^3 - 84*x^2 - 54*x - 9 [[[1, 1; -5, 0; 0, -5], [0, -1; 5, 1], 5, Vecsmall([1, 2])], [[1; 0; 0], Mat (1), 1, Vecsmall([1])]] 2 1 1 1 [-1, 0, 0]~ [1, 0, 0]~ [-1, 0, 0]~ [-1 -1] [ 5 0] [ 0 5] [Mod(1, x^2 + x - 1), Mod(x, x^2 + x - 1), Mod(-2*x - 1, x^2 + x - 1), Mod(- x - 1, x^2 + x - 1), Mod(2*x, x^2 + x - 1), Mod(x - 2, x^2 + x - 1), Mod(2*x + 2, x^2 + x - 1), Mod(-2*x - 1, x^2 + x - 1), Mod(2, x^2 + x - 1), Mod(-2* x + 2, x^2 + x - 1), Mod(-2*x - 4, x^2 + x - 1), Mod(x + 3, x^2 + x - 1), Mo d(3, x^2 + x - 1), Mod(2, x^2 + x - 1), Mod(2*x - 4, x^2 + x - 1), Mod(3*x, x^2 + x - 1), Mod(-2*x + 2, x^2 + x - 1), Mod(2*x, x^2 + x - 1), Mod(-2, x^2 + x - 1), Mod(-2, x^2 + x - 1), Mod(-2*x - 6, x^2 + x - 1), Mod(-2*x - 2, x ^2 + x - 1), Mod(1, x^2 + x - 1), Mod(5, x^2 + x - 1), Mod(-4*x - 1, x^2 + x - 1), Mod(3*x, x^2 + x - 1), Mod(2*x + 1, x^2 + x - 1), Mod(-2*x - 4, x^2 + x - 1), Mod(-3, x^2 + x - 1), Mod(-6*x + 2, x^2 + x - 1)] [Mod(1, x^2 + x - 1), Mod(x, x^2 + x - 1), Mod(-2*x - 1, x^2 + x - 1), Mod(- x - 1, x^2 + x - 1), Mod(2*x, x^2 + x - 1), Mod(x - 2, x^2 + x - 1), Mod(2*x + 2, x^2 + x - 1), Mod(-2*x - 1, x^2 + x - 1), Mod(2, x^2 + x - 1), Mod(-2* x + 2, x^2 + x - 1), Mod(-2*x - 4, x^2 + x - 1), Mod(x + 3, x^2 + x - 1), Mo d(3, x^2 + x - 1), Mod(2, x^2 + x - 1), Mod(2*x - 4, x^2 + x - 1), Mod(3*x, x^2 + x - 1)] [[1, -2, 0, 2, -2, 0, -2, 0, 0, 4, 4, 0, 2, 4, 0, -4], [1, -1, 0, -1, 2, 0, 4, 3, 0, -2, -4, 0, 2, -4, 0, -1], [1, -1, 0, -1, 3, 0, -3, 3, 0, -3, 0, 0, 4, 3, 0, -1], [1, 1, 0, -1, -2, 0, 4, -3, 0, -2, 4, 0, 2, 4, 0, -1], [1, 1, 0, -1, 1, 0, -5, -3, 0, 1, 4, 0, -4, -5, 0, -1], [1, 2, 0, 2, 0, 0, 0, 0, 0, 0, 6, 0, 4, 0, 0, -4]] [1 0 0 0 0 0] [0 1 0 0 0 0] [0 0 1 0 0 0] [0 0 0 1 0 0] [0 0 0 0 1 0] [0 0 0 0 0 1] 1 [ 1 -2 0 4 -2 1] [ 0 0 0 2 -1 1/2] [ 6 -18 0 78 -36 16] [ 3 2 -1/2 18 -7 5/2] [12 12 -2 60 -23 8] [12 18 -2 48 -18 6] 1 [ 3 0 -1/3 24 -10 4] [ 0 0 0 -3 1 -1/3] [ 24 0 -3 288 -120 48] [ -2 -3 1/3 -32 13 -5] [-12 -12 2 -180 73 -28] [-18 -12 3 -252 102 -39] 1 [ 1 0 0 10 -4 5/3] [-1 0 1/6 -10 4 -3/2] [ 6 6 0 150 -60 24] [ 0 0 0 -24 10 -25/6] [ 0 0 0 -120 49 -20] [ 0 0 0 -150 60 -24] 1 [1 0 0 0 0 0] [0 1 0 0 0 0] [0 0 1 -144 60 -24] [0 0 0 25 -10 4] [0 0 0 120 -49 20] [0 0 0 144 -60 25] 1 [1, 1] 1 0 [[-17150*x^4 + 6950*x^2 - 360, 1008420*x^6 + 3025260*x^5 + 3769570*x^4 + 246 2740*x^3 + 888440*x^2 + 168230*x + 13080, -1008420*x^6 - 3025260*x^5 - 37695 70*x^4 - 2531340*x^3 - 991340*x^2 - 222930*x - 23280], [346430*x^4 - 130490* x^2 + 6480, -25210500*x^6 - 75631500*x^5 - 93735040*x^4 - 60724720*x^3 - 216 87680*x^2 - 4061060*x - 311880, 25210500*x^6 + 75631500*x^5 + 93735040*x^4 + 62110440*x^3 + 23766260*x^2 + 5185800*x + 527820], [-201684*x^6 - 696290*x^ 4 + 214670*x^2 - 8628, 105279048*x^6 + 315232092*x^5 + 387699760*x^4 + 24862 0120*x^3 + 87804500*x^2 + 16247792*x + 1232136, -105279048*x^6 - 316442196*x ^5 - 390725020*x^4 - 255438960*x^3 - 95007500*x^2 - 19813716*x - 1915440]] 1 [[Mat([[1, 0; 0, 1], 1]), 0, 0, 0, 0], [0, Mat([[1, 0; 0, 1], 1]), 0, 0, 0], [0, 0, Mat([[1, 0; 0, 1], 1]), 0, 0], [0, 0, 0, Mat([[1, 0; 0, 1], 1]), 0], [0, 0, 0, 0, Mat([[1, 0; 0, 1], 1])]] [84, 10] 1 1 1 1 4 1 1 2 2 2 2 4 1 1 1 1 1 1 1 1 1 1 1 1 2 [ 2 -1 -1 2] [-1 2 1 -2] [ 1 -1 0 0] [ 0 0 0 -1] [-1] x^8 - 28*x^7 - 292*x^6 + 16496*x^5 - 115568*x^4 - 1800704*x^3 + 33061376*x^2 - 192352256*x + 396169216 -1/2 [1/2, 1/74] [ 0 0 0 -4312 440 -704] [ 0 0 0 792 -80 128] [ 0 0 0 0 0 0] [4312 -792 0 0 0 -88] [-440 80 0 0 0 8] [ 704 -128 0 88 -8 0] 1 1 1 [ 0 0 0 -2160 456 -96 -2304 678 -198 -576 492 -102] [ 0 0 0 360 -76 16 384 -113 33 96 -82 17] [ 0 0 0 0 0 0 0 0 0 0 0 0] [2160 -360 0 0 0 0 -5760 1680 -480 -2880 2400 -480] [-456 76 0 0 0 0 1176 -343 98 588 -490 98] [ 96 -16 0 0 0 0 -240 70 -20 -120 100 -20] [2304 -384 0 5760 -1176 240 0 -24 24 -2160 1752 -336] [-678 113 0 -1680 343 -70 24 0 -5 630 -511 98] [ 198 -33 0 480 -98 20 -24 5 0 -186 151 -29] [ 576 -96 0 2880 -588 120 2160 -630 186 0 -36 18] [-492 82 0 -2400 490 -100 -1752 511 -151 36 0 -9] [ 102 -17 0 480 -98 20 336 -98 29 -18 9 0] 1 1 1 [0 0 0 0] [0 0 0 0] [0 0 0 0] [0 0 0 0] [0 0] [0 0] [ 0 -51 765 2244 -969 7276 1122 0 -629 901] [ 51 0 -153 -629 545/2 -2057 -340 0 187 -272] [ -765 153 0 2686 -1173 8976 1734 0 -884 1360] [-2244 629 -2686 0 -51 969 1224 0 -357 833] [ 969 -545/2 1173 51 0 -255 -510 0 136 -340] [-7276 2057 -8976 -969 255 0 3570 0 -799 2295] [-1122 340 -1734 -1224 510 -3570 0 0 204 -85] [ 0 0 0 0 0 0 0 0 0 0] [ 629 -187 884 357 -136 799 -204 0 0 -170] [ -901 272 -1360 -833 340 -2295 85 0 170 0] [ 0 0 0 2128 -532 2641 1368 0 -1919 1463] [ 0 0 0 -456 229/2 -570 -285 0 399 -304] [ 0 0 0 1805 -456 2280 1083 0 -1520 1159] [-2128 456 -1805 0 19 -19 1463 0 -1672 1387] [ 532 -229/2 456 -19 0 -19 -380 0 437 -361] [-2641 570 -2280 19 19 0 1843 0 -2109 1748] [-1368 285 -1083 -1463 380 -1843 0 0 209 -76] [ 0 0 0 0 0 0 0 0 0 0] [ 1919 -399 1520 1672 -437 2109 -209 0 0 -133] [-1463 304 -1159 -1387 361 -1748 76 0 133 0] [ 0 0 91 -26 -130 52 52 0] [ 0 0 0 0 0 0 0 0] [-91 0 0 -65 -52 -13 130 -143] [ 26 0 65 0 -39 26 -39 65] [130 0 52 39 0 39 13 65] [-52 0 13 -26 -39 0 13 -26] [-52 0 -130 39 -13 -13 0 -52] [ 0 0 143 -65 -65 26 52 0] [[[[0, 33, 693, 54, 648, 486, 0]], [[0, 33, 693, 54, 648, 486, 0]]], 2 + 2*3 + 3^2 + 3^3 + 2*3^4 + 3^5 + O(3^6), Vecsmall([3, 6, 6, 1])] O(3^6) + (2 + 3 + 3^3 + O(3^4))*x + (2*3 + O(3^2))*x^2 + O(3^2)*x^3 + O(x^4) O(3^6) + O(3^4)*x + O(3^2)*x^2 + O(3^2)*x^3 + O(x^4) [[[[1243, 273, 2254, 1029, 0]], [[1234, 833, 294, 0, 0]], [[1243, 1295, 196, 1372, 0]], [[1243, 1295, 196, 1372, 0]], [[1234, 833, 294, 0, 0]], [[1243, 273, 2254, 1029, 0]]], 1 + 2*7 + 4*7^2 + 2*7^3 + O(7^4), Vecsmall([7, 4, 4, 1])] (6 + 3*7 + 5*7^2 + 3*7^3 + O(7^4)) + (6*7^2 + O(7^3))*x + (7 + O(7^2))*x^2 + O(7)*x^3 + O(x^4) 6 + 3*7 + 5*7^2 + 3*7^3 + O(7^4) [[[[6558, 5094, 2304, 5832, 2268, 0, 5103, 0], [3, 3024, 5508, 4374, 2916, 0 , 0, 0]], [[6558, 5094, 2304, 5832, 2268, 0, 5103, 0], [3, 3024, 5508, 4374, 2916, 0, 0, 0]]], [0, 1/36; 1/36, 0], Vecsmall([3, 8, 7, 1])] [(2*3^-1 + 1 + 3 + 3^2 + 3^3 + 3^4 + O(3^5)) + (2 + 3^3 + O(3^4))*x + (1 + 2 *3 + O(3^2))*x^2 + (2*3^-1 + 1 + O(3))*x^3 + (2*3^-1 + O(3^0))*x^4 + O(x^5), (3^-1 + 1 + 3 + 3^2 + 3^3 + 3^4 + O(3^5)) + (1 + 2*3 + 2*3^2 + 3^3 + O(3^4) )*x + (3^-2 + 3^-1 + O(3^2))*x^2 + (2*3^-2 + 2 + O(3))*x^3 + (3^-2 + 2*3^-1 + O(3^0))*x^4 + O(x^5)] [O(3^5) + O(3^4)*x + O(3^2)*x^2 + O(3)*x^3 + O(x^4), O(3^5) + O(3^4)*x + O(3 ^2)*x^2 + O(3)*x^3 + O(x^4)] [[[[6558, 2205, 5895, 972, 1296, 5832, 5103, 0], [3, 729, 459, 3645, 2673, 2 187, 4374, 0]], [[6558, 2205, 5895, 972, 1296, 5832, 5103, 0], [3, 729, 459, 3645, 2673, 2187, 4374, 0]]], [0, 1/18; 1/18, 0], Vecsmall([3, 8, 7, 1])] [[[[0, 1953, 729, 3888, 729, 3645, 0, 0], [0, 3312, 1863, 5994, 729, 1458, 0 , 0]], [[0, 1953, 729, 3888, 729, 3645, 0, 0], [0, 3312, 1863, 5994, 729, 14 58, 0, 0]]], [0, 1/18; 1/18, 1/18], Vecsmall([3, 8, 7, 1])] [[[[6546, 684, 5499, 4617, 2106, 5832, 5832, 0], [6, 5427, 2673, 2187, 1458, 0, 0, 0]], [[6546, 684, 5499, 4617, 2106, 5832, 5832, 0], [6, 5427, 2673, 2 187, 1458, 0, 0, 0]]], [0, 1/126; 1/126, 1/126], Vecsmall([3, 8, 7, 1])] (2 + 3 + 3^2 + O(3^3)) + (1 + O(3))*x + (1 + O(3))*x^2 + O(x^3) (2 + 3 + 3^2 + 2*3^3 + 2*3^5 + 3^6 + O(3^7)) + (1 + 3 + 2*3^2 + 3^3 + O(3^5) )*x + (1 + 2*3 + O(3^3))*x^2 + (3 + O(3^2))*x^3 + O(3)*x^4 + O(x^5) O(3^7) + O(3^5)*x + O(3^3)*x^2 + O(3^2)*x^3 + O(3)*x^4 + O(x^5) (2 + 3 + 3^2 + 2*3^3 + 2*3^5 + 3^6 + O(3^7)) + (1 + 3 + 2*3^2 + 3^3 + O(3^5) )*x + (1 + 2*3 + O(3^3))*x^2 + (3 + O(3^2))*x^3 + O(3)*x^4 + O(x^5) O(11^9) + O(11^8)*x + O(11^7)*x^2 + O(11^6)*x^3 + O(11^5)*x^4 + O(11^4)*x^5 + O(11^3)*x^6 + O(11^2)*x^7 + O(11)*x^8 + O(x^9) O(3^5) + O(3^3)*x + (1 + 2*3 + O(3^2))*x^2 + (1 + O(3))*x^3 + O(x^4) O(11^7) + (10 + 3*11 + 6*11^2 + 9*11^3 + 8*11^4 + 5*11^5 + O(11^6))*x + (6 + 3*11 + 2*11^2 + 6*11^3 + 6*11^4 + O(11^5))*x^2 + (2 + 2*11 + 11^2 + 10*11^3 + O(11^4))*x^3 + (5 + 8*11^2 + O(11^3))*x^4 + (4 + 10*11 + O(11^2))*x^5 + ( 1 + O(11))*x^6 + O(x^7) (2 + 2*3 + 2*3^2 + 3^4 + O(3^6)) + (1 + 2*3 + 3^2 + 3^3 + O(3^4))*x + (1 + 3 + O(3^2))*x^2 + (2 + O(3^2))*x^3 + O(x^4) [(2*3^-1 + 1 + 3 + 3^2 + 3^3 + 3^4 + O(3^5)) + (2 + 3^3 + O(3^4))*x + (1 + 2 *3 + O(3^2))*x^2 + (2*3^-1 + 1 + O(3))*x^3 + (2*3^-1 + O(3^0))*x^4 + O(x^5), (3^-1 + 1 + 3 + 3^2 + 3^3 + 3^4 + O(3^5)) + (1 + 2*3 + 2*3^2 + 3^3 + O(3^4) )*x + (3^-2 + 3^-1 + O(3^2))*x^2 + (2*3^-2 + 2 + O(3))*x^3 + (3^-2 + 2*3^-1 + O(3^0))*x^4 + O(x^5)] [O(5^19), 4 + 3*5 + 3*5^2 + 4*5^3 + 3*5^4 + 4*5^5 + 4*5^6 + 3*5^7 + 5^8 + 2* 5^10 + 3*5^13 + 3*5^14 + 3*5^16 + 5^18 + O(5^19), O(5^19), 2 + 2*5^2 + 3*5^3 + 3*5^4 + 5^5 + 3*5^6 + 3*5^7 + 2*5^8 + 5^9 + 4*5^10 + 4*5^11 + 4*5^12 + 3* 5^13 + 3*5^14 + 4*5^15 + 3*5^16 + 4*5^17 + 2*5^18 + O(5^19), O(5^19), 4 + 5 + 4*5^4 + 4*5^5 + 3*5^8 + 5^11 + 3*5^12 + 5^13 + 3*5^14 + 5^15 + 5^16 + 3*5^ 17 + 4*5^18 + O(5^19)] [1, -1, 1, -2, 0]: [1, 1] [1, -1, 1, -17, 30]: [2, 1] [1, -1, 1, -96608, -11533373]: [3, 1] [1, -1, 1, -1568, -4669]: [1, 1] [1, -1, 1, -95528, -11804669]: [6, 1] [1, -1, 1, 6112, -41533]: [2, 1] [1, 0, 1, 4, -6]: [1, 1] [1, 0, 1, -1, 0]: [1, 1/3] [1, 0, 1, -171, -874]: [3, 1] [1, 0, 1, -36, -70]: [2, 1] [1, 0, 1, -11, 12]: [2, 1/3] [1, 0, 1, -2731, -55146]: [6, 1] [[1, 1], [1, 1/3], [3, 1], [2, 1], [2, 1/3], [6, 1]] 5 [[[1/6, 0, -1/6, -1/3, -1/2]~, [0, 1/2, 0, 0, -1/2]~, [1/6, 0; -1/2, 1; -1/6 , 0; -1/3, 0; 0, -1]], [[1/18, 0, -1/18, -1/9, -1/6]~, [0, 1/2, 0, 0, -1/2]~ , [1/18, 0; -1/2, 1; -1/18, 0; -1/9, 0; 1/3, -1]], [[1/2, 0, -1/2, -1, -3/2] ~, [0, 1/2, 0, 0, -1/2]~, [1/2, 0; -1/2, 1; -1/2, 0; -1, 0; -1, -1]], [[1/3, 0, -1/3, -2/3, -1]~, [0, 1, 0, 0, -1]~, [1/3, 0; 0, 1; -1/3, 0; -2/3, 0; -1 , -1]], [[1/9, 0, -1/9, -2/9, -1/3]~, [0, 1, 0, 0, -1]~, [1/9, 0; 0, 1; -1/9 , 0; -2/9, 0; -1/3, -1]], [[1, 0, -1, -2, -3]~, [0, 1, 0, 0, -1]~, [1, 0; 0, 1; -1, 0; -2, 0; -3, -1]]] 1 1 *** at top-level: ...it(57,2,1);M=mssplit(ms);msdim(M) *** ^-------- *** msdim: incorrect type in checkms [please apply msinit] (t_VEC). *** at top-level: ...2]);[W,xpm]=msfromell(E);mseval(W,xpm[1],[1]) *** ^-------------------- *** mseval: incorrect type in mspathlog (t_VEC). *** at top-level: W=msinit(6,4);msatkinlehner(W,4) *** ^------------------ *** msatkinlehner: domain error in msatkinlehner: N % Q != 0 *** at top-level: msinit(-11,2,0) *** ^--------------- *** msinit: domain error in msinit: N <= 0 *** at top-level: msinit(11,1,0) *** ^-------------- *** msinit: domain error in msinit: k < 2 *** at top-level: msinit(1/2,2,0) *** ^--------------- *** msinit: incorrect type in msinit (t_FRAC). *** at top-level: msinit(1,1/2,0) *** ^--------------- *** msinit: incorrect type in msinit (t_FRAC). *** at top-level: msinit(11,2,2) *** ^-------------- *** msinit: domain error in msinit: |sign| > 1 *** at top-level: msinit(11,2,-2) *** ^--------------- *** msinit: domain error in msinit: |sign| > 1 Total time spent: 1954 pari-2.17.2/src/test/32/nfcompositum0000644000175000017500000001477114760137411015642 0ustar billbillSuite: compositum of relative extensions compositum of degrees 2 and 3 over quadratic field: 1 compositum of degrees 2 and 4 over quadratic field: 1 compositum of degrees 5 and 7 over quadratic field: 1 compositum of degrees 2 and 3 over degree 5 field: 1 compositum of degrees 2 and 4 over degree 5 field: 1 compositum of degrees 5 and 4 over degree 5 field: 1 [x^10 + Mod(-5/2*y + 5/2, y^2 - 5)*x^9 + Mod(-5*y + 20, y^2 - 5)*x^8 + Mod(- 20*y + 30, y^2 - 5)*x^7 + Mod(-45/2*y + 145/2, y^2 - 5)*x^6 + Mod(-71/2*y + 121/2, y^2 - 5)*x^5 + Mod(-20*y + 60, y^2 - 5)*x^4 + Mod(-25*y + 5, y^2 - 5) *x^3 + 45*x^2 + Mod(-5*y + 15, y^2 - 5)*x + Mod(-2*y + 6, y^2 - 5), x^10 + M od(5/2*y + 5/2, y^2 - 5)*x^9 + Mod(5*y + 20, y^2 - 5)*x^8 + Mod(20*y + 30, y ^2 - 5)*x^7 + Mod(45/2*y + 145/2, y^2 - 5)*x^6 + Mod(79/2*y + 121/2, y^2 - 5 )*x^5 + Mod(25*y + 85, y^2 - 5)*x^4 + Mod(15*y + 55, y^2 - 5)*x^3 + Mod(10*y - 5, y^2 - 5)*x^2 - 10*x + Mod(-2*y + 6, y^2 - 5)] [x^10 + Mod(-5/2*y + 5/2, y^2 - 5)*x^9 + Mod(-5*y + 20, y^2 - 5)*x^8 + Mod(- 20*y + 30, y^2 - 5)*x^7 + Mod(-45/2*y + 145/2, y^2 - 5)*x^6 + Mod(-71/2*y + 121/2, y^2 - 5)*x^5 + Mod(-20*y + 60, y^2 - 5)*x^4 + Mod(-25*y + 5, y^2 - 5) *x^3 + 45*x^2 + Mod(-5*y + 15, y^2 - 5)*x + Mod(-2*y + 6, y^2 - 5), Mod(Mod( 26/2945*y - 653/5890, y^2 - 5)*x^9 + Mod(1633/5890*y - 869/2945, y^2 - 5)*x^ 8 + Mod(2951/5890*y - 5939/2945, y^2 - 5)*x^7 + Mod(21757/11780*y - 29451/11 780, y^2 - 5)*x^6 + Mod(18733/11780*y - 69587/11780, y^2 - 5)*x^5 + Mod(1445 /589*y - 9436/2945, y^2 - 5)*x^4 + Mod(7893/11780*y - 34679/11780, y^2 - 5)* x^3 + Mod(9461/5890*y + 3919/2945, y^2 - 5)*x^2 + Mod(-8383/11780*y - 54699/ 11780, y^2 - 5)*x + Mod(261/589*y - 2467/2945, y^2 - 5), x^10 + Mod(-5/2*y + 5/2, y^2 - 5)*x^9 + Mod(-5*y + 20, y^2 - 5)*x^8 + Mod(-20*y + 30, y^2 - 5)* x^7 + Mod(-45/2*y + 145/2, y^2 - 5)*x^6 + Mod(-71/2*y + 121/2, y^2 - 5)*x^5 + Mod(-20*y + 60, y^2 - 5)*x^4 + Mod(-25*y + 5, y^2 - 5)*x^3 + 45*x^2 + Mod( -5*y + 15, y^2 - 5)*x + Mod(-2*y + 6, y^2 - 5)), Mod(Mod(26/2945*y - 653/589 0, y^2 - 5)*x^9 + Mod(1633/5890*y - 869/2945, y^2 - 5)*x^8 + Mod(2951/5890*y - 5939/2945, y^2 - 5)*x^7 + Mod(21757/11780*y - 29451/11780, y^2 - 5)*x^6 + Mod(18733/11780*y - 69587/11780, y^2 - 5)*x^5 + Mod(1445/589*y - 9436/2945, y^2 - 5)*x^4 + Mod(7893/11780*y - 34679/11780, y^2 - 5)*x^3 + Mod(9461/5890 *y + 3919/2945, y^2 - 5)*x^2 + Mod(-8383/11780*y - 42919/11780, y^2 - 5)*x + Mod(261/589*y - 2467/2945, y^2 - 5), x^10 + Mod(-5/2*y + 5/2, y^2 - 5)*x^9 + Mod(-5*y + 20, y^2 - 5)*x^8 + Mod(-20*y + 30, y^2 - 5)*x^7 + Mod(-45/2*y + 145/2, y^2 - 5)*x^6 + Mod(-71/2*y + 121/2, y^2 - 5)*x^5 + Mod(-20*y + 60, y ^2 - 5)*x^4 + Mod(-25*y + 5, y^2 - 5)*x^3 + 45*x^2 + Mod(-5*y + 15, y^2 - 5) *x + Mod(-2*y + 6, y^2 - 5)), -1] Mod(0, x^10 + Mod(-5/2*y + 5/2, y^2 - 5)*x^9 + Mod(-5*y + 20, y^2 - 5)*x^8 + Mod(-20*y + 30, y^2 - 5)*x^7 + Mod(-45/2*y + 145/2, y^2 - 5)*x^6 + Mod(-71/ 2*y + 121/2, y^2 - 5)*x^5 + Mod(-20*y + 60, y^2 - 5)*x^4 + Mod(-25*y + 5, y^ 2 - 5)*x^3 + 45*x^2 + Mod(-5*y + 15, y^2 - 5)*x + Mod(-2*y + 6, y^2 - 5)) 1 [x^5 + Mod(y, y^2 - 5), x^10 + Mod(77*y - 275, y^2 - 5)*x^5 + Mod(-41525*y + 96630, y^2 - 5), x^10 + Mod(77*y + 275, y^2 - 5)*x^5 + Mod(41525*y + 96630, y^2 - 5)] x^25 + Mod(155*y, y^2 - 5)*x^20 + 148050*x^15 + Mod(-7810450*y, y^2 - 5)*x^1 0 + 675940125*x^5 + Mod(715728775*y, y^2 - 5) x^10 + 5*x^9 + 15*x^8 + 30*x^7 + 45*x^6 + Mod(2*y + 51, y^2 - 5)*x^5 + Mod(5 *y + 45, y^2 - 5)*x^4 + Mod(-10*y + 30, y^2 - 5)*x^3 + Mod(-20*y + 15, y^2 - 5)*x^2 + Mod(-5*y + 5, y^2 - 5)*x + Mod(y + 6, y^2 - 5) [x^10 + 5*x^9 + 15*x^8 + 30*x^7 + 45*x^6 + Mod(2*y + 51, y^2 - 5)*x^5 + Mod( 5*y + 45, y^2 - 5)*x^4 + Mod(-10*y + 30, y^2 - 5)*x^3 + Mod(-20*y + 15, y^2 - 5)*x^2 + Mod(-5*y + 5, y^2 - 5)*x + Mod(y + 6, y^2 - 5), Mod(-32280/622201 *x^9 + Mod(22275/622201*y - 145260/622201, y^2 - 5)*x^8 + Mod(89100/622201*y - 397350/622201, y^2 - 5)*x^7 + Mod(244100/622201*y - 22995/20071, y^2 - 5) *x^6 + Mod(420450/622201*y - 918351/622201, y^2 - 5)*x^5 + Mod(510720/622201 *y - 852705/622201, y^2 - 5)*x^4 + Mod(424640/622201*y - 238275/622201, y^2 - 5)*x^3 + Mod(871950/622201*y + 235710/622201, y^2 - 5)*x^2 + Mod(714855/62 2201*y - 1610346/622201, y^2 - 5)*x + Mod(-62626/622201*y - 860751/622201, y ^2 - 5), x^10 + 5*x^9 + 15*x^8 + 30*x^7 + 45*x^6 + Mod(2*y + 51, y^2 - 5)*x^ 5 + Mod(5*y + 45, y^2 - 5)*x^4 + Mod(-10*y + 30, y^2 - 5)*x^3 + Mod(-20*y + 15, y^2 - 5)*x^2 + Mod(-5*y + 5, y^2 - 5)*x + Mod(y + 6, y^2 - 5)), Mod(-322 80/622201*x^9 + Mod(22275/622201*y - 145260/622201, y^2 - 5)*x^8 + Mod(89100 /622201*y - 397350/622201, y^2 - 5)*x^7 + Mod(244100/622201*y - 22995/20071, y^2 - 5)*x^6 + Mod(420450/622201*y - 918351/622201, y^2 - 5)*x^5 + Mod(5107 20/622201*y - 852705/622201, y^2 - 5)*x^4 + Mod(424640/622201*y - 238275/622 201, y^2 - 5)*x^3 + Mod(871950/622201*y + 235710/622201, y^2 - 5)*x^2 + Mod( 714855/622201*y - 988145/622201, y^2 - 5)*x + Mod(-62626/622201*y - 860751/6 22201, y^2 - 5), x^10 + 5*x^9 + 15*x^8 + 30*x^7 + 45*x^6 + Mod(2*y + 51, y^2 - 5)*x^5 + Mod(5*y + 45, y^2 - 5)*x^4 + Mod(-10*y + 30, y^2 - 5)*x^3 + Mod( -20*y + 15, y^2 - 5)*x^2 + Mod(-5*y + 5, y^2 - 5)*x + Mod(y + 6, y^2 - 5)), -1] [x^2 + x + 1, Mod(0, x^2 + x + 1), Mod(x, x^2 + x + 1), -1] [x^3 - 3*x^2 + 3*x + 1, x^6 + 3*x^5 + 6*x^4 + 11*x^3 + 12*x^2 - 3*x + 1] [x^3 - 3*x^2 + 3*x + 1, x^6 + 3*x^5 + 6*x^4 + 11*x^3 + 12*x^2 - 3*x + 1] 0:[1, 1] 2:1 0:[1] 2:1 0:[1] 2:1 0:[1, 1] 2:1 [x^6 - 8*x^4 - 2*x^3 + 13*x^2 - 10*x - 1] *** at top-level: nfcompositum(nfinit(x),w^2+1,w^2+1) *** ^----------------------------------- *** nfcompositum: incorrect priority in polcompositum: variable x >= w *** at top-level: nfcompositum(x,w^2+1,w^2+1) *** ^--------------------------- *** nfcompositum: incorrect type in checknf [please apply nfinit()] (t_POL). *** at top-level: nfcompositum(nfinit(x-1),x^3-2,x^3-1) *** ^------------------------------------- *** nfcompositum: incorrect priority in polcompositum: variable x >= x *** at top-level: nfcompositum(nfinit(x^2+1),x^3-2,x^3-1) *** ^--------------------------------------- *** nfcompositum: incorrect priority in polcompositum: variable x >= x *** at top-level: nfcompositum(nfinit(x-1),y^3-2,y^3-1) *** ^------------------------------------- *** nfcompositum: incorrect priority in polcompositum: variable x >= y *** at top-level: nfcompositum(bnfinit(x),x^3-2,x^3-1) *** ^------------------------------------ *** nfcompositum: incorrect priority in polcompositum: variable x >= x Total time spent: 596 pari-2.17.2/src/test/32/objets0000644000175000017500000000416614676526175014421 0ustar billbill echo = 1 ? +3 3 ? -5 -5 ? 5+3 8 ? 5-3 2 ? 5/3 5/3 ? 5\3 1 ? 5\/3 2 ? 5%3 2 ? 5^3 125 ? binary(65537) [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1] ? bittest(10^100,100) 1 ? ceil(-2.5) -2 ? centerlift(Mod(456,555)) -99 ? component(1+O(7^4),3) 1 ? conj(1+I) 1 - I ? conjvec(Mod(x^2+x+1,x^3-x-1)) [4.0795956234914387860104177508366260326, 0.46020218825428060699479112458168 698369 + 0.18258225455744299269398828369501930574*I, 0.460202188254280606994 79112458168698369 - 0.18258225455744299269398828369501930574*I]~ ? truncate(1.7,&e) 1 ? e -1 ? denominator(12345/54321) 18107 ? divrem(345,123) [2, 99]~ ? divrem(x^7-1,x^5+1) [x^2, -x^2 - 1]~ ? floor(-1/2) -1 ? floor(-2.5) -3 ? frac(-2.7) 0.30000000000000000000000000000000000000 ? I^2 -1 ? imag(2+3*I) 3 ? lex([1,3],[1,3,5]) -1 ? max(2,3) 3 ? min(2,3) 2 ? Mod(-12,7) Mod(2, 7) ? norm(1+I) 2 ? norm(Mod(x+5,x^3+x+1)) 129 ? numerator((x+1)/(x-1)) x + 1 ? 1/(1+x)+O(x^20) 1 - x + x^2 - x^3 + x^4 - x^5 + x^6 - x^7 + x^8 - x^9 + x^10 - x^11 + x^12 - x^13 + x^14 - x^15 + x^16 - x^17 + x^18 - x^19 + O(x^20) ? numtoperm(7,1035) Vecsmall([2, 4, 6, 1, 5, 7, 3]) ? permtonum([4,7,1,6,3,5,2]) 2781 ? 37. 37.000000000000000000000000000000000000 ? real(5-7*I) 5 ? shift(1,50) 1125899906842624 ? shift([3,4,-11,-12],-2) [0, 1, -2, -3] ? shiftmul([3,4,-11,-12],-2) [3/4, 1, -11/4, -3] ? sign(-1) -1 ? sign(0) 0 ? sign(0.) 0 ? simplify(((x+I+1)^2-x^2-2*x*(I+1))^2) -4 ? sizedigit([1.3*10^5,2*I*Pi*exp(4*Pi)]) 7 ? truncate(-2.7) -2 ? truncate(sin(x^2)) -1/5040*x^14 + 1/120*x^10 - 1/6*x^6 + x^2 ? type(Mod(x,x^2+1)) "t_POLMOD" ? valuation(6^10000-1,5) 5 ? \p57 realprecision = 57 significant digits ? Pi 3.14159265358979323846264338327950288419716939937510582098 ? \p38 realprecision = 38 significant digits ? O(x^12) O(x^12) ? padicno=(5/3)*127+O(127^5) 44*127 + 42*127^2 + 42*127^3 + 42*127^4 + O(127^5) ? padicprec(padicno,127) 5 ? length(divisors(1000)) 16 ? Mod(10873,49649)^-1 *** at top-level: Mod(10873,49649)^-1 *** ^--- *** _inv: impossible inverse in Fp_inv: Mod(131, 49649). ? (1+I)*(1+1/2*I) 1/2 + 3/2*I ? print("Total time spent: ",gettime); Total time spent: 1 pari-2.17.2/src/test/32/qfisom0000644000175000017500000000123314567450071014407 0ustar billbill[2, [Mat(-1)]] 78382080 78382080 78382080 78382080 78382080 78382080 339738624 339738624 339738624 339738624 OK OK OK OK OK 3840 OK 3840 OK OK [4, [[-1, 0; 0, -1], [1, 0; 0, -1]]] [2, [[-1, 0; 0, -1]]] [0, 0] "Group([[-1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, -1]], [[0, 0, 0, 1], [0, 1, 1, 0], [0, -1, 0, 0], [1, -1, -1, 0]], [[-1, 0, 0, 0], [0, 0, -1, 1], [-1, 0, 1, 0], [-1, 1, 1, 0]])" "MatrixGroup<4, Integers() |[[-1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0 , 0, 0, -1]], [[0, 0, 0, 1], [0, 1, 1, 0], [0, -1, 0, 0], [1, -1, -1, 0]], [ [-1, 0, 0, 0], [0, 0, -1, 1], [-1, 0, 1, 0], [-1, 1, 1, 0]]>" [12, 4] [12, 4] [12, 4] Total time spent: 1311 pari-2.17.2/src/test/32/quad0000644000175000017500000000235314567450071014047 0ustar billbill1 2.6180339887498948482045868343656381177 1.6180339887498948482045868343656381177 + I 1.6180339887498948482045868343656381177 0.E-38 + 1.6180339887498948482045868343656381177*I -1 *** at top-level: norml2(w) *** ^--------- *** norml2: incorrect type in gnorml2 (t_QUAD). 1 2 1 0 2 1 2 1 0 0 1 0 1 0 1 0 1 1 0 *** at top-level: quadgen(-8)<1 *** ^-- *** _<_: incorrect type in gsigne (t_QUAD). 0.70710678118654752440084436210484903928 2.5825756949558400065880471937280084890 (a)->[sign(z)|z<-[a,a-1,a-2,1-a,2-a]] [1, 1, -1, -1, 1] [1, 1, -1, -1, 1] I w 2147483648.5000000000582076609134674072 4294967297 -4294967298 4294967298 -4294967297 4294967297 -4294967297 2.2847006554165615148712535010323047844 *** at top-level: floor(w8) *** ^--------- *** floor: incorrect type in gfloor (t_QUAD). *** at top-level: ceil(w8) *** ^-------- *** ceil: incorrect type in gceil (t_QUAD). *** at top-level: sign(w8) *** ^-------- *** sign: incorrect type in gsigne (t_QUAD). *** at top-level: floor(Mod(0,3)*quadgen(5)) *** ^-------------------------- *** floor: incorrect type in gfloor (t_QUAD). Total time spent: 1 pari-2.17.2/src/test/32/nfpolsturm0000644000175000017500000000125714567450071015330 0ustar billbill[0, 0, 0, 2, 2] 0 [0, 0, 0, 2] [0, 0, 0, 0, 0] [0, 0, 0, 0, 0] [0, 0, 0, 0, 0] [0, 2, 2, 2, 2] *** at top-level: nfpolsturm(nf,a,3) *** ^------------------ *** nfpolsturm: domain error in nfpolsturm: index > 2 *** at top-level: nfpolsturm(nf,a,[-1..1]) *** ^------------------------ *** nfpolsturm: domain error in nfpolsturm: index <= 0 *** at top-level: nfpolsturm(nf,a,[1..3]) *** ^----------------------- *** nfpolsturm: domain error in nfpolsturm: index > 2 *** at top-level: nfpolsturm(nf,0,1) *** ^------------------ *** nfpolsturm: zero polynomial in nfpolsturm. Total time spent: 4 pari-2.17.2/src/test/32/qfb0000644000175000017500000000657314676526175013707 0ustar billbill[-1, 6, 6] Qfb(5, 7, 9) Qfb(3, 2, 3) Qfb(-2, -34, 17) Qfb(-2, 34, 17) Qfb(1, 34, -34) Qfb(-2, 34, 17) Qfb(17, 34, -2) Qfb(-2, 34, 17) Qfb(1, -1, 6) Qfb(8, 13, 6) Qfb(1, 1, 6) Qfb(1009, 60, 99108027750247771) Qfb(1, 0, 100000000000000000039) Qfb(1, 0, 100000000000000000039) [Qfb(6, 6, 6), Qfb(6, 6, 6)] [Qfb(1, 1, 6), Qfb(6, 25, 27)] [Qfb(1, 8, -7), Qfb(77, -134, 58)] Qfb(1, 1, 6) [Qfb(1, 1, 6), [22479, 76177; -39508, -133885]] Qfb(749, 2207, -1712) [Qfb(749, 2207, -1712), [-1, 3; -2, 5]] [Qfb(4, 3, -3), [127327, -416128; -148995, 486943]] Qfb(4, 3, -3) 4 -3 3/2 [Qfb(4, 3, -3), [127327, -416128; -148995, 486943]] Qfb(18446744073709551629, 4741036151112220792, 304625896260305173) Qfb(18446744073709551629, 7562574061564804959, 775103267656920011) [Qfb(1, 3161, -2020), 0.E-38] [Qfb(1, 3161, -2020), 0.E-38] [Qfb(-2020, 879, 1142), 4.2534194190682551490597749170464512664] [Qfb(-2020, 879, 1142), 4.2534194190682551490597749170464512664] [Qfb(1142, 879, -2020), -4.5388938608022665730118906813243859146] [Qfb(1142, 879, -2020), -4.5388938608022665730118906813243859146] [Qfb(-1045, 1991, 1444), 27.007896094723553897837109793403107911] [Qfb(-1045, 1991, 1444), 27.007896094723553897837109793403107911] [Qfb(-83, 3095, 1268), 9.4331465036326480252050895573872311672] [Qfb(-1757, 2109, 790), 5.0164695840555562190683281300124845079] test qfbred, large coefs 1 test qfbredsl2, large coefs 1 *** at top-level: qfbredsl2(q,1.) *** ^--------------- *** qfbredsl2: incorrect type in qfbredsl2 (t_REAL). *** at top-level: [1,2]*[1,2,4] *** ^-------- *** _*_: forbidden multiplication t_VEC (2 elts) * t_VEC (3 elts). *** at top-level: R*[1,2] *** ^------ *** _*_: forbidden multiplication t_VEC (2 elts) * t_VEC (2 elts). *** at top-level: [1,2]*R *** ^-- *** _*_: forbidden multiplication t_VEC (2 elts) * t_VEC (2 elts). *** at top-level: [i,0.]*[1,2] *** ^------ *** _*_: forbidden multiplication t_VEC (2 elts) * t_VEC (2 elts). *** at top-level: [1,2]*[i,0.] *** ^------- *** _*_: forbidden multiplication t_VEC (2 elts) * t_VEC (2 elts). *** at top-level: [i,0.]*[i,0.] *** ^------- *** _*_: forbidden multiplication t_VEC (2 elts) * t_VEC (2 elts). *** at top-level: f*g *** ^-- *** _*_: inconsistent multiplication t_QFB * t_QFB. *** at top-level: f/g *** ^-- *** _/_: inconsistent multiplication t_QFB * t_QFB. *** at top-level: f*g *** ^-- *** _*_: inconsistent multiplication t_QFB * t_QFB. *** at top-level: f/g *** ^-- *** _/_: inconsistent multiplication t_QFB * t_QFB. *** at top-level: Qfb(1,,2) *** ^--------- *** Qfb: incorrect type in Qfb (t_INT). *** at top-level: Qfb(1) *** ^------ *** Qfb: incorrect type in Qfb (t_INT). *** at top-level: Qfb(1,2) *** ^-------- *** Qfb: incorrect type in Qfb (t_INT). *** at top-level: Qfb(['x,2,3]) *** ^------------- *** Qfb: incorrect type in Qfb (t_POL). *** at top-level: ...18,-18);g=Qfb(11,52,-41);qfbcomp([f,1.],g) *** ^----------------- *** qfbcomp: sorry, Shanks's distance in general composition is not yet implemented. Total time spent: 165 pari-2.17.2/src/test/32/setdebug0000644000175000017500000000273414567450071014722 0ustar billbill ["alg" "arith" "bern" "bnf" "bnr" "bnrclassfield" "bb_group" "compiler" "ell " "ellanal" "ellcard" "ellisogeny" "ellrank" "ellsea" "factcyclo" "factor" " factorff" "factorint" "factormod" "fflog" "galois" "gammamellininv" "gchar" "genus2red" "hensel" "hgm" "hyperell" "intnum" "io" "isprime" "lfun" "mat" " mathnf" "mf" "mod" "mpqs" "ms" "mt" "nf" "nffactor" "nflist" "nfsubfields" " padicfields" "pol" "polclass" "polgalois" "polmodular" "polroots" "qf" "qfll l" "qfsolve" "qfisom" "quadclassunit" "rnf" "stark" "subcyclo" "subgrouplist " "thue" "trans" "zetamult"] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] 2 0 debug = 2 debug("bnf") = 2 debug("bnf") = 2 debug("bnf") = 1 debug("bnf") = 1 debug("bnf") = 1 debug("bnf") = 1 debug("bnf") = 2 debug("bnf") = 2 debugfiles = 10 *** at top-level: 1/0 *** ^-- *** _/_: impossible inverse in gdiv: 0. gp_context_restore: restoring pari_infile to stdin done debugfiles = 1 *** at top-level: setdebug("does_not_exist") *** ^-------------------------- *** setdebug: domain error in setdebug: does_not_exist not a valid debug domain debugfiles = 0 *** domain error in setdebug: does_not_exist not a valid debug domain *** domain error in setdebug: does_not_exist not a valid debug domain *** domain error in setdebug: does_not_exist not a valid debug domain Total time spent: 0 pari-2.17.2/src/test/32/install0000644000175000017500000000046714567450071014567 0ustar billbill"t_CLOSURE" 3 addii: installed function library name: addii prototype: GG addii: new identifier 5 "t_CLOSURE" *** not an ulong: GDL0,U, *** ^----- *** not a long: GDL0,L, *** ^----- *** not an ulong: GD-1,U, *** ^----- Total time spent: 0 pari-2.17.2/src/test/32/nfdiscfactors0000644000175000017500000000023114567450071015736 0ustar billbill[-4, Mat([2, 2])] [-3, Mat([3, 1])] [-18776600027605036223072206839903299223174857211437893915142967, [3, 6; 7, 5; 1073741827, 6]] Total time spent: 50 pari-2.17.2/src/test/32/ratpoints0000644000175000017500000005132314676526175015153 0ustar billbill1:[] 2:[[0, 2, 1], [0, -2, 1]] 3:[[0, 2, 1], [0, -2, 1], [-2, 346, 5], [-2, -346, 5]] 4:[[0, 0, 1]] 5:[] 6:[[0, 0, 1], [-1, 0, 1]] 7:[[-3, 6, 2], [-3, -6, 2]] 8:[] 9:[] 10:[] 11:[] 12:[[3, 31, 2], [3, -31, 2], [2, 51, 3], [2, -51, 3]] 13:[] 14:[[0, 0, 1], [-1, 2, 1], [-1, -2, 1]] 15:[] 16:[] 17:[] 18:[[1, 0, 1]] 19:[[-1, 1, 1], [-1, -1, 1], [1, 20, 2], [1, -20, 2]] 20:[[-1, 3, 1], [-1, -3, 1]] 21:[[0, 2, 1], [0, -2, 1]] 22:[[-2, 7, 1], [-2, -7, 1], [0, 1, 1], [0, -1, 1]] 23:[[-1, 2, 1], [-1, -2, 1]] 24:[[1, 11, 2], [1, -11, 2]] 25:[] 26:[[1, 1, 1], [1, -1, 1]] 27:[] 28:[] 29:[[-3, 38, 1], [-3, -38, 1], [-1, 2, 1], [-1, -2, 1], [1, 2, 1], [1, -2, 1 ], [7, 602, 1], [7, -602, 1], [1, 513, 6], [1, -513, 6]] 30:[] 31:[[0, 2, 1], [0, -2, 1]] 32:[[1, 1, 1], [1, -1, 1]] 33:[] 34:[[0, 0, 1], [-1, 3, 2], [-1, -3, 2]] 35:[[-1, 3, 1], [-1, -3, 1]] 36:[] 37:[] 38:[[0, 0, 1], [-1, 3, 1], [-1, -3, 1]] 39:[[0, 2, 1], [0, -2, 1]] 40:[] 41:[[0, 1, 1], [0, -1, 1]] 42:[] 43:[[0, 1, 1], [0, -1, 1]] 44:[[1, 2, 1], [1, -2, 1]] 45:[[0, 3, 1], [0, -3, 1], [1, 23, 2], [1, -23, 2]] 46:[] 47:[] 48:[[0, 2, 1], [0, -2, 1]] 49:[[-1, 4, 1], [-1, -4, 1]] 50:[[1, 3, 1], [1, -3, 1]] 51:[] 52:[[1, 4, 1], [1, -4, 1]] 53:[[-1, 2, 1], [-1, -2, 1], [-1, 4, 2], [-1, -4, 2]] 54:[[-1, 1, 1], [-1, -1, 1]] 55:[[0, 0, 1]] 56:[[1, 3, 1], [1, -3, 1]] 57:[[-1, 4, 1], [-1, -4, 1], [0, 3, 1], [0, -3, 1], [2, 107, 3], [2, -107, 3 ], [38, 1939745, 83], [38, -1939745, 83]] 58:[[0, 1, 1], [0, -1, 1], [1, 3, 2], [1, -3, 2], [-13, 6499, 9], [-13, -649 9, 9], [-49, 198463, 12], [-49, -198463, 12]] 59:[[1, 0, 1]] 60:[] 61:[] 62:[[0, 3, 1], [0, -3, 1]] 63:[] 64:[] 65:[[0, 3, 1], [0, -3, 1]] 66:[[0, 0, 1]] 67:[] 68:[] 69:[] 70:[[1, 3, 1], [1, -3, 1]] 71:[[1, 0, 1]] 72:[] 73:[] 74:[[0, 0, 1]] 75:[[0, 3, 1], [0, -3, 1]] 76:[] 77:[[0, 3, 1], [0, -3, 1]] 78:[[-1, 4, 1], [-1, -4, 1]] 79:[] 80:[] 81:[] 82:[] 83:[] 84:[[-1, 2, 1], [-1, -2, 1]] 85:[] 86:[] 87:[] 88:[] 89:[] 90:[] 91:[] 92:[[1, 1, 1], [1, -1, 1]] 93:[] 94:[[-1, 0, 1]] 95:[[0, 3, 1], [0, -3, 1], [4, 23, 1], [4, -23, 1]] 96:[[0, 1, 1], [0, -1, 1]] 97:[[0, 2, 1], [0, -2, 1]] 98:[[-1, 2, 1], [-1, -2, 1], [1, 2, 1], [1, -2, 1]] 99:[] 100:[[2, 3461, 11], [2, -3461, 11]] 101:[[-1, 1, 1], [-1, -1, 1]] 102:[[0, 1, 1], [0, -1, 1]] 103:[] 104:[] 105:[] 106:[] 107:[] 108:[[-1, 5, 1], [-1, -5, 1]] 109:[[-1, 1, 1], [-1, -1, 1]] 110:[[-2, 8, 1], [-2, -8, 1], [-1, 1, 1], [-1, -1, 1], [2, 16, 1], [2, -16, 1]] 111:[[0, 3, 1], [0, -3, 1]] 112:[] 113:[[1, 144, 4], [1, -144, 4]] 114:[] 115:[[3, 82, 2], [3, -82, 2]] 116:[] 117:[[2, 4, 1], [2, -4, 1]] 118:[[-1, 2, 1], [-1, -2, 1]] 119:[] 120:[] 121:[[0, 0, 1], [1, 2, 1], [1, -2, 1], [-2, 16, 1], [-2, -16, 1]] 122:[[0, 2, 1], [0, -2, 1], [3, 23, 1], [3, -23, 1]] 123:[] 124:[] 125:[[1, 3, 1], [1, -3, 1]] 126:[] 127:[[-1, 1, 1], [-1, -1, 1]] 128:[] 129:[] 130:[] 131:[] 132:[[0, 3, 1], [0, -3, 1]] 133:[] 134:[[0, 1, 1], [0, -1, 1]] 135:[] 136:[] 137:[[0, 2, 1], [0, -2, 1]] 138:[] 139:[] 140:[[-1, 3, 1], [-1, -3, 1], [2, 3, 1], [2, -3, 1], [3, 6, 2], [3, -6, 2]] 141:[[0, 3, 1], [0, -3, 1], [1, 6, 1], [1, -6, 1], [-4, 419, 7], [-4, -419, 7]] 142:[[1, 2, 1], [1, -2, 1], [7, 2996, 10], [7, -2996, 10]] 143:[] 144:[[1, 2, 1], [1, -2, 1]] 145:[[0, 2, 1], [0, -2, 1]] 146:[] 147:[[3, 49, 2], [3, -49, 2]] 148:[[-1, 18, 2], [-1, -18, 2]] 149:[] 150:[] 151:[[0, 0, 1]] 152:[[0, 3, 1], [0, -3, 1]] 153:[] 154:[[0, 2, 1], [0, -2, 1]] 155:[[-1, 1, 1], [-1, -1, 1]] 156:[[-2, 22, 1], [-2, -22, 1]] 157:[] 158:[[0, 1, 1], [0, -1, 1]] 159:[[1, 1, 1], [1, -1, 1]] 160:[] 161:[] 162:[] 163:[] 164:[] 165:[] 166:[[-1, 1, 1], [-1, -1, 1], [0, 3, 1], [0, -3, 1]] 167:[] 168:[[3, 1, 1], [3, -1, 1]] 169:[] 170:[] 171:[[1, 4, 1], [1, -4, 1]] 172:[[-1, 1, 1], [-1, -1, 1]] 173:[[0, 3, 1], [0, -3, 1], [1, 0, 1]] 174:[] 175:[] 176:[[1, 5, 1], [1, -5, 1]] 177:[[10, 3648, 7], [10, -3648, 7]] 178:[[-20, 21952, 1], [-20, -21952, 1], [0, 2, 1], [0, -2, 1]] 179:[[-1, 2, 1], [-1, -2, 1]] 180:[] 181:[[1, 1, 1], [1, -1, 1], [-27, 1795891, 89], [-27, -1795891, 89]] 182:[[-1, 5, 2], [-1, -5, 2]] 183:[] 184:[] 185:[] 186:[] 187:[] 188:[] 189:[[-1, 9, 2], [-1, -9, 2]] 190:[] 191:[] 192:[] 193:[[1, 3, 1], [1, -3, 1]] 194:[[-1, 1, 2], [-1, -1, 2], [1, 1, 1], [1, -1, 1]] 195:[] 196:[[-1, 1, 1], [-1, -1, 1]] 197:[] 198:[] 199:[[0, 2, 1], [0, -2, 1]] 200:[] 201:[[7, 357, 4], [7, -357, 4]] 202:[[0, 1, 1], [0, -1, 1]] 203:[] 204:[] 205:[] 206:[[1, 3, 1], [1, -3, 1]] 207:[] 208:[[0, 0, 1]] 209:[[-2, 9, 1], [-2, -9, 1]] 210:[[1, 0, 1]] 211:[[-1, 7, 2], [-1, -7, 2]] 212:[[0, 2, 1], [0, -2, 1]] 213:[[0, 1, 1], [0, -1, 1]] 214:[[0, 2, 1], [0, -2, 1], [2, 12, 3], [2, -12, 3]] 215:[] 216:[] 217:[[-2, 3, 1], [-2, -3, 1], [-1, 0, 1], [0, 1, 1], [0, -1, 1], [-6, 133, 5 ], [-6, -133, 5]] 218:[] 219:[[-1, 75, 4], [-1, -75, 4]] 220:[] 221:[[-1, 3, 1], [-1, -3, 1]] 222:[] 223:[[1, 3, 1], [1, -3, 1]] 224:[] 225:[] 226:[] 227:[] 228:[[0, 3, 1], [0, -3, 1], [2, 21, 1], [2, -21, 1]] 229:[] 230:[] 231:[[0, 1, 1], [0, -1, 1], [1, 5, 2], [1, -5, 2]] 232:[] 233:[[0, 3, 1], [0, -3, 1]] 234:[] 235:[] 236:[[0, 2, 1], [0, -2, 1]] 237:[[-1, 1, 1], [-1, -1, 1], [1, 101, 4], [1, -101, 4]] 238:[[-1, 2, 1], [-1, -2, 1], [1, 13, 2], [1, -13, 2]] 239:[[-3, 58, 1], [-3, -58, 1]] 240:[[1, 4, 1], [1, -4, 1], [3, 1408, 8], [3, -1408, 8]] 241:[] 242:[[0, 1, 1], [0, -1, 1]] 243:[[1, 2, 1], [1, -2, 1]] 244:[] 245:[] 246:[[-2, 9, 1], [-2, -9, 1]] 247:[[1, 4, 1], [1, -4, 1]] 248:[[-1, 3, 1], [-1, -3, 1]] 249:[] 250:[] 251:[] 252:[] 253:[] 254:[] 255:[[-1, 1, 1], [-1, -1, 1]] 256:[] 257:[] 258:[] 259:[[0, 1, 1], [0, -1, 1]] 260:[] 261:[] 262:[] 263:[[0, 0, 1]] 264:[[0, 1, 1], [0, -1, 1]] 265:[] 266:[] 267:[[1, 1, 1], [1, -1, 1]] 268:[] 269:[] 270:[] 271:[] 272:[] 273:[[0, 2, 1], [0, -2, 1]] 274:[[-4, 114, 1], [-4, -114, 1]] 275:[[0, 3, 1], [0, -3, 1]] 276:[] 277:[] 278:[] 279:[] 280:[] 281:[] 282:[[0, 2, 1], [0, -2, 1]] 283:[[-1, 3, 1], [-1, -3, 1]] 284:[] 285:[] 286:[[0, 3, 1], [0, -3, 1]] 287:[[20, 25315, 19], [20, -25315, 19]] 288:[] 289:[[-1, 1, 1], [-1, -1, 1]] 290:[] 291:[[0, 3, 1], [0, -3, 1], [3, 291, 5], [3, -291, 5]] 292:[] 293:[] 294:[] 295:[] 296:[] 297:[] 298:[] 299:[] 300:[] 301:[] 302:[[0, 3, 1], [0, -3, 1]] 303:[] 304:[[-2, 37, 3], [-2, -37, 3]] 305:[[-1, 2, 1], [-1, -2, 1], [1, 2, 1], [1, -2, 1]] 306:[] 307:[] 308:[] 309:[] 310:[[0, 3, 1], [0, -3, 1]] 311:[] 312:[[0, 3, 1], [0, -3, 1]] 313:[] 314:[] 315:[] 316:[] 317:[[0, 2, 1], [0, -2, 1], [1, 0, 1]] 318:[] 319:[[0, 3, 1], [0, -3, 1], [-704, 40680297, 933], [-704, -40680297, 933]] 320:[[0, 0, 1]] 321:[[-1, 1, 1], [-1, -1, 1], [1, 5, 1], [1, -5, 1]] 322:[] 323:[[36, 131678, 1], [36, -131678, 1]] 324:[[0, 2, 1], [0, -2, 1]] 325:[] 326:[] 327:[] 328:[[-1, 1, 1], [-1, -1, 1], [1, 11, 2], [1, -11, 2], [1, 503, 6], [1, -503 , 6], [2, 13, 1], [2, -13, 1], [3, 113, 5], [3, -113, 5]] 329:[[0, 0, 1]] 330:[[1, 3, 1], [1, -3, 1]] 331:[] 332:[[1, 3, 1], [1, -3, 1]] 333:[] 334:[] 335:[] 336:[[-3, 10, 1], [-3, -10, 1], [0, 2, 1], [0, -2, 1], [-1, 46, 3], [-1, -46 , 3]] 337:[] 338:[[0, 0, 1]] 339:[] 340:[[0, 1, 1], [0, -1, 1], [-1, 16, 2], [-1, -16, 2]] 341:[[93, 594431, 28], [93, -594431, 28]] 342:[[0, 1, 1], [0, -1, 1]] 343:[[-1, 2, 1], [-1, -2, 1]] 344:[] 345:[[1, 0, 1]] 346:[[0, 2, 1], [0, -2, 1]] 347:[[0, 0, 1]] 348:[] 349:[[0, 2, 1], [0, -2, 1], [1, 5, 1], [1, -5, 1]] 350:[] 351:[[-1, 0, 1], [0, 2, 1], [0, -2, 1], [1, 0, 1]] 352:[[0, 2, 1], [0, -2, 1], [1, 0, 1]] 353:[] 354:[] 355:[] 356:[[0, 3, 1], [0, -3, 1]] 357:[[0, 2, 1], [0, -2, 1]] 358:[[0, 0, 1], [-1, 2, 1], [-1, -2, 1], [1, 11, 2], [1, -11, 2]] 359:[] 360:[] 361:[] 362:[] 363:[] 364:[] 365:[[1, 3, 1], [1, -3, 1]] 366:[] 367:[] 368:[[0, 0, 1]] 369:[] 370:[[0, 3, 1], [0, -3, 1]] 371:[[-1, 0, 1], [-2, 0, 7]] 372:[] 373:[] 374:[] 375:[[-1, 0, 1]] 376:[] 377:[] 378:[] 379:[[0, 0, 1]] 380:[] 381:[[0, 2, 1], [0, -2, 1]] 382:[] 383:[] 384:[[-2, 92, 3], [-2, -92, 3]] 385:[] 386:[[1, 0, 1]] 387:[[0, 0, 1]] 388:[] 389:[] 390:[[-1, 4, 1], [-1, -4, 1]] 391:[] 392:[[-4, 190, 1], [-4, -190, 1]] 393:[] 394:[[-1, 0, 1]] 395:[] 396:[[-1, 3, 1], [-1, -3, 1]] 397:[] 398:[] 399:[[-1, 2, 1], [-1, -2, 1]] 400:[[1, 2, 1], [1, -2, 1]] 401:[[-5, 159, 3], [-5, -159, 3]] 402:[] 403:[[-1, 3, 1], [-1, -3, 1]] 404:[[-2, 11, 1], [-2, -11, 1]] 405:[] 406:[] 407:[] 408:[[2, 6, 1], [2, -6, 1]] 409:[] 410:[] 411:[[-2, 13, 1], [-2, -13, 1]] 412:[] 413:[] 414:[[-5, 95, 4], [-5, -95, 4]] 415:[] 416:[] 417:[[-1, 6, 1], [-1, -6, 1]] 418:[[2, 1, 1], [2, -1, 1]] 419:[] 420:[[1, 2, 2], [1, -2, 2]] 421:[] 422:[] 423:[] 424:[[1, 1, 1], [1, -1, 1]] 425:[] 426:[] 427:[[-1, 2, 1], [-1, -2, 1], [0, 1, 1], [0, -1, 1]] 428:[] 429:[[-2, 9, 1], [-2, -9, 1], [0, 3, 1], [0, -3, 1]] 430:[] 431:[] 432:[[1, 5, 1], [1, -5, 1]] 433:[[4, 43, 5], [4, -43, 5]] 434:[] 435:[[1, 0, 1], [-3, 42, 4], [-3, -42, 4]] 436:[] 437:[] 438:[[1, 3, 1], [1, -3, 1]] 439:[[1, 0, 1]] 440:[[1, 2, 1], [1, -2, 1]] 441:[[5, 1735, 8], [5, -1735, 8], [-11, 7265, 16], [-11, -7265, 16]] 442:[] 443:[[0, 3, 1], [0, -3, 1]] 444:[[-2, 9, 1], [-2, -9, 1]] 445:[[1, 2, 1], [1, -2, 1]] 446:[[-1, 2, 1], [-1, -2, 1]] 447:[] 448:[] 449:[[0, 3, 1], [0, -3, 1]] 450:[] 451:[] 452:[] 453:[] 454:[[-1, 2, 1], [-1, -2, 1]] 455:[] 456:[] 457:[] 458:[] 459:[[-1, 0, 1]] 460:[] 461:[] 462:[[-1, 3, 1], [-1, -3, 1]] 463:[] 464:[] 465:[[0, 1, 1], [0, -1, 1]] 466:[[2, 11, 1], [2, -11, 1]] 467:[[0, 0, 1], [1, 10, 2], [1, -10, 2]] 468:[[-1, 460, 6], [-1, -460, 6]] 469:[[-2, 20, 1], [-2, -20, 1]] 470:[[-1, 3, 1], [-1, -3, 1], [-6, 368, 5], [-6, -368, 5]] 471:[[1, 3, 1], [1, -3, 1]] 472:[] 473:[] 474:[[0, 2, 1], [0, -2, 1]] 475:[[-1, 3, 1], [-1, -3, 1], [11, 2535, 1], [11, -2535, 1]] 476:[] 477:[[1, 19, 2], [1, -19, 2]] 478:[] 479:[[-1, 3, 1], [-1, -3, 1], [0, 2, 1], [0, -2, 1]] 480:[] 481:[] 482:[] 483:[] 484:[[1, 2, 1], [1, -2, 1], [-1, 11, 2], [-1, -11, 2]] 485:[] 486:[] 487:[[1, 3, 1], [1, -3, 1]] 488:[] 489:[[-2, 4, 1], [-2, -4, 1]] 490:[[-1, 27, 2], [-1, -27, 2]] 491:[] 492:[] 493:[] 494:[[0, 0, 1]] 495:[[0, 1, 1], [0, -1, 1]] 496:[] 497:[[-1, 3, 1], [-1, -3, 1], [0, 1, 1], [0, -1, 1], [3, 74, 2], [3, -74, 2] , [-8, 1591, 7], [-8, -1591, 7]] 498:[] 499:[] 500:[] 501:[[-1, 5, 1], [-1, -5, 1]] 502:[[-1, 4, 1], [-1, -4, 1]] 503:[[0, 1, 1], [0, -1, 1]] 504:[] 505:[[2, 76, 3], [2, -76, 3], [7, 7780, 15], [7, -7780, 15]] 506:[[0, 1, 1], [0, -1, 1], [1, 1, 1], [1, -1, 1], [3, 10, 2], [3, -10, 2]] 507:[[0, 1, 1], [0, -1, 1], [-4, 95, 3], [-4, -95, 3]] 508:[[1, 1, 1], [1, -1, 1], [-1, 55, 3], [-1, -55, 3], [2, 64, 3], [2, -64, 3]] 509:[[3, 57, 2], [3, -57, 2]] 510:[[2, 14, 1], [2, -14, 1]] 511:[[-1, 4, 1], [-1, -4, 1]] 512:[] 513:[[-3, 5, 1], [-3, -5, 1]] 514:[[0, 3, 1], [0, -3, 1]] 515:[] 516:[[0, 3, 1], [0, -3, 1]] 517:[[-1, 5, 1], [-1, -5, 1], [1, 1, 1], [1, -1, 1], [1, 22, 2], [1, -22, 2] ] 518:[] 519:[] 520:[[-1, 0, 1], [0, 1, 1], [0, -1, 1]] 521:[[-7, 521, 5], [-7, -521, 5]] 522:[] 523:[] 524:[] 525:[] 526:[[-2, 20, 1], [-2, -20, 1], [1, 2, 1], [1, -2, 1], [22, 31638, 15], [22, -31638, 15]] 527:[] 528:[] 529:[[1, 3, 1], [1, -3, 1]] 530:[] 531:[] 532:[[-1, 1, 1], [-1, -1, 1]] 533:[] 534:[] 535:[] 536:[] 537:[] 538:[[1, 4, 1], [1, -4, 1], [1, 23, 2], [1, -23, 2]] 539:[] 540:[] 541:[[0, 3, 1], [0, -3, 1], [-5, 257, 4], [-5, -257, 4]] 542:[] 543:[[-1, 3, 1], [-1, -3, 1]] 544:[] 545:[[-1, 0, 1], [0, 3, 1], [0, -3, 1]] 546:[[-1, 0, 1]] 547:[[0, 0, 1]] 548:[[0, 3, 1], [0, -3, 1], [-5, 348, 6], [-5, -348, 6]] 549:[] 550:[] 551:[] 552:[[-1, 1, 1], [-1, -1, 1]] 553:[] 554:[] 555:[] 556:[] 557:[[0, 3, 1], [0, -3, 1]] 558:[] 559:[[0, 3, 1], [0, -3, 1]] 560:[] 561:[[-1, 7, 2], [-1, -7, 2]] 562:[] 563:[] 564:[] 565:[] 566:[[3, 3, 2], [3, -3, 2]] 567:[] 568:[] 569:[] 570:[] 571:[] 572:[] 573:[] 574:[[0, 3, 1], [0, -3, 1]] 575:[] 576:[[1, 4, 1], [1, -4, 1]] 577:[] 578:[] 579:[] 580:[[1, 0, 1]] 581:[] 582:[[0, 1, 1], [0, -1, 1]] 583:[] 584:[[-1, 4, 1], [-1, -4, 1]] 585:[[0, 1, 1], [0, -1, 1]] 586:[[0, 1, 1], [0, -1, 1]] 587:[] 588:[] 589:[[4, 100, 1], [4, -100, 1]] 590:[[1, 0, 1], [-313, 27928221051, 2496], [-313, -27928221051, 2496]] 591:[] 592:[[0, 1, 1], [0, -1, 1]] 593:[] 594:[] 595:[] 596:[] 597:[] 598:[[0, 2, 1], [0, -2, 1]] 599:[] 600:[[1, 3, 1], [1, -3, 1]] 601:[] 602:[[-1, 0, 1]] 603:[] 604:[[-1, 4, 1], [-1, -4, 1]] 605:[[0, 3, 1], [0, -3, 1]] 606:[[1, 1, 1], [1, -1, 1]] 607:[] 608:[[-3, 81, 1], [-3, -81, 1]] 609:[[-47, 3295394, 104], [-47, -3295394, 104]] 610:[[0, 2, 1], [0, -2, 1]] 611:[[-1, 5, 1], [-1, -5, 1]] 612:[[1, 1, 1], [1, -1, 1]] 613:[[-1, 5, 1], [-1, -5, 1]] 614:[[1, 0, 1]] 615:[] 616:[[-1, 53, 4], [-1, -53, 4]] 617:[] 618:[[-2, 16, 1], [-2, -16, 1], [-1, 0, 1], [0, 2, 1], [0, -2, 1], [5, 198, 1], [5, -198, 1], [1, 27, 2], [1, -27, 2], [7, 5094, 11], [7, -5094, 11]] 619:[[0, 2, 1], [0, -2, 1], [3, 20, 4], [3, -20, 4]] 620:[] 621:[[0, 0, 1]] 622:[] 623:[] 624:[[1, 4, 1], [1, -4, 1]] 625:[] 626:[] 627:[] 628:[[0, 1, 1], [0, -1, 1], [-57, 543145, 112], [-57, -543145, 112]] 629:[[0, 3, 1], [0, -3, 1]] 630:[[0, 3, 1], [0, -3, 1]] 631:[] 632:[[-1, 2, 1], [-1, -2, 1], [1, 0, 1]] 633:[] 634:[] 635:[] 636:[] 637:[[0, 3, 1], [0, -3, 1]] 638:[[-1, 3, 1], [-1, -3, 1], [0, 3, 1], [0, -3, 1]] 639:[[-1, 3, 1], [-1, -3, 1]] 640:[] 641:[] 642:[[-4, 170, 1], [-4, -170, 1], [0, 2, 1], [0, -2, 1]] 643:[[-8, 604, 1], [-8, -604, 1], [-2, 22, 1], [-2, -22, 1], [-1, 5, 1], [-1 , -5, 1], [0, 0, 1], [1, 1, 1], [1, -1, 1], [-1, 381, 9], [-1, -381, 9], [1, 4, 2], [1, -4, 2], [-9, 3228, 8], [-9, -3228, 8], [-1, 95, 5], [-1, -95, 5] , [9, 1200, 10], [9, -1200, 10]] 644:[[0, 1, 1], [0, -1, 1], [1, 3, 1], [1, -3, 1]] 645:[] 646:[] 647:[[1, 1, 1], [1, -1, 1]] 648:[[0, 1, 1], [0, -1, 1]] 649:[[0, 1, 1], [0, -1, 1]] 650:[] 651:[[1, 0, 1], [-4, 123, 5], [-4, -123, 5]] 652:[] 653:[[0, 3, 1], [0, -3, 1]] 654:[] 655:[[0, 2, 1], [0, -2, 1]] 656:[] 657:[] 658:[[0, 1, 1], [0, -1, 1]] 659:[] 660:[] 661:[[0, 0, 1], [-1, 2, 1], [-1, -2, 1], [1, 8, 2], [1, -8, 2]] 662:[[0, 2, 1], [0, -2, 1], [1, 2, 1], [1, -2, 1]] 663:[[-1, 5, 1], [-1, -5, 1], [0, 3, 1], [0, -3, 1], [2, 17, 1], [2, -17, 1] ] 664:[[-1, 3, 1], [-1, -3, 1]] 665:[[-3, 112, 2], [-3, -112, 2]] 666:[] 667:[] 668:[] 669:[[-1, 2, 1], [-1, -2, 1]] 670:[[1, 2, 1], [1, -2, 1]] 671:[] 672:[] 673:[[-1, 1, 1], [-1, -1, 1], [-1, 7, 2], [-1, -7, 2]] 674:[] 675:[] 676:[[0, 1, 1], [0, -1, 1]] 677:[] 678:[[-1, 1, 1], [-1, -1, 1]] 679:[] 680:[] 681:[] 682:[[0, 0, 1]] 683:[[0, 3, 1], [0, -3, 1]] 684:[] 685:[] 686:[[1, 2, 1], [1, -2, 1]] 687:[] 688:[] 689:[[0, 0, 1]] 690:[[2, 5, 1], [2, -5, 1], [3, 50, 1], [3, -50, 1]] 691:[[0, 3, 1], [0, -3, 1]] 692:[[-1, 25, 3], [-1, -25, 3]] 693:[] 694:[] 695:[] 696:[] 697:[] 698:[] 699:[] 700:[[-1, 4, 1], [-1, -4, 1]] 701:[] 702:[[-1, 4, 1], [-1, -4, 1]] 703:[[0, 2, 1], [0, -2, 1], [1, 1, 1], [1, -1, 1], [63, 338641, 71], [63, -3 38641, 71], [168, 8223850, 205], [168, -8223850, 205]] 704:[[1, 2, 1], [1, -2, 1]] 705:[[4, 10, 3], [4, -10, 3]] 706:[] 707:[] 708:[] 709:[[0, 1, 1], [0, -1, 1]] 710:[[-1, 2, 1], [-1, -2, 1]] 711:[[0, 2, 1], [0, -2, 1]] 712:[[-1, 5, 1], [-1, -5, 1], [-2, 24, 1], [-2, -24, 1]] 713:[] 714:[[-4, 16, 1], [-4, -16, 1], [0, 2, 1], [0, -2, 1], [1, 187, 5], [1, -187 , 5]] 715:[] 716:[[-1, 3, 1], [-1, -3, 1]] 717:[] 718:[[-1, 0, 1], [0, 2, 1], [0, -2, 1]] 719:[[-1, 2, 1], [-1, -2, 1]] 720:[] 721:[] 722:[[-1, 3, 1], [-1, -3, 1]] 723:[] 724:[[1, 16, 2], [1, -16, 2], [-1, 71, 3], [-1, -71, 3], [-5, 820, 6], [-5, -820, 6], [71, 117115, 51], [71, -117115, 51]] 725:[] 726:[[1, 0, 1]] 727:[] 728:[] 729:[] 730:[] 731:[] 732:[[1, 5, 2], [1, -5, 2], [5, 209, 8], [5, -209, 8]] 733:[] 734:[] 735:[[-1, 1, 1], [-1, -1, 1], [1, 1, 1], [1, -1, 1], [4, 1, 1], [4, -1, 1]] 736:[] 737:[] 738:[[0, 1, 1], [0, -1, 1]] 739:[[1, 0, 1]] 740:[] 741:[[0, 2, 1], [0, -2, 1], [1, 0, 1], [10, 2328, 1], [10, -2328, 1], [-9, 7 67, 4], [-9, -767, 4]] 742:[] 743:[[1, 4, 1], [1, -4, 1]] 744:[[-1, 1, 1], [-1, -1, 1]] 745:[[-2, 10, 1], [-2, -10, 1], [1, 2, 1], [1, -2, 1]] 746:[] 747:[[3, 67, 1], [3, -67, 1], [-1, 4, 2], [-1, -4, 2]] 748:[] 749:[] 750:[[-2, 12, 1], [-2, -12, 1]] 751:[] 752:[] 753:[] 754:[[0, 1, 1], [0, -1, 1]] 755:[] 756:[] 757:[] 758:[] 759:[[0, 2, 1], [0, -2, 1]] 760:[[5, 2086, 13], [5, -2086, 13]] 761:[[0, 3, 1], [0, -3, 1]] 762:[] 763:[] 764:[[0, 1, 1], [0, -1, 1]] 765:[[-2, 23, 3], [-2, -23, 3]] 766:[] 767:[] 768:[[1, 4, 1], [1, -4, 1]] 769:[[-1, 537, 6], [-1, -537, 6], [41, 636063, 51], [41, -636063, 51]] 770:[] 771:[] 772:[[-1, 1, 1], [-1, -1, 1]] 773:[] 774:[] 775:[] 776:[[0, 3, 1], [0, -3, 1], [1, 25, 2], [1, -25, 2], [-1, 209, 4], [-1, -209 , 4]] 777:[[0, 2, 1], [0, -2, 1]] 778:[[2, 10, 1], [2, -10, 1]] 779:[[0, 1, 1], [0, -1, 1], [3, 241, 5], [3, -241, 5]] 780:[] 781:[] 782:[] 783:[] 784:[[0, 0, 1], [-3, 102, 2], [-3, -102, 2], [12, 34950, 23], [12, -34950, 2 3]] 785:[] 786:[[1, 2, 1], [1, -2, 1]] 787:[[-1, 3, 1], [-1, -3, 1]] 788:[[0, 2, 1], [0, -2, 1]] 789:[] 790:[] 791:[] 792:[[-1, 3, 1], [-1, -3, 1], [0, 1, 1], [0, -1, 1]] 793:[] 794:[] 795:[[0, 0, 1], [1, 0, 2]] 796:[[-2, 6, 1], [-2, -6, 1], [-1, 0, 1]] 797:[[0, 3, 1], [0, -3, 1]] 798:[[-1, 1, 1], [-1, -1, 1]] 799:[] 800:[[-1, 1, 1], [-1, -1, 1], [0, 3, 1], [0, -3, 1]] 801:[[-2, 17, 1], [-2, -17, 1], [5, 368, 1], [5, -368, 1]] 802:[] 803:[] 804:[[0, 1, 1], [0, -1, 1], [1, 0, 1]] 805:[[-1, 0, 1]] 806:[] 807:[[0, 2, 1], [0, -2, 1], [3, 2357, 10], [3, -2357, 10]] 808:[] 809:[] 810:[] 811:[[-1, 0, 1], [0, 3, 1], [0, -3, 1]] 812:[] 813:[] 814:[] 815:[] 816:[] 817:[] 818:[] 819:[] 820:[] 821:[[1, 3, 1], [1, -3, 1]] 822:[] 823:[[0, 3, 1], [0, -3, 1]] 824:[] 825:[[-1, 6, 1], [-1, -6, 1], [0, 3, 1], [0, -3, 1]] 826:[[-1, 70, 3], [-1, -70, 3]] 827:[] 828:[[1, 1, 1], [1, -1, 1]] 829:[] 830:[[0, 2, 1], [0, -2, 1]] 831:[[-1, 0, 1], [4, 190, 1], [4, -190, 1]] 832:[] 833:[[-2, 1, 1], [-2, -1, 1]] 834:[[-3, 27, 2], [-3, -27, 2], [-1, 9, 2], [-1, -9, 2]] 835:[[-1, 4, 1], [-1, -4, 1]] 836:[] 837:[[0, 2, 1], [0, -2, 1]] 838:[] 839:[] 840:[[1, 12, 2], [1, -12, 2], [-1, 180, 4], [-1, -180, 4], [4, 9039, 17], [4 , -9039, 17]] 841:[[0, 2, 1], [0, -2, 1], [-1, 25, 2], [-1, -25, 2]] 842:[] 843:[[-1, 4, 1], [-1, -4, 1]] 844:[] 845:[] 846:[[-1, 4, 1], [-1, -4, 1]] 847:[[3, 265, 5], [3, -265, 5]] 848:[] 849:[] 850:[] 851:[] 852:[] 853:[] 854:[[-1, 3, 1], [-1, -3, 1]] 855:[] 856:[[1, 3, 1], [1, -3, 1]] 857:[] 858:[[1, 11, 2], [1, -11, 2]] 859:[] 860:[] 861:[] 862:[] 863:[[2, 12, 1], [2, -12, 1]] 864:[[0, 2, 1], [0, -2, 1]] 865:[] 866:[[0, 2, 1], [0, -2, 1]] 867:[] 868:[] 869:[] 870:[] 871:[] 872:[] 873:[] 874:[[1, 2, 1], [1, -2, 1]] 875:[[13, 6807, 9], [13, -6807, 9]] 876:[] 877:[[-1, 1, 1], [-1, -1, 1]] 878:[[0, 2, 1], [0, -2, 1], [1, 2, 1], [1, -2, 1], [4, 154, 1], [4, -154, 1] ] 879:[[1, 24, 2], [1, -24, 2]] 880:[] 881:[] 882:[[1, 3, 1], [1, -3, 1]] 883:[[-1, 1, 1], [-1, -1, 1]] 884:[] 885:[[-3, 80, 2], [-3, -80, 2]] 886:[] 887:[[1, 0, 1]] 888:[] 889:[[-1, 4, 1], [-1, -4, 1]] 890:[] 891:[[0, 3, 1], [0, -3, 1], [92, 14946963, 209], [92, -14946963, 209]] 892:[] 893:[] 894:[] 895:[[-2, 27, 1], [-2, -27, 1]] 896:[] 897:[[0, 1, 1], [0, -1, 1], [-1, 12, 2], [-1, -12, 2], [3, 56, 2], [3, -56, 2]] 898:[[0, 1, 1], [0, -1, 1]] 899:[] 900:[[0, 3, 1], [0, -3, 1]] 901:[[0, 2, 1], [0, -2, 1]] 902:[[1, 0, 1]] 903:[] 904:[] 905:[[1, 0, 1]] 906:[] 907:[] 908:[] 909:[[-1, 3, 1], [-1, -3, 1]] 910:[[-1, 2, 1], [-1, -2, 1]] 911:[] 912:[] 913:[[-1, 1, 1], [-1, -1, 1]] 914:[] 915:[] 916:[] 917:[[-1, 3, 1], [-1, -3, 1], [0, 1, 1], [0, -1, 1]] 918:[[-1, 3, 1], [-1, -3, 1], [-1, 23, 2], [-1, -23, 2], [14, 4236, 13], [14 , -4236, 13]] 919:[] 920:[[0, 3, 1], [0, -3, 1]] 921:[] 922:[] 923:[] 924:[] 925:[] 926:[[-1, 1, 1], [-1, -1, 1], [1, 1, 1], [1, -1, 1]] 927:[] 928:[] 929:[[0, 2, 1], [0, -2, 1], [1, 0, 1], [7, 1990, 11], [7, -1990, 11]] 930:[] 931:[[0, 0, 1]] 932:[[-1, 14, 2], [-1, -14, 2]] 933:[] 934:[] 935:[[1, 1, 1], [1, -1, 1]] 936:[[0, 0, 1]] 937:[] 938:[] 939:[] 940:[] 941:[] 942:[[0, 1, 1], [0, -1, 1]] 943:[] 944:[[0, 2, 1], [0, -2, 1], [1, 2, 2], [1, -2, 2]] 945:[] 946:[[1, 1, 1], [1, -1, 1]] 947:[] 948:[[-2, 8, 1], [-2, -8, 1], [-1, 4, 1], [-1, -4, 1], [0, 2, 1], [0, -2, 1] , [3, 38, 1], [3, -38, 1], [6, 200, 1], [6, -200, 1], [127, 3151792, 49], [1 27, -3151792, 49], [1, 16, 2], [1, -16, 2], [325, 2360754224, 1058], [325, - 2360754224, 1058]] 949:[[3, 81, 4], [3, -81, 4]] 950:[] 951:[] 952:[[1, 2, 1], [1, -2, 1]] 953:[] 954:[[-1, 4, 1], [-1, -4, 1]] 955:[] 956:[[1, 2, 2], [1, -2, 2]] 957:[] 958:[] 959:[[1, 19, 2], [1, -19, 2]] 960:[] 961:[] 962:[] 963:[[-3, 39, 1], [-3, -39, 1], [-2, 9, 1], [-2, -9, 1]] 964:[] 965:[[2, 3, 1], [2, -3, 1]] 966:[[1, 1, 1], [1, -1, 1]] 967:[] 968:[] 969:[] 970:[[0, 1, 1], [0, -1, 1], [-3, 287, 5], [-3, -287, 5]] 971:[] 972:[[1, 2, 1], [1, -2, 1]] 973:[] 974:[] 975:[] 976:[[-1, 3, 1], [-1, -3, 1], [1, 1, 1], [1, -1, 1]] 977:[] 978:[[0, 2, 1], [0, -2, 1]] 979:[[0, 3, 1], [0, -3, 1], [1, 1, 1], [1, -1, 1]] 980:[[0, 2, 1], [0, -2, 1]] 981:[[-1, 1, 1], [-1, -1, 1]] 982:[] 983:[[1, 1, 1], [1, -1, 1], [-1, 23, 2], [-1, -23, 2]] 984:[[0, 0, 1], [-1, 0, 1], [3, 0, 2]] 985:[] 986:[[0, 3, 1], [0, -3, 1]] 987:[] 988:[] 989:[] 990:[] 991:[[-1, 3, 1], [-1, -3, 1]] 992:[] 993:[[1, 3, 1], [1, -3, 1]] 994:[] 995:[[1, 1, 1], [1, -1, 1]] 996:[[0, 0, 1]] 997:[] 998:[[0, 2, 1], [0, -2, 1]] 999:[] 1000:[[0, 2, 1], [0, -2, 1]] 1001:[[-3, 15, 1], [-3, -15, 1], [0, 0, 1]] Total time spent: 4593 pari-2.17.2/src/test/32/factorff0000644000175000017500000001226014567450071014705 0ustar billbill[t, t^2 + 1, -t^2 - t + 1]~ [t^2, t^2 + t + 1, t^2 - t + 1]~ [Mod(Mod(1, 2), Mod(1, 2)*y^2 + Mod(1, 2)*y + Mod(1, 2))]~ [x + 1 6] [x + t 6] [1 6] [1 6] []~ []~ [x + a 1] [x, x + 1, x + 2, x + a, x + (a + 1), x + (a + 2), x + (2*a + 1), x + (2*a + 2), x + a^2, x + (a^2 + 1), x + (a^2 + 2), x + (a^2 + a), x + (a^2 + a + 1) , x + (a^2 + a + 2), x + (a^2 + 2*a), x + (a^2 + 2*a + 1), x + (a^2 + 2*a + 2), x + 2*a^2, x + (2*a^2 + 1), x + (2*a^2 + 2), x + (2*a^2 + a), x + (2*a^2 + a + 1), x + (2*a^2 + a + 2), x + (2*a^2 + 2*a), x + (2*a^2 + 2*a + 1), x + (2*a^2 + 2*a + 2)]~ check 2 Mat([0, 1]) matrix(0,2) Mat([0, 1]) matrix(0,2) matrix(0,2) matrix(0,2) Mat([x + (a^2 + a), 1]) Mat([1, 1]) Mat([x + (a^2 + a), 1]) Mat([x + a, 2]) Mat([1, 2]) Mat([x + a, 2]) Mat([x^2 + x + a, 1]) Mat([2, 1]) Mat([x^2 + x + a, 1]) Mat([x + (a^2 + 1), 2]) Mat([1, 2]) Mat([x + (a^2 + 1), 2]) [x + (a^2 + a + 1), 1; x^2 + (a^2 + a + 1)*x + a^2, 1] [1, 1; 2, 1] [x + (a^2 + a + 1), 1; x^2 + (a^2 + a + 1)*x + a^2, 1] check 3 Mat([0, 1]) matrix(0,2) Mat([0, 1]) matrix(0,2) matrix(0,2) matrix(0,2) Mat([x + (2*a^2 + 1), 1]) Mat([1, 1]) Mat([x + (2*a^2 + 1), 1]) [x + a, 1; x + 2*a, 1] [1, 1; 1, 1] [x + a, 1; x + 2*a, 1] Mat([x^2 + x + a, 1]) Mat([2, 1]) Mat([x^2 + x + a, 1]) Mat([x^2 + (a^2 + 2), 1]) Mat([2, 1]) Mat([x^2 + (a^2 + 2), 1]) [x + (2*a^2 + 2), 1; x^2 + (a^2 + 1)*x + (a^2 + a), 1] [1, 1; 2, 1] [x + (2*a^2 + 2), 1; x^2 + (a^2 + 1)*x + (a^2 + a), 1] check 1267650600228229401496703205653 Mat([0, 1]) matrix(0,2) Mat([0, 1]) matrix(0,2) matrix(0,2) matrix(0,2) Mat([x + (a^2 + a + 1267650600228229401496703205649), 1]) Mat([1, 1]) Mat([x + (a^2 + a + 1267650600228229401496703205649), 1]) [x + a, 1; x + 1267650600228229401496703205652*a, 1] [1, 1; 1, 1] [x + a, 1; x + 1267650600228229401496703205652*a, 1] Mat([x^2 + x + a, 1]) Mat([2, 1]) Mat([x^2 + x + a, 1]) [x + (248056872368006019846473856603*a^2 + 632070353960340619554852923412*a + 686373698767074524134118021946), 1; x + (1019593727860223381650229349050*a ^2 + 635580246267888781941850282241*a + 581276901461154877362585183707), 1] [1, 1; 1, 1] [x + (248056872368006019846473856603*a^2 + 632070353960340619554852923412*a + 686373698767074524134118021946), 1; x + (1019593727860223381650229349050*a ^2 + 635580246267888781941850282241*a + 581276901461154877362585183707), 1] [x + (444781501243445200409703971769*a^2 + 380007214266207022733465160082*a + 1196315968196929648722484158008), 1; x^2 + (822869098984784201086999233884 *a^2 + 887643385962022378763238045571*a + 71334632031299752774219047645)*x + (920324322169569708634203378635*a^2 + 325733854995540949882328420355*a + 52 2626156517642858900111418754), 1] [1, 1; 2, 1] [x + (444781501243445200409703971769*a^2 + 380007214266207022733465160082*a + 1196315968196929648722484158008), 1; x^2 + (822869098984784201086999233884 *a^2 + 887643385962022378763238045571*a + 71334632031299752774219047645)*x + (920324322169569708634203378635*a^2 + 325733854995540949882328420355*a + 52 2626156517642858900111418754), 1] [ x + 1 1] [ x + 2 1] [ x + 3 1] [ x + 4 1] [ x + (t^3 + 4*t) 1] [ x + (t^3 + 4*t + 1) 1] [ x + (t^3 + 4*t + 2) 1] [ x + (t^3 + 4*t + 3) 1] [ x + (t^3 + 4*t + 4) 1] [ x + (2*t^3 + 3*t) 1] [x + (2*t^3 + 3*t + 1) 1] [x + (2*t^3 + 3*t + 2) 1] [x + (2*t^3 + 3*t + 3) 1] [x + (2*t^3 + 3*t + 4) 1] [ x + (3*t^3 + 2*t) 1] [x + (3*t^3 + 2*t + 1) 1] [x + (3*t^3 + 2*t + 2) 1] [x + (3*t^3 + 2*t + 3) 1] [x + (3*t^3 + 2*t + 4) 1] [ x + (4*t^3 + t) 1] [ x + (4*t^3 + t + 1) 1] [ x + (4*t^3 + t + 2) 1] [ x + (4*t^3 + t + 3) 1] [ x + (4*t^3 + t + 4) 1] [0 1] matrix(0,2) matrix(0,2) matrix(0,2) matrix(0,2) matrix(0,2) [x^4 + 4*t 1] [4 1] [x + t 1] [x + a 1] [1, a, a + 1, a^2]~ [ x + 79228162514264337593543950396 1] [ x + 79228162514264337593543950396*a 1] [x + (79228162514264337593543950396*a + 79228162514264337593543950396) 1] [ x + 79228162514264337593543950396*a^2 1] [ x^2 + (2*a + 1)*x + (a^2 + a + 1) 1] [ x^4 + x^3 + x^2 + x + 1 1] [1 1] [1 1] [1 1] [1 1] [2 1] [4 1] [x^4 + (79228162514264337593543950396*a^2 + 79228162514264337593543950395*a + 79228162514264337593543950395)*x^3 + (a^2 + 11*a + 79228162514264337593543 950396)*x^2 + (79228162514264337593543950393*a^2 + 7922816251426433759354395 0389*a + 2)*x + (4*a^2 + 79228162514264337593543950396*a) 1] [x^2 + (2*a + 1)*x + (a^2 + a + 1) 2] [x^4 + x^3 + x^2 + x + 1 4] [x^10 + 79228162514264337593543950396*a^2*x^9 + (792281625142643375935439503 95*a^2 + 79228162514264337593543950395*a)*x^8 + (8*a^2 + 7922816251426433759 3543950393*a + 79228162514264337593543950396)*x^7 + (4*a^2 + 12*a + 79228162 514264337593543950394)*x^6 + (79228162514264337593543950377*a^2 + 9*a + 7922 8162514264337593543950395)*x^5 + a^2*x^4 + (2*a^2 + 2*a)*x^3 + (792281625142 64337593543950389*a^2 + 4*a + 1)*x^2 + (79228162514264337593543950393*a^2 + 79228162514264337593543950385*a + 3)*x + (20*a^2 + 7922816251426433759354395 0388*a + 1) 1] 3 3 107 37 4096 3584 5832 200 1000 200 Total time spent: 4540 pari-2.17.2/src/test/32/permgroup0000644000175000017500000000000014676526175015132 0ustar billbillpari-2.17.2/src/test/32/alggroup0000644000175000017500000000716214760123736014740 0ustar billbill2 x^3 - 21*x + 7 1 5 ordering S1 1 [1] [1] S2 1 [1, 1] [1, 1] S3 1 [1, 1, 4] [1, 1, 1] S4 1 [1, 1, 4, 9, 9] [1, 1, 1, 1, 1] S1 1 [1] [1] S2 1 [1, 1] [1, 1] S3 1 [1, 1, 4] [1, 1, 1] D8 1 [1, 1, 1, 1, 4] [1, 1, 1, 1, 1] D10 1 [1, 1, 4, 4] [1, 1, 1, 1] D12 1 [1, 1, 1, 1, 4, 4] [1, 1, 1, 1, 1, 1] D14 1 [1, 1, 12] [1, 1, 3] D16 1 [1, 1, 1, 1, 4, 8] [1, 1, 1, 1, 1, 2] D18 1 [1, 1, 4, 12] [1, 1, 1, 3] D20 [1, 1, 1, 1, 4, 4, 4, 4] [1, 1, 1, 1, 1, 1, 1, 1] D22 [1, 1, 20] [1, 1, 5] D24 [1, 1, 1, 1, 4, 4, 4, 8] [1, 1, 1, 1, 1, 1, 1, 2] D26 [1, 1, 24] [1, 1, 6] D28 [1, 1, 1, 1, 12, 12] [1, 1, 1, 1, 3, 3] D30 [1, 1, 4, 4, 4, 4, 4, 4, 4] [1, 1, 1, 1, 1, 1, 1, 1, 1] D32 [1, 1, 1, 1, 4, 8, 16] [1, 1, 1, 1, 1, 2, 4] D8 1 [1, 1, 1, 1, 4] [1, 1, 1, 1, 1] D10 1 [1, 1, 8] [1, 1, 2] D12 1 [1, 1, 1, 1, 4, 4] [1, 1, 1, 1, 1, 1] D14 1 [1, 1, 12] [1, 1, 3] D16 1 [1, 1, 1, 1, 4, 8] [1, 1, 1, 1, 1, 2] D18 1 [1, 1, 4, 12] [1, 1, 1, 3] D20 [1, 1, 1, 1, 8, 8] [1, 1, 1, 1, 2, 2] D22 [1, 1, 20] [1, 1, 5] D24 [1, 1, 1, 1, 4, 4, 4, 8] [1, 1, 1, 1, 1, 1, 1, 2] alggroup [0, 0, 0, 0, 0, 0, [1, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0; 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0; 0, 1 , 0, 0, 0, 0; 0, 0, 1, 0, 0, 0; 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 1], [[1, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0; 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 1], [0, 0, 1, 0, 0, 0; 1, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1; 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0; 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 1; 0, 0, 0, 1, 0, 0], [0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 1; 0 , 0, 0, 0, 1, 0; 1, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0; 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0; 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 1; 0, 1, 0, 0, 0, 0; 1, 0, 0 , 0, 0, 0; 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1; 0, 0, 0, 0, 1, 0; 0, 0, 0, 1, 0, 0; 0, 0, 1, 0, 0, 0; 0, 1, 0, 0, 0, 0; 1, 0, 0, 0, 0, 0]], 0, [6, 0, 0 , 0, 0, 0]] 1 [0, 0, 0, 0, 0, 0, [1, 0; 0, 1], [1, 0; 0, 1], [[1, 0; 0, 1], [0, 1; 1, 0]], 0, [2, 0]] S1 1 1 1 S2 1 1 1 S3 1 1 1 S4 1 1 1 S5 1 1 1 S1 1 1 1 S2 1 1 1 S3 1 1 1 S4 1 1 1 D6 1 1 1 1 D8 1 1 1 1 D10 1 1 1 1 D12 1 1 1 1 D14 1 1 1 1 D16 1 1 1 1 D18 1 1 1 1 D20 1 1 1 1 D22 1 1 1 1 D24 1 1 1 1 D26 1 1 1 1 D28 1 1 1 1 D30 1 1 1 1 D32 1 1 1 1 D34 1 1 1 1 D36 1 1 1 1 D38 1 1 1 1 D40 1 1 1 1 D10 1 1 D14 1 1 D22 1 1 D26 1 1 D34 1 1 D38 1 1 D46 1 1 D58 1 1 testing decomposition. testing decomposition. testing decomposition. *** at top-level: alggroupcenter(['x,'y]) *** ^----------------------- *** alggroupcenter: incorrect type in checkgroupelts (t_VEC). *** at top-level: alggroupcenter('x,1) *** ^-------------------- *** alggroupcenter: incorrect type in checkgroupelts (t_POL). *** at top-level: alggroup("a") *** ^------------- *** alggroup: incorrect type in checkgroupelts (t_STR). *** at top-level: alggroup(["a"]) *** ^--------------- *** alggroup: incorrect type in checkgroupelts (t_VEC). *** at top-level: alggroup(["a","b","c"]) *** ^----------------------- *** alggroup: incorrect type in checkgroupelts (t_VEC). *** at top-level: alggroup([Vecsmall([1]),Vecsmall([1,2]),Vecsma *** ^---------------------------------------------- *** alggroup: inconsistent dimensions in checkgroupelts [length of permutations]. *** at top-level: alggroup([Vecsmall([1]),Vecsmall([2,3]),Vecsma *** ^---------------------------------------------- *** alggroup: inconsistent dimensions in checkgroupelts [length of permutations]. Total time spent: 465 pari-2.17.2/src/test/32/quaddisc0000644000175000017500000000135314567450071014711 0ustar billbill-4 -11 -8 -388 -24 -95 -376 -372 -23 -91 -40 -356 -88 -87 -344 -340 -84 -83 -328 -4 -20 -79 -312 -308 -19 -3 -296 -292 -8 -71 -280 -276 -68 -67 -264 -26 0 -4 -7 -248 -244 -15 -59 -232 -228 -56 -55 -24 -212 -52 -51 -8 -4 -3 -47 -1 84 -20 -11 -43 -168 -164 -40 -39 -152 -148 -4 -35 -136 -132 -8 -31 -120 -116 -7 -3 -104 -4 -24 -23 -88 -84 -20 -19 -8 -68 -4 -15 -56 -52 -3 -11 -40 -4 - 8 -7 -24 -20 -4 -3 -8 -4 0 1 8 12 1 5 24 28 8 1 40 44 12 13 56 60 1 17 8 76 5 21 88 92 24 1 104 12 28 2 9 120 124 8 33 136 140 1 37 152 156 40 41 168 172 44 5 184 188 12 1 8 204 13 53 24 220 56 57 232 236 60 61 248 28 1 65 264 268 17 69 280 284 8 73 296 12 76 77 312 316 5 1 328 332 21 85 344 348 88 89 40 364 92 93 376 380 24 97 8 44 1 Total time spent: 1 pari-2.17.2/src/test/32/bnrisgalois0000644000175000017500000000143614676526175015444 0ustar billbill[[1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 3], [1, 0, 0, 0; 0, 3, 0, 2; 0, 0, 1, 0; 0, 0, 0, 1], [1, 0, 0, 0; 0, 3, 1, 2; 0, 0, 1, 0; 0, 0, 0, 1], [ 3, 0, 2, 2; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1]] [[1651, 7700, 4200, 2800; 0, 11, 0, 0; 3, 1, 1, 4; 0, 0, 0, 2], [3149, 3500, 7000, 0; 0, 5, 0, 4; 3, 1, 1, 4; 0, 0, 0, 1]] [[1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 3], [1, 0, 0, 0; 0, 3, 0, 2; 0, 0, 1, 0; 0, 0, 0, 1], [1, 0, 0, 0; 0, 3, 1, 2; 0, 0, 1, 0; 0, 0, 0, 1], [ 3, 0, 2, 2; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1]] [[1, 11, 10, 4, 5, 6, 8, 7, 9, 3, 2, 18, 17, 29, 28, 16, 13, 12, 19, 21, 20, 31, 30, 32, 27, 26, 25, 15, 14, 23, 22, 24], [1, 10, 11, 5, 4, 6, 7, 8, 9, 2, 3, 29, 28, 18, 17, 16, 15, 14, 26, 25, 27, 22, 24, 23, 20, 19, 21, 13, 12 , 32, 31, 30]] Total time spent: 268 pari-2.17.2/src/test/32/contfrac0000644000175000017500000000201714567450071014711 0ustar billbill *** at top-level: contfrac(1,[],-1) *** ^----------------- *** contfrac: domain error in contfrac: nmax < 0 *** at top-level: contfracpnqn(Vecsmall([])) *** ^-------------------------- *** contfracpnqn: incorrect type in pnqn (t_VECSMALL). [1 0] [0 1] [;] [;] [2 1] [1 0] [2] [1] [2] [1] [10 3] [ 7 2] [1] [1] [1 3] [1 2] [1 3 10] [1 2 7] [144 22] [ 33 5] [4] [1] [4 22] [1 5] [4 22 144] [1 5 33] [[], []] [[-1], []] [[-1], [1/2]] [[], []] 0 [[-1, 1/3, 1/15, 1/35, 1/63, 1/99, 1/143, 1/195], [1/2, 1/36, 1/100, 1/196, 1/324, 1/484, 1/676, 1/900]] *** at top-level: contfraceval(e,1,10) *** ^-------------------- *** contfraceval: nonexistent component in contfraceval: index > 8 410105312/150869313 517656/190435 410105312/150869313 [[-2], [1]] [[], []] *** at top-level: contfracinit(1) *** ^--------------- *** contfracinit: incorrect type in contfracinit (t_INT). [[2, 0], [3]] Total time spent: 1 pari-2.17.2/src/test/32/fflog0000644000175000017500000000125714676526175014226 0ustar billbill *** Warning: new stack size = 10000000 (9.537 Mbytes). [1, [1, matrix(0,2)]] 0 [2, [2, Mat([2, 1])]] 1 [2, [4294967290, [2, 1; 5, 1; 19, 1; 22605091, 1]]] 17 [2, [18446744073709551628, [2, 2; 7, 1; 658812288346769701, 1]]] 17 3 0 1234567891012345678 1234567891012345678 12345678910 2739979050900541 1234567891012345 123456789101 1 1 1 1 1 1 1 error("incorrect type in generic discrete logarithm (order factorization) (t _COMPLEX).") error("incorrect type in generic discrete logarithm (order factorization) (t _INT).") error("incorrect type in factorback [not a factorization] (t_MAT).") error("incorrect type in factorback [not an exponent vector] (t_COL).") Total time spent: 3135 pari-2.17.2/src/test/32/gcdext0000644000175000017500000001051214760123736014367 0ustar billbill[0, 0, 0] [0, 0, 0] [0, 0, 0] [0, 1, 2] [0, 3 + 2*5 + 2*5^2 + O(5^3), 1] [0, 1, x] [0, 0, 0] [0, 0, 0] [0, 0, 0] [0, 1/2, 1] [0, 3 + 2*5 + 2*5^2 + O(5^3), 1] [0, 1, x] [0, 0, 0] [0, 0, 0] [0, 0, 0] [0, 1/2, 1] [0, 3 + 2*5 + 2*5^2 + O(5^3), 1] [0, 1, x] [1, 0, 2] [1/2, 0, 1] [1/2, 0, 1] [0, 1, 2] [1/2, 0, 1] [1/2, 0, 1] [3 + 2*5 + 2*5^2 + O(5^3), 0, 1] [3 + 2*5 + 2*5^2 + O(5^3), 0, 1] [3 + 2*5 + 2*5^2 + O(5^3), 0, 1] [3 + 2*5 + 2*5^2 + O(5^3), 0, 1] [3 + 2*5 + 2*5^2 + O(5^3), 0, 1] [3 + 2*5 + 2*5^2 + O(5^3), 0, 1] [1, 0, x] [1, 0, x] [1, 0, x] [0, 1/2, 1] [0, 3 + 2*5 + 2*5^2 + O(5^3), 1] [0, 1, x] [0, -3, 3*x + 5] [0, 1, (10*T^3 + 3*T + 5)*z^6 + (11*T^3 + 15*T^2 + 10*T + 13)*z^4 + (14*T^3 + 13*T^2 + 15)*z^2 + (9 + 13*T + 14*T^2 + 11*T^3 + O(T^20))] Mod(1, 7)*x x + a [(a^4 + 2*a^3 + a^2 + a + 1)*x^2 + (a^4 + 2*a^3 + a^2 + a + 2)*x + 1, (2*a^4 + a^3 + 2*a^2 + 2*a + 2)*x + (2*a^4 + a^3 + 2*a^2 + 2*a + 1), 1] 392757252698671644518933194646259026606358825037832605168120733455355904*x + Mod(-32732367347867845727545221115691651450464375408154119*a^11 - 349901420 764144182157149001212224917120789154588440854*a^10 + 30199581788056574475558 8538031580678248706119440652965202*a^9 + 26465784564265590995770389845795315 85894051381563732492448*a^8 - 2145753607489079692256122053078728286338795227 860524853856887*a^7 - 138114466412982853002182990113719175057961009014502444 45692338*a^6 + 5693688219591330427165368038355599886351744436714343758769292 516*a^5 + 26056823738974452070461793291997279246768552686129616910795970032* a^4 - 11017829044510831595466283417995196913182686859426697723597490195648*a ^3 - 41423109488051504169006424755508272063137897706691923745421860003200*a^ 2 - 14256642019682515742570563716442803419996115605538672924160897393965312* a - 126109974024633409447895964809596877746839040357983165563808547232812032 , a^12 + 12*a^11 - 13002*a^10 - 130740*a^9 + 105793425*a^8 + 832682592*a^7 - 500807817792*a^6 - 2934008282880*a^5 + 1667712407121792*a^4 + 6980361555806 208*a^3 - 3225774176703664128*a^2 - 7116861358234533888*a + 3895041509102090 981376) 1 + I 1 1 2 w w Mod(2, 4) *** at top-level: gcd(1/2,Mod(2,4)) *** ^----------------- *** gcd: inconsistent gcd t_INTMOD , t_FRAC. Mod(1, 4) 2 Mod(1, 5) Mod(1, 5) 1/2 1/2 1 1 1 Mod(1, x^3) Mod(x, x^3) 1 *** at top-level: gcd(t,1/x) *** ^---------- *** gcd: inconsistent gcd t_POLMOD , t_RFRAC. 1 y x 1/x^2 1 1 1 0 1 1 error("forbidden multiplication t_REAL * t_FFELT.") error("forbidden gcd t_REAL , t_FFELT.") error("forbidden gcd t_REAL , t_FFELT.") 1 1 error("inconsistent gcd t_INTMOD , t_FFELT.") error("impossible inverse in FF_Z_Z_muldiv: 2.") error("inconsistent gcd t_FRAC , t_FFELT.") 1 1 1 error("inconsistent gcd t_FRAC , t_FFELT.") 0 1 error("inconsistent gcd t_FRAC , t_FFELT.") error("forbidden multiplication t_FFELT * t_COMPLEX.") error("forbidden gcd t_FFELT , t_COMPLEX.") error("forbidden gcd t_FFELT , t_COMPLEX.") error("forbidden multiplication t_FFELT * t_QUAD.") error("forbidden gcd t_FFELT , t_QUAD.") error("forbidden gcd t_FFELT , t_QUAD.") error("forbidden multiplication t_FFELT * t_PADIC.") 1 error("inconsistent gcd t_FFELT , t_PADIC.") error("forbidden multiplication t_FFELT * t_PADIC.") 1 error("inconsistent gcd t_FFELT , t_PADIC.") error("forbidden multiplication t_FFELT * t_PADIC.") error("inconsistent gcd t_FFELT , t_PADIC.") error("inconsistent gcd t_FFELT , t_PADIC.") 1 1 + I Mod(1, 3) 1 Mod(1, 13) 2 1 2*x + 2 (x - 1)/x Mod(1, x^2 + Mod(-y, y^2 + 1)) 1 (-k + 0.E-38)/k 1/18446744073709551616 Mod(1, 2)*x + Mod(1, 2) x + 1 0 Mod(0, 3) Mod(Mod(1, y^2 + 1), x^2 + Mod(-y, y^2 + 1)) 1688783551193734882643358005264268224496699289284988569676870644033613652597 6261075318513696652827406883336492943280027486259114788378627257789577321276 9741268090936776870515273462153041660394611531667597848189711480905914472001 8484127517300606465789652185929623897088281175220904636490347021096445001887 8650074591624939506243891584469076776743491709064234887811661601168885280367 38807730709203142810389700524543565487 1 1 [0, 0]~ [0, 0]~ [0, 0]~ [0, 0]~ [0, 0]~ [Mod(0, 5), Mod(0, 5)]~ [Mod(0, 5), Mod(0, 5)]~ [0, 0]~ [0, 0]~ [0, 0]~ [0, 0]~ [Mod(0, 340282366920938463463374607431768211507), Mod(0, 3402823669209384634 63374607431768211507)]~ [Mod(0, 340282366920938463463374607431768211507), Mod(0, 3402823669209384634 63374607431768211507)]~ Total time spent: 62 pari-2.17.2/src/test/32/asymp0000644000175000017500000000400314676526175014252 0ustar billbill realprecision = 115 significant digits -oo -oo -oo -oo [1, 1/12, 1/288, -139/51840, -571/2488320, 163879/209018880, 5246819/7524679 6800, -534703531/902961561600, -4483131259/86684309913600, 432261921612371/5 14904800886784000, 6232523202521089/86504006548979712000, -25834629665134204 969/13494625021640835072000, -1579029138854919086429/97161300155814012518400 00, 746590869962651602203151/116593560186976815022080000, 151151360102809790 3631961/2798245444487443560529920000, -8849272268392873147705987190261/29969 2087104605205332754432000000, -142801712490607530608130701097701/57540880724 084199423888850944000000] [1, 1/12, 1/288, -139/51840, -571/2488320, 163879/209018880, 5246819/7524679 6800, -534703531/902961561600, -4483131259/86684309913600, 432261921612371/5 14904800886784000, 72970412083803/1012789331008942090] [0, 1, -1/2, 1/3, -1/4, 1/5, -1/6, 1/7, -1/8, 1/9, -1/10, 1/11, -1/12, 1/13, -1/14, 1/15, -1/16] [0, 1, -1/2, 1/3, -1/4, 1/5, -1/6, 1/7, -1/8, 1/9, -1/10, 1/11, -1/12, 1/13, -1/14, 1/15, -1/16] [0, 1, -1/2, 1/3, -1/4, 1/5, -1/6, 1/7, -1/8, 1/9, -1/10, 1/11, -1/12, 1/13, -1/14, 1/15, -1/16, 1/17] [1, 0, -1/6, 0, 1/120, 0, -1/5040, 0, 1/362880, 0, -1/39916800, 0, 1/6227020 800, 0, -1/1307674368000, 0, 1/355687428096000, 0, -1/121645100408832000, 0, 1/51090942171709440000, 0, -1/25852016738884976640000, 0, 1/155112100433309 85984000000, 0, 0] realprecision = 38 significant digits 1.0000000000000000000000000000000000000 0.E-37 0.50000000000000000000000000000000000000 1 0.E-38 -22 -14 [0, -5/48, -7/64, -81/5120, -3/2048] [0, 1/12, 0, -1/360, 0, 1/1260, 0, -1/1680, 0, 1/1188, 0, -691/360360, 0, 1/ 156, 0] [] *** at top-level: asympnum(1) *** ^----------- *** asympnum: incorrect type in asympnum (t_INT). *** at top-level: limitnum(1) *** ^----------- *** limitnum: incorrect type in limitnum (t_INT). *** at top-level: limitnum(n->1,-1) *** ^----------------- *** limitnum: domain error in limitnum: alpha <= 0 Total time spent: 159 pari-2.17.2/src/test/32/real0000644000175000017500000000062114567450071014034 0ustar billbill5.9 E347063955532709820 1.7 E-347063955532709821 *** at top-level: 1.<<2^64 *** ^---- *** overflow in t_INT-->long assignment. *** at top-level: 1.>>2^64 *** ^---- *** overflow in t_INT-->long assignment. 0.E1 1 1 0 0 1 1 0 0 1 1 0 0 1 1 1 1 0 0 0 0 -oo 0 -1 1 3 4 1 1 2 [1, 1/2, 2, 2, 2/(x + 1)] [0, 0, 3, 3, 3/(x + 1)] Total time spent: 1 pari-2.17.2/src/test/32/fft0000644000175000017500000000125214567450071013671 0ustar billbill[1, -1]~ [2, 0] [2, 2] [1, I, -1, -I]~ [2 + I, -I, -I, 2 + I] [4, 4*I, 0, 4] [1, -I, -1, I]~ [2 + I, 2 + I, -I, -I] [4, 4*I, 0, 4] -97 1 1 [2] [x] *** at top-level: fft(rootsof1(3),x^2+x+1) *** ^------------------------ *** fft: inconsistent dimensions in fft. *** at top-level: fftinv(rootsof1(3),x^2+x+1) *** ^--------------------------- *** fftinv: inconsistent dimensions in fft. *** at top-level: fft([],[]) *** ^---------- *** fft: inconsistent dimensions in fft. *** at top-level: fftinv([],[]) *** ^------------- *** fftinv: inconsistent dimensions in fft. Total time spent: 33 pari-2.17.2/src/test/32/ellpadiclambdamu0000644000175000017500000000306614676526175016411 0ustar billbill *** Warning: new stack size = 12000000 (11.444 Mbytes). [[8, 4], [0, 0]] [[2, 4], [0, 0]] [[8, 4], [0, 0]] [[8, 6], [0, 0]] [[8, 4], [0, 0]] [[10, 4], [0, 0]] [[3, 1], [0, 0]] [[2, 4], [0, 0]] [[4, 2], [0, 0]] [[2, 6], [0, 0]] [[7, 1], [0, 0]] [[3, 1], [0, 0]] [[1, 1], [0, 0]] [[1, 9], [0, 0]] [[7, 5], [0, 0]] [[8, 4], [0, 0]] [[2, 2], [0, 0]] [[3, 3], [0, 0]] [[9, 3], [0, 0]] [[3, 11], [0, 0]] [[2, 2], [0, 0]] [[7, 5], [0, 0]] [[3, 1], [0, 0]] [[1, 3], [0, 0]] [[6, 2], [0, 0]] [[2, 5], [0, 0]] [[0, 0], [0, 0]] [[0, 0], [0, 0]] [[1, 3], [0, 0]] [[0, 7], [0, 0]] [2, 0] [0, 0] [1, 0] [0, 1] [0, 0] [2, 0] [1, 0] [1, 0] [4, 0] [0, 0] [1, 0] [1, 0] [2, 0] [4, 0] [2, 0] [0, 0] [2, 0] [0, 0] [0, 1] [0, 2] [0, 0] *** at top-level: lambdamu(E20a1,2) *** ^----------------- *** in function lambdamu: ellpadiclambdamu(e,p,d,i) *** ^------------------------- *** ellpadiclambdamu: sorry, additive reduction in ellpadiclambdamu is not yet implemented. *** at top-level: lambdamu(E20a1,3,2) *** ^------------------- *** in function lambdamu: ellpadiclambdamu(e,p,d,i) *** ^------------------------- *** ellpadiclambdamu: domain error in ellpadiclambdamu: isfundamental(D) = 0 *** at top-level: lambdamu(ellinit([1,1],5),5) *** ^---------------------------- *** in function lambdamu: ellpadiclambdamu(e,p,d,i) *** ^------------------------- *** ellpadiclambdamu: incorrect type in ellpadiclambdamu (t_VEC). Total time spent: 843 pari-2.17.2/src/test/32/io0000644000175000017500000000434114567450071013523 0ustar billbill0 ["123", "456", "a7b", "\\frac{1}{2}"] 0 [1, 3] 0 1 0 setting x setting y y 0 List([]) 0 2 ["1+1"] 1+1 0 1:1 2:2 3:3 4:4 5:5 6:6 7:7 8:8 9:9 10:10 11:12345678910 1:1 2:2 3:3 4:4 5:5 6:6 7:7 8:8 9:9 10:10 11:12345678910 fileopen:0 (5) fileclose(0) *** at top-level: ...ileopen(F));fileclose(f);fileread(f) *** ^----------- *** fileread: invalid file descriptor in fileread [0] fileopen:0 (5) fileclose(0) *** at top-level: ...ileopen(F));fileclose(f);filereadstr(f) *** ^-------------- *** filereadstr: invalid file descriptor in filereadstr [0] fileopen:0 (5) fileclose(0) *** at top-level: ...ileopen(F));fileclose(f);filewrite(f,"b") *** ^---------------- *** filewrite: invalid file descriptor in filewrite [0] fileopen:0 (5) fileclose(0) *** at top-level: ...ileopen(F));fileclose(f);filewrite1(f,"b") *** ^----------------- *** filewrite1: invalid file descriptor in filewrite1 [0] fileopen:0 (5) fileclose(0) *** at top-level: ...ileopen(F));fileclose(f);fileflush(f) *** ^------------ *** fileflush: invalid file descriptor in fileflush [0] fileopen:0 (5) *** at top-level: my(f=fileopen(F,"w"));fileread(f) *** ^----------- *** fileread: invalid file descriptor in fileread [0] fileclose(0) fileopen:0 (5) *** at top-level: my(f=fileopen(F,"a"));filereadstr(f) *** ^-------------- *** filereadstr: invalid file descriptor in fileread [0] fileclose(0) fileopen:0 (5) *** at top-level: my(f=fileopen(F));filewrite(f,"b") *** ^---------------- *** filewrite: invalid file descriptor in filewrite [0] fileclose(0) fileopen:0 (5) *** at top-level: my(f=fileopen(F,"r"));filewrite1(f,"b") *** ^----------------- *** filewrite1: invalid file descriptor in filewrite1 [0] fileclose(0) *** at top-level: fileflush('x) *** ^------------- *** fileflush: incorrect type in fileflush (t_POL). Total time spent: 0 pari-2.17.2/src/test/32/primorial0000644000175000017500000000051614676526175015124 0ustar billbill[1, 1, 2, 6, 6, 30, 30, 210, 210, 210, 210, 2310, 2310] 2305567963945518424753102147331756070 *** at top-level: (-1)# *** ^---- *** _#: domain error in primorial: argument < 0 *** at top-level: Pi# *** ^--- *** incorrect type in gtos [integer expected] (t_REAL). Total time spent: 0 pari-2.17.2/src/test/32/intnum0000644000175000017500000001521014724330077014421 0ustar billbill? allocatemem(20*10^6); *** Warning: new stack size = 20000000 (19.073 Mbytes). ? check(a,b)=my(t=abs((a-b)/b));if(t,ceil(log(t)/log(10)),-oo); ? \p96 realprecision = 96 significant digits ? check(intcirc(s=1,0.5,zeta(s)),1) -84 ? f(s)=gamma(s)^3; ? c=2; ? A=[-oo,3*Pi/2]; ? B=[+oo,3*Pi/2]; ? F(z)=my(a=-log(z));intnum(t=A,B,exp(a*I*t),T)*exp(a*c)/(2*Pi); ? T=intfuncinit(t=A,B,f(c+I*t)); ? ref=F(4); ? \p38 realprecision = 38 significant digits ? T=intfuncinit(t=A,B,f(c+I*t)); ? check(F(4),ref) -37 ? \p96 realprecision = 96 significant digits ? f(x)=1/(exp(x)-1)-exp(-x)/x; ? F=truncate(f(t+O(t^7))); ? g(x)=if(x>1e-18,f(x),subst(F,t,x)); ? check(intnum(x=0,[oo,1],f(x)),Euler) -oo ? check(intnum(x=0,[oo,1],g(x)),Euler) -oo ? check(intnum(x=0,1,1/sqrt(x)),2) -58 ? check(intnum(x=[0,-1/2],1,1/sqrt(x)),2) -oo ? check(intnum(x=100000,oo,1/(1+x^2)),atan(1/100000)) -oo ? check(intnum(x=0,1,x*cos(Pi*x)),-2/Pi^2) -oo ? check(intnum(x=0,1,x*cos(Pi*x),2),-2/Pi^2) -oo ? check(intnum(x=[0,-1/2],[oo,-3/2],1/(sqrt(x)+x^(3/2))),Pi) -oo ? check(intnum(x=[-oo,-3/2],[oo,-3/2],1/(1+abs(x)^(3/2))),8*Pi/sqrt(27)) -oo ? check(intnum(x=-oo,oo,1/(1+x^2)),Pi) -oo ? f(x)=if(x<0,1/(1+(-x)^(3/2)),1/(1+x^(5/2))); ? a=4*Pi/sqrt(27)+2*(Pi/5)/sin(2*Pi/5); ? check(intnum(x=[-oo,-3/2],[oo,-5/2],f(x)),a) -oo ? f(x)=if(x<0,1/(1+(-x)^(3/2)),exp(-x)); ? check(intnum(x=[-oo,-3/2],[oo,1],f(x)),4*Pi/sqrt(27)+1) -oo ? f(x)=if(x<0,1/(1+(-x)^(3/2)),sinc(x)); ? check(intnum(x=[-oo,-3/2],[oo,-I],f(x)),4*Pi/sqrt(27)+Pi/2) -oo ? f(x)=if(x<0,exp(2*x),1/(1+x^(3/2))); ? check(intnum(x=[-oo,2],[oo,-3/2],f(x)),1/2+4*Pi/sqrt(27)) -oo ? f(x)=if(x<0,exp(2*x),1/(1+x^(5/2))); ? check(intnum(x=[-oo,2],[oo,-5/2],f(x)),1/2+2*(Pi/5)/sin(2*Pi/5)) -oo ? f(x)=if(x<0,exp(2*x),exp(-x)); ? check(intnum(x=[-oo,2],[oo,1],f(x)),3/2) -oo ? f(x)=if(x<0,exp(2*x),sinc(x)); ? check(intnum(x=[-oo,2],[oo,-I],f(x)),1/2+Pi/2) -oo ? f(x)=if(x<0,2*sinc(2*x),1/(1+x^(3/2))); ? check(intnum(x=[-oo,-2*I],[oo,-3/2],f(x)),Pi/2+4*Pi/sqrt(27)) -oo ? f(x)=if(x<0,2*sinc(2*x),1/(1+x^(5/2))); ? check(intnum(x=[-oo,-2*I],[oo,-5/2],f(x)),Pi/2+2*(Pi/5)/sin(2*Pi/5)) -96 ? f(x)=if(x<0,2*sinc(2*x),exp(-x)); ? check(intnum(x=[-oo,-2*I],[oo,1],f(x)),Pi/2+1) -oo ? f(x)=if(x<0,2*sinc(2*x),sinc(x)); ? check(intnum(x=[-oo,-2*I],[oo,-I],f(x)),Pi) -oo ? f(x)=cos((3+tanh(x))*x)/sqrt(1+x^2); ? a=intnum(x=[-oo,2*I],[oo,4*I],f(x),1); ? check(intnum(x=[-oo,2*I],[oo,4*I],f(x)),a) -51 ? check(intnum(x=[0,-1/2],[1,-1/3],x^(-1/2)+(1-x)^(-1/3)),7/2) -oo ? T=intnuminit([0,-1/2],[1,-1/3]); ? check(intnum(x=[0,-1/2],[1,-1/3],x^(-1/2)+(1-x)^(-1/3),T),7/2) -oo ? check(intnum(x=0,[oo,1],sinc(x)),Pi/2) -2 ? check(intnum(x=0,[oo,-I],sinc(x)),Pi/2) -oo ? check(intnum(x=0,[oo,-2*I],2*sinc(2*x)),Pi/2) -oo ? A=intnum(x=0,1,sinc(x/2)^2/2)+intnum(x=1,oo,1/x^2)-intnum(x=1,[oo,I],cos(x)/x^2); ? check(A,Pi/2) -95 ? check(intnum(x=0,[oo,1],sin(x)^3*exp(-x)),3/10) -47 ? check(intnum(x=0,[oo,-I],sin(x)^3*exp(-x)),3/10) -85 ? tab=intnuminit(0,[oo,-I],1); ? check(intnum(x=0,oo,sin(x)^3*exp(-x),tab),3/10) -96 ? check(intnum(x=0,[oo,-I],x^2*sin(x)),-2) -oo ? tab=intnuminit(-1,1); ? check(intnum(x=-1,1,intnum(y=-sqrt(1-x^2),sqrt(1-x^2),x^2+y^2,tab),tab),Pi/2) -96 ? \p96 ? check(intnumgauss(x=0,1,sin(x)),1-cos(1)) -96 ? T=intnumgaussinit(); ? check(intnumgauss(x=0,1,1/(x+1),T),log(2)) -oo ? check(intnumgauss(x=0,1,1/(x+1)^(4/3),T),3-3/2^(1/3)) -95 ? check(intnumgauss(x=2,1,x,T),-3/2) -oo ? check(intnumgauss(x=-1,1,1/(1+x^2),20),Pi/2) -15 ? T=intnumgaussinit(100); ? check(intnumgauss(x=-2,2,1/(1+x^2),T),2*atan(2)) -41 ? check(intnumgauss(t=1,2,t,4),3/2) -oo ? bestappr(intnumgauss(t=1,2,t,1),100) 3/2 ? bestappr(intnumgauss(t=1,2,t,2),100) 3/2 ? bestappr(intnumgauss(t=1,2,t,3),100) 3/2 ? localprec(115);intnumgauss(x=1,2,1/x)-log(2) 0.E-115 ? checkps(a,b)=my(t=norml2(Vec(b-a)));if(t,ceil(log(t)/log(10)),-oo); ? checkps(intnum(t=0,x,exp(t)),exp(x)-1) -oo ? checkps(intnum(t=-x,0,exp(t)),1-exp(-x)) -oo ? checkps(intnum(t=-x,x,exp(t)),exp(x)-exp(-x)) -oo ? tab=intnuminit(1-x,1+y); ? norml2(apply(Vec,Vec(intnum(t=-x,y,exp(t),tab)-(exp(y)-exp(-x))))) 0.E-192 ? checkps(intnum(t=[0,-1/2],x^2,1/sqrt(t)),2*x) -115 ? checkps(intnum(t=1-x^2,[1,-1/2],1/sqrt(1-t)),2*x) -115 ? checkps(intnum(t=[x^2,-1/2],1,1/sqrt(t)),2-2*x) -115 ? checkps(intnum(t=0,[1-x^2,-1/2],1/sqrt(1-t)),2-2*x) -115 ? f(t)=(t^2*(1-t))^(1/3); ? checkps(intnum(t=[x^3,-1/3],[1-x^3,-2/3],(2/3*t-t^2)/(t^2*(1-t))^(2/3)),f(1-x^3)-f(x^3)) -77 ? \p38 realprecision = 38 significant digits ? intnum(x=-oo,[0,-1/2],1/sqrt(-x*(x^4+1))) 2.5189270468096534385807611189769924243 ? \pb20 realbitprecision = 20 significant bits (6 decimal digits displayed) ? intnumromb(x=0,1,sin(x)) 0.459698 ? intnumromb(x=0,1,sin(x),1) 0.459698 ? intnumromb(x=1,100,exp(-x^2),2) 0.139403 ? intnumromb(x=0,1,sinc(x),3) 0.946083 ? intnumromb(x=0,110,x,1) 6048.32 ? intnumromb(x=2,110,x,1) 6039.11 ? exponent(intnumromb(x=-110,90,x,1)+1998.3)<-5 1 ? intnumromb(x=2,1,x,1) -1.50000 ? intnuminit(-oo,oo,1); ? intnuminit([x,-1/2],x) *** at top-level: intnuminit([x,-1/2],x) *** ^---------------------- *** intnuminit: sorry, intnuminit with singularity at non constant limit is not yet implemented. ? intnum(t=[x^2,-1/2],1,1/sqrt(t),intnuminit([0,-1/2],1)) *** at top-level: intnum(t=[x^2,-1/2],1,1/sqrt(t),intnuminit([0, *** ^------------------------ *** sorry, non integer tab argument is not yet implemented. ? intnumgauss(t=1,2,1,"") *** at top-level: intnumgauss(t=1,2,1,"") *** ^----- *** incorrect type in intnumgauss (t_STR). ? intnuminit([oo,1+I],[oo,""]) *** at top-level: intnuminit([oo,1+I],[oo,""]) *** ^---------------------------- *** intnuminit: incorrect type in intnum [incorrect a] (t_VEC). ? intnuminit([oo,1+I,2],[oo,1]) *** at top-level: intnuminit([oo,1+I,2],[oo,1]) *** ^----------------------------- *** intnuminit: incorrect type in intnum [incorrect a] (t_VEC). ? intnum(x=oo,oo,1) *** Warning: integral from oo to oo. 0 ? intnum(x=-oo,-oo,1) *** Warning: integral from -oo to -oo. 0 ? intnuminit(x=-oo,oo,-1); *** at top-level: intnuminit(x=-oo,oo,-1) *** ^----------------------- *** intnuminit: domain error in intnuminit: m < 0 ? intfuncinit(t=0,1,s); *** at top-level: intfuncinit(t=0,1,s) *** ^-- *** sorry, intfuncinit with finite endpoints is not yet implemented. ? intfuncinit(t=[-oo,I],[oo,I],s); *** at top-level: ...uncinit(t=[-oo,I],[oo,I],s) *** ^-- *** sorry, intfuncinit with hard endpoint behavior is not yet implemented. ? print("Total time spent: ",gettime); Total time spent: 1859 pari-2.17.2/src/test/32/idealramgroups0000644000175000017500000000204214676526175016140 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([3, 5, 1, 6, 2, 4]), [[[Vecsmall([3, 5, 1, 6, 2, 4])], Vecsmall([ 2])]]], [Vecsmall([5, 6, 4, 3, 1, 2]), [[[Vecsmall([5, 6, 4, 3, 1, 2])], Vec small([2])]]], [Vecsmall([6, 3, 2, 5, 4, 1]), [[[Vecsmall([6, 3, 2, 5, 4, 1] )], Vecsmall([2])]]]] [[[Vecsmall([2, 1, 4, 3, 6, 5, 8, 7]), Vecsmall([3, 4, 1, 2, 7, 8, 5, 6]), V ecsmall([5, 6, 7, 8, 1, 2, 3, 4])], Vecsmall([2, 2, 2])], [[Vecsmall([2, 1, 4, 3, 6, 5, 8, 7]), Vecsmall([3, 4, 1, 2, 7, 8, 5, 6])], Vecsmall([2, 2])], [[Vecsmall([2, 1, 4, 3, 6, 5, 8, 7]), Vecsmall([3, 4, 1, 2, 7, 8, 5, 6])], V ecsmall([2, 2])], [[Vecsmall([3, 4, 1, 2, 7, 8, 5, 6])], Vecsmall([2])], [[V ecsmall([3, 4, 1, 2, 7, 8, 5, 6])], Vecsmall([2])]] [[[Vecsmall([5, 3, 7, 1, 8, 2, 6, 4]), Vecsmall([3, 4, 8, 7, 2, 1, 5, 6])], Vecsmall([4, 2])], [[Vecsmall([5, 3, 7, 1, 8, 2, 6, 4])], Vecsmall([4])]] 8 Total time spent: 857 pari-2.17.2/src/test/32/gchar-large0000644000175000017500000000040714676526175015301 0ustar billbill *** Warning: new stack size = 66000000 (62.943 Mbytes). precision SEGV [160, 8, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0] 1 gchareval precision bug 1 1 1 1 1 trivial ideal bug 1 argument determination bug [730422, 6, 2, 0, 0, 0, 0, 0, 0, 0, 0] Total time spent: 12406 pari-2.17.2/src/test/32/algsplit0000644000175000017500000000311414676526175014742 0ustar billbillM_2(F_4) M_2(F_9) M_2(F_31^2) M_2(F_p^2) M_d(F_31^n) d=1 n=1 d=1 n=2 d=1 n=3 d=1 n=4 d=1 n=5 d=1 n=6 d=1 n=7 d=1 n=8 d=1 n=9 d=1 n=10 d=2 n=1 d=2 n=2 d=2 n=3 d=2 n=4 d=3 n=1 d=3 n=2 d=4 n=1 examples from documentation [2 0] [0 2*a] [a + 2 0] [ a 2] 1 [0 0] [a 0] bad input *** at top-level: algsplit("toto") *** ^---------------- *** algsplit: incorrect type in checkalg [please apply alginit()] (t_STR). *** at top-level: algsplit(alginit(nfinit('y),[-1,-1])) *** ^------------------------------------- *** algsplit: sorry, splitting a characteristic 0 algebra over its center is not yet implemented. *** at top-level: algsplit(algtableinit([matid(3),[0,0,0;1,1,0;0 *** ^---------------------------------------------- *** algsplit: the algebra must be simple (alg_finite_csa_split 1). *** at top-level: algsplit(algtableinit([matid(2),[0,0;1,1]],2)) *** ^---------------------------------------------- *** algsplit: the algebra must be simple (alg_finite_csa_split 2). *** at top-level: algsplit(matblock([2,1,1,1],1,q)) *** ^--------------------------------- *** algsplit: the algebra must be simple (try_split 1). *** at top-level: algsplit(matblock([1,2,3],1,q)) *** ^------------------------------- *** algsplit: the algebra must be simple (try_split 2). *** at top-level: algsplit(algtableinit(mt,2)) *** ^---------------------------- *** algsplit: the algebra must be simple (alg_finite_csa_split 3). Total time spent: 708 pari-2.17.2/src/test/32/whatnow0000644000175000017500000000122314567450071014577 0ustar billbillThis function no longer exists New syntax: char(x,y) ===> charpoly(x,y) charpoly(A,{v='x},{flag=5}): det(v*Id-A)=characteristic polynomial of the matrix or polmod A. flag is optional and ignored unless A is a matrix; it ma y be set to 0 (Le Verrier), 1 (Lagrange interpolation), 2 (Hessenberg form), 3 (Berkowitz), 4 (modular) if A is integral, or 5 (default, choose best method ). Algorithms 0 (Le Verrier) and 1 (Lagrange) assume that n! is invertible, whe re n is the dimension of the matrix. This function did not change This function did not exist in Pari 1.39 New syntax: compimag(x,y) ===> x*y x*y: product of x and y. Total time spent: 0 pari-2.17.2/src/test/32/gamma0000644000175000017500000003377314730124522014200 0ustar billbill(0.65296549642016672783864624794608469715 + 0.343065839816545357588735986978 31148676*I) + (0.19044897540645184469078131473790885364 + 0.5805524673194769 2349794265298068695525*I)*x + (0.090862784286733058570355592072096462602 + 0 .21088392899265350361451872767550590408*I)*x^2 + (0.034253752000523576920016 074597694397590 + 0.15168994440796279268955277197772465641*I)*x^3 + (-0.0093 139210540785894159197859484392067432 + 0.03306465179643991397682862055127742 8299*I)*x^4 + (0.0066762623841895560506752315759505427095 + 0.01516404667566 6586697065188398143396917*I)*x^5 + O(x^6) 1 - 0.57721566490153286060651209008240243104*x + 0.9890559953279725553953956 5150063470794*x^2 - 0.90747907608088628901656016735627511493*x^3 + 0.9817280 8683440018733638029402185085036*x^4 - 0.981995068903145202104701413791374675 51*x^5 + O(x^6) 1 + 0.42278433509846713939348790991759756896*x + 0.4118403304264396947888835 6141823227690*x^2 + 0.081576919247086266378835484144359593009*x^3 + 0.074249 010753513898319820126665575735432*x^4 - 0.0002669820687450147683211197695238 2515661*x^5 + O(x^6) 0.50000000000000000000000000000000000000*x^-1 + 0.46139216754923356969674395 495879878448 + 0.93661624898783663224281375818851553069*x + 0.72048875166669 501900756857612523634632*x^2 + 1.1032890464233243060581361321045221793*x^3 + O(x^4) (-0.30434960902188368417660077077485938103 + 0.48375784292991511172812918802 297918039*I) + (0.59465032062247697727187848272191072247 + 0.576674047468581 17413405079475000049045*I)*x + (0.23150004831138189314916325909209289721 - 0 .14711677137965943279150680857845149795*I)*x^2 + (-0.02190784473534413804389 4242836567535805 + 0.044442141724177702067115896271895013565*I)*x^3 + (-0.00 095310203972899907556180572534221362410 - 0.01322027411091502743411636095975 8682565*I)*x^4 + (0.0023292347420337443292606199295988510753 + 0.00349489957 19835964464884744063791902941*I)*x^5 + O(x^6) -0.57721566490153286060651209008240243104*x + 0.8224670334241132182362075833 2301259461*x^2 - 0.40068563438653142846657938717048333026*x^3 + 0.2705808084 2778454787900092413529197569*x^4 - 0.20738555102867398526627309729140683361* x^5 + O(x^6) 0.42278433509846713939348790991759756896*x + 0.32246703342411321823620758332 301259461*x^2 - 0.067352301053198095133246053837149996923*x^3 + 0.0205808084 27784547879000924135291975694*x^4 - 0.00738555102867398526627309729140683361 08*x^5 + O(x^6) 0.E-38 0.E-38 [(0.59465032062247697727187848272191072247 + 0.57667404746858117413405079475 000049045*I) + (0.46300009662276378629832651818418579441 - 0.294233542759318 86558301361715690299591*I)*x + (-0.065723534206032414131682728509702607416 + 0.13332642517253310620134768881568504070*I)*x^2 + (-0.003812408158915996302 2472229013688544964 - 0.052881096443660109736465443839034730260*I)*x^3 + (0. 011646173710168721646303099647994255377 + 0.01747449785991798223244237203189 5951470*I)*x^4 + (-0.0077757069690405743408170730434310459472 - 0.0040345642 341327827815714280332882428196*I)*x^5 + O(x^6), (0.4630000966227637862983265 1818418579441 - 0.29423354275931886558301361715690299591*I) + (-0.1314470684 1206482826336545701940521483 + 0.26665285034506621240269537763137008139*I)*x + (-0.011437224476747988906741668704106563491 - 0.1586432893309803292093963 3151710419078*I)*x^2 + (0.046584694840674886585212398591977021508 + 0.069897 991439671928929769488127583805883*I)*x^3 + (-0.03887853484520287170408536521 7155229737 - 0.020172821170663913907857140166441214100*I)*x^4 + (0.022560335 060417259303085193102966460794 - 0.00036753612083320862918606972353477943052 *I)*x^5 + O(x^6), (-0.13144706841206482826336545701940521483 + 0.26665285034 506621240269537763137008139*I) + (-0.022874448953495977813483337408213126982 - 0.31728657866196065841879266303420838157*I)*x + (0.1397540845220246597556 3719577593106453 + 0.20969397431901578678930846438275141765*I)*x^2 + (-0.155 51413938081148681634146086862091895 - 0.080691284682655655631428560665764856 399*I)*x^3 + (0.11280167530208629651542596551483230397 - 0.00183768060416604 31459303486176738971526*I)*x^4 + (-0.060385141064853397644954035047742260711 + 0.033280565716561889360694008049839150654*I)*x^5 + O(x^6), (-0.0228744489 53495977813483337408213126982 - 0.31728657866196065841879266303420838157*I) + (0.27950816904404931951127439155186212905 + 0.4193879486380315735786169287 6550283530*I)*x + (-0.46654241814243446044902438260586275685 - 0.24207385404 796696689428568199729456920*I)*x^2 + (0.451206701208345186061703862059329215 88 - 0.0073507224166641725837213944706955886104*I)*x^3 + (-0.301925705324266 98822477017523871130355 + 0.16640282858280944680347004024919575327*I)*x^4 + (0.13442567256047517668092840739154252347 - 0.202713401516738016734740658864 97663399*I)*x^5 + O(x^6), (0.27950816904404931951127439155186212905 + 0.4193 8794863803157357861692876550283530*I) + (-0.93308483628486892089804876521172 551370 - 0.48414770809593393378857136399458913840*I)*x + (1.3536201036250355 581851115861779876476 - 0.022052167249992517751164183412086765831*I)*x^2 + ( -1.2077028212970679528990807009548452142 + 0.6656113143312377872138801609967 8301307*I)*x^3 + (0.67212836280237588340464203695771261736 - 1.0135670075836 900836737032943248831700*I)*x^4 + (-0.10528231491150367363825212448097382743 + 0.96553709445705650132059416641866849116*I)*x^5 + O(x^6)] [-0.57721566490153286060651209008240243104 + 1.64493406684822643647241516664 60251892*x - 1.2020569031595942853997381615114499908*x^2 + 1.082323233711138 1915160036965411679028*x^3 - 1.0369277551433699263313654864570341681*x^4 + 1 .0173430619844491397145179297909205279*x^5 + O(x^6), 1.644934066848226436472 4151666460251892 - 2.4041138063191885707994763230228999815*x + 3.24696970113 34145745480110896235037083*x^2 - 4.1477110205734797053254619458281366722*x^3 + 5.0867153099222456985725896489546026395*x^4 - 6.0500956642915369610387852 990987805576*x^5 + O(x^6), -2.4041138063191885707994763230228999815 + 6.4939 394022668291490960221792470074167*x - 12.44313306172043911597638583748441001 7*x^2 + 20.346861239688982794290358595818410558*x^3 - 30.2504783214576848051 93926495493902788*x^4 + 42.171248960313662253904780017363403541*x^5 + O(x^6) , 6.4939394022668291490960221792470074167 - 24.88626612344087823195277167496 8820033*x + 61.040583719066948382871075787455231674*x^2 - 121.00191328583073 922077570598197561115*x^3 + 210.85624480156831126952390008681701770*x^4 - 33 6.67481998956362404439853046209045232*x^5 + O(x^6), -24.88626612344087823195 2771674968820033 + 122.08116743813389676574215157491046335*x - 363.005739857 49221766232711794592683346*x^2 + 843.42497920627324507809560034726807082*x^3 - 1683.3740999478181202219926523104522616*x^4 + 3027.0075951865218900595293 797145647074*x^5 + O(x^6)] [-x^-1 + 0.92278433509846713939348790991759756896 + 2.8949340668482264364724 151666460251892*x - 0.077056903159594285399738161511449990768*x^2 + 2.144823 2337111381915160036965411679028*x^3 + O(x^4), x^-2 + 2.894934066848226436472 4151666460251892 - 0.15411380631918857079947632302289998153*x + 6.4344697011 334145745480110896235037083*x^2 + O(x^3), -2*x^-3 - 0.1541138063191885707994 7632302289998153 + 12.868939402266829149096022179247007417*x + O(x^2), 6*x^- 4 + 12.868939402266829149096022179247007417 + O(x), -24*x^-5 + O(x^0)] 8.9348022005446793094172454999380755676 3.2317006071311007300714876688669951960 E616 -3.5449077018110320545963349666822903656 - 0.1293535897955400553154795370758 8123108*x - 15.838884621997332891305490359174586834*x^2 - 0.0882351409230713 74511750322744686275982*x^3 - 63.934119924167817737375290277713885431*x^4 - 0.042848354492868684268292005312709221526*x^5 + O(x^6) 1 - 0.57721566490153286060651209008240243104*a*x + O(x^2) -0.57721566490153286060651209008240243104*a*x + O(x^2) *** gamma: Warning: normalizing a series with 0 leading term. 2*x^-1 + O(x^0) -x^-1 - 0.57721566490153286060651209008240243104 + 1.64493406684822643647241 51666460251892*x - 1.2020569031595942853997381615114499908*x^2 + 1.082323233 7111381915160036965411679028*x^3 - 1.0369277551433699263313654864570341681*x ^4 + 1.0173430619844491397145179297909205279*x^5 + O(x^6) x^-1 - 0.57721566490153286060651209008240243104 + 0.989055995327972555395395 65150063470794*x - 0.90747907608088628901656016735627511493*x^2 + 0.98172808 683440018733638029402185085036*x^3 - 0.9819950689031452021047014137913746755 1*x^4 + O(x^5) 4.0238726007709377354370243392300398572 E2564 [277.25887222397812376689284858327062723, 3.87259191484931827281803063328635 18476 E-121, -1.4996968138956309548176444376280653535 E-241, 1.1615427512435 006366566899997979044432 E-361, -1.3494543201652240481582949154701235393 E-4 81, 2.0903543558921320021382869187469293510 E-601, -4.0475446888989623994126 565496733243106 E-721, 9.4046933023328526091709711857806087161 E-841, -2.549 4377470976218155924961095682808954 E-960, 7.89834560545752902057243432280120 14193 E-1080] [277.25887222397812376689284858327062723 + 1.5707963267948966192313216916397 514421*I, -7.4984840694781547740882221881403267677 E-242 - 3.872591914849318 2728180306332863518476 E-121*I, 1.4996968138956309548176444376280653535 E-24 1 - 5.8077137562175031832834499989895222158 E-362*I, 6.747271600826120240791 4745773506176966 E-482 + 1.1615427512435006366566899997979044432 E-361*I, -1 .3494543201652240481582949154701235393 E-481 + 1.045177177946066001069143459 3734646755 E-601*I, -2.0237723444494811997063282748366621553 E-721 - 2.09035 43558921320021382869187469293510 E-601*I, 4.04754468889896239941265654967332 43106 E-721 - 4.7023466511664263045854855928903043581 E-841*I, 1.27471887354 88109077962480547841404477 E-960 + 9.4046933023328526091709711857806087161 E -841*I, -2.5494377470976218155924961095682808954 E-960 + 3.94917280272876451 02862171614006007097 E-1080*I, -1.3764181199571211681456298903009397326 E-11 99 - 7.8983456054575290205724343228012014193 E-1080*I] [0.70315664064524318722569033366791109947, 9.3792466449891237538616899443825 200120, -0.23620405164172740300374166856770727812, 194.594276219187622421625 51787389029643, -0.31375599950673136337542809687292720373, 15381.64852802630 3808998957195309894170, -1.3180061075500352022813739032757796477, 2580876.87 11348436068076206992583434680, -11.146030731869932467590724595498400233, 743 190865.27947328456252812843702470971] [-x^-1 + O(x^0), x^-2 + O(x^-1), -2*x^-3 + O(x^-2), 6*x^-4 + O(x^-3), -24*x^ -5 + O(x^-4), 120*x^-6 + O(x^-5), -720*x^-7 + O(x^-6), 5040*x^-8 + O(x^-7), -40320*x^-9 + O(x^-8), 362880*x^-10 + O(x^-9)] 0.036489973978576520559023667001244432804 + 0.467401100272339654708622749969 03778383*x + O(x^2) x^-1 + O(x^0) 9999999999999999.5772156649015330017905 9999999999999999.4227843350984672382991 36.841361487904730902009429765103126607 - 6.28318530717958647692528676655900 57684*I 36.841361487904730886566296784796549486 170141183460469231740910675752738881536 1001.0000000000000000000000000000000000 8.4592930575197658134779513864578051837 E92 8.4592930575197658134779513864578051837 E92 + 417.27460269708707626917373711 782229398*I 799877009219260410589.21059353880333769 + 88.7228391116729996053515014380223 25492*I -864.73828787067971564321683481711497423 - 631.46012337154844093099132003918 007972*I 1.7724538509055160272981674833411451828 3.2007257594901922498857741835634344245 E867 3.0616681090421088936612867355651954590 E867 - 9.193770672812704213454512890 0883765323 E866*I 8459293057519765813477951386457805183660969095271154721136672171659780563637 16339197618169691.8420416798032146865778 + 417.27460269708707626917373711782 2293981451080884873662980649365715022960425756218794729722851598595227020005 2467288*I 8459293057519765813477951386457805183660969095271154721136672171659780563637 16339197618169691.8420416798032146865778 + 41727.460269708707626917373711782 2293981451080884873662980649365715022960425756218794729722851598595227020005 2467288*I 8459293057519765813477951386457805183660969095271154721136672171659780563637 16339197618169691.8420416798032146865778407117373385742831330551204346169684 432 + 417274.602697087076269173737117822293981451080884873662980649365715022 9604257562187947297228515985952270200052467287642139293693997776338197086953 142287383*I 0.99999999999999999999999999999942278433509846713939348790991858662495316863 6615471796845732492343995375856774526593328777198552545340369146294559716293 3800 -1000000.5772166539584356686368774405975327324364299837039157908236471064277 4207952925289528676019700485467432997942048345744111188601460149907155979685 1143 realprecision = 38 significant digits 2.6789385347077476336556929409746776441 1.3541179394264004169452880281545137855 3.6256099082219083119306851558676720030 1.2254167024651776451290983033628905269 5.5663160017802352042500968952077261114 1.1287870299081259612609010902588420133 7.5339415987976119046992298412151336246 2.3704361844166009086464735041766525099 1.4345188480905567756360197394564231366 1.0896523574228969512523767551028929712 11.499428186073990663885609852439200980 2.1275570586022219715722784393442933506 1.5287091970871110050473026638281056936 1.0555465648134663023137014847342622098 23.462487693183319881385711469586294930 4.3968001000002525082360090974782051647 3.0815055600034352026059386146337367711 1.9322353352363753417755866326226966547 1.6399148048748842094926399415540991281 1.2850506996660505175844624287857794935 1.1737241052110611751264934325039885767 1.0258364967528902874118049964999185687 1.1304468487397583052339766579000353759 E156 1.1413851228335801146661943537905279353 E154 -3.1238305253309576820203344603145336407 E-155 3.1251326639409330707998343913109131879 E-157 4.5628187500777884959959637081483557229 E456568 1.3768469063730103610139202204469277024 E-456572 *** at top-level: lngamma(-2+x) *** ^------------- *** lngamma: domain error in intformal: residue(series, pole) != 0 *** at top-level: gamma(O(x)) *** ^----------- *** gamma: domain error in gamma: argument = 0 *** at top-level: lngamma(O(x)) *** ^------------- *** lngamma: domain error in lngamma: argument = 0 *** at top-level: psi(O(x)) *** ^--------- *** psi: domain error in psi: argument = 0 *** at top-level: psi(-1) *** ^------- *** psi: domain error in psi: argument = nonpositive integer Total time spent: 21 pari-2.17.2/src/test/32/parallel0000644000175000017500000000574414676526175014732 0ustar billbill3 3 [[1238926361552897, 1; 93461639715357977769163558199606896584051237541638188 580280321, 1], [13821503, 1; 61654440233248340616559, 1; 1473226532114531733 1353282383, 1]] [[1238926361552897, 1; 93461639715357977769163558199606896584051237541638188 580280321, 1], [13821503, 1; 61654440233248340616559, 1; 1473226532114531733 1353282383, 1]] [[1238926361552897, 1; 93461639715357977769163558199606896584051237541638188 580280321, 1], [13821503, 1; 61654440233248340616559, 1; 1473226532114531733 1353282383, 1]] 188 Vecsmall([188, 722, 752]) [414951556888099295851240786369116115101244623224243689999565732969065281141 2908146399707048947103794288197886611300789182395151075411775307886874834113 963687061181803401509523685563, 41495155688809929585124078636911611510124462 3224243689999565732969065281141290814639970704894710379428819788661130078918 2395151075411775307886874834113963687061181803401509523686097, 4149515568880 9929585124078636911611510124462322424368999956573296906528114129081463997070 4894710379428819788661130078918239515107541177530788687483411396368706118180 3401509523686127] Vecsmall([188, 722, 752]) Vecsmall([188, 722, 752]) [414951556888099295851240786369116115101244623224243689999565732969065281141 2908146399707048947103794288197886611300789182395151075411775307886874834113 963687061181803401509523685563, 41495155688809929585124078636911611510124462 3224243689999565732969065281141290814639970704894710379428819788661130078918 2395151075411775307886874834113963687061181803401509523686097, 4149515568880 9929585124078636911611510124462322424368999956573296906528114129081463997070 4894710379428819788661130078918239515107541177530788687483411396368706118180 3401509523686127] [188, 1] [414951556888099295851240786369116115101244623224243689999565732969065281141 2908146399707048947103794288197886611300789182395151075411775307886874834113 963687061181803401509523685563, 41495155688809929585124078636911611510124462 3224243689999565732969065281141290814639970704894710379428819788661130078918 2395151075411775307886874834113963687061181803401509523686097, 4149515568880 9929585124078636911611510124462322424368999956573296906528114129081463997070 4894710379428819788661130078918239515107541177530788687483411396368706118180 3401509523686127] 698 -23 [256, 256, 256, 256, 256, 256, 256, 256, 256, 256] 7432339208719 7432339208719 [75, 85070591730234615858594180193637120807] 4037913 4037913 122000794103870768 9332631163681257191468510474348427988008043411461821539470699523874806785183 6741595904657279211968270649138824528587207188850935847525748940467527387325 054665 9332631163681257191468510474348427988008043411461821539470699523874806785183 6741595904657279211968270649138824528587207188850935847525748940467527387325 054665 9521178792347580584002042939268037925342547696358372341728375471603175645372 9096437859124211041754647719520327867641536994468529159577112884673057840841 880623 36 65 85 [1, 2, 3] [[(i)->my(aaa=123,bbb=345);[self(),[i,aaa,bbb]], [1, 123, 345]]] [1, 1, 0] Total time spent: 13902 pari-2.17.2/src/test/32/language0000644000175000017500000000040414676526175014705 0ustar billbill[1] [List([10]), [List([]), List([])]] [List([10]), [List([4]), List([])]] [2, 0] [6 3] [2 1] [List([1]), List([1, 4])] [List([10]), [List([4]), List([])], [2, 0], [6, 3; 2, 1], List([1]), List([1 , 4])] (~x)->x[1]++ 4 [4, [4]] [4, [4]] Total time spent: 0 pari-2.17.2/src/test/32/nfields0000644000175000017500000006676614760123736014563 0ustar billbill echo = 1 ? setrand(1);N=10^8;a=matrix(3,5,j,k,vectorv(5,l,random\N)); ? nfpol=x^5-5*x^3+5*x+25;nf=nfinit(nfpol) [x^5 - 5*x^3 + 5*x + 25, [1, 2], 595125, 45, [[1, -1.08911514572050482502495 27946671612684, -2.4285174907194186068992069565359418365, 0.7194669112891317 8943997506477288225734, -2.5558200350691694950646071159426779972; 1, -0.1383 8372073406036365047976417441696637 - 0.4918163765776864349975328551474152510 7*I, 1.9647119211288133163138753392090569931 + 0.809714924188978951282940822 19556466857*I, -0.072312766896812300380582649294307897122 + 2.19808037538462 76641195195160383234878*I, -0.98796319352507039803950539735452837195 + 1.570 1452385894131769052374806001981109*I; 1, 1.682941293594312776162956161507997 6006 + 2.0500351226010726172974286983598602164*I, -0.75045317576910401286427 186094108607489 + 1.3101462685358123283560773619310445916*I, -0.787420688747 75359433940488309213323155 + 2.1336633893126618034168454610457936018*I, 1.26 58732110596551455718089553258673705 - 2.716479010374315056657802803578983483 5*I], [1, -1.0891151457205048250249527946671612684, -2.428517490719418606899 2069565359418365, 0.71946691128913178943997506477288225734, -2.5558200350691 694950646071159426779972; 1, -0.63020009731174679864801261932183221744, 2.77 44268453177922675968161614046216617, 2.1257676084878153637389368667440155906 , 0.58218204506434277886573208324566973893; 1, 0.353432655843626071347053090 97299828470, 1.1549969969398343650309345170134923246, -2.2703931422814399645 001021653326313849, -2.5581084321144835749447428779547264828; 1, 3.732976416 1953853934603848598678578170, 0.55969309276670831549180550098995851667, 1.34 62427005649082090774405779536603703, -1.450605799314659911085993848253116112 9; 1, -0.36709382900675984113447253685186261580, -2.060599444304916341220349 2228721306665, -2.9210840780604153977562503441379268334, 3.98235222143397020 22296117589048508540], [16, -17, -39, 12, -41; 16, -10, 44, 34, 9; 16, 6, 18 , -36, -41; 16, 60, 9, 22, -23; 16, -6, -33, -47, 64], [5, 2, 0, -1, -2; 2, -2, -5, -10, 20; 0, -5, 10, -10, 5; -1, -10, -10, -17, 1; -2, 20, 5, 1, -8], [345, 0, 200, 110, 177; 0, 345, 95, 1, 145; 0, 0, 5, 4, 3; 0, 0, 0, 1, 0; 0 , 0, 0, 0, 1], [63, 3, 0, -6, -9; 3, 8, -5, -1, 16; 0, -5, 22, -10, 0; -6, - 1, -10, -14, -9; -9, 16, 0, -9, -2], [345, [138, 117, 330, 288, -636; -172, -88, 65, 118, -116; 53, 1, 138, -173, 65; 1, -172, 54, 191, 106; 0, 118, 173 , 225, -34]], [3, 5, 23]], [-2.4285174907194186068992069565359418365, 1.9647 119211288133163138753392090569931 + 0.80971492418897895128294082219556466857 *I, -0.75045317576910401286427186094108607489 + 1.31014626853581232835607736 19310445916*I], [15, x^4 - 10*x^2 + 5*x + 20, 15*x, 2*x^4 - 5*x^2 + 10*x - 5 , -x^4 + 5*x^3 + 5*x^2 - 20*x - 10], [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 946691128913178943997506477288225734, -2.55582003506916949506460711594267799 72; 1, -0.13838372073406036365047976417441696637 + 0.49181637657768643499753 285514741525107*I, 1.9647119211288133163138753392090569931 - 0.8097149241889 7895128294082219556466857*I, -0.072312766896812300380582649294307897122 - 2. 1980803753846276641195195160383234878*I, -0.98796319352507039803950539735452 837195 - 1.5701452385894131769052374806001981109*I; 1, 1.6829412935943127761 629561615079976006 + 2.0500351226010726172974286983598602164*I, -0.750453175 76910401286427186094108607489 + 1.3101462685358123283560773619310445916*I, - 0.78742068874775359433940488309213323155 + 2.1336633893126618034168454610457 936018*I, 1.2658732110596551455718089553258673705 - 2.7164790103743150566578 028035789834835*I], [1, -1.0891151457205048250249527946671612684, -2.4285174 907194186068992069565359418365, 0.71946691128913178943997506477288225734, -2 .5558200350691694950646071159426779972; 1, 0.3534326558436260713470530909729 9828470, 1.1549969969398343650309345170134923246, -2.27039314228143996450010 21653326313849, -2.5581084321144835749447428779547264828; 1, -0.630200097311 74679864801261932183221744, 2.7744268453177922675968161614046216617, 2.12576 76084878153637389368667440155906, 0.58218204506434277886573208324566973893; 1, 3.7329764161953853934603848598678578170, 0.559693092766708315491805500989 95851667, 1.3462427005649082090774405779536603703, -1.4506057993146599110859 938482531161129; 1, -0.36709382900675984113447253685186261580, -2.0605994443 049163412203492228721306665, -2.9210840780604153977562503441379268334, 3.982 3522214339702022296117589048508540], [16, -17, -39, 12, -41; 16, 6, 18, -36, -41; 16, -10, 44, 34, 9; 16, 60, 9, 22, -23; 16, -6, -33, -47, 64], [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, 10 6; 0, 118, 173, 225, -34]], [3, 5, 23]], [-1.0891151457205048250249527946671 612684, -0.13838372073406036365047976417441696637 + 0.4918163765776864349975 3285514741525107*I, 1.6829412935943127761629561615079976006 + 2.050035122601 0726172974286983598602164*I], [2, 2*x, -x^4 + 3*x^3 - 5*x^2 - 4*x + 2, -x^4 + 2*x^3 - 2*x^2 - 9*x - 2, -x^4 + 2*x^3 - 4*x^2 - 7*x - 4], [1, 0, -1, -7, - 14; 0, 1, 1, -2, -15; 0, 0, 0, 2, 4; 0, 0, 1, 1, -2; 0, 0, -1, -3, -4], [1, 0, 0, 0, 0, 0, -1, -1, -2, 4, 0, -1, 3, -1, 1, 0, -2, -1, -3, -1, 0, 4, 1, - 1, -1; 0, 1, 0, 0, 0, 1, 1, -1, -1, 1, 0, -1, -2, -1, 1, 0, -1, -1, -1, 3, 0 , 1, 1, 3, -3; 0, 0, 1, 0, 0, 0, 0, 0, 1, -1, 1, 0, 0, 0, -2, 0, 1, 0, -1, - 1, 0, -1, -2, -1, -1; 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 2, 1, 0, 1, 0, 0, 0, 0, 2, 0, -1; 0, 0, 0, 0, 1, 0, -1, -1, -1, 1, 0, -1, 0, 1, 0, 0, -1 , 1, 0, 0, 1, 1, 0, 0, -1]] ? nfinit(nfpol,3)[2] Mod(-1/2*x^4 + 3/2*x^3 - 5/2*x^2 - 2*x + 1, x^5 - 2*x^4 + 3*x^3 + 8*x^2 + 3* x + 2) ? nf3=nfinit(x^6+108); ? setrand(1);bnf2=bnfinit(y^3-y-1);nf2=bnf2.nf; ? setrand(1);bnf=bnfinit(x^2-x-57,,[0.2,0.2]);[bnf.cyc,bnf.fu] [[3], [Mod(-x - 7, x^2 - x - 57)]] ? setrand(1);my(K=bnfinit(x^2-x-100000,1));[K.cyc,K.fu] [[5], [Mod(379554884019013781006303254896369154068336082609238336*x + 119836 165644250789990462835950022871665178127611316131167, x^2 - x - 100000)]] ? bnr=bnrinit(bnf,[[5,3;0,1],[1,0]],1);bnr.cyc [12] ? bnr2=bnrinit(bnf,[[25,13;0,1],[1,1]]);bnr2.bid [[[25, 13; 0, 1], [1, 1]], [80, [20, 2, 2], [17, [2, 2]~, [0, -2]~]], [Mat([ [5, [-2, 1]~, 1, 1, [1, 57; 1, 2]], 2]), Mat([[5, [-2, 1]~, 1, 1, [1, 57; 1, 2]], 2])], [[[[20], [17], [25, 13; 0, 1], [[[2, 2]~, [1, 2], [5, [-2, 1]~, 1, 1, [1, 57; 1, 2]]]~, 2, [4, Mat([2, 2])]], [4, 7, [[[5], [6], Mat([1, -13 ]), 5]]], [[-15]~, Mat(16)]]], [[2, 2], Vecsmall([1, 2]), [-0.04528654880364 0718227839951807630066450, -0.034713451196359281772160048192369933551; 0.010 397655620934129810079722893872882085, -0.05039765562093412981007972289387288 2085], 16.099559462816166945393896537005798909, [-12, -1; 1, -2]]], [[1; 0; 0], [0, 0; 1, 0; 0, 1]]] ? rnfinit(nf2,x^5-x-2) [x^5 - x - 2, [83718587879473471, -18162091535584830*x^14 + 6593998738955900 *x^13 + 89125883511340690*x^12 - 123429972713895380*x^11 - 86184686128261590 *x^10 + 508290939376248430*x^9 - 88425050961683595*x^8 - 806556841120532680* x^7 - 2575481228604156570*x^6 + 2756771576006241774*x^5 - 289772792762362859 5*x^4 + 4379071886234238350*x^3 - 4957913590225421420*x^2 - 9814084760206994 84*x + 24006278056864075, 39516536165538345*x^14 - 6500512476832995*x^13 - 1 96215472046117185*x^12 + 229902227480108910*x^11 + 237380704030959181*x^10 - 1064931988160773805*x^9 - 20657086671714300*x^8 + 1772885205999206010*x^7 + 5952033217241102348*x^6 - 4838840187320655696*x^5 + 5180390720553188700*x^4 - 8374015687535120430*x^3 + 8907744727915040221*x^2 + 4155976664123434381*x + 318920215718580450], [49744, 3109], 1, [2, 3109], [], [[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], 1, [y^3 - y - 1, [1, 1], -23, 1, [[1, 0.754877666246 69276004950889635852869189, 1.3247179572447460259609088544780973407; 1, -0.8 7743883312334638002475444817926434595 - 0.7448617666197442365931704286043923 6724*I, -0.66235897862237301298045442723904867037 + 0.5622795120623012438991 8214490937306150*I], [1, 0.75487766624669276004950889635852869189, 1.3247179 572447460259609088544780973407; 1, -1.6223005997430906166179248767836567132, -0.10007946656007176908127228232967560887; 1, -0.13257706650360214343158401 957487197871, -1.2246384906846742568796365721484217319], [16, 12, 21; 16, -2 6, -2; 16, -2, -20], [3, -1, 0; -1, 1, 3; 0, 3, 2], [23, 16, 13; 0, 1, 0; 0, 0, 1], [7, -2, 3; -2, -6, 9; 3, 9, -2], [23, [10, 1, 8; 7, 3, 1; 1, 7, 10]] , [23]], [1.3247179572447460259609088544780973407, -0.6623589786223730129804 5442723904867037 + 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 + 189*x^3 + 144*x^2 + 25*x + 1, 39516536165538345/83718587879473471*x^14 - 65005124768 32995/83718587879473471*x^13 - 196215472046117185/83718587879473471*x^12 + 2 29902227480108910/83718587879473471*x^11 + 237380704030959181/83718587879473 471*x^10 - 1064931988160773805/83718587879473471*x^9 - 20657086671714300/837 18587879473471*x^8 + 1772885205999206010/83718587879473471*x^7 + 59520332172 41102348/83718587879473471*x^6 - 4838840187320655696/83718587879473471*x^5 + 5180390720553188700/83718587879473471*x^4 - 8374015687535120430/83718587879 473471*x^3 + 8907744727915040221/83718587879473471*x^2 + 4155976664123434381 /83718587879473471*x + 318920215718580450/83718587879473471, -1, y^3 - y - 1 , x^5 - x - 2], [0, 0]] ? bnfcertify(bnf) 1 ? setrand(1);K=bnfinit(x^4+24*x^2+585*x+1791,,[0.1,0.1]); ? u=nfalgtobasis(K,73/1029*x^3-319/1029*x^2+1033/343*x+9829/343); ? U=concat(K.fu,K.tu[2]); ? [K.cyc,nffactorback(K,U,bnfisunit(K,u))==u] [[4], 1] ? bnrconductor(bnf,[[25,13;0,1],[1,1]]) [[5, 3; 0, 1], [1, 0]] ? bnrconductorofchar(bnr,[2]) [[5, 3; 0, 1], [0, 0]] ? bnfisprincipal(bnf,[5,1;0,1],0) [1]~ ? bnfisprincipal(bnf,[5,1;0,1]) [[1]~, [2, 1/3]~] ? bnfisunit(bnf,Mod(3405*x-27466,x^2-x-57)) [-4, 1]~ ? bnfnarrow(bnf) [3, [3], [[3, 2; 0, 1]]] ? bnfsignunit(bnf) [ 1] [-1] ? bnrclassno(bnf,[[5,3;0,1],[1,0]]) 12 ? lu=ideallist(bnf,55,3); ? bnrclassnolist(bnf,lu) [[3], [], [3, 3], [3], [6, 6], [], [], [], [3, 3, 3], [], [3, 3], [3, 3], [] , [], [12, 6, 6, 12], [3], [3, 3], [], [9, 9], [6, 6], [], [], [], [], [6, 1 2, 6], [], [3, 3, 3, 3], [], [], [], [], [], [3, 6, 6, 3], [], [], [9, 3, 9] , [6, 6], [], [], [], [], [], [3, 3], [3, 3], [12, 12, 6, 6, 12, 12], [], [] , [6, 6], [9], [], [3, 3, 3, 3], [], [3, 3], [], [6, 12, 12, 6]] ? bnrdisc(bnr,Mat(6)) [12, 12, 18026977100265125] ? bnrdisc(bnr) [24, 12, 40621487921685401825918161408203125] ? bnrdisc(bnr2,,,2) 0 ? bnrdisc(bnr,Mat(6),,1) [6, 2, [125, 13; 0, 1]] ? bnrdisc(bnr,,,1) [12, 1, [1953125, 1160888; 0, 1]] ? bnrdisc(bnr2,,,3) 0 ? bnrdisclist(bnf,lu) [[[6, 6, Mat([229, 3])]], [], [[], []], [[]], [[12, 12, [5, 3; 229, 6]], [12 , 12, [5, 3; 229, 6]]], [], [], [], [[], [], []], [], [[], []], [[], []], [] , [], [[24, 24, [3, 6; 5, 9; 229, 12]], [], [], [24, 24, [3, 6; 5, 9; 229, 1 2]]], [[]], [[], []], [], [[18, 18, [19, 6; 229, 9]], [18, 18, [19, 6; 229, 9]]], [[], []], [], [], [], [], [[], [24, 24, [5, 12; 229, 12]], []], [], [[ ], [], [], []], [], [], [], [], [], [[], [12, 12, [3, 3; 11, 3; 229, 6]], [1 2, 12, [3, 3; 11, 3; 229, 6]], []], [], [], [[18, 18, [2, 12; 3, 12; 229, 9] ], [], [18, 18, [2, 12; 3, 12; 229, 9]]], [[12, 12, [37, 3; 229, 6]], [12, 1 2, [37, 3; 229, 6]]], [], [], [], [], [], [[], []], [[], []], [[], [], [], [ ], [], []], [], [], [[12, 12, [2, 12; 3, 3; 229, 6]], [12, 12, [2, 12; 3, 3; 229, 6]]], [[18, 18, [7, 12; 229, 9]]], [], [[], [], [], []], [], [[], []], [], [[], [24, 24, [5, 9; 11, 6; 229, 12]], [24, 24, [5, 9; 11, 6; 229, 12]] , []]] ? bnrdisclist(bnf,20) [[[[Vecsmall([]), Vecsmall([])], [[6, 6, Mat([229, 3])], [0, 0, 0], [0, 0, 0 ], [0, 0, 0]]]], [], [[[Vecsmall([12]), Vecsmall([1])], [[0, 0, 0], [12, 6, [-1, 1; 3, 3; 229, 6]], [0, 0, 0], [0, 0, 0]]], [[Vecsmall([13]), Vecsmall([ 1])], [[0, 0, 0], [0, 0, 0], [12, 6, [-1, 1; 3, 3; 229, 6]], [0, 0, 0]]]], [ [[Vecsmall([10]), Vecsmall([1])], [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0 ]]]], [[[Vecsmall([20]), Vecsmall([1])], [[12, 12, [5, 3; 229, 6]], [24, 12, [5, 9; 229, 12]], [0, 0, 0], [0, 0, 0]]], [[Vecsmall([21]), Vecsmall([1])], [[12, 12, [5, 3; 229, 6]], [0, 0, 0], [24, 12, [5, 9; 229, 12]], [0, 0, 0]] ]], [], [], [], [[[Vecsmall([12]), Vecsmall([2])], [[0, 0, 0], [0, 0, 0], [0 , 0, 0], [0, 0, 0]]], [[Vecsmall([12, 13]), Vecsmall([1, 1])], [[0, 0, 0], [ 0, 0, 0], [0, 0, 0], [24, 0, [3, 12; 229, 12]]]], [[Vecsmall([13]), Vecsmall ([2])], [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]]], [], [[[Vecsmall([44] ), Vecsmall([1])], [[0, 0, 0], [0, 0, 0], [12, 6, [-1, 1; 11, 3; 229, 6]], [ 0, 0, 0]]], [[Vecsmall([45]), Vecsmall([1])], [[0, 0, 0], [12, 6, [-1, 1; 11 , 3; 229, 6]], [0, 0, 0], [0, 0, 0]]]], [[[Vecsmall([10, 12]), Vecsmall([1, 1])], [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [[Vecsmall([10, 13]), V ecsmall([1, 1])], [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]]], [], [], [[ [Vecsmall([12, 20]), Vecsmall([1, 1])], [[24, 24, [3, 6; 5, 9; 229, 12]], [4 8, 24, [3, 12; 5, 18; 229, 24]], [0, 0, 0], [0, 0, 0]]], [[Vecsmall([13, 20] ), Vecsmall([1, 1])], [[0, 0, 0], [0, 0, 0], [24, 12, [3, 6; 5, 6; 229, 12]] , [48, 0, [3, 12; 5, 18; 229, 24]]]], [[Vecsmall([12, 21]), Vecsmall([1, 1]) ], [[0, 0, 0], [24, 12, [3, 6; 5, 6; 229, 12]], [0, 0, 0], [48, 0, [3, 12; 5 , 18; 229, 24]]]], [[Vecsmall([13, 21]), Vecsmall([1, 1])], [[24, 24, [3, 6; 5, 9; 229, 12]], [0, 0, 0], [48, 24, [3, 12; 5, 18; 229, 24]], [0, 0, 0]]]] , [[[Vecsmall([10]), Vecsmall([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]]]]], [[[Vecs mall([68]), Vecsmall([1])], [[0, 0, 0], [0, 0, 0], [0, 0, 0], [12, 0, [17, 3 ; 229, 6]]]], [[Vecsmall([69]), Vecsmall([1])], [[0, 0, 0], [0, 0, 0], [0, 0 , 0], [12, 0, [17, 3; 229, 6]]]]], [], [[[Vecsmall([76]), Vecsmall([1])], [[ 18, 18, [19, 6; 229, 9]], [36, 18, [-1, 1; 19, 15; 229, 18]], [0, 0, 0], [0, 0, 0]]], [[Vecsmall([77]), Vecsmall([1])], [[18, 18, [19, 6; 229, 9]], [0, 0, 0], [36, 18, [-1, 1; 19, 15; 229, 18]], [0, 0, 0]]]], [[[Vecsmall([10, 20 ]), Vecsmall([1, 1])], [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]], [[Vecs mall([10, 21]), Vecsmall([1, 1])], [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]]]] ? bnrisprincipal(bnr,idealprimedec(bnf,7)[1]) [[9]~, [32879/6561, 13958/19683]~] ? dirzetak(nfinit(x^3-10*x+8),30) [1, 2, 0, 3, 1, 0, 0, 4, 0, 2, 1, 0, 0, 0, 0, 5, 1, 0, 0, 3, 0, 2, 0, 0, 2, 0, 1, 0, 1, 0] ? factornf(x^3+x^2-2*x-1,t^3+t^2-2*t-1) [ x + Mod(-t, t^3 + t^2 - 2*t - 1) 1] [ x + Mod(-t^2 + 2, t^3 + t^2 - 2*t - 1) 1] [x + Mod(t^2 + t - 1, t^3 + t^2 - 2*t - 1) 1] ? vp=idealprimedec(nf,3)[1] [3, [1, 0, 1, 0, 0]~, 1, 1, [1, 4, -1, 6, -4; -1, 2, 4, 3, -5; -1, -1, 1, 0, 4; -1, -1, -2, 0, -2; 0, 3, 0, 0, 0]] ? idx=idealhnf(nf,vp) [3 2 1 0 1] [0 1 0 0 0] [0 0 1 0 0] [0 0 0 1 0] [0 0 0 0 1] ? idealred(nf,idx,[1,5,6]) [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=idealdiv(nf,5,idealprimedec(nf,5)[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] ? 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) [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] ? idz=idealintersect(nf,idx,idy) [15 10 5 0 12] [ 0 5 0 0 2] [ 0 0 5 0 1] [ 0 0 0 5 2] [ 0 0 0 0 1] ? aid=[idx,idy,idz,1,idx]; ? idealadd(nf,idx,idy) [1 0 0 0 0] [0 1 0 0 0] [0 0 1 0 0] [0 0 0 1 0] [0 0 0 0 1] ? idealaddtoone(nf,idx,idy) [[6, 0, 0, 0, 0]~, [-5, 0, 0, 0, 0]~] ? 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, 4, 2, -1, -3]~ ? idealcoprime(nf,idx,idx) [-1/3, 1/3, 1/3, 1/3, 0]~ ? idealdiv(nf,idy,idt) [5 0 0 10/3 41/9] [0 5 0 5/3 31/9] [0 0 5 5/3 13/9] [0 0 0 5/3 1/9] [0 0 0 0 1/3] ? idealdiv(nf,idx2,idx,1) [3 2 1 0 1] [0 1 0 0 0] [0 0 1 0 0] [0 0 0 1 0] [0 0 0 0 1] ? idealfactor(nf,idz) [[3, [1, 0, 1, 0, 0]~, 1, 1, [1, 4, -1, 6, -4; -1, 2, 4, 3, -5; -1, -1, 1, 0 , 4; -1, -1, -2, 0, -2; 0, 3, 0, 0, 0]] 1] [[5, [-1, 0, 0, 0, 2]~, 4, 1, [2, -3, 0, -12, 6; 2, 2, -5, -2, 6; 1, 1, 0, - 1, -7; 2, 2, 5, 3, 1; 1, -4, 0, -1, 3]] 3] [[5, [2, 0, 0, 0, -2]~, 1, 1, [2, 1, 10, -4, 2; 0, 0, -5, 0, 0; 3, -1, 0, -1 , -7; 0, 0, 5, 5, 5; 1, -2, 0, 3, 1]] 1] ? idealhnf(nf,vp[2],3) [3 2 1 0 1] [0 1 0 0 0] [0 0 1 0 0] [0 0 0 1 0] [0 0 0 0 1] ? ideallist(bnf,20) [[[1, 0; 0, 1]], [], [[3, 2; 0, 1], [3, 0; 0, 1]], [[2, 0; 0, 2]], [[5, 3; 0 , 1], [5, 1; 0, 1]], [], [], [], [[9, 5; 0, 1], [3, 0; 0, 3], [9, 3; 0, 1]], [], [[11, 9; 0, 1], [11, 1; 0, 1]], [[6, 4; 0, 2], [6, 0; 0, 2]], [], [], [ [15, 8; 0, 1], [15, 3; 0, 1], [15, 11; 0, 1], [15, 6; 0, 1]], [[4, 0; 0, 4]] , [[17, 14; 0, 1], [17, 2; 0, 1]], [], [[19, 18; 0, 1], [19, 0; 0, 1]], [[10 , 6; 0, 2], [10, 2; 0, 2]]] ? bid=idealstar(nf2,54) [[[54, 0, 0; 0, 54, 0; 0, 0, 54], [0]], [132678, [1638, 9, 9]], [[[2, [2, 0, 0]~, 1, 3, 1], 1; [3, [3, 0, 0]~, 1, 3, 1], 3], [[2, [2, 0, 0]~, 1, 3, 1], 1; [3, [3, 0, 0]~, 1, 3, 1], 3]], [[[[7], [[1, -27, -27]~], [2, 0, 0; 0, 2, 0; 0, 0, 2], [[1, [1, 1, 0; 0, 0, 1; 0, 1, 0], [2, [2, 0, 0]~, 1, 3, 1], y^3 + y + 1]~, y^2 + y, [7, Mat([7, 1])]]], [[234, 9, 9], [[-1, 16, 12]~, [1, - 24, 0]~, [1, 0, -24]~], [27, 0, 0; 0, 27, 0; 0, 0, 27], [[1, [1, 2, 0; 0, 0, 1; 0, 1, 0], [3, [3, 0, 0]~, 1, 3, 1], y^3 + 2*y + 2]~, y^2 + 1, [26, [2, 1 ; 13, 1]]], [26, [-7, 4, 3]~, [[[3, 3, 3], [4, [1, 3, 0]~, [1, 0, 3]~], [1, 0, 0; 0, 1, 0; 0, 0, 1], 3], [[3, 3, 3], [10, [1, 9, 0]~, [1, 0, 9]~], [1, 0 , 0; 0, 1, 0; 0, 0, 1], 9]]], [[-207, 0, 0]~, [208, 0, 0, 156, 0, 0; 0, 1, 0 , 0, -6, 0; 0, 0, 1, 0, 0, -6]]]], [[], Vecsmall([])]], [[-234; 0; 0], [7, - 182, 182; 3, -5, 5; 0, 1, 0]]] ? ideallog(nf2,y,bid) [568, 2, 3]~ ? idealmin(nf,idx,[1,2,3]) [-2, 1, 1, 0, 1]~ ? idealnorm(nf,idt) 9 ? 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,5,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, [-1, 0, 1, 0, 0]~, 1, 1, [0, 2, 0, -4, -2; 0, 0, 0, 2, 0; 0, 0, -2, -2, -2; 1, 0, 3, 0, -1; 1, 0, 1, 0, -1]], [2, [0, 0, 0, 1, 1]~, 1, 4, [1, -1, 3 , -1, 1; 0, 0, -2, -1, 1; 1, 0, 1, 0, -2; 0, 0, 1, 2, 2; 0, -1, 0, 1, 1]]] ? idealprimedec(nf,3) [[3, [1, 0, 1, 0, 0]~, 1, 1, [1, 4, -1, 6, -4; -1, 2, 4, 3, -5; -1, -1, 1, 0 , 4; -1, -1, -2, 0, -2; 0, 3, 0, 0, 0]], [3, [1, 1, 1, 0, 0]~, 2, 2, [0, -6, 3, -9, 9; 2, -1, -7, -5, 7; 2, 1, 0, 1, -7; 1, 2, 3, 2, 4; 0, -5, -1, 0, 2] ]] ? idealprimedec(nf,11) [[11, [11, 0, 0, 0, 0]~, 1, 5, 1]] ? idealtwoelt(nf,idy) [5, [2, 2, 1, 2, 1]~] ? idealtwoelt(nf,idy,10) [-1, 4, 2, 4, 2]~ ? idealstar(nf2,54) [[[54, 0, 0; 0, 54, 0; 0, 0, 54], [0]], [132678, [1638, 9, 9]], [[[2, [2, 0, 0]~, 1, 3, 1], 1; [3, [3, 0, 0]~, 1, 3, 1], 3], [[2, [2, 0, 0]~, 1, 3, 1], 1; [3, [3, 0, 0]~, 1, 3, 1], 3]], [[[[7], [[1, 0, -27]~], [2, 0, 0; 0, 2, 0; 0, 0, 2], [[1, [1, 1, 0; 0, 0, 1; 0, 1, 0], [2, [2, 0, 0]~, 1, 3, 1], y^3 + y + 1]~, y + 1, [7, Mat([7, 1])]]], [[234, 9, 9], [[-17, 14, -8]~, [1, -24, 0]~, [1, 0, -24]~], [27, 0, 0; 0, 27, 0; 0, 0, 27], [[1, [1, 2, 0; 0, 0, 1; 0, 1, 0], [3, [3, 0, 0]~, 1, 3, 1], y^3 + 2*y + 2]~, 2*y^2 + y + 2, [26, [2 , 1; 13, 1]]], [26, [-11, -10, -2]~, [[[3, 3, 3], [4, [1, 3, 0]~, [1, 0, 3]~ ], [1, 0, 0; 0, 1, 0; 0, 0, 1], 3], [[3, 3, 3], [10, [1, 9, 0]~, [1, 0, 9]~] , [1, 0, 0; 0, 1, 0; 0, 0, 1], 9]]], [[-207, 0, 0]~, [208, 0, 0, 156, 0, 0; 0, 1, 0, 0, -6, 0; 0, 0, 1, 0, 0, -6]]]], [[], Vecsmall([])]], [[-234; 0; 0] , [7, -182, 182; 3, -5, 5; 0, 1, 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] ? nfbasistoalg(nf,ba) Mod(x^3 + 5, x^5 - 5*x^3 + 5*x + 25) ? nfdisc(x^3+4*x+12) -1036 ? nfeltdiv(nf,ba,bb) [584/373, 66/373, -32/373, -105/373, 120/373]~ ? nfeltdiveuc(nf,ba,bb) [2, 0, 0, 0, 0]~ ? nfeltdivrem(nf,ba,bb) [[2, 0, 0, 0, 0]~, [4, -1, -5, -1, -3]~] ? nfeltmod(nf,ba,bb) [4, -1, -5, -1, -3]~ ? nfeltmul(nf,ba,bb) [50, -15, -35, 60, 15]~ ? nfeltpow(nf,bb,5) [-291920, 136855, 230560, -178520, 74190]~ ? nfeltreduce(nf,ba,idx) [1, 0, 0, 0, 0]~ ? nfeltval(nf,ba,vp) 0 ? nffactor(nf2,x^3+x) [ x 1] [x^2 + 1 1] ? aut=nfgaloisconj(nf3) [-x, x, -1/12*x^4 - 1/2*x, -1/12*x^4 + 1/2*x, 1/12*x^4 - 1/2*x, 1/12*x^4 + 1 /2*x]~ ? nfgaloisapply(nf3,aut[5],Mod(x^5,x^6+108)) Mod(-1/2*x^5 + 9*x^2, x^6 + 108) ? nfhilbert(nf,3,5) -1 ? nfhilbert(nf,3,5,vp) -1 ? nfhnf(nf,[a,aid]) [[1, 1, 4; 0, 1, 0; 0, 0, 1], [[15, 2, 10, 12, 4; 0, 1, 0, 0, 0; 0, 0, 1, 0, 0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], 1, 1]] ? da=nfdetint(nf,[a,aid]) [15 10 5 0 12] [ 0 5 0 0 2] [ 0 0 5 0 1] [ 0 0 0 5 2] [ 0 0 0 0 1] ? nfhnfmod(nf,[a,aid],da) [[1, 1, 4; 0, 1, 0; 0, 0, 1], [[15, 2, 10, 12, 4; 0, 1, 0, 0, 0; 0, 0, 1, 0, 0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], 1, 1]] ? nfisideal(bnf.nf,[5,1;0,1]) 1 ? nfisincl(x^2+1,x^4+1) [-x^2, x^2] ? nfisincl(x^2+1,nfinit(x^4+1)) [-x^2, x^2] ? nfisisom(x^3+x^2-2*x-1,x^3+x^2-2*x-1) [x, -x^2 - x + 1, x^2 - 2] ? nfisisom(x^3-2,nfinit(x^3-6*x^2-6*x-30)) [-1/25*x^2 + 13/25*x - 2/5] ? nfroots(nf2,x+2) [Mod(-2, y^3 - y - 1)]~ ? nfrootsof1(nf) [2, -1] ? nfsnf(nf,[a[,1..3],[1,1,1],[idealinv(nf,idx),idealinv(nf,idy),1]]) [[15706993357777254170417850, 1636878763571210697462070, 1307908830618593502 9427775, 1815705333955314515809980, 7581330311082212790621785; 0, 5, 0, 0, 0 ; 0, 0, 5, 0, 0; 0, 0, 0, 5, 0; 0, 0, 0, 0, 5], [1, 0, 0, 0, 0; 0, 1, 0, 0, 0; 0, 0, 1, 0, 0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], [1, 0, 0, 0, 0; 0, 1, 0, 0, 0; 0, 0, 1, 0, 0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1]] ? nfsubfields(nf) [[x, 0], [x^5 - 5*x^3 + 5*x + 25, x]] ? polcompositum(x^4-4*x+2,x^3-x-1) [x^12 - 4*x^10 + 8*x^9 + 12*x^8 + 12*x^7 + 138*x^6 + 132*x^5 - 43*x^4 + 58*x ^2 - 128*x - 5] ? polcompositum(x^4-4*x+2,x^3-x-1,1) [[x^12 - 4*x^10 + 8*x^9 + 12*x^8 + 12*x^7 + 138*x^6 + 132*x^5 - 43*x^4 + 58* x^2 - 128*x - 5, Mod(-279140305176/29063006931199*x^11 + 129916611552/290630 06931199*x^10 + 1272919322296/29063006931199*x^9 - 2813750209005/29063006931 199*x^8 - 2859411937992/29063006931199*x^7 - 414533880536/29063006931199*x^6 - 35713977492936/29063006931199*x^5 - 17432607267590/29063006931199*x^4 + 4 9785595543672/29063006931199*x^3 + 9423768373204/29063006931199*x^2 - 427797 76146743/29063006931199*x + 37962587857138/29063006931199, x^12 - 4*x^10 + 8 *x^9 + 12*x^8 + 12*x^7 + 138*x^6 + 132*x^5 - 43*x^4 + 58*x^2 - 128*x - 5), M od(-279140305176/29063006931199*x^11 + 129916611552/29063006931199*x^10 + 12 72919322296/29063006931199*x^9 - 2813750209005/29063006931199*x^8 - 28594119 37992/29063006931199*x^7 - 414533880536/29063006931199*x^6 - 35713977492936/ 29063006931199*x^5 - 17432607267590/29063006931199*x^4 + 49785595543672/2906 3006931199*x^3 + 9423768373204/29063006931199*x^2 - 13716769215544/290630069 31199*x + 37962587857138/29063006931199, x^12 - 4*x^10 + 8*x^9 + 12*x^8 + 12 *x^7 + 138*x^6 + 132*x^5 - 43*x^4 + 58*x^2 - 128*x - 5), -1]] ? polgalois(x^6-3*x^2-1) [12, 1, 1, "A_4(6) = [2^2]3"] ? polred(x^5-2*x^4-4*x^3-96*x^2-352*x-568) [x, x^5 - x^4 + 2*x^3 - 4*x^2 + x - 1] ? polred(x^4-28*x^3-458*x^2+9156*x-25321,3) [ 0 x] [ 1/115*x^2 - 14/115*x - 212/115 x^2 - 2*x - 9] [ -1/115*x^2 + 14/115*x + 442/115 x^2 - 2*x - 9] [ 1/115*x^2 - 14/115*x - 327/115 x^2 - 10] [1/4485*x^3 - 7/1495*x^2 - 1034/4485*x + 7924/4485 x^4 - 8*x^2 + 6] ? polred(x^4+576,1) [x, x^2 - 3*x + 3, x^2 - 2*x + 2, x^2 - x + 1, x^2 + 1, x^4 - x^2 + 1] ? polred(x^4+576,3) [ 0 x] [ -1/192*x^3 - 1/8*x + 3/2 x^2 - 3*x + 3] [ -1/24*x^2 + 1 x^2 - 2*x + 2] [ 1/24*x^2 + 1 x^2 - 2*x + 2] [ -1/192*x^3 - 1/8*x + 1/2 x^2 - x + 1] [ 1/192*x^3 + 1/8*x + 1/2 x^2 - x + 1] [ -1/24*x^2 x^2 + 1] [1/192*x^3 + 1/48*x^2 - 1/8*x x^4 - x^2 + 1] ? p2=Pol([1,3021,-786303,-6826636057,-546603588746,3853890514072057]); ? fa=[11699,6;2392997,2;4987333019653,2]; ? polred(p2,0,fa) [x, x^5 - 80*x^3 - 223*x^2 + 800*x + 2671] ? polred(p2,1,fa) [x, x^5 - 80*x^3 - 223*x^2 + 800*x + 2671] ? polredabs(x^5-2*x^4-4*x^3-96*x^2-352*x-568) x^5 - x^4 + 2*x^3 - 4*x^2 + x - 1 ? polredabs(x^5-2*x^4-4*x^3-96*x^2-352*x-568,1) [x^5 - x^4 + 2*x^3 - 4*x^2 + x - 1, Mod(2*x^4 - x^3 + 3*x^2 - 3*x - 1, x^5 - x^4 + 2*x^3 - 4*x^2 + x - 1)] ? polredord(x^3-12*x+45*x-1) [x, 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], [-7, -63, -116]~] ? rnfbasis(bnf2,aa) [1 0 0 [-66/25, -24/25, -3/25]~ [-202/25, 97/25, -241/25]~] [0 1 0 [48/25, -3/25, 9/25]~ [61/25, -121/25, 238/25]~] [0 0 1 [51/25, 39/25, 8/25]~ [267/25, 38/25, 136/25]~] [0 0 0 [37/25, 18/25, -4/25]~ [124/25, -64/25, 117/25]~] [0 0 0 [-6/25, -9/25, 2/25]~ [-47/25, -8/25, -1/25]~] ? rnfdisc(nf2,p) [[416134375, 202396875, 60056800; 0, 3125, 2700; 0, 0, 25], [-7, -63, -116]~ ] ? 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]~ [22/25, 33/25, -99/25]~] [0 1 0 [-6/5, -4/5, 2/5]~ [-16/25, -24/25, 72/25]~] [0 0 1 [-3/5, -2/5, 1/5]~ [8/25, 12/25, -36/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, [-66/25, -24/25, -3/25]~, [69/125, 1/5, 3/125]~; 0, 1, 0, [48/25, -3/25, 9/25]~, [-48/125, 2/125, -9/125]~; 0, 0, 1, [51/25, 39/25, 8/25]~, [ -56/125, -41/125, -8/125]~; 0, 0, 0, [37/25, 18/25, -4/25]~, [-39/125, -18/1 25, 4/125]~; 0, 0, 0, [-6/25, -9/25, 2/25]~, [7/125, 9/125, -2/125]~], [1, 1 , 1, 1, [125, 0, 22; 0, 125, 108; 0, 0, 1]], [416134375, 202396875, 60056800 ; 0, 3125, 2700; 0, 0, 25], [-7, -63, -116]~] ? setrand(1);quadclassunit(1-10^7,,[1,1]) [2416, [1208, 2], [Qfb(277, 55, 9028), Qfb(1700, 1249, 1700)], 1] ? setrand(1);quadclassunit(10^9-3,,[0.5,0.5]) [4, [4], [Qfb(211, 31405, -16263)], 2800.6252519070160764863706217370745514, 1] ? getheap()[1] 165 ? print("Total time spent: ",gettime); Total time spent: 42 pari-2.17.2/src/test/32/rnfkummer0000644000175000017500000000135514676526175015136 0ustar billbill *** Warning: new stack size = 40000000 (38.147 Mbytes). 1 1 2 1 3 4 1 5 1 6 1 7 1 8 1 9 x^5 - 10*x^3 + 20*x - 10 10 1 11 1 12 x^2 + (y^5 - 37*y^4 + 315*y^3 + 503*y^2 + 130*y - 301) 13 0 14 x^2 + (157*y^5 - 1702*y^4 + 39*y^3 - 595*y^2 + 732*y - 1534) 15 1 16 x^2 - 5 17 1 18 x^3 - 3*x - 1 19 x^5 - 10*x^3 + 5*x^2 + 10*x + 1 20 x^2 + 1 x^2 + (-2814*y^3 - 107928/5*y^2 + 8892*y + 341148/5) x^2 + (-4*y^2 + 12*y - 13) x^2 + (-25*y^2 - 20*y - 28) x^3 + Mod(-3837*y^2 + 258*y - 107823, y^3 + 28*y + 2)*x + Mod(366568*y^2 - 2 5322*y + 10265498, y^3 + 28*y + 2) *** at top-level: rnfkummer(bnfinit(x^2+23)) *** ^-------------------------- *** rnfkummer: incorrect priority in bnrclassfield: variable x = x Total time spent: 6645 pari-2.17.2/src/test/32/random0000644000175000017500000000373714760123736014404 0ustar billbill324237808 Mod(2, 3) a^2 [[a, a + 1], 1] 3223690774*a^2 + 2495927739*a + 1543932468 [[222673296*a^2 + 832141822*a + 1993872865, 3473855231*a^2 + 2165401445*a + 1363496513], 1] 4063307077606482163*a^2 + 2169871353760194456*a + 10598342506117936052 [[2557945391375694509*a^2 + 5182580949942002905*a + 4115304207846177355, 808 4599253441901006*a^2 + 17319169765369271807*a + 5394713598728073384], 1] 0.56071855301363810851584520787407920871 Mod(5, 7)*x^3 + Mod(2, 7)*x^2 + Mod(1, 7)*x + Mod(6, 7) *** at top-level: randomprime(2) *** ^-------------- *** randomprime: domain error in randomprime: N <= 2 *** at top-level: randomprime([0,1]) *** ^------------------ *** randomprime: domain error in randomprime: floor(b) - max(ceil(a),2) < 0 *** at top-level: randomprime([2.5,2.4]) *** ^---------------------- *** randomprime: domain error in randomprime: b-a < 0 *** at top-level: randomprime([2.4,2.5]) *** ^---------------------- *** randomprime: domain error in randomprime: floor(b) - max(ceil(a),2) < 0 1051006573 5 1267650600228229401496703924683 37 37 2 [1, 6, 3, 4, 4, 2, -7, 7, 4, -8] *** at top-level: random("") *** ^---------- *** random: incorrect type in genrand (t_STR). *** at top-level: setrand(2^65) *** ^------------- *** setrand: domain error in setrand: n != getrand() *** at top-level: setrand(-1) *** ^----------- *** setrand: domain error in setrand: n <= 0 *** at top-level: randomprime([3,100],Mod(0,2)) *** ^----------------------------- *** randomprime: elements not coprime in randomprime: 0 2 *** at top-level: randomprime(2,2) *** ^---------------- *** randomprime: domain error in randomprime: N <= 2 *** at top-level: randomprime(3,2) *** ^---------------- *** randomprime: no prime satisfies congruence in interval. Total time spent: 2 pari-2.17.2/src/test/32/idealappr0000644000175000017500000000037514567450071015060 0ustar billbill3 [23/2, [6, 1/2]~] -23/2 [0, 0] *** at top-level: idealtwoelt(K,[;],1) *** ^-------------------- *** idealtwoelt: domain error in idealtwoelt2: element mod ideal != 0 0 [2748900, [-661475, -403399, 358895]~] Total time spent: 1 pari-2.17.2/src/test/32/quadray0000644000175000017500000024473614676526175014612 0ustar billbill-15: x^2 - x + 1 -35: x^2 - x - 1 -51: x^2 - x + 1 -91: x^2 - x + 2 -115: x^2 - x - 1 -123: x^2 - x + 1 -187: x^2 - x + 3 -195: x^4 - x^3 + 2*x^2 + x + 1 -235: x^2 - x - 1 -267: x^2 - x + 1 -403: x^2 - x - 3 -427: x^2 - x + 2 -435: x^4 - x^3 + 2*x^2 + x + 1 -483: x^4 - x^3 - x^2 - 2*x + 4 -555: x^4 - x^3 + 2*x^2 + x + 1 -595: x^4 - x^3 + 5*x^2 + 2*x + 4 -627: x^4 - x^3 - 2*x^2 - 3*x + 9 -715: x^4 - x^3 + 8*x^2 + 3*x + 9 -795: x^4 - x^3 + 2*x^2 + x + 1 -1435: x^4 - x^3 + 5*x^2 + 2*x + 4 -20: x^2 + 1 -24: x^2 - 2 -40: x^2 + 2 -52: x^2 + 1 -84: x^4 - x^2 + 1 -88: x^2 - 2 -120: x^4 + 2*x^2 + 4 -132: x^4 - x^2 + 1 -148: x^2 + 1 -168: x^4 - 2*x^3 + x^2 - 6*x + 9 -228: x^4 - x^2 + 1 -232: x^2 + 2 -280: x^4 - 2*x^3 - 5*x^2 + 6*x - 1 -312: x^4 + 2*x^2 + 4 -340: x^4 + 3*x^2 + 1 -372: x^4 - x^2 + 1 -408: x^4 + 2*x^2 + 4 -420: x^8 - 3*x^6 + 8*x^4 - 3*x^2 + 1 -520: x^4 + 6*x^2 + 4 -532: x^4 - 3*x^2 + 4 -660: x^8 - 3*x^6 + 8*x^4 - 3*x^2 + 1 -708: x^4 - x^2 + 1 -760: x^4 - 2*x^3 - 5*x^2 + 6*x - 1 -840: x^8 - 4*x^7 + 22*x^6 - 52*x^5 + 117*x^4 - 152*x^3 + 160*x^2 - 92*x + 1 9 -1012: x^4 - 5*x^2 + 9 -1092: x^8 + 3*x^6 + 5*x^4 + 12*x^2 + 16 -1320: x^8 - 4*x^7 + 22*x^6 - 52*x^5 + 117*x^4 - 152*x^3 + 160*x^2 - 92*x + 19 -1380: x^8 - 3*x^6 + 8*x^4 - 3*x^2 + 1 -1428: x^8 + 3*x^6 + 5*x^4 + 12*x^2 + 16 -1540: x^8 - 4*x^7 - 4*x^6 + 26*x^5 - 3*x^4 - 42*x^3 + 56*x^2 - 30*x + 9 -1848: x^8 - 4*x^7 + 18*x^6 - 40*x^5 + 83*x^4 - 104*x^3 + 22*x^2 + 24*x + 4 -5460: x^16 + 9*x^14 + 44*x^12 + 261*x^10 + 1029*x^8 + 1044*x^6 + 704*x^4 + 576*x^2 + 256 -1155: x^8 + 15*x^6 + 32*x^4 + 15*x^2 + 1 -1995: x^8 + 15*x^6 + 32*x^4 + 15*x^2 + 1 -3003: x^8 - 9*x^6 + 80*x^4 - 9*x^2 + 1 -3315: x^8 + 9*x^6 + 77*x^4 + 36*x^2 + 16 x^20 + 27*x^19 + 601*x^18 - 4014*x^17 + 9878*x^16 - 12222*x^15 + 8299*x^14 + 513*x^13 - 12221*x^12 + 18036*x^11 - 17652*x^10 + 18036*x^9 - 12221*x^8 + 5 13*x^7 + 8299*x^6 - 12222*x^5 + 9878*x^4 - 4014*x^3 + 601*x^2 + 27*x + 1 x^88 - 40020669926358941160*x^87 + 24818793423306608856949584839454391158484 *x^86 - 451973748435231895940407803697160552367624*x^85 + 121004331374769746 054948634032289469332999202*x^84 + 10059034519705811655247252004833057160111 397504*x^83 + 351284965440856373689297063590147136894509846260*x^82 + 707678 7287183022340559185242964779073439110772112*x^81 + 7424864222152380159098443 6783829317747047323123243*x^80 + 3016669049298212175376092685252207677089225 7842640*x^79 - 8503049963424563714394067134889147531482230019127096*x^78 - 6 465786499366041070602916523486769538280412443510592*x^77 + 42150640446078238 28889410160434091263108115351306399268*x^76 + 119525498598846149476451596656 291689313170011135603889064*x^75 + 20718604339256925426029633374659465824208 08944831769026648*x^74 + 270442350108592451558861828173327053458397647311211 61439752*x^73 + 285289444253762620585561596576563633155859094294552566693317 *x^72 + 2511360320483460798105377398519192324398612242438706127652544*x^71 + 18767162620094934148004508464072766541604227783326918296860524*x^70 + 12042 3236654140529086575067911655764408706511359484732574173280*x^69 + 6698817371 51097381424117880193907743151768744395737304965311638*x^68 + 326030488372458 1257592451461949148632593587481718123636435123040*x^67 + 1401218174432359703 4445628272252822116949974099153581386829916444*x^66 + 5367567444185487660948 9208131197694348596313231643993076280314304*x^65 + 1849586073448214933624859 71605260396892443743494472396759635803315*x^64 + 578456213592452525292885126 678569328965911834184953238551507495512*x^63 + 16556817033476544452278210145 76515450466671643615335188802513429760*x^62 + 436878840618787239769625306249 7812500894047454768846457782824580152*x^61 + 1068901472860957747029160191079 1767817886254017900185293235705392064*x^60 + 2434351573155431230076300160060 7496079487124511808873652848483412160*x^59 + 5169291351655811457272426459136 7158576380942435990299052219843612304*x^58 + 1022998330750281135258911239455 74251052215437006684583051817380710576*x^57 + 188216797464058241448403558395 102741401235865324690992824034126437157*x^56 + 32060490325705765556225025226 1154391117300969466803557524988405580272*x^55 + 5026257120330186308702396982 13303008551061011852403188260952091908532*x^54 + 719344126023656757735145641 575616692987264009491520118662670217955328*x^53 + 92863816021928333070040902 0325566534550048821651703177989079236808666*x^52 + 1060255920795694954480037 612092276836813066528658822564102146651872808*x^51 + 10301589215685511855337 00012926850740762293883499745887488519869745108*x^50 + 771562428494427189300 153767022260995609490878443644218508155682351496*x^49 + 27346597807333111348 9250648988966144580871198921998690911757680224167*x^48 - 3923005119785941970 23702549831167038133623220261146198494006317061248*x^47 - 107531566077276356 7397744183394797701786847214693166357365831146616968*x^46 - 1589451619928021 606930471659130946568147974811578111348229080651241920*x^45 - 17807285584553 57793403089789263493950243261264268279117584476244784076*x^44 - 158945161992 8021606930471659130946568147974811578111348229080651241920*x^43 - 1075315660 772763567397744183394797701786847214693166357365831146616968*x^42 - 39230051 1978594197023702549831167038133623220261146198494006317061248*x^41 + 2734659 78073331113489250648988966144580871198921998690911757680224167*x^40 + 771562 428494427189300153767022260995609490878443644218508155682351496*x^39 + 10301 58921568551185533700012926850740762293883499745887488519869745108*x^38 + 106 0255920795694954480037612092276836813066528658822564102146651872808*x^37 + 9 28638160219283330700409020325566534550048821651703177989079236808666*x^36 + 719344126023656757735145641575616692987264009491520118662670217955328*x^35 + 502625712033018630870239698213303008551061011852403188260952091908532*x^34 + 320604903257057655562250252261154391117300969466803557524988405580272*x^33 + 188216797464058241448403558395102741401235865324690992824034126437157*x^3 2 + 102299833075028113525891123945574251052215437006684583051817380710576*x^ 31 + 51692913516558114572724264591367158576380942435990299052219843612304*x^ 30 + 24343515731554312300763001600607496079487124511808873652848483412160*x^ 29 + 10689014728609577470291601910791767817886254017900185293235705392064*x^ 28 + 4368788406187872397696253062497812500894047454768846457782824580152*x^2 7 + 1655681703347654445227821014576515450466671643615335188802513429760*x^26 + 578456213592452525292885126678569328965911834184953238551507495512*x^25 + 184958607344821493362485971605260396892443743494472396759635803315*x^24 + 5 3675674441854876609489208131197694348596313231643993076280314304*x^23 + 1401 2181744323597034445628272252822116949974099153581386829916444*x^22 + 3260304 883724581257592451461949148632593587481718123636435123040*x^21 + 66988173715 1097381424117880193907743151768744395737304965311638*x^20 + 1204232366541405 29086575067911655764408706511359484732574173280*x^19 + 187671626200949341480 04508464072766541604227783326918296860524*x^18 + 251136032048346079810537739 8519192324398612242438706127652544*x^17 + 2852894442537626205855615965765636 33155859094294552566693317*x^16 + 270442350108592451558861828173327053458397 64731121161439752*x^15 + 207186043392569254260296333746594658242080894483176 9026648*x^14 + 119525498598846149476451596656291689313170011135603889064*x^1 3 + 4215064044607823828889410160434091263108115351306399268*x^12 - 646578649 9366041070602916523486769538280412443510592*x^11 - 8503049963424563714394067 134889147531482230019127096*x^10 + 30166690492982121753760926852522076770892 257842640*x^9 + 74248642221523801590984436783829317747047323123243*x^8 + 707 6787287183022340559185242964779073439110772112*x^7 + 35128496544085637368929 7063590147136894509846260*x^6 + 10059034519705811655247252004833057160111397 504*x^5 + 121004331374769746054948634032289469332999202*x^4 - 45197374843523 1895940407803697160552367624*x^3 + 24818793423306608856949584839454391158484 *x^2 - 40020669926358941160*x + 1 x^180 - 51943580593235209115083942712389400740668999369044471856895869572767 632154790719027854950985687*x^179 + 2547067915519807589841747083394507454979 0011527047653789753822310509943417124290253283094780925633779566003695241876 25607464220675698078104131248853904115685519116107718359916443145223952387*x ^178 + 856553204115408701571995615320558014258368114267533599476048702248757 8902931990647387774030794984717551258507939754932426394582122894184128382067 3569718022270291080598668993546776793532380154605306*x^177 + 762080502049470 4596056107304576599883142953678664313128034639146864833136453854583485947432 8177873097803164055573630934557797549232895603414584717394309407907786380469 1683834066404398393999145427753183790*x^176 + 308956387636466960153212938167 7324702311668880384172270669030644914696644648416192123216702361395347555520 1495693461977412751821857739072346944409047470651675235147675440424833117756 620892810879743135932320774*x^175 + 4884082662966665508762665969667649569784 5383873744492103182446854649967702283785050616521253612447115822047297077954 9614257317623478309277167745811150568304415956966429217813229788441116863100 4611840186992685967179*x^174 + 124005751296377747143710892598982088036932674 2142684503704154223658839486788375142268292156393058732202380086677633411654 8906703591687073852643697697716348962297583421466683339923965234468615997649 73368284228647193399*x^173 + 77807342164244792507055296791047457009683139076 6947550930281827860194252415153283906741350015821421760488076097868784697023 0684361377176470035198102530788844464458277074023468487612291349831916437723 0037354352780222249*x^172 - 266780829858115272388789250462200876445272313022 9458822467054384295379499065005972497338635889603051515741573734931874924695 7762408306245748926170958653384087543385833522528441856486249210097660034861 41241557823792412532*x^171 + 14828387316468627026106844845255173547861518903 8589804985538974108300682790820861191991101023068971076505863346789787263249 0126030705881134291752595991307720023292738164624564498269365143236280388326 494814603159167594322356*x^170 + 2072714630254694525113015470563866763470442 2896220054319081495621750749375349838158314700070013284414958575563065629489 9298590460673967042987581924280852650108640761845803254699501956119005286958 261737898381117495750422003980*x^169 + 4082791913658668250669500487553396688 5085691856416081922391794020222319071345465620337482939902695391053957179581 6611178564058054521757672875527012214760684410920857152888054853976552319787 6482624865506579220641586389147210551*x^168 + 259189082653047933938409996483 4388754704904320561628999269016762833054641395201768798413743705844841716523 7122469823713043234758088183799986341785098434142194216335145773402440120312 8996614247360365624068492442391061043753826375*x^167 + 187953325502846394560 1845576629993961992277419183089685715578164443785846738744772926323542142109 3239442057010359289122214569790614009609800219235849343052099855997036406115 0923659276590113217049579865275822653265241753456459305677*x^166 - 991521344 5331010597888861249891641758957210552260378821158082129353375249195112911754 5101896722210096101308894624313777264446536224444928929934283573873319884763 96421078624456037269503565600020449431475165029149896378441501395456086*x^16 5 + 870693463207410936114722926699616258456056310070174066271951439226764821 3754498248686363880077592953938815295745097173153881494887680426204688519814 5897926708879854493196612672343274340176910775178567635481360192954408109761 462192666*x^164 + 3291269524452623301119531480681600174871375032940729132937 0111633092058003369070348946123426594086592059620504463833497832222752798945 6786539655327366403796168376108709100410788811433213881703418728731545343808 0442501304279059153710266*x^163 - 484246978651008470853848049302633937841710 0550099032573348884254048698254002568503682165709558099310997622779159632947 3025430835921039731844769840401840637061784295187888579980063280775750740026 326213445261209232925320378956182578938287*x^162 + 2366596557978274147475255 9694980204169227021539516608112189319106501133980328077568567038119905399100 7262473707379165967733688444634721899783534252243520926838729652205328556398 93844358125373580233579396300331967493836532017339326648417*x^161 - 17861170 0215272735065228998593221635895564621730723507909826896490382687997403628306 4372396936244334959016553113715105764010891971421665085465778102274753181053 1359367179288752406620535700142801097476915172283884503644920276078920893715 961*x^160 + 5442886569416213072883949195207003561672975168183342200753916623 1352236561897735153650345477157913505173224695785900066453147636135746522196 8827923591138659172463973059604218652821751160134239388400400287612441644522 959559654240096950196384*x^159 - 1878459194456192332344340381238953837099207 3242518317157665963817987346890603378811086853859511458448823118145390556032 4154260960085054869261002833248663395080605671172589053299559751809388877985 0319337022684143396368259434426190698508218580*x^158 - 184127686942437509991 1682977301117955663562464265148547217904344728959181240974449884065092029207 1219636898969097801966235466592457246648086083637230209961453625153292993135 3654541155851737335657948991190630601809654864812836013412428233332508*x^157 + 6272745337714289642780597731451440214649776184728899306566105704002623998 3846347725688034820317498349655377903497224390190783460776334008364647848917 2185092927745795075828017034702156144511828098427591206009505705409852728295 6922223630676347544*x^156 - 130604497267883349741727434418972048161536102040 0079797720405754446746742329603550983122106752795162131799337624121456619065 4040984420476843424034832196407821304821044910660899700295392042290695059542 0192036616889048813209519926849958791965413764*x^155 + 193926478941415365968 2053039191650223015193274556301436638340272814361000782491228757908126714135 5744831221609082890601733276886531625139761625422579999591146356457708488690 66496229883200724281039999541182828857613242844117034223500903997780849964*x ^154 - 208974081851580435134258388853435474877812078509775426825496895616316 4247844796032344219123951883470813854035626246176679417061266672681500232259 0819881630082047200072248185982748889171705144305698252911851141436968395735 658717414968653352018931248*x^153 + 1672646641882017449123000870294181985430 0761766363953593948968045530794890931499833945021531203099422476121576329491 5115325960697513628674724029981734640823975379662772003784140453861998461512 834247290509716832865395591217427305274661390000337103156*x^152 - 1133671449 3365295420476716878286616778916616227898741966819659317216135015136322466563 9827520548877905001507920274192410200096811676503284991805981968482979122155 1667739765953276248859306767909175625527281202034750975189910458947747942582 531447345892*x^151 + 9686019535728726397130721344019529061590234306774474243 9775684839133142925738217830167297947427381690011105467748624943273307935251 9499655312785116384255798310740712404573339361423884780107379495371631287103 7645627569348897599991117672316256550430096*x^150 - 119041422102704367724958 8670984575013578769595187713509039012506017888268506357273229685836102923546 0042880742312037127040383670254597841508519424535302963725051506007472454825 8974287875801351389617602402488639578930420752407411968308213028222350043652 *x^149 + 1390123122192263005517637294725114792837919558648428420458046731138 9247265920089325134952307005121333495864776226593824308305802270042865765522 1706646232757561716861576911604612712092794424651617086755060497490406116694 4942837594012909743669233042838778*x^148 - 123556176727604048392495454055977 6399401450331126081896858806346942631913417189093648332266104142047071085393 9823740200206373338590719973268754644225041558662153246796876936041537325415 712055287848699094590808089508684909536725801531454334504662219155298*x^147 + 78338857321405672298333791473025282082268588399811517655878927064487660842 9607987213338588537735184368455093544029691810855962878302724567812912958403 0825298526758499964573195767901492416707505928731723979119497738428625056534 2370732550549861221973628014*x^146 - 337429582052616696434247676773381390391 7055420548509812685321889562165936397719575630122778103303140528950818170117 1026255806634894861047352747650017243235019037703269391120793396636598558834 3500355068020592838333693543614719695933939552850201760137124456*x^145 + 126 7022512449095517765635963857489440320956185849532448394191453064873093377283 3265337003928417799194535821386624283453961529673399508105934582815314275613 7678638219426069444953840237686338226443443810754745407998159540925231095791 4375045407870857103723132*x^144 - 153719609646143637199240438779331521362833 0310998022856189520090149655383700607165028197046414621578662674582267335714 8666559983310416796564643262431404031085708670498514131879172395315308884725 086995597751964859239544450069420287019254955379338574827976392*x^143 + 2752 6304730305492309519611803297873567100995379403820014027217572772469997269963 1748009334990330332456740707557146239264293783419594063347012801512753255648 8881765170905842263824483323437412768565907107652500759762684840263032684703 37380600828996170962184046*x^142 - 35523095157828313337139462591351702816577 1657314332343178845563474958542277571903631744992145135630234735095041102708 2345107273636547410151070834277389339249300538652341339871040322822838485719 858336476359261521139254885461283464480406069617193177086233150446*x^141 + 3 4465803554989246489275769454764022910035142135182748059069252044933640478411 7307420416885830806110765171489332421312130211574457885515807957701177125587 6661225789242989640797022695297712572706533434600560766081391785453226598427 1205078552129981020849945722662*x^140 - 268373722516115839581073071008494919 0456447093682830001175926782807962713700083271168738651540876330140533486735 6212670696857859739463338404796759488859624213038265846572508064515479105995 6333436847011768914542767112707721040710586854450242752202162514502517912*x^ 139 + 1742444297891369493991077844263622734267621349666334184372478600323885 9274274057411635646353155281298451648136704209002938845039923935043096379256 4945721786177563429720654144039386133241554831725367065310144005542392522004 1645737733894132094639323829473024157820*x^138 - 963039078892037951990470202 7468142690696595830419680618831266273162745223389393610063433083213953579433 1498149151107810908751113241849208570338521838179678717281819508263987198750 1951924824700995996767534695158748257780864272656666861530432230128739030598 8300028*x^137 + 457447376242160839222865523212081512251204172769554541536513 6010675335568757571514112103791600745366139173664147588418919365588570555754 7201003803879915712080042312095406320055413204732204964260573379515119902554 321889204610298573371864198642424001195728006133182*x^136 - 1868860578136529 9491100566653843653174297026478659238845320831747624530880395790502643308730 5462268585078679776019946603866991516563272428283420299615035631054324035580 7669631492489263529234747091359176119230324423792605912297491073916656362078 32174634098946284598*x^135 + 65093076668803329116252899967129264121954195081 3165825173825622033622982444205859242607493663511833086292972086895883603422 4352287091011138657074487961579204189764700353920301472872505685227133477493 45517047708745645767806883427498415677547239236298519819304443846*x^134 - 18 8737857214948682414768736751123125995536055732425264657481481197221465136381 8263080004881765201151009039934832304971738613022285488660591980899059758561 7366670880266091842937662126151457793355558304191543211766144762254313419741 75714575265820939899419742919508060*x^133 + 42953889394645520155740965583894 8254975167613584775116826651538942451816286881091436166450578237021021126058 7376408754507104013237607018922017023401049094197048725524392809860540776061 0681787413121689140926769612819886834513469809393226136437731088172895759675 25206*x^132 - 63261727328918865906350940397161109868277289808692349026207015 7309911965921420948111081525007085507792610014228611379115265836635218591862 4482685303352489099685390524441351132050179570452776530090912230189731431879 125807895290459527651483474680605068851138729175634*x^131 - 1119917054839792 2751688900486058857057243360132605635779686384574213339264438353376214516815 2207498910643644483743753772520064969246600402986900436948848152659373181329 5043050789946887406470007794027558566892567839570362080341591028664006259784 979214096682612622692*x^130 + 4271314220049466852560738338393246245128105321 7108326600567680720579375803199815405014779522998261575404021302604267102318 9973496984002749534274370752056057799997646445393423249459072172570153388076 90270224780252688493775073451490812831750493851260007482523315136586*x^129 - 148023590100710673141860886464816208028643509093283015533625006596766946972 6741578398020050334876578221252235677233082465182051389340632694789790351225 9115953643872578590861494318898368229141353955324644187699428307147375218229 1248178529493117079561875143739124185634*x^128 + 246175641614565897679653848 5278045743286736401969417596627545851445013857575343959525966011452777041860 1869322995580927692188758796260764328940765798775338277071600497396412898284 6342663264119335560750008714258096212502569271025201095741906534219351860811 124404494196*x^127 + 1990565893680671595442880060323376805411690898242032023 4239133079106312028397798694740007864603898415855926572783576585034622967997 5575446479539827712484639591071048813727255731760017261708300771575388890158 591817638333201062459001177511936169630253047386566741135222*x^126 - 3016573 2341675486865253308430441797191448447887193219597832133129727214089635223501 3420645212244383261917032590855201496548201420356430642227248391186457171733 8876314939133108407277975244227776960656325124355051502725255975073566061339 620994099300340563608380613367050*x^125 + 1257948144362960333134666662231940 3520935251787268873160231319726921665830921964289640164226960267401382195941 0507546787902030963701849030258171787071185516798073095493413189997247441301 2363645824641255038770075189157898962912949013449974648054148641764400320533 8871882*x^124 - 366475271260105058017315536083033948306360270631496526170966 8533370069635382315040133597595175856841519762702237383805014287542574172530 6210807276260801506088986006283626986882464595447299254658758485568943925875 853699462405048328247959368186852953798221740253247284792*x^123 + 8471667404 0018254168541029547267006611224730675524513635334023354380604251758054675593 5413776225446989659313910683079873583112382327573250917778108062870743163021 6965584066720515779759514188951805094972301673794254962048375194153324360075 8727975735045108792516939770864*x^122 - 161146935717428461799784793801173853 4799737191324944707968337975196134044400893575466678041623869973266066574271 1435647219232676062975775017270732119064549881937724549671623652481177104960 6102487507016989267838733791065664530366349655384775511706599600386112512946 557632*x^121 + 2522694849864480951479825412582961761101029175375006299005032 3620295897587695065324670940000207944207812042399077482469097012869133985212 6354595110186421998141347799854111539239085705015451817020704883026517132793 698058647769011690212936405831828960609809154392310067086*x^120 - 3123954350 9500414655822246820581466016766786100370771446195101114970617420873338985187 2315673998753642061765284674623730429562551231647203516276142369010876697525 2061798837483708658347309888670578337964579148520979957165473678360131302986 17785547855899873691057926811306*x^119 + 26093073450128435322247521043157618 8712392067239030279298185926981851613832003883595362112194063431825921469777 7131659026396971729721032938463093179955600695600080670675651357367571081793 3768796854158042814794986008423382503555686761603718155957955520619915926285 1046258*x^118 - 546620888417310306456913297002373587712583541328636451073449 6886209350963457906027266059482196156973048570086277940148682564568467798438 0285254978737341206009503937974698380503149962544290779617099637261387918629 06553536781663415296571417609896418531671323802662549340*x^117 - 50182021729 3272384861232464186597002893681068429473599603378492391207630929901153313074 7556376877685127771266174954090809732508146930392545806488414232849981602588 1335383921214771830072947665323419883309028215410288472590477875403748309525 8171403839074803113722901930619*x^116 + 118406103336876158577917454186709740 5449294198484094378541103762383848536861007244183348157579457933081098099434 7987985778741196393539613217121527222032672240767536916435194526743758819619 0063225181878442213678933572194923238652257406338724947439730929871504295850 1899245*x^115 - 176734272677759520180709847378647130652166835479092271077232 7067981192822476939413912953115815829947318808933249885514336602487836197536 9611127131928890515684844943744748937382837125994011164383657897820620204611 77419977223148716322298719262705865767989172293892727336803*x^114 + 17753024 8530519942716171951800965388948822797211110233322549229100349316200278964800 3343785390491378071036048329384421918922891522117638503012421231548652255160 9599399433846703918342084346728100760000876417162144138571778762943474072695 63098844605653811371200441716482612*x^113 - 68055808039422415389652936779491 5026270001374161671086886435342385993661681436002138177107204224273906832078 4550021770688659201646483026969760576245696112286845508450285259619203332272 0607576466516522822599227539775561873960850804338603845784871088630793662781 4494090172*x^112 - 171345855168993153971261857965957509597335839923271917993 0591415159154748543112880240425751510004701705465610982555391151034624958936 9879115829869566643976034053215829935761929815383663545384160654490729816046 26649741228358475390951398611771434975819632467920927623648602*x^111 + 47552 8035498943149856772358089912005247194452214038396267610512853006205877224336 1926512880782786766025384282981294577511242497413537295024045772317451006411 5818078293866049727834002439604775548744427611299658913382859972919684056285 23953865800092933414124830547621130787*x^110 - 67242845398127603346764378735 8630417913935967603492325560313387832908161625682986070993808856191981689362 7337618874976711707752413017492294772666895660870194024839210050819796389750 1107885069331081963929674153546422780993129544541729439872603263786386221427 59365186532673*x^109 + 55277967193070494108505087891929956655236889687657826 8175977451438771610569912425740087266827286735858716699401268464277514456005 1393232906738794805715412356740750890873873435323228244674952180988795091974 844777831874994317609349719963129292674653332785827444869904448205*x^108 - 4 1613159149582603037007821378021268206873842361757130321500129691291418451571 4472352328413744363607247454062853765212695133675510221970937823367502714872 5264869179155436190999803707918965482858909915679294544758294286168029187155 42674704594105656661109974298786084926216*x^107 - 64968550520798695907403393 0416095844971770756779773877908365468264830766792721054670459397639118998550 4854765543268865886038920660387928909044011453689430024047009170672072811027 5782636138143658008315348604258233043465414839888086317182504579245353574551 48087384017967480*x^106 + 10988704303885892826315283975311210242722783884449 6602821133827001873720461030281740372523131562861261636562127194114761297380 7567084209038324237434507186912029498523360122835533024309739840677831689412 3866277910335992520712968840312446267340837533424627065123680989778324*x^105 - 1037769081322395498728280928797930421673181636784651943232652987200370379 9887100753154281880152957110034253066824316513009332837888828809575782813589 8395431699875068691882278140209738486991188655032931569583339555950811469751 14819216369493334147767991300084429910831005417*x^104 + 69810186616581919293 4087787107108500858284600224749854536503416055380938630777674032345768445107 9032740625501338477163577149719360331436837611189692791831261366092124431433 6123841173727343108316374825964917374812406255193704152752318584125714566685 03155908009579048097943*x^103 - 62618742936856051264116083169826991776205278 5386210430790988069604384137878194361389699073225403863192706786752381073990 4629809810678656127043145873535279223707645117591581849318483810783264428888 878968101286898381392510682070079334990623735577742545874102235967038827767* x^102 + 88547713577136747022744956480711506392268841458610902634308115200722 8001393811863713127092848888453031249274119846056297769374759830206187529701 1903856417069237945552069729259203293736154678785007420066778201855082685563 641521979888163226986534911148352808279115809917358*x^101 - 4630158507380629 2388093315791533391137484806668109034703107450628858742143410102799736933423 6907074978067722826731138207487756769203481925052544349731537665931451375605 6491082785764360244007240454153410730447743408991269401214809728107755411693 172395012634341107448006498*x^100 - 1987106430336286502255096633621975778269 2749388116010785359867801694785712027822174277716791024889732874123796999017 1165326722657523135611227287116367063127157679861619224054599116072941563451 0018552431779605085569288059085092991937490866241369045567079522410549051673 8430*x^99 + 6116111486479868423461963851524196927490094772654137109281820240 9655601335862868609893744275312622546677599324483201519748792880440223783865 4698142956751915407410209991596924924552268184253687896341372281276522326101 46924043615114529192462392320461821295874662972625510705*x^98 - 858543407202 8582480876325305001979394403680268817452625497746550339718414937826890236809 6758090513332370728027354524452052318746523877507900393006790670253886201007 7151654142173689494119764321155798594114038476768325934248961469594904974057 82950778627016658691250674749383*x^97 + 490657445429729269017920968754688301 6620517611911217595219014813015157155188541123765870476789021829481317185682 2346556428383215072814614042291152340886085128841976463982340477579191182175 5499560251631802981685749888173758813318700520169103214089237413133223676806 81136483*x^96 + 588480356039113348615320015128938548650997950279831325677040 1070851758771375890193257175605171144175873327958813862484089151772708967824 5090710382325088735952719657758536202632425695397040762304230638936597396706 141037241892685559313526162149365318736429347633086308123732*x^95 - 17860801 0792691455581088588394658008616948993017279794644452692311940825238452683644 2319855428360563553746309477403369295008059059368147822762461583481089204503 0764049052795948146830428753094428042821800841448746792034840653376273350188 2132907610936220993092559868115464848*x^94 + 2080698898949934438755286742414 6744709766506973468237223938818775848985645787102709849630670421667929387077 1839075966340916755041077369098858794090822988106295163721588178394959186872 9508222800790599280424915420728365948473247641413622178547384599468880111768 92625701864148*x^93 - 855864218009308575944636024731111359775112255204531345 0227262959123310950664276060293965525931786616911167403341188615339530286675 6775269831884121745448799689118137607558616438099756213430487533482486835346 075682903923880766231253716972279618549611306311532332784130069552*x^92 - 13 6808840532983525733371616856915983783270410509211401019532102689258560876086 9527424128221769318567475482882108641281228508725452571176264919548871309015 8567261995935441375507973903437038954795573527871968541716126334097932463611 5855437833626026464694567238228672113384692*x^91 + 3083618181674886298656898 1166117178805224503007958449196073139881830099761716540415100166992970870487 3373126707079788137630463247890473378063608477167239399012803238136948080412 0312330266139820196748423629961267609185986608819581540758534872341667324689 62725982670350394704*x^90 - 289813403115309877208771459417444034084104076525 9424539591515173961928303088393009380304940043691096832523560373895822112785 5808066054703063840814273369617911574459101343616657558236169574623914019563 0152780337575962071156042744164046198739767637262303611768624103749962308*x^ 89 + 72613516630962625965473064217525199676649443527570426575481770740043888 6779646591936295747831851104939101651758342323554432645301127945581635380942 7667424563537772502070799105048465507245059623491244896462413185145901940314 5696053808385861551596378474452839548918080875392*x^88 + 2007137579167957439 0719911721927558340943820520648172319420534796396724837614574044411853430783 6722420021463109835306685189533078441109841798470591234934768692554906817588 1207883501035322616933512472492706367178783380343756988188031103657790713917 44233368892636267232901060*x^87 - 341583527690850438763926482860330447741875 4305316360798807536901393938873869395520682617524619723932218997197449552997 7902796418727196784273654618816384850023400797434252298928612530838816162641 9574193744111685493591811397803624718762999077541037470623557200013418602943 344*x^86 + 26018106816532769824515089189721783374074645569591071162155828403 0232272450337410678138897855399057733160129008028400975157648521806369052132 6598794386401757044711814737218799723053160173284842744313272283592926991658 43454191912138368855662104946473338105764358284022377572*x^85 - 285687497537 0233084322274278589877961032877493803575239781590446839383349838850110790540 3648812210524131836405185194224569727115488819662642038492004860753207681555 8064901322408777764393214575140844637199884061193474482510361153824419358509 00211274244171508240172003554579*x^84 - 185573110599032244389576804101570527 0843481327670529736455724859117579642729259313496498283495085435901054470028 2535196961772216663035884293412871166129440632779930980074617184610893507366 8787347778013694399060652311121162557391893749324368007933315027120013043270 445299679*x^83 + 25050117171467230890654410834087578617559538489554781281579 3157881185513898265592143907721703598168076058572348175071967137401886379765 0888321554412070999395502650926168357968511833244292802087783872357923454661 96695362647033860816591741894381954763538781291764410558313991*x^82 - 156624 0805166486574430551541640026858587070051407347684313586931160679067646271535 7829110559493831623647655992465253608722147473274284815377360979913488645232 4593004096825642014547164807256580851492214151707379016954878586353260655456 252800749153240368998676635038282783458*x^81 - 11012223211385811697215073324 1921762613953353874156837170764058477228457541142548719349032469796569578235 3672680465156231420291792630380279912309212851197963260878119761617542365940 8318430631980819407521411635240395800739279192347581702754335107271855384807 48046492479002*x^80 + 111235651556599161905998900669481587907856029607842384 7058721145611490097096177499329308286485980098377201553695581299300616429252 2896328548114223502627261314995818846022537138353738293647104367494387573394 8393580977308270455034395646105894483336815886915572733813700662098*x^79 - 1 2379020348161516025309044646747619580648761934003227421750700116671436042176 9234916272072233533611217288217765756191391217561297135624913793687875324800 7048123566476086580476470670309837456621193106958657582668447487991539286833 57031134988178799550492266664939630915472321*x^78 + 644986875872857655262996 2870357260072805613051355925273289691398310869281737114462536081840128975833 0126180055099077158183624456453836279081213829170321954905360807167962624432 0834840220201004905145194463702511094693925819892194681047038159942946067231 75356042055357536463*x^77 + 632358398592670498095591997355631111077729590643 2790651615164768723582162467454648690012209970035792209695666782959269273807 2446931808206460612526556054521554052793022216016750971388084812894581490191 87488153428597505906544272968607176655503312813518126744417345713254937*x^76 - 4407859464775144416487947396167367671725803977033500362272840558411894622 4142347820758760948628866949429655387790156661766965605123758771588193309114 1713374027265271324050920162934924792826148476476160753572716996003978356956 83804000368513801138734053137773265487620770740*x^75 + 416372459606780296337 1450264046151575655550849081038974416037216542290125884466463363808042083850 9725418382508403123824265992064946980309513636360132567064198384175231861989 9012223863450049443691606628550828159458118620199310401445249248178059313891 70550354597821348040080*x^74 - 184161864081127040151143217561783123125395859 3984003709177376821791781406937773897678496561663900933927169138471529228790 5120635576312602740572720848588646957621039854850944227105781066695720878550 615756344477554232044466772542846688611602947158650463473157163999798684880* x^73 - 294578669269207164351858864041819495442047310529305439637416055593898 7162766090787137613214756965908109965354836546249973970248312691190106013609 0096047571535265598414402965513205463264379299412109566296535132357163168956 32417972107859793797811490919775354115913639814509*x^72 + 116883470301786694 7940105919928790584076295711500240939987022716541425069544597244574520104343 0843831048650119597248348399831622778255382707463446772861932339155184508820 8691492120804327123688321050527154392082194558601074437356409645501206599517 48548591269958013706855735*x^71 - 962337617562843751668517056379887654984035 3607775335999245012386540197534720757701144759975007037123456361469330484819 1315697282222826434358396253666199318705803758613569124925030815057449171128 4560115497697369485081240160416963318875432658639303154335108578568393415001 1*x^70 + 3726752627853214173014791913150187098796942009506244634835348186874 6218248319652489347706949219918369593434279794434225414007742000717921598981 1967637764507611718683775885631603729498673872931482040372125187697058620137 8729901384977948736920393075869570682078658147246402*x^69 + 6664265109721472 5027167403028506905386766457143598965411785702251914095207487701546804662501 9973661173639310250173508615816977744154467727637322113813424769329746934178 2443037607433520297691194068563933234561377974297855282622664908800977935892 66781529161410379918516384*x^68 - 207155588658254864820236483929333843353850 2314782709935428769719703150188593756759875477634107095955930003335004909963 7806096997987389425073233030518177133541278388985086967790086225554199073757 9183726492903476789901947898423219398782945711055270770359481994540571424130 4*x^67 + 1533378023324702195795907021652744267401738630185227412509325644190 9317029060634416164456507736338956677716876820335111092883359676091733924360 7562229802747370137957394804745995747839571913841959663322372004062970960303 2739266325572053308062722007360886556152476819257995*x^66 - 5448017961352466 8954308761386777114515861425568699050923629567132295720176133619693154821070 6679446412666455188970580511515741859257380970964727783399666659463150181605 5832418778533170218818696428046565610812780388008951253152709903494726503303 47825776795872045310257331*x^65 - 782824212320460720852470872605130544762708 5270844370030560427574258798403117425649643063954946491985881365052474110155 1061361746263419716606571746236356433610334478429319747526941053865615635278 723792660268903548758991779230812111021711115289261014249648789576891768349* x^64 + 241834633150739573689757316859489557852802058328995612290604847372968 8962517428202844726500527178649942306770989823832330134459212595922531552449 0113231117621334324551438466322046602200466264537273693298034252254721421676 4952766269941267448422272698762518675998018630028*x^63 - 1666339352730570520 3639407453322817405171376787484109204948738088424073980877086807482951938601 8865103399869046069476520137316208493195695957902129110473449041403464176591 9862359175005557769808809061623387720644388156956972127266850675533756707525 90808120744985654078946*x^62 + 570449220804489887130193887685456156518623172 5938262332193484731157547462002602737462832660959996983966122744124822282431 6513410409807491982186685917971756931992668327222699312497837591559016609364 497532211515388699725043424503916154248093353508075820460159560673674726*x^6 1 + 379845061301619031112865499569621029871812941926085546779444789597593099 2185392685054292994780700584857914762885227739218300244363323904098764703684 3361325604313463057739669057343485520202139735014463468397975802705055082320 02067235766810391945048746973605012517899250*x^60 - 179994905002158006799826 1581248012266767598208187591516407746996243019260988129520947344375845837479 4375473622136858584586366278763492407789131148115802682216654123834671962143 5349323536462397163996997039950567353507544138641982512459740031444726096910 94329488186488560*x^59 + 119982265165997044452636805135365752758447406488957 0849779495733478576958767846719905517427473004995721810584114866176087023280 6873265056291159390228424704274613300367658551594974395489222878733856100659 323368722107547660243619913236809974787583082322603729616639857984*x^58 - 41 4498343303395026162273181308147077705273369693379285169454980456825999696414 1108191789225342382926105642661506635099783996258510012027273821755928691169 8167108483458843302305307979514403727827680023751217095370719902334212472094 52432417836264144119102122277397817768*x^57 + 151296257711150774319086699562 0621904293538949888063494638380250947255821384926730801679647950967103397199 8232664074317796747475932212744662087954481765782241246318995396862540981468 8990486802544852254612284845621149784604770996714678404380352987098024383778 212981782*x^56 + 77172024931648750131579375330854241317819193485030367789630 0194979153932088946756095579709069441269038355362032598061536345375371499825 7603589364289068081989344439616890875432673156016666549955986167393531518011 67940120441305635456765616769010583292909919688853748166*x^55 - 533362214813 2692571383637474154386631336646003027379100089536309803633081806433335487865 3788348099478071550518684140405592181062300213393211342562869431261195244746 4055597603055279266341016276936298547770626014341819185195774706572228813839 188337921892972222814214310*x^54 + 19809672028428641640899800622402763302466 1074260655961612294389483118237887223011979572958763434751014838641676318160 5147310285574152096915663041869066749730025370705253261451722595574825909044 34743256388662636089294615411424475808328353443007431056186153291193660236*x ^53 - 3298236730725312112107997188999732021783635308764336412988146411506139 7104102160872908196077077455976298299221998872649597890835291998156291479044 1156752915907868097785637632834657415730880385603530195196698224915641474164 13441042710366926553820042101416886262527990*x^52 - 101449365782699643760207 3313704763252338242187697491537141888115893684195480412346735267432884547401 4326674844047109008343871306484926351769633249049418818884494773111342516465 1364847880469035878140408781793697844423605606532175548895998431434178111893 10391299541374*x^51 + 997010027853800903810835659831173696396465410573075578 3905356009776229418935908969084901777161285772610734056245264176199983282362 9243150822898802087782083582569387718010137408195023053062329504663705594403 79207927321560114457596629472924327212630999737789491694628*x^50 - 400136364 1205954524277253466159627211505461211798229164611000835355077955105452940106 5043117114065854192422518937652264386811681003511656062957851230278085993229 0192913573475644905186402717704749806127538925050731511982133457968662243173 0574757902251581738927743514*x^49 + 9180213565693093847510479570029388499565 5962139940688297118935762169143151779122206282849955988804045093690808202777 1911618936765072016334219087961215540705432215522135777876375064000492729289 146413824719753030999530625757538495495631483556564886408485696916274754*x^4 8 - 501301210215460642688466550524464459820491039666763299722186435065388308 0998476722426260605286629208716991084876566352805637002187528368901275570021 1644840502467709341605696416994819511376212841122712589602930316113642419950 349056502832731819476610421210838732740*x^47 - 54944298141158889585149685718 7336779616988953202758365462768772698687661348560047998087075022182507327394 7519184487938281971887003668567460606612213622645012761958365390879314022191 3390146402903001771434654731924912308476740943900732699364805260630537589779 248726*x^46 + 26686242659774581832060629132908634079744101584587342617793147 5307484074819549903437909197788777407246096377950996274109900334593209284669 9285933458439326397108293597155087876694426014357663784876151672816297841341 0567270026180297395204928647366053260719567023642*x^45 - 7052486107172135206 1948720744051909520509772591994862049253916379923010961566356969081325001527 6292596993146766741009335610467932996827331500592308883886627814990767499859 2394117000761761120597925240350755933951486120638079133147944601048042610283 120648681977182*x^44 + 12094887988138431717848391295686703675228636456392942 8682928139939229340261144090919567211768947492261796729623549396284079133495 0340419054279131563933305486551030416968393033147914495046708454093512499973 890279938140031139050906270219603864516933692949758319412*x^43 - 13249348861 2052453833911384927269989662957662727807923412036942065407705141769113172260 4562201840504522929158651370739513572711063413085138434059101868053588204820 3501768317607444088231087593813985100365809682458092656030031376932623184206 7770517384807361785676*x^42 + 1335101451287203762576138569495941477971504274 6021839256417498499034598980956043459656243655749784623012085862698394648682 7521666667680743107938078657228707393173302010891133955653957891206671708545 21488797288438881522832497235465398261203063264934026405622216*x^41 - 499475 9281308667412284807719782367452360187792248198012964464639579785518460647882 3014472001994317756006942461078978073213429085061547197216262635883812900592 1762751571689421659752686372945957018076639346750248956405331139984740983345 9224825604519148808410998*x^40 + 2123055922106609642987166390747900882690095 8265815080171818541132693855937048009649851884749195950160943998565872859377 2466719457136622623105718221481729397353928547971338648745934933818733937555 9722029289477935787063071140468460122494931142480075599166922066*x^39 - 5735 6058097105987281579532842451121455107789722350655401468909089438850594255611 7398406496524366947519084716044767896958134185399473668974877433779111152344 5537408221196487932870899207582741017935334684933397499648658504512170298450 81211351675478818348250014*x^38 + 101323645478522769412770862955451494838700 8662851023057079588279613730397359405727823936580260643332082414004528447161 9032650746240307864113277781931187876839372237162972094621638339957461376513 5960868446031017264818726765755631590746592742117108410287162304*x^37 - 1158 2691707749694320983466811601420819483438159197492729367460974781919497846083 2310429882055944418973561703899132956324878554694827218593251972032733158957 9073374625050919799091874768764116278381338067763168272226788014070435497357 3342854568112725548119716*x^36 + 8305639013155526915236550603371532656184411 8485479725403465416008780582431421160189594698593377625798613038172701584227 4206678281269713323953843252700015484543752538426082787722637328521354532797 854400197712614233087564302182567125978130820395479367756272*x^35 - 72553146 6299857240224175450027827480387792541339702494044488085609115659954701904593 4063182032757400157986647557124710638076669642745888083114891044280939887931 1080380921785649390927188469314188121124356596001115383235298455028416330896 607528890361908254*x^34 + 19860798394812096491425064118869331882474934679022 5013755600349219086403728983462588925205132120800514991648137327905331386108 2705026046100093497647310070721575578185071569257102022328094661667732591461 4871110127674403701118049341045392289086401193314942*x^33 - 4504073630957286 8996977652497679946908816176921415580423759147328165686549644634042466661073 3511461352309328969240076472657648713663010059789108519959246932375899814162 7806075361906437084097330297847347043691634727928126429902493759079959944869 550465866*x^32 + 69070920659658480551690757737221770374761684950145185121047 2484618737300993281417864275556465857656908421568917719365815679023157411215 6057258090256560697376971566576951036121500346489928053597706896717897892051 06698965797835172312757476105925970954316*x^31 - 950505499088700807538705994 4852731534709761992249213459182019380991510107647264892021396558868144681611 0662751219780692605034863184825513108322135455467480199290708985357993844600 052787576017748490330946803622885911462082828385374632295839177766961104*x^3 0 + 146871001034451764467214379577713350818960453105454365246878113141243396 2615951663537883759634270986980824512323040156750516514483187596408739659469 9598984366473798855873087478723052705650039925818705324797901096311128210246 360020474709693712139627212*x^29 - 21967157682673292571077015450821069674087 1544590587052875727692154504672915643984006806321437086319058849365052767208 2180148377519601579902888730828514202452285184145954435822512134773040530752 315307032862652438081839581459737476241460047819927741316*x^28 + 25868119256 5279242165718547565481040416951897690007278140339301372610232089805802058986 0750808024571604981879223368087235334407689838584104951724530561739372122119 8951117323168039502216475583876368959953874029365022369810172602125325497095 6445408416*x^27 - 2428059268010321918244811964086129262156487932219116205050 4070649327791508268466838408282079070232219613570494028527410574628542390142 2207371899314254390315983442044698383945383757774385604939274532392556556337 58840387565176697754574091764000708652*x^26 + 228044964584692160131546765047 2366230486843363280069375103638842382972106217168205477299195570432297721283 4433913421328769323459813505283451769698919188569838637736110033080505201432 29246149018773191614239310593408598408683107352357568527200654044*x^25 - 240 6358660663137122033270184955011680904324977408022614274765749948013776439046 4906763369553397919412224096925386397722165397929814334230617641557808733911 0574280678118160005286224756835902809740658092872319513670690482675603106255 535345368222072*x^24 + 17662623687632442866313848276740533318473562530568602 6085380981148726634500393960831149553262597329458902932994016704916196167706 1802977969263820447192793617562366039417910781021352992596284460784056551089 2584667589514772071439777359014056460388*x^23 - 1017233748361584303945573233 3032677102808866261456706104325822118295706056417248083910297875201722536975 2472365095568346621934137039403008509886158851525905826470428214804919613199 4864749556380390451533567703437432891192535285335888731490497100*x^22 + 6962 4456632649901142038343508876142609309013148113719161965752973745996685396900 6242981394546059022035086880100336674301708003625923297490632324135942177919 6475754925837957964115788320422751182797666627301620661963625816748809270833 0371586416*x^21 - 5935499297476735425457730389595586123363077244239039067258 8757027689826646450579634779345685940054648366379750425264531723684895242726 1296842788479967443307602969542957303586075752713784702233094467073009888400 4709831827016377193151480549079*x^20 - 9924231276887632055264945002835855931 6153619298064184888082607712523327637455849379369518935749807342918090562216 3515240369483362753072379694694969114717331800146736581921176222284191504989 22256734920743781356158658426818610320388361445943*x^19 - 223034910041976985 5872625998444601823522405237422212480311276936526222907234872314934718146257 7999956125097315186127418244514895084164378747477418159356551630505131305135 965903638935951781824035858082445936492127698502477328282539866049529*x^18 - 236643075076678358536974434180237346813030211220576398492261042505158468477 4245106684856714329733460194522211899691204030539339797067532556065266564996 8995125799175143049170891303055998502994776437035748429866958228412329271509 6914727786*x^17 + 2542147127057127485965235153724151047113766830500853009593 4057432271073053439213859505464662101818485064985498169276132525055092922810 7659183430955698520972071635491614118402866501132808889569521209673251362824 76709756655755991836417802*x^16 + 183111149787713493280210397619912322103096 5247871179773154030195420556994309371058325110985700072545919333159157805938 6224014037352998052003315867311050614119923950889255536852768279112155091364 24174340648729576596630358137790527045198*x^15 - 449821041069912943789836264 5632599818971731559621159648780555694409049475593695526598586098851324811318 2519341945707916157927951713037252573987087918917682037480599453640794209186 225479459166338434922942612532823032751347335799704869*x^14 - 22982911151946 0414712287398340054262339910173840391365052883789755652220150460120847132485 5387525455121237089427182900348837425717452397567606502432587339063493335218 99975599619910693111772391894198334123224235975702158966025975889*x^13 + 425 1167449102860417605682557582269062328643891986101063790164447568501066388281 7083671619051397999677516644732430950231634364346445730340715448369087696718 20523719962939869299988336933823914482320626610429276999595557594057384713*x ^12 - 2634769415254884935578685134629261396873246071233388299830258283684407 2876185708249044979665212650744995875688959242932243838420517823860588878429 2448997291893491640954677331782979368685632076417137547307030222199889038379 76940*x^11 - 178196131047104477494733878949091986680056821951080835036094383 8004052330411696017910506157765585633940095861000688753523141138483928490467 4511256960034750139170510478764583267207761340591670181326537548133703111264 9106926204*x^10 + 1825000405670995013845885918902187142186986666482440933839 6462521386957836588377301330171147216240982523247505481312286617417272521511 8638399348219471080155689525455946137646839420547370091703312293991788729921 1491191185252*x^9 - 65201626996640512322761674559318066561117950070675294766 3169824762769899024352909587195016688965354038529484926750838814982572946010 1979637110489360349176312329919783316622660007379629280095704481299477431710 45016069129*x^8 - 1437891149083999662420144342263678250208894256538560561654 8933951961391248431401653150798776891480895285823868174684751112400557598552 7985918610201118598268431458892734242196304467884366814923258790382419891488 25558929*x^7 - 1428280930363758251384969101052572662110879466805595758704451 0527911033933582902662199662263051097627055254401259144549052189981714948608 3243967370749726951525986876271444939969618263711803265644040382245363794511 71*x^6 - 1170826372197459055177820600881979710066693446685651498813175990981 0745762172031150515086932467894419392120220600061432329279936873889655682224 7191725072125442393957901078704198243471395495180025340969870794174*x^5 - 11 8223168675776843350634299306552668061864957826207103017499838634433318705119 3832689526795798631026606743575718322278065328528551578753575871762638217620 241416850427234233281589721441720700844787815627946*x^4 - 953048457007008296 1795451881320794184817199918350969024576327248906812630041977334151670173523 3419849726478663631547211301749427543946011643243124123502481796513891248511 161398944690550172434214114*x^3 - 254706791524256177472181318251041912950779 4390935955929617768730635253624759862293118182940797954335902313821207678848 027543595348285081414397619295455292216447729433614628265514361363667915*x^2 + 7114590568532928191072122754665584122789751912529693393245247725975835948 7615527828928204048113*x - 1 x^240 + (-15*y - 36)*x^239 + (499*y + 430)*x^238 + (-6344*y - 983)*x^237 + ( 35389*y - 20411)*x^236 + (-40904*y + 178707)*x^235 + (-424808*y - 438197)*x^ 234 + (1415485*y - 635208)*x^233 + (1438139*y + 2974605)*x^232 + (-5864817*y + 6566480)*x^231 + (-25462020*y - 12961894)*x^230 + (19238389*y - 79956654) *x^229 + (247313433*y - 30224897)*x^228 + (294927621*y + 801098945)*x^227 + (-2353679384*y + 1069498319)*x^226 + (-3266832488*y - 5793469739)*x^225 + (1 2761071756*y - 10152009124)*x^224 + (28891772141*y + 27706877778)*x^223 + (- 56780498004*y + 70327470888)*x^222 + (-156989267296*y - 100643285180)*x^221 + (163182970660*y - 341901790078)*x^220 + (692925090103*y + 282970748175)*x^ 219 + (-520851483678*y + 1249500770581)*x^218 + (-2100987167651*y - 97780636 3155)*x^217 + (2144907137575*y - 3501192827999)*x^216 + (5741131351957*y + 5 368774573391)*x^215 + (-12949633488740*y + 9667592872104)*x^214 + (-18978818 705192*y - 28988343801763)*x^213 + (61143701295650*y - 42854297857883)*x^212 + (99522339968066*y + 118416217970085)*x^211 + (-203990291010201*y + 226088 796680855)*x^210 + (-487486417978576*y - 306059642167156)*x^209 + (371437987 605861*y - 969565907346414)*x^208 + (1761877237395113*y + 250996844693464)*x ^207 + (347587448455796*y + 2909203449118066)*x^206 + (-4262623171412271*y + 1900082482875272)*x^205 + (-5112561845313059*y - 5258998337190094)*x^204 + (4703077156935772*y - 10817923562329066)*x^203 + (19596724151621886*y + 4579 71706716061)*x^202 + (10779811934500297*y + 31310302362591686)*x^201 + (-444 71188376651271*y + 33091705261026148)*x^200 + (-70367728073948453*y - 553681 43890230595)*x^199 + (58047935399898944*y - 125056052810735004)*x^198 + (196 220179915190037*y + 46078797156864550)*x^197 + (-15612945533449050*y + 27845 2806220656846)*x^196 + (-364966710997667886*y + 30164046307811567)*x^195 + ( -76920393658091100*y - 455669527002677921)*x^194 + (569724473209147360*y - 1 04273935104641941)*x^193 + (107554480539021407*y + 761016430421970356)*x^192 + (-1120756441763956820*y + 138805435659787599)*x^191 + (-36744368496876235 9*y - 1741313178847717412)*x^190 + (2626931562224608194*y - 1142827140366519 672)*x^189 + (3001549496003468616*y + 3542726921147289593)*x^188 + (-3816304 655625513057*y + 6563685064488706687)*x^187 + (-12280102244383760786*y - 216 9956083918876046)*x^186 + (-3280308295039992672*y - 20013773166146345265)*x^ 185 + (28534969871679714183*y - 14758677431499660732)*x^184 + (3420538527727 7312731*y + 35129207175233160758)*x^183 + (-35562575528916824663*y + 6232129 2808100809456)*x^182 + (-97526968113689340266*y - 24577168539715006795)*x^18 1 + (-2924482708853224503*y - 135200656059538396115)*x^180 + (16755988046047 3073606*y - 50231770182088582728)*x^179 + (117217186558944665294*y + 1844313 16627662099968)*x^178 + (-175018700423712057769*y + 199325075624692888658)*x ^177 + (-287672838056258651793*y - 130006789216819808906)*x^176 + (433136887 58928043819*y - 370488386653834436323)*x^175 + (435685264104825475131*y - 87 230951613648934063)*x^174 + (260789110179489506909*y + 473346146286012258862 )*x^173 + (-477453708065915165092*y + 475828532275903297714)*x^172 + (-73312 5023480253537968*y - 445824632107486741239)*x^171 + (377925441616168009977*y - 1037951764481934863694)*x^170 + (1401192440853964064557*y + 2712041812199 21501426)*x^169 + (-116817470274758714683*y + 1837817520966021102844)*x^168 + (-2362860273074857968126*y + 103875680474127044027)*x^167 + (-421763202246 558569481*y - 2985437596461812106201)*x^166 + (3701454711020661872373*y - 87 8419497758685431399)*x^165 + (1521006793930665203185*y + 4486769840934475059 679)*x^164 + (-5292413186031800428648*y + 2393646591871321675898)*x^163 + (- 3527560907713404811933*y - 6046342849737077241029)*x^162 + (6659475347960239 461641*y - 4934471883467342725819)*x^161 + (6606218484397706362957*y + 70346 33694928572084799)*x^160 + (-7071251229918632950519*y + 85221454139378375409 88)*x^159 + (-10654172673396879304988*y - 6660938661086516468010)*x^158 + (5 677741559220425296264*y - 12963319200223537566424)*x^157 + (1537868439480061 5926642*y + 3975042669473795569897)*x^156 + (-1409491575820818236069*y + 177 68498236629148702410)*x^155 + (-19928654122136236656860*y + 2108177954625221 499359)*x^154 + (-6549200784773657451762*y - 21617243705895522615660)*x^153 + (22645379524677683996954*y - 11738628703873244299229)*x^152 + (17408053637 884918322314*y + 22982504260819896781381)*x^151 + (-22809630522578701355929* y + 23340226072231874490562)*x^150 + (-29550558164952915082604*y - 224392369 77615542871417)*x^149 + (22094525765620020809639*y - 36386527353264595233550 )*x^148 + (44442209345887020103552*y + 21630493829993114594971)*x^147 + (-20 362621509381561401708*y + 54254830555411448139989)*x^146 + (-659133869795653 69752671*y - 17161940478911028975987)*x^145 + (10842803083053018739937*y - 7 8798826823995559998884)*x^144 + (91671114659094334230114*y + 699010605156960 463896)*x^143 + (13121977610624125288643*y + 103143317388027280663819)*x^142 + (-112336281183122778011108*y + 29666952173920616332098)*x^141 + (-4771339 6391497944676658*y - 119352040791078382516354)*x^140 + (12522214489937288097 8343*y - 66535424263344578690303)*x^139 + (86443391588395703449231*y + 13128 8792905554584140170)*x^138 + (-138308631379146285689943*y + 1087117764446364 01209940)*x^137 + (-134836856528001466894586*y - 145826834678543169365085)*x ^136 + (152261003156819774060466*y - 165525545074570372890946)*x^135 + (2000 19883617103704090631*y + 155735524429003454571137)*x^134 + (-155214006426713 875482591*y + 236255888142978579163439)*x^133 + (-271843213937284128310312*y - 151199785544397594300869)*x^132 + (145501652264843306972923*y - 305326875 506321100258855)*x^131 + (336932852565943631529246*y + 140097781638111061499 104)*x^130 + (-135773050794564515416176*y + 368242715265481945864410)*x^129 + (-400908655930869378612741*y - 131401561676926670933942)*x^128 + (12442649 3872813948801626*y - 435145712814328666799539)*x^127 + (46899879143136708390 7400*y + 112351662733835870233203)*x^126 + (-94381628626117531492779*y + 498 937937395927788353831)*x^125 + (-521540559152841029573809*y - 72188367562634 255595303)*x^124 + (49231480359271694594387*y - 535280543629519838165745)*x^ 123 + (541321200409785903521904*y + 28961946371400127296768)*x^122 + (-12936 229773088822436824*y + 542775176498979507958864)*x^121 - 5428178716207228568 54615*y*x^120 + (-12936229773088822436824*y - 542775176498979507958864)*x^11 9 + (541321200409785903521904*y - 28961946371400127296768)*x^118 + (49231480 359271694594387*y + 535280543629519838165745)*x^117 + (-52154055915284102957 3809*y + 72188367562634255595303)*x^116 + (-94381628626117531492779*y - 4989 37937395927788353831)*x^115 + (468998791431367083907400*y - 1123516627338358 70233203)*x^114 + (124426493872813948801626*y + 435145712814328666799539)*x^ 113 + (-400908655930869378612741*y + 131401561676926670933942)*x^112 + (-135 773050794564515416176*y - 368242715265481945864410)*x^111 + (336932852565943 631529246*y - 140097781638111061499104)*x^110 + (145501652264843306972923*y + 305326875506321100258855)*x^109 + (-271843213937284128310312*y + 151199785 544397594300869)*x^108 + (-155214006426713875482591*y - 23625588814297857916 3439)*x^107 + (200019883617103704090631*y - 155735524429003454571137)*x^106 + (152261003156819774060466*y + 165525545074570372890946)*x^105 + (-13483685 6528001466894586*y + 145826834678543169365085)*x^104 + (-1383086313791462856 89943*y - 108711776444636401209940)*x^103 + (86443391588395703449231*y - 131 288792905554584140170)*x^102 + (125222144899372880978343*y + 665354242633445 78690303)*x^101 + (-47713396391497944676658*y + 119352040791078382516354)*x^ 100 + (-112336281183122778011108*y - 29666952173920616332098)*x^99 + (131219 77610624125288643*y - 103143317388027280663819)*x^98 + (91671114659094334230 114*y - 699010605156960463896)*x^97 + (10842803083053018739937*y + 787988268 23995559998884)*x^96 + (-65913386979565369752671*y + 17161940478911028975987 )*x^95 + (-20362621509381561401708*y - 54254830555411448139989)*x^94 + (4444 2209345887020103552*y - 21630493829993114594971)*x^93 + (2209452576562002080 9639*y + 36386527353264595233550)*x^92 + (-29550558164952915082604*y + 22439 236977615542871417)*x^91 + (-22809630522578701355929*y - 2334022607223187449 0562)*x^90 + (17408053637884918322314*y - 22982504260819896781381)*x^89 + (2 2645379524677683996954*y + 11738628703873244299229)*x^88 + (-654920078477365 7451762*y + 21617243705895522615660)*x^87 + (-19928654122136236656860*y - 21 08177954625221499359)*x^86 + (-1409491575820818236069*y - 177684982366291487 02410)*x^85 + (15378684394800615926642*y - 3975042669473795569897)*x^84 + (5 677741559220425296264*y + 12963319200223537566424)*x^83 + (-1065417267339687 9304988*y + 6660938661086516468010)*x^82 + (-7071251229918632950519*y - 8522 145413937837540988)*x^81 + (6606218484397706362957*y - 703463369492857208479 9)*x^80 + (6659475347960239461641*y + 4934471883467342725819)*x^79 + (-35275 60907713404811933*y + 6046342849737077241029)*x^78 + (-529241318603180042864 8*y - 2393646591871321675898)*x^77 + (1521006793930665203185*y - 44867698409 34475059679)*x^76 + (3701454711020661872373*y + 878419497758685431399)*x^75 + (-421763202246558569481*y + 2985437596461812106201)*x^74 + (-2362860273074 857968126*y - 103875680474127044027)*x^73 + (-116817470274758714683*y - 1837 817520966021102844)*x^72 + (1401192440853964064557*y - 271204181219921501426 )*x^71 + (377925441616168009977*y + 1037951764481934863694)*x^70 + (-7331250 23480253537968*y + 445824632107486741239)*x^69 + (-477453708065915165092*y - 475828532275903297714)*x^68 + (260789110179489506909*y - 473346146286012258 862)*x^67 + (435685264104825475131*y + 87230951613648934063)*x^66 + (4331368 8758928043819*y + 370488386653834436323)*x^65 + (-287672838056258651793*y + 130006789216819808906)*x^64 + (-175018700423712057769*y - 199325075624692888 658)*x^63 + (117217186558944665294*y - 184431316627662099968)*x^62 + (167559 880460473073606*y + 50231770182088582728)*x^61 + (-2924482708853224503*y + 1 35200656059538396115)*x^60 + (-97526968113689340266*y + 24577168539715006795 )*x^59 + (-35562575528916824663*y - 62321292808100809456)*x^58 + (3420538527 7277312731*y - 35129207175233160758)*x^57 + (28534969871679714183*y + 147586 77431499660732)*x^56 + (-3280308295039992672*y + 20013773166146345265)*x^55 + (-12280102244383760786*y + 2169956083918876046)*x^54 + (-38163046556255130 57*y - 6563685064488706687)*x^53 + (3001549496003468616*y - 3542726921147289 593)*x^52 + (2626931562224608194*y + 1142827140366519672)*x^51 + (-367443684 968762359*y + 1741313178847717412)*x^50 + (-1120756441763956820*y - 13880543 5659787599)*x^49 + (107554480539021407*y - 761016430421970356)*x^48 + (56972 4473209147360*y + 104273935104641941)*x^47 + (-76920393658091100*y + 4556695 27002677921)*x^46 + (-364966710997667886*y - 30164046307811567)*x^45 + (-156 12945533449050*y - 278452806220656846)*x^44 + (196220179915190037*y - 460787 97156864550)*x^43 + (58047935399898944*y + 125056052810735004)*x^42 + (-7036 7728073948453*y + 55368143890230595)*x^41 + (-44471188376651271*y - 33091705 261026148)*x^40 + (10779811934500297*y - 31310302362591686)*x^39 + (19596724 151621886*y - 457971706716061)*x^38 + (4703077156935772*y + 1081792356232906 6)*x^37 + (-5112561845313059*y + 5258998337190094)*x^36 + (-4262623171412271 *y - 1900082482875272)*x^35 + (347587448455796*y - 2909203449118066)*x^34 + (1761877237395113*y - 250996844693464)*x^33 + (371437987605861*y + 969565907 346414)*x^32 + (-487486417978576*y + 306059642167156)*x^31 + (-2039902910102 01*y - 226088796680855)*x^30 + (99522339968066*y - 118416217970085)*x^29 + ( 61143701295650*y + 42854297857883)*x^28 + (-18978818705192*y + 2898834380176 3)*x^27 + (-12949633488740*y - 9667592872104)*x^26 + (5741131351957*y - 5368 774573391)*x^25 + (2144907137575*y + 3501192827999)*x^24 + (-2100987167651*y + 977806363155)*x^23 + (-520851483678*y - 1249500770581)*x^22 + (6929250901 03*y - 282970748175)*x^21 + (163182970660*y + 341901790078)*x^20 + (-1569892 67296*y + 100643285180)*x^19 + (-56780498004*y - 70327470888)*x^18 + (288917 72141*y - 27706877778)*x^17 + (12761071756*y + 10152009124)*x^16 + (-3266832 488*y + 5793469739)*x^15 + (-2353679384*y - 1069498319)*x^14 + (294927621*y - 801098945)*x^13 + (247313433*y + 30224897)*x^12 + (19238389*y + 79956654)* x^11 + (-25462020*y + 12961894)*x^10 + (-5864817*y - 6566480)*x^9 + (1438139 *y - 2974605)*x^8 + (1415485*y + 635208)*x^7 + (-424808*y + 438197)*x^6 + (- 40904*y - 178707)*x^5 + (35389*y + 20411)*x^4 + (-6344*y + 983)*x^3 + (499*y - 430)*x^2 + (-15*y + 36)*x - 1 x^3 + (-y - 1)*x^2 + (y - 2)*x + 1 x^6 + (-y - 1)*x^5 + (y - 2)*x^4 + 5*x^3 + (-y - 1)*x^2 + (y - 2)*x + 1 x^15 + (-13*y - 28)*x^14 + (-35*y + 71)*x^13 + (-96*y + 193)*x^12 + (-5*y - 196)*x^11 + (-239*y - 365)*x^10 + (120*y + 1489)*x^9 + (-261*y - 2084)*x^8 + (-261*y + 2345)*x^7 + (120*y - 1609)*x^6 + (-239*y + 604)*x^5 + (-5*y + 201 )*x^4 + (-96*y - 97)*x^3 + (-35*y - 36)*x^2 + (-13*y + 41)*x - 1 x^64 - 2869316*y*x^63 - 14321320456*x^62 + 157634598028*y*x^61 - 20284120752 9344*x^60 - 187341502817748*y*x^59 + 42513677421330536*x^58 + 89659277585427 48*y*x^57 - 581758105735037800*x^56 - 22856296353162116*y*x^55 - 17452945591 56518504*x^54 - 264489521649865972*y*x^53 + 3806496834205999360*x^52 - 74814 8105793479444*y*x^51 + 34464709754552397448*x^50 - 807085220707689700*y*x^49 + 112558678351798157916*x^48 + 885683152130937644*y*x^47 + 3063853398816684 17048*x^46 + 13203419547826420924*y*x^45 + 419863456051485069824*x^44 + 3434 3465258453402972*y*x^43 + 465608689069031605064*x^42 + 80309592889200941068* y*x^41 - 360175722030581287640*x^40 + 110486596140091600940*y*x^39 - 1490512 424563931678536*x^38 + 143957811491089032572*y*x^37 - 3739364774219046032256 *x^36 + 100323919847689168220*y*x^35 - 4985975135633301110936*x^34 + 5481611 3881156185292*y*x^33 - 6135008383051601995834*x^32 - 54816113881156185292*y* x^31 - 4985975135633301110936*x^30 - 100323919847689168220*y*x^29 - 37393647 74219046032256*x^28 - 143957811491089032572*y*x^27 - 1490512424563931678536* x^26 - 110486596140091600940*y*x^25 - 360175722030581287640*x^24 - 803095928 89200941068*y*x^23 + 465608689069031605064*x^22 - 34343465258453402972*y*x^2 1 + 419863456051485069824*x^20 - 13203419547826420924*y*x^19 + 3063853398816 68417048*x^18 - 885683152130937644*y*x^17 + 112558678351798157916*x^16 + 807 085220707689700*y*x^15 + 34464709754552397448*x^14 + 748148105793479444*y*x^ 13 + 3806496834205999360*x^12 + 264489521649865972*y*x^11 - 1745294559156518 504*x^10 + 22856296353162116*y*x^9 - 581758105735037800*x^8 - 89659277585427 48*y*x^7 + 42513677421330536*x^6 + 187341502817748*y*x^5 - 202841207529344*x ^4 - 157634598028*y*x^3 - 14321320456*x^2 + 2869316*y*x + 1 x^21 + (-13*y - 229)*x^20 + (234*y - 100)*x^19 + (-480*y + 8370)*x^18 + (-17 35*y - 16719)*x^17 + (4913*y - 7834)*x^16 + (-2688*y + 51064)*x^15 + (-3960* y - 34104)*x^14 + (1782*y - 32956)*x^13 + (8448*y + 5262)*x^12 + (-6380*y + 97204)*x^11 + (-6380*y - 90824)*x^10 + (8448*y - 13710)*x^9 + (1782*y + 3117 4)*x^8 + (-3960*y + 38064)*x^7 + (-2688*y - 48376)*x^6 + (4913*y + 2921)*x^5 + (-1735*y + 18454)*x^4 + (-480*y - 7890)*x^3 + (234*y - 134)*x^2 + (-13*y + 242)*x - 1 x^6 - 2*y*x^5 + (-y - 7)*x^4 - 4*x^3 + (y - 8)*x^2 + (2*y - 2)*x + 1 x^240 + (-15*y - 36)*x^239 + (499*y + 430)*x^238 + (-6344*y - 983)*x^237 + ( 35389*y - 20411)*x^236 + (-40904*y + 178707)*x^235 + (-424808*y - 438197)*x^ 234 + (1415485*y - 635208)*x^233 + (1438139*y + 2974605)*x^232 + (-5864817*y + 6566480)*x^231 + (-25462020*y - 12961894)*x^230 + (19238389*y - 79956654) *x^229 + (247313433*y - 30224897)*x^228 + (294927621*y + 801098945)*x^227 + (-2353679384*y + 1069498319)*x^226 + (-3266832488*y - 5793469739)*x^225 + (1 2761071756*y - 10152009124)*x^224 + (28891772141*y + 27706877778)*x^223 + (- 56780498004*y + 70327470888)*x^222 + (-156989267296*y - 100643285180)*x^221 + (163182970660*y - 341901790078)*x^220 + (692925090103*y + 282970748175)*x^ 219 + (-520851483678*y + 1249500770581)*x^218 + (-2100987167651*y - 97780636 3155)*x^217 + (2144907137575*y - 3501192827999)*x^216 + (5741131351957*y + 5 368774573391)*x^215 + (-12949633488740*y + 9667592872104)*x^214 + (-18978818 705192*y - 28988343801763)*x^213 + (61143701295650*y - 42854297857883)*x^212 + (99522339968066*y + 118416217970085)*x^211 + (-203990291010201*y + 226088 796680855)*x^210 + (-487486417978576*y - 306059642167156)*x^209 + (371437987 605861*y - 969565907346414)*x^208 + (1761877237395113*y + 250996844693464)*x ^207 + (347587448455796*y + 2909203449118066)*x^206 + (-4262623171412271*y + 1900082482875272)*x^205 + (-5112561845313059*y - 5258998337190094)*x^204 + (4703077156935772*y - 10817923562329066)*x^203 + (19596724151621886*y + 4579 71706716061)*x^202 + (10779811934500297*y + 31310302362591686)*x^201 + (-444 71188376651271*y + 33091705261026148)*x^200 + (-70367728073948453*y - 553681 43890230595)*x^199 + (58047935399898944*y - 125056052810735004)*x^198 + (196 220179915190037*y + 46078797156864550)*x^197 + (-15612945533449050*y + 27845 2806220656846)*x^196 + (-364966710997667886*y + 30164046307811567)*x^195 + ( -76920393658091100*y - 455669527002677921)*x^194 + (569724473209147360*y - 1 04273935104641941)*x^193 + (107554480539021407*y + 761016430421970356)*x^192 + (-1120756441763956820*y + 138805435659787599)*x^191 + (-36744368496876235 9*y - 1741313178847717412)*x^190 + (2626931562224608194*y - 1142827140366519 672)*x^189 + (3001549496003468616*y + 3542726921147289593)*x^188 + (-3816304 655625513057*y + 6563685064488706687)*x^187 + (-12280102244383760786*y - 216 9956083918876046)*x^186 + (-3280308295039992672*y - 20013773166146345265)*x^ 185 + (28534969871679714183*y - 14758677431499660732)*x^184 + (3420538527727 7312731*y + 35129207175233160758)*x^183 + (-35562575528916824663*y + 6232129 2808100809456)*x^182 + (-97526968113689340266*y - 24577168539715006795)*x^18 1 + (-2924482708853224503*y - 135200656059538396115)*x^180 + (16755988046047 3073606*y - 50231770182088582728)*x^179 + (117217186558944665294*y + 1844313 16627662099968)*x^178 + (-175018700423712057769*y + 199325075624692888658)*x ^177 + (-287672838056258651793*y - 130006789216819808906)*x^176 + (433136887 58928043819*y - 370488386653834436323)*x^175 + (435685264104825475131*y - 87 230951613648934063)*x^174 + (260789110179489506909*y + 473346146286012258862 )*x^173 + (-477453708065915165092*y + 475828532275903297714)*x^172 + (-73312 5023480253537968*y - 445824632107486741239)*x^171 + (377925441616168009977*y - 1037951764481934863694)*x^170 + (1401192440853964064557*y + 2712041812199 21501426)*x^169 + (-116817470274758714683*y + 1837817520966021102844)*x^168 + (-2362860273074857968126*y + 103875680474127044027)*x^167 + (-421763202246 558569481*y - 2985437596461812106201)*x^166 + (3701454711020661872373*y - 87 8419497758685431399)*x^165 + (1521006793930665203185*y + 4486769840934475059 679)*x^164 + (-5292413186031800428648*y + 2393646591871321675898)*x^163 + (- 3527560907713404811933*y - 6046342849737077241029)*x^162 + (6659475347960239 461641*y - 4934471883467342725819)*x^161 + (6606218484397706362957*y + 70346 33694928572084799)*x^160 + (-7071251229918632950519*y + 85221454139378375409 88)*x^159 + (-10654172673396879304988*y - 6660938661086516468010)*x^158 + (5 677741559220425296264*y - 12963319200223537566424)*x^157 + (1537868439480061 5926642*y + 3975042669473795569897)*x^156 + (-1409491575820818236069*y + 177 68498236629148702410)*x^155 + (-19928654122136236656860*y + 2108177954625221 499359)*x^154 + (-6549200784773657451762*y - 21617243705895522615660)*x^153 + (22645379524677683996954*y - 11738628703873244299229)*x^152 + (17408053637 884918322314*y + 22982504260819896781381)*x^151 + (-22809630522578701355929* y + 23340226072231874490562)*x^150 + (-29550558164952915082604*y - 224392369 77615542871417)*x^149 + (22094525765620020809639*y - 36386527353264595233550 )*x^148 + (44442209345887020103552*y + 21630493829993114594971)*x^147 + (-20 362621509381561401708*y + 54254830555411448139989)*x^146 + (-659133869795653 69752671*y - 17161940478911028975987)*x^145 + (10842803083053018739937*y - 7 8798826823995559998884)*x^144 + (91671114659094334230114*y + 699010605156960 463896)*x^143 + (13121977610624125288643*y + 103143317388027280663819)*x^142 + (-112336281183122778011108*y + 29666952173920616332098)*x^141 + (-4771339 6391497944676658*y - 119352040791078382516354)*x^140 + (12522214489937288097 8343*y - 66535424263344578690303)*x^139 + (86443391588395703449231*y + 13128 8792905554584140170)*x^138 + (-138308631379146285689943*y + 1087117764446364 01209940)*x^137 + (-134836856528001466894586*y - 145826834678543169365085)*x ^136 + (152261003156819774060466*y - 165525545074570372890946)*x^135 + (2000 19883617103704090631*y + 155735524429003454571137)*x^134 + (-155214006426713 875482591*y + 236255888142978579163439)*x^133 + (-271843213937284128310312*y - 151199785544397594300869)*x^132 + (145501652264843306972923*y - 305326875 506321100258855)*x^131 + (336932852565943631529246*y + 140097781638111061499 104)*x^130 + (-135773050794564515416176*y + 368242715265481945864410)*x^129 + (-400908655930869378612741*y - 131401561676926670933942)*x^128 + (12442649 3872813948801626*y - 435145712814328666799539)*x^127 + (46899879143136708390 7400*y + 112351662733835870233203)*x^126 + (-94381628626117531492779*y + 498 937937395927788353831)*x^125 + (-521540559152841029573809*y - 72188367562634 255595303)*x^124 + (49231480359271694594387*y - 535280543629519838165745)*x^ 123 + (541321200409785903521904*y + 28961946371400127296768)*x^122 + (-12936 229773088822436824*y + 542775176498979507958864)*x^121 - 5428178716207228568 54615*y*x^120 + (-12936229773088822436824*y - 542775176498979507958864)*x^11 9 + (541321200409785903521904*y - 28961946371400127296768)*x^118 + (49231480 359271694594387*y + 535280543629519838165745)*x^117 + (-52154055915284102957 3809*y + 72188367562634255595303)*x^116 + (-94381628626117531492779*y - 4989 37937395927788353831)*x^115 + (468998791431367083907400*y - 1123516627338358 70233203)*x^114 + (124426493872813948801626*y + 435145712814328666799539)*x^ 113 + (-400908655930869378612741*y + 131401561676926670933942)*x^112 + (-135 773050794564515416176*y - 368242715265481945864410)*x^111 + (336932852565943 631529246*y - 140097781638111061499104)*x^110 + (145501652264843306972923*y + 305326875506321100258855)*x^109 + (-271843213937284128310312*y + 151199785 544397594300869)*x^108 + (-155214006426713875482591*y - 23625588814297857916 3439)*x^107 + (200019883617103704090631*y - 155735524429003454571137)*x^106 + (152261003156819774060466*y + 165525545074570372890946)*x^105 + (-13483685 6528001466894586*y + 145826834678543169365085)*x^104 + (-1383086313791462856 89943*y - 108711776444636401209940)*x^103 + (86443391588395703449231*y - 131 288792905554584140170)*x^102 + (125222144899372880978343*y + 665354242633445 78690303)*x^101 + (-47713396391497944676658*y + 119352040791078382516354)*x^ 100 + (-112336281183122778011108*y - 29666952173920616332098)*x^99 + (131219 77610624125288643*y - 103143317388027280663819)*x^98 + (91671114659094334230 114*y - 699010605156960463896)*x^97 + (10842803083053018739937*y + 787988268 23995559998884)*x^96 + (-65913386979565369752671*y + 17161940478911028975987 )*x^95 + (-20362621509381561401708*y - 54254830555411448139989)*x^94 + (4444 2209345887020103552*y - 21630493829993114594971)*x^93 + (2209452576562002080 9639*y + 36386527353264595233550)*x^92 + (-29550558164952915082604*y + 22439 236977615542871417)*x^91 + (-22809630522578701355929*y - 2334022607223187449 0562)*x^90 + (17408053637884918322314*y - 22982504260819896781381)*x^89 + (2 2645379524677683996954*y + 11738628703873244299229)*x^88 + (-654920078477365 7451762*y + 21617243705895522615660)*x^87 + (-19928654122136236656860*y - 21 08177954625221499359)*x^86 + (-1409491575820818236069*y - 177684982366291487 02410)*x^85 + (15378684394800615926642*y - 3975042669473795569897)*x^84 + (5 677741559220425296264*y + 12963319200223537566424)*x^83 + (-1065417267339687 9304988*y + 6660938661086516468010)*x^82 + (-7071251229918632950519*y - 8522 145413937837540988)*x^81 + (6606218484397706362957*y - 703463369492857208479 9)*x^80 + (6659475347960239461641*y + 4934471883467342725819)*x^79 + (-35275 60907713404811933*y + 6046342849737077241029)*x^78 + (-529241318603180042864 8*y - 2393646591871321675898)*x^77 + (1521006793930665203185*y - 44867698409 34475059679)*x^76 + (3701454711020661872373*y + 878419497758685431399)*x^75 + (-421763202246558569481*y + 2985437596461812106201)*x^74 + (-2362860273074 857968126*y - 103875680474127044027)*x^73 + (-116817470274758714683*y - 1837 817520966021102844)*x^72 + (1401192440853964064557*y - 271204181219921501426 )*x^71 + (377925441616168009977*y + 1037951764481934863694)*x^70 + (-7331250 23480253537968*y + 445824632107486741239)*x^69 + (-477453708065915165092*y - 475828532275903297714)*x^68 + (260789110179489506909*y - 473346146286012258 862)*x^67 + (435685264104825475131*y + 87230951613648934063)*x^66 + (4331368 8758928043819*y + 370488386653834436323)*x^65 + (-287672838056258651793*y + 130006789216819808906)*x^64 + (-175018700423712057769*y - 199325075624692888 658)*x^63 + (117217186558944665294*y - 184431316627662099968)*x^62 + (167559 880460473073606*y + 50231770182088582728)*x^61 + (-2924482708853224503*y + 1 35200656059538396115)*x^60 + (-97526968113689340266*y + 24577168539715006795 )*x^59 + (-35562575528916824663*y - 62321292808100809456)*x^58 + (3420538527 7277312731*y - 35129207175233160758)*x^57 + (28534969871679714183*y + 147586 77431499660732)*x^56 + (-3280308295039992672*y + 20013773166146345265)*x^55 + (-12280102244383760786*y + 2169956083918876046)*x^54 + (-38163046556255130 57*y - 6563685064488706687)*x^53 + (3001549496003468616*y - 3542726921147289 593)*x^52 + (2626931562224608194*y + 1142827140366519672)*x^51 + (-367443684 968762359*y + 1741313178847717412)*x^50 + (-1120756441763956820*y - 13880543 5659787599)*x^49 + (107554480539021407*y - 761016430421970356)*x^48 + (56972 4473209147360*y + 104273935104641941)*x^47 + (-76920393658091100*y + 4556695 27002677921)*x^46 + (-364966710997667886*y - 30164046307811567)*x^45 + (-156 12945533449050*y - 278452806220656846)*x^44 + (196220179915190037*y - 460787 97156864550)*x^43 + (58047935399898944*y + 125056052810735004)*x^42 + (-7036 7728073948453*y + 55368143890230595)*x^41 + (-44471188376651271*y - 33091705 261026148)*x^40 + (10779811934500297*y - 31310302362591686)*x^39 + (19596724 151621886*y - 457971706716061)*x^38 + (4703077156935772*y + 1081792356232906 6)*x^37 + (-5112561845313059*y + 5258998337190094)*x^36 + (-4262623171412271 *y - 1900082482875272)*x^35 + (347587448455796*y - 2909203449118066)*x^34 + (1761877237395113*y - 250996844693464)*x^33 + (371437987605861*y + 969565907 346414)*x^32 + (-487486417978576*y + 306059642167156)*x^31 + (-2039902910102 01*y - 226088796680855)*x^30 + (99522339968066*y - 118416217970085)*x^29 + ( 61143701295650*y + 42854297857883)*x^28 + (-18978818705192*y + 2898834380176 3)*x^27 + (-12949633488740*y - 9667592872104)*x^26 + (5741131351957*y - 5368 774573391)*x^25 + (2144907137575*y + 3501192827999)*x^24 + (-2100987167651*y + 977806363155)*x^23 + (-520851483678*y - 1249500770581)*x^22 + (6929250901 03*y - 282970748175)*x^21 + (163182970660*y + 341901790078)*x^20 + (-1569892 67296*y + 100643285180)*x^19 + (-56780498004*y - 70327470888)*x^18 + (288917 72141*y - 27706877778)*x^17 + (12761071756*y + 10152009124)*x^16 + (-3266832 488*y + 5793469739)*x^15 + (-2353679384*y - 1069498319)*x^14 + (294927621*y - 801098945)*x^13 + (247313433*y + 30224897)*x^12 + (19238389*y + 79956654)* x^11 + (-25462020*y + 12961894)*x^10 + (-5864817*y - 6566480)*x^9 + (1438139 *y - 2974605)*x^8 + (1415485*y + 635208)*x^7 + (-424808*y + 438197)*x^6 + (- 40904*y - 178707)*x^5 + (35389*y + 20411)*x^4 + (-6344*y + 983)*x^3 + (499*y - 430)*x^2 + (-15*y + 36)*x - 1 x^6 + (-2*y - 2)*x^5 + (2*y - 4)*x^4 + 14*x^3 + (-2*y - 2)*x^2 + (2*y - 4)*x + 1 x^8 + 9*x^6 - 16*x^4 + 9*x^2 + 1 x^20 + 6*x^19 + 24*x^18 + 46*x^17 + 57*x^16 + 51*x^15 + 37*x^14 + 21*x^13 + 12*x^12 + 3*x^11 - 11*x^10 - 3*x^9 + 15*x^8 + 14*x^7 + 9*x^6 + 15*x^5 + 15*x ^4 + 6*x^3 + 3*x^2 + 3*x + 1 x^20 + 12*x^18 + 6*x^16 - 5*x^14 - 9*x^12 + 17*x^10 - 9*x^8 + 6*x^4 - 3*x^2 + 1 x^24 + 4*x^22 + 8*x^20 + 20*x^18 + 32*x^16 - 12*x^14 - 42*x^12 - 12*x^10 + 3 2*x^8 + 20*x^6 + 8*x^4 + 4*x^2 + 1 x^21 - 7*x^20 + (3*y + 16)*x^19 + (-22*y - 3)*x^18 + (64*y - 46)*x^17 + (-80 *y + 89)*x^16 + (14*y - 133)*x^15 + (57*y + 244)*x^14 + (-56*y - 259)*x^13 + (132*y - 3)*x^12 + (-317*y + 204)*x^11 + (317*y - 113)*x^10 + (-132*y + 129 )*x^9 + (56*y - 315)*x^8 + (-57*y + 301)*x^7 + (-14*y - 119)*x^6 + (80*y + 9 )*x^5 + (-64*y + 18)*x^4 + (22*y - 25)*x^3 + (-3*y + 19)*x^2 - 7*x + 1 x^4 - y*x^3 - 3*x^2 + y*x + 1 x^4 + (-1/4*y + 1/2)*x^3 - 2*x^2 + (1/4*y + 1/2)*x + 1 x^2 - x + 1 Total time spent: 343 pari-2.17.2/src/test/32/prec0000644000175000017500000000142314567450071014043 0ustar billbill+oo +oo I 77 57 128 1 + O(x) 1 + O(3^5) 1 38 +oo 38 64 38 64 38 128 +oo 3 +oo 2 1 1 +oo *** at top-level: padicprec(0,"") *** ^--------------- *** padicprec: incorrect type in padicprec (t_STR). 1 1 2 *** at top-level: padicprec(O(2^2),3) *** ^------------------- *** padicprec: inconsistent moduli in padicprec: 2 != 3 2 3 3 3 4 *** at top-level: localprec(-1) *** ^------------- *** localprec: domain error in localprec: p < 1 *** at top-level: localbitprec(-1) *** ^---------------- *** localbitprec: domain error in localbitprec: p < 1 0 0 *** at top-level: localprec('x) *** ^------------- *** localprec: incorrect type in localprec (t_POL). Total time spent: 2 pari-2.17.2/src/test/32/op0000644000175000017500000000013214567450071013524 0ustar billbill2 3 1 10 2 [2, 3, 1, 10, 2] 3 1 2 2 [2, 2, 2, 10, 2] [3, 3, 1, 10, 1] Total time spent: 0 pari-2.17.2/src/test/32/sumformal0000644000175000017500000000040514557721031015112 0ustar billbill *** at top-level: sumformal(1/n) *** ^-------------- *** sumformal: incorrect type in sumformal [not a t_POL] (t_RFRAC). 0 x 1/2*n^2 + 1/2*n 1/3*n^3 + 1/2*n^2 + 1/6*n 1/2*y*x^2 + (1/2*y + 1)*x (1/2*y^2 + 1/2*y)*x + y Total time spent: 4 pari-2.17.2/src/test/32/lift0000644000175000017500000000143014567450071014046 0ustar billbilllift 1 2 x 3 8/3 x x + 2 1 + 2*x + 3*x^2 + O(x^4) (a)->lift(a,'x) 1 Mod(2, 3) x 3 + O(3^3) 2*3^-1 + 2 + O(3) x Mod(1, 3)*x + Mod(2, 3) Mod(1, 5) + Mod(2, 5)*x + Mod(3, 5)*x^2 + O(x^4) (a)->lift(a,'y) 1 Mod(2, 3) x 3 + O(3^3) 2*3^-1 + 2 + O(3) Mod(x, x^2) Mod(1, 3)*x + Mod(2, 3) Mod(1, 5) + Mod(2, 5)*x + Mod(3, 5)*x^2 + O(x^4) (a)->lift(a,'z) 1 Mod(2, 3) x 3 + O(3^3) 2*3^-1 + 2 + O(3) Mod(x, x^2) Mod(1, 3)*x + Mod(2, 3) Mod(1, 5) + Mod(2, 5)*x + Mod(3, 5)*x^2 + O(x^4) centerlift 1 -1 x 3 -1/3 x x - 1 1 + 2*x - 2*x^2 + O(x^4) liftall 1 2 x 3 8/3 x x + 2 1 + 2*x + 3*x^2 + O(x^4) liftint 1 2 x 3 8/3 Mod(x, x^2) x + 2 1 + 2*x + 3*x^2 + O(x^4) liftpol 1 Mod(2, 3) x 3 + O(3^3) 2*3^-1 + 2 + O(3) x Mod(1, 3)*x + Mod(2, 3) Mod(1, 5) + Mod(2, 5)*x + Mod(3, 5)*x^2 + O(x^4) Total time spent: 0 pari-2.17.2/src/test/32/sqrtn0000644000175000017500000000651614760137411014264 0ustar billbill0.E-38 0.E-12 0.E-12 + 0.E-12*I 0.79370052598409973737585281963615413020 1.1739849967053285099666839718862667420 2 + O(17^100) 1010311380446684911802268122009368691535646607849018888903290947605488591556 607742 125907569 31622776601683793319988935444327185337 3300034791125284639 *** at top-level: sqrtn(Mod(0,3),-2) *** ^------------------ *** sqrtn: impossible inverse in Fl_sqrtn: Mod(0, 3). *** at top-level: sqrtn(O(3),-2) *** ^-------------- *** sqrtn: impossible inverse in ginv: O(3). *** at top-level: sqrtn(0*ffgen((2^64+13)^2),-2) *** ^------------------------------ *** sqrtn: impossible inverse in FpXQ_sqrtn: 0. *** at top-level: sqrtn(0*ffgen(3^2),-2) *** ^---------------------- *** sqrtn: impossible inverse in Flxq_sqrtn: Vecsmall([0]). *** at top-level: sqrtn(0*ffgen(2^2),-2) *** ^---------------------- *** sqrtn: impossible inverse in F2xq_sqrtn: Vecsmall([0]). 9 1.0717734625362931642130063250233420229 0.80901699437494742410229341718281905886 + 0.5877852522924731291687059546390 7276860*I 1 + 3^2 + 2*3^4 + 2*3^5 + 3^6 + O(3^8) 2 + 2*3 + 2*3^2 + 2*3^3 + 2*3^4 + 2*3^5 + 2*3^6 + 2*3^7 + O(3^8) 1 + O(3^2) 1 1 1 *** at top-level: sqrtn(Mod(2,4),3) *** ^----------------- *** sqrtn: impossible inverse in Fl_inv: Mod(2, 4). *** at top-level: sqrtn(Mod(2,4),3,&z) *** ^-------------------- *** sqrtn: impossible inverse in Fl_inv: Mod(2, 4). 1.0000000000000000000000000000000000000 0 0 0 2 0 347761 478116 1 2.1415926535897932384626433832795028842 100000000000000000000 0.E2 1 -1 + w 1 5/4 2 1 2 error("not an n-th power residue in Qp_sqrt: 1 + 2 + O(2^2).") error("not an n-th power residue in Qp_sqrt: 1 + 2 + O(2^3).") error("not an n-th power residue in gsqrt: Mod(2, 11).") error("not a prime number in Fl_nonsquare: 33.") 0.E-5 + 0.E-5*I [3 + O(3^2), 1] [2 + O(2^2), -1] [2 + O(2^3), 1 + 2 + O(2^2)] [2.0000000000000000000000000000000000000, 3.00000000000000000000000000000000 00000] error("not an n-th power residue in gsqrtn: Mod(2, 7).") [0, 0] Mod(2, 21) error("not a prime number in sqrtn [modulus]: 35.") [Mod(99, 101), Mod(100, 101)] error("not an n-th power residue in gsqrtn: Mod(3, 19).") 0.E-38 *** at top-level: sqrtn(Mod(13,112),6) *** ^-------------------- *** sqrtn: not a prime number in sqrtn [modulus]: 112. *** at top-level: sqrtint(1e80) *** ^------------- *** sqrtint: precision too low in truncr (precision loss in truncation). *** at top-level: sqrtint(-1.0) *** ^------------- *** sqrtint: domain error in sqrtint: argument < 0 *** at top-level: sqrtint('x) *** ^----------- *** sqrtint: incorrect type in sqrtint (t_POL). *** at top-level: sqrtnint('x,3) *** ^-------------- *** sqrtnint: incorrect type in sqrtint (t_POL). *** at top-level: sqrtnint(-1.0,3) *** ^---------------- *** sqrtnint: domain error in sqrtnint: argument < 0 *** at top-level: sqrtint(-quadgen(5)) *** ^-------------------- *** sqrtint: domain error in sqrtint: argument < 0 *** at top-level: sqrtnint(-quadgen(5),3) *** ^----------------------- *** sqrtnint: domain error in sqrtnint: argument < 0 Total time spent: 78 pari-2.17.2/src/test/32/ellisogeny0000644000175000017500000000127014760123736015264 0ustar billbill *** at top-level: ellisogenyapply(x,x) *** ^-------------------- *** ellisogenyapply: incorrect type in checkellisog (t_POL). *** at top-level: ellisogenyapply([f,g,h],1) *** ^-------------------------- *** ellisogenyapply: incorrect type in checkellpt (t_INT). 1 [0, 0, 0, Mod(-15*y^2 - 4, 4*y^3 + 4*y + 12), Mod(14*y + 66, 4*y^3 + 4*y + 1 2)] -23 [0, 0, 0, -10561698077959875*a^4 + 21123396155919750*a^3 - 27141876721748250 *a^2 + 16580178643788375*a - 24552962658897750, 565993718198530366379250*a^4 - 1131987436397060732758500*a^3 + 1454513461596357695975750*a^2 - 888519743 397827329596500*a + 1315775760364764668065250] Total time spent: 41 pari-2.17.2/src/test/32/digits0000644000175000017500000000470414676526175014414 0ustar billbill[] [] 0 0 [7, 8, 8, 8, 6, 0, 9, 0, 5, 2, 2, 1, 0, 1, 1, 8, 0, 5, 4, 1, 1, 7, 2, 8, 5, 6, 5, 2, 8, 2, 7, 8, 6, 2, 2, 9, 6, 7, 3, 2, 0, 6, 4, 3, 5, 1, 0, 9, 0, 2, 3 , 0, 0, 4, 7, 7, 0, 2, 7, 8, 9, 3, 0, 6, 6, 4, 0, 6, 2, 5] 1234560123456012345601234560123456012345601234560123456012345601234560123456 012345601234560123456012 1234560123456012345601234560123456012345601234560123456012345601234560123456 012345601234560123456012 3 3 -3 -3 2135987037910203028034168274845001000524289162347811403313193997866717429906 085126638830664810496 0 12 135 1938780 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0] [[0], [0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0 , 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0 , 0, 0, 1, 0, 1, 0, 0, 1, 0, 0]] [[1], [0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 , 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 , 0, 1]] [[], [1]] [16, 21, 21, 21, 19, 27, 43, 45, 45, 39] [1, 0, 3] [232830, 2764705149] 4 1 3 2 [1, 0, 1] 2 [1, 1, 1, 1] 4 [] [] [1] [1, 0, 2] 74565 90144042671290236482932261665 74565 219 13221424875890015231 219 (x)->x+0x1234 (x)->x+0b1011 *** at top-level: binary(I) *** ^--------- *** binary: incorrect type in binary (t_COMPLEX). *** at top-level: digits(2+O(3),2) *** ^---------------- *** digits: incorrect type in digits (t_PADIC). *** at top-level: digits(10,-1) *** ^------------- *** digits: domain error in digits: abs(B) < 2 *** at top-level: digits(10,1) *** ^------------ *** digits: domain error in digits: abs(B) < 2 Total time spent: 63 pari-2.17.2/src/test/32/zetamult0000644000175000017500000003257114676526175015001 0ustar billbill+oo -128 -129 -129 1.2020569031595942853997381615114499908 1 +oo 4.2873531809368449481366386334009956593 1.0040773561979443393786852385086524653*x^4 + 0.9776070866815472455151492988 8030583051*x^3 + 0.92386598479057797349517398328599257419*x^2 + 0.8120553410 0237252484908447742731075772*x + 0.56974741226440286489854563529873403165 360.000000000000000000000000000000000000000000000000000000 1814400.00000000000000000000000000000000000000000000000000 43589145600.0000000000000000000000000000000000000000000000 3201186852864000.00000000000000000000000000000000000000000 562000363888803840000.000000000000000000000000000000000000 201645730563302817792000000.000000000000000000000000000000 132626429906095529318154240000000.000000000000000000000000 147616399519802070423809304821760000000.000000000000000000 261511308733300555880003612050037145600000000.000000000000 702503058876439949271571303122255784968192000000000.000000 [3360, 46830, -6615, 210, -2]~ [48, 2667, -299, 3, 0]~ [480, -13650, 1455, -8, 0]~ [5040, -201915, 25200, -504, 2]~ -1.15153869097617581216300736863878355674280983995679503971 E-7 -0.999984764214906106441682774961407240922101425935387593423*x^4 + 0.0240006 873913037036082477237096633262097335761976727085410*x^3 - 0.0008056502029984 59293651120083162755826511840457120985600712*x^2 + 1.60145850105971121296327 079242063937710914596858620454392 E-5*x - 1.15153869097617581216300736863878 355674280983995679503971 E-7 [1.64493406684822643647241516664602518921894990120679843774, 1.2020569031595 9428539973816151144999076498629234049888179, 2.40411380631918857079947632302 289998152997258468099776359, 1.082323233711138191516003696541167902774750951 91872690768, 1.35290404213892273939500462067645987846843868989840863460, 1.8 9406565899449183515300646894704382985581416585777208845, 3.24696970113341457 454801108962350370832425285575618072305, 1.036927755143369926331365486457034 16805708091950191281197, 1.1334789151328136607970110178859769320890912918456 0422723, 1.26573815274672368610011163539872295998959026222179497220, 1.45884 047272561115503140269825660848805361100690917780271, 1.748493952693942358428 33929254343678014964212394025204847, 2.0738555102867398526627309729140683361 1416183900382562395, 2.68887054784786855029405924757152818417471267109847344 519, 4.14771102057347970532546194582813667222832367800765124790] [1.64493406684822643647241516664602518921894990120679843774, 1.2020569031595 9428539973816151144999076498629234049888179, 1.08232323371113819151600369654 116790277475095191872690768, 0.270580808427784547879000924135291975693687737 979681726921, 0.811742425283353643637002772405875927081063213939045180762, 1 .03692775514336992633136548645703416805708091950191281197, 0.096551159989443 7344656455314289427640320103723436914152526, 0.22881039760335375976874614894 1688791932509342719882160229, 0.71156619755057243209697380608640261209256120 4438339236492] [1.64493406684822643647241516664602518921894990120679843774, 1.2020569031595 9428539973816151144999076498629234049888179, 2.40411380631918857079947632302 289998152997258468099776359, 1.082323233711138191516003696541167902774750951 91872690768, 1.35290404213892273939500462067645987846843868989840863460, 1.8 9406565899449183515300646894704382985581416585777208845, 3.24696970113341457 454801108962350370832425285575618072305, 1.036927755143369926331365486457034 16805708091950191281197, 1.1334789151328136607970110178859769320890912918456 0422723, 1.26573815274672368610011163539872295998959026222179497220, 1.45884 047272561115503140269825660848805361100690917780271, 1.748493952693942358428 33929254343678014964212394025204847, 2.0738555102867398526627309729140683361 1416183900382562395, 2.68887054784786855029405924757152818417471267109847344 519, 4.14771102057347970532546194582813667222832367800765124790] [1.03692775514336992633136548645703416805708091950191281197, 0.0965511599894 437344656455314289427640320103723436914152526, 0.228810397603353759768746148 941688791932509342719882160229, 0.096551159989443734465645531428942764032010 3723436914152526, 0.71156619755057243209697380608640261209256120443833923649 2, 0.228810397603353759768746148941688791932509342719882160229, 0.7115661975 50572432096973806086402612092561204438339236492, 1.0369277551433699263313654 8645703416805708091950191281197] [1.03692775514336992633136548645703416805708091950191281197, 1.1334789151328 1366079701101788597693208909129184560422723, 1.26573815274672368610011163539 872295998959026222179497220, 1.458840472725611155031402698256608488053611006 90917780271, 1.74849395269394235842833929254343678014964212394025204847, 2.0 7385551028673985266273097291406833611416183900382562395, 2.68887054784786855 029405924757152818417471267109847344519, 4.147711020573479705325461945828136 67222832367800765124790] [1.03692775514336992633136548645703416805708091950191281197, 0.0965511599894 437344656455314289427640320103723436914152526, 0.228810397603353759768746148 941688791932509342719882160229, 0.711566197550572432096973806086402612092561 204438339236492] [1.03692775514336992633136548645703416805708091950191281197, 1.1334789151328 1366079701101788597693208909129184560422723, 1.26573815274672368610011163539 872295998959026222179497220, 1.458840472725611155031402698256608488053611006 90917780271, 1.74849395269394235842833929254343678014964212394025204847, 2.0 7385551028673985266273097291406833611416183900382562395, 2.68887054784786855 029405924757152818417471267109847344519, 4.147711020573479705325461945828136 67222832367800765124790] [[1.64493406684822643647241516664602518921894990120679843774, 1.202056903159 59428539973816151144999076498629234049888179, 1.2020569031595942853997381615 1144999076498629234049888179, 1.08232323371113819151600369654116790277475095 191872690768, 0.270580808427784547879000924135291975693687737979681726921, 0 .811742425283353643637002772405875927081063213939045180762, 1.08232323371113 819151600369654116790277475095191872690768, 1.036927755143369926331365486457 03416805708091950191281197, 0.0965511599894437344656455314289427640320103723 436914152526, 0.228810397603353759768746148941688791932509342719882160229, 0 .0965511599894437344656455314289427640320103723436914152526, 0.7115661975505 72432096973806086402612092561204438339236492, 0.2288103976033537597687461489 41688791932509342719882160229, 0.7115661975505724320969738060864026120925612 04438339236492, 1.03692775514336992633136548645703416805708091950191281197], Vecsmall([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])] [[1.64493406684822643647241516664602518921894990120679843774, 1.202056903159 59428539973816151144999076498629234049888179, 2.4041138063191885707994763230 2289998152997258468099776359, 1.08232323371113819151600369654116790277475095 191872690768, 1.35290404213892273939500462067645987846843868989840863460, 1. 89406565899449183515300646894704382985581416585777208845, 3.2469697011334145 7454801108962350370832425285575618072305, 1.03692775514336992633136548645703 416805708091950191281197, 1.133478915132813660797011017885976932089091291845 60422723, 1.26573815274672368610011163539872295998959026222179497220, 1.4588 4047272561115503140269825660848805361100690917780271, 1.74849395269394235842 833929254343678014964212394025204847, 2.073855510286739852662730972914068336 11416183900382562395, 2.6888705478478685502940592475715281841747126710984734 4519, 4.14771102057347970532546194582813667222832367800765124790], Vecsmall( [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])] [[1.64493406684822643647241516664602518921894990120679843774, 1.202056903159 59428539973816151144999076498629234049888179, 1.0823232337111381915160036965 4116790277475095191872690768, 0.27058080842778454787900092413529197569368773 7979681726921, 0.811742425283353643637002772405875927081063213939045180762, 1.03692775514336992633136548645703416805708091950191281197, 0.09655115998944 37344656455314289427640320103723436914152526, 0.2288103976033537597687461489 41688791932509342719882160229, 0.7115661975505724320969738060864026120925612 04438339236492], Vecsmall([1, 2, 4, 5, 6, 8, 9, 10, 12])] [[1.64493406684822643647241516664602518921894990120679843774, 1.202056903159 59428539973816151144999076498629234049888179, 2.4041138063191885707994763230 2289998152997258468099776359, 1.08232323371113819151600369654116790277475095 191872690768, 1.35290404213892273939500462067645987846843868989840863460, 1. 89406565899449183515300646894704382985581416585777208845, 3.2469697011334145 7454801108962350370832425285575618072305, 1.03692775514336992633136548645703 416805708091950191281197, 1.133478915132813660797011017885976932089091291845 60422723, 1.26573815274672368610011163539872295998959026222179497220, 1.4588 4047272561115503140269825660848805361100690917780271, 1.74849395269394235842 833929254343678014964212394025204847, 2.073855510286739852662730972914068336 11416183900382562395, 2.6888705478478685502940592475715281841747126710984734 4519, 4.14771102057347970532546194582813667222832367800765124790], Vecsmall( [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])] [[1.03692775514336992633136548645703416805708091950191281197, 0.096551159989 4437344656455314289427640320103723436914152526, 0.22881039760335375976874614 8941688791932509342719882160229, 0.09655115998944373446564553142894276403201 03723436914152526, 0.7115661975505724320969738060864026120925612044383392364 92, 0.228810397603353759768746148941688791932509342719882160229, 0.711566197 550572432096973806086402612092561204438339236492, 1.036927755143369926331365 48645703416805708091950191281197], Vecsmall([8, 9, 10, 11, 12, 13, 14, 15])] [[1.03692775514336992633136548645703416805708091950191281197, 1.133478915132 81366079701101788597693208909129184560422723, 1.2657381527467236861001116353 9872295998959026222179497220, 1.45884047272561115503140269825660848805361100 690917780271, 1.74849395269394235842833929254343678014964212394025204847, 2. 07385551028673985266273097291406833611416183900382562395, 2.6888705478478685 5029405924757152818417471267109847344519, 4.14771102057347970532546194582813 667222832367800765124790], Vecsmall([8, 9, 10, 11, 12, 13, 14, 15])] [[1.03692775514336992633136548645703416805708091950191281197, 0.096551159989 4437344656455314289427640320103723436914152526, 0.22881039760335375976874614 8941688791932509342719882160229, 0.71156619755057243209697380608640261209256 1204438339236492], Vecsmall([8, 9, 10, 12])] [[1.03692775514336992633136548645703416805708091950191281197, 1.133478915132 81366079701101788597693208909129184560422723, 1.2657381527467236861001116353 9872295998959026222179497220, 1.45884047272561115503140269825660848805361100 690917780271, 1.74849395269394235842833929254343678014964212394025204847, 2. 07385551028673985266273097291406833611416183900382562395, 2.6888705478478685 5029405924757152818417471267109847344519, 4.14771102057347970532546194582813 667222832367800765124790], Vecsmall([8, 9, 10, 11, 12, 13, 14, 15])] -0.25605881150603710456985454427610338162 - 0.051261786085721384557374617462 073362286*I 0.048250857868918017413968344598407239721 + 0.001534207397761626669814489042 0608830932*I -0.0058255504354777196406487442876352524660 - 0.0041315235725142450454289851 114040104503*I -0.69314718055994530941723212145817656807 0.69314718055994530941723212145817656807 -130 -130 0.12858542026992476315022579869859134164634255831679545190786847359366251019 6822128188606526464069017217433043023703740372059863634831356857820132159442 5404233763751019370556030736542558121080918914225531750377221046645326805192 7633331771844407425424459600104217434539675002417539210433694364798296033562 2654293310444734703344652896747434958280377369858736549292748270 Vecsmall([0, 0, 1, 1, 0, 0, 1, 1]) Vecsmall([3, 1, 3, 1]) 89 Vecsmall([0, 0, 1, 1, 0, 0, 1, 1]) Vecsmall([3, 1, 3, 1]) 89 Vecsmall([0, 0, 1, 1, 0, 0, 1, 1]) Vecsmall([3, 1, 3, 1]) 89 Vecsmall([2, 1, 1]) Vecsmall([4]) Vecsmall([2, 1, 1]) Vecsmall([3, 1, 3, 1]) 1 [] *** at top-level: zetamult([1,2]) *** ^--------------- *** zetamult: incorrect type in zetamultconvert (t_VECSMALL). *** at top-level: zetamult("a") *** ^------------- *** zetamult: incorrect type in zetamultconvert (t_STR). *** at top-level: zetamultall(0) *** ^-------------- *** zetamultall: domain error in zetamultall: k < 1 *** at top-level: zetamultall(64) *** ^--------------- *** zetamultall: overflow in zetamultall. *** at top-level: zetamult([0,2,1]) *** ^----------------- *** zetamult: incorrect type in zetamultconvert (t_VECSMALL). *** at top-level: zetamult([0,1,0]) *** ^----------------- *** zetamult: incorrect type in zetamultconvert (t_VECSMALL). *** at top-level: zetamult([0,-1,1]) *** ^------------------ *** zetamult: incorrect type in zetamultconvert (t_VECSMALL). *** at top-level: zetamult([1,-1,1]) *** ^------------------ *** zetamult: incorrect type in zetamultconvert (t_VECSMALL). *** at top-level: zetamult([1,0,1]) *** ^----------------- *** zetamult: incorrect type in zetamultconvert (t_VECSMALL). *** at top-level: polylogmult([2],[]) *** ^------------------- *** polylogmult: incorrect type in polylogmult [#s != #z] (t_VEC). *** at top-level: polylogmult([1],[1]) *** ^-------------------- *** polylogmult: incorrect type in polylogmult [divergent] (t_VECSMALL). *** at top-level: polylogmult(1,[],-1) *** ^-------------------- *** polylogmult: incorrect type in polylogmult (t_INT). Total time spent: 98 pari-2.17.2/src/test/32/lfunartin0000644000175000017500000000000014567450071015102 0ustar billbillpari-2.17.2/src/test/32/bern0000644000175000017500000000725114676526175014057 0ustar billbill *** Warning: new stack size = 44000000 (41.962 Mbytes). -1/2 1/6 0 -1/30 0 1/42 0 -1/30 0 5/66 0 -691/2730 0 7/6 0 -3617/510 0 43867/798 0 -174611/330 1 x - 1/2 x^2 - x + 1/6 x^3 - 3/2*x^2 + 1/2*x x^4 - 2*x^3 + x^2 - 1/30 x^5 - 5/2*x^4 + 5/3*x^3 - 1/6*x 1 1/2 1/6 0 -1/30 0 [1, 1/6, -1/30, 1/42, -1/30, 5/66, -691/2730, 7/6, -3617/510, 43867/798, -17 4611/330, 854513/138, -236364091/2730, 8553103/6, -23749461029/870, 86158412 76005/14322, -7709321041217/510, 2577687858367/6, -26315271553053477373/1919 190, 2929993913841559/6, -261082718496449122051/13530, 152009764391807080269 1/1806, -27833269579301024235023/690, 596451111593912163277961/282, -5609403 368997817686249127547/46410, 495057205241079648212477525/66, -80116571813548 9957347924991853/1590, 29149963634884862421418123812691/798, -24793929293132 26753685415739663229/870, 84483613348880041862046775994036021/354, -12152331 40483755572040304994079820246041491/56786730] 601580873.90064236838430386817483591677 3.7508755436454409098345241010481418931 E218 -4.9971936871087436660009945707007258731 E1822 -104203435297641800915507592803138769896333127491490532929531166632958450572 7519290260805334565313825687466304288058398986061317055037227125673791728358 1349758270676379026329737258680437265409027141273365440974202940525915613066 3560412599913831518338400385290760913773448329773518728092595019422753511174 189569/131070 0.E-11 601580873.90064236838430386817483591677 0.E-31 1 0 -1 [1, -1, 5, -61, 1385, -50521, 2702765, -199360981, 19391512145, -24048796754 41, 370371188237525, -69348874393137901, 15514534163557086905, -408707250929 3123892361, 1252259641403629865468285, -441543893249023104553682821, 1775193 91579539289436664789665, -80723299235887898062168247453281, 4122206033951770 2122347079671259045, -23489580527043108252017828576198947741, 14851150718114 980017877156781405826684425, -10364622733519612119397957304745185976310201, 7947579422597592703608040510088070619519273805, -666753751668554497743502847 4773748197524107684661, 6096278645568542158691685742876843153976539044435185 , -6053285248188621896314383785111649088103498225146815121, 6506162486684608 847715870634080822983483644236765385576565, -7546659939008739098061432565889 736744212240024711699858645581, 94203218964202412042022862376905832272093888 52599646009394905945, -12622019251806218719903409237287489255482341061191825 594069964920041, 18108911496579230496545807741652158688733487349236314106008 095454231325] 1 -1 5 -61 1385 -50521 2702765 -199360981 19391512145 -2404879675441 370371188237525 1 x - 1/2 x^2 - x x^3 - 3/2*x^2 + 1/4 x^4 - 2*x^3 + x x^5 - 5/2*x^4 + 5/2*x^2 - 1/2 1 1 x + 1 x^2 + 4*x + 1 x^3 + 11*x^2 + 11*x + 1 x^4 + 26*x^3 + 66*x^2 + 26*x + 1 8553103/6 *** at top-level: bernfrac(-1) *** ^------------ *** bernfrac: domain error in bernfrac: index < 0 *** at top-level: bernreal(-1) *** ^------------ *** bernreal: domain error in bernreal: index < 0 *** at top-level: bernpol(-1) *** ^----------- *** bernpol: domain error in bernpol: index < 0 *** at top-level: bernpol(-1,1) *** ^------------- *** bernpol: domain error in bernpol: index < 0 *** at top-level: eulerfrac(-1) *** ^------------- *** eulerfrac: domain error in eulerfrac: index < 0 *** at top-level: eulerreal(-1) *** ^------------- *** eulerreal: domain error in eulerreal: index < 0 *** at top-level: eulerpol(-1) *** ^------------ *** eulerpol: domain error in eulerpol: index < 0 *** at top-level: eulerianpol(-1) *** ^--------------- *** eulerianpol: domain error in eulerianpol: index < 0 Total time spent: 8758 pari-2.17.2/src/test/32/bnf0000644000175000017500000000452214676526175013674 0ustar billbill *** Warning: new stack size = 108000000 (102.997 Mbytes). [85997496, [42998748, 2], [[408188227, 99620635; 0, 1], [2, 1; 0, 1]]] 12.340047278667903334059769086970462209 4.1894250945222025884896456921310573069 *** bnfinit: Warning: nonmonic polynomial in bnfinit, using polredbest. [1, [], []] *** bnfinit: Warning: nonmonic polynomial in bnfinit, using polredbest. [1, [], []] [2, -1] 512 [54898, [54898], [[3, 1; 0, 1]]] [26] [1, [], []] [3, 3] [2, 0]~ 388 [2 0] [0 1] [960, 24, 2] *** bnfisprincipal: Warning: precision too low for generators, not given. [[]~, [162750437823065137172097975916686005389067937291604243871415620233030 69241961, 399251576746385937680752111531458737834259745833777339037944802718 1914746015, -402630887520085140394007801991356622609650925416836073597848182 049497266399, -3875196415920480829978279850511752676499384722019721458357455 29259111353576, -52461316448281616990887375052684957466837666099934108964075 9880949016596504]~] [[[[[[1, 0, 0, 0, 0; 0, 1, 0, 0, 0; 0, 0, 1, 0, 0; 0, 0, 0, 1, 0; 0, 0, 0, 0 , 1], [0]], [1, []], [matrix(0,2), matrix(0,2)], [[], [[], Vecsmall([])]], [ ]], []]], [[[[[2, 0, 0, 0, 0; 0, 1, 0, 0, 0; 0, 0, 1, 0, 0; 0, 0, 0, 1, 0; 0 , 0, 0, 0, 1], [0]], [1, []], [Mat([[2, [0, 0, 1, -1, 0]~, 3, 1, [0, -80, 60 , -10, -60; 0, 0, -100, 0, -20; 0, 0, 0, -10, -100; 0, 2, -2, 0, 2; 1, 0, 0, -10, 0]], 1]), matrix(0,2)], [[], [[], Vecsmall([])]], []], [[]]]]] [[[5, 1, [2, 2; 5, 2; 39821, 1; 161141, 1]]], [[]], []] [[[0, 0, 0]], [[10, 0, [-1, 1; 2, 5; 5, 4; 39821, 2; 161141, 2]]], []] [[[[Vecsmall([]), Vecsmall([])], 0, 0, 0]], [[[Vecsmall([50]), Vecsmall([1]) ], 0, 0, 0]], [], [[[Vecsmall([50]), Vecsmall([2])], 0, 0, 0], [[Vecsmall([5 6]), Vecsmall([1])], 0, 0, 0]]] [matrix(0,2)] [Mat([[2, [-1, 0, 1, 0, 0]~, 1, 2, [0, -80, -20, 0, 0; 0, -1, -100, -10, -12 0; 1, 0, -1, -20, -100; 0, 2, 0, 0, 0; 1, 1, -1, -10, 0]], 1]), Mat([[2, [0, 0, 1, -1, 0]~, 3, 1, [0, -80, 60, -10, -60; 0, 0, -100, 0, -20; 0, 0, 0, -1 0, -100; 0, 2, -2, 0, 2; 1, 0, 0, -10, 0]], 2])] 1 [[4]~, [229/2401, -2/2401]~] [0, -2, 0]~ [728, 2] [] [] [2] [] *** bnfisprincipal: Warning: precision too low for generators, not given. 18 [120, 4, 4, 2] 112850 57283006 6991.0621514282156507401147284476429807 [3655264, 5209.9895739084984458417625206539859558] 13118744 38231520 23095900 352 192 [2] [1, 1] [1, 1] [2, 2] Total time spent: 14996 pari-2.17.2/src/test/32/resultant0000644000175000017500000007662514732363470015153 0ustar billbill *** Warning: new stack size = 20000000 (19.073 Mbytes). 1127614608 911045 -23334121 15152875237197769342976 1 4789697380021054650345938381924768779764502171151476021251465336909773783338 1483478046719619493978767437813786102680708004930493639232124484712989030743 77376 5591778626126198515789740127923726924138993122908566507963011388676468961202 4477425313882678703984217553283789132475364222241284814412314235455434422980 7710892411505927222662178875831559611191917768447356156048451344207870859235 3421574869121809933510172523951949560305425573780083942051414584453903225103 9150588607156375894233737091156899560058104991022009737098022791771063870332 4543754376917999871790501326547853054436444495861161564399190140572883960196 4316196975817429852098537493490087741730840438498474174124950599821563462379 4776250318165223172258299094200163699119837367865451816040219464272808536682 6366448478399563694093511562444580982947874089384832363620244514399470126325 1221138634876570856880659380036429623915483515843179086549287327024998004564 7976338198194174093893290033883921204928495263532870000949040615012556044932 1818817854986256664488406380789052297112100244473983193254140610618060591371 899564340082899114785688720906351258905787053899776 7081072488122549108437740087055070486542322805098742006332199056679193928966 4483785295568554162322036400017122263928267064345800987077874888846659771496 6170549511731996859294513678297798592859196096017665960363670523570420377721 2919429331810768214726379757777338665118630273090090442002357392565485086331 5412450577546522243130333620009107379345899855572005517250317530197793851722 3355902478870693674755098498729934799138680215415329581514280083638477701043 9833756129716245879910591555562933614970015160148305939648207485535526079234 0506699237254741161806485754160707356885468112747818240990343439929195771261 5718119731260544392168170080797529909765466194544434766073431138630521097535 7468986434676998993972786577010278592120332643280493735615754118765736720057 2393565271488265393041765173848995399894723709392064991834838703664591278597 3082437298288444379811881610029611376601722270737965832251382983968232233649 8871844617255503719150928022965927019986189521620111495073311653079160054784 6857440559795860180426346941115122603046544514726275045580655957003854337394 2366607422738440023830359041009316801704138433518791880556684554000725519633 6314221737402120724621182545795068118781015520862409165116892715165782201744 7373528760095126876619409888737755809138526698545586130093257520346765161706 3668856674264264360780430404097555123190894892970707035925992771214318693453 9933063048724159581078642517219830228441155730464252333929338601304473477379 9924164123779424453250220315240908440937220701876898151966131532288459419998 7193319301791449277695747801099373571458888429427291702061589949699722004575 4707271425056836723915364693803883154598841808528064617757070166253079521282 9330993749058818913084870487521920089024720415354689556927595116643657782190 7772163668281509363539079928183803467678757273373526894367221203626621799795 0834794280858064768554880652430560684135485447762704940367795197161950331922 1933358870993764673870859837952485667866798702804457244640778314935644379077 1781507677136287186820379853171767323733496951804295617087357625661051104152 1796342712986360278714707030680719176226964227465901389213818171046492873465 0022790780563242373313610025898026386690016904386357791379547299812905227390 1289797056874223293654886944596148419408207352315947914652557188420178927934 2848619416825409009261520189608713137382207964171283558993905022859982486695 9083539842491853405079547629485109169490879476146913423588991526498785270327 3968511118988030085179508566878601698165562240004498473335561372165388144302 5299351926733300122236311522899635357333042443410986368545768414279154922277 9119056516432750446537012271038703954019716627215359282310427886580436806649 1128763133722567880219150198570570334214903477999954881887377115447377529450 4743238205391224700586995860603351466477628176669368096677069674459366626343 1922851858053123966451232560199488110901933493373773342297093283394419388248 4588916794714441254931339361853072424034331084764085081987592855543881808243 1779116507645535321440983529543254866843835344498356598259597110076846725320 6851381772957660420342635656117691678289746109819594274521914714099658185017 8103384766865875768775851148845968289169127685348378811992123602296633104373 2805377772394628665071343459476385073839007177030802143173978958766607853438 1299576637513893400073478172504247752287917016974831919723343256352815430862 2756735538729480299222282240438655236155081637699288961373884981739501718182 2681375497299984831021291189018514228948558064909058423273859290080459595571 1759917019292934458035585962564362223881131293139396977742617328161512636776 1481197065944479079708702464472102740839784622024302517281715139380530650311 1915971888668147117514765329906797514964395684832725088547469451338928840681 2720007091412810257156421902095403437335707368255329889993567282476060201844 5771396723720966942646908853851819209514039160674238448209530171041506333081 6987469227749752421380683026987025045039827341868747252476484201784372446710 3510248767574924856801643658855141372196574234941500177109628589376464368340 2999855256027646684276215612404965044584115542842898614670574653437772506535 4923273222262319450335041587329691932221764773887410781545905870741527518830 0856696173015051150711714497101540120133632210837848926748871140267926449098 1423419401755524300390263874468295460307895598999553133968897373983301216878 2734049667608533709411627027619810284143582046196764517591998490057580029106 3609272592147333011404236522621245214993427142890298259090018689952508140536 9654638037034014821665971679425142385118234439462497731669309557480650496918 1834649980677855020436832515946267480139639823701397028549118270169170519415 6721794171223686532838514733056067604528123664171806646382399462634890916813 6669485840561432308522405899924251087786067664162652793044413599537424129707 5477186898973633516352568883257904332028806586709401569864515982688222129153 1567052855728262995530434353630134178070106956944279797548165372439216825076 8326715576786303582598430095125742864236163720296213905787039885884463657834 4643437508267891744779261877500947228066699509369586576615123985367219743858 6658022062041430002005181878216355419666743135504759692658299056669357259645 1140384349942471935622171122262819380938871819723106690671480887238746092900 8259392457845570085120138974098112147614179833839988811199774487498092129908 2525330985586942998714786716070693999685611141806930181168204974764634546790 2491116660085873519752267226746027234992210672340901561111569016509087980484 7241366934438873990966498559499978863196895478498708930733440029703211754971 3174338633455354574979245770026845320172157118052425714203442756762690452556 2195168177038659757872091439804829007952032160043794866268382905222485457033 4877085046605283955920544774598658688901188561694172099986871239644906361688 0166806589820637842653846370311841209424194808154992103008317976618840646505 3524843776927351496372745683004763216358973783229858596853568141313750965802 6732704253827791291256677915251801050186660146187981397142021248163932831949 1242424936332974106235910726775448936949225963230406509254485317395735192765 9629100658168052496684342007876499412743472614751505477517198117059603151774 0513333347014771131213527388744277817255738469560576073881746517093241538950 8379623995721601203434646863118546318466543153575568871197413866654425349795 9709665081383739157130696886846685180184094150972054886673926466898476160056 9251865200870473249492728358926161261942133179621059876513623829755485965508 1765991185475814355042047437792982556193134305138749561348141122718465434028 5955347577189501961066057321746605591478524411065032570202848093134945388063 1469805925510862902366653958969425851152732736769061502994730346813692391400 2188444260504305088747166891225921799545810287134453936174360046753896543846 4725311018589188158298923975056694464632127746952940324604386896534946901154 0189748233921118167859285574717815593009931414748460169210424421915763646667 2549643791464812661184224613907766599594347549012695657501957708976598982379 6246315465707511680970636654737842632945349283341207033490434420327941078448 1247500527894528017587459786622669024443518026949815548731423263169447248228 5110467004911800020475713052104208484239152280018530719982927713299542152131 6714018358725068038634436774574546773146283899186292132944165251525364117406 2333682077664235142911764750699483904374984050720750763989372219539833457960 7517904946980952462925255681650144231984545917747245637003964519102283728734 7801223416232398530453943213234148790697908440512084299095779197332999945341 4964437542186365784691171021464796820401539232838986619037169900580166453697 8875543972648384797560654661388477062010340611513997845689183412371725641192 7259435812034642758959741241517961837062742047554891249269300463738657711558 2873355887128229794245851803952135238397923971740033612324297035200484275438 9156423664686366531825242597376576860994929676476159165395192353567061116835 0879052026395527993330789894200638408494686144201609307220354927475939107543 4100442246166647741053132902356715119673330523458821912870829882436969397956 9406895726081967239095445456258787542857469923106451553636440562462133562360 2668811067192149078795792377466748973463935910225355341714595027831656267131 7448279182843337911131360717637361214496493274000813932176510723999645466023 2577690480408703033440600514220628547543775356283381461661090490710822064909 4442349542870358299272174730711563333091694493018076280359800542459534086476 1753773084515412810070994263488287449786031849963340685709770929949412357769 8595467102933787819050340231630643521983014085233294591129365647969335691870 1645312144680039661515859963988461311015875682686126364930986339192596055528 5415821644430946059242051021689727062158285718368764970142254220221251016570 1562643814866019675250331401163912499653408827720323147052395354630909040950 2449569343309008357721192162211813923928897216896982491145981783817245900369 5174601436757895126770570726969854492290667489978001725658920553817006873736 9361312619106558444263836067946213531312792247596380264510333469355965494293 8057756424419773526095629957221330300887874765988164844737994868164641605222 2825624132991984850324866986619296607978229622915429194579009932988226000946 2799716898319535999601514182213198784020927602509705335937317436616464565386 2872053875185499951244257832174070631688990682874482631471691339296616648363 3357285120715643816652078133798755984077111980231423933018801082978392585421 0557410505624607436448090236794246925372257552335205668157924552625077577745 1444994285443412758408944565156472565466791294345215703318051430639461056798 9104112885134043465540265984546300434414876490392033240018221222923160975692 3574118451325235191746732118645012230660740739534589705361993281591810042848 1386376501091030428196191317149726249705003607276293632768455631898002411316 8723568666921731614366149245523567264036839088882693159534231662113318927190 2700597763458658138616263432657882123932584966891493766304566230992548511870 1578565808767928420814686276337773212621085152030353396508799832670048785694 9458195423731556131061003012038999565838203945938486770903260446305772890830 7066407095099849010110311279170801482672160151298019450205523688931455046837 2696701818054864809290668621005085842719448633255369262839048473607324076854 3876512651160078271451580705114404951011889183775018819798848974826562003664 6661732798500898437911439686901081863261839430043923237046283466602427871304 8506953093641642163367712127257564040734310940434747428181583577390637815785 0568728380279883244330109231305923546694823757987289677640095975011241184318 9915958392805871916668742980025522360460089258695511886998639786040952838129 9175637805687931816598611425185730113293288911861332695586714572145658115029 9844338849992973326251312720024106411331530108183020506081531934467942310766 5480466436597036298814762723036190616555337378880978653796168575503594499080 4938901966476145425173757988475188344145289435972780305559861056903328353435 7097324796734880384585281130228000670331841246489779777755289555189750148212 2460528569662635491485226214600657466593819032606384448441494814219184451373 2970238465927788712086864971958121372221766814952929308218481647008620534821 4870259320816045694040663489812592473817436697294095899807395498397055191786 4246700427676626086795906762335651942030658186154911718028023640965476401541 6331290138619972853394139193068857312592167829698870990849405149987021278969 3611178142790638697562338466404270499149409798871543973677872220822218818707 9274126492516822409042659368169703465936982972778620219021231830098682652554 0129952966507080659132966853812023584303362666270317227465529934100811015105 8868990725432564987605223395940547374046157871476155638971225706634706527197 2100070728017924350626608177098973079265381463675975950527323756525988663565 2792980895669484248299410038263537660623017805311298685765900580697924240570 4587261148427817001651793337528843665500553095898064074090246369336456936473 4373803950522485651344423864279448523115897237705822685322793258751461529039 8924994348239102187147135789338076432776608620822393601589765157207326701598 4974900600705558869601187220120358321975167707693820494316713534023111843805 9283173364786844421849556149175619273166387467854407493491717116722424505053 1728410586881113103309453413145528185963208374232941772791717539803691080384 2397504701077839217768067902076125594575708755459937027409745203440094884479 5140234505133742864665356178364606835448830939783260650214862842555014663195 6415594335179574317671856504206447373591062916029471992300116963386628460524 2847904416596141934741828146379809581664158905733011925952574996015569831756 9703063616018931599351925057216994635704120606881418401365121636867122399809 2774750147634980569429662641208390283422787696005105225767492395514821395148 2324024851334114743756051875991639774324459647227599873088565986456465788550 2092343371481239343113881272770926693174789149230168249996032172137615301356 4980996965817634459665187513080922525605201604845857286564525064751439629278 3000725290349331142295275597309690835948790615844571089136616960068195339705 6194453861378417806817597789190149182835100252960383932417019745974444767099 0624786637634290275002442959915995647243356991025785049598063354253091991467 2884054539571691939828506354835147188797863438910609128541007455256683557131 0562342964055240007307201315671721394884726343064451522335113780730215996618 7001991699723165212904103307749537867071104955163912366676956060671585948075 8856561990076412149919627753695230757225285324756951063606903236791929080189 3973661505448117852920548942305793298953857044793936910063454602785182803429 6064134170981414962838068243888581694538254933156788556169768331700594145992 0829625229407628504478197743358306906062714062770191995932116159202455454698 1833772637944551971708296532225251958444281762416016999602533345461193450313 0648189438004061438499414165320145166394394137001741494601734265729049916536 8786615510481765352709341172007999297661820452214994434444847483883226297140 1401674898781247484082998956186471711709567755084249521203388115453739850984 8201380092084758372275724538800301564602934678377853362331910728064061151092 9552063475242103758900477732246484302256511528132759160221241392285002767024 3669353741641622336731841455767829054402291230797389101828234070416279585998 4177436328311159747118290973201619007228947454290436250321638835917076230562 5908006734101378403247160809171990515159263712996771840506632764382172811486 1045805889911666828084633587319003655886973250316525236916645981137835447238 4293626020194196895754257039489866614124700604916502009470350933899248574263 2433831333725836823737934116481556444659294843962623404784927612972830908818 7995066167536899612315082598662649426372702024801212726876754386409528327484 0407885195827599897275621697816182411963589270076348733404107791216013908821 3312645242645005779272501822320994675104938946391158040143587955328884418481 8552189233778681399753847414887764033120998535989960058575892967832407772128 1486370558522744063535928001892364461867715745222791284527793212818188214212 5151430384435843528957786512789031489302505302683680671161908878734972360980 0169606010403993591690593687152871349591312158380146505938090653290650464244 2393715616059833231533447758770144994797243194913401125749757861887967071474 0668243840880239975410140487167665497226423304105183321456942712666755366048 4513930715943788103872965224019765145227252865954271143477545308093565624554 2038273819668351030692714185064237433409989989843369326821584267652829971183 1047748516522526723332327680235436145444057502299686617058124219054013357604 2058644381474119584378752212603826077589535634202050954327560432207418222041 2946673374895032454261423042963903275402019846909997207392220695906575618068 1181429287813762522813907938908102094558672580674959851503384043646005266215 3556850616430494449519453861414586052518051253449165323698938124942367235337 0262664752264544375885466166799033815620881800700646346140590254007360813756 6106251312723308725668659882494606260328217635132797924501855990617961457672 1019271798366689077713053020708507055485816592439719097528763798162719234761 5768842729973762210377565701985356010572319029207706749810973378297162497315 2429257893364899813089138087002591377752115806621791689735535324942239281389 7707658659115297091177669024303780469123021110257015997626532926986838094760 0251473914561276418783777747329910981979578981148252984143759266894331122042 9041445345958715283155660279310587345830247860448837525261315766198993992499 5959135476557955828889140898705619068986297758402572687925341338893322191018 4951574210527100911563052359377857775455187162182640677583563839405015418626 6271003135442406476904292013486173064280165102275860877358055961680377018117 9407258058194062595343490331433128277476287025562338780716296607863734421964 6398504753473310937624280680487514461999171822917905958714467444259409540096 5125686461106746954329208107230838711949699315085161624573548764472629924000 9388826927578163869644055897801290539733180405120167542888739695296935787527 2277231024000866999422003496826219681773340717008049883536929150209759419719 2476724495228873880421184843573662693488497521949703654293617023731876188021 8161101036337107718919946052334638989394796774173354409309562498787726965123 8501379728687520420137037318041140155292864410431179358106654346624235823545 3064016217648136175289259908242738578378187682097303323420320267640427880197 0546103037587443506906154893888189366292745693373465818296838130553615764337 2012379056702209339738530032711295715914291111593610024223834654681234489950 2995984070241882647259917195419249566653665169904729139657919194431471824505 6330324626778144078219820414708337050772319628837159448612020902643054481443 7785951186072214743077777545529851432900878096517420251324683967383472320646 7072171826870056133206946006956594590822413225672457103287494913610929672857 2802979513803760415959689167004444098745469704235693893440234078348358992130 2902412804083486203809602146349295979585966691897800454007145734217841442504 2509656059394416722763927807238311390512732351899114617488579954637344893472 6956418040020563753576439361112293250812538205606862069824031389592220753938 3931980444000396952790300025110413488020461314044867096400482555611861766557 8779872633208790282853041828436599000821439615909297936909400476874231409386 1107957033048878824727553773211614689966672780402203443704886999018746632918 4578570059506705179295259119648586493455744160376834283354774861549013613756 8914104974148435789675196156799768181676487349484914162264963803701991647308 7077370046772797817386919223496396655554669074903108105861101273892479122450 4487000094244471654652318170723070150479698387577348165943027364806795695771 1605973865900671088466048319535078791374564546245300366331708247635343933398 1970452195592950156793361600483926819755275149212838754795843185318110832468 1382112309145641859606129754154071672948878109857709847136184953440514957541 3641496697051930106770483801168708463106269498367706651154782577811514002639 5106563888263605829321212608718331459495599039042081814718848457860199057649 5346982843071231821350857965681984563335821957754569468382305016184024887604 8160723684261393716356258451730935748281676054966556038316792751070826540054 2473315712042588604514882868227176108332833877184166366265303737221912013662 4512167901067209682554392111071155499467651327936730515479173229263731514370 3330182513953368428655392818025057917570653783124434362274261551843983160477 7351162406242450929672186628419950329891867814208035883609977838886238833276 5330774679847630559105909002838233097431528046724187446177909715044255520881 8889404837062703651637318360772404220635983462926485432718138685237631857455 0598465166755132919094585655974966874524784130599703711634113352005177406926 9603316645497284293848590370977640427328887687375912505822778917514360380115 5682283488759427844250167972992511302878057532531484502529732162662116955639 7406173957119233848745104829248262313597011029557702426889396863083570940205 7509537898825756241704038780955282562441114537127841752209332467489719207566 1744264901601182958290811929305241680377823312435028072780502748828361181784 5922938685656775729737638617283841787967835602522574138712851435180707114732 7070864077169181369700790505644456673957432875813509347521540262444684384812 1628162757064794714790594967511664494982986431532091869678632267880119090181 3358285913239640118632956526316790292934199787619720599635756782126973040030 8849995749515739684821341699562520787829013184888043096654760631188226253631 8585742707987188915896804232114765200530074024419150347592072019161120869323 4748482955558033228065455570160118248780022998383870238441158071327622059726 4610703982594367716830470741988537826072641367377235148800000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000 6424194875218376701463113579276658235425909119319864401234806441094021127054 1375266956365232048220109345396592726319742460454879981062694340660155949810 0158596374952141691378161159043297105952129759212696862483103011107449914024 0094518530978010978915317583738701606420973822157506086835007914978002982268 5532998094510470979840507359084614024762021412168744501835585051640684574287 1078953105601656693485703971643934048397703383418980257911777900546820380805 4170495763626051350369423653552681147090272505727727116438873040672296148742 3911117072924868470426691405643972081983053358547587471903955838256977365810 7214608397690540588379230455866567931949997177575434025237758134753480761133 28381591924887486184484485922972282971065248302182867907169925597 5666658170985421428568776023708028963706995520080659357168692551584779660342 8845370048005616413297301438788684948250159498753561703887501771998471467047 0572365820592328518742718645259795706159687456606230246406028480921554259928 5340467680010491452771885463865912263236353978700007220144125780098160197203 2031201691364593717086444953556041504587784874247426094277154056141748358043 3092986242590451866923730053842550530645976252654457481607935574398512975433 5958612625992295737052292037154444584538830158625476522119502606425844311713 7568524432625716058524905583126467948164530845151327970412952427667083285696 1654438323710321253566705831201432914714319143016623815060881384835591899090 2471009192031544760372901915755330058532299670144074706793928555485848393159 1828050109715302094839971124460319775966476623121401249450851220197356866122 8030237845317849716956219074680650465917640347731788333583546848508416734340 3898157780073751187903396667377222823979111370825580014201215182931295599914 4605197631998749857550713081687598984457233392295649568376711423487711804910 2828628167987521424766213383686969797280488819530652810103906518166447659272 3960381547488477643959422660036664159679049695106798176262658899212922595345 2454875526563586504128373884988804533889790263675488058966242204666913885135 4761573671014826411947138132267980759790003000518532492673507771928777973799 4462263269300516966805110216380798756683709747323283623552894566069041854716 5029737260856017571432569467896308128832457972079937266842795609362963233465 6327577377986418531570275825779937665992342542699460636407443029919577857433 8281851600006090764198717337191559381124541561638319703069586167725629299517 5076255282960787602293050101970033429356854625906232924704291310702886456251 8632469985653278132588227168080017020040737658591877433454971545485013311503 6561434485127084618089632304423817006708918171546906346335387536183560949225 6036074667890092069337996522372744178148163354405930752765169071704137022745 3128090263426824477803494585851173850223374121732489365069889497237403158227 9840839631127334319988930212402475223960918680308467061859410851679902975904 4661251441881460358726937406012647950645653613408222529039998067223110238643 6584292316840781276633771054531894956472312394322235029051864341558369191090 2082097544642694038762391681516198232954168712855564402707363812139413162515 0480689998678584944350427513554851672228063533753307926177250358938882470874 0552103661088094930068257811242447871657269388113518991542989510629246336165 8479986550036211371919196414464310026701922662394921566955076574453643730934 1341714157231194704091874372904256798372091118444460231449307037375034411885 3676576076869932519269429557331764241054721425368240513547145593868968757079 8413509507002710738565824220172607150332145236704442306962285332528127656564 2590547122402610145691024371453366639652111607302939245318506315359461958010 0338927812940593249471506386124415697212645252323776162585064558232775462345 0951607701158724151244612836110221471968264848258590874666079962640426472074 3487324130608218105825409790022539148520998476124281291687889066415082363438 6377246876252328877677745106379993913801568088315491443230018175530767089172 2280158309314854025846942336224310461844675465480506733085433084145387991886 9163462389952637245366258421425459491140903882880003377713821451634188188884 1270198600409570953154950542534700105045291091093642996156632611959521886490 8877592687889204374862069654416936978853484961795533371115377921813664130820 8894785497117037657605284341185537822982652138954441751771331074319374402086 3465730168436263997343397576043651046145427257983216065136429702161412662944 2533223411458043954241454056372388815682513236663702933669435298342603484167 4852785108888112467902247752587923476008872710917234044426046543641356109789 5876614276812058803783525798121627107430819643445666863755934345575064341943 2421032153639761995700534388812500609556342126624454207517606357454052961253 1916416611193320507596890878455922703579754346646730035078177578839631475550 5154158684730661893835639483595803909842534400000000 -146466598037214168132166946505504582163231930504557323838755829912078704914 7232527937922846836370373882122793776918426462873008206004301364448376259630 0479960292079047337203318689620054594788601914812264756266003542446303110405 9560079971360943834135331209843652685215567853268091899077562013277846536466 1786518361349621668764106591611342239895640346016543607765851182771101386113 1718339502303309148563294578063244261544184459699371894760765768843605074654 7819950060859169704099256831302939154372463310228820624840543133303743930037 6832934573832667131007316074052766767211417435693835817229175698303748426224 8164061481748353716219313553054565951525041510277959943506642274215459240400 3413401913246940636306835336167263971847965958219668263615363229308670003786 1280039502702514466128151473480194115101423711109540716126364366215022998077 3438647003907052554543859418494105956511786638237430891776264628858558346877 0999659442974447178448949336232579513990920556348752372589170183967760081282 1068289815831941416139365959202771157717021073756071068631224445237941841902 1010658333344411773566886865763298166211226814014383373536918777417377201936 0194260907892936117931560105492485208945051722728459321506684015902216398736 1437975998395864293392034350055095596731285567989250747678871045484053969091 7738158228784687166822861537430240167501324801433542590655581872680422750854 3569243672323920014911105847183250923458086240362287243614402774812893620769 8958454584510734797308369548615843411537874069109470839942512266512001813365 1686265685135225872723370661848625082264317185263751868490644013658070593769 5212774412568374551078701167623193603318820391281854674000166562224088265619 7825432639193103479385714210231933101171528480116302844082573381791300062745 3330296747551928284460293572813648085075110582219522739451115791229369187172 3294412418856265068263073465221599276551549319404148769602303854312999142835 4606621084918266578016717978376941310421414846182410260276675218940359642915 0789105727294502216051212140336002972753983918342578254176884786051351324666 191659726146306072405158680 5826600558186537404838856131370471039379659134 58076907875090050502110574307657256807287717388760005394175044663 2615551406650875838181122330253797985104602070241678014791853540448034257062 39419 1177939634036131600533146804222733342399463976109814236899724042387935525345 792616589264996745575 227719861472038658791603995367201962254031696071197510053300364489 1025559083270339613328225485791293069513108821161587766318899893534558082149 559351 4618707505262750497822661744140123902029723820123390596302244701544184757399 151666179549811431957 1973 [2, -2, 4] y^4 + 2*y^3 + 3*y^2 + 2*y + 1 1 1 y^4 [-2*x^2 - y*x, x^2, x^4] [1, 0, 1] [-18*y, 6*y^2 + 4, 4] Mod(0, 3) Mod(1, 3) Mod(0, 2) [-x + 1, 1, 1] x^4 + 2*y*x^2 + y^2 x^20 - 10*x^16 + 20*x^15 + 40*x^12 + 2600*x^11 + 150*x^10 - 80*x^8 + 12400*x ^7 - 17000*x^6 + 500*x^5 + 80*x^4 + 5600*x^3 + 11000*x^2 + 5000*x + 593 [[x^2 + 3*x + 3, Mod(1, x^2 + 3*x + 3), Mod(x + 1, x^2 + 3*x + 3), -1]] [[x + 1, Mod(1, x + 1), Mod(0, x + 1), -1]] [45671927336311364467850760841756180909547222299*x^6 - 638029451049406534289 96491621391444883*x^5 + 106338241871278317114400197462819155342*x^4 + 425352 96637591897616699159146921999851*x^3 + 9903520494138797980865529865*x^2 - 39 614081870486412415152952656*x + 9903520475692053718177416741] [667495948725284411242102370309765312062497672901277377113445345107917941040 17772879647319062957*x^6 - 2171101673199678691497348517844959723714357964663 2712534377807943409537671283*x^5 + 36185027886661311527309721781519334037214 478219681963940798292612566583022564*x^4 + 144740111546645246021359462830663 80462537830921711208017066808153775216384423*x^3 + 7846377169233351033910387 08812777604016555171156676604667*x^2 - 3138550867693340411607531225455714238 857061766766623031418*x + 78463771692333510305075634189183913841335825117460 0402391] [3*x^2 - x + 3, 27*x^2 - 9*x + 237] 81*x^4 - 54*x^3 + 801*x^2 - 264*x + 711 z^2 Mod(2, 3) Mod(41170744616631889845480363679839550251, 17014118346046923173168730371588 4105727) Mod(2, 3) Mod(38717016415582912972454608850047745351, 17014118346046923173168730371588 4105727) Mod(1, 3)*z^3*y^3 2 4 y^2 (x^3 + 1)/x^3 81*x^12 + 540*x^11 + 1456*x^10 + 1980*x^9 + 1318*x^8 + 239*x^7 - 151*x^6 - 3 8*x^5 + 19*x^4 - x^3 - 2*x^2 x^12 + 20*x^11 + 154*x^10 + 558*x^9 + 916*x^8 + 473*x^7 - 75*x^6 - 64*x^5 + 19*x^4 + x^3 - 2*x^2 -479174066176*y^49 - 151613669376*y^36 - 15990504192*y^23 - 562166163*y^10 (a + 1)*x^43 + x^41 + a*x^40 + a*x^39 + (a + 1)*x^38 + (a + 1)*x^37 + x^36 + x^35 + x^34 + a*x^33 + (a + 1)*x^32 + (a + 1)*x^31 + x^29 + a*x^28 + (a + 1 )*x^26 + (a + 1)*x^23 + (a + 1)*x^22 + x^21 + a*x^20 + (a + 1)*x^19 + x^17 + a*x^16 + (a + 1)*x^15 + (a + 1)*x^14 + x^13 + a*x^12 + a*x^11 + (a + 1)*x^9 + x^8 + a*x^6 + a*x^3 + a*x^2 + (a + 1)*x + 1 Total time spent: 2854 pari-2.17.2/src/test/32/sumdedekind0000644000175000017500000000015414567450071015406 0ustar billbill-1/18 0 1145846923/57826382 56713727820156410558782357164918483627/73786976294838206464 Total time spent: 4 pari-2.17.2/src/test/32/multiif0000644000175000017500000000014014567450071014556 0ustar billbill1 1 1 1 1 1 default 2 2 2 2 default default 3 3 default default default 1 2 Total time spent: 4 pari-2.17.2/src/test/32/ell0000644000175000017500000011514314760123736013673 0ustar billbill *** Warning: new stack size = 14000000 (13.351 Mbytes). ellwp:1:x^-2 - 1/5*x^2 + 1/75*x^6 - 2/4875*x^10 + O(x^14) ellwp:I:x^-2 - 1/5*I*x^2 - 1/75*x^6 + 2/4875*I*x^10 + O(x^14) ellwp:z:x^-2 - 1/5*z*x^2 + 1/75*z^2*x^6 - 2/4875*z^3*x^10 + O(x^14) ellwp:Mod(z, z^2 + 5):x^-2 + Mod(-1/5*z, z^2 + 5)*x^2 + Mod(-1/15, z^2 + 5)* x^6 + Mod(2/975*z, z^2 + 5)*x^10 + O(x^14) ellwp:Mod(z, z^2 + 5):x^-2 + Mod(-1/5*z, z^2 + 5)*x^2 + Mod(-1/15, z^2 + 5)* x^6 + Mod(2/975*z, z^2 + 5)*x^10 + O(x^14) ellwp:Mod(4, 1009):Mod(1, 1009)*x^-2 + Mod(201, 1009)*x^2 + Mod(350, 1009)*x ^6 + Mod(345, 1009)*x^10 + O(x^14) ellwp:z:x^-2 + 807*z*x^2 + 148*z^2*x^6 + 368*z^3*x^10 + O(x^14) ellzeta:1:x^-1 + 1/15*x^3 - 1/525*x^7 + 2/53625*x^11 + O(x^15) ellzeta:I:x^-1 + 1/15*I*x^3 + 1/525*x^7 - 2/53625*I*x^11 + O(x^15) ellzeta:z:x^-1 + 1/15*z*x^3 - 1/525*z^2*x^7 + 2/53625*z^3*x^11 + O(x^15) ellzeta:Mod(z, z^2 + 5):x^-1 + Mod(1/15*z, z^2 + 5)*x^3 + Mod(1/105, z^2 + 5 )*x^7 + Mod(-2/10725*z, z^2 + 5)*x^11 + O(x^15) ellzeta:Mod(z, z^2 + 5):x^-1 + Mod(1/15*z, z^2 + 5)*x^3 + Mod(1/105, z^2 + 5 )*x^7 + Mod(-2/10725*z, z^2 + 5)*x^11 + O(x^15) ellzeta:Mod(4, 1009):Mod(1, 1009)*x^-1 + Mod(942, 1009)*x^3 + Mod(959, 1009) *x^7 + Mod(519, 1009)*x^11 + O(x^15) ellzeta:z:x^-1 + 740*z*x^3 + 123*z^2*x^7 + 150*z^3*x^11 + O(x^15) ellsigma:1:x + 1/60*x^5 - 1/10080*x^9 - 23/259459200*x^13 + O(x^17) ellsigma:I:x + 1/60*I*x^5 + 1/10080*x^9 + 23/259459200*I*x^13 + O(x^17) ellsigma:z:x + 1/60*z*x^5 - 1/10080*z^2*x^9 - 23/259459200*z^3*x^13 + O(x^17 ) ellsigma:Mod(z, z^2 + 5):x + Mod(1/60*z, z^2 + 5)*x^5 + Mod(1/2016, z^2 + 5) *x^9 + Mod(23/51891840*z, z^2 + 5)*x^13 + O(x^17) ellsigma:Mod(z, z^2 + 5):x + Mod(1/60*z, z^2 + 5)*x^5 + Mod(1/2016, z^2 + 5) *x^9 + Mod(23/51891840*z, z^2 + 5)*x^13 + O(x^17) ellsigma:Mod(4, 1009):x + Mod(740, 1009)*x^5 + Mod(607, 1009)*x^9 + Mod(802, 1009)*x^13 + O(x^17) ellsigma:z:x + 185*z*x^5 + 101*z^2*x^9 + 990*z^3*x^13 + O(x^17) ellformalw:1:x^3 + x^7 + 2*x^11 + 5*x^15 + O(x^19) ellformalw:I:x^3 + I*x^7 - 2*x^11 - 5*I*x^15 + O(x^19) ellformalw:z:x^3 + z*x^7 + 2*z^2*x^11 + 5*z^3*x^15 + O(x^19) ellformalw:Mod(z, z^2 + 5):x^3 + Mod(z, z^2 + 5)*x^7 + Mod(-10, z^2 + 5)*x^1 1 + Mod(-25*z, z^2 + 5)*x^15 + O(x^19) ellformalw:Mod(z, z^2 + 5):x^3 + Mod(z, z^2 + 5)*x^7 + Mod(-10, z^2 + 5)*x^1 1 + Mod(-25*z, z^2 + 5)*x^15 + O(x^19) ellformalw:Mod(4, 1009):x^3 + Mod(4, 1009)*x^7 + Mod(32, 1009)*x^11 + Mod(32 0, 1009)*x^15 + O(x^19) ellformalw:z:x^3 + z*x^7 + 2*z^2*x^11 + 5*z^3*x^15 + O(x^19) ellformalpoint:1:[x^-2 - x^2 - x^6 - 2*x^10 + O(x^14), -x^-3 + x + x^5 + 2*x ^9 + O(x^13)] ellformalpoint:I:[x^-2 - I*x^2 + x^6 + 2*I*x^10 + O(x^14), -x^-3 + I*x - x^5 - 2*I*x^9 + O(x^13)] ellformalpoint:z:[x^-2 - z*x^2 - z^2*x^6 - 2*z^3*x^10 + O(x^14), -x^-3 + z*x + z^2*x^5 + 2*z^3*x^9 + O(x^13)] ellformalpoint:Mod(z, z^2 + 5):[x^-2 + Mod(-z, z^2 + 5)*x^2 + Mod(5, z^2 + 5 )*x^6 + Mod(10*z, z^2 + 5)*x^10 + O(x^14), -x^-3 + Mod(z, z^2 + 5)*x + Mod(- 5, z^2 + 5)*x^5 + Mod(-10*z, z^2 + 5)*x^9 + O(x^13)] ellformalpoint:Mod(z, z^2 + 5):[x^-2 + Mod(-z, z^2 + 5)*x^2 + Mod(5, z^2 + 5 )*x^6 + Mod(10*z, z^2 + 5)*x^10 + O(x^14), -x^-3 + Mod(z, z^2 + 5)*x + Mod(- 5, z^2 + 5)*x^5 + Mod(-10*z, z^2 + 5)*x^9 + O(x^13)] ellformalpoint:Mod(4, 1009):[Mod(1, 1009)*x^-2 + Mod(1005, 1009)*x^2 + Mod(9 93, 1009)*x^6 + Mod(881, 1009)*x^10 + O(x^14), Mod(1008, 1009)*x^-3 + Mod(4, 1009)*x + Mod(16, 1009)*x^5 + Mod(128, 1009)*x^9 + O(x^13)] ellformalpoint:z:[x^-2 + 1008*z*x^2 + 1008*z^2*x^6 + 1007*z^3*x^10 + O(x^14) , -x^-3 + z*x + z^2*x^5 + 2*z^3*x^9 + O(x^13)] ellformaldifferential:1:[1 + 2*x^4 + 6*x^8 + 20*x^12 + O(x^16), x^-2 + x^2 + 3*x^6 + 10*x^10 + O(x^14)] ellformaldifferential:I:[1 + 2*I*x^4 - 6*x^8 - 20*I*x^12 + O(x^16), x^-2 + I *x^2 - 3*x^6 - 10*I*x^10 + O(x^14)] ellformaldifferential:z:[1 + 2*z*x^4 + 6*z^2*x^8 + 20*z^3*x^12 + O(x^16), x^ -2 + z*x^2 + 3*z^2*x^6 + 10*z^3*x^10 + O(x^14)] ellformaldifferential:Mod(z, z^2 + 5):[Mod(1, z^2 + 5) + Mod(2*z, z^2 + 5)*x ^4 + Mod(-30, z^2 + 5)*x^8 + Mod(-100*z, z^2 + 5)*x^12 + O(x^16), Mod(1, z^2 + 5)*x^-2 + Mod(z, z^2 + 5)*x^2 + Mod(-15, z^2 + 5)*x^6 + Mod(-50*z, z^2 + 5)*x^10 + O(x^14)] ellformaldifferential:Mod(z, z^2 + 5):[Mod(1, z^2 + 5) + Mod(2*z, z^2 + 5)*x ^4 + Mod(-30, z^2 + 5)*x^8 + Mod(-100*z, z^2 + 5)*x^12 + O(x^16), Mod(1, z^2 + 5)*x^-2 + Mod(z, z^2 + 5)*x^2 + Mod(-15, z^2 + 5)*x^6 + Mod(-50*z, z^2 + 5)*x^10 + O(x^14)] ellformaldifferential:Mod(4, 1009):[Mod(1, 1009) + Mod(8, 1009)*x^4 + Mod(96 , 1009)*x^8 + Mod(271, 1009)*x^12 + O(x^16), Mod(1, 1009)*x^-2 + Mod(4, 1009 )*x^2 + Mod(48, 1009)*x^6 + Mod(640, 1009)*x^10 + O(x^14)] ellformaldifferential:z:[1 + 2*z*x^4 + 6*z^2*x^8 + 20*z^3*x^12 + O(x^16), x^ -2 + z*x^2 + 3*z^2*x^6 + 10*z^3*x^10 + O(x^14)] ellformallog:1:x + 2/5*x^5 + 2/3*x^9 + 20/13*x^13 + O(x^17) ellformallog:I:x + 2/5*I*x^5 - 2/3*x^9 - 20/13*I*x^13 + O(x^17) ellformallog:z:x + 2/5*z*x^5 + 2/3*z^2*x^9 + 20/13*z^3*x^13 + O(x^17) ellformallog:Mod(z, z^2 + 5):Mod(1, z^2 + 5)*x + Mod(2/5*z, z^2 + 5)*x^5 + M od(-10/3, z^2 + 5)*x^9 + Mod(-100/13*z, z^2 + 5)*x^13 + O(x^17) ellformallog:Mod(z, z^2 + 5):Mod(1, z^2 + 5)*x + Mod(2/5*z, z^2 + 5)*x^5 + M od(-10/3, z^2 + 5)*x^9 + Mod(-100/13*z, z^2 + 5)*x^13 + O(x^17) ellformallog:Mod(4, 1009):Mod(1, 1009)*x + Mod(607, 1009)*x^5 + Mod(347, 100 9)*x^9 + Mod(797, 1009)*x^13 + O(x^17) ellformallog:z:x + 404*z*x^5 + 337*z^2*x^9 + 312*z^3*x^13 + O(x^17) ellformalexp:1:x - 2/5*x^5 + 2/15*x^9 - 44/975*x^13 + O(x^17) ellformalexp:I:x - 2/5*I*x^5 - 2/15*x^9 + 44/975*I*x^13 + O(x^17) ellformalexp:z:x - 2/5*z*x^5 + 2/15*z^2*x^9 - 44/975*z^3*x^13 + O(x^17) ellformalexp:Mod(z, z^2 + 5):x + Mod(-2/5*z, z^2 + 5)*x^5 + Mod(-2/3, z^2 + 5)*x^9 + Mod(44/195*z, z^2 + 5)*x^13 + O(x^17) ellformalexp:Mod(z, z^2 + 5):x + Mod(-2/5*z, z^2 + 5)*x^5 + Mod(-2/3, z^2 + 5)*x^9 + Mod(44/195*z, z^2 + 5)*x^13 + O(x^17) ellformalexp:Mod(4, 1009):x + Mod(402, 1009)*x^5 + Mod(473, 1009)*x^9 + Mod( 617, 1009)*x^13 + O(x^17) ellformalexp:z:x + 605*z*x^5 + 471*z^2*x^9 + 120*z^3*x^13 + O(x^17) (E)->ellisoncurve(E,[0,0]):1:1 (E)->ellisoncurve(E,[0,0]):I:1 (E)->ellisoncurve(E,[0,0]):z:1 (E)->ellisoncurve(E,[0,0]):Mod(z, z^2 + 5):1 (E)->ellisoncurve(E,[0,0]):Mod(z, z^2 + 5):1 (E)->ellisoncurve(E,[0,0]):Mod(4, 1009):1 (E)->ellisoncurve(E,[0,0]):z:1 (E)->ellordinate(E,0):1:[0] (E)->ellordinate(E,0):I:[0] (E)->ellordinate(E,0):z:[0] (E)->ellordinate(E,0):Mod(z, z^2 + 5):[0] (E)->ellordinate(E,0):Mod(z, z^2 + 5):[0] (E)->ellordinate(E,0):Mod(4, 1009):[Mod(0, 1009)] (E)->ellordinate(E,0):z:[0] (E)->elldivpol(E,5):1:5*x^12 + 62*x^10 - 105*x^8 - 300*x^6 - 125*x^4 - 50*x^ 2 + 1 (E)->elldivpol(E,5):I:5*x^12 + 62*I*x^10 + 105*x^8 + 300*I*x^6 - 125*x^4 - 5 0*I*x^2 - 1 (E)->elldivpol(E,5):z:5*x^12 + 62*z*x^10 - 105*z^2*x^8 - 300*z^3*x^6 - 125*z ^4*x^4 - 50*z^5*x^2 + z^6 (E)->elldivpol(E,5):Mod(z, z^2 + 5):Mod(5, z^2 + 5)*x^12 + Mod(62*z, z^2 + 5 )*x^10 + Mod(525, z^2 + 5)*x^8 + Mod(1500*z, z^2 + 5)*x^6 + Mod(-3125, z^2 + 5)*x^4 + Mod(-1250*z, z^2 + 5)*x^2 + Mod(-125, z^2 + 5) (E)->elldivpol(E,5):Mod(z, z^2 + 5):Mod(5, z^2 + 5)*x^12 + Mod(62*z, z^2 + 5 )*x^10 + Mod(525, z^2 + 5)*x^8 + Mod(1500*z, z^2 + 5)*x^6 + Mod(-3125, z^2 + 5)*x^4 + Mod(-1250*z, z^2 + 5)*x^2 + Mod(-125, z^2 + 5) (E)->elldivpol(E,5):Mod(4, 1009):Mod(5, 1009)*x^12 + Mod(248, 1009)*x^10 + M od(338, 1009)*x^8 + Mod(980, 1009)*x^6 + Mod(288, 1009)*x^4 + Mod(259, 1009) *x^2 + Mod(60, 1009) (E)->elldivpol(E,5):z:5*x^12 + 62*z*x^10 + 904*z^2*x^8 + 709*z^3*x^6 + 884*z ^4*x^4 + (50*z^4 + 809*z^3 + 859*z^2 + 150*z + 50)*x^2 + (5*z^4 + 1008*z^3 + 1003*z^2 + 2*z + 1) (E)->ellxn(E,3):1:[x^9 - 12*x^7 + 30*x^5 + 36*x^3 + 9*x, 9*x^8 + 36*x^6 + 30 *x^4 - 12*x^2 + 1] (E)->ellxn(E,3):I:[x^9 - 12*I*x^7 - 30*x^5 - 36*I*x^3 + 9*x, 9*x^8 + 36*I*x^ 6 - 30*x^4 + 12*I*x^2 + 1] (E)->ellxn(E,3):z:[x^9 - 12*z*x^7 + 30*z^2*x^5 + 36*z^3*x^3 + 9*z^4*x, 9*x^8 + 36*z*x^6 + 30*z^2*x^4 - 12*z^3*x^2 + z^4] (E)->ellxn(E,3):Mod(z, z^2 + 5):[Mod(1, z^2 + 5)*x^9 + Mod(-12*z, z^2 + 5)*x ^7 + Mod(-150, z^2 + 5)*x^5 + Mod(-180*z, z^2 + 5)*x^3 + Mod(225, z^2 + 5)*x , Mod(9, z^2 + 5)*x^8 + Mod(36*z, z^2 + 5)*x^6 + Mod(-150, z^2 + 5)*x^4 + Mo d(60*z, z^2 + 5)*x^2 + Mod(25, z^2 + 5)] (E)->ellxn(E,3):Mod(z, z^2 + 5):[Mod(1, z^2 + 5)*x^9 + Mod(-12*z, z^2 + 5)*x ^7 + Mod(-150, z^2 + 5)*x^5 + Mod(-180*z, z^2 + 5)*x^3 + Mod(225, z^2 + 5)*x , Mod(9, z^2 + 5)*x^8 + Mod(36*z, z^2 + 5)*x^6 + Mod(-150, z^2 + 5)*x^4 + Mo d(60*z, z^2 + 5)*x^2 + Mod(25, z^2 + 5)] (E)->ellxn(E,3):Mod(4, 1009):[Mod(1, 1009)*x^9 + Mod(961, 1009)*x^7 + Mod(48 0, 1009)*x^5 + Mod(286, 1009)*x^3 + Mod(286, 1009)*x, Mod(9, 1009)*x^8 + Mod (144, 1009)*x^6 + Mod(480, 1009)*x^4 + Mod(241, 1009)*x^2 + Mod(256, 1009)] (E)->ellxn(E,3):z:[x^9 + 997*z*x^7 + 30*z^2*x^5 + 36*z^3*x^3 + 9*z^4*x, 9*x^ 8 + 36*z*x^6 + 30*z^2*x^4 + 997*z^3*x^2 + z^4] (E)->ellmul(E,[0,0],0):1:[0] (E)->ellmul(E,[0,0],0):I:[0] (E)->ellmul(E,[0,0],0):z:[0] (E)->ellmul(E,[0,0],0):Mod(z, z^2 + 5):[0] (E)->ellmul(E,[0,0],0):Mod(z, z^2 + 5):[0] (E)->ellmul(E,[0,0],0):Mod(4, 1009):[0] (E)->ellmul(E,[0,0],0):z:[0] (E)->ellneg(E,[0,0]):1:[0, 0] (E)->ellneg(E,[0,0]):I:[0, 0] (E)->ellneg(E,[0,0]):z:[0, 0] (E)->ellneg(E,[0,0]):Mod(z, z^2 + 5):[0, 0] (E)->ellneg(E,[0,0]):Mod(z, z^2 + 5):[0, 0] (E)->ellneg(E,[0,0]):Mod(4, 1009):[0, Mod(0, 1009)] (E)->ellneg(E,[0,0]):z:[0, 0] -1 0 152 1031:[504, 2] 2053:[1008, 2] 4099:[4196] 8209:[8291] 16411:[8280, 2] 32771:[32545] 65537:[65115] 131101:[130579] 262147:[261873] 524309:[525362] 1048583:[1048721] 2097169:[2099343] 4194319:[4190448] 8388617:[4196176, 2] 16777259:[16776451] 33554467:[33556544] 67108879:[33553348, 2] 134217757:[134207016] 268435459:[268450764] 536870923:[536886729] 1073741827:[1073696739] 2147483659:[2147445985] 4294967311:[4294892145] 8589934609:[8589800815] 17179869209:[17179907771] 34359738421:[34359891299] 68719476767:[68719109932] 137438953481:[137439150447] 274877906951:[274876963417] 549755813911:[549755723143] 1099511627791:[1099510624080] 2199023255579:[1099512197774, 2] 4398046511119:[4398049864270] 8796093022237:[8796090641581] 17592186044423:[17592179180564] 35184372088891:[35184377696395] 70368744177679:[70368735914810] 140737488355333:[140737466844674] 281474976710677:[281474967245574] 562949953421381:[562949910045019] 1125899906842679:[562949923357406, 2] 2251799813685269:[2251799812875502] 4503599627370517:[4503599672855988] 9007199254740997:[9007199395723803] 18014398509482143:[18014398460825440] 36028797018963971:[18014398463069820, 2] 72057594037928017:[36028797145369816, 2] 144115188075855881:[144115187446866113] 288230376151711813:[288230375567209858] 576460752303423619:[576460752721346915] 1152921504606847009:[1152921506693313952] 2305843009213693967:[2305843010596733829] 4611686018427388039:[4611686021547019756] 9223372036854775837:[9223372041689460430] 15 1 1 163663 121661 1 1023 494 0 1728 j 0 Mod(0, 5) Mod(3, 5) Mod(1, 2)*j 0 0 0 Mod(1, 3)*j [0, D*a2, 0, D^2*a4, D^3*a6] [a1, T*a1^2 + a2, a3, a4, T*a3^2 + a6] [a1, a2, a3, a4, a6] [0, -a1^2 - 4*a2, 0, 8*a3*a1 + 16*a4, -16*a3^2 - 64*a6] [-a1, a1^2 + 5*a2, -5*a3, 10*a3*a1 + 25*a4, 25*a3^2 + 125*a6] [0, 0, 0, 25*a4, 125*a6] -8 -4 [0, 0, 0, -11737467275460978540, -17351253812244416823734891600, 0, -2347493 4550921957080, -69405015248977667294939566400, -1377681380425173666806670582 14340531600, 563398429222126969920, 14991483293779176135706946342400, -26569 379066176956739643152125596317141644100461473562624000, -882216989/131072, V ecsmall([1]), [Vecsmall([128, -1])], [0, 0, 0, 0, 0, 0, 0, 0]] [1/512, 0, 0, 0] 133304232 133304232 [[-8, -1792], [24, -1792]] [[-4, -27], [12, -27]] [[-8, -64], [24, -64]] [[1, -11], [-3, -11]] [[24, -3456], [-8, -3456]] [[-8, -5184], [24, -5184]] [[24, -93312], [24, -93312], [-3, -93312], [-3, -93312]] [[-3, 11664], [-3, 11664], [24, 11664], [24, 11664]] [[-3, -34992], [-3, -34992], [24, -34992], [24, -34992]] [[1, 64], [1, 64], [-8, 64], [-8, 64]] [[1, -15], [-4, -15], [8, -15], [-8, -15]] [[1, -11648], [1, -11648], [-8, -11648], [-8, -11648]] 12 a a 8*x^9 + 54*x^8 + 393*x^7 + 2373*x^6 + 6993*x^5 + 15267*x^4 + 19998*x^3 + 473 4*x^2 - 25880*x - 30932 -1 -4*x^3 - 9*x^2 - 26*x - 37 -3*x^4 - 9*x^3 - 39*x^2 - 111*x - 41 [0, 0] [x, 1] [x^4 - 13*x^2 - 74*x - 41, 4*x^3 + 9*x^2 + 26*x + 37] [x^16 - 260*x^14 - 5968*x^13 - 39963*x^12 - 140444*x^11 - 195486*x^10 + 5215 64*x^9 + 5378114*x^8 + 23699984*x^7 + 74549288*x^6 + 183951360*x^5 + 3366091 54*x^4 + 444753656*x^3 + 432135644*x^2 + 255731272*x + 49749605, 16*x^15 + 1 80*x^14 + 1792*x^13 + 14753*x^12 + 84148*x^11 + 414370*x^10 + 1658348*x^9 + 4652985*x^8 + 9212312*x^7 + 10904612*x^6 + 434120*x^5 - 24648228*x^4 - 39304 176*x^3 - 13741184*x^2 + 25100064*x + 25859152] [x^25 - 650*x^23 - 23335*x^22 - 259290*x^21 - 1456154*x^20 - 2820445*x^19 + 20761370*x^18 + 277111495*x^17 + 2007242185*x^16 + 11282671667*x^15 + 529194 54495*x^14 + 207385350880*x^13 + 677127946605*x^12 + 1857857835015*x^11 + 43 12300313262*x^10 + 8526087679330*x^9 + 14394585463670*x^8 + 20512909438825*x ^7 + 23836827014955*x^6 + 20324637565929*x^5 + 7866409553255*x^4 - 796635515 1205*x^3 - 15373355872840*x^2 - 10304273387855*x - 2425203075812, 25*x^24 + 450*x^23 + 6865*x^22 + 90410*x^21 + 848806*x^20 + 6747580*x^19 + 45352495*x^ 18 + 229321140*x^17 + 838958290*x^16 + 2007441886*x^15 + 1506282910*x^14 - 1 1941908510*x^13 - 67097680775*x^12 - 197749423840*x^11 - 360107712461*x^10 - 248110872190*x^9 + 863441551840*x^8 + 3852505140470*x^7 + 8796991424540*x^6 + 14201708642530*x^5 + 17446507273700*x^4 + 16338035413000*x^3 + 1142822256 7925*x^2 + 5633997157650*x + 1472351694025] [0] [-23338430276487649199700397847721116081702650343430925719105465344187224269 2167848859501069746367317057135733659821516586965453870026354744714986684965 8323996212283434950398700511439/21452304628477972409549628569820513272484339 3023834534814913254065684077308619895779034479691808535960623339165042624323 5345631919723231687684699452030828176986716708998958804636224, -892721634620 8423324340896231392069270729522715981007828685033969863523382353428674866926 4734542739355918998020644016664732197288414787069129806148688960193235312780 7158822883693587635120259554260938849967680317634128924102700969620674883736 9307779952513049787052947107461/31420343828112469950094830391399473730286380 5713026983524763427660191121031569408909200906270720147570836507805210795709 8988916304745235223129078126602318052803199405011168522054272192266092941904 104143227672460543588095008724194999641591292020853488313837016518733957632] [-1, 1] [-1, -3] [833245230963211172586751702962398963656841653/30025043966406435914574252820 2802293592821136, -572865877831905829779071583256995923720966703129995025914 40045201397/5202660393781989115440421988056492168066969880055771334597510887 616] [-10325327/6270016, -17317169781/15700120064] [-10325327/6270016, -17317169781/15700120064] 16*x^33 + 20048*x^30 - 524864*x^27 - 20273280*x^24 - 35051520*x^21 - 1832755 20*x^18 - 818626560*x^15 - 1017937920*x^12 - 390856704*x^9 + 74973184*x^6 + 102760448*x^3 + 4194304 0 [1, 0] [-1, -1] 1 0 1 1 0 0 [2.7807400137667297710631976271813584994, 1.39037000688336488553159881359067 92497 - 1.0687497763561930661592635474375038788*I] [5.5614800275334595421263952543627169988, 2.78074001376672977106319762718135 84994 - 2.1374995527123861323185270948750077575*I] [2, 3, 4, 5] [[2.7310287229193649821042781373532528269 E-8, 1.365514361459682491052139068 6766264135 E-8 - 2.0932938775238211538088662030244109173 E-7*I], [6.29884879 13763781029368062481832691764, 3.1494243956881890514684031240916345882 - 9.6 559523521538567664774654983716074769*I]] [[6.4470842711340804176260084181666178112 E-9, 3.223542135567040208813004209 0833089056 E-9 - 4.9415965197974094063227743203128717389 E-8*I], [26.6823516 60262728761263905104981541916, 13.341175830131364380631952552490770958 - 40. 903270551222725120144381157344817311*I]] [Mod(-w - 2, w^2 - 5), Mod(2*w + 5, w^2 - 5), Mod(-w + 1, w^2 - 5), Mod(-3, w^2 - 5)] [3.1096482423243803285501491221965830079, 1.55482412116219016427507456109829 15039 + 1.0643747452102737569438859937299427442*I] [6.2192964846487606571002982443931660157, 3.10964824232438032855014912219658 30079 + 2.1287494904205475138877719874598854884*I] [5.5614800275334595421263952543627169988, 2.78074001376672977106319762718135 84994 - 2.1374995527123861323185270948750077575*I] [6.2192964846487606571002982443931660157, 3.10964824232438032855014912219658 30079 + 2.1287494904205475138877719874598854884*I] [-1.1547274830668428355945002349018042438, -0.828886258466578582202749882549 09787812 + 0.52313677422798965199542236165917364573*I, -0.828886258466578582 20274988254909787812 - 0.52313677422798965199542236165917364573*I] [10351, [1/2, -1, -2, 5/4], 1, [11, 1; 941, 1], [[1, 5, 0, 1], [1, 5, 0, 1]] ] [10351, [1, -1, 0, -1], 1, [11, 1; 941, 1], [[1, 5, 0, 1], [1, 5, 0, 1]]] [0, 1, [18446744073709551629, -1020847100762815391828969860044649660923, -55 340232221128654887, 25108406941546723108427206932497066002105857518694949724 756], 1] [9, [9], [[Mod(3, 7), Mod(5, 7)]]] [0, 0, 0, 413748, 716503104, 0, 827496, 2866012416, -171187407504, -19859904 , -619058681856, -226311754192704000000, 97158364170048/2807086984375, Vecsm all([1]), [Vecsmall([128, -1])], [0, 0, 0, 0, 0, 0, 0, [[2, 3]~]]] [1/30, -13/150, -1/10, -79/500] 1 [36, [36], [[a^4 + a, a^3 + a + 1]]] 1 [3, [3], [[0, 2]]] 1 [4, [4], [[Mod(3, 5), Mod(3, 5)]]] [3^-1 + 2 + 2*3^2 + 2*3^5 + 2*3^6 + 2*3^7 + O(3^8)]~ [1 + 2*3 + 3^2 + 2*3^3 + 3^4 + 3^5 + 2*3^6 + 3^7 + 3^8 + O(3^10), 1 + 3 + 3^ 3 + 3^4 + 2*3^5 + 2*3^6 + 2*3^7 + O(3^10), 3 + 2*3^3 + 2*3^7 + O(3^8), [1 + 2*3 + 3^2 + 2*3^3 + 3^4 + 3^6 + 3^9 + O(3^10), 1 + 3 + 2*3^2 + 3^3 + 2*3^4 + 2*3^5 + 3^6 + 3^9 + O(3^10)], 2*3^2 + 3^4 + 3^5 + 3^6 + O(3^7), [[20563, 24 337, 40465, 16489, 23050], [21109, 27838, 25318, 29611, 23050], [3 + 2*3^2 + 2*3^4 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + O(3^10), 3^2 + 2*3^3 + 3^4 + 3^6 + 3^7 + 2*3^8 + 2*3^9 + O(3^10), 3^4 + 2*3^5 + 2*3^6 + 2*3^8 + O(3^10), 3^8 + 2*3^9 + O(3^10)], 0]] error("inconsistent moduli in ellinit: 3 != 5") error("inconsistent moduli in ellinit: 3 != 5") error("incorrect type in elliptic curve base_ring (t_VEC).") [3^-1 + 2 + 2*3^2 + 2*3^5 + 2*3^6 + 2*3^7 + O(3^10)]~ [3^2 + 2*3^3 + 3^4 + 2*3^5 + 3^6 + 3^7 + 2*3^8 + 3^9 + 3^10 + O(3^12), 3 + 3 ^2 + 3^4 + 3^5 + 2*3^6 + 2*3^7 + 2*3^8 + O(3^11), 3 + 2*3^3 + 2*3^7 + O(3^8) , [3^-2 + 2*3^-1 + 1 + 2*3 + 3^2 + 3^4 + 3^7 + O(3^8), 3^-2 + 3^-1 + 2 + 3 + 2*3^2 + 2*3^3 + 3^4 + 3^7 + O(3^8)], 2*3^2 + 3^4 + 3^5 + 3^6 + O(3^7)] [3^-4 + 3^-2 + O(3^0), 2*3^-6 + 2*3^-5 + 2*3^-4 + O(3^-2)] [2 + 2^6 + O(2^9), Mod(x, x^2 + (2 + 2^2 + 2^3 + 2^4 + 2^5 + 2^7 + 2^8 + O(2 ^9))), 2^3 + 2^4 + O(2^8), [2^-3 + 2^2 + 2^4 + 2^7 + 2^10 + O(2^11), 2^-3 + 2^2 + 2^5 + 2^6 + 2^10 + O(2^13)], 1, [[9377, 4065, 481], [8993, 7137, 1505] , [2^4 + 2^5 + O(2^11), 2^7 + O(2^9)], -3]] [1 + 2^2 + 2^7 + 2^9 + 2^11 + O(2^13), Mod(x, x^2 + (1 + 2 + 2^3 + 2^4 + 2^5 + 2^6 + 2^8 + 2^10 + 2^12 + O(2^13))), 2^6 + 2^10 + 2^11 + O(2^12), [2^-2 + 1 + 2 + 2^4 + 2^9 + 2^10 + O(2^15), 2^-2 + 1 + 2 + 2^4 + 2^8 + 2^11 + 2^15 + O(2^16)], 1, [[6221, 7757], [140365, 7757], [2^8 + 2^10 + 2^11 + 2^12 + 2^ 13 + 2^14 + O(2^15)], -2]] x^-2 + 31/15*x^2 + 2501/756*x^4 + 961/675*x^6 + 77531/41580*x^8 + O(x^9) [5.0000000000000000000000000000000000000, 5.00000000000000000000000000000000 00001] [-12.064158953746718488850195394125882872 - 15.92520450223955742328295296854 0594885*I, 176.27130319116395732662786731582177463 - 31.20263982848450159665 8857828111044055*I] [0] [-1.2137559863387746413172077159498331998, -0.757861263970860955134912630669 68406623*I] [-1, -2*w] 4.9747357492884922209880132412724056589 - 3.14159265358979323846264338327950 28842*I 2.1511232801862930857154336102180672650 E-39 + 2.284733249535410131896634108 2212062060*I [-0.11111111111111111111110856972094952393 - 1512366075204170948725763450259 63248351/100000000000000000000000000000000000000000000000000*I, 7.3468396926 392969248046033576390354864 E-40 + 1/100000000000000000000000000000000000000 00000000000*I] [-1, 1/2*I] [[-1, 1/2*I], [0.59200051084078635056480901325155142952, -6.5791855625999796 522076912731847814832*I]] [1, 1] x^-2 - 1/5*x^2 - 1/7*x^4 + 1/75*x^6 + 3/385*x^8 + 277/238875*x^10 - 2/5775*x ^12 + O(x^14) x^-2 - 1/5*x^2 - 1/7*x^4 + 1/75*x^6 + O(x^7) 8.9760336058655702799613054290253052730 -8.9795585687185301843619815765809019105 0.0070737179180847219897019688523688143770 - 4.54459013280902760664280136539 71181199*I [1, 2] x^-2 + 103.98999607107861876118376809420672237*x^2 - 649.9550420035218272005 1926719405777425*x^4 + 3604.6397609543155221247400145868915015*x^6 - 18433.3 15162997447301537872827568145124*x^8 + 90164.1927526450698484311468148077532 96*x^10 - 425973.41586156854974946172781042993149*x^12 + O(x^14) x^-2 + 103.98999607107861876118376809420672237*x^2 - 649.9550420035218272005 1926719405777425*x^4 + 3604.6397609543155221247400145868915015*x^6 + O(x^7) 15.663727422159594482268754503777038319 -39.480069718736152480166362703315829534 11.908171148288278998948804099769395608 + 1.97957325252946376553721096563444 46188*I [1, 3] x^-2 + 103.98999607107861876118376809420672237*x^2 - 649.9550420035218272005 1926719405777425*x^4 + 3604.6397609543155221247400145868915015*x^6 - 18433.3 15162997447301537872827568145124*x^8 + 90164.1927526450698484311468148077532 96*x^10 - 425973.41586156854974946172781042993149*x^12 + O(x^14) x^-2 + 103.98999607107861876118376809420672237*x^2 - 649.9550420035218272005 1926719405777425*x^4 + 3604.6397609543155221247400145868915015*x^6 + O(x^7) 15.663727422159594482268754503777038319 -39.480069718736152480166362703315829534 11.908171148288278998948804099769395608 + 1.97957325252946376553721096563444 46188*I [2, 1] x^-1 + 1/15*x^3 + 1/35*x^5 - 1/525*x^7 - 1/1155*x^9 - 277/2627625*x^11 + 2/7 5075*x^13 + O(x^15) x^-1 + 1/15*x^3 + 1/35*x^5 - 1/525*x^7 + O(x^8) 3.0025857981852417376980007365038576528 -3.0023507303355942712341893343171384978*I 1.4945837634650773441141478432745008118 - 1.49552579635851441107083905597206 14467*I [2, 2] x^-1 - 34.663332023692872920394589364735574123*x^3 + 129.9910084007043654401 0385343881155485*x^5 - 514.94853727918793173210571636955592878*x^7 + 2048.14 61292219385890597636475075716805*x^9 - 8196.74479569500634985737698316434120 88*x^11 + 32767.185835505273057650902139263840884*x^13 + O(x^15) x^-1 - 34.663332023692872920394589364735574123*x^3 + 129.9910084007043654401 0385343881155485*x^5 - 514.94853727918793173210571636955592878*x^7 + O(x^8) 2.0876703200272312306836757817491311848 -0.75844907585936710327841325497105198841*I 1.8018229730105461594800210664505892492 - 4.22108966565276293974646245627813 69113*I [2, 3] x^-1 - 34.663332023692872920394589364735574123*x^3 + 129.9910084007043654401 0385343881155485*x^5 - 514.94853727918793173210571636955592878*x^7 + 2048.14 61292219385890597636475075716805*x^9 - 8196.74479569500634985737698316434120 88*x^11 + 32767.185835505273057650902139263840884*x^13 + O(x^15) x^-1 - 34.663332023692872920394589364735574123*x^3 + 129.9910084007043654401 0385343881155485*x^5 - 514.94853727918793173210571636955592878*x^7 + O(x^8) 2.0876703200272312306836757817491311848 -0.75844907585936710327841325497105198841*I 1.8018229730105461594800210664505892492 - 4.22108966565276293974646245627813 69113*I [3, 1] x + 1/60*x^5 + 1/210*x^7 - 1/10080*x^9 - 1/138600*x^11 - 167/259459200*x^13 - 19/1513512000*x^15 + O(x^17) x + 1/60*x^5 + 1/210*x^7 - 1/10080*x^9 + O(x^10) 0.33340409272605175654322174351877926789 0.33339973807064633526799756411632693201*I 0.33307632454406929865753194192439552171 + 0.3330414840427217068846417452694 8964210*I [3, 2] x - 8.6658330059232182300986473411838935307*x^5 + 21.66516806678406090668397 5573135259142*x^7 - 26.820236316624371444380506060914371291*x^9 + 17.0678844 10182821575498030395896430672*x^11 + 0.9724196316598484235781214649285975622 3*x^13 - 15.440886182405758633317637416815798050*x^15 + O(x^17) x - 8.6658330059232182300986473411838935307*x^5 + 21.66516806678406090668397 5573135259142*x^7 - 26.820236316624371444380506060914371291*x^9 + O(x^10) 0.30631122697380979289268115078987850649 0.28630802922181366479814671169863862828*I 0.53021646242894349905972369056429285871 + 0.3781418838145237834855647058271 9409289*I [3, 3] x - 8.6658330059232182300986473411838935307*x^5 + 21.66516806678406090668397 5573135259142*x^7 - 26.820236316624371444380506060914371291*x^9 + 17.0678844 10182821575498030395896430672*x^11 + 0.9724196316598484235781214649285975622 3*x^13 - 15.440886182405758633317637416815798050*x^15 + O(x^17) x - 8.6658330059232182300986473411838935307*x^5 + 21.66516806678406090668397 5573135259142*x^7 - 26.820236316624371444380506060914371291*x^9 + O(x^10) 0.30631122697380979289268115078987850649 0.28630802922181366479814671169863862828*I 0.53021646242894349905972369056429285871 + 0.3781418838145237834855647058271 9409289*I [4, 1] 0 0 -1.0984000330177788282680372407424344829 -1.0984130942966868400436474225688716324 + 1.5707963267948966192313216916397 514421*I -0.75286232322707031868584884787482252469 + 0.785345859584418994173505759767 90041015*I [4, 2] 0 0 -1.1831536122930622250712755356827420688 + 6.2831853071795864769252867665590 057684*I -1.2506870224867757820652851907990498543 + 1.5707963267948966192313216916397 514421*I -0.42886850134944751864186009377385060419 + 0.619519575104929600932212172490 11490055*I [4, 3] 0 0 -1.1831536122930622250712755356827420688 + 6.2831853071795864769252867665590 057684*I -1.2506870224867757820652851907990498543 + 1.5707963267948966192313216916397 514421*I -0.42886850134944751864186009377385060419 + 0.619519575104929600932212172490 11490055*I 1.6173867356247324265790062491002415217 1.0000000000000000000000000000000000000 1.5262092342121874283486002659660931273 1.3072271083373083684152764113581310986 + 0.12080804002667750325506916371967 524765*I 1.8905637270339962486716864116288975237 - 0.20223185382981983227377558872544 258971*I [2.5135797437238231405782694715779164652, 1.25678987186191157028913473578895 82326 + 0.78959476569186174055147277865716603189*I] [3.1415926535897932384626433832795028842, 9.42477796076937971538793014983850 86526*I] (x)->elleisnum(x,2) -2.9936282668967606065680548947245432597 - 7.1637767384648910133063235008836 078048*I 157.90045350239951165298459055643475560 157.90045350239951165298459055643475560 (x)->real(elleisnum(x,4,1)) -4.0000000000000000000000000000000000000 2079.7999214215723752236753618841344474 2079.7999214215723752236753618841344474 (x)->real(elleisnum(x,6,1)) -4.0000000000000000000000000000000000000 -18198.741176098611161614539481433617679 -18198.741176098611161614539481433617679 (x)->real(elleisnum(x,10)) -41472.000000000000000000000000000000000 98106527293.111533926136928277796284706 98106527293.111533926136928277796284706 45515516542954982422.225456145489798060 2.0716622535417196510500376518804560198 E39 41.333333333333333333333333333333333334 128 -1 [0] 347813742467679407541/38941611811810745401 -113 [0.49999999999999999999999999999999999998 + 1.000000000000000000000000000000 0000000*I, 1.5617041082089070087003342842479112065 + 0.560285392988767405183 91807553710802979*I] error("incorrect type in ellpointtoz (t_VEC).") 3 + 11^2 + 2*11^3 + 3*11^4 + 6*11^5 + 10*11^6 + 8*11^7 + O(11^8) O(11^8) error("sorry, ellpointtoz when u not in Qp is not yet implemented.") error("sorry, ellpointtoz when u not in Qp is not yet implemented.") Mod(2 + 2*3 + 2*3^2 + 2*3^3 + 2*3^4 + 2*3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + 2*3^10 + 2*3^11 + 2*3^12 + 2*3^13 + 2*3^14 + 2*3^15 + 2*3^16 + 2*3^17 + 2* 3^18 + 2*3^19 + 2*3^20 + 2*3^21 + 2*3^22 + 2*3^23 + 2*3^24 + 2*3^25 + 2*3^26 + 2*3^27 + 2*3^28 + 2*3^29 + 2*3^30 + 2*3^31 + O(3^32), x^2 + (1 + 2*3 + 2* 3^2 + 3^3 + 2*3^5 + 2*3^6 + 3^7 + 2*3^8 + 2*3^11 + 3^12 + 3^15 + 3^16 + 3^18 + 3^19 + 2*3^20 + 2*3^22 + 2*3^23 + 3^24 + 2*3^26 + 3^27 + 2*3^29 + 2*3^30 + 2*3^31 + O(3^32))) Mod((2 + 2*3 + 2*3^2 + 2*3^3 + 2*3^4 + 2*3^5 + 2*3^6 + 2*3^7 + 2*3^8 + O(3^9 )), x^2 + (1 + 3 + 2*3^4 + 3^8 + O(3^9))) Mod(O(3^9), x^2 + (1 + 3 + 2*3^4 + 3^8 + O(3^9))) error("sorry, ellpointtoz when u not in Qp is not yet implemented.") Mod((2 + 2*3 + 3^2 + 3^3 + 3^5 + 3^7 + O(3^10))*x + (1 + 3 + 2*3^2 + 2*3^4 + 2*3^5 + 3^6 + 3^8 + 2*3^9 + O(3^10)), x^2 + (3 + 3^3 + 2*3^4 + 3^5 + 2*3^6 + 3^7 + 2*3^8 + 3^9 + 2*3^10 + 3^11 + O(3^13))) Mod(O(3^10)*x + O(3^10), x^2 + (3 + 3^3 + 2*3^4 + 3^5 + 2*3^6 + 3^7 + 2*3^8 + 3^9 + 2*3^10 + 3^11 + O(3^13))) Mod((2^2 + 2^4 + 2^5 + 2^6 + 2^8 + O(2^10))*x + (1 + 2 + 2^2 + 2^8 + O(2^11) ), x^2 + (1 + 2^2 + 2^4 + 2^5 + 2^7 + 2^8 + 2^9 + O(2^11))) Mod(O(2^11)*x + O(2^9), x^2 + (1 + 2^2 + 2^4 + 2^5 + 2^7 + 2^8 + 2^9 + O(2^1 1))) 4*5 + 3*5^2 + 2*5^4 + 2*5^5 + 3*5^6 + 3*5^7 + 3*5^8 + 3*5^9 + 3*5^10 + O(5^1 1) O(5^10) 2 + O(2^8) O(2^9) 2^7 + 2^8 + 2^10 + 2^11 + 2^13 + 2^15 + O(2^18) O(2^15) [Mod(0, 11), Mod(0, 11), Mod(0, 11), Mod(1, 11), Mod(1, 11), Mod(0, 11), Mod (2, 11), Mod(4, 11), Mod(10, 11), Mod(7, 11), Mod(5, 11), Mod(10, 11), Mod(9 , 11), Vecsmall([3]), [11, [9, 5, [6, 0, 0, 0]]], [0, 0, 0, 0]] 1 [0.86602540378443864676372317075293618347 - 1/2*I, -0.8660254037844386467637 2317075293618348 - 1/2*I] [-2, 3] [0, 1] [1, 0, 0, 0] 0.035247504442186170440172838583518049039 error("incorrect type in ellheight [not a rational point] (t_VEC).") [1, 0, 0, 0] [100000000000000000039, 0, 0, 0] [0, 0, 0, 1, 1, 0, 2, 4, -1, -48, -864, -496, 6912/31, Vecsmall([1]), [Vecsm all([128, -1])], [0, 0, 0, 0, 0, 0, 0, [[2]~]]] [0, 0, 0, 1/16, 1/64, 0, 1/8, 1/16, -1/256, -3, -27/2, -31/256, 6912/31, Vec small([1]), [Vecsmall([128, -1])], [0, 0, 0, 0, 0, 0, 0, [[2]~, [1/2, 0, 0, 0], [0, 0, 0, 1, 1, 0, 2, 4, -1, -48, -864, -496, 6912/31, Vecsmall([1]), [V ecsmall([128, -1])], [0, 0, 0, 0, 0, 0, 0, [[2]~]]]]]] 0 20 0 0 -16 0 -4 14 8 0 0 0 26 0 2 0 -28 11124672632 0 0 0 0 0 9623756642 1757839784 0 10364773916 0 -11268052540 -89 20565254 10819287710 0 0 0 8122434446 1728 0 0 -22 0 -14 0 -22 0 0 26 0 18 0 -14 2 0 0 -11632185758 0 11654847458 0 6266694946 12139026234 0 -765697030 0 -993589 2958 0 11860023378 -8888351742 0 -12108381446 0 -12120201878 -3375 16 0 -10 0 -22 24 0 -20 0 0 4 0 8 -18 -26 0 3823447300 13247194 -10908503128 0 1880681120 0 0 12050551284 10977324518 0 0 0 -948699894 0 0 9979357082 11495943932 0 8000 0 -18 6 22 0 0 0 2 0 0 18 0 0 22 0 0 -10793410270 0 0 30 0 0 0 2640064994 8901937002 0 0 0 0 8077589434 0 5325840 630 -5129549082 0 54000 20 0 0 16 0 4 -14 -8 0 0 0 26 0 2 0 -28 -11124672632 0 0 0 0 0 -9623756642 1757839784 0 10364773916 0 -11268052540 8 920565254 -10819287710 0 0 0 8122434446 -32768 0 0 3 0 0 0 23 16 0 0 21 25 -15 0 0 -20 7894594559 0 0 9919498893 0 0 -7887871151 0 0 0 0 0 491192422 -8259190543 0 0 0 12121352347 287496 0 0 22 0 -14 0 22 0 0 -26 0 -18 0 14 2 0 0 -11632185758 0 11654847458 0 -6266694946 -12139026234 0 -765697030 0 99358 92958 0 11860023378 8888351742 0 -12108381446 0 12120201878 -884736 0 7 23 -9 11 0 18 -24 0 0 0 0 17 0 -22 -25 0 -8412576737 0 0 0 0 8538343901 12113814432 -11651750401 12092421657 0 0 0 0 0 -11058211849 0 -1330007630 -12288000 20 0 0 -23 0 19 14 25 0 0 0 7 0 23 0 -11 -9788647777 0 0 0 0 0 11231998687 11288673199 0 304785419 0 -11268052540 268 1012851 10819287710 0 0 0 -11884260649 16581375 16 0 10 0 22 24 0 -20 0 0 -4 0 8 -18 -26 0 -3823447300 13247194 -10908503128 0 1880681120 0 0 12050551284 10977324518 0 0 0 948699894 0 0 9979357082 11495943932 0 -884736000 11 0 0 -13 0 0 0 0 -25 -2 0 -6 0 -27 -10 0 -12128231367 0 -9395300833 -435256334 0 0 0 -11932204400 -10588952138 0 0 0 0 0 0 -7319300662 0 0 -147197952000 -21 -16 0 0 -23 1 5 7 20 -25 0 11 0 13 0 -27 0 11781526319 1637387588 0 12146798315 0 -8198706882 0 3977562293 8890885111 -9549303299 -11553067388 9924967665 3852111021 0 5199002617 772472488 0 -262537412640768000 0 19 0 0 0 -21 0 0 4 -23 8 0 0 0 -25 -12 0 0 6564371741 0 0 2618909413 0 2136229176 0 0 0 4357107277 1635802689 30896 18289 0 -5064045658 0 0 4294985035 [0, 1, [5, 0, 0, 0], 1] 1 0 [6.2500000000000000000000000000000000000, -140.62500000000000000000000000000 000000] error("incorrect type in checkell (t_VEC).") [0, 0, 0, x^2, x, 0, 2*x^2, 4*x, -x^4, -48*x^2, -864*x, -64*x^6 - 432*x^2, 6 912*x^4/(4*x^4 + 27), Vecsmall([0]), [Vecsmall([128, 0])], [0, 0, 0, 0]] error("incorrect type in ellminimalmodel (E / number field) (t_VEC).") error("incorrect type in checkell over Fq (t_VEC).") [0, 0, 0, 1, 2, 0, 2, 8, -1, -48, -1728, -1792, 432/7, Vecsmall([0]), [Vecsm all([128, -1])], [0, 0, 0, 0]] [0, 0, 0, 0, 1, 0, 0, 4, 0, 0, 1, 3, 0, Vecsmall([4]), [0, [Vecsmall([0]), V ecsmall([0, 1]), [Vecsmall([0, 1]), Vecsmall([0]), Vecsmall([0]), Vecsmall([ 0])]]], [0, 0, 0, 0]] [0, 0, 0, 1.0000000000000000000000000000000000000, 1, 0, 2.00000000000000000 00000000000000000000, 4, -1.0000000000000000000000000000000000000, -48.00000 0000000000000000000000000000000, -864, -496.00000000000000000000000000000000 000, 222.96774193548387096774193548387096774, Vecsmall([0]), [Vecsmall([128, -1])], [0, 0, 0, 0]] 1 -1 1 1 2170814464 4 5.5851222210291762172101660392028515730 1 2170814464/531441 4 5.5851222210291762172101660392028515730 -21952 6 0.33022365934448053902826194612283487754 3.5069511370460869021391160508020304780 -52760 -52832 [[1, -1], 2] [[509051665/47782462464, -2265512629515497/10444864034930688], 12] ellformalw t^3 - t^5 + t^6 - t^7 - 3*t^8 + 9*t^9 - 2*t^10 - 21*t^11 + 45*t^12 - 21*t^13 - 140*t^14 + 339*t^15 - 91*t^16 - 1051*t^17 + 2394*t^18 + O(t^19) x^3 - x^5 + x^6 - x^7 + O(x^8) t^3 - t^5 + t^6 - t^7 + O(t^8) ellformalpoint [t^-2 + 1 - t + 2*t^2 + t^3 - 5*t^4 + 3*t^5 + 5*t^6 - 19*t^7 + 22*t^8 + 33*t ^9 - 129*t^10 + 111*t^11 + 228*t^12 - 855*t^13 + O(t^14), -t^-3 - t^-1 + 1 - 2*t - t^2 + 5*t^3 - 3*t^4 - 5*t^5 + 19*t^6 - 22*t^7 - 33*t^8 + 129*t^9 - 11 1*t^10 - 228*t^11 + 855*t^12 + O(t^13)] [x^-2 + 1 - x + 2*x^2 + O(x^3), -x^-3 - x^-1 + 1 - 2*x + O(x^2)] [t^-2 + 1 - t + 2*t^2 + O(t^3), -t^-3 - t^-1 + 1 - 2*t + O(t^2)] ellformaldifferential [1 - t^2 + 2*t^3 - 3*t^4 - 6*t^5 + 23*t^6 - 12*t^7 - 53*t^8 + 160*t^9 - 131* t^10 - 470*t^11 + 1471*t^12 - 882*t^13 - 4257*t^14 + 12628*t^15 + O(t^16), t ^-2 + t - 2*t^2 - 2*t^3 + 11*t^4 - 9*t^5 - 18*t^6 + 78*t^7 - 94*t^8 - 175*t^ 9 + 725*t^10 - 676*t^11 - 1603*t^12 + 6293*t^13 + O(t^14)] [1 - x^2 + 2*x^3 - 3*x^4 + O(x^5), x^-2 + x - 2*x^2 + O(x^3)] [1 - t^2 + 2*t^3 - 3*t^4 + O(t^5), t^-2 + t - 2*t^2 + O(t^3)] ellformallog t - 1/3*t^3 + 1/2*t^4 - 3/5*t^5 - t^6 + 23/7*t^7 - 3/2*t^8 - 53/9*t^9 + 16*t ^10 - 131/11*t^11 - 235/6*t^12 + 1471/13*t^13 - 63*t^14 - 1419/5*t^15 + 3157 /4*t^16 + O(t^17) x - 1/3*x^3 + 1/2*x^4 - 3/5*x^5 + O(x^6) t - 1/3*t^3 + 1/2*t^4 - 3/5*t^5 + O(t^6) ellformalexp t + 1/3*t^3 - 1/2*t^4 + 14/15*t^5 - 1/6*t^6 - 76/315*t^7 - 7/10*t^8 + 7547/1 1340*t^9 + 977/3780*t^10 - 5116/22275*t^11 - 78977/113400*t^12 + 3069607/608 1075*t^13 + 1651/2970*t^14 - 526660427/2554051500*t^15 - 5754943993/68108040 00*t^16 + O(t^17) x + 1/3*x^3 - 1/2*x^4 + 14/15*x^5 + O(x^6) t + 1/3*t^3 - 1/2*t^4 + 14/15*t^5 + O(t^6) 242.47010035195076100129810400142304776 0 x^2 - 2 x^2 - 2 [-0.52751724240790530394437835702346995884*I, -0.090507650025885335533571758 708283389896*I] 2 -0.48277875419094304282545632435466338444 0.52578296428738825649865226488368985136 [[16, 61]] [[1, -1], [2, 0], [0, -3]] [[-266/25, 538/125]] [[-36131/400, 361313/8000]] 4186.4576715604358523717788647869484149 [0] [2, -5] [250922/185761, -347287135/80062991] [0] [0] [0] [0, 0] [0, 0] [11432100241/375584400, 1105240264347961/7278825672000] [Mod(1, 19), Mod(14, 19)] 0 -3 -4 -8 -12 -16 -28 -7 -11 -19 -27 -43 -67 -163 *** at top-level: ellK(1) *** ^------- *** ellK: domain error in ellK: k^2 = 1 *** at top-level: ellinit([]) *** ^----------- *** ellinit: incorrect type in ellinit (t_VEC). *** at top-level: ellinit([1,1],quadgen(5)) *** ^------------------------- *** ellinit: incorrect type in elliptic curve base_ring (t_QUAD). *** at top-level: ellinit([Mod(1,2),1],O(2)) *** ^-------------------------- *** ellinit: incorrect type in elliptic curve base_ring (t_VEC). *** at top-level: ellinit([O(2),1],ffgen(2^3)) *** ^---------------------------- *** ellinit: incorrect type in elliptic curve base_ring (t_VEC). *** at top-level: ellinit([O(2),1],1.) *** ^-------------------- *** ellinit: incorrect type in elliptic curve base_ring (t_VEC). *** at top-level: ellinit([ffgen(5),1],3) *** ^----------------------- *** ellinit: inconsistent moduli in ellinit: 3 != 5 *** at top-level: ellinit([1.,Mod(1,3)]) *** ^---------------------- *** ellinit: incorrect type in elliptic curve base_ring (t_VEC). *** at top-level: ellformalw(e,0) *** ^--------------- *** ellformalw: domain error in ellformalw: precision <= 0 *** at top-level: ellformalw(e,-1) *** ^---------------- *** ellformalw: domain error in ellformalw: precision <= 0 *** at top-level: elltwist([0,0]) *** ^--------------- *** elltwist: incorrect type in elltwist (t_VEC). *** at top-level: ellchangepoint([[1,1],1,1],[1,0,0,0]) *** ^------------------------------------- *** ellchangepoint: incorrect type in ellchangepoint (t_INT). *** at top-level: ellpointtoz(e,[1,[0]]) *** ^---------------------- *** ellpointtoz: forbidden addition t_INT + t_VEC (1 elts). *** at top-level: ellpointtoz(E3,[1,[0]]) *** ^----------------------- *** ellpointtoz: incorrect type in ellpointtoz (t_VEC). *** at top-level: ellchangepoint([1],[1,2,3,4]) *** ^----------------------------- *** ellchangepoint: incorrect type in ellchangepoint (t_VEC). *** at top-level: ellchangepoint([1,2,3],[1,2,3,4]) *** ^--------------------------------- *** ellchangepoint: incorrect type in ellchangepoint (t_VEC). *** at top-level: ellchangepointinv([1],[1,2,3,4]) *** ^-------------------------------- *** ellchangepointinv: incorrect type in ellchangepointinv (t_VEC). *** at top-level: ellchangepointinv([1,2,3],[1,2,3,4]) *** ^------------------------------------ *** ellchangepointinv: incorrect type in ellchangepointinv (t_VEC). *** at top-level: ellchangepoint([;],[1,2,3,4]) *** ^----------------------------- *** ellchangepoint: incorrect type in ellchangepoint (t_MAT). *** at top-level: ellchangepointinv([;],[1,2,3,4]) *** ^-------------------------------- *** ellchangepointinv: incorrect type in ellchangepointinv (t_MAT). *** at top-level: ellchangepoint(Mat(1),[1,2,3,4]) *** ^-------------------------------- *** ellchangepoint: incorrect type in ellchangepoint (t_MAT). *** at top-level: ellchangepointinv(Mat(1),[1,2,3,4]) *** ^----------------------------------- *** ellchangepointinv: incorrect type in ellchangepointinv (t_MAT). *** at top-level: ellchangecurve(E,chbug) *** ^----------------------- *** ellchangecurve: incorrect type in checkcoordch (t_VECSMALL). *** at top-level: ellchangepoint([0,0],chbug) *** ^--------------------------- *** ellchangepoint: incorrect type in checkcoordch (t_VECSMALL). *** at top-level: ellchangepointinv([0,0],chbug) *** ^------------------------------ *** ellchangepointinv: incorrect type in checkcoordch (t_VECSMALL). Total time spent: 1340 pari-2.17.2/src/test/32/debugger0000644000175000017500000000772514676526175014723 0ustar billbill echo = 1 ? default(breakloop,1) ? my(bound=100,step=20,halt=41);check(B)=my(bi=[B^2]);for(i=1,bound,my(p=i+step,N=p^2);if(i==halt,error("check:",N))) (B)->my(bound=100,step=20,halt=41);my(bi=[B^2]);for(i=1,bound,my(p=i+step,N= p^2);if(i==halt,error("check:",N))) ? check(1000); *** at top-level: check(1000) *** ^----------- *** in function check: ...i+step,N=p^2);if(i==halt,error("check:",N))) *** ^------------------- *** user error: check:3721 *** Break loop: type 'break' to go back to GP prompt break> [bound,step,halt,i,p,N,bi,B] [100, 20, 41, 41, 61, 3721, [1000000], 1000] break> break ? [bound,step,halt,i,p,N,bi,B] [bound, step, halt, i, p, N, bi, B] ? my(p=120);for(i=1,100,1/0) *** at top-level: my(p=120);for(i=1,100,1/0) *** ^--- *** _/_: impossible inverse in gdiv: 0. *** Break loop: type 'break' to go back to GP prompt break> [p,i] [120, 1] break> dbg_err() error("impossible inverse in gdiv: 0.") break> break ? fun(N)=check(N^2+1); ? fun(20); *** at top-level: fun(20) *** ^------- *** in function fun: check(N^2+1) *** ^------------ *** in function check: ...i+step,N=p^2);if(i==halt,error("check:",N))) *** ^------------------- *** user error: check:3721 *** Break loop: type 'break' to go back to GP prompt break> N 3721 break> dbg_up(4) *** at top-level: fun(20) *** ^------- *** in function fun: check(N^2+1) *** ^------------ break> N 20 break> dbg_down(4) *** at top-level: fun(20) *** ^------- *** in function fun: check(N^2+1) *** ^------------ *** in function check: ...i+step,N=p^2);if(i==halt,error("check:",N))) *** ^------------------- break> N 3721 break> break ? f(N,x)=my(z=x^2+1);breakpoint();gcd(N,z^2+1-z); ? f(221,3) *** at top-level: f(221,3) *** ^-------- *** in function f: my(z=x^2+1);breakpoint();gcd(N,z^2+1-z) *** ^--------------------------- *** Break loop: to continue; 'break' to go back to GP prompt break> z 10 13 ? z z ? iferrname("e_VAR",vector(10000,i,1/(i-100)),E,Vec(E)) *** at top-level: ...("e_VAR",vector(10000,i,1/(i-100)),E,Vec(E)) *** ^------------------- *** _/_: impossible inverse in gdiv: 0. *** Break loop: type 'break' to go back to GP prompt break> i 100 break> break ? f()=1/0 ()->1/0 ? f(); *** at top-level: f() *** ^--- *** in function f: 1/0 *** ^-- *** _/_: impossible inverse in gdiv: 0. *** Break loop: type 'break' to go back to GP prompt break> allocatemem(10^7) *** Warning: new stack size = 10000000 (9.537 Mbytes). ? for(i=1,10,if(i==2,1/0)); *** at top-level: for(i=1,10,if(i==2,1/0)) *** ^---- *** _/_: impossible inverse in gdiv: 0. *** Break loop: type 'break' to go back to GP prompt break> i 2 break> N=5 5 break> M=6;1/0 *** at top-level: for(i=1,10,if(i==2,1/0)) *** ^---- *** in anonymous function: M=6;1/0 *** ^-- *** _/_: impossible inverse in gdiv: 0. *** Break loop: type 'break' to go back to break> break[2]> break *** at top-level: for(i=1,10,if(i==2,1/0)) *** ^---- break> N 5 break> M M break> break ? F1(T)=1/0; ? F1(2) *** at top-level: F1(2) *** ^----- *** in function F1: 1/0 *** ^-- *** _/_: impossible inverse in gdiv: 0. *** Break loop: type 'break' to go back to GP prompt break> dbg_up *** at top-level: F1(2) *** ^----- break> T T break> break ? print("Total time spent: ",gettime); Total time spent: 1 pari-2.17.2/src/test/32/plotexport0000644000175000017500000000071014676526175015342 0ustar billbill" 1 1000 div scale\n1 setlinejoin\n/p {moveto 0 2 rlineto 2 0 " " version='1.1' xmlns='http://www.w3.org/2000/svg'>= x Total time spent: 38 pari-2.17.2/src/test/32/harmonic0000644000175000017500000000050114567450071014706 0ustar billbill0 1 3/2 11/6 7381/2520 1968329/1270080 385 *** this should be a small non-negative integer: harmonic(1.) *** ^--- *** at top-level: harmonic(1,x) *** ^------------- *** harmonic: incorrect type in harmonic (t_POL). Total time spent: 0 pari-2.17.2/src/test/32/size0000644000175000017500000000026414567450071014066 0ustar billbill0 1 1 1 0 3 3 [1, 3] [3, 1] [2, 3] *** at top-level: matsize(1) *** ^---------- *** matsize: incorrect type in matsize (t_INT). 1 1 1 1 Total time spent: 0 pari-2.17.2/src/test/32/mspadic0000644000175000017500000003572514567450071014546 0ustar billbill *** Warning: new stack size = 50000000 (47.684 Mbytes). [2^-1 + 1 + 2^2 + 2^4 + O(2^5), 1 + 2^2 + O(2^4)]~ [2*3^-1 + 1 + 3 + 3^2 + 3^3 + O(3^4), 3^-1 + 1 + 3 + 3^2 + 3^3 + O(3^4)]~ [1 + O(3^5), O(3^5)]~ 4 + 3*5 + 4*5^2 + 2*5^3 + O(5^4) 1 + O(5^4) [1 + O(3^5), O(3^5)]~ [O(2^3), O(2^2)]~ 2^4 + 2^5 + O(2^6) [O(3^10), O(3^10)]~ [2 + 3 + 3^2 + 3^3 + 3^4 + 3^5 + 2*3^6 + O(3^9), 2*3 + 2*3^2 + 2*3^3 + 3^5 + 2*3^8 + O(3^9)]~ [2*5 + 5^2 + 5^4 + O(5^5), 3*5 + 3*5^2 + 2*5^4 + O(5^5)]~ [[[[2031, 1484, 1568, 0, 0]], [[2031, 1960, 1029, 343, 0]], [[2006, 1792, 17 64, 686, 0]], [[2006, 1792, 1764, 686, 0]], [[2031, 1960, 1029, 343, 0]], [[ 2031, 1484, 1568, 0, 0]]], 1 + 5*7 + 7^3 + O(7^4), Vecsmall([7, 4, 4, 1])] [[[[2017, 441, 2009, 0, 0]], [[2017, 2177, 1421, 1372, 0]], [[2009, 1715, 20 58, 0, 0]], [[2009, 1715, 2058, 0, 0]], [[2017, 2177, 1421, 1372, 0]], [[201 7, 441, 2009, 0, 0]]], 4 + 7 + 2*7^3 + O(7^4), Vecsmall([7, 4, 4, 1])] [[[[2184, 720, 117, 1458, 81, 0, 729], [3, 837, 1134, 0, 729, 0, 0]], [[2184 , 720, 117, 1458, 81, 0, 729], [3, 837, 1134, 0, 729, 0, 0]]], [0, 1/36; 1/3 6, 0], Vecsmall([3, 7, 6, 1])] [[[[3, 1617, 980, 0, 0]], [[0, 861, 1764, 686, 0]], [[2398, 1526, 490, 1029, 0]], [[2398, 1526, 490, 1029, 0]], [[0, 861, 1764, 686, 0]], [[3, 1617, 980 , 0, 0]]], 1/6, Vecsmall([7, 4, 4, 1])] [[[[28, 63, 0, 0, 0]], [[28, 63, 0, 0, 0]]], 2 + 2*3 + 3^2 + 3^3 + O(3^4), V ecsmall([3, 4, 4, 29])] [[[[63, 27, 0, 0, 0]], [[63, 27, 0, 0, 0]]], 2 + 3 + 3^2 + 3^3 + O(3^4), Vec small([3, 4, 4, 5])] [[[[1850, 2500, 1250, 0, 0]], [[2500, 125, 0, 0, 0]], [[625, 3000, 0, 0, 0]] , [[1275, 625, 1875, 0, 0]]], 3*5^-1 + 5 + O(5^3), Vecsmall([5, 5, 4, -3])] 0: 2 + 3 + 3^2 + 2*3^3 + 2*3^5 + 3^6 + 3^7 + O(3^10) 3 + 2*3^4 + 2*3^5 + 2*3^6 + O(3^8) 3^4 + 2*3^7 + O(3^8) 3^3 + 2*3^5 + O(3^7) -2: 2 + 2*3 + 2*3^2 + 2*3^4 + 3^6 + 3^7 + 3^8 + 3^9 + O(3^10) 3 + 2*3^3 + 3^4 + 3^5 + 2*3^7 + O(3^8) 3^3 + 2*3^4 + 2*3^6 + 2*3^7 + O(3^8) 3^3 + 2*3^5 + 2*3^6 + O(3^7) [0, 1]: O(3^10) O(3^8) O(3^8) O(3^7) [1, 0]: 2 + 2*3 + 3^3 + 3^4 + 3^6 + 3^8 + O(3^10) 3 + 2*3^3 + 2*3^4 + 2*3^5 + 2*3^6 + 3^7 + O(3^8) 3^3 + 3^5 + 3^6 + 2*3^7 + O(3^8) 3^3 + 2*3^5 + 3^6 + O(3^7) [2, 0]: 2 + 3^3 + 3^4 + 3^6 + 3^8 + 3^9 + O(3^10) 3 + 2*3^3 + 3^4 + 3^5 + 3^7 + O(3^8) 2*3^3 + 2*3^4 + 2*3^6 + O(3^8) 3^3 + O(3^7) 0: [2^-1 + 2 + 2^2 + 2^5 + 2^6 + O(2^9), 2^-1 + 2^2 + 2^3 + 2^6 + 2^7 + O(2^8)] ~ [1 + 2^4 + 2^5 + 2^6 + 2^7 + O(2^8), 1 + 2^2 + 2^3 + 2^5 + O(2^7)]~ [2^2 + 2^4 + 2^5 + O(2^7), 2^2 + 2^3 + 2^4 + 2^5 + O(2^6)]~ [2^4 + O(2^5), O(2^4)]~ -2: [2^-1 + 2^2 + 2^3 + 2^5 + 2^7 + O(2^9), 2^-1 + 2 + 2^3 + 2^5 + 2^6 + O(2^8)] ~ [1 + 2^3 + 2^5 + O(2^8), 1 + 2^2 + 2^4 + 2^5 + 2^6 + O(2^7)]~ [2^2 + 2^4 + O(2^7), 2^2 + 2^3 + 2^4 + 2^5 + O(2^6)]~ [2^4 + O(2^5), O(2^4)]~ [0, 1]: [O(2^9), O(2^8)]~ [O(2^8), O(2^7)]~ [O(2^7), O(2^6)]~ [O(2^5), O(2^4)]~ [1, 0]: [2^-1 + 1 + 2^7 + 2^8 + O(2^9), 2^-1 + 1 + 2 + 2^2 + 2^3 + 2^4 + 2^7 + O(2^8 )]~ [1 + 2^2 + 2^3 + 2^7 + O(2^8), 1 + 2^3 + 2^4 + 2^5 + O(2^7)]~ [2^2 + 2^5 + O(2^7), 2^2 + 2^3 + 2^4 + 2^5 + O(2^6)]~ [2^4 + O(2^5), O(2^4)]~ [2, 0]: [2^-1 + 2^4 + 2^5 + 2^6 + 2^7 + 2^8 + O(2^9), 2^-1 + 2 + 2^2 + 2^3 + 2^4 + O (2^8)]~ [1 + 2^3 + 2^4 + 2^5 + 2^6 + 2^7 + O(2^8), 1 + 2^2 + 2^5 + 2^6 + O(2^7)]~ [2^2 + 2^4 + 2^6 + O(2^7), 2^2 + 2^3 + 2^4 + 2^5 + O(2^6)]~ [2^4 + O(2^5), O(2^4)]~ 0: 5 + 7 + 5*7^2 + 4*7^3 + 7^4 + 2*7^5 + 4*7^6 + 4*7^7 + 2*7^8 + 2*7^9 + O(7^10 ) 5*7 + 2*7^2 + 6*7^3 + 2*7^4 + 2*7^5 + O(7^9) 3*7^2 + 6*7^3 + 3*7^4 + 3*7^5 + 7^7 + 2*7^8 + O(7^9) 6*7^3 + 7^4 + 3*7^5 + 6*7^7 + O(7^9) -2: 3 + 3*7 + 5*7^2 + 4*7^3 + 2*7^4 + 7^5 + 5*7^6 + 4*7^7 + 5*7^8 + 2*7^9 + O(7^ 10) 7 + 4*7^2 + 3*7^3 + 6*7^4 + 4*7^5 + 7^6 + 2*7^7 + 7^8 + O(7^9) 2*7^2 + 2*7^3 + 5*7^4 + 4*7^5 + 6*7^6 + 6*7^7 + 7^8 + O(7^9) 6*7^3 + 6*7^4 + 6*7^5 + 7^6 + 6*7^7 + 4*7^8 + O(7^9) [0, 1]: O(7^10) O(7^9) O(7^9) O(7^9) [1, 0]: 5 + 6*7 + 5*7^2 + 4*7^3 + 6*7^4 + 5*7^5 + 7^6 + 5*7^7 + 2*7^8 + 3*7^9 + O(7^ 10) 5*7 + 5*7^2 + 7^3 + 7^4 + 7^5 + 5*7^6 + 5*7^8 + O(7^9) 3*7^2 + 5*7^3 + 3*7^4 + 7^5 + 2*7^6 + 7^7 + 5*7^8 + O(7^9) 6*7^3 + 4*7^4 + 6*7^5 + 6*7^6 + 3*7^7 + 3*7^8 + O(7^9) [2, 0]: 5 + 4*7 + 2*7^2 + 3*7^3 + 3*7^4 + 4*7^5 + 6*7^6 + 6*7^7 + 5*7^8 + O(7^10) 5*7 + 7^2 + 3*7^3 + 4*7^4 + 6*7^5 + 5*7^6 + 4*7^7 + 6*7^8 + O(7^9) 3*7^2 + 4*7^3 + 6*7^4 + 2*7^5 + 5*7^6 + O(7^9) 6*7^3 + 3*7^5 + 4*7^7 + 4*7^8 + O(7^9) 0: 1 + O(3^10) 2*3 + 2*3^5 + 2*3^6 + O(3^8) 2*3^3 + 3^4 + 2*3^5 + O(3^8) 2*3^3 + 2*3^5 + 2*3^6 + O(3^7) -2: 1 + 2*3 + 2*3^2 + 3^4 + 3^5 + 2*3^6 + 3^7 + 2*3^8 + 2*3^9 + O(3^10) 2*3 + 3^4 + 3^5 + 2*3^6 + 3^7 + O(3^8) 3^3 + 3^4 + 2*3^5 + 3^6 + 3^7 + O(3^8) 2*3^3 + 3^5 + O(3^7) [0, 1]: O(3^10) O(3^8) O(3^8) O(3^7) [1, 0]: 1 + 2*3 + 3^2 + 3^3 + 3^4 + 2*3^5 + 3^6 + 3^7 + 2*3^8 + 3^9 + O(3^10) 2*3 + 2*3^4 + 2*3^6 + 2*3^7 + O(3^8) 3^3 + O(3^8) 2*3^3 + 3^5 + O(3^7) [2, 0]: 1 + 3 + 3^3 + 3^5 + 2*3^6 + 2*3^7 + 3^8 + O(3^10) 2*3 + 2*3^3 + 2*3^5 + 3^6 + O(3^8) 2*3^4 + 3^6 + 2*3^7 + O(3^8) 2*3^3 + 2*3^5 + 3^6 + O(3^7) 0: O(11^10) 4*11 + 3*11^2 + 10*11^3 + 7*11^4 + 5*11^5 + 10*11^6 + 2*11^7 + 9*11^8 + 6*11 ^9 + O(11^10) 5*11^3 + 7*11^4 + 10*11^5 + 6*11^6 + 2*11^7 + 5*11^8 + 2*11^9 + O(11^10) 5*11^3 + 3*11^4 + 11^5 + 2*11^6 + 8*11^8 + 5*11^9 + O(11^10) -2: 6 + 5*11 + 5*11^2 + 2*11^3 + 9*11^4 + 11^5 + 9*11^6 + 7*11^7 + 3*11^8 + 8*11 ^9 + O(11^10) 2*11 + 11^2 + 8*11^3 + 4*11^4 + 4*11^5 + 10*11^6 + 10*11^7 + 11^8 + 8*11^9 + O(11^10) 11^2 + 11^4 + 8*11^5 + 7*11^6 + 5*11^7 + 2*11^8 + 6*11^9 + O(11^10) 7*11^4 + 7*11^5 + 2*11^6 + 9*11^7 + 5*11^8 + 9*11^9 + O(11^10) [0, 1]: O(11^10) O(11^10) O(11^10) O(11^10) [1, 0]: 4*11 + 3*11^2 + 6*11^3 + 8*11^4 + 3*11^5 + 6*11^6 + 11^7 + 4*11^8 + 4*11^9 + O(11^10) 4*11 + 3*11^2 + 11^3 + 6*11^4 + 3*11^5 + 11^6 + 11^7 + 10*11^8 + 8*11^9 + O( 11^10) 10*11^3 + 10*11^4 + 9*11^5 + 5*11^6 + 2*11^7 + 3*11^8 + 9*11^9 + O(11^10) 5*11^3 + 3*11^4 + 8*11^5 + 2*11^6 + 9*11^7 + 2*11^8 + 6*11^9 + O(11^10) [2, 0]: 8*11 + 6*11^2 + 6*11^4 + 2*11^5 + 7*11^7 + 6*11^8 + 9*11^9 + O(11^10) 4*11 + 3*11^2 + 8*11^3 + 7*11^4 + 9*11^5 + 3*11^6 + 2*11^7 + 8*11^8 + 4*11^9 + O(11^10) 4*11^3 + 3*11^4 + 5*11^5 + 4*11^6 + 7*11^7 + 6*11^8 + 8*11^9 + O(11^10) 5*11^3 + 3*11^4 + 4*11^5 + 11^6 + 10*11^7 + 4*11^8 + 5*11^9 + O(11^10) 0: [O(2^10), O(2^9)]~ [O(2^8), O(2^7)]~ [2^5 + 2^6 + O(2^7), 2^5 + O(2^6)]~ [O(2^5), O(2^4)]~ -2: [2^6 + 2^7 + 2^9 + O(2^10), 2^6 + 2^7 + 2^8 + O(2^9)]~ [2^6 + 2^7 + O(2^8), 2^6 + O(2^7)]~ [2^5 + 2^6 + O(2^7), 2^5 + O(2^6)]~ [O(2^5), O(2^4)]~ [0, 1]: [O(2^10), O(2^9)]~ [O(2^8), O(2^7)]~ [O(2^7), O(2^6)]~ [O(2^5), O(2^4)]~ [1, 0]: [2^4 + 2^6 + 2^7 + O(2^10), 2^4 + 2^7 + O(2^9)]~ [O(2^8), O(2^7)]~ [2^5 + O(2^7), 2^5 + O(2^6)]~ [O(2^5), O(2^4)]~ [2, 0]: [2^6 + 2^7 + O(2^10), 2^6 + 2^7 + 2^8 + O(2^9)]~ [2^6 + O(2^8), 2^6 + O(2^7)]~ [2^5 + 2^6 + O(2^7), 2^5 + O(2^6)]~ [O(2^5), O(2^4)]~ [[[[2, 51, 0, 54, 0]], [[79, 30, 0, 27, 0]]], 1 + 2*3 + O(3^4), Vecsmall([3, 4, 4, 5])] [[[[174, 425, 475, 0, 0]], [[172, 400, 300, 0, 0]], [[172, 400, 300, 0, 0]], [[174, 425, 475, 0, 0]]], 3 + 3*5 + 5^2 + O(5^4), Vecsmall([5, 4, 4, -3])] [[[[1467, 5778, 6237, 2430, 5832, 2187, 0, 0, 0]], [[1467, 5778, 6237, 2430, 5832, 2187, 0, 0, 0]]], 2 + 2*3 + 3^2 + 3^3 + 3^4 + 2*3^5 + 3^6 + 3^7 + O(3 ^8), Vecsmall([3, 8, 8, 1])] *** at top-level: Wp=mspadicinit(msinit(25,2,1),5,4,1) *** ^--------------------------------- *** mspadicinit: sorry, mspadicinit when p^2 | N is not yet implemented. *** at top-level: oms=mspadicmoments(Wp,phi) *** ^---------------------- *** mspadicmoments: incorrect type in mstooms [v_p(ap) > mspadicinit flag] (t_VEC). [[28704438, 43044921, 28698258, 43046631, 28697823, 31655514, 40406052, 4241 9955, 42962282, 42910380, 42995952, 43040223, 43042464, 43045218, 43046702, 43046610, 43046643, 43046718, 43046718]~, [43023393, 28707534, 43042941, 286 99164, 43046298, 30101157, 39895767, 42353352, 42893463, 42954543, 43041654, 43035273, 43040547, 43045290, 43046337, 43046703, 43046694, 43046703, 0]~] [[28697958, 0, 43046697, 0, 28697823, 0, 39183249, 0, 43037183, 0, 43045038, 0, 43041006, 0, 43046453, 0, 43046643, 0, 43046718]~, [28709478, 0, 4304650 5, 0, 28697823, 0, 38646180, 0, 42834513, 0, 43030584, 0, 43041276, 0, 43046 382, 0, 0, 0, 0]~] [3^-1 + 1 + 2*3 + 3^2 + 2*3^3 + 2*3^4 + 2*3^5 + 2*3^6 + O(3^7), 2*3^-1 + 2 + 2*3 + 2*3^2 + 3^3 + 2*3^4 + 3^5 + O(3^7)]~ [2 + 2*3 + O(3^9), O(3^9), O(3^9), O(3^9), 1 + 2*3^2 + 2*3^3 + 2*3^4 + 2*3^5 + 2*3^6 + 2*3^7 + 2*3^8 + O(3^9)] [O(3^10), 2 + 2*3 + 2*3^2 + 2*3^3 + 2*3^4 + 2*3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + O(3^10), O(3^10), 2 + 2*3 + 2*3^2 + 2*3^3 + 2*3^4 + 2*3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + O(3^10), O(3^10)] [4*5 + 2*5^2 + 2*5^3 + 2*5^4 + 4*5^5 + 3*5^6 + 4*5^7 + 3*5^8 + 3*5^9 + 2*5^1 0 + 3*5^11 + 4*5^12 + O(5^13), O(5^13), 2 + 4*5^3 + 4*5^4 + 5^5 + 4*5^7 + 3* 5^8 + 5^9 + 4*5^10 + 3*5^12 + O(5^13), O(5^13), 5 + 4*5^2 + 4*5^4 + 3*5^5 + 3*5^6 + 2*5^7 + 5^8 + 4*5^9 + 3*5^11 + 5^12 + O(5^13)] [O(5^13), 1 + 5 + 5^2 + 5^4 + 5^7 + 3*5^8 + 4*5^9 + 2*5^10 + 4*5^11 + 4*5^12 + O(5^13), O(5^13), 3 + 4*5 + 2*5^2 + 5^3 + 5^4 + 3*5^5 + 5^6 + 5^7 + 2*5^8 + 3*5^9 + O(5^13), O(5^13)] [4 + 5 + 3*5^2 + 4*5^4 + 4*5^5 + 3*5^6 + 5^7 + 3*5^8 + 2*5^9 + 3*5^10 + 2*5^ 11 + 4*5^12 + O(5^13), O(5^13), 1 + 4*5 + 5^2 + 5^3 + 4*5^4 + 3*5^5 + 2*5^6 + 2*5^7 + 3*5^8 + 5^10 + 4*5^11 + 3*5^12 + O(5^13), O(5^13), 4 + 2*5 + 3*5^2 + 3*5^3 + 4*5^4 + 3*5^5 + 4*5^7 + 5^8 + 3*5^9 + 4*5^10 + 2*5^11 + 2*5^12 + O(5^13)] [3 + 5*7 + 7^2 + 7^3 + 4*7^4 + 4*7^5 + 3*7^6 + 5*7^7 + 2*7^8 + 3*7^9 + 2*7^1 0 + 6*7^11 + 3*7^12 + 4*7^13 + 5*7^14 + O(7^15), O(7^15), 3 + 4*7 + 5*7^2 + 6*7^3 + 2*7^4 + 7^5 + 7^6 + 4*7^8 + 5*7^10 + 5*7^12 + 4*7^13 + 3*7^14 + O(7^ 15), O(7^15), 6 + 5*7^2 + 4*7^3 + 3*7^4 + 6*7^5 + 7^6 + 2*7^7 + 3*7^8 + 4*7^ 9 + 2*7^11 + 5*7^12 + 7^14 + O(7^15), O(7^15), 3 + 3*7 + 7^2 + 5*7^4 + 3*7^5 + 4*7^6 + 2*7^7 + 6*7^8 + 6*7^10 + 2*7^11 + 7^12 + 3*7^13 + 4*7^14 + O(7^15 )] [O(7^15), 5 + 3*7 + 2*7^2 + 3*7^3 + 4*7^4 + 6*7^5 + 6*7^6 + 2*7^7 + 2*7^8 + 3*7^9 + 5*7^10 + 5*7^11 + 4*7^12 + 2*7^13 + 4*7^14 + O(7^15), O(7^15), 2 + 4 *7^3 + 6*7^4 + 3*7^5 + 7^6 + 3*7^7 + 4*7^8 + 7^9 + 5*7^10 + 3*7^11 + 2*7^12 + 4*7^13 + 5*7^14 + O(7^15), O(7^15), 6 + 5*7 + 7^2 + 4*7^3 + 3*7^4 + 7^5 + 6*7^6 + 7^7 + 5*7^9 + 3*7^10 + 4*7^11 + 3*7^12 + 6*7^13 + 5*7^14 + O(7^15), O(7^15)] [1 + 3 + 3^3 + 3^4 + 2*3^5 + 3^6 + 3^9 + O(3^11), O(3^11), 1 + 3^2 + 2*3^4 + 3^7 + 2*3^8 + 2*3^9 + 2*3^10 + O(3^11)] [1 + 7 + 3*7^2 + 7^3 + 3*7^4 + 5*7^5 + 5*7^6 + 6*7^8 + 7^9 + 5*7^10 + O(7^11 ), O(7^11), 4 + 2*7 + 6*7^2 + 3*7^3 + 3*7^4 + 4*7^5 + 7^6 + 7^7 + 7^9 + 3*7^ 10 + O(7^11)] [O(7^11), 6 + 4*7 + 3*7^2 + 2*7^3 + 6*7^4 + 5*7^5 + 5*7^6 + 6*7^7 + 6*7^8 + 2*7^9 + 2*7^10 + O(7^11), O(7^11)] [7 + 3*7^2 + 7^3 + 3*7^4 + 6*7^5 + 5*7^7 + 2*7^8 + 6*7^9 + 5*7^10 + O(7^11), O(7^11), 5*7 + 6*7^3 + 6*7^4 + 7^5 + 5*7^6 + 7^7 + 3*7^8 + 6*7^9 + 5*7^10 + O(7^11)] [4 + 7 + 4*7^2 + 7^3 + 2*7^5 + 4*7^7 + 4*7^8 + 7^10 + 4*7^11 + 7^12 + O(7^13 ), O(7^13), O(7^13), O(7^13), 5 + 5*7 + 7^2 + 7^3 + 3*7^4 + 3*7^5 + 5*7^6 + 3*7^7 + 2*7^9 + 6*7^10 + 3*7^11 + 4*7^12 + O(7^13)] [O(7^13), 2 + 3*7^2 + 6*7^3 + 5*7^4 + 5*7^6 + 5*7^7 + 6*7^8 + 5*7^9 + 4*7^10 + 5*7^11 + 6*7^12 + O(7^13), O(7^13), 4 + 2*7 + 5*7^2 + 3*7^3 + 3*7^6 + 2*7 ^7 + 6*7^8 + 6*7^9 + 2*7^10 + 2*7^11 + 6*7^12 + O(7^13), O(7^13)] [6*7^2 + 4*7^3 + 2*7^4 + 6*7^5 + 4*7^6 + 2*7^9 + O(7^10), O(7^10), O(7^10), O(7^10), 2*7^2 + 2*7^3 + 6*7^4 + 7^5 + 2*7^6 + 3*7^7 + 3*7^8 + 6*7^9 + O(7^1 0)] [O(7^10), 5*7 + 6*7^2 + 5*7^3 + 3*7^4 + 6*7^5 + 6*7^6 + 6*7^7 + 6*7^8 + 6*7^ 9 + O(7^10), O(7^10), 6*7 + 6*7^2 + 2*7^3 + 5*7^4 + 6*7^5 + 6*7^6 + 6*7^7 + 6*7^8 + 6*7^9 + O(7^10), O(7^10)] [[3^-1 + 1 + 2*3 + 3^2 + 2*3^3 + 2*3^4 + 2*3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3 ^9 + 2*3^10 + 2*3^11 + O(3^12), 2*3^-1 + 2 + 2*3 + 2*3^2 + 3^3 + 2*3^4 + 3^5 + O(3^12)]~, [O(3^12), O(3^12)]~, [3^-2 + 2*3^-1 + 1 + O(3^12), 3^-2 + 3^-1 + 1 + 2*3 + 2*3^3 + 2*3^4 + 2*3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + 2*3^10 + 2*3^11 + O(3^12)]~, [O(3^12), O(3^12)]~, [3^-1 + 2 + 2*3 + 2*3^2 + 2*3^3 + 2*3^4 + 2*3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + 2*3^10 + 2*3^11 + O(3^12), 2*3^-1 + 1 + 3^3 + O(3^12)]~] [[3*5^-1 + 2*5 + 4*5^2 + 4*5^3 + 4*5^4 + 4*5^5 + 4*5^6 + 4*5^7 + 4*5^8 + 4*5 ^9 + 4*5^10 + O(5^11), 3*5^-1 + 3 + 3*5 + 3*5^2 + O(5^13)]~, [O(5^11), O(5^1 3)]~, [3*5^-1 + 1 + O(5^11), 3*5^-1 + 4 + 2*5 + 4*5^2 + 4*5^3 + 4*5^4 + 4*5^ 5 + 4*5^6 + 4*5^7 + 4*5^8 + 4*5^9 + 4*5^10 + 4*5^11 + 4*5^12 + O(5^13)]~] [[2 + 3^2 + 3^4 + 2*3^5 + O(3^13), 2 + 3^4 + 3^6 + 2*3^8 + 3^9 + 2*3^10 + 2* 3^11 + 2*3^12 + 2*3^13 + O(3^14)]~, [O(3^13), O(3^14)]~, [O(3^13), O(3^14)]~ , [O(3^13), O(3^14)]~, [1 + 2*3 + 2*3^2 + 2*3^3 + 2*3^4 + 2*3^5 + 2*3^6 + 2* 3^7 + 2*3^8 + 2*3^9 + 2*3^10 + 2*3^11 + 2*3^12 + O(3^13), 1 + 2*3 + 3^4 + O( 3^14)]~] [[1 + 2 + 2^3 + 2^4 + O(2^18), 2 + 2^2 + 2^4 + 2^5 + 2^6 + 2^8 + 2^11 + 2^12 + 2^13 + 2^14 + 2^15 + 2^16 + 2^17 + O(2^18)]~, [O(2^18), O(2^18)]~, [2^-1 + 1 + 2^2 + 2^4 + 2^7 + 2^8 + 2^11 + 2^12 + 2^15 + 2^16 + O(2^18), 2^-1 + 2 + 2^4 + 2^8 + 2^10 + 2^11 + 2^14 + 2^15 + O(2^18)]~, [O(2^18), O(2^18)]~, [2 ^-1 + 1 + 2 + 2^5 + 2^9 + 2^13 + 2^17 + O(2^18), 2^-1 + 2^2 + 2^5 + 2^7 + 2^ 8 + 2^9 + 2^11 + 2^12 + 2^13 + 2^15 + 2^16 + 2^17 + O(2^18)]~, [O(2^18), O(2 ^18)]~, [1 + 2 + 2^2 + 2^3 + 2^4 + 2^5 + 2^6 + 2^7 + 2^8 + 2^9 + 2^10 + 2^11 + 2^12 + 2^13 + 2^14 + 2^15 + 2^16 + 2^17 + O(2^18), 2 + 2^2 + 2^3 + 2^4 + 2^5 + O(2^18)]~] [[2 + 2^6 + 2^7 + 2^9 + 2^10 + 2^12 + 2^13 + 2^15 + 2^16 + 2^17 + O(2^18), 2 ^4 + 2^5 + 2^6 + 2^8 + 2^11 + 2^12 + 2^15 + O(2^18)]~, [O(2^18), O(2^18)]~, [1 + 2 + 2^4 + 2^5 + 2^6 + 2^8 + 2^9 + 2^10 + 2^12 + 2^14 + 2^16 + O(2^18), 1 + 2 + 2^2 + 2^3 + 2^4 + 2^6 + 2^7 + 2^9 + 2^10 + 2^14 + 2^15 + 2^16 + 2^17 + O(2^18)]~, [O(2^18), O(2^18)]~, [1 + 2 + 2^2 + 2^4 + 2^8 + 2^9 + 2^11 + 2 ^13 + 2^15 + 2^17 + O(2^18), 1 + 2 + 2^4 + 2^7 + 2^10 + 2^12 + 2^13 + 2^14 + 2^15 + 2^16 + 2^17 + O(2^18)]~, [O(2^18), O(2^18)]~, [2 + 2^3 + 2^5 + 2^6 + 2^8 + 2^9 + 2^10 + 2^11 + 2^12 + 2^13 + 2^14 + 2^15 + 2^16 + 2^17 + O(2^18) , 2^4 + 2^5 + 2^9 + 2^11 + 2^13 + O(2^18)]~] [2^6 + O(2^10), O(2^10), 2^6 + 2^8 + O(2^10), O(2^10), 2^6 + O(2^10), O(2^10 ), 2^6 + 2^8 + O(2^10)] [[2*7^-1 + 5 + 7 + 4*7^2 + O(7^17), 5*7^-1 + 5 + 6*7^2 + 5*7^3 + 4*7^4 + 2*7 ^5 + 2*7^7 + 2*7^9 + 6*7^10 + 6*7^11 + 6*7^12 + 6*7^13 + 6*7^14 + 6*7^15 + 6 *7^16 + O(7^17)]~, [O(7^17), O(7^17)]~, [5*7^-2 + 5*7^-1 + 2 + 4*7 + 6*7^2 + 6*7^3 + 6*7^4 + 6*7^5 + 6*7^6 + 6*7^7 + 6*7^8 + 6*7^9 + 6*7^10 + 6*7^11 + 6 *7^12 + 6*7^13 + 6*7^14 + 6*7^15 + 6*7^16 + O(7^17), 4*7^-2 + 1 + 6*7 + 2*7^ 2 + 6*7^3 + 6*7^4 + 6*7^5 + 2*7^6 + O(7^17)]~, [O(7^17), O(7^17)]~, [6*7^-2 + 5*7^-1 + 6*7 + 2*7^2 + 7^3 + 4*7^4 + 5*7^5 + 2*7^6 + 7^7 + 4*7^8 + 5*7^9 + 2*7^10 + 7^11 + 4*7^12 + 5*7^13 + 2*7^14 + 7^15 + 4*7^16 + O(7^17), 2*7^-2 + 7^-1 + 2 + 2*7 + 4*7^2 + 3*7^3 + 4*7^5 + 5*7^6 + 2*7^7 + 7^8 + 4*7^9 + 5*7 ^10 + 2*7^11 + 7^12 + 4*7^13 + 5*7^14 + 2*7^15 + 7^16 + O(7^17)]~, [O(7^17), O(7^17)]~, [6*7^-2 + 6*7^-1 + 4 + 6*7 + 6*7^2 + 6*7^3 + 6*7^4 + 6*7^5 + 6*7 ^6 + 6*7^7 + 6*7^8 + 6*7^9 + 6*7^10 + 6*7^11 + 6*7^12 + 6*7^13 + 6*7^14 + 6* 7^15 + 6*7^16 + O(7^17), 2*7^-2 + 6*7^-1 + 6*7 + 7^2 + 2*7^3 + 2*7^4 + 2*7^5 + O(7^17)]~, [O(7^17), O(7^17)]~, [4*7^-1 + 2 + O(7^17), 3*7^-1 + 5 + 2*7 + 4*7^2 + 7^3 + 4*7^7 + 6*7^8 + 6*7^9 + 6*7^10 + 6*7^11 + 6*7^12 + 6*7^13 + 6 *7^14 + 6*7^15 + 6*7^16 + O(7^17)]~] Total time spent: 9597 pari-2.17.2/src/test/32/polylog0000644000175000017500000000253614676526175014617 0ustar billbill1.0496589501864398696458324932101000704 2.0886953792151632708518141489041442185 - 4.27563394103876217704892645569519 63565*I 4.3226178452644705784020044544722613393 - 2.90951877177225946407469488966471 03179*I [-0.20561675835602830455905189583075314865 - 0.91596559417721901505460351493 238411077*I, -0.20561675835602830455905189583075314865 + 0.91596559417721901 505460351493238411077*I]~ [0.58224052646501250590265632015968010874, 0.7275863077163333895135362968404 8110789] x + 1/4*x^2 + 1/9*x^3 + 1/16*x^4 + O(x^5) 0.58224052646501250590265632015968010874 + 1.3862943611198906188344642429163 531362*x + 0.61370563888010938116553575708364686385*x^2 + 0.5150591481598541 5844595232388847084820*x^3 + 0.56074461109355209566440484750062706103*x^4 + O(x^5) -2.3699397969983658319855374253503230488 0.87901454183427816216335165300236244393 0.34657359027997265470861606072908828404 4.2907022622606505026505656858632022811 E122 320 -x/(x - 1) x/(x^2 - 2*x + 1) *** at top-level: polylog(3,2,5) *** ^-------------- *** polylog: invalid flag in polylog. *** at top-level: polylog(2,Mod(1,2),0) *** ^--------------------- *** polylog: sorry, padic polylogarithm is not yet implemented. *** at top-level: polylog(3,"",0) *** ^--------------- *** polylog: incorrect type in polylog (t_STR). Total time spent: 3 pari-2.17.2/src/test/32/cyclo0000644000175000017500000000370014676526175014235 0ustar billbill *** Warning: new stack size = 8000000 (7.629 Mbytes). *** at top-level: poliscyclo(1) *** ^------------- *** poliscyclo: incorrect type in poliscyclo (t_INT). 0 0 100000 12345 [x - 1, x + 1] [x - 1, x^2 + x + 1] [x - 1, x^2 + 1] [x - 1, x^4 + x^3 + x^2 + x + 1] [x - 1, x^2 - x + 1] [x - 1, x^6 + x^5 + x^4 + x^3 + x^2 + x + 1] [x - 1, x^4 + 1] [x - 1, x^6 + x^3 + 1] [x - 1, x^4 - x^3 + x^2 - x + 1] [x + 1, x^2 + x + 1] [x + 1, x^2 + 1] [x + 1, x^4 + x^3 + x^2 + x + 1] [x + 1, x^2 - x + 1] [x + 1, x^6 + x^5 + x^4 + x^3 + x^2 + x + 1] [x + 1, x^4 + 1] [x + 1, x^6 + x^3 + 1] [x + 1, x^4 - x^3 + x^2 - x + 1] [x^2 + 1, x^2 + x + 1] [x^6 + 2*x^5 + 3*x^4 + 3*x^3 + 3*x^2 + 2*x + 1] [x^4 + x^2 + 1] [x^8 + 2*x^7 + 3*x^6 + 3*x^5 + 3*x^4 + 3*x^3 + 3*x^2 + 2*x + 1] [x^4 + 1, x^2 + x + 1] [x^8 + x^7 + x^6 + x^5 + x^4 + x^3 + x^2 + x + 1] [x^2 + x + 1, x^4 - x^3 + x^2 - x + 1] [x^2 + 1, x^4 + x^3 + x^2 + x + 1] [x^2 + 1, x^2 - x + 1] [x^2 + 1, x^6 + x^5 + x^4 + x^3 + x^2 + x + 1] [x^2 + 1, x^4 + 1] [x^2 + 1, x^6 + x^3 + 1] [x^2 + 1, x^4 - x^3 + x^2 - x + 1] [x^4 + x^3 + x^2 + x + 1, x^2 - x + 1] [x^10 + 2*x^9 + 3*x^8 + 4*x^7 + 5*x^6 + 5*x^5 + 5*x^4 + 4*x^3 + 3*x^2 + 2*x + 1] [x^4 + 1, x^4 + x^3 + x^2 + x + 1] [x^10 + x^9 + x^8 + 2*x^7 + 2*x^6 + x^5 + 2*x^4 + 2*x^3 + x^2 + x + 1] [x^8 + x^6 + x^4 + x^2 + 1] [x^6 + x^5 + x^4 + x^3 + x^2 + x + 1, x^2 - x + 1] [x^4 + 1, x^2 - x + 1] [x^6 + x^3 + 1, x^2 - x + 1] [x^6 - 2*x^5 + 3*x^4 - 3*x^3 + 3*x^2 - 2*x + 1] [x^4 + 1, x^6 + x^5 + x^4 + x^3 + x^2 + x + 1] [x^12 + x^11 + x^10 + 2*x^9 + 2*x^8 + 2*x^7 + 3*x^6 + 2*x^5 + 2*x^4 + 2*x^3 + x^2 + x + 1] [x^6 + x^5 + x^4 + x^3 + x^2 + x + 1, x^4 - x^3 + x^2 - x + 1] [x^4 + 1, x^6 + x^3 + 1] [x^4 + 1, x^4 - x^3 + x^2 - x + 1] [x^6 + x^3 + 1, x^4 - x^3 + x^2 - x + 1] 1 1 1 + 2^2 + 2^3 + 2^6 + 2^7 + 2^10 + 2^11 + 2^14 + 2^15 + 2^18 + 2^19 + O(2^22 ) 1 + 2^4 + 2^5 + 2^6 + 2^7 + 2^12 + 2^13 + 2^14 + 2^15 + 2^20 + 2^21 + 2^22 + O(2^23) Total time spent: 7 pari-2.17.2/src/test/32/trans20000644000175000017500000001531714760123736014332 0ustar billbill5.0431656433600286513118821892854247103 [0.54030230586813971740093660744297660373 - 0.841470984807896506652502321630 29899962*I, 0.54030230586813971740093660744297660373 + 0.8414709848078965066 5250232163029899962*I]~ error("incorrect type in exp (t_STR).") O(2^0) error("impossible inverse in powp: O(2^0).") 0 1 2 + O(x^2) 2.8284271247461900976033774484193961571 + O(x^2) Mod(1, y) + Mod(1/2, y)*x + O(x^2) 2 + 1/4*x + O(x^2) error("domain error in gpow [irrational exponent]: valuation != 0") O(x^0) 1 + 0.50000000000000000000000000000000000000*x + O(x^2) error("overflow in sqrtn [valuation].") error("incorrect type in gpow (t_STR).") error("incorrect type in gpow(0,n) (t_INTMOD).") x^196608 error("overflow in pow_monome [degree].") error("overflow in gpow.") 1.0000000000000000000000000000000000000 0.E-38 1 + 1/2*x - 1/16*x^2 + 1/32*x^3 - 21/1024*x^4 + 31/2048*x^5 - 195/16384*x^6 + 319/32768*x^7 - 34325/4194304*x^8 + 58899/8388608*x^9 + O(x^10) [1.0000000000000000000000000000000000000, 1.45679103104690686918643238326508 19750] 3 + 2*3^2 + 3^3 + O(3^4) error("incorrect type in exp (t_INTMOD).") 1 + O(3^5) 1 + 3 + 3^2 + 2*3^3 + 2*3^4 + O(3^5) 0.54030230586813971740093660744297660373 + 0.8414709848078965066525023216302 9899962*I error("incorrect type in log (t_INTMOD).") error("domain error in Qp_log: argument = 0") O(3^4) 1.5707963267948966192313216916397514421*I error("incorrect type in cos (t_INTMOD).") 1 + O(3^5) 1 + 3^2 + 2*3^4 + O(3^6) 1.5430806348152437784779056207570616826 error("incorrect type in sin (t_INTMOD).") O(3^5) 3 + 3^2 + 3^3 + 2*3^4 + O(3^5) 1.1752011936438014568823818505956008152*I error("incorrect type in tan (t_INTMOD).") O(3^5) 3 + 3^2 + 3^4 + O(3^5) 0.76159415595576488811945828260479359041*I error("incorrect type in cotan (t_INTMOD).") error("impossible inverse in divpp: O(3^5).") 3^-1 + 2 + 3^2 + O(3^3) -1.3130352854993313036361612469308478329*I 0.27175258531951171652884372249858892071 + 1.0839233273386945434757520612119 717214*I -6.4327243140309447361378632346554969618 E-17 -0.45765755436028576375027741043204727643 1.5707963267948966192313216916397514421 + O(x) -1.5707963267948966192313216916397514421 + O(x) 1.5707963267948966192313216916397514421*I + O(x) -1.5707963267948966192313216916397514421*I + O(x) O(x) 1.4142135623730950488016887242096980786*x + O(x^2) 1.3169578969248167086250463473079684440 + 0.57735026918962576450914878050195 745565*x - 0.19245008972987525483638292683398581855*x^2 + O(x^3) O(x) 0.84147098480789650665250232163029899962*I 0.E-38 + 1.0000000000000000000000000000000000000*I 0.E-38 - 1.0000000000000000000000000000000000000*I 0.E-38 - 1.0000000000000000000000000000000000000*I 0.E-38 + 1.0000000000000000000000000000000000000*I 1.6 e-38 4.9 e-39 3.1 e-39 0.e-38 0.e-38 0.e-38 0.e-38 0.e-38 0.e-57 6.3 e-39 0.e-38 0.e-38 0.e-38 4.2 e-39 0.e-38 0.e-38 -0.20484755831421800270211268209700671730 - 1.024400881608445881724860454410 8866770*I 2.2048475583142180027021126820970067173 - 1.02440088160844588172486045441088 66770*I 1.0000000000000000000000000000000000000 + 1.65042575879754287602533772956136 24439*I 1.0000000000000000000000000000000000000 - 1.65042575879754287602533772956136 24439*I 0.15729920705028513065877936491739074071 - 0.4151074974205947033402682494413 3736537*x + 0.41510749742059470334026824944133736537*x^2 + O(x^3) 3 + O(3^2) x + 1/2*x^2 + 1/6*x^3 + 1/24*x^4 + 1/120*x^5 + 1/720*x^6 + 1/5040*x^7 + 1/40 320*x^8 + 1/362880*x^9 + 1/3628800*x^10 + 1/39916800*x^11 + 1/479001600*x^12 + 1/6227020800*x^13 + 1/87178291200*x^14 + 1/1307674368000*x^15 + 1/2092278 9888000*x^16 + O(x^17) O(x) 1.0000000000000000000050000000000000000 E-20 + 1.000000000000000000010000000 0000000000*x + O(x^2) 1.1170000166126746685453698198370956101 1.7182818284590452353602874713526624978 -1.0000000000000000000000000000000000000 -4.7866697272721544799724285830597925865 E-10998741 4.7866697272721544799724285830597925865 E-10998741 x - 1/2*x^2 + 1/3*x^3 - 1/4*x^4 + O(x^5) 9.9999999995000000000333333333308333333 E-11 + 0.999999999900000000009999999 99900000000*x - 0.49999999990000000001499999999800000000*x^2 + 0.33333333323 333333335333333333000000000*x^3 - 0.24999999990000000002499999999500000000*x ^4 + O(x^5) O(x) 9.9999999995000000000333333333308333333 E-11 9.9999999995000000000333333333308333333 E-11 9.9999999999999999999500000000000000000 E-21 9.9999999999999999999333333333433333333 E-11 + 9.999999999000000000066666666 6666666667 E-11*I 9.9999999999999999999999999999999999999 E-21 + 9.999999999999999999900000000 0000000000 E-21*I 4*5 + 3*5^2 + O(5^3) -0.69314718055994530941723212145817656807 -2.0794415416798359282516963643745297042 -3090477397 74.445568222817551305703193915436427255 + 1.58602795576098137135242138363547 30014*I -74.445568222817551305703193915436427255 + 1.5555646978288118671102219996440 298828*I 1 1 1.0000000000000000000000000000000000000 0.95885107720840600054657587043114277616 1101.3232874703393377236524554846364403 0.96671074810035670154056228439966270092 - 0.3317468333156205932854800814081 5291940*I 1 + O(3^2) 1 + 3 + 3^2 + O(3^3) 1 - 1/6*x^2 + 1/120*x^4 - 1/5040*x^6 + 1/362880*x^8 - 1/39916800*x^10 + 1/62 27020800*x^12 - 1/1307674368000*x^14 + O(x^16) 1.0000000000000000000000000000000000000 1 + O(3^4) 1 + (3^-1 + 1 + 3 + O(3^2))*x^2 + (3^-1 + 2 + 2*3 + O(3^2))*x^4 + (3^-2 + 3^ -1 + O(3))*x^6 + (3^-4 + 3^-3 + 3^-2 + O(3^-1))*x^8 + (3^-4 + 2*3^-3 + O(3^- 1))*x^10 + (2*3^-5 + 2*3^-4 + 3^-3 + O(3^-2))*x^12 + (3^-6 + 3^-5 + O(3^-3)) *x^14 + O(x^16) 1 - 1.6449340668482264364724151666460251892*x^2 + 0.811742425283353643637002 77240587592708*x^4 - 0.19075182412208421369647211183579759898*x^6 + 0.026147 847817654800504653261419496157949*x^8 - 0.0023460810354558236375089358411726 226961*x^10 + 0.00014842879303107100368487273566815058771*x^12 - 6.975873661 6563804745344485568159551740 E-6*x^14 + O(x^16) 0.E-2003 exp: [320, 320, 320] expm1: [320, 320, 320] log: [320, 320, 320] arg: [320, 320, 320] cos: [320, 320, 320] sin: [320, 320, 320] tan: [320, 320, 320] cotan: [320, 320, 320] sinc: [320, 320, 320] cosh: [320, 320, 320] sinh: [320, 320, 320] tanh: [320, 320, 320] cotanh: [320, 320, 320] acos: [320, 320, 320] asin: [320, 320, 320] atan: [320, 320, 320] acosh: [320, 320, 320] asinh: [320, 320, 320] atanh: [320, 320, 320] sqrt: [320, 320, 320] (x)->sqrtn(x,3): [320, 320, 320] gamma: [320, 320, 320] lngamma: [320, 320, 320] psi: [320, 320, 320] zeta: [320, 320, 320] -63 -63 -64 -63 *** at top-level: sinc(2+O(3^2)) *** ^-------------- *** sinc: domain error in gsinc(t_PADIC): argument out of range *** at top-level: sinc(1/x) *** ^--------- *** sinc: domain error in sinc: valuation < 0 *** at top-level: atanh(1-2^(-if(sizebyte(0)==16,63,31))) *** ^--------------------------------------- *** atanh: overflow in atanhuu. Total time spent: 15 pari-2.17.2/src/test/32/nfislocalpower0000644000175000017500000000055014567450071016141 0ustar billbill0 1 0 0 0 1 0 1 1 1 1 1 0 0 1 *** at top-level: nfislocalpower(K,"",1,0) *** ^------------------------ *** nfislocalpower: incorrect type in checkprid (t_STR). *** at top-level: nfislocalpower(K,"","",0) *** ^------------------------- *** nfislocalpower: incorrect type in checkprid (t_STR). Total time spent: 9 pari-2.17.2/src/test/32/stark0000644000175000017500000002022614676526175014252 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 2584: x^8 - 2*x^7 - 19*x^6 + 22*x^5 + 112*x^4 - 34*x^3 - 177*x^2 - 62*x + 11 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 + Mo d(1674997/2*y + 40234809/2, y^2 - 577)*x + Mod(-810062*y - 19458357, y^2 - 5 77) [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(781/3*y^2 - 1531/3*y - 7317, y^3 - y^2 - 30*y - 27)*x^2 + Mod(-9385/3*y^2 + 18397/3*y + 87963, y^3 - y^2 - 30*y - 27)*x + Mod(8526*y^2 - 16713*y - 239732, y^3 - y^2 - 30*y - 27) [y^3 - 14*y - 7, 1]: x^3 + Mod(-5*y^2 - 21*y - 10, y^3 - 14*y - 7)*x^2 + Mod (25*y^2 + 98*y + 42, y^3 - 14*y - 7)*x + Mod(-30*y^2 - 119*y - 52, y^3 - 14* y - 7) [y^3 - y^2 - 16*y + 22, 1]: x^3 + Mod(-10*y^2 - 27*y + 60, y^3 - y^2 - 16*y + 22)*x^2 + Mod(171*y^2 + 464*y - 1016, y^3 - y^2 - 16*y + 22)*x + Mod(-715* y^2 - 1940*y + 4234, y^3 - y^2 - 16*y + 22) [y^3 - y^2 - 30*y + 71, 1]: x^3 + Mod(-35*y^2 - 108*y + 604, y^3 - y^2 - 30* y + 71)*x^2 + Mod(194*y^2 + 599*y - 3364, y^3 - y^2 - 30*y + 71)*x + Mod(-25 9*y^2 - 800*y + 4495, y^3 - y^2 - 30*y + 71) [y^3 - y^2 - 16*y - 6, 1]: x^3 + Mod(-11*y^2 + 47*y + 22, y^3 - y^2 - 16*y - 6)*x^2 + Mod(293*y^2 - 1260*y - 532, y^3 - y^2 - 16*y - 6)*x + Mod(-1325*y^ 2 + 5696*y + 2410, y^3 - y^2 - 16*y - 6) [y^3 - 36*y - 45, 1]: x^3 + Mod(-12*y^2 - 78*y - 79, y^3 - 36*y - 45)*x^2 + Mod(1589/3*y^2 + 3469*y + 3642, y^3 - 36*y - 45)*x + Mod(-3038/3*y^2 - 6631* y - 6962, y^3 - 36*y - 45) [y^3 - 12*y - 1, [5, y + 1]]: x^6 + Mod(-2*y^2 - 7*y - 2, y^3 - 12*y - 1)*x^ 5 + Mod(27*y^2 + 94*y + 1, y^3 - 12*y - 1)*x^4 + Mod(-149*y^2 - 521*y - 32, y^3 - 12*y - 1)*x^3 + Mod(410*y^2 + 1439*y + 127, y^3 - 12*y - 1)*x^2 + Mod( -557*y^2 - 1957*y - 178, y^3 - 12*y - 1)*x + Mod(298*y^2 + 1046*y + 89, y^3 - 12*y - 1) [y^3 - y^2 - 37*y + 64, 1]: x^3 + Mod(-20*y^2 - 91*y + 230, y^3 - y^2 - 37*y + 64)*x^2 + Mod(17039/3*y^2 + 25994*y - 195548/3, y^3 - y^2 - 37*y + 64)*x + Mod(-504718*y^2 - 2309993*y + 5792200, y^3 - y^2 - 37*y + 64) [y^3 - y^2 - 9*y + 8, 1]: x^3 + Mod(-y^2 - 3*y, y^3 - y^2 - 9*y + 8)*x^2 + M od(5*y^2 + 12*y - 11, y^3 - y^2 - 9*y + 8)*x + Mod(-6*y^2 - 13*y + 15, y^3 - y^2 - 9*y + 8) [y^3 - 21*y - 35, 1]: x^3 + Mod(-4*y^2 + 12*y + 48, y^3 - 21*y - 35)*x^2 + M od(20*y^2 - 64*y - 219, y^3 - 21*y - 35)*x + Mod(-34*y^2 + 106*y + 381, y^3 - 21*y - 35) [y^3 - y^2 - 16*y + 8, 1]: x^3 + Mod(-3/2*y^2 - 11/2*y, y^3 - y^2 - 16*y + 8 )*x^2 + Mod(10*y^2 + 34*y - 18, y^3 - y^2 - 16*y + 8)*x + Mod(-16*y^2 - 53*y + 32, y^3 - y^2 - 16*y + 8) [y^3 - y^2 - 4*y - 1, 7]: x^9 + Mod(3803*y^2 - 4845*y - 13885, y^3 - y^2 - 4 *y - 1)*x^8 + Mod(-11843718*y^2 + 15087600*y + 43242511, y^3 - y^2 - 4*y - 1 )*x^7 + Mod(2447928994*y^2 - 3118393621*y - 8937617416, y^3 - y^2 - 4*y - 1) *x^6 + Mod(-122752473137*y^2 + 156373216132*y + 448180745635, y^3 - y^2 - 4* y - 1)*x^5 + Mod(2291810549483*y^2 - 2919515812766*y - 8367614391752, y^3 - y^2 - 4*y - 1)*x^4 + Mod(-20378966548367*y^2 + 25960573005885*y + 7440551044 5644, y^3 - y^2 - 4*y - 1)*x^3 + Mod(92972141705228*y^2 - 118436333193067*y - 339449973794721, y^3 - y^2 - 4*y - 1)*x^2 + Mod(-210119040368961*y^2 + 267 668660944174*y + 767164243383345, y^3 - y^2 - 4*y - 1)*x + Mod(1864214244966 95*y^2 - 237480491909325*y - 680642034264572, y^3 - y^2 - 4*y - 1) [y^3 - y^2 - 7*y + 6, [29, y - 13]]: x^7 + Mod(-5*y^2 - 11*y + 7, y^3 - y^2 - 7*y + 6)*x^6 + Mod(143*y^2 + 254*y - 306, y^3 - y^2 - 7*y + 6)*x^5 + Mod(- 1762*y^2 - 3082*y + 3846, y^3 - y^2 - 7*y + 6)*x^4 + Mod(11513*y^2 + 20157*y - 25127, y^3 - y^2 - 7*y + 6)*x^3 + Mod(-39912*y^2 - 69904*y + 87044, y^3 - y^2 - 7*y + 6)*x^2 + Mod(67549*y^2 + 118318*y - 147287, y^3 - y^2 - 7*y + 6 )*x + Mod(-43616*y^2 - 76398*y + 95101, y^3 - y^2 - 7*y + 6) x^4 + Mod(-76380*y - 241536, y^2 - 10)*x^3 + Mod(172310688*y + 544894236, y^ 2 - 10)*x^2 + Mod(-82152672984*y - 259789562496, y^2 - 10)*x + Mod(219125233 728*y + 692934831396, y^2 - 10) x^4 - 15*x^2 + 17 x^22 + Mod(-484*y - 690, y^2 - 2)*x^21 + Mod(262460*y + 371189, y^2 - 2)*x^2 0 + Mod(-74642968*y - 105561124, y^2 - 2)*x^19 + Mod(12359949244*y + 1747960 7892, y^2 - 2)*x^18 + Mod(-1228206324448*y - 1736946041486, y^2 - 2)*x^17 + Mod(72410409996832*y + 102403783874596, y^2 - 2)*x^16 + Mod(-242801944176048 2*y - 3433738024243325, y^2 - 2)*x^15 + Mod(43802607668538096*y + 6194624183 2154430, y^2 - 2)*x^14 + Mod(-404426622619526814*y - 571945614693280489, y^2 - 2)*x^13 + Mod(1808722254066857816*y + 2557919542267385439, y^2 - 2)*x^12 + Mod(-3440199803094615858*y - 4865177218809656977, y^2 - 2)*x^11 + Mod(1808 722254066857816*y + 2557919542267385439, y^2 - 2)*x^10 + Mod(-40442662261952 6814*y - 571945614693280489, y^2 - 2)*x^9 + Mod(43802607668538096*y + 619462 41832154430, y^2 - 2)*x^8 + Mod(-2428019441760482*y - 3433738024243325, y^2 - 2)*x^7 + Mod(72410409996832*y + 102403783874596, y^2 - 2)*x^6 + Mod(-12282 06324448*y - 1736946041486, y^2 - 2)*x^5 + Mod(12359949244*y + 17479607892, y^2 - 2)*x^4 + Mod(-74642968*y - 105561124, y^2 - 2)*x^3 + Mod(262460*y + 37 1189, y^2 - 2)*x^2 + Mod(-484*y - 690, y^2 - 2)*x + Mod(1, y^2 - 2) *** at top-level: ...rinit(bnf,[id[1],[1,1]]);bnrstarkunit(bnr) *** ^----------------- *** bnrstarkunit: domain error in bnrstarkunit: # unramified places != 1 Total time spent: 5000 pari-2.17.2/src/test/32/diffop0000644000175000017500000000077614567450071014373 0ustar billbill(X^11 + 55*X^9 + 990*X^7 + 6930*X^5 + 17325*X^3 + 10395*X)*E Mod(((512*C^8 - 130560*C^6 + 1693440*C^4 - 4838400*C^2 + 3628800)/C^11)*S, S ^2 + (C^2 - 1)) 240*q + 4320*q^2 + 20160*q^3 + 70080*q^4 + 151200*q^5 + 362880*q^6 + 577920* q^7 + 1123200*q^8 + 1635120*q^9 + 2721600*q^10 + 3516480*q^11 + 5886720*q^12 + 6857760*q^13 + 10402560*q^14 + 12700800*q^15 + O(q^16) Mod(1, x^2 - y) Mod(0, x^2 + y) ((Mod(2, 3)*llx + Mod(2, 3))*lx^4 + Mod(1, 3)*lx^2 + Mod(2, 3))/(Mod(1, 3)*l lx^2*lx^6*x^6) Total time spent: 0 pari-2.17.2/src/test/32/map0000644000175000017500000000540114676526175013701 0ustar billbillMap([1, 2; 3, 4; 5, 6]) [1, 3, 5] [5, 3, 1] [1 2] [3 4] [5 6] Map([1, 4; 3, 16; 5, 36]) Map([1, -2; 3, -4; 5, -6]) [1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1] [1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1] -1 0 Map([;]) 0 Map(Mat([2, 3])) [1 List([11, 31, 41, 61, 71])] [2 List([2])] [3 List([3, 13, 23, 43, 53, 73, 83])] [5 List([5])] [7 List([7, 17, 37, 47, 67, 97])] [9 List([19, 29, 59, 79, 89])] *** at top-level: mapget(M,7) *** ^----------- *** mapget: nonexistent component in mapget: index not in map *** at top-level: mapdelete(~M,7) *** ^--------------- *** mapdelete: nonexistent component in mapdelete: index not in map *** at top-level: Vec(M,1) *** ^-------- *** Vec: incorrect type in gtovec (t_LIST). *** at top-level: Vec(M,-1) *** ^--------- *** Vec: incorrect type in gtovec (t_LIST). [Map(Mat([0, 0])), [0, 0, 1]] Map(["a", List([]); "b", List([])]) Map(["a", List([1]); "b", List([])]) Map(["a", List([1, 2]); "b", List([])]) Map(["a", List([1, 2]); "b", List([]); "c", List([3])]) Map(["a", List([1, 2]); "b", List([]); "c", List([3, 4])]) Map(["a", List([1, 2]); "b", List([5]); "c", List([3, 4])]) *** at top-level: maplisterr(~M,"d",6) *** ^-------------------- *** in function maplisterr: mapapply(~M,k,(~y)->listput(~y,v)) *** ^---------------------------------- *** mapapply: nonexistent component in mapapply: index not in map *** at top-level: Map([1,2;2,3;1,3;1,4]) *** ^---------------------- *** Map: domain error in Map: x is not one-to-one *** variable name expected: mapdelete(1,1) *** ^---- *** at top-level: mapdelete(~L,1) *** ^--------------- *** mapdelete: incorrect type in mapdelete (t_LIST). *** at top-level: mapget(1,1) *** ^----------- *** mapget: incorrect type in mapget (t_INT). *** at top-level: mapget(L,1) *** ^----------- *** mapget: incorrect type in mapget (t_LIST). *** at top-level: mapisdefined(1,1) *** ^----------------- *** mapisdefined: incorrect type in mapisdefined (t_INT). *** at top-level: mapisdefined(L,1) *** ^----------------- *** mapisdefined: incorrect type in mapisdefined (t_LIST). *** too few arguments: mapput(1,1) *** ^- *** too few arguments: mapput(~L,1) *** ^- *** at top-level: Map(1) *** ^------ *** Map: incorrect type in Map (t_INT). Total time spent: 16 pari-2.17.2/src/test/32/zn0000644000175000017500000001710014676526175013552 0ustar billbill *** Warning: new stack size = 18000000 (17.166 Mbytes). Mod(1, 2) Mod(3, 4) Mod(5, 9223372036854775837) Mod(5, 85070591730234616400799229995519050569) Mod(5, 170141183460469232801598459991038101138) Mod(5, 170141183460469232801598459991038101138) Mod(5, 170141183460469232801598459991038101138) [2, [2], [-1]] [1, [], []] [4, [4], [Mod(7, 10)]] [6, [6], [Mod(3, 14)]] [216, [36, 6], [Mod(2, 247), Mod(160, 247)]] [216, [36, 6], [Mod(2, 247), Mod(160, 247)]] [216, [36, 6], [Mod(2, 247), Mod(160, 247)]] [2, [2], [-1]] Mod(84, 148) [599, 599, 599, 599] [1000000003700000003419, 1000000003700000003419, 1000000003700000003419, 100 0000003700000003419] [8000000029600000027360, [1000000003700000003420, 2, 2, 2], [697836335347937 5237713, 5000000019000000018049, 15000000057000000054151, 100000000380000000 36101]] [392658269393604457523, 74265827068860445865, 1, 1]~ [392658269393604457523, 74265827068860445865, 1, 1]~ Mod(3, 20000000076000000072200) *** at top-level: znlog(Mod(3,N/2),G) *** ^------------------- *** znlog: inconsistent moduli in Rg_to_Fp: 10000000038000000036100 != 20000000076000000072200 *** at top-level: znlog(G,3) *** ^---------- *** znlog: incorrect type in znlog (t_INT). [] [] [] [] 0 0 [] [] [] 1 48 [] [] [] 194 Mod(1, 2) 945843084768538962295343 34034873 47119348 188202816 error("incorrect type in generic discrete logarithm (order factorization) (t _COMPLEX).") error("incorrect type in generic discrete logarithm (order factorization) (t _INT).") error("incorrect type in generic discrete logarithm (order factorization) (t _MAT).") error("incorrect type in generic discrete logarithm (order factorization) (t _MAT).") [] [[4, 0, 0]] [[0, 3, 0], [0, 2, 0], [0, 1, 0], [0, 0, 0]] [[0, 0, 1], [0, 0, 0]] [[2, 3, 0], [4, 2, 0], [6, 1, 0], [4, 2, 1], [6, 1, 1], [0, 0, 1], [2, 3, 1] , [0, 0, 0]] [[2, 1, 0], [4, 0, 0], [6, 3, 0], [4, 0, 1], [6, 3, 1], [0, 2, 1], [2, 1, 1] , [0, 2, 0]] *** at top-level: bnrchar(bnr,H,[0,1/2,1/2]) *** ^-------------------------- *** bnrchar: incorrect type in bnrchar [inconsistent values] (t_VEC). [[1, 3, 1], [2, 2, 1], [3, 1, 1], [4, 0, 1], [5, 3, 1], [6, 2, 1], [7, 1, 1] , [0, 2, 0], [1, 1, 0], [2, 0, 0], [3, 3, 0], [4, 2, 0], [5, 1, 0], [6, 0, 0 ], [7, 3, 0], [0, 0, 1]] [0, 0] [1, 1] [0, 1] [1, 0] [0, 1, 0, 1] [-1, 1, -1, 1] [[0], [1], [3], [2]] [0, 0] [1, 1] [16, 1] [12, 1] 10 10 10 0 -1 -1 9/10 9/10 9/10 1 2 x x^2 1 [[12, 1], [2, 0]] [[12, 1]] [1, 16]~ [1, 16]~ [1, matrix(0,2)] [25, Mat([5, 2])] 75 75 [1, 1]~ 1:[1, matrix(0,2)]:[]~ 4:[25, Mat([5, 2])]:[2]~ 7:[5, Mat([5, 1])]:[1]~ 13:[25, Mat([5, 2])]:[19]~ 16:[25, Mat([5, 2])]:[4]~ 19:[25, Mat([5, 2])]:[18]~ 22:[25, Mat([5, 2])]:[17]~ 26:[3, Mat([3, 1])]:[1]~ 28:[25, Mat([5, 2])]:[7]~ 31:[25, Mat([5, 2])]:[8]~ 32:[15, [3, 1; 5, 1]]:[1, 1]~ 34:[25, Mat([5, 2])]:[14]~ 37:[25, Mat([5, 2])]:[9]~ 43:[5, Mat([5, 1])]:[3]~ 46:[25, Mat([5, 2])]:[12]~ 49:[5, Mat([5, 1])]:[2]~ 52:[25, Mat([5, 2])]:[1]~ 58:[25, Mat([5, 2])]:[3]~ 61:[25, Mat([5, 2])]:[16]~ 64:[25, Mat([5, 2])]:[6]~ 67:[25, Mat([5, 2])]:[13]~ 68:[15, [3, 1; 5, 1]]:[1, 3]~ 73:[25, Mat([5, 2])]:[11]~ 74:[15, [3, 1; 5, 1]]:[1, 2]~ [[1, matrix(0,2)], []~] [8, [1, 1]~] [8, [0, 1]~] [[4, Mat([2, 2])], [1]~] [[1, matrix(0,2)], []~] [48, [0, 1, 1]~] [[8, Mat([2, 3])], [1, 1]~] [48, [1, 1, 1]~] [[16, Mat([2, 4])], [0, 3]~] [[3, Mat([3, 1])], [1]~] [[16, Mat([2, 4])], [1, 3]~] [[24, [2, 3; 3, 1]], [1, 1, 1]~] [[8, Mat([2, 3])], [0, 1]~] [48, [0, 3, 1]~] [[4, Mat([2, 2])], [1]~] [48, [1, 3, 1]~] [[16, Mat([2, 4])], [0, 1]~] [[24, [2, 3; 3, 1]], [0, 1, 1]~] [[16, Mat([2, 4])], [1, 1]~] [[12, [2, 2; 3, 1]], [1, 1]~] [0, 0, 0]~, [0, 0, 0]~ [0, 1, 0]~, [0, 0, 1]~ [1, 2, 0]~, [0, 0, 0]~ [1, 1, 0]~, [0, 0, 1]~ [0, 3, 0]~, [0, 0, 0]~ [0, 0, 0]~, [0, 0, 1]~ [1, 3, 0]~, [0, 0, 0]~ [1, 2, 0]~, [0, 0, 1]~ [0, 2, 0]~, [0, 0, 0]~ [0, 3, 0]~, [0, 0, 1]~ [1, 0, 0]~, [0, 0, 0]~ [1, 3, 0]~, [0, 0, 1]~ [0, 1, 0]~, [0, 0, 0]~ [0, 2, 0]~, [0, 0, 1]~ [1, 1, 0]~, [0, 0, 0]~ [1, 0, 0]~, [0, 0, 1]~ [[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [10, 0, 0], [10, 1, 0], [10, 0, 1], [10, 1, 1]] [[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0], [1, 1, 0], [1, 0, 1] , [1, 1, 1], [2, 0, 0], [2, 1, 0], [2, 0, 1], [2, 1, 1], [4, 0, 0], [4, 1, 0 ], [4, 0, 1], [4, 1, 1]] [[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [2, 0, 0], [2, 1, 0], [2, 0, 1] , [2, 1, 1], [4, 0, 0], [4, 1, 0], [4, 0, 1], [4, 1, 1]] [[0, 0, 0], [2, 0, 0], [2, 1, 0], [2, 0, 1], [2, 1, 1]] [[5, 0], [5, 1], [5, 2], [5, 3], [10, 1], [20, 1]] [[6, 0], [6, 1], [6, 2], [6, 3], [6, 4], [6, 5], [12, 1], [12, 3], [12, 5], [18, 1], [18, 2], [36, 1]] [] [[]] [[]] [[]] [[]] [] [] 126000 1 125 126000 11 1 []~ 125 [14]~ [[125, Mat([5, 3])], [14]~] [[31500, [2, 2; 3, 2; 5, 3; 7, 1]], [1, 1, 1, 1]~] 1009 82127 [0, 3, 3, 0, 2]~ 1 65501 [] []~ [1, []~] 0 0 0 [0]~ [0]~ [] []~ [[1, matrix(0,2)], []~] -1 -1 0 -1 0 *** at top-level: zncharinduce(G2,[]~,3) *** ^---------------------- *** zncharinduce: domain error in zncharinduce: N % q != 0 [0]~ [0]~ [15, [3, 1; 5, 1]] [11] 45 1.7320508075688772935274463415058723670*I 0 2.2360679774997896964091736687312762354 0 -16.104201132412986864073866738029737749 + 6.3761042876342817490516477498551 864451*I -16.104201132412986864073866738029737749 - 6.3761042876342817490516477498551 864448*I [0, 0, 0, 0, 0, 0, 0, 0, 0, 23.511410091698925166748238185562910744 - 38.042 260651806142884657573335175285736*I, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76.084521303612285769315146670350571472 + 47.0228201833978 50333496476371125821488*I] -4.5898860806696040374567274190849232043 + 24.061025451266108103399220192776 614357*I -4.5898860806696040374567274190849232043 - 24.061025451266108103399220192776 614357*I 0 4.0000000000000000000000000000000000000*I 8 0 [41, 61, 111, 131] [41, 31261, 324611, 506221] *** at top-level: znprimroot(8) *** ^------------- *** znprimroot: domain error in znprimroot: n = 8 *** at top-level: znprimroot(15) *** ^-------------- *** znprimroot: domain error in znprimroot: n = 15 *** at top-level: znprimroot(30) *** ^-------------- *** znprimroot: domain error in znprimroot: n = 15 *** at top-level: znstar(0,1) *** ^----------- *** znstar: sorry, znstar(0,1) is not yet implemented. *** at top-level: znconreychar(G8,2) *** ^------------------ *** znconreychar: elements not coprime in znconreylog: 2 8 *** at top-level: znconreychar(znstar(8),2) *** ^------------------------- *** znconreychar: incorrect type in znconreychar (t_VEC). *** at top-level: znconreyexp(znstar(192,1),[2,8,1,1]~) *** ^------------------------------------- *** znconreyexp: incorrect type in znconreyexp (t_COL). *** at top-level: znsubgroupgenerators([I]) *** ^------------------------- *** znsubgroupgenerators: incorrect type in znsubgroupgenerators (t_VEC). [[1, [0]], [1, [], []], [[]~, Vecsmall([])], [[], [], [;], [], [], []], [;]] *** at top-level: znconreylog(G,"") *** ^----------------- *** znconreylog: incorrect type in znconreylog (t_STR). *** at top-level: znconreylog(G,Mod(0,2)) *** ^----------------------- *** znconreylog: incorrect type in znconreylog (t_INTMOD). *** at top-level: znconreylog(G,[1]) *** ^------------------ *** znconreylog: incorrect type in znconreylog (t_VEC). *** at top-level: znconreylog(G,[1]~) *** ^------------------- *** znconreylog: incorrect type in znconreylog (t_COL). Total time spent: 1872 pari-2.17.2/src/test/32/bnfinit0000644000175000017500000000000011636712103014520 0ustar billbillpari-2.17.2/src/test/32/compat0000644000175000017500000047411714760137411014406 0ustar billbill *** too few arguments: abs() *** ^- *** at top-level: addell() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: addell(e,z1,z2) ===> elladd(e,z1,z2) elladd(E,z1,z2): sum of the points z1 and z2 on elliptic curve E. [] *** at top-level: adj() *** ^----- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: adj(x) ===> matadjoint(x) matadjoint(M,{flag=0}): adjoint matrix of M using Leverrier-Faddeev's algorithm. If flag is 1, computes the characteristic polynomial independently first. *** at top-level: akell() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: akell(e,n) ===> ellak(e,n) ellak(E,n): computes the n-th Fourier coefficient of the L-function of the elliptic curve E (assumes E is an integral model). *** at top-level: algdep2() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: algdep2(x,n,dec) ===> algdep(x,n,dec) algdep(z,k,{flag=0}): algebraic relations up to degree k of z, using lindep([1,z,...,z^(k-1)], flag). *** at top-level: algtobasis() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: algtobasis(nf,x) ===> nfalgtobasis(nf,x) nfalgtobasis(nf,x): transforms the algebraic number x into a column vector on the integral basis nf.zk. *** at top-level: anell() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: anell(e,n) ===> ellan(e,n) ellan(E,n): computes the first n Fourier coefficients of the L-function of the elliptic curve E defined over a number field. *** at top-level: apell() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: apell(e,n) ===> ellap(e,n) ellap(E,{p}): given an elliptic curve E defined over a finite field Fq, return the trace of Frobenius a_p = q+1-#E(Fq); for other fields of definition K, p must define a finite residue field, (p prime for K = Qp or Q; p a maximal ideal for K a number field), return the order of the (nonsingular) reduction of E. *** at top-level: apell2() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: apell2(e,n) ===> ellap(e,n) ellap(E,{p}): given an elliptic curve E defined over a finite field Fq, return the trace of Frobenius a_p = q+1-#E(Fq); for other fields of definition K, p must define a finite residue field, (p prime for K = Qp or Q; p a maximal ideal for K a number field), return the order of the (nonsingular) reduction of E. *** at top-level: apprpadic() *** ^----------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: apprpadic(x,a) ===> padicappr(x,a) padicappr(pol,a): p-adic roots of the polynomial pol congruent to a mod p. *** at top-level: assmat() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: assmat(x) ===> matcompanion(x) matcompanion(x): companion matrix to polynomial x. *** at top-level: basis() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: basis(x) ===> nfbasis(x) nfbasis(T,{&dK}): integral basis of the field Q[a], where a is a root of the polynomial T, using the round 4 algorithm. An argument [T,listP] is possible, where listP is a list of primes or a prime bound, to get an order which is maximal at certain primes only. If present, dK is set to the discriminant of the returned order. *** at top-level: basis2() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: basis2(x) ===> nfbasis(x,2) nfbasis(T,{&dK}): integral basis of the field Q[a], where a is a root of the polynomial T, using the round 4 algorithm. An argument [T,listP] is possible, where listP is a list of primes or a prime bound, to get an order which is maximal at certain primes only. If present, dK is set to the discriminant of the returned order. *** at top-level: basistoalg() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: basistoalg(nf,x) ===> nfbasistoalg(nf,x) nfbasistoalg(nf,x): transforms the column vector x on the integral basis into an algebraic number. *** at top-level: bilhell() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: bilhell(e,z1,z2) ===> ellbil(e,z1,z2) ellbil(E,z1,z2): deprecated alias for ellheight(E,P,Q). *** at top-level: bin() *** ^----- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: bin(x,y) ===> binomial(x,y) binomial(n,{k}): binomial coefficient n*(n-1)...*(n-k+1)/k! defined for k in Z and any n. If k is omitted and n a nonnegative integer, return the vector [binomial(n,0),...,binomial(n,n)]. *** at top-level: boundcf() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: boundcf(x,lmax) ===> contfrac(x,,lmax) contfrac(x,{b},{nmax}): continued fraction expansion of x (x rational,real or rational function). b and nmax are both optional, where b is the vector of numerators of the continued fraction, and nmax is a bound for the number of terms in the continued fraction expansion. *** at top-level: boundfact() *** ^----------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: boundfact(x,lim) ===> factor(x,lim) factor(x,{D}): factorization of x over domain D. If x and D are both integers, return partial factorization, using primes < D. *** at top-level: buchcertify() *** ^------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: buchcertify(bnf) ===> bnfcertify(bnf) bnfcertify(bnf,{flag = 0}): certify the correctness (i.e. remove the GRH) of the bnf data output by bnfinit. If flag is present, only certify that the class group is a quotient of the one computed in bnf (much simpler in general). *** at top-level: buchfu() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: buchgen() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: buchgenforcefu() *** ^---------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: buchgenfu() *** ^----------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: buchimag() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: buchimag(D,c1,c2,g) ===> quadclassunit(D,,[c1,c2,g]) 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. *** at top-level: buchinit() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: buchinit(P) ===> bnfinit(P,2) bnfinit(P,{flag=0},{tech=[]}): compute the necessary data for future use in ideal and unit group computations, including fundamental units if they are not too large. flag and tech are both optional. flag can be any of 0: default, 1: include all data in algebraic form (compact units). See manual for details about tech. *** at top-level: buchinitforcefu() *** ^----------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: buchinitforcefu(P) ===> bnfinit(P,1) bnfinit(P,{flag=0},{tech=[]}): compute the necessary data for future use in ideal and unit group computations, including fundamental units if they are not too large. flag and tech are both optional. flag can be any of 0: default, 1: include all data in algebraic form (compact units). See manual for details about tech. *** at top-level: buchinitfu() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: buchinitfu(P) ===> bnfinit(P) bnfinit(P,{flag=0},{tech=[]}): compute the necessary data for future use in ideal and unit group computations, including fundamental units if they are not too large. flag and tech are both optional. flag can be any of 0: default, 1: include all data in algebraic form (compact units). See manual for details about tech. *** at top-level: buchnarrow() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: buchnarrow(bnf) ===> bnfnarrow(bnf) bnfnarrow(bnf): given a big number field as output by bnfinit, gives as a 3-component vector the structure of the narrow class group. *** at top-level: buchray() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: buchray(bnf,ideal) ===> bnrinit(bnf,ideal) bnrinit(bnf,f,{flag=0},{cycmod}): 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. If the positive integer cycmod is present, only compute the ray class group modulo cycmod-th powers. *** at top-level: buchrayinit() *** ^------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: buchrayinit(bnf,ideal) ===> bnrinit(bnf,ideal) bnrinit(bnf,f,{flag=0},{cycmod}): 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. If the positive integer cycmod is present, only compute the ray class group modulo cycmod-th powers. *** at top-level: buchrayinitgen() *** ^---------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: buchrayinitgen(bnf,ideal) ===> bnrinit(bnf,ideal,1) bnrinit(bnf,f,{flag=0},{cycmod}): 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. If the positive integer cycmod is present, only compute the ray class group modulo cycmod-th powers. *** at top-level: buchreal() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: buchreal(D) ===> quadclassunit(D) 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. *** at top-level: bytesize() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: bytesize(x) ===> sizebyte(x) sizebyte(x): number of bytes occupied by the complete tree of the object x. *** at top-level: cf() *** ^---- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: cf(x) ===> contfrac(x) 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. *** at top-level: cf2() *** ^----- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: cf2(b,x) ===> contfrac(x,b) 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. *** at top-level: changevar() *** ^----------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: char() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: char(x,y) ===> charpoly(x,y) charpoly(A,{v='x},{flag=5}): det(v*Id-A)=characteristic polynomial of the matrix or polmod A. flag is optional and ignored unless A is a matrix; it may be set to 0 (Le Verrier), 1 (Lagrange interpolation), 2 (Hessenberg form), 3 (Berkowitz), 4 (modular) if A is integral, or 5 (default, choose best method). Algorithms 0 (Le Verrier) and 1 (Lagrange) assume that n! is invertible, where n is the dimension of the matrix. *** at top-level: char1() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: char1(x,y) ===> charpoly(x,y,1) charpoly(A,{v='x},{flag=5}): det(v*Id-A)=characteristic polynomial of the matrix or polmod A. flag is optional and ignored unless A is a matrix; it may be set to 0 (Le Verrier), 1 (Lagrange interpolation), 2 (Hessenberg form), 3 (Berkowitz), 4 (modular) if A is integral, or 5 (default, choose best method). Algorithms 0 (Le Verrier) and 1 (Lagrange) assume that n! is invertible, where n is the dimension of the matrix. *** at top-level: char2() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: char2(x,y) ===> charpoly(x,y,2) charpoly(A,{v='x},{flag=5}): det(v*Id-A)=characteristic polynomial of the matrix or polmod A. flag is optional and ignored unless A is a matrix; it may be set to 0 (Le Verrier), 1 (Lagrange interpolation), 2 (Hessenberg form), 3 (Berkowitz), 4 (modular) if A is integral, or 5 (default, choose best method). Algorithms 0 (Le Verrier) and 1 (Lagrange) assume that n! is invertible, where n is the dimension of the matrix. *** at top-level: chell() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: chell(x,y) ===> ellchangecurve(x,y) ellchangecurve(E,v): change data on elliptic curve according to v=[u,r,s,t]. *** at top-level: chptell() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: chptell(x,y) ===> ellchangepoint(x,y) ellchangepoint(x,v): change data on point or vector of points x on an elliptic curve according to v=[u,r,s,t]. *** at top-level: classno() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: classno(x) ===> qfbclassno(x) 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. *** at top-level: classno2() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: classno2(x) ===> qfbclassno(x,1) 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. *** at top-level: coeff() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: coeff(x,s) ===> polcoeff(x,s) polcoeff(x,n,{v}): deprecated alias for polcoef. *** at top-level: compimag() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: compimag(x,y) ===> x*y x*y: product of x and y. *** at top-level: compo() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: compo(x,s) ===> component(x,s) 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 ".". *** at top-level: compositum() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: compositum(pol1,pol2) ===> polcompositum(pol1,pol2) polcompositum(P,Q,{flag=0}): vector of all possible compositums of the number fields defined by the polynomials P and Q; flag is optional, whose binary digits mean 1: output for each compositum, not only the compositum polynomial pol, but a vector [R,a,b,k] where a (resp. b) is a root of P (resp. Q) expressed as a polynomial modulo R, and a small integer k such that al2+k*al1 is the chosen root of R; 2: assume that the number fields defined by P and Q are linearly disjoint. *** at top-level: compositum2() *** ^------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: compositum2(pol1,pol2) ===> polcompositum(pol1,pol2,1) polcompositum(P,Q,{flag=0}): vector of all possible compositums of the number fields defined by the polynomials P and Q; flag is optional, whose binary digits mean 1: output for each compositum, not only the compositum polynomial pol, but a vector [R,a,b,k] where a (resp. b) is a root of P (resp. Q) expressed as a polynomial modulo R, and a small integer k such that al2+k*al1 is the chosen root of R; 2: assume that the number fields defined by P and Q are linearly disjoint. *** at top-level: comprealraw() *** ^------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: comprealraw(x,y) ===> qfbcompraw(x,y) qfbcompraw(x,y): Gaussian composition without reduction of the binary quadratic forms x and y. *** at top-level: conductor() *** ^----------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: conductor(a1) ===> bnrconductor(a1) 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]. *** at top-level: conductorofchar() *** ^----------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: conductorofchar(bnr,chi) ===> bnrconductorofchar(bnr,chi) bnrconductorofchar(bnr,chi): this function is obsolete, use bnrconductor. *** at top-level: convol() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: convol(x,y) ===> serconvol(x,y) serconvol(x,y): convolution (or Hadamard product) of two power series. *** at top-level: core2() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: core2(x) ===> core(x,1) core(n,{flag=0}): unique squarefree integer d dividing n such that n/d is a square. If (optional) flag is nonzero, 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. *** at top-level: coredisc2() *** ^----------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: coredisc2(x) ===> coredisc(x,1) coredisc(n,{flag=0}): discriminant of the quadratic field Q(sqrt(n)). If (optional) flag is nonzero, 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. *** at top-level: cvtoi() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: cvtoi(x) ===> truncate(x,&e) truncate(x,{&e}): truncation of x; when x is a power series,take away the O(X^). If e is present, do not take into account loss of integer part precision, and set e = error estimate in bits. *** at top-level: cyclo() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: cyclo(n) ===> polcyclo(n) polcyclo(n,{a = 'x}): n-th cyclotomic polynomial evaluated at a. *** at top-level: decodefactor() *** ^-------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: decodefactor(fa) ===> factorback(fa) factorback(f,{e}): given a factorization f, gives the factored object 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]. *** at top-level: decodemodule() *** ^-------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: decodemodule(nf,fa) ===> bnfdecodemodule(nf,fa) bnfdecodemodule(nf,m): given a coded module m as in bnrdisclist, gives the true module. *** at top-level: degree() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: degree(x) ===> poldegree(x) poldegree(x,{v}): degree of the polynomial or rational function x with respect to main variable if v is omitted, with respect to v otherwise. For scalar x, return 0 if x is nonzero and -oo otherwise. *** at top-level: denom() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: denom(x) ===> denominator(x) denominator(f,{D}): denominator of f. *** at top-level: deplin() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: deplin(x) ===> lindep(x,-1) lindep(v,{flag=0}): integral linear dependencies between components of v. flag is optional, and can be 0: default, guess a suitable accuracy, or positive: accuracy to use for the computation, in decimal digits. *** at top-level: det() *** ^----- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: det(x) ===> matdet(x) matdet(x,{flag=0}): determinant of the matrix x using an appropriate algorithm depending on the coefficients. If (optional) flag is set to 1, use classical Gaussian elimination (usually worse than the default). *** at top-level: det2() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: det2(x) ===> matdet(x,1) matdet(x,{flag=0}): determinant of the matrix x using an appropriate algorithm depending on the coefficients. If (optional) flag is set to 1, use classical Gaussian elimination (usually worse than the default). *** at top-level: detint() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: detint(x) ===> matdetint(x) matdetint(B): some multiple of the determinant of the lattice generated by the columns of B (0 if not of maximal rank). Useful with mathnfmod. *** at top-level: diagonal() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: diagonal(x) ===> matdiagonal(x) matdiagonal(x): creates the diagonal matrix whose diagonal entries are the entries of the vector x. *** at top-level: disc() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: disc(x) ===> poldisc(x) poldisc(pol,{v}): discriminant of the polynomial pol, with respect to main variable if v is omitted, with respect to v otherwise. *** at top-level: discf() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: discf(x) ===> nfdisc(x) nfdisc(T): discriminant of the number field defined by the polynomial T. An argument [T,listP] is possible, where listP is a list of primes or a prime bound. *** at top-level: discf2() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: discf2(x) ===> nfdisc(x,2) nfdisc(T): discriminant of the number field defined by the polynomial T. An argument [T,listP] is possible, where listP is a list of primes or a prime bound. *** at top-level: discrayabs() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: discrayabs(bnr,subgroup) ===> bnrdisc(bnr,subgroup) bnrdisc(A,{B},{C},{flag=0}): absolute or relative [N,R1,discf] of the field defined by A,B,C. [A,{B},{C}] is of type [bnr], [bnr,subgroup], [bnf, modulus] or [bnf,modulus,subgroup], where bnf is as output by bnfinit, bnr by bnrinit, and subgroup is the HNF matrix of a subgroup of the corresponding ray class group (if omitted, the trivial subgroup). flag is optional whose binary digits mean 1: give relative data; 2: return 0 if modulus is not the conductor. *** at top-level: discrayabscond() *** ^---------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: discrayabscond(bnr) ===> bnrdisc(bnr,,,2) bnrdisc(A,{B},{C},{flag=0}): absolute or relative [N,R1,discf] of the field defined by A,B,C. [A,{B},{C}] is of type [bnr], [bnr,subgroup], [bnf, modulus] or [bnf,modulus,subgroup], where bnf is as output by bnfinit, bnr by bnrinit, and subgroup is the HNF matrix of a subgroup of the corresponding ray class group (if omitted, the trivial subgroup). flag is optional whose binary digits mean 1: give relative data; 2: return 0 if modulus is not the conductor. *** at top-level: discrayabslist() *** ^---------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: discrayabslist(bnf,list) ===> bnrdisclist(bnf,list) bnrdisclist(bnf,bound,{arch}): list of discriminants of ray class fields of all conductors up to norm bound. The ramified Archimedean places are given by arch; all possible values are taken if arch is omitted. Supports the alternative syntax bnrdisclist(bnf,list), where list is as output by ideallist or ideallistarch (with units). *** at top-level: discrayabslistarch() *** ^-------------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: discrayabslistarch(bnf,arch,bound) ===> bnrdisclist(bnf,bound,arch) bnrdisclist(bnf,bound,{arch}): list of discriminants of ray class fields of all conductors up to norm bound. The ramified Archimedean places are given by arch; all possible values are taken if arch is omitted. Supports the alternative syntax bnrdisclist(bnf,list), where list is as output by ideallist or ideallistarch (with units). *** at top-level: discrayabslistarchall() *** ^----------------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: discrayabslistarchall(bnf,bound) ===> bnrdisclist(bnf,bound,,1) bnrdisclist(bnf,bound,{arch}): list of discriminants of ray class fields of all conductors up to norm bound. The ramified Archimedean places are given by arch; all possible values are taken if arch is omitted. Supports the alternative syntax bnrdisclist(bnf,list), where list is as output by ideallist or ideallistarch (with units). *** at top-level: discrayabslistlong() *** ^-------------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: discrayabslistlong(bnf,bound) ===> bnrdisclist(bnf,bound) bnrdisclist(bnf,bound,{arch}): list of discriminants of ray class fields of all conductors up to norm bound. The ramified Archimedean places are given by arch; all possible values are taken if arch is omitted. Supports the alternative syntax bnrdisclist(bnf,list), where list is as output by ideallist or ideallistarch (with units). *** at top-level: discrayrel() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: discrayrel(bnr,subgroup) ===> bnrdisc(bnr,subgroup,,1) bnrdisc(A,{B},{C},{flag=0}): absolute or relative [N,R1,discf] of the field defined by A,B,C. [A,{B},{C}] is of type [bnr], [bnr,subgroup], [bnf, modulus] or [bnf,modulus,subgroup], where bnf is as output by bnfinit, bnr by bnrinit, and subgroup is the HNF matrix of a subgroup of the corresponding ray class group (if omitted, the trivial subgroup). flag is optional whose binary digits mean 1: give relative data; 2: return 0 if modulus is not the conductor. *** at top-level: discrayrelcond() *** ^---------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: discrayrelcond(bnr,subgroup) ===> bnrdisc(bnr,subgroup,,3) bnrdisc(A,{B},{C},{flag=0}): absolute or relative [N,R1,discf] of the field defined by A,B,C. [A,{B},{C}] is of type [bnr], [bnr,subgroup], [bnf, modulus] or [bnf,modulus,subgroup], where bnf is as output by bnfinit, bnr by bnrinit, and subgroup is the HNF matrix of a subgroup of the corresponding ray class group (if omitted, the trivial subgroup). flag is optional whose binary digits mean 1: give relative data; 2: return 0 if modulus is not the conductor. *** at top-level: divres() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: divres(x,y) ===> divrem(x,y) divrem(x,y,{v}): euclidean division of x by y giving as a 2-dimensional column vector the quotient and the remainder, with respect to v (to main variable if v is omitted). *** at top-level: divsum() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: divsum(n,X,expr) ===> sumdiv(n,X,expr) sumdiv(n,X,expr): sum of expression expr, X running over the divisors of n. *** at top-level: eigen() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: eigen(x) ===> mateigen(x) mateigen(x,{flag=0}): complex eigenvectors of the matrix x given as columns of a matrix H. If flag=1, return [L,H], where L contains the eigenvalues and H the corresponding eigenvectors. *** at top-level: euler() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: euler ===> Euler Euler=Euler(): Euler's constant with current precision. *** at top-level: extract() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: extract(x,y) ===> vecextract(x,y) vecextract(x,y,{z}): extraction of the components of the matrix or vector x according to y and z. If z is omitted, y represents columns, otherwise y corresponds to rows and z to columns. y and z can be vectors (of indices), strings (indicating ranges as in "1..10") or masks (integers whose binary representation indicates the indices to extract, from left to right 1, 2, 4, 8, etc.). *** at top-level: fact() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: fact(x) ===> factorial(x) factorial(x): factorial of x, the result being given as a real number. *** at top-level: factcantor() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: factcantor(x,p) ===> factorcantor(x,p) factorcantor(x,p): this function is obsolete, use factormod. *** at top-level: factfq() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: factfq(x,p,a) ===> factorff(x,p,a) factorff(x,{p},{a}): obsolete, use factormod. *** at top-level: factmod() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: factmod(x,p) ===> factormod(x,p) factormod(f,{D},{flag=0}): factors the polynomial f over the finite field defined by the domain D; flag is optional, and can be 0: default or 1: only the degrees of the irreducible factors are given. *** at top-level: factoredbasis() *** ^--------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: factoredbasis(x,p) ===> nfbasis(x,,p) nfbasis(T,{&dK}): integral basis of the field Q[a], where a is a root of the polynomial T, using the round 4 algorithm. An argument [T,listP] is possible, where listP is a list of primes or a prime bound, to get an order which is maximal at certain primes only. If present, dK is set to the discriminant of the returned order. *** at top-level: factoreddiscf() *** ^--------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: factoreddiscf(x,p) ===> nfdisc(x,,p) nfdisc(T): discriminant of the number field defined by the polynomial T. An argument [T,listP] is possible, where listP is a list of primes or a prime bound. *** at top-level: factoredpolred() *** ^---------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: factoredpolred(x,p) ===> polred(x,,p) polred(T,{flag=0}): deprecated, use polredbest. Reduction of the polynomial T (gives minimal polynomials only). The following binary digits of (optional) flag are significant 1: partial reduction, 2: gives also elements. *** at top-level: factoredpolred2() *** ^----------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: factoredpolred2(x,p) ===> polred(x,2,p) polred(T,{flag=0}): deprecated, use polredbest. Reduction of the polynomial T (gives minimal polynomials only). The following binary digits of (optional) flag are significant 1: partial reduction, 2: gives also elements. *** at top-level: factorpadic2() *** ^-------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: factorpadic2(x,p,r) ===> factorpadic(x,p,r,1) factorpadic(pol,p,r): p-adic factorization of the polynomial pol to precision r. *** at top-level: factpol() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: factpol(x,l,hint) ===> factor(x) factor(x,{D}): factorization of x over domain D. If x and D are both integers, return partial factorization, using primes < D. *** at top-level: factpol2() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: factpol2(x,l,hint) ===> factor(x) factor(x,{D}): factorization of x over domain D. If x and D are both integers, return partial factorization, using primes < D. *** at top-level: fibo() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: fibo(x) ===> fibonacci(x) fibonacci(x): Fibonacci number of index x. *** at top-level: fpn() *** ^----- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: fpn(p,n) ===> ffinit(p,n) ffinit(p,n,{v='x}): monic irreducible polynomial of degree n in F_p[v]. *** at top-level: galois() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: galois(x) ===> polgalois(x) polgalois(T): Galois group of the polynomial T (see manual for group coding). Return [n, s, k, name] where n is the group order, s the signature, k the index and name is the GAP4 name of the transitive group. *** at top-level: galoisapply() *** ^------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: galoisapply(nf,aut,x) ===> nfgaloisapply(nf,aut,x) nfgaloisapply(nf,aut,x): apply the Galois automorphism aut to the object x (element or ideal) in the number field nf. *** at top-level: galoisconj() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: galoisconj(nf) ===> nfgaloisconj(nf) nfgaloisconj(nf,{flag=0},{d}): list of conjugates of a root of the polynomial x=nf.pol in the same number field. flag is optional (set to 0 by default), meaning 0: use combination of flag 4 and 1, always complete; 1: use nfroots; 4: use Allombert's algorithm, complete if the field is Galois of degree <= 35 (see manual for details). nf can be simply a polynomial. *** at top-level: galoisconj1() *** ^------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: galoisconj1(nf) ===> nfgaloisconj(nf,2) nfgaloisconj(nf,{flag=0},{d}): list of conjugates of a root of the polynomial x=nf.pol in the same number field. flag is optional (set to 0 by default), meaning 0: use combination of flag 4 and 1, always complete; 1: use nfroots; 4: use Allombert's algorithm, complete if the field is Galois of degree <= 35 (see manual for details). nf can be simply a polynomial. *** at top-level: galoisconjforce() *** ^----------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: galoisconjforce ===> nfgaloisconj(nf,1) nfgaloisconj(nf,{flag=0},{d}): list of conjugates of a root of the polynomial x=nf.pol in the same number field. flag is optional (set to 0 by default), meaning 0: use combination of flag 4 and 1, always complete; 1: use nfroots; 4: use Allombert's algorithm, complete if the field is Galois of degree <= 35 (see manual for details). nf can be simply a polynomial. *** at top-level: gamh() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: gamh(x) ===> gammah(x) gammah(x): gamma of x+1/2 (x integer). *** at top-level: gauss() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: gauss(a,b) ===> matsolve(a,b) matsolve(M,B): solution of MX=B (M matrix, B column vector or matrix). *** at top-level: gaussmodulo() *** ^------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: gaussmodulo(M,D,Y) ===> matsolvemod(M,D,Y) matsolvemod(M,D,B,{flag=0}): one solution of system of congruences MX=B mod D (M matrix, B and D column vectors). If (optional) flag is nonzero return all solutions. *** at top-level: gaussmodulo2() *** ^-------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: gaussmodulo2(M,D,Y) ===> matsolvemod(M,D,Y,1) matsolvemod(M,D,B,{flag=0}): one solution of system of congruences MX=B mod D (M matrix, B and D column vectors). If (optional) flag is nonzero return all solutions. *** at top-level: globalred() *** ^----------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: globalred(x,y) ===> ellglobalred(x,y) ellglobalred(E): E being an elliptic curve over a number field, returns [N, v, c, faN, L], where N is the conductor of E, c is the product of the local Tamagawa numbers c_p, faN is the factorization of N and L[i] is elllocalred(E, faN[i,1]); v is an obsolete field. *** at top-level: goto() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: hclassno() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: hclassno(x) ===> qfbhclassno(x) qfbhclassno(x): Hurwitz-Kronecker class number of x>0. *** at top-level: hell() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: hell(e,x) ===> ellheight(e,x) ellheight(E,{P},{Q}): Faltings height of the curve E, resp. canonical height of the point P on elliptic curve E, resp. the value of the attached bilinear form at (P,Q). *** at top-level: hell2() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: hell2(e,x) ===> ellheight(e,x,1) ellheight(E,{P},{Q}): Faltings height of the curve E, resp. canonical height of the point P on elliptic curve E, resp. the value of the attached bilinear form at (P,Q). *** at top-level: hermite() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: hermite(x) ===> mathnf(x) mathnf(M,{flag=0}): (upper triangular) Hermite normal form of M, basis for the lattice formed by the columns of M. Basic values of flag are 0 (default): only return the Hermite normal form H, 1: return [H,U] such that H is the HNF of M, and U is an invertible matrix such that MU=H. These two use a naive algorithm; larger values of flag correspond to more involved algorithms and are restricted to integer matrices; flag = 4: returns [H,U] using LLL reduction along the way; flag = 5: return [H,U,P] where P is a permutation of row indices such that P applied to M U is H. *** at top-level: hermite2() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: hermite2(x) ===> mathnf(x,1) mathnf(M,{flag=0}): (upper triangular) Hermite normal form of M, basis for the lattice formed by the columns of M. Basic values of flag are 0 (default): only return the Hermite normal form H, 1: return [H,U] such that H is the HNF of M, and U is an invertible matrix such that MU=H. These two use a naive algorithm; larger values of flag correspond to more involved algorithms and are restricted to integer matrices; flag = 4: returns [H,U] using LLL reduction along the way; flag = 5: return [H,U,P] where P is a permutation of row indices such that P applied to M U is H. *** at top-level: hermitehavas() *** ^-------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: hermitemod() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: hermitemod(x,d) ===> mathnfmod(x,d) mathnfmod(x,d): (upper triangular) Hermite normal form of x, basis for the lattice formed by the columns of x, where d is a multiple of the nonzero determinant of this lattice. *** at top-level: hermitemodid() *** ^-------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: hermitemodid(x,d) ===> mathnfmodid(x,d) mathnfmodid(x,d): (upper triangular) Hermite normal form of x concatenated with matdiagonal(d). *** at top-level: hermiteperm() *** ^------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: hermiteperm(x) ===> mathnf(x,3) mathnf(M,{flag=0}): (upper triangular) Hermite normal form of M, basis for the lattice formed by the columns of M. Basic values of flag are 0 (default): only return the Hermite normal form H, 1: return [H,U] such that H is the HNF of M, and U is an invertible matrix such that MU=H. These two use a naive algorithm; larger values of flag correspond to more involved algorithms and are restricted to integer matrices; flag = 4: returns [H,U] using LLL reduction along the way; flag = 5: return [H,U,P] where P is a permutation of row indices such that P applied to M U is H. *** at top-level: hess() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: hess(x) ===> mathess(x) mathess(x): Hessenberg form of x. *** at top-level: hilb() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: hilb(x,y) ===> hilbert(x,y) hilbert(x,y,{p}): Hilbert symbol at p of x,y. *** at top-level: hilbp() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: hilbp(x,y,p) ===> hilbert(x,y,p) hilbert(x,y,{p}): Hilbert symbol at p of x,y. *** at top-level: hvector() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: hvector(n,X,expr) ===> vector(n,X,expr) vector(n,{X},{expr=0}): row vector with n components of expression expr (X ranges from 1 to n). By default, fills with 0s. *** at top-level: i() *** ^--- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: i ===> I I=I(): square root of -1. *** at top-level: idealaddmultone() *** ^----------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: idealaddmultone(nf,list) ===> idealaddtoone(nf,list) idealaddtoone(nf,x,{y}): if y is omitted, when the sum of the ideals in the number field K defined by nf and given in the vector x is equal to Z_K, gives a vector of elements of the corresponding ideals who sum to 1. Otherwise, x and y are ideals, and if they sum up to 1, find one element in each of them such that the sum is 1. *** at top-level: idealaddone() *** ^------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: idealaddone(nf,x,y) ===> idealaddtoone(nf,x,y) idealaddtoone(nf,x,{y}): if y is omitted, when the sum of the ideals in the number field K defined by nf and given in the vector x is equal to Z_K, gives a vector of elements of the corresponding ideals who sum to 1. Otherwise, x and y are ideals, and if they sum up to 1, find one element in each of them such that the sum is 1. *** at top-level: idealapprfact() *** ^--------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: idealapprfact(nf,x) ===> idealappr(nf,x,1) idealappr(nf,x,{flag}): 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; x may also be a prime ideal factorization with possibly zero exponents. flag is deprecated (ignored), kept for backward compatibility. *** at top-level: idealdivexact() *** ^--------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: idealdivexact(nf,x,y) ===> idealdiv(nf,x,y,1) idealdiv(nf,x,y,{flag=0}): quotient x/y of two ideals x and y in HNF in the number field nf. If (optional) flag is nonzero, the quotient is supposed to be an integral ideal (slightly faster). *** at top-level: idealhermite() *** ^-------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: idealhermite(nf,x) ===> idealhnf(nf,x) idealhnf(nf,u,{v}): hermite normal form of the ideal u in the number field nf if v is omitted. If called as idealhnf(nf,u,v), the ideal is given as uZ_K + vZ_K in the number field K defined by nf. *** at top-level: idealhermite2() *** ^--------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: idealhermite2(nf,x) ===> idealhnf(nf,x) idealhnf(nf,u,{v}): hermite normal form of the ideal u in the number field nf if v is omitted. If called as idealhnf(nf,u,v), the ideal is given as uZ_K + vZ_K in the number field K defined by nf. *** at top-level: idealinv2() *** ^----------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: idealinv2(nf,x) ===> idealinv(nf,x,1) idealinv(nf,x): inverse of the ideal x in the number field nf. *** at top-level: ideallistarchgen() *** ^------------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: ideallistarchgen(nf,list,arch) ===> ideallistarch(nf,list,arch) ideallistarch(nf,list,arch): list is a vector of vectors of bid's as output by ideallist. Return a vector of vectors with the same number of components as the original list. The leaves give information about moduli whose finite part is as in original list, in the same order, and Archimedean part is now arch. The information contained is of the same kind as was present in the input. *** at top-level: ideallistunit() *** ^--------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: ideallistunit(nf,list) ===> ideallist(nf,list,2) ideallist(nf,bound,{flag=4}): vector of vectors L of all idealstar of all ideals of norm<=bound. If (optional) flag is present, its binary digits are toggles meaning 1: give generators; 2: add units; 4: give only the ideals and not the bid; 8: omit ideals which cannot be conductors. *** at top-level: ideallistunitarch() *** ^------------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: ideallistunitarch ===> ideallistarch(nf,list,arch) ideallistarch(nf,list,arch): list is a vector of vectors of bid's as output by ideallist. Return a vector of vectors with the same number of components as the original list. The leaves give information about moduli whose finite part is as in original list, in the same order, and Archimedean part is now arch. The information contained is of the same kind as was present in the input. *** at top-level: ideallistunitarchgen() *** ^---------------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: ideallistunitarchgen ===> ideallistarch(nf,list,arch) ideallistarch(nf,list,arch): list is a vector of vectors of bid's as output by ideallist. Return a vector of vectors with the same number of components as the original list. The leaves give information about moduli whose finite part is as in original list, in the same order, and Archimedean part is now arch. The information contained is of the same kind as was present in the input. *** at top-level: ideallistunitgen() *** ^------------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: ideallistunitgen ===> ideallist(nf,list,3) ideallist(nf,bound,{flag=4}): vector of vectors L of all idealstar of all ideals of norm<=bound. If (optional) flag is present, its binary digits are toggles meaning 1: give generators; 2: add units; 4: give only the ideals and not the bid; 8: omit ideals which cannot be conductors. *** at top-level: ideallistzstar() *** ^---------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: ideallistzstar(nf,bound) ===> ideallist(nf,bound) ideallist(nf,bound,{flag=4}): vector of vectors L of all idealstar of all ideals of norm<=bound. If (optional) flag is present, its binary digits are toggles meaning 1: give generators; 2: add units; 4: give only the ideals and not the bid; 8: omit ideals which cannot be conductors. *** at top-level: ideallistzstargen() *** ^------------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: ideallistzstargen(nf,bound) ===> ideallist(nf,bound,1) ideallist(nf,bound,{flag=4}): vector of vectors L of all idealstar of all ideals of norm<=bound. If (optional) flag is present, its binary digits are toggles meaning 1: give generators; 2: add units; 4: give only the ideals and not the bid; 8: omit ideals which cannot be conductors. *** at top-level: ideallllred() *** ^------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: ideallllred(nf,x,vdir) ===> idealred(nf,x,vdir) idealred(nf,I,{v=0}): LLL reduction of the ideal I in the number field nf along direction v, in HNF. *** at top-level: idealmulred() *** ^------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: idealmulred(nf,x,y) ===> idealmul(nf,x,y,1) idealmul(nf,x,y,{flag=0}): product of the two ideals x and y in the number field nf. If (optional) flag is nonzero, reduce the result. *** at top-level: idealpowred() *** ^------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: idealpowred(nf,x,y) ===> idealpow(nf,x,y,1) idealpow(nf,x,k,{flag=0}): k-th power of the ideal x in HNF in the number field nf. If (optional) flag is nonzero, reduce the result. *** at top-level: idealtwoelt2() *** ^-------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: idealtwoelt2(nf,x,a) ===> idealtwoelt(nf,x,a) idealtwoelt(nf,x,{a}): two-element representation of an ideal x in the number field nf. If (optional) a is nonzero, first element will be equal to a. *** at top-level: idmat() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: idmat(n) ===> matid(n) matid(n): identity matrix of order n. *** at top-level: image() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: image(x) ===> matimage(x) matimage(x,{flag=0}): basis of the image of the matrix x. flag is optional and can be set to 0 or 1, corresponding to two different algorithms. *** at top-level: image2() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: image2(x) ===> matimage(x,1) matimage(x,{flag=0}): basis of the image of the matrix x. flag is optional and can be set to 0 or 1, corresponding to two different algorithms. *** at top-level: imagecompl() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: imagecompl(x) ===> matimagecompl(x) matimagecompl(x): vector of column indices not corresponding to the indices given by the function matimage. *** at top-level: incgam1() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: incgam2() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: incgam3() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: incgam4() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: incgam4(s,x,y) ===> incgam(s,x,y) incgam(s,x,{g}): incomplete gamma function. g is optional and is the precomputed value of gamma(s). *** at top-level: indexrank() *** ^----------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: indexrank(x) ===> matindexrank(x) matindexrank(M): gives two extraction vectors (rows and columns) for the matrix M such that the extracted matrix is square of maximal rank. *** at top-level: indsort() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: indsort(x) ===> vecsort(x,,1) vecsort(x,{cmpf},{flag=0}): sorts the vector x in ascending order, according to the comparison function cmpf, if not omitted. Binary digits of flag (if present) mean: 1: indirect sorting, return the permutation instead of the permuted vector, 4: use descending instead of ascending order, 8: remove duplicate entries. *** at top-level: initalg() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: initalg(pol) ===> nfinit(pol) nfinit(pol,{flag=0}): pol being a nonconstant irreducible polynomial in Q[X], returns an nf structure attached to the number field Q[X] / (pol). Binary digits of flag mean 1: two-element vector [nf,Mod(a,P)], where Mod(a,P) is a polmod equal to Mod(x,pol) and P=nf.pol; 2: first use polredbest to find a simpler polynomial P; 4: do not LLL-reduce the maximal order basis nf.zk. *** at top-level: initalgred() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: initalgred(x) ===> nfinit(x,2) nfinit(pol,{flag=0}): pol being a nonconstant irreducible polynomial in Q[X], returns an nf structure attached to the number field Q[X] / (pol). Binary digits of flag mean 1: two-element vector [nf,Mod(a,P)], where Mod(a,P) is a polmod equal to Mod(x,pol) and P=nf.pol; 2: first use polredbest to find a simpler polynomial P; 4: do not LLL-reduce the maximal order basis nf.zk. *** at top-level: initalgred2() *** ^------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: initalgred2(x) ===> nfinit(x,3) nfinit(pol,{flag=0}): pol being a nonconstant irreducible polynomial in Q[X], returns an nf structure attached to the number field Q[X] / (pol). Binary digits of flag mean 1: two-element vector [nf,Mod(a,P)], where Mod(a,P) is a polmod equal to Mod(x,pol) and P=nf.pol; 2: first use polredbest to find a simpler polynomial P; 4: do not LLL-reduce the maximal order basis nf.zk. *** at top-level: initell() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: initell(x) ===> ellinit(x) ellinit(x,{D=1}): let x be a vector [a1,a2,a3,a4,a6], or [a4,a6] if a1=a2=a3=0, defining the curve Y^2 + a1.XY + a3.Y = X^3 + a2.X^2 + a4.X + a6; x can also be a string, in which case the curve with matching name is retrieved from the elldata database, if available. This function initializes an elliptic curve over the domain D (inferred from coefficients if omitted). *** at top-level: initzeta() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: integ() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: integ(x,y) ===> intformal(x,y) intformal(x,{v}): formal integration of x with respect to v, or to the main variable of x if v is omitted. *** at top-level: intersect() *** ^----------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: intersect(x,y) ===> matintersect(x,y) matintersect(x,y): intersection of the vector spaces whose bases are the columns of x and y. *** at top-level: intgen() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: intgen(x=a,b,s) ===> intnum(x=a,b,s,1) intnum(X=a,b,expr,{tab}): numerical integration of expr from a to b with respect to X. Plus/minus infinity is coded as +oo/-oo. Finally tab is either omitted (let the program choose the integration step), a nonnegative integer m (divide integration step by 2^m), or data precomputed with intnuminit. *** at top-level: intinf() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: intinf(x=a,b,s) ===> intnum(x=a,b,s,2) intnum(X=a,b,expr,{tab}): numerical integration of expr from a to b with respect to X. Plus/minus infinity is coded as +oo/-oo. Finally tab is either omitted (let the program choose the integration step), a nonnegative integer m (divide integration step by 2^m), or data precomputed with intnuminit. *** at top-level: intopen() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: intopen(x=a,b,s) ===> intnum(x=a,b,s,3) intnum(X=a,b,expr,{tab}): numerical integration of expr from a to b with respect to X. Plus/minus infinity is coded as +oo/-oo. Finally tab is either omitted (let the program choose the integration step), a nonnegative integer m (divide integration step by 2^m), or data precomputed with intnuminit. *** at top-level: inverseimage() *** ^-------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: inverseimage(x,y) ===> matinverseimage(x,y) matinverseimage(x,y): an element of the inverse image of the vector y by the matrix x if one exists, the empty vector otherwise. *** at top-level: isdiagonal() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: isdiagonal(x) ===> matisdiagonal(x) matisdiagonal(x): true(1) if x is a diagonal matrix, false(0) otherwise. *** at top-level: isfund() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: isfund(x) ===> isfundamental(x) isfundamental(D): true(1) if D is a fundamental discriminant (including 1), false(0) if not. *** at top-level: isideal() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: isideal(nf,x) ===> nfisideal(nf,x) nfisideal(nf,x): true(1) if x is an ideal in the number field nf, false(0) if not. *** at top-level: isincl() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: isincl(x,y) ===> nfisincl(x,y) nfisincl(f,g,{flag=0}): let f and g define number fields, either irreducible rational polynomials or number fields as output by nfinit; tests whether the number field f is isomorphic to a subfield of g. Return 0 if not, and otherwise all the embeddings (flag=0, default), only one (flag=1), or all embeddings as rational functions (flag=2). *** at top-level: isinclfast() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: isinclfast(nf1,nf2) ===> nfisincl(nf1,nf2,1) nfisincl(f,g,{flag=0}): let f and g define number fields, either irreducible rational polynomials or number fields as output by nfinit; tests whether the number field f is isomorphic to a subfield of g. Return 0 if not, and otherwise all the embeddings (flag=0, default), only one (flag=1), or all embeddings as rational functions (flag=2). *** at top-level: isirreducible() *** ^--------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: isirreducible(x) ===> polisirreducible(x) polisirreducible(pol): true(1) if pol is an irreducible nonconstant polynomial, false(0) if pol is reducible or constant. *** at top-level: isisom() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: isisom(x,y) ===> nfisisom(x,y) nfisisom(f,g): as nfisincl but tests whether f is isomorphic to g. *** at top-level: isisomfast() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: isisomfast(x,y) ===> nfisisom(x,y) nfisisom(f,g): as nfisincl but tests whether f is isomorphic to g. *** at top-level: isoncurve() *** ^----------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: isoncurve(e,x) ===> ellisoncurve(e,x) ellisoncurve(E,z): true(1) if z is on elliptic curve E, false(0) if not. *** at top-level: isprincipal() *** ^------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: isprincipal(bnf,x) ===> bnfisprincipal(bnf,x,0) bnfisprincipal(bnf,x,{flag=1}): bnf being output by bnfinit, gives [e,t], where e is the vector of exponents on the class group generators and t is the generator of the resulting principal ideal. In particular x is principal if and only if e is the zero vector. flag is optional, whose binary digits mean 1: output [e,t] (only e if unset); 2: increase precision until t can be computed (do not insist if unset); 4: return t in factored form (compact representation). *** at top-level: isprincipalforce() *** ^------------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: isprincipalforce(bnf,x) ===> bnfisprincipal(bnf,x,2) bnfisprincipal(bnf,x,{flag=1}): bnf being output by bnfinit, gives [e,t], where e is the vector of exponents on the class group generators and t is the generator of the resulting principal ideal. In particular x is principal if and only if e is the zero vector. flag is optional, whose binary digits mean 1: output [e,t] (only e if unset); 2: increase precision until t can be computed (do not insist if unset); 4: return t in factored form (compact representation). *** at top-level: isprincipalgen() *** ^---------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: isprincipalgen(bnf,x) ===> bnfisprincipal(bnf,x) bnfisprincipal(bnf,x,{flag=1}): bnf being output by bnfinit, gives [e,t], where e is the vector of exponents on the class group generators and t is the generator of the resulting principal ideal. In particular x is principal if and only if e is the zero vector. flag is optional, whose binary digits mean 1: output [e,t] (only e if unset); 2: increase precision until t can be computed (do not insist if unset); 4: return t in factored form (compact representation). *** at top-level: isprincipalgenforce() *** ^--------------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: isprincipalgenforce(bnf,x) ===> bnfisprincipal(bnf,x,3) bnfisprincipal(bnf,x,{flag=1}): bnf being output by bnfinit, gives [e,t], where e is the vector of exponents on the class group generators and t is the generator of the resulting principal ideal. In particular x is principal if and only if e is the zero vector. flag is optional, whose binary digits mean 1: output [e,t] (only e if unset); 2: increase precision until t can be computed (do not insist if unset); 4: return t in factored form (compact representation). *** at top-level: isprincipalray() *** ^---------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: isprincipalray(bnf,x) ===> bnrisprincipal(bnf,x) bnrisprincipal(bnr,x,{flag=1}): bnr being output by bnrinit and x being an ideal coprime to bnr.mod, returns [v,alpha], where v is the vector of exponents on the ray class group generators and alpha is the generator of the resulting principal ideal. If (optional) flag is set to 0, output only v. *** at top-level: isprincipalraygen() *** ^------------------- *** not a function in function call *** at top-level: ispsp() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: ispsp(x) ===> ispseudoprime(x) ispseudoprime(x,{flag}): true(1) if x is a strong pseudoprime, false(0) if not. If flag is 0 or omitted, use BPSW test, otherwise use strong Rabin-Miller test for flag randomly chosen bases. *** at top-level: isqrt() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: isqrt(x) ===> sqrtint(x) sqrtint(x,{&r}): integer square root y of x, where x is a nonnegative real number. If r is present, set it to the remainder x - y^2. *** at top-level: isset() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: isset(x) ===> setisset(x) setisset(x): true(1) if x is a set (row vector with strictly increasing entries), false(0) if not. *** at top-level: issqfree() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: issqfree(x) ===> issquarefree(x) issquarefree(x): true(1) if x is squarefree, false(0) if not. *** at top-level: isunit() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: isunit(bnf,x) ===> bnfisunit(bnf,x) bnfisunit(bnf,x,{U}): bnf being output by bnfinit, give 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. If U is present, as given by bnfunits, decompose x on the attached S-units generators. *** at top-level: jacobi() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: jacobi(x) ===> qfjacobi(x) qfjacobi(A): eigenvalues and orthogonal matrix of eigenvectors of the real symmetric matrix A. *** at top-level: jbesselh() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: jbesselh(n,x) ===> besseljh(n,x) besseljh(n,x): J-bessel function of index n+1/2 and argument x, where n is a nonnegative integer. *** at top-level: jell() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: jell(x) ===> ellj(x) ellj(x): elliptic j invariant of x. *** at top-level: karamul() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: kbessel() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: kbessel(nu,x) ===> besselk(nu,x) besselk(nu,x): K-bessel function of index nu and argument x. *** at top-level: kbessel2() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: kbessel2(nu,x) ===> besselk(nu,x) besselk(nu,x): K-bessel function of index nu and argument x. *** at top-level: ker() *** ^----- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: ker(x) ===> matker(x) matker(x,{flag=0}): basis of the kernel of the matrix x. flag is optional, and may be set to 0: default; nonzero: x is known to have integral entries. *** at top-level: keri() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: keri(x) ===> matker(x,1) matker(x,{flag=0}): basis of the kernel of the matrix x. flag is optional, and may be set to 0: default; nonzero: x is known to have integral entries. *** at top-level: kerint() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: kerint(x) ===> matkerint(x) matkerint(x,{flag=0}): LLL-reduced Z-basis of the kernel of the matrix x with integral entries; flag is deprecated, kept for backward compatibility. *** at top-level: kerint1() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: kerint1(x) ===> matkerint(x,1) matkerint(x,{flag=0}): LLL-reduced Z-basis of the kernel of the matrix x with integral entries; flag is deprecated, kept for backward compatibility. *** at top-level: kerint2() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: kro() *** ^----- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: kro(x,y) ===> kronecker(x,y) kronecker(x,y): kronecker symbol (x/y). *** at top-level: label() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: lambdak() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: laplace() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: laplace(x) ===> serlaplace(x) serlaplace(x): replaces the power series sum of a_n*x^n/n! by sum of a_n*x^n. For the reverse operation, use serconvol(x,exp(X)). *** at top-level: legendre() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: legendre(n) ===> pollegendre(n) pollegendre(n,{a='x},{flag=0}): legendre polynomial of degree n evaluated at a. If flag is 1, return [P_{n-1}(a), P_n(a)]. *** at top-level: lexsort() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: lexsort(x) ===> vecsort(x,,2) vecsort(x,{cmpf},{flag=0}): sorts the vector x in ascending order, according to the comparison function cmpf, if not omitted. Binary digits of flag (if present) mean: 1: indirect sorting, return the permutation instead of the permuted vector, 4: use descending instead of ascending order, 8: remove duplicate entries. *** at top-level: lindep2() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: lindep2(x) ===> lindep(x,1) lindep(v,{flag=0}): integral linear dependencies between components of v. flag is optional, and can be 0: default, guess a suitable accuracy, or positive: accuracy to use for the computation, in decimal digits. *** at top-level: lll() *** ^----- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: lll(x) ===> qflll(x) qflll(x,{flag=0}): LLL reduction of the vectors forming the matrix x (gives the unimodular transformation matrix T such that x*T is LLL-reduced). flag is optional, and can be 0: default, 1: disable FLATTER, 2: assumes x is integral, returns a partially reduced basis, 3: assumes x is integral, in place (return x*T), 4: assumes x is integral, returns [K,T] where K is the integer kernel of x and T the LLL reduced image, 5: same as 4 but x may have polynomial coefficients, 8: same as 0 but x may have polynomial coefficients. *** at top-level: lll1() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: lllgen() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: lllgen(x) ===> qflll(x,8) qflll(x,{flag=0}): LLL reduction of the vectors forming the matrix x (gives the unimodular transformation matrix T such that x*T is LLL-reduced). flag is optional, and can be 0: default, 1: disable FLATTER, 2: assumes x is integral, returns a partially reduced basis, 3: assumes x is integral, in place (return x*T), 4: assumes x is integral, returns [K,T] where K is the integer kernel of x and T the LLL reduced image, 5: same as 4 but x may have polynomial coefficients, 8: same as 0 but x may have polynomial coefficients. *** at top-level: lllgram() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: lllgram(x) ===> qflllgram(x) qflllgram(G,{flag=0}): LLL reduction of the lattice whose gram matrix is G (gives the unimodular transformation matrix). flag is optional and can be 0: default,1: disable FLATTER, 4: assumes x is integral, returns [K,T], where K is the integer kernel of x and T the LLL reduced image, 5: same as 4 but x may have polynomial coefficients, 8: same as 0 but x may have polynomial coefficients. *** at top-level: lllgram1() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: lllgramgen() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: lllgramgen(x) ===> qflllgram(x,8) qflllgram(G,{flag=0}): LLL reduction of the lattice whose gram matrix is G (gives the unimodular transformation matrix). flag is optional and can be 0: default,1: disable FLATTER, 4: assumes x is integral, returns [K,T], where K is the integer kernel of x and T the LLL reduced image, 5: same as 4 but x may have polynomial coefficients, 8: same as 0 but x may have polynomial coefficients. *** at top-level: lllgramint() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: lllgramint(x) ===> qflllgram(x,1) qflllgram(G,{flag=0}): LLL reduction of the lattice whose gram matrix is G (gives the unimodular transformation matrix). flag is optional and can be 0: default,1: disable FLATTER, 4: assumes x is integral, returns [K,T], where K is the integer kernel of x and T the LLL reduced image, 5: same as 4 but x may have polynomial coefficients, 8: same as 0 but x may have polynomial coefficients. *** at top-level: lllgramkerim() *** ^-------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: lllgramkerim(x) ===> qflllgram(x,4) qflllgram(G,{flag=0}): LLL reduction of the lattice whose gram matrix is G (gives the unimodular transformation matrix). flag is optional and can be 0: default,1: disable FLATTER, 4: assumes x is integral, returns [K,T], where K is the integer kernel of x and T the LLL reduced image, 5: same as 4 but x may have polynomial coefficients, 8: same as 0 but x may have polynomial coefficients. *** at top-level: lllgramkerimgen() *** ^----------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: lllgramkerimgen(x) ===> qflllgram(x,5) qflllgram(G,{flag=0}): LLL reduction of the lattice whose gram matrix is G (gives the unimodular transformation matrix). flag is optional and can be 0: default,1: disable FLATTER, 4: assumes x is integral, returns [K,T], where K is the integer kernel of x and T the LLL reduced image, 5: same as 4 but x may have polynomial coefficients, 8: same as 0 but x may have polynomial coefficients. *** at top-level: lllint() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: lllint(x) ===> qflll(x,1) qflll(x,{flag=0}): LLL reduction of the vectors forming the matrix x (gives the unimodular transformation matrix T such that x*T is LLL-reduced). flag is optional, and can be 0: default, 1: disable FLATTER, 2: assumes x is integral, returns a partially reduced basis, 3: assumes x is integral, in place (return x*T), 4: assumes x is integral, returns [K,T] where K is the integer kernel of x and T the LLL reduced image, 5: same as 4 but x may have polynomial coefficients, 8: same as 0 but x may have polynomial coefficients. *** at top-level: lllintpartial() *** ^--------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: lllintpartial(x) ===> qflll(x,2) qflll(x,{flag=0}): LLL reduction of the vectors forming the matrix x (gives the unimodular transformation matrix T such that x*T is LLL-reduced). flag is optional, and can be 0: default, 1: disable FLATTER, 2: assumes x is integral, returns a partially reduced basis, 3: assumes x is integral, in place (return x*T), 4: assumes x is integral, returns [K,T] where K is the integer kernel of x and T the LLL reduced image, 5: same as 4 but x may have polynomial coefficients, 8: same as 0 but x may have polynomial coefficients. *** at top-level: lllkerim() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: lllkerim(x) ===> qflll(x,4) qflll(x,{flag=0}): LLL reduction of the vectors forming the matrix x (gives the unimodular transformation matrix T such that x*T is LLL-reduced). flag is optional, and can be 0: default, 1: disable FLATTER, 2: assumes x is integral, returns a partially reduced basis, 3: assumes x is integral, in place (return x*T), 4: assumes x is integral, returns [K,T] where K is the integer kernel of x and T the LLL reduced image, 5: same as 4 but x may have polynomial coefficients, 8: same as 0 but x may have polynomial coefficients. *** at top-level: lllkerimgen() *** ^------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: lllkerimgen(x) ===> qflll(x,5) qflll(x,{flag=0}): LLL reduction of the vectors forming the matrix x (gives the unimodular transformation matrix T such that x*T is LLL-reduced). flag is optional, and can be 0: default, 1: disable FLATTER, 2: assumes x is integral, returns a partially reduced basis, 3: assumes x is integral, in place (return x*T), 4: assumes x is integral, returns [K,T] where K is the integer kernel of x and T the LLL reduced image, 5: same as 4 but x may have polynomial coefficients, 8: same as 0 but x may have polynomial coefficients. *** at top-level: lllrat() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: ln() *** ^---- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: ln(x) ===> log(x) log(x): natural logarithm of x. *** at top-level: localred() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: localred(e) ===> elllocalred(e) elllocalred(E,{p}): E being an elliptic curve, returns [f,kod,[u,r,s,t],c], where f is the conductor's exponent, kod is the Kodaira type for E at p, [u,r,s,t] is the change of variable needed to make E minimal at p, and c is the local Tamagawa number c_p. *** at top-level: logagm() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: logagm(x) ===> log(x,1) log(x): natural logarithm of x. *** at top-level: lseriesell() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: lseriesell(e,s,N,A) ===> elllseries(e,s,A) elllseries(E,s,{A=1}): L-series at s of the elliptic curve E, where A a cut-off point close to 1. *** at top-level: makebigbnf() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: makebigbnf(sbnf) ===> bnfinit(sbnf) bnfinit(P,{flag=0},{tech=[]}): compute the necessary data for future use in ideal and unit group computations, including fundamental units if they are not too large. flag and tech are both optional. flag can be any of 0: default, 1: include all data in algebraic form (compact units). See manual for details about tech. *** at top-level: mat() *** ^----- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: mat(x) ===> Mat(x) Mat({x=[]}): transforms any GEN x into a matrix. Empty matrix if x is omitted. *** at top-level: matextract() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: matextract(x,y,z) ===> vecextract(x,y,z) vecextract(x,y,{z}): extraction of the components of the matrix or vector x according to y and z. If z is omitted, y represents columns, otherwise y corresponds to rows and z to columns. y and z can be vectors (of indices), strings (indicating ranges as in "1..10") or masks (integers whose binary representation indicates the indices to extract, from left to right 1, 2, 4, 8, etc.). *** at top-level: mathell() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: mathell(e,x) ===> ellheightmatrix(e,x) ellheightmatrix(E,x): gives the height matrix for vector of points x on elliptic curve E. *** at top-level: matrixqz2() *** ^----------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: matrixqz2(x,p) ===> matrixqz(x,-1) matrixqz(A,{p=0}): if p>=0, transforms the rational or integral mxn (m>=n) matrix A into an integral matrix with gcd of maximal determinants coprime to p. If p=-1, finds a basis of the intersection with Z^n of the lattice spanned by the columns of A. If p=-2, finds a basis of the intersection with Z^n of the Q-vector space spanned by the columns of A. *** at top-level: matrixqz3() *** ^----------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: matrixqz3(x,p) ===> matrixqz(x,-2) matrixqz(A,{p=0}): if p>=0, transforms the rational or integral mxn (m>=n) matrix A into an integral matrix with gcd of maximal determinants coprime to p. If p=-1, finds a basis of the intersection with Z^n of the lattice spanned by the columns of A. If p=-2, finds a basis of the intersection with Z^n of the Q-vector space spanned by the columns of A. *** at top-level: minideal() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: minideal(nf,ix,vdir) ===> idealmin(nf,ix,vdir) idealmin(nf,ix,{vdir}): pseudo-minimum of the ideal ix in the direction vdir in the number field nf. *** at top-level: minim() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: minim(x,bound,maxnum) ===> qfminim(x,bound,maxnum) qfminim(x,{B},{m},{flag=0}): x being a square and symmetric matrix representing a positive definite quadratic form, this function deals with the vectors of x whose norm is less than or equal to B, enumerated using the Fincke-Pohst algorithm, storing at most m vectors (no limit if m is omitted). The function searches for the minimal nonzero vectors if B is omitted. The precise behavior depends on flag. 0: returns at most 2m vectors (unless m omitted), returns [N,M,V] where N is the number of vectors enumerated, M the maximum norm among these, and V lists half the vectors (the other half is given by -V). 1: ignores m and returns the first vector whose norm is less than B. 2: as 0 but uses a more robust, slower implementation *** at top-level: minim2() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: minim2(x,bound) ===> qfminim(x,bound,,1) qfminim(x,{B},{m},{flag=0}): x being a square and symmetric matrix representing a positive definite quadratic form, this function deals with the vectors of x whose norm is less than or equal to B, enumerated using the Fincke-Pohst algorithm, storing at most m vectors (no limit if m is omitted). The function searches for the minimal nonzero vectors if B is omitted. The precise behavior depends on flag. 0: returns at most 2m vectors (unless m omitted), returns [N,M,V] where N is the number of vectors enumerated, M the maximum norm among these, and V lists half the vectors (the other half is given by -V). 1: ignores m and returns the first vector whose norm is less than B. 2: as 0 but uses a more robust, slower implementation *** at top-level: mod() *** ^----- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: mod(x,y) ===> Mod(x,y) Mod(a,b): create 'a modulo b'. *** at top-level: modp() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: modp(x,y,p) ===> Mod(x,y) Mod(a,b): create 'a modulo b'. *** at top-level: modulargcd() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: modulargcd(x,y) ===> gcd(x,y,1) gcd(x,{y}): greatest common divisor of x and y. *** at top-level: mu() *** ^---- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: mu(n) ===> moebius(n) moebius(x): Moebius function of x. *** at top-level: nfdiv() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: nfdiv(nf,a,b) ===> nfeltdiv(nf,a,b) nfeltdiv(nf,x,y): element x/y in nf. *** at top-level: nfdiveuc() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: nfdiveuc(nf,a,b) ===> nfeltdiveuc(nf,a,b) nfeltdiveuc(nf,x,y): gives algebraic integer q such that x-qy is small. *** at top-level: nfdivres() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: nfdivres(nf,a,b) ===> nfeltdivrem(nf,a,b) nfeltdivrem(nf,x,y): gives [q,r] such that r=x-qy is small. *** at top-level: nfhermite() *** ^----------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: nfhermite(nf,x) ===> nfhnf(nf,x) nfhnf(nf,x,{flag=0}): if x=[A,I], gives a pseudo-basis [B,J] of the module sum A_jI_j. If flag is nonzero, return [[B,J], U], where U is the transformation matrix such that AU = [0|B]. *** at top-level: nfhermitemod() *** ^-------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: nfhermitemod(nf,x,detx) ===> nfhnfmod(nf,x,detx) nfhnfmod(nf,x,detx): if x=[A,I], and detx is a multiple of the ideal determinant of x, gives a pseudo-basis of the module sum A_jI_j. *** at top-level: nfmod() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: nfmod(nf,a,b) ===> nfeltmod(nf,a,b) nfeltmod(nf,x,y): gives r such that r=x-qy is small with q algebraic integer. *** at top-level: nfmul() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: nfmul(nf,a,b) ===> nfeltmul(nf,a,b) nfeltmul(nf,x,y): element x.y in nf. *** at top-level: nfpow() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: nfpow(nf,a,k) ===> nfeltpow(nf,a,k) nfeltpow(nf,x,k): element x^k in nf. *** at top-level: nfreduce() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: nfreduce(nf,a,id) ===> nfeltreduce(nf,a,id) nfeltreduce(nf,a,id): gives r such that a-r is in the ideal id and r is small. *** at top-level: nfsmith() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: nfsmith(nf,x) ===> nfsnf(nf,x) nfsnf(nf,x,{flag=0}): if x=[A,I,J], outputs D=[d_1,...d_n] Smith normal form of x. If flag is nonzero return [D,U,V], where UAV = Id. *** at top-level: nfval() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: nfval(nf,a,pr) ===> nfeltval(nf,a,pr) nfeltval(nf,x,pr,{&y}): valuation of element x at the prime pr as output by idealprimedec. *** at top-level: nucomp() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: nucomp(x,y,l) ===> qfbnucomp(x,y,l) qfbnucomp(x,y,L): composite of primitive positive definite quadratic forms x and y using nucomp and nudupl, where L=[|D/4|^(1/4)] is precomputed. *** at top-level: numer() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: numer(x) ===> numerator(x) numerator(f,{D}): numerator of f. *** at top-level: nupow() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: nupow(x,n) ===> qfbnupow(x,n) qfbnupow(x,n,{L}): n-th power of primitive positive definite quadratic form x using nucomp and nudupl. *** at top-level: o() *** ^--- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: o(x) ===> O(x) O(p^e): p-adic or power series zero with precision given by e. *** at top-level: ordell() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: ordell(e,x) ===> ellordinate(e,x) ellordinate(E,x): y-coordinates corresponding to x-ordinate x on elliptic curve E. *** at top-level: order() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: order(x) ===> znorder(x) znorder(x,{o}): order of the integermod x in (Z/nZ)*. Optional o represents a multiple of the order of the element. *** at top-level: orderell() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: orderell(e,x) ===> ellorder(e,x) ellorder(E,z,{o}): order of the point z on the elliptic curve E over a number field or a finite field, 0 if nontorsion. The parameter o, if present, represents a nonzero multiple of the order of z. *** at top-level: ordred() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: ordred(x) ===> polredord(x) polredord(x): this function is obsolete, use polredbest. *** at top-level: pascal() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: pascal(n) ===> matpascal(n) matpascal(n,{q}): Pascal triangle of order n if q is omitted. q-Pascal triangle otherwise. *** at top-level: perf() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: perf(a) ===> qfperfection(a) qfperfection(G): rank of matrix of xx~ for x minimal vectors of a Gram matrix G. *** at top-level: permutation() *** ^------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: permutation(n,k) ===> numtoperm(n,k) numtoperm(n,k): permutation number k (mod n!) of n letters (n C-integer). *** at top-level: permutation2num() *** ^----------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: permutation2num(vect) ===> permtonum(vect) permtonum(x): ordinal (between 0 and n!-1) of permutation x. *** at top-level: pf() *** ^---- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: pf(x,p) ===> qfbprimeform(x,p) qfbprimeform(x,p): returns the prime form of discriminant x, whose first coefficient is p. *** at top-level: phi() *** ^----- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: phi(x) ===> eulerphi(x) eulerphi(x): Euler's totient function of x. *** at top-level: pi() *** ^---- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: pi ===> Pi Pi=Pi(): the constant pi, with current precision. *** at top-level: pnqn() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: pnqn(x) ===> contfracpnqn(x) contfracpnqn(x,{n=-1}): [p_n,p_{n-1}; q_n,q_{n-1}] corresponding to the continued fraction x. If n >= 0 is present, returns all convergents from p_0/q_0 up to p_n/q_n. *** at top-level: pointell() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: pointell(e,z) ===> ellztopoint(e,z) ellztopoint(E,z): inverse of ellpointtoz. Returns the coordinates of point P on the curve E corresponding to a complex or p-adic z. *** at top-level: polint() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: polint(xa,ya,x) ===> polinterpolate(xa,ya,p) polinterpolate(X,{Y},{t = 'x},{&e}): polynomial interpolation at t according to data vectors X, Y, i.e., given P of minimal degree such that P(X[i]) = Y[i] for all i, return P(t). If Y is omitted, take P such that P(i) = X[i]. If present and t is numeric, e will contain an error estimate on the returned value (Neville's algorithm). *** at top-level: polred2() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: polred2(x) ===> polred(x,2) polred(T,{flag=0}): deprecated, use polredbest. Reduction of the polynomial T (gives minimal polynomials only). The following binary digits of (optional) flag are significant 1: partial reduction, 2: gives also elements. *** at top-level: polredabs2() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: polredabs2(x) ===> polredabs(x,1) polredabs(T,{flag=0}): a smallest generating polynomial of the number field for the T2 norm on the roots, with smallest index for the minimal T2 norm. flag is optional, whose binary digit mean 1: give the element whose characteristic polynomial is the given polynomial. 4: give all polynomials of minimal T2 norm (give only one of P(x) and P(-x)). *** at top-level: polredabsall() *** ^-------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: polredabsall(x) ===> polredabs(x,4) polredabs(T,{flag=0}): a smallest generating polynomial of the number field for the T2 norm on the roots, with smallest index for the minimal T2 norm. flag is optional, whose binary digit mean 1: give the element whose characteristic polynomial is the given polynomial. 4: give all polynomials of minimal T2 norm (give only one of P(x) and P(-x)). *** at top-level: polredabsfast() *** ^--------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: polredabsfast(x) ===> polredabs(x,8) polredabs(T,{flag=0}): a smallest generating polynomial of the number field for the T2 norm on the roots, with smallest index for the minimal T2 norm. flag is optional, whose binary digit mean 1: give the element whose characteristic polynomial is the given polynomial. 4: give all polynomials of minimal T2 norm (give only one of P(x) and P(-x)). *** at top-level: polredabsnored() *** ^---------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: polredabsnored(x) ===> polredabs(x,2) polredabs(T,{flag=0}): a smallest generating polynomial of the number field for the T2 norm on the roots, with smallest index for the minimal T2 norm. flag is optional, whose binary digit mean 1: give the element whose characteristic polynomial is the given polynomial. 4: give all polynomials of minimal T2 norm (give only one of P(x) and P(-x)). *** at top-level: polvar() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: polvar(x) ===> variable(x) variable({x}): main variable of object x. Gives p for p-adic x, 0 if no variable can be attached to x. Returns the list of user variables if x is omitted. *** at top-level: poly() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: poly(x,v) ===> Pol(x,v) Pol(t,{v='x}): convert t (usually a vector or a power series) into a polynomial with variable v, starting with the leading coefficient. *** at top-level: polylogd() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: polylogd(m,x) ===> polylog(m,x,1) polylog(m,x,{flag=0}): m-th polylogarithm of x. flag is optional, and can be 0: default, 1: D_m~-modified m-th polylog of x, 2: D_m-modified m-th polylog of x, 3: P_m-modified m-th polylog of x. *** at top-level: polylogdold() *** ^------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: polylogdold(m,x) ===> polylog(m,x,2) polylog(m,x,{flag=0}): m-th polylogarithm of x. flag is optional, and can be 0: default, 1: D_m~-modified m-th polylog of x, 2: D_m-modified m-th polylog of x, 3: P_m-modified m-th polylog of x. *** at top-level: polylogp() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: polylogp(m,x) ===> polylog(m,x,3) polylog(m,x,{flag=0}): m-th polylogarithm of x. flag is optional, and can be 0: default, 1: D_m~-modified m-th polylog of x, 2: D_m-modified m-th polylog of x, 3: P_m-modified m-th polylog of x. *** at top-level: polyrev() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: polyrev(x,v) ===> Polrev(x,v) Polrev(t,{v='x}): convert t (usually a vector or a power series) into a polynomial with variable v, starting with the constant term. *** at top-level: polzag() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: polzag(n,m) ===> polzagier(n,m) polzagier(n,m): Zagier's polynomials of index n,m. *** at top-level: powell() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: powell(e,x,n) ===> ellmul(e,x,n) ellmul(E,z,n): n times the point z on elliptic curve E (n in Z). *** at top-level: powrealraw() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: powrealraw(x,n) ===> qfbpowraw(x,n) qfbpowraw(x,n): n-th power without reduction of the binary quadratic form x. *** at top-level: prec() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: prec(x,n) ===> precision(x,n) precision(x,{n}): if n is present, return x at precision n. If n is omitted, return real precision of object x. *** at top-level: primedec() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: primedec(nf,p) ===> idealprimedec(nf,p) idealprimedec(nf,p,{f=0}): prime ideal decomposition of the prime number p in the number field nf as a vector of prime ideals. If f is present and nonzero, restrict the result to primes of residue degree <= f. *** at top-level: primroot() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: primroot(n) ===> znprimroot(n) znprimroot(n): returns a primitive root of n when it exists. *** at top-level: principalideal() *** ^---------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: principalidele() *** ^---------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: prodinf1() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: prodinf1(X=a,expr) ===> prodinf(X=a,expr,1) prodinf(X=a,expr,{flag=0}): infinite product (X goes from a to infinity) of real or complex expression. flag can be 0 (default) or 1, in which case compute the product of the 1+expr instead. *** at top-level: qfi() *** ^----- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: qfi(a,b,c) ===> Qfb(a,b,c) Qfb(a,{b},{c}): binary quadratic form a*x^2+b*x*y+c*y^2. *** at top-level: qfr() *** ^----- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: qfr(a,b,c,d) ===> Qfb(a,b,c,d) Qfb(a,{b},{c}): binary quadratic form a*x^2+b*x*y+c*y^2. 1546275796 *** at top-level: rank() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: rank(x) ===> matrank(x) matrank(x): rank of the matrix x. *** at top-level: rayclassno() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: rayclassno(bnf,x) ===> bnrclassno(bnf,x) bnrclassno(A,{B},{C}): relative degree of the class field defined by A,B,C. [A,{B},{C}] is of type [bnr], [bnr,subgroup], [bnf,modulus], or [bnf,modulus,subgroup]. Faster than bnrinit if only the ray class number is wanted. *** at top-level: rayclassnolist() *** ^---------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: rayclassnolist(bnf,liste) ===> bnrclassnolist(bnf,liste) bnrclassnolist(bnf,list): if list is as output by ideallist or similar, gives list of corresponding ray class numbers. *** at top-level: recip() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: recip(x) ===> polrecip(x) polrecip(pol): reciprocal polynomial of pol. *** at top-level: redimag() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: redimag(x) ===> qfbred(x) qfbred(x,{flag=0},{isd},{sd}): reduction of the binary quadratic form x. All other args. are optional. The argument isd and sd, if present, supply the values of floor(sqrt(d)) and sqrt(d) respectively, where d is the discriminant. If d<0, its value is not used. flag can be any of 0: default; 1: do a single reduction step; *** at top-level: redreal() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: redreal(x) ===> qfbred(x) qfbred(x,{flag=0},{isd},{sd}): reduction of the binary quadratic form x. All other args. are optional. The argument isd and sd, if present, supply the values of floor(sqrt(d)) and sqrt(d) respectively, where d is the discriminant. If d<0, its value is not used. flag can be any of 0: default; 1: do a single reduction step; *** at top-level: redrealnod() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: redrealnod(x,d) ===> qfbred(x,2,,d) qfbred(x,{flag=0},{isd},{sd}): reduction of the binary quadratic form x. All other args. are optional. The argument isd and sd, if present, supply the values of floor(sqrt(d)) and sqrt(d) respectively, where d is the discriminant. If d<0, its value is not used. flag can be any of 0: default; 1: do a single reduction step; *** at top-level: reduceddisc() *** ^------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: reduceddisc(f) ===> poldiscreduced(f) poldiscreduced(f): vector of elementary divisors of Z[a]/f'(a)Z[a], where a is a root of the polynomial f. *** at top-level: regula() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: regula(x) ===> quadregulator(x) quadregulator(D): regulator of the real quadratic field of discriminant D. *** at top-level: reorder() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: resultant() *** ^----------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: resultant(x,y) ===> polresultant(x,y) polresultant(x,y,{v},{flag=0}): resultant of the polynomials x and y, with respect to the main variables of x and y if v is omitted, with respect to the variable v otherwise. flag is optional, and can be 0: default, uses either the subresultant algorithm, a modular algorithm or Sylvester's matrix, depending on the inputs; 1 uses Sylvester's matrix (should always be slower than the default). *** at top-level: resultant2() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: resultant2(x,y) ===> polresultant(x,y,1) polresultant(x,y,{v},{flag=0}): resultant of the polynomials x and y, with respect to the main variables of x and y if v is omitted, with respect to the variable v otherwise. flag is optional, and can be 0: default, uses either the subresultant algorithm, a modular algorithm or Sylvester's matrix, depending on the inputs; 1 uses Sylvester's matrix (should always be slower than the default). *** at top-level: reverse() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: reverse(x) ===> serreverse(x) serreverse(s): reversion of the power series s. *** at top-level: rhoreal() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: rhoreal(x) ===> qfbred(x,1) qfbred(x,{flag=0},{isd},{sd}): reduction of the binary quadratic form x. All other args. are optional. The argument isd and sd, if present, supply the values of floor(sqrt(d)) and sqrt(d) respectively, where d is the discriminant. If d<0, its value is not used. flag can be any of 0: default; 1: do a single reduction step; *** at top-level: rhorealnod() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: rhorealnod(x,d) ===> qfbred(x,3,,d) qfbred(x,{flag=0},{isd},{sd}): reduction of the binary quadratic form x. All other args. are optional. The argument isd and sd, if present, supply the values of floor(sqrt(d)) and sqrt(d) respectively, where d is the discriminant. If d<0, its value is not used. flag can be any of 0: default; 1: do a single reduction step; *** at top-level: rndtoi() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: rndtoi(x) ===> round(x,&e) round(x,{&e}): take the nearest integer to all the coefficients of x. If e is present, do not take into account loss of integer part precision, and set e = error estimate in bits. *** at top-level: rnfdiscf() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: rnfdiscf(nf,pol) ===> rnfdisc(nf,pol) rnfdisc(nf,T): given a polynomial T with coefficients in nf, gives a 2-component vector [D,d], where D is the relative ideal discriminant, and d is the relative discriminant in nf^*/nf*^2. *** at top-level: rnfequation2() *** ^-------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: rnfequation2(nf,pol) ===> rnfequation(nf,pol,1) rnfequation(nf,pol,{flag=0}): given a pol with coefficients in nf, gives an absolute equation z of the number field defined by pol. flag is optional, and can be 0: default, or nonzero, gives [z,al,k], where z defines the absolute equation L/Q as in the default behavior, al expresses as an element of L a root of the polynomial defining the base field nf, and k is a small integer such that t = b + k al is a root of z, for b a root of pol. *** at top-level: rnfhermitebasis() *** ^----------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: rnfhermitebasis(bnf,order) ===> rnfhnfbasis(bnf,order) rnfhnfbasis(bnf,M): given a bnf attached to a number field K and a projective Z_K module M given by a pseudo-matrix, returns either a true HNF basis of M if one exists, or zero otherwise. If M is a polynomial with coefficients in K, replace it by the pseudo-matrix returned by rnfpseudobasis. *** at top-level: rootmod() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: rootmod(x,p) ===> polrootsmod(x,p) polrootsmod(f,{D}): roots of the polynomial f over the finite field defined by the domain D. *** at top-level: rootmod2() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: rootmod2(x,p) ===> polrootsmod(x,p) polrootsmod(f,{D}): roots of the polynomial f over the finite field defined by the domain D. *** at top-level: rootpadic() *** ^----------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: rootpadic(x,p,r) ===> polrootspadic(x,p,r) polrootspadic(f,p,r): p-adic roots of the polynomial f to precision r. *** at top-level: roots() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: roots(x) ===> polroots(x) polroots(T): complex roots of the polynomial T using Schonhage's method, as modified by Gourdon. *** too few arguments: rootsof1() *** ^- *** at top-level: rootsold() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: rounderror() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: rounderror(x) ===> round(x,&e) round(x,{&e}): take the nearest integer to all the coefficients of x. If e is present, do not take into account loss of integer part precision, and set e = error estimate in bits. *** at top-level: series() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: series(x,v) ===> Ser(x,v) Ser(s,{v='x},{d=seriesprecision}): convert s into a power series with variable v and precision d, starting with the constant coefficient. *** at top-level: set() *** ^----- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: set(x) ===> Set(x) Set({x=[]}): convert x into a set, i.e. a row vector with strictly increasing coefficients. Empty set if x is omitted. *** at top-level: sigmak() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: sigmak(k,x) ===> sigma(x,k) sigma(x,{k=1}): sum of the k-th powers of the divisors of x. k is optional and if omitted is assumed to be equal to 1. *** at top-level: signat() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: signat(x) ===> qfsign(x) qfsign(x): signature of the symmetric matrix x. *** at top-level: signunit() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: signunit(bnf) ===> bnfsignunit(bnf) bnfsignunit(bnf): matrix of signs of the real embeddings of the system of fundamental units found by bnfinit. *** at top-level: simplefactmod() *** ^--------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: simplefactmod(x,p) ===> factormod(x,p,1) factormod(f,{D},{flag=0}): factors the polynomial f over the finite field defined by the domain D; flag is optional, and can be 0: default or 1: only the degrees of the irreducible factors are given. *** at top-level: size() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: size(x) ===> sizedigit(x) sizedigit(x): rough upper bound for the number of decimal digits of (the components of) x. DEPRECATED. *** at top-level: smallbasis() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: smallbasis(x) ===> nfbasis(x,1) nfbasis(T,{&dK}): integral basis of the field Q[a], where a is a root of the polynomial T, using the round 4 algorithm. An argument [T,listP] is possible, where listP is a list of primes or a prime bound, to get an order which is maximal at certain primes only. If present, dK is set to the discriminant of the returned order. *** at top-level: smallbuchinit() *** ^--------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: smalldiscf() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: smalldiscf(x) ===> nfdisc(x,1) nfdisc(T): discriminant of the number field defined by the polynomial T. An argument [T,listP] is possible, where listP is a list of primes or a prime bound. *** at top-level: smallfact() *** ^----------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: smallfact(x) ===> factor(x,0) factor(x,{D}): factorization of x over domain D. If x and D are both integers, return partial factorization, using primes < D. *** at top-level: smallinitell() *** ^-------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: smallinitell(x) ===> ellinit(x,1) ellinit(x,{D=1}): let x be a vector [a1,a2,a3,a4,a6], or [a4,a6] if a1=a2=a3=0, defining the curve Y^2 + a1.XY + a3.Y = X^3 + a2.X^2 + a4.X + a6; x can also be a string, in which case the curve with matching name is retrieved from the elldata database, if available. This function initializes an elliptic curve over the domain D (inferred from coefficients if omitted). *** at top-level: smallpolred() *** ^------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: smallpolred(x) ===> polred(x,1) polred(T,{flag=0}): deprecated, use polredbest. Reduction of the polynomial T (gives minimal polynomials only). The following binary digits of (optional) flag are significant 1: partial reduction, 2: gives also elements. *** at top-level: smallpolred2() *** ^-------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: smallpolred2(x) ===> polred(x,3) polred(T,{flag=0}): deprecated, use polredbest. Reduction of the polynomial T (gives minimal polynomials only). The following binary digits of (optional) flag are significant 1: partial reduction, 2: gives also elements. *** at top-level: smith() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: smith(x) ===> matsnf(x) matsnf(X,{flag=0}): Smith normal form (i.e. elementary divisors) of the matrix X, expressed as a vector d; X must have integer or polynomial entries. Binary digits of flag mean 1: returns [u,v,d] where d=u*X*v, otherwise only the diagonal d is returned, 4: removes all information corresponding to entries equal to 1 in d. *** at top-level: smith2() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: smith2(x) ===> matsnf(x,1) matsnf(X,{flag=0}): Smith normal form (i.e. elementary divisors) of the matrix X, expressed as a vector d; X must have integer or polynomial entries. Binary digits of flag mean 1: returns [u,v,d] where d=u*X*v, otherwise only the diagonal d is returned, 4: removes all information corresponding to entries equal to 1 in d. *** at top-level: smithclean() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: smithclean(x) ===> matsnf(x,4) matsnf(X,{flag=0}): Smith normal form (i.e. elementary divisors) of the matrix X, expressed as a vector d; X must have integer or polynomial entries. Binary digits of flag mean 1: returns [u,v,d] where d=u*X*v, otherwise only the diagonal d is returned, 4: removes all information corresponding to entries equal to 1 in d. *** at top-level: smithpol() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: smithpol(x) ===> matsnf(x,2) matsnf(X,{flag=0}): Smith normal form (i.e. elementary divisors) of the matrix X, expressed as a vector d; X must have integer or polynomial entries. Binary digits of flag mean 1: returns [u,v,d] where d=u*X*v, otherwise only the diagonal d is returned, 4: removes all information corresponding to entries equal to 1 in d. *** at top-level: sort() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: sort(x) ===> vecsort(x) vecsort(x,{cmpf},{flag=0}): sorts the vector x in ascending order, according to the comparison function cmpf, if not omitted. Binary digits of flag (if present) mean: 1: indirect sorting, return the permutation instead of the permuted vector, 4: use descending instead of ascending order, 8: remove duplicate entries. *** at top-level: sqred() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: sqred(x) ===> qfgaussred(x) qfgaussred(q,{flag=0}): square reduction of the symmetric matrix q. flag=0: returns a square matrix A such that q(x) = sum_i A[i,i] (x[i] + sum_{j != i} A[i,j] x[j])^2; flag=1 return [U,V] where U is a square matrix and V a vector such that q = U~ * matdiagonal(V) * U *** at top-level: srgcd() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: srgcd(x,y) ===> gcd(x,y,2) gcd(x,{y}): greatest common divisor of x and y. *** at top-level: sturm() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: sturm(x) ===> polsturm(x) polsturm(T,{ab}): number of distinct real roots of the polynomial T (in the interval ab = [a,b] if present). *** at top-level: sturmpart() *** ^----------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: sturmpart(x,a,b) ===> polsturm(x,a,b) polsturm(T,{ab}): number of distinct real roots of the polynomial T (in the interval ab = [a,b] if present). *** at top-level: subcyclo() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: subcyclo(p,d) ===> polsubcyclo(p,d) polsubcyclo(n,d,{v='x}): finds an equation (in variable v) for the d-th degree subfields of Q(zeta_n). Output is a polynomial, or a vector of polynomials if there are several such fields or none. *** at top-level: subell() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: subell(e,a,b) ===> ellsub(e,a,b) ellsub(E,z1,z2): difference of the points z1 and z2 on elliptic curve E. *** at top-level: sumalt2() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: sumalt2(X=a,expr) ===> sumalt(X=a,expr,1) sumalt(X=a,expr,{flag=0}): Cohen-Villegas-Zagier's acceleration of alternating series expr, X starting at a. flag is optional, and can be 0: default, or 1: uses a slightly different method using Zagier's polynomials. *** at top-level: sumpos2() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: sumpos2(X=a,expr) ===> sumpos(X=a,expr,1) sumpos(X=a,expr,{flag=0}): sum of positive (or negative) series expr, the formal variable X starting at a. flag is optional, and can be 0: default, or 1: uses a slightly different method using Zagier's polynomials. *** at top-level: supplement() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: supplement(x) ===> matsupplement(x) matsupplement(x): supplement the columns of the matrix x to an invertible matrix. *** at top-level: sylvestermatrix() *** ^----------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: sylvestermatrix(x,y) ===> polsylvestermatrix(x,y) polsylvestermatrix(x,y): forms the sylvester matrix attached to the two polynomials x and y. Warning: the polynomial coefficients are in columns, not in rows. *** at top-level: taniyama() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: taniyama(e) ===> elltaniyama(e) elltaniyama(E,{n=seriesprecision}): modular parametrization of elliptic curve E/Q. *** at top-level: tchebi() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: tchebi(n) ===> polchebyshev(n) polchebyshev(n,{flag=1},{a='x}): Chebyshev polynomial of the first (flag = 1) or second (flag = 2) kind, of degree n, evaluated at a. *** at top-level: teich() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: teich(x) ===> teichmuller(x) teichmuller(x,{tab}): Teichmuller character of p-adic number x. If x = [p,n], return the lifts of all teichmuller(i + O(p^n)) for i = 1, ..., p-1. Such a vector can be fed back to teichmuller, as the optional argument tab, to speed up later computations. *** at top-level: threetotwo() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: threetotwo2() *** ^------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: torsell() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: torsell(e) ===> elltors(e) elltors(E): torsion subgroup of elliptic curve E: order, structure, generators. *** at top-level: trans() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: trans(x) ===> mattranspose(x) mattranspose(x): x~ = transpose of x. *** at top-level: trunc() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: trunc(x) ===> truncate(x) truncate(x,{&e}): truncation of x; when x is a power series,take away the O(X^). If e is present, do not take into account loss of integer part precision, and set e = error estimate in bits. *** at top-level: tschirnhaus() *** ^------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: tschirnhaus(x) ===> poltschirnhaus(x) poltschirnhaus(x): random Tschirnhausen transformation of the polynomial x. *** at top-level: twototwo() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: unit() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: unit(x) ===> quadunit(x) quadunit(D,{v = 'w}): fundamental unit u of the quadratic order of discriminant D where D must be positive. If v is given, the variable name is used to display u, else 'w' is used. *** at top-level: vec() *** ^----- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: vec(x) ===> Vec(x) Vec(x,{n}): transforms the object x into a vector of dimension n. *** at top-level: vecindexsort() *** ^-------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: vecindexsort(x) ===> vecsort(x,,1) vecsort(x,{cmpf},{flag=0}): sorts the vector x in ascending order, according to the comparison function cmpf, if not omitted. Binary digits of flag (if present) mean: 1: indirect sorting, return the permutation instead of the permuted vector, 4: use descending instead of ascending order, 8: remove duplicate entries. *** at top-level: veclexsort() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: veclexsort(x) ===> vecsort(x,,2) vecsort(x,{cmpf},{flag=0}): sorts the vector x in ascending order, according to the comparison function cmpf, if not omitted. Binary digits of flag (if present) mean: 1: indirect sorting, return the permutation instead of the permuted vector, 4: use descending instead of ascending order, 8: remove duplicate entries. *** at top-level: vvector() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: vvector(n,X,expr) ===> vectorv(n,X,expr) vectorv(n,{X},{expr=0}): column vector with n components of expression expr (X ranges from 1 to n). By default, fill with 0s. *** at top-level: weipell() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: weipell(e) ===> ellwp(e) ellwp(w,{z='x},{flag=0}): computes the value at z of the Weierstrass P function attached to the lattice w, as given by ellperiods. Optional flag means 0 (default), compute only P(z), 1 compute [P(z),P'(z)]. *** at top-level: wf() *** ^---- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: wf(x) ===> weber(x) weber(x,{flag=0}): one of Weber's f function of x. flag is optional, and can be 0: default, function f(x)=exp(-i*Pi/24)*eta((x+1)/2)/eta(x), 1: function f1(x)=eta(x/2)/eta(x) 2: function f2(x)=sqrt(2)*eta(2*x)/eta(x). *** at top-level: wf2() *** ^----- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: wf2(x) ===> weber(x,2) weber(x,{flag=0}): one of Weber's f function of x. flag is optional, and can be 0: default, function f(x)=exp(-i*Pi/24)*eta((x+1)/2)/eta(x), 1: function f1(x)=eta(x/2)/eta(x) 2: function f2(x)=sqrt(2)*eta(2*x)/eta(x). *** at top-level: zell() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: zell(e,P) ===> ellpointtoz(e,P) ellpointtoz(E,P): lattice point z corresponding to the point P on the elliptic curve E. *** at top-level: zideallog() *** ^----------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: zideallog(nf,x,bid) ===> ideallog(nf,x,bid) ideallog({nf},x,bid): if bid is a big ideal, as given by idealstar(nf,D,...), gives the vector of exponents on the generators bid.gen (even if these generators have not been explicitly computed). *** at top-level: zidealstar() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: zidealstar(nf,I) ===> idealstar(nf,I) idealstar({nf},N,{flag=1},{cycmod}): gives the structure of (Z_K/N)^*, where N is a modulus (an ideal in any form or a vector [f0, foo], where f0 is an ideal and foo is a {0,1}-vector with r1 components. If the positive integer cycmod is present, only compute the group modulo cycmod-th powers. flag is optional, and can be 0: structure as an abelian group [h,d,g] where h is the order, d the orders of the cyclic factors and g the generators; if flag=1 (default), gives a bid structure used in ideallog to compute discrete logarithms; underlying generators are well-defined but not explicitly computed, which saves time; if flag=2, same as with flag=1 except that the generators are also given. If nf is omitted, N must be an integer and we return the structure of (Z/NZ)^*. *** at top-level: zidealstarinit() *** ^---------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: zidealstarinit(nf,id) ===> idealstar(nf,id,1) idealstar({nf},N,{flag=1},{cycmod}): gives the structure of (Z_K/N)^*, where N is a modulus (an ideal in any form or a vector [f0, foo], where f0 is an ideal and foo is a {0,1}-vector with r1 components. If the positive integer cycmod is present, only compute the group modulo cycmod-th powers. flag is optional, and can be 0: structure as an abelian group [h,d,g] where h is the order, d the orders of the cyclic factors and g the generators; if flag=1 (default), gives a bid structure used in ideallog to compute discrete logarithms; underlying generators are well-defined but not explicitly computed, which saves time; if flag=2, same as with flag=1 except that the generators are also given. If nf is omitted, N must be an integer and we return the structure of (Z/NZ)^*. *** at top-level: zidealstarinitgen() *** ^------------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: zidealstarinitgen(nf,id) ===> idealstar(nf,id,2) idealstar({nf},N,{flag=1},{cycmod}): gives the structure of (Z_K/N)^*, where N is a modulus (an ideal in any form or a vector [f0, foo], where f0 is an ideal and foo is a {0,1}-vector with r1 components. If the positive integer cycmod is present, only compute the group modulo cycmod-th powers. flag is optional, and can be 0: structure as an abelian group [h,d,g] where h is the order, d the orders of the cyclic factors and g the generators; if flag=1 (default), gives a bid structure used in ideallog to compute discrete logarithms; underlying generators are well-defined but not explicitly computed, which saves time; if flag=2, same as with flag=1 except that the generators are also given. If nf is omitted, N must be an integer and we return the structure of (Z/NZ)^*. *** at top-level: box() *** ^----- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: box(x,a) ===> plotbox(x,a) plotbox(w,x2,y2,{filled=0}): 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). If filled=1, fill the box. *** at top-level: color() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: color(w,c) ===> plotcolor(w,c) plotcolor(w,c): in rectwindow w, set default color to c. Possible values for c are [R,G,B] values, a color name or an index in the graphcolormap default: factory settings are 0=white, 1=black, 2=blue, 3=sienna, 4=red, 5=green, 6=grey, 7=gainsborough. Return [R,G,B] value attached to color. *** at top-level: cursor() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: cursor(w) ===> plotcursor(w) plotcursor(w): current position of cursor in rectwindow w. *** at top-level: draw() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: draw(list) ===> plotdraw(list) plotdraw(w,{flag=0}): draw rectwindow w. More generally, w can be of the form [w1,x1,y1, w2,x2,y2,etc.]: draw rectwindows wi at given xi,yi positions. If flag!=0, the xi,yi express fractions of the size of the current output device. *** at top-level: initrect() *** ^---------- *** not a function in function call *** at top-level: killrect() *** ^---------- *** not a function in function call *** at top-level: line() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: line(w,x2,y2) ===> plotlines(w,x2,y2) plotlines(w,X,Y,{flag=0}): draws an open polygon in rectwindow w where X and Y contain the x (resp. y) coordinates of the vertices. If X and Y are both single values (i.e not vectors), draw the corresponding line (and move cursor). If (optional) flag is nonzero, close the polygon. *** at top-level: lines() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: lines(w,x2,y2) ===> plotlines(w,x2,y2) plotlines(w,X,Y,{flag=0}): draws an open polygon in rectwindow w where X and Y contain the x (resp. y) coordinates of the vertices. If X and Y are both single values (i.e not vectors), draw the corresponding line (and move cursor). If (optional) flag is nonzero, close the polygon. *** at top-level: move() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: move(w,x,y) ===> plotmove(w,x,y) plotmove(w,x,y): move cursor to position x,y in rectwindow w. *** at top-level: ploth2() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: ploth2(X=a,b,expr) ===> ploth(X=a,b,expr,1) ploth(X=a,b,expr,{flag=0},{n=0}): plot of expression expr, X goes from a to b in high resolution. Both flag and n are optional. Binary digits of flag mean: 1=Parametric, 2=Recursive, 4=no_Rescale, 8=no_X_axis, 16=no_Y_axis, 32=no_Frame, 64=no_Lines (do not join points), 128=Points_too (plot both lines and points), 256=Splines (use cubic splines), 512=no_X_ticks, 1024= no_Y_ticks, 2048=Same_ticks (plot all ticks with the same length), 4096=Complex (the two coordinates of each point are encoded as a complex number). n specifies number of reference points on the graph (0=use default value). Returns a vector for the bounding box. *** at top-level: plothmult() *** ^----------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: plothmult(X=a,b,expr) ===> ploth(X=a,b,expr) ploth(X=a,b,expr,{flag=0},{n=0}): plot of expression expr, X goes from a to b in high resolution. Both flag and n are optional. Binary digits of flag mean: 1=Parametric, 2=Recursive, 4=no_Rescale, 8=no_X_axis, 16=no_Y_axis, 32=no_Frame, 64=no_Lines (do not join points), 128=Points_too (plot both lines and points), 256=Splines (use cubic splines), 512=no_X_ticks, 1024= no_Y_ticks, 2048=Same_ticks (plot all ticks with the same length), 4096=Complex (the two coordinates of each point are encoded as a complex number). n specifies number of reference points on the graph (0=use default value). Returns a vector for the bounding box. *** at top-level: point() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: point(w,x,y) ===> plotpoints(w,x,y) plotpoints(w,X,Y): draws in rectwindow w the points whose x (resp y) coordinates are in X (resp Y). If X and Y are both single values (i.e not vectors), draw the corresponding point (and move cursor). *** at top-level: points() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: points(w,x,y) ===> plotpoints(w,x,y) plotpoints(w,X,Y): draws in rectwindow w the points whose x (resp y) coordinates are in X (resp Y). If X and Y are both single values (i.e not vectors), draw the corresponding point (and move cursor). *** at top-level: postdraw() *** ^---------- *** not a function in function call *** at top-level: postploth() *** ^----------- *** not a function in function call *** at top-level: postploth2() *** ^------------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: postploth2(X=a,b,expr) ===> psploth(X=a,b,expr,1) psploth(X=a,b,expr,{flags=0},{n=0}): obsolete function. *** at top-level: postplothraw() *** ^-------------- *** not a function in function call *** at top-level: pprint() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: pprint1() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. This function no longer exists *** at top-level: rbox() *** ^------ *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: rbox(w,dx,dy) ===> plotrbox(w,dx,dy) plotrbox(w,dx,dy,{filled}): 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). If filled=1, fill the box. *** at top-level: read() *** ^------ *** read: You never gave me anything to read!. *** at top-level: rline() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: rline(w,dx,dy) ===> plotrline(w,dx,dy) plotrline(w,dx,dy): if the cursor is at (x1,y1), draw a line from (x1,y1) to (x1+dx,y1+dy) (and move the cursor) in the rectwindow w. *** at top-level: rlines() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. *** at top-level: rlines() *** ^-------- *** bug in whatnow, please report. *** at top-level: rmove() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: rmove(w,dx,dy) ===> plotrmove(w,dx,dy) plotrmove(w,dx,dy): move cursor to position (dx,dy) relative to the present position in the rectwindow w. *** at top-level: rpoint() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: rpoint(w,dx,dy) ===> plotrpoint(w,dx,dy) plotrpoint(w,dx,dy): draw a point (and move cursor) at position dx,dy relative to present position of the cursor in rectwindow w. *** at top-level: rpoints() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. *** at top-level: rpoints() *** ^--------- *** bug in whatnow, please report. *** at top-level: scale() *** ^------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: scale(w,x1,x2,y1,y2) ===> plotscale(w,x1,x2,y1,y2) plotscale(w,x1,x2,y1,y2): scale the coordinates in rectwindow w so that x goes from x1 to x2 and y from y1 to y2 (y2 default(realprecision,n) default({key},{val}): returns the current value of the default key. If val is present, set opt to val first. If no argument is given, print a list of all defaults as well as their values. *** at top-level: setserieslength() *** ^----------------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: setserieslength(n) ===> default(seriesprecision,n) default({key},{val}): returns the current value of the default key. If val is present, set opt to val first. If no argument is given, print a list of all defaults as well as their values. *** at top-level: settype() *** ^--------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: settype(x,t) ===> type(x,t) type(x): return the type of the GEN x. *** at top-level: string() *** ^-------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: string(w,x) ===> plotstring(w,x) plotstring(w,x,{flags=0}): draw in rectwindow w the string corresponding to x. Bits 1 and 2 of flag regulate horizontal alignment: left if 0, right if 2, center if 1. Bits 4 and 8 regulate vertical alignment: bottom if 0, top if 8, v-center if 4. Can insert additional gap between point and string: horizontal if bit 16 is set, vertical if bit 32 is set. *** at top-level: texprint() *** ^---------- *** not a function in function call A function with that name existed in GP-1.39.15. Please update your script. New syntax: texprint(x) ===> printtex(x) printtex({str}*): outputs its string arguments in TeX format. Total time spent: 5 pari-2.17.2/src/test/32/genus2red0000644000175000017500000012357714760123736015027 0ustar billbillType: [I{0-0-0}], p. 155 [1, Mat([7, 0]), [x^5 + x^3 - 2*x^2 + 3*x + 1, 0], [7, [1, []], ["(tame) [I{ 0-0-0}] page 155", []]]] Type: [I*{0-0-0}], p. 155 [2401, Mat([7, 4]), [7*x^5 + 7*x^3 - 14*x^2 + 21*x + 7, 0], [7, [1, []], ["( tame) [I*{0-0-0}] page 155", [2, 2, 2, 2]]]] Type: [II], p. 155 [49, Mat([7, 2]), [x^6 + 28*x^4 - 49*x^2 + 343, 0], [7, [1, []], ["(tame) [I I] page 155", []]]] [9, Mat([3, 2]), [x^6 + 12*x^4 - 9*x^2 + 27, 0], [3, [1, []], ["[II] page 15 5", []]]] Type: [III], p. 155 [2401, Mat([7, 4]), [x^6 + 28*x^3 + 49, 0], [7, [1, []], ["[III] page 155", [3, 3]]]] Type: [IV], p. 155 [2401, Mat([7, 4]), [7*x^6 + 245*x^3 + 343, 0], [7, [4, []], ["[III*{3}] pag e 184", []]]] Type: [V], p. 156 [2401, Mat([7, 4]), [x^6 + 7, 0], [7, [1, []], ["[V] page 156", [3]]]] Type: [V*], p. 156 [2401, Mat([7, 4]), [49*x^6 + 7, 0], [7, [1, []], ["[V*] page 156", [3]]]] Type: [VI], p. 156 [2401, Mat([7, 4]), [x^5 + 21*x^3 + 49*x, 0], [7, [1, []], ["(tame) [VI] pag e 156", [2, 2]]]] Type: [VII], p. 156 [2401, Mat([7, 4]), [x^5 + 7*x, 0], [7, [1, []], ["[VII] page 156", [2]]]] Type: [VII*], p. 156 [2401, Mat([7, 4]), [7*x^5 + 49*x, 0], [7, [1, []], ["[VII*] page 156", [2]] ]] Type: [VIII-1], p. 156 [2401, Mat([7, 4]), [x^5 + 7, 0], [7, [1, []], ["[VIII-1] page 156", []]]] Type: [VIII-2], p. 157 [2401, Mat([7, 4]), [x^5 + 343, 0], [7, [1, []], ["[VIII-2] page 157", []]]] Type: [VIII-3], p. 157 [2401, Mat([7, 4]), [7*x^5 + 343, 0], [7, [1, []], ["[VIII-3] page 157", []] ]] Type: [VIII-4], p. 157 [2401, Mat([7, 4]), [49*x^5 + 7, 0], [7, [1, []], ["[VIII-4] page 157", []]] ] Type: [IX-1], p. 157 [2401, Mat([7, 4]), [x^5 + 49, 0], [7, [1, []], ["[IX-1] page 157", [5]]]] Type: [IX-2], p. 157 [2401, Mat([7, 4]), [7*x^5 + 1, 0], [7, [1, []], ["[IX-2] page 157", [5]]]] Type: [IX-3], p. 157 [2401, Mat([7, 4]), [7*x^5 + 49, 0], [7, [1, []], ["[IX-3] page 157", [5]]]] Type: [IX-4], p. 158 [2401, Mat([7, 4]), [49*x^5 + 1, 0], [7, [1, []], ["[IX-4] page 158", [5]]]] Type: [I{0}-I{0}-10], p. 158 [1, Mat([7, 0]), [x^6 + 63668057609090279857414351392240013*x^4 + 5080218607 39623365322188197652216501772434524836002*x^3 + 1910041728272708395722430541 76720030*x^2 + 1524065582218870159634622202046929362731654966748013*x + 5080 21860739623365322188197652216501772434524836001, 0], [7, [5, [Mod(2, 7), Mod (5, 7)]], ["(tame) [I{0}-I{0}-10] page 158", []]]] [1, Mat([3, 0]), [x^6 + 12157665459056928800*x^4 + 4239115827521620351429443 3202*x^3 - 12157665459056928801*x^2 - 42391158263058538055237504400*x + 4239 1158275216203514294433201, 0], [3, [5, [Mod(0, 3), Mod(1, 3)]], ["[I{0}-I{0} -10] page 158", []]]] Type: [I{0}*-I{0}*-10], p. 158 [2401, Mat([7, 4]), [x^6 - 3*x^5 + 3119734822845423713013303218219760640*x^4 + 174251498233690804946306083258439121068035387359467068*x^3 - 522754494701 071974956308228570573828328352393092171529*x^2 + 261377247350536227541748732 24064163053785883855665547000*x + 339790421555697087895745575999685007210492 83193655926885, 0], [7, [5, [Mod(2, 7), Mod(2, 7)]], ["(tame) [I*{0}-I*{0}-1 0] page 158", [2, 2, 2, 2]]]] [81, Mat([3, 4]), [x^6 - 3*x^5 + 109418989131512359203*x^4 + 114456127310258 0527491412618835*x^3 - 3433683820949026419446923244535*x^2 - 686736763675536 0349712765606247*x + 40059644570079312321008239374945, 0], [3, [5, [Mod(0, 3 ), Mod(0, 3)]], ["[I*{0}-I*{0}-10] page 158", [2, 2, 2, 2]]]] Type: [I{0}-I{0}*-10], p. 159 [49, Mat([7, 2]), [x^6 + 3119734822845423713013303218219760493*x^4 + 1742514 98233690814305510551794710260107945042018748344*x^3 + 9359204468536271139039 909654659281470*x^2 + 522754494701072446036266478229554493337138344276005519 *x + 174251498233690814305510551794710260107945042018748343, 0], [7, [5, [Mo d(2, 7), Mod(5, 7)]], ["(tame) [I{0}-I*{0}-10] page 159", [2, 2]]]] [9, Mat([3, 2]), [x^6 + 109418989131512359208*x^4 + 114456127343083749488594 9696428*x^3 - 109418989131512359209*x^2 - 1144561273321418505754437337218*x + 1144561273430837494885949696427, 0], [3, [5, [Mod(0, 3), Mod(1, 3)]], ["[I {0}-I*{0}-10] page 159", [2, 2]]]] Type: [2I{0}-11], p. 159 [49, Mat([7, 2]), [x^6 - 21*x^4 + 574743694141699243350*x^2 + 26517308418364 47612787128678837, 0], [7, [5, [Mod(2, 7), Mod(2, 7)]], ["(tame) [2I{0}-11] page 159", []]]] [9, Mat([3, 2]), [x^6 - 9*x^4 - 282429536454*x^2 + 150095482585608537, 0], [ 3, [5, [Mod(0, 3), Mod(0, 3)]], ["[2I{0}-11] page 159", []]]] Type: [2I{0}*-10], p. 159 [2401, Mat([7, 4]), [x^6 - 21*x^4 + 82106242020242749176*x^2 + 5411695603795 2111668959660849*x - 574743694141699243546, 0], [7, [5, [Mod(2, 7), Mod(2, 7 )]], ["(tame) [2I*{0}-10] page 159", [2, 2]]]] Type: [2I{0}*-10], p. 159 [2401, Mat([7, 4]), [x^6 - 21*x^4 + 82106242020242749176*x^2 + 5411695603795 2111668959660849*x - 574743694141699243546, 0], [7, [5, [Mod(2, 7), Mod(2, 7 )]], ["(tame) [2I*{0}-10] page 159", [2, 2]]]] Type: [I{0}-II-10], p. 159 [49, Mat([7, 2]), [x^5 + 3*x^4 + x^3 + 3556153025177363557255317383565515512 407041673852007*x^2 + 10668459075532090671765952150696546537221125021556021* x + 3556153025177363557255317383565515512407041673852007, 0], [7, [5, [Mod(0 , 7), Mod(2, 7)]], ["(tame) [I{0}-II-10] page 159", []]]] Type: [I{0}-II*-10], p. 160 [49, Mat([7, 2]), [x^5 + 3*x^4 + x^3 + 8538323413450849900970017037940802745 289307058918668807*x^2 + 256149702403525497029100511138224082358679211767560 06421*x + 8538323413450849900970017037940802745289307058918668807, 0], [7, [ 5, [Mod(0, 7), Mod(2, 7)]], ["(tame) [I{0}-II*-10] page 160", []]]] [243, Mat([3, 5]), [x^5 + 3*x^4 + x^3 + 10301051460877537453973547267843*x^2 + 30903154382632612361920641803529*x + 10301051460877537453973547267843, 0] , [3, [5, [Mod(0, 3), Mod(0, 3)]], ["[I{0}-II*-10] pages 159-177", []]]] Type: [I{0}-IV-10], p. 160 [49, Mat([7, 2]), [x^5 + 3*x^4 + x^3 + 2489307117624154490078722168495860858 6849291716964049*x^2 + 74679213528724634702361665054875825760547875150892147 *x + 24893071176241544900787221684958608586849291716964049, 0], [7, [5, [Mod (0, 7), Mod(2, 7)]], ["(tame) [I{0}-IV-10] page 160", [3]]]] [243, Mat([3, 5]), [x^5 + 3*x^4 + x^3 + 381520424476945831628649898809*x^2 + 1144561273430837494885949696427*x + 381520424476945831628649898809, 0], [3, [5, [Mod(0, 3), Mod(0, 3)]], ["[I{0}-IV-10] pages 159-177", [3]]]] Type: [I{0}-IV*-10], p. 160 [49, Mat([7, 2]), [x^5 + 3*x^4 + x^3 + 1219760487635835700138573862562971820 755615294131238401*x^2 + 365928146290750710041572158768891546226684588239371 5203*x + 1219760487635835700138573862562971820755615294131238401, 0], [7, [5 , [Mod(0, 7), Mod(2, 7)]], ["(tame) [I{0}-IV*-10] page 160", [3]]]] [243, Mat([3, 5]), [x^5 + 3*x^4 + x^3 + 3433683820292512484657849089281*x^2 + 10301051460877537453973547267843*x + 3433683820292512484657849089281, 0], [3, [5, [Mod(0, 3), Mod(0, 3)]], ["[I{0}-IV*-10] pages 159-177", [3]]]] Type: [I{0}*-II-10], p. 160 [2401, Mat([7, 4]), [49*x^5 + 21*x^4 + x^3 + 1742514982336908143055105517947 10260107945042018748343*x^2 + 7467921352872463470236166505487582576054787515 0892147*x + 3556153025177363557255317383565515512407041673852007, 0], [7, [5 , [Mod(0, 7), Mod(2, 7)]], ["(tame) [I*{0}-II-10] page 160", [2, 2]]]] [2187, Mat([3, 7]), [9*x^5 + 9*x^4 + x^3 + 1144561273430837494885949696427*x ^2 + 1144561273430837494885949696427*x + 127173474825648610542883299603, 0], [3, [5, [Mod(0, 3), Mod(0, 3)]], ["[I*{0}-II-10] pages 159-177", [2, 2]]]] Type: [I{0}*-II*-10], p. 160-161 [2401, Mat([7, 4]), [49*x^5 + 21*x^4 + x^3 + 4183778472590916451475308348590 99334519176045887014771543*x^2 + 1793047916824678479203703577967568576510754 48237292044947*x + 8538323413450849900970017037940802745289307058918668807, 0], [7, [5, [Mod(0, 7), Mod(2, 7)]], ["(tame) [I*{0}-II*-10] page 160", [2, 2]]]] [2187, Mat([3, 7]), [9*x^5 + 9*x^4 + x^3 + 92709463147897837085761925410587* x^2 + 92709463147897837085761925410587*x + 10301051460877537453973547267843, 0], [3, [5, [Mod(0, 3), Mod(0, 3)]], ["[I*{0}-II*-10] pages 159-177", [2, 2 ]]]] Type: [I{0}*-IV-10], p. 161 [2401, Mat([7, 4]), [49*x^5 + 21*x^4 + x^3 + 1219760487635835700138573862562 971820755615294131238401*x^2 + 522754494701072442916531655384130780323835126 056245029*x + 24893071176241544900787221684958608586849291716964049, 0], [7, [5, [Mod(0, 7), Mod(2, 7)]], ["(tame) [I*{0}-IV-10] page 161", [6, 2]]]] Type: [I{0}*-IV*-10], p. 161 [2401, Mat([7, 4]), [49*x^5 + 21*x^4 + x^3 + 5976826389415594930679011926558 5619217025149412430681649*x^2 + 25614970240352549702910051113822408235867921 176756006421*x + 1219760487635835700138573862562971820755615294131238401, 0] , [7, [5, [Mod(0, 7), Mod(2, 7)]], ["(tame) [I*{0}-IV*-10] page 161", [6, 2] ]]] Type: [I{0}-III-10], p. 161 [49, Mat([7, 2]), [x^5 + 3*x^4 + 44567640326363195900190045974568008*x^3 + 1 33702920979089587700570137923704021*x^2 + 4456764032636319590019004597456800 7*x, 0], [7, [5, [Mod(2, 7), Mod(6, 7)]], ["(tame) [I{0}-III-10] page 161", [2]]]] Type: [I{0}-III*-10], p. 162 [49, Mat([7, 2]), [x^5 + 3*x^4 + 2183814375991796599109312252753832344*x^3 + 6551443127975389797327936758261497029*x^2 + 2183814375991796599109312252753 832343*x, 0], [7, [5, [Mod(2, 7), Mod(6, 7)]], ["(tame) [I{0}-III*-10] page 162", [2]]]] Type: [I{0}*-III-10], p. 162 [2401, Mat([7, 4]), [49*x^5 + 21*x^4 + 2183814375991796599109312252753832344 *x^3 + 935920446853627113903990965465928147*x^2 + 44567640326363195900190045 974568007*x, 0], [7, [5, [Mod(2, 7), Mod(6, 7)]], ["(tame) [I*{0}-III-10] pa ge 162", [2, 2, 2]]]] Type: [I{0}*-III*-10], p. 162 [2401, Mat([7, 4]), [49*x^5 + 21*x^4 + 1070069044235980333563563003849377848 08*x^3 + 45860101895827728581295557307830479203*x^2 + 2183814375991796599109 312252753832343*x, 0], [7, [5, [Mod(2, 7), Mod(6, 7)]], ["(tame) [I*{0}-III* -10] page 162", [2, 2, 2]]]] Type: [2II-10], p. 162 [2401, Mat([7, 4]), [x^6 - 21*x^4 + 147*x^2 + 7730993719707444524137094407*x - 343, 0], [7, [5, [Mod(0, 7), Mod(0, 7)]], ["(tame) [2II-10] page 162", [] ]]] [59049, Mat([3, 10]), [x^6 - 9*x^4 + 27*x^2 + 5559060566555523*x - 27, 0], [ 3, [5, [Mod(0, 3), Mod(0, 3)]], ["[2II-10] page 162", []]]] Type: [2II*-10], p. 163 [2401, Mat([7, 4]), [x^6 - 21*x^4 + 147*x^2 + 378818692265664781682717625943 *x - 343, 0], [7, [5, [Mod(0, 7), Mod(0, 7)]], ["(tame) [2II*-10] page 163", []]]] [59049, Mat([3, 10]), [x^6 - 9*x^4 + 27*x^2 + 50031545098999707*x - 27, 0], [3, [5, [Mod(0, 3), Mod(0, 3)]], ["[2II*-10] page 163", []]]] Type: [II-II-10], p. 163 [2401, Mat([7, 4]), [x^6 - 3*x^5 + 3*x^4 + 355615302517736355725531738356551 5512407041673852013*x^3 - 10668459075532090671765952150696546537221125021556 021*x^2 + 10668459075532090671765952150696546537221125021556021*x + 21336918 151064181343531904301393093074442250043112042, 0], [7, [5, [Mod(0, 7), Mod(0 , 7)]], ["(tame) [II-II-10] page 163", []]]] Type: [II-II*-10], p. 163 [2401, Mat([7, 4]), [x^6 - 3*x^5 + 3*x^4 + 355615302517736355725531738356551 5512407041673868813*x^3 - 10668459075532090671765952150696546537221125021556 021*x^2 + 10668459075532090671765952150696546537221125021556021*x + 59764707 741130771943232863948202053701512742370756829642, 0], [7, [5, [Mod(0, 7), Mo d(0, 7)]], ["(tame) [II-II*-10] page 163", []]]] Type: [II*-II*-10], p. 163 [2401, Mat([7, 4]), [x^6 - 3*x^5 + 3*x^4 + 853832341345084990097001703794080 2745289307058918685613*x^3 - 25614970240352549702910051113822408235867921176 756006421*x^2 + 25614970240352549702910051113822408235867921176756006421*x + 143495063286454983435702106339633130937332094432187147970442, 0], [7, [5, [ Mod(0, 7), Mod(0, 7)]], ["(tame) [II*-II*-10] page 163", []]]] Type: [II*-II*-(-1)], p. 163 [2401, Mat([7, 4]), [7*x^6 - 21*x^5 + 21*x^4 + 679*x^3 - 1029*x^2 + 1029*x + 16464, 0], [7, [5, [Mod(0, 7), Mod(0, 7)]], ["(tame) [II*-II*--1] page 163" , []]]] Type: [II-IV-10], p. 164 [2401, Mat([7, 4]), [x^6 - 3*x^5 + 3*x^4 + 355615302517736355725531738356551 5512407041673852055*x^3 - 10668459075532090671765952150696546537221125021556 021*x^2 + 10668459075532090671765952150696546537221125021556021*x + 17069534 5208513450748255234411144744595538000344896336, 0], [7, [5, [Mod(0, 7), Mod( 0, 7)]], ["(tame) [II-IV-10] page 164", [3]]]] Type: [II-IV*-10], p. 164 [2401, Mat([7, 4]), [x^6 - 3*x^5 + 3*x^4 + 355615302517736355725531738356551 5512407041673854407*x^3 - 10668459075532090671765952150696546537221125021556 021*x^2 + 10668459075532090671765952150696546537221125021556021*x + 85347672 60425672537412761720557237229776900017244816800, 0], [7, [5, [Mod(0, 7), Mod (0, 7)]], ["(tame) [II-IV*-10] page 164", [3]]]] Type: [II*-IV-10], p. 164 [2401, Mat([7, 4]), [x^6 - 3*x^5 + 3*x^4 + 853832341345084990097001703794080 2745289307058918668855*x^3 - 25614970240352549702910051113822408235867921176 756006421*x^2 + 25614970240352549702910051113822408235867921176756006421*x + 409839523845640795246560817821158531773886738828096102736, 0], [7, [5, [Mod (0, 7), Mod(0, 7)]], ["(tame) [II*-IV-10] page 164", [3]]]] Type: [II*-IV-(-1)], p. 164 [2401, Mat([7, 4]), [x^6 + 56*x^3 + 343, 0], [7, [5, [Mod(0, 7), Mod(0, 7)]] , ["[II*-IV-(-1)] page 164", [3]]]] Type: [II*-IV*-10], p. 164-165 [2401, Mat([7, 4]), [343*x^6 - 147*x^5 + 21*x^4 + 41837784725909164514753083 4859099334519176045887014771591*x^3 - 17930479168246784792037035779675685765 1075448237292044947*x^2 + 25614970240352549702910051113822408235867921176756 006421*x + 58548503406520113606651545403022647396269534118299443248, 0], [7, [5, [Mod(0, 7), Mod(0, 7)]], ["(tame) [II*-IV*-10] page 164", [3]]]] Type: [2IV-10], p. 165 [2401, Mat([7, 4]), [x^6 - 21*x^4 + 147*x^2 + 54116956037952111668959660506, 0], [7, [5, [Mod(0, 7), Mod(0, 7)]], ["(tame) [2IV-10] page 165", [3]]]] [59049, Mat([3, 10]), [x^6 - 9*x^4 + 27*x^2 + 16677181699666542, 0], [3, [5, [Mod(0, 3), Mod(0, 3)]], ["[2IV-10] page 165", [3]]]] Type: [2IV*-10], p. 165 [2401, Mat([7, 4]), [x^6 - 21*x^4 + 147*x^2 + 378818692265664781682717625600 , 0], [7, [5, [Mod(0, 7), Mod(0, 7)]], ["(tame) [2IV*-10] page 165", [3]]]] [59049, Mat([3, 10]), [x^6 - 9*x^4 + 27*x^2 + 50031545098999680, 0], [3, [5, [Mod(0, 3), Mod(0, 3)]], ["[2IV*-10] page 165", [3]]]] Type: [IV-IV-10], p. 165 [2401, Mat([7, 4]), [x^6 - 3*x^5 + 3*x^4 + 248930711762415449007872216849586 08586849291716964097*x^3 - 7467921352872463470236166505487582576054787515089 2147*x^2 + 74679213528724634702361665054875825760547875150892147*x + 1194867 416459594155237786640878013212168766002414274352, 0], [7, [5, [Mod(0, 7), Mo d(0, 7)]], ["(tame) [IV-IV-10] page 165", [3, 3]]]] Type: [IV-IV*-10], p. 165 [2401, Mat([7, 4]), [x^6 - 3*x^5 + 3*x^4 + 248930711762415449007872216849586 08586849291716966449*x^3 - 7467921352872463470236166505487582576054787515089 2147*x^2 + 74679213528724634702361665054875825760547875150892147*x + 5974337 0822979707761889332043900660608438300120713717600, 0], [7, [5, [Mod(0, 7), M od(0, 7)]], ["(tame) [IV-IV*-10] page 165", [3, 3]]]] Type: [IV*-IV*-10], p. 166 [2401, Mat([7, 4]), [343*x^6 - 147*x^5 + 21*x^4 + 41837784725909164514753083 4859099334519176045887014771549*x^3 - 17930479168246784792037035779675685765 1075448237292044947*x^2 + 25614970240352549702910051113822408235867921176756 006421*x + 7318562925815014200831443175377830924533691764787430406, 0], [7, [5, [Mod(0, 7), Mod(0, 7)]], ["(tame) [IV*-IV*-10] page 166", [3, 3]]]] Type: [II-III-10], p. 166 [2401, Mat([7, 4]), [x^6 - 3*x^5 + 44567640326363195900190045974568010*x^4 - 133702920979089587700570137923704015*x^3 + 13370292097908958770057013792370 4021*x^2 + 267405841958179175401140275847408042*x, 0], [7, [5, [Mod(0, 7), M od(6, 7)]], ["(tame) [II-III-10] page 166", [2]]]] Type: [II-III*-10], p. 166 [2401, Mat([7, 4]), [x^6 - 3*x^5 + 2183814375991796599109312252753832346*x^4 - 6551443127975389797327936758261497023*x^3 + 65514431279753897973279367582 61497029*x^2 + 13102886255950779594655873516522994058*x, 0], [7, [5, [Mod(0, 7), Mod(6, 7)]], ["(tame) [II-III*-10] page 166", [2]]]] Type: [II*-III-10], p. 166 [2401, Mat([7, 4]), [x^6 - 3*x^5 + 44567640326363195900190045974568010*x^4 - 133702920979089587700570137923687215*x^3 + 13370292097908958770057013792370 4021*x^2 + 749003763324859870298593912648589925642*x, 0], [7, [5, [Mod(0, 7) , Mod(6, 7)]], ["(tame) [II*-III-10] page 166", [2]]]] Type: [II*-III-(-1)], p. 167 [2401, Mat([7, 4]), [x^5 + 7*x^3 + 49*x^2 + 343, 0], [7, [5, [Mod(0, 7), Mod (6, 7)]], ["[II*-III-(-1)] page 167", [2]]]] Type: [II*-III*-10], p. 167 [2401, Mat([7, 4]), [343*x^6 - 147*x^5 + 74904833096518623349449410269456449 3670*x^4 - 321020713270794100069068901154813354373*x^3 + 4586010189582772858 1295557307830479203*x^2 + 104823090047606236757246988132183952464*x, 0], [7, [5, [Mod(0, 7), Mod(6, 7)]], ["(tame) [II*-III*-10] page 167", [2]]]] Type: [IV-III-10], p. 167 [2401, Mat([7, 4]), [x^6 - 3*x^5 + 44567640326363195900190045974568010*x^4 - 133702920979089587700570137923703973*x^3 + 13370292097908958770057013792370 4021*x^2 + 2139246735665433403209122206779264336*x, 0], [7, [5, [Mod(0, 7), Mod(6, 7)]], ["(tame) [III-IV-10] page 167", [6]]]] [2187, Mat([3, 7]), [x^6 - 3*x^5 + 36472996377170786406*x^4 - 10941898913151 2359201*x^3 + 109418989131512359209*x^2 + 291783971017366291224*x, 0], [3, [ 5, [Mod(0, 3), Mod(0, 3)]], ["[III-IV-10] pages 161-177", [6]]]] Type: [IV-III*-10], p. 167 [2401, Mat([7, 4]), [x^6 - 3*x^5 + 2183814375991796599109312252753832346*x^4 - 6551443127975389797327936758261496981*x^3 + 65514431279753897973279367582 61497029*x^2 + 104823090047606236757246988132183952464*x, 0], [7, [5, [Mod(0 , 7), Mod(6, 7)]], ["(tame) [III*-IV-10] page 167", [6]]]] [2187, Mat([3, 7]), [x^6 - 3*x^5 + 328256967394537077630*x^4 - 9847709021836 11232873*x^3 + 984770902183611232881*x^2 + 2626055739156296621016*x, 0], [3, [5, [Mod(0, 3), Mod(0, 3)]], ["[III*-IV-10] pages 162-177", [6]]]] Type: [IV-III*-(-1)], p. 167 [2401, Mat([7, 4]), [x^6 + 7*x^4 + 7*x^3 + 49*x, 0], [7, [5, [Mod(0, 7), Mod (6, 7)]], ["[IV-III*-(-1)] page 167", [6]]]] Type: [IV*-III-10], p. 168 [2401, Mat([7, 4]), [x^6 - 3*x^5 + 44567640326363195900190045974568010*x^4 - 133702920979089587700570137923701621*x^3 + 13370292097908958770057013792370 4021*x^2 + 106962336783271670160456110338963216800*x, 0], [7, [5, [Mod(0, 7) , Mod(6, 7)]], ["(tame) [III-IV*-10] page 168", [6]]]] Type: [IV*-III*-10], p. 168 [2401, Mat([7, 4]), [343*x^6 - 147*x^5 + 74904833096518623349449410269456449 3670*x^4 - 321020713270794100069068901154813354415*x^3 + 4586010189582772858 1295557307830479203*x^2 + 13102886255950779594655873516522994058*x, 0], [7, [5, [Mod(0, 7), Mod(6, 7)]], ["(tame) [III*-IV*-10] page 168", [6]]]] Type: [2III-10], p. 168 [2401, Mat([7, 4]), [x^6 - 21*x^4 + 3909821048582988049*x^3 + 147*x^2 - 2736 8747340080916343*x - 343, 0], [7, [5, [Mod(6, 7), Mod(6, 7)]], ["(tame) [2II I-10] page 168", [2]]]] [81, Mat([3, 4]), [x^6 - 9*x^4 + 31381059609*x^3 + 27*x^2 - 94143178827*x - 27, 0], [3, [5, [Mod(0, 3), Mod(0, 3)]], ["[2III-10] page 168", [2]]]] Type: [2III*-10], p. 168 [2401, Mat([7, 4]), [x^6 - 21*x^4 + 27368747340080916343*x^3 + 147*x^2 - 191 581231380566414401*x - 343, 0], [7, [5, [Mod(6, 7), Mod(6, 7)]], ["(tame) [2 III*-10] page 168", [2]]]] [81, Mat([3, 4]), [x^6 - 9*x^4 + 94143178827*x^3 + 27*x^2 - 282429536481*x - 27, 0], [3, [5, [Mod(0, 3), Mod(0, 3)]], ["[2III*-10] page 168", [2]]]] Type: [III-III-10], p. 169 [2401, Mat([7, 4]), [x^6 - 3*x^5 + 44567640326363195900190045974568017*x^4 - 133702920979089587700570137923704029*x^3 + 44567640326363195900190045974568 0070*x^2 - 356541122610905567201520367796544056*x, 0], [7, [5, [Mod(6, 7), M od(6, 7)]], ["(tame) [III-III-10] page 169", [2, 2]]]] Type: [III-III*-10], p. 169 [2401, Mat([7, 4]), [x^6 - 3*x^5 + 44567640326363195900190045974568353*x^4 - 133702920979089587700570137923704365*x^3 + 15420403552921665781465755907200 530422*x^2 - 15331268272268939389665375815251394408*x, 0], [7, [5, [Mod(6, 7 ), Mod(6, 7)]], ["(tame) [III-III*-10] page 169", [2, 2]]]] Type: [III*-III*-{10}], p. 169 [2401, Mat([7, 4]), [343*x^6 - 147*x^5 + 74904833096518623349449410269456449 3719*x^4 - 321020713270794100069068901154813354429*x^3 + 1528670063194257619 37651857692768264010*x^2 - 17470515007934372792874498022030658744*x, 0], [7, [5, [Mod(6, 7), Mod(6, 7)]], ["(tame) [III*-III*-10] page 169", [2, 2]]]] Type: [I{9-0-0}], p. 170 [7, Mat([7, 1]), [x^5 + 40353610*x^3 + x^2 + 121060821*x + 40353607, 0], [7, [2, [Mod(2, 7)]], ["(tame) [I{9-0-0}] page 170", [9]]]] Type: [I{9}-I{0}-10], p. 170 [7, Mat([7, 1]), [x^5 - 2*x^4 + 19100417282727083957224305458025611*x^3 + 50 8021860739623327121353632198048587323823689491995*x^2 - 10160437207084759789 80782478311514614647856768035178*x + 205005150237173513518523762302840650436 56128020898248641608, 0], [7, [6, [Mod(2, 7)]], ["(tame) [I{0}-I{9}-10] page 170", [9]]]] [3, Mat([3, 1]), [x^5 - 2*x^4 - 12157665459056909117*x^3 + 42391158299531534 432408290803*x^2 - 84782555861919303105175385286*x + 83442755948935574997537 1623128484, 0], [3, [6, [Mod(0, 3)]], ["(tame) [I{0}-I{9}-10] page 170", [9] ]]] Type: [I{0}-I*{9}-10], p. 170 [49, Mat([7, 2]), [x^6 + 4*x^5 + 19100417282727083957224307394998728*x^4 + 5 08021860739623479924691894014720245118274940175011*x^3 + 3556153062945129319 148051483501814963799504492542834*x^2 + 100452521126907926660581690807062797 6335864597950580018666977*x + 7031676478883553015620189472307296962082581739 484589084102397, 0], [7, [6, [Mod(2, 7)]], ["(tame) [I{0}-I*{9}-10] page 170 ", [4]]]] [9, Mat([3, 2]), [x^6 - 12157665459056751660*x^4 + 4239115825090087259618057 5607*x^3 + 127171321168158531362286712374*x^2 + 7509466510672336877795600427 053229*x + 22528399551400256301066821173173441, 0], [3, [6, [Mod(0, 3)]], [" [I{0}-I*{9}-10] page 170", [4]]]] Type: [I{9}-I{0}*-10], p. 171 [343, Mat([7, 3]), [x^5 - 2*x^4 + 935920446853627113903990965506281755*x^3 + 174251498233690812433669658087456032299963111086892049*x^2 - 34850299642961 3861779505001656767519159936482237292310*x + 7031676653135051513685365046987 434309974051911168099284071544, 0], [7, [6, [Mod(2, 7)]], ["(tame) [I{9}-I*{ 0}-10] page 170", [18, 2]]]] Type: [I*{9-0-0}], p. 171 [2401, Mat([7, 4]), [7*x^5 + 282475270*x^3 + 7*x^2 + 847425747*x + 282475249 , 0], [7, [2, [Mod(2, 7)]], ["(tame) [I*{9-0-0}] page 171", [4, 2, 2]]]] Type: [I*{9}-I{0}*-10], p. 171 [2401, Mat([7, 4]), [x^6 + 4*x^5 + 935920446853627113903990967443254872*x^4 + 174251498233690819921033232916472943531890842723624217*x^3 + 1219760489486 456222471317833459850493873847680657395212*x^2 + 344552147465294121823456159 637489836481536621034944927824583035*x + 24118650322570587620837872021372610 10629601295382324365507824195, 0], [7, [6, [Mod(2, 7)]], ["(tame) [I*{0}-I*{ 9}-10] page 171", [4, 2, 2]]]] Type: [II{9-0}], p. 171 [343, Mat([7, 3]), [x^6 - 2*x^5 + 5764823*x^4 - 42*x^3 + 121060891*x^2 - 98* x + 282475298, 0], [7, [2, [Mod(0, 7)]], ["(tame) [II{9-0}] page 171", [36]] ]] Type: [II*{9-0}], p. 172 [49, Mat([7, 2]), [7*x^6 - 14*x^5 + 40353761*x^4 - 294*x^3 + 847426237*x^2 - 686*x + 1977327086, 0], [7, [2, [Mod(0, 7)]], ["(tame) [II*{9-0}] page 172" , []]]] Type: [II-I{9}-10], p. 172 [343, Mat([7, 3]), [x^5 - 2*x^4 + 40353608*x^3 + 355615302517736355725531738 3565515512407041673852007*x^2 - 71123060503547271145106347671310310248140833 47704014*x + 143503605166021459462966633611988455305592896146287740491256, 0 ], [7, [6, [Mod(0, 7)]], ["(tame) [I{9}-II-10] page 172", [9]]]] Type: [II*-I{9}-10], p. 172 [343, Mat([7, 3]), [x^5 - 2*x^4 + 40353608*x^3 + 853832341345084990097001703 7940802745289307058918668807*x^2 - 17076646826901699801940034075881605490578 614117837337614*x + 34455215600361752417058288730238428118872854364723686491 9505656, 0], [7, [6, [Mod(0, 7)]], ["(tame) [I{9}-II*-10] page 172", [9]]]] Type: [IV-I{9}-10], p. 173 [343, Mat([7, 3]), [x^5 - 2*x^4 + 40353608*x^3 + 248930711762415449007872216 84958608586849291716964049*x^2 - 4978614235248308980157444336991721717369858 3433928098*x + 1004525236162150216240766435283919187139150273024014183438792 , 0], [7, [6, [Mod(0, 7)]], ["(tame) [I{9}-IV-10] page 173", [9, 3]]]] Type: [IV*-I{9}-10], p. 173 [343, Mat([7, 3]), [x^5 - 2*x^4 + 40353608*x^3 + 121976048763583570013857386 2562971820755615294131238401*x^2 - 24395209752716714002771477251259436415112 30588262476802*x + 492217365719453605957975553289120401698183633781766949885 00808, 0], [7, [6, [Mod(0, 7)]], ["(tame) [I{9}-IV*-10] page 173", [9, 3]]]] Type: [II-I*{9}-10], p. 173 [2401, Mat([7, 4]), [x^6 + 4*x^5 + 1977326732*x^4 + 355615302517736355725531 7383565515512407053537812471*x^3 + 14224612100709454229021269534262062049628 166695408028*x^2 + 703167643976587000304355161166839129604312116674559885295 1124*x + 42190058894638237831031485792393199392975843893780593635051248, 0], [7, [6, [Mod(0, 7)]], ["(tame) [I*{9}-II-10] page 173", [4]]]] Type: [II*-I*{9}-10], p. 174 [2401, Mat([7, 4]), [x^6 + 4*x^5 + 1977326732*x^4 + 853832341345084990097001 7037940802745289307070782629271*x^3 + 34153293653803399603880068151763210981 157228235674675228*x^2 + 168830551318778538773075674196158075017995339213561 82845935648724*x + 101298331406026409032306597387536071742535001188967205317 758046448, 0], [7, [6, [Mod(0, 7)]], ["(tame) [I*{9}-II*-10] page 174", [4]] ]] Type: [II*-I*{9}-(-1)], p. 174 [2401, Mat([7, 4]), [7*x^5 - 14*x^4 + 282475256*x^3 + 343*x^2 - 686*x + 1384 1287544, 0], [7, [6, [Mod(0, 7)]], ["(tame) [I*{9}-II*--1] page 174", [4]]]] Type: [IV-I*{9}-10], p. 174 [2401, Mat([7, 4]), [x^6 + 4*x^5 + 1977326732*x^4 + 248930711762415449007872 21684958608586849303580924513*x^3 + 9957228470496617960314888673983443434739 7166867856196*x^2 + 49221735078361090021304861281678739072301848167219191970 657868*x + 295330412262467664817220400546752395750830907256464155445358736, 0], [7, [6, [Mod(0, 7)]], ["(tame) [I*{9}-IV-10] page 174", [12]]]] Type: [IV*-I*{9}-10], p. 174 [2401, Mat([7, 4]), [x^6 + 4*x^5 + 1977326732*x^4 + 121976048763583570013857 3862562971820755615305995198865*x^3 + 48790419505433428005542954502518872830 22461176524953604*x^2 + 2411865018839693411043938202802258214542790560193740 406562235532*x + 14471190200860915576043799626790867391790714455566743616822 578064, 0], [7, [6, [Mod(0, 7)]], ["(tame) [I*{9}-IV*-10] page 174", [12]]]] Type: [IV*-I*{9}-(-1)], p. 175 [2401, Mat([7, 4]), [7*x^5 - 14*x^4 + 282475256*x^3 + 49*x^2 - 98*x + 197732 6792, 0], [7, [6, [Mod(0, 7)]], ["(tame) [I*{9}-IV*--1] page 174", [12]]]] [2187, Mat([3, 7]), [3*x^5 - 6*x^4 + 59052*x^3 + 9*x^2 - 18*x + 177156, 0], [3, [6, [Mod(0, 3)]], ["[I*{9}-IV*--1] pages 159-177", [12]]]] Type: [IV-II{9}], p. 175 [343, Mat([7, 3]), [x^6 - 2*x^5 + 40353608*x^4 + 7*x^3 - 14*x^2 + 282475256* x, 0], [7, [2, [Mod(0, 7)]], ["(tame) [II{9}-IV] page 175", [29]]]] [729, Mat([3, 6]), [x^6 - 2*x^5 + 19684*x^4 + 3*x^3 - 6*x^2 + 59052*x, 0], [ 3, [6, [Mod(0, 3)]], ["[IV-II{9}] page 175", [29]]]] Type: [IV*-II{9}], p. 175 [343, Mat([7, 3]), [x^6 - 2*x^5 + 5764802*x^4 + 49*x^3 - 98*x^2 + 282475298* x, 0], [7, [2, [Mod(0, 7)]], ["(tame) [II{9}-IV*] page 175", [28]]]] [729, Mat([3, 6]), [x^6 - 2*x^5 + 6562*x^4 + 9*x^3 - 18*x^2 + 59058*x, 0], [ 3, [6, [Mod(0, 3)]], ["[IV*-II{9}] page 175", [28]]]] Type: [IV*-II{0}], p. 175 [343, Mat([7, 3]), [7*x^5 + 49*x^3 + 49*x^2 + 343, 0], [7, [2, [Mod(0, 7)]], ["[IV*-II{0}] page 175", []]]] [729, Mat([3, 6]), [3*x^5 + 9*x^3 + 9*x^2 + 27, 0], [3, [6, [Mod(0, 3)]], [" [IV*-II{0}] page 175", []]]] Type: [II-II*{9}], p. 176 [2401, Mat([7, 4]), [x^5 + 282475249*x^3 + 7*x^2 + 1977326743, 0], [7, [2, [ Mod(0, 7)]], ["[II-II*{9}] page 176", [2, 2]]]] [2187, Mat([3, 7]), [x^5 + 59049*x^3 + 3*x^2 + 177147, 0], [3, [6, [Mod(0, 3 )]], ["[II-II*{9}] page 176", [2, 2]]]] Type: [II*-II*{9}], p. 176 [2401, Mat([7, 4]), [7*x^6 - 14*x^5 + 282475256*x^4 + 49*x^3 - 98*x^2 + 1977 326792*x, 0], [7, [2, [Mod(0, 7)]], ["(tame) [II*-II*{9}] page 176", [2, 2]] ]] [2187, Mat([3, 7]), [3*x^6 - 6*x^5 + 59052*x^4 + 9*x^3 - 18*x^2 + 177156*x, 0], [3, [6, [Mod(0, 3)]], ["[II*-II*{9}] page 176", [2, 2]]]] Type: [III-I{9}-10], p. 176 [343, Mat([7, 3]), [x^5 - 2*x^4 + 44567640326363195900190046014921615*x^3 - 89135280652726391800380091949136014*x^2 + 1798465087215052472983476240759695 323819256*x, 0], [7, [6, [Mod(6, 7)]], ["(tame) [I{9}-III-10] page 176", [18 ]]]] [27, Mat([3, 3]), [x^5 - 2*x^4 + 36472996377170806087*x^3 - 7294599275434157 2806*x^2 + 717934460688229759556652*x, 0], [3, [6, [Mod(0, 3)]], ["[I{9}-III -10] pages 159-177", [18]]]] Type: [III*-I{9}-10], p. 176 [343, Mat([7, 3]), [x^5 - 2*x^4 + 2183814375991796599109312252794185951*x^3 - 4367628751983593198218624505507664686*x^2 + 881247892735375711761903357972 25070867143544*x, 0], [7, [6, [Mod(6, 7)]], ["(tame) [I{9}-III*-10] page 176 ", [18]]]] [27, Mat([3, 3]), [x^5 - 2*x^4 + 328256967394537097311*x^3 - 656513934789074 155254*x^2 + 6461410146194067836009868*x, 0], [3, [6, [Mod(0, 3)]], ["[I{9}- III*-10] pages 159-177", [18]]]] Type: [III-I*{9}-10], p. 177 [2401, Mat([7, 4]), [x^6 + 4*x^5 + 44567640326363195900190047951894732*x^4 + 267405841958179175401140283756715034*x^3 + 88124786777749712899851365386582 460699453771*x^2 + 528748722538339171106362420127476948226402066*x - 6168735 09628062366290756156815389740634465608, 0], [7, [6, [Mod(6, 7)]], ["(tame) [ I*{9}-III-10] page 177", [4, 2]]]] [81, Mat([3, 4]), [x^6 + 36472996377170963544*x^4 + 72945992754341572814*x^3 + 6460972470237541785510147*x^2 + 12922163778453346599281658*x - 1938324566 7680019897328164, 0], [3, [6, [Mod(0, 3)]], ["[I*{9}-III-10] pages 159-177", [4, 2]]]] Type: [III*-I*{9}-10], p. 177 [2401, Mat([7, 4]), [x^6 + 4*x^5 + 2183814375991796599109312254731159068*x^4 + 13102886255950779594655873524432301050*x^3 + 4318114552109735932092716903 942542282683541067*x^2 + 25908687404378619384211758586246368564860027954*x - 30226801971775055948247051683954096626707029144, 0], [7, [6, [Mod(6, 7)]], ["(tame) [I*{9}-III*-10] page 177", [4, 2]]]] [81, Mat([3, 4]), [x^6 + 328256967394537254768*x^4 + 656513934789074155262*x ^3 + 58148752232137876078094403*x^2 + 116299474006080119382197514*x - 174449 211009120179071701948, 0], [3, [6, [Mod(0, 3)]], ["[I*{9}-III*-10] pages 159 -177", [4, 2]]]] Type: [III*-I*{9}-(-1)], p. 177 [2401, Mat([7, 4]), [7*x^5 - 14*x^4 + 282475305*x^3 - 98*x^2 + 1977326792*x, 0], [7, [6, [Mod(6, 7)]], ["(tame) [I*{9}-III*--1] page 177", [4, 2]]]] Type: [III-II{9}], p. 177 [343, Mat([7, 3]), [x^6 - 2*x^5 + 40353608*x^4 + 7*x^2 - 14*x + 282475256, 0 ], [7, [2, [Mod(6, 7)]], ["(tame) [II{9}-III] page 177", [19]]]] Type: [III*-II{9}], p. 178 [343, Mat([7, 3]), [x^6 - 2*x^5 + 5764802*x^4 + 343*x^2 - 686*x + 1977327086 , 0], [7, [2, [Mod(6, 7)]], ["(tame) [II{9}-III*] page 178", [19]]]] Type: [III*-II{0}], p. 178 [343, Mat([7, 3]), [7*x^6 + 49*x^4 + 49*x^2 + 343, 0], [7, [2, [Mod(6, 7)]], ["(tame) [II{0}-III*] page 178", []]]] Type: [III-II*{9}], p. 178 [2401, Mat([7, 4]), [x^6 + 282475249*x^4 + 7*x^2 + 1977326743, 0], [7, [2, [ Mod(6, 7)]], ["(tame) [II*{9}-III] page 178", [8]]]] Type: [III*-II*{9}], p. 178 [2401, Mat([7, 4]), [49*x^6 + 1977326743*x^4 + 7*x^2 + 282475249, 0], [7, [2 , [Mod(6, 7)]], ["(tame) [II*{9}-III*] page 178", [8]]]] Type: [I{9-8-0}], p. 179 [49, Mat([7, 2]), [x^5 + x^4 + 46118407*x^3 + 34588805*x^2 + 232630473633600 *x - 232630554340814, 0], [7, [3, []], ["(tame) [I{8-9-0}] page 179", [72]]] ] Type: [I{9}-I{8}-10}], p. 179 [49, Mat([7, 2]), [x^5 + 79792266297611999*x^4 + 256923577521058878088611317 639703031862407*x^3 + 205005145156954900983818558659781116742032881369987397 51195*x^2 - 41001029029909867670917466553668751161754024538661404934400*x + 118181407081110395672359026541012872529905940276396171922010844814, 0], [7, [7, []], ["(tame) [I{8}-I{9}-10] page 179", [72]]]] Type: [I*{9-8-0}], p. 180 [2401, Mat([7, 4]), [7*x^5 + 7*x^4 + 322828849*x^3 + 242121635*x^2 + 1628413 315435200*x - 1628413880385698, 0], [7, [3, []], ["(tame) [I*{8-9-0}] page 1 80", [4, 2, 2]]]] [81, Mat([3, 4]), [3*x^5 + 3*x^4 + 78729*x^3 + 39363*x^2 + 387361440*x - 387 479538, 0], [3, [3, []], ["(tame) [I*{8-9-0}] page 180", [4, 2, 2]]]] Type: [I*{9}-I*{8}-10], p. 180 [2401, Mat([7, 4]), [x^6 + 558545864083284011*x^5 + 125892552985318850263419 64618171002060370009*x^4 + 7031676478883553330351571935604422778407017230014 542438128339*x^3 + 281267059190903660066737582393121131015113920617862950327 59138*x^2 + 1986274486911633708389059586001471994720392681842749646477323061 061338*x + 11917647427750508601928684316018206546318610433380303440718925199 651500, 0], [7, [7, []], ["(tame) [I*{8}-I*{9}-10] page 180", [4, 2, 2]]]] Type: [I{9}-I*{8}-10], p. 180 [343, Mat([7, 3]), [x^5 + 558545864083284005*x^4 + 1798465042647412146620279 223477921223036843*x^3 + 100452521126907903640229144920187323147932185427354 5939119501*x^2 - 20090504224655835266657461170142416866476292458123049372930 94*x + 40536216601669598101144906108238208297572724431553769920914920922744, 0], [7, [7, []], ["(tame) [I{9}-I*{8}-10] page 180", [18, 2]]]] [27, Mat([3, 3]), [x^5 + 10460353201*x^4 + 717897987691831668083527*x^3 + 75 09466513543928828768912373164901*x^2 - 15018918898855459881467074562933778*x + 147816338880860903040887156922341555148, 0], [3, [7, []], ["[I{9}-I*{8}-1 0] page 180", [18, 2]]]] Type: [2I{8}-10], p. 181 [343, Mat([7, 3]), [x^6 + 1977326722*x^4 + 9387480337620071731394*x^2 + 1856 2115855305211939015772541728, 0], [7, [7, []], ["(tame) [2I{8}-10] page 181" , [8]]]] [27, Mat([3, 3]), [x^6 + 177138*x^4 + 2541864765474*x^2 + 450276280295106672 , 0], [3, [7, []], ["[2I{8}-10] page 181", [8]]]] Type: [2I{9}-10}], p. 181 [343, Mat([7, 3]), [x^6 + 1977326722*x^4 + 9387480337647754305649*x^3 - 2768 2574255*x^2 + 18562115855305211938918883531664*x + 96889010064, 0], [7, [7, []], ["(tame) [2I{9}-10] page 181", [9]]]] Type: [2I{8}-0], p. 181 [343, Mat([7, 3]), [x^6 - 7*x^4 + 117600*x^2 + 823886, 0], [7, [3, []], ["(t ame) [2I{8}-0] page 181", [8]]]] Type: [2I{9}-0], p. 181 [343, Mat([7, 3]), [x^6 - 7*x^4 + 117649*x^3 - 49*x^2 + 823543*x + 343, 0], [7, [3, []], ["(tame) [2I{9}-0] page 181", [9]]]] Type: [2I*{8}-10}], p. 181 [2401, Mat([7, 4]), [x^6 + 1977326743*x^5 - 21*x^4 - 27682574402*x^3 + 65712 362363534280139690*x^2 + 129934811447123020117269034708856*x - 4599865365447 39960977144, 0], [7, [7, []], ["(tame) [2I*{8}-10] page 181", [2, 2]]]] [81, Mat([3, 4]), [x^6 + 177147*x^5 - 9*x^4 - 1062882*x^3 + 7625597485014*x^ 2 + 1350851717674586412*x - 22876792454988, 0], [3, [7, []], ["[2I*{8}-10] p ages 159, 181", [2, 2]]]] Type: [2I*{9}-10}], p. 181 [2401, Mat([7, 4]), [x^6 + 1977326743*x^5 - 21*x^4 + 65712362363506597565141 *x^3 + 129934811447123020117172145698596*x^2 - 459986536544643071966394*x - 343, 0], [7, [7, []], ["(tame) [2I*{9}-10] page 181", [4]]]] Type: [II{9-8}], p. 182 [343, Mat([7, 3]), [x^6 - 2*x^5 + 46118416*x^4 - 80707228*x^3 + 232630877169 677*x^2 - 564950498*x + 1628413880385698, 0], [7, [3, []], ["[II{9-8}] page 182", [36]]]] [27, Mat([3, 3]), [x^6 - 2*x^5 + 26248*x^4 - 39372*x^3 + 129238581*x^2 - 118 098*x + 387479538, 0], [3, [3, []], ["[II{9-8}] page 182", [36]]]] Type: [III{8}], p. 182 [2401, Mat([7, 4]), [49*x^5 - 14*x^3 + 2402*x, 0], [7, [3, []], ["(tame) [II I{8}] page 182", [2, 2]]]] Type: [III{9}], p. 182 [2401, Mat([7, 4]), [49*x^5 - 14*x^3 + 16807*x^2 + x, 0], [7, [3, []], ["(ta me) [III{9}] page 182", [4]]]] Type: [I{9-8-5}], pp. 182-183 [49, Mat([7, 2]), [x^6 - 6*x^5 + 46135228*x^4 - 265214472*x^3 + 233406173743 369*x^2 - 931878986337810*x + 3910752249023424154, 0], [7, [4, []], ["(tame) [I{5-8-9}] page 182", [157]]]] Type: [I*{9-8-5}], pp. 183 [2401, Mat([7, 4]), [7*x^6 - 42*x^5 + 322946596*x^4 - 1856501304*x^3 + 16338 43216203583*x^2 - 6523152904364670*x + 27375265743163969078, 0], [7, [4, []] , ["(tame) [I*{5-8-9}] page 183", [4, 4]]]] Type: [II{9-8}], p. 183 [343, Mat([7, 3]), [x^6 - 2*x^5 + 5764788*x^4 + 28*x^3 - 80589530*x^2 - 2353 96*x + 678505665796, 0], [7, [4, []], ["(tame) [II{9-8}] page 183", [44]]]] [27, Mat([3, 3]), [x^6 - 2*x^5 + 6556*x^4 + 12*x^3 - 38634*x^2 - 1476*x + 48 42756, 0], [3, [4, []], ["(tame) [II{9-8}] page 183", [44]]]] Type: [II{9-9}], p. 183 [343, Mat([7, 3]), [x^6 - 2*x^5 + 5764788*x^4 + 117677*x^3 - 80942477*x^2 + 678223190400*x + 282475298, 0], [7, [4, []], ["(tame) [II{9-9}] page 183", [ 45]]]] [27, Mat([3, 3]), [x^6 - 2*x^5 + 6556*x^4 + 741*x^3 - 40821*x^2 + 4783680*x + 59058, 0], [3, [4, []], ["(tame) [II{9-9}] page 183", [45]]]] Type: [II*{9-8}], p. 184 [343, Mat([7, 3]), [7*x^6 - 14*x^5 + 40353516*x^4 + 196*x^3 - 564126710*x^2 - 1647772*x + 4749539660572, 0], [7, [4, []], ["(tame) [II*{9-8}] page 184", [8]]]] Type: [II*{9-9}], p. 184 [343, Mat([7, 3]), [7*x^6 - 14*x^5 + 40353516*x^4 + 823739*x^3 - 566597339*x ^2 + 4747562332800*x + 1977327086, 0], [7, [4, []], ["(tame) [II*{9-9}] page 184", [9]]]] Type: [III{12}], p. 184 [2401, Mat([7, 4]), [x^6 - 14*x^3 + 117698, 0], [7, [4, []], ["[III{12}] pag e 184", [3, 3]]]] [59049, Mat([3, 10]), [x^6 - 6*x^3 + 738, 0], [3, [4, []], ["[III{12}] page 184", [3, 3]]]] Type: [III{13}], p. 184 [2401, Mat([7, 4]), [x^6 - 14*x^3 + 117649*x + 49, 0], [7, [4, []], ["[III{1 3}] page 184", [9]]]] [59049, Mat([3, 10]), [x^6 - 6*x^3 + 729*x + 9, 0], [3, [4, []], ["[III{13}] page 184", [9]]]] Type: [III{14}], p. 184 [2401, Mat([7, 4]), [x^6 - 14*x^3 + 117649*x^2 + 49, 0], [7, [4, []], ["[III {14}] page 184", [9]]]] [59049, Mat([3, 10]), [x^6 - 6*x^3 + 729*x^2 + 9, 0], [3, [4, []], ["[III{14 }] page 184", [9]]]] Type: [III*{6}], p. 184 [2401, Mat([7, 4]), [7*x^6 - 98*x^3 + 17150, 0], [7, [4, []], ["[III*{6}] pa ge 184", []]]] [59049, Mat([3, 10]), [3*x^6 - 18*x^3 + 270, 0], [3, [5, [Mod(0, 3), Mod(0, 3)]], ["[III*{6}] page 184", []]]] Type: [III*{7}], p. 184 [2401, Mat([7, 4]), [7*x^6 - 98*x^3 + 16807*x + 343, 0], [7, [4, []], ["[III *{7}] page 184", []]]] [59049, Mat([3, 10]), [3*x^6 - 18*x^3 + 243*x + 27, 0], [3, [5, [Mod(0, 3), Mod(0, 3)]], ["[III*{7}] page 184", []]]] Type: [III{8}], p. 184 [2401, Mat([7, 4]), [x^6 - 14*x^3 + 2401*x^2 + 49, 0], [7, [4, []], ["[III{8 }] page 184", [9]]]] [59049, Mat([3, 10]), [x^6 - 6*x^3 + 81*x^2 + 9, 0], [3, [5, [Mod(0, 3), Mod (0, 3)]], ["[III{8}] page 184", [9]]]] echo = 1 ? genus2red(-x^6-6*x^2-7,3) [81, Mat([3, 4]), [-x^6 - 6*x^2 - 7, 0], [3, [7, []], ["(tame) [I*{1}-I*{1}- 0] page 180", [4, 4]]]] ? genus2red(-9*x^6+6*x^5-8*x^4-5*x^3+5*x^2-10*x+3,3) [9, Mat([3, 2]), [-9*x^6 + 6*x^5 - 8*x^4 - 5*x^3 + 5*x^2 - 10*x + 3, 0], [3, [3, []], ["(tame) [I{2-8-0}] page 179", [8, 2]]]] ? genus2red(3*x^6+3*x^4+3*x^3+x^2-5*x-5,3) [27, Mat([3, 3]), [3*x^6 + 3*x^4 + 3*x^3 + x^2 - 5*x - 5, 0], [3, [2, [Mod(0 , 3)]], ["(tame) [II{4}-III] page 177", [9]]]] ? genus2red(-3*x^6+6*x^5-1*x^4+6*x^3-6*x^2-1*x-6,3) [3, Mat([3, 1]), [-3*x^6 + 6*x^5 - x^4 + 6*x^3 - 6*x^2 - x - 6, 0], [3, [6, [Mod(2, 3)]], ["(tame) [I{0}-I{1}-1] page 170", []]]] ? genus2red((x^3+2*x+1)*(x^3+3^2*x^2+3^8),3) [3, Mat([3, 1]), [x^6 + 9*x^5 + 2*x^4 + 6580*x^3 + 9*x^2 + 13122*x + 6561, 0 ], [3, [6, [Mod(1, 3)]], ["(tame) [I{0}-I{2}-1] page 170", [2]]]] ? P=x^6+4*x^5-24*x^4-16*x^3-52*x^2-48*x; ? genus2red(P,3) [9, Mat([3, 2]), [x^6 + 4*x^5 - 24*x^4 - 16*x^3 - 52*x^2 - 48*x, 0], [3, [7, []], ["(tame) [I{2}-I{2}-1] page 179", [2, 2]]]] ? P=x^6+4*x^5+24*x^4+32*x^3+56*x^2+48*x+24; ? genus2red(P,3) [9, Mat([3, 2]), [x^6 + 4*x^5 + 24*x^4 + 32*x^3 + 56*x^2 + 48*x + 24, 0], [3 , [7, []], ["(tame) [I{1}-I{1}-1] page 179", []]]] ? P=24*x^5+56*x^4+76*x^3+33*x^2-4*x-20; ? genus2red(P,3) [9, Mat([3, 2]), [24*x^5 + 56*x^4 + 76*x^3 + 33*x^2 - 4*x - 20, 0], [3, [7, []], ["(tame) [I{2}-I{2}-1] page 179", [2, 2]]]] ? P=-3*x^6+6*x^5-25*x^4+36*x^3-69*x^2+38*x-39; ? genus2red(P,3) [9, Mat([3, 2]), [-3*x^6 + 6*x^5 - 25*x^4 + 36*x^3 - 69*x^2 + 38*x - 39, 0], [3, [7, []], ["(tame) [I{1}-I{1}-1] page 179", []]]] ? P=-5*x^5+5*x^4+10*x^3-7; ? genus2red([P,1],3) [9, Mat([3, 2]), [-5*x^5 + 5*x^4 + 10*x^3 - 7, 1], [3, [7, []], ["(tame) [I{ 1}-I{2}-1] page 179", [2]]]] ? P=-5*x^6-3*x^5-10*x^4-10*x^3-7; ? genus2red([P,1],3) [3, Mat([3, 1]), [-5*x^6 - 3*x^5 - 10*x^4 - 10*x^3 - 7, 1], [3, [6, [Mod(1, 3)]], ["(tame) [I{0}-I{1}-1] page 170", []]]] ? P=3*x^5+5*x^4+5*x-4; ? genus2red([P,1],3) [3, Mat([3, 1]), [3*x^5 + 5*x^4 + 5*x - 4, 1], [3, [6, [Mod(1, 3)]], ["(tame ) [I{0}-I{2}-1] page 170", [2]]]] ? Q=x^2+x;P=-9*x^6+6*x^5-8*x^4-5*x^3+5*x^2-10*x+3; ? genus2red([P,Q],3) [3, Mat([3, 1]), [-9*x^6 + 6*x^5 - 8*x^4 - 5*x^3 + 5*x^2 - 10*x + 3, x^2 + x ], [3, [6, [Mod(0, 3)]], ["(tame) [I{0}-I{12}-1] page 170", [12]]]] ? Q=x^3+1;P=-7*x^6+5*x^3+5*x^2-6*x+1; ? genus2red([P,Q],3) [3, Mat([3, 1]), [-7*x^6 + 5*x^3 + 5*x^2 - 6*x + 1, x^3 + 1], [3, [6, [Mod(2 , 3)]], ["(tame) [I{0}-I{1}-1] page 170", []]]] ? genus2red(27*x^5+97*x^4+118*x^3+60*x^2+13*x+1,3) [729, Mat([3, 6]), [27*x^5 + 97*x^4 + 118*x^3 + 60*x^2 + 13*x + 1, 0], [3, [ 6, [Mod(0, 3)]], ["[IV-II{6}] page 175", [20]]]] ? genus2red([-x^6-3*x^4-10*x^2-1,x],3) [729, Mat([3, 6]), [-x^6 - 3*x^4 - 10*x^2 - 1, x], [3, [5, [Mod(0, 3), Mod(0 , 3)]], ["[IV*-IV*-0] pages 160-175", [3, 3]]]] ? genus2red([-60*x^6-203*x^5-291*x^4-244*x^3-129*x^2-41*x-7,x^3+x^2+x+1]) [729, [2, -1; 3, 6], [-60*x^6 - 203*x^5 - 291*x^4 - 244*x^3 - 129*x^2 - 41*x - 7, x^3 + x^2 + x + 1], [[2, [5, [Mod(0, 2), Mod(0, 2)]], []], [3, [5, [Mo d(0, 3), Mod(0, 3)]], ["[2IV*-0] page 165", [3]]]]] ? genus2red(6*x^6+5*x^4+x^2+1,7) [2401, Mat([7, 4]), [6*x^6 + 5*x^4 + x^2 + 1, 0], [7, [5, [Mod(0, 7), Mod(0, 7)]], ["(tame) [II-II-0] page 163", []]]] ? genus2red([1,x^3-1]) [18225, [3, 6; 5, 2], [-x^3 + 1, x^3 + 1], [[3, [5, [Mod(0, 3), Mod(0, 3)]], ["[II-II-0] pages 159-174", []]], [5, [5, [Mod(0, 5), Mod(0, 5)]], ["[I{0}- II-0] page 159", []]]]] ? genus2red(x^5+1/5,5) [1953125, Mat([5, 9]), [25*x^5 + 5, 0], [5, [1, []], ["[VIII-4] page 157", [ ]]]] ? genus2red(273*x^6-38933/5*x^5-4483763/4*x^4+371954149/10*x^3+569046245/4*x^2+12389355*x-42117075,5) [125, Mat([5, 3]), [2730000*x^6 - 15573200*x^5 - 448376300*x^4 + 2975633192* x^3 + 2276184980*x^2 + 39645936*x - 26954928, 0], [5, [6, [Mod(3, 5)]], ["(t ame) [I{4}-I*{0}-0] page 170", [4, 2, 2]]]] ? genus2red(177*x^6+126*x^5-63*x^4+72*x+84,3) [729, Mat([3, 6]), [1593*x^6 - 2808*x^5 + 1962*x^4 - 676*x^3 + 113*x^2 - 4*x , 0], [3, [6, [Mod(0, 3)]], ["[I{5}-IV*-0] pages 159-177", [15]]]] ? genus2red(3*(4*x^6+6*x^5+3*x^4+8*x^3+9*x^2-3),3) [59049, Mat([3, 10]), [108*x^6 + 270*x^5 + 279*x^4 + 160*x^3 + 57*x^2 + 12*x + 1, 0], [3, [5, [Mod(0, 3), Mod(0, 3)]], ["[II-IV*-0] pages 159-174", [3]] ]] ? genus2red(x^6+27,3) [81, Mat([3, 4]), [x^6 + 27, 0], [3, [5, [Mod(0, 3), Mod(0, 3)]], ["[2I*{0}- 0] pages 159, 181", [2, 2]]]] ? genus2red(150*x^6+180*x^5-270*x^4+2040*x^3-1350*x^2+3060*x+270,3) [81, Mat([3, 4]), [1350*x^6 - 2160*x^5 + 1080*x^4 + 640*x^3 - 960*x^2 + 480* x - 80, 0], [3, [5, [Mod(0, 3), Mod(0, 3)]], ["[III*-III*-0] pages 162-177", [2, 2]]]] ? genus2red(-3*x^6-36*x^5-72*x^4+270*x^3+3,3) [2187, Mat([3, 7]), [-27*x^6 - 162*x^5 - 297*x^4 - 146*x^3 - 3*x^2 + 12*x + 2, 0], [3, [5, [Mod(0, 3), Mod(0, 3)]], ["[IV*-IV*-0] pages 160-175", [3, 3] ]]] ? print("Total time spent: ",gettime); Total time spent: 49 pari-2.17.2/src/test/32/cmp0000644000175000017500000000114314567450071013670 0ustar billbill(f,g)->[cmp(f,f),cmp(f,g),cmp(g,f)] [0, -1, 1] [0, -1, 1] [0, -1, 1] [0, -1, 1] [0, -1, 1] [0, -1, 1] [0, -1, 1] [0, -1, 1] *** at top-level: Mod(1,3)>0 *** ^-- *** _>_: forbidden comparison t_INTMOD , t_INT. -1 [1, 1, 0] [0, 1, 1] 1 0 *** at top-level: 1<='x *** ^---- *** _<=_: forbidden comparison t_INT , t_POL. *** at top-level: 1.<='x *** ^---- *** _<=_: forbidden comparison t_REAL , t_POL. *** at top-level: 1/2<='x *** ^---- *** _<=_: forbidden comparison t_FRAC , t_POL. Total time spent: 4 pari-2.17.2/src/test/32/ellseaJ0000644000175000017500000000017614567450071014475 0ustar billbill *** Warning: new stack size = 10000000 (9.537 Mbytes). 18784748 72057593931167604 72057594037928000 Total time spent: 164 pari-2.17.2/src/test/32/algebras0000644000175000017500000027747114760306645014716 0ustar billbillcontains nfabs: 1 [[x^4 + x^3 + x^2 + x + 1, [1], [125, 5], 1, [5], [], [[1, x, x^2, x^3], [1, 1, 1, 1]], [1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], 1, [y, [1, 0], 1, 1, [Mat(1), Mat(1), Mat(16), Mat(1), 1, Mat(1), [1, 0], []], [0.E-57], [ 1], Mat(1), Mat(1)], [x^4 + x^3 + x^2 + x + 1, 0, 0, y, x^4 + x^3 + x^2 + x + 1], [0, [[1; 0; 0; 0], Mat(1), 1, Vecsmall([1])]]], [x^2, -x^3 - x^2 - x - 1, x^3], Mod(3, y), Vecsmall([0]), [[[3, [3]~, 1, 1, 1], [5, [5]~, 1, 1, 1] ], Vecsmall([3, 1])], 0, [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0 , 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 ; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 1, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1 , 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, -1, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0; 0 , 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 1, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1 , 0], [0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0 , 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0 , 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 1, 0, 0, -1; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1 , 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 1, -1, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, -1, -1, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0; 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0 , 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0 , 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1; 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, -1; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0; 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0 , 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, -3, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0; 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0; 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -1, 0, -1, 0, 0 , 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0; 0, 0, 0, 0 , 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, -3; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -3, 0, 0; 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0 , 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0 , 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0 , 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, -3; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 0, 3; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3 , -3; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 1, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0; 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0 , 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0 , 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0; 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0 , 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, -3, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 0, 3, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, -3, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 3, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, -3, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0 , 3, 0; 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -1, 0, 0, 1 , 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0 , 3, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, -3; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -3, 0, 0; 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, 0, 0, -1, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0 , 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 0, 3, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, -3, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, -3; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0 , 0, 3; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, -3; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, -1, 0, 0 , 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0 , 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0; 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, -3, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -3, 0, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, -3, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 0, 3, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3 , -3, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0; 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, -3, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0; 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, -1, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, -3, -3, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 3, 3, 0 , 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -3, 0, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 3, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 3, 0, 0, -3; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0; 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, - 3, 0, 0; 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, -3, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 3, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 3, 0, -3, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 0, 3, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, -3, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 , 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, -3; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, -3; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, 0, 3; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, -3; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, -1, -1, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ], 0, [16, -4, 4, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] Suite: all Suite: get degree: 1 center: 1 splitting: 1 automorphism: 1 b: 1 trivial hasse invariants: 1 charac: 1 dim: 1 absdim: 1 basis: 1 invbasis: 1 basis*invbasis: 1 iscyclic: 1 radical: 1 Suite: operations radical: 1 addition: 1 negation: 1 soustraction: 1 multiplication: 1 non-commutativity: 0 left division: 1 right division: 1 noncommutative left division: 1 noncommutative right division: 1 division by non-invertible: error("impossible inverse in algdivl: [Mod(Mod(- 1, i^2 + 1)*s, s^2 + 2), Mod(Mod(i - 1, i^2 + 1), s^2 + 2)]~.") nilpotent: 1 square: 1 square j: 1 inverse: 1 powers: 1 negative powers: 1 multiplication table j: 1 multiplication table: 1 characteristic polynomial: 1 characteristic polynomial j: 1 trace zero: 1 trace commutator: 1 trace: 1 norm zero: 1 norm one: 1 norm j: 1 norm is multiplicative a*b: 1 norm is multiplicative b*a: 1 poleval: 1 poleval b: 1 Suite: tensor product of cyclic algebras radical 1: 1 radical 2: 1 radical 3: 1 tensor of degree 2 and 3 no mo: 1 Suite: Grunwald-Wang A quadratic over Q, 2 large inert, imaginary: 1 A quartic over Q, 2 large inert, imaginary: error("sorry, nfgrunwaldwang for nonprime degree is not yet implemented.") A : degree 4 over Q(i), local degrees [4,1,1]: 1 A degree 3 over Q(j), local degrees [3,3] larger primes: 1 A : degree 3 over Q(sqrt(5)), local degrees [3,3] [0,0], larger primes: 1 A : degree 5 over Q(sqrt(7)), local degrees [5,5,5,5,5,5,5] [0,0]: 1 A : degree 9 over Q(zeta_9), local degrees [9,9,9,9]: 1 A degree 2 over totally real sextic, local degrees [2,2] [2,2,2,2,2,2], larg er primes: 1 A degree 2 over totally real sextic, local degrees [] [2,2,2,2,2,2]: 1 Suite: more operations construct algebra: [[x^3 - 21*x + 7, [1], [49, 1], 27, [7], [], [[1, x + 1, x^2 - x - 2], [1, 1/3, Mat(1/9)]], [1, -1, 1; 0, 1, 1; 0, 0, 1], 27, [y, [1, 0], 1, 1, [Mat(1), Mat(1), Mat(16), Mat(1), 1, Mat(1), [1, 0], []], [0.E-57 ], [1], Mat(1), Mat(1)], [x^3 - 21*x + 7, 0, 0, y, x^3 - 21*x + 7], [[x^3 - 21*x + 7, [3, 0], 49, 27, [[1, -1.2469796037174670610500097680084796213, 1.8 019377358048382524722046390148901023; 1, 0.445041867912628808577805128993589 51893, -1.2469796037174670610500097680084796213; 1, 1.8019377358048382524722 046390148901023, 0.44504186791262880857780512899358951893], [1, -1.246979603 7174670610500097680084796213, 1.8019377358048382524722046390148901023; 1, 0. 44504186791262880857780512899358951893, -1.246979603717467061050009768008479 6213; 1, 1.8019377358048382524722046390148901023, 0.445041867912628808577805 12899358951893], [16, -20, 29; 16, 7, -20; 16, 29, 7], [3, 1, 1; 1, 5, -2; 1 , -2, 5], [7, 0, 5; 0, 7, 5; 0, 0, 1], [3, -1, -1; -1, 2, 1; -1, 1, 2], [7, [2, 1, -1; 1, 3, 1; 0, 1, 2]], [7]], [-4.74093881115240118315002930402543886 38, 0.33512560373788642573341538698076855680, 4.4058132074145147574166139170 446703070], [9, 3*x + 3, x^2 - x - 11], [1, -1, 10; 0, 3, 3; 0, 0, 9], [1, 0 , 0, 0, 1, -1, 0, -1, 2; 0, 1, 0, 1, 1, 1, 0, 1, -1; 0, 0, 1, 0, 1, 0, 1, 0, 0]], [[1; 0; 0], Mat(1), 1, Vecsmall([1])]]], [-1/3*x^2 - 2/3*x + 14/3, 1/3 *x^2 - 1/3*x - 14/3], Mod(-6, y), Vecsmall([0]), [[[2, [2]~, 1, 1, 1], [3, [ 3]~, 1, 1, 1], [7, [7]~, 1, 1, 1]], Vecsmall([1, 2, 0])], 0, [1, 0, 0, 0, 0, 4/7, 0, 4/7, 5/7; 0, 1, 0, 0, 0, 4/7, 0, 2/7, 5/7; 0, 0, 1, 0, 0, 5/7, 0, 0 , 1/7; 0, 0, 0, 1, 0, 5/7, 0, 1/7, 5/7; 0, 0, 0, 0, 1, 5/7, 0, 4/7, 5/7; 0, 0, 0, 0, 0, 1/7, 0, 0, 1/7; 0, 0, 0, 0, 0, 0, 1, 2/7, 5/7; 0, 0, 0, 0, 0, 0, 0, 1/7, 5/7; 0, 0, 0, 0, 0, 0, 0, 0, 1/7], [1, 0, 0, 0, 0, -4, 0, -4, 19; 0 , 1, 0, 0, 0, -4, 0, -2, 9; 0, 0, 1, 0, 0, -5, 0, 0, 4; 0, 0, 0, 1, 0, -5, 0 , -1, 5; 0, 0, 0, 0, 1, -5, 0, -4, 20; 0, 0, 0, 0, 0, 7, 0, 0, -7; 0, 0, 0, 0, 0, 0, 1, -2, 5; 0, 0, 0, 0, 0, 0, 0, 7, -35; 0, 0, 0, 0, 0, 0, 0, 0, 7], [[1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0 , 0, 0, 0, 0, 1], [0, 1, -1, 4, 4, 5, 19, 8, 17; 1, 1, 1, 4, 4, 7, 9, 6, 12; 0, 1, 0, 5, 5, 7, 4, 5, 10; 0, 0, 0, 6, 5, 7, 5, 5, 10; 0, 0, 0, 4, 4, 5, 2 0, 8, 17; 0, 0, 0, -7, -7, -9, -7, -7, -14; 0, 0, 0, 0, 0, 0, 5, 1, 2; 0, 0, 0, 0, 0, 0, -35, -9, -21; 0, 0, 0, 0, 0, 0, 7, 2, 5], [0, -1, 2, 0, -4, -2, -15, -9, -22; 0, 1, -1, 0, -4, -3, -7, -5, -11; 1, 0, 0, 0, -5, -3, -4, -4, -8; 0, 0, 0, 0, -4, -3, -4, -4, -8; 0, 0, 0, 1, -4, -2, -16, -9, -22; 0, 0, 0, 0, 7, 5, 7, 7, 14; 0, 0, 0, 0, 0, 0, -2, -1, -3; 0, 0, 0, 0, 0, 0, 28, 1 2, 35; 0, 0, 0, 0, 0, 0, -7, -3, -9], [0, 0, -4, 0, -4, -3, -6, -4, -5; 0, 0 , -4, 0, -2, -3, 0, -2, -5; 0, 0, -5, 0, 0, -3, 0, 0, -1; 1, 0, -5, 0, -1, - 3, 0, 0, 0; 0, 1, -5, 0, -4, -3, 0, -2, 0; 0, 0, 7, 0, 0, 4, 0, 0, 0; 0, 0, 0, 1, -2, 0, 0, -1, 0; 0, 0, 0, 0, 7, 0, 0, 4, 0; 0, 0, 0, 0, 0, 1, 0, 0, 1] , [0, -4, 0, -15, -15, -21, 0, -11, -19; 0, -4, 0, -7, -7, -11, 0, -7, -15; 0, -5, 0, -4, -4, -8, -6, -6, -13; 0, -4, -1, -4, -4, -8, 0, -4, -8; 1, -4, 1, -16, -16, -21, 0, -12, -22; 0, 7, 0, 7, 7, 13, 0, 7, 14; 0, 0, 0, -2, -3, -3, 0, -2, -3; 0, 0, 0, 28, 28, 35, 0, 20, 35; 0, 0, 0, -7, -7, -9, 0, -5, -9], [0, -3, -2, -9, -12, -15, -5, -12, -23; 0, -1, -3, -3, -6, -8, 1, -6, - 14; 0, -3, -3, 0, -3, -6, -4, -4, -9; 0, -3, -4, 1, -3, -6, 0, -3, -6; 0, -2 , -3, -9, -12, -15, 0, -11, -21; 1, 5, 5, 1, 5, 11, 1, 6, 12; 0, 0, 0, -1, - 3, -2, 2, -2, -3; 0, 0, 0, 21, 21, 23, 0, 19, 36; 0, 0, 0, -5, -4, -5, -1, - 4, -8], [0, -4, 19, -6, 0, 7, 0, -2, -1; 0, -2, 9, 0, -6, 1, 0, -4, -1; 0, 0 , 4, 0, 0, 2, 0, 0, 4; 0, -1, 5, 0, 0, 3, -6, -2, 0; 0, -4, 20, 0, 0, 12, 0, -2, 0; 0, 0, -7, 0, 0, -5, 0, 0, -7; 1, -2, 5, 0, 0, 3, 0, 0, 0; 0, 7, -35, 0, 0, -21, 0, 2, 0; 0, 0, 7, 0, 0, 5, 0, 0, 1], [0, -1, 4, -10, -8, -9, 8, -4, -4; 0, -1, 2, -2, -4, -3, 6, -2, -2; 0, -2, 1, 0, 0, -1, 2, 0, 1; 0, -2, 0, 0, -1, -2, 4, 0, 2; 0, -1, 5, -8, -8, -7, 10, -4, -4; 0, 3, -1, 2, 2, 4, -8, 0, -3; 0, 0, 1, -1, -2, -1, 2, -1, -1; 1, -2, -9, 16, 17, 13, -10, 10, 12; 0, 1, 2, -4, -4, -3, 2, -2, -2], [0, 5, 8, -17, -10, -7, 20, -2, 3; 0, 2 , 3, 1, -4, 2, 20, 2, 9; 0, 0, 0, 5, 4, 5, 16, 7, 17; 0, -1, -1, 2, 0, 0, 15 , 4, 13; 0, 6, 9, -9, -9, 0, 30, 1, 10; 0, 0, 0, 0, 0, 0, -28, -7, -21; 0, 1 , 2, -1, -3, 0, 4, -1, 0; 0, -14, -21, 21, 21, 0, -21, 7, 0; 1, 5, 5, -5, -4 , 2, 4, 0, 3]], 0, [9, 3, 3, 0, 0, 9, 0, 6, 9]] norm(u): 1 norm(t): 1 trace(u): 1 trace(t): 1 u+t: 1 u*t: 1 u^3: 1 w^-1 L: 1 w^-1 R: 1 w^-1*u: [Mod(0, x^3 - 21*x + 7), Mod(Mod(1, y), x^3 - 21*x + 7), Mod(0, x^3 - 21*x + 7)]~ u*w^-1: [Mod(0, x^3 - 21*x + 7), Mod(Mod(1, y), x^3 - 21*x + 7), Mod(0, x^3 - 21*x + 7)]~ charpol(w): Y^3 - 21*Y^2 + 1179*Y + 9447301/28 eval charpol: 1 trace(w): 1 norm(w): 1 dim: 1 absdim: 1 iscommutative: 1 issemisimple: 1 issimple: 1 algleftmultable w+ww: 1 algleftmultable w*ww: 1 alg(basis(w)): 1 alg(basis(ww)): 1 basis(w)+ww: 1 basis(w)-ww: 1 w+basis(ww): 1 w-basis(ww): 1 basis(w)*ww: 1 w*basis(ww): 1 basis(w)^2: 1 basis(ww)^2: 1 basis(w)\ww: 1 w\basis(ww): 1 basis(ww)\w: 1 wwbasis(w): 1 basis(w)^-1: 1 basis(ww)^-1: 1 basis(w)/ww: 1 w/basis(ww): 1 basis(ww)/w: 1 ww/basis(w): 1 trace(basis(w)): 1 trace(basis(ww)): 1 alg(basis(w)) 2: 1 alg(basis(ww)) 2: 1 basis(w)+ww 2: 1 basis(w)-ww 2: 1 w+basis(ww) 2: 1 w-basis(ww) 2: 1 basis(w)*ww 2: 1 w*basis(ww) 2: 1 basis(w)^2 2: 1 basis(ww)^2 2: 1 basis(w)ww 2: 1 wbasis(ww) 2: 1 basis(ww)w 2: 1 wwbasis(w) 2: 1 basis(w)^-1 2: 1 basis(ww)^-1 2: 1 basis(w)/ww 2: 1 w/basis(ww) 2: 1 basis(ww)/w 2: 1 ww/basis(w) 2: 1 trace(basis(w)) 2: 1 trace(basis(ww)) 2: 1 alg(basis(w)) 3: 1 alg(basis(ww)) 3: 1 basis(w)+ww 3: 1 basis(w)-ww 3: 1 w+basis(ww) 3: 1 w-basis(ww) 3: 1 basis(w)*ww 3: 1 w*basis(ww) 3: 1 basis(w)^2 3: 1 basis(ww)^2 3: 1 basis(w)ww 3: 1 wbasis(ww) 3: 1 basis(ww)w 3: 1 wwbasis(w) 3: 1 basis(w)^-1 3: 1 basis(ww)^-1 3: 1 basis(w)/ww 3: 1 w/basis(ww) 3: 1 basis(ww)/w 3: 1 ww/basis(w) 3: 1 trace(basis(w)) 3: 1 trace(basis(ww)) 3: 1 radical: 1 iscommutative cyc 3: 1 issemisimple cyc 3: 1 issimple cyc 3: 1 algleftmultable/Q w+ww: 1 algleftmultable/Q w*ww: 1 alg(basis(w))/Q: 1 alg(basis(ww))/Q: 1 basis(w)+ww/Q: 1 basis(w)-ww/Q: 1 w+basis(ww)/Q: 1 w-basis(ww)/Q: 1 basis(w)*ww/Q: 1 w*basis(ww)/Q: 1 basis(w)^2/Q: 1 basis(ww)^2/Q: 1 basis(w)ww/Q: 1 wbasis(ww)/Q: 1 basis(ww)w/Q: 1 wwbasis(w)/Q: 1 basis(w)^-1/Q: 1 basis(ww)^-1/Q: 1 basis(w)/ww/Q: 1 w/basis(ww)/Q: 1 basis(ww)/w/Q: 1 ww/basis(w)/Q: 1 trace(basis(w))/Q: 1 trace(basis(ww))/Q: 1 radical/Q: 1 iscommutative /Q: 1 issemisimple /Q: 1 issimple /Q: 1 Suite: table algebra algisassociative 0.0: 1 algisassociative 0.1: error("incorrect type in algisassociative (mult. table ) (t_VEC).") algisassociative 0.2: 1 algisassociative 0.3: error("incorrect type in algisassociative (mult. table ) (t_POL).") construction 0: [0, 0, 0, 0, 0, 0, [1, 0, 0; 0, 1, 0; 0, 0, 1], [1, 0, 0; 0, 1, 0; 0, 0, 1], [[1, 0, 0; 0, 1, 0; 0, 0, 1], [0, 0, 0; 1, 0, 1; 0, 0, 0], [0, 0, 0; 0, 0, 0; 1, 0, 1]], 0, [3, 0, 1]] iscyclic 0: 1 dim 0: 1 dim 0b: 1 char 0: 1 a+b 0: 1 a-b 0: 1 a*b 0: 1 b*a 0: 1 a^2 0: 1 b^2 0: 1 e^691691 0: 1 d^101 0: 1 multable(a) 0: 1 multable(b) 0: 1 divl(d,a) 0: 1 divl(d,b) 0: 1 d^-1 0: 1 divr(a,d) 0: 1 divr(b,d) 0: 1 rad(al) 0: 1 ss(al) 0: 1 proj(a) idem 0: 1 idemproj 0: [[0, 0, 0, 0, 0, 0, Mat(1), Mat(1), [Mat(1)], 0, [1]], [0, 0, 0, 0, 0, 0, Mat(1), Mat(1), [Mat(1)], 0, [1]]] simple components 0: 1 center al 0: 1 center ss 0: 1 primesubalg ss 0: error("domain error in algprimesubalg: characteristic = 0" ) x^3 - 2*x^2 + x charpol annihil(a) 0: 1 x^3 - x^2 charpol annihil(b) 0: 1 x^3 charpol annihil(c) 0: 1 x^3 - 4*x^2 + 5*x - 2 charpol annihil(d) 0: 1 x^3 - 3*x^2 + 3*x - 1 charpol annihil(e) 0: 1 random 0: [1, 0, 0]~ algsimpledec 0: 1 alg_decomposition 0: 1 iscommutative 0: 1 issemisimple 0: 1 issimple 0: 1 issimple ss 0: 1 isdivision 0: 1 algisassociative 2: 1 construction 2: [0, 0, 0, 0, 0, 0, [1, 0, 0; 0, 1, 0; 0, 0, 1], [1, 0, 0; 0, 1, 0; 0, 0, 1], [[1, 0, 0; 0, 1, 0; 0, 0, 1], [0, 0, 0; 1, 0, 1; 0, 0, 0], [0, 0, 0; 0, 0, 0; 1, 0, 1]], 2, [1, 0, 1]] iscyclic 2: 1 dim 2: 1 char 2: 1 a+b 2: 1 a-b 2: 1 a*b 2: 1 b*a 2: 1 a^2 2: 1 b^2 2: 1 multable(a) 2: 1 multable(b) 2: 1 divl(un,a) 2: 1 divl(un,b) 2: 1 un^-1 2: 1 divr(a,un) 2: 1 divr(b,un) 2: 1 rad(al) 2: 1 ss(al) 2: 1 proj(a) idem 2: 1 idemproj 2: [[0, 0, 0, 0, 0, 0, Mat(1), Mat(1), [Mat(1)], 2, [1]], [0, 0, 0, 0, 0, 0, Mat(1), Mat(1), [Mat(1)], 2, [1]]] simple components 2: 1 center al 2: 1 center ss 2: 1 primesubalg ss 2: 1 x^3 + x charpol annihil(a) 2: 1 x^3 + x^2 charpol annihil(b) 2: 1 x^3 charpol annihil(c) 2: 1 random 2: [1, 0, 0]~ algsimpledec 2: 1 alg_decomposition 2: 1 iscommutative 2: 1 issemisimple 2: 1 issimple 2: 1 issimple ss 2: 1 matrix trace 2: 1 matrix norm 2: 1 norm 2: 1 construction 3: [0, 0, 0, 0, 0, 0, [1, 0; 0, 1], [1, 0; 0, 1], [[1, 0; 0, 1] , [0, 0; 1, 0]], 3, [2, 0]] iscyclic 3: 1 dim 3: 1 char 3: 1 a+b 3: 1 a-b 3: 1 a*b 3: 1 b*a 3: 1 a^2 3: 1 b^2 3: 1 a^691691 3: 1 multable(a) 3: 1 multable(b) 3: 1 algdivl(a,b) 3: 1 a^-1 3: 1 algdivr(b,a) 3: 1 rad(al) 3: 1 ss(al) 3: 1 center al 3: 1 center ss 3: 1 primesubalg ss 3: 1 x^2 + x + 1 charpol annihil(a) 3: 1 x^2 charpol annihil(b) 3: 1 random 3: [1, 0]~ algsimpledec 3: 1 alg_decomposition 3: 1 iscommutative 3: 1 issemisimple 3: 1 issemisimple ss 3: 1 issimple 3: 1 issimple ss 3: 1 construction 3c: [0, 0, 0, 0, 0, 0, [1, 0, 0; 0, 1, 0; 0, 0, 1], [1, 0, 0; 0 , 1, 0; 0, 0, 1], [[1, 0, 0; 0, 1, 0; 0, 0, 1], [0, 0, 0; 1, 0, 0; 0, 1, 0], [0, 0, 0; 0, 0, 0; 1, 0, 0]], 3, [0, 0, 0]] iscyclic 3c: 1 dim 3c: 1 char 3c: 1 a+b 3c: 1 a-b 3c: 1 a*b 3c: 1 b*a 3c: 1 a^2 3c: 1 b^2 3c: 1 a^691691 3c: 1 multable(a) 3c: 1 multable(b) 3c: 1 algdivl(a,b) 3c: 1 a^-1 3c: 1 algdivr(b,a) 3c: 1 rad(al) 3c: 1 ss(al) 3c: 1 center al 3c: 1 center ss 3c: 1 primesubalg ss 3c: 1 x^3 + 2 charpol annihil(a) 3c: 1 x^3 charpol annihil(b) 3c: 1 random 3c: [1, 0, 0]~ algsimpledec 3c: 1 alg_decomposition 3c: 1 iscommutative 3c: 1 issemisimple 3c: 1 issemisimple ss 3c: 1 issimple 3c: 1 issimple ss 3c: 1 construction 2b: [0, 0, 0, 0, 0, 0, [1, 0; 0, 1], [1, 0; 0, 1], [[1, 0; 0, 1 ], [0, 1; 1, 1]], 2, [0, 1]] iscyclic 2b: 1 dim 2b: 1 char 2b: 1 a+b 2b: 1 a-b 2b: 1 a*b 2b: 1 b*a 2b: 1 a^2 2b: 1 b^2 2b: 1 a^691691 2b: 1 multable(a) 2b: 1 multable(b) 2b: 1 divl(a,b) 2b: 1 a^-1 2b: 1 divr(b,a) 2b: 1 rad(al) 2b: 1 center al 2b: 1 primesubalg al 2b: 1 x^2 + x + 1 charpol annihil(a) 2b: 1 x^2 + x + 1 charpol annihil(b) 2b: 1 random 2b: [1, 0]~ algsimpledec 2b: 1 alg_decomposition 2b: 1 iscommutative 2b: 1 issemisimple 2b: 1 issimple 2b: 1 issimple,1 2b: 1 construction 3b: [0, 0, 0, 0, 0, 0, [1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [[1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [0, 1, 0, 0; 1, 0, 0, 0; 0, 0, 1, 0; 0, 0 , 0, 2], [0, 0, 0, 2; 0, 0, 0, 2; 1, 2, 0, 0; 0, 0, 0, 0], [0, 0, 2, 0; 0, 0 , 1, 0; 0, 0, 0, 0; 1, 1, 0, 0]], 3, [1, 0, 0, 0]] iscyclic 3b: 1 dim 3b: 1 char 3b: 1 a+b 3b: 1 a-b 3b: 1 a*b 3b: 1 b*a 3b: 1 a^2 3b: 1 b^2 3b: 1 a^691691 3b: 1 b^691691 3b: 1 multable(a) 3b: 1 multable(b) 3b: 1 divl(a,b) 3b: 1 a^-1 3b: 1 divr(b,a) 3b: 1 rad(al) 3b: 1 center al 3b: 1 primesubalg al 3b: 1 x^4 + x^2 + 1 charpol annihil(a) 3b: 1 x^4 + 2*x^3 + x^2 charpol annihil(b) 3b: 1 x^4 charpol annihil(c) 3b: 1 random 3b: [1, 0, 0, 1]~ algsimpledec 3b: 1 alg_decomposition 3b: 1 iscommutative 3b: 1 issemisimple 3b: 1 issimple 3b: 1 construction 2c: [0, 0, 0, 0, 0, 0, [1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [[1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [0, 0, 1, 0; 1, 0, 0, 1; 0, 0, 0, 0; 0, 0 , 1, 0], [0, 0, 0, 0; 0, 0, 0, 0; 1, 0, 0, 0; 0, 1, 0, 0], [0, 0, 0, 0; 0, 0 , 0, 0; 0, 0, 1, 0; 1, 0, 0, 1]], 2, [0, 0, 0, 0]] iscyclic 2c: 1 dim 2c: 1 char 2c: 1 a+b 2c: 1 a-b 2c: 1 a*b 2c: 1 b*a 2c: 1 a^2 2c: 1 b^2 2c: 1 a^691691 2c: 1 b^691691 2c: 1 c^691691 2c: 1 multable(a) 2c: 1 multable(b) 2c: 1 divl(c,a) 2c: 1 divl(c,b) 2c: 1 c^-1 2c: 1 divr(a,c) 2c: 1 divr(b,c) 2c: 1 rad(al) 2c: 1 center al 2c: 1 primesubalg al 2c: 1 x^4 charpol annihil(a) 2c: 1 x^4 + x^2 charpol annihil(b) 2c: 1 x^4 + x^2 + 1 charpol annihil(c) 2c: 1 random 2c: [1, 0, 0, 1]~ algsimpledec 2c: 1 alg_decomposition 2c: 1 iscommutative 2c: 1 issemisimple 2c: 1 issimple 2c: 1 construction 5: [0, 0, 0, 0, 0, 0, Mat(1), Mat(1), [Mat(1)], 5, [1]] iscyclic 5: 1 dim 5: 1 char 5: 1 a+b 5: 1 a-b 5: 1 a*b 5: 1 b*a 5: 1 a^2 5: 1 b^2 5: 1 a^691691 5: 1 multable(a) 5: 1 multable(b) 5: 1 divl(a,b) 5: 1 a^-1 5: 1 divr(a,b) 5: 1 rad(al) 5: 1 center al 5: 1 primesubalg al 5: 1 x + 3 charpol annihil(a) 5: 1 x + 2 charpol annihil(b) 5: 1 random 5: [1]~ algsimpledec 5: 1 alg_decomposition 5: 1 iscommutative 5: 1 issemisimple 5: 1 issimple 5: 1 construction 0b: [0, 0, 0, 0, 0, 0, [1, 0, 0, 0, 0; 0, 1, 0, 0, 0; 0, 0, 1, 0, 0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], [1, 0, 0, 0, 0; 0, 1, 0, 0, 0; 0, 0, 1, 0, 0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], [[1, 0, 0, 0, 0; 0, 1, 0, 0, 0; 0, 0, 1, 0, 0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], [0, 0, 1, 0, 0; 1, 0, 0, 1, 0; 0, 0, 0, 0, 0; 0, 0, -1, 0, 0; 0, 1, -1, -1, 1], [0, 0, 0, 0, 0; 0, 0, 0, 0, 0; 1 , 0, 0, 0, 0; 0, 1, 0, 0, 0; 0, 0, 0, 0, 0], [0, 0, 0, 0, 0; 0, 0, 0, 0, 0; 0, 0, 1, 0, 0; 1, 0, 0, 1, 0; 0, 0, 0, 0, 0], [0, 0, 0, 0, 0; 0, 0, 0, 0, 0; 0, 0, 0, 0, 0; 0, 0, 0, 0, 0; 1, 1, 0, 0, 1]], 0, [5, 1, 0, 2, 1]] iscyclic 0b: 1 dim 0b: 1 char 0b: 1 a+b 0b: 1 a-b 0b: 1 a*b 0b: 1 b*a 0b: 1 a^2 0b: 1 b^2 0b: 1 a^691691 0b: 1 b^691 0b: 1 multable(a) 0b: 1 multable(b) 0b: 1 divl(b,a) 0b: 1 b^-1 0b: 1 divr(a,b) 0b: 1 rad(al) 0b: 1 idemproj 0b: [[0, 0, 0, 0, 0, 0, [1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [[1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [0, 0, 1, 0; 1, 0, 0, 1; 0, 0, 0, 0; 0, 0, - 1, 0], [0, 0, 0, 0; 0, 0, 0, 0; 1, 0, 0, 0; 0, 1, 0, 0], [0, 0, 0, 0; 0, 0, 0, 0; 0, 0, 1, 0; 1, 0, 0, 1]], 0, [4, 0, 0, 2]], [0, 0, 0, 0, 0, 0, Mat(1), Mat(1), [Mat(1)], 0, [1]]] simple components 0b: 1 mt M2 component 0b: 1 center al 0b: 1 primesubalg al 0b: error("domain error in algprimesubalg: characteristic = 0 ") x^5 - 4*x^4 + 6*x^3 - 4*x^2 + x charpol annihil(a) 0b: 1 x^5 - 6*x^4 + 14*x^3 - 16*x^2 + 9*x - 2 charpol annihil(b) 0b: 1 random 0b: [1, 0, 0, 1, 1]~ algsimpledec 0b: 1 alg_decomposition 0b: 1 subalg M2(Q): 1 iscommutative 0b: 1 issemisimple 0b: 1 issimple 0b: 1 construction 3d: [0, 0, 0, 0, 0, 0, [1, 0, 0, 0, 0; 0, 1, 0, 0, 0; 0, 0, 1, 0, 0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], [1, 0, 0, 0, 0; 0, 1, 0, 0, 0; 0, 0, 1, 0, 0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], [[1, 0, 0, 0, 0; 0, 1, 0, 0, 0; 0, 0, 1, 0, 0; 0, 0, 0, 1, 0; 0, 0, 0, 0, 1], [0, 0, 1, 0, 0; 1, 0, 0, 1, 0; 0, 0, 0, 0, 0; 0, 0, 2, 0, 0; 0, 1, 2, 2, 1], [0, 0, 0, 0, 0; 0, 0, 0, 0, 0; 1, 0 , 0, 0, 0; 0, 1, 0, 0, 0; 0, 0, 0, 0, 0], [0, 0, 0, 0, 0; 0, 0, 0, 0, 0; 0, 0, 1, 0, 0; 1, 0, 0, 1, 0; 0, 0, 0, 0, 0], [0, 0, 0, 0, 0; 0, 0, 0, 0, 0; 0, 0, 0, 0, 0; 0, 0, 0, 0, 0; 1, 1, 0, 0, 1]], 3, [2, 1, 0, 2, 1]] iscyclic 3d: 1 dim 3d: 1 char 3d: 1 a+b 3d: 1 a-b 3d: 1 a*b 3d: 1 b*a 3d: 1 a^2 3d: 1 b^2 3d: 1 a^691691 3d: 1 b^691 3d: 1 multable(a) 3d: 1 multable(b) 3d: 1 divl(b,a) 3d: 1 b^-1 3d: 1 divr(a,b) 3d: 1 rad(al) 3d: 1 idemproj 3d: [[0, 0, 0, 0, 0, 0, [1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [[1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [0, 0, 1, 0; 1, 0, 0, 1; 0, 0, 0, 0; 0, 0, 2 , 0], [0, 0, 0, 0; 0, 0, 0, 0; 1, 0, 0, 0; 0, 1, 0, 0], [0, 0, 0, 0; 0, 0, 0 , 0; 0, 0, 1, 0; 1, 0, 0, 1]], 3, [1, 0, 0, 2]], [0, 0, 0, 0, 0, 0, Mat(1), Mat(1), [Mat(1)], 3, [1]]] simple components 3d: 1 mt M2 component 3d: 1 center al 3d: 1 primesubalg al 3d: 1 x^5 + 2*x^4 + 2*x^2 + x charpol annihil(a) 3d: 1 x^5 + 2*x^3 + 2*x^2 + 1 charpol annihil(b) 3d: 1 random 3d: [1, 0, 0, 1, 1]~ algsimpledec 3d: 1 alg_decomposition 3d: 1 subalg M2(F3): 1 iscommutative 3d: 1 issemisimple 3d: 1 issimple 3d: 1 issimple,1 3d: 1 maxorder assoc: 1 natorder assoc: 1 spl(1): 1 spl(i): 1 spl(j): 1 spl(k): 1 spl(basis(1)): 1 spl(basis(i)): 1 spl(basis(j)): 1 spl(basis(k)): 1 spl(a*1): 1 spl(a*i): 1 spl(a*j): 1 spl(a*k): 1 spl(b*1): 1 spl(b*i): 1 spl(b*j): 1 spl(b*k): 1 nattomax 1: 1 nattomax 2: 1 ord*invord=id: 1 spl additive: 1 spl multiplicative: 1 changebasis bug 1: 1 changebasis bug 2: 1 changebasis bug 3: 1 changebasis bug 4: 1 algtableinit segfault bug: 1 center of CSA: 1 radical of CSA: 1 decomposition of CSA: 1 alg_decomposition of CSA: 1 alsimple bug 0 tests for al_CSA: 1 1 algebra: csa getcenter: 1 csa getsplitting: 1 getrelmultable: 1 getsplittingdata: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 hasse invariants: hassei csa: error("sorry, computation of Hasse invariants over table CSA is not yet implemented.") hassef cas: error("sorry, computation of Hasse invariants over table CSA is not yet implemented.") hasse csa: error("sorry, computation of Hasse invariants over table CSA is n ot yet implemented.") csa splitting pol: 1 csa basis: 1 csa invbasis: 1 csa absdim: 1 csa char: 1 csa deg: 1 csa dim: 1 csa absdim: 1 csa type: 1 csa iscommutative: 1 csa issemisimple: 1 elements: [0, Mod(y, y^3 - y + 1), 0, 0]~ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]~ csa add: 1 csa neg: 1 csa neg 2: 1 csa sub: 1 csa mul: 1 csa mul 2: 1 csa sqr: 1 csa sqr 2: 1 csa mt: 1 csa inv: 1 csa inv 2: 1 csa divl: 1 csa pow: 1 csa mul 3: 1 csa mul 4: 1 csa pow 2: 1 csa sub 2: 1 csa sub 3: 1 csa inv 3: 1 csa inv 4: 1 csa inv 5: 1 csa trace: 1 csa trace 2: 1 csa abs trace: 1 csa abs trace 2: 1 1 testcharpol 1 1 1 testcharpol2 1 1 1 testnorm 1 1 1 testnorm2 1 1 1 examples from docu 0 [2, 2]~ 0 1 [Mod(Mod(-1/3, y), x^2 + 1), Mod(Mod(2/3, y), x^2 + 1)]~ 0 1 1 [Mod(-2/5*x - 1/5, x^2 + 1), 0]~ [0, 2, -1, -1, 2, 0, 0, 0]~ [Mod(Mod(y, y^2 - 5), x^2 - 2), 1]~ [Mod(Mod(-1/2*y, y^2 - 5)*x + Mod(-1/4*y + 5/4, y^2 - 5), x^2 - 2), Mod(Mod( -3/4*y + 7/4, y^2 - 5), x^2 - 2)]~ [0, 1, 0, 0, 2, -3, 0, 0]~ [[0, 0, 0, 0, 0, 0, Mat(1), Mat(1), [Mat(1)], 2, [1]], [0, 0, 0, 0, 0, 0, [1 , 0; 0, 1], [1, 0; 0, 1], [[1, 0; 0, 1], [0, 1; 1, 1]], 2, [0, 1]]] [1 0] [0 1] [0 0] [0, 0, 0, 0, 0, 0, [1, 0; 0, 1], [1, 0; 0, 1], [[1, 0; 0, 1], [0, 1; 1, 1]], 2, [0, 1]] [[0, 0, 0, 0, 0, 0, [1, 0; 0, 1], [1, 0; 0, 1], [[1, 0; 0, 1], [0, 1; 1, 1]] , 2, [0, 1]], [1, 0; 0, 0; 0, 1]] 1 0 0 0 0 1 [[[2, [2, 0]~, 1, 2, 1], [3, [3, 0]~, 1, 2, 1]], Vecsmall([0, 1])] 12960000 12960000 12 y^3 - y + 1 2 4 -1/3*x^2 - 4/3*x + 26/3 Mod(5929, y) 13 1 [[[2, [2, 0]~, 1, 2, 1], [19, [-9, 2]~, 1, 1, [-8, 2; 2, -10]]], Vecsmall([0 , 1])] Vecsmall([1, 0]) 1/2 0 1/2 0 2 1 2 1 2 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 [1, [2, [2, 0]~, 1, 2, 1]] x^2 + Mod(-y + 13, y^2 - 5) [1 0 0 -1] [0 1 0 -1] [0 0 1 -1] [0 0 0 2] [1 0 0 1/2] [0 1 0 1/2] [0 0 1 1/2] [0 0 0 1/2] [[1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [0, -1, 1, 0; 1, 0, 1, 1; 0, 0, 1, 1; 0, 0, -2, -1], [0, -1, -1, -1; 0, -1, 0, -1; 1, -1, 0, 0; 0, 2, 0, 1], [0, -1, 0, -1; 0, 0, 1, 0; 0, -1, 1, 0; 1, 1, -1, 1]] [1/2, -1/2, 0, 0]~ [2, 3, 5, -4]~ [0 -1 1 0] [1 0 1 1] [0 0 1 1] [0 0 -2 -1] [-1 0 0 -1] [-1 0 1 0] [-1 -1 0 -1] [ 2 0 0 1] [-1, -1, 0, 0]~ [Mod(x + 1, x^2 + 1) Mod(x - 1, x^2 + 1)] [Mod(x + 1, x^2 + 1) Mod(-x + 1, x^2 + 1)] [8, -8, 0, 0]~ [0, 1, -1, 0]~ 11 22 3 [[1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [0, y, 0, 0; 1, 0, 0, 0; 0, 0, 0, y; 0, 0, 1, 0], [0, 0, y^2, 0; 0, 0, 0, -y^2; 1, 0, 0, 0; 0, -1, 0, 0], [0, 0, 0, -5; 0, 0, y^2, 0; 0, -y, 0, 0; 1, 0, 0, 0]] x^2 - y [[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]~, [1, 0; 0, -1; 0, 0; 0, 0; 0, 0; 0, 0 ; 0, 1; 0, 0; 0, 0; 0, 0; 0, 0; 0, 0], [1, Mod(x^2, x^6 - 5), Mod(x^4, x^6 - 5), Mod(x, x^6 - 5), Mod(1/2*x^4 + 1/2*x^3 + 1/2*x + 1/2, x^6 - 5), Mod(1/2 *x^5 + 1/2*x^4 + 1/2*x^2 + 1/2*x, x^6 - 5), Mod(x^2, x^6 - 5), Mod(x^4, x^6 - 5), Mod(x^4 + x^2 + 1, x^6 - 5), 3, Mod(x^2, x^6 - 5), Mod(x^4, x^6 - 5); 0, 0, 0, 0, 0, 0, 1, Mod(x^2, x^6 - 5), Mod(1/10*x^4 + 1/2*x^2 + 1/2, x^6 - 5), Mod(1/2*x^4 - 1/2*x, x^6 - 5), Mod(-1/10*x^3 + 1/2, x^6 - 5), Mod(-1/10* x^5 + 1/2*x^2, x^6 - 5)]] 2 18 18 1 1 1 matrices over algebras [[1, 0, 2, 2, 2, 2, 0, -2]~ [-2, -1, 1, 0, -1, -2, -1, 1]~] [[1, 2, 0, -2, 2, 1, 2, 2]~ [2, -2, -2, 0, -2, 2, -1, 2]~] [[-2, 0, -2, 2, 0, 2, 0, -2]~ [0, 2, -1, 0, -2, -2, -1, -1]~] [[0, 2, 0, -2, -1, 1, 1, -1]~ [0, 2, 0, 2, 0, 1, 0, 1]~] mul alM: [[-30, 47, -39, 42, 87, 60, -139, 78]~, [119, 6, 38, 12, 28, -23, 2 6, -63]~; [23, 104, -18, 58, 147, 119, -168, -17]~, [199, 126, 65, 73, 17, 9 8, -63, -98]~] sqr alM: 1 divl alM: 1 divr alM: 1 isinv alM: 1 isinv alM 2: 1 inv alM: 1 inv alM 2: 1 neg alM: 1 sub alM: 1 add alM: 1 algtobasis basistoalg alM 1: 1 algtobasis basistoalg alM 2: 1 algleftmultable add alM: 1 algleftmultable mul alM: 1 algleftmultable sqr alM: 1 algsplitm add alM: 1 algsplitm mul alM: 1 algsplitm sqr alM: 1 algsplitm sqr alM 2: 1 algtrace alM: 1 algtrace alM 2: 1 algtrace abs alM: 1 algtrace abs alM 2: 1 algtrace prod alM: 1 algnorm alM: 1 algnorm alM 2: 1 algcharpoly alM: 1 algcharpoly alM 2: 1 pow alM: 1 pow alM 2: 1 pow 0 alM: 1 [[Mod(Mod(1/2*y + 1/2, y^2 - 5)*x + Mod(-1/2*y - 1/2, y^2 - 5), x^2 + 1), Mo d(Mod(-1/14*y - 11/14, y^2 - 5)*x + Mod(1/14*y + 17/14, y^2 - 5), x^2 + 1)]~ [Mod(3*x + Mod(-3/4*y - 13/4, y^2 - 5), x^2 + 1), Mod(Mod(1/28*y + 5/4, y^2 - 5)*x - 13/7, x^2 + 1)]~] [[Mod(-17/2*x + Mod(-1/2*y + 4, y^2 - 5), x^2 + 1), Mod(Mod(1/14*y - 10/7, y ^2 - 5)*x + Mod(-1/7*y + 53/14, y^2 - 5), x^2 + 1)]~ [Mod(Mod(1/4*y + 7/4, y ^2 - 5)*x + Mod(1/2*y + 5, y^2 - 5), x^2 + 1), Mod(Mod(1/14*y - 6/7, y^2 - 5 )*x + Mod(-1/28*y + 1/28, y^2 - 5), x^2 + 1)]~] [[Mod(Mod(1/2*y + 3/2, y^2 - 5)*x + Mod(3/2*y - 3/2, y^2 - 5), x^2 + 1), Mod (Mod(-1/14*y - 11/14, y^2 - 5)*x + Mod(1/14*y + 3/14, y^2 - 5), x^2 + 1)]~ [ Mod(Mod(-1/2*y + 2, y^2 - 5)*x + Mod(3/4*y - 7/4, y^2 - 5), x^2 + 1), Mod(Mo d(-1/28*y + 41/28, y^2 - 5)*x + Mod(1/14*y - 22/7, y^2 - 5), x^2 + 1)]~] [[Mod(Mod(-y - 7/2, y^2 - 5)*x + Mod(1/4*y + 1/4, y^2 - 5), x^2 + 1), Mod(Mo d(-1/28*y - 3/4, y^2 - 5)*x + 5/14, x^2 + 1)]~ [Mod(Mod(5/4*y - 9/4, y^2 - 5 )*x + Mod(-1/4*y + 5/4, y^2 - 5), x^2 + 1), Mod(Mod(1/28*y - 17/28, y^2 - 5) *x + Mod(-1/28*y + 25/28, y^2 - 5), x^2 + 1)]~] mul scalar alM: 1 [ [2, 1, 0, 2]~ [-1, -1, 2, -1]~] [[2, 1, -1, -2]~ [1, -1, 0, -1]~] [ [-2, 2, 2, 1]~ [-2, -2, 2, 1]~] [[-1, -2, 1, 1]~ [0, 1, 0, -1]~] mul alM t: [[-10, 4, 7, 3]~, [-4, -13, -3, -1]~; [-4, 5, 5, 11]~, [2, -2, 7, 5]~] sqr alM t: 1 divl alM t: 1 divr alM t: 1 isinv alM t: 1 isinv alM t 2: 1 inv alM t: 1 inv alM t 2: 1 neg alM t: 1 sub alM t: 1 add alM t: 1 algleftmultable add alM t: 1 algleftmultable mul alM t: 1 algleftmultable sqr alM t: 1 algtrace alM t: 1 algtrace alM t 2: 1 algtrace prod alM t: 1 algnorm alM t: 1 algnorm alM t 2: 1 algcharpoly alM t: 1 algcharpoly alM t 2: 1 pow alM t: 1 pow alM 2 t: 1 pow 0 alM t: 1 csa al2 al2 contains nfabs: 1 [[x^2 + (-2*y^2 + 2*y)*x + (6*y^2 - 5*y + 5), [292133, -1964*x^5 + 4725*x^4 - 14044*x^3 - 95698*x^2 - 164828*x - 456632, -1406*x^5 + 4870*x^4 - 7674*x^3 - 64939*x^2 - 119188*x + 52103], [[412, 92, 376; 0, 4, 0; 0, 0, 4], [-7, -4 , 2]~], 1, [2, 103], [], [[1, x], [1, 1]], [1, 0; 0, 1], 1, [y^3 - y + 1, [1 , 1], -23, 1, [[1, 0.75487766624669276004950889635852869189, -1.324717957244 7460259609088544780973407; 1, -0.87743883312334638002475444817926434595 + 0. 74486176661974423659317042860439236724*I, 0.66235897862237301298045442723904 867037 + 0.56227951206230124389918214490937306150*I], [1, 0.7548776662466927 6004950889635852869189, -1.3247179572447460259609088544780973407; 1, -0.1325 7706650360214343158401957487197871, 1.2246384906846742568796365721484217319; 1, -1.6223005997430906166179248767836567132, 0.1000794665600717690812722823 2967560887], [16, 12, -21; 16, -2, 20; 16, -26, 2], [3, -1, 0; -1, 1, -3; 0, -3, 2], [23, 16, 10; 0, 1, 0; 0, 0, 1], [7, -2, -3; -2, -6, -9; -3, -9, -2] , [23, [-10, -1, 8; -7, -3, 1; 1, 7, -10]], [23]], [-1.324717957244746025960 9088544780973407, 0.66235897862237301298045442723904867037 + 0.5622795120623 0124389918214490937306150*I], [1, y^2 - 1, y], [1, 0, 1; 0, 0, 1; 0, 1, 0], [1, 0, 0, 0, 0, -1, 0, -1, 1; 0, 1, 0, 1, -1, 0, 0, 0, 1; 0, 0, 1, 0, -1, 0, 1, 0, 0]], [x^6 - 4*x^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 191, -1406/292 133*x^5 + 4870/292133*x^4 - 7674/292133*x^3 - 64939/292133*x^2 - 119188/2921 33*x + 52103/292133, 0, y^3 - y + 1, x^2 + (-2*y^2 + 2*y)*x + (6*y^2 - 5*y + 5)], [0, [[1, 0, 0; 0, -1, 0; 0, 0, 1; 0, 0, 0; 0, 0, 0; 0, 0, 0], [1, 0, 0 ; 0, -1, 0; 0, 0, 1], 1, Vecsmall([1, 2, 3])]]], [[1, 0, 0, 0; 0, 1, 0, 0; 0 , 0, 1, 0; 0, 0, 0, 1], [0, 0, 1, 0; 1, 0, 0, 1; 0, 0, 0, 0; 0, 0, -1, 0], [ 0, 0, 0, 0; 0, 0, 0, 0; 1, 0, 0, 0; 0, 1, 0, 0], [0, 0, 0, 0; 0, 0, 0, 0; 0, 0, 1, 0; 1, 0, 0, 1]], [[0, 1, -1, -1, -2, 2, 0, 0, -2, 2, 0, 0]~, [1, 0; 0 , 0; 0, 0; 0, 0; 0, 0; 0, 0; 0, 1; 0, 0; 0, 0; 0, 0; 0, 0; 0, 0], [1, Mod(-1 964/292133*x^5 + 4725/292133*x^4 - 14044/292133*x^3 - 95698/292133*x^2 - 164 828/292133*x - 456632/292133, x^6 - 4*x^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 191), Mod(-1406/292133*x^5 + 4870/292133*x^4 - 7674/292133*x^3 - 64939/29 2133*x^2 - 119188/292133*x + 52103/292133, x^6 - 4*x^5 + 15*x^4 + 14*x^3 + 1 20*x^2 + 36*x + 191), Mod(-516/6719059*x^5 + 59549/6719059*x^4 - 144104/6719 059*x^3 + 56369/6719059*x^2 + 2656099/6719059*x + 5563831/6719059, x^6 - 4*x ^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 191), Mod(-54291/6719059*x^5 + 21048 9/6719059*x^4 - 786258/6719059*x^3 - 905381/6719059*x^2 - 6840464/6719059*x - 4510816/6719059, x^6 - 4*x^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 191), Mo d(-48132/6719059*x^5 + 241931/6719059*x^4 - 785055/6719059*x^3 - 523468/6719 059*x^2 - 1628025/6719059*x + 4121552/6719059, x^6 - 4*x^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 191), 0, 0, 0, 0, 0, 0; 0, 0, 0, Mod(-499864/154538357*x ^5 - 232506/154538357*x^4 + 2075504/154538357*x^3 - 39252216/154538357*x^2 - 107292314/154538357*x - 129681996/154538357, x^6 - 4*x^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 191), Mod(1153778/154538357*x^5 - 4109402/154538357*x^4 + 13244560/154538357*x^3 + 24564582/154538357*x^2 + 151883496/154538357*x - 1 0149974/154538357, x^6 - 4*x^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 191), Mo d(171940/154538357*x^5 - 3019052/154538357*x^4 + 13537158/154538357*x^3 - 30 710744/154538357*x^2 - 25903390/154538357*x - 175396598/154538357, x^6 - 4*x ^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 191), 1, Mod(-1964/292133*x^5 + 4725 /292133*x^4 - 14044/292133*x^3 - 95698/292133*x^2 - 164828/292133*x - 456632 /292133, x^6 - 4*x^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 191), Mod(-1406/29 2133*x^5 + 4870/292133*x^4 - 7674/292133*x^3 - 64939/292133*x^2 - 119188/292 133*x + 52103/292133, x^6 - 4*x^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 191), Mod(-516/6719059*x^5 + 59549/6719059*x^4 - 144104/6719059*x^3 + 56369/67190 59*x^2 + 2656099/6719059*x + 5563831/6719059, x^6 - 4*x^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 191), Mod(-54291/6719059*x^5 + 210489/6719059*x^4 - 78625 8/6719059*x^3 - 905381/6719059*x^2 - 6840464/6719059*x - 4510816/6719059, x^ 6 - 4*x^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 191), Mod(-48132/6719059*x^5 + 241931/6719059*x^4 - 785055/6719059*x^3 - 523468/6719059*x^2 - 1628025/671 9059*x + 4121552/6719059, x^6 - 4*x^5 + 15*x^4 + 14*x^3 + 120*x^2 + 36*x + 1 91)]], 0, 0, 0, [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 , 0; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1 , 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 1, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 ; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 1], [0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, -1, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0; 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0 , -1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, -1; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0], [0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 , 0, 0; 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 , 0; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1 ; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1; 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], [ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0 , 0, 0, 0, 0, 0, 0, 1, 0, 0, 0; 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0 , -1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0 , 0, -1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0; 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1; 1, -1, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0; 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0; 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 ; 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, -1, 1; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0; 0, 0, 0, 0 , 0, 0, -1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 , 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0; 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0; 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 1, 0, 0 , 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, -1, 0 , 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0; 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1; 1, -1, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0; 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, -1, 1; 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0]], 0, [12, -4, 0, 0, 0, 0, 0, 0, 0, 6, -2, 0]] csa al3 al3 contains nfabs: 1 trivial algebra over a quadratic field [[x, [1, -x], [1, 1], 1, [], [], [[1], [1]], Mat(1), 1, [y^2 + 1, [0, 1], -4 , 1, [Mat([1, 0.E-57 + 1.0000000000000000000000000000000000000*I]), [1, 1.00 00000000000000000000000000000000000; 1, -1.000000000000000000000000000000000 0000], [16, 16; 16, -16], [2, 0; 0, -2], [2, 0; 0, 2], [1, 0; 0, -1], [1, [0 , -1; 1, 0]], [2]], [0.E-57 + 1.0000000000000000000000000000000000000*I], [1 , y], [1, 0; 0, 1], [1, 0, 0, -1; 0, 1, 1, 0]], [x^2 + 1, -x, -1, y^2 + 1, x ], [[x^2 + 1, [0, 1], -4, 1, [Mat([1, 0.E-57 + 1.000000000000000000000000000 0000000000*I]), [1, 1.0000000000000000000000000000000000000; 1, -1.000000000 0000000000000000000000000000], [16, 16; 16, -16], [2, 0; 0, -2], [2, 0; 0, 2 ], [1, 0; 0, -1], [1, [0, -1; 1, 0]], [2]], [0.E-57 + 1.00000000000000000000 00000000000000000*I], [1, x], [1, 0; 0, 1], [1, 0, 0, -1; 0, 1, 1, 0]], [[1, 0; 0, -1], [1, 0; 0, -1], 1, Vecsmall([1, 2])]]], [Mod(y, y^2 + 1)], Mod(1, y^2 + 1), Vecsmall([]), [[], Vecsmall([])], 0, [1, 0; 0, 1], [1, 0; 0, 1], [[1, 0; 0, 1], [0, -1; 1, 0]], 0, [2, 0]] [y]~ [-2*y + 1]~ [-3, 1]~ [-y + 1]~ [-3, 2]~ [Mod(Mod(y + 2, y^2 + 1), x)]~ [-1/5, 7/5]~ [-1/5, 7/5]~ [Mod(Mod(-y, y^2 + 1), x)]~ [1, 2]~ [Mod(Mod(y, y^2 + 1), x)] [ 0 1] [-1 0] x + Mod(2*y - 1, y^2 + 1) Mod(-y - 3, y^2 + 1) 1 Mod(-y - 3, y^2 + 1) 1 1 1 0 0 1 1 1 0 [] trivial algebra over Q [[x, [1], [1, 1], 1, [], [], [[1], [1]], Mat(1), 1, [y, [1, 0], 1, 1, [Mat(1 ), Mat(1), Mat(16), Mat(1), 1, Mat(1), [1, 0], []], [0.E-57], [1], Mat(1), M at(1)], [x, 0, 0, y, x], [[x, [1, 0], 1, 1, [Mat(1), Mat(1), Mat(16), Mat(1) , 1, Mat(1), [1, 0], []], [0.E-77], [1], Mat(1), Mat(1)], [Mat(1), Mat(1), 1 , Vecsmall([1])]]], [0], Mod(1, y), Vecsmall([0]), [[], Vecsmall([])], 0, Ma t(1), Mat(1), [Mat(1)], 0, [1]] [-2]~ [1/3]~ [4/5]~ [-5/3]~ [14/5]~ [-2/3]~ [12/5]~ [12/5]~ [-1/2]~ [1/3]~ [-2] [Mod(1/3, x)] x - 1/3 4/5 4/5 4/5 1 1 1 0 0 1 1 1 0 [] trivial CSA over Q [Mod(9, y)]~ [4]~ nontrivial CSA over Q [Mod(0, y), Mod(12, y), Mod(6, y), Mod(12, y)]~ [-81, 27, 36, 45]~ empty matrices -v: 1 v^(-1): 1 v^n: 1 v^0: 1 mt(v)1 spl(v)1 trace(v): 1 trace abs(v): 1 norm(v): 1 charpoly(v): 1 v+v: 1 v-v: 1 v*v: 1 v/v: 1 v\v: 1 v*nv: 1 v*v 2: 1 trace(v) char 2: 1 [0, 0, 0, 0, 0, 0, Mat(1), Mat(1), [Mat(1)], 0, [1]] [12]~ [-1/7]~ [83/7]~ [85/7]~ [-12/7]~ [-12]~ [1/12]~ [1/49]~ [-1/84]~ 12 12 -1/7 x - 12 [-1/7] [1]~ 1 1 1 1 trivial tensor product 1 1 splitting a nasty commutative algebra 1 1 1 1 non associative algebra 0 csa without maximal order simplify bug #1671 testing simplify: degree 1 cyclic over Q 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 testing simplify: degree 1 cyclic over Q(i) 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 testing simplify: degree 1 csa over Q 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 testing simplify: degree 1 csa over Q(i) 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 testing simplify: quatalg over Q(s5) 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 testing simplify: quatalg csa over Q 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 [1 0] [0 0] [0 1/2] [0 0] algpoleval relative poly in basis form 1 1 1 1 1 1 doc algpoleval 1 1 1 1 splitting field bug for CSA 1 1 *** at top-level: algsplittingfield(almt) *** ^----------------------- *** algsplittingfield: incorrect type in alg_get_splittingfield [use alginit] (t_VEC). *** at top-level: algdegree(almt) *** ^--------------- *** algdegree: incorrect type in alg_get_degree [use alginit] (t_VEC). *** at top-level: alghassei(almt) *** ^--------------- *** alghassei: incorrect type in alg_get_hasse_i [use alginit] (t_VEC). *** at top-level: alghassef(almt) *** ^--------------- *** alghassef: incorrect type in alg_get_hasse_f [use alginit] (t_VEC). *** at top-level: algrandom(1,1) *** ^-------------- *** algrandom: incorrect type in checkalg [please apply alginit()] (t_INT). *** at top-level: algrandom(almt,I) *** ^----------------- *** algrandom: incorrect type in algrandom (t_COMPLEX). 0 *** at top-level: algdim([1,[1],0,0,0,0,0,0,0,0]) *** ^------------------------------- *** algdim: incorrect type in checkalg [please apply alginit()] (t_VEC). *** at top-level: algdim([1,[1],0,0,0,0,0,0,0,0],1) *** ^--------------------------------- *** algdim: incorrect type in checkalg [please apply alginit()] (t_VEC). *** at top-level: algtensor(al,al2) *** ^----------------- *** algtensor: incorrect type in checkalg [please apply alginit()] (t_VEC). *** at top-level: algtensor(al2,al) *** ^----------------- *** algtensor: incorrect type in checkalg [please apply alginit()] (t_VEC). *** at top-level: algtensor(1,z,1) *** ^---------------- *** algtensor: incorrect type in checkalg [please apply alginit()] (t_INT). *** at top-level: algisassociative([1],0) *** ^----------------------- *** algisassociative: incorrect type in algisassociative (mult. table) (t_VEC). 0 *** at top-level: algmul(almt,a,b) *** ^---------------- *** algmul: incorrect type in alg_model (t_COL). *** at top-level: algtomatrix(almt,a,1) *** ^--------------------- *** algtomatrix: incorrect type in alg_model (t_COL). *** at top-level: alginv(almt,a) *** ^-------------- *** alginv: incorrect type in alg_model (t_COL). *** at top-level: algalgtobasis(almt,a) *** ^--------------------- *** algalgtobasis: incorrect type in algalgtobasis [use alginit] (t_VEC). *** at top-level: algbasistoalg(almt,[0,0,0,0]~) *** ^------------------------------ *** algbasistoalg: incorrect type in algbasistoalg [use alginit] (t_VEC). *** at top-level: algpoleval(almt,1,a) *** ^-------------------- *** algpoleval: incorrect type in algpoleval (t_INT). *** at top-level: algadd(almt,[zero;zero],m) *** ^-------------------------- *** algadd: inconsistent dimensions in alM_add (rows). *** at top-level: algadd(almt,[zero;zero;zero],[zero;zero]) *** ^----------------------------------------- *** algadd: inconsistent dimensions in alM_add (columns). *** at top-level: algsub(almt,[zero;zero],m) *** ^-------------------------- *** algsub: inconsistent dimensions in alM_sub (rows). *** at top-level: algsub(almt,[zero;zero;zero],[zero;zero]) *** ^----------------------------------------- *** algsub: inconsistent dimensions in alM_sub (columns). *** at top-level: algmul(almt,m,[zero;zero;zero]) *** ^------------------------------- *** algmul: inconsistent dimensions in alM_mul. *** at top-level: algsqr(almt,[zero;zero]) *** ^------------------------ *** algsqr: inconsistent dimensions in alM_mul. *** at top-level: algdivl(almt,m,zero) *** ^-------------------- *** algdivl: forbidden division t_MAT (1 x 2) \ t_COL (4 elts). *** at top-level: algdivl(almt,Mat([[zero]~]),[zero,zero;zero,ze *** ^---------------------------------------------- *** algdivl: inconsistent dimensions in algdivl. *** at top-level: algdivl(almt,m,m) *** ^----------------- *** algdivl: inconsistent dimensions in algdivl (nonsquare). *** at top-level: alginv(almt,m) *** ^-------------- *** alginv: inconsistent dimensions in alginv_i (nonsquare). *** at top-level: algtomatrix(almt,m,1) *** ^--------------------- *** algtomatrix: inconsistent dimensions in algleftmultable_mat (nonsquare). *** at top-level: algpow(almt,m,3) *** ^---------------- *** algpow: inconsistent dimensions in alM_mul. *** at top-level: algtrace(almt,m) *** ^---------------- *** algtrace: inconsistent dimensions in algtrace_mat (nonsquare). *** at top-level: algcharpoly(almt,m) *** ^------------------- *** algcharpoly: inconsistent dimensions in algleftmultable_mat (nonsquare). *** at top-level: algcharpoly(alginit(nfinit(y),[-1,-1]),m) *** ^----------------------------------------- *** algcharpoly: incorrect type in easychar (t_MAT). *** at top-level: algnorm(almt,m) *** ^--------------- *** algnorm: inconsistent dimensions in algleftmultable_mat (nonsquare). *** at top-level: algnorm(alginit(nfinit(y),[-1,-1]),m) *** ^------------------------------------- *** algnorm: inconsistent dimensions in det. *** at top-level: alginit(nfinit(y),[2,[[],[]],[x]]) *** ^---------------------------------- *** alginit: incorrect type in Hasse invariant (t_POL). *** at top-level: alginit(nfinit(y),[2,[],[1,1]]) *** ^------------------------------- *** alginit: incorrect type in checkhasse [hf] (t_VECSMALL). *** at top-level: alginit(nfinit(y),[2,[[],[]],Vecsmall([1])]) *** ^-------------------------------------------- *** alginit: domain error in checkhasse: sum(Hasse invariants) != 0 *** at top-level: alginit(y,[2,[[],[]],[1]]) *** ^-------------------------- *** alginit: incorrect type in alginit (t_POL). *** at top-level: alginit(nfinit(y),y) *** ^-------------------- *** alginit: incorrect type in alginit (t_POL). *** at top-level: alginit(nfinit(y),[1,2,3,4]) *** ^---------------------------- *** alginit: incorrect type in alginit (t_VEC). *** at top-level: algtableinit(mt,y) *** ^------------------ *** algtableinit: incorrect type in algtableinit (t_POL). *** at top-level: alginit(nfinit(y^2+1),-3) *** ^------------------------- *** alginit: domain error in alg_matrix: n <= 0 *** at top-level: alginit(nfinit(x^2+1),3) *** ^------------------------ *** alginit: incorrect priority in alginit: variable x >= x *** at top-level: alginit(nfinit(highvar^2+1),3) *** ^------------------------------ *** alginit: incorrect priority in alginit: variable x >= highvar *** at top-level: ...t(nfinit(y^2-2),[-1,-1]);algrandom(al,-10) *** ^----------------- *** algrandom: domain error in algrandom: b < 0 *** at top-level: algrelmultable(al) *** ^------------------ *** algrelmultable: incorrect type in alg_get_relmultable [algebra not given via mult. table] (t_VEC). *** at top-level: algsplittingdata(al) *** ^-------------------- *** algsplittingdata: incorrect type in alg_get_splittingdata [algebra not given via mult. table] (t_VEC). *** at top-level: alghasse(almt,1) *** ^---------------- *** alghasse: incorrect type in alghasse [use alginit] (t_VEC). *** at top-level: algindex(almt,1) *** ^---------------- *** algindex: incorrect type in algindex [use alginit] (t_VEC). *** at top-level: algisdivision(almt) *** ^------------------- *** algisdivision: sorry, algisdivision for table algebras is not yet implemented. *** at top-level: algissplit(almt) *** ^---------------- *** algissplit: incorrect type in algissplit [use alginit] (t_VEC). *** at top-level: algisramified(almt) *** ^------------------- *** algisramified: incorrect type in algissplit [use alginit] (t_VEC). *** at top-level: algramifiedplaces(almt) *** ^----------------------- *** algramifiedplaces: incorrect type in algramifiedplaces [not a central simple algebra over a number field] (t_VEC). *** at top-level: alghasse(al) *** ^------------ *** alghasse: must provide a place pl. *** at top-level: alghasse(al,-1) *** ^--------------- *** alghasse: domain error in is_place_emb: pl <= 0 *** at top-level: alghasse(al,3) *** ^-------------- *** alghasse: domain error in is_place_emb: pl > 2 *** at top-level: alghasse(al,2^100) *** ^------------------ *** alghasse: domain error in is_place_emb: pl > 2 *** at top-level: alghasse(al,[]) *** ^--------------- *** alghasse: incorrect type in is_place_emb (t_VEC). *** at top-level: alghasse(al,1/3) *** ^---------------- *** alghasse: incorrect type in is_place_emb (t_FRAC). *** at top-level: algtableinit([matid(2),[0,1/2;1,0]]) *** ^------------------------------------ *** algtableinit: domain error in algtableinit: denominator(mt) != 1 *** at top-level: alginit(Q,[matid(2),[0,1/2;1,0]]) *** ^--------------------------------- *** alginit: domain error in alg_csa_table: denominator(mt) != 1 *** at top-level: alginit(Q,[-1/2,-1]) *** ^-------------------- *** alginit: domain error in alg_hilbert: denominator(a) != 1 *** at top-level: alginit(Q,[-1,-1/2]) *** ^-------------------- *** alginit: domain error in alg_hilbert: denominator(b) != 1 *** at top-level: alginit(rnfinit(Q,x^2+1),[-x,-1/2]) *** ^----------------------------------- *** alginit: domain error in alg_cyclic: denominator(b) != 1 *** at top-level: algsqr([0,0,0,0,0,0,0,0,0,0,0],[]~) *** ^----------------------------------- *** algsqr: incorrect type in checkalg [please apply alginit()] (t_VEC). *** at top-level: algsqr([0,0,0,0,0,0,0,0,[],0,0],[]~) *** ^------------------------------------ *** algsqr: incorrect type in checkalg [please apply alginit()] (t_VEC). *** at top-level: algsqr([0,0,0,0,0,0,0,0,[0],0,0],[]~) *** ^------------------------------------- *** algsqr: incorrect type in checkalg [please apply alginit()] (t_VEC). *** at top-level: algsqr([0,0,0,0,0,0,0,0,[[;]],0,0],[]~) *** ^--------------------------------------- *** algsqr: incorrect type in alg_model (t_COL). *** at top-level: algsqr([[],0,0,0,0,0,0,0,[[;]],0,0],[]~) *** ^---------------------------------------- *** algsqr: incorrect type in checkalg [please apply alginit()] (t_VEC). *** at top-level: algsqr([[],[0],0,0,0,0,0,0,[[;]],0,0],[]~) *** ^------------------------------------------ *** algsqr: incorrect type in checkalg [please apply alginit()] (t_VEC). *** at top-level: algdim([[],[0],0,0,0,0,0,0,[[;]],0,0]) *** ^-------------------------------------- *** algdim: incorrect type in checkalg [please apply alginit()] (t_VEC). *** at top-level: algdegree([[],[0],0,0,0,0,0,0,[[;]],0,0]) *** ^----------------------------------------- *** algdegree: incorrect type in checkalg [please apply alginit()] (t_VEC). *** at top-level: algdegree([rnfinit(nfinit(y),x),[[]],0,0,0,0,0 *** ^---------------------------------------------- *** algdegree: incorrect type in alg_get_degree [use alginit] (t_VEC). *** at top-level: algcenter([rnfinit(nfinit(y),x),[[]],0,0,0,0,0 *** ^---------------------------------------------- *** algcenter: incorrect type in alg_get_center [use alginit] (t_VEC). *** at top-level: algcentralproj(almt,0) *** ^---------------------- *** algcentralproj: incorrect type in alcentralproj (t_INT). *** at top-level: algcentralproj(almt,[zero,zero]) *** ^-------------------------------- *** algcentralproj: incorrect type in alcentralproj [z[i]'s not surjective] (t_VEC). *** at top-level: algsubalg(almt,0) *** ^----------------- *** algsubalg: incorrect type in algsubalg (t_INT). *** at top-level: algisassociative([]) *** ^-------------------- *** algisassociative: incorrect type in algisassociative (mult. table) (t_VEC). *** at top-level: algisassociative([matid(2),Mat([1,1])]) *** ^--------------------------------------- *** algisassociative: incorrect type in algisassociative (mult. table) (t_VEC). 0 *** at top-level: algisassociative([matid(1)],[]) *** ^------------------------------- *** algisassociative: incorrect type in algisassociative (t_VEC). *** at top-level: algsqr(algtableinit([matid(1)]),[1,2]~) *** ^--------------------------------------- *** algsqr: incorrect type in alg_model (t_COL). *** at top-level: algsqr(al,vector(691)~) *** ^----------------------- *** algsqr: incorrect type in alg_model (t_COL). *** at top-level: algsqr(al,[1,2,3,4,5,6,7,f^2]~) *** ^------------------------------- *** algsqr: incorrect type in checkalgx (t_POL). *** at top-level: algsqr(al,[f^3,[]]~) *** ^-------------------- *** algsqr: incorrect type in checkalgx (t_VEC). *** at top-level: algmul(al,[;],[1,2]~) *** ^--------------------- *** algmul: incorrect type in algmul (t_COL). *** at top-level: algdivl(al,[;],matid(1)) *** ^------------------------ *** algdivl: inconsistent dimensions in algdivl. *** at top-level: algdivl(al,matid(1),matrix(1,2)) *** ^-------------------------------- *** algdivl: inconsistent dimensions in algdivl (nonsquare). *** at top-level: algdivl(al,matrix(0,3),[;]) *** ^--------------------------- *** algdivl: inconsistent dimensions in algdivl (nonsquare). *** at top-level: algdivl(al,[;],matrix(0,3)) *** ^--------------------------- *** algdivl: inconsistent dimensions in algdivl (nonsquare). *** at top-level: algdivl(al,matrix(1,1),[;]) *** ^--------------------------- *** algdivl: inconsistent dimensions in algdivl. *** at top-level: alginv(al,[0,0]~) *** ^----------------- *** alginv: impossible inverse in alginv: [0, 0]~. *** at top-level: algalgtobasis(al0mt,[1]~) *** ^------------------------- *** algalgtobasis: incorrect type in algalgtobasis [use alginit] (t_VEC). *** at top-level: algbasistoalg(al0mt,[1]~) *** ^------------------------- *** algbasistoalg: incorrect type in algbasistoalg [use alginit] (t_VEC). *** at top-level: nfgrunwaldwang(nfinit(y),0,[],[],'x) *** ^------------------------------------ *** nfgrunwaldwang: incorrect type in nfgrunwaldwang (t_INT). *** at top-level: nfgrunwaldwang(nfinit(y),[2],'x-'x,[1]) *** ^--------------------------------------- *** nfgrunwaldwang: incorrect type in nfgrunwaldwang (t_POL). *** at top-level: alginit(rnfinit(nfinit(y),x),0) *** ^------------------------------- *** alginit: incorrect type in alginit (t_INT). *** at top-level: alginit(rnfinit(nfinit(y),x),[1,2,3,4]) *** ^--------------------------------------- *** alginit: incorrect type in alginit (t_VEC). *** at top-level: alginit(nfinit(y),[matid(2),matid(2)]) *** ^-------------------------------------- *** alginit: incorrect type in alg_csa_table (t_VEC). *** at top-level: alginit(nfinit(y),[matid(2),[0,1;1,0]]) *** ^--------------------------------------- *** alginit: domain error in alg_csa_table: (nonsquare) dimension != 1 *** at top-level: nfgrunwaldwang(nfinit(y),0,[],[0]) *** ^---------------------------------- *** nfgrunwaldwang: incorrect type in nfgrunwaldwang (t_INT). *** at top-level: nfgrunwaldwang(nfinit(y),[2],[],[0]) *** ^------------------------------------ *** nfgrunwaldwang: inconsistent dimensions in nfgrunwaldwang [#Lpr != #Ld]. *** at top-level: nfgrunwaldwang(nfinit(y),[2],[2],[]) *** ^------------------------------------ *** nfgrunwaldwang: domain error in nfgrunwaldwang [pl should have r1 components]: #pl != 1 *** at top-level: nfgrunwaldwang(nfinit(y),[2],[6],[0]) *** ^------------------------------------- *** nfgrunwaldwang: sorry, nfgrunwaldwang for non prime-power local degrees (a) is not yet implemented. *** at top-level: nfgrunwaldwang(nfinit(y),[2,3],[2,3],[0]) *** ^----------------------------------------- *** nfgrunwaldwang: sorry, nfgrunwaldwang for non prime-power local degrees (b) is not yet implemented. *** at top-level: nfgrunwaldwang(nfinit(y),[2],[3],[-1]) *** ^-------------------------------------- *** nfgrunwaldwang: sorry, nfgrunwaldwang for non prime-power local degrees (c) is not yet implemented. *** at top-level: nfgrunwaldwang(nfinit(y),[[]~],[3],[-1]) *** ^---------------------------------------- *** nfgrunwaldwang: incorrect type in checkprid (t_COL). *** at top-level: nfgrunwaldwang(nfinit(y),[2],[9],[0]) *** ^------------------------------------- *** nfgrunwaldwang: sorry, nfgrunwaldwang for nonprime degree is not yet implemented. *** at top-level: algdegree(A) *** ^------------ *** algdegree: incorrect type in alg_get_degree [use alginit] (t_VEC). *** at top-level: algsub(A,1,1) *** ^------------- *** algsub: incorrect type in alg_model (t_INT). *** at top-level: algadd(A,1,1) *** ^------------- *** algadd: incorrect type in alg_model (t_INT). *** at top-level: algneg(A,1) *** ^----------- *** algneg: incorrect type in alg_model (t_INT). *** at top-level: algmul(A,1,1) *** ^------------- *** algmul: incorrect type in alg_model (t_INT). *** at top-level: algsqr(A,1) *** ^----------- *** algsqr: incorrect type in alg_model (t_INT). *** at top-level: algdivl(A,1,1) *** ^-------------- *** algdivl: incorrect type in alg_model (t_INT). *** at top-level: algdivr(A,1,1) *** ^-------------- *** algdivr: incorrect type in alg_model (t_INT). *** at top-level: alginv(A,1) *** ^----------- *** alginv: incorrect type in alg_model (t_INT). *** at top-level: ...;PR=idealprimedec(K,2);A=alginit(K,[3,[PR,[1]] *** ^--------------------- *** alginit: domain error in checkhasse: Hasse invariant at real place [must be 0 or 1/2] != 0 *** at top-level: ...;P3=idealprimedec(K,3);A=alginit(K,[3,[concat( *** ^--------------------- *** alginit: domain error in checkhasse: Hasse invariant at real place [must be 0 or 1/2] != 0 *** at top-level: algtensor(alginit(nfinit(y),2),alginit(nfinit( *** ^---------------------------------------------- *** algtensor: inconsistent tensor product [not the same center] t_VEC (11 elts) , t_VEC (11 elts). *** at top-level: algtensor(alginit(nfinit(y),2),alginit(nfinit( *** ^---------------------------------------------- *** algtensor: sorry, tensor of cyclic algebras of noncoprime degrees is not yet implemented. *** at top-level: alginit(nf,[2,[[p2,p2],[1/2,1/2]],[0]]) *** ^--------------------------------------- *** alginit: error in checkhasse [duplicate prime ideal]. *** at top-level: alginit(nf,[2,[[p2,p3],[1/2,1/2]],[0,0]]) *** ^----------------------------------------- *** alginit: domain error in checkhasse [hi should have r1 components]: #hi != 1 *** at top-level: alginit(nf,[2,[[p2,p3],[1/2,1/2],0],[0]]) *** ^----------------------------------------- *** alginit: incorrect type in Hasse invariant (t_VEC). *** at top-level: alginit(nf,[2,[0,[1/2,1/2]],[0]]) *** ^--------------------------------- *** alginit: incorrect type in Hasse invariant (t_VEC). *** at top-level: alginit(nf,[2,[[p2,p3],0],[0]]) *** ^------------------------------- *** alginit: incorrect type in Hasse invariant (t_INT). *** at top-level: alginit(nf,[2,[[p2,p3],[1/2,1/2,0]],[0]]) *** ^----------------------------------------- *** alginit: inconsistent dimensions in checkhasse [Lpr and Lh should have same length]. *** at top-level: alginit(nf,[2,[[p2,p3],[1/2,1/2]],[1/3]]) *** ^----------------------------------------- *** alginit: domain error in hasseconvert [degree should be a denominator of the invariant]: denom(h) ndiv 2 *** at top-level: algcharpoly(al,a,'z) *** ^-------------------- *** algcharpoly: incorrect priority in algredcharpoly: variable z >= y *** at top-level: algcharpoly(al,[1,2,3]~) *** ^------------------------ *** algcharpoly: incorrect type in alg_model (t_COL). *** at top-level: algindex(1,1) *** ^------------- *** algindex: incorrect type in checkalg [please apply alginit()] (t_INT). *** at top-level: algsqr(al,[Mod(1,y),Mod(2,y)]~) *** ^------------------------------- *** algsqr: incorrect type in alg_model (t_COL). *** at top-level: algsqr(al,[Mod(1,y),Mod(2,y)]~) *** ^------------------------------- *** algsqr: incorrect type in alg_model (t_COL). *** at top-level: alfail=alginit(nf,[0,0],'x) *** ^-------------------- *** alginit: domain error in rnfequation: issquarefree(B) = 0 *** at top-level: algb(al) *** ^-------- *** algb: incorrect type in alg_get_b [noncyclic algebra] (t_VEC). *** at top-level: algaut(al) *** ^---------- *** algaut: incorrect type in alg_get_aut [noncyclic algebra] (t_VEC). *** at top-level: algtableinit([Mat(1)],1) *** ^------------------------ *** algtableinit: not a prime number in algtableinit: 1. *** at top-level: algtableinit([Mat(1)],4) *** ^------------------------ *** algtableinit: not a prime number in algtableinit: 4. *** at top-level: algpoleval(al,x+1,"toto") *** ^------------------------- *** algpoleval: incorrect type in alg_model (t_STR). *** at top-level: algpoleval(al,x+1,[1,2,3]) *** ^-------------------------- *** algpoleval: incorrect type in algpoleval [vector must be of length 2] (t_VEC). *** at top-level: algpoleval(al,x+1,[1,2]) *** ^------------------------ *** algpoleval: incorrect type in algpoleval [mx must be the multiplication table of x] (t_INT). *** at top-level: algpoleval(al,x+1,[a,mb]) *** ^------------------------- *** algpoleval: incorrect type in algpoleval [mx must be the multiplication table of x] (t_MAT). *** at top-level: algpoleval(al,x+1,[1,mb]) *** ^------------------------- *** algpoleval: incorrect type in algpoleval [mx must be the multiplication table of x] (t_MAT). *** at top-level: alginit(nfinit(y),["a",[[],[]],[]]) *** ^----------------------------------- *** alginit: incorrect type in alginit [degree should be an integer] (t_STR). *** at top-level: alginit(nfinit(y),[1,[[],[]],[]]) *** ^--------------------------------- *** alginit: domain error in alg_hasse: degree <= 1 *** at top-level: alginit(nfinit(y),[0,[[],[]],[]]) *** ^--------------------------------- *** alginit: domain error in alg_hasse: degree <= 1 *** at top-level: algrandom(,1) *** ^------------- *** algrandom: incorrect type in algrandom (t_INT). *** at top-level: algrandom(,-1.) *** ^--------------- *** algrandom: domain error in algrandom: b < 0 *** at top-level: algneg(,[1..4]) *** ^--------------- *** algneg: incorrect type in H_model (t_VEC). *** at top-level: algneg(,Mod(1,2)) *** ^----------------- *** algneg: incorrect type in H_model (t_INTMOD). *** at top-level: algneg(,[1..5]~) *** ^---------------- *** algneg: incorrect type in H_model (t_COL). *** at top-level: algneg(,[1,2,3,I]~) *** ^------------------- *** algneg: incorrect type in H_model (t_COL). *** at top-level: algadd(,1,[]~) *** ^-------------- *** algadd: incorrect type in H_model (t_COL). *** at top-level: algadd(,O(3^3),I) *** ^----------------- *** algadd: incorrect type in H_model (t_PADIC). *** at top-level: algadd(,I,[1;2]) *** ^---------------- *** algadd: forbidden H_add t_COMPLEX , t_MAT (2 x 1). *** at top-level: algadd(,Mat([1,2]),[3;4]) *** ^------------------------- *** algadd: inconsistent dimensions in alM_add (rows). *** at top-level: algadd(,Mat(1),Mat(O(3))) *** ^------------------------- *** algadd: incorrect type in H_model (t_PADIC). *** at top-level: algadd(,I,Mat(2)) *** ^----------------- *** algadd: forbidden H_add t_COMPLEX , t_MAT (1 x 1). *** at top-level: algtrace(,O(x^2)) *** ^----------------- *** algtrace: incorrect type in H_model (t_SER). *** at top-level: algtrace(,[[1..4]~;[2..5]~]) *** ^---------------------------- *** algtrace: inconsistent dimensions in algtrace_mat (nonsquare). *** at top-level: algtomatrix(,1+I*'x) *** ^-------------------- *** algtomatrix: incorrect type in H_model (t_POL). *** at top-level: algmul(,[1,2,3,4]~,'x) *** ^---------------------- *** algmul: incorrect type in H_model (t_POL). *** at top-level: algmul(,'y,I) *** ^------------- *** algmul: incorrect type in H_model (t_POL). *** at top-level: algmul(,[1,2;3,4],1+I) *** ^---------------------- *** algmul: forbidden H_mul t_MAT (2 x 2) , t_COMPLEX. *** at top-level: algsqr(,O(3^3)) *** ^--------------- *** algsqr: incorrect type in H_model (t_PADIC). *** at top-level: algnorm(,Mod(1,2)) *** ^------------------ *** algnorm: incorrect type in H_model (t_INTMOD). *** at top-level: algcharpoly(,sin) *** ^----------------- *** algcharpoly: incorrect type in H_model (t_CLOSURE). *** at top-level: alginv(,'x) *** ^----------- *** alginv: incorrect type in H_model (t_POL). *** at top-level: alginv(,0) *** ^---------- *** alginv: impossible inverse in alginv: 0. *** at top-level: algdivl(,'x,1) *** ^-------------- *** algdivl: incorrect type in H_model (t_POL). *** at top-level: algdivl(,[1,2,3,4]~,'y) *** ^----------------------- *** algdivl: incorrect type in H_model (t_POL). *** at top-level: algdivl(,0,1) *** ^------------- *** algdivl: impossible inverse in algdivl: 0. *** at top-level: algdivl(,[;],1) *** ^--------------- *** algdivl: forbidden H_divl t_MAT (0 x 0) , t_INT. *** at top-level: algdivl(,[1,2,3,4]~,[;]) *** ^------------------------ *** algdivl: forbidden H_divl t_COL (4 elts) , t_MAT (0 x 0). *** at top-level: algdivl(,[1;2],Pi) *** ^------------------ *** algdivl: forbidden H_divl t_MAT (2 x 1) , t_REAL. *** at top-level: algpoleval(,'x,'x) *** ^------------------ *** algpoleval: incorrect type in H_model (t_POL). *** at top-level: algpoleval(,'x,[1,2;3,4]) *** ^------------------------- *** algpoleval: incorrect type in H_poleval (t_MAT). *** at top-level: algpoleval(,O(3),[1,2,3,4]~) *** ^---------------------------- *** algpoleval: incorrect type in algpoleval (t_PADIC). *** at top-level: algdivl(,matrix(0,3),[;]) *** ^------------------------- *** algdivl: inconsistent dimensions in H_divl (nonsquare). *** at top-level: algdivl(,[;],matrix(0,3)) *** ^------------------------- *** algdivl: inconsistent dimensions in H_divl (nonsquare). *** at top-level: algdivl(,matrix(1,1),[;]) *** ^------------------------- *** algdivl: inconsistent dimensions in H_divl. *** at top-level: algramifiedplaces(H) *** ^-------------------- *** algramifiedplaces: incorrect type in algramifiedplaces [not a central simple algebra over a number field] (t_VEC). *** at top-level: H0=H;H0[1]=O(2);algrandom(H0,1.) *** ^---------------- *** algrandom: incorrect type in checkalg [please apply alginit()] (t_VEC). *** at top-level: algsqr(H,[]~) *** ^------------- *** algsqr: incorrect type in H_model (t_COL). *** at top-level: algsqr(H,O(x)) *** ^-------------- *** algsqr: incorrect type in H_model (t_SER). *** at top-level: algalgtobasis(H,1) *** ^------------------ *** algalgtobasis: incorrect type in algalgtobasis [use alginit] (t_VEC). *** at top-level: algbasistoalg(H,1) *** ^------------------ *** algbasistoalg: incorrect type in algbasistoalg [use alginit] (t_VEC). *** at top-level: algcentralproj(H,[1]) *** ^--------------------- *** algcentralproj: incorrect type in algcentralproj [not a table algebra] (t_VEC). *** at top-level: algcharpoly(R,[1,2,3,4]~) *** ^------------------------- *** algcharpoly: incorrect type in R_charpoly (t_COL). *** at top-level: algcharpoly(C,[1,2,3,4]~) *** ^------------------------- *** algcharpoly: incorrect type in C_charpoly (t_COL). *** at top-level: algdisc(R) *** ^---------- *** algdisc: incorrect type in algdisc [real algebra] (t_VEC). *** at top-level: algdisc(C) *** ^---------- *** algdisc: incorrect type in algdisc [real algebra] (t_VEC). *** at top-level: algdisc(H) *** ^---------- *** algdisc: incorrect type in algdisc [real algebra] (t_VEC). *** at top-level: algdivl(C,[;],1) *** ^---------------- *** algdivl: forbidden C_divl t_MAT (0 x 0) , t_INT. *** at top-level: algdivl(C,[1,2,3,4]~,[1,2,3,4]~) *** ^-------------------------------- *** algdivl: incorrect type in C_divl (t_COL). *** at top-level: algdivl(C,matrix(2,1),matrix(1,1)) *** ^---------------------------------- *** algdivl: inconsistent dimensions in C_divl (nonsquare). *** at top-level: algdivl(C,matrix(2,2),matrix(3,3)) *** ^---------------------------------- *** algdivl: inconsistent dimensions in C_divl. *** at top-level: alginit(1.,1) *** ^------------- *** alginit: domain error in alginit: real Hasse invariant [must be 0 or 1/2] out of range *** at top-level: alginv(C,[1..4]~) *** ^----------------- *** alginv: incorrect type in alginv_i (t_COL). *** at top-level: alginv(C,0) *** ^----------- *** alginv: impossible inverse in alginv: 0. *** at top-level: alglatadd(H,[matid(4),1],[matid(4),1]) *** ^-------------------------------------- *** alglatadd: incorrect type in alglataddinter [real algebra] (t_VEC). *** at top-level: alglatcontains(H,[matid(4),1],[1..4]~) *** ^-------------------------------------- *** alglatcontains: incorrect type in alglatcontains [real algebra] (t_VEC). *** at top-level: alglatelement(H,[matid(4),1],[1..4]~) *** ^------------------------------------- *** alglatelement: incorrect type in alglatelement [real algebra] (t_VEC). *** at top-level: alglathnf(H,matid(4)) *** ^--------------------- *** alglathnf: incorrect type in alglathnf [real algebra] (t_VEC). *** at top-level: alglatindex(H,[matid(4),1],[matid(4),1]) *** ^---------------------------------------- *** alglatindex: incorrect type in alglatindex [real algebra] (t_VEC). *** at top-level: alglatinter(H,[matid(4),1],[matid(4),1]) *** ^---------------------------------------- *** alglatinter: incorrect type in alglataddinter [real algebra] (t_VEC). *** at top-level: alglatlefttransporter(H,[matid(4),1],[matid(4) *** ^---------------------------------------------- *** alglatlefttransporter: incorrect type in alglatlefttransporter [real algebra] (t_VEC). *** at top-level: alglatmul(H,[matid(4),1],[matid(4),1]) *** ^-------------------------------------- *** alglatmul: incorrect type in alglatmul [real algebra] (t_VEC). *** at top-level: alglatrighttransporter(H,[matid(4),1],[matid(4 *** ^---------------------------------------------- *** alglatrighttransporter: incorrect type in alglatrighttransporter [real algebra] (t_VEC). *** at top-level: alglatsubset(H,[matid(4),1],[matid(4),1]) *** ^----------------------------------------- *** alglatsubset: incorrect type in alglatsubset [real algebra] (t_VEC). *** at top-level: algnorm(R,[1..4]~) *** ^------------------ *** algnorm: incorrect type in R_norm (t_COL). *** at top-level: algnorm(C,[1..4]~) *** ^------------------ *** algnorm: incorrect type in C_norm (t_COL). *** at top-level: algquotient(H,[;]) *** ^------------------ *** algquotient: incorrect type in alg_quotient [not a table algebra] (t_VEC). *** at top-level: algrelmultable(H) *** ^----------------- *** algrelmultable: incorrect type in alg_get_relmultable [algebra not given via mult. table] (t_VEC). *** at top-level: algsplittingdata(H) *** ^------------------- *** algsplittingdata: incorrect type in alg_get_splittingdata [algebra not given via mult. table] (t_VEC). *** at top-level: algsubalg(H,[1;0;0;0]) *** ^---------------------- *** algsubalg: incorrect type in algsubalg [real algebra] (t_VEC). *** at top-level: algtableinit(H) *** ^--------------- *** algtableinit: incorrect type in algtableinit (t_VEC). *** at top-level: algtensor(H,H) *** ^-------------- *** algtensor: sorry, tensor of noncyclic algebras is not yet implemented. *** at top-level: algtomatrix(R,[1,2,3,4]~) *** ^------------------------- *** algtomatrix: incorrect type in R_tomatrix (t_COL). *** at top-level: algtomatrix(C,[1,2,3,4]~) *** ^------------------------- *** algtomatrix: incorrect type in C_tomatrix (t_COL). *** at top-level: algtrace(R,[1,2,3,4]~) *** ^---------------------- *** algtrace: incorrect type in R_trace (t_COL). *** at top-level: algtrace(C,[1,2,3,4]~) *** ^---------------------- *** algtrace: incorrect type in C_trace (t_COL). *** at top-level: algtrace(H0,1) *** ^-------------- *** algtrace: incorrect type in algtrace [apply alginit] (t_VEC). *** at top-level: algnorm(H0,1) *** ^------------- *** algnorm: incorrect type in algnorm [apply alginit] (t_VEC). *** at top-level: algcharpoly(H0,1) *** ^----------------- *** algcharpoly: incorrect type in algcharpoly [apply alginit] (t_VEC). *** at top-level: algtomatrix(H0,1) *** ^----------------- *** algtomatrix: incorrect type in algtomatrix [apply alginit] (t_VEC). *** at top-level: alginv(H0,1) *** ^------------ *** alginv: incorrect type in alginv_i [apply alginit] (t_VEC). *** at top-level: algdim(H0) *** ^---------- *** algdim: incorrect type in algreal_dim (t_VEC). *** at top-level: algrandom(H0,1.) *** ^---------------- *** algrandom: incorrect type in algrandom [apply alginit] (t_VEC). *** at top-level: algdim(al) *** ^---------- *** algdim: incorrect type in alg_get_dim (t_VEC). *** at top-level: algdim(al,1) *** ^------------ *** algdim: incorrect type in alg_get_absdim (t_VEC). *** at top-level: algsqr(al,[1..20]~) *** ^------------------- *** algsqr: incorrect type in alg_model (t_COL). *** at top-level: algsqr(al,[O(x)]~) *** ^------------------ *** algsqr: incorrect type in alg_model (t_COL). new algsimpledec 0 [0, [[[0, 0, 0, 0, 0, 0, Mat(1), Mat(1), [Mat(1)], 0, [1]], Mat([1, 1, 0]), [0; 1; 0]], [[0, 0, 0, 0, 0, 0, Mat(1), Mat(1), [Mat(1)], 0, [1]], Mat([1, 0 , 0]), [1; -1; -1]], [[0, 0, 0, 0, 0, 0, Mat(1), Mat(1), [Mat(1)], 0, [1]], Mat([1, 0, 1]), [0; 0; 1]]]] 0 [0, [[[0, 0, 0, 0, 0, 0, Mat(1), Mat(1), [Mat(1)], 5, [1]], Mat([1, 1, 0]), [0; 1; 0]], [[0, 0, 0, 0, 0, 0, Mat(1), Mat(1), [Mat(1)], 5, [1]], Mat([1, 0 , 1]), [0; 0; 1]], [[0, 0, 0, 0, 0, 0, Mat(1), Mat(1), [Mat(1)], 5, [1]], Ma t([1, 0, 0]), [1; 4; 4]]]] [[0; 0; 1], [[[0, 0, 0, 0, 0, 0, Mat(1), Mat(1), [Mat(1)], 0, [1]], Mat([1, 0, 0]), [1; -1; 0]], [[0, 0, 0, 0, 0, 0, Mat(1), Mat(1), [Mat(1)], 0, [1]], Mat([1, 1, 0]), [0; 1; 0]]]] [[0; 0; 1], [[[0, 0, 0, 0, 0, 0, Mat(1), Mat(1), [Mat(1)], 5, [1]], Mat([1, 1, 0]), [0; 1; 0]], [[0, 0, 0, 0, 0, 0, Mat(1), Mat(1), [Mat(1)], 5, [1]], M at([1, 0, 0]), [1; 4; 0]]]] norm(,1) 16 Mod(-y + 1, y^2 - 5) 16 16/6561 254891155326721/5764801 1 1 trace(,1) Mod(2*y + 2, y^2 - 5) 8 8 1 1 1 1 charpoly(,1) x^2 - 2*y*x - 4*y x^8 - 40*x^6 - 160*x^5 + 240*x^4 + 3200*x^3 + 9600*x^2 + 12800*x + 6400 x^8 - 40*x^6 - 160*x^5 + 240*x^4 + 3200*x^3 + 9600*x^2 + 12800*x + 6400 1 1 1 more al_MAT tests add 1 1 1 1 alg/basis 1 1 1 1 1 1 1 1 charpoly 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 inv/div 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 mul 1 1 1 neg 1 1 1 norm 1 1 1 pow 1 1 1 sqr 1 1 1 sub 1 1 1 trace 1 1 1 abs trace 1 1 1 algtomatrix 1 1 1 1 1 1 1 1 algleftmultable 1 1 1 1 1 1 1 1 1 1 1 1 more al_CSA tests 1 1 1 1 charpoly 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 inv/div 1 1 1 1 1 1 1 1 mul 1 1 1 neg 1 1 1 norm 1 1 1 pow 1 1 1 sqr 1 1 1 sub 1 1 1 trace 1 1 1 abs trace 1 1 1 algtomatrix 1 1 1 1 1 1 1 1 algleftmultable 1 1 1 1 1 1 1 1 1 1 csa pol/polmod bugs [[1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [0, -1, 0, 0; 1, 0, 0, 0; 0, 0, 0, -1; 0, 0, 1, 0], [0, 0, y, 0; 0, 0, 0, -y; 1, 0, 0, 0; 0, -1, 0, 0 ], [0, 0, 0, y; 0, 0, y, 0; 0, 1, 0, 0; 1, 0, 0, 0]] [Mod(1000/9*y + 4400/81, y^2 - 5), Mod(1000/9*y, y^2 - 5), Mod(1000/9*y, y^2 - 5), Mod(1000/27*y, y^2 - 5)]~ [Mod(927/1936*y + 2025/1936, y^2 - 5), Mod(-729/1936*y - 8343/9680, y^2 - 5) , Mod(-729/1936*y - 8343/9680, y^2 - 5), Mod(-243/1936*y - 2781/9680, y^2 - 5)]~ [Mod(50/9*y, y^2 - 5), Mod(10, y^2 - 5), Mod(10, y^2 - 5), Mod(10/3, y^2 - 5 )]~ 1 1 1 1 1 1 1 csa: denom over Z[y] but not over ZK [[1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [0, -1, 0, 0; 1, 0, 0, 0; 0, 0, 0, -1; 0, 0, 1, 0], [0, 0, 1/2*y - 1/2, 0; 0, 0, 0, -1/2*y + 1/2; 1, 0, 0, 0; 0, -1, 0, 0], [0, 0, 0, 1/2*y - 1/2; 0, 0, 1/2*y - 1/2, 0; 0, 1, 0, 0; 1, 0, 0, 0]] *** at top-level: al=alginit(nf,mt*Mod(1,nf.pol)) *** ^---------------------------- *** alginit: domain error in alg_csa_table: denominator(mt) != 1 al_MAT over al_CSA 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 algleftmultable 1 1 1 1 1 1 Hamilton quaternions ["t_REAL", "t_REAL", "t_REAL", "t_REAL"]~ 38 1 308 H_neg 1 1 1 1 1 1 H_add 1 1 1 1 1 1 H_trace 1 1 1 1 1 1 1 1 H_tomatrix 1 1 [1 0] [0 1] [1 0] [0 1] [1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1] [1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3x3 matrices 1 1 1 1 1 1 1 1 1 1 1 [-100 - 1000*I 0] [ 0 -100 + 1000*I] [ 1 + 2*I -3 - 4*I] [ 3 - 4*I 1 - 2*I] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 nonsquare matrices 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 *** at top-level: algpow(,m,-9) *** ^------------- *** algpow: impossible inverse in alginv: (...). 1 *** at top-level: algdivr(,m,n) *** ^------------- *** algdivr: impossible inverse in alginv: (...). 1 1 1 1 1 [;] 4 -I -1 "t_REAL" 0 2 4 4 1/2 Vecsmall([1]) 2 1 0 1 1 1 1 0 [[1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [0, -1, 0, 0; 1, 0, 0, 0; 0, 0, 0, -1; 0, 0, 1, 0], [0, 0, -1, 0; 0, 0, 0, 1; 1, 0, 0, 0; 0, -1, 0, 0 ], [0, 0, 0, -1; 0, 0, -1, 0; 0, 1, 0, 0; 1, 0, 0, 0]] 1 [[4, 4], [4, 4], [4, 4], [4, 4]] 1 1 1 1 1 1 0 1 "t_COMPLEX" 1 1 1 1 1 1 1 1 1 1 1 1 1 1 4 1 1 1 1 4 "t_REAL" 1 "t_REAL" 0 1 1 1 0 Vecsmall([0]) 1 1 1 1 0 1 1 1 [Mat(1)] 1 [[1, 1]] 1 0 1 "t_REAL" 1 1 "t_REAL" 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 4 I 1 I 0 1 1 2 0 Vecsmall([]) 1 1 1 1 0 1 1 1 [[1, 0; 0, 1], [0, -1; 1, 0]] 1 [[2, 2], [2, 2]] 1 1 1 0 1 "t_COMPLEX" 1 1 "t_COMPLEX" 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ["t_REAL"] 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 nfgrunwaldwang SEGV #1669 x^2 + Mod(-17, y) *** at top-level: nfgrunwaldwang(nfinit(x),[2,3],[1,2],Vecsmall( *** ^---------------------------------------------- *** nfgrunwaldwang: incorrect priority in nfgrunwaldwang: variable x >= x alginit SEGV #2465 *** at top-level: ...rnfinit(Q,x^3+x^2-2*x-1);alginit(F,[2,x^2-2]) *** ^-------------------- *** alginit: inconsistent variables in nf_to_scalar_or_basis, x != y. *** at top-level: alginit(F,[2,y]) *** ^---------------- *** alginit: incorrect type in alginit (t_POL). [1] [1] [1] [1/2] [1/2] 1 GW modified arguments 1 rnf/gchar confusion (#2473) "t_POL" 1 *** at top-level: algpoleval(al,pol,[;]) *** ^---------------------- *** algpoleval: incorrect type in algpoleval (t_MAT). 1 1 *** at top-level: al2=algtensor(al,al) *** ^---------------- *** algtensor: sorry, tensor of noncyclic algebras is not yet implemented. *** at top-level: al2=algtensor(al,al) *** ^---------------- *** algtensor: sorry, tensor of noncyclic algebras is not yet implemented. maxord flag *** at top-level: alghasse(alg,idealprimedec(Q,2)[1]) *** ^----------------------------------- *** alghasse: Hasse invariants were not computed for this algebra. *** at top-level: alghassef(alg) *** ^-------------- *** alghassef: Hasse invariants were not computed for this algebra. *** at top-level: algindex(alg) *** ^------------- *** algindex: Hasse invariants were not computed for this algebra. *** at top-level: algramifiedplaces(alg) *** ^---------------------- *** algramifiedplaces: Hasse invariants were not computed for this algebra. 1 1 1 1 1 1 1 1 *** nfinit: Warning: nonmonic polynomial. Result of the form [nf,c]. segfault in algsubalg for invalid input 3 integral coefficients in alginit 1 1 1 1 Total time spent: 1668 pari-2.17.2/src/test/32/ideal0000644000175000017500000001452014702763006014166 0ustar billbill[;] [1, 0] [1, 0] [[1]~, 0] [2, [2], [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] 0 [512, [16, 8, 4], [[-2, -3]~, [0, 5]~, [0, -1]~]] [1, [], []] [1/2 0] [ 0 1/2] [1]~ [5 2] [0 1] [2 1] [0 1] [2 0 0] [0 1 0] [0 0 1] [1/12 0 0] [ 0 1/12 0] [ 0 0 1/12] [2 0 0] [0 2 0] [0 0 2] [1/6 0 0] [ 0 1/6 0] [ 0 0 1/6] [1/3 0 0] [ 0 1/6 0] [ 0 0 1/6] [1 0 0] [0 1 0] [0 0 1/2] 0 0 1 1 [1725 35 1704] [ 0 5 4] [ 0 0 1] 5 [1 0 0] [0 1 0] [0 0 1/2] [1 0 0] [0 1 0] [0 0 1] [1/2 0 0] [ 0 1/2 0] [ 0 0 1/2] [1 0 0] [0 1 0] [0 0 1] [1 0 0] [0 1/2 0] [0 0 1/2] 7 8 9 10 11 [1 0 0] [0 1 0] [0 0 1] [[1, 0, 0; 0, 1, 0; 0, 0, 1], Mat([2, 1])] [[1, 0, 0; 0, 1, 0; 0, 0, 1], Mat([2, 1])] 1/2 6010/3 2510 2 6010/3 [2, [2]~, 1, 1, 1] 0 0 7 7 1 1 [5, [-1, -2, 1]~, 1, 2, [2, 0, 2; 1, 2, 0; 0, 1, 2]] 0 0 [[6, 4, 2, 4; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], [-4/3, -2/3, -1/3, -1/6]~ ] matrix(0,2) [[2, [2, 0, 0, 0]~, 1, 4, 1] 1] matrix(0,2) [[2, [2, 0, 0, 0]~, 1, 4, 1] -1] [[2, [2, 0, 0, 0]~, 1, 4, 1] 4] [[67452192952521724999, [-16711321285323715217, 1]~, 1, 1, [1671132128532371 5218, -1; 1, 16711321285323715217]] 1] [[762234946175168528650011228121, [-63146078120386376378131819641, 1]~, 1, 1 , [63146078120386376378131819642, -1; 1, 63146078120386376378131819641]] -1] [ [13, [-3, 1]~, 1, 1, [4, -1; 1, 3]] 2] [[13, [4, 1]~, 1, 1, [-3, -1; 1, -4]] 2] [ [3, [-1, 1]~, 2, 1, [-1, -1; 1, -2]] 1] [[37, [-10, 1]~, 1, 1, [11, -1; 1, 10]] 1] matrix(0,2) [[37, [-10, 1]~, 1, 1, [11, -1; 1, 10]] 1] [ [3, [-1, 1]~, 2, 1, [-1, -1; 1, -2]] 1] [ [37, [-10, 1]~, 1, 1, [11, -1; 1, 10]] 1] [[1093, [-151, 1]~, 1, 1, [152, -1; 1, 151]] 1] [67452192952521724999 19368419142280277485321497629511555041951889852345/762 234946175168528650011228121] [0 1/762234946175168528650011228121] [[67452192952521724999, 50740871667198009782; 0, 1], [7622349461751685286500 11228121, 699088868054782152271879408480; 0, 1]] [[67452192952521724999, 50740871667198009782; 0, 1], 1] [1, 1] [1, 2] [[1, 0; 0, 1], [2, 0; 0, 2]] [18, 9]~ [-85124952/2401, 33204681/2401]~ [249/2401, 1644/2401]~ [7, 14]~ 14 [1, 0] [2, [0, -4]~] [3, [8/125, 0]~] [3, [2/5, 3; [0, 1]~, 3]] [4, [0, 1]~] 4632 [9, 4]~ [15, 4]~ [-3, 4]~ [-15, 4]~ -2 2 0 1 [75 22 41] [ 0 1 0] [ 0 0 1] 1 0 1 0 1 [2] 1 [10 0 0] [ 0 5 0] [ 0 0 5] [] *** nfinit: Warning: nonmonic polynomial. Result of the form [nf,c]. [[2, [0, 1]~, 2, 1, [0, -2; 1, 0]]] 1 1 [1/9, 1/18, 0, 0, 0, 0]~ 1 1 [1 0 0 5/9] [0 1 5/9 0] [0 0 1/9 0] [0 0 0 1/9] [1, -30]~ [1, 30]~ [] [784, 784, 4, 4] [49, 49, 0, 0]~ [0, 0]~ *** at top-level: ideallist(x,-300) *** ^----------------- *** ideallist: incorrect type in checknf [please apply nfinit()] (t_POL). *** at top-level: idealaddtoone(Q,2,[;]) *** ^---------------------- *** idealaddtoone: elements not coprime in idealaddtoone: Mat(2) [;] *** at top-level: idealaddtoone(Q,[;],[;]) *** ^------------------------ *** idealaddtoone: elements not coprime in idealaddtoone: [;] [;] *** at top-level: idealaddtoone(Q,[1,[;],Mat(1/2)]) *** ^--------------------------------- *** idealaddtoone: incorrect type in idealaddmultoone [integer matrix] (t_MAT). *** at top-level: idealhnf(Q,[x,x,x,x,x]) *** ^----------------------- *** idealhnf: incorrect type in idealhnf [fake prime ideal] (t_VEC). *** at top-level: idealval(Q,2,[x,x,x,x,x]) *** ^------------------------- *** idealval: incorrect type in checkprid (t_VEC). *** at top-level: idealval(Q,Mat(2),[x,x,x,x,x]) *** ^------------------------------ *** idealval: incorrect type in checkprid (t_VEC). *** at top-level: ideallog(Q,2,zQ) *** ^---------------- *** ideallog: elements not coprime in zlog_prk1: 2 Mat(4) *** at top-level: ideallog(,0,zerror) *** ^------------------- *** ideallog: elements not coprime in znconreylog: 0 6 *** at top-level: ideallog(,2,zerror) *** ^------------------- *** ideallog: elements not coprime in znconreylog: 2 6 *** at top-level: ideallog(,3,zerror) *** ^------------------- *** ideallog: elements not coprime in znconreylog: 3 6 *** at top-level: ideallog(Q,3,zerror) *** ^-------------------- *** ideallog: incorrect type in checkbid (t_VEC). *** at top-level: ideallog(,3,zQ) *** ^--------------- *** ideallog: incorrect type in znconreylog (t_VEC). *** at top-level: idealmul(Kerror,[2,1;0,1],[2,1;0,1]) *** ^------------------------------------ *** idealmul: inconsistent dimensions in idealmul. *** at top-level: idealmul(Kerror,matid(4),matid(4)) *** ^---------------------------------- *** idealmul: inconsistent dimensions in idealmul. *** at top-level: idealred(nf,[2,Mat(1)]) *** ^----------------------- *** idealred: incorrect type in idealtyp [extended ideal] (t_VEC). *** at top-level: K=nfinit(y^3+8*y^2-128*y-512) *** ^------------------- *** _^s: forbidden multiplication t_COL (3 elts) * t_COL (3 elts). *** at top-level: idealstar(K,[4,Vecsmall([1,1,1])]) *** ^---------------------------------- *** idealstar: incorrect type in Idealstar [incorrect archimedean component] (t_VECSMALL). *** at top-level: idealstar(K,[4,Vecsmall([1,4,2])]) *** ^---------------------------------- *** idealstar: incorrect type in Idealstar [incorrect archimedean component] (t_VECSMALL). *** at top-level: idealstar(K,[4,Vecsmall([-1,2,3])]) *** ^----------------------------------- *** idealstar: incorrect type in Idealstar [incorrect archimedean component] (t_VECSMALL). *** at top-level: idealstar(K,[4,Vecsmall([1,1])]) *** ^-------------------------------- *** idealstar: incorrect type in Idealstar [incorrect archimedean component] (t_VECSMALL). *** at top-level: idealred(K,[4,3,2,1;0,3,2,1;0,0,2,1;0,0,0,1]) *** ^--------------------------------------------- *** idealred: inconsistent dimensions in idealred. Total time spent: 112 pari-2.17.2/src/test/32/eval0000644000175000017500000000005014567450071014034 0ustar billbillVecsmall([1, 2, 3]) Total time spent: 0 pari-2.17.2/src/test/32/self0000644000175000017500000000003014567450071014034 0ustar billbill120 Total time spent: 0 pari-2.17.2/src/test/32/kernel0000644000175000017500000000261214567450071014373 0ustar billbillINT: 187654321 conv:signe: 1, 0b2f60b1 +:signe: 1, 0a72ff63 -:signe: 1, 0bebc1ff *:signe: -1, 00083b0b 5e0e86ee /:signe: -1, 0000000f rem:signe: 1, 0025ad1f pow: signe: 1, 007d1b13 db833a61 signe: 1, 00003d23 74418fff 02bee98c c29618c1 signe: 1, 0e99ea50 3d586253 467c3cea a7f1a742 85bba548 639e3a9d 8890c181 signe: 1, 00d5322a b115c7b2 9cf0c571 1679c253 8cea7ca0 1cbe7596 78ae7d09 c969dc26 cd42e2ad 51204d31 635bced8 66d36dbb 0351ebad 5363c301 signe: 1, 0000b18c 84df6289 66df9491 766a39a4 0685a8a3 cfc68c74 4d9dcb91 02634462 b398839e 1a6892ef 5efe0281 bcae4afb eb64fcab f930fa7a 00f01335 2a5dc7c3 4295b5c3 b031c96e a5c19079 8e647dac 09e2091e 67abbc58 c118d1b7 76f5e31c e97a9180 140e859c 64a53cad 0d508601 invmod:signe: 1, 000089fe 3c4ba859 b9472dac d0585e64 b5311881 edf8024b aaf6ce9e 98d94a2d b253c748 bc185be1 6de1e5f8 831bbecd a3d629dc 0fc9440e b0ab325d 53dd21c5 9fb7fc20 cc22d98c e8fe6eca 928c7f4f a3861061 a7ab0bdc 71deda26 17a28387 77487563 9f0f88ac 424ca4d5 3dcae2a5 REAL: 187654321.000000 conv1:signe: 1, expo: 27, b2f60b10 00000000 conv2:signe: 1, expo: 27, b2f60b10 00000000 +:signe: 1, expo: 27, a72ff630 00000000 -:signe: 1, expo: 27, bebc1ff0 00000000 *:signe: -1, expo: 51, 83b0b5e0 e86ee000 /:signe: -1, expo: 3, f3333482 0be1df0a gcc bug?:signe: 1, expo: 0, c0000000 00000000 pari-2.17.2/src/test/32/rootsof10000644000175000017500000000202314567450071014663 0ustar billbill[1]~ [1, -1]~ [1, -1/2 + 0.86602540378443864676372317075293618347*I, -1/2 - 0.866025403784 43864676372317075293618347*I]~ [1, I, -1, -I]~ [1, 0.30901699437494742410229341718281905886 + 0.951056516295153572116439333 37938214341*I, -0.80901699437494742410229341718281905886 + 0.587785252292473 12916870595463907276860*I, -0.80901699437494742410229341718281905886 - 0.587 78525229247312916870595463907276860*I, 0.30901699437494742410229341718281905 886 - 0.95105651629515357211643933337938214341*I]~ [1, 1/2 + 0.86602540378443864676372317075293618347*I, -0.5000000000000000000 0000000000000000000 + 0.86602540378443864676372317075293618347*I, -1, -0.500 00000000000000000000000000000000000 - 0.866025403784438646763723170752936183 47*I, 1/2 - 0.86602540378443864676372317075293618347*I]~ *** at top-level: rootsof1(0) *** ^----------- *** rootsof1: domain error in rootsof1: N <= 0 *** at top-level: rootsof1(-1) *** ^------------ *** rootsof1: domain error in rootsof1: N <= 0 Total time spent: 0 pari-2.17.2/src/test/32/log0000644000175000017500000000024214567450071013671 0ustar billbill9.9999999999999999999999999999950000000 E-31 -5.7721566490153286060651209008157996401 E-31 69.077552789821370520539743640530349012 30 + O(33) Total time spent: 0 pari-2.17.2/src/test/32/program0000644000175000017500000000447614567450071014574 0ustar billbill1 echo = 1 ? alias(ln,log) ? ln(2) 0.69314718055994530941723212145817656807 ? for(x=1,5,print(x!)) 1 2 6 24 120 ? fordiv(10,x,print(x)) 1 2 5 10 ? forprime(p=1,30,print(p)) 2 3 5 7 11 13 17 19 23 29 ? forstep(x=0,2.9,Pi/12,print(sin(x))) 0.E-38 0.25881904510252076234889883762404832835 0.50000000000000000000000000000000000000 0.70710678118654752440084436210484903928 0.86602540378443864676372317075293618347 0.96592582628906828674974319972889736763 1.0000000000000000000000000000000000000 0.96592582628906828674974319972889736764 0.86602540378443864676372317075293618348 0.70710678118654752440084436210484903931 0.50000000000000000000000000000000000003 0.25881904510252076234889883762404832839 ? forvec(x=[[1,3],[-2,2]],print1([x[1],x[2]]," "));print(" "); [1, -2] [1, -1] [1, 0] [1, 1] [1, 2] [2, -2] [2, -1] [2, 0] [2, 1] [2, 2] [3 , -2] [3, -1] [3, 0] [3, 1] [3, 2] ? if(3<2,print("bof"),print("ok")); ok ? kill(y);print(x+y); x + y ? f(u)=u+1; ? print(f(5));kill(f); 6 ? f=12 12 ? g(u)=if(u,,return(17));u+2 (u)->if(u,,return(17));u+2 ? g(2) 4 ? g(0) 17 ? n=33;until(n==1,print1(n," ");if(n%2,n=3*n+1,n=n/2));print(1) 33 100 50 25 76 38 19 58 29 88 44 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1 ? m=5;while(m<20,print1(m," ");m=m+1);print() 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ? default(seriesprecision,12) ? print((x-12*y)/(y+13*x)); (x - 12*y)/(13*x + y) ? print([1,2;3,4]) [1, 2; 3, 4] ? print1(x+y);print(x+y); x + yx + y ? print((x-12*y)/(y+13*x)); (x - 12*y)/(13*x + y) ? print([1,2;3,4]) [1, 2; 3, 4] ? print1(x+y);print1(" equals ");print(x+y); x + y equals x + y ? print1("give a value for s? ");s=input();print(1/(s^2+1)) give a value for s? printtex((x+y)^3/(x-y)^2) \frac{x^3 + 3\*y\*x^2 + 3\*y^2\*x + y^3}{x^2 - 2\*y\*x + y^2} 1 ? for(i=1,100,for(j=1,25,if(i+j==32,break(2)));print(i)) 1 2 3 4 5 6 ? u=v=p=q=1;for(k=1,400,w=u+v;u=v;v=w;p*=w;q=lcm(q,w);if(k%50==0,print(k" "log(p)/log(q)))); 50 1.5612291269030992792061717254933840846 100 1.6013353755908753487111410311704818784 150 1.6069155486736591275233947740278385687 200 1.6186599989915284815081751756012014738 250 1.6262847062047467650860809884971000430 300 1.6278227768451030011920245320536334380 350 1.6321059051729866681896522731053701088 400 1.6324242855329314481714056192369470068 ? if(getheap()!=HEAP,getheap()) ? print("Total time spent: ",gettime); Total time spent: 5 pari-2.17.2/src/test/32/quadclassunit0000644000175000017500000005010214760123736015770 0ustar billbill *** Warning: new stack size = 72000000 (68.665 Mbytes). 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] Mod(11196455778304025936, 18446744073709551557) + Mod(15094424487818408561, 18446744073709551557)*w 2 10 1 3 2 1 -1 5 150 150 150 3221225472 536870912 1 1331383621463592367935072749832754049872752443524941868072753528488198423051 6155252521913978327933871319513567734674995952944882291564414920804355520376 6373968592797227579450144176715285425996954026427896749013760313608815476449 884723502419086935416492200525714402341926955345567 + 9766464452469103545038 5949078519979040360731478061598807512211227050101784793847267130640656779998 1754212772705522344965369859908461727998749102647409039187621696111368677549 4546750271919526317071168340655247576306504373948793374169966111618434281600 82286198999797634392968896*w 9261428415283884326746252276541219607108629637467584393177958051111254872948 9159179926525020547165408595208179684835150845731612841384211851198945833260 8584507367536871317754526684041823204119660823148219324156306343990849620623 9877147060262609797591790262004668397991633725097548158989324156827551833611 6692839083976603087074771719894835584930658687493874773272836639421751859881 2806297525719512860677101818225717395718897147214424759200437655066982237889 0176821989871564490528064062070907004131221254914307642817960387293638773387 6577563727046163968968036185357346521391535271013163839676337299617853183047 2012231245207909601051294928659216456385413657165576935481272752080678088542 3833625063186774385855217338392082970393729169336483564418964403530430670154 056827175040356316795496623259533302243682787468130703 + 2593079808366927198 9895570950558697583407613969978293559775075854443753684195909773473999096274 3252512846177716274338368250686093896428392970303739610297502959940799606950 8147250915418983718622960677764359871447990308468025018351444819049392778737 0770103488069280098950330186870296834602840563517955327215058648389214923701 4353960957484176791933898185191336134982998598313843432522761107515175900951 7147970547118614307668508008238226235283789603357060030411040155611831165023 5389235928138655411423517711476446057167108254546678242927692674800127386237 8555884775778295028832927653982493531225209752789915194782890516216978162530 3820775354084940573553039154514237320763162099337220144861402643368321727653 9701868988119450988413480529277700937005021753523408038133236640203107234470 191063531086727416202250690087904*w 1 ? setrand(1);quadclassunit(572).no 2 ? setrand(11);quadclassunit(-8419588).cyc [176, 2] ? setrand(2);quadclassunit(-1459008).cyc [16, 4, 2, 2] ? setrand(7);quadclassunit(-3799812).cyc [54, 2, 2, 2] ? setrand(1);quadclassunit(-13163208).cyc [156, 2, 2] ? setrand(38);quadclassunit(-29920).cyc [4, 2, 2, 2] ? quadclassunit(-13163208,,[0.1]).cyc [156, 2, 2] ? setrand(1);quadclassunit((2^70+25)).cyc [17] ? setrand(1);quadclassunit(8*3*5*7).cyc [2, 2] ? setrand(1);quadclassunit(-612556842419).cyc [192199] ? setrand(2);quadclassunit(-699,,[6,6]).cyc [10] ? quadunit(1.) *** at top-level: quadunit(1.) *** ^------------ *** quadunit: incorrect type in quadunit (t_REAL). ? quadunitindex(1.,2) *** at top-level: quadunitindex(1.,2) *** ^------------------- *** quadunitindex: incorrect type in quadunitindex (t_REAL). ? quadunitindex(5,1.) *** at top-level: quadunitindex(5,1.) *** ^------------------- *** quadunitindex: incorrect type in quadunitindex (t_REAL). ? quadunitnorm(1.) *** at top-level: quadunitnorm(1.) *** ^---------------- *** quadunitnorm: incorrect type in quadunitnorm (t_REAL). ? print("Total time spent: ",gettime); Total time spent: 5363 pari-2.17.2/src/test/32/set0000644000175000017500000000102714567450071013705 0ustar billbill[1, 2, 3] [] [1, 2, 3] List([1, 2, 3]) [1] [-2, 1, 3, 5, 7, x, "1"] [-5, 2, 5, 7, "1"] [5, 7, "1"] 0 1 [-2, 1, 3, x] 3 7 0 3 *** at top-level: setsearch(1,3) *** ^-------------- *** setsearch: incorrect type in setsearch (t_INT). [-5, -2, 1, 2, 3, 5, 7, x, "1"] [-5, -2, 1, 2, 3, x] [2] [3, 4, 5, 6, 7] [2, 3, 4, 5, 6] *** at top-level: setbinop(x->x,X) *** ^---------------- *** setbinop: incorrect type in setbinop [function needs exactly 2 arguments] (t_CLOSURE). Total time spent: 0 pari-2.17.2/src/test/32/charpoly0000644000175000017500000002335614760123736014744 0ustar billbill(-y + 1)*x + (y^2 - 2*y - 1) (-y + 1)*x + (y^2 - 2*y - 1) (-y + 1)*x + (y^2 - 2*y - 1) (-y + 1)*x + (y^2 - 2*y - 1) x^4 - 16*x^2 x^4 - 16*x^2 x^2 - 4*x [1 14/39] [0 1] [1 0.35897435897435897435897435897435897438] [0 1] [[5/3, 21/10]~, [1, 14/39; 0, 1]] [0.025784835985469857086599615759958975735, 0.199915025473745745510054037511 86752336, 0.45186281535484114060969116665631585174, 429.32243732318594325679 365518007185765]~ -113 -x^2 + (-y - w)*x + (-y + (w^2 - w)) x - 1 x - 1.0000000000000000000000000000000000000 x + Mod(2, 3) x - 1/2 x + (2 + O(3)) x^2 + 1 x^2 - x - 1 Mod(1, 3)*x^2 + Mod(1, 3)*x + Mod(1, 3) Mod(1, 18446744073709551629)*x^2 + Mod(18446744073709551627, 184467440737095 51629)*x + Mod(1, 18446744073709551629) 1 x^6 - x^5 - 3*x^4 - 3*x^3 - 3*x^2 - x + 1 x^4 - 4*x^3 + 6*x^2 - 4*x + 1 x^4 - 4*x^3 + 6*x^2 - 4*x + 1 x^4 - 73786976294838206516*x^3 + 2041694201525630783657939720089299321846*x^ 2 - 25108406941546723108427206932497066002105857518694949724756*x + 11579208 9237316195749980275248795307917777354730270819790751905975615430356881 Mod(1, 3)*x^4 + Mod(1, 3)*x^3 + Mod(1, 3)*x^2 + Mod(1, 3)*x Mod(1, 18446744073709551629)*x^4 + Mod(18446744073709551600, 184467440737095 51629)*x^3 + Mod(46, 18446744073709551629)*x^2 + Mod(16, 1844674407370955162 9)*x [1 0] [0 1] [;] [1] [0 0 0] [0 0 0] [0 0 0] [Mod(0, 2) Mod(0, 2) Mod(0, 2)] [Mod(0, 2) Mod(0, 2) Mod(0, 2)] [Mod(0, 2) Mod(0, 2) Mod(0, 2)] *** at top-level: charpoly(x*matid(3)) *** ^-------------------- *** charpoly: incorrect priority in charpoly: variable x = x 1 1 1 1 x^4 - 4*x^3 + 6*x^2 - 4*x + 2 x^2 x^2 - 2*x + 1 x^2 - 2*y*x + y^2 x^24 - 24*x^23 + 276*x^22 - 2024*x^21 + 10626*x^20 - 42504*x^19 + 134596*x^1 8 - 346104*x^17 + 735471*x^16 - 1307504*x^15 + 1961256*x^14 - 2496144*x^13 + 2704156*x^12 - 2496144*x^11 + 1961256*x^10 - 1307504*x^9 + 735471*x^8 - 346 104*x^7 + 134596*x^6 - 42504*x^5 + 10626*x^4 - 2024*x^3 + 276*x^2 - 24*x + 1 x^2 - 2*x + 1 x^2 + Mod(1, 2)/(Mod(1, 2)*t^2)*x + ((Mod(1, 2)*t + Mod(1, 2))/(Mod(1, 2)*t^ 3)) 1 1 1 1 x^4 - 4*x^3 + 6*x^2 - 4*x + 2 x^2 x - 1 x - y x - 1 x - 1 Mod(1, 2)*t^3*x^2 + Mod(1, 2)*t*x + (Mod(1, 2)*t + Mod(1, 2)) [;] [[]~, [;]] [1] [[1]~, Mat(1)] [0.70710678118654752440084436210484903928 0.E-38 0.E-38 0.E-38 0.70710678118 654752440084436210484903929 0.E-38 0.E-38] [0.70710678118654752440084436210484903929 0.E-38 0.E-38 0.E-38 -0.7071067811 8654752440084436210484903928 0.E-38 0.E-38] [0.E-38 0.23999696351543677575648770150590372098 -0.283622172709065437120208 22398582804906 0.67967633521490150959346301374385356331 0.E-38 0.61582013154 270957217214628524015061291 0.14410262172049431191936511310596050606] [0.E-38 0.57468823740117602493745785679291224747 0.4865110738636043847765149 5190903150502 -0.18177019777953707317421657491323056668 0.E-38 0.05324914872 2421216995940588902203986718 0.63020990801504974979984540216856201701] [0.E-38 -0.24043700257187013561719500269086834184 0.283801439462237029600622 82614614643943 0.67944594395243594261215492515632318777 0.E-38 -0.5829103477 6025522011810821578892183638 0.24538852147975121227580790648499184101] [0.E-38 0.74377206690669372496948296733199987942 -0.158340728801955467428818 50584341540904 0.14741548796449545166318703395156923765 0.E-38 -0.4135075560 3228008533391235202071506688 -0.47855146129147985876298725459512205052] [0.E-38 -0.033586419572483189091808052063575280391 0.75976996171045044547062 225467793619648 0.14704270707111516638694570644189499592 0.E-38 0.3273486235 2740451628393369366728230362 -0.54114958992381541523203116716439231357] [[0.E-38, -3.1356028349282496289992466889123954235 E-39, -6.6005164507495315 900700991108611527795 E-40, 1.1073849293427036872827738448743471865 E-39, 2. 0000000000000000000000000000000000000, 2.50000000000000000000000000000000000 00, 2.5000000000000000000000000000000000000]~, [0.70710678118654752440084436 210484903928, 0.E-38, 0.E-38, 0.E-38, 0.707106781186547524400844362104849039 29, 0.E-38, 0.E-38; 0.70710678118654752440084436210484903929, 0.E-38, 0.E-38 , 0.E-38, -0.70710678118654752440084436210484903928, 0.E-38, 0.E-38; 0.E-38, 0.23999696351543677575648770150590372098, -0.283622172709065437120208223985 82804906, 0.67967633521490150959346301374385356331, 0.E-38, 0.61582013154270 957217214628524015061291, 0.14410262172049431191936511310596050606; 0.E-38, 0.57468823740117602493745785679291224747, 0.48651107386360438477651495190903 150502, -0.18177019777953707317421657491323056668, 0.E-38, 0.053249148722421 216995940588902203986718, 0.63020990801504974979984540216856201701; 0.E-38, -0.24043700257187013561719500269086834184, 0.2838014394622370296006228261461 4643943, 0.67944594395243594261215492515632318777, 0.E-38, -0.58291034776025 522011810821578892183638, 0.24538852147975121227580790648499184101; 0.E-38, 0.74377206690669372496948296733199987942, -0.1583407288019554674288185058434 1540904, 0.14741548796449545166318703395156923765, 0.E-38, -0.41350755603228 008533391235202071506688, -0.47855146129147985876298725459512205052; 0.E-38, -0.033586419572483189091808052063575280391, 0.75976996171045044547062225467 793619648, 0.14704270707111516638694570644189499592, 0.E-38, 0.3273486235274 0451628393369366728230362, -0.54114958992381541523203116716439231357]] [0.094247377762193110823572405894446819110 0.1007319779597465661840061702737 0826505 -0.13796838008981869099272360326078603959 0.194993074636186339533837 20407359667016 -0.27522271898194095574315490823181620856 0.38617091980744374 260336948522072070636 -0.52878630957763874247700837996424775674 0.6476283207 1729815428349355195312315376] [-0.10882178928969198042785567455777466243 -0.116259829019504336645161834954 87266815 0.15900102463277054464665632731646012970 -0.22339955664906057708388 046975432400941 0.30786857735194148013221023380783069167 -0.3901727978820578 0056615333825748428218 0.30529491817843851256955368319244250026 0.7478167706 0191475552514472942688281961] [0.14864767241019140314390370955655238429 0.15853826566217279199899358765867 120249 -0.21553827130184423833830446357901146946 0.2956515293984901502336085 4053093504941 -0.36732309203066635458019288577262250711 0.250220063544559156 85723782746140625324 0.77463706559500199287630149469514751653 0.145958888196 50902244968277200547896340] [-0.20836942434367765354495379928158186619 -0.220722470192972771838213290584 56186766 0.29289931779648172913702226291407895325 -0.36203541623658169056969 850464786050190 0.23760016126641020610963463018920404239 0.77938866060189419 518245923528690081774 0.16449913947567352290562539148928205511 0.00660555663 67593717394750689706182518100] [0.29311269821551284468605156340666800889 0.30199159016749032837546806561477 677755 -0.36079394521481966306467252709292749449 0.2345102225993577866319464 9222217670106 0.78047544541528484932007064793946338720 0.1688765514483696645 7325284882609782529 0.0075824989973347732698502576653284742318 7.34120692436 17626911895906327535194928 E-5] [-0.40874691656100117214073288701980681899 -0.373847777666460341231624084522 51032351 0.23379620286291741370344659221846917553 0.780741106732999003151624 99600342745502 0.16995676864482051628193580745139458477 0.007819638546366871 2356314062791686639906 8.4644610562694015620551693596200336173 E-5 2.0307160 171909465650112069515723482437 E-7] [0.54669721570318168483733648069363453752 0.24968260684711249931702042700872 169599 0.78085966032955569706540596275120518417 0.17022591404290783653133162 661579054145 0.0078785532858503322198934102971566544785 8.738852106526657370 2802308261684708781 E-5 2.3440098646058821590480529354923735286 E-7 1.402792 1134460678902341070026165828238 E-10] [-0.60157656298724075146212329751181192466 0.7805007653330039911647689955662 1062820 0.16988790125523000704561514362887737473 0.0078922385706886901729850 888296874730012 8.8070604359810882602528939286099732678 E-5 2.42066018050937 77923217045368544976644 E-7 1.6196564620116883989531147963955877852 E-10 2.4 219107376156469122768726740544294465 E-14] x^30 - 0.76516931571532443949977397460018697741*x^29 - 0.1073023603581493760 8734526925455561214*x^28 + 0.019457062241521787634276969284992617893*x^27 - 0.31275367314185866456349716808080489485*x^26 + 0.22780195826554292132541327 312088864285*x^25 - 0.016193346168520792074795805806845803517*x^24 + 0.00355 25086801107690870149444990035091058*x^23 - 0.0636454763432968902234398339866 82291752*x^22 + 0.040324627302586751431502318425872942402*x^21 - 0.027342646 226471509522212232582336974893*x^20 + 0.026850469736486930978355865504127910 235*x^19 - 0.0026254132222286115118328660227464357649*x^18 - 0.0002275391252 8284814022789257758203208913*x^17 + 0.00016821803823439175193590331665685235 694*x^16 - 0.0020112520694333278505699057453120175166*x^15 + 0.0006447099710 8889332311642873461933780548*x^14 - 0.00037581999335954534509286659829661314 659*x^13 + 0.00019215028415136985280165854606938798620*x^12 + 4.676879321222 3338067823872655470453602 E-5*x^11 - 1.8671738292175717801594568814404467612 E-5*x^10 + 6.8751870320490202943891939671979515391 E-6*x^9 - 2.789936446132 5364867088576623136852097 E-6*x^8 - 2.4568247268367038251402226383778614333 E-6*x^7 - 9.1606728883384639895109722489861445877 E-8*x^6 + 7.01786353698582 98211825773057452554631 E-7*x^5 - 2.4854865076454988606280719185511336021 E- 7*x^4 + 8.8955438505235556907853087847010591359 E-8*x^3 + 9.1041350759191250 869609873161898997733 E-9*x^2 - 1.9360051774746636290650582547013488672 E-8* x + 3.5251905160916583918731318966948840204 E-9 *** at top-level: charpoly(Mod('b,'b^2+Mod('a,'a^2+1)),'newvar) *** ^--------------------------------------------- *** charpoly: incorrect priority in RgXQ_charpoly: variable newvar < a *** at top-level: minpoly(Mod(y,x),'y) *** ^-------------------- *** minpoly: incorrect priority in minpoly: variable x < y Total time spent: 46 pari-2.17.2/src/test/32/polygonal0000644000175000017500000000000014557721031015100 0ustar billbillpari-2.17.2/src/test/32/forperm0000644000175000017500000001067314567450071014573 0ustar billbillVecsmall([1]) Vecsmall([1, 2, 3, 4]) Vecsmall([1, 2, 4, 3]) Vecsmall([1, 3, 2, 4]) Vecsmall([1, 3, 4, 2]) Vecsmall([1, 4, 2, 3]) Vecsmall([1, 4, 3, 2]) Vecsmall([2, 1, 3, 4]) Vecsmall([2, 1, 4, 3]) Vecsmall([2, 3, 1, 4]) Vecsmall([2, 3, 4, 1]) Vecsmall([2, 4, 1, 3]) Vecsmall([2, 4, 3, 1]) Vecsmall([3, 1, 2, 4]) Vecsmall([3, 1, 4, 2]) Vecsmall([3, 2, 1, 4]) Vecsmall([3, 2, 4, 1]) Vecsmall([3, 4, 1, 2]) Vecsmall([3, 4, 2, 1]) Vecsmall([4, 1, 2, 3]) Vecsmall([4, 1, 3, 2]) Vecsmall([4, 2, 1, 3]) Vecsmall([4, 2, 3, 1]) Vecsmall([4, 3, 1, 2]) Vecsmall([4, 3, 2, 1]) Vecsmall([1, 1, 1, 3]) Vecsmall([1, 1, 3, 1]) Vecsmall([1, 3, 1, 1]) Vecsmall([3, 1, 1, 1]) Vecsmall([1, 2, 1, 3, 1, 4]) Vecsmall([1, 2, 1, 3, 4, 1]) Vecsmall([1, 2, 1, 4, 1, 3]) Vecsmall([1, 2, 1, 4, 3, 1]) Vecsmall([1, 2, 3, 1, 1, 4]) Vecsmall([1, 2, 3, 1, 4, 1]) Vecsmall([1, 2, 3, 4, 1, 1]) Vecsmall([1, 2, 4, 1, 1, 3]) Vecsmall([1, 2, 4, 1, 3, 1]) Vecsmall([1, 2, 4, 3, 1, 1]) Vecsmall([1, 3, 1, 1, 2, 4]) Vecsmall([1, 3, 1, 1, 4, 2]) Vecsmall([1, 3, 1, 2, 1, 4]) Vecsmall([1, 3, 1, 2, 4, 1]) Vecsmall([1, 3, 1, 4, 1, 2]) Vecsmall([1, 3, 1, 4, 2, 1]) Vecsmall([1, 3, 2, 1, 1, 4]) Vecsmall([1, 3, 2, 1, 4, 1]) Vecsmall([1, 3, 2, 4, 1, 1]) Vecsmall([1, 3, 4, 1, 1, 2]) Vecsmall([1, 3, 4, 1, 2, 1]) Vecsmall([1, 3, 4, 2, 1, 1]) Vecsmall([1, 4, 1, 1, 2, 3]) Vecsmall([1, 4, 1, 1, 3, 2]) Vecsmall([1, 4, 1, 2, 1, 3]) Vecsmall([1, 4, 1, 2, 3, 1]) Vecsmall([1, 4, 1, 3, 1, 2]) Vecsmall([1, 4, 1, 3, 2, 1]) Vecsmall([1, 4, 2, 1, 1, 3]) Vecsmall([1, 4, 2, 1, 3, 1]) Vecsmall([1, 4, 2, 3, 1, 1]) Vecsmall([1, 4, 3, 1, 1, 2]) Vecsmall([1, 4, 3, 1, 2, 1]) Vecsmall([1, 4, 3, 2, 1, 1]) Vecsmall([2, 1, 1, 1, 3, 4]) Vecsmall([2, 1, 1, 1, 4, 3]) Vecsmall([2, 1, 1, 3, 1, 4]) Vecsmall([2, 1, 1, 3, 4, 1]) Vecsmall([2, 1, 1, 4, 1, 3]) Vecsmall([2, 1, 1, 4, 3, 1]) Vecsmall([2, 1, 3, 1, 1, 4]) Vecsmall([2, 1, 3, 1, 4, 1]) Vecsmall([2, 1, 3, 4, 1, 1]) Vecsmall([2, 1, 4, 1, 1, 3]) Vecsmall([2, 1, 4, 1, 3, 1]) Vecsmall([2, 1, 4, 3, 1, 1]) Vecsmall([2, 3, 1, 1, 1, 4]) Vecsmall([2, 3, 1, 1, 4, 1]) Vecsmall([2, 3, 1, 4, 1, 1]) Vecsmall([2, 3, 4, 1, 1, 1]) Vecsmall([2, 4, 1, 1, 1, 3]) Vecsmall([2, 4, 1, 1, 3, 1]) Vecsmall([2, 4, 1, 3, 1, 1]) Vecsmall([2, 4, 3, 1, 1, 1]) Vecsmall([3, 1, 1, 1, 2, 4]) Vecsmall([3, 1, 1, 1, 4, 2]) Vecsmall([3, 1, 1, 2, 1, 4]) Vecsmall([3, 1, 1, 2, 4, 1]) Vecsmall([3, 1, 1, 4, 1, 2]) Vecsmall([3, 1, 1, 4, 2, 1]) Vecsmall([3, 1, 2, 1, 1, 4]) Vecsmall([3, 1, 2, 1, 4, 1]) Vecsmall([3, 1, 2, 4, 1, 1]) Vecsmall([3, 1, 4, 1, 1, 2]) Vecsmall([3, 1, 4, 1, 2, 1]) Vecsmall([3, 1, 4, 2, 1, 1]) Vecsmall([3, 2, 1, 1, 1, 4]) Vecsmall([3, 2, 1, 1, 4, 1]) Vecsmall([3, 2, 1, 4, 1, 1]) Vecsmall([3, 2, 4, 1, 1, 1]) Vecsmall([3, 4, 1, 1, 1, 2]) Vecsmall([3, 4, 1, 1, 2, 1]) Vecsmall([3, 4, 1, 2, 1, 1]) Vecsmall([3, 4, 2, 1, 1, 1]) Vecsmall([4, 1, 1, 1, 2, 3]) Vecsmall([4, 1, 1, 1, 3, 2]) Vecsmall([4, 1, 1, 2, 1, 3]) Vecsmall([4, 1, 1, 2, 3, 1]) Vecsmall([4, 1, 1, 3, 1, 2]) Vecsmall([4, 1, 1, 3, 2, 1]) Vecsmall([4, 1, 2, 1, 1, 3]) Vecsmall([4, 1, 2, 1, 3, 1]) Vecsmall([4, 1, 2, 3, 1, 1]) Vecsmall([4, 1, 3, 1, 1, 2]) Vecsmall([4, 1, 3, 1, 2, 1]) Vecsmall([4, 1, 3, 2, 1, 1]) Vecsmall([4, 2, 1, 1, 1, 3]) Vecsmall([4, 2, 1, 1, 3, 1]) Vecsmall([4, 2, 1, 3, 1, 1]) Vecsmall([4, 2, 3, 1, 1, 1]) Vecsmall([4, 3, 1, 1, 1, 2]) Vecsmall([4, 3, 1, 1, 2, 1]) Vecsmall([4, 3, 1, 2, 1, 1]) Vecsmall([4, 3, 2, 1, 1, 1]) Vecsmall([1, 2, 3, 2, 3]) Vecsmall([1, 2, 3, 3, 2]) Vecsmall([1, 3, 2, 2, 3]) Vecsmall([1, 3, 2, 3, 2]) Vecsmall([1, 3, 3, 2, 2]) Vecsmall([2, 1, 2, 3, 3]) Vecsmall([2, 1, 3, 2, 3]) Vecsmall([2, 1, 3, 3, 2]) Vecsmall([2, 2, 1, 3, 3]) Vecsmall([2, 2, 3, 1, 3]) Vecsmall([2, 2, 3, 3, 1]) Vecsmall([2, 3, 1, 2, 3]) Vecsmall([2, 3, 1, 3, 2]) Vecsmall([2, 3, 2, 1, 3]) Vecsmall([2, 3, 2, 3, 1]) Vecsmall([2, 3, 3, 1, 2]) Vecsmall([2, 3, 3, 2, 1]) Vecsmall([3, 1, 2, 2, 3]) Vecsmall([3, 1, 2, 3, 2]) Vecsmall([3, 1, 3, 2, 2]) Vecsmall([3, 2, 1, 2, 3]) Vecsmall([3, 2, 1, 3, 2]) Vecsmall([3, 2, 2, 1, 3]) Vecsmall([3, 2, 2, 3, 1]) Vecsmall([3, 2, 3, 1, 2]) Vecsmall([3, 2, 3, 2, 1]) Vecsmall([3, 3, 1, 2, 2]) Vecsmall([3, 3, 2, 1, 2]) Vecsmall([3, 3, 2, 2, 1]) Vecsmall([]) Vecsmall([]) Vecsmall([]) Vecsmall([1]) *** variable name expected: forperm(p,3,) *** ^--- *** at top-level: forperm(1.0,q,) *** ^--------------- *** incorrect type in forperm (t_REAL). *** at top-level: forperm(-1,q,) *** ^-------------- *** domain error in forperm: a < 0 Total time spent: 1 pari-2.17.2/src/test/32/elltors0000644000175000017500000001053614567450071014603 0ustar billbill[1, [], []] [2, [2], [[15, -8]]] [3, [3], [[5, 9]]] [4, [4], [[5, -2]]] [5, [5], [[5, 5]]] [6, [6], [[9, 23]]] [7, [7], [[-1, 2]]] [8, [8], [[2, 6]]] [9, [9], [[-3, 7]]] [10, [10], [[0, 9]]] [12, [12], [[-9, 49]]] [4, [2, 2], [[-29/4, 25/8], [-7, 3]]] [8, [4, 2], [[-2, 3], [-1, 0]]] [12, [6, 2], [[1, 2], [3, -2]]] [16, [8, 2], [[4, 58], [-36, 18]]] [16, [8, 2], [[117433600, 6734213027200], [352179456, -176089728]]] [4, [2, 2], [[-1377493124511464657, 0], [-691668349248679055, 0]]] [16, [8, 2], [[Mod(0, t^2 - 5), Mod(0, t^2 - 5)], [Mod(3/5*t + 17/15, t^2 - 5), Mod(209/225*t + 97/45, t^2 - 5)]]] 8 2 [1, [], []] [1, [], []] [25, [25], [[Mod(-t^7 - t^6 - t^5 - t^4 + 1, t^10 + t^9 + t^8 + t^7 + t^6 + t^5 + t^4 + t^3 + t^2 + t + 1), Mod(-t^9 - 2*t^8 - 2*t^7 - 3*t^6 - 3*t^5 - 2 *t^4 - 2*t^3 - t^2 - 1, t^10 + t^9 + t^8 + t^7 + t^6 + t^5 + t^4 + t^3 + t^2 + t + 1)]]] [11, [11], [[Mod(-78848, y^2 + 7), Mod(-5992448*y - 15454208, y^2 + 7)]]] [15, [15], [[Mod(0, y^2 + 7), Mod(-26*y + 14, y^2 + 7)]]] [20, [10, 2], [[831474369/262144, 519671480625/4194304], [Mod(-59375/256*y + 261214369/262144, y^2 + 2), Mod(0, y^2 + 2)]]] -536129/8192*y + 15673889/65536 -2001779325/262144*y + 115490749725/4194304 [24, [12, 2], [[Mod(-20655/8192*y + 15795/2048, y^2 - 13), Mod(300055185/209 7152*y - 270394605/524288, y^2 - 13)], [Mod(221/8*y - 6461/64, y^2 - 13), Mo d(0, y^2 - 13)]]] -313766195076761969526071169866614175160*y + 1735663223649526033628839600302 712469280 [14, [14], [[Mod(358950904714175557651106659750101468600*y - 224800911486294 2058383152194083021128800, y^2 + 11), Mod(-623358463905364610014856551413519 5275639238995135197696000*y + 7068212904273547655621435172436672299424081219 4549767368000, y^2 + 11)]]] [32, [16, 2], [[Mod(-5089/81696780*y^3 - 7/21780*y^2 - 898639/7426980*y - 12 37/1980, y^4 + 2002*y^2 + 116281), Mod(-8470441/296559311400*y^3 - 41923/790 61400*y^2 - 1494908191/26959937400*y - 7401793/7187400, y^4 + 2002*y^2 + 116 281)], [Mod(-1/900, y^4 + 2002*y^2 + 116281), 0]]] [9, [3, 3], [[Mod(-2, y^2 + 3), Mod(-3*y + 1, y^2 + 3)], [1, -5]]] [20, [20], [[Mod(-2*y^2 + 12*y + 12, y^3 - y^2 - 2*y - 2), Mod(52*y^2 - 8*y + 16, y^3 - y^2 - 2*y - 2)]]] [36, [6, 6], [[Mod(-7/32, y^4 + 5*y^2 + 1), Mod(7/512*y^3 + 7/128*y + 35/512 , y^4 + 5*y^2 + 1)], [Mod(1/128*y^3 + 3/64*y - 21/128, y^4 + 5*y^2 + 1), Mod (-1/512*y^3 - 3/256*y + 21/512, y^4 + 5*y^2 + 1)]]] [32, [8, 4], [[0, 0], [Mod(-37/3570750*y^3 - 30007/3570750*y + 222/575, y^4 + 541*y^2 + 72900), Mod(-731971/2463817500*y^3 - 888/1520875*y^2 - 194058451 /2463817500*y - 51282/1520875, y^4 + 541*y^2 + 72900)]]] [64, [8, 8], [[Mod(-3/7*y^15 + 34/7*y^14 - 191/7*y^13 + 97*y^12 - 241*y^11 + 446*y^10 - 4639/7*y^9 + 5844/7*y^8 - 6441/7*y^7 + 6214/7*y^6 - 751*y^5 + 38 25/7*y^4 - 2313/7*y^3 + 1054/7*y^2 - 317/7*y + 45/7, y^16 - 8*y^15 + 36*y^14 - 104*y^13 + 220*y^12 - 368*y^11 + 516*y^10 - 624*y^9 + 664*y^8 - 624*y^7 + 516*y^6 - 368*y^5 + 220*y^4 - 104*y^3 + 36*y^2 - 8*y + 1), Mod(-41/7*y^15 + 304/7*y^14 - 1269/7*y^13 + 3317/7*y^12 - 895*y^11 + 9434/7*y^10 - 1737*y^9 + 13604/7*y^8 - 13345/7*y^7 + 11526/7*y^6 - 8663/7*y^5 + 5395/7*y^4 - 2675/7 *y^3 + 984/7*y^2 - 223/7*y + 12/7, y^16 - 8*y^15 + 36*y^14 - 104*y^13 + 220* y^12 - 368*y^11 + 516*y^10 - 624*y^9 + 664*y^8 - 624*y^7 + 516*y^6 - 368*y^5 + 220*y^4 - 104*y^3 + 36*y^2 - 8*y + 1)], [Mod(-1006/329*y^15 + 763/47*y^14 - 17540/329*y^13 + 4104/47*y^12 - 29994/329*y^11 + 11747/329*y^10 + 2568/47 *y^9 - 60499/329*y^8 + 92956/329*y^7 - 16937/47*y^6 + 118390/329*y^5 - 10387 8/329*y^4 + 70088/329*y^3 - 5507/47*y^2 + 11498/329*y - 2228/329, y^16 - 8*y ^15 + 36*y^14 - 104*y^13 + 220*y^12 - 368*y^11 + 516*y^10 - 624*y^9 + 664*y^ 8 - 624*y^7 + 516*y^6 - 368*y^5 + 220*y^4 - 104*y^3 + 36*y^2 - 8*y + 1), Mod (-4412/329*y^15 + 35995/329*y^14 - 22978/47*y^13 + 459612/329*y^12 - 134990/ 47*y^11 + 1532149/329*y^10 - 2078812/329*y^9 + 2438613/329*y^8 - 358218/47*y ^7 + 2277477/329*y^6 - 256916/47*y^5 + 1211712/329*y^4 - 660116/329*y^3 + 27 1037/329*y^2 - 9730/47*y + 10205/329, y^16 - 8*y^15 + 36*y^14 - 104*y^13 + 2 20*y^12 - 368*y^11 + 516*y^10 - 624*y^9 + 664*y^8 - 624*y^7 + 516*y^6 - 368* y^5 + 220*y^4 - 104*y^3 + 36*y^2 - 8*y + 1)]]] [27, [9, 3], [[-3, -5], [Mod(-x^4 + 3*x^2, x^6 + 3), Mod(-3/2*x^5 + 1/2*x^4 + 9/2*x^3 - 3/2*x^2 - 3/2*x - 1/2, x^6 + 3)]]] [4, [2, 2], [[-2147484185, 0], [0, 0]]] 2 2 0 0 [1, [], []] [5, [5], [[114135566422431, 27065925164925932985472]]] Total time spent: 345 pari-2.17.2/src/test/32/mfgaloisrep0000644000175000017500000000107614676526175015440 0ustar billbill[12, 124, Mod(87, 124)]:[[12, 3], [2, 12; 31, 8]] [12, 133, Mod(83, 133)]:[[12, 3], [7, 6; 19, 8]] [24, 148, Mod(105, 148)]:[[24, 12], [2, 16; 37, 18]] [12, 171, Mod(94, 171)]:[[12, 3], [3, 16; 19, 6]] [12, 201, Mod(104, 201)]:[[12, 3], [3, 6; 67, 8]] [12, 209, Mod(197, 209)]:[[12, 3], [11, 6; 19, 8]] [12, 224, Mod(95, 224)]:[[12, 3], [2, 18; 7, 8]] [24, 229, Mod(122, 229)]:[[24, 12], Mat([229, 18])] [24, 261, Mod(244, 261)]:[[24, 12], [3, 12; 29, 18]] -12 [12, 3] [12, 1, 1, "A4"] [ 2 4] [31 2] -24 [24, 12] [24, -1, 1, "S4"] [ 2 2] [37 3] Total time spent: 2838 pari-2.17.2/src/test/32/minim0000644000175000017500000000004314567450071014220 0ustar billbill1 1 78 77 136 Total time spent: 62 pari-2.17.2/src/test/32/bnfsunit0000644000175000017500000000267014760123736014747 0ustar billbill *** Warning: new stack size = 22000000 (20.981 Mbytes). [x, x + 1, x^2 + 1, x^2 - 2*x - 1, 7] 31.029990599327622684230279153223459647 [1, [], []] [0, 0, 1, 0, 0, 0, 0]~ [0, 0, 1, 0, 1, 0, 0]~ []~ [0, 0, 37, 0, 20, 0, 0]~ []~ [[Mat([-x + 1, 1]), Mat([-1, 1])], [], [;], 1] []~ [[Mat([[0, 1, 0]~, 1]), Mat([[1, 1, 0]~, 1]), Mat([[1, 0, 1]~, 1]), Mat([[-1 , -2, 1]~, 1]), Mat([[7, 0, 0]~, 1]), Mat([-x + 1, 1]), Mat([-1, 1])], [[2, [0, 1, 0]~, 3, 1, [0, 2, 0; 0, 0, 2; 1, 0, 0]], [3, [1, 1, 0]~, 3, 1, [1, 2, -2; -1, 1, 2; 1, -1, 1]], [5, [2, 1, 0]~, 1, 1, [-1, 2, -4; -2, -1, 2; 1, - 2, -1]], [5, [-1, -2, 1]~, 1, 2, [2, 0, 2; 1, 2, 0; 0, 1, 2]], [7, [7, 0, 0] ~, 1, 3, 1]]~, matrix(0,5), 1] [1, 0, 1, 0, 0, 0, 0]~ []~ [37, 0, 20, 0, 0, 0, 0]~ []~ [0, 1]~ [1, 0]~ [-1/2*x - 3/2] 0.69314718055994530941723212145817656807 [1, [], []] [2] 5.6285569682787745211960896402558797364 [2, [2], [[11, 1; 0, 1]]] [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]~ [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]~ [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]~ [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]~ [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]~ [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]~ [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]~ [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]~ [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0]~ [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]~ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0]~ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0]~ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]~ 1 Total time spent: 1631 pari-2.17.2/src/test/32/lex0000644000175000017500000000067214567450071013707 0ustar billbill[1, 1, 0] [1, 2, -1] [1, 3, -1] [1, 4, -1] [1, 5, -1] [1, 6, -1] [1, 7, -1] [1, 8, -1] [2, 2, 0] [2, 3, 1] [2, 4, 1] [2, 5, 1] [2, 6, 1] [2, 7, 1] [2, 8, 1] [3, 3, 0] [3, 4, -1] [3, 5, 1] [3, 6, -1] [3, 7, -1] [3, 8, 1] [4, 4, 0] [4, 5, 1] [4, 6, 1] [4, 7, -1] [4, 8, 1] [5, 5, 0] [5, 6, -1] [5, 7, -1] [5, 8, 1] [6, 6, 0] [6, 7, -1] [6, 8, 1] [7, 7, 0] [7, 8, 1] [8, 8, 0] -1 -1 1 -1 -1 0 1 1 -1 -1 1 -1 -1 1 -1 1 1 1 -1 Total time spent: 4 pari-2.17.2/src/test/32/ellheight0000644000175000017500000000000014567450071015045 0ustar billbillpari-2.17.2/src/test/32/zncoppersmith0000644000175000017500000000121514567450071016016 0ustar billbill[100000000000] 1 [1339991002000615200] 1 [-997, -955, -913, -871, -829, -787, -745, -703, -661, -619, -577, -535, -49 3, -451, -409, -367, -325, -283, -241, -199, -157, -115, -73, -31, 11, 53, 9 5, 137, 179, 221, 263, 305, 347, 389, 431, 473, 515, 557, 599, 641, 683, 725 , 767, 809, 851, 893, 935, 977] *** at top-level: zncoppersmith(v*P,v*n,p,p*v) *** ^---------------------------- *** zncoppersmith: overflow in zncoppersmith [bound too large]. *** at top-level: zncoppersmith(x/2,10,5,5) *** ^------------------------- *** zncoppersmith: incorrect type in zncoppersmith (t_POL). Total time spent: 68 pari-2.17.2/src/test/32/history0000644000175000017500000000057214567450071014617 0ustar billbill2 3 4 5 *** at top-level: %`````` *** ^------- *** %: History result %-1 not available [%1-%5]. 0 3 3 1 1 1 *** at top-level: %`` *** ^--- *** %: History result %11 not available [%13-%13]. *** at top-level: %`` *** ^--- *** %: History result %12 has been deleted (histsize changed). 1 Total time spent: 0 pari-2.17.2/src/test/32/ellff0000644000175000017500000000045514760123736014206 0ustar billbill *** Warning: new stack size = 10000000 (9.537 Mbytes). [[Mod(325254531735269032, 18446744073709551557), Mod(2692423357974964052, 18 446744073709551557)]] 18446744078921414430 93 88 [0] [0] Mod(1, 2)*a1^2*x^2 + Mod(1, 2)*a3^2 63759030914642012164449632 925103102313118416118 Total time spent: 7832 pari-2.17.2/src/test/32/ramanujantau0000644000175000017500000000064414676526175015616 0ustar billbill *** Warning: new stack size = 10000000 (9.537 Mbytes). 1 -804352952075176386846143824455748 -13315918075567401218116415546424460893941774043543776 2197918163306431508972245458640290595016727590854926561659594845349627915113 15520 0 0 0 -6048 -1809673056 0 *** at top-level: ramanujantau(x) *** ^--------------- *** ramanujantau: incorrect type in ramanujantau (t_POL). Total time spent: 2774 pari-2.17.2/src/test/32/solve0000644000175000017500000000341214676526175014254 0ustar billbill14.134725141734693790457251983562470271 [14.134725141734693790457251983562470271, 21.0220396387715549926284795938969 02777, 25.010857580145688763213790992562821819, 30.4248761258595132103118975 30584091320, 32.935061587739189690662368964074903489, 37.5861781588256712572 17763480705332821, 40.918719012147495187398126914633254396, 43.3270732809149 99519496122165406805783, 48.005150881167159727942472749427516042, 49.7738324 77672302181916784678563724058, 52.970321477714460644147296608880990064, 56.4 46247697063394804367759476706127553, 59.347044002602353079653648674992219031 , 60.831778524609809844259901824524003803, 65.112544048081606660875054253183 705029, 67.079810529494173714478828896522216770, 69.546401711173979252926857 526554738443, 72.067157674481907582522107969826168391, 75.704690699083933168 326916762030345923, 77.144840068874805372682664856304637016, 79.337375020249 367922763592877116228191, 82.910380854086030183164837494770609497, 84.735492 980517050105735311206827741417, 87.425274613125229406531667850919213252, 88. 809111207634465423682348079509378396, 92.49189927055848429625972524181068487 9, 94.651344040519886966597925815208153938, 95.87063422824530975874102921924 6781695, 98.831194218193692233324420138622327821] 3183 -128 -128 -128 -373 *** at top-level: solvestep(x=1,100,-1,hardy(x)) *** ^--------- *** domain error in solvestep: step <= 0 *** at top-level: solve(x=-oo,0,exp(x)-2) *** ^--- *** _-_: the PARI stack overflows ! current stack size: 8000000 (7.629 Mbytes) [hint] set 'parisizemax' to a nonzero value in your GPRC *** at top-level: solve(x=2,oo,exp(x)-2) *** ^--------- *** exp: overflow in expo(). Total time spent: 287 pari-2.17.2/src/test/32/padic0000644000175000017500000002040714676526175014207 0ustar billbill+oo [O(2)]~ [Mod(0, t)]~ [Mod(0, t^2 + 1)]~ [2*5 + O(5^2), 3*5 + O(5^2)]~ [(1 + O(3^5))*y^2 + O(3^5)*y + O(3^5) 1] [(1 + O(5^2))*x + O(5^2) 1] [(1 + O(5^2))*x + O(5^2) 1] [ (1 + O(5^2))*x + O(5^2) 1] [ (1 + O(5^2))*x + O(5^2) 1] [(1 + O(5^2))*x + (1 + O(5^2)) 1] [(1 + O(5^2))*x + (1 + O(5^2)) 1] [(1 + O(5^2))*x + (1 + O(5^2)) 1] [(1 + O(5^2))*x + (2 + O(5^2)) 1] [(1 + O(5^2))*x + O(5^2) 2] [(1 + O(2^5))*x + O(2^5) 1] [303091841983800080655794283008425100039742205409907463050265866099342335310 9435450473759394409290772958513969209043309887654107823563961950120902162328 9769326760830012577046380799009644065843091379678844848336197237093057023804 6689848912926486505130709901883062497124814860382257802988956439425088932461 0372025296688642620365911220110991569990328464459735660494309717728461213007 1801499708339544755377536878289360381720619549093067863866419820272280136477 2830800728859838435544923858759881340490985695391715382902245978494662272462 6052864155393228763598731308273292630444845297138100310999495119765776446322 3860052732483765519446500500094346234790611688099389032815052584811119320550 3704669618458110652816974131143493927907230211763195122366400692171033393720 271195569191, 13020836829112671085985220226774471665002775641446996088876884 3691338423847199876670450857336997350275120427670497827105902457829900805568 9719472368109783134615365374621272645318492298469870785155840876721739513480 5863213246980524738313176449660582809667252629484206997514702295002515061510 0684360909834392213592414944152124335972138550682495171014579333479279921333 5904066365587070683781105745761987654966795582331907184529593280396827369610 2019154579782144905432984081972843049020762285632803482844786928852456176727 9344982547780680381242398549057381848394717649769513041214735182126715458420 8350305350756518594813992253867533694908369935455537375264348437017294628673 7633210413290943225901496946252789071904264368534914051665187493778714162848 7537382321251210717887612]~ [2, 2, 2] [3, 2, 2] [6, 2, 2] [7, 2, 2] [10, 2, 2] [2, 2, 3] [3, 2, 3] [4, 2, 3] [5, 2, 3] [6, 2, 3] [7, 2, 3] [10, 2, 3] [2, 3, 3] [3, 3, 3] [4, 3, 3] [5, 3, 3] [6, 3, 3] [7, 3, 3] [8, 3, 3] [9, 3, 3] [10, 3, 3] [2, 11, 3] [3, 11, 3] [4, 11, 3] [5, 11, 3] [6, 11, 3] [7, 11, 3] [8, 11, 3] [9, 11, 3] [10, 11, 3] [2, 18446744073709551629, 3] [3, 18446744073709551629, 3] [4, 18446744073709551629, 3] [5, 18446744073709551629, 3] [6, 18446744073709551629, 3] [7, 18446744073709551629, 3] [8, 18446744073709551629, 3] [9, 18446744073709551629, 3] [10, 18446744073709551629, 3] [2^3 + O(2^6), 1 + 2^2 + O(2^6), 1 + 2 + 2^4 + 2^5 + O(2^6)]~ [Mod((1 + 2 + 2^2 + 2^3 + 2^4 + 2^5 + 2^6 + 2^7 + 2^8 + 2^9 + O(2^10))*y + ( 1 + 2^2 + 2^6 + 2^7 + O(2^10)), y^2 + y + 1), Mod((1 + 2 + 2^2 + 2^3 + 2^4 + 2^5 + 2^6 + 2^7 + 2^8 + 2^9 + O(2^10))*y + (1 + 2 + 2^4 + 2^5 + 2^8 + O(2^1 0)), y^2 + y + 1)]~ [Mod((1 + 2 + 2^2 + 2^3 + 2^4 + 2^5 + O(2^6))*y + (2^3 + O(2^6)), y^2 + y + 1), Mod((1 + 2 + 2^2 + 2^3 + 2^4 + 2^5 + O(2^6))*y + (1 + 2^2 + O(2^6)), y^2 + y + 1), Mod((1 + 2 + 2^2 + 2^3 + 2^4 + 2^5 + O(2^6))*y + (1 + 2 + 2^4 + 2 ^5 + O(2^6)), y^2 + y + 1)]~ [Mod((1 + 2 + 2^2 + 2^3 + 2^4 + 2^5 + O(2^6))*y + (2^3 + O(2^6)), y^2 + y + 1), Mod((1 + 2 + 2^2 + 2^3 + 2^4 + 2^5 + O(2^6))*y + (1 + 2^2 + O(2^6)), y^2 + y + 1), Mod((1 + 2 + 2^2 + 2^3 + 2^4 + 2^5 + O(2^6))*y + (1 + 2 + 2^4 + 2 ^5 + O(2^6)), y^2 + y + 1)]~ 1/2 3 + 3^2 + O(3^5) 2 + 2^2 + O(2^5) 1 + 2*3^2 + 3^3 + 3^4 + O(3^5) 1 + O(x) 3 + 2*3^3 + 3^4 + O(3^5) O(x) 3 + O(3^5) O(x) 3^-1 + O(3^3) O(x) 1 + 2*3 + 2*3^2 + 2*3^3 + 2*3^4 + O(3^5) 1 + 2 + 2^2 + 2^3 + O(2^5) 18446744073709551627 + 18446744073709551628*18446744073709551629 + O(1844674 4073709551629^2) 3074457345618258605 + 15372286728091293024*18446744073709551629 + O(18446744 073709551629^2) 2*3^2 + 2*3^3 + 2*3^6 + 3^7 + 2*3^8 + 3^9 + O(3^10) 3^-1 + 2 + 3 + 3^3 + 3^5 + 3^6 + O(3^10) 1 + O(2) 1 + 2^2 + O(2^3) 1 + 2 + 2^2 + 2^3 + 2^5 + 2^6 + O(2^7) 1 + 2 + 2^2 + 2^3 + 2^5 + 2^6 + 2^7 + O(2^8) 1 + 2^2 + 2^4 + O(2^5) 1 + 2^2 + 2^4 + 2^5 + O(2^6) 1 + 5^2 + 2*5^4 + 5^5 + 3*5^6 + 2*5^7 + 3*5^8 + 4*5^9 + 4*5^10 + 4*5^11 + 3* 5^15 + 3*5^16 + 5^18 + 2*5^20 + 3*5^21 + 4*5^22 + 3*5^23 + 4*5^24 + 4*5^25 + 2*5^26 + 3*5^27 + 3*5^29 + 3*5^30 + 3*5^31 + 5^33 + 2*5^34 + 4*5^36 + 4*5^3 7 + 4*5^39 + 4*5^41 + 3*5^42 + 5^43 + 3*5^45 + 2*5^46 + 5^47 + 2*5^48 + 4*5^ 50 + 2*5^51 + 2*5^52 + 2*5^53 + 4*5^54 + 2*5^55 + 5^57 + 5^58 + 3*5^59 + 3*5 ^60 + 2*5^62 + 3*5^63 + 4*5^64 + 3*5^65 + 5^66 + 4*5^68 + 2*5^73 + 2*5^76 + 2*5^77 + 2*5^79 + 5^81 + 5^82 + 5^84 + 5^85 + 5^86 + 5^90 + 4*5^91 + 5^92 + 3*5^93 + 5^94 + 5^96 + 4*5^97 + 5^98 + 3*5^99 + O(5^101) 2*3^3 + 2*3^4 + O(3^6) 2 + 2^4 + O(2^5) 1 + O(2) 1 + O(2^2) 2 + 2^4 + O(2^6) 2 + 2^4 + O(2^7) 1 + 2^2 + O(2^4) 1 + 2^2 + O(2^5) [1 + 2^2 + O(2^5), 2 + 2^3 + O(2^5), 2^-1 + 1 + 2^5 + O(2^6), 2^2 + 2^3 + O( 2^6), 1 + 2^2 + 2^4 + 2^5 + 2^7 + O(2^8), 2^4 + 2^5 + O(2^8), 2^2 + 2^4 + 2^ 8 + O(2^9), 2^5 + 2^6 + O(2^9), 2^3 + 2^5 + 2^7 + 2^8 + O(2^11), 2^8 + 2^9 + 2^10 + 2^11 + O(2^12), 2^6 + 2^9 + 2^11 + 2^12 + O(2^13)] 4*5 + 2*5^2 + 5^3 + 3*5^4 + 3*5^5 + 5^7 + 3*5^8 + 2*5^9 + 5^10 + 3*5^11 + 3* 5^12 + 5^14 + 5^16 + 2*5^17 + 2*5^18 + 2*5^19 + 5^20 + 3*5^21 + 3*5^22 + 3*5 ^23 + 2*5^24 + 5^25 + 5^27 + 5^28 + 4*5^29 + 3*5^31 + 4*5^32 + 2*5^33 + 4*5^ 34 + 4*5^35 + 2*5^36 + 3*5^37 + 5^39 + 2*5^40 + 3*5^42 + 2*5^43 + 5^44 + 2*5 ^45 + 5^47 + 4*5^48 + 3*5^49 + 2*5^51 + 3*5^52 + 2*5^54 + 4*5^55 + 4*5^56 + 3*5^57 + 5^58 + 3*5^59 + 3*5^60 + 3*5^63 + 5^65 + 3*5^66 + 3*5^67 + 5^69 + 2 *5^70 + 2*5^74 + 4*5^75 + 3*5^76 + 2*5^77 + 5^78 + 5^79 + 2*5^82 + 2*5^83 + 4*5^85 + 2*5^86 + 4*5^87 + 5^89 + 5^91 + 3*5^92 + 5^93 + 3*5^94 + 5^95 + 4*5 ^96 + 2*5^97 + 4*5^98 + 3*5^99 + 4*5^100 + 3*5^101 + O(5^102) 3^2 + 3^3 + 2*3^4 + 3^5 + 2*3^6 + 3^8 + 3^10 + 3^11 + 3^12 + 3^13 + 2*3^15 + 3^17 + 2*3^19 + 3^20 + 3^22 + 3^24 + 3^25 + 3^26 + 3^29 + 2*3^30 + 2*3^31 + 2*3^33 + 2*3^34 + 2*3^36 + 3^38 + 3^41 + 2*3^42 + 2*3^43 + 3^47 + 2*3^48 + 2*3^49 + 3^50 + O(3^51) 3 + 2*3^4 + 3^5 + 2*3^6 + 3^7 + 2*3^8 + 3^9 + 2*3^10 + 2*3^11 + 2*3^13 + 2*3 ^16 + 2*3^17 + 3^18 + 2*3^19 + 3^20 + 2*3^21 + 3^22 + 3^23 + 3^26 + 3^28 + 2 *3^30 + 2*3^31 + 3^32 + 2*3^33 + 2*3^34 + 2*3^35 + 3^36 + 2*3^37 + 3^38 + 2* 3^40 + 2*3^43 + 2*3^46 + 3^48 + 2*3^49 + 2*3^51 + 3^52 + O(3^53) [2 + 4*7 + 2*7^2 + 4*7^4 + 6*7^5 + 4*7^7 + 6*7^8 + 5*7^9 + O(7^10), O(7^10), 5 + 3*7^2 + 4*7^3 + 3*7^4 + 6*7^5 + 2*7^6 + 6*7^7 + 2*7^8 + 5*7^9 + O(7^10) , O(7^10), 2 + 4*7 + 5*7^2 + 6*7^3 + 2*7^4 + 3*7^5 + 3*7^6 + 4*7^7 + 5*7^8 + O(7^10), O(7^10), 7^-1 + 4*7 + 2*7^2 + 4*7^3 + 3*7^4 + 4*7^5 + 3*7^6 + 3*7^ 8 + 3*7^9 + O(7^10), O(7^9), 7 + 5*7^2 + 3*7^3 + 5*7^4 + 2*7^5 + 3*7^6 + 5*7 ^7 + 2*7^8 + 7^10 + O(7^11), O(7^11), 3*7 + 5*7^2 + 7^4 + 3*7^5 + 4*7^6 + 6* 7^7 + 6*7^8 + 6*7^9 + 6*7^10 + O(7^11)] 2 + 5 + 2*5^2 + O(5^3) 2^2 + 2^3 + 2^4 + 2^5 + 2^6 + 2^9 + O(2^10) 3 + 2*3^2 + 3^3 + 2*3^5 + 2*3^6 + 3^8 + O(3^10) 5 + 2*5^2 + 4*5^3 + 2*5^4 + 5^6 + 4*5^7 + 2*5^8 + 3*5^9 + O(5^10) 101 + 50*101^2 + 84*101^3 + 41*101^4 + 89*101^5 + 4*101^6 + 34*101^7 + 10*10 1^8 + 77*101^9 + O(101^10) []~ []~ []~ [4, 0, 0, 0] [+oo, 2, 1/2, 1/2] [+oo, 2, 1/2, 1/2] [(1 + O(2^3))*x^3 + (2 + 2^2 + O(2^3))*x^2 + O(2^3)*x + O(2^3) 1] [(1 + O(2^3))*x^6 + (2 + O(2^3))*x^5 + (2 + 2^2 + O(2^3))*x^4 + (2^2 + O(2^3 ))*x^3 + O(2^3)*x^2 + O(2^3)*x + O(2^3) 1] [ (1 + O(2^2))*x + O(2^2) 2] [(2 + O(2^2))*x^2 + O(2^2)*x + (1 + O(2^2)) 1] [O(2^2)]~ [O(3^10)]~ [4, 4, 4, 4, 4, 4, 4, 4] [4, 4, 4, 4, 4, 4, 4, 4] (1 + O(3^7))*x + (1 + 3^3 + 2*3^4 + 3^6 + O(3^7)) 0 6139557 3626068*x + 3626068 [ x^2 + x + 29525 1] [x^2 + 59048*x + 29525 1] [9*x^4 + 44287 1] *** at top-level: padicappr(x^2+1+O(3),Mod(-1+O(5^10),y^2-2)) *** ^------------------------------------------- *** padicappr: inconsistent moduli in Zp_to_Z: 5 != 3 *** at top-level: padicappr(x^2+1+O(3),-1+O(5^10)) *** ^-------------------------------- *** padicappr: inconsistent moduli in Zp_to_Z: 5 != 3 *** at top-level: padicappr(x^2+1,1/3+O(3)) *** ^------------------------- *** padicappr: domain error in padicappr: v(a) < 0 *** at top-level: gamma(1/3+O(3^4)) *** ^----------------- *** gamma: domain error in gamma: v_p(x) < 0 *** at top-level: psi(1/3+O(3^4)) *** ^--------------- *** psi: domain error in psi: v_p(x) < 0 Total time spent: 8 pari-2.17.2/src/test/32/isprime0000644000175000017500000005046414760123736014573 0ustar billbill *** Warning: new stack size = 62000000 (59.128 Mbytes). 1 1 1 1 [1, 1, 0] [1, 1, 0] [1, 1, 0] [1, 1, 0] [0, 1, 0, 1] 1 1 1 [115792089237316195423570985008687907853269984665640564039457584007913129645 657, 26277779554128913609954779058232363788521114678955502753401829636681, 8 0687662500901867092047699754802901705350288059670998026953, 5226195652861307 3298419378777290957419649773021913, 2230938125527750076770229326926528843267 411013, 458380547673669627444045551333712881906833, 655389880696349883130454 0926030837, 3094624324252741256658991] 1 0 [115792089237316195423570985008687907853269984665640564039457584007913129645 657, [2, 3, 101, [4776901371176410702292532384846860885035890456503323598987 5240927356901669, 2, [477690137117641070229253238484686088503589045650332359 89875240927356901669, [2, 3, 35437, [237470764391881188851670682297783, 2, [ 237470764391881188851670682297783, [2, 3, 1029859, [384309509670549057122820 83, 2, [38430950967054905712282083, [2, 11, 8821, 13007, 1384110626125243]]] ]]], [473040069351431854709203123134857609, 2, [4730400693514318547092031231 34857609, [2, 47, 419, [3002590192907580451868704127957, 2, [300259019290758 0451868704127957, [2, 22973, 23889163499]]]]]]]]]]] 1 0 1 0 1 0 2 1 1 "[1]\n N = 100000000000000000000000000000000069\n t = 546867911035452074\n s = 2963504668391148\na = 0\nD = -3\nm = 99999999999999999453132088964547996\ nq = 33743830764501150277\nE = [0, 1]\nP = [33871007718198692871763537900223 244, 37634983931409678910567952612637528]\n[2]\n N = 33743830764501150277\n t = -11610830419\n s = 734208843\na = 0\nD = -3\nm = 33743830776111980697\nq = 45959444779\nE = [0, 27804066824294720140]\nP = [16662256621764551072, 71 7141744113721531]\n" "[* [* 100000000000000000000000000000000069, 3, -1, 999999999999999994531320 88964547996, [* 0, 1 *], [* 33871007718198692871763537900223244, 37634983931 409678910567952612637528, 1 *], [* [* 33743830764501150277, 1 *] *] *], [* 3 3743830764501150277, 3, -1, 33743830776111980697, [* 0, 27804066824294720140 *], [* 16662256621764551072, 717141744113721531, 1 *], [* [* 45959444779, 1 *] *] *] *]" [PRIMO - Primality Certificate] Format=4 TestCount=2 [Comments] https://pari.math.u-bordeaux.fr/ [Candidate] N=0x13426172C74D822B878FE800000045 [1] S=0xA874AB30CB6EC W=0x796DD77B853FAAA A=0x0 B=0x1 T=0x685F8389020BF8EFBDD69F4BE3B0C [2] S=0x2BC3234B W=-0x2B40F3653 A=0x0 B=-0x526E47D559ADC7B9 T=0xE73C3A1DF8AD21A0 [PRIMO - Primality Certificate] Format=4 TestCount=20 [Comments] https://pari.math.u-bordeaux.fr/ [Candidate] N=0x833223F144EEB94EEADF37CB2E02035B9AE2F07E27CB3294F0EB83BB726AEB49D22A1695 E24BB3EB875942FD98F16849F2653487381EF1E8FBD5E95C6B7B [1] S=0x637 W=-0xFFB1744FF54835147E392FA7D9FF8A084F876D03EFCF3D86470D1A301FCDEF J=-0xA6A03EA6E9EC5F68460AB4899596A93B7EC2E09F4780A807AEEAC54D2F26F51E087D5D3 925E28F91A1248A55369BAEFE11372F07CE682AFE1AC41552328 T=0x35D7F058D5823F97AC6AD075DD58E2209565809F6B860ADF39A968F9892E1B4B2ABDC78D 6DB296F78C8A3451F9FB21A7DA2BB27BEAB9B757906CF70381A8 [2] S=0x1C8F61 W=-0x7C54C8E391DD9FD066E4D80EC381A44838571AC35314E7FDCA80308B13AD3 A=0x0 B=-0x89399737C15AC46ECDDF4AB6FC613C07F5C208F4525349CA9E30249F724D8FD573E03A3 41177C108787BE0DBF887F1A94C7BFF56965BC50BA8ED2B109 T=0x4228234CAE8900ADCFEF49A037D560C8E2C2ED4227D4A2CDA8703079D3DA3C75467D70F0 B06F09A955FEFF97757BC4E599C64BB9FACA61B3CB4331F70 [3] S=0x1094 W=-0x94599D911598B690B9BBF116102A51E3729546C40CEC8940C921116A22 J=-0x2245AE8000 T=0x5AD00801E96F984D3224DE1AA1CD318A9FE304F03E3E6DED3A6B82BF88D173860B508451 6F6F9BE4C7E88920956D08B678B373190760B3BADA34 [4] S=0x1119C W=-0x52499704942F96E5E284FF1252BC44B433CD1CFD00464FC8DC16EB77E J=0x1926C20336976599EAF35B2592C348CC428C98DF798F2C7DB89D7CA1537B2C7871B1EF59 92B90E32288A7C8277A55B80CF9A44E5C6A5A04B2 T=0x5342F42A31FC13E3A492BA281827EA7E1E62BE1D9E1C9C69A1D9B5B932E074067A4B9953 65F4A578FDE237EE82FFDF18BE3B26AAB18FF2E30 [5] S=0x16F W=-0x62BA803367835ABDFDEF999C2BDA04F79028F37850F4EFE96B02F7D A=0x0 B=0x21100BA1BDCB9481B02ADB5891EE480C806F0EAE98CDDC01819C2899949BF7C7B19B8FDB 036CD9F7329DB128DD0D3510FF6369835C0D7 T=0xAAD7D93A4256E6B2B70757A011D800C39962486CE3BA88788716E9AC581C37C140116D12 E2E9ABD56262A1A25547241510EB2B4CFFBC4 [6] S=0x54 W=-0x5709B2E5D4C47F22E7DE96EBEC9A24E3B1F41A6E5A6062A99F1486 A=0x0 B=0x1 T=0x5B3189FA262C0259E16F63F000194C4D5BBE3BB39075C068A34E30288DED00B063876877 E9D68E100A50B479104B85497A9BA510638 [7] S=0x1423147456 W=0x48CC11EE5056CCF2378516112FF474D3F78BBF5550126F6504E56 J=0x1F40 T=0x57BAD3984E48C51A34B1C9A1F7F87E2C8E4B7693C9FD72AE4EAA56E2454F282F6B418D5C C04FD1F3B8ACF85BF1BFCEE0F6A475D9E [8] S=0x1ECB3 W=-0x1F6DFAE11AB161C3ED3B7E18E337354C7FF7484DD5DE9E44B J=-0x2245AE8000 T=0xB4070B57E0DCCE274B858A7F2C78D48EA8E15D0546C167E8650285232493E44F4DAFA11B C80D5C074FDA40F68CDDE6D5 [9] S=0x7B7F33 W=-0x18127FC99762CD931F957910A808FC0CE34600A4C9617D3 A=0x0 B=-0x456416F992EEE25B1FBFE9BF3E78017C9FC6F3B3A9D8EB39143CC6540961A652E9B2C11 D0BCE1B3D72607BF013AD T=0x8D2114F3EB778DE946C640F9A1CC4D5A33986F6C81B479B73E74675550A9213B057D6FDE BC4527B5B7421AC1E93C [10] S=0xC66D8D W=0x1F0228CFD240159624478F7EF677EF4A9EE58B729B0D A=0x0 B=0x6CF79CDA296B9E1BF4E51D471E12E8C153D5139E6DB9F079D84B76CEB1297755EF66C450 C9D64EE854ACE8 T=0x8646E8D17025D613995DFBF77F00BA2BD8B23FEF9D97A535CB3AE60436FD5209170AA1EF 8C8A4EB6B9C740 [11] S=0x21B41 W=-0x1314C0B7FBDA29CB7EAE39D4D8ED5A489DF433DF1 A=0x0 B=-0x18516C1A9B8D3DAE6D8A1D41B764DE3F08E37534A5133665A1AC823F1BFABF74CE8807A C3426140C T=0x1038BC3FFD9358DBF44B5A4E77E57D3E31D3824F513FC2E0E924F2F80458A840D2506995 213E3B35A [12] S=0x11C7D27E W=0x72B6A2345C517B23284BC106DF9DE75D158F16 J=-0x45894D8934205DCB8236AC28743B0E8F31604C54E82568F606B3AE72844B5597B303D21 744BC T=0x1DA12A2758B1C56D45CC3E33470B88496573AA7D0EDE8F740C44B36A324EB9D6CA15371A 22BF [13] S=0x2D37382 W=-0x62128374105EB3C867C5FAF49FF768A4EA4 A=-0x31C083973E132B3AB3EA01B98F38AC5A46F12AAE7FBAA83649585143C7427F8936F5C B=0x0 T=0x878877C140116D12E2E9ABD56262A1A25547241510EB2B4CFFBC472AECA534DF8F8E8 [14] S=0x8DC98CBC W=-0x3B702D1DE486C6FEB99F0D54B406A3C6 J=0x1D749BECDE3071BCCEE13C2314FA41D861D378B72097C132DBE4CA3F6610AEA T=0x18F286B84EB43633FDCBA2234DDA4B6FC23E8698F494639658DE51CFA05EA65 [15] S=0x804 W=0x33566044CD90384F13FFE5D1522E A=0x0 B=0x1 T=0x1C1937B4940485E16AEEE14778B4CF36EBE05863863C4423E10A0F3 [16] S=0x5741A67A W=0xDF33A3F8E4066BCC4AE4EE06FC A=-0x3CAD1F53EC12F88EA8E4FFC7C54E0D0C6FD58E11E0332E84E825 B=0x0 T=0x924F2506995213E3B35A920334C68EE54936027CF03BABADFE1E [17] S=0x30C3C0D W=0x2F4DCB3F9772B2BC872E449 A=0x0 B=-0x10020841ED81925E2E27A50B8F18B3EEB78FACFB68AEF T=0x2348453CFADDF8DE946C640F9A1CC4D5A33986F6C81B4 [18] S=0x1C0F066AF5 W=0x679B0738F2EF458F8F5 A=0x0 B=0x4D8991956C516D96F87EE9AB71F96AD841420C T=0xBFE64A57743C1A30D54B8689C1D88B238C8A21 [19] S=0xBB64DED W=0x4333C21B3BAD697 A=0x0 B=-0x272DB40B479FFD94C73A20D5F0EDF T=0x2ECA744F79FDD9314E05B5D1533B4 [20] S=0x1784FEE97 W=-0x18DADD3318C1 A=0x0 B=0x23ADC04D29B522C27555F3 T=0x279D8007CF22A87E6AAA30 [* [* 1048474851051175859967518917298456628433649128513856679398306821693162 8397921750730378327608727075136798800609455679041145417393925989505195157778 7259, 4843, -1, 104847485105117585996751891729845662843364912851385667939830 6821693162839796692780501795336392590929771923941754447816158616037422663643 18421805185387, [* 164615906193655523900798506109562715388917607940582570636 8302841589306355168049466843913164393839201226521892908659173193182293772167 751700467239569, 17748272482041674768396422095786746723738052237049151287841 2060427447245779807483707996021941129186393246326675760538872063107926868880 00856050111426 *], [* 618174939653175803652771072922992607561511932892481395 1015169046125514426228522415028969074513763150575383475214577755457059279992 0118859114693061075, 5739243915246129208913969408736114076038900447177317333 0548438051460460666024150251328773513369624429052083472719546401126012072933 19302741061719162, 1 *], [* [* 659003677593448057804851613638250552126743638 2865221115011356515984681582631632812707701674372036013651313273126636179501 0436041650763242251291757, 1 *] *] *], [* 6590036775934480578048516136382505 5212674363828652211150113565159846815826316328127077016743720360136513132731 266361795010436041650763242251291757, 3, -1, 6590036775934480578048516136382 5055212674363828652211150113565159846815840045965544631977981018175483208262 468652447059935595979879482556681963329, [* 0, 39126503300415305686795736950 9831830289805348744659287207898630909119106907135483069064403278094989849501 18109979675077242517649515193633483414372 *], [* 129078036871042336929671104 8900482761642198606234357152726726947793143910952716779246467443068109825925 1428433483262184370283291972674592242343792, 1857933651566742209309125597630 5866751336176987263483540604770985931314164831311717916697287956874511612418 297298380376604077009503847690514490154, 1 *], [* [* 35208585803135847098612 4268858660784066116780877475399006757794383256491994477601772451107520320559 20543514133124280837893200495951827313633, 1 *] *] *], [* 352085858031358470 9861242688586607840661167808774753990067577943832564919944776017724511075203 2055920543514133124280837893200495951827313633, 67, -1, 35208585803135847098 6124268858660784066116780877475399006757794383256531989574800694963167531401 35766387373372567852526690405600875374939652, [* 352085858031358470986124268 8586607840661167808774753990067577943832564919944776017724511075203205592054 3514133124280772891488513894732145633, 3520858580313584709861242688586607840 6611678087747539900675779438325649199447760177245110752032055920543507754378 285787477559967047569777633 *], [* 16897569397338217857103299359758531712544 7512987899726441301702891649479165609816090666133362202684802360071806161381 35786950432206211439156, 398344838174338257297920158628297480997991842640660 8081718483685065004138683578176343898775806532881399459866056474207911319233 405814157072, 1 *], [* [* 82960852505032627470811561936536471269113284843891 4700769928827481754316657810557716689838669654471404038015376245347000245183 8095045933, 1 *] *] *], [* 8296085250503262747081156193653647126911328484389 1470076992882748175431665781055771668983866965447140403801537624534700024518 38095045933, 51, -1, 8296085250503262747081156193653647126911328484389147007 6992882748176818206749276475504606043125809529558872009714399860895722292522 79468, [* 723358656407961487245564595593014868480076430499615728481069615697 7134501975084433372749120220012333501094115060642675480312315605961353, 4714 4534061315601897959096715982446316795453458592959213581291092989908143012583 00323595347403295219370459147819525274111031843161073948 *], [* 551266052015 2443990285739945113649968077412399945748448168087127639181194034514630584698 357992502794860482350869959619391431408668704893, 64039458022978523401562608 9031629432854699437035419910985293307530146691076333632718539163189297380529 200919717082571814510418146868021, 1 *], [* [* 11844105491552827861174627653 5515492075143174067573910794633205910822937306192217000035129408837030337443 424147270858119033353738397, 1 *] *] *], [* 11844105491552827861174627653551 5492075143174067573910794633205910822937306192217000035129408837030337443424 147270858119033353738397, 3, -1, 1184410549155282786117462765355154920751431 7406757391079463320591147277021595309374641583171473396265502995414965051173 7045191575579, [* 0, 2291797096882472347646969652543792181897549716036737325 9489869184610669639185309921568649939108181653611881888454701782277916311767 *], [* 11842291192184816869669598468121539669306998014591712410257946953028 8328872197521765625637878820722848939199822681479190164636957636, 2680743736 7943345610544196794801959689649487578666245148899398596668901320566965216399 793980669153956497091261209769261364574299255, 1 *], [* [* 32272767006955934 2266338628162167553338264779475678231048046882592568856174259111025656217206 359571267111591688421012907480086037, 1 *] *] *], [* 32272767006955934226633 8628162167553338264779475678231048046882592568856174259111025656217206359571 267111591688421012907480086037, 3, -1, 3227276700695593422663386281621675533 3826477947567823104804688262837416569794531794941164679635644589212264040489 9868852624788124, [* 0, 1 *], [* 2469233261259855661932182976283867779880515 9666979068606536957433536193238624655247974862706340247288110083423663176943 7814457912, 1333477409842787076764437583112893861792533513116687943697171482 14067473631477412831337284167891925943810953361394374503442775527, 1 *], [* [* 3841996072256658836504031287644851825455533088996169417238653364623501972 594587118445376747575671974906221909582141295864580811, 1 *] *] *], [* 38419 9607225665883650403128764485182545553308899616941723865336462350197259458711 8445376747575671974906221909582141295864580811, 8, -1, 384199607225665883650 4031287644851825455533088996169417238653362751813850908461017232714165520358 303193368605055427915946900598, [* 38419960722566588365040312876448518254555 3308899616941723865336462350197259458711844537674757567197490622190958214129 5714052811, 3841996072256658836504031287644851825455533088996169417238653364 623501972594587118445376747575671974906221909582140666456836811 *], [* 29140 8723862471500601133926780384468015659260217295529037678940738684322056773419 9934572569834876990885175972913925959767600429, 1038208064379008029894251089 5809637395904450230797038078656140011235310432274321917024966270083000540296 40429426930586580366109, 1 *], [* [* 444223592167483854578240685916809122269 8000536331519796694687421676874997851200318747437832474899593212236376625668 9, 1 *] *] *], [* 4442235921674838545782406859168091222698000536331519796694 6874216768749978512003187474378324748995932122363766256689, 67, -1, 44422359 2167483854578240685916809122269800053633151979669592046452365368077493939172 75522630629088178578394941888637, [* 742519341678400012162395850914408813236 1430594518660600002669754430249443616963974366594387972000778641266750726234 , 15239324936307805508800566403185325262035875125866467902147166178737475086 818283151356916082447601837706620980752826 *], [* 39784950703189220546624308 1711704896361532186368397811794999800928899281092531390057244555693347522331 05961664252752, 213995007098807210674631395396137287492430027196578533672479 46729962508478077067320011217940587379205613281085141565, 1 *], [* [* 352192 2383612940946938030190173780611188368074725103104467514302212504206559005630 43784023203091136822655770127, 1 *] *] *], [* 352192238361294094693803019017 3780611188368074725103104467514302212504206559005630437840232030911368226557 70127, 3, -1, 35219223836129409469380301901737806111883680747251031048364206 4980206573150174531107612676443648815746000942563, [* 0, 1892245773769818716 2047354411484542638867952375639243516770619130583041357133601144042171647407 1017061998840418 *], [* 3314479968516182898976651342959975763964167766985032 13921906460040544021011257075996476305095277644484425410876, 709005446800857 1817548096410316507048759643826932404029687886080830917985505612895196912878 2191120464385323881, 1 *], [* [* 4351549144383975897345200223455837056207720 5926652702830415461632095046890170697799949697410381850766993, 1 *] *] *], [ * 43515491443839758973452002234558370562077205926652702830415461632095046890 170697799949697410381850766993, 3, -1, 4351549144383975897345200223455837056 2077205926652691228782470298911822248492396024205412899846315299717, [* 0, 1 5253674776209590255914553527416544669516418268956111131572401389590778082874 772542697910893606679653608 *], [* 18796636399903498248573517860319536572142 597796915965160538527074306149720980817206536526467754549167936, 13541691688 6888204062388116503423284264011249722937274749898351156490322373021521285293 49790092754377750, 1 *], [* [* 334627134257901359613194950840459985898966477 3504066058547703902348255613678193609405643319251929, 1 *] *] *], [* 3346271 3425790135961319495084045998589896647735040660585477039023482556136781936094 05643319251929, 3, -1, 33462713425790135961319495084045998589896647735058089 96591143336000749155561349262493936312701387, [* 0, 314336879611066888520165 7916922736197620626796006346194433436857478529072906585083817625995673549 *] , [* 21655734556248285500844167183079111756616745231574786557858427899960354 55952778378481054840501082, 403627667311724252272685794156819915504682219494 065842675182705088410392588416118939686375784948, 1 *], [* [* 24239736199313 3857987522510732029921186655808698781519358426597512531721023792223231891307 63, 1 *] *] *], [* 242397361993133857987522510732029921186655808698781519358 42659751253172102379222323189130763, 328, -1, 242397361993133857987522510732 02992118665580867319957351827947433273928915526035567673906934, [* 670971099 3257405955413773660246088639062294486128760883856693752628624199860471619124 754107, 13028577996285518697124880716791185908510659933374447268873262168613 85559013038113760303848 *], [* 204674575604690679025367928968028347277590339 96800123176409553628696084519896286022891471692, 928183261866384076316082487 0943864958918885286767858089965440309422259859119933700075825185, 1 *], [* [ * 81257351999213034760913331692221986823633647172218931839659275074469549537 008857797, 1 *] *] *], [* 81257351999213034760913331692221986823633647172218 931839659275074469549537008857797, 4, -1, 8125735199921303476091333169222198 6823634181128708645776291697423442063719037600106, [* 5766075089950174965031 0608848565035666626736007209935826665105968979557878053553001, 0 *], [* 6428 1223917609107191067931696269772839673306888734850834739360513387330148272503 016, 97197182469969476024497243816736711789655312160193567249366066059009294 56299410039, 1 *], [* [* 171385269639856550454513385364684741062574748598361 2152668116425125124471797, 1 *] *] *], [* 1713852696398565504545133853646847 410625747485983612152668116425125124471797, 91, -1, 171385269639856550454513 3853646847410704754390059852485129178388076021424060, [* 4050580404652074987 52977558847168614419888585021295559995757788262381141057, 421361059648362247 25578843971687603465604229159519862750703890550851599286 *], [* 924048162335 865235576441372348516601911105090008322602172319674958991776308, 55460562344 902606750336669815111479720648045728831082867487846994109375901, 1 *], [* [* 720470581712361012808879380868886453293907785871566789831698315073, 1 *] *] *], [* 720470581712361012808879380868886453293907785871566789831698315073, 3, -1, 720470581712361012808879380868885412047602284765541595425122362644, [ * 0, 1 *], [* 18494488033143675216778771158645047374404062793706881339329561 4195, 245718975415055368701152492954633039114615070977315172460337998591, 1 *], [* [* 351106521302320181680740439019924664740546922400361401279299397, 1 *] *] *], [* 35110652130232018168074043901992466474054692240036140127929939 7, 4, -1, 351106521302320181680740439019906980878340478759206493970610250, [ * 253603531890624172691821365566315813370298929386261911945533216, 0 *], [* 235109753368318201254337626809703057506380360044686498402795038, 13751284082 5085816748818027112461370334181506986197163795725064, 1 *], [* [* 2398399238 63557582239019126226245576477503114503133961, 1 *] *] *], [* 239839923863557 582239019126226245576477503114503133961, 3, -1, 2398399238635575822390191253 11255416279539037749327553, [* 0, 144011430232416023815582339896989412549989 768347488282 *], [* 211210849098147497668049160549893749206993597717316020, 105450399178101325686264761693126287110561056044207590, 1 *], [* [* 46904699 32933290897429108206544459578732909701, 1 *] *] *], [* 469046993293329089742 9108206544459578732909701, 3, -1, 469046993293329089742907762757486583717810 0625, [* 0, 1729141303020103662211040662297860009845932556 *], [* 4279503455 825167114707645725600189155862415905, 56727771151198665197107813483929483109 8887428, 1 *], [* [* 38921455998794973853000704141821101, 1 *] *] *], [* 389 21455998794973853000704141821101, 3, -1, 38921455998794973550348988730912279 , [* 0, 26207296594095002258775921565431246 *], [* 1518449483101162051732781 4757004212, 17530253168429360720552211357743933, 1 *], [* [* 198076715482836 775824935827, 1 *] *] *], [* 198076715482836775824935827, 3, -1, 19807671548 2864104117986389, [* 0, 43132920423084997832168947 *], [* 478918802487290924 50069040, 45736570588545364146636989, 1 *], [* [* 31373660453195251, 1 *] *] *] *] 1 9 19 1 1 *** at top-level: primecertexport([0],1) *** ^---------------------- *** primecertexport: incorrect type in primecertexport - invalid certificate (t_VEC). *** at top-level: primecertexport([],1) *** ^--------------------- *** primecertexport: incorrect type in primecertexport - invalid certificate (t_VEC). Total time spent: 10418 pari-2.17.2/src/test/32/galoischartable0000644000175000017500000000167214676526175016256 0ustar billbill[1, 1, 1, 1]~:[1, 1, 1, 1]~:[-x + 1, -x + 1, -x + 1, -x + 1]~ [1, -1, 1, 1]~:[1, -1, 1, 1]~:[-x + 1, x + 1, -x + 1, -x + 1]~ [2, 0, -y^3 - y^2 - 1, y^3 + y^2]~:[1, -1, 1, 1]~:[x^2 - 2*x + 1, -x^2 + 1, x^2 + (y^3 + y^2 + 1)*x + 1, x^2 + (-y^3 - y^2)*x + 1]~ [2, 0, y^3 + y^2, -y^3 - y^2 - 1]~:[1, -1, 1, 1]~:[x^2 - 2*x + 1, -x^2 + 1, x^2 + (-y^3 - y^2)*x + 1, x^2 + (y^3 + y^2 + 1)*x + 1]~ [1, 1, 1, 1]~:[1, 1, 1, 1]~:[-x + 1, -x + 1, -x + 1, -x + 1]~ [1, -1, 1, 1]~:[1, -1, 1, 1]~:[-x + 1, x + 1, -x + 1, -x + 1]~ [2, 0, -y^3 - y^2 - 1, y^3 + y^2]~:[1, -1, 1, 1]~:[x^2 - 2*x + 1, -x^2 + 1, x^2 + (y^3 + y^2 + 1)*x + 1, x^2 + (-y^3 - y^2)*x + 1]~ [2, 0, y^3 + y^2, -y^3 - y^2 - 1]~:[1, -1, 1, 1]~:[x^2 - 2*x + 1, -x^2 + 1, x^2 + (-y^3 - y^2)*x + 1, x^2 + (y^3 + y^2 + 1)*x + 1]~ *** at top-level: galoischartable(S3) *** ^------------------- *** galoischartable: incorrect type in checkgroupelts (t_VEC). Total time spent: 349 pari-2.17.2/src/test/32/perm0000644000175000017500000000374614567450071014067 0ustar billbill[1, 2, 3, 4]:1:1:[Vecsmall([1]), Vecsmall([2]), Vecsmall([3]), Vecsmall([4]) ] [1, 2, 4, 3]:2:-1:[Vecsmall([1]), Vecsmall([2]), Vecsmall([3, 4])] [1, 3, 2, 4]:2:-1:[Vecsmall([1]), Vecsmall([2, 3]), Vecsmall([4])] [1, 3, 4, 2]:3:1:[Vecsmall([1]), Vecsmall([2, 3, 4])] [1, 4, 2, 3]:3:1:[Vecsmall([1]), Vecsmall([2, 4, 3])] [1, 4, 3, 2]:2:-1:[Vecsmall([1]), Vecsmall([2, 4]), Vecsmall([3])] [2, 1, 3, 4]:2:-1:[Vecsmall([1, 2]), Vecsmall([3]), Vecsmall([4])] [2, 1, 4, 3]:2:1:[Vecsmall([1, 2]), Vecsmall([3, 4])] [2, 3, 1, 4]:3:1:[Vecsmall([1, 2, 3]), Vecsmall([4])] [2, 3, 4, 1]:4:-1:[Vecsmall([1, 2, 3, 4])] [2, 4, 1, 3]:4:-1:[Vecsmall([1, 2, 4, 3])] [2, 4, 3, 1]:3:1:[Vecsmall([1, 2, 4]), Vecsmall([3])] [3, 1, 2, 4]:3:1:[Vecsmall([1, 3, 2]), Vecsmall([4])] [3, 1, 4, 2]:4:-1:[Vecsmall([1, 3, 4, 2])] [3, 2, 1, 4]:2:-1:[Vecsmall([1, 3]), Vecsmall([2]), Vecsmall([4])] [3, 2, 4, 1]:3:1:[Vecsmall([1, 3, 4]), Vecsmall([2])] [3, 4, 1, 2]:2:1:[Vecsmall([1, 3]), Vecsmall([2, 4])] [3, 4, 2, 1]:4:-1:[Vecsmall([1, 3, 2, 4])] [4, 1, 2, 3]:4:-1:[Vecsmall([1, 4, 3, 2])] [4, 1, 3, 2]:3:1:[Vecsmall([1, 4, 2]), Vecsmall([3])] [4, 2, 1, 3]:3:1:[Vecsmall([1, 4, 3]), Vecsmall([2])] [4, 2, 3, 1]:2:-1:[Vecsmall([1, 4]), Vecsmall([2]), Vecsmall([3])] [4, 3, 1, 2]:4:-1:[Vecsmall([1, 4, 2, 3])] [4, 3, 2, 1]:2:1:[Vecsmall([1, 4]), Vecsmall([2, 3])] [1922760350154212639070, -1] *** at top-level: permsign(Vecsmall([1,1])) *** ^------------------------- *** permsign: incorrect type in permsign (t_VECSMALL). *** at top-level: permsign(Vecsmall([1,2,1])) *** ^--------------------------- *** permsign: incorrect type in permsign (t_VECSMALL). *** at top-level: permorder(Vecsmall([1,2,1])) *** ^---------------------------- *** permorder: incorrect type in permorder (t_VECSMALL). *** at top-level: permcycles(Vecsmall([1,2,1])) *** ^----------------------------- *** permcycles: incorrect type in permcycles (t_VECSMALL). Total time spent: 1 pari-2.17.2/src/test/32/alglattices0000644000175000017500000001173314702763267015420 0ustar billbill1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 189971089/194100624 [[27566, 0, 12226, 0, 1278, 19660, 16330, 23653; 0, 27566, 0, 15341, 17088, 9182, 16196, 10908; 0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 2, 0, 0, 1; 0, 0, 0, 0, 0, 2, 0, 1; 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 0, 1], 1/6] [[165396, 82698, 36678, 82698, 131152, 84420, 148184, 156415; 0, 82698, 0, 4 6023, 46718, 12460, 43548, 54950; 0, 0, 3, 0, 0, 0, 2, 1; 0, 0, 0, 3, 0, 0, 2, 0; 0, 0, 0, 0, 14, 0, 4, 3; 0, 0, 0, 0, 0, 28, 0, 11; 0, 0, 0, 0, 0, 0, 1 , 0; 0, 0, 0, 0, 0, 0, 0, 1], 1/6] [[1806, 903, 978, 0, 317, 271, 250, 330; 0, 903, 0, 831, 690, 226, 810, 664; 0, 0, 3, 0, 1, 1, 1, 1; 0, 0, 0, 3, 0, 1, 0, 2; 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 2, 0, 1; 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 0, 1], 1] [[165396, 82698, 36678, 82698, 131152, 84420, 148184, 156415; 0, 82698, 0, 4 6023, 46718, 12460, 43548, 54950; 0, 0, 3, 0, 0, 0, 2, 1; 0, 0, 0, 3, 0, 0, 2, 0; 0, 0, 0, 0, 14, 0, 4, 3; 0, 0, 0, 0, 0, 28, 0, 11; 0, 0, 0, 0, 0, 0, 1 , 0; 0, 0, 0, 0, 0, 0, 0, 1], 1/60] [[1806, 903, 978, 0, 317, 271, 250, 330; 0, 903, 0, 831, 690, 226, 810, 664; 0, 0, 3, 0, 1, 1, 1, 1; 0, 0, 0, 3, 0, 1, 0, 2; 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 2, 0, 1; 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 0, 1], 1/10] [[1185338, 0, 344575, 0, 937244, 1019942, 107078, 703531; 0, 1185338, 0, 854 546, 55132, 1075074, 264290, 407310; 0, 0, 13783, 0, 0, 0, 13144, 9191; 0, 0 , 0, 13783, 0, 0, 5239, 9830; 0, 0, 0, 0, 27566, 0, 15341, 15340; 0, 0, 0, 0 , 0, 27566, 0, 12226; 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 0, 1], 3/137 83] [[86, 0, 25, 0, 0, 0, 0, 24; 0, 86, 0, 62, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 86, 0, 25, 24; 0, 0, 0, 0, 0, 86, 0, 62; 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 0, 1], 3] 1 1 [113935/6, 201011/2, -5/6, 1/6, 47/6, 5/6, 0, 1/6]~ make integral 1 1 1 1 1 integral subalg [1 0] [0 0] [0 1/2] [0 0] 1 [1 0] [0 0] [0 1] [0 0] bug in subalg when first vector is not 1 1 bug trivial intersection [Mat(1), 1] [Mat(1), 1] [Mat(1), 1] [Mat(1), 1] [[1, 0; 0, 1], 1] [[1, 0; 0, 1], 1] [[1, 0; 0, 1], 1] [[1, 0; 0, 1], 1] image of lifts in algsimpledec 1 1 1 1 1 1 1 1 1 1 1 1 1 1 lattices in al_CSA 1 1 1 examples from docu 4 64 4 64 0 1 4 1 0 1 [-2, -3, 0, 1, 2, 0, 1, 2]~ 1 1 2244004 0 0 0 1 0 1 0 bad inputs *** at top-level: alglathnf(al,0) *** ^--------------- *** alglathnf: incorrect type in alglathnf (t_INT). *** at top-level: alglathnf(al,Mat([0,0,0,0,0,0,0,0])) *** ^------------------------------------ *** alglathnf: inconsistent dimensions in alglathnf. *** at top-level: alglathnf(al,[0;0;0;0;0;0;0;0]) *** ^------------------------------- *** alglathnf: inconsistent dimensions in alglathnf. [] *** at top-level: alglathnf(al,fakemat) *** ^--------------------- *** alglathnf: incorrect type in alglathnf (t_VEC). *** at top-level: alglathnf(al,matid(8)*0) *** ^------------------------ *** alglathnf: impossible inverse in alglathnf [m does not have full rank]: [0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0]. *** at top-level: alglathnf(al,fakemat) *** ^--------------------- *** alglathnf: impossible inverse in alglathnf [m does not have full rank]: [0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 0, 1]. *** at top-level: lat=alglathnf(al,matconcat([mt*0,mt*0])) *** ^------------------------------------ *** alglathnf: inconsistent dimensions in alglathnf. *** at top-level: lat1=alglathnf(al,a) *** ^--------------- *** alglathnf: inconsistent dimensions in alglathnf. *** at top-level: print(alglatelement(al,lat1,col~)) *** ^---------------------------- *** alglatelement: incorrect type in alglatelement (t_VEC). *** at top-level: alglatmul(al,a,b) *** ^----------------- *** alglatmul: incorrect type in alglatmul [one of lat1, lat2 has to be a lattice] (t_COL). *** at top-level: algmakeintegral(mt) *** ^------------------- *** algmakeintegral: incorrect type in algmakeintegral (t_VEC). *** at top-level: algmakeintegral(mt) *** ^------------------- *** algmakeintegral: incorrect type in algmakeintegral (t_VEC). *** at top-level: algmakeintegral('x,1) *** ^--------------------- *** algmakeintegral: incorrect type in algmakeintegral (t_POL). *** at top-level: alglatmul(al,lat1,[matdiagonal([1,1,0,1,1,1,1, *** ^---------------------------------------------- *** alglatmul: incorrect type in checklat [please apply alglathnf()] (t_VEC). Total time spent: 1009 pari-2.17.2/src/test/32/interpol0000644000175000017500000000170014676526175014756 0ustar billbillx + 1 Mod(1, 7)*x + Mod(1, 7) Mod(1, 7) -1/6*x^2 + 3/2*x + 2/3 Mod(3, 7) 2.5416666666666666666666666666666666667 -5 0 0 2 Mod(0, 2) Mod(0, 2) Mod(1, 2) [0, 0] [0, x] [0, y] [0, z] [0, 0] [0, 0] [0, x] [0, y] [0, z] [0, 0] [1, 0] [1, x] [1, y] [1, z] [1, z] [x, x] [x, x] [x, x] [x, z] [x, z] [x, x] [x^2, x] [y*x, x] [x*z, z] [x*z + x, z] [-x + 1, x] [0, x] [-x + y, x] [z - x, z] [z + (-x + 1), z] -53 x^10 - 55*x^9 + 1320*x^8 - 18150*x^7 + 157773*x^6 - 902055*x^5 + 3416930*x^4 - 8409500*x^3 + 12753576*x^2 - 10628640*x + 3628800 y^10 - 55*y^9 + 1320*y^8 - 18150*y^7 + 157773*y^6 - 902055*y^5 + 3416930*y^4 - 8409500*y^3 + 12753576*y^2 - 10628640*y + 3628800 Mod(1, 11)*x^10 + Mod(10, 11) Mod(1, 11)*y^10 + Mod(10, 11) Mod(1, 13)*x^168 + Mod(12, 13) x^168 + 12 u^127 + 1 *** at top-level: polfromroots([1,x,x^2]) *** ^----------------------- *** polfromroots: incorrect priority in polfromroots: variable x <= x Total time spent: 2 pari-2.17.2/src/test/32/dirpowers0000644000175000017500000000523614676526175015150 0ustar billbill[] [] [1, 1, 1, 1] [1, 2, 3, 4] [1, 4, 9, 16] [1, 8, 27, 64] [1, 1.4142135623730950488016887242096980786, 1.73205080756887729352744634150 58723670, 2.0000000000000000000000000000000000000] 0 0 10 2.0833333333333333333333333333333333333 2.0833333333333333333333333333333333333 12.090146129863427947363219363504219501 1.9653021041108146546512931866285750493 [1.9652020181681766461565644823842534893, 0.43040854096600401209015519993282 704002] [55, 55] [0.041897577398655032585440138634963632004 + 7.84548434752766636977062596508 16782648*I, 1.2926661988939694056249568781548650166 - 1.63107319923557309956 20043464509556404*I] [-55.112930619682615066911086040019358083 - 44.44126680192827104879729279561 8935975*I, -0.41262539995889051994694841326536901919 - 1.0288981537580831472 355449945376884991*I] [698.39042616261298398261703286444592576 - 112.52248820687484746874723284542 334635*I, 1.1673120325915655539584094238809590955 - 0.1159263046041925215957 8749223122033015*I] [1.0741291135795916698696069551832231517 + 3.4684926826973844043265761284823 058565*I, 1.0741291135795916698696069551832231517 + 3.4684926826973844043265 761284823058565*I] [-8.2434414235704534132928208305554717036 - 2.448503034082522518259315843458 2455501*I, -8.2434414235704534132928208305554717036 - 2.44850303408252251825 93158434582455501*I] [25.211000631842838701970474772546238322 - 12.394392754306293173303878815239 207457*I, 25.211000631842838701970474772546238322 + 12.394392754306293173303 878815239207457*I] [-1.0903919505424645481052013370239090357 - 0.055452612662147317600450970909 611553836*I, -1.0903919505424645481052013370239090357 - 0.055452612662147317 600450970909611553836*I] [-1.0903919505424645481052013370239090357 - 0.055452612662147317600450970909 611553836*I, -1.0903919505424645481052013370239090357 + 0.055452612662147317 600450970909611553845*I] [0.24357314579371262933848001240493391315 + 5.170564927097716798784416266217 0252290*I, 0.24357314579371262933848001240493391315 - 5.17056492709771679878 44162662170252290*I] [0.24357314579371262933848001240493391315 + 5.170564927097716798784416266217 0252290*I, 0.24357314579371262933848001240493391316 - 5.17056492709771679878 44162662170252290*I] [15.739767189942602267316988599103061542 - 0.8483830921232338761109235866240 6041569*I, 15.739767189942602267316988599103061542 + 0.848383092123233876110 92358662406041569*I] [15.739767189942602267316988599103061542 - 0.8483830921232338761109235866240 6041569*I, 15.739767189942602267316988599103061542 + 0.848383092123233876110 92358662406041568*I] *** at top-level: dirpowerssum('x,1) *** ^------------------ *** dirpowerssum: incorrect type in dirpowerssum (t_POL). Total time spent: 17 pari-2.17.2/src/test/32/trans0000644000175000017500000006641114676526175014263 0ustar billbill realprecision = 2003 significant digits (2000 digits displayed) echo = 1 ? abs(-0.01) 0.01000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000 ? agm(1,2) 1.45679103104690686918643238326508197497386394322130559079417238326792645458 0250900257473712818448444328189401816036799935576243074340124511691213249952 2793768970211976726893728266666782707432902072384564600963133367494416649516 4008269322390862633767383824102548872626451365906604088758851004667281309474 3978935512911720175447186956416035641113070606125170400972745374521370401420 1441576823232389645029091322392292018630204591966775362115295609984320494009 6186133886391108403038148862815907317011423554730230353362620898683561308007 5985703121250813571733533606272496417145565136129415437696905495272776402217 1898328404019382434954163396634111712470749200493994758236553202742331569542 1876892595105619103413471250457295583940482770732998417330233202020190654108 3764475690954512308594220997449412380273230046465841574004772512701790771147 6178286660643441589473410355454995401702603050129297014707762364655074858504 2893120294754259839628734570376126531045680923276419320475962493117272367678 4849010063883831645335627155765372880260543270126668904548807658246837332956 7456063204392060008273159252979241205175727929568980698371820180811180125021 3108997246951100317036787543001787446227930192106015685776149083936743191510 5478717272782446538831715921363968336746689231345994523668360452657260101103 3970534995271323625630073974543738138730451563908543487241207008447748794693 7515044344604858428093017239592603673212918887571985640286492629881099516041 7385214470404976503137921156910217010840121652176385776278443131535045190731 0748437504378670908384466987679450508904899924299954903140622820681590930451 6140452345824869722715061998188837843566441517471116059500690242314345907596 6810454416997061373268370421830924936517791683419258027937814913005585514983 9054216129918366396073532425917284089191304056017436113358867622552811309835 6883812066118653768412057434259281956810028485877428124011968982035483804304 1113162808407169939503577633814675423251711145297625856010709698328986771681 3002707534621244314382491 ? agm(1+O(7^5),8+O(7^5)) 1 + 4*7 + 6*7^2 + 5*7^3 + 2*7^4 + O(7^5) ? 4*arg(3+3*I) 3.14159265358979323846264338327950288419716939937510582097494459230781640628 6208998628034825342117067982148086513282306647093844609550582231725359408128 4811174502841027019385211055596446229489549303819644288109756659334461284756 4823378678316527120190914564856692346034861045432664821339360726024914127372 4587006606315588174881520920962829254091715364367892590360011330530548820466 5213841469519415116094330572703657595919530921861173819326117931051185480744 6237996274956735188575272489122793818301194912983367336244065664308602139494 6395224737190702179860943702770539217176293176752384674818467669405132000568 1271452635608277857713427577896091736371787214684409012249534301465495853710 5079227968925892354201995611212902196086403441815981362977477130996051870721 1349999998372978049951059731732816096318595024459455346908302642522308253344 6850352619311881710100031378387528865875332083814206171776691473035982534904 2875546873115956286388235378759375195778185778053217122680661300192787661119 5909216420198938095257201065485863278865936153381827968230301952035301852968 9957736225994138912497217752834791315155748572424541506959508295331168617278 5588907509838175463746493931925506040092770167113900984882401285836160356370 7660104710181942955596198946767837449448255379774726847104047534646208046684 2590694912933136770289891521047521620569660240580381501935112533824300355876 4024749647326391419927260426992279678235478163600934172164121992458631503028 6182974555706749838505494588586926995690927210797509302955321165344987202755 9602364806654991198818347977535663698074265425278625518184175746728909777727 9380008164706001614524919217321721477235014144197356854816136115735255213347 5741849468438523323907394143334547762416862518983569485562099219222184272550 2542568876717904946016534668049886272327917860857843838279679766814541009538 8378636095068006422512520511739298489608412848862694560424196528502221066118 6306744278622039194945047123713786960956364371917287467764657573962413890865 8326459958133904780275901 ? bernreal(12) -0.2531135531135531135531135531135531135531135531135531135531135531135531135 5311355311355311355311355311355311355311355311355311355311355311355311355311 3553113553113553113553113553113553113553113553113553113553113553113553113553 1135531135531135531135531135531135531135531135531135531135531135531135531135 5311355311355311355311355311355311355311355311355311355311355311355311355311 3553113553113553113553113553113553113553113553113553113553113553113553113553 1135531135531135531135531135531135531135531135531135531135531135531135531135 5311355311355311355311355311355311355311355311355311355311355311355311355311 3553113553113553113553113553113553113553113553113553113553113553113553113553 1135531135531135531135531135531135531135531135531135531135531135531135531135 5311355311355311355311355311355311355311355311355311355311355311355311355311 3553113553113553113553113553113553113553113553113553113553113553113553113553 1135531135531135531135531135531135531135531135531135531135531135531135531135 5311355311355311355311355311355311355311355311355311355311355311355311355311 3553113553113553113553113553113553113553113553113553113553113553113553113553 1135531135531135531135531135531135531135531135531135531135531135531135531135 5311355311355311355311355311355311355311355311355311355311355311355311355311 3553113553113553113553113553113553113553113553113553113553113553113553113553 1135531135531135531135531135531135531135531135531135531135531135531135531135 5311355311355311355311355311355311355311355311355311355311355311355311355311 3553113553113553113553113553113553113553113553113553113553113553113553113553 1135531135531135531135531135531135531135531135531135531135531135531135531135 5311355311355311355311355311355311355311355311355311355311355311355311355311 3553113553113553113553113553113553113553113553113553113553113553113553113553 1135531135531135531135531135531135531135531135531135531135531135531135531135 5311355311355311355311355311355311355311355311355311355311355311355311355311 355311355311355311355311355 ? bernvec(6) [1, 1/6, -1/30, 1/42, -1/30, 5/66, -691/2730] ? eta(q) 1 - q - q^2 + q^5 + q^7 - q^12 - q^15 + O(q^17) ? gammah(10) 1133278.38894878556733457416558889247556029830827515977660872341452948339005 6004153717630538727607290658350271700893237334889580173178076577597995379664 6009714415152490764416630481375706606053932396039541459764525989187023837695 1671610855238044170151137400635358652611835795089229729903867565432085491785 4385740637379886563030379410949122020517030255827739818376409926875136586189 2723863412249690833216320407918186480305202146014474770321625907339955121137 5592642390902407584016964257200480120814533383602757695668466603948271024098 9327940404023866529740516995285324916879158647845355052036653927090566136730 0094575478250332011940143726954935586482054200041299507288301750480889450074 6343904971296912338686722783533463981407672637863409944118391772608796763236 9447079178552767334696553209914181695759970997941993901164691598147347830004 4823839605663115658079374350293361148126253885222073444191541294051101114944 2148757269775793389728426903218921936202601614618932645339512192242743521391 3623655029508006651504215607326378350230912034475135438952688674605137188671 8291478726407002040566684129567384943465438236552781293212272474626739330722 3823357944724162685811265841905467657996783321819427448381523647154314724898 8856361879313902224622692050075011483135711717132961476630033785190129658511 7517708668749218485078393526224163290497667641778463362558549256811856160652 4106684792418747471383982225174086085681964985490608637796815226536639176681 1441751691654768874563756211537865821827254193841183086848150171014212517613 4162649414056791266931385305249721381461657257845049119527820872404022311592 3493153739717855496390762049815239940623016182617392553134094087438136687759 5419535805662758475769269988659439227267578534611414012815013931015921875970 6336658641047462598114625941565529553227923237890531007539153745378752638260 5084066808355122734552729235496172099847732335381840125710668124155748264901 6432532465927671474115401431858884909633728259417038958526362232126251606829 1066841997114282966060548 ? Pi 3.14159265358979323846264338327950288419716939937510582097494459230781640628 6208998628034825342117067982148086513282306647093844609550582231725359408128 4811174502841027019385211055596446229489549303819644288109756659334461284756 4823378678316527120190914564856692346034861045432664821339360726024914127372 4587006606315588174881520920962829254091715364367892590360011330530548820466 5213841469519415116094330572703657595919530921861173819326117931051185480744 6237996274956735188575272489122793818301194912983367336244065664308602139494 6395224737190702179860943702770539217176293176752384674818467669405132000568 1271452635608277857713427577896091736371787214684409012249534301465495853710 5079227968925892354201995611212902196086403441815981362977477130996051870721 1349999998372978049951059731732816096318595024459455346908302642522308253344 6850352619311881710100031378387528865875332083814206171776691473035982534904 2875546873115956286388235378759375195778185778053217122680661300192787661119 5909216420198938095257201065485863278865936153381827968230301952035301852968 9957736225994138912497217752834791315155748572424541506959508295331168617278 5588907509838175463746493931925506040092770167113900984882401285836160356370 7660104710181942955596198946767837449448255379774726847104047534646208046684 2590694912933136770289891521047521620569660240580381501935112533824300355876 4024749647326391419927260426992279678235478163600934172164121992458631503028 6182974555706749838505494588586926995690927210797509302955321165344987202755 9602364806654991198818347977535663698074265425278625518184175746728909777727 9380008164706001614524919217321721477235014144197356854816136115735255213347 5741849468438523323907394143334547762416862518983569485562099219222184272550 2542568876717904946016534668049886272327917860857843838279679766814541009538 8378636095068006422512520511739298489608412848862694560424196528502221066118 6306744278622039194945047123713786960956364371917287467764657573962413890865 8326459958133904780275901 ? precision(Pi,38) 3.14159265358979323846264338327950288420 ? sqr(1+O(2)) 1 + O(2^3) ? sqrt(13+O(127^12)) 34 + 125*127 + 83*127^2 + 107*127^3 + 53*127^4 + 42*127^5 + 22*127^6 + 98*12 7^7 + 127^8 + 23*127^9 + 122*127^10 + 79*127^11 + O(127^12) ? teichmuller(7+O(127^12)) 7 + 57*127 + 58*127^2 + 83*127^3 + 52*127^4 + 109*127^5 + 74*127^6 + 16*127^ 7 + 60*127^8 + 47*127^9 + 65*127^10 + 5*127^11 + O(127^12) ? \p500 realprecision = 500 significant digits ? Catalan 0.91596559417721901505460351493238411077414937428167213426649811962176301977 6254769479356512926115106248574422619196199579035898803325859059431594737481 1584069953320287733194605190387274781640878659090247064841521630002287276409 4238825995774150881639747025248201156070764488380787337048990086477511322599 7134340748540755323076856533576809583526021938232395080072068035576104823573 3942319149829836189977069036404180862179411019175327431499782339761055122477 9530324875371878665828082360570225594194818097 ? Euler 0.57721566490153286060651209008240243104215933593992359880576723488486772677 7664670936947063291746749514631447249807082480960504014486542836224173997644 9235362535003337429373377376739427925952582470949160087352039481656708532331 5177661152862119950150798479374508570574002992135478614669402960432542151905 8775535267331399254012967420513754139549111685102807984234877587205038431093 9973613725530608893312676001724795378367592713515772261027349291394079843010 3417771778088154957066107501016191663340152279 ? acos(0.5) 1.04719755119659774615421446109316762806572313312503527365831486410260546876 2069666209344941780705689327382695504427435549031281536516860743908453136042 8270391500947009006461737018532148743163183101273214762703252219778153761585 4941126226105509040063638188285564115344953681810888273779786908674971375790 8195668868771862724960506973654276418030571788122630863453337110176849606822 1737947156506471705364776857567885865306510307287057939775372643683728493581 541266542498557839619175749637426460610039831 ? acosh(3) 1.76274717403908605046521864995958461805632065652327082150659121730675436844 4052175667413783820512085713479632384212984377524145023953183875054510925531 5808184431573607257943924806147148192510979557431265247356130135260657908083 2711638011905460870335948934683023103172356012785221262668194525145789831496 9445764001529311893860982812579887622449034763169345542526389217689105106337 1787365189299048490338319777210134365908031791918295896639410019154526845141 480345838118685682417318463628901744528191443 ? 3*asin(sqrt(3)/2) 3.14159265358979323846264338327950288419716939937510582097494459230781640628 6208998628034825342117067982148086513282306647093844609550582231725359408128 4811174502841027019385211055596446229489549303819644288109756659334461284756 4823378678316527120190914564856692346034861045432664821339360726024914127372 4587006606315588174881520920962829254091715364367892590360011330530548820466 5213841469519415116094330572703657595919530921861173819326117931051185480744 623799627495673518857527248912279381830119491 ? asinh(0.5) 0.48121182505960344749775891342436842313518433438566051966101816884016386760 8221774412009429122723474997231839958293656411272568323726737622753059241864 4097541824170072118371502238239374691872752432791930187970790035617267969445 4575230534543418876528553256490207399693496618755630102123996367930820635997 7988509980156825797852649328666651116241713808272592788479026096533113247227 5149314064985088932176366002566661953210679681757661847307351598603984845754 5412056323413570047800639487224315261789680045 ? 3*atan(sqrt(3)) 3.14159265358979323846264338327950288419716939937510582097494459230781640628 6208998628034825342117067982148086513282306647093844609550582231725359408128 4811174502841027019385211055596446229489549303819644288109756659334461284756 4823378678316527120190914564856692346034861045432664821339360726024914127372 4587006606315588174881520920962829254091715364367892590360011330530548820466 5213841469519415116094330572703657595919530921861173819326117931051185480744 623799627495673518857527248912279381830119491 ? atanh(0.5) 0.54930614433405484569762261846126285232374527891137472586734716681874714660 9304483436807877406866044393985014532978932871184002112965259910526400935383 6387053015813845916906835896868494221804799518712851583979557605727959588753 3567352747008338779011110158512647344878034505326075282143406901815868664928 8891183495827396065909074510015051911815061124326374099112995548726245448229 0267335044229825428742220595094285438237474335398065429147058010830605920007 0491275719597438444683992471511278657676648427 ? besseljh(1,1) 0.24029783912342701089584304474193368045758480608072900860700721913956804181 9821642483230581867706826873304134469286897059613333800107373387969440858132 2409671228346463513063730101700769785661236389472736777787130860593313537501 4950471611773181090861874975058165031596147120593670107339079838226694509538 1174862561382806604491442967609698710345402983618630021989455840750069855186 9089492304665506543890102558566214670131694260158621630986009048855189842820 0103186464147214505293464124112486584095535336 ? cos(1) 0.54030230586813971740093660744297660373231042061792222767009725538110039477 4471764517951856087183089343571731160030089097860633760021663456406512265417 3185847179711644744794942331179245513932543359435177567028925963757361543275 4964175449177511513122273010063135707823223677140151746899593667873067422762 0245077637440675874981617842720216455851115632968890571081242729331698685247 1456894904342375433094423024093596239583182454728173664078071243433621748100 3220271297578822917644683598726994264913443918 ? cosh(1) 1.54308063481524377847790562075706168260152911236586370473740221471076906304 9223698964264726435543035587046858604423527565032194694709586290763493942377 3472069151633480026408029059364105029494057980033657762593319443209506958499 1368981037430548471273929845616039038581747145363600451873630682751434880120 2720574972705524471670706447103271142282939448411677273102139632958667273012 2826261409857215459162042522453939258584439199475134380734969475319971032521 055637731102374474158960765443652715148207669 ? exp(1) 2.71828182845904523536028747135266249775724709369995957496696762772407663035 3547594571382178525166427427466391932003059921817413596629043572900334295260 5956307381323286279434907632338298807531952510190115738341879307021540891499 3488416750924476146066808226480016847741185374234544243710753907774499206955 1702761838606261331384583000752044933826560297606737113200709328709127443747 0472306969772093101416928368190255151086574637721112523897844250569536967707 854499699679468644549059879316368892300987931 ? exp(1.123) 3.07406257154898987680161138009760625104248179708261339399712186197767466996 4935625311477807765382361174054209564400933143178772679923822312458571526893 0949675915002937652898704613739372482459452568993085662295138072557500421797 5971600253639265100975969190654549368799844236165029593059925114588814911583 9185488320031389051117206437605098919216790228388886978184284707042848120462 1182818728513135542290354814654148922271957843494116542832234810156127014491 955053641170027738831683277094167546025000529 ? incgam(4,1,6) 5.88607105874307714552838032258337387913297809650828535212538882715938393191 8396853714356389534714299946037204429503923331951612684642064138026457431905 5805294751098780374098407782238580023298615198035196589516153270359568407982 7992725182985932743696823436032979670756942663882506560584119323653928852565 9814209708876601791309278295271957611829097587465878928057118995331313636440 2883453599077405070514506827481973857316860179666499801153515201126481557348 108412200404484860301786425134984607926838502 ? incgamc(2,1) 0.26424111765711535680895245967707826510837773793646433098432639660507700851 0200393285705451308160712506745349446312009583506048414419741982746692821011 8024338156112652453237699027220177497087673100245600426310480841205053949002 1500909352126758407037897070495877541155382167014686679926985084543258893429 2523223786390424776086340213091005298521362801566765133992860125583585795444 9639568300115324366185686646564753267835392477541687524855810599859189805331 4864484749494393924622766968581269240091451873 ? log(2) 0.69314718055994530941723212145817656807550013436025525412068000949339362196 9694715605863326996418687542001481020570685733685520235758130557032670751635 0759619307275708283714351903070386238916734711233501153644979552391204751726 8157493206515552473413952588295045300709532636664265410423915781495204374043 0385500801944170641671518644712839968171784546957026271631064546150257207402 4816377733896385506952606683411372738737229289564935470257626520988596932019 6505855476470330679365443254763274495125040607 ? sin(Pi/6) 0.50000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000 ? sinh(1) 1.17520119364380145688238185059560081515571798133409587022956541301330756730 4323895607117452089623391840419533327579532356785218901919457282136840352883 2484238229689806253026878572974193778037894530156457975748559863812033933000 2119435713493927674792878380863977809159438228870943791837123225023064326834 8982186865900736859713876553648773791543620849195059840098569695750460170734 7646045559914877642254885845736315892502135438245978143162874775249565935186 798861968577094170390099113872716177152780263 ? sqr(tan(Pi/3)) 3.00000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000 ? tanh(1) 0.76159415595576488811945828260479359041276859725793655159681050012195324457 6638483458947521673676714421902759701554077532368309114762485413297006669611 3211253965101376080877764393409926042066795531174758011305900662577831975245 1237997591796119707757354591410814335043351567518059703276048802963895774140 4110555282743457474128870116732022433666141820426521385314984008017809424940 5971665020197077111278076211510055741702778683601321201082307883017522102475 0850545493659202265152413525903793814306804484 ? thetanullk(0.5,7) -804.63037320243369422783730584965684022502842525603918290428537089203649185 3005202838354617419978916066838351498344792388634514250685494567531066970308 1395985000299687911464724641787835671746030420666636980738176244141521534964 5910468287548147547821547802569972386188420035275376210374637455233928908304 8519707951113024675783203592515011343853492633432924541927657918744234297707 8009339159045897789510058204677594956471190358977738843586880213576194151544 6040652826323066997075899093444932117587282486 ? \p210 realprecision = 211 significant digits (210 digits displayed) ? dilog(0.5) 0.58224052646501250590265632015968010874419847480612642543434704787317104407 1683200816840318587915857185644360650489146599186798136823369642378773825725 010992996274322284433100379999291599248198351965163954430361 ? eint1(2) 0.04890051070806111956723983522804952231449218496302311632732287371169292871 4152191279268961007451641767339733440496339126093474911387068904573480132428 0606565260878276314803271231475388617592828799527149833070515 ? lngamma(10^50*I) -157079632679489661923132169163975144209858469968811.93673753887608474948977 0941153418951907406847934940095420371647821881900698782085734298414871973667 351244826946727013485797329023211606491949054831345082284018 + 1141292546497 0228420089957273421821038005507443143864.09476847610738955343272591658130426 4976155641647932550343141949832879612722439831043441291767982893579577059574 3877177782974245137531522747279687821610884364*I ? polylog(5,0.5) 0.50840057924226870745910884925858994131954112566482164872449779635262539422 8780242619384210049344955062253148566177885373776251290109126927256295587733 653575441097747430180753135597085935261518462072899907112039 ? polylog(-4,t) (-t^4 - 11*t^3 - 11*t^2 - t)/(t^5 - 5*t^4 + 10*t^3 - 10*t^2 + 5*t - 1) ? polylog(5,0.5,1) 1.03379274554168906408344764673478841754654188263517803810922886849674521856 8302490767987790059233900087664928281011147504065464055196977752510643903051 08453214093020806938180803753912648028281347292317330014656 ? polylog(5,0.5,2) 1.03445942344901048625461825783418822628308099519811715037388226488478462874 5613316541842884367897989911634714028478465772399056966065341954518002332809 93803867195735501893802985262734041524337126856608372430479 ? polylog(5,0.5,3) 0.94956934899649226018699647701016092398772870595673235481511016276008056001 9780143078976018486726179185715990894178927384257428042889858760164776911430 334108913396327982261675208743365007260765477862866539420350 ? psi(1) -0.5772156649015328606065120900824024310421593359399235988057672348848677267 7766467093694706329174674951463144724980708248096050401448654283622417399764 4923536253500333742937337737673942792595258247094916008735204 ? round(prod(k=1,17,x-exp(2*I*Pi*k/17)),&e) x^17 - 1 ? e -693 ? theta(0.5,3) 0.08080641825189469129987168321046629852436630463736585818145355698789812007 7007090242373481570553349455066987093523256662570622075796055596272586626054 1756288186798491280103427257359418016911094472073083250230198 ? weber(I) 1.18920711500272106671749997056047591529297209246381741301900222471946666822 6917159870781344538137673716037394774769213186063726361789847756785360862538 01777507015151140355709227316234286888992417544607190871050 ? weber(I,1) 1.09050773266525765920701065576070797899270271854006712178566764768330053084 8841840338211140494203119891451619262918090010347769026116087255320275930582 70136445935603377184958072509793552467405409688916300069889 ? weber(I,2) 1.09050773266525765920701065576070797899270271854006712178566764768330053084 8841840338211140494203119891451619262918090010347769026116087255320275930582 70136445935603377184958072509793552467405409688916300069889 ? zeta(3) 1.20205690315959428539973816151144999076498629234049888179227155534183820578 6313090186455873609335258146199157795260719418491995998673283213776396837207 90016145394178294936006671919157552224249424396156390966410 ? \p38 realprecision = 38 significant digits ? besselk(1+I,1) 0.32545977186584141085464640324923711950 + 0.2894280370259921276345671592415 2302743*I ? erfc(2) 0.0046777349810472658379307436327470713891 ? gamma(10.5) 1133278.3889487855673345741655888924756 ? hyperu(1,1,1) 0.59634736232319407434107849936927937607 ? incgam(2,1) 0.73575888234288464319104754032292173489 ? zeta(0.5+14.1347251*I) 5.2043097453468479398562848599360610966 E-9 - 3.2690639869786982176409251733 763732423 E-8*I ? if(getheap()!=HEAP,getheap()) ? print("Total time spent: ",gettime); Total time spent: 10 pari-2.17.2/src/test/32/modpr0000644000175000017500000001027114760123736014234 0ustar billbill *** at top-level: nfeltmulmodpr(nfinit(x),x,x,1) *** ^------------------------------ *** nfeltmulmodpr: incorrect type in checkprid (t_INT). [0, 1, error("inconsistent variables in poltobasis, t != y."), 1, error("inc onsistent variables in poltobasis, z != y."), 0, error("incorrect type in Rg _to_ff (t_COL).")] y^2 + 1: [1, [1, 1], [2, [1, 1]~, 2, 1, [1, -1; 1, 1]]]~ *[1, 1]: error("impossible inverse in F2xq_inv: 0.") 0 *[1, 2]: 0 0 *[1, 3]: 0 0 *[1, 4]: error("impossible inverse in F2xq_inv: 0.") 0 *[2, 2]: 1 1 *[2, 3]: 1 1 *[2, 4]: error("impossible inverse in F2xq_inv: 0.") 0 *[3, 3]: 1 1 *[3, 4]: error("impossible inverse in F2xq_inv: 0.") 0 *[4, 4]: error("impossible inverse in F2xq_inv: 0.") 0 *1: [0, 0]~ *2: [1, 0]~ *3: error("inconsistent variables in poltobasis, t != y.") *4: [1, 0]~ *5: error("inconsistent variables in poltobasis, z != y.") *6: [0, 0]~ *7: error("incorrect type in Rg_to_ff (t_COL).") [0, error("impossible inverse in Fl_inv: Mod(0, 3)."), error("inconsistent v ariables in poltobasis, t != y."), t, error("inconsistent variables in polto basis, z != y."), error("impossible inverse in Rg_to_ff: Mod(0, 3)."), error ("incorrect type in Rg_to_ff (t_COL).")] y^2 + 1: [1, [1, 0; 0, 1], [3, [3, 0]~, 1, 2, 1], t^2 + 1]~ *[1, 1]: error("impossible inverse in Flxq_inv: 0.") 0 *[1, 2]: 0 0 *[2, 2]: 1 2 *1: [0, 0]~ *2: error("impossible inverse in Fl_inv: Mod(0, 3).") *3: error("inconsistent variables in poltobasis, t != y.") *4: error("inconsistent variables in poltobasis, t != y.") *5: error("inconsistent variables in poltobasis, z != y.") *6: error("impossible inverse in Rg_to_ff: Mod(0, 3).") *7: error("incorrect type in Rg_to_ff (t_COL).") [0, error("impossible inverse in Fl_inv: Mod(0, 3)."), error("inconsistent v ariables in poltobasis, t != y."), 0, error("inconsistent variables in polto basis, z != y."), error("incorrect type in Rg_to_ff (t_COL)."), error("impos sible inverse in Rg_to_ff: Mod(0, 3).")] y^3 - 9: [1, [1, 0, 0], [3, [0, 1, 0]~, 3, 1, [0, 3, 0; 0, 0, 3; 1, 0, 0]]]~ *[1, 1]: error("impossible inverse in Flxq_inv: 0.") 0 *[1, 2]: error("impossible inverse in Flxq_inv: 0.") 0 *[2, 2]: error("impossible inverse in Flxq_inv: 0.") 0 *1: [0, 0, 0]~ *2: error("impossible inverse in Fl_inv: Mod(0, 3).") *3: error("inconsistent variables in poltobasis, t != y.") *4: [0, 0, 0]~ *5: error("inconsistent variables in poltobasis, z != y.") *6: error("incorrect type in Rg_to_ff (t_COL).") *7: error("impossible inverse in Rg_to_ff: Mod(0, 3).") 1 0 0 [0, 1, error("inconsistent variables in poltobasis, t != y."), t, error("inc onsistent variables in poltobasis, z != y."), error("incorrect type in Rg_to _ff (t_COL)."), 0] y^3 - 9: [[0, -1, -1]~, [1, 1, 0; 0, 1, 1], [2, [1, 1, 1]~, 1, 2, [1, 3, 0; 0, 1, 3; 1, 0, 1]], t^2 + t + 1]~ *[1, 1]: error("impossible inverse in F2xq_inv: 0.") 0 *[1, 2]: 0 0 *[1, 3]: 0 0 *[1, 4]: error("impossible inverse in F2xq_inv: 0.") 0 *[2, 2]: 1 1 *[2, 3]: t + 1 t *[2, 4]: error("impossible inverse in F2xq_inv: 0.") 0 *[3, 3]: 1 t + 1 *[3, 4]: error("impossible inverse in F2xq_inv: 0.") 0 *[4, 4]: error("impossible inverse in F2xq_inv: 0.") 0 *1: [0, 0, 0]~ *2: [1, 0, 0]~ *3: error("inconsistent variables in poltobasis, t != y.") *4: error("inconsistent variables in poltobasis, t != y.") *5: error("inconsistent variables in poltobasis, z != y.") *6: error("incorrect type in Rg_to_ff (t_COL).") *7: error("inconsistent variables in poltobasis, t != y.") y [1, 0]~ [x + 1 3] 1 [1, 1]~ [;] [0, 1]~ [1 1] [1 1] [1] [1] *** at top-level: LI(matsolve(m,v)) *** ^-------------- *** matsolve: impossible inverse in gauss: [1, 1; 1, 1]. *** at top-level: LI(matsolve(m,m)) *** ^-------------- *** matsolve: impossible inverse in gauss: [1, 1; 1, 1]. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]~ *** at top-level: nfmodpr(nfinit(x),[],[]~) *** ^------------------------- *** nfmodpr: incorrect type in checkprid (t_COL). 2*t 2*y *** at top-level: nfmodpr(Kerr,[y,2;y^2/9,3],Perr) *** ^-------------------------------- *** nfmodpr: impossible inverse in Rg_to_ff: Mod(0, 3). Total time spent: 84 pari-2.17.2/src/test/32/time0000644000175000017500000000003414567450071014045 0ustar billbill1 1 1 1 Total time spent: 0 pari-2.17.2/src/test/32/intnumosc0000644000175000017500000000041014676526175015136 0ustar billbill realprecision = 115 significant digits 1/2 [1/2, 1/2, 3/8, 1/3, 115/384, 11/40, 5887/23040, 151/630, 259723/1146880, 15 619/72576] [3/8, 1/3, 115/384, 11/40, 5887/23040, 151/630, 259723/1146880, 15619/72576] 1: -384 -384 2: -385 3: -384 Total time spent: 14865 pari-2.17.2/src/test/32/analyz0000644000175000017500000000033514567450071014411 0ustar billbill echo = 1 ? sum(x=0,50000,x); ? sum(x=1,1000,log(x)); ? sum(x=1,25,sum(y=1,100,x/y),0.0); ? sum(x=1,100,sum(y=1,100,x/y,0.0)); ? if(getheap()!=HEAP,getheap()) ? print("Total time spent: ",gettime); Total time spent: 17 pari-2.17.2/src/test/32/cxtrigo0000644000175000017500000000104214567450071014566 0ustar billbillatan: 0.0 + I*-1.0 is a pole ? atan: 0.0 + I*1.0 is a pole ? atanh: -1.0 + I*0.0 is a pole ? atanh: 1.0 + I*0.0 is a pole ? 0.E-1155 0.E-1155 0.E-1155 0.E-1155 0.E-1155 0.E-1155 1.1702607277107686407657936407619050318 -1.3130352854993313036361612469308478329*I 0.27390375020968549781950404333381912154 - 1.0057146343488479442511142161269 763393*I 1.5574077246549022305069748074583601731*I 5.4210108624275221700372640043497085571 E-20 - 1.570796326794896619231321691 6397514421*I 1.6263032587282566510111792013049125672 E-19 Total time spent: 137 pari-2.17.2/src/test/32/round40000644000175000017500000004103014676526175014335 0ustar billbill *** Warning: new stack size = 10000000 (9.537 Mbytes). 1 disc = 691051969765063543658256000000000000 2 disc = 31088519960728128454656000000000000 3 disc = 1802370734536 4 disc = 654752768 5 disc = -58773124044 6 disc = 11378694989371408384 7 disc = -48269476692516748870958029675063944413184 8 disc = 1461501637330902918203684832716283019655932542976 9 disc = 1346286087882789617664 10 disc = 193428131138340667952988160000000000000000 11 disc = 11378694989371408384 12 disc = 144 13 disc = 442050625 14 disc = 12008989 15 disc = 16974593 16 disc = 31554496 17 disc = 33076161 18 disc = 11574317056 19 disc = 10368641602001 20 disc = 39213900625 21 disc = 103161709 22 disc = 105823817 23 disc = 65037750625 24 disc = 73116160000 25 disc = 183250432 26 disc = 21292697885552828353 27 disc = 213813760000 28 disc = 225360027841 29 disc = 114655968874330129 30 disc = 393832837 31 disc = 440711081 32 disc = 364488705441 33 disc = 370150560000 34 disc = 234001122366390625 35 disc = 395451064801 36 disc = 364007458703857 37 disc = 497871360000 38 disc = 588865925376 39 disc = 709732288 40 disc = 647395642881 41 disc = 659020863601 42 disc = 446012924483368791310336 43 disc = 670801950625 44 disc = 728933458176 45 disc = 689869781056000000 46 disc = 913308254830140625 47 disc = 979146657 48 disc = 1064726745878753869969 49 disc = 1048772096 50 disc = 1082432160000 51 disc = 1192518600625 52 disc = 1559914552888693 53 disc = 1442919878656 54 disc = 1334633301 55 disc = 1490902050625 56 disc = 2980200459393400813138329769 57 disc = 1718786550625 58 disc = 1810639360000 59 disc = 1835743170816 60 disc = 2222606887281 61 disc = 1856331989 62 disc = 1986121593 63 disc = 2752095195136 64 disc = 2786442301696 65 disc = 2217342464 66 disc = 2972069112961 67 disc = 3035957760000 68 disc = 5920163568466890625 69 disc = 3471607400625 70 disc = 2588282117 71 disc = 7027753833487138816 72 disc = 5245121853990193 73 disc = 5958832035878149 74 disc = 2961169856 75 disc = 4797852160000 76 disc = 3301293169 77 disc = 3436115229 78 disc = 5922408960000 79 disc = 42098158229810084367630336 80 disc = 26961206542479413771201 81 disc = 7233948160000 82 disc = 11899888859544201 83 disc = 7909194404241 84 disc = 24827168863016095744 85 disc = 9082363580416 86 disc = 9272177250625 87 disc = 9421854806016 88 disc = 16696389126347776 89 disc = 52518884338097360421921 90 disc = 30232096024977015625 91 disc = 5564051648 92 disc = 10971993760000 93 disc = 12625407900625 94 disc = 24566124836069257 95 disc = 6869835701 96 disc = 7177888089 97 disc = 13932481925376 98 disc = 52817485810944986209 99 disc = 7495014493 100 disc = 31681277442558976 101 disc = 71415925156555415437890625 102 disc = 9166361760000 103 disc = 103063708057575099687890625 104 disc = 17471883970840462300304775614373553 105 disc = 95468057368868913808408576 106 disc = 17515230173 107 disc = 62523502209 108 disc = 62523502209 109 disc = 74724856128 110 disc = 80174499328 111 disc = 183637853504 112 disc = 326371204125 113 disc = 376367048000 114 disc = 567869252041 115 disc = 567869252041 116 disc = 688231506789 117 disc = 899470488077 118 disc = 941192000000 119 disc = 998800479936 120 disc = 1095593933629 121 disc = 1488181848713 122 disc = 2565164201769 123 disc = 2565164201769 124 disc = 2694903759296 125 disc = 2704209893568 126 disc = 3151307486781 127 disc = 3338010958625 128 disc = 3471072448221 129 disc = 4007556327104 130 disc = 4624076296000 131 disc = 4831094417625 132 disc = 5534900853769 133 disc = 5534900853769 134 disc = 6056434988352 135 disc = 6080389219008 136 disc = 6636193049088 137 disc = 7100029448000 138 disc = 7534146860864 139 disc = 7720128615744 140 disc = 8606302763157 141 disc = 9288810792261 142 disc = 9750967476544 143 disc = 10229618526912 144 disc = 10367362235125 145 disc = 15883285246353 146 disc = 18243373078125 147 disc = 18525482136000 148 disc = 18753251922432 149 disc = 20339710127073 150 disc = 21673299838841 151 disc = 21682629379125 152 disc = 22454408824128 153 disc = 22454408824128 154 disc = 22454408824128 155 disc = 22886952012288 156 disc = 24907321081664 157 disc = 24991851015053 158 disc = 25002110044521 159 disc = 25002110044521 160 disc = 25032903977277 161 disc = 27100023260653 162 disc = 29698839199232 163 disc = 31033149890625 164 disc = 31033149890625 165 disc = 31033149890625 166 disc = 32012033131008 167 disc = 32795655776729 168 disc = 32795655776729 169 disc = 32795655776729 170 disc = 32795655776729 171 disc = 33252674173893 172 disc = 33823616904000 173 disc = 35861911358833 174 disc = 37156053182409 175 disc = 37166075494848 176 disc = 40509102979584 177 disc = 45990453983552 178 disc = 50722851083913 179 disc = 51035911843357 180 disc = 51895117000000 181 disc = 51895117000000 182 disc = 52464835537856 183 disc = 57566111236928 184 disc = 57566111236928 185 disc = 64867893832000 186 disc = 68443024217625 187 disc = 70608870146368 188 disc = 70608870146368 189 disc = 70608870146368 190 disc = 73792042960384 191 disc = 78496212952513 192 disc = 78496212952513 193 disc = 78496212952513 194 disc = 78496212952513 195 disc = 80018416634688 196 disc = 81272764978496 197 disc = 83780436119093 198 disc = 88812049936896 199 disc = 91343875006656 200 disc = 93113668703125 201 disc = 95343780573504 202 disc = 95343780573504 203 disc = 95550545616813 204 disc = 100856310518592 205 disc = 100856310518592 206 disc = 101481612657984 207 disc = 102588675089797 208 disc = 102792615579584 209 disc = 104413920565969 210 disc = 104413920565969 211 disc = 106712258605568 212 disc = 109627139656000 213 disc = 109627139656000 214 disc = 109627139656000 215 disc = 117102420633024 216 disc = 121935391665472 217 disc = 124460777226752 218 disc = 130323843000000 219 disc = 131197182717797 220 disc = 131623667572032 221 disc = 142114065431625 222 disc = 143318415538368 223 disc = 148203857088000 224 disc = 154888759857664 225 disc = 155625375008069 226 disc = 160032253665088 227 disc = 160315392124224 228 disc = 160315392124224 229 disc = 160315392124224 230 disc = 163963718650837 231 disc = 164206490176000 232 disc = 168855627483648 233 disc = 172808693000000 234 disc = 172808693000000 235 disc = 182284263000000 236 disc = 190983561521472 237 disc = 190983561521472 238 disc = 190983561521472 239 disc = 205849293516125 240 disc = 207390588005888 241 disc = 219747465563625 242 disc = 227081481823729 243 disc = 227081481823729 244 disc = 238374130976064 245 disc = 238374130976064 246 disc = 238374130976064 247 disc = 239853467163968 248 disc = 240421391475741 249 disc = 244152343937501 250 disc = 244152343937501 251 disc = 244152343937501 252 disc = 245832015985984 253 disc = 245832015985984 254 disc = 245832015985984 255 disc = 250380544197952 256 disc = 250380544197952 257 disc = 250380544197952 258 disc = 264856663448000 259 disc = 266306899520753 260 disc = 266953144495869 261 disc = 268036698442176 262 disc = 280342627195392 263 disc = 284124652664021 264 disc = 286295419093312 265 disc = 286295419093312 266 disc = 286295419093312 267 disc = 292979858533713 268 disc = 293019561288000 269 disc = 301855146292441 270 disc = 301855146292441 271 disc = 312604448196032 272 disc = 325603874022336 273 disc = 343308792619261 274 disc = 343956387524625 275 disc = 358470842647653 276 disc = 363887297335457 277 disc = 370533009640625 278 disc = 378388023667289 279 disc = 378388023667289 280 disc = 378388023667289 281 disc = 378435108978368 282 disc = 382167204596009 283 disc = 385272136297125 284 disc = 391853565596233 285 disc = 407478805289353 286 disc = 412162994888000 287 disc = 419718684302848 288 disc = 420610640203125 289 disc = 427178948689297 290 disc = 430522800097229 291 disc = 437262761657701 292 disc = 458528043068928 293 disc = 461406087545417 294 disc = 471655843734321 295 disc = 471655843734321 296 disc = 471710378827584 297 disc = 471710378827584 298 disc = 471710378827584 299 disc = 474114086770176 300 disc = 479184750300277 301 disc = 492814358126272 302 disc = 507558505272832 303 disc = 512537788181952 304 disc = 526672365558093 305 disc = 531381953186973 306 disc = 534063139779637 307 disc = 545919434583489 308 disc = 561188988355904 309 disc = 561188988355904 310 disc = 561188988355904 311 disc = 561842388364096 312 disc = 586376253000000 313 disc = 586376253000000 314 disc = 611354775822848 315 disc = 619777755576000 316 disc = 626277261303693 317 disc = 632689381320192 318 disc = 642489904555569 319 disc = 646877982134125 320 disc = 646877982134125 321 disc = 646877982134125 322 disc = 650182119827968 323 disc = 654605112335552 324 disc = 654605112335552 325 disc = 654605112335552 326 disc = 676928662294464 327 disc = 678155219611793 328 disc = 683425351376704 329 disc = 687273151702249 330 disc = 704612615071625 331 disc = 706705122232017 332 disc = 706705122232017 333 disc = 706705122232017 334 disc = 722893530076992 335 disc = 726766684501312 336 disc = 740652641361333 337 disc = 743283484296704 338 disc = 743702041351801 339 disc = 743702041351801 340 disc = 761874028623037 341 disc = 761949106541056 342 disc = 765458231098176 343 disc = 773039298114433 344 disc = 778002617184317 345 disc = 810000647049313 346 disc = 814597322969457 347 disc = 840297038077125 348 disc = 847557413131456 349 disc = 847557413131456 350 disc = 847557413131456 351 disc = 847557413131456 352 disc = 860329562380029 353 disc = 873174569112000 354 disc = 884514834431488 355 disc = 884514834431488 356 disc = 888834215593792 357 disc = 898101431252641 358 disc = 901568676645125 359 disc = 920173609084625 360 disc = 927543993493824 361 disc = 936704478987584 362 disc = 936704478987584 363 disc = 936704478987584 364 disc = 945000308955968 365 disc = 945000308955968 366 disc = 945000308955968 367 disc = 946850453833536 368 disc = 948500270840277 369 disc = 965396977375537 370 disc = 995805877256000 371 disc = 995805877256000 372 disc = 995805877256000 373 disc = 4239150758955121 374 disc = 71583777861999601 375 disc = 154348440599505681 376 disc = 206144025464586496 377 disc = 498311414318121121 378 disc = 988566915013816576 379 disc = 1594861774888100161 380 disc = 1920991678454430481 381 disc = 3203072711854650625 382 disc = 3282543960141600625 383 disc = 3563847743378991201 384 disc = 11629529577315932881 385 disc = 14937144551057330176 386 disc = 15104107144156878961 387 disc = 18107955017924915521 388 disc = 32757037519097735281 389 disc = 34660765693554192481 390 disc = 39891322034514837441 391 disc = 47965803087841295281 392 disc = 54568636296342159616 393 disc = 73911569995951513281 394 disc = 3830987530897003258893 395 disc = 17723470954150385603125 396 disc = 33413112917251096211093 397 disc = 34637703462495298817024 398 disc = 88388569691530342400000 399 disc = 219491114456594107591949 400 disc = 480467194090863436127232 401 disc = 1037662435085339279821824 402 disc = 1173200147537629968564224 403 disc = 1288413852163540951269376 404 disc = 1309219498202517731691949 405 disc = 2589525908257257679485601 406 disc = 3190278955076438566369093 407 disc = 3227335013943818471790557 408 disc = 3713732460841424506170368 409 disc = 4862809470873883357637632 410 disc = 6002643624777941817982976 411 disc = 7126069515444754920275968 412 disc = 12952518753342414842160584761 413 disc = 19889530276837831068388593664 414 disc = 33146763213552556976071497289 415 disc = 134058271322059099333696000000 416 disc = 143177496454836860404568609521 417 disc = 782366492329362629572165894144 418 disc = 885679687572037927988717116729 419 disc = 1932285652221352905364571537408 420 disc = 792696226576452305767009651523584 421 disc = 1120727194291010174129782797578125 422 disc = 1677627312816188946952964414636032 423 disc = 40650250977089753091644821936498677 424 disc = 82968596939468322350524272929144832 425 disc = 86620507852136986313803229728551889 426 disc = -48269476692516748870958029675063944413184 427 disc = 3057647616 428 disc = -61837572703801526878847827968 429 disc = 10953815427820782987807562683135882947045385765546796605368678856 6125676724691632661454253689888403350678050281881600000000000000000000000000 0000000000000000000000 430 disc = -4047658052954461065912911660658154357072747299150021320490491581 6357719261043885533725876268976267090078699982339498617717978285115098117423 5226786109719181996179722769519700738142090773570860994444369576764647340001 6271055386451054047833315739281064060031306134989387012001240366983880112401 0950391140893121715388041767973840048335480267318286333231520541406374861862 1393537964424677884127250669128055090586243928496505152582326687370689187624 8193649132417798542886781065276330907871042811558631554710375998113711429289 8496513938923014831159547568236743150682002399344666964624978609632942422782 6498518955202829946466452792918443649912549887356822674330431196145149803023 4895588458953982456193472068052465591438058958231038395076434692769303458913 1290964204147229157301290925386293126167130333738976824399921085466861118333 7378074137212916065543375824994038692415387212889537750773611240570763116746 580968621149210575140668368291928317296640 3940200619639447921227904010014361380507973927046544666794829340424572177149 7210611414266254884915640806627990306816 63456228123711897600000000 32065375478269160177874763776 44676618219970392643498326834331791020485046219833344 3353338721974729817301054329173240175627277795006862757734308781291047845002 3018568598687979818620835459868306327959658030836737051459691258806591089437 47971479203517856656769812503986176 2 2 [1, 1/23737807549715*x + 1/23737807549715], -84 [1, 1/23737807549715*x + 1/23737807549715], -84 [1, 1/23737807549715*x + 1/23737807549715], -84 [1, 1/23737807549715*x + 1/23737807549715], -84 [1, 1/23737807549715*x + 1/23737807549715], -84 1600000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000854400000000000000002528000000000000000000000000000000 0000000000000000000000000000000000000000000114062400000000000001349952000000 0000000009985600000000000000000000000000000000000000000000000000000000000000 0000000001802185920000000000005332310400000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000007118634384 551496736222216254722000000000000000000 827291662110720806941937696976 827291662110720806941937696976 1829588275678412623545199440085617991487329070573733217623919229319113044984 7043240296490405430571600333921237812878855963389645333434375832029389798100 2257959673546096955479576068586475382480853862613306969417169103011638331660 1201306395825655815434916376708877260320176246425838223520116446772502951367 2790265882534695009041416263989393942592637795846111196045811536983805538340 3470672172674826053707419541728656323114415002332379364150877698691695081667 82125762150400207360000 4189564028720259381657840273063936 -1654803061237150235374988302272 5033282519448254898115181335637339779499927021879296 1:54093014241918194490790565349126012693637887341617741824 2:553900847066715196553514334399802255955654225567861 3:204167719032640005019024666808345229591452567904719732736 4:1828817141453620393409111381752847743954357322097635622912 5:9672040923761648510052237707018213014769550076092297 6:3675884616011070783687160997253268066945780976814240301056 7:3959521610580314758184414487345010567876948477322672996352 8:16610976983408161860132514151532389839369654937559591026688 9:2427474086166184834997553625222284507930409205227017644015616 10:7930100729168743029157195105967004685434512374878186344546304 11:142794883631838386845143772662895621364419715962902697749 12:47171107507345688156787233808458382362555566179527607671586816 13:50338572322914292936802724906444930709086927612846345126936576 14:137365062346927097139876841580855098110582805146769136183672832 15:175125191814328750737342932680409914455890063666159436076941312 16:188914209014206386337673461200696552539540401586305733927632896 1:54093014241918194490790565349126012693637887341617741824 2:553900847066715196553514334399802255955654225567861 3:204167719032640005019024666808345229591452567904719732736 4:1828817141453620393409111381752847743954357322097635622912 5:9672040923761648510052237707018213014769550076092297 6:3675884616011070783687160997253268066945780976814240301056 7:3959521610580314758184414487345010567876948477322672996352 8:16610976983408161860132514151532389839369654937559591026688 9:2427474086166184834997553625222284507930409205227017644015616 10:7930100729168743029157195105967004685434512374878186344546304 11:142794883631838386845143772662895621364419715962902697749 12:47171107507345688156787233808458382362555566179527607671586816 13:50338572322914292936802724906444930709086927612846345126936576 14:137365062346927097139876841580855098110582805146769136183672832 15:175125191814328750737342932680409914455890063666159436076941312 16:188914209014206386337673461200696552539540401586305733927632896 2084850211225600 Total time spent: 1689 pari-2.17.2/src/test/32/bnflog0000644000175000017500000000133614676526175014376 0ustar billbill *** Warning: new stack size = 12000000 (11.444 Mbytes). [2, 1] [1, 2] [1, 1] 225 64 432 [6, 1] [6, 1] [1, 2] [1024] [[4, 2], [4], [2]] [] [[5], [5], []] [2, 2] [[], [], [2]] [10, 2, 2] [[512, 2], [256], [2, 2]] [6, 2, 2] [[2, 2, 2], [], [2, 2, 2]] [4, 4] [[613], [613], []] [14] [[], [], []] [[3], [3], []] [[7], [], [7]] [273] [[4], [4], []] [[3], [], [3]] [[13, 13], [13], [13]] [14] [[2], [], [2]] [[9], [9], []] [[], [], []] [6, 6, 2] [[2, 2, 2], [], [2, 2, 2]] [[3], [], [3]] [150, 15] [[2, 2], [2], [2]] [[3, 3], [], [3, 3]] [[25, 5], [], [25, 5]] [105, 3] [[25, 5, 5], [25, 5, 5], []] [6, 2, 2, 2] [[2, 2, 2, 2], [], [2, 2, 2, 2]] [[3, 3], [3], [3]] [[5, 5], [5, 5], []] [[4], [2], [2]] [[], [], []] Total time spent: 2199 pari-2.17.2/src/test/32/sumnum0000644000175000017500000000661314567450071014444 0ustar billbill *** Warning: new stack size = 40000000 (38.147 Mbytes). +oo +oo +oo 1.6449340668482264364724151666460251892 0.39493406684822643647241516664602518922 1.6449340668482264364724151666460251892 +oo 2.6123753486854883433485675679240716306 2.6123753486854883433485675679240716306 1.6123753486854883433485675679240716306 (n)->1/(n^2+1) -38 -38 -40 -38 (n)->log(1+1/n)/n +oo -38 -36 -38 (n)->lngamma(1+1/n)/n +oo +oo -37 -39 (n)->sin(1/sqrt(n))/n^(3/2) +oo +oo -36 +oo 2.3979771206715998375659850036324914715 2.3979771206715998375659850036324914714 +oo +oo *** at top-level: sumnummonien(n=1,1/n^2,tab) *** ^---------- *** incompatible initial value 2 != 1. +oo +oo +oo +oo -36 +oo realprecision = 115 significant digits +oo +oo +oo +oo +oo -115 +oo +oo +oo +oo +oo -115 realprecision = 308 significant digits -308 -307 -307 +oo -307 -307 -307 [-307, -305] -307 +oo -408 2.47966052573232990761047428236557457611831203144307271235622022056652147251 7605158008989579019155072837095780182410363956184573887461660980052873616581 6577757896142310226542037192089589361644803693741989026767407181994861341239 0058993512488079811186434271036137090844427472126934630595857603882052659184 49350 realprecision = 38 significant digits 0.94536905472633293526609521540827019813 0.E-37 realprecision = 19 significant digits 1.644934066848226436 *** at top-level: sumnum(n=1,1/n^2,"bug") *** ^------------ *** incorrect type in sumnum (t_STR). *** at top-level: sumnumap(n=1,1/n^2,"bug") *** ^------------ *** incorrect type in sumnumap (t_STR). *** at top-level: intnumapinit(x,y) *** ^----------------- *** not a function in function call *** at top-level: sumnummonieninit([-1,1]) *** ^------------------------ *** sumnummonieninit: domain error in sumnummonieninit: a <= 0 *** at top-level: sumnummonieninit([1,-1]) *** ^------------------------ *** sumnummonieninit: domain error in sumnummonieninit: a+b <= 1 *** at top-level: sumnummonieninit(,[n->2^-n,oo]) *** ^------------------------------- *** sumnummonieninit: forbidden addition t_INT + t_INFINITY. *** at top-level: sumnummonieninit(oo) *** ^-------------------- *** sumnummonieninit: incorrect type in sumnummonieninit (t_INFINITY). *** at top-level: sumnumlagrangeinit([1/5,0]) *** ^--------------------------- *** sumnumlagrangeinit: sorry, sumnumlagrange for this alpha is not yet implemented. *** at top-level: sumnumlagrangeinit(x) *** ^--------------------- *** sumnumlagrangeinit: incorrect type in sumnumlagrangeinit (t_POL). *** at top-level: sumnumlagrangeinit(x,-2) *** ^------------------------ *** sumnumlagrangeinit: domain error in sumnumlagrangeinit: c1 <= 0 *** at top-level: prodinf(n=0,1+2^-n,2) *** ^--------------------- *** prodinf: invalid flag in prodinf. *** at top-level: sumalt(n=0,1,2) *** ^--------------- *** sumalt: invalid flag in sumalt. *** at top-level: sumpos(n=0,1,2) *** ^--------------- *** sumpos: invalid flag in sumpos. *** at top-level: intnumosc(x=0,besselj(0,x)^2,Pi) *** ^---------- *** sumnumsidi diverges. Total time spent: 3527 pari-2.17.2/src/test/32/subst0000644000175000017500000000425014676526175014265 0ustar billbillY/x x + 1 [[1, 3], [2, 3]] [[1, 3], [2, 3]] [[1, 3], [2, 3], [1, 4], [2, 4]] [[1, 3, 5], [2, 3, 5], [1, 4, 5], [2, 4, 5], [1, 3, 6], [2, 3, 6], [1, 4, 6] , [2, 4, 6]] [[x + y, y], [x, y], [x + y, x + y], [x, x + y]] 0 O(x^2) *** at top-level: subst(x+O(x^2),x,Mod(1,3)) *** ^-------------------------- *** subst: forbidden substitution t_SER , t_INTMOD. Mod(0, 3) *** at top-level: subst(1/x+O(x^2),x,Mod(0,3)) *** ^---------------------------- *** subst: impossible inverse in gsubst: Mod(0, 3). Mod(2, 3) Mod(0, 3) [Mod(0, 3) Mod(0, 3)] [Mod(0, 3) Mod(0, 3)] Mod(1, 3) [Mod(1, 3) Mod(0, 3)] [Mod(0, 3) Mod(1, 3)] [Mod(1, 3)*y + Mod(1, 3) Mod(0, 3)] [ Mod(0, 3) Mod(1, 3)*y + Mod(1, 3)] [Mod(1, 3) + Mod(1, 3)*y + O(y^2) Mod(0, 3)] [ Mod(0, 3) Mod(1, 3) + Mod(1, 3)*y + O(y^2)] [Mod(1, 3) Mod(0, 3)] [Mod(0, 3) Mod(1, 3)] [Mod(0, 3) Mod(0, 3)] [Mod(0, 3) Mod(0, 3)] [Mod(0, 3)] [Mod(1, 3)] [Mod(1, 3)] [Mod(0, 3)] "t_POL" "t_INT" "t_POL" "t_POL" "t_POL" "t_POL" [3, 4] [3, 4]~ 1/y Mod(y*x, y^2*x^2 + 1) y*x/(y^2*x^2 + 1) List([]) List([y*x^2]) x^2 + y^2*x^3 + O(x^4) [t] [t] [;] *** at top-level: subst(1,x,Mat([1,2])) *** ^--------------------- *** subst: forbidden substitution t_INT , t_MAT (1 x 2). 4*y^2 + O(y^3) 1 + O(x) x + O(x^2) *** at top-level: substpol(x+O(x^4),x^2,x) *** ^------------------------ *** substpol: domain error in gdeflate: valuation(x) % 2 != 0 1 (y + 1) + (y + 1)*x + O(x^2) Mod(1, y)/(Mod(1, y)*x) Mod(-a, a^2 - 2) 0 O(y) + (1 - y + O(y^2))*x + O(x^2) Mod(0, 2)*t^90 + O(t^91) Mod(128180/979869*t^15 - 604511/979869*t^14 - 151549/326623*t^13 + 3615112/9 79869*t^12 + 530094/326623*t^11 - 5186329/979869*t^10 - 254488/89079*t^9 - 7 960673/979869*t^8 - 4836011/326623*t^7 + 21827149/979869*t^6 + 69695441/9798 69*t^5 + 51405083/979869*t^4 - 81475/979869*t^3 - 3334127/326623*t^2 - 19002 11/979869*t + 3682385/979869, t^16 - 4*t^15 - 7*t^14 + 26*t^13 + 33*t^12 - 3 4*t^11 - 51*t^10 - 76*t^9 - 158*t^8 + 100*t^7 + 669*t^6 + 778*t^5 + 261*t^4 - 128*t^3 - 100*t^2 - 14*t + 1) Total time spent: 2 pari-2.17.2/src/test/32/sumdiv0000644000175000017500000000345014760123736014423 0ustar billbill3628800 20993420690550 3628800 20993420690550 3628800 20993420690550 3628800 20993420690550 0 0 7 [7, 720] 4 15 829440 270 15334088 20993420690550 57335533287534038504 273823/64800 1 error("domain error in moebius: argument = 0") 0 [0, 1] error("domain error in omega: argument = 0") error("domain error in bigomega: argument = 0") 2 error("domain error in numdiv: argument = 0") error("domain error in sumdiv: argument = 0") error("domain error in sumdivk: argument = 0") error("domain error in sumdivk: argument = 0") error("domain error in sumdivk: argument = 0") 1 error("incorrect type in moebius (t_MAT).") 0 [0, 1] error("incorrect type in omega (t_MAT).") error("incorrect type in bigomega (t_MAT).") 2 error("incorrect type in numdiv (t_MAT).") error("incorrect type in sumdiv (t_MAT).") error("incorrect type in sumdivk (t_MAT).") error("incorrect type in sumdivk (t_MAT).") error("incorrect type in sumdivk (t_MAT).") 0 -1 -2 [-2, 1] 1 1 1 2 3 5 9 -3/2 0 -1 -2 [-2, 1] 1 1 1 2 3 5 9 -3/2 1 1 1 [1, 1] 0 0 1 1 1 1 1 1 [1] 1 0 [0, 1] *** at top-level: divisors(fa) *** ^------------ *** divisors: domain error in divisors: argument = 0 [30, 2] [1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 24, 30, 40, 60, 120] x^10 + 16*x^9 + 115*x^8 + 491*x^7 + 1387*x^6 + 2729*x^5 + 3822*x^4 + 3805*x^ 3 + 2616*x^2 + 1146*x + 252 x^10 + 16*x^9 + 115*x^8 + 491*x^7 + 1387*x^6 + 2729*x^5 + 3822*x^4 + 3805*x^ 3 + 2616*x^2 + 1146*x + 252 x^10 + 16*x^9 + 115*x^8 + 491*x^7 + 1387*x^6 + 2729*x^5 + 3822*x^4 + 3805*x^ 3 + 2616*x^2 + 1146*x + 252 x^10 + 16*x^9 + 115*x^8 + 491*x^7 + 1387*x^6 + 2729*x^5 + 3822*x^4 + 3805*x^ 3 + 2616*x^2 + 1146*x + 252 *** at top-level: divisors([1,2]) *** ^--------------- *** divisors: incorrect type in divisors (t_VEC). 0 762104756900678410271641 Total time spent: 0 pari-2.17.2/src/test/32/thue0000644000175000017500000000266014567450071014063 0ustar billbill *** Warning: new stack size = 100000000 (95.367 Mbytes). [] [[0, -1]] [[-4, -3], [-4, 3], [4, -3], [4, 3]] [[1, 1]] [[-1, -1], [-1, 0], [0, -1], [0, 1], [1, 0], [1, 1]] [[-4, -2], [1868, 514]] [] [[5, 1]] [[-1, -1], [1, 1]] [[-1, -1], [1, 1]] *** at top-level: thueinit(x^0) *** ^------------- *** thueinit: constant polynomial in thueinit. [[-4, -1], [-2, -2], [2, 2], [4, 1]] [[0, 3], [3, -276], [3, 0]] [[0, 3], [3, 0], [19, 2], [27, 3]] [[-1, -1], [-1, 1], [1, -1], [1, 1]] [[0, 0]] [[0, 0]] [[0, 0]] [[-1, -1], [-1, 1], [1, -1], [1, 1]] [] [[0, 1], [1, -537825], [1, 0], [1, 1], [537824, 1]] [[44, -131]] [[-17711, -28657], [2584, 4181], [4181, 6765], [10946, 17711]] [] [[0, -1], [0, 1]] [[0, 1]] [[-8, 6], [-2, -2], [-2, 0], [0, -2], [2, -2]] [[-2, -1], [-1, -2], [1, 2], [2, 1]] [] [] [[-12100, 5500], [-12100, 6600], [-11000, 1100], [-11000, 9900], [-9900, -11 00], [-9900, 11000], [-6600, -5500], [-6600, 12100], [-5500, -6600], [-5500, 12100], [-1100, -9900], [-1100, 11000], [1100, -11000], [1100, 9900], [5500 , -12100], [5500, 6600], [6600, -12100], [6600, 5500], [9900, -11000], [9900 , 1100], [11000, -9900], [11000, -1100], [12100, -6600], [12100, -5500]] 44 44 2 2 24 6 [] [] [[0, 1]] [] [] [[739, -219]] [[739, -219]] [[-774658, -365105], [-774658, 365105], [774658, -365105], [774658, 365105]] [[-1, 0], [1, 0]] [[-1, 0], [1, 0]] [[-1, 0], [1, 0]] 32 [] [[-18, -9], [9, -9], [9, 18]] Total time spent: 3736 pari-2.17.2/src/test/32/nfhilbert0000644000175000017500000000757114567450071015101 0ustar billbill[-1, -1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1] [-1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, -1] -1 *** at top-level: nfhilbert(nf,Mod(0,3),3,pr) *** ^--------------------------- *** nfhilbert: domain error in nfhilbert: a = 0 *** at top-level: nfhilbert(nf,3,0.,pr) *** ^--------------------- *** nfhilbert: domain error in nfhilbert: b = 0 1 1 -1 1 -1 1 [1, 2]: 1 [1, 3]: 1 [1, 4]: error("precision too low in hilbert.") [1, 5]: error("precision too low in hilbert.") [1, 6]: 1 [1, 7]: 1 [1, 8]: 0 [1, 9]: error("precision too low in hilbert.") [1, 10]: 1 [1, 11]: 1 [2, 3]: 1 [2, 4]: error("precision too low in hilbert.") [2, 5]: error("precision too low in hilbert.") [2, 6]: 1 [2, 7]: 1 [2, 8]: 0 [2, 9]: error("precision too low in hilbert.") [2, 10]: 1 [2, 11]: 1 [3, 4]: error("forbidden hilbert t_REAL , t_INTMOD.") [3, 5]: error("forbidden hilbert t_REAL , t_INTMOD.") [3, 6]: error("forbidden hilbert t_REAL , t_INTMOD.") [3, 7]: error("forbidden hilbert t_REAL , t_INTMOD.") [3, 8]: error("forbidden hilbert t_REAL , t_INTMOD.") [3, 9]: error("forbidden hilbert t_REAL , t_PADIC.") [3, 10]: error("forbidden hilbert t_REAL , t_PADIC.") [3, 11]: error("forbidden hilbert t_REAL , t_PADIC.") [4, 5]: error("precision too low in hilbert.") [4, 6]: error("precision too low in hilbert.") [4, 7]: error("precision too low in hilbert.") [4, 8]: error("precision too low in hilbert.") [4, 9]: error("precision too low in hilbert.") [4, 10]: error("precision too low in hilbert.") [4, 11]: error("precision too low in hilbert.") [5, 6]: error("precision too low in hilbert.") [5, 7]: error("precision too low in hilbert.") [5, 8]: error("precision too low in hilbert.") [5, 9]: error("precision too low in hilbert.") [5, 10]: error("precision too low in hilbert.") [5, 11]: error("precision too low in hilbert.") [6, 7]: error("inconsistent moduli in hilbert: 3 != 8") [6, 8]: error("inconsistent moduli in hilbert: 5 != 8") [6, 9]: error("inconsistent moduli in hilbert: 8 != 2") [6, 10]: error("inconsistent moduli in hilbert: 8 != 2") [6, 11]: error("inconsistent moduli in hilbert: 8 != 5") [7, 8]: error("inconsistent moduli in hilbert: 5 != 3") [7, 9]: error("inconsistent moduli in hilbert: 3 != 2") [7, 10]: error("inconsistent moduli in hilbert: 3 != 2") [7, 11]: error("inconsistent moduli in hilbert: 3 != 5") [8, 9]: error("inconsistent moduli in hilbert: 5 != 2") [8, 10]: error("inconsistent moduli in hilbert: 5 != 2") [8, 11]: 0 [9, 10]: error("precision too low in hilbert.") [9, 11]: error("precision too low in hilbert.") [10, 11]: error("inconsistent moduli in hilbert: 2 != 5") p = 0: 1: 1 2: 1 3: 1 4: error("inconsistent moduli in hilbert: 2 != \"oo\"") 5: error("inconsistent moduli in hilbert: 4 != \"oo\"") 6: error("inconsistent moduli in hilbert: 8 != \"oo\"") 7: error("inconsistent moduli in hilbert: 3 != \"oo\"") 8: error("inconsistent moduli in hilbert: 5 != \"oo\"") 9: error("inconsistent moduli in hilbert: 0 != 2") 10: error("inconsistent moduli in hilbert: 0 != 2") 11: error("inconsistent moduli in hilbert: 0 != 5") p = 2: 1: 1 2: -1 3: error("inconsistent moduli in hilbert: 2 != \"oo\"") 4: error("precision too low in hilbert.") 5: error("precision too low in hilbert.") 6: 1 7: error("precision too low in hilbert.") 8: error("precision too low in hilbert.") 9: error("precision too low in hilbert.") 10: 1 11: error("inconsistent moduli in hilbert: 2 != 5") p = 5: 1: 1 2: 1 3: error("inconsistent moduli in hilbert: 5 != \"oo\"") 4: error("inconsistent moduli in hilbert: 2 != 5") 5: error("inconsistent moduli in hilbert: 4 != 5") 6: error("inconsistent moduli in hilbert: 8 != 5") 7: error("inconsistent moduli in hilbert: 3 != 5") 8: error("precision too low in hilbert.") 9: error("inconsistent moduli in hilbert: 5 != 2") 10: error("inconsistent moduli in hilbert: 5 != 2") 11: 1 -1 -1 1 Total time spent: 173 pari-2.17.2/src/test/32/sumiter0000644000175000017500000000232114567450071014600 0ustar billbill realprecision = 19 significant digits echo = 1 ? intnum(x=0,Pi,sin(x)) 2.000000000000000000 ? intnum(x=0,4,exp(-x^2)) 0.8862269117895689458 ? intnum(x=1,[1],1/(1+x^2))-Pi/4 0.E-19 ? intnum(x=-0.5,0.5,1/sqrt(1-x^2))-Pi/3 0.E-18 ? intnum(x=0,[[1],-I],sin(x)/x)-Pi/2 0.E-18 ? \p38 realprecision = 38 significant digits ? prod(k=1,10,1+1/k!) 3335784368058308553334783/905932868585678438400000 ? prod(k=1,10,1+1./k!) 3.6821540356142043935732308433185262946 ? Pi^2/6*prodeuler(p=2,10000,1-p^-2) 1.0000098157493066238697591433298145222 ? prodinf(n=0,(1+2^-n)/(1+2^(-n+1))) 0.33333333333333333333333333333333333329 ? prodinf(n=0,-2^-n/(1+2^(-n+1)),1) 0.33333333333333333333333333333333333329 ? solve(x=1,4,sin(x)) 3.1415926535897932384626433832795028842 ? sum(k=1,10,2^-k) 1023/1024 ? sum(k=1,10,2.^-k) 0.99902343750000000000000000000000000000 ? 4*sumalt(n=0,(-1)^n/(2*n+1)) 3.1415926535897932384626433832795028842 ? 4*sumalt(n=0,(-1)^n/(2*n+1),1) 3.1415926535897932384626433832795028842 ? sumdiv(8!,x,x) 159120 ? suminf(n=1,2.^-n) 0.99999999999999999999999999999999999999 ? 6/Pi^2*sumpos(n=1,n^-2) 0.99999999999999999999999999999999999999 ? if(getheap()!=HEAP,getheap()) ? print("Total time spent: ",gettime); Total time spent: 15 pari-2.17.2/src/test/32/nfrootsof10000644000175000017500000000037514567450071015217 0ustar billbill *** Warning: new stack size = 20000000 (19.073 Mbytes). 46 46 18 2 2 2 4 68 170 [2, -1] [2, -1] *** at top-level: nfrootsof1(x^0) *** ^--------------- *** nfrootsof1: constant polynomial in nfrootsof1. Total time spent: 2237 pari-2.17.2/src/test/32/modular0000644000175000017500000000754714567450071014572 0ustar billbill1: Mod(1, 2)*x^8 + Mod(1, 2)*x^6 + Mod(1, 2)*x^4 + Mod(1, 2)*x^2 + Mod(1, 2) 2: Mod(1, 3)*x^8 + Mod(1, 3)*x^6 + Mod(1, 3)*x^4 + Mod(1, 3)*x^2 + Mod(1, 3) 3: Mod(1, 4294967295)*x^8 + Mod(1, 4294967295)*x^6 + Mod(1, 4294967295)*x^4 + Mod(1, 4294967295)*x^2 + Mod(1, 4294967295) 4: Mod(1, 18446744073709551615)*x^8 + Mod(1, 18446744073709551615)*x^6 + Mod (1, 18446744073709551615)*x^4 + Mod(1, 18446744073709551615)*x^2 + Mod(1, 18 446744073709551615) 5: Mod(1, 100000000000000000000)*x^8 + Mod(1, 100000000000000000000)*x^6 + M od(1, 100000000000000000000)*x^4 + Mod(1, 100000000000000000000)*x^2 + Mod(1 , 100000000000000000000) 1: Mod(1, 2)*x^8 + Mod(1, 2)*x^6 + Mod(1, 2)*x^4 + Mod(1, 2)*x^2 + Mod(1, 2) 2: Mod(1, 3)*x^8 + Mod(1, 3)*x^7 + Mod(2, 3)*x^5 + Mod(2, 3)*x^4 + Mod(2, 3) *x^3 + Mod(1, 3)*x + Mod(1, 3) 3: Mod(1, 4294967295)*x^8 + Mod(4294967293, 4294967295)*x^7 + Mod(3, 4294967 295)*x^6 + Mod(4294967291, 4294967295)*x^5 + Mod(5, 4294967295)*x^4 + Mod(42 94967291, 4294967295)*x^3 + Mod(3, 4294967295)*x^2 + Mod(4294967293, 4294967 295)*x + Mod(1, 4294967295) 4: Mod(1, 18446744073709551615)*x^8 + Mod(18446744073709551613, 184467440737 09551615)*x^7 + Mod(3, 18446744073709551615)*x^6 + Mod(18446744073709551611, 18446744073709551615)*x^5 + Mod(5, 18446744073709551615)*x^4 + Mod(18446744 073709551611, 18446744073709551615)*x^3 + Mod(3, 18446744073709551615)*x^2 + Mod(18446744073709551613, 18446744073709551615)*x + Mod(1, 1844674407370955 1615) 5: Mod(1, 100000000000000000000)*x^8 + Mod(99999999999999999998, 10000000000 0000000000)*x^7 + Mod(3, 100000000000000000000)*x^6 + Mod(999999999999999999 96, 100000000000000000000)*x^5 + Mod(5, 100000000000000000000)*x^4 + Mod(999 99999999999999996, 100000000000000000000)*x^3 + Mod(3, 100000000000000000000 )*x^2 + Mod(99999999999999999998, 100000000000000000000)*x + Mod(1, 10000000 0000000000000) 1: [Mod(1, 2), Mod(0, 2); Mod(1, 2), Mod(0, 2)] 2: [Mod(0, 3), Mod(0, 3); Mod(2, 3), Mod(2, 3)] 3: [Mod(4294967286, 4294967295), Mod(6, 4294967295); Mod(4294967276, 4294967 295), Mod(14, 4294967295)] 4: [Mod(18446744073709551606, 18446744073709551615), Mod(6, 1844674407370955 1615); Mod(18446744073709551596, 18446744073709551615), Mod(14, 184467440737 09551615)] 5: [Mod(99999999999999999991, 100000000000000000000), Mod(6, 100000000000000 000000); Mod(99999999999999999981, 100000000000000000000), Mod(14, 100000000 000000000000)] 1: [Mod(1, 2), Mod(0, 2); Mod(1, 2), Mod(0, 2)] 2: [Mod(1, 3), Mod(1, 3); Mod(0, 3), Mod(1, 3)] 3: [Mod(7, 4294967295), Mod(10, 4294967295); Mod(15, 4294967295), Mod(22, 42 94967295)] 4: [Mod(7, 18446744073709551615), Mod(10, 18446744073709551615); Mod(15, 184 46744073709551615), Mod(22, 18446744073709551615)] 5: [Mod(7, 100000000000000000000), Mod(10, 100000000000000000000); Mod(15, 1 00000000000000000000), Mod(22, 100000000000000000000)] Mod(Mod(1, y), x) Mod(Mod(1, y), x) error("forbidden division t_INT % t_STR.") error("impossible inverse in %: 0.") error("impossible inverse in %: 0.") error("inconsistent division t_SER % t_POL.") Mod(x, x^2) Mod(x, x^2) Mod(x, x^2) Mod(1, 3) Mod(-x, x^2 + 1) [Mod(1, 2), Mod(0, 2)] Mod(1, 2)*x Mod(1, y)*x Mod(0, 2) Mod(0, 2) Mod(2, 7) Mod(4, 7) debug = 1 *** _+_: Warning: coercing quotient rings; moduli 2 and 3 -> 1. Mod(0, 1) *** _-_: Warning: coercing quotient rings; moduli 2 and 3 -> 1. Mod(0, 1) *** _*_: Warning: coercing quotient rings; moduli 2 and 3 -> 1. Mod(0, 1) *** _/_: Warning: coercing quotient rings; moduli 2 and 3 -> 1. Mod(0, 1) Mod(0, 2) Mod(0, 2) Mod(1, 2) Mod(1, 2) *** _+_: Warning: coercing quotient rings; moduli x and x + 1 -> 1. Mod(0, 1) *** _-_: Warning: coercing quotient rings; moduli x and x + 1 -> 1. Mod(0, 1) *** _*_: Warning: coercing quotient rings; moduli x and x + 1 -> 1. Mod(0, 1) *** _/_: Warning: coercing quotient rings; moduli x and x + 1 -> 1. Mod(0, 1) Mod(2, x) Mod(0, x) Mod(1, x) Mod(1, x) 1 1 1 1 1 1 1 Total time spent: 1 pari-2.17.2/src/test/32/help0000644000175000017500000001460514760123736014050 0ustar billbillx: user defined variable sin(x): sine of x. f = ()->1 echo: default echo: default log: default new is aliased to: sin(x): sine of x. test1 test2 test3 test4 new is aliased to: test2 does_not_exist: unknown identifier Help topics: for a list of relevant subtopics, type ?n for n in 0: user-defined functions (aliases, installed and user functions) 1: PROGRAMMING under GP 2: Standard monadic or dyadic OPERATORS 3: CONVERSIONS and similar elementary functions 4: functions related to COMBINATORICS 5: NUMBER THEORETICAL functions 6: POLYNOMIALS and power series 7: Vectors, matrices, LINEAR ALGEBRA and sets 8: TRANSCENDENTAL functions 9: SUMS, products, integrals and similar functions 10: General NUMBER FIELDS 11: Associative and central simple ALGEBRAS 12: ELLIPTIC CURVES 13: L-FUNCTIONS 14: HYPERGEOMETRIC MOTIVES 15: MODULAR FORMS 16: MODULAR SYMBOLS 17: GRAPHIC functions 18: The PARI community Also: ? functionname (short on-line help) ?\ (keyboard shortcuts) ?. (member functions) Extended help (if available): ?? (opens the full user's manual in a dvi previewer) ?? tutorial / refcard / libpari (tutorial/reference card/libpari manual) ?? refcard-ell (or -lfun/-mf/-nf: specialized reference card) ?? keyword (long help text about "keyword" from the user's manual) ??? keyword (a propos: list of related functions). Member functions, followed by relevant objects a1-a6, b2-b8, c4-c6 : coeff. of the curve. ell area : area ell bid : big ideal bid, bnr bnf : big number field bnf,bnr clgp : class group quad,bid, bnf,bnr cyc : cyclic decomposition quad,bid, clgp,ell, bnf,bnr diff, codiff: different and codifferent nf,bnf,bnr disc : discriminant ell,nf,bnf,bnr,rnf e, f : inertia/residue degree prid fu : fundamental units bnf gen : generators bid,prid,clgp,ell, bnf,bnr, gal group: group ell, gal index: index nf,bnf,bnr j : j-invariant ell mod : modulus bid, bnr, gal nf : number field nf,bnf,bnr,rnf no : number of elements quad,bid, clgp,ell, bnf,bnr normfu: quad omega, eta: [w1,w2] and [eta1, eta2] ell orders: relative orders of generators gal p : rational prime prid, ell,nf,bnf,bnr,rnf,gal pol : defining polynomial nf,bnf,bnr, gal polabs: defining polynomial over Q rnf reg : regulator quad, bnf roots: roots ell,nf,bnf,bnr, gal sign,r1,r2 : signature nf,bnf,bnr t2 : t2 matrix nf,bnf,bnr tate : Tate's [u^2, u, q, [a,b], L, Ei] ell tu : torsion unit and its order bnf zk : integral basis nf,bnf,bnr,rnf zkst : structure of (Z_K/m)* bid, bnr # : enable/disable timer ## : print time for last result \\ : comment up to end of line \a {n} : print result in raw format (readable by PARI) \B {n} : print result in beautified format \c : list all commands (same effect as ?*) \d : print all defaults \e {n} : enable/disable echo (set echo=n) \g {n} : set debugging level \gf{n} : set file debugging level \gm{n} : set memory debugging level \h {m-n}: hashtable information \l {f} : enable/disable logfile (set logfile=f) \m {n} : print result in prettymatrix format \o {n} : set output method (0=raw, 1=prettymatrix, 2=prettyprint, 3=2-dim) \p {n} : change real precision \pb{n} : change real bit precision \ps{n} : change series precision \q : quit completely this GP session \r {f} : read in a file \s : print stack information \t : print the list of PARI types \u : print the list of user-defined functions \um : print the list of user-defined member functions \uv : print the list of user-defined variables, excluding closures \v : print current version of GP \w {nf} : write to a file \x {n} : print complete inner structure of result \y {n} : disable/enable automatic simplification (set simplify=n) {f}=optional filename. {n}=optional integer cmp divrem lex max min shift shiftmul sign vecmax vecmin test6 List of the PARI types: t_INT : long integers [ cod1 ] [ cod2 ] [ man_1 ] ... [ man_k ] t_REAL : long real numbers [ cod1 ] [ cod2 ] [ man_1 ] ... [ man_k ] t_INTMOD : integermods [ code ] [ mod ] [ integer ] t_FRAC : irred. rationals [ code ] [ num. ] [ den. ] t_FFELT : finite field elt. [ code ] [ cod2 ] [ elt ] [ mod ] [ p ] t_COMPLEX: complex numbers [ code ] [ real ] [ imag ] t_PADIC : p-adic numbers [ cod1 ] [ cod2 ] [ p ] [ p^r ] [ int ] t_QUAD : quadratic numbers [ cod1 ] [ mod ] [ real ] [ imag ] t_POLMOD : poly mod [ code ] [ mod ] [ polynomial ] ------------------------------------------------------------- t_POL : polynomials [ cod1 ] [ cod2 ] [ man_1 ] ... [ man_k ] t_SER : power series [ cod1 ] [ cod2 ] [ man_1 ] ... [ man_k ] t_RFRAC : irred. rat. func. [ code ] [ num. ] [ den. ] t_QFB : qfb [ code ] [ a ] [ b ] [ c ] [ disc ] t_VEC : row vector [ code ] [ x_1 ] ... [ x_k ] t_COL : column vector [ code ] [ x_1 ] ... [ x_k ] t_MAT : matrix [ code ] [ col_1 ] ... [ col_k ] t_LIST : list [ cod1 ] [ cod2 ] [ vec ] t_STR : string [ code ] [ man_1 ] ... [ man_k ] t_VECSMALL: vec. small ints [ code ] [ x_1 ] ... [ x_k ] t_CLOSURE: functions [ code ] [ arity ] [ proto ] [ operand ] ... t_ERROR : error context [ code ] [ errnum ] [ dat_1 ] ... [ dat_k ] t_INFINITY: a*infinity [ code ] [ a ] f = ()->1 g = ()->0 a&&b: boolean operator "and". x==y: return 1 if x and y are equal, 0 otherwise. Total time spent: 0 pari-2.17.2/src/test/32/subcyclopclgp0000644000175000017500000000742114676526175016001 0ustar billbill *** Warning: new stack size = 46000000 (43.869 Mbytes). [3, [0, []], [13, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]], [100, 20, 2, 2], 479, 743] [18446744073709551629, [0, []], [0, []], [100, 20, 2, 2], 479, 1471] [3, [0, []], [1, [1]], [22], 3, 5] [5, [0, []], [0, []], [54], 7, 7] [ 3 [0, []] [0, []] [10, 2, 2] 15 15] [ 7 [0, []] [0, []] [10, 2, 2] 15 15] [11 [0, []] [1, [1]] [10, 2, 2] 15 39] [107, [1, [1]], [0, []], [106], 3, 105] [107, [1, [1]], [0, []], [106], 3, 105] [3, [3, [1, 1, 1]], [0, []], [520], 15, 64] [7 [1, [1]] [24, [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 , 1, 1, 1]] [72, 12, 2, 2] 447 1079] [13 [0, []] [21, [4, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] [72, 12, 2, 2] 447 1439] [19 [0, []] [12, [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] [72, 12, 2, 2] 447 1943] [37 [1, [1]] [21, [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] [72, 12, 2, 2] 447 2591] [5, [1, [1]], [2, []], [4, 2], 5, 7] [5, [1, [1]], [3, []], [4, 2], 5, 7] [5, [0, []], [3, []], [4, 2], 5, 7] [5, [0, []], [2, []], [4, 2], 5, 7] [5, [1, [1]], [4, []], [4, 2], 5, 7] [5, [1, [1]], [5, []], [4, 2], 5, 7] [5, [2, []], [2, []], [4, 2], 5, 7] [5, [2, []], [2, []], [4, 2], 5, 7] [3, [0, []], [4, []], [4, 2], 5, 5] [3, [0, []], [6, []], [4, 2], 5, 5] [3, [0, []], [6, []], [4, 2], 5, 5] [3, [2, [1, 1]], [6, []], [4, 2], 5, 5] [3, [2, []], [6, []], [4, 2], 5, 5] [3, [1, [1]], [4, []], [4, 2], 5, 5] [259176647621110622126858782356107328484665259976342412115021268552433997073 8387617403167945550619469621721492378859369344558141003944325421484295160165 8857911348399189883165249380303216445442659845855001807057124765546668168690 4914799785176235594224702493673300848000188617396610597819959791711857860352 39145141831024813815964913062362245006368360500425, 1] [121570884819145671205307244859029699074598957961532892469483554432830641388 777227654529364423115629965737963479911429585496318440106839961087, 1] [162935216088090780658533197925491939407421070241657280420048257800218223929 6716668979394376148874639179770652242209388930212658768615417720698413949275 13804806893854630203503843198360000, 2] (131707,2,3) 1 3 8 13 18 23 (363043,2,3) 4 8 14 20 26 32 38 44 [217] [45] [T^7 + 3*T^6 + 3*T^5 + 6*T^4 + 3*T^3 + 3*T^2 + 6*T, T^5 + 6*T^4 + 6*T] [T^7 + 3*T^6 + 3*T^5 + 6*T^4 + 3*T^3 + 3*T^2 + 6*T, T^5 + 6*T^4 + 6*T] [T^7 + 3*T^6 + 3*T^5 + 6*T^4 + 3*T^3 + 3*T^2 + 6*T, T^5 + 6*T^4 + 6*T] [14, -16, [2, 5]] [14, -19, [1, 3]] [x^6 + 5658*x^5 + 1404*x^4 + 5046*x^3 + 3951*x^2 + 1128*x] [3] [T + 585, T^2 + 405*T] [x^6 + 18780*x^5 + 14526*x^4 + 18168*x^3 + 3951*x^2 + 1128*x] [x^3 + 132*x^2 + 248*x + 106] [] [6, -2, [1]] [1, 1, []] *** at top-level: subcyclopclgp([7,[1]],3) *** ^------------------------ *** subcyclopclgp: domain error in subcyclopclgp: p divides [F:Q] = 6 *** at top-level: subcyclopclgp([7,[1,7]],11) *** ^--------------------------- *** subcyclopclgp: elements not coprime in galoissubcyclo: 7 7 *** at top-level: subcyclopclgp([7,[1]],2) *** ^------------------------ *** subcyclopclgp: domain error in subcyclopclgp: p = 2 *** at top-level: subcyclopclgp([7,[1]],[2,5]) *** ^---------------------------- *** subcyclopclgp: domain error in subcyclopclgp: p = 2 *** at top-level: subcyclopclgp([7,[1]],[3,11]) *** ^----------------------------- *** subcyclopclgp: domain error in subcyclopclgp: p divides [F:Q] = 6 *** at top-level: subcyclopclgp([7,[1]],4) *** ^------------------------ *** subcyclopclgp: not a prime number in subcyclopclgp: 4. *** at top-level: subcyclopclgp([7],5,64) *** ^----------------------- *** subcyclopclgp: invalid flag in subcyclopclgp. "e_IMPL" "e_IMPL" "e_IMPL" Total time spent: 3977 pari-2.17.2/src/test/32/version0000644000175000017500000000003714760123736014577 0ustar billbill[2, 17, 2] Total time spent: 0 pari-2.17.2/src/test/32/norm0000644000175000017500000000173014760137411014061 0ustar billbill1/4 *** at top-level: norml2(quadgen(5)) *** ^------------------ *** norml2: incorrect type in gnorml2 (t_QUAD). 1 1 1/2 1 (x)->normlp(x,1) 6 10 21 2.4142135623730950488016887242096980786 1.6180339887498948482045868343656381177 5 (x)->normlp(x,2) 3.7416573867739413855837487323165493018 5.4772255750516611345696978280080213395 9.5393920141694564915262158602322654026 1.7320508075688772935274463415058723670 1.6180339887498948482045868343656381177 5 (x)->normlp(x,2.5) 3.4585606563304871862271371438840799750 4.9402040006184485884345102892270748966 8.2976320964215261445777796306034959974 1.6273657035458510939647914767411763647 1.6180339887498948482045868343656381177 5 normlp 3 4 6 1.4142135623730950488016887242096980786 1.6180339887498948482045868343656381177 5.0000000000000000000000000000000000000 422481 +oo +oo 1 *** at top-level: normlp(-1,-oo) *** ^-------------- *** normlp: domain error in normlp: p <= 0 Total time spent: 1 pari-2.17.2/src/test/32/orthopol0000644000175000017500000000157714567450071014772 0ustar billbillU T L H LA 1 1 1 1 1 1 1 1 0 -1 209 1 1 1 1 1 *** at top-level: polhermite(-1) *** ^-------------- *** polhermite: domain error in polhermite: degree < 0 *** at top-level: polhermite(0,,1) *** ^---------------- *** polhermite: domain error in polhermite: degree < 0 *** at top-level: polhermite(0,1,1) *** ^----------------- *** polhermite: domain error in polhermite: degree < 0 *** at top-level: pollaguerre(-1) *** ^--------------- *** pollaguerre: domain error in pollaguerre: degree < 0 *** at top-level: pollaguerre(0,,,1) *** ^------------------ *** pollaguerre: domain error in pollaguerre: degree < 0 *** at top-level: pollaguerre(0,,1,1) *** ^------------------- *** pollaguerre: domain error in pollaguerre: degree < 0 Total time spent: 88 pari-2.17.2/src/test/32/addprimes0000644000175000017500000000243614567450071015067 0ustar billbill[[0, 1, 210, 4, 4, 48, 16, 576, 65000, 10922688], [0, -1, 210000630, 5, 5, 4 8000096, 32, 576002304, 65000390000650000, 10922786304486912881835264], [0, 1, 210007560020790, 6, 6, 48001632003072, 64, 576021888078336, 6500468009724 0468000708500000, 10923867696016192486063520726766954883717632], [0, 0, 2100 06930, 6, 7, 48001776007968009216, 96, 576023616144576254592, 65005070125906 093564391733467296447350000, 10923966011120401354532760288014407980573122245 052972159937408], [0, -1, -210000630, 5, 5, 48000096, 32, 576002304, 6500039 0000650000, 10922786304486912881835264]] Testing 210, addprimes = [1000003] Testing 210000630, addprimes = [1000003] Testing 210007560020790, addprimes = [1000003] Testing 210008190043470062370, addprimes = [1000003] Testing -210000630, addprimes = [1000003] Testing 210, addprimes = [1000003, 1000033] Testing 210000630, addprimes = [1000003, 1000033] Testing 210007560020790, addprimes = [1000003, 1000033] Testing 210008190043470062370, addprimes = [1000003, 1000033] Testing -210000630, addprimes = [1000003, 1000033] Testing 210, addprimes = [1000033] Testing 210000630, addprimes = [1000033] Testing 210007560020790, addprimes = [1000033] Testing 210008190043470062370, addprimes = [1000033] Testing -210000630, addprimes = [1000033] [] [1009] Total time spent: 12 pari-2.17.2/src/test/32/nflistQTall0000644000175000017500000000411414676526175015361 0ustar billbill *** Warning: new stack size = 48000000 (45.776 Mbytes). 1: [1] 2: [1] 3: [1, 1] 4: [1, 1, 1, 1, 1] 5: [1, 1, 1, 1, 1] 6: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 7: [1, 1, 1, 1, 1, 1, 1] 8: [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 ] 9: [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] 10: [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] 11: [1, 1, 1, 1, 1, 1, 1, 1] 12: [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, 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, 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, 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, 1, 1, 1, 1, 1] 13: [1, 1, 1, 1, 1, 1, 1, 1, 1] 14: [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] 15: [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, 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: 41295 pari-2.17.2/src/test/32/exact00000644000175000017500000000124711636712103014271 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.17.2/src/test/32/nfeltsign0000644000175000017500000000110514676526175015112 0ustar billbill[-1, -1, -1, 1, 1] -1 [-1, -1, -1, 1] [1, 1, 1, 1] [-1, -1, -1, -1] 0 [-1, 1, 1, 1, 1] [1, 1, 1, 1, 1] 1 [1, 1, 1, 1] [-1] [-1, -1] *** at top-level: nfeltsign(nf,a,3) *** ^----------------- *** nfeltsign: domain error in nfeltsign: index > 2 *** at top-level: nfeltsign(nf,a,[-1..1]) *** ^----------------------- *** nfeltsign: domain error in nfeltsign: index <= 0 *** at top-level: nfeltsign(nf,a,[1..3]) *** ^---------------------- *** nfeltsign: domain error in nfeltsign: index > 2 Total time spent: 14 pari-2.17.2/src/test/32/rootsreal0000644000175000017500000000607514760123736015134 0ustar billbill[1.0000000000000000000000000000000000000, 2.00000000000000000000000000000000 00000, 3.0000000000000000000000000000000000000]~ [1.0000000000000000000000000000000000000]~ [2.0000000000000000000000000000000000000, 3.00000000000000000000000000000000 00000]~ [1.0000000000000000000000000000000000000, 2.00000000000000000000000000000000 00000, 3.0000000000000000000000000000000000000]~ [2.0000000000000000000000000000000000000, 3.00000000000000000000000000000000 00000]~ [1.0000000000000000000000000000000000000, 2.00000000000000000000000000000000 00000]~ 1 2 3 2 2 3 2 2 2 [-22.176420046821213834911725420609849287, -1.220401103882337235735459354425 6902868]~ [-0.98480775301220805936674302458952301367, -0.86602540378443864676372317075 293618347, -0.64278760968653932632264340990726343291, -0.3420201433256687330 4409961468225958076, 0.E-38, 0.34202014332566873304409961468225958076, 0.642 78760968653932632264340990726343291, 0.8660254037844386467637231707529361834 7, 0.98480775301220805936674302458952301367]~ [-0.98768834059513772619004024769343726076, -0.89100652418836786235970957141 362631277, -0.70710678118654752440084436210484903928, -0.4539904997395467915 6040836635787119898, -0.15643446504023086901010531946716689231, 0.1564344650 4023086901010531946716689231, 0.45399049973954679156040836635787119898, 0.70 710678118654752440084436210484903928, 0.891006524188367862359709571413626312 77, 0.98768834059513772619004024769343726076]~ []~ []~ *** at top-level: polrootsreal(0) *** ^--------------- *** polrootsreal: zero polynomial in realroots. *** at top-level: polrootsreal(Pol(0)) *** ^-------------------- *** polrootsreal: zero polynomial in realroots. *** at top-level: polrootsreal(Mod(1,2)) *** ^---------------------- *** polrootsreal: incorrect type in realroots (t_INTMOD). [0.E-38]~ [0.E-38 + 0.E-38*I, 1.0000000000000000000000000000000000000 + 0.E-38*I, 2.00 00000000000000000000000000000000000 + 0.E-38*I, 3.00000000000000000000000000 00000000000 + 0.E-38*I]~ []~ [1.0000000000000000000000000000000000000]~ []~ 1 0 0 3 2 3 []~ []~ [0.E-38]~ [1.2599210498948731647672106072782283506]~ [-1.2599210498948731647672106072782283506]~ 2 [0.E-38]~ 1 2 [-2.0000000000000000000000000000000000000]~ 1 1 1 1 1 1 1 1 1 1 [0.59441447601624956642908249516963028371]~ [-1.1451026912004224304268100262663119669, 0.4760236029181340344691576771197 9045497, 3.6690790882822883959576523491465215119]~ [0.E-38, 0.E-38, 1.0000000000000000000000000000000000000]~ [0.E-38, 0.E-38, 1.0000000000000000000000000000000000000, 2.0000000000000000 000000000000000000000, 2.0000000000000000000000000000000000000, 2.0000000000 000000000000000000000000000, 3.0000000000000000000000000000000000000, 3.0000 000000000000000000000000000000000]~ 19 2 [-1.0000000000000000000000000000000000000, 1.0000000000000000000000000000000 000000]~ 2 [0.025327233692927898289899330575272612041]~ []~ *** at top-level: polrootsreal(0.E25*x^2+0.E25*x+0.E25) *** ^------------------------------------- *** polrootsreal: zero polynomial in realroots. Total time spent: 54 pari-2.17.2/src/test/32/hyperelldisc0000644000175000017500000000434714676526175015623 0ustar billbill-27 800000 1400263200000 1 0 [] [0, -1] [-14/27] [] [23640005/1615441, -23640005/1615441] [-149/108, 852292983271/629856] 1 -22876928 [[398*x^6 + 1687*x^5 + 2954*x^4 + 2738*x^3 + 1418*x^2 + 390*x + 45, x^3 + x^ 2], [2, [1, 0; 0, 1], x^3 + x^2]] 7222041363087360 1 [2*x^10 + 9*x^9 + 8*x^8 + x^6 + 8*x^5 + 6*x^4 + 5*x^3 + 7*x + 3, 0] [1, [524494, -909; -505088299, 875368], 0] [2*x^10 + 9*x^9 + 8*x^8 + x^6 + 8*x^5 + 6*x^4 + 5*x^3 + 7*x + 3, 0] [x^3 + 1, 0] [1, [-1, 9; 1, -10], 0] [x^3 + 1, 0] *** at top-level: hyperellred(1) *** ^-------------- *** hyperellred: incorrect type in hyperellred (t_INT). *** at top-level: hyperellred(Pol(1)) *** ^------------------- *** hyperellred: domain error in hyperellred: disc(W) == 0 *** at top-level: hyperellred(x) *** ^-------------- *** hyperellred: domain error in hyperellred: genus = 0 *** at top-level: hyperellred(x^2+1) *** ^------------------ *** hyperellred: domain error in hyperellred: genus = 0 *** at top-level: hyperellchangecurve(x^3+1,[[1,2],0]) *** ^------------------------------------ *** hyperellchangecurve: incorrect type in hyperellchangecurve (t_VEC). *** at top-level: hyperellchangecurve(x^3+1,[1,Mat(1),0]) *** ^--------------------------------------- *** hyperellchangecurve: incorrect type in hyperellchangecurve (t_VEC). *** at top-level: hyperellchangecurve([],[1,Mat(1),0]) *** ^------------------------------------ *** hyperellchangecurve: incorrect type in hyperellchangecurve (t_VEC). *** at top-level: hyperellchangecurve(x^0,[1,matid(2),0]) *** ^--------------------------------------- *** hyperellchangecurve: constant polynomial in hyperellchangecurve. *** at top-level: hyperellminimalmodel(15625*x^6+15626*x^3+1,,5) *** ^---------------------------------------------- *** hyperellminimalmodel: incorrect type in hyperellminimalmodel (t_INT). *** at top-level: hyperellminimalmodel(15625*x^6+15626*x^3+1,,[x *** ^---------------------------------------------- *** hyperellminimalmodel: incorrect type in hyperellminimalmodel (t_VEC). Total time spent: 340 pari-2.17.2/src/test/32/bestappr0000644000175000017500000000124514676526175014746 0ustar billbill-1/7 -1/6 -1/7 [] -1/7 -1/7 [] "t_INT" 3/31 -1/48 (x^3 + 1)/(x^10 + 2) [] 1/(x + 1) 1/(x + 1) [] 1/(x^6 + 1) (-x + 2)/(x^2 - x) -x^2/(x - 1) -1/(x^5 - x^4) -x^10/(x^11 - 11*x^10 + 55*x^9 - 165*x^8 + 330*x^7 - 462*x^6 + 462*x^5 - 330 *x^4 + 165*x^3 - 55*x^2 + 11*x - 1) (-x^5 - x - 2)/(x^11 - 11*x^10 + 55*x^9 - 165*x^8 + 330*x^7 - 462*x^6 + 462* x^5 - 330*x^4 + 165*x^3 - 55*x^2 + 11*x - 1) (4*x^3 + 60*x^2 + 360*x + 840)/(x^4 - 16*x^3 + 120*x^2 - 480*x + 840) (-10*x^3 + 105*x)/(x^4 - 45*x^2 + 105) (-x^4 + 45*x^2 - 105)/(10*x^3 - 105*x) (1373*x^3 - 475*x^2 - 716*x + 181)/(113*x^3 - 92*x^2 + 173*x - 181) x^6 + x^5 - 5*x^4 - 4*x^3 + 6*x^2 + 3*x - 1 [] [] Total time spent: 1 pari-2.17.2/src/test/32/bnfisintnorm0000644000175000017500000001565714676526175015652 0ustar billbill echo = 1 ? setrand(1);bnf=bnfinit(x^2+105); ? for(i=1,1000,do(i)) 1:1 4:1 9:1 16:1 25:1 36:1 49:1 64:1 81:1 100:1 105:1 106:2 109:2 114:2 121:3 130:2 141:2 144:1 154:2 169:3 186:2 196:1 205:2 225:1 226:2 249:2 256:1 274:2 289:1 301:2 324:1 330:2 361:3 394:2 400:1 420:1 421:2 424:2 429:4 436:2 441:1 445:2 456:2 466:2 469:2 484:3 501:2 505:2 520:2 529:1 541:2 546:2 564:2 576:1 589:4 616:2 625:1 634:2 645:2 676:3 681:2 709:2 729:1 730:2 744:2 781:4 784:1 820:2 834:2 841:1 861:2 889:2 900:1 904:2 945:1 946:4 949:4 954:2 961:3 970:2 981:2 994:2 996:2 ? setrand(1);bnf=bnfinit(x^2-65); ? for(i=1,1000,do(i-500)) -491:2 -490:6 -485:2 -484:3 -481:2 -469:4 -464:10 -454:4 -446:4 -441:3 -439:2 -419:2 -416:6 -415:2 -406:8 -404:6 -400:5 -394:4 -389:2 -386:4 -376:8 -365:2 -364:6 -361:1 -360:4 -350:4 -335:2 -334:4 -329:4 -326:4 -324:3 -316:6 -315:2 -311:2 -296:8 -290:4 -289:1 -274:4 -269:2 -261:2 -260:3 -259:4 -256:9 -251:2 -250:2 -244:6 -235:2 -234:2 -225:1 -224:12 -211:2 -199:2 -196:9 -194:4 -191:2 -185:2 -181:2 -179:2 -169:1 -166:4 -160:6 -146:4 -144:5 -140:6 -139:2 -134:4 -131:2 -126:4 -121:1 -116:6 -104:4 -101:2 -100:3 -94:4 -91:2 -90:2 -81:1 -79:2 -74:4 -65:1 -64:7 -61:2 -56:8 -49:3 -40:4 -36:3 -35:2 -29:2 -26:2 -25:1 -16:5 -14:4 -10:2 -9:1 -4:3 -1:1 0:1 1:1 4:3 9:1 10:2 14:4 16:5 25:1 26:2 29:2 35:2 36:3 40:4 49:3 56:8 61:2 64:7 65:1 74:4 79:2 81:1 90:2 91:2 94:4 100:3 101:2 104:4 116:6 121:1 126:4 131:2 134:4 139:2 140:6 144:5 146:4 160:6 166:4 169:1 179:2 181:2 185:2 191:2 194:4 196:9 199:2 211:2 224:12 225:1 234:2 235:2 244:6 250:2 251:2 256:9 259:4 260:3 261:2 269:2 274:4 289:1 290:4 296:8 311:2 315:2 316:6 324:3 326:4 329:4 334:4 335:2 350:4 360:4 361:1 364:6 365:2 376:8 386:4 389:2 394:4 400:5 404:6 406:8 415:2 416:6 419:2 439:2 441:3 446:4 454:4 464:10 469:4 481:2 484:3 485:2 490:6 491:2 ? setrand(1);bnf=bnfinit(x^5-37); ? for(i=1,1000,do(i-500)) -499:1 -497:3 -496:2 -494:1 -491:3 -490:1 -487:1 -486:1 -483:1 -481:1 -478:1 -477:1 -476:1 -475:1 -474:1 -468:1 -466:1 -465:4 -463:1 -461:1 -457:1 -455:1 -454:1 -452:1 -450:1 -448:2 -447:1 -446:1 -443:1 -442:1 -441:1 -439:1 -435:1 -434:1 -426:2 -425:1 -424:1 -419:1 -417:1 -416:2 -415:1 -412:1 -405:1 -403:1 -402:1 -400:2 -398:1 -394:1 -392:1 -386:1 -382:3 -381:1 -380:1 -373:1 -372:4 -371:1 -370:1 -365:1 -364:1 -361:1 -360:1 -359:1 -358:1 -355:3 -354:1 -350:1 -349:1 -348:1 -347:1 -345:1 -343:1 -342:1 -340:1 -338:1 -337:1 -333:1 -332:1 -327:1 -326:1 -325:1 -324:1 -323:1 -321:1 -320:2 -317:1 -315:1 -314:1 -313:1 -310:1 -306:1 -304:2 -296:1 -293:1 -292:1 -291:1 -289:1 -288:2 -284:3 -282:1 -281:3 -280:1 -279:1 -276:1 -274:1 -272:2 -269:1 -267:1 -266:1 -265:1 -260:1 -259:1 -258:1 -256:3 -252:1 -250:1 -248:1 -247:1 -245:1 -243:1 -239:1 -238:1 -237:1 -234:1 -233:1 -227:1 -226:1 -225:1 -224:2 -223:1 -221:1 -217:1 -213:2 -212:1 -208:2 -206:1 -201:1 -200:1 -199:1 -197:1 -196:1 -193:1 -191:3 -190:1 -186:4 -185:1 -182:1 -180:1 -179:1 -177:1 -175:1 -174:1 -171:1 -170:1 -169:1 -166:1 -163:1 -162:1 -160:2 -157:1 -155:1 -153:1 -152:1 -148:1 -146:1 -144:2 -142:3 -141:1 -140:1 -138:1 -137:1 -136:1 -133:1 -130:1 -129:1 -128:2 -126:1 -125:1 -124:1 -119:1 -117:1 -113:1 -112:2 -106:1 -104:1 -103:1 -100:1 -98:1 -95:1 -93:4 -91:1 -90:1 -87:1 -85:1 -83:1 -81:1 -80:2 -76:1 -74:1 -73:1 -72:1 -71:3 -70:1 -69:1 -68:1 -65:1 -64:2 -63:1 -62:1 -56:1 -53:1 -52:1 -50:1 -49:1 -45:1 -40:1 -38:1 -37:1 -36:1 -35:1 -34:1 -32:2 -31:1 -28:1 -26:1 -25:1 -20:1 -19:1 -18:1 -17:1 -16:2 -14:1 -13:1 -10:1 -9:1 -8:1 -7:1 -5:1 -4:1 -2:1 -1:1 0:1 1:1 2:1 4:1 5:1 7:1 8:1 9:1 10:1 13:1 14:1 16:2 17:1 18:1 19:1 20:1 25:1 26:1 28:1 31:1 32:2 34:1 35:1 36:1 37:1 38:1 40:1 45:1 49:1 50:1 52:1 53:1 56:1 62:1 63:1 64:2 65:1 68:1 69:1 70:1 71:3 72:1 73:1 74:1 76:1 80:2 81:1 83:1 85:1 87:1 90:1 91:1 93:4 95:1 98:1 100:1 103:1 104:1 106:1 112:2 113:1 117:1 119:1 124:1 125:1 126:1 128:2 129:1 130:1 133:1 136:1 137:1 138:1 140:1 141:1 142:3 144:2 146:1 148:1 152:1 153:1 155:1 157:1 160:2 162:1 163:1 166:1 169:1 170:1 171:1 174:1 175:1 177:1 179:1 180:1 182:1 185:1 186:4 190:1 191:3 193:1 196:1 197:1 199:1 200:1 201:1 206:1 208:2 212:1 213:2 217:1 221:1 223:1 224:2 225:1 226:1 227:1 233:1 234:1 237:1 238:1 239:1 243:1 245:1 247:1 248:1 250:1 252:1 256:3 258:1 259:1 260:1 265:1 266:1 267:1 269:1 272:2 274:1 276:1 279:1 280:1 281:3 282:1 284:3 288:2 289:1 291:1 292:1 293:1 296:1 304:2 306:1 310:1 313:1 314:1 315:1 317:1 320:2 321:1 323:1 324:1 325:1 326:1 327:1 332:1 333:1 337:1 338:1 340:1 342:1 343:1 345:1 347:1 348:1 349:1 350:1 354:1 355:3 358:1 359:1 360:1 361:1 364:1 365:1 370:1 371:1 372:4 373:1 380:1 381:1 382:3 386:1 392:1 394:1 398:1 400:2 402:1 403:1 405:1 412:1 415:1 416:2 417:1 419:1 424:1 425:1 426:2 434:1 435:1 439:1 441:1 442:1 443:1 446:1 447:1 448:2 450:1 452:1 454:1 455:1 457:1 461:1 463:1 465:4 466:1 468:1 474:1 475:1 476:1 477:1 478:1 481:1 483:1 486:1 487:1 490:1 491:3 494:1 496:2 497:3 499:1 500:1 ? bnfisintnorm(bnfinit(x^3+5),5) [-x] ? bnfisintnorm(bnfinit('y^2+93),54647) [] ? bnf=bnfinit('y^2-1466,1); ? bnfisintnorm(bnf,10,1) [[[-268, 7]~, 1; -4005185*y - 153352043, 1], [[-268, -7]~, 1; -4005185*y - 1 53352043, 1]] ? bnfisintnorm(bnf,-10,1) [Mat([[-268, 7]~, 1]), Mat([[-268, -7]~, 1])] ? bnf=bnfinit('y^2-100129,1); ? bnfisintnorm(bnf,-6,1) [[2, 3071; 5, 47; 7, 129; 13, 47; 17, -176; [3515009, 45881]~, -214; [346912 8, -45881]~, -161; [8580951, -30241]~, -247; [8611192, 30241]~, -245; [-8425 8577, 180407]~, 44; [-84438984, -180407]~, 26; [-70198541, 363931]~, -155; [ -70562472, -363931]~, -173; [1474271, -6361]~, 97; [1480632, 6361]~, 92; [-4 280741, -15869]~, 423; [-4264872, 15869]~, 421; [-3059431, 47921]~, 29; [-31 07352, -47921]~, 16; [-2407, 17]~, -1], [2, 665; 5, -79; 7, 164; 13, -79; 17 , -85; [3515009, 45881]~, -15; [3469128, -45881]~, -116; [8580951, -30241]~, -8; [8611192, 30241]~, -16; [-84258577, 180407]~, -76; [-84438984, -180407] ~, -42; [-70198541, 363931]~, -122; [-70562472, -363931]~, -88; [1474271, -6 361]~, 172; [1480632, 6361]~, 185; [-4280741, -15869]~, 93; [-4264872, 15869 ]~, 101; [-3059431, 47921]~, -5; [-3107352, -47921]~, 16; [-2407, 17]~, -1], [2, -678; 5, 79; 7, -165; 13, 79; 17, 86; [3515009, 45881]~, 16; [3469128, -45881]~, 117; [8580951, -30241]~, 9; [8611192, 30241]~, 17; [-84258577, 180 407]~, 76; [-84438984, -180407]~, 42; [-70198541, 363931]~, 123; [-70562472, -363931]~, 89; [1474271, -6361]~, -173; [1480632, 6361]~, -186; [-4280741, -15869]~, -95; [-4264872, 15869]~, -103; [-3059431, 47921]~, 5; [-3107352, - 47921]~, -16; [-2407, 17]~, 1], [2, -3084; 5, -47; 7, -130; 13, -47; 17, 177 ; [3515009, 45881]~, 215; [3469128, -45881]~, 162; [8580951, -30241]~, 248; [8611192, 30241]~, 246; [-84258577, 180407]~, -44; [-84438984, -180407]~, -2 6; [-70198541, 363931]~, 156; [-70562472, -363931]~, 174; [1474271, -6361]~, -98; [1480632, 6361]~, -93; [-4280741, -15869]~, -425; [-4264872, 15869]~, -423; [-3059431, 47921]~, -29; [-3107352, -47921]~, -16; [-2407, 17]~, 1]] ? bnf=bnfinit('x^2-2305843005992468481,1); ? v=bnfisintnorm(bnf,2305843008139952128,1); ? #v 31 ? print("Total time spent: ",gettime); Total time spent: 531 pari-2.17.2/src/test/32/forvec0000644000175000017500000000360214676526175014411 0ustar billbill[3/2, 3/2, 3/2] [3/2, 3/2, 5/2] [3/2, 5/2, 3/2] [3/2, 5/2, 5/2] [5/2, 3/2, 3/2] [5/2, 3/2, 5/2] [5/2, 5/2, 3/2] [5/2, 5/2, 5/2] [3/2, 3/2, 3/2] [3/2, 3/2, 5/2] [3/2, 3/2, 7/2] [3/2, 5/2, 5/2] [3/2, 5/2, 7/2] [3/2, 7/2, 7/2] [5/2, 5/2, 5/2] [5/2, 5/2, 7/2] [5/2, 7/2, 7/2] [7/2, 7/2, 7/2] [3/2, 5/2, 7/2] [1, 1, 1] [1, 1, 2] [1, 1, 3] [1, 2, 1] [1, 2, 2] [1, 2, 3] [1, 3, 1] [1, 3, 2] [1, 3, 3] [2, 1, 1] [2, 1, 2] [2, 1, 3] [2, 2, 1] [2, 2, 2] [2, 2, 3] [2, 3, 1] [2, 3, 2] [2, 3, 3] [3, 1, 1] [3, 1, 2] [3, 1, 3] [3, 2, 1] [3, 2, 2] [3, 2, 3] [3, 3, 1] [3, 3, 2] [3, 3, 3] [1, 1, 1] [1, 1, 2] [1, 1, 3] [1, 2, 2] [1, 2, 3] [1, 3, 3] [2, 2, 2] [2, 2, 3] [2, 3, 3] [3, 3, 3] [1, 2, 3] [1, 1] [3/2, 3/2, 3/2] [3/2, 3/2, 5/2] [3/2, 3/2, 7/2] [3/2, 5/2, 5/2] [3/2, 5/2, 7/2] [3/2, 7/2, 7/2] [5/2, 5/2, 5/2] [5/2, 5/2, 7/2] [5/2, 7/2, 7/2] [7/2, 7/2, 7/2] [3/2, 2, 5/2] [3/2, 2, 7/2] [3/2, 2, 9/2] [3/2, 3, 7/2] [3/2, 3, 9/2] [3/2, 4, 9/2] [5/2, 3, 7/2] [5/2, 3, 9/2] [5/2, 4, 9/2] [0] [0, 0, 0] [0, 1, 0] [1, 0, 0] [1, 1, 0] [2, 0, 0] [2, 1, 0] [2, 1, 0, -25] [0, -2, -4] [2, 3, 3, 0] [-1, 1, 4, 2] [] *** at top-level: forvec(v=[[1]],) *** ^---------------- *** forvec: incorrect type in forvec [expected vector not of type [min,MAX]] (t_VEC). *** at top-level: forvec(v=[[1,I]],) *** ^------------------ *** forvec: incorrect type in gfloor (t_COMPLEX). *** at top-level: forvec(v=[[1,1],[1,1]],,3) *** ^-------------------------- *** forvec: invalid flag in forvec. *** at top-level: forvec(v=[2,3,0,-1,2],) *** ^----------------------- *** forvec: incorrect type in forvec [expected vector not of type [min,MAX]] (t_INT). *** at top-level: forvec(v=[[2,3],3,0],) *** ^---------------------- *** forvec: incorrect type in forvec [expected vector not of type [min,MAX]] (t_INT). Total time spent: 1 pari-2.17.2/src/test/32/qfsolve0000644000175000017500000000346114676526175014607 0ustar billbilldim=3 [2, 42762409] [3, 3617] [4, 5] [5, 43] [6, 31] [9, 5] [11, 7] [12, 3] [13, 17] [14, 19] [15, 73] [16, 79] [17, 38287] [18, 3774601] [19, 7] [20, 3] [21, 61] [22, 3] [23, 229] [24, 7] [25, 3] [27, 68196433] [28, 2393] [29, 13] [30, 145963897] [31, 71] [33, 433] [34, 3] [35, 409] [36, 3] [37, -1] [38, 11483] [41, 11] [44, -1] [45, 281] [46, 4363] [47, -1] [48, 7] [49, 41] [52, 5965507] [53, 13] [56, 135319] [57, 2473301] [58, 141613] [59, -1] [60, 109] [61, 3] [62, -1] [65, 5] [66, 13] [67, 11] [68, 271] [69, 7] [70, 642419] [73, 29] [74, 1951] [76, 3] [77, -1] [78, 107] [79, -1] [80, 48199741] [81, 89] [82, 11] [83, 157] [84, 197] [85, 5] [86, -1] [87, -1] [88, 11] [89, 29] [90, 7] [91, -1] [92, 3] [93, 17] [94, 7] [95, 3] [98, 31] [99, 19] dim=4 [20, 2] [71, 2] [81, 2] [96, 2] [100, 2] dim=5 dim=6 dim=7 dim=8 [-3 -10 3] [ 5 -6 -5] [-1 0 -1] [-3 2 11] [ 5 -26 27] [-1 4 -5] [-3 -16 -10] [ 5 4 -6] [-1 -2 -2] [1]~ -1 -2 [1, 0]~ [-42, 35]~ [-1 0 1] [ 0 2 0] [ 1 0 1] [0, 5, -1]~ 3 [-12 0 -1] [ 0 24 0] [ 0 0 24] [310 -62 3] [-62 16 -1] [-18 2 0] [[1, -1, 2; -1, 2, -3; 2, -3, 6], [0, -2/13, -1/13; 2/17, 1/17, -1/17; 1/17, -19/221, 36/221], 1] [[-1, 0, 0; 0, -1, 0; 0, 0, 1], [0, 0, 1/5; 5/323, -1/323, 0; -1/323, -5/323 , 0], 1/26] *** at top-level: qfsolve([1,0,0;0,1,1;0,0,1]) *** ^---------------------------- *** qfsolve: incorrect type in qfsolve [not symmetric] (t_MAT). [-1, -1, 5, 1, 0, 0, 2]~ *** at top-level: qfsolve(Q) *** ^---------- *** qfsolve: sorry, qfsolve, dim >= 10 is not yet implemented. *** at top-level: ...]/5);F=factor(matdet(M));qfsolve([M,F]) *** ^-------------- *** qfsolve: sorry, qfsolve, dim >= 10 is not yet implemented. Total time spent: 1627 pari-2.17.2/src/test/32/chinese0000644000175000017500000000052514760123736014532 0ustar billbillMod(x, x^2 + 1) Mod(x, x^4 - 1) Mod(2, 6)*x^2 + Mod(1, 6)*x + Mod(1, 6) [Mod(1, 4), Mod(1, 6)] *** at top-level: chinese(1) *** ^---------- *** chinese: incorrect type in association (t_INT). Mod(0, 1) Mod(x + 1, x^2) Mod(x + 1, 2*x^2) Mod(x + 1, x^2) Mod(10, 15)*x^2 + Mod(1, 15)*x + Mod(14, 15) Total time spent: 0 pari-2.17.2/src/test/32/factormod0000644000175000017500000003750214676526175015111 0ustar billbill *** Warning: new stack size = 350000000 (333.786 Mbytes). [x + 7, 1; x + 8, 1; x + 20, 1; x + 21, 1; x + 24, 1; x + 50, 1; x + 60, 1; x + 63, 1; x + 68, 1; x + 72, 1; x + 125, 1; x + 139, 1; x + 146, 1; x + 150 , 1; x + 170, 1; x + 180, 1; x + 189, 1; x + 193, 1; x + 204, 1; x + 212, 1; x + 216, 1; x + 239, 1; x + 293, 1; x + 338, 1; x + 343, 1; x + 346, 1; x + 364, 1; x + 365, 1; x + 375, 1; x + 377, 1; x + 392, 1; x + 406, 1; x + 412 , 1; x + 416, 1; x + 417, 1; x + 425, 1; x + 438, 1; x + 448, 1; x + 450, 1; x + 457, 1; x + 463, 1; x + 464, 1; x + 466, 1; x + 502, 1; x + 506, 1; x + 510, 1; x + 512, 1; x + 530, 1; x + 540, 1; x + 567, 1; x + 578, 1; x + 579 , 1; x + 612, 1; x + 614, 1; x + 622, 1; x + 636, 1; x + 648, 1; x + 682, 1; x + 716, 1; x + 717, 1; x + 751, 1; x + 767, 1; x + 769, 1; x + 778, 1; x + 791, 1; x + 814, 1; x + 826, 1; x + 844, 1; x + 845, 1; x + 865, 1; x + 874 , 1; x + 879, 1; x + 881, 1; x + 904, 1; x + 910, 1; x + 923, 1; x + 944, 1; x + 980, 1; x + 982, 1; x + 994, 1; x + 1014, 1; x + 1015, 1; x + 1029, 1; x + 1030, 1; x + 1038, 1; x + 1040, 1; x + 1057, 1; x + 1092, 1; x + 1095, 1 ; x + 1120, 1; x + 1125, 1; x + 1131, 1; x + 1136, 1; x + 1160, 1; x + 1165, 1; x + 1176, 1; x + 1178, 1; x + 1208, 1; x + 1218, 1; x + 1223, 1; x + 122 6, 1; x + 1236, 1; x + 1241, 1; x + 1248, 1; x + 1251, 1; x + 1255, 1; x + 1 265, 1; x + 1275, 1; x + 1279, 1; x + 1280, 1; x + 1282, 1; x + 1314, 1; x + 1325, 1; x + 1327, 1; x + 1344, 1; x + 1350, 1; x + 1371, 1; x + 1373, 1; x + 1389, 1; x + 1392, 1; x + 1398, 1; x + 1403, 1; x + 1406, 1; x + 1409, 1; x + 1417, 1; x + 1445, 1; x + 1468, 1; x + 1481, 1; x + 1506, 1; x + 1518, 1; x + 1522, 1; x + 1526, 1; x + 1530, 1; x + 1535, 1; x + 1536, 1; x + 1555 , 1; x + 1573, 1; x + 1590, 1; x + 1620, 1; x + 1658, 1; x + 1681, 1; x + 16 87, 1; x + 1694, 1; x + 1701, 1; x + 1705, 1; x + 1706, 1; x + 1721, 1; x + 1734, 1; x + 1737, 1; x + 1744, 1; x + 1756, 1; x + 1763, 1; x + 1783, 1; x + 1790, 1; x + 1802, 1; x + 1804, 1; x + 1826, 1; x + 1836, 1; x + 1842, 1; x + 1849, 1; x + 1866, 1; x + 1868, 1; x + 1882, 1; x + 1891, 1; x + 1892, 1 ; x + 1901, 1; x + 1908, 1; x + 1927, 1; x + 1928, 1; x + 1936, 1; x + 1942, 1; x + 1944, 1; x + 1945, 1; x + 2021, 1; x + 2035, 1; x + 2046, 1; x + 205 4, 1; x + 2065, 1; x + 2068, 1; x + 2110, 1; x + 2148, 1; x + 2151, 1; x + 2 164, 1; x + 2171, 1; x + 2185, 1; x + 2209, 1; x + 2212, 1; x + 2213, 1; x + 2231, 1; x + 2253, 1; x + 2257, 1; x + 2260, 1; x + 2275, 1; x + 2276, 1; x + 2291, 1; x + 2293, 1; x + 2301, 1; x + 2307, 1; x + 2334, 1; x + 2338, 1; x + 2360, 1; x + 2373, 1; x + 2429, 1; x + 2434, 1; x + 2442, 1; x + 2450, 1; x + 2455, 1; x + 2461, 1; x + 2478, 1; x + 2483, 1; x + 2485, 1; x + 2528 , 1; x + 2532, 1; x + 2535, 1; x + 2575, 1; x + 2593, 1; x + 2595, 1; x + 26 00, 1; x + 2602, 1; x + 2622, 1; x + 2626, 1; x + 2633, 1; x + 2637, 1; x + 2643, 1; x + 2672, 1; x + 2674, 1; x + 2689, 1; x + 2712, 1; x + 2717, 1; x + 2730, 1; x + 2769, 1; x + 2776, 1; x + 2800, 1; x + 2827, 1; x + 2828, 1; x + 2832, 1; x + 2840, 1; x + 2873, 1; x + 2894, 1; x + 2900, 1; x + 2926, 1 ; x + 2929, 1; x + 2940, 1; x + 2941, 1; x + 2945, 1; x + 2946, 1; x + 2947, 1; x + 2957, 1; x + 2982, 1; x + 3007, 1; x + 3017, 1; x + 3019, 1; x + 302 0, 1; x + 3028, 1; x + 3042, 1; x + 3045, 1; x + 3056, 1; x + 3065, 1; x + 3 087, 1; x + 3090, 1; x + 3094, 1; x + 3114, 1; x + 3116, 1; x + 3120, 1; x + 3121, 1; x + 3154, 1; x + 3163, 1; x + 3171, 1; x + 3200, 1; x + 3205, 1; x + 3221, 1; x + 3229, 1; x + 3232, 1; x + 3238, 1; x + 3268, 1; x + 3276, 1; x + 3278, 1; x + 3285, 1; x + 3317, 1; x + 3332, 1; x + 3338, 1; x + 3343, 1; x + 3344, 1; x + 3359, 1; x + 3360, 1; x + 3368, 1; x + 3375, 1; x + 3393 , 1; x + 3407, 1; x + 3408, 1; x + 3418, 1; x + 3448, 1; x + 3449, 1; x + 34 51, 1; x + 3454, 1; x + 3466, 1; x + 3469, 1; x + 3480, 1; x + 3495, 1; x + 3502, 1; x + 3511, 1; x + 3515, 1; x + 3528, 1; x + 3534, 1; x + 3536, 1; x + 3572, 1; x + 3578, 1; x + 3589, 1; x + 3607, 1; x + 3624, 1; x + 3654, 1; x + 3669, 1; x + 3670, 1; x + 3678, 1; x + 3708, 1; x + 3723, 1; x + 3744, 1 ; x + 3753, 1; x + 3758, 1; x + 3765, 1; x + 3769, 1; x + 3793, 1; x + 3795, 1; x + 3805, 1; x + 3808, 1; x + 3815, 1; x + 3821, 1; x + 3825, 1; x + 383 7, 1; x + 3840, 1; x + 3846, 1; x + 3869, 1; x + 3889, 1; x + 3929, 1; x + 3 941, 1; x + 3942, 1; x + 3944, 1; x + 3947, 1; x + 3959, 1; x + 3961, 1; x + 3975, 1; x + 3981, 1; x + 3982, 1; x + 4032, 1; x + 4050, 1; x + 4094, 1; x + 4099, 1; x + 4103, 1; x + 4113, 1; x + 4119, 1; x + 4138, 1; x + 4145, 1; x + 4153, 1; x + 4167, 1; x + 4176, 1; x + 4194, 1; x + 4209, 1; x + 4218, 1; x + 4222, 1; x + 4227, 1; x + 4235, 1; x + 4238, 1; x + 4251, 1; x + 4265 , 1; x + 4267, 1; x + 4273, 1; x + 4289, 1; x + 4301, 1; x + 4335, 1; x + 43 52, 1; x + 4360, 1; x + 4378, 1; x + 4390, 1; x + 4404, 1; x + 4411, 1; x + 4423, 1; x + 4443, 1; x + 4475, 1; x + 4483, 1; x + 4489, 1; x + 4499, 1; x + 4504, 1; x + 4505, 1; x + 4510, 1; x + 4518, 1; x + 4523, 1; x + 4538, 1; x + 4554, 1; x + 4564, 1; x + 4565, 1; x + 4566, 1; x + 4578, 1; x + 4590, 1 ; x + 4605, 1; x + 4608, 1; x + 4649, 1; x + 4661, 1; x + 4665, 1; x + 4670, 1; x + 4684, 1; x + 4693, 1; x + 4697, 1; x + 4705, 1; x + 4719, 1; x + 472 7, 1; x + 4730, 1; x + 4739, 1; x + 4770, 1; x + 4781, 1; x + 4820, 1; x + 4 834, 1; x + 4840, 1; x + 4855, 1; x + 4860, 1; x + 4883, 1; x + 4906, 1; x + 4913, 1; x + 4924, 1; x + 4939, 1; x + 4963, 1; x + 4974, 1; x + 4987, 1; x + 5002, 1; x + 5039, 1; x + 5043, 1; x + 5054, 1; x + 5061, 1; x + 5063, 1; x + 5078, 1; x + 5082, 1; x + 5102, 1; x + 5103, 1; x + 5115, 1; x + 5118, 1; x + 5135, 1; x + 5163, 1; x + 5170, 1; x + 5189, 1; x + 5202, 1; x + 5207 , 1; x + 5209, 1; x + 5211, 1; x + 5216, 1; x + 5219, 1; x + 5232, 1; x + 52 46, 1; x + 5268, 1; x + 5275, 1; x + 5287, 1; x + 5289, 1; x + 5349, 1; x + 5368, 1; x + 5370, 1; x + 5386, 1; x + 5406, 1; x + 5410, 1; x + 5411, 1; x + 5412, 1; x + 5416, 1; x + 5461, 1; x + 5464, 1; x + 5478, 1; x + 5508, 1; x + 5509, 1; x + 5518, 1; x + 5526, 1; x + 5530, 1; x + 5547, 1; x + 5588, 1 ; x + 5596, 1; x + 5598, 1; x + 5604, 1; x + 5609, 1; x + 5618, 1; x + 5646, 1; x + 5650, 1; x + 5653, 1; x + 5662, 1; x + 5672, 1; x + 5673, 1; x + 567 6, 1; x + 5690, 1; x + 5703, 1; x + 5724, 1; x + 5734, 1; x + 5776, 1; x + 5 781, 1; x + 5784, 1; x + 5789, 1; x + 5797, 1; x + 5808, 1; x + 5826, 1; x + 5832, 1; x + 5835, 1; x + 5836, 1; x + 5845, 1; x + 5900, 1; x + 5959, 1; x + 5966, 1; x + 5969, 1; x + 5987, 1; x + 5993, 1; x + 6026, 1; x + 6063, 1; x + 6085, 1; x + 6086, 1; x + 6092, 1; x + 6094, 1; x + 6105, 1; x + 6125, 1; x + 6127, 1; x + 6138, 1; x + 6151, 1; x + 6162, 1; x + 6164, 1; x + 6184 , 1; x + 6195, 1; x + 6197, 1; x + 6203, 1; x + 6204, 1; x + 6226, 1; x + 62 63, 1; x + 6296, 1; x + 6302, 1; x + 6320, 1; x + 6323, 1; x + 6330, 1; x + 6389, 1; x + 6444, 1; x + 6453, 1; x + 6454, 1; x + 6457, 1; x + 6463, 1; x + 6481, 1; x + 6492, 1; x + 6500, 1; x + 6505, 1; x + 6508, 1; x + 6513, 1; x + 6555, 1; x + 6565, 1; x + 6586, 1; x + 6599, 1; x + 6613, 1; x + 6616, 1 ; x + 6617, 1; x + 6627, 1; x + 6636, 1; x + 6639, 1; x + 6643, 1; x + 6671, 1; x + 6680, 1; x + 6685, 1; x + 6691, 1; x + 6693, 1; x + 6701, 1; x + 674 2, 1; x + 6759, 1; x + 6763, 1; x + 6771, 1; x + 6780, 1; x + 6781, 1; x + 6 811, 1; x + 6825, 1; x + 6828, 1; x + 6873, 1; x + 6877, 1; x + 6878, 1; x + 6879, 1; x + 6883, 1; x + 6903, 1; x + 6919, 1; x + 6921, 1; x + 6940, 1; x + 7000, 1; x + 7002, 1; x + 7014, 1; x + 7021, 1; x + 7043, 1; x + 7057, 1; x + 7070, 1; x + 7073, 1; x + 7078, 1; x + 7080, 1; x + 7082, 1; x + 7087, 1; x + 7100, 1; x + 7119, 1; x + 7126, 1; x + 7154, 1; x + 7171, 1; x + 7174 , 1; x + 7186, 1; x + 7187, 1; x + 7207, 1; x + 7211, 1; x + 7226, 1; x + 72 28, 1; x + 7235, 1; x + 7246, 1; x + 7250, 1; x + 7287, 1; x + 7302, 1; x + 7315, 1; x + 7326, 1; x + 7350, 1; x + 7365, 1; x + 7376, 1; x + 7383, 1; x + 7406, 1; x + 7429, 1; x + 7434, 1; x + 7449, 1; x + 7455, 1; x + 7469, 1; x + 7508, 1; x + 7519, 1; x + 7550, 1; x + 7559, 1; x + 7562, 1; x + 7570, 1 ; x + 7584, 1; x + 7592, 1; x + 7596, 1; x + 7605, 1; x + 7619, 1; x + 7624, 1; x + 7628, 1; x + 7640, 1; x + 7681, 1; x + 7684, 1; x + 7699, 1; x + 771 1, 1; x + 7723, 1; x + 7724, 1; x + 7725, 1; x + 7735, 1; x + 7751, 1; x + 7 766, 1; x + 7771, 1; x + 7779, 1; x + 7784, 1; x + 7785, 1; x + 7790, 1; x + 7800, 1; x + 7806, 1; x + 7814, 1; x + 7846, 1; x + 7866, 1; x + 7878, 1; x + 7885, 1; x + 7899, 1; x + 7911, 1; x + 7929, 1; x + 7937, 1; x + 7954, 1; x + 7988, 1; x + 8000, 1; x + 8016, 1; x + 8022, 1; x + 8024, 1; x + 8038, 1; x + 8051, 1; x + 8054, 1; x + 8062, 1; x + 8067, 1; x + 8071, 1; x + 8080 , 1; x + 8095, 1; x + 8113, 1; x + 8122, 1; x + 8136, 1; x + 8144, 1; x + 81 51, 1; x + 8170, 1; x + 8176, 1; x + 8186, 1; x + 8190, 1; x + 8195, 1; x + 8239, 1; x + 8257, 1; x + 8307, 1; x + 8308, 1; x + 8314, 1; x + 8328, 1; x + 8330, 1; x + 8342, 1; x + 8345, 1; x + 8347, 1; x + 8348, 1; x + 8360, 1; x + 8400, 1; x + 8420, 1; x + 8443, 1; x + 8449, 1; x + 8452, 1; x + 8464, 1 ; x + 8468, 1; x + 8474, 1; x + 8481, 1; x + 8484, 1; x + 8494, 1; x + 8496, 1; x + 8520, 1; x + 8524, 1; x + 8531, 1; x + 8536, 1; x + 8545, 1; x + 856 6, 1; x + 8581, 1; x + 8611, 1; x + 8619, 1; x + 8620, 1; x + 8635, 1; x + 8 665, 1; x + 8682, 1; x + 8700, 1; x + 8711, 1; x + 8717, 1; x + 8753, 1; x + 8755, 1; x + 8761, 1; x + 8774, 1; x + 8778, 1; x + 8787, 1; x + 8794, 1; x + 8809, 1; x + 8820, 1; x + 8823, 1; x + 8835, 1; x + 8838, 1; x + 8840, 1; x + 8841, 1; x + 8871, 1; x + 8881, 1; x + 8882, 1; x + 8896, 1; x + 8914, 1; x + 8921, 1; x + 8929, 1; x + 8930, 1; x + 8945, 1; x + 8946, 1; x + 8951 , 1; x + 8957, 1; x + 8972, 1; x + 9004, 1; x + 9011, 1; x + 9013, 1; x + 90 21, 1; x + 9051, 1; x + 9057, 1; x + 9060, 1; x + 9068, 1; x + 9084, 1; x + 9089, 1; x + 9118, 1; x + 9126, 1; x + 9135, 1; x + 9168, 1; x + 9169, 1; x + 9173, 1; x + 9175, 1; x + 9195, 1; x + 9199, 1; x + 9202, 1; x + 9224, 1; x + 9233, 1; x + 9244, 1; x + 9247, 1; x + 9261, 1; x + 9269, 1; x + 9270, 1 ; x + 9272, 1; x + 9282, 1; x + 9307, 1; x + 9332, 1; x + 9342, 1; x + 9343, 1; x + 9344, 1; x + 9348, 1; x + 9349, 1; x + 9360, 1; x + 9363, 1; x + 938 9, 1; x + 9395, 1; x + 9416, 1; x + 9449, 1; x + 9457, 1; x + 9461, 1; x + 9 462, 1; x + 9489, 1; x + 9513, 1; x + 9520, 1; x + 9559, 1; x + 9572, 1; x + 9577, 1; x + 9600, 1; x + 9615, 1; x + 9617, 1; x + 9646, 1; x + 9652, 1; x + 9656, 1; x + 9663, 1; x + 9667, 1; x + 9687, 1; x + 9689, 1; x + 9694, 1; x + 9696, 1; x + 9714, 1; x + 9754, 1; x + 9757, 1; x + 9761, 1; x + 9804, 1; x + 9806, 1; x + 9811, 1; x + 9828, 1; x + 9834, 1; x + 9839, 1; x + 9847 , 1; x + 9855, 1; x + 9860, 1; x + 9916, 1; x + 9929, 1; x + 9951, 1; x + 99 55, 1; x + 9982, 1; x + 9988, 1; x + 9996, 1; x + 9998, 1; x + 10013, 1; x + 10014, 1; x + 10029, 1; x + 10032, 1; x + 10036, 1; x + 10058, 1; x + 10076 , 1; x + 10077, 1; x + 10080, 1; x + 10104, 1; x + 10118, 1; x + 10125, 1; x + 10138, 1; x + 10141, 1; x + 10179, 1; x + 10221, 1; x + 10224, 1; x + 102 35, 1; x + 10243, 1; x + 10254, 1; x + 10268, 1; x + 10344, 1; x + 10345, 1; x + 10347, 1; x + 10353, 1; x + 10361, 1; x + 10362, 1; x + 10381, 1; x + 1 0388, 1; x + 10397, 1; x + 10398, 1; x + 10407, 1; x + 10421, 1; x + 10423, 1; x + 10440, 1; x + 10447, 1; x + 10453, 1; x + 10463, 1; x + 10485, 1; x + 10487, 1; x + 10499, 1; x + 10506, 1; x + 10526, 1; x + 10533, 1; x + 10545 , 1; x + 10552, 1; x + 10555, 1; x + 10568, 1; x + 10583, 1; x + 10584, 1; x + 10588, 1; x + 10595, 1; x + 10602, 1; x + 10608, 1; x + 10631, 1; x + 106 69, 1; x + 10699, 1; x + 10716, 1; x + 10734, 1; x + 10753, 1; x + 10754, 1; x + 10759, 1; x + 10763, 1; x + 10767, 1; x + 10771, 1; x + 10783, 1; x + 1 0808, 1; x + 10821, 1; x + 10844, 1; x + 10872, 1; x + 10880, 1; x + 10883, 1; x + 10886, 1; x + 10891, 1; x + 10897, 1; x + 10900, 1; x + 10916, 1; x + 10918, 1; x + 10939, 1; x + 10945, 1; x + 10962, 1; x + 10964, 1; x + 10975 , 1; x + 11007, 1; x + 11009, 1; x + 11010, 1; x + 11014, 1; x + 11024, 1; x + 11034, 1; x + 11038, 1; x + 11041, 1; x + 11048, 1; x + 11053, 1; x + 110 63, 1; x + 11066, 1; x + 11071, 1; x + 11081, 1; x + 11111, 1; x + 11113, 1; x + 11124, 1; x + 11129, 1; x + 11153, 1; x + 11158, 1; x + 11164, 1; x + 1 1169, 1; x + 11194, 1; x + 11197, 1; x + 11232, 1; x + 11249, 1; x + 11251, 1; x + 11259, 1; x + 11260, 1; x + 11274, 1; x + 11275, 1; x + 11295, 1; x + 11307, 1; x + 11309, 1; x + 11345, 1; x + 11366, 1; x + 11379, 1; x + 11385 , 1; x + 11408, 1; x + 11410, 1; x + 11415, 1; x + 11424, 1; x + 11444, 1; x + 11445, 1; x + 11463, 1; x + 11475, 1; x + 11498, 1; x + 11511, 1; x + 115 20, 1; x + 11522, 1; x + 11538, 1; x + 11572, 1; x + 11573, 1; x + 11607, 1; x + 11641, 1; x + 11653, 1; x + 11667, 1; x + 11675, 1; x + 11677, 1; x + 1 1710, 1; x + 11711, 1; x + 11722, 1; x + 11749, 1; x + 11759, 1; x + 11777, 1; x + 11779, 1; x + 11783, 1; x + 11787, 1; x + 11823, 1; x + 11825, 1; x + 11826, 1; x + 11832, 1; x + 11839, 1; x + 11841, 1; x + 11851, 1; x + 11864 , 1; x + 11872, 1; x + 11873, 1; x + 11877, 1; x + 11883, 1; x + 11897, 1; x + 11912, 1; x + 11914, 1; x + 11924, 1; x + 11925, 1; x + 11943, 1; x + 119 46, 1; x + 11951, 1; x + 11996, 1; x + 12050, 1; x + 12073, 1; x + 12077, 1; x + 12085, 1; x + 12096, 1; x + 12100, 1; x + 12109, 1; x + 12119, 1; x + 1 2139, 1; x + 12143, 1; x + 12150, 1; x + 12164, 1; x + 12217, 1; x + 12221, 1; x + 12226, 1; x + 12229, 1; x + 12239, 1; x + 12265, 1; x + 12268, 1; x + 12269, 1; x + 12281, 1; x + 12282, 1] [1 1 1] [1 1 1] [1 3 27] [1 1 1] [1 2 4 5 15 15 52 131 373 400] [4 1 1 1 1 1 1 1 1 1] [Mod(1, 41), Mod(3, 41), Mod(9, 41), Mod(14, 41), Mod(27, 41), Mod(32, 41), Mod(38, 41), Mod(40, 41)]~ [Mod(1, 5), Mod(2, 5)]~ []~ [ Mod(1, 2)*x 1] [Mod(1, 2)*x + Mod(1, 2) 2] [Mod(0, 2) 1] matrix(0,2) matrix(0,2) matrix(0,2) [1 1] [1 2] [2 1] [Mod(1, 2)*x^3 + Mod(1, 2)*x^2 + Mod(1, 2)*x 1] [ Mod(1, 2)*x + Mod(1, 2) 2] [ Mod(1, 2)*x^2 + Mod(1, 2)*x 1] [Mod(1, 2)*x^2 + Mod(1, 2)*x + Mod(1, 2) 2] [Mod(1, 7), Mod(2, 7), Mod(3, 7), Mod(5, 7), Mod(6, 7)]~ []~ [Mod(0, 18446744073709551629)]~ [Mod(9223372036854775814, 18446744073709551629)]~ [Mod(1, 18446744073709551629)*x + Mod(2370518075556110396, 18446744073709551 629) 1] [Mod(1, 18446744073709551629)*x + Mod(16076225998153441233, 1844674407370955 1629) 1] [1 1] [1 1] [2 1] [Mod(1, 18446744073709551629)*x^2 + Mod(2370518075556110396, 184467440737095 51629) 1] [Mod(1, 18446744073709551629)*x^2 + Mod(16076225998153441233, 18446744073709 551629) 1] [2 1] [2 1] [4 1] [Mod(1, 18446744073709551629)*x + Mod(2370518075556110396, 18446744073709551 629) 1] [Mod(1, 18446744073709551629)*x + Mod(16076225998153441233, 1844674407370955 1629) 1] [Mod(0, 18446744073709551629) 1] matrix(0,2) matrix(0,2) matrix(0,2) 1 0 0 [Mod(1, 100000000000000000039)*x + Mod(1, 100000000000000000039) 2] *** at top-level: polrootsmod(x^3-1,2^101-1) *** ^-------------------------- *** polrootsmod: not a prime number in polrootsmod: 2535301200456458802993406410751. *** at top-level: polrootsmod(x^10-1,1023) *** ^------------------------ *** polrootsmod: not a prime number in polrootsmod: 1023. *** at top-level: polrootsmod(Pol(0),p) *** ^--------------------- *** polrootsmod: zero polynomial in FpX_roots. *** at top-level: polrootsmod(Pol(0),2) *** ^--------------------- *** polrootsmod: zero polynomial in FpX_roots. *** at top-level: factormod(x,0) *** ^-------------- *** factormod: incorrect type in factormod (t_INT). *** at top-level: factormod(x^3+1,[y^2+1,2]) *** ^-------------------------- *** factormod: not an irreducible polynomial in FpX_ffintersect: y^2 + 1. *** at top-level: factormod(x^3+1,[y^2+1,5]) *** ^-------------------------- *** factormod: not an irreducible polynomial in FpX_ffintersect: y^2 + 1. Total time spent: 6110 pari-2.17.2/src/test/32/lfuntype0000644000175000017500000011427114676526175015000 0ustar billbill *** Warning: new stack size = 32000000 (30.518 Mbytes). 1 (lfun(2+2*I)): 0.867351829635993064984331343735080128 - 0.2751272388078576 48618660643099638784*I 1 (lfun): 1.64493406684822643647241516664602519 1 (lfuncreate): 1.64493406684822643647241516664602519 1 (lfunderiv): 1.98928023429890102342085868742151638 1 (lfunlambda): 0.523598775598298873077107230546583814 1 (lfunderivlambda): 1.75054087517561195443134301219438671 1 (lfuncheckfeq): -125 1 (lfuncheckfeq(lfundual)): -125 1 (lfunhardy): -0.962008487244040578808410995533804668 1 (lfunorderzero): 0 1 (lfuntheta): 6.97468471241799127935745572277338608 E-6 1 (lfunan): [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 1 (lfuneuler): 1/(-x + 1) 1 (lfuneuler): 1/(-x + 1) 2 (lfun(2+2*I)): 1.12333141140778335615825044285504358 - 0.20572393424008957 9168986058576242213*I 2 (lfun): 1.12668244130002057515926549006290887 2 (lfuncreate): 1.12668244130002057515926549006290887 2 (lfunderiv): -0.0739665394770796291826438851506381467 2 (lfunlambda): 307.349474824750613782011597114857345 2 (lfunderivlambda): 2028.44361211531684713029044069301716 2 (lfuncheckfeq): -135 2 (lfuncheckfeq(lfundual)): -135 2 (lfunhardy): -32.0187142459059089067720240979799474 2 (lfunorderzero): 0 2 (lfuntheta): 0.644880443922533252020549213995002683 2 (lfunan): [1, 1, -1, 1, -1, -1, -1, 1, 1, -1] 2 (lfuneuler): error("domain error in lfuneuler: L Euler product unknown") 2 (lfuneuler): error("domain error in lfuneuler: L Euler product unknown") 3 (lfun(2+2*I)): 0.867351829635993064984331343735080128 - 0.2751272388078576 48618660643099638784*I 3 (lfun): 1.64493406684822643647241516664602519 3 (lfuncreate): 1.64493406684822643647241516664602519 3 (lfunderiv): 1.98928023429890102342085868742151638 3 (lfunlambda): 0.523598775598298873077107230546583814 3 (lfunderivlambda): 1.75054087517561195443134301219438671 3 (lfuncheckfeq): -125 3 (lfuncheckfeq(lfundual)): -125 3 (lfunhardy): -0.962008487244040578808410995533804668 3 (lfunorderzero): 0 3 (lfuntheta): 6.97468471241799127935745572277338608 E-6 3 (lfunan): [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 3 (lfuneuler): 1/(-x + 1) 3 (lfuneuler): 1/(-x + 1) 4 (lfun(2+2*I)): 0.867351829635993064984331343735080128 - 0.2751272388078576 48618660643099638784*I 4 (lfun): 1.64493406684822643647241516664602519 4 (lfuncreate): 1.64493406684822643647241516664602519 4 (lfunderiv): 1.98928023429890102342085868742151638 4 (lfunlambda): 0.523598775598298873077107230546583814 4 (lfunderivlambda): 1.75054087517561195443134301219438671 4 (lfuncheckfeq): -125 4 (lfuncheckfeq(lfundual)): -125 4 (lfunhardy): -0.962008487244040578808410995533804668 4 (lfunorderzero): 0 4 (lfuntheta): 6.97468471241799127935745572277338608 E-6 4 (lfunan): [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 4 (lfuneuler): 1/(-x + 1) 4 (lfuneuler): 1/(-x + 1) 5 (lfun(2+2*I)): 0.949916475911290720435819638338837398 + 0.0358510582342774 432932879184370842385*I 5 (lfun): 1.11000100602501539293722225605953854 5 (lfuncreate): 1.11000100602501539293722225605953854 5 (lfunderiv): 0.669852609442395829160609748322498753 5 (lfunlambda): 0.411691210167071362400798524486894766 5 (lfunderivlambda): 1.02176971928729966874801188387679870 5 (lfuncheckfeq): -125 5 (lfuncheckfeq(lfundual)): -126 5 (lfunhardy): -3.64660129563929901138519608143743026 5 (lfunorderzero): 0 5 (lfuntheta): 0.0157988317398153985319166069771851730 5 (lfunan): [1, 0, 0, 0, 1, 0, 1, 1, 0, 0] 5 (lfuneuler): 1/(-x^3 + 1) 5 (lfuneuler): 1/(x^3 - x^2 - x + 1) 6 (lfun(2+2*I)): 0.960469113962719412457341069363902769 - 0.1991333185305432 04973932590620634790*I 6 (lfun): 1.44015971587760808014950643651388461 6 (lfuncreate): 1.44015971587760808014950643651388461 6 (lfunderiv): 1.20790493328953415202167654530214252 6 (lfunlambda): 15.1394857852014167637577362197215928 6 (lfunderivlambda): 33.4405872605427381564001956871118088 6 (lfuncheckfeq): -125 6 (lfuncheckfeq(lfundual)): -126 6 (lfunhardy): -4.08829338502546324257338625990485586 6 (lfunorderzero): 0 6 (lfuntheta): 1.13757137255097719624384252004385603 6 (lfunan): [1, 1, 0, 1, 0, 0, 2, 1, 2, 0] 6 (lfuneuler): 1/(x^4 - 2*x^2 + 1) 6 (lfuneuler): 1/(-x^4 + 2*x^3 - 2*x + 1) 7 (lfun(2+2*I)): 0.887051722161133224804094699195349656 - 0.0999067808584280 739437653935028589538*I 7 (lfun): 1.21998708680570001482863205426357289 7 (lfuncreate): 1.21998708680570001482863205426357289 7 (lfunderiv): 0.762796284947312317636159697617761159 7 (lfunlambda): 5.55053411599446277532809280321518335 7 (lfunderivlambda): 16.4247273107012156001650889621709003 7 (lfuncheckfeq): -125 7 (lfuncheckfeq(lfundual)): -126 7 (lfunhardy): -33.3510919076492736298184197284568787 7 (lfunorderzero): 0 7 (lfuntheta): 0.361499663398646699814328423183576477 7 (lfunan): [1, 0, 1, 1, 0, 0, 0, 0, 1, 0] 7 (lfuneuler): 1/(-x + 1) 7 (lfuneuler): 1/(x^6 - 2*x^3 + 1) 8 (lfun(2+2*I)): 1.01014959689340434127328002008544181 + 0.00460950332602321 477016321962871214377*I 8 (lfun): 1.02520012413454187241405609393565270 8 (lfuncreate): 1.02520012413454187241405609393565270 8 (lfunderiv): 0.290243846659575984385442888269496413 8 (lfunlambda): 49.0489852899023616549347454114196815 8 (lfunderivlambda): 122.703161456545443829561585953784387 8 (lfuncheckfeq): -125 8 (lfuncheckfeq(lfundual)): -117 8 (lfunhardy): -416.099831965089837996809818950453792 8 (lfunorderzero): 0 8 (lfuntheta): 3.44087660704865850944777670515339473 8 (lfunan): [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] 8 (lfuneuler): 1/(-x^5 + 1) 8 (lfuneuler): 1/(-x^5 + 1) 9 (lfun(2+2*I)): 0.949916475911290720435819638338837398 + 0.0358510582342774 432932879184370842385*I 9 (lfun): 1.11000100602501539293722225605953854 9 (lfuncreate): 1.11000100602501539293722225605953854 9 (lfunderiv): 0.669852609442395829160609748322498753 9 (lfunlambda): 0.411691210167071362400798524486894766 9 (lfunderivlambda): 1.02176971928729966874801188387679870 9 (lfuncheckfeq): -125 9 (lfuncheckfeq(lfundual)): -126 9 (lfunhardy): -3.64660129563929901138519608143743026 9 (lfunorderzero): 0 9 (lfuntheta): 0.0157988317398153985319166069771851730 9 (lfunan): [1, 0, 0, 0, 1, 0, 1, 1, 0, 0] 9 (lfuneuler): 1/(-x^3 + 1) 9 (lfuneuler): 1/(x^3 - x^2 - x + 1) 10 (lfun(2+2*I)): 0.960469113962719412457341069363902769 - 0.199133318530543 204973932590620634790*I 10 (lfun): 1.44015971587760808014950643651388461 10 (lfuncreate): 1.44015971587760808014950643651388461 10 (lfunderiv): 1.20790493328953415202167654530214252 10 (lfunlambda): 15.1394857852014167637577362197215928 10 (lfunderivlambda): 33.4405872605427381564001956871118088 10 (lfuncheckfeq): -125 10 (lfuncheckfeq(lfundual)): -126 10 (lfunhardy): -4.08829338502546324257338625990485586 10 (lfunorderzero): 0 10 (lfuntheta): 1.13757137255097719624384252004385603 10 (lfunan): [1, 1, 0, 1, 0, 0, 2, 1, 2, 0] 10 (lfuneuler): 1/(x^4 - 2*x^2 + 1) 10 (lfuneuler): 1/(-x^4 + 2*x^3 - 2*x + 1) 11 (lfun(2+2*I)): 1.01014959689340434127328002008544181 + 0.0046095033260232 1477016321962871214377*I 11 (lfun): 1.02520012413454187241405609393565270 11 (lfuncreate): 1.02520012413454187241405609393565270 11 (lfunderiv): 0.290243846659575984385442888269496413 11 (lfunlambda): 49.0489852899023616549347454114196815 11 (lfunderivlambda): 122.703161456545443829561585953784387 11 (lfuncheckfeq): -125 11 (lfuncheckfeq(lfundual)): -117 11 (lfunhardy): -416.099831965089837996809818950453792 11 (lfunorderzero): 0 11 (lfuntheta): 3.44087660704865850944777670515339473 11 (lfunan): [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] 11 (lfuneuler): 1/(-x^5 + 1) 11 (lfuneuler): 1/(-x^5 + 1) 12 (lfun(2+2*I)): 1.12532189635570715506930528561542964 - 0.1981192712402207 95548871937824100842*I 12 (lfun): 1.12646149283743545826589288741282639 12 (lfuncreate): 1.12646149283743545826589288741282639 12 (lfunderiv): -0.106643303255744149171372286269629223 12 (lfunlambda): 6.09558510278361919521104233766987484 12 (lfunderivlambda): 3.74333087979076530805010837414125948 12 (lfuncheckfeq): -145 12 (lfuncheckfeq(lfundual)): -145 12 (lfunhardy): 7.72570574643479921846538924565267674 12 (lfunorderzero): 0 12 (lfuntheta): 1.05639763494267810934038480491026780 12 (lfunan): [1, 1, -1, 1, -1, -1, -1, 1, 1, -1] 12 (lfuneuler): 1/(x + 1) 12 (lfuneuler): 1/(x + 1) 13 (lfun(2+2*I)): 1.03662732820491359322708140897279358 + 0.0859804139482783 139638913686916326391*I 13 (lfun): 0.915965594177219015054603514932384111 13 (lfuncreate): 0.915965594177219015054603514932384111 13 (lfunderiv): -0.0744152124356782349684632354196243782 13 (lfunlambda): 0.583121808061637560276768912936789838 13 (lfunderivlambda): 0.114613612706050741461087882041868999 13 (lfuncheckfeq): -161 13 (lfuncheckfeq(lfundual)): -161 13 (lfunhardy): 1.11887810622860782830935076371956226 13 (lfunorderzero): 0 13 (lfuntheta): 0.0864278365243912084432316052103232828 13 (lfunan): [1, 0, -1, 0, 1, 0, -1, 0, 1, 0] 13 (lfuneuler): 1/(x + 1) 13 (lfuneuler): 1/(x + 1) 14 (lfun(2+2*I)): 1.12333141140778335615825044285504358 - 0.2057239342400895 79168986058576242213*I 14 (lfun): 1.12668244130002057515926549006290887 14 (lfuncreate): 1.12668244130002057515926549006290887 14 (lfunderiv): -0.0739665394770796291826438851506381467 14 (lfunlambda): 307.349474824750613782011597114857345 14 (lfunderivlambda): 2028.44361211531684713029044069301716 14 (lfuncheckfeq): -135 14 (lfuncheckfeq(lfundual)): -135 14 (lfunhardy): -32.0187142459059089067720240979799474 14 (lfunorderzero): 0 14 (lfuntheta): 0.644880443922533252020549213995002683 14 (lfunan): [1, 1, -1, 1, -1, -1, -1, 1, 1, -1] 14 (lfuneuler): 1/(x + 1) 14 (lfuneuler): 1/(x + 1) 15 (lfun(2+2*I)): 1.18993474354304186202727389259331023 + 0.1328493179839900 81581393445507787175*I 15 (lfun): 0.958716122716883155391936429331178526 + 0.1455658767850895904617 04511811986454*I 15 (lfuncreate): 0.958716122716883155391936429331178526 + 0.1455658767850895 90461704511811986454*I 15 (lfunderiv): -0.0591413218047954564398507937923812557 + 0.006118657582823 76156782087453731118700*I 15 (lfunlambda): 0.762922049761440418690870666154443650 + 0.1158376441792639 10717418476709550389*I 15 (lfunderivlambda): 0.199288892380239436881894010302036366 + 0.01413439818 96183761935888318063581707*I 15 (lfuncheckfeq): -149 15 (lfuncheckfeq(lfundual)): -150 15 (lfunhardy): 1.55917777033017611725882089543272526 15 (lfunorderzero): 0 15 (lfuntheta): 0.144901841935081749386909416583014010 + 0.00015402754051112 9979340854596822260595*I 15 (lfunan): [1, I, -I, -1, 0, 1, I, -I, -1, 0] 15 (lfuneuler): 1/(I*x + 1) 15 (lfuneuler): 1/(-I*x + 1) 16 (lfun(2+2*I)): 0.812604478837615264081041441696081495 + 0.514416651333746 378091008370108662656*I 16 (lfun): 0.546048036215013518334126660433444339 16 (lfuncreate): 0.546048036215013518334126660433444339 16 (lfunderiv): -0.0959573119238136060007138805040959715 16 (lfunlambda): 0.304294283451836098972454594957268991 16 (lfunderivlambda): 0.0952662577295564170986337258946811760 16 (lfuncheckfeq): -133 16 (lfuncheckfeq(lfundual)): -133 16 (lfunhardy): 0.976135045322300085894183747108898238 16 (lfunorderzero): 0 16 (lfuntheta): 0.0431719735280827499438273571824780835 16 (lfunan): [1, -2, -1, 2, 1, 2, -2, 0, -2, -2] 16 (lfuneuler): 1/(3*x^2 + x + 1) 16 (lfuneuler): 1/(7*x^2 + 2*x + 1) 17 (lfun(2+2*I)): 1.05441088967025847639700174582678268 - 0.0437965218308543 972243790110054896863*I 17 (lfun): 0.854150990582710704905318842265811791 17 (lfuncreate): 0.854150990582710704905318842265811791 17 (lfunderiv): -0.563680254369571457961650191778685453 17 (lfunlambda): 21.4628101650286568303423166010642305 17 (lfunderivlambda): 84.6860027256230673814304478704976471 17 (lfuncheckfeq): -133 17 (lfuncheckfeq(lfundual)): -133 17 (lfunhardy): 7.74311970300071112878317906422293686 17 (lfunorderzero): 1 17 (lfuntheta): 0.845217473227940738281482088078284970 17 (lfunan): [1, 0, 0, 0, -3, 0, 3, 0, -3, 0] 17 (lfuneuler): 1/(3*x^2 + 1) 17 (lfuneuler): 1/(7*x^2 - 3*x + 1) 18 (lfun(2+2*I)): 0.983123026966600972235271763464832152 - 0.142795067389383 410657238079666789672*I 18 (lfun): 0.827575260744555627007653592699965500 18 (lfuncreate): 0.827575260744555627007653592699965500 18 (lfunderiv): -0.875121181243473933259520819418902910 18 (lfunlambda): 378.670686852444160289127394423531793 18 (lfunderivlambda): 4720.96654358276176337631662799998913 18 (lfuncheckfeq): -146 18 (lfuncheckfeq(lfundual)): -146 18 (lfunhardy): -15.1496471038025101587073549412310555 18 (lfunorderzero): 2 18 (lfuntheta): -7.66887438046223655192193159814085172 18 (lfunan): [1, 0, 0, 0, 1, 0, -5, 0, -3, 0] 18 (lfuneuler): 1/(3*x^2 + 1) 18 (lfuneuler): 1/(7*x^2 + 5*x + 1) 19 (lfun(2+2*I)): 0.986272530104809525931751893853141579 + 0.380194362558928 269127554603798823940*I 19 (lfun): 0.661475187921069742727520633979626890 19 (lfuncreate): 0.661475187921069742727520633979626890 19 (lfunderiv): -0.143841395493176354263568656394993696 19 (lfunlambda): 0.502660867426504462749745133338672589 19 (lfunderivlambda): 0.194423310221159541633508034175323825 19 (lfuncheckfeq): -135 19 (lfuncheckfeq(lfundual)): -135 19 (lfunhardy): 1.40769352445571988754639305252078288 19 (lfunorderzero): 0 19 (lfuntheta): 0.0748042148252653877260316447816012193 19 (lfunan): [1, -1, -1, -1, 1, 1, 0, 3, 1, -1] 19 (lfuneuler): error("domain error in lfuneuler: L Euler product unknown") 19 (lfuneuler): error("domain error in lfuneuler: L Euler product unknown") 20 (lfun(2+2*I)): 0.942554443220049051278304920516580006 + 0.312677821809173 216264955458380123548*I 20 (lfun): 0.715646128860824975496114129546066520 20 (lfuncreate): 0.715646128860824975496114129546066520 20 (lfunderiv): -0.104078945840239040164684535929948910 20 (lfunlambda): 0.217530338535707305284341997050366540 20 (lfunderivlambda): 0.0892378811863639550977544016344157046 20 (lfuncheckfeq): -128 20 (lfuncheckfeq(lfundual)): -128 20 (lfunhardy): 0.918363811092074652593939091596159437 20 (lfunorderzero): 0 20 (lfuntheta): 0.0376306737026613074168498659517336581 20 (lfunan): [1, -1, -1, 1, 0, 1, 0, -1, 1, 0] 20 (lfuneuler): 1/(x + 1) 20 (lfuneuler): -1/(x^2 - 1) 21 (lfun(2+2*I)): 0.983156882878079938487282171360591884 + 0.353194962261196 002564857765328902644*I 21 (lfun): 0.674799694647841558297090873047044024 21 (lfuncreate): 0.674799694647841558297090873047044024 21 (lfunderiv): -0.144459052073310639849294659026575599 21 (lfunlambda): 0.786272293506885181814790577878794421 21 (lfunderivlambda): 0.439600775028143260430643207576823695 21 (lfuncheckfeq): -135 21 (lfuncheckfeq(lfundual)): -135 21 (lfunhardy): 3.79061239478881621189127455732904238 21 (lfunorderzero): 0 21 (lfuntheta): 0.134200875056831888281326006943741896 21 (lfunan): [1, -1, -1, 0, 0, 1, 0, 1, 0, 0] 21 (lfuneuler): 1/(x^2 + x + 1) 21 (lfuneuler): -1/(x^2 - 1) 22 (lfun(2+2*I)): 0.962982168489679880431392035586407118 - 0.234200959048951 882935348716027476470*I 22 (lfun): 1.43188245144643874656760459657418548 22 (lfuncreate): 1.43188245144643874656760459657418548 22 (lfunderiv): 1.14223041230261295333309858024639521 22 (lfunlambda): 1.17597438698744354816129454894324752 22 (lfunderivlambda): 2.40842648438108841366598888487879842 22 (lfuncheckfeq): -125 22 (lfuncheckfeq(lfundual)): -126 22 (lfunhardy): -7.51839897592411690553818137933108261 22 (lfunorderzero): 0 22 (lfuntheta): 0.0829263329333191552592027164591883916 22 (lfunan): [1, 1, 0, 1, 1, 0, 0, 1, 0, 1] 22 (lfuneuler): 1/(-x^4 + 1) 22 (lfuneuler): 1/(-x^4 + 1) 23 (lfun(2+2*I)): 1.05544984319374660163990598385147237 - 0.0278463853956589 702737996317036817484*I 23 (lfun): 0.933168362869390134471259026110368548 23 (lfuncreate): 0.933168362869390134471259026110368548 23 (lfunderiv): -0.201338426294825303502241188844208367 23 (lfunlambda): 22.1507381280721352570462243870431034 23 (lfunderivlambda): 67.8562437546532253473488720592101670 23 (lfuncheckfeq): -132 23 (lfuncheckfeq(lfundual)): -132 23 (lfunhardy): 34.2647536056616554131134077735811003 23 (lfunorderzero): 0 23 (lfuntheta): 1.46158125463504108062419125651124102 23 (lfunan): [1, 0, 0, 0, -1, 0, -1, 0, 0, 0] 23 (lfuneuler): 1/(-x^3 + 1) 23 (lfuneuler): 1/(x^3 + x^2 + x + 1) 24 (lfun(2+2*I)): 0.314725764042099582234904322115508057 - 0.231679648750520 683224464505823069849*I 24 (lfun): -0.500000000000000000000000000000000000 24 (lfuncreate): -0.500000000000000000000000000000000000 24 (lfunderiv): -2.00635645590858485121010002672996044 24 (lfunlambda): -1.00000000000000000000000000000000000*x^-1 + O(x^0) 24 (lfunderivlambda): -2.00000000000000000000000000000000000*x^-3 + O(x^0) 24 (lfuncheckfeq): -127 24 (lfuncheckfeq(lfundual)): -127 *** lfunhardy: Warning: lfuninit: insufficient initialization. 24 (lfunhardy): -0.560030581473544907895266753611346294 *** lfunorderzero: Warning: lfuninit: insufficient initialization. 24 (lfunorderzero): 0 24 (lfuntheta): 1.74367117810449781983936393069334652 E-6 24 (lfunan): [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] 24 (lfuneuler): -1/(9*x - 1) 24 (lfuneuler): -1/(49*x - 1) 25 (lfun(2+2*I)): 4.50220519384937626303186082099696243 - 4.3298635928705556 4202429968242321878*I 25 (lfun): 9.86960440108935861883449099987615114*x^-1 + O(x^0) 25 (lfuncreate): 9.86960440108935861883449099987615114*x^-1 + O(x^0) 25 (lfunderiv): 19.7392088021787172376689819997523023*x^-3 + O(x^0) 25 (lfunlambda): 2*x^-1 + O(x^0) 25 (lfunderivlambda): 4.00000000000000000000000000000000000*x^-3 + O(x^0) 25 (lfuncheckfeq): -132 25 (lfuncheckfeq(lfundual)): -132 25 (lfunhardy): -2.54691134661967700629333850455933015 25 (lfunorderzero): 0 25 (lfuntheta): 0.0300468935207456941605384111157272271 25 (lfunan): [8, 24, 32, 24, 48, 96, 64, 24, 104, 144] 25 (lfuneuler): error("domain error in lfuneuler: L Euler product unknown") 25 (lfuneuler): error("domain error in lfuneuler: L Euler product unknown") 26 (lfun(2+2*I)): 1.05241064477041873318193519537236185 - 0.1608955747037985 03038741351081641405*I 26 (lfun): 2.01462456214967463058325687359239722*x^-1 + O(x^0) 26 (lfuncreate): 2.01462456214967463058325687359239722*x^-1 + O(x^0) 26 (lfunderiv): 4.02924912429934926116651374718479443*x^-3 + O(x^0) 26 (lfunlambda): 4.89897948556635619639456814941178278*x^-1 + O(x^0) 26 (lfunderivlambda): 9.79795897113271239278913629882356557*x^-3 + O(x^0) 26 (lfuncheckfeq): -133 26 (lfuncheckfeq(lfundual)): -134 26 (lfunhardy): -0.364668424109818965684669507657798407 + 1.3830788993347127 3245200290438392433*I 26 (lfunorderzero): 0 26 (lfuntheta): 0.824318881419642678102693112376337799 26 (lfunan): [2, 2, 6, 8, 8, 16, 16, 14, 22, 24] 26 (lfuneuler): error("domain error in lfuneuler: L Euler product unknown") 26 (lfuneuler): error("domain error in lfuneuler: L Euler product unknown") 27 (lfun(2+2*I)): 1.18804693262527074421402024152657566 + 0.0169467905017687 700998086956426426175*I 27 (lfun): 0.931057660663704589501110472460906969 27 (lfuncreate): 0.931057660663704589501110472460906969 27 (lfunderiv): -0.198753013038428814612884126426729362 27 (lfunlambda): 2.21689280911624649967055487226065461 27 (lfunderivlambda): 1.88357514427291640029859388228010041 27 (lfuncheckfeq): -127 27 (lfuncheckfeq(lfundual)): -127 27 (lfunhardy): 7.17395993078952418346611051537992346 27 (lfunorderzero): 0 27 (lfuntheta): 0.337407342909411940137856153550159686 27 (lfunan): [1, 0.618033988749894848204586834365638118, -1.6180339887498948 4820458683436563812, -0.618033988749894848204586834365638118, 0, -1, 0.61803 3988749894848204586834365638118, -1, 1.61803398874989484820458683436563812, 0] 27 (lfuneuler): (x^2 + 1.61803398874989484820458683436563812*x + 1)/(x^4 + ( 3.23606797749978969640917366873127624 + 0.E-38*I)*x^3 + (4.61803398874989484 820458683436563812 + 0.E-38*I)*x^2 + (3.23606797749978969640917366873127624 + 0.E-38*I)*x + 1) 27 (lfuneuler): (x^2 - 0.618033988749894848204586834365638118*x + 1)/(x^4 + (-1.23606797749978969640917366873127624 + 0.E-38*I)*x^3 + (2.381966011250105 15179541316563436188 + 0.E-38*I)*x^2 + (-1.236067977499789696409173668731276 24 + 0.E-38*I)*x + 1) 28 (lfun(2+2*I)): 1.18804693262527074421402024152657566 + 0.0169467905017687 700998086956426426175*I 28 (lfun): 0.931057660663704589501110472460906969 28 (lfuncreate): 0.931057660663704589501110472460906969 28 (lfunderiv): -0.198753013038428814612884126426729362 28 (lfunlambda): 2.21689280911624649967055487226065461 28 (lfunderivlambda): 1.88357514427291640029859388228010041 28 (lfuncheckfeq): -127 28 (lfuncheckfeq(lfundual)): -127 28 (lfunhardy): 7.17395993078952418346611051537992346 28 (lfunorderzero): 0 28 (lfuntheta): 0.337407342909411940137856153550159686 28 (lfunan): [1, 0.618033988749894848204586834365638118, -1.6180339887498948 4820458683436563812, -0.618033988749894848204586834365638118, 0, -1, 0.61803 3988749894848204586834365638118, -1, 1.61803398874989484820458683436563812, 0] 28 (lfuneuler): 1/(x^2 + (-a^3 - a^2)*x + 1) 28 (lfuneuler): 1/(x^2 + (a^3 + a^2 + 1)*x + 1) 29 (lfun(2+2*I)): 1.97095478109473626151409334076430269 + 0.7212505424211209 88811935651764296371*I 29 (lfun): 1.34216766218391027978149727736401520 29 (lfuncreate): 1.34216766218391027978149727736401520 29 (lfunderiv): -0.289467129078272588184009850230335970 29 (lfunlambda): 2.51581529931044805567467206281524710 29 (lfunderivlambda): 2.15023979597284392004555238774529014 29 (lfuncheckfeq): -133 29 (lfuncheckfeq(lfundual)): -134 29 (lfunhardy): 2.88457710220275832832906417483001595 + 3.320248804244026470 40570818421869110*I 29 (lfunorderzero): 0 29 (lfuntheta): 0.434382085569470197082039266150814022 29 (lfunan): [2, -2, -2, 0, -2, 6, -2, 0, 4, 4] 29 (lfuneuler): error("domain error in lfuneuler: L Euler product unknown") 29 (lfuneuler): error("domain error in lfuneuler: L Euler product unknown") 30 (lfun(2+2*I)): 1.05215766525546270424075156084210888 + 0.1480552710648707 84313251753406970236*I 30 (lfun): 0.809751106609671408144793153947935896 30 (lfuncreate): 0.809751106609671408144793153947935896 30 (lfunderiv): -0.230553499342620968412594228080737767 30 (lfunlambda): 2.84508677060152583795233609110032793 30 (lfunderivlambda): 5.72042597506703362142231570977928228 30 (lfuncheckfeq): -138 30 (lfuncheckfeq(lfundual)): -138 30 (lfunhardy): 4.82759945264842489400079344115231836 30 (lfunorderzero): 0 30 (lfuntheta): 0.255529558843879352779494600248601708 30 (lfunan): [1, 0, -2, 0, 0, 0, 6, 0, -3, 0] 30 (lfuneuler): 1/(9*x^4 + 6*x^3 + 7*x^2 + 2*x + 1) 30 (lfuneuler): 1/(49*x^4 - 42*x^3 + 23*x^2 - 6*x + 1) 31 (lfun(2+2*I)): 0.892533520461485310267532602120606649 + 0.369759130949347 052877510442839011849*I 31 (lfun): 0.661750897709297254765646777699396229 31 (lfuncreate): 0.661750897709297254765646777699396229 31 (lfunderiv): -0.100198907838435439279351895772703391 31 (lfunlambda): 0.195570681343254990332946430943753302 31 (lfunderivlambda): 0.0749239012411173053088561775689436985 31 (lfuncheckfeq): -127 31 (lfuncheckfeq(lfundual)): -127 31 (lfunhardy): 0.864451108504179190697182277329149391 31 (lfunorderzero): 0 31 (lfuntheta): 0.0335249955311935737808002279532091786 31 (lfunan): [1.00000000000000000000000000000000000, -1.41421356237309504880 168872420969808, -0.577350269189625764509148780501957456, 1.0000000000000000 0000000000000000000, 0.447213595499957939281834733746255247, 0.8164965809277 26032732428024901963797, -0.755928946018454454429033072468360122, 0, -0.6666 66666666666666666666666666666667, -0.632455532033675866399778708886543707] 31 (lfuneuler): error("domain error in lfuneuler: L Euler product unknown") 31 (lfuneuler): error("domain error in lfuneuler: L Euler product unknown") 32 (lfun(2+2*I)): 0.716831782196234821238761071490633231 - 0.067015070703718 6429975753420765617769*I 32 (lfun): 0.927063680000812502070566529520225006 - 0.4636493814548368227024 67503091703650*I 32 (lfuncreate): 0.927063680000812502070566529520225006 - 0.4636493814548368 22702467503091703650*I 32 (lfunderiv): -0.143256874145152423514415023225143850 - 0.3961647536892626 60173591777551018604*I 32 (lfunlambda): 12.9155385383067700070237257032678171 - 6.45940681705575277 494114466734634465*I 32 (lfunderivlambda): 35.1193413454993176171736719370452213 - 7.613089348635 93293431041048800849801*I 32 (lfuncheckfeq): -135 32 (lfuncheckfeq(lfundual)): -135 32 (lfunhardy): -6.06894730215816312163990422182951797 32 (lfunorderzero): 0 32 (lfuntheta): 0.791380404145982157820251519960134007 - 0.69357279218782834 8143705402400363936*I 32 (lfunan): [1, -2*I, I, -2, 0, 2, -2*I, 0, 2, 0] 32 (lfuneuler): -1/(3*x^2 + I*x - 1) 32 (lfuneuler): -1/(7*x^2 - 2*I*x - 1) 33 (lfun(2+2*I)): 1.54401367148723047739869917809075892 - 0.3066196072551902 92880025893390189371*I 33 (lfun): 1.05759924459095784934751165232316747 33 (lfuncreate): 1.05759924459095784934751165232316747 33 (lfunderiv): -0.408747886435859247722794694061668411 33 (lfunlambda): 2.06360650643378826421061953416975612 33 (lfunderivlambda): 1.51184826781495430006436436989704103 33 (lfuncheckfeq): -126 33 (lfuncheckfeq(lfundual)): -126 33 (lfunhardy): 2.51411164942405476920599343563372085 33 (lfunorderzero): 0 33 (lfuntheta): 0.232890677512561985703253016507150509 33 (lfunan): [1, 2, -2, 0, -4, -4, -3, 0, 10, -8] 33 (lfuneuler): 1/(-27*x^3 - 6*x^2 + 2*x + 1) 33 (lfuneuler): 1/(-343*x^3 - 21*x^2 + 3*x + 1) 34 (lfun(2+2*I)): 0.303405850109043665303356963374313989 - 0.800773835388083 237102945790893273292*I 34 (lfun): 1.14023086836473321650196653022065102 34 (lfuncreate): 1.14023086836473321650196653022065102 34 (lfunderiv): -1.11674975027352774622605153706610075 34 (lfunlambda): 24.4732268476097591351989671678990237 34 (lfunderivlambda): 30.7386834367153126705397075456521323 34 (lfuncheckfeq): -137 34 (lfuncheckfeq(lfundual)): -137 34 (lfunhardy): 2.78976423040565601454207435285880273 34 (lfunorderzero): 0 34 (lfuntheta): 1.77200139530428063034309080843969445 34 (lfunan): [1, 0, 5, 0, -9, 0, 20, 0, -5, 0] 34 (lfuneuler): 1/(729*x^4 - 135*x^3 + 30*x^2 - 5*x + 1) 34 (lfuneuler): 1/(117649*x^4 - 6860*x^3 + 210*x^2 - 20*x + 1) 35 (lfun(2+2*I)): 0.916730350303318103087486334081602257 + 0.080000921063523 1270096399584387902400*I 35 (lfun): 0.799218743638286290089171295296216843 - 0.1018472971194699401517 35406675991017*I 35 (lfuncreate): 0.799218743638286290089171295296216843 - 0.1018472971194699 40151735406675991017*I 35 (lfunderiv): -0.142644286962673512538005313505213032 + 0.0239818528768680 814484997672610144396*I 35 (lfunlambda): 1.78079459126418558682748985336301658 - 0.22693301087957631 7134137455805333488*I 35 (lfunderivlambda): 0.520810035426246155331958340245976692 - 0.02937583896 18095965013489026034308737*I 35 (lfuncheckfeq): -128 35 (lfuncheckfeq(lfundual)): -127 35 (lfunhardy): 3.39451744115290048505005314356062885 35 (lfunorderzero): 0 35 (lfuntheta): 0.331428687131746195426755630905940924 - 0.00131804792398201 159878026645787272537*I 35 (lfunan): [1, -1/2 - 0.866025403784438646763723170752936183*I, -1/2 + 0.8 66025403784438646763723170752936183*I, -1/2 + 0.8660254037844386467637231707 52936183*I, -1/2 - 0.866025403784438646763723170752936183*I, 1, 0, 1, -1/2 - 0.866025403784438646763723170752936183*I, -1/2 + 0.866025403784438646763723 170752936183*I] 35 (lfuneuler): error("domain error in lfuneuler: L Euler product unknown") 35 (lfuneuler): error("domain error in lfuneuler: L Euler product unknown") 36 (lfun(2+2*I)): [1.18804693262527074421402024152657566 + 0.016946790501768 7700998086956426426175*I, 0.858815082305618950606114011932380802 + 0.2713868 68570736704398072891146763810*I] 36 (lfun): [0.931057660663704589501110472460906969, 0.7013814207493952044164 48062960213334] 36 (lfuncreate): [0.931057660663704589501110472460906969, 0.7013814207493952 04416448062960213334] 36 (lfunderiv): [-0.198753013038428814612884126426729362, -0.109593360553515 446882197953836578605] 36 (lfunlambda): [2.21689280911624649967055487226065461, 1.67002269977422131 348428067946990593] 36 (lfunderivlambda): [1.88357514427291640029859388228010041, 1.681303352669 11476544927983377647771] 36 (lfuncheckfeq): -127 36 (lfuncheckfeq(lfundual)): -127 36 (lfunhardy): [7.17395993078952418346611051537992346, 3.623083436410096146 49157084927233504] 36 (lfunorderzero): 0 36 (lfuntheta): [0.337407342909411940137856153550159686, 0.24422397199610032 0515432582659385598] 36 (lfunan): [[1, 1], [0.618033988749894848204586834365638118 + 0.E-38*I, -1 .61803398874989484820458683436563812 + 0.E-38*I], [-1.6180339887498948482045 8683436563812 + 0.E-38*I, 0.618033988749894848204586834365638118 + 0.E-38*I] , [-0.618033988749894848204586834365638118 + 0.E-38*I, 1.6180339887498948482 0458683436563812 + 0.E-38*I], [0, 0], [-1.0000000000000000000000000000000000 0 + 0.E-38*I, -1.00000000000000000000000000000000000 + 0.E-38*I], [0.6180339 88749894848204586834365638118 + 0.E-38*I, -1.6180339887498948482045868343656 3812 + 0.E-38*I], [-1.00000000000000000000000000000000000 + 0.E-38*I, -1.000 00000000000000000000000000000000 + 0.E-38*I], [1.618033988749894848204586834 36563812 + 0.E-38*I, -0.618033988749894848204586834365638118 + 0.E-38*I], [0 , 0]] 36 (lfuneuler): error("domain error in lfuneuler: L Euler product unknown") 36 (lfuneuler): error("domain error in lfuneuler: L Euler product unknown") 37 (lfun(2+2*I)): [1.34832050269383270105539305256058035 + 0.207876261877455 649951134053600745676*I, 0.933816175747323073621884899011650668 - 0.27699630 6235557539430032763400061965*I] 37 (lfun): [0.809970291234109778603393108722237662 + 0.274868381256949337697 808122344748406*I, 1.22609858506160642391001983506463949 - 0.097943275553695 0139409741113095949733*I] 37 (lfuncreate): [0.809970291234109778603393108722237662 + 0.274868381256949 337697808122344748406*I, 1.22609858506160642391001983506463949 - 0.097943275 5536950139409741113095949733*I] 37 (lfunderiv): [-0.151725351265238354012778234115126335 + 0.121278626383396 639830241868278505889*I, 0.0860039446936686061214916577333550524 - 0.0329727 397312519111641605043367341386*I] 37 (lfunlambda): [1.41801853168239696679659210810911885 + 0.4812132773438227 86213432506969817576*I, 2.14653615583586699350404921918811073 - 0.1714697209 16803689341181529635105309*I] 37 (lfunderivlambda): [1.04409022907556005671891067171186296 + 0.09023102195 18981718710179327549961148*I, 1.19880071012498724644182489498516045 - 0.0368 918047255747193704447063223973550*I] 37 (lfuncheckfeq): -125 37 (lfuncheckfeq(lfundual)): -126 37 (lfunhardy): [3.15670832622568771988604638363873313, 1.747310103751590027 90095927917174677] 37 (lfunorderzero): 0 37 (lfuntheta): [0.376968591177380458225059441997225895 + 0.0238441032386768 986906444291026655063*I, 0.405052050048118311474278559671515764 - 0.01457362 59061798298691418574839721961*I] 37 (lfunan): [[1, 1], [-0.309016994374947424102293417182819059 + 0.951056516 295153572116439333379382143*I, 0.809016994374947424102293417182819059 - 0.58 7785252292473129168705954639072769*I], [-0.809016994374947424102293417182819 059 + 0.587785252292473129168705954639072769*I, 0.30901699437494742410229341 7182819059 + 0.951056516295153572116439333379382143*I], [-0.8090169943749474 24102293417182819059 - 0.587785252292473129168705954639072769*I, 0.309016994 374947424102293417182819059 - 0.951056516295153572116439333379382143*I], [0. 309016994374947424102293417182819059 + 0.95105651629515357211643933337938214 3*I, -0.809016994374947424102293417182819059 - 0.587785252292473129168705954 639072769*I], [-0.309016994374947424102293417182819059 - 0.95105651629515357 2116439333379382143*I, 0.809016994374947424102293417182819059 + 0.5877852522 92473129168705954639072769*I], [0.809016994374947424102293417182819059 + 0.5 87785252292473129168705954639072769*I, -0.3090169943749474241022934171828190 59 + 0.951056516295153572116439333379382143*I], [0.8090169943749474241022934 17182819059 - 0.587785252292473129168705954639072769*I, -0.30901699437494742 4102293417182819059 - 0.951056516295153572116439333379382143*I], [0.30901699 4374947424102293417182819059 - 0.951056516295153572116439333379382143*I, -0. 809016994374947424102293417182819059 + 0.58778525229247312916870595463907276 9*I], [-1.00000000000000000000000000000000000 + 0.E-38*I, -1.000000000000000 00000000000000000000 + 0.E-38*I]] 37 (lfuneuler): 1/([0.809016994374947424102293417182819059 - 0.5877852522924 73129168705954639072769*I, -0.309016994374947424102293417182819059 - 0.95105 6516295153572116439333379382143*I]*x + 1) 37 (lfuneuler): 1/([-0.809016994374947424102293417182819059 - 0.587785252292 473129168705954639072769*I, 0.309016994374947424102293417182819059 - 0.95105 6516295153572116439333379382143*I]*x + 1) 38 (lfun(2+2*I)): 0.725489894813037832162274170792454244 - 0.230820567349391 064333654403353070547*I 38 (lfun): 0.785398163397448309615660845819875721*x^-1 + O(x^0) 38 (lfuncreate): 0.785398163397448309615660845819875721*x^-1 + O(x^0) 38 (lfunderiv): 1.57079632679489661923132169163975144*x^-3 + O(x^0) 38 (lfunlambda): 1.00000000000000000000000000000000000*x^-1 + O(x^0) 38 (lfunderivlambda): 2.00000000000000000000000000000000000*x^-3 + O(x^0) 38 (lfuncheckfeq): -126 38 (lfuncheckfeq(lfundual)): -126 38 (lfunhardy): -0.970151315570594793182470517189156371 38 (lfunorderzero): 0 38 (lfuntheta): 0.00374186017254235308169191833938384906 38 (lfunan): [1, 2, 0, 4, 10, 0, 0, 8, 9, 20] 38 (lfuneuler): -1/(9*x^2 - 1) 38 (lfuneuler): -1/(49*x^2 - 1) 39 (lfun(2+2*I)): 0.969884912304406412386573423640615706 - 0.164391551765859 140234467892395315007*I 39 (lfun): 1.27256455841637073641435038298551047 39 (lfuncreate): 1.27256455841637073641435038298551047 39 (lfunderiv): 0.447141087190784579702256562219019062 39 (lfunlambda): 0.136759133221372121585038561415947144 39 (lfunderivlambda): 0.170136363411355997746638367056411693 39 (lfuncheckfeq): -125 39 (lfuncheckfeq(lfundual)): -125 39 (lfunhardy): -1.24231704732035088396643971851259267 39 (lfunorderzero): 0 39 (lfuntheta): 0.00374186017254235308169191833938384906 39 (lfunan): [1, 0.707106781186547524400844362104849039, 0, 0.50000000000000 0000000000000000000000, 0.894427190999915878563669467492510494, 0, 0, 0.3535 53390593273762200422181052424520, 0.333333333333333333333333333333333333, 0. 632455532033675866399778708886543707] 39 (lfuneuler): -1/(0.333333333333333333333333333333333333*x^2 - 1) 39 (lfuneuler): -1/(0.142857142857142857142857142857142857*x^2 - 1) 40 (lfun(2+2*I)): 0.620847243123242295812028241845979768 - 0.365805033975834 317719684857084415038*I 40 (lfun): 1.18336177677891977912152512046892098*x^-1 + O(x^0) 40 (lfuncreate): 1.18336177677891977912152512046892098*x^-1 + O(x^0) 40 (lfunderiv): 2.36672355355783955824305024093784196*x^-3 - 0.4188957893279 36286661350187945149060 + O(x) 40 (lfunlambda): 0.305321864725739671684867838310794704*x^-1 - 0.64177482324 8850026374436209391618772 + O(x) 40 (lfunderivlambda): 0.610643729451479343369735676621589407*x^-3 - 3.074744 34600977474530204293108686963 + O(x) 40 (lfuncheckfeq): -124 40 (lfuncheckfeq(lfundual)): -124 40 (lfunhardy): 0.924063648607020890354673611620642808 40 (lfunorderzero): 0 40 (lfuntheta): 0.000715683516278074649423960686323379227 40 (lfunan): [1, 3, 0, 7, 12, 0, 0, 15, 10, 36] 40 (lfuneuler): 1/(9*x^4 - 10*x^2 + 1) 40 (lfuneuler): 1/(49*x^4 - 50*x^2 + 1) 41 (lfun(2+2*I)): 0.947476363904759011895872697580416691 - 0.937145822198315 234814555289003751548*I 41 (lfun): 1.56524441379265684860349952571396221 41 (lfuncreate): 1.56524441379265684860349952571396221 41 (lfunderiv): -0.0974822416674753490684194328018108908 41 (lfunlambda): 1.98240520868786396417643970464304061 41 (lfunderivlambda): 1.08018240929281875388539242602951370 41 (lfuncheckfeq): -136 41 (lfuncheckfeq(lfundual)): -136 41 (lfunhardy): 0.584670414132644129762485183849883879 41 (lfunorderzero): 0 41 (lfuntheta): 0.181970361533588665307802750449858661 41 (lfunan): [1, 1, 7, -7, 0, 7, 6, -15, 22, 0] 41 (lfuneuler): 1/(27*x^2 - 7*x + 1) 41 (lfuneuler): 1/(343*x^2 - 6*x + 1) 42 (lfun(2+2*I)): 0.688796624095670797678023602799082159 - 0.298757462204177 557256046622289626725*I 42 (lfun): 1.18318926859330917506683903887866332 - 0.38252792464848934659370 2399747808619*I 42 (lfuncreate): 1.18318926859330917506683903887866332 - 0.38252792464848934 6593702399747808619*I 42 (lfunderiv): -0.118329715605221747397085260355516201 - 0.0919652026746179 455278413210043897764*I 42 (lfunlambda): 4.61546228092126059525204769648824689 - 1.49219001091282947 415105294611888620*I 42 (lfunderivlambda): 4.90100616091992349220087455477620192 - 0.720094486207 843870455149704475144848*I 42 (lfuncheckfeq): -127 42 (lfuncheckfeq(lfundual)): -127 42 (lfunhardy): 2.17694800910455842894576460335817262 42 (lfunorderzero): 0 42 (lfuntheta): 0.593734546170982628749761158168210536 - 0.17011441672449623 9840795353091106978*I 42 (lfunan): [1, 1.03957970587853882155090730295295895 - 1.43085871205996099 826797658241904256*I, 0, -0.348596700253486245653200720135778009 - 1.0728703 2548377110294699280762148618*I, 0, 0, -2.51625902488442472836131592547899775 + 0.817582118008756363016428134480589156*I, 1.46663068900338109385778755450 141613 + 0.476537197956836693591651688282474718*I, -2.4270509831248422723068 8025154845718 - 1.76335575687741938750611786391721831*I, 0] 42 (lfuneuler): 1/((2.42705098312484227230688025154845718 + 1.76335575687741 938750611786391721831*I)*x^2 + 1) 42 (lfuneuler): 1/((2.51625902488442472836131592547899775 - 0.81758211800875 6363016428134480589156*I)*x + 1) 43 (lfun(2+2*I)): 0.950842141038857147019313517864687157 - 0.023775765925741 7614418889362270233083*I 43 (lfun): 1.08100935077967627123631266500166221 43 (lfuncreate): 1.08100935077967627123631266500166221 43 (lfunderiv): 0.383532859067516452595974615402567726 43 (lfunlambda): 911.287408029371706721339813363300659 43 (lfunderivlambda): 4588.00070538359061716794387044059306 43 (lfuncheckfeq): -125 43 (lfuncheckfeq(lfundual)): -123 43 (lfunhardy): -321.162572791313788196329570908841935 43 (lfunorderzero): 0 43 (lfuntheta): 43.5317192042439188629460340100838749 43 (lfunan): [1, 0, 0, 1, 0, 0, 0, 0, 0, 0] 43 (lfuneuler): 1/(x^6 - 2*x^3 + 1) 43 (lfuneuler): 1/(x^6 - 2*x^3 + 1) 44 (lfun(2+2*I)): 0.867351829635993064984331343735080128 - 0.275127238807857 648618660643099638784*I 44 (lfun): 1.64493406684822643647241516664602519 44 (lfuncreate): 1.64493406684822643647241516664602519 error("sorry, domain = [] for derivatives in lfuninit is not yet implemented .") 44 (lfunlambda): 0.523598775598298873077107230546583814 error("sorry, domain = [] for derivatives in lfuninit is not yet implemented .") 44 (lfuncheckfeq): -125 44 (lfuncheckfeq(lfundual)): -125 44 (lfunhardy): -0.962008487244040578808410995533804668 44 (lfunorderzero): 0 44 (lfuntheta): 6.97468471241799127935745572277338608 E-6 44 (lfunan): [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 44 (lfuneuler): 1/(-x + 1) 44 (lfuneuler): 1/(-x + 1) 45 (lfun(2+2*I)): 0.922776163650349305999729933896297615 - 0.210629145130885 436777484004430146615*I 45 (lfun): 1.50670300992298503088656504818207140 45 (lfuncreate): 1.50670300992298503088656504818207140 45 (lfunderiv): 1.54673238030356925747170841068625513 45 (lfunlambda): 0.305321864725739671684867838310794704 45 (lfunderivlambda): 1.54673238030356925747170841068625513 45 (lfuncheckfeq): -125 45 (lfuncheckfeq(lfundual)): -125 45 (lfunhardy): -1.07637023438345995368832251445133622 45 (lfunorderzero): 0 45 (lfuntheta): 0.00374186017254235308169191833938384906 45 (lfunan): [1, 1, 0, 1, 2, 0, 0, 1, 1, 2] 45 (lfuneuler): 1/(-x^2 + 1) 45 (lfuneuler): 1/(-x^2 + 1) Total time spent: 9317 pari-2.17.2/src/test/32/bessel0000644000175000017500000014027614567450071014401 0ustar billbill1.8572024140248075150290504794684852507 E-10 1 - 1/46*x^2 + 1/4600*x^4 - 1/745200*x^6 + O(x^7) besselh1 [1, 1]: error("incorrect type in isint (t_POL).") [1, 2]: error("incorrect type in isint (t_POL).") [1, 3]: error("incorrect type in isint (t_POL).") [1, 4]: error("incorrect type in isint (t_POL).") [2, 1]: 1 + (-1/4 - 1/2*I)*x^2 + (1/64 + 3/64*I)*x^4 + (-1/2304 - 11/6912*I) *x^6 + O(x^7) [2, 2]: 0.76519768655796655144971752610266322091 + 0.08825696421567695798292 6766023515162828*I [2, 3]: 0.93846980724081290422840467359971262557 - 0.44451873350670655714839 847506833191038*I [2, 4]: 0.22744989480229475542017649479538153049 - 0.05105545867308961813450 6215898455430057*I [3, 1]: 4*I*x^-2 + (1 + I) + (-1/8 - 5/16*I)*x^2 + O(x^3) [3, 2]: 0.44005058574493351595968220371891491313 - 0.78121282130028871654715 000004796482055*I [3, 3]: 0.24226845767487388638395457614153164080 - 1.47147239267024306918858 46353232974532*I [3, 4]: -0.015640669069980772062382408481746291203 - 0.292666506764257448350 36876789097604882*I [4, 1]: (1 - I) + (-1/6 + 1/2*I)*x^2 + (1/120 - 1/24*I)*x^4 + (-1/5040 + 1/7 20*I)*x^6 + O(x^7) [4, 2]: 0.67139670714180309041636401204046708054 - 0.43109886801837607952052 096729853340009*I [4, 3]: 0.54097378993452809133091313466411641349 - 0.99024588024340488002335 195542348755756*I [4, 4]: 0.14085110084956896263172093887132583804 - 0.20269003235062497321863 218183621826188*I [5, 1]: error("domain error in besseln: 2n mod Z != 0") [5, 2]: 0.26938214945091836540555327716757818205 - 1.03976259800634355895849 86807324939546*I [5, 3]: 0.10940542017270712675781308031594165118 - 2.26083223277617932197371 42212172870084*I [5, 4]: -0.19118520534054547001908105095911444129 - 0.3150944893490879685794 3764282485894340*I [6, 1]: 380507258880*I*x^-20 + 10569646080*I*x^-18 + 165150720*I*x^-16 + O(x ^-15) [6, 2]: 2.6306151236874532069978536877905029441 E-10 - 121618014.27868918928 813042666797114529*I [6, 3]: 2.6131773608228030862436154291215029458 E-13 - 121963623349.56963053 464019824934463602*I [6, 4]: -3689851.3824160519844673516400513272729 - 205195.348659968658569759 91788233215816*I [7, 1]: error("domain error in besseln: 2n mod Z != 0") [7, 2]: 0.58245577631758767297591196874548910891 - 1.44030896971971272914426 26374028590791*I [7, 3]: 0.38021680508212671683351192801028812479 - 0.98141687216350076398947 866786133576037*I [7, 4]: 0.20154312205360321787812231235059586177 - 0.76783553572168519458542 835586375224028*I besselh2 [1, 1]: error("incorrect type in isint (t_POL).") [1, 2]: error("incorrect type in isint (t_POL).") [1, 3]: error("incorrect type in isint (t_POL).") [1, 4]: error("incorrect type in isint (t_POL).") [2, 1]: 1 + (-1/4 + 1/2*I)*x^2 + (1/64 - 3/64*I)*x^4 + (-1/2304 + 11/6912*I) *x^6 + O(x^7) [2, 2]: 0.76519768655796655144971752610266322091 - 0.08825696421567695798292 6766023515162828*I [2, 3]: 0.93846980724081290422840467359971262557 + 0.44451873350670655714839 847506833191038*I [2, 4]: 1.6477670588097637977792999000562559034 - 0.942004436545154646198413 22655202096895*I [3, 1]: -4*I*x^-2 + (1 - I) + (-1/8 + 5/16*I)*x^2 + O(x^3) [3, 2]: 0.44005058574493351595968220371891491313 + 0.78121282130028871654715 000004796482055*I [3, 3]: 0.24226845767487388638395457614153164080 + 1.47147239267024306918858 46353232974532*I [3, 4]: 1.2439613389157879924008217252327509830 + 1.022722564418433025377072 5711483489108*I [4, 1]: (1 + I) + (-1/6 - 1/2*I)*x^2 + (1/120 + 1/24*I)*x^4 + (-1/5040 - 1/7 20*I)*x^6 + O(x^7) [4, 2]: 0.67139670714180309041636401204046708054 + 0.43109886801837607952052 096729853340009*I [4, 3]: 0.54097378993452809133091313466411641349 + 0.99024588024340488002335 195542348755756*I [4, 4]: 1.7949514649306922611370433739385788319 + 0.323099244779188375242885 44204680075863*I [5, 1]: error("domain error in besseln: 2n mod Z != 0") [5, 2]: 0.26938214945091836540555327716757818205 + 1.03976259800634355895849 86807324939546*I [5, 3]: 0.10940542017270712675781308031594165118 + 2.26083223277617932197371 42212172870084*I [5, 4]: 0.79927619103677503777576265264156481050 + 1.08771932295608823645995 14526225738913*I [6, 1]: -380507258880*I*x^-20 - 10569646080*I*x^-18 - 165150720*I*x^-16 + O( x^-15) [6, 2]: 2.6306151236874532069978536877905029441 E-10 + 121618014.27868918928 813042666797114529*I [6, 3]: 2.6131773608228030862436154291215029458 E-13 + 121963623349.56963053 464019824934463602*I [6, 4]: 3689851.3824160527671366489980962693903 + 205195.3486599858655861754 3080013707678*I [7, 1]: error("domain error in besseln: 2n mod Z != 0") [7, 2]: -0.053793008222511491987048146883432543616 + 0.334151434861435901321 42313893855556329*I [7, 3]: -0.56713133425013005304402421178983091608 + 0.3472809452441059847447 3666211692428234*I [7, 4]: 0.56669526894058228371774833075826997077 + 0.56952668509437225367197 037537154780157*I besseli [1, 1]: error("incorrect type in isint (t_POL).") [1, 2]: error("incorrect type in isint (t_POL).") [1, 3]: error("incorrect type in isint (t_POL).") [1, 4]: error("incorrect type in isint (t_POL).") [2, 1]: 1 + 1/4*x^2 + 1/64*x^4 + 1/2304*x^6 + O(x^7) [2, 2]: 1.2660658777520083355982446252147175376 [2, 3]: 1.0634833707413235192631844154453565293 [2, 4]: 0.93760847680602927659973819742581871695 + 0.49652994760912213216645 972122523819950*I [3, 1]: 1 + 1/8*x^2 + 1/192*x^4 + 1/9216*x^6 + O(x^7) [3, 2]: 0.56515910399248502720769602760986330733 [3, 3]: 0.25789430539089631636247965952320963419 [3, 4]: 0.36502802882708778851335190162868643100 + 0.61416033492290361016921 965837550234589*I [4, 1]: 1 + 1/6*x^2 + 1/120*x^4 + 1/5040*x^6 + O(x^7) [4, 2]: 0.93767488824548764671726288439139336783 [4, 3]: 0.58799308679041632548887344016323449809 [4, 4]: 0.72698064596355457190337225790772836581 + 0.64183847533798587174998 976767935220305*I [5, 1]: 1 + 0.10355339059327376220042218105242451964*x^2 + 0.003791260736238 8304125791589473295974330*x^4 + 7.1572974488511092712416929822558597732 E-5* x^6 + O(x^7) [5, 2]: 0.33140333780825958195735832301263837654 [5, 3]: 0.11521946070729671962775067900799783493 [5, 4]: 0.12322584912763267310364477086934931491 + 0.47591631113525426300712 693607959667758*I [6, 1]: 1 + 1/44*x^2 + 1/4224*x^4 + 1/658944*x^6 + O(x^7) [6, 2]: 2.7529480398368736252357102010027635344 E-10 [6, 3]: 2.6430419258812795384721773266572060848 E-13 [6, 4]: -3.9133464867902247105872448856946075458 E-10 + 8.603508207756458902 4593151718189946275 E-9*I [7, 1]: 1 + (1/10 - 1/20*I)*x^2 + (1/320 - 1/320*I)*x^4 + (1/21760 - 1/13056 *I)*x^6 + O(x^7) [7, 2]: 0.25369454079993178519197028239401935067 - 0.70438419774772610421577 993808361942912*I [7, 3]: -0.10655105565636707643885659348968940182 - 0.3307637608360080173839 7259495461028707*I [7, 4]: 0.47875240945839830415507917927631039129 + 0.07128046026390996971374 9689821284593892*I besselj [1, 1]: error("incorrect type in isint (t_POL).") [1, 2]: error("incorrect type in isint (t_POL).") [1, 3]: error("incorrect type in isint (t_POL).") [1, 4]: error("incorrect type in isint (t_POL).") [2, 1]: 1 - 1/4*x^2 + 1/64*x^4 - 1/2304*x^6 + O(x^7) [2, 2]: 0.76519768655796655144971752610266322091 [2, 3]: 0.93846980724081290422840467359971262557 [2, 4]: 0.93760847680602927659973819742581871695 - 0.49652994760912213216645 972122523819950*I [3, 1]: 1 - 1/8*x^2 + 1/192*x^4 - 1/9216*x^6 + O(x^7) [3, 2]: 0.44005058574493351595968220371891491313 [3, 3]: 0.24226845767487388638395457614153164080 [3, 4]: 0.61416033492290361016921965837550234589 + 0.36502802882708778851335 190162868643100*I [4, 1]: 1 - 1/6*x^2 + 1/120*x^4 - 1/5040*x^6 + O(x^7) [4, 2]: 0.67139670714180309041636401204046708054 [4, 3]: 0.54097378993452809133091313466411641349 [4, 4]: 0.96790128289013061188438215640495233496 + 0.06020460621428170101212 6630105291248378*I [5, 1]: 1 - 0.10355339059327376220042218105242451964*x^2 + 0.003791260736238 8304125791589473295974330*x^4 - 7.1572974488511092712416929822558597732 E-5* x^6 + O(x^7) [5, 2]: 0.26938214945091836540555327716757818205 [5, 3]: 0.10940542017270712675781308031594165118 [5, 4]: 0.30404549284811478387834080084122518461 + 0.38631241680350013394025 690489885747395*I [6, 1]: 1 - 1/44*x^2 + 1/4224*x^4 - 1/658944*x^6 + O(x^7) [6, 2]: 2.6306151236874532069978536877905029441 E-10 [6, 3]: 2.6131773608228030862436154291215029458 E-13 [6, 4]: 3.9133464867902247105872448856946075458 E-10 + 8.6035082077564589024 593151718189946275 E-9*I [7, 1]: 1 + (-1/10 + 1/20*I)*x^2 + (1/320 - 1/320*I)*x^4 + (-1/21760 + 1/130 56*I)*x^6 + O(x^7) [7, 2]: 0.26433138404753809049443191093102828265 - 0.55307876742913841391141 974923215175792*I [7, 3]: -0.093457264584001668105256141889771395645 - 0.317067963459697389622 37100287220573902*I [7, 4]: 0.38411919549709275079793532155443291627 - 0.09915442531365647045672 8990246102219357*I besseljh [1, 1]: error("incorrect type in jbesselh (t_POL).") [1, 2]: error("incorrect type in jbesselh (t_POL).") [1, 3]: error("incorrect type in jbesselh (t_POL).") [1, 4]: error("incorrect type in jbesselh (t_POL).") [2, 1]: 1 - 1/6*x^2 + 1/120*x^4 - 1/5040*x^6 + O(x^7) [2, 2]: 0.67139670714180309041636401204046708055 [2, 3]: 0.54097378993452809133091313466411641349 [2, 4]: 0.96790128289013061188438215640495233496 + 0.06020460621428170101212 6630105291248379*I [3, 1]: 1 - 1/10*x^2 + 1/280*x^4 - 1/15120*x^6 + O(x^7) [3, 2]: 0.24029783912342701089584304474193368046 [3, 3]: 0.091701699625651302638474313904745269419 [3, 4]: 0.25115830598729948221749558131361228142 + 0.37320184370263719381653 345438379595363*I [4, 1]: error("incorrect type in jbesselh (t_FRAC).") [4, 2]: error("incorrect type in jbesselh (t_FRAC).") [4, 3]: error("incorrect type in jbesselh (t_FRAC).") [4, 4]: error("incorrect type in jbesselh (t_FRAC).") [5, 1]: error("incorrect type in jbesselh (t_REAL).") [5, 2]: error("incorrect type in jbesselh (t_REAL).") [5, 3]: error("incorrect type in jbesselh (t_REAL).") [5, 4]: error("incorrect type in jbesselh (t_REAL).") [6, 1]: 1 - 1/46*x^2 + 1/4600*x^4 - 1/745200*x^6 + O(x^7) [6, 2]: 5.6781874776346222992991061255420209609 E-11 [6, 3]: 3.9855051571881205185285902998553718521 E-14 [6, 4]: -7.5567733209249243890651301118780275736 E-10 + 2.075203626533608360 9445714978636418532 E-9*I [7, 1]: error("incorrect type in jbesselh (t_COMPLEX).") [7, 2]: error("incorrect type in jbesselh (t_COMPLEX).") [7, 3]: error("incorrect type in jbesselh (t_COMPLEX).") [7, 4]: error("incorrect type in jbesselh (t_COMPLEX).") besselk [1, 1]: error("incorrect type in isint (t_POL).") [1, 2]: error("incorrect type in isint (t_POL).") [1, 3]: error("incorrect type in isint (t_POL).") [1, 4]: error("incorrect type in isint (t_POL).") [2, 1]: 1/2*x^2 + 3/64*x^4 + 11/6912*x^6 + O(x^7) [2, 2]: 0.42102443824070833333562737921260903614 [2, 3]: 0.92441907122766586178192416753021698954 [2, 4]: 0.080197726946517818726968736564279166834 - 0.3572774592853302506059 4569325002398166*I [3, 1]: -4*x^-2 + 1 + 5/16*x^2 + O(x^3) [3, 2]: 0.60190723019723457473754000153561733926 [3, 3]: 1.6564411200033008936964454031740915115 [3, 4]: 0.024568305523740348612477346185201235995 - 0.4597194738011893647760 4300851857199811*I [4, 1]: 1/2*x^-1 - 1 + 1/4*x - 1/6*x^2 + 1/48*x^3 - 1/120*x^4 + O(x^5) [4, 2]: 0.46106850444789455843957587387569458969 [4, 3]: 1.0750476034999202387227558602482085118 [4, 4]: 0.068685783419996419480057426969766668173 - 0.3815782598126830739602 7449697029326916*I [5, 1]: error("domain error in besselk: 2n mod Z != 0") [5, 2]: 0.84808712130706055249297377794312403937 [5, 3]: 2.8356740750874926233948621504947623564 [5, 4]: -0.060833677914566850837201614245364256444 - 0.575727321703454299901 71626792018756559*I [6, 1]: 380507258880*x^-20 - 10569646080*x^-18 + 165150720*x^-16 + O(x^-15) [6, 2]: 180713289.90102945469159786130234001591 [6, 3]: 188937569319.90025964462417816833870273 [6, 4]: -322320.09995047688108832869622332914303 - 5796004.99791820584997486 34606037942199*I [7, 1]: error("domain error in besselk: 2n mod Z != 0") [7, 2]: 0.32545977186584141085464640324923711950 + 0.28942803702599212763456 715924152302743*I [7, 3]: 0.38335176781651847215073123333424046031 + 0.96679218008775594813220 288497987441031*I [7, 4]: 0.31594457269950863123935043154373419884 - 0.40665811731437652111601 397817696670098*I bessely [1, 1]: error("incorrect type in isint (t_POL).") [1, 2]: error("incorrect type in isint (t_POL).") [1, 3]: error("incorrect type in isint (t_POL).") [1, 4]: error("incorrect type in isint (t_POL).") [2, 1]: -1/2*x^2 + 3/64*x^4 - 11/6912*x^6 + O(x^7) [2, 2]: 0.088256964215676957982926766023515162828 [2, 3]: -0.44451873350670655714839847506833191038 [2, 4]: 0.44547448893603251403195350532678276945 + 0.71015858200373452117956 170263043718646*I [3, 1]: 4*x^-2 + 1 - 5/16*x^2 + O(x^3) [3, 2]: -0.78121282130028871654715000004796482055 [3, 3]: -1.4714723926702430691885846353232974532 [3, 4]: -0.65769453559134523686372066951966247983 + 0.6298010039928843822316 0206685724863709*I [4, 1]: -1 + 1/2*x^2 - 1/24*x^4 + 1/720*x^6 + O(x^7) [4, 2]: -0.43109886801837607952052096729853340009 [4, 3]: -0.99024588024340488002335195542348755756 [4, 4]: -0.26289463856490667423075881194150951025 + 0.8270501820405616492526 6121753362649691*I [5, 1]: error("domain error in besseln: 2n mod Z != 0") [5, 2]: -1.0397625980063435589584986807324939546 [5, 3]: -2.2608322327761793219737142212172870084 [5, 4]: -0.70140690615258810251969454772371641734 + 0.4952306981886602538974 2185180033962590*I [6, 1]: 380507258880*x^-20 + 10569646080*x^-18 + 165150720*x^-16 + O(x^-15) [6, 2]: -121618014.27868918928813042666797114529 [6, 3]: -121963623349.56963053464019824934463602 [6, 4]: -205195.34865997726207796767434123461747 + 3689851.38241605237580200 03190737983316*I [7, 1]: error("domain error in besseln: 2n mod Z != 0") [7, 2]: -0.88723020229057431523284288817070732122 - 0.3181243922700495824814 8005781446082626*I [7, 3]: -0.66434890870380337436710766498913002135 - 0.4736740696661283849387 6806990005952044*I [7, 4]: -0.66868111040802872412869936561765002092 + 0.1825760734434895329198 1300920383705450*I [0.38318604387456485808270441031554362198 - 1.130318207984970054415392055219 7266147*I, -0.38318604387456485808270441031554362198 + 0.E-38*I]~ [-0.38318604387456485808270441031554362198 + 0.E-38*I, 0.3831860438745648580 8270441031554362198 + 1.1303182079849700544153920552197266147*I]~ [0.E-39 - 0.44005058574493351595968220371891491313*I, 0.E-39 + 0.44005058574 493351595968220371891491313*I]~ [0.E-38 - 0.56515910399248502720769602760986330733*I, 0.E-38 + 0.56515910399 248502720769602760986330733*I]~ [-0.20755374871029735167013412472066868268 - 0.20755374871029735167013412472 066868268*I, -0.20755374871029735167013412472066868268 + 0.20755374871029735 167013412472066868268*I]~ [-0.69122984369208426288314166384697051872 + 1.22712623014357148924328078170 72674867*I, -0.69122984369208426288314166384697051872 - 1.227126230143571489 2432807817072674867*I]~ [-0.56515910399248502720769602760986330733 - 0.38318604387456485808270441031 554362198*I, -0.56515910399248502720769602760986330733 + 0.38318604387456485 808270441031554362198*I]~ [0.44005058574493351595968220371891491313 - 0.781212821300288716547150000047 96482055*I] [0.44005058574493351595968220371891491313 + 0.781212821300288716547150000047 96482055*I] [0.56515910399248502720769602760986330733] [0.44005058574493351595968220371891491313] [0.24029783912342701089584304474193368046] [0.60190723019723457473754000153561733926] [-0.78121282130028871654715000004796482055] [0.44005058574493351595968220371891491313 - 0.781212821300288716547150000047 96482055*I]~ [0.44005058574493351595968220371891491313 + 0.781212821300288716547150000047 96482055*I]~ [0.56515910399248502720769602760986330733]~ [0.44005058574493351595968220371891491313]~ [0.24029783912342701089584304474193368046]~ [0.60190723019723457473754000153561733926]~ [-0.78121282130028871654715000004796482055]~ Mat(0.44005058574493351595968220371891491313 - 0.781212821300288716547150000 04796482055*I) Mat(0.44005058574493351595968220371891491313 + 0.781212821300288716547150000 04796482055*I) Mat(0.56515910399248502720769602760986330733) Mat(0.44005058574493351595968220371891491313) Mat(0.24029783912342701089584304474193368046) Mat(0.60190723019723457473754000153561733926) Mat(-0.78121282130028871654715000004796482055) 0.E-96 5.3192304053524357058659474657917582463 E-127 2.0125228237125015700004500237283661172 E-436 2.4844429420058669729947094283340842193 E432 0.0047283119070895239175760719012169162853 -0.024784331292351778914862356097141290939 5.7412378153505365740198971395908944617 E-10 2.0105123109834969409015328783614871604 E-436 2.4869298723974136282615178613414138395 E432 - 1.480925522592041523487272157 6116922802 E-435*I 0.062200112662645642652489586979995864550 + 0.010824212034833557456516928216 930133817*I 0.011801978377952229766126560304361525414 - 0.057046978607313057957606029839 944987986*I 4.2209797174340754183277966157107172716 E-190 + 4.22097971743407541832779661 57107172716 E-190*I 0.00014306263028209073497114130362445206539 1 + O(x^6) besseli [1, 1]: 2.4856607193657748986356437429659575630 E432 [1, 2]: -1.5451771027266804046337333180007460260 E305 + 2.246025142812183460 1850899267207034244 E304*I [1, 3]: 0.024582448675255660268518437392545230710 + 0.0056107834946578905662 974762959191371167*I [1, 4]: -1.2947050862408574628776609143474939397 E305 - 8.727870919498735222 9925765464760526646 E304*I [1, 5]: 2.2395029243164949434902599086059981178 E432 + 1.0784877670960617239 614658517761283142 E432*I [1, 6]: -1.2947050862408574628776609143474939397 E305 + 8.727870919498735222 9925765464760526646 E304*I [1, 7]: 0.024582448675255660268518437392545230710 - 0.0056107834946578905662 974762959191371167*I [1, 8]: -1.5451771027266804046337333180007460260 E305 - 2.246025142812183460 1850899267207034244 E304*I [2, 1]: 2.4856860959462824296130707595251599223 E432 - 2.5376839670138339901 132218740578601306 E427*I [2, 2]: -1.5451738523412843454830448784088054204 E305 + 2.246248190589809023 7829137005484137046 E304*I [2, 3]: 0.021501763301150156327475615367929667537 + 0.0035426091073249918969 002783908212047629*I [2, 4]: -1.0178175119446992833079884708384124254 E305 - 5.064268877880692318 8993276529455393768 E304*I [2, 5]: 1.7194071211868787556248215691954830514 E432 + 5.6471914839155637822 272668103479253403 E431*I [2, 6]: -1.9200218804194672861734868969326635461 E305 + 9.553636844531660944 4029542862409466974 E304*I [2, 7]: 0.029575950688457475982661629993444814778 - 0.0045927674915960729734 327106958753552123*I [2, 8]: -1.5451994076890234680155950849264485369 E305 - 2.246057645291566006 9402760891030641530 E304*I [3, 1]: 2.4857114730451169403938101984901370326 E432 [3, 2]: -1.5451961572565038171562045210393816157 E305 + 2.246280696289581295 6764062082302594929 E304*I [3, 3]: 0.020305223639384459006881913368674604310 + 0.0008526053592032359631 7948548707113870921*I [3, 4]: -9.8644462725999457820690271383124140716 E304 - 1.434013095209158790 7001723728453862122 E304*I [3, 5]: 1.5868643705776739593937691130852820735 E432 + 0.E394*I [3, 6]: -2.4204411463340704061650601634118549930 E305 + 3.518640787438033481 0514230562188506052 E304*I [3, 7]: 0.031806705285588439167191746206798806615 + 0.0013355463533280581299 403294909248456245*I [3, 8]: -1.5451961572565038171562045210393816157 E305 - 2.246280696289581295 6764062082302594929 E304*I [4, 1]: 2.4856860959462824296130707595251599223 E432 + 2.5376839670138339901 132218740578601306 E427*I [4, 2]: -1.5451994076890234680155950849264485369 E305 + 2.246057645291566006 9402760891030641530 E304*I [4, 3]: 0.020430405924494580709555754980572307032 - 0.0020887333188997190596 524379086198216316*I [4, 4]: -1.1198630030328726662601462851403493875 E305 + 1.956788380893516353 1088394090457863156 E304*I [4, 5]: 1.7194071211868787556248215691954830514 E432 - 5.6471914839155637822 272668103479253405 E431*I [4, 6]: -2.1125924466166727524523196980007640144 E305 - 3.691744589447522399 8544605888912080586 E304*I [4, 7]: 0.027554816955294054755719250755283447701 + 0.0060307507904979972193 232623329608125960*I [4, 8]: -1.5451738523412843454830448784088054204 E305 - 2.246248190589809023 7829137005484137046 E304*I [5, 1]: 2.4856607193657748986356437429659575630 E432 [5, 2]: -1.5451771027266804046337333180007460260 E305 + 2.246025142812183460 1850899267207034244 E304*I [5, 3]: 0.022536178799273833991618203086610957105 - 0.0051437357486238973105 888898632399491103*I [5, 4]: -1.4896078436639369886355376919199975879 E305 + 4.680673459099010877 3926013309709589056 E304*I [5, 5]: 2.2395029243164949434902599086059981178 E432 - 1.0784877670960617239 614658517761283142 E432*I [5, 6]: -1.4896078436639369886355376919199975879 E305 - 4.680673459099010877 3926013309709589056 E304*I [5, 7]: 0.022536178799273833991618203086610957105 + 0.0051437357486238973105 888898632399491103*I [5, 8]: -1.5451771027266804046337333180007460260 E305 - 2.246025142812183460 1850899267207034244 E304*I [6, 1]: 2.4856860959462824296130707595251599223 E432 - 2.5376839670138339901 132218740578601306 E427*I [6, 2]: -1.5451738523412843454830448784088054204 E305 + 2.246248190589809023 7829137005484137046 E304*I [6, 3]: 0.027554816955294054755719250755283447701 - 0.0060307507904979972193 232623329608125960*I [6, 4]: -2.1125924466166727524523196980007640144 E305 + 3.691744589447522399 8544605888912080586 E304*I [6, 5]: 3.2435564274462906545771386266293310224 E432 - 1.0653815251841017294 730836955871683493 E432*I [6, 6]: -1.1198630030328726662601462851403493875 E305 - 1.956788380893516353 1088394090457863156 E304*I [6, 7]: 0.020430405924494580709555754980572307032 + 0.0020887333188997190596 524379086198216316*I [6, 8]: -1.5451994076890234680155950849264485369 E305 - 2.246057645291566006 9402760891030641530 E304*I [7, 1]: 2.4857114730451169403938101984901370326 E432 [7, 2]: -1.5451961572565038171562045210393816157 E305 + 2.246280696289581295 6764062082302594929 E304*I [7, 3]: 0.031806705285588439167191746206798806615 - 0.0013355463533280581299 403294909248456245*I [7, 4]: -2.4204411463340704061650601634118549930 E305 - 3.518640787438033481 0514230562188506052 E304*I [7, 5]: 3.8936922662009485370523116945463611354 E432 + 0.E394*I [7, 6]: -9.8644462725999457820690271383124140716 E304 + 1.434013095209158790 7001723728453862122 E304*I [7, 7]: 0.020305223639384459006881913368674604310 - 0.0008526053592032359631 7948548707113870921*I [7, 8]: -1.5451961572565038171562045210393816157 E305 - 2.246280696289581295 6764062082302594929 E304*I [8, 1]: 2.4856860959462824296130707595251599223 E432 + 2.5376839670138339901 132218740578601306 E427*I [8, 2]: -1.5451994076890234680155950849264485369 E305 + 2.246057645291566006 9402760891030641530 E304*I [8, 3]: 0.029575950688457475982661629993444814778 + 0.0045927674915960729734 327106958753552123*I [8, 4]: -1.9200218804194672861734868969326635461 E305 - 9.553636844531660944 4029542862409466973 E304*I [8, 5]: 3.2435564274462906545771386266293310224 E432 + 1.0653815251841017294 730836955871683492 E432*I [8, 6]: -1.0178175119446992833079884708384124254 E305 + 5.064268877880692318 8993276529455393768 E304*I [8, 7]: 0.021501763301150156327475615367929667537 - 0.0035426091073249918969 002783908212047629*I [8, 8]: -1.5451738523412843454830448784088054204 E305 - 2.246248190589809023 7829137005484137046 E304*I besselj [1, 1]: 0.025214632146741783819153296786562033748 [1, 2]: -1.4564575254656885575010834665330380987 E305 - 5.628055123456293103 3870467402521565740 E304*I [1, 3]: 2.4233400155236446840072289597196650746 E432 + 5.5311154477179654881 698990922102316462 E431*I [1, 4]: -1.5564150479592748582598604858392529091 E305 - 1.248629917076764659 5496259563471327037 E304*I [1, 5]: 0.022717598579825889019328936142237520271 + 0.0109402188763021065946 42783954996273368*I [1, 6]: -1.5564150479592748582598604858392529091 E305 + 1.248629917076764659 5496259563471327037 E304*I [1, 7]: 2.4233400155236446840072289597196650746 E432 - 5.5311154477179654881 698990922102316462 E431*I [1, 8]: -1.4564575254656885575010834665330380987 E305 + 5.628055123456293103 3870467402521565740 E304*I [2, 1]: 0.025538586062759239140984947244497877972 + 0.0001179280785241255071 2196828612985327568*I [2, 2]: -1.2716329178698389636754301746165561798 E305 - 3.975747219422487331 3063069161081647375 E304*I [2, 3]: 2.0943306323234396200826279712245949093 E432 + 3.3511205931115322212 970081403457420446 E431*I [2, 4]: -1.3321790464128243295334640694409037738 E305 - 1.906980889014033643 3254125079940310807 E303*I [2, 5]: 0.017638784420884734076517181658297753859 + 0.0058838252307657534815 778686539900055742*I [2, 6]: -1.8297493639741487427648549912586242846 E305 + 2.621881323573538762 4637484040141912364 E303*I [2, 7]: 2.8765150490569231122839775701446273218 E432 - 4.6032895883994025287 790431319728028743 E431*I [2, 8]: -1.7465312275019257027460597254297410998 E305 + 5.460788568035683097 1895612133642925115 E304*I [3, 1]: 0.025413426845977796926133168003053463998 + 0.0010670960492438536322 800385595391088391*I [3, 2]: -1.2346053812406893419062575089408394464 E305 - 1.794769047536425184 6238663723318913419 E304*I [3, 3]: 1.9860732544675793664155077533034548596 E432 [3, 4]: -1.2346053812406893419062575089408394464 E305 + 1.794769047536425184 6238663723318913419 E304*I [3, 5]: 0.016223790264266262604461803812538684308 + 0.0006812281790914578279 4951409055222478878*I [3, 6]: -1.9339225315872744707335480219651117224 E305 - 2.811379532898257844 7054693467460186972 E304*I [3, 7]: 3.1110441235383884191586669177117255770 E432 [3, 8]: -1.9339225315872744707335480219651117224 E305 + 2.811379532898257844 7054693467460186972 E304*I [4, 1]: 0.024029546329346004071715027182510986437 + 0.0013661519345551034224 342744609728964778*I [4, 2]: -1.3321790464128243295334640694409037738 E305 + 1.906980889014033643 3254125079940310818 E303*I [4, 3]: 2.0943306323234396200826279712245949093 E432 - 3.3511205931115322212 970081403457420447 E431*I [4, 4]: -1.2716329178698389636754301746165561798 E305 + 3.975747219422487331 3063069161081647375 E304*I [4, 5]: 0.016932126201225476403239444505512533199 - 0.0045144088292558222943 811763677294454175*I [4, 6]: -1.7465312275019257027460597254297410998 E305 - 5.460788568035683097 1895612133642925116 E304*I [4, 7]: 2.8765150490569231122839775701446273218 E432 + 4.6032895883994025287 790431319728028744 E431*I [4, 8]: -1.8297493639741487427648549912586242846 E305 - 2.621881323573538762 4637484040141912371 E303*I [5, 1]: 0.023115738628140587091285701740786488980 [5, 2]: -1.5564150479592748582598604858392529091 E305 + 1.248629917076764659 5496259563471327037 E304*I [5, 3]: 2.4233400155236446840072289597196650746 E432 - 5.5311154477179654881 698990922102316461 E431*I [5, 4]: -1.4564575254656885575010834665330380987 E305 + 5.628055123456293103 3870467402521565740 E304*I [5, 5]: 0.020826560862524043723459251385973094288 - 0.0100295431084418113313 55497532347920735*I [5, 6]: -1.4564575254656885575010834665330380987 E305 - 5.628055123456293103 3870467402521565740 E304*I [5, 7]: 2.4233400155236446840072289597196650747 E432 + 5.5311154477179654881 698990922102316462 E431*I [5, 8]: -1.5564150479592748582598604858392529091 E305 - 1.248629917076764659 5496259563471327037 E304*I [6, 1]: 0.024029546329346004071715027182510986437 - 0.0013661519345551034224 342744609728964778*I [6, 2]: -1.8297493639741487427648549912586242846 E305 + 2.621881323573538762 4637484040141912371 E303*I [6, 3]: 2.8765150490569231122839775701446273218 E432 - 4.6032895883994025287 790431319728028743 E431*I [6, 4]: -1.7465312275019257027460597254297410998 E305 + 5.460788568035683097 1895612133642925116 E304*I [6, 5]: 0.030770588100747065951417590900504539780 - 0.0120815917966189059270 89354393959665927*I [6, 6]: -1.2716329178698389636754301746165561798 E305 - 3.975747219422487331 3063069161081647375 E304*I [6, 7]: 2.0943306323234396200826279712245949093 E432 + 3.3511205931115322212 970081403457420446 E431*I [6, 8]: -1.3321790464128243295334640694409037738 E305 - 1.906980889014033643 3254125079940310816 E303*I [7, 1]: 0.025413426845977796926133168003053463998 - 0.0010670960492438536322 800385595391088392*I [7, 2]: -1.9339225315872744707335480219651117224 E305 - 2.811379532898257844 7054693467460186973 E304*I [7, 3]: 3.1110441235383884191586669177117255771 E432 [7, 4]: -1.9339225315872744707335480219651117224 E305 + 2.811379532898257844 7054693467460186973 E304*I [7, 5]: 0.039808346479821425859380995132457118601 - 0.0016715309396485877121 202445959301446269*I [7, 6]: -1.2346053812406893419062575089408394464 E305 - 1.794769047536425184 6238663723318913419 E304*I [7, 7]: 1.9860732544675793664155077533034548596 E432 [7, 8]: -1.2346053812406893419062575089408394464 E305 + 1.794769047536425184 6238663723318913419 E304*I [8, 1]: 0.025538586062759239140984947244497877972 - 0.0001179280785241255071 2196828612985327568*I [8, 2]: -1.7465312275019257027460597254297410998 E305 - 5.460788568035683097 1895612133642925115 E304*I [8, 3]: 2.8765150490569231122839775701446273218 E432 + 4.6032895883994025287 790431319728028743 E431*I [8, 4]: -1.8297493639741487427648549912586242846 E305 - 2.621881323573538762 4637484040141912364 E303*I [8, 5]: 0.033375798080276757978155533605920371387 + 0.0107917827858411635339 86947107903010137*I [8, 6]: -1.3321790464128243295334640694409037738 E305 + 1.906980889014033643 3254125079940310809 E303*I [8, 7]: 2.0943306323234396200826279712245949093 E432 - 3.3511205931115322212 970081403457420447 E431*I [8, 8]: -1.2716329178698389636754301746165561798 E305 + 3.975747219422487331 3063069161081647375 E304*I besselk [1, 1]: 2.0115378317827380046209050698226219312 E-436 [1, 2]: -2.5664756567347393482898467109972504447 E-309 + 1.91505389332460151 74545217420096133013 E-309*I [1, 3]: -0.0074081439681527541272249854592273176164 - 0.03893476016904834117 5605104667996440942*I [1, 4]: -7.0560960884367217600533153137641357232 E304 + 4.854317034421300433 6918971752040275449 E305*I [1, 5]: -7.8089334552762391265996822755650558681 E432*I [1, 6]: -7.0560960884367217600533153137641357232 E304 - 4.854317034421300433 6918971752040275449 E305*I [1, 7]: -0.0074081439681527541272249854592273176164 + 0.03893476016904834117 5605104667996440942*I [1, 8]: -2.5664756567347393482898467109972504447 E-309 - 1.91505389332460151 74545217420096133013 E-309*I [2, 1]: 2.0115173161384134911056307306739562310 E-436 + 2.051543515679161136 6448244446738651215 E-441*I [2, 2]: -2.5665032692877456881991945602025641612 E-309 + 1.91501686029383981 03551822369260893789 E-309*I [2, 3]: -0.0074078220276625683692309106410098600748 - 0.03893523289548685118 3761449620656714205*I [2, 4]: -7.0561981979871734226584102487002793189 E304 + 4.854387107527135998 5938415383014827487 E305*I [2, 5]: -7.9723693079032640578011895137158323519 E427 - 7.809013178155134815 8651355443167793936 E432*I [2, 6]: -7.0567968136963097605083204050944131056 E304 - 4.854306823034418838 7136119600817319606 E305*I [2, 7]: -0.0074076712465352088982228877521737255038 + 0.03893443823184726910 7072949265886558506*I [2, 8]: -2.5664386241701029022257444191700620750 E-309 - 1.91502628070339018 34257256265771421299 E-309*I [3, 1]: 2.0114968009124230001497203148070247858 E-436 [3, 2]: -2.5664662363251912152727606115719287940 E-309 + 1.91498924820695840 18201341606979203413 E-309*I [3, 3]: -0.0074073493045131996418622979073898774485 - 0.03893491095017569546 8525252818903862863*I [3, 4]: -7.0568989333639141253039720483878437445 E304 + 4.854376895992211274 0927328375662587311 E305*I [3, 5]: -7.8090929026624027370380602523628742456 E432*I [3, 6]: -7.0568989333639141253039720483878437445 E304 - 4.854376895992211274 0927328375662587311 E305*I [3, 7]: -0.0074073493045131996418622979073898774485 + 0.03893491095017569546 8525252818903862863*I [3, 8]: -2.5664662363251912152727606115719287940 E-309 - 1.91498924820695840 18201341606979203413 E-309*I [4, 1]: 2.0115173161384134911056307306739562310 E-436 - 2.051543515679161136 6448244446738651215 E-441*I [4, 2]: -2.5664386241701029022257444191700620750 E-309 + 1.91502628070339018 34257256265771421299 E-309*I [4, 3]: -0.0074076712465352088982228877521737255038 - 0.03893443823184726910 7072949265886558506*I [4, 4]: -7.0567968136963097605083204050944131056 E304 + 4.854306823034418838 7136119600817319606 E305*I [4, 5]: 7.9723693079032640578011895137158323519 E427 - 7.8090131781551348158 651355443167793936 E432*I [4, 6]: -7.0561981979871734226584102487002793189 E304 - 4.854387107527135998 5938415383014827487 E305*I [4, 7]: -0.0074078220276625683692309106410098600748 + 0.03893523289548685118 3761449620656714205*I [4, 8]: -2.5665032692877456881991945602025641612 E-309 - 1.91501686029383981 03551822369260893789 E-309*I [5, 1]: 2.0115378317827380046209050698226219312 E-436 [5, 2]: -2.5664756567347393482898467109972504447 E-309 + 1.91505389332460151 74545217420096133013 E-309*I [5, 3]: -0.0074081439681527541272249854592273176164 - 0.03893476016904834117 5605104667996440942*I [5, 4]: -7.0560960884367217600533153137641357232 E304 + 4.854317034421300433 6918971752040275449 E305*I [5, 5]: -7.8089334552762391265996822755650558681 E432*I [5, 6]: -7.0560960884367217600533153137641357232 E304 - 4.854317034421300433 6918971752040275449 E305*I [5, 7]: -0.0074081439681527541272249854592273176164 + 0.03893476016904834117 5605104667996440942*I [5, 8]: -2.5664756567347393482898467109972504447 E-309 - 1.91505389332460151 74545217420096133013 E-309*I [6, 1]: 2.0115173161384134911056307306739562310 E-436 + 2.051543515679161136 6448244446738651215 E-441*I [6, 2]: -2.5665032692877456881991945602025641612 E-309 + 1.91501686029383981 03551822369260893789 E-309*I [6, 3]: -0.0074078220276625683692309106410098600748 - 0.03893523289548685118 3761449620656714205*I [6, 4]: -7.0561981979871734226584102487002793189 E304 + 4.854387107527135998 5938415383014827487 E305*I [6, 5]: -7.9723693079032640578011895137158323519 E427 - 7.809013178155134815 8651355443167793936 E432*I [6, 6]: -7.0567968136963097605083204050944131056 E304 - 4.854306823034418838 7136119600817319606 E305*I [6, 7]: -0.0074076712465352088982228877521737255038 + 0.03893443823184726910 7072949265886558506*I [6, 8]: -2.5664386241701029022257444191700620750 E-309 - 1.91502628070339018 34257256265771421299 E-309*I [7, 1]: 2.0114968009124230001497203148070247858 E-436 [7, 2]: -2.5664662363251912152727606115719287940 E-309 + 1.91498924820695840 18201341606979203413 E-309*I [7, 3]: -0.0074073493045131996418622979073898774485 - 0.03893491095017569546 8525252818903862863*I [7, 4]: -7.0568989333639141253039720483878437445 E304 + 4.854376895992211274 0927328375662587311 E305*I [7, 5]: -7.8090929026624027370380602523628742456 E432*I [7, 6]: -7.0568989333639141253039720483878437445 E304 - 4.854376895992211274 0927328375662587311 E305*I [7, 7]: -0.0074073493045131996418622979073898774485 + 0.03893491095017569546 8525252818903862863*I [7, 8]: -2.5664662363251912152727606115719287940 E-309 - 1.91498924820695840 18201341606979203413 E-309*I [8, 1]: 2.0115173161384134911056307306739562310 E-436 - 2.051543515679161136 6448244446738651215 E-441*I [8, 2]: -2.5664386241701029022257444191700620750 E-309 + 1.91502628070339018 34257256265771421299 E-309*I [8, 3]: -0.0074076712465352088982228877521737255038 - 0.03893443823184726910 7072949265886558506*I [8, 4]: -7.0567968136963097605083204050944131056 E304 + 4.854306823034418838 7136119600817319606 E305*I [8, 5]: 7.9723693079032640578011895137158323519 E427 - 7.8090131781551348158 651355443167793936 E432*I [8, 6]: -7.0561981979871734226584102487002793189 E304 - 4.854387107527135998 5938415383014827487 E305*I [8, 7]: -0.0074078220276625683692309106410098600748 + 0.03893523289548685118 3761449620656714205*I [8, 8]: -2.5665032692877456881991945602025641612 E-309 - 1.91501686029383981 03551822369260893789 E-309*I bessely [1, 1]: -0.00091761919707902324460164195942213702321 [1, 2]: 5.6280551234562931033870467402521565740 E304 - 1.4564575254656885575 010834665330380987 E305*I [1, 3]: -5.5311154477179654881698990922102316462 E431 + 2.423340015523644684 0072289597196650746 E432*I [1, 4]: 1.2486299170767646595496259563471327037 E304 - 1.5564150479592748582 598604858392529091 E305*I [1, 5]: -0.00082674632915781439620093115270223745836 + 0.0458333372079664761 10614637883024009251*I [1, 6]: 1.2486299170767646595496259563471327037 E304 + 1.5564150479592748582 598604858392529091 E305*I [1, 7]: -5.5311154477179654881698990922102316462 E431 - 2.423340015523644684 0072289597196650746 E432*I [1, 8]: 5.6280551234562931033870467402521565740 E304 + 1.4564575254656885575 010834665330380987 E305*I [2, 1]: 0.00074948154761669661890207681454386482648 - 0.00401839530823312585 14822086028765269010*I [2, 2]: 3.9757472194224873313063069161081647375 E304 - 1.2716329178698389636 754301746165561798 E305*I [2, 3]: -3.3511205931115322212970081403457420446 E431 + 2.094330632323439620 0826279712245949093 E432*I [2, 4]: 1.9069808890140336433254125079940310807 E303 - 1.3321790464128243295 334640694409037738 E305*I [2, 5]: 0.0041636973619895962918700171218279345090 + 0.045449762939324383785 241640220770127976*I [2, 6]: 2.6218813235735387624637484040141912364 E303 + 1.8297493639741487427 648549912586242846 E305*I [2, 7]: -4.6032895883994025287790431319728028743 E431 - 2.876515049056923112 2839775701446273218 E432*I [2, 8]: 5.4607885680356830971895612133642925115 E304 + 1.7465312275019257027 460597254297410998 E305*I [3, 1]: 0.0048348930324701626682283717477888277596 - 0.005608928098919208205 9255855493123569599*I [3, 2]: 1.7947690475364251846238663723318913419 E304 - 1.2346053812406893419 062575089408394464 E305*I [3, 3]: 1.9860732544675793664155077533034548596 E432*I [3, 4]: -1.7947690475364251846238663723318913419 E304 - 1.234605381240689341 9062575089408394464 E305*I [3, 5]: 0.0052207609026225584725588962167757118100 + 0.047246145209163267736 520557364904505266*I [3, 6]: -2.8113795328982578447054693467460186972 E304 + 1.933922531587274470 7335480219651117224 E305*I [3, 7]: -3.1110441235383884191586669177117255770 E432*I [3, 8]: 2.8113795328982578447054693467460186972 E304 + 1.9339225315872744707 335480219651117224 E305*I [4, 1]: 0.0086813706582002463510136113148450436056 - 0.003781432189093645637 0094313799613876807*I [4, 2]: -1.9069808890140336433254125079940310818 E303 - 1.332179046412824329 5334640694409037738 E305*I [4, 3]: 3.3511205931115322212970081403457420447 E431 + 2.0943306323234396200 826279712245949093 E432*I [4, 4]: -3.9757472194224873313063069161081647375 E304 - 1.271632917869838963 6754301746165561798 E305*I [4, 5]: 0.0053818184553966444204052214684031635194 + 0.046489107572217841395 706600352886938072*I [4, 6]: -5.4607885680356830971895612133642925116 E304 + 1.746531227501925702 7460597254297410998 E305*I [4, 7]: 4.6032895883994025287790431319728028744 E431 - 2.8765150490569231122 839775701446273218 E432*I [4, 8]: -2.6218813235735387624637484040141912371 E303 + 1.829749363974148742 7648549912586242846 E305*I [5, 1]: 0.010113472547144292198441852802294035910 [5, 2]: -1.2486299170767646595496259563471327037 E304 - 1.556415047959274858 2598604858392529091 E305*I [5, 3]: 5.5311154477179654881698990922102316461 E431 + 2.4233400155236446840 072289597196650746 E432*I [5, 4]: -5.6280551234562931033870467402521565740 E304 - 1.456457525465688557 5010834665330380987 E305*I [5, 5]: 0.0091119239113627880867538555729257837119 + 0.046041193009265827542 612548172535128035*I [5, 6]: -5.6280551234562931033870467402521565740 E304 + 1.456457525465688557 5010834665330380987 E305*I [5, 7]: 5.5311154477179654881698990922102316462 E431 - 2.4233400155236446840 072289597196650747 E432*I [5, 8]: -1.2486299170767646595496259563471327037 E304 + 1.556415047959274858 2598604858392529091 E305*I [6, 1]: 0.0086813706582002463510136113148450436055 + 0.003781432189093645637 0094313799613876807*I [6, 2]: -2.6218813235735387624637484040141912371 E303 - 1.829749363974148742 7648549912586242846 E305*I [6, 3]: 4.6032895883994025287790431319728028743 E431 + 2.8765150490569231122 839775701446273218 E432*I [6, 4]: -5.4607885680356830971895612133642925116 E304 - 1.746531227501925702 7460597254297410998 E305*I [6, 5]: 0.012713145265711477038869462922373677478 + 0.0522907788552731792409 20329542125890851*I [6, 6]: -3.9757472194224873313063069161081647375 E304 + 1.271632917869838963 6754301746165561798 E305*I [6, 7]: 3.3511205931115322212970081403457420446 E431 - 2.0943306323234396200 826279712245949093 E432*I [6, 8]: -1.9069808890140336433254125079940310816 E303 + 1.332179046412824329 5334640694409037738 E305*I [7, 1]: 0.0048348930324701626682283717477888277597 + 0.005608928098919208205 9255855493123569597*I [7, 2]: 2.8113795328982578447054693467460186973 E304 - 1.9339225315872744707 335480219651117224 E305*I [7, 3]: 3.1110441235383884191586669177117255771 E432*I [7, 4]: -2.8113795328982578447054693467460186973 E304 - 1.933922531587274470 7335480219651117224 E305*I [7, 5]: 0.0054393279228748967480685777841798635475 + 0.059612845226880014579 588577586198225639*I [7, 6]: -1.7947690475364251846238663723318913419 E304 + 1.234605381240689341 9062575089408394464 E305*I [7, 7]: -1.9860732544675793664155077533034548596 E432*I [7, 8]: 1.7947690475364251846238663723318913419 E304 + 1.2346053812406893419 062575089408394464 E305*I [8, 1]: 0.00074948154761669661890207681454386482645 + 0.00401839530823312585 14822086028765269007*I [8, 2]: 5.4607885680356830971895612133642925115 E304 - 1.7465312275019257027 460597254297410998 E305*I [8, 3]: -4.6032895883994025287790431319728028743 E431 + 2.876515049056923112 2839775701446273218 E432*I [8, 4]: 2.6218813235735387624637484040141912364 E303 - 1.8297493639741487427 648549912586242846 E305*I [8, 5]: -0.0034765640621960206054076102540308630094 + 0.05362391222052911641 2861129408469970143*I [8, 6]: 1.9069808890140336433254125079940310809 E303 + 1.3321790464128243295 334640694409037738 E305*I [8, 7]: -3.3511205931115322212970081403457420447 E431 - 2.094330632323439620 0826279712245949093 E432*I [8, 8]: 3.9757472194224873313063069161081647375 E304 + 1.2716329178698389636 754301746165561798 E305*I 11.628856980944362293418444710423341176 2.4048255576957727686216318793264546431 30.634606468431975117549578926854232737 0.89357696627916752158488710205833824123 29.064030252728398055304718405181344394 1:3.8317059702075123156144358863081607666 2:5.1356223018406825563014016901377654570 3:6.3801618959239835062366146419427033053 4:7.5883424345038043850696300079856174174 5:8.7714838159599540191228671334095605630 6:9.9361095242176848946930891269651919315 7:11.086370019245083845762764435929999140 8:12.225092264004655175612804769107398951 9:13.354300477435331066419924883491922176 10:14.475500686554541238451637655413151976 11:15.589847884455484680876296733454892608 12:16.698249933848246473203530230023595666 13:17.801435153282442168759357635981491426 14:18.899997953174023642932004510201750562 15:19.994430629816384585761082823694914663 16:21.085146113064718937846237094033074998 17:22.172494618826326205595850739307328423 18:23.256776085110037252890681563869726827 19:24.338249623407174552892989123587853236 20:25.417140814072523580431614414564773477 1:2.1971413260310170351490335626989662731 2:3.3842417671495934727014260185379031127 3:4.5270246611496438503700268671036276387 4:5.6451478942208959141201921858734355731 5:6.7471838248710218565418920142734110622 6:7.8377378223268715659282659676064674521 7:8.9196057348737890383148443845810630168 8:9.9946283820824833853741704657999102848 9:11.064090256031012847033608015849138909 10:12.128927704415439386692455063522342405 11:13.189846995683844934383594098881726898 12:14.247395665073945189762487210965589543 13:15.302007858589249651888091701336044788 14:16.354034360047550649389844581348616303 15:17.403763165970662719188114201635509529 16:18.451433996482453689836379610766242272 17:19.497248785532551224782982830653688879 18:20.541379428638668923555592458448947646 19:21.583973613353356322685017972736158141 20:22.625159280072318034841395413055408526 1:[3.8317059702075123156144358863081607666, 7.015586669815618753537049981476 5247433, 10.173468135062722077185711776775844070, 13.32369193631422303239368 4126947876751, 16.470630050877632812552460470989551449] 2:[5.1356223018406825563014016901377654570, 8.417244140399864857783613676153 8846738, 11.619841172149059427094144986755334885, 14.79595178235126074666147 1320227965273, 17.959819494987826455115142077253733178] 3:[6.3801618959239835062366146419427033053, 9.761023129981669678545388500085 8482595, 13.015200721698434419832684382879382029, 16.22346616031876812222802 4524950161878, 19.409415226435011553575420295720643484] 4:[7.5883424345038043850696300079856174174, 11.06470948850118488271832229019 2246095, 14.372536671617589678573987104868953111, 17.61596604980483304151375 3574456105258, 20.826932956962387683037453002094499552] 5:[8.7714838159599540191228671334095605630, 12.33860419746694398608209764445 9004413, 15.700174079711671037587715595026422501, 18.98013387517992112077073 6748466932307, 22.217799896561267868824764947529187163] 6:[9.9361095242176848946930891269651919315, 13.58929017054121705253131849791 2174403, 17.003819667816014455303006720982586058, 20.32078921356650555309615 1431540086031, 23.586084435581390299548064081080728247] 7:[11.086370019245083845762764435929999140, 14.82126872701317125136539232719 0796661, 18.287582832481726446143071367864397561, 21.64154101984840077512881 5411562238678, 24.934927887673022268865641506072750221] 8:[12.225092264004655175612804769107398951, 16.03777419088770883194699165090 9823459, 19.554536430997055146252395834070673354, 22.94517313187462024042735 9836988563515, 26.266814641176643710483143027226718567] 9:[13.354300477435331066419924883491922176, 17.24122038248912845187422532821 7983251, 20.807047789264107167347823551097252147, 24.23388525775055206077837 3987422558521, 27.583748963573006317690836291521563620] 10:[14.475500686554541238451637655413151976, 18.4334636669665826420350966187 87993887, 22.046985364697801872045600165534209415, 25.5094505541828260882193 99783998860407, 28.887375063530457027056438478305693470] 1:[2.1971413260310170351490335626989662731, 5.429681040794135132772005190852 5841966, 8.5960058683311689264296061801639678511, 11.74915483083988124339942 1939922350714, 14.897442128336725378844819156429870880] 2:[3.3842417671495934727014260185379031127, 6.793807513268267538291167109836 9487124, 10.023477979360037978505391792081418281, 13.20998671020641638278086 3125329852185, 16.378966558947456561726714466123708445] 3:[4.5270246611496438503700268671036276387, 8.097553762860490704402213990112 8042290, 11.396466739595866739252048190629504946, 14.62307774239387317407672 2507725200649, 17.818455232945520262553239064736739443] 4:[5.6451478942208959141201921858734355731, 9.361620615244542866446668156590 3713835, 12.730144474090464540793450066048393123, 15.99962708538247928675796 6874316766752, 19.224428959316809735706305451159766204] 5:[6.7471838248710218565418920142734110622, 10.59717672678203149974766880853 7618852, 14.033804104911232516963508310199092390, 17.34708639322838195634788 9513027220862, 20.602899017175334795707652436381785603] 6:[7.8377378223268715659282659676064674521, 11.81103710760944728309999564519 3908585, 15.313615118517857393317834348451618608, 18.67070496590672382354761 8743885113827, 21.958290897126570997898730191892452831] 7:[8.9196057348737890383148443845810630168, 13.00771143538831345592949526728 7491325, 16.573915129085334479843284147522675643, 19.97434231235242618607853 9684567280826, 23.293972585596647621260694623193296041] 8:[9.9946283820824833853741704657999102848, 14.19036129580014110634349816191 5916556, 17.817887841179872852307547591235047697, 21.26093227125944966704728 0934420040025, 24.612576377421522401032770643459052373] 9:[11.064090256031012847033608015849138909, 15.36130134357592519638434728127 2531143, 19.047949646361388498134304161945969065, 22.53276541631386865777161 8066992162550, 25.916204963326620210880809869934217343] 10:[12.128927704415439386692455063522342405, 16.5222843947844263035971282446 02541739, 20.265984501212253844371680398022326422, 23.7916697194542722223252 63582039439934, 27.206568881574773834609443530029753392] 7.3122392097548233110029969918958058997 E-44 1.6724995288520292841114715831119972199 E-31 12109828087520543559410637777.994596959 -2.2989094375886282011570325214217497288 E40 error("domain error in Qp_log: argument = 0") error("domain error in Qp_log: argument = 0") error("incorrect type in isint (t_PADIC).") error("incorrect type in isint (t_PADIC).") error("forbidden multiplication t_REAL * t_STR.") error("forbidden multiplication t_REAL * t_STR.") error("incorrect type in gexpo (t_STR).") error("incorrect type in isint (t_STR).") error("sorry, p-adic besseli is not yet implemented.") error("sorry, p-adic besselj is not yet implemented.") error("sorry, p-adic besselk is not yet implemented.") error("sorry, p-adic besseln is not yet implemented.") error("incorrect type in besseli (t_STR).") error("incorrect type in besselj (t_STR).") error("incorrect type in besselk (t_STR).") error("incorrect type in besseln (t_STR).") *** at top-level: besseljzero(0,-1) *** ^----------------- *** besseljzero: domain error in besselzero: n <= 0 *** at top-level: besselyzero(0,-1) *** ^----------------- *** besselyzero: domain error in besselzero: n <= 0 Total time spent: 109 pari-2.17.2/src/test/32/ploth0000644000175000017500000003022414676526175014253 0ustar billbill echo = 1 ? \p19 realprecision = 19 significant digits ? default(parisize,"16M"); *** Warning: new stack size = 16000000 (15.259 Mbytes). ? t=plothsizes(); ? plotinit(0,t[1]-11,t[2]-11) ? plotscale(0,0,1000,0,1000); ? plotbox(0,500,500) ? plotdraw(0) ? write("pari0.svg",plotexport("svg",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=-1,1,floor(x)) 0 --------------------------------"""""""""""""""""""""""""""""""" | : | | : | | : | | : | | : | | : | | : | | : | | : | | : | | : | | : | | : | | : | | : | | : | | : | | : | | : | | : | -1 ________________________________...............................| -1 1 ? plot(x=-1,1,-floor(x)) 1 """"""""""""""""""""""""""""""""'''''''''''''''''''''''''''''''| | : | | : | | : | | : | | : | | : | | : | | : | | : | | : | | : | | : | | : | | : | | : | | : | | : | | : | | : | | : | 0 ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,________________________________ -1 1 ? plot(x=0,1,-0.29) 0.71 |''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''| | | | | | | | | | | | | | | | | | | | | | | | | | | | | ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, | | | | | | | | | | -0.29 ________________________________________________________________ 0 1 ? plot(x=-5,5,sin(x)) 0.9995545 x""x_''''''''''''''''''''''''''''''''''_x""x'''''''''''''''''''| | 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)],"Parametric",100) [-0.9998741276738750683, 0.9998741276738750683, -0.9998741276738750683, 0.99 98741276738750683] ? ploth(t=0,2*Pi,[sin(5*t),sin(7*t)],"Parametric|Recursive",100) [-1.000000000000000000, 1.000000000000000000, -1.000000000000000000, 1.00000 0000000000000] ? plothraw(vector(501,k,k-1),vector(501,k,(k-1)*(k-1)/500)); ? 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)) ? write("pari1.svg",plothexport("svg",x=-5,5,sin(x))); ? write("pari2.svg",plothrawexport("svg",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]) ? write("pari3.svg",plotexport("svg",[0,10,10])) ? ploth(x=0,1,x^3,"Splines") [0.E-307, 1.000000000000000000, 0.E-307, 1.000000000000000000] ? ploth(x=0,1,[x^2,x^3],"Parametric|Splines") [0.E-307, 0.9999999999999998890, 0.E-307, 0.9999999999999998890] ? plotinit(1); ? plotcopy(0,1,300,0); ? plotclip(1); ? plotdraw([1,10,10]); ? plotkill(1); ? plotinit(1); ? plotcopy(0,1,1/2,0,1); ? plotclip(1); ? plotdraw([1,10,10]); ? plotkill(1); ? plotinit(1); ? plotcopy(0,1,1/2,1/3,3); ? plotclip(1); ? plotdraw([1,10,10]); ? plotkill(1); ? plotinit(1); ? plotcopy(0,1,1/3,1/3,5); ? plotclip(1); ? plotdraw([1,10,10]); ? plotkill(1); ? plotinit(1); ? plotcopy(0,1,1/3,1/3,7); ? plotclip(1); ? plotdraw([1,10,10]); ? s=plothsizes(); ? plotinit(1,s[1]-1,s[2]-1);plotscale(1,-3,3,-3,3); ? plotrecthraw(1,[[-3.0+6/100*j,-3.0+6/100*j]|j<-[0..100]]); ? plotdraw(1); ? plotinit(1,s[1]-1,s[2]-1);plotscale(1,-3,3,-3,3); ? v=vector(100,j,-3+6/100*j); ? plotrecthraw(1,[v,v,apply(sqr,v),apply(x->x^3,v)]); ? plotdraw(1); ? plotinit(1,s[1]-1,s[2]-1);plotscale(1,-3,3,-3,3); ? plotrecthraw(1,[apply(sqr,v),apply(x->x^3,v),apply(cos,v),apply(sin,v)],1); ? plotdraw(1); ? plotinit(1,s[1]-1,s[2]-1);plotscale(1,-3,3,-3,3); ? plotrecthraw(1,[apply(x->exp(I*x),v),apply(x->x*exp(I*x),v)],4096); ? plotdraw(1); ? plotinit(-1) *** at top-level: plotinit(-1) *** ^------------ *** plotinit: domain error in graphic function: rectwindow < 0 ? plotinit(100) *** at top-level: plotinit(100) *** ^------------- *** plotinit: domain error in plotinit: rectwindow > 15 ? plotmove(-1,0,0) *** at top-level: plotmove(-1,0,0) *** ^---------------- *** plotmove: domain error in graphic function: rectwindow < 0 ? plotmove(100,0,0) *** at top-level: plotmove(100,0,0) *** ^----------------- *** plotmove: domain error in graphic function: rectwindow > 17 ? plotcopy(0,1,2,1,1) *** at top-level: plotcopy(0,1,2,1,1) *** ^------------------- *** plotcopy: domain error in plotcopy: dx > 1 ? plotcopy(0,1,-1,1,1) *** at top-level: plotcopy(0,1,-1,1,1) *** ^-------------------- *** plotcopy: domain error in plotcopy: dx < 0 ? plotcopy(0,1,1,2,1) *** at top-level: plotcopy(0,1,1,2,1) *** ^------------------- *** plotcopy: domain error in plotcopy: dy > 1 ? plotcopy(0,1,1,-1,1) *** at top-level: plotcopy(0,1,1,-1,1) *** ^-------------------- *** plotcopy: domain error in plotcopy: dy < 0 ? ploth(x=0,2*Pi,if(x<1,[cos(x),sin(x)],1),"Parametric") *** at top-level: ploth(x=0,2*Pi,if(x<1,[cos(x),sin(x)],1),"Para *** ^---------------------------- *** inconsistent dimensions in plotrecth. ? ploth(t=0,2*Pi,[sin(5*t),sin(7*t)],"Recursive",100) *** at top-level: ploth(t=0,2*Pi,[sin(5*t),sin(7*t)],"Recursive" *** ^------------------------------- *** incorrect type in ploth [multi-curves + recursive] (t_VEC). ? ploth(x=0,2*Pi,1,"Parametric") *** at top-level: ploth(x=0,2*Pi,1,"Parametric") *** ^--------------- *** incorrect type in ploth [not a t_VEC in parametric plot] (t_INT). ? ploth(x=0,1,x,,1) *** at top-level: ploth(x=0,1,x,,1) *** ^----- *** domain error in ploth: #points < 2 ? default(graphcolormap,["white","black","gray","violetred","red","green","blue","gainsboro","purple"]) ? default(graphcolors,[7,4,9,8,5,6]) ? ploth(X=-1,9,vector(6,k,sin(X+k))) *** at top-level: ploth(X=-1,9,vector(6,k,sin(X+k))) *** ^-------------- *** nonexistent component in graphcolormap: index > 9 ? print("Total time spent: ",gettime); Total time spent: 90 pari-2.17.2/src/test/32/nfsplitting0000644000175000017500000001115614567450071015457 0ustar billbill *** at top-level: nfsplitting(1) *** ^-------------- *** nfsplitting: incorrect type in checknf [please apply nfinit()] (t_INT). x x x y x^120 + 900*x^116 + 508450*x^112 + 3093750*x^110 + 233445700*x^108 + 6244625 000*x^106 + 86356219375*x^104 + 6147962343750*x^102 - 9942720082555*x^100 + 3349338126562500*x^98 - 1654757011326100*x^96 + 1309871930885937500*x^94 + 1 2436255994792015950*x^92 + 627622053389650906250*x^90 + 10990443401191124447 575*x^88 + 376988045414723757750000*x^86 + 5753330797521192519076250*x^84 + 177095246957480012540937500*x^82 + 2532236050928665494862464460*x^80 + 66602 887475268525125564843750*x^78 + 900151039266122540911840715400*x^76 + 176011 62771342375630639534375000*x^74 + 297430062665456220256577151477075*x^72 + 2 930309217240262538594060043562500*x^70 + 72799466070683508609604970583641825 *x^68 + 544024340743931708706461811877750000*x^66 + 815192787279703050465510 9860308253125*x^64 + 109815744628769444357250042241632031250*x^62 + 14587139 1991398970515017378630342573815*x^60 + 8649858988205592244458199943754150781 250*x^58 - 28260531870665143418958164521279483618600*x^56 - 4028396539193675 80525292500109637748437500*x^54 + 106953851435466039913768978932670329879545 0*x^52 - 117799258418763740543911272144086881778781250*x^50 + 21225667468078 1774826232152789145244306484575*x^48 - 1157371878847856250227888707333507692 960375000*x^46 - 60605754850991956455326492294916133973935406250*x^44 - 2931 8354970878696157506850322206226355212812500*x^42 + 2969007992022620344286139 006599749400952695117330*x^40 + 18940874618289173736585545257929220177884468 75000*x^38 - 462258652890221831497176176774279926624850728121600*x^36 - 7387 86176377220399331352006274159764367952001562500*x^34 - 271554668935406462553 6181765731364171583296080250050*x^32 + 9040698598507624900324513465462196895 3701672354656250*x^30 + 6671002781929457078914865848663080213892617538608397 00*x^28 + 8674210771396452568056517384098059387025568935299000000*x^26 + 398 10727829888294052738784121978440350534098819581529375*x^24 + 165091395418543 016833097401882144226762030772580167343750*x^22 + 27455383835034865960434299 3914027364500470431599325551949*x^20 + 5727389048071940962286881233887371037 10592833161132812500*x^18 + 680363944593316626764117242129370969026933149388 6975000*x^16 + 1207367254754819680587174702262138380906821896553743750000*x^ 14 + 1324631954910684324357431850891744535485699735726160156250*x^12 - 24458 13956434295007552447734476548803933624572506738281250*x^10 + 309719742207326 9812049512199025218992726116649855468750000*x^8 + 34385172087788316066248428 61577883803163997230102539062500*x^6 - 3386560639084519090735630415918618954 238015795898437500000*x^4 + 105395630279973820390312384403539563373280780029 2968750000*x^2 + 1865600384408017914532215685346909435223786258697509765625 x^4 + 2*x^2 + 4 x^2 + 1 x^32 - 10356*x^24 + 127847862*x^16 - 11069073684*x^8 + 565036352721 x^32 - 10356*x^24 + 127847862*x^16 - 11069073684*x^8 + 565036352721 [x^32 - 10356*x^24 + 127847862*x^16 - 11069073684*x^8 + 565036352721, 37/121 5568892160*x^25 - 3473/11255267520*x^17 + 170732291/45021070080*x^9 + 156413 8031/3215790720*x] x^32 - 10356*x^24 + 127847862*x^16 - 11069073684*x^8 + 565036352721 [x^32 - 10356*x^24 + 127847862*x^16 - 11069073684*x^8 + 565036352721, 37/121 5568892160*x^25 - 3473/11255267520*x^17 + 170732291/45021070080*x^9 + 156413 8031/3215790720*x] [x^54 + 1791882*x^36 + 1482897537*x^18 + 14348907, -2876/574975052397*x^46 + 17/42590744622*x^37 - 1146359/127900134*x^28 + 3391/4737042*x^19 - 72355820 /9737253*x^10 + 913175/721278*x] [x^54 + 1791882*x^36 + 1482897537*x^18 + 14348907, -2876/574975052397*x^46 + 17/42590744622*x^37 - 1146359/127900134*x^28 + 3391/4737042*x^19 - 72355820 /9737253*x^10 + 913175/721278*x] x^10 - 30*x^8 + 325*x^6 - 1500*x^4 + 2500*x^2 + 2000 x^22 + x^21 + x^20 + x^19 + x^18 + x^17 + x^16 + x^15 + x^14 + x^13 + x^12 + x^11 + x^10 + x^9 + x^8 + x^7 + x^6 + x^5 + x^4 + x^3 + x^2 + x + 1 x^42 + 48020*x^28 + 96001584*x^14 + 52706752 x^42 + 48020*x^28 + 96001584*x^14 + 52706752 *** nfsplitting: Warning: ignoring incorrect degree bound 43. x^42 + 48020*x^28 + 96001584*x^14 + 52706752 *** at top-level: nfsplitting(x^6-8,,1) *** ^--------------------- *** nfsplitting: not an irreducible polynomial in nfsplitting: x^6 - 8. *** at top-level: nfsplitting(x^5+5/4*x+1,,1) *** ^--------------------------- *** nfsplitting: incorrect type in nfsplitting (t_POL). *** at top-level: galoissplittinginit(x^2) *** ^------------------------ *** galoissplittinginit: not an irreducible polynomial in nfsplitting: x^2. Total time spent: 172 pari-2.17.2/src/test/32/ellissupersingular0000644000175000017500000000020214567450071017040 0ustar billbill[2, 3, 5, 47, 53, 59] [[1], [1], [0, 0], [0, 0], [0, 0], [0, 0]] [[0], [1], [0, 0], [0, 0], [1, 0], [0, 0]] Total time spent: 377 pari-2.17.2/src/test/32/partition0000644000175000017500000001041114567450071015120 0ustar billbill1 8646071025430235692572306890072717030146724518193248646261116875039232350406 4122598473575016156709489555875867462346177817327218448788050480708550298957 4471483457937988438791783450144642834886864800778387328738323763398284354678 2467335026575150468969 1315427338504929671669092893786176891908548434593143202526362264344662102688 7135460507830403502328150530572701695452361942348769947362008712123081217734 3187588697310977671154801113558915889945842493651964099879750098080254447377 4788789260448084624118833910204856780861639068659823549617824714773817253043 9615105518523078574457183315543226124650052897717744601504125318067437912564 426796827005538082281337283642237399241533 *** at top-level: numbpart(10^15+2) *** ^----------------- *** numbpart: overflow in numbpart [n < 10^15]. [Vecsmall([])] [Vecsmall([1])] [Vecsmall([9]), Vecsmall([1, 8]), Vecsmall([2, 7]), Vecsmall([3, 6]), Vecsma ll([4, 5]), Vecsmall([1, 1, 7]), Vecsmall([1, 2, 6]), Vecsmall([1, 3, 5]), V ecsmall([1, 4, 4]), Vecsmall([2, 2, 5]), Vecsmall([2, 3, 4]), Vecsmall([3, 3 , 3]), Vecsmall([1, 1, 1, 6]), Vecsmall([1, 1, 2, 5]), Vecsmall([1, 1, 3, 4] ), Vecsmall([1, 2, 2, 4]), Vecsmall([1, 2, 3, 3]), Vecsmall([2, 2, 2, 3]), V ecsmall([1, 1, 1, 1, 5]), Vecsmall([1, 1, 1, 2, 4]), Vecsmall([1, 1, 1, 3, 3 ]), Vecsmall([1, 1, 2, 2, 3]), Vecsmall([1, 2, 2, 2, 2]), Vecsmall([1, 1, 1, 1, 1, 4]), Vecsmall([1, 1, 1, 1, 2, 3]), Vecsmall([1, 1, 1, 2, 2, 2]), Vecs mall([1, 1, 1, 1, 1, 1, 3]), Vecsmall([1, 1, 1, 1, 1, 2, 2]), Vecsmall([1, 1 , 1, 1, 1, 1, 1, 2]), Vecsmall([1, 1, 1, 1, 1, 1, 1, 1, 1])] [Vecsmall([3, 3, 3]), Vecsmall([1, 2, 3, 3]), Vecsmall([2, 2, 2, 3]), Vecsma ll([1, 1, 1, 3, 3]), Vecsmall([1, 1, 2, 2, 3]), Vecsmall([1, 2, 2, 2, 2]), V ecsmall([1, 1, 1, 1, 2, 3]), Vecsmall([1, 1, 1, 2, 2, 2]), Vecsmall([1, 1, 1 , 1, 1, 1, 3]), Vecsmall([1, 1, 1, 1, 1, 2, 2]), Vecsmall([1, 1, 1, 1, 1, 1, 1, 2]), Vecsmall([1, 1, 1, 1, 1, 1, 1, 1, 1])] [] [] [] [] [Vecsmall([0, 1, 1, 1])] [Vecsmall([0, 1, 1, 2]), Vecsmall([1, 1, 1, 1])] [Vecsmall([0, 1, 1, 3]), Vecsmall([0, 1, 2, 2]), Vecsmall([1, 1, 1, 2])] [1, 4] [2, 3] [1, 1, 3] [1, 2, 2] [0, 0, 1, 4] [0, 0, 2, 3] [0, 1, 1, 3] [0, 1, 2, 2] [1, 1, 1, 2] 451276 [9] [1, 8] [2, 7] [3, 6] [4, 5] [1, 1, 7] [1, 2, 6] [1, 3, 5] [1, 4, 4] [2, 2, 5] [2, 3, 4] [3, 3, 3] [1, 1, 1, 6] [1, 1, 2, 5] [1, 1, 3, 4] [1, 2, 2, 4] [1, 2, 3, 3] [2, 2, 2, 3] [1, 1, 1, 1, 5] [1, 1, 1, 2, 4] [1, 1, 1, 3, 3] [1, 1, 2, 2, 3] [1, 2, 2, 2, 2] [1, 1, 1, 1, 1, 4] [1, 1, 1, 1, 2, 3] [1, 1, 1, 2, 2, 2] [1, 1, 1, 1, 1, 1, 3] [1, 1, 1, 1, 1, 2, 2] [1, 1, 1, 1, 1, 1, 1, 2] [1, 1, 1, 1, 1, 1, 1, 1, 1] [11] [1, 10] [2, 9] [3, 8] [4, 7] [5, 6] [1, 1, 9] [1, 2, 8] [1, 3, 7] [1, 4, 6] [1, 5, 5] [2, 2, 7] [2, 3, 6] [2, 4, 5] [3, 3, 5] [3, 4, 4] [1, 1, 1, 8] [1, 1, 2, 7] [1, 1, 3, 6] [1, 1, 4, 5] [1, 2, 2, 6] [1, 2, 3, 5] [1, 2, 4, 4] [1, 3, 3, 4] [2, 2, 2, 5] [2, 2, 3, 4] [2, 3, 3, 3] [1, 1, 1, 1, 7] [1, 1, 1, 2, 6] [1, 1, 1, 3, 5] [1, 1, 1, 4, 4] [1, 1, 2, 2, 5] [1, 1, 2, 3, 4] [1, 1, 3, 3, 3] [1, 2, 2, 2, 4] [1, 2, 2, 3, 3] [2, 2, 2, 2, 3] [1, 11] [2, 10] [3, 9] [4, 8] [5, 7] [6, 6] [1, 1, 10] [1, 2, 9] [1, 3, 8] [1, 4, 7] [1, 5, 6] [2, 2, 8] [2, 3, 7] [2, 4, 6] [2, 5, 5] [3, 3, 6] [3, 4, 5] [4, 4, 4] [1, 1, 1, 9] [1, 1, 2, 8] [1, 1, 3, 7] [1, 1, 4, 6] [1, 1, 5, 5] [1, 2, 2, 7] [1, 2, 3, 6] [1, 2, 4, 5] [1, 3, 3, 5] [1, 3, 4, 4] [2, 2, 2, 6] [2, 2, 3, 5] [2, 2, 4, 4] [2, 3, 3, 4] [3, 3, 3, 3] [1, 1, 1, 1, 8] [1, 1, 1, 2, 7] [1, 1, 1, 3, 6] [1, 1, 1, 4, 5] [1, 1, 2, 2, 6] [1, 1, 2, 3, 5] [1, 1, 2, 4, 4] [1, 1, 3, 3, 4] [1, 2, 2, 2, 5] [1, 2, 2, 3, 4] [1, 2, 3, 3, 3] [2, 2, 2, 2, 4] [2, 2, 2, 3, 3] [1, 1, 1, 1, 1, 7] [1, 1, 1, 1, 2, 6] [1, 1, 1, 1, 3, 5] [1, 1, 1, 1, 4, 4] [1, 1, 1, 2, 2, 5] [1, 1, 1, 2, 3, 4] [1, 1, 1, 3, 3, 3] [1, 1, 2, 2, 2, 4] [1, 1, 2, 2, 3, 3] [1, 2, 2, 2, 2, 3] [2, 2, 2, 2, 2, 2] [5, 6, 6, 6] [3, 3, 5, 6, 6] [3, 4, 4, 6, 6] [3, 4, 5, 5, 6] [3, 5, 5, 5, 5] [4, 4, 4, 5, 6] [4, 4, 5, 5, 5] [3, 3, 3, 3, 5, 6] [3, 3, 3, 4, 4, 6] [3, 3, 3, 4, 5, 5] [3, 3, 4, 4, 4, 5] [3, 4, 4, 4, 4, 4] [3, 3, 3, 3, 3, 3, 5] [3, 3, 3, 3, 3, 4, 4] [0, 0, 0, 2, 3] [0, 0, 1, 1, 3] [0, 0, 1, 2, 2] [0, 1, 1, 1, 2] [1, 1, 1, 1, 1] [0, 0, 3, 3, 3, 3, 3] [0, 1, 2, 3, 3, 3, 3] [0, 2, 2, 2, 3, 3, 3] [1, 1, 1, 3, 3, 3, 3] [1, 1, 2, 2, 3, 3, 3] [1, 2, 2, 2, 2, 3, 3] [2, 2, 2, 2, 2, 2, 3] Total time spent: 2560 pari-2.17.2/src/test/32/logint0000644000175000017500000000217514676526175014425 0ustar billbill99 100 1267650600228229401496703205376 232 6901746346790563787434755862277025452451108972170386555162524223799296 146 116 100 1 3 1651 1651 6901746346790563787434755862277025452451108972170386555162524223799296 1041 1041 4821988420928667320811351852787360333668329931564502550956051671640915800419 7255158077335478528442643299623256958526367248611783552541551799415660418227 9066476522546267180905672382315821399022183326431300271091122443466877780285 0649355332943555329948297859314325322666069955800439444612134621043655228370 3642508371230446840543229113955718597479885876650700621984044093699147322172 5596570727592516882270037912915565136686923012836525539007932531265536783103 76496165838881373499302269835830744446403 69 69 590295810358705651712 5 5 32 *** at top-level: logint(-Pi,2) *** ^------------- *** logint: domain error in logint: x < 1 *** at top-level: logint(-quadgen(5),2) *** ^--------------------- *** logint: domain error in logint: x < 1 *** at top-level: logint(-1/2,2) *** ^-------------- *** logint: domain error in logint: x < 1 Total time spent: 1 pari-2.17.2/src/test/32/mspolygon0000644000175000017500000001341014567450071015140 0ustar billbill[[[-1, 1; -1, 0], [1, 0; 0, 1], [0, 1; -1, 6], [-1, 1; -6, 5], [-1, 1; -5, 4 ], [1, -2; 4, -7], [-2, 1; -7, 3], [1, -2; 3, -5], [-2, 1; -5, 2], [1, -1; 2 , -1]], Vecsmall([2, 1, 4, 3, 6, 5, 8, 7, 10, 9]), [[-1, -1; 0, -1], [1, -1; 0, 1], [-5, 1; -36, 7], [-7, 1; -36, 5], [11, -3; 48, -13], [13, -3; 48, -1 1], [11, -4; 36, -13], [13, -4; 36, -11], [5, -3; 12, -7], [7, -3; 12, -5]]] [[[-1, 1; -1, 0], [1, 0; 0, 1], [0, 1; -1, 6], [-1, 1; -6, 5], [-1, 1; -5, 4 ], [-1, 1; -4, 3], [-1, 1; -3, 2], [-1, 2; -2, 3], [-2, 3; -3, 4], [-3, 1; - 4, 1]], Vecsmall([2, 1, 4, 3, 10, 9, 8, 7, 6, 5]), [[-1, -1; 0, -1], [1, -1; 0, 1], [-5, 1; -36, 7], [-7, 1; -36, 5], [-5, 4; -24, 19], [-7, 5; -24, 17] , [-5, 3; -12, 7], [-7, 3; -12, 5], [-17, 5; -24, 7], [-19, 4; -24, 5]]] [[[1, 0; 0, 1], [0, 1; -1, 0]], Vecsmall([1, 2]), [[0, 1; -1, 0], [0, -1; 1, -1]]] [-1/5 -1/5] [ 1 0] [ 0 1] [-51/88 -3/8 -3/11 -215/671] [ -25/8 -2 -3/2 -855/488] [ 5/11 3/11 3/11 193/671] [ 0 1/88 0 0] [ 0 0 1/2 41/122] [ 0 0 0 11/488] [-292 -82 -88 -109 -111 -109 -157 -623 -86 -119 2295 -875 74 485 -1901/5 -98 /5 2027 2131 -237 2017 9046/5 -3034/5 -2816/15 4051/3 -186 658 -2283/260 342 1481/3120] [-3900 -2931/2 -4089/4 -1785 -6651/4 -2557/2 -8035/4 -4740 -2090 -1521 4365 -18845/4 -3225/4 -30 -2167 -4641/2 11741/4 6173/2 -3238 19433/4 8943/2 -3847 -9271/4 32635/12 -2242 772 -156811/312 9526607/6240] [-504 -204 -126 -3168/13 -258 -1948/13 -258 -903 -196 -2892/13 -5056 11741/1 3 -59889/52 -89590/39 -27452/65 -305743/195 -25279/5 -664137/130 -5660/13 -3 415219/780 -1434919/390 -111512/195 -24485/39 -371557/130 -588 -200003/104 - 1194589/3120 -3018279/1040] [-4083/2 -4505/4 -1541/4 -5017/4 -1023 -2007/4 -3855/4 -3003/4 -6241/4 -1687 /2 3619/4 -8979/4 1367/4 3037/4 -611/20 -4183/20 2629/4 757/2 -1798 1509 260 71/20 -7509/20 -13613/15 3193/6 -698 1877/4 248969/3120 2092777/4160] [-12944 -14355/2 -9709/4 -63881/8 -52121/8 -25289/8 -24409/4 -4745 -39595/4 -10727/2 36251/8 -111389/8 7911/4 34903/8 -1517/8 -12403/8 24131/8 2455/2 -1 1420 33911/4 14701/2 -9309/4 -46647/8 64609/24 -17925/4 10263/4 288059/624 3 1650659/12480] [-327945 -182835 -61080 -203190 -165840 -79545 -154379 -119775 -250965 -1363 00 82860 -344580 45115 98610 -4677 -45190 45930 30 -289869 185895 161988 -57 509 -149768 50126 -115001 54168 136933/13 1220425/26] [13439/4 16553/10 7167/10 122693/65 32263/20 118949/130 8176/5 4155/2 11697/ 5 352189/260 3205/2 720887/260 47817/130 1474709/3120 533561/1040 237839/156 25075/12 1903519/780 755721/260 846199/3120 92829/520 667197/520 227787/130 328313/390 30483/20 3564659/6240 842271/4160 337171/320] [86863/4 42695/4 37145/8 316623/26 83373/8 154041/26 423029/40 54165/4 60361 /4 1137687/130 90027/8 918731/52 167436/65 360285/104 219236/65 2101885/208 115151/8 1731941/104 488335/26 132391/52 951147/520 8702241/1040 8875903/780 18546419/3120 198493/20 210133/52 2856421/2080 22852571/3120] [560985/2 275115/2 60105 2041230/13 134550 1993065/26 136683 352575/2 389085 /2 1468876/13 156285 2926545/13 928017/26 646605/13 1150683/26 6946451/52 19 6755 2935905/13 3153025/13 553290/13 828551/26 5667307/52 1919296/13 1293577 7/156 129087 1467745/26 2890055/156 629511907/6240] [0 1/5 1/20 43/260 1/10 1/130 1/20 0 1/10 23/130 0 7/65 23/130 7/65 9/52 1/1 30 1/20 17/520 17/130 517/3120 103/1560 19/1560 137/780 59/520 1/10 71/6240 523/12480 191/6240] [0 0 3/8 7/104 0 9/26 11/40 0 1/4 81/260 0 5/52 81/260 5/52 17/104 3/65 1/4 33/208 7/52 1/52 125/624 257/1560 3/104 503/1560 7/20 3/13 913/6240 687/4160 ] [0 0 0 60/13 0 30/13 0 0 0 40/13 0 30/13 40/13 30/13 12/13 30/13 0 30/13 3/1 3 45/13 43/13 95/26 48/13 211/78 0 20/13 223/78 6479/3120] [0 0 0 0 1/4 0 0 0 0 0 0 0 0 11/48 19/80 7/30 7/60 7/120 0 7/60 13/60 13/60 1/15 7/120 0 13/160 1217/12480 599/6240] [0 0 0 0 0 1/8 0 0 0 0 0 0 0 0 1/10 9/80 0 1/16 0 0 11/240 11/240 13/120 1/1 6 0 1/16 11/104 557/12480] [0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1/2 0 0 0 0 0 0 0 0 0 1/2 9/52 791/1040] [0 0 0 0 0 0 0 1 0 0 0 0 3/4 2/3 4/5 11/15 1/15 1/30 0 3/20 1/15 311/390 2/5 18/65 0 31/120 457/1040 667/3120] [0 0 0 0 0 0 0 0 1/2 0 0 0 1/4 0 1/10 3/10 0 0 0 0 3/20 1/65 1/15 29/78 0 1/ 4 35/156 43/195] [0 0 0 0 0 0 0 0 0 1 0 0 1/2 0 0 0 0 0 0 0 0 21/26 0 47/78 0 1/2 127/156 7/3 120] [0 0 0 0 0 0 0 0 0 0 1/4 0 1/16 1/12 1/20 1/15 7/30 29/120 0 17/80 7/30 79/1 560 1/15 47/260 0 1/12 113/1560 365/2496] [0 0 0 0 0 0 0 0 0 0 0 1/8 1/16 0 1/10 1/20 0 0 0 0 7/80 63/520 13/120 23/31 2 0 0 22/195 179/4160] [0 0 0 0 0 0 0 0 0 0 0 0 1/2 0 0 0 0 0 0 0 0 5/26 0 31/78 0 0 19/78 553/1560 ] [0 0 0 0 0 0 0 0 0 0 0 0 0 1/12 1/20 1/15 1/15 1/30 0 1/15 1/15 1/15 0 1/30 0 1/24 83/3120 41/1560] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 1/5 1/10 0 0 0 0 2/15 2/15 2/15 0 0 0 71/780 7/ 520] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1/2 0 0 0 0 0 0 0 0 0 0 2/13 17/1040] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1/15 1/30 0 1/20 1/30 7/390 0 11/390 0 1/24 133/3120 3/104] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1/8 0 0 7/60 37/312 0 61/520 0 0 19/1040 73/6240] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1/2 0 0 25/52 0 77/156 0 0 29/156 61/48 0] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1/240 0 1/260 0 1/780 0 0 1/260 7/249 6] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1/240 1/312 0 1/260 0 0 1/780 7/124 80] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1/52 0 1/156 0 0 1/156 31/3120] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1/60 0 0 0 7/3120 97/12480] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1/24 0 0 23/624 509/12480] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 9/10] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1/480 1/960 1/3120] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1/6240 1/12480] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1/2080] [1 0 0 0] [8 0 0 0] [0 1 0 0] [0 0 5 9/2] [0 0 12 11] [0 0 0 1/2] Total time spent: 114 pari-2.17.2/src/test/32/hypergeom0000644000175000017500000001464314676526175015133 0ustar billbill *** Warning: new stack size = 10000000 (9.537 Mbytes). 1F1 4: -127 4: -255 7: -255 0.030197383422318500739786292363619845072 2.8284271247461900976033774484193961571 1.3315111152667654252176268707430756605 E-39 + 1.414213562373095048801688724 2096980786*I 50.343020954867419706123354314640690679 0.0010271017807084596221820129185302701137 -3.5423522481569286041969331655231169577 - 4.1563154358960628799975992342968 727908*I 2F0 1: -127 4: -127 2F1 20: -120 21: -119 20: -249 21: -248 3F1 1: -127 2: -127 3: -127 4: -127 3F2 1: -127 0.010755543103981336691090575342270364916 0.69314718055994511627005156151293529802 28/5: -125 29/5: -123 6: -125 31/5: -123 32/5: -125 -128 7.9999999999999999999999999999999999999 13.054813248885128935535510479301488203 -128 0.76342068053916758561787756449255894402 1.6752931349345765309211012564734179541 1.9721037126267142061807688820853354439 1 [0.35502805388781723926006318600418317640, 0.6149266274460007351509223690936 1355359] [0.33149330543214118898452933261713434589 - 0.317449858968443773477642927909 25852646*I, 0.64885820833039494458484765317286500293 + 0.3449586347680483702 4710860866729328133*I] [0.13529241631288141552414742351546630618, 1.2074235949528712594363788170282 869954] 2.6344821520881844895505525695264981561 E-291 0.024273887680160131605667472886346835004 3.0903009822753419949181566235987700160 3.0903009822753419949181566235987700160 [-1, 1, 2, 1]~ 0.70809200298127252820036742866403357571 - 0.5808881688552449029956683984899 4493431*I 1 + x + 1/2*x^2 + 1/6*x^3 + 1/24*x^4 + 1/120*x^5 + 1/720*x^6 + 1/5040*x^7 + 1/40320*x^8 + 1/362880*x^9 + 1/3628800*x^10 + 1/39916800*x^11 + 1/479001600* x^12 + 1/6227020800*x^13 + 1/87178291200*x^14 + 1/1307674368000*x^15 + 1/209 22789888000*x^16 + O(x^17) 1 + 2*x + 3*x^2 + 4*x^3 + 5*x^4 + 6*x^5 + 7*x^6 + 8*x^7 + 9*x^8 + 10*x^9 + 1 1*x^10 + 12*x^11 + 13*x^12 + 14*x^13 + 15*x^14 + 16*x^15 + 17*x^16 + O(x^17) 4 + 16*x + 48*x^2 + 128*x^3 + 320*x^4 + 768*x^5 + 1792*x^6 + 4096*x^7 + 9216 *x^8 + 20480*x^9 + 45056*x^10 + 98304*x^11 + 212992*x^12 + 458752*x^13 + 983 040*x^14 + 2097152*x^15 + O(x^16) 4 + 16*x^2 + 48*x^4 + 128*x^6 + 320*x^8 + 768*x^10 + 1792*x^12 + 4096*x^14 + O(x^16) 1 + 2/3*x + 1/2*x^2 + 2/5*x^3 + 1/3*x^4 + 2/7*x^5 + 1/4*x^6 + 2/9*x^7 + 1/5* x^8 + 2/11*x^9 + 1/6*x^10 + 2/13*x^11 + 1/7*x^12 + 2/15*x^13 + 1/8*x^14 + 2/ 17*x^15 + 1/9*x^16 + O(x^17) 1.5451774444795624753378569716654125446 + 1.81929022208175009864857211333834 98216*x + 2.5421293337547497040542836599849505353*x^2 + 3.887655109987334122 5219102400401319060*x^3 + 6.2808622250316646936952243998996702350*x^4 + 10.5 25930659924004735131461440240791436*x^5 + 18.1061617935106556180265899727714 86649*x^6 + 31.757344471975644301653508633665173373*x^7 + 56.545974938054800 321279605574253359911*x^8 + 101.89783347098933261937865427943697798*x^9 + 18 5.42476636382346823736696058523864845*x^10 + 340.164146115294251118472085995 84294883*x^11 + 628.31101675019578924331048034234027753*x^12 + 1167.33011776 88090693221005038780363253*x^13 + 2179.7211762096948514526417774042078743*x^ 14 + 4088.0614907526509835676975415376898682*x^15 + O(x^16) 1.5451774444795624753378569716654125446 + 1.81929022208175009864857211333834 98216*x^2 + 2.5421293337547497040542836599849505353*x^4 + 3.8876551099873341 225219102400401319060*x^6 + 6.2808622250316646936952243998996702350*x^8 + 10 .525930659924004735131461440240791436*x^10 + 18.1061617935106556180265899727 71486649*x^12 + 31.757344471975644301653508633665173373*x^14 + O(x^16) 1.0094620656249420088071330689077712257 - 0.03880548252725574271114157054099 7898358*I 1.3658702151284039238349824096285170462 1.2554469815542412045782999961607539985 - 0.24161088425121476374403057661591 870286*I -127 -127 -127 -127 -127 -124 1.0000000000000000000000000000000000000 1.2037672964679416776055581379045160237 - 2.52116432965353018871661339239871 26896 E-11*I 1 + 2^2 + 2^3 + 2^6 + 2^8 + O(2^10) 1 + 3 + 3^2 + 3^3 + 3^4 + 3^5 + 3^6 + 3^7 + 3^8 + 3^9 + O(3^10) 1 + 3 + 2*3^2 + 3^3 + 3^5 + 2*3^6 + 3^7 + 3^9 + 2*3^10 + O(3^11) 1 + 7^2 + 2*7^4 + 5*7^5 + 7^8 + 4*7^9 + 4*7^11 + 6*7^12 + 6*7^13 + 2*7^14 + 6*7^15 + 7^18 + 4*7^19 + 4*7^20 + 7^21 + 3*7^22 + 5*7^23 + 5*7^25 + 4*7^26 + 3*7^28 + 6*7^29 + O(7^30) 256*x^4 - 11 O(5^159) 1 + 2^3 + 2^7 + 2^9 + 2^10 + 2^12 + 2^13 + 2^15 + 2^18 + 2^20 + 2^21 + 2^23 + 2^26 + 2^27 + 2^28 + 2^35 + 2^36 + 2^37 + 2^38 + 2^40 + 2^41 + 2^44 + 2^45 + 2^46 + 2^48 + 2^49 + 2^51 + 2^52 + 2^53 + 2^55 + 2^56 + 2^58 + 2^60 + 2^6 2 + 2^63 + 2^64 + 2^65 + 2^66 + 2^67 + 2^68 + 2^72 + 2^74 + 2^75 + 2^76 + 2^ 80 + 2^81 + 2^82 + 2^84 + 2^87 + 2^88 + 2^89 + 2^91 + 2^92 + 2^94 + 2^97 + 2 ^98 + 2^100 + O(2^101) 3125*x^6 + 27 O(2^80) O(2^101) 1 - 1/(256*b^2*a)*x + 1/((65536*b^4 + 131072*b^3 + 65536*b^2)*a^2 + (65536*b ^4 + 131072*b^3 + 65536*b^2)*a)*x^2 - 1/((16777216*b^6 + 100663296*b^5 + 218 103808*b^4 + 201326592*b^3 + 67108864*b^2)*a^3 + (50331648*b^6 + 301989888*b ^5 + 654311424*b^4 + 603979776*b^3 + 201326592*b^2)*a^2 + (33554432*b^6 + 20 1326592*b^5 + 436207616*b^4 + 402653184*b^3 + 134217728*b^2)*a)*x^3 + O(x^4) 5.7905592870252580604286032943587762265 *** at top-level: airy(O(x)) *** ^---------- *** airy: incorrect type in airy (t_SER). 1 + O(x) *** at top-level: hypergeom([2,1],0,1) *** ^-------------------- *** hypergeom: domain error in hypergeom: b[1] <= 0 *** at top-level: hypergeom([2,1],[2,-1],1) *** ^------------------------- *** hypergeom: domain error in hypergeom: b[2] <= 0 *** at top-level: hypergeom([2,3],1,1) *** ^-------------------- *** hypergeom: domain error in hypergeom: real(vecsum(D)-vecsum(N)) <= 0 *** at top-level: hypergeom([1/2,1/2,1/2],[1/3,1/3],1-10^-6) *** ^------------------------------------------ *** hypergeom: sorry, 3F2 for these arguments is not yet implemented. *** at top-level: hypergeom([1,2,3,4],[],1/2) *** ^--------------------------- *** hypergeom: sorry, this hypergeometric function is not yet implemented. *** at top-level: hypergeom(,,2+O(2^10)) *** ^---------------------- *** hypergeom: divergent p-adic hypergeometric sum. *** at top-level: hypergeom([1,1/3],1,3+O(3^10)) *** ^------------------------------ *** hypergeom: divergent p-adic hypergeometric sum. *** at top-level: hypergeom([1/2,1/2],5/6,-4+O(2^80)) *** ^----------------------------------- *** hypergeom: divergent p-adic hypergeometric sum. Total time spent: 2935 pari-2.17.2/src/test/32/ispower0000644000175000017500000002705614710142650014603 0ustar billbill[101, 6] [5, 2160] [3, 21218] [5, 21218] [5, 84872] [21, 21218] [35, 21218] [105, 21218] [100003, 103] [121, 541] [2, 2] [3, 2] [2, 3] [4, 2] [2, 5] [3, 3] [5, 2] [2, 6] [2, 7] [6, 2] [4, 3] [2, 10] [2, 11] [3, 5] [7, 2] [2, 12] [2, 13] [2, 14] [3, 6] [2, 15] [5, 3] [8, 2] [2, 17] [2, 18] [3, 7] [2, 19] [2, 20] [2, 21] [2, 22] [9, 2] [2, 23] [2, 24] [4, 5] [2, 26] [6, 3] [2, 28] [2, 29] [2, 30] [2, 31] [3, 10] [10, 2] [2, 33] [2, 34] [2, 35] [4, 6] [3, 11] [2, 37] [2, 38] [2, 39] [2, 40] [2, 41] [3, 12] [2, 42] [2, 43] [2, 44] [2, 45] [11, 2] [2, 46] [7, 3] [3, 13] [2, 47] [2, 48] [4, 7] [2, 50] [2, 51] [2, 52] [3, 14] [2, 53] [2, 54] [2, 55] [5, 5] [2, 56] [2, 57] [2, 58] [3, 15] [2, 59] [2, 60] [2, 61] [2, 62] [2, 63] [12, 2] [2, 65] [2, 66] [2, 67] [2, 68] [2, 69] [2, 70] [3, 17] [2, 71] [2, 72] [2, 73] [2, 74] [2, 75] [2, 76] [3, 18] [2, 77] [2, 78] [2, 79] [2, 80] [8, 3] [2, 82] [3, 19] [2, 83] [2, 84] [2, 85] [2, 86] [2, 87] [2, 88] [5, 6] [2, 89] [3, 20] [2, 90] [13, 2] [2, 91] [2, 92] [2, 93] [2, 94] [2, 95] [2, 96] [3, 21] [2, 97] [2, 98] [2, 99] [4, 10] [2, 101] [2, 102] [2, 103] [3, 22] [2, 104] [2, 105] [2, 106] [2, 107] [2, 108] [2, 109] [2, 110] [3, 23] [2, 111] [2, 112] [2, 113] [2, 114] [2, 115] [2, 116] [2, 117] [3, 24] [2, 118] [2, 119] [2, 120] [4, 11] [2, 122] [2, 123] [2, 124] [6, 5] [2, 126] [2, 127] [14, 2] [2, 129] [5, 7] [2, 130] [2, 131] [2, 132] [3, 26] [2, 133] [2, 134] [2, 135] [2, 136] [2, 137] [2, 138] [2, 139] [2, 140] [9, 3] [2, 141] [2, 142] [2, 143] [4, 12] [2, 145] [2, 146] [2, 147] [2, 148] [3, 28] [2, 149] [2, 150] [2, 151] [2, 152] [2, 153] [2, 154] [2, 155] [2, 156] [3, 29] [2, 157] [2, 158] [2, 159] [2, 160] [2, 161] [2, 162] [2, 163] [2, 164] [3, 30] [2, 165] [2, 166] [2, 167] [2, 168] [4, 13] [2, 170] [2, 171] [2, 172] [3, 31] [2, 173] [2, 174] [2, 175] [2, 176] [2, 177] [2, 178] [2, 179] [2, 180] [2, 181] [15, 2] [2, 182] [2, 183] [2, 184] [2, 185] [2, 186] [2, 187] [2, 188] [2, 189] [3, 33] [2, 190] [2, 191] [2, 192] [2, 193] [2, 194] [2, 195] [4, 14] [2, 197] [2, 198] [3, 34] [2, 199] [2, 200] [2, 201] [2, 202] [2, 203] [2, 204] [2, 205] [2, 206] [2, 207] [3, 35] [2, 208] [2, 209] [2, 210] [2, 211] [2, 212] [2, 213] [2, 214] [2, 215] [6, 6] [2, 217] [2, 218] [2, 219] [2, 220] [2, 221] [2, 222] [2, 223] [2, 224] [4, 15] [3, 37] [2, 226] [2, 227] [2, 228] [2, 229] [2, 230] [2, 231] [2, 232] [2, 233] [2, 234] [3, 38] [2, 235] [2, 236] [2, 237] [2, 238] [2, 239] [2, 240] [2, 241] [2, 242] [10, 3] [3, 39] [2, 244] [2, 245] [2, 246] [2, 247] [2, 248] [2, 249] [2, 250] [2, 251] [2, 252] [3, 40] [2, 253] [2, 254] [2, 255] [16, 2] [2, 257] [2, 258] [2, 259] [2, 260] [2, 261] [2, 262] [3, 41] [2, 263] [2, 264] [2, 265] [2, 266] [2, 267] [2, 268] [2, 269] [2, 270] [2, 271] [2, 272] [3, 42] [2, 273] [2, 274] [2, 275] [2, 276] [2, 277] [2, 278] [2, 279] [7, 5] [2, 280] [2, 281] [3, 43] [2, 282] [2, 283] [2, 284] [2, 285] [2, 286] [2, 287] [2, 288] [4, 17] [2, 290] [2, 291] [3, 44] [2, 292] [2, 293] [2, 294] [2, 295] [2, 296] [2, 297] [2, 298] [2, 299] [2, 300] [2, 301] [3, 45] [2, 302] [2, 303] [2, 304] [2, 305] [2, 306] [2, 307] [2, 308] [2, 309] [2, 310] [2, 311] [3, 46] [2, 312] [2, 313] [2, 314] [2, 315] [2, 316] [5, 10] [2, 317] [2, 318] [2, 319] [2, 320] [2, 321] [2, 322] [3, 47] [2, 323] [4, 18] [2, 325] [2, 326] [2, 327] [2, 328] [2, 329] [2, 330] [2, 331] [2, 332] [3, 48] [2, 333] [2, 334] [2, 335] [2, 336] [2, 337] [2, 338] [2, 339] [2, 340] [2, 341] [2, 342] [6, 7] [2, 344] [2, 345] [2, 346] [2, 347] [2, 348] [2, 349] [2, 350] [2, 351] [2, 352] [2, 353] [3, 50] [2, 354] [2, 355] [2, 356] [2, 357] [2, 358] [2, 359] [2, 360] [4, 19] [2, 362] [17, 2] [2, 363] [2, 364] [3, 51] [2, 365] [2, 366] [2, 367] [2, 368] [2, 369] [2, 370] [2, 371] [2, 372] [2, 373] [2, 374] [3, 52] [2, 375] [2, 376] [2, 377] [2, 378] [2, 379] [2, 380] [2, 381] [2, 382] [2, 383] [2, 384] [2, 385] [3, 53] [2, 386] [2, 387] [2, 388] [2, 389] [2, 390] [2, 391] [2, 392] [2, 393] [2, 394] [2, 395] [2, 396] [3, 54] [2, 397] [2, 398] [2, 399] [4, 20] [2, 401] [5, 11] [2, 402] [2, 403] [2, 404] [2, 405] [2, 406] [2, 407] [3, 55] [2, 408] [2, 409] [2, 410] [2, 411] [2, 412] [2, 413] [2, 414] [2, 415] [2, 416] [2, 417] [2, 418] [2, 419] [3, 56] [2, 420] [11, 3] [2, 421] [2, 422] [2, 423] [2, 424] [2, 425] [2, 426] [2, 427] [2, 428] [2, 429] [2, 430] [3, 57] [2, 431] [2, 432] [2, 433] [2, 434] [2, 435] [2, 436] [2, 437] [2, 438] [2, 439] [2, 440] [4, 21] [3, 58] [2, 442] [2, 443] [2, 444] [2, 445] [2, 446] [2, 447] [2, 448] [2, 449] [2, 450] [2, 451] [2, 452] [2, 453] [3, 59] [2, 454] [2, 455] [2, 456] [2, 457] [2, 458] [2, 459] [2, 460] [2, 461] [2, 462] [2, 463] [2, 464] [3, 60] [2, 465] [2, 466] [2, 467] [2, 468] [2, 469] [2, 470] [2, 471] [2, 472] [2, 473] [2, 474] [2, 475] [2, 476] [3, 61] [2, 477] [2, 478] [2, 479] [2, 480] [2, 481] [2, 482] [2, 483] [4, 22] [2, 485] [2, 486] [2, 487] [2, 488] [3, 62] [2, 489] [2, 490] [2, 491] [2, 492] [2, 493] [2, 494] [2, 495] [2, 496] [2, 497] [2, 498] [5, 12] [2, 499] [2, 500] [3, 63] [2, 501] [2, 502] [2, 503] [2, 504] [2, 505] [2, 506] [2, 507] [2, 508] [2, 509] [2, 510] [2, 511] [18, 2] [2, 513] [2, 514] [2, 515] [2, 516] [2, 517] [2, 518] [2, 519] [2, 520] [2, 521] [2, 522] [2, 523] [2, 524] [3, 65] [2, 525] [2, 526] [2, 527] [2, 528] [4, 23] [7, 6] [2, 530] [2, 531] [2, 532] [2, 533] [2, 534] [2, 535] [2, 536] [3, 66] [2, 537] [2, 538] [2, 539] [2, 540] [2, 541] [2, 542] [2, 543] [2, 544] [2, 545] [2, 546] [2, 547] [2, 548] [3, 67] [2, 549] [2, 550] [2, 551] [2, 552] [2, 553] [2, 554] [2, 555] [2, 556] [2, 557] [2, 558] [2, 559] [2, 560] [3, 68] [2, 561] [2, 562] [2, 563] [2, 564] [2, 565] [2, 566] [2, 567] [2, 568] [2, 569] [2, 570] [2, 571] [2, 572] [2, 573] [3, 69] [2, 574] [2, 575] [4, 24] [2, 577] [2, 578] [2, 579] [2, 580] [2, 581] [2, 582] [2, 583] [2, 584] [2, 585] [3, 70] [2, 586] [2, 587] [2, 588] [2, 589] [2, 590] [2, 591] [2, 592] [2, 593] [2, 594] [2, 595] [2, 596] [2, 597] [2, 598] [3, 71] [2, 599] [2, 600] [2, 601] [2, 602] [2, 603] [2, 604] [2, 605] [2, 606] [2, 607] [2, 608] [2, 609] [5, 13] [2, 610] [3, 72] [2, 611] [2, 612] [2, 613] [2, 614] [2, 615] [2, 616] [2, 617] [2, 618] [2, 619] [2, 620] [2, 621] [2, 622] [2, 623] [3, 73] [2, 624] [8, 5] [2, 626] [2, 627] [2, 628] [2, 629] [2, 630] [2, 631] [2, 632] [2, 633] [2, 634] [2, 635] [2, 636] [3, 74] [2, 637] [2, 638] [2, 639] [2, 640] [2, 641] [2, 642] [2, 643] [2, 644] [2, 645] [2, 646] [2, 647] [2, 648] [2, 649] [3, 75] [2, 650] [2, 651] [2, 652] [2, 653] [2, 654] [2, 655] [2, 656] [2, 657] [2, 658] [2, 659] [2, 660] [2, 661] [2, 662] [3, 76] [2, 663] [2, 664] [2, 665] [2, 666] [2, 667] [2, 668] [2, 669] [2, 670] [2, 671] [2, 672] [2, 673] [2, 674] [2, 675] [3, 77] [4, 26] [2, 677] [2, 678] [2, 679] [2, 680] [2, 681] [2, 682] [2, 683] [2, 684] [2, 685] [2, 686] [2, 687] [2, 688] [3, 78] [2, 689] [2, 690] [2, 691] [2, 692] [2, 693] [2, 694] [2, 695] [2, 696] [2, 697] [2, 698] [2, 699] [2, 700] [2, 701] [2, 702] [3, 79] [2, 703] [2, 704] [2, 705] [2, 706] [2, 707] [2, 708] [2, 709] [2, 710] [2, 711] [2, 712] [2, 713] [2, 714] [2, 715] [3, 80] [2, 716] [2, 717] [2, 718] [2, 719] [2, 720] [2, 721] [2, 722] [2, 723] [2, 724] [19, 2] [2, 725] [2, 726] [2, 727] [2, 728] [12, 3] [2, 730] [2, 731] [2, 732] [2, 733] [5, 14] [2, 734] [2, 735] [2, 736] [2, 737] [2, 738] [2, 739] [2, 740] [2, 741] [2, 742] [3, 82] [2, 743] [2, 744] [2, 745] [2, 746] [2, 747] [2, 748] [2, 749] [2, 750] [2, 751] [2, 752] [2, 753] [2, 754] [2, 755] [2, 756] [3, 83] [2, 757] [2, 758] [2, 759] [2, 760] [2, 761] [2, 762] [2, 763] [2, 764] [2, 765] [2, 766] [2, 767] [2, 768] [2, 769] [3, 84] [2, 770] [2, 771] [2, 772] [2, 773] [2, 774] [2, 775] [2, 776] [2, 777] [2, 778] [2, 779] [2, 780] [2, 781] [2, 782] [2, 783] [3, 85] [4, 28] [2, 785] [2, 786] [2, 787] [2, 788] [2, 789] [2, 790] [2, 791] [2, 792] [2, 793] [2, 794] [2, 795] [2, 796] [2, 797] [3, 86] [2, 798] [2, 799] [2, 800] [2, 801] [2, 802] [2, 803] [2, 804] [2, 805] [2, 806] [2, 807] [2, 808] [2, 809] [2, 810] [2, 811] [3, 87] [2, 812] [2, 813] [2, 814] [2, 815] [2, 816] [2, 817] [2, 818] [2, 819] [2, 820] [2, 821] [2, 822] [2, 823] [2, 824] [2, 825] [3, 88] [2, 826] [2, 827] [2, 828] [2, 829] [2, 830] [2, 831] [2, 832] [2, 833] [2, 834] [2, 835] [2, 836] [2, 837] [2, 838] [2, 839] [3, 89] [2, 840] [4, 29] [2, 842] [2, 843] [2, 844] [2, 845] [2, 846] [2, 847] [2, 848] [2, 849] [2, 850] [2, 851] [2, 852] [2, 853] [3, 90] [2, 854] [2, 855] [2, 856] [2, 857] [2, 858] [2, 859] [2, 860] [2, 861] [2, 862] [2, 863] [2, 864] [2, 865] [2, 866] [2, 867] [2, 868] [3, 91] [2, 869] [2, 870] [2, 871] [5, 15] [2, 872] [2, 873] [2, 874] [2, 875] [2, 876] [2, 877] [2, 878] [2, 879] [2, 880] [2, 881] [2, 882] [3, 92] [2, 883] [2, 884] [2, 885] [2, 886] [2, 887] [2, 888] [2, 889] [2, 890] [2, 891] [2, 892] [2, 893] [2, 894] [2, 895] [2, 896] [3, 93] [2, 897] [2, 898] [2, 899] [4, 30] [2, 901] [2, 902] [2, 903] [2, 904] [2, 905] [2, 906] [2, 907] [7, 7] [2, 908] [2, 909] [2, 910] [2, 911] [3, 94] [2, 912] [2, 913] [2, 914] [2, 915] [2, 916] [2, 917] [2, 918] [2, 919] [2, 920] [2, 921] [2, 922] [2, 923] [2, 924] [2, 925] [3, 95] [2, 926] [2, 927] [2, 928] [2, 929] [2, 930] [2, 931] [2, 932] [2, 933] [2, 934] [2, 935] [2, 936] [2, 937] [2, 938] [2, 939] [2, 940] [3, 96] [2, 941] [2, 942] [2, 943] [2, 944] [2, 945] [2, 946] [2, 947] [2, 948] [2, 949] [2, 950] [2, 951] [2, 952] [2, 953] [2, 954] [2, 955] [3, 97] [2, 956] [2, 957] [2, 958] [2, 959] [2, 960] [4, 31] [2, 962] [2, 963] [2, 964] [2, 965] [2, 966] [2, 967] [2, 968] [2, 969] [2, 970] [3, 98] [2, 971] [2, 972] [2, 973] [2, 974] [2, 975] [2, 976] [2, 977] [2, 978] [2, 979] [2, 980] [2, 981] [2, 982] [2, 983] [2, 984] [2, 985] [3, 99] [2, 986] [2, 987] [2, 988] [2, 989] [2, 990] [2, 991] [2, 992] [2, 993] [2, 994] [2, 995] [2, 996] [2, 997] [2, 998] [2, 999] [6, 10] [3, -4] [3, -2] [3, -21218] [3, -1/4] 0 0 0 3 1 [1431, 5737585] [1278, 6780590] [983, 36262840] [508, 2044406843184] [274, 3873816255479006870044] [228, 34028236692093846346337460743176821665314] 10 10 1267650600228229401496703205653 121 1 [0, 0, 1, 0] [0, 0, 0, 0] [0, 0, Mod(735321672858813933, 1000039000207000297), 0] [0, 0, 0, 0] [Mod(766696600158900228, 1000039000207000297), Mod(9366110197497040718447998 65730, 1000113004462069006305361406593), Mod(6, 1000039000207000297), Mod(30 66786400635600912, 8000312001656002376)] [Mod(761273567620851421, 1000039000207000297), Mod(6350198471236493446056154 0863, 1000113004462069006305361406593), Mod(542283254184885017, 100003900020 7000297), Mod(4933525601020401464, 8000312001656002376)] Mod(583, 875) 1 Mod(0, 2) 0 0 1 Mod(Mod(1, 2)*y^2 + Mod(1, 2)*y + Mod(1, 2), Mod(1, 2)*y^3 + Mod(1, 2)*y^2 + Mod(1, 2)) 0 Mod(Mod(2, 5)*y^2 + Mod(4, 5), Mod(1, 5)*y^3 + Mod(1, 5)*y^2 + Mod(1, 5)) Mod(2, 5) 0 1 0 1 1 y 0 1 Mod(1, 2)*x + Mod(1, 2) t*x^2 + (t + 1)*x + 1 Mod(1, 5)*x^2 + Mod(3, 5)*x + Mod(2, 5) 2/x 1 1.2247448713915890490986420373529456960 1 0 1 1 t^2 + t + 1 0 1 0 1 1 1/2 x + 1/2 1/2 1 *** at top-level: issquare(Mod(1,4)*(x+1)^2) *** ^-------------------------- *** issquare: sorry, issquare for even characteristic != 2 is not yet implemented. 0 0 -2 1 -2/3 1 0 0 0 2 x + 2 0 11 1 1 1/(2*x) 1 + 1/3*x + O(x^2) -2/3 121 121 187 1 0 5 51 [0, 1, 1, 1, 1, 1] [0, 1, 1, 1, 1, 1] [0, 1, 1, 1, 1, 1] [0, 1, 1, 1, 1, 1] [0, 1, 1, 1, 1, 1] [0, 1, 1, 1, 1, 1] [0, 1, 1, 1, 1, 1] [0, 1, 1, 1, 1, 1] *** at top-level: ispower(Mod(x,x^2+1),2,&y) *** ^-------------------------- *** ispower: sorry, ispower for general t_POLMOD is not yet implemented. *** at top-level: ispower(Mod(x,x^2+1),2) *** ^----------------------- *** ispower: sorry, ispower for general t_POLMOD is not yet implemented. 11 29 101 1 (x - 1)/(x - 2) 1 (x + 1)/(x + 2) 1 1 1 1 Total time spent: 1346 pari-2.17.2/src/test/32/characteristic0000644000175000017500000000064014567450071016102 0ustar billbill0 0 6 0 3 0 3 0 3 2 0 0 2 *** at top-level: characteristic([ffgen(2),ffgen(3)]) *** ^----------------------------------- *** characteristic: inconsistent moduli in characteristic: 2 != 3 *** at top-level: characteristic([ffgen(2),Mod(1,3)]) *** ^----------------------------------- *** characteristic: inconsistent moduli in characteristic: 2 != 3 Total time spent: 0 pari-2.17.2/src/test/32/genus20000644000175000017500000000203614676526175014330 0ustar billbill[x^6 + a*x + b, 0, [-480*b, 5280*b^2, 20480*b^3, -9427200*b^4, 800000*a^6 - 11943936*b^5]] [x^6 + a*x + b, 2, -480*b] [x^6 + a*x + b, 4, 5280*b^2] [x^6 + a*x + b, 6, 20480*b^3] [x^6 + a*x + b, 8, -9427200*b^4] [x^6 + a*x + b, 10, 800000*a^6 - 11943936*b^5] [x^5 + a*x + b, 0, [80*a, 480*a^2, -1280*a^3, -83200*a^4, 65536*a^5 + 800000 *b^4]] [x^5 + a*x + b, 2, 80*a] [x^5 + a*x + b, 4, 480*a^2] [x^5 + a*x + b, 6, -1280*a^3] [x^5 + a*x + b, 8, -83200*a^4] [x^5 + a*x + b, 10, 65536*a^5 + 800000*b^4] [[x^6, x^3 + a*x + b], 0, [-4*a^3 - 147*b^2, -2*a^6 + 12*b^2*a^3 + 411*b^4, 36*b^2*a^6 + 12*b^4*a^3 + 401*b^6, -a^12 - 24*b^2*a^9 - 960*b^4*a^6 - 3308*b ^6*a^3 - 56967*b^8, -80*b^6*a^6 - 1080*b^8*a^3 - 18225*b^10]] [[x^6, x^3 + a*x + b], 2, -4*a^3 - 147*b^2] [[x^6, x^3 + a*x + b], 4, -2*a^6 + 12*b^2*a^3 + 411*b^4] [[x^6, x^3 + a*x + b], 6, 36*b^2*a^6 + 12*b^4*a^3 + 401*b^6] [[x^6, x^3 + a*x + b], 8, -a^12 - 24*b^2*a^9 - 960*b^4*a^6 - 3308*b^6*a^3 - 56967*b^8] [[x^6, x^3 + a*x + b], 10, -80*b^6*a^6 - 1080*b^8*a^3 - 18225*b^10] Total time spent: 0 pari-2.17.2/src/test/32/gchar-lfun0000644000175000017500000000506714676526175015162 0ustar billbill *** Warning: new stack size = 78000000 (74.387 Mbytes). Watkins 6.3 [[5, 0, 2, 2; 0, 5, 4, 2; 0, 0, 1, 0; 0, 0, 0, 1], []] [[5, 4, 1, 4; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], []] [1, []] I 1 -3/2 82745751406 + 355321179532*I 362254248594 + 43264990186*I 1 1 [3125, 4, [-1, 0, 0, 1]] 1 1 [] -3/2 [625, 4, [-1, 0, 0, 1]] 1 1 [[5, 0, 2, 2; 0, 5, 4, 2; 0, 0, 1, 0; 0, 0, 0, 1], []] 2778743/335817 + 7837035/220562*I 1 [[5, 4, 1, 4; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1], []] [1, []] Watkins 3.7 & 6.1 1 -1/2 + 489061/564719*I 1 1 [1, []] 3684093207 c of infinity type (2,0) -591844/788369 + 205142/310529*I -104200/529593 - 185083/188773*I 412230/435083 + 141948/443821*I -1 -1 -1 300863/829918 + 11851/12716*I 480891/768376 - 342287/438863*I -164008/165937 - 60802/399921*I 1 [1, []] [1, []] [1, []] [[0, -1, -1]~] 12381910021 6703372087 10611058327 1 1 -230000000000 1 Watkins examples 6.2 1 [[3, 0]] [3481, 4, [0, 1]] 1 1 1 575274201679174793153 S intersects mod 1 1 1 -1 -662784/684523 - 138919/555644*I 488380/954317 + 375973/437621*I 1 -931099/958120 - 157514/667955*I -327737/344913 - 255142/818721*I 1 1 1 [1, [0]] [1, [0]] [[4, 3, 0; 0, 1, 0; 0, 0, 1], [0]] [1, [0]] billtest [1, [0, 0, 0]] 1 [1, [1, 1, 0]] [1, [0, 0, 0]] 1 1 [[4, 0, 0; 0, 4, 0; 0, 0, 4], [1, 1, 1]] [1, [0, 0, 0]] 1 1 [[4, 0, 0; 0, 4, 0; 0, 0, 4], [1, 1, 1]] [1, [0, 0, 0]] 1 L function with imaginary shifts [0, 0, 0, 0] 1 1 1 1 need to increase prec II 293542/945551 [[10, 0, 7, 4; 0, 10, 9, 3; 0, 0, 1, 0; 0, 0, 0, 1], [0, 0]] 1 bug [Mat(16), [0]] 1 [Mat(32), [0]] 1 [Mat(288), [0]] 1 -1 1 bug from Atelier demo [1, -2, -6, 4, 5] norm component fix [5000000, 3000000, [-1000000 + 6528503*I, -1000000 - 6528503*I]] [1, 0, 0, 4, 5, 0, 0, 0, 9, 0] over Q [1, -1, [1]] [1, 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9, 1/10] 1 [1, -1, [1]] [1, 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9, 1/10] 1 [1, -1, [1]] [1, 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9, 1/10] 1 shifted zeta_K [5, -1, [1, 1]] [1, 0, 0, 1/4, 1/5, 0, 0, 0, 1/9, 0] 1 [5, -1, [1, 1]] [1, 0, 0, 1/4, 1/5, 0, 0, 0, 1/9, 0] 1 bad inputs *** at top-level: lfuncreate([gc,[1]~]) *** ^--------------------- *** lfuncreate: inconsistent dimensions in check_gchar_i [chi]. *** at top-level: lfuncreate([gc,[1,0,0,'x]~]) *** ^---------------------------- *** lfuncreate: incorrect type in check_gchar_i [coefficient] (t_POL). *** at top-level: lfuncreate([gc,[1,0,0,0,I]~]) *** ^----------------------------- *** lfuncreate: sorry, lfun for gchar with imaginary norm component is not yet implemented. Total time spent: 12299 pari-2.17.2/src/test/32/nflist0000644000175000017500000004750514676526175014436 0ustar billbill *** Warning: new stack size = 28000000 (26.703 Mbytes). group = C1 [1] [1] [x, 1] x [x] 1 [x] [x] group = C2 [3043, 3043] [3043, 3043] [x, 5] x 6086 5 [x^2 - x - 1] [x^2 - x - 1] group = C3 [15851, 0] [15851, 0] [x, 7] x 15851 49 [x^3 - x^2 - 2*x + 1] [x^3 - x^2 - 2*x + 1] group = S3 [366, 1520] [366, 1520] [x^2 - x - 555, 2] x^2 - x - 555 [x^3 - x^2 - 27*x + 61] 8884 [x^3 - x^2 - 27*x + 61, x^3 - x^2 - 12*x + 44] [x^3 - x^2 - 27*x + 61] group = C4 [586, 0, 582] [586, 0, 582] [x^2 - x - 1, [15, 6; 0, 3]] x^2 - x - 1 456 1125 [x^4 - 30*x^2 + 45] [x^4 - 30*x^2 + 45] group = V4 [3603, 0, 13076] [3603, 0, 13076] [x^2 - 10, 1] [x^2 - 10, x^2 - x - 1, x^2 - 2] 232 1600 [x^4 - 26*x^2 + 9, x^4 + 96*x^2 + 1024] [x^4 - 90*x^2 + 1225] group = D4 [1, 6, 17] [1, 6, 17] [x^2 - x - 1, [29, 5; 0, 1]] x^2 - x - 1 [x^4 - x^3 - 3*x^2 + x + 1, x^4 - x^3 + 2*x - 1, x^4 - x^2 - 1, x^4 - 2*x^3 + 2*x^2 - x - 1, x^4 - x^3 - 3*x - 1] 725 [x^4 - 11*x^2 + 29] [x^4 - 11*x^2 + 29] group = A4 [4, 0, 23] [4, 0, 23] [x^3 - x^2 - 10*x + 8, 8] [x^3 - x^2 - 10*x + 8, 8] [x^4 + 7*x^2 - 2*x + 14, x^4 - 6*x^2 - 8*x + 28, x^4 - 2*x^3 - 7*x^2 + 6*x + 11] 61504 [x^4 - 6*x^2 - 8*x + 28, x^4 - 2*x^3 - 7*x^2 + 6*x + 11] [x^4 - 6*x^2 - 8*x + 28, x^4 - 2*x^3 - 7*x^2 + 6*x + 11] group = S4 [7, 219, 140] [7, 219, 140] [x^3 - x^2 - 14*x + 23, 1] [x^3 - x^2 - 14*x + 23, 1] [x^4 - 26*x^2 - 8*x + 1] 2777 [x^4 - 26*x^2 - 8*x + 1] [x^4 - 26*x^2 - 8*x + 1] group = C5 [21, 0, 0] [21, 0, 0] [x, 11] x 21 14641 [x^5 - x^4 - 4*x^3 + 3*x^2 + 3*x - 1] [x^5 - x^4 - 4*x^3 + 3*x^2 + 3*x - 1] group = D5 [0, 0, 2] [0, 0, 2] [x^2 - x + 12, 1] [x^2 - x + 12, 1] [x^5 - 2*x^4 + 2*x^3 - x^2 + 1] 2209 [x^5 - 2*x^4 + 2*x^3 - x^2 + 1] [x^5 - 2*x^4 + 2*x^3 - x^2 + 1] group = F5 [0, 0, 4] [0, 0, 4] [x^4 - x^3 + x^2 - x + 1, [10, 0, 4, 2; 0, 10, 4, 6; 0, 0, 2, 0; 0, 0, 0, 2] ] [x^4 - x^3 + x^2 - x + 1, [10, 0, 4, 2; 0, 10, 4, 6; 0, 0, 2, 0; 0, 0, 0, 2] ] [x^5 - 2, x^5 + 5*x^3 + 5*x - 1] 50000 [x^5 - 2] [x^5 - 2] group = C6 [203, 0, 0, 236] [203, 0, 0, 236] [x^2 - 2, 7] [x^2 - 2, x^3 - x^2 - 2*x + 1] [x^6 + 2*x^5 - 9*x^4 - 14*x^3 + 10*x^2 + 8*x + 1, x^6 - 12*x^4 - 2*x^3 + 21* x^2 - 6*x - 1, x^6 + 2*x^5 - 13*x^4 - 14*x^3 + 26*x^2 + 28*x + 1, x^6 + 2*x^ 5 - 17*x^4 - 34*x^3 + 30*x^2 + 32*x - 7, x^6 + 2*x^5 - 25*x^4 - 44*x^3 + 92* x^2 + 112*x - 92, x^6 + 2*x^5 - 29*x^4 - 10*x^3 + 174*x^2 - 76*x - 31, x^6 + 2*x^5 - 33*x^4 - 20*x^3 + 220*x^2 - 64*x - 188, x^6 + 2*x^5 - 45*x^4 - 66*x ^3 + 390*x^2 + 340*x - 599, x^6 - 48*x^4 + 70*x^3 + 453*x^2 - 1050*x + 503, x^6 - 48*x^4 - 56*x^3 + 453*x^2 + 840*x + 62] 1229312 [x^6 + 2*x^5 - 9*x^4 - 14*x^3 + 10*x^2 + 8*x + 1, x^6 + 2*x^5 + 3*x^4 + 2*x^ 3 + 18*x^2 + 16*x + 41] [x^6 + 2*x^5 - 9*x^4 - 14*x^3 + 10*x^2 + 8*x + 1, x^6 + 2*x^5 + 3*x^4 + 2*x^ 3 + 18*x^2 + 16*x + 41] group = [6, 2] [16, 0, 0, 91] [16, 0, 0, 91] [x^3 - 11*x - 11, [17, 14, 1; 0, 1, 0; 0, 0, 1]] [x^3 - 11*x - 11, x^3 - 11*x - 11, x^3 - 11*x - 11, x^2 - x - 4] [x^6 - 73*x^4 + 22*x^3 + 988*x^2 + 880*x - 491] 71931233 [x^6 - 3*x^5 - 5*x^4 + 15*x^3 - 5*x^2 - 3*x + 1] [x^6 - 3*x^5 - 5*x^4 + 15*x^3 - 5*x^2 - 3*x + 1] group = [6, 3] [0, 0, 3, 12] [0, 0, 3, 12] [x^2 - x - 1, 7] [x^2 - x - 1, x^3 + 2*x - 2] [x^6 - x^5 - 2*x^4 + 5*x^3 - 2*x^2 - x + 1, x^6 - x^3 - 1, x^6 - x^5 - x^4 + 4*x^3 + 3*x^2 - 1] 98000 [x^6 - x^5 - 2*x^4 + 5*x^3 - 2*x^2 - x + 1] [x^6 - x^5 - 2*x^4 + 5*x^3 - 2*x^2 - x + 1] group = [6, 4] [0, 0, 13, 0] [0, 0, 13, 0] [x^3 - x^2 - 2*x + 1, [4, [0, 1, 1]]] x^3 - x^2 - 2*x + 1 [x^6 + x^4 - 2*x^2 - 1, x^6 - x^5 - 2*x^4 + x^3 - 7, x^6 - x^5 + 3*x^4 + 7*x ^3 - 9*x^2 + 19*x - 13, x^6 - 2*x^5 + 8*x^4 + 3*x^3 - 4*x^2 + 31*x - 29, x^6 - 2*x^5 - x^4 + x^3 - 14*x^2 + 28*x - 56] 153664 [x^6 + x^4 - 2*x^2 - 1] [x^6 + x^4 - 2*x^2 - 1] group = [6, 5] [0, 0, 0, 7] [0, 0, 0, 7] [x^2 - x + 1, [26, 18; 0, 2]] x^2 - x + 1 [x^6 - x^5 - 4*x^4 + 3*x^3 + 6*x^2 - 5*x + 1, x^6 - x^5 + x^4 - 2*x^3 + 4*x^ 2 - 3*x + 1, x^6 - 3*x^5 + 4*x^4 - x^3 - 2*x^2 + x + 1, x^6 - 3*x^5 + 4*x^4 - 2*x^3 - 2*x^2 + 2*x + 1] 73008 [x^6 - x^5 - 4*x^4 + 3*x^3 + 6*x^2 - 5*x + 1] [x^6 - x^5 - 4*x^4 + 3*x^3 + 6*x^2 - 5*x + 1] group = [6, 6] [3, 21, 20, 0] [3, 21, 20, 0] [x^3 - x^2 - 2*x + 1, [181, 37, 43; 0, 1, 0; 0, 0, 1]] x^3 - x^2 - 2*x + 1 28 434581 [x^6 - 2*x^5 - 4*x^4 + 5*x^3 + 4*x^2 - 2*x - 1] [x^6 - 2*x^5 - 4*x^4 + 5*x^3 + 4*x^2 - 2*x - 1] group = [6, 7] [0, 0, 6, 0] [0, 0, 6, 0] [x^3 - 4*x - 1, [1, [1, 1, 0]]] x^3 - 4*x - 1 [x^6 - x^4 - x^3 - x^2 + 1] 52441 [x^6 - x^4 - x^3 - x^2 + 1] [x^6 - x^4 - x^3 - x^2 + 1] group = [6, 8] [0, 0, 1, 11] [0, 0, 1, 11] [x^3 - x^2 - 3*x + 1, [[37, 33, 27; 0, 1, 0; 0, 0, 1], [0, 1, 1]]] x^3 - x^2 - 3*x + 1 [x^6 - 3*x^5 + 6*x^4 - 7*x^3 + 2*x^2 + x - 1] 810448 [x^6 - 3*x^5 + 6*x^4 - 7*x^3 + 2*x^2 + x - 1] [x^6 - 3*x^5 + 6*x^4 - 7*x^3 + 2*x^2 + x - 1] group = [6, 9] [0, 0, 1, 1] [0, 0, 1, 1] [x^3 + 12*x^2 + 576*x + 34560, 1] [x^3 + 12*x^2 + 576*x + 34560, x^3 + 12*x^2 + 576*x - 41472] [x^6 - 2*x^5 + 2*x^4 - 4*x^3 + 2*x^2 - 4*x + 1] 242000 [x^6 - 2*x^5 + 2*x^4 - 4*x^3 + 2*x^2 - 4*x + 1] [x^6 - 2*x^5 + 2*x^4 - 4*x^3 + 2*x^2 - 4*x + 1] group = [6, 10] [0, 0, 3, 0] [0, 0, 3, 0] [x^4 - x^3 + x^2 - x + 1, [31, 0, 18, 1; 0, 31, 18, 13; 0, 0, 1, 0; 0, 0, 0, 1]] x^4 - x^3 + x^2 - x + 1 [x^6 - x^5 + 4*x^4 - 2*x^3 + 6*x^2 - 5*x + 1, x^6 - x^5 + x^4 - x^3 - 4*x^2 + 5] 600625 [x^6 - x^5 + 4*x^4 - 2*x^3 + 6*x^2 - 5*x + 1] [x^6 - x^5 + 4*x^4 - 2*x^3 + 6*x^2 - 5*x + 1] group = [6, 11] [0, 0, 22, 31] [0, 0, 22, 31] [x^3 + x - 1, [73, 54, 23; 0, 1, 0; 0, 0, 1]] x^3 + x - 1 15 70153 [x^6 - 3*x^5 + 5*x^4 - 5*x^3 + 3*x^2 - x - 1] [x^6 - 3*x^5 + 5*x^4 - 5*x^3 + 3*x^2 - x - 1] group = [6, 13] [0, 0, 1, 6] [0, 0, 1, 6] [x^4 - x^3 + 8*x^2 - 7*x + 19, 1] x^4 - x^3 + 8*x^2 - 7*x + 19 [x^6 - x^5 + x^4 - 2*x^2 + x - 1] 30125 [x^6 - x^5 + x^4 - 2*x^2 + x - 1] [x^6 - x^5 + x^4 - 2*x^2 + x - 1] group = C7 [10, 0, 0] [10, 0, 0] [x, 29] x [x^7 - x^6 - 12*x^5 + 7*x^4 + 28*x^3 - 14*x^2 - 9*x - 1, x^7 - x^6 - 18*x^5 + 35*x^4 + 38*x^3 - 104*x^2 + 7*x + 49, x^7 - 21*x^5 - 21*x^4 + 91*x^3 + 112 *x^2 - 84*x - 97, x^7 - x^6 - 30*x^5 - 3*x^4 + 254*x^3 + 246*x^2 - 245*x - 1 37, x^7 - x^6 - 48*x^5 - 37*x^4 + 312*x^3 + 12*x^2 - 49*x + 1, x^7 - x^6 - 5 4*x^5 + 31*x^4 + 558*x^3 + 32*x^2 - 1713*x - 1121, x^7 - x^6 - 84*x^5 + 217* x^4 + 1348*x^3 - 3988*x^2 - 1433*x + 1163, x^7 - x^6 - 90*x^5 - 69*x^4 + 130 6*x^3 - 124*x^2 - 5249*x + 4663, x^7 - x^6 - 102*x^5 + 195*x^4 + 1850*x^3 - 978*x^2 - 8933*x - 5183, x^7 - x^6 - 120*x^5 + 711*x^4 - 784*x^3 - 1956*x^2 + 2863*x + 343] 594823321 [x^7 - 609*x^5 - 609*x^4 + 70847*x^3 - 25172*x^2 - 1321124*x - 2048647] [x^7 - 609*x^5 - 609*x^4 + 70847*x^3 - 25172*x^2 - 1321124*x - 2048647] group = D7 [0, 0, 0, 1] [0, 0, 0, 1] [x^2 - x + 18, 1] [x^2 - x + 18, 1] [x^7 - x^6 - x^5 + x^4 - x^3 - x^2 + 2*x + 1] 357911 [x^7 - x^6 - x^5 + x^4 - x^3 - x^2 + 2*x + 1] [x^7 - x^6 - x^5 + x^4 - x^3 - x^2 + 2*x + 1] group = M21 [0, 0, 0, 0] [0, 0, 0, 0] group = M42 [0, 0, 0, 0] [0, 0, 0, 0] group = C9 [2, 0, 0, 0, 0] [2, 0, 0, 0, 0] [x^3 - 3*x - 1, [9, 0, 0; 0, 9, 6; 0, 0, 3]] x^3 - 3*x - 1 [x^9 - 9*x^7 + 27*x^5 - 30*x^3 + 9*x - 1] 31381059609 [x^9 - 9*x^7 + 27*x^5 - 30*x^3 + 9*x - 1] [x^9 - 9*x^7 + 27*x^5 - 30*x^3 + 9*x - 1] group = [9, 2] [2, 0, 0, 0, 0] [2, 0, 0, 0, 0] [x^3 - 3*x - 1, 7] [x^3 - 3*x - 1, x^3 - 21*x - 35, x^3 - x^2 - 2*x + 1, x^3 - 21*x - 28] [x^9 - 3*x^8 - 6*x^7 + 21*x^6 + 9*x^5 - 45*x^4 - x^3 + 30*x^2 - 3, x^9 - 15* x^7 - 4*x^6 + 54*x^5 + 12*x^4 - 38*x^3 - 9*x^2 + 6*x + 1] 62523502209 [x^9 - 15*x^7 - 4*x^6 + 54*x^5 + 12*x^4 - 38*x^3 - 9*x^2 + 6*x + 1] [x^9 - 15*x^7 - 4*x^6 + 54*x^5 + 12*x^4 - 38*x^3 - 9*x^2 + 6*x + 1] group = D9 [0, 0, 0, 0, 1] [0, 0, 0, 0, 1] [x^2 - x + 15, 2] x^2 - x + 15 [x^9 - 3*x^8 + 4*x^7 - 5*x^6 + 6*x^5 - x^4 - 5*x^3 + 4*x^2 - 2] 775511104 [x^9 - 3*x^8 + 4*x^7 - 5*x^6 + 6*x^5 - x^4 - 5*x^3 + 4*x^2 - 2] [x^9 - 3*x^8 + 4*x^7 - 5*x^6 + 6*x^5 - x^4 - 5*x^3 + 4*x^2 - 2] group = C11 [1, 0, 0, 0, 0] [1, 0, 0, 0, 0] [x, 23] x [x^11 - x^10 - 10*x^9 + 9*x^8 + 36*x^7 - 28*x^6 - 56*x^5 + 35*x^4 + 35*x^3 - 15*x^2 - 6*x + 1] 41426511213649 [x^11 - 1265*x^9 - 759*x^8 + 578358*x^7 + 587972*x^6 - 114679334*x^5 - 13750 4235*x^4 + 9167517744*x^3 + 9817582522*x^2 - 201646411164*x - 102399340451] [x^11 - 1265*x^9 - 759*x^8 + 578358*x^7 + 587972*x^6 - 114679334*x^5 - 13750 4235*x^4 + 9167517744*x^3 + 9817582522*x^2 - 201646411164*x - 102399340451] group = D11 [0, 0, 0, 0, 0, 0] [0, 0, 0, 0, 0, 0] [x^11 - 1265*x^9 - 759*x^8 + 578358*x^7 + 587972*x^6 - 114679334*x^5 - 13750 4235*x^4 + 9167517744*x^3 + 9817582522*x^2 - 201646411164*x - 102399340451] x x^6 - 2*x^5 + 3*x^4 - 4*x^2 + 4*x - 3 [x, 53] [x^2 - x - 2110, 1] [[x^2 + 1, 3], [x^2 - x + 1, 4], [x^2 - 3, [1, [1, 1]]]] [x^3 - x^2 - 24*x + 27, 2] [x^6 - x^5 + x^4 - x^3 + x^2 - x + 1, [14, 0, 2, 10, 6, 6; 0, 14, 4, 8, 8, 4 ; 0, 0, 2, 0, 0, 0; 0, 0, 0, 2, 0, 0; 0, 0, 0, 0, 2, 0; 0, 0, 0, 0, 0, 2]] [x^6 - x^5 + 5*x^3 + 39*x^2 - 74*x + 155, 1] x^2 - 2 [[x^2 - 2, 7], [x^3 - x^2 - 2*x + 1, 8]] [[x^3 + x - 1, [[31, 21, 3; 0, 1, 0; 0, 0, 1], [1]]], [x^3 + x - 1, [[31, 21 , 3; 0, 1, 0; 0, 0, 1], [1]]], [x^3 + x - 1, [[31, 21, 3; 0, 1, 0; 0, 0, 1], [1]]], [x^2 - x + 8, 1]] [[x^3 - 3*x - 1, 7], [x^3 - 21*x - 35, 1], [x^3 - x^2 - 2*x + 1, 9], [x^3 - 21*x - 28, 1]] 0 *** nfresolvent: Warning: ignoring incorrect degree bound 18. 0 [x^2 + 1] [x^5 - 5*x - 12] [x^5 - 2*x^4 + 6*x^3 - 9*x^2 + 4*x + 1] [x^5 + 10*x^3 - 10*x^2 - 15*x - 18] 22 10 [[], [], [], [x^6 - x^5 + x^4 - x^3 + 15*x^2 - x + 29]] [[], []] [[x^4 - 10*x^2 + 20], [], [x^4 + 10*x^2 + 20]] [[x^3 - 6*x - 2], [x^3 - 6*x - 12]] [[x^3 - x^2 - 5*x - 1, x^3 - 5*x - 1, x^3 - 4*x - 1, x^3 + x^2 - 4*x - 1, x^ 3 + x^2 - 3*x - 1, x^3 + 2*x^2 - 4*x - 2, x^3 + 2*x^2 - 4*x - 1, x^3 + 2*x^2 - 3*x - 2, x^3 + 2*x^2 - 3*x - 1, x^3 + 4*x^2 - x - 2], [x^3 + x + 1, x^3 + 2*x + 1, x^3 + x^2 + x + 2, x^3 + x^2 + 2*x + 1, x^3 + x^2 + 3*x + 1, x^3 + x^2 + 3*x + 2, x^3 + 2*x^2 + 2*x + 2, x^3 + 2*x^2 + 3*x + 3, x^3 + 3*x^2 + 3*x + 3, x^3 + 2*x^2 + 6*x + 4]] [] [[x^5 - 9*x^3 - 4*x^2 + 17*x + 12], [], [x^5 - x^4 + 2*x^3 - 14*x^2 + 5*x - 17]] [[], [], [x^6 - x^3 - 1], []] [[x^9 - 9*x^7 + 27*x^5 - 30*x^3 + 9*x - 1], [], [], [], []] [[], [], [], [], [x^9 - 3*x^8 + 4*x^7 - 5*x^6 + 6*x^5 - x^4 - 5*x^3 + 4*x^2 - 2]] [x^9 - 2*x^8 + x^7 - 8*x^6 + 13*x^5 + 13*x^4 + 39*x^3 - 3*x^2 - 432*x - 405] 4 5 0 1 [x^2 - x - 1, x^2 - 2, x^2 - 3, x^2 - x - 3, x^2 - x - 4, x^2 - x - 5, x^2 - 6, x^2 - x + 1, x^2 + 1, x^2 - x + 2, x^2 + 2, x^2 - x + 3, x^2 - x + 4, x^ 2 - x + 5, x^2 + 5, x^2 - x + 6, x^2 + 6] [x^3 + x + 1, x^3 + 2*x + 1, x^3 + x^2 + x + 2, x^3 + x^2 + 2*x + 1, x^3 + x ^2 + 3*x + 1, x^3 + x^2 + 3*x + 2, x^3 + 2*x^2 + 2*x + 2, x^3 + 2*x^2 + 3*x + 3, x^3 + 3*x^2 + 3*x + 3, x^3 + 2*x^2 + 6*x + 4] 2 [] [] [x^2 - x - 4611686018427387904] [x^2 - x + 4611686018427387905] [] [x^2 + 4611686018427387905] [x^2 - 4611686018427387906, x^2 + 4611686018427387906] [x^2 - 4611686018427387907] [x^4 - 36893488147419103234*x^2 + 38187111840804345392508053338668630977, x^ 4 - 36893488147419103234*x^2 + 18446744073709551617] [] [] [] [] [] [x^6 + 2*x^5 - 9*x^4 - 14*x^3 + 10*x^2 + 8*x + 1, x^6 + 2*x^5 + 3*x^4 + 2*x^ 3 + 18*x^2 + 16*x + 41] [x^6 + 2*x^5 - 27*x^4 - 38*x^3 + 178*x^2 + 116*x - 239, x^6 + 2*x^5 + 21*x^4 + 26*x^3 + 210*x^2 + 148*x + 881] [x^6 - 3*x^5 + 7*x^4 - 9*x^3 + 7*x^2 - 3*x + 1] [x^6 - 3*x^5 + 7*x^4 - 9*x^3 + 7*x^2 - 3*x + 1] [x^6 - x^4 - 2*x^3 + x^2 + x + 1, x^6 - 2*x^4 + x^2 + 1] [x^6 - x^4 - x^3 - x^2 + 1] [x^4 + 2890*x^2 - 1234616*x + 63201517, x^4 - 213414*x^2 - 1234616*x + 11808 005213, x^4 - 38438*x^2 - 1234616*x + 198375645, x^4 - 75950*x^2 - 1234616*x + 693306021, x^4 + 41130*x^2 - 1234616*x + 513663501, x^4 + 12138*x^2 - 123 4616*x + 28807757, x^4 + 151010*x^2 - 1234616*x + 5934964757, x^4 - 4118*x^2 - 1234616*x + 92514525, x^4 - 22838*x^2 - 1234616*x - 8500739, x^4 - 9062*x ^2 - 1234616*x + 185351197, x^4 + 27426*x^2 - 1234616*x + 17052053, x^4 + 19 9114*x^2 - 1234616*x + 9340586349, x^4 + 6410*x^2 - 1234616*x + 51631661, x^ 4 - 254502*x^2 - 1234616*x + 15705760989, x^4 - 34470*x^2 - 1234616*x + 4816 20317, x^4 + 6250*x^2 - 1234616*x + 120263757, x^4 + 67522*x^2 - 1234616*x + 1531795701, x^4 + 24418*x^2 - 1234616*x + 17573077, x^4 - 53654*x^2 - 12346 16*x + 158554957, x^4 + 23674*x^2 - 1234616*x + 223451149, x^4 + 11866*x^2 - 1234616*x + 49398573, x^4 + 69082*x^2 - 1234616*x + 940601709, x^4 + 17570* x^2 - 1234616*x + 162982037, x^4 - 90102*x^2 - 1234616*x + 1517844269, x^4 - 25254*x^2 - 1234616*x + 27954525, x^4 - 8822*x^2 - 1234616*x + 159585837, x ^4 + 199018*x^2 - 1234616*x + 9933523789] [x^4 - 12406*x^2 - 367048*x - 246355, x^4 - 2822*x^2 - 367048*x + 24197325, x^4 + 42522*x^2 - 367048*x + 582148637, x^4 + 13402*x^2 - 367048*x + 2509357 , x^4 - 56918*x^2 - 367048*x + 897455629, x^4 - 12822*x^2 - 367048*x + 53137 41, x^4 - 9062*x^2 - 367048*x - 2043491, x^4 + 22042*x^2 - 367048*x + 350226 37, x^4 + 22282*x^2 - 367048*x + 108889389] [x^4 + 134166*x^2 - 14895608*x + 2433287281, x^4 - 15266*x^2 - 2127944*x + 5 77785017, x^4 + 55450*x^2 - 14895608*x + 2704952669, x^4 + 288172*x^2 - 2127 944*x + 20675201648, x^4 - 283894*x^2 - 27663272*x + 5256230733, x^4 - 25339 6*x^2 - 3951896*x + 9312424576, x^4 + 516932*x^2 - 27663272*x + 74101849120, x^4 + 2003430*x^2 - 3951896*x + 1008764048929, x^4 - 25100*x^2 - 2127944*x - 50276032, x^4 - 236178*x^2 - 14895608*x + 844476681, x^4 + 86524*x^2 - 212 7944*x + 1359222128, x^4 + 1343516*x^2 - 14895608*x + 459265503856, x^4 + 73 132*x^2 - 3343912*x + 1733021936, x^4 + 564630*x^2 - 23407384*x + 1638239454 25, x^4 + 70676*x^2 - 3343912*x + 938246416, x^4 + 1174124*x^2 - 23407384*x + 269767498272, x^4 - 482454*x^2 - 23407384*x + 70326282157, x^4 - 10628*x^2 - 3343912*x + 4110395168, x^4 - 199580*x^2 - 23407384*x + 1064606144, x^4 - 534026*x^2 - 3343912*x + 67430683889, x^4 + 125622*x^2 - 1519960*x + 392789 4177, x^4 + 1131716*x^2 - 10639720*x + 290965381392, x^4 - 214*x^2 - 1519960 *x + 182862637, x^4 - 131068*x^2 - 10639720*x + 31089928000, x^4 + 905660*x^ 2 - 10639720*x + 196509337792, x^4 + 118062*x^2 - 1519960*x + 4102674697, x^ 4 + 90198*x^2 - 10639720*x + 2132109217, x^4 + 60650*x^2 - 1519960*x + 34855 6653, x^4 + 8942*x^2 - 1519960*x + 104195625, x^4 + 163978*x^2 - 10639720*x + 21652307213, x^4 - 125922*x^2 - 1519960*x + 3484084153, x^4 - 2064772*x^2 - 10639720*x + 1050122858112] [x^3 - 9*x - 3] [[x^11 - x^10 - 10*x^9 + 9*x^8 + 36*x^7 - 28*x^6 - 56*x^5 + 35*x^4 + 35*x^3 - 15*x^2 - 6*x + 1, x^11 - x^10 - 30*x^9 + 63*x^8 + 220*x^7 - 698*x^6 - 101* x^5 + 1960*x^4 - 1758*x^3 + 35*x^2 + 243*x + 29], [], [], [], [], []] [[x^5 - 10*x^3 + 20*x - 10, x^5 - x^4 - 8*x^3 + 6*x^2 + 13*x - 9, x^5 - 9*x^ 3 - 4*x^2 + 17*x + 12], [], [x^5 - 3, x^5 - 2, x^5 + 5*x^3 + 5*x - 1, x^5 - x^4 + 4*x^3 + 4*x^2 - x + 13, x^5 + 5*x^3 + 5*x - 2, x^5 - x^4 - 2*x^3 + x^2 + 2*x - 3, x^5 - 2*x^4 - 2*x^3 + 8*x^2 - x - 10, x^5 + 2*x^3 - 4*x^2 - x - 4, x^5 - x^4 + 2*x^3 - 4*x^2 + x - 1, x^5 - x^4 + x^2 + 3*x + 1]] [x] [x^3 - x^2 - 2*x + 1, x^3 - 3*x + 1, x^3 - x^2 - 4*x - 1, x^3 - x^2 - 6*x + 7, x^3 - x^2 - 10*x + 8, x^3 - x^2 - 12*x - 11, x^3 - x^2 - 14*x - 8, x^3 - x^2 - 20*x + 9, x^3 - 21*x - 35, x^3 - 21*x + 28] [x^4 + 10*x^2 + 5, x^4 - 30*x^2 + 45, x^4 - 10*x^2 + 5, x^4 - 70*x^2 + 245, x^4 - 10*x^2 + 20, x^4 + 10*x^2 + 20, x^4 - 110*x^2 + 605, x^4 + 30*x^2 + 45 , x^4 + 130*x^2 + 845, x^4 - 4*x^2 + 2, x^4 + 4*x^2 + 2, x^4 - 12*x^2 + 18, x^4 + 12*x^2 + 18, x^4 + 26*x^2 + 117, x^4 - 78*x^2 + 1053, x^4 - 26*x^2 + 1 17, x^4 - 34*x^2 + 17, x^4 + 58*x^2 + 725] [x^4 + 14*x^2 + 1, x^4 - 4*x^2 + 64, x^4 + 20*x^2 + 16, x^4 - 10*x^2 + 121, x^4 + 22*x^2 + 25, x^4 + 28*x^2 + 64, x^4 - 2*x^2 + 81, x^4 + 22*x^2 + 9, x^ 4 + 24*x^2 + 16, x^4 + 4*x^2 + 144] 15 [x^4 - 2*x^3 + 2*x^2 + 2, x^4 - x^3 + 5*x^2 - 4*x + 3, x^4 - 2*x^3 + 6*x^2 - 4*x + 2, x^4 - x^3 + 6*x^2 - 5*x + 8, x^4 - x^3 + 3*x^2 + x + 20, x^4 - x^3 - 3*x + 4, x^4 - 2*x^3 + 2*x^2 + 4*x + 2, x^4 + 3*x^2 - 7*x + 4, x^4 - 2*x^ 3 + 10*x^2 - 8*x + 2, x^4 + 7*x^2 - 2*x + 14, x^4 - x^3 - 7*x^2 + 2*x + 9] [x^4 + 12*x^2 - 8*x + 16, x^4 - 2*x^2 - 8*x + 25, x^4 - 8*x + 16, x^4 + 2*x^ 2 - 8*x + 21, x^4 + 6*x^2 - 8*x + 17, x^4 + 10*x^2 - 8*x + 109, x^4 + 282*x^ 2 - 8*x + 19933, x^4 - 8*x - 16, x^4 - 14*x^2 - 16*x + 13, x^4 + 2*x^2 - 8*x - 59, x^4 - 20*x^2 - 16*x - 16, x^4 - 2*x^2 - 8*x - 23, x^4 + 2*x^2 - 16*x - 3, x^4 - 8*x^2 - 8*x - 16, x^4 - 2*x^2 - 32*x - 47, x^4 - 6*x^2 - 8*x - 19 , x^4 + 10*x^2 - 8*x - 83] [x^5 - x^4 - 4*x^3 + 3*x^2 + 3*x - 1, x^5 - 10*x^3 - 5*x^2 + 10*x - 1, x^5 - x^4 - 12*x^3 + 21*x^2 + x - 5, x^5 - x^4 - 16*x^3 - 5*x^2 + 21*x + 9, x^5 - x^4 - 24*x^3 + 17*x^2 + 41*x + 13, x^5 - x^4 - 28*x^3 - 37*x^2 + 25*x - 1, x^5 - x^4 - 40*x^3 - 93*x^2 - 21*x + 17, x^5 - x^4 - 52*x^3 + 89*x^2 + 109*x - 193, x^5 - x^4 - 60*x^3 + 12*x^2 + 784*x - 128, x^5 - x^4 - 72*x^3 + 123* x^2 + 223*x + 49] [x^5 - 2*x^4 + 2*x^3 - x^2 + 1, x^5 - x^4 + x^3 - 2*x^2 + 3*x - 1, x^5 - 2*x ^4 + 3*x^3 - 3*x^2 + x + 1, x^5 - x^4 - x^2 + 3*x - 1, x^5 - x^4 - 2*x^3 + x ^2 + 3*x - 1, x^5 - x^4 + 2*x^3 - x^2 + x + 2, x^5 - x^4 - x^3 + 3*x - 1, x^ 5 + x^3 - 3*x^2 + x - 3, x^5 - x^4 + 3*x^2 - x + 2, x^5 - x^3 - 2*x^2 + 3*x + 4] [x^5 - 3, x^5 - 2, x^5 + 5*x^3 + 5*x - 1, x^5 - x^4 + 4*x^3 + 4*x^2 - x + 13 , x^5 + 5*x^3 + 5*x - 2, x^5 - x^4 - 2*x^3 + x^2 + 2*x - 3, x^5 - 2*x^4 - 2* x^3 + 8*x^2 - x - 10, x^5 + 2*x^3 - 4*x^2 - x - 4, x^5 - x^4 + 2*x^3 - 4*x^2 + x - 1, x^5 - x^4 + x^2 + 3*x + 1] [x^6 - x^5 - 2*x^4 + x^3 + 7*x^2 + 7] [x^6 - 2*x^5 - 5*x^4 - 16*x^3 + 8*x + 28] *** at top-level: nflist("S3",-1) *** ^--------------- *** nflist: domain error in nflist: Xinf <= 0 *** at top-level: nflist("S3",[-1,2]) *** ^------------------- *** nflist: domain error in nflist: Xinf <= 0 *** at top-level: nflist("S3",[1,-2]) *** ^------------------- *** nflist: domain error in nflist: X <= 0 *** at top-level: nflist("S5") *** ^------------ *** nflist: unsupported group (S5). Use one of "C1"=[1,1]; "C2"=[2,1]; "C3"=[3,1], "S3"=[3,2]; "C4"=[4,1], "V4"=[4,2], "D4"=[4,3], "A4"=[4,4], "S4"=[4,5]; "C5"=[5,1], "D5"=[5,2], "F5"="M20"=[5,3], "A5"=[5,4]; "C6"=[6,1], "D6"=[6,2], [6,3], [6,4],..., [6,13]; "C7"=[7,1], "D7"=[7,2], "M21"=[7,3], "M42"=[7,4]; "C9"=[9,1], [9,2], "D9"=[9,3]." Also supported are "Cp"=[p,1] and "Dp"=[p,2] for any odd prime p. *** at top-level: nflist([10,1]) *** ^-------------- *** nflist: unsupported group ([10, 1]). Use one of "C1"=[1,1]; "C2"=[2,1]; "C3"=[3,1], "S3"=[3,2]; "C4"=[4,1], "V4"=[4,2], "D4"=[4,3], "A4"=[4,4], "S4"=[4,5]; "C5"=[5,1], "D5"=[5,2], "F5"="M20"=[5,3], "A5"=[5,4]; "C6"=[6,1], "D6"=[6,2], [6,3], [6,4],..., [6,13]; "C7"=[7,1], "D7"=[7,2], "M21"=[7,3], "M42"=[7,4]; "C9"=[9,1], [9,2], "D9"=[9,3]." Also supported are "Cp"=[p,1] and "Dp"=[p,2] for any odd prime p. *** at top-level: nflist([9,9]) *** ^------------- *** nflist: unsupported group ([9, 9]). Use one of "C1"=[1,1]; "C2"=[2,1]; "C3"=[3,1], "S3"=[3,2]; "C4"=[4,1], "V4"=[4,2], "D4"=[4,3], "A4"=[4,4], "S4"=[4,5]; "C5"=[5,1], "D5"=[5,2], "F5"="M20"=[5,3], "A5"=[5,4]; "C6"=[6,1], "D6"=[6,2], [6,3], [6,4],..., [6,13]; "C7"=[7,1], "D7"=[7,2], "M21"=[7,3], "M42"=[7,4]; "C9"=[9,1], [9,2], "D9"=[9,3]." Also supported are "Cp"=[p,1] and "Dp"=[p,2] for any odd prime p. *** at top-level: nflist([11,3]) *** ^-------------- *** nflist: unsupported group ([11, 3]). Use one of "C1"=[1,1]; "C2"=[2,1]; "C3"=[3,1], "S3"=[3,2]; "C4"=[4,1], "V4"=[4,2], "D4"=[4,3], "A4"=[4,4], "S4"=[4,5]; "C5"=[5,1], "D5"=[5,2], "F5"="M20"=[5,3], "A5"=[5,4]; "C6"=[6,1], "D6"=[6,2], [6,3], [6,4],..., [6,13]; "C7"=[7,1], "D7"=[7,2], "M21"=[7,3], "M42"=[7,4]; "C9"=[9,1], [9,2], "D9"=[9,3]." Also supported are "Cp"=[p,1] and "Dp"=[p,2] for any odd prime p. *** at top-level: nflist("M21",[1,10^4],,x) *** ^------------------------- *** nflist: incorrect type in makeMgenvec [field] (t_POL). *** at top-level: nflist("C3",x) *** ^-------------- *** nflist: incorrect variable in nflist / Q(T). *** at top-level: nflist("C3",[x]) *** ^---------------- *** nflist: incorrect type in nflist (t_VEC). Total time spent: 45508 pari-2.17.2/src/test/32/lambert0000644000175000017500000001667614567450071014560 0ustar billbill-127 -127 -127 1 1 x - 2*x^2 + 8*x^3 - 52*x^4 + O(x^5) -1 + 2.3316439815971242033635360621684008764*x - 1.8121878856393634902401916 475684416652*x^2 + 1.9366311144923597553632774576683830638*x^3 - 2.353551201 8816145168215435615164839701*x^4 + 3.0668589010506319128931489227040074985*x ^5 - 4.1753356002581771388549841774603735734*x^6 + 5.85802372987477414881505 38461186213042*x^7 - 8.4010322175239773709841616885138862869*x^8 + O(x^10) realprecision = 115 significant digits -376 -5.3402596700949534941383668225555610985116172433805954782315993056895856593 63371478458597643249567847856769658260138 - 20.16142319411729957052660761663 9900799892307588217464341143516460929255818314114185848396736787490164559224 53507938*I -4.9880136260605828005616558438145653171651930088796221871134876787550777308 24303513524813324318790229759607448463585 - 13.79009856365686552397559158400 6611900218963961468842433717889077888873574776280275593805359695000142386074 92412155*I -4.4490981787008898640867157232460451274645883248560292243219377121537983732 39181560278546205925643712909055768051551 - 7.307060789217608631014416845535 8639797400912986829032801724659855526522573777510811321213152295822684446665 25409901*I -3.5771520639572972184093919635119948804017962577930759236835277557916872363 50575462861463655620846808017732465627597 -0.1118325591589629648335694568202658422726453622912658633296897727621943319 600088273854870109175450158342884320482618 -4.4490981787008898640867157232460451274645883248560292243219377121537983732 39181560278546205925643712909055768051551 + 7.307060789217608631014416845535 8639797400912986829032801724659855526522573777510811321213152295822684446665 25409901*I -4.9880136260605828005616558438145653171651930088796221871134876787550777308 24303513524813324318790229759607448463585 + 13.79009856365686552397559158400 6611900218963961468842433717889077888873574776280275593805359695000142386074 92412155*I -5.3402596700949534941383668225555610985116172433805954782315993056895856593 63371478458597643249567847856769658260138 + 20.16142319411729957052660761663 9900799892307588217464341143516460929255818314114185848396736787490164559224 53507938*I -5.6014109903427322096167650220733623490356358844594914803619168843779914275 42038373624026462955940523347054962339599 + 26.49519305147605343386793972471 1257766439571616373780373344156828463901168909519710293826814383985153180447 87219294*I 1 1 -1.0000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000100000000000000 E-100 -235.72115887568531366046060613052381904089474941552282678480126614915620456 73087957949162547505515081005140328081624 -127 realprecision = 38 significant digits 2294.8466716835068696527927859936167900 [80756, 143546, 206207, 268880, 331575, 394291, 457025, 519772, 582530, 6452 97] [645297, 1273229, 1901362, 2529568, 3157809, 3786071, 4414346, 5042630, 5670 920, 6299215] -124 -125 -124 -0.11183255915896296483356945682026584227 + 1.259138243719728965715054006070 5240031*x - 1.6852428384809363610210659367818340853*x^2 + 3.4291673226261904 583853755123230321787*x^3 - 8.3124278935896423816322275264661558589*x^4 + 22 .192041045064393615638086769981588715*x^5 - 62.98871981557945627008906176672 5915063*x^6 + 186.51177668554172322377457555088051806*x^7 - 569.652409554563 39671619044006869748162*x^8 + 1781.5472885816549140607351235777129833*x^9 - 5676.7252711861651241033436836863691051*x^10 + 18363.79942204727076369120249 6303983962*x^11 - 60151.619699528575339208972954882737287*x^12 + 199105.5264 9949197207531959345366339638*x^13 - 664959.24537741790849323213330675990009* x^14 + 2237932.4714533367844314248148604297082*x^15 + O(x^16) -3.5771520639572972184093919635119948804 - 13.880252213229780748699361486619 519025*x - 58.951959272161933194695044664902424002*x^2 + O(x^3) (-0.31813150520476413531265425158766451720 + 1.33723570143068940890116214319 37106125*I) + (-0.69737020568869652814336849691964576475 - 0.593497673464482 61340594535025574132226*I)*x + (-0.33297334840180772560161645925109511009 - 0.49935253218764022307275247549263486578*I)*x^2 + (-0.2168636246943983568828 3040756615878561 - 0.49469441527649194153909613354792024339*I)*x^3 + (-0.160 20988127571126017705750236841905251 - 0.532578770626109204090740710366128680 73*I)*x^4 + (-0.12677288710193265638699448893876408203 - 0.60627151593817740 035089226627833359509*I)*x^5 + (-0.10475327844045706942259679324196057640 - 0.72014724453603639046705025073100163687*I)*x^6 + (-0.0891764685999430439009 80705138917501307 - 0.88540404532387013537890293079186615007*I)*x^7 + (-0.07 7586192554111070194946545325347354324 - 1.1203123602733012827902280837251262 279*I)*x^8 + (-0.068631600653858547181071490834145680710 - 1.452342481900855 3333227724598860306772*I)*x^9 + (-0.061508999455518349081010553357784107267 - 1.9219122678369782834401795177329475913*I)*x^10 + (-0.05571062741146945249 8696189575810912902 - 2.5881755204709353605112547694582420543*I)*x^11 + (-0. 050900098566873235057129781731068364461 - 3.53771093391828492695126969994227 46099*I)*x^12 + (-0.046845820129709063433619277861998722536 - 4.897479321691 1263872928749155211431733*I)*x^13 + (-0.043383187504440321433413244752801483 734 - 6.8541325989233120421465180303974100232*I)*x^14 + (-0.0403920297091715 56525032384691785928830 - 9.6828191677170351499970157871737049292*I)*x^15 + O(x^16) (-0.31813150520476413531265425158766451720 - 1.33723570143068940890116214319 37106125*I) + (-0.69737020568869652814336849691964576475 + 0.593497673464482 61340594535025574132226*I)*x + (-0.33297334840180772560161645925109511009 + 0.49935253218764022307275247549263486578*I)*x^2 + (-0.2168636246943983568828 3040756615878561 + 0.49469441527649194153909613354792024339*I)*x^3 + (-0.160 20988127571126017705750236841905251 + 0.532578770626109204090740710366128680 73*I)*x^4 + (-0.12677288710193265638699448893876408203 + 0.60627151593817740 035089226627833359509*I)*x^5 + (-0.10475327844045706942259679324196057640 + 0.72014724453603639046705025073100163687*I)*x^6 + (-0.0891764685999430439009 80705138917501307 + 0.88540404532387013537890293079186615007*I)*x^7 + (-0.07 7586192554111070194946545325347354324 + 1.1203123602733012827902280837251262 279*I)*x^8 + (-0.068631600653858547181071490834145680710 + 1.452342481900855 3333227724598860306772*I)*x^9 + (-0.061508999455518349081010553357784107267 + 1.9219122678369782834401795177329475913*I)*x^10 + (-0.05571062741146945249 8696189575810912902 + 2.5881755204709353605112547694582420543*I)*x^11 + (-0. 050900098566873235057129781731068364461 + 3.53771093391828492695126969994227 46099*I)*x^12 + (-0.046845820129709063433619277861998722536 + 4.897479321691 1263872928749155211431733*I)*x^13 + (-0.043383187504440321433413244752801483 734 + 6.8541325989233120421465180303974100232*I)*x^14 + (-0.0403920297091715 56525032384691785928830 + 9.6828191677170351499970157871737049292*I)*x^15 + O(x^16) x^3 + O(x^4) x^2 + O(x^4) x^2 - x^4 + O(x^5) 3 + 2*3^2 + 2*3^6 + 3^8 + 3^9 + O(3^10) O(3^10) 2*3 + 2*3^2 + 2*3^3 + 3^4 + 3^5 + 2*3^9 + 3^10 + O(3^11) O(3^10) 2^2 + 2^4 + 2^6 + 2^7 + 2^8 + 2^9 + O(2^11) 2^2 + 2^4 + 2^6 + 2^7 + 2^8 + 2^9 + 2^11 + O(2^12) *** at top-level: lambertw(1/x) *** ^------------- *** lambertw: domain error in lambertw: valuation < 0 *** at top-level: lambertw(0,-1) *** ^-------------- *** lambertw: domain error in glambertW: argument out of range *** at top-level: lambertw(mie+x+O(x^2)) *** ^---------------------- *** lambertw: odd valuation at branch point. Total time spent: 1310 pari-2.17.2/src/test/32/divisors0000644000175000017500000000107314567450071014755 0ustar billbill[1, 66, 196, 456, 2926, 12936] [19, 84, 539, 1254, 3724, 245784] [1, 72, 143, 924, 2912, 10296] [28, 99, 312, 2016, 4004, 288288] [2, 352, 702, 2277, 14352, 123552] [23, 198, 1248, 4048, 8073, 1420848] [1, 14, 40, 105, 560] [1] [1] [1] [1, 2, 3, 4, 6, 12] [[1, matrix(0,2)]] [[1, matrix(0,2)], [2, Mat([2, 1])], [3, Mat([3, 1])], [4, Mat([2, 2])], [6, [2, 1; 3, 1]], [12, [2, 2; 3, 1]]] [1, matrix(0,2)] [2, Mat([2, 1])] [4, Mat([2, 2])] [5, Mat([5, 1])] [10, [2, 1; 5, 1]] [20, [2, 2; 5, 1]] [25, Mat([5, 2])] [50, [2, 1; 5, 2]] [100, [2, 2; 5, 2]] Total time spent: 1 pari-2.17.2/src/test/32/member0000644000175000017500000002143114760123736014362 0ustar billbill.pol: x .a1: 0 .a2: 0 .a3: 0 .a4: 0 .a6: 0 NF .codiff: [1, 553/1105; 0, 1/1105] .diff: [1105, 553; 0, 1] .disc: 1105 .index: 2 .nf: [y^2 - 1105, [2, 0], 1105, 2, [[1, -17.12077013859466140231529077105260 9448; 1, 16.120770138594661402315290771052609448], [1, -17.12077013859466140 2315290771052609448; 1, 16.120770138594661402315290771052609448], [16, -274; 16, 258], [2, -1; -1, 553], [1105, 553; 0, 1], [553, 1; 1, 2], [1105, [553, 276; 1, 552]], [5, 13, 17]], [-33.241540277189322804630581542105218897, 33. 241540277189322804630581542105218897], [2, y - 1], [1, 1; 0, 2], [1, 0, 0, 2 76; 0, 1, 1, -1]] .p: [5, 13, 17] .pol: y^2 - 1105 .r1: 2 .r2: 0 .roots: [-33.241540277189322804630581542105218897, 33.2415402771893228046305 81542105218897] .sign: [2, 0] .t2: [2, -1.0000000000000000000000000000000000000; -1.0000000000000000000000 000000000000000, 553.00000000000000000000000000000000000] .zk: [1, 1/2*y - 1/2] NF chvar *** nfinit: Warning: nonmonic polynomial. Result of the form [nf,c]. .codiff: [1/2, 0; 0, 1/4] .diff: [4, 0; 0, 2] .disc: -8 .index: 1 .nf: [y^2 + 2, [0, 1], -8, 1, [Mat([1, 0.E-57 + 1.41421356237309504880168872 42096980786*I]), [1, 1.4142135623730950488016887242096980786; 1, -1.41421356 23730950488016887242096980786], [16, 23; 16, -23], [2, 0; 0, -4], [4, 0; 0, 2], [2, 0; 0, -1], [2, [0, -2; 1, 0]], [2]], [0.E-57 + 1.4142135623730950488 016887242096980786*I], [1, y], [1, 0; 0, 1], [1, 0, 0, -2; 0, 1, 1, 0]] .p: [2] .pol: y^2 + 2 .r1: 0 .r2: 1 .roots: [0.E-57 + 1.4142135623730950488016887242096980786*I] .sign: [0, 1] .t2: [2, 0.E-57; 0.E-57, 4.0000000000000000000000000000000000000] .zk: [1, y] BNF .bnf.cyc: [2, 2] .clgp: [4, [2, 2], [[2, 0; 0, 1], [3, 0; 0, 1]]] .codiff: [1, 553/1105; 0, 1/1105] .cyc: [2, 2] .diff: [1105, 553; 0, 1] .disc: 1105 .fu: [Mod(857*y - 28488, y^2 - 1105)] .gen: [[2, 0; 0, 1], [3, 0; 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], [16, -274; 16, 258], [2, -1; -1, 553], [1105, 553; 0, 1], [553, 1; 1, 2], [1105, [553, 276; 1, 552]], [5, 13, 17]], [-33.241540277189322804630581542105218897, 33. 241540277189322804630581542105218897], [2, y - 1], [1, 1; 0, 2], [1, 0, 0, 2 76; 0, 1, 1, -1]] .no: 4 .p: [5, 13, 17] .pol: y^2 - 1105 .r1: 2 .r2: 0 .reg: 10.950385405825605330267750825017937393 .roots: [-33.241540277189322804630581542105218897, 33.2415402771893228046305 81542105218897] .sign: [2, 0] .t2: [2, -1.0000000000000000000000000000000000000; -1.0000000000000000000000 000000000000000, 553.00000000000000000000000000000000000] .tu: [2, -1] .zk: [1, 1/2*y - 1/2] BNR .bid: [[[4, 0; 0, 4], [0, 0]], [4, [2, 2], [[1, -2]~, [-1, -2]~]], [[[2, [-1 , 1]~, 1, 1, [0, 276; 1, -1]], 2; [2, [2, 1]~, 1, 1, [1, 276; 1, 0]], 2], [[ 2, [-1, 1]~, 1, 1, [0, 276; 1, -1]], 2; [2, [2, 1]~, 1, 1, [1, 276; 1, 0]], 2]], [[[[2], [[1, -2]~], [4, 1; 0, 1], [[[0, -1]~, [1, 1], [2, [-1, 1]~, 1, 1, [0, 276; 1, -1]]]~, 1, [1, matrix(0,2)]], [1, 1, [[[2], [3], Mat([1, -1]) , 2]]], [[0]~, Mat(1)]], [[2], [[-1, -2]~], [4, 0; 0, 1], [[[1, -1]~, [1, 0] , [2, [2, 1]~, 1, 1, [1, 276; 1, 0]]]~, 1, [1, matrix(0,2)]], [1, 1, [[[2], [3], Mat([1, 0]), 2]]], [[0]~, Mat(1)]]], [[], Vecsmall([])]], [[1; 0], [0; 1]]] .bnf.cyc: [2, 2] .clgp: [4, [2, 2]] .codiff: [1, 553/1105; 0, 1/1105] .cyc: [2, 2] .diff: [1105, 553; 0, 1] .disc: 1105 .index: 2 .mod: [[4, 0; 0, 4], [0, 0]] .nf: [y^2 - 1105, [2, 0], 1105, 2, [[1, -17.12077013859466140231529077105260 9448; 1, 16.120770138594661402315290771052609448], [1, -17.12077013859466140 2315290771052609448; 1, 16.120770138594661402315290771052609448], [16, -274; 16, 258], [2, -1; -1, 553], [1105, 553; 0, 1], [553, 1; 1, 2], [1105, [553, 276; 1, 552]], [5, 13, 17]], [-33.241540277189322804630581542105218897, 33. 241540277189322804630581542105218897], [2, y - 1], [1, 1; 0, 2], [1, 0, 0, 2 76; 0, 1, 1, -1]] .no: 4 .p: [5, 13, 17] .pol: y^2 - 1105 .r1: 2 .r2: 0 .roots: [-33.241540277189322804630581542105218897, 33.2415402771893228046305 81542105218897] .sign: [2, 0] .t2: [2, -1.0000000000000000000000000000000000000; -1.0000000000000000000000 000000000000000, 553.00000000000000000000000000000000000] .zk: [1, 1/2*y - 1/2] .zkst: [4, [2, 2], [[1, -2]~, [-1, -2]~]] RNF .disc: [[4420, 553; 0, 1], [1, 2]~] .index: [2, 0; 0, 1] .nf: [y^2 - 1105, [2, 0], 1105, 2, [[1, -17.12077013859466140231529077105260 9448; 1, 16.120770138594661402315290771052609448], [1, -17.12077013859466140 2315290771052609448; 1, 16.120770138594661402315290771052609448], [16, -274; 16, 258], [2, -1; -1, 553], [1105, 553; 0, 1], [553, 1; 1, 2], [1105, [553, 276; 1, 552]], [5, 13, 17]], [-33.241540277189322804630581542105218897, 33. 241540277189322804630581542105218897], [2, y - 1], [1, 1; 0, 2], [1, 0, 0, 2 76; 0, 1, 1, -1]] .p: [2, 5, 13, 17] .pol: x^2 - y .polabs: x^4 - 1105 .zk: [[1, x - 1], [1, [1, 1/2; 0, 1/2]]] QUADCLASSUNIT .clgp: [4, [2, 2], [Qfb(2, 33, -2), Qfb(3, 31, -12)]] .cyc: [2, 2] .gen: [Qfb(2, 33, -2), Qfb(3, 31, -12)] .no: 4 .normfu: -1 .reg: 10.950385405825605330267750825017937393 GAL .gen: [Vecsmall([2, 1])] .group: [Vecsmall([1, 2]), Vecsmall([2, 1])] .mod: 1924481769277537925474295096745532701170466590649506396700122170162248 74137973943 .orders: Vecsmall([2]) .p: 7 .pol: x^2 - 680564733841876926926749214863536422912 .roots: [8115106970904773215875220506543554430286346080245400415743406046580 3070437569694, 1112971072187060603886773046091177258141831982624966355125781 56550421803700404249]~ ELL .a1: 1 .a2: 2 .a3: 3 .a4: 4 .a6: 5 .b2: 9 .b4: 11 .b6: 29 .b8: 35 .c4: -183 .c6: -3429 .area: 2.9719152678179096707716479509361896060 .disc: -10351 .eta: [3.1096482423243803285501491221965830079, 1.55482412116219016427507456 10982915039 + 1.0643747452102737569438859937299427442*I] .gen: [[1, 2]] .j: 6128487/10351 .omega: [2.7807400137667297710631976271813584994, 1.390370006883364885531598 8135906792497 - 1.0687497763561930661592635474375038788*I] .roots: [-1.6189099322673713423780009396072169751, -0.3155450338663143288109 9953019639151248 + 2.0925470969119586079816894466366945829*I, -0.31554503386 631432881099953019639151248 - 2.0925470969119586079816894466366945829*I, 4.1 850941938239172159633788932733891659*I, -1.303364898401057013567001409410825 4626 + 2.0925470969119586079816894466366945829*I, -1.30336489840105701356700 14094108254626 - 2.0925470969119586079816894466366945829*I]~ ELLFp .a1: Mod(1, 13) .a2: Mod(2, 13) .a3: Mod(3, 13) .a4: Mod(4, 13) .a6: Mod(5, 13) .b2: Mod(9, 13) .b4: Mod(11, 13) .b6: Mod(3, 13) .b8: Mod(9, 13) .c4: Mod(12, 13) .c6: Mod(3, 13) .cyc: [13] .disc: Mod(10, 13) .gen: [[Mod(6, 13), Mod(12, 13)]] .group: [13, [13], [[Mod(6, 13), Mod(12, 13)]]] .j: Mod(9, 13) .no: 13 .p: 13 ELLFq .a1: 1 .a2: 2 .a3: 3 .a4: 4 .a6: 5 .b2: 9 .b4: 11 .b6: 3 .b8: 9 .c4: 12 .c6: 3 .cyc: [195] .disc: 10 .gen: [[9*x + 8, 0]] .group: [195, [195], [[9*x + 8, 0]]] .j: 9 .no: 195 .p: 13 ELLQp .a1: 1 .a2: 2 .a3: 3 .a4: 4 .a6: 5 .b2: 9 .b4: 11 .b6: 29 .b8: 35 .c4: -183 .c6: -3429 .disc: -10351 .group: [12, [12], [[10, 4]]] .j: 6128487/10351 .p: 11 .roots: [9 + O(11^2)]~ .tate: [6 + 8*11 + 5*11^2 + 8*11^4 + O(11^5), Mod(x, x^2 + (5 + 2*11 + 5*11^ 2 + 10*11^3 + 2*11^4 + O(11^5))), 3*11 + 7*11^2 + O(11^5), [6 + 3*11 + O(11^ 5), 6 + 11 + 9*11^2 + 11^3 + 2*11^4 + O(11^5)], 1, [[39, 134943, 48065, 1359 11], [31719, 92956, 62706, 135911], [2*11 + 2*11^2 + 9*11^3 + 8*11^4 + O(11^ 5), 6*11^2 + 9*11^3 + 2*11^4 + O(11^5), 10*11^4 + O(11^5)], 0]] FFELT .f: 3 .gen: x .mod: x^3 + x^2 + 1 .p: 2 .pol: x .f: 3 .gen: x .mod: x^3 + 2*x + 2 .p: 3 .pol: x .f: 2 .gen: x .mod: x^2 + x + 1 .p: 18446744073709551629 .pol: x INTMOD .mod: 3 POLMOD .mod: x^2 + 1 .pol: x QFB .disc: -8 QUAD .disc: -4 .fu: [] .mod: w^2 + 1 .pol: w .tu: [4, w] .zk: [1, w] PRID .e: 1 .f: 1 .gen: [2, [-1, 1]~] .p: 2 PADIC .mod: 9 .p: 3 MODPR .e: 1 .f: 1 .gen: [2, [-1, 1]~] .p: 2 BID .bid: [[[4, 1; 0, 1], [0, 0]], [2, [2], [3]], [Mat([[2, [-1, 1]~, 1, 1, [0, 276; 1, -1]], 2]), Mat([[2, [-1, 1]~, 1, 1, [0, 276; 1, -1]], 2])], [[[[2], [3], [4, 1; 0, 1], [[[0, -1]~, [1, 1], [2, [-1, 1]~, 1, 1, [0, 276; 1, -1]]] ~, 1, [1, matrix(0,2)]], [1, 1, [[[2], [3], Mat([1, -1]), 2]]], [[0]~, Mat(1 )]]], [[], Vecsmall([])]], [Mat(1)]] .clgp: [2, [2], [3]] .cyc: [2] .gen: [3] .mod: [[4, 1; 0, 1], [0, 0]] .no: 2 .zkst: [2, [2], [3]] BID (nogen) .bid: [[[4, 1; 0, 1], [0, 0]], [2, [2]], [Mat([[2, [-1, 1]~, 1, 1, [0, 276; 1, -1]], 2]), Mat([[2, [-1, 1]~, 1, 1, [0, 276; 1, -1]], 2])], [[[[2], [3], [4, 1; 0, 1], [[[0, -1]~, [1, 1], [2, [-1, 1]~, 1, 1, [0, 276; 1, -1]]]~, 1, [1, matrix(0,2)]], [1, 1, [[[2], [3], Mat([1, -1]), 2]]], [[0]~, Mat(1)]]], [[], Vecsmall([])]], [Mat(1)]] .clgp: [2, [2]] .cyc: [2] .mod: [[4, 1; 0, 1], [0, 0]] .no: 2 .zkst: [2, [2]] [1/3 0 0] [ 0 1/6 0] [ 0 0 1/6] MF .mod: t^2 + t + 1 .mod: Mod(1, t^2 + t + 1)*y^2 + Mod(-2*t, t^2 + t + 1) Total time spent: 73 pari-2.17.2/src/test/32/qfbsolve0000644000175000017500000002022414676526175014745 0ustar billbill[1, 1, 1]:1:[[1, 0]] [1, 1, 1]:3:[[-1, 2]] [1, 1, 1]:7:[[2, 1], [-3, 1]] [1, 1, 1]:13:[[3, 1], [-4, 1]] [1, 1, 1]:19:[[3, 2], [-5, 2]] [1, 1, 1]:21:[[-4, -1], [5, -1]] [1, 29, 271]:1:[[1, 0]] [1, 29, 271]:61:[[-14, 1], [-15, 1]] [1, 29, 271]:63:[[13, -1], [16, -1]] [1, 29, 271]:67:[[-12, 1], [-17, 1]] [1, 29, 271]:73:[[-11, 1], [-18, 1]] [1, 29, 271]:81:[[10, -1], [19, -1]] [1, 29, 271]:91:[[9, -1], [20, -1]] [1, 29, 271]:103:[[-8, 1], [-21, 1]] [1, 29, 271]:117:[[7, -1], [22, -1]] [1, 29, 271]:133:[[6, -1], [23, -1]] [1, 29, 271]:151:[[-5, 1], [-24, 1]] [1, 29, 271]:171:[[4, -1], [25, -1]] [1, 29, 271]:193:[[-3, 1], [-26, 1]] [1, 29, 271]:217:[[2, -1], [27, -1]] [1, 29, 271]:243:[[1, -1], [28, -1], [29, -2]] [1, 29, 271]:247:[[-31, 2], [27, -2]] [1, 29, 271]:259:[[-33, 2], [25, -2]] [1, 29, 271]:271:[[0, 1], [-29, 1]] [1, 29, 271]:279:[[-35, 2], [23, -2]] [1, 29, 271]:1:[1, 0] [1, 29, 271]:4:[2, 0] [1, 29, 271]:9:[3, 0] [1, 29, 271]:16:[4, 0] [1, 29, 271]:25:[5, 0] [1, 29, 271]:36:[6, 0] [1, 29, 271]:49:[7, 0] [1, 29, 271]:61:[-14, 1] [1, 29, 271]:63:[16, -1] [1, 29, 271]:64:[8, 0] [1, 29, 271]:67:[-12, 1] [1, 29, 271]:73:[-11, 1] [1, 29, 271]:81:[19, -1] [1, 29, 271]:91:[9, -1] [1, 29, 271]:100:[10, 0] [1, 29, 271]:103:[-8, 1] [1, 29, 271]:117:[22, -1] [1, 29, 271]:121:[11, 0] [1, 29, 271]:133:[6, -1] [1, 29, 271]:144:[12, 0] [1, 29, 271]:151:[-5, 1] [1, 29, 271]:169:[13, 0] [1, 29, 271]:171:[25, -1] [1, 29, 271]:193:[-3, 1] [1, 29, 271]:196:[14, 0] [1, 29, 271]:217:[2, -1] [1, 29, 271]:225:[15, 0] [1, 29, 271]:243:[28, -1] [1, 29, 271]:244:[-28, 2] [1, 29, 271]:247:[-31, 2] [1, 29, 271]:252:[32, -2] [1, 29, 271]:256:[16, 0] [1, 29, 271]:259:[-33, 2] [1, 29, 271]:268:[-24, 2] [1, 29, 271]:271:[0, 1] [1, 29, 271]:279:[-35, 2] [1, 29, 271]:289:[17, 0] [1, 29, 271]:292:[-22, 2] [1, 29, 271]:1:[[1, 0]] [1, 29, 271]:4:[[2, 0]] [1, 29, 271]:9:[[3, 0]] [1, 29, 271]:16:[[4, 0]] [1, 29, 271]:25:[[5, 0]] [1, 29, 271]:36:[[6, 0]] [1, 29, 271]:49:[[7, 0]] [1, 29, 271]:61:[[-15, 1], [-14, 1]] [1, 29, 271]:63:[[13, -1], [16, -1]] [1, 29, 271]:64:[[8, 0]] [1, 29, 271]:67:[[-17, 1], [-12, 1]] [1, 29, 271]:73:[[-18, 1], [-11, 1]] [1, 29, 271]:81:[[9, 0], [10, -1], [19, -1]] [1, 29, 271]:91:[[9, -1], [20, -1]] [1, 29, 271]:100:[[10, 0]] [1, 29, 271]:103:[[-21, 1], [-8, 1]] [1, 29, 271]:117:[[7, -1], [22, -1]] [1, 29, 271]:121:[[11, 0]] [1, 29, 271]:133:[[6, -1], [23, -1]] [1, 29, 271]:144:[[12, 0]] [1, 29, 271]:151:[[-24, 1], [-5, 1]] [1, 29, 271]:169:[[13, 0]] [1, 29, 271]:171:[[4, -1], [25, -1]] [1, 29, 271]:193:[[-26, 1], [-3, 1]] [1, 29, 271]:196:[[14, 0]] [1, 29, 271]:217:[[2, -1], [27, -1]] [1, 29, 271]:225:[[15, 0]] [1, 29, 271]:243:[[1, -1], [28, -1], [29, -2]] [1, 29, 271]:244:[[-30, 2], [-28, 2]] [1, 29, 271]:247:[[-31, 2], [27, -2]] [1, 29, 271]:252:[[26, -2], [32, -2]] [1, 29, 271]:256:[[16, 0]] [1, 29, 271]:259:[[-33, 2], [25, -2]] [1, 29, 271]:268:[[-34, 2], [-24, 2]] [1, 29, 271]:271:[[-29, 1], [0, 1]] [1, 29, 271]:279:[[-35, 2], [23, -2]] [1, 29, 271]:289:[[17, 0]] [1, 29, 271]:292:[[-36, 2], [-22, 2]] [2, 1, 3]:2:[[1, 0], [-1, 0]] [2, 1, 3]:3:[[0, 1]] [2, 1, 3]:4:[[1, -1]] [2, 1, 3]:6:[[-1, -1]] [2, 1, 3]:9:[[2, -1]] [2, 1, 3]:12:[[-1, 2]] [2, 1, 3]:13:[[2, 1]] [2, 1, 3]:16:[[-1, -2]] [2, 1, 3]:18:[[3, -1]] [2, 1, 3]:24:[[-3, -1], [-3, 2]] [2, 1, 3]:26:[[-1, 3]] [2, 1, 3]:29:[[-2, 3]] [3, 4, 5]:3:[[1, 0], [-1, 0]] [3, 4, 5]:4:[[1, -1]] [3, 4, 5]:5:[[0, 1]] [3, 4, 5]:9:[[2, -1]] [3, 4, 5]:12:[[-1, -1]] [3, 4, 5]:15:[[1, -2]] [3, 4, 5]:20:[[3, -1]] [3, 4, 5]:23:[[-3, 2]] [3, 4, 5]:25:[[-2, -1]] [3, 4, 5]:3:[1, 0] [3, 4, 5]:4:[1, -1] [3, 4, 5]:5:[0, 1] [3, 4, 5]:9:[2, -1] [3, 4, 5]:12:[-1, -1] [3, 4, 5]:15:[1, -2] [3, 4, 5]:16:[2, -2] [3, 4, 5]:20:[3, -1] [3, 4, 5]:23:[-3, 2] [3, 4, 5]:25:[-2, -1] [3, 4, 5]:27:[3, 0] [3, 4, 5]:3:[[-1, 0], [1, 0]] [3, 4, 5]:4:[[1, -1]] [3, 4, 5]:5:[[0, 1]] [3, 4, 5]:9:[[2, -1]] [3, 4, 5]:12:[[-2, 0], [-1, -1], [2, 0]] [3, 4, 5]:15:[[1, -2]] [3, 4, 5]:16:[[2, -2]] [3, 4, 5]:20:[[0, 2], [3, -1]] [3, 4, 5]:23:[[-3, 2]] [3, 4, 5]:25:[[-2, -1]] [3, 4, 5]:27:[[-3, 0], [3, 0]] [5, 1, -9]:-29:[[-401, -322], [1, 2]] [5, 1, -9]:-27:[[-198, 137], [-23, 16]] [5, 1, -9]:-25:[[-11, -9], [56, 45]] [5, 1, -9]:-15:[[-61, -49], [-6, -5], [7, -5], [357, -247]] [5, 1, -9]:-13:[[-529, 366], [4, -3]] [5, 1, -9]:-11:[[-185, 128], [10, -7]] [5, 1, -9]:-9:[[0, 1], [335, 269]] [5, 1, -9]:-5:[[-1, 1], [604, 485]] [5, 1, -9]:-3:[[-66, -53], [1, 1]] [5, 1, -9]:-1:[[-13, 9]] [5, 1, -9]:1:[[-5, -4]] [5, 1, -9]:3:[[-3, 2], [172, -119]] [5, 1, -9]:5:[[-269, -216], [1, 0]] [5, 1, -9]:9:[[-873, 604], [2, -1]] [5, 1, -9]:11:[[4, 3], [71, 57]] [5, 1, -9]:13:[[-203, -163], [-2, -1]] [5, 1, -9]:15:[[-159, 110], [-3, -2], [16, -11], [137, 110]] [5, 1, -9]:25:[[-146, 101], [-29, 20]] [5, 1, -9]:27:[[9, 7], [76, 61]] [5, 1, -9]:29:[[-1045, 723], [5, -3]] [5, 16, 7]:-29:[[-6, 11]] [5, 16, 7]:-28:[[-7, 3], [-5, 9], [7, -13], [125, -239]] [5, 16, 7]:-25:[[-4, 7], [8, -15]] [5, 16, 7]:-23:[[3, -2], [45, -86]] [5, 16, 7]:-20:[[-3, 5], [9, -17], [13, -5], [99, -37]] [5, 16, 7]:-13:[[-10, 19], [-2, 3]] [5, 16, 7]:-7:[[-5, 2], [91, -34]] [5, 16, 7]:-5:[[-34, 65], [2, -1]] [5, 16, 7]:-4:[[1, -1], [11, -21]] [5, 16, 7]:-1:[[8, -3]] [5, 16, 7]:1:[[-1, 2]] [5, 16, 7]:4:[[-57, 109], [-3, 1]] [5, 16, 7]:5:[[-23, 44], [1, 0]] [5, 16, 7]:7:[[0, -1], [12, -23]] [5, 16, 7]:13:[[-11, 4], [75, -28]] [5, 16, 7]:20:[[1, -3], [13, -25], [19, -7], [67, -25]] [5, 16, 7]:23:[[4, -1], [80, -153]] [5, 16, 7]:25:[[27, -10], [59, -22]] [5, 16, 7]:28:[[-35, 67], [1, 1], [35, -13], [51, -19]] [5, 16, 7]:29:[[43, -16]] [5, 16, 7]:-29:[-6, 11] [5, 16, 7]:-28:[-5, 9] [5, 16, 7]:-25:[8, -15] [5, 16, 7]:-23:[45, -86] [5, 16, 7]:-20:[-3, 5] [5, 16, 7]:-16:[2, -2] [5, 16, 7]:-13:[-10, 19] [5, 16, 7]:-9:[24, -9] [5, 16, 7]:-7:[-5, 2] [5, 16, 7]:-5:[-34, 65] [5, 16, 7]:-4:[1, -1] [5, 16, 7]:-1:[8, -3] [5, 16, 7]:1:[-1, 2] [5, 16, 7]:4:[-57, 109] [5, 16, 7]:5:[1, 0] [5, 16, 7]:7:[12, -23] [5, 16, 7]:9:[-3, 6] [5, 16, 7]:13:[-11, 4] [5, 16, 7]:16:[-114, 218] [5, 16, 7]:20:[67, -25] [5, 16, 7]:23:[4, -1] [5, 16, 7]:25:[27, -10] [5, 16, 7]:28:[51, -19] [5, 16, 7]:29:[43, -16] [5, 16, 7]:-29:[[-6, 11]] [5, 16, 7]:-28:[[-10, 4], [-7, 3], [-5, 9], [7, -13], [125, -239], [182, -68 ]] [5, 16, 7]:-25:[[-4, 7], [8, -15], [40, -15]] [5, 16, 7]:-23:[[3, -2], [45, -86]] [5, 16, 7]:-20:[[-68, 130], [-3, 5], [4, -2], [9, -17], [13, -5], [99, -37]] [5, 16, 7]:-16:[[2, -2], [22, -42], [32, -12]] [5, 16, 7]:-13:[[-10, 19], [-2, 3]] [5, 16, 7]:-9:[[24, -9]] [5, 16, 7]:-7:[[-5, 2], [91, -34]] [5, 16, 7]:-5:[[-34, 65], [2, -1]] [5, 16, 7]:-4:[[1, -1], [11, -21], [16, -6]] [5, 16, 7]:-1:[[8, -3]] [5, 16, 7]:1:[[-1, 2]] [5, 16, 7]:4:[[-57, 109], [-3, 1], [-2, 4]] [5, 16, 7]:5:[[-23, 44], [1, 0]] [5, 16, 7]:7:[[0, -1], [12, -23]] [5, 16, 7]:9:[[-3, 6]] [5, 16, 7]:13:[[-11, 4], [75, -28]] [5, 16, 7]:16:[[-114, 218], [-6, 2], [-4, 8]] [5, 16, 7]:20:[[-46, 88], [1, -3], [2, 0], [13, -25], [19, -7], [67, -25]] [5, 16, 7]:23:[[4, -1], [80, -153]] [5, 16, 7]:25:[[-5, 10], [27, -10], [59, -22]] [5, 16, 7]:28:[[-35, 67], [0, -2], [1, 1], [24, -46], [35, -13], [51, -19]] [5, 16, 7]:29:[[43, -16]] [-16382350221535464479, 8479443857936402504] [[-18446744073709551616, -1], [-16382350221535464479, 8479443857936402504], [16382350221535464479, 8479443857936402504], [18446744073709551616, -1]] [-16382350221535464479, 8479443857936402504] [[-18446744073709551616, -1], [-16382350221535464479, 8479443857936402504], [16382350221535464479, 8479443857936402504], [18446744073709551616, -1]] [] [[-4, -1], [4, -1]] [8, 7] [] [20, 6] [10547339, 694995] [3, [0, 2]] [7, [5, 1]] [13, [7, 1]] [19, [8, 2]] [31, [11, 1]] [37, [11, 3]] [43, [13, 1]] [61, [14, 4]] [67, [16, 2]] [73, [17, 1]] [79, [17, 3]] [97, [19, 3]] [1009, [0, 1]] [1013, [2, 1]] [1109, [10, 1]] [1153, [12, 1]] [1409, [20, 1]] [1493, [22, 1]] [2609, [40, 1]] [3313, [48, 1]] [4157, [11, 2]] [4261, [15, 2]] [4373, [58, 1]] [4397, [19, 2]] [4877, [29, 2]] [5261, [35, 2]] [5557, [39, 2]] [5717, [41, 2]] [6637, [51, 2]] [7517, [59, 2]] [7757, [61, 2]] [8753, [88, 1]] [9109, [90, 1]] [9181, [10, 3]] [9277, [14, 3]] [9337, [16, 3]] [9473, [92, 1]] [9661, [75, 2]] [] [] *** at top-level: qfbsolve(Qfb(1,0,1),1,4) *** ^------------------------ *** qfbsolve: invalid flag in qfbsolve. Total time spent: 1319 pari-2.17.2/src/test/32/lindep0000644000175000017500000000162114567450071014365 0ustar billbill[-1, -1, 1]~ [1, -2]~ [1, -2, 1]~ [y, y, -1, -y^2]~ [1]~ x^2 + (-y^3 - y^2 - 5*y - 1) 0 (y - 1)*x + 1 x + (-5*y - 1) y*x + y^2 (27*T - 4)*x^3 + 3*x + 1 [(27*T^2 - 4*T)*x^2 + (54*T - 2)*x + 6, 0] [x - 2*T, -2*T^3 + 2*T] []~ [1]~ []~ []~ 1 *** at top-level: algdep(1,-1) *** ^------------ *** algdep: domain error in algdep: degree < 0 x^2 - 2 1 x^2 + 191025*x - 121287375 [Mod(0, E^3), Mod(0, E^3), Mod(0, E^3)]~ [-1, -1, 1]~ [-1, -1, 1]~ []~ *** at top-level: lindep([[1,0,0]~,[0,1,0],[1,1,0]]) *** ^---------------------------------- *** lindep: incorrect type in lindep (t_VEC). [-1, -1, 1]~ Mod(-2*t^3 - 2*t^2 - 1, t^4 + t^3 + t^2 + t + 1) Mod(t, t^4 + t^3 + t^2 + t + 1)*x + Mod(2*t^3 + 2*t^2 + 1, t^4 + t^3 + t^2 + t + 1) [Mod(t^2 + 2, t^4 + t^3 + t^2 + t + 1)] Mod(-x + 1, x^2 - 2) Mod(-2*x + 1, 4*x^2 - 2) Mod(3*x + 1, x^3 - 2) "t_FRAC" Total time spent: 2 pari-2.17.2/src/test/32/nfsign0000644000175000017500000000000014567450071014364 0ustar billbillpari-2.17.2/src/test/32/variable0000644000175000017500000000056114567450071014701 0ustar billbill0 3 x x y y y z 0 y [x, y, z] [y, x, y, z, y] [y, x, y, z, y] [y, y, x, y, z, y] [y, y, x, y, z, y] [y, y, x, y, z, y, y] [y, y, x, y, z, y, y, tt] *** at top-level: varhigher("zzz",y);1/0 *** ^-- *** _/_: impossible inverse in gdiv: 0. [y, y, x, y, z, y, y, tt] [y, x, y, z, y] [y, y, x, y, z, y, y, tt] Total time spent: 0 pari-2.17.2/src/test/32/subcyclo0000644000175000017500000001176114676526175014755 0ustar billbillx - 1 [x^2 + 2, x^2 + 262, x^2 - 262, x^2 - 2, x^2 - 131, x^2 + 1, x^2 + x + 33] [] [x^4 - x^3 - 4*x^2 + 4*x + 1, x^4 - x^3 + 2*x^2 + x + 1, x^4 + x^3 + x^2 + x + 1] [x^4 + 4*x^2 + 2, x^4 + 1, x^4 - 4*x^2 + 2] [x^4 + x^3 - 1649*x^2 - 16046*x - 13868, x^4 + x^3 + 1599*x^2 + 4805*x + 925 33, x^4 + x^3 - 1649*x^2 - 9637*x + 396308, x^4 - x^3 + 120*x^2 - 368*x + 83 5, x^4 + x^3 - 2403*x^2 - 3605*x + 158798, x^4 + x^3 + 1541*x^2 + 11185*x + 474811, x^4 + x^3 - 2403*x^2 - 61286*x - 418012, x^4 - x^3 + 62*x^2 - 832*x + 7447, x^4 - x^3 - 141*x^2 + 966*x - 1804, x^4 - x^3 + 91*x^2 - 281*x + 545 , x^4 - x^3 - 141*x^2 + 589*x - 296, x^4 + x^3 + 4*x^2 + 20*x + 23, x^4 + x^ 3 - 2403*x^2 - 29241*x + 30618, x^4 + x^3 + 1541*x^2 - 1633*x + 679899, x^4 + x^3 - 2403*x^2 + 41258*x - 110380, x^4 - x^3 + 62*x^2 + 154*x + 8433, x^4 - x^3 + 93*x^2 + 95*x + 731, x^4 + x^3 + 2*x^2 - 4*x + 3, x^4 + x^3 + 1575*x ^2 + 4793*x + 592621, x^4 - x^3 + 28*x^2 - 152*x + 1667, x^4 + x^3 + 1601*x^ 2 - 1603*x + 198279, x^4 - x^3 + 54*x^2 + 56*x + 263, x^4 + x^3 + 1575*x^2 - 8025*x + 310625, x^4 - x^3 + 28*x^2 + 290*x + 1225, x^4 - x^3 - 125*x^2 + x + 3452, x^4 - x^3 - 57*x^2 + x + 664, x^4 + x^3 - 1604*x^2 - x + 602447, x^ 4 + x^3 - 6*x^2 - x + 1, x^4 - x^3 - 52*x^2 - 21*x + 441, x^4 + x^3 - 864*x^ 2 + 369*x + 136161, x^4 + x^3 - 832*x^2 + 385*x + 148225, x^4 + x^3 - 136*x^ 2 + 733*x - 1067, x^4 + x^3 - 850*x^2 + 376*x + 141376, x^4 - x^3 - 67*x^2 - 28*x + 784, x^4 - x^3 - 31*x^2 - 12*x + 144] [] [x^4 + 10*x^2 + 5, x^4 - 30*x^2 + 45] [x^4 - 30*x^2 + 45] [x^4 + 10*x^2 + 5] [x^4 - 4*x^2 + 2, x^4 + 4*x^2 + 2] [x^4 - 4*x^2 + 2] [x^4 + 4*x^2 + 2] [] [x^4 + 26*x^2 + 117, x^4 - 34*x^2 + 17, x^4 + 58*x^2 + 725, x^4 + 442*x^2 + 33813, x^4 - 442*x^2 + 2873, x^4 + 442*x^2 + 26741, x^4 + 442*x^2 + 5525, x^ 4 + 754*x^2 + 98397, x^4 + 754*x^2 + 122525, x^4 - 754*x^2 + 136097, x^4 - 7 54*x^2 + 45617, x^4 - 986*x^2 + 14297, x^4 + 986*x^2 + 209525, x^4 + 986*x^2 + 83317, x^4 + 986*x^2 + 4437, x^4 + 12818*x^2 + 28436733, x^4 - 12818*x^2 + 2416193, x^4 + 12818*x^2 + 35409725, x^4 + 12818*x^2 + 22489181, x^4 + 128 18*x^2 + 4646525, x^4 - 12818*x^2 + 39332033, x^4 - 12818*x^2 + 13183313, x^ 4 + 12818*x^2 + 14080573, x^4 + 12818*x^2 + 749853, x^4 - 12818*x^2 + 360506 25, x^4 - 12818*x^2 + 18002881, x^4 - 12818*x^2 + 7851025, x^4 - 12818*x^2 + 57681] [x^4 - 34*x^2 + 17, x^4 - 442*x^2 + 2873, x^4 - 754*x^2 + 136097, x^4 - 754* x^2 + 45617, x^4 - 986*x^2 + 14297, x^4 - 12818*x^2 + 2416193, x^4 - 12818*x ^2 + 39332033, x^4 - 12818*x^2 + 13183313, x^4 - 12818*x^2 + 36050625, x^4 - 12818*x^2 + 18002881, x^4 - 12818*x^2 + 7851025, x^4 - 12818*x^2 + 57681] [x^4 - 12818*x^2 + 2416193, x^4 - 12818*x^2 + 39332033, x^4 - 12818*x^2 + 13 183313, x^4 - 12818*x^2 + 36050625, x^4 - 12818*x^2 + 18002881, x^4 - 12818* x^2 + 7851025, x^4 - 12818*x^2 + 57681] [x^4 + 26*x^2 + 117, x^4 + 58*x^2 + 725, x^4 + 442*x^2 + 33813, x^4 + 442*x^ 2 + 26741, x^4 + 442*x^2 + 5525, x^4 + 754*x^2 + 98397, x^4 + 754*x^2 + 1225 25, x^4 + 986*x^2 + 209525, x^4 + 986*x^2 + 83317, x^4 + 986*x^2 + 4437, x^4 + 12818*x^2 + 28436733, x^4 + 12818*x^2 + 35409725, x^4 + 12818*x^2 + 22489 181, x^4 + 12818*x^2 + 4646525, x^4 + 12818*x^2 + 14080573, x^4 + 12818*x^2 + 749853] [x^4 + 12818*x^2 + 28436733, x^4 + 12818*x^2 + 35409725, x^4 + 12818*x^2 + 2 2489181, x^4 + 12818*x^2 + 4646525, x^4 + 12818*x^2 + 14080573, x^4 + 12818* x^2 + 749853] [x^4 - 15*x^2 + 1, x^4 - 21*x^2 + 16, x^4 - 253*x^2 + 14400, x^4 - 23*x^2 + 9, x^4 - 197*x^2 + 8100, x^4 - 125*x^2 + 2304, x^4 - 299*x^2 + 1521] [x^4 - 15*x^2 + 1, x^4 - 21*x^2 + 16, x^4 - 253*x^2 + 14400, x^4 - 23*x^2 + 9, x^4 - 197*x^2 + 8100, x^4 - 125*x^2 + 2304, x^4 - 299*x^2 + 1521] [] [x^4 - 253*x^2 + 14400, x^4 - 197*x^2 + 8100, x^4 - 125*x^2 + 2304, x^4 - 29 9*x^2 + 1521] [x^5 - x^4 - 40000000000000008*x^3 + 4799349848000001007863468*x^2 - 2070949 39362953948289937266220320*x + 3043548546332103529870070921741607052224] [x^5 - x^4 - 40000000000000008*x^3 + 4799349848000001007863468*x^2 - 2070949 39362953948289937266220320*x + 3043548546332103529870070921741607052224] [x^7 - 2100000000000000063*x^5 - 1067899720300000032036991609*x^4 + 23387243 4985670618916173049570118357*x^3 + 22974228953591083407845565187732481558560 8974*x^2 + 41913357289128469461227435971800114114801518938382040*x + 2307579 385519802951463152376638877452496951831343729562714825] [x^11 - 550010395*x^9 + 1038529627839*x^8 + 73390662577307328*x^7 - 26654747 9690774529918*x^6 - 2640411932144211435109207*x^5 + 114562053785414038707968 40423*x^4 + 25961803091675008629250232835529*x^3 - 1375905234079359459940218 86568694725*x^2 + 32742529445468781606472553119898154375*x + 186713923538732 662200104881973476687265625] [x^13 - 7811934*x^11 + 264303767*x^10 + 19195179559374*x^9 - 256775418833493 3*x^8 - 18350853359895498637*x^7 + 4599217908449496166848*x^6 + 617209842581 6501137236186*x^5 - 2203548672671159816192981375*x^4 - 551902632993161959396 204094076*x^3 + 310661530444569613362601943860803*x^2 - 33085094534137468619 672490102581262*x + 108074525352446303737418732869819611] Total time spent: 140 pari-2.17.2/src/test/32/bit0000644000175000017500000001675214567450071013703 0ustar billbill4 3 2 3 100 *** at top-level: hammingweight(I) *** ^---------------- *** hammingweight: incorrect type in hammingweight (t_COMPLEX). [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0] #bitand [0, 0, 0] [0, 3, 0] [0, -3, 0] [0, 36893488147419103231, 0] [0, 340282366920938463481821351505477763073, 0] [0, -340282366920938463481821351505477763073, 0] [0, I, error("forbidden bitwise and t_INT , t_COMPLEX.")] [3, 3, 3] [3, -3, 1] [3, 36893488147419103231, 3] [3, 340282366920938463481821351505477763073, 1] [3, -340282366920938463481821351505477763073, 3] [3, I, error("forbidden bitwise and t_INT , t_COMPLEX.")] [-3, -3, -3] [-3, 36893488147419103231, 36893488147419103229] [-3, 340282366920938463481821351505477763073, 340282366920938463481821351505 477763073] [-3, -340282366920938463481821351505477763073, -3402823669209384634818213515 05477763075] [-3, I, error("forbidden bitwise and t_INT , t_COMPLEX.")] [36893488147419103231, 36893488147419103231, 36893488147419103231] [36893488147419103231, 340282366920938463481821351505477763073, 184467440737 09551617] [36893488147419103231, -340282366920938463481821351505477763073, 18446744073 709551615] [36893488147419103231, I, error("forbidden bitwise and t_INT , t_COMPLEX.")] [340282366920938463481821351505477763073, 3402823669209384634818213515054777 63073, 340282366920938463481821351505477763073] [340282366920938463481821351505477763073, -340282366920938463481821351505477 763073, 1] [340282366920938463481821351505477763073, I, error("forbidden bitwise and t_ INT , t_COMPLEX.")] [-340282366920938463481821351505477763073, -34028236692093846348182135150547 7763073, -340282366920938463481821351505477763073] [-340282366920938463481821351505477763073, I, error("forbidden bitwise and t _INT , t_COMPLEX.")] [I, I, error("forbidden bitwise and t_COMPLEX , t_COMPLEX.")] #bitnegimply [0, 0, 0] [0, 3, 0] [0, -3, 0] [0, 36893488147419103231, 0] [0, 340282366920938463481821351505477763073, 0] [0, -340282366920938463481821351505477763073, 0] [0, I, error("forbidden bitwise negated imply t_INT , t_COMPLEX.")] [3, 3, 0] [3, -3, 2] [3, 36893488147419103231, 0] [3, 340282366920938463481821351505477763073, 2] [3, -340282366920938463481821351505477763073, 0] [3, I, error("forbidden bitwise negated imply t_INT , t_COMPLEX.")] [-3, -3, 0] [-3, 36893488147419103231, -36893488147419103232] [-3, 340282366920938463481821351505477763073, -34028236692093846348182135150 5477763076] [-3, -340282366920938463481821351505477763073, 34028236692093846348182135150 5477763072] [-3, I, error("forbidden bitwise negated imply t_INT , t_COMPLEX.")] [36893488147419103231, 36893488147419103231, 0] [36893488147419103231, 340282366920938463481821351505477763073, 184467440737 09551614] [36893488147419103231, -340282366920938463481821351505477763073, 18446744073 709551616] [36893488147419103231, I, error("forbidden bitwise negated imply t_INT , t_C OMPLEX.")] [340282366920938463481821351505477763073, 3402823669209384634818213515054777 63073, 0] [340282366920938463481821351505477763073, -340282366920938463481821351505477 763073, 340282366920938463481821351505477763072] [340282366920938463481821351505477763073, I, error("forbidden bitwise negate d imply t_INT , t_COMPLEX.")] [-340282366920938463481821351505477763073, -34028236692093846348182135150547 7763073, 0] [-340282366920938463481821351505477763073, I, error("forbidden bitwise negat ed imply t_INT , t_COMPLEX.")] [I, I, error("forbidden bitwise negated imply t_COMPLEX , t_COMPLEX.")] #bitor [0, 0, 0] [0, 3, 3] [0, -3, -3] [0, 36893488147419103231, 36893488147419103231] [0, 340282366920938463481821351505477763073, 3402823669209384634818213515054 77763073] [0, -340282366920938463481821351505477763073, -34028236692093846348182135150 5477763073] [0, I, error("forbidden bitwise or t_INT , t_COMPLEX.")] [3, 3, 3] [3, -3, -1] [3, 36893488147419103231, 36893488147419103231] [3, 340282366920938463481821351505477763073, 3402823669209384634818213515054 77763075] [3, -340282366920938463481821351505477763073, -34028236692093846348182135150 5477763073] [3, I, error("forbidden bitwise or t_INT , t_COMPLEX.")] [-3, -3, -3] [-3, 36893488147419103231, -1] [-3, 340282366920938463481821351505477763073, -3] [-3, -340282366920938463481821351505477763073, -1] [-3, I, error("forbidden bitwise or t_INT , t_COMPLEX.")] [36893488147419103231, 36893488147419103231, 36893488147419103231] [36893488147419103231, 340282366920938463481821351505477763073, 340282366920 938463500268095579187314687] [36893488147419103231, -340282366920938463481821351505477763073, -3402823669 20938463463374607431768211457] [36893488147419103231, I, error("forbidden bitwise or t_INT , t_COMPLEX.")] [340282366920938463481821351505477763073, 3402823669209384634818213515054777 63073, 340282366920938463481821351505477763073] [340282366920938463481821351505477763073, -340282366920938463481821351505477 763073, -1] [340282366920938463481821351505477763073, I, error("forbidden bitwise or t_I NT , t_COMPLEX.")] [-340282366920938463481821351505477763073, -34028236692093846348182135150547 7763073, -340282366920938463481821351505477763073] [-340282366920938463481821351505477763073, I, error("forbidden bitwise or t_ INT , t_COMPLEX.")] [I, I, error("forbidden bitwise or t_COMPLEX , t_COMPLEX.")] #bitxor [0, 0, 0] [0, 3, 3] [0, -3, -3] [0, 36893488147419103231, 36893488147419103231] [0, 340282366920938463481821351505477763073, 3402823669209384634818213515054 77763073] [0, -340282366920938463481821351505477763073, -34028236692093846348182135150 5477763073] [0, I, error("forbidden bitwise xor t_INT , t_COMPLEX.")] [3, 3, 0] [3, -3, -2] [3, 36893488147419103231, 36893488147419103228] [3, 340282366920938463481821351505477763073, 3402823669209384634818213515054 77763074] [3, -340282366920938463481821351505477763073, -34028236692093846348182135150 5477763076] [3, I, error("forbidden bitwise xor t_INT , t_COMPLEX.")] [-3, -3, 0] [-3, 36893488147419103231, -36893488147419103230] [-3, 340282366920938463481821351505477763073, -34028236692093846348182135150 5477763076] [-3, -340282366920938463481821351505477763073, 34028236692093846348182135150 5477763074] [-3, I, error("forbidden bitwise xor t_INT , t_COMPLEX.")] [36893488147419103231, 36893488147419103231, 0] [36893488147419103231, 340282366920938463481821351505477763073, 340282366920 938463481821351505477763070] [36893488147419103231, -340282366920938463481821351505477763073, -3402823669 20938463481821351505477763072] [36893488147419103231, I, error("forbidden bitwise xor t_INT , t_COMPLEX.")] [340282366920938463481821351505477763073, 3402823669209384634818213515054777 63073, 0] [340282366920938463481821351505477763073, -340282366920938463481821351505477 763073, -2] [340282366920938463481821351505477763073, I, error("forbidden bitwise xor t_ INT , t_COMPLEX.")] [-340282366920938463481821351505477763073, -34028236692093846348182135150547 7763073, 0] [-340282366920938463481821351505477763073, I, error("forbidden bitwise xor t _INT , t_COMPLEX.")] [I, I, error("forbidden bitwise xor t_COMPLEX , t_COMPLEX.")] #bitneg [0, 36893488147419103231, -1] [3, 36893488147419103228, -4] [-3, 2, 2] [36893488147419103231, 0, -36893488147419103232] [340282366920938463481821351505477763073, 18446744073709551614, -34028236692 0938463481821351505477763074] [-340282366920938463481821351505477763073, 18446744073709551616, 34028236692 0938463481821351505477763072] error("incorrect type in bitwise negation (t_COMPLEX).") 1 1 *** at top-level: bitneg(1,-2) *** ^------------ *** bitneg: domain error in bitwise negation: exponent < -1 340282366920938463463374607431768211454 Total time spent: 0 pari-2.17.2/src/test/32/multivar-mul0000644000175000017500000000002714567450071015547 0ustar billbillTotal time spent: 3744 pari-2.17.2/src/test/32/mathnf0000644000175000017500000001030314760137375014370 0ustar billbill echo = 1 ? mathnf([0,2]) [2] ? mathnf([0,2],1) [Mat(2), [1, 0; 0, 1]] ? mathnf([0,x]) [x] ? mathnf([0,x],1) [Mat(x), [1, 0; 0, 1]] ? mathnf([x;1]) [x] [1] ? mathnf([x;1],1) [[x; 1], Mat(1)] ? mathnf([x,x^2+1;x^3+x+1,x+2]*Mod(1,5)) [Mod(1, 5)*x^5 + Mod(2, 5)*x^3 + Mod(4, 5)*x + Mod(1, 5) Mod(4, 5)*x^4 + Mod (2, 5)*x^3 + Mod(4, 5)*x^2 + Mod(3, 5)*x] [Mod(0, 5) 1] ? v=[116085838,181081878,314252913,10346840]; ? [H,U]=mathnf(v,1);[v*U,norml2(U)] [[0, 0, 0, 1], 2833319] ? [H,U]=mathnf(v,5);[v*U,norml2(U)] [[0, 0, 0, 1], 765585180708864230567243002686057927228240493] ? M=[0,0,0,0,0,0,0,0,0,13;0,0,0,0,0,0,0,0,23,6;0,0,0,0,0,0,0,23,-4,-7;0,0,0,0,0,0,17,-3,5,-5;0,0,0,0,0,56,16,-16,-15,-17;0,0,0,0,57,24,-16,-25,2,-21;0,0,0,114,9,56,51,-52,25,-55;0,0,113,-31,-11,24,0,28,34,-16;0,50,3,2,16,-6,-2,7,-19,-21;118,43,51,23,37,-52,18,38,51,28];mathnf(M) [787850171872400 32189386376004 356588299060422 742392731867995 282253457851 430 665185047494955 664535243562463 744564809133574 113975061998590 52745901 3372200] [0 12 6 11 5 3 7 6 6 0] [0 0 3 1 2 1 1 0 0 0] [0 0 0 1 0 0 0 0 0 0] [0 0 0 0 1 0 0 0 0 0] [0 0 0 0 0 1 0 0 0 0] [0 0 0 0 0 0 1 0 0 0] [0 0 0 0 0 0 0 1 0 0] [0 0 0 0 0 0 0 0 1 0] [0 0 0 0 0 0 0 0 0 1] ? M=[16*x^9-224*x^8+1176*x^7-2744*x^6+2401*x^5,0,0,0,0,0,16*x^9-224*x^8+1176*x^7-2744*x^6+2401*x^5,0,0,0,0,0,16*x^9-224*x^8+1176*x^7-2744*x^6+2401*x^5,0,0,0,0,0;0,-32*x^9+560*x^8-3920*x^7+13720*x^6-24010*x^5+16807*x^4,0,0,0,0,0,-32*x^10+560*x^9-3920*x^8+13720*x^7-24010*x^6+16807*x^5,0,0,0,422576*x^9-5916064*x^8+31059336*x^7-72471784*x^6+63412811*x^5,0,-32*x^10+560*x^9-3920*x^8+13720*x^7-24010*x^6+16807*x^5,0,0,0,0;0,0,64*x^9-1344*x^8+11760*x^7-54880*x^6+144060*x^5-201684*x^4+117649*x^3,0,0,0,0,0,32*x^10-560*x^9+3920*x^8-13720*x^7+24010*x^6-16807*x^5,0,0,0,0,0,64*x^11-1344*x^10+11760*x^9-54880*x^8+144060*x^7-201684*x^6+117649*x^5,0,0,0;0,0,0,-128*x^9+3136*x^8-32928*x^7+192080*x^6-672280*x^5+1411788*x^4-1647086*x^3+823543*x^2,0,0,0,0,0,-32*x^10+560*x^9-3920*x^8+13720*x^7-24010*x^6+16807*x^5,0,0,0,0,0,-128*x^12+3136*x^11-32928*x^10+192080*x^9-672280*x^8+1411788*x^7-1647086*x^6+823543*x^5,0,0;0,0,0,0,256*x^9-7168*x^8+87808*x^7-614656*x^6+2689120*x^5-7529536*x^4+13176688*x^3-13176688*x^2+5764801*x,0,0,0,0,0,32*x^10-560*x^9+3920*x^8-13720*x^7+24010*x^6-16807*x^5,0,0,0,0,0,256*x^13-7168*x^12+87808*x^11-614656*x^10+2689120*x^9-7529536*x^8+13176688*x^7-13176688*x^6+5764801*x^5,0;0,0,0,0,0,-512*x^9+16128*x^8-225792*x^7+1843968*x^6-9680832*x^5+33882912*x^4-79060128*x^3+118590192*x^2-103766418*x+40353607,0,0,0,0,0,-512*x^10+8960*x^9-62720*x^8+219520*x^7-384160*x^6+268912*x^5,0,0,0,0,0,-512*x^14+16128*x^13-225792*x^12+1843968*x^11-9680832*x^10+33882912*x^9-79060128*x^8+118590192*x^7-103766418*x^6+40353607*x^5]; ? [H,U]=mathnf(M,1); ? M*U[,1..12]==0 1 ? M*U[,13..18]==H 1 ? mathnf([]) [;] ? mathnf([],1) [[;], [;]] ? mathnf([;]) [;] ? mathnf([;],1) [[;], [;]] ? mathnfmodid(matrix(0,2),[]) [;] ? mathnfmodid([0,7;-1,0;-1,-1],[6,2,2]) [2 1 1] [0 1 0] [0 0 1] ? mathnfmodid([;],[2]) [2] ? matsolvemod([;],[]~,[]~,1) [[]~, [;]] ? matsolvemod([;],[],[]~,1) *** at top-level: matsolvemod([;],[],[]~,1) *** ^------------------------- *** matsolvemod: incorrect type in matsolvemod (D) (t_VEC). ? matsolvemod([;],[]~,[],1) *** at top-level: matsolvemod([;],[]~,[],1) *** ^------------------------- *** matsolvemod: incorrect type in matsolvemod (Y) (t_VEC). ? matsolvemod([;],2,[1]~,1) 0 ? matsolvemod([;],[2]~,[1]~,1) 0 ? matsolvemod([;],[2]~,1,1) 0 ? matsolvemod([;],1,1,1) [[]~, [;]] ? matsolvemod([1,2;3,4],1,2,1) [[0, 0]~, [1, 0; 0, 1]] ? M=[2,1,1,0,0,-1,0,-1,1,0,-1,1,0,0,0,0;0,0,0,0,0,0,0,0,0,-2,0,0,-1,0,0,0;0,0,0,0,0,0,0,-1,-1,0,0,-1,0,0,0,0;0,0,0,0,0,0,0,0,0,0,0,-2,0,2,0,0;0,0,0,0,0,0,0,-1,1,0,0,-1,0,0,0,0;0,0,0,0,0,0,0,0,0,0,0,0,0,-2,0,0;0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0;2,0,0,1,1,1,0,2,2,0,2,0,2,2,3,2]; ? E=[0,0,0,0,0,0,0,2]~;B=[0,0,0,0,0,0,0,0]~; ? matsolvemod(M,B,E,0) [0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]~ ? matsolvemod([;],[2]~,[2,3]~,1) *** at top-level: matsolvemod([;],[2]~,[2,3]~,1) *** ^------------------------------ *** matsolvemod: inconsistent dimensions in matsolvemod [2]. ? print("Total time spent: ",gettime); Total time spent: 5 pari-2.17.2/src/test/kerntest.c0000644000175000017500000000430714702752210014741 0ustar billbill#include "pari.h" GEN gen_0, gen_1, gen_m1, gen_2, gen_m2; THREAD pari_sp avma; THREAD size_t memused = 0; ulong DEBUGLEVEL,DEBUGMEM = 0; const double LOG10_2 = 0.; const long lontyp[] = {0}; THREAD VOLATILE int PARI_SIGINT_block, PARI_SIGINT_pending; struct pari_mainstack * pari_mainstack; long *varpriority; void mt_sigint_block(void) { } void mt_sigint_unblock(void) { } void new_chunk_resize(size_t x) {(void)x;} void specinit(void) { long size = 100000L; pari_mainstack = malloc(sizeof(*pari_mainstack)); pari_mainstack->size = size; pari_mainstack->bot = (pari_sp)malloc(size); pari_mainstack->top = avma = pari_mainstack->bot + size; gen_0 = cgeti(2); affui(0, gen_0); gen_1 = utoipos(1); gen_m1= utoineg(1); gen_2 = utoipos(2); gen_m2= utoineg(2); } void sorstring(ulong x) { #ifdef LONG_IS_64BIT if (x>>32) printf("%08lx ", x>>32); printf("%08lx ", x & 0xFFFFFFFF); #else printf("%08lx ", x); #endif } void _voiri(GEN x) { long i, lx = lgefint(x); GEN y = int_MSW(x); printf("signe: %ld, ",signe(x)); for (i=2; i < lx; i++, y = int_precW(y)) sorstring(*y); printf("\n"); } void _voirr(GEN x) { long i, lx = lg(x); printf("signe: %ld, expo: %ld, ",signe(x),expo(x)); for (i=2; i < lx; i++) sorstring(x[i]); printf("\n"); } int main(void) { 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.17.2/src/test/dotest0000755000175000017500000000741114567450071014176 0ustar billbill#!/bin/sh trap exit 2 unset COLUMNS bitlen=$1; shift exe_suff=$1; shift testlist=$@ if (tail -n 1 $0 >/dev/null 2>&1); then tail='tail -n' else tail='tail -' fi if (head -n 1 $0 >/dev/null 2>&1); then head='head -n' else head='head -' fi if (printf %-22s foo >/dev/null 2>&1); then printf=OK else printf= fi wrln () { echo "$1"; echo "$1" >&3; } wr () { echo $n "$1$c"; echo $n "$1$c" >&3; } wrtab () { if test -n "$printf"; then printf %$1s "$2" printf %$1s "$2" >&3 else echo $n "$2 $c" echo $n "$2 $c" >&3 fi; } confdir=../config testdir=../src/test execdir=. case `$confdir/arch-osname` in *-cygwin*|*-mingw*|*-msys*) crlf=OK ;; *) crlf= ;; esac if test -f /bin/rm ; then RM=/bin/rm; else RM=rm ; fi (echo "hi there\c" ; echo " ") > echotmp if grep c echotmp >/dev/null 2>&1 ; then n=-n; c=; else n=; c='\c'; fi $RM -f echotmp . $confdir/version exec 3>> Bench-$VersionMajor.$VersionMinor.$patch dotestSUF=${dotestSUF:-"sta dyn"} for suf in $dotestSUF; do if test -s $execdir/gp-$suf$exe_suff; then SUF="$SUF $suf" datadir=`echo 'print(default(datadir))' | $RUNTEST $execdir/gp-$suf$exe_suff -q -f` fi done file_test=gp.out for suf in $SUF; do eval time$suf=0 files$suf=; done for testdata in $testlist; do O=$IFS;IFS=_;set $testdata;IFS=$O;testname=$1;testmul=$2 pkgs=`${head}1 $testdir/in/$testname | grep package: | cut -f2 -d:` skip="" for pkg in $pkgs; do if test ! -x "$datadir/$pkg"; then wrln "! Skipping $testname: optional package $pkg not installed." skip="true"; fi done if test "$skip" = "true"; then untested="$untested $testname" else file_in=$testdir/in/$testname file_out=$testdir/$bitlen/$testname if test ! -r $file_out; then file_out=$testdir/32/$testname; fi if test ! -r $file_out; then touch $file_out; fi if test ! -r $file_in; then wrln "Error! Missing file, can't test $testname" exit 1 fi testmul=${testmul:-1000} wrtab -27 "* Testing $testname " for suf in $SUF; do file_diff=$testname-$suf.dif gp=$execdir/gp-$suf$exe_suff (echo 'gettime();0;'; cat $file_in; \ echo 'print("Total time spent: ",gettime);') \ | $RUNTEST $gp -q --test $GPTESTOPT > $file_test 2>&1 if test -n "$crlf"; then # when building on windows, remove extra cr so diff's will match cat $file_test | tr -d '\r' | diff -c $file_out - > $file_diff else diff -c $file_out $file_test > $file_diff fi pat=`grep "^[-+!] " $file_diff | grep -v "Total time"` time=`${tail}1 $file_test | sed -n 's,.*Total time spent: \(.*\),\1,p'` if test -n "$time"; then eval t='$'time$suf if test -n "$exprbug"; then t=`expr $time \'\*\' $testmul / 1000 + $t` else t=`expr $time '*' $testmul / 1000 + $t` fi eval time$suf=$t fi pre= if test -z "$pat"; then wr "gp-$suf..TIME=" wrtab 8 "$time "; else eval BUG$suf=BUG eval files$suf=\"'$'files$suf $file_diff\" wrtab -21 "gp-$suf..BUG [${time:-0}]" fi done wrln fi done $RM -f $file_test BUG= for suf in $SUF; do B=`eval echo '$'BUG$suf`; BUG="$BUG$B" t=`eval echo '$'time$suf` if test -n "$B"; then B=' [BUG]'; fi wrln "+++$B Total bench for gp-$suf is $t" done if test -n "$untested"; then wrln "The following tests were skipped:$untested" fi if test -z "$BUG"; then exit 0; fi pwd=`pwd` wrln wrln "PROBLEMS WERE NOTED. The following files list them in diff format: " wrln "Directory: $pwd" 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" if test "$dump_dif" = 1; then cat $f; fi done fi done exit 1 pari-2.17.2/src/test/in/0000755000175000017500000000000014760315601013343 5ustar billbillpari-2.17.2/src/test/in/equal0000644000175000017500000000352314760137411014401 0ustar billbill[O(3)===O(3), 1+O(3)===2+O(3), 1+O(3)==O(3^-1), 1+O(3)==2+O(3)] [O(x)===O(y), 2+O(x)===1+O(x)] [1.===1., 1.===-1.] f(x)=1; g(x)=1; h()=1; my(y=1);e(x)=y; [e===f,e===e] [f===g, f===h] [3/2===-3/2, 3/2===3/2] m=Mod(1,2); [Mod(1,3)===m, m===Mod(0,2), m===m] m=Mod(1,x); [m===Mod(Pol(1),x), m===Mod(1,y), m===m] t=ffgen(8); [t===t+1, t===ffgen(4), t===t] q=Qfb(1,2,3); [q===Qfb(1,2,2), q===Qfb(1,3,3), q===Qfb(2,2,3), Qfb(1,0,-2)===Qfb(1,0,-2), q===q] Qfb(1,0,-2)==Qfb(1,0,-2) 1/x===1/y [[1,2,3]===[1,2], [1,2,3]===[1,2,4], [1,2,3]===[1,2,3.], [1,2]===[1,2]] quadgen(5)==quadgen(13) ["ab"==="ac", "ab"==="ab"] L=List([1,2]); [L===List([]), L===List([2,1]), L===List([1]), L===L] [[]==0, []~==0] oo===oo -oo===-oo oo===-oo [I===1+I, I===I] w=quadgen(5); [w===1+w, w===w] w==w quadgen(5)===quadgen(13) f()=1; g()=0; [f==g,f==f] [f===g,f===f] List()==List() List(1)==List() List()==List(1) List(1)==List(1) List(2)==List(1) L=List();listput(~L,1);listpop(~L);L==List() g=ffgen(2^3); h=ffgen(3^3); q=quadgen(5); v=[g,g^0,-g^0,h,h^0,-h^0,\ q,1+0*q,-1+0*q,\ O(x),x+O(x^2),1+O(x),-1+O(x),1+O(x^2),1+x+O(x^2),0./x+1+O(x^2),0./x+1+x+O(x^2),\ (x+0.)/x,(-x+0.)/x,(2*x+0.)/x,\ [], [1], []~, [1]~, [2]~, [1,1]~, [1,0]~,[-1,0]~,\ [;],Mat(1),Mat(2), matid(2), [1,0;0,2], [1,1;0,1], -matid(2)]; for (i=1,#v, print([v[i]==1,v[i]==-1])) A=Ser(vector(40000,i,i==1)); A==A Mod(14,20) == Mod(39,55) Mod(13,20) == Mod(39,55) Mod(1+x, x^2+x) == Mod(1-x, x^2-x) Mod(2+x, x^2+x) == Mod(1-x, x^2-x) Mod(Mod(y,y^2+1),x^2-2) == Mod(y,y^2+1) test(x)=[x==1, x==-1]; [test(O(29^-1)), test(O(29^0)), test(O(29))] test(Mod(0, 6*x^0)) test(x*O(7^-1)+Mod(1,a^0)) test(O(7^-4)*v0^-2+O(v0)) test(Mod(0,Pol([y+1]))) test(Q=O(13^-5)+O(v0)) test(7/12*v0^-2+O(v0^-1)) test(Mod(0,1)*v0+O(v0^2)) test(Ser([Mod(0,5)],v1)/v1*x^0) 1/Pol([1,Qfb(8,3,9)])==-1 \\ #2393 O(23^0)*v0/(6*v0+O(v1^-5))==1 Mod(0,1)*x^0==x^0 pari-2.17.2/src/test/in/valuation0000644000175000017500000000141214676526175015306 0ustar billbilla = [0, 1, 1/3, 1.0, Mod(1,2), Mod(1,3), ffgen(Mod(1,3)*(x^2+1)), 2*I, 3 + O(3^2), Mod(x,x^2+1), 2*x + 2, 3*(x +O(x^2)) ]; b = [2, 3, x, x^2+1 ]; { for (i = 1, #a, for(j = 1, #b, v = iferr(valuation(a[i],b[j]), E, "ERROR"); print1(v, " ") ); print() ) } valuation(0,1) valuation(0,-1) valuation(0,0) valuation(0,I) z=1+'x; valuation(Mod(z^2,z^3), z) valuation(y+O(y^2),x) \\ #1319 s=Mod(1,3)*(1+x); valuation((s+O(x^2)) - s,x) \\ #1336 1./(x+1)+O(x^2) \\ #1345 valuation(0*x,3) == oo 1+O(x)-1 poldegree(0) poldegree(Pol(Mod(0,3))) poldegree(0./x) valuation(x^2) valuation(x^2+O(x^3)) valuation(2^2+O(2^3)) \\ #2381 valuation(x*(y^2-1), y+1) valuation(y*(x^2-1), x+1) valuation(Pol(0), x) valuation(Pol(0), x^2) valuation(Pol(0), x+1) \\ ERRORS valuation(Pi) pari-2.17.2/src/test/in/ranges0000644000175000017500000000232014567450071014550 0ustar billbill[2^100..2^100+3] [x^2+1|x<-[1..40],isprime(x)] [x|x<-primes(40)] [x|x<-[1..40],isprime(x)] [x|x<-Vecsmall([1..40]),isprime(x)] [a^2+b^2|a<-[1..10];b<-[1..10],gcd(a,b)==1] [a^2+b^2|a<-[1..10],isprime(a);b<-[1..10],a!=b && isprime(b)] [[a,b,c]|a<-[1..5];b<-[1..a];c<-[1..b]] primes(100)[4..7] V=[1..5]; V[2..3] V[1..-2] V[-3..-1] V[^3] V[6..5] V[6..-1] V[1..0] V[0..-1] V[-1..-2] L=List(V); L[2..3] L[1..-2] L[-3..-1] L[^3] L[6..5] L[6..-1] L[1..0] L[0..-1] L[-1..-2] V=Vecsmall(V); V[2..3] V[1..-2] V[-3..-1] V[^3] M=matrix(5,5,i,j,i+5*j-5); M[2..3,2..3] M[1..2,1] M[1,1..4] M[1..3,] M[,1..3] M[1..5,1..-2] M[1..-2,1..-2] M[-3..-1,-3..-1] M[^3,2..3] M[^2,1] M[1,^4] M[^3,] M[,^3] M[^5,1..-2] M[1..-2,^-2] M[-3..-1,-3..-1] Mat()[1..0,1..0] f(v,c=0)=my(a,b=[1,2]);[a,b[c]]=v;[a,b]; f([1,2],1) f([3,4],2) g(v)= { my(a,[b,c]=v,d=v,e=0,f=I); [a,b,c,d,e,f]; } h(v)= { local(a,[b,c]=v,d=v,e=0,f=I); [a,b,c,d,e,f]; } g([3,4]) h([3,4]) [a,,,b]=[1..4];[a,b] my([,a,,b]=[1..4]);[a,b] local([a,,b,]=[1..4]);[a,b] \\ #1552 [x|x<-[];y<-[]] [x|x<-[1..5];y<-[1..x-1];z<-[1]] [x|x<-[1..5];y<-[1..x], ybnrmap(S,x), subgrouplist(bnr.cyc)) \\ ERRORS bnrmap(1,2) bnrmap(bnr, bnrinit(x,1)) bnrmap(S,[1,2,3]) bnrmap(S,[1,2]/2) bnrmap(S,[1,2,3]~) bnrmap(S,[1,2]~/2) bnrmap(S,matid(3)) bnrmap(S,matid(2)/2) pari-2.17.2/src/test/in/nflistQT0000644000175000017500000000105314567450071015037 0ustar billbilldefault(new_galois_format,1); tst(n,k)= { P = nflist([n,k],'t); V = List(); for(a=1,20, Q = subst(P,t,a); if (polisirreducible(Q), if (n > 11 || polgalois(Q)[3] == k, listput(~V,Q)))); if (!#V, error(k)); #V; } L=[1,1,2,5,5,16,7]; S = vector(#L,i,[1..L[i]]); for(n=1,#S,print1(n,": ");print([tst(n,k) | k<-S[n]])) nflist("S25",'t) nflist("A25",'t) nflist("A24",'t) nflist("A23",'t) nflist("A22",'t) nflist([47,6],'t) nflist([47,5],'t) nflist("C1",'t) nflist("C2",'t) nflist("C3",'t) \\ ERRORS nflist([4,6]) nflist([18,100000]) pari-2.17.2/src/test/in/factorint0000644000175000017500000000057514676526175015306 0ustar billbillfactorint(-33623546348886051018593728804851,1) factorint(691160558642,1) /* MPQS */ factorint(10^120+1,14) p = 10^7+19; q = 10^10+19; r = 10^11+3; factorint(p^2*q*r,14) factorint(p*q^2*r,14) factorint(p*q*r^2,14) factorint(p^3*r,14) factorint(p^4*r,14) factorint(p^5*r,14) n=10^15+3; factor(n,10^6) factor(n,10^8) \\ #2165 factor(78857659^4 * 59571877) \\ #2469 factor(2^2203-1) pari-2.17.2/src/test/in/programming0000644000175000017500000001013214676526175015625 0ustar billbill\\package:elldata /* GP; init_programming() */ foo()=1; global(GRAPH=0,W); plot(x=0,10,sin(Pi*cos(x))) if(GRAPH,print("ploth: ",ploth(x=0,20,besselj(1,x)))); plothexport("svg",x=0,20,[sin(2*x),cos(3*x)],1); plotinit(1); print("plotrecth: ",plotrecth(1,x=0,20,[sin(Pi*cos(2*x)),cos(3*x)],1)) plotexport("svg",1); if(GRAPH,print("psploth: ",psploth(x=0,20,[sin(cos(2*x)),cos(3*x)],1))) print("alarm: ",alarm(2^29,factor(91))) print1("forqfvec:");forqfvec(v,matid(4),,print1(" ",v));print(); print("matrix: ",matrix(2,3,i,j,[i,j])); print("vector: ",vector(3,i,i+1)); print("vectorsmall: ",vectorsmall(3,i,i+3)); print("vectorv: ",vectorv(3,i,i+2)); print("direuler: ",direuler(p=3,10,1/(1-kronecker(-4,p)*'X))); print1("for:"); for(i=1,3,print1(" ",i)); print(); print1("forcomposite:"); forcomposite(c=1,10,print1(" ",c)); print(); print1("fordiv:"); fordiv(30,d,print1(" ",d)); print(); print1("fordivfactored:"); fordivfactored(30,d,print1(" ",d)); print(); print1("foreach:"); foreach(primes([1,10]),v,print1(" ",v)); print(); print1("forell:"); forell(E,1,100,print1(" ",E[1]),1); print(); print("forfactored: unsupported"); print1("forpart:");forpart(p=5,print1(" ",p));print(); print1("forpart:");forpart(p=5,print1(" ",p),,3);print(); print1("forprime:"); forprime(p=2,10,print1(" ",p)); print(); print1("forprimestep:"); forprimestep(p=2,20,Mod(1,3),print1(" ",p)); print(); print("forsquarefree: unsupported"); print1("forstep:"); forstep(i=1,21,3,print1(" ",i)); print(); print1("forstep(vec):"); forstep(i=1,21,[2,4],print1(" ",i)); print(); print1("forsubgroup:"); forsubgroup(G=[5,5],,print1(" ",matsnf(G))); print(); print1("forsubset:");forsubset(5,p,print1(" ",p));print(); print1("forvec:"); forvec(v=[[1,3],[1,2]],print1(" ",v)); print(); print("iferr: ",iferr(zeta(1),E,E)) print1("parfor: ");W=vector(10);parfor(i=1,10,binomial(2*i,i),E,W[i]=E);print(W) print1("parforeach: ");W=vector(20);parforeach(primes([1,20]),i,binomial(2*i,i),E,W[i]=E);print(W); print1("parforprime: ");W=vector(20);parforprime(i=1,20,binomial(2*i,i),E,W[i]=E);print(W); print1("parforprimestep: ");W=vector(20);parforprimestep(i=1,20,Mod(1,3),binomial(2*i,i),E,W[i]=E);print(W); print1("parforstep: ");W=vector(100);parforstep(i=1,100,3,binomial(2*i,i),E,W[i]=E);print(W); print1("parforstep: ");W=vector(100);parforstep(i=1,100,Mod(1,3),binomial(2*i,i),E,W[i]=E);print(W); print1("parforstep: ");W=vector(100);parforstep(i=1,100,[4,-1],binomial(2*i,i),E,W[i]=E);print(W); print1("parforvec: ");W=vector(9);parforvec(v=[[0,2],[0,2]],fromdigits(v,3),E,W[E+1]=v);print(W); print1("parforvec: ");W=vector(9);parforvec(v=[[0,2],[0,2]],fromdigits(v,3),E,W[E+1]=v,1);print(W); print1("parforvec: ");W=vector(9);parforvec(v=[[0,2],[0,2]],fromdigits(v,3),E,W[E+1]=v,2);print(W); if(GRAPH,print("parploth:",parploth(x=1,2,1/gamma(x)))); if(GRAPH,print("parploth:",parploth(x=0,2*Pi,[cos(2*x),sin(3*x)],1))); parplothexport("svg",x=1,2,1/gamma(x)); parplothexport("svg",x=0,2*Pi,[cos(2*x),sin(3*x)],1); print("parsum:",parsum(i=1,3,i)); print("parvector: ",parvector(3,i,i+1)); print("derivnum: ",derivnum(x=3,1/(1+x^2))); print("intcirc: ",intcirc(x=0,2,zeta(x))); print1("intfuncinit: "); my(A=intfuncinit(x=[-oo,1],[+oo,1],exp(-x^2))); \ print(intnum(x=[-oo,1],[+oo,1],exp(-x),A)); print("intnum: ",intnum(x=0,1,1/(1+x^2))); print("intnumgauss: ",intnumgauss(x=0,1,1/(1+x^2))); print("intnumromb: ",intnumromb(x=0,1,1/(1+x^2))); print("prod: ",prod(i=1,10,i)); print("prodeuler: ",prodeuler(p=2,10,p)); print("prodinf: ",prodinf(n=1,1-2^-n)); print("solve: ",solve(x=1.6,4.6,tan(x)-x)) print("solvestep ",solvestep(X=0,10,1,sin(X^2))); print("solvestep ",solvestep(X=0,10,1,sin(X^2)),1); print("sum: ",sum(i=1,10,i)); print("sumalt: ",sumalt(n=1,(-1)^(n+1)*n^-2)); print("sumdiv: ",sumdiv(30,d,d)); print("sumdivmult: ",sumdivmult(30,d,eulerphi(d))); print("suminf: ",suminf(n=1,2^-n*moebius(n))) print("sumnum : ",sumnum(n=1,n^-2)) print("sumnumap : ",sumnumap(n=1,n^-2)) print("sumnumlagrange : ",sumnumlagrange(n=1,n^-2)) print("sumnummonien : ",sumnummonien(n=1,n^-2)) print("sumpos : ",sumpos(n=1,n^-2)) print("compr: ",[x^2+1|x<-primes(10)]); print("compr: ",[x^2+1|x<-[1..10], isprime(x)]); pari-2.17.2/src/test/in/prime0000644000175000017500000000145614760137411014411 0ustar billbilltest(N)= { default(primelimit, N); for (b=10, 20, print1(prime(2^b), " ")); for (b=10, 26, print1(primepi(2^b), " ")); } prime(41539) test(10^6); test(10^8); primepi(2^32) precprime(1) primepi(2750160) \\ #1855 primes(50) primes([-5,5]) primes([3/2, 11/2]) primes([10,20]) primes([2^32-100,2^32+100]) primes([2^64-100,2^64+100]) #primes([2^50,2^50+200000]) #primes([10^7, 10^7+10^6]) #primes([2^1023+5000, 2^1023+7000]) nextprime(2^32-1) nextprime(2^64-1) nextprime(2.5) precprime(2.5) \\ #2584 forprime(p=524288,1048576,1) forprime(p=1048607,1048617,1) \\ #2612 forprime(p=1099505335069-100000,1099505335069+10000,) \\ Errors, keep at end of file \\#1668 primes([1,Pol(2)]); nextprime(x) precprime(x) \\#2113 Cannot test: the test would not finish before end of universe. \\\p520 \\primepi(Pi*10^100) pari-2.17.2/src/test/in/aurifeuille0000644000175000017500000000057011636712103015573 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.17.2/src/test/in/ellsea0000644000175000017500000000567314676526175014566 0ustar billbilldefault(parisize,"12M"); \\ 10M overflows 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])); J= {[Mod(139969198258936384621998533779, 896615193897208487551655423041), Mod(153550450851144056623726364403,1160030981035862964864325445299), Mod(386229222639189135614980939195,529656639561667839197968630433), Mod(543979953519664739130128566041,817701636704151811034504702087), Mod(80210534001353032236065226821, 983440823277044783790077069059), Mod(1293115044598381293398949316, 383857664397975779060725841281), Mod(4476559808559052,72057594037929289)]; } for(i=1,#J, print(i,":",ellcard(ellinit([J[i]])))) g=ffgen(nextprime(2^32)^2);E=ellinit([g,3]);ellap(E) b=ffgen(37^18,'b);E=ellinit([b]);ellap(E) p=558585999018706642134255046066558322465303141603116942905122131373672993; P=x^2+120725427834944054196720244713485427580768840528013606312647904569445909*x+48793460342192244809295001967323568023224292191521342609807900353904368; E=ellinit([ffgen(P*Mod(1,p),'a)]); ellap(E) p = 1048845330395786101209709; E = ellinit([1,56], p); ellsea(E,1) ellsea(E,2) a=ffgen(ffinit(nextprime(2^30),3),'a); E = ellinit([1,a]); ellsea(E,1) ellsea(E,2) ellsea(ellinit([1,519],523)) p = nextprime(2^100); E = ellinit([1122988618244467583984567614936, 429172847969450664478514342664], p); ellsea(E, -1) E = ellinit([1213812743793711191989251498394, 677975617584150034841507871840], p); ellsea(E, 2) ellsea(E, -2) p=1048845330395786101209839; E = ellinit([1,15], p); F=ellinit([1,-15], p); ellsea(E, 1) ellsea(E, -1) ellsea(F, 1) ellsea(F, -1) ellsea(E, 7) ellsea(E, -7) ellsea(F, 7) ellsea(F, -7) pari-2.17.2/src/test/in/nfweilheight0000644000175000017500000000346114676526175015767 0ustar billbill\\check computed values against values computed with magma, and some integer values \\Height of roots of unity must be zero (Kronecker's theorem) f=polcyclo(23); K=nfinit(f); a=Mod(x, f); nfweilheight(K, vector(8,i,x^random(22))) < 1.E-30 \\computed value f = x^5 + 5*x^4 - 5*x^2 + 10*x - 9; K = nfinit(f); b = x/23 + 1; c = 13; d = 2*x^2 + x/5 + 1/3; e = 1/13; nfweilheight(K, [x, b, c, d, e])-11.2110562747564085637132907074 < 1.E-25 nfweilheight(K, [x, x, x, x]) < 1.E-28 \\ on coprime integers the height is equal to log(max(abs)), and is \\ independent of the field nfweilheight(K, [13, -101, 17, 2, 4, random(100)]) - log(101) < 1.E-28 \\another computed value f = x^9 - 2083331363; K2 = nfinit(f); b = x/23 +1; c = 13; d = 2*x^2+ x/5 + 1/3; e = 1/13; nfweilheight(K2, [x, b, c, d, e])-13.8699151920009083492877110288 < 1.E-25 \\same testing as before, but on a different field nfweilheight(K2, [x, x, x, x]) < 1.E-28 nfweilheight(K2, [13, -101, 17, 2, 4, random(100)]) - log(101) < 1.E-25 \\more computed values f=x^7 - 8*x - 305; K=nfinit(f); b = x+1; c = x^4 - 2/17; d = 2*x^2+ x/5 + 1/3; e = 0; nfweilheight(K, [x, b, c, d, e]) - 8.58009410222389340649418534729 < 1.E-25 f = x^7 + 7 * x^6 - 7* x^5 + 3* x^4 + 8*x^3 - 9* x^2 - 2*x - 5; K=nfinit(f); a=[1/75, -2/19, 1/17, 2/77, 1/26, 2/85, -1/72]~; b=[-3/71, -1/2, 1/18, -1/32, 1/5, 1/67, -1/77]~; c=[1/10, 1/9, -1/75, -1/51, -2/85, -1/69, 0]~; d=[1/86, -2/11, 1/92, 1/17, -1/69, -2/7, -1/10]~; nfweilheight(K, [a, b, c, d])-38.3423241063701442282800571406 < 1.E-25 \\more testing with integer entries nfweilheight(K, [-1009, 2, 4*random(100), random(1000), random(1000)]) - log(1009) < 1.E-28 nfweilheight(K, [1997, 2, 4*random(100), random(1000), random(1000)]) - log(1997) < 1.E-28 nfweilheight(K, [1009, 2, 4*random(100), random(1000), random(1000)]) - log(1009) < 1.E-28 pari-2.17.2/src/test/in/gammamellininv0000644000175000017500000000446514676526175016317 0ustar billbillf(t)=4*besselk(0,2*Pi*t); G = gammamellininvinit([0,0]); g(t)=gammamellininv(G,t); { for(a=1,30, for(b=-5,5, my(z = a/12+I*b/6, e = exponent(f(z)-g(z))); if(e > -101, warning(z,":",e)))) } GR(s)=Pi^-(s/2)*gamma(s/2); gmellininv(Vga)= { my(c = 1,A,B,T); localbitprec(getlocalbitprec()+64); my(f(s) = prod(i=1,#Vga,GR(s+Vga[i]))); A = [-oo,Pi/2]; B = [+oo,Pi/2]; T = intfuncinit(t=A,B, f(c + I*t)); z->my(a=-log(z));intnum(t=A,B, exp(a*I*t), T)*exp(a*c) / (2*Pi); } chk(Vga,f,t) = exponent(f(t)-gammamellininv(Vga,t)); L=[[0],[1],[1/2],[3/2],[0,0],[0,1/2],[0,1],[0,2],[0,3],[0,0,0],[0,0,1/2],[0,0,1],[0,1,1],[0,1,2],[0,1,3/2],[0,0,0,0,0]]; M=apply(gmellininv,L); S=[1/2,3/2,2,3,4, 1/2+I,3/2+I,2+I,3+I,4+I]; { for(i=1,#L, my(G = gammamellininvinit(L[i])); for(j=1,5, \\ gmellininv does not support complex z my(e = chk(G,M[i],S[j])); if(e > -121, warning([1,i,j],":",e)))); } chkd(v,w,t)=exponent(derivnum(s=t,gammamellininv(v,s))-gammamellininv(w,t)); { for(i=1,#L, my(v); if(1, localbitprec(320); v = gammamellininvinit(L[i])); my(w = gammamellininvinit(L[i], 1)); for(j=1,#S, if(j<=5 || denominator(L[i])==1, my(e = chkd(v,w,S[j])); if(e > -117, warning([2,i,j], ":", e))))); } { my(e = exponent(gammamellininv([0,1/2,1,3/2],5)-2^(3/2)*exp(-4*Pi*sqrt(5)))); if (e > -128, error("[0,1/2,1,3/2]:5",":",d)); } gammamellininv([0],121.) gammamellininv(1,0) G = gammamellininvinit([1], 2); a(z) = 4*Pi*z*exp(-Pi*z^2)*(2*Pi*z^2-3); f(z) = exponent(a(z) - gammamellininv(G,z)); f(I) f(2+I) chk(f)= my(a = f()); localbitprec(getlocalbitprec()+64); exponent(a - f()); chk(()->gammamellininv([0,10^-38],3/10)) chk(()->gammamellininv([0,1+10^-38],3/10)) chk(()->gammamellininv([1/2,1/2+10^-38],3/10)) chk(()->gammamellininv([0,1/2,1/2+10^-38,10^-38],3/10)) chk(()->gammamellininv([0,1/2,10^-38,10^-38],3/10)) gammamellininvasymp([0],10) gammamellininvasymp([0,1/2],10) gammamellininvasymp(1,10) gammamellininv(1,1) gammamellininv(gammamellininvinit(1),1) localprec(100); gammamellininvinit([1/3*I,-1/3*I]); \\#2283 localbitprec(220); gammamellininvinit(concat(vector(5,i,[0,1]))); gammamellininvinit(vector(9,i,1)); localbitprec(180);gammamellininvinit([-2,-2,-1,-1,0,0,1]); \\#2502 \\ERRORS gammamellininvasymp([]) gammamellininvinit([]) gammamellininvinit(x,-2) pari-2.17.2/src/test/in/rnf0000644000175000017500000001665014760123736014071 0ustar billbillnf=nfinit(y^2+1); rnfidealmul(rnfinit(nf,x^4-x-1),2,3) rnfidealmul(rnfinit(nf,[x^4-x-1,10^3]),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)) nf=nfinit(y^2-y-4);T=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; rnfpseudobasis(nf,T) rnfpseudobasis(nf,[T,10^3]) rnfpseudobasis(nf,[T, [3, 79, 269, 1361, 2789]]) T = x^2+1009^3*(10^6+3)^2*y; rnfpseudobasis(nf,T) rnfpseudobasis(nf,[T,100]) rnfpseudobasis(nf,[T,1010]) rnfpseudobasis(nf,[T, [idealprimedec(nf,2)[1], 1009]]) rnfdisc(nf,T) rnfdisc(nf,[T,100]) rnfdisc(nf,[T,1010]) rnfpseudobasis(nf,[T, [idealprimedec(nf,2)[1], 1009]]) rnfpseudobasis(nf,[T, [2, 1009]]) Q = bnfinit(y); T=x^4+x^3-71*x^2+72*x+5184; rnfconductor(Q,T) rnfconductor(Q,T,2) rnfconductor(Q,[T,10^3],2) rnfconductor(Q,[T, [2,3,7,41]],2) rnfconductor(Q,galoissubcyclo(117,116),2) K=bnfinit(quadpoly(1596,y),1); rnfbasis(K,rnfsteinitz(K,rnfpseudobasis(K,quadray(K,1)))); \\#2353 M=[[1,0;0,3],[1,1],[1,1]]; nfsnf(Q,M) nfsnf(Q,M,1) M=[[2,0;0,2],[2,2],[1,1]]; nfsnf(Q,M) nfsnf(Q,M,1) \\ oo loop after bnrmod commit 2b72fbfbf rnfconductor(bnfinit(a^3-a^2-6*a+7),x^3-a*x^2+(5*a^2-35)*x+(8*a^2+6*a-35))[3] 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(nfinit(y),x) rnfisabelian(nfinit(y^2+23),x^3+x^2-1) T = polcyclo(7, x+Mod(y, nf.pol)); rnfisabelian(nf, T) rnfisabelian(nfinit(a^2+1),5*x^3+2) rnfisabelian(nfinit(y^4+2),polsubcyclo(13,6)) rnfisabelian(nfinit(y^4+2),subst(polsubcyclo(13,6),x,7/6*x)) T=rnfisnorminit(bnfinit(y^3+y^2-2*y-1), x^3-y); [a,b]=rnfisnorm(T,y); [b,liftpol(norm(a)*b)] [a,b]=rnfisnorm(T,2,100); [b,liftpol(norm(a)*b)] [a,b]=rnfisnorm(T,2,-2*3*5*7); [b,liftpol(norm(a)*b)] do(T,u,flag=0)=liftpol(rnfisnorm(T,u,flag)); T=rnfisnorminit(y^2+23, x^2-y); do(T,y) do(T,2,100) \\#1157 rnfisnorminit(y,x^2-Mod(2+y,y)); \\#1778 K = bnfinit(x^4-2*x^3-27*x^2+28*x+53); t = varhigher("t"); L = rnfisnorminit(K,t^2-310*x^3+465*x^2+11005*x-274660); [a,b]=rnfisnorm(L,-28124/93*x^3+14062/31*x^2+562480/93*x+166769/31); liftpol(norm(a)*b) \\#1255 K = nfinit(z^3+z^2-2*z-1); rnf = rnfinit(K, x^2+Mod(-z,z^3+z^2-2*z-1)*x+1); a = rnfeltup(rnf,z^2) rnfeltdown(rnf, a) setrand(1);a=matrix(3,4,j,k,vectorv(3,l,random(21))); idx=idealprimedec(K,3)[1]; aid=[idx,1,1,1]; [A,U]=nfhnf(K,[a,aid],1); A U lift(matbasistoalg(K,a)*matbasistoalg(K,U)) a=a[,1..3]; [A,U,V]=nfsnf(K,[a, aid[1..3], [1,1,1]],1); A U V lift(matbasistoalg(K,U)*matbasistoalg(K,a)*matbasistoalg(K,V)) nf=nfinit(y); A = [[1,1/2;0,1],[1,1]]; nfhnfmod(nf, A, nfdetint(nf,A)) K=bnfinit(y^2-40); bnfisnorm(K,2, 0) bnfisnorm(K,6, 0) K=bnfinit(y^3-21); bnfisnorm(K,2) bnfisnorm(K,6) L=rnfinit(K,x^2-y); M=rnfinit(K,x); v = [2,1/2,x+y,Mod(1,K.pol),Mod(1/2,K.pol),Mod(y,K.pol),Mod(1,L.polabs),Mod(1/2,L.polabs),Mod(x,L.polabs),Mod(x+y/2,L.pol),y,z,Mod(y+1/2,y^2+1),[1]~,[1,2]~,[1,y]~,[1,I]~, y+I,x^2]; f=[rnfalgtobasis,rnfbasistoalg,rnfeltabstorel,rnfeltreltoabs,rnfeltup,rnfeltdown,rnfelttrace,rnfeltnorm]; test(L,v) = { for (i=1,#v, for (j=1,#f, print(f[j],"(L,",v[i]], "): ", iferr(f[j](L,v[i]), E,E)); print(f[j],"(M,",v[i]], "): ", iferr(f[j](M,v[i]), E,E)) )); my (K = L.nf); for (i=1,#v, print(i, ": ", iferr(rnfcharpoly(K,x^2-y,v[i]),E,E)) ); } test(L,v); KQ = nfinit(y+1); LQ = rnfinit(KQ, x^2-y); vQ = [2,1/2,x+y, Mod(1/2,KQ.pol), y, Mod(Mod(x/2+1,KQ.pol),LQ.pol), Mod(x,LQ.pol), Mod(x,LQ.polabs), Mod(x+y/2,x^2-y), x, [1]~,[1,2]~,[y]~]; test(LQ, vQ); nf = nfinit(y); rnf = rnfinit(nf,x^2-2); rel = Mod(Mod(1,y)+0*y,x^2-2); a = rnfeltreltoabs(rnf,rel) variable(lift(a)) Labs = nfinit(L); idL = idealhnf(Labs, x^3+x^2+10); idK = idealhnf(K, y^2+10*y+5); id = rnfidealabstorel(L,Labs.zk*idL) rnfidealnormabs(L,id) == idealnorm(Labs, idL) m = rnfidealreltoabs(L, id) mathnf(matalgtobasis(Labs,m)) == idL P3 = idealprimedec(K,3); \\ pr[5] depends on 32/64-bit arch strip5(pr)=pr[1..4]; apply(strip5, rnfidealprimedec(L, P3[1])) my(v=rnfidealprimedec(L,7)); [apply(strip5, v[1]), apply(strip5, v[2][1])] k=nfinit(y^3-y^2+1); rnfidealprimedec(rnfinit(k,x),idealprimedec(k,89)[1]) rnffa(rnf,id)=my(fa=rnfidealfactor(rnf,id)); fa[,1] = apply(strip5,fa[,1]); fa; rnffa(L,7) rnffa(L,x) rnffa(L,y) rnfidealfactor(L,id) == rnfidealfactor(L,idL) m = rnfidealup(L, idK) mabs = rnfidealup(L, idK, 1); mathnf( Mat(apply(x->nfalgtobasis(Labs,x), m)) ) == mabs rnfidealdown(L, m) == idK rnfidealdown(L, mabs) == idK m = rnfidealdown(L, Labs.zk*idL) M=rnfidealup(L, m) mathnf(matalgtobasis(Labs,M)) == rnfidealup(L, m, 1) \\ V=concat(v, [[;], [], 0, [[;],[]], idealprimedec(K,2)[1], idK, idL, Labs.zk*idL, id]); f=[rnfidealhnf,rnfidealreltoabs,rnfidealabstorel,rnfidealdown,rnfidealup,rnfidealnormrel,rnfidealnormabs,rnfidealtwoelt]; { for (i=1,#V, print(i,":"); for (j=1, #f, print(iferr(f[j](L,V[i]),E,E)) ) ) } rnfidealmul(L, 0,1) rnfidealmul(L, 1,0) rnfidealmul(L, x,y) rnfidealmul(L, y,x) rnfidealmul(L, id,x) rnfidealmul(L, x,id) rnfdet(K,[[;],[]]) rnfdet(K,id) rnfbasis(bnfinit(y^2-1105),x^2-y) \\#1508 K=nfinit(y); L=rnfinit(K,x^3-2); rnfeltdown(L,Mod(Mod(1,K.pol),L.polabs)) rnf=rnfinit(nfinit(y^2+1),x^2-2); rnfidealup(rnf, matid(2)/2) k1=bnfinit(y^3+y^2-2*y-1); u=x^3+y*x^2+(y-2)*x+(y^2-y-1); rnfconductor(k1,u) rnfconductor(k1,u / Mod(y,k1.pol))[^2] \\ wrong: not Abelian rnfconductor(k1, y*x^2+(y-2)*x+(y^2-y-1))[^2] rnfconductor(k1,u,2) K = bnfinit(y^4+10*y^2+17); rnfconductor(K, x + 1/2*y^3 - 1/2*y^2 + 9/2*y - 13/2)[1] rnfconductor(bnfinit(y^2+y+1),[x^6-3,100],2) K = nfinit(y^2+y+1); rnfislocalcyclo(rnfinit(K, x^3-2)) rnfislocalcyclo(rnfinit(K, x)) rnfislocalcyclo(rnfinit(K, x^3 - y)) rnfislocalcyclo(rnfinit(K, x^3 - y + 3^6)) nf=nfinit(y^2+9); \\ 3 divides index P=idealprimedec(nf,3)[1]; rnfdedekind(nf, (x+y/3)^3+3*y, P) 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, pr3, 1) t = 't; T = polcyclo(9,t); pol = y^2 + Mod(t^5+t^2+t-1, T)*y + Mod(1-t, T); Qchi=nfinit([T,10^6]); rnfinit(Qchi,[pol,10^6]); \\ segv in 2.11 k = nfinit(y^4 + 10*y^2 + 17); rnfdisc(k, x^2 - x + 1/Mod(y,k.pol)) rnfdisc(k, x^2 - x + 1/2) k = nfinit(y^4 - 10*y^2 + 1); rnfdisc(k,x^2-(y^3/2+y^2-5*y/2+1)) default(parisize,"12M"); \\ 10M overflows on 64bit pol=x^2+(-4*y^60+2*y^58-4*y^56+7*y^54-5*y^52+y^48+3*y^46-3*y^44-2*y^42+3*y^40+y^38-2*y^36-3*y^34+6*y^32-3*y^30-y^28-2*y^26+5*y^24-y^22-4*y^20+2*y^18+2*y^16-y^14-3*y^12+3*y^10+2*y^8-2*y^6-4*y^4+5*y^2+5); rnfdisc(nfinit(y^62-y^2-1),pol) \\ #2453 A=nfinit(t^2-2); B=rnfinit(A, y^2-3); C=nfinit(B); D=rnfinit(C, x^2-11); E=nfinit(D); \\ ERRORS, keep at end of file rnfdedekind(nf, P, pr2, 1) rnfdedekind(nf, P) rnfdedekind(nf, P, [pr2,pr3]) rnfdedekind(nf, x^2) rnfconductor(nf, x^2); rnfconductor(nf, [x^2,1]); rnfpseudobasis(nf, x^2/2 + 1); rnfpseudobasis(nf, x^2 + 1/2); rnfpseudobasis(nf, x^2); rnfeltnorm(x,x) rnfelttrace(x,x) rnfislocalcyclo(rnfinit(K, x^6-y+1)) \\#1530 L=rnfinit(nfinit(y^2-3),x^2+23); rnfidealtwoelt(L, [[1;0], [1/104]]) \\#2093 nf = nfinit(y); rnf = rnfinit(nf,x^2+5); rnfidealup(rnf,Mat(3),1); bnfinit(rnf) \\#2495 nf = nfinit(y^2+1); p = 693097151489577169008672217912084052214809976903253232857439; q = 134030351997211063914384780332714266256061083570879885159579; rnfinit(nf,[x^2+p*q*(7564756*y+76578564), 2^20]).disc pari-2.17.2/src/test/in/galoisinit0000644000175000017500000001245014676526175015452 0ustar billbilldefault(parisize,"16M"); \\ 14M overflows do(p)=galoisidentify(galoisinit(p)); do(algdep(I,3)) do(galoissubcyclo(bnrinit(bnfinit(y),[1232,[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^36-9*x^35+39*x^34-117*x^33+309*x^32-744*x^31+1509*x^30-2736*x^29+5118*x^28-9930*x^27+17586*x^26-25014*x^25+28269*x^24-33297*x^23+56064*x^22-99678*x^21+130920*x^20-101487*x^19+10906*x^18+79494*x^17-112527*x^16+97506*x^15-83133*x^14+86349*x^13-101097*x^12+104667*x^11-58137*x^10-23812*x^9+94116*x^8-115215*x^7+79920*x^6-27150*x^5-8715*x^4+13350*x^3-2400*x^2-1200*x+400) 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^2-3*x+4) nfgaloisconj(x^3-x-1) nfgaloisconj(x^24+2814) nfgaloisconj(x^4+1) nf=nfinit(polcyclo(7)); s = nfgaloisconj(nf)[2]; pr = idealprimedec(nf,11)[1]; nfgaloisapply(nf,s,idealhnf(nf,pr)) nfgaloisapply(nf,s,pr) nfgaloisapply(nf,s,x^2+x) nfgaloisapply(nf,s,1/2) v=[1,1/2,Mod(x,nf.pol),x,vectorv(6),[;],[1,2;x,3]]; for (i=1,#v, print(nfgaloisapply(nf,s,[1,v[i]]))) galoistest(P,f)= { my(G,F,L); G=galoisinit(P); F=galoissubfields(G,f); for (i=1,#F, my(L=F[i]); if (subst(L[1],variable(L[1]),L[2])!=0, error("galoissubfields1")); if (f==2 && factorback(L[3]*Mod(1,L[1]))!=P, error("galoissubfields2"))); } galoistest(x^4 + 431452248691495692750746750*x^3+447244936830156353775324765*x^2+5580140636706480467906000*x - 238676773812533681600,2); galoistest(polcyclo(88)); G=galoisinit(x); galoisexport(G); galoisexport(G,1); G=galoisinit(x^12-30*x^8-370*x^6+1665*x^4+23166*x^2+81); galoispermtopol(G,G.gen) galoisexport(G) galoisexport(G, 1) G=galoisinit(x^12-24*x^10-10*x^9+216*x^8+180*x^7-844*x^6-1080*x^5+1056*x^4+2200*x^3+720*x^2-240*x-80); L=galoissubgroups(G) apply(H->galoisisnormal(G,H),L) apply(H->galoisisabelian(H),L) apply(H->galoisisabelian(H,1),L) apply(H->galoisisabelian(H,2),L) apply(permcycles,G.group) apply(permorder,G.group) apply(permsign,G.group) vector(#G.group, i, galoisfixedfield(G,G.group[i],1)) galoisfixedfield(G,G.group[2]) galoisfixedfield(G,G.group[2],2,y) \\ #2253 G=galoisinit(x^9-5*x^8-70*x^7+269*x^6+1591*x^5-4531*x^4-11255*x^3+29326*x^2+7688*x-29791); galoisfixedfield(G,G.gen,2) galoissubcyclo(17,2) galoissubcyclo(1,1) galoissubcyclo(1,1,1) galoissubcyclo(1,1,2) galoissubcyclo(znstar(124),[3,0;0,2]) galoisidentify(galoissubcyclo(znstar(124),[3,0;0,2],3)) galoissubcyclo(znstar(124,1),[3,0;0,2]) \\#2232 G=bnrinit(bnfinit(a),[65,[0]]); L=subgrouplist(G,[2]); galoissubcyclo(G,L[1]) G=bnrinit(bnfinit(a),[65,[0]], 1); \\ include generators galoissubcyclo(G,L[1]) G=galoisinit(polcyclo(20)) galoissubfields(G) G=galoisinit(x^6+108); galoissubfields(G,2,z) P=nfsplitting(x^4-x-1);G=galoisinit([P,nfgaloisconj(P)]); vecsort(apply(permorder,Vec(G.group))) P=x^5-x-1;galoisinit([P,nfgaloisconj(P)]) G=galoissplittinginit(x^5+20*x+16);#galoissubgroups(G) #galoissubgroups(G.group) galoisidentify(G) P =x^18-2*x^17-3*x^16+10*x^15-8*x^14-11*x^13+42*x^12-26*x^11-65*x^10+79*x^9+11*x^8-72*x^7+35*x^6+10*x^5-21*x^4+8*x^3+x^2-x+1; G=galoissplittinginit(P);galoisidentify(G) \\ ERRORS G=galoisinit(x^6-3*x^5+5*x^4-5*x^3+5*x^2-3*x+1); galoispermtopol(G,[4,3,6,5,1,2]) pari-2.17.2/src/test/in/elliptic0000644000175000017500000000230614724330077015100 0ustar billbillHEAP=[74, if(sizebyte(0)==16,4434,4617)]; default(realprecision,154); Pi; default(realprecision,38); \e ellinit([-1,0]) ellinit([-17,0],1) ellsub(%,[-1,4],[-4,2]) ellj(I) \\ acurve=ellinit([0,0,1,-1,0]) apoint=[2,2] elladd(acurve,apoint,apoint) ellak(acurve,1000000007) ellan(acurve,100) ellap(acurve,10007) deu=direuler(p=2,100,1/(1-ellap(acurve,p)*x+if(acurve.disc%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) ellordinate(acurve,1) ellpointtoz(acurve,apoint) ellztopoint(acurve,%) ellmul(acurve,apoint,10) ellwp(acurve, x+O(x^33)) q*Ser(ellan(acurve,100),q) \\ bcurve=ellinit([-3,0]) elllocalred(bcurve,2) elltaniyama(bcurve) \\ ccurve=ellinit([0,0,-1,-1,0]) l=elllseries(ccurve,2) exponent(elllseries(ccurve,2,1.2)-l) < -125 \\ tcurve=ellinit([1,0,1,-19,26]); ellorder(tcurve,[1,2]) elltors(tcurve) \\ mcurve=ellinit([-17,0]); mpoints=[[-1,4],[-4,2]]~; mhbi=ellbil(mcurve,mpoints,[9,24]) ma=ellheightmatrix(mcurve,mpoints) matsolve(ma,mhbi) \\ cmcurve=ellinit([0,-3/4,0,-2,-1]) ellmul(cmcurve,[x,y],quadgen(-7)) if (getheap()!=HEAP, getheap()) pari-2.17.2/src/test/in/polmodular0000644000175000017500000001615514676526175015474 0ustar billbillhash_base = 2^64; init_h = 5381; split_Z(n) = { my (bits = 8, base = 2^bits, sgn = sign(n) % base, res = []); n = abs(n); while (n != 0, res = concat(res, bitand(n, base - 1)); n = shift(n, -bits)); res = concat(res, sgn); } glue(h, a) = bitand((((h << 5) + h) + a), hash_base - 1); hash_Z(n) = { my (v = split_Z(n), h = init_h); for (i = 1, #v, h = glue(h, v[i])); h; } hash_ZX(pol) = { my (v = Vec(pol), h = init_h); for (i = 1, #v, h = glue(h, hash_Z(v[i]))); h; } hash_ZXX(pol) = { my (v = [Vec(c) | c <- Vec(pol)], h = init_h); for (i = 1, #v, h = glue(h, hash_ZX(v[i]))); h; } { lvl_idx = [0, 1, 2, 0, 3, 0, 4, 0, 0, 0, 5, 0, 6, 0, 0, 0, 7, 0, 8, 0, 0, 0, 9]; modpoly_hashes = [ 953115400354185, 619732354788530567, 7671381920119322245, 1662362517513198972, 11499552816775494464, 10945716853871337038, 1858790070632847848, 16279119036202003022, 9091292905489559584 ]; } check_modpoly(L, hash, inv = 0) = { if (hash_ZXX(polmodular(L, inv)) != hash, error("Bad modpoly")); } default(parisize, "18M"); \\ overflows 16M { MAX_LEVEL = 23; \\ This already gives 89% coverage in 1.2s forprime(L = 2, MAX_LEVEL, check_modpoly(L, modpoly_hashes[lvl_idx[L]])); modfn_in = [[2, 5, 7818678061185], [5, 1, 14017670839540699521], [5, 5, 10135583858468178383], [7, 1, 6937006200180283618], [7, 5, 9634555674574853739], [19, 1, 11245295902670825360], [29, 1, 16325532180637558646], [47, 1, 5045713438637349850], [61, 5, 5614541323969591564], [71, 0, 8840690212199031415], [101, 1, 18403372459340572304], [139, 1, 4966835288214143418], [359, 1, 15999826932501894898], \\ takes 3s, no smaller example though :( [5, 6, 14025475434705720054], [5, 9, 4070138482583618498], [7, 10, 2092081457940371680], [3, 14, 7826463370842897], [2, 15, 7613995049265], [5, 21, 2152391919677952616], [3, 26, 7840368574373379], [2, 35, 8034981587292], [2, 39, 8034981863898], [5, 2, 14025475647798473994], [5, 23, 4078176315075291878], [7, 24, 15539023920884183490], [5, 27, 2153788462654972246], [5, 28, 4579080621787198547], [41, 2, 18150754343002627833], [41, 5, 3465379807262449566], [41, 6, 12863521307608118553], [41, 9, 5674021873271863077], [41, 10, 15269149163413540837], [41, 14, 12129179001644404437], [41, 15, 445355180908304715], [41, 21, 9618478875553953373], [41, 23, 7613336307888355697], [41, 24, 7221767736513486251], [41, 26, 2777849492219862654], [41, 27, 1438586205409091583], [41, 28, 8177252307561913215], [41, 35, 8718342713488965926], [41, 39, 1857869646559265631], [29, 21, 140598897682543022], [101, 21, 1028254489804326757], [53, 15, 11992315117197580073], \\ NB: The hashes for these tests do not come from \\ an independent source [17, 3, 7524902883828545591], [19, 3, 13749860608403259582], [19, 4, 451945996748663121], [19, 8, 13661084005765275348] ]; for (i = 1, #modfn_in, my (in = modfn_in[i]); check_modpoly(in[1], in[3], in[2])); \\ Check that specifying variables works my (phi7 = polmodular(7)); if (phi7 != polmodular(7, , 'x, 'y) || phi7 != polmodular(7, , 'x) || polmodular(7, , 's, 't) != substvec(phi7, ['x, 'y], ['s, 't]), error("Bad variables")); \\ Check argument checking my (got_err); iferr (polmodular(7, , "I am the queen of France", 'x), err, got_err = 1, errname(err) == "e_TYPE"); if ( ! got_err, error("No type error from bad param")); got_err = 0; iferr (polmodular(7, , ffgen(2^3), 'x), err, got_err = 1, errname(err) == "e_DOMAIN"); if ( ! got_err, error("No domain error from non-prime field arg")); got_err = 0; iferr (polmodular(1), err, got_err = 1, errname(err) == "e_DOMAIN"); if ( ! got_err, error("No error from level 1")); got_err = 0; iferr (polmodular(6), err, got_err = 1, errname(err) == "e_IMPL"); if ( ! got_err, error("No error from composite level")); got_err = 0; iferr (polmodular(7, , 'x, 'y, 1), err, got_err = 1, errname(err) == "e_FLAG"); if ( ! got_err, error("No error from inappropriate flag")); got_err = 0; iferr (polmodular(7, , 'x, 'x), err, got_err = 1, errname(err) == "e_PRIORITY"); if ( ! got_err, error("No error from same variables")); got_err = 0; iferr (polmodular(7, , 'y, 'x), err, got_err = 1, errname(err) == "e_PRIORITY"); if ( ! got_err, error("No error from bad variables")); got_err = 0; iferr (polmodular(3, 5); polmodular(2, 1), err, got_err = 1, errname(err) == "e_DOMAIN"); if ( ! got_err, error("No error from incompatible level/invariant pair")); got_err = 0; iferr (polmodular(19, 7), err, got_err = 1, errname(err) == "e_DOMAIN"); if ( ! got_err, error("No error from bad invariant")); } all(v) = { my (r = 1); for (i = 1, #v, r = r && v[i]); r; } poloftype(f, tp) = { type(f) == "t_POL" && all([type(polcoeff(f, d)) == tp | d <- [0 .. poldegree(f)]]); } lift_ffx(f) = { my (v = Vec(f)); if ( ! all([poldegree(c.pol) == 0 | c <- v]), error("Polynomial has coeffs in extension")); Pol([polcoeff(c.pol, 0) | c <- Vec(f)], variable(f)); } check_eval_modpoly(L, j, p, expected) = { my (jm = Mod(j, p), jf = j * ffgen(p)^0, um = polmodular(L, , jm, 'y, 0), uf = polmodular(L, , jf, 'y, 0), vm = polmodular(L, , jm, 'y, 1), vf = polmodular(L, , jf, 'y, 1)); if ( ! poloftype(um, "t_INTMOD") || ! poloftype(uf, "t_FFELT") || type(vm) != "t_VEC" || #vm != 3 || type(vf) != "t_VEC" || #vf != 3, error("Invalid return type")); if ( ! all([poloftype(v, "t_INTMOD") | v <- vm]) || ! all([poloftype(v, "t_FFELT") | v <- vf]), error("Invalid coefficients")); if (um != vm[1] || uf != vf[1] || lift(um) != lift_ffx(uf) || hash_ZX(lift(um)) != expected[1], error("Wrong result for modpoly eval")); if (hash_ZX(lift(vm[2])) != expected[2], error("Wrong derivative")); if (hash_ZX(lift(vm[3])) != expected[3], error("Wrong second derivative")); } { my (p = nextprime(2^40)); check_eval_modpoly( 5, 7, 151, [8033941431460000, 243641761686181, 243612090562303]); check_eval_modpoly(19, 7, 151, [11844895572672018496, 369501438945078285, 13082720985735388448]); \\check_eval_modpoly( 5, 7, factorial(12), XXXX); check_eval_modpoly( 5, 7, p, [3901199766181530739, 4054334766401667256, 16751141247645108349]); \\check_eval_modpoly(23, 7, factorial(12), XXXX); check_eval_modpoly(23, 7, p, [2360118342899681926, 2787294817779511277, 18359991236545579908]); } { my(p=randomprime(10^100),q=Mod(random(p),p)); if(subst(polmodular(7),x,q)!=polmodular(7,,q),error("polmodular(7,,q)")); } { my(i = ffgen(Mod(1, 7)*(x^2 + 1)), Phi = polmodular(2, 0, i^2)); if(!all([ffgen(c) == i | c <- Vec(Phi)]), error("wrong base field")); } pari-2.17.2/src/test/in/combinat0000644000175000017500000000056214567450071015073 0ustar billbillvector(10, k, stirling(11,k)) vector(11, k, stirling(12,k)) vector(10, k, stirling(11,k, 2)) vector(11, k, stirling(12,k, 2)) v = vector(5!,i,numtoperm(5, i-1)) if(vecsort(v,lex)!=v,error("numtoperm")); vector(#v, i, permtonum(v[i])) vector(#v, i, permtonum(Vecsmall(v[i]))) stirling(100,0) iferr(permtonum([1,3,0]), E, Vec(E)) permtonum(1) permtonum([]) numtoperm(0,0) pari-2.17.2/src/test/in/gchar0000644000175000017500000005050214676526175014374 0ustar billbilldefault(parisize,"10M"); \\ 8M overflows gcharinit(bnfinit('y),1); print("one large field"); bnf=bnfinit(polcyclo(17)); p1 = idealadd(bnf, 13, x^4-4*x^3-4*x+1); p2 = idealadd(bnf, 17, x-1); p3=idealadd(bnf ,19, x^8-6*x^7-4*x^6-3*x^5+8*x^4-3*x^3-4*x^2-6*x+1); N=idealfactorback(bnf,[p1,p2,p3],[1,0,0]); gc=gcharinit(bnf,N); round(gc.cyc) print("non trivial cm subfield"); pol = rnfequation(polcyclo(5,'y),'x^2-'y-1); bnf = bnfinit(pol,1); gc = gcharinit(bnf,1); mathnf(gcharalgebraic(gc)) /* TODO: better check for values */ pr = idealprimedec(bnf,11)[1]; \\c1 = [1,0,0,0,0,0,0,-8]~; c1 = gcharidentify(gc,[1,2,3,4],[[-2,8*I],[2,8*I],[16,8*I],[-16,8*I]]); gcharisalgebraic(gc,c1,&pq) pq gcharlocal(gc,c1,1) gcharlocal(gc,c1,2) gcharlocal(gc,c1,3) gcharlocal(gc,c1,4) bestappr(log(abs(gchareval(gc,c1,pr)))/log(11)) \\c2 = [0,1,0,0,0,0,0,-5]~; c2 = gcharidentify(gc,[1,2,3,4],[[0,5*I],[0,5*I],[10,5*I],[-10,5*I]]); gcharisalgebraic(gc,c2,&pq) pq gcharlocal(gc,c2,1) gcharlocal(gc,c2,2) gcharlocal(gc,c2,3) gcharlocal(gc,c2,4) bestappr(log(abs(gchareval(gc,c2,pr)))/log(11)) print("gcharalgebraic"); gc = gcharinit(polcyclo(5),25); alg = gcharalgebraic(gc); matrank(alg) denominator(alg) alg[6,]==0 matdet(mathnf(2*alg)[1..5,1..5]/2)==2 gcharalgebraic(gc,[[2,3],[0,0]]) [chi] = gcharalgebraic(gc,[[-2,3],[1,0]]); chi[#chi] == -1/2 gcharisalgebraic(gc,[0,0,1,0,0,0]~) chi = gcharidentify(gc,[1,2],[[-1,0],[1,0]]); gcharisalgebraic(gc,concat(chi,-3/2),&pq) pq gc = gcharinit(x^2+1,1); [chi]=gcharalgebraic(gc,[[4,0]]); abs(chi) gcharisalgebraic(gc,chi,&pq) pq print("gcharisalgebraic r1>0"); bnf = bnfinit(x^2-5); gc = gcharinit(bnf,8); gcharisalgebraic(gc,[0,0]~,&pq) pq gcharisalgebraic(gc,[1,0]~,&pq) pq gcharisalgebraic(gc,[0,1]~,&pq) gcharisalgebraic(gc,[0,0,-1]~,&pq) pq gcharisalgebraic(gc,[0,0,-1/2]~,&pq) bnf = bnfinit(x^3-x-1); gc = gcharinit(bnf,9); gcharisalgebraic(gc,[0,0,0,0]~,&pq) pq gcharisalgebraic(gc,[1,0,0,0]~,&pq) pq gcharisalgebraic(gc,[0,2,0,0]~,&pq) pq gcharisalgebraic(gc,[0,0,1,0]~,&pq) gcharisalgebraic(gc,[0,0,0,1]~,&pq) gcharisalgebraic(gc,[0,1,0,0,-1]~,&pq) pq gcharisalgebraic(gc,[0,1,0,0,-1/2]~,&pq) print("need to increase prec"); pol = x^4 - 2*x^3 + 5*x^2 - 2*x - 1; bnf = bnfinit(pol); N = (2*3*7*11)^2; gc = gcharinit(bnf,N); print("larger fields"); print("r2 = 5, clno = 5"); pol = x^12 + 8*x^10 + 6*x^8 - 268*x^6 - 1438*x^4 - 3420*x^2 - 3078; bnf = bnfinit(pol); gc = gcharinit(bnf,1); gc = gcharinit(bnf,2*3*7); print("r2 = 4, clno = 3"); pol = x^8 - 3*x^5 - x^4 + 8*x^2 - 10*x + 6; bnf = bnfinit(pol); gc = gcharinit(bnf,1); gc = gcharinit(bnf,3^4*117*1009); print("r2 = 8, clno = 16"); pol = x^20 - 4*x^19 + 2*x^18 + 12*x^17 - 248*x^16 + 577*x^15 - 2210*x^14 + 4900*x^13 - 1187*x^12 + 7487*x^11 + 23396*x^10 - 53786*x^9 - 64916*x^8 - 97158*x^7 - 267387*x^6 + 221033*x^5 + 460138*x^4 + 9786*x^3 + 481572*x^2 + 115934*x - 511901; bnf = bnfinit(pol); {p5 = idealadd(bnf, 5, 96965017807771961905683702603422608463328455154870010/9523197523984467081398524314103182597785758649553142622913*x^19 -243702022593120105582606367863258391277124600413664280/9523197523984467081398524314103182597785758649553142622913*x^18 -173785223880858947981363371041479604207829500044070035/3174399174661489027132841438034394199261919549851047540971*x^17 +2246708897157516926966583891688362785713249927792681345/9523197523984467081398524314103182597785758649553142622913*x^16 -7760358825179556246215703931103085586929873875979038665/3174399174661489027132841438034394199261919549851047540971*x^15 +5991271817067359399837986097786709619023316405452671045/3174399174661489027132841438034394199261919549851047540971*x^14 -7293791089064536257647343890928334214525350150840247620/732553655691112852415271101084860199829673742273318663301*x^13 +9007652007415671496609726357891030960671674064881086160/3174399174661489027132841438034394199261919549851047540971*x^12 +963431180384079513015132976216364636048834461748683606840/9523197523984467081398524314103182597785758649553142622913*x^11 -541153718261886447488302057317224751222484902406081244665/9523197523984467081398524314103182597785758649553142622913*x^10 +495993549060025841136781668831845626147271198224290730420/1058133058220496342377613812678131399753973183283682513657*x^9 -2951512431380945050194084758301837078633183983299494641110/9523197523984467081398524314103182597785758649553142622913*x^8 -4229836816264991752928370151739394467094932865979692757325/3174399174661489027132841438034394199261919549851047540971*x^7 -3551897129770853600638689559295650739899333509563576842360/3174399174661489027132841438034394199261919549851047540971*x^6 -11081640567925230059874148533475145986631681618481200814914/3174399174661489027132841438034394199261919549851047540971*x^5 -29821379555152458168834404288142990415610216045122401039040/9523197523984467081398524314103182597785758649553142622913*x^4 +60674413212920467734881418550608279784972041558727891609720/9523197523984467081398524314103182597785758649553142622913*x^3 -6685591543847809652898148650746047356406283505802044502066/9523197523984467081398524314103182597785758649553142622913*x^2 +975035794097135137816802771013149686408385892613702411829/732553655691112852415271101084860199829673742273318663301*x +534871993442126298320141788238586645765887992741948876367/56350281207008680955020853929604630756128749405639897177)}; p5 = idealfactor(bnf,p5)[1,1]; p101 = idealadd(bnf, 101, x^2-18*x-28); p101 = idealfactor(bnf, p101)[1,1]; gc = gcharinit(bnf,[p5,[0,0,0,0]]); gc = gcharinit(bnf,[[p5,1;p101,3],[0,1,0,1]]); print("gcharidentify"); gc = gcharinit(x^2-5,1); om = Pi/log((1+sqrt(5))/2); lchiv = [[0,om-I],[0,-om-I]]; chi = gcharidentify(gc,[1,2],lchiv); abs(chi[1]) chi[2] chi == gcharidentify(gc,[1,2],lchiv) \\ lchiv was altered, see 8c67726 bnf = bnfinit(x^4 - x^3 + 3*x^2 + 2*x + 1, 1); gc = gcharinit(bnf, 1); round(gc.cyc) gcharidentify(gc,[],[]) pr = idealprimedec(bnf, 101)[1]; idl = idealadd(bnf, 140788137003612377, 6496*x^3-6496*x^2+19489*x-35497622602420127); B=2; {forvec(V=[[0,1],[-B,B],[-B,B],[-B,B]], chi = V~; param = gcharduallog(gc,chi); if(gcharidentify(gc,[pr],[gchareval(gc,chi,pr,0)])!=chi,print("FAIL a: chi=",chi)); if(gcharidentify(gc,[pr,1,2],[gchareval(gc,chi,pr,0), [param[4],param[2]],[param[5],param[3]]])!=chi,print("FAIL b: chi=",chi))); }; gcharidentify(gc,[1,2],[[0,1],[0,0]]) gcharidentify(gc,[1,2],[[0,1/2],[0,0]]) gcharidentify(gc,[1,2],[[0,0.7],[0,0]]) gcharidentify(gc,[1],[[0,0]]) \\ TODO init interface /* bigger units, cm, etc. */ gc = gcharinit(x^2 + 4625968752,1); mathnf(matconcat([gcharalgebraic(gc),matdiagonal(round(gc.cyc))])) pol = x^6 + 2854*x^4 + 2036329*x^2 + 513996528; gc = gcharinit(pol,7*13); round(gc.cyc) alg = gcharalgebraic(gc); matrank(alg) denominator(alg) alg[7..10,] == 0 denominator(round([concat(vector(3,v,gcharlocal(gc,chi,v))) | chi <- Vec(alg)]*10^10)/10^10) /* big class number, precision */ print("prec increase"); f = x^3 - 5929*x^2 - 5932*x - 1; gc = gcharinit(f,1); round(gc.cyc) /* increase prec */ localbitprec(64);bitprecision(gcharnewprec(gc)[1])>=64 localbitprec(764);bitprecision(gcharnewprec(gc)[1])>=764 /* evaluate */ p=idealprimedec(gc.nf,13)[1]; chi = [137,7,1,0,-1283,1233]~; localbitprec(64); v1 = gchareval(gcharnewprec(gc),chi,p,0); localbitprec(128); v2 = gchareval(gcharnewprec(gc),chi,p,0); exponent(v1-v2) <= -64 p=idealprimedec(gc.nf,nextprime(1<<32))[1]; \\gcharlog(gc,p); localbitprec(132); v1 = gchareval(gcharnewprec(gc),chi,p,0); localbitprec(256); v2 = gchareval(gcharnewprec(gc),chi,p,0); exponent(v1-v2) <= -132 print("limit cases"); bnf = bnfinit(x^2-5,1); gc = gcharinit(bnf,1); abs(gcharalgebraic(gc)) bnf = bnfinit(x^2+1,1); gc = gcharinit(bnf,1); mathnf(gcharalgebraic(gc)) gcharalgebraic(gc,[[2,0]]) gc = gcharinit(x^4+x^2+x+1,1); gcharalgebraic(gc) gcharalgebraic(gc,[[1,0],[1,0]]) gcharalgebraic(gc,[[0,0],[0,0]]) gcharalgebraic(gc,[[1,1],[1,1]]) bnf = bnfinit(x^2-15,1); gc = gcharinit(bnf,1); gcharalgebraic(gc,[[0,0],[0,0]]) gcharalgebraic(gc,[[1,0],[0,1]])[1][2..3] bnf = bnfinit(x^3-x-1,1); gc = gcharinit(bnf,1); gcharalgebraic(gc,[[1,0],[1,1]]) gcharalgebraic(gc,[[1,0],[1,0]]) print("gcharisalgebraic"); bnf = bnfinit(polcompositum(x^2+1,x^2-2,2),1); gc = gcharinit(bnf,1); gcharisalgebraic(gc,[0,0,1]~) gcharisalgebraic(gc,[0,1,0,1]~) gcharisalgebraic(gc,[0,1,0,1/2]~) gcharisalgebraic(gc,[0,1,0,1/3]~) print("gcharduallog"); bnf = bnfinit(polcompositum(x^2+1,x^2-2,2),1); gc = gcharinit(bnf,1); chi1 = gcharidentify(gc, [1,2], [[-2,0],[2,0]]); chi2 = gcharidentify(gc, [1,2], [[8,0],[0,0]]); chi3 = gcharidentify(gc, [1,2], [[-5,0.9],[1,-0.9]]); round(10^20*gcharduallog(gc,chi1+chi2)) round(10^20*gcharduallog(gc,-chi1+chi3)) chi = [1,2,3,-2+I]~; pr = idealprimedec(bnf,2)[1]; logchi = gcharduallog(gc,chi); logpr = gcharlog(gc,pr); ev1 = gchareval(gc,chi,pr,0); ev2 = logchi*logpr; ev2 -= round(real(ev2)); exponent(ev1-ev2) <= -128 print("gchareval"); bnf = bnfinit(x^2-5,1); gc = gcharinit(bnf,1); {pr = idealprimedec(bnf,4868320566074468416097809002841831981658439271775190047920287334713696332088188270302203142585474506572031649428572390977423717630750557541900820118557642144443115103994166347876446053933456365372443159385038281515406885479747287229391251928691579336473986380517198489368653247235220470411135182771495870761970425831248490802339741145177367606504253702366044757540837091578313318381751990985274838858471553879603486279186618215547339963941317895448200405735601843412836041079417187853293418139422395939702479069851901004480187793116104550625410950517848593134330788344046026982177143293369431992447318613826461691545456669249262035189314826400325163760162186599556491881653572410925778376382784596006650973201534577780715605881753754637909365503082172360234118525438866377677143768516149987111093650011641611864293773011677933805015609245095155892783139734857107226208996763683785018645448619606720812034222383494488841874984727092271722163949359822795927735020861595850675165350830336905890838102021)[1]}; chi = [16876547436542378657653465325489780897097678654765346543]~; v1 = gchareval(gc,chi,pr,0); localbitprec(256); v2 = gchareval(gcharnewprec(gc),chi,pr,0); exponent(v1-v2) <= -128 pr2 = idealprimedec(bnf,13)[1]; chi = [1]~; round(exp(2*I*Pi*(gchareval(gc,[1,-1]~,pr2,0) - gchareval(gc,chi,pr2,0)))) round(exp(2*Pi*(gchareval(gc,[1,-I]~,pr2,0) - gchareval(gc,chi,pr2,0)))) print("gcharidentify 2"); bnf = bnfinit(x^2-2,1); gc = gcharinit(bnf,1); round(gc.cyc) pr = idealprimedec(bnf,7)[1]; th = gchareval(gc,[5]~,pr,0); gcharidentify(gc,[pr],[th]) chiw = gcharidentify(gc,[pr],[th+I*5/7]); exponent(gchareval(gc,chiw,pr,0)-th-I*5/7) < -125 print("gcharlocal"); bnf = bnfinit(x^2-5,1); gc = gcharinit(bnf,1); chi = gcharidentify(gc,[1],[[0,6.5285026052729938134630673568725898156]]); round(10^5*gcharlocal(gc,chi,1)) round(10^5*gcharlocal(gc,chi,2)) gc = gcharinit(bnf,[1,[1,0]]); chi = gcharidentify(gc,[1],[[0,6.5285026052729938134630673568725898156]]); round(10^5*gcharlocal(gc,chi,1)) round(10^5*gcharlocal(gc,chi,2)) gc = gcharinit(bnf,[2^2,[1,0]]); chi = gcharidentify(gc,[1],[[1,1.0]]); round(10^5*gcharlocal(gc,chi,1)) round(10^5*gcharlocal(gc,chi,2)) round(10^5*gcharlocal(gc,concat(chi,3.),1)) round(10^5*gcharlocal(gc,concat(chi,-2.),2)) round(10^5*gcharlocal(gc,concat(chi,10.*I),2)) pr = idealprimedec(bnf,2)[1]; loc = gcharlocal(gc,chi,pr,&bid); bid.cyc charorder(bid.cyc,loc[1..-2]) loc[#loc] loc = gcharlocal(gc,2*chi,pr); charorder(bid.cyc,loc[1..-2]) loc[#loc] loc = gcharlocal(gc,3*chi,pr); charorder(bid.cyc,loc[1..-2]) loc[#loc] gcharlocal(gc,6*chi,pr) bnf = bnfinit(x^3-x^2+5*x+1,1); gc = gcharinit(bnf,1); pr = idealprimedec(bnf,3)[1]; chi = gcharidentify(gc,[1,2,pr],[[0,1.],[2,-0.5],-0.11]); round(10^5*gcharlocal(gc,chi,1)) round(10^5*gcharlocal(gc,chi,2)) round(10^5*gcharlocal(gc,chi,pr)) bnf = bnfinit(x^2-5); gc = gcharinit(bnf,[4,[1,0]]); pr = idealprimedec(bnf,2)[1]; pr2 = idealprimedec(bnf,3)[1]; chi = gcharidentify(gc,[1,pr2],[[0,-1.],0]); loc = gcharlocal(gc,chi,pr,&bid); bid.cyc charorder(bid.cyc,loc[1..-2]) loc[#loc] print("doc gcharidentify"); bnf = bnfinit(x^2-5,1); gc = gcharinit(bnf,1); chi = gcharidentify(gc,[2],[[0,13.]]); gcharlocal(gc,chi,2) pr = idealprimedec(bnf,11)[1]; chi = gcharidentify(gc,[pr],[0.3]); gchareval(gc,chi,pr,0) bnf = bnfinit(x^2-5,1); gc = gcharinit(bnf,1); pr = idealprimedec(bnf,11)[1]; chi = gcharidentify(gc,[pr],[0.184760]); abs(chi[1]) > 1000 localprec(10); chi = gcharidentify(gc,[pr],[0.184760]); abs(chi[1]) < 1000 bnf = bnfinit(x^2-2,1); gc = gcharinit(bnf,1); round(gc.cyc) loc1 = [0,3.5-1/3*I]; loc2 = [0,-3.5-1/3*I]; chi = gcharidentify(gc,[1,2],[loc1,loc2]); chi[#chi] == 1/3 exponent(gcharlocal(gc,chi,1)-loc1) < 0 exponent(gcharlocal(gc,chi,2)-loc2) < 0 gc = gcharinit(x^5-7*x+1,5); chi = [1,2,-3,0,-1,3]~; Lv = [1,3,idealprimedec(gc.nf,13)[1],idealprimedec(gc.nf,23)[1],4]; chi == gcharidentify(gc,Lv,[gcharlocal(gc,chi,v)|v<-Lv]) print("doc gcharinit"); bnf = bnfinit(polcyclo(5),1); pr = idealprimedec(bnf,5)[1]; gc = gcharinit(bnf,idealpow(bnf,pr,2)); round(gc.cyc) chi1 = gcharidentify(gc, [1,2], [[-1,0],[1,0]]); chi2 = gcharidentify(gc, [1,2], [[1,0],[1,0]]); chi3 = gcharidentify(gc, [1,2], [[1,-0.82],[0,0.82]]); chi = chi1 + chi2 - chi3; gcharconductor(gc,chi)[1] print("doc gcharalgebraic"); bnf = bnfinit(x^4-2*x^3+23*x^2-22*x+6,1); gc = gcharinit(bnf,1); round(gc.cyc) alg = gcharalgebraic(gc); matrank(alg) denominator(alg) alg[4,] == 0 gcharalgebraic(gc,[[1,1],[0,1]]) [chi] = gcharalgebraic(gc,[[1,1],[0,2]]); chi[#chi] print("doc gcharconductor"); bnf = bnfinit(x^2-5,1); gc = gcharinit(bnf,[(13*19)^2,[1,1]]); round(gc.cyc) pr1 = idealprimedec(bnf,149)[1]; pr2 = idealprimedec(bnf,109)[1]; pr3 = idealprimedec(bnf,29)[1]; {chi = gcharidentify(gc, [1,2,pr1,pr2,pr3],[[1,-0.000105],[0,0.000105], 0.2486947292,-0.1108103,0.34497])}; \\chi = [0,0,1,1]~; gcharconductor(gc,chi) gcharconductor(gc,13*chi) gcharconductor(gc,13*19*chi) gcharconductor(gc,13*19*168*chi) print("doc gcharduallog"); bnf = bnfinit(x^3+4*x-1,1); gc = gcharinit(bnf,[1,[1]]); round(gc.cyc) chi = [0,1,0]~; f = gcharduallog(gc,chi); type(f) pr = idealprimedec(bnf,2)[1]; v = gcharlog(gc,pr); val1 = exp(2*I*Pi*f*v); val2 = gchareval(gc,chi,pr); exponent(val1-val2) < -125 print("doc gcharisalgebraic"); bnf = bnfinit(x^4+1,1); gc = gcharinit(bnf,1); round(gc.cyc) chi1 = [0,0,1]~; gcharisalgebraic(gc,chi1) gcharlocal(gc,chi1,1) chi_e1 = gcharidentify(gc, [1,2], [[-6,0],[2,0]]); chi2 = concat(chi_e1,-3); \\chi2 = [1,0,0,-3]~ gcharisalgebraic(gc,chi2,&typ) typ gcharlocal(gc,chi2,1) print("doc gcharalgebraic part 2"); bnf = bnfinit(x^4+15*x^2+45,1); gc = gcharinit(bnf,1); gc.cyc[1..-2] [chi] = gcharalgebraic(gc,[[2,0],[2,0]]); Lsum = 0; {forvec(v=vectorv(2,i,[0,gc.cyc[i]-1]), Lan = round(lfunan([gc,chi+concat(v,[0,0,0,0]~)],20)); Lsum += Lan; print(abs(Lan)); )}; Lsum E = ellinit([0, 0, 1, -270, -1708]); bnf = bnfinit(x^2+3,1); p3 = idealprimedec(bnf,3)[1]; gc = gcharinit(bnf,Mat([p3,2])); gc.cyc[1..-2] [chi] = gcharalgebraic(gc,[[1,0]]); LE = lfuncreate(E); lfunan(LE,20) Lchi = lfuncreate([gc,chi]); round(lfunan(Lchi,20)) L = lfungenus2([-2*x^4 - 2*x^3 + 2*x^2 + 3*x - 2, x^3]); bnf = bnfinit(a^4 - a^3 + 2*a^2 + 4*a + 3, 1); pr = idealprimedec(bnf,13)[1]; gc = gcharinit(bnf,pr); gc.cyc[1..-2] chitors = [1,0,0,0,0]~; typ = [[1,0],[1,0]]; [chi0] = gcharalgebraic(gc,typ); igood = oo; nbgood = 0; {for(i=0,gc.cyc[1]-1, chi = chi0 + i*chitors; Lchi = lfuncreate([gc,chi]); if(lfunparams(L) == lfunparams(Lchi) && exponent(lfunan(L,10) - lfunan(Lchi,10)) < -50, igood=i; nbgood++ ); )}; nbgood chi = chi0 + igood*chitors; Lchi = lfuncreate([gc,chi]); lfunan(L,30) round(lfunan(Lchi,30)) print("doc gcharlocal"); bnf = bnfinit(x^3-x-1); gc = gcharinit(bnf,1); round(gc.cyc) chi = concat(gcharidentify(gc,[1,2],[[0,-4.88],[6,2.44]]), 1/3); \\chi = [0,1,1/3]~; pr = idealprimedec(bnf,5)[1]; gcharlocal(gc,chi,1) gcharlocal(gc,chi,2) gcharlocal(gc,chi,pr) bnf = bnfinit(x^2+1,1); pr3 = idealprimedec(bnf,3)[1]; pr5 = idealprimedec(bnf,5)[1]; gc = gcharinit(bnf,[pr3,2;pr5,3]); round(gc.cyc) pr2 = idealprimedec(bnf,2)[1]; pr13 = idealprimedec(bnf,13)[1]; chi = gcharidentify(gc,[1,pr2,pr13],[[1,0],-0.446666666,0.3097498124]); \\chi = [1,1,1]~; loc = gcharlocal(gc,chi,pr3,&bid); bid.cyc charorder(bid.cyc,loc[1..-2]) loc[#loc] loc = gcharlocal(gc,chi,pr5,&bid); bid.cyc charorder(bid.cyc,loc[1..-2]) loc[#loc] print("doc gcharlog"); bnf = bnfinit(x^3-x^2+5*x+1,1); gc = gcharinit(bnf,3); round(gc.cyc) chi = [1,1,0,-1]~; f = gcharduallog(gc,chi); pr = idealprimedec(bnf,5)[1]; v = gcharlog(gc,pr); type(v) exponent(exp(2*I*Pi*f*v) - gchareval(gc,chi,pr)) < -100 print("doc gchareval"); bnf = bnfinit(x^2-5); gc = gcharinit(bnf,1); chi = [1]~; pr = idealprimedec(bnf,11)[1]; s = -sign(gchareval(gc,chi,pr,0)); a = gchareval(gc,chi,pr); if(s<0, a=conj(a)); round(10^10*a) b = s*gchareval(gc,chi,pr,0); round(10^10*b) exponent(a - exp(2*Pi*I*b)) < -125 print("prime sort bug"); bnf = bnfinit(x,1); p2 = idealprimedec(bnf,2)[1]; p3 = idealprimedec(bnf,3)[1]; gc = gcharinit(bnf,[p3,1;p2,2]); chi = [1]~; #gcharlocal(gc,chi,p2) == 2 print("LLL erase bug"); bnf = bnfinit(x^8 + 3804*x^6 - 3808*x^5 + 3603342*x^4 - 7212384*x^3 + 5416900*x^2 - 1808808*x + 226578, 1); gc = gcharinit(bnf,1); chi = [0,0,0,1,0,0,0,0,0,0]~; A = idealprimedec(bnf,2)[1]; B = idealprimedec(bnf,5)[1]; AB = idealmul(bnf,A,B); vA = gchareval(gc,chi,A,0); vB = gchareval(gc,chi,B,0); vAB = gchareval(gc,chi,AB,0); v = vAB - vA - vB; v -= round(v); exponent(v) < -125 print("bestS fix"); bnf = bnfinit(x^2+5,1); gc = gcharinit(bnf,1); round(gc.cyc) chi = [1,0]~; gchareval(gc,chi,idealprimedec(bnf,2)[1],0) != 0 gchareval(gc,chi,idealprimedec(bnf,3)[1],0) != 0 print("bug #2373"); a = 'a; bnf=bnfinit(a^6-3*a^5+19*a^4-31*a^3+121*a^2-143*a+307); gc=gcharinit(bnf,46); pr=idealprimedec(bnf,37723331332351742373432849364353603676875519354218200736622011846348771299073); gcharlog(gc,pr[2]); print("over Q"); bnf = bnfinit(y,1); pr = idealprimedec(bnf,5)[1]; gc = gcharinit(bnf,1); chi = [1]~; logchi = gcharduallog(gc,chi) logx = gcharlog(gc,pr); round(10^6*logx) gchareval(gc,chi,pr) round(10^6 * exp(2*Pi*I * (logchi * logx))) gcharlocal(gc,chi,1) round(10^6*gcharlocal(gc,chi,pr)) abs(gcharalgebraic(gc)) gcharalgebraic(gc,[[1,1]]) gcharconductor(gc,chi) gcharisalgebraic(gc,chi,&pq) pq gcharidentify(gc,[1],[[0,I]]) gc = gcharinit(bnf,4); chi = [1]~; logchi = gcharduallog(gc,chi) logx = gcharlog(gc,pr); round(10^6*logx) gchareval(gc,chi,pr) round(10^6 * exp(2*Pi*I * (logchi * logx))) gcharlocal(gc,chi,1) round(10^6*gcharlocal(gc,chi,pr)) pr2 = idealprimedec(bnf,2)[1]; round(10^6*gcharlocal(gc,chi,pr2)) abs(gcharalgebraic(gc)) gcharalgebraic(gc,[[1,0]]) gcharconductor(gc,chi) gcharisalgebraic(gc,chi,&pq) pq gcharidentify(gc,[1],[[0,I]]) localprec(300); gc = gcharnewprec(gc); print("bug in length checks"); bnf = bnfinit(x^2-5,1); pr2 = idealprimedec(bnf,2)[1]; pr3 = idealprimedec(bnf,3)[1]; pr5 = idealprimedec(bnf,5)[1]; gc = gcharinit(bnf,[pr2,2;pr3,1;pr5,1]); chi = [0,0,0,1]~; gcharlocal(gc,chi,1) L = lfuncreate([gc,chi]); print("bad inputs"); gcharinit([],1) gcharinit(bnfinit(x),[]) gcharinit(bnfinit(x),[1,[]]) gcharidentify([],[1],[[0,0]]); gcharidentify('gc,[1],[[0,0]]); bnf = bnfinit(x^4 - x^3 + 3*x^2 + 2*x + 1, 1); gc = gcharinit(bnf, 1); pr = idealprimedec(bnf, 101)[1]; gcharidentify(gc,[1,1],[[0,0],[0,0]]); gcharidentify(gc,[1,0],[[0,0],[0,0]]); gcharidentify(gc,[1,3],[[0,0],[0,0]]); gcharidentify(gc,[1,[]],[[0,0],[0,0]]); gcharidentify(gc,[1,'x],[[0,0],[0,0]]); gcharidentify(gc,[[]],[1.]); gcharidentify(gc,[pr],[1+O(3^7)]); gcharidentify(gc,[pr],['x]); gcharidentify(gc,[1],['x]); gcharidentify(gc,[1],[[]]); gcharidentify(gc,[1],[[0.1,0]]); gcharidentify(gc,[1],[[0,O(3^7)]]); gcharidentify(gc,[1],[0,0]); gc = gcharinit(bnf, pr); gcharidentify(gc,[pr],[0]); tmp = gc[4]; gc[4] = 0; gcharnewprec(gc); gc[4] = tmp; tmp = gc[1]; gc[1] = 0; gcharnewprec(gc); gc[1] = tmp; tmp = gc[8]; gc[8] = 0; gcharnewprec(gc); gc[8] = tmp; tmp = gc[8][1][2]; gc[8][1][2] = 2^20; gcharidentify(gc,[],[]); gc[8][1][2] = tmp; gc = gcharinit(x^2+1,1); gcharalgebraic(gc,0); gcharalgebraic(gc,[1..10]); gcharalgebraic(gc,[0]); gcharalgebraic(gc,[[]]); gcharalgebraic(gc,[[0,[]]]); gcharalgebraic(gc,[[[],0]]); gchareval(gc,O(3^7),1,0); gchareval(gc,[0,O(3^7)],1,0); chareval(gc,[0]~,1); gcharisalgebraic(gc,[1]); \\ regression tests gc = gcharinit(bnfinit(x^2-x-276,1), [2,[0,1]]); gc = gcharinit(x^2-2,1); gcharalgebraic(gc,[]) gc = gcharinit(x^3-x-1,1); gcharalgebraic(gc,[[1,1]]) bnf = bnfinit(x^2-5); gc = gcharinit(bnf,[4,[1,0]]); pr = idealprimedec(bnf,2)[1]; gcharlocal(gc,[0,1]~,0) gcharlocal(gc,[0,1]~,3) gcharlocal(gc,[0,1,O(5^2)]~,1) \\don't put tests after the errors pari-2.17.2/src/test/in/memory0000644000175000017500000000035714676526175014623 0ustar billbilldefault(parisize, 1<<20); vector(100000, k, k); \\ #1881 default(parisize, 100kB); default(parisize, 100KB); default(parisize, 1MB); \\ ERRORS default(parisize, 1kb); default(parisize, 1nB); default(parisize, 1gB); default(parisize, 1mB); pari-2.17.2/src/test/in/export0000644000175000017500000000152714567450071014622 0ustar billbillexport(f=i->i^2+1); parsum(i=1,1,f(i)) parsum(i=1,10,f(i)) \\ errors f(i)=z=3;i^2+1; export(f); parsum(i=1,10,f(i)) f(i)=local(z);i^2+1; export(f); parsum(i=1,10,f(i)) f(i)=local(z=3);i^2+1; export(f); parsum(i=1,10,f(i)) world="sequential"; export(world="parallel"); inline(prpar,prseq,prsin) prsin()=parfor(i=1,1,world,E,return(E)); prseq()=parfor(i=1,3,1,E,if(i==3,return(world))); prpar()=parfor(i=1,3,world,E,if(i==3,return(E))); prsin() prseq() prpar() parfor(i=3,3,prsin(),E,if(i==3,return(E))) parfor(i=3,3,prseq(),E,if(i==3,return(E))) parfor(i=3,3,prpar(),E,if(i==3,return(E))) parfor(i=1,3,prsin(),E,if(i==3,return(E))) parfor(i=1,3,prseq(),E,if(i==3,return(E))) parfor(i=1,3,prpar(),E,if(i==3,return(E))) parfor(i=1,3,1,E,if(i==3,return(prsin()))) parfor(i=1,3,1,E,if(i==3,return(prseq()))) parfor(i=1,3,1,E,if(i==3,return(prpar()))) pari-2.17.2/src/test/in/ffisom0000644000175000017500000001174714567450071014571 0ustar billbillfpisom2(l,P,Q)= { my(L, x=variable(P)); L = polrootsmod(P, [l,subst(Q,x,MAXVARN)]); subst(lift(L),MAXVARN,x)*Mod(1,Q); } fptest(l,P,Q)= [ if(subst(P,x,c),error([a,l,P,Q])) | c<-fpisom2(l,P,Q)]; print("-------------e=0--------------"); fptest(13,x^4+2*x^2+2*x+1,x^4+2*x^3+2*x^2+1); fptest(131,x^10+126*x^5+78,x^10+128*x^5+70); fptest(11,x^3+2*x^2+6*x+7,x^3+5*x^2+3*x+6); fptest(1009,x^17+x+25,x^17+42*x^16+61*x^15+952*x^14+113*x^13+398*x^12+694*x^11+238*x^10+465*x^9+308*x^8+545*x^7+145*x^6+79*x^5+896*x^4+515*x^3+63*x^2+808*x+1008); fptest(1009,x^16+x^15+964*x^14+911*x^13+650*x^12+165*x^11+451*x^10+957*x^9+342*x^8+616*x^7+212*x^6+595*x^5+130*x^4+63*x^3+340*x^2+537*x+694,x^16+11); fptest(1009,x^20+595*x^19+863*x^18+194*x^17+127*x^16+364*x^15+31*x^14+869*x^13+422*x^12+663*x^11+669*x^10+28*x^9+9*x^8+937*x^7+35*x^6+292*x^5+302*x^4+441*x^3+863*x^2+118*x+1,x^20+919*x^19+582*x^18+634*x^17+881*x^16+563*x^15+966*x^14+892*x^13+894*x^12+40*x^11+322*x^10+961*x^9+431*x^8+172*x^7+641*x^6+599*x^5+1001*x^4+718*x^3+582*x^2+851*x+1); fptest(23,x^20+x+5,x^20+4*x^19+15*x^18+17*x^17+6*x^16+3*x^15+8*x^14+16*x^13+11*x^12+20*x^11+x^10+20*x^9+11*x^8+16*x^7+8*x^6+3*x^5+6*x^4+17*x^3+15*x^2+4*x+1); fptest(10007,x^30+9557*x^29+7812*x^28+7090*x^27+7645*x^26+4110*x^25+3307*x^24+5763*x^23+7900*x^22+3872*x^21+8123*x^20+4076*x^19+3265*x^18+3777*x^17+3398*x^16+5674*x^15+4018*x^14+6820*x^13+6479*x^12+984*x^11+5652*x^10+1129*x^9+7573*x^8+1822*x^7+837*x^6+4169*x^5+4787*x^4+1616*x^3+5185*x^2+2649*x+1933,x^30+x+2); fptest(67108879,x^30+67107859*x^29+502860*x^28+41752426*x^27+47923483*x^26+56252217*x^25+29702433*x^24+34566275*x^23+43724662*x^22+43031233*x^21+6098024*x^20+7989587*x^19+27885185*x^18+50348895*x^17+46982824*x^16+27081672*x^15+64032686*x^14+24948096*x^13+22483934*x^12+62577008*x^11+33925741*x^10+21192636*x^9+60947997*x^8+24913164*x^7+28577178*x^6+19817925*x^5+12532882*x^4+28467302*x^3+18972253*x^2+4366256*x+32457808,x^30+50150808*x^29+63186895*x^28+49093281*x^27+9998922*x^26+33903391*x^25+64572368*x^24+18465285*x^23+9365844*x^22+146044*x^21+52005244*x^20+51914117*x^19+50853399*x^18+47731827*x^17+63045151*x^16+30915147*x^15+52060592*x^14+54056376*x^13+50213837*x^12+47827172*x^11+33322080*x^10+37183875*x^9+59905379*x^8+12524247*x^7+53983516*x^6+18456131*x^5+47473382*x^4+30607833*x^3+17662487*x^2+66659374*x+2497577); print("-------------e=1--------------"); fptest(11,x^11+x^9+9*x^7+3*x^6+8*x^5+7*x^4+5*x^3+x^2+10*x+3,x^11+10*x+1); fptest(7,x^14+x+4,x^14+5*x^8+5*x^7+x^2+2*x+5); fptest(5,x^30+4*x^26+4*x^25+3*x^20+3*x^16+3*x^12+3*x^8+4*x^6+3*x^4+x^2+x+4,x^30+x^3+x+3); fptest(7,x^35+2*x^2+x+6,x^35+2*x^28+6*x^24+3*x^23+4*x^22+4*x^21+3*x^17+5*x^16+2*x^15+x^14+5*x^13+x^12+4*x^11+4*x^10+5*x^9+4*x^8+3*x^7+2*x^6+6*x^5+3*x^4+x^3+2*x^2+2*x+3); print("-------------e=2--------------"); fptest(2,x^4+x+1,x^4+x^3+1); fptest(5,x^25+2*x^3+3*x+2,x^25+2*x^19+3*x^17+4*x^16+2*x^15+x^14+x^13+3*x^12+2*x^11+4*x^10+2*x^8+4*x^7+4*x^5+2*x^4+3*x^3+2*x+2); fptest(3,x^18+x^3+2*x+1,x^18+x^17+2*x^16+2*x^15+x^14+x^13+x^12+x^11+x^10+2*x^9+x^7+2*x^5+x^4+2*x^3+1); fptest(2,x^20+x^3+1,x^20+x^14+x^13+x^10+x^7+x^5+x^4+x^3+x^2+x+1); print("-------------e=3--------------"); fptest(2,x^8+x^4+x^3+x+1,x^8+x^6+x^5+x^3+1); fptest(3,x^27+x^5+x^3+x^2+2*x+2,x^27+x^25+2*x^24+x^23+x^22+x^20+x^17+2*x^15+2*x^13+x^12+2*x^11+2*x^10+x^9+2*x^8+x^7+2*x^6+2*x^5+2*x^4+2); fptest(2,x^40+x^5+x^4+x^3+1,x^40+x^38+x^37+x^36+x^35+x^34+x^32+x^31+x^30+x^29+x^28+x^25+x^23+x^19+x^16+x^15+x^13+x^11+x^10+x^9+x^7+x^5+x^3+x^2+1); print("-------------e>=4--------------"); fptest(2,x^16+x^15+x^14+x^12+x^7+x^6+x^5+x^2+1,x^16+x^5+x^3+x+1); fptest(2,x^32+x^7+x^3+x^2+1,x^32+x^29+x^28+x^27+x^25+x^24+x^22+x^18+x^17+x^15+x^14+x^13+x^11+x^5+x^4+x^3+1); fptest(2,x^64+x^4+x^3+x+1,x^64+x^59+x^57+x^56+x^53+x^52+x^51+x^48+x^47+x^46+x^45+x^42+x^40+x^39+x^35+x^33+x^32+x^30+x^29+x^26+x^25+x^24+x^22+x^21+x^20+x^18+x^17+x^14+x^13+x^11+x^10+x^7+x^5+x^2+1); fptest(2,x^48+x^5+x^3+x^2+1,x^48+x^46+x^45+x^43+x^42+x^40+x^39+x^38+x^37+x^35+x^34+x^33+x^31+x^29+x^25+x^19+x^18+x^16+x^12+x^9+x^4+x^3+1); print("----------large p---------------"); fptest(300007,x^29+111826*x^28+192245*x^27+118259*x^26+116591*x^25+90193*x^24+179240*x^23+218526*x^22+105853*x^21+39775*x^20+120877*x^19+141649*x^18+95990*x^17+253141*x^16+113157*x^15+174998*x^14+231363*x^13+45405*x^12+279688*x^11+260746*x^10+295341*x^9+186647*x^8+1286*x^7+5846*x^6+226308*x^5+155249*x^4+161003*x^3+892*x^2+124319*x+45791 ,x^29+144375*x^28+258947*x^27+2448*x^26+213576*x^25+275912*x^24+295000*x^23+16021*x^22+62890*x^21+223177*x^20+133874*x^19+291070*x^18+268346*x^17+231097*x^16+27675*x^15+181579*x^14+144969*x^13+37193*x^12+236074*x^11+44381*x^10+87819*x^9+180121*x^8+195512*x^7+82624*x^6+113318*x^5+67595*x^4+26623*x^3+13359*x^2+191742*x+143596); print("----------huge p---------------"); p=nextprime(3^64);P=ffinit(p,19);Q=poltschirnhaus(P);fptest(p,P,Q); p=nextprime(3^66);P=ffinit(p,19);Q=poltschirnhaus(P);fptest(p,P,Q); p=1208925819614629174706189; P=x^3+154950186819311566804335*x^2+793256884583803289109038*x+629557146926040851399629; Q=factormod(polcyclo(13),p)[3,1]; fptest(p,P,Q); pari-2.17.2/src/test/in/subgroup0000644000175000017500000000077714567450071015155 0ustar billbillG=[53835600, 29] do(h,G)=print(mathnf(concat(h,matdiagonal(G)))); forsubgroup(h=G,[5], do(h,G)) forsubgroup(h=G,[10], do(h,G)) subgrouplist(G,[12]) forsubgroup(h=[],[1],print(h)) forsubgroup(h=[],[2],print(h)) forsubgroup(h=[],2,print(h)) forsubgroup(h=[2,3],2,print(h)) forsubgroup(h=matid(2),2,print(h)) default(debug,5); #subgrouplist(vector(4,i,2)) default(debug,0); subgrouplist(1) subgrouplist([2,2],[2]~) subgrouplist([2,2],-1) p=10^50+151;q=10^51+121; G=[2*3*p*q]; subgrouplist(G,3) subgrouplist(G,[3]) pari-2.17.2/src/test/in/ellisomat0000644000175000017500000000731514676526175015305 0ustar billbilldefault(parisize,"14M"); \\ overflows 12M X;Y; eq(E) = Y^2+E.a1*X*Y+E.a3*Y - (X^3 + E.a2*X^2 + E.a4*X + E.a6); checkiso(E1,E2,iso)= { my(EE1 = eq(E1)); my([x,y,z]=substvec(iso,['x,'y],Mod([X,Y], EE1))); my(z2=sqr(z),z4=sqr(z2),z6=z2*z4); lift(y^2+E2.a1*x*y*z+E2.a3*y*z*z2 - (x^3+E2.a2*x^2*z2+E2.a4*x*z4+E2.a6*z^6)); } checkisov(E,V)= { apply(v->my(E2=ellinit(v[1])); checkiso(E,E2,v[2]), V); } check(V)= { for(i=1,#V, my(E=ellinit([V[i]])); my(Et=ellminimalmodel(elltwist(E,ellminimaltwist(E,1)))); my([L,M]=ellisomat(Et), [L2, M2] = ellisomat(Et,, 1)); if (M!=M2, error("ellisomat:",i)); print(V[i],":",M,":",checkisov(Et,L))); } check([-2^15,-11^2,-11*131^3,-17^2*101^3/2,-17*373^3*2^-17,-96^3,-7*11^3,-7*137^3*2083^3,-960^3,-5280^3,-640320^3]) check([0,1728,-3375, 8000, 54000, 287496, -12288000, 16581375]) check([9938375/21952, 111284641/50625, -10218313/17576, -25/2]); ellisomat(ellinit([0,-1,1,-10,-20])) ellisomat(ellinit([1,0,1,4,-6]),2) ellisomat(ellinit([1,0,1,4,-6]),3) chk(E)= { my([L,M]=ellisomat(E));print(M);apply(l->checkiso(E,ellinit(l[1]),l[2]),L); } nf=nfinit(phi^2-phi-1); chk(ellinit([0,1,phi,-47*phi+31,560*phi-803],nf)) chk(ellinit([phi+1,1,phi+1,6*phi-1,13*phi+2],nf)) nf=nfinit(a^2-2); chk(ellinit([a,-1,0,18,46],nf)) ellisomat(ellinit([-824740032823875,9115932407325507114750],nfinit(y-16581375)),1)[2] E=ellinit([-1880854563/4225,6682049310818/274625]); ellisomat(E,,1)[2] E=ellinit([-1880854563/4225,6682049310818/274625],nfinit(a^2+1)); ellisomat(E,,1)[2] my(s=7,t=(48*s^2+32)/(s^2-2));E=ellinit(ellfromj(t^3/(t+16)),bnfinit(a^2-2)); ellisomat(E,,1)[2] E=ellinit([1,a-1,a+1,2510*a-4889,87171*a-107201],nfinit(a^2-a+3)); ellisomat(E,,1)[2] \\ From Barinder Banwait: nf=nfinit(w^2-5); E=ellinit([95673435586560*w - 213932305612800],nf); ellisomat(E,,1)[2] E=ellinit([184068066743177379840*w - 411588709724712960000],nf); ellisomat(E,,1)[2] E=ellinit([1,0,1,4,-6]); ellisotree(E) ellisotree(ellisomat(E,2,1)) ellisotree(ellisomat(E,2)) ellisotree(ellisomat(E,3,1)) ellisotree(ellisomat(E,,1)) \\ CM case E=ellinit([8000],nfinit(a^2+2)); ellisomat(E) ellisomat(E,2)[2] \\ hard cases K = bnfinit(t^4+20*t^2+16,1); E = ellinit([-567/16*t^3-1377/8*t^2+81/4*t-324,1215/2*t^3-3726*t^2+972*t-3726],K); ellisomat(E,,1)[2] \\ https://www.lmfdb.org/EllipticCurve/4.4.1600.1/1.1/a/1 K = nfinit(Polrev([4, 0, -6, 0, 1],t)); E = ellinit([Polrev([0,-1,0,1/2],t),Polrev([-1,-1,0,0],t),Polrev([-1,-2,1/2,1/2],t),Polrev([-304,-284,51/2,85/2],t),Polrev([-2650,-2911,589/2,951/2],t)], K); ellisomat(E,,1)[2] \\ https://www.lmfdb.org/EllipticCurve/4.4.1600.1/16.1/a/1 K = nfinit(Polrev([4, 0, -6, 0, 1],t)); E = ellinit([Polrev([0,-2,0,1/2],t),Polrev([-2,-1,1/2,1/2],t),Polrev([0,0,0,0],t),Polrev([60,-72,-12,14],t),Polrev([-34,44,8,-9],t)], K); ellisomat(E,,1)[2] \\ https://www.lmfdb.org/EllipticCurve/4.4.1600.1/81.1/a/1 K = nfinit(Polrev([4, 0, -6, 0, 1],t)); E = ellinit([Polrev([0,-2,0,1/2],t),Polrev([-2,-1,1/2,1/2],t),Polrev([1,-1,0,1/2],t),Polrev([3,1,-7/2,-3/2],t),Polrev([13,6,-35/2,-15/2],t)], K); ellisomat(E,,1)[2] \\ https://www.lmfdb.org/EllipticCurve/4.4.1600.1/81.2/b/2 K = nfinit(Polrev([4, 0, -6, 0, 1],t)); E = ellinit([Polrev([0,-1,0,1/2],t),Polrev([1,1,0,-1/2],t),Polrev([-1,1,1/2,0],t),Polrev([5,6,-3/2,-3/2],t),Polrev([6,7,-3/2,-3/2],t)], K); ellisomat(E,,1)[2] \\ https://www.lmfdb.org/EllipticCurve/4.4.2304.1/9.1/a/1 K = nfinit(Polrev([1, 0, -4, 0, 1],t)); E = ellinit([Polrev([-2,-4,1,1],t),Polrev([0,1,0,0],t),Polrev([0,1,0,0],t),Polrev([-4780,9170,1265,-2463],t),Polrev([163923,-316598,-43876,84852],t)], K); ellisomat(E,,1)[2] \\ ERRORS ellisomat(ellinit([-824740032823875,9115932407325507114750],nfinit(x-16581375))) ellisomat(ellinit([-824740032823875,9115932407325507114750],nfinit(y-16581375))) pari-2.17.2/src/test/in/zetahurwitz0000644000175000017500000000174114760123736015677 0ustar billbillcheck(a,b)=my(c=abs(a-b)); if(!c,-oo, ceil(log(c)/log(10))); f(s,x)=check(zetahurwitz(s,x)+zetahurwitz(s,x+1/2), 2^s*zetahurwitz(s,2*x)); f(Pi,Pi) f(Pi,Pi+I*log(2)) check(zetahurwitz(Pi,1),zeta(Pi)) s = Pi+I*log(2); check(zetahurwitz(s,1), zeta(s)) check(zetahurwitz(s,3), zeta(s)-1-1/2^s) check((zetahurwitz(s,1/4)-zetahurwitz(s,3/4))/4^s, lfun(-4,s)) check(zetahurwitz(-3.4,1), zeta(-3.4)) check(zetahurwitz(2.1,1,2), zeta''(2.1)) zetahurwitz(2, 21) zetahurwitz(2, I, 18) zetahurwitz(7+O(7^5),1) zetahurwitz(7+O(7^5),2) zetahurwitz(3+O(2^5),1/2) zetahurwitz(3+O(2^5),1/4) zetahurwitz(3,2+O(5^5)) zetahurwitz(-2.3,Pi+I*log(2)) zetahurwitz(-1+x^2,1) zetahurwitz(1+x + O(x^7),2) zetahurwitz(x,1+x) zetahurwitz(x,2) zetahurwitz(x,2,1) zetahurwitz(4,2^20) zetahurwitz(4,2^100) zetahurwitz(4,2.^128) zetahurwitz(-1,1) zetahurwitz(-2,I) zetahurwitz(1/2+100000*I,1/2) zetahurwitz(2,20*I) \\ ERRORS zetahurwitz(1,Pi) zetahurwitz(1+O(x),1) zetahurwitz(O(2)+x,1) zetahurwitz(y+x,1) zetahurwitz([],[]) pari-2.17.2/src/test/in/nf0000644000175000017500000001107514676526175013715 0ustar billbillnfinit(factor(polzagier(9,5))[2,1],3).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]),4).disc nf=nfinit(y^5-4*y^3+2*y+11); funs = [nfelttrace, nfeltnorm, (nf,x)->nfeltpow(nf,x,2),\ (nf,x)->nfeltpow(nf,x,-1), (nf,x)->nfbasistoalg(nf,x),\ (nf,x)->nfalgtobasis(nf,x)]; okmat = [2,3,4]; ok(x,okmat)= okmat || type(x) != "t_MAT"; v = [4/3, -1, y^2+y+1, Mod(y,nf.pol),Mod(1/2,nf.pol),[1,2,3,4,5]~,[3,3;y,2]]; try1(f, okmat) = { for (j=1,#v, if (!ok(v[j],okmat), next); print( f(nf, v[j])) ); } for (i = 1, #funs, try1(funs[i], setsearch(okmat, i))) funs = [nfeltadd, nfeltdiv, nfeltdiveuc, nfeltdivrem, nfeltmod, nfeltmul]; okmat = [2,6]; try2(f, okmat) = { for (i=1, #v, if (!ok(v[i],okmat), next); for (j=1,#v, if (!ok(v[j],okmat), next); print( f(nf, v[i],v[j]) ))); } for (i = 1, #funs, try2(funs[i], setsearch(okmat, i))); nfisincl(nfinit(x-1),y) p=x^2+3;nfbasis([p, factor(poldisc(p))]) P = [13,73,89]; TP = [x^4-x^3+10558*x^2-2169592*x+195873967, P]; nfbasis(TP) nfbasis(TP,&D) D sqrtint(abs(D / vecprod([p^valuation(D,p) | p <-P]))) \\#1158 nf=nfinit(x^2+x+1); nfinit(nf) \\#2277 nfeltdiv(nf, 0, 1+x/2) K=nfinit([x^5-x^4+x^3+100*x+20,[1,x,x^2-x,1/2*x^4-1/2*x^3+1/2*x^2+40,x^3-x^2+x]], 4); K.index K=nfinit([x^5+9*x^4+851*x^3+18890*x^2+252376*x+529348, 39820], 4); nfcertify(K) nf=nfinit( [ x^7 + 2539107, [43] ] ); \\ #1973 g=polcyclo(13); f=x^12-2*x^11+17*x^10-73*x^9+198*x^8-578*x^7+1533*x^6-3404*x^5+5716*x^4-8260*x^3+18652*x^2-25578*x+15601; nfisincl(f,g) \\#1921 K=nfinit('x^2-2);L=nfinit('x^4-2); nfisincl(K,L) nfisincl(K.pol,L) nfisincl(K,L.pol) nfisincl(x^3-21*x-35,x^6-48*x^4-56*x^3+453*x^2+840*x+62) \\#2023 nfisincl(x^3-11*x^2+42*x-49,polcompositum(x^3-x-1,x^7-x-1)[1]) nfisincl(x^3-11*x^2+42*x-49,x^6+12*x^5+60*x^4+80*x^3-1860*x^2-12108*x-18821) \\#2041 nfisincl(y^2 + 1, z^4 + 1) nfisincl(x^5-x^4+x^3-2*x^2+3*x-1,x^20+x^15+x^10+x^5+1) \\#2022 nfisisom(K,x^2-8) nfisisom(x^2-8,K) nfisisom(nfinit(y^2 + 1), z^2 + 1) K = nfinit(x^2 + 1); nfisisom(K, y^2 + 1); K.pol nfeltissquare(K, -1) nfeltissquare(K, -1, &t) t nfeltissquare(K, -2) nfeltissquare(K, 4) nfeltissquare(K, 4, &t) t nfeltispower(K, x, 3) nfeltispower(K, x, 3, &t) t nfeltispower(K, -2, 3) nfeltispower(K, 8, 3) nfeltispower(K, 8, 3, &t) t K = nfinit(x); nfeltissquare(K, -2) nfeltissquare(K, 4) nfeltissquare(K, 4, &t) t nfeltispower(K, -2, 3) nfeltispower(K, 8, 3) nfeltispower(K, 8, 3, &t) t \\#2144 nfisincl(x^3+9,x^6+2187) nfisincl(x^3+9*27,x^6+2187*3^6) nfisincl(x^3+9,x^6+2187,1) nfisincl(x^3+9*27,x^6+2187*3^6,1) nfisincl(x^3+9,x^3+9) nfisincl(x^3+9,x^3+9,1) p=10^62+447; q=10^42+63; nf=nfinit([polcompositum(x^2-p,x^2-q,2), [2,p,q]]); idealprimedec(nf,25339)[1].gen \\ overflow in get_norm \\ test old-style nf.zk K=nfinit(x^2+23); K[7] /= 2; nfbasistoalg(K,[0,1]~) nfalgtobasis(K,x) K.zk nfinit(x, 3)[2] nfinit(x, 1)[2] nfinit(1/2*x + 3/5, 3)[2] \\ #2169 nfinit(x^12-3*x^11+7*x^10-6*x^9+58*x^8-49*x^7+529*x^6-653*x^5+404*x^4-54*x^3-5711*x^2+2581*x+7009); \\ #2173 nfinit(x^10-3*x^9+39*x^8-66*x^7+527*x^6-201*x^5+3149*x^4+1827*x^3+12852*x^2+8563*x+29809); nfinit(x^16-4*x^15+8*x^14-8*x^13-x^12+14*x^11-26*x^10+12*x^9+84*x^8-166*x^7+246*x^6-376*x^5+382*x^4-330*x^3+282*x^2-146*x+29); \\ #2453 A = nfinit(x^2+1); type(A.p) B = nfinit([x^2+1,[1,x],[2]]); type(B.p) \\ ERRORS: keep at end of file nfinit([y^3+2,[1,x]]) nfinit([y^3+2,[1,x,x^2]]) nfinit([y^3+2,[1,y^5,y]]) nfdisc([y^2+2,matid(3)]) nfdisc([2*y^2+1,matid(3)]) nfdisc([y^2+2,""]) nfnewprec(x) nfnewprec(quadgen(5)) nfnewprec(vector(5)) nfnewprec(vector(6)) nfnewprec(vector(8)) nfnewprec(vector(9)) nfnewprec(vector(12)) nfnewprec(vector(16)) nfisincl(y^2 + 1, z^4 + z^2 + 1) nfisisom(x,x^0) nf=nfinit('a^2+1); idealhnf(nf,3,('a^2+1)*Mod(1,3)) nfalgtobasis(nf,['a,'a]~) \\ # 2213 nfisincl(x^2-2^5,nfinit(x^4-2)) \\ # 2214 (duplicate of 2213) nfisincl(x^9 - 3*x^6 - 6*x^3 - 1,nfinit(x^18 - 3*x^15 + 15*x^12 + 20*x^9 + 33*x^6 + 6*x^3 + 1)) nfeltispower(nfinit(x^4-2),x,2^64-100) \\ #2385 K=nfinit(x^2+1357*x+3299); idealcoprime(K,10,60) idealcoprime(K,10,10) K=nfinit(x^2+134*x+712); F=idealfactor(K, idealhnf(K, 2, 1/2*x+36)); idealchinese(K, [F, [1,1]], [1/2*x+32]) P=x^4-2*x^3-5100097469481115*x^2-198889183441538805903225*x+21641388126139219732345004536462;nfdisc(P) e=2^1000; Q=nfinit(x); nfeltnorm(Q, [2, e; 2, -e]) nfeltnorm(Q, [2/3, e; 6, 1-e; 15, 2*e+1; 1/5, 2*e-3]) nfeltnorm(Q, [-2, 1+e; 2, 1-e]) nfeltnorm(Q, Mat([1,1])) pari-2.17.2/src/test/in/character0000644000175000017500000000250714567450071015234 0ustar billbillG=[15,5]; chi=[1,1]; charker(G,chi) charconj(G,chi) charorder(G,chi) G=znstar(100,1); a=[1,0]; A=znconreylog(G,a); m=znconreyexp(G,a); charker(G,a) charker(G,A) charker(G,m) charpow(G,a,0) charpow(G,A,0) charpow(G,m,0) charpow(G,a,-2) charpow(G,A,-2) charpow(G,m,-2) charpow(G,a,3) charpow(G,A,3) charpow(G,m,3) charconj(G,a) charconj(G,A) charconj(G,m) charorder(G,a) charorder(G,A) charorder(G,m) b=[12,1]; B=znconreylog(G,b); n=znconreyexp(G,b); charmul(G,n,m) charmul(G,a,b) charmul(G,A,B) charmul(G,a,B) charmul(G,a,n) charmul(G,m,B) chardiv(G,n,m) chardiv(G,a,b) chardiv(G,A,B) chardiv(G,a,B) chardiv(G,a,n) chardiv(G,m,B) test(G)= { my(N = G.mod,D); print("* ",N); for(i=1,N, if(gcd(N,i)!=1,next); D = znchartokronecker(G,i);if (!D,next); D0 = znchartokronecker(G,i,1); print(i,": ",[D,D0]); chi = znconreylog(G,i); if (vector(N,j,kronecker(D,j)) != vector(N,j,chareval(G,chi,j,[-1,2])), error(D)) ); } test(G) test(znstar(8,1)) test(znstar(5,1)) test(znstar(1,1)) test(D) = { my([G,cyc]=znchar(D), C = znconreylog(G,cyc)); [cyc, C, znconreyexp(G,C), charorder(G,cyc)]; } test(1) test(5) test(Mod(1,5)) test(Mod(3,5)) G = znstar(100,1); test([G,13]) test([G,[0,19]~]) test([G,[2, [1,1]]]) \\ Errors znchar(0) znchar(2) znchar(3) znchar([]~) znchar([1,2,3]) znchar([1,2]) znchar([znstar(100,1), [1,2,3]]) pari-2.17.2/src/test/in/krasner0000644000175000017500000000107114567450071014740 0ustar billbillfilter_output(p, v) = { vecsort(vector(#v, j, if (type(v[j]) == type([]), my([D,e,f,d]=v[j]); [valuation(poldisc(D), p), e, f, d] , valuation(poldisc(v[j]), p))) , cmp); } do(p,N,flag)=filter_output(p, padicfields(p,N,flag)); p = 2; for (d = 2, 50, if (d%p, print(do(p,d,1)))) p = 3; for (d = 2, 50, if (d%p, print(do(p,d,1)))) do(2, 105, 1) do(5, 21, 1) do(23, 75, 1) do(23459, 18, 1) do(2, [8,12], 1) do(2^21+17, 30, 1) do(2^64+13, 8, 1) do(2^64+13, 2, 1) padicfields(2^64+13, 8, 2) do(2, 4, 1) do(2, 3, 0) padicfields(3,3) padicfields(5,5) pari-2.17.2/src/test/in/mf0000644000175000017500000005554014724330077013705 0ustar billbilldefault(parisize,"64M"); \\ overflows 62M getcache() Z4=znstar(4,1); Z5=znstar(5,1); Z8=znstar(8,1); vec(f)=mfcoefs(f,15); vec(mfeisenstein(2,[Z5,2])) vec(mfeisenstein(3,[Z5,2])) vec(mfeisenstein(2,[Z8,3],[Z8,5])) vec(mfeisenstein(3,[Z8,3],[Z8,5])) mfdim(mfinit([12,2],3)) mfdim(mfinit([225,2],3)) mfdim([10^9,4], 3) mfdim([10^9,1,Mod(3,4)], 3) mfdim([1,2],3) Th=1+2*sum(n=1,4,q^(n^2),O(q^20)); mf=mfinit([4,2]);mftobasis(mf,Th^4) mf=mfinit([4,3,[Z4,3]]);mftobasis(mf,Th^6) mf=mfinit([4,4]);mftobasis(mf,Th^8) mf=mfinit([4,5,[Z4,3]]);mftobasis(mf,Th^10) mf=mfinit([4,12],1); mfcoefs(mfinit(mf,0),10) mfcoefs(mf,10) mfcoefs(mf,5,2) D=q*eta(q)^24; mftobasis(mf,D+O(q^2),1) mftobasis(mf,D+O(q^3),1) mftobasis(mf,D+O(q^4),1) mftobasis(mf,D+O(q^5),1) v=mftonew(mf,D); [#v, v[1][1..2]] v2=concat(0,Vec(D)); mftobasis(mf,v2) mftobasis(mf,v2~) apply(mfdim, mfinit([1,0,0], 1)) apply(mfdim, mfinit([1,0,0])) apply(mfdim, mfinit([1,-1,0])) apply(mfdim, mfinit([1,-1,[]])) apply(mfdim, mfinit([1,-1,[1,1]])) apply(mfdim, mfinit([1,1,0],0)) apply(mfdim, mfinit([1,1,[1,1]],1)) mfdim([2,-1,-1]) mfdim([11,2,-1]) mfdim(mfinit([1,0,1], 1)) mfdim(mfinit([1,0,1])) mfdim(mfinit([4,0,-4], 1)) mfdim(mfinit([4,0,-4])) mfdim([1,0],1) mfdim([1,0]) mfdim([1,0,0],1) mfdim([1,0,0]) mfdim([1,0,1],1) mfdim([1,0,1]) mfdim([4,0,-4],1) mfdim([4,0,-4]) mfdim([4,0,[1,-4,-4,1]],1) mfdim([4,0,[1,-4,-4,1]]) N=7^3*13^3;mfdim([N,2,Mod(107,N)]) N=5^3*13^3;mfdim([N,2,Mod(101,N)]) N=5^3*17^3;mfdim([N,2,Mod(101,N)]) mf=mfinit([155,2],0); mfsplit(mf,,1) mfsplit(mf, 1)[2] mfsplit(mf, 2)[2] mfsplit(mf, 3)[2] mfsplit(mf, 4)[2] mffields(mfinit([104,4,104],0)) mffields(mfinit([35,4,Mod(11,35)],0)) L=mfinit([23,1,0],3); vector(#L,i,mfdim(L[i])) #mfbasis([23,1,-23],0) mfdim([23,1,0],3) mfdim([23,1,0],2) mfdim([23,1,-1],2) L=mfinit([35,2,0],0); #L mf=L[1]; #mfinit([296,1,0],0) mfadd(F,G) = mflinear([F,G],[1,1]); [f,g] = mfbasis(mf); mfcoefs(f,19) mfcoefs(g,19) vec(mfadd(f,g)) vec(mfmul(f,g)) vec(mflinear([f,g],[1,2])) mfcoefs(f,49) vec(mfhecke(mf,g,3)) f2=mfbd(f,2); vec(f2) vec(mfbd(f2,3)) vec(mftwist(f,-7)) vec(mfEk(0)) T=mfcusps(96) apply(x->mfcuspwidth(96,x),T) apply(x->mfcuspisregular([96,2,Mod(7,96)],x), T) apply(x->mfcuspisregular([96,1/2,Mod(7,96)],x), T) mfnumcusps(96) mfnumcusps(2^64) mfnumcusps(factor(6^64)) mfsturm([96,6]) mfdim([96,6],0) mfdim([96,6]) vec(mftraceform([1,0])) T=mftraceform([96,6],1); mfdescribe(T) mfdescribe(mflinear([T],[0])) [mfcoef(T,2), mfcoef(T,3)] vec(T) T=mftraceform([96,6]); [mfcoef(T,2), mfcoef(T,3)] vec(T) T=mftraceform([23,1,-23]); vec(T) T=mftraceform([52,1,Mod(3,52)]); vec(T) T=mftraceform([88,1,Mod(59,88)],0); vec(T) T=mftraceform([88,1,Mod(65,88)],0); vec(T) T=mftraceform([88,1,Mod(65,88)],1); vec(T) T=mftraceform([8,4,8],0); vec(T) T=mftraceform([15,2]); vec(T) T=mftraceform([15,4]); vec(T) mf = mfinit([15,4],1); mfparams(mflinear(mf,[1,0,1,0])) mf=mfinit([16,6]); B = mfbasis(mf); F = mflinear([B[7],B[8]],[4,7]); mfconductor(mf,F) V=mftonew(mf,F); for (i=1,#V,v=V[i];print([v[1],v[2],mfcoefs(v[3],9)])) mfisequal(F,mflinear([mfbd(v[3],v[2])|v<-V],vector(#V,k,1))) mf=mfinit([96,6],1);#mf[3] F=mflinear([mf[3][1],mf[3][2]],[4,7]); V=mftonew(mf,F); for (i=1,#V,v=V[i];print([v[1],v[2],mfcoefs(v[3],9)])) mfisequal(F,mflinear([mfbd(v[3],v[2])|v<-V],vector(#V,k,1))) checkmftonew(S,f) = { my(V = mftonew(S,f)); mfisequal(f,mflinear([mfbd(v[3],v[2])|v<-V],vector(#V,i,1))); } checkmftonew(mfinit([22,2],1),mfbd(mfbasis([11,2],0)[1],2)) checkspace(SN) = [checkmftonew(SN,f)|f<-mfbasis(SN)]; checkspace(mfinit([22,2],1)) checkspace(mfinit([48,2],1)) checkspace(mfinit([62,2],1)) checkspace(mfinit([36,4],1)) mfconductor(mf,F) #mfinit([96,6],2)[3] #mfinit([96,6],3)[2] mf=mfinit(mf,0);#mf[3] mfsplit(mf,,1) mfsplit(mf,,2) [poldegree(p) | p<-mffields(mf)] mfsplit(mf,1) mfsplit(mf,2) LC=mfeigenbasis(mf); for(i=1,#LC,print(concat(mfcoefs(LC[i],9), mfparams(LC[i])[4]))) f=LC[#LC]; vec(mfmul(f,f)) mfsturm(mf) F=mflinear(mfbasis(mf)[1..3],[4,-7,11]); mftobasis(mf,F) mfheckemat(mf,2) mfheckemat(mf,3) mfheckemat(mf, [9,15,25]) b = mfbasis(mf); for(i=1,#b,print(mfeval(mf,b[i],I/2))) D=mfDelta(); mfD = mfinit(D,1); mfeval(mfD,D,I/10) mfeval(mfD,D,1+2*I) mf23=mfinit([23,2],0);F=mfeigenbasis(mf23)[1]; mfcuspval(mf23,F,oo) mfcuspval(mf23,F,0) mfcuspval(mf23,F,1/2) \\ to make it identical in 32/64 bits round(mfeval(mf23,F,I/50) * 1e35) round(mfslashexpansion(mf23,F,[1,0;1,1],2,0) * 1e35) vec(mfdiv(mfpow(D,3),mfpow(D,2))) mfcoefs(D,0) \\ #2078 mfa = mfatkininit(mf,32); mfa[2] mfatkininit(mfinit([12,11,-3],0), 4)[2] vec(mfatkin(mfa,mf[3][1])) mfatkininit(mfinit([3,7,-3],0), 3)[2] L=[lfuninit(l,[3,4,0],1) | l<-concat(lfunmf(mf))]; vector(#L,i,lfun(L[i],2)) vector(#L,i,lfun(L[i],1)) vector(#L,i,lfun(L[i],0,1)) vector(#L,i,lfun(L[i],-1,1)) mf=mfinit([163,4],3); f=mfbasis(mf)[2]; mfeval(mf,f,I/400) real(mfeval(mf,f,1.5+I/400)) mf=mfinit([5,4],0); vF=mfeigenbasis(mf); #vF F=vF[1]; liftpol(mfcoefs(F, 9)) R=mfslashexpansion(mf,F,[1,0;1,1],10,0,¶ms); lift(bestapprnf(R*25,polcyclo(5,'t))) params mf=mfinit([11,2],1);F=mfbasis(mf)[1]; mfslashexpansion(mf,F,[1,0;0,1],5,0,¶ms) params mf=mfinit([44,3,-4],4);F=mfbasis(mf)[1]; mfslashexpansion(mf,F,[1,0;2,1],4,0,¶ms) params mf=mfinit([7,4,Mod(2,7)], 0); F=mfbasis(mf)[1]; mfslashexpansion(mf,F,[1,0;1,1],5,0,¶ms) params mf=mfinit([12,8],0);F=mfbasis(mf)[1]; mfslashexpansion(mf,F,[1,0;2,1],12,0) mfslashexpansion(mf,F,[1,0;2,1],12,1) mf=mfinit([12,7,-4],0);F=mfbasis(mf)[1]; mfslashexpansion(mf,F,[1,0;6,1],7,1,&A) A mf=mfinit([12,3,-4],0);F=mfbasis(mf)[1]; V=mfslashexpansion(mf,F,[1,1;4,5],4,1) mf=mfinit([12,3,-4],1); mfslashexpansion(mf,F,[1,1;4,5],4,1)==V mf=mfinit([4,7,-4]); B=mfbasis(mf); mfslashexpansion(mf,B[1],[0,-1;4,0],5,1,&A) A mf=mfinit([256,2]);f=mfeigenbasis(mf)[5]; mfslashexpansion(mf,f,[1,0;64,1],3,1,&A) A mf=mfinit([28,3/2],1);F=mfbasis(mf)[1];mf2=mfinit([56,3/2],1); mfslashexpansion(mf2,F,[1,0;1,1],5,0) mf=mfinit([96,2,8], 0); mfa = mfatkininit(mf,3); mfa[2] mfa[3] mfa = mfatkininit(mf,32); mfa[2] mfa[3] mf=mfinit([45,3,Mod(2,5)],0); mfa = mfatkininit(mf,9); factor(charpoly(mfa[2])) mfa[3] mf=mfinit([12,7,Mod(3,4)],0); mfatkineigenvalues(mf,3) mf=mfinit([24,3,-3],0); mfatkineigenvalues(mf,24) mf=mfinit([5,60],0); mfatkineigenvalues(mf,5) E4=mfEk(4); mf=mfinit([2,4]); mfslashexpansion(mf,E4,[0,-1;1,0],10,0) mf=mfinit([58,2], 0); F=mfeigenbasis(mf)[1]; round(mfslashexpansion(mf,F,[0,-1;58,0],10,0)) mf=mfinit([79,1,-79]); F=mfbasis(mf)[1]; 79 * lift(bestapprnf(mfslashexpansion(mf,F,[0,-1;1,0],5,0), x^2+79)) mf=mfinit([24,3,-3], 0); mfatkininit(mf,24)[2] [mf,F,coe]=mffromell(ellinit([-1,1]));coe vec(F) mfcoefs(F,6,2) [mf,F,coe]=mffromqf(2*matid(10));coe vec(F) mfcoefs(F,6,2) [mf,F,coe]=mffromqf(2*matid(2),x^4-6*x^2*y^2+y^4); vec(F) [mf,F,coe]=mffromqf(Mat); vec(F) [mf,F,coe]=mffromqf(2*matid(2),(x+I*y)^3); vec(F) [mf,F,coe]=mffromqf(2*matid(2),3); vec(F) mfwt1all(N)= { my(mf=mfinit([N,1,0],1)); if (#mf, print(N,": ", vector(#mf, i, my(v = mf[i][3], [G,c] = mf[i][1][3]); [znconreyexp(G,c), vector(#v,j,lift(vec(v[j])))]))); } for(N=1,150,mfwt1all(N)); for(N=1,150,print1([N,mfdim([N,1,-1],1),mfdim([N,1,-1],0)]," ")); mfdim([23,1,0]) mfdim([23,1,0],0) mfdim([23,1,0],1) mfdim([23,1,0],2) mfdim([23,1,0],3) mfdim([46,1,0],2) G=znstar(23,1); w=[[G,v] | v<-chargalois(G)]; mfdim([23,1,w],0) mfdim([23,1,w],1) mfdim([23,1,w],2) mfdim([96,2,-1],0) mfdim([96,2,-1],1) mfdim([96,2,-1],2) mfdim([96,2,-1],3) mfdim([96,2,-1],4) mfdim([96,2,0],0) mfdim([96,2,0],1) mfdim([96,2,0],2) mfdim([96,2,0],3) mfdim([96,2,0],4) G=znstar(96,1); w=[[G,v] | v<-chargalois(G)]; mfdim([96,2,w],0) mfdim([96,2,w],1) mfdim([96,2,w],2) mfdim([96,2,w],3) mfdim([96,2,w],4) mfdim([240,1,-1],1) \\ regressions mfdim(mfinit([154,1,0],1)[1]) mfinit([248,1,0],1); mfdim([455,1,Mod(94,455)],0) #mfinit([344,1,0],0) #mfinit([1024,1,0],0) #mfinit([1099,1,0],0) T=mfTheta();vec(T) mfT = mfinit(T); mfeval(mfT,T,[0,1/2,1,oo, (38+I)/85.]) T=mfTheta(Mod(2,7)); vec(T) mfparams(T) T=mfTheta(Mod(2,5)); vec(T) mfparams(T) E=mfEk(10); vec(E) D=mfDelta(); vec(D) mfparams(mfD) vec(mfshift(D,1)) mftaylor(D,10) mftaylor(D,10,1) E4=mfEk(4); E6=mfEk(6); N=mflinear([mfmul(mfmul(E4,E4),E4), mfmul(E6,E6)], [1,-1]); mf=mfinit(N); vec(N) == vec(mflinear(mf,N)) vec(mfdiv(N, D)) N=mflinear([mfpow(E4,3), mfpow(E6,2)], [1,-1]); vec(N) mfcoefs(mfderiv(E6),6) mfcoefs(mfderiv(E6,-1),6) mfcoefs(mfderivE2(E6),6) N=19; f=mfeisenstein(2,Mod(6,N)); g=mfeisenstein(2,Mod(11,N)); E=mfmul(f,g); mfcoefs(E,6) f = mfbracket(mfbd(E4,4), mfTheta(), 1); vec(f) mfcoefs(f,0) f = mfbracket(mfbd(E4,4), mfTheta(), 0); vec(f) mfcoefs(f,0) mfcoefs(mfbracket(E4,E6,1),10)/(-3456) mf = mfinit([7,3,Mod(6,7)], 0); [f]=mfeigenbasis(mf); lfunmfspec(lfunmf(mf,f)) mf=mfinit([10,7,[Z5,2]], 0); mffields(mf) [f1,f2]=mfeigenbasis(mf); vE=mfembed(f1) mfembed(vE,mfcoefs(f1,4)) mfembed(mf) vE=mfembed(f2); #vE mfembed(vE[1],mfcoefs(f2,4)) mfembed(vE[2],mfcoefs(f2,4)) mfembed(vE[1], [1,t;y,1/2]) mfperiodpol(mf,f1) f1=mfsymbol(mf,f1); f2=mfsymbol(mf,f2); mfperiodpol(mf,f1) mfperiodpol(mf,f2) mfsymboleval(f1,[0,oo]) mfsymboleval(f1,[1/2 + I/10000,oo]) mfsymboleval(f1,[1/2 + I/20,oo]) mfsymboleval(f1,[1/2 + I/(20+1e-10),oo]) mfsymboleval(f1,[1/3,1/2]) mfsymboleval(f2,[1/3,1/2]) mfsymboleval(f2,[1/2,1/2]) \\ #2260 mfpetersson(f1) m=mfpetersson(f2); if (exponent(m[2,1]) < -126, m[2,1]=0); if (exponent(m[1,2]) < -126, m[1,2]=0); m normlp(mfpetersson(f1,f2)) < 1e-38 normlp(mfpetersson(f2,f1)) < 1e-38 L=mfmanin(f2)[1]; liftpol(L[1]) L[2][3] FS5=mfsymbol(mfeisenstein(4,1,5)); FS3=FS5[3]; for(i=1,#FS3,print(FS3[i])); mfsymboleval(FS5,[0,oo]) mfsymboleval(FS5,[1/5,oo]) FS16=mfsymbol(mfeisenstein(4,-4,-4)); mfsymboleval(FS16,[0,oo]) mfsymboleval(FS16,[1/4,oo]) mfsymboleval(FS16,[1/4,oo],[0,-1;1,4]) mfsymboleval(FS16,[0,oo],[0,-1;1,2]) mfatkineigenvalues(mf,1) mfatkineigenvalues(mf,2) mfatkineigenvalues(mf,5) mfatkineigenvalues(mf,10) mfparams(mf) #mfbasis(mf) liftpol(mfcoefs(mfbasis(mf)[1], 9)) F = mfeigenbasis(mf); #F liftpol(mfcoefs(F[1], 9)) liftpol(mfcoefs(F[2], 9)) mfcoefs(mffrometaquo([1,2;11,2]),10) f=mffrometaquo([864,6;432,-3;288,-2;144,1]); mfcoefs(f,11,12) mfcoefs(f,12,12) F=mffrometaquo([1,8;2,-2;4,2;6,2;12,2]); mf=mfinit([12,6],1); mftobasis(mf,F) F=mffrometaquo([1,-16;2,68]); mf=mfinit([4,26],1); F2=mfhecke(mf,F,2); mf2=mfinit([2,26],1); mftobasis(mf2,F2) mfcoefs(mffrometaquo(matrix(0,2)),5) mfdim(mfinit([24,4,Mod(23,24)],1),1) data = [63,2, Mod(46,63)]; B=mfbasis(mfinit(data,3)); MF = mfinit(data,4); lift(mftobasis(MF,B[3])) mfsturm(MF) charpoly(mfheckemat(MF,2)) mfsturm(mfinit([1,4])) mfgaloistype([11,1,1]) mfgaloistype([148,1,Mod(105,148)]) mfgaloistype([71,1, -71]) mf = mfinit([71,1, -71]); mfgaloistype(mf) [f]=mfeigenbasis(mf); lfunmfspec(lfunmf(mf,f)[1]) mfgaloistype([124,1, Mod(67,124)]) \\ slow: ~ 10s, but needed to reproduce regression /* mf=mfsplit(mfinit([633,1,Mod(71,633)],1)); mfgaloistype(mf, mfeigenbasis(mf)[2]) mf=mfsplit(mfinit([675,1,Mod(161,675)],1)); mfgaloistype(mf, mfeigenbasis(mf)[1]) */ see(L) = for(i=1,#L, my(f=L[i]); print([mfparams(f), mfcoefs(f,10)])); L=mfeigensearch([[1..40],2],[[2,1],[3,-1]]); see(L) L=mfeigensearch([[1..40],2],[[2,Mod(1,3)],[3,Mod(2,4)]]); see(L) L=mfeigensearch([[1..38],2],[[2,-1],[11,-6]]); see(L) L=mfeigensearch([[1..16],3],[[2,0]]); see(L) V=mfsearch([[11..40],2],[0,1,2,3,4],1); for(i=1,#V,print([mfparams(V[i])[1..3],mfcoefs(V[i],10)])); V=mfsearch([60,2],[0,1,2,3,4,5,6], 1); #V mfcoefs(V[1],5) #mfsearch([193,1],[0],1) #mfsearch([195,1],[0],1) charpoly(mfheckemat(mfinit([106,2],1),2)) G=znstar(164,1); L=[chi | chi <- chargalois(G,164), zncharisodd(G,chi)]; apply(chi->charorder(G,chi),L) mfdim([164, 1, apply(x->[G,x], L)],0) mfdim([667, 1, [Mod(45,667)]],0) mfdim([329, 1, [Mod(46,329)]],0) mfdim([484, 1, [Mod(3,484)]],0) mfdim([191, 1, [Mod(190,191)]],0) mfdim([195, 1, [Mod(194,195)]],0) N=4; L=mfcosets(N) mftocoset(N, [1,1;2,3], L) mfcosets(mf23) /* regressions */ mf=mfinit([77,1, Mod(20,77)],0); lift(mfcoefs(mf[3][1],10)) mfgaloistype(mf) mf=mfinit([196,1,Mod(67,196)],0);mfdim(mf) mf=mfinit([297,1, Mod(10,297)],0); lift(mfcoefs(mf[3][1],10)) mfgaloistype(mf) mf=mfinit([416,1, Mod(159,416)],1);mfdim(mf) \\ oo loop in Zab_indexrank mf=mfinit([72,2,Mod(11,72)],0);mfdim(mf) \\ division by 1 in mfheckematwt1 mf=mfinit([283,1,-283],0); mfdim(mf) mfheckemat(mf,[2,3]) mf=mfinit([765, 1, Mod(254, 765)], 0); mfgaloistype(mf) mf=mfinit([837, 1, -31], 0); mfgaloistype(mf) \\ Tests lfunmf E4=mfEk(4);E6=mfEk(6);D=mfDelta(); mf=mfinit([1,4],3); mfeval(mf,E4,I) mfeval(mf,E4,I/10) mf12=mfinit([1,12],3); mfeval(mf12,mfEk(12),I) L4=lfunmf(mf, E4); [lfun(L4,0),lfun(L4,1)*Pi^2/zeta(3),lfun(L4,4)/zeta(4)] L6=lfunmf(mfinit([1,6],3), E6); [lfun(L6,0),lfun(L6,1)*Pi^4/zeta(5),lfun(L6,6)/zeta(6)] L12=lfunmf(mfinit([1,12],0), D); omp=lfunlambda(L12,3) vector(6,i,bestappr(lfunlambda(L12,2*i-1)/omp)) omm=lfunlambda(L12,2) vector(5,i,bestappr(lfunlambda(L12,2*i)/omm)) L18=lfunmf(mfinit([1,18],0), mfmul(D,E6)); omp=lfunlambda(L18,3); vector(9,i,bestappr(lfunlambda(L18,2*i-1)/omp)) omm=lfunlambda(L18,2) vector(8,i,bestappr(lfunlambda(L18,2*i)/omm)) mf = mfinit([25,3,Mod(2,5)],0); F = mfbasis(mf)[1]; L=lfunmf(mf,F); lfun(L,1) [mf,F] = mffromqf([2,0;0,2]); L=lfunmf(mf,F); lfun(L,1) lfun(L,2) mf=mfinit([11,2,Mod(3,11)]); f=mfbasis(mf)[1]; lfuncheckfeq(lfunmf(mf,f)) \\ oo loop due to low precision in mffrickeeigen p=[4,54]; lfunmf(mfinit(p,0), mftraceform(p,0)); mf=mfinit(D); PP=mfperiodpol(mf,D,-1);cP=polcoeff(PP,1) PP/=cP;bestappr(PP) PM=mfperiodpol(mf,D,1);cM=polcoeff(PM,0) PM/=cM;bestappr(PM) Ds = mfsymbol(mf,D); DS=mfpetersson(Ds) [pols,oms]=mfmanin(Ds); pols oms[3] bestappr(DS/(oms[1]*oms[2]/I), 10^8) mf=mfinit([11,2],1); fs=mfsymbol(mf,mfbasis(mf)[1]); DS=mfpetersson(fs) [pols,oms]=mfmanin(fs); pols oms[3] mf=mfinit([11,4],1); fs=mfsymbol(mf,mfbasis(mf)[1]); mfpetersson(fs) real(mfpetersson(fs, mfsymbol(mf,mfbasis(mf)[2]))) mf=mfinit([12,3,-4],1); fs=mfsymbol(mf,mfbasis(mf)[1]); real(subst(fs[3][24],x,x/I)) mfpetersson(fs) mfsymboleval(fs,[2/5,3/4]) mf=mfinit([12,6,12],1); fs=mfsymbol(mf,mfbasis(mf)[5]); real(subst(fs[3][14],x,x/I)) mfpetersson(fs) mfsymboleval(fs,[2,3;5,4]) mfsymboleval(fs,[0,0]) mfsymboleval(fs,[I,2*I]) mfsymboleval(fs,[0,oo],[2,0;0,1]) mfsymboleval(fs,[I,2*I],[2,0;0,1]) mfperiodpolbasis(12) mfperiodpolbasis(12,1) mfperiodpolbasis(12,-1) mfperiodpolbasis(2) mfperiodpolbasis(-1) mf=mfinit([23,4],0); [f1,f2]=mfeigenbasis(mf); F=mfsymbol(mf,f1); mfeval(mf,f2,0.9995346163+0.02156773223*I) \\ regression \\#2134 f=mffrometaquo([1,1;3,1;5,1;15,1]); z = 1+I/300; mf2=mfinit([30,2],1); real(mfeval(mf2,f,z)) mfpetersson(F) mf=mfinit([23,2],0); f = mfeigenbasis(mf)[1]; F = mfsymbol(mf, f); mfsymboleval(F,[217/554+1/554*I,oo]) \\ #2360 mfslashexpansion(mf,f,[1,0;0,1],5,1) mfcuspisregular(mf,1/2); L=liftpol(mfmanin(F)); [v[1] | v<-L] [v[2][3] | v<-L] mf=mfinit([7,4,Mod(2,7)], 0); F=mfsymbol(mf, mfeigenbasis(mf)[1]); L=mfmanin(F) mfcusps(mf) mf = mfinit([37,2],4); f=mfbasis(mf)[2]; s=mfsymbol(mf,f); mfpetersson(s) T=mfTheta();mf=mfinit([12,1/2]);CU12=mfcusps(12) mfcusps(mf) apply(x->mfcuspwidth(mf,x), CU12) apply(x->mfcuspisregular(mf,x), CU12) apply(x->mfcuspisregular([12,2,-4],x), CU12) apply(x->mfcuspval(mf,T,x),CU12) mf=mfinit([12,6,12],1);F=mfbasis(mf)[5]; apply(x->mfcuspval(mf,F,x),CU12) mf=mfinit([12,3,-4],1);F=mfbasis(mf)[1]; apply(x->mfcuspval(mf,F,x),CU12) D=mfDelta();F=mfderiv(D); G=mfmul(D,mfEk(2));mfisequal(F,G) p(mf,f) = mfdescribe(f,&g); concat([mfparams(f), mfspace(mf,f), [mfdescribe(f)], apply(mfdescribe,g[1])]); F2=mfeisenstein(7,-3); p(mfinit(F2,3),F2) F3=mfeisenstein(7,-3,5); p(mfinit(F3,3),F3) F4=mfEk(4); p(mfinit(F4,3),F4) [mf,F5]=mffromqf([2,1;1,6]); p(mf,F5) T=mfTheta(); mfT = mfinit(T); p(mfT, T) p(mfT, mfhecke(mfT,T,9)) F6=mfDelta(); p(mfD,F6) F7=mffrometaquo([1,2;11,2]); p(mfinit(F7),F7) [mf,F8]=mffromell(ellinit([0,1,1,9,1])); p(mf,F8) p(mf,mfadd(F7,F8)) p(mf,mfpow(F2,3)) p(mf,mfmul(F2,F3)) p(mfD,mfbracket(F4,F4,2)) p(mf,mflinear([F7,F8],[1,-1])) p(mf,mfdiv(F3,F2)) p(mf,mfshift(F6,1)) p(mf,mfderiv(F4)) p(mfD,mfderivE2(F4,4)) p(mf,mftwist(F4,5)) p(mfD,mfhecke(mfD,F6,5)) p(mfinit([3,4],3),mfbd(F4,3)) mf=mfinit([6,2],3);B=mfbasis(mf); for(i=1,#B,print(p(mf,B[i]))); mf=mfinit([24,4]);B=mfbasis(mf); for(i=1,#B,print(p(mf,B[i]))); apply(x->mfconductor(mf,x),B) mf=mfinit([23,1,-23],1); f=mfbasis(mf)[1]; p(mf,f) mfpetersson(mfsymbol(mf,f)) mf=mfinit([92,1,-23],1); mfconductor(mf,f) mf=mfinit([96,2]); L=mfbasis(mf); mf0=mfinit(mf,0); mftobasis(mf0,L[1],1) mffromlfun(lfuncreate(x^2+1)) mffromlfun(lfunqf(matid(3))) mffromlfun(ellinit([0,-1,1,-10,-20])) F=mffromell(ellinit([0,1]))[2]; mfisCM(F) mf = mfinit([39,1,-39],0); F=mfeigenbasis(mf)[1]; mfisCM(F) f = mffrometaquo(Mat([1,24])); mfisetaquo(f) f = mffrometaquo([1,1;23,1]); mfisetaquo(f) f = mffrometaquo([1,12;193,12]); mfisetaquo(f) f = mffrometaquo(Mat([1,-24]), 1); mfisetaquo(f) mfisetaquo(f,1) mfisetaquo(mffromell(ellinit([0,1,1,0,0]))[2]) mfisetaquo(mfpow(mfDelta(),20)) \\ Half-integral weight dim2(N,k,space)= { my(L=mfdim([N,k+1/2,0],space)); if (!k && space==1, for(i=1,#L,print1(L[i][2..3]," ")), for(i=1,#L,print1(L[i][3]," ")) ); } for(N=1,300,dim2(4*N,0,1));print(); for(N=1,10,dim2(4*N,0,3)); for(N=1,10,dim2(4*N,0,4)); for(N=1,10,dim2(4*N,1,1)); for(N=1,10,dim2(4*N,1,3)); for(N=1,10,dim2(4*N,1,4)); for(N=1,10,dim2(4*N,2,1)); for(N=1,10,dim2(4*N,2,3)); for(N=1,10,dim2(4*N,2,4)); for(N=1,10,dim2(4*N,3,1)); for(N=1,10,dim2(4*N,3,3)); for(N=1,10,dim2(4*N,3,4)); for(N=1,10,print1(mfdim([4*N,3+1/2,-1],1)," ")); for(N=1,10,print1(mfdim([4*N,3+1/2,-1],3)," ")); for(N=1,10,print1(mfdim([4*N,3+1/2,-1],4)," ")); L=mfinit([12,7/2,0],1); vector(#L,i,[vec(f) | f<-mfbasis(L[i])]) mf=mfinit([24,5/2],1); mfcoefs(mf,5) mf=mfinit([28,5/2],1); B=mfbasis(mf); mfcoefs(mf,5) for(i=1,#B,print(vec(B[i]))); mf=mfinit([28,5/2,Mod(2,7)],1); B=mfbasis(mf); [G,chi] = znchar(mf); chi [G,chi] = znchar(B[1]); chi mfslashexpansion(mf, B[1], [1,0;2,1], 5, 1) mfheckemat(mf,4) for(i=1,#B,print(lift(vec(B[i])))); T=mfTheta(); T2=mfmul(T,T); mfparams(T2) mf=mfinit([20,3/2]); B=mfbasis(mf); for(i=1,#B,print(lift(vec(B[i])))); mf=mfinit([4,5/2]);#mfbasis(mf) mfparams(mffrometaquo([1,24])) mfparams(mffrometaquo([2,12])) mfparams(mffrometaquo([3,8])) mfparams(mffrometaquo([4,6])) mfparams(mffrometaquo([6,4])) mfparams(mffrometaquo([12,2])) mfparams(mffrometaquo([24,1])) F=mffrometaquo([8,3]);mfparams(F) mf=mfinit([64,3/2]); mftobasis(mf,F) V=mfslashexpansion(mf,F,[0,-1;1,0],10,0,&A); [A,V] mfslashexpansion(mf,F,[0,-1;1,0],10,1) V=mfslashexpansion(mf,F,[-1,0;2,-1],10,0,&A); [A,V] mfslashexpansion(mf,F,[-1,0;2,-1],10,1) mfeval(mf,F,I) T=mfTheta(); mf=mfinit(T); mfslashexpansion(mf,T,[-1,0;0,-1],2,1) mfslashexpansion(mf,T,[-1,0;-2,-1],2,1) mfslashexpansion(mf,T,[1,0;2,1],2,1) mfslashexpansion(mf,T,[0,1;-1,0],2,1) mfslashexpansion(mf,T,[0,-1;1,0],2,1) mfslashexpansion(mf,T,[0,1;-1,-1],2,1) mfslashexpansion(mf,T,[2^64+1,2^64+3;9223372036854775808,9223372036854775809],2,1) mf=mfinit([36,5/2],1);mfparams(mfbasis(mf)[3]) K=mfkohnenbasis(mf); nbcol=matsize(K)[2] K~ mfparams(mfshimura(mf,mflinear(mf,K[,1]))[2]) mfparams(mfshimura(mf,mflinear(mf,K[,2]),5)[2]) (mfcoefs(mf,20)*K)~ mf=mfinit([60,5/2],1);bij=mfkohnenbijection(mf);bij[2] bij[4] mfkohneneigenbasis(mf,bij)[2..3] mf=mfinit([52,3/2,Mod(15,52)],1);mfkohnenbijection(mf)[2..4] mf=mfinit([12,5/2]); apply(x->mfconductor(mf,x),mfbasis(mf)) mfconductor(mf,mflinear(mf,[0,1,2,4,8])) mf=mfinit([12,5/2],1); F=mfbasis(mf)[1]; FSbug = mfsymbol(mf,F); mfpetersson(FSbug) T5S=mfsymbol(mfTheta(5));Pi/mfpetersson(T5S) F=mffrometaquo([1,-2;2,5;4,-2]);mfparams(F) F=mffrometaquo([1,2;2,-1]);mfparams(F) mf=mfinit(F);mftobasis(mf,F) E1=mfeisenstein(4,-3,-4); mfdescribe(E1) E2=mfeisenstein(3,5,-7); mfdescribe(E2) E3=mfderivE2(mfmul(E1,E2), 3); mfdescribe(E3) mfdescribe(mfDelta()) mfdescribe(mfEk(2)) mfdescribe(mfhecke(mfinit([1,2]),mfEk(2),3)) [mfdescribe(mfinit([37,4],i)) | i<-[0..4]] [mfdescribe(mfinit([16,3/2],i)) | i<-[1,4]] E=mfmul(mfeisenstein(4,-3,-4),mfeisenstein(3,1,-3)); mfdescribe(E,&g); apply(mfdescribe,g[1]) f1=mffromqf(matdiagonal([1,6,36]*2))[2]; f2=mffromqf(matdiagonal([4,6,9]*2))[2]; F=mflinear([f1,f2],[1,-1]/2); mf=mfinit(F); [mf2,g]=mfshimura(mf,F); mfcuspval(mf2,g,0) T3=mfpow(T,3);mf=mfinit(T3); [mf,TSHI,res]=mfshimura(mf,T3); mfcoefs(TSHI,10) T5=mfpow(T,5); [mf,TSHI,res]=mfshimura(mfinit(T5),T5); mfcoefs(TSHI,10) mftobasis(mfinit(TSHI,4),TSHI) F4=mfmul(mfbd(T,4),mffrometaquo([8,1;16,1])); F4S=mfshimura(mfinit(F4),F4)[2];mfcoefs(F4S,20) EH=mfEH(13/2); mfdescribe(EH); mfcoef(EH,1001) mfcoef(EH,13*5^2) mfcoefs(EH,15,2) EH=mfEH(3/2); \\ to test hclassno6u mfcoefs(EH,2,10^8) mfcoefs(EH,2,10^8+3) mf=mfinit(EH); vec(EH) vec(mfEH(5/2)) vec(mfEH(7/2)) vec(mfEH(9/2)) vec(mfEH(11/2)) vec(mfEH(13/2)) vec(mfEH(15/2)) vec(mfEH(19/2)) vec(mfhecke(mf, EH, 6)) vec(mfhecke(mf, EH, 4)) mf2=mfinit([12,3/2]); vec(mfhecke(mf2, EH, 4)) vec(mfhecke(mf, EH, 9)) vec(mfhecke(mf2, EH, 9)) vec(mfhecke(mf, EH, 25)) vec(mfhecke(mf, EH, 3^6)) vec(mfhecke(mf2, EH, 25)) vec(mfhecke(mfT, mfTheta(),4)) vec(mfhecke(mfT, mfTheta(),3^4)) mf=mfinit([32,5/2,8],1); F=mfbasis(mf)[1]; mfa = mfatkininit(mf,32); vec(mfatkin(mfa,F)) mfa[3] mffrometaquo([1,1],1) M8=mfinit([8,5/2]); a8=mfatkininit(M8,8); M82=mfatkininit(a8[1],8); a8[2]*M82[2] mf=mfinit([11,4]);B=mfbasis(mf)[1..2]; FE1=mflinear(B,[1,-1]);FE2=mflinear(B,[1,-11^4]); FE1S=mfsymbol(mf,FE1);FE2S=mfsymbol(mf,FE2); real(mfpetersson(FE1S,FE2S)) E=mfeisenstein(3); mf=mfinit([3,3]); ES=mfsymbol(mf,E); mfsymboleval(ES,[1,I]) mfcuspval(mf,E,1/2) mffrometaquo([1,-24]) mfcoefs(mffrometaquo([1,-24],1),6) mf=mfinit([53,2]); F=mfeigenbasis(mf)[1]; ms=mfsymbol(mf,F);mfpetersson(ms) f=mfeisenstein(4,Mod(1,2),Mod(1,2)); vec(f) \\ #2314 E=mfpow(mfeisenstein(4),3);mfcoef(E,0) getcache()[,1..4] \\ ERRORS, leave at end of bench mftobasis(mf0,L[1]) mfdim([4,1/2],0) mfdim([4,1/2],2) mfdim([4,1/2],5) mfeisenstein(2,1.0) mfeisenstein(2,[0,0]) mfeisenstein(6,Mod(7,9),Mod(4,9)); mfinit([1,1.0]) L=mfeigenbasis(mfinit([14,6,Mod(9,14)],0)); mfmul(L[1],L[2]) mfcuspwidth(0,0) mfparams(mfadd(F2,F3)) mfparams(mfadd(F4,F6)) mfinit([23,1,Mod(22,45)],0); mfinit([23,2,Mod(22,45)],0); mfinit([7,1,-7],2); mfinit([7,1,-7],5); mfinit([1,2],5) mfgaloistype([11,1,Mod(2,11)], mfeisenstein(1,1,Mod(2,11))) D=mfDelta(); mfdiv(D,mfpow(D,2)) mfeval(mfD,D,-I) mfslashexpansion(mfD,D,[1,2;3,4],1,1) mftonew(mfD,1) T=mftraceform([96,6],4); mfshimura(mfinit(T5),T5,4) mf=mfinit([1,4],3); mftonew(mf,E4) mffields(mf) mfdiv(1,mfTheta()) mfdiv(D,mftraceform([1,3])) mfcosets(1.) mf=mfinit([1,0]);F=mfbasis(mf)[1];mfsymbol(mf,F); mf=mfinit([12,5/2],1); F=mfbasis(mf)[1]; mfmanin(FSbug) mfsymboleval(FSbug,[0,1]) mfgaloistype([4,1,-4],x) N=19; f=mfeisenstein(2,Mod(6,N)); g=mfeisenstein(2,Mod(11,N)); E=mfmul(f,g); mfdiv(E,f); mf=mfinit([7, 6, Mod(2,7)],0); [F] = mfeigenbasis(mf); mfpow(F,3) mffromqf(Mat(2),x*y) mffromqf(2*matid(2),x*y^2) \\ #2484 [f] = mfeigensearch([11,2]); F = mftwist(f,-3); mfcoefs(F,20) vector(21,n,mfcoef(F,n-1)) \\ #2572 mf=mfinit([12,3,Mod(7,12)],1);F=mfbasis(mf)[1]; mfslashexpansion(mf,F,[1,0;5,1],3,1)[4] \\ #2586 mf=mfinit([27,2],0);f=mfeigenbasis(mf)[1]; symb=mfsymbol(mf,f);a=(-1+sqrt(-3))/2; F(s,t)=mfsymboleval(symb,[s,t]); exponent(F(oo,0)+F(0,a)-F(oo,a))<-128 pari-2.17.2/src/test/in/polyser0000644000175000017500000000232314760123736014771 0ustar billbillHEAP=[61, if(sizebyte(0)==16,4887,4938)]; \e apol=y^3+5*y+1 deriv((x+y)^5,y) ((x+y)^5)' dz=vector(30,k,1);dd=vector(30,k,k==1);dm=dirdiv(dd,dz) direuler(s=1,40,1+s*X+s^2*X) dirmul(abs(dm),dz) zz=yy;yy=xx;eval(zz) factorpadic(apol,7,8) intformal(sin(x)) intformal((-x^2-2*a*x+8*a)/(x^4-14*x^3+(2*a+49)*x^2-14*a*x+a^2)) newtonpoly(x^4+3*x^3+27*x^2+9*x+81,3) padicappr(apol,1+O(7^8)) padicappr(x^3+5*x+1,Mod(x*(1+O(7^8)),x^2+x-1)) Pol(sin(x)) Pol([1,2,3,4,5]) Polrev([1,2,3,4,5]) polcoeff(sin(x),7) polcyclo(105) pcy=polcyclo(405) pcy * pcy poldegree(x^3/(x-1)) poldisc(x^3+4*x+12) poldiscreduced(x^3+4*x+12) polinterpolate([0,2,3],[0,4,9],5) polisirreducible(x^5+3*x^3+5*x^2+15) pollegendre(10) zpol=0.3+pollegendre(10) polrecip(3*x^7-5*x^3+6*x-9) polresultant(x^3-1,x^3+1) polresultant(x^3-1.,x^3+1.,,1) polroots(x^5-5*x^2-5*x-5) polroots(x^4-1000000000000000000000) polrootsmod(x^16-1,41) polrootspadic(x^4+1,41,6) polsturm(zpol) polsturm(zpol,0.91,1) polsylvestermatrix(a2*x^2+a1*x+a0,b1*x+b0) polsym(x^17-1,17) poltchebi(10) polzagier(6,3) serconvol(sin(x),x*cos(x)) serlaplace(x*exp(x*y)/(exp(x)-1)) serreverse(tan(x)) subst(sin(x),x,y) subst(sin(x),x,x+x^2) taylor(y/(x-y),y) variable(name^4-other) if (getheap()!=HEAP, getheap()) pari-2.17.2/src/test/in/number0000644000175000017500000000422514676526175014601 0ustar billbillHEAP=[96, if(sizebyte(0)==16,3267,3323)]; \e addprimes([nextprime(10^9),nextprime(10^10)]) localbitprec(1024);bestappr(Pi,10000) gcdext(123456789,987654321) bigomega(12345678987654321) binomial(1.1,5) chinese(Mod(7,15),Mod(13,21)) content([123,456,789,234]) contfrac(Pi) contfrac(Pi,5) contfrac((exp(1)-1)/(exp(1)+1),[1,3,5,7,9]) contfracpnqn([2,6,10,14,18,22,26]) contfracpnqn([1,1,1,1,1,1,1,1;1,1,1,1,1,1,1,1]) core(54713282649239) core(54713282649239,1) coredisc(54713282649239) coredisc(54713282649239,1) divisors(8!) eulerphi(257^2) factor(17!+1) factor(100!+1,0) factor(40!+1,100000) factorback(factor(12354545545)) factor(230873846780665851254064061325864374115500032^6) factorcantor(x^11+1,7) centerlift(lift(factormod(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) qfbcomp(Qfb(5,3,-1),Qfb(7,1,-1)) qfbcomp([Qfb(5,3,-1),0.],[Qfb(7,1,-1),1.]) qfbcompraw(Qfb(5,3,-1),Qfb(7,1,-1)) qfbcompraw([Qfb(5,3,-1),0.],[Qfb(7,1,-1),1.]) qfbhclassno(2000003) qfbnucomp(Qfb(2,1,9),Qfb(4,3,5),3) form=Qfb(2,1,9);qfbnucomp(form,form,3) qfbnupow(form,111) qfbpow([Qfb(5,3,-1),0.],3) qfbpowraw([Qfb(5,3,-1),0.],3) qfbprimeform(-44,3) qfbred(Qfb(3,10,12),,-1) qfbred([Qfb(3,10,-20),1.5]) qfbred([Qfb(3,10,-20),1.5],2,18) qfbred([Qfb(3,10,-20),1.5],1) qfbred([Qfb(3,10,-20),1.5],3,18) quaddisc(-252) quadgen(-11) quadpoly(-11) quadregulator(17) quadunit(17) sigma(100) sigma(100,2) sigma(100,-3) sqrtint(10!^2+1) znorder(Mod(33,2^16+1)) forprime(p=2,100,print(p," ",lift(znprimroot(p)))) znstar(3120) if (getheap()!=HEAP, getheap()) pari-2.17.2/src/test/in/sumnumrat0000644000175000017500000000222714676526175015344 0ustar billbill\p115 sumnumrat(1/x,-oo) sumnumrat(1/x^2,-oo) sumeulerrat(y/x^2,1) F=1/(x^2+1)^2; sumnumrat(F,1) F=1/((x+1)*(x^2+x+1)); sumnumrat(F,0) F=1+1/x^2; prodnumrat(F,1) sumeulerrat(1/(q^2+1),1) sumeulerrat(1/(q+1),2) z = zeta(2)/zeta(4); exponent(prodeulerrat(1+1/q^2,1) - z) exponent(prodeulerrat(1+1/q^4,1/2) - z) prodeulerrat(1-2/(q*(q+1)),1) exponent(prodeulerrat(1+1/q,3) - zeta(3)/zeta(6)) sumnumrat(0,0) prodnumrat(1,1) prodeulerrat(1) sumeulerrat(0) \\ #2357 exponent(prodeulerrat(1/(1-1/x^2)) - zeta(2)) \\ #2190 m=100;prodeulerrat((p-2)/(p-1)+(p-1)^(m-1)/p^m,1,3) S = 5.860056454092251396039917840682865151109267605836469570260459245112533010750289129320452484305732931556286661157629 E-9; exponent(sumeulerrat(1/p,2,10^7) - S) < -384 S = 1.000000005860056471262372114707057832977756961053190894780909349332937607270144123030429510269114760410610337790942; exponent(prodeulerrat(1+1/p,2,10^7) - S) < -381 \\ #2566 f(N) = sum(k=1,N,1/(p^(2*k)-1)); prodeulerrat(f(18)/f(17)) \\ errors sumnumrat(1/x^2,oo) sumnumrat(1.0,1) sumnumrat(1/x,10) prodnumrat(1+1/x,10) prodnumrat(2,1) sumeulerrat(1) sumeulerrat(1/p) prodeulerrat(2) prodeulerrat(1+1/p) sumeulerrat(x^2/(1+x),2) pari-2.17.2/src/test/in/ellweilpairing0000644000175000017500000000753014567450071016310 0ustar billbillweil(E,P,Q,m,p)=lift(ellweilpairing(E,P,Q,m)); tate(E,P,Q,m,p)=if(p%m!=1,return(0));lift(elltatepairing(E,P,Q,m)^((p-1)/m)); check(v,P,Q,m,p)= { my (E=ellinit(v*Mod(1,p))); P*=Mod(1,p); Q*=Mod(1,p); print([weil(E,P,Q,m,p),tate(E,P,Q,m,p),ellgroup(E)]); } check([0,0,1,0,0],[0,0],[57,46],3,103) check([0,0,1,0,0],[64,63],[0,0],3,109) check([0,0,1,0,0],[0,0],[150,32],3,151) check([0,0,1,0,0],[0,156],[13,144],3,157) check([0,0,1,0,0],[0,0],[59,58],3,163) check([0,0,1,0,0],[192,84],[0,192],3,193) check([0,0,1,0,0],[198,92],[0,0],3,199) check([0,0,0,1,0],[1,51],[72,9],4,113) check([0,0,0,1,0],[88,56],[1,31],4,137) check([1,0,0,0,3],[13,6],[147,89],4,149) check([0,0,1,0,0],[5,58],[36,128],4,157) check([0,0,1,0,3],[30,1],[26,1],5,31) check([0,0,1,0,0],[58,107],[22,76],6,109) check([0,0,1,0,0],[90,4],[32,1],6,127) check([0,0,1,0,0],[138,60],[62,155],6,157) check([0,0,0,1,0],[47,53],[160,147],7,197) check([0,0,0,1,0],[50,80],[16,65],8,113) check([1,0,0,0,3],[25,82],[23,49],8,149) check([0,0,1,0,0],[10,67],[88,35],9,127) check([0,0,1,0,0],[102,32],[87,55],9,163) check([0,0,1,0,0],[12,11],[17,5],9,19) check([0,0,1,0,0],[190,47],[194,169],9,199) check([0,0,0,1,0],[28,34],[22,11],10,137) check([0,0,0,1,0],[94,84],[10,142],10,157) check([0,0,0,1,0],[159,29],[115,100],14,197) check([0,0,0,1,0],[154,21],[58,126],15,157) check([0,0,0,1,0],[121,63],[121,64],16,127); check([0,0,0,1,0],[18,104],[177,153],16,191); check([0,0,1,0,0],[16,56],[16,56],2,113); check([0,0,1,0,0],[66,63],[66,63],2,127); check([0,0,1,0,0],[126,78],[89,78],2,157); check([0,0,1,0,0],[150,89],[150,89],2,179); check([0,0,1,0,0],[22,95],[22,95],2,191); check([0,0,0,1,3],[4,1],[4,6],6,7); check([0,0,0,0,2],[3,1],[3,1], 3,7); t=ffgen(Mod(1,2)*(t^6+t^5+t^3+t^2+1)); E=ellinit([0,0,1,0,0],t); P=[t^2+t+1,t+1]; Q=[t^5+t^3+t^2,t^5+t^4+t^3+t^2+t+1]; ellweilpairing(E,P,P,3) ellweilpairing(E,P,Q,3) elltatepairing(E,P,Q,3) elltatepairing(E,P,P,3) elltatepairing(E,Q,Q,3) t=ffgen(ffinit(3,6),'t); E=ellinit([0,0,0,1,0],t); P=[2*t^5+2*t^4+t^2+2*t+2,2*t^5+t^4+t^3+2*t^2+1]; Q=[t^4+t^3+t^2+t+2,t^5+2*t^4+2*t^2+t]; ellweilpairing(E,P,Q,28) elltatepairing(E,P,Q,28) elltatepairing(E,P,P,28) elltatepairing(E,Q,Q,28) t=ffgen(ffinit(5,6),'t); E=ellinit([0,0,1,0,0],t); P=[4*t^5+4*t^4+3*t^3+2*t^2+2*t,4*t^5+4*t^4+2*t^3+2*t^2+4]; Q=[t^5+2*t^4+4*t^3+2*t^2+4*t+1,2*t^5+t^4+3*t+1]; ellweilpairing(E,P,Q,126) elltatepairing(E,P,Q,126) elltatepairing(E,P,P,126) elltatepairing(E,Q,Q,126) t=ffgen(ffinit(101,6),'t); E=ellinit([3,7],t); P=[89*t^5+75*t^4+75*t^3+89*t^2,48*t^5+6*t^4+52*t^3+10*t^2+58*t+29]; ellweilpairing(E,P,P,5) elltatepairing(E,P,P,5) t=ffgen(2^4,'t); E=ellinit([1,0,0,0,t^3+t^2+t+1]); Q=[t^3+t^2,t+1]; elltatepairing(E,Q,Q,5)^3 t=ffgen(3^6,'t); E=ellinit([0,2*t^5+2*t^3+t^2+t+1,0,0,t^3+2*t^2+t]); Q=[2*t^5+2*t^4+t^3+2*t^2+2*t+1,2*t^5+t^2]; elltatepairing(E,Q,Q,8)^91 t=ffgen(5^4,'t); E=ellinit([0,0,0,4*t^3+4*t^2+4*t+1,3*t^3+2]); Q=[3*t^3+2*t^2+1,3*t^2+4*t]; elltatepairing(E,Q,Q,48)^13 p=nextprime(2^65); t=ffgen(p^2,'t); E=ellinit([t^2,0]); [N]=ellgroup(E) d=(p^2-1)/N; P=[14078684373865444404*t+24675141949190748313,34082614562121616748*t+9184592839883218620]; Q=[3606608601291892434*t+22502667145150289531,23709671617839429105*t+22495649567796533868]; ellweilpairing(E,P,Q,N) elltatepairing(E,P,Q,N)^d test(p) = { forvec(v=vector(5,i,[0,p-1]), E=ellinit(v*Mod(1,p)); if (!#E, next); G=ellgroup(E);if(#G>1,print(v,":",G)), ); } test(3); test(5); check2(E)= { E=ellinit(E); my([n,D,G] = ellgroup(E,,1)); my(o = D[1], [P,Q] = G); my(z = ellweilpairing(E,P,Q,o)); forvec(v=vector(4,i,[0,o-1]), my(Pk, Qj, d, w); Pk = elladd(E, ellmul(E,P,v[1]),ellmul(E,Q,v[2])); Qj = elladd(E, ellmul(E,P,v[3]),ellmul(E,Q,v[4])); d = v[1]*v[4]-v[2]*v[3]; w = ellweilpairing(E,Pk,Qj,o); if(w != z^d, error(v,[Pk,Qj],[w,z^d]))); } a=ffgen(2^4,'a); check2([0, a^2, a^3, 0, 0]); check2([0, a^2, a^3, a^4, 0]); pari-2.17.2/src/test/in/hgm0000644000175000017500000001226514676526175014067 0ustar billbillhgmdegree(h)=hgmparams(h)[1]; hgmmvalue(h)=h[6]; hgmweight(h)=hgmparams(h)[2]; val=[1,2,3,4]/5; m=hgminit(val); if (m != hgminit([5]), error(1)); if (m != hgminit([5,0,0,0,-1]), error(2)); hgmeulerfactor(m,-1,101) hgmeulerfactor(m,-1,97) hgmcoefs(m,-1,36) H=hgminit([2],[1]); hgmeulerfactor(H,-8,11) H=hgminit([30],[1,2,3,5]); hgmmvalue(H)==30^30/(15^15*10^10*6^6) hgmeulerfactor(H,1/2,7) hgmweight(hgminit([1/2],[0])) hgmweight(hgminit([1/4,3/4],[0,0])) hgmweight(hgminit([1/6,1/3,2/3,5/6],[0,0,1/4,3/4])) hgmweight(hgminit([1/6,1/3,2/3,5/6],[1/8,3/8,5/8,7/8])) hgmweight(hgminit([6,2],[1,1,1])) hgmweight(hgminit([6],[1,2])) hgmweight(hgminit([8],[1,2,3])) hgmweight(hgminit([5],[1,1,1,1])) hgmweight(hgminit([5,6],[1,1,2,2,3])) hgmweight(hgminit([3,8],[1,1,1,2,6])) hgmweight(hgminit([3,3],[2,2,4])) hgmdegree(hgminit([1/2],[0])) hgmdegree(hgminit([5,6],[1,1,2,2,3])) hgmdegree(hgminit([3,8],[1,1,1,2,6])) hgmdegree(hgminit([3,3],[2,2,4])) hgmparams(hgminit([3],[6])) hgmparams(hgminit([4],[1,2])) hgmparams(hgminit([6,10],[3,12])) hgmparams(hgminit([2,2,2,2,3,3,3,6,6],[1,1,4,5,9])) hgmmvalue(hgminit([1/6,1/3,2/3,5/6],[1/8,3/8,5/8,7/8])) hgmmvalue(hgminit([1/2,1/2,1/2,1/2],[0,0,0,0])) hgmmvalue(hgminit([5],[1,1,1,1])) H=hgminit(vector(16,i,1/2),vector(16));hgmissymmetrical(H) H=hgminit([1/2],[0]);H2=hgmtwist(H);hgmalpha(H2) hgmgamma(H2) hgmtwist(H2)==H H=hgminit([6],[1,2]);H2=hgmtwist(H);hgmcyclo(H2) hgmalpha(H2) hgmgamma(H2) H=hgminit([1/2,1/2,1/2,1/2],[0,0,0,0]); H1=hgminit([1,1,1],[6,2]); H2=hgminit([6,2],[1,1,1]); [hgmweight(H2),hgmdegree(H2)] H3=hgminit([1/12,5/12,7/12,11/12],[0,1/2,1/2,1/2]); [hgmweight(H3),hgmdegree(H3)] H=hgminit([1,1,1],[6,2]); H=hgminit([1/2,1/2,1/2,1/2],[0,0,0,0]); hgmeulerfactor(H,-1,5) forprime(p=5,19,print(hgmeulerfactor(H2,4,p))) forprime(p=11,29,print(hgmeulerfactor(H3,-5,p))) H1=hgminit([1,1,1],[1/2,1/2,1/2]); hgmeulerfactor(H1,-1,3) H2=hgminit([1/2,1/2,1/2],[1,1,1]); L=lfunhgm(H2,1/4); lfunrootres(L) hgmeulerfactor(H2,-1,3) H=hgminit([1,1,1,3],[2,5]); hgmeulerfactor(H,1/5,7) H=hgminit([1/2,1/2,1/2,1/2],[0,0,0,0]); L=lfunhgm(H,-1); lfunan(L,20) hgmcoefs(H,-1,20) hgmcoefs(H,1/5,20) vtov(V)=my(W=vector(#V));for(i=1,#V,my(Vi=V[i],Wi=vector(#Vi,j,Vec(Vi[j])));W[i]=Wi);W; R=hgmbydegree(2);for(w=0,#R-1,print(w,": ",vtov(R[w+1]))); R=hgmbydegree(8);vector(#R,i,#R[i]) R=hgmbydegree(9);vector(#R,i,#R[i]) \\#hgmbydegree(10) \\lfunhgm(H,6/7) H=hgminit([1/6,5/6],[0,1/2]); L=lfunhgm(H,-1) lfuneuler(L,2) lfuneuler(L,3) \\ HCAN=hgminit([1/2,1/2,1/2]); lfunhgm(HCAN,1/4) hgmcoef(HCAN, 1/64, 11) hgmcoef(HCAN, 1/64, 11^2) hgmcoef(HCAN, 1/64, 11^3) hgmcoef(HCAN, 1/64, 11^4) hgmcoef(HCAN, 1/64, [5,2;11,2]) hgmcoef(HCAN, 1/64, Mat([7,6])) hgmcoef(HCAN, 1/64, Mat([11,4])) \\ hgmeulerfactor(HCAN,[1/4,5,-8],3) hgmeulerfactor(HCAN,1/4,3) hgmeulerfactor(HCAN,5,3) hgmeulerfactor(HCAN,-8,3) hgmeulerfactor(HCAN,4/3,3) [hgmeulerfactor(HCAN,-1/8,3,&c), c] [hgmeulerfactor(HCAN,-1/2,3,&c), c] [hgmeulerfactor(HCAN,1/5,5,&c), c] hgmcoef(HCAN,1/64,4) hgmeulerfactor(HCAN,-25/2,5) hgmeulerfactor(HCAN,1/64,2) hgmeulerfactor(HCAN,-1/64,2) L=lfunhgm(HCAN,1/64); L[1][2][2] lfuncheckfeq(L) H=hgminit([3,3],[1,2,6]); L=lfunhgm(H,4);L[3] H=hgminit(Vecsmall(2), Vecsmall(1)); hgmeulerfactor(H,-8,3) H=hgminit([3,12],[1,1,6,6]); H[10] hgmeulerfactor(H,8,7) hgmeulerfactor(H,12,11) H=hgminit([4,4,4],[1,1,1,2,6]); H[10] hgmeulerfactor(H,8,7) hgmeulerfactor(H,12,11) H=hgminit([2,4,10],[1,18]); H[10] hgmeulerfactor(H,14,13) H=hgminit([5]); hgmeulerfactor(H,11^5,11) hgmcoef(H,1/2,2) hgmeulerfactor(H,1/2,2) hgmcoefs(H,-1,1000); \\ make sure it's not too slow H=hgminit([3,3],[1,1,1,1]); hgmeulerfactor(H,7^3,7,&c) c \\ hgmeulerfactor(H,[7^3,5],7,&c) hgmeulerfactor(H,5,7,&c) c H=hgminit([5],[3,3]); \\ too large for 32 bits \\ hgmcoef(H,1/8,98041) \\ hgmcoef(H,1/8,98017) hgmcoef(H,1/8,65521) hgmcoef(H,1/8,65519) hgmeulerfactor(H,1/2^3,2) hgmeulerfactor(H,1/7^3,7) hgmeulerfactor(hgminit([10],[3,3]), 1/7^3, 7) hgmeulerfactor(hgminit([2,2,2],[4,1]), -1/48, 3) H=hgminit([1/2,1/2,1/2,1/2,1/2]); hgmeulerfactor(H,-1,79) \\ too large for 32 bits \\ hgmeulerfactor(H,-1,107) H=hgminit([7]); hgmeulerfactor(H,1/3,2) H=hgminit([-17, -1, 1, 1, 1, 0, 1]) H=hgminit([5],[1,1,1,1]); hgmeulerfactor(H,1,11) hgmcoefs(H,1,12) hgmeulerfactor(hgminit([4,4],[6,6]),1,71) /* Guess pole */ #lfunhgm(HCAN,1/4)==7 #lfunhgm(HCAN,-1/4)==7 /* Guess wild factors/conductor */ test(H, t) = my(L=lfunhgm(H,t));[L[1][2][2][2],L[^1]]; default(realbitprecision,64); test(HCAN,-4) test(HCAN,-3) H=hgminit([2,3],[1,4]); test(H,2) H=hgminit([1/3,1/2,2/3],[0,0,0]); test(H,2) test(H,2/27) H=hgminit([2,3],[1,6]); hgmeulerfactor(H,4,2) hgmeulerfactor(H,4,3) test(H,4) H=hgminit([1/2,1/2,1/2,1/2],[0,0,0,0]); L=lfunhgm(H,2^(-8)); [lfuneuler(L,p)|p<-primes([1,20])] H=hgminit([1/5,2/5,3/5,4/5],[0,1/6,-1/6,0]); hgmeulerfactor(H,7/(3125/432),5) hgmeulerfactor(H,-7/(3125/432),5) \\ ERRORS hgminit([0]) H=hgminit(2, Vecsmall(1)) H=hgminit([2], Vecsmall(1)) lfunhgm(1,1) hgminit([1,1],[0]) hgmcoef(H,1.,1) hgmcoefs(H,1.,1) hgmeulerfactor(H,1.,3) hgminit([1/2],[1/2]) hgminit([1.0],[1/2]) hgminit([1/2],[0.]) hgminit([1],[1]) hgminit([]) hgminit([],[]) p=if(sizebyte(0)==16, 2^32+15, 2^16+1); H=hgminit([2,2,2,2,2,2,2,2,2,2]); hgmeulerfactor(H,1,p) hgmeulerfactor(HCAN,1,p) hgmalpha(Pi) hgmgamma(Pi) pari-2.17.2/src/test/in/ellglobalred0000644000175000017500000000201614567450071015723 0ustar billbill\\package:elldata { forell(E,1,9999, N = ellconvertname(E[1])[1]; M = ellglobalred( ellinit(E[2], 1) )[1]; if (N != M, print(E," bad for N = ",N)) ); } ellidentify(ellinit([1,1])) ellsearch("11a1") ellsearch("11a") ellsearch("11b") ellsearch("11") ellsearch([11,0,1]) ellsearch([11,0]) ellsearch([11]) ellsearch(11) ellinit("11a1").j iferr(ellsearch([0,0,0,0]),E,E) iferr(ellsearch([0,0,0]),E,E) iferr(ellsearch("curve"),E,E) iferr(ellsearch(I),E,E) c=0;forell(E,1,100,c++); c c=0;forell(E,1,100,c++,1); c ellidentify(ellinit([1,1],nfinit('a^2-5))) { K = nfinit(t); forell(E, 1, 1000, my(e,N,f,v); v = [1/60,7131/3600,11/12,5/12]; e = ellchangecurve(ellinit(E[2],1), v); eK= ellchangecurve(ellinit(E[2],K), v); N = ellconvertname(E[1])[1]; f = factor(N)[,1]; for(i=1, #f, my(p = f[i], P,A,B); P=idealprimedec(K,p)[1]; A=elllocalred(e,P.p); A[3]=0; B=elllocalred(eK,P); B[3]=0; if(A!=B, error(E[2])); if(ellap(e,p) != ellap(eK,P),error(E[2])) ) ) } pari-2.17.2/src/test/in/ser0000644000175000017500000000657714676526175014116 0ustar billbills=x+x^2+O(x^5) f=[atan,asin,acos,cosh,sinh,tanh,cotanh,acosh,asinh,atanh]; { for (i=1,#f, print(f[i](s)); print(f[i](O(x^5))); print(f[i]([Pol(1)])); ) } O(x^-2) O(1/x^2) trace(I*x+1+O(x^2)) norm(I*x+1+O(x^2)) a=Ser(vector(200,i,i)); a^2 == a*(a+1) - a \\ test RgX_mullow, RgX_sqrlow 3+O(1) serreverse(x/2+O(x^2)) serreverse(tan(x)/2) iferr(sqrt(x+1/y),E,E) \\ #2063 ((y^-3+O(y))*x+1)/x s = 1/x + x + 2*x^2 + O(x^3); serchop(s) serchop(s, 2) serchop(s, 100) s = Mod(0,3) + x + O(x^2) serchop(s) serchop(Mod(0,3)+O(x^2)) serchop(Mod(0,3)*x+O(x^2)) s = Mod(0,3)+O(x); s * s s = 1 + O(x); 0 * s [Pol(0) * s, Pol(0) / s] [Mod(0,3) * s, Mod(0,3) / s] [Pol(Mod(0,3)) * s, Pol(Mod(0,3)) / s] [0. * s, 0. / s] Ser(Qfb(1,2,3)) Ser(Qfb(1,2,3),, 5.5) Ser(Qfb(1,2,-5)) Ser(Qfb(1,2,-5),y,2) Ser([1,2,3], y, 5) Ser([1,2,3]~, y, 5) Ser([],,3) Ser(Vecsmall([1,2,3]), y, 5) Ser(x+O(x^2),,3) Ser(O(x^2),,3) Ser(x+x^2+x^3+O(x^4),,2) Ser(x^2+x^3,x,0) Ser(1+x,x,0) Ser(1/(x+1),x,0) Ser(1/x,x,0) Ser(1/y,x,0) Ser(x+y+O(x^2),x) Ser(x+y+O(x^2),y) s = Ser(Mod(0,7)) Ser(Mod(1,7)*(x^4+x^2), x,3) s+O(x^16) s+Mod(1,7) s+Mod(1,7)*x s/x s' deriv(s,y) trace(s) round(s) round(s,&e) lift(s) lift(s,x) liftint(s) O(x^2)*0 deriv(Mod(2,4)*x^2+O(x^3)) x^3*(1+O(y^2)) Mod(1,3)*x^3*(1+O(y^2)) O(x)/2 s = O(3^2)+O(x); s/3 s/2 s*3 (1+O(x))^2 1/(x+0.)+O(x^2) 1/(x^2+0.)+O(x^2) [1==O(x), 1==O(x^0), 1==O(x^-1), 1 == 0.+O(x), 1 == 0.+O(1)] [-1==O(x), -1==O(x^0), -1==O(x^-1), -1 == 0.+O(x), -1 == 0.+O(1)] [2==O(x), 2==O(x^0), 2==O(x^-1), 2 == 0.+O(x), 2 == 0.+O(1)] a=Mod(3,9) + O(x^2); b=Mod(3,9) + O(x^2); a*b a=1./x+O(1);a-a a=1/x+O(1);a-a a=Mod(1,2)/x+O(1);a-a Mod(0,5) * O(x^1) Mod(1,5) * O(x^0) O(x^0) / Mod(1,5) subst(1+O(x),x,y) subst(1+x+O(x^2),x,y^2) O(1)==O(x) O(1)==x O(x)==1 1+O(x)==O(x) Ser([Mod(0,2)]) == 1 S = Ser([Mod(0,2)]) / x; S == 1 S + 1 O(x^-2)/(4+O(11)) O(x^-2)+(x+O(23^0))/x^3 O(x^-1)/(1+O(23)+I) O(x^-2)/(1+O(23)+I) serconvol(O(x^-2),O(23)*O(x^-2)) \\ #2364 f=Mod(y^4+y/t^3+1/t^6+1/t^12,2); s=t^-1+t^-3; subst(f,y,s) \\ #2188 S = x+O(x^2);T = O(y) + x + O(x^2); T==S S = x+O(x^2);T = O(y) + x + x^2 + O(x^3); T==S S = x+O(x^2);T = O(y) + O(x); T==S S = x+x^2+ O(x^3);T = O(y) + x + O(x^2); T==S exp(x+O(x^200))*exp(-x+O(x^200)) exp(x+O(x^200))^2==exp(2*x+O(x^200)) subst(1+x^3+O(x^6),x,x+O(x^4)) subst(1+x^2+O(x^6),x,x+O(x^3)) subst(1+x^3+x^4+O(x^6),x,x+x^2+O(x^3)) subst(x^2+O(x^3),x,0*x) subst(x^2+O(x^3),x,Mod(0,3)*x) subst(x^2+O(x^3),x,O(3)*x) subst(1+x+O(x^2),x,0*x) subst(1+x+O(x^2),x,Mod(0,3)*x) subst(1+x+O(x^2),x,O(3)*x) subst(1+x^2+O(x^3),x,z) subst(1+x^2+y^2+O(x^3),x,z) laurentseries(x->sin(x)/x^2, 3) laurentseries(x->sin(x)/x^2, 3, t) laurentseries(x->(cos(x)-1)/x) f=1+4*t^2+36*t^4+O(t^6); g=q-4*q^3+14*q^5+O(q^7); subst(f,t,g) f=t^32000+O(t^32001); g=q*Ser(vector(32000,i,1),q); h=subst(f,t,g) f=q^32000+O(q^32001); h=subst(f,q,g) exp(1.*x + O(x^2)) exp(.*x) 1/(0.+x)+O(x^2) polcoef(0.+O(x),0) polcoef(Mod(0,2)+O(x),0) z=(Mod(2,17)*v1^-2+O(v1^-1))/(Mod(5,12)*v1^-4+O(v1)); z==1 z-1 s=taylor(1/((x-1)*(y-1)),x,5); taylor(s,y,5) \\ #2452 \\ #2559 (Mod(0,2)+O(x)) * (1+O(x)) \\ Errors. Keep at end of file polcoef(0.+O(x),1) polcoef(Mod(0,2)+O(x),1) subst(x^-1+O(x),x,Mod(0,3)) subst(O(x^-1),x,Mod(0,3)) subst(x^-1+O(x),x,0*x) subst(O(x^-1),x,0*x) Ser(1/x,y) Ser(x,y) Ser([x],y) Ser(x,, -5) Ser("") O(13^-5)/Mat(Mod(2,26)*y*x+(Mod(1,2)*y^-1+O(y^3))) laurentseries(1) laurentseries((x,y)->1) O(x) / Mod(0,5) O(x) / O(y) O(y) / O(x) pari-2.17.2/src/test/in/env0000644000175000017500000000016014567450071014061 0ustar billbillstrexpand("~root") #strexpand("~") > 1 strexpand("$AAA, $BBB, $AAA") getenv("AAA") getenv("__DOES_NOT_EXIST__") pari-2.17.2/src/test/in/vararg0000644000175000017500000000126414567450071014561 0ustar billbillmyprintsep(s,v[..])=if(#v>0,print1(v[1]);for(i=2,#v,print1(s,v[i])));print(); print(myprintsep) ?myprintsep arity(myprintsep) print1(":");myprintsep() print1(":");myprintsep(", ") myprintsep(", ",a,b,c,d) myprintsep(", ",a,,c,) myprintsep(,a,b,c,d) myprintf = printf; myprintf("x=%d\n",5) myprintf("x=%d y=%d\n",5,7) myprintf("x=%d y=%d z=%d\n",5,7,9) f1(x,y=0)=x+y; arity(f1) arity(()->1) default(strictargs,1) myprintsep(s,v[..])=if(#v>0,print1(v[1]);for(i=2,#v,print1(s,v[i])));print(); arity(myprintsep) print1(":");myprintsep() print1(":");myprintsep(", ") myprintsep(", ",a,b,c,d) myprintsep(,a,b,c,d) myprintsep(", ",a,,c,) make_function(a) = (b,c)->123; f=make_function(456); f(1) pari-2.17.2/src/test/in/extract0000644000175000017500000000250614676526175014763 0ustar billbillA=vector(100,i,i); for(i=35,99, print1(vecextract(A,1<f(x,4)); test(x->f(x,-4))) | f <- fun]; test(x->component(x,2)); test(x->component(x,10)); test(x->polcoef(x,-1)); test(x->polcoef(x,2)); test(x->polcoef(x,10)); polcoef(O(x),0) s=x*(y+O(x))+y; polcoef(s,0,y) polcoef(s,1,y) s=y+O(y^2); polcoef(s,0,x) polcoef(s,1,x) s=1/(1-2*x+O(x^3)) * 1/(1-3*y+O(y^3)); polcoef(s,2,y) vecextract(Vecsmall([3,4,5]),[2,3,1]) vecextract([1], 11) vecextract([1], "1..2") vecextract([1], 1/2) vecextract(1, 1) vecextract(matid(2),[3],[]) [1][2..3] [1][-10..3] 1[1..2] [1/2..1] [1..1/2] pari-2.17.2/src/test/in/select0000644000175000017500000000043614567450071014556 0ustar billbillselect(isprime, vector(50,i,i^2+1)) select(isprime, List([1,2,3,4,5]), 1) select(isprime, List([1,2,3,4,5])) select(x->(x<100), %) select(x->x, [0,1,2;0,2,0]) select(x->!x, [0,1,2;0,2,0]) [x|x<-List(),x%2] [x|x<-List([1..4]), x%2] v=Vecsmall([1,2,3]); select(x->x,v,1) select(x->x,v) pari-2.17.2/src/test/in/ellpadic0000644000175000017500000000414514676526175015067 0ustar billbilldefault(parisize,"12M") \\ overflows 10M e=ellinit([1,-1,1,-1,-14]); E=ellinit([0,0,0,-e.c4/48,-e.c6/864]); P=[1,-1/4;0,1]; { forprime(p=3,40,if(p==17,next); A=ellpadicfrobenius(e,p,10); B=ellpadicfrobenius(E,p,10); if(P*B!=A*P,error(p))); } Ep=ellinit(E,O(3^5)); [ellintegralmodel(Ep,&v)[1..5],v] elllocalred(Ep) elllocalred(ellchangecurve(Ep,[3,0,0,0])) elllocalred(ellchangecurve(Ep,[1/3,0,0,0])) E=ellinit([1,-1,1,0,0]);P=[0,0]; ellpadicheight(E,2,4, P) ellpadicheight(E,3,4, P) ellpadicheight(E,5,4, P) E=ellinit([0,-1,1,-10,-20]);P=[5,5]; ellpadicheight(E,19,6, P) ellpadicheight(E,19,0, P) Ep=ellinit([0,-1,1,-10,-20], O(11^5)); [ellap(Ep), ellap(Ep,11)] [ellcard(Ep), ellcard(Ep,11)] [ellgroup(Ep), ellgroup(Ep,11)] [ellissupersingular(Ep), ellissupersingular(Ep,11)] ellpadics2(Ep,11,5) E=ellinit([1,0,1,-6,4],O(5^5)); ellissupersingular(E) lift(ellpadicfrobenius(E,5,5)) ellinit([1,1,1,1,1],O(2^2)).group ellinit([0,2],O(2^2)).group ellinit([1,1,2,1,1],O(2^2)).group ellinit([1,3,1,2,2],O(3^2)).group ellinit([1,2,2,2,3],O(3^2)).group ellinit([1,1,3,1,3],O(3^2)).group ellinit([3,4],O(5^2)).group ellinit([0,5],O(5^2)).group ellinit([2,2],O(5^2)).group E=ellinit([0,0,1,-4,2]);P=[-2,1]; ellpadicheight(E,3,5, P) P2 = ellmul(E,P,2); ellpadiclog(E,3,5,P) ellpadiclog(E,3,5,P2) E=ellinit([0,0,1,-7,6]); P=[-2,3]; P2=ellmul(E,P,2); Q=[-1,3]; Q2=ellmul(E,Q,2); R=[0,2]; ellpadicheight(E,2,5, P,Q2) ellpadicheight(E,2,5, P2,Q) M=ellpadicheightmatrix(E,5,5, [P,Q,R]); lift(M) ellpadicheight(E,3,5, P)*[1,2]~ ellpadicheight(E,3,5, P,Q)*[1,2]~ matdet(M[1]) matdet(M[2]) E=ellinit([-577/48,14689/864]); ellpadics2(E,43,6) E=ellinit([1,0,1,-460,-3830]); ellpadics2(E,5,6) E=ellinit([0,0,1,-1,0]); \\ 37a1 ellpadics2(E,5,6) ellpadicbsd(E,7,10) ellpadicbsd(E,37,10) E=ellinit([0,1,1,-7,5]); ellpadicbsd(E,7,5) ellpadicregulator(E,7,5,[[-1,3]]) ellpadicbsd(E,7,5,-4) E=ellinit([1, -1, 1, 0, 0]); ellpadicfrobenius(E,5,7) E=ellinit([0,0,1,-4,2]); ellpadicfrobenius(E,3,5) \\ ERRORS keep at end of file ellap(Ep,2) ellpadics2(Ep,2,5) ellcard(Ep,2) ellgroup(Ep,2) ellissupersingular(Ep,2) elllocalred(Ep,2) ellgroup(ellinit([5^6,5^6]),5,1) pari-2.17.2/src/test/in/lfunlarge0000644000175000017500000000222614723617446015262 0ustar billbilldefault(parisize,20M); default(realprecision,38); lfun(-4,1/2+10^6*I) lfun(101,1/2+10^5*I) exponent(lfun(Mod(3,4),1/2+10^5*I)-lfun(-4,1/2+10^5*I)) < -128 lfun(Mod(3,5),1/2+10^5*I) lfun(Mod(2,10^3+1),1/2+10^3*I) exponent(lfun(Mod(2,7),1/2-10^4*I)-conj(lfun(Mod(4,7),1/2+10^4*I))) < -128 lfunhardy(Mod(3,5),10^8) lfunzeros(Mod(3,5),[10^6,10^6+1]) exponent(lfun(1,1/2+3000*I)-zeta(1/2+3000*I)) < -125 exponent(lfun(1,1/4+3000*I)-zeta(1/4+3000*I)) < -123 exponent(lfun(1,3/5+3000*I)-zeta(3/5+3000*I)) < -125 lfun(1,1/2+10^6*I) lfun(1,1/2+10^10*I) lfun(1,1/2+10^12*I) lfunhardy(1,10^14) lfunzeros(1,[10^10,10^10+1]) default(realprecision,211) zeta(1/2+10^8*I) exponent(lfun(1,1/2+12000*I)-zeta(1/2+12000*I)) < -128 lfun(1,1/2+10^12*I) z0=solve(t=10^10-0.2,10^10,lfunhardy(1,t)) exponent(lfun(1,1/2+z0*I)) default(realprecision,38) lfun(polcyclo(7),1/2+10^10*I) lfun(polsubcyclo(13,3),1/2+10^10*I) L=lfuninit(1, []); lfun(L,1/2+10^10*I) L=lfuninit(Mod(3,5), []); lfun(L,1/2+10^10*I) L=lfuninit(polsubcyclo(13,3),[]); lfun(L,1/2+10^10*I) zeta(1/2+3000*I) zeta(1/2+10^(-10)+3000*I) lfun(-4,1/2+3000*I) lfun(-4,1/2+10^(-10)+3000*I) lfun(-4,1/2+8000*I) lfun(-4,1/2+8000*I+10^(-10)) pari-2.17.2/src/test/in/pol0000644000175000017500000000467514676526175014114 0ustar billbillo = [Mod(0,3),y,1/y, (y^2+1)/y, [1,2,3], Vecsmall([1,2,0]), Qfb(1,2,4), Qfb(1,2,-4), y+2*y^2+O(y^4)]; { for (i=1,#o, my (v = o[i]); printsep(" ", Pol(v,y), Pol(v,x), Polrev(v)); printsep(" ", Ser(v,y), Ser(v,x), Ser(v,,5)); ) } o = [2*x+3*y, 2+x+y+O(x^2), 2+x+y+O(y^2)]; { for (i=1,#o, my (v = o[i]); printsep(" ",pollead(v), pollead(v,x), pollead(v,y)) ) } polrecip(1) pollead(z,y) pollead(y,z) polgraeffe(x^2+x+1) polgraeffe(x^3+x+1) polsym(2*x^4+1,4) poltomonic(9*x^2-1/2) U=poltomonic(9*x^2-1/2,&L);[U,L] poltomonic(x^2+4) U=poltomonic(x^2+4,&L);[U,L] poltomonic(2*x,&L); L norm(I*x+1) norm(Mod(0,x^0)) norm(Mod(1,x^0)) norm(Mod(x^0,x^0)) trace(I*x+1) trace(Mod(0,x^0)) trace(Mod(1,x^0)) trace(Mod(x^0,x^0)) matcompanion(2*x^2+1) serlaplace(1+x+x^2) serlaplace(x^2+x^3) serlaplace(1) test()= { my(P,a,V); P=x^4+7*x^3+12*x+5;Q=7*y^3-y-1;Q1=y^3-y-1; a=ffgen([11,5],'a); b=ffgen([2,10],'b); V=[P, x^4+7/2*x^3+12/7*x+5/4, P*Mod(1,11), subst(P,x,x+a), subst(P,x,x+b), subst(P,x,x+y)*Mod(1,Q1), subst(P,x,x+y)*Mod(1,Q), subst(P,x,x+y/3)*Mod(1,Q1), subst(P,x,x+y/3)*Mod(1,Q), subst(P,x,x+y)*Mod(Mod(1,11),Q*Mod(1,11)) ]; for(i=1,#V, my(R=V[i],R2=R^2,RI=polrecip(R)); if(R2!=R*(R+1)-R,error(R)); if((R+1)^2%R!=1,error(R)); if(R^2%R!=0,error(R)); if(Mod(R,R2+R-1)^-1*R!=1,error(R)); my(U=gcd(R2,R*(R+1)));if(U!=R*pollead(U),error([R,U])); my([U,V,D]=gcdext(R,RI));if(U*R+V*RI!=D,error([R,U*R+V*RI-D])); if(poldisc(R)*'z^12!=poldisc(subst(R,x,x/'z)*z^4),error(R)); print(i,":",R2)); print("done"); } test() check(A)=if(A^2+A!=A*(A+1),error(A)); A=Mod(-6,y^2-2)*x+Mod(48*z+60,y^2-2);B=Mod(1,y^2-2)*x+Mod(10,y^2-2); A*B A=Mod(1,z^2-z-1)*y+(Mod(1/2*z+1/2,z^2-z-1)*x+Mod(1/2*z+1/2,z^2-z-1)); check(A) A=x^2+y*z*x+Mod(1,y^2+3); check(A) A=x^4+x*y^5+Mod(1,y^2+1); check(A) A=x^4+x*y^5+Mod(1,5*y^2+y+1); check(A) T=x^2+2; polrootsbound(T) polrootsbound(T, 1e-5) \\#1651 f1=(x-1)/(x*x-x); type(subst(1/f1,x,1)) \\#1690 P(x,y)=(x+1)*y^2+(x^2-x+1)*y+(x^2+x); T = P(exp(I*Pi),y); polroots(T) exponent(polrootsbound(T)) polrootsbound('x) \\ call newton_polygon with 2 successive vanishing coefs polroots(x^5-1370*x^3+375380*x+2477386) \\#2286 polroots(1.E-47*t^6 + 1.E-47*t^5 + 4.E-46*t^4) \\#2418 polroots(4*x^3+4*x^2+28*x+144) polzagier(-1,1) \\#2558 f = Mod(Mod(1,3), Mod(a^2+2,3))*x^3 (1/f) * O(x^2) \\ Errors polrootsbound(Pol(0)) polrootsbound(1) Pol("") (1/x) % x poltomonic(Pol(0)) pari-2.17.2/src/test/in/concat0000644000175000017500000000122214567450071014540 0ustar billbillA=[1,2;3,4]; B=[5,6]~; C=[7,8]; D=9; matconcat([A, B]) matconcat([A, C]~) matconcat([A, B; C, D]) matconcat([1, [2,3]~, [4,5,6]~]) matconcat([1, [2,3], [4,5,6]]~) matconcat([B, C; A, D]) matconcat([]) concat("x",2) concat([;],1) concat([;],[]) concat([;],[1]) concat(1,[;]) concat([],[;]) concat([1],[;]) concat(1,2) concat(1,[2]) concat(1,Mat(2)) concat(1,A) concat(Mat(2),1) concat(A,1) concat([1,2],[]~) concat([1,2],[1]~) concat([1,2],[1,2]~) concat([2,3], matid(2)) concat([]~,[1,2]) concat([3]~,[1,2]) concat([2,3]~,[]) concat([2,3]~,[1]) concat([2,3]~,[1,2]) concat([;],[]) concat(A,[1,2]) concat(List([[1],[2]])) concat([1]~,Mat(2)) concat(List([])) pari-2.17.2/src/test/in/graph0000644000175000017500000000175014676526175014412 0ustar billbillHEAP=[31, if(sizebyte(0)==16,362,366)]; \e plotinit(0,500,500) plotmove(0,0,0);plotbox(0,500,500) plotmove(0,200,150) plotcursor(0) write("pari.ps", plotexport("ps", 0)) plotinit(1,700,700) plotkill(1) plotmove(0,0,900);plotlines(0,900,0) plotlines(0,vector(5,k,50*k),vector(5,k,10*k*k)) plotmove(0,243,583);plotcursor(0) plot(x=-5,5,sin(x),-1,1) plotpoints(0,225,334) plotpoints(0,vector(10,k,10*k),vector(10,k,5*k*k)) write("pari.ps", plotexport("ps", [0,20,20])) write("pari.ps", plothexport("ps",x=-5,5,sin(x))) write("pari.ps", plothexport("ps",t=0,2*Pi,[sin(5*t),sin(7*t)],1,100)) write("pari.ps", plothrawexport("ps",vector(100,k,k),vector(100,k,k*k/100))) plotmove(0,50,50);plotrbox(0,50,50) plotrline(0,200,150) plotcursor(0) plotrmove(0,5,5);plotcursor(0) plotrpoint(0,20,20) plotinit(3,600,600);plotscale(3,-7,7,-2,2);plotcursor(3) plotmove(0,100,100);plotstring(0,Pi) plotmove(0,200,200);plotstring(0,"(0,0)") write("pari.ps", plotexport("ps", [0,10,10])) if (getheap()!=HEAP, getheap()) pari-2.17.2/src/test/in/hyperell0000644000175000017500000000451114567450071015121 0ustar billbillhc(P,p)= { print(centerlift(hyperellpadicfrobenius(P,p,3))); checkfeq(hyperellcharpoly(P*Mod(1,p)),p); } checkfeq(P,q)= { for(i=0,poldegree(P),if (type(polcoeff(P,i))!="t_INT",error(dbg_x(P)))); my(M=minpoly(Mod(x+q/x,P))); if(poldegree(M)!=poldegree(P)/2,error([P,q,M])); M; } { for(g=1,6, for(n=1,2*g, my(H=n*(x^(2*g+1)-2*x^n+1)); printsep(":",g,n,hc(H,19)))) } { for(g=1,5, for(n=1,2*g+1, H=n*(x^(2*g+2)-3*x^n+1); printsep(":",g,n,hc(H,29)))) } { forprime(p=3,7, print(hc(x^6+x+1,p))); forprime(p=3,11, print(hc(x^10+x+1,p))); forprime(p=3,7, g=ffgen(ffinit(p,3),'g); H=hyperellcharpoly((x^6+g*x+1)); print(checkfeq(H,p^3))); } { my(a,P,Q,E); a=ffgen([5,5],'a); setrand(3); for (i=1, 10, P=random(a*x^3); H=hyperellcharpoly(P); E=ellinit(ellfromeqn('y^2-P)); if(ellap(E)!=-polcoeff(H,1),error(H))); } P=hyperellcharpoly(Mod(1,3)*(x^10+x^4+x^3+2*x^2+x));checkfeq(P,3) P=hyperellcharpoly(Mod(1,3)*(x^12+x^4+1));checkfeq(P,3) P=hyperellcharpoly(Mod(1,3)*(x^14+x^4+2));checkfeq(P,3) g=ffgen(ffinit(79,2),'g); P=hyperellcharpoly(x^5+g*x^3+2*x+5);checkfeq(P,79^2) P=hyperellcharpoly(g*(x^5+g*x^3+2*x+5));checkfeq(P,79^2) P=hyperellcharpoly(x^5+Mod('g,g.mod*Mod(1,79))*x^3+2*x+5);checkfeq(P,79^2) P=hyperellcharpoly(x^6+g*x^3+2*x+5);checkfeq(P,79^2) P=hyperellcharpoly(g*(x^6+g*x^3+2*x+5));checkfeq(P,79^2) P=hyperellcharpoly((x^7+x^3+2*x+5)*Mod(1,79));checkfeq(P,79) P=hyperellcharpoly((x^8+x^3+2*x+5)*Mod(1,79));checkfeq(P,79) P=hyperellcharpoly([x^5+x+1,x]*Mod(1,79));checkfeq(P,79) P=hyperellcharpoly((x^3+x+1)*ffgen(3^2)^0);checkfeq(P,9) P=hyperellcharpoly([x^5+x+1,x+1]*Mod(1,2));checkfeq(P,2) P=hyperellcharpoly([x^5+x+1,x^2+x+1]*Mod(1,2));checkfeq(P,2) P=hyperellcharpoly([x^5+x+1,x^3]*Mod(1,2));checkfeq(P,2) P=hyperellcharpoly([x^6+x^5+x^4+1,x+1]*Mod(1,2));checkfeq(P,2) P=hyperellcharpoly([x^6+x+1,x^2]*Mod(1,2));checkfeq(P,2) P=hyperellcharpoly([x^6+x+1,x^3]*Mod(1,2));checkfeq(P,2) P=hyperellcharpoly([x^2+x+1,x^3]*Mod(1,2));checkfeq(P,2) P=hyperellcharpoly([x^3+x+1,x^3]*Mod(1,2));checkfeq(P,2) P=hyperellcharpoly([x^4+x+1,x^3]*Mod(1,2));checkfeq(P,2) g=ffgen(ffinit(7,3),'g);P=hyperellcharpoly(x^5+g);checkfeq(P,7^3) liftall(hyperellpadicfrobenius(x^5+'a*x+1,['a^2+1,3],10)) \\ error hyperellcharpoly((256*a^5+5)*Mod(1,5)) hyperellcharpoly((256*a^5+5)*ffgen(5^2)) pari-2.17.2/src/test/in/matsnf0000644000175000017500000003365714676526175014614 0ustar billbillminpoly([-5,0,-1,1;0,-5,-1,-1;1,1,-5,0;-1,1,0,-5]) minpoly([-5,0,-1,1;0,-5,-1,-1;1,1,-5,0;-1,1,0,-5]/3) minpoly([-5,0,-1,1;0,-5,-1,-1;1,1,-5,0;-1,1,0,-5]/a) minpoly([-5,0,-1,1;0,-5,-1,-1;1,1,-5,0;-1,1,0,-5]*a) matsnf([1,2;3,4],2) matsnf([-X-5,-1,-1,0;0,X^2+10*X+26,-1,-X-5;1,-X-5,-X-5,1;-1,0,0,1],2) minpoly([a+4/51*d,29/51*d,55/17*d,-9/17*d;-11/51*d,a+35/51*d,-11/17*d,12/17*d;23/51*d,1/51*d,a+6/17*d,-5/17*d;11/17*d,16/17*d,33/17*d,a-19/17*d]) D=[36,12,2]; snfrank(D, 2) snfrank(D, 4) snfrank(D, 8) snfrank(D, 3) snfrank(D, 0) snfrank(D) p=2^64+13; D=[6*p^3, 2*p^2, p^2, p, 1]; snfrank(D, p^3) snfrank(D, p^2) snfrank(D, p) D=matsnf([-x-5,-1,-1,0; 0,x^2+10*x+26,-1,-x-5; 1,-x-5,-x-5,1; -1,0,0,1]); snfrank(D, x^2 + 10*x + 27) A=matdiagonal([x-1,x^2+1,x-1,(x^2+1)^2,x,(x-1)^2]); D=matsnf(A); snfrank(D,x-1) snfrank(D,(x-1)^2) snfrank(D,(x-1)^3) snfrank(D,x^2+1) snfrank([0,12,1,1]) snfrank([0,12,1,1], 2) snfrank([0,x,1,1]) snfrank([0,x,1,1], x) checkfrobenius(M)= { my([F,B] = matfrobenius(M,2)); if(M!=B^-1*F*B, error("matfrobenius:",M)); F } { for(i=1,15, print(checkfrobenius(matrix(i,i,k,j,k>=j)))); for(i=1,10, print(checkfrobenius(matpascal(i)))); for(i=1,8, print(checkfrobenius(mathilbert(i)))); } matsnf(matdiagonal([x,0,x]), 2) matsnf(matdiagonal([1+x,0,x]), 2) \\Bug #1208 matsnf([0;1;2], 4) matsnf([0;1;2], 5) matsnf(Mat([0,1,2]), 4) matsnf(Mat([0,1,2]), 5) m=[2*x^6+x^5+2*x^4+2*x^3+x^2+2*x+2,2*x^5+x^3+2*x^2+2,x^3+x^2+x;2*x^6+x^3+x+2,2*x^5+2*x^4+x^3+2*x,x^3+2*x^2+2*x;2*x^6+x^4+x^3+2*x^2+2,2*x^5+2*x^4+2*x^3+x^2+2,x^3+2*x^2+x+2];matsnf(m*Mod(1,3), 2) m=[1,0,0,1,1,1,1,1,0;1,0,0,1,1,0,1,0,0;0,0,0,0,1,0,0,1,0;0,0,0,0,1,1, 0,0,1;0,1,0,0,0,1,1,0,1;1,1,1,0,0,0,1,1,0;0,0,1,0,0,1,0,1,1;0,0,1,1,1,1,0,1,0;0, 1,0,0,0,0,1,1,0]*1.; round(matfrobenius(m)) round(minpoly(m)) m=[27,0;0,3;1,1;0,0]; v=matsnf(m,1+4) snfrank(v,3) v=matsnf(m,1) snfrank(v,3) a=[32,16,8,4,8,16,4,4,8,4,4,16,0,4,8,0,28,12,16,4,20,6,4,14,30,18,20,24,22,0,0,0,0,0,0,0,10,0,9,18,26,9,20,26,27,18,3,4,19,21,23,19,11,7,18,10,28,31,26,3,31,7,19,11,25,27,13,31,9,5,9,31,3,24,14,1,0,16;0,16,0,4,0,8,0,2,0,0,0,8,0,0,0,0,10,0,12,0,6,0,12,0,10,10,12,14,14,2,2,2,0,0,0,0,12,2,14,0,6,14,4,0,14,5,2,11,6,8,2,3,14,11,13,0,6,11,5,14,2,0,4,3,8,3,3,3,0,8,10,11,6,6,12,12,14,5;0,0,8,4,0,0,4,4,0,4,0,0,2,4,0,0,6,4,4,0,4,4,6,6,6,0,4,2,2,2,0,0,2,2,0,0,6,2,1,6,2,1,4,4,0,6,4,3,5,6,6,7,5,6,0,6,2,3,2,5,1,1,4,7,6,2,7,4,3,7,5,3,3,6,3,3,4,0;0,0,0,4,0,0,0,2,0,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,2,0,0,2,2,2,0,0,0,0,0,2,0,0,2,0,0,0,3,1,3,2,1,1,2,3,3,2,3,2,2,0,2,0,0,1,0,0,3,1,0,0,3,1,0,2,3,3,0,0,2,0;0,0,0,0,8,0,4,0,0,0,4,0,2,0,0,2,4,4,0,4,4,2,6,6,6,2,4,4,4,2,0,0,2,2,0,0,2,2,0,4,6,0,6,2,6,3,3,6,4,1,0,4,0,4,1,1,2,3,1,1,6,1,6,5,4,2,5,1,5,6,3,6,0,6,4,3,0,4;0,0,0,0,0,8,0,2,0,0,0,0,0,0,0,0,6,0,6,0,6,0,2,0,6,6,0,0,2,0,0,0,0,0,0,0,4,0,7,0,4,7,4,0,7,6,5,5,4,5,6,3,6,3,1,7,3,5,6,6,6,1,5,1,4,7,7,4,0,7,2,0,2,4,4,3,4,6;0,0,0,0,0,0,4,0,0,0,0,0,2,0,0,2,0,2,2,0,0,2,0,0,0,0,0,2,2,0,0,0,0,0,0,0,2,0,3,0,2,3,2,0,2,1,2,2,2,2,2,0,2,3,3,0,3,1,2,0,3,1,1,1,3,1,2,1,1,3,2,0,2,0,1,1,0,0;0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,0,1,0,0,1,0,1,0,0,0,1,1,1,1;0,0,0,0,0,0,0,0,8,4,4,0,2,0,0,0,4,0,2,0,0,4,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,6,0,2,6,2,6,3,7,4,5,0,4,7,4,5,5,4,2,4,3,1,6,0,1,6,6,1,3,5,7,3,1,1,0,5,1,0,5,4;0,0,0,0,0,0,0,0,0,4,0,0,2,0,0,0,0,2,0,0,2,0,0,0,0,0,2,2,2,2,0,0,2,2,0,0,0,2,0,2,2,0,2,2,3,3,3,3,1,2,3,2,3,1,3,3,2,3,1,3,3,2,1,2,3,3,3,3,2,1,1,2,1,2,3,1,3,2;0,0,0,0,0,0,0,0,0,0,4,0,2,0,0,0,2,0,2,0,2,2,2,2,2,0,2,2,2,2,0,0,2,2,0,0,0,2,3,0,2,3,0,0,3,0,2,2,0,0,3,3,0,1,3,0,0,2,2,0,2,3,0,3,1,2,0,1,2,1,3,3,2,2,1,2,3,2;0,0,0,0,0,0,0,0,0,0,0,8,0,4,0,0,0,0,0,4,6,6,4,2,2,0,6,4,4,2,2,2,0,0,0,0,0,2,5,0,2,5,0,4,5,0,6,2,1,4,6,4,3,2,1,2,7,5,3,5,4,6,0,0,0,7,3,5,7,1,1,1,7,2,0,1,0,6;0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,1,0,1,0,0,1,1,1,1,0,0,0,1,1,0,0,1,0,0,0,1,1,1,1,1,1,0,0,0,0,1;0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,2,0,0,2,2,2,0,0,0,2,2,2,2,2,0,0,0,0,0,2,1,0,0,1,0,2,0,1,0,3,2,0,3,2,2,2,0,0,1,0,0,3,0,2,0,1,0,2,0,0,2,0,0,2,1,0,1,2,1,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,2,0,6,0,0,2,0,6,2,2,2,2,6,6,0,0,0,0,0,0,0,4,0,4,4,0,4,0,4,4,1,6,1,2,3,3,3,1,4,5,3,6,6,3,3,1,5,2,5,7,1,7,6,3,4,6,2,3,2,7,0,5,6;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,1,1,0,1,1,0,1,0,1,0,1,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,1,1,0,0,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,1,0,1,0,1,0,1,1,0,0,1,0,0,1,1,0,1,0,1,1,1,1,0,1,1,0,1,0,1,0,0,1,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,1,0,1,1,1,1,0,0,1,0,0,1,1,1,1,1,1,0,1,0,1,0,0,1,0,0,0,1,1,0,0,1,1,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,1,0,1,1,1,0,0,0,0,1,1,0,1,1,1,1,0,1,1,0,1,0,0,0,0,1,0,0,0;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,2,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,2,3,0,2,2,3,3,2,2,1,1,1,3,0,3,1,1,0,3,2,1,2,0,3,3,1,3,3,1,1,1,0,3,2,1,0,1,2;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0,1,1,0,0,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,0,0,0,0;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,1,1,0,1,0,0,0,0,1,0,0,1,1,0,1,1,0,1,1,1,1,1,1,0,0,1,0,1,0,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,1,0,0,0,0,1,0,0,0,0,0,1,1,0,1,0,0,0,0,0,1,0,1,0,0,1,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,1,1,0,0,1,1,1,0,0,0,0,0,0,1,0,1,0,0,0,1,0,1,0,1,1,1,1,1,0,0,1,1,1,0;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,1,0,1,1,1,1,1,0,1,0,1,1,0,1,1,1,1,0,1,1,0,0,0,0,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1,1,0,1,0,0,0,0,0,0,1,1,0,1,1,0,1,1,0,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,1,1,1,0,0,1,0,1,0,1,1,1,0,1,1,1,1,1,0,0,1,1,0,1,1,0,0;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,1,1,1,0,0,1,0,1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,1,1,0,1,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,1,1,1,0,1,0,0,1,0,1,1,1,0,1,1,0,0,1,1,0,0,1,1,1,1,1,1,1,1,0,1,1,0,0;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,24,24,8,8,4,8,6,24,10,2,4,2,0,4,2,0,20,12,31,3,11,22,26,27,5,12,0,16,3,23,27,5,25,17,2,24,28,11,28,14,22,16,23,20,15,4,16,17;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,6,0,0,0,4,4,6,0,4,4,1,4,0,4,2,2,4,1,7,7,5,4,5,7,2,1,7,1,5,3,3,6,4,5,5,7,4,6,6,4,5,6;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,4,0,0,0,2,0,0,2,0,2,6,2,7,5,4,2,2,3,2,6,6,6,2,3,0,7,0,7,0,0,3,0,6,7,3,4,1,1,3,7,6,2,2,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,6,4,0,6,6,0,0,2,0,3,1,3,2,7,1,5,5,7,2,3,3,3,3,6,7,1,2,5,4,3,4,3,1,7,1,6,0,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,8,4,0,4,0,2,2,6,2,6,4,4,6,0,3,1,2,4,6,0,3,1,5,1,7,2,4,1,5,5,1,4,0,7,0,2,7,2,0,1,5,7,3,1,5;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,2,0,0,2,0,2,2,0,3,1,2,2,0,3,2,2,2,0,0,3,0,1,0,1,2,0,3,2,2,3,1,2,2,0,3,3,1,1,0,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,8,6,0,4,2,4,4,0,4,0,6,0,6,3,1,1,2,4,1,7,1,1,5,7,3,4,0,5,6,3,4,0,0,3,1,1,0,6,1,6,7,1,6;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,1,0,0,1,0,1,0,1,1,1,0,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,0,1,0,0,0,0,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,6,0,2,6,1,6,7,7,2,0,7,2,1,3,0,0,0,3,7,3,1,4,3,0,0,0,6,7,0,4,0,3,7,6,0,0,7,7;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,2,3,1,1,3,0,3,1,2,0,2,3,0,1,2,2,0,3,0,1,3,2,2,3,1,1,2,3,2,1,0,3,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,2,0,0,0,0,1,0,0,1,1,0,1,1,1,0,1,1,1,1,1,0,0,0,0,1,1,0,1,0,1,1,1,1,1,1,0,1,1,0;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,1,0,0,1,1,0,1,0,1,1,1,0,0,0,0,0,0,1,0,0,1,0,0,1,1,0,0,0,1,0,1,0,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,2,2,3,0,0,3,0,3,0,2,0,2,2,3,1,2,1,1,3,0,0,1,2,2,1,3,0,2,0,0,1,0,1,0,2;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,1,1,0,0,1,1,1,0,1,0,1,0,1,1,1,0,0,0,0,1,0,1,0,1,1,0,1,1,1,0,1,0,1,0;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,1,0,0,0,1,0,0,0,1,1,0,0,1,1,0,0,1,0,0,0,0,0,1,0,1,1,1,1,1,1,0;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,6,6,6,2,6,6,0,0,0,0,0,0,0,0,4,4,0,4,4,0,0,0,0,0,4,3,0,5,0,5,0,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,1,1,1,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,1,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,0,1,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,4,4,0,0,2,4,6,2,2,2,2,4,0,0,0,2,4,3,1,4,4,0,0,6,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,2,2,0,2,2,0,0,2,2,2,0,0,0,0,2,1,2,2,0,3,3,1,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,4,0,0,0,0,2,2,2,0,0,2,0,0,0,2,2,2,0,1,0,2,2,3,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,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,1,0;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,0,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,2,2,2,2,2,2,2,0,0,0,1,1,2,1,3,1,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,1,0,0,1,0,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,1,0,1,0,1,1,0;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1,0,0,1,0,0,0;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,1,0,0,1,1,1,0,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,1,1,1,0,0,0,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,1,1,0;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,2,1,3,0,1,0,3,2,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,2,1,1,0,1,0,1,0,1;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,2,0,0;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2]; matsnf(a) default(parisize,"88M"); \\ overflows 86M in 32bit [u,v,d] = matsnf(a,1); u*a*v == d pari-2.17.2/src/test/in/ellmanin0000644000175000017500000000023114676526175015101 0ustar billbill\\package:elldata default(parisize,"10M"); { forell(e,1,100, my(E=ellinit(e[2]), m = ellmaninconstant(E)); if (m!=1,print(e[1],":",m)); ); } pari-2.17.2/src/test/in/deriv0000644000175000017500000000223714676526175014423 0ustar billbillsin'(4) sin'(1+I) sin'(x) derivnum(x=4,sin(x)) derivnum(x=t^2+O(t^4),sin(x)) derivnum(x=t,sin(x)) derivnum(x=1/(1+t),sin(x)) derivnum(x=1,Pi^x) v=[Mod(x*y+1,x^2+1), Mod(1,3), ffgen(2^3,'t), 1+x*y+O(x^3), x/(x+y), (x^3/3+x+1) / (x^2+1)^2, [x*y], Mat(x*y)]; { for (i=1,#v, my(u=v[i]); print(deriv(u,'x)); print(u'); print(derivn(u,2,'x)); print(deriv(u,'y)); print(derivn(u,2,'y)); iferr(print(intformal(u,'x)),E,print(E)); iferr(print(intformal(u,'y)),E,print(E)); ) } intformal(1-A,Y) a=intformal(Pol(0,x), y) b=intformal(Pol(0,y), x) variable(a) variable(b) a=intformal(O(x), y) b=intformal(O(y), x) variable(a) variable(b) f(x) = (x^2+x)*'y; f'(1) f''(1) derivn(f,2)(1) derivnum(x=0,1/(x^2+1),2) derivnum(x=2.0,1/(x^2+1),2) derivnum(x=1+I,1/(x^2+1),2) derivnum(x=t,1/(x^2+1),2) derivnum(x=1/t,1/(x^2+1),2) derivnum(x=0,exp(sin(x)),16) round( derivnum(x=0,exp(sin(x)),[0..13]) ) derivnum(t=0,1,[]) \\ #2216 derivnum(t=x^2,exp(t),4) derivnum(t=x^2+O(x^20),exp(t),4) derivnum(z=0,0,0) \\ #2162 deriv(2/(4*x^2+1),x) \\ ERORS derivnum(z=0,0,[0,-1]) derivnum(z=0,0,[1,-1]) derivnum(z=0,0,x) derivn(cos,-1) derivn(cos,1,'x) sin'("") sin''("") (x->x)'("") (x->x)''("") pari-2.17.2/src/test/in/dirmul0000644000175000017500000000130114567450071014563 0ustar billbilldirmul([0,1],[0,1]) dirdiv([0,1,1,1,1],[1]) dirmul(vector(10,n,moebius(n)),vector(10,n,1)) dirmul([1,2,3,4],[1,2,3,4]) dirdiv([1,2,3,4],[1,2,3,4]) dirdiv([1,2,3,4],2*[1,2,3,4]) direuler(p=1.5,10.5,1/((1-X)*(1-p*X))) direuler(p=2,10,1/((1-X)*(1-p*X)), -1) direuler(p=2,10,1/((1-X)*(1-p*X)), 1) direuler(p=2,10,1/((1-X)*(1-p*X)), 2) direuler(p=2,10,1/((1-X)*(1-p*X)), 3.5) direuler(p=2,10,-1/(X^2-1)) direuler(p=2,10,(X^2-1)/(X^3+X-1)) direuler(p=I,10.5,1/((1-X)*(1-p*X))) direuler(p=2.5,I,1/((1-X)*(1-p*X))) direuler(p=2,10,1/((1-X)*(1-p*X)), I) direuler(p=2,1,1/((1-X)*(1-p*X)), 1) direuler(p=2,2,1/((1-X)*(1-p*X)), 2) direuler(p=2,2,1/((1-X)*(1-p*X)), 5) direuler(p=2,10,1/2) direuler(p=2,10,1/(x-2)) pari-2.17.2/src/test/in/alghasse0000644000175000017500000002040214760124241015051 0ustar billbilldefault(parisize,"12M"); \\ 10M overflows on 64 bit \\Tests related to hasse invariants in algebras do(name, test) = { setrand(1); print(name,": ", iferr(test(), E, E)); } gusuite(name, tests) = print("Suite: ", name); tests(); searchin(hf,pr,h) = { for(i=1,#hf[1], if(hf[1][i]==pr, return(hf[2][i]==h))); return(h==0); } samehasse(hf1,hi1,hf2,hi2) = { if (hi1 != hi2, return(0)); for (i=1, #hf1[1], if (!searchin(hf2,hf1[1][i],hf1[2][i]), return(0))); for (i=1,#hf2[1], if (!searchin(hf1,hf2[1][i],hf2[2][i]), return(0))); return(1); } hassetriv(hf,hi) = samehasse(hf,hi,[[],Vecsmall([])],Vecsmall(vector(#hi,i,0))); altriv(al) = hassetriv(alghassef(al),alghassei(al)); alsame(al,hf,hi) = samehasse(alghassef(al),alghassei(al),hf,hi); alcheckhasse(al) = { my(n,h); n = algdegree(al); h = Mod(0,n); for(i=1, #alghassef(al)[1], h += alghassef(al)[2][i]); for(i=1, #alghassei(al), h += (n/2)*alghassei(al)[i]); return(h == Mod(0,n)); } al_cyclotomic(p,b,fl=3) = { my(Q,F,pc,r); Q = nfinit(y); pc = polcyclo(p,x); F = rnfinit(Q,pc); r = lift(znprimroot(p)); return(alginit(F, [Mod(Mod(1,y)*x^r,pc), b], 'x, fl)); } hasse0() = gusuite("hasse sum to 0", ()->{ do("cyclo construction", ()->al_cyclotomic(3,-175624635)); do("cyclo ramified at infinity", ()->alcheckhasse(al_cyclotomic(3,-175624635))); do("cyclo unramified at infinity", ()->alcheckhasse(al_cyclotomic(3,2763764))); do("cyclo 5", ()->alcheckhasse(al_cyclotomic(5,7861623))); do("cyclo 5 bis", ()->alcheckhasse(al_cyclotomic(5,6569846846546548798*25))); do("cyclo 7 bis no mo", ()->alcheckhasse(al_cyclotomic(7,168656465154165487*7^3,2))); do("cyclo 11 no mo", ()->alcheckhasse(al_cyclotomic(11,87165765,2))); do("quat -1,-1 over Q", ()->alcheckhasse(alginit(nfinit(y),[-1,-1]))); do("quat -1,-1 over Q(sqrt(2))", ()->alcheckhasse(alginit(nfinit(y^2-2),[-1,-1],x))); do("quat -1,-1 over Q(sqrt(60))", ()->alcheckhasse(alginit(nfinit(y^2-60),[-1,-1],x))); }); alfromhasse() = gusuite("algebra from Hasse invariants", ()->{ my(nf, pr7, pr13, finvm, finv, finv1, finv2, iinvm, iinv, iinv1, iinv2, d1,\ d2, d, dm, mai, al); nf = nfinit(y^3+y^2-2*y-1); pr7 = idealprimedec(nf,7); pr13 = idealprimedec(nf,13); J = varhigher("J"); al = alginit(nf,3,J); do("matrix algebra invariants", ()->altriv(al)); d1 = 3; finv1 = [pr13,Vecsmall([1,1,1])]; iinv1 = Vecsmall([0,0,0]); al = alginit(nf,[d1,finv1,iinv1],J); do("algebra 1 invariants", ()->alsame(al,finv1,iinv1)); d2 = 2; finv2 = [pr7,Vecsmall([1])]; iinv2 = Vecsmall([1,0,0]); al = alginit(nf,[d2,finv2,iinv2],J); do("algebra 2 invariants", ()->alsame(al,finv2,iinv2)); nf = nfinit(y); p13 = idealprimedec(nf,13)[1]; finv1 = [[p13],[Mod(1,2)]]; iinv1 = Vecsmall([1]); do("test", ()->alginit(nf,[2,finv1,iinv1],J)); d = 6; p3 = idealprimedec(nf,3)[1]; p5 = idealprimedec(nf,5)[1]; p7 = idealprimedec(nf,7)[1]; p11 = idealprimedec(nf,11)[1]; finv = [[p3,p5,p7,p11], Vecsmall([3,2,2,2])]; iinv = Vecsmall([3]); al = alginit(nf,[d,finv,iinv],J,0); do("degree 6 algebra over Q", ()->alsame(al,finv,iinv)); nf = nfinit(y^2-5); finv1 = [[],[]]; iinv1 = Vecsmall([1,1]); do("trivial finite conditions", ()->my(al=alginit(nf,[2,finv1,iinv1])); [alghassei(al),alghassef(al)]); }); all() = gusuite("all", ()->{ hasse0(); alfromhasse(); }); all(); \\better accessors for hasse invariants print("better accessors"); setrand(1); x='x; nf = nfinit(y^3-y+1); rnf = rnfinit(nf, polcyclo(5,x)); al = alginit(rnf, [x^2,-2],, 0); alghasse(al,1) alghasse(al,2) alghasse(al,idealprimedec(nf,2)[1]) alghasse(al,idealprimedec(nf,3)[1]) alghasse(al,idealprimedec(nf,5)[1]) alghasse(al,idealprimedec(nf,5)[2]) algindex(al,1) algindex(al,2) algindex(al,idealprimedec(nf,2)[1]) algindex(al,idealprimedec(nf,3)[1]) algindex(al,idealprimedec(nf,5)[1]) algindex(al,idealprimedec(nf,5)[2]) algindex(al) algisdivision(al,1) algisdivision(al,2) algisdivision(al,idealprimedec(nf,2)[1]) algisdivision(al,idealprimedec(nf,3)[1]) algisdivision(al,idealprimedec(nf,5)[1]) algisdivision(al,idealprimedec(nf,5)[2]) algisdivision(al) algissplit(al,1) algissplit(al,2) algissplit(al,idealprimedec(nf,2)[1]) algissplit(al,idealprimedec(nf,3)[1]) algissplit(al,idealprimedec(nf,5)[1]) algissplit(al,idealprimedec(nf,5)[2]) algissplit(al) algisramified(al,1) algisramified(al,2) algisramified(al,idealprimedec(nf,2)[1]) algisramified(al,idealprimedec(nf,3)[1]) algisramified(al,idealprimedec(nf,5)[1]) algisramified(al,idealprimedec(nf,5)[2]) algisramified(al) algramifiedplaces(al) print(" "); al = 0; al = alginit(rnf, [x^2,-1],, 0); alghasse(al,1) alghasse(al,2) alghasse(al,idealprimedec(nf,2)[1]) alghasse(al,idealprimedec(nf,5)[1]) alghasse(al,idealprimedec(nf,5)[2]) algindex(al,1) algindex(al,2) algindex(al,idealprimedec(nf,2)[1]) algindex(al,idealprimedec(nf,5)[1]) algindex(al,idealprimedec(nf,5)[2]) algindex(al) algisdivision(al,1) algisdivision(al,2) algisdivision(al,idealprimedec(nf,2)[1]) algisdivision(al,idealprimedec(nf,5)[1]) algisdivision(al,idealprimedec(nf,5)[2]) algisdivision(al) algissplit(al,1) algissplit(al,2) algissplit(al,idealprimedec(nf,2)[1]) algissplit(al,idealprimedec(nf,5)[1]) algissplit(al,idealprimedec(nf,5)[2]) algissplit(al) algisramified(al,1) algisramified(al,2) algisramified(al,idealprimedec(nf,2)[1]) algisramified(al,idealprimedec(nf,5)[1]) algisramified(al,idealprimedec(nf,5)[2]) algisramified(al) algramifiedplaces(al) print(" "); al = 0; al = alginit(rnf, [x^2, 1],, 0); alghasse(al,1) alghasse(al,2) alghasse(al,idealprimedec(nf,2)[1]) alghasse(al,idealprimedec(nf,5)[2]) algindex(al,1) algindex(al,2) algindex(al,idealprimedec(nf,2)[1]) algindex(al,idealprimedec(nf,5)[2]) algindex(al) algisdivision(al,1) algisdivision(al,2) algisdivision(al,idealprimedec(nf,2)[1]) algisdivision(al,idealprimedec(nf,5)[2]) algisdivision(al) algissplit(al,1) algissplit(al,2) algissplit(al,idealprimedec(nf,2)[1]) algissplit(al,idealprimedec(nf,5)[2]) algissplit(al) algisramified(al,1) algisramified(al,2) algisramified(al,idealprimedec(nf,2)[1]) algisramified(al,idealprimedec(nf,5)[2]) algisramified(al) algramifiedplaces(al) print("Hasse inv 0 bug"); setrand(1); a='a; K=nfinit(a);PR=idealprimedec(K,2);A=alginit(K,[3,[PR,[0]],[0]],,0); algdegree(A) algdim(A) algindex(A) algisdivision(A) algadd(A,[1,0,0,0,0,0,0,0,0]~,[1,2,3]~) algsub(A,[1,0,0,0,0,0,0,0,0]~,[1,2,3]~) algmul(A,[0,0,0,0,0,0,0,0,0]~,[1,2,3]~) print("\ntests with splitting field that does not descend"); setrand(1); nf = nfinit(y^2-5); al = alginit(nf,[y,-1]); algramifiedplaces(al) al = alginit(nf,[-3+y,-1]); algramifiedplaces(al) al = alginit(nf,[-3+y,y]); algramifiedplaces(al) nf = nfinit(y^4 - 10*y^2 + 1); p3 = idealprimedec(nf,3)[1]; p5 = idealprimedec(nf,5)[1]; al = alginit(nf, [2, [[p3,p5],[1/2,1/2]], [1/2,0,0,1/2]]); algramifiedplaces(al) al = alginit(nf, [2, [[p3],[1/2]], [0,1/2,0,0]]); algramifiedplaces(al) nf = nfinit(y^8 - 40*y^6 + 352*y^4 - 960*y^2 + 576); p3 = idealprimedec(nf,3)[1]; al = alginit(nf, [2,[[p3],[1/2]], [1/2,0,0,1/2,1/2,0,0,0]]); algramifiedplaces(al) print("degree bug"); nf = nfinit(y); p2 = idealprimedec(nf,2)[1]; p3 = idealprimedec(nf,3)[1]; al = alginit(nf, [4,[[p2,p3],[1/2,1/2]],[0]]); algdegree(al) {for(i=1,10, al = alginit(nf, [2,[[p2,p3],[0,0]],[0]]); print1(algdegree(al)," "); )}; al = alginit(nf, [4,[[p2,p3],[0,0]],[0]]); algdegree(al) nf = nfinit(z^2+1); p31 = idealprimedec(nf,31)[1]; p2 = idealprimedec(nf,2)[1]; {for(i=1,10, al = alginit(nf, [2, [[p31,p2], [0, 0]], []]); print1(algdegree(al)," "); )}; print("infinite loop in GW"); \\Bug #2343 F=nfinit(y^4 - y^3 - 3*y^2 + y + 1); P=nfgrunwaldwang(F, [], Vecsmall([]), Vecsmall([-1, 0, -1, 0])); P=nfgrunwaldwang(F, [], Vecsmall([]), Vecsmall([0, 0, -1, 0])); print("inefficiency in backtrackfacto"); F=nfinit(y^5-y^4-3*y^2+1); setrand(5) alginit(F, [2, [[], []], [1,1,0]],,0); print("bug: alg_complete at ramified primes"); \\James Rickards's example setrand(1); F=nfinit(y^3 - y^2 - 10*y + 8); setrand(1); pr1 = idealprimedec(F, 2)[1]; pr2 = idealprimedec(F, 13)[1]; A=alginit(F, [2, [[pr1, pr2], [1, 1]], [0, 1, 1]]); \\more examples nf = nfinit(y^2-17); [pr1,pr2] = idealprimedec(nf,2); al = alginit(nf,[2,[[pr1],[1/2]],[0,1]],,0); nf = nfinit(y^4 + 7*y^2 + 49); pr1 = idealprimedec(nf,3)[1]; pr2 = idealprimedec(nf,5)[1]; al = alginit(nf,[3,[[pr1,pr2],[1/3,2/3]],[]],,0); pari-2.17.2/src/test/in/lll0000644000175000017500000000144414676526175014074 0ustar billbillqflllgram(matid(2)*1.) m=[219902325555200,60779507942430,113687426768697,93478400051083;219902325555200 ,60779507942430,61044718855924,60943417301157;214748364800,155393376570,17984250 9148,115833849065;214748364800,155393376570,134851934330,188630128295]; qflll(m, 1) qflll(m,3) M=[x, x^3 - 852*x^2 - 833561*x; x^3 + 1053355*x^2, x^5 + 1052503*x^4 - 898292021*x^3 - 878035647155*x^2 + 1]; test()= { for(i=1,#v, for (j=1,#f, print(iferr(f[j](v[i]),E,E)); ) ); } v=[[;],Mat(1),Mat(0),Mat([1,2]), [x, x+1; x^2, x^2+x], M]; f=[qflll,x->qflll(x,1),x->qflll(x,2),x->qflll(x,4),x->qflll(x,5),x->qflll(x,8)]; test(); v=vector(#v,i,v[i]~*v[i]); f=[qflllgram,x->qflllgram(x,1),x->qflllgram(x,4),x->qflllgram(x,5),x->qflllgram(x,8)]; test(); \\ ERRORS qflllgram([1,2,3;4,5,6]) qfminim([1,2,3;4,5,6],,,2) pari-2.17.2/src/test/in/nfeltembed0000644000175000017500000000031714676526175015414 0ustar billbillnf = nfinit('y^3 - 2); nfeltembed(nf, y) nfeltembed(nf, y, [2]) nfeltembed(nf, y, [1,2]) nfeltembed(nf, 2, [1..3]) nf=nfinit(x^4-3); [nfeltembed(nf,x,i) | i <- [1..3]] \\Errors nfeltembed(nf, y, [1,2,4]) pari-2.17.2/src/test/in/ellfromeqn0000644000175000017500000000043414760123736015441 0ustar billbillellfromeqn(t0*y^3+(s1+s0*x)*y^2 +(r2+r1*x+r0*x^2)*y+(q3+q2*x+q1*x^2+q0*x^3)) ellfromeqn(t0*y^2+(s0*x^2+s1*x+s2)*y+(r0*x^4+r1*x^3+r2*x^2+r3*x+r4)) ellfromeqn(t0*x^2+(s0*y^2+s1*y+s2)*x+(r0*y^4+r1*y^3+r2*y^2+r3*y+r4)) ellfromeqn((t0*x^2+t1*x+t2)*y^2+(r0*x^2+r1*x+r2)*y+(s0*x^2+s1*x+s2)) pari-2.17.2/src/test/in/ellanal0000644000175000017500000000170714676526175014723 0ustar billbillrk(x)=x=ellinit(x);ellanalyticrank(x); rk([0, -1, 1, -10, -20]) rk([0, 0, 1, -1, 0]) rk([0, 1, 1, -2, 0]) rk([0, 0, 1, -7, 6]) rk([-5187, 176830]) he(x)=x=ellinit(x);ellheegner(x); he([1, 1, 0, -1297, -18530]) he([0, -1, 1, -33, 93]) he([-157^2,0]) he([0,0,-9/484,0,-27/234256]) he([1,-1,1,4,6]) getheap()[1] E=ellinit([0,-1437004800,0,458885065605120000,0]); ellglobalred(E); ellheegner(E) L = ellinit([0,0,1,7,6]); ellL1(L) ellL1(L,1) ellL1(L,3) ellL1(ellinit([0,1,1,-2,0]),2) default(realprecision,115); ellL1(L) ellL1(L,1) ellL1(L,3) ellL1(ellinit([0,1,1,-2,0]),2) ellmoddegree(ellinit([0,1,0,-4,-4])) ellmoddegree(ellinit([-4,0])) ellmoddegree(ellinit([0,-1,0,4,-4])) ellmoddegree(ellinit([0,-1,0,-8,-16])) ellmoddegree(ellinit([0,0,1,0,-7])) ellmoddegree(ellinit([1,-1,0,0,-5])) ellmoddegree(ellinit([1,-1,0,-69,-208])) ellmoddegree(ellinit([0, -1, 1, 0, 0])) ellmoddegree(ellinit([-4,-3])) ellmoddegree(ellinit([1,-1,0,-363204,-84000240])) \\ small E.area pari-2.17.2/src/test/in/mat0000644000175000017500000001716114724330077014061 0ustar billbilliferr(Mat([1]) + matrix(0,1),E,E) iferr(1/matrix(2,2,i,j,Mod(0, 2)),E,E) test(n)= { until(matrank(M)==n,M=matrix(n,n,i,j,random(Mod(1,2)))); if(M^-1*M!=matid(n),error("F2m")); } test(200) test(2) matsize(matrix(0, 0) * matrix(0, 2)) h=mathilbert(40); [Q,R] = matqr(h); exponent(h-Q*R) < -122 [q,R] = matqr(h,1); exponent(mathouseholder(q,h)-R) < -122 matqr([;]) matqr([;],1) mathouseholder(q, vectorv(40,i,1)) Mat(List()) Mat(List([1])) Mat([Mat(2)]) print(Mat([Mat(2)])) Mat([[1,2,3],[2,3,4]]~) Mat(Qfb(1,2,5)) matdiagonal(matid(2)) iferr(matdiagonal([1,2;3,4]),E,E) matpascal(4,1/2) A=[1,2,3;4,5,6];B=[4,6;10,12] matinverseimage(A,B) matinverseimage(A*Mod(1,2),B) matinverseimage(A*Mod(1,7),B) matinverseimage(A*Mod(1,2^64+13),B) matinverseimage(A*Mod(1,3037000507),B) B=[4,10]~; matinverseimage(A*Mod(1,2),B) matinverseimage(A*Mod(1,7),B) matinverseimage(A*Mod(1,2^64+13),B) matinverseimage(A*Mod(1,3037000507),B) test(f)= { print(f,":"); print(f(A*Mod(1,2))); print(f(A*Mod(1,7))); print(f(A*Mod(1,3037000507))); print(f(A*Mod(1,2^64+13))); print(f(A*(1+O(101^3)))); } testall()= { test(matdet); test(matrank); test(matadjoint); test(matimage); test(matimagecompl); test(matindexrank); test(matker); test(lindep); test(x->matsolve(x,vectorv(#x,i,i))); test(x->matsolve(x,matrix(#x,#x,i,j,i+j))); test(x->x^(-1)); test(x->x^2); test(x->A*x); } A = [1,2,4;2,12,7;2,9,11]; testall(); A = [;] testall(); A=[0,1,0;1,0,1;2,0,3]; matdet(A*Mod(1,3037000507)) matdet(A*Mod(1,2^64+13)) matsolve(A*Mod(1,2^64+13),[1,2,3]~) m=[1,0;0,0;0,1]; b=[1,2;0,0;3,4]; matsolve(m,b) matsolve(m/2,b) matsolve(m*Mod(1,2),b) matsolve(m*Mod(1,3),b) matsolve(m*Mod(1,2^64+13),b) matsolve(m*ffgen(2^3)^0,b) \\ #2261 matsolve([1,1,1/2; 1,0,1/2; 2,1,0], [-1;1;-1]) \\ #2338 target(n) = matrix(2*n-1, n^2, i, j, (j-1)%n + (j-1)\n == i-1); expand(V, n) = vector(n*n, i, V[(i-1)%n + 1] * V[(i-1)\n + 1]); vecrev(V) = vector(#V, i, V[#V-i+1]); { expansion(F, n) = my([l] = matsize(F), M = matrix(l, n^2)); for(i = 1, l, M[i,] = expand(vecrev(F[i,]), n)); M; } { F = [ 0,0,0,0,0,0,1; 1,0,0,0,0,0,0; 0,0,0,0,0,1,0; 0,1,0,0,0,0,0; 0,0,0,0,0,1,1; 1,1,0,0,0,0,0; 0,0,1,0,1,0,0; 0,1,0,1,0,0,1; 1,0,0,1,0,1,0; 0,1,1,0,0,0,1; 1,0,0,0,1,1,0; 0,1,1,0,1,1,0; 1,0,0,0,0,0,1; 1,0,0,0,1,1,1; 1,1,1,0,0,0,1; 1,0,1,1,0,1,1; 1,1,0,1,1,0,1; 1,1,0,0,0,1,1; 1,1,0,1,1,1,1; 1,1,1,1,0,1,1; 1,1,1,0,1,1,1; 1,1,1,1,1,1,1 ]; } S = matsolve(expansion(F, 7)~, target(7)~); matker([1.,I;I,-1.]) matkerint(Mat([1,1])) trace(matid(3)) trace([;]) iferr(trace(Mat([1,2])),E,E) matrixqz([1/3,1/4;1/2,1/3]) matrixqz(matrix(2,2),-1) m=[1,-4,6,1;-13,14,-8,-3;0,0,0,0;0,0,0,0;7,-9,3,2;-7,9,7,4;0,0,0,0;0,0,0,0;10,-2,-2,0;0,0,-4,-4;0,0,0,0;0,0,0,0;-7,9,-7,-4;-4,-3,7,3;0,0,0,0;0,0,0,0;-5,1,9,4;1,-4,-10,-5;0,0,0,0;0,0,0,0;-13,14,-8,-5;-3,-7,7,4;0,0,0,0;0,0,0,0;-18,15,5,3;8,6,-6,-2;0,0,0,0;0,0,0,0;0,0,0,0;4,3,3,1;0,0,0,0;0,0,0,0;11,-6,4,3;-7,9,7,2;0,0,0,0;0,0,0,0;-5,1,7,4;4,3,1,1;0,0,0,0;0,0,0,0;-6,5,-9,-7;-9,-2,10,7;0,0,0,0;0,0,0,0;-1,4,-4,-1;-20,4,6,4;0,0,0,0;0,0,0,0;0,0,-8,-4;9,2,6,3;0,0,0,0;0,0,0,0;0,0,0,0;0,0,0,0;3,7,1,0;6,-5,-7,-5;0,0,0,0;0,0,0,0;-11,6,8,5;0,0,-6,-4;0,0,0,0;0,0,0,0;-12,10,10,6;0,0,-8,-4;0,0,0,0;0,0,0,0;-5,1,3,2;-6,5,-7,-3;0,0,0,0;0,0,0,0;10,-2,-6,-4;-4,-3,3,1;0,0,0,0;0,0,0,0;0,0,0,0;0,0,0,0;0,0,0,0;0,0,0,0;-2,8,0,-2;2,-8,-4,-2;0,0,0,0;0,0,0,0]; a=matrixqz(m,-2);matdet(a~*a) matrixqz([2,0;0,2;1,0;0,1],-2) matrixqz([1,0;0,2/3;1/2,0;0,1/3],-2) matrixqz([1/2,0;0,0],-1) matrixqz([1/2;0],-1) matrixqz([;],-2) mathnf(matrixqz(matrix(3,3,i,j,1/(i+j)),-2)) mathnf(matrixqz(matrix(4,2,i,j,1/(i+13*j+1))*matrix(2,4,i,j,(i+j)/(i^2+j^2)),-2)) mathnf(matrixqz([2/5,3;0,0;1,1/7],-2)) \\ #2387 W=[266,828,54,-1080;-183,-255,303,-405;-22,-1242,-458,1620;314,2304,-112,-1530;100,1190,94,-1126];matrixqz(W) A=[1,2,3;4,5,6;7,8,9]; test(lindep) test(matsupplement) A=matrix(5,1); test(matsupplement) default(parisize,"1M"); \\ need to exercise gerepile in matker+matimage p=2^64+13; A=matrix(70,70,i,j, i+j); Ap=Mod(A,p); #matker(Ap) #matimage(Ap) #matker(A) #matker(Mod(A,3)) matker([3,0,2,2;1,3,3,3]) vecsum([]) vecsum([2]) vecsum(primes(4)) vecprod([]) vecprod([1,2,3]) content([]) content([;]) content(matrix(0,2)) vectorsmall(3) v=vectorsmall(3,i,3*i^2) content(v) content(vectorsmall(0)) v=vectorsmall(5,i,(3-i)*i) content(v) m=[1,0;0,0;0,1]; b=[1,2;0,0;3,4]; liftint(Mod(m,2)^(-1)) liftint(Mod(m,3)^(-1)) liftint(Mod(m,2^64+13)^(-1)) liftint(matsolve(Mod(m,2),b)) liftint(matsolve(Mod(m,3),b)) liftint(matsolve(Mod(m,2^64+13),b)) (m*ffgen(2^2)^0)^(-1) (m*ffgen(3^2)^0)^(-1) (m*ffgen((2^64+13)^2)^0)^(-1) m=[1,2,3;4,5,6]; m[2,]=[1,2,3] m m[1,]*=2 m test(t) = { N = [1, 2; -1, -2]*t^0; print(matinverseimage(N, N^0)); } test(Mod(1, 3)); test(Mod(1, nextprime(2^64))); test(ffgen(2^17)); test(ffgen(2017^3)); test(ffgen(nextprime(2^64)^3)); p = nextprime(2^63); q = nextprime(p + 1); { forvec(v = vector(8, i, [0, 2]), matker([p^v[1]*q^v[2], p^v[3]*q^v[4]; p^v[5]*q^v[6], p^v[7]*q^v[8]], 1)); } test(x,u=1) = { n = 22; r = 12; M = matrix(n, n, i, j, random(x)*u); P = matrix(n, r, i, j, if(2*i >= 3*j + 8, random(x)*u, 0)); N = P*matrix(r, n, i, j, random(x)*u); S = matsupplement(P); Q = N[,1..r]; R = mattranspose(P); X = matsolve(M, N); K = matker(N); J = matimage(N); if (M*X != N, error("M*X == N")); if (N*K != 0,error("N*K == 0")); if (N*lindep(N) != 0, error("lindep(N)")); if (R*lindep(R) != 0, error("lindep(R)")); if (matimage(J) != J, error("matimage(J)")); if (matdet(S) == 0, error("matsupplement(S)")); if (matrank(J) != r, error("matrank(J)")); if (matrank(K) != n - r, error("matrank(K)")); if (matrank(N) != r, error("matrank(N)")); if (J^-1 * J != matid(r), error("J^-1 * J")); if (matdet(M^-1) != matdet(M)^-1, error("matdet")); if (P*matinverseimage(P, Q) != Q, error("matinverseimage")); if(#lindep(J), error("lindep(J)")); if(#matker(K), error("matker(K)")); if(#matker(M), error("matker(M)")); if(#matinverseimage(N, M),error("matinverseimage(N, M)")); if(#matinverseimage(P, M),error("matinverseimage(P, M)")); iferr(N^-1, e,, errname(e) == "e_INV"); iferr(matsolve(N, M), e,, errname(e) == "e_INV"); } p=nextprime(2^65); test(Mod(1, 8161)); test(Mod(1, p)); default(parisize,"16M"); \\ 14M overflows test(ffgen([2017,3])); test(ffgen([p,2])); test(x^3*Mod(1,17),Mod(1,ffinit(17,4))); test(x^2*Mod(1,p),Mod(1,ffinit(p,3))); test(x,u=1) = { my(R = matrix(5, 5, i, j, random(x)*u)); if(R^2+R!=R*(R+1),error([x,u])); } test(10*x^3,Mod(1,x^4+7*x^3+12*x+5)); test(10*x^3,Mod(1,(x^4+7*x^3+12*x+5)/7)); test(10*x^3,Mod(1,5*x^4+7*x^3+12*x+5)); test(10*x^3,Mod(1/11,x^4+7*x^3+12*x+5)); test(10*x^3,Mod(1/11,(x^4+7*x^3+12*x+5)/7)); test(10*x^3,Mod(1/11,5*x^4+7*x^3+12*x+5)); [0,0;-1,0;1,1]^(-1) [1,2;3,4;5,6]^-1 A=[0,0;-10,200;-4,80;0,0;-10,200;-4,80;-50,1000;-80,1600;-28,560]; B=[0,1;0,0;0,0;-3,-2;20,10;25,-10;-8,-6;30,20;25,-15]; matintersect(A,B) a = ffgen([65537, 96]); M = matrix(40, 30, i, j, random(a)) * matrix(30, 40, i, j, random(a)); matrank(M) M=matrix(100,200);N=matrix(200,100); [matsize(M*N), matsize(N*M)] A=[x,2;y,4]; B=[x,-2; y,3; 3, 4]; matreduce(matconcat([A,B]~)) matreduce(matrix(0,2)) matreduce([]) matreduce([1,1,2,1,3,1,2]) matreduce([1]) \\ #2582 M = [1,1;1,0]; M*M \\ Errors, keep at end of file 1/Mat([0,0]~) mathouseholder(1,1) [q,r]=matqr(matid(2),1); mathouseholder(q,1) matsolve([1,0;0,0]*Mod(1,2),[1,1]~) matsolve([1,0;0,0]*Mod(1,3),[1,1]~) vecsum(1) 1~ vectorsmall(3,i,i^100) m=[1,2,3;4,5,6]; m[1,]=[1,2] m[1,]=[1,2,3,4] m[1,]=[1,2,3]~ [1,2,3;4,5,6]^-1 [1,2,3;4,5,6;7,8,9]^-1 matrixqz(matrix(2,2)) matrixqz([;],-3) matreduce(1) matreduce([;]) matreduce([1,x;1,y]) [[1,2;1,3],[2,1]]^-1 Mat(0)/Mat(0) pari-2.17.2/src/test/in/binomial0000644000175000017500000000055314676526175015103 0ustar billbilldefault(parisize,"34M"); \\ overflows 32M binomial(x,2) binomial(6,3) binomial(6) binomial(2^64-1,4) binomial(3,5) binomial(3,3) binomial(10001111,3532222) % (2^32 + 15) binomial(-2,-4) binomial(-2,-1) binomial(-2,2) binomial(-1,-4) binomial(-2,3) binomial(Mod(0,3),2) binomial(Mod(0,3),-1) binomial(Mod(0,3),0) \\errors binomial(1,2.) binomial(-1) binomial(1.) pari-2.17.2/src/test/in/qf0000644000175000017500000000343114676526175013715 0ustar billbillQ = [0,7,2,3; 7,0,6,8; 2,6,0,9; 3,8,9,0]; qfcholesky(Q) M = qfgaussred(Q) [U,V] = qfgaussred(Q,1); D = matdiagonal(V); if(U~*D*U!=Q || M!=U+D-1,error("qfgaussred")); Q=[2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1;-1,2,1,1,1,1,1,1,1,1,1,1,1;-1,1,2,1,1,1,1,1,1,1,1,1,1;-1,1,1,2,1,1,1,1,1,1,1,1,1;-1,1,1,1,2,1,1,1,1,1,1,1,1;-1,1,1,1,1,2,1,1,1,1,1,1,1;-1,1,1,1,1,1,2,1,1,1,1,1,1;-1,1,1,1,1,1,1,2,1,1,1,1,1;-1,1,1,1,1,1,1,1,2,1,1,1,1;-1,1,1,1,1,1,1,1,1,2,1,1,1;-1,1,1,1,1,1,1,1,1,1,2,1,1;-1,1,1,1,1,1,1,1,1,1,1,2,1;-1,1,1,1,1,1,1,1,1,1,1,1,2]; Q[3,7] += 1.25; Q[7,3] += 1.25; qfsign(Q) Q=[8,4,4,4,4,4,4,4,4,4,4,4;4,8,4,4,4,4,4,4,4,4,4,4;4,4,8,0,0,0,3,0,0,0,0,0;4,4,0 ,8,4,4,1,4,4,4,4,4;4,4,0,4,8,4,4,4,4,4,4,4;4,4,0,4,4,8,4,4,4,4,4,4;4,4,3,1,4,4,8 ,4,1,1,1,1;4,4,0,4,4,4,4,8,4,4,4,4;4,4,0,4,4,4,1,4,8,4,4,4;4,4,0,4,4,4,1,4,4,8,4 ,4;4,4,0,4,4,4,1,4,4,4,8,4;4,4,0,4,4,4,1,4,4,4,4,8]; qfminim(Q,,0,2)[1] qfrep(Q,16) qfrep(Q,8,1) qfminim(Q,,,1) qfminim(Q,8,,1) qfminim(Q,4,,1) qfminim([;],4,,1) qfminim([;],4,,2) qfminim(Mat(1),,,2) \\ #2262 qfminim(matid(2),0,1,2) qfminim(matid(2),0,1,1) qfminim(matid(2),0,1,0) U=qfcholesky(Q);round(U~*U-Q,&e);e L=[360815,2283021;-316840,2566404]; qfminim(L~*L,10^16)[2] qfminim(L~*L,10^16,,2)[2] forqfvec(v, [3,2;2,3], 3, print(v)) forqfvec(v, [3,2;2,3],, print(v)) forqfvec(v,[;],3,) forqfvec(v,matid(2),-6, print(".") ) \\ #2237 qfminim(matid(2),-6) qfminim(matid(2),-6,,2) x=[1,2,3]~; y=[-1,0,1]~; qfeval(,x) q=[1,2,3;2,2,-1;3,-1,0]; qfeval(q,x) qfeval(,x,y) qfeval(q,x,y) M=[1,2,3;4,5,6;7,8,9]; qfeval(,M) qfeval(q,M) \\ ERRORS, keep at end qfeval(,1) qfeval(,1,1) qfeval(Mat(1),x) qfeval(Mat(x~),x) qfeval(,1,1) qfeval(,[1],[1,2]) qfeval(q,[1,2],[1,2]) qfeval(Mat([1,2]),[1,2],[1,2]) qfeval(1,1) \\ #2451 Q=matdiagonal([10^10,1]);N=10^11; forqfvec(v,Q,N, if(qfeval(Q,v) > N,error(v))) pari-2.17.2/src/test/in/forsubset0000644000175000017500000000115214567450071015307 0ustar billbilltest(N) = /* check cardinalities and compatibility of forksubset/forallsubset */ { my(l1,l2,l3,k); l1 = []; forsubset(N, s, l1 = concat(l1,s)); if (#l1 != 2^N, error(N)); l2 = []; for (k = 0, N, l3 = []; forsubset([N,k], s, l3 = concat(l3,s)); if (#l3 != binomial(N,k), error([N,k])); l2 = concat(l2, l3); ); if (l1 != l2, error("size ", N)); } test(0); test(1); test(2); test(3); test(4); test(5); forsubset(4,s,print(s)); \\ corner cases forsubset([0,0],s,print(s)) forsubset(0,s,print(s)) forsubset([0,1],s,print(s)) forsubset(-1,s,) forsubset([2,-1],s,) \\ errors forsubset('x,s,) pari-2.17.2/src/test/in/div0000644000175000017500000000200714676526175014067 0ustar billbillv=[3,4,3.1,1/2,x^2+1, Mod(x,x^2+1),ffgen(3^5,'t),quadgen(5),quadgen(-8),2+O(3^3),Mod(2,3), 2^64 + 1]; { for (i=1,#v, for(j=1,#v, print("* ",[i,j]); print(iferr(v[i]/v[j],E,E)); print(iferr(v[i]\v[j],E,E)); print(iferr(v[i]%v[j],E,E)); print(iferr(v[i]\/v[j],E,E)); print(iferr(divrem(v[i],v[j]),E,E)); ) ) } w=[x + O(x^2),[2,3],Mat(2)]; { for (i=1,#w, for(j=1,#v, print("* ",[i,j]); print(iferr(w[i]/v[j],E,E)); print(iferr(w[i]\v[j],E,E)); print(iferr(w[i]%v[j],E,E)); print(iferr(w[i]\/v[j],E,E)); ) ) } for (i=2,#w, print(w[i]%2)) for (i=2,#w, print(w[i]\2)) divrem(x+y^2,y+x,y) divrem([3,5],2) divrem(1,x) divrem(1,Pol(1)) divrem(1,"a") (5/3) \/ 1 floor((x^2+1)/x) 1/(1-x*y) 1/(y*x-1) M=[1,2,0;3,1,1];A=[1,2,4;2,12,7;2,9,11]; M/A []/0 []~/0 [;]/0 [1]/0 m=Mod(1,ffinit(3,3,a));P=(x^8+a*x^2+x+a)*m;Q=(x^5+4*x^3+a*x+(a^2+1))*m;P%Q (x^7+x^3+x+1)*Mod(1,Mod(1,2)*d)%(x^4+x^3+x^2+1) Mod(1,2)/(182*x+13) Mod(1,2)/(O(x^2)+182*x+13) Mod(1,2)/((2*x+1)/(3*x+1)) Mod(1,2)*x/(2*x+1) pari-2.17.2/src/test/in/polred0000644000175000017500000000754114676526175014602 0ustar billbilldefault(parisize,12M); rnfpolredbest(nfinit(quadpoly(5,y)),x^7-14*x^5+56*x^3-56*x+22) \\ rnfpolred(nfinit(quadpoly(1996,y)),quadray(1996,1)) \\ rnfpolred(nfinit(quadpoly(904,y)),quadray(904,1)) K=bnfinit(quadpoly(29,y)); T=quadray(29,17) rnfpolredabs(K,T) chk(K,T)=[rnfconductor(K,T,2),norm(poldisc(T))]; chk(K,rnfpolredbest(K,T)) chk(K,rnfpolredabs(K,[T,100],16)) chk(K,rnfpolredbest(K,[T,100])) K=nfinit(y^3-y-1); T=x^3-x-1; rnfpolredabs(K,T) rnfpolredabs(K,T,2) [P,a]=rnfpolredbest(K,T,1); liftall(subst(K.pol,y,a)) [P,a,b]=rnfpolredbest(K,T,3); liftall(subst(K.pol,y,a)) substvec(T,[x,y],[a,b]) rnfpolred(nfinit(quadpoly(1129,y)),quadray(1129,1)); nfinit(Pol([256,-2560,5120,6400,-60320,6976,116320,72560,-456615,270630,-129362])); polredabs(quadpoly(14586217464)) 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) polredabs(y^4-2*y^3-24*y^2+61*y+2,1) \\#1146 polredabs(x^9-4*x^7-3*x^6+9*x^5+8*x^4-6*x^3-9*x^2-4*x-1) \\#1228 polredabs(x^5-13*x^3+3*x^2+5*x-1) \\#1229 polredabs(x^6+21471450*x^2+71643071500) polredbest(x^6+21471450*x^2+71643071500) polredbest(4*x^4+146077*x^2+2629386) polredabs(2*x+1) polredabs(2*x+1,1) polred([x,[1]]) polred(2*x+1) polred(2*x+1,1) polred(4*x^2+1,2) polredbest(2*x+1) polredbest(2*x+1,1) polredbest(4*x^2+1,1) polredord(2*x+1) polredord(4*x^2+1) \\ #1519, test T->unscale != 1 polredbest(x^8+24*x^6+80*x^5+1040*x^4-4288*x^3-12736*x^2-61952*x+311296,1) \\ #1511 polredabs(x^16-4*x^15-334*x^14+264*x^13+32231*x^12+57392*x^11-1031422*x^10-3628868*x^9+7185297*x^8+42417784*x^7+11283472*x^6-137773504*x^5-127243504*x^4+69059728*x^3+56307944*x^2-6264432*x+6436) \\ #1653 f=x^40+10*x^39+75*x^38+410*x^37+1888*x^36+7364*x^35+25310*x^34+77140*x^33+211669*x^32+524946*x^31+1183823*x^30+2430610*x^29+4548530*x^28+7743916*x^27+11954920*x^26+16627228*x^25+20626386*x^24+22445616*x^23+20835590*x^22+15611648*x^21+8209812*x^20+1290846*x^19-2562740*x^18-2525172*x^17-76374*x^16+2095346*x^15+2320830*x^14+1050748*x^13-71120*x^12-238080*x^11+31952*x^10+106808*x^9+12549*x^8-18470*x^7-485*x^6+3202*x^5-232*x^4-430*x^3+150*x^2-20*x+1; polredbest(f); polredabs(x^5 - 331137220*x^4 + 37922047405356360*x^3 - 1127174691845938128093840*x^2 + 52208293424667465123438066822480*x - 16507431553557006099641796204889368224) f=5*x^12+13*x^4+11*x^3+2*x+1; [g,h] = polredabs(f,1); [g,subst(f,x,h)] \\ #1961 polredabs(x^15-15*x^13-2*x^12+78*x^11-10*x^10-393*x^9+81*x^8+939*x^7-373*x^6-822*x^5+723*x^4-1588*x^3-57*x^2+127*x-13) \\ #1963 f=x^23-4324*x^21-6486*x^20+5382299*x^19-23233933*x^18-2724444300*x^17+29686323629*x^16+512000507352*x^15-10294412120640*x^14+6885232378569*x^13+1102283075184770*x^12-8796561210816172*x^11-7798660667836453*x^10+474243077814357335*x^9-2826995282155771181*x^8+5949260040976823570*x^7+9167317157190582864*x^6-81864894718917833350*x^5+204445625295748936871*x^4-269173314235796280477*x^3+199912058984322799237*x^2-78929282232647458634*x+12862216057817467245; polredabs(f)==f K=nfinit(z^4 + 50*z^2 + 45); u=rnfpolredabs(K,x^4 - 6*x^2 - 5*x - 1) rnfpolredabs(K,u) \\ #2035 K=nfinit(polcyclo(5,t)); rnfpolredabs(K, y^2+(t^3+3*t^2+3*t+1)*y+(-53*t^3-10*t-10), 1)[1] \\ #2301 polredbest(4*x^6+1,1) \\ #2414 polredbest(y^4 - y^3 - 1/4,1) \\ #2538 K=nfinit(y^4-18*y^2+82); b=-4*y^3-12*y^2+40*y+121; rnfpolredabs(K,x^4-b) rnfpolredabs(K,x^4+(4*y^3-9*y^2-40*y+95)*x^2+(-2*y^3+8*y^2+20*y-82)*x+(58*y^3-178*y^2-520*y+1604)) K=bnfinit(y^4 - 18*y^2 + 82); A=x^4+(4*y^3-15*y^2-40*y+149)*x^2+(-2*y^3+8*y^2+20*y-82)*x+(46*y^3-136*y^2-424*y+1262); rnfpolredabs(K,A) B=x^4+Mod(4*y^3+12*y^2-40*y-121,y^4-18*y^2+82); rnfpolredabs(K,B) A=x^4+(4*y^3-10*y^2-40*y+105)*x^2+(-2*y^3+10*y^2+16*y-82)*x+(54*y^3-162*y^2-484*y+1458); rnfpolredabs(K,A) \\ ERRORS, keep at end of file \\#2241 polredbest(x^6+30*x^5+133*x^4-2340*x^3-12284*x^2+29519*x-3856) pari-2.17.2/src/test/in/polclass0000644000175000017500000003256714676526175015143 0ustar billbilldefault(parisize,"10M"); \\ overflows 8M hash_base = 2^64; init_h = 5381; split_Z(n) = { my (bits = 8, base = 2^bits, sgn = sign(n) % base, res = []); n = abs(n); while (n != 0, res = concat(res, bitand(n, base - 1)); n = shift(n, -bits)); res = concat(res, sgn); } glue(h, a) = bitand((((h << 5) + h) + a), hash_base - 1); hash_Z(n) = { my (v = split_Z(n), h = init_h); for (i = 1, #v, h = glue(h, v[i])); h; } hash_ZX(pol) = { my (v = Vec(pol), h = init_h); for (i = 1, #v, h = glue(h, hash_Z(v[i]))); h; } check_disc(D, hash, seed = 0) = { if (seed != 0, setrand(seed)); my(P = polclass(D[1], D[2])); if (D[2]==0 && polisclass(P)!=D[1], error("polisclass(polclass(",D[1],"))!=",D[1])); my (h = hash_ZX(P)); if (h != hash, error("Wrong class polynomial for D = ", D[1], ", inv = ", D[2]), "hash = ", h); } { D = [[[-3, 0], 199415601], [[-4, 0], 392824566], [[-7, 0], 392666638], [[-8, 0], 392685999], [[-11, 0], 392619250], [[-20, 0], 427908603366], [[-23, 0], 466294765623259], [[-39, 0], 16505852200663133551], [[-47, 0], 6402944422652024363], [[-87, 0], 4174888675786545598], [[-71, 0], 9700283236680509421], [[-95, 0], 13008454496997756490], [[-56, 0], 11998671908550620494], [[-264, 0], 12912619012374504058], [[-152, 0], 10731008721722142465], [[-3792, 0], 7620467061686776546], [[-7139, 0], 12274439570299924406], [[-163, 0], 249740438023929931], [[-24, 0], 7166885172778], [[-40, 0], 236296854599224], [[-131, 0], 8331420221009258450], [[-451, 0], 14359598510137794606], [[-356, 0], 4527984144770046237], [[-120, 0], 6891115741722954474], [[-311, 0], 15021837413190908510], [[-335, 0], 17672415898312866530], [[-519, 0], 13506744947615842737], [[-84, 0], 4664273993601588884], [[-271, 0], 4652420391100252414], [[-167, 0], 2826053336532203363], [[-231, 0], 6425030865187792225], [[-280, 0], 6063510379317462346], [[-251, 0], 5232582682029074054], [[-1620, 0], 1232737106430825415], [[-391, 5], 14572212426390106882], [[-20111, 1], 5411404000905873008], [[-392, 5], 1938827148297849283], [[-343, 1], 257546238364177159], [[-2783, 1], 10996804753710941904], [[-391, 1], 12637340198398619526], [[-5599, 1], 15562216764308300369], [[-224, 0], 10018273001722667737], [[-288, 0], 15500427279901381447], [[-644, 0], 16119498756774694982], [[-7139, 0], 12274439570299924406], [[-215, 9], 7528041078664363719], [[-371, 9], 8506587209427855528], [[-539, 9], 8748779700064132114], [[-671, 9], 5929593196577825871], [[-280, 10], 6774102711], [[-344, 10], 3407806631764244633], [[-440, 10], 8033768874193878], [[-920, 10], 8900106068891464863], [[-327, 14], 820264988495455618], [[-847, 14], 8900106376097441137], [[-2415, 14], 4702919368381193176], [[-3471, 14], 4207077986598738230], [[-3519, 14], 7023161748919318882], [[-6655, 14], 11728172978868873828], [[-71, 15], 265107590925814617], [[-7391, 21], 18207206522799977933], [[-260, 24], 7377189545749], [[-312, 26], 6774103800], [[-168, 27], 6774105724], [[-6776, 28], 969506930726366988], [[-164, 35], 8506586868542907145], [[-280, 35], 6774107067], [[-527, 6], 16357965504658585322], [[-47, 6], 243447500721580], [[-42955, 35], 14052068170087575320], [[-5032, 27], 16716694557985895220 /*twist is 3867221821476957240*/], [[-49348, 27], 10861324145157519298], [[-204456,27], 15931382689715710614], [[-31460, 15], 17615562111387810148], [[-207480, 26], 7872480165757364895], [[-943024, 35], 17468381263281201818], \\ N.B. These tests don't come from an independent source [[-487, 4], 265345096494820938], [[-487, 8], 772539374239967193], [[-4, 5], 205098588] ]; for (i = 1, #D, check_disc(D[i][1], D[i][2])); DR = [[[-75, 0], 7797221584007659, 376671349665989785645468855509664073846994182881400101766546260394720617934366189060409433769160357181533432220573885805924825693540852008021952564459774590810585211475243394327684717245750110745945026072328072760225571953639433771639283459668005522842154890829456908826675941553773883099694408386765914172430146193260890042281309331937613624260297092915479077192844416843235737033853226359061755041806842898913531132580673421160537655521664429456369047671439914653309055536929498242296184145972586723145667150625185761830949962500298373529056584928040536064567524870263474685887743703040527814911203719509822876332870699144742892184561609398829910546156826731793518047498225315541275444481177788292169213637463551669277949522309499858775613218022974443961718597909705550334907908272096681310881421925063809112518357896869373327907899703426268496281560228765042197657321214742009561132906624005191491690624145861907151224119699824761808776256630533762728719441507893787757775848664794475988539811278575134333922682568740464050564864294502794430114540622076105981748851862287121587354249984704456793486070616857344028549087804854311807866277937114409612028264996212844411377427435191858159128965207532045931755537411540995454270687742541089492939476560082], [[-243, 0], 10890205224450786941, 819816539003337703951551030334491985811219590735808650180084142425889087428278968474816967078788694496520947544632247845148293960128431184216429913375564738983435120171372870463833059539919475240115755341447859856740148463438091631147817394080277037577189318264494706821721345983257007207604976565659002445459533752756403439594595147954877184727959282333598933690523890222486574862338277271651603375551722191624435592552060776002053134461739050123189055598823370045610053376263074127907593363552123382309729600820747663525085476951111221315643502593164457035295391801162246544107314533457417879806021098968509300182682540829561660369718219958918702187270446232698794813755480218436460242299594360809397850298336439084244705407778140537600292162873108406078811122401339560541945962750458360813545456362536413450759306402982253681310730782288761995853476768379157689767510249258235383040592111399964287410641000424797854996084393758288398059903384898037630395150017169041181270749377250772914279451145788567644479020046227191205609636239269452021245993971524029995510112434006315050031017396470300928176256241735855429441793194487014544763039598262470846572824386988540861783118073704736780177053813565445211750595008551163984105886194036038475757862082957], [[-588, 0], 879637271447453785, 722172781875446948725027515502840397805803222574263498938157594834753683539692286353539379550260903961870953681724730652335944539054343214809842109182109376376073404934944783430561780090926711128352240351787729618963067414744940653491552049787247397068335298858059915825702852961307136083870626600760767835946633951456834700248463253765418088580513814400067434333278000748727896494114214077094766308557268821917667449381466097345351641374194851269731747888023854019055881132865422068901694215525217069307365686664460579110497068925420022191531596796819270908424786079485895699300312731851621077417224747357440195326283221688405149148310871267542131565275881843830667704094780810055193197890989350423968947844027604016370949415740373443463212927661990707144843034492549347563234263847345087343863729913728036463982329922404548652813756727386840999876115923084606166024940965586010450200229416349092936572815279513133323207117397659789511994921332289638592093388560749212300029278651884171306493436892928038820455609679624565527968832712465530213919299178940798157452403212185383817925419187972425719729474468729656592316632439083960654603463616738116233198556419632548161066690834007443366276926895963450902134482716015380443358800099100412263111150979648], [[-1936, 0], 12042224483327737942, 1216866102333088130226524487913144208763734959917103691345969409207516868291718354363183168079965162895868164110454068295852403913687063897316076456732180244314693491111859072668845951826176461315221230058882016799221709155152952471964012736330885451089911136340521851921137288731711645985018653207987024594821449521955479976072917497655704811136469355917733730202537028759098395693891168127853723688728461687547524692980924681009739778062916688599274600924902816402188733597929385212483531422542423979111917373373585978124654150004913998429781081552019917407337230736817542160592949209643774691682024891032738521704689750777805611535687724288457092597016530770301762651133083255869909365609188976361538992126091328095544442922892343390321793772426187309802431464642021666763994457491312667884863871652314337261276496152417457940894836459814316686634775678387158467697914839871436783832178376515625541434789638029419363540511603683658124001143169292488167504419402598460417472547700995407928658213724085415458907242448196429214332894114471850475375711280198098487532816256589287927692486819421805100968297601956068629138524802993613615898230916542578235706687386704879350698179214328913835629864793298388274831137006096634798081307397384701672353002489976], [[-9464, 27], 5838598543968928741, 971139859541539616455075472900871966684445886977524219712621182627452641738170743950581780568829461151266154948079688625260075517281608241987838943732170482046768221929691266245633815142295331012266345361025063298703781829470762291189612365408932129643179104583139454418787386761923101185430770632737852524773963710654122518627917169712709368494827992636945238166518387075005445361264151396088968297095892419521699242270065142895617766430928838221156081322779436189777855217319420550761746571111854615106199425776868531293331645201061020372749829651516464252654687468052692567240414198030892065484818978998288613402083443724834071908030625335571589293504087111354767090827145185368562125001952066613125853368107092130625039931744896896188108648729699937618898649396661193004024196233594623490493378529132432237889029945152360812025808575506573780427329930694881608767838773009911886208424710101255863975363472239340897484025133403045878621608134224132652043064579135366914626745922900237622551009882486999845852791398666923911380143191687845115969658901039215688660195638057312524743660482333830320630523279502463305903338291861973365480740971894854961817219983334320080191073956364702303641228818622994573234724106246909630786570309531361965607975717738], [[-224, 35], 8748776263983593377, 1216866102333088130226524487913144208763734959917103691345969409207516868291718354363183168079965162895868164110454068295852403913687063897316076456732180244314693491111859072668845951826176461315221230058882016799221709155152952471964012736330885451089911136340521851921137288731711645985018653207987024594821449521955479976072917497655704811136469355917733730202537028759098395693891168127853723688728461687547524692980924681009739778062916688599274600924902816402188733597929385212483531422542423979111917373373585978124654150004913998429781081552019917407337230736817542160592949209643774691682024891032738521704689750777805611535687724288457092597016530770301762651133083255869909365609188976361538992126091328095544442922892343390321793772426187309802431464642021666763994457491312667884863871652314337261276496152417457940894836459814316686634775678387158467697914839871436783832178376515625541434789638029419363540511603683658124001143169292488167504419402598460417472547700995407928658213724085415458907242448196429214332894114471850475375711280198098487532816256589287927692486819421805100968297601956068629138524802993613615898230916542578235706687386704879350698179214328913835629864793298388274831137006096634798081307397384701672353002489976], [[-7391, 21], 18207206522799977933, 1216866102333088130226524487913144208763734959917103691345969409207516868291718354363183168079965162895868164110454068295852403913687063897316076456732180244314693491111859072668845951826176461315221230058882016799221709155152952471964012736330885451089911136340521851921137288731711645985018653207987024594821449521955479976072917497655704811136469355917733730202537028759098395693891168127853723688728461687547524692980924681009739778062916688599274600924902816402188733597929385212483531422542423979111917373373585978124654150004913998429781081552019917407337230736817542160592949209643774691682024891032738521704689750777805611535687724288457092597016530770301762651133083255869909365609188976361538992126091328095544442922892343390321793772426187309802431464642021666763994457491312667884863871652314337261276496152417457940894836459814316686634775678387158467697914839871436783832178376515625541434789638029419363540511603683658124001143169292488167504419402598460417472547700995407928658213724085415458907242448196429214332894114471850475375711280198098487532816256589287927692486819421805100968297601956068629138524802993613615898230916542578235706687386704879350698179214328913835629864793298388274831137006096634798081307397384701672353002489976]]; for (i = 1, #DR, check_disc(DR[i][1], DR[i][2], DR[i][3])); my (got_err = 0); iferr(polclass(-5), err, got_err = 1, errname(err) == "e_DOMAIN"); if ( ! got_err, error("No error when given non discriminant")); my (got_err = 0); iferr(polclass(-3,7), err, got_err = 1, errname(err) == "e_DOMAIN"); if ( ! got_err, error("No error when given bad invariant")); if (variable(polclass(-7, , 'z)) != 'z, error("Didn't use user-provided variable")); } \\ Regressions setrand(51);polclass(-8,5) hash_ZX(polclass(-54087)) polisclass(x^0) pari-2.17.2/src/test/in/bbhnf0000644000175000017500000001205314676526175014366 0ustar billbillranddistinct(n) = { my(i=0,j=0); while(i==j, i = random([1,n]); j = random([1,n]); ); [i,j]; } randSLn(n,nb,B,A = matid(n)) = { my(i,j,a,tmp); for(count=1,nb, [i,j] = randdistinct(n); a = random([-B,B]); A[,i] = A[,i] + a*A[,j]; [i,j] = randdistinct(n); ); A; } rmzerocol(A) = { my(L=[]); for(i=1,#A, if(A[,i]!=0, L = concat(L,[A[,i]])) ); matconcat(L); } print("bb hermite Z/NZ"); N=1800; nb = 500; setrand(1); print("imagemod"); {for(m=1,4, for(n=1,4, for(count=1,nb, A = matrix(m,n,i,j,random([0,N-1])); h1 = mathnfmodid(A,N); h2 = matimagemod(A,N,&U); if(rmzerocol(h1%N)!=h2, print("fail: ", A)); if(A*(U*Mod(1,N))!=h2, print("fail2: ", A, "\n", h2, "\n", U)); ); ); );} {M = matdiagonal([900,4,9,25,10]);M[1,]=[900,2*65,9*13,25*11,5*17];} H = matimagemod(M,N) nb = 250; {for(count=1,nb, A = randSLn(5,50,N,M); if(H != matimagemod(A,N), print("fail3: ", A); ); );} {M = [11,28,-1; 2,1,89; 5,78,15; 0,8,3; 0,0,3 ];} H = matimagemod(M,N) {for(count=1,300, A = randSLn(3,30,N,M); if(H != matimagemod(A,N), print("fail4: ", A); ); );} print("kermod"); d=1800; nb=250; setrand(1); {for(m=1,5, for(n=1,5, for(count=1,nb, M = matrix(m,n,i,j,random([0,d-1])); K = matkermod(M,d,&im); if((M*K)%d!=0, print("fail:", M)); K2 = matsolvemod(M,d,0,1)[2]; K3 = matimagemod(K2,d); if(K!=K3, print("fail2:", M, K, K3)); im2 = matimagemod(M,d); if(im!=im2, print("fail3:", M, im, im2)); ); ); );} d = 6; matkermod(Mat([0]),d) matkermod(Mat([1]),d) matkermod(Mat([2]),d) matkermod([1;0],d) matkermod([2;0],d) matkermod([0;0],d) matkermod([3;0],d) matkermod([0;1],d) matkermod([0;2],d) matkermod([1;3],d) matkermod([2;3],d) matkermod([2;4],d) matkermod(Mat([1,0]),d) matkermod(Mat([0,1]),d) matkermod(Mat([2,0]),d) matkermod(Mat([1,3]),d) matkermod(Mat([0,3]),d) matkermod(Mat([2,3]),d) matkermod([1,0;0,0],d) matkermod([2,0;0,3],d) matkermod([1,1;0,1],d) matkermod([2,1;0,3],d) matkermod([4,2;4,2],d) matkermod([2,2;3,0],d) print("invmod"); d=1800; nb=100; setrand(1); {for(m=1,5, for(n=1,5, for(count=1,nb, M = matrix(m,n,i,j,random([0,d-1])); U = 0; iferr(U = matinvmod(M,d),E, if(errname(E)!="e_INV", print(E)) ); if(U!=0 && (U*M)%d != 1, printsep(" ", "fail 1800:", M, U, (U*M)%d)); ); ); );} d=31; nb=100; setrand(1); {for(m=1,5, for(n=1,5, for(count=1,nb, M = matrix(m,n,i,j,random([0,d-1])); U = 0; iferr(U = matinvmod(M,d),E, if(errname(E)!="e_INV", print(E)) ); if(U!=0 && (U*M)%d != 1, printsep(" ", "fail 31:", M, U, (U*M)%d)); ); ); );} \\matsolvemod aff2lin(X) = mathnf(matconcat([X[2],X[1];0,1])); M = [1,2;3,4]; aff2lin(matsolvemod(M, [3,4]~, [1,2]~, 1)) aff2lin(matsolvemod(M, 3, [1,1]~, 1)) aff2lin(matsolvemod([1,1;1,1], [15,6]~, [2,2]~, 1)) aff2lin(matsolvemod(Mat([2,4,6]), 8, [2]~, 1)) aff2lin(matsolvemod([3;5;7], [2,3,5]~, [-1,-2,-3]~, 1)) aff2lin(matsolvemod([7,8,6;1,11,16],512,[-1,-1]~,1)) matsolvemod([1,1;1,1], 32, [17,1]~) matsolvemod(Mat(1),2,[1]~) matsolvemod([;],2,1) matsolvemod([;],2,0) matsolvemod([;],[2,2]~,1) matsolvemod([;],[2,2]~,0) matsolvemod([;],[2,2]~,[0,0]~) matsolvemod([;],[2,2]~,[1,2]~) matsolvemod([;],2,[1,2]~) matsolvemod(Mat(1),2,1) matsolvemod([1,2;3,4],0,1) \\zero ring matimagemod([1,2;3,4],1) matdetmod(Mat(3),1) matdetmod([;],1) matkermod([1,2;3,4],1) matinvmod([1,2;3,4],1) matinvmod([1,2;3,4;5,6],1) matsolvemod(Mat(1),1,[1]~,1) \\examples from docu A = [2,1;0,2]; matimagemod(A,6,&U) U (A*U)%6 A = [1,2,3;5,1,4] K = matkermod(A,6) (A*K)%6 A = [3,1,2;1,2,1;3,1,1]; U = matinvmod(A,6) (U*A)%6 A = [4,2,3; 4,5,6; 7,8,9]; matdetmod(A,27) \\end examples matdetmod([0,1;1,0],9) matdetmod([7,1;1,0],9) matdetmod([6,0;0,1],9) matimagemod([1;2],4) matimagemod([4,1;0,4],8,&U) U matsolvemod(matrix(1,0),0,[0]~) matsolvemod(matrix(1,0),0,0) matsolvemod(matrix(1,0),[0]~,[0]~) matsolvemod(matrix(1,0),[0]~,[0]~,1) matsolvemod(Mat([1]),[0]~,[0]~) matsolvemod(Mat([1]),[0]~,0) matsolvemod(Mat([1]),0,0,1) matsolvemod(Mat([2]),0,1,1) matsolvemod(Mat([21,110]),0,1,1) \\matdetmod fixes M = [21,7,7;23,2,7;20,21,31]; n=36; matdetmod(M,n) == matdet(M)%n M = matrix(11,11,i,j,if(jx+1) strtex(-oo) strtex(oo) Str(x) Str(1/2) Str("a","b",1) v = Vecsmall([1..255]); Vecsmall(strchr(v)) == v strsplit("::a::b::::", "::") strsplit("a:b::::cc", ":") strsplit("abc", "") strsplit("abc") strsplit("aba", "a") strsplit("aa", "a") strjoin(["a", 1, "cc"], "/") strjoin(["a", 1, "cc"]) strjoin([]) strjoin(["a"]) strjoin([1]) strtime(12345678) \\ Errors, keep at end of file strchr(-1) strsplit(1,1) strsplit("1",'x) strjoin(1, "/") strjoin([],1) pari-2.17.2/src/test/in/mscosets0000644000175000017500000000152714567450071015141 0ustar billbillPsl2=mspolygon(1); gamma_0(N)=msfarey(Psl2,x->x[2,1]%N==0); gamma_1(N)=msfarey(gamma_0(N),(g->my(a=g[1,1]%N); a==1 || a==N-1)); gamma_(N)=msfarey(gamma_1(N),g->g[1,2]%N==0); gamma_00(N)=msfarey(gamma_0(N),x->x[1,2]%N==0); gamma1_0(N1,N2)=msfarey(Psl2,x->x[2,1]%N1==0 && x[1,2]%N2==0); gamma1(N1,N2)= { my (N = lcm(N1,N2)); msfarey(Psl2, x->(x[2,1]%N1==0 && x[1,2]%N2==0 && x[2,1]%N==0 && x[1,2]%N==0)) }; gammafrom(N,d)=msfarey(gamma_0(N),x->(x[2,1]%(N*d)==0)); test(F)=my(A=F[2]); A^2 == A^0; F=gamma_0(5) msfarey(Psl2, x->x[2,1]%5==0,&C); C mscosets(F[3], x->x[2,1]%5==0) gamma_1(5) gamma_(3) gamma_00(3) gamma1_0(3,4) gamma1(3,4) gammafrom(10,3) F=gamma_1(91); test(F) mscosets([Vecsmall([2,1,3]), Vecsmall([2,3,1])],x->x^3==x^0) \\ ERRORS mscosets([],x->1) mscosets([1],(x,y)->1) N=24; G0 = mspolygon(N); msfarey(G0, g -> a=g[1,1]%N; a==1); pari-2.17.2/src/test/in/disc0000644000175000017500000000537014567450071014223 0ustar billbillpoldisc(Mod(1, 2)*x) poldisc(Mod(1, 3)*(2*x^3+x^2+5)) poldisc(Mod(1, 3)*(2*x^3+x+5)) poldisc((a*x^3+b*x^2+c*x+d)) poldisc((a*x^3+b*x^2+c*x+d)*Mod(1,3)) poldisc((a*x^3+c*x+d)*Mod(1,3)) poldisc(y^2/x+1, y) poldisc(x, y) check(P)= { my(d=poldegree(P)); if(poldisc(P)*y^(d*(d-1))!=poldisc(subst(P,x,x/y)*y^d),error(P)); } test(a)= { check(a^0*x^6+(a^9+a^8+a^7+a^6+a^4+a^3+a)*x+(a^9+a^8+a^7+2*a^6+a^4+a^2)); print(a^0*x^0*0,":",a^0*x^0); } test(ffgen(2^10,'a)); test(ffgen(3^10,'a)); test(ffgen([nextprime(2^100),5],'a)); test(Mod(Mod(1,2),ffinit(2,5,'a))); test(Mod(Mod(1,3),ffinit(3,5,'a))); my(p=nextprime(2^100)); test(Mod(Mod(1,nextprime(2^100)),ffinit(p,3,'a))); \\ #1830 p=Pol([1,12,-41,-1046,-1152,39768,128414,-829340,-4525890,8899442,94079590,4385944,-1307089619,-1852433280,12494993027,34801502551,-77942248052,-390957423498,215189990152,3107265788332,1420485007463,-18347443916369,-23277245912959,80992666070621,174175172136656,-256947893746801,-907981487991468,484717098540915,3624070471203629,223320207786810,-11495832122433637,-5970240860086125,29459554866159718,27626780885543732,-61174934576020682,-85453537075841594,101601090502467492,205071787088061635,-128623032844198712,-402298722797595630,103257810302253206,661593554032027685,13023738437946757,-924770373478411117,-228669477020600489,1106930103187315214,501417832370076217,-1137744012688843614,-748484700066174875,1002096690610670198,887074929263872304,-749681502970099140,-878282874862417133,466192451440777121,743397334132464078,-228293327650766293,-544343133811559511,73246386276267014,346915388490966115,2655042441806609,-192876875700267550,-25542640982995001,93481097097188652,23309890824202258,-39341812220193672,-14459562353785875,14260775252163516,7110363380474628,-4385795657650451,-2904911553101253,1111356927314961,1003888928894249,-216866559082696,-295159994592569,25722943511905,73725762974324,1493634668853,-15527611742629,-1817577645774,2717078090720,579368368367,-384681131682,-124276266074,41834786710,20049074850,-3059594663,-2480136051,67764972,231104576,16656470,-15345258,-2573079,629755,190125,-7992,-7579,-537,116,21,1]); poldisc(p) poldiscfactors(x^0) poldiscfactors(x) poldiscfactors(x^2+1) T=x^4 - 36769809176826048*x^3 + 341005843447471336362247372459582*x^2 - 55175428449449617975400382424484477584006986048*x + 2251690401007462966577022376495167683872612094945483390567809; poldiscfactors(T) poldiscfactors(T,1) T=y^24+4*y^23-14*y^22-72*y^21+79*y^20+596*y^19-26*y^18-2440*y^17-913*y^16+6004*y^15+4594*y^14-6872*y^13-3220*y^12+14436*y^11+20340*y^10+10564*y^9+21950*y^8+28292*y^7+38580*y^6+31312*y^5+64413*y^4+46004*y^3+48710*y^2+18852*y+22307; poldiscfactors(T) a=ffgen(3^2,'a);poldisc(x^6+a*x+y) poldisc(Pol(0)) \\#2157 poldisc(x^4 + 8/y*x) \\ ERRORS, keep at end of file poldisc(x^2/y^2, y) pari-2.17.2/src/test/in/ff0000644000175000017500000001171114760123736013670 0ustar billbilljell(x)=if(#x,x.j,[]); { test(p,f) = setrand(1); a = ffgen([p,f], 'a); [ ffgen(a^2+a+3), 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), jell(ellinit([a,1])), a/x, (x+a)/(x-a), if(1,setrand(1);b=ffprimroot(a)), fforder(a), b^fflog(a,b), factormod(x^2+x+a), polrootsmod(x^2+x+a) ]; } default(echo,1); test(2, 20) test(7, 7) test(precprime(2^32), 3) test(nextprime(2^32), 3) default(echo,0); stest(p,n)= { my(a=ffgen(ffinit(p,n),'a)^2); if(sqrt(a)^2!=a,error([p,n])); } ftest(p,n,r)= { my(a=ffgen(ffinit(p,n),'a)^r); if(sqrtn(a,r)^r!=a,error([p,n,r])); } default(echo,1); stest(2,1005); stest(17,2); stest(17,3); stest(17,4); stest(nextprime(2^31),2); stest(nextprime(2^31),3); stest(nextprime(2^31),4); stest(nextprime(2^63),2); stest(nextprime(2^63),3); stest(nextprime(2^63),4); stest(nextprime(2^65),2); stest(nextprime(2^65),3); stest(nextprime(2^65),4); ftest(2,1005,7); ffgen(ffinit(2^32-5,101),'a)^10000 ffgen(ffinit(2^64-59,101),'a)^10000 for(i=1,10,print(ffnbirred(11,i))); for(i=1,10,print(ffnbirred(11,i,1))); t = ffgen(2^64)^((2^64-1)\5);1/t sqrt(Mod(-1,4296540161)) sqrt(Mod(-1,18446744073944432641)) centerlift(factorcantor(prod(i=-10,10,(x^2-i)),2^64+13)[,1]) conjvec(Mod(x, x^2+Mod(1,3))) default(echo,0); test(q)= { my(t = ffgen(q,'t), m=[t,t^2,1+t^3; 1+t,1+t^2,1+t^3]); print(matker(m)); print(matimage(m)); print(matrank(m)); my(M = [t,2*t^0,3*t^0; t,t^2,1+t^3; 1+t,1+t^2,1+t^3]); print(matdet(M)); print(M^(-1)*M); my(v = [t^0, t^1, t^2]~); print(M*v); print(M*matsolve(M, v) == v); print(M*matinverseimage(M, v) == v); print(matsolve(M, matid(3)*t^0) == M^(-1)); print(matinverseimage(M, matid(3)*t^0) == M^(-1)); my(N = t*[0, 1; 0, 0]); iferr(N^-1, e,, errname(e) == "e_INV"); iferr(matsolve(N, t*[0, 1]~), e,, errname(e) == "e_INV"); print(matinverseimage(N, t*[1, 0]~)); print(matinverseimage(N, t*[0, 1]~)); print(matinverseimage(N, N^0)); print(matindexrank(N)); print(matsupplement(t*[0; 1])); print(lindep(t*[1; 1])); print(lindep(t*[0, 0; 1, 1])); } default(echo,1); test(2^5) test(7^5) test((2^64+13)^5) default(echo,0); test(q, n=10)={ my(t = ffgen(q, 't), M = matrix(n, n, i, j, random(t))); if(subst(charpoly(M), 'x, M) != 0, error("test:",[q,n])); } default(echo,1); test(nextprime(2^7)^5) test(nextprime(2^15)^5) test(nextprime(2^31)^5) test(nextprime(2^63)^5) test(nextprime(2^80)^5) test(nextprime(2^7)^5, 27) test(nextprime(2^15)^5, 27) test(nextprime(2^31)^5, 27) test(nextprime(2^63)^5, 27) test(nextprime(2^80)^2, 27) my(a=ffgen([2,100]));(0*a*x)*x default(echo,0); test(p=3,f=10,d=2,e=2)= { my(Pa,Pb); my(q = p^f); my(a = ffgen([p,f],'a), b = ffgen([p,d*f],'b), c = ffgen([p,e*d*f],'c)); my(m = ffembed(a, b), n = ffembed(b, c), k = ffembed(a, c)); my(rm = ffinvmap(m), rn = ffinvmap(n), rk = ffinvmap(k)); my(nm = ffcompomap(n,m), rmrn =ffcompomap(rm,rn)); my(rnk = ffcompomap(rn,k), rkn = ffcompomap(rk,n)); my(rmm = ffcompomap(rm,m), mrm = ffcompomap(m,rm)); my(fr=fffrobenius(b,f)); my(z = b); for(i=1,d-1,z = b + ffmap(fr,z)); if (ffmap(m,ffmap(rm,z))!=z,error("fffrobenius")); if (minpoly(ffmap(m,a),'a) != a.mod,error("minpoly")); Pa = a^2+a+3; Pb = ffmap(m,Pa); if (ffmap(rm,Pb)!=Pa, error("ffmap")); if (ffmap(rm,b)!=[],error("ffmap")); my(Qa = [Pa,x^2+x*Pa+1], Qb = ffmap(m,Qa), Qc = ffmap(n,Qb)); if (ffmap(rm,Qb)!=Qa,error("ffmap: rm")); if (ffmap(nm,Qa)!=Qc,error("ffmap: n o m")); if (ffmap(rmm,Qa)!=Qa,error("ffmap: rm o m")); if (ffmap(mrm,Qb)!=Qb,error("ffmap: m o m")); if (ffmap(rmrn,Qc)!=Qa,error("ffmap: rm o rn")); if (ffmap(rnk,Qa)!=ffmap(rn,ffmap(k,Qa)),error("ffmap: rn o k")); if (ffmap(rkn,Qb)!=ffmap(rk,ffmap(n,Qb)),error("ffmap: rk o n")); iferr(ffcompomap(m,n),E,print(E)); iferr(ffcompomap(rn,rm),E,print(E)); iferr(ffcompomap(m,rn),E,print(E)); iferr(ffcompomap(rm,n),E,print(E)); R=factor(b.mod*a^0)[1,1]; [d,l]=ffextend(a,R); if(subst(ffmap(l,R),'b,d),error("ffextend")); if(minpoly(ffmap(l,a))!=minpoly(a),error("ffextend")); iferr(ffextend(a,x^2+b*x+1),E,print(E)); if (ffmaprel(m,Pa).pol!=Pb, error("ffmaprel")); if (ffmaprel(rm,Pb).pol!=Pa, error("ffmaprel")); if (ffmaprel(rm,b).pol!='b, error("ffmaprel")); mPa = ffmaprel(m,Pa); if (subst(minpoly(mPa),x,mPa)!=0, error("minpoly")); rmPb = ffmaprel(rm,Pb); if (subst(minpoly(rmPb),x,rmPb)!=0, error("minpoly")); rmb = ffmaprel(rm,b); if (subst(minpoly(rmb),x,rmb)!=0, error("minpoly")); } default(echo,1); test(2,1,5,3) test(2,5,5,3) test(3,1,2,3) test(3,10,2,3) test(nextprime(2^100),1,3,2) test(nextprime(2^100),3,3,2) /* error */ ffinit(1,1) ffinit(4,2) ffinit(2^64,2) ffgen(x^2+x+Mod(1,3)) ffembed(ffgen([3,5],'b),ffgen([3,6],'a)); a=ffgen(3^3,'a); ffinvmap(ffextend(a,x^2+x+a)); fforder(ffgen(8)*0) pari-2.17.2/src/test/in/print0000644000175000017500000000102414567450071014425 0ustar billbillprintsep(":", 1,2,3,4);print(0); printsep(":");print(0); printsep1(":", 1,2,3,4);print(0); printsep1(":");print(0); printsep(":",matid(2));print(0); printsep1(":",matid(2));print(0); printp(matid(2)) w=42; print(quadgen(5)) q = 2 + 0*quadgen(-3,z); printtex(q) print(q) q = quadgen(-3,z); printtex(q) print(q) q = 2*quadgen(-3,z); printtex(q) print(q) q = 2 + 3*quadgen(-3,'z); printtex(q) print(q) q = 2 + 3*I; printtex(q) print(q) f(x)=my(y=Pi*x);y*sin(y); g(x)=my(y=Pi*x);y*cos(y); M=[f,g;f,g]; eval(Str(f))==f eval(Str(M))==M pari-2.17.2/src/test/in/minmax0000644000175000017500000000054214676526175014600 0ustar billbillv = [-3,7,-2,11]; w = [-oo,-Pi^100,2^100,+oo]; obj = [1, v, Vecsmall(v), List(v), [-3,7;-2,11], w]; { for (i = 1, #obj, my (o = obj[i], u,v); vecmin(o, &u); vecmax(o, &v); print(i, ": ", [vecmax(o), vecmin(o), u, v, abs(vecmax(o)), abs(vecmin(o))]); ) } \\ ERRORS vecmin([]) vecmin(Mat()) vecmin(List()) vecmax([]) vecmax(Mat()) vecmax(List()) pari-2.17.2/src/test/in/bnrL10000644000175000017500000000122514724330077014250 0ustar billbillsetrand(1); K=bnfinit(x^2+31);bnrL1(bnrinit(K,1)) setrand(1); K=bnfinit(x^2-3); setrand(1); bnrL1(bnrinit(K,5),,5) setrand(1); bnrL1(bnrinit(K,[5,[1,0]]),,5) \\ avoid 32/64-bit discrepancy for near-0 components filter(v)= apply(x->if(exponent(imag(x[2])) < -127, real(x),x), v); setrand(1); filter( bnrL1(bnrinit(K,[5,[1,1]]),,5) ) setrand(1); K=bnfinit(x^2-168);\\#1601 setrand(1); bnrL1(bnrinit(K,[6,[1,1]]),,5) P=x^5-x^4-5*x^3+4*x^2+3*x-1; S=x^10-26*x^8+233*x^6-832*x^4+1024*x^2-401; bnf=bnfinit(a^2-401*25); cond=rnfconductor(bnf,P,1); bnr=bnrinit(bnf,cond[1]); real(bnrL1(bnr,cond[3],1)) default(realprecision,100); bnrL1(bnrinit(bnfinit(Q),[5,[1]]))[1] pari-2.17.2/src/test/in/rfrac0000644000175000017500000000203614676526175014404 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) (1+x)/(2+x)*(1+O(3^5)) M = [ 1, 1, 1; 'a, 'b, 'c; 'a^2, 'b^2, 'c^2 ]; [A, B, C] = M^-1 * [ 'u, 'v, 'w ]~; X = A^2 + B^2 + C^2; Y = A*B + A*C + B*C; Z = 'u^2 - 2*Y; [X == Z,X - Z] poldegree(y/x) trace(I/x) 1./x-1/x type(1/x-1/x) type(Pol(0)/x) Pol(0)/(Mod(1,2)*x) pari-2.17.2/src/test/in/ellnf0000644000175000017500000001521214760301046014365 0ustar billbilldefault(parisize,"16M"); K=nfinit(t^3-2); e=ellinit([t+1,t^2 - (t^3+(t+1)*t)], K); P=[t,t]; ellisoncurve(e, P) elladd(e, P,P) ellmul(e, P,3) ellordinate(e, t) ellordinate(e, t+1) elldivpol(e, 3) ellfromj(Mod(t,t^3-2)) ellinit(e, idealprimedec(K,2)[1]) ellinit(e, idealprimedec(K,5)[1]) K = nfinit(t); e = ellchangecurve(ellinit([1,0],K),[17^2,0,0,0]); P = idealprimedec(K,17)[1]; elllocalred(e,P) nf4=nfinit(a^2+1); P17 = idealprimedec(nf4,17)[1]; P13 = idealprimedec(nf4,13)[1]; P5 = idealprimedec(nf4,5)[1]; E=ellinit([1+a,0,1,0,0],nf4); ellheight(E) E2 = ellchangecurve(E, [17,0,0,0]); [ellap(E2, P5), ellap(E2, P13), ellap(E2, P17)] [ellcard(E2, P5), ellcard(E2, P13), ellcard(E2, P17)] [ellgroup(E2, P5), ellgroup(E2, P13), ellgroup(E2, P17)] E3 = ellchangecurve(E, [1/17,a,a+1,0]); ellap(E3, P17) ellan(E2,20) ellan(E3,20) ellglobalred(E) ellglobalred(E2) ellglobalred(E3) K=nfinit(x^4+20*x^2+16); E = ellinit([-1377/256*x^6-6885/32*x^4+729/4*x^3-4131/2*x^2+14013/4*x+5589/4, -1863/16*x^6-9315/2*x^4-5589/2*x^3-44712*x^2-53460*x+33534], K); P2 = idealprimedec(K,2)[1]; [ellap(E,P2), ellgroup(E,P2)] P3 = idealprimedec(K,3)[1]; [ellap(E,P3), ellgroup(E,P3)] P5 = idealprimedec(K,5)[1]; [ellap(E,P5), ellgroup(E,P5)] E = ellinit([1/4*x^2+3,-7/4*x^2-1,-3/16*x^3-5/4*x^2-1/2,-1/4*x^3-3/4*x^2-x,-3/16*x^3-1/4*x^2-3/2*x+1/2],K); ellgroup(E,P2,1) ellgroup(E,P3,1) P=idealprimedec(K,209844281664738991); for(i=1,4, if(idealval(K,E.disc,P[i])>0,print(ellgroup(E,P[i],1)[1..2]))); K=bnfinit(a^2 - 2*3*5*29); e = ellinit([a,1], K); E = ellchangecurve(e, Mod([2^3 * 3 * a, a+123, 17*a+2, 16*a+3], K.pol)); ellintegralmodel(E)[1..5] ellintegralmodel(E, &v)[1..5] v ellminimalmodel(E, &v)[1..5] v ellminimalmodel(ellinit([a^4,(a+2)^6], K)) bnf=bnfinit(x^2-323); E=ellinit([-629/900*x-124919/1200,17/100*x+104941/3600],bnf); F=ellminimalmodel(E,&urst); lift(urst) R=[-17/30*x-37/60,-3/10*x-17/60]; ellisoncurve(E,R) for(i=1,3,print(i,":",ellheight(E,ellmul(E,R,i))/i^2)) p=2*10^10+89; q=10^10+19; P=nfbasistoalg(K, bnfisprincipal(K, idealprimedec(K,p)[1])[2]); Q=nfbasistoalg(K, bnfisprincipal(K, idealprimedec(K,q)[1])[2]); e = ellinit([P^3*Q^4,P^6*Q^4], K); ellminimalmodel(e,&v); v ellglobalred(e) ellheight(e) e = ellinit([P^4*Q^4,P^6*Q^4], K); ellglobalred(e) K=bnfinit(a^2-65); u=Mod(8+a,K.pol); e = ellinit([1,40*u+1,0,25*u^2,0], K); ellminimalmodel(e) e = ellinit([1,10*u+1,0,25*u^2,0], K); ellminimalmodel(e) ellglobalred(e) E=ellinit([0,-1,0,-15/16*z^2+5/2*z+8,5/16*z^2-9*z+14],nfinit(z^3-4*z^2-32*z+64)); ellglobalred(E) E=ellinit([-3850829794560*a-15877538149168,-8352767604912215040*a-34439343881478343808],bnfinit(a^2-17)); ellminimalmodel(E,&v)[1..5] v \\ #1899 E=ellinit([0,34,0,225,0],bnfinit(a^2-7)); ellminimalmodel(E, &v)[1..5] v K = nfinit(a^2 - a + 1); E = ellinit([1, -1, 0, -3*a, -3*a + 3],K); /* Same curve, non integral model */ E2 = ellinit([(144*a+9)/-48,(3240*a-2565)/-864],K); idealnorm(K,ellglobalred(E)[1]) idealnorm(K,ellglobalred(E2)[1]) elltamagawa(E) elltamagawa(E2) ellrootno(E) ellrootno(E2) elltors(E) elltors(E2) ellbsd(E) ellbsd(E2) E.omega E2.omega E.eta E2.eta E.area E2.area K=bnfinit(t^5 - 8*t^4 - 2*t^3 + 2*t^2 + t - 8); E=ellinit([-10, -6, -10, -7, -8],K); Emin=ellminimalmodel(E); Emin.omega K = nfinit(a^2 - a - 22); E = ellinit([0, 0, 1, -1590*a - 8580, 92750*a + 359875],K); idealnorm(K,ellglobalred(E)[1]) elltamagawa(E) ellrootno(E) elltors(E) ellbsd(E) ellbsd(ellchangecurve(E,[1/Mod(a,K.pol),0,0,0])) ellbsd(ellchangecurve(E,[Mod(a,K.pol),0,0,0])) E.omega E.eta E.area K = nfinit(a^3 - a^2 + 1); E = ellinit([a + 1, -a^2 - a - 1, a^2 + a, -a^2, -a^2 + 1],K); idealnorm(K,ellglobalred(E)[1]) elltamagawa(E) ellrootno(E) elltors(E) ellbsd(E) E.omega E.eta E.area K = nfinit(a^2-a-57); E = ellinit([a,-a,a,-5692-820*a,-259213-36720*a],K); ellminimaldisc(E) K = nfinit(a^2-26); E = ellinit([a,a-1,a+1,4*a+10,2*a+6],K); ellminimaldisc(E) E = ellinit([1,2,3,4,5]); ellminimaldisc(E) nf2=nfinit(a^2-2); nf3=nfinit(a^2-a-1); E=ellinit([0, 0, 0, -3/2*a - 3/16, 7/8*a + 7/32],nf3); ellminimaldisc(E) ellheight(E,[-a+11/4,3*a-9/2]) E=ellinit([0,0,1,-5*a-25,-15*a-49], nf3); ellheight(E,[-4*a+3,-a+1]) ellrootno(E) E=ellinit([a+1,a-1,a,6*a+2,14*a+34],nf2); ellheight(E,[-3/2*a+1/2,-9/4*a-3/2]) ellheight(E,[-a+1,-3*a-3]); ellrootno(E) E=ellinit([0,a+1,0,18*a-27,-55*a+78],nf2); ellheight(E,[2*a-5,-2*a+5]) ellrootno(E) E=ellinit([0,a+a^2,0,a^3,(a+1)^2],nf3); ellheight(E,[-a,a+1]) ellheight(E,[-a^2,a+1]) ellrootno(E) E=ellinit([0,a+a^2,0,a^3,(a+1)^2],nfinit(a^2-a-3)); ellheight(E,[-a,a+1]) ellheight(E,[-a^2,a+1]) ellrootno(E) E=ellinit([0,1,0,a*(1-a),(a+1)^2],nf3); ellheight(E,[-a,a+1]) ellheight(E,[a-1,a+1]) ellrootno(E) E=ellinit([0,a,1,a+1,0],nf4); ellheight(E,[0,0]) ellrootno(E) E=ellinit([1,a+1,0,-2*a-1,1],nf4); ellheight(E,[-2*a,-2*a-1]) ellrootno(E) E = ellinit([x+1,-x+1,0,7*x-46,-22*x+118], nfinit(x^2-x+3)); ellheight(E,[3,-2*x+2]) ellrootno(E) E = ellinit([x+1,-1,x,-x^2,0], nfinit(x^3-x^2+1)); ellheight(E,[0,-x]) ellrootno(E) E = ellinit([-22032-15552*a,0],nf2); ellheight(E,[-72*a-108,0]) ellrootno(E) \\#2461 nf3 = nfinit(a^3-41*a^2+426*a-184); E = ellinit([1,-3/46*a^2+73/46*a-4],nf3); ellrootno(E) \\#2001 E=ellinit([0,-1,0,-49,141]); K=nfinit(t^5-8*t^4-2*t^3+7*t^2+6*t-10); EK=ellinit(E,K); v=[-10389455*t^4+94207180*t^3-74647193*t^2-43748717*t+61159408,2455284431170392*t^4-11016432463258648*t^3-93170850675195967*t^2+178129308340634152*t-98800231481430471,0,2728467290019334591152803*t^4-22989796437900272628924775*t^3+2354051986650548020107980*t^2+37608622876236967823113454*t-29191600123918022419958490]; Emin=ellchangecurve(EK,Mod(v,K.pol)); u=nfeltembed(K,v[1]); A1 = Emin.area; A2 = apply(x->abs(x)^2,u) * E.area; exponent(vector(3,i,(A1[i]-A2[i])/A2[i])) E=ellinit([1,a+1,a+1,18606575967166652*a-153729155890347509,3849964978395963953436488*a-31808746938748928238787861],nfinit(a^2-a-60)); ellrootno(E) e(D,f,p)= { my(v=valuation(f,p),k=kronecker(D,p)); (1-p^v)*(1-k)/(p^(v-1)*(1-p)*(k-p)); } fal(E)= { my(D,f,wD,hD,aD,F,h); [D,f]=coredisc(elliscm(E),1); wD=if(D==-4,4,D==-3,6,2); hD=quadclassunit(D)[1]; aD=abs(D); F=factor(f)[,1]; h=log( idealnorm(E.nf,ellminimaldisc(E))^(1/(12*poldegree(E.nf.pol))) *(f*sqrt(abs(D))/Pi)^(1/2) *prod(k=1,aD,gamma(k/aD)^(-kronecker(D,k)*wD/(4*hD))) *prod(i=1,#F,F[i]^(e(D,f,F[i])/2)) ); he = ellheight(E); if(abs(h-he)>10^-35,error(E)); } Q=nfinit(a); fal(ellinit([4,0],Q)) fal(ellinit([0,1],Q)) fal(ellinit([255^3],Q)) fal(ellinit([-292658282496*a-180872773632],nfinit(a^2-a-1))) fal(ellinit([85995*a-138510],nfinit(a^2-a-1))) fal(ellinit([6548115718144*a-22082088337408],nfinit(a^2-a-8))) nf=bnfinit(a^2-11*a-1); ellinit([Mod(-5*a+12,a^2-a-1),Mod(-10,a^2-a-1),Mod(-16,a^2-a-1),Mod(44,a^2-a-1),Mod(15*a-97,a^2-a-1)],nf); pari-2.17.2/src/test/in/pow0000644000175000017500000000153014676526175014112 0ustar billbill(Mod(1,3)+I)^0 (Mod(1,9)+I*Mod(1,3))^0 (1/x)^0 [;]^0 Mat(2)^0 Mod(0,1)^0 Mod(2,3)^0 q=Qfb(2,0,-1); q^0 q^1 [q,1.]^0 [q,1.]^1 [q,1.]^2 v=Vecsmall([3,2,1]); v^0 v^1 O(2)^1 O(2)^-2 (1/2)^-2 (-2/3)^-2 (-1/4)^(1/2) (-1/8)^(1/3) (-4)^(1/2) (-8)^(1/3) n=2^64; 1^n (-1)^n (-1)^(n+1) 2^n (1/2)^n Qfb(2,0,-1)^n Mod(x,polcyclo(7))^n O(x)^(1/2) (x^3+O(x^6))^(1/3) [2,3]^3. [2,3]~^3. Mat(2)^3. O(x^0)^(1/3) 0.^(1/2) Mod(2,3)^100000000000000000000000001 Mod(4,5)^100000000000000000000000001 Mod(2,3)^(1/2) Mod(2,3)^(1/3) Mod(1,4)^(1/2) (2+O(7^5))^(1/2) (3+O(7^5))^(1/2) a=2+O(7^3); a^a sqrt(1+O(2)) sqrt(1+O(2^3)) sqrt(Mod(2,4)) [0,1]^[1,2] [0,1]^[1,2]~ [0,1]^[1,1;2,3] (x+Mod(0,1))^0 2^(-1-10^-9) 2^Mod(2,(I*1E-28*x+1)) 2^(1+O(3^4)) (-1)^(1/2) (-1)^(-1/2) powers(Mod(2,11),10) powers(Pi,7) powers(3, 5, 2) powers(3,-1) powers(3,0) \\ERRORS [1]^2 [1]^1 [1]^0 List()^1 pari-2.17.2/src/test/in/det0000644000175000017500000000230114567450071014044 0ustar billbillM=[8, 520037431316, 0, 520037431316, 0, 520035574851, 0, 965887922181; 520037431316, 38628881218179226412880, 4958989308, 38629 323366757228004016, 73478513407, 38628858533840109643628, 4243910044575227, 71751970539224190286968; 0, 4958989308, 0, 4957132843, 0, 5710115047, -5940688, 0; 520037431316, 38629323366757228004016, 4957132843, 38629765515335229595152, 74231495611, 38629300680212375365180, 4243835813079616, 71752791774805257538227; 0, 73478513407, 0, 74231495611, -5940688, 0, 1856465, 0; 520035574851, 38628858533840109643628, 5710115047, 38629300680212375365180, 0, 38628836591317537513845, 4243835813079616, 71751920822489123831004; 0, 4243910044575227, -5940688, 4243835813079616, 1856465, 4243835813079616, -752982204, 7881921412974726; 965887922181, 71751970539224190286968, 0, 71752791774805257538227, 0, 71751920822489123831004, 7881921412974726, 133277068316447073113823]; matdet(M) matdet(M,1) centerlift(chinese(apply(p->matdet(M*Mod(1,p)),primes(200)))) centerlift(chinese(apply(p->matdet(M*Mod(1,p)),vector(5,i,nextprime(2^(128+i)))))) \\ #2128 matdet([x,1/x,1;y,1/y,1;1,1,1]) \\ #2445 d=69; v=vector(2*d); v[2]=1; for(k=3,2*d,v[k]=v[k-1]+(v[k-2]+1)\2) M=matrix(d,d,x,y,v[d+x-y]); matdet(M) pari-2.17.2/src/test/in/lfun0000644000175000017500000003604414676526175014261 0ustar billbilldefault("parisize","16M"); \\ overflows 14M zetaan(n)=vector(n,i,1); K=bnfinit('x^3+'x^2-3*'x-1); L148=lfuncreate(K); lfuncost(L148, [20]) lfunthetacost(L148) for(i=1,10,print(i,":",lfun(L148,-i))) L117=lfundiv(nfinit('x^4-'x^3-'x^2+'x+1),1); for(i=1,10,print(i,":",lfun(L117,i))) e121=ellinit([1,1,1,-30,-76]); \\ 121a1 L121=lfuninit(e121,[100],2); lfuncost(L121) lfun(L121,1+100*I) lfun(L121,1+x+O(x^3)) lfun(1,1+x+O(x^4),1) lfun(1,1+x+O(x^4),2) lfun(1,2+x^2+O(x^6),1) lfun(1,2+x^2+O(x^6),2) \p36 lfun(x^4-2,x+O(x^6),1) lfun(x^4-2,x+O(x^6),2) \p38 lfuncreate(x^2+1/2); lfun(polcyclo(12),2) lfunmul(1,Mod(2,5))[2..5] lfun(lfunmul(1,1),1) lfun(lfunmul(x^2+1,x^2+1),1) lfun(lfundiv(x^2+1,-4),1) pol=x^6-3*x^5+5*x^4-5*x^3+5*x^2-3*x+1; real(lfun(lfundiv(pol,[bnrinit(bnfinit(x^2+23),1),[1]]),1)) \\ check for loss in accuracy in lfunthetaspec nf24217=nfinit(x^5-5*x^3-x^2+3*x+1); L2=lfuncreate(nf24217); lfunhardy(L2,5) lfunhardy(L2,-5) lfun(1,0.,2) \\ division by 0 due to unnormalized series /* higher precision */ default("realprecision",54) /* Riemann */ lzeta = lfuncreate(1); lfun(lzeta,1) lfun(lzeta,1/2+200*I) lfun(lzeta,.5+200*I) lfun(lzeta,0,1) lfun(lzeta,x) lfunzeros(lzeta,14.14) lfunzeros(lzeta,[14,14.5]) lfunzeros(lzeta,30) lfunzeros(lzeta,[-20,20]) lzeta[6]=0; lfun(lzeta,2) lfuntheta(lzeta,1e50) lfuntheta(lzeta,1e50+I) /* odd Dirichlet char */ lfun(Mod(8,13), 1) /* EC */ e = ellinit([0, 0, 1, -7, 6]); lfunzeros(e,20) lfunzeros(e,[0,3]) lfunzeros(e,[-3,-1]) lfunzeros(e,[1,3]) lfunzeros(e,[-3,3]) /* Ramanujan */ ltau=lfunetaquo(Mat([1,24])); lfunmfspec(ltau) mf=mfinit([4,9,-4],0); F=mfeigenbasis(mf)[1];L=lfunmf(mf,F);lfunmfspec(L) /* other functions */ t = 4+I/5; t^2*lfuntheta(L121,t) lfuntheta(L121,1/t) vv=lfunthetainit(L121,1/t); lfuntheta(vv,1/t) lfunthetacost(vv) vv=lfunthetainit(L117,[1,2/5]); lfuntheta(vv,1) my(x = 2*I/5); e=exp(x/2)*lfuntheta(vv, exp(x)); /* should be real */ [real(e),round(imag(e)*10^55)] M=msinit(11,4,1); F=mssplit(M,msnew(M))[1]; L=lfuncreate([n->subst(lift(msqexpansion(M,F,n)),'x,1+sqrt(3)),0,[0,1],[4,3/2],11,1]); default("realprecision",115); lfun(L,2) default("realprecision",54); Z101=znstar(101,1); L=lfuncreate([Z101,[1]]); L=lfuninit(L,[1,1,1]); lfuncheckfeq(L) L=lfuninit(L,[1,1,1]); lfuncheckfeq(L) lfuncheckfeq(L,11/10) lfuncheckfeq(L,9/10) lfun(L,1) lfun(L,2) { my(V=lfunan(L,100)); my(q=exp(2*I*Pi/101),S=sum(i=1,100,V[i]*q^i)/sqrt(-101)); my(z=lfuntheta(L,1),eps=abs(S-z/conj(z))); if(eps>10^-55,error("charinit(101): ",eps)); } lfunzeros(L,20) L=lfuncreate([Z101,[1]]); L=lfuninit(L,[1,0,0]); lfuncheckfeq(L) lfun(L,1) K=bnfinit('x^2+23);B=bnrinit(K,1); L=lfuncreate([B,[1]]); lfuncheckfeq(L) algdep(exp(lfun(L,0,1)),3) /* GENUS 2 curve */ print("Curve y^2+(x^3+x^2+1)*y = x^2+x"); L=lfungenus2([x^2+x,x^3+x^2+1]); default("realprecision",19); lfuncheckfeq(L) print("Curve y^2+(x^3+1)*y = x^2+x"); L=lfungenus2([x^2+x,x^3+1]); for(i=1,20,lfunan(L,i)) print("Curve y^2+(x^2+x)*y = x^6+3*x^5+6*x^4+7*x^3+6*x^2+3*x+1"); L=lfungenus2([x^6+3*x^5+6*x^4+7*x^3+6*x^2+3*x+1,x^2+x]); L[5]*=4; lfuncheckfeq(L) print("Curve y^2=",x^5+x); fun(p, d)= \\ if (d == 2), only 1 + trace term is needed { my(p16=p%16, p8=p16%8); if (d == 2 && p8 != 1, return (1)); if (p8 == 5 || p8 == 7, return((1+p*x^2)^-2)); my([u,v] = qfbsolve(Qfb(1,0,2),p)); if (p8 == 3, return (1 / (1 + (-4*u^2 + 2*p)*x^2 + p^2*x^4))); if (u%4 != 1, u=-u); if(p16==1,(1-2*x*u+p*x^2)^-2, (1+2*x*u+p*x^2)^-2); } L=lfuncreate([[(p,d)->fun(p, d),[[2, 1]]], 0, [0,0,1,1], 2, 2^16, -1]); default("realprecision",38) lfuncheckfeq(L) lfunrootres(L) lfun(L,1,1) print("Curve y^2=",x^5+1); B=bnfinit(polcyclo(5)); fun2(p, d)= \\ if (d == 2), only 1 + trace term is needed { my(p10 = p%10); if (p10 != 1, if (d == 2, return (1)); return (if (p10==9, 1 / (1+2*p*x^2+p^2*x^4), 1 / (1 + p^2*x^4))); ); my (u = nfbasistoalg(B, bnfisprincipal(B,idealprimedec(B,p)[1])[2])); my (a = subst(liftpol(u),x,x^2) * u); for (i = 0, 9, my (b = (-x)^i * a); my (t = nfelttrace(B, b), t10 = t % 10); if (t10 == 4, return(if (d == 2, 1 + t*x, 1 / polrecip(minpoly(b))))); ); } L=lfuncreate([[(p,d)->fun2(p,d),[[2,1],[5, 1]]], 0, [0,0,1,1], 2, 5^4*2^4, 1]); lfuncheckfeq(L) lfunrootres(L) lfun(L,1) lfungenus2(x^5+3^5) \\#2047 print("Elliptic curves over number fields"); K=nfinit(a^2+1); E1=ellinit([1+a,0,1,0,0],K); lfuncheckfeq(E1) lfunlambda(E1,1) E2=ellinit([a,0,a,0,0],K); lfuncheckfeq(E2) lfunlambda(E2,1) E3=ellinit([1,a-1,a+1,-a-1,0],K); lfuncheckfeq(E3) lfunlambda(E3,1) E4=ellinit([0,1-a,a,-a,0],K); lfuncheckfeq(E4) lfunlambda(E4,2) K2=nfinit(a^2-a+5); E5=ellinit([a,1-a,1,-1,0],K2); lfuncheckfeq(E5) lfunlambda(E5,1) K=bnfinit(subst(x^3-x^2-3*x+1,x,a)); E=ellinit([a^2-a-2,-a^2+2*a+3,a^2-1,-a^2+a+4,-a^2+2],K); localbitprec(4); lfuncheckfeq(E) localbitprec(32);lfuncheckfeq(E) print("Grossencharacter"); K=bnfinit(polcyclo(5)); id5=idealprimedec(K,5)[1]; B=bnrinit(K,id5); F(p,d)= { my(pr=idealprimedec(K, p, d-1)); 1 / simplify(lift(prod(k=1,#pr, 1 - G(pr[k])*X^pr[k].f))); } G(pr)= { if(idealval(K,B.mod,pr),0, my([e,al] = bnrisprincipal(B,pr)); my(al1=nfbasistoalg(K,al)); my(al2=nfbasistoalg(K,nfgaloisapply(K,x^2,al))); my(al3=nfbasistoalg(K,nfgaloisapply(K,x^3,al))); al1^3*al2^2*al3^1); } L=lfuncreate([(p,d)->F(p,d),0,[-1,0,0,1],4,625,0]); lfuncheckfeq(L) lfun(L,2)/(Pi/5^(15/4)*gamma(1/5)^(7/2)*gamma(3/5)^(1/2)/(gamma(4/5)^(7/2)*gamma(2/5)^(1/2))) print("tensor product") E=ellinit([0,-1,1,-10,-20]); F=ellinit([1,0,1,4,-6]); L=lfuncreate([[(p,e)->my(ta=ellap(E,p),tb=ellap(F,p));1/(p^4*x^4-tb*ta*p^2*x^3+(-2*p^2+(ta^2+tb^2)*p)*x^2-tb*ta*x+1),[[2,1/(2*x^2-2*x+1)],[7,1/(7*x^2+2*x+1)],[11,1/(11*x^2+1)]]],1,[-1,0,0,1],3,23716,0]); \pb64 lfuncheckfeq(L) lfun(L,3/2) print("check all formats"); default("realprecision",54) e = ellinit([0, 0, 1, -1, 0]); le2 = lfuncreate([ n->ellan(e,n), 0, [0,1], 2, 37, -1]); le3 = lfuncreate([ ellan(e,1000), 0, [0,1], 2, 37, -1]); le4 = lfuncreate([ (p,d)->1/(1-ellap(e,p)*'x+if(p!=37,p*'x^2)), 0, [0,1], 2, 37, -1]); le41 = lfuncreate([ [(p,d)->1/(1-ellap(e,p)*'x+p*'x^2), [[37,1/(1+'x)]]], 0, [0,1], 2, 37, -1]); lfuncheckfeq(le2) lfuncheckfeq(le3) lfuncheckfeq(le4) lfuncheckfeq(le41) lfunan(le41,10) lfunan(2^63+5,10) lfunan(2^64+5,10) lfunparams(lfuncreate(1)) lfunparams(1) lfunparams(ellinit([1,1])) lfunparams(Mod(19,3)) \\ zeta(s)*zeta(s-(k-1)), single pole at k if k even >= 4 f(k) = lfuncreate([n->vector(n,i,sigma(i,k-1)),0,[0,1],k,1,I^k,zeta(k)]); exponent(lfun(f(4),5)-zeta(5)*zeta(2)) \\ bernfrac(2*k) / (4*k) forstep(k=4,18,2,print(bestappr(-lfun(f(k),0),10000000))) L = lfuninit(x^2+1, [1,2,2]); lfun(L,2)/(Pi^2/6*Catalan) lfunhardy(L,2) lfun(lfunetaquo([1,1;3,1;5,1;15,1]),2) lfun(lfunetaquo(Mat([1,24])),2) lfun(lfunetaquo([5,2;7,2]),2) lfun(ellinit([1,1,1,-10,-10]),2) \\ 15a1 lfunan(lfunetaquo([12,1;13*12,1]),1) \\ #2457 L=lfunqf(Mat(1)); lfuncheckfeq(L) lfuncheckfeq(lfunshift(L,1)) localbitprec(64);lfuncheckfeq(lfunshift(L,1,1)) L=lfunshift(1,4); lfun(L,2) \\ residue 2*Pi/sqrt(23) at 1 L=lfunqf([2,1;1,12]); L=lfuninit(L,[1/2,20],1); newton(L,z,N)=for(i=1,N,z-=lfun(L,z)/lfun(L,z,1));z; z=newton(L,1/2+16*I,10) abs(lfun(L,z))>1e-50 localprec(100); L=lfunmul(1,1); lfun(L,2)/(Pi^4/36) lfuncheckfeq(L) localbitprec(300);L=lfunmul(L,1); lfun(L,3)/(zeta(3)^3) lfuncheckfeq(L) print("zeta(s-a)"); Z(a)=lfuncreate([(p,n)->1/(1-p^a*x+O(x^n)),0,[-a],2*a+1,1,1,[[a+1,0]]]); lfuncheckfeq(Z(1)) lfun(Z(1),2) lfun(Z(1),3) lfuncheckfeq(Z(2)) lfun(Z(2),2) lfun(Z(2),3) print("zeta(s)*zeta(s-a)"); L(a)=lfuncreate([(p,n)->1/((1-p^a*x)*(1-x)),0,[-a,0],a+1,1,1,[[a+1,lfun(1,a+1+x+O(x^2))*(1/x+Euler+O(x))],[1,lfun(1,1-a+x+O(x^3))*(1/x+Euler+O(x))]]]); lfuncheckfeq(L(1)) lfun(L(1),2) lfun(L(1),3) lfuncheckfeq(L(2)) lfun(L(2),2) lfun(L(2),3) lf=[1,-7,-3,25,3,21,-9,-63,6,-21,-4,-75,-3,63,-9,169,37,-42,-75,75,27,28,10,189,-76,21,-90,-225,212,63,-6,-623,12,-259,-27,150,-88,525,9,-189,-3,-189,547,-100,18,-70,-147,-507,25,532,-111,-75,-108,630,-12,567,225,-1484,-45,-225,145,42,-54,2233,-9,-84,-632,925,-30,189,-650,-378,859,616,228,-1875,36,-63,-978,507,-234,21,931,675,111,-3829,-636,252,-571,-126,27,250,18,1029,-225,1869,453,-175,-24,-1900,830,777,1246,189,81,756,707,-2250,-378,84,264,-1521,-225,-1575,30,5300,-18,315,-333,567,-1722,-1015,9,-150,-108,378,1607,-6111,-1641,63,-1399,300,675,4424,-270,-2331,-861,210,1938,-675,441,4550,12,1014,636,-6013,-75,-2200,157,-1596,2356,4725,222,-252,-18,225,-414,6846,324,-1869,-90,1638,-11,-75,36,-6517,-1852,-1701,-1460,-777,-450,13675,-2021,4452,684,-676,135,3997,1444,450,442,-189,-435,-630,-264,-126,-148,-3675,810,1575,-366,-6699,-2790,-3171,27,625,-815,168,-2753,4788,1896,-5810,-1908,-2775,-9,-8722,60,-507,300,-567,-3519,-2700,1950,-4949,1641,5670,54,2646,-2577,-300,-111,-1848,100,5607,-456,1575,-2302,5625,-813,-210,-108,-13356,-1136,126,-441,-1125,2934,2331,5251,-1521,5366,12054,2673,3625,75,-63,225,378,-2793,756,4478,-1350,-40,-11249,-333,13257,-1794,11487,792,-225,1272,9793,4270,-756,-324,-4725,1713,-15800,7959,1890,-2409,6253,-81,6027,304,-750,1592,-13566,-36,1701,7566,-3087,-737,-16250,675,-84,27,-3738,-6553,-4452,-1359,21475,-6777,525,-135,5544,360,-1099,-30,5700,-4923,-16492,-2490,-12675,435,-1554,1350,900,-3738,126,4001,-567,2685,2898,-162,-24450,7560,-2268,-848,6699,-2121,630,-2775,-5850,228,77,1134,189,1323,-252,-6732,23275,-528,12964,-1896,4563,-5228,10220,675,2775,24,3150,-2808,-34461,-90,14147,2829,-15900,4999,-4788,270,2492,-18397,-945,-1950,-14275,999,-10108,3871,-1134,-1861,-3094,5166,675,2577,3045,3171,1690,-18,1848,972,450,-6977,1036,324,9261,-636,-5670,8517,-5625,-4821,2562,5665,18333,108,19530,3282,11325,-194,-189,370,-1575,4197,5705,-2934,-600,-1484,19271,-2025,-12844,-2484,-13272,18,20750,-702,13356,352,6993,-12944,63,2583,31150,405,-420,2793,1869,-5814,-2100,-1919,2025,21564,24633,-882,6804,-2812,-13650,-1305,17675,-36,-11487,-1559,-15210,-4556,-378,-1908,-9450,-750,18039,-4476,756,150,777,7725,6600,-1713,-700,-471,-20097,-8444,3192,12,-5625,-7068,16114,81,-14175,-2673,5691,-3330,750,-5217,756,-2666,35828,54,7952,-672,-450,5688,3087,1242,2835,-2188,-20538,5700,-8325,-648,-36757,-1129,5607,264,-37562,270,-43050,1359,-18711,467,-9135,33,-525,-4973,225,7844,-1575,-72,-1014,5850,19551,-3859,-2700,5556,-31346,4091,3402,2490,280,4380,40175,10085,2331,-7731,-31311,6750,12558,3738,-41025,588,-5544,6063,567,-2290,-8904,11663,-34975,-2052,-29890,-222,2028,-13838,2268,-270,16875,9,-11991,2121,39816,-4332,-55713,-100,-6750,16984,16863,-1326,-23051,-1134,567,-6079,-21525,870,-2128,-15900,1890,8802,-11144,792,48450,-28136,252,-1641,-4563,444,-52962,591,11025,-675,5159,2106,40950,-13725,-4725,16866,300,1098,-189,-760,13398,21984,45871,8370,15900,-8379,9513,432,-54117,-54,47439,3770,-1875,450,945,2445,-14872,16344,-2520,-999,3925,8259,210]; L=lfuncreate([lf,0,[-1,0,0,1],4,61,1]); localprec(38);lfunconductor(L,100) K=bnfinit(y^2+47); rel=x^5+2*x^4+2*x^3+x^2-1; [f,bnr,subg]=rnfconductor(K,rel); L=lfuninit([bnr,subg],[2,0,0]); lfun(L,2) lfuncost(L) \\ #2434 K=bnfinit(polcyclo(3,a));[f,bnr,subg]=rnfconductor(K,x^3-2); M=lfuninit([bnr,subg],[1.,3.,2]); L=lfuninit(polcyclo(3), [1/2,0,0]); lfuncheckfeq(L) lfuncost(L) lfunconductor(1,1) K=bnfinit(y^2-4493); R0=bnrinit(K,[idealprimedec(K,1123)[1],[1,1]]); L=lfuncreate([R0,[7]]); localprec(1000); c=lfuncost(L,[0],1) /* lfunconductor */ default(realprecision,38); lfunconductor(1) lfunconductor(-4) lfunconductor(857) lfunconductor(120) lfunconductor(2108) lfunconductor(1,[],-1) lfunrootres(x^3+x^2-3*x-1) default(realprecision,19) lfunconductor(1,10) /* guess small conductor */ e1=ellinit([0, 0, 1, -7, 6]); lfunconductor(e1) lnf725=lfundiv(x^4-x^3-3*x^2+x+1,1); lfunconductor(lnf725,,1) lfunconductor(lnf725, divisors(725)) /* bigger one. * remark: should be able to search in a big range * with few coefficients, would be faster */ lnf24217=lfundiv(nf24217,1); lfunconductor(lnf24217,10^5,1) e2=ellinit([3,-27,-18,24,9]); lfunconductor(e2,10^8,1) N=nfinit(x^6-3*x^5+5*x^4-5*x^3+5*x^2-3*x+1);G=galoisinit(N); L=lfunartin(N,G,[[-1,1;-1,0],[0,1;1,0]],1); if(lfunan(L,100)!=lfunan(lfundiv(x^3-3*x^2+2*x-1,1),100),error("lfunartin")); N=nfinit(x^12-11*x^10+44*x^8-78*x^6+60*x^4-16*x^2+1); G=galoisinit(N); L=lfunartin(N,G,[1,-y+1,y,-y+1,-1,y,-y,1,y-1,-y,y-1,-1]~,6); if(round(lfunan(L,100)-lfunan([znstar(28,1),[5,1]],100),&e),error("lfunartin")); e K=nfinit(polcyclo(4,a));G=galoisinit(K);[T,o]=galoischartable(G); L=lfunartin(K,G,T[,1]+T[,2],o); localbitprec(50);lfuncheckfeq(L) \\lfuntwist E=ellinit([0,-1,1,-10,-20]); lfunan(lfuntwist(E,-4),10) lfunan(lfuntwist(E,Mod(2,7)),10) bnr=bnrinit(bnfinit(a),13);lfunan(lfuntwist(E,[bnr,[1]]),10) localbitprec(20); #lfunzeros('x^2-2,6) lfuncost(1, [100], 5) L = lfuninit(polcyclo(5), [1/2,1/2,50]); lfuncost(L) lfun(1,2000) default(realprecision,38) Z=znstar(7,1); La=lfuncreate([Z,[2]]); Lb=lfuncreate([Z,[4]]); L=La;L[2]=Lb[1]; lfun(L,2+I) lfun(La,2+I) { L1=lfuncreate([Z,[1]]); L2=lfuncreate([Z,[3]]); my(t=lfunrootres(L1)[3]); L=lfuncreate([n->lfunan(L1,n)+lfunan(L2,n),n->conj(lfunan(L1,n))*t+lfunan(L2,n),[1],1,7,1]); } f(s)=[round(lfun(L,s)/(lfun(L1,s)+lfun(L2,s)),&e),e]; lfuncheckfeq(L) f(2+I) \\ zeta via lfuncreate + Lambda polar part a=n->vector(n,i,1); z=lfuncreate([a, a, [0], 1, 1, 1, [[0,-1/x+O(1)], [1,1/x+O(1)]]~]); lfun(z,2) { E=ellinit([0,0,1,0,-7]); \\27a1 localbitprec(48); for(i=1,7, L=lfunsympow(E,i); print(i,":",lfuncheckfeq(L))) } L=lfunsympow(E,5); lfun(L,1,1) \\ #2118 Z = lfuncreate([n->[1], 0, [0], 1, 1, 1, 1]); lfun(Z,2) \\ #2185 bnr=bnrinit(bnfinit('a^4+47),1); lfun([bnr,[1]],2) L=lfuncreate(()->x^2-3); lfuncheckfeq(L) lfuncheckfeq(lfunmul(L,L)) lfuncheckfeq(lfunmul(L,1)) lfuncheckfeq(lfundiv(L,1)) lfuncheckfeq(lfuntwist(L,Mod(2,5))) lfuncheckfeq(lfunshift(L,1/2)) lfun(1, -2+O(x)) lfun(1, -2+O(x^2)) lfun(1, 0.) lfun(x^2+1, -1+O(x^2)) K=bnfinit(y^2-17); R=bnrinit(K,[idealmul(K,2,idealprimedec(K,67)[1]),[1,0]]); lfun([R,[[1],[3]]],0,1) lfun([R,[2]],1) lfun([R,[[2]]],1) bnf=bnfinit(y^2+1); bnr=bnrinit(bnf,12); L=lfun([bnr,[[2,0],[6,0]]],2) L=lfunshift(1,-100); lfun(L,-100+50*I); \\ SEGV at low accuracy lfun(y^8-4*y^7+7*y^6-7*y^5+7*y^4-7*y^3+2*y^2+y-1,0,1) \\ ERRORS: keep them at end of file lfuntheta(1,0) lfunhardy(1,I) lfun(1,2,-1) lfunan(lfuncreate([1,0,[0],1,1,1,1]),10) N=nfinit(x^2+1);G=galoisinit(N);lfunartin(N,G,[1]~,2) N=nfinit(x^2+1);G=galoisinit(N);lfunartin(N,G,[1,1,1]~,2) Lt=lfuncreate([1,0,[-1,0,0,1,-2,-1,0,0],21,61^2,1]); localbitprec(16);lfun(Lt,12); L=lfuncreate([[(p,e)->1-p*x+O(x^2),[[2,3,1/(x^2-x+1)]]],1,[0,0],2,1,0]); lfun(L,1) lfunzeros(1, [3,1]) errbnr=bnrinit(bnfinit('a^2+47),3); lfuncreate([errbnr,[[1],[2]]]); errG=znstar(44,1); lfuncreate([errG,[[1],[2]]]); lfuncreate([errG,[[1,8]~,[1,7]~]]); lfuncreate([errG,[[1,8]~,[0,1]~]]); lfunorderzero([errG,[[1,8]~,[1,2]~]]); L=lfuncreate([[(x,y,z)->1,1],0,[0],1,1,1,1]); lfunan(L,5) L=lfuncreate([[(x,y,z)->1,[1]],0,[0],1,1,1,1]); lfunan(L,5) L=lfuncreate([[x->1,[1]],0,[0],1,1,1,1]); lfunan(L,5) L=lfuncreate([[(x,y)->1,[2,3]],0,[0],1,1,1,1]); lfunan(L,5) L=lfuncreate([[(x,y)->1,[[2,3]]],0,[0],1,1,1,1]); lfunan(L,5) L=lfuncreate([[(x,y)->1,[["",3]]],0,[0],1,1,1,1]); lfunan(L,5) L=lfuncreate([[(x,y)->1,[[2,""]]],0,[0],1,1,1,1]); lfunan(L,5) lfun([[],[""]],1) \\ #2251 lfuneuler(x^2+1,Pi) lfunthetacost(polcyclo(43)) lfuncheckfeq(1,I) pari-2.17.2/src/test/in/arith0000644000175000017500000000031014567450071014375 0ustar billbill\\#1304 issquarefree(0) \\#1412 core(4*10^15+27) { forfactored(d=-100,100, if (issquarefree(d[1]) != issquarefree(d[2]), error(d)); if (isfundamental(d[1]) != isfundamental(d[2]), error(d)) ); } pari-2.17.2/src/test/in/printf0000644000175000017500000000535014676526175014613 0ustar billbillaa=[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) printf("%10.6f",1/2510629980073882876067348736); \\#2198 my(M=[1,2,3;4,5,6;7,8,9]); printf("%5d",M); printf("%5.2f",1.0*M); \\ conversions using gtolong() printf("%c",97.5) printf("%c",97+1/2) printf("%c",97 + 0.*I) printf("%c",97 +0*quadgen(5)) printf("%1.2f",Mat([1.,2.])) printf("%c",'x) default(format,"f.5") -0.00000000000000000000000000000000000000293873587705572 printf("%d",factor(2*3*5*7)) printf("%5d\n", -1+I); printf("%5d\n", -1-I); printf("%5d\n", 1-I); printf("%5d\n", 1+I); printf("%05d\n", -1+I); printf("%05d\n", -1-I); printf("%05d\n", 1-I); printf("%05d\n", 1+I); printf("%.5g\n", -1+I); printf("%.5g\n", -1-I); printf("%.5g\n", 1-I); printf("%.5g\n", 1+I); printf("%.5g\n", [1+I, 1-I]); pari-2.17.2/src/test/in/zeta0000644000175000017500000000073014676526175014251 0ustar billbillallocatemem(20*10^6); zeta(3+O(5^10)) zeta(1 + I/100) zeta(1000.5) zeta(1000) zeta(100) zeta(31) zeta(100+100*I) zeta(60+I) zeta(-1000+I) zeta(2+O(2^10)) zeta(2^64) zeta(-2^64) iferr(zeta(-1-2^64),E,E) zeta(2+1e-101*I) zeta(1.01) zeta(1e-32) zeta(50.5) zeta(-2.5) zeta(O(x)) default(seriesprecision,3) zeta(1+x) zeta(1/2+I*x+O(x^2)) zeta''(0) zeta([2,3,4]) zeta([3/2,5/2,7/2]) zeta([2]) zeta(I+2^(-64)) zeta(0.+O(x)) \\ Errors zeta(1) zeta(1+O(3)) \\#2375 \ps1 zeta(1+t) pari-2.17.2/src/test/in/sort0000644000175000017500000000146214760123736014266 0ustar billbillv = [[1,2], [4,1], [3,4], [1,3/2], [5/2,1.]]; a = [1,2]; b = [5,2]; w = vecsort(v) vecsearch(w, a) vecsearch(w, b) K = [ 1, 2, 3, [2,1], [3,1], (x,y)->x[1] - y[1] ]; { for (i = 1, #K, iferr (w = vecsort(v, K[i]); print(w); print(vecsearch(w, a, K[i])); print(vecsearch(w, b, K[i])), E, print(E)) ) } v = [x^2+1, x^3-2, x+1, x^2+27]; f(x)=poldisc(x); vecsort(v, f) vecsort(v, f, 1) vecsort(v, f, 1+4) vecsort(v, f, 1+4+8) vecsearch(v, x+10, f) T=vecsort(Vecsmall([4,3,2,1])) vecsearch(T,-1) vecsearch(T,5) vecsearch(T,3) T=vecsort(List([4,3,2,1])) vecsearch(T,-1) vecsearch(T,3) vecsearch(List(),1) v=[4,3,4,1,4,2,3]; vecsort(v,, 8) vecsort(v,, 8+1) vecsort(v,, 8+4) vecsort(v,, 8+4+1) vecsort(List(),,4) \\Errors vecsearch(Vecsmall(1),1,1) vecsort(Vecsmall(1),1) pari-2.17.2/src/test/in/factorback0000644000175000017500000000016114724330232015360 0ustar billbill\\ ERRORS factorback(Vecsmall([1,2]),[3,4]) factorback('x,[3,4]) factorback([1,2,3],[3,4]) factorback([1,2],'x) pari-2.17.2/src/test/in/linear0000644000175000017500000000510214676526175014556 0ustar billbillHEAP=[97, if(sizebyte(0)==16,9032,9212)]; \e algdep(2*cos(2*Pi/13),6) algdep(2*cos(2*Pi/13),6,15) charpoly([1,2;3,4],z) charpoly(Mod(x^2+x+1,x^3+5*x+1),z) charpoly([1,2;3,4],z,1) charpoly(Mod(1,8191)*[1,2;3,4],z,2) lindep(Mod(1,7)*[2,-1;1,3]) lindep([(1-3*sqrt(2))/(3-2*sqrt(3)),1,sqrt(2),sqrt(3),sqrt(6)]) lindep([(1-3*sqrt(2))/(3-2*sqrt(3)),1,sqrt(2),sqrt(3),sqrt(6)],14) matadjoint([1,2;3,4]) matcompanion(x^5-12*x^3+0.0005) matdet([1,2,3;1,5,6;9,8,7]) matdet([1,2,3;1,5,6;9,8,7],1) matdetint([1,2,3;4,5,6]) matdiagonal([2,4,6]) mateigen([1,2,3;4,5,6;7,8,9]) mathess(mathilbert(7)) mathilbert(5) amat=1/mathilbert(7) mathnf(amat) mathnf(amat,1) mathnf(amat,4) mathnf(amat,5) mathnfmod(amat,matdetint(amat)) mathnfmodid(amat,123456789*10^100) matid(5) matimage([1,3,5;2,4,6;3,5,7]) matimage([1,3,5;2,4,6;3,5,7],1) matimage(Pi*[1,3,5;2,4,6;3,5,7]) matimagecompl([1,3,5;2,4,6;3,5,7]) matimagecompl(Pi*[1,3,5;2,4,6;3,5,7]) matindexrank([1,1,1;1,1,1;1,1,2]) matintersect([1,2;3,4;5,6],[2,3;7,8;8,9]) matinverseimage([1,1;2,3;5,7],[2,2,6]~) matisdiagonal([1,0,0;0,5,0;0,0,0]) matker(matrix(4,4,x,y,x/y)) matker(matrix(4,4,x,y,sin(x+y))) matker(matrix(4,4,x,y,x+y),1) matkerint(matrix(4,4,x,y,x*y)) matkerint(matrix(4,4,x,y,x*y),1) matkerint(matrix(4,6,x,y,2520/(x+y))) matmuldiagonal(amat,[1,2,3,4,5,6,7]) matmultodiagonal(amat^-1,%) matpascal(8) matrank(matrix(5,5,x,y,x+y)) matrix(5,5,x,y,gcd(x,y)) matrixqz([1,3;3,5;5,7],0) mathnf(matrixqz([1/3,1/4,1/6;1/2,1/4,-1/4;1/3,1,0],-1)) mathnf(matrixqz([1,3;3,5;5,7],-2)) matsize([1,2;3,4;5,6]) matsnf(1/mathilbert(6)) matsnf(x*matid(5)-matrix(5,5,j,k,1),2) matsolve(mathilbert(10),[1,2,3,4,5,6,7,8,9,0]~) matsolvemod([2,3;5,4],[7,11]~,[1,4]~) matsolvemod([2,3;5,4],[7,11]~,[1,4]~,1) matsupplement([1,3;2,4;3,6]) mattranspose(vector(2,x,x)) %*%~ norml2(vector(10,x,x)) qfgaussred(mathilbert(5)) qfjacobi(mathilbert(6)) m=1/mathilbert(7) mp=concat(m,matid(7)) qflll(m) qflllgram(m) qflllgram(m,1) qflllgram(mp~*mp,4) qflll(m,1) qflll(m,2) qflll(mp,4) qfminim([2,1;1,2],4,6) qfperfection([2,0,1;0,2,1;1,1,2]) qfsign(mathilbert(5)-0.11*matid(5)) trace(1+I) trace(Mod(x+5,x^3+x+1)) Vec(sin(x)) vecmax([-3,7,-2,11]) vecmin([-3,7,-2,11]) concat([1,2],[3,4]) concat(Mat(vector(4,x,x)~),vector(4,x,10+x)~) vecextract([1,2,3,4,5,6,7,8,9,10],1000) vecextract(matrix(15,15,x,y,x+y),vector(5,x,3*x),vector(3,y,3*y)) round((1.*mathilbert(7))^(-1) << 77) / 2^77 vecsort([8,7,6,5],,1) vecsort([[1,5],[2,4],[1,5,1],[1,4,2]]) vecsort(vector(17,x,5*x%17)) vecsort([[1,8,5],[2,5,8],[3,6,-6],[4,8,6]],2) vecsort([[1,8,5],[2,5,8],[3,6,-6],[4,8,6]],[2,1]) vector(10,x,1/x) if (getheap()!=HEAP, getheap()) pari-2.17.2/src/test/in/ellrank0000644000175000017500000001665514706137543014742 0ustar billbilldefault(parisize,"24M"); \\ overflows 20M [GMP], 22M [portable] mwrank(E,e=0) = setrand(1); ellrank(E,e); { E=ellinit([1,0,1,34318214642441646362435632562579908747, 3184376895814127197244886284686214848599453811643486936756]); } R=mwrank(E) round(matdet(ellheightmatrix(E,ellsaturation(E,R[4],100)))) { E=ellinit([0,-438879732513040081/428593506250000,0,-112353213812869130368/26787094140625,3081846839375070007684953094049946244/717548412498706207275390625]); } R=mwrank(E) round(matdet(ellheightmatrix(E,ellsaturation(E,R[4],100)))) dujella= { [[1,0,0,-1086750289534747727483801311783198679020964,435973165715323898311705750809969552813996511661336976727731984], [1,1,1,-204436185783252342785934887233210383183371840,1165977772244037776901948451219544033496456897571880326934385121505], [1,1,1,-10920091632464590365831264648975539,437651494057993449247068775775947593191303103178481], [1,0,0,-615411322294732283803288785027250860840,5538719221187391635372324416383813743465156669756429313600], [0,-1,0,-28988736544619415368095370719165120,2092184664137813418988486724511221531954993872509532], [1,1,1,690560257169377937125059126423812540,-33492188518937203020097127431557287129957999127407035], [1,0,0,-756828185715435657801375588494450478688880,253401847133358152315350001760510755926602193561212158650118400], [0,1,0,-11849634571550798667743047864720,15613761915399875450490670165233536220551598068], [1,0,0,-304241169811532712979315990,2065986446448965089594679105215890328100], [1,0,0,-476388667785943389435012002002520620,126543502804781110382893072580356730547061880243200400], [1,0,0,-4422329901784763147754792226039053294186858800,98943710602886706347390586357680210847183616798063680624530387016000], [1,0,0,-3531474678706925407855636725500,2548317483638211729406118411284184511350250000], [1,-1,1,-42403753582533569425032932,106274144228004532427905140464314177031], [1,0,0,-2749906390198370341509293334209840,55466178854972875780766488008304927128432629217600], [1,0,0,-544753256053055692212823356675,154756127532691562955214620687209364995464257], [1,-1,0,-1478818379630960182018543975144238479079598870400357903794,21612333371564362906227820064846376685227380006732368388851217276076518563786908263808], [0,1,0,-126805284556646749335939083075808898286800006041,6437933136993997783664151467830511224300392764380156814845149031129959], [1,0,0,-1209873315556653510389989204544209972082084,331058311839965956052748107957148273288865814054655695750098704], [1,1,1,-3303894515586689289541165506478574062530571840,73094841061617585831898118162636503049865840051589473263026790881505], [1,1,1,-16343354562559064151871130832020659,-42639589563151841387449703830240754991749490260239], [0,1,0,-6141005737705911671519806644217969840,5857433177348803158586285785929631477808095171159063188], [1,1,1,-2245321045583713014514387556551626518613389075,40951023798706743647147655022412395573869307978556305934134697952785], [0,-1,0,-3600510377430985267434688529347574077140,83138379062405631329348360175446817662846629397471808788100], [0,1,0,-23686061832482481624168232900,1401294826072670363740983663536729053022048], [0,-1,0,-866893152450363503763740085700,61220734062068506723288644020689511073795652], [1,0,0,-37680956700999226080263982005713090640,-36992898397926078743894505902555362159162611772488902400], [1,0,1,-5012222351518888614250804048874855041913,136464417579052941096027626504118630642626009794008307407656], [1,0,0,-990429690240960203866170,343844266388187332499781887080604900], [1,0,0,-2353799432200918732090882185,39989567111692230080439457690563434811225], [1,0,0,-59964332656283235183736182568175070,5262192586204697880378286484023061659919913201000900], [1,0,0,-15745932530829089880,24028219957095969426339278400], [1,0,0,-2564530435455464744050430,-774033544664307864229665861908231100], [1,0,0,-18262097056293794050462967800,947221615382521776843113311413294620840000], [1,0,0,-1501011456398147086648544266758850,22251270940723503314374317274872523646621572635332], [1,0,0,-590353702194591280765010561772238260,174588372339329184400865798305984325852297773091859600]]; } womack= {[ [0, 0, 1, -79, 342], [1, 0, 0, -22, 219], [0, 0, 1, -247, 1476], [1, -1, 0, -415, 3481], [0, 0, 0, -532, 4420], [1, 1, 0, -2582, 48720], [0, 0, 1, -7077, 235516], [1, -1, 0, -2326, 43456], [1, -1, 0, -16249, 799549], [1, -1, 1, -63147, 6081915], [0, 0, 0, -10012, 346900], [1, 0, 1, -14733, 694232], [0, 0, 1, -36673, 2704878], [1, -1, 0, -92656, 10865908], [1, -1, 0, -18664, 958204], [1, -1, 0, -106384, 13075804], [1, -1, 0, -222751, 40537273], [0, 0, 0, -481663, 128212738], [1, -1, 0, -71899, 5522449], [1, -1, 0, -124294, 14418784], [1, -1, 0, -135004, 97151644], [1, -1, 0, -613069, 98885089], [0, 0, 1, -3835819, 2889890730], [1, 0, 1, -1493028, 701820182], [1, 0, 1, -1076185, 496031340], [0, 0, 1, -16312387, 25970162646], [1, -1, 0, -10194109, 12647638369], [0, 0, 1, -21078967, 35688990786], [1, -1, 0, -1536664, 648294124], [1, -1, 0, -4513546, 3716615296], [0, 0, 1, -16359067, 26274178986], [1, -1, 0, -38099014, 115877816224], [1, -1, 0, -41032399, 106082399089], [1, -1, 0, -34125664, 69523358164] ];} checkwomack()= { for(i=1,#womack, print("W:",i,":",mwrank(ellinit(womack[i]))[1..2])); } checkwomack() checkdujella()= { for(i=1,#dujella, print("D:",i,":",mwrank(ellinit(dujella[i]),2)[1..2])); } checkdujella() crv3(D)=[0,0,1,0,(-27*D-1)/4]; quer=[-23,-3299,-3321607,-653329427]; checkquer()= { for(i=1,#quer, print("Q:",i,":",mwrank(ellinit(crv3(quer[i])))[1..2])); } checkquer() checktwist(e,f,v=[])= { my(E=ellinit(e), F=ellinit(f), rk, R, C, D); setrand(1); rk = ellrankinit(E); R = ellrank([rk,F],,v); print(R); foreach(ell2cover([rk,F]),C, if(!ellisoncurve(F,C[2]*Mod(1,y^2-C[1])),error(e))); if(#R[3]&&vecmin(ellisoncurve(F,R[3]))==0,error("twist")); } checktwist([28,-172,304,-328628448,1486696690624],[66,-954,5454,-37136547171,1787447910597444]); checktwist([66,-954,5454,-173907,-7341759],[28,-172,304,-4064,-20032]); checktwist([66,-954,5454,-173502,-7327179],[28,-172,304,-3744,-20032]); checktwist([-1,1],[-36,216]); checktwist([-289,1],[-289*5^2,-5^3],[[369/4,-2753/8]]); checktwist([1,3],[323761,552660027]); E=ellinit([-27^2,7]); [Q,P]=ell2cover(E)[1] H=hyperellratpoints(Q,10^4,1)[1] PE=substvec(P,[x,y],H) ellisoncurve(E,PE) E=ellinit([-441,0]); [Q,P]=ell2cover(E)[1] H=hyperellratpoints(Q,10^4,1)[1] PE=substvec(P,[x,y],H) ellisoncurve(E,PE) \\ gcov for(i=1,8,setrand(i); ellrank(ellinit([1,0,0,-164,-1386]))); mwrank(ellinit([-3888,-97200])) mwrank(ellinit([-2109,-37100])) for(i=1,4,setrand(i); ellrank(ellinit([0,-1,0,-30169,-2107466]))); \\ check for old regressions mwrank(ellinit([-181^2,-1])) mwrank(ellinit([1,0,1,-33,68])) mwrank(ellinit([0,1,0,-150908,-22509312])) E=ellinit([0,-7396/27]); ellglobalred(E); mwrank(E) mwrank(ellinit([0,-1,0,-260,-1530])) E=ellinit([0,0,0,-1,351298031616]); mwrank(E) mwrank(ellinit([-625,3125])) mwrank(ellinit([1,0,1,54,-4676])); mwrank(ellinit([0,0,1,0,11864580])) mwrank(ellinit([0,-1,0,-877,-9662])) mwrank(ellinit([0, -1, 1, -616, -25561])) mwrank(ellinit([1, -1, 1, -3129930, -2196797303])) mwrank(ellinit([1,-1,1,-2111,-34914])) mwrank(ellinit([1,0,1,4143,72058])) E=ellinit([0,21,0,112,0]); mwrank(E) E=elltwist(E,1821016415105981103692022320410328256932518913); mwrank(E) localbitprec(64); mwrank(ellinit([1,0,0,-3548640074840486080,-2573007444343298815350037540])) \\error checktwist([1,2],[1,3]) checktwist([1,0],[2,0]) checktwist([0,1],[0,3]) ellrank([ellinit([1/2]),1,1]); ellrank([ellinit([1,1,1,1,1]),1,1]); ellrank([ellinit([0,1,1,1,1]),1,1]); pari-2.17.2/src/test/in/subfields0000644000175000017500000003066714676526175015302 0ustar billbilldefault(nbthreads,1); default(parisize,"32M"); \\ overflows 30M /* 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 */ ,x^12-4*x^11-14*x^10+44*x^9+226*x^8+380*x^7-542*x^6-2620*x^5+4249*x^4-6312*x^3+13056*x^2-67392*x+97344 /* #1758 */ ];} { for (i=1,#v, P = v[i]; S = nfsubfields(P); print(i,":", apply(x->poldegree(x[1]),S)); for(j=1,#S,s=S[j];if(subst(s[1],x,Mod(s[2],P)),error([P,s])))) } { for (i=1,#v, P = v[i]; S1 = nfsubfields(P,,1); S2 = nfsubfields(P,2,1); foreach(S1,s,if(type(s)!="t_POL",error([P,s]))); foreach(S2,s,if(type(s)!="t_POL",error([P,s])))); } nfsubfields(x^7-x-1,1) nfsubfields(x^7-x-1,7) nfsubfields(x^7-x-1,5) nfsubfields(x^6-3*x^5+5*x^4-5*x^3+5*x^2-3*x+1,1) nfsubfields(x^6-3*x^5+5*x^4-5*x^3+5*x^2-3*x+1,6) nfsubfields(x^6-3*x^5+5*x^4-5*x^3+5*x^2-3*x+1,3) nfsubfields(x^7-x-1,1,1) nfsubfields(x^7-x-1,7,1) nfsubfields(x^7-x-1,5,1) nfsubfields(x^6-3*x^5+5*x^4-5*x^3+5*x^2-3*x+1,1,1) nfsubfields(x^6-3*x^5+5*x^4-5*x^3+5*x^2-3*x+1,6,1) nfsubfields(x^6-3*x^5+5*x^4-5*x^3+5*x^2-3*x+1,3,1) /* maximal CM subfield */ dec(pol) = { my(vp); vp = [15889, 11927, 10499, 18367, 10159, 11657, 13159, 14983, 12541, 17789]; print(vector(#vp,i,factormod(pol,vp[i],1)[,1]~)); setrand(1); }; testcm(a,P) = { my(pol,v); if(!a,return(a)); pol=a[1]; v=variable(pol); if(pol!=subst(pol,v,-v), return(-1)); if(polsturm(pol), return(-2)); if(polsturm(substpol(pol,v^2,v))!=poldegree(pol)/2, return(-3)); if(subst(pol,v,Mod(a[2],P))!=0, return(-4)); dec(pol); \\to quickly check if different output defines the same field a }; testmaxcm(P,fl=0) = { my(a); print("P=", P, " fl=",fl); if(fl, a = nfsubfieldscm(nfinit(P)), \\else a = nfsubfieldscm(P) ); b = nfsubfieldscm(P,1); if(b && type(b)!="t_POL",error(P)); testcm(a,P) }; setrand(1); x = 'x; y = varhigher("y"); testmaxcm(x^2+2*x+7) \\d=2 testmaxcm(x^2+x+7) \\d=2 testmaxcm(x) \\d=0 testmaxcm(x^2-2) \\d=0 testmaxcm(x^3-x-1) \\d=0 testmaxcm(x^2+3,1) \\d=2 testmaxcm(x^4+3) \\d=2 testmaxcm(x^6+3,1) \\d=2 Galois testmaxcm(y^6-2*y^3+7*y^2+28*y+29) \\d=2 testmaxcm(x^6+2*x^4+x^2+3) \\d=2 testmaxcm(x^4-x+1,1) \\d=0 testmaxcm(x^3-x+1) \\d=0 testmaxcm(x^4-x^3+2*x-1) \\d=0 testmaxcm(x^4+10*x^2+81,1) \\d=4 Galois testmaxcm(y^4-y^3+3*y^2-2*y+4) \\d=4 testmaxcm(x^4+4*x^2+2,1) \\d=4 Galois testmaxcm(y^4-2*y^3+5*y^2-4*y+2,1)\\d=4 testmaxcm(x^8-4*x^7+6*x^6-4*x^5+11*x^4-20*x^3+10*x^2+81,1) \\d=4 pol = x^12-4*x^10+6*x^8+6*x^6-19*x^4+10*x^2+81; fa = nffactor(pol,subst(pol,x,y)); print("with factorisation given, P=",pol); testcm(nfsubfieldscm([pol,fa]),pol) \\d=4 testmaxcm(x^8+8*x^6-16*x^5+32*x^4-48*x^3+88*x^2-80*x+49,1) \\d=4 testmaxcm(x^12+4*x^9+4*x^8+6*x^6+8*x^5+2*x^4+4*x^3+4*x^2+1,1) \\d=4 testmaxcm(x^16-8*x^14+1108*x^12+3704*x^10+31142*x^8+104712*x^6+151252*x^4+101000*x^2+25921,1) \\d=4 testmaxcm(x^32+64*x^30+6784*x^28+313984*x^26+7747040*x^24+108163584*x^22+981706752*x^20+10666873856*x^18+162128298368*x^16+1744771198976*x^14+10419948331008*x^12+43184187432960*x^10+220661237381120*x^8+598077891510272*x^6+1432066821718016*x^4+4527791925035008*x^2+5903913504477184) \\d=4 pol=x^12+16*x^10-2*x^9-23*x^8-354*x^7+78*x^6-12*x^5+1468*x^4+1120*x^3+1808*x^2+768*x+576; \\d=2 nf = nfinit(pol); fa = nffactor(nf,subst(pol,x,y)); print("with factorisation given, P=",pol); testcm(nfsubfieldscm([nf,fa]),pol) testmaxcm(x^4 + 12*x^3 + 256*x^2 + 3336*x + 12604,1) \\d=4 Galois testmaxcm(y^2+y+1,1) \\d=2 testmaxcm(x^6-3*x^5+10*x^4-15*x^3+19*x^2-12*x+3,1) \\d=6 testmaxcm(x^6-2*x^5+5*x^4-7*x^3+10*x^2-8*x+8) \\d=6 testmaxcm(x^6-3*x^5+9*x^4-13*x^3+14*x^2-8*x+2) \\d=6 testmaxcm(x^6-x^5+3*x^4+5*x^2-2*x+1) \\d=6 Galois \\bug #2279 {testmaxcm( a^32 - 325413*a^30 + 65270233310*a^28 + 1500863526264933*a^26 + 21376978048106811144*a^24 + 5551736480851565829015*a^22 + 133169745322757800314805500*a^20 + 63038687459374293832889074215*a^18 + 257768884325926210746438801850200*a^16 + 106388222008795550711265556291586085*a^14 + 77117030842561455372903634633528375614*a^12 + 89909431142768246830844916641035661283*a^10 + 433487290591291262458414346008665504185*a^8 - 43302983359912417821332209228814088*a^6 + 3368895127412412772163639959696*a^4 + 2707609737271108248140094720*a^2 + 255851012946831041433600)}; \\bug (Pascal) testmaxcm(x^6-3*x^5+4*x^4-3*x^3+4*x^2-3*x+1); /* pol=x^64+96*x^62+3664*x^60+138336*x^58+48820072*x^56+3774511776*x^54+70408452368*x^52-3415715897312*x^50-181460174504612*x^48-1463269424430880*x^46+112876320630546640*x^44+3886553626590075360*x^42+32310544425610576856*x^40-817216419624670193120*x^38-18911989493213299044592*x^36+75574827575221188959392*x^34+6783110257645673896066374*x^32+67427794556366653417262880*x^30-409224232405699240608837520*x^28-10185024231373897791953995488*x^26+33608627271402636315786176216*x^24+2140786977982277330764698677728*x^22+21348037724434578430036558445488*x^20+100303837892445470036900049409120*x^18+582288171538387674384751933046364*x^16+7711202633675979091131330471311264*x^14+69710093402021717453738274884587632*x^12+386871329165182266612613221832239264*x^10+1514959930843170006056476784315321960*x^8+3874327706504734663911058389446508896*x^6+7048076339097734475940309155972500528*x^4+6410435303585417655341147657197094624*x^2+3772954882839399478106092174375436161; nf = nfinit([pol,10^6]); \\40s nfcertify(nf)==[] fa = nffactor(nf,subst(pol,x,y)); \\2min testcm(nfsubfieldscm([nf,fa]),pol) \\10s \\nfsubfields 2h \\d=4 */ y = 'y; \\from doc nf = nfinit(x^8 + 20*x^6 + 10*x^4 - 4*x^2 + 9); nfsubfieldscm(nf) testcm(nfsubfieldscm(nf),nf.pol) pol = y^16 - 8*y^14 + 29*y^12 - 60*y^10 + 74*y^8 - 48*y^6 + 8*y^4 + 4*y^2 + 1; fa = nffactor(pol, subst(pol,y,x)); nfsubfieldscm([pol,fa]) setrand(1); \\ necessary for 32/64-bit compatibility testcm(nfsubfieldscm([pol,fa]),pol) /* maximal subfields */ nfsubfieldsmax(x+1) nfsubfieldsmax(x^2+1) nfsubfieldsmax(polcyclo(5)) nfsubfieldsmax(polcyclo(7)) nfsubfieldsmax(x^6+x^4+2*x^2+1) nfsubfieldsmax(x^12+x^10-x^9+x^8+3*x^7+2*x^6+2*x^5-x^4+x^2+x+1) nfsubfieldsmax(x^18+x^16-x^15+x^14-2*x^13+2*x^12+4*x^11+4*x^10+2*x^9-2*x^7-2*x^6-2*x^5-x^4+x^2+x+1) nfsubfieldsmax(x^7-x-1) nfsubfieldsmax(x^7-x^6-12*x^5+7*x^4+28*x^3-14*x^2-9*x-1) nfsubfieldsmax(x^8-3*x^7+6*x^6-9*x^5+9*x^4-7*x^3+4*x^2-x+1) nfsubfieldsmax(x^12-5*x^11+13*x^10-25*x^9+39*x^8-50*x^7+53*x^6-48*x^5+37*x^4-23*x^3+12*x^2-4*x+1) nfsubfieldsmax(x+1,1) nfsubfieldsmax(x^2+1,1) nfsubfieldsmax(polcyclo(5),1) nfsubfieldsmax(polcyclo(7),1) nfsubfieldsmax(x^6+x^4+2*x^2+1,1) nfsubfieldsmax(x^12+x^10-x^9+x^8+3*x^7+2*x^6+2*x^5-x^4+x^2+x+1,1) nfsubfieldsmax(x^18+x^16-x^15+x^14-2*x^13+2*x^12+4*x^11+4*x^10+2*x^9-2*x^7-2*x^6-2*x^5-x^4+x^2+x+1,1) nfsubfieldsmax(x^7-x-1,1) nfsubfieldsmax(x^7-x^6-12*x^5+7*x^4+28*x^3-14*x^2-9*x-1,1) nfsubfieldsmax(x^8-3*x^7+6*x^6-9*x^5+9*x^4-7*x^3+4*x^2-x+1,1) nfsubfieldsmax(x^12-5*x^11+13*x^10-25*x^9+39*x^8-50*x^7+53*x^6-48*x^5+37*x^4-23*x^3+12*x^2-4*x+1,1) /* nfsubfields using factorisation */ y = varhigher("y"); nfsubfields_fa(pol,d=0) = nfsubfields([pol,nffactor(pol,subst(pol,x,y))],d); nfsubfields_fa(x^2+1) nfsubfields_fa(polcyclo(5)) nfsubfields_fa(polcyclo(7)) {for(i=1,#v, L = nfsubfields_fa(v[i]); print(apply(a->poldegree(a[1]),L)) )}; nfsubfields_fa(x^7-x-1,1) nfsubfields_fa(x^7-x-1,7) nfsubfields_fa(x^7-x-1,5) nfsubfields_fa(x^7-x-1) nfsubfields_fa(x^6-3*x^5+5*x^4-5*x^3+5*x^2-3*x+1,1) nfsubfields_fa(x^6-3*x^5+5*x^4-5*x^3+5*x^2-3*x+1,6) nfsubfields_fa(x^6-3*x^5+5*x^4-5*x^3+5*x^2-3*x+1,3) nfsubfields_fa(x^8-3*x^7+6*x^6-9*x^5+9*x^4-7*x^3+4*x^2-x+1) nfsubfields_fa(x^12-5*x^11+13*x^10-25*x^9+39*x^8-50*x^7+53*x^6-48*x^5+37*x^4-23*x^3+12*x^2-4*x+1) {#nfsubfields_fa(x^32-152*x^30+9592*x^28-329344*x^26+6791636*x^24-87823728*x^22 +723817584*x^20-3802250784*x^18+12604302140*x^16-26054878368*x^14 +33346127520*x^12-26066364480*x^10+12062323568*x^8-3111766784*x^6 +403544704*x^4-21688960*x^2+364816,16)} /* 1525 */ \\ slow with bad prime choice #nfsubfields(x^48-16*x^47+60*x^46+376*x^45-3456*x^44+3040*x^43+53876*x^42-174976*x^41-272765*x^40+2261976*x^39-1548616*x^38-13833480*x^37+29163082*x^36+34773712*x^35-174606468*x^34+60009120*x^33+527504938*x^32-686236912*x^31-709808060*x^30+2088782160*x^29-316365156*x^28-3142585264*x^27+2700543492*x^26+1831044936*x^25-4013808579*x^24+1417663200*x^23+1532709728*x^22-1935905360*x^21+1440999246*x^20-1499656216*x^19+1178342448*x^18+374800016*x^17-2223766223*x^16+2988494200*x^15-2313016936*x^14+860459880*x^13+422835584*x^12-1235711560*x^11+1535454560*x^10-1283650224*x^9+771182694*x^8-207859016*x^7-63471948*x^6+107318416*x^5-56103454*x^4+684280*x^3+4810240*x^2-298000*x-10775,12) #nfsubfields(x^34+63*x^33+3*x^32+98*x^31+24*x^30+81*x^29+82*x^28+85*x^27+79*x^26+60*x^25+82*x^24+15*x^23+76*x^22+39*x^21+39*x^20+16*x^19+66*x^18+66*x^17+81*x^16+35*x^15+66*x^14+87*x^13+90*x^12+71*x^11+64*x^10+24*x^9+58*x^8+16*x^7+79*x^6+85*x^5+51*x^4+41*x^3+63*x^2+97*x+63) #nfsubfields(x^24+79*x^23+93*x^22+18*x^21+37*x^20+22*x^19+30*x^18+43*x^17+56*x^16+77*x^15+19*x^14+93*x^13+91*x^12+87*x^11+23*x^10+46*x^9+54*x^8+18*x^7+56*x^6+61*x^5+47*x^2+17*x+47) nfsubfields(y^4-2,2,1) nfsubfields(y^4-2,,1) nfsubfields(y^4-2,3,1) \\Bill's variable priority bug P=x^6+108; t = varhigher("t"); F = nffactor(P,subst(P,x,t)); nfsubfields([P,F]) F = nffactor(subst(P,x,a),P); nfsubfields([subst(P,x,a),F]) F=nffactor(subst(P,x,a),P); nfsubfields([P,F]) \\bad inputs nfsubfieldscm(1) nfsubfieldscm(x^2+1/2) nfsubfieldscm([1,matrix(0,2)]) nfsubfieldscm([[],matrix(0,2)]) nfsubfieldscm([]); nfsubfieldscm([x^2+1,1]) nfsubfieldscm([nfinit(x^2+1),1]) nfsubfieldscm(4*x^2+1); nfsubfieldscm(x^0); nfsubfields([x^2-5,[z,1;z,1]]); nfsubfields([x^2-5,[z-x,1;z+x,1]]); pari-2.17.2/src/test/in/qfbclassno0000644000175000017500000000206714567450071015434 0ustar billbillqfbclassno(-100036) qfbclassno(-107128) qfbclassno(-101839) qfbclassno(-113071) qfbclassno(-44507759) qfbclassno(-57403799) qfbclassno(-94361767) qfbclassno(-111385627) qfbclassno(-136801204) qfbclassno(-185415288) qfbclassno(-198154147) qfbclassno(-223045972) qfbclassno(-1253840791) qfbclassno(-1382998299) qfbclassno(-1567139127) qfbclassno(-1788799151) qfbclassno(-1850979435) qfbclassno(-4386842803) qfbclassno(-5082406399) v3=[-653329427,-1876623871,-2520963512,-2676277123,-3146813128,-3972542271,-4724490703,-5252241199,-5288116947,-5866841451,-6127792087,-6223830596,-6903777631,-6905985272,-7189850292,-7309564084,-7311232679,-7592829611,-7993105123,-8308370723,-8417780779,-8418280523,-8624990111,-9552870967,-9775810067,-9906365947,-5393946914743]; [qfbclassno(d)|d<-v3] v5=[-11199,-12451,-11203620,-35663739,-1264381632596,-258559351511807]; [qfbclassno(d)|d<-v5] v7=[-63499,-183619,-501510767,-703668901863,-469874684955252968120]; [qfbclassno(d)|d<-v7] qfbclassno(1-2^100) qfbclassno(5<<4) qfbclassno(5<<60) qfbclassno(5<<64) qfbclassno(33844) qfbhclassno(4<<60) pari-2.17.2/src/test/in/lerch0000644000175000017500000000053614676526175014407 0ustar billbilllerchphi(5+3*I,2+3*I,1-I) lerchphi(0.8,1/2+10*I,2) lerchphi(-1,2,1) lerchphi(1/2,1,1/2) F(z,k,a)=-1/(z-1)*sum(q=0,k,(z/(z-1))^q*sum(j=0,q,(-1)^j*(j+a)^k*binomial(q,j))); exponent(lerchphi(5+2*I,-3,1/2-I)-F(5+2*I,3,1/2-I)) lerchphi(5+3*I,2,1-I) lerchphi(5+I,2,1-I) lerchphi(99/100,1/2,2) lerchzeta(1/4+3*I,1/4+I,7/8-I) lerchzeta(1/2+100000*I,1/2,1/2) pari-2.17.2/src/test/in/apply0000644000175000017500000000146714676526175014443 0ustar billbillapply(x->x^2, [1,2,3,4]) apply(x->x^2, [1,2;3,4]) apply(x->x^2, 4*x^2 + 3*x+ 2) apply(x->x^2, 4*x^2 + 3*x+ 2 + O(x^3)) apply(x->x^2, List([1,2,3,4])) L = List([Mod(1,3), Mod(2,4)]); apply(lift, L) L = List(primes(10)); select(x->x%3==1, L) f(x)=L=0;x-1; L=List(); apply(f, L); L=[1,2,3]; apply(f, L) L=[1,2,3]; [f(x) | x<-L] L=[1,2,3]; [x | x<-L, f(x)] L=[1,2,3]; select(f, L) L=Map([1,2;3,4;5,6]); apply(f,L) L=Map([1,1;3,2;5,1]); select(f,L) [x|x<-Map([1,2;3,4])] M=Map([1,2;3,4;5,6]); apply(x->x+1,M) select(x->x%4==2,M) select(x->x%4==2,M,1) fold((x,y)->x*y, [1,2,3,4]) fold((x,y)->[x,y], [1,2,3,4]) fold((x,f)->f(x), [2,sqr,sqr,sqr]) fold((x,y)->(x+y)/(1-x*y),[1..5]) printfnl(format,args[..]) = call(printf,[format,args]);print(); printfnl("%s: %s, %s",1,2,3) call("_*_",[3,5]) \\errors call(strprintf, ["%d", 10]) pari-2.17.2/src/test/in/nflistA50000644000175000017500000000073014676526175014773 0ustar billbill\\ package: nflistdata G = "A5"; nflist(G) nflist(G,,-2) nflist(G,,1) nflist(G,[100,18000]) nflist(G,18496) nflist(G,42849) nflist(G,[18497,10^5]) nflist(G,[18497,10^5],-2) G = "A5cond"; nflist(G) nflist(G,,-2) nflist(G,,1) nflist(G,[100,500]) nflist(G,633) nflist(G,[634, 1000]) G = [6,12]; nflist(G) nflist(G,,-2) nflist(G,,2) nflist(G,[100,280000]) nflist(G,287296) nflist(G,[287297,10^6]) nflist(G,[287297,10^6],-2) nfresolvent(x^6-2*x^5+3*x^4-4*x^3+2*x^2-2*x-1,3) pari-2.17.2/src/test/in/matpermanent0000644000175000017500000000073614676526175016007 0ustar billbillmatpermanent([;]) matpermanent(Mat(a)) matpermanent(Mat(1)) matpermanent([a,b,c;d,e,f;g,h,j]) m = [1,2,3;4,5,6;7,8,9]; matpermanent(m) matpermanent(m/2) matpermanent(m*1.) m = matrix(20,20,i,j,1); matpermanent(m) m = matrix(20,20,i,j,2^i + j); matpermanent(m) m = matrix(20,20,i,j,16^i + j); matpermanent(m) { for (n = 1, 10, m = matrix(n,n,i,j,i!=j); if (matpermanent(m)!=n!*sum(i=0,n,(-1)^i/i!), error(n))) } \\Errors matpermanent(matrix(64)) matpermanent(matrix(2,3)) pari-2.17.2/src/test/in/content0000644000175000017500000000104514676526175014760 0ustar billbillo=[2,1.0,Mod(1,3),2/3,ffgen(2^3),1/2+I/3,2+O(2^-3),1/2+O(2^3),quadgen(5)/3,Mod(x/2,x^2),2*x,2/x, Qfb(1,2,4),Qfb(-1,2,4),[2,3/4], [1,2;3/2,4], 1/2+x/y, [1/2+x/y], 1/(2*y) + O(x^2), y+O(y^2)]; test(f)= print(f); [ print(iferr(f(p),E,E)) | p<-o ]; test(denominator); test(x->denominator(x,1)); test(x->denominator(x,'y)); test(numerator); test(x->numerator(x,1)); test(x->numerator(x,'y)); test(content); test(x->content(x,1)); test(x->content(x,'y)); numerator(1/x+1/y,'x) numerator(1/x+1/y,'y) variables(content(1,y)) variables(content(x*y*z+1,y)) pari-2.17.2/src/test/in/agm0000644000175000017500000000070214676526175014051 0ustar billbillgagm(a,b)= { my(prec=10^(1-precision(a*1.))); while(norm(a-b)>prec^2, aa = (a+b)/2; bb = sqrt(a*b); if (norm(aa-bb)>norm(aa+bb), bb=-bb); a=aa;b=bb); a; } testagm(x)= { my(e = norm(agm(x,1)-gagm(x,1))); if(e > 1.E-75, printf("error %s: %s\n",x,e)); } for(i=-6,6,for(j=-6,6,testagm(1/6+i/3+j*I/3))); agm(1,2+O(5)) localbitprec(192); a = 1.0; s = agm(a, a*I + x + O(x^200)); polcoeff(s, 0) polcoeff(s, 10) polcoeff(s, 100) pari-2.17.2/src/test/in/lfunquad0000644000175000017500000000055614676526175015133 0ustar billbilllfun(8,-7) LD=[-3,-4,-7,5,8,13,-20,-24,-51,-56,101,104,105,-103,-107,-116]; { for(i=1, #LD, D=LD[i]; print1(D," "); for(k=2,20, print(lfun(D,1-k))); forstep(k=100+(D<0),300+(D<0),100, print(lfun(D,1-k)))); } for (k=0,3,print(lfun(-3,k))) for (k=0,3,print(lfun(-4,k))) for (k=0,3,print(lfun(5,k))) for (k=0,3,print(lfun(8,k))) lfun(10^6+1, 1-80) eulerfrac(448) pari-2.17.2/src/test/in/galois0000644000175000017500000002056314676526175014572 0ustar billbill\\package:galdata test(a)= { my(x, y, z); for (i=1, 10000, z = eval(Str("T", a, "_", i)); if (poldegree(z) == 1, break); \\ undefined x = polgalois(z); y = polgalois(poltschirnhaus( poltschirnhaus(z) )); print(x, x==y) ); } { T1_1 = x; T2_1 = x^2+x+1; T3_1 = x^3+x^2-2*x-1; T3_2 = x^3+2; T4_1 = x^4+x^3+x^2+x+1; T4_2 = x^4+1; T4_3 = x^4-2; T4_4 = x^4+8*x+12; T4_5 = x^4+x+1; T5_1 = x^5+x^4-4*x^3-3*x^2+3*x+1; T5_2 = x^5-5*x+12; T5_3 = x^5+2; T5_4 = x^5+20*x+16; T5_5 = x^5-x+1; T6_1 = x^6+x^5+x^4+x^3+x^2+x+1; T6_2 = x^6+108; T6_3 = x^6+2; T6_4 = x^6-3*x^2-1; T6_5 = x^6+3*x^3+3; T6_6 = x^6-3*x^2+1; T6_7 = x^6-4*x^2-1; T6_8 = x^6-3*x^5+6*x^4-7*x^3+2*x^2+x-4; T6_9 = x^6+2*x^3-2; T6_10= x^6+6*x^4+2*x^3+9*x^2+6*x-4; T6_11= x^6+2*x^2+2; T6_12= x^6-2*x^5-5*x^2-2*x-1; T6_13= x^6+2*x^4+2*x^3+x^2+2*x+2; T6_14= x^6-x^5-10*x^4+30*x^3-31*x^2+7*x+9; T6_15= x^6+24*x-20; T6_16= x^6+x+1; T7_1 = x^7+x^6-12*x^5-7*x^4+28*x^3+14*x^2-9*x+1; T7_2 = x^7+7*x^3+7*x^2+7*x-1; T7_3 = x^7-14*x^5+56*x^3-56*x+22; T7_4 = x^7+2; T7_5 = x^7-7*x^3+14*x^2-7*x+1; T7_6 = x^7+7*x^4+14*x+3; T7_7 = x^7+x+1; T8_50 = x^8-x-1; T8_49 = x^8-2*x^6-2*x^5-x^4-x^3+4*x^2+4*x-2; T8_48 = x^8-2*x^6-2*x^5+2*x^4+4*x^2+2; T8_47 = x^8+x^2+2*x+1; T8_46 = x^8-4*x^5-9*x^4-16*x^2-12*x+9; T8_45 = x^8-2*x^6-2*x^5+4*x^3+2*x^2+2; T8_44 = x^8+x^2-1; T8_43 = x^8-x^7+7*x^2-x+1; T8_42 = x^8-2*x^6+2*x^5+3*x^4-2*x^3+x^2+4*x+2; T8_41 = x^8-4*x^5+3*x^4+16*x^2+12*x+9; T8_40 = x^8+8*x^6+18*x^4-1; T8_39 = x^8+x^2+1; T8_38 = x^8-4*x^6+28; T8_37 = x^8-4*x^7+28*x^5-21*x^4-70*x^3+189*x^2-173*x+69; T8_36 = x^8-4*x^7+112*x^4+224*x^3-112*x^2-736*x+536; T8_35 = x^8+4*x^2-1; T8_34 = x^8+4*x^7+5*x^6+x^5+x^4-2*x^3-x^2+3*x+2; T8_33 = x^8-8*x^6+18*x^4-16*x^3-40*x^2+8*x+23; T8_32 = x^8-8*x^6+18*x^4+4; T8_31 = x^8+2*x^6+x^4+14; T8_30 = x^8+4*x^6+4*x^4-2; T8_29 = x^8+x^4+2*x^2+1; T8_28 = x^8+4*x^6+2; T8_27 = x^8+5*x^6+3*x^4-6*x^2-4; T8_26 = x^8+2*x^4-2; T8_25 = x^8-x^7+29*x^2+29; T8_24 = x^8-4*x^2+4; T8_23 = x^8-8*x^6+12*x^4-12; T8_22 = x^8+x^4+4; T8_21 = x^8+2*x^4+4*x^2+2; T8_20 = x^8+x^6-6*x^4-x^2+1; T8_19 = x^8+4*x^4+4*x^2+1; T8_18 = x^8+2*x^6+2*x^2+1; T8_17 = x^8+2*x^4+2; T8_16 = x^8+4*x^4+2; T8_15 = x^8+3; T8_14 = x^8+2*x^7+4*x^6-2*x^5+2*x^4-2*x^3+4*x^2+2*x+1; T8_13 = x^8+4*x^6+8*x^4+4; T8_12 = x^8-22*x^6+135*x^4-150*x^2+1; T8_11 = x^8+9; T8_10 = x^8+2*x^6+4*x^4+3*x^2+1; T8_9 = x^8+4*x^4+1; T8_8 = x^8-2; T8_7 = x^8+x^7-28*x^6-7*x^5+70*x^4+7*x^3-28*x^2-x+1; T8_6 = x^8+2; T8_5 = x^8-12*x^6+36*x^4-36*x^2+9; T8_4 = x^8+3*x^4+1; T8_3 = x^8-x^4+1; T8_2 = x^8+1; T8_1 = x^8+x^7-7*x^6-6*x^5+15*x^4+10*x^3-10*x^2-4*x+1; T9_34 = x^9-x-1; T9_33 = x^9+27*x-24; T9_32 = x^9+x^7+2*x^5+4*x^3-x^2+x+1; T9_31 = x^9-2*x^7-2*x^6-x^5-x^4+4*x^3+5*x^2+4*x+1; T9_30 = x^9+2*x^5+4*x^4+4*x^3+4*x^2+x+1; T9_29 = x^9-6*x^6-18*x^5+36*x^4-36*x^3+108*x^2-144*x+48; T9_28 = x^9-2*x^7-2*x^6-x^5-2*x^4+3*x^2+3*x+1; T9_27 = x^9-36*x^6-54*x^5+432*x^3+324*x^2-243*x-1152; T9_26 = x^9-x^7+5*x^6+x^5-2*x^4+4*x^3+3*x^2-x-1; T9_25 = x^9-9*x^6-9*x^4+24*x^3+9*x^2-9*x+1; T9_24 = x^9-2*x^6-2*x^3-2; T9_23 = x^9+9*x^7-60*x^6+72*x^5+354*x^3-495*x^2+2124*x-845; T9_22 = x^9-12*x^6-27*x^5-18*x^4+9*x^3+36*x-8; T9_21 = x^9+3*x^6+3*x^3-2; T9_20 = x^9-2*x^7-2*x^6-2*x^5+x^4+4*x^3+3*x^2+3*x+1; T9_19 = x^9-3*x^8-24*x^5-24*x^4-48*x+16; T9_18 = x^9-2*x^6-2*x^3-1; T9_17 = x^9-17*x^7-6*x^6+87*x^5+47*x^4-143*x^3-69*x^2+72*x+27; T9_16 = x^9-2*x^7+3*x^6+x^5-x^4-2*x^3+x+1; T9_15 = x^9-9*x^7-21*x^6+72*x^5+99*x^4-99*x^3-585*x^2+549*x+166; T9_14 = x^9-30*x^6+45*x^5+126*x^4-240*x^3-90*x^2+405*x+80; T9_13 = x^9-2*x^6-x^3+1; T9_12 = x^9+x^8+x^7+4*x^6-2*x^5-x^4+3*x^3+x^2-1; T9_11 = x^9-x^6+5*x^3+1; T9_10 = x^9-2; T9_9 = x^9-3*x^8+3*x^7-15*x^6+33*x^5-3*x^4+24*x^3+6*x^2-4; T9_8 = x^9-6*x^6+8*x^3-8; T9_7 = x^9-232*x^7-9*x^6+7485*x^5+8631*x^4-3097*x^3-738*x^2+325*x-27; T9_6 = x^9+x^8-32*x^7-84*x^6-14*x^5+112*x^4+84*x^3+4*x^2-8*x-1; T9_5 = x^9+3*x^6+3*x^3-1; T9_4 = x^9+4*x^6+3*x^3-1; T9_3 = x^9+9*x^7-6*x^6+27*x^5-36*x^4+27*x^3-54*x^2-32; T9_2 = x^9-15*x^7+4*x^6+54*x^5-12*x^4-38*x^3+9*x^2+6*x-1; T9_1 = x^9-9*x^7+27*x^5-30*x^3+9*x-1; T10_45 = x^10-x-1; T10_44 = x^10-2*x^8-2*x^7-2*x^3+2*x^2+x-1; T10_43 = x^10-2*x^8-2*x^7-2*x^6-2*x^5-x^4-2*x^3+3*x^2-2*x+1; T10_42 = x^10-32*x^5-200*x^2+256; T10_41 = x^10+2*x^9+4*x^8-x^6+x^4-2*x-1; T10_40 = x^10+x^9-x^8-x^7-2*x^6+2*x^3+3*x^2+x+1; T10_39 = x^10-2*x^8-2*x^7-2*x^6-2*x^5+2*x^4-2*x^3+2*x^2-1; T10_38 = x^10-2*x^8-x^6-2*x^4+2*x^2-2; T10_37 = x^10-2*x^8-2*x^7-x^6-x^5-x^4-2*x^3-2*x^2+1; T10_36 = x^10-2*x^8-x^6+3*x^4-x^2+2; T10_35 = x^10+300*x^6-18*x^5+10000*x^2-200*x+81; T10_34 = x^10-x^8-2*x^6-x^4+x^2-1; T10_33 = x^10-2*x^9+12*x^8-20*x^7+66*x^6-20*x^5+228*x^4+84*x^3+276*x^2+120*x+100; T10_32 = x^10-9*x^8+27*x^6+2*x^5-27*x^4-9*x^3+8*x+1; T10_31 = x^10-1800*x^8-24000*x^7+1422000*x^6+30960000*x^5-462480000*x^4-14500800000*x^3+12996000000*x^2+2414368000000*x-12197187420489; T10_30 = x^10+90*x^6-648*x^5+1080*x^4-2160*x^3+3645*x^2+5400*x+12960; T10_29 = x^10+2*x^8-2*x^6-x^2+2; T10_28 = x^10-10*x^7+10*x^6+36*x^5+50*x^4-10*x^3-1; T10_27 = x^10+3*x^6-2*x^5+x^2+2*x+1; T10_26 = x^10-15*x^8-75*x^6-6*x^5-165*x^4-30*x^3-180*x^2-50*x-90; T10_25 = x^10-2*x^8-2*x^6-x^2-2; T10_24 = x^10+x^8-x^4+3*x^2-1; T10_23 = x^10-2*x^8-x^7+3*x^6+2*x^5-2*x^4-2*x^3+2*x^2+3*x+1; T10_22 = x^10-2*x^8-2*x^7-x^6+x^4-2*x^3+2*x^2-1; T10_21 = x^10+x^6-2*x^5-x^4+3*x^2-2*x+1; T10_20 = x^10-3*x^9+x^8+36*x^7-39*x^6-105*x^5+99*x^4+180*x^3-45*x^2-135*x-45; T10_19 = x^10-10*x^8+35*x^6-2*x^5-50*x^4+10*x^3+25*x^2-10*x+2; T10_18 = x^10+60*x^6-240*x^5+850*x^2-5440*x-1088; T10_17 = x^10-2*x^5-2; T10_16 = x^10+7*x^8+17*x^6-31*x^4-40*x^2+127; T10_15 = x^10-x^8-2*x^6+x^4+3*x^2-1; T10_14 = x^10+x^8-4*x^6-3*x^4+3*x^2+1; T10_13 = x^10-2*x^8-x^7-2*x^6+x^5+3*x^4-2*x^3-x^2+x+1; T10_12 = x^10+2*x^9+3*x^8-x^6-2*x^5-x^4+3*x^2+2*x+1; T10_11 = x^10+10*x^6+25*x^2-8; T10_10 = x^10-2*x^5-4; T10_9 = x^10-50*x^8-100*x^7+865*x^6+4036*x^5+4100*x^4+16400*x^2+13120*x+2624; T10_8 = x^10-4*x^8+2*x^6+5*x^4-2*x^2-1; T10_7 = x^10-2*x^5-15*x^4-10*x^3-15*x^2-5; T10_6 = x^10+5*x^8-33*x^7-67*x^6+132*x^5-375*x^4+1551*x^3+5505*x^2-8987*x+4291; T10_5 = x^10-2; T10_4 = x^10-x^5-1; T10_3 = x^10-x^8-x^6+3*x^4+2*x^2+1; T10_2 = x^10-35*x^6+130*x^4+160; T10_1 = x^10-x^9+x^8-x^7+x^6-x^5+x^4-x^3+x^2-x+1; T11_8 = x^11-x-1; T11_7 = x^11+x^10+2*x^9+2*x^8+x^6-x^5+2*x^4+2*x^3+x^2-1; T11_6 = x^11-x^10-121*x^9+65*x^8+5345*x^7-481*x^6-96739*x^5-23689*x^4+413690*x^3-493810*x^2+26910*x-856170; T11_5 = x^11-898*x^9-3080*x^8+293480*x^7+4185984*x^6-145552352*x^5+1474999680*x^4-16923164544*x^3+177410331648*x^2-709199732736*x+63589515264; T11_4 = x^11-2; T11_3 = x^11-33*x^9+396*x^7-2079*x^5+4455*x^3-2673*x-243; T11_2 = x^11-x^10+5*x^8+8*x^5+6*x^4-x^3+x^2+3*x+1; T11_1 = x^11+x^10-10*x^9-9*x^8+36*x^7+28*x^6-56*x^5-35*x^4+35*x^3+15*x^2-6*x-1; } default(new_galois_format, 1) for (i = 1, 11, test(i)) default(new_galois_format, 0) for (i = 1, 7, test(i)) \\ miscellaneous tests setrand(3);polgalois(x^8-24447832222819253258096747170722821932737551721814653244372785289945042560370884249414339208601850*x^4+24447832222819253258096747170722821932737551721825709426404304862673539625219608619381278993545125*x^2+24447832222819253258096747170722821932737551721825709426404304862673539625219608619381278993545125) polgalois(polzagier(11,0)/polzagier(1,0)) polgalois(x^8-1864259299553450972214799899167226732549697977945716*x^6+331143259018657601105207922631212331088735421305543663274125986698777318014979969*x^4-2225286541902342283500014249183311190477390*x^2+5) polgalois(x^8+162644002617632464507038884216211529274267271168000002) polgalois(x^8+2^2^12) setrand(5);polgalois(x^8-3911867303938246274330482940384509030446487325649036998411199166662010711465575565062431210085563041214249877058238647352476889609806751307308111079477582030570450*x^4-3911867303938246274330482940384509030446487325649036998411199166662010711465575569485025077906938222890835591100732814736005780908137290944485033156820540880540405*x^2+3911867303938246274330482940384509030446487325649036998411199166662010711465575569485025077906938222890835591100732814736005780908137290944485033156820540880540405) setrand(15);polgalois(x^8-1642492255488433999638100059165477791152530*x^4-1642492255488433999640965798385546876573045*x^2+1642492255488433999640965798385546876573045) setrand(4);polgalois(x^8-264*x^6+25410*x^4-1054152*x^2+15856203) setrand(15);polgalois(x^8-3512859249280433994187541000*x^6+1542522513156886787688759313741174472421584953335229070*x^4-60930543678769127629182898645000*x^2+300849025) setrand(1); polgalois(x^11+627*x^4-584) pari-2.17.2/src/test/in/round0000644000175000017500000000052014676526175014432 0ustar billbillround((1e-40 + x) / (1e-39 + x)) v=[1,1.6,-4/3,Mod(1,3),quadgen(5),Mod(4/3+x,x^2+1/2),x,4/3+x/3+O(x^2),1/x,[4/3,2],matid(2)/3,""]; test(f)= for(i=1,#v, print(iferr(f(v[i]),E,E))); test(ceil) test(floor) test(frac) test(round) round(0,&E); test(x->[round(x,&e), if(e==E,-oo,e)]) test(truncate) test(x->[truncate(x,&e), if(e==E,-oo,e)]) pari-2.17.2/src/test/in/bnr0000644000175000017500000001170714676526175014075 0ustar billbilldefault(parisize,"160M"); K=bnfinit(x^3-x-1); subgrouplist(bnrinit(K,10)) K=bnrinit(K,20); default(realprecision,77); nfnewprec(K); default(realprecision,38); subgrouplist(K) subgrouplist(K, 2) subgrouplist(K, 2, 1) bnrconductor(bnfinit(K),4,Mat(3)) subgrouplist(bnrinit(bnfinit(x),22)) Qi = bnfinit(x^2+1); bnrL1(bnrinit(Qi,10),1); bnrisconductor(bnrinit(Qi,x-5),[1]) setrand(5);bnrL1(bnrinit(bnfinit(y^2+6),1)); bnrL1(bnrinit(bnfinit(x),[5,[1]])); \\ #1399 bnrdisc(bnfinit(y^2+1), 12) setrand(1);bnf=bnfinit(x^2-x-57); test(m)= { print(bnrisconductor(bnf,m), ", ", bnrclassno(bnf,m), ", ", bnrdisc(bnf,m)); } test([[25,13;0,1],[1,1]]) test([[25,13;0,1],[1,0]]) test([[5,3;0,1],[1,0]]) test([5,3;0,1]) m=[idealfactor(bnf,[5,3;0,1]),[1,0]]; H=Mat(2); bnr=bnrinit(bnf, idealstar(bnf,m,2)); f=[bnrclassno,bnrdisc,bnrconductor]; { for (i=1,#f, print(f[i](bnr)); print(f[i](bnr,H)); print(f[i](bnf,m)); print(f[i](bnf,m,H)); ) } bnrdisc(bnf,m,H,1) bnrdisc(bnf,m,H,2) bnrdisc(bnf,m,H,3) bnrdisc(bnf,[5,3;0,1],H,2) bnrdisc(bnf,[5,3;0,1],H,3) bnrclassno(bnf, idealprimedec(bnf,5)[1]) bnr=bnrinit(bnf,[7,[1,1]]); bnrclassno(bnf,[7,Vecsmall([1,2])]) bnrclassno(bnf,[7,Vecsmall([1])]) bnrclassno(bnf,[7,Vecsmall([2])]) bnrclassno(bnf,[7,Vecsmall([])]) bnrclassno(bnf,[7,Vecsmall([1,2,3])]) bnrrootnumber(bnr, [2,1]) bnrrootnumber(bnr, [0,0]) bnrconductor(bnr,[0,0]) chi=[1,0]; bnrconductor(bnr,chi) charorder(bnf,[1]) chareval(bnf,[1], idealprimedec(bnf,3)[1]) charorder(bnr,chi) chareval(bnr,chi,2) chareval(bnr,chi,1/7) chareval(bnr,chi,x+1) chareval(1,chi,1) L=idealprimedec(bnf,3); bnr=bnrinit(bnf,[L[1],[1,1]]); chi=[3]; chareval(bnr,chi,1) chareval(bnr,chi,L[1].gen[2]) chareval(bnr,chi,L[2].gen[2]) bnr=bnrinit(bnfinit(x^2-97),1); bnrrootnumber(bnr,[]) narrow(T)=bnfnarrow(bnfinit(T)); narrow(x^2-460) narrow(x^6-x^5-12*x^4+5*x^3+23*x^2-6*x-9) narrow(x^2-9004) narrow(x^2-7980) \\#1804 K=bnfinit(y^2-5); bnr = bnrinit(K,[1,[1,1]]); bnrdisc(bnr) bnrdisc(bnr,,,1) bnrdisc(bnr,,,2) bnrdisc(K,[1,[1,0]],,2) bnrdisc(K,[1,[0,0]],,2) ideallog(K,1/2,idealstar(K,[1,[1,1]])) setrand(1); F = bnfinit(x^3-3); f = idealmul(F, idealprimedec(F,3)[1], 5); bnr = bnrinit(F, [f, [1]]); C = bnr.cyc; forvec(c = vector(#C,i,[0,C[i]-1]), print(bnrrootnumber(bnr,c))) bnf=bnfinit(x^2+69); id = [9,0;0,3]; bnrinit(bnf,id,1).clgp bnrinit(bnf,1,1,5).clgp bnrinit(bnf,1,0,5).clgp bnf=bnfinit(x^2-x+6);bnr=bnrinit(bnf,[29,18;0,1]); bnrisprincipal(bnr,1) bnrinit(bnf,idealfactor(bnf,1)).no \\ #1890 \\ #2275 bnr=bnrinit(bnfinit(quadpoly(1546508,y)),9); bnrisprincipal(bnr,idealprimedec(bnr,43)[1]); bnf=bnfinit(x^2-486); P2 = idealprimedec(bnf,2)[1]; P3 = idealprimedec(bnf,3)[1]; bnrinit(bnf, [[P2,1;P3,15],[1,1]], 1); \\ slow p = 1932251269128214818974844517133; N = p*5; bnf=bnfinit('y); bnr = bnrinit(bnf,N); pol = bnrclassfield(bnr,[2,0;0,1],1); rnfnormgroup(bnr,pol) \\ slow p=277619787333362637441898246271; bnf=bnfinit(a^3 - 6544*a - 7375129,1); bnrinit(bnf,p,,2).cyc \\ slow bnf=bnfinit(a^2+3321607); bnr=bnrinit(bnf,1,,3); bnr.cyc bnrisprincipal(bnr,idealprimedec(bnr,13)[1],0) bnr=bnrinit(bnf,3,,3); bnr.cyc bnrisprincipal(bnr,idealprimedec(bnr,13)[1],0) \\ wrong relations => bug in rnfkummer setrand(1); bnr=bnrinit(bnfinit(y^4-y^3+16*y^2-16*y+61),5,,5); #bnrclassfield(bnr,5) \\ wrong generators => bug in rnfkummer setrand(1); bnr=bnrinit(bnfinit(y^4+30*y^2+18),5); #bnrclassfield(bnr,5) K=bnfinit(x^2-30); bnr=bnrinit(K,[4,[1,1]]); P=idealprimedec(K,3)[1]; bnrisprincipal(bnr,P,4) bnrisprincipal(bnr,P,1) bnrisprincipal(bnr,P,0) bnr = bnrinit(bnr,bnr.mod,1); bnrisprincipal(bnr,P,4) bnrisprincipal(bnr,P,1) bnrisprincipal(bnr,P,0) Q = bnfinit(y); bnr1 = bnrinit(Q, [7, [1]]); bnr2 = bnrinit(Q, [13, [1]]); H1 = Mat(2); H2 = Mat(2); [bnr,H] = bnrcompositum([bnr1, H1], [bnr2,H2]); bnrclassfield(bnr,H) \\ #2474 bnf=bnfinit(x^10-5*x^9-1917*x^8-220484*x^7+1861684*x^6+179215404*x^5+7592279335*x^4-103008837215*x^3-4729077708495*x^2-100465756135620*x+46969787343312,1); c=-87960936842121514526026936210077449/20478587125920981732510068909405420355936908475*x^9 + 20694070332091021276793475810169961563/163828697007367853860080551275243362847495267800*x^8 + 722596578529617191421551065927082530211/81914348503683926930040275637621681423747633900*x^7 + 925677949019226006362057400402541633039/1365239141728065448834004593960361357062460565*x^6 - 2499909911735778294890847390465998764973849/81914348503683926930040275637621681423747633900*x^5 - 56665720721729079138715368953267342193693143/81914348503683926930040275637621681423747633900*x^4 - 98200368131235052206306228461784391914157537/20478587125920981732510068909405420355936908475*x^3 + 46102732902489970280764495888340637157740495173/54609565669122617953360183758414454282498422600*x^2 + 70266180209134341308704477651177994629370824031/6826195708640327244170022969801806785312302825*x - 25791090363471214251680822888336444894841557666/758466189848925249352224774422422976145811425; m=idealhnf(bnf,3,c); bnr=bnrinit(bnf,[m,[1,0]]); id=idealhnf(bnf, 97, x^2 - 43*x - 414); bnrisprincipal(bnr,id,0) pari-2.17.2/src/test/in/factor0000644000175000017500000000455514676526175014575 0ustar billbillfactor(x^2+I) factor(x^2-1.) factor(x^2+I+1.) factor(x^2+Mod(1,5)) factor(x^2+Mod(1,3)+I) factor(x^2+Mod(1,5)*I) factor(x^2+(1+O(5))*I) factor(x^2+(1+O(3))+I) factor(x^2+(1+O(5))) factor(x^2+quadgen(-3)) factor(x^2+quadgen(-3)*Mod(1,3)) factor(x^2+quadgen(-3)*Mod(1,5)) factor(x^2+quadgen(-3)*(1+O(5))) factor(x^2+quadgen(-3)*(1+O(3))) factor(x^2+Mod(y,y^2+1)) factor(x^2+Mod(y*Mod(1,3),y^2+1)) factor(x^2+Mod(y*Mod(1,5),y^2+1)) factor(x^2+Mod(y*(1+O(3)),y^2+1)) factor(5/2 + I/3) factor(5^4 + 5^4*I) factor(5 + I) factor(15+3*I) factor(4+4*I) factor((3+4*I)/25) factor(15,3) q=31271192761826143388782348951/31274945109847936339856761591; factor(q,2) factor(q,500100) factor(257377849,100) factor((x-2.)*(x^2+1)) factor((x+1)^2/(x^2-4)) factor((x^2+1)/x) factor(x^2+a^3*x-Mod(6,a^2-2)) factor(83833759205078410,131) factor(3856811226351960485865701609925634373222448596241780085459117390,131) factor(-455688433941833690722771369629,0) p1 = (289*x^4 + 1)^8; p2 = (19*x^2 + 1)^16; factor(p1) factor(p2) factor(x^2-1/y^2) factor(y/x) factor((x^3+y^3)^2*(x^4+y^4)) factor(x^3+y^3) factor((x^7-y^7)*Mod(1,7)) factor((x^7-y)*Mod(1,7)) factor(x^5+y*x^4+y^2*x^3+(y^2-1)*x^2+(y^3-y)*x+(y^4-y^2)) factor((x^2+y^2) * Mod(1,13)) factor(x^3+I*y*x^2+(y^2+I)*x+(I*y^3-y)) factor((x^3+y^3+z^3-3*x*y*z)*Mod(1,7)) centerlift(factor((x^3+y^3+1-3*x*y)*(1+O(7^3)))) factor(x*y*(x+y)) E(n)=ellinit([2,1-n^2,(1-n^2)*(1+n),0,0]); factor(elldivpol(ellinit(E(t)),4)) factor(0.*x^2+x+1) factor(0.*x^2+x+I) factor(x^2+1, I) factor(x^2-1, 1.) factor(x^2+I+1, 1.) factor(x^2+1,Mod(1,5)) factor(x^2+Mod(1,3),I) factor(x^2+1,O(5)) factor(x^2+O(5^2)) factor(x^2+(1+O(3)),I) factor(x^2+x+1,quadgen(-3)) factor(x^2+quadgen(-3),Mod(1,3)) factor(x^2+quadgen(-3),Mod(1,5)) factor(x^2+quadgen(-3),O(5)) factor(x^2+quadgen(-3),O(3)) factor(x^2+y,Mod(1,y^2+1)) factor(x^2+Mod(y,y^2+1),Mod(1,3)) factor(x^2+Mod(y,y^2+1),Mod(1,5)) factor(x^2+Mod(y,y^2+1),O(3)) factor(5/2,I) factor(x^2+a^3*x-6,Mod(1,a^2-2)) factor((x*y+1)*(x*y+2),Mod(1,2)) factor((x*y+1)*x*(y^2+y+1)*(z^3+z+1),Mod(1,2)) factor(1/(x^5+3*y*x^4+3*y^2*x^3+y^3*x^2)) factor((x-1)*(x-y)^2) factor(x^3+y^3,quadgen(-3)) factor(x^7-y^7,Mod(1,7)) factor(x^7-y,Mod(1,7)) factor(x^2+y^2,Mod(1,13)) factor(x^3+y^3+z^3-3*x*y*z,Mod(1,7)) sum(i=1,10,setrand(i);polisirreducible((Mod(1,2)*((t^2+1)*x^4+(t^4+1)*x^2+1)))) lift(factor(Mod(1,2)*x^15+(Mod(1,2)*a^3+Mod(1,2)*a^2+Mod(1,2)*a+Mod(1,2))*x^13)) pari-2.17.2/src/test/in/iterator0000644000175000017500000000645614676526175015152 0ustar billbillN = 1<<64; for(a=N-2, N+2, print(a)) for(a=-N-2, -N+2, print(a)) for(n=2,oo,if(n>10,break);print(n)) forprime(p=2^32-50,2^32+30,print(p)) forprime(p=2^63,2^63+500,print(p)) forprime(p=2^64-70,2^64+50,print(p)) forprime(n=2,,if(n>10,break);print(n)) /*backward compat */ forprime(n=2,oo,if(n>10,break);print(n)) forprime(n=2^100,,if(n>2^100+400,break);print(n)) forprime(n=2^100,oo,if(n>2^100+400,break);print(n)) forprimestep(a=1,10,Mod(2,4),print(a)) forprimestep(a=3,10,Mod(2,4),print(a)) forprimestep(a=0,1,Mod(2,4),print(a)) forprimestep(a=1,10,Mod(3,6),print(a)) forprimestep(p=2^32-50,2^32+30,Mod(1,3),print(p)) forprimestep(p=2^64-70,2^64+50,Mod(2,3), print(p)) forprimestep(n=2,,5,if(n>20,break);print(n)) /*backward compat */ forprimestep(n=2,oo,5,if(n>20,break);print(n)) forprimestep(n=2^100,,Mod(2,3),if(n>2^100+400,break);print(n)) forprimestep(n=2^100,oo,Mod(2,3),if(n>2^100+400,break);print(n)) p=18446744073709551533; forprimestep(i=p,p+400,10,print(i)) q=10^8+7; forprimestep(p=q-1,21*q,q, print1(p" ")) \\ #2439 \\ #2531 my(n=8);forprimestep(p=nextprime(10^8),10^8+10^n,10^n,print(p)) my(n=9);forprimestep(p=nextprime(10^8),10^8+10^n,10^n,print(p)) my(p0=1500301459763,step=4907262314955);forprimestep(p=p0-step,2e14,step,print(p)) forprimestep(p=2,oo,2^64,print(p)) forprimestep(p=3,oo,Mod(0,5),print(p)) for(a=0.5,3,print(a)) for(a=1,10, print(a+=2)) forstep(a=5,1,-2,print1(a," ")) forstep(a=1,10,[1,3],print1(a," ")) forstep(a=1,10,Mod(2,3),print1(a," ")) forstep(a=.1,17,Mod(2,5),print(a)) forstep(a=1/10,17,Mod(2,5),print(a)) my(s=1,a=0);forstep(i=1,20,s,s++;a+=i);a forprime(p=2,10,p=4) foreach([],p,print(p)); foreach(List(),p,print(p)); foreach(Mat(),p,print(p)); foreach(primes([1,100]),p,print1(" ",p));print() foreach(List([1..10]),p,print1(" ",p));print() foreach(matid(3),p,print1(" ",p));print() forcomposite(a=2,4,print(a)) forcomposite(a=10,10,print(a)) forcomposite(a=2,10,print(a)) forcomposite(a=5,11,print(a)) forcomposite(a=6,12,print(a)) forcomposite(a=6,,print(a); if (a>8, break)) forcomposite(a=6,oo,print(a); if(a>8,break)) forcomposite(a=6,12,print(a); a=1) forcomposite(a=2,3,print(a)) { for(i=1,4,for(j=5,8, if ([i,j]==[2,6], next, [i,j]==[3,6], next(2), [i,j]==[4,6], next(3)); print([i,j]))) } forfactored(N=10^5,10^5+10,print(N)) c=0;forfactored(N=1,10^6, my([n,f]=N); if (factorback(f)!=n || c++!=n,error(N))) c=-10^6-1;forfactored(N=-10^6,-1, my([n,f]=N); if (factorback(f)!=n || c++!=n,error(N))) forfactored(x=-3,-1,print(x)) forfactored(x=-3,-1, if (x[1]==-2,break); print(x)) forfactored(x=-3,0,print(x)) forfactored(x=-3,0, if (x[1]==-1, break); print(x)) forfactored(x=-3,0, if (x[1]==0, break); print(x)) forfactored(x=-3,2,print(x)) forfactored(x=-3,2, if (x[1]==-1, break);print(x)) forfactored(x=-3,2, if (x[1]==0, break);print(x)) forfactored(x=-3,2, if (x[1]==1, break);print(x)) forfactored(x=0,2,print(x)) forfactored(x=0,2, if (x[1]==0, break);print(x)) forfactored(x=0,2, if (x[1]==1, break);print(x)) forfactored(x=1,-1,print(x)) forfactored(n=223092868, 223092871, print(n) ) forsquarefree(N=-5,5,print(N)) forsquarefree(N=10^5,10^5+10,print(N)) forsquarefree(N=-10^5-10,-10^5,print(N)) c=0;forsquarefree(N=1,10^6, my([n,f]=N); if (factorback(f)!=n,error(N)); c++);c c=0;forsquarefree(N=-10^6,-1, my([n,f]=N); if (factorback(f)!=n,error(N));c++);c \\ errors foreach(x^2+1,x,) pari-2.17.2/src/test/in/polmod0000644000175000017500000000212114567450071014562 0ustar billbilltest() = { print(a*b); print(a/b); print(sqr(a)); print(a^-1); print(a^3); print(a^0); } T=2*x^2 + x + 1; a = Mod(x+1/2, T); b = Mod(x/3+1, T); test(); T=2*x^3 + x + 1; a = Mod(x^2+x+1/2, T); b = Mod(x^2+x/3+1, T); test(); modp(p) = { t = T*Mod(1,p); a = Mod((x^2+x+3) * Mod(1,p), t); b = Mod((3*x^2+2*x+5) * Mod(1,p), t); } modp(17); test(); modp(18446744073709551629); test(); (Mod(1/2, 't)*'x + Mod(1, 't)) ^ 2 Mod(Mod(x,x^2+1),x) Mod(Mod(0,2),y^0)*x*x Mod(y,x) Mod(1/y,x) Mod(O(y),x) Mod(x,y) Mod(1/x,y) Mod(1+O(y),y) Mod(1+O(y),y+1) Mod(1,7*x^0) Mod(2,13)+Mod(0,7*x^0) modreverse(Mod(0,Pol(1))) modreverse(Mod(1,x+1)) norm(Mod(2^65,3*x+1)) norm(Mod('a,3*x+1)) Mat(1/2*x) * Mat(Mod(1,x^2-2)) (Mod(5,7)*x+Mod(y^0,7*y+1))*x V=factorback(primes([2^31,2^31+1000])); (Mod((x+1)*(x^3+3*x+1)+V,(x+1)*(x^3+x+1))^-1)^-1 V=factorback(primes([2^63,2^63+1000])); (Mod((x+1)*(x^3+3*x+1)+V,(x+1)*(x^3+x+1))^-1)^-1 \\#1743 pi=Mod(z^7-1,z^24 +763670323290*z^16+335841304485*z^8+1); liftall(1/(pi*(1+O(2^20)))) \\#1748 pi=Mod(O(7^12)*z^8+z^7-1,z^24 +763670323290*z^16+335841304485*z^8+1); 1/pi; pari-2.17.2/src/test/in/galpol0000644000175000017500000000115414567450071014553 0ustar billbill\\ package: galpol galoisgetpol(8) for(i=1,5,printsep(":",galoisgetname(8,i),galoisgetgroup(8,i),galoisgetpol(8,i))) for(i=1,5,print(galoisgetpol(8,i,2))) test(n,k)= if(galoisidentify(galoisinit(galoisgetpol(n,k)[1])) != [n,k], error([n,k])); test(8,3) test(18,5) test(27,3) test(45,2) test(30,4) test(32,4) test(32,13) test(32,30) test(32,32) test(36,9) test(42,2) test(48,12) test(64,3) test(64,14) test(64,16) test(64,48) test(64,51) test(64,70) test(64,68) test(64,80) test(64,44) galoisidentify(galoisinit(polcyclo(390))) \\ Errors, keep at end of file galoisgetpol(8,6) galoisgetpol(3,1,3) galoisgetpol(3,1,2) pari-2.17.2/src/test/in/qfcvp0000644000175000017500000000206214676526175014425 0ustar billbilltest_cvp(A, target, bound, sols)= { r = qfcvp(A, target, bound); V = r[3]; if(r[1] != sols, print("ERROR, wrong number of close vectors")); for(i=1, r[1], if(bound > 0 && qfeval(A, V[,i]-target) > bound * (1+0.001), print("ERROR, result too far away."))); return r; }; M = [2,1;1,2]; t = [0.5,0.5]~; test_cvp(M, t, 0, 2); test_cvp(M, t, 0.5, 2); test_cvp(M, t, 1.5, 4); Q=[8,4,4,4,4,4,4,4,4,4,4,4;4,8,4,4,4,4,4,4,4,4,4,4;4,4,8,0,0,0,3,0,0,0,0,0;4,4,0 ,8,4,4,1,4,4,4,4,4;4,4,0,4,8,4,4,4,4,4,4,4;4,4,0,4,4,8,4,4,4,4,4,4;4,4,3,1,4,4,8 ,4,1,1,1,1;4,4,0,4,4,4,4,8,4,4,4,4;4,4,0,4,4,4,1,4,8,4,4,4;4,4,0,4,4,4,1,4,4,8,4 ,4;4,4,0,4,4,4,1,4,4,4,8,4;4,4,0,4,4,4,1,4,4,4,4,8]; t = [0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5]~; test_cvp(Q, t, 0, 6); test_cvp(Q, t, 4, 6); qfcvp(Q, t~, 4); \\ test transpose input R = Mat([1]); test_cvp(R, [3/2]~, 0, 2); test_cvp(R, [1.6]~, 0, 1); test_cvp(R, [1.5]~, 2.25, 4); test_cvp(R, [1.51]~, 2.25, 3); test_cvp(Mat(), []~, 2.25, 0); print("Cases that should fail:") qfcvp(Mat(), [1.5]~, 2.25); qfcvp(Q, [1.5, 5]~, 2.25); pari-2.17.2/src/test/in/err0000644000175000017500000001325414760123736014071 0ustar billbillf(x) = 1/x; g(N) = for(i = -N, N, f(i)); g(10) print(); f=matsolve; f(Mat(0), Col(1)) print(); (matsolve)(Mat(0), Col(1)) print(); a.foo=1/(1+a^2); g(x)=[x.foo]; g(I) print(); (x->1/x)(0) print(); ecm(N,t,B)= { for(a=1,t, iferr( my(E=ellinit([0,0,0,a,1]*Mod(1,N))); ellmul(E,[0,1]*Mod(1,N),B), err,if(errname(err)=="e_INV",return(gcd(lift(component(err,2)),N)) ,error(err)))); } ecm(2^64+1,10,200!) ecm2(N,t,B)= { for(a=1,t, iferr( my(E=ellinit([0,0,0,a,1]*Mod(1,N))); ellmul(E,[0,1]*Mod(1,N),B), err,return(gcd(lift(component(err,2)),N)) ,errname(err)=="e_INV")); } ecm2(2^64+1,10,200!) rev(A) = my(B=Ser(A)); serreverse(B); iferr(rev([0,0,0,2,2,4,8,4,16,12]),E,0); \\ e_COPRIME T=t^2-2;p=2;A=x^2+1;B=[x+t,x+t];r=polhensellift(A,B,[p,T],6) \\ e_DIM / e_TYPE M = matid(2); M[,1] = 1 M[,3] = 1 M[,1] = [1,2] M[,1] = [1,2,3]~ M[1,] = 1 M[3,] = 1 M[1,] = [1,2]~ M[1,] = [1,2,3] [;][1,] [;][,1] 1[1] issquare(1,&v[1]) 1[1,1] 1[,1] issquare(1,&v[,1]) 1[1,] issquare(1,&v[1,]) v=Vecsmall([1]); v[2] = 1 v[1] = Pi v[1] = 2^64 v[Pi] = 1 \\ RgM_check_ZM M = [1.,0;0,1]; qflll(M,1) \\ RgV_check_ZV addprimes(1.) \\e_MODULUS nfalgtobasis(nfinit(t^3-2),Mod(t,t^2+1)) \\e_DIM vector(-1,i,0) vectorv(-1,i,0) vectorsmall(-1,i,0) matrix(-1,1,i,j,0) matrix(1,-1,i,j,0) next(-1) break(-1) v[-1] v[#v+1] subst(x,1,0) exp(1e40) exp(-1e40) exp(1/x) cos(1/x) sin(1/x) tan(1/x) cotan(1/x) atan(1/x) asin(1/x) acos(1/x) asinh(1/x) acosh(1/x) atanh(1/x) lngamma(x) besselj(2,1/x) besseljh(2,1/x) besselk(2,1/x) besselk(1/3,O(x)) besseln(2,1/x) besseln(1/3,O(x)) polylog(2,1/x) sqrt(x) sqrt(2+O(2^2)) sqrtn(x,3) sqrtn(2+O(2^2),3) log(x) log(0) abs(x+O(x^2)) real(Vecsmall([])) imag(Vecsmall([])) vecmax(Vecsmall([])) vecmax([]) vecmax([], &i) vecmin(Vecsmall([])) vecmin([]) vecmmin([], &i) vecmax(matrix(0,2)) L=List(); listput(L, x, -1) listinsert(L,x,-1) listpop(L) ellj(Mod(1,2)) ellj(Qfb(1,1,1)) eta(1+O(2)) eta(1/x) K = nfinit(y^2+1); idealhnf(K, Qfb(1,1,1)) idealfactor(K, [;]) idealval(K, [;], idealprimedec(K,2)[1]); idealdiv(K,2,0, 1); valuation(Pi,2) x^Pi x^x 0^0. agm([],[]) sin(1/2+O(2^1)) cos(1/9+O(3^1)) exp(1/9+O(3^1)) G=[[Vecsmall([6,11,14,16,17,1,21,24,26,27,2,29,30,3,31,4,5,34,36,37,7,39,40,8,41,9,10,42,12,13,15,44,45,18,46,19,20,47,22,23,25,28,48,32,33,35,38,43]),Vecsmall([5,10,13,15,1,17,20,23,25,2,27,28,3,30,4,31,6,33,35,7,37,38,8,40,9,41,11,12,42,14,16,43,18,45,19,46,21,22,47,24,26,29,32,48,34,36,39,44]),Vecsmall([15,25,28,1,4,31,35,38,2,9,41,3,12,42,5,6,16,43,7,19,46,8,22,47,10,11,26,13,14,29,17,18,32,48,20,21,36,23,24,39,27,30,33,34,44,37,40,45]),Vecsmall([30,40,1,42,14,13,45,2,47,24,23,4,5,6,29,28,3,7,48,34,33,9,10,11,39,38,8,15,16,17,12,19,20,21,44,43,18,25,26,27,22,31,35,36,37,32,41,46]),Vecsmall([7,1,44,18,37,20,2,29,3,17,5,35,43,48,45,33,21,39,8,27,10,15,28,42,30,13,6,36,19,32,34,25,38,47,40,23,11,16,4,12,14,46,26,9,22,24,31,41])],Vecsmall([2,2,2,2,3])]; galoissubgroups(G) bnrstark(bnrinit(bnfinit(y^2+1),2)) bnrstark(bnrinit(bnfinit(y^2-2),[4,[1,1]])) quadray(-16,1) quadray(bnfinit(x^3-2),1) galoissubcyclo(-1) galoissubcyclo(6,Mod(1,3)) galoissubcyclo(6,[;]) galoissubcyclo(6,Mat(1)) galoissubcyclo(znstar(5),matid(2)) galoissubcyclo( [3, [3], [3]], Mat(3)) galoissubcyclo(bnrinit(bnfinit(y^2+1),1), 2) polsubcyclo(-1,2); polsubcyclo(2,-1); random(0) znprimroot(0) sqrtint(-1) sqrtnint(-1,2) sqrtnint(2,-2) znprimroot(8) polroots(x^2+Mod(1,2)) polroots(0) polroots(Mod(1,2)) polrootsmod(x,x) prime(-2) addprimes(-1) padicappr(x^2+1+O(3^5), 1+O(5)) factorpadic(x^2+1,2,-1) polrootspadic(x^2+1,2,-1) ellinit([1+O(3),1+O(5)]) ellwp([1,I],I) ellsigma([1,I],x,1) ellsigma([1,I],1,1) E=ellinit([1,1]); ellap(E) ellap(E,1) ellap(E,'x) ellissupersingular(x,1) elltaniyama(E,-1) ellheight(E,[2,2]) ellheight(E,,[2,2]) Qfb(0,0,0) quadpoly(2) qfbprimeform(2,5) qfbcomp(Qfb(1,1,1),Qfb(1,0,2)) \\qfbcompraw(Qfb(21,1,2),Qfb(112,0,2)) galoisinit(x^2) galoisinit(2*x) ellL1(1,-1) ellheegner(ellinit([0,-1,1,-10,-20])) ellheegner(ellinit([0,0,1,-7,6])) substpol(x+O(x^2),x^3,x) intformal(1/(x^2+1)) component(x,-1) component(O(x),2) component(Vecsmall([]),1) component(x->x,6) polcoef(O(x),2) polcoef(x+O(x^2),2) polcoef([],2) matcompanion(0*x) matrixqz(Mat([1,2])) matrixqz(Mat(0)) vecextract([1],[-1]); vecextract([1],[2]); idealfrobenius(K,galoisinit(K),idealprimedec(K,2)[1]) nfisincl(x^2,x^2+1) polcompositum(x^2,x) rnfdedekind(K, x^2+x-1/3) hilbert(Mod(1,2),1) hilbert(Mod(1,3),Mod(1,5)) hilbert(Mod(1,3),2,0) znorder(0) znorder(Mod(2,4)) contfrac(1e100) contfrac(1.,[1],10) contfrac(1,,-1) contfracpnqn(matrix(3,1)); divisors(1/2) idealstar(K,0) idealstar(K,1/2) idealaddtoone(K,[[;]]) idealdiv(K,1,2,1) idealred(K,matid(2),[]) idealtwoelt(K,matid(2),1/2) rnf=rnfinit(K,x^2-y); rnfeltdown(rnf, x) matid(-1) polinterpolate([1,1],[2,3],Pi) modreverse(Mod(-x^3+9*x,x^4-10*x^2+1)) rnfnormgroup(bnrinit(bnfinit(K),9), x^3-2) concat([1,2],[3,4]~) concat([]) concat(List()) mathnfmod([1;2],2) removeprimes(2) forstep(a=1,2,0,) e=ellinit([1,1+O(31^2)]); e.omega e.eta e.area e=ellinit([0,1]); e.tate ellorder(e, [0,0]*Mod(1,2)) thue(x*(x^3-2),0); direuler(p=2, 10, 2/(1-p*X)) solve(x=0,1,x^2+1) warning(1) iferr(1/0,E,1,errname(E)=="e_DOMAIN") iferr(1/0,E,return(4)) iferr(1/0,E,1,break()) \\ backward compatibility. Eventually remove inv(x) = trap (e_INV, INFINITY, 1/x) inv(2) inv(0) trap (e_INV, INFINITY, log(0)) a=1; notafunc('a) a n=1<<10000; znlog(Mod(1,n),Mod(1,n+1)) Mod(0,n)^(-1) a=Mod(1,7)*x+y; b=Mod(1,7*y^2+7)*x+4; a*b a%b (a*x^2+b)^2 M=[Mod(1,7),1;0,Mod(x,7*x^2+7)]; matrank(M) matimage(M) matker(M); default(plothsizes,"[") default(plothsizes,"1") default(plothsizes,"[2,") default(plothsizes,"[2,]") default(plothsizes,"[2,3]") \\ succeeds Pol(O(17^-1),v0)/Pol([Mod(9,23),O(23^-3)],v0) \\ #2393 pari-2.17.2/src/test/in/bnrclassfield0000644000175000017500000002507014676526175016125 0ustar billbilldefault(parisize,"44M"); \\ overflows 42M count = 0; nfisprobisom(P,Q, n = 50)= { forprime (p = 2,oo, my(FP = factormod(P,p,1)); if (vecmax(FP[,2]) > 1, next()); my(FQ = factormod(Q,p,1)); if (vecmax(FQ[,2]) > 1, next()); if(FP[,1] != FQ[,1], return(0)); n--; if(!n,return(1))); } check(K,f,sol,flag, expo = 32)= { if (!sol || poldegree(f) != poldegree(sol), return(0)); if (exponent(f) > exponent(sol) + expo, error(exponent(f)," > ",exponent(sol)," + ",expo)); if (flag != 2, sol = rnfequation(K,sol); f = rnfequation(K,f)); nfisprobisom(sol,f); } checkvec(K,f,~sol,flag, expo = 32)= { for (j=1,#sol, if (check(K,f,sol[j],flag,expo), sol[j]=0; return(1))); return(0); } do(t, flag = 0, sol = 0, expo = 32) = { my(f = 1, H = 0); if (type(t) == "t_VEC", if (#t == 3, [t,f,H] = t, [t,f] = t)); my(K = bnfinit(t), T); setrand(1); print(count++); T = liftpol(bnrclassfield(bnrinit(K,f), H, flag)); if (!sol, return(T)); if (type(T) != "t_VEC", return(check(K,T,sol,flag, expo))); [checkvec(K,t,~sol,flag, expo) | t<-T]; } do(y^2+6) \\1 do(y^2+30) do(y^2-y+10) do(y^2-y+22) s=x^6+(2*y-4)*x^5+(-2*y-49)*x^4+(-40*y+38)*x^3+(-22*y+456)*x^2+(168*y+288)*x+(180*y-611); do(y^2-y+22,1,s) \\5 s=[x^8+(-2*y+2)*x^7+(-y-36)*x^6+(12*y-16)*x^5+(3*y+21)*x^4+(6*y+16)*x^3+(-4*y+12)*x^2+(2*y-18)*x+(2*y-7)]; do(y^2-y+24,,s) s=[x^2+(-y-2),x^5+(101464750*y+192858990)*x^3+(-108719876266494185*y+152155420535969655)*x^2+(2694338662186141731750*y-14807033089517485684890)*x+(18862914098615255705031752813*y-410373474000278666208453327219)]; do(y^2-y+30,,s) s=x^10+(-2*y-4)*x^9+(4*y-50)*x^8+(40*y-36)*x^7+(56*y+653)*x^6+(-242*y+1802)*x^5+(-818*y-408)*x^4+(-692*y-8486)*x^3+(1302*y-11876)*x^2+(3188*y-1340)*x+(2420*y+7577); do(y^2-y+30,1,s) s=[x^9-24*x^7+(-2*y+1)*x^6+495*x^5+(12*y-6)*x^4-30*x^3+(-18*y+9)*x^2+18*x+(2*y-1)]; do(y^2-y+50,,s) s=[x^2+3,x^2+7,x^3-3*x+9]; do(y^2-y+58,,s) \\10 s=x^12-2*x^11+(-4*y-5)*x^10+(8*y-28)*x^9+(9*y-308)*x^8+(100*y+482)*x^7+(-132*y+429)*x^6+(1082*y-294)*x^5+(-1617*y+15083)*x^4+(-1770*y+18798)*x^3+(-2764*y-60684)*x^2+(15996*y-16436)*x+(-2045*y-11529); do(y^2-y+58,1,s) s=x^16-6*x^15+27*x^14-78*x^13+(4*y+142)*x^12+240*x^11+(-36*y+297)*x^10+(-48*y-564)*x^9-3143*x^8+(96*y-1224)*x^7+(144*y+1044)*x^6+1920*x^5+(-64*y+2336)*x^4-2496*x^3+1728*x^2-768*x+256; do(y^2-y+595,1,s) s=[x^3+15*x+(10*y-5),x^8+(-2*y+5)*x^6+(2*y-6)*x^5+(-5*y-75)*x^4+(-54*y-258)*x^3+(185*y-711)*x^2+(-118*y-66)*x+(72*y+305)]; do(y^2-y+174,,s) do(y^2-y+1007) do(y^2+105) \\15 s=x^27-13*x^26+87*x^25+(2*y-480)*x^24+(-17*y+2492)*x^23+(71*y-11474)*x^22+(-301*y+44475)*x^21+(1432*y-154355)*x^20+(-5878*y+491504)*x^19+(19312*y-1346275)*x^18+(-60553*y+3140529)*x^17+(168655*y-6741496)*x^16+(-371696*y+13501864)*x^15+(678767*y-24741734)*x^14+(-1082635*y+46288449)*x^13+(1183374*y-97233723)*x^12+(529638*y+197106251)*x^11+(-6132942*y-318835894)*x^10+(15301717*y+368696308)*x^9+(-23543559*y-267144050)*x^8+(25723793*y+63312848)*x^7+(-21031976*y+89347006)*x^6+(13238860*y-108009320)*x^5+(-6610848*y+54605464)*x^4+(2720928*y-12390400)*x^3+(-908928*y-1409280)*x^2+(203264*y+2308608)*x+(-20480*y-770048); do(y^2-y+825,1,s) s=[x^16+6*x^15+7*x^14+(2*y-78)*x^13+(9*y-318)*x^12+(2*y-110)*x^11+(-119*y+1388)*x^10+(-338*y+1248)*x^9+(116*y-4804)*x^8+(1844*y+328)*x^7+(1471*y+29005)*x^6+(-3194*y+12792)*x^5+(-2580*y-54159)*x^4+(4304*y-39034)*x^3+(2303*y+33060)*x^2+(-2220*y+9738)*x+(-540*y-8965)]; do(y^2-y+102,,s) s=[x^3+78*x-592,x^3-39*x+310*y,x^3+6*x+4*y,x^3+78*x-1207168,x^4-4*y*x^3-5853*x^2+3916*y*x+959512]; do(y^2+974,,s) do([y,[15,[1]]]) s=[x^3-291*x+1843,x^32+388*x^30+35890*x^28+1341995*x^26+26505541*x^24+312065587*x^22+2327967602*x^20+11357699251*x^18+36771136457*x^16+79108818025*x^14+111890072979*x^12+101706019796*x^10+57316093902*x^8+18924774302*x^6+3292770148*x^4+231052836*x^2+360937]; do([y,[97,[1]]],,s) \\20 do(y^3-y^2+3*y+6,,[x^4 + (y^2 - 2)*x^2 + (-y - 1)]) s=[x^2+(-28*y^2+36*y-25),x^4+(y^2+8*y-10)*x^2+(27*y^2-37*y+16)]; do([y^3-y^2+1,[6545,1333,2018;0,1,0;0,0,1]],,s) \\do(y^2-y+33515) \\~4 seconds \\do(y^2-y+246) \\~9 seconds \\Bill's bug (internal rnfkummer needs optimal conductor) s=[x^4+(1/32*a^2-1/8*a+53/8)*x^2-1]; do([a^4+392*a^2+64*a+37456,[31,8,5,29;0,1,0,0;0,0,1,0;0,0,0,1],Mat(4)],,s) \\23 s=[x^2+7,x^2+19,x^3-21*x+7,x^9-8436*x^7-26087*x^6+130131*x^5+282036*x^4-551760*x^3-293265*x^2+703836*x-241129]; do([y,[19*7,[1]]],,s) print("sanitize"); do([a^4+392*a^2+64*a+37456,[31,8,5,29;0,1,0,0;0,0,1,0;0,0,0,1],Mat(3)]) \\25 bnrclassfield(bnfinit(y^2+6),Mat(2)) print("hard DLs (#2228)"); p = 1624384359015881850161120870813; bnf = bnfinit('y); bnr = bnrinit(bnf,p); L = bnrclassfield(bnr,2); [#L,poldegree(L[1]),nfdisc(L[1])] p = 1519276421662273577; bnr = bnrinit(bnf,p); L = bnrclassfield(bnr,4); [#L,poldegree(L[1]),nfdisc(L[1])] bnf=bnfinit('y^2-5); p=1594287814679644276013; bnr=bnrinit(bnf,p,,2); bnrclassfield(bnr,2) \\large compositum do([y,[vecprod(primes(8)),[1]], 2],1) \\flag 2 do(y^2+6,2) s=x^12-6*x^11-4*x^10+162*x^9-111*x^8-2160*x^7+3880*x^6+21270*x^5-33936*x^4-161652*x^3+116306*x^2+927816*x+976141; do(y^2-y+22,2,s) s=x^24-4*x^23-10*x^22-20*x^21+462*x^20-1082*x^19+2961*x^18-31722*x^17+247117*x^16-882980*x^15+1842308*x^14-1544496*x^13+3211657*x^12-39314820*x^11+152409044*x^10-232536070*x^9+320758771*x^8+178913634*x^7+1263026049*x^6-5148649720*x^5+744537336*x^4-4090769680*x^3+17058701456*x^2-3566396096*x+399052096; do(y^2-y+58,2,s) do(y^2-y+10,2) \\30 do(y^2-y+24,2) s=x^18-48*x^16+1566*x^14-23621*x^12+244113*x^10-19818*x^8-3170*x^6+17427*x^4-3258*x^2+199; do(y^2-y+50,2,s,64) \\#2371 bnf=bnfinit(y^6-y^5-285*y^4+6485*y^3+42484*y^2-2039004*y+12574320,1); cond = idealfactorback(bnf,idealprimedec(bnf,53)); sol= 310814079206400*x^8+(-2486512633651200*y-621628158412800)*x^7+(66887916480*y^5+818204587200*y^4-14257492603200*y^3+8951914683835200*y^2+16487050492725120*y-89368170197644800)*x^6+(-5644994604480*y^5-32924404497600*y^4-16226414938641600*y^3-70063716497544000*y^2-321020635715176320*y+5190839147637158400)*x^5+(113452713491040*y^5+22942648879365600*y^4+69195975272978400*y^3+317297566469268000*y^2+17224950803810016960*y-191456383385131603200)*x^4+(-19442722659212160*y^5-130893599494627200*y^4+546316792739625600*y^3-17485006969648310400*y^2-98888467973396048640*y+2356534918683614592000)*x^3+(109122986233578240*y^5+2617790380992864000*y^4-54740124198804844800*y^3-324358882573563129600*y^2+19373008639762348623360*y-133533794658507646233600)*x^2+(-869940047122534080*y^5+3668917763131790400*y^4+356477231016250344000*y^3-4048958829765766593600*y^2-46696295095177525902720*y+558997264698690246105600)*x+(131100352706584800*y^5-17248825388454660000*y^4-335591938853448631200*y^3+3860394375558818512800*y^2+164739391281530106148800*y-1627160628948961718304000); T = lift(bnrclassfield(bnrinit(bnf,cond,,2),,1)); check(bnf,T,~sol); \\bug: correct absolute field, wrong extension print("correct absolute, incorrect relative extension"); setrand(1); bnf = bnfinit(y^2+7); dec = idealprimedec(bnf,37); bnr = bnrinit(bnf,dec[1]); pol1 = bnrclassfield(bnr,9)[1]; s=x^9+(6*y+9)*x^7+(-y-20)*x^6+(45/2*y-99/2)*x^5+(-42*y+48)*x^4+(131/2*y-303/2)*x^3+(-36*y+279)*x^2+(-216*y-213)*x+(-86*y+1055); check(bnf,pol1,s,0) idealval(bnf,rnfdisc(bnf,pol1)[1],dec[1]) bnr = bnrinit(bnf,dec[2]); pol2 = bnrclassfield(bnr,9)[1]; s=x^9+(-6*y+9)*x^7+(y-20)*x^6+(-45/2*y-99/2)*x^5+(42*y+48)*x^4+(-131/2*y-303/2)*x^3+(36*y+279)*x^2+(216*y-213)*x+(86*y+1055); check(bnf,pol2,s,0) idealval(bnf,rnfdisc(bnf,pol1)[1],dec[1]) \\bug: corrupted bnr bnf = bnfinit(y^3-y^2+1); bnr = bnrinit(bnf,[6545,1333,2018;0,1,0;0,0,1]); bnrclassfield(bnr,[2,0;0,2]) bnrclassfield(bnr,[2,1;0,1]) print("segfault bug with character input"); poldegree(bnrclassfield(bnfinit(a^2+23),[1],2))==6 print("bug: relative polynomial instead of absolute"); bnf = bnfinit(y^3 - y^2 - 2*y + 1,1); bnr = bnrinit(bnf,[Mat([idealprimedec(bnf,2)[1],3]),[1,1,1]]); poldegree(bnrclassfield(bnr,[2, 0, 0, 0; 0, 2, 1, 0; 0, 0, 1, 0; 0, 0, 0, 1],2)) \\#2146 bnf=bnfinit(y^3-7*y-7,1); bnr=bnrinit(bnf,[[13729,0,0;0,13729,0;0,0,13729],[0,0,0]]); bnrclassfield(bnr,4,1); print("examples from doc"); bnf = bnfinit(y^3+14*y-1); bnf.cyc pol = bnrclassfield(bnf,,1) \\Hilbert class field rnfdisc(bnf,pol)[1] bnr = bnrinit(bnf,3*5*7); bnr.cyc bnrclassfield(bnr,2) \\maximal 2-elementary subextension R=bnrinit(bnfinit(t^2+115),7); f=bnrclassfield(R,[1,0;0,3]); s=x^3+84*x-91399*t; check(R,f[1],s,0) print("tough discrete log"); p=406969676467377719018888256331; bnr=bnrinit(bnfinit(a^2+1),p^2); bnrclassfield(bnr,3) print("tough factorization for structure of k(pr)^*"); setrand(1);p = randomprime(10^200,3); bnrclassfield(bnrinit(bnfinit(y), p,, 3), 3) print("tough conductor factorization"); setrand(1); p=randomprime(2^200,7); q=randomprime(2^200,7); bnf=bnfinit(a^2+a+2); M=matconcat([idealfactor(bnf,p),idealfactor(bnf,q)]~); bnr=bnrinit(bnf,M,,7); bnrclassfield(bnr) print("vector of subgroups"); \\ avoid 32-bit differences RED(red, a)=if (type(a)=="t_POL", red(a), apply(x->RED(red,x),a)); setrand(1);bnr=bnrinit(bnfinit(y^2+3299), 3,, 3); L=subgrouplist(bnr, [3], 1); setrand(1);RED(x->rnfpolredabs(bnr,x), bnrclassfield(bnr, L, 0)) setrand(1);RED(x->rnfpolredabs(bnr,x), bnrclassfield(bnr, L, 1)) setrand(1);RED(polredabs, bnrclassfield(bnr, L, 2)) bnrclassfield(bnr,[]) deg(a)=poldegree(if (type(a)=="t_POL", a, a[1])); filter(v)=[if (cmp(a,b=(-1)^deg(a)*subst(a,x,-x)) < 0,b,a)| a<-v]; filter(bnrclassfield(bnfinit(y^2+31),[Mat(3)])) \\ bnf.Ge contains t_FRAC setrand(1);bnf=bnfinit(y^4+394*y^2+197);bnr=bnrinit(bnf,1,,5);f=bnrclassfield(bnr); s=x^5+(-2349980/7*y^2-925002340/7)*x^3+(49550643842275363355/7*y^2+19498113719555868395685/7)*x^2+(1746603558382375785229605/14*y^2+321242974266101824080279155/14)*x+(-5046922430979180236843378133620866307/14*y^2-1986375600660391162873839261584212464823/14); check(bnr,f[1],s,,147) \\ test rnfkummersimple for ell > 2 setrand(1);bnrclassfield(bnfinit(y^4 - y^3 - 5*y^2 - 6*y + 36)) \\#2325 bnf = bnfinit(a^3-2); bnrclassfield(bnf) bnrclassfield(bnf,,1) bnrclassfield(bnf,,2) bnrclassfield(bnf,[[],[]]) bnrclassfield(bnf,[[],[]],1) bnrclassfield(bnf,[[],[]],2) K=bnrinit(bnfinit(y^4-y^3+16*y^2-16*y+61),[89,9,52,85;0,1,0,0;0,0,1,0;0,0,0,1]); bnrclassfield(K,5) \\ #2280 setrand(1);bnf=bnfinit(quadpoly(-2923,a)); R=bnrclassfield(bnf,3); if(!check(bnf,R[1],x^3 + 48*x + (26*a - 13)),error("quadpoly(-2923),3")); print("bad inputs"); bnrclassfield(y^2+6,Mat(2)) K = bnfinit(y^2+6); bnr=bnrinit(K,2^66);m=matdiagonal(bnr.cyc); bnrclassfield(bnr,m) bnrclassfield(bnr,[m]) bnrclassfield(K,Mat(1/2)) bnrclassfield(K,1/2) bnrclassfield(K,matid(2)) bnrclassfield(K,Mat(2),3) bnrclassfield(K,Mat(2),-1) bnrclassfield(vector(6),Mat(2)) bnrclassfield(bnrinit(bnfinit(y,1),[73786976294838212093,[1]])) bnrclassfield(bnfinit(x)); pari-2.17.2/src/test/in/modsym0000644000175000017500000001323114760123736014604 0ustar billbillallocatemem(40*10^6) W2 = msinit(11,2,-1); W1 = msinit(11,2,1); W = msinit(11,2); msdim(W1) msdim(W2) msdim(W) msgetsign(W2) msgetsign(W1) msgetsign(W) msgetlevel(W) msgetweight(W) mshecke(W2, 2) mshecke(W1, 2) mshecke(W, 2) mshecke(W1, 11) M=msinit(1,12); msgetlevel(M) msgetweight(M) msgetsign(M) msatkinlehner(M,1) mscuspidal(M) msdim(M) mseisenstein(M) D = [0,1,0]~ \\ Delta mseval(M,D) mseval(M,D,[0,oo]) msfromcusp(M,0) msfromhecke(M, [[2,-24]]) mshecke(M,2) msissymbol(M,D) mslattice(M) msnew(M) mspathgens(M) mspathlog(M,[1/2,1/3]) mspetersson(M,D) mspolygon(M) msqexpansion(M,D) msstar(M) M=msinit(1,32,1); mssplit(M) E = ellinit([1,2]); [W,xpm] = msfromell(E); mseval(W,xpm[1],[1/2,1/3]) mseval(W,xpm[1],[1,1;2,3]) E = ellinit([0,-1,1,-10,-20]); [W,xpm] = msfromell(E,1); mseval(W,xpm,[1/2,1/3]) E=ellinit([1,-1,1,-1,-14]); [W,xpm] = msfromell(E,1); mseval(W,xpm) mseval(W,xpm,[0,1/3]) check_twist(e) = msfromell(ellinit(e))[2]; check_twist([0,1]) \\36a1 check_twist([0,-1,1,-7,10]) \\121b1 check_twist([1,-1,0,0,-5]) \\45a1 check_twist([0,0,1,-3,-5]) \\99d1 check_twist([0,0,1,0,-7]) \\27a1 \\17a1-4 vE=[[1,-1,1,-1,-14],[1,-1,1,-6,-4],[1,-1,1,-91,-310],[1,-1,1,-1,0]]; msfromell([ellinit(e)|e<-vE])[2] W = msinit(227,2,1); Wnew = msnew(W); mssplit(W, Wnew) #mssplit(W, Wnew, 1) #mssplit(W, Wnew, 2) #mssplit(W, Wnew, 3) W=msinit(12,2,1); mssplit(W) W = msinit(11,6,1); mssplit(W) W = msinit(1000,2,1); matsize( msnew(W)[1] ) W = msinit(2, 4); charpoly(mshecke(W, 2)) W = msinit(3, 6); charpoly(mshecke(W, 2)) W = msinit(4, 4); charpoly(mshecke(W, 3)) W = msinit(11, 4); charpoly(mshecke(W, 2)) W = msinit(2, 8); charpoly(mshecke(W, 2)) [g,R]=mspathgens(W) mspathlog(W,g[1]) mspathlog(W,g[2]) mspathlog(W,[1/3,1/2]) mseval(W,[0,0]) s=msnew(W)[1][,1]; mseval(W,s) mseval(W,s,[0,0]) mseval(W,[;],[1/3,1/2]) mseval(W,Mat([s,s]),[1/3,1/2]) mseval(W,s,g[1]) mseval(W,s,g[2]) W = msinit(11, 2); T = mshecke(W, 3); [S,E] = mscuspidal(W, 1) msdim(S) msdim(E) E == mseisenstein(W) S == mscuspidal(W) msfromcusp(W,1) msfromcusp(W,oo) msfromcusp(W,1/2) msfromhecke(W, [[2,-2],[3,-1]]) W = msinit(23,2, 1); V = mssplit(W); msqexpansion(W, V[1], 30) msqexpansion(W, V[1]) M=msinit(603,2,1);;V=mssplit(M,,1); Set([v|v<-vector(#V,i,msqexpansion(M,V[i]))]) W = msinit(6,4); m=msatkinlehner(W,1) matdet(m) m=msatkinlehner(W,2) matdet(m) m=msatkinlehner(W,3) matdet(m) m=msatkinlehner(W,6) matdet(m) msstar(W) N = msnew(W)[1]; s = N[,1]; msissymbol(W,s) msissymbol(W,N) S = mseval(W,s); msissymbol(W,S) T=S; T[3]++; msissymbol(W,T) M = msinit(7,8, 1); N = msnew(M)[1]; s = N[,1]; S = mseval(M,s); mseval(M,N) msissymbol(M, S) W=msinit(17,2); G=mspathgens(W)[1]; vector(#G,i,mspathlog(W,G[i])) W=msinit(96,6,1); matsize(msnew(W)[1]) \\ used to be too slow check(N,k)= { M=msinit(N,k,1); S=mssplit(M); for(i=1, #S, f = msqexpansion(M,S[i],2)[1]; mod = if(type(f)=="t_INT", x, f.mod); if(polsturm(mod)!=poldegree(mod), error([N,k,i],":",f,": not real")); print(poldegree(mod)); ); } check(49,4) check(49,6) check(64,4) check(64,6) M=msinit(14,2,1); S=mscuspidal(M); mshecke(M,2) mshecke(M,2,S) M = msinit(23,4); S = msfromhecke(M, [[5, x^4-14*x^3-244*x^2+4832*x-19904]]); charpoly(mshecke(M,5,S)) [M,xpm] = msfromell(ellinit([0,-1,1,-10,-20])); mspetersson(M, xpm[1],xpm[2]) [M,xpm] = msfromell(ellinit([1,1,0,-9825,-412250])); \\1225e1, #1906 [content(xpm[1]), content(xpm[2])] M = msinit(11,4); n = msdim(M); A = matid(n); T=matrix(n,n,i,j,mspetersson(M,A[,i],A[,j])) mspetersson(M, A, A) == T mspetersson(M, A) == T mspetersson(M) == T M = msinit(12,4); n = msdim(M); A = matid(n); T=matrix(n,n,i,j,mspetersson(M,A[,i],A[,j])) mspetersson(M, A, A) == T mspetersson(M, A) == T mspetersson(M) == T M = msinit(11,4,1); mspetersson(M) M = msinit(11,4,-1); mspetersson(M) M = msinit(17,4); mspetersson(M) M = msinit(19,4); mspetersson(M) M = msinit(13,4); mspetersson(M) \\ mspadic from now on ellpadicmoments(e,p,n, D=1) = { e = ellinit(e); my(Wp, [M,xpm]=msfromell(e,sign(D))); Wp = mspadicinit(M, p, n); mspadicmoments(Wp, xpm, D) }; msseries(e,p,n,i=0,D=1)={ my(M = ellpadicmoments(e,p,n,D)); mspadicseries(M,i) }; /* good ordinary */ M=ellpadicmoments([0,1,1,0,0],3,4) \\ 43a1 mspadicseries(M) mspadicseries(M,1) M=ellpadicmoments([0,1,1,-9,-15],7,2) \\ 19a1 mspadicseries(M) mspadicL(M,0) /* supersingular */ M=ellpadicmoments([1,-1,1,-1,-14],3,5) \\ 17a1 mspadicseries(M) mspadicseries(M,1) ellpadicmoments([1,-1,0,4,-3],3,5) \\ 73a1 ellpadicmoments([1,-1,1,0,0],3,5) \\ 53a1 ,a_3=-3 rank 1 ellpadicmoments([1,-1,1,-3,3],3,5) \\ 26b1 ,a_3=-3 rank 0 E11a1=[0,-1,1,-10,-20]; E15a1=[1,1,1,-10,-10]; E17a1=[1,-1,1,-1,-14]; E43a1=[0,1,1,0,0]; E389a1=[0,1,1,-2,0]; msseries(E11a1,3,1) msseries(E11a1,3,5) msseries(E11a1,3,5,1) \\ 1-teich component -> 0 msseries(E11a1,3,5,2) \\ 2-teich component msseries(E15a1,11,7,7) \\ 2 real connected comp. msseries(E389a1,3,3) \\ 2 real connected comp. msseries(E11a1,11,7) \\ split -> trivial zero msseries(E43a1,3,4,0,-19) \\ twist msseries(E17a1,3,5) \\ supersingular M=msinit(3,6,-1); xpm=[-1]~; Wp = mspadicinit(M,5,10); oms = mspadicmoments(Wp, xpm, 1); vector(6,j,mspadicL(oms,j-1)) testweil(E)= { my([e,s]=ellweilcurve(ellinit(E))); for(i=1,#e, print(e[i][1..5], ": ",s[i])); } testweil([1,-1,1,-2,0]) testweil([1,-1,1,-96608,-11533373]) testweil([1,0,1,4,-6]) E=ellinit([1,0,1,4,-6]); [e,s]=ellweilcurve(E,&ms); s msdim(ms[1]) ms[2] ellweilcurve(ellisomat(E)) == [e,s] ellweilcurve(ellisomat(E,,1)) == [e,s] \\ Errors, keep at end of file ms=msinit(57,2,1);M=mssplit(ms);msdim(M) E = ellinit([1,2]); [W,xpm] = msfromell(E); mseval(W,xpm[1],[1]) W = msinit(6,4); msatkinlehner(W,4) msinit(-11,2,0) msinit(11,1,0) msinit(1/2,2,0) msinit(1,1/2,0) msinit(11,2,2) msinit(11,2,-2) pari-2.17.2/src/test/in/nfcompositum0000644000175000017500000000515014760137411016013 0ustar billbilldo(name, test) = { setrand(1); print(name,": ", iferr(test(), E, E)); } gusuite(name, tests) = print("Suite: ", name); tests(); nfcompo() = gusuite("compositum of relative extensions", ()->{ my(nf, pol, ii); pol = y^2+1; nf = nfinit(pol); ii = Mod(y,pol); do("compositum of degrees 2 and 3 over quadratic field", (()->my(L=nfcompositum(nf,x^2-ii,x^3-5,3), a=Mod(L[2],L[1]), b=Mod(L[3],L[1])); polisirreducible(L[1]) && a^2-ii==0 && b^3-5==0 && b+L[4]*a==Mod(x,L[1]))); do("compositum of degrees 2 and 4 over quadratic field", (()->my(L=nfcompositum(nf,x^2-ii,x^4-5,3), a=Mod(L[2],L[1]), b=Mod(L[3],L[1])); polisirreducible(L[1]) && a^2-ii==0 && b^4-5==0 && b+L[4]*a==Mod(x,L[1]))); do("compositum of degrees 5 and 7 over quadratic field", (()->my(L=nfcompositum(nf,x^5+ii*x+1,x^7-5*x+ii,3), a=Mod(L[2],L[1]), b=Mod(L[3],L[1])); polisirreducible(L[1]) && a^5+ii*a+1==0 && b^7-5*b+ii==0 && b+L[4]*a==Mod(x,L[1]))); pol = y^5-2; nf = nfinit(pol); ii = Mod(y,pol); do("compositum of degrees 2 and 3 over degree 5 field", (()->my(L=nfcompositum(nf,x^2-ii,x^3-5,3), a=Mod(L[2],L[1]), b=Mod(L[3],L[1])); polisirreducible(L[1]) && a^2-ii==0 && b^3-5==0 && b+L[4]*a==Mod(x,L[1]))); do("compositum of degrees 2 and 4 over degree 5 field", (()->my(L=nfcompositum(nf,x^2-ii,x^4-5,3), a=Mod(L[2],L[1]), b=Mod(L[3],L[1])); polisirreducible(L[1]) && a^2-ii==0 && b^4-5==0 && b+L[4]*a==Mod(x,L[1]))); do("compositum of degrees 5 and 4 over degree 5 field", (()->my(L=nfcompositum(nf,x^5+ii*x+1,x^4-5*x+ii,3), a=Mod(L[2],L[1]), b=Mod(L[3],L[1])); polisirreducible(L[1]) && a^5+ii*a+1==0 && b^4-5*b+ii==0 && b+L[4]*a==Mod(x,L[1]))); }); nfcompo(); K = nfinit(y^2-5); L = nfcompositum(K, x^5-y, polcyclo(5)) L = nfcompositum(K, x^5-y, polcyclo(5), 1); [R,a,b,k] = L[1] a^5 - y liftall(b^5) L = nfcompositum(K, x^5-y, x^5-y) L = nfcompositum(K, x^5-y, x^5-y,2) L = nfcompositum(K, x^5-y, polcyclo(3),2) L = nfcompositum(K, x^5-y, polcyclo(3),3) nfcompositum(nfinit(y),x,x^2+x+1,3) \\#1777 nfcompositum(nfinit(y-1),x^3-2,x^3-1) \\#1796 nfcompositum(bnfinit(y),x^3-2,x^3-1) \\#2461 nf = nfinit(y^3-41*y^2+426*y-184); P = 4*x^3+4*x+(-6/23*y^2+146/23*y-16); Q = x^2+(-17280/23*y^2+314496/23*y+70144); { foreach([P,Q],p, foreach([P,Q],q, foreach([0,2],k, my(C=nfcompositum(nf,p,q,k),L=if(k==0,apply(pollead,C),pollead(C))); print(k,":",L)))) } \\#2605 nfcompositum(nfinit(y-2),x^2-y,x^3-x-1) \\bad input nfcompositum(nfinit(x),w^2+1,w^2+1) nfcompositum(x,w^2+1,w^2+1) nfcompositum(nfinit(x-1),x^3-2,x^3-1) nfcompositum(nfinit(x^2+1),x^3-2,x^3-1) nfcompositum(nfinit(x-1),y^3-2,y^3-1) nfcompositum(bnfinit(x),x^3-2,x^3-1) pari-2.17.2/src/test/in/objets0000644000175000017500000000153014676526175014573 0ustar billbill\e +3 -5 5+3 5-3 5/3 5\3 5\/3 5%3 5^3 binary(65537) bittest(10^100,100) ceil(-2.5) centerlift(Mod(456,555)) component(1+O(7^4),3) conj(1+I) conjvec(Mod(x^2+x+1,x^3-x-1)) truncate(1.7,&e) e denominator(12345/54321) divrem(345,123) divrem(x^7-1,x^5+1) floor(-1/2) floor(-2.5) frac(-2.7) I^2 imag(2+3*I) lex([1,3],[1,3,5]) max(2,3) min(2,3) Mod(-12,7) norm(1+I) norm(Mod(x+5,x^3+x+1)) numerator((x+1)/(x-1)) 1/(1+x)+O(x^20) numtoperm(7,1035) permtonum([4,7,1,6,3,5,2]) 37. real(5-7*I) shift(1,50) shift([3,4,-11,-12],-2) shiftmul([3,4,-11,-12],-2) sign(-1) sign(0) sign(0.) simplify(((x+I+1)^2-x^2-2*x*(I+1))^2) sizedigit([1.3*10^5,2*I*Pi*exp(4*Pi)]) truncate(-2.7) truncate(sin(x^2)) type(Mod(x,x^2+1)) valuation(6^10000-1,5) \p 57 Pi \p 38 O(x^12) padicno=(5/3)*127+O(127^5) padicprec(padicno,127) length(divisors(1000)) Mod(10873,49649)^-1 (1+I)*(1+1/2*I) pari-2.17.2/src/test/in/qfisom0000644000175000017500000000556314567450071014603 0ustar billbillmaxdiag(M)=vecmax(vector(#M,i,M[i,i])); in(M,fl)=if(fl,qfisominit(M,fl),qfisominit(M)); checkauto(M,f,fl)= { my(G=if(f,qfauto(in(M,fl)),if(fl,qfauto(M,fl),qfauto(M)))); for(j=1,#G[2],my(Q=G[2][j]); if(M!=Q~*M*Q ,error(v))); print(G[1]); } checkisom(M,N,f,fl)= { my(Q=if(f==0,if(fl,qfisom(M,N,fl),qfisom(M,N)), f==1,qfisom(in(M,fl),N), f==2,qfisom(in(M,fl),N,,qfauto(N)))); if(Q==0 || M!=Q~*N*Q ,error(N),print("OK")); } qfauto(Mat(1)) M=[4,-2,-1,1,1,-2,-2,-2,-1,-1,-1,-1;-2,4,-1,-2,-2,2,2,0,-1,-1,-1,-1;-1,-1,4,-1,-1,1,1,2,0,0,2,2;1,-2,-1,4,1,-1,-1,0,2,2,-1,-1;1,-2,-1,1,4,-1,-1,-1,1,1,0,0;-2,2,1,-1,-1,4,1,0,-1,-1,-1,-1;-2,2,1,-1,-1,1,4,2,1,1,0,0;-2,0,2,0,-1,0,2,4,2,2,2,2;-1,-1,0,2,1,-1,1,2,4,2,1,0;-1,-1,0,2,1,-1,1,2,2,4,0,1;-1,-1,2,-1,0,-1,0,2,1,0,4,2;-1,-1,2,-1,0,-1,0,2,0,1,2,4]; qfauto(qfisominit(M,,qfminim(M,maxdiag(M))))[1] qfauto(qfisominit(M,,qfminim(M,maxdiag(M))[3]))[1] checkauto(M,0) checkauto(M,0,[1,1]) checkauto(M,1) checkauto(M,1,[1,1]) N1=[2,0,-1,-1,-1,1,0,0,0,0,-1,0,-1,1,0,0;0,2,1,1,1,-1,0,0,-1,1,-1,0,0,0,1,1;-1,1,4,2,2,-2,0,1,1,0,-1,1,-1,1,-1,-1;-1,1,2,4,2,-2,0,1,-1,0,1,1,1,1,1,1;-1,1,2,2,4,-2,0,1,-1,0,-1,1,-1,1,1,1;1,-1,-2,-2,-2,4,-1,0,1,0,1,0,1,-1,-1,-1;0,0,0,0,0,-1,2,-1,-1,0,-1,0,-1,0,1,0;0,0,1,1,1,0,-1,2,1,0,0,1,0,1,-1,0;0,-1,1,-1,-1,1,-1,1,4,0,0,0,0,0,-3,-2;0,1,0,0,0,0,0,0,0,2,-1,0,0,-1,0,0;-1,-1,-1,1,-1,1,-1,0,0,-1,4,0,3,-1,0,0;0,0,1,1,1,0,0,1,0,0,0,2,0,1,0,0;-1,0,-1,1,-1,1,-1,0,0,0,3,0,4,-1,0,1;1,0,1,1,1,-1,0,1,0,-1,-1,1,-1,4,0,0;0,1,-1,1,1,-1,1,-1,-3,0,0,0,0,0,4,2;0,1,-1,1,1,-1,0,0,-2,0,0,0,1,0,2,4]; N2=[6,-4,4,-2,2,-1,1,1,-1,2,1,-2,3,-1,1,0;-4,8,-6,2,-1,0,0,-1,2,-4,0,3,-3,0,-2,-1;4,-6,8,-4,1,1,2,2,-2,5,3,-4,2,1,2,2;-2,2,-4,4,-1,0,-2,-2,1,-3,-3,2,-1,-1,-1,-1;2,-1,1,-1,2,0,1,0,0,1,1,-1,1,0,0,0;-1,0,1,0,0,2,1,0,0,1,1,-1,-1,1,0,1;1,0,2,-2,1,1,4,2,0,2,3,-2,0,1,0,1;1,-1,2,-2,0,0,2,4,-1,1,1,-2,1,0,1,0;-1,2,-2,1,0,0,0,-1,2,-1,0,1,-1,0,0,0;2,-4,5,-3,1,1,2,1,-1,6,4,-3,0,2,1,2;1,0,3,-3,1,1,3,1,0,4,6,-2,-2,2,0,2;-2,3,-4,2,-1,-1,-2,-2,1,-3,-2,4,-1,-1,-1,-1;3,-3,2,-1,1,-1,0,1,-1,0,-2,-1,4,-1,1,-1;-1,0,1,-1,0,1,1,0,0,2,2,-1,-1,2,0,1;1,-2,2,-1,0,0,0,1,0,1,0,-1,1,0,2,0;0,-1,2,-1,0,1,1,0,0,2,2,-1,-1,1,0,2]; checkauto(N1,0) checkauto(N1,0,[1,1]); checkauto(N1,1) checkauto(N1,1,[1,1]); checkisom(N1,N2,0) checkisom(N1,N2,0,[1,1]) checkisom(N1,N2,1) checkisom(N1,N2,1,[1,1]) checkisom(N1,N2,2) L1=[3,-2,-1,1,1;-2,2,0,-1,-1;-1,0,2,1,1;1,-1,1,2,2;1,-1,1,2,3]; L2=matid(5); checkauto(L1,0) checkisom(L1,L2,0) checkauto(L1,1) checkisom(L1,L2,1) checkisom(L1,L2,2) qfauto([[1,0;0,1],[0,0;1,0]]) qfauto([[1,0;0,1],[0,1;0,0]]) A=[4,3;3,10];B=[16,6;6,10]; [qfisom(A,B),qfisom(B,A)] G= [1152,[[-1,0,0,0;0,-1,0,0;0,0,-1,0;0,0,0,-1],[0,0,0,1;0,1,1,0;0,-1,0,0;1,-1,-1,0],[-1,0,0,0;0,0,-1,1;-1,0,1,0;-1,1,1,0]]]; qfautoexport(G) qfautoexport(G,1) Q=qfminim(N1);G=qfauto(N1); apply(length,qforbits(G[2],Q[3])) apply(length,qforbits(G,Q[3])) apply(length,qforbits(G,Q)) pari-2.17.2/src/test/in/quad0000644000175000017500000000130314676526175014235 0ustar billbillw=quadgen(5); w^0 w+1. w+(I+0.) 1.*w (I+0.)*w norm(w) norml2(w) trace(w) trace(1+0*w) floor(w) floor(1/2 + w/7) ceil(w) ceil(1/2 + w/7) round(w) round(1/2 + w/7) ceil(quadgen(5)*0) w < 1 1 < w w < 1. 1. < w w < 3/2 3/2 < w w < w w <= w w <= +oo w <= -oo quadgen(-8) < 1 z=66992092050551637663438906713182313772-47370562574818466708936539960450008968*quadgen(8); z*1. 2*quadgen(21)-3 + 0. \\ #2362 test(a)=[sign(z) | z<-[a,a-1,a-2,1-a,2-a]] test(w) test(quadgen(8)) w8 = quadgen(-8); round(w8) w = quadgen(2^64+1) w * 1. floor(2*w) floor(-2*w) ceil(2*w) ceil(-2*w) round(2*w) round(-2*w) quadgen(5) + 2/3 + 0.\\ #2419 \\ Errors keep at end of file floor(w8) ceil(w8) sign(w8) floor(Mod(0,3)*quadgen(5)) pari-2.17.2/src/test/in/nfpolsturm0000644000175000017500000000104114567450071015501 0ustar billbillnf = nfinit(y^5+y^4-4*y^3-3*y^2+3*y+1); t = x^2 - nf.zk[2]; nfpolsturm(nf, t) nfpolsturm(nf, t, 1) nfpolsturm(nf, t, [1..4]) nfpolsturm(nf, -1) nfpolsturm(nf, y) nfpolsturm(nf, Mod(y,nf.pol)) nfpolsturm(nf, x^2-(y+950385237198502187979577282097391163977102921506573742575513/495253880608585631635195731645995689515566957889181807495428)) nf=nfinit(a^2-2); for(n=1,100,if(nfpolsturm(nf,x^2-Mod(a+1,a^2-2)^n)!=[if (n%2,0,2),2],print(n))) \\ Errors nfpolsturm(nf, a, 3) nfpolsturm(nf, a, [-1..1]) nfpolsturm(nf, a, [1..3]) nfpolsturm(nf, 0, 1) pari-2.17.2/src/test/in/qfb0000644000175000017500000000400414676526175014054 0ustar billbillVec(qfbred(Qfb([6,6,-1]),1)) Qfb(5*x^2+7*x+9) Qfb(Mat([3,1;1,3])) q=Qfb(7, 30, -14)^2; qfbpowraw(q,-1) q*q^2 q^0 q^1 q^-1 q^-(2^64+1) q=Qfb(2, 1, 3); q2=q*q; q3=qfbcompraw(q,q2) qfbpowraw(q,3) qfbred(q3,1) q=Qfb(1009, 60, 99108027750247771) qfbnupow(q, 8839368315) L = sqrtnint(abs(poldisc(q)), 4); qfbnupow(q, 8839368315,L) f=Qfb(2,2,2); g=Qfb(3,3,3); [f * g, qfbcompraw(f, g)] f=Qfb(3,2,8); g=Qfb(2,1,3); [f * g, qfbcompraw(f, g)] f=Qfb(7,18,-18); g=Qfb(11,52,-41); [f * g, qfbcompraw(f, g)] q=Qfb(22000957029,25035917443,7122385192); qfbred(q) qfbredsl2(q) q=Qfb(33947,-39899,11650); qfbred(q) qfbredsl2(q) q=Qfb(1099511627776,1879224363605,802966544317); [qr,U]=qfbredsl2(q) qfeval(q,U) qfeval(q,U[,1]) qfeval(q,U[,2]) qfeval(q,U[,1],U[,2]) D=poldisc(q); qfbredsl2(q,sqrtint(D)) qfbredsl2(q); p=2^64+13; qfbprimeform(-4,p) qfbprimeform(5,p) D=10^7+1; u=[qfbprimeform(D,1),0.]; f=qfbred(u,1); f^0 qfbpow(f,0) f^1 qfbpow(f,1) f^-1 qfbpow(f,-1) f^6 qfbpow(f,6) f*f f*f/f egcd(x,y)= { my(k=2*y,Q=qfbred(Qfb(k^2*x^2+1,2*k^2*x*y,k^2*y^2))); my([a,b,c]=Vec(Q),p,q,u,v,g); if(!issquare(a,&p),error("gcd")); g=y/p; q = -x/g; issquare(c-k^2*g^2,&u); if ((1+q*u)%p!=0,u=-u); v=(1+q*u)/p; [u,v,g]; } print("test qfbred, large coefs"); my([p,q] = [random(2^100000), random(2^100000)],[u,v,g] = egcd(p,q)); u*p+q*v==g egcdsl2(x,y)= { my(k=2*y,[Q,U]=qfbredsl2(Qfb(k^2*x^2+1,2*k^2*x*y,k^2*y^2))); my([a,b,c]=Vec(Q),p,q,u,v,g); if(!issquare(a,&p),error("gcd")); if (sign(U[1,1])!=sign(p),p=-p); g=y/p; q = -x/g; issquare(c-k^2*g^2,&u); if ((1+q*u)%p!=0,u=-u); v=(1+q*u)/p; [p,u;q,v]==U; } print("test qfbredsl2, large coefs"); my([p,q] = [random(2^100000), random(2^100000)]);egcdsl2(p,q) \\ Errors, keep at end of file qfbredsl2(q,1.); r=Qfb(5,7,1); i=Qfb(5,1,1); R=[r,0.]; [1,2]*[1,2,4] R*[1,2] [1,2]*R [i,0.]*[1,2] [1,2]*[i,0.] [i,0.]*[i,0.] f=Qfb(12,5,3);g=Qfb(5,5,2); f*g f/g f=Qfb(8,14,1);g=Qfb(4,12,6); f*g \\ should fail f/g Qfb(1,,2) Qfb(1) Qfb(1,2) Qfb(['x,2,3]) f=Qfb(7,18,-18); g=Qfb(11,52,-41); qfbcomp([f,1.],g) pari-2.17.2/src/test/in/setdebug0000644000175000017500000000042514567450071015077 0ustar billbillsetdebug()~ setdebug("bnf",2) setdebug("bnf") setdebug("bnf",0) setdebug("bnf") \g 2 \g bnf \g "bnf" \g 1"bnf" \g 1bnf \g "bnf"1 \g bnf \g bnf2 \g bnf \\ ERRORS \gf 10 1/0 \gf 1 setdebug("does_not_exist") \gf 0 \g 1 "does_not_exist" \g "does_not_exist" \g "does_not_exist" 1 pari-2.17.2/src/test/in/install0000644000175000017500000000030714567450071014742 0ustar billbillinstall(addii,GG) type(addii) addii(1,2) ?addii kill(addii) ?addii install(addiu,"GD0,U,") addiu(2,3) type(addiu) \\ ERRORS install(addiu,"GDL0,U,") install(addiu,"GDL0,L,") install(addiu,"GD-1,U,") pari-2.17.2/src/test/in/nfdiscfactors0000644000175000017500000000014614567450071016125 0ustar billbillnfdiscfactors(nfinit([x^2+1,[1,x]])) nfdiscfactors(x^2+3) nfdiscfactors(x^7+3*(2^30+3)^3*(2^31+11)^7) pari-2.17.2/src/test/in/ratpoints0000644000175000017500000005333114676526175015336 0ustar billbillaffine2proj(P)= { my([X,Y]=P); my(x=numerator(X),z=denominator(X),y=Y*z^3); [x,y,z]; } { V=[ [-10,-8,1,-2,0,-5,-4], [4,-6,-4,-7,-8,5,-3], [4,-8,2,-3,-1,0,-6], [0,5,6,2,-7,4,-8], [-5,10,-9,-6,7,-1,3], [0,-8,-6,-9,-8,-6,-9], [-6,5,7,-10,-1,1,-2], [-2,9,-3,-3,-4,-2,-3], [7,-7,-2,5,-1,8,7], [-6,10,-6,9,-3,-7,-2], [-3,-8,10,6,3,7,-7], [-5,5,8,7,-2,2,-3], [-8,5,9,-6,-2,-6,-1], [0,6,0,-9,6,2,-3], [2,1,-5,9,-9,1,-2], [-5,8,-4,-5,10,-10,-5], [-2,3,1,4,-5,7,3], [-8,-8,4,8,7,3,-6], [6,6,-5,-8,-5,-5,-2], [6,-10,-6,-6,-7,-8,-8], [4,10,-9,-1,6,10,3], [1,2,7,3,-7,-9,-2], [-7,-5,-2,0,-3,-9,2], [3,1,-7,-3,4,7,3], [-3,7,6,-3,-1,7,-8], [-8,-3,0,-3,4,7,4], [10,10,5,-7,0,3,-2], [-7,-3,10,-4,-3,-7,3], [7,-8,-2,7,-4,1,3], [3,-3,-9,-10,5,-2,-1], [4,9,-7,8,-3,1,10], [-4,-9,-7,-3,9,7,8], [-2,5,7,4,0,6,4], [0,1,1,-1,4,4,9], [8,4,-4,1,-3,-10,3], [-10,-10,-3,9,7,0,-4], [-7,-1,7,-9,9,-5,-7], [0,5,1,-4,10,-2,-3], [4,6,-6,1,-7,-8,-9], [2,-7,-4,3,-2,-8,2], [1,8,-8,-5,-2,9,-4], [-6,9,-10,2,9,5,2], [1,-4,-6,-9,-1,-3,-4], [-2,4,3,1,-2,-10,10], [9,5,-10,1,-10,-10,5], [-1,6,-3,4,-6,-6,-2], [3,4,-6,-6,-9,5,-1], [4,-8,-2,6,6,3,8], [2,0,3,0,10,4,5], [-10,3,0,1,5,8,2], [8,6,-2,5,-3,3,-9], [10,-10,-3,-4,8,8,7], [6,10,-4,-3,-9,-10,8], [-5,-1,-3,-4,5,10,9], [0,8,10,10,-8,8,-2], [8,-4,-2,-10,-1,9,9], [9,2,5,1,4,9,10], [1,-2,6,-7,-4,-8,1], [-6,8,-2,0,7,-5,-2], [-4,-5,-7,8,-4,-4,-1], [6,9,-9,3,-8,10,10], [9,-5,5,2,2,1,1], [-7,-2,1,8,2,-8,-1], [5,-6,7,-7,6,-6,9], [9,10,4,1,-1,7,-7], [0,1,10,7,-9,-8,9], [-10,9,5,-9,4,-3,6], [-7,-6,5,9,-7,-10,-7], [-8,-5,6,-7,-1,-4,-2], [-4,7,6,0,3,1,-4], [2,4,5,7,-10,-9,1], [-3,9,-5,9,2,-8,2], [7,2,10,-1,-4,-10,-2], [0,-4,-9,-4,-4,-6,-10], [9,1,-4,-4,4,7,6], [-2,-1,6,8,4,-8,-10], [9,-8,-5,9,2,-5,8], [5,0,10,-10,2,5,-6], [6,0,9,-7,-8,0,-2], [6,3,-6,3,8,10,-9], [-7,-2,-6,-1,10,-2,-5], [-7,3,-5,9,1,-8,6], [-5,7,-8,10,1,-9,1], [6,-6,-7,0,6,3,-4], [-2,-2,-10,-7,-5,-3,0], [-6,-6,-3,-4,-9,-10,6], [7,-6,0,10,-1,1,-8], [10,9,-9,2,1,9,-3], [-6,-4,-9,5,-10,10,8], [-10,-8,-10,8,-1,-9,9], [3,-3,-9,-4,-6,-8,-4], [-2,8,9,-6,5,-7,-6], [6,9,-9,3,7,10,-5], [6,10,2,-5,0,-6,-9], [9,-6,6,-9,-8,7,-1], [1,0,-9,7,-10,-7,-10], [4,-3,3,5,-4,-5,2], [-9,-3,8,-6,2,9,3], [10,-4,1,4,10,1,-5], [5,10,0,-8,-9,6,3], [-9,5,-4,-5,4,-4,6], [1,-2,5,-5,-9,3,2], [-8,-3,6,1,9,0,10], [-3,-5,-3,-7,5,-4,-8], [-7,8,7,1,-3,10,-4], [8,0,8,9,9,-7,0], [-5,-8,-3,10,-9,4,-8], [3,-9,10,3,4,-9,-7], [6,-8,-1,10,2,-5,-9], [8,4,-6,-1,3,3,2], [9,5,9,4,5,3,-9], [-3,4,-5,9,-7,8,-7], [3,9,-5,8,0,1,-4], [-1,3,10,0,-3,2,1], [7,-10,0,8,-10,3,10], [7,-6,-4,2,0,-4,0], [-8,4,-8,6,10,-9,2], [-1,-10,-5,-2,1,9,6], [-10,-4,2,9,4,7,-3], [5,1,4,2,-7,4,-4], [0,4,2,-10,-3,5,6], [4,4,3,6,4,3,-1], [-10,10,-10,8,-8,-6,-9], [7,7,10,-9,-5,-1,-3], [-7,10,4,-3,1,1,3], [-10,5,-8,4,1,4,-4], [-3,1,-1,8,10,4,8], [2,10,3,-7,-1,-3,-6], [-7,8,0,7,10,2,-6], [-3,-4,-5,-2,1,-1,-5], [-2,10,-4,8,-7,-4,-2], [9,0,10,8,-4,4,-7], [3,9,-5,0,1,4,7], [1,10,4,9,1,-10,5], [7,-6,-10,10,-8,2,-7], [7,-3,7,10,-7,-6,6], [4,4,2,4,10,-1,3], [-4,-6,10,10,7,-5,-9], [6,-8,1,-9,2,8,-7], [3,-5,-6,-5,7,3,-2], [9,8,-7,8,7,3,8], [7,4,-4,6,4,-7,-6], [-3,10,-1,1,4,-9,0], [-3,5,-2,-6,9,-6,7], [4,7,3,9,4,2,-7], [-10,-3,1,10,5,-9,5], [-5,5,-9,7,10,2,-3], [7,1,0,6,-5,9,-6], [-5,1,-7,-9,-1,9,-4], [7,-6,-9,5,-2,-3,-6], [0,6,9,-5,8,-5,10], [9,10,-2,9,9,-3,5], [-4,7,8,0,-6,-1,-1], [4,5,7,-3,5,-9,4], [-5,-7,8,5,-8,-5,-1], [-10,5,-10,0,-2,2,10], [7,7,5,-9,-10,2,1], [1,-10,-8,1,3,4,-8], [-8,4,10,1,-10,2,2], [7,2,-4,-2,-10,-3,3], [3,-5,-6,-2,-5,2,9], [-3,-6,-9,-7,-3,3,-8], [-6,-4,0,-1,9,-3,-8], [-7,9,9,-7,4,0,-1], [2,4,4,1,-9,10,-10], [9,-1,-8,6,8,1,-2], [10,-10,5,10,9,-10,-3], [10,0,-10,-6,6,-7,2], [10,0,-1,3,10,2,-3], [-10,10,-2,7,5,-9,10], [-2,-8,7,-6,6,9,10], [6,5,2,-1,3,2,-4], [9,5,-10,-6,-1,3,0], [-2,-10,5,4,8,-6,-5], [8,-4,-3,2,4,-5,-5], [2,4,10,-4,8,-2,7], [-4,10,8,9,1,-2,8], [4,5,6,4,-8,9,8], [-3,-6,4,1,6,2,-6], [-8,8,-9,9,-7,-1,-3], [7,-2,-9,10,1,4,-10], [-1,-5,-5,-7,-9,4,-3], [-3,8,2,0,-6,9,9], [-4,5,0,-10,-4,-6,-8], [-10,-6,-7,-6,-9,-2,4], [-2,-5,-1,0,8,3,-10], [-4,-3,6,9,-5,1,-8], [2,0,6,8,-8,-2,-9], [2,4,2,-7,-2,-4,-7], [2,-7,-4,7,-2,9,7], [3,-7,-3,0,1,1,-4], [-4,-7,1,7,1,-4,-3], [8,7,-4,-3,0,-2,3], [-3,-7,1,8,3,-2,1], [3,0,-7,2,-6,5,-7], [-4,-2,-6,-3,-6,-2,10], [5,10,1,10,10,-6,-4], [-4,6,5,-10,2,6,-3], [4,-5,2,3,-10,3,8], [-5,4,-10,4,6,0,-2], [-7,-3,-9,7,-3,2,1], [1,-9,-9,2,8,8,7], [-7,1,-7,-7,1,-6,-10], [-9,1,-2,-5,3,5,-3], [-3,-9,-3,9,6,-9,4], [-2,9,-9,5,5,-7,8], [5,-10,8,-8,-3,-8,-10], [0,1,-7,7,6,3,-8], [-1,-9,4,-8,-5,-6,-2], [-6,5,1,8,-8,3,-3], [6,8,-4,1,3,9,-1], [4,-6,7,10,-9,-7,-8], [1,7,-3,3,0,-10,-1], [4,-6,-2,3,-1,7,-6], [5,-8,-2,-4,-6,10,-5], [10,-3,2,-1,-6,-8,-1], [1,2,-5,-10,-7,-4,-1], [7,-8,4,0,5,4,1], [3,6,-2,2,6,-6,1], [8,-4,6,1,-9,8,-8], [-4,-6,8,5,-5,-4,5], [-7,-3,8,-6,1,-6,-4], [8,-4,-10,-3,10,4,4], [-4,4,3,-7,1,-3,-8], [6,-5,-4,-5,-7,-5,9], [-10,6,-9,-8,2,2,2], [-7,1,10,-9,10,-2,-4], [9,0,-8,8,-3,10,2], [3,-4,2,8,10,2,-1], [2,8,-8,6,-6,7,8], [1,5,-8,-4,-8,-7,7], [-3,4,-5,-6,-10,-1,7], [9,-6,-3,3,-6,-1,-1], [-6,4,-10,6,-10,-4,-1], [-4,-7,-4,4,-2,-8,7], [4,8,-2,-2,-3,-7,-5], [5,-10,0,2,-9,-4,-7], [8,-7,-5,-6,0,7,-5], [7,-9,4,10,-7,1,6], [10,-8,1,8,0,-3,8], [3,3,2,-2,-6,-2,-10], [1,0,-8,5,6,-1,-8], [-5,6,0,10,7,-4,-10], [10,-5,2,5,6,8,7], [7,2,7,-6,-8,-2,2], [3,7,3,8,-3,-4,1], [8,-2,9,0,-5,9,-3], [6,0,5,-6,-9,-3,-2], [-5,-8,-10,2,1,-2,-1], [3,1,-9,5,-10,8,-8], [6,-7,-4,-8,-2,-1,-4], [-1,0,0,5,-2,-9,2], [-7,10,-2,-2,-7,-7,-2], [6,4,-3,-3,-1,-9,5], [10,6,5,4,-1,-1,-4], [-8,-4,-2,7,3,9,1], [5,0,3,-6,0,10,-2], [5,-10,7,7,5,2,5], [1,3,4,-10,3,2,-8], [-2,-1,4,-10,-10,-3,-7], [-9,1,6,1,4,0,9], [6,9,10,-4,2,6,10], [0,2,-3,-1,-4,6,-1], [1,-4,-7,-2,3,1,6], [-1,-4,0,-2,-3,4,8], [-8,4,-9,-4,-5,5,-6], [-1,4,6,-9,6,-5,0], [-6,-1,-3,5,-6,4,-7], [6,-10,10,2,3,5,1], [-10,-8,-1,7,-8,-2,5], [3,-2,3,8,4,7,10], [7,-4,8,5,-1,3,5], [4,10,7,0,5,-3,5], [-8,-3,-8,7,-3,-10,1], [9,7,2,3,-7,-3,-3], [-9,-7,-2,9,-2,-4,4], [-4,-7,3,9,5,4,-5], [3,3,4,10,-6,2,5], [-9,2,9,0,-9,2,3], [-6,-7,-1,-1,-7,-10,1], [-6,8,9,-10,-3,-4,8], [4,9,7,-4,4,1,10], [6,6,4,-5,-2,-8,-6], [-8,5,10,-2,1,1,3], [-3,-2,2,-3,0,8,-4], [9,2,6,8,9,8,-1], [5,9,5,-10,10,3,-8], [-4,1,-9,-4,-2,0,-9], [10,7,4,3,-4,-7,-6], [-5,9,-6,-9,-6,-6,4], [9,0,-6,3,-9,-8,-6], [-4,0,4,-5,8,-10,9], [3,-7,5,5,9,-6,-10], [-4,-5,2,9,5,-3,-10], [5,6,0,2,-6,10,0], [-7,-8,-1,10,-10,-3,-8], [-9,6,2,-2,3,7,-9], [-7,-3,-10,-6,-6,9,1], [3,-10,9,2,10,7,9], [-5,9,-9,9,-7,1,-5], [6,-2,3,-3,3,-8,-8], [9,-7,1,-9,-9,-6,-5], [-3,-2,-5,1,0,0,-8], [3,3,-6,-7,3,-8,-2], [10,-9,-8,1,-4,8,6], [-8,3,5,3,-4,-8,0], [-3,3,-9,-7,5,-5,-8], [8,10,-1,9,7,10,-3], [-2,1,10,9,-2,-6,1], [9,4,-6,9,-7,2,4], [7,-8,-6,2,-6,2,-2], [9,-9,0,8,4,0,-9], [-4,-6,-3,6,9,9,9], [-3,-6,-2,-7,6,0,10], [5,-4,-7,0,-3,8,-8], [7,1,5,-2,-7,-7,-7], [4,-3,5,-6,7,-1,-6], [6,-2,-4,4,-9,7,8], [9,4,-3,8,1,7,3], [0,-2,-8,-9,-2,4,10], [-3,6,9,8,-3,-2,10], [-8,-10,7,-8,6,6,-5], [-8,-5,0,9,-9,-1,8], [4,-1,10,1,5,-8,1], [-4,5,4,0,-4,-9,-1], [-9,8,-6,-8,2,-7,-6], [-7,-8,8,9,5,6,9], [7,-9,-3,2,-5,6,1], [0,1,-1,0,-1,-5,0], [3,-9,2,0,5,6,2], [8,-7,-3,3,-8,-5,-4], [10,8,-9,-7,3,2,2], [10,5,3,-2,-6,9,-5], [-10,7,5,-1,-6,3,-6], [-10,-9,-1,-4,-10,-1,-1], [4,7,10,-4,-1,3,1], [-8,-7,0,-6,0,-6,4], [0,2,-4,10,-7,2,9], [8,-8,-1,9,5,-8,7], [1,-10,-8,1,0,-5,-2], [10,9,-10,6,8,9,-3], [1,-3,-8,4,-7,-10,0], [6,-7,-1,4,-1,-2,-5], [8,6,-4,2,-2,-7,-6], [10,-2,7,-10,-6,9,-8], [4,2,9,6,-2,1,4], [0,9,-4,-5,3,-4,-6], [2,4,-4,-10,-9,-1,-1], [4,6,10,2,2,-5,6], [-9,3,-1,-9,-7,3,-10], [4,9,-6,-5,3,-4,-1], [4,9,-10,-7,-8,9,3], [-2,8,0,8,5,5,-7], [-7,9,1,-3,2,9,-8], [-4,-1,-10,6,8,-6,-2], [9,7,4,0,2,8,-4], [4,9,-7,10,10,-10,-4], [0,6,0,-8,-1,-2,1], [-4,3,-5,1,-2,-9,-2], [-7,-5,-8,-5,7,-5,8], [8,1,-10,-8,-9,-10,6], [-8,-3,-2,4,-5,2,-2], [-5,-1,9,0,-6,-8,-5], [-2,-7,-1,-3,7,-9,7], [2,4,2,0,6,2,-7], [7,-3,-1,7,-5,4,-2], [-9,-8,-1,-2,10,-7,-4], [0,-10,10,7,-8,-10,3], [2,8,2,-4,4,0,-7], [9,6,7,-8,10,-8,-10], [-2,-9,-7,0,-2,-9,-7], [-3,8,1,3,7,1,-2], [-9,-2,-2,1,4,0,4], [-9,4,-5,2,-9,7,2], [-2,-9,5,2,-1,4,-5], [2,2,-7,-10,5,-7,6], [5,-7,2,-4,0,-1,-1], [8,-1,2,10,10,-5,4], [0,9,-2,-4,2,-5,-1], [-9,4,-6,1,-7,-7,-3], [4,-1,5,-4,3,-7,2], [-3,9,-5,6,5,2,0], [6,7,-4,9,-9,9,-4], [8,-6,-5,-7,-3,2,7], [-6,-8,1,2,8,5,-7], [5,9,-7,2,-6,-8,5], [0,-2,-7,-5,-9,-7,-7], [-6,5,10,6,0,6,0], [10,4,-6,0,-5,-8,4], [-1,-3,-9,-7,1,-9,6], [-3,-8,-4,-1,1,-7,5], [-4,-6,7,10,7,6,10], [8,7,-1,-8,-10,1,-9], [3,7,1,8,1,-4,6], [-7,1,-3,9,0,10,-7], [-7,-6,8,-7,-6,2,3], [3,0,4,-3,-5,-8,-2], [6,1,2,-3,1,7,9], [3,-6,5,9,-1,5,5], [6,4,-3,6,0,-5,-4], [-1,-4,1,-9,3,3,0], [-2,-7,-8,-2,0,-2,-5], [8,0,-3,1,-4,-3,6], [-1,-7,-9,10,-4,-5,2], [6,-4,-2,-1,-4,4,-2], [3,-2,-7,-1,-9,2,-7], [-9,-8,-8,-10,-7,6,-10], [10,9,-4,1,5,-4,1], [5,10,-9,-3,-3,-6,-10], [10,6,-10,-7,3,8,-2], [-7,10,5,6,-8,-1,5], [-8,-8,-10,-6,6,-8,-8], [-3,-8,9,-1,3,1,4], [-10,-8,-9,8,-1,-10,1], [3,-8,5,1,3,-10,-1], [-8,5,1,9,-9,0,-3], [8,-9,10,-10,-1,-10,-10], [-1,5,-10,-4,-8,-10,8], [-6,9,-8,10,-10,-3,4], [3,-10,2,9,4,1,10], [8,6,8,4,1,4,-9], [3,-10,8,-5,-2,-10,8], [10,-5,-3,7,-1,6,-2], [6,-10,-4,-9,0,8,10], [2,10,-6,6,10,10,-1], [7,-8,4,-10,3,9,3], [1,2,-3,-10,3,10,5], [-5,-8,-6,9,-1,9,-6], [9,-10,9,-6,8,3,-1], [-7,1,-8,0,-10,-4,4], [-10,1,0,3,4,3,10], [10,-3,10,2,7,-4,3], [-3,9,-6,-3,7,0,-6], [-9,-3,0,1,4,1,-4], [6,2,-4,6,0,-6,-4], [7,-5,5,4,-9,6,-6], [-10,-10,4,-2,7,-2,-7], [8,-8,2,-6,10,2,1], [5,-10,-2,1,-10,8,8], [8,6,3,-9,-5,8,-7], [5,2,8,8,0,6,-7], [-4,3,-10,4,-3,4,-1], [9,-3,-8,0,-8,-9,-6], [-5,9,-6,-8,2,3,2], [-1,10,-2,4,10,-9,-8], [-5,-10,8,-7,-5,8,-3], [-10,8,-4,8,4,-2,-7], [-8,4,-1,-10,4,3,-4], [9,-1,1,-9,9,4,-1], [-7,-7,9,0,6,-3,-7], [-2,-4,-8,3,9,9,-4], [3,9,9,5,-9,8,7], [-3,-4,-9,1,-2,4,9], [-5,2,3,-6,-10,-9,3], [-3,10,5,7,2,1,0], [3,-10,9,-1,2,-2,-4], [3,3,-6,-1,-6,3,-6], [8,6,-9,7,-3,-4,2], [-5,-1,4,-1,5,-1,-7], [-8,8,0,-7,-8,-10,1], [-1,0,10,2,8,-5,8], [-2,-2,-8,-4,9,-8,-4], [-10,-8,-1,8,2,0,2], [-10,7,-4,3,-4,-6,1], [1,2,-7,-3,-9,-7,2], [-3,10,2,-6,-5,9,-1], [0,4,-9,9,9,7,-6], [5,2,-5,-3,-10,-9,10], [-10,9,3,2,5,-5,3], [-2,5,10,-10,5,3,-6], [-9,1,0,5,8,10,-6], [2,-6,-5,6,2,9,3], [-4,9,-8,-2,0,-10,0], [4,6,-9,-3,-2,-4,2], [-8,-7,2,10,9,-5,4], [-5,4,-5,6,6,2,-1], [3,10,-3,-6,-10,-7,-1], [8,6,-1,-1,9,1,-5], [4,-8,-2,-9,-6,3,-1], [8,-8,-7,-6,-10,3,-6], [-1,6,7,-2,6,-10,1], [5,1,6,-6,-5,-10,-8], [-3,6,9,-3,-4,-9,-3], [3,8,8,-10,-7,-1,3], [10,0,-7,-4,7,-8,9], [2,-9,2,-9,-8,10,8], [-9,8,-3,5,1,-2,9], [-7,4,-7,10,-2,5,-1], [10,-1,-5,3,1,-1,0], [10,3,5,-10,10,7,-1], [2,-5,0,3,4,-7,-3], [-5,-6,-9,7,-1,-9,9], [8,6,-8,-10,3,1,8], [0,1,-1,5,4,0,10], [1,3,-1,-9,9,-6,-3], [-7,0,1,8,7,8,4], [1,8,0,-1,9,-2,4], [-1,-8,-8,-3,-10,3,-10], [7,0,-8,3,0,-6,-4], [5,-3,-10,-10,8,-8,8], [-4,-2,7,-7,0,-4,9], [10,2,5,-2,-4,-7,-2], [1,6,1,1,-1,-6,6], [-1,-7,4,-1,-1,-6,-6], [2,7,-1,1,-2,7,10], [1,-6,2,-3,9,2,-4], [1,10,6,-8,6,7,1], [6,5,-3,-7,-6,8,-2], [6,-1,-10,-4,5,3,3], [10,1,4,-1,7,10,-4], [7,2,-6,-9,6,-8,-6], [-5,8,0,-3,7,5,-10], [-2,0,0,8,-9,-4,0], [9,-8,-6,1,6,10,1], [-6,-7,3,-9,-9,6,-4], [9,-2,-2,6,4,9,10], [8,1,0,-4,-5,-9,10], [-8,-2,6,9,0,6,6], [10,10,4,1,9,-6,4], [1,9,-1,2,10,9,10], [2,-9,-6,-10,0,1,-1], [-2,-1,-3,4,-5,6,-6], [-3,7,9,5,8,9,-2], [-5,5,8,10,8,7,9], [-2,5,-10,3,4,10,-2], [-10,-1,-6,10,6,-1,6], [7,4,-1,-2,9,2,10], [5,-8,-7,4,10,-8,-3], [2,-2,6,4,5,-1,-5], [8,2,-4,6,6,1,2], [-9,2,-3,7,6,2,3], [2,4,1,-2,-8,-10,-2], [-6,-1,5,9,10,5,-1], [-10,9,10,2,-7,-3,-8], [2,-2,2,9,-2,0,-1], [-6,-1,6,7,-8,0,-8], [-4,-1,0,7,1,-4,-2], [10,-6,2,2,10,-5,3], [8,-10,-4,3,2,4,10], [-9,3,1,-5,-10,-6,-5], [9,-3,-2,-2,-8,-1,5], [-5,3,-5,2,3,10,-2], [5,-10,0,-7,1,8,-6], [5,-6,-3,3,-7,0,7], [9,4,1,1,-7,-8,-6], [2,5,-5,-10,1,0,-3], [0,8,9,-5,2,8,10], [9,10,10,2,2,7,-6], [-4,-2,-6,4,10,4,5], [-8,-5,-8,4,8,-10,-6], [-3,-4,7,-1,-10,7,6], [-7,-5,-2,0,-6,-4,7], [-7,5,2,-7,-5,1,-3], [-6,0,8,-4,10,-4,-5], [-10,-5,-8,-1,5,4,6], [-7,-7,2,-5,8,0,2], [9,-7,-7,2,-4,-1,4], [10,-2,-7,-9,7,-5,0], [9,-9,9,7,0,2,5], [2,6,3,10,3,1,8], [7,8,-8,0,-6,-4,1], [-3,7,-10,4,5,4,1], [-9,0,-7,-10,-8,8,9], [3,-8,9,-5,2,-4,1], [-10,-1,5,4,6,-5,4], [-6,-2,-4,8,-1,-8,5], [-7,-7,-7,-4,-7,-4,-8], [-3,-10,0,7,-9,1,-4], [-7,9,-8,3,8,8,-2], [-2,-10,-5,7,-10,-10,-9], [7,-2,9,1,3,4,6], [10,-9,-10,-4,1,6,0], [-4,10,1,9,-7,-4,-8], [9,2,4,-8,-5,-5,1], [-2,-3,-9,1,-6,-4,3], [3,-3,-3,6,2,4,7], [5,-3,-9,2,10,8,-6], [-9,-4,2,0,-10,-8,-9], [3,9,1,3,-8,-5,3], [-2,-6,10,1,9,-4,-8], [-10,3,-10,2,3,8,1], [1,-3,-1,-4,0,-5,2], [-7,5,10,8,2,-7,-3], [-5,-6,9,-3,-10,-8,5], [1,9,3,-4,-5,-2,-6], [1,9,-1,-1,-10,-3,-3], [10,4,3,7,-1,-2,-9], [-4,-7,1,-3,5,6,8], [8,10,-2,4,-6,-5,4], [2,-10,-3,-9,5,6,9], [-3,8,2,-1,-9,0,-2], [1,-6,-8,-1,2,1,-2], [-3,3,5,-4,10,-9,-10], [-8,0,-2,5,-10,0,1], [6,-5,-1,-6,0,0,-10], [-10,0,3,1,0,7,6], [7,-6,1,-6,9,3,2], [4,-8,3,-3,-4,-10,9], [-2,10,-8,-1,1,8,-5], [-3,7,8,-1,-2,3,-3], [-7,-6,-5,4,6,-4,3], [2,9,-1,-1,3,-4,0], [-5,-1,-10,0,-6,-3,-7], [6,1,7,3,1,-9,-3], [9,-7,0,-8,6,10,-3], [-8,0,-3,-2,3,8,3], [-9,-4,8,-2,0,7,-10], [-6,7,-6,0,4,-8,6], [6,-7,0,4,-2,5,-4], [4,-5,5,-9,-7,8,3], [8,-2,-9,-2,9,-5,8], [5,1,10,10,-10,-6,-9], [10,3,9,-4,1,-4,0], [-4,-2,5,2,-7,9,-3], [2,-5,3,8,8,2,9], [-1,-4,10,-4,0,4,9], [5,7,-3,-10,-3,-8,7], [4,10,6,7,1,-3,3], [4,-3,-8,9,-9,5,4], [-8,1,-7,-9,4,-2,-9], [0,5,-9,-8,0,1,-8], [-5,-5,3,6,2,-10,-3], [-4,-1,2,4,7,-4,-7], [8,1,-5,9,1,1,1], [-2,7,9,5,-1,-4,7], [-8,6,8,-9,-7,-5,2], [-10,9,2,-8,-10,5,-5], [1,7,6,-2,9,-8,1], [9,8,8,9,-1,-6,-3], [9,-3,-1,6,7,-3,7], [-8,0,-2,10,-2,-2,-5], [-10,0,9,5,10,-7,-7], [-8,-6,-6,-1,-9,-4,-7], [-5,8,-6,-1,10,-3,2], [3,-8,-6,10,10,-3,0], [-8,6,4,0,-1,-8,-1], [9,2,2,-5,8,-8,-1], [9,-9,-6,8,-10,-10,5], [-6,-3,-7,5,8,-10,6], [-3,-8,-2,-9,1,-6,7], [-3,-7,-1,2,1,7,0], [4,4,-1,8,-9,-7,6], [0,-2,4,0,9,-10,0], [1,-1,5,-2,2,10,-6], [2,5,2,5,-6,5,8], [-6,-1,-3,6,0,2,10], [-1,0,5,9,-4,-5,-3], [1,-8,-4,-3,5,3,-4], [1,9,-7,-9,-10,4,3], [-5,6,-7,-10,7,-5,1], [5,1,-4,-8,-3,10,-1], [-10,8,4,-9,-2,3,-8], [9,6,9,5,8,-6,1], [5,-5,-7,-8,-10,0,-3], [4,-9,-10,2,10,-6,-7], [7,-3,2,-6,0,6,-4], [5,5,1,2,10,7,-7], [1,8,7,8,-3,-1,-9], [-7,9,7,1,-10,7,8], [-3,2,-6,3,3,-1,-7], [0,-2,6,6,3,-9,-10], [4,-5,7,-8,-6,9,3], [9,-10,3,8,6,-2,3], [-7,-6,10,1,-6,-6,1], [10,2,-3,-10,2,-5,10], [10,9,-7,-10,2,8,-6], [-1,6,-5,1,-2,0,-5], [-5,-4,3,3,0,-8,-2], [-4,5,7,6,2,-7,3], [-10,2,4,-4,6,6,0], [2,6,0,3,1,-6,6], [-3,1,-7,2,-9,4,1], [5,7,-3,4,6,-5,-1], [-9,4,9,-10,-7,10,6], [-1,1,-9,-6,-4,-3,-5], [1,-6,2,8,-3,-3,-8], [2,-8,-8,-10,4,-9,-1], [-10,-2,2,-5,5,2,-1], [8,-1,-7,-1,-9,-4,7], [-10,6,-7,-10,6,7,7], [-1,-6,9,-10,-2,-4,-8], [0,5,-9,-10,-7,-5,-7], [9,2,1,-1,0,-4,-5], [3,1,-4,-8,-3,-9,7], [-10,-9,-1,7,-2,-1,-7], [-10,7,2,2,8,2,-7], [2,2,10,-5,-10,6,8], [5,-9,-8,1,-10,-1,6], [0,-5,-3,10,8,-9,-6], [7,-3,2,-10,-8,-7,7], [9,5,6,1,0,0,10], [3,3,-8,7,2,6,4], [2,10,-3,7,4,-4,-8], [-4,6,7,4,0,8,7], [-5,5,8,-7,-9,-2,-1], [-3,-6,-8,-6,4,2,-1], [5,-7,-5,5,8,-3,-10], [6,-1,0,-8,10,7,10], [6,10,3,-7,-8,-6,-2], [-9,-10,4,6,3,-8,6], [-1,8,-1,-2,-10,-6,-1], [-2,2,6,-7,-5,-4,8], [4,-8,5,2,1,-8,5], [8,1,-8,-6,-4,6,7], [8,1,9,3,8,-7,-5], [-8,10,-6,-7,-6,-2,-5], [-5,0,6,-3,5,10,-6], [10,-7,3,-9,-7,-6,-5], [1,-7,-1,4,3,-10,-4], [7,5,2,7,9,-2,-4], [4,-4,4,9,-5,-10,-9], [2,-1,5,1,9,-5,4], [-7,4,-5,-8,-10,6,6], [4,-7,-10,6,-5,-6,-1], [-4,-6,7,4,-8,8,-5], [7,-2,-4,-4,-5,-7,-2], [10,3,-6,3,10,6,-8], [4,1,7,-4,-1,10,-3], [8,0,6,-5,1,7,-9], [-5,-2,8,7,4,1,9], [-5,0,7,9,-3,5,0], [-5,-4,1,-4,-3,-1,7], [-7,5,8,3,-7,-1,-9], [5,-4,4,-2,5,-1,-2], [-7,-3,7,7,1,6,8], [-1,-1,-10,7,-6,7,4], [8,6,8,9,-8,-9,5], [-8,0,8,0,-10,10,7], [-10,2,-9,4,6,-9,-5], [-3,-3,9,8,9,-3,-5], [6,7,10,2,9,6,10], [-1,5,-5,2,2,-4,-7], [5,2,-3,-6,-4,1,7], [5,6,10,-3,8,-5,2], [-7,-6,2,-4,9,10,-3], [-9,3,3,-3,-6,7,-3], [8,8,-7,9,5,-2,-8], [1,-3,-5,-2,-4,0,6], [10,3,6,1,-10,-3,-7], [2,-1,-10,7,-3,9,4], [4,-2,-4,0,-8,5,5], [-3,0,-3,-3,5,-1,3], [5,6,3,7,10,-9,-6], [-5,7,6,7,4,-3,7], [-8,8,-9,4,6,1,2], [-8,-7,-10,2,-5,-2,4], [-2,0,10,4,2,-1,6], [-10,-5,-4,-2,0,10,8], [7,0,7,5,6,-2,-2], [8,-2,5,-10,10,-10,-7], [10,-2,-5,0,-10,3,9], [2,3,10,2,-10,7,-8], [8,-7,5,-9,1,1,-7], [1,1,8,3,9,9,8], [10,10,-8,7,-6,10,10], [-2,-10,-5,-8,-8,6,-6], [-5,-6,3,-8,-2,-5,-5], [-1,-1,3,5,7,2,2], [4,-5,-5,-6,3,5,7], [-1,7,-2,-6,-4,-4,-10], [9,10,2,-6,-3,-8,-7], [3,0,8,9,0,-5,4], [-9,4,-6,10,-7,6,10], [1,-8,-10,-6,5,-1,-6], [-1,-7,0,0,-6,8,-8], [-7,-7,-6,9,-9,-9,6], [8,-2,-2,6,10,6,7], [-1,6,8,-9,8,7,-3], [8,10,-4,9,1,6,9], [3,8,-2,-7,-7,-1,-8], [-6,9,-8,-4,-6,0,2], [-2,-6,-9,7,5,1,9], [-5,1,-7,-1,-10,8,7], [-7,8,-1,1,-10,-2,-9], [6,-5,3,-3,-2,-1,-4], [9,-5,9,10,-1,-10,9], [4,-1,5,3,-7,9,-8], [8,-2,6,-5,3,-2,2], [1,-1,5,4,3,7,-6], [-10,-7,5,4,3,-2,-10], [-4,8,-8,3,-5,-1,4], [-7,-7,0,-2,-4,-7,5], [3,3,7,-7,-10,-9,6], [0,9,7,8,10,-9,6], [-7,1,-9,1,-5,-4,-2], [-1,10,-9,-5,-3,3,9], [-3,2,6,-3,1,-7,-3], [4,10,8,3,2,7,-1], [3,-3,3,-10,-3,8,10], [-3,7,8,-5,3,4,-4], [-5,2,4,-4,-4,9,10], [1,-1,1,-2,4,5,5], [2,9,10,8,-4,-10,2], [3,-9,2,-3,-7,-3,6], [0,-2,4,-6,10,1,6], [2,-3,5,7,0,8,5], [9,7,4,5,-10,8,8], [6,9,8,6,-8,-8,2], [2,-8,3,6,7,10,-9], [9,3,-4,-9,-10,2,2], [-1,5,1,3,6,7,7], [-10,6,-8,10,5,10,-7], [-10,8,2,2,2,-1,2], [1,7,10,-6,-1,-8,-3], [2,-9,8,-4,-9,4,-10], [7,4,-9,7,5,10,9], [4,8,-8,-2,-7,-3,-9], [-5,0,7,-1,-8,-9,7], [-10,-7,-7,1,3,7,-5], [-9,-5,0,-2,-8,2,-2], [9,9,10,5,-6,1,2], [6,10,-2,6,-6,-2,-1], [-4,-5,4,-10,-3,0,9], [-9,-5,-2,-2,7,-7,3], [5,4,-7,7,-5,6,2], [5,-6,-6,-4,-7,-5,-8], [-10,-9,-10,-1,-6,-1,8], [2,-10,2,-6,8,-9,-3], [-8,5,5,-2,2,-7,10], [-3,-3,6,3,-9,-8,3], [2,-6,3,1,8,-8,9], [-3,-7,2,0,-2,10,-8], [9,-9,-2,-8,-4,5,-8], [-5,-4,-10,-5,-1,7,10], [9,-1,8,-8,4,-2,4], [7,0,-2,3,6,2,-8], [-9,7,6,0,3,7,-2], [10,7,-8,-7,-10,1,8], [-9,9,9,1,-7,9,6], [4,8,-8,-9,2,-1,-1], [-8,7,7,-2,-3,0,9], [8,-3,-1,0,-9,5,6], [5,-10,-8,-1,8,-2,-3], [-3,-5,10,5,-5,-8,-3], [10,1,-2,-3,8,-8,-10], [3,9,-9,0,10,0,2], [4,1,-5,-6,-9,-1,6], [-8,4,1,10,1,-3,6], [-7,5,8,-3,10,4,5], [5,-9,10,-3,-3,-2,-8], [4,-10,-2,-6,10,8,9], [-8,5,9,-2,-4,-4,-3], [7,-4,1,-9,-6,-6,-5], [-9,10,-2,4,-4,-8,2], [-4,7,1,-2,-4,-9,10], [-10,-8,10,-7,3,5,3], [7,6,-10,-5,-5,-7,-5], [3,9,6,9,-6,-5,-3], [2,-6,-4,3,-2,-2,6], [-3,-6,4,8,3,0,5], [-5,1,-8,-5,6,5,3], [-7,-3,1,7,2,1,6], [-8,0,8,-8,10,-6,-2], [-4,-6,-10,5,10,-2,10], [8,6,5,9,-2,-7,2], [10,-6,7,-10,1,3,4], [2,-6,-8,-2,2,1,9], [8,-9,-3,-6,-4,6,-3], [7,-2,-10,7,0,-3,-10], [8,1,3,3,-4,2,-6], [-1,-10,9,1,8,10,0], [-6,9,-10,-9,-6,10,-5], [-4,0,-5,3,-9,1,4], [4,-3,-5,-6,0,8,5], [10,5,-6,-9,6,-4,6], [4,7,1,-1,0,-4,7], [-8,-2,-1,-7,7,4,9], [10,-7,-4,2,7,-9,7], [-2,10,-6,-6,-3,1,5], [7,-9,-9,5,-4,5,-5], [-1,2,-5,-5,-8,-1,-3], [-5,-9,4,4,6,-4,1], [-5,-1,-2,5,2,-3,-1], [-5,9,2,-2,7,-6,-1], [-1,-10,-7,6,-9,9,9], [-4,6,-1,-10,10,2,5], [3,7,-4,5,3,-9,2], [4,4,-7,4,0,-9,8], [6,8,-6,-1,10,2,-4], [-3,-6,-7,6,0,-10,8], [-5,6,-10,10,-9,-3,-6], [3,3,-7,2,2,6,0], [2,-3,-7,-10,6,3,-10], [-5,4,-3,-1,8,0,-6], [10,-9,-2,-9,1,-3,2], [7,8,0,-2,-3,0,5], [-6,6,9,-4,1,0,-6], [-3,2,5,-5,3,4,9], [2,-5,-9,-7,0,-7,4], [-9,1,-7,7,0,-1,-3], [9,-8,-10,-8,-5,5,-10], [-9,-5,-4,4,-10,6,-5], [10,-4,-10,-2,-7,7,-2], [3,-9,1,-9,-5,5,0], [-9,3,8,1,9,-2,8], [2,0,-10,2,-9,4,-9], [1,-1,7,7,5,10,-8], [1,0,5,-10,2,2,-1], [-8,4,5,-5,2,-9,5], [9,10,3,-7,8,7,7], [4,-3,-10,2,6,-5,-8], [-2,-4,7,-6,10,-2,-3], [7,0,-1,5,-7,5,3], [-8,3,5,8,5,-7,8], [3,-5,-2,6,2,2,-6], [-10,-7,4,-1,1,-8,-8], [10,-4,9,6,10,-6,6], [-10,-1,2,8,0,-3,-8], [6,2,4,1,7,2,-3], [7,-5,6,6,1,9,0], [-10,6,8,-4,7,0,8], [10,3,7,0,10,8,-10], [2,-9,-6,-6,-6,-3,-7], [-7,9,1,6,8,10,-7], [-10,0,-8,-1,4,8,1], [-2,5,-10,6,-7,3,3], [1,-1,-4,3,7,-7,0], [8,2,3,-2,6,-1,-9], [5,0,0,-7,-1,-9,9], [9,-7,-4,1,-9,-2,-10], [-9,-10,9,-9,-9,4,-7], [8,6,-3,2,-7,1,1], [-10,-4,-6,-10,-5,-4,-8], [-7,5,-7,10,-9,-9,7], [-3,10,-8,-9,-9,4,8], [-10,1,-6,5,7,-6,10], [10,-6,5,-1,-8,3,-5], [-3,2,-3,10,-4,10,-7], [4,4,-9,-7,7,-2,3], [10,2,-6,-1,8,10,1], [0,2,9,-7,1,10,2], [5,0,-8,-7,-10,8,4], [10,7,-4,9,7,6,8], [2,-3,-1,2,9,8,-5], [10,-2,-2,-7,9,-7,0], [0,5,-7,-5,0,-1,-3], [3,1,6,0,-2,-5,0], [5,-2,-10,7,4,5,5], [-2,-10,4,7,10,-7,8], [-7,-2,-1,-8,-3,0,7], [-4,3,-10,1,1,1,10], [1,4,-4,-7,0,1,-8], [3,4,-2,10,-10,7,6], [4,-5,-9,2,10,-1,-2], [-7,6,-5,6,-8,-4,-6], [-3,9,-1,-7,0,5,-2], [-7,0,8,-2,-2,-6,-5], [4,0,1,-7,8,4,0], [-6,8,9,0,-4,-7,-3], [-7,-1,-5,-6,7,1,7], [-4,-9,-1,8,-10,0,3], [7,-1,10,-7,2,-3,-4], [-9,5,-5,-6,9,-1,0], [10,4,5,-9,3,2,-5], [5,-10,9,5,7,0,3], [3,-3,0,-10,0,-6,0], [-8,3,2,-5,-5,2,-1], [-4,-10,-10,10,-4,4,3], [6,1,-9,5,6,8,9], [-8,2,3,5,7,7,5], [-4,0,7,-3,6,-8,-5], [6,9,8,7,9,0,-9], [-9,9,-7,9,-7,-10,0], [-1,7,6,-6,4,-6,6], [-9,-9,-7,8,-6,9,-3], [5,-7,-1,-8,3,6,3], [-1,-2,-10,2,-10,10,3], [-5,-6,3,2,6,5,-7], [-8,1,8,-1,7,-2,3], [1,-6,-4,-8,2,2,6], [3,0,1,6,-1,-1,-2], [-10,0,1,8,2,0,3], [6,-5,-6,7,9,-9,-10], [-10,-10,-10,-5,-5,6,0], [8,-4,-8,1,-10,8,-3], [7,-3,3,-6,1,5,-6], [8,10,10,7,6,-3,0], [4,-6,6,-3,6,0,7], [9,-7,-3,10,-2,-2,-4], [4,-1,-4,-8,-3,7,-7], [-8,2,9,-4,0,-5,-7], [-2,9,7,7,3,7,-5], [8,5,10,-5,-8,-6,-3], [0,6,-10,-5,-6,-7,10], [-9,-2,3,-10,5,-9,-1], [9,-4,-6,-10,10,7,8], [-7,-4,-1,-1,4,7,-7], [-9,-3,-5,-2,-7,-5,7], [-6,8,4,-3,10,-7,9], [-10,-2,4,1,8,-2,-3], [3,-3,-7,-2,9,8,7], [8,9,8,9,9,9,-1], [-3,10,6,-4,3,1,-4], [5,1,1,5,-10,-4,-2], [-7,7,3,2,1,-5,0], [0,-4,-10,-2,9,-3,-3], [2,8,-7,-4,5,7,-9], [4,-4,4,4,0,5,5], [5,-2,2,-3,9,3,8], [4,3,-8,3,-9,4,6], [0,9,7,8,8,1,0] ]; for(i=1,#V, print1(i,":"); my(L=hyperellratpoints(Polrev(V[i]),16383)); print(apply(affine2proj,L))); } pari-2.17.2/src/test/in/factorff0000644000175000017500000000377014567450071015075 0ustar billbilldo(f,p,T)=centerlift(lift(polrootsmod(f,[p,T]))); do(x^3+x^2+x-1,3,t^3+t^2+t-1) t = ffgen(3^3,'t); do((x^3+x^2+x-1)*t^0, t.p, t.mod) polrootsmod(x^4+1,[2,y^2+y+1]) t = ffgen(('t^2+'t+1)*Mod(1,2)); f=x^12+t*x^10+x^6+(t+1)*x^2+1; factormod(f) factormod(f,,1) \\ #1241 polrootsmod(x^2 - x - ffgen(v^2+Mod(1,3))) \\ #1350 polrootsmod(2*x+1,[2,y]) a=ffgen(2^12,'a);factor(2*x^2+x+a) a=ffgen([3,3],'a);factormod((x^27-x)/(x-a))[,1] check(p)= { print("check ",p); a = ffgen([p,3],'a); V = [0*x*'a,'a*x^0,x*'a-1,x^2-'a^2,x^2+x+'a,'a*x^2+1,'a*x^3+x+1]; for(i=1,#V, print(factormod(V[i],a)); print(factormod(V[i],a,1)); print(liftall(factormod(V[i],[a.p,a.mod])))); } check(2) check(3) check(nextprime(2^100)); t = ffgen(5^4,'t); factor(x^24-t^0) factormod(Pol(0),t) factormodSQF(Pol(0),t) factormod(Pol(1),t) factormod(Pol(1),t,1) factormodSQF(Pol(1),t) factormodDDF(Pol(1),t) factormod(x^4-t,t) factormod(x^4-t,t,1) factor(5*x^2+x+t) p = nextprime(2^96); a = ffgen(p^3,'a); factor(p*x^2+x+a) P=(x-1)*(x-a)*(x-a^2)*(x-a-1)*subst(ffinit(p,2),x,x+a)*ffinit(p,4); polrootsmod(P) factormod(P) factormod(P,,1) factormodDDF(P) factormodSQF(P) check(P)=my(V=polrootsmod(P));for(i=1,#V,if(subst(P,x,V[i])!=0,error(P)));#V; a=ffgen([3,2],'a);check((x^2+a*x)^3*(x+1)) a=ffgen([2,2],'a);check((x^2+a*x)^2*(x+1)) a=ffgen([3,107],'a);check(x^107+2*x^3+a^0) a=ffgen([3,37],'a);check(subst(x^37+x^3+x^2+2*x+2,x,x+a)) { my(s); a=ffgen([2,2],'a); forvec(v=vector(6,i,[0,3]), P = x^7+Polrev([(x\2)*a+x|x<-v]); s += check(P)); s } { my(s); a=ffgen([2,3],'a); forvec(v=vector(4,i,[0,7]), P = x^6+Polrev([(x\4)*a^2+(x\2)*a+x|x<-v])*x+1; s += check(P)); s } { my(s); a=ffgen([3,2],'a); forvec(v=vector(4,i,[0,8]), P = x^6+Polrev([(x\3)*a+x|x<-v])*x+1; s += check(P)); s } a=ffprimroot(ffgen([2,10],'a));check(factorback(vector(200,i,x-a^i))) a=ffprimroot(ffgen([3,7],'a)); check(factorback(vector(1000,i,x-a^i))) a=ffprimroot(ffgen([nextprime(2^100),2],'a));check(factorback(vector(200,i,x-a^i))) pari-2.17.2/src/test/in/alggroup0000644000175000017500000000671614676526175015140 0ustar billbill\\examples from docu nf = nfinit(y^2+1); PR = idealprimedec(nf,5); #PR hi = []; hf = [PR, [1/3,-1/3]]; A = alginit(nf, [3,hf,hi]); algsplittingfield(A).pol K = nfsplitting(x^4+x+1); gal = galoisinit(K); al = alggroupcenter(gal,,&cc); algiscommutative(al) #cc[3] \\end examples \\test ordering in simpledec print("ordering"); Sn(n) = [Vecsmall(numtoperm(n,i)) | i <- [0..n!-1]]; D2n(n)= { [[vectorsmall(2*n,i,if(i==n,1,i==2*n,n+1,i+1)), vectorsmall(2*n,i,if(i==1,n+1,i==n+1,1,2*n+2-i))],Vecsmall([n,2])]; } testordering(al)={ my(jac, ss, dec); jac=algradical(al); if(jac==0, ss=al, ss=algquotient(al,jac)); dec=algsimpledec(ss)[2]; print(apply(algdim,dec)); print([#algcenter(x) | x<-dec]); }; setrand(1); {for(n=1,4, print("S",n); al = alggroup(Sn(n),7); print(algisassociative(al)); testordering(al); );} {for(n=1,3, print("S",n); al = alggroup(Sn(n)); print(algisassociative(al)); testordering(al); );} {for(n=4,16, print("D",2*n); al = alggroup(D2n(n),691); if(n<10,print(algisassociative(al))); testordering(al); );} {for(n=4,12, print("D",2*n); al = alggroup(D2n(n)); if(n<10,print(algisassociative(al))); testordering(al); );} \\alggroup print("alggroup"); K = nfsplitting(x^3-x+1); gal = galoisinit(K); al = alggroup(gal) algissemisimple(al) alggroup([Vecsmall([2,1]),Vecsmall([1,2])]); alggroup([Vecsmall([1,2])]); alggroup([Vecsmall([1,2,3]), Vecsmall([1,3,2])]) gal = galoisinit(nfsplitting(x^4+7)); alggroup(gal); gal = galoisinit(nfsplitting(x^6+7)); alggroup(gal); \\alggroupcenter {for(n=1,5, print("S",n); al = alggroupcenter(Sn(n),7); print(algisassociative(al)); print(algiscommutative(al)); print(algdim(al) == #algsimpledec(al)[2]); );} {for(n=1,4, print("S",n); al = alggroupcenter(Sn(n)); print(algisassociative(al)); print(algiscommutative(al)); print(algdim(al) == #algsimpledec(al)[2]); );} conjD2neven(n)=2+(n-2)/2+2; conjD2nodd(n)=1+(n-1)/2+1; conjD2n(n)=if(n%2,conjD2nodd(n),conjD2neven(n)); firstprime1mod(n) = { p = 2; while(p%n!=1, p=nextprime(p+1)); p; } {for(n=3,20, print("D",2*n); p = firstprime1mod(2*n); al = alggroupcenter(D2n(n),p); print(algdim(al) == conjD2n(n)); print(algisassociative(al)); print(algiscommutative(al)); print(algdim(al) == #algsimpledec(al)[2]); );} {forprime(p=5,30, print("D",2*p); al = alggroupcenter(D2n(p)); print(algdim(al) == conjD2n(p)); print(algdim(al) > #algsimpledec(al)[2]); );} alggroupcenter(Sn(3),0); \\ #2525 testdec(al,dec) = { my(quo,proj,lif,z,e); z = algrandom(al,5); print("testing decomposition."); for(i=1,#dec, [quo,proj,lif] = dec[i]; if(proj*algsqr(al,z) != algsqr(quo,proj*z), print("not alg hom: i=", i);); if(proj*lif != matid(algdim(quo)), print("map is not a lift of proj: i=",i) ); e = lif*vectorv(algdim(quo),j,j==1); if(algsqr(al,e)!=e, print("lift of 1 is not an idempotent: i=", i);); ); }; \\Bill: random slow cases G=galoisinit(x^24-24*x^22+253*x^20-1540*x^18+5984*x^16-15488*x^14+27026*x^12-31448*x^10+23540*x^8-10528*x^6+2416*x^4-192*x^2+1); al = alggroup(G); setrand(2); dec=algsimpledec(al,1)[2]; testdec(al,dec); setrand(8690); dec=algsimpledec(al,1)[2]; testdec(al,dec); setrand(1294); dec=algsimpledec(al,1)[2]; testdec(al,dec); \\bad inputs alggroupcenter(['x,'y]); alggroupcenter('x,1); \\Bill's bug alggroup("a"); alggroup(["a"]); alggroup(["a", "b", "c"]); alggroup([Vecsmall([1]), Vecsmall([1,2]), Vecsmall([1,2,3])]); alggroup([Vecsmall([1]), Vecsmall([2,3]), Vecsmall([1,2,3])]); pari-2.17.2/src/test/in/quaddisc0000644000175000017500000000017614567450071015075 0ustar billbillf(a,b)= { forfactored(d = a, b, D=quaddisc(d); if (D != quaddisc(d[1]), error(d)); print1(D," ")); } f(-100,0) f(1,100) pari-2.17.2/src/test/in/bnrisgalois0000644000175000017500000000040614567450071015610 0ustar billbillK=bnfinit(a^4-3*a^2+253009);B=bnrinit(K,9);G=galoisinit(K); S=vecsort(subgrouplist(B,3)); map=Map();for(i=1,#S,mapput(map,S[i],i)); [H|H<-S, bnrisgalois(B,G,H)] M=bnrgaloismatrix(B,G) [H|H<-S, bnrisgalois(B,M,H)] [[mapget(map,bnrgaloisapply(B,m,s))|s<-S]| m<-M] pari-2.17.2/src/test/in/contfrac0000644000175000017500000000115414567450071015074 0ustar billbillcontfrac(1,[],-1) contfracpnqn(Vecsmall([])) contfracpnqn([]) contfracpnqn([],0) contfracpnqn([],1) contfracpnqn([2]) contfracpnqn([2],0) contfracpnqn([2],1) v=[1,2,3]; contfracpnqn(v) contfracpnqn(v,0) contfracpnqn(v,1) contfracpnqn(v,2) v=[1,2,3;4,5,6]; contfracpnqn(v) contfracpnqn(v,0) contfracpnqn(v,1) contfracpnqn(v,2) s=exp(x); contfracinit(s,0) contfracinit(s,1) contfracinit(s,2) e=contfracinit([]) contfraceval(e,1) e=contfracinit(s) contfraceval(e,1,10) contfraceval(e,1, 8) contfraceval(e,1, 6) contfraceval(e,1) contfracinit([1,2,3]) contfracinit(Pol(0)) contfracinit(1); contfracinit(x/(3*x^2+2*x+1),3) pari-2.17.2/src/test/in/fflog0000644000175000017500000000210214676526175014376 0ustar billbilldefault(parisize,"10M"); \\ 8M overflows test2(p)= { ffgen(x*Mod(1,p)); g = ffprimroot(ffgen((x+1)*Mod(1,p)), &o); print([g, o]); fflog(g^17, g, o); } test2(2) test2(3) test2(precprime(1<<32)) test2(nextprime(1<<64)) t = ffgen(7^4); fflog(t^6,t^2) t = ffgen(11^5)^0; fflog(t, t, 1) t = ffprimroot(ffgen(2^61)); fflog(t^1234567891012345678,t) t = ffprimroot(ffgen(2^65)); fflog(t^1234567891012345678,t) t = ffprimroot(ffgen(3^23)); fflog(t^12345678910,t) t = ffprimroot(ffgen(3^33)); fflog(t^2739979050900541,t) t = ffprimroot(ffgen(5^23)); fflog(t^1234567891012345,t) t = ffprimroot(ffgen(5^17)); fflog(t^123456789101,t) test(P,p,ord)= { my(a,b,u,l); a=ffgen(P*Mod(1,p),'a); b=ffprimroot(a); u=random(a); l=if(ord,fflog(u,b,ord),fflog(u,b)); b^l==u; } test(x^2+1,1073742623) test(x^2+1,1152921504606849707) test(x^4+699*x^2+107,1129) test(polcyclo(5),1073749723) test(polcyclo(7),1073741833) test(ffinit(5,24),5,5^24-1) p=2^64+13; g=ffprimroot(ffgen(p^2), &o); a=2*g^0; g^fflog(a,g,o) == a v=[I,-1,Mat(1),matid(2)/2]; for(i=1,#v, print(iferr(fflog(a,g,v[i]),E,E))); pari-2.17.2/src/test/in/gcdext0000644000175000017500000001462214760123736014557 0ustar billbill{ a=[0,0*x,O(5^3),2,2+O(5^3),x]; for(i=1,#a, for(j=1,#a, print(gcdext(a[i],a[j])))); } gcdext(-1/3*x - 5/9,-x - 5/3) z;T; FF=Mod((O(2^4)*T^3+O(2^4)*T^2+O(2^4)*T+O(2^4))*z^7+((2+2^3+O(2^4))*T^3+O(2^4)*T^2+(1+2+O(2^4))*T+(1+2^2+O(2^4)))*z^6+(O(2^4)*T^3+O(2^4)*T^2+O(2^4)*T+O(2^4))*z^5+((1+2+2^3+O(2^4))*T^3+(1+2+2^2+2^3+O(2^4))*T^2+(2+2^3+O(2^4))*T+(1+2^2+2^3+O(2^4)))*z^4+(O(2^4)*T^3+O(2^4)*T^2+O(2^4)*T+O(2^4))*z^3+((2+2^2+2^3+O(2^4))*T^3+(1+2^2+2^3+O(2^4))*T^2+O(2^4)*T+(1+2+2^2+2^3+O(2^4)))*z^2+(O(2^4)*T^3+O(2^4)*T^2+O(2^4)*T+O(2^4))*z+((1+2^3+O(2^4))+(1+2^2+2^3+O(2^4))*T+(2+2^2+2^3+O(2^4))*T^2+(1+2+2^3+O(2^4))*T^3+O(T^20)),(1+O(2^4))*z^8+(1+O(2^4))); GG=Mod((O(2^4)*T^3+O(2^4)*T^2+O(2^4)*T+O(2^4))*z^7+((2+2^3+O(2^4))*T^3+O(2^4)*T^2+(1+2+O(2^4))*T+(1+2^2+O(2^4)))*z^6+(O(2^4)*T^3+O(2^4)*T^2+O(2^4)*T+O(2^4))*z^5+((1+2+2^3+O(2^4))*T^3+(1+2+2^2+2^3+O(2^4))*T^2+(2+2^3+O(2^4))*T+(1+2^2+2^3+O(2^4)))*z^4+(O(2^4)*T^3+O(2^4)*T^2+O(2^4)*T+O(2^4))*z^3+((2+2^2+2^3+O(2^4))*T^3+(1+2^2+2^3+O(2^4))*T^2+O(2^4)*T+(1+2+2^2+2^3+O(2^4)))*z^2+(O(2^4)*T^3+O(2^4)*T^2+O(2^4)*T+O(2^4))*z+((1+2^3+O(2^4))+(1+2^2+2^3+O(2^4))*T+(2+2^2+2^3+O(2^4))*T^2+(1+2+2^3+O(2^4))*T^3+O(T^20)),(1+O(2^4))*z^8+(1+O(2^4))); AA=truncate(lift(lift(FF))); BB=truncate(lift(lift(GG))); gcdext(AA,BB) gcd(x*Mod(1,7),x*Mod(1,7)) a=ffgen([3,5],'a); gcd((x^2+a*x+1)*(x+a),(x^3+a*x^2+a*x)*(x+a)) gcdext(x^2+a*x+1,x^3+a*x^2+a*x) \\ #2159 a='a; [P,Q,T]=[392757252698671644518933194646259026606358825037832605168120733455355904*x+(-32732367347867845727545221115691651450464375408154119*a^11-349901420764144182157149001212224917120789154588440854*a^10+301995817880565744755588538031580678248706119440652965202*a^9+2646578456426559099577038984579531585894051381563732492448*a^8-2145753607489079692256122053078728286338795227860524853856887*a^7-13811446641298285300218299011371917505796100901450244445692338*a^6+5693688219591330427165368038355599886351744436714343758769292516*a^5+26056823738974452070461793291997279246768552686129616910795970032*a^4-11017829044510831595466283417995196913182686859426697723597490195648*a^3-41423109488051504169006424755508272063137897706691923745421860003200*a^2-14256642019682515742570563716442803419996115605538672924160897393965312*a-126109974024633409447895964809596877746839040357983165563808547232812032),111803742489188645831681663344180674994365922928166912*x^3-83852806866891484373761247508135506245774442196125184*x^2+(12348904879976881337869569556155*a^11-250445894940842285432364650173775907*a^10-2597516391857725347876152069556695050*a^9+2738853504244544132425234560706042154874*a^8+22688857129426122093804816885398083679847*a^7-21762177549107842299693349522678564962736119*a^6-127665214054781454991155578265860141009689416*a^5+88461561911307031312255843171859939298925544784*a^4+346348882088725906358361823977571887641905346880*a^3-325654100038602077230986044994819766302283514425536*a^2-716001103348426243506424449886291672834136360965632*a+276988391939950578803619869121391914842756565190680576)*x+(12348904879976881337869569556155*a^11-250445894940842285432364650173775907*a^10-2597516391857725347876152069556695050*a^9+2738853504244544132425234560706042154874*a^8+22688857129426122093804816885398083679847*a^7-21762177549107842299693349522678564962736119*a^6-127665214054781454991155578265860141009689416*a^5+88461561911307031312255843171859939298925544784*a^4+346348882088725906358361823977571887641905346880*a^3-325654100038602077230986044994819766302283514425536*a^2-716001103348426243506424449886291672834136360965632*a+612399619407516516298664859153933939825854333975181312),a^12+12*a^11-13002*a^10-130740*a^9+105793425*a^8+832682592*a^7-500807817792*a^6-2934008282880*a^5+1667712407121792*a^4+6980361555806208*a^3-3225774176703664128*a^2-7116861358234533888*a+3895041509102090981376];gcd(P*Mod(1,T),Q*Mod(1,T)) gcd(2*I, 1+I) gcd(I*1., I+1.) gcd(1+O(2),1+O(3)) gcd(2+O(2^2),4+O(2^3)) w=quadgen(5); gcd(w,2*w) gcd(2*w,w) gcd(2,Mod(2,4)) gcd(1/2,Mod(2,4)) gcd(1/3,Mod(2,4)) gcd(Mod(2,4), 2+O(2^3)) gcd(Mod(2,5), I) gcd(Mod(2,5), w) gcd(1/2, 1/(I+1)) gcd(1/2, 2+O(2^3)) gcd(I, 2+O(2^3)) gcd(I, w) gcd(w, 2+O(2^3)) t = Mod(x^2,x^3); gcd(t,y) gcd(t,x) gcd(t,1/y) gcd(t,1/x) gcd(t,1/(x+1)) gcd(Pol(0), y) gcd(x+O(x^5), x^2+O(x^3)) gcd(x+O(x^5), 1/x^2) v=[1,2,1.,Mod(1,2),1/2,1/3,2/3,I,quadgen(5), 1+O(2),2+O(2^2),1/2+O(2)]; { t1=ffgen(2^3); t0=0*t1; t2=ffgen(3^3); for (i=1,#v, print(iferr(gcd(t0,v[i]),E,E)); print(iferr(gcd(t1,v[i]),E,E)); print(iferr(gcd(t2,v[i]),E,E)); ) } gcd(0,1.+I) gcd(0,1+I) gcd(0,Mod(1,3)+I) gcd(1/2, 1.+I) gcd(1,Mod(2,13)/(13*y+1)) gcd(4*x,2*x^0) gcd(4*x,2*x+1) gcd((4*x+2)*(x+1),4*x*(x+1)) gcd(x-1,(x-1)/x) gcd(Mod(1,y^2+1),Mod(1,x^2+Mod(-y,y^2+1))) gcd(Pol(0.),x) (k+1.)/k - (2*k+1.)/k gcd(1/(2^64*y),Mod(x^2,2^64*x^3)) gcd(Mod(1,2)*x+Mod(1,2),Mod(0,2)) gcd(Mod(1,2)*x+Mod(1,2), 0*ffgen(2^3)) lcm(Pol(0),0) lcm(0,Mod(0,3)) lcm(Mod(1,y^2+1),Mod(1,x^2+Mod(-y,y^2+1))) V=factorback(primes([2^63,2^63+1000])) gcd((x+1+V)*(x^3+3*x+1),(x+1)*(x^3+x+1)) gcd((x+1)*(x^3+3*x+1),(x+1)*(x^3+x+1)+V) chkgcdext(a,b,p)= { my(P=random(Mod(1,p)*x^a),Q=random(Mod(1,p)*x^b)); my([u,v,d]=gcdext(P,Q)); if(u*P+v*Q!=d,error([P,Q,p])); my([u,v,d]=polresultantext(P,Q)); if(u*P+v*Q!=d,error([P,Q,p])); } chkgcdext(200,200,17) chkgcdext(200,200,nextprime(2^31)) chkgcdext(200,200,nextprime(2^63)) chkgcdext(200,200,nextprime(2^95)) chkgcdext(300,100,17) chkgcdext(300,100,nextprime(2^31)) chkgcdext(300,100,nextprime(2^63)) chkgcdext(300,100,nextprime(2^95)) chkgcdext(200,300,nextprime(2^31)) chkgcdext(200,300,nextprime(2^63)) chkgcdext(200,300,nextprime(2^95)) chkhalfgcd(a,b)= { my([M,V]=halfgcd(a,b)); if (M*[a,b]~!=V, error([a,b])); M*[a,b]~-V; } chkhalfgcd(858824,528747) chkhalfgcd(858824,-528747) chkhalfgcd(-858824,528747) chkhalfgcd(-858824,-528747) chkhalfgcd(4*x^5+4*x^4+4*x^3+4*x^2+2*x+3,3*x^4+x^3+2) chkhalfgcd((4*x^5+4*x^4+4*x^3+4*x^2+2*x+3)*Mod(1,5),(3*x^4+x^3+2)*Mod(1,5)) chkhalfgcd(random(Mod(1,5)*x^1000),random(Mod(1,5)*x^1000)) a=ffgen([5,5],'a); chkhalfgcd(4*x^5+4*a*x^4+4*x^3+4*(a+1)*x^2+2*x+3,3*a*x^4+x^3+2*(a+1)) a=ffgen([2,100],'a); chkhalfgcd(4*x^5+4*a*x^4+4*x^3+4*(a+1)*x^2+2*x+3,3*a*x^4+x^3+2*(a+1)) a=ffgen([nextprime(2^128),3],'a); chkhalfgcd(4*x^5+4*a*x^4+4*x^3+4*(a+1)*x^2+2*x+3,3*a*x^4+x^3+2*(a+1)) b=Mod(a.pol,a.mod); chkhalfgcd(4*x^5+4*b*x^4+4*x^3+4*(b+1)*x^2+2*x+3,3*b*x^4+x^3+2*(b+1)) p=nextprime(2^128); chkhalfgcd((4*x^5+4*x^4+4*x^3+4*x^2+2*x+2^64+1)*Mod(1,p),(3*x^4+x^3+2^96)*Mod(1,p)) chkhalfgcd(random(Mod(1,p)*x^1000),random(Mod(1,p)*x^1000)) pari-2.17.2/src/test/in/asymp0000644000175000017500000000270214676526175014440 0ustar billbillcheck(a,b) = my(t = abs((a-b)/b)); if (t, ceil(log(t)/log(10)), -oo); default(realprecision, 211); pi=Pi; localbitprec(620); v = vector(128,n,n*sin(1/n)); \p115 check(limitnum(n -> n*sin(1/n)), 1) check(limitnum(v), 1) check(limitnum(n -> n^2*sin(1/n^2),2), 1) check(limitnum(n -> (1+1/n)^n), exp(1)) f(n) = n! / (n^n*exp(-n)*sqrt(2*Pi*n)); asympnum(f) bestappr(asympnumraw(f,10), 2^60) asympnum(n->log(1+1/n^2),2)[1..17] \p115 asympnum(n->log(1+1/n^pi),pi)[1..17] bestappr(asympnumraw(n->log(1+1/n^pi),17,pi),2^60) asympnum(v) \p38 log(limitnum(n->(1+1/n)^n)) limitnum(n->sum(j=1,n,sqrt(j)/j^2),1/2) - zeta(3/2) limitnum(n->n^2*(1-cos(1/n)),2) v2(N,mul = 1) = { my(q = mul*N, V); if (q == 1, return ([1/3])); V = vector(q); V[1] = V[2] = 1; for(n = 2, q - 1, V[n+1] = ((2*n + 1)*V[n] + 3*(n - 1)*V[n-1]) / (n + 2)); f = (n -> 3^n / n^(3/2)); return (vector(N, n, V[n*mul] / f(n*mul))); } limitnum(v2) > 1e6 limitnum(N->v2(N,10))-3/sqrt(12*Pi) h(n)= { \\ 1.612 makes a difference between 32-bit/64-bit archs localbitprec(ceil(bitprecision(1.) * 1.8)); my(a=1,A=1,B=1.); vector(n, i, a=B/i; A+=a; B+=A; a); } H=h(1849); b(n)=log(H[n])-(2*sqrt(n)-3/4*log(n)); localprec(57); C=-1/2-log(2*sqrt(Pi)); check(limitnum(n->b(n^2)), C) check(limitnum(n->b(20*n), 1/2), C) asympnum(n->b(n^2)-C) asympnum(n->lngamma(n+1)-(n+1/2)*log(n)+n-1/2*log(2*Pi)) asympnum(a->if(a%40==0,a^(-5/2)*I,0)) \\ Errors, keep at end asympnum(1) limitnum(1) limitnum(n->1,-1) pari-2.17.2/src/test/in/real0000644000175000017500000000121314567450071014214 0ustar billbill{ if (sizebyte(0)==16, \\ #1322 default(realprecision,2); print(1. << 2^60); print(1. >> 2^60); , \\ can't be tested on 32-bit kernel: fake answer print("5.9 E347063955532709820"); print("1.7 E-347063955532709821"); ); } 1. << 2^64 1. >> 2^64 1+0e1 0e1==1 0e1==1. 0e1<1 0e1<1. 0e1<=1 0e1<=1. 0e1>1 0e1>1. 0e1>=1 0e1>=1. 0e-1==1 0e-1==1. 0e-1<1 0e-1<1. 0e-1<=1 0e-1<=1. 0e-1>1 0e-1>1. 0e-1>=1 0e-1>=1. exponent(0) exponent(-1) exponent(1/2) exponent(2.0) exponent([-10,5,11]) exponent([-10,5;11,16.0]) exponent(2.*x - 1.) exponent(2.*x - 1. + O(x^2)) exponent(quadgen(-15)) v=[1,1/2,2+3*quadgen(-3),2+3*I, (2+3*I)/(x+1)]; real(v) imag(v) pari-2.17.2/src/test/in/fft0000644000175000017500000000103214676526175014061 0ustar billbillw = rootsof1(2) g = fft(w, x+1) fftinv(w, g) w = rootsof1(4) g = fft(w, x^3+I*x+1) fftinv(w, g) W = conj(rootsof1(4)) g = fft(W, x^3+I*x+1) fftinv(W, g) N = 512; w = rootsof1(N); T = random(1000 * x^(N-1)); U = fft(w, T); V = vector(N, i, subst(T, 'x, w[i])); exponent(V - U) round(Polrev(fftinv(w,U) / N)) == T w=powers(znprimroot(17),15); g=random(x^15*Mod(1,17)); U=fft(w,g); V=fftinv(w,U)/#w; V==Vecrev(g) fft([1]~,[2]~) fftinv([1],[x]) \\ Errors fft(rootsof1(3), x^2+x+1) fftinv(rootsof1(3), x^2+x+1) fft([],[]) fftinv([],[]) pari-2.17.2/src/test/in/ellpadiclambdamu0000644000175000017500000000444714676526175016577 0ustar billbilldefault(parisize, "12M"); \\ overflows 10M lambdamu(e,p,d=1,i=0)= ellpadiclambdamu(e, p, d, i); E11a1 = ellinit([0, -1, 1, -10, -20]); E11a2 = ellinit([0, -1, 1, -7820, -263580]); E11a3 = ellinit([0, -1, 1, 0, 0]); E17a1 = ellinit([1,-1,1,-1,-14]); E19a1 = ellinit([0, 1, 1, -9, -15]); E19a3 = ellinit([0, 1, 1, 1, 0]); E20a1 = ellinit([0, 1, 0, 4, 4]); E21a1 = ellinit([1, 0, 0, -4, -1]); E34a1 = ellinit([1, 0, 0, -3, 1]); E37a1 = ellinit([0, 0, 1, -1, 0]); E40a1 = ellinit([-7,-6]); E44a1 = ellinit([0, 1, 0, 3, -1]); E62a1 = ellinit([1, -1, 1, -1, 1]); E70a1 = ellinit([1, -1, 1, 2, -3]); E73a1 = ellinit([1, -1, 0, 4, -3]); E84a1 = ellinit([0, 1, 0, 7, 0]); E91a1 = ellinit([0, 0, 1, 1, 0]); E94a1 = ellinit([1, -1, 1, 0, -1]); E106c1 = ellinit([1, 0, 0, -283, -2351]); E115a1 = ellinit([0, 0, 1, 7, -11]); E142c1 = ellinit([1, -1, 0, -1, -3]); E145a1 = ellinit([1, -1, 1, -3, 2]); E429a1 = ellinit([1, 1, 1, 2, 2]); E434e1 = ellinit([1, -1, 1, -2364, -43641]); E435b1 = ellinit([0, -1, 1, 79, -1123]); E437a1 = ellinit([0, -1, 1, 19, 100]); E437b1 = ellinit([0, -1, 1, 0, -5]); E438a1 = ellinit([1, 0, 0, -938, -9564]); E438b1 = ellinit([1, 0, 0, -13, -19]); E438c1 = ellinit([1, 1, 0, -5, -3]); E1483a1 = ellinit([0, 1, 1, 2, 2]); lambdamu(E17a1,3,-167) lambdamu(E17a1,3,-187) lambdamu(E40a1,3,-379) lambdamu(E62a1,3,-296) lambdamu(E73a1,3,-151) lambdamu(E142c1,3,397) lambdamu(E429a1,5) lambdamu(E106c1,5,-312) lambdamu(E84a1,5,-443) lambdamu(E142c1,3,461) lambdamu(E91a1,3) lambdamu(E37a1,17) lambdamu(E37a1,19) lambdamu(E17a1,3,-239) lambdamu(E115a1,3,-127) lambdamu(E70a1,3,-299) lambdamu(E17a1,3,-56) lambdamu(E145a1,3,401) lambdamu(E62a1,3,-59) lambdamu(E94a1,3,137) lambdamu(E1483a1,5) lambdamu(E115a1,3,-127) lambdamu(E429a1,5) lambdamu(E429a1,7) lambdamu(E434e1,3) lambdamu(E437b1,2) lambdamu(E438a1,5) lambdamu(E438b1,5) lambdamu(E438c1,5) lambdamu(E435b1,2) lambdamu(E20a1,3) lambdamu(E20a1,5) lambdamu(E21a1,3) lambdamu(E19a1,3) lambdamu(E19a3,3) lambdamu(E34a1,3) lambdamu(E437a1,3) lambdamu(E437a1,5) lambdamu(E44a1,3) lambdamu(E435b1,3) lambdamu(E437a1,3) lambdamu(E437a1,5) lambdamu(E434e1,2) lambdamu(E44a1,3) lambdamu(E20a1,3) lambdamu(E20a1,5) lambdamu(E434e1,2) lambdamu(E435b1,3) lambdamu(E11a1,5) lambdamu(E11a2,5) lambdamu(E11a3,5) \\ ERRORS lambdamu(E20a1,2) lambdamu(E20a1,3,2) lambdamu(ellinit([1,1],5),5) pari-2.17.2/src/test/in/io0000644000175000017500000000234414567450071013706 0ustar billbillF="io-testfile"; del()=system(Str("rm -f ", F)); del() write(F, 123) write(F, 456) write1(F, "a",7) write1(F, "b") write(F) writetex(F, 1/2) readstr(F) del() \\ write(F, 1) write(F, "1+2") readvec(F) del() \\ writebin(F,1) read(F) del() writebin(F) read(F) del() L=List();writebin(F,L) read(F) del() \\ write(F,"1+1"); s = Str("cat ", F); extern(s) externstr(s) n = fileextern(s); while(l = fileread(n), print(l)); fileclose(n); del() { my(f=fileopen(F,"w")); for(i=1,10, filewrite(f,i)); fileclose(f); my(f=fileopen(F,"a")); for(i=1,10, filewrite1(f,i); fileflush(f)); filewrite1(f,"\n"); fileclose(f); my(i=0,l,f=fileopen(F)); while(l=fileread(f), print(i++,":",eval(l))); fileclose(f); my(i=0,l,f=fileopen(F,"r")); while(l=filereadstr(f), print(i++,":",l)); fileflush(); fileclose(f); } setdebug("io",1) my(f=fileopen(F));fileclose(f);fileread(f) my(f=fileopen(F));fileclose(f);filereadstr(f) my(f=fileopen(F));fileclose(f);filewrite(f,"b") my(f=fileopen(F));fileclose(f);filewrite1(f,"b") my(f=fileopen(F));fileclose(f);fileflush(f) my(f=fileopen(F,"w"));fileread(f) my(f=fileopen(F,"a"));filereadstr(f) my(f=fileopen(F));filewrite(f,"b"); my(f=fileopen(F,"r"));filewrite1(f,"b"); fileflush('x) setdebug("io",0) pari-2.17.2/src/test/in/primorial0000644000175000017500000000005614676526175015305 0ustar billbillvector(13,i,(i-1)#) 100# \\ ERRORS (-1)# Pi# pari-2.17.2/src/test/in/intnum0000644000175000017500000001144014724330077014604 0ustar billbilldefault(echo,1); allocatemem(20 * 10^6); check(a,b) = my(t = abs((a-b)/b)); if (t, ceil(log(t)/log(10)), -oo); \p96 check(intcirc(s=1, 0.5, zeta(s)), 1) f(s) = gamma(s)^3; \\ f(c+it) decrease as exp(-3Pi|t|/2) c = 2; \\ arbitrary A = [-oo,3*Pi/2]; B = [+oo,3*Pi/2]; F(z) = { my (a = -log(z)); intnum(t=A,B, exp(a*I*t), T)*exp(a*c) / (2*Pi); } T = intfuncinit(t=A,B, f(c + I*t)); ref=F(4); \p38 T = intfuncinit(t=A,B, f(c + I*t)); check(F(4), ref) \p96 f(x) = 1/(exp(x)-1) - exp(-x)/x; F = truncate( f(t + O(t^7)) ); g(x) = if (x > 1e-18, f(x), subst(F,t,x)); check(intnum(x = 0, [oo,1], f(x)), Euler) check(intnum(x = 0, [oo,1], g(x)), Euler) check(intnum(x = 0, 1, 1/sqrt(x)), 2) check(intnum(x = [0,-1/2], 1, 1/sqrt(x)), 2) check(intnum(x = 100000, oo, 1/(1+x^2)), atan(1/100000)) check(intnum(x=0,1,x*cos(Pi*x)), -2/Pi^2) check(intnum(x=0,1,x*cos(Pi*x),2), -2/Pi^2) check(intnum(x = [0,-1/2], [oo,-3/2], 1/(sqrt(x)+x^(3/2))), Pi) check(intnum(x = [-oo,-3/2], [oo,-3/2], 1/(1+abs(x)^(3/2))), 8*Pi/sqrt(27)) check(intnum(x = -oo, oo, 1/(1+x^2)), Pi) f(x)=if (x<0,1/(1+(-x)^(3/2)), 1/(1+x^(5/2))); a=4*Pi/sqrt(27) + 2*(Pi/5)/sin(2*Pi/5); check(intnum(x = [-oo,-3/2], [oo,-5/2], f(x)),a) f(x)=if (x<0,1/(1+(-x)^(3/2)), exp(-x)); check(intnum(x = [-oo,-3/2], [oo,1], f(x)), 4*Pi/sqrt(27)+1) f(x)=if (x<0,1/(1+(-x)^(3/2)), sinc(x)); check(intnum(x = [-oo,-3/2], [oo,-I], f(x)), 4*Pi/sqrt(27)+Pi/2) f(x)=if (x<0,exp(2*x), 1/(1+x^(3/2))); check(intnum(x = [-oo,2], [oo,-3/2], f(x)), 1/2+4*Pi/sqrt(27)) f(x)=if (x<0,exp(2*x), 1/(1+x^(5/2))); check(intnum(x = [-oo,2], [oo,-5/2], f(x)), 1/2+2*(Pi/5)/sin(2*Pi/5)) f(x)=if (x<0,exp(2*x), exp(-x)); check(intnum(x = [-oo,2], [oo,1], f(x)), 3/2) f(x)=if (x<0,exp(2*x), sinc(x)); check(intnum(x = [-oo,2], [oo,-I], f(x)), 1/2+Pi/2) f(x)=if (x<0,2*sinc(2*x), 1/(1+x^(3/2))); check(intnum(x = [-oo,-2*I], [oo,-3/2], f(x)), Pi/2+4*Pi/sqrt(27)) f(x)=if (x<0,2*sinc(2*x), 1/(1+x^(5/2))); check(intnum(x = [-oo,-2*I], [oo,-5/2], f(x)), Pi/2+2*(Pi/5)/sin(2*Pi/5)) f(x)=if (x<0,2*sinc(2*x), exp(-x)); check(intnum(x = [-oo,-2*I], [oo,1], f(x)), Pi/2+1) f(x)=if (x<0,2*sinc(2*x), sinc(x)); check(intnum(x = [-oo,-2*I], [oo,-I], f(x)), Pi) f(x)=cos((3+tanh(x))*x)/sqrt(1+x^2); a = intnum(x = [-oo,2*I], [oo,4*I], f(x), 1); check(intnum(x = [-oo,2*I], [oo,4*I], f(x)), a) check(intnum(x=[0,-1/2],[1,-1/3], x^(-1/2) + (1-x)^(-1/3)), 7/2) T=intnuminit([0,-1/2],[1,-1/3]); check(intnum(x=[0,-1/2],[1,-1/3], x^(-1/2) + (1-x)^(-1/3), T), 7/2) check(intnum(x = 0, [oo,1], sinc(x)), Pi/2) check(intnum(x = 0, [oo,-I], sinc(x)), Pi/2) check(intnum(x = 0, [oo,-2*I], 2*sinc(2*x)), Pi/2) A=intnum(x=0,1,sinc(x/2)^2/2)+intnum(x=1,oo,1/x^2)-intnum(x=1,[oo,I],cos(x)/x^2); check(A, Pi/2) check(intnum(x = 0, [oo, 1], sin(x)^3*exp(-x)), 3/10) check(intnum(x = 0, [oo,-I], sin(x)^3*exp(-x)), 3/10) tab = intnuminit(0,[oo,-I], 1); check(intnum(x = 0, oo, sin(x)^3*exp(-x), tab), 3/10) check(intnum(x = 0, [oo, -I], x^2*sin(x)), -2) tab = intnuminit(-1,1); check(intnum(x=-1,1, intnum(y=-sqrt(1-x^2),sqrt(1-x^2),x^2+y^2,tab),tab), Pi/2) \p96 check(intnumgauss(x=0,1,sin(x)), 1-cos(1)) T=intnumgaussinit(); check(intnumgauss(x=0,1,1/(x+1),T), log(2)) check(intnumgauss(x=0,1,1/(x+1)^(4/3),T), 3-3/2^(1/3)) check(intnumgauss(x=2,1,x,T),-3/2) check(intnumgauss(x=-1,1,1/(1+x^2), 20), Pi/2) T=intnumgaussinit(100); check(intnumgauss(x=-2,2,1/(1+x^2), T), 2*atan(2)) check(intnumgauss(t=1,2,t,4),3/2) bestappr(intnumgauss(t=1,2,t,1), 100) bestappr(intnumgauss(t=1,2,t,2), 100) bestappr(intnumgauss(t=1,2,t,3), 100) localprec(115); intnumgauss(x=1,2,1/x)-log(2) \\ Power series checkps(a,b) = my(t = norml2(Vec(b-a))); if (t, ceil(log(t)/log(10)), -oo); checkps(intnum(t=0,x,exp(t)),exp(x)-1) checkps(intnum(t=-x,0,exp(t)),1-exp(-x)) checkps(intnum(t=-x,x,exp(t)),exp(x)-exp(-x)) tab = intnuminit(1-x,1+y); norml2(apply(Vec,Vec(intnum(t=-x,y,exp(t),tab)-(exp(y)-exp(-x))))) checkps(intnum(t=[0,-1/2],x^2,1/sqrt(t)),2*x) checkps(intnum(t=1-x^2,[1,-1/2],1/sqrt(1-t)),2*x) checkps(intnum(t=[x^2,-1/2],1,1/sqrt(t)),2-2*x) checkps(intnum(t=0,[1-x^2,-1/2],1/sqrt(1-t)),2-2*x) f(t)=(t^2*(1-t))^(1/3); checkps(intnum(t=[x^3,-1/3],[1-x^3,-2/3],(2/3*t-t^2)/(t^2*(1-t))^(2/3)),f(1-x^3)-f(x^3)) \p38 intnum(x=-oo,[0,-1/2],1/sqrt(-x*(x^4+1))) \pb20 intnumromb(x=0,1,sin(x)) intnumromb(x=0,1,sin(x), 1) intnumromb(x=1,100,exp(-x^2), 2) intnumromb(x=0,1,sinc(x), 3) \\ wrong result at this accuracy intnumromb(x=0,110,x, 1) \\ wrong result at this accuracy intnumromb(x=2,110,x, 1) \\ wrong result exponent(intnumromb(x=-110,90,x, 1) + 1998.3) < -5 intnumromb(x=2,1,x, 1) intnuminit(-oo,oo,1); \\ Errors intnuminit([x,-1/2],x) intnum(t=[x^2,-1/2],1,1/sqrt(t),intnuminit([0,-1/2],1)) intnumgauss(t=1,2,1,"") intnuminit([oo,1+I],[oo,""]) intnuminit([oo,1+I,2],[oo,1]) intnum(x=oo,oo,1) intnum(x=-oo,-oo,1) intnuminit(x=-oo,oo,-1); intfuncinit(t=0,1,s); intfuncinit(t=[-oo,I],[oo,I],s); pari-2.17.2/src/test/in/idealramgroups0000644000175000017500000000167114676526175016331 0ustar billbill{ K=nfinit(x^30 - 240*x^28 + 24364*x^26 - 1366520*x^24 + 46492470*x^22 - 994986280*x^20 + 13527103660*x^18 - 116596891080*x^16 + 634140564945*x^14 - 2144111162280*x^12 + 4349007947424*x^10 - 4933119511040*x^8 + 2746986107136*x^6 - 564152514560*x^4 + 40138752000*x^2 - 409600000); G=galoisinit(K); forprime(p=2,37, pr = idealprimedec(K,p)[1]; print(pr.p,":", apply(galoisidentify,idealramgroups(K,G,pr)))) } K=nfinit(x^6 + 12*x^5 + 60*x^4 + 376*x^3 + 80268*x^2 + 4569240*x + 66227068); G=galoisinit(K); vecsort([[idealfrobenius(K,G,D),idealramgroups(K,G,D)]|D<-idealprimedec(K,29)],lex) K=nfinit(polcyclo(24)); G=galoisinit(K); P=idealprimedec(K,2)[1]; idealramgroups(K,G,P) \\#1755 P=x^8-12*x^6+36*x^4-36*x^2+9;N=nfinit(P);G=galoisinit(N); idealramgroups(N,G,idealprimedec(N,3)[1]) \\#1908 P=x^12+60*x^10+1260*x^8+10900*x^6+34200*x^4+9000*x^2+500;N=nfinit(P); G=galoisinit(N); pr=idealprimedec(N,2)[1]; ram=idealramgroups(N,G,pr); #ram pari-2.17.2/src/test/in/gchar-large0000644000175000017500000000233614676526175015466 0ustar billbilldefault(parisize,"66M"); \\ overflows 64M print("precision SEGV"); pol = x^8 + 9748*x^6 - 9748*x^5 + 23738821*x^4 - 47472768*x^3 + 35604576*x^2 - 11868192*x + 1483524; bnf = bnfinit(pol,1); gc = gcharinit(bnf,[1,[]]); round(gc.cyc) pr = idealprimedec(bnf,29)[1]; chi = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]~; gc.cyc[1] % denominator(gchareval(gc,chi,pr,0)) == 0 print("gchareval precision bug"); chi = vectorv(#gc.cyc-1,i,1); p2 = idealprimedec(bnf,2); logp = gcharlog(gc,p2); localbitprec(2^8); logp1 = gcharlog(gc,p2); localbitprec(2^9); logp2 = gcharlog(gc,p2); localbitprec(2^10); logp3 = gcharlog(gc,p2); exponent(logp-logp3) < -128 + 5 exponent(logp1-logp3) < -256 + 5 + 32 exponent(logp2-logp3) < -512 + 5 v = gchareval(gc, chi, p2, 0); localbitprec(256); gc1 = gcharnewprec(gc); v1 = gchareval(gc1,chi,p2,0); localbitprec(512); gc2 = gcharnewprec(gc); v2 = gchareval(gc2,chi,p2,0); exponent(v-v2) < -128 + 5 + 32 exponent(v1-v2) < -256 + 5 + 32 print("trivial ideal bug"); gchareval(gc,chi,idealhnf(bnf,1),0) == 0 print("argument determination bug"); {pol = x^8 - 4*x^7 + 16222*x^6 - 48652*x^5 + 71214421*x^4 - 142347760*x^3 + 44175759480*x^2 - 44104593708*x + 7360689434427}; bnf = bnfinit(pol,1); gc = gcharinit(bnf,1); round(gc.cyc) pari-2.17.2/src/test/in/algsplit0000644000175000017500000001165714567450071015125 0ustar billbillsetrand(1) vec2mat(d,n,V) = { my(M = matrix(d,d), x = 'x, c); for(i=0,d^2*n-1, c = V[i+1]; M[i\(n*d) + 1, (i\n)%d + 1] += c*x^(i%n) ); c = polcoeff(M[1,1],0); for(i=2,d,M[i,i]+=c); M }; mat2vec(d,n,M) = { my(V = vector(d^2*n), c = polcoeff(M[1,1],0)); for(i=2,d,M[i,i]-=c); for(i=1,d, for(j=1,d, for(k=0,n-1, V[n*d*(i-1) + n*(j-1) + k + 1] = polcoeff(M[i,j],k); ) ) ); V }; matalg(d,n,p) = { my(pol = ffinit(p,n), mtx, N=d^2*n, x, basis, mt=vector(N)); basis = vector(N,i,vec2mat(d,n,vector(N,k,k==i))); basis = basis*Mod(1,p)*Mod(1,pol); for(i=1,N, x = basis[i]; mtx = matconcat(vector(N,j,mat2vec(d,n,liftall(x*basis[j]))~)); mt[i] = mtx; ); algtableinit(mt,p) }; smallchg(mt,p) = { my(i,j,N=#mt,c); if(N==1, return(mt)); if(p, c=random([1,p-1]), c=1); i = random([2,N]); j=i; while(j==i,j=random([1,N])); for(k=1,N, mt[k][,i] += c*mt[k][,j]; mt[k][j,] -= c*mt[k][i,]; ); mt[i] += c*mt[j]; if(p,mt%p,mt) }; chg(mt,nb=3*#mt,p=0) = { for(c=1,nb,mt=smallchg(mt,p)); mt }; test2(d,n,p,nb=1) = { my(al,mt,mt2,res,map,x,y,Mx,My); setrand(1); al = matalg(d,n,p); mt = algmultable(al); mt2 = mt; for(c=1,nb, if(c>1, mt2 = chg(mt2,#mt\4 + 5,p)); al = algtableinit(mt2,p); res = algsplit(al,'t); map = res[1]; mapi = res[2]; x = algrandom(al,10); y = algrandom(al,10); Mx = map*x; My = map*y; if(Mx*My != map*algmul(al,x,y), print("FAIL"); return(0)); ); [al,map,mapi] }; print("M_2(F_4)"); test2(2,2,2,200); print("M_2(F_9)"); test2(2,2,3,100); q = 31; print("M_2(F_31^2)"); test2(2,2,q,30); p = nextprime(10^20); print("M_2(F_p^2)"); test2(2,2,p,30); print("M_d(F_31^n)"); for(d=1,4,for(n=1,min(18\(d^2),10),print("d=",d," n=",n);if(!test2(d,n,q,10), break(2)))); isblock(M,L) = { my(d,mini,nxt); d = #M[,1]; mini=L[1]; nxt=2; for(j=1,d, if(j>mini, mini += L[nxt]; nxt += 1; ); for(i=mini+1,d, if(M[i,j]!=0,return(0)); ); ); 1 }; matblock(L,n,p) = { d = sum(i=1,#L,L[i]); al0 = matalg(d,n,p); basis = [b | b<-Vec(matid(d^2*n)), isblock(vec2mat(d,n,b),L)]; basis = Mat(basis); algsubalg(al0,basis)[1]; }; print("examples from documentation"); al0 = alginit(nfinit(y^2+7), [-1,-1]); al = algtableinit(algmultable(al0), 3); \\isomorphic to M_2(F_9) [map,mapi] = algsplit(al, 'a); x = [1,2,1,0,0,0,0,0]~; fx = map*x y = [0,0,0,0,1,0,0,1]~; fy = map*y map*algmul(al,x,y) == fx*fy map*mapi[,6] print("bad input"); algsplit("toto"); algsplit(alginit(nfinit('y),[-1,-1])); algsplit(algtableinit([matid(3),[0,0,0;1,1,0;0,0,1],[0,0,0;0,0,0;1,0,0]],2)); algsplit(algtableinit([matid(2),[0,0;1,1]],2)); algsplit(matblock([2,1,1,1],1,q)); algsplit(matblock([1,2,3],1,q)); {mt=[[1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 1, 0, 0, 0, 0, 0; 1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 1; 0, 0, 0, 1, 0, 0, 1, 0, 0; 0, 1, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 1, 0, 1; 0, 0, 0, 0, 1, 1, 0, 0, 0; 1, 0, 0, 0, 1, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 1, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 1, 0, 1; 0, 0, 0, 0, 0, 0, 0, 0, 1; 1, 0, 0, 0, 0, 0, 0, 0, 0; 0, 1, 1, 0, 0, 0, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 1; 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 1, 1, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 1, 0; 0, 1, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 1, 0, 0, 0, 0, 0; 1, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 1; 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 1, 0, 0, 1, 0, 0], [0, 0, 0, 0, 1, 1, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 1, 0, 1; 0, 0, 0, 0, 1, 0, 0, 0, 0; 1, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 1, 0, 0, 0, 0, 1; 0, 1, 1, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 1, 0, 0, 0, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 1; 0, 0, 0, 1, 0, 0, 1, 0, 0; 0, 0, 0, 0, 1, 1, 0, 0, 0; 0, 1, 1, 0, 0, 0, 0, 0, 0; 0, 1, 0, 0, 0, 0, 0, 1, 0; 1, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0; 0, 0, 0, 0, 1, 1, 0, 0, 0; 0, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 1, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0; 0, 0, 0, 0, 0, 0, 0, 0, 1; 0, 1, 1, 0, 0, 0, 0, 0, 0; 1, 0, 0, 0, 0, 1, 0, 0, 0; 0, 0, 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, 0, 0, 0, 0, 1; 0, 0, 0, 0, 1, 1, 0, 0, 0; 0, 0, 0, 0, 0, 0, 0, 1, 0; 0, 1, 0, 0, 0, 0, 0, 1, 0; 0, 0, 0, 0, 1, 0, 0, 0, 0; 0, 0, 0, 0, 0, 0, 1, 0, 0; 1, 0, 0, 0, 1, 0, 0, 0, 0]]}; algsplit(algtableinit(mt,2)); pari-2.17.2/src/test/in/whatnow0000644000175000017500000000013214567450071014757 0ustar billbillwhatnow(changevar) whatnow(char) whatnow(allocatemem) whatnow(proveGRH) whatnow(compimag) pari-2.17.2/src/test/in/gamma0000644000175000017500000000243014730124522014344 0ustar billbilldefault(seriesprecision,6); gamma(2+I+x) gamma(1+x) gamma(2+x) gamma(-2+x) lngamma(2+I+x) lngamma(1+x) lngamma(2+x) lngamma(1) lngamma(1.) [psi(2+I+x,d)|d<-[0..4]] [psi(1+x,d)|d<-[0..4]] [psi(-2+x,d)|d<-[0..4]] psi(-1/2,1) psi(2^-1024,1) gamma(-1/2+x) gamma(1+a*x+O(x^2)) lngamma(1+a*x+O(x^2)) gamma(0.+1/2*x+O(x^2)) psi(x) gamma(x) gamma(1000) [psi(2^400,d)|d<-[0..9]] [psi(2^400*I,d)|d<-[0..9]] [psi(-1.5,d)|d<-[0..9]] [psi(x+O(x^2),d)|d<-[0..9]] real(psi((3/2+0.E-38*I)+x/2+O(x^2))) gamma(x+O(x^2)) gamma(-1-10^-16) gamma(10^-16) lngamma(-1-10^-16) lngamma(10^-16) binomial(2^64+1,2) binomial(1001.,1000) lngamma(2^301) lngamma(2^301 + 2*I) lngamma(2^64 + 2*I) lngamma(-200.5) gammah(0) gammah(400) gammah(400+I) default(realprecision,115); lngamma(2^301 + 2*I) lngamma(2^301 + 200*I) default(realprecision,154); lngamma(2^301 + 2000*I) gamma(1+10^-30) gamma(-1e-6) \p38 gamma(1/3) gamma(2/3) gamma(1/4) gamma(3/4) gamma(1/6) gamma(5/6) gamma(1/8) gamma(3/8) gamma(5/8) gamma(7/8) gamma(1/12) gamma(5/12) gamma(7/12) gamma(11/12) gamma(1/24) gamma(5/24) gamma(7/24) gamma(11/24) gamma(13/24) gamma(17/24) gamma(19/24) gamma(23/24) gamma(1/24+100) gamma(1/24+99) gamma(1/24-99) gamma(1/24-100) gamma(1/24+10^5) gamma(1/24-10^5) \\ ERRORS lngamma(-2+x) gamma(O(x)) lngamma(O(x)) psi(O(x)) psi(-1) pari-2.17.2/src/test/in/parallel0000644000175000017500000000467414676526175015115 0ustar billbillisp(i)=issquare(poldisc('x^36+i!+1)); export(isp); parsum(i=1,100,isp(i)) unexport(isp); exportall(); parsum(i=1,100,isp(i)) unexportall(); V=[2^256 + 1, 2^193 - 1]; parapply(factor,V) my(V=[2^256 + 1, 2^193 - 1]); parvector(#V,i,factor(V[i])) fun(V)=pareval(vector(#V,i,()->factor(V[i]))); fun(V) parfirst(fun,V)=parfor(i=1,#V,fun(V[i]),j,if(j,return([i,j]))); parfirst(isprime, [2^600..2^600+1000])[1] parselect(isprime, [2^600..2^600+1000],1) parselect(isprime, [2^600..2^600+1000]) isfermatprime(p)=Mod(2,p)^(p-1)==1; select(x->x==1,parapply(isfermatprime,[2^600..2^600+1000]),1) parselect(isfermatprime,[2^600..2^600+1000],1) select(isfermatprime,[2^600..2^600+1000]) parfirst(isfermatprime,[2^600..2^600+1000]) parselect(isfermatprime,[2^600..2^600+1000]) my(f(x)=isprime(2*x+1));#parselect(x->f(x)==0,[1..1000]) /* Disable tests that depends on ellsea findp(E,n)= { my(check(p) = my(c=ellcard(E,p)); if(isprime(c),c,0)); parforprime(p=2^n,,check(p),card,if(card,return([p,card]))); } my(E=ellinit([1,3])); findp(E,80) */ parsum(i=1,10000,moebius(i)) localbitprec(256);parvector(10,i,bitprecision(1.)) inline(ell,ell2); ell(a,B,N)=my(E=ellinit([0,0,0,a,1]*Mod(1,N))); ellpow(E,[0,1]*Mod(1,N),B); ecm(N,t,B)= iferr(parvector(t,a,ell(a,B,N)),err,gcd(lift(component(err,2)),N),errname(err)=="e_INV"); ecm(2^101-1,500,600!) ell2(a,B,N)=iferr(ell(a,B,N),err,return(gcd(lift(component(err,2)),N)),errname(err)=="e_INV");0; ecm2(N,t,B)=my(z);parfirst(a->ell2(a,B,N),[1..t])[2]; ecm2(2^101-1,500,600!) uninline(); chkell(n)=a->my(E=ellinit([1,0,0,0,ffgen(2^n)^a]),N=ellcard(E)/4);if(isprime(N),N); ellp(n)=parfirst(chkell(n),[1..10000]); ellp(128) my(N=1);until(type(A)=="t_ERROR",A=alarm(1,parfor(i=1,10,for(i=1,N,isprime(i))));N*=2); my(s,L=List());parfor(x=1,10,x!,f,s+=f);s my(s,L=List());parfor(x=1,oo,if(x<=10,x!),f,s+=f;if(x>=10,break));s my(s);parforprime(p=2,20,p!,f,s+=f);s my(s);parforstep(p=1,100,3,p!,f,s+=f);s my(s);parforstep(p=1,100,Mod(1,3),p!,f,s+=f);s my(s);parforstep(p=1,100,[2,-1],p!,f,s+=f);s my(s);parforvec(v=[[1,3],[1,3]],factorback(v),f,s+=f);s my(s);parforvec(v=[[1,4],[1,4]],factorback(v),f,s+=f,1);s my(s);parforvec(v=[[1,5],[1,5]],factorback(v),f,s+=f,2);s test(f)=my(f=f,CS);CS=vector(10,n,[n,n]);F=parapply(u->f(u[1],u[2])+f(u[2],u[1]),CS); for(i=1,100,test((x,y)->x+y)); my(X = List([1..3]),Z=[1,2]);parapply(x->X[x],Vec(X)) my(aaa=123,bbb=345); parvector(1,i,[self(),[i,aaa,bbb]]) my(a=varlower("a")); parapply(n->poldegree(n,a),[x+a,a*x+1,x+1]) pari-2.17.2/src/test/in/language0000644000175000017500000000102614676526175015070 0ustar billbillg(v, f) = v; f(n) = g([1], x->0); f(1) foo = vectorsmall(1); for(i=1,1, foo[1]); L=List(); W=[L,L]; V=[0,0]; M=[1,1;1,1]; N=List([1]); f(~x,a)=listput(~x,2*a); h(~x,a)=listput(x[1],a+1); g(~x,a)=x[1]+=a; k(~x,a,b)=x[,1]*=a;x[1,]*=b; l(x,a) = f(~x,a);x; f(~L,5); [L,W] h(~W,3); [L,W] g(~V,2); V k(~M,2,3); M NN=l(N,2); [N, NN] { my(L=List(), W=[L,L], V=[0,0], M=[1,1;1,1], N = List([1]), NN); f(~L,5); g(~V,2); h(~W,3); k(~M,2,3); NN=l(N,2); [L,W,V,M,N,NN] } x.inc=x[1]++ [3].inc z=[3];[z.inc,z] my(z=[3]);[z.inc,z] pari-2.17.2/src/test/in/nfields0000644000175000017500000000672714760123736014734 0ustar billbill\e \\ setrand(1);N=10^8;a=matrix(3,5,j,k,vectorv(5,l,random\N)); nfpol=x^5-5*x^3+5*x+25; nf=nfinit(nfpol) nfinit(nfpol,2) nfinit(nfpol,3)[2] nf3=nfinit(x^6+108); setrand(1);bnf2=bnfinit(y^3-y-1);nf2=bnf2.nf; setrand(1);bnf=bnfinit(x^2-x-57,,[0.2,0.2]); [bnf.cyc, bnf.fu] setrand(1); my(K=bnfinit(x^2-x-100000,1)); [K.cyc,K.fu] bnr=bnrinit(bnf,[[5,3;0,1],[1,0]],1); bnr.cyc bnr2=bnrinit(bnf,[[25,13;0,1],[1,1]]); bnr2.bid rnfinit(nf2,x^5-x-2) \\ bnfcertify(bnf) setrand(1); K=bnfinit(x^4+24*x^2+585*x+1791,,[0.1,0.1]); u=nfalgtobasis(K,73/1029*x^3-319/1029*x^2+1033/343*x+9829/343); U=concat(K.fu,K.tu[2]); [K.cyc, nffactorback(K,U,bnfisunit(K,u)) == u] bnrconductor(bnf,[[25,13;0,1],[1,1]]) bnrconductorofchar(bnr,[2]) bnfisprincipal(bnf,[5,1;0,1],0) bnfisprincipal(bnf,[5,1;0,1]) bnfisunit(bnf,Mod(3405*x-27466,x^2-x-57)) bnfnarrow(bnf) bnfsignunit(bnf) bnrclassno(bnf,[[5,3;0,1],[1,0]]) lu=ideallist(bnf,55,3); bnrclassnolist(bnf,lu) bnrdisc(bnr,Mat(6)) bnrdisc(bnr) bnrdisc(bnr2,,,2) bnrdisc(bnr,Mat(6),,1) bnrdisc(bnr,,,1) bnrdisc(bnr2,,,3) bnrdisclist(bnf,lu) bnrdisclist(bnf,20) bnrisprincipal(bnr,idealprimedec(bnf,7)[1]) dirzetak(nfinit(x^3-10*x+8), 30) factornf(x^3+x^2-2*x-1,t^3+t^2-2*t-1) \\ vp=idealprimedec(nf,3)[1] idx=idealhnf(nf,vp) idealred(nf,idx,[1,5,6]) idy=idealdiv(nf,5,idealprimedec(nf,5)[1]) 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)) idealcoprime(nf,idx,idx) idealdiv(nf,idy,idt) idealdiv(nf,idx2,idx,1) idealfactor(nf,idz) idealhnf(nf,vp[2],3) ideallist(bnf,20) bid=idealstar(nf2,54) ideallog(nf2,y,bid) idealmin(nf,idx,[1,2,3]) idealnorm(nf,idt) idp=idealpow(nf,idx,7) idealpow(nf,idx,5,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) nfbasistoalg(nf,ba) nfdisc(x^3+4*x+12) nfeltdiv(nf,ba,bb) nfeltdiveuc(nf,ba,bb) nfeltdivrem(nf,ba,bb) nfeltmod(nf,ba,bb) nfeltmul(nf,ba,bb) nfeltpow(nf,bb,5) nfeltreduce(nf,ba,idx) nfeltval(nf,ba,vp) nffactor(nf2,x^3+x) aut=nfgaloisconj(nf3) nfgaloisapply(nf3,aut[5],Mod(x^5,x^6+108)) nfhilbert(nf,3,5) nfhilbert(nf,3,5,vp) nfhnf(nf,[a,aid]) da=nfdetint(nf,[a,aid]) nfhnfmod(nf,[a,aid],da) nfisideal(bnf.nf,[5,1;0,1]) nfisincl(x^2+1,x^4+1) nfisincl(x^2+1,nfinit(x^4+1)) nfisisom(x^3+x^2-2*x-1,x^3+x^2-2*x-1) nfisisom(x^3-2,nfinit(x^3-6*x^2-6*x-30)) nfroots(nf2,x+2) nfrootsof1(nf) nfsnf(nf,[a[,1..3], [1,1,1], [idealinv(nf,idx),idealinv(nf,idy),1]]) nfsubfields(nf) polcompositum(x^4-4*x+2,x^3-x-1) polcompositum(x^4-4*x+2,x^3-x-1,1) polgalois(x^6-3*x^2-1) polred(x^5-2*x^4-4*x^3-96*x^2-352*x-568) polred(x^4-28*x^3-458*x^2+9156*x-25321,3) polred(x^4+576,1) polred(x^4+576,3) p2=Pol([1,3021,-786303,-6826636057,-546603588746,3853890514072057]); fa=[11699,6;2392997,2;4987333019653,2]; polred(p2,0,fa) polred(p2,1,fa) polredabs(x^5-2*x^4-4*x^3-96*x^2-352*x-568) polredabs(x^5-2*x^4-4*x^3-96*x^2-352*x-568,1) polredord(x^3-12*x+45*x-1) polsubcyclo(31,5) setrand(1);poltschirnhaus(x^5-x-1) \\ p=x^5-5*x+y; aa=rnfpseudobasis(nf2,p) rnfbasis(bnf2,aa) rnfdisc(nf2,p) rnfequation(nf2,p) rnfequation(nf2,p,1) rnfhnfbasis(bnf2,aa) rnfisfree(bnf2,aa) rnfsteinitz(nf2,aa) \\ setrand(1);quadclassunit(1-10^7,,[1,1]) setrand(1);quadclassunit(10^9-3,,[0.5,0.5]) getheap()[1] pari-2.17.2/src/test/in/rnfkummer0000644000175000017500000001341114676526175015314 0ustar billbillallocatemem(40*10^6) count = 0; nfisprobisom(P,Q,n)= { forprime(p=2,oo, my(FP=factormod(P,p,1),FQ=factormod(Q,p,1)); if(vecmax(FP[,2])>1 || vecmax(FQ[,2])>1, next()); if(FP[,1]!=FQ[,1], return(0)); n--; if(!n,return(1))); } do(nf,f, H = 0, sol, expo = 32)= { my(T,K); setrand(1); print(count++); K=bnrinit(bnfinit(nf,1),f); T=liftpol(rnfkummer(K, H)); if (!sol, return(T)); sol=rnfequation(K,sol); T=rnfequation(K,T); if (exponent(T) >= exponent(sol)+expo, error(Str(exponent(T),">=",exponent(sol),"+",expo))); if(!nfisprobisom(sol,T,100), error("Non isomorphic: ",T)); 1; } \\1 s=x^3+(-1518*y^3-19215*y^2-34929*y-44574)*x+(-60109*y^3-749439*y^2-1267239*y - 1564605); do(y^4+12*y^3+15*y^2+15*y-15,1,,s) s=x^3+(-2966607821298137695221*y^3+476631046289035481994*y^2+192709457001514904928*y-3466403968157289515244)*x+(2540572479236177356777153564954770*y^3-408570956574208393016204492517851*y^2-164574364514926539352315962553323*y+2968147937781020190344296341491759); do(y^4-13*y^3+2*y^2+2*y-15,1,,s) s=x^5-1715*x^3+588245*x+2224060; do(y^4-y^3-2404*y^2+2404*y+1154401, 5, matdiagonal([5,1])); s=x^5+110*x^3-385*x^2+(-6875*y+13310)*x+(20625*y+32197); do(quadpoly(-8,y), 11, [5,2;0,1],s, 128) \\ behaviour depend on kernel: bnfinit(Kz) too complicated \\do(quadpoly(181433,y),1) \\5 s=x^5-1303210*x^3-3085796744620*x^2+197388502848770385*x-2485682349742051838204; do(quadpoly(-1752,y), 19, matdiagonal([5,1,1]),s, 205) s=x^3+(336*y^5-828*y^4+1392*y^3-648*y^2+642*y+708)*x+(-1912*y^5+4824*y^4-8258*y^3+4314*y^2-4150*y-3594); do(nfinit(y^6-2*y^5+3*y^4+y^2+3*y+1), 2,, s) s=x^5+(17017652173565571513458621056962*y^3+12092145775172043054548359109292*y^2-876325659055432449266468856998622*y-622686226498527114644408241456762)*x^3+(-3509904899717566966361185126674382222066108248*y^3-2494015112748825304350579819178605081336660639*y^2+180742895265230743774161845730710476962698024868*y+128429551566977306010167099728851556007053429284)*x^2+(-1972361656110697509244968379675717662455301447086165796289400202*y^3-1401490900378015477557575577469182804976562578329531347503191642*y^2+101566955920731277024130968369809169962198986145523774515702599862*y+72169910655579515123740845629476995598141584116856346581053927787)*x+(34721240711563041872902655091500329727616260135040946866379973649336303371935962/5*y^3+24671693832786211543559425805647889122051819888022849161623390846096663130382901/5*y^2-1787973678122699988761167318155157950566709361557781579817258775320505214806036792/5*y-1270471281086259788398204676300747617880461477918128294395645166564235888677144306/5); do(y^4-52*y^2+26, 3, Mat(5), s, 128) s=x^3+(149826*y-5449275)*x+(162077290*y-5893045381); do(quadpoly(5288,y), 9, [1,0;0,3],s) do(y^4+y^3-9*y^2-9*y+11, 10, Mat(5)) \\10 s=x^5+(-529233791226172709100320/81*y^3+3856182858784066157178560/81*y^2+19968952019298399590558240/27*y-1767943061901363725254720)*x^3+(21016918588870574311435370027106800/9*y^3-153136633658805062951977710977807840/9*y^2-793006504596568244295808438522363120/3*y+631876581124697283193080866876590640)*x^2+(99538230152635328168723025018245409255387840040/81*y^3-725270425418204908413609232830115267947275641300/81*y^2-3755758182784678377160496318527825877206726398460/27*y+332514526301452771136644707346843750911135033280)*x+(1941590900241005290199398084175241231379799910514989312794/27*y^3-14147111678061387270415384857052593696568582438030377393362/27*y^2-73259750550300118059950705916778690241941650239204460587372/9*y+19458066839490303713476895648671719865039612076039284017118); do(y^4-y^3-159*y^2-441*y+1701, 10, Mat(5),s,128) s=x^5+(-2760116613489424684185680*y-25596268476580686164852330)*x^3+(2822328864746831957012367413172460940*y+26173201160487613338298184296409027890)*x^2+(22521335074832656216040962332820759440095503975180*y+208854269493224240023328311873583704058925723623705)*x+(-6679144273925645056255136241787816440935337639536263503273192*y-61939835872761085128676422377548845549491163927579451363961202); do(quadpoly(344,y),11,matdiagonal([5,1]),s) /* \\ 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]); bnrclassfield(bnfinit(y^2+5393946914743),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 */ P=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]); (P==x^2+(1/4*y^5+9/4*y^4+1/2*y^3+3/4*y^2+7/4*y-3/2)) || (P==x^2+(-1/4*y^5-7/4*y^4+7/2*y^3-15/4*y^2+11/4*y-3/2)) /* 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),[3,1;0,1])) \\15 do(quadpoly(689,y), 2, Mat(2),x^2 + (-8*y - 101)) do(y^8-76*y^6+1425*y^4-5776*y^2+5776, 5, matdiagonal([2,1])) s=x^3+(257*y^3-1029*y^2-7159*y+54438)*x+(1388161802/3*y^3-11630342135/6*y^2-36056723284/3*y+570374601445/6); do(y^4 - 34*y^2 + 1189, 5, matdiagonal([3,1,1]), s) do(y, [36,[1]], matdiagonal([3,1])) \\ #1632 do(quadpoly(3409,y),25,[5,1;0,1]) \\ #1873 do(y^6-2*y^5+8*y^4-18*y^3+24*y^2-18*y+6,168,matdiagonal([2,1,1,1,1,1,1,1])) \\ #1744 lift(rnfkummer(bnrinit(bnfinit(y^4-62*y^2+186,1),744),[1,0,0,0;0,1,0,0;0,0,2,1;0,0,0,1])) \\ #1760 mod=[[385,0,305;0,385,265;0,0,5],[0]]; setrand(1); bnr=bnrinit(bnfinit(y^3-y^2+1),mod); lift(rnfkummer(bnr,[1,0,0;0,2,1;0,0,1])) mod=[[429,234,78;0,39,0;0,0,39],[0]]; setrand(1); bnr=bnrinit(bnfinit(y^3+y-1,1),mod); lift(rnfkummer(bnr,[2,1,1;0,1,0;0,0,1])) \\ #2154 setrand(1); k=bnfinit(y^4 - 561*y^2 - 1334*y + 104607,1); bnr=bnrinit(k,idealprimedec(k,2)[1]); \\ no need to print result [depends on arch], was "bug in rnfkummer" rnfkummer(bnr,subgrouplist(bnr,[3],0)[1]); \\ #2182 rnfkummer(bnrinit(bnfinit(y^3+28*y+2,1),1)) \\ ERRORS, keep at end of file rnfkummer(bnfinit(x^2+23)) pari-2.17.2/src/test/in/random0000644000175000017500000000153314676526175014570 0ustar billbillff(p,f) = ffgen(p^f, 'a); doell(a)= { my(e, P); e = ellinit([1,1,3,4,5]*a); P = random(e); [P, ellisoncurve(e,P)]; } doff(p,f)=my(a = ff(p,f)); print(random(a)); doell(a); setrand(2^33 + 3) random() setrand(1); random(Mod(1,3)) doff(2,3) doff(precprime(2^32), 3) doff(nextprime(2^64), 3) random(1.) random(x^5*Mod(1,7)) randomprime(2) randomprime([0,1]) randomprime([2.5,2.4]) randomprime([2.4,2.5]) randomprime() randomprime(10) randomprime([2^100, 2^100 + 2^20]) randomprime(100,4) randomprime([10,100],Mod(2,5)) randomprime(100,Mod(0,2)) for (i=1,10, a = random([15,20]); if (a < 15 || a > 20, print(a))) s=getrand(); v=vector(10,i,random()); setrand(s); w=vector(10,i,random()); if(v != w,error("setrand")); vector(10,i,random(-10)) \\ ERRORS random("") setrand(2^65) setrand(-1) randomprime([3,100], Mod(0,2)) randomprime(2, 2) randomprime(3, 2) pari-2.17.2/src/test/in/idealappr0000644000175000017500000000050414676526175015246 0ustar billbillidealaddtoone(nfinit(x),[1,[;]]); K=nfinit(x^2+23); A=idealhnf(K,x/2); idealtwoelt(K, 3, 6) idealtwoelt(K, A) idealtwoelt(K, A, x) idealtwoelt(K, [;]) idealtwoelt(K, [;], 1) idealtwoelt(K, [;], 0) nf=nfinit(t^3-t^2-383270*t+54978000); A=idealhnf(nf, 2748900, 71779/66*t^2+579907/66*t-278805100); idealtwoelt(nf, A) \\ #2437 pari-2.17.2/src/test/in/quadray0000644000175000017500000000217314676526175014757 0ustar billbill\\ 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,-1435,-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]; foreach(v, p, print(p,": ",quadhilbert(p))) \\ other quad imaginary whose class group has exponent 2;result depend on arch { v=[[-1155,x^8 + 15*x^6 + 32*x^4 + 15*x^2 + 1], [-1995,x^8 + 15*x^6 + 32*x^4 + 15*x^2 + 1], [-3003,x^8 - 9*x^6 + 80*x^4 - 9*x^2 + 1], [-3315,x^8 + 9*x^6 + 77*x^4 + 36*x^2 + 16]]; foreach(v, x, my([D,q] = x, p = quadhilbert(D)); if(nfisisom(p,q), print(D,": ",q))); } quadhilbert(-4036) quadhilbert(-300003) quadhilbert(-3628843) Q(D,f) = lift(quadray(D,f)); Q(-4,31) Q(-11,2) Q(-15,3) Q(-179,2) Q(-2276,2) Q(-251,2) Q(-35,2) Q(-4,31) Q(-51,3) Q(8-48*3,2) Q(1-48*3,3) Q(1-48*3,4) Q(40-48*3,6) Q(-7,7) K = bnfinit(y^2+5); P5=idealprimedec(K,5)[1]; Q(K,P5) K = bnfinit(y^2+5*12); P2=idealprimedec(K,2)[1]; P5=idealprimedec(K,5)[1]; Q(K,idealmul(K,P2,P5)) \\#1633 quadray(-11,3) pari-2.17.2/src/test/in/prec0000644000175000017500000000173414676526175014244 0ustar billbillprecision(0) bitprecision(0) precision(I,3) t=(precision(1.,77)*x+1); precision(t) localprec(57);precision(1.) localbitprec(128);bitprecision(1.) bitprecision(1 + O(x), 10) bitprecision(1 + O(3^5), 10) bitprecision(1, 10) precision(1./t) precision(Qfb(1,0,-2)) localprec(37.5); getlocalprec() localbitprec(127/2); getlocalbitprec() precision(precision(1.,37.5)) bitprecision(bitprecision(1.,127/2)) getlocalprec() getlocalbitprec() serprec(1,x) serprec(x+O(x^3),x) serprec(x+O(x^3),y) serprec((1+O(y^2))*x+y + O(y^3), y) serprec(0.+O(x),x) serprec(Mod(0,2)+O(x),x) padicprec(0,2) padicprec(0,"") padicprec(1,2) == padicprec(0,2) padicprec(1/2,2)== padicprec(0,2) padicprec(Mod(1,9),3) padicprec(O(2^2),3) padicprec(O(2^2),2) t=1+O(2^3); padicprec(t,2) padicprec((x+2)*t, 2) padicprec((1+2*x+O(x^2))*t, 2) padicprec([2,4]*t, 2) \\ ERRORS localprec(-1) localbitprec(-1) iferr(localbitprec(2^63-1),E,0) \\ to avoid != results depending on arch iferr(localprec(2^63-1),E,0) localprec('x) pari-2.17.2/src/test/in/op0000644000175000017500000000017314567450071013713 0ustar billbilla = 5; a \= 2 b = 5; b \/= 2 c = 5; c >>= 2 d = 5; d <<= 1 e = 5; e %= 3 m=[a,b,c,d,e] a++ e-- m[2]-- m[3]++ m [a,b,c,d,e] pari-2.17.2/src/test/in/sumformal0000644000175000017500000000015514557721031015276 0ustar billbillsumformal(1/n) sumformal(0) sumformal(1) sumformal(n) sumformal(n^2) sumformal(x*y + 1) sumformal(x*y + 1,y) pari-2.17.2/src/test/in/lift0000644000175000017500000000053214567450071014232 0ustar billbillv=[Mod(y,y^2+1), Mod(1,z), Mod(2,3), 1+O(3)]; T=Pol(v,'x); Z=[1, Mod(5,3), "x", 3+O(3^3), -1/3+O(3), Mod(x,x^2), x*Mod(1,3) + Mod(2,3), (1+2*x+3*x^2+O(x^4))*Mod(1,5)]; F=[lift, a->lift(a,'x), a->lift(a,'y), a->lift(a,'z), centerlift,liftall,liftint,liftpol]; { for(i=1,#F, my (f=F[i]); print(f); for (j=1,#Z, print(f(Z[j]))) ) } pari-2.17.2/src/test/in/sqrtn0000644000175000017500000000322514676526175014457 0ustar billbillsqrt(0) sqrtn(0.,3) sqrtn(0.*I,3) sqrtn(1/2,3) sqrtn(quadgen(5),3) sqrtn(8+O(17^100), 3) test(b, M)= { my (B = b); for (i=2, M, B *= b; \\ b^i a = sqrtnint(B + 1, i); if (a != b, error([b, B, i])); ); } test(2, 100); test(2^32+1, 10); test(2^64+1, 10); a=10^1000000; sqrtnint(a,12345) sqrtnint(a,123456) sqrtnint(10^300,8) sqrtnint(10^500,27) sqrtn(Mod(0,3),-2) sqrtn(O(3),-2) sqrtn(0*ffgen((2^64+13)^2),-2) sqrtn(0*ffgen(3^2),-2) sqrtn(0*ffgen(2^2),-2) sqrtnint(10^1000,1001) sqrtn(2., 10, &z) z sqrtn(10+O(3^8), 10, &z) z sqrtn(1+O(3^3), -3) sqrtn(1,1) sqrtn(1,-1,&z) z sqrtn(Mod(2,4),3) sqrtn(Mod(2,4),3,&z) sqrtn(1, 3) sqrtint(0) sqrtint(0,&r) r sqrtint(4,&r) r sqrtint(120938191237,&r) r sqrtint(Pi,&r) r sqrtint(1e40,&r) r sqrtint(quadgen(5),&r) r sqrtint(9/4,&r) r sqrtnint(132/3, 4) sqrtnint(quadgen(17), 3) sqrtnint(8.1, 3) iferr(sqrt(3+O(2^2)),E,E) iferr(sqrt(3+O(2^3)),E,E) iferr(sqrt(Mod(2,11)),E,E) iferr(sqrt(Mod(2,33)),E,E) sqrt(0.e-10+1e-10*I) [sqrtn(27+O(3^4),3,&z), z] [sqrtn(16+O(2^5),4,&z), z] [sqrtn(2^6+O(2^9),6,&z), z] sqrtn([8,27],3) iferr(sqrtn(Mod(2,7),3),E,E) [sqrtn(Mod(2,7),3,&z),z] iferr(sqrtn(Mod(2,21),3),E,E) iferr(sqrtn(Mod(6,35),6),E,E) [sqrtn(Mod(64,101),6,&z),z] iferr(sqrtn(Mod(3,19),4),E,E) sqrtn(0,3) check(a)= { for(d=-5,5,if(d, my(u=sqrtn(a^d,d,&z)); if(u^d!=a^d,error("sqrtn ",[a,d])); if (z^d!=1,error("sqrtn(&z)",[a,d])))); } check(Mod(3,101)); check(Mod(nextprime(2^65),nextprime(2^100))); check(ffgen([3,7])); check(ffgen([nextprime(2^100),3])); \\ ERRORS sqrtn(Mod(13,112),6) \\ #2242 sqrtint(1e80) sqrtint(-1.0) sqrtint('x) sqrtnint('x,3) sqrtnint(-1.0,3) sqrtint(-quadgen(5)) sqrtnint(-quadgen(5),3) pari-2.17.2/src/test/in/ellisogeny0000644000175000017500000002563014676526175015466 0ustar billbillx; y; t; ellhyperellipticpolynomials(E, x = 'x) = { my (one = E.j^0); x *= one; return([x^3 + E.a2 * x^2 + E.a4 * x + E.a6, E.a1 * x + E.a3]); } elldefiningequation(E, x = 'x, y = 'y) = { my (one = E.j^0); x *= one; y *= one; my (eqns = ellhyperellipticpolynomials(E, x)); return(y^2 + eqns[2]*y - eqns[1]); } ellbasechar(E) = iferr(E.p, unused_param, 0); ffone(p, n = 1, v = 't) = ffgen(p^n, v)^0; num_isog(E, isog) = { my([x,y,d] = isog); my(d2 = d^2, d3 = d2*d, d4 = d2^2, d6 = d3^2); ((x + E.a2*d2)*x + E.a4*d4)*x + E.a6*d6 - y*(y + E.a1*d*x + d3*E.a3); } isog_satisfies_eqns(E, F, isog) = { if (Mod(num_isog(F,isog), elldefiningequation(E)) != 0, error("Isogeny polynomials don't satisfy the curve equations")); } kernel_poly_from_generator(E, P, ord = 0, x = 'x, check = 1) = { if (check && ! ellisoncurve(E, P), error("Given point is not on given curve.")); if (!ord, ord = ellorder(E, P)); my (one = E.j^0, rP = P, res = Pol([one], x)); for (r = 1, ord \ 2, res *= x - rP[1]; rP = elladd(E, rP, P)); res; } check_ker_pol_from_gen() = { my (x = 'x, one = ffone(101)); my (data = [ [1, [1, 1], [0], 1, Pol([1], x)], [one, [37, 42], [85, 0], 2, x + 16], [one, [37, 42], [89, 71], 3, x + 12], [one, [37, 42], [21, 9], 5, x^2 + 12*x + 14], [one, [37, 42], [58, 59], 18, x^9 + 100*x^8 + 68*x^7 + 59*x^6 + 49*x^5 + 86*x^4 + 98*x^3 + 12*x^2 + 70*x + 56] ]); for (i = 1, #data, my ([rg_one, ainvs, pt, ord, expected] = data[i], E = ellinit(ainvs * rg_one)); pt *= rg_one; my (res = kernel_poly_from_generator(E, pt, ord, x)); if (res != expected || Mod(elldivpol(E, ord, x), res) != 0, error("kernel polynomial is incorrect"))); } check_data(E, P, ord) = { my (p = ellbasechar(E), M = [7, 13, 3, 4]); if (p != 0, my (n = (E.j).f); t = ffgen(p^n, 't); if ( p == 2, M = [t, t+1, t, 1] * t^0, p == 3, M = [t, t+1, 2*t, t+2] * t^0)); E = ellchangecurve(E, M); P = ellchangepoint(P, M); if (!ellisoncurve(E, P) || ellorder(E, P) != ord, error("Broken data: ", ord, "-torsion")); my (F, G, FF, GG, ker); F = ellisogeny(E, P); FF = ellisogeny(E, P, 1); if (F[1] != FF, error("Got different curve when only computing image")); ker = kernel_poly_from_generator(E, P, ord, 'x); G = ellisogeny(E, ker); GG = ellisogeny(E, ker, 1); if (G[1] != GG, error("Got different curve when only computing image")); if (F[1][1..5] != G[1][1..5], error("Different curves obtained for same kernel")); if (F[2] != G[2], error("Different isogenies obtained for same kernel")); isog_satisfies_eqns(E, F[1], F[2]); } tatecrv(b, c, p = 0, n = 1) = { my (one = if (p == 0, 1, ffone(p, n))); ellinit([1 - c, -b, -b, 0, 0] * one); } do_tate(b, c, ord, p = 0, n = 1) = { my (E, P = [0, 0], t, M = Vec([1,0,0,1])); E = tatecrv(b, c, p, n); check_data(E, P, ord); } check_apply(E, ker, P, fP) = { my ([F, f] = ellisogeny(E, ker)); if (ellisogenyapply(f, P) != fP, error("Wrong image of point")); } check_compose() = { my (one = ffone(101), E = ellinit([6, 53, 85, 32, 34] * one), P = [84, 71] * one, \\ order 5 [F, f] = ellisogeny(E, P), Q = [89, 44] * one, \\ order 2 [G, g] = ellisogeny(ellinit(F), Q), gof = ellisogenyapply(g, f)); isog_satisfies_eqns(E, ellinit(G), gof); } check_prio_err(E, ker, var1, var2, tst, msg) = { my (got_err = 0); iferr(ellisogeny(E, ker, 0, var1, var2), err, got_err = 1, errname(err) == "e_PRIORITY" && variable(component(err, 2)) == tst); if (! got_err, error(msg)); } check_errs() = { my (E = ellinit([8, 5]), P = [0, 0], got_err = 0); \\ ellisoncurve(E, P) = 0 iferr(ellisogeny(E, P), err, got_err = 1, errname(err) == "e_DOMAIN" && component(err, 4) == E && component(err, 5) == P); if (! got_err, error("No error when P not on E")); my (var1 = 'var1, var2 = 'var2); check_prio_err(E, P, var2, var1, 'var2, "No error with bad variable order"); iferr(ellisogeny(E, "banana bread"), err, got_err = 1, errname(err) == "e_TYPE" && component(err, 2) == "banana bread"); if (! got_err, error("No error with bad kernel type")); check_prio_err(E, ['pvx, 0], 'x, 'g1, 'pvx, "No error with bad x-point base field variable order"); check_prio_err(E, [0, 'pvy], 'x, 'g2, 'pvy, "No error with bad y-point base field variable order"); check_prio_err(E, 'x * 'asdf, 'x, 'g3, 'asdf, "No error with bad kernel variable order"); check_prio_err(ellinit(['a4, 'a6]), [0], 'x, 'g4, 'a4, "No error with bad j-invariant variable order"); my (t = ffgen(2^2, 't), one = t^0, E = ellinit([t, t + 1, 0, t, t] * one), div2 = elldivpol(E, 2)); div2 /= polcoeff(div2, poldegree(div2)); iferr(ellisogeny(E, div2), err, got_err = 1, errname(err) == "e_DOMAIN" && component(err, 4) == E && component(err, 5) == div2); if (! got_err, error("No error when quotienting E by E[2] in char 2")); } check_ker_pol_from_gen(); check_compose(); check_errs(); P = [0, 0]; E = ellinit([0, 3, 0, 7, 0]); \\ Doing "1-torsion" check_data(E, [0], 1); check_apply(E, [0], P, P); check_apply(E, P, [0], [0]); \\ Doing 2-torsion check_data(E, P, 2); one = ffone(1009); E = ellinit([0, 3, 0, 7, 0] * one); check_data(E, [0], 1); check_apply(E, [0], P, P); check_data(E, P * one, 2); check_apply(E, P, P, [0]); in = [149, 125] * one; out = [833, 506] * one; check_apply(E, P, in, out); check_apply(E, P, [0], [0]); \\ Doing 3-torsion... E = ellinit([1, 0, 1, 0, 0]); check_data(E, P, 3); E = ellinit([1, 0, 1, 0, 0] * ffone(1009)); check_data(E, P, 3); t = ffgen(2^4, 't); one = t^0; E = ellinit([t^3+t^2+1,t^3+t+1,t^3+t^2+t+1,t^3+t+1,t^3+t+1]*one); Q = [t^2+t+1,t^3+t^2+1]*one; check_data(E, Q, 3); Q = [t^2+t,t^3+t^2+1]*one; check_data(E, Q, 2); Q = [t^3+t,t^3+t^2]; check_data(E, Q, 6); t = ffgen(2^5, 't); E = ellinit([t^3+t^2+1,t^4+t^3+t,t^4+1,t^3+1,t^2+t]); Q = [t^4+t^3+t^2,t^3+t^2]; check_data(E, Q, 3); t = ffgen(3^2, 't); one = t^0; Q = [t, 1] * one; E = ellinit([2,2*t,t+2,2*t,2*t+1]*one); check_data(E, Q, 3); \\ Quotient by full 2-torsion. Arbitrary E here; just need char(k) != 2. E = ellinit([0, 3, 0, 7, 0] * ffone(1009)); ker = elldivpol(E, 2) * E.j^0; F = ellisogeny(E, ker); FF = ellisogeny(E, ker, 1); if (F[1] != FF, error("Got different curve when only computing image")); isog_satisfies_eqns(E, F[1], F[2]); \\ See Kubert 1976 for why all this works. Data was selected randomly. \\ Doing 4-torsion... b = -128/7; c = 0; do_tate(b, c, 4); \\ Doing 5-torsion... b = 121/13; c = b; do_tate(b, c, 5); do_tate(b, c, 5, 2, 7); \\ Doing 6-torsion... c = -7/2; b = c + c^2; do_tate(b, c, 6); do_tate(b, c, 6, 3, 3); \\ Doing 7-torsion... d = 21/11; c = d^2 - d; b = d * c; do_tate(b, c, 7); t = ffgen(2^3, 't); d = t; c = d^2 - d; b = d * c; do_tate(b, c, 7, 2, 3); \\ We do these two over a finite field to (1) avoid stack overflow \\ and (2) to make them run a bit faster. \\ Doing 8-torsion... d = 11/7; b = (2 * d - 1) * (d - 1); c = b/d; do_tate(b, c, 8); do_tate(b, c, 8, 1009); t = ffgen(2^3, 't); d = t; b = (2 * d - 1) * (d - 1); c = b/d; do_tate(b, c, 8, 2, 3); \\ Doing 9-torsion... f = 1/7; d = f * (f - 1) + 1; c = f * (d - 1); b = c * d; do_tate(b, c, 9); do_tate(b, c, 9, 61, 2); t = ffgen(3^3, 't); f = t; d = f * (f - 1) + 1; c = f * (d - 1); b = c * d; do_tate(b, c, 9, 3, 3); \\ Francois Brunault's example E = ellinit([0, -1, 1, 0, 0]); z = Mod('t, polcyclo(11, 't)); a = z + 1/z; xP = a*(a - 1)*(a + 2); \\ [25]P = 0 on E. P = [xP, a*xP]; F = ellisogeny(E, P, 0, 'x, 'y); G = ellisogeny(E, kernel_poly_from_generator(E, P, 25, 'x), 0, 'x, 'y); if (F[1] != G[1], error("Different curves obtained for same kernel")); if (F[2] != G[2], error("Different isogenies obtained for same kernel")); isog_satisfies_eqns(E, F[1], F[2]); ellisogenyapply(x,x) ellisogenyapply([f,g,h],1) E = ellinit([-11/16,-445/32]); [e2,iso2] = ellisogeny(E,[5/2,0]); [e4,iso4] = ellisogeny(E,[27/4,17]); E2 = ellinit(e2); [e4p,iso2p] = ellisogeny(E2,[11, 0]); [e4,iso4] == [e4p,ellisogenyapply(iso2p,iso2)] E=ellinit([1,3]); ellisogeny(E,x-Mod(y,elldivpol(E,2,y)),1) a='a; nf=nfinit(a^6-3*a^5+5*a^4-5*a^3+5*a^2-3*a+1); j=-1904875*a^4+3809750*a^3-4893875*a^2+2989000*a-4426500; E=ellinit([j],nf); elliscm(E) P=x^11+(26363645*a^4-52727290*a^3+67743445*a^2-41379800*a+61284300)*x^10+(425198844352975*a^4-850397688705950*a^3+1092693121108050*a^2-667494276755075*a+988467471418350)*x^9+(2830014116614781625375*a^4-5660028233229563250750*a^3+7272684300788441737125*a^2-4442670184173660111750*a+6578984635750305846375)*x^8+(2263344741088871402400322500*a^4-4526689482177742804800645000*a^3+5816434508071287220399991250*a^2-3553089766982415817999668750*a+5261638163046277899866595000)*x^7+(-84080972281496363098317260784300000*a^4+168161944562992726196634521568600000*a^3-216074670275279855810432355668493750*a^2+131993697993783492712115094884193750*a-195464546125392318289224515971068750)*x^6+(-568351523564746435935291686513186881218750*a^4+1136703047129492871870583373026373762437500*a^3-1460572644706814908984934185280818378875000*a^2+892221121142068473049642498767631497656250*a-1321256992858376468492701626215702401218750)*x^5+(-1707748682214702675736769935984296041081437500000*a^4+3415497364429405351473539871968592082162875000000*a^3-4388641370454173516119348631088285566122972500000*a^2+2680892688239470840382578695103989525041535000000*a-3970034028005570543013063361570151787119815781250)*x^4+(-2363047006543053545682121744696305732886075654271484375*a^4+4726094013086107091364243489392611465772151308542968750*a^3-6072653406936679403703724135909026277503650983280859375*a^2+3709606400393625858021602391212720544617575329009375000*a-5493417809924079435269981996989646540506909179745312500)*x^3+(-280135469328858733032688977354161465279177706559772294921875*a^4+560270938657717466065377954708322930558355413119544589843750*a^3-719903416018950551927048293957869843442972282753550347656250*a^2+439767946690091818894359316603708378163794576193778052734375*a-651235956009982677846293379956586209128269240008555027343750)*x^2+(2968159866535837774480545362636433639107381460850411041514326171875*a^4-5936319733071675548961090725272867278214762921700822083028652343750*a^3+7627696815147200290307277202459139197040556807423060964253681640625*a^2-4659536948611362515826731839822705557933175346572649922739355468750*a+6900134541709030790125148064283533506425208531936964653523935546875)*x+(55842031714753553320268766494358196423992333725337785504940816559863281250/23*a^4-111684063429507106640537532988716392847984667450675571009881633119726562500/23*a^3+143505103031764790871127707693587588851616311527794721536356020007666015625/23*a^2-87663071317011237550858941199229392427623977802456936031415203447802734375/23*a+129816973896318202576954742292189182535432534636464463503237824043554687500/23); lift(ellisogeny(E,P,1)) pari-2.17.2/src/test/in/digits0000644000175000017500000000267314676526175014601 0ustar billbillbinary(0) digits(0) fromdigits([]) fromdigits(Vecsmall([])) digits(5^100) fromdigits(vector(100,i,i%7)) fromdigits(vectorsmall(100,i,i%7)) fromdigits([1,0,-1],2) fromdigits(Vecsmall([1,0,-1]),2) fromdigits([1,1,0,1],-2) fromdigits(Vecsmall([1,1,0,1]),-2) fromdigits([1,2^65+2^130,2^64+2^131],2^160) check(a,b)=my(v=digits(a,b));if(subst(Pol(v),'x,b)!=a || vecmax(v)>=b || fromdigits(v,b)!=a,error([a,b])); check(5^100,2) check(5^100,3) check(3^100,2^64-1) check(3^100,2^128+1) sumdigits(0) sumdigits(129) sumdigits(123456789123456789123456789) sumdigits(100000!) binary(0.) binary(0.005) binary(1.1) binary([0,1]) vector(10, i, sumdigits(123456789, i+1)) digits(2^128+3, 2^64) digits(999999999999999,4294967295) sumdigits(2^128+3, 2^64) sumdigits(-3,3) sumdigits(-3,10) sumdigits(-3,2) digits(5,-2) sumdigits(5,-2) digits(-5,-2) sumdigits(-5,-2) digits(O(2^4)) digits(O(3^4)) digits(1+O(3^4)) digits(1234+O(3^4)) test(B)= { for(n=-1000,1000, my(D=digits(n,B)); if((#D && (vecmax(D)>=abs(B) || vecmin(D)<0)) || fromdigits(D,B)!=if(B<0,n,abs(n)), error("digits:",[n,B,D]))); } test(2); test(3); test(4); test(7); test(-2); test(-3); test(-4); test(-7); 0x12345 0x1234567890ABCDEF987654321 0x0000000000000000012345 0b11011011 0b1011011101111011111011111101111111011111111011111111101111111111 0b000000000000000000000000000000000000000000000000000000000000000011011011 x->x+0x1234 x->x+0b1011 \\ Errors binary(I) digits(2+O(3),2) digits(10,-1) digits(10,1) pari-2.17.2/src/test/in/zetamult0000644000175000017500000000372014676526175015155 0ustar billbilltest(a,b)= if(a==b,oo, exponent(a-b)); test(zetamult([2,1]), zeta(3)) test(zetamult([4,2]), (zeta(3)^2 - 4*zeta(6)/3)) test(zetamult([4,4]), (zeta(4)^2 - zeta(8))/2) test(zetamult([2,2,2]), zeta(2)^3/6 + zeta(6)/3 - zeta(2)*zeta(4)/2) zetamult(2) zetamult([]) s=[2,1,1,1,3]; test(zetamult(s),polylogmult(s)) zetamult(s,1) zetamult(s,x) default(realprecision,57); V=vector(10, k, vector(2*k, j, 1+2*(j%2))); for(k=1,#V, print(Pi^(4*k) / zetamult(V[k]))); v = [zeta(9),Pi^2*zeta(7),Pi^4*zeta(5),Pi^6*zeta(3)]; LD=[2,2,2,2]; { for(i=1,4, LE=LD; LE[i]=3; z = lindep(concat(zetamult(LE),v)); if (z[1] < 0, z = -z); print(z); ); } polylogmult([6,1,2,3,4],[-1,1,1,1,1]) polylogmult(Vecsmall([6,1,2,3,4]),[-1,1,1,1,1],x) for(i=1,15, print(zetamultall(5, i))) default(realprecision,38); polylogmult([2,1], exp(2*I*Pi/7) * [1,1]) polylogmult([2,1,1], exp(2*I*Pi/7) * [1,1,1]) polylogmult([2,1,1,1], exp(2*I*Pi/7) * [1,1,1,1]) polylogmult([1],[-1]) polylogmult([1],[1/2]) f(t)=polylogmult([2,1],[-1,-1],t); g(t)=polylogmult([2,3,4],,t); exponent(f(0.2)-(0.8*f(0)+0.2*f(1))) P=polinterpolate([g(1),g(2),g(3)]); exponent(g(0.2)-subst(P,x,0.2)) default(realprecision,366); a=(1+sqrt(5))/2;w=(1+sqrt(-3))/2; real(polylogmult([1,1,1,1],[1/a,a,1,w])) default(realprecision,38); avec=[3,1,3,1]; evec=[0,0,1,1,0,0,1,1]; a=89; zetamultconvert(avec,0) zetamultconvert(avec,1) zetamultconvert(avec,2) zetamultconvert(evec,0) zetamultconvert(evec,1) zetamultconvert(evec,2) zetamultconvert(a,0) zetamultconvert(a,1) zetamultconvert(a,2) { for (i = 1, 2^10, a = zetamultconvert(i); if (zetamultconvert(a,2) != i, error(i)) ); } zetamultdual([4]) zetamultdual([2,1,1]) zetamultdual(4) zetamultdual([0,0,1,1,0,0,1,1]) zetamult([],1) zetamultall(1,1) \\ Errors, keep at end of file zetamult([1,2]) zetamult("a") zetamultall(0) zetamultall(64) zetamult([0,2,1]) zetamult([0,1,0]) zetamult([0,-1,1]) zetamult([1,-1,1]) zetamult([1,0,1]) polylogmult([2],[]) polylogmult([1],[1]) polylogmult(1,[],-1) pari-2.17.2/src/test/in/lfunartin0000644000175000017500000000124714567450071015302 0ustar billbill\\ package: galpol testartin(P)= { N = nfinit(P); G = galoisinit(N); [T, o] = galoischartable(G); for(i=1,#T, L = lfunartin(N,G,T[,i],o); if(lfuncheckfeq(L)>-40,print(["error:",galoisidentify(G),i]))); } checkartin(m)= { for(n=1,m, for(i=1,galoisgetpol(n), testartin(galoisgetpol(n,i)[1]))); } localbitprec(64);checkartin(15) \\ Old interface testold(P,R,o)= { N = nfinit(P); G = galoisinit(N); for(i=1,#T, L = lfunartin(N,G,R,o); if(lfuncheckfeq(L)>-40,print(["error:",galoisidentify(G),i]))); } P = x^10-2*x^9-20*x^8+2*x^7+69*x^6-x^5-69*x^4+2*x^3+20*x^2-2*x-1; R = [[a^3-a^2+a-1,0;0,-a],[0,1;1,0]]; localbitprec(64);testold(P,R,10) pari-2.17.2/src/test/in/bern0000644000175000017500000000204214760137411014213 0ustar billbilldefault(parisize,"44M"); \\ overflows 42M bernfrac(0); bernfrac(1); for(k = 1, 20, print(bernfrac(k))); for(k = 0, 5, print(bernpol(k))); for(k = 0, 5, print(bernpol(k,1))); for(i = 1, 10^6, bernpol(5,1)); bernvec(30) bernreal(30) bernreal(202) bernreal(1024) bernfrac(256) eulerreal(30) - eulerfrac(30) localprec(57); bernreal(30) localprec(57); eulerreal(30) - eulerfrac(30) eulerfrac(0) eulerfrac(1) eulerfrac(2) eulervec(30) forstep(k = 0, 20, 2, print(eulerfrac(k))); for(k = 0, 5, print(eulerpol(k))); for(k = 0, 5, print(eulerianpol(k))); p=2^32-5; B=Mod(bernvec(7000), p); X=Mod(1,p)*x + O(x^14002); t=X/(exp(X)-1); j=0; J=Mod(1,p); /* 2i and j! mod p */ for (i=0, #B-1, if (B[1+i] != polcoeff(t,j)*J, error(i)); j+=2; J *= j*(j-1)) E=Mod(eulervec(7000), p); t=1/cosh(X); j=0; J=Mod(1,p); /* 2i and j! mod p */ for (i=0, #E-1, if (E[1+i] != polcoeff(t,j)*J, error(i)); j+=2; J *= j*(j-1)) bernvec(579)[14] \\ Errors, keep at end of file bernfrac(-1) bernreal(-1) bernpol(-1) bernpol(-1,1) eulerfrac(-1) eulerreal(-1) eulerpol(-1) eulerianpol(-1) pari-2.17.2/src/test/in/bnf0000644000175000017500000001023514676526175014054 0ustar billbilldefault(parisize,"108M"); \\ overflows 106M 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 bnfinit(x-1/2).clgp bnfinit(x^2-1/2).clgp bnfinit(x^2+2).tu \\ #2027 setrand(1);bnfinit(x^3-3*x^2-910095904*x+10793133991936,1).no \\ #2139 setrand(3);bnfinit(x^2-(1130481^2+4)).clgp setrand(2);bnfinit(x^4 - x^3 + 63*x^2 - 22*x + 1004).cyc setrand(1);bnfinit(x^8 - 8*x^6 + 38*x^4 - 143*x^2 + 121).clgp bnfcertify(bnfinit(x^2-40!)); bnfcertify(bnfinit(x^8-2)); \\#2168 bnfcertify(bnfinit(x^8-4*x^5-x^4+4*x^3+1,1)); \\#1736 setrand(1);bnfinit(x^3-87156*x^2-6728799*x-456533).cyc \\#1253 k=bnfinit(z^2+19*z+6,1); bnfisunit(k,k.fu[1]^2) \\#1247 setrand(1);bnfinit(x^2+1635847).no \\#1381 K = bnfinit(x^2+23); L = bnrdisclist(K, 10); s = L[2]; bnfdecodemodule(K, s[1][1]) \\ rare wrong result setrand(3805);bnfinit(y^8-44466*y^6+1977225156*y^4-87919293786696*y^2+3909419317519224336).cyc default(realprecision,19); K=bnfinit(x^5-x^4+x^3+100*x+20,1); A=idealpow(K,idealprimedec(K,5)[2],150); bnfisprincipal(K,A); default(realprecision,173); K=nfnewprec(K); bnfisprincipal(K,A) nfnewprec(bnfinit(x)); ideallist(bnrinit(K,1),2,2) l=ideallist(K,4,0);ideallistarch(K,l,[1]); l=ideallist(K,3,3);L=ideallistarch(K,l,[1]); bnrdisclist(K,l) bnrdisclist(K,L) bnrdisclist(K,4,[1]) ideallist(K, -1) ideallist(K, -4) \\#2180 bnrdisclist(bnfinit(galoissubcyclo(32,15)),94); \\#1631 setrand(1);bnfinit(x^16-48*x^14+934*x^12-9632*x^10+57251*x^8-198568*x^6+386172*x^4-377776*x^2+137288).no \\ oo loop in 2.9 setrand(1);K=bnfinit(x^2+2323); P=idealprimedec(K,23)[1]; bnfisprincipal(K,P) \\ #2054 \\ Disabled, too slow \\D = 1460939943556665662782863549; \\K = nfinit([x^2-D,[3,7,1586327]]); setrand(426507128); \\bnfinit(K,,[0.132,0.15]); \\ #2164 bnf = bnfinit(y^4-y-1); bnfisunit(bnf,-y^3+2*y^2-1) \\ #2183 setrand(53152); bnfinit(y^12+179*y^10+32041*y^8+5735339*y^6+1026625681*y^4+183765996899*y^2+32894113444921).cyc setrand(1);bnfinit(x^28+2*x^27-23*x^26-70*x^25+137*x^24+741*x^23+247*x^22-2779*x^21-3751*x^20+3417*x^19+10616*x^18+3418*x^17-11131*x^16-12909*x^15-900*x^14+9818*x^13+10369*x^12+2704*x^11-5294*x^10-6549*x^9-2031*x^8+1826*x^7+2029*x^6+616*x^5-187*x^4-221*x^3-80*x^2-14*x-1).cyc setrand(1);bnfinit(x^8-4*x^7-42*x^6+140*x^5+361*x^4-960*x^3-540*x^2+1044*x+603,1).cyc setrand(1);bnfinit(x^4-25*x^2+25,1).cyc \\ FIXME: takes 8s without [0.3] setrand(1);bnfinit(x^6-x^5-26*x^4+57*x^3+98*x^2-345*x+225,1,[0.3]).cyc \\overflow when h>>1 setrand(1); D = 2^60+33; bnf = bnfinit(x^2+D); P = idealprimedec(bnf, 3^30 + 4)[1]; bnfisprincipal(bnf,P,1+4); bnfisprincipal(bnf,P,1); \\loss of accuracy bnf=bnfinit(a^3 - 65249548*a - 207761301170,1);exponent(bnf[3]) \\ wrong cyclic components setrand(1);bnfinit(a^6+6748*a^4-750056*a^3+45535504*a^2-2530688944*a+140646000784,1).cyc \\ D. Broadhurst's examples P=x^7+10*x^6+16*x^5+160*x^4+76*x^3+760*x^2+96*x+962; localbitprec(64);setrand(1); bnfinit(nfinit(P),1).no P=x^7+3*x^6+57*x^5+171*x^4+927*x^3+2781*x^2+4455*x+13368; localbitprec(64);setrand(1);bnfinit(nfinit(P)).no P=x^7+3*x^6+54*x^5+162*x^4+621*x^3+1863*x^2+1404*x+4215; localbitprec(128);bitprecision(bnfinit(P,1).reg,128) P=x^7+6*x^6+30*x^5+180*x^4+207*x^3+1242*x^2+378*x+2271; localbitprec(128); k=bnfinit(P); [k.no, bitprecision(k.reg,128)] P=x^7-37*x^6+664*x^5-7380*x^4+2648*x^3-416*x^2+32*x-1; localbitprec(128); bnfinit(P).no P=x^7+22*x^6+184*x^5+764*x^4+2020*x^3+3792*x^2+5712*x+4; localbitprec(128); bnfinit(P,1).no P=x^7+8*x^6+6*x^5-128*x^4+224*x^3+4608*x^2+12672*x+4; localbitprec(128); bnfinit(P,1).no P=x^7-22*x^6+169*x^5-568*x^4+1263*x^3-1506*x^2+2295*x+2; localbitprec(128); bnfinit(P,1).no localbitprec(128); bitprecision(bnfinit(x).nf) \\ #2355 bnfinit(x^3+x^2-300718516569853095954224822736606480534192*x+63469622412272370773369114880921263373233288077845073732447296,1).cyc \\ #2372 P=y^6 + 3*y^5 + 6*y^4 - 886567*y^3 - 1329855*y^2 + 1329864*y + 196504250944; localprec(38);bnf=bnfinit(P,1); apply(x->nfeltnorm(bnf,x),bnf.fu) bnf=bnfinit(y^6-4*y^5-13*y^4+41*y^3+230*y^2+284*y+184,1); apply(x->idealnorm(bnf,x),bnf.fu) localbitprec(64); setrand(1); bnfinit(x^4 - 330*x^2 + 5445).cyc \\ ERRORS: keep at end of file pari-2.17.2/src/test/in/resultant0000644000175000017500000000657614732363470015333 0ustar billbillk;c;d;e;f;g;junk2;junk3;b;h;j;a;z;x2;x3;x4;x1; allocatemem(20*10^6); do(P,Q)=my(v=variable()); substvec(polresultant(P,Q), v, vector(#v,i,i)); P = Pol([k,c,d,e,f,g]); Q = P'; do(P,Q) P = Pol([1,b,c,d,e]); Q = Pol([1,g,h,k,j]); do(P,Q) P = x^7 + x^3 + b*x^2 + c*x + d; Q = x^7 + x^3 + f*x^2 + g*x + h; do(P,Q) P = x^20 + a*x^5 + b; Q = x^20 + c*x^5 + d; do(P,Q) P = (x+a)^8; Q = (x+z)^8; do(P,Q) P = x^50 + 5*a*x^40 + 4*a*x^30 + a*x^20 + 2*a*x^10 + 3*a; Q = x^45 + 2*b*x^35 + b*x^25 + 4*b*x^15 + 5*b*x^5 + 6*b; do(P,Q) P = polcyclo(31); P = subst(P, x, a*x); Q = polcyclo(29); Q = subst(Q, x, a*x); do(P,Q) P = 1 + Polrev( vector(101, j, b^(101-j)) ); Q = 1 + Polrev( vector(101, j, b^(j-1)) ); do(P,Q) P = 1 + Polrev( vector(301,i,1) ); Q = 1 + Polrev( vector(201,i,i-1) ); do(P,Q) P = 1 + Polrev( vector(301,j, (j-1)^5) ); Q = 1 + Polrev( vector(301,j, (j-1)^4) ); do(P,Q) n = 110; polrandom(d, fudge) = x^d + Polrev(vector(d+1, i, round(2^32*sin(i+fudge)))); P = polrandom(n,0); Q = polrandom(n,1/2); do(P,Q) polresultant(-27673*x^2+322883101*x-1876122109136,x^4+4503599627370517) P=-27673*x^2+322883101*x-1876122109136; for(n=2,3,for(l=1,3,print(polresultant(P*x^l+1,n*x^4+4503599627370517)))) polresultant(z^1746-1, polcyclo(1973, z)) for(i=1,15,if(rnfequation(polcyclo(17,'y),x+y^i,1)[2]^17!=1,print("error",i))) \\ #1233 polresultantext(x^2+1, x^2-1) \\ #1234 polresultant(x^4+x^2+1, x^4-y, x, 0) p1=x2*(x3-x4);p2=x2*(x3-2*x4);polresultant(p1,p2,x1) polresultant(x,x,y) A = x*y; B = (x+y)^2; polresultant(A, B) polresultantext(A, B, y) polresultantext(1,x) \\ #1509 polresultantext(y^3+y,3*y^2+1,y) poldisc(x^3 + Mod(2,3)*x^2) poldisc(x^3 + Mod(2,3)*x^2+1) norm(Mod(Pol(Mod(0,2)), 3*x)) polresultantext(x+1, x^2) \\#1614 polresultant(1+x*z^2,1+y*z^4,z) polcompositum(x^5-5,x^4-2,2) polcompositum(x-1, x^2+x+1, 1) polcompositum(x-1, x, 1) my(p=nextprime(2^31));polcompositum(p*x^2+x+1,p*x^3+x+1) my(p=nextprime(2^63));polcompositum(p*x^2+x+1,p*x^3+x+1) polcompositum(x^2+x/3+1,x^2+x/3+1) polcompositum(x^2+x/3+1,x^2+x/3+1,2) polresultant(x^2+1,z,x) P=polcyclo(101);Q=P'; polresultant(P*Mod(1,3),Q) polresultant(P*Mod(1,2^127-1),Q) P=polcyclo(2003);Q=P'; polresultant(P*Mod(1,3),Q) polresultant(P*Mod(1,2^127-1),Q) polresultant(Mod(1,3)*x*y*z,Mod(1,3)*(x^2+1)*y*z) polresultant(x,2) polresultant(x^2,2) polresultant(x^2,y) polresultant(y^2+1/x, y/x+1, y) check(P,Q)= { my(d=poldegree(P),e=poldegree(Q)); if(polresultant(P,Q)*y^(d*e)!=polresultant(subst(P,x,'x/y)*y^d,subst(Q,'x,x/y)*y^e),error(P)); } test(a)=check(a^0*x^6+(a^9+a^8+a^7+a^6+a^4+a^3+a)*x+(a^9+a^8+a^7+2*a^6+a^4+a^2),a^0*x^7+(a^8+a^7+a^6+a^4+a^3+a)*x+(a^9+a^7+2*a^6+a^4+a^2)); test(ffgen(2^10,'a)); test(ffgen(3^10,'a)); test(ffgen([nextprime(2^100),5],'a)); test(Mod(Mod(1,2),ffinit(2,5,'a))); test(Mod(Mod(1,3),ffinit(3,5,'a))); my(p=nextprime(2^100)); test(Mod(Mod(1,nextprime(2^100)),ffinit(p,3,'a))); polresultant(x^2+y*x+y^4,(3*x^4+(y+5)*x^3+(2*y+1)*x^2+y*x+y^3)/x,y) polresultant(x^2+y*x+y^4,(x^4+(y+5)*x^3+(2*y+1)*x^2+y*x+y^3)/x,y) polresultant(-y^7 + x*y^2 + x^4,(624*y^10 + 832*x^3*y^8 - 156*x*y^5 - 117*x^2 )/y) a=ffgen([2,2],'a); f=x^6 + (y^5 + (a + 1)); g=(a*x^11+a*x^10+(a*y^2+(a+1)*y+(a+1))*x^9+((a+1)*y^3+(a+1)*y^2+y)*x^8+(y^3+a*y^2+a)*x^7+(y^4+y^3+y+a)*x^6+(a*y^3+y^2+(a+1)*y+1)*x^5+((a+1)*y^3+a*y^2+y+(a+1))*x^4+(a*y^3+y^2+(a+1)*y+a)*x^3+((a+1)*y^3+a*y)*x^2+(a*y^3+a*y^2+a*y+a)*x+((a+1)*y^4+y+1))/(a*x^3+(a+1)); polresultant(f,g,'y) pari-2.17.2/src/test/in/sumdedekind0000644000175000017500000000013414567450071015566 0ustar billbillsumdedekind(-2,-3) sumdedekind(2, 4) sumdedekind(123186,28913191) sumdedekind(2^64+1, 2^65) pari-2.17.2/src/test/in/multiif0000644000175000017500000000061314567450071014745 0ustar billbillf(x)= { if(x==1,print(1)); if(x==1,print(1) ,print("default")); if(x==1,print(1) ,x==2,print(2)); if(x==1,print(1) ,x==2,print(2) ,print("default")); if(x==1,print(1) ,x==2,print(2) ,x==3,print(3)); if(x==1,print(1) ,x==2,print(2) ,x==3,print(3) ,print("default")); } for(i=1,4,f(i)); g(x)=if(x,return(1),return(2),return(3)); g(1) g(0) pari-2.17.2/src/test/in/ell0000644000175000017500000003614214760123736014056 0ustar billbilldefault(parisize,"14M"); \\ overflows 10M [GMP], 12M [porable] /* Test generic */ F={ [ellwp, ellzeta, ellsigma, ellformalw, ellformalpoint, ellformaldifferential, ellformallog, ellformalexp, E->ellisoncurve(E,[0,0]), E->ellordinate(E,0), E->elldivpol(E,5), E->ellxn(E,3), E->ellmul(E,[0,0],0), E->ellneg(E,[0,0]) ]; } L={ [1,I,'z,Mod('z,'z^2+5), ellinit([0,0,0,'z,0],nfinit('z^2+5)), Mod(4,1009),ffgen([1009,5],'z)]; } L=apply(x->if(type(x)=="t_VEC",x,ellinit([x,0])),L); for(j=1,#F,for(i=1,#L, print(F[j],":",L[i][4],":",F[j](L[i])))); ellap(ellinit([1,0,1,4,-6]), 2) ellap(ellinit([0,17]), 2) ellap(ellinit([0, 0, 1, -1, 0]),2486246173) testgroup(v,p)= { my(E,F,G,g); E=ellinit(v); if(!E || E.disc%p==0, next); G=ellgroup(E,p,1); if (G.no == 1, return); g=G.gen; if (!ellisoncurve(E,g), error(E, G)); F=vector(#g,i, ellorder(E,g[i],G.no)); if ((p <= 3 && F!=G.cyc) || (p > 3 && F[1] != G.cyc[1]), print("error:",v,":",F,":",G)); } { for(x=10,63, my(p,E,G,g); p=nextprime(2^x);E=ellinit([0,0,1,2,3]); G = ellgroup(E,p,1); if (!ellisoncurve(E,G.gen), error(E)); if(ellorder(E,G.gen[1])!=G.cyc[1], error(E)); print(p,":",ellgroup(E,p))); for(p=2,3, forvec(v=vector(5,i,[0,p-1]), testgroup(v,p))); forvec(v=vector(2,i,[0,4]), testgroup(v,5)); } setrand(1) a=ffgen(2^8,'a); E=ellinit([a,1,0,0,1]); P=[a^3,ellordinate(E,a^3)[1]]; Q=ellmul(E,P,113); e=elllog(E,P,Q,242) ellmul(E,Q,e) == P ellpow(E,Q,e) == P p=655637; E=ellinit([123,47], p); X=1;until(Y!=[],X++;Y=ellordinate(E,X)); P=[X,Y[1]]; Q=ellmul(E,P,113); o=ellorder(E,P, p+1-ellap(E,p)) e=elllog(E,P,Q,o) ellmul(E,Q,e) == P p=1073741827; E=ellinit([1,3], p); G=[Mod(1050932506,p),Mod(12325986,p)]; P=ellmul(E,G,1023); elllog(E,P,G) ellorder(ellinit([0,2],1),[-1,-1]*Mod(1,997)) ellinit([a1,a2,a3,a4,a6]*Mod(1,5)); ellinit([a1,a2,a3,a4,a6]); ellinit([0]).j ellinit([1728]).j ellinit([j]).j ellinit([Mod(0,2)]).j ellinit([Mod(0,5)]).j ellinit([Mod(3,5)]).j ellinit(['j*Mod(1,2)]).j ellinit([Mod(0,3)]).j ellinit([3], 3).j ellinit([1728], ffgen(3^5,'a)).j ellinit(['j*Mod(1,3)]).j elltwist([0,a2,0,a4,a6],x^2-D/4)[1..5] lift(elltwist([a1,a2,a3,a4,a6]*Mod(1,2),x^2+x+T)[1..5]) elltwist([a1,a2,a3,a4,a6],1)[1..5] elltwist([a1,a2,a3,a4,a6],-4)[1..5] elltwist([a1,a2,a3,a4,a6],5)[1..5] elltwist([a4,a6],5)[1..5] e = ellinit([4,0]); ellminimaltwist(e) ellminimaltwist(e,1) e = ellinit([-882216989/131072]); e = ellintegralmodel(e,&v) v ellminimaltwist(e) ellminimaltwist(e,1) twisttest(c4,c6, T)= { my(e = ellinit([c4/-48, c6/-864])); vector(#T, i, my (et = ellinit(elltwist(e, T[i]))); my (d = ellminimaltwist(et)); et = ellinit(elltwist(et,d)); [d, ellminimalmodel(et).disc]); } T3 = [1,-3]; twisttest(-4*3,8*3^3, T3) twisttest(0,8*3^3, T3) twisttest(-4*3,0, T3) twisttest(16,-8*19, T3) twisttest(-4*3^4, 8*3^6, T3) twisttest(4*3^6, 16*3^9, T3) T2 = [1,-4,8,-8]; a=2;b=3; twisttest(3*2^a, 9*2^b, T2) a=4;b=5; twisttest(3*2^a, 9*2^b, T2) b=5; twisttest(0, 9*2^b, T2) a=4; twisttest(3*2^a, 0, T2) twisttest(1, -161, T2) d=2; twisttest(-17*2^(2*d), 2^(3*d), T2) ellminimaltwist(ellinit([216,-432]),1) a=ffgen(2^5,'a);ellinit([a]).j a=ffgen(3^5,'a);ellinit([a]).j e = ellinit([1,2,3,5,7]); elldivpol(e,4) elldivpol(e,-1) elldivpol(e,-2) elldivpol(e,-3) ellxn(e,0) ellxn(e,1) ellxn(e,2) ellxn(e,4) ellxn(e,5) P=[-1,1]; Q=ellmul(e,P,20); if (ellisdivisible(e,Q,0,&A), A) if (ellisdivisible(e,[0],0,&A), A) if (ellisdivisible(e,Q,1,&A), A) if (ellisdivisible(e,Q,20,&A), A) if (ellisdivisible(e,Q,-20,&A), A) if (ellisdivisible(e,Q,2,&A), A) if (ellisdivisible(e,Q,5,&A), A) if (ellisdivisible(e,Q, ellxn(e,5), &A), A) if (ellisdivisible(e,Q,11,&A), A) if (ellisdivisible(e,Q,22,&A), A) e = ellinit([0,1]); elldivpol(e,8) \\ #2106 e = ellinit([0,0,1,-1,0]); P = [0,0]; K = nfinit(nfsplitting(elldivpol(e, 3))); eK = ellinit([0,0,1,-1,0], K); ellisdivisible(eK, P, 3) P6 = ellmul(eK, P, 6); if (ellisdivisible(eK, P6, 3, &Q), Q) if (ellisdivisible(eK, P6, 2, &Q), Q) \\ #2408 e=ellinit([-25,0]); p=[-4,6]; q=ellmul(e,p,4); ellisdivisible(e,q,4) ellisdivisible(e,q,2^64) e=ellinit([1,0,0,-45,81]); ellisdivisible(e, [6,3], 2) ellisdivisible(e, [6,3], 2*7^64) ellisdivisible(e, [6,3], 5*7^64) ellisdivisible(e, [6,3], 5^64) e = ellinit([1,2,3,4,5]); e.omega E = ellchangecurve(e, [2,3,4,5]); E.omega ellisisom(e, E) nf=nfinit(w^2-5); e=ellinit([13051432067771989785714502010560*w-29183889307258811368264006524000,38378930075688840770085369672398433447789974880*w-85817896552951396873277345020781210730736734000],nf); e.omega E=ellchangecurve(e,[2+w,5+2*w,w-1,3]*Mod(1,nf.pol)); E.omega ellisisom(e, E) e = ellinit([1.,2,3,4,5]); e.eta E = ellchangecurve(e, [2,3,4,5]); E.eta e = ellinit([1,2,3,4,5]); e.eta; e.roots; E = ellchangecurve(e, [2,3,4,5]); E.omega E.eta E.roots ellglobalred(E) ellglobalred(e) p = 2^64+13; E = ellchangecurve(e, [1/p, 2,3,4]); elllocalred(E,p) E = ellchangecurve(e, [1,0,0,0]); E = ellchangecurve(e, [2,3,4,5]*Mod(1,7)); iferr(E.omega, e, e); E.group ellminimalmodel(ellinit([1/5,1/4,1/3,1/2,1],1),&v) v j=ffgen(2^5,'a);e = ellinit([j]); e.group; elllog(e,e.gen[1],e.gen[1]) E = ellchangecurve(e,[3,7,1,0]); E.group e = ellinit([Mod(1,3)]); e.group; elllog(e,e.gen[1],e.gen[1]) E = ellchangecurve(e,[2,7,1,0]); E.group e = ellinit([Mod(1,5)]); e.group; elllog(e,e.gen[1],e.gen[1]) E = ellchangecurve(e,[2,7,1,0]); E.group e = ellinit([1/3 + O(3^9)]); e.roots e = ellinit([1/3], O(3^5)); e.tate iferr(ellinit(e,O(5)),E,E) iferr(ellinit(e,5),E,E) iferr(ellinit(e,1.0),E,E) e.roots E = ellchangecurve(e,[3,1,1,2]); E.tate ellztopoint(e,3) e = ellinit([11/8], O(2^5)); e.tate e = ellinit([1,0,1,4,-6], O(2^5)); e.tate e = ellinit([0,-1,1,-10,-20]); \\#1185 ellwp(e,x+O(x^12)) \\#1683 ellztopoint(e,3*e.omega[1]/5) ellwp(e, 0.1 + 0.2*I, 1) \\#1683 e = ellinit([1,1,0,-1740,22184]); z=-3.0059315873096303229151114945365166621 + 0.E-36*I/2; ellztopoint(e,z) \\#1800 ellztopoint(ellinit([-1,0]), I) \\#1186 ellmul(ellinit([3,0]), [1,2], -quadgen(-4)) \\#2060 ellzeta([1,I],2/10+I) \\#2061 ellsigma([1,I],1/2+I) logsigma(e,z='x)=if(type(z) != "t_POL" && type(z) != "t_SER", ellsigma(e,z,1)); v = [ellwp,ellzeta,ellsigma,logsigma]; ellperiods([1,0.1 + I/10^50]) e = ellinit([1,1]); w = ellperiods([1,I/2]) w2 = ellperiods([1,I/2], 1) u = [e,w,w2]; { for (i = 1, #v, my(f = v[i]); for (j = 1, #u, my (a = u[j]); print([i,j]); print(f(a)); print(f(a, x+O(x^10))); print(f(a, 1/3)); print(f(a, I/3)); print(f(a, (1+I)/3)); ) ) } ellK(1/3) ellK(x+y); \\ would overflow stack ellE(1) ellE(1/3) ellK(1/3+I) ellE(1/3+I) elleta(e) elleta([1,I]) v = [x->elleisnum(x,2),x->real(elleisnum(x,4,1)),x->real(elleisnum(x,6,1)),x->real(elleisnum(x,10))]; { for (i = 1, #v, my(f = v[i]); print(f); print(f(e)); print(f(w)); print(f(w2)); ) } elleisnum([1,I/2^30],2) elleisnum([1,I/2^30],4) \\ #2167 E=ellinit([0,-1,1,-10,-20]); e=elleisnum(E,4,1) bitprecision(e) \\ #1257 ellrootno(ellinit([0,-1,1,217,-282])) \\ #1296 e=ellinit([0,-1,0,-33,62]); ellztopoint(e,-2.5261979245524788020279452840822073870+0.E-36*I) \\ #1308 ellinit([108/91,11664/8281,-6561/8281,708588/753571,-14348907/68574961]).disc e=ellinit([-4179962088,-104017551778988]); P=[-12142738583336098442192836816176736488756409885083993663515903318775477283438352137135249323/325305271731471715644495647421121780765173058515779520952978859131039949432429351736409, 8334307521730470040507793911525024226184207596596408790562824419588749760136126836698728499174598419862301314492216896610149595/5867277807417841262595745323516111503774365731904549455908426496476272821377832232255239022995172589310668134318512865886323566173]; exponent(ellztopoint(e,ellpointtoz(e,P))[1] - P[1]) e=ellinit([1,3.+I]); x=1/2+I; y=ellordinate(e,x)[1]; ellztopoint(e,ellpointtoz(e,[x,y])) testzellQp(e, P)= { my(a,q,Q); a = ellpointtoz(e,P); Q = ellztopoint(e,a); if (liftall(Q-P),error([e,P])); print(a); q = e.tate[3]; a = a^2; if (type(a) == "t_PADIC", a /= q^(valuation(a,a.p) \ valuation(q,a.p)); /* reduce mod q^Z */ ); a - ellpointtoz(e, elladd(e,P,P)); } e=ellinit([0,-1,1,0,0], O(11^5)); \\ BIB #1840 iferr(ellpointtoz(e,[Mod(3,'x^2+1),1]), E, E) iferr(testzellQp(e, [0,0]), E, E) E3 = ellinit([0,-1,0,-24,-36], O(3^20)); iferr(ellpointtoz(E3,[-3,0]),E,E) iferr(ellpointtoz(E3,[6,0]),E,E) iferr(ellpointtoz(E3,[-2,0]),E,E) e=ellinit([1,1,1,-10,-10], O(3^5)); testzellQp(e, [3,-2]) iferr(testzellQp(e, ellmul(e,[0,0],2)), E, E) \\ not on curve ! e=ellinit([2/9], O(3^10)); x=2; y=ellordinate(e,x)[1]; testzellQp(e, [x,y]) e=ellinit([1/4], O(2^10)); x=1/2; y=ellordinate(e,x)[1]; testzellQp(e, [x,y]) e=ellinit([1,-1,1,98,126],O(5^10)); testzellQp(e, [1,14]) e=ellinit([1,1,1,3,-5],O(2^10)); testzellQp(e,[5,10]) e=ellinit([1,-1,1,-48,147], O(2^10)); testzellQp(e,[13,-47]) ellinit([1,1], Mod(1,11)) ellrootno(ellinit([31^4,31^6]), 31) e=ellinit([1,0,0,1,1]); ellordinate(e, I) E=ellchangecurve(e,[1/(2^4*3^4*5^2*7),2,3,4]); forprime(p=2,11, if (ellap(e,p) != ellap(E,p),error(p))); for(k=2,50, if (ellak(e,k) != ellak(E,k),error(k))); if (ellan(e,100) != ellan(E,100),error("ellan")); P=ellchangepoint([0,1],[1,2,3,4]) ellchangepointinv(P,[1,2,3,4]) \\#1416 E=ellinit([155818018413/16,-78179511999813417/32]); ellminimalmodel(E,&v); E2=ellchangecurve(E,v); ellminimalmodel(E2,&w); w \\#1432 E=ellinit([-3,-60,480,0,0]); ellheight(E,[0,0]) iferr(ellheight(E,[0.,0]), e, e) p=10^20+39; q=10^21+117; e = ellinit([p^3*q^4,p^6*q^4]); ellminimalmodel(e,&v); v e = ellinit([p^4*q^4,p^6*q^4]); ellminimalmodel(e,&v); v e=ellminimalmodel(ellinit([1,1])); e=ellchangecurve(e,1) e=ellchangecurve(e,[2,0,0,0]) ellinit(ellinit([0,1]*Mod(1,5),ffgen(5^2))); J=[0,1728,-3375,8000,54000,-32768,287496,-884736,-12288000,16581375,-884736000,-147197952000,-262537412640768000]; { for (i=1,#J, my(e = ellinit([J[i]])); my(v = ellan(e,200)); print("\n", e.j); forprime(p = 127, 200, print1(v[p]," ")); print(); forprime(p = 2^65, 2^65+1000, print1(ellap(e,p)," ")); ); } p=2^32+15; ellcard(ellinit([1,2,3,4,5], p)) E=ellinit([625,15625]); elllocalred(E,5) ellisoncurve(E,[0.,125.]) ellisoncurve(E,[1e-50,125+1e-50]) elladd(E,[0.,125.],[0.,125+1e-38]) iferr(ellmul([0,1,0,2,-15],[2,1],5),E,E) x='x; E=ellinit([x^2,x]) iferr(ellminimalmodel(E), e, e) iferr(ellweilpairing(E,[0],[0],1), e, e) ellinit([1,2],1.) ellinit([ffgen(5),1],5) ellinit([1.,1],precision(1.,60)) \\#1527 E = ellinit([0,0,0,-82,0]); ellrootno(E,2) ellrootno(E) ellrootno(E,2) E=ellinit([0,20,0,-352,512]); ellrootno(E,2) E.disc elltamagawa(E) ellbsd(E) F=ellinit([-1456/243,93184/19683]); /* isomorphic to E */ ellrootno(F,2) F.disc elltamagawa(F) ellbsd(F) E=ellinit([1,0,1,4,-6]); E.disc elltamagawa(E) ellbsd(E) ellbsd(ellinit([-5*36^4,0])) \\#1558 ellap(ellinit([-1137195,489565862]),2038074751) ellap(ellinit([582304190,64196421]),2147438927) e=ellinit([0,-1,1,-2,2]); P=[2,-2]; ellnonsingularmultiple(e, P) e=ellinit([-111,214]); P=[35,-198]; v = [4*3,12,214,12]; e=ellchangecurve(e,v); P=ellchangepoint(P,v); ellnonsingularmultiple(e,P) e=ellinit([0,-1,1,-2,2]); test(f)=print(f(e,,'t)); print(f(e,5)); print(f(e,5,'t)); F=[ellformalw,ellformalpoint,ellformaldifferential,ellformallog,ellformalexp]; for(i=1,#F,print(F[i]);test(F[i])); \\#1637 U=[-245369975623514803521420211420402474815373720177518420696215292670924086780233779586506792145074717/4069861969699146045958032034788970995470603578576,-696053034387689435413673877713244121475782562610666903528251447608130654196417305610237634015759861/4069861969699146045958032034788970995470603578576,-49356694805693369953216822105035107974083562942605713355717183776373331122267882948881129025418396548321363993080002121985116427859996985649385099335/4069861969699146045958032034788970995470603578576,5996724761485351384753083917633373954904218466995628499407992841502416127074022935350022919212488198205525833829916828282709837728834438536000230267/1017465492424786511489508008697242748867650894644,-1943033527672518505867347410801184866534773028979571976479290969993491996577167508758887358085512124817167326269402804641328588524702957475568608101932310746684310251168033629279636817525659690186705/4069861969699146045958032034788970995470603578576]; E=ellinit(U); P=[283188771261789732541662405743402980051199109235,39175522019721182331498476245534716069785193060995]; ellheight(E,P) \\#1648 ellinit([0,0,0,0,1]).a1 E=ellinit([-22032-15552*x,0], nfinit(x^2-2)); P=[-72*x-108,0]; elltwist(E,1).nf.pol elltwist(E,-3).nf.pol ellpointtoz(E,P) E=ellinit([134199387,91266697],3031140653); P = [911071793,1086747416]; Q = ellmul(E,P,2); elllog(E,Q,P) ellheight(ellinit([1,0,1,4,-6])) ellheight(ellinit([0,-1/5])) \\ #448 E=ellinit([0,1,1,20,-890]); P=ellmul(E,[16,61],45*23); ellsaturation(E,[P],100) E=ellinit([0,0,1,-7,6]); V=[[1879462415967166/931705846156449,-30751668616480047298756/28439256014143448903793],[-4918796969449106250916/1682155121549140256041,-124886419810479084631920999334858/68992052177891195733628251285589],[72257627402076649/69972081056148496,-2774239841245604882535253/18509180294972016896964544]]; ellsaturation(E,V,100) E=ellinit([1,0,0,-302,-2036]); P=ellmul(E,[-10,8],27); ellsaturation(E,[P],100) E=ellinit([1,0,0,-24432,-1471934]); P=ellmul(E,[-36131/400,361313/8000],27); ellsaturation(E,[P],100) E=ellinit([1, -1, 0, -68705883315799311348202115610, -6927648117957955118232151592960456184746700]); P= {[[113342761790029931460/10201, 1206337152320852615766208461270/1030301], [636777339479579609637060/2785561, 508137344974540844766208684877873430/4649101309], [-2765318487951880977574055644295509649664609591740/ 18638910579269379823833484960252281, -19371097071038068258214678181828244987430387816577790939234819716151670/ 2544666000475387448352622851610210610184352554784179] ]; } Q=ellsaturation(E,P,3); matdet(ellheightmatrix(E,Q)) \\ elltrace E = ellinit([0,0,0,1,15]); x = 'x; y = 'y; t = 't; T = x^3-135*x-408; P1 = Mod([x/8-1,1/32*x^2 - 11/32*x - 19/4],T); P2 = Mod([2,5],T); P3 = Mod([0,y],y^2-15); P4 = [0,Mod(y,y^2-15)]; P5 = Mod([t,2],t^3+t+11); elltrace(E,[0]) elltrace(E,P1) elltrace(E,P2) elltrace(E,P3) elltrace(E,P4) elltrace(E,P5) E=ellinit([1,0]); elltrace(E,Mod([t,0],t^2+1)) elltrace(E,[0,0]*Mod(1,t^3-2)) E=ellinit([-13^2,0]); elltrace(E,[-10*x^3+10*x-13,-16*x^3+16*x-34]*Mod(1,x^4-x^3+2*x-1)) E=ellinit([2,3],19); P=[11*x^3+11*x^2+x+12,15*x^4+9*x^3+18*x^2+18*x+6]*Mod(1,x^5+x^4+15*x^3+16*x^2+3*x+1); elltrace(E,P) foreach([1,0,1728,8000,54000,287496,16581375,-3375,-32768,-884736,-12288000,-884736000,-147197952000,-262537412640768000], j, print(elliscm(ellinit([j])))) \\ ERRORS, keep at end of file ellK(1) ellinit([]) ellinit([1,1],quadgen(5)) ellinit([Mod(1,2),1],O(2)) ellinit([O(2),1],ffgen(2^3)) ellinit([O(2),1],1.) ellinit([ffgen(5),1],3) ellinit([1.,Mod(1,3)]) e=ellinit([0,-1,1,-2,2]); ellformalw(e,0) ellformalw(e,-1) elltwist([0,0]) ellchangepoint([[1,1],1,1],[1,0,0,0]) ellpointtoz(e,[1,[0]]) ellpointtoz(E3,[1,[0]]) ellchangepoint([1],[1,2,3,4]) ellchangepoint([1,2,3],[1,2,3,4]) ellchangepointinv([1],[1,2,3,4]) ellchangepointinv([1,2,3],[1,2,3,4]) ellchangepoint([;],[1,2,3,4]) ellchangepointinv([;],[1,2,3,4]) ellchangepoint(Mat(1),[1,2,3,4]) ellchangepointinv(Mat(1),[1,2,3,4]) E=ellinit([0,1]); chbug = Vecsmall([if(sizebyte(0)==16,2^62,2^30)+3,1]); \\ mimic gen_1 ellchangecurve(E, chbug) ellchangepoint([0,0], chbug) ellchangepointinv([0,0], chbug) pari-2.17.2/src/test/in/debugger0000644000175000017500000000114314567450071015057 0ustar billbill\e default(breakloop,1) my(bound=100,step=20,halt=41); check(B)= { my(bi=[B^2]); for(i=1,bound, my(p=i+step,N=p^2); if(i==halt,error("check:",N))) } check(1000); [bound, step, halt, i, p, N, bi, B] break [bound, step, halt, i, p, N, bi, B] my(p=120);for(i=1,100,1/0) [p,i] dbg_err() break fun(N)=check(N^2+1); fun(20); N dbg_up(4) N dbg_down(4) N break f(N,x)=my(z=x^2+1);breakpoint();gcd(N,z^2+1-z); f(221,3) z z iferrname("e_VAR",vector(10000,i,1/(i-100)),E,Vec(E)) i break f()=1/0 f(); allocatemem(10^7) for(i=1,10,if(i==2,1/0)); i N=5 M=6;1/0 break N M break F1(T) = 1/0; F1(2) dbg_up T break pari-2.17.2/src/test/in/plotexport0000644000175000017500000000156114676526175015531 0ustar billbill\\ platform independent test(s)= concat(Vec(s)[30..88]); plotinit(0,500,500) plotmove(0,0,0);plotbox(0,500,500) test(plotexport("ps",[0,0,0])) 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); plotpoints(0,225,334) plotpoints(0,vector(10,k,10*k),vector(10,k,5*k*k)) test(plotexport("svg",[0,20,20])) test(plothexport("svg",x=-5,5,sin(x))) test(plothexport("svg",t=0,2*Pi,[sin(5*t),sin(7*t)],1,100)) test(plothrawexport("svg",vector(100,k,k),vector(100,k,k*k/100))) plotmove(0,50,50);plotrbox(0,50,50) plotrline(0,200,150) plotrmove(0,5,5); plotrpoint(0,20,20) plotinit(3,600,600);plotscale(3,-7,7,-2,2); test(plotexport("svg",[0,0,0])) plotmove(0,100,100);plotstring(0,Pi); plotmove(0,200,200);plotstring(0,"(0,0)"); test(plotexport("svg",[0,10,10])) localbitprec(32); s = plothexport("svg", X=-1,1,sin(1/X), "Recursive"); pari-2.17.2/src/test/in/ellratpoints0000644000175000017500000000246714676526175016037 0ustar billbillW= {[ [0, 0, 1, -79, 342], [1, 0, 0, -22, 219], [0, 0, 1, -247, 1476], [1, -1, 0, -415, 3481], [0, 0, 0, -532, 4420], [1, 1, 0, -2582, 48720], [0, 0, 1, -7077, 235516], [1, -1, 0, -2326, 43456], [1, -1, 0, -16249, 799549], [1, -1, 1, -63147, 6081915] ]; } check(E)= { E=ellinit(E); L=ellratpoints(E,1000); if(#L!=#Set(L),error([E,L])); for(i=1,#L,if(!ellisoncurve(E,L[i]),error([E,L[i]]))); #L+1; } for(i=1,#W,print(check(W[i]))) check([0,0,1/7^3,-7/7^4,6/7^6]) E=ellinit([-25,1]);ellratpoints(E,10,1) E=ellinit([-25,2]);ellratpoints(E,10,1) E=ellinit([0,0,1,-7,6]);ellratpoints(E,[10^5,1]) E=ellinit([0,0,1,-7,6]);ellratpoints(E,[10^5,[5,10]]) checkhyp(P,Q)= { L=hyperellratpoints([P,Q],10000); if(#L!=#Set(L),error([P,Q,L])); for(i=1,#L, if(!hyperellisoncurve([P,Q],L[i]),error([P,Q,L[i]]))); #L; } P=82342800 *x^6 - 470135160 *x^5 + 52485681 *x^4 + 2396040466 *x^3 + 567207969 *x^2 - 985905640 *x + 247747600; hyperellratpoints(P,[10,1]) checkhyp(P,0) checkhyp(-x^6+x^3+x+1,2*x^3) checkhyp((-x^6+x^3+x+1)/4,x^3) checkhyp((-x^6+x^3+x+1)/16,x^3/2) checkhyp(x^6+4*x+1/7) hyperellratpoints(9*x^2,3) hyperellratpoints(x^2+x+1,[5,10]) P=780778196253125*x^4+406402229450000*x^3+76766809420000*x^2+5710274976000*x+95843046656; hyperellratpoints(P,[0,1]) \\ errors E=ellinit([0,0,1,-7,6]);ellratpoints(E,[10^5,[5]]) pari-2.17.2/src/test/in/incgam0000644000175000017500000000171414676526175014547 0ustar billbillVs=[0,10^-10,10^-100,200,-21/2,1/2,10-I,1+128*I,60,30+60*I]; Vx=[19+236*I,1/10,-1/10,I/10,-I/10,1/10-I/10,50,100,-100,100+1001*I]; test(fun, p) = { my (P = 1/10.^(p-1)); for (i=1,#Vs, for (j=1,#Vx, my (v,w, s = Vs[i], x = Vx[j]); localprec(p); v = fun(s, x); localprec(p + 38); w = fun(s, x); e = abs((v-w)/w); \\ e = if (abs(w) < 1, abs(v-w), abs((v-w)/w)); if (e > P, printf("%9s, %13s: %.1e\n", s,x,e)); ) ); } test(incgam, 115) test(incgam, 19) test(incgam, 38) test(incgam, 77) test(incgam, 96) Vs=[1/10+1/5*I,-1/10,-1/10+2/5*I,2/5*I,-2/5*I,-1,-20,-200001/10000]; Vx=[11/10,13/10,1/10000]; test(incgam, 38) test(incgam, 76) incgam(-1000.4,2) incgam(1/2,10^8) incgam(-3,20) incgam(1/5,50) incgamc(2,0) printf("%.28Pg\n", imag(incgam(110.0,I))) printf("%.28Pg\n", imag(incgam(110,I))) incgam(110.0,10*I) eint1(-0.3-95*I) eint1(100) incgam(-10+1e-100,1) eint1(2,5) \p1000 eint1(100) \p481 eint1(150) eint1(0) pari-2.17.2/src/test/in/modfun0000644000175000017500000000032114676526175014572 0ustar billbilleta(2+O(2^20)) eta(x+x^2+x^3+x^4+O(x^5)) eta(x+2*x^2+ O(x^5)) eta(I) ellj(2+O(2^20)) ellj(x+x^2+x^3+x^4+O(x^5)) ellj(x+O(x^70)) theta(1/2,I) weber(1.0*I,1) weber(1+I) weber(I/2+1/3,2) \\errors eta(0) eta(1/2) pari-2.17.2/src/test/in/nffactor0000644000175000017500000003525514676526175015122 0ustar billbilldefault(parisize,"16M"); \\ 14M overflows do(T, P) = lift(nffactor(nfinit(T),P)[,1]); do(polcyclo(13,y),x^72-291*x^70+168*x^69+40380*x^68-48588*x^67-3528919*x^66+6672120*x^65+215657160*x^64-575538144*x^63-9642387423*x^62+34735086786*x^61+318475831783*x^60-1543992152304*x^59-7526047084203*x^58+51709921323996*x^57+110268119466273*x^56-1306863903654948*x^55-197687339387338*x^54+24340617020480994*x^53-37674206381844006*x^52-309388136734870296*x^51+1097175021601270233*x^50+1965430743178095924*x^49-17057741307681944498*x^48+12695705864721864408*x^47+149941210123858078557*x^46-449449010694960248724*x^45-360137445013361079753*x^44+4743771886303072354536*x^43-7957480107528139931362*x^42-20006312987061736459890*x^41+103127662005251951018025*x^40-57922725775374790826892*x^39-575374977336477060878406*x^38+1141042155363070337681952*x^37+2107623272811930164219492*x^36-8555883275792119671168984*x^35-6622038332271478648217502*x^34+67788499073804904961005264*x^33-62194621346216574281355513*x^32-298503076979390816950994616*x^31+935868776923024509133161567*x^30-602191893688026944562387144*x^29-2378403718028116295265005703*x^28+7144715267789671188060423636*x^27-8264313767410946129053876314*x^26-2988303993119955116599622124*x^25+36320303706133493815706370331*x^24-93405543373036036850518472592*x^23+137892731303549623166716872621*x^22-73374564495372153466268524626*x^21-180690507689854149951443988039*x^20+506199649638427572646328975856*x^19-511453665473658325356669209047*x^18-183193264910244539106552118338*x^17+1423840911419731272911578335897*x^16-2367314022969857609246689985844*x^15+2236677523353346112926136338695*x^14-1548489683091587051973217338168*x^13+2105049137205776145162583648404*x^12-4754348311294629767834593856064*x^11+7567806891220394207855512254933*x^10-7605431066578089163623568649610*x^9+3882625664788999249342771140339*x^8+1356469287400668040516453202076*x^7-3841355512345259545848813224621*x^6+2330504083587501732658867007532*x^5-169172628407290891217225606775*x^4-398965703199322569698936377044*x^3+198978398979453484569202793808*x^2-60597282938946837445378411698*x+12280639561039083425818958713) do(polcyclo(5,y),x^48+12*x^46+948*x^44+7200*x^42+152361*x^40+815832*x^38+9475380*x^36+44654004*x^34+299137536*x^32+1335241260*x^30+5029216452*x^28+15282825984*x^26+37737671337*x^24+79579803672*x^22+143658877428*x^20+222699104460*x^18+303698198961*x^16+348787956312*x^14+312863646960*x^12+212893847424*x^10+111407984496*x^8+43762394880*x^6+11836253952*x^4+1904684544*x^2+136048896) do(polsubcyclo(17,8,y),x^48-104*x^46+4664*x^44-122476*x^42+2137838*x^40-26567700*x^38+245144964*x^36-1725955872*x^34+9441692003*x^32-40611588644*x^30+138356971048*x^28-374714866240*x^26+807289826646*x^24-1380693858220*x^22+1866021172640*x^20-1978766780068*x^18+1630151673857*x^16-1029505301024*x^14+489498952012*x^12-170832297056*x^10+42133382284*x^8-6904507136*x^6+669868016*x^4-28899680*x^2+16) do(polsubcyclo(19,6,y),x^64-6384*x^62+18261761*x^60-31231019568*x^58+35925400902280*x^56-29635423138225800*x^54+18244443900381139917*x^52-8609789775431197305288*x^50+3173715440318358526295493*x^48-926253189958924421506713024*x^46+216130107574547887816493973792*x^44-40600173780591579547211667354912*x^42+6168621134132051706341715912515370*x^40-760139434277348135867991392951415744*x^38+76052955647065900426700689494084391434*x^36-6175311843554416772593815034596603661344*x^34+406137362468726923132369140307868626461744*x^32-21559959594011538596615817038079394912524336*x^30+919122010228667702998458013093798368177514170*x^28-31251399013676293208252728256910183010646331888*x^26+840017792466500823059432352741453680599704357258*x^24-17651171087877975905738341268934550365403253370816*x^22+285940694256111366646633973109729677687028435758880*x^20-3510138236669349338216717168753743720690200440965920*x^18+31970659328447652254136627725804141367170891626180389*x^16-210577501276259853380917767547980363666145460503950096*x^14+972633665701140285445722173171004563157651576027463941*x^12-3038789368329382179884462851269146550248145196800679728*x^10+6158927928896588396670590928896385649075890120481042824*x^8-7695135079270077790657693634058524039308535641860032904*x^6+5510293734552561962521574495431679567021222445632508873*x^4-1998778331104544904932086470347413669495129560426038280*x^2+273892744995340833777347939263771534786080723599733441) do(y^16-748*y^14+183362*y^12-18209312*y^10+854163776*y^8-19811731456*y^6+217053667328*y^4-963359277056*y^2+1401249857536,x^64-50520*x^62+1184742668*x^60-17134912892184*x^58+171302841202784230*x^56-1257730595773642457272*x^54+7035168717087126283039868*x^52-30701149599207543908253060456*x^50+106209876041363261331175274376961*x^48-294437498300554938723628131780900528*x^46+658747632370852789155278036118795891376*x^44-1194508299658559259423544698671941624911936*x^42+1758886106345358997541429698467814358261692768*x^40-2102877763749659939135348751421310839041552295168*x^38+2037272869739882513058383232251947632400144748327680*x^36-1593244672706602785431833797822694649876503949099971584*x^34+1000137401948528280332750479657406431558467421878362177792*x^32-500163144667908835632768747437877749311388525989506418016256*x^30+197386643425666396587295586758946216300889646426384501395505152*x^28-60764991565332609893728829321665731738637757708625749066895851520*x^26+14391680825163014577680716072706067747656540117078764576362349133824*x^24-2579614931575491289251668514169821364409673054271152939186037020688384*x^22+343089307498773969742537952871359998792597096472804803564329469006053376*x^20-33039893809399713739300133477660888984993965585329459081212907387885715456*x^18+2232207983615195492545494908634867604311043135572503317867045868579149840384*x^16-101424324951708207798235121163034156328923938680623314497489525231592962785280*x^14+2924360883858624736764622501847786486366632522081726107231999581887779150233600*x^12-49361130671745243582144295846906126266126621338339076133495563142930969537806336*x^10+439086453618923969602036267436177792533605154882821831371393950663185250364948480*x^8-1791241595903032942764035441499088453133177154876529243608326027299172423825358848*x^6+3156683219740128500900617761806000080676491013147893106666462267204557337199116288*x^4-2047559682560580731342531379502232338263001052780076721919148124626016913223319552*x^2+364046770867177439711105777657339121207381033680019800170419997640962734592884736) do(y^20+1161*y^16+357096*y^12+15694096*y^8+129931776*y^4+26873856,x^20+1219*x^16+25560*x^14+1352565*x^12+15766260*x^10+468310924*x^8-1266123120*x^6+27117441616*x^4+101145350400*x^2+914700960000) do(y^3+y^2+2,x^24+69) do(y^4+7^2,x^28-14*x^24+20321*x^20+166992*x^16+1171296*x^12+1342208*x^8-5005056*x^4+3211264) setrand(1);do(y^16-24*y^14+196*y^12-696*y^10+1118*y^8-840*y^6+292*y^4-40*y^2+1,x^32-208*x^30+12736*x^28-330032*x^26+4326444*x^24-32221712*x^22+147532904*x^20-437660272*x^18+869634612*x^16-1179150112*x^14+1097619208*x^12-696893680*x^10+295476664*x^8-80251024*x^6+12946192*x^4-1075648*x^2+33614) setrand(29);do(y^16+6*y^8+1,x^64+112*x^60+4672*x^56-61472*x^52+1722640*x^48-19382720*x^44+137146112*x^40+89961600*x^36+762162272*x^32-7723483904*x^28+17460562944*x^24+100233636352*x^20+74611011840*x^16-74722169856*x^12+20300812288*x^8+1358714880*x^4+21381376) setrand(6);do(y^16+2,x^64+192*x^62+17568*x^60+1019520*x^58+42131676*x^56+1319651424*x^54+32559096528*x^52+649228312512*x^50+10651553826426*x^48+145639438552224*x^46+1674922821206832*x^44+16307859539653056*x^42+135023677732167696*x^40+953248899971965824*x^38+5745239175305568960*x^36+29556064271185194240*x^34+129595725382952883843*x^32+483002100692576612640*x^30+1523870714370199019760*x^28+4047489983524093705152*x^26+8985812828648862019536*x^24+16525310345394167002752*x^22+24893927149975603242048*x^20+30294355815129821928192*x^18+29274561574319887883226*x^16+21987801771104340121824*x^14+12494344840480632094992*x^12+5187763623118143696192*x^10+1502211081063677383836*x^8+283567347515314680480*x^6+31146155438884525872*x^4+1543354925530003776*x^2+8057044481403681) do(y^32+28*y^24+70*y^16+28*y^8+1, x^16-72*x^12-280*x^8+288*x^4+16) S=x^5-5*x^3+4*x-1; T=y^15-25*y^13+202*y^11-16*y^10-665*y^9+115*y^8+916*y^7-160*y^6-537*y^5+80*y^4+119*y^3-16*y^2-8*y+1; lift(nfroots(T,S)) S=polsubcyclo(97,12); lift(nfroots(subst(S,x,y),S)) S=x^9+9*x^8+36*x^7+69*x^6+36*x^5-99*x^4-303*x^3-450*x^2-342*x-226; T=y^9-15*y^6-87*y^3-125; lift(nffactor(T,S)) lift(nffactor(nfinit(y^2+1),(x-y)^3*(x^2+y)^4*(x^3-y*x+y)^5)) lift(factor(Mod(y,y^2+1)*x^2 + y)) lift(nffactor(nfinit(y^2+1),Mod(y,y^2+1)*x^2 + y)) factor((2*x+1)^2*(x+1)^3) {P=x^9 - 9*x^7 + 27*x^5 - 30*x^3 + 9*x - 2/7; K= a^27-63*a^25+1701*a^23-25914*a^21+246960*a^19-700*a^18-1543941*a^17+21168*a^16+6465060*a^15-254016*a^14-18197865*a^13+1560552*a^12+34034175*a^11-5321988*a^10-40965225*a^9+10224144*a^8+29604330*a^7-10606932*a^6-10927980*a^5+5186160*a^4+1256409*a^3-777924*a^2+21952; #nfroots(K,P)} \\ no factor #930 nf = nfinit(y^16-24*y^12+80*y^10-172*y^8+192*y^6-112*y^4+32*y^2+4); P = x^16-24*x^12+80*x^10-172*x^8+192*x^6-112*x^4+32*x^2+4; do(nf, P) nfroots(nf, P*(x^2+y)*(x^2+2*y)) \\ Bug #959 P=x^36+12*x^35-900*x^34-585*x^33+232905*x^32-1232184*x^31-15039873*x^30+110066100*x^29+430062960*x^28-3889034165*x^27-6885371553*x^26+72277665264*x^25+75990228525*x^24-788853282390*x^23-669954405945*x^22+5321235823803*x^21+4528671343041*x^20-22706777648475*x^19-20887787332600*x^18+62214414690960*x^17+62136364754205*x^16-111213087488775*x^15-118854042392850*x^14+131983619890275*x^13+148593402314775*x^12-105099439356375*x^11-122927027339625*x^10+56029221057500*x^9+67224101142000*x^8-19578944328750*x^7-23826919393125*x^6+4261743915000*x^5+5216451275625*x^4-517952334375*x^3-635253609375*x^2+26484140625*x+32625390625; #nfgaloisconj(nfinit([P,nfbasis([P, factor(poldisc(P), 175069)])]),1) \\ Bug #1006 #do(y^24-12*y^23+72*y^22-286*y^21+849*y^20-2022*y^19+4034*y^18-6894*y^17+10182*y^16-13048*y^15+14532*y^14-13974*y^13+11365*y^12-7578*y^11+4038*y^10-1766*y^9+762*y^8-408*y^7+236*y^6-126*y^5+69*y^4-38*y^3+18*y^2-6*y+1,8*x^9+42*x^6+6*x^3-1) \\ Bug #980 P=x^6 - x^5 - 76*x^4 + 60*x^3 + 1140*x^2 + 1155*x - 695 Q=a^36 - 140*a^34 + 8402*a^32 - 288950*a^30 + 6406703*a^28 - 97539585*a^26 + 1059042259*a^24 - 8396309325*a^22 + 49297808195*a^20 - 215811263825*a^18 + 704643601819*a^16 - 1705347924285*a^14 + 3017070472643*a^12 - 3809285900925*a^10 + 3299709349267*a^8 - 1836758642090*a^6 + 585303753211*a^4 - 85409835875*a^2 + 3969153125 lift(nfroots(Q,P)) \\ Bug #1023 do(a^2+13,polcyclo(13,13*x^2)) \\ Bug #1070 do(y^2-5,x^5-x^4-7*x^3+x^2+7*x-3) \\ Bug #1075 lift(nffactor(polcyclo(21,y), x^2-y^7)) \\ Bug #1132 do(y^4-y^2+1, 3*x^3+(-12*y^3+6*y)*x^2-11*y^2*x+(2*y^3-4*y)) \\ Bug #1141 do(y^2-y+1, (x-(1+y)/3)^2*(x+2*(1+y)/3)) \\ Bug #1142 lift(nffactor(3*y^2+1, 3*x^2+1)) lift(nfroots(3*y^2+1, 3*x^2+1)) \\#1207 lift(nffactor(t^6-6*t^5-3298534883316*t^4+13194139533310*t^3+3626777458830693384585198*t^2-7253554917667983838937052*t-1329227995784915872903826851489644559,x^3-3)) \\#1276 pol=1225*x^6+1750*x^5-21675*x^4-380*x^3+110180*x^2-129720*x+48771;lift(factorback(factornf(pol,subst(pol,x,y)))) \\#1438 factor((x^2-1)*(x^2-2)*(x^2-5)) \\#1446 factor((x^80-1)/(x-1)) \\also exercises Flx_extgcd above half-gcd threshold test(T,p)= { v=polhensellift(T,lift(factormod(T,p)[,1]),p,10); valuation(T-factorback(v),p); } \\also exercises FqX_extgcd above half-gcd threshold test(polcyclo(503),3) test(polcyclo(211),18446744073709551667) do(y^2-22,x^2+926246528884912528275985458927067632*y-4344481316563541186659879867597013188) nf = nfinit(y^2+1); do(nf,(x^2+4)/(x^2+1)^2) do(nf,y/(x^2+1)^2) nfroots(a^2+1,x^2) nfroots(,x+1/2) nfroots(,x^2-1/4) nfroots(,(x+1)*(x^2+1)) \\#1841 K = nfinit (y^4 + 57*y^2 + 661); P = Mod((1/11*y^2 + 56/11)*x^2 + x + 3, K.pol); nfroots (K, P) nfroots (K, P / pollead(P)) nfroots (K, P / (pollead(P)*y)) \\ #1956, #1957 nfroots(a^2-a+3,x^2+Mod(84*a-248/3,a^2-a+3)*x+Mod(-1440*a-73760/9,a^2-a+3)) nfroots(a^2-a+3,a*(x^2-4)) nffactor(y^2+7, (11*x)^4 - 10*(11*x)^2 + 1) \\ #2009 nffactor(y^8-y^6+y^4-y^2+1,x^4-1) \\ #2013 #nffactor(y^16+8, x^128+38963*x^120+443415855*x^112-3190514348*x^104+1973183073491*x^96+12244232235795*x^88+1921165187202898*x^80+36262111346728415*x^72+203445143688320136*x^64+36262111346728415*x^56+1921165187202898*x^48+12244232235795*x^40+1973183073491*x^32-3190514348*x^24+443415855*x^16+38963*x^8+1)[,2] \\ #2083 f=x^20-15*x^19+70989*x^18-1646113*x^17+3890074283*x^16-199035549796*x^15+203804256639644*x^14-10657741285726487*x^13+9779630086245476401*x^12-457685358591718595073*x^11+211985887298317287648516*x^10-13621268697129972225420327*x^9+3065457104886066023133986949*x^8-28110542105571309419720191704*x^7+34539665971867983088754678645580*x^6-1061445386217881235978009629856081*x^5+498395492968339432558541006017143039*x^4-15789239186368833250097534490638459475*x^3+1774782276941552319212370439848636475557*x^2+4469330093535998306027448264353195140536*x+4277406750726325717327241436124994515881; g=y^20-5*y^19-497395*y^18+43617925*y^17+92084825461*y^16-13577322967760*y^15-7694013534722665*y^14+1430561593275815035*y^13+321534254513790999596*y^12-70299145498412320125190*y^11-6894702144208513885815805*y^10+1786517983436254067840917780*y^9+72426826805051978098685836211*y^8-24338190557208310471662504670520*y^7-255231848841911020332784180965840*y^6+172908549561723112381441893500998965*y^5-1042438501414486010172621550211101919*y^4-555813027721813935650430329326884907050*y^3+6754721428610694790490649672796107843280*y^2+470810707124413968773034018937652067163520*y+3896560262532181966922924457358135376686480; apply(poldegree, nffactor(g, f)[,1]) \\ very slow if too few maximal ideals tested #nfroots(y^42 + 448*y^41 + 938*y^40 + 30*y^39 - 243*y^38 + 165*y^37 - 886*y^36 + 904*y^35 - 265*y^34 + 710*y^33 + 182*y^32 + 903*y^31 + 330*y^30 - 17*y^29 - 865*y^28 + 24*y^27 + 521*y^26 - 426*y^25 - 266*y^24 - 863*y^23 - 312*y^22 + 851*y^21 + 745*y^20 + 211*y^19 + 569*y^18 - 974*y^17 + 925*y^16 - 165*y^15 + 134*y^14 - 47*y^13 - 880*y^12 + 273*y^11 + 241*y^10 - 268*y^9 - 674*y^8 + 657*y^7 + 273*y^6 + 626*y^5 - 682*y^4 - 595*y^3 + 472*y^2 - 906*y - 633, x^21 + (-y + 1102609961)*x^20 - 1102609961*y*x^19 + 1897*x^18 - 1897*y*x^17 + 443738939*x^15 + (-443738939*y - 674)*x^14 + 674*y*x^13 - 1601470*x^11 + 1601470*y*x^10 - 11136*x^9 + (11136*y + 323053911)*x^8 - 323053911*y*x^7 - 3966537*x^4 + 3966537*y*x^3 + 66050170*x^2 + (-66050170*y - 850727634)*x + 850727634*y) \\ #2224 liftall(nffactor(polcyclo(22,t),y^3-t^5*y^2+(-t^9+t^8-t^7+t^6-t^5+t^4-t^3+t^2-t+1)*y-t^4)) \\ #2345 z=165559824909720476613877584753341483144637646579557529026273280000/9*a^2+56078742454776309859578474600162204885727171768074523043664131900438884288102400000/9*a+4748774887119566581834096656075080887220928529284512367607230603029718257830039234103453402398720000/9; P = a^3-86049406274089479559709541243402288*a-9715606813562913292353222097273654531394752027484288; liftall(nfroots(P,x^2-z)) \\ Errors, keep at end of file polhensellift(x^2+x+1,[x+a,x+a+1],2,10) pari-2.17.2/src/test/in/list0000644000175000017500000000162414760123736014252 0ustar billbillL = List(); for (i=1,10^5,listput(~L,i)) L = List([1,2,3]); for (i=1,5000,listinsert(~L,i,3)) L = List([1,2,3,3]); concat(L,5) concat(1,L) L = concat(L,L) listsort(~L); L listsort(~L,1); L listpop(~L); L listpop(~L,1); L \\ L = List([[1,2,3], 2]) L[1][1] = 3 L L = List([Vecsmall([1,2,3]), 2]) L[1][1] = 3 L = List(); listput(~L,1); listpop(~L); listpop(~L); matdiagonal(List([0])) g(L)=for(i=1,5,listput(~L,5-i));L; l=List([10,9,8,7,6,5]); g(l) l listkill(l) listcreate() subst(List([x,x^2+y]),x,1) substvec(List([x,y]), [x,y], [y,x]) substpol(List([x^2,x^3]), x^2, y) getheap()[1] chinese(List()) chinese(List([Mod(1,3)])) chinese(List([Mod(0,2),Mod(1,3),Mod(2,5)])) liftint(List([0,1])) L = List([1,2,3]); List(L) L[1] L[1]*=2 L L[1]=3 L listinsert(~L,4,10) L \\ Errors, keep at end of file listpop(1) L='L; listpop(~L) listput(L,1) listinsert(~L,1,1) L=Map(); listpop(~L) listput(~L,1) listinsert(~L,1,1) pari-2.17.2/src/test/in/ellmodulareqn0000644000175000017500000000017314567450071016141 0ustar billbill\\package:seadata ellmodulareqn(2) ellmodulareqn(11) ellmodulareqn(3,y,z) \\ errors ellmodulareqn(1) ellmodulareqn(2,y,x) pari-2.17.2/src/test/in/harmonic0000644000175000017500000000020214567450071015066 0ustar billbillharmonic(0) harmonic(1) harmonic(2) harmonic(3) harmonic(10) harmonic(10,2) harmonic(10,-2) \\ ERRORS harmonic(1.) harmonic(1,x) pari-2.17.2/src/test/in/size0000644000175000017500000000056114676526175014262 0ustar billbilllong_is_64 = (#(2^32) == 1); #0. #1 #1. == if (long_is_64==1, 2, 4) length([x]) length(List()) length(List([1,2,3])) length("abc") matsize([1,2,3]) matsize([1,2,3]~) matsize(matrix(2,3)) matsize(1) sizebyte(0) == if (long_is_64, 16, 8) sizebyte(x+1) == if (long_is_64, 80, 40) sizebyte([x,y]) == if (long_is_64, 168, 84) sizebyte([List(1)]) == if (long_is_64, 80, 40) pari-2.17.2/src/test/in/mspadic0000644000175000017500000000700314676526175014726 0ustar billbilldefault(parisize, "50M"); \\ overflows 48M { elldata= Map([ \\ rank 0 "11a1",[0,-1,1,-10,-20]; "14a1",[1,0,1,4,-6]; "15a1",[1,1,1,-10,-10]; "17a1",[1,-1,1,-1,-14]; "19a1",[0,1,1,-9,-15]; "26b1",[1,-1,1,-3,3]; "33a1",[1,1,0,-11,0]; "43a1",[0,1,1,0,0]; \\ rank 1 "37a1",[0,0,1,-1,0]; "53a1",[1,-1,1,0,0]; \\ rank 2 "389a1",[0,1,1,-2,0] ]); } myellinit(s)= ellinit(if(type(s)=="t_STR",mapget(elldata,s),s)); \\ a2 = 0 e=myellinit("19a1"); ellpadicL(e, 2, 5) \\ a3 = 0 e=myellinit("17a1");p=3; L=ellpadicL(e,p,4) F=[0,-p;1,ellap(e,p)]; (1-p^{-1}*F)^-2*L / bestappr(ellL1(e)/e.omega[1]) \\ a5 = -2 p=5; L=ellpadicL(e,p,4) al=polrootspadic(x^2-ellap(e,p)*x+p,p,7)[2]; (1-al^(-1))^(-2)*L / bestappr(ellL1(e)/e.omega[1]) \\ a3 = -3 != 0 e=myellinit("26b1");p=3; L=ellpadicL(e,p,4); F=[0,-p;1,ellap(e,p)]; (1-p^{-1}*F)^-2*L / bestappr(ellL1(e)/e.omega[1]) \\ huge memory 1001a1 e=ellinit([0,-1,1,-15881,778423]);p=2;n=3; ellpadicL(e,p,n) E=myellinit("53a1");P=[0,0]; ellpadicL(E,2,10,,2) ellpadicL(E,3,10) ellpadicL(E,3,10,,1) ellpadicL(E,5,5,,2) testord(s, p, n, D = 1) = { my(e = myellinit(s)); my([M,xp] = msfromell(e,1)); Wp = mspadicinit(M, p, n, 0); mspadicmoments(Wp, xp, D); } testss(s, p, n) = { my(e = myellinit(s)); my([M,xp] = msfromell(e,1)); Wp = mspadicinit(M, p, n); mspadicmoments(Wp,xp); } testord("11a1", 7, 4) testord("17a1", 7, 4) testss("17a1", 3, 4) testord("14a1", 7, 4) testord("43a1", 3, 4, 29) e=myellinit("11a1"); [M,phi]=msfromell(e,1); Wp = mspadicinit(M, 3, 4, 0); mspadicmoments(Wp, phi, 5) Wp = mspadicinit(M, 5, 4, 0); mspadicmoments(Wp, phi, -3) vchar = [0,-2,[0,1],[1,0],[2,0]]; test(M,phi,p)= { my(Wp, mu, ap); ap = mshecke(M,p,phi)[1,1]; Wp = mspadicinit(M,p,10, valuation(ap,p)); mu=mspadicmoments(Wp,phi); for (i=1,#vchar, print(vchar[i],":"); for(r=0,3, print(mspadicL(mu,vchar[i],r))); ); } test(M,phi,3); test(M,phi,2); test(M,phi,7); e=myellinit("33a1"); [M,phi]=msfromell(e,1); test(M,phi,3) test(M,phi,11) e=myellinit("389a1"); [M,phi]=msfromell(e,1); test(M,phi,2) [M,phi]=msfromell(e,-1); Wp = mspadicinit(M, 3, 4, 0); mspadicmoments(Wp, phi, 5) Wp = mspadicinit(M, 5, 4, 0); mspadicmoments(Wp, phi, -3) \\==== W = msinit(50,4,1); phi = mssplit(W, msnew(W), 1)[1]; Wp = mspadicinit(W, 3, 6, 0); mspadicmoments(Wp, phi) Wp=mspadicinit(msinit(25,2,1),5,4, 1); \\ must fail p^2 | N M=msinit(4,6,1); phi=-[1,8,1,-32]~; \\ v_p(ap) = 1 Wp=mspadicinit(M,3,5, 2); oms=mspadicmoments(Wp, phi); \\ must fail Wp=mspadicinit(M,3,5, 1); PHI=mstooms(Wp,phi); msomseval(Wp,PHI,[1/2,1/3]) msomseval(Wp,PHI,[0,oo]) oms=mspadicmoments(Wp, PHI); \\ now succeeds mspadicL(oms) msnewsymb(N,k,s=1) = { my(xpm,M); M=msinit(N,k,s); xpm = mssplit(M,msnew(M),1)[1]; [M,xpm]; }; testmspadicL(N,k,p,signe=1,D=1) = { my([M,xpm]=msnewsymb(N,k,signe)); my(ap = mshecke(M,p,xpm)[1,1]); my(Wp,oms); Wp = mspadicinit(M,p,10, if(ap,valuation(ap,p), k-1)); oms = mspadicmoments(Wp, xpm, D); vector(k-1,j, mspadicL(oms,j-1)); } \\ ordinary testmspadicL(3,6,3) testmspadicL(3,6,3,-1) testmspadicL(3,6,5) testmspadicL(3,6,5,-1) testmspadicL(3,6,5,-1, -3) testmspadicL(3,8,7) testmspadicL(3,8,7,-1) testmspadicL(5,4,3) testmspadicL(5,4,7) testmspadicL(5,4,7,-1) testmspadicL(5,4,7,1, 5) testmspadicL(11,6,7) testmspadicL(11,6,7,-1) testmspadicL(14,6,7) testmspadicL(14,6,7,-1) \\supersingular testmspadicL(4,6,3) \\ ap=12 testmspadicL(9,4,5) \\ ap=0 testmspadicL(17,6,3) \\ ap=-18 testmspadicL(3,8,2) \\ testmspadicL(5,8,2) testmspadicL(10,8,2) testmspadicL(3,10,7) \\ ap=9128, valuation 1 pari-2.17.2/src/test/in/polylog0000644000175000017500000000052214676526175014772 0ustar billbillpolylog(3,0.9) polylog(2,3.9) polylog(3,3.9) polylog(2,Mod(x,x^2+1)) polylog(2,[0.5,0.6]) polylog(2,x+O(x^5)) polylog(2,1/2+x+O(x^5)) dilog(-4) polylog(2,1.1+I,1) polylog(1,2,3) polylog(-70,(sqrt(5)-1)/2) localbitprec(320);bitprecision(dilog(2.0)) polylog(0,x) polylog(-1,x) \\errors polylog(3,2,5) polylog(2,Mod(1,2),0) polylog(3,"",0) pari-2.17.2/src/test/in/cyclo0000644000175000017500000000163314676526175014422 0ustar billbillallocatemem(8000000); poliscyclo(1) poliscyclo(x^0) poliscyclo(x) for (i=1,100, if (poliscyclo(polcyclo(i)) != i, error(i))) for (i=1,100, if (!poliscycloprod(x^i-1), error(i))) poliscyclo(polcyclo(10^5)) poliscyclo(polcyclo(12345)) { for (i=1,10, f = polcyclo(i); for(j=i+1,10, g = f*polcyclo(j); if (poliscyclo(g), error("is ", [i,j])); if (!poliscycloprod(g), error("prod ", [i,j])); print (polcyclofactors(g)) ) ); } poliscycloprod((x-1)^2) poliscycloprod((x+1)^2*(x-1)) test(n,t)= if (polcyclo(n,t) != subst(polcyclo(n),x,t), error([n,t])); test(5,1);test(5,-1); test(10,1);test(10,-1); test(40,1);test(40,-1); test(2,-1); test(10,-1); test(11,-1); test(5,Mod(-1,3)) polcyclo(524308,2+O(2^20)) polcyclo(524308,2^2+O(2^20)) \\ roots of 1 test(20, I) test(10, Mod(3,11)) test(10, 2 + O(11)) test(30, -1.0) z15 = Mod(t,polcyclo(15,t)); test(15, z15) test(30, z15) test(105, z15) pari-2.17.2/src/test/in/trans20000644000175000017500000000541314724330077014506 0ustar billbillOVERFLOW_EXPONENT=if(sizebyte(0)==16, 2^50, 2^20); exp(quadgen(5)) exp(Mod(x,x^2+1)) iferr(exp(""),E,E) N=2^64; O(2^0)^N iferr(O(2^0)^-N,E,E) 0^N Pol(1)^N (8+O(x^2))^(1/3) (8+O(x^2))^(1/2) sqrt(Mod(1,y)*(1+x+O(x^2))) sqrt(4+x+O(x^2)) iferr(O(x)^0.5,E,E) O(1)^0.5 (1+x+O(x^2))^0.5 iferr(O(x)^((2^65)/3),E,E) iferr(""^0,E,E) iferr(0^Mod(1,3),E,E) N=2^16; y=x^N; y^3 iferr(y^OVERFLOW_EXPONENT,E,E) iferr(0.^(2.^64),E,E) agm(1,1) agm(-1,1) agm(1+x+O(x^10),1) agm(1,[1,2]) log(4+O(3^4)) obj=[Mod(1,3), O(3^5), 3 + O(3^5),I]; test(f,p)=print(iferr(f(p),E,E)); [test(f,p) | f<-[exp,log,cos,sin,tan,cotan];p<-obj]; tan(1+I) tan(-127336279536511925./2^49) cotan(2) asin(1+O(x^3)) asin(-1+O(x^3)) asinh(I+O(x^3)) asinh(-I+O(x^3)) acosh(1+O(x^3)) acosh(1+x^2+O(x^3)) acosh(2+x+O(x^3)) acos(1+O(x^3)) sinh(I) tan(1+10^18*I) tan(1-10^18*I) cotan(1+10^18*I) cotan(1-10^18*I) w=Pi/4; test(z)= my(a=expm1(z),b=exp(z)-1); printf("%.1e\n", abs(a-b)/abs(a)); for (i=0,7, z=1e-20+i*w; test(z)) for (i=0,7, z=1e-20+i*w+I; test(z)) erfc(1/2+I) erfc(-1/2+I) erfc(-I) erfc(I) erfc(1+x+O(x^3)) expm1(3+O(3^2)) expm1(x) expm1(O(x)) expm1(1e-20+x+O(x^2)) expm1(3/4) expm1(1) expm1(-26534495976095.469977) if(sizebyte(0)==16 && exponent(expm1(26534495976095.469977))!=38281185757201\ ,error("expm1(26534495976095.469977)")); expm1(-4.7866697272721544799724285830597925865 E-10998741) expm1(4.7866697272721544799724285830597925865 E-10998741) forstep(x=1, 1+2*Pi, Pi/2, if(exponent(expm1(I*x)-exp(I*x)+1) > -127,print(x))) \\ #2494 log1p(x + O(x^5)) log1p(1e-10 + x + O(x^5)) log1p(O(x)) log1p(1/10^10) log1p(1e-10) log1p(1e-20) log1p(1e-10*(1+I)) log1p(1e-20*(1+I)) log1p(2+O(5^3)) log1p(-1+1/2) log1p(-1+1/8) round(log1p(-1+10^-10) << 27) a=-1633048355459347662258066616498.+ 107206003159399666971219664801296.*I; acosh(a) asinh(a) localprec(1310); precision(imag(cos(Pi*(1+I/2^2048)))) >= 1310 localprec(1000); exponent(sinh(1e-500)-1e-500) < -4985 sinc(0) sinc(1/2) sinc(10*I) sinc(1+I) sinc(O(3^2)) sinc(3+O(3^4)) sinc(x) sinc(0.*I) sinc(O(3^4)*I) sinc((1+O(3^3)) * x) sinc(Pi * x) localprec(2003); log(exp(1.5)) - 1.5 localbitprec(320); obj=[1.2, 2.1*I, 1+1.1*I]; { fun=[exp,expm1,log,arg, cos,sin,tan,cotan,sinc, cosh,sinh,tanh,cotanh, acos,asin,atan, acosh,asinh,atanh, sqrt,x->sqrtn(x,3), gamma,lngamma,psi,zeta]; for (i=1, #fun, my (f = fun[i]); print1(f,": " ); print([bitprecision(f(p)) | p<-obj])); } tst(f, z) = { localbitprec(64); a = f(z * 1.); localbitprec(128);b = f(z * 1.); exponent(b/a - 1); } z = -0xffffffffffffffd6 / 2^64; tst(atanh,z) z = -0xffffffffffffffeb / 2^64; tst(atanh,z) z = 0x1000000000000004 / 2^60; tst(acosh,z) z = 0x33bc6d3d39ebfccc8 / 2^56; tst(tan,z) \\ ERRORS keep at end of file sinc(2+O(3^2)) sinc(1/x) atanh(1-2^(-if(sizebyte(0)==16,63,31))) pari-2.17.2/src/test/in/nfislocalpower0000644000175000017500000000124114567450071016321 0ustar billbillK=bnfinit(y^2+1); P=idealprimedec(K,2)[1]; nfislocalpower(K,P,2,2) nfislocalpower(K,P,-1,2) nfislocalpower(K,P,-1,4) P=idealprimedec(K,5)[1]; nfislocalpower(K,P,P.gen[2],2) nfislocalpower(K,P,P.gen[2],5) nfislocalpower(K,P,y,5) nfislocalpower(K,P,y,10) nfislocalpower(K,P,Mod(y+1,K.pol)^10,10) p=406969676467377719018888256331; P=idealprimedec(K,p)[1]; nfislocalpower(K,P,y,2) nfislocalpower(K,P,y,p) N=nfinit(x^2-155);pr=idealprimedec(N,5)[1]; nfislocalpower(N,pr,20*x-249,5) K=nfinit(y^3-2); P=idealprimedec(K,3)[1]; nfislocalpower(K,P,2^18,54) nfislocalpower(K,P,y,3) nfislocalpower(K,P,y,0) nfislocalpower(K,P,1,0) nfislocalpower(K,"",1,0) nfislocalpower(K,"","",0) pari-2.17.2/src/test/in/stark0000644000175000017500000000226214676526175014434 0ustar billbillallocatemem(20*10^6) v=[321,520,577,840,904,1009,1129,1229,1297,1509,1901,1937,2305,2584,2920,3281,2^15-199]; for(i=1, #v, print(v[i],": ",polredabs(quadhilbert(v[i])))) { v = [ [y^2-145,1], [y^2-229,1], [y^2-401,1], [y^2-577,1], [y^2-761,1], [y^3-y^2-17*y-16,1], [y^3-14*y-7,1], [y^3-y^2-16*y+22,1], [y^3-36*y-45,1], [y^3-21*y-35,1], /* tougher: */ [y^3-12*y-1,1], [y^3-y^2-17*y-16,1], [y^3-y^2-30*y-27,1], [y^3-14*y-7,1], [y^3-y^2-16*y+22,1], [y^3-y^2-30*y+71,1], [y^3-y^2-16*y-6,1], [y^3-36*y-45,1], [y^3-12*y-1,[5,y+1]], [y^3-y^2-37*y+64,1], [y^3-y^2-9*y+8,1], [y^3-21*y-35,1], [y^3-y^2-16*y+8,1], [y^3-y^2-4*y-1,7], [y^3-y^2-7*y+6,[29,y-13]] ]; } do(w) = { my(mod, bnf); mod = w[2]; bnf = bnfinit(w[1]); if (type(mod) == "t_VEC", mod = idealhnf(bnf, mod[1], mod[2])); bnrstark(bnrinit(bnf,mod)); } for(i = 1, #v, print(v[i],": ",do(v[i]))); \\ quadray(31897,1) bnrstark(bnrinit(bnfinit(quadpoly(40,y)),120),matdiagonal([1,1,2,2])) \\#1776 quadhilbert(2669) \\ bnrstarkunit bnf = bnfinit(y^2-2); id=idealprimedec(bnf,199); bnr=bnrinit(bnf,[id[1],[1,1]]); bnrstarkunit(bnr) \\ errors bnf=bnfinit(y^2 - 23); id=idealprimedec(bnf,487); bnr=bnrinit(bnf,[id[1],[1,1]]); bnrstarkunit(bnr) pari-2.17.2/src/test/in/diffop0000644000175000017500000000042214567450071014541 0ustar billbilldiffop(E*X,[X,E],[1,X*E],10) diffop(Mod(S/C,S^2+C^2-1),[C],[-S],10) E4(n)=1+240*sum(i=1,n,sigma(i,3)*q^i)+O(q^(n+1)); diffop(E4(15),[q],[q]) diffop(Mod(y,x^2-y),[y],[1]) diffop(Mod(10^100,x^2+y),[y],[1]) diffop(lllx,[x,lx,llx,lllx],[1,1/x,1/(x*lx),1/(x*lx*llx)],6)*Mod(1,3) pari-2.17.2/src/test/in/map0000644000175000017500000000361414676526175014067 0ustar billbillshankslog(a,g,card)= { my(M=Map()); my(h=a,B=sqrtint(card)+1); for(i=0,B-1, mapput(~M,h,i); h*=g); g2=h*a^-1; h=1; for(i=0,B,my(j); if(mapisdefined(M,h,&j), return(i*B-j)); h*=g2); error("shankslog: not found"); } if(Mod(2,1000003)^shankslog(Mod(3,1000003),Mod(2,1000003),1000002)!=3, error("shankslog")); tablelog(g,card)= { my(M=Map()); my(h=1); for(i=0,card-1, mapput(~M,h,i);h*=g); M; } tablelogdel(g,card)= { my(M=Map()); my(h=1); for(i=0,card-1, mapput(~M,h,i);h*=g); h=1; for(i=0,card-1, mapdelete(~M,h);h*=g); #M; } a=ffgen(5^5,'a); g=ffprimroot(a); T=tablelog(g,5^5-1); if(g^mapget(T,a^2+a+1)!=a^2+a+1,error("shankslog")); if(tablelogdel(g,5^5-1),error("mapdelete")); M=Map([1,2;3,4;5,6]) Vec(M) Vecrev(M) Mat(M) apply(sqr,M) for(i=0,2,mapput(~M, 2*i+1, -mapget(M,2*i+1)));M M0=Map(matrix(10,2,i,j,i)); M1=Map(matrix(10,2,i,j,if(j==1,i,i*x^0))); M2=Map(matrix(10,2,i,j,11-i)); M3=Map(matrix(10,2,i,j,12-i)); M4=Map(matrix(10,2,i,j,i*x^0)); MV=[M0,M1,M2,M3,M4]; [a==b|a<-MV;b<-MV] [a===b|a<-MV;b<-MV] cmp(M0,M1) cmp(M0,M0) M=Map(); mapput(~M,2,3); mapdelete(~M,2); M mapisdefined(M,2) mapput(~M,2,3);M bagput(~M,k,v)=my(z=List());mapisdefined(M,k,&z);listput(~z,v);mapput(~M,k,z); get(N,q)= { my(M=Map()); forprime(p=2,N,bagput(~M,p%q,p)); Mat(M); } get(100,10) M=Map([1,2;3,4;5,6]); mapget(M,7) mapdelete(~M,7) Vec(M,1) Vec(M,-1) [Map(Mat([0, 0])), [0, 0, 1]] maplistput(~M,k,v) = mapapply(~M,k,(~y)->listput(~y,v),()->List(v)); maplisterr(~M,k,v) = mapapply(~M,k,(~y)->listput(~y,v)); M = Map(["a",List(); "b",List()]) maplistput(~M,"a",1); M maplistput(~M,"a",2); M maplistput(~M,"c",3); M maplistput(~M,"c",4); M maplisterr(~M,"b",5); M \\ Errors, keep at end maplisterr(~M,"d",6); Map([1,2;2,3;1,3;1,4]) L=List(); mapdelete(1,1) mapdelete(~L,1) mapget(1,1) mapget(L,1) mapisdefined(1,1) mapisdefined(L,1) mapput(1,1) mapput(~L,1) Map(1) pari-2.17.2/src/test/in/zn0000644000175000017500000001300014676526175013727 0ustar billbilldefault(parisize,"18M"); \\ 16M overflows znprimroot(2) znprimroot(4) p=9223372036854775837; znprimroot(p) znprimroot(p^2) znprimroot(2*p^2) znprimroot([2,1;p,2]) znprimroot([2*p^2,[2,1;p,2]]) znstar(0) znstar(1) znstar(10) znstar(14) znstar(247) znstar(-247) znstar(factor(-247)) znstar(factor(0)) Mod(10,148)^(2^64) do(n)= { g = Mod(3,n); phi = eulerphi(n); G = g^(phi-1); o = znorder(g, phi); fo = factor(o); [znlog(G,g), znlog(G,g,o), znlog(G,g,fo), znlog(G,g,[o,fo])]; } do(2^5*5^3*7) N = 2^3*5^2*nextprime(10^10)^2; do(N) G = znstar(N,1); G.clgp znlog(3, G) L=znlog(Mod(3,N), G) factorback(Mod(G.gen,N),L) znlog(Mod(3,N/2), G) znlog(G,3) znlog(7,Mod(3,8),znorder(Mod(3,8))) znlog(7,Mod(3,8)) znlog(0,Mod(3,4)) znlog(0,Mod(3,4),1) znlog(1,Mod(3,4)) znlog(1,Mod(3,4),1) znlog(0,Mod(2,4)) znlog(0,Mod(2,4),1) znlog(6,Mod(2,7),znorder(Mod(2,7))) znlog(3,Mod(3,8),znorder(Mod(3,8))) znlog(5,Mod(2,401)) znlog(7,3+O(2^3)) znlog(7,3+O(2^3), znorder(Mod(3,8))) znlog(7,3+O(7^3)) znlog(2,3+O(7^3)) { for (i = 1,10^4, d = eulerphi(i); if (!istotient(d, &n) || eulerphi(n) != d, error(i))) } Mod(1,2)-Mod(2,4) p=2^80+13; znlog(Mod(3,p),Mod(2,p)) p=314138927;znlog(Mod(p\17,p),Mod(5,p)) p=282744227;znlog(200474227,Mod(10,p)) p=276922883;znlog(3,Mod(2,p)) \\ SEGV in Z_issmooth_fact g=Mod(3,11); v=[I,-1,Mat(1),matid(2)/2,Mat([5,1])]; a=Mod(-1,11); for(i=1,#v, print(iferr(znlog(a,g,v[i]),E,E))); bnr = bnrinit(bnfinit(x), [160,[1]], 1); g = bnr.gen; bnrchar(bnr, g, [1/2,0,0]) bnrchar(bnr, [g[1],g[3]]) bnrchar(bnr, [1,0,0;0,1,0;0,0,2]) H=[4,1,0; 0,1,0; 0,0,2]; bnrchar(bnr, H) bnrchar(bnr, H, [0,1/2,0]) H=[8,4,2;0,2,1;0,0,1]; bnrchar(bnr, H, [0,1/2,1/2]) bnrchar(bnr, H, [0,0,1/2]) G8=znstar(8,1); znconreychar(G8,1) znconreychar(G8,3) znconreychar(G8,5) znconreychar(G8,7) vector(4, i, zncharisodd(G8,2*i-1)) forstep(i=1,8,2,if(znconreyexp(G8, znconreylog(G8, i)) != i, error(i))); z = [[1,-1],2]; vector(4, i, chareval(G8, [1,0], 1+2*i, z)) G=znstar(5,1); vector(4,i,znconreychar(G,i)) G=znstar(75,1); for(i=1, G.mod,\ if (gcd(i,G.mod)==1 && 2*chareval(G,i,-1) != zncharisodd(G,i),error(i))) znconreychar(G,1) znconreychar(G,2) znconreychar(G,11) chi=znconreychar(G,71) charorder(G,chi) charorder(G,71) charorder(G,znconreylog(G,71)) chareval(G,chi,1) chareval(G,chi,5) chareval(G,chi,1/3) chareval(G,chi,7/2) chareval(G,71,7/2) chareval(G,znconreylog(G,71),7/2) chareval(G,chi,2, 10) chareval(G,chi,2, 20) chareval(G,chi,2, [x,10]) chareval(G,chi,2, [x,20]) chareval(G,chi,2, [[0..9], 10]) bnrchar(G, [2], [1/10]) bnrchar(G, [2,7], [1/10,0]) log11 = ideallog(, 11, G); znconreylog(G,log11) znconreylog(G,11) znconreyconductor(G, 1) znconreyconductor(G, 4) znconreyconductor(G, 2) znconreyconductor(G, 2, &chi) chi { for (i=1,75, if (gcd(i,75)==1, f = znconreyconductor(G,i,&chi0); if (f != 75, print(i,":",f,":", chi0)))) } test(G, chi)= { N = znconreyconductor(G, chi); N0 = znconreyconductor(G, chi, &chi0); if (N != N0, error(chi)); print([N0, chi0]); G0 = znstar(N0,1); L = znconreylog(G,chi); if (zncharinduce(G0, chi0, G.mod) != L, error(chi)); if (zncharinduce(G0, chi0, G) != L, error(chi)); } test(G8,1) test(G8,3) test(G8,5) test(G8,7) G = znstar(48,1); for(i=1,48,if(gcd(i,48)==1,test(G,i))) { for (i = 1, 48, if (gcd(i,48)!=1,next); chi = i; chi2 = znchardecompose(G, chi, 2); chi3 = znchardecompose(G, chi, 3); print(chi2,", ",chi3); if (znconreyexp(G, charmul(G,chi2,chi3)) != i, error(i))) } G = znstar(300,1); L = chargalois(G,2) G = znstar(96,1); chargalois(G) chargalois(G,4) chargalois(G,[1,4]) chargalois([60,4], [12]) chargalois([180,6], [30]) chargalois(G,[]) \\ #2341 G = znstar(1,1); chargalois(G) chargalois(G, 1) chargalois(G, 2) chargalois(G, [1]) chargalois(G, [2]) \\ #2339 znchardecompose(znstar(2,1),[],2) G = znstar(126000,1); zncharconductor(G,11) zncharconductor(G,1) zncharconductor(G,1009) [G0,chi0]=znchartoprimitive(G,11); G0.mod chi0 [G0,chi0]=znchartoprimitive(G,1); G0.mod chi0 [G0,chi0]=znchartoprimitive(G,1009); G0.mod chi0 test(G,1009) test(G,82127) znconreyexp(G, znconreylog(G, 1009)) znconreyexp(G, znconreylog(G, 82127)) chi=[100,1,0,1,0]; l=znconreylog(G, chi) znconreychar(G,l) == chi znconreyexp(G,l) G6=znstar(6,1); G1=znstar(1,1); znconreychar(G1,1) znconreylog(G1,1) test(G1,1) chareval(G1,[]~,1) chareval(G1,[],1) chareval(G1,1,1) zncharinduce(G1,1,6) zncharinduce(G1,1,G6) G2=znstar(2,1); znconreychar(G2,1) znconreylog(G2,1) test(G2,1) chareval(G2,[]~,2) chareval(G2,[],2) chareval(G2,[],1) chareval(G2,1,2) chareval(G2,1,1) zncharinduce(G2,[]~,3) zncharinduce(G2,1,6) zncharinduce(G2,1,G6) G=znstar(30,1); znconreyconductor(G, 29) G=znstar(46,1); chi=znconreychar(G,45) znconreyexp(G,chi) [G,chi]=znchar(-3); znchargauss(G,chi) [G,chi]=znchar(-4); znchargauss(G,chi,2) [G,chi]=znchar(5); znchargauss(G,chi) G=znstar(300,1); znchargauss(G,7) znchargauss(G,71) znchargauss(G,131) G=znstar(600,1); vector(30,a,znchargauss(G,7,a)) znchargauss(G,491) znchargauss(G,11) G=znstar(12,1); znchargauss(G,[0,1]~,3) znchargauss(G,[1,0]~,3) [g,chi]=znchar(Mod(1,16));znchargauss(g,chi,0) [g,chi]=znchar(Mod(15,16));znchargauss(g,chi,0) qp(m, p, flag = 0)= { my(d = quaddisc(m), f = lcm(d, p), H); H = vectorsmall(f, a, a % p == 1 && kronecker(d,a) > 0); znsubgroupgenerators(H,flag); } qp(36322, 5) qp(36322, 5, 1) \\ Errors, keep at end of file znprimroot(8) znprimroot(15) znprimroot(30) znstar(0,1) znconreychar(G8,2) znconreychar(znstar(8),2) znconreyexp(znstar(192,1), [2,8,1,1]~) znsubgroupgenerators([I]) G=znstar(1,1) znconreylog(G, "") znconreylog(G, Mod(0,2)) znconreylog(G, [1]) znconreylog(G, [1]~) pari-2.17.2/src/test/in/compat0000644000175000017500000001032414567450071014557 0ustar billbillabs() addell() addprimes() adj() akell() algdep2() algtobasis() anell() apell() apell2() apprpadic() assmat() basis() basis2() basistoalg() bilhell() bin() boundcf() boundfact() buchcertify() buchfu() buchgen() buchgenforcefu() buchgenfu() buchimag() buchinit() buchinitforcefu() buchinitfu() buchnarrow() buchray() buchrayinit() buchrayinitgen() buchreal() bytesize() cf() cf2() changevar() char() char1() char2() chell() chptell() classno() classno2() coeff() compimag() compo() compositum() compositum2() comprealraw() conductor() conductorofchar() convol() core2() coredisc2() cvtoi() cyclo() decodefactor() decodemodule() degree() denom() deplin() det() det2() detint() diagonal() disc() discf() discf2() discrayabs() discrayabscond() discrayabslist() discrayabslistarch() discrayabslistarchall() discrayabslistlong() discrayrel() discrayrelcond() divres() divsum() eigen() euler() extract() fact() factcantor() factfq() factmod() factoredbasis() factoreddiscf() factoredpolred() factoredpolred2() factorpadic2() factpol() factpol2() fibo() fpn() galois() galoisapply() galoisconj() galoisconj1() galoisconjforce() gamh() gauss() gaussmodulo() gaussmodulo2() globalred() goto() hclassno() hell() hell2() hermite() hermite2() hermitehavas() hermitemod() hermitemodid() hermiteperm() hess() hilb() hilbp() hvector() i() idealaddmultone() idealaddone() idealapprfact() idealdivexact() idealhermite() idealhermite2() idealinv2() ideallistarchgen() ideallistunit() ideallistunitarch() ideallistunitarchgen() ideallistunitgen() ideallistzstar() ideallistzstargen() ideallllred() idealmulred() idealpowred() idealtwoelt2() idmat() image() image2() imagecompl() incgam1() incgam2() incgam3() incgam4() indexrank() indsort() initalg() initalgred() initalgred2() initell() initzeta() integ() intersect() intgen() intinf() intopen() inverseimage() isdiagonal() isfund() isideal() isincl() isinclfast() isirreducible() isisom() isisomfast() isoncurve() isprincipal() isprincipalforce() isprincipalgen() isprincipalgenforce() isprincipalray() isprincipalraygen() ispsp() isqrt() isset() issqfree() isunit() jacobi() jbesselh() jell() karamul() kbessel() kbessel2() ker() keri() kerint() kerint1() kerint2() kro() label() lambdak() laplace() legendre() lexsort() lindep2() lll() lll1() lllgen() lllgram() lllgram1() lllgramgen() lllgramint() lllgramkerim() lllgramkerimgen() lllint() lllintpartial() lllkerim() lllkerimgen() lllrat() ln() localred() logagm() lseriesell() makebigbnf() mat() matextract() mathell() matrixqz2() matrixqz3() minideal() minim() minim2() mod() modp() modulargcd() mu() nfdiv() nfdiveuc() nfdivres() nfhermite() nfhermitemod() nfmod() nfmul() nfpow() nfreduce() nfsmith() nfval() nucomp() numer() nupow() o() ordell() order() orderell() ordred() pascal() perf() permutation() permutation2num() pf() phi() pi() pnqn() pointell() polint() polred2() polredabs2() polredabsall() polredabsfast() polredabsnored() polvar() poly() polylogd() polylogdold() polylogp() polyrev() polzag() powell() powrealraw() prec() primedec() primroot() principalideal() principalidele() prodinf1() qfi() qfr() random() rank() rayclassno() rayclassnolist() recip() redimag() redreal() redrealnod() reduceddisc() regula() reorder() resultant() resultant2() reverse() rhoreal() rhorealnod() rndtoi() rnfdiscf() rnfequation2() rnfhermitebasis() rootmod() rootmod2() rootpadic() roots() rootsof1() rootsold() rounderror() series() set() sigmak() signat() signunit() simplefactmod() size() smallbasis() smallbuchinit() smalldiscf() smallfact() smallinitell() smallpolred() smallpolred2() smith() smith2() smithclean() smithpol() sort() sqred() srgcd() sturm() sturmpart() subcyclo() subell() sumalt2() sumpos2() supplement() sylvestermatrix() taniyama() tchebi() teich() threetotwo() threetotwo2() torsell() trans() trunc() tschirnhaus() twototwo() unit() vec() vecindexsort() veclexsort() vvector() weipell() wf() wf2() zell() zideallog() zidealstar() zidealstarinit() zidealstarinitgen() box() color() cursor() draw() initrect() killrect() line() lines() move() ploth2() plothmult() point() points() postdraw() postploth() postploth2() postplothraw() pprint() pprint1() print() print1() rbox() read() rline() rlines() rmove() rpoint() rpoints() scale() setprecision() setserieslength() settype() string() texprint() pari-2.17.2/src/test/in/genus2red0000644000175000017500000004000514760123736015171 0ustar billbill\\ Input from Namikawa-Ueno's list of curves of genus 2 \\ with expected reduction types. \\ t is to be substituted with a prime number bigger or equal to 7 \\ and can be taken to be 5 most of the time... \\ a, b, c are generic integers (to be changed if unexpected output) do(P, s) = print("Type: ", s); genus2red(subst(P,'t,7),7); P0=x^5+a*x^3+b*x^2+c*x+1; do(substvec(P0, [a,b,c], [1,-2,3]), "[I{0-0-0}], p. 155") P0=x^5+a*t^2*x^3+b*t^3*x^2+c*t^4*x+t^5; do(substvec(P0, [a,b,c], [1,-2,3]), "[I*{0-0-0}], p. 155") P0=x^6+a*t*x^4+b*t^2*x^2+t^3; do(substvec(P0, [a,b], [4,-1]), "[II], p. 155") genus2red(substvec(P0,[a,b,t],[4,-1,3]),3) P0=x^6+a*t*x^3+t^2; do(subst(P0, 'a, 4), "[III], p. 155") P0=t*(x^6+a*t*x^3+t^2); do(subst(P0, 'a, 5), "[IV], p. 155") P0=x^6+t; do(P0, "[V], p. 156") P0=x^6+t^5; do(P0, "[V*], p. 156") P0=x*(x^4+a*t*x^2+t^2); do(subst(P0, 'a, 3), "[VI], p. 156") P0=x*(x^4+t); do(P0, "[VII], p. 156") P0=x*(x^4+t^5); do(P0, "[VII*], p. 156") P0=x^5+t; do(P0, "[VIII-1], p. 156") P0=x^5+t^3; do(P0, "[VIII-2], p. 157") P0=x^5+t^7; do(P0, "[VIII-3], p. 157") P0=x^5+t^9; do(P0, "[VIII-4], p. 157") P0=x^5+t^2; do(P0, "[IX-1], p. 157") P0=x^5+t^4; do(P0, "[IX-2], p. 157") P0=x^5+t^6; do(P0, "[IX-3], p. 157") P0=x^5+t^8; do(P0, "[IX-4], p. 158") \\ Elliptic type, \\ m > 0 FIXME: changed ! m = 10; P0=(x^3+a*x+1)*(x^3+b*t^(4*m)*x+t^(6*m)) ; do(substvec(P0, [a,b], [3,10]), strprintf("[I{0}-I{0}-%ld], p. 158", m)) \\ misprint in N-U: m+1 must be m. genus2red(substvec(P0,['a,'b,'t],[-1,1,3]),3) \\ m >= 0 m = 10; P0=((x-1)^3+a*t^2*(x-1)+t^3)*(x^3+b*t^(4*m+2)*x+t^(6*m+3)); do(substvec(P0, [a,b], [3,10]), strprintf("[I{0}*-I{0}*-%ld], p. 158", m)) genus2red(substvec(P0,['a,'b,'t],[-1,1,3]),3) \\ m >= 0 m = 10; P0=(x^3+a*x+1)*(x^3+b*t^(4*m+2)*x+t^(6*m+3)); do(substvec(P0, [a,b], [3,10]), strprintf("[I{0}-I{0}*-%ld], p. 159", m)) genus2red(substvec(P0,['a,'b,'t],[-1,1,3]),3) \\ m >= 0 m = 10; P0=(x^2-t)^3+a*t^(2*m+4)*(x^2-t)+t^(3*m+6); do(subst(P0, 'a, 3), strprintf("[2I{0}-%ld], p. 159",m+1)) genus2red(substvec(P0,['a,'t],[-1,3]),3) \\ m >= 0 m = 10; P0=(x^2-t)^3+a*t^(2*m+3)*(x^2-t)+t^(3*m+4)*x; do(subst(P0, 'a, 3), strprintf("[2I{0}*-%ld], p. 159",m)) \\ m >= 0 m = 10; P0=(x^2-t)^3+a*t^(2*m+3)*(x^2-t)+t^(3*m+4)*x; do(subst(P0, 'a, 3), strprintf("[2I{0}*-%ld], p. 159",m)) \\ m >= 0 m = 10; P0=(x^3+t^(6*m+1))*(x^2+a*x+1); do(subst(P0, 'a, 3), strprintf("[I{0}-II-%ld], p. 159",m)) \\ m >= 0 m = 10; P0=(x^3+t^(6*m+5))*(x^2+a*x+1); do(subst(P0, 'a, 3), strprintf("[I{0}-II*-%ld], p. 160",m)) genus2red(substvec(P0,['a,'t],[3,3]),3) \\ m >= 0 m = 10; P0=(x^3+t^(6*m+2))*(x^2+a*x+1); do(subst(P0, 'a, 3), strprintf("[I{0}-IV-%ld], p. 160",m)) genus2red(substvec(P0,['a,'t],[3,3]),3) \\ m >= 0 m = 10; P0=(x^3+t^(6*m+4))*(x^2+a*x+1); do(subst(P0, 'a, 3), strprintf("[I{0}-IV*-%ld], p. 160",m)) genus2red(substvec(P0,['a,'t],[3,3]),3) \\ m >= 0 m = 10; P0=t*(x^3+t^(6*m+4))*(x^2+a*x+1); do(subst(P0, 'a, 3), strprintf("[I{0}*-II-%ld], p. 160",m)) genus2red(substvec(P0,['a,'t],[3,3]),3) \\ m >= -1 m = 10; P0=t*(x^3+t^(6*m+8))*(x^2+a*x+1); do(subst(P0, 'a, 3), strprintf("[I{0}*-II*-%ld], p. 160-161",m)) genus2red(substvec(P0,['a,'t],[3,3]),3) \\ m >= 0 m = 10; P0=t*(x^3+t^(6*m+5))*(x^2+a*x+1); do(subst(P0, 'a, 3), strprintf("[I{0}*-IV-%ld], p. 161",m)) \\ m >= -1 m = 10; P0=t*(x^3+t^(6*m+7))*(x^2+a*x+1); do(subst(P0, 'a, 3), strprintf("[I{0}*-IV*-%ld], p. 161",m)) \\ m >= 0 m = 10; P0=x*(x^2+t^(4*m+1))*(x^2+a*x+1); do(subst(P0, 'a, 3), strprintf("[I{0}-III-%ld], p. 161",m)) \\ m >= 0 m = 10; P0=x*(x^2+t^(4*m+3))*(x^2+a*x+1); do(subst(P0, 'a, 3), strprintf("[I{0}-III*-%ld], p. 162",m)) \\ m >= 0 m = 10; P0=t*x*(x^2+t^(4*m+3))*(x^2+a*x+1); do(subst(P0, 'a, 3), strprintf("[I{0}*-III-%ld], p. 162",m)) \\ m >= -1 m = 10; P0=t*x*(x^2+t^(4*m+5))*(x^2+a*x+1); do(subst(P0, 'a, 3), strprintf("[I{0}*-III*-%ld], p. 162",m)) \\ m >= 0 m = 10; P0=(x^2-t)^3+t^(3*m+3)*x; do(P0, strprintf("[2II-%ld], p. 162",m)) genus2red(subst(P0,'t,3),3) \\ m >= 0 m = 10; P0=(x^2-t)^3+t^(3*m+5)*x; do(P0, strprintf("[2II*-%ld], p. 163",m)) genus2red(subst(P0,'t,3),3) \\ m >= 0 m = 10; P0=(x^3+t^(6*m+1))*((x-1)^3+t); do(P0, strprintf("[II-II-%ld], p. 163",m)) \\ m >= 0 m = 10; P0=(x^3+t^(6*m+1))*((x-1)^3+t^5); do(P0, strprintf("[II-II*-%ld], p. 163",m)) \\ m >= 0 m = 10; P0=(x^3+t^(6*m+5))*((x-1)^3+t^5); do(P0, strprintf("[II*-II*-%ld], p. 163",m)) \\ m = -1 P0=t*(x^3+t^2)*((x-1)^3+t^2); do(P0, "[II*-II*-(-1)], p. 163") \\ m >= 0 m = 10; P0=(x^3+t^(6*m+1))*((x-1)^3+t^2); do(P0, strprintf("[II-IV-%ld], p. 164",m)) \\ m >= 0 m = 10; P0=(x^3+t^(6*m+1))*((x-1)^3+t^4); do(P0, strprintf("[II-IV*-%ld], p. 164",m)) \\ m >= 0 m = 10; P0=(x^3+t^(6*m+5))*((x-1)^3+t^2); do(P0, strprintf("[II*-IV-%ld], p. 164",m)) \\ m = -1 P0=(x^3+t^2)*(x^3+t); do(P0, "[II*-IV-(-1)], p. 164") \\ m bigger or equal -1 m = 10; P0=t*(x^3+t^(6*m+7))*((x-1)^3+t^2); do(P0, strprintf("[II*-IV*-%ld], p. 164-165",m)) \\ m >= 0 m = 10; P0=(x^2-t)^3+t^(3*m+4); do(P0, strprintf("[2IV-%ld], p. 165",m)) genus2red(subst(P0,'t,3),3) \\ m >= 0 m = 10; P0=(x^2-t)^3+t^(3*m+5); do(P0, strprintf("[2IV*-%ld], p. 165",m)) genus2red(subst(P0,'t,3),3) \\ m >= 0 m = 10; P0=(x^3+t^(6*m+2))*((x-1)^3+t^2); do(P0, strprintf("[IV-IV-%ld], p. 165",m)) \\ m >= 0 m = 10; P0=(x^3+t^(6*m+2))*((x-1)^3+t^4); do(P0, strprintf("[IV-IV*-%ld], p. 165",m)) \\ m >= -1 m = 10; P0=t*(x^3+t^(6*m+7))*((x-1)^3+t); do(P0, strprintf("[IV*-IV*-%ld], p. 166",m)) \\ m >= 0 m = 10; P0=x*(x^2+t^(4*m+1))*((x-1)^3+t); do(P0, strprintf("[II-III-%ld], p. 166",m)) \\ m >= 0 m = 10; P0=x*(x^2+t^(4*m+3))*((x-1)^3+t); do(P0, strprintf("[II-III*-%ld], p. 166",m)) \\ m >= 0 m = 10; P0=x*(x^2+t^(4*m+1))*((x-1)^3+t^5); do(P0, strprintf("[II*-III-%ld], p. 166",m)) \\ m = -1 P0=(x^2+t)*(x^3+t^2); do(P0, "[II*-III-(-1)], p. 167") \\ m at least -1 m = 10; P0=t*x*(x^2+t^(4*m+5))*((x-1)^3+t^2); do(P0, strprintf("[II*-III*-%ld], p. 167",m)) \\ m >= 0 m = 10; P0=x*(x^2+t^(4*m+1))*((x-1)^3+t^2); do(P0, strprintf("[IV-III-%ld], p. 167",m)) genus2red(subst(P0,'t,3),3) \\ m >= 0 m = 10; P0=x*(x^2+t^(4*m+3))*((x-1)^3+t^2); do(P0, strprintf("[IV-III*-%ld], p. 167",m)) genus2red(subst(P0,'t,3),3) \\ m = -1 P0=x*(x^2+t)*(x^3+t); do(P0, "[IV-III*-(-1)], p. 167") \\ the top horizontal line has mult. 3. \\ m >= 0 m = 10; P0=x*(x^2+t^(4*m+1))*((x-1)^3+t^4); do(P0, strprintf("[IV*-III-%ld], p. 168",m)) \\ m at least -1 m = 10; P0=t*x*(x^2+t^(4*m+5))*((x-1)^3+t); do(P0, strprintf("[IV*-III*-%ld], p. 168",m)) \\ m >= 0 m = 10; P0=(x^2-t)*((x^2-t)^2+t^(2*m+2)*x); do(P0, strprintf("[2III-%ld], p. 168",m)) genus2red(subst(P0,'t,3),3) \\ m >= 0 m = 10; P0=(x^2-t)*((x^2-t)^2+t^(2*m+3)*x); do(P0, strprintf("[2III*-%ld], p. 168",m)) genus2red(subst(P0,'t,3),3) \\ m >= 0 m = 10; P0=x*(x^2+t^(4*m+1))*(x-1)*((x-1)^2+t); do(P0, strprintf("[III-III-%ld], p. 169",m)) \\ m >= 0 m = 10; P0=x*(x^2+t^(4*m+1))*(x-1)*((x-1)^2+t^3); do(P0, strprintf("[III-III*-%ld], p. 169",m)) \\ m >= -1 m = 10; P0=t*x*(x^2+t^(4*m+5))*(x-1)*((x-1)^2+t); do(P0, strprintf("[III*-III*-{%ld}], p. 169",m)) \\ Parabolic type \\ n > 0 n = 9; P0=(x^3+a*x+1)*(x^2+t^n); do(subst(P0, 'a, 3), strprintf("[I{%ld-0-0}], p. 170",n)) \\ n, m > 0 n = 9; m = 10; P0=(x^3+a*t^(4*m)*x+t^(6*m))*((x-1)^2+t^n); do(subst(P0, 'a, 3), strprintf("[I{%ld}-I{0}-%ld], p. 170",n, m)) genus2red(substvec(P0,['a,'t],[-1,3]),3) \\ n, m >= 0 n = 9; m = 10; P0=(x+t)*(x^2+t^(n+2))*((x-1)^3+a*t^(4*m)*(x-1)+t^(6*m)); do(subst(P0, 'a, 3), strprintf("[I{0}-I*{%ld}-%ld], p. 170",n, m)) genus2red(substvec(P0,['a,'t],[-1,3]),3) \\ n, m >= 0 n = 9; m = 10; P0=(x^3+a*t^(4*m+2)*x+t^(6*m+3))*((x-1)^2+t^n); do(subst(P0, 'a, 3), strprintf("[I{%ld}-I{0}*-%ld], p. 171",n, m)) \\ n > 0 n = 9; P0=t*(x^3+a*x+1)*(x^2+t^n); do(subst(P0, 'a, 3), strprintf("[I*{%ld-0-0}], p. 171",n)) \\ n, m >= 0 n = 9; m = 10; P0=(x+t)*(x^2+t^(n+2))*((x-1)^3+a*t^(4*m+2)*(x-1)+t^(6*m+3)); do(subst(P0, 'a, 3), strprintf("[I*{%ld}-I{0}*-%ld], p. 171",n, m)) \\ n > 0 n = 9; P0=(x^4+a*t*x^2+t^2)*((x-1)^2+t^(n-1)); do(subst(P0, 'a, 3), strprintf("[II{%ld-0}], p. 171",n)) \\ n > 0 n = 9; P0=t*(x^4+a*t*x^2+t^2)*((x-1)^2+t^(n-1)); do(subst(P0, 'a, 3), strprintf("[II*{%ld-0}], p. 172",n)) \\ n > 0, m >= 0 n = 9; m = 10; P0=(x^3+t^(6*m+1))*((x-1)^2+t^n); do(P0, strprintf("[II-I{%ld}-%ld], p. 172",n, m)) \\ n > 0, m >= 0 n = 9; m = 10; P0=(x^3+t^(6*m+5))*((x-1)^2+t^n); do(P0, strprintf("[II*-I{%ld}-%ld], p. 172",n, m)) \\ n > 0, m >= 0 n = 9; m = 10; P0=(x^3+t^(6*m+2))*((x-1)^2+t^n); do(P0, strprintf("[IV-I{%ld}-%ld], p. 173",n, m)) \\ n > 0, m >= 0 n = 9; m = 10; P0=(x^3+t^(6*m+4))*((x-1)^2+t^n); do(P0, strprintf("[IV*-I{%ld}-%ld], p. 173",n, m)) \\ n, m >= 0 n = 9; m = 10; P0=(x-1+t)*((x-1)^2+t^(n+2))*(x^3+t^(6*m+1)); do(P0, strprintf("[II-I*{%ld}-%ld], p. 173",n, m)) \\ n, m >= 0 n = 9; m = 10; P0=(x-1+t)*((x-1)^2+t^(n+2))*(x^3+t^(6*m+5)); do(P0, strprintf("[II*-I*{%ld}-%ld], p. 174",n, m)) \\ n >= 0, m = -1 n = 9; P0=t*((x-1)^2+t^n)*(x^3+t^2); do(P0, strprintf("[II*-I*{%ld}-(-1)], p. 174",n)) \\ n, m >= 0 n = 9; m = 10; P0=(x-1+t)*((x-1)^2+t^(n+2))*(x^3+t^(6*m+2)); do(P0, strprintf("[IV-I*{%ld}-%ld], p. 174",n, m)) \\ n, m >= 0 n = 9; m = 10; P0=(x-1+t)*((x-1)^2+t^(n+2))*(x^3+t^(6*m+4)); do(P0, strprintf("[IV*-I*{%ld}-%ld], p. 174",n, m)) \\ n >= 0, m = -1 n = 9; P0=t*((x-1)^2+t^n)*(x^3+t); do(P0, strprintf("[IV*-I*{%ld}-(-1)], p. 175",n)) genus2red(subst(P0,'t,3),3) \\ n >= 0 n = 9; P0=x*(x^3+t)*((x-1)^2+t^n); do(P0, strprintf("[IV-II{%ld}], p. 175",n)) genus2red(subst(P0,'t,3),3) \\ n > 0 n = 9; P0=x*(x^3+t^2)*((x-1)^2+t^(n-1)); do(P0, strprintf("[IV*-II{%ld}], p. 175",n)) genus2red(subst(P0,'t,3),3) \\ n = 0 P0=(x^2+t^3)*(x^3+t^4); do(P0, "[IV*-II{0}], p. 175") genus2red(subst(P0,'t,3),3) \\ n >= 0 n = 9; P0=(x^3+t)*(x^2+t^(n+1)); do(P0, strprintf("[II-II*{%ld}], p. 176",n)) genus2red(subst(P0,'t,3),3) \\ n >= 0 n = 9; P0=t*x*(x^3+t)*((x-1)^2+t^n); do(P0, strprintf("[II*-II*{%ld}], p. 176",n)) genus2red(subst(P0,'t,3),3) \\ n > 0, m >= 0 n = 9; m = 10; P0=x*(x^2+t^(4*m+1))*((x-1)^2+t^n); do(P0, strprintf("[III-I{%ld}-%ld], p. 176",n,m)) genus2red(subst(P0,'t,3),3) \\ n > 0, m >= 0 n = 9; m = 10; P0=x*(x^2+t^(4*m+3))*((x-1)^2+t^n); do(P0, strprintf("[III*-I{%ld}-%ld], p. 176",n,m)) genus2red(subst(P0,'t,3),3) \\ n, m >= 0 n = 9; m = 10; P0=(x+t)*(x^2+t^(n+2))*(x-1)*((x-1)^2+t^(4*m+1)); do(P0, strprintf("[III-I*{%ld}-%ld], p. 177",n,m)) genus2red(subst(P0,'t,3),3) \\ n, m >= 0 n = 9; m = 10; P0=(x+t)*(x^2+t^(n+2))*(x-1)*((x-1)^2+t^(4*m+3)); do(P0, strprintf("[III*-I*{%ld}-%ld], p. 177",n,m)) genus2red(subst(P0,'t,3),3) \\ n >= 0, m = -1 n = 9; P0=t*x*(x^2+t)*((x-1)^2+t^n); do(P0, strprintf("[III*-I*{%ld}-(-1)], p. 177",n)) \\ attach one more projective line of mult. 1 to the component 2B \\ n >= 0 n = 9; P0=(x^4+t)*((x-1)^2+t^n); do(P0, strprintf("[III-II{%ld}], p. 177",n)) \\ n > 0 n = 9; P0=(x^4+t^3)*((x-1)^2+t^(n-1)); do(P0, strprintf("[III*-II{%ld}], p. 178",n)) \\ n = 0 P0=t*(x^2+t)*(x^4+t); do(P0, "[III*-II{0}], p. 178") \\ n >= 0 n = 9; P0=(x^4+t)*(x^2+t^(n+1)); do(P0, strprintf("[III-II*{%ld}], p. 178",n)) \\ n >= 0 n = 9; P0=(x^4+t^3)*(x^2+t^(n+2)); do(P0, strprintf("[III*-II*{%ld}], p. 178",n)) \\ Parabolic type continued \\ n, p > 0 n = 9; p = 8; P0=(x^2+t^n)*((x+1)^2+t^p)*(x-1); do(P0, strprintf("[I{%ld-%ld-0}], p. 179",n,p)) \\ n, p, m > 0 n = 9; p = 8; m = 10; P0=(x+t^(2*m))*(x^2+t^(4*m+n))*((x-1)^2+t^p); do(P0, strprintf("[I{%ld}-I{%ld}-%ld}], p. 179",n,p,m)) \\ n, p > 0 n = 9; p = 8; P0=t*(x^2+t^n)*((x+1)^2+t^p)*(x-1); do(P0, strprintf("[I*{%ld-%ld-0}], p. 180",n,p)) genus2red(subst(P0,'t,3),3) \\ n, p > 0, m >= 0 n = 9; p = 8; m = 10; P0=(x+t^(2*m+1))*(x^2+t^(4*m+n+2))*(x-1+t)*((x-1)^2+t^(p+2)); do(P0, strprintf("[I*{%ld}-I*{%ld}-%ld], p. 180",n,p,m)) \\ n, p > 0, m >= 0 n = 9; p = 8; m = 10; P0=(x+t^(2*m+1))*(x^2+t^(4*m+p+2))*((x-1)^2+t^n); do(P0, strprintf("[I{%ld}-I*{%ld}-%ld], p. 180",n,p,m)) genus2red(subst(P0,'t,3),3) \\ n > 0 even, m > 0 k = 4; m = 10; n=2*k; P0=((x^2-t)+t^(m+1))*((x^2-t)^2+t^(2*m+k+2)); do(P0, strprintf("[2I{%ld}-%ld], p. 181",n,m)) genus2red(subst(P0,'t,3),3) \\ n > 0 odd, m > 0 k = 4; m = 10; n=2*k+1; P0=((x^2-t)+t^(m+1))*((x^2-t)^2+t^(2*m+k+2)*x); do(P0, strprintf("[2I{%ld}-%ld}], p. 181",n,m)) \\ n > 0 even, m=0 k = 4; n=2*k; P0=((x^2-t)+a*t)*((x^2-t)^2+t^(k+2)); do(subst(P0, 'a, 2), strprintf("[2I{%ld}-0], p. 181",n)) \\ n > 0 odd, m=0 k = 4; n=2*k+1; P0=((x^2-t)+a*t)*((x^2-t)^2+t^(k+2)*x); do(subst(P0, 'a, 2), strprintf("[2I{%ld}-0], p. 181",n)) \\ n > 0 even, m >= 0 k = 4; m = 10; n=2*k; P0=((x^2-t)+t^(m+1)*x)*((x^2-t)^2+t^(2*m+k+3)); do(P0, strprintf("[2I*{%ld}-%ld}], p. 181",n,m)) genus2red(subst(P0,'t,3),3) \\ n > 0 odd, m k = 4; m = 10; n=2*k+1; P0=((x^2-t)+t^(m+1)*x)*((x^2-t)^2+t^(2*m+k+3)*x); do(P0, strprintf("[2I*{%ld}-%ld}], p. 181",n,m)) \\ n, p > 0 n = 9; p = 8; P0=(x^2+t)*(x^2+t^(p+1))*((x-1)^2+t^(n-1)); do(P0, strprintf("[II{%ld-%ld}], p. 182",n,p)) genus2red(subst(P0,'t,3),3) \\ n > 0 even k = 4; n=2*k; P0=x*((x^2-t^3)^2+t^(k+6)); do(P0, strprintf("[III{%ld}], p. 182",n)) \\ n > 0 odd k = 4; n=2*k+1; P0=x*((x^2-t^3)^2+t^(k+5)*x); do(P0, strprintf("[III{%ld}], p. 182",n)) \\ n, p, q > 0 n = 9; p = 8; q = 5; P0=(x^2+t^n)*((x-1)^2+t^p)*((x-2)^2+t^q); do(P0, strprintf("[I{%ld-%ld-%ld}], pp. 182-183",n,p,q)) \\ n, p, q > 0 n = 9; p = 8; q = 5; P0=t*(x^2+t^n)*((x-1)^2+t^p)*((x-2)^2+t^q); do(P0, strprintf("[I*{%ld-%ld-%ld}], pp. 183",n,p,q)) \\ n, p > 0, p even n = 9; k = 4; p=2*k; P0=((x^2-t)^2+t^(k+2))*((x-1)^2+t^(n-1)); do(P0, strprintf("[II{%ld-%ld}], p. 183",n,p)) genus2red(subst(P0,'t,3),3) \\ n, p > 0, p odd n = 9; k = 4; p=2*k+1; P0=((x^2-t)^2+t^(k+2)*x)*((x-1)^2+t^(n-1)); do(P0, strprintf("[II{%ld-%ld}], p. 183",n,p)) genus2red(subst(P0,'t,3),3) \\ n, p > 0 n = 9; k = 4; l = 0; p=2*k+l; P0=t*((x^2-t)^2+t^(k+2)*x^l)*((x-1)^2+t^(n-1)); do(P0, strprintf("[II*{%ld-%ld}], p. 184",n,p)) \\ n, p > 0 n = 9; k = 4; l = 1; p=2*k+l; P0=t*((x^2-t)^2+t^(k+2)*x^l)*((x-1)^2+t^(n-1)); do(P0, strprintf("[II*{%ld-%ld}], p. 184",n,p)) \\ n > 0 k = 4; l = 0; n=3*k+l; P0=(x^3-t)^2+t^(k+2)*x^l; do(P0, strprintf("[III{%ld}], p. 184",n)) genus2red(subst(P0,'t,3),3) \\ n > 0 k = 4; l = 1; n=3*k+l; P0=(x^3-t)^2+t^(k+2)*x^l; do(P0, strprintf("[III{%ld}], p. 184",n)) genus2red(subst(P0,'t,3),3) \\ n > 0 k = 4; l = 2; n=3*k+l; P0=(x^3-t)^2+t^(k+2)*x^l; do(P0, strprintf("[III{%ld}], p. 184",n)) genus2red(subst(P0,'t,3),3) \\ n > 0 k = 2; l = 0; n=3*k+l; P0=t*((x^3-t)^2+t^(k+2)*x^l); do(P0, strprintf("[III*{%ld}], p. 184",n)) genus2red(subst(P0,'t,3),3) \\ n > 0 k = 2; l = 1; n=3*k+l; P0=t*((x^3-t)^2+t^(k+2)*x^l); do(P0, strprintf("[III*{%ld}], p. 184",n)) genus2red(subst(P0,'t,3),3) \\ n > 0 k = 2; l = 2; n=3*k+l; P0=(x^3-t)^2+t^(k+2)*x^l; do(P0, strprintf("[III{%ld}], p. 184",n)) genus2red(subst(P0,'t,3),3) \\ Extras : p = 3 \e \\ Colin Stahlke, bug28 genus2red(-x^6-6*x^2-7,3) genus2red(-9*x^6+6*x^5-8*x^4-5*x^3+5*x^2-10*x+3,3) \\ M. Stoll, bug28 genus2red(3*x^6+3*x^4+3*x^3+x^2-5*x-5,3) \\ Colin Stahlke, bug28 genus2red(-3*x^6+6*x^5-1*x^4+6*x^3-6*x^2-1*x-6,3) \\ J. Mueller, bug28 genus2red((x^3+2*x+1)*(x^3+3^2*x^2+3^8),3) \\ A. Brumer, bug28 P=x^6+4*x^5-24*x^4-16*x^3-52*x^2-48*x; genus2red(P,3) P=x^6+4*x^5+24*x^4+32*x^3+56*x^2+48*x+24; genus2red(P,3) P=24*x^5+56*x^4+76*x^3+33*x^2-4*x-20; genus2red(P,3) P=-3*x^6+6*x^5-25*x^4+36*x^3-69*x^2+38*x-39; genus2red(P,3) \\ M. Stoll, bug28 P=-5*x^5+5*x^4+10*x^3-7; genus2red([P,1],3) P=-5*x^6-3*x^5-10*x^4-10*x^3-7; genus2red([P,1],3) P=3*x^5+5*x^4+5*x-4; genus2red([P,1],3) Q=x^2+x; P=-9*x^6+6*x^5-8*x^4-5*x^3+5*x^2-10*x+3; genus2red([P,Q],3) \\ M. Stoll, bug27 Q=x^3+1; P=-7*x^6+5*x^3+5*x^2-6*x+1; genus2red([P,Q],3) \\ #1596 genus2red(27*x^5 + 97*x^4 + 118*x^3 + 60*x^2 + 13*x + 1,3) \\ #1597 genus2red([-x^6 - 3*x^4 - 10*x^2 - 1,x],3) \\ #1597 genus2red([-60*x^6-203*x^5-291*x^4-244*x^3-129*x^2-41*x-7,x^3+x^2+x+1]) \\ #1597 genus2red(6*x^6+5*x^4+x^2+1,7) \\ #1597 genus2red([1,x^3-1]) genus2red(x^5+1/5, 5) genus2red(273*x^6-38933/5*x^5-4483763/4*x^4+371954149/10*x^3+569046245/4*x^2+12389355*x-42117075,5) \\ #1826 genus2red(177*x^6+126*x^5-63*x^4+72*x+84,3) \\ #2053 genus2red(3*(4*x^6 + 6*x^5 + 3*x^4 + 8*x^3 + 9*x^2 - 3), 3) genus2red(x^6+27,3) \\ #2331 genus2red(150*x^6+180*x^5-270*x^4+2040*x^3-1350*x^2+3060*x+270, 3) genus2red(-3*x^6-36*x^5-72*x^4+270*x^3+3,3) pari-2.17.2/src/test/in/cmp0000644000175000017500000000112714567450071014054 0ustar billbilltest(f,g)=[cmp(f,f), cmp(f,g), cmp(g,f)] test(()->1, ()->2) test(1.,2.) test(1,2) test(Vecsmall([1,2]),Vecsmall([1,3])) test(List([1,2]),List([1,3])) test(x,x+1) test(x,y) test(O(x),x+O(x^2)) v=[-oo, 1/2, 1, oo]; for (i=1, #v, for(j=i+1,#v, if( v[i] >= v[j], error([i,j])))); for (i=1, #v, for(j=i+1,#v, if( !(v[i] < v[j]), error([i,j])))); for (i=1, #v, if(!(v[i] == v[i]), error(i))); for (i=1, #v, if(!(v[i] === v[i]), error(i))); Mod(1,3) > 0 lex(Vecsmall([1,2]),Vecsmall([1,3])) ["x"<="y", "x"<="x", "x"<="w"] [oo <= -oo, oo <= oo, -oo <= -oo] 1. <= oo 1. <= -oo 1 <= 'x 1. <= 'x 1/2 <= 'x pari-2.17.2/src/test/in/ellseaJ0000644000175000017500000000031314676526175014662 0ustar billbilldefault(parisize, "10M"); \\ 8M overflows default(datadir,"nonexistent"); \\ disable cache p=72057594037928017; ellap(ellinit([2,3],p)) ellsea(ellinit([0,1],p)) \\ j=0 ellsea(ellinit([1,0],p)) \\ j=1728 pari-2.17.2/src/test/in/algebras0000644000175000017500000031752114760311542015057 0ustar billbillal = alginit(nfinit(y), [Mat(1)]); \\reported by Bill J = varhigher("J",y); Q=nfinit(y); T=polcyclo(5, 'x); F=rnfinit(Q, T); A = alginit(F, [Mod(x^2,T), 3]); print("contains nfabs: ", algsplittingfield(A)[12][1] != 0); A[1][12][1] = 0; A qamt(a,b) = { my(m_i,m_j,m_k); m_i = [0,a,0,0; 1,0,0,0; 0,0,0,a; 0,0,1,0]; m_j = [0, 0,b, 0; 0, 0,0,-b; 1, 0,0, 0; 0,-1,0, 0]; m_k = [0, 0,0,-a*b; 0, 0,b, 0; 0,-a,0, 0; 1, 0,0, 0]; [matid(4), m_i, m_j, m_k] }; do(name, test) = { setrand(1); print(name,": ", iferr(test(), E, E)); } gusuite(name, tests) = print("Suite: ", name); tests(); searchin(hf,pr,h) = { my(i,n); for(i=1,#hf[1], if(hf[1][i]==pr, return(hf[2][i]==h)) ); return(h==0); }; samehasse(hf1,hi1,hf2,hi2) = { my(i,n); if(hi1 != hi2, return(0)); n = #hf1[1]; for(i=1,n, if(!searchin(hf2,hf1[1][i],hf1[2][i]), return(0)); ); n = #hf2[1]; for(i=1,n, if(!searchin(hf1,hf2[1][i],hf2[2][i]), return(0)); ); return(1); }; hassetriv(hf,hi) = samehasse(hf,hi,[[],Vecsmall([])],Vecsmall(vector(#hi,i,0))); altriv(al) = hassetriv(alghassef(al),alghassei(al)); alsame(al,hf,hi) = samehasse(alghassef(al),alghassei(al),hf,hi); testcharpol(al,a)= { my (T = algcharpoly(al,a)); print(T); !algpoleval(al,T,a); } get() = gusuite("get", ()->{ my(s='s,i='i,poli,nf,ii,pols,rnf,ss,al); poli = i^2+1; nf = nfinit(poli); ii = Mod(i,poli); pols = s^2+2; rnf = rnfinit(nf, pols); ss = Mod(s,pols); al = alginit(rnf,[-ss,ii]); do("degree", ()->algdegree(al)==2); do("center", ()->algcenter(al)==nf); do("splitting", ()->algsplittingfield(al)==rnf); do("automorphism", ()->algaut(al)==-ss); do("b", ()->algb(al)==ii); do("trivial hasse invariants", ()->altriv(al)); do("charac", ()->algchar(al)==0); do("dim", ()->algdim(al)==4); do("absdim", ()->algdim(al,1)==8); do("basis", ()->#algbasis(al)==8); do("invbasis", ()->#alginvbasis(al)==8); do("basis*invbasis", ()->algbasis(al)*alginvbasis(al)==matid(8)); do("iscyclic", ()->algtype(al)==3); do("radical", ()->algradical(al)==0); \\cyclic => simple }); operations() = gusuite("operations", ()->{ my(s='s,i='i,poli,nf,ii,pols,rnf,ss,al,n,un,u,j); poli = i^2+1; nf = nfinit(poli); ii = Mod(i,poli); pols = s^2+2; rnf = rnfinit(nf, pols); ss = Mod(s,pols); ss = ss*Mod(1,poli); al = alginit(rnf,[-ss,ii]); do("radical", ()->algradical(al)==0); \\cyclic => simple nfii = ii; ii = ii*Mod(1,pols); n = [-ss,ii-1]~; un = [1,0]~; u = [1-ss,ii-1]~; j = [0,1]~; do("addition", ()->algadd(al,n,un)==u); do("negation", ()->algneg(al,u)==[ss-1,1-ii]~); do("soustraction", ()->algsub(al,u,n)==un); do("multiplication", ()->algmul(al,n,un)==n); do("non-commutativity", ()->algmul(al,n,j)==algmul(al,j,n)); do("left division", ()->algdivl(al,u,n)==n); do("right division", ()->algdivr(al,n,u)==n); do("noncommutative left division", ()->algdivl(al,u,j)==[ii+1,1-ss]~); do("noncommutative right division", ()->algdivr(al,j,u)==[ii+1,1+ss]~); do("division by non-invertible", ()->algdivl(al,n,u)); do("nilpotent", ()->algsqr(al,n)==[0,0]~); do("square", ()->algsqr(al,u)==algadd(al,u,n)); do("square j", ()->algsqr(al,j)==[ii,0]~); do("inverse", ()->alginv(al,u)==algsub(al,un,n)); do("powers", ()->algpow(al,u,124)==algadd(al,un,algmul(al,[124,0]~,n))); do("negative powers", ()->algpow(al,j,-56)==un); do("multiplication table j", ()->algtomatrix(al,j)==[0,ii;1,0]); do("multiplication table", ()->algtomatrix(al,u)==[1-ss,-1-ii;ii-1,1+ss]); do("characteristic polynomial", ()->algcharpoly(al,u,'y)==y^2-2*y+1); do("characteristic polynomial j", ()->algcharpoly(al,j,'y)==y^2-nfii); do("trace zero", ()->algtrace(al,n)==0); do("trace commutator", ()->algtrace(al,algsub(al,algmul(al,j,u),algmul(al,u,j)))==0); do("trace", ()->algtrace(al,algmul(al,u,j))==-2-2*nfii); do("norm zero", ()->algnorm(al,n)==0); do("norm one", ()->algnorm(al,u)==1); do("norm j", ()->algnorm(al,j)==-nfii); a = algadd(al,u,j); b = algadd(al, n, [12-4*ii+ss*(4-ii),7+3*ii+ss*(1+7*ii)]~); do("norm is multiplicative a*b", ()->nfalgtobasis(nf,algnorm(al,algmul(al,a,b)))==nfalgtobasis(nf,nfeltmul(nf,algnorm(al,a),algnorm(al,b)))); do("norm is multiplicative b*a", ()->nfalgtobasis(nf,algnorm(al,algmul(al,b,a)))==nfalgtobasis(nf,nfeltmul(nf,algnorm(al,b),algnorm(al,a)))); do("poleval", ()->algbasistoalg(al,algpoleval(al,x^3-2,u)) ==\ algsub(al,algpow(al,u,3),[2,0]~)); do("poleval b", ()->algbasistoalg(al,algpoleval(al,x^3+i*x-3*i,u)) ==\ algsub(al,algadd(al,algpow(al,u,3), algmul(al,[i,0]~,u)), [3*i,0]~)); }); tensor() = gusuite("tensor product of cyclic algebras", ()->{ my(nf,pol,jj,al1,al2,al3,hf12,hf23,p7,p7b,p3,p5); pol = y^2+y+1; nf = nfinit(pol); jj = Mod(y,pol); al1 = alginit(rnfinit(nf,x^2-(1+jj)), [-x, 4*jj+5]); al2 = alginit(rnfinit(nf,x^3-2), [jj*x, 7]); al3 = alginit(rnfinit(nf,x^4+x^3+x^2+x+1), [x^2, 7]); do("radical 1", ()->algradical(al1)==0); \\cyclic => simple do("radical 2", ()->algradical(al2)==0); \\cyclic => simple do("radical 3", ()->algradical(al3)==0); \\cyclic => simple p3 = idealprimedec(nf,3)[1]; p5 = idealprimedec(nf,5)[1]; p7 = idealprimedec(nf,7)[1]; p7b = idealprimedec(nf,7)[2]; hf12 = [[p3,p7,p7b],Vecsmall([3,4,5])]; hf23 = [[p5,p7,p7b],Vecsmall([6,11,7])]; do("tensor of degree 2 and 3 no mo", ()->alsame(algtensor(al1,al2,0),hf12,Vecsmall([]))); }); rnfprimedec2(rnf,pp,nf2) = { my(nf = rnf.nf,pp2,pp3); pp2 = rnfidealup(rnf,pp); pp3 = idealadd(nf2,pp2[1],pp2[2]); for(i=3, #pp2, pp3 = idealadd(nf2,pp3,pp2[i])); return(idealfactor(nf2,pp3)); }; rnfprimedec(rnf,pp) = rnfprimedec2(rnf,pp,nfinit(rnf.polabs)); testgwa(nf,Lpr,Ld,pl) = ()->{ my(rnf, d, n, nf2); rnf = rnfinit(nf,nfgrunwaldwang(nf,Lpr,Ld,pl,x)); d = rnf.disc[1]; n = poldegree(rnf.pol); return(1); nf2 = nfinit(rnf.polabs); for(i=1,#Lpr, if(#mattranspose(rnfprimedec2(rnf,Lpr[i],nf2))*Ld[i] != n, return(0))); return(1); }; gw() = gusuite("Grunwald-Wang", ()->{ my(p2,p3,p5,p7,p11,p13,p17,pp,ppp,nf); nf = nfinit(y); p2 = idealprimedec(nf,2)[1]; p3 = idealprimedec(nf,3)[1]; p5 = idealprimedec(nf,5)[1]; pp = idealprimedec(nf,nextprime(1234))[1]; ppp = idealprimedec(nf,nextprime(4321))[1]; do("A quadratic over Q, 2 large inert, imaginary", testgwa(nf,[pp,ppp],Vecsmall([2,2]),Vecsmall([-1]))); do("A quartic over Q, 2 large inert, imaginary", testgwa(bnfinit(nf),[pp,ppp],Vecsmall([4,4]),Vecsmall([-1]))); nf = nfinit(y^2+1); p2 = idealprimedec(nf,2)[1]; p3 = idealprimedec(nf,3)[1]; p5 = idealprimedec(nf,5)[1]; do("A : degree 4 over Q(i), local degrees [4,1,1]", testgwa(nf,[p2,p3,p5],Vecsmall([4,1,1]),Vecsmall([]))); nf = nfinit(y^2+y+1); p2 = idealprimedec(nf,2)[1]; p3 = idealprimedec(nf,3)[1]; p5 = idealprimedec(nf,5)[1]; p7 = idealprimedec(nf,7)[1]; pp = idealprimedec(nf,nextprime(1248))[1]; ppp = idealprimedec(nf,nextprime(7531))[1]; do("A degree 3 over Q(j), local degrees [3,3] larger primes", testgwa(nf,[pp,ppp],[3,3],[])); nf = nfinit(y^2-5); p2 = idealprimedec(nf,2)[1]; p3 = idealprimedec(nf,3)[1]; p5 = idealprimedec(nf,5)[1]; p7 = idealprimedec(nf,7)[1]; p11 = idealprimedec(nf,11)[1]; p13 = idealprimedec(nf,13)[1]; p17 = idealprimedec(nf,17)[1]; pp = idealprimedec(nf,nextprime(1248))[1]; ppp = idealprimedec(nf,nextprime(4897))[1]; do("A : degree 3 over Q(sqrt(5)), local degrees [3,3] [0,0], larger primes", testgwa(nf,[pp,ppp],[3,3],[0,0])); /* TODO check what happens with [-1,-1] */ nf = nfinit(y^2-7); p2 = idealprimedec(nf,2)[1]; p3 = idealprimedec(nf,3)[1]; p5 = idealprimedec(nf,5)[1]; p7 = idealprimedec(nf,7)[1]; p11 = idealprimedec(nf,11)[1]; p13 = idealprimedec(nf,13)[1]; p17 = idealprimedec(nf,17)[1]; do("A : degree 5 over Q(sqrt(7)), local degrees [5,5,5,5,5,5,5] [0,0]", testgwa(nf,[p2,p3,p5,p7,p11,p13,p17],Vecsmall([5,5,5,5,5,5,5]),Vecsmall([0,0]))); /* TODO check what happens with [-1,-1] */ nf = nfinit(polcyclo(9,y)); p2 = idealprimedec(nf,2)[1]; p3 = idealprimedec(nf,3)[1]; p5 = idealprimedec(nf,5)[1]; p7 = idealprimedec(nf,7)[1]; do("A : degree 9 over Q(zeta_9), local degrees [9,9,9,9]", testgwa(nf,[p2,p3,p5,p7],Vecsmall([9,9,9,9]),Vecsmall([]))); nf = nfinit(y^6 -y^5 -7*y^4 +2*y^3 +7*y^2 -2*y -1); p2 = idealprimedec(nf,2)[1]; p3 = idealprimedec(nf,3)[1]; p5 = idealprimedec(nf,5)[1]; p7 = idealprimedec(nf,7)[1]; p11 = idealprimedec(nf,11)[1]; p13 = idealprimedec(nf,13)[1]; p17 = idealprimedec(nf,17)[1]; pp = idealprimedec(nf,nextprime(1357))[1]; ppp = idealprimedec(nf,nextprime(853))[1]; do("A degree 2 over totally real sextic, local degrees [2,2] [2,2,2,2,2,2], larger primes", testgwa(nf,[pp,ppp],Vecsmall([2,2]),Vecsmall([-1,-1,-1,-1,-1,-1]))); do("A degree 2 over totally real sextic, local degrees [] [2,2,2,2,2,2]", testgwa(nf,[],Vecsmall([]),Vecsmall([-1,-1,-1,-1,-1,-1]))); }); moreoperations() = gusuite("more operations", ()->{ my(x='x, y='y, nf, p1, p2, iinv, finv, al, u, t, b, w, un, pol1, pol2, cp, mul, rnf, aut, ww, tt, ord, invord, Y = varhigher("Y",y)); pol1 = y; nf = nfinit(pol1); p1 = idealprimedec(nf,2)[1]; p2 = idealprimedec(nf,3)[1]; iinv = [0]; finv = [[p1,p2],[-2/3,-1/3]]; setrand(3); al = alginit(nf,[3,finv,iinv],x); do("construct algebra", ()->al); pol2 = algsplittingfield(al).pol; mul = Mod(1,pol1)*Mod(1,pol2); u = [0,1,0]~*mul; t = [x,0,0]~*mul; b = [algb(al),0,0]~*mul; w = [x+x^2-7,1/2+x-3/7*x^2,12*x-1]~*mul; un = [1,0,0]~*mul; do("norm(u)", ()->lift(algnorm(al,u))==lift(algb(al))); do("norm(t)", ()->algnorm(al,t)==rnfeltnorm(algsplittingfield(al),x)); do("trace(u)", ()->algtrace(al,u)==0); do("trace(t)", ()->algtrace(al,t)==rnfelttrace(algsplittingfield(al),x)); do("u+t", ()->algadd(al,u,t)==algadd(al,t,u)); do("u*t", ()->algmul(al,u,t)!=algmul(al,t,u)); do("u^3", ()->algpow(al,u,3)==b); do("w^-1 L", ()->algmul(al,w,alginv(al,w))==un); do("w^-1 R", ()->algmul(al,alginv(al,w),w)==un); do("w^-1*u", ()->algmul(al,w,algdivl(al,w,u))); do("u*w^-1", ()->algmul(al,algdivr(al,u,w),w)); cp = algcharpoly(al,w,Y); do("charpol(w)", ()->cp); do("eval charpol", ()->algadd(al,algadd(al,algpow(al,w,3),algmul(al,[polcoeff(cp,2),0,0]~*mul,algsqr(al,w))),algadd(al,algmul(al,[polcoeff(cp,1),0,0]~*mul,w),[polcoeff(cp,0),0,0]~*mul))==0); do("trace(w)", ()->algtrace(al,w)==-polcoeff(cp,2)); do("norm(w)", ()->algnorm(al,w)==-polcoeff(cp,0)); do("dim", ()->algdim(al)==9); do("absdim", ()->algdim(al,1)==9); do("iscommutative", ()->algiscommutative(al)==0); do("issemisimple", ()->algissemisimple(al)==1); do("issimple", ()->algissimple(al)==1); pol1 = y^2+1; nf = nfinit(pol1); pol2 = x^3 + x^2 - 2*x - 1; rnf = rnfinit(nf,pol2); aut = x^2-2; al = alginit(rnf,[aut,Mod(2,pol1)]); mul = Mod(1,pol1)*Mod(1,pol2); u = [0,1,0]~*mul; t = [x,0,0]~*mul; tt = [y*x,0,0]~*mul; b = [2,0,0]~*mul; un = [1,0,0]~*mul; w = [y*x-1/3*x^2, 2+y/7-x, -12*x-3*y*x^2]~*mul; ww = [-x^2*y, 1/13+y+x+4*x^2, (-2+y)*x^2+(y/3+1/5)*x]~*mul; ord = algbasis(al); invord = alginvbasis(al); do("algleftmultable w+ww", ()->algtomatrix(al,algadd(al,w,ww),1)==(algtomatrix(al,w,1)+algtomatrix(al,ww,1))); do("algleftmultable w*ww", ()->algtomatrix(al,algmul(al,w,ww),1)==(algtomatrix(al,w,1)*algtomatrix(al,ww,1))); do("alg(basis(w))", ()->algbasistoalg(al,algalgtobasis(al,w))==w); do("alg(basis(ww))", ()->algbasistoalg(al,algalgtobasis(al,ww))==ww); do("basis(w)+ww", ()->algadd(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algadd(al,w,ww))); do("basis(w)-ww", ()->algsub(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algsub(al,w,ww))); do("w+basis(ww)", ()->algadd(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algadd(al,w,ww))); do("w-basis(ww)", ()->algsub(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algsub(al,w,ww))); do("basis(w)*ww", ()->algmul(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algmul(al,w,ww))); do("w*basis(ww)", ()->algmul(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algmul(al,w,ww))); do("basis(w)^2", ()->algsqr(al,algalgtobasis(al,w))==algalgtobasis(al,algsqr(al,w))); do("basis(ww)^2", ()->algsqr(al,algalgtobasis(al,ww))==algalgtobasis(al,algsqr(al,ww))); do("basis(w)\\ww", ()->algdivl(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algdivl(al,w,ww))); do("w\\basis(ww)", ()->algdivl(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algdivl(al,w,ww))); do("basis(ww)\\w", ()->algdivl(al,algalgtobasis(al,ww),w)==algalgtobasis(al,algdivl(al,ww,w))); do("ww\basis(w)", ()->algdivl(al,ww,algalgtobasis(al,w))==algalgtobasis(al,algdivl(al,ww,w))); do("basis(w)^-1", ()->alginv(al,algalgtobasis(al,w))==algalgtobasis(al,alginv(al,w))); do("basis(ww)^-1", ()->alginv(al,algalgtobasis(al,ww))==algalgtobasis(al,alginv(al,ww))); do("basis(w)/ww", ()->algdivr(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algdivr(al,w,ww))); do("w/basis(ww)", ()->algdivr(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algdivr(al,w,ww))); do("basis(ww)/w", ()->algdivr(al,algalgtobasis(al,ww),w)==algalgtobasis(al,algdivr(al,ww,w))); do("ww/basis(w)", ()->algdivr(al,ww,algalgtobasis(al,w))==algalgtobasis(al,algdivr(al,ww,w))); do("trace(basis(w))", ()->algtrace(al,w)==algtrace(al,algalgtobasis(al,w))); do("trace(basis(ww))", ()->algtrace(al,ww)==algtrace(al,algalgtobasis(al,ww))); w = [0,0,x*y]~*mul; ww = [1+y,1+x,1+x^2]~*mul; do("alg(basis(w)) 2", ()->algbasistoalg(al,algalgtobasis(al,w))==w); do("alg(basis(ww)) 2", ()->algbasistoalg(al,algalgtobasis(al,ww))==ww); do("basis(w)+ww 2", ()->algadd(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algadd(al,w,ww))); do("basis(w)-ww 2", ()->algsub(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algsub(al,w,ww))); do("w+basis(ww) 2", ()->algadd(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algadd(al,w,ww))); do("w-basis(ww) 2", ()->algsub(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algsub(al,w,ww))); do("basis(w)*ww 2", ()->algmul(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algmul(al,w,ww))); do("w*basis(ww) 2", ()->algmul(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algmul(al,w,ww))); do("basis(w)^2 2", ()->algsqr(al,algalgtobasis(al,w))==algalgtobasis(al,algsqr(al,w))); do("basis(ww)^2 2", ()->algsqr(al,algalgtobasis(al,ww))==algalgtobasis(al,algsqr(al,ww))); do("basis(w)\ww 2", ()->algdivl(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algdivl(al,w,ww))); do("w\basis(ww) 2", ()->algdivl(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algdivl(al,w,ww))); do("basis(ww)\w 2", ()->algdivl(al,algalgtobasis(al,ww),w)==algalgtobasis(al,algdivl(al,ww,w))); do("ww\basis(w) 2", ()->algdivl(al,ww,algalgtobasis(al,w))==algalgtobasis(al,algdivl(al,ww,w))); do("basis(w)^-1 2", ()->alginv(al,algalgtobasis(al,w))==algalgtobasis(al,alginv(al,w))); do("basis(ww)^-1 2", ()->alginv(al,algalgtobasis(al,ww))==algalgtobasis(al,alginv(al,ww))); do("basis(w)/ww 2", ()->algdivr(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algdivr(al,w,ww))); do("w/basis(ww) 2", ()->algdivr(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algdivr(al,w,ww))); do("basis(ww)/w 2", ()->algdivr(al,algalgtobasis(al,ww),w)==algalgtobasis(al,algdivr(al,ww,w))); do("ww/basis(w) 2", ()->algdivr(al,ww,algalgtobasis(al,w))==algalgtobasis(al,algdivr(al,ww,w))); do("trace(basis(w)) 2", ()->algtrace(al,w)==algtrace(al,algalgtobasis(al,w))); do("trace(basis(ww)) 2", ()->algtrace(al,ww)==algtrace(al,algalgtobasis(al,ww))); w = [1/2,1/3*x,1/5]~*mul; ww = [1+y,1+x,1+x^2]~*mul; do("alg(basis(w)) 3", ()->algbasistoalg(al,algalgtobasis(al,w))==w); do("alg(basis(ww)) 3", ()->algbasistoalg(al,algalgtobasis(al,ww))==ww); do("basis(w)+ww 3", ()->algadd(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algadd(al,w,ww))); do("basis(w)-ww 3", ()->algsub(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algsub(al,w,ww))); do("w+basis(ww) 3", ()->algadd(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algadd(al,w,ww))); do("w-basis(ww) 3", ()->algsub(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algsub(al,w,ww))); do("basis(w)*ww 3", ()->algmul(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algmul(al,w,ww))); do("w*basis(ww) 3", ()->algmul(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algmul(al,w,ww))); do("basis(w)^2 3", ()->algsqr(al,algalgtobasis(al,w))==algalgtobasis(al,algsqr(al,w))); do("basis(ww)^2 3", ()->algsqr(al,algalgtobasis(al,ww))==algalgtobasis(al,algsqr(al,ww))); do("basis(w)\ww 3", ()->algdivl(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algdivl(al,w,ww))); do("w\basis(ww) 3", ()->algdivl(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algdivl(al,w,ww))); do("basis(ww)\w 3", ()->algdivl(al,algalgtobasis(al,ww),w)==algalgtobasis(al,algdivl(al,ww,w))); do("ww\basis(w) 3", ()->algdivl(al,ww,algalgtobasis(al,w))==algalgtobasis(al,algdivl(al,ww,w))); do("basis(w)^-1 3", ()->alginv(al,algalgtobasis(al,w))==algalgtobasis(al,alginv(al,w))); do("basis(ww)^-1 3", ()->alginv(al,algalgtobasis(al,ww))==algalgtobasis(al,alginv(al,ww))); do("basis(w)/ww 3", ()->algdivr(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algdivr(al,w,ww))); do("w/basis(ww) 3", ()->algdivr(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algdivr(al,w,ww))); do("basis(ww)/w 3", ()->algdivr(al,algalgtobasis(al,ww),w)==algalgtobasis(al,algdivr(al,ww,w))); do("ww/basis(w) 3", ()->algdivr(al,ww,algalgtobasis(al,w))==algalgtobasis(al,algdivr(al,ww,w))); do("trace(basis(w)) 3", ()->algtrace(al,w)==algtrace(al,algalgtobasis(al,w))); do("trace(basis(ww)) 3", ()->algtrace(al,ww)==algtrace(al,algalgtobasis(al,ww))); do("radical", ()->algradical(al)==0); \\cyclic => simple do("iscommutative cyc 3", ()->algiscommutative(al)==0); do("issemisimple cyc 3", ()->algissemisimple(al)==1); do("issimple cyc 3", ()->algissimple(al)==1); pol1 = y; nf = nfinit(pol1); pol2 = x^2-2; rnf = rnfinit(nf,pol2); aut = -x; al = alginit(rnf,[aut,Mod(5,pol1)]); mul = Mod(1,pol1)*Mod(1,pol2); u = [0,1]~*mul; t = [x,0]~*mul; b = [5,0]~*mul; un = [1,0]~*mul; w = [-1/3*x^2, 2/7-x]~*mul; ww = [-x^2*4, 1/13+x+4*x^2]~*mul; ord = algbasis(al); invord = alginvbasis(al); do("algleftmultable/Q w+ww", ()->algtomatrix(al,algadd(al,w,ww),1)==(algtomatrix(al,w,1)+algtomatrix(al,ww,1))); do("algleftmultable/Q w*ww", ()->algtomatrix(al,algmul(al,w,ww),1)==(algtomatrix(al,w,1)*algtomatrix(al,ww,1))); do("alg(basis(w))/Q", ()->algbasistoalg(al,algalgtobasis(al,w))==w); do("alg(basis(ww))/Q", ()->algbasistoalg(al,algalgtobasis(al,ww))==ww); do("basis(w)+ww/Q", ()->algadd(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algadd(al,w,ww))); do("basis(w)-ww/Q", ()->algsub(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algsub(al,w,ww))); do("w+basis(ww)/Q", ()->algadd(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algadd(al,w,ww))); do("w-basis(ww)/Q", ()->algsub(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algsub(al,w,ww))); do("basis(w)*ww/Q", ()->algmul(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algmul(al,w,ww))); do("w*basis(ww)/Q", ()->algmul(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algmul(al,w,ww))); do("basis(w)^2/Q", ()->algsqr(al,algalgtobasis(al,w))==algalgtobasis(al,algsqr(al,w))); do("basis(ww)^2/Q", ()->algsqr(al,algalgtobasis(al,ww))==algalgtobasis(al,algsqr(al,ww))); do("basis(w)\ww/Q", ()->algdivl(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algdivl(al,w,ww))); do("w\basis(ww)/Q", ()->algdivl(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algdivl(al,w,ww))); do("basis(ww)\w/Q", ()->algdivl(al,algalgtobasis(al,ww),w)==algalgtobasis(al,algdivl(al,ww,w))); do("ww\basis(w)/Q", ()->algdivl(al,ww,algalgtobasis(al,w))==algalgtobasis(al,algdivl(al,ww,w))); do("basis(w)^-1/Q", ()->alginv(al,algalgtobasis(al,w))==algalgtobasis(al,alginv(al,w))); do("basis(ww)^-1/Q", ()->alginv(al,algalgtobasis(al,ww))==algalgtobasis(al,alginv(al,ww))); do("basis(w)/ww/Q", ()->algdivr(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algdivr(al,w,ww))); do("w/basis(ww)/Q", ()->algdivr(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algdivr(al,w,ww))); do("basis(ww)/w/Q", ()->algdivr(al,algalgtobasis(al,ww),w)==algalgtobasis(al,algdivr(al,ww,w))); do("ww/basis(w)/Q", ()->algdivr(al,ww,algalgtobasis(al,w))==algalgtobasis(al,algdivr(al,ww,w))); do("trace(basis(w))/Q", ()->algtrace(al,w)==algtrace(al,algalgtobasis(al,w))); do("trace(basis(ww))/Q", ()->algtrace(al,ww)==algtrace(al,algalgtobasis(al,ww))); do("radical/Q", ()->algradical(al)==0); \\cyclic => simple do("iscommutative /Q", ()->algiscommutative(al)==0); do("issemisimple /Q", ()->algissemisimple(al)==1); do("issimple /Q", ()->algissimple(al)==1); }); tablealg() = gusuite("table algebra", ()->{ my(x='x, al, mt, p, un, a, b, c, d, e, ss, projm, liftm, pa, sc); mt = [[1,0,0;0,1,0;0,0,1],[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]]; \\Matrices [*,*;0,*] un = [1,0,0]~; a = [1,0,-1]~; b = [0,-1,1]~; do("algisassociative 0.0", ()->algisassociative(mt)); do("algisassociative 0.1", ()->algisassociative(mt[2..3])); my (mt0 = mt); mt0[3][3,1] = 1; do("algisassociative 0.2", ()->algisassociative(mt0)); do("algisassociative 0.3", ()->algisassociative('x)); al = algtableinit(mt,0); do("construction 0", ()->al); do("iscyclic 0", ()->algtype(al)==1); do("dim 0", ()->algdim(al,1)==3); do("dim 0b", ()->algdim(al)==3); do("char 0", ()->algchar(al)==0); do("a+b 0", ()->algadd(al,a,b)==[1,-1,0]~); do("a-b 0", ()->algsub(al,a,b)==[1,1,-2]~); do("a*b 0", ()->algmul(al,a,b)==[0,-1,0]~); do("b*a 0", ()->algmul(al,b,a)==[0,0,0]~); do("a^2 0", ()->algsqr(al,a)==a); do("b^2 0", ()->algsqr(al,b)==b); e = [1,1,0]~; do("e^691691 0", ()->algpow(al,e,691691)==[1,691691,0]~); d = [1,0,1]~; do("d^101 0", ()->algpow(al,d,101)==[1,0,2^101-1]~); do("multable(a) 0", ()->algtomatrix(al,a,1)==[1,0,0;0,1,0;-1,0,0]); do("multable(b) 0", ()->algtomatrix(al,b,1)==[0,0,0;-1,0,-1;1,0,1]); do("divl(d,a) 0", ()->algdivl(al,d,a)==a); do("divl(d,b) 0", ()->algdivl(al,d,b)==[0,-1,1/2]~); do("d^-1 0", ()->alginv(al,d)==[1,0,-1/2]~); do("divr(a,d) 0", ()->algdivr(al,a,d)==a); do("divr(b,d) 0", ()->algdivr(al,b,d)==[0,-1/2,1/2]~); c = [0,7,0]~; do("rad(al) 0", ()->#algradical(al)==1); \\matrices [0,*;0,0] do("ss(al) 0", ()->#algradical(algquotient(al,algradical(al)))==0); [ss,projm,liftm] = algquotient(al,algradical(al),1); pa = projm*a; do("proj(a) idem 0", ()->algsqr(ss,pa)==pa); do("idemproj 0", ()->algcentralproj(ss,[pa,algsub(ss,projm*un,pa)])); sc = algcentralproj(ss,[pa,algsub(ss,projm*un,pa)]); do("simple components 0", ()->algmultable(sc[1])==[Mat(1)] && algmultable(sc[2])==[Mat(1)]); do("center al 0", ()->#algcenter(al)==1); do("center ss 0", ()->#algcenter(ss)==2); do("primesubalg ss 0", ()->#algprimesubalg(ss)==-1); do("charpol annihil(a) 0", ()->testcharpol(al,a)); do("charpol annihil(b) 0", ()->testcharpol(al,b)); do("charpol annihil(c) 0", ()->testcharpol(al,c)); do("charpol annihil(d) 0", ()->testcharpol(al,d)); do("charpol annihil(e) 0", ()->testcharpol(al,e)); do("random 0", ()->algrandom(al,1)); do("algsimpledec 0", ()->#algsimpledec(ss)[2]==2); do("alg_decomposition 0", ()->dec=algsimpledec(al); #dec[1]==1 && #dec[2]==2); do("iscommutative 0", ()->algiscommutative(al)==0); do("issemisimple 0", ()->algissemisimple(al)==0); do("issimple 0", ()->algissimple(al)==0); do("issimple ss 0", ()->algissimple(ss)==0); do("isdivision 0", ()->algisdivision(al)==0); p = 2; al = algtableinit(mt,p); do("algisassociative 2", ()->algisassociative(mt,p)); do("construction 2", ()->al); do("iscyclic 2", ()->algtype(al)==1); do("dim 2", ()->algdim(al,1)==3); do("char 2", ()->algchar(al)==p); do("a+b 2", ()->algadd(al,a,b)==[1,1,0]~); do("a-b 2", ()->algsub(al,a,b)==algadd(al,a,b)); do("a*b 2", ()->algmul(al,a,b)==[0,p-1,0]~); do("b*a 2", ()->algmul(al,b,a)==[0,0,0]~); do("a^2 2", ()->algsqr(al,a)==a*Mod(1,p)); do("b^2 2", ()->algsqr(al,b)==b*Mod(1,p)); do("multable(a) 2", ()->algtomatrix(al,a,1)==[1,0,0;0,1,0;-1,0,0]*Mod(1,p)); do("multable(b) 2", ()->algtomatrix(al,b,1)==[0,0,0;-1,0,-1;1,0,1]*Mod(1,p)); do("divl(un,a) 2", ()->algdivl(al,un,a)==a*Mod(1,p)); do("divl(un,b) 2", ()->algdivl(al,un,b)==b*Mod(1,p)); do("un^-1 2", ()->alginv(al,un)==un); do("divr(a,un) 2", ()->algdivr(al,a,un)==a*Mod(1,p)); do("divr(b,un) 2", ()->algdivr(al,b,un)==b*Mod(1,p)); do("rad(al) 2", ()->#algradical(al)==1); \\matrices [0,*;0,0] do("ss(al) 2", ()->#algradical(algquotient(al,algradical(al)))==0); [ss,projm,liftm] = algquotient(al,algradical(al),1); pa = projm*a; do("proj(a) idem 2", ()->algsqr(ss,pa)==pa*Mod(1,p)); do("idemproj 2", ()->algcentralproj(ss,[pa,algsub(ss,projm*un,pa)])); sc = algcentralproj(ss,[pa,algsub(ss,projm*un,pa)]); do("simple components 2", ()->algmultable(sc[1])==[Mat(Mod(1,p))] && algmultable(sc[2])==[Mat(Mod(1,p))]); do("center al 2", ()->#algcenter(al)==1); do("center ss 2", ()->#algcenter(ss)==2); do("primesubalg ss 2", ()->#algprimesubalg(ss)==2); do("charpol annihil(a) 2", ()->testcharpol(al,a)); do("charpol annihil(b) 2", ()->testcharpol(al,b)); do("charpol annihil(c) 2", ()->testcharpol(al,c)); do("random 2", ()->algrandom(al,1)); do("algsimpledec 2", ()->#algsimpledec(ss)[2]==2); do("alg_decomposition 2", ()->dec=algsimpledec(al); #dec[1]==1 && #dec[2]==2); do("iscommutative 2", ()->algiscommutative(al)==0); do("issemisimple 2", ()->algissemisimple(al)==0); do("issimple 2", ()->algissimple(al)==0); do("issimple ss 2", ()->algissimple(ss)==0); do("matrix trace 2", ()->algtrace(al,[un,vector(3)~;vector(3)~,un])==0); do("matrix norm 2", ()->algnorm(al,[un,vector(3)~;vector(3)~,un])==1); do("norm 2", ()->algnorm(al,un)==1); p = 3; mt = [[1,0;0,1],[0,0;1,0]];\\F3[x]/(x^2) un = [1,0]~; a = [1,-1]~; b = [0,1]~; al = algtableinit(mt,p); do("construction 3", ()->al); do("iscyclic 3", ()->algtype(al)==1); do("dim 3", ()->algdim(al,1)==2); do("char 3", ()->algchar(al)==p); do("a+b 3", ()->algadd(al,a,b)==un); do("a-b 3", ()->algsub(al,a,b)==[1,1]~); do("a*b 3", ()->algmul(al,a,b)==[0,1]~); do("b*a 3", ()->algmul(al,b,a)==[0,1]~); do("a^2 3", ()->algsqr(al,a)==[1,1]~); do("b^2 3", ()->algsqr(al,b)==[0,0]~); do("a^691691 3", ()->algpow(al,a,691691)==[1,-691691]~*Mod(1,p)); do("multable(a) 3", ()->algtomatrix(al,a,1)==[1,0;-1,1]*Mod(1,p)); do("multable(b) 3", ()->algtomatrix(al,b,1)==[0,0;1,0]); do("algdivl(a,b) 3", ()->algdivl(al,a,b)==b); do("a^-1 3", ()->alginv(al,a)==[1,1]~); do("algdivr(b,a) 3", ()->algdivr(al,b,a)==b); do("rad(al) 3", ()->#algradical(al)==1); \\ideal (x) do("ss(al) 3", ()->#algradical(algquotient(al,algradical(al)))==0); [ss,projm,liftm] = algquotient(al,algradical(al),1); do("center al 3", ()->#algcenter(al)==2); do("center ss 3", ()->#algcenter(ss)==1); do("primesubalg ss 3", ()->#algprimesubalg(ss)==1); do("charpol annihil(a) 3", ()->testcharpol(al,a)); do("charpol annihil(b) 3", ()->testcharpol(al,b)); do("random 3", ()->algrandom(al,1)); do("algsimpledec 3", ()->#algsimpledec(ss)[2]==1); do("alg_decomposition 3", ()->dec=algsimpledec(al); #dec[1]==1 && #dec[2]==1); do("iscommutative 3", ()->algiscommutative(al)==1); do("issemisimple 3", ()->algissemisimple(al)==0); do("issemisimple ss 3", ()->algissemisimple(ss)==1); do("issimple 3", ()->algissimple(al)==0); do("issimple ss 3", ()->algissimple(ss)==1); p = 3; mt = [[1,0,0;0,1,0;0,0,1],[0,0,0;1,0,0;0,1,0],[0,0,0;0,0,0;1,0,0]];\\F3[x]/(x^3) un = [1,0,0]~; a = [1,-1,0]~; b = [0,1,0]~; al = algtableinit(mt,p); do("construction 3c", ()->al); do("iscyclic 3c", ()->algtype(al)==1); do("dim 3c", ()->algdim(al,1)==3); do("char 3c", ()->algchar(al)==p); do("a+b 3c", ()->algadd(al,a,b)==un); do("a-b 3c", ()->algsub(al,a,b)==[1,1,0]~); do("a*b 3c", ()->algmul(al,a,b)==[0,1,p-1]~); do("b*a 3c", ()->algmul(al,b,a)==[0,1,p-1]~); do("a^2 3c", ()->algsqr(al,a)==[1,1,1]~); do("b^2 3c", ()->algsqr(al,b)==[0,0,1]~); do("a^691691 3c", ()->algpow(al,a,691691)==[1,-691691,(691691*691690)\2]~*Mod(1,p)); do("multable(a) 3c", ()->algtomatrix(al,a,1)==[1,0,0;-1,1,0;0,-1,1]*Mod(1,p)); do("multable(b) 3c", ()->algtomatrix(al,b,1)==[0,0,0;1,0,0;0,1,0]); do("algdivl(a,b) 3c", ()->algdivl(al,a,b)==[0,1,1]~); do("a^-1 3c", ()->alginv(al,a)==[1,1,1]~); do("algdivr(b,a) 3c", ()->algdivr(al,b,a)==[0,1,1]~); do("rad(al) 3c", ()->#algradical(al)==2); \\ideal (x), basis (x,x^2) do("ss(al) 3c", ()->#algradical(algquotient(al,algradical(al)))==0); [ss,projm,liftm] = algquotient(al,algradical(al),1); do("center al 3c", ()->#algcenter(al)==3); do("center ss 3c", ()->#algcenter(ss)==1); do("primesubalg ss 3c", ()->#algprimesubalg(ss)==1); do("charpol annihil(a) 3c", ()->testcharpol(al,a)); do("charpol annihil(b) 3c", ()->testcharpol(al,b)); do("random 3c", ()->algrandom(al,1)); do("algsimpledec 3c", ()->#algsimpledec(ss)[2]==1); do("alg_decomposition 3c", ()->dec=algsimpledec(al); #dec[1]==2 && #dec[2]==1); do("iscommutative 3c", ()->algiscommutative(al)==1); do("issemisimple 3c", ()->algissemisimple(al)==0); do("issemisimple ss 3c", ()->algissemisimple(ss)==1); do("issimple 3c", ()->algissimple(al)==0); do("issimple ss 3c", ()->algissimple(ss)==1); p = 2; mt = [[1,0;0,1],[0,1;1,1]]; \\F2[x]/(x^2+x+1) un = [1,0]~; a = [0,1]~; b = [1,1]~; al = algtableinit(mt,p); do("construction 2b", ()->al); do("iscyclic 2b", ()->algtype(al)==1); do("dim 2b", ()->algdim(al,1)==2); do("char 2b", ()->algchar(al)==p); do("a+b 2b", ()->algadd(al,a,b)==un); do("a-b 2b", ()->algsub(al,a,b)==un); do("a*b 2b", ()->algmul(al,a,b)==un); do("b*a 2b", ()->algmul(al,b,a)==un); do("a^2 2b", ()->algsqr(al,a)==b); do("b^2 2b", ()->algsqr(al,b)==a); do("a^691691 2b", ()->algpow(al,a,691691)==b); do("multable(a) 2b", ()->algtomatrix(al,a,1)==[0,1;1,1]); do("multable(b) 2b", ()->algtomatrix(al,b,1)==[1,1;1,0]); do("divl(a,b) 2b", ()->algdivl(al,a,b)==a); do("a^-1 2b", ()->alginv(al,a)==b); do("divr(b,a) 2b", ()->algdivr(al,b,a)==a); do("rad(al) 2b", ()->#algradical(al)==0); \\separable extension of F2 do("center al 2b", ()->#algcenter(al)==2); do("primesubalg al 2b", ()->#algprimesubalg(al)==1); do("charpol annihil(a) 2b", ()->testcharpol(al,a)); do("charpol annihil(b) 2b", ()->testcharpol(al,b)); do("random 2b", ()->algrandom(al,1)); do("algsimpledec 2b", ()->#algsimpledec(al)[2]==1); do("alg_decomposition 2b", ()->dec=algsimpledec(al); dec[1]==0 && #dec[2]==1 && algdim(dec[2][1],1)==2); do("iscommutative 2b", ()->algiscommutative(al)==1); do("issemisimple 2b", ()->algissemisimple(al)==1); do("issimple 2b", ()->algissimple(al)==1); do("issimple,1 2b", ()->algissimple(al,1)==1); p = 3; mt = [matid(4), [0,1,0,0; 1,0,0,0; 0,0,1,0; 0,0,0,-1], [0,0,0,1/2; 0,0,0,1/2; 1,-1,0,0; 0,0,0,0], [0,0,1/2,0; 0,0,-1/2,0; 0,0,0,0; 1,1,0,0]]*Mod(1,p); \\M_2(F3) un = [1,0,0,0]~; a = [0,1,-1,0]~; b = [1,1,0,1]~; al = algtableinit(mt,p); do("construction 3b", ()->al); do("iscyclic 3b", ()->algtype(al)==1); do("dim 3b", ()->algdim(al,1)==4); do("char 3b", ()->algchar(al)==p); do("a+b 3b", ()->algadd(al,a,b)==[1,-1,2,1]~*Mod(1,p)); do("a-b 3b", ()->algsub(al,a,b)==[2,0,2,2]~); do("a*b 3b", ()->algmul(al,a,b)==[2,2,0,2]~); do("b*a 3b", ()->algmul(al,b,a)==[2,0,1,1]~); do("a^2 3b", ()->algsqr(al,a)==un); do("b^2 3b", ()->algsqr(al,b)==-b*Mod(1,p)); do("a^691691 3b", ()->algpow(al,a,691691)==a*Mod(1,p)); do("b^691691 3b", ()->algpow(al,b,691691)==b); do("multable(a) 3b", ()->algtomatrix(al,a,1)==[0,1,0,1;1,0,0,1;2,1,1,0;0,0,0,2]); do("multable(b) 3b", ()->algtomatrix(al,b,1)==[1,1,2,0;1,1,1,0;0,0,2,0;1,1,0,0]); do("divl(a,b) 3b", ()->algdivl(al,a,b)==[2,2,0,2]~); do("a^-1 3b", ()->alginv(al,a)==[0,1,2,0]~); do("divr(b,a) 3b", ()->algdivr(al,b,a)==[2,0,1,1]~); c = [0,0,1,0]~; do("rad(al) 3b", ()->#algradical(al)==0); \\matrix ring is semisimple do("center al 3b", ()->#algcenter(al)==1); do("primesubalg al 3b", ()->#algprimesubalg(al)==1); do("charpol annihil(a) 3b", ()->testcharpol(al,a)); do("charpol annihil(b) 3b", ()->testcharpol(al,b)); do("charpol annihil(c) 3b", ()->testcharpol(al,c)); do("random 3b", ()->algrandom(al,1)); do("algsimpledec 3b", ()->#algsimpledec(al)[2]==1); do("alg_decomposition 3b", ()->dec=algsimpledec(al); dec[1]==0 && #dec[2]==1 && #algcenter(dec[2][1])==1); do("iscommutative 3b", ()->algiscommutative(al)==0); do("issemisimple 3b", ()->algissemisimple(al)==1); do("issimple 3b", ()->algissimple(al)==1); p = 2; mt = [matid(4), [0,0,1,0; 1,0,0,1; 0,0,0,0; 0,0,-1,0], [0,0,0,0; 0,0,0,0; 1,0,0,0; 0,1,0,0], [0,0,0,0; 0,0,0,0; 0,0,1,0; 1,0,0,1]]*Mod(1,p); \\M_2(F2) un = [1,0,0,0]~; a = [0,1,0,0]~; b = [1,0,0,1]~; al = algtableinit(mt,p); do("construction 2c", ()->al); do("iscyclic 2c", ()->algtype(al)==1); do("dim 2c", ()->algdim(al,1)==4); do("char 2c", ()->algchar(al)==p); do("a+b 2c", ()->algadd(al,a,b)==[1,1,0,1]~); do("a-b 2c", ()->algsub(al,a,b)==[1,1,0,1]~); do("a*b 2c", ()->algmul(al,a,b)==[0,0,0,0]~); do("b*a 2c", ()->algmul(al,b,a)==a); do("a^2 2c", ()->algsqr(al,a)==[0,0,0,0]~); do("b^2 2c", ()->algsqr(al,b)==b); c = [1,1,1,1]~; do("a^691691 2c", ()->algpow(al,a,691691)==[0,0,0,0]~); do("b^691691 2c", ()->algpow(al,b,691691)==b); do("c^691691 2c", ()->algpow(al,c,691691)==[0,1,1,1]~); do("multable(a) 2c", ()->algtomatrix(al,a,1)==[0,0,1,0;1,0,0,1;0,0,0,0;0,0,1,0]); do("multable(b) 2c", ()->algtomatrix(al,b,1)==[1,0,0,0;0,1,0,0;0,0,0,0;1,0,0,0]); do("divl(c,a) 2c", ()->algdivl(al,c,a)==[0,0,0,1]~); do("divl(c,b) 2c", ()->algdivl(al,c,b)==[0,0,1,0]~); do("c^-1 2c", ()->alginv(al,c)==[0,1,1,1]~); do("divr(a,c) 2c", ()->algdivr(al,a,c)==[1,1,0,1]~); do("divr(b,c) 2c", ()->algdivr(al,b,c)==[0,1,0,0]~); do("rad(al) 2c", ()->#algradical(al)==0); \\matrix ring is semisimple do("center al 2c", ()->#algcenter(al)==1); do("primesubalg al 2c", ()->#algprimesubalg(al)==1); do("charpol annihil(a) 2c", ()->testcharpol(al,a)); do("charpol annihil(b) 2c", ()->testcharpol(al,b)); do("charpol annihil(c) 2c", ()->testcharpol(al,c)); do("random 2c", ()->algrandom(al,1)); do("algsimpledec 2c", ()->#algsimpledec(al)[2]==1); do("alg_decomposition 2c", ()->dec=algsimpledec(al); dec[1]==0 && #dec[2]==1 && #algcenter(dec[2][1])==1); do("iscommutative 2c", ()->algiscommutative(al)==0); do("issemisimple 2c", ()->algissemisimple(al)==1); do("issimple 2c", ()->algissimple(al)==1); p = 5; mt = [Mat(Mod(1,p))]; un = [1]~; a = [2]~; b = [3]~; al = algtableinit(mt,p); do("construction 5", ()->al); do("iscyclic 5", ()->algtype(al)==1); do("dim 5", ()->algdim(al,1)==1); do("char 5", ()->algchar(al)==p); do("a+b 5", ()->algadd(al,a,b)==[Mod(0,p)]~); do("a-b 5", ()->algsub(al,a,b)==[Mod(4,p)]~); do("a*b 5", ()->algmul(al,a,b)==[Mod(1,p)]~); do("b*a 5", ()->algmul(al,b,a)==[Mod(1,p)]~); do("a^2 5", ()->algsqr(al,a)==[Mod(4,p)]~); do("b^2 5", ()->algsqr(al,b)==[Mod(-1,p)]~); do("a^691691 5", ()->algpow(al,a,691691)==b); do("multable(a) 5", ()->algtomatrix(al,a,1)==Mat(Mod(2,p))); do("multable(b) 5", ()->algtomatrix(al,b,1)==Mat(Mod(3,p))); do("divl(a,b) 5", ()->algdivl(al,a,b)==[Mod(4,p)]~); do("a^-1 5", ()->alginv(al,a)==[Mod(3,p)]~); do("divr(a,b) 5", ()->algdivr(al,a,b)==[Mod(4,p)]~); do("rad(al) 5", ()->#algradical(al)==0); \\F5, dim 1 do("center al 5", ()->#algcenter(al)==1); do("primesubalg al 5", ()->#algprimesubalg(al)==1); do("charpol annihil(a) 5", ()->testcharpol(al,a)); do("charpol annihil(b) 5", ()->testcharpol(al,b)); do("random 5", ()->algrandom(al,1)); do("algsimpledec 5", ()->#algsimpledec(al)[2]==1); do("alg_decomposition 5", ()->dec=algsimpledec(al); dec[1]==0 && #dec[2]==1 && algdim(dec[2][1],1)==1); do("iscommutative 5", ()->algiscommutative(al)==1); do("issemisimple 5", ()->algissemisimple(al)==1); do("issimple 5", ()->algissimple(al)==1); p = 0; \\M_2(Q)+Q mt = [matid(5), [0,0,1,0,0; 1,0,0,1,0; 0,0,0,0,0; 0,0,-1,0,0; 0,1,-1,-1,1], [0,0,0,0,0; 0,0,0,0,0; 1,0,0,0,0; 0,1,0,0,0; 0,0,0,0,0], [0,0,0,0,0; 0,0,0,0,0; 0,0,1,0,0; 1,0,0,1,0; 0,0,0,0,0], [0,0,0,0,0; 0,0,0,0,0; 0,0,0,0,0; 0,0,0,0,0; 1,1,0,0,1] ]; un = [1,0,0,0,0]~; a = [1,0,0,0,-1]~; b = [1,1,0,0,0]~; al = algtableinit(mt,p); do("construction 0b", ()->al); do("iscyclic 0b", ()->algtype(al)==1); do("dim 0b", ()->algdim(al,1)==5); do("char 0b", ()->algchar(al)==p); do("a+b 0b", ()->algadd(al,a,b)==[2,1,0,0,-1]~); do("a-b 0b", ()->algsub(al,a,b)==[0,-1,0,0,-1]~); do("a*b 0b", ()->algmul(al,a,b)==[1,1,0,0,-2]~); do("b*a 0b", ()->algmul(al,b,a)==algmul(al,a,b));\\a central do("a^2 0b", ()->algsqr(al,a)==a); do("b^2 0b", ()->algsqr(al,b)==[1,2,0,0,1]~); do("a^691691 0b", ()->algpow(al,a,691691)==a); do("b^691 0b", ()->algpow(al,b,691)==[1,691,0,0,2^691-1-691]~); do("multable(a) 0b", ()->algtomatrix(al,a,1)== [1,0,0,0,0; 0,1,0,0,0; 0,0,1,0,0; 0,0,0,1,0; -1,-1,0,0,0]); do("multable(b) 0b", ()->algtomatrix(al,b,1)== [1,0,1,0,0; 1,1,0,1,0; 0,0,1,0,0; 0,0,-1,1,0; 0,1,-1,-1,2]); do("divl(b,a) 0b", ()->algdivl(al,b,a)==[1,-1,0,0,0]~); do("b^-1 0b", ()->alginv(al,b)==[1,-1,0,0,1/2]~); do("divr(a,b) 0b", ()->algdivr(al,a,b)==algdivl(al,b,a)); do("rad(al) 0b", ()->#algradical(al)==0); do("idemproj 0b", ()->algcentralproj(al,[a,algsub(al,un,a)])); sc = algcentralproj(al,[a,algsub(al,un,a)]); do("simple components 0b", ()->algdim(sc[1],1)==4 && algdim(sc[2],1)==1); do("mt M2 component 0b", ()->algmultable(sc[1])[1]==matid(4)); do("center al 0b", ()->#algcenter(al)==2); do("primesubalg al 0b", ()->#algprimesubalg(al)==-1); do("charpol annihil(a) 0b", ()->testcharpol(al,a)); do("charpol annihil(b) 0b", ()->testcharpol(al,b)); do("random 0b", ()->algrandom(al,1)); do("algsimpledec 0b", ()->#algsimpledec(al)[2]==2); do("alg_decomposition 0b", ()->dec=algsimpledec(al); dec[1]==0 && #dec[2]==2 && #algcenter(dec[2][1])==1 && #algcenter(dec[2][2])==1 && (algdim(dec[2][1],1)==4 || algdim(dec[2][2],1)==4)); do("subalg M2(Q)", ()->sal=algsubalg(al,[1,0,0,0; 0,1,0,0; 0,0,1,0; 0,0,0,1;\ 0,0,0,0])[1]; algisassociative(sal) && algradical(sal)==0 &&\ #algsimpledec(sal)[2]==1); do("iscommutative 0b", ()->algiscommutative(al)==0); do("issemisimple 0b", ()->algissemisimple(al)==1); do("issimple 0b", ()->algissimple(al)==0); p = 3; al = algtableinit(mt,p); do("construction 3d", ()->al); do("iscyclic 3d", ()->algtype(al)==1); do("dim 3d", ()->algdim(al,1)==5); do("char 3d", ()->algchar(al)==p); do("a+b 3d", ()->algadd(al,a,b)==[2,1,0,0,-1]~*Mod(1,p)); do("a-b 3d", ()->algsub(al,a,b)==[0,-1,0,0,-1]~*Mod(1,p)); do("a*b 3d", ()->algmul(al,a,b)==[1,1,0,0,-2]~*Mod(1,p)); do("b*a 3d", ()->algmul(al,b,a)==algmul(al,a,b));\\a central do("a^2 3d", ()->algsqr(al,a)==a*Mod(1,p)); do("b^2 3d", ()->algsqr(al,b)==[1,2,0,0,1]~); do("a^691691 3d", ()->algpow(al,a,691691)==a*Mod(1,p)); do("b^691 3d", ()->algpow(al,b,691)==[1,691,0,0,2^691-1-691]~*Mod(1,p)); do("multable(a) 3d", ()->algtomatrix(al,a,1)== [1,0,0,0,0; 0,1,0,0,0; 0,0,1,0,0; 0,0,0,1,0; -1,-1,0,0,0]*Mod(1,p)); do("multable(b) 3d", ()->algtomatrix(al,b,1)== [1,0,1,0,0; 1,1,0,1,0; 0,0,1,0,0; 0,0,-1,1,0; 0,1,-1,-1,2]*Mod(1,p)); do("divl(b,a) 3d", ()->algdivl(al,b,a)==[1,-1,0,0,0]~*Mod(1,p)); do("b^-1 3d", ()->alginv(al,b)==[1,-1,0,0,1/2]~*Mod(1,p)); do("divr(a,b) 3d", ()->algdivr(al,a,b)==algdivl(al,b,a)); do("rad(al) 3d", ()->#algradical(al)==0); do("idemproj 3d", ()->algcentralproj(al,[a,algsub(al,un,a)])); sc = algcentralproj(al,[a,algsub(al,un,a)]); do("simple components 3d", ()->algdim(sc[1],1)==4 && algdim(sc[2],1)==1); do("mt M2 component 3d", ()->algmultable(sc[1])[1]==matid(4)); do("center al 3d", ()->#algcenter(al)==2); do("primesubalg al 3d", ()->#algprimesubalg(al)==2); do("charpol annihil(a) 3d", ()->testcharpol(al,a)); do("charpol annihil(b) 3d", ()->testcharpol(al,b)); do("random 3d", ()->algrandom(al,1)); do("algsimpledec 3d", ()->#algsimpledec(al)[2]==2); do("alg_decomposition 3d", ()->dec=algsimpledec(al); dec[1]==0 && #dec[2]==2 && #algcenter(dec[2][1])==1 && #algcenter(dec[2][2])==1 && (algdim(dec[2][1],1)==4 || algdim(dec[2][2],1)==4)); do("subalg M2(F3)", ()->sal=algsubalg(al,[1,0,0,0; 0,1,0,0; 0,0,1,0; 0,0,0,1;\ 0,0,0,0]); algisassociative(sal[1]) && algradical(sal[1])==0 &&\ #algsimpledec(sal[1])[2]==1); do("iscommutative 3d", ()->algiscommutative(al)==0); do("issemisimple 3d", ()->algissemisimple(al)==1); do("issimple 3d", ()->algissimple(al)==0); do("issimple,1 3d", ()->algissimple(al,1)==0); }); all() = gusuite("all", ()->{ get(); operations(); tensor(); gw(); moreoperations(); tablealg(); }); all(); nf = nfinit(y^2-2); al = alginit(nf, [-3,-5], x,3); print("maxorder assoc: ", algisassociative(al[9])); al0 = alginit(nf, [-3,-5], x,0); print("natorder assoc: ", algisassociative(al0[9])); un = [1,0]~; ii = [x,0]~; jj = [0,1]~; kk = algmul(al,ii,jj); print("spl(1): ", algtomatrix(al,un)==matid(2)); print("spl(i): ", algtomatrix(al,ii)==[x,0;0,-x]); print("spl(j): ", algtomatrix(al,jj)==[0,-5;1,0]); print("spl(k): ", algtomatrix(al,kk)==[0,-5*x;-x,0]); print("spl(basis(1)): ", algtomatrix(al,algalgtobasis(al,un))==matid(2)); print("spl(basis(i)): ", algtomatrix(al,algalgtobasis(al,ii))==[x,0;0,-x]); print("spl(basis(j)): ", algtomatrix(al,algalgtobasis(al,jj))==[0,-5;1,0]); print("spl(basis(k)): ", algtomatrix(al,algalgtobasis(al,kk))==[0,-5*x;-x,0]); a = y+1; b = 1/3; c = -y/5+1/2; print("spl(a*1): ", algtomatrix(al,a*un)==a*matid(2)); print("spl(a*i): ", algtomatrix(al,a*ii)==a*[x,0;0,-x]); print("spl(a*j): ", algtomatrix(al,a*jj)==a*[0,-5;1,0]); print("spl(a*k): ", algtomatrix(al,a*kk)==a*[0,-5*x;-x,0]); print("spl(b*1): ", algtomatrix(al,b*un)==b*matid(2)); print("spl(b*i): ", algtomatrix(al,b*ii)==b*[x,0;0,-x]); print("spl(b*j): ", algtomatrix(al,b*jj)==b*[0,-5;1,0]); print("spl(b*k): ", algtomatrix(al,b*kk)==b*[0,-5*x;-x,0]); ord = algbasis(al); invord = alginvbasis(al); setrand(1); x1 = algrandom(al,1); ax1 = algbasistoalg(al,x1); nx1 = algalgtobasis(al0,ax1); print("nattomax 1: ", nx1==ord*x1); setrand(2); x2 = algrandom(al,1); ax2 = algbasistoalg(al,x2); nx2 = algalgtobasis(al0,ax2); print("nattomax 2: ", nx2==ord*x2); print("ord*invord=id: ", ord*invord == matid(8)); print("spl additive: ", algtomatrix(al,x1) + algtomatrix(al,x2) == algtomatrix(al, algadd(al,x1,x2))); print("spl multiplicative: ", algtomatrix(al,x1) * algtomatrix(al,x2) == algtomatrix(al, algmul(al,x1,x2))); print("changebasis bug 1: ", algalgtobasis(al,algbasistoalg(al,algmul(al,x1,x2)))==algmul(al,x1,x2)); print("changebasis bug 2: ", algalgtobasis(al0,algmul(al0,ax1,ax2)) == algmul(al0,nx1,nx2)); print("changebasis bug 3: ", invord*algmul(al0,nx1,nx2) == algmul(al,x1,x2)); print("changebasis bug 4: ", algtomatrix(al,x1,1) == invord*algtomatrix(al0,nx1,1)*ord); print("algtableinit segfault bug: "); alt = algtableinit(al[9]); print(alt != 'alt); print("center of CSA: ", #algcenter(alt)==2); print("radical of CSA: ", algradical(alt)==0); print("decomposition of CSA: ", #algsimpledec(alt)[2]==1); dec = algsimpledec(alt); {print("alg_decomposition of CSA: ", #dec==2 && dec[1]==0 && #dec[2]==1 && #algcenter(dec[2][1])==2 && algdim(dec[2][1],1)==8);} print("alsimple bug"); mt = [matid(3), [0,0,0;1,1,0;0,0,0], [0,0,0;0,0,0;1,0,1]]; A = algtableinit(mt); algissimple(A) print("tests for al_CSA: "); T = y^3-y+1; nf = nfinit(T); m_i = [0,-1,0, 0;\ 1, 0,0, 0;\ 0, 0,0,-1;\ 0, 0,1, 0]; m_j = [0, 0,-1,0;\ 0, 0, 0,1;\ 1, 0, 0,0;\ 0,-1, 0,0]; m_k = [0, 0, 0, -1;\ 0, 0,-1, 0;\ 0, 1, 0, 0;\ 1, 0, 0, 0]; mt = [matid(4), m_i, m_j, m_k]; print(algisassociative(mt)); al = alginit(nf, mt, 'x); print(al != 0); print("algebra:"); print("csa getcenter: ", algcenter(al) == nf); print("csa getsplitting: ", algsplittingfield(al) != 0); print("getrelmultable: ", algrelmultable(al) == mt); print("getsplittingdata:"); print(#algsplittingdata(al) == 3); print(#algsplittingdata(al)[1] == 12); print(#algsplittingdata(al)[2] == 2); print(#algsplittingdata(al)[3][1,] == 12); print(#algsplittingdata(al)[3][,1] == 2); print(al[3][3]*al[3][2][,1] == [1,0]~); print(al[3][3]*al[3][2][,2] == [0,1]~); polabs = al[1][12][1].pol; for(i=1,10,\ print(al[3][3]*algmul(al, al[3][2][,1], algpow(al,al[3][1],i)) == [Mod(x^i,polabs),0]~);\ print(al[3][3]*algmul(al, al[3][2][,2], algpow(al,al[3][1],i)) == [0,Mod(x,polabs)^i]~)\ ); print("hasse invariants:"); do("hassei csa", () -> alghassei(al) == 0); do("hassef cas", () -> alghassef(al) == 0); do("hasse csa", () -> alghasse(al,1) == 0); print("csa splitting pol: ", poldegree(al[1][12][1].pol) == 6); print("csa basis: ", matsize(algbasis(al)) == [12,12]); print("csa invbasis: ", matsize(alginvbasis(al)) == [12,12]); print("csa absdim: ", #algmultable(al) == algdim(al,1)); print("csa char: ", algchar(al) == 0); print("csa deg: ", algdegree(al) == 2); print("csa dim: ", algdim(al) == 4); print("csa absdim: ", algdim(al,1) == 12); print("csa type: ", algtype(al) == 2); \\2==al_CSA print("csa iscommutative: ", algiscommutative(al)==0); print("csa issemisimple: ", algissemisimple(al)==1); print("elements:"); a = [0, Mod(y,T), 0, 0]~; b = [0, -1, Mod(2*y^2,T), 0]~; c = [Mod(1-y+2*y^2,T), 3, 0, Mod(-3*y,T)]~; mynorm(aa) = sum(i=1,4,aa[i]^2); algbasistoalg(al,a) algalgtobasis(al,[1,2,3,4,5,6,7,8,9,10,11,12]~) print("csa add: ", algadd(al,a,b) == a+b); print("csa neg: ", algneg(al,a) == -a); print("csa neg 2: ", algneg(al,b) == -b); print("csa sub: ", algsub(al,a,b) == a-b); print("csa mul: ", algmul(al,a,b) == [Mod(y,T), 0, 0, Mod(2*y-2,T)]~); print("csa mul 2: ", algmul(al,b,a) == [Mod(y,T), 0, 0, Mod(2-2*y,T)]~); print("csa sqr: ", algsqr(al,a) == [Mod(-y^2,T),0,0,0]~); print("csa sqr 2: ", algsqr(al,b) == [Mod(-1-4*y^4,T),0,0,0]~); print("csa mt: ", algrelmultable(al)*b == -m_i + Mod(2*y^2,T)*m_j); print("csa inv: ", alginv(al,a) == -1/y^2*a); print("csa inv 2: ", alginv(al,b) == -1/Mod(1+4*y^4,T)*b); print("csa divl: ", algdivl(al,1+a+b,b) == algmul(al, alginv(al, 1+a+b), b)); print("csa pow: ", algpow(al, a, 5) == Mod(y^4,T)*a); aa = algalgtobasis(al, a); bb = algalgtobasis(al, b); cc = algalgtobasis(al, c); print("csa mul 3: ", algmul(al,aa,b) == algalgtobasis(al,algmul(al,a,b))); print("csa mul 4: ", algmul(al,a,bb) == algalgtobasis(al,algmul(al,a,b))); print("csa pow 2: ", algpow(al,aa,13) == algalgtobasis(al,algpow(al,a,13))); print("csa sub 2: ", algsub(al,aa,b) == algalgtobasis(al,algsub(al,a,b))); print("csa sub 3: ", algsub(al,bb,a) == algalgtobasis(al,algsub(al,b,a))); print("csa inv 3: ", alginv(al,aa) == algalgtobasis(al,alginv(al,a))); print("csa inv 4: ", alginv(al,bb) == algalgtobasis(al,alginv(al,b))); print("csa inv 5: ", alginv(al,algadd(al,a,bb)) == algalgtobasis(al,alginv(al,algadd(al,a,b)))); print("csa trace: ", algtrace(al,cc) == 2*c[1]); print("csa trace 2: ", algtrace(al,c) == 2*c[1]); print("csa abs trace: ", algtrace(al,cc,1) == 4*trace(Mod(c[1],T))); print("csa abs trace 2: ", algtrace(al,c,1) == 4*trace(Mod(c[1],T))); D = 12; flag = 1; for(i=1, D,\ for(j=i, D,\ ei = matid(D)[,i];\ ej = matid(D)[,j];\ flag = flag && (algtomatrix(al,ei)*algtomatrix(al,ej) == algtomatrix(al, algmul(al, ei, ej)));\ flag = flag && (algtomatrix(al,ei)+algtomatrix(al,ej) == algtomatrix(al, algadd(al, ei, ej)))\ )); print(flag); print("testcharpol"); testcharpol(al,elt) = print(algcharpoly(al,elt)==x^2-algtrace(al,elt)*x+mynorm(elt)); testcharpol(al,a); testcharpol(al,b); testcharpol(al,c); print("testcharpol2"); testcharpol2(al,elt) = print(algcharpoly(al,elt)==x^2-algtrace(al,elt)*x+mynorm(algbasistoalg(al,elt))); testcharpol2(al,aa); testcharpol2(al,bb); testcharpol2(al,cc); print("testnorm"); testnorm(al,elt) = print(algnorm(al,elt) == mynorm(elt)); testnorm(al,a); testnorm(al,b); testnorm(al,c); print("testnorm2"); testnorm2(al,elt) = print(algnorm(al,elt) == mynorm(algbasistoalg(al,elt))); testnorm2(al,aa); testnorm2(al,bb); testnorm2(al,cc); doubleindex(N,i,j) = (i-1)*N+j; matrixringmt(N) = { my(mt = [Mat([Col(0,N^2) | i<-[1..N^2]]) | j<-[1..N^2]], B, Bi, mt2=Vec(0,N^2)); for(i=1,N, for(j=1,N, for(k=1,N, mt[doubleindex(N,i,j)][doubleindex(N,i,k),doubleindex(N,j,k)] = 1 ) ) ); B = matid(N^2); for(i=1, N, B[doubleindex(N,i,i),1]=1); Bi = B^(-1); mt2[1] = matid(N^2); for(i=2,N^2, mt2[i] = Bi*mt[i]*B); mt2; } print("examples from docu"); setrand(1); algtype([]) A = alginit(nfinit(y),[-1,1]); algadd(A,[1,0]~,[1,2]~) algisinv(A,[-1,1]~) algisinv(A,[1,2]~,&ix) ix algisdivl(A,[x+2,-x-2]~,[x,1]~) algisdivl(A,[x+2,-x-2]~,[-x,x]~) algisdivl(A,[x+2,-x-2]~,[-x,x]~,&z) z A = alginit(nfinit(y^2-5),[2,y]); algalgtobasis(A,[y,1]~) algbasistoalg(A,algalgtobasis(A,[y,1]~)) algbasistoalg(A,[0,1,0,0,2,-3,0,0]~) algalgtobasis(A,algbasistoalg(A,[0,1,0,0,2,-3,0,0]~)) mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]]; A = algtableinit(mt,2); e = [0,1,0]~; one = [1,0,0]~; e2 = algsub(A,one,e); algcentralproj(A,[e,e2]) algprimesubalg(A) algquotient(A,[0;1;0]) algsubalg(A,[1,0; 0,0; 0,1]) algiscommutative(A) algissimple(A) mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]]; A = algtableinit(mt); algiscommutative(A) algissemisimple(A) algissimple(A) algissimple(A,1) nf = nfinit(y^2-5); A = alginit(nf, [-3,1-y]); alghassef(A) algdegree(A)^algdim(A,1)*nf.disc^algdim(A)*idealnorm(nf,alghassef(A)[1][2])^algdegree(A) algdisc(A) nf = nfinit(y^3-y+1); A = alginit(nf, [-1,-1]); algdim(A,1) algcenter(A).pol algdegree(A) algdim(A) nf = nfinit(y); p = idealprimedec(nf,7)[1]; p2 = idealprimedec(nf,11)[1]; A = alginit(nf,[3,[[p,p2],[1/3,2/3]],[0]]); algaut(A) algb(A) mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]]; A = algtableinit(mt,13); algchar(A) algtype(A) nf = nfinit(y^2-5); A = alginit(nf, [-1,2*y-1]); alghassef(A) A = alginit(nf, [-1,y]); alghassei(A) alghasse(A, 1) alghasse(A, 2) alghasse(A, idealprimedec(nf,2)[1]) alghasse(A, idealprimedec(nf,5)[1]) algindex(A, 1) algindex(A, 2) algindex(A, idealprimedec(nf,2)[1]) algindex(A, idealprimedec(nf,5)[1]) algindex(A) algisdivision(A, 1) algisdivision(A, 2) algisdivision(A, idealprimedec(nf,2)[1]) algisdivision(A, idealprimedec(nf,5)[1]) algisdivision(A) algissplit(A, 1) algissplit(A, 2) algissplit(A, idealprimedec(nf,2)[1]) algissplit(A, idealprimedec(nf,5)[1]) algissplit(A) algisramified(A, 1) algisramified(A, 2) algisramified(A, idealprimedec(nf,2)[1]) algisramified(A, idealprimedec(nf,5)[1]) algisramified(A) algramifiedplaces(A) nf = nfinit(y^2-5); pr = idealprimedec(nf,13)[1]; pol = nfgrunwaldwang(nf, [pr], [2], [0,-1], 'x) A = alginit(nfinit(y), [-1,-1]); alginvbasis(A) algbasis(A) algmultable(A) alginv(A,[1,1,0,0]~) algmul(A,[1,1,0,0]~,[0,0,2,1]~) algtomatrix(A,[0,1,0,0]~,1) algtomatrix(A,[0,x]~,1) algneg(A,[1,1,0,0]~) algtomatrix(A,[0,0,0,2]~) algpow(A,[1,1,0,0]~,7) algsub(A,[1,1,0,0]~,[1,0,1,0]~) algtrace(A,[5,0,0,1]~) algtrace(A,[5,0,0,1]~,1) algtype(A) nf = nfinit(y^3-5); a = y; b = y^2; mt = qamt(a,b); A = alginit(nf,mt,'x); algrelmultable(A) algsplittingfield(A).pol algsplittingdata(A) algtype(A) mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]]; A = algtableinit(mt,19); algnorm(A,[0,-2,3]~) A = algtableinit(mt); algnorm(A,[0,-2,3]~) m_i=[0,-1,0,0;1,0,0,0;0,0,0,-1;0,0,1,0]; m_j=[0,0,-1,0;0,0,0,1;1,0,0,0;0,-1,0,0]; m_k=[0,0,0,-1;0,0,-1,0;0,1,0,0;1,0,0,0]; mt = [matid(4), m_i, m_j, m_k]; A = algtableinit(mt); algissemisimple(A) algissimple(A) algissimple(A,1) \\end examples print("matrices over algebras"); scal8(a) = vector(8,i,if(i==1,a,0))~; setrand(1); nf = nfinit(y^2-5); al = alginit(nf, [-1,-7]); setrand(1); M1 = [algrandom(al,2),algrandom(al,2);algrandom(al,2),algrandom(al,2)] M2 = [algrandom(al,2),algrandom(al,2);algrandom(al,2),algrandom(al,2)] print("mul alM: ", algmul(al,M1,M2)); a = [1,2,3,4,5,6,7,8]~; M = Mat([0,0]); M[1,1] = a; M[1,2] = a; algmul(al, M, [a,a,a;a,a,a]); print("sqr alM: ", algsqr(al,M1) == algmul(al,M1,M1)); print("divl alM: ", algmul(al,M1,algdivl(al,M1,M2)) == M2); print("divr alM: ", algmul(al,algdivr(al,M1,M2),M2) == M1); print("isinv alM: ", algisinv(al, M1)); print("isinv alM 2: ", algisinv(al, M2)); un = [1,0,0,0,0,0,0,0]~; zero = [0,0,0,0,0,0,0,0]~; id = [un,zero;zero,un]; {print("inv alM: ", algmul(al,M1,alginv(al,M1)) == id && algmul(al,alginv(al,M1),M1) == id);} {print("inv alM 2: ", algmul(al,M2,alginv(al,M2)) == id && algmul(al,alginv(al,M2),M2) == id);} print("neg alM: ", algneg(al,M1) == -M1); print("sub alM: ", algsub(al,M1,M2) == M1-M2); print("add alM: ", algadd(al,M1,M2) == M1+M2); print("algtobasis basistoalg alM 1: ", algalgtobasis(al, algbasistoalg(al, M1)) == M1); print("algtobasis basistoalg alM 2: ", algalgtobasis(al, algbasistoalg(al, M2)) == M2); print("algleftmultable add alM: ", algtomatrix(al, M1,1)+algtomatrix(al,M2,1) == algtomatrix(al, algadd(al, M1, M2),1)); print("algleftmultable mul alM: ", algtomatrix(al, M1,1)*algtomatrix(al,M2,1) == algtomatrix(al, algmul(al, M1, M2),1)); {print("algleftmultable sqr alM: ", algtomatrix(al, M1,1)^2 == algtomatrix(al, algsqr(al, M1),1));} print("algsplitm add alM: ", algtomatrix(al, M1)+algtomatrix(al,M2) == algtomatrix(al, algadd(al, M1, M2))); print("algsplitm mul alM: ", algtomatrix(al, M1)*algtomatrix(al,M2) == algtomatrix(al, algmul(al, M1, M2))); print("algsplitm sqr alM: ", algtomatrix(al, M1)^2 == algtomatrix(al, algsqr(al, M1))); print("algsplitm sqr alM 2: ", algtomatrix(al, M2)^2 == algtomatrix(al, algsqr(al, M2))); {print("algtrace alM: ", algtrace(al,M1) == algtrace(al,M1[1,1]) + algtrace(al,M1[2,2]));} {print("algtrace alM 2: ", algtrace(al,M2) == algtrace(al,M2[1,1]) + algtrace(al,M2[2,2]));} {print("algtrace abs alM: ", algtrace(al,M1,1) == 2*(algtrace(al,M1[1,1],1) + algtrace(al,M1[2,2],1)));} {print("algtrace abs alM 2: ", algtrace(al,M2,1) == 2*(algtrace(al,M2[1,1],1) + algtrace(al,M2[2,2],1)));} {print("algtrace prod alM: ", algtrace(al, algmul(al,M1,M2)) == algtrace(al, algmul(al,M2,M1)));} {print("algnorm alM: ", algnorm(al,algmul(al,M1,M2)) == algnorm(al,M1) * algnorm(al,M2));} {print("algnorm alM 2: ", algnorm(al,algmul(al,M2,M1)) == algnorm(al,M1) * algnorm(al,M2));} {print("algcharpoly alM: ", poldegree(algcharpoly(al,M1))==4 && polcoeff(algcharpoly(al,M1),3) == -algtrace(al,M1) && polcoeff(algcharpoly(al,M1),0) == algnorm(al,M1));} {print("algcharpoly alM 2: ", poldegree(algcharpoly(al,M2))==4 && polcoeff(algcharpoly(al,M2),3) == -algtrace(al,M2) && polcoeff(algcharpoly(al,M2),0) == algnorm(al,M2));} m = 15; n = -8; {print("pow alM: ", algmul(al, algpow(al,M1,m), algpow(al,M1,n)) == algpow(al,M1,m+n));} {print("pow alM 2: ", algmul(al, algpow(al,M2,m), algpow(al,M2,n)) == algpow(al,M2,m+n));} print("pow 0 alM: ", algpow(al,M1,0) == id); algbasistoalg(al,M1) algbasistoalg(al,M2) m1 = [1,2;3,4]; m2 = [5,6;7,8]; M1 = apply(scal8,m1); M2 = apply(scal8,m2); print("mul scalar alM: ", algmul(al,M1,M2) == apply(scal8,m1*m2)); m_i=[0,-1,0,0;1,0,0,0;0,0,0,-1;0,0,1,0]; m_j=[0,0,-1,0;0,0,0,1;1,0,0,0;0,-1,0,0]; m_k=[0,0,0,-1;0,0,-1,0;0,1,0,0;1,0,0,0]; mt = [matid(4), m_i, m_j, m_k]; al = algtableinit(mt); setrand(10); M1 = [algrandom(al,2),algrandom(al,2);algrandom(al,2),algrandom(al,2)] M2 = [algrandom(al,2),algrandom(al,2);algrandom(al,2),algrandom(al,2)] print("mul alM t: ", algmul(al,M1,M2)); print("sqr alM t: ", algsqr(al,M1) == algmul(al,M1,M1)); print("divl alM t: ", algmul(al,M1,algdivl(al,M1,M2)) == M2); print("divr alM t: ", algmul(al,algdivr(al,M1,M2),M2) == M1); print("isinv alM t: ", algisinv(al, M1)); print("isinv alM t 2: ", algisinv(al, M2)); un = [1,0,0,0]~; zero = [0,0,0,0]~; id = [un,zero;zero,un]; {print("inv alM t: ", algmul(al,M1,alginv(al,M1)) == id && algmul(al,alginv(al,M1),M1) == id);} {print("inv alM t 2: ", algmul(al,M2,alginv(al,M2)) == id && algmul(al,alginv(al,M2),M2) == id);} print("neg alM t: ", algneg(al,M1) == -M1); print("sub alM t: ", algsub(al,M1,M2) == M1-M2); print("add alM t: ", algadd(al,M1,M2) == M1+M2); print("algleftmultable add alM t: ", algtomatrix(al,M1,1) + algtomatrix(al,M2,1) == algtomatrix(al, algadd(al,M1,M2),1)); print("algleftmultable mul alM t: ", algtomatrix(al,M1,1) * algtomatrix(al,M2,1) == algtomatrix(al, algmul(al,M1,M2),1)); print("algleftmultable sqr alM t: ", algtomatrix(al,M1,1)^2 == algtomatrix(al,algsqr(al,M1),1)); {print("algtrace alM t: ", algtrace(al,M1) == 2*(algtrace(al,M1[1,1]) + algtrace(al,M1[2,2])));} {print("algtrace alM t 2: ", algtrace(al,M2) == 2*(algtrace(al,M2[1,1]) + algtrace(al,M2[2,2])));} {print("algtrace prod alM t: ", algtrace(al, algmul(al,M1,M2)) == algtrace(al, algmul(al,M2,M1)));} {print("algnorm alM t: ", algnorm(al,algmul(al,M1,M2)) == algnorm(al,M1) * algnorm(al,M2));} {print("algnorm alM t 2: ", algnorm(al,algmul(al,M2,M1)) == algnorm(al,M1) * algnorm(al,M2));} {print("algcharpoly alM t: ", poldegree(algcharpoly(al,M1))==16 && polcoeff(algcharpoly(al,M1),15) == -algtrace(al,M1) && polcoeff(algcharpoly(al,M1),0) == algnorm(al,M1));} {print("algcharpoly alM t 2: ", poldegree(algcharpoly(al,M2))==16 && polcoeff(algcharpoly(al,M2),15) == -algtrace(al,M2) && polcoeff(algcharpoly(al,M2),0) == algnorm(al,M2));} m = 32; n = -63; {print("pow alM t: ", algmul(al, algpow(al,M1,m), algpow(al,M1,n)) == algpow(al,M1,m+n));} {print("pow alM 2 t: ", algmul(al, algpow(al,M2,m), algpow(al,M2,n)) == algpow(al,M2,m+n));} print("pow 0 alM t: ", algpow(al,M2,0) == id); T = y^3-y+1; nf = nfinit(T); print("csa al2"); setrand(1); al2 = alginit(nf, matrixringmt(2), 'x); print("al2 contains nfabs: ", algsplittingfield(al2)[12][1] != 0); al2b = al2; al2b[1][12][1] = 0; \\ depends on 32/64bit print(al2b); print("csa al3"); al3 = alginit(nf, matrixringmt(3), 'x); print("al3 contains nfabs: ", algsplittingfield(al3)[12][1] != 0); \\limit cases print("trivial algebra over a quadratic field"); al = alginit(rnfinit(nfinit(y^2+1),x),[y,1]) a = [y]~ b = [1-2*y]~ c = [-3,1]~ algadd(al,a,b) algsub(al,c,a) algmul(al,a,b) algdivl(al,b,c) algdivr(al,c,b) alginv(al,a) algalgtobasis(al,b) algtomatrix(al,a) algtomatrix(al,a,1) algcharpoly(al,b) algtrace(al,c) algtrace(al,c,1) == trace(trace(algbasistoalg(al,c)[1])) algnorm(al,c) algiscommutative(al) algissemisimple(al) algissimple(al) alghasse(al,1) alghasse(al,idealprimedec(nfinit(y^2+1),2)[1]) algindex(al) algisdivision(al) algissplit(al) algisramified(al) algramifiedplaces(al) print("trivial algebra over Q"); al = alginit(rnfinit(nfinit(y),x),[y,1]) a = [-2]~ b = [1/3]~ c = [4/5]~ algadd(al,a,b) algsub(al,c,a) algmul(al,a,b) algdivl(al,b,c) algdivr(al,c,b) alginv(al,a) algalgtobasis(al,b) algtomatrix(al,a,1) algtomatrix(al,b) algcharpoly(al,b) algtrace(al,c) algtrace(al,c,1) algnorm(al,c) algiscommutative(al) algissemisimple(al) algissimple(al) alghasse(al,1) alghasse(al,idealprimedec(nfinit(y),2)[1]) algindex(al) algisdivision(al) algissplit(al) algisramified(al) algramifiedplaces(al) print("trivial CSA over Q"); al = alginit(nfinit(y), [Mat(1)]); algsqr(al,[Mod(3,y)]~) algsqr(al,[2]~) print("nontrivial CSA over Q"); {m_i = [0,-1,0, 0; 1, 0,0, 0; 0, 0,0,-1; 0, 0,1, 0]; m_j = [0, 0,-1,0; 0, 0, 0,1; 1, 0, 0,0; 0,-1, 0,0]; m_k = [0, 0, 0, -1; 0, 0,-1, 0; 0, 1, 0, 0; 1, 0, 0, 0]; mt = [matid(4), m_i, m_j, m_k];} al = alginit(nfinit(y), mt); algsqr(al,[Mod(3,y),Mod(2,y),Mod(1,y),Mod(2,y)]~) algsqr(al,[2,3,4,5]~) print("empty matrices"); al = alginit(nfinit(y), [-1,-1]); print("-v: ", algneg(al,[;]) == [;]); print("v^(-1): ", alginv(al,[;]) == [;]); print("v^n: ", algpow(al, [;], 13) == [;]); print("v^0: ", algpow(al, [;], 0) == [;]); print("mt(v)", algtomatrix(al, [;], 1) == [;]); print("spl(v)", algtomatrix(al, [;]) == [;]); print("trace(v): ", algtrace(al, [;]) == 0); print("trace abs(v): ", algtrace(al, [;], 1) == 0); print("norm(v): ", algnorm(al, [;]) == 1); print("charpoly(v): ", algcharpoly(al, [;]) == 1 && type(algcharpoly(al,[;])) == "t_POL"); print("v+v: ", algadd(al,[;],[;]) == [;]); print("v-v: ", algsub(al,[;],[;]) == [;]); print("v*v: ", algmul(al,[;],[;]) == [;]); print("v/v: ", algdivr(al,[;],[;]) == [;]); print("v\\v: ", algdivl(al,[;],[;]) == [;]); v1 = matrix(0,1); print("v*nv: ", algmul(al,v1,matid(1))==v1); print("v*v 2: ", algmul(al,[;],matrix(0,1))==matrix(0,1)); print("trace(v) char 2: ", algtrace(algtableinit([matid(1)],2), [;]) == 0); mt0 = [Mat([1])]; almt0 = algtableinit(mt0,0) a = [12]~ b = [-1/7]~ algadd(almt0,a,b) algsub(almt0,a,b) algmul(almt0,a,b) algneg(almt0,a) alginv(almt0,a) algsqr(almt0,b) algdivl(almt0,a,b) algtrace(almt0,a) algtrace(almt0,a,1) algnorm(almt0,b) algcharpoly(almt0,a) algtomatrix(almt0,b,1) algpow(almt0,a,0) algiscommutative(almt0) algissemisimple(almt0) algissimple(almt0) algisdivision(almt0) print("trivial tensor product"); al1 = alginit(nfinit(y),1); al2 = alginit(nfinit(y),2); print(algtensor(al1,al2)==al2); print(algtensor(al2,al1)==al2); print("splitting a nasty commutative algebra"); {mt = [matid(8), [0,2,0,0,0,0,0,0; 1,0,0,0,0,0,0,0; 0,0,0,2,0,0,0,0; 0,0,1,0,0,0,0,0; 0,0,0,0,0,2,0,0; 0,0,0,0,1,0,0,0; 0,0,0,0,0,0,0,2; 0,0,0,0,0,0,1,0], [0,0,3,0,0,0,0,0; 0,0,0,3,0,0,0,0; 1,0,0,0,0,0,0,0; 0,1,0,0,0,0,0,0; 0,0,0,0,0,0,3,0; 0,0,0,0,0,0,0,3; 0,0,0,0,1,0,0,0; 0,0,0,0,0,1,0,0], [0,0,0,6,0,0,0,0; 0,0,3,0,0,0,0,0; 0,2,0,0,0,0,0,0; 1,0,0,0,0,0,0,0; 0,0,0,0,0,0,0,6; 0,0,0,0,0,0,3,0; 0,0,0,0,0,2,0,0; 0,0,0,0,1,0,0,0], [0,0,0,0,5,0,0,0; 0,0,0,0,0,5,0,0; 0,0,0,0,0,0,5,0; 0,0,0,0,0,0,0,5; 1,0,0,0,0,0,0,0; 0,1,0,0,0,0,0,0; 0,0,1,0,0,0,0,0; 0,0,0,1,0,0,0,0], [0,0,0,0,0,10,0, 0; 0,0,0,0,5, 0,0, 0; 0,0,0,0,0, 0,0,10; 0,0,0,0,0, 0,5, 0; 0,2,0,0,0, 0,0, 0; 1,0,0,0,0, 0,0, 0; 0,0,0,2,0, 0,0, 0; 0,0,1,0,0, 0,0, 0], [0,0,0,0,0,0,15, 0; 0,0,0,0,0,0, 0,15; 0,0,0,0,5,0, 0, 0; 0,0,0,0,0,5, 0, 0; 0,0,3,0,0,0, 0, 0; 0,0,0,3,0,0, 0, 0; 1,0,0,0,0,0, 0, 0; 0,1,0,0,0,0, 0, 0], [0,0,0,0,0, 0, 0,30; 0,0,0,0,0, 0,15, 0; 0,0,0,0,0,10, 0, 0; 0,0,0,0,5, 0, 0, 0; 0,0,0,6,0, 0, 0, 0; 0,0,3,0,0, 0, 0, 0; 0,2,0,0,0, 0, 0, 0; 1,0,0,0,0, 0, 0, 0] ];} {chg = [1, 0,0,0,0,0, 0, 0; 0, 1,0,0,0,0, 0, 0; 0,-2,1,1,0,0, 0, 0; 0,-1,0,1,0,0, 0, 0; 0, 0,0,0,1,1,-2, 0; 0, 0,0,0,0,1, 0,-1; 0, 0,0,0,0,0, 1, 0; 0, 0,0,0,0,0, 0, 1];} chgi = chg^(-1); mt2 = vector(8,j,chgi*sum(i=1,8,chg[i,j]*mt[i])*chg); algisassociative(mt2) al = algtableinit(mt2); algiscommutative(al) algissemisimple(al) setrand(9991); algissimple(al,1) print("non associative algebra"); mt = [matid(3), [0,2,3;1,4,5;0,6,7], [0,8,9;0,10,11;1,12,13]]; algisassociative(mt) print("csa without maximal order"); alginit(nfinit(y), [matid(1)], 'x, 0); print("simplify bug #1671"); test(str,al)={ my(sal = simplify(al), x, y); setrand(1); print("testing simplify: ", str); print(algtype(al) == algtype(sal)); print(algdim(al) == algdim(sal)); setrand(11); x = algrandom(al,3); y = algrandom(al,10); print(algsqr(al,x) == algsqr(sal,x)); print(algtomatrix(al,x) == algtomatrix(sal,x)); print(algcharpoly(al,x) == algcharpoly(sal,x)); print(algnorm(al,x) == algnorm(sal,x)); print(algtomatrix(al,x,1) == algtomatrix(sal,x,1)); print(algtrace(al,x) == algtrace(sal,x)); print(algtrace(al,x,1) == algtrace(sal,x,1)); print(alginv(al,x) == alginv(sal,x)); print(algpow(al,x,42) == algpow(sal,x,42)); print(algmul(al,x,y) == algmul(sal,x,y)); print(algdivl(al,x,y) == algdivl(sal,x,y)); print(algpoleval(al,algcharpoly(al,x),x) == 0); print(algpoleval(al,algcharpoly(al,y),y) == 0); print(algbasistoalg(al,x) == algbasistoalg(sal,x)); x = algbasistoalg(al,x); print(algbasistoalg(al,y) == algbasistoalg(sal,y)); y = algbasistoalg(al,y); print(algsqr(al,x) == algsqr(sal,x)); print(algtomatrix(al,x) == algtomatrix(sal,x)); print(algcharpoly(al,x) == algcharpoly(sal,x)); print(algnorm(al,x) == algnorm(sal,x)); print(algtomatrix(al,x,1) == algtomatrix(sal,x,1)); print(algtrace(al,x) == algtrace(sal,x)); print(algtrace(al,x,1) == algtrace(sal,x,1)); print(alginv(al,x) == alginv(sal,x)); print(algpow(al,x,42) == algpow(sal,x,42)); print(algmul(al,x,y) == algmul(sal,x,y)); print(algdivl(al,x,y) == algdivl(sal,x,y)); print(algadd(al,x,y) == algadd(al,x,simplify(y))); print(algmul(al,x,y) == algmul(al,x,simplify(y))); print(algmul(al,x,y) == algmul(al,simplify(x),simplify(y))); }; test("degree 1 cyclic over Q", alginit(nfinit(y),1)); test("degree 1 cyclic over Q(i)", alginit(nfinit(y^2+1),1)); test("degree 1 csa over Q", alginit(nfinit(y), [matid(1)])); test("degree 1 csa over Q(i)", alginit(nfinit(y^2+1), [matid(1)])); test("quatalg over Q(s5)", alginit(nfinit(y^2-5), [-2,-3])); {m_i = [0,-1,0, 0; 1, 0,0, 0; 0, 0,0,-1; 0, 0,1, 0]; m_j = [0, 0,-1,0; 0, 0, 0,1; 1, 0, 0,0; 0,-1, 0,0]; m_k = [0, 0, 0, -1; 0, 0,-1, 0; 0, 1, 0, 0; 1, 0, 0, 0]; mt = [matid(4), m_i, m_j, m_k];} test("quatalg csa over Q", alginit(nfinit(y), mt)); m = matcompanion(x^4+1); mt = [m^i | i <- [0..3]]; al = algtableinit(mt); B = [1,0;0,0;0,1/2;0,0] al2 = algsubalg(al,B); print("algpoleval relative poly in basis form"); pol = y^2-2; nf = nfinit(pol); a = 1+y; b = -3-y; al = alginit(nf, [a,b]); ii = algalgtobasis(al,[x,0]~); algpoleval(al, x^2-a, ii) == 0 jj = algalgtobasis(al,[0,1]~); algpoleval(al, x^2-b, jj) == 0 kk = algalgtobasis(al,[0,-x]~); algpoleval(al, x^2+Mod(a,pol)*b, kk) == 0 w = algrandom(al,10); T = x^3 + 7*x^2 - y^5*x + (8-2*y); al = alginit(nf, qamt(a,b)); ii = algalgtobasis(al,[0,1,0,0]~); algpoleval(al, x^2-a, ii) == 0 jj = algalgtobasis(al,[0,0,1,0]~); algpoleval(al, x^2-b, jj) == 0 kk = algalgtobasis(al,[0,0,0,1]~); algpoleval(al, x^2+Mod(a,pol)*b, kk) == 0 print("doc algpoleval"); nf = nfinit(y^2-5); al = alginit(nf,[y,-1]); b = [1..8]~; pol = algcharpoly(al,b,,1); \\absolute characteristic polynomial algpoleval(al,pol,b)==0 mb = algtomatrix(al,b,1); algpoleval(al,pol,[b,mb])==0 pol = algcharpoly(al,b); \\reduced characteristic polynomial algpoleval(al,pol,b) == 0 exponent(algpoleval(,polcyclo(8),[1,0,0,1]~/sqrt(2))) < -100 print("splitting field bug for CSA"); setrand(1); pol = y^2-2; nf = nfinit(pol); a = (3+y)^2; b = -y-7; al = alginit(nf, qamt(a,b)); ii = [0,1,0,0]~; algnorm(al,ii) == -Mod(a,pol) rnf = algsplittingfield(al); spld = algsplittingdata(al); t = spld[1]; algpoleval(al, minpoly(rnfeltabstorel(rnf,x)), t) == 0 \\ bad inputs a = [12]~; b = [-1/7]~; m_i = [0,-1,0, 0;\ 1, 0,0, 0;\ 0, 0,0,-1;\ 0, 0,1, 0]; m_j = [0, 0,-1,0;\ 0, 0, 0,1;\ 1, 0, 0,0;\ 0,-1, 0,0]; m_k = [0, 0, 0, -1;\ 0, 0,-1, 0;\ 0, 1, 0, 0;\ 1, 0, 0, 0]; mt = [matid(4), m_i, m_j, m_k]; almt = algtableinit(mt,0); algsplittingfield(almt); algdegree(almt); alghassei(almt); alghassef(almt); algrandom(1,1) algrandom(almt,I) algtype(1) algdim([1,[1],0,0,0,0,0,0,0,0]) algdim([1,[1],0,0,0,0,0,0,0,0],1) algtensor(al,al2) algtensor(al2,al) algtensor(1,z,1) algisassociative([1],0) algisassociative([[1,0;0,2],[0,0;0,0]]) \\valid input algmul(almt,a,b) algtomatrix(almt,a,1) alginv(almt,a) algalgtobasis(almt,a) algbasistoalg(almt,[0,0,0,0]~) algpoleval(almt,1,a) zero = [0,0,0,0]~; m = Mat([1,1]); m[1,1]=zero; m[1,2]=zero; algadd(almt, [zero;zero], m) algadd(almt, [zero;zero;zero], [zero;zero]); algsub(almt, [zero;zero], m) algsub(almt, [zero;zero;zero], [zero;zero]); algmul(almt, m, [zero;zero;zero]); algsqr(almt, [zero;zero]); algdivl(almt, m, zero); algdivl(almt, Mat([[zero]~]), [zero,zero;zero,zero]); algdivl(almt, m, m); alginv(almt, m); algtomatrix(almt,m,1); algpow(almt, m, 3); algtrace(almt, m); algcharpoly(almt, m); algcharpoly(alginit(nfinit(y),[-1,-1]), m); algnorm(almt, m); algnorm(alginit(nfinit(y),[-1,-1]), m); alginit(nfinit(y),[2,[[],[]],[x]]) alginit(nfinit(y),[2,[],[1,1]]) alginit(nfinit(y),[2,[[],[]],Vecsmall([1])]) alginit(y,[2,[[],[]],[1]]) alginit(nfinit(y), y) alginit(nfinit(y), [1,2,3,4]) algtableinit(mt,y); alginit(nfinit(y^2+1),-3); alginit(nfinit(x^2+1),3); highvar = varhigher("highvar"); alginit(nfinit(highvar^2+1),3); al = alginit(nfinit(y^2-2),[-1,-1]); algrandom(al,-10) al = alginit(nfinit(y^2-2),[-1,-1]); algrelmultable(al); algsplittingdata(al); alghasse(almt, 1); algindex(almt, 1); algisdivision(almt); algissplit(almt); algisramified(almt); algramifiedplaces(almt); alghasse(al); alghasse(al, -1); alghasse(al, 3); alghasse(al, 2^100); alghasse(al, []); alghasse(al, 1/3); algtableinit([matid(2), [0,1/2;1,0]]); Q = nfinit(y); alginit(Q, [matid(2), [0,1/2;1,0]]); alginit(Q, [-1/2, -1]); alginit(Q, [-1, -1/2]); alginit(rnfinit(Q, x^2+1), [-x,-1/2]); algsqr([0,0,0,0,0,0,0,0,0,0,0],[]~); algsqr([0,0,0,0,0,0,0,0,[],0,0],[]~); algsqr([0,0,0,0,0,0,0,0,[0],0,0],[]~); algsqr([0,0,0,0,0,0,0,0,[[;]],0,0],[]~); algsqr([[],0,0,0,0,0,0,0,[[;]],0,0],[]~); algsqr([[],[0],0,0,0,0,0,0,[[;]],0,0],[]~); algdim([[],[0],0,0,0,0,0,0,[[;]],0,0]); algdegree([[],[0],0,0,0,0,0,0,[[;]],0,0]); algdegree([rnfinit(nfinit(y),x),[[]],0,0,0,0,0,0,[[;]],0,0]); algcenter([rnfinit(nfinit(y),x),[[]],0,0,0,0,0,0,[[;]],0,0]); algcentralproj(almt,0); algcentralproj(almt,[zero,zero]); algsubalg(almt,0); algisassociative([]); algisassociative([matid(2),Mat([1,1])]); algisassociative([[1,2;3,4],matid(2)]) \\valid input algisassociative([matid(1)],[]); algsqr(algtableinit([matid(1)]),[1,2]~); algsqr(al,vector(691)~); algsqr(al,[1,2,3,4,5,6,7,f^2]~); algsqr(al,[f^3,[]]~); algmul(al,[;],[1,2]~); algdivl(al,[;],matid(1)); algdivl(al,matid(1),matrix(1,2)); algdivl(al,matrix(0,3),[;]); algdivl(al,[;],matrix(0,3)); algdivl(al,matrix(1,1),[;]); alginv(al,[0,0]~); al0mt = algtableinit([matid(1)]); algalgtobasis(al0mt,[1]~); algbasistoalg(al0mt,[1]~); nfgrunwaldwang(nfinit(y),0,[],[],'x); nfgrunwaldwang(nfinit(y),[2],'x-'x,[1]); alginit(rnfinit(nfinit(y),x),0); alginit(rnfinit(nfinit(y),x),[1,2,3,4]); alginit(nfinit(y), [matid(2),matid(2)]); alginit(nfinit(y), [matid(2),[0,1;1,0]]); nfgrunwaldwang(nfinit(y), 0, [], [0]); nfgrunwaldwang(nfinit(y), [2], [], [0]); nfgrunwaldwang(nfinit(y), [2], [2], []); nfgrunwaldwang(nfinit(y), [2], [6], [0]); nfgrunwaldwang(nfinit(y), [2,3], [2,3], [0]); nfgrunwaldwang(nfinit(y), [2], [3], [-1]); nfgrunwaldwang(nfinit(y), [[]~], [3], [-1]); nfgrunwaldwang(nfinit(y), [2], [9], [0]); mt=[matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]]; A=algtableinit(mt,2); algdegree(A) algsub(A,1,1) algadd(A,1,1) algneg(A,1) algmul(A,1,1) algsqr(A,1) algdivl(A,1,1) algdivr(A,1,1) alginv(A,1) a='a; K=nfinit(a);PR=idealprimedec(K,2);A=alginit(K,[3,[PR,[1]],[-1]]); K=nfinit(a);P2=idealprimedec(K,2);P3=idealprimedec(K,3);A=alginit(K,[3,[concat(P2,P3),[1/3,-2/3]],[1/3]]); algtensor(alginit(nfinit(y),2),alginit(nfinit(y^2+1),3)); algtensor(alginit(nfinit(y),2),alginit(nfinit(y),2)); nf = nfinit(y); p2 = idealprimedec(nf,2)[1]; p3 = idealprimedec(nf,3)[1]; \\alginit(nf, [2, [[p2,p3],[1/2,1/2]], [0]]); alginit(nf, [2, [[p2,p2],[1/2,1/2]], [0]]); alginit(nf, [2, [[p2,p3],[1/2,1/2]], [0,0]]); alginit(nf, [2, [[p2,p3],[1/2,1/2],0], [0]]); alginit(nf, [2, [0,[1/2,1/2]], [0]]); alginit(nf, [2, [[p2,p3],0], [0]]); alginit(nf, [2, [[p2,p3],[1/2,1/2,0]], [0]]); alginit(nf, [2, [[p2,p3],[1/2,1/2]], [1/3]]); al = alginit(nfinit(y),[-1,-1]); setrand(23); a = algrandom(al,2); algcharpoly(al,a,'z); al = alginit(nfinit(y^2+7), [-1,-1]); algcharpoly(al,[1,2,3]~); algindex(1, 1) al = alginit(nfinit(y), [Mat(1)]); algsqr(al,[Mod(1,y),Mod(2,y)]~) {m_i = [0,-1,0, 0; 1, 0,0, 0; 0, 0,0,-1; 0, 0,1, 0]; m_j = [0, 0,-1,0; 0, 0, 0,1; 1, 0, 0,0; 0,-1, 0,0]; m_k = [0, 0, 0, -1; 0, 0,-1, 0; 0, 1, 0, 0; 1, 0, 0, 0]; mt = [matid(4), m_i, m_j, m_k];} al = alginit(nfinit(y), mt); algsqr(al,[Mod(1,y),Mod(2,y)]~) alfail = alginit(nf, [0,0], 'x); algb(al); algaut(al); algtableinit([Mat(1)],1) algtableinit([Mat(1)],4) al = alginit(nfinit(y),[-1,-1]); algpoleval(al,x+1,"toto") algpoleval(al,x+1,[1,2,3]) algpoleval(al,x+1,[1,2]) a = [1..4]~; b = [5..8]~; mb = algtomatrix(al,b,1); algpoleval(al,x+1,[a,mb]); algpoleval(al,x+1,[1,mb]); alginit(nfinit(y),["a",[[],[]],[]]); alginit(nfinit(y),[1,[[],[]],[]]); alginit(nfinit(y),[0,[[],[]],[]]); algrandom(,1); algrandom(,-1.); algneg(,[1..4]); algneg(,Mod(1,2)); algneg(,[1..5]~); algneg(,[1,2,3,I]~); algadd(,1,[]~); algadd(,O(3^3),I); algadd(,I,[1;2]); algadd(,Mat([1,2]),[3;4]); algadd(,Mat(1),Mat(O(3))); algadd(,I,Mat(2)); algtrace(,O(x^2)); algtrace(,[[1..4]~;[2..5]~]); algtomatrix(,1+I*'x); algmul(,[1,2,3,4]~,'x); algmul(,'y,I); algmul(,[1,2;3,4],1+I); algsqr(,O(3^3)); algnorm(,Mod(1,2)); algcharpoly(,sin); alginv(,'x); alginv(,0); algdivl(,'x,1); algdivl(,[1,2,3,4]~,'y); algdivl(,0,1); algdivl(,[;],1); algdivl(,[1,2,3,4]~,[;]); algdivl(,[1;2],Pi); algpoleval(,'x,'x); algpoleval(,'x,[1,2;3,4]); algpoleval(,O(3),[1,2,3,4]~) algdivl(,matrix(0,3),[;]); algdivl(,[;],matrix(0,3)); algdivl(,matrix(1,1),[;]); H = alginit(1.,1/2); R = alginit(1.,0); C = alginit(I,0); algramifiedplaces(H); H0 = H; H0[1] = O(2); algrandom(H0,1.); algsqr(H,[]~); algsqr(H,O(x)); algalgtobasis(H,1); algbasistoalg(H,1); algcentralproj(H,[1]); algcharpoly(R,[1,2,3,4]~) algcharpoly(C,[1,2,3,4]~) algdisc(R) algdisc(C) algdisc(H) algdivl(C,[;],1) algdivl(C,[1,2,3,4]~,[1,2,3,4]~) algdivl(C,matrix(2,1),matrix(1,1)) algdivl(C,matrix(2,2),matrix(3,3)) alginit(1.,1); alginv(C,[1..4]~); alginv(C,0); alglatadd(H,[matid(4),1],[matid(4),1]); alglatcontains(H,[matid(4),1],[1..4]~); alglatelement(H,[matid(4),1],[1..4]~); alglathnf(H,matid(4)); alglatindex(H,[matid(4),1],[matid(4),1]); alglatinter(H,[matid(4),1],[matid(4),1]); alglatlefttransporter(H,[matid(4),1],[matid(4),1]); alglatmul(H,[matid(4),1],[matid(4),1]); alglatrighttransporter(H,[matid(4),1],[matid(4),1]); alglatsubset(H,[matid(4),1],[matid(4),1]); algnorm(R,[1..4]~); algnorm(C,[1..4]~); algquotient(H,[;]); algrelmultable(H); algsplittingdata(H); algsubalg(H,[1;0;0;0]); algtableinit(H); algtensor(H,H); algtomatrix(R,[1,2,3,4]~); algtomatrix(C,[1,2,3,4]~); algtrace(R,[1,2,3,4]~); algtrace(C,[1,2,3,4]~); H0 = H; H0[9] = concat(H0[9],[matid(4)]); algtrace(H0,1); algnorm(H0,1); algcharpoly(H0,1); algtomatrix(H0,1); alginv(H0,1); algdim(H0); algrandom(H0,1.); al = alginit(nfinit(y),[-1,-1]); al[2][1] = O(x); algdim(al); algdim(al,1); al = alginit(nfinit(y^2+1), algmultable(al)); algsqr(al,[1..20]~); al = alginit(nfinit(y),1); algsqr(al,[O(x)]~); \\end bad inputs print("new algsimpledec"); \\ K^3 mt = [matid(3),[0,0,0;1,1,0;0,0,0],[0,0,0;0,0,0;1,0,1]]; al = algtableinit(mt); algissimple(al) setrand(1); algsimpledec(al,1) al2 = algtableinit(mt,5); algissimple(al2) setrand(2); algsimpledec(al2,1) \\ upper-tri in M2(K) mt = [matid(3),[0,0,0;1,1,0;0,0,1],[0,0,0;0,0,0;1,0,0]]; al = algtableinit(mt); setrand(1); algsimpledec(al,1) al2 = algtableinit(mt,5); setrand(1); algsimpledec(al2,1) print("norm(,1)"); nf = nfinit(y^2-5); B = alginit(nf,[-1,y]); b = [x,1]~; algnorm(B,b,1) n = algnorm(B,b) nfeltnorm(nf,n)^2 algnorm(B,b/3,1) algnorm(B,[3,5,1,6,7,-2,1/7,0]~,1) m = [[1/3,y]~,[0,0]~;[y+1,y-1]~,[1..8]~]; algnorm(B,m,1)==matdet(algtomatrix(B,m,1)) a = algrandom(B,2); algnorm(B,a,1)*algnorm(B,b,1)==algnorm(B,algmul(B,a,b),1) print("trace(,1)"); nf = nfinit(y^2-5); A = alginit(nf,[-1,y]); a = [1+x+y,2*y]~*Mod(1,y^2-5)*Mod(1,x^2+1); t = algtrace(A,a) algtrace(A,a,1) algdegree(A)*nfelttrace(nf,t) b = [1+x/3+y,y-x/7]~*Mod(1,y^2-5)*Mod(1,x^2+1); algdegree(A)*nfelttrace(nf,algtrace(A,b))==algtrace(A,b,1) c = [4/3,2,1,6,8,9,-1,3/2]~; algdegree(A)*nfelttrace(nf,algtrace(A,c))==algtrace(A,c,1) m = [[y,x]~*Mod(1,y^2-5)*Mod(1,x^2+1),[1,0]~;[1..8]~,[1/7,5,6,7,8,1/4,1/3,1/2]~]; 2*algdegree(A)*nfelttrace(nf,algtrace(A,m))==algtrace(A,m,1) algtrace(A,[[1,0]~,[0,0]~;[0,0]~,[1,0]~],1)==4*algdim(A,1) print("charpoly(,1)"); nf = nfinit(y^2-5); al = alginit(nf,[-3-y,y]); pol = nf.pol; polrel = algsplittingfield(al).pol; a = [y,1+x]~*Mod(1,pol)*Mod(1,polrel); P = lift(algcharpoly(al,a)) algcharpoly(al,a,,1) lift(P*subst(P,y,-y)*Mod(1,pol))^2 b = [1+x/3+y/2,3*y-x/7]~*Mod(1,pol)*Mod(1,polrel); P = lift(algcharpoly(al,b)); Q = algcharpoly(al,b,,1); Q == lift(P*subst(P,y,-y)*Mod(1,pol))^2 c = [4/3,2,1/7,6,4,9,-1,3/2]~; P = lift(algcharpoly(al,c)); Q = algcharpoly(al,c,,1); Q == lift(P*subst(P,y,-y)*Mod(1,pol))^2 {m = [[y/3,x+1]~*Mod(1,pol)*Mod(1,polrel),[1,7/11]~; [1..8]~,[1/7,5,6,7/2,8,1/4,1,-1/2]~];} P = lift(algcharpoly(al,m)); Q = algcharpoly(al,m,,1); Q==lift(P*subst(P,y,-y)*Mod(1,pol))^4 print("more al_MAT tests"); setrand(1); nf=nfinit(y^2-5); pol = nf.pol; al=alginit(nf,[y,-1]); polrel = algsplittingfield(al).pol; m1 = matrix(2,2,i,j,algrandom(al,1)/(i+2*j)); {m2 = matrix(2,2,i,j,vector(2,k,random(2)+random(2)*x+random(2)*y+ random(2)*x*y)~*Mod(1,polrel)*Mod(1,pol)/prime(i+2*j));} {m3 = [[1,0]~,[1..8]~;[y+x,y-x]~*Mod(1,polrel)*Mod(1,pol), [1,3,5,0,-1,-2,0,-2]~/3];} print("add"); algadd(al,m1,m2)==algadd(al,m2,m1) algadd(al,m1,m3)==algadd(al,m3,m1) algadd(al,m1,m2)==algadd(al,m2,m1) algadd(al,algadd(al,m1,m2),m3) == algadd(al,m1,algadd(al,m2,m3)) print("alg/basis"); algalgtobasis(al,m1) == m1 algbasistoalg(al,m2) == m2 algalgtobasis(al,algbasistoalg(al,algalgtobasis(al,m1))) == algalgtobasis(al,m1) algalgtobasis(al,algbasistoalg(al,algalgtobasis(al,m2))) == algalgtobasis(al,m2) algalgtobasis(al,algbasistoalg(al,algalgtobasis(al,m3))) == algalgtobasis(al,m3) algbasistoalg(al,algalgtobasis(al,algbasistoalg(al,m1))) == algbasistoalg(al,m1) algbasistoalg(al,algalgtobasis(al,algbasistoalg(al,m2))) == algbasistoalg(al,m2) algbasistoalg(al,algalgtobasis(al,algbasistoalg(al,m3))) == algbasistoalg(al,m3) print("charpoly"); mid = [[1,0]~,[0,0]~;[0,0]~,[1,0]~]; t = 123/7; testcp(m)= { my(P,Q); P = algcharpoly(al,m); print(algnorm(al,m) == polcoeff(P,0)); print(algtrace(al,m) == -polcoeff(P,3)); print(algnorm(al,algsub(al,m,t*mid))==subst(P,x,t)); Q = algcharpoly(al,m,,1); print(algnorm(al,m,1) == polcoeff(Q,0)); print(algtrace(al,m,1) == -polcoeff(Q,31)); print(algnorm(al,algsub(al,m,t*mid),1)==subst(Q,x,t)); } testcp(m1); testcp(m2); testcp(m3); print("inv/div"); algisinv(al,m1,&m1i) m1i == alginv(al,m1) algdivl(al,m1,m2) == algmul(al,m1i,m2) algdivr(al,m2,m1) == algmul(al,m2,m1i) algisdivl(al,m1,m3,&d13) algdivl(al,m1,m3) == d13 algisinv(al,m2,&m2i) m2i == alginv(al,m2) algdivl(al,m2,m1) == algmul(al,m2i,m1) algdivr(al,m1,m2) == algmul(al,m1,m2i) algisdivl(al,m2,m3,&d23) algdivl(al,m2,m3) == d23 algisinv(al,m3,&m3i) m3i == alginv(al,m3) algdivl(al,m3,m1) == algmul(al,m3i,m1) algdivr(al,m1,m3) == algmul(al,m1,m3i) algisdivl(al,m3,m2,&d32) algdivl(al,m3,m2) == d32 midbasis = [[1,0,0,0,0,0,0,0]~,vector(8)~;vector(8)~,[1,0,0,0,0,0,0,0]~]; algmul(al,m1i,m1) == midbasis algmul(al,m1,m1i) == midbasis algmul(al,m2i,m2) == midbasis algmul(al,m2,m2i) == midbasis algmul(al,m3i,m3) == midbasis algmul(al,m3,m3i) == midbasis print("mul"); algmul(al,algmul(al,m1,m2),m3) == algmul(al,m1,algmul(al,m2,m3)) algmul(al,m1,algadd(al,m2,m3)) == algadd(al, algmul(al,m1,m2), algmul(al,m1,m3)) algmul(al,algadd(al,m1,m2),m3) == algadd(al,algmul(al,m1,m3),algmul(al,m2,m3)) print("neg"); algadd(al,m1,algneg(al,m1)) == 0 algadd(al,m2,algneg(al,m2)) == 0 algadd(al,m3,algneg(al,m3)) == 0 print("norm"); algnorm(al,m1)*algnorm(al,m2) == algnorm(al,algmul(al,m1,m2)) algnorm(al,m1)*algnorm(al,m3) == algnorm(al,algmul(al,m1,m3)) algnorm(al,m3)*algnorm(al,m2) == algnorm(al,algmul(al,m3,m2)) print("pow"); algpow(al,m1,5) == algmul(al,algpow(al,m1,2),algpow(al,m1,3)) algalgtobasis(al,algpow(al,m2,3)) == algmul(al,algpow(al,m2,5),algpow(al,m2,-2)) algpow(al,m3,3) == algmul(al,algpow(al,m3,-1),algpow(al,m3,4)) print("sqr"); algsqr(al,m1) == algpow(al,m1,2) algsqr(al,m2) == algpow(al,m2,2) algsqr(al,m3) == algpow(al,m3,2) print("sub"); algsub(al,m2,m3) == algadd(al,m2,algneg(al,m3)) algsub(al,m1,m3) == algadd(al,m1,algneg(al,m3)) algsub(al,m1,m2) == algadd(al,m1,algneg(al,m2)) print("trace"); algtrace(al,m2)+algtrace(al,m3) == algtrace(al,algadd(al,m2,m3)) algtrace(al,m1)+algtrace(al,m3) == algtrace(al,algadd(al,m1,m3)) algtrace(al,m1)+algtrace(al,m2) == algtrace(al,algadd(al,m1,m2)) print("abs trace"); algtrace(al,m2,1)+algtrace(al,m3,1) == algtrace(al,algadd(al,m2,m3),1) algtrace(al,m1,1)+algtrace(al,m3,1) == algtrace(al,algadd(al,m1,m3),1) algtrace(al,m1,1)+algtrace(al,m2,1) == algtrace(al,algadd(al,m1,m2),1) print("algtomatrix"); sm1 = algtomatrix(al,m1); sm2 = algtomatrix(al,m2); sm3 = algtomatrix(al,m3); #sm1==4 #sm1[,1]==4 sm2+sm3 == algtomatrix(al,algadd(al,m2,m3)) sm2*sm3 == algtomatrix(al,algmul(al,m2,m3)) sm1+sm3 == algtomatrix(al,algadd(al,m1,m3)) sm1*sm3 == algtomatrix(al,algmul(al,m1,m3)) sm1+sm2 == algtomatrix(al,algadd(al,m1,m2)) sm1*sm2 == algtomatrix(al,algmul(al,m1,m2)) print("algleftmultable"); M1 = algtomatrix(al,m1,1); M2 = algtomatrix(al,m2,1); M3 = algtomatrix(al,m3,1); #M1==32 #M1[,1]==32 #M2==32 #M2[,1]==32 #M3==32 #M3[,1]==32 M2+M3 == algtomatrix(al,algadd(al,m2,m3),1) M2*M3 == algtomatrix(al,algmul(al,m2,m3),1) M1+M3 == algtomatrix(al,algadd(al,m1,m3),1) M1*M3 == algtomatrix(al,algmul(al,m1,m3),1) M1+M2 == algtomatrix(al,algadd(al,m1,m2),1) M1*M2 == algtomatrix(al,algmul(al,m1,m2),1) print("more al_CSA tests"); setrand(1); nf = nfinit(y^2-5); mti = [0,-1,0,0;[1,0]~,0,0,0;0,0,0,-1;0,0,1,0]; mtj = [0,0,Mod(y,y^2-5),0;0,0,0,-y;1,0,0,0;0,-1,0,0]; mtk = [0,0,0,y;0,0,[1,2]~,0;0,1,0,0;1,0,0,0]; mt = [matid(4),mti,mtj,mtk]; al = alginit(nf,mt); a1 = [1/2,-3,2,4/3,-1,0,1,2/5]~; a2 = [1+2*y,y/3,5/2,-3*y/7]~*Mod(1,y^2-5); a3 = algrandom(al,2)/13; aid = [1,0,0,0]~; algadd(al,algadd(al,a1,a2),a3) == algadd(al,a1,algadd(al,a2,a3)) algadd(al,a1,a2) == algadd(al,a2,a1) algbasistoalg(al,algalgtobasis(al,algbasistoalg(al,a1))) == algbasistoalg(al,a1) algalgtobasis(al,algbasistoalg(al,algalgtobasis(al,a2))) == algalgtobasis(al,a2) t = 7/3; testcp(a)= { my(P,Q); P = algcharpoly(al,a); print(algnorm(al,a) == polcoeff(P,0)); print(algtrace(al,a) == -polcoeff(P,1)); print(algnorm(al,algsub(al,a,t*aid))==subst(P,x,t)); Q = algcharpoly(al,a,,1); print(algnorm(al,a,1) == polcoeff(Q,0)); print(algtrace(al,a,1) == -polcoeff(Q,7)); print(algnorm(al,algsub(al,a,t*aid),1)==subst(Q,x,t)); } print("charpoly"); testcp(a1); testcp(a2); testcp(a3); print("inv/div"); algisinv(al,a1,&a1i) a1i == alginv(al,a1) algdivl(al,a1,a2) == algmul(al,a1i,a2) algdivr(al,a2,a1) == algmul(al,a2,a1i) algisdivl(al,a1,a3,&d13) algdivl(al,a1,a3) == d13 aidbasis = vector(8,i,i==1)~; algmul(al,a1i,a1) == aidbasis algmul(al,a1,a1i) == aidbasis a2i = alginv(al,a2); print("mul"); algmul(al,a2i,a2) == aid algmul(al,a2,a2i) == aid algmul(al,algmul(al,a1,a2),a3) == algmul(al,a1,algmul(al,a2,a3)) print("neg"); algadd(al,a1,algneg(al,a1)) == 0 algadd(al,a2,algneg(al,a2)) == 0 algadd(al,a3,algneg(al,a3)) == 0 print("norm"); algnorm(al,a1)*algnorm(al,a2) == algnorm(al,algmul(al,a1,a2)) algnorm(al,a1)*algnorm(al,a3) == algnorm(al,algmul(al,a1,a3)) algnorm(al,a3)*algnorm(al,a2) == algnorm(al,algmul(al,a3,a2)) print("pow"); algpow(al,a1,5) == algmul(al,algpow(al,a1,2),algpow(al,a1,3)) algpow(al,a2,3) == algmul(al,algpow(al,a2,5),algpow(al,a2,-2)) algpow(al,a3,3) == algmul(al,algpow(al,a3,-1),algpow(al,a3,4)) print("sqr"); algsqr(al,a1) == algpow(al,a1,2) algsqr(al,a2) == algpow(al,a2,2) algsqr(al,a3) == algpow(al,a3,2) print("sub"); algsub(al,a2,a3) == algadd(al,a2,algneg(al,a3)) algsub(al,a1,a3) == algadd(al,a1,algneg(al,a3)) algsub(al,a1,a2) == algadd(al,a1,algneg(al,a2)) print("trace"); algtrace(al,a2)+algtrace(al,a3) == algtrace(al,algadd(al,a2,a3)) algtrace(al,a1)+algtrace(al,a3) == algtrace(al,algadd(al,a1,a3)) algtrace(al,a1)+algtrace(al,a2) == algtrace(al,algadd(al,a1,a2)) print("abs trace"); algtrace(al,a2,1)+algtrace(al,a3,1) == algtrace(al,algadd(al,a2,a3),1) algtrace(al,a1,1)+algtrace(al,a3,1) == algtrace(al,algadd(al,a1,a3),1) algtrace(al,a1,1)+algtrace(al,a2,1) == algtrace(al,algadd(al,a1,a2),1) print("algtomatrix"); sa1 = algtomatrix(al,a1); sa2 = algtomatrix(al,a2); sa3 = algtomatrix(al,a3); #sa1==2 #sa1[,1]==2 sa2+sa3 == algtomatrix(al,algadd(al,a2,a3)) sa2*sa3 == algtomatrix(al,algmul(al,a2,a3)) sa1+sa3 == algtomatrix(al,algadd(al,a1,a3)) sa1*sa3 == algtomatrix(al,algmul(al,a1,a3)) sa1+sa2 == algtomatrix(al,algadd(al,a1,a2)) sa1*sa2 == algtomatrix(al,algmul(al,a1,a2)) print("algleftmultable"); ma1 = algtomatrix(al,a1,1); ma2 = algtomatrix(al,a2,1); ma3 = algtomatrix(al,a3,1); #ma1==8 #ma1[,1]==8 #ma2==8 #ma2[,1]==8 ma2+ma3 == algtomatrix(al,algadd(al,a2,a3),1) ma2*ma3 == algtomatrix(al,algmul(al,a2,a3),1) ma1+ma3 == algtomatrix(al,algadd(al,a1,a3),1) ma1*ma3 == algtomatrix(al,algmul(al,a1,a3),1) ma1+ma2 == algtomatrix(al,algadd(al,a1,a2),1) ma1*ma2 == algtomatrix(al,algmul(al,a1,a2),1) print("csa pol/polmod bugs"); setrand(1); nf = nfinit(y^2-5); mti = [0,-1,0,0;1,0,0,0;0,0,0,-1;0,0,1,0]; mtj = [0,0,y,0;0,0,0,-y;1,0,0,0;0,-1,0,0]; mtk = [0,0,0,y;0,0,y,0;0,1,0,0;1,0,0,0]; mt = [matid(4),mti,mtj,mtk]; al = alginit(nf,mt*Mod(1,nf.pol)); algrelmultable(al) a = [y,y,y,y/3]~; algpow(al,a,4) algpow(al,a,-2) algmul(al,a,a) algnorm(al,a) == algnorm(al,algalgtobasis(al,a)) algnorm(al,a,1) == algnorm(al,algalgtobasis(al,a),1) algtrace(al,a) == algtrace(al,algalgtobasis(al,a)) algtrace(al,a,1) == algtrace(al,algalgtobasis(al,a),1) algcharpoly(al,a) == algcharpoly(al,algalgtobasis(al,a)) algcharpoly(al,a,,1) == algcharpoly(al,algalgtobasis(al,a),,1) algtomatrix(al,a) == algtomatrix(al,algalgtobasis(al,a)) print("csa: denom over Z[y] but not over ZK"); setrand(1); nf = nfinit(y^2-5); mti = [0,-1,0,0;1,0,0,0;0,0,0,-1;0,0,1,0]; mtj = [0,0,(y-1)/2,0;0,0,0,-(y-1)/2;1,0,0,0;0,-1,0,0]; mtk = [0,0,0,(y-1)/2;0,0,(y-1)/2,0;0,1,0,0;1,0,0,0]; mt = [matid(4),mti,mtj,mtk]; al = alginit(nf,mt*Mod(1,nf.pol)); algrelmultable(al) mti = [0,-1,0,0;1,0,0,0;0,0,0,-1;0,0,1,0]; mtj = [0,0,(y-1)/3,0;0,0,0,-(y-1)/3;1,0,0,0;0,-1,0,0]; mtk = [0,0,0,(y-1)/3;0,0,(y-1)/3,0;0,1,0,0;1,0,0,0]; mt = [matid(4),mti,mtj,mtk]; al = alginit(nf,mt*Mod(1,nf.pol)); print("al_MAT over al_CSA"); setrand(1); nf = nfinit(y^2-5); mti = [0,-1,0,0;1,0,0,0;0,0,0,-1;0,0,1,0]; mtj = [0,0,(y-1)/2,0;0,0,0,-(y-1)/2;1,0,0,0;0,-1,0,0]; mtk = [0,0,0,(y-1)/2;0,0,(y-1)/2,0;0,1,0,0;1,0,0,0]; mt = [matid(4),mti,mtj,mtk]; al = alginit(nf,mt*Mod(1,nf.pol)); m1 = [algrandom(al,2)/2,algrandom(al,1)/3;algrandom(al,2)/5,algrandom(al,3)]; m2 = [[y,1/2,2-y,0]~,[3,y/2,-3*y,1]~;[7,0,0,y]~,[1-y,2,-y,0]~]; algnorm(al,algmul(al,m1,m2)) == algnorm(al,m1)*algnorm(al,m2) algnorm(al,algmul(al,m1,m2),1) == algnorm(al,m1,1)*algnorm(al,m2,1) algtrace(al,algadd(al,m1,m2)) == algtrace(al,m1)+algtrace(al,m2) algtrace(al,algadd(al,m1,m2),1) == algtrace(al,m1,1)+algtrace(al,m2,1) mid = [[1,0,0,0]~,vector(4)~;vector(4)~,[1,0,0,0]~]; t = -3/7; testcp(m)= { my(P,Q); P = algcharpoly(al,m); print(algnorm(al,m) == polcoeff(P,0)); print(algtrace(al,m) == -polcoeff(P,3)); print(algnorm(al,algsub(al,m,t*mid))==subst(P,x,t)); Q = algcharpoly(al,m,,1); print(algnorm(al,m,1) == polcoeff(Q,0)); print(algtrace(al,m,1) == -polcoeff(Q,31)); print(algnorm(al,algsub(al,m,t*mid),1)==subst(Q,x,t)); } testcp(m1); testcp(m2); print("algleftmultable"); M1 = algtomatrix(al,m1,1); M2 = algtomatrix(al,m2,1); #M1==32 #M1[,1]==32 #M2==32 #M2[,1]==32 M1+M2 == algtomatrix(al,algadd(al,m1,m2),1) M1*M2 == algtomatrix(al,algmul(al,m1,m2),1) print("Hamilton quaternions"); a = algrandom(,1.); apply(type,a) b = algrandom(,1.); precision(b) algrandom(,0.)==0 localprec(300); precision(algrandom(,1.)) print("H_neg"); algneg(,a) == -a algneg(,[a,b;b,a]) == [-a,-b;-b,-a] algneg(,2.) == -2 algneg(,I) == -I algneg(,1/2) == -1/2 algneg(,3) == -3 print("H_add"); algadd(,a,b) == a+b algadd(,I,[1..4]~) == [1,3,3,4]~ algadd(,[1..4]~,10.) == [11.,2,3,4]~ algadd(,2.*I,3/2) == 3/2 + 2.*I algadd(,[a;b],[2;I]) == [algadd(,a,2);algadd(,b,I)] algsub(,a,b) == a-b print("H_trace"); algtrace(,a) == 2*a[1] algtrace(,b,1) == 4*b[1] algtrace(,[a,0;1,b]) == algtrace(,a) + algtrace(,b) algtrace(,[a,0;1,b],1) == 8*(a[1]+b[1]) algtrace(,1) == 2 algtrace(,1/2+I) == 1 algtrace(,matid(2)) == 4 algtrace(,matid(2),1) == 16 print("H_tomatrix"); algtomatrix(,a+b) == algtomatrix(,a)+algtomatrix(,b) algtomatrix(,a+b,1) == algtomatrix(,a,1)+algtomatrix(,b,1) algtomatrix(,[1,0,0,0]~) algtomatrix(,1) algtomatrix(,[1,0,0,0]~,1) algtomatrix(,1,1) algtomatrix(,[0,1,0,0]~) == algtomatrix(,I) algtomatrix(,[0,1,0,0]~,1) == algtomatrix(,I,1) algtomatrix(,I)^2 == -1 algtomatrix(,I,1)^2 == -1 algtomatrix(,[0,0,1,0]~)^2 == -1 algtomatrix(,[0,0,1,0]~,1)^2 == -1 algtomatrix(,[0,0,0,1]~)^2 == -1 algtomatrix(,[0,0,0,1]~,1)^2 == -1 algtomatrix(,I)*algtomatrix(,[0,0,1,0]~) == algtomatrix(,[0,0,0,1]~) M = Mat(1); M[1,1] = a; algtomatrix(,M) == algtomatrix(,a) algtomatrix(,M,1) == algtomatrix(,a,1) M = [1.+I,2;3/2-I,Pi*I]; N = [-7,3+4/5*I;sqrt(2),exp(sqrt(5)*I)]; P = matrix(2,2,i,j,algrandom(,1.)); exponent(algtrace(,algmul(,M,N)) - algtrace(,algmul(,N,M))) < -120 exponent(algmul(,M,algmul(,N,P)) - algmul(,algmul(,M,N),P)) < -120 algtomatrix(,M)*algtomatrix(,N) == algtomatrix(,M*N) exponent(algtomatrix(,M,1)*algtomatrix(,N,1) - algtomatrix(,M*N,1)) < -120 trace(algtomatrix(,M)) == algtrace(,M[1,1])+algtrace(,M[2,2]) trace(algtomatrix(,N)) == algtrace(,N[1,1])+algtrace(,N[2,2]) {exponent(trace(algtomatrix(,M,1)) - 2*(algtrace(,M[1,1],1) + algtrace(,M[2,2],1))) < -120} {exponent(trace(algtomatrix(,N,1)) - 2*(algtrace(,N[1,1],1) + algtrace(,N[2,2],1))) < -120} print("3x3 matrices"); M = matrix(3,3,i,j,algrandom(,1.)); N = matrix(3,3,i,j,algrandom(,2.)); P = matrix(3,3,i,j,algrandom(,3.)); exponent(algtrace(,algmul(,M,N)) - algtrace(,algmul(,N,M))) < -120 exponent(algmul(,M,algmul(,N,P)) - algmul(,algmul(,M,N),P)) < -120 exponent(algmul(,M,algadd(,N,P)) - algadd(,algmul(,M,N),algmul(,M,P))) < -120 exponent(algtomatrix(,M)*algtomatrix(,N) - algtomatrix(,algmul(,M,N))) < -120 exponent(algtomatrix(,M,1)*algtomatrix(,N,1) - algtomatrix(,algmul(,M,N),1)) < -120 algtomatrix(,M+N) == algtomatrix(,M)+algtomatrix(,N) exponent(algtomatrix(,M+N,1) - (algtomatrix(,M,1)+algtomatrix(,N,1))) < -120 trace(algtomatrix(,M)) == algtrace(,M[1,1])+algtrace(,M[2,2])+algtrace(,M[3,3]) {exponent(trace(algtomatrix(,N)) - (algtrace(,N[1,1]) + algtrace(,N[2,2]) + algtrace(,N[3,3]))) < -120} {exponent(trace(algtomatrix(,M,1)) - 3*(algtrace(,M[1,1],1) + algtrace(,M[2,2],1) + algtrace(,M[3,3],1))) < -120} {exponent(trace(algtomatrix(,N,1)) - 3*(algtrace(,N[1,1],1) + algtrace(,N[2,2],1) + algtrace(,N[3,3],1))) < -110} algtomatrix(,[-100-1000*I;[1,2,3,4]~]) c = algrandom(,3.); exponent(algmul(,a,algmul(,b,c)) - algmul(,algmul(,a,b),c)) < -120 algtrace(,algmul(,a,b)) == algtrace(,algmul(,b,a)) algmul(,1,a) == a algmul(,b,1) == b algmul(,I,I) == [-1,0,0,0]~ algmul(,[0,0,1,0]~,[0,0,1,0]~) == [-1,0,0,0]~ algmul(,[0,0,0,1]~,[0,0,0,1]~) == [-1,0,0,0]~ algmul(,I,[0,0,1,0]~) == [0,0,0,1]~ exponent(algmul(,a,algadd(,b,c)) - algadd(,algmul(,a,b),algmul(,a,c))) < -120 exponent(algtomatrix(,algmul(,a,b)) - algtomatrix(,a)*algtomatrix(,b)) < -120 exponent(algtomatrix(,algmul(,a,b),1) - algtomatrix(,a,1)*algtomatrix(,b,1)) < -120 algsqr(,M) == algmul(,M,M) algnorm(,M) == real(matdet(algtomatrix(,M))) algnorm(,M,1) == matdet(algtomatrix(,M,1)) z=sqrt(2)+Pi*I; algsqr(,sqrt(2)+Pi*I) == z^2 algnorm(,a) == norml2(a) algnorm(,a,1) == norml2(a)^2 algnorm(,b) == norml2(b) algnorm(,b,1) == norml2(b)^2 algnorm(,c) == norml2(c) algnorm(,c,1) == norml2(c)^2 exponent(algnorm(,c) - real(matdet(algtomatrix(,c)))) < -120 exponent(algnorm(,c,1) - matdet(algtomatrix(,c,1))) < -110 algnorm(,c) == algmul(,c,algsub(,algtrace(,c),c))[1] algnorm(,z) == norm(z) algnorm(,z,1) == norm(z)^2 algcharpoly(,a) == x^2 - algtrace(,a)*x + algnorm(,a) exponent(algcharpoly(,a) - real(charpoly(algtomatrix(,a)))) < -120 algcharpoly(,a,,1) == (x^2 - algtrace(,a)*x + algnorm(,a))^2 exponent(algcharpoly(,a,,1) - charpoly(algtomatrix(,a,1))) < -120 algcharpoly(,z) == x^2 - algtrace(,z)*x + algnorm(,z) algcharpoly(,z,,1) == (x^2 - algtrace(,z)*x + algnorm(,z))^2 algnorm(,algmul(,a,b)) == algnorm(,a)*algnorm(,b) exponent(algnorm(,algmul(,M,N)) - algnorm(,M)*algnorm(,N)) < -110 exponent(algcharpoly(,N) - real(charpoly(algtomatrix(,N)))) < -110 m = matrix(3,3,i,j,vectorv(4,k,random(3))); pol = algcharpoly(,m); pol == real(charpoly(algtomatrix(,m))) polcoef(pol,5) == -algtrace(,m) polcoef(pol,0) == algnorm(,m) pol = algcharpoly(,m,,1); pol == charpoly(algtomatrix(,m,1)) polcoef(pol,35) == -algtrace(,m,1) polcoef(pol,0) == algnorm(,m,1) print("nonsquare matrices"); M = matrix(4,7,i,j,algrandom(,1.)); N = matrix(7,5,i,j,algrandom(,1.)); P = matrix(5,8,i,j,algrandom(,1.)); exponent(algmul(,M,algmul(,N,P)) - algmul(,algmul(,M,N),P)) < -120 exponent(algsqr(,a) - algmul(,a,a)) < -120 exponent(algsqr(,b) - algmul(,b,b)) < -120 exponent(algsqr(,c) - algmul(,c,c)) < -120 !algisinv(,0) !algisinv(,vectorv(4)) algisinv(,a) ai = alginv(,a); exponent(algsub(,algmul(,a,ai),1)) < -120 algisinv(,b,&bi) bi == alginv(,b) exponent(algsub(,algmul(,b,bi),1)) < -120 algisinv(,z) alginv(,z) == 1/z exponent(algsub(,algmul(,a,algdivl(,a,b)),b)) < -120 algdivl(,b,c) == algmul(,alginv(,b),c) algdivl(,b,0) == 0 algisdivl(,0,0) !algisdivl(,0,a) exponent(algnorm(,[1,a;2,I])) > -64 m = [1,a;2,I]; algisinv(,m,&mi) mi == alginv(,m) exponent(algsub(,algmul(,m,mi),matid(2))) < -120 exponent(algsub(,algmul(,mi,m),matid(2))) < -120 n = [I-3/2,b;c,z]; ni = alginv(,n); exponent(algsub(,algmul(,n,ni),matid(2))) < -120 exponent(algsub(,algmul(,ni,n),matid(2))) < -120 mni = alginv(,algmul(,m,n)); exponent(algsub(,mni, algmul(,ni,mi))) < -120 exponent(algsub(,algmul(,algdivr(,n,m),m),n)) < -120 ra = bestappr(a); rb = bestappr(b); rc = bestappr(c); m = [ra,rb;algmul(,rc,ra),algmul(,rc,rb)]; algnorm(,m) == 0 !algisinv(,m) n = algmul(,m,[1,[6,7,8,9]~;3,4+I]); algisdivl(,m,n,&quo) algmul(,m,quo) == n quo == algdivl(,m,n) exponent(algsub(, algpow(,a,3), algmul(,a,algsqr(,a)))) < -120 algpow(,a,0) == 1 algpow(,a,-2) == algsqr(,alginv(,a)) algpow(,[;],0) == [;] algpow(,[;],7) == [;] algpow(,[;],-5) == [;] algpow(,m,0) == matid(2) algpow(,m,3) == algmul(,algsqr(,m),m) algpow(,m,-9) exponent(algsub(,algmul(,algdivr(,a,b),b),a)) < -120 algdivr(,m,n) exponent(algpoleval(,x^4-7*x,z) - (z^4-7*z)) < -110 exponent(algsub(,algpoleval(,x^2,a),algsqr(,a))) < -120 {exponent(algsub(,algpoleval(,x^3-x+1,b), algadd(,algsub(,algpow(,b,3),b),1))) < -120} exponent(algpoleval(,algcharpoly(,a),a)) < -120 exponent(algpoleval(,algcharpoly(,b),b)) < -120 algdivl(,[;],[;]) H = alginit(1.,1/2); algtype(H) algaut(H) algb(H) type(algcenter(H)) algchar(H) algdegree(H) algdim(H) algdim(H,1) alghasse(H) alghassei(H) algindex(H) algisassociative(H) algiscommutative(H) algisdivision(H) algisramified(H) algissemisimple(H) algissimple(H) algissplit(H) mt = algmultable(H) algisassociative(mt) apply(matsize,mt) mt[1] == 1 mt[2]^2 == -1 mt[3]^2 == -1 mt[4] == mt[2]*mt[3] mt[3]*mt[2] == -mt[4] Mat([m[,1] | m <- mt]) == matid(4) algradical(H) algsimpledec(H) == [0,[H]] type(algsplittingfield(H)) algadd(H,a,b) == algadd(,a,b) algcharpoly(H,a) == algcharpoly(,a) algdivl(H,a,b) == algdivl(,a,b) algdivr(H,a,b) == algdivr(,a,b) alginv(H,a) == alginv(,a) algisdivl(H,a,b) == algisdivl(,a,b) algisinv(H,a) == algisinv(,a) algmul(H,a,b) == algmul(,a,b) algneg(H,a) == algneg(,a) algnorm(H,a) == algnorm(,a) algpoleval(H,x^3+x+1,a) == algpoleval(,x^3+x+1,a) algpow(H,a,5) == algpow(,a,5) algpow(H,a,0) == algpow(,a,0) algpow(H,a,-3) == algpow(,a,-3) #algrandom(H,1.) algsqr(H,a) == algsqr(,a) algsub(H,a,b) == algsub(,a,b) algtomatrix(H,a) == algtomatrix(,a) algtrace(H,a) == algtrace(,a) R = alginit(1.,0); algtype(R) type(algaut(R)) algb(R) type(algcenter(R)) algchar(R) algdegree(R) algdim(R) algdim(R,1) alghasse(R) alghassei(R) algindex(R) algisassociative(R) algiscommutative(R) algisdivision(R) algisramified(R) algissemisimple(R) algissimple(R) algissplit(R) mt = algmultable(R) algisassociative(mt) apply(matsize,mt) mt[1] == 1 algradical(R) algsimpledec(R) == [0,[R]] type(algsplittingfield(R)) algbasis(R) == matid(1) alginvbasis(R) == matid(1) a = algrandom(R,1.); type(a) b = algrandom(R,2.); m22 = matrix(2,2,i,j,algrandom(R,1.)); m22b = matrix(2,2,i,j,algrandom(R,1.)); m23 = matrix(2,3,i,j,algrandom(R,1.)); m32 = matrix(3,2,i,j,algrandom(R,1.)); algadd(R,a,b) == a+b algadd(R,m22,m22b) == m22 + m22b algneg(R,a) == -a algsub(R,a,b) == a-b algsub(R,m22,m22) == 0 algmul(R,a,b) == a*b algmul(R,m22,m23) == m22*m23 algsqr(R,a) == a^2 algsqr(R,m22) == m22^2 algtomatrix(R,a) == Mat(a) algtomatrix(R,b,1) == Mat(b) algtomatrix(R,m22) == m22 algtomatrix(R,m22b,1) == m22b algnorm(R,a) == a algnorm(R,b,1) == b algnorm(R,m22) == matdet(m22) algnorm(R,m22b,1) == matdet(m22b)^2 algtrace(R,a) == a algtrace(R,b,1) == b algtrace(R,m22) == trace(m22) algtrace(R,m22b,1) == 2*trace(m22b) algcharpoly(R,a) == x-a algcharpoly(R,b,,1) == x-b algcharpoly(R,m22) == charpoly(m22) algcharpoly(R,m22b,,1) == charpoly(m22b)^2 exponent(algdivl(R,a,b) - b/a) < -100 exponent(algdivl(R,m22,m22b) - m22^(-1)*m22b) < -100 {m22noninv = matrix(2,1,i,j,round(algrandom(R,10.))) * matrix(1,2,i,j,round(algrandom(R,10.)))}; algnorm(R,m22noninv) == 0 exponent(m22noninv * algdivl(R,m22noninv,m22noninv*m22) - m22noninv*m22) < -100 exponent(m22*alginv(R,m22) - matid(2)) < -100 exponent(algdivr(R,a,b) - a/b) < -100 algdivr(R,m22,m22b) == m22*m22b^(-1) !algisdivl(R,0.,1) algisdivl(R,0.,0.) !algisdivl(R,m22noninv,m22) !algisinv(R,0.) !algisinv(R,m22noninv) algisinv(R,a) algisinv(R,m22b) algpow(R,a,8) == a^8 exponent(algpow(R,a,-2) - a^(-2)) < -100 algpow(R,a,0) == 1. algpow(R,m22,3) == m22^3 exponent(algpow(R,m22,-5) - m22^(-5)) < -100 algpow(R,m22,0) == matid(2) algpoleval(R,x^3-x+1,a) == a^3-a+1 C = alginit(I,0); algtype(C) algaut(C) algb(C) algcenter(C) algchar(C) algdegree(C) algdim(C) algdim(C,1) alghasse(C) alghassei(C) algindex(C) algisassociative(C) algiscommutative(C) algisdivision(C) algisramified(C) algissemisimple(C) algissimple(C) algissplit(C) mt = algmultable(C) algisassociative(mt) apply(matsize,mt) mt[1] == 1 mt[2]^2 == -1 Mat([m[,1] | m <- mt]) == matid(2) algradical(C) algsimpledec(C) == [0,[C]] type(algsplittingfield(C)) algbasis(C) == matid(2) alginvbasis(C) == matid(2) z = algrandom(C,1.); type(z) u = algrandom(C,2.); mc22 = matrix(2,2,i,j,algrandom(C,1.)); mc22b = matrix(2,2,i,j,algrandom(C,1.)); mc23 = matrix(2,3,i,j,algrandom(C,1.)); mc32 = matrix(3,2,i,j,algrandom(C,1.)); algadd(C,z,u) == z+u algadd(C,m22,mc22) == m22 + mc22 algneg(C,z) == -z algsub(C,z,u) == z-u algsub(C,m22,mc22) == m22 - mc22 algmul(C,z,u) == z*u algmul(C,mc32,mc22) == mc32*mc22 algsqr(C,u) == u^2 algsqr(C,mc22) == mc22^2 algtomatrix(R,z) == Mat(z) algtomatrix(C,z) == Mat(z) algtomatrix(C,u,1) == [real(u),-imag(u);imag(u),real(u)] algtomatrix(C,mc22) == mc22 matsize(algtomatrix(C,mc22,1)) == [4,4] Set(apply(type,concat(Vec(algtomatrix(C,mc22,1))))) algtomatrix(C,mc22,1)+algtomatrix(C,mc22b,1) == algtomatrix(C,mc22+mc22b,1) {exponent(algtomatrix(C,mc22,1)*algtomatrix(C,mc22b,1) - algtomatrix(C,mc22*mc22b,1)) < -100} algnorm(C,z) == z algnorm(C,u,1) == norm(u) algnorm(C,mc22) == matdet(mc22) algnorm(C,mc22b,1) == norm(matdet(mc22b))^2 algtrace(C,z) == z algtrace(C,u,1) == 2*real(u) algtrace(C,mc22) == trace(mc22) algtrace(C,mc22b,1) == 4*real(trace(mc22b)) algcharpoly(C,z) == x-z algcharpoly(C,u,,1) == x^2 - 2*real(u)*x + norm(u) algcharpoly(C,m22) == charpoly(m22) P = charpoly(m22b); algcharpoly(C,m22b,,1) == real(P*conj(P))^2 algdivl(C,z,u) == u/z exponent(algdivl(C,mc22,mc22b) - mc22^(-1)*mc22b) < -100 {mc22noninv = matrix(2,1,i,j,round(algrandom(C,10.))) * matrix(1,2,i,j,round(algrandom(C,10.)))}; algnorm(C,mc22noninv) == 0 exponent(mc22noninv*algdivl(C,mc22noninv,mc22noninv*mc22)-mc22noninv*mc22)<-100 exponent(mc22*alginv(C,mc22) - matid(2)) < -100 exponent(algdivr(C,z,u) - z/u) < -100 algdivr(C,mc22,mc22b) == mc22*mc22b^(-1) !algisdivl(R,0.+0.*I,I) algisdivl(R,0.+0.*I,0.*I) !algisdivl(C,mc22noninv,mc22) !algisinv(C,0.*I) !algisinv(C,m22noninv) algisinv(C,z) algisinv(C,mc22b) algpow(C,z,11) == z^11 exponent(algpow(C,z,-6) - z^(-6)) < -100 algpow(C,z,0) == 1. algpow(C,mc22,5) == mc22^5 exponent(algpow(C,mc22,-3) - mc22^(-3)) < -100 algpow(C,mc22,0) == matid(2) exponent(algpoleval(C,x^3-x+1,z) - (z^3-z+1)) < -100 print("nfgrunwaldwang SEGV #1669"); nfgrunwaldwang(nfinit(y),[2,3],[1,2],Vecsmall(1)) nfgrunwaldwang(nfinit(x),[2,3],[1,2],Vecsmall(1)) print("alginit SEGV #2465"); Q=nfinit(y); F=rnfinit(Q,x^3+x^2-2*x-1); alginit(F,[2,x^2-2]) alginit(F,[2,y]) \\alg_model bug for 1-dim al_CSA al = alginit(nfinit(y),[matid(1)]); algtomatrix(al,[Mod(1,y)]~) algtomatrix(al,[1]~) algtomatrix(al,[1+y-y]~) algtomatrix(al,[1/2]~) algtomatrix(al,[Mod(1/2,y)]~) \\al_MATRIX sqr bug al = algtableinit([matid(2),[0,0;1,0]],2); m = [[1,1]~,[1,0]~;[0,1]~,[0,0]~]; type(algsqr(al,m))=="t_MAT" print("GW modified arguments"); L = [2,3]; Q = nfinit('z); gw = nfgrunwaldwang(Q,L,[2 | p <- L],[1],'y); print(L==[2,3]); print("rnf/gchar confusion (#2473)"); F=nfinit(y^10 - y^9 - 11*y^8 + 13*y^7 + 35*y^6 - 43*y^5 - 36*y^4 + 41*y^3 + 10*y^2 - 7*y - 1); id=idealprimedec(F, 5)[1]; A=alginit(F, [2, [[id], [1]], [1, 1, 1, 1, 0, 1, 1, 1, 1, 1]],,0); type(algsplittingfield(A).pol) \\algpoleval type check setrand(1); nf = nfinit(y^2-5); al = alginit(nf,[y,-1]); a = [1..8]~; pol = algcharpoly(al,a); algpoleval(al,pol,a)==0 algpoleval(al,pol,[;]) pol = algcharpoly(al,a,,1); algpoleval(al,pol,a)==0 ma = algtomatrix(al,a,1); algpoleval(al,pol,[a,ma])==0 \\not implemented al = algtableinit([Mat(1)]); al2 = algtensor(al,al); al = algtableinit([Mat(1)],2); al2 = algtensor(al,al); print("maxord flag"); setrand(1); p = randomprime(10^60); q = randomprime(10^60); D = p*q; Q = nfinit(y); alg = alginit(Q, [-1,-D],,0); alghasse(alg,idealprimedec(Q,2)[1]) alg = alginit(Q, [-D,-1],,0); alghassef(alg) algindex(alg) algramifiedplaces(alg) nb = 100; Lpr = [idealprimedec(Q,p)[1] | p <- primes(nb)]; Lh = [1/2 | pr <- Lpr]; alg = alginit(Q,[2,[Lpr,Lh],[0]],,0); algbasis(alg) == matid(4) alg = alginit(Q,[2,[Lpr,Lh],[0]],,1); algdisc(alg) == - 2^4 * vecprod(primes(nb))^2 nf = nfinit(y^2+y+1); al1 = alginit(nf,[p,-1]); P = x^3-q; rnf = rnfinit(nf,P); al2 = alginit(rnf, [y*x,-1]); \\al = algtensor(al1,al2,0); \\too long: 5s ; find a replacement test mt = qamt(-D,-1); al = alginit(Q,mt,,0); r = randomprime(2^20); alg = alginit(Q, [-1,-D*r^2],,0); algbasis(alg) == matid(4) alg = alginit(Q, [-1,-D*r^2],,1); algbasis(alg) != matid(4) algdisc(alg)%r != 0 p = randomprime([2^21,2^25]); q = randomprime([2^21,2^25]); alg = alginit(Q, [-1,-p*q^2],,2); algbasis(alg) == matid(4) algdisc(alg)%q == 0 alghasse(alg, idealprimedec(Q,q)[1]) == 0 \\example from Mickael Montessinos z = 'z; {mu=z^2 - 11002587770426695439129164047/1737260475313383983450*z + 6545246845996161752942936173068414/868630237656691991725;} K=nfinit(mu)[1]; {a=Mod(-69086050716125587677489266397120505050532860277271020543856131112359472587249662596671157785576853587734894096237342986133482192522376606166312001078976428714783686509419622091061230480777960739344862221463*z + 17453734866925059675086784329655571003277844536255892750682707497315715224615308957737819137643460547574317397225176742916615587901357323690105414054047014710629006726626291809468283041248154785368119402124315203921703504063895910608939, z^2 - z - 92872063185781870942858883351009206258508089837924172);} {b=Mod(-1035464865145958113498386343817353611512208005431706435751486532489352629097073992049773530058639270194660491130007336201173807672154956934359635775222574770842789685409237393049361814801314845912471006607076157129175506026341062584943375971447249024144909990346373996322237069233036298963526709971155410826143109337077867748290573536280996027777874316518815261022303435909974867174963523171489569835351872410087590894716041063648356690146913649149359434604377562735743595799274721681898135071375254453371875705493674846620286422579264452470750164641481757486*z + 266243872090899957611917622625085819912625185933035287288945961691311901961554524941870710600171398449371439959525398334037907904475189170784501224724867894108420227524056470930694025544733616206766010919775405696175885593113192582156794019402900498167170603497231935265954237883930313410463105795157319796329621453835830351071644066742681126927422850589151914181348581283512688655651184057188621686726190394203802175891713113867315165212798716829664371534269293476510694504642348414507472514058827790192348669455400772967473649404232753822915836606995513095160066145989929210528668576404, z^2 - z - 92872063185781870942858883351009206258508089837924172);} al=alginit(K,[a,b],,0); print("segfault in algsubalg for invalid input"); nf = nfinit(y); al = alginit(nf, [-1,-1]); alt = algtableinit(algmultable(al),3); B = [1, 0, 0, 0; 0, 7625597484987, 6608353175723, 6996189950772; 0, 0, 1, 0; 0, 0, 0, 1]; alB = algsubalg(alt,B)[1]; algdim(alB) print("integral coefficients in alginit"); fewops(alg) = { my(a,b,nrd); algramifiedplaces(alg); a = algrandom(al,10); b = algrandom(al,10); algmul(al,a,b); algadd(al,a,b); nrd = algnorm(al,a); trd = algtrace(al,a); algcharpoly(al,b); print(algcharpoly(al,a) == x^2 - trd*x + nrd); algtomatrix(al,a); 1 }; nf = nfinit(y^2-5); alg = alginit(nf, [-1,(1+y)/2]); fewops(alg); alg = alginit(nf, [(1+y)/2, -1]); fewops(alg); rnf = rnfinit(nf, x^2-(1+y)/2); alg = alginit(rnf, [-x,-1]); fewops(alg); rnf = rnfinit(nf, x^2+1); alg = alginit(rnf, [-x,(1+y)/2]); fewops(alg); pari-2.17.2/src/test/in/ideal0000644000175000017500000002635214702763006014356 0ustar billbillQi = nfinit(x^2+1); idealintersect(Qi,0,1) Q = nfinit(y); idealaddtoone(Q,1,[;]) idealaddtoone(Q,[;],1) idealaddtoone(Q,[1,[;]]) zQ = idealstar(,4); zerror=z=znstar(6,1); z.clgp p=19;N=19^4;z=znstar(N,1);g=Mod(z.gen[1],N); for(i=1,1000,if (i%p && g^ideallog(,i,z)[1] != i, error(i))) z=znstar(3120,1); Mat(vector(#z,i,znlog(z.gen[i],z))) nfisideal(Qi,matdiagonal([6,12])) P = idealprimedec(Qi,2)[1]; idealprincipalunits(Qi,P,10) idealprincipalunits(Qi,P,1) idealintersect(Qi, 1/2,1/2) ideallog(Q,1/2,idealstar(Q,3,1)) idealdiv(Qi,7*x-1,3*x+1,1) K=nfinit(x^2-236*x+13384);\\ Q(sqrt(60)), in disguise idealhnf(K, qfbprimeform(60,2)) Kerror=K=nfinit(x^3-2); u=nfalgtobasis(K,x);v=nfalgtobasis(K,x^2); idealhnf(K,Mat([u,v])) idealhnf(K,1/4,1/6) idealhnf(K,4,[6,0,0]~) idealhnf(K,2,1/6) idealhnf(K,1/3,u/2) idealhnf(K,u,v/2) P = idealprimedec(K,5); idealval(K,P[1],P[2]) idealval(K,P[2],P[1]) idealval(K,P[2],P[2]) P[1][2] += 5; idealval(K,P[1],P[1]) idealmul(K,P[1],P[1].gen[2]) idealnorm(K,P[1]) idealinv(K,Mod(x,K.pol)) idealinv(K,Mod(x-1,K.pol)) idealinv(K,2) idealinv(K,1) idealpow(K,idealhnf(K,x),-2) v=[1,1/2,x,Mod(x,K.pol),P[1],[;],Mat(1),vector(5),[1,2,3;4,5,6;7,8,9],[1,2,3;0,4,5;0,0,6],I]; for(i=1,#v, if(!nfisideal(K,v[i]),print(i))) idealred(K,2) idealred(K,[2,[;]]) idealred(K,[2,factor(1)]) idealdown(K, -1/2) idealdown(K, -2/3*(11*x+7)) idealdown(K, [2, 11, 5]~) idealdown(K, idealprimedec(K, 2)[1]) idealdown(nf, idealhnf(K, -2/3*(11*x+7))) idealismaximal(Q,Mat(2)) idealismaximal(K,2) idealismaximal(K,5) idealismaximal(K,7).p idealismaximal(K,-7).p pr=idealprimedec(K,5)[1]; idealismaximal(K,pr) == pr pr = idealprimedec(K,31)[2]; idealismaximal(K,idealhnf(K,pr)) == pr idealismaximal(K, x^2+1) idealismaximal(nfinit(x^5-x-1), [330,241,183,-175,348]~) \\ #2556 \\ https://github.com/sagemath/sage/issues/38766 : idealismaximal(nfinit(x^4 - 18*x^2 + 9), 3) K=nfinit(x^4+26); A=idealhnf(K,7,x^3+2*x^2-3*x+1); idealred(K,[A,1]) k=nfinit(polcyclo(5)); idealfactor(k,101,100) idealfactor(k,2*101,100) idealfactor(k,101/103,100) idealfactor(k,101/(2*103),100) idealfactor(k,2^4*[0,1,0,0]~,100) nf=nfinit(x^2+x+1); p = 67452192952521724999; pi = idealprimedec(nf,p)[1]; q = 762234946175168528650011228121; qi = idealprimedec(nf,q)[1]; f=idealfactor(nf, idealdiv(nf,pi,qi)) idealfactor(nf, 787033*(x+1), 100) fa = idealfactor(nf, 471440*x + 612823, 100) idealfactor(nf,fa[2,1],10) idealfactor(nf,fa[2,1],40) idealfactor(nf, 471440*x + 612823, 2000) id=idealfactorback(nf,f) idealnumden(nf,id) idealnumden(nf,pi) idealnumden(nf,1) idealnumden(nf,1/2) idealnumden(nf,x/2) nffactorback(nf, [3, x+1, [1,2]~], [1, 2, 3]) test(nf,F,v)= { my(Y = idealchinese(nf,F,v), P = F[,1], E = F[,2]); for (i=1,#P, if( nfeltval(nf, nfeltadd(nf,v[i],-Y),P[i]) < E[i], error(i))); Y; } v = [x,0,[0,1/7^4]~,Mod(x,nf.pol)]; F = idealfactor(nf, 2*3*7); F[,2] *= 3; test(nf,F,v) F[,2] = [0,1,-2,3]~; test(nf,F,v) F[,2] = [1,1,1,1]~; test(nf,F,[1,0,0,0]) test(nf,F,[0,1/11,0,0]) P = F[2,1]; v = nfeltval(nf, 0, P, &y); [v == valuation(0,2),y] v = nfeltval(nf, 12, P, &y); [v,y] v = nfeltval(nf, (2/5*(1-x))^3, P, &y); [v,y] v = nfeltval(nf, [2/5,3; 1-x,3], P, &y); [v,y] v = nfeltval(nf, nfeltpow(nf,P.gen[2],4), P, &y); [v,y] K=nfinit(x^3-9216*x-1); pr=idealprimedec(K,2)[1]; y=[-7251900112893394084630798621252778318328823533401193294840423185069284010118591056272912470850596269372678704921912086470447212545880393655162109344551257556522001544975617113653626505416989042867708649441635537906645036859305944019456658330693793415682691843066999955760793392760905274945376164960562430160499108743499489166126112286009187484098481841959052276342967337596329855275728191062143785239993461801661066499033908665360152840022520735711822526852796653675739586967804491713715733508499227401313919685231314583572415034026601694878847990666591234129630499499618519087857790138725749828198318462952936971186543274927991920100085364830093053624697582983462351788061311719734582985213317107441673887626159137920132977234063900896027136396636365117069606665341092785349565712790993664097231039603008339544399512868277612682210429393171461063237969283817710245,-2360132442057874747689273820720362046424339941461618886350826050226768088358242993964507296057577657594202672684207104480519301251180707938704041235100833509586519915077407676914716744353674738283667692061514086450255178210255999941322465197431410516193011963762146689482400150209177411411055794184310126356273013824737007989745355371999985613009192210527609466796508488868265962799895319379492168131560647427585471768508335892838647659384132817585825652205567211488476594688742130447090335185302733753528466373580383524136862656055037349165584500453223287208442578102315800773028624685576661911327535886726849611703792108343011574990463354707094879326961457784184392523878142031564479577307514152659262501057646532992968611372467068531210214277356801401290262284113607511465114006914847245463594108562489712048466456627569000216549896556809542683160106911342243,7079629137248140607534263802511617544277840436474159263127045636894875018982059388290823938229939700694216000711029248248544320867096904399737148347483828065653911945212992193990277681601615586973113160415823443330728056183046750020038707042234967620499753361349333910802934291323385057054936022813276581538843838138306483625117978511593393573171189586878645265348062069729269352782261507177928838084859848129123524772826668386532195847961354852784978639003003276853101259131041414526570347944356412769953044865974762989385211557990996134656942808880432381990089265583355794420791687584993069037904769041249653099646630151551521202190654880886047498561993191792371550922197828560939461770201848049399192335647711875733227730750137220427214593608880562566905108670517623437950158138092591013780943449078454922467260689488043719085499977593585468727939031959225672]~; nfeltval(K,y,pr) K = nfinit(t^2-2); fa = idealfactor(K, 2^2*3); C = idealchinese(K, [fa, [1,1]]); idealchinese(K, C, [1,t]) idealchinese(K, C, [-1,t]) C = idealchinese(K, fa); idealchinese(K, C, [1,t]) C = idealchinese(K, [C,[-1,-1]]); idealchinese(K, C, [1,t]) F = idealfactor(Q,2); idealchinese(Q, [F,[-1]], [0]) idealchinese(Q, [F,[1]], [0]) idealchinese(Q, [F,[0]], [0]) K = nfinit(x^3 - 2); A = idealhnf(K, 46875, 3*x-15909); idealispower(K, A, 3, &B) B idealispower(K, A/6, 3) A = idealhnf(K, 9375, 3*x+2841); idealispower(K, A, 3) idealispower(K, A, 1) idealispower(K, x, 2) \\ #2019 idealispower(nfinit('y), 4, 2, &A) A K = nfinit(x^3 - 2); idealispower(K,2*5^3,3, &A) A \\ #1643 K=nfinit(x^8-1310*x^6+575380*x^4-93689568*x^2+3644295424); idealprimedec(K,17,1) K=nfinit(2*x^2+1); idealprimedec(K,2) nf=nfinit(x^6+108); a=Mod(x,x^6+108); { for(k=2,5, u=nfalgtobasis(nf,(2*a^2+a+3)*random(2^100*x^6)^k); b=idealredmodpower(nf,u,k); v=nfeltmul(nf,u,nfeltpow(nf,b,k)); if(exponent(v) > 8, error())); } idealredmodpower(nf,0,2) idealredmodpower(nf,1,2) idealredmodpower(nf,x^5-3*x^4-3*x^3+18*x^2-18*x-54,2) normlp(idealredmodpower(nf,x/2,2))<=4/3 normlp(idealredmodpower(nf,x/12,2))==2 \\ #2181 K=nfinit(x^8-x^7+853*x^6-1705*x^5+728461*x^4+1452660*x^3+619196112*x^2+618470208*x+526936617216); u=-3295726369461731289346462354027551095147507850796810976485053015787461298353108007583029758931909391395188837628668142381696585601437206958160059088656895054166218670573364811083286147878242585838527045253797229311486033571024871881929287881077914632802195379103689126727632008134046230078244187204095701757094128/260724204971*x^7+152863926358270815544472123370490820166780242836471008050258163804853439449801824873411217655847998109907297746769178336511497087330162778040820494775879882958573450265443161858185457172379185261151238335647103015398581733887282351101399242916823136952231183683199101605679082163422859803969844993303192375158488395/260724204971*x^6+2406969062350137466974129399472410998165327268340813973208132297136368946979717955888179787396728806465215113589203085301099423514588331588410673016489928975328731366941577055358386555440702685134595491735392116911370554413115054763882219750201465929629596212857087211828803278102003368100380518925867680945671392758/260724204971*x^5+137081377031906128392870125864427558076072913056967813032379896192971269428599909167009269953614565674098274721075933937534960141450285421213854815419440875039596388799075475996861092731865801389720913656617782135991020999908157644078900708443933197909880176896579654094373664440105249916909867638439259664338357/357911*x^4-4070384803042875340985803129476097507909253548244290568349511184577280798573048974379898801802416130979368946784139048555791283831757663295406137658907489681591104458511952667444030644669716367155349587332608227047763781013968599806140375397111055668273281172821830908149779634693364726621708244806767055285739243/357911*x^3+168568151397754802332659319517140588351513494220656094382082344667989521434320523470084625110632495651098654578074052487914578127730269525935219602706975998497315707490354656426031415845673577166983029177291634864418998327847405449225543246927771172876308151314755102488557891516111932299073018228704234809975838558280/3672171901*x^2+181362559355967687441569495330120111725438491767051963183672797774029950131820046784857408792196513411721255514863234109334262708584276295532717046352106452388095588290213473060646544156544816015150427479886047726758182800473609208937424330313768632341406130437806943904609093544637112676778467331699309127867113568552/51720731*x+372127521854786946433207593778098718752150069645620903197210809657741784407186452886727962060707364324199752951617693996241954393320511097561377550117731467675995153475373681027825265683582338981915799545023659321144005643029640559571880834933169400027679490835114916769308702041993834252518389568506982417895596595904/728461; if (!idealispower(K,u,5,&v) || idealpow(K,v,5) != idealhnf(K,u), error("#2181")) \\ #2258 K = nfinit(x^4 + 1393*x^2 + 484416); J = idealpow(K,idealprimedec(K,3)[1],-2) / 5; idealdiv(K,J,[0,1/5,0,0]~) K = nfinit (x^2 + 134*x + 712); fa = idealfactor(K, 60); CH = idealchinese(K, fa); C = [2670768074695170611139434716011157107733, -7258527314365930510409656450413725891970]~ / 89111260116725317454044216131056431951297033; C = vector(matsize(fa)[1], i, C); idealchinese(K, fa, C) idealchinese(K, CH, C) ideallist(nfinit(x^3+x+1),-100) nf = nfinit(x^2+1); q = 66990068194224668837688920640869956213511365270390760834869624766543930275514582783438208741938158015056628000321140177444704840033011710554698818802921051297606201206504901337138328970627492071570690600494775984423655258784559572122767730803974727272339050939987775644235692970853518057821562556942886455466289; M = 784; f = 13*q; bid = idealstar(nf,f,,M); bid.cyc ideallog(nf,11,bid) \\ #2549 setrand(1);nf=nfinit(x^2+1);bid=idealstar(nf,49,,2);ideallog(nf,3,bid) \\ Errors, keep at end of file ideallist(x,-300) idealaddtoone(Q,2,[;]) idealaddtoone(Q,[;],[;]) idealaddtoone(Q,[1,[;],Mat(1/2)]) idealhnf(Q,[x,x,x,x,x]) idealval(Q,2,[x,x,x,x,x]) idealval(Q,Mat(2),[x,x,x,x,x]) ideallog(Q,2,zQ) ideallog(,0,zerror) ideallog(,2,zerror) ideallog(,3,zerror) ideallog(Q,3,zerror) ideallog(,3,zQ) idealmul(Kerror,[2,1;0,1],[2,1;0,1]) idealmul(Kerror,matid(4),matid(4)) idealred(nf,[2,Mat(1)]) K=nfinit(y^3+8*y^2-128*y-512); idealstar(K,[4,Vecsmall([1,1,1])]) idealstar(K,[4,Vecsmall([1,4,2])]) idealstar(K,[4,Vecsmall([-1,2,3])]) idealstar(K,[4,Vecsmall([1,1])]) idealred(K, [4,3,2,1;0,3,2,1;0,0,2,1;0,0,0,1]) pari-2.17.2/src/test/in/eval0000644000175000017500000000005714567450071014225 0ustar billbilleval(Vecsmall([1,2,3])) eval("\\") \\eval("=") pari-2.17.2/src/test/in/self0000644000175000017500000000004114567450071014220 0ustar billbill(n->if(n==0,1,n*self()(n-1)))(5) pari-2.17.2/src/test/in/rootsof10000644000175000017500000000015414676526175015062 0ustar billbillrootsof1(1) rootsof1(2) rootsof1(3) rootsof1(4) rootsof1(5) rootsof1(6) \\ Errors rootsof1(0) rootsof1(-1) pari-2.17.2/src/test/in/log0000644000175000017500000000011014676526175014057 0ustar billbilllog(1+10^-30) lngamma(1+10^-30) lngamma(10^-30) iferr(log(2+O(33)),E,E) pari-2.17.2/src/test/in/program0000644000175000017500000000176414676526175014765 0ustar billbillHEAP=[47, if(sizebyte(0)==16,2097,3531)]; STACK=if(sizebyte(0)==16, 232, 128); STACK == getstack \e alias(ln,log) ln(2) for(x=1,5,print(x!)) fordiv(10,x,print(x)) forprime(p=1,30,print(p)) forstep(x=0,2.9,Pi/12,print(sin(x))) forvec(x=[[1,3],[-2,2]],print1([x[1],x[2]]," "));print(" "); if(3<2,print("bof"),print("ok")); kill(y);print(x+y); f(u)=u+1; print(f(5));kill(f); f=12 g(u)=if(u,,return(17));u+2 g(2) g(0) n=33;until(n==1,print1(n," ");if(n%2,n=3*n+1,n=n/2));print(1) m=5;while(m<20,print1(m," ");m=m+1);print() \\ default(seriesprecision,12) print((x-12*y)/(y+13*x)); print([1,2;3,4]) print1(x+y);print(x+y); print((x-12*y)/(y+13*x)); print([1,2;3,4]) print1(x+y);print1(" equals ");print(x+y); print1("give a value for s? ");s=input();print(1/(s^2+1)) printtex((x+y)^3/(x-y)^2) for(i=1,100,for(j=1,25,if(i+j==32,break(2)));print(i)) { u=v=p=q=1; for (k=1,400, w=u+v; u=v; v=w; p *= w; q=lcm(q,w); if (k%50==0, print(k" "log(p)/log(q)) ) ); } if (getheap()!=HEAP, getheap()) pari-2.17.2/src/test/in/quadclassunit0000644000175000017500000000261314760123736016156 0ustar billbilldefault(parisize, "72M"); \\ overflows 70M test(D) = { for (d = D, D+10^3, if (!isfundamental(d),next); print(d, " ", quadclassunit(d).cyc) ); } setrand(1); test(10^15); test(-10^15) { for(i=1,10000, my(D=2*i-(i%2)); if(issquare(D),next()); my(w=quadunit(D), N=norm(w)); if(denominator(w)>1 || abs(N)!=1 || quadunitnorm(D) != N, error(D))) } quadunit(2^48+21) * Mod(1,2^64-59) quadunitindex(157,3) quadunitindex(157,11) quadunitindex(-3,1) quadunitindex(-3,2) quadunitindex(-4,2) quadunitindex(-8,2) quadunitnorm(17345) quadunitindex(17345, 10) quadunitindex(5, [100, [2,2;5,2]]) quadunitindex(5, 100) quadunitindex(5, [2,2;5,2]) quadunitindex(5, 2^32) quadunitindex(28, 2^32) quadunitindex(8461,2) quadunit(74881) quadunit(511681) quadunitindex(76,3) \\ #2491 default(echo,1); \\#1180 setrand(1);quadclassunit(572).no \\ #1195 setrand(11);quadclassunit(-8419588).cyc setrand(2);quadclassunit(-1459008).cyc setrand(7);quadclassunit(-3799812).cyc setrand(1); quadclassunit(-13163208).cyc \\ #1195 with non-fundamental discriminants [oo loop] setrand(38);quadclassunit(-29920).cyc quadclassunit(-13163208,,[0.1]).cyc setrand(1); quadclassunit((2^70+25)).cyc setrand(1); quadclassunit(8*3*5*7).cyc \\ #1700 setrand(1);quadclassunit(-612556842419).cyc \\ #2015 setrand(2); quadclassunit(-699,,[6,6]).cyc \\ ERRORS quadunit(1.) quadunitindex(1.,2) quadunitindex(5,1.) quadunitnorm(1.) pari-2.17.2/src/test/in/set0000644000175000017500000000066614567450071014077 0ustar billbillSet(Vecsmall([1,2,1,3])) Set(List([])) L=List([1,3,1,2,3]); Set(L) listsort(L,1); L Set(1) a=Set([5,-2,7,3,5,1,x,"1"]) b=Set([7,5,-5,7,2,"1"]) setintersect(a,b) setisset([-3,5,7,7]) setisset(a) setminus(a,b) setsearch(a,3) setsearch(a,"1") setsearch(b,3) setsearch(L,3) setsearch(1,3) setunion(a,b) setdelta(a,b) setdelta(Set([1,2]),Set([1])) X = [1,2,3]; Y = [2,3,4]; setbinop((x,y)->x+y, X,Y) setbinop((x,y)->x+y, X) setbinop(x->x, X) pari-2.17.2/src/test/in/charpoly0000644000175000017500000001462214730120536015112 0ustar billbillcharpoly([x,x+1;1,2],y,0) charpoly([x,x+1;1,2],y,1) charpoly([x,x+1;1,2],y,2) charpoly([x,x+1;1,2],y,3) charpoly([0,0,2,2;0,0,2,2;2,2,0,0;2,2,0,0]) charpoly([0,0,2,2;0,0,2,2;2,2,0,0;2,2,0,0],,4) minpoly(matrix(4,4,i,j,i/j)) A=[5/3,7/45;0,21/10]; mateigen(A) mateigen(A*1.) mateigen(A,1) m=[224,221,13,2;201,199,12,2;100,99,6,1;85,84,5,1]; [D,M]=mateigen(m,1); D exponent(m*M - M*matdiagonal(D)) localbitprec(64); one = 1.; localbitprec(32); mateigen(m*one); mateigen(m*one, 1); \\ were errors M=[x,x+y;x+1,1];charpoly(M,w) v=[1,1.,Mod(1,3),1/2,1+O(3),I,quadgen(5),matid(2)*Mod(1,3),matid(2)*Mod(1,2^64+13)]; for(i=1,#v,print(charpoly(v[i]))) { \\ #2010 g(s2,s3)=s6=s2*s3;[2,0,0,-s6+3,2*s3-3*s2,3*s3-3*s2; 0,-2,0,s3-s2,-s6+2,-s6+3; 0,0,-1,s3-2*s2,-s6+1,-s6+3; 0,0,s3,2*s6-6,-5*s3+6*s2,-6*s3+7*s2; -2*s3,2,-s6+5,-7*s3+10*s2,8*s6-21,9*s6-27; 2*s3,-2,s6-5,8*s3-11*s2,-9*s6+23,-10*s6+30]/2; } exponent(charpoly(g(sqrt(2),sqrt(3))) - (x^6-x^5-3*x^4-3*x^3-3*x^2-x+1)) < -120 centerlift(charpoly(g(sqrt(2+O(23^10)), sqrt(3+O(23^10))))) charpoly(matid(4),,0) charpoly(matid(4),,3) charpoly(matid(4)*(2^64+13)) m=[1,2,3,4;5,6,7,8;9,10,11,12;1,5,7,11]; charpoly(m*Mod(1,3)) charpoly(m*Mod(1,2^64+13)) matadjoint(matid(2),1) matadjoint([;]) matadjoint(Mat(1)) matadjoint([x,0,0;0,0,0;0,0,0]) matadjoint([Mod(1,2)*x,0,0;0,0,0;0,0,0]) charpoly(x*matid(3)) charpoly(Mod(0,x^0)) charpoly(Mod(0*x,x^0)) charpoly(Mod(1,x^0)) charpoly(Mod(x,x^0)) charpoly(Mod(x+1,x^4+1)) charpoly(Mod(x,x^2)) charpoly(Mod(1,x^2+x+1)) charpoly(Mod(y,x^2+x+1)) charpoly(Mod(1,x^24+1)) charpoly(Mod(1,x^2)) charpoly(Mod(1/(x-(t+1))*Mod(1,2),(t+1)*x^2+t*x+1)) minpoly(Mod(0,x^0)) minpoly(Mod(0*x,x^0)) minpoly(Mod(1,x^0)) minpoly(Mod(x,x^0)) minpoly(Mod(x+1,x^4+1)) minpoly(Mod(x,x^2)) minpoly(Mod(1,x^2+x+1)) minpoly(Mod(y,x^2+x+1)) minpoly(Mod(1,x^24+1)) minpoly(Mod(1,x^2)) minpoly(Mod(1/(x-(t+1))*Mod(1,2),(t+1)*x^2+t*x+1)) test(a)= { if(subst(charpoly(a),x,a),error(a)); if(subst(minpoly(a),x,a),error(a)); } test(Mod(x^7+x+1,x^41+x^13/13+x/17)) test(Mod(x^7+x^5/5+1,x^41+x^13/13+x/17)) test(p)= { my(P,Q); P=random(x^10*'b^10*Mod(1,p))*Mod(1,ffinit(p,10,'b)); Q=random(x^10*'b^10*Mod(1,p))*Mod(1,ffinit(p,10,'b)); my(z=Mod(P,Q)); if(subst(minpoly(z),x,z)!=0,error(z)); if(subst(charpoly(z),x,z)!=0,error(z)); } test(5); test(nextprime(2^40)); test(nextprime(2^100)); a=[1,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0;0,1,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0;0,0,1,-1,0,0,0,0,0,0,0,0,0,0,0,0,0;-1,-1,-1,4,0,0,0,0,-1,0,0,0,0,0,0,0,0;0,0,0,0,1,0,0,-1,0,0,0,0,0,0,0,0,0;0,0,0,0,0,1,0,-1,0,0,0,0,0,0,0,0,0;0,0,0,0,0,0,1,-1,0,0,0,0,0,0,0,0,0;0,0,0,0,-1,-1,-1,4,-1,0,0,0,0,0,0,0,0;0,0,0,-1,0,0,0,-1,4,-1,-1,0,0,0,0,0,0;0,0,0,0,0,0,0,0,-1,1,0,0,0,0,0,0,0;0,0,0,0,0,0,0,0,-1,0,4,-1,-1,-1,0,0,0;0,0,0,0,0,0,0,0,0,0,-1,1,0,0,0,0,0;0,0,0,0,0,0,0,0,0,0,-1,0,1,0,0,0,0;0,0,0,0,0,0,0,0,0,0,-1,0,0,3,-1,0,-1;0,0,0,0,0,0,0,0,0,0,0,0,0,-1,3,-2,0;0,0,0,0,0,0,0,0,0,0,0,0,0,0,-2,2,0;0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,1]; mateigen(a); mateigen([;]) mateigen([;],1) mateigen(Mat(1)) mateigen(Mat(1),1) t=sqrt(5); M=[1,-1,0,0,0,0,0;-1,1,0,0,0,0,0;0,0,1,(t-1)/4,(-t-1)/4,(-t-1)/4,(t-1)/4;0,0,(t-1)/4,1,(t-1)/4,(-t-1)/4,(-t-1)/4;0,0,(-t-1)/4,(t-1)/4,1,(t-1)/4,(-t-1)/4;0,0,(-t-1)/4,(-t-1)/4,(t-1)/4,1,(t-1)/4;0,0,(t-1)/4,(-t-1)/4,(-t-1)/4,(t-1)/4,1]; mateigen(M) mateigen(M,1) M= [1/2,0.43301270189221932338186158537646809174,0,0,0,0,0,0;0.43301270189221932338186158537646809174,0.59375000000000000000000000000000000000,0.16010860571811872473782872938314143736,0,0,0,0,0;0,0.16010860571811872473782872938314143736,0.17773437500000000000000000000000000000,0.043156991785125689527076292745166173981,0,0,0,0;0,0,0.043156991785125689527076292745166173981,0.046264648437500000000000000000000000000,0.010983784699077503627379527042372838459,0,0,0;0,0,0,0.010983784699077503627379527042372838459,0.011680603027343750000000000000000000000,0.0027580894367975917547150661058975793532,0,0;0,0,0,0,0.0027580894367975917547150661058975793532,0.0029273033142089843750000000000000000000,0.00069028107976465866361951420577874482654,0;0,0,0,0,0,0.00069028107976465866361951420577874482655,0.00073227286338806152343750000000000000000,0.00017261768635203427455190103576949842909;0,0,0,0,0,0,0.00017261768635203427455190103576949842909,0.00018309801816940307617187500000000000000]; mateigen(M) \\#2406 {P7a=[15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0; 0,0,0,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0; 0,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,0,0; 0,10,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0; 0,0,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,0; 0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,0; 0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0; 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0; 0,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,0,0,0,0,0,0; 0,0,0,10,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0; 0,0,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,0,0,0,0,0; 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0,0,0; 0,0,0,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,0,0,0,0; 0,0,30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0; 0,0,0,0,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,0,0,0; 0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,10,0,0,0,0; 0,0,0,0,0,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,0,0; 30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0; 0,0,0,0,0,0,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,0; 0,0,0,0,0,0,0,0,0,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0; 0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0; 0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,10,0,0; 0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0; 0,0,0,0,0,0,0,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0; 0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0; 0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,6; 0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0; 0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,10; 0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15; 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,30,0,0,0,0,0]/30;} F7a=[1/2,7,1/2,1/3,1/2,1/5,1/2,7,1/2,1/3,1/2,7,1/2,7,1/2,1/3,1/2,7,1/2,7,1/2,1/3,1/2,7,1/2,1/5,1/2,1/3,1/2,7]; my(t = 0.1, m = matdiagonal(vector(#F7a,k,F7a[k]^t))*P7a); charpoly(m) mateigen(m); \\ Errors, keep at end of file charpoly(Mod('b, 'b^2 + Mod('a,'a^2+1)), 'newvar) minpoly(Mod(y,x), 'y) pari-2.17.2/src/test/in/polygonal0000644000175000017500000000024214557721031015272 0ustar billbillP(n,s)=((s-2)*n^2-(s-4)*n)>>1; test(s)=for(n=0,10, if (!ispolygonal(P(n,s),s,&N) || N != n, error([n,s]))); for (s=4,10, test(s)) for (s=2^64, 2^64+10, test(s)) pari-2.17.2/src/test/in/forperm0000644000175000017500000000101214567450071014740 0ustar billbilltest(N) = /* compatibility with numtoperm */ { my(i,p); i = 0; forperm(N, p, if (Vecsmall(numtoperm(N,i)) != p, error([N,i,p])); i++ ); } test(1); test(2); test(3); test(4); test(5); forperm([1],p,print(p)) forperm(4,q,print(q)) forperm([1,1,1,3],q,print(q)) forperm([1,2,1,3,1,4],q,print(q)) forperm(Vecsmall([1,2,3,2,3]),q,print(q)) \\ corner cases forperm([],p,print(p)) forperm(Vecsmall([]),p,print(p)) forperm(0,p,print(p)) forperm(1,p,print(p)) \\ errors forperm(p,3,) forperm(1.0,q,) forperm(-1,q,) pari-2.17.2/src/test/in/elltors0000644000175000017500000000514714567450071014767 0ustar billbilldo(e)=elltors(ellinit(e)); do([0, -1, 1, -7820, -263580]) do([1, 0, 1, -171, -874]) do([0, 1, 1, -9, -15]) do([1, 1, 1, -80, 242]) do([0, -1, 1, -10, -20]) do([1, 0, 1, 4, -6]) do([1, -1, 1, -3, 3]) do([1, 1, 1, 35, -28]) do([1, -1, 1, -14, 29]) do([1, 0, 0, -45, 81]) do([1, -1, 1, -122, 1721]) do([1, 1, 1, -135, -660]) do([1, 1, 1, -10, -10]) do([1, 0, 1, -19, 26]) do([1, 0, 0, -1070, 7812]) do([1,0,0,-372368141774940800,87459461608665181808640000]) do([0,706607569223786457,0,-1866575649655837263252847197205171425,-1298198297451307472292414787720779720378300792679274425]) K=nfinit(t^2-5); s=Mod(t,K.pol); E=ellinit([-31/60*s-1/12, -11/9*s-8/3, -11/9*s-8/3, 0, 0], K); T=elltors(E) ellorder(E,T.gen[1]) ellorder(E,T.gen[2]) K=nfinit(t^4+18*t^2-324*t-27);E=ellinit([1,3],K); elltors(E) do(v,K)= { my(e=ellinit(v,K), t=elltors(e)); if (apply(p->ellorder(e,p),t.gen) != t.cyc, error(v)); t; } K=nfinit(t^8-998*t^6+44424*t^4+5106934*t^2+126046063); do([1,3],K) K=nfinit(polcyclo(11,t)); do([0,-1,1,0,0],K) \\ [11] K = nfinit(y^2+7); a1=-209*y-579; a2=26752*y+147840; a3=-10486784*y-57953280; do([a1,a2,a3,0,0],K) \\ [15] a1=(-2*y+15); a2=26*y-14; a3=26*y-14; do([a1,a2,a3,0,0],K) \\ [10,2] a2=-261214369/131072; a4=75626226572068161/68719476736; K=nfinit(y^2+2); do([0,a2,0,a4,0],K) \\ [12,2] K=nfinit(y^2-13); a2=(-4289032*y+15673889)/65536 a4=(-32028469200*y+115490749725)/4194304 do([0,a2,0,a4,0],K) \\ [14] K=nfinit(y^2+11); a1=-2601888534886283704*y+154252733407512581857; a2=-313766195076761969526071169866614175160*y+1735663223649526033628839600302712469280 a3=-43286504429925775681153399339981518914403432663035092419000*y+239448337641930912934754848966237361950084593095601008052000; do([a1,a2,a3,0,0],K) \\ [16,2] K=nfinit(y^4+2002*y^2+116281); a2=12974641/13176900; a4=16/14641; do([0,a2,0,a4,0],K) \\ [3,3] K=nfinit(y^2+3); do([1,-1,0,12,8],K) \\ [20] K=nfinit(y^3-y^2-2*y-2); a=(-5*y^2-y)/2; b=-14*y^2-12*y-8; do([a,b,b,0,0],K) \\ [6,6] K=nfinit(y^4+5*y^2+1); a=9/8; b=7/64; do([a,b,b,0,0],K) \\ [8,4] K=nfinit(y^4+541*y^2+72900); a=431/690; b=-259/529; do([a,b,b,0,0],K) \\ [8,8] K=nfinit(y^16-8*y^15+36*y^14-104*y^13+220*y^12-368*y^11+516*y^10-624*y^9+664*y^8-624*y^7+516*y^6-368*y^5+220*y^4-104*y^3+36*y^2-8*y+1); do([-1,0],K) \\ [9,3] K=nfinit(x^6+3); do([1,-1,1,-14,29],K) E = ellinit([-2147484185^2,0]); elltors(E) ellorder(E, [0,0]) ellorder(E, [2147484185, 0]) ellorder(E, [2147484185/3, 1/11]) E = ellinit([1,1]); P = [72, 611]; ellorder (E, ellmul(E, P, 20)) \\#1660 do([2,x],nfinit(x^2+2)) \\#1920 E=ellinit([0,1,1,-1805632198953220354072743054330,937164323059943920996847199260009653476285734]); elltors(E) pari-2.17.2/src/test/in/mfgaloisrep0000644000175000017500000000201514676526175015614 0ustar billbillgets4(N,CHI,id=1)= { my(mf = mfinit([N,1,CHI],0)); my(F = mfeigenbasis(mf), T = mfgaloistype(mf)); my(S4B = [i | i <- [1,#T], T[i] < 0], i = S4B[id]); my(L = mfgaloisprojrep(mf,F[i])); my(G = galoisinit(L)); [galoisidentify(G), factor(nfdisc(L))]; } S=[[12,124,Mod(87,124)],[12,133,Mod(83,133)],[24,148,Mod(105,148)],[12,171,Mod(94,171)],[12,201,Mod(104,201)],[12,209,Mod(197,209)],[12,224,Mod(95,224)],[24,229,Mod(122,229)],[24,261,Mod(244,261)]]; for(i=1,#S,my([d,N,chi]=S[i]);print(S[i],":",gets4(N,chi))) \\examples from doc mf = mfinit([4*31,1,Mod(87,124)],0); F = mfeigenbasis(mf)[1]; mfgaloistype(mf,F) pol = mfgaloisprojrep(mf,F); gal = galoisinit(pol); galoisidentify(gal) pol4 = polredbest(galoisfixedfield(gal,gal.gen[3])[1]); polgalois(pol4) factor(nfdisc(pol4)) mf = mfinit([4*37,1,Mod(105,148)],0); F = mfeigenbasis(mf)[1]; mfgaloistype(mf,F) pol = mfgaloisprojrep(mf,F); gal = galoisinit(pol); galoisidentify(gal) pol4 = polredbest(galoisfixedfield(gal,gal.gen[3..4])[1]); polgalois(pol4) factor(nfdisc(pol4)) pari-2.17.2/src/test/in/minim0000644000175000017500000001000514567450071014401 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) d = [11870535336,4926369655,32404766,5833735188,-260286973,1176994945,-938673930,1133212506,-1074526606,-70224083,-516302409,2824815072,-4372545965,-3541960809,-934179491,1051267712;4926369655,11870535336,-1490432686,-875900356,3641011352,-133471097,5248732172,5339909303,1977366972,2112029217,1618397291,1453763043,-5074494971,3402204872,-6089917,-2536340118;32404766,-1490432686,11870535336,123881942,1472835948,538053943,-2072520281,-2111014772,-243328180,66329388,-1668343637,5366171257,-1644082716,1999937160,1862466413,-2684624269;5833735188,-875900356,123881942,11870535336,-4482992193,724356870,-2581885607,-1123344860,-5909559285,-374057682,-1737269060,1373350629,-685882364,-2860185796,1915679243,-2582189975;-260286973,3641011352,1472835948,-4482992193,11870535336,-3382162923,-2727082036,-172926336,3957014148,4123782659,-869026456,-712184755,1975235830,598346444,-803583682,764543726;1176994945,-133471097,538053943,724356870,-3382162923,11870535336,4149099372,-1345152733,3238996158,-1859449765,788927568,627981303,-1997619722,-5100674624,1082079081,-4600113518;-938673930,5248732172,-2072520281,-2581885607,-2727082036,4149099372,11870535336,2778219046,565855490,-4509773947,2630869581,161812815,-2518706476,2620761340,1350174537,-1070307221;1133212506,5339909303,-2111014772,-1123344860,-172926336,-1345152733,2778219046,11870535336,1405373352,-94842121,5935267668,1644886404,-4169157373,1191448802,400673054,-137185759;-1074526606,1977366972,-243328180,-5909559285,3957014148,3238996158,565855490,1405373352,11870535336,-1017421319,-2747041871,-2019274686,1090295757,2591545854,433617674,63706423;-70224083,2112029217,66329388,-374057682,4123782659,-1859449765,-4509773947,-94842121,-1017421319,11870535336,-570490848,1731611845,-2658074571,-1297231573,-350469672,-40728837;-516302409,1618397291,-1668343637,-1737269060,-869026456,788927568,2630869581,5935267668,-2747041871,-570490848,11870535336,2791532769,26571128,-1302311714,1214830887,1283425367;2824815072,1453763043,5366171257,1373350629,-712184755,627981303,161812815,1644886404,-2019274686,1731611845,2791532769,11870535336,-3163139204,110178163,-49759695,-1512817003;-4372545965,-5074494971,-1644082716,-685882364,1975235830,-1997619722,-2518706476,-4169157373,1090295757,-2658074571,26571128,-3163139204,11870535336,-55032693,-2820423865,4651789746;-3541960809,3402204872,1999937160,-2860185796,598346444,-5100674624,2620761340,1191448802,2591545854,-1297231573,-1302311714,110178163,-55032693,11870535336,5683626972,-2169747194;-934179491,-6089917,1862466413,1915679243,-803583682,1082079081,1350174537,400673054,433617674,-350469672,1214830887,-49759695,-2820423865,5683626972,11870535336,-5697137302;1051267712,-2536340118,-2684624269,-2582189975,764543726,-4600113518,-1070307221,-137185759,63706423,-40728837,1283425367,-1512817003,4651789746,-2169747194,-5697137302,11870535336]; qfperfection(d) pari-2.17.2/src/test/in/bnfsunit0000644000175000017500000000245414676526175015143 0ustar billbilldefault(parisize,"22M"); \\ overflows 20M bnf=bnfinit(x^3-2); S=idealfactor(bnf,2*3*5*7)[,1]; B=bnfsunit(bnf,S); B[1] B[4] B[5] bnfissunit(bnf,B,x) bnfissunit(bnf,B,x+2) bnfissunit(bnf,B,x+100) bnfissunit(bnf,B,[x+2,20;x,17]) bnfisunit(bnf, x+100) B=bnfunits(bnf) bnfisunit(bnf,x,B) B=bnfunits(bnf,S) bnfisunit(bnf,x+2,B) bnfisunit(bnf,x+100,B) bnfisunit(bnf,[x+2,20;x,17],B) S=bnfsunit(bnf,[]); bnfissunit(bnf,S,2) bnfissunit(bnf,S,-1) bnfissunit(bnf,S,bnf.fu[1]) bnf=bnfinit(x^2+23); S=bnfsunit(bnf,idealprimedec(bnf,2)[1..1]); S[1] S[4] S[5] bnf=bnfinit(x^2-210); S=bnfsunit(bnf,idealprimedec(bnf,2)[1..1]); S[1] S[4] S[5] \\ #2207 setrand(1); L=bnfinit(x^6-68463*x^4-5120808*x^3+1250774892*x^2+192368273328*x+7520491439712,1); S2=vecextract(idealprimedec(L,2), [3,2,1]); S7=idealprimedec(L,7); S13=vecextract(idealprimedec(L,13), [1,3,2]); S5=idealprimedec(L,5); S=concat([S2,S7,S13,S5]); U=bnfunits(L,S); foreach(U[1],u,print(bnfisunit(L,u,U))) \\ from D. Broadhurst's examples P=x^7-22*x^6+169*x^5-568*x^4+1263*x^3-1506*x^2+2295*x+2; setrand(1); bnf=bnfinit(P,1); US=bnfunits(bnf,idealprimedec(bnf,2)); u=US[1]; t=4*(x^2-18*x+85)/x^2*Mod(1,bnf.pol); v=bnfisunit(bnf,t,US); for(i=1,#u,u[i][,2] *= v[i]); P=nfmodprinit(bnf,idealprimedec(bnf,2^32+15)[1]); nfmodpr(bnf,matreduce(matconcat(u~)), P) / nfmodpr(bnf,t,P) pari-2.17.2/src/test/in/lex0000644000175000017500000000143314567450071014065 0ustar billbillv = [0, 2, [1,2], [1,2;3,4], [1,0;1,2], [1,2,3]~, [1,2,3;4,5,6], I]; isvec(x) = type(x) == "t_VEC" || type(x) == "t_COL"; { for (i = 1, #v, for (j = i, #v, s = lex(v[i],v[j]); print([i,j,s]); if (s != -lex(v[j], v[i]), error(2)); if (isvec(v[i]) && lex(Vecsmall(v[i]), v[j]) != s, error(3)); if (isvec(v[j]) && lex(v[i], Vecsmall(v[j])) != s, error(4)); ) ); } lex(1,[1]) lex(1,[2]) lex(1,[0]) lex([1],Mat(1)) lex([1],Mat([1,0]~)) v = Vecsmall([1,2,3]); lex(v, [1,2,3]) lex(v, [1,2]) lex(v, Vecsmall([1,2])) lex(v, Vecsmall([1,2,3,4])) lex(v, Vecsmall([1,2,4])) lex(v, Vecsmall([1,2,2])) lex(v, [1,2,4]) lex(v, [4,2,3]) lex(v, [0,2,3]) lex(v, [[1,2,3],2,3]) lex(v, [[0,2,3],2,3]) lex(v, [[],2,3]) lex(v, [Vecsmall([]),2,3]) lex(v, [Vecsmall(1),2,3]) pari-2.17.2/src/test/in/ellheight0000644000175000017500000000142214567450071015240 0ustar billbill\\package:elldata { K = nfinit(t^3-2); d = #K.zk; forell(E, 1, 1000, my(e,N,f,v,P,F,FK); N = ellconvertname(E[1])[1]; v = [1/60,7131/3600,11/12,5/12]; F = ellinit(E[2]); FK = ellinit(E[2],K); e = ellchangecurve(F, v); eK= ellchangecurve(FK, v); P = E[3]; for(i=1,#P, my(Q=ellchangepoint(P[i],v)); my(hF=ellheight(F,P[i])); if (!ellisoncurve(e,Q),error("e:",Q)); if (!ellisoncurve(eK,Q),error("eK:",Q)); my(hFK=ellheight(FK,P[i])/d); if (abs(hF-hFK)>10^-15,error("height/FK:",E[1],":",[hF,hFK,exp(hF-hFK)])); my(he=ellheight(e,Q)); if (hF!=he,error("height:",E[1],":",[hF,he])); my(hK=ellheight(eK,Q)/d); if (abs(hF-hK)>10^-15,error("height/K:",E[1],":",[Q,exp(hF-hK)])); ); ) } pari-2.17.2/src/test/in/zncoppersmith0000644000175000017500000000104214567450071016176 0ustar billbillp = 10^30+57; q = 10^31+33; N = p*q; p0 = p % 10^20; z = zncoppersmith(10^19*x + p0, N, 10^12, 10^29) gcd(z[1]*10^19 + p0, N) == p setrand(1); P = 4625048078322670354774415943228839104529734663852281547523640; e = 3; X = floor(N^0.3); x0 = 1339991002000615200; C = lift( (Mod(x0,N) + P)^e ); z = zncoppersmith((P+x)^3 - C, N, X) z[1] == x0 zncoppersmith(Pol([192378,19237198,912831923,12938719]), 2*3*5*7, 1000.5, 29.5) \\ ERRORS p=nextprime(2^20);q=nextprime(2*p);n=q*p;v=n+1;P=x^2-1; zncoppersmith(v*P,v*n,p,p*v) zncoppersmith(x/2, 10, 5, 5) pari-2.17.2/src/test/in/history0000644000175000017500000000014614567450071014776 0ustar billbill2 3 4 5 %`````` %```` %3 % %#3;1 %#```;1 %#;1 default(histsize,1) 1; %`` default(histsize,10) %`` %13 pari-2.17.2/src/test/in/ellff0000644000175000017500000000771514760123736014376 0ustar billbilldefault(parisize,"10M"); \\ overflows 8M test(p,n=0,v='a,w=1)= { my(a=if(n,ffgen(p^n,v),p)); my(E=ellinit([w,1,1-w,0,a+3],a)); my(G=ellgenerators(E)); if (#G==0,return); [d1]=ellgroup(E); my(P=random(E)); G=G[1]; if(ellorder(E,G)!=d1,error([p,n,0])); if(ellmul(E,G,d1)!=[0],error([p,n,1])); if(ellmul(E,P,d1)!=[0],error([p,n,2])); if(d1%ellorder(E,P)!=0,error([p,n,3])); if (d1<10^7, P=ellmul(E,G,1023); if(elllog(E,P,G)!=1023%d1,error([p,n,4])); ); } test(2); test(2,78); test(2,100); test(2,255); test(2,1,,0); test(2,2,,0); test(2,4,,0); test(2,6,,0); test(2,101,,0); test(3,,,0); test(3,50,,0); test(3,51,,1); test(5); test(5,3,,0); test(5,6,,0); test(5,50,,0); test(7,3); test(7,51); test(11,2); test(11,12); test(11,18); test(11,19,,5); test(13,41); test(17,2); test(1009,3); test(1013,7); test(1009,11,'x); test(17); test(41); test(41,13); test(1073741827); test(nextprime(2^65),2); p=18446744073709551557; e=ellinit([3,3],p);N=ellcard(e); setrand(1); g=ellgenerators(e) ellorder(e,g[1]) a=ffgen(101^3,'a); E=ellinit([1,3],a); E.j E.disc P=random(E);Q=random(E); R=elladd(E,P,Q); elladd(E,ellsub(E,R,P),ellneg(E,Q)) N=ellcard(E);ellmul(E,P,N) checkorder(E, N)= { for(i=1,4, P=random(E); if(ellmul(E,P,N)!=[0],error(a))); } check(a)= { my(E,Et,P,N); E=ellinit(a); Et=elltwist(E); if (ellap(Et)!=-ellap(E),error("twist:",a)); N=ellcard(E); if ((N==1)!=(#random(E)==1),error(a)); checkorder(E, N); ellgenerators(E); } { for(a=1,8, g = ffprimroot(ffgen(2^a,'t)); for(i=0,2^a-2, check([g^i]))); for(a=1,6, g = ffprimroot(ffgen(3^a,'t)); for(i=0,3^a-2, check([g^i]))); for(a=1,4, g = ffprimroot(ffgen(5^a,'t)); for(i=0,5^a-2, check([g^i]))); } testss(n,N)= { my(a); a=ffprimroot(ffgen([2,n],'a)); for(i=1,N, E=ellinit([0,0,random(a),random(a),random(a)]); if(#E, checkorder(E,ellcard(E)))); } for(i=1,8,testss(i,min(1000,2^(3*i)))); checkt(p,n,f,B=100)= { my(a=ffgen(p^n,'a)); for(i=1,B, my(E,Et,N,b); until(b,b=random(a)); E=ellinit(if(f==0,[0,b],f==1,[b,0],[b^2,b^3])); if(#E==0,next); Et=elltwist(E); if (ellap(Et)!=-ellap(E),error("twist:",[p,n,f])); N=ellcard(E); if(#ellmul(E,random(E),N)>1,error([p,n,f],b))); } checkt(3,5,0); checkt(3,6,0); checkt(3,5,1); checkt(3,6,1); checkt(3,5,2); checkt(3,6,2); checkt(7,5,0); checkt(7,6,0); checkt(11,5,0); checkt(11,6,0); checkt(7,5,1); checkt(7,6,1); checkt(13,5,1); checkt(13,6,1); checkt(11,6,2); checkt(13,5,2); checkt(18446744073709551667,2,0,10); checkt(18446744073709551667,3,0,10); checkt(18446744073709551667,2,1,10); checkt(18446744073709551667,3,1,10); checkt(18446744073709551667,2,2,10); checkt(18446744073709551667,3,2,10); checkt(18446744073709551629,2,0,10); checkt(18446744073709551629,3,0,10); checkt(18446744073709551629,2,1,10); checkt(18446744073709551629,3,1,10); checkt(18446744073709551629,2,2,10); checkt(18446744073709551629,3,2,10); E=ellinit([a1,a2,a3,a4,a6]*Mod(1,2)); elldivpol(E,2) check(q)= { my(g,E,x = 1,y); g = ffprimroot(ffgen(q,'t)); E = ellinit([g]); for(i=1,10, x *= g; y = ellordinate(E,x); for(i=1,#y, if (!ellisoncurve(E,[x,y[i]]), error([x,y]))) ); } check(2^4) check(3^4) check((2^64+13)^4) checkext(p)= { b=ffgen(p,'a); E=ellinit([1,0,0,0,1],p); a=ffgen(p^6,'b); F=ellinit(E,a); P=random(F); if (!ellisoncurve(F,P),error(p)); if(!ellisoncurve(F,ellmul(F,P,2)),error(p)); } checkext(5) checkext(3) checkext(2) check2(p,B=10)= { my(a=ffgen([p,12],'a)); my(E=ellinit([1,(a+1)^(p^9+p^6+p^3+1)],a)); if(!E,return()); my(N=ellcard(E)); for(i=1,B, if(#ellmul(E,random(E),N)>1,error(i,":",b))); } forprime(p=2,100,check2(p)); check2(nextprime(2^16)); check2(nextprime(2^32)); check2(nextprime(2^64)); z = ffgen(41^16); E=ellinit([z,z]); ellcard(E) z = ffgen([41,13]); E = ellinit([z^28]);ellcard(E) a=ffgen(('a^3-'a^2-2*'a+1)*Mod(1,23)); E=ellinit([a^2-2,0,1,-14*a^2+9*a+19,-69*a^2+63*a+85],a); for(i=1,100,setrand(i);my(F=E);if(ellcard(F)!=12040,error(i))); pari-2.17.2/src/test/in/ramanujantau0000644000175000017500000000056614676526175016003 0ustar billbilldefault(parisize,"10M"); \\ 8M overflows tauvec(N) = Vec(q*eta(q + O(q^N))^24); N = 10^3; vector(N, n, ramanujantau(n)) == tauvec(N) ramanujantau(10^6+3) ramanujantau(10^7+3,16) ramanujantau(10^7+3,24) ramanujantau(-1) ramanujantau(factor(-1)) ramanujantau(factor(0)) ramanujantau(factor(6)) ramanujantau(factor(6),24) ramanujantau(factor(-6),24) \\ ERRORS ramanujantau(x) pari-2.17.2/src/test/in/solve0000644000175000017500000000067514676526175014446 0ustar billbillhardy(x)=real(zeta(1/2+I*x)*exp(I*(arg(gamma((1/2+I*x)/2))-log(Pi)/2*x))); solve(x=1,20,hardy(x)) solvestep(x=1,100,1,hardy(x)) #solvestep(x=0,10000,2,sin(x)) exponent(solve(x=-oo,oo,exp(x)-2)-log(2)) exponent(solve(x=-oo,2,exp(x)-2)-log(2)) exponent(solve(x=0,oo,exp(x)-2)-log(2)) exponent(solve(x=-0.001,Pi/2-0.01,sin(x)+cos(x)-1)) \\ #2412 \\ Errors, keep at end solvestep(x=1,100,-1,hardy(x)) solve(x=-oo,0,exp(x)-2) solve(x=2,oo,exp(x)-2) pari-2.17.2/src/test/in/padic0000644000175000017500000000635514760123736014365 0ustar billbillpadicprec(1,2) padicappr(x,O(2)) padicappr('x,Mod(0,'t)+O(7^10)) padicappr(x^2+Mod(O(3^2),t^2+1),Mod(0,t^2+1)+O(3^2)) padicappr(x^2+25,5+O(5^2)) factorpadic(y^2+3^5,3,5) factor(x^2*(1+O(5^2))) factorpadic(x^2*(x+1)^3*(x+2)*(1+O(5^2)), 5, 2) factorpadic(x^2, 5, 2) factorpadic(3*x + O(2^5),2,5) p=2^64+13; liftint(padicappr((x-1)^30+p^30, 1+O(p^40))) test(p, e = 1)= { my (N = 7*p^2); for (i=0,10,if (!ispower(i+O(p^e), N), print([i,p,e]))); for (i=1,10,if (!ispower((i+O(p^e))^N, N), error([i,p,e]))); } test(2) test(2,2) test(2,3) test(3) test(3,3) test(11,3) test(nextprime(2^64),3) polrootspadic(x^3-x+8, 2, 6) f = subst(x^3-x+8, x, x + Mod(y,y^2+y+1)); padicappr(f, Mod(1+O(2^10)-y, y^2+y+1)) polrootspadic(f, [y^2+y+1,2], 6) polrootspadic(2*y*f, [y^2+y+1,2], 6) \\#1424 lift(1/2 + O(2)) s=3+3^2+O(3^5) t=2+2^2+O(2^5) f=[cosh,sinh,tanh,cotanh]; { for (i=1,#f, print(f[i](s)); print(f[i](O(x))); ) } gamma(s) gamma(t) p=2^64+13; gamma(3 + O(p^2)) gamma(-3 + O(p^2)) lngamma(17+O(3^10)) lngamma(17/3+O(3^10)) gamma(1/5+O(2^2)) gamma(1/5+O(2^3)) gamma(123+O(2^7)) gamma(123+O(2^8)) gamma(29+O(2^5)) gamma(29+O(2^6)) gamma(495+O(5^101)) psi(s) psi(t) psi(1/5+O(2^2)) psi(1/5+O(2^3)) psi(123+O(2^7)) psi(123+O(2^8)) psi(29+O(2^5)) psi(29+O(2^6)) [psi(29+O(2^6),i)|i<-[0..10]] psi(495+O(5^101)) psi(990566545678011756250681 + O(3^51)) psi(495+O(3^51)) [psi(O(7^10),i)|i<-[0..10]] I + O(5^3) log(1+4+O(2^10)) log(1+3+O(3^10)) log(1+5+O(5^10)) log(1+101+O(101^10)) T = x^12 + 208*x^6 + 64; phi = polcyclo(9); prec = 10; p = 3; v = factorpadic(T, p, prec)[,1]; liftall( padicappr(phi, Mod(-2+O(p^prec), v[1])) ) T = teichmuller([17,10]); for(i=1,16,if (teichmuller(i+O(17^10),T) != teichmuller(i+O(17^10)), error(i))) \\#1793 padicappr(x^3+1,-2+O(2^5)) padicappr(x^3+1,Mod(-2+O(2^5),y^3+3)) newtonpoly(x^4+3*x^2+27*x+x+81,3) newtonpoly(x^4+3*x^2+27*x,3) newtonpoly(x^4+y*x^2+y^3*x,y) \\#1863 f=x^9+42*x^7-16*x^6+504*x^5-336*x^4+1560*x^3-1008*x^2+64; factorpadic(f,2,3) \\#1876 factorpadic(2*x^4+x^2,2,2) polrootspadic(2*x^4+x^2,2,2) \\#1905 polrootspadic(x,3,10) T = y^32 - 8*y^31 + 132*y^30 - 872*y^29 + 7978*y^28 - 43984*y^27 + 278592*y^26 - 1280230*y^25 + 6016836*y^24 - 22767800*y^23 + 83696182*y^22 - 259841076*y^21 + 772364746*y^20 - 1922859142*y^19 + 4097944748*y^18 - 7433491240*y^17 + 18853991151*y^16 - 45141140592*y^15 + 200971321044*y^14 - 495395957226*y^13 + 841610071252*y^12 - 313005796720*y^11 - 2973750987680*y^10 + 5018975002436*y^9 + 29214528458769*y^8 - 73301518803394*y^7 + 195023156598096*y^6 - 265879507425724*y^5 + 441249179094943*y^4 - 310432057395848*y^3 + 286093590632140*y^2 - 68137080187062*y + 169311946842369; fa=factorpadic(T,2,1); [poldegree(P) | P <- fa[,1]] fa=factorpadic(T,2,15); [poldegree(P) | P <- fa[,1]] T=polsubcyclo(271,9); factorpadic(T,3,7)[4,1] polteichmuller(0*x^0,5,10) polteichmuller(2*x^0,5,10) polteichmuller(3*x-2,5,10) checkfrob(P,p,e)= { my(Q=polteichmuller(P,p,e)); if(valuation(content(minpoly(Mod(x,Q)^p)-Q),p)x[1],c) primecertisvalid(c) c[1][1]++; primecertisvalid(c) c=primecert(p,1) primecertisvalid(c) c[2][4][1]++; primecertisvalid(c) isprime(18446744073709551557, 3) isprime(437256732647720373392867051041, 3) isprime(10^472+69169) \\ would trigger umr in 2.2.11: red_montgomery() isprime(85070591730234615857870057863360474949); stripgit(c) = strjoin(strsplit(c, "\n")[^6], "\n"); primecert(1) primecert(2) primecert(18446744073709551557); primecert(18446744073709551629); primecertisvalid(primecert(18446744073709551557)) primecertisvalid(primecert(18446744073709551629)) cert = [[100000000000000000000000000000000069, 546867911035452074, 2963504668391148, 0, [33871007718198692871763537900223244, 37634983931409678910567952612637528]], [33743830764501150277, -11610830419, 734208843, 0, [16662256621764551072, 717141744113721531]]]; primecertexport(cert) primecertexport(cert,2) print(stripgit(primecertexport(cert,1))) setrand(1); cert = primecert(104847485105117585996751891729845662843364912851385667939830682169316283979217507303783276087270751367988006094556790411454173939259895051951577787259); print(stripgit(primecertexport(cert,1))) print(primecertexport(cert,2)) primecertisvalid(primecert(16285004170961712447000975451705488808641461042245717587564868626116060638362995676584291019647333487131164585910692526519723394628478390124381641415798852319473605083279694798821564187404325769317838108581838244806431287065930206020985599594140650596158360451027455871094479408389113611410568437054557)) C=primecert(2^500+55,,250);#C C2=primecert(C);#C2 primecertisvalid(C2) \\ #2166 addprimes(275509565477848842604777623828011666349761); isprime(polcyclo(712,2),1) \\ Errors, keep at end of file primecertexport([0],1) primecertexport([],1) pari-2.17.2/src/test/in/galoischartable0000644000175000017500000000367114567450071016427 0ustar billbill\\ package: galpol inn(len, c1, c2, f) = simplify(lift(sum(i=1,#len,len[i]*c1[i]*subst(c2[i],y,1/y))*Mod(1,f))); testchar(G, n = poldegree(G.pol))= { my(cl = galoisconjclasses(G)); my(len = apply(length, cl)); my([ct,e] = galoischartable(G)); my(dim = simplify(ct[1,])); my(one = vector(#dim,k,1)); my(f = polcyclo(e,y)); if (#len!=#dim, error("dim1")); if (sum(i=1,#dim,dim[i]^2)!=n,error("dim2")); if (sum(i=1,#len,len[i])!=n,error("dim3")); M=matrix(#len,#dim,i,j,inn(len,ct[,i],ct[,j],f)); if(M!=n*matid(#len),error("columns")); M=matrix(#len,#dim,i,j,inn(one,ct[i,],ct[j,],f)); if(!matisdiagonal(M),error("lines")); for(i=1,#len,if(M[i,i]<0,error("diag"))); } { for(i=1,16, for(j=1,galoisgetpol(i), [pol,den] = galoisgetpol(i,j,1); gal = galoisinit(pol,den); testchar(gal); )); } \\#1931 G=galoisinit(x^24-24*x^22+253*x^20-1540*x^18+5984*x^16-15488*x^14+27026*x^12-31448*x^10+23540*x^8-10528*x^6+2416*x^4-192*x^2+1); setrand(211); testchar(G) dopol(G)= { my([T,o]=galoischartable(G)); for(i=1,#T,printsep(":", T[,i], galoischardet(G,T[,i],o), galoischarpoly(G,T[,i],o))); } G=galoisinit(x^10-2*x^9-20*x^8+2*x^7+69*x^6-x^5-69*x^4+2*x^3+20*x^2-2*x-1); dopol(G) {G = [Vecsmall([1, 2, 3, 4, 5]), Vecsmall([1, 5, 4, 3, 2]), Vecsmall([2, 1, 5, 4, 3]), Vecsmall([2, 3, 4, 5, 1]), Vecsmall([3, 2, 1, 5, 4]), Vecsmall([3, 4, 5, 1, 2]), Vecsmall([4, 3, 2, 1, 5]), Vecsmall([4, 5, 1, 2, 3]), Vecsmall([5, 1, 2, 3, 4]), Vecsmall([5, 4, 3, 2, 1])];} dopol(G) G=[[Vecsmall([28,40,13,30,4,19,22,7,8,32,25,38,33,16,29,18,14,24,21,9,3,1,11,5,36,23,35,10,34,20,2,37,27,6,12,41,31,42,15,17,39,26]),Vecsmall([3,38,1,42,21,8,12,6,11,29,9,7,17,23,30,34,13,35,31,33,5,41,14,36,37,28,32,26,10,15,19,27,20,16,18,24,25,2,40,39,22,4])],Vecsmall([21,2])]; testchar(G, 42); \\ ERRORS S3=[[Vecsmall([2,1,3]),Vecsmall([2,3,1])],Vecsmall(6)]; galoischartable(S3) pari-2.17.2/src/test/in/perm0000644000175000017500000000054614567450071014244 0ustar billbill{ forperm(4,p, printsep(":",Vec(p),permorder(p),permsign(p),permcycles(p))); } { my(s=0,m=1,q=[]); forprime(p=1,60, s += p; m *= p; q = concat([q,[s+2-p..s],s+1-p])); q = Vecsmall(q); [permorder(q),permsign(q)] } \\error permsign(Vecsmall([1,1])) permsign(Vecsmall([1,2,1])) permorder(Vecsmall([1,2,1])) permcycles(Vecsmall([1,2,1])) pari-2.17.2/src/test/in/alglattices0000644000175000017500000002200114702763267015570 0ustar billbill\\Tests for lattices, orders and makeintegral in algebras Sn(n) = [Vecsmall(numtoperm(n,i)) | i <- [0..n!-1]]; D2n(n)= { [[vectorsmall(2*n,i,if(i==n,1,i==2*n,n+1,i+1)), vectorsmall(2*n,i,if(i==1,n+1,i==n+1,1,2*n+2-i))],Vecsmall([n,2])]; } firstprime1mod(n) = { p = 2; while(p%n!=1, p=nextprime(p+1)); p; } al = alginit(nfinit(y^2+7), [-1,-1]); a = [1,1,-1/2,1,1/3,-1,1,1]~; mt = algtomatrix(al,a,1); lat = alglathnf(al,mt); print(type(lat)=="t_VEC"); print(#lat == 2); print(type(lat[1])=="t_MAT"); print(type(lat[2])=="t_FRAC"); print(type(lat[1][1,1])=="t_INT"); print(lat[1][2,1]==0); c = [1,1,-1,1,0,-1,1,1]~; mt = algtomatrix(al,c,1); lat = alglathnf(al,mt); print(lat[2]==1); print(lat == alglathnf(al,c)) lat = alglathnf(al,matid(8)*2); print(lat[2]==2); b = [1,0,-1,1,0,-1,2,1]~; mtb = algtomatrix(al,b,1); lat = alglathnf(al,matconcat([mt,mtb])); print(lat==[1,1]); print(lat == alglathnf(al,[mt,mtb])); lat = alglathnf(al,matconcat([7*mt/2,7*mtb/2]),21/2); print(lat==[1,7/2]); lat1 = alglathnf(al,a); lat2 = alglathnf(al,c); N = algdim(al,1); lat3 = [11*matid(N),1]; lat4 = [3*matid(N),1]; print(alglatinter(al,lat3,lat4) == [matid(N),33]); print(alglatadd(al,lat3,lat4) == [matid(N),1]); print(alglatadd(al,lat1,alglatadd(al,lat2,lat3)) == alglatadd(al,alglatadd(al,lat1,lat2),lat3)); print(alglatinter(al,lat1,alglatinter(al,lat2,lat3)) == alglatinter(al,alglatinter(al,lat1,lat2),lat3)); {print(alglatinter(al, alglatadd(al,lat1,lat2), lat3) == alglatadd(al, alglatinter(al,lat1,lat3),alglatinter(al,lat2,lat3)));} inter1 = alglatinter(al,lat1,lat2,&sum1); sum2 = alglatadd(al,lat1,lat2,&inter2); print(inter1==inter2); print(sum1==sum2); print(sum1[2]==1/6); print(inter1[2]==1); print(alglatindex(al,lat1,lat2)); print(alglatmul(al,lat1,lat2)); print(alglatmul(al,b,lat1)); print(alglatmul(al,lat2,b)); print(alglatmul(al,b/10,lat1)); print(alglatmul(al,lat2,b/10)); print(alglatlefttransporter(al,lat1,lat2)); print(alglatrighttransporter(al,lat1,lat2)); setrand(88); aa = algrandom(al,10); print(alglathnf(al,aa/10,matdet(algtomatrix(al,aa,1))/10)==alglathnf(al,aa/10)); print(alglatcontains(al,lat1,a)); col = [3,6,-5,1,23,2,0,1]~; print(alglatelement(al,lat1,col)); testlataddinter()= { my(lat=[0,0,0],int12,int23,sum12,index,elt1, elt2,tr12L,tr23R,col1,col2); my(lat=[0,0,0],int12,int23,sum12,index,elt,tr12L,tr23R); elt1=algrandom(al,5)/random([1,8]); elt2=algrandom(al,5)/random([1,8]); elt=algrandom(al,5); for(i=1,3,lat[i]=alglathnf(al,algrandom(al,2)/random([1,8]))); sum12 = alglatadd(al,lat[1],lat[2],&int12); if(alglatadd(al,lat[1],alglatadd(al,lat[2],lat[3],&int23)) != alglatadd(al,sum12,lat[3]), print("error (add)",lat); return(0) ); if(alglatinter(al,lat[1],int23) != alglatinter(al,int12,lat[3]), print("error (inter)",lat); return(0) ); if(!alglatsubset(al,lat[1],sum12,&index) || (index!=alglatindex(al,lat[1],sum12)), print("error (subset/index)",lat); return(0) ); if(alglatsubset(al,lat[1],lat[2]) != (lat[2]==sum12), print("error (subset)",lat); return(0) ); if(alglatindex(al,lat[2],lat[3])*alglatindex(al,lat[3],lat[2])!=1, print("error (index)", lat); return(0) ); if(alglatmul(al,lat[1],alglatmul(al,lat[2],lat[3])) != alglatmul(al,alglatmul(al,lat[1],lat[2]),lat[3]), print("error (latmul)", lat); return(0) ); if((alglatmul(al,elt1,alglatmul(al,elt2,lat1)) != alglatmul(al,algmul(al,elt1,elt2),lat1)) || (alglatmul(al,alglatmul(al,lat2,elt1),elt2) != alglatmul(al,lat2,algmul(al,elt1,elt2))), print("error (latmul elt)", lat, elt1, elt2); return(0) ); tr12L = alglatlefttransporter(al,lat[1],lat[2]); tr12L = tr12L[1]*tr12L[2]; for(i=1,8, if(!alglatsubset(al,alglatmul(al,tr12L[,i],lat[1]),lat[2]), print("error (left transporter)", lat, i); return(0) ) ); tr23R = alglatrighttransporter(al,lat[2],lat[3]); tr23R = tr23R[1]*tr23R[2]; for(i=1,8, if(!alglatsubset(al,alglatmul(al,lat[2],tr23R[,i]),lat[3]), print("error (right transporter)", lat, i); return(0) ) ); for(i=1,5, col1 = [random([-10,10]) | j <- [1..8]]~; if(!alglatcontains(al,lat1,alglatelement(al,lat1,col1),&col2) || col1!=col2, print("error (latelement)", lat, col1); return(0) ); if(alglatcontains(al,lat1,col1,&col2) && col1!=alglatelement(al,lat1,col2), print("error (latcontains)", lat, col1); return(0) ) ); 1 }; setrand(1); nb = 250; for(i=1,nb,if(!testlataddinter(),print(i);break())); print("make integral"); mt = [matid(2),[0,-1/4;1,0]]; mt2 = algmakeintegral(mt); algisassociative(mt2) al = algtableinit(mt2); algissimple(al) {mt = [matid(4), [0,-1,0,0;1,0,0,0;0,0,0,-3;0,0,1/3,0], [0,0,2/9,0;0,0,0,-2/3;1,0,0,0;0,-1/3,0,0], [0,0,0,2;0,0,2/3,0;0,3,0,0;1,0,0,0]];} mt2 = algmakeintegral(mt); algisassociative(mt2) al = algtableinit(mt2); algissimple(al) mt = algmultable(alginit(nfinit(y),[-3,7])); mt == algmakeintegral(mt) print("integral subalg"); m = matcompanion(x^4+1); mt = [m^i | i <- [0..3]]; al = algtableinit(mt); B = [1,0;0,0;0,1/2;0,0] al2 = algsubalg(al,B); algisassociative(al2[1]) al2[2] print("bug in subalg when first vector is not 1"); mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]]; A = algtableinit(mt,2); B = algsubalg(A,[0,1; 0,0; 1,0]); algissimple(B[1]) print("bug trivial intersection"); al = alginit(nfinit(y),1); lat = [Mat(1),1]; alglatinter(al,lat,lat) alglatinter(al,lat,lat,&s) s alglatadd(al,lat,lat) al = alginit(nfinit(y^2-2),1); lat = [[1,1;0,1],1]; alglatinter(al,lat,lat) alglatadd(al,lat,lat) alglatinter(al,lat,lat,&s) s print("image of lifts in algsimpledec"); testidem(al)={ dec = algsimpledec(al,1)[2]; Le = [d[3][,1] | d <- dec]; for(i=1,#Le, ei = Le[i]; if(algsqr(al,ei)!=ei, print(0); return;); for(j=i+1,#Le, ej = Le[j]; if(algmul(al,ei,ej)!=0, print(0); return;); ); ); print(1); } {for(n=2,4, al = alggroup(Sn(n),7); testidem(al); );} {for(n=2,5, al = alggroupcenter(Sn(n),11); testidem(al); );} {for(n=2,4, p = firstprime1mod(2*n); al = alggroup(D2n(n),p); testidem(al); );} {for(n=2,5, al = alggroupcenter(Sn(n),11); testidem(al); );} /* \\needs galpol package {for(i=1,267, print("i=",i); [pol,den] = galoisgetpol(64,i,1); gal = galoisinit(pol,den); al = alggroupcenter(gal,193); testidem(al); );}*/ print("lattices in al_CSA"); setrand(1); nf = nfinit(y^2-7); a = y; b = y+1; ab = lift(Mod(a*b,nf.pol)); mti = [0,a,0,0;1,0,0,0;0,0,0,a;0,0,1,0]; mtj = [0,0,b,0;0,0,0,-b;1,0,0,0;0,-1,0,0]; mtk = [0,0,0,-ab;0,0,b,0;0,-a,0,0;1,0,0,0]; mt = [matid(4),mti,mtj,mtk]; al = alginit(nf,mt); x1 = [0,2/7,7,-1,0,0,1/5,-5]~; x2 = [-1/7-3*y,y+3/5,y,20+y]~; lat1 = alglathnf(al,x1); lat2 = alglathnf(al,x2); lat3 = alglathnf(al,concat([8/5*matid(8),[1,0,0,1,0,1,1,1]~])); alglatsubset(al,alglatmul(al,alglatlefttransporter(al,lat1,lat3),lat1),lat3) alglatadd(al,lat1,alglatadd(al,lat2,lat3))==alglatadd(al,alglatadd(al,lat1,lat2),lat3) {alglatinter(al,lat1,alglatinter(al,lat2,lat3)) == alglatinter(al,alglatinter(al,lat1,lat2),lat3)} print("examples from docu") al = alginit(nfinit(y^2+7), [-1,-1]); lat1 = alglathnf(al,[1,1,0,0,0,0,0,0]~); lat2 = alglathnf(al,[1,0,1,0,0,0,0,0]~); latsum = alglatadd(al,lat1,lat2,&latinter); matdet(latsum[1]) matdet(latinter[1]) latinter = alglatinter(al,lat1,lat2,&latsum); matdet(latsum[1]) matdet(latinter[1]) alglatsubset(al,lat1,lat2) alglatsubset(al,lat1,latsum,&index) index alglatindex(al,lat1,lat2) lat1==lat2 a1 = [1,-1,0,1,2,0,1,2]~; a2 = [0,1,2,-1,0,0,3,1]~; lat1 = alglathnf(al,a1); alglatcontains(al,lat1,a1,&c) c c = [1..8]~; elt = alglatelement(al,lat1,c); alglatcontains(al,lat1,elt,&c2) c==c2 lat2 = alglathnf(al,a2); lat3 = alglatmul(al,lat1,lat2); matdet(lat3[1]) lat3 == alglathnf(al, algmul(al,a1,a2)) lat3 == alglatmul(al, lat1, a2) lat3 == alglatmul(al, a1, lat2) lat1 = alglathnf(al,[1,-1,0,1,2,0,5,2]~); lat2 = alglathnf(al,[0,1,-2,-1,0,0,3,1]~); tr = alglatlefttransporter(al,lat1,lat2); alglatsubset(al,alglatmul(al,tr[1][,7]*tr[2],lat1),lat2) alglatsubset(al,alglatmul(al,lat1,tr[1][,7]*tr[2]),lat2) lat1 = alglathnf(al,matdiagonal([1,3,7,1,2,8,5,2])); lat2 = alglathnf(al,matdiagonal([5,3,8,1,9,8,7,1])); tr = alglatrighttransporter(al,lat1,lat2); alglatsubset(al,alglatmul(al,lat1,tr[1][,8]*tr[2]),lat2) alglatsubset(al,alglatmul(al,tr[1][,8]*tr[2],lat1),lat2) \\end examples print("bad inputs"); al = alginit(nfinit(y^2+7), [-1,-1]); alglathnf(al,0); alglathnf(al,Mat([0,0,0,0,0,0,0,0])); alglathnf(al,[0;0;0;0;0;0;0;0]); fakemat = matid(8); fakemat[5,6] = [] alglathnf(al,fakemat); alglathnf(al,matid(8)*0); fakemat = matid(8); fakemat[1,1] = 0; alglathnf(al,fakemat); lat = alglathnf(al,matconcat([mt*0,mt*0])); a = [[0,0]~,[0,0]~;[0,0]~,[0,0]~]; lat1 = alglathnf(al,a); lat2 = alglathnf(al,c); col = [3,6,-5,1,23,2,0,1]~; print(alglatelement(al,lat1,col~)); a = [1,1,-1/2,1,1/3,-1,1,1]~; b = [1,0,-1,1,0,-1,2,1]~; alglatmul(al,a,b); mt = [matid(2),[0,-1/4;1/2,0]]; algmakeintegral(mt); mt = [[1,0;-1,1],[0,-1/4;1,0]]; algmakeintegral(mt); algmakeintegral('x,1); alglatmul(al,lat1,[matdiagonal([1,1,0,1,1,1,1,1]),1]); \\end bad inputs pari-2.17.2/src/test/in/interpol0000644000175000017500000000372314676526175015147 0ustar billbillpolinterpolate([2,3,4]) polinterpolate([2,3,4] * Mod(1,7)) polinterpolate([2,3,4] * Mod(1,7),, 0) polinterpolate([1,2,4], [2,3,4]) polinterpolate([1,2,4] * Mod(1,7), [2,3,4], 0) polinterpolate([1,2,4], [2,3,4], 1.5) polinterpolate([1,2,4], [2,3,4], 1.5, &e); e polinterpolate([1,2],[0,0]) polinterpolate([],[]) polinterpolate([1],[2]) polinterpolate([],[],Mod(1,2)) polinterpolate([0],[0],Mod(1,2)) polinterpolate([1],[1],Mod(1,2)) z = varhigher("z", x); \\ so variable ordering is z < x < y test(a,b,v) = my(f = polinterpolate(a,b,v)); [f, variable(f)]; test([], [], 1) test([], [], x) test([], [], y) test([], [], z) test([], [], z + 1) \\ expect [0, z], currently returns [0, 0] test([0], [0], 1) test([0], [0], x) test([0], [0], y) test([0], [0], z) test([0], [0], z + 1) \\ expect [0, z], currently returns [0, 0] test([1], [1], 1) test([1], [1], x) test([1], [1], y) test([1], [1], z) test([1], [1], z + 1) test([1], [x], 1) test([1], [x], x) test([1], [x], y) test([1], [x], z) test([1], [x], z + 1) test([0, 1], [0, x], 1) test([0, 1], [0, x], x) test([0, 1], [0, x], y) test([0, 1], [0, x], z) test([0, 1], [0, x], z + 1) test([x, x + 1], [0, 1], 1) test([x, x + 1], [0, 1], x) test([x, x + 1], [0, 1], y) test([x, x + 1], [0, 1], z) test([x, x + 1], [0, 1], z + 1) \\ #2278 { L=[171.85709359795519703262758396375873346, 172.07370935058205701768102781476945962, 172.35728325338672545837466598657524599, 172.41182832475750407455714929729713304, 172.55312573251184046455435932144446488, 172.78621879385058735425749037479266039, 172.98741734512381337317617661926866615, 173.28085540159446122341219189646960445]; exponent(polinterpolate(L, L) - x)} polfromroots([1..10]) polfromroots([1..10],y) polfromroots([1..10]*Mod(1,11)) polfromroots([1..10]*Mod(1,11),y) T=(a^2-3*a+6)*Mod(1,13);polfromroots(vector(168,i,Mod(a,T)^i)) w=ffprimroot(ffgen([13,2],'w));polfromroots(vector(168,i,w^i)) w=ffprimroot(ffgen([2,7],'w));polfromroots(vector(127,i,w^i),u) /* ERROR */ polfromroots([1,x,x^2]) pari-2.17.2/src/test/in/dirpowers0000644000175000017500000000137514676526175015332 0ustar billbilldirpowers(-1,1) dirpowers(0,1) dirpowers(4,0) dirpowers(4,1) dirpowers(4,2) dirpowers(4,3) dirpowers(4,1/2) dirpowerssum(-1,1) dirpowerssum(0,1) dirpowerssum(4,1) dirpowerssum(4,-1) dirpowerssum(4,-1, n->kronecker(-23,n)) dirpowerssum(10^5,-1) dirpowerssum(10^4,-1,n->kronecker(-23,n)) dirpowerssum(10^3,-1,n->[kronecker(-23,n), kronecker(5,n)]) dirpowerssum(10,1,n->[1, 1]) dirpowerssum(10,I,,1) dirpowerssum(100,I,,1) dirpowerssum(1000,I,,1) dirpowerssum(10,-1/2+I,,2) dirpowerssum(100,-1/2+I,,2) dirpowerssum(1000,-1/2+I,,2) dirpowerssum(10,-1/2+I,n->n^I,2) dirpowerssum(10,-1/2+I,n->n^I,1) dirpowerssum(100,-1/2+I,n->n^I,2) dirpowerssum(100,-1/2+I,n->n^I,1) dirpowerssum(1000,-1/2+I,n->n^I,2) dirpowerssum(1000,-1/2+I,n->n^I,1) \\ ERRORS dirpowerssum('x,1) pari-2.17.2/src/test/in/trans0000644000175000017500000000162114676526175014435 0ustar billbillHEAP=[193, if(sizebyte(0)==16,5521,7902)]; \\ A tres grande precision \p 2000 \e abs(-0.01) agm(1,2) agm(1+O(7^5),8+O(7^5)) 4*arg(3+3*I) bernreal(12) bernvec(6) eta(q) gammah(10) Pi precision(Pi,38) sqr(1+O(2)) sqrt(13+O(127^12)) teichmuller(7+O(127^12)) \\ A grande precision \p 500 Catalan Euler acos(0.5) acosh(3) 3*asin(sqrt(3)/2) asinh(0.5) 3*atan(sqrt(3)) atanh(0.5) besseljh(1,1) cos(1) cosh(1) exp(1) exp(1.123) incgam(4,1,6) incgamc(2,1) log(2) sin(Pi/6) sinh(1) sqr(tan(Pi/3)) tanh(1) thetanullk(0.5,7) \\ A moyenne precision \p 210 dilog(0.5) eint1(2) lngamma(10^50*I) polylog(5,0.5) polylog(-4,t) polylog(5,0.5,1) polylog(5,0.5,2) polylog(5,0.5,3) psi(1) round(prod(k=1,17,x-exp(2*I*Pi*k/17)), &e) e theta(0.5,3) weber(I) weber(I,1) weber(I,2) zeta(3) \\ A faible precision \p 38 besselk(1+I,1) erfc(2) gamma(10.5) hyperu(1,1,1) incgam(2,1) zeta(0.5+14.1347251*I) \\ if (getheap() != HEAP, getheap()) pari-2.17.2/src/test/in/modpr0000644000175000017500000000303714760123736014420 0ustar billbillnfeltmulmodpr(nfinit(x),x,x,1); v=[0,1/3,t,y,z,[1,1/3]~, [1,1,1/3]~]; test(P) = { my(f, V = apply(t->iferr(nfmodpr(K,t,P),E,E),v)); print(V); V = select(t->type(t)!="t_ERROR", V); print(K.pol, ": ", P); f=[(x,y)->x/y, (x,y)->x*y]; for (i=1,#V, for (j=i,#V, print("*",[i,j],":"); for (k=1, #f, print(iferr(f[k](V[i],V[j]), E,E))) ) ); for(i=1,#v, print("*",i,":"); print(iferr(nfeltreducemodpr(K,v[i],P), E,E)); ); } K=nfinit(y^2+1); P = nfmodprinit(K,idealprimedec(K,2)[1]); test(P); P = nfmodprinit(K,idealprimedec(K,3)[1],t); test(P); Kerr = K=nfinit(y^3-9); Perr = P = nfmodprinit(K,idealprimedec(K,3)[1]); test(P); nfmodpr(K, [y, 2; y^2/9, 2], P) nfmodpr(K, [y, 3; y^2/9, 2], P) nfmodpr(K, [y, 0; y^2/3, 2], P) P = nfmodprinit(K,idealprimedec(K,2)[2],t); test(P); K=nfinit(y^2-1105); P7=nfmodprinit(K,idealprimedec(K,7)[1]); nfmodprlift(K,nfmodpr(K,y,P7),P7) P = nfmodprinit(K,idealprimedec(K,2)[1]); nfeltreducemodpr(K,(-y+1)/2,P) nffactormod(K, x^3+y*x^2+y*x+1, P) nfmodprlift(K,1,P) PU(x)=apply(t->nfmodpr(K,t,P),x); LI(x)=nfmodprlift(K,x,P); m=PU([1,y;[1/2,1/2]~,1]); v = PU([1,y]~) LI(matker(m)) LI(matsolve(m,v)) m=PU([y,y^2;y^2,y^3]) LI(matker(m)) LI(matsolve(m,v)) LI(matsolve(m,m)) K=nfinit(charpoly(Mod(2*x+1,polcyclo(51)))); P=idealprimedec(K,2)[1]; nfeltreducemodpr(K,P.gen[2],nfmodprinit(K,P)) nfmodpr(nfinit(x),[],[]~) nf = nfinit(y^4-2); pr = idealprimedec(nf,3)[1]; modpr = nfmodprinit(nf,pr,t); a = nfmodpr(nf,y^5,modpr) nfmodprlift(nf,a,modpr) \\ ERRORS nfmodpr(Kerr, [y, 2; y^2/9, 3], Perr) pari-2.17.2/src/test/in/time0000644000175000017500000000044114567450071014231 0ustar billbillgettime(); WT=getwalltime(); T=getabstime(); for(i=1,2*10^6,) \\ %5 T2=getabstime(); t2=gettime(); WT2=getwalltime(); abs(t2 - (T2-T)) < 5 abs((WT2-WT) - (T2-T)) < 5 for(i=1,2*10^6,) t3=gettime(); abs(t2+t3 - (getabstime() - T)) < 5 [a,b] = %#5; abs(a - (T2-T)) < 2 && abs(b - (T2-T)) < 5 pari-2.17.2/src/test/in/intnumosc0000644000175000017500000000071414676526175015327 0ustar billbill\p115 bestappr(intnumosc(x=0,sinc(x),Pi,1)/Pi,10^8) vector(10,n,bestappr(intnumosc(x=0,sinc(x)^n,Pi)/Pi,10^8)) vector(8,n,bestappr(intnumosc(x=0,sinc(x)^(n+2),Pi,2)/Pi,10^8)) print("1:"); exponent(intnumosc(x=0,besselj(0,x)*sin(2*x),Pi)-1/sqrt(3)) exponent(intnumosc(x=0,besselj(0,x)*sin(2*x),Pi,2)-1/sqrt(3)) print("2:"); exponent(intnumosc(x=0,besselj(0,x)*sin(3*x),Pi)-1/sqrt(8)) print("3:"); exponent(intnumosc(t=1,frac(t)^2/t^2,1)-(log(2*Pi)-Euler-1)) pari-2.17.2/src/test/in/analyz0000644000175000017500000000026714676526175014611 0ustar billbillHEAP=[9, if(sizebyte(0)==16,114,122)]; \e sum(x=0,50000,x); sum(x=1,1000,log(x)); sum(x=1,25,sum(y=1,100,x/y),0.0); sum(x=1,100,sum(y=1,100,x/y,0.0)); if (getheap()!=HEAP, getheap()) pari-2.17.2/src/test/in/cxtrigo0000644000175000017500000000201614567450071014752 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 = 4) = { my (h = 1 / N); forstep (re = -N, N, h, forstep (im = -N, N, h, iferr( 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)); ), ERR, printf ("%s: %.1f + I*%.1f is a pole ?\n", f, re, im)) ) ); } for(k = 1, #fun, test(fun[k], FUN[k])); default(realprecision,1155); a=sqrt(2)/2; sin(asin(a)) - a cos(acos(a)) - a tan(atan(a)) - a sinh(asinh(a)) - a cosh(acosh(a)) - a tanh(atanh(a)) - a default(realprecision,38); a *= 1.; cotan(a) cotan(I) cotan(a+I) tanh(I) atanh(2^64) atanh(3/2^64) pari-2.17.2/src/test/in/round40000644000175000017500000025316114676526175014531 0ustar billbillallocatemem(10 * 10^6) { v = [ [1,0,-363,0,53550,0,-4091823,0,170172414,0,-3663509067,0,33703350345,0,-63300912912,0,32451860736], [1,-6,18,-30,42,-174,738,-2514,6885,-14348,21720,-29856,48284,-47064,-27768,139824,-135588,56256,78464,-60528,18864,47296,73728,-109056,80656], [1,2,3,-3,122,-1], [1,1,-2,-26,39,-1], [1,0,3888,-12], [1,0,-12,-84,-196,2856,6328,-42336,-64820,352464,298928,-1776096,-262416,5458656,-1875872,-6688416,7866576], [1,0,57,0,1197,0,13681,0,136854,0,1048044,0,4603892,0,11460015,0,16001100,0,11131014,0,2739339,0,-368793,0,-7569], [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16], [1,0,-432,0,68688,0,-4717440,0,112637304,0,409406400,0,2774305728,0,4041156096,0,11224978704], [1,0,160,0,11216,0,455360,0,11928052,0,212540000,0,2645190320,0,23223642560,0,143402547926,0,613283590880,0,1764753386480,0,3275906117440,0,3788371498452,0,2940754348320,0,1769278869776,0,73445288000,0,87782430961], [1,0,0,0,-42,0,560,0,-1645,0,2352,0,10290,0,10192,0,3969], [1,0,0,0,576], [1,-43,624,-3816,11173,-15800,9408,-1152,-256], [1,-28,141,0,-887,336,1436], [1,-171,3222,1079,-25200,-9024,34304], [1,-124,1109,-2208,-1504,2048,256], [1,-347283,25076856,-419348507,1408022154,-1607716596,540519736], [1,-130544,2518160,-15612096,27910496,42272512,-146951936,78195712,1806592], [1,-219,2951,-12762,6701,80815,-139748,-128864,354688,42752,-263168], [1,-20819,4970290,-185332015,974972214,1853069313,-4527488547,-3894160116,4476129404], [1,-155,2836,-14379,14428,13117,-9421], [1,-262286,3014265745,-8638841144522,-7230469691722,19997484886500,5356591151857], [1,-599,17808,-98580,-253979,537680,1226232,464832,18896], [1,-29999376,561121360,-119997504,-4488970656,479990016,8977941760,1919960064,256], [1,-25283692,99985153436,-3431807998368,5805487078640,46121794880,-628204481984], [1,-271,14191,-320438,3790080,-25112800,92495160,-167147800,50530009,301971239,-450938136,211398894,-16216756,-8116135,1041461], [1,-16555440,793241872,-6812040640,18249197408,-12596399360,-9598940928,7536655360,2589634816], [1,-3335,1068872,-29372236,170603861,-25778864,-465050888,178972480,-13193008], [1,-511,60996,-2085405,31489262,-239889832,934179225,-1604993848,-72959248,4517839616,-6762846464,4114843648,-916779008], [1,-295,3558,-5031,-24914,17697,28397], [1,-20167,13515214,-589415581,409276760,689575296,-490712576], [1,-1423,112198,-2946382,25666342,-2017279,-128707766,38702420,141457873], [1,-13921853102206569014202396016,13823607745009668573058211237056109158822,-82639509138390410981775119083025418818311274199568,7191389922579887711216370122117810510341770052031768545,-6403782491712680689180662417515214438745217916122612992,-16491332368693741394107994410424645158974225360655824008,12504550730163409756349966122713154452136883600552704256,-700835788721071887889404301240818143183667934525633904], [1,-2265,351933,-10876260,113882619,-320899050,-624685627,2393614800,1152858000,-3523888640,-151501056,1315123200,-232738816], [1,-711,98421,-3240421,25070664,-58439271,31703851,28789266,-19416303], [1,-506,49087,-1669640,17231279,47336349,-144695555,-359331616,176538278,650890177,224030107], [1,-189958896599609331973768440700,687813619771577743504399928302877897734798,-860743693595930793317020644139268141132387039380,2604128524727083170656936316847150343534889684322129,280304933578645057171094798274221018642041201687880,-8574385501054918331765273413936458875072943056877128,-479436876642637253489428928646435311733187408834720,6755064609347154305550891307820436374837227182458896], [1,-4690816,910531264,-11915116288,18021615232,54853406720,-82373120000,-64180142080,54969143296], [1,-6649860,1576752264,-22267257600,-85164579264,-77640519936,-18089594368], [1,-33050180802,1659048077186129481,-272574365342594573834910,11095950373591662695013161508,58710086095790534948543753694,105952057692427053452669684769,70434206621571881660299570170,9218882946199589918384363001], [1,-329544091788,469019476748118,-61449507761159844,363555883847040681,-209190672257869480,-1016729503227038920,1359941005734916512,-457890480465748336], [1,-1150160,1331537926,-601897862304,133574881579623,-15016280356014512,791282768405768068,-14453225350510767424,3154149235832315999,242466621761228454864,224495153622717846854,-670291322259768317344,-916062740958336644647,48963442301119929008,327298375561074497040,32908217054793357184,-23393721242771438528], [1,-2851,158608,-1924400,1243901,34900240,22503032,-108662912,-119975344], [1,-11111186112955398247507018336,243445863707559988779970226428228863828166,-414424563629922001757819169028157495238172960,1123139273032476660541621993600473674277033409,498129315610741879775567628417300033144884288,-2159960274391288199445420339203867726147763080,161278633821087460912298650651190604277783808,333627755901815676223362327425185259040194704], [1,-14504420704,1182354951470244,-23480009042438862560,27882235470885485836070,-9087586203362364155630944,599651930510874648548788156,-3678137244259701713858840096,7016885534906558207253820945,1533248468172570268668346560,-20993688867208520156247602216,24208677107524343574382863104,-8499807937568973364674358384], [1,-2913,1474630,-174340074,5392477240,-26251520300,-34286734387,209569240200,193605730560,-244321588224,-184759603200,14498496512,10333454336], [1,-2181,137643,-694573,1252707,-898221,209611], [1,-973,167753,-3919581,16265742,49310580,-279670537,-250608765,1769132170,725790142,-5312558309,-1392312472,7380239894,1386140637,-3489374699], [1,-1212,22194,-55328,-30951,115500,-2908], [1,-4773835280837163132310630467298960,9870109995525906834183518595974886029184804344444758,-1782775404778879896945364961485617187018000556874876449394160,89883389132977359805126346146881786926610135522042323723472323569,72714593243136238897319878334430413252438964969406750065955662080,-321968360190732413575930663497507427814725029860845628527928503688,-312452766852442968760965441219058671845140150026306340120175130880,41087519521030021203246250696563962180882228355460884053944990096], [1,-49896695,527277779708,-120568048624615,452535974730544,1625411298707505,-1448067181855113,-2752052546805840,2221923470234796], [1,-1046,20228,-68392,-265619,904512,1991640,-2358154,-6146747,-2463528,407228], [1,-549625252,1238278325058,-15329043153964,28925414899409,130312025889136,-32291232291184,-108323448091520,-24340205012416], [1,-2949,16059,10208,-83400,-25584,78256], [1,-3640278,2282599369,-18694808796,-4328145452,125291204160,-18186492672,-205081362432,13073301504], [1,-3152,285561,-9564226,152595945,-1188640275,3575524815,4816808889,-47197026465,33049819979,215848146317,-258582345090,-504831954170,649899122769,650345190624,-691225563843,-408430121580,242381088477,57377645757], [1,-15395,20249992,-239327620,273434573,856975880,-760838848,-750006400,143449856], [1,-2003677328,3012846911824,-25136484060736,32567282104928,90286574332160,-166925807110912,-30270493268992,97725572006144], [1,-61640944,166625534272,-3562612049536,15797138088064,236548072448,-60906347638784,18108824379392,56198906318848], [1,-21383884,35000497050,-11829222158080,237367247198299,-217929167425584,-553512315641022,292541289325812,110433041508969], [1,-23869184,4853367907,-14052765056,-26838500008,56069168640,30654626608], [1,-225138,52033917,-248800311,97200810,921552876,-1066931352], [1,-88696708256,4437008017160880,-23039907832217560704,26485741273275758734176,42379932318953038254592,-58866917909043924655360,-68089115862472243066880,20476771544555918463232], [1,-421636160003888,1902246275640252720,-166497940584948453440,3590656805496104164192,-18533569942452269505792,40219147880321276111616,-39862736608896158137344,14916521497035956080896], [1,-3320,224698,-424748,-1157911,905628,951268], [1,-64961,187497640,-8356326784,-15832630267,65698325576,143412228032,-26731714048,-127433961472], [1,-232394051587274973485503996066296,4038758106150313180814013396186630354012,-18284722485505087322089714887666913243539528,93595182799438815963839033321760695064344070,209067053454541747659819712614587487150583608,-588680842304077969068594235539671561808141348,-538836714977811176095248603569636252559381624,867715345720344138137761716498628626987199041], [1,-53655,319168490,-186349285325,21120443415975,-686099144383750,4735314251803625,2204357656605000,-26162347980297500,12824037220300000,33965267757150000,-36652423750000000,9889099639000000], [1,-125472786714116,674561716001370442,-230527140127968669608,8169775848285148195,1888371575828384127208,1007346199547631496042,-3767048153290292678684,-3343242731361766639199], [1,-34088504,1506866218,-1104149192,-12689882023,4007782176,25448506156], [1,-243443804696372,2923285683273533645014,-103724188690208930700257484,219554589005762032602647336897,-27447284989915966720818474455448,820411316616154701751838916778832,2735010684783093171601973097236320,1536067156806457414066577673199968,-1646791109769306193071759068458624,-1348134788310032629244426609918208,-193806232242166413772905190324736,-7677311000369732927493903060736], [1,-5331,3275258,-663977892,41259312682,9981725432,-375222796900,-231422557815,575556116832,210741891801,-134691222781], [1,-5138,96044,-353472,-420203,3742600,-2116288,-11951190,13094613,11859720,-16211204], [1,-532733417840,4744177349160832,-8413021486831026176,22311336993776500736,-7638962491965308928,-7352121709731774464], [1,-7637967984048,3386340581184784,-42324961034160576,122919529892620128,-58964720593317120,-192640220764305152,245607942083017728,-76666118683840256], [1,-2006,1008774,-17353883,-7844872,51013821,14640013], [1,-12474419222154,2431008594310441359,-6912314557744523417164,33605190900312985781583,-52569003547113031969674,25970935931836648827073], [1,-161443012754157099829832920,10138436074617165816404765780234617807802044,-20060069047647004218617188450114148708733068200,660050897576330492829543886032989254940435324134,-974098875961622456132597564420652229994235789160,-2264260286588310696319122780977992700907740060420,4240004472781140599100651710696566992990808375400,-1414274241286414395747708743194177178965032607775], [1,-1553722352,901513660416,-152989098177664,6553256584676096,-109901782972756992,685652288206471168,-43714124749955072,-9422339586035687424,8817974156500074496,44807770136073207808,-45324909008823779328,-87566115761309089792,86042657488023584768,51374273094909689856,-59775177056420102144,12687790985866903552], [1,-165086,69953110,-9018434345,392237516455,-5982463478261,18025737017474,55747520697647,-168806685673984,-244753603799872,393573790098944,502650387525632,-215239123238912,-336114163122176,-57002141155328], [1,-93823428592,34799861952304,-443389708735808,779896340053856,1393944632569600,-1484337524757760,-2345449331993600,-694036275654400], [1,-61061,2315481,-35028903,275610780,-1232308077,3218060943,-4849095216,3959990439,-1499118593,179027083], [1,-5695,92812,-488095,780736,805481,-2779721,525584,1541164], [1,-8235528536,78777096091648,-14962965975823424,752649877179796160,-12880180969335749632,38155186289451728896,469400924480987815936,702074460321333391360,-715079303427341254656,-2125387453139301433344,-1140826580450709602304,-3849685126809911296], [1,-5406403952479432,6865958511876428164654,-71567316451693131796818392,1752342108645328326901864169,-5653754613528818355093017840,2811073291210554121492866968,7423802461456459480849518400,-6565509149627058490734170224], [1,-151343,1368301504,-21253251016,26539419173,96661676120,-105696181312,-91329016192,40152391424], [1,-807505248612,37556725718396046,-265013994507552057420,318993321672688235401233,978883284203583405618744,4557622950652832660664,-2130952270988696435076960,-1494408400545790896087024], [1,-9448903436,104730633623688,-53760865135709952,4832151934763017856,-84739601628184897024,-42812862492100717568,184460624879942123520,71427552535240871936,-98041653705232138240,-30794067428621123584], [1,-79582678925,8620909385125051,-236507758358268974098,174874878867315968757470,-18058520227439698846912507,645254756102974107764676912,-7870697647323874283979696891,11521347153009947384786791458,34576202721355388442595149476,-70344554343965963219721213592,-10740194212304372050166074384,62770663206984074836346600032,-16345615646987859185051367488,569708459683633657748324224], [1,-456523770,8737152129501,-982742700549550,27196974696122506,-267044865205988930,534419840754543701,3738689503783264990,-4543932463986286454,-15278585690067252590,8496454288061882845,19353624370456339750,-1008847637476820975], [1,-34856,3760018,-13969928,-5409343,51565824,-37781504], [1,-301640751830458520553597141376,328952494035105106001631823186510670131969344412,-133358741515025683238080442729603137995456051732608,1955525927172552794216114449002457559485718278748870,9397121011646773996373023708967458825619733367758208,13257860889783058889903253607299903955098315590042012,6433754692163674744311497881625324357727770698216576,492667067892517490964245788797821843444034967148801], [1,-512577532102040,43768111570354384,-683727333405049120,2702203304894313824,-3908326472950549120,1831103370543136000,-49811703475904000,-49563059750240000], [1,-4442,2971547,-533338420,2818485691,606965289,-20799684871,16060220236,40016291866,-40620996767,-6838744349], [1,-1661445000,648950992194,-9056465203448,-52361475864447,-82213976895840,-37808675256052], [1,-3549,1055643,2390843,-2763021,-10087077,-6219557], [1,-523628898243604618995885416807147298909363801451789372900,367600369666309006452842123621050246321452143630580273014679831593578783458649152654286,-3343275983768744237278154637602147245967274497790433362036635892377724426950499872902658229340,1832082009549845619949867091376004679654159119363411909937509445666660442613413884422767828119857,7972083317253398926405060410933145316118484573008126052905764693835293798003418767254772929076840,11794511604384984730506391635816484705277974441262698427609855343001177151538798564737754260305528,6870707586084866428566813547262155529526409904008120571289108710304360279945306394092746374847840,1364739780535919594206700656372505401403107870453922666372253727638308252150474474123624152944400], [1,-223216,303477256,-17417922005,277522832382,-594271046752,-5464816647875,5815492998512,37144434715472,-2497746038784,-79766894614784,-25810480361472,32744553869312], [1,-7391,100628,-303943,-80708,1274729,-1168709], [1,-11102485161464,638119123854694146704,-1090684976797347138361401856,5790691092346201260104535212544,-2905557524355781158067995198312448,-1740704435184319464552349984251904,8456003228780781810129632899235840,611694445981518923832996667392000,-1827580422204898657895630230781952,296569960368897491493657596919808], [1,-382595410,10131435161569707,-339358625351926857460,1944397043581582983327025,-377576456004292682578424730,18893558349780213971828050325,-114503495274862313003240421015,-941511767079645429966258595415,170925446090929041685072722405,7547994422752820490440513334577,4952842395416051576334911693070,-20605333735289498909471577909366,-17080193694570124063317347368550,22769567946872826808692277299420,13826681275125601697987763384700,-10810372895085097433637727654775], [1,-317966635855342617399169385408829217452748440,13678545113125269147071264087266524532070024308404763646867605208904755730954,-15684278338411526690829309518564793208753920587856759367478501240440935756809346120,612415923065287098473685281157727791918451722108963506485602685360057577081310228969,537814306804262126760386283977264831761888559875268935565912225023248124597985989680,-1990656139061697921305239415958192303820860550542494738202435034180069987344650996640,-2055469177845059349200042772439815497299423127890291811872672651394061790113952185600,-318082857370566991270588466777928875794349614537780585539495916100466479816098809600], [1,-416659279474111237,330377843894082003274229160,-62905768010062743987970346108852670,16821570317735641478410538460455385145365,-1198558791812587254354860392504583675770158336,18870041073230571748664972200517215466193250634297,-3110266503818994429391891213184926395344435891196215,46333969996580915198177746519714350753415778619811755,-71051745585560409536489422446312023987208684949679585,-171670385086621478643416705514305417043725434872977218,353998192629745372651831816938706517212108845354144981,38406503908964266753393497382125776817470966499185790,-335208974242087685397896701245395328967475262796476705,183830028342252095617620250485464751517776308230766835,-28324287359035373403013837385189183497723403582130478,-370669783454900697332687258050823467831694680481879], [1,-2942,425807,-21480253,510509165,-6192552408,36292590688,-53610411500,-425058743459,1751257692002,873280257113,-13398050061528,6817766400536,51340604838743,-41334969659574,-115572213676468,88181505312905,157994239939799,-76512548098590,-116800296271737,13943948986543,27978407467337,1658082397889], [1,-235975492672,591805571783776,-382200656154472448,73171728402630615744,-2825821907089361173504,22281146497688453411328,32388399560710497509376,-589295596207800671283712,-475154989792559233744896,5936410136560770774966272,9110311309239759390113792,-15457901130275180849086464,-36773863935231836576546816,-392960681613067998593024,38539327581294094379384832,21102849638169519181594624], [1,-22,135,-317,90,941,-1851,1519,-580,83], [1,-480,13575,-57397,-15045,155166,-22856,-113661,22119,20089], [1,-5349,69225,30959,-693771,-198237,1904389,513114,-1472148,-541304], [1,-45,339,-792,-186,2907,-2911,-765,2280,-829], [1,-1999,44014,-243753,270704,621536,-1193984,115712,409600,32768], [1,-2154,83832,-98620,-727088,628528,1715120,-1208288,-1009216,688192], [1,-84,180,796,-1713,-2337,5216,1461,-5232,1819], [1,-28714,389720,-442556,-3374000,506160,5449392,774688,-540736,3136], [1,-131061,64254945,-433211377,-295697859,2231628243,196751629,-2475058518,468570444,325387336], [1,-43228917,3217754381,-36758007254,-59567284560,289702061749,332943277127,-581210582241,-584264535430,52410165263], [1,-31323,7353216,-107319715,116275089,383163324,-599105591,-198697686,666629724,-267848648], [1,-170,447,951,-2186,-2265,2785,2117,-798,-433], [1,-97,920,-2507,191,7795,-7979,-2434,5592,-1609], [1,-25601,4735751,-157811795,73527676,713816792,-217322176,-919714240,50378496,268434944], [1,-404,4704,3918,-92546,-153360,222561,511962,102988,-113801], [1,-431,5515,-29560,84442,-134947,110307,-22471,-27036,14251], [1,-129254964843,35178418165170,-223350030592755,251360581683972,960227812394016,-2217902130474495,-80657197605174,3263837746063692,-2051179019383688], [1,-10430037,3613650129,-255462258585,649253166885,405120779307,-2141143390203,901824939450,1197088044012,-731164579192], [1,-50244,30294557,-672636955,-5671628428,-15674959992,-18431496640,-7309777088,1356664064,746926592], [1,-339,4344,10623,-36633,-85575,53843,193416,92484,2087], [1,-31428,5168421,-69645814,-94901634,121411929,57346600,-76184430,18720885,-1242287], [1,-1322,9117,-14806,-25436,87546,-32311,-75542,33116,26104], [1,-189471444,37709676681,-165918005985,34691048736,558925368933,-498161898711,-154612190805,146945330826,-21509240369], [1,-2147,464267,-6245532,12094236,28528805,-87534615,6524347,127671918,-83816513], [1,-2783342,8025984,23658900,-59547440,-78387408,138067248,117240288,-97770944,-60103616], [1,-1255489,64926593,-338839895,426458329,692772093,-1921085372,734227214,1055601045,-717464063], [1,-36319094,630812278698,-1655815071045331,-6028129014962075,246012746225435,22671225935869189,25087340269832470,2776221409366657,-4230997679557999], [1,-873711251373,753411928367685,-13806936287537310,-111661195235268408,-270166294338135339,-191717097502403145,179751315005491911,323631491466547362,124064847445413967], [1,-14849018,494063251800,-710653227516,-3713349421616,4822039295664,4687257735600,-9757306885344,4980576448960,-802641509312], [1,-33175596,143698989,797637285,-324064356,-3785215656,-2493975360,2377896000,1441632000,-683840000], [1,-1929,14472,20253,-156633,-129093,449669,289806,-258072,24407], [1,-614748,2204740,20504164,7285904,-146034016,-334984464,-302768000,-123461056,-18857792], [1,-3029,22091,-40644,-47982,203135,-80355,-209549,146292,22027], [1,-3981,1369677,-17835518,-21602640,14896077,19095023,-1882569,-3453006,-58337], [1,-56691,2221227,-15141714,16322598,55966149,-107613132,13226364,54559296,-19694537], [1,-14521960,647012999,-4984218590,-36502752545,-43863546837,79899788485,212682283274,154229646540,36019185544], [1,-158662082,2623228504,-11293514652,2847667984,61874154160,-78720960080,-54521566560,105714608064,-17136358336], [1,-196587,3209851035,-169981929492,1004435496252,-2429211599883,2941338597321,-1853910108045,570724116606,-66727824497], [1,-911,5074,-2190,-29204,37810,39031,-64347,-13824,25019], [1,-7845,71310,-122285,-330972,945684,133568,-1565232,369216,616384], [1,-145515609,153019764729,-3709746066522,1393445404674,19486365429555,-8829957473691,-23095161469062,11557736900892,833570519624], [1,-1279836,7972421733,-33976650387,-87081745548,139649755464,254306919488,-38030593728,-154168849152,-46733991424], [1,-1983,670992,-4138497,3171843,9255633,-5546089,-7199220,876864,930959], [1,-22338,412581,-1979142,682380,7847946,-7588855,-3039222,2196060,626552], [1,-22113768108,3796190022029887441,-60498021996410510930523,-71963443045623180847600,487699550239607072040156,523305125593515644446032,-1131228403974427035526864,-946796045857905092061056,584092504774559261558848], [1,-16954592,118348117057,-461615145371,-96594517766,2084887420818,-1349388002526,-2335232607204,2081484755957,104568589897], [1,-10489,2707211,-104488860,245611206,380234947,-1177729795,106009611,667160224,62376107], [1,-45837,369335901,-31624086134,-169410056472,-164382128003,465586425823,980522077951,392287249570,-132604621897], [1,-463038,45146493216,-1001353353260,-1082922317616,5505441329328,3829125921584,-6282318595872,-885395763648,497609171008], [1,-841,13536,9553,-157013,-163985,275717,183350,-197524,13031], [1,-15461,715359,-5328764,15402786,-16694517,-5169563,23976863,-13678964,443227], [1,-862775,10856170258,-3134053418062,-1375422646243,19989421509103,3876108599660,-31488084661671,5161577814899,4115642633441], [1,-50213409,41604993225,-1178945921599,1767674719401,4428816426693,-5499446500460,-5981060846562,3930075321357,2711088130897], [1,-14509669203,854596766777094810,-7066981747963431235083291,46268306243972593019173548,-119361738755744810792850960,153452578934040181394048337,-101367063741886754383215702,31015690796531163812304780,-2923893082958254149947912], [1,-734,33756,-127241,-72904,584650,-73590,-605936,-25506,23491], [1,-73853860518,13777317132366702,-115071949708121348242,160844716195874633181,682814078330976048036,-833639776266212564111,-943177567400978615382,831764080222499743356,66392226304335963256], [1,-694758725855,106254756427419398,-3784025583829693170297,-13131948767566391974232,-12527679077150368308464,-1542996140822612863744,1578487928494511479040,-80007592280225568768,597456985245478912], [1,-17515,10964993,-247423288,310805648,1085556229,-1447110681,-631704583,509927518,170424799], [1,-8336,239429,-1115012,1550830,675992,-3307903,2496650,-569892,13592], [1,-5629442086276204273505,386546651233719446359200330993497888059691,-72838371990626194759378155526759022817640816485447,-68944817078273525878833279122529093499192548461768,532698119339953491504511496245901043962109891591692,399760666506683453127871057655514820189115908767536,-1251030146293132816263700188101197788442427262158608,-574105270447410879019496275688738988931548783376384,933502079102512278754584352311502694379008136095296], [1,-89444164815,3805216350344442726,-19525076579766367621887201,10677494665576920234465120,172915220543339268243570816,-75371913447675512226165760,-481724974617695286501519360,133078578075456026880442368,404416685885850617500663808], [1,-5017340872,54242041495381,-5530836376965691,-11636668895078592,11075773964676508,38232904505954064,23198971246434608,2517662503984512,53606420009024], [1,-39793,797843,-4481430,9023194,-3106271,-9102293,6350523,2351580,-1467437], [1,-34677,757365,-2384830,-8575564,7310693,25880563,2552523,-19252762,-8564513], [1,-958954166,5186058440675,-5517238669966482,15054662708038354,6305516444274500,-46821935177109565,37215625652899170,-4390922315873148,-2421624954194536], [1,-6299100,13352120109,-51758626611,-417163766490,-393905254122,823253994102,1291197091500,235580470281,-131269473631], [1,-68277338,5340670808,-96736086908,-116282155376,520304803568,350815905584,-710962872544,-144532807488,203482129472], [1,-1001,222000,-9506853,78349585,-284295243,538163385,-539633442,256936366,-38830541], [1,-38919,34177467,-59964732,-1118422710,-2838483267,-2244178117,692405229,1753197504,630872507], [1,-17126633628,18516619842741,-5017128507606003,8455548998534724,25861081463217288,-49455246822756288,-20953146111899328,72565428488438016,-31456789981646336], [1,-1263537,9873936,-28868559,36398475,-12468609,-10015971,4721094,1594332,-10529], [1,-19146870,1769475136,5281209652,-10032427760,-40835782480,-6739762640,71055695712,63912971840,15410458688], [1,-7447032,4924412571,-359721985189,117617755923,2143792138494,-1486073631188,-2975007994749,3230985686523,-741473702423], [1,-517106,58273606,-1373815122,-4952974364,4913608780,27153942409,6950089002,-34145062392,-20469346393], [1,-3757,1530645,-28029222,2359216,144391005,61784671,-203472129,-207072198,-54303129], [1,-173780,45443268,-1790226588,-8863383152,-4818339936,30375498864,42501629952,-3312569792,-19727103296], [1,-2400825,190198232783,-22943866813291,24838048578516,112066877369032,-119639920213824,-123200993753280,100605510714624,35506136494592], [1,-25753,6751411,-44524192,68742386,111823375,-385704903,257283371,63338444,-67180373], [1,-284655,209650037,-38162364134,-163511305238,-14981588021,711289445675,760350260231,-313829615616,-502101723341], [1,-68325922,137056373910552,-11145282232549212,21173555959782288,42902777425768240,-99554991522541136,10187009777496736,51567358997901760,-19350004011936704], [1,-11733462,65284119,-55303584,-232858944,336527964,205314537,-268417494,-148242276,-18541736], [1,-258893,79530727,-4243301484,-11876635766,16008454795,57961696909,6993684303,-48619490844,-16019695837], [1,-18001,4498247,-188001200,-52454414,551685395,-309521095,-64332897,57315780,-7370757], [1,-1435968130,714533588440,-8231837770332,40163539982096,-106986363839824,167944712628400,-155368804314976,78443060916160,-16677501283264], [1,-405158247,18670761978019422,27304726717430303,-407622516493630984,-1469519465184311920,-1133627454427613440,1794923858940870912,3248244532977154048,1358504654641917952], [1,-404792,2745549,-2331396,-17521082,28819704,34082865,-69811830,-19635428,46786072], [1,-68548140398,1451627133858028890,-5095232432365659132155182,3088999911253813409361703,38873934921503404756228124,-21888154468509856869401849,-79286358464811742369152944,38737113817267168448327653,19271373881512324513129886], [1,-233746,2998825,-13950594,28124252,-19043266,-12805079,21860330,-5429540,-1331272], [1,-10355,21543,160412,-124146,-768627,10747,1106549,390000,-98893], [1,-238089,2428653591,-52281136592,55494790434,272982489999,-244755630607,-464342035173,229499404284,232532331139], [1,-9804802050650,16692730784125432,-2541495071565357628,21109219806111169040,-72218607566697081616,126705850231213211952,-117594235131211600096,52634612644066947776,-8014881018162450368], [1,-1546315729274,288782232725785318,-11969666848599934914420,-27130970349234930466201,47347882539110061930082,124498595190336220679942,-1304964757812833452501,-64114240217284796166421,11258025941338821246113], [1,-84967786647367,333964189732653895352180494,-9366745551868952432186167003262289,-22234121711987296225427381730172744,19539169743580452197619049789466096,51305696359169176802147610083269888,-17680157436544518186836737589196544,-26000314945482248211133277039052800,4518541019882267511313091077443584], [1,-7748673829668,83640796005524661,-937392562807456731,-4611558327627410100,288178943379431256,19088931030202667712,14002224746809121856,-11962021354522502400,-8709955859254358528], [1,-843304,33763525,-106394721,-151759084,340324475,-121861811,-28549267,13500892,493667], [1,-576711,9817828593,-1467968536170,1986116686590,2315529499551,-1792787441257,-759829031733,199468065048,18428192267], [1,-67782267991926,3118994381718067776,-4510225427657444408844,-9065205219388262002800,14548147545483838825008,26311576762212059385392,-13479025960226694184608,-13821453446321155975104,1249714021685870356544], [1,-116597,11204304,-75508472,143658084,90374012,-590670119,595390427,-100047640,-72256661], [1,-3749259036,554393241540,-10928530910172,-39909926964720,20361183490848,153596163158000,62626956568704,-84859519298496,-23307365582656], [1,-2485415052,131251617492,-500838205596,-311199622896,1007849076384,593369475824,-435068972160,-386665742016,-74265379648], [1,-235161,314874197,-3066156650,1109853192,24058441897,-22580421725,-49502851657,52464975134,9173335783], [1,-1315854,125620602,-575073054,-177194175,3317366889,-1778517616,-5030239005,3601178400,766593875], [1,-264278631900,6391720172245021,-1626519277074267211,2468549508074110996,7490117873595926920,-9983338376585959872,-7051946118841625792,5426902073117889792,1165973386759172608], [1,-79480668163070691548277,579797667303611907678285,871006426643549798058665,-5664575884052113261186899,-2721765628562603760591507,18297656442680378045473468,795444294656219988472938,-19650372769147029403078227,4906440383881879319836057], [1,-17361556040,19571584838731,-1912255610523653,-6599847690074333,-1764459194463858,10908227354203500,5823874326739107,-3161768996970613,-458530154815991], [1,-942677402975,306729542653406,-2223101555541649,-3021993537312,7932499451339520,-2016256763813888,-5852785072668672,743954651807744,853725799251968], [1,-388145,847961035,-14279672808,5155032058,75179631715,-45679619663,-98354672793,40080406380,43812242819], [1,-449715623374,5733757254592,-14174764915308,-36178039104112,88431316773488,56172051631024,-118680037031968,-12225526217408,30136055145536], [1,-6233425,50543493135,-277319344376,37556421978,1194329803539,-616149265735,-956720534777,-149559849324,-308254333], [1,-6720205764,466584698229,-850591371171,-5544923326524,-2245384789368,3411810485312,216995495232,-119747460864,6720270848], [1,-68026878750,236661304531200,-24579892325699628,77376432563312400,2783150175184752,-213772569953649232,171920098000293600,41445518831184192,-55371652962821056], [1,-618153,190453312,-13900878563,20306957207,79305438779,-96593023923,-148646368490,107484573608,96104956471], [1,-3837199411252,15987954244320349,-4697757619575778443,2802514151170278956,38842254787450812632,-17674389726474822464,-102961225717149802432,26969461377075245824,86730122212734152192], [1,-312562763163,346886487839985702,-93018430645583163427,-387503893699644070202,-227171488895637052053,1059383162575032981336,1901280189644540086305,1023913564393379937375,106567992233337642217], [1,-361474931790,611242743954816096,1973129339163640404,-4210002821826072816,-21443528944285721232,-15903091278377251408,17306737477063294944,15843200491976309568,-4434448077967904704], [1,-3778306,8394069,18391906,-34113836,-39223526,37637081,36203162,-3782500,-3555784], [1,-191995,18675888,-415738733,-487665149,3237735637,2525439827,-7701107584,-3455492344,5556122951], [1,-3528390465674391,295399734866669842800558,-2387118057773104769342178715473,-7115146127465248916444129922720,11963803174219131542545857515424,51351848128578616328477557919744,7113243674866320054741354132480,-92257589727819000341535933628416,-68487179831190246952800572440576], [1,-45037547,172457645883975,-1790412841228672560,2627143167768991192,9869078575652884449,-12596759728507943955,-11343571983898538301,8920514581505543602,836831771418477463], [1,-14544930060140,137330449552913,-154735085579409,-876479584619080,1181245400641645,1927455097458009,-1718524722383285,-1592842129577062,-167254737213209], [1,-1873500886,25283363424,-29198798220,-138943513968,158616778288,124060717360,-125965364384,-21725034944,16468307008], [1,-3806541,20782949919,-25366811811144,71965988436246,12103674791283,-142770198449983,57267830343243,20593396170576,-4139930393533], [1,-60381,329921913,-102719400354,-307998071508,131405772501,985414316087,568240988175,-134586047862,-1251538057], [1,-19205016,82891756860,-75612791103068,-22071609728016,593620957189344,99885969101168,-1527816117229632,-114091235429184,1291999661947072], [1,-5057480,64075800525,-114778121458632,342619789089451,253607005501671,-1403010587394510,423528819767088,1315290786628078,-789115629856541], [1,-17285705759,3645479098061046,-977455946035418697,574017488559447304,3349789413247368432,-3569470539005100288,-1037838976341249792,2354542035384567808,-697220011518488576], [1,-6736624153863,183177091628494320483286,-6180182788352798530510347577,2716240087955115185667279592,22390195136916081365570958960,-6868581589286990272316103936,-23220089103784231280127389440,2774463146325228316623759360,6830897897415504340570279936], [1,-284114632574,23328357826240,-297773293976816,-1110327740162464,569323040643840,4056968008207104,1629816222242048,-1887449511731968,-365569572674048], [1,-61113734390,16008403307648,-87192050722668,-8774403711472,522877371403184,-217607455565136,-1064677625078688,341515181013568,772225254630464], [1,-575283,495123480,-94146773163,-254138442099,329023946235,1060550521751,-194008114416,-860201958138,231411895019], [1,-8715488748,5970471668822748,-131516946743691692,-362146003783658160,550507485957558816,1689675762706695152,-133240171325456256,-1367117267311120704,41605663243747264], [1,-754302766,204635138688,307739257524,-2886558712752,-9696999595088,-10366769647184,-2966994334496,924587406400,210205089856], [1,-298841222,38173752800,-1269934926572,7899038846608,-16724081597392,-866792844880,54216158908256,-76186873466304,33725611694144], [1,-2022907274,153018343932907460,320981614532593515,-1651825547656661424,-5520681723930583807,-2507330145920455952,7612874974670639605,9523512831628249435,3051738873709998473], [1,-345693,380929328,-8222062311,40755162175,-80293086305,60679695873,375595674,-15404928472,1789630471], [1,-1171530,41629156263,-9975372520038,4403806572024,63987965950752,-13186797282636,-112717060634367,-8838630882576,39713414160403], [1,-15249215987703345643683789,65999669051011969127587880853,-57965945899301298379214742190,-480754726560884120624717949336,46654331036366608056055398309,922676089806829907322011185351,525899145779582992611381401751,803706295997501863197084450,-6533057249290496498299013153], [1,-3,-85,330,1854,-8885,-7333,67837,-61572,-15731], [1,-18999317,14188004237,-654799572422,-142273400912,3076892255165,436752369839,-2186399517169,-425979209310,-20092498369], [1,-55267655,19031864097901,-1323773104630459478,7816233223528156410,-13003751961452721333,-4361156381824269353,29106395680462736587,-19234804081092308268,-410206599790220149], [1,-412277031461850,21678032306781299848248,-2461595077336056893741948,10570781888949923022591312,-10667200780571632434652752,-10137987860380589840189776,21329690948753641253058336,-8768906897999430259248192,500089379074200034412608], [1,-6974625030,7921875723488,-1938747773729292,1214230999079824,4740127316419120,-2454499565586384,-1488131163123616,296470031713856,27233217614912], [1,-792296275135581,7157731383572903793,-14192905336051175984266,-56193023159687986802166,3245304106744257077607,240118027162073934066565,219593747170291395284346,-127601727583918000465764,-153555585114394714772984], [1,-67379282,4783160426852,-37576960879135497,120962277105887128,40492542396123880,-423592117788419911,293306304698596826,64540471360047660,-29466075743752904], [1,-885599,1922958558,-14798379535,23102811288,29078205681,-91476357427,46833416626,23835146496,-18433878713], [1,-37874815979,112053086952040606,-1544680561043401411,-6722143771571041474,-749983562147267093,20680704519842468816,14958350042389121649,-13882577924450532001,-12578727178554392743], [1,-31069515170,993008647032,-6402959118300,-2905149336944,48134362508976,-26066596030032,-84622776300384,86427873915328,-16089254473664], [1,-104969409,2035692788899,-1999021285887904,4277012701797850,6490533958588179,-18781551224385823,6497216849011975,7256037158527100,-3779402883441125], [1,-4555508548662,2674415374271232,-81556857978611852,-155911831259546544,195164499853718640,353033807605799600,-121630137797124768,-160738427156398272,53457532904521792], [1,-292626982,11992564939200,-330201914364588,80624084150032,1942305209216560,-245628921486416,-3461988496574112,-175512680818624,1550860071386176], [1,-173228820876,1791731502684,-1014936656748,-18417922724208,19590235822176,60388707916784,-68861940059520,-61536451698240,71275249001408], [1,-11246620216342,99851364475552,328388289229524,-393490018444528,-2024960633935312,-1892179994121296,-20385701464480,686502512699968,229322168012864], [1,-1237071828105,226330377674255,-1028826653892667,-1243355993777356,7113712215592584,1502735894044352,-14186021241027776,-227811750892288,8154199934755328], [1,-2880325,13051731,61229670,-55416886,-332621863,-257926005,24693879,68374404,11869747], [1,-1216510579279377834,226162806214537461603432492,-91363300579643873512882902453,-190363013774198779059661199340,320772368294364761476370276040,621146801883650894342167055082,-209967955680511453135279973748,-206835781623241247022061648872,46846125166425639252867787039], [1,-16051762116,19087414262829,-126691360247643,-707884372586988,204692259817224,3682390171810368,2263521694089024,-4668341182458624,-4304362700713472], [1,-7418819767071,2646922977548674967694,-83245372936799845908873,498860138779433263629168,-1152057925399851778938048,848492435332317598462976,783476452275007945113600,-1568089294433419059658752,672589256230703474671616], [1,-7250282,838327455,-23386012735,-34079059949,85710931608,65998729223,-89276257757,3941198888,4945836787], [1,-658926378322,18624546237015928,-2062234561069619292,-10800530029643230576,-14347395422084489296,13569364360070177968,50870831766432498080,45071763330662993344,13380496521121534016], [1,-87653,78349445,-12327824838,-54682458328,-36903462411,115909907863,154880615935,24370087762,-3917426209], [1,-438085,117367249,-765249018,-902080036,6285923837,1004191351,-14765116657,2699080210,7161771479], [1,-89381858,-142394209,799646068,1526254980,-1546314144,-4251799647,-1262470950,1268754300,579015000], [1,-1678781529,6313135911903,-888987461357292,461137299708870,4475062911662451,-2137281952110171,-4379994405324045,79551555963984,364326732434611], [1,-5621468032962190117,19721495932848051225969410979081,-494435239021384832364087405797378646465,-3503664529435812829750998396559356043915,-9124243100343144417050357428842011111837,-9526368450086740816186714808892443240283,-486694537840218958297274619641538468550,5828567877426929283173978233126673295980,2905667579994707534468750797365702380296], [1,-814194057585,414056472969393,-19420820935146007,-135767377725635751,-267506949366593571,44028334994232964,753808838498392206,873256330986976101,315197368076799697], [1,-48907,2168113,-15522118,40915117,-21872408,-102803829,224647094,-179223282,51380371], [1,-1019523,5276891832,-512500692083,-2386438662987,-2722713064845,1113611574359,2316252243144,-228547173210,-175243581101], [1,-335795,8955359,-4221018,-218609410,-604886039,-661683308,-298461804,-23856012,12327687], [1,-8493477,119548048545,-1039122579942,1104300080064,4829469460413,-7772017130269,-3487646723661,6666637397586,1090822908167], [1,-24148314,10369842460185,-66358173654029330,-184211899158470751,179153716075265505,863191377824078990,425853472285376526,-508078822351279560,-363722086791200321], [1,-91217336,11790289341,-293572970004,1239757219462,-1181507394248,-2289699741743,4943392317978,-2519232117732,117157404888], [1,-251463513,10440593464,-14265126137,-210419757524,-221483555932,501196160416,1091475057552,697417217984,146211954368], [1,-25940023070,16615613882984966,-829888106638892401149,3107103253174297644999,-337341923594596490527,-10542300455562618582368,12615050591111237515880,-3682983838644978274608,316368182375400330512], [1,-344710145293,506731498334954649,-1305002432564881675,-27770714167595284139,-100974973531681593551,-159136863919579149436,-110396521799745595710,-17097447266803771775,9483928020957047641], [1,-19910899,1108243349,-1950406148,-38850153660,-82634407987,34083615647,288974196125,324929315398,117212127463], [1,-9615,1189381,-10892942,-70419271,-89261804,65855479,155687606,9425986,-52554269], [1,-1147627924054,4374439941008582,-1169722829354124386,-612087790189978155,8807145419930617852,3294095723624945425,-21200736991273111062,-4444970550839273348,16300547401929510392], [1,-7771959873865200,24298758098496889106127,-13467349983140240629450854,-31435123124322071864978217,31200803159740556829335643,120465025183103142530732661,82581065775122714689153866,16184315122000165922082828,-210904929440283813831032], [1,-76777,759763,-2575014,2781966,2455221,-7052269,3554543,904532,-762341], [1,-129121,120356183,-1587001214,7055600862,-14501253063,14635813347,-6580536485,811733712,33502771], [1,-53749,13871545,-212064370,-371996812,1399479345,1662006187,-2712066489,-1696167522,1758914271], [1,-709961863,5807333837354195,-30105496773035385164,118414882271428824296,-124409004468477171111,-6841469921742780647,45908280183240492363,185601242150477146,-3309039887809200593], [1,-449844927,501967196801922,-72847833684086316098,188158281820054449237,-42630456470973039012,-106990492719289674022,32807845530580852935,13035007653546210654,-3390566962302687329], [1,-23035292,118489036601663,-48932375051930605557,8568147074136076147,390559380607279426130,-92321152949709386920,-955466384049168573505,215934908717498580239,651139902668687666017], [1,-1682208809185979027263740087665,38460669002109216521306017047488771434208899615232339,-789215380710611948301225849906279583250175442757096555490324572457729702,1298256148668053925249650971384686586826702470064914229044090274999256215,6030329823121832098863396859553835498131032809403984593479645183753512324,-9490084470419754437453910267860740292415249457134746840897452481872148103,-12394600943847745519754407531435779729178452247379772195631334665755880166,17341080285216312802767349120791681272978457502031451943896949208999010428,3296271969194505878859122633527852637478172298602731294774862093346579128], [1,-1144265495309835730,49923475084524347869216,-15995488733125357472577758,-48796962740367288699108596,55713495918778048738211031,264166134873195160170026981,71070428772729452084221562,-287282783333568985533701572,-168386733883938686911812856], [1,-57220933917748482791055,421432683704137008041973785434926,-19706728990556038367918172669771186953673,-12723424145005161802854383220896287885368,127580657871872145892123207192434478107408,65741687506553976917267947208625253170432,-225142929942783048993990402047872349206272,-69761989665958342964660248694611335247872,78030709323948095525370311539795889876992], [1,-439201344361100057172,298682339369083510723957169,-1993819825297374478439136896,-413303435630088983138297958,14748097505558080719171177748,-9462024177248915246648070223,-26659710763054612986043303206,25359544965613546263800593388,-1888978298649312011654077384], [1,-5802127263,287719052234104404,-28057294707841304943420,35994973074431882507118,93560769205410381354270,-68930980457931982724892,-75581789160975641071308,-2168783935945534218663,1123856354218638808457], [1,0,-1125,-8187,418527,6063246,-29628708,-1114750107,-8016271533,-19159072973], [1,-291018221130686,6177811912283862896672,-24098188560084773665644,-55048694056791696049840,168071111174651808652720,115168131681977741268528,-310410872603033686377248,-2220471709185131354560,40713723811892150741056], [1,-45742676674,13285226508600,-884300379122844,-7924935686070000,-26863342798122320,-44887054617934160,-37686285269143904,-13497695087511104,-823934867294144], [1,-6812707,29260293621,-3863681916534,-33899272787250,-111278748580121,-166973063735213,-96219537975701,14879138337040,25557866840803], [1,-452685,258015456,-32640097359,-100508736369,-549156225,290122084313,369635601162,172652033112,26034334007], [1,-828120321,19196894484243,-2089902600280579,-8925328592739468,-8315112977750355,6139800082126669,8199504364294929,-793429782322065,-1642176313344791], [1,-29399280246084,41736821359896213,-8689441224824011203,25748899993528535340,13652429148325027992,-79459998887124758848,4683397865515364928,63322739270171112192,-2397673249658495488], [1,-25665087553029947767,5002010563050666885419506918,-4640397039631951425031718106690993,13276249105588143916264279701500984,1544827222563604148108556918471440,-40633243602231836771322648275415296,48647018551609709297127556195926272,-20092948136529590566080329583429632,1899626379682900076985335069339648], [1,-4637070372,267390918364691973,-3359070220125120611,-8105967729252032076,14433914809537703496,29396438188961407040,-16037510797635992256,-27512591734201443072,319497287955931648], [1,-740389088691,5004042945081330,-151636472754243634,-523513097234815119,412846622368142655,2424331629274400332,849682242734634177,-1814618342964912189,-649092289960547063], [1,-22667808,21478629458,-159734672882,310522791150,312843358201,-1596160761077,1087057090346,1013551660772,-1068737159384], [1,-118268599457732021762,13399423901526523925888893396,-37425136346633436638727167810220927,91910191137993644964843610826806732,158700085555037722899767217847608640,-466718969360496984942243557276658311,-57994110985325353303034094257966982,489803170996960297784106903074766828,-101196279482189530047794770391958856], [1,-8381463,4529381481,-7123725636,-40365253980,58609388961,112828469567,-139876332639,-95346809970,79811896607], [1,-190623987134302,10493332733817654112,-200976379697735153132,-362113359089685425264,1357637176890689247600,2000562870652299770800,-2241151875769637504288,-3021369928455051919552,-180984330143355512768], [1,-545911781686038,1730369425087127616,-272632842836862857356,888993602871827854480,191956349995970603696,-2594867433851352350928,969701493484050638176,1269690910288337998400,40768664618894583872], [1,-85874508818,1654204738629592,-716784590322130460,5627245910316387344,-17839758794358300240,28737683622515717296,-24297806085710613088,9830990459438087104,-1346093235942890432], [1,-27076783192750,24271758572883968,-243037537579443116,-2310073161266346160,-5326182729140894160,-675777809414818256,13147788338535368160,17552314353524427328,7070510147611960384], [1,-21155105313,1070254921430139,-8712148588351133312,-8310650783259700974,24696514940072822943,6983175715238778641,-12380078215276546173,-800178352897745916,349756210435254643], [1,-12385688757,1916080199393019,-58741618673592542228,26929663025166493266,239986041238361005407,-12316995824222759299,-248523201105492395517,-58399583014201665996,11162188846705939387], [1,-15580412921,10623466568,154966313561,-51279535173,-535328756625,-20329193443,668167599734,246541089532,-85980663233], [1,-1891790001388,574801216007853,-13941273621114531,67799559326838492,-108653948402398568,-13754837500374848,207321333594705472,-191671749190377728,52120943273655808], [1,-762692554055132,188338536604999496013685,-46929736652845070757445419374,-57831423295578968941024692602,204770636072818689433603599849,160466853240255751165397666568,-263630344100570306422895267718,-45159126601739526691377711235,65450970623725405682676537889], [1,-3106123,810597809,-1876412892,-9309480837,20165946328,35098753439,-71648543976,-43488201116,84488560031], [1,-3918735787722242231421117,80084232039976969048861461,-429331637992124079459325854,831075230218880302651032120,-408725236905283779167498811,-420414034582254809217609993,361175537167240879449700119,35761097653507891045200210,-48640722933604597956528257], [1,-112011082963371,5899066359243887720046,-14995174545778923704947,-34251476632829243370858,109639206542080354146123,10175095996245722651752,-196595181254681388459807,130116571613861427796599,-11528618720994558355439], [1,-3246166543941725424,151410873803245034545931959,-110953078534039896467952064542,609107951424251899808848415239,-1121115269275985262145454134649,637639391393057012614116747237,232557885323381458359435104522,-260101647651275389179436402868,16856809039625836040762310344], [1,-120054372,126025066500,-1421354175318,1353917591943,6080973645663,-8845904223982,-1484583717465,5457878297754,-1388894309713], [1,-46957890382377078,570204983223035855740524,-25672873250292003289796170440,33292485242970903574364959872,150518964306624020618101483008,-181040742420192126948708179968,-213632903931162431063281238016,195891936156400167131409285120,69566168302856134094250573824], [1,-32613422196,13293195120138093,-1451198812942745283,-11756808143248997588,-32085693547566336488,-24881695260413271872,37363082983377837632,77251669176633041664,37728923163711151616], [1,-1177876571708,6366485452947343117,-46575653986899163507,118087889720953902204,-102687859188394641768,-32784338554941935424,82031747722754312768,-13088162495314385152,-9550737546785669632], [1,-106193595,4410985912,-41256964077,-99838531933,157099639053,265867078099,-92388561848,5247677968,166889743], [1,-23408585484,71423272387788501,-5957416320204490299,6046568575728367188,17271011510560257480,-12692446337212757440,-7771006242052503744,5134862897421219072,49153182042931712], [1,-694029721,183524338905,-6882896399490,8710775797688,20599308065701,-29781479801389,-10134047490425,24318968190922,-7450233496889], [1,-902673908688158,1392214421567394848,-15624512933141859116,45976911448034913616,-1847088925044495568,-164925717518358482896,157602672401859580640,105528690493768488000,-141810055562534205376], [1,-145135715,1186849347,-1232951040,-9840395474,18746113329,23583433803,-57550208091,-12643422272,45915585619], [1,-1137129,2442823,10556386,-17706290,-32192263,32586259,30777579,-11138776,-8089213], [1,-466028963406063,64934307251398103646,-6795302529775113006487,-20111248346049663289440,10166165643444478722408,51213693101581443134377,-4938111472168085906118,-31715758212696299786004,3018843864850336077112], [1,-9987419931184017,766560303506581526663724687,-73777573791928694859141506558885353,240702694079437759281909426824308596,105453916148765716102467506033386794,-909588225036127831694292097476051563,434609095030391040744938868028123509,574516931945941600135504148887557936,-282567548391085032510183482287898684], [1,-619200324,247155304503,-14227997035842,-2932198663218,80360375375082,12041228088737,-110627350073286,-22984587133092,12136738671032], [1,-194430045483,10930146184233981,-37004080723791054054,169726782696692480550,-121850854246462427577,-419088703965457667649,644180698259593014915,-130415057098479078768,-77994015988756051997], [1,-37014675,150133071037,-89620040871142,-4246798262090,640816272972087,147122927011511,-1170139960911845,-531617720804872,159192200026963], [1,-1085703,3628104285,-197606400462,-400590842046,571459462659,1475071012244,732972054948,15568335054,-9004627981], [1,-4805757,162271526,-1207375811,3240587248,-3189146408,-248324480,2064628672,-711019520,-103058944], [1,-8082773729841,7260177718541589,28691529131451941,-20557898848641255,-213364185531482127,-184371916552970420,329892988876405854,601797085412257449,259979183434469281], [1,-327891526494659045215108397,12415949753135545692786849440153069,-2528824608659201824230894171119626984446,-19867650886035452536415225545819645157008,-59490878386915725860364903888898567091339,-80096469746659429846156883572389294365529,-36334678633058706082811834269602763167737,16048305290574653957540109247696824131978,14598909565142137515897772375275790462111], [1,-1046380114073260670,20461446800168814236788782402,-1395232429054800226055784119164,-11814830543579397346428451421,5187235222648332575642588530166,-236870611278038562893157010142,-4651363385403742416925139405309,150561742385028119335244624551,1038951692548448313014037731009], [1,-14044369,12712692256,-286283415627,368099638175,1245716824619,-1974026678075,-427395032890,1130080662208,-32110434817], [1,-5189841843,23667382972401,-12751055463010026,-70854790453915134,-97420334705757141,102420442025729991,333086507171382423,198625307893879704,-5385976036858301], [1,-100447264,2367460909,-11647735164,-22659089650,114239885504,72479652193,-359640790390,-77397327524,373442503832], [1,-2137478889,106206931677635,-137342518370245600,-548950403860134704,-806850507473777605,-509923887572030632,-99145665684287766,22120067430795354,6701494189754083], [1,-76845191,309627891,1178754408,-2684467622,-5638221435,7036965267,8677867233,-5024074076,-329883557], [1,-73349517645,9184526794530,-275174935414557,624089227488372,736671369199572,-2530554989347968,497043204973776,1702306987221312,-627298115144768], [1,-314188397798636593619823,335970190538190385985388108,-2414209575658577982978368202,-5403727205452820242763021868,12933423122404575469588280664,19593247481667281142338815857,-15129693407601610182001856262,-13604065318256732137470719220,7457050262510409218629063672], [1,-19613331564964,221825287915904845,-928652730777886419,-692577743679720820,4056206153338650200,-326088834466007360,-3929148676265343424,2185149010484329216,-265604387866161664], [1,-3981185570,76011080711988933,-23874049544574829458,-136138771723302192998,-240844682398345291548,-76918201009868870223,155033768170795859610,109760640295897249900,18782705380108675000], [1,-172918841552596,3326082333651752197,-77606226984224548443,-323486630754573011620,43392800154469323992,1311641451694761581248,833149624842987031616,-1354833569202833797376,-1213199124937137459712], [1,-219939,25656614,-148980261,300996296,-192818528,-86227968,120957952,-15949824,-1933312], [1,-325039,3248407325,-61496266078,208103854874,26916787075,-960970439460,946207281740,582283091062,-831729129029], [1,-27077552910,996329801790,-7650375746856,21540998233233,-18800807089122,-20061209044887,49042182145770,-30149768524068,5007823431256], [1,-28751530871839,10574092487997798958822,-1064233181826773349067411689,3086017265431827206232691784,2585812762794672936236166800,-12627806321822040150419161856,2591019949720475543671503104,12609645435265892314981599232,-6595161125977310121290272768], [1,-1167525,31775760,-249446135,758488911,-920336241,222836969,228398058,-23167992,-466673], [1,-25887144925806,3228307717735968,-83460145644098736,-31254690807457824,701552749826173440,32196751623863552,-1808979773357928192,147213095097255168,1319250460887229952], [1,-186067,8007080296,-1865934302217,3966801254303,9764014243985,-22965783804461,-7322978196952,29716362405820,-11181475114489], [1,-9105950887403324,17666285281338173839583953,-570225555961995219052493620,333720143634492832572686024,1257498900967760044752503413,-71646383269843578661102537,-323577514416177359919299151,25676111897036233933151855,5136184155827329813126817], [1,-407428497251464,1169129660369347454339,-12408323314263781106933,-22924663153724183062269,56734592730273345953278,88457730891209789862388,-46732029534409282400013,-57420744657176302056509,17302177255596979365593], [1,-213213855519,5423797965783991833,-1071312540597931185690,-498371991342578083170,5827169960992863316359,3468725904869426685603,-6569781497332253668557,-5369231464981086373632,-798079038447414756797], [1,-39145644316170,43098838479383974936,-1393381401798061080472636,-3902984552673438037505456,3794052851460402331786032,17307395339038214282812080,7735210768810043394014240,-7927441531908453543449664,-4759108912905967023018944], [1,-71587718645955734,417709663167480853549472,-121646909545951504366970700,178902787378484431960104912,289349589287143068373753968,-622054227198478243591683920,331988161251811787761431392,-68106746864077162624351936,4673098904747061778490432], [1,-4705121338830,188778652339574912,-86569198544652853100,134884524756528912976,310097710221151687856,-423514086093021322192,-287314421675886646304,299569972394547221568,-18948072597586879424], [1,-871311988917,41911926136054575,-17588024008736068228,-120949716225573676494,-238622182867805315625,121301920871698218781,1024479863088054971979,1286847499723222294116,524750985381154767083], [1,-660365,155219491,-1477944460,-1948890582,9157180447,10047668573,-12801064069,-17022201300,-4708346837], [1,-162440766,9725435232,-139472754732,-141447952944,651832308528,463200875056,-409455676704,-139580609472,31344580672], [1,-73991769,3779656539275,-1588324550621888,-2850700671540006,6639439780940335,12458178772978345,-3001336183876405,-7186195488461548,1228560936643291], [1,-602280,185127438,-8032330614,4655899242,36336791775,-13888605445,-34794992070,566261220,5905586312], [1,-793305427,10722262867,-37799372520,13250340782,134903221145,-150273057893,-117445140091,161375702896,16536355067], [1,-7241081574,25886115248064,-786523151946252,1487821004382864,4799922480477360,-12254503026731984,-3204019391007648,23648365707528768,-14001538998804416], [1,-68709109711103355268342,794212042694172998959675623203456,-199639739058313536433860442701516,-12256667642945599347878098666683632,-5135370218322307255753488643369808,55826302577396829528549641891338800,42093919672649181457791027580818272,-78094346463401717012162246496433600,-73603759196961759355613981208833984], [1,-3333295274727,34572781123653309,-11642536353513403198,-23346644708711384862,50795498459103908163,109640146196378460331,-23335310666994177381,-69139738612718500884,14647493405052447371], [1,-113,1176,-3819,-386,23467,-28696,-29832,52809,20412,-29249,-13190,-223], [1,-1572,41840,-301023,589524,1129931,-5022917,2678727,7731400,-10207822,3007737,369710,-116575], [1,-46755835,1206514419,-5981923871,-20191272521,74416768475,265724484731,116877948397,-443728589789,-721745657080,-459066275673,-134096733890,-14549748671], [1,-264906556,164181027958,-18724183114540,70479317370001,72968634377264,-492727397394752,41734123101312,1145261155531392,-311954756027392,-1066408976920576,177404063801344,324503752118272], [1,-5714993505410139272296507009782216,49344904230148839293333660593889114227590536,-75912374820652001820427996265214005713100104096,7989457304633369412761744707841570955171670040304,-15974027141958161121922623941579887028811517171968,-74507683121314337453815413692153070376569859762432,171572955584394974398431302183548180568510573755392,196203312057724991575518132602141074697099154452224,-592343421549858666594462955237479564143319009110016,-21950313161471530090788036532799002703196428335104,665588107659149680139605375551402393227427753877504,-327313607586270398972920248639723917317625964130304], [1,-229977242,5072291958437,-111384225021100,762216494900532,-1477672431507456,-1588524670358112,8220409292590464,-6523629466987136,-5815313742183936,11727602200559872,-6334684476656640,1139431063577600], [1,-6882808231898278414037342656,3455143367204290127157342521604388436332,-36661537168170277066262237535877306066556,49588942370382232589832601858597528091646,356029612847288265291799825046259689332740,-524595811862855775985469194571914871611070,-1025519268248587041651819209950715500501700,1453885449064670671053483316089032783488877,747401846174933080367524379803979196331968,-1239203088628559715562735153436589082944258,371531325751546776299376086652334941513708,-25967762675439783998636643093161918358399], [1,-776227,35260611,-410113332,1237367010,2841962582,-15400560964,-1522071034,58779614473,-20028404187,-89273582271,28252161234,49612618017], [1,-136450,5782301,-48188974,-56158306,391808464,181381185,-993288620,-120590148,904251232,-106435088,-198059200,24040000], [1,-185290035842832019128,489482814788592695857251131528,-123165591405668541618484310233779552,1382699398509947087245384403121233136,1451187676274817203561770378629695744,-13349894710179599610890326621200296192,-7161656140212798022704305275356945408,43064097291752964399345748822207213312,16507693434261046711880963152245303296,-50477638084627481625862451247360866304,-13250359536841308975630870347363442688,14228047455441382330877775957566296064], [1,-75175041843787104,61342026170367580199808,-459463266498901473284181276,1317681283458970522968876746,914122129345622228984628000,-4650476380148947381939741522,1679357874014236559395086036,1961391076946617638906024301,-625118212064863116606332772,-340301790330722833417811686,37393240021622932269078624,16301182707955190633537041], [1,-103236086,1999763737347,-18474454131370,23989959263891,154675342323716,-361052854031686,-347070912266276,1292028449255827,25369597086578,-1592955973471413,278906963487694,623764364353873], [1,-32005221058803772,4637628625018039965419958,-3717203173067266200276095100,515928600836885426751576737537,2320049127272374987480220302912,-336813174821028838294852909072,-15025829957190389847037460506240,-18686879576562303590015975665568,15747418480602911176531575123968,45665292986239411427949932910848,29894966333608668824087612589056,5838410116627764613546230919424], [1,-88609157169,692928400278227226000,-18639810502615504141898100307,205777952269910958141151211118,-482100482299731057868364980215,-544825876501103943774907374028,3041454447812245838666224632240,-2257391223497009459404058192895,-2899875613277346059907829946934,4886609292155880670960692388815,-2131600168767190456076052602130,207947193981122938848112605041], [1,-3183024216747548838268,347142389627273461829262758,-441720998655169990664213630864,4524051142705909842996317944557,21516534920861500399431369303444,12595830718870799466701805370122,-52288927013806481740769778432036,-93644009415943389791426854732746,-59025104012256737349525392054516,-14575361103996761413374764908204,-565750002074801746316160856768,165811130561518571726921110129], [1,-81149837561968,58618864154304079578,-10830571585373935637269404,559883747296995376809712124049,-704021501828066365749085402734,-2399148964611094599666442234758,3316182464824620576759571538086,1774891982677587277011080687322,-3555103338212968630407231466105,821712824228692877635550872675,183505222060318667427166134250,6885453722596067903626375625], [1,-1563597153071082805844103218753996,67018408332460754570119044177545638014970296054,-37099623251162852103090511887535812015226342243484,2192103164616289787313759550176665641270606908066305,3243664850340545232184241866506929046611370635737776,-10514814844966903945501503146066088655871990118947664,-14593405378288550597224538554184727096639754156996160,8248342728040074458071264923080698568212480136102752,10243276134747222494276314221993162945870371455561984,-1845163538579634478672993723514426190163328408691456,-1777735033500819774671164457229092452663819911004160,154226446779924775048387201885796557892082364170496], [1,-31223691959794830602,42765558803732842831684673,-2162188858003428992663539272,22770781950430057176647472882,102451102783461555146628667630,-112668144173957992900965272712,-704253264672437025442827529992,-120308852756586442278247401279,1487503938885226109640060456728,941700250082578881601264792984,-685422721638535434474056198048,-502933781105705055904786490864], [1,-115413570,287574254057,-58930369951719,352419522365346,1169402955316028,-2959989895389245,-6672131819310801,7192141635813067,12811780547077466,-4190604601917150,-4269036523999336,678648868147889], [1,-20591096196457859900,1840165796772256356932562727958,-131023868085871742456573444328908,701541835202696113652263210173297,-977060642871327547379950033689264,-894856974044186745852632084570176,2756921144494190878619328965507456,-668446399254552912794190974754176,-1496860430561691770146268333923328,603516994619292536597205769392128,-11814503100330293795716197736448,-1872632051224425073935746363392], [1,0,-1820,0,136936,0,-219035,0,32426,0,-1245,0,1], [1,-1838,110466,-1457530,-594624,21403672,7660335,-108811868,-64537506,201749902,118477401,-163628568,-66610521,54780838,6013838,-2634629], [1,-31231,3740300,-91245378,298050327,934268992,-4401788427,-2431740698,23399074654,-4515560125,-58297569578,31288267422,67359582176,-48602354979,-27725192380,22560578171], [1,-40906,4286270,-77984287,300321740,106381441,-2061594435,1180829506,5534987315,-3707589161,-8142120477,3490266018,6790116438,-312434143,-2360372242,-631502281], [1,-18809,1007298,-19194788,162121198,-636963643,1090404363,-104031362,-2310502773,3004164956,-1048406868,-331692206,203203153,-8625326,-3759294,39563], [1,-280247649,12370143747059,-850996907727117,17385934340695578,-104953177346379097,159438058163777720,405739918822250928,-1435006226138656256,743609052920692224,1986922299122192384,-2872064678639902720,712942514844729344,923102855384727552,-660573116061712384,124295145963126784], [1,-147688084208955,162514697333979754370332,-143071328373556693619330813,814498028407902816901453997,1196611416136583566907442618,-9230269879970666415572781126,-5425788355021335902884454579,39559829432680865697441913757,21760961992967478375384616236,-74241951529995456358177390411,-53798271555346409210041704986,46955989795933394809385282456,49835178466379490784238600176,6845569936271203166407322128,-2455600842687476406035136544], [1,-55984,12125520,-753020810,14698113542,-10692173035,-119906892189,96604699315,352327599777,-246807485043,-429478006526,248789197002,163568577073,-96696233259,13402072876,-354876733], [1,-1558704,11732227927,-17345399656327,7366503686195955,-219574743844310286,1050340456599871611,-735317912369847266,-4907175335868488768,9266149963815066786,3225135837007914497,-18338172819145680515,7818339608856537238,8690381388382833077,-5833601680346328990,-53861918546721361], [1,-47014,1305366,-11961382,38360176,27298817,-406153819,532893405,1091715987,-2802659689,-217964548,4576634412,-1968144183,-2321534605,992713950,510072919], [1,-1468556417308,8300573606061360977,-2705938416133717124406,88913013089260833668088,-724328419046932245976481,1018249670823443732932416,4943137677182200075532416,-13176958801527732381953024,-3702816671601945471262720,34434714043481702461800448,-19941833091022080943325184,-15466571196576506123911168,11141321908580043460706304,2504851002933833130573824,-1206197920399232258277376], [1,-145550294,227269379365,-25771911970426,342428330853015,-1911328449126942,5363840743877974,-6826775727050422,-822314470569433,12964880540399583,-11801460015689989,-2874370303777420,9159227460645875,-2583732509408625,-1835556642885000,850347584171875], [1,-89808081674911266815048,79128424242713365122209007041188013157,-3052605634288681896804299927151469576341541685931943,24591740445889625411404075364678274009623245146424112178428077240,-17295013047448966608202709921007706026591999795959417294752856173802683699,32065934259538323730519329339477925731742492637748351705129217070213658440,180607570389961128875518521066867058106924267586859262925565140714113736839,-310783026814865911699927351862274732318782062129735230464762961875076241643,-702304544416243133992984157877194404768211184446016846306225029609718535980,1058727794193198264458438705495642936140864153797692639517740426916759598389,1221126278789507833801318925491932404091838452610087168109897350161355693478,-1440615126322106993870227378444982950194867821903521311858465280054265740520,-826267695361720929583800717830386241328018992164187448340917881743650769552,584055962731112025260083552274427498515225164253321542720142989848153502736,28668284880261406684208154295930066873387643924604067624639811913733221856], [1,-388076989,1079758962665,-281006949020358,2301148841669910,-3410848405792517,-17769471739473636,56921951799902635,9594228172805605,-213590792333203357,191641376766491029,201891846345306138,-385039239395541241,133476271288119771,48496821572762834,-23740268125285297], [1,-47962447,344298998595169,-1598332423506290719,104781036499703828895,-749710308556203862066,-4349324659762972691351,-632975120607203069430,18754307769062652874915,19566916842088227057339,-11596690452466850281895,-21211124126666080071840,-2795072395379003358055,5387658101225234848338,2195619029190942811826,204373679742809086883], [1,-16518941628,5965603522057334479,-7902534202340150038231033,1563180197295523061482407892335,-46882526739774604073556748947752515,199012743910932707366382724114583796,193796820300599395174342295123702072,-1867627039195345259033198899684724864,1248034401840430437165453602838706816,5205132319166130315425869956472064512,-7581715285764862346487806635495281664,-2219003884964290099007728441527504896,9678066934299569255447806826446049280,-5773320352397120248544510362810892288,1009574104375918576911526017373011968], [1,-214049722596,3515714950664743487,-1352763252743625525233897,134556838299926508927771395895,-694229409087478927613911873976723,-1102057343661796638891548804391356,4122358655749500542829101852368056,6567735440113497250488420670505856,-7532406362362521310529100542616960,-12841282877968992332152198801927680,3381821301827390538283885749808128,8356624089583657435604470882791424,1493225778137995040855190707687424,-199261734637216839574037309931520,-1830221442717099448219317600256], [1,-743770101390697,179419980281548028514163,-47209784662238068446421397693,1248977050905179806682070021106,1138108288107148036661401765271,-16195729635522542904392224321224,-10335199330314339547964315816528,79093290025996932849843874650624,45994798119262657358160806641152,-176564325311670661882126639722496,-104241905119071943248240054968320,168410248253547783422319967862784,106300676916113531032996015702016,-43266322876251150948515193552896,-27685068885118507173495257956352], [1,-1139079482,9939596145423448,-1902335933481257389,117425735899567780910,-2203383527933426907249,-8743264574237991049024,12590871955008258625152,64511776855381108698112,-7620215622544895725568,-160648619168498645729280,-43192155000817402511360,142877658633594204061696,44786017920496170958848,-34610078159668865138688,-5023825047731467976704], [1,-28249891883667623002,209333791113233162830035670621,-206080823889129581613504494878551149,745711151920412521002496959709010921922,-349900362184470467941911122602681421536801,25866755459018097671760805134724063035040394,-218360750504778413337426314748621266761874617,726694460005575886021746251339899033147125897,-948101347386199003904663020605411105820179610,-351473235980877001164810248335701001104968716,2263115345811528628293565339506776266436277322,-1628043327174614390095620802286856399277274247,-1058795307729955319256746357017277202924597536,1647620403823835898580119036145445721584451129,-123241927747452934984757753685795984657593930,-445672242624063036022259389581035096502293254,70659594429098734590418715111126748446091156,39508671506444537160482623431102153222427649], [1,-38916737668,1528799614490356,-2959843739298189104,150572195870418370016,-1887499327892869844416,10111591039381440766592,-24333285436127064356608,9015500577097486903296,83798762809040412580864,-175225989236014069346304,72431666294194247462912,184152647584566164135936,-277161654443569499160576,123482629056011438227456,28344410041864025210880,-47905841572526876590080,17103424167689825288192,-2096255434680407687168], [1,-1275747,575090691,-21949658774,205310705256,49953112230,-4602380202278,-1053036804867,33434535620298,15540401250227,-109588439593713,-70375383550812,174662374195533,138502456852110,-125360405379972,-123681682521918,23360045823231,40926121982052,7767192570581], [1,-191284643876,6341580163006836,-1934761696042349496,164849740308816714448,-4754806011233115697888,31297720637036736916912,40563063715135443568640,-447349624075426149585792,-106666893295835639752960,2465625625557089016418048,238299557470283831347200,-6723424858005364092543232,-1437413580211248751588352,9098140489377774130455552,4194676060685113931065344,-4594013743663310745149440,-3833217510275099671912448,-745788684857196104839168], [1,-11750704,1200072194,-27059115460,275329643437,-1507066331248,4350637026294,-3402695953616,-19674226511210,71635260352328,-81896826447748,-72414392799636,335995637293393,-374570043319420,6375222215324,412780308002080,-455545471094544,219580211621952,-41955549898176], [1,-205266599,3059043580551,-7377470986131672,255750467781184134,-1632953660152413431,1068348929913192629,15919951883702020817,-32949097618499452897,-41812738164568952022,160392472026537870106,-19845888168060926647,-288196883084542066323,200932996304757155217,155961581801981478736,-191793894011410484713,20117729114239674902,27921588898947726276,-6338062216813197688], [1,-45609411820,264233335559214594,-66441505779889023806,1651301768353913905227,-5702509244843790310454,-17718742162923383793609,94554646423607253705100,41437587470866244656495,-576600445583458394851654,185162070050586644716796,1716238691984098960776328,-1138541205600600045107878,-2575616331400632645628288,2165795832813798728006237,1728370435725705408915414,-1598090764684425326864451,-311652308942791826171932,277546280986572881143364], [1,-1504162,19478258228,-1774538541554,33455987402844,43770320753508,-1315720656188287,-2806299428446827,13190626459075508,39866462208944136,-42146184067179328,-226648796078997568,-47571258714568960,562561066722199040,515663033658126336,-448457920894472192,-815336848346726400,-205333486181974016,175547802745831424,85189809140924416,6179324718743552,-953640242118656], [1,-2914968254,729565958618632,-37698933666991280689,557592894223395782959240,-1616283511372600082985105238,97042988438726838461737336436,-232284398484404334687457106105,-6732183788640945316473023556024,-21348108851313726862647539943344,9922779856397149629502473433344,151080206871502990665840133664512,191217808340180216960353992423424,-216777783257003298753858212900864,-657568359287067519413657902383104,-264659148877840769934330259767296,519913318612345880722233221447680,525921319263424904995708534259712,19307792423762224049692793110528,-124791473356889212827540555563008,-16503846133252696483685908611072,10339744705904321576640217874432], [1,-480959,127971287,-6210024988,117387642442,-974058483871,2716073861918,7176144743881,-48663748603594,18221811396627,253842407160806,-280982367878873,-541503028206526,840715026571134,401195003303691,-937048907916075,29239682420856,364610731756647,-90373942881826,-27466833161452,8779464511312,-163262489641], [1,-39941932898,6210764439806586,-5769357270954813832,1526235405765947359933,-105496607496711652450502,450637888725327737131320,9650202211913359888961239,31737300783657595070950160,-10913973852576470640831520,-245106653555832534199738368,-427683566166591584370447360,43660237154569010897502208,877952103594834582382673920,792609270976277877255831552,-195542552331371677253369856,-644898095720832121314476032,-295879994185715924103856128,-3536321127891585200029696,19459832831021097932554240,1829846937231585372536832,7561943891893450440704], [1,-86337736,7598242460043,-167569983434765540,17305983969682532799,-292019419313169397092,2075131431123040068658,-6665424416191304282566,2295068132975694200659,52514343624238390352037,-155524020328280599942642,72098535485922177259119,502162464846325947972732,-1081612566036474720415173,329934201842389030200420,1737975836203010588034872,-2616168718135781832784509,780663560042069680589185,1552368103386097794485265,-1884069429357675284396666,861632370133018734294910,-149417527248961307018797], [1,-75050219,2577820557210,-8708771477008617,10240537455834038070,-4171566442262579317992,166242467088694549400458,-1033863257761812234666121,-8510117703992561276196134,-1712218241553391418046499,59073478059006844802989434,62496120000886690394671741,-133496170027675884289942785,-206919534061107404384206114,87453839145789156887240569,220760986134809816904048267,7507090977497795083539865,-78187519420065641576046009,-14126847417965732398061212,2838691415177922884136661,323334550937520096385754,-26940726295898710940521], [1,-17381757580476,43726977976046475,-38587155046755611490,14404264950505670063217,-1992519320820093070368720,21131148543713011874724917,-40503643542455943304425426,-221092172903838528916304883,686267541176044244116291476,934545360515028736247232153,-3842393422466848354481305014,-2297337276469143012081280444,10852822516123803157100624352,4469779496649171224523959382,-16461707981027715595966487388,-7275510508518637850373793095,11989066274939596734697677612,6820828079009357932513725593,-2377962517799535371613331494,-1864695755179413468652723812,-215224289114498638277938504], [1,0,57,0,1197,0,13681,0,136854,0,1048044,0,4603892,0,11460015,0,16001100,0,11131014,0,2739339,0,-368793,0,-7569], [1,0,0,0,-18,0,0,0,9], [-23708160,-225566208,-1131314688,-3968372736,-7276863744,-1112932224,22694392512,49279399488,50845741200,22483386864], [1,0,-2688,0,3413088,0,-2724744960,0,1535600481660,0,-650301043097664,0,215057090579702112,0,-56979500534544010752,0,12312194148189466704810,0,-2197264040603188502904000,0,326768343229764821604655296,0,-40745795222319658376664019968,0,4276794417515300890531785084048,0,-378647131200860936657636244230400,0,28286761991498448324281307379182240,0,-1780798310985522419497792899399649536,0,94205009985586665787286958769846028883,0,-4168270688350510971203431806915951526848,0,153256282053016072956650306840248729289280,0,-4641329002870144811569747153738728312276480,0,114452317987845573283355038818157554058821648,0,-2263985500383570937855397654604966209249105664,0,35234824323208949432122287222843195049195649184,0,-420671474677100937747713465131110877388775747840,0,3726806815195567658159272381046654302782322548810,0,-23439111687336557701224954796394993807990875876416,0,98647323369477358239247622147334076753681287255648,0,-257022322568849250028056718999196809455429653200128,0,377528109863340174709450199038785141413258084463900,0,-293678194586629498753778041508197163621948960832960,0,112835081178121597247315790519267337889550215700672,0,-17664834640659843760086846517563699616091492848896,0,464167528830919430707812939827867130195290216481], [1,0,-17229669740904638767885350393332951562413714341828385758128479090081583244187998208,0,-71235119005677090243907227200286049434393307742277600967494975973115889925067636736,0,-5259378713381781018295191965451438296538249792128869065118144857985370794902945792,0,-67185232557396629198034682141700718381157435991581841393585439368871735885394083840] ]; } B=8*10^4;for (j = 1, #v, print (j, "\tdisc = ", nfdisc([Pol(v[j]),B]))); \\ regression cases: nfdisc([x^64+2^16, 2]) { setrand(4); nfdisc([x^16+55217847968*x^14+11568829819230010799488*x^12+19573246544559873463135725971456*x^10+115798873240393273382017613115315418501120*x^8+9751010259434557755318401766641355472978476793856*x^6+2904119935452194825826787270394602800779367044985691045888*x^4+6769347776028701650273803177165355131571803342503490887843053568*x^2+63248430005730803250826766342470963758035727918152866840245543135870976,100]) } { \\ #682 setrand(3);nfdisc(x^16-60984*x^12+11303671896*x^8-20089501740000*x^4 +108519183506250000) } { nfdisc([x^24-550424160*x^22+23447555340004224*x^20-254383477518162636864000 *x^18+862812576554550932720517161472*x^16-1110768959838047114430666510009753 600*x^14+541867253550600812790187039808706018508800*x^12-8880986872306708993 8371545135871969866802135040*x^10+502809538666033468057546874414277270924367 6318040064*x^8-104322413758462359374825625780272604972404212502794076160*x^6 +694786520666433058606640970483690360770938934881316184784896*x^4-1330062293 022709810755455132342051017217797022292939901816012800*x^2+16121742882523614 4296369045049933195993063619592571720690380570624,100]) } { nfdisc(x^72-75690*x^66+2229471657*x^60-36061389458264*x^54+392606586400579 074*x^48+539504008591676523876*x^42-426714543074858418197350*x^36-4006505099 33584626955407768*x^30+394042536990878794791484268061*x^24-91837221214280331 370349672199754*x^18+6951526052977952270050730689115037*x^12+785336155384304 5069776294861433728*x^6+4160868820129268027225702088135675904) } f=x^3 - 17298759218009623610183566031041339386720075700346652258609213718601496711017550 61362121841699226629974891813971909562156420018402691827454215309735885355556958 2565670693186076986600637143595083773458690435867304359843677566038921950799648* x^2 + 18711064803260370378157988406301782093292956776803873824168436875360414402394604 63586013733720488993651052248629894449551488639706757608435718517657626971261696 197926369466104020743029503447382758370181747288622353407958575237402147782740*x - 12656647741002885497431100319705272363568484609743163724263941366068388136613989 08689606630749523725171680318089454979912662201922998310310302859164016403007659 6050019301107038128290274152242961922293776060278436798656129125675827400300576; d=poldisc(f); e=valuation(d,2); valuation(nfdisc([f, [2,e; d/2^e,1]]),2) valuation(nfdisc([f, [2]]), 2) T = (x+1)^2 + 3*5^2*7^31; P = [[7], [5,7], factor(poldisc(T)), 7, 2]; for (i=1,#P, print(nfbasis([T,P[i]]), ", ", nfdisc([T,P[i]]))); p=10^100+267; q=10^120+79; T=polcompositum(x^2-p,x^2-q,2); nfdisc([T,[2,p,q]]) \\#1710 nfdisc(x^10-29080*x^5-25772600) \\#1735 P=x^10-2*x^9+12*x^8-12*x^7-181*x^6-4*x^5-6899*x^4+9780*x^3+6360*x^2+702*x-45; setrand(3); nfdisc(P) setrand(138); nfdisc(P) \\#2011 {nfdisc([ x^8 - 1852391133887779557197954101589261582189937135300705361732122605016667 5063444487117209600000002*x^6 + 66046032206948280681505445107777407158857150 7786666214157824890103497236708061373121624051677103378820065953589806447932 3040479517382543883335153986997613941795159674242391254234108671759292877251 5031154397064403303886209889075200000016*x^4 - 61171542244308866675691121761 6327714005525597151441388699040484267060775757052196963817130148238195987896 6448748825708153340901285158840187363891895981048830978300458035511777195248 8895145381018279012769938416424729156645871771884187596259840899356835906874 7730396358706617053542591613414581062482029464867475302414234419200000000*x^ 2 + 109051959257031239482474293713904499500234667691020023406541348336965128 5433328371966513980373672720867274391022554420298936550273060002685473689170 1545816271286317334966430106620557285909297145868903907602494913712472583649 0320168126428075024986655173099965777776148070297038169609742633321238475716 0277240403200637394323973803072310856025374382648070080573188733759065218101 9265646095092838488158448902084901164447371316596773535481703804984969764903 32160000000000000000, 500000])} \\#2178 setrand(43);nfdisc(x^12-4*x^11-1948*x^10+23072*x^9+1377243*x^8-28119512*x^7-305497980*x^6+12643497432*x^5-64374713540*x^4-1604497782672*x^3+26693470513376*x^2-159320374579040*x+352544728838416) \\ addprimes + poldiscfactors issue addprimes(100830379193747691689); nfdisc(x^7+104*x^6+2540*x^5+264160*x^4+2150524*x^3+223654496*x^2+606920400*x+63119721602) setrand(1); nfdisc([x^16+16*x^15+244*x^14+2296*x^13+18450*x^12+113656*x^11+590688*x^10+2493008*x^9+8817921*x^8+25589512*x^7+60996812*x^6+116732248*x^5+174844396*x^4+196363088*x^3+156454400*x^2+79347872*x+20093840, 2]) R=[x^18-16317*x^16+118265679*x^14-499751696685*x^12+1356826788429804*x^10-2*x^9-2454501053204715402*x^8-130374*x^7+2958493389873577537161*x^6-825805188*x^5-2291143160736473552954775*x^4-995783308458*x^3+1034452165511804318001640548*x^2-192870755863740*x-207465509693465643368389954303,x^18-9*x^17-4527*x^16+36420*x^15+9107928*x^14-64393560*x^13-10689026928*x^12+64972937610*x^11+8064418702896*x^10-40919217836426*x^9-4056253553431053*x^8+16471246861855062*x^7+1360185290303573985*x^6-4138377813051149349*x^5-293223492158277347730*x^4+593363579344952839536*x^3+36874630413790711445403*x^2-37172004689485179428553*x-2061013830816580611531337,x^18-18909*x^16+158835663*x^14-777924548301*x^12+2448129805015212*x^10-2*x^9-5133730369226054922*x^8-151110*x^7+7173535192263002255241*x^6-1109468484*x^5-6440812638454992423582711*x^4-1550851897002*x^3+3371767910496794603125514916*x^2-348235453503612*x-784124430882823858867201581823,x^18-24120*x^16+258469983*x^14-1615093297896*x^12+6485409174021219*x^10-2*x^9-17354959450550835192*x^8-192798*x^7+30949684635470905454106*x^6-1806252138*x^5-35468348149236006427736736*x^4-3222052603476*x^3+23701734415466465618443073049*x^2-923376934009314*x-7036787497174133615932814873749,x^18-9*x^17-6228*x^16+50028*x^15+17238708*x^14-121547160*x^13-27833882208*x^12+168585685254*x^11+28890717035526*x^10-146001856802066*x^9-19991989822923603*x^8+80845829851908510*x^7+9222929477593141785*x^6-27952363904606870319*x^5-2735288787505473360315*x^4+5517259461309504285840*x^3+473216952948872495094441*x^2-475980254920965556981305*x-36386350755204343325666851,x^18-26064*x^16+301821183*x^14-2038098415296*x^12+8844330450957507*x^10-2*x^9-25577809343692467552*x^8-208350*x^7+49296974017814615428986*x^6-2109465594*x^5-61057837619272781803264176*x^4-4066697905332*x^3+44099040368179012801324581081*x^2-1259550686239362*x-14150902225881104829423021922093,x^18-26280*x^16+306845343*x^14-2089208237016*x^12+9141333058417059*x^10-2*x^9-26656133020277532552*x^8-210078*x^7+51801761630361133785306*x^6-2144607498*x^5-64693014704344881503608896*x^4-4168759357716*x^3+47112705977531626131422847129*x^2-1301881153237794*x-15243588522444164508467506482949,x^18-30816*x^16+421932735*x^14-3368992922832*x^12+17287990507342467*x^10-2*x^9-59124936922907462352*x^8-246366*x^7+134765458082464897973946*x^6-2949647706*x^5-197412176445695197121960208*x^4-6724704946164*x^3+168639398613796944085316936793*x^2-2463223311935298*x-64008053489782103433738755790781,x^18-53604*x^16+1276847343*x^14-17738815699956*x^12+158398764849860067*x^10-2*x^9-942789497809942322892*x^8-428670*x^7+3740360370690952838819946*x^6-8931178674*x^5-9537919464612775763471709096*x^4-35437428073572*x^3+14185272025519176200645700315801*x^2-22594207791078162*x-9374890256028339024343740864581953,x^18-61137*x^16+1660970079*x^14-26319179560305*x^12+268060856904047124*x^10-2*x^9-1819865230850090585322*x^8-488934*x^7+8235497078548354028729001*x^6-11619088668*x^5-23954709004868655898823597715*x^4-52586058368778*x^3+40639166693178065110230087609468*x^2-38243680133640660*x-30637420213594351526757933017080303,x^18-72639*x^16+2344786983*x^14-44146869318471*x^12+534265430959948932*x^10-2*x^9-4309919354549718272502*x^8-580950*x^7+23175873581625955756813161*x^6-16404357744*x^5-80105753989711591612066439901*x^4-88219901379282*x^3+161493208110351438878491064237556*x^2-76238535552449112*x-144679984120874107673623184519850643,x^18-74529*x^16+2468400543*x^14-47683740529281*x^12+592089025593419892*x^10-2*x^9-4900720997686062950442*x^8-596070*x^7+27038911952281027969588521*x^6-17269414524*x^5-95891572587764622868520362371*x^4-95289750586122*x^3+198351727309627259459477604818076*x^2-84492230227247412*x-182329331532735647789992127491585903,x^18-75069*x^16+2504301903*x^14-48727873312941*x^12+609439531249033452*x^10-2*x^9-5080897507781407398282*x^8-600390*x^7+28236241736214825876396681*x^6-17520656004*x^5-100863892029697512375669011991*x^4-97376885435562*x^3+210149928872509578402641735165796*x^2-86968860865364412*x-194575500945760220267090041080683263,x^18-83925*x^16+3130066863*x^14-68090433028581*x^12+952108549690946364*x^10-2*x^9-8874603981370153807722*x^8-671238*x^7+55140873757696223257956681*x^6-21899894868*x^5-220224777409772799294278240991*x^4-136082296139946*x^3+513013638170568696512842701098964*x^2-135884247169771404*x-531083155224313036226872569249156799,x^18-86220*x^16+3303605583*x^14-73831181869596*x^12+1060621869166679619*x^10-2*x^9-10156515224834180984292*x^8-689598*x^7+64832423321572128802580106*x^6-23114376738*x^5-266016700258644044614361469336*x^4-147558328095876*x^3+636644490462323405588555209365849*x^2-151375081686960114*x-677106829061098314170521069309486249,x^18-86949*x^16+3359709423*x^14-75720012985461*x^12+1096955854581215772*x^10-2*x^9-10593302898646966206762*x^8-695430*x^7+68192623034866614624249801*x^6-23507011764*x^5-282171338151106292421390705231*x^4-151334223292842*x^3+681020548365776210507932733739636*x^2-156562009313964012*x-730432419604662516324563180569813183]; for(i=1,#R,print(i,":",nfdisc(R[i]))) for(i=1,#R,print(i,":",nfdisc(poltschirnhaus(R[i])))); \\ #2510 setrand(2);nfdisc(x^8-56*x^6+840*x^4-3136*x^2+3136) pari-2.17.2/src/test/in/bnflog0000644000175000017500000000273114676526175014560 0ustar billbilldefault(parisize,"12M"); \\ overflows 10M K=bnfinit(y^2+1); P2 = idealprimedec(K,2)[1]; bnflogef(K, P2) P3 = idealprimedec(K,3)[1]; bnflogef(K, P3) P5 = idealprimedec(K,5)[1]; bnflogef(K, P5) bnflogdegree(K, 6, 2) bnflogdegree(K, 6, 3) bnflogdegree(K, 6*idealmul(K,P2,P5), 5) K = bnfinit(polcompositum(y^2+y+1,y^3-2, 2)); bnflogef(K, idealprimedec(K,2)[1]) bnflogef(K, idealprimedec(K,3)[1]) bnflogef(K, idealprimedec(K,5)[1]) K = bnfinit(y^2+521951); K.cyc bnflog(K, 2) T0 = polcompositum(y^2+1,y^2-11,2); K = bnfinit(T0); K.cyc bnflog(K, 5) K = bnfinit(polcompositum(y^2+1,y^2-78,2)); K.cyc bnflog(K, 2) K = bnfinit(polcompositum(y^2+1,y^2-455,2)); K.cyc bnflog(K, 2) K = bnfinit(polcompositum(y^2+1,y^2-1173,2)); K.cyc bnflog(K, 2) K = bnfinit(polcompositum(y^2+1,y^2-1227,2)); K.cyc bnflog(K, 613) K = bnfinit(y^4+13*y^2-12*y+52); K.cyc bnflog(K, 2) bnflog(K, 3) bnflog(K, 7) K = bnfinit(polcompositum(y^2+3,y^2-1234577,2), 1); K.cyc bnflog(K, 2) bnflog(K, 3) bnflog(K, 13) K = bnfinit(polcompositum(y^2+y+1,y^2-303,2)); K.cyc bnflog(K, 2) bnflog(K, 3) bnflog(K, 5) K = bnfinit(y^5+2*y^4+18*y^3+34*y^2+17*y+3^10, 1); K.cyc bnflog(K, 2) bnflog(K, 3) K = bnfinit(polcompositum(polcyclo(5,y),y^2-5029,2), 1); K.cyc bnflog(K, 2) bnflog(K, 3) bnflog(K, 5) K = bnfinit(polcompositum(T0,y^2+499,2), 1); K.cyc bnflog(K, 5) K = bnfinit(polcompositum(T0,y^3+3*y^2+2*y+125,2), 1); K.cyc bnflog(K, 2) bnflog(K, 3) bnflog(K, 5) F=bnfinit(x^2-4565649,1); bnflog(F,2) bnflog(bnrinit(bnfinit(x^2+1),3),2) pari-2.17.2/src/test/in/sumnum0000644000175000017500000000735214676526175014641 0ustar billbillallocatemem(40 * 10^6); check(a,b)=my(c=abs(a-b)); if(!c,oo, ceil(log(c)/log(10))); check(sumnummonien(n=1,1/n^2), Pi^2/6) check(sumnummonien(n=1,log(1+1/n)/n), sumpos(n=1,log(1+1/n)/n)) tab=sumnummonieninit(,1); check(sumnummonien(n=1, 1/n^2, tab), -zeta'(2)) sumnummonien(n=0,1/(n+1)^2) sumnummonien(n=2,1/(n+1)^2) tab=sumnummonieninit(1,,0); sumnummonien(n=0,1/(n+1)^2,tab) tab=sumnummonieninit([3,0]); check(sumnummonien(n=1,n^-3,tab), zeta(3)) tab=sumnummonieninit([1,1/2],,0); sumnummonien(n=0,1/(n+1)^(3/2),tab) tab=sumnummonieninit([1/2,1],n->1); sumnummonien(n=1,1/n^(3/2),tab) tab=sumnummonieninit([1/2,1],n->1,2); sumnummonien(n=2,1/n^(3/2),tab) TEST=[n->1/(n^2+1), n->log(1+1/n)/n, n->lngamma(1+1/n)/n, n->sin(1/sqrt(n))/n^(3/2)]; FUN=[f->sumnum(n=1,f(n)), f->sumnummonien(n=1,f(n)), f->sumnumap(n=1,f(n)), f->sumnumsidi(n=1,f(n))]; localprec(57); V=[sumnummonien(n=1,f(n)) | f<-TEST]; { for (i = 1, #TEST, my (f = TEST[i]); print(f); for (j = 1, #FUN, my (SUM = FUN[j]); my (t = check(SUM(f), V[i])); print(t); ) ) } sumnum(n = [1, -3/2], sin(1/sqrt(n))/n) sumnumap(n = [1, -3/2], sin(1/sqrt(n))/n) tab=sumnummonieninit(,n->log(n)^2); check(sumnummonien(n=1, 1/n^2, tab), zeta''(2)) tab=sumnummonieninit(,n->log(n),2); check(sumnummonien(n=2,1/n^2,tab), -zeta'(2)) sumnummonien(n=1,1/n^2,tab) \\error tab=sumnummonieninit([1,2]); check(sumnummonien(n=1, 1/n^3, tab), zeta(3)) tab=sumnummonieninit([1,1/2]); check(sumnummonien(n=1, 1/n^(3/2), tab), zeta(3/2)) localprec(57); V = sumnum(n=[1,-3/2], sin(1/sqrt(n))/n); tmon=sumnummonieninit([1/2,1]); check(sumnummonien(n=1, sin(1/sqrt(n))/n, tmon), V) check(sumnum(n=[1,-3/2], sin(1/sqrt(n))/n), V) T=sumnumapinit([oo,-3/2]); check(sumnumap(n=[1,-3/2], sin(1/sqrt(n))/n, T), V) { localprec(77); tmon=sumnummonieninit([1/2,1]); check(sumnummonien(n=1,n^(-3/2), tmon), zeta(3/2)) } \p115 z2 = zeta(2); z3 = zeta(3); z32 = zeta(3/2); z73 = zeta(7/3); check(sumnumlagrange(n=1,n^-2),z2) check(sumnumlagrange(n=2,n^-2),z2-1) tab=sumnumlagrangeinit([1,0]); check(sumnumlagrange(n=1,n^-2,tab),z2) check(sumnumlagrange(n=2,n^-2,tab),z2-1) tab=sumnumlagrangeinit([2,0]); check(sumnumlagrange(n=1,n^-3,tab),z3) check(sumnumlagrange(n=2,n^-3,tab),z3-1) tab=sumnumlagrangeinit([1/2,0]); check(sumnumlagrange(n=1,n^(-3/2),tab),z32) check(sumnumlagrange(n=2,n^(-3/2),tab),z32-1) tab=sumnumlagrangeinit([1/3,0]); check(sumnumlagrange(n=1,n^(-7/3),tab),z73) check(sumnumlagrange(n=2,n^(-7/3),tab),z73-1) tab=sumnumlagrangeinit(1/3); check(sumnumlagrange(n=1,n^(-7/3),tab),z73) check(sumnumlagrange(n=2,n^(-7/3),tab),z73-1) \p 308 a = sumpos(n=1, 1/(n^3+n+1)); b = sumpos(n=1, 1/(n^3+n+1), 1); check(a, b) tab = sumnuminit(); b = sumnum(n=1, 1/(n^3+n+1), tab); check(a, b) a = sumpos(n=1,1/(n^2+1)); b = sumpos(n=1,1/(n^2+1), 1); check(a, b) b = sumnum(n=1,1/(n^2+1), tab); check(a, b) check(sumnum(n=[1,-4/3],n^(-4/3)), zeta(4/3)) tab = sumnuminit([+oo,-3/2]); check(sumnum(n=1,1/(n*sqrt(n)),tab), zeta(3/2)) \\ check(suminf(n=1, 2^(-n)), 1) check(suminf(n=1, [2^(-n),3^(-n)]), [1,1/2]) check(sumpos(n=1, 2^(-n)), 1) check(sumnum(n=[1, 1],2^(-n)), 1) check(sumnumap(n=[1, 1],2^(-n)), 1) \\ very slow if bad tuning for expQ localbitprec(1024); sumpos(n=1,(exp(1/n)-1)/n) \p38 f(x) = -log(cos(x)); F = truncate( f(t + O(t^16)) ); g(x) = if (x > 1e-2, f(x), subst(F,t,x)); sumpos(n=1,g(1/n)) sumpos(n=0,0) \\#1729 \p19 sumpos(n=1,1/n^2) \\ ERRORS: keep them at end of file sumnum(n=1,1/n^2,"bug"); sumnumap(n=1,1/n^2,"bug"); intnumapinit(x,y) sumnummonieninit([-1,1]); sumnummonieninit([1,-1]); sumnummonieninit(,[n->2^-n,oo]); sumnummonieninit(oo) sumnumlagrangeinit([1/5,0]) sumnumlagrangeinit(x) sumnumlagrangeinit(x,-2) prodinf(n=0,1+2^-n,2) sumalt(n=0,1,2) sumpos(n=0,1,2) intnumosc(x = 0, besselj(0,x)^2,Pi); pari-2.17.2/src/test/in/subst0000644000175000017500000000741614676526175014456 0ustar billbillp; q; subst(Y/X,X,x) substvec(x+y,[x,y],[1,x]) substvec([x,y],[x,y],[[1,2],3]) substvec([x,y],[x,y],[[1,2],[3]]) substvec([x,y],[x,y],[[1,2],[3,4]]) substvec([x,y,z],[x,y,z],[[1,2],[3,4],[5,6]]) substvec([x,y],[x,y],[[x+y,x],[y,x+y]]) \\ #1321 v = [p + w*q, w*p + q] * Mod(1, w + 1); substvec(x+y, [x, y], v) \\ #1447 subst(O(x^2),x,0*x) subst(x+O(x^2),x,Mod(1,3)) subst(x+O(x^2),x,Mod(0,3)) subst(1/x+O(x^2),x,Mod(0,3)) subst(2+x+O(x^2),x,Mod(0,3)) subst(Pol(0),x,Mod(1,3)) subst(Pol(0),x,Mod(1,3)*matid(2)) subst(Pol(1),x,Mod(1,3)) subst(Pol(1),x,Mod(1,3)*matid(2)) subst(y+1,x,Mod(1,3)*matid(2)) subst(1+y+O(y^2),x,Mod(1,3)*matid(2)) subst(1,x,Mod(1,3)*matid(2)) subst(0,x,Mod(1,3)*matid(2)) subst(Pol(0),x,Mat(Mod(1,3))) subst(Pol(1),x,Mat(Mod(1,3))) subst(1,x,Mat(Mod(1,3))) subst(0,x,Mat(Mod(1,3))) type(subst(Pol(0),'y,1)) type(subst(Pol(0),'x,1)) type(subst(Pol(0),'y,Mod(1,3))) type(subst('u^0,u,x)) type(subst('x^0,'y,1)) type(subst('x*'y,'y,0)) subst(x+1, x, [2,3]) subst(x+1, x, [2,3]~) substpol(x,1/x,y) substpol(Mod(x*y^2, y^3*x^2+1), y^2,y) substpol(x*y^2/(y^3*x^2+1), y^2,y) substpol(List(), y^2,y) substpol(List(x^2*y^2), y^2,y) substpol(x^2+y^3*x^3+O(x^4),y^2, y) variables(substpol(x,1/x,t)) variables(substpol(x+1+1/x,x+1/x,t)) subst(1,x,[;]) subst(1,x,Mat([1,2])) subst(x^2+x^3+O(x^4),x, 2*y+O(y^2)) substpol(1+O(x^2),x^2,x) substpol(x^2+O(x^4),x^2,x) substpol(x+O(x^4),x^2,x) substpol(1,x^2,x) \\#1727 substvec(1+x+y+x*y+O(x^2), [x,y],[x,y]) subst(Mod(1/z,y),z,x) \\#1988 subst(Mod(-a,a^2-2),z,0) subst(((-6*t^2-t)*u^4+(t^2)*u^3+(P)*t^3*u)/u^2,t,0) \\#2264 p=s1*x+s1*x^2+(1/2*s1^2+s1+s2)*x^3+(1/6*s1^3+3/2*s1^2+(s2+1)*s1+(s2+s3))*x^4+(1/24*s1^4+7/6*s1^3+(1/2*s2+3)*s1^2+(3*s2+(s3+1))*s1+(1/2*s2^2+2*s2+(s3+s4)))*x^5+(1/120*s1^5+5/8*s1^4+(1/6*s2+25/6)*s1^3+(7/2*s2+(1/2*s3+5))*s1^2+(1/2*s2^2+7*s2+(3*s3+(s4+1)))*s1+(3/2*s2^2+(s3+2)*s2+(s3+(s4+s5))))*x^6+(1/720*s1^6+31/120*s1^5+(1/24*s2+15/4)*s1^4+(5/2*s2+(1/6*s3+65/6))*s1^3+(1/4*s2^2+13*s2+(7/2*s3+(1/2*s4+15/2)))*s1^2+(7/2*s2^2+(s3+13)*s2+(6*s3+(3*s4+(s5+1))))*s1+(1/6*s2^3+9/2*s2^2+(3*s3+(s4+3))*s2+(1/2*s3^2+2*s3+(2*s4+(s5+s6)))))*x^7+(1/5040*s1^7+7/80*s1^6+(1/120*s2+301/120)*s1^5+(31/24*s2+(1/24*s3+175/12))*s1^4+(1/12*s2^2+91/6*s2+(5/2*s3+(1/6*s4+70/3)))*s1^3+(15/4*s2^2+(1/2*s3+36)*s2+(25/2*s3+(7/2*s4+(1/2*s5+21/2))))*s1^2+(1/6*s2^3+14*s2^2+(7*s3+(s4+22))*s2+(1/2*s3^2+11*s3+(7*s4+(3*s5+s6))))*s1+(7/6*s2^3+(1/2*s3+17/2)*s2^2+(7*s3+(3*s4+(s5+3)))*s2+(3/2*s3^2+(s4+2)*s3+(2*s4+(s5+(s6+s7))))))*x^8+O(x^9); subst(p, x, x); \\ takes oo time if content(p) is computed \\#2267 subst(O(y) + x + O(x^2), x, (1 - y + O(y^2))*x + O(x^2)) \\#2364 subst(Mod(y^4+y/t^3+1/t^6+1/t^12,2),y,t^-1+t^-3+O(t^100)) \\#2565 { x1= Mod(21664460/9330057*t^15 - 191313205/18660114*t^14 - 111678844/9330057*t^13 + 1216843451/18660114*t^12 + 461984720/9330057*t^11 - 921914329/9330057*t^10 - 240563560/3110019*t^9 - 2711591027/18660114*t^8 - 2861932214/9330057*t^7 + 3340545232/9330057*t^6 + 4362074636/3110019*t^5 + 11468434639/9330057*t^4 + 90614081/848187*t^3 - 1043498858/3110019*t^2 - 882894976/9330057*t + 4744475/1036673, t^16 - 4*t^15 - 7*t^14 + 26*t^13 + 33*t^12 - 34*t^11 - 51*t^10 - 76*t^9 - 158*t^8 + 100*t^7 + 669*t^6 + 778*t^5 + 261*t^4 - 128*t^3 - 100*t^2 - 14*t + 1); y1= Mod(9436330/9330057*t^15 - 13837621/3110019*t^14 - 99537241/18660114*t^13 + 266729318/9330057*t^12 + 22779814/1036673*t^11 - 45584945/1036673*t^10 - 35257972/1036673*t^9 - 193768309/3110019*t^8 - 837865087/6220038*t^7 + 488484232/3110019*t^6 + 1277859469/2073346*t^5 + 1663486070/3110019*t^4 + 703904849/18660114*t^3 - 158423625/1036673*t^2 - 749625223/18660114*t + 56335111/18660114, t^16 - 4*t^15 - 7*t^14 + 26*t^13 + 33*t^12 - 34*t^11 - 51*t^10 - 76*t^9 - 158*t^8 + 100*t^7 + 669*t^6 + 778*t^5 + 261*t^4 - 128*t^3 - 100*t^2 - 14*t + 1); } substvec((-20*y^2 + 9)*x^2/(x^2 - y^2), ['x,'y], [x1,y1]) pari-2.17.2/src/test/in/sumdiv0000644000175000017500000000240614760123736014605 0ustar billbilln = 10!; fa = factor(n); sumdiv(n, d, eulerphi(d)) sumdiv(n, d, d^2) sumdiv(fa, d, eulerphi(d)) sumdiv(fa, d, d^2) sumdivmult(n, d, eulerphi(d)) sumdivmult(n, d, d^2) sumdivmult(fa, d, eulerphi(d)) sumdivmult(fa, d, d^2) sigma2(x) = sigma(x,2); sigma3(x) = sigma(x,3); sigma_1(x) = sigma(x,-1); core2(x) = core(x,1); fun = [ispowerful, moebius, core, core2, omega, bigomega, eulerphi, numdiv, sigma, sigma2, sigma3, sigma_1]; for(i=1,#fun, print(fun[i](fa))) v = concat([-50..-1], [1..50]); fav = apply(factor, v); { for (i=1,#fun, my(f = fun[i]); for (j=1,#v, if (f(v[j]) != f(fav[j]), error([f,v[j]])))) } \\ allow 0 fun0 = [ispowerful, core, core2, eulerphi]; { for (i=1,#fun0, my(f = fun0[i]); if (f(0) != f(factor(0)), error([f,0]))) } test(fa)= for(i=1,#fun, print(iferr(fun[i](fa),E,E))); test(0) test(factor(0)) test(-2) test(factor(-2)) fa = factor(1); for(i=1,#fun, print(fun[i](fa))) divisors(fa) fa = factor(0); ispowerful(fa) core(fa) core2(fa) divisors(fa) fa = [5!, factor(5!)]; core2(fa) divisors(fa) n = x^2*(x+1)^3*(x+2)^5; fa = factor(n); sumdiv(n, d, d) sumdiv(fa, d, d) sumdivmult(n, d, d) sumdivmult(fa, d, d) \\#1664 divisors([1,2]) \\#1702 moebius(factor(18)) \\ core would destroy its input R = 762104756900678410271641; core(R); R pari-2.17.2/src/test/in/thue0000644000175000017500000001116214567450071014242 0ustar billbillallocatemem(100*10^6); thue(x^4 - 13*x^3 - 172*x^2 - 13*x + 1, 9) thue(x^3 - 2, 2) thue(x^6 - 2, 2638) thue(x^3 + x^2 - 43690*x - 3529208, -3572896) thue(x^4-x^3+x^2-x+1,1) thue(x^3-48,320) thue(x^7-401,88) thue(thueinit(x^3-100,1), 25) thue((x+1)^2*(x^2+2), 12) thue((4*x+1)^2*(x^2+2), 75) thueinit(x^0) thue(23*x^4 + 40*x^3 - 600*x^2 + 160*x + 368, -144) thue(x^3+92*x+1,3^3) thue(x^3-18*x^2+81*x+1,3^3) thue((x^4+1)^2,4) thue((x^2+1)^2*(x^2-2),0) thue((x^3-2)^2,0) thue(x^3-2,0) thue((x^2+1)^2*(x^2-2),-4) thue(x^3-12*x-13,87) setrand(1);thue(x^3-537825*x^2+537824*x+1, 1) thue(thueinit(x^3-x-1),1578191) thue((10946*x-6765)*(x^2+x-1), 1) thue((x^3-2)^2,-4) thue((x^3-2)^2,4) thue((x^3-2)^3,-8) thue((x^3-x+1)^3,-512) thue((2*x^3+2)^3*(x+1)^3, 157464) thue(x^4+1,20^30+3) thue(-(x^4+1),10^20) thue(x^2+x+1, 7*13*11^2*10^4) do(T,a)= { my(L = thue(T,a), d = poldegree(T)); for(i=1,#L, my([u,v]=L[i]); my(h = if(v, v^d*subst(T,x,u/v), pollead(T)*u^d)); if(h!=a, error([u,v]))); #L; } do(x^2+1,10^10) do(4*x^2+1,10^10) do(x^2+5,10^10) do(4*x^2+5,10^10) do(x^2+x+1,7*13*11^2*10^4) do(25*x^2+45*x+21,10^4) \\ short continued fraction [#1629] thue(-14*x^3+10*x^2+63*x-5,1) \\ round error thue(29*x^3+130*x^2-35*x-48,1) \\ #1630 T=thueinit(10*x^3+6*x^2-41*x+8,1); thue(T,8) thue(-26*x^3+106*x^2+117*x-53,1) T=thueinit(8758*x^3 - 15667*x^2 - 10120*x - 23938,1); thue(T,1) P=-74*x^3+236*x^2+1500*x-469; thue(P,1) thue(thueinit(P,1),1) \\ denominators thue(x^2+3, 10^12 + 39) \\ #2003 + missing solution p=x^28+1731*x^26+922623*x^24+191101246*x^22+20130551985*x^20+1253260615292*x^18+49888378570100*x^16+1321233290968720*x^14+23633671333922020*x^12+284346917208077022*x^10+2247402310097126980*x^8+11107629226258927789*x^6+31330156854132324561*x^4+42585395771105656706*x^2+21292697885552828353; thue(p,1) thue(x^2+10^20,1,[1]) thue(x^2+x*10^20+10^40,1,[1]) \\ addprimes issue addprimes(360000000029); #thue(x^2+1,500009*500029* 360000000029* 2^100) { /* #252, #2296 */ thueinit(x^76+54687*x^74+1331409702*x^72+19294128253783*x^70+1878910698050 05926*x^68+1316103875879574524715*x^66+6928411165475589202157365*x^64+282656 01816777038835336956296*x^62+91400756764560817129471682430464*x^60+238301396 929638667200442999270449412*x^58+507599640095276712508391037681631012864*x^5 6+892498013590370337884521258437261828512004*x^54+13058051125037082855876656 03530643585035234682*x^52+1599704196388643067865899482606106296517340746234* x^50+1648693947468111663454266410635199577958709090018780*x^48+1434383013265 936944871141197360008258547232909851891562*x^46+1055849837928294731596871954 258328961575247209261438815532*x^44+6583893883514388036620346642839604275660 29686163968634741618*x^42+34786339179545333202022551273149279021904054412411 5349548497306*x^40+155618545623882506256647934775052281194816623166250956528 455476140*x^38+5884335225955273733359535669924706155305033323888549133038445 1754496*x^36+187555158104606473963495307983264503281777678485432278059780545 66731332*x^34+50198055501664894435361316813724305483917492385987314163950427 03924840016*x^32+11224400635060745044227482776842712690172594965601806413094 70797894071357668*x^30+20831871181186581631484573893437224049354128942169978 5098607399921597106223941*x^28+318283508779520505745347725901768768088744645 68357325854282602776660644907236735*x^26+39623343744308977655796345507986280 84419763402710919880217016533956575743304686062*x^24+39677279425758842513773 1011250354921937194381988127282097881441791677100218894823415*x^22+314446562 0437057365491469689153779708771612812934492884362053182599698195803379737078 2*x^20+193218462253762438930328899478446070124439303766540053117670847176261 0586818661410507259*x^18+896730494408605371087014654739087786574970449662887 68336085606913177971948281572511434737*x^16+30394524242952246470288123587221 26420410158865754289708994377347655728705424140768271779892*x^14+72102036555 0045711218896556431516655334198584471998361289159337699799900516216772135898 99920*x^12+11367539978311271814412274473436097275981738259454259177918409719 04414393463036113868508034176*x^10+11230904437813718587766363478285636923911 496290123758733224250429666623697944153531813674338816*x^8+63909047484450872 6667108573753409231740471208100390840723339396060557404017422357595809204940 80*x^6+176842247739964531891182887798451093710155575758662537711298418990445 611753966533809149772484608*x^4+14312476391695290649330030833204746873479848 6056764704852623085926055626863515512636287595986944*x^2+2879820481730619500 55529070071389519187679665146560289272601644716511470652898701730997141504); } \\ #2365 ti=thueinit(3*x^3 + 5*x^2 - 14*x + 54,1); thue(ti,1) \\ #2397 ti=thueinit(x^3-3*x^2+1); thue(ti,2187) pari-2.17.2/src/test/in/nfhilbert0000644000175000017500000000324114567450071015251 0ustar billbillnf=nfinit(y^3-1009); P = primes(20); pr = idealprimedec(nf,1009)[1]; a = y^11*(y+1)*101; b = y^5*(y+3)*19; vector(#P, i, nfhilbert(nf, a, P[i]*b, pr)) pr = idealprimedec(nf,19)[1]; a = 19^11*(y+1)*101; b = 19^5*(y+3)*19; vector(#P, i, nfhilbert(nf, a, (1+P[i]*y)*b, pr)) /* old regression cases: */ nf=nfinit(y^2+1); pr=idealprimedec(nf,2)[1]; nfhilbert(nf, [1,1]~, 3, pr) nfhilbert(nf, Mod(0,3), 3, pr) nfhilbert(nf, 3, 0., pr) nfhilbert(nf,[1,-2]~,[1,-2]~, pr) nf=nfinit(y^2+3); nfhilbert(nf,[3,0]~,[3,0]~,idealprimedec(nf,2)[1]) \\ #1147 K = nfinit(x^5-23); p = idealprimedec(K, 2)[1]; nfhilbert(K,x,-x^2-5*x,p) q = idealprimedec(K, 3)[2]; nfhilbert(K,x^4-x^3+x^2-x+1,24*x^3+24*x^2+48,q) \\ t = [1,0,...,0]~ in nfhilbertp nfhilbert(K,-x,-x^2) nfhilbert(K,1,x^2) K = nfinit(x^8 + 2*x^7 + 3*x^6 + 3*x^4 + 3*x^2 + 2*x + 3); p = idealprimedec(K, 2)[1]; { for (j = 1,10, setrand(j); a = vectorv(8,i,random(7)); b = vectorv(8,i,random(7)); c = vectorv(8,i,random(7)); d = nfeltmul(K,b,c); if (nfhilbert(K, a,b,p) * nfhilbert(K, a,c,p) != nfhilbert(K, a,d,p), error([a,b,c])) ) } L = [2, 3, 1.0, Mod(1,2), Mod(1,4), Mod(1,8), Mod(1,3), Mod(0,5), 1 + O(2^2), 1 + O(2^3), 1 + O(5)]; for (i=1,#L, for(j=i+1,#L, print([i,j], ": ", iferr(hilbert(L[i],L[j]), E, E)))) print("p = 0:"); for (i=1,#L, print(i, ": ", iferr(hilbert(L[i],L[i], 0), E, E))) print("p = 2:"); for (i=1,#L, print(i, ": ", iferr(hilbert(L[i],L[i], 2), E, E))) print("p = 5:"); for (i=1,#L, print(i, ": ", iferr(hilbert(L[i],L[i], 5), E, E))) \\#1251 hilbert(-1,-1,0) \\#1261 K=nfinit(y^2+5); P=idealprimedec(K,2)[1]; nfhilbert(K,2*y,2,P) \\#1569 K=nfinit(x^3-4*x+2); nfhilbert(K,2,-2, idealprimedec(K,2)[1]) pari-2.17.2/src/test/in/sumiter0000644000175000017500000000106014676526175014773 0ustar billbillHEAP=[24, if(sizebyte(0)==16,301,332)]; \p 19 \e intnum(x=0,Pi,sin(x)) intnum(x=0,4,exp(-x^2)) intnum(x=1,[1],1/(1+x^2)) - Pi/4 intnum(x=-0.5,0.5,1/sqrt(1-x^2)) - Pi/3 intnum(x=0,[[1],-I],sin(x)/x) - Pi/2 \p 38 prod(k=1,10,1+1/k!) prod(k=1,10,1+1./k!) Pi^2/6*prodeuler(p=2,10000,1-p^-2) prodinf(n=0,(1+2^-n)/(1+2^(-n+1))) prodinf(n=0,-2^-n/(1+2^(-n+1)),1) solve(x=1,4,sin(x)) sum(k=1,10,2^-k) sum(k=1,10,2.^-k) 4*sumalt(n=0,(-1)^n/(2*n+1)) 4*sumalt(n=0,(-1)^n/(2*n+1),1) sumdiv(8!,x,x) suminf(n=1,2.^-n) 6/Pi^2*sumpos(n=1,n^-2) if (getheap()!=HEAP, getheap()) pari-2.17.2/src/test/in/nfrootsof10000644000175000017500000000102514567450071015372 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) do(x^16+2*x^15-x^14-4*x^13+x^12+4*x^11-2*x^9-3*x^8+7*x^6-9*x^4+4*x^3+4*x^2-4*x+1) do(polcyclo(68)) do(polcyclo(85)) nfrootsof1(x^2023+x+1) nfrootsof1(x^2024+x-1) \\ errors nfrootsof1(x^0) pari-2.17.2/src/test/in/modular0000644000175000017500000000151214567450071014736 0ustar billbillv = [2,3,2^32-1,2^64-1,10^20]; f(a,b,p)=(a*Mod(1,p)) * (b*Mod(1,p)); g(a,p)=sqr(a*Mod(1,p)); test(a,b)= { for (i=1,#v,print(i, ": ", f(a,b,v[i]))); for (i=1,#v,print(i, ": ", g(a,v[i]))); } test(polcyclo(10),polcyclo(5)); test([1,2;3,4], [-1,2;-4,2]); Mod(Mod(1,y),x) Mod(Mod(1,x),y) iferr(Mod(1,"a"),E,E) iferr(Mod(0,0),E,E) iferr(Mod(0,Pol(0)),E,E) iferr(Mod(x+O(x^2), x^3), E,E) Mod(x+O(x^2), x^2) Mod(x+O(x^3), x^2) Mod(Mod(x,x^3), x^2) Mod(Mod(1,12), 9) Mod(1/x,x^2+1) Mod([5,6],2) Mod(3*x,2) Mod(x,y) Mod(Pol(0),2) Pol(0)*Mod(1,2) k=100000000000000000000; Mod(3,7)^-k Mod(3,7)^k \g1 a=Mod(1,2);b=Mod(1,3); a+b a-b a*b a/b a+a a-a a*a a/a a=Mod(1,x);b=Mod(1,x+1); a+b a-b a*b a/b a+a a-a a*a a/a \\#1652 p=436^56-35;lift(Mod(271,p)^((p-1)/2)) \\#1717 Mod(0,1)==0 Mod(0,1)==1 Mod(0,1)==-1 Mod(0,x^0)==0 Mod(0,x^0)==1 Mod(0,x^0)==-1 pari-2.17.2/src/test/in/help0000644000175000017500000000042714567450071014227 0ustar billbillf()=1; ?x ?sin ?f ?echo ?default(echo) ?default(log) alias(new,sin) ?new addhelp(x,"test1") addhelp(sin,"test2") addhelp(f,"test3") addhelp(echo,"test4") addhelp(new,"test5") addhelp(addii,"test6") ?x ?sin ?f ?echo ?new ?does_not_exist ? ?. ?\ ?2 ?addii \t g()=0; \u ?_&&_ ?_==_ pari-2.17.2/src/test/in/subcyclopclgp0000644000175000017500000000432514676526175016163 0ustar billbilldefault(parisize,"46M"); \\ overflows 44M subcyclopclgp(22220,3) subcyclopclgp(22220,nextprime(2^64)) subcyclopclgp(23,3) subcyclopclgp(81,5) subcyclopclgp(132,[3,7,11],) subcyclopclgp([8*53^2,[16855,1009]],107) /* 107 | h(106) */ Q = bnfinit(y); bnr1 = bnrinit(Q, 8); H1 = Mat(2); bnr2 = bnrinit(Q, [53^2, [1]]); H2 = Mat(53); [bnr,H] = bnrcompositum([bnr1, H1], [bnr2, H2]); subcyclopclgp([bnr,H], 107) subcyclopclgp(521,3,1) subcyclopclgp(10220,[7,13,19,37],1) { L = [[5,1111], [5,7523], [5,36227], [5,36293], [5,36322], [5,42853], [5,-5657], [5,-14606], [3,853], [3,9546], [3,11703], [3,13767], [3,13894], [3,15338]]; for (i = 1, #L, [p,m] = L[i]; f = abs( if (m%4 == 1, 5*m, 20*m) ); H = [a | a<-[1..f], a % 5 == 1 && gcd(a,f) == 1 && kronecker(m,a) == 1]; print(subcyclopclgp([f,H],p)) ); } subcyclohminus(997) subcyclohminus(998) subcyclohminus(999) /* p : prime s.t. 2^e*l^f || (p-1); relative class numbers of subfields of * Q(zeta_p) with degree 2^e*l^t (0 <= t <= f) */ test_pl(p,l)= { my(q = 2^valuation(p-1,2), H = znprimroot(p)^q); printf("(%d,%d,%d) ",p,q,l); for(t = 0, valuation(p-1,l), printf("%d ", subcyclohminus([p, H], l)); H = H^l; \\ g^(q*l^t) ); printf("\n"); } test_pl(131707,3) test_pl(363043,3) subcycloiwasawa(22220, 41) subcycloiwasawa(10220, 13) subcycloiwasawa([1152328, [3, 7, 19]], 3, 3) /* F=Q(sqrt(-458),sqrt(-629)) */ H=[2,0,1,1,0;0,2,0,1,1;0,0,1,0,0;0,0,0,1,0;0,0,0,0,1]; subcycloiwasawa([znstar(1152328, 1), H],3,3) /* same */ subcycloiwasawa(polcompositum(x^2+458,x^2+629,2),3,3) subcycloiwasawa(x^2+1501391,3) subcycloiwasawa(x^2+956238,3) subcycloiwasawa(x^2+239,3,9) T = polcompositum(x^2 - 42853, polcyclo(5))[1]; subcycloiwasawa(T, 5) subcycloiwasawa(T, 5, 4) subcycloiwasawa(x^2+239, 3, 10) subcycloiwasawa(x^2-17, 2, 10) subcycloiwasawa(x^2-101, 2, 10) subcycloiwasawa(x^2+239,3) \\ #2390 subcycloiwasawa(x^2+87,3) \\ errors, keep at end of file subcyclopclgp([7, [1]], 3) subcyclopclgp([7, [1,7]], 11) subcyclopclgp([7, [1]], 2) subcyclopclgp([7, [1]], [2,5]) subcyclopclgp([7, [1]], [3,11]) subcyclopclgp([7, [1]], 4) subcyclopclgp([7], 5, 64) iferr(subcycloiwasawa(11,2^64),E,Vec(E)[1]) iferr(subcycloiwasawa(11,7,22),E,Vec(E)[1]) iferr(subcycloiwasawa(2^64+13,7,1),E,Vec(E)[1]) pari-2.17.2/src/test/in/version0000644000175000017500000000002014567450071014751 0ustar billbillversion()[1..3] pari-2.17.2/src/test/in/norm0000644000175000017500000000073514760137411014247 0ustar billbillnorml2(-1/2) norml2(quadgen(5)) norml2(quadgen(-3)) normlp(-1, 1) normlp(-1/2, 1) normlp(I, 1) F = [x->normlp(x,1), x->normlp(x,2), x->normlp(x,2.5), normlp]; { for(i=1, #F, my(f = F[i]); print(f); print(f([1,-2,3])); print(f([1,-2;-3,4])); print(f([[1,2],[3,4],5,6])); print(f((1+I) + I*x^2)); print(f(-quadgen(5))); print(f(3+4*I)); ) } normlp([95800,217519,414560], 4) normlp([1,oo], oo) normlp([1,-oo], oo) normlp(-1,oo) normlp(-1,-oo) pari-2.17.2/src/test/in/orthopol0000644000175000017500000000264014567450071015144 0ustar billbillU(n)=polchebyshev(n,2); T(n)=polchebyshev(n,1); L(n)=pollegendre(n); H(n)=polhermite(n); LA(n)=pollaguerre(n,1/3); print("U");for (n=-50,50, if (U(n+1)+U(n-1)-2*x*U(n), print(n))) print("T");for (n=-50,50, if (T(n+1)+T(n-1)-2*x*T(n), print(n))) print("L");for (n=-50,50, if ((n+1)*L(n+1)-(2*n+1)*x*L(n)+n*L(n-1), print(n))) print("H");for (n=0,100, Hn=H(n); if (H(n+1)-2*x*Hn+Hn', print(n))) print("LA");a = 1/3; for (n=1,100, if((n+1)*LA(n+1)+(x-(2*n+a+1))*LA(n)+(n+a)*LA(n-1),print(n))); T=polchebyshev(5,1,x); subst(T,x,2) == polchebyshev(5,1,2) U=polchebyshev(5,2,x); subst(U,x,2) == polchebyshev(5,2,2) H=polhermite(5); subst(H,x,2) == polhermite(5,2) H=polhermite(5,,1); subst(H,x,2) == polhermite(5,2,1) L=pollegendre(5); subst(L,x,2) == pollegendre(5,2) L=pollegendre(5,,1); subst(L,x,2) == pollegendre(5,2,1) LA=pollaguerre(5,1/3); subst(LA,x,2) == pollaguerre(5,1/3,2) LA=pollaguerre(5,1/3,,1); subst(LA,x,2) == pollaguerre(5,1/3,2,1) polchebyshev(-1,2,2) polchebyshev(-2,2,2) polchebyshev(4,2,2) z=Mod(2,2^64+13); N=1000; T=polchebyshev(N,1);subst(T,x,z) == polchebyshev(N,1,z) T=polchebyshev(N,2);subst(T,x,z) == polchebyshev(N,2,z) T=polhermite(N);subst(T,x,z) == polhermite(N,z) T=pollegendre(N);subst(T,x,z) == pollegendre(N,z) T=pollaguerre(N,1/3);subst(T,x,z) == pollaguerre(N,1/3,z) \\ Errors, keep at end of file polhermite(-1) polhermite(0,,1) polhermite(0,1,1) pollaguerre(-1) pollaguerre(0,,,1) pollaguerre(0,,1,1) pari-2.17.2/src/test/in/addprimes0000644000175000017500000000113714567450071015246 0ustar billbillp = nextprime(10^6); q = nextprime(p+1); a = 2*3*5*7; sigma2(x) = sigma(x, 2); sigma3(x) = sigma(x, 3); fun = [ispowerful, moebius, core, omega, bigomega, eulerphi, numdiv, sigma, sigma2, sigma3]; vec(n) = vector(#fun, i, fun[i](n)); args = [a, a*p, a*p*q, a*p^2*q, -a*p]; vals = vector(#args, i, vec(args[i])) TEST() = { for (i=1,#args, my(n = args[i]); print("Testing ", n, ", addprimes = ", addprimes()); if (vec(n) != vals[i], error(n)) ); } addprimes(p); TEST(); addprimes([p,q]); TEST(); removeprimes(p); TEST(); removeprimes(addprimes()) addprimes([p,q,1009]); removeprimes([p,q]) pari-2.17.2/src/test/in/nflistQTall0000644000175000017500000000072314676526175015545 0ustar billbill\\package:galdata nflistdata default(new_galois_format,1); default(parisize,"48M"); \\ overflows 40M [GMP], 46M [portable] tst(n,k)= { my(c = 0, V = List(), P = nflist([n,k],'t)); for (a = 1, 100, my(Q = subst(P,t,a)); if (polisirreducible(Q), if (n > 11 || (polgalois(Q)[3] == k && c++ == 1), return(1)))); error(k); } L=[1,1,2,5,5,16,7,50,34,45,8,301,9,63,104]; S = vector(15,i,[1..L[i]]); for(n=1,#S,print1(n,": ");print([tst(n,k) | k<-S[n]])) pari-2.17.2/src/test/in/exact00000644000175000017500000000107114676526175014471 0ustar billbillMod(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.17.2/src/test/in/nfeltsign0000644000175000017500000000222614676526175015301 0ustar billbillnf = nfinit(x^5+x^4-4*x^3-3*x^2+3*x+1); t = nf.zk[2]; nfeltsign(nf, t) nfeltsign(nf, t, 1) nfeltsign(nf, t, [1..4]) nfeltsign(nf, [1,0,0,0,0]~, [1..4]) nfeltsign(nf, [-1/2,0,0,0,0]~, [1..4]) nfeltsign(nf, 0, 1) nfeltsign(nf, x+950385237198502187979577282097391163977102921506573742575513/495253880608585631635195731645995689515566957889181807495428) u = [x,2;2,-3]; nfeltsign(nf, u) nfeltsign(nf, u, 1) nfeltsign(nf, u, [1..4]) nf=nfinit(a^2-2); for(n=1,100,if(nfeltsign(nf,Mod(a+1,a^2-2)^n)!=[(-1)^n,1],print(n))) \\#2571 c=-114304969395075358172568956118107958797088205582487/8*x^2-1941762517087769652774338691007805097338043062848183/8*x+1316729173405932760915446743314396469951509506994957/2; nf=nfinit(x^3+5*x^2+1240*x-2992); nfeltsign(nf,c) \\#2217 pol=y^6-3*y^5+345*y^4-685*y^3-23547*y^2+23889*y-572438; nf = nfinit(pol); c=64113452896332165808752478841108920358611/18*y^4-64113452896332165808752478841108920358611/9*y^3-197187989995349756135115637139944886536280*y^2+3613497272812627776240833947360116878011651/18*y-46064974046127698515199898568801651913025508/9; nfeltsign(nf,c) \\ Errors nfeltsign(nf, a, 3) nfeltsign(nf, a, [-1..1]) nfeltsign(nf, a, [1..3]) pari-2.17.2/src/test/in/rootsreal0000644000175000017500000000352614760123736015314 0ustar billbillT=x^3-6*x^2+11*x-6; polrootsreal(T) polrootsreal(T, [-oo,3/2]) polrootsreal(T, [3/2,6]) polrootsreal(T, [-oo,+oo]) polrootsreal(T, [2,3]) polrootsreal(T, [1,2]) polsturm(T, [-oo,3/2]) polsturm(T, [3/2,6]) polsturm(T, [-oo,+oo]) polsturm(T, [2,3]) polsturm(T, [1,2]) polsturm(T, [1,+oo]) polsturm(T, 2,3) polsturm(T, 2.,3) polsturm(T,,2) polrootsreal(x^10 + 23*x^9 + 19*x^8 + 18*x^7 + 39*x^6 + 41*x^5 + 46*x^4 + 24*x^3 - 4*x^2 + 2*x + 42) polrootsreal(polchebyshev(9)) polrootsreal(polchebyshev(10)) polrootsreal(x^0) polrootsreal(1) polrootsreal(0) polrootsreal(Pol(0)) polrootsreal(Mod(1,2)) polrootsreal(x+0.) \\ #2196 polroots(T*x+0.) polroots(1) polrootsreal(T,[1,1]) polrootsreal(T,[0,0]) polsturm(T,[1,1]) polsturm(T,[2,1]) polsturm(-5500*x^4+440*x^3+21780*x^2-9680*x-29040,[-oo,-4]) U=(x^2-1)*(x-2); polsturm(U) polsturm(U,[-oo,1]) polsturm(U,[-1,+oo]) polrootsreal(x,[1,2]) polrootsreal(x,[-2,-1]) polrootsreal(x,[-1,1]) polrootsreal(x^3-2) polrootsreal(x^3+2) \\#1605 polsturm(33*x^2-4*x-1) polrootsreal(4*x) polsturm(-4*x) polsturm((x^4-2)^2) \\#1807 T=x^3+x^2-x+2; polrootsreal(T) polsturm(T) polsturm(T,[-3,-1]) polsturm(T,[-2,-1]) polsturm(T,[-oo,-2]) polsturm(T,[-2,oo]) T=4*x^3-2*x^2-x-1; polsturm(T,[0,oo]) polsturm(T,[0,1]) polsturm(T,[0,2]) polsturm(T,[1,3]) polsturm(x+0.) \\#1808 polrootsreal(3*x^3-4*x^2+3*x-1) \\#1809 polrootsreal(x^3-3*x^2-3*x+2) \\#1810 polrootsreal(x^3-x^2) polrootsreal((x^3-x^2)*(x-2)^3*(x-3)^2) default(realprecision,19); #polroots((x+1)^2 * (x-1)^7 * (x^2-x+1)^5 * 1.0) \\#1884 default(realprecision,38); polsturm(x^2-1,[-1,1]) polrootsreal(x^2-1,[-1,1]) polsturm((x-1)^2*(x+2)*1.) \\#2112 pol=-x^4-2*x^3-x^2/3-x/100+1/2000; polrootsreal(pol,[1/100,oo]) pol=-x^4-2*x^3-x^2/3-x/100+1/1000; polrootsreal(pol,[1/10,oo]) \\ one extra root \\ ERRORS: KEEP AT END OF FILE polrootsreal(0.E25*x^2+0.E25*x+0.E25) \\ # 2516 pari-2.17.2/src/test/in/hyperelldisc0000644000175000017500000000644414676526175016005 0ustar billbillhyperelldisc([x^3,1]) hyperelldisc(x^5+1) hyperelldisc(3*x^5+7) hyperellisoncurve([2*x^6+3*x^5+x^4+x^3-x,x^3+1],[1/3,-14/27]) hyperellisoncurve([2*x^6+3*x^5+x^4+x^3-x,x^3+1],[1/3,14/27]) hyperellordinate([2*x^6+3*x^5+x^4+x^3-x,x^3+1],1) hyperellordinate([2*x^6+3*x^5+x^4+x^3-x,x^3+1],0) hyperellordinate([2*x^6+3*x^5+x^4+x^3-x,x^3+1],1/3) hyperellordinate(x^4+30*x^2+25,1) hyperellordinate(x^4+30*x^2+25,-2940/1271) genus(W)= { my([P,Q] = W); my(R = 4*P+Q^2); (poldegree(R)+1)\2-1; } pointchange(Po,C)= { my([x,y]=Po); my(g=genus(W), [e,M,H] = C); my([a,c]=M[,1],[b,d]=M[,2]); if(c*x+d==0,return([0])); my(X=(a*x+b)/(c*x+d)); my(Y=(e*y+subst(H,'x,x))/(c*x+d)^(g+1)); [X,Y]; } W=[subst(polrecip(2176782336*x^6+60466176*x^5+1296*x^2+1),x,81*x+3)-x^6,2*x^3]; W2 = hyperellminimalmodel(W, &C); P=[241/771,-3207473/458314011]; Q=pointchange(P,C) hyperellisoncurve(W,Q) hyperellminimaldisc(W) W=1593*x^6+6750*x^5+11817*x^4+10952*x^3+5672*x^2+1560*x+180; [hyperellminimalmodel(W,&C),C] hyperellminimaldisc(W) W=[subst(x^6+2*x^5+x^4+2*x^3+6*x^2+4*x+1,x,(9*x+19)/(3*x+27))*(3*x+27)^6,0]; WC=hyperellminimalmodel(W,&C); hyperellchangecurve(W,C)==WC test(g,pp=3,u=2,B1=10,B2=B1) = { my(W = pp^u*[random(-B1*x^(2*g+2)),random(-B2*x^(g+1))]); if(hyperelldisc(W)==0 || genus(W)!=g,return); my(M = matrix(2,2,i,j,random(-B1)), de=matdet(M)); if(de==0,return); my(F=factor(2*pp*abs(de))[,1]); my(Wt = hyperellchangecurve(W,[1,M,random(-B*x^(g+1))])); my(C,R = hyperellminimalmodel(W,&C, F)); if(denominator(content(apply(content,R)))>1,error([W,R])); my(Ct,Rt = hyperellminimalmodel(Wt,&Ct,F)); if(denominator(content(apply(content,Rt)))>1,error([Wt,Rt])); if (hyperellchangecurve(W,C)!=R,error("basis change",[W])); if (hyperellchangecurve(Wt,Ct)!=Rt,error("basis change",[Wt])); my(D1 = hyperelldisc(R)); my(Dt = hyperelldisc(Rt)); if(D1 != Dt,error("bad disc:",[W,Wt,R,Rt,D1,Dt])); } for(g=1,2, for(u=0,3, for(i=1,200,test(g,3,u,10,10);test(g,3,u,10,1)))); Q=3254970343038012341524172854446838425023065603322913691574585048043114585293181679254547*x^10+33800276476042018693016760875356135186204584220861792256285249020038281364520918787141*x^9+157945036745175622258322114356626710153773848689934730039281029149926268846410374446*x^8+437368934061034056405076582738875725638756989295437727587277434342233019817359259*x^7+794802450922474530538930245393951491008877497334838937989252320203330150784568*x^6+990406907115776184058530684983249675764756088320969293058409575137878307692*x^5+857048957857534031865836424000784216261689141405786336930764753734221161*x^4+508558361540808033391345602789721912959021860389315102234368788750072*x^3+198036518916159104098971223461808211923666349711869043250644599512*x^2+45698925276170974360066148647971952363526378982195194455592407*x+4745469685449988616659186902678739797214235093067916047144; hyperellred(Q,&M) M hyperellchangecurve(Q,M) Q = 1001*x^4 + 3704*x^3 + 5136*x^2 + 3163*x + 730; hyperellred(Q,&M) M hyperellchangecurve(Q,M) \\ ERRORS, KEEP AT END OF FILE hyperellred(1) hyperellred(Pol(1)) hyperellred(x) hyperellred(x^2+1) hyperellchangecurve(x^3+1,[[1,2],0]) hyperellchangecurve(x^3+1,[1,Mat(1),0]) hyperellchangecurve([],[1,Mat(1),0]) hyperellchangecurve(x^0,[1,matid(2),0]) hyperellminimalmodel(15625*x^6+15626*x^3+1,,5) hyperellminimalmodel(15625*x^6+15626*x^3+1,,[x]) pari-2.17.2/src/test/in/bestappr0000644000175000017500000000152214676526175015126 0ustar billbillbestappr(-1./7, 7) bestappr(-1./7, 6) bestappr(Mod(-1/7,100)) bestappr(Mod(-1/7,100), 6) bestappr(Mod(-1/7,100), 7) bestappr(-1/7 + O(5^10)) bestappr(-1/7 + O(5^10), 6) type( bestappr(1+0.*I) ) bestappr(Mod(10,307), 40) bestappr(-1/48.) bestapprPade((x^3+1)/(x^10+2)) bestapprPade((x^3+1)/(x^10+2), 4) bestapprPade(1/(1+x+O(x^10))) bestapprPade(1/(1+x+O(x^10)), 5) bestapprPade(1/(1+x^6+O(x^13)), 5) bestapprPade(1/(1+x^6+O(x^13))) bestapprPade(Mod(x^3+x^2+x+1, x^5-2)) bestapprPade(x^2+x^3+x^4+O(x^5)) bestapprPade(x^-4+x^-3+x^-2+O(x^-1)) bestapprPade(x^10/(1-x)^11+O(x^22)) \\#1945 bestapprPade(Mod((x^5+x+2)/(1-x)^11,x^20),12) \\#1946 bestapprPade(exp(x),3,4) bestapprPade(tan(x),3,4) bestapprPade(cotan(x),4,3) bestapprPade(polsubcyclo(13,6),3,3) bestapprPade(polsubcyclo(13,6),6,3) bestapprPade((1+x)/(1+x^3+x^6),3,3) bestapprPade(Pol(0),0,0) pari-2.17.2/src/test/in/bnfisintnorm0000644000175000017500000000115314676526175016016 0ustar billbilldo(i)= { my(t = bnfisintnorm(bnf,i)); for (k=1,#t, if (nfeltnorm(bnf,t[k])!=i, error([i,k]))); if (#t, print(i,":",#t)); } \e setrand(1); bnf=bnfinit(x^2+105); for(i=1,1000, do(i)) setrand(1); bnf=bnfinit(x^2-65); for(i=1,1000, do(i-500)) setrand(1); bnf=bnfinit(x^5-37); for(i=1,1000, do(i-500)) /* regression tests: */ bnfisintnorm(bnfinit(x^3+5), 5) bnfisintnorm(bnfinit('y^2+93),54647) bnf = bnfinit('y^2-1466,1); bnfisintnorm(bnf, 10, 1) bnfisintnorm(bnf, -10, 1) bnf = bnfinit('y^2-100129,1); bnfisintnorm(bnf,-6,1) bnf = bnfinit('x^2-2305843005992468481,1); v=bnfisintnorm(bnf,2305843008139952128,1); #v pari-2.17.2/src/test/in/forvec0000644000175000017500000000146214676526175014575 0ustar billbillV=vector(3,i,[3/2,3]); forvec(v=V,print(v)) print() V=vector(3,i,[3/2,4]); forvec(v=V,print(v),1) print() forvec(v=V,print(v),2) V=vector(3,i,[1,3]); forvec(v=V,print(v)) print() forvec(v=V,print(v),1) print() forvec(v=V,print(v),2) forvec(v=[[1,2],[0,1]],print(v),1) forvec(v=[[1,2],[0,1]],print(v),2) forvec(v=vector(3,i,[3/2,7/2]),print(v),1) print() forvec(v=[[3/2,3],[2,4],[3/2,5]],print(v),2) forvec(v=[1],print(v)) forvec(v=[3,2,1],print(v)) my(i=0);forvec(v=[3,2,1,0],if(i++==300,print(v);break())); my(i=0);forvec(v=[0,0,0],if(i++==300,print(v);break())); my(i=0);forvec(v=[3,4,0,0],if(i++==300,print(v);break())); my(i=0);forvec(v=[0,2,0,3],if(i++==300,print(v);break())); forvec(v=[],print(v)) forvec(v=[[1]],) forvec(v=[[1,I]],) forvec(v=[[1,1],[1,1]],,3) forvec(v=[2,3,0,-1,2],) forvec(v=[[2,3],3,0],) pari-2.17.2/src/test/in/qfsolve0000644000175000017500000025415714676526175015003 0ustar billbill{M=[[-634,-706,-200;-706,527,-110;-200,-110,-997],[-670,164,205;164,-391,-509;205,-509,-117],[586,-448,120;-448,-342,-233;120,-233,-851],[-387,-147,450;-147,-808,-22;450,-22,-119],[739,-44,-48;-44,-739,-134;-48,-134,459],[-519,-45,-514;-45,324,178;-514,178,-83],[-482,-683,18;-683,705,852;18,852,315],[808,-16,555;-16,-723,-538;555,-538,-66],[243,205,-14;205,-119,853;-14,853,891],[-220,10,-564;10,-440,-9;-564,-9,413],[383,66,53;66,-962,-104;53,-104,300],[-845,257,264;257,-7,-866;264,-866,259],[-76,676,371;676,-541,-332;371,-332,-417],[111,-203,-57;-203,-634,-30;-57,-30,275],[-926,-548,-178;-548,483,141;-178,141,-953],[-810,-164,648;-164,-802,-612;648,-612,-274],[818,88,630;88,369,524;630,524,-565],[-165,99,-70;99,83,-716;-70,-716,-493],[-183,56,320;56,509,-931;320,-931,-543],[19,799,-94;799,-866,-658;-94,-658,-604],[-859,-569,525;-569,476,217;525,217,-852],[-527,708,47;708,22,-79;47,-79,902],[360,-425,126;-425,-578,-411;126,-411,581],[2,821,59;821,-893,524;59,524,-788],[470,155,-752;155,-679,-683;-752,-683,-584],[398,107,-644;107,-840,374;-644,374,-274],[-839,8,-410;8,-451,-774;-410,-774,801],[-556,-134,-368;-134,183,566;-368,566,686],[-62,354,-396;354,313,350;-396,350,-891],[518,163,17;163,821,332;17,332,-593],[574,-155,19;-155,424,305;19,305,-978],[-720,873,341;873,-131,-116;341,-116,-414],[417,-39,201;-39,910,-9;201,-9,-538],[-34,-193,-22;-193,-632,362;-22,362,-778],[36,-748,-131;-748,-21,147;-131,147,-143],[-236,-560,-211;-560,803,-632;-211,-632,620],[708,-76,-360;-76,814,248;-360,248,263],[790,-271,-338;-271,-114,-400;-338,-400,-12],[-744,-737,-70;-737,-270,-754;-70,-754,816],[-845,520,141;520,-559,73;141,73,132],[-276,406,-305;406,153,-349;-305,-349,41],[632,62,653;62,-125,439;653,439,-256],[-598,-39,-488;-39,-36,461;-488,461,-506],[406,99,-178;99,747,-99;-178,-99,781],[686,-38,-491;-38,-330,-564;-491,-564,253],[427,69,-615;69,933,215;-615,215,-558],[290,-326,-365;-326,928,208;-365,208,754],[-149,-113,197;-113,877,292;197,292,233],[-701,-265,776;-265,911,-259;776,-259,-531],[81,-169,-170;-169,445,-107;-170,-107,632],[-433,153,215;153,15,-362;215,-362,-77],[-108,10,-734;10,-133,-88;-734,-88,-154],[-48,-365,-68;-365,413,-217;-68,-217,-436],[162,-63,184;-63,-728,-240;184,-240,-845],[-96,-233,-747;-233,951,833;-747,833,-30],[-314,-311,-656;-311,322,-663;-656,-663,-639],[-106,-465,-662;-465,-111,53;-662,53,-97],[-410,166,-445;166,-565,104;-445,104,823],[180,-312,19;-312,984,-10;19,-10,701],[-165,936,-247;936,103,743;-247,743,-414],[-571,451,-527;451,419,-499;-527,-499,-473],[-680,182,651;182,-194,-89;651,-89,-889],[670,75,246;75,72,609;246,609,-58],[-929,-764,508;-764,-984,-405;508,-405,-915],[102,736,116;736,634,722;116,722,-656],[33,214,-533;214,-205,-453;-533,-453,844],[235,270,-692;270,68,-323;-692,-323,729],[945,236,5;236,-506,329;5,329,866],[885,-737,539;-737,908,146;539,146,314],[-179,-252,-29;-252,-966,442;-29,442,-116],[-496,-25,-581;-25,-90,-136;-581,-136,492],[513,432,-290;432,-708,47;-290,47,-933],[364,-386,-310;-386,-460,224;-310,224,-363],[-124,214,795;214,-930,-213;795,-213,818],[69,-552,-189;-552,807,-300;-189,-300,249],[-977,-141,-158;-141,169,199;-158,199,-355],[929,268,383;268,945,618;383,618,943],[177,-329,-78;-329,-953,216;-78,216,644],[-335,-314,-76;-314,-572,-229;-76,-229,-214],[609,-226,65;-226,578,271;65,271,-938],[962,-213,483;-213,-159,383;483,383,473],[-821,-501,368;-501,-602,489;368,489,461],[-636,-385,597;-385,-913,903;597,903,849],[967,350,-825;350,352,475;-825,475,974],[-982,7,98;7,-563,-840;98,-840,-726],[-504,81,-124;81,-470,191;-124,191,-846],[756,273,253;273,932,348;253,348,331],[52,-645,783;-645,-606,-565;783,-565,918],[22,-781,-238;-781,-382,-637;-238,-637,-618],[-405,497,-397;497,-489,-593;-397,-593,-916],[-856,5,85;5,-866,-24;85,-24,-540],[764,-153,9;-153,362,-127;9,-127,-1000],[-551,-637,624;-637,-864,361;624,361,12],[-522,203,-199;203,-239,-581;-199,-581,-228],[724,644,245;644,71,456;245,456,983],[-369,-142,164;-142,-644,302;164,302,580],[-485,-786,-362;-786,-207,-326;-362,-326,-257],[373,-271,514;-271,734,390;514,390,-410],[-223,-301,32;-301,-480,-549;32,-549,358],[-501,82,-557;82,609,-296;-557,-296,962];[394,-209,-606,-399;-209,-552,157,-626;-606,157,144,-188;-399,-626,-188,293],[-870,-559,-338,-156;-559,931,293,-7;-338,293,-920,46;-156,-7,46,-563],[703,435,-32,-310;435,-313,103,-144;-32,103,-262,64;-310,-144,64,-769],[523,481,141,-252;481,-291,-403,7;141,-403,-625,-556;-252,7,-556,847],[473,331,-38,-36;331,-346,-409,58;-38,-409,-864,-20;-36,58,-20,-299],[847,138,609,-195;138,-215,232,-257;609,232,953,220;-195,-257,220,63],[544,-494,56,-441;-494,-73,154,-847;56,154,-427,565;-441,-847,565,-503],[-548,200,253,353;200,-582,142,278;253,142,-514,-577;353,278,-577,-555],[-954,-835,-720,-541;-835,-642,116,74;-720,116,-939,168;-541,74,168,32],[-921,16,-253,-807;16,559,-16,-401;-253,-16,604,591;-807,-401,591,848],[-184,326,-437,151;326,-560,373,-103;-437,373,-913,-731;151,-103,-731,735],[637,57,-209,785;57,708,463,-909;-209,463,197,-275;785,-909,-275,751],[901,175,-364,245;175,14,141,811;-364,141,-104,-499;245,811,-499,-705],[-184,942,-258,171;942,-149,-629,366;-258,-629,-935,216;171,366,216,986],[661,647,-235,-432;647,-176,177,192;-235,177,-123,379;-432,192,379,-760],[-957,440,-161,-888;440,2,-148,-48;-161,-148,-598,-743;-888,-48,-743,550],[959,720,-158,225;720,-588,-46,258;-158,-46,530,-753;225,258,-753,367],[291,-64,-481,-53;-64,829,386,305;-481,386,638,213;-53,305,213,22],[949,-74,304,129;-74,-143,-673,-167;304,-673,545,-43;129,-167,-43,-485],[217,861,-669,-333;861,884,-12,675;-669,-12,110,-540;-333,675,-540,67],[957,-415,416,493;-415,862,148,-308;416,148,453,-253;493,-308,-253,-822],[-838,-392,-57,-288;-392,-83,130,323;-57,130,87,199;-288,323,199,-464],[-43,256,-625,-195;256,-320,362,1;-625,362,-611,-142;-195,1,-142,-538],[-524,-608,-260,-17;-608,-211,-123,-438;-260,-123,633,-264;-17,-438,-264,659],[139,-93,776,-239;-93,384,67,-639;776,67,-561,-645;-239,-639,-645,895],[704,-399,-485,-425;-399,-519,748,163;-485,748,-182,-274;-425,163,-274,834],[67,-693,-88,664;-693,987,39,-62;-88,39,-915,-327;664,-62,-327,-434],[-901,102,-239,-270;102,-311,-212,591;-239,-212,771,-105;-270,591,-105,502],[-58,-876,422,-195;-876,-105,-761,-819;422,-761,-760,379;-195,-819,379,117],[995,22,48,-495;22,519,368,-411;48,368,-925,720;-495,-411,720,632],[445,-738,-222,299;-738,-786,-232,-352;-222,-232,-619,-341;299,-352,-341,81],[-490,495,1,-342;495,-222,192,608;1,192,6,-412;-342,608,-412,-723],[684,-101,124,-102;-101,395,-184,413;124,-184,-731,14;-102,413,14,-945],[102,-118,-635,-737;-118,-652,37,575;-635,37,-879,-84;-737,575,-84,748],[732,-244,-50,270;-244,-277,53,574;-50,53,-224,683;270,574,683,223],[466,-48,-330,-472;-48,-834,699,-489;-330,699,-318,745;-472,-489,745,859],[252,72,115,248;72,-846,11,-645;115,11,289,281;248,-645,281,-276],[270,537,-17,345;537,289,-338,489;-17,-338,429,-701;345,489,-701,-214],[731,812,-291,-457;812,-9,-77,294;-291,-77,217,156;-457,294,156,-646],[246,160,-739,53;160,560,-7,437;-739,-7,-803,13;53,437,13,4],[789,-415,-730,436;-415,905,-467,34;-730,-467,97,-35;436,34,-35,128],[111,120,-205,-83;120,358,-58,284;-205,-58,-131,-463;-83,284,-463,825],[96,-218,-174,-75;-218,-200,378,201;-174,378,-221,-29;-75,201,-29,169],[841,-443,244,834;-443,-46,774,-48;244,774,188,194;834,-48,194,-966],[-622,430,-699,-145;430,-977,30,-116;-699,30,-781,-447;-145,-116,-447,452],[787,-20,-232,-250;-20,-50,310,-314;-232,310,-106,422;-250,-314,422,-894],[17,275,-251,-497;275,-581,-179,196;-251,-179,-643,-558;-497,196,-558,-114],[-867,-236,-249,300;-236,318,-308,237;-249,-308,721,-321;300,237,-321,531],[738,575,-59,145;575,721,-480,442;-59,-480,592,170;145,442,170,-757],[201,121,-379,162;121,-469,-132,378;-379,-132,-272,309;162,378,309,-280],[908,109,-209,-921;109,-203,495,371;-209,495,350,240;-921,371,240,-571],[93,29,-738,-360;29,-715,287,-725;-738,287,-523,-109;-360,-725,-109,16],[-97,-86,131,-369;-86,231,-168,30;131,-168,-751,-484;-369,30,-484,-399],[-815,-360,-481,-48;-360,320,326,191;-481,326,555,548;-48,191,548,-707],[96,235,-680,612;235,748,-74,-298;-680,-74,-648,-670;612,-298,-670,622],[-39,-344,297,-252;-344,834,-77,41;297,-77,-60,-279;-252,41,-279,645],[914,196,209,-238;196,-7,44,447;209,44,16,-194;-238,447,-194,-632],[-314,163,756,341;163,982,-61,288;756,-61,706,-76;341,288,-76,-321],[-492,-316,-59,-350;-316,-861,-647,-270;-59,-647,837,-90;-350,-270,-90,-629],[-565,450,97,156;450,984,-271,-315;97,-271,583,-40;156,-315,-40,-110],[-496,-37,98,-453;-37,-152,-81,-349;98,-81,-811,-292;-453,-349,-292,-688],[953,281,-556,904;281,311,-557,-644;-556,-557,845,100;904,-644,100,-359],[-643,497,-310,-229;497,-925,172,255;-310,172,-151,350;-229,255,350,854],[863,150,318,-30;150,-522,-464,-274;318,-464,-942,-256;-30,-274,-256,228],[-211,493,-509,-6;493,215,344,-548;-509,344,227,-727;-6,-548,-727,-682],[-276,-9,204,515;-9,-80,-2,-211;204,-2,-842,43;515,-211,43,543],[-169,669,215,22;669,92,370,18;215,370,684,123;22,18,123,707],[-577,-130,-286,-189;-130,-529,-189,-770;-286,-189,381,-12;-189,-770,-12,-169],[952,-268,40,545;-268,-710,-236,196;40,-236,-559,-115;545,196,-115,571],[418,132,-154,278;132,928,116,-122;-154,116,538,-528;278,-122,-528,37],[782,83,-31,351;83,-662,-39,-609;-31,-39,-414,-249;351,-609,-249,215],[318,532,-172,-248;532,-783,-399,10;-172,-399,-877,823;-248,10,823,-748],[-68,233,-456,-484;233,225,-375,455;-456,-375,-324,188;-484,455,188,-250],[-684,-179,65,466;-179,647,-392,-1;65,-392,-222,292;466,-1,292,-251],[-592,447,-605,51;447,-233,430,67;-605,430,-573,-263;51,67,-263,-506],[-43,308,-326,-746;308,-241,-537,-197;-326,-537,-407,34;-746,-197,34,112],[112,95,137,533;95,317,807,711;137,807,4,26;533,711,26,-792],[755,-108,121,-537;-108,-730,-485,-202;121,-485,753,29;-537,-202,29,965],[-54,235,113,192;235,320,-837,-258;113,-837,398,-498;192,-258,-498,683],[-852,55,-567,102;55,612,-594,460;-567,-594,29,-501;102,460,-501,-213],[4,-100,473,-28;-100,202,64,48;473,64,-593,-616;-28,48,-616,-834],[-692,-666,531,-306;-666,559,49,-619;531,49,-390,-730;-306,-619,-730,324],[-641,-381,108,62;-381,118,-110,-194;108,-110,697,329;62,-194,329,-869],[281,752,-869,350;752,-545,-169,138;-869,-169,782,-376;350,138,-376,97],[-58,647,-85,391;647,-968,459,-166;-85,459,469,323;391,-166,323,-104],[-20,728,757,569;728,531,530,-500;757,530,-47,101;569,-500,101,-500],[-980,413,-81,602;413,647,118,30;-81,118,-787,-709;602,30,-709,582],[518,-59,335,247;-59,-184,460,-518;335,460,510,-216;247,-518,-216,-7],[762,-305,724,-25;-305,-328,805,414;724,805,-942,-83;-25,414,-83,-88],[388,-318,-111,416;-318,146,-678,742;-111,-678,35,543;416,742,543,891],[402,5,-176,845;5,-56,-427,-745;-176,-427,217,196;845,-745,196,363],[981,159,-168,186;159,760,-718,816;-168,-718,356,-245;186,816,-245,244],[495,-302,243,-33;-302,-118,97,-204;243,97,20,192;-33,-204,192,153],[954,-725,339,422;-725,-4,-230,712;339,-230,-57,-11;422,712,-11,-690],[765,-702,29,-644;-702,789,-366,75;29,-366,49,-479;-644,75,-479,575],[-62,381,327,631;381,577,-512,-672;327,-512,146,158;631,-672,158,126],[-947,541,87,-893;541,-495,-41,-665;87,-41,861,60;-893,-665,60,175],[-910,488,-479,-431;488,991,143,229;-479,143,783,-356;-431,229,-356,-333],[846,-356,-144,-336;-356,888,-228,-471;-144,-228,-194,-647;-336,-471,-647,-724],[-10,454,119,65;454,468,-597,260;119,-597,567,-110;65,260,-110,106];[-564,568,485,513,7;568,-526,612,-346,460;485,612,183,-757,-36;513,-346,-757,-536,505;7,460,-36,505,693],[-379,-94,-635,347,-257;-94,-489,84,-418,229;-635,84,361,-107,-17;347,-418,-107,-48,-715;-257,229,-17,-715,-966],[533,-388,15,340,-489;-388,-366,-37,-836,-93;15,-37,627,328,-271;340,-836,328,-576,-812;-489,-93,-271,-812,-769],[-518,-276,-221,336,787;-276,307,463,342,374;-221,463,-417,499,428;336,342,499,-572,-117;787,374,428,-117,-648],[-63,-268,835,-443,-432;-268,-811,713,-136,-363;835,713,58,151,791;-443,-136,151,-517,-412;-432,-363,791,-412,104],[-95,-786,24,-81,-432;-786,744,139,312,251;24,139,423,298,479;-81,312,298,-672,-239;-432,251,479,-239,9],[888,-546,-211,69,-50;-546,220,59,432,76;-211,59,454,552,432;69,432,552,283,-368;-50,76,432,-368,614],[-164,-64,-626,247,-567;-64,116,-387,584,-334;-626,-387,555,-430,553;247,584,-430,213,-966;-567,-334,553,-966,929],[626,493,-33,391,-355;493,868,-572,193,394;-33,-572,252,-258,-172;391,193,-258,-822,349;-355,394,-172,349,359],[-554,412,-131,31,507;412,794,-428,-31,44;-131,-428,683,-157,330;31,-31,-157,-780,464;507,44,330,464,-750],[45,210,831,-678,-52;210,-539,157,219,-94;831,157,452,698,-380;-678,219,698,-203,-513;-52,-94,-380,-513,-221],[148,-171,-445,202,659;-171,-531,551,-48,-440;-445,551,502,18,-69;202,-48,18,240,-437;659,-440,-69,-437,-778],[-544,-88,-52,-34,-341;-88,238,517,527,306;-52,517,-192,403,79;-34,527,403,210,471;-341,306,79,471,781],[463,-680,-929,668,294;-680,-264,682,-498,864;-929,682,-503,-903,-562;668,-498,-903,438,-217;294,864,-562,-217,-58],[-66,-495,-201,-401,-128;-495,171,570,-139,-745;-201,570,614,-566,356;-401,-139,-566,-818,-797;-128,-745,356,-797,967],[-768,345,73,-335,-489;345,-478,52,211,-100;73,52,94,0,264;-335,211,0,619,-695;-489,-100,264,-695,447],[-239,-24,198,-123,-152;-24,374,-611,-425,-191;198,-611,589,-615,336;-123,-425,-615,26,-782;-152,-191,336,-782,950],[-336,670,8,196,86;670,857,144,-710,-682;8,144,648,-21,854;196,-710,-21,936,923;86,-682,854,923,-368],[-536,235,-207,-112,-499;235,-391,-900,106,189;-207,-900,346,-359,581;-112,106,-359,-461,-341;-499,189,581,-341,269],[-264,431,731,73,-190;431,-513,-131,-101,-23;731,-131,-223,119,245;73,-101,119,-553,511;-190,-23,245,511,530],[943,-212,171,-448,-45;-212,-613,286,-453,-603;171,286,-36,-8,-134;-448,-453,-8,-452,-372;-45,-603,-134,-372,-610],[434,-204,457,47,-340;-204,-163,705,327,49;457,705,-463,-555,-40;47,327,-555,-996,-402;-340,49,-40,-402,421],[202,-242,-953,-143,-284;-242,161,225,-197,-828;-953,225,151,-407,808;-143,-197,-407,535,348;-284,-828,808,348,-688],[-668,725,-427,528,330;725,813,-586,-488,209;-427,-586,951,107,-254;528,-488,107,2,-472;330,209,-254,-472,294],[-839,-247,50,445,-82;-247,114,-527,-150,-201;50,-527,-504,-233,96;445,-150,-233,863,697;-82,-201,96,697,254],[-975,-683,-223,410,591;-683,-56,-133,-592,424;-223,-133,-633,174,-339;410,-592,174,453,-286;591,424,-339,-286,-850],[69,75,609,39,182;75,36,292,587,251;609,292,-678,151,-196;39,587,151,-906,-435;182,251,-196,-435,948],[-102,251,-928,478,-2;251,-622,449,-307,-166;-928,449,-832,512,0;478,-307,512,925,491;-2,-166,0,491,646],[14,768,-575,216,555;768,-196,422,772,-823;-575,422,-373,684,305;216,772,684,904,569;555,-823,305,569,15],[741,-172,99,-82,-553;-172,-787,573,320,225;99,573,-672,-740,569;-82,320,-740,-198,-943;-553,225,569,-943,-413],[-981,21,38,19,43;21,-55,-303,568,243;38,-303,-376,-55,-721;19,568,-55,83,-402;43,243,-721,-402,943],[710,97,-685,411,71;97,-324,773,-582,597;-685,773,-692,393,-204;411,-582,393,410,11;71,597,-204,11,-238],[-765,404,-10,-80,251;404,-195,2,167,304;-10,2,369,328,308;-80,167,328,-859,-281;251,304,308,-281,151],[126,584,513,334,-25;584,-358,-99,27,329;513,-99,793,-106,195;334,27,-106,-532,-18;-25,329,195,-18,617],[732,-546,81,-379,-399;-546,-205,79,19,-73;81,79,987,-435,575;-379,19,-435,999,-90;-399,-73,575,-90,-341],[-373,-891,190,539,327;-891,-997,-89,185,433;190,-89,778,-1,-337;539,185,-1,394,-141;327,433,-337,-141,281],[-624,102,-778,200,-350;102,-748,-333,146,-243;-778,-333,-10,90,145;200,146,90,-728,146;-350,-243,145,146,-166],[-848,-806,255,240,283;-806,373,744,858,404;255,744,-504,55,-867;240,858,55,950,101;283,404,-867,101,427],[302,-557,-629,100,8;-557,-627,502,60,226;-629,502,-812,748,352;100,60,748,658,330;8,226,352,330,-252],[280,575,579,-515,257;575,-355,-201,203,163;579,-201,689,-540,58;-515,203,-540,737,-342;257,163,58,-342,485],[491,353,76,-533,337;353,756,-358,-237,105;76,-358,-301,350,-232;-533,-237,350,905,558;337,105,-232,558,616],[-594,299,-104,-275,37;299,883,503,695,592;-104,503,-275,199,248;-275,695,199,21,-32;37,592,248,-32,692],[-79,448,106,323,-45;448,-967,649,351,400;106,649,-458,-435,275;323,351,-435,-117,-759;-45,400,275,-759,-165],[-740,-85,540,-27,244;-85,-934,472,575,171;540,472,-947,476,550;-27,575,476,-582,566;244,171,550,566,-509],[831,-113,-331,92,-472;-113,89,110,-295,93;-331,110,338,665,-273;92,-295,665,-754,558;-472,93,-273,558,-883],[277,-733,-472,67,638;-733,170,-229,160,-805;-472,-229,510,-61,-135;67,160,-61,-89,-231;638,-805,-135,-231,769],[567,517,-261,-38,357;517,386,2,777,226;-261,2,590,-394,-296;-38,777,-394,188,-236;357,226,-296,-236,209],[-697,-632,494,513,-241;-632,95,-245,487,100;494,-245,-37,0,15;513,487,0,717,-33;-241,100,15,-33,440],[-474,-135,-35,-406,-241;-135,-128,402,-26,-170;-35,402,-933,-41,-138;-406,-26,-41,791,-167;-241,-170,-138,-167,-286],[-854,-121,-48,-570,419;-121,-59,22,-196,368;-48,22,-194,-258,-46;-570,-196,-258,497,6;419,368,-46,6,-124],[-306,470,671,-322,41;470,988,-964,131,193;671,-964,-218,175,378;-322,131,175,470,-50;41,193,378,-50,506],[478,-324,-581,89,540;-324,-885,-57,-600,-464;-581,-57,785,-69,-182;89,-600,-69,-595,157;540,-464,-182,157,-322],[-724,62,466,-176,570;62,-735,181,-420,-19;466,181,53,-293,-14;-176,-420,-293,-990,344;570,-19,-14,344,-771],[-429,13,-134,543,-175;13,-200,-702,291,-202;-134,-702,684,-389,321;543,291,-389,-510,189;-175,-202,321,189,-713],[919,83,-70,309,-566;83,-977,402,-190,-312;-70,402,-829,-533,106;309,-190,-533,-306,-35;-566,-312,106,-35,-599],[-620,-223,29,-150,-213;-223,248,497,-768,-305;29,497,-657,798,0;-150,-768,798,930,30;-213,-305,0,30,-51],[-965,53,-98,155,195;53,-349,634,225,948;-98,634,-847,125,573;155,225,125,33,507;195,948,573,507,-390],[-526,338,50,394,607;338,435,-100,590,403;50,-100,-480,-228,792;394,590,-228,-377,-478;607,403,792,-478,514],[-293,280,-137,60,247;280,-6,116,-506,177;-137,116,-906,764,452;60,-506,764,-420,275;247,177,452,275,294],[307,490,-31,-208,347;490,-456,726,-453,113;-31,726,-892,450,-532;-208,-453,450,-393,-230;347,113,-532,-230,-417],[700,408,-90,-330,249;408,325,-344,-6,64;-90,-344,608,358,-550;-330,-6,358,342,388;249,64,-550,388,628],[-668,-7,558,-90,3;-7,805,67,158,8;558,67,178,-635,401;-90,158,-635,-163,-413;3,8,401,-413,-501],[-940,319,-177,-311,170;319,-588,749,843,403;-177,749,-134,-381,-577;-311,843,-381,-709,-161;170,403,-577,-161,995],[458,-800,-2,-551,-101;-800,-832,477,-256,329;-2,477,384,-263,183;-551,-256,-263,800,-468;-101,329,183,-468,-321],[-198,-129,-271,347,-584;-129,182,36,-962,-226;-271,36,-274,-336,-522;347,-962,-336,456,-115;-584,-226,-522,-115,557],[360,283,902,651,-69;283,-673,-326,-867,39;902,-326,199,130,582;651,-867,130,471,37;-69,39,582,37,796],[-795,-20,-143,-308,554;-20,-521,609,174,563;-143,609,-539,44,159;-308,174,44,122,-707;554,563,159,-707,-584],[-885,550,178,-421,145;550,-413,-180,-757,578;178,-180,-501,208,345;-421,-757,208,-882,136;145,578,345,136,-705],[188,552,-114,248,-867;552,-594,-348,266,-172;-114,-348,-428,604,242;248,266,604,617,-81;-867,-172,242,-81,867],[702,361,239,-502,172;361,-932,-89,-486,-789;239,-89,991,91,349;-502,-486,91,447,280;172,-789,349,280,-236],[-717,-249,-608,-505,97;-249,-222,-65,157,505;-608,-65,-796,697,614;-505,157,697,187,139;97,505,614,139,-747],[829,126,59,-147,-5;126,-239,-261,-327,475;59,-261,-13,-210,-417;-147,-327,-210,594,-249;-5,475,-417,-249,637],[710,116,-118,709,285;116,-847,-351,28,-535;-118,-351,-348,232,-256;709,28,232,479,-382;285,-535,-256,-382,906],[-383,-85,563,-666,563;-85,924,974,356,211;563,974,14,250,-510;-666,356,250,458,166;563,211,-510,166,753],[-968,18,-75,638,-462;18,-37,79,-504,-92;-75,79,-543,72,253;638,-504,72,-896,929;-462,-92,253,929,-319],[614,-856,-127,541,-245;-856,-676,816,-940,-298;-127,816,-220,-522,140;541,-940,-522,878,581;-245,-298,140,581,245],[-85,-34,-122,-478,-115;-34,-759,-367,-193,603;-122,-367,605,276,79;-478,-193,276,798,508;-115,603,79,508,592],[-333,-138,-112,-263,179;-138,817,756,-48,391;-112,756,969,-731,752;-263,-48,-731,156,-321;179,391,752,-321,-712],[477,249,-294,-37,336;249,440,-302,622,-527;-294,-302,-692,-319,-269;-37,622,-319,685,-541;336,-527,-269,-541,-967],[-873,138,-286,-799,317;138,779,-78,13,-300;-286,-78,394,24,61;-799,13,24,-578,-441;317,-300,61,-441,178],[731,432,388,128,763;432,-160,-144,-97,24;388,-144,888,330,135;128,-97,330,-884,-301;763,24,135,-301,-902],[903,29,435,-334,522;29,876,526,26,449;435,526,-16,162,27;-334,26,162,-659,-382;522,449,27,-382,262],[-379,-816,431,-196,-632;-816,-939,-65,-621,111;431,-65,254,247,-416;-196,-621,247,-377,-50;-632,111,-416,-50,493],[-140,-350,-271,364,-657;-350,-321,-101,-87,-648;-271,-101,117,-376,-616;364,-87,-376,-331,26;-657,-648,-616,26,-793],[-846,962,-39,798,-742;962,-844,404,123,562;-39,404,-536,44,-729;798,123,44,-552,71;-742,562,-729,71,-458],[-943,-160,-175,148,-289;-160,625,624,-87,123;-175,624,-198,-23,-459;148,-87,-23,-854,291;-289,123,-459,291,119],[125,24,-75,172,605;24,-192,-385,707,129;-75,-385,-106,-110,-81;172,707,-110,179,239;605,129,-81,239,-216],[329,-86,307,-776,-546;-86,818,256,100,-332;307,256,-805,-398,321;-776,100,-398,-761,-576;-546,-332,321,-576,-2],[934,-696,-129,-171,-99;-696,-882,385,-535,-707;-129,385,488,305,8;-171,-535,305,-27,465;-99,-707,8,465,-329],[-279,11,260,-35,-333;11,175,-854,-246,-126;260,-854,-31,487,43;-35,-246,487,-775,195;-333,-126,43,195,-956],[-999,613,-166,-58,808;613,-518,-574,-664,416;-166,-574,-387,313,95;-58,-664,313,872,-34;808,416,95,-34,851],[-746,-456,-738,326,418;-456,418,848,62,483;-738,848,-980,104,-547;326,62,104,118,-18;418,483,-547,-18,301],[268,-302,-195,725,103;-302,-931,-885,812,-278;-195,-885,-3,-572,-280;725,812,-572,719,867;103,-278,-280,867,551],[544,230,-284,344,-698;230,-593,-370,-322,576;-284,-370,-979,-118,-9;344,-322,-118,942,714;-698,576,-9,714,-851],[301,-368,-694,45,212;-368,388,110,-530,-364;-694,110,271,-9,418;45,-530,-9,-838,-239;212,-364,418,-239,-448],[-243,224,27,249,337;224,317,-432,-383,133;27,-432,-681,779,-89;249,-383,779,844,405;337,133,-89,405,138],[481,61,-452,385,-156;61,-549,-691,-389,-36;-452,-691,597,345,-685;385,-389,345,-748,598;-156,-36,-685,598,-745],[-586,846,126,-357,704;846,-840,746,-6,203;126,746,673,-556,-262;-357,-6,-556,556,-206;704,203,-262,-206,663],[796,-218,-314,-352,214;-218,-973,649,-525,410;-314,649,-108,-642,-177;-352,-525,-642,139,-568;214,410,-177,-568,-655],[540,393,834,299,-166;393,153,35,109,150;834,35,-660,-529,569;299,109,-529,695,558;-166,150,569,558,989];[250,623,394,139,394,-485;623,950,605,-643,19,-311;394,605,-188,799,386,-600;139,-643,799,248,659,-616;394,19,386,659,236,-145;-485,-311,-600,-616,-145,-743],[899,543,-487,324,-284,-752;543,-305,-138,-108,-66,-360;-487,-138,-936,121,573,506;324,-108,121,164,-5,-438;-284,-66,573,-5,-878,151;-752,-360,506,-438,151,-891],[-349,136,-393,659,-232,488;136,42,806,279,327,313;-393,806,687,588,-121,223;659,279,588,109,-205,714;-232,327,-121,-205,684,-747;488,313,223,714,-747,192],[932,463,-748,68,-150,-264;463,-444,384,866,726,125;-748,384,-31,-160,804,179;68,866,-160,-498,159,-183;-150,726,804,159,794,463;-264,125,179,-183,463,-507],[519,132,272,-150,56,-96;132,451,38,560,-365,190;272,38,-686,135,-238,-510;-150,560,135,353,-129,240;56,-365,-238,-129,571,-256;-96,190,-510,240,-256,-627],[-694,137,-268,131,-429,-201;137,-130,-69,-39,-130,336;-268,-69,622,-515,174,453;131,-39,-515,-333,165,-316;-429,-130,174,165,853,836;-201,336,453,-316,836,-31],[920,-703,166,174,-451,124;-703,-651,56,297,-34,-24;166,56,530,148,14,516;174,297,148,503,317,82;-451,-34,14,317,934,350;124,-24,516,82,350,-921],[284,333,-642,510,563,441;333,909,442,561,-372,-319;-642,442,72,684,46,-802;510,561,684,-936,-48,285;563,-372,46,-48,546,221;441,-319,-802,285,221,-149],[556,-200,75,-156,529,264;-200,-689,-314,98,-144,-60;75,-314,110,-517,-399,81;-156,98,-517,768,471,706;529,-144,-399,471,-607,134;264,-60,81,706,134,-336],[-31,76,-13,412,-442,-71;76,-179,-306,469,-82,-107;-13,-306,-505,162,71,253;412,469,162,-376,190,231;-442,-82,71,190,-374,-517;-71,-107,253,231,-517,467],[-52,334,-360,-86,-466,80;334,478,43,-203,500,-33;-360,43,294,417,-590,-507;-86,-203,417,305,772,480;-466,500,-590,772,-476,180;80,-33,-507,480,180,-603],[-534,-134,-366,388,-656,-393;-134,-847,565,-148,372,137;-366,565,-550,-68,-262,-716;388,-148,-68,-832,254,162;-656,372,-262,254,-795,47;-393,137,-716,162,47,870],[-49,385,306,-659,479,-423;385,811,-288,5,608,-839;306,-288,-851,-383,-206,117;-659,5,-383,-936,408,569;479,608,-206,408,-438,-203;-423,-839,117,569,-203,-584],[138,-137,32,189,-635,168;-137,-782,19,-224,-133,-523;32,19,726,-57,271,-138;189,-224,-57,-884,-565,-630;-635,-133,271,-565,-305,529;168,-523,-138,-630,529,390],[-875,-791,-144,511,108,-164;-791,-59,-596,6,-520,534;-144,-596,-721,355,201,-129;511,6,355,738,-58,-318;108,-520,201,-58,-41,436;-164,534,-129,-318,436,-743],[457,540,-477,847,412,-89;540,-196,305,841,20,176;-477,305,293,-290,-627,-747;847,841,-290,-962,-147,33;412,20,-627,-147,-651,824;-89,176,-747,33,824,-472],[440,36,42,-257,307,556;36,112,-417,496,-199,298;42,-417,-624,417,395,195;-257,496,417,291,407,142;307,-199,395,407,-724,-167;556,298,195,142,-167,486],[-56,311,800,-536,-91,451;311,724,-120,403,159,339;800,-120,-169,-600,304,-562;-536,403,-600,-444,-404,-475;-91,159,304,-404,886,163;451,339,-562,-475,163,701],[831,-9,-193,250,-259,-177;-9,-279,-447,671,-344,243;-193,-447,119,250,-220,-13;250,671,250,-404,359,-171;-259,-344,-220,359,-77,-141;-177,243,-13,-171,-141,-71],[-290,-385,-7,232,300,-595;-385,715,544,-108,-746,-590;-7,544,365,-105,-187,-159;232,-108,-105,-923,582,334;300,-746,-187,582,-281,651;-595,-590,-159,334,651,322],[-907,229,-390,78,347,-413;229,945,-480,151,-738,711;-390,-480,-89,-188,-693,6;78,151,-188,656,-586,443;347,-738,-693,-586,-751,-396;-413,711,6,443,-396,-17],[-915,-17,591,161,16,-448;-17,177,300,723,326,0;591,300,489,-680,-591,279;161,723,-680,-119,-371,-937;16,326,-591,-371,-724,-244;-448,0,279,-937,-244,-270],[-376,-205,333,-491,171,364;-205,968,120,251,-80,-334;333,120,-33,-346,-517,-757;-491,251,-346,-74,-261,618;171,-80,-517,-261,-537,169;364,-334,-757,618,169,-464],[-158,-435,-280,29,549,-51;-435,-742,427,308,817,-432;-280,427,-317,544,472,-361;29,308,544,-951,256,35;549,817,472,256,907,284;-51,-432,-361,35,284,460],[-497,-300,-715,433,44,-341;-300,296,-76,-900,-319,-644;-715,-76,239,710,-30,-232;433,-900,710,-780,25,-612;44,-319,-30,25,-91,677;-341,-644,-232,-612,677,963],[-483,-373,254,58,112,-472;-373,781,-720,645,432,442;254,-720,227,145,719,-242;58,645,145,-265,-308,-19;112,432,719,-308,-110,305;-472,442,-242,-19,305,-641],[426,717,-190,194,600,-397;717,-324,392,98,238,68;-190,392,-313,316,-723,535;194,98,316,721,419,483;600,238,-723,419,-820,9;-397,68,535,483,9,737],[-682,519,-724,-204,-606,-348;519,-484,299,23,-49,-319;-724,299,-794,342,-498,36;-204,23,342,276,611,332;-606,-49,-498,611,-962,-432;-348,-319,36,332,-432,-955],[971,-610,-29,-607,146,-692;-610,-906,-177,217,536,-522;-29,-177,398,-61,49,-333;-607,217,-61,-421,-69,-21;146,536,49,-69,578,754;-692,-522,-333,-21,754,-889],[137,612,379,731,-89,149;612,-706,-257,-698,507,290;379,-257,110,407,455,260;731,-698,407,659,82,-404;-89,507,455,82,-618,-136;149,290,260,-404,-136,-790],[714,-226,-159,177,-129,450;-226,381,-254,-349,-409,95;-159,-254,-961,129,446,-302;177,-349,129,-396,-198,-214;-129,-409,446,-198,415,-123;450,95,-302,-214,-123,415],[141,699,-683,-890,449,-692;699,-533,-356,293,-166,268;-683,-356,-473,32,-16,151;-890,293,32,-183,240,335;449,-166,-16,240,-534,-122;-692,268,151,335,-122,266],[-307,377,889,-520,-105,-446;377,900,305,302,43,297;889,305,-834,187,-880,294;-520,302,187,-446,-649,-515;-105,43,-880,-649,662,-387;-446,297,294,-515,-387,-570],[-526,-630,488,-512,101,-657;-630,212,-529,-261,-16,7;488,-529,429,172,105,-875;-512,-261,172,-720,172,230;101,-16,105,172,724,-11;-657,7,-875,230,-11,833],[704,840,-58,-261,667,-482;840,-160,90,-382,-89,462;-58,90,-133,59,281,-62;-261,-382,59,-485,784,4;667,-89,281,784,-563,67;-482,462,-62,4,67,-634],[-462,-146,772,494,397,834;-146,174,23,377,15,528;772,23,-445,-144,116,-225;494,377,-144,660,-471,-251;397,15,116,-471,455,-443;834,528,-225,-251,-443,580],[-48,-185,267,-414,206,-165;-185,592,-46,269,84,-306;267,-46,251,-64,-640,82;-414,269,-64,878,-529,-361;206,84,-640,-529,840,48;-165,-306,82,-361,48,929],[376,830,212,-693,32,-372;830,-39,37,-397,140,74;212,37,384,-533,621,577;-693,-397,-533,492,348,-103;32,140,621,348,-107,169;-372,74,577,-103,169,-106],[-460,583,225,-2,687,55;583,724,294,-832,17,-361;225,294,-714,86,-234,272;-2,-832,86,-598,199,-81;687,17,-234,199,-370,-394;55,-361,272,-81,-394,-16],[-352,-297,28,362,-321,-290;-297,972,10,227,-145,526;28,10,-794,-10,397,305;362,227,-10,-94,-400,-430;-321,-145,397,-400,869,352;-290,526,305,-430,352,-93],[-699,-128,29,418,-137,946;-128,-946,293,336,152,-100;29,293,473,-603,233,-260;418,336,-603,883,882,-183;-137,152,233,882,248,-197;946,-100,-260,-183,-197,-688],[696,-143,489,-228,405,549;-143,-919,749,-176,-471,-816;489,749,-221,-272,598,671;-228,-176,-272,652,-51,-6;405,-471,598,-51,563,-734;549,-816,671,-6,-734,360],[-521,405,92,352,-158,-111;405,-696,-361,115,-444,-459;92,-361,871,142,267,-36;352,115,142,905,253,-199;-158,-444,267,253,-320,189;-111,-459,-36,-199,189,-46],[-790,367,117,-43,175,409;367,654,131,-823,-37,377;117,131,89,-14,-185,-317;-43,-823,-14,963,241,767;175,-37,-185,241,-141,-149;409,377,-317,767,-149,811],[-250,666,475,-73,701,-21;666,-136,214,213,-718,185;475,214,-42,456,177,-302;-73,213,456,191,15,231;701,-718,177,15,-331,-490;-21,185,-302,231,-490,-339],[-20,-312,-255,12,-45,123;-312,415,-415,311,-577,424;-255,-415,700,229,-535,222;12,311,229,763,-800,986;-45,-577,-535,-800,784,-45;123,424,222,986,-45,689],[85,-623,-81,-82,440,358;-623,-864,244,108,-61,210;-81,244,-158,46,215,-33;-82,108,46,-955,-36,-402;440,-61,215,-36,-236,-879;358,210,-33,-402,-879,-70],[-750,-192,-92,279,-99,-155;-192,658,-202,628,-366,-563;-92,-202,194,203,38,335;279,628,203,-276,-149,-27;-99,-366,38,-149,550,-79;-155,-563,335,-27,-79,-310],[959,206,-23,-249,793,256;206,-19,-578,284,-8,539;-23,-578,318,-396,292,538;-249,284,-396,394,581,112;793,-8,292,581,721,-371;256,539,538,112,-371,-869],[157,372,-914,641,146,-734;372,-704,130,631,250,466;-914,130,-789,526,675,-252;641,631,526,-341,155,93;146,250,675,155,-321,-845;-734,466,-252,93,-845,18],[408,179,-258,-35,370,-745;179,753,-494,-183,-725,512;-258,-494,255,447,-200,-648;-35,-183,447,912,596,125;370,-725,-200,596,-262,250;-745,512,-648,125,250,-767],[770,-730,289,36,-314,-199;-730,259,-746,740,286,-508;289,-746,580,251,-401,103;36,740,251,764,372,167;-314,286,-401,372,-269,-853;-199,-508,103,167,-853,-34],[-579,325,661,-348,645,-729;325,433,871,801,221,-631;661,871,846,-124,27,433;-348,801,-124,-251,-990,-97;645,221,27,-990,-957,-618;-729,-631,433,-97,-618,-373],[221,204,482,-309,-150,-760;204,-265,-487,-295,26,-244;482,-487,-961,-108,-113,405;-309,-295,-108,-800,-369,-21;-150,26,-113,-369,122,475;-760,-244,405,-21,475,347],[-820,32,-50,356,-705,-243;32,-651,543,121,-684,-186;-50,543,186,-247,656,-244;356,121,-247,350,100,247;-705,-684,656,100,-680,906;-243,-186,-244,247,906,-469],[431,-287,357,-430,-130,373;-287,-248,500,113,895,-59;357,500,60,-576,82,192;-430,113,-576,-478,-772,369;-130,895,82,-772,-462,268;373,-59,192,369,268,-734],[-352,-378,98,-49,374,623;-378,-999,197,68,266,180;98,197,701,-208,-129,-412;-49,68,-208,863,-117,442;374,266,-129,-117,-518,694;623,180,-412,442,694,501],[924,168,-46,550,41,84;168,608,-653,-514,-201,693;-46,-653,-744,751,158,-75;550,-514,751,-549,143,-563;41,-201,158,143,-564,-356;84,693,-75,-563,-356,731],[993,644,-32,-19,-163,372;644,467,-377,297,387,-321;-32,-377,920,76,-455,808;-19,297,76,649,-450,71;-163,387,-455,-450,284,-158;372,-321,808,71,-158,529],[246,248,608,-198,-18,405;248,-359,243,479,-563,-14;608,243,-109,140,314,98;-198,479,140,488,264,321;-18,-563,314,264,-853,-387;405,-14,98,321,-387,616],[-637,-606,-12,-32,902,-41;-606,912,162,-371,-284,-739;-12,162,-909,-711,34,-326;-32,-371,-711,379,-626,151;902,-284,34,-626,-716,125;-41,-739,-326,151,125,-764],[-538,-632,-235,904,480,53;-632,-156,-336,-342,82,-172;-235,-336,-24,123,129,-444;904,-342,123,-125,-151,83;480,82,129,-151,70,-48;53,-172,-444,83,-48,-537],[497,-860,-57,197,-237,-131;-860,-312,-391,202,329,550;-57,-391,139,165,49,578;197,202,165,-771,580,131;-237,329,49,580,643,164;-131,550,578,131,164,-341],[-735,583,120,164,-565,-76;583,-174,-174,389,-674,-180;120,-174,464,375,-454,-451;164,389,375,-605,-317,-821;-565,-674,-454,-317,456,-456;-76,-180,-451,-821,-456,-373],[687,580,851,459,139,-93;580,-476,-912,455,-605,381;851,-912,-532,663,140,-736;459,455,663,665,-312,223;139,-605,140,-312,-724,-185;-93,381,-736,223,-185,132],[160,-532,608,-331,-600,60;-532,613,853,310,296,44;608,853,35,54,212,-7;-331,310,54,519,480,33;-600,296,212,480,293,689;60,44,-7,33,689,266],[579,4,-562,-731,175,-782;4,318,392,468,-568,-563;-562,392,-891,348,256,7;-731,468,348,327,-178,-422;175,-568,256,-178,837,-723;-782,-563,7,-422,-723,-238],[-739,453,742,543,-791,-417;453,793,169,-102,-156,-188;742,169,-17,108,-351,-553;543,-102,108,-599,-18,195;-791,-156,-351,-18,-223,-114;-417,-188,-553,195,-114,-322],[-678,-308,-290,52,175,14;-308,-988,-705,135,-705,-532;-290,-705,-291,-494,-87,-725;52,135,-494,-500,-506,-189;175,-705,-87,-506,-943,-583;14,-532,-725,-189,-583,995],[-837,134,-213,-67,200,104;134,-490,-400,635,199,-255;-213,-400,682,59,-221,322;-67,635,59,-797,284,-399;200,199,-221,284,881,577;104,-255,322,-399,577,477],[555,14,-887,-202,695,528;14,-927,330,-314,375,-391;-887,330,-134,464,446,346;-202,-314,464,-313,345,363;695,375,446,345,-79,-184;528,-391,346,363,-184,780],[422,58,282,210,-461,94;58,796,706,258,588,-301;282,706,-838,-252,291,-204;210,258,-252,-718,-112,414;-461,588,291,-112,-480,-630;94,-301,-204,414,-630,-889],[-256,759,-214,685,465,-315;759,-944,538,57,-482,299;-214,538,307,640,-137,403;685,57,640,-235,367,213;465,-482,-137,367,188,33;-315,299,403,213,33,-175],[-880,-536,-590,-111,127,-279;-536,749,-180,-387,331,44;-590,-180,-735,-445,347,-44;-111,-387,-445,704,-43,-22;127,331,347,-43,-197,215;-279,44,-44,-22,215,-766],[356,180,416,168,658,-14;180,-229,-316,-408,-834,-724;416,-316,408,-197,-218,-406;168,-408,-197,-754,88,429;658,-834,-218,88,-244,587;-14,-724,-406,429,587,-556],[-968,504,-302,-234,-393,667;504,-948,-680,598,-100,770;-302,-680,-94,-419,135,-350;-234,598,-419,-386,303,350;-393,-100,135,303,-116,69;667,770,-350,350,69,411],[385,259,177,46,13,120;259,-467,445,-398,210,189;177,445,560,58,-26,560;46,-398,58,-874,224,63;13,210,-26,224,-628,156;120,189,560,63,156,-497],[-124,429,577,-223,-36,405;429,343,-398,-302,448,-48;577,-398,920,304,768,570;-223,-302,304,-55,-415,-71;-36,448,768,-415,906,-490;405,-48,570,-71,-490,-330],[714,684,-730,-19,290,-210;684,-984,59,256,72,280;-730,59,-122,46,-7,936;-19,256,46,-177,-697,-104;290,72,-7,-697,-812,502;-210,280,936,-104,502,956],[-835,240,277,73,220,448;240,921,286,617,309,52;277,286,3,202,21,42;73,617,202,966,233,-318;220,309,21,233,540,-165;448,52,42,-318,-165,-601],[826,58,-448,7,570,254;58,-803,-45,327,496,-321;-448,-45,753,861,396,313;7,327,861,-277,-240,-484;570,496,396,-240,-350,605;254,-321,313,-484,605,477],[-847,-687,565,-182,719,62;-687,299,138,-496,-38,-438;565,138,256,-156,416,41;-182,-496,-156,-816,580,-533;719,-38,416,580,610,118;62,-438,41,-533,118,-910],[-646,-187,760,489,-95,91;-187,-112,-162,-729,-435,-220;760,-162,-249,197,65,180;489,-729,197,-196,-9,250;-95,-435,65,-9,245,520;91,-220,180,250,520,682],[368,-508,-170,198,508,-43;-508,-900,203,-730,-33,-499;-170,203,-192,-47,151,-75;198,-730,-47,82,-271,-61;508,-33,151,-271,324,737;-43,-499,-75,-61,737,417],[982,350,-168,63,808,-314;350,372,-245,-844,427,-780;-168,-245,350,195,122,322;63,-844,195,-138,-112,434;808,427,122,-112,-418,460;-314,-780,322,434,460,-548],[-754,146,14,154,313,436;146,798,668,499,-626,241;14,668,-954,-68,372,386;154,499,-68,-798,619,-444;313,-626,372,619,588,-121;436,241,386,-444,-121,-831],[-822,-100,-182,39,-913,-73;-100,-374,-379,-64,254,-58;-182,-379,-974,-473,-71,-805;39,-64,-473,-169,335,-471;-913,254,-71,335,320,-419;-73,-58,-805,-471,-419,-161],[-649,-296,877,-659,-394,522;-296,804,-65,456,87,-811;877,-65,931,365,284,113;-659,456,365,73,-174,184;-394,87,284,-174,920,498;522,-811,113,184,498,-483],[288,-408,-114,771,519,-372;-408,-362,-282,565,-94,-137;-114,-282,180,-813,-311,-227;771,565,-813,-306,175,-422;519,-94,-311,175,438,5;-372,-137,-227,-422,5,76],[-298,145,-880,-215,268,-450;145,390,415,-316,-284,-189;-880,415,-89,-21,615,-306;-215,-316,-21,486,576,-214;268,-284,615,576,456,258;-450,-189,-306,-214,258,132],[453,260,-81,-494,-121,164;260,-679,662,-549,-175,625;-81,662,-590,-494,144,349;-494,-549,-494,-510,144,-489;-121,-175,144,144,355,546;164,625,349,-489,546,-822],[-326,-26,-165,-218,342,-278;-26,961,-454,-298,-621,-509;-165,-454,927,-413,-84,-789;-218,-298,-413,603,478,709;342,-621,-84,478,549,-67;-278,-509,-789,709,-67,-356],[888,443,211,186,-204,-166;443,518,339,768,635,-52;211,339,626,-115,854,-179;186,768,-115,910,278,-208;-204,635,854,278,-616,663;-166,-52,-179,-208,663,-371],[13,149,-183,503,388,145;149,174,-481,287,-14,744;-183,-481,11,487,209,73;503,287,487,421,469,-933;388,-14,209,469,463,-219;145,744,73,-933,-219,945],[996,129,-245,-267,-30,-569;129,-399,-692,96,-24,70;-245,-692,508,-256,-412,-59;-267,96,-256,-3,286,-96;-30,-24,-412,286,-964,131;-569,70,-59,-96,131,677],[-568,492,-797,-185,-77,-181;492,-608,237,-143,488,270;-797,237,-19,834,473,-442;-185,-143,834,74,-505,714;-77,488,473,-505,-343,-615;-181,270,-442,714,-615,-168],[825,-302,-377,296,221,542;-302,166,174,-89,44,-213;-377,174,-190,195,-711,26;296,-89,195,425,388,190;221,44,-711,388,669,-69;542,-213,26,190,-69,-292],[302,-942,-32,-165,458,115;-942,-9,-21,447,-412,346;-32,-21,728,-513,-514,-422;-165,447,-513,477,390,315;458,-412,-514,390,173,-532;115,346,-422,315,-532,-499],[370,599,-62,-34,-115,57;599,319,433,423,358,-417;-62,433,-994,-74,147,-352;-34,423,-74,886,128,-472;-115,358,147,128,976,-150;57,-417,-352,-472,-150,-775],[946,-23,-247,-316,628,-800;-23,4,290,-227,-567,-930;-247,290,-403,-185,-505,162;-316,-227,-185,-181,485,2;628,-567,-505,485,603,-833;-800,-930,162,2,-833,382];[-657,218,-1,-499,774,297,-562;218,670,298,71,678,450,417;-1,298,-906,345,-505,-13,146;-499,71,345,-163,-45,-350,-9;774,678,-505,-45,464,68,-744;297,450,-13,-350,68,883,-33;-562,417,146,-9,-744,-33,-653],[-651,277,-344,-557,-100,-5,30;277,173,742,649,426,637,138;-344,742,349,-680,182,-76,-124;-557,649,-680,727,235,513,882;-100,426,182,235,252,-194,-8;-5,637,-76,513,-194,-40,-555;30,138,-124,882,-8,-555,984],[-278,169,-928,416,-189,-786,198;169,-688,123,604,-852,-286,421;-928,123,495,-55,-54,172,149;416,604,-55,156,-103,-362,215;-189,-852,-54,-103,-976,80,67;-786,-286,172,-362,80,-328,445;198,421,149,215,67,445,517],[753,310,-161,167,18,192,-314;310,-549,163,639,67,-150,664;-161,163,871,155,248,-423,194;167,639,155,589,-765,-850,-131;18,67,248,-765,-223,-49,-580;192,-150,-423,-850,-49,-803,440;-314,664,194,-131,-580,440,-791],[-898,-426,-688,-411,-129,-434,-26;-426,287,-618,-166,355,-45,-437;-688,-618,-43,-143,394,-406,-272;-411,-166,-143,-714,548,-679,-178;-129,355,394,548,792,348,291;-434,-45,-406,-679,348,338,-506;-26,-437,-272,-178,291,-506,-872],[-669,-536,-125,567,-808,511,-118;-536,197,84,-11,-443,627,-430;-125,84,286,499,-314,9,-34;567,-11,499,-476,11,-699,-53;-808,-443,-314,11,935,18,261;511,627,9,-699,18,634,11;-118,-430,-34,-53,261,11,-169],[-379,96,11,-80,-343,-385,-744;96,681,62,-343,-10,-240,-9;11,62,-642,-767,183,-421,-800;-80,-343,-767,-259,73,-665,-382;-343,-10,183,73,761,-111,-300;-385,-240,-421,-665,-111,195,-170;-744,-9,-800,-382,-300,-170,662],[876,196,80,-115,-372,220,206;196,343,477,60,-128,751,-298;80,477,256,433,496,-477,143;-115,60,433,522,345,-800,338;-372,-128,496,345,-362,86,575;220,751,-477,-800,86,697,123;206,-298,143,338,575,123,-616],[-205,-318,175,-27,-488,270,-295;-318,-753,-278,-529,199,-352,787;175,-278,-968,-412,450,198,602;-27,-529,-412,778,285,-105,941;-488,199,450,285,455,-842,-66;270,-352,198,-105,-842,380,-103;-295,787,602,941,-66,-103,-790],[-462,-521,403,76,-219,-161,-546;-521,-472,179,-303,552,606,-494;403,179,-991,-245,514,337,133;76,-303,-245,-514,87,-233,31;-219,552,514,87,561,151,462;-161,606,337,-233,151,-74,16;-546,-494,133,31,462,16,-631],[505,53,-114,-406,664,319,-243;53,-983,-393,166,-180,-68,-172;-114,-393,-995,-463,-266,127,-821;-406,166,-463,262,13,36,150;664,-180,-266,13,423,42,-635;319,-68,127,36,42,968,480;-243,-172,-821,150,-635,480,-782],[302,-223,276,-96,85,-138,-263;-223,-793,-501,-293,422,529,382;276,-501,-943,207,514,-70,771;-96,-293,207,586,11,338,756;85,422,514,11,120,-390,411;-138,529,-70,338,-390,-419,302;-263,382,771,756,411,302,481],[335,-465,13,-133,-195,16,593;-465,-737,108,-543,-28,-65,-2;13,108,-416,881,-60,863,225;-133,-543,881,-122,-191,-803,463;-195,-28,-60,-191,69,190,312;16,-65,863,-803,190,-573,-331;593,-2,225,463,312,-331,561],[557,-886,-442,139,-237,575,-334;-886,-165,-99,-578,-587,250,123;-442,-99,20,-206,398,-509,-613;139,-578,-206,696,-250,476,52;-237,-587,398,-250,543,-176,742;575,250,-509,476,-176,-668,162;-334,123,-613,52,742,162,-72],[-256,738,-236,-81,521,512,-67;738,300,67,62,-520,34,235;-236,67,780,-469,140,-228,-247;-81,62,-469,-822,502,649,-368;521,-520,140,502,333,-809,84;512,34,-228,649,-809,-75,657;-67,235,-247,-368,84,657,483],[254,-269,69,341,-754,473,147;-269,660,-699,-134,-24,-67,-45;69,-699,35,-307,-16,-47,-528;341,-134,-307,438,342,-610,-74;-754,-24,-16,342,526,-721,646;473,-67,-47,-610,-721,-454,127;147,-45,-528,-74,646,127,-659],[-407,581,-416,67,66,-379,187;581,633,417,225,-352,62,-64;-416,417,85,-214,722,488,518;67,225,-214,-15,95,265,-36;66,-352,722,95,709,98,-614;-379,62,488,265,98,977,-111;187,-64,518,-36,-614,-111,-144],[168,-149,226,-257,-324,-242,256;-149,-395,-559,7,-415,305,667;226,-559,-737,263,-112,-876,431;-257,7,263,-693,-145,436,617;-324,-415,-112,-145,-8,848,-685;-242,305,-876,436,848,-331,-33;256,667,431,617,-685,-33,781],[-493,150,-108,-195,-30,-562,-557;150,-58,-320,79,-129,-456,191;-108,-320,82,441,-625,151,-112;-195,79,441,625,505,134,188;-30,-129,-625,505,113,788,-446;-562,-456,151,134,788,931,52;-557,191,-112,188,-446,52,-693],[-257,20,262,-274,5,446,-284;20,734,-134,-390,-164,378,335;262,-134,990,643,-3,411,-69;-274,-390,643,398,612,218,-65;5,-164,-3,612,443,634,-337;446,378,411,218,634,200,-841;-284,335,-69,-65,-337,-841,340],[-414,-84,167,142,7,298,-197;-84,-576,795,356,596,289,368;167,795,-594,250,428,-7,44;142,356,250,-481,-357,527,-336;7,596,428,-357,-906,-321,140;298,289,-7,527,-321,804,408;-197,368,44,-336,140,408,668],[35,557,-451,383,189,-443,-533;557,832,995,177,-357,273,139;-451,995,-184,442,40,-357,348;383,177,442,226,-487,-215,-284;189,-357,40,-487,398,-83,151;-443,273,-357,-215,-83,-241,-542;-533,139,348,-284,151,-542,831],[956,-222,-121,-224,-8,-422,-439;-222,965,799,-60,127,808,-458;-121,799,548,-769,25,-235,42;-224,-60,-769,-396,350,-309,433;-8,127,25,350,879,276,339;-422,808,-235,-309,276,-39,-29;-439,-458,42,433,339,-29,-717],[-747,583,508,-311,-22,-100,-176;583,558,777,487,25,626,-218;508,777,446,33,-254,-526,-197;-311,487,33,-865,942,-591,-153;-22,25,-254,942,-566,-310,192;-100,626,-526,-591,-310,750,59;-176,-218,-197,-153,192,59,-920],[667,-531,-248,620,-72,-156,-279;-531,665,-153,-237,-231,91,265;-248,-153,-1,306,-352,-492,202;620,-237,306,-891,-340,1,618;-72,-231,-352,-340,779,68,764;-156,91,-492,1,68,137,33;-279,265,202,618,764,33,653],[386,163,-387,-254,-208,-40,737;163,-296,-546,225,-17,99,-15;-387,-546,571,-72,-895,-100,291;-254,225,-72,-195,-222,478,-592;-208,-17,-895,-222,318,-708,-336;-40,99,-100,478,-708,-883,-148;737,-15,291,-592,-336,-148,-698],[431,-211,-112,160,-3,841,366;-211,198,79,-453,-183,223,183;-112,79,243,-204,480,168,-648;160,-453,-204,169,-80,-52,-341;-3,-183,480,-80,-577,274,55;841,223,168,-52,274,-702,-478;366,183,-648,-341,55,-478,928],[431,21,-4,646,197,366,-363;21,48,904,207,-20,476,597;-4,904,-660,754,211,347,407;646,207,754,-647,-10,-39,387;197,-20,211,-10,726,-372,2;366,476,347,-39,-372,-308,274;-363,597,407,387,2,274,77],[709,192,222,174,-105,-173,364;192,-471,-174,-116,-107,338,-4;222,-174,-911,256,118,-443,412;174,-116,256,781,249,-525,-98;-105,-107,118,249,-658,-81,-154;-173,338,-443,-525,-81,854,719;364,-4,412,-98,-154,719,739],[708,-639,135,400,-524,462,384;-639,-711,90,-302,-496,858,-220;135,90,929,324,212,876,-833;400,-302,324,525,335,-20,-493;-524,-496,212,335,67,491,399;462,858,876,-20,491,640,249;384,-220,-833,-493,399,249,421],[-365,216,-176,275,9,-248,-76;216,459,-334,167,121,427,255;-176,-334,-151,146,-879,-846,-181;275,167,146,-387,-162,149,24;9,121,-879,-162,402,768,560;-248,427,-846,149,768,-290,-195;-76,255,-181,24,560,-195,-123],[-225,283,143,-512,790,-529,-203;283,-405,91,328,236,451,-197;143,91,707,294,-156,-39,413;-512,328,294,-517,641,-27,630;790,236,-156,641,892,474,-414;-529,451,-39,-27,474,494,728;-203,-197,413,630,-414,728,445],[293,247,547,-187,-63,-225,-510;247,525,-182,861,-350,482,515;547,-182,-140,-139,-91,-749,303;-187,861,-139,-856,-402,-307,-198;-63,-350,-91,-402,-432,-406,-440;-225,482,-749,-307,-406,665,-243;-510,515,303,-198,-440,-243,313],[431,282,150,482,-570,-252,294;282,224,240,90,-700,-554,-81;150,240,-516,-74,62,373,328;482,90,-74,-313,189,-54,-730;-570,-700,62,189,402,-26,-282;-252,-554,373,-54,-26,-709,-683;294,-81,328,-730,-282,-683,110],[-174,143,517,614,-145,-362,-519;143,741,383,-381,22,-514,-678;517,383,849,-409,-496,-56,497;614,-381,-409,659,-347,340,736;-145,22,-496,-347,526,296,137;-362,-514,-56,340,296,648,95;-519,-678,497,736,137,95,-934],[318,-645,275,-730,-326,633,107;-645,-247,-156,-53,116,-511,-162;275,-156,-630,-570,262,-343,526;-730,-53,-570,-631,690,329,-312;-326,116,262,690,-455,-207,-152;633,-511,-343,329,-207,-711,-496;107,-162,526,-312,-152,-496,-417],[-101,-812,-33,66,-774,363,378;-812,681,-71,-263,-128,747,547;-33,-71,641,531,613,-531,-99;66,-263,531,579,167,-450,0;-774,-128,613,167,638,-645,-153;363,747,-531,-450,-645,304,-43;378,547,-99,0,-153,-43,408],[-386,189,698,382,-278,-611,609;189,-601,2,-478,344,261,301;698,2,710,-587,-393,-304,255;382,-478,-587,98,-652,-87,87;-278,344,-393,-652,-788,-168,-508;-611,261,-304,-87,-168,792,-22;609,301,255,87,-508,-22,672],[1,-104,-86,40,-647,816,-352;-104,406,-81,-537,493,80,-435;-86,-81,-284,-66,554,-623,680;40,-537,-66,-356,29,-443,248;-647,493,554,29,746,138,685;816,80,-623,-443,138,424,34;-352,-435,680,248,685,34,922],[-682,-50,318,-106,241,743,-780;-50,926,20,385,-582,626,237;318,20,-374,-88,-69,-122,-824;-106,385,-88,-49,-469,390,398;241,-582,-69,-469,-978,-624,-206;743,626,-122,390,-624,557,538;-780,237,-824,398,-206,538,868],[-910,-842,182,171,273,-403,17;-842,737,478,-363,723,319,-225;182,478,99,507,-469,54,-186;171,-363,507,427,-128,271,-239;273,723,-469,-128,-682,-455,-389;-403,319,54,271,-455,712,-162;17,-225,-186,-239,-389,-162,892],[-364,164,-488,-562,-12,-482,416;164,652,-86,436,180,-102,20;-488,-86,-351,-471,-252,346,250;-562,436,-471,758,516,-14,163;-12,180,-252,516,204,-524,-219;-482,-102,346,-14,-524,306,101;416,20,250,163,-219,101,-523],[-916,-771,265,-35,-501,783,587;-771,-632,15,187,687,-308,-32;265,15,103,-346,-254,91,89;-35,187,-346,707,-63,14,436;-501,687,-254,-63,440,-502,-91;783,-308,91,14,-502,405,-182;587,-32,89,436,-91,-182,-450],[-53,-809,-515,-200,44,-145,326;-809,-948,512,-124,-898,-316,322;-515,512,936,153,-148,-146,206;-200,-124,153,959,-152,-321,7;44,-898,-148,-152,71,-76,-786;-145,-316,-146,-321,-76,817,-700;326,322,206,7,-786,-700,-662],[-302,67,-462,263,105,8,292;67,327,-823,-42,-113,527,30;-462,-823,417,55,860,-10,425;263,-42,55,173,281,-394,122;105,-113,860,281,-854,-221,-99;8,527,-10,-394,-221,227,-182;292,30,425,122,-99,-182,-346],[-119,795,-290,-384,121,-469,430;795,-552,645,-722,-394,-170,51;-290,645,600,-222,12,-297,117;-384,-722,-222,-454,-223,-475,-789;121,-394,12,-223,-411,321,529;-469,-170,-297,-475,321,-873,182;430,51,117,-789,529,182,-349],[117,509,-692,-458,-347,-602,203;509,279,-346,393,-879,798,-496;-692,-346,-973,97,-705,-283,62;-458,393,97,-21,-167,-709,-206;-347,-879,-705,-167,-400,-300,-501;-602,798,-283,-709,-300,-803,-620;203,-496,62,-206,-501,-620,920],[975,303,-34,653,-515,-128,-160;303,-703,-62,-749,-24,-40,-108;-34,-62,-391,-85,254,-713,-443;653,-749,-85,597,298,-433,-134;-515,-24,254,298,-460,738,375;-128,-40,-713,-433,738,312,487;-160,-108,-443,-134,375,487,-620],[-981,789,214,562,462,-166,172;789,-829,323,554,-240,35,-524;214,323,491,-355,881,-401,74;562,554,-355,639,-211,10,80;462,-240,881,-211,-383,-868,100;-166,35,-401,10,-868,-229,-605;172,-524,74,80,100,-605,-209],[429,863,-528,200,-44,-239,687;863,-427,684,-810,364,101,-64;-528,684,-196,102,247,-284,-142;200,-810,102,-89,-719,-163,137;-44,364,247,-719,775,-524,247;-239,101,-284,-163,-524,-630,37;687,-64,-142,137,247,37,766],[442,-92,461,-146,-273,75,326;-92,721,243,-13,-137,49,325;461,243,-944,-341,-654,63,-261;-146,-13,-341,-232,-147,518,-381;-273,-137,-654,-147,-976,366,-674;75,49,63,518,366,835,584;326,325,-261,-381,-674,584,-946],[458,294,-391,31,-493,233,-911;294,-262,327,-369,388,-85,-94;-391,327,491,-2,275,45,-40;31,-369,-2,-769,-802,-38,108;-493,388,275,-802,65,-592,706;233,-85,45,-38,-592,696,-294;-911,-94,-40,108,706,-294,419],[991,340,-589,-442,-22,210,897;340,258,-15,-71,-366,29,-201;-589,-15,-888,148,149,-278,246;-442,-71,148,-834,-182,-161,-222;-22,-366,149,-182,-625,-676,111;210,29,-278,-161,-676,38,342;897,-201,246,-222,111,342,798],[736,29,739,-519,-41,174,-774;29,-184,24,-309,826,9,-527;739,24,135,-420,306,589,353;-519,-309,-420,-441,-63,-146,-272;-41,826,306,-63,-953,-569,-297;174,9,589,-146,-569,652,-511;-774,-527,353,-272,-297,-511,-479],[-109,587,6,96,377,-33,-97;587,-609,-191,364,-276,-540,-52;6,-191,500,-21,158,-698,249;96,364,-21,746,-2,-430,-804;377,-276,158,-2,498,-389,626;-33,-540,-698,-430,-389,968,-594;-97,-52,249,-804,626,-594,216],[-571,-349,-384,108,271,604,-1;-349,-949,-190,-891,-93,-143,173;-384,-190,652,-74,-346,-159,618;108,-891,-74,-925,-782,-1,345;271,-93,-346,-782,-244,496,485;604,-143,-159,-1,496,724,166;-1,173,618,345,485,166,604],[-613,73,540,200,372,355,166;73,-962,190,-582,-117,-596,393;540,190,155,18,-327,-89,762;200,-582,18,805,-3,529,-308;372,-117,-327,-3,-604,-88,-450;355,-596,-89,529,-88,679,-111;166,393,762,-308,-450,-111,-247],[330,524,-107,-556,-84,57,783;524,663,-148,373,685,-204,405;-107,-148,-216,104,-264,471,51;-556,373,104,-862,97,-167,-661;-84,685,-264,97,261,745,-393;57,-204,471,-167,745,785,54;783,405,51,-661,-393,54,436],[977,-115,278,768,-817,-844,183;-115,287,178,-402,-558,-397,-558;278,178,-402,123,-708,158,-99;768,-402,123,140,-676,245,-9;-817,-558,-708,-676,985,228,187;-844,-397,158,245,228,-950,129;183,-558,-99,-9,187,129,-905],[-418,19,223,349,-143,561,784;19,200,-698,444,18,633,39;223,-698,-923,-365,419,-71,-104;349,444,-365,-116,64,-278,348;-143,18,419,64,-115,-772,526;561,633,-71,-278,-772,-62,360;784,39,-104,348,526,360,495],[-996,-141,409,84,635,-241,327;-141,607,111,-622,154,-49,-450;409,111,-233,-522,114,-388,-35;84,-622,-522,-496,-648,-210,-180;635,154,114,-648,178,-530,-75;-241,-49,-388,-210,-530,-505,-88;327,-450,-35,-180,-75,-88,505],[-505,-167,448,452,616,-300,473;-167,978,237,580,-364,334,104;448,237,948,74,-536,-860,-344;452,580,74,926,-758,31,581;616,-364,-536,-758,-472,-269,300;-300,334,-860,31,-269,464,-374;473,104,-344,581,300,-374,536],[-924,506,-147,-140,841,-163,-94;506,899,168,-373,-132,-214,618;-147,168,701,-230,-200,100,-632;-140,-373,-230,-86,122,-541,-169;841,-132,-200,122,815,874,-462;-163,-214,100,-541,874,521,521;-94,618,-632,-169,-462,521,998],[960,-103,392,192,-61,280,-369;-103,122,-804,-260,-197,314,76;392,-804,348,161,568,-213,10;192,-260,161,634,166,-222,738;-61,-197,568,166,574,179,-130;280,314,-213,-222,179,354,-241;-369,76,10,738,-130,-241,754],[844,283,407,-361,-784,-629,-443;283,895,-741,377,552,545,-356;407,-741,-446,713,-37,-642,-95;-361,377,713,-706,-509,790,-129;-784,552,-37,-509,929,-216,831;-629,545,-642,790,-216,-381,126;-443,-356,-95,-129,831,126,864],[-44,-613,-265,-59,-454,86,-523;-613,695,-185,100,70,-185,261;-265,-185,516,-915,-514,-305,-183;-59,100,-915,-479,673,-599,9;-454,70,-514,673,-97,147,443;86,-185,-305,-599,147,-52,171;-523,261,-183,9,443,171,40],[615,-292,734,37,350,511,-512;-292,394,773,-557,158,-754,212;734,773,466,406,412,519,-125;37,-557,406,964,117,-569,99;350,158,412,117,-131,-741,134;511,-754,519,-569,-741,-996,32;-512,212,-125,99,134,32,34],[-355,-682,-504,-263,483,226,392;-682,-581,45,142,631,-117,-233;-504,45,334,327,765,-196,-286;-263,142,327,-785,367,98,-324;483,631,765,367,482,-40,468;226,-117,-196,98,-40,151,495;392,-233,-286,-324,468,495,-171],[-691,-179,-303,319,211,-212,59;-179,-148,-340,-622,-170,332,323;-303,-340,-233,52,734,-50,-470;319,-622,52,-522,-204,344,-554;211,-170,734,-204,753,37,133;-212,332,-50,344,37,704,260;59,323,-470,-554,133,260,-214],[-430,244,-408,98,568,-419,-263;244,-498,-523,854,-242,436,573;-408,-523,761,-390,554,-762,-188;98,854,-390,526,196,-723,-193;568,-242,554,196,-930,-118,-299;-419,436,-762,-723,-118,-244,409;-263,573,-188,-193,-299,409,-954],[-735,487,539,-167,200,167,212;487,-195,356,-722,-42,338,77;539,356,37,-497,723,-74,388;-167,-722,-497,-702,-357,-134,-83;200,-42,723,-357,-229,-666,547;167,338,-74,-134,-666,482,-26;212,77,388,-83,547,-26,-699],[-560,-459,8,-566,424,-163,266;-459,40,251,-484,847,-77,-806;8,251,-120,431,23,-32,-17;-566,-484,431,114,-392,-411,-456;424,847,23,-392,492,-92,-128;-163,-77,-32,-411,-92,-644,47;266,-806,-17,-456,-128,47,-358],[-616,38,400,782,-451,-560,243;38,641,-945,-72,-426,-80,-308;400,-945,493,161,150,652,-130;782,-72,161,-182,-392,99,236;-451,-426,150,-392,-164,-7,155;-560,-80,652,99,-7,114,-744;243,-308,-130,236,155,-744,558],[-987,-215,49,-444,-384,-381,-367;-215,-468,61,-421,541,86,432;49,61,21,-308,862,-435,239;-444,-421,-308,-762,-189,62,-520;-384,541,862,-189,33,-358,-566;-381,86,-435,62,-358,-652,504;-367,432,239,-520,-566,504,223],[122,769,689,-167,-441,471,-585;769,217,-172,-209,-408,-284,370;689,-172,-762,714,380,131,-200;-167,-209,714,228,-157,153,-664;-441,-408,380,-157,70,476,-347;471,-284,131,153,476,-505,-284;-585,370,-200,-664,-347,-284,-925],[-435,-265,190,-229,366,212,-510;-265,972,-244,142,-542,304,-272;190,-244,492,-69,-610,555,-292;-229,142,-69,110,-380,-179,-362;366,-542,-610,-380,-600,-228,-80;212,304,555,-179,-228,-465,-65;-510,-272,-292,-362,-80,-65,-722],[-177,-233,784,85,183,-223,-84;-233,817,78,344,391,559,-496;784,78,839,224,330,371,230;85,344,224,-278,412,-272,197;183,391,330,412,639,-809,-132;-223,559,371,-272,-809,109,454;-84,-496,230,197,-132,454,-8],[466,393,20,79,-620,-613,-319;393,48,32,520,13,38,-394;20,32,-607,-369,-263,-144,701;79,520,-369,-666,399,-87,536;-620,13,-263,399,-198,640,-619;-613,38,-144,-87,640,-184,751;-319,-394,701,536,-619,751,-506],[-102,-407,-405,-138,-542,-43,669;-407,955,-156,256,-752,-475,-266;-405,-156,759,54,272,-562,123;-138,256,54,555,-155,-458,520;-542,-752,272,-155,432,678,-187;-43,-475,-562,-458,678,-679,863;669,-266,123,520,-187,863,999],[336,672,-224,-42,-744,803,26;672,-74,-277,402,-180,-131,-288;-224,-277,28,-862,-359,-183,-623;-42,402,-862,-49,-396,-288,-147;-744,-180,-359,-396,-399,401,425;803,-131,-183,-288,401,-523,402;26,-288,-623,-147,425,402,671],[343,302,451,869,-728,461,469;302,-479,-552,-94,99,335,343;451,-552,123,137,-22,-150,371;869,-94,137,-567,29,107,749;-728,99,-22,29,-921,126,78;461,335,-150,107,126,-967,774;469,343,371,749,78,774,-392],[304,146,-18,-752,-8,-481,-790;146,133,175,113,212,-370,-62;-18,175,-586,-334,-677,353,-505;-752,113,-334,-440,-592,431,180;-8,212,-677,-592,79,282,350;-481,-370,353,431,282,569,262;-790,-62,-505,180,350,262,725],[-892,304,-153,-826,-17,209,-21;304,-228,-16,751,167,590,495;-153,-16,339,94,-287,-176,-335;-826,751,94,759,-44,338,-62;-17,167,-287,-44,823,-262,72;209,590,-176,338,-262,166,-551;-21,495,-335,-62,72,-551,267],[858,408,-336,620,83,95,247;408,-973,229,-540,326,126,153;-336,229,379,-102,-37,-334,-233;620,-540,-102,51,-72,-782,372;83,326,-37,-72,778,-571,863;95,126,-334,-782,-571,884,101;247,153,-233,372,863,101,292],[805,581,525,-453,374,-453,64;581,665,155,36,-90,357,-181;525,155,-944,691,-432,-147,-299;-453,36,691,-785,-199,514,-43;374,-90,-432,-199,-278,-559,-390;-453,357,-147,514,-559,501,-89;64,-181,-299,-43,-390,-89,821],[-217,-496,-326,151,715,-222,58;-496,-627,281,-323,-691,-42,20;-326,281,754,-327,269,61,-702;151,-323,-327,418,544,349,-7;715,-691,269,544,-52,-146,-94;-222,-42,61,349,-146,23,656;58,20,-702,-7,-94,656,416],[258,-267,-600,-364,-541,52,-36;-267,-964,-55,343,-169,-401,-160;-600,-55,962,143,-364,136,231;-364,343,143,-814,-149,83,547;-541,-169,-364,-149,-297,441,-664;52,-401,136,83,441,-648,125;-36,-160,231,547,-664,125,-186],[708,-24,600,480,556,-701,628;-24,498,-49,-41,94,-69,407;600,-49,-836,281,641,-636,-372;480,-41,281,173,-193,18,351;556,94,641,-193,-414,-33,59;-701,-69,-636,18,-33,58,-212;628,407,-372,351,59,-212,838],[404,379,-164,490,-372,-323,-178;379,121,-352,-507,-379,-58,-253;-164,-352,936,760,534,-648,463;490,-507,760,540,-221,-193,-283;-372,-379,534,-221,965,114,-500;-323,-58,-648,-193,114,588,516;-178,-253,463,-283,-500,516,133],[-274,-8,774,69,632,746,-742;-8,550,834,-903,291,-438,-107;774,834,902,-160,-580,423,-143;69,-903,-160,852,453,216,-372;632,291,-580,453,562,211,56;746,-438,423,216,211,288,-255;-742,-107,-143,-372,56,-255,381],[29,-608,-241,-79,639,-259,44;-608,-80,727,279,150,-707,11;-241,727,-964,-562,-228,271,299;-79,279,-562,233,-245,-250,-16;639,150,-228,-245,208,-249,566;-259,-707,271,-250,-249,-498,342;44,11,299,-16,566,342,502],[-372,69,-132,48,802,42,-573;69,349,-147,702,-346,177,-132;-132,-147,-588,-729,-253,211,373;48,702,-729,-885,994,206,-391;802,-346,-253,994,-654,286,-125;42,177,211,206,286,-412,5;-573,-132,373,-391,-125,5,917],[857,-510,115,216,-52,263,11;-510,906,25,-444,-200,801,-659;115,25,832,493,-543,-283,-80;216,-444,493,-723,-89,-383,-48;-52,-200,-543,-89,228,641,179;263,801,-283,-383,641,-984,390;11,-659,-80,-48,179,390,314],[-786,-107,592,-837,329,-489,-279;-107,326,699,517,-347,109,-273;592,699,852,366,499,16,-329;-837,517,366,939,-584,-909,494;329,-347,499,-584,-172,-535,-62;-489,109,16,-909,-535,-147,223;-279,-273,-329,494,-62,223,442],[-529,-343,-828,-312,-108,143,-370;-343,583,-181,167,-353,654,490;-828,-181,586,334,-153,-633,214;-312,167,334,538,635,-73,-251;-108,-353,-153,635,338,-2,-38;143,654,-633,-73,-2,732,543;-370,490,214,-251,-38,543,-691],[-791,-269,-24,310,42,44,-620;-269,64,-128,341,635,482,-346;-24,-128,-745,451,-170,232,-236;310,341,451,403,466,-26,-684;42,635,-170,466,-274,510,-103;44,482,232,-26,510,35,-232;-620,-346,-236,-684,-103,-232,736],[-410,-80,172,-425,205,677,232;-80,373,214,214,-24,232,-602;172,214,771,493,250,-99,546;-425,214,493,881,-773,-465,-210;205,-24,250,-773,-858,231,664;677,232,-99,-465,231,337,-335;232,-602,546,-210,664,-335,-405],[268,-65,-243,164,-411,352,-74;-65,-70,-191,22,81,89,508;-243,-191,-211,140,-200,-766,687;164,22,140,572,30,-779,441;-411,81,-200,30,-903,-329,510;352,89,-766,-779,-329,276,352;-74,508,687,441,510,352,-884],[183,-42,-185,-223,389,-71,312;-42,365,387,-828,-348,91,-815;-185,387,-561,484,-238,-10,374;-223,-828,484,-835,383,2,397;389,-348,-238,383,-852,-936,152;-71,91,-10,2,-936,834,-652;312,-815,374,397,152,-652,-485],[577,44,346,411,287,817,385;44,293,-391,67,455,-125,-706;346,-391,-393,690,600,-139,601;411,67,690,-29,112,301,-324;287,455,600,112,431,296,-877;817,-125,-139,301,296,-373,255;385,-706,601,-324,-877,255,-210];[808,-278,875,-231,-399,765,-565,50;-278,221,592,-213,177,-142,857,-69;875,592,-413,56,-105,-81,-184,406;-231,-213,56,-429,-157,175,484,135;-399,177,-105,-157,997,663,302,59;765,-142,-81,175,663,-39,137,106;-565,857,-184,484,302,137,-521,-252;50,-69,406,135,59,106,-252,399],[161,157,43,-345,453,649,77,-136;157,-768,194,-548,480,-97,-710,-429;43,194,-445,490,285,-678,923,637;-345,-548,490,215,271,-107,926,102;453,480,285,271,739,-373,-185,-466;649,-97,-678,-107,-373,755,464,-453;77,-710,923,926,-185,464,-617,-261;-136,-429,637,102,-466,-453,-261,-779],[743,-327,77,563,9,-897,132,362;-327,-673,511,210,-354,-168,-545,301;77,511,514,525,-511,-457,122,-456;563,210,525,236,132,29,199,266;9,-354,-511,132,94,158,286,-78;-897,-168,-457,29,158,738,10,-492;132,-545,122,199,286,10,242,-381;362,301,-456,266,-78,-492,-381,767],[551,505,-571,261,236,-131,341,85;505,641,-277,-294,298,-125,11,271;-571,-277,416,390,-95,-423,166,-278;261,-294,390,-219,-483,582,476,-175;236,298,-95,-483,736,-212,209,49;-131,-125,-423,582,-212,-712,-294,110;341,11,166,476,209,-294,-524,-50;85,271,-278,-175,49,110,-50,-539],[475,359,-523,-420,609,-527,-78,-101;359,953,646,-263,-266,-137,5,307;-523,646,348,289,453,-535,-289,-657;-420,-263,289,963,-124,-118,-1,-70;609,-266,453,-124,-338,470,831,300;-527,-137,-535,-118,470,-970,226,517;-78,5,-289,-1,831,226,-634,404;-101,307,-657,-70,300,517,404,366],[980,164,-93,192,119,-740,245,657;164,844,-4,-506,111,284,-440,-335;-93,-4,474,41,7,583,308,434;192,-506,41,52,-17,477,-103,147;119,111,7,-17,3,-449,-606,-38;-740,284,583,477,-449,288,186,-168;245,-440,308,-103,-606,186,588,-283;657,-335,434,147,-38,-168,-283,-608],[702,374,72,726,26,-251,-277,-646;374,-197,772,48,42,-921,-95,183;72,772,-944,671,685,-164,-307,-742;726,48,671,212,86,57,173,606;26,42,685,86,-552,-80,-561,-73;-251,-921,-164,57,-80,72,497,195;-277,-95,-307,173,-561,497,-715,-35;-646,183,-742,606,-73,195,-35,384],[311,-486,254,208,305,101,379,-147;-486,-706,1,375,-160,249,566,-784;254,1,965,-582,-576,72,367,355;208,375,-582,-634,-189,771,-100,526;305,-160,-576,-189,766,-326,-797,366;101,249,72,771,-326,-275,-288,498;379,566,367,-100,-797,-288,-796,295;-147,-784,355,526,366,498,295,-216],[621,385,545,-215,-193,652,-102,-335;385,663,-954,337,-89,-287,-52,295;545,-954,228,-68,-319,-537,54,548;-215,337,-68,128,-189,-89,-541,578;-193,-89,-319,-189,-471,340,-24,-53;652,-287,-537,-89,340,232,201,-740;-102,-52,54,-541,-24,201,-425,-527;-335,295,548,578,-53,-740,-527,935],[-757,829,-286,395,13,484,72,535;829,-659,-621,-139,-267,-51,833,-148;-286,-621,973,-667,136,-158,-20,-334;395,-139,-667,820,-595,275,54,196;13,-267,136,-595,450,157,-109,879;484,-51,-158,275,157,797,686,22;72,833,-20,54,-109,686,209,-440;535,-148,-334,196,879,22,-440,-811],[-810,-857,-276,-493,-173,-325,372,514;-857,171,228,152,592,-219,-809,-613;-276,228,737,-440,158,-63,-17,-24;-493,152,-440,465,392,592,-11,268;-173,592,158,392,-113,158,-58,-431;-325,-219,-63,592,158,593,164,241;372,-809,-17,-11,-58,164,-75,-227;514,-613,-24,268,-431,241,-227,-207],[-320,220,-310,312,251,-597,-2,-48;220,-268,-316,-874,-290,284,-485,327;-310,-316,-550,899,-626,180,-659,263;312,-874,899,187,-23,-716,166,726;251,-290,-626,-23,-140,-255,146,-160;-597,284,180,-716,-255,-256,429,-32;-2,-485,-659,166,146,429,717,38;-48,327,263,726,-160,-32,38,-834],[-26,222,-112,-333,-202,214,90,-711;222,436,-141,344,-370,108,-703,-562;-112,-141,494,-214,11,-781,-221,231;-333,344,-214,865,175,-617,-41,414;-202,-370,11,175,569,182,-413,-311;214,108,-781,-617,182,-617,409,-260;90,-703,-221,-41,-413,409,209,-42;-711,-562,231,414,-311,-260,-42,481],[-564,30,35,-156,437,-180,-133,-249;30,-287,-632,-442,-332,631,-502,-67;35,-632,-917,-31,-191,495,-541,-644;-156,-442,-31,-83,312,-212,116,192;437,-332,-191,312,-299,-112,-316,232;-180,631,495,-212,-112,264,226,-87;-133,-502,-541,116,-316,226,754,-95;-249,-67,-644,192,232,-87,-95,598],[-912,-37,407,599,368,434,324,26;-37,-10,-78,-400,-21,187,-151,603;407,-78,-198,817,111,-796,859,-436;599,-400,817,968,-805,154,-479,592;368,-21,111,-805,-57,-376,-632,-17;434,187,-796,154,-376,743,369,280;324,-151,859,-479,-632,369,-851,658;26,603,-436,592,-17,280,658,-803],[-211,212,428,-720,-651,188,708,-289;212,-780,-18,-345,265,194,-487,48;428,-18,-501,38,343,685,285,25;-720,-345,38,744,244,519,672,425;-651,265,343,244,941,-318,-56,-181;188,194,685,519,-318,12,-413,161;708,-487,285,672,-56,-413,276,-549;-289,48,25,425,-181,161,-549,604],[-262,150,242,-310,314,-665,312,805;150,-403,-540,80,-676,-607,128,-249;242,-540,-208,-712,-542,-247,358,147;-310,80,-712,-127,337,-608,-614,579;314,-676,-542,337,545,-175,-746,-36;-665,-607,-247,-608,-175,-653,74,245;312,128,358,-614,-746,74,-934,564;805,-249,147,579,-36,245,564,86],[-621,172,354,106,936,-47,258,-305;172,-331,95,-233,-331,445,-542,40;354,95,-677,117,-16,-298,162,247;106,-233,117,372,367,-647,-232,-136;936,-331,-16,367,523,274,375,8;-47,445,-298,-647,274,707,-765,291;258,-542,162,-232,375,-765,36,-485;-305,40,247,-136,8,291,-485,-453],[845,-105,-231,350,329,-442,755,132;-105,399,674,634,123,34,-145,94;-231,674,-531,427,170,683,-181,-350;350,634,427,439,450,333,654,65;329,123,170,450,27,209,373,-483;-442,34,683,333,209,359,808,-578;755,-145,-181,654,373,808,235,-349;132,94,-350,65,-483,-578,-349,353],[-54,-425,166,21,458,-478,-71,-682;-425,837,-567,179,-231,166,-555,-1;166,-567,572,71,329,-143,132,-98;21,179,71,766,447,548,-249,-499;458,-231,329,447,-82,-770,-182,-82;-478,166,-143,548,-770,-679,303,55;-71,-555,132,-249,-182,303,-210,-606;-682,-1,-98,-499,-82,55,-606,-368],[-721,246,-538,945,-96,391,-352,-225;246,-99,-25,127,-123,-252,421,-586;-538,-25,836,-549,-188,242,-514,-467;945,127,-549,-67,-54,-308,-641,-797;-96,-123,-188,-54,690,-45,498,393;391,-252,242,-308,-45,233,728,-371;-352,421,-514,-641,498,728,323,-365;-225,-586,-467,-797,393,-371,-365,728],[-585,-371,752,-334,482,193,-119,-166;-371,-666,736,37,-634,575,65,-174;752,736,893,938,124,325,-414,233;-334,37,938,-467,62,-672,100,416;482,-634,124,62,19,-618,-522,180;193,575,325,-672,-618,-131,253,120;-119,65,-414,100,-522,253,-644,-289;-166,-174,233,416,180,120,-289,598],[-834,14,-85,202,-197,503,-44,-425;14,-689,522,-656,108,-258,56,378;-85,522,-379,-334,-421,540,-321,-436;202,-656,-334,521,-642,475,228,-493;-197,108,-421,-642,-881,-119,-114,177;503,-258,540,475,-119,-137,-41,-60;-44,56,-321,228,-114,-41,432,141;-425,378,-436,-493,177,-60,141,759],[-177,-670,-708,580,-790,-437,-319,-249;-670,173,836,-376,-175,52,366,163;-708,836,-848,-301,-568,384,-254,-718;580,-376,-301,892,-36,310,110,-594;-790,-175,-568,-36,-118,-368,-4,-50;-437,52,384,310,-368,-714,19,-852;-319,366,-254,110,-4,19,2,-241;-249,163,-718,-594,-50,-852,-241,8],[-188,-684,-298,581,626,-102,640,-271;-684,-286,-288,6,563,375,-501,454;-298,-288,-904,-198,816,454,-228,-953;581,6,-198,-901,369,393,169,-407;626,563,816,369,-598,53,-48,223;-102,375,454,393,53,-426,-349,3;640,-501,-228,169,-48,-349,-775,91;-271,454,-953,-407,223,3,91,469],[-406,180,601,-134,-338,-95,63,-351;180,932,-550,469,-303,-40,61,657;601,-550,-144,32,-116,-137,-494,-200;-134,469,32,-249,-351,-722,47,-786;-338,-303,-116,-351,811,238,108,-360;-95,-40,-137,-722,238,905,-138,729;63,61,-494,47,108,-138,-307,-188;-351,657,-200,-786,-360,729,-188,-372],[-301,-656,-404,122,-19,-420,519,32;-656,597,-843,358,-870,-408,-391,-86;-404,-843,489,47,384,-497,260,-724;122,358,47,-27,-191,369,-31,261;-19,-870,384,-191,-545,-383,-707,59;-420,-408,-497,369,-383,-550,514,-45;519,-391,260,-31,-707,514,654,-187;32,-86,-724,261,59,-45,-187,-161],[-353,-129,579,82,195,1,272,-273;-129,9,195,812,-184,51,440,82;579,195,-69,-472,-465,312,104,111;82,812,-472,361,659,-204,267,-156;195,-184,-465,659,-714,62,401,868;1,51,312,-204,62,-976,-556,-353;272,440,104,267,401,-556,-326,-96;-273,82,111,-156,868,-353,-96,-597],[91,-161,609,247,729,447,479,-399;-161,209,-393,-128,-19,-315,465,436;609,-393,-513,321,366,186,423,-297;247,-128,321,-119,124,636,-287,-577;729,-19,366,124,-71,335,552,-241;447,-315,186,636,335,519,310,422;479,465,423,-287,552,310,775,366;-399,436,-297,-577,-241,422,366,-355],[864,442,244,-155,-133,-41,-487,571;442,472,-683,-97,-649,-19,-485,-208;244,-683,-671,-128,-199,-608,150,-536;-155,-97,-128,-925,85,167,-183,-527;-133,-649,-199,85,233,279,-334,135;-41,-19,-608,167,279,69,-373,0;-487,-485,150,-183,-334,-373,-106,-426;571,-208,-536,-527,135,0,-426,523],[-277,799,399,46,-158,-105,-472,-446;799,-725,-636,528,427,918,-580,-205;399,-636,340,250,-379,298,78,-671;46,528,250,856,-187,-67,428,-623;-158,427,-379,-187,-784,-648,-372,-213;-105,918,298,-67,-648,271,-176,126;-472,-580,78,428,-372,-176,-837,585;-446,-205,-671,-623,-213,126,585,-866],[384,-598,-133,-338,148,490,-16,-371;-598,-995,648,-350,342,400,-125,32;-133,648,996,505,0,-19,486,334;-338,-350,505,699,-188,238,-14,-539;148,342,0,-188,138,72,-665,-298;490,400,-19,238,72,-151,484,656;-16,-125,486,-14,-665,484,781,90;-371,32,334,-539,-298,656,90,-913],[92,-103,-494,-476,-657,645,189,167;-103,-454,650,198,-5,483,-364,151;-494,650,-948,373,-314,704,-66,-189;-476,198,373,438,325,289,-566,-82;-657,-5,-314,325,52,-318,726,-194;645,483,704,289,-318,22,-205,572;189,-364,-66,-566,726,-205,416,-656;167,151,-189,-82,-194,572,-656,48],[256,-683,-311,472,475,156,8,-81;-683,-560,272,-892,197,-847,-241,-426;-311,272,-332,240,-20,-498,-603,-791;472,-892,240,-68,-38,543,340,-54;475,197,-20,-38,-489,-220,526,-790;156,-847,-498,543,-220,404,33,-444;8,-241,-603,340,526,33,855,-374;-81,-426,-791,-54,-790,-444,-374,-140],[834,120,-67,-684,-158,287,-257,0;120,696,454,-382,221,298,-420,430;-67,454,-831,61,505,88,29,-217;-684,-382,61,723,-59,907,-77,-198;-158,221,505,-59,-790,-96,-243,-44;287,298,88,907,-96,-375,326,338;-257,-420,29,-77,-243,326,-742,542;0,430,-217,-198,-44,338,542,487],[-73,376,-251,-591,142,88,-240,-553;376,392,-586,-685,-342,62,860,219;-251,-586,-980,358,-652,-34,-337,-669;-591,-685,358,-594,66,-704,-283,-462;142,-342,-652,66,185,23,-832,-505;88,62,-34,-704,23,-48,187,363;-240,860,-337,-283,-832,187,-309,-78;-553,219,-669,-462,-505,363,-78,-382],[704,123,-420,-628,168,47,-187,-517;123,-936,335,460,-331,160,-13,300;-420,335,-344,653,525,-826,-226,-89;-628,460,653,-237,111,633,256,44;168,-331,525,111,-218,-414,-423,103;47,160,-826,633,-414,-976,254,455;-187,-13,-226,256,-423,254,726,-701;-517,300,-89,44,103,455,-701,118],[74,-582,-710,287,45,-329,81,-158;-582,483,48,-32,-267,807,-673,-380;-710,48,657,667,-217,-765,-42,921;287,-32,667,-183,-549,724,-303,-390;45,-267,-217,-549,960,295,-273,141;-329,807,-765,724,295,-575,-576,-53;81,-673,-42,-303,-273,-576,-285,-94;-158,-380,921,-390,141,-53,-94,-403],[-363,-189,12,113,-405,265,-209,-520;-189,-265,-291,-8,655,-267,803,235;12,-291,379,316,615,-94,78,148;113,-8,316,804,764,533,-529,-432;-405,655,615,764,-433,-79,-430,-441;265,-267,-94,533,-79,147,-8,-616;-209,803,78,-529,-430,-8,964,-121;-520,235,148,-432,-441,-616,-121,230],[-715,-69,-734,299,-234,696,-106,718;-69,657,-278,445,109,408,-494,-33;-734,-278,447,31,-49,8,84,356;299,445,31,-354,352,-757,34,672;-234,109,-49,352,-899,523,27,240;696,408,8,-757,523,-903,-324,-774;-106,-494,84,34,27,-324,358,-217;718,-33,356,672,240,-774,-217,527],[-583,-373,75,-445,158,99,-393,319;-373,-531,89,-168,206,-120,582,184;75,89,666,118,341,107,76,-283;-445,-168,118,870,91,47,-477,-305;158,206,341,91,-961,84,77,-237;99,-120,107,47,84,647,-663,81;-393,582,76,-477,77,-663,98,-171;319,184,-283,-305,-237,81,-171,128],[-921,-483,442,-562,500,-511,-292,248;-483,-903,107,-330,515,-219,-111,3;442,107,-303,-132,-487,19,564,830;-562,-330,-132,-18,235,-14,-436,354;500,515,-487,235,-836,97,-343,-125;-511,-219,19,-14,97,811,-63,-162;-292,-111,564,-436,-343,-63,39,100;248,3,830,354,-125,-162,100,-238],[429,75,-149,-102,567,-56,350,788;75,-27,-189,302,-275,-157,-136,319;-149,-189,475,-172,82,98,-54,-680;-102,302,-172,192,288,249,728,-21;567,-275,82,288,421,-188,-834,-563;-56,-157,98,249,-188,989,-245,661;350,-136,-54,728,-834,-245,716,-165;788,319,-680,-21,-563,661,-165,-625],[771,-671,-414,135,-676,-505,-283,-540;-671,228,755,322,-429,-87,-218,-102;-414,755,678,120,-281,-41,62,-28;135,322,120,-69,-160,158,73,-533;-676,-429,-281,-160,677,-133,-518,821;-505,-87,-41,158,-133,-701,87,164;-283,-218,62,73,-518,87,-494,-727;-540,-102,-28,-533,821,164,-727,8],[7,-57,-530,89,212,72,221,-397;-57,-984,-288,-134,-115,-237,16,-609;-530,-288,-355,-75,487,-208,320,48;89,-134,-75,-20,-223,-303,-62,-119;212,-115,487,-223,-657,-306,248,-290;72,-237,-208,-303,-306,375,-375,154;221,16,320,-62,248,-375,-568,-201;-397,-609,48,-119,-290,154,-201,-626],[-320,-26,261,617,-684,-155,-3,-251;-26,-683,-415,890,596,106,194,-555;261,-415,-11,184,106,611,159,-57;617,890,184,122,-552,755,644,-332;-684,596,106,-552,164,-389,-260,-35;-155,106,611,755,-389,90,442,196;-3,194,159,644,-260,442,7,83;-251,-555,-57,-332,-35,196,83,-862],[-115,-242,247,-150,-239,-13,340,-158;-242,889,-712,172,-772,48,37,172;247,-712,749,333,-221,-244,-206,-474;-150,172,333,36,389,374,-73,-204;-239,-772,-221,389,599,-311,36,-293;-13,48,-244,374,-311,-985,-43,-149;340,37,-206,-73,36,-43,-949,633;-158,172,-474,-204,-293,-149,633,-202],[185,390,-301,-518,11,382,285,112;390,166,-418,66,-113,-163,-552,-874;-301,-418,-736,317,-216,713,-36,-508;-518,66,317,-191,865,108,964,218;11,-113,-216,865,-994,-528,234,-54;382,-163,713,108,-528,-481,509,742;285,-552,-36,964,234,509,-181,-354;112,-874,-508,218,-54,742,-354,606],[225,-41,-323,-325,857,2,-111,852;-41,-296,-186,181,-1,77,-152,-513;-323,-186,-964,372,-599,-264,24,-232;-325,181,372,-285,22,225,-502,-88;857,-1,-599,22,-500,354,352,114;2,77,-264,225,354,247,77,-245;-111,-152,24,-502,352,77,823,272;852,-513,-232,-88,114,-245,272,-640],[-882,182,-721,-2,708,658,-128,-405;182,-600,-779,-15,-33,-307,3,500;-721,-779,726,14,816,30,79,-513;-2,-15,14,-937,-385,-212,106,-673;708,-33,816,-385,652,857,125,-490;658,-307,30,-212,857,327,478,-519;-128,3,79,106,125,478,604,348;-405,500,-513,-673,-490,-519,348,-49],[-247,279,-233,300,-596,536,107,119;279,-955,-57,-108,-312,-241,-470,-649;-233,-57,968,-576,-494,160,-80,254;300,-108,-576,-275,258,-208,-187,-574;-596,-312,-494,258,312,301,262,202;536,-241,160,-208,301,-13,-220,-389;107,-470,-80,-187,262,-220,292,412;119,-649,254,-574,202,-389,412,428],[-992,-65,97,-390,110,-593,65,469;-65,849,100,813,302,-85,1,445;97,100,-914,841,-808,149,-604,-588;-390,813,841,-444,-129,338,276,-397;110,302,-808,-129,672,316,-197,88;-593,-85,149,338,316,350,-83,-642;65,1,-604,276,-197,-83,-872,249;469,445,-588,-397,88,-642,249,900],[-518,-140,218,137,-57,-375,618,614;-140,-544,255,156,-208,424,45,-306;218,255,851,-169,-208,100,432,-277;137,156,-169,276,-540,435,-567,591;-57,-208,-208,-540,-706,360,79,-168;-375,424,100,435,360,-959,-542,39;618,45,432,-567,79,-542,243,-547;614,-306,-277,591,-168,39,-547,985],[659,-3,124,177,-179,-29,764,-387;-3,-481,302,172,-11,23,30,-255;124,302,-722,255,-99,496,247,-661;177,172,255,-551,584,364,27,83;-179,-11,-99,584,-849,-119,-627,91;-29,23,496,364,-119,-189,195,-173;764,30,247,27,-627,195,-196,-547;-387,-255,-661,83,91,-173,-547,558],[-467,572,-60,174,-365,155,-386,-903;572,-724,298,97,302,-434,-77,173;-60,298,-941,-511,178,212,434,191;174,97,-511,-928,831,-352,584,114;-365,302,178,831,-165,-25,-308,-87;155,-434,212,-352,-25,-254,-314,-740;-386,-77,434,584,-308,-314,236,173;-903,173,191,114,-87,-740,173,-567],[584,220,-533,423,173,214,-377,623;220,662,-31,912,-94,45,606,512;-533,-31,-451,-122,-411,65,393,855;423,912,-122,-142,348,-541,449,368;173,-94,-411,348,934,376,213,-579;214,45,65,-541,376,700,116,432;-377,606,393,449,213,116,-404,-43;623,512,855,368,-579,432,-43,-804],[542,64,-578,858,-678,-686,373,-98;64,314,-421,610,-603,-73,414,-411;-578,-421,-644,-311,-172,136,198,-320;858,610,-311,639,941,-22,142,397;-678,-603,-172,941,-831,304,-262,-155;-686,-73,136,-22,304,463,-216,-88;373,414,198,142,-262,-216,236,-381;-98,-411,-320,397,-155,-88,-381,-264],[773,-819,-786,105,-88,-614,-700,-859;-819,-558,-403,725,-163,-168,-124,-35;-786,-403,-618,-257,-685,369,357,471;105,725,-257,430,-530,473,-178,347;-88,-163,-685,-530,-794,197,144,708;-614,-168,369,473,197,-255,282,237;-700,-124,357,-178,144,282,757,451;-859,-35,471,347,708,237,451,134],[-829,21,-560,-575,193,-236,-375,-315;21,-125,31,-537,-127,-577,-390,-607;-560,31,801,-352,13,-126,-42,169;-575,-537,-352,509,231,25,-174,122;193,-127,13,231,201,550,134,419;-236,-577,-126,25,550,-591,-149,-534;-375,-390,-42,-174,134,-149,-158,-290;-315,-607,169,122,419,-534,-290,412],[311,371,379,404,213,474,314,-104;371,683,-450,107,66,-27,35,37;379,-450,-232,17,-94,115,603,-1;404,107,17,-500,768,634,-765,14;213,66,-94,768,-80,62,-318,-243;474,-27,115,634,62,486,-331,594;314,35,603,-765,-318,-331,910,-389;-104,37,-1,14,-243,594,-389,-788],[-796,156,607,220,-460,23,-736,-365;156,620,-547,-507,-226,418,40,-217;607,-547,-238,283,-676,-375,77,263;220,-507,283,-262,-30,46,130,-325;-460,-226,-676,-30,-83,7,434,-307;23,418,-375,46,7,-664,756,-274;-736,40,77,130,434,756,601,65;-365,-217,263,-325,-307,-274,65,867],[332,-160,-560,30,-455,505,-16,-30;-160,227,293,157,-68,-201,-32,341;-560,293,-676,682,392,85,60,385;30,157,682,350,585,-1,-314,-117;-455,-68,392,585,571,224,-112,720;505,-201,85,-1,224,-69,-83,-237;-16,-32,60,-314,-112,-83,-20,333;-30,341,385,-117,720,-237,333,-638],[-257,400,-726,473,104,-420,-104,-332;400,-219,-591,389,-249,-163,230,-100;-726,-591,-491,-311,-280,605,-699,89;473,389,-311,-729,203,-358,451,-77;104,-249,-280,203,-113,-682,544,330;-420,-163,605,-358,-682,551,609,-65;-104,230,-699,451,544,609,921,-452;-332,-100,89,-77,330,-65,-452,575],[-172,-171,-32,549,-113,328,-33,-219;-171,-630,843,-273,-135,-17,-395,-30;-32,843,-249,-309,50,-250,481,525;549,-273,-309,-945,521,766,134,488;-113,-135,50,521,808,-341,311,485;328,-17,-250,766,-341,-684,846,-132;-33,-395,481,134,311,846,-536,-541;-219,-30,525,488,485,-132,-541,-235],[-7,-168,267,44,525,215,739,74;-168,-792,105,575,643,-374,-272,613;267,105,911,841,-72,316,-390,-109;44,575,841,-348,142,53,-49,-176;525,643,-72,142,369,463,269,-86;215,-374,316,53,463,-217,197,-37;739,-272,-390,-49,269,197,-922,32;74,613,-109,-176,-86,-37,32,595],[-211,856,-146,-570,-229,-636,-109,282;856,-94,-63,409,-620,234,498,641;-146,-63,134,90,533,93,156,-454;-570,409,90,-568,-617,-89,33,-511;-229,-620,533,-617,396,-278,526,-220;-636,234,93,-89,-278,456,-308,700;-109,498,156,33,526,-308,-456,-540;282,641,-454,-511,-220,700,-540,-886],[143,-192,-28,-357,370,50,359,143;-192,-232,729,-314,767,55,108,-599;-28,729,-278,12,-316,803,-842,869;-357,-314,12,-420,552,-467,634,388;370,767,-316,552,-500,-42,212,-277;50,55,803,-467,-42,392,885,98;359,108,-842,634,212,885,-183,-117;143,-599,869,388,-277,98,-117,938],[-801,780,-373,306,688,-182,573,-120;780,-749,424,-128,-456,584,116,-312;-373,424,-407,-389,-408,153,-533,48;306,-128,-389,571,-142,687,-170,-137;688,-456,-408,-142,17,-236,-234,507;-182,584,153,687,-236,-819,-447,865;573,116,-533,-170,-234,-447,-451,-411;-120,-312,48,-137,507,865,-411,459],[-157,-171,263,17,-728,-193,762,257;-171,-413,-239,-868,431,364,-566,-172;263,-239,-37,-585,311,362,-186,715;17,-868,-585,797,-416,-674,138,-520;-728,431,311,-416,-918,-227,-483,483;-193,364,362,-674,-227,-581,-508,923;762,-566,-186,138,-483,-508,42,-343;257,-172,715,-520,483,923,-343,-720],[367,329,361,-44,320,-128,349,580;329,-827,370,37,412,-234,358,399;361,370,-232,231,-103,-208,778,-174;-44,37,231,471,-605,450,-70,-310;320,412,-103,-605,416,229,143,-225;-128,-234,-208,450,229,-617,561,771;349,358,778,-70,143,561,-742,6;580,399,-174,-310,-225,771,6,-852],[-229,-391,772,601,-348,-207,312,952;-391,-368,-245,265,170,252,694,109;772,-245,893,-441,156,235,-210,-620;601,265,-441,838,585,-262,753,-32;-348,170,156,585,465,476,-52,-421;-207,252,235,-262,476,986,-370,-203;312,694,-210,753,-52,-370,-897,521;952,109,-620,-32,-421,-203,521,506],[-895,-403,690,-490,130,-670,-27,837;-403,-392,384,-401,932,195,-213,-813;690,384,658,205,448,-825,182,-445;-490,-401,205,-742,-179,-657,-368,36;130,932,448,-179,-606,717,-29,176;-670,195,-825,-657,717,-861,271,-35;-27,-213,182,-368,-29,271,541,369;837,-813,-445,36,176,-35,369,-628],[-208,-129,8,142,-466,103,11,-558;-129,136,84,631,198,715,-292,-724;8,84,-917,-178,-648,-243,868,-444;142,631,-178,-893,-614,792,146,-291;-466,198,-648,-614,22,83,-180,245;103,715,-243,792,83,-465,22,413;11,-292,868,146,-180,22,-818,895;-558,-724,-444,-291,245,413,895,617],[-749,13,400,364,-214,-750,632,-364;13,-929,664,398,-182,30,80,115;400,664,-703,58,84,472,-419,-60;364,398,58,-487,162,-686,-466,-577;-214,-182,84,162,138,504,674,759;-750,30,472,-686,504,439,770,311;632,80,-419,-466,674,770,859,393;-364,115,-60,-577,759,311,393,787],[-780,366,-190,-207,963,-465,-393,-877;366,-624,-844,-177,571,-282,-3,430;-190,-844,-927,753,440,-517,-286,378;-207,-177,753,-189,540,-9,322,889;963,571,440,540,-286,141,272,219;-465,-282,-517,-9,141,411,268,-27;-393,-3,-286,322,272,268,-738,-192;-877,430,378,889,219,-27,-192,462],[-969,275,-875,-677,-65,29,-457,281;275,-833,262,116,-111,-162,-803,262;-875,262,773,56,-424,277,613,-156;-677,116,56,-825,187,-17,-92,-595;-65,-111,-424,187,401,49,-206,235;29,-162,277,-17,49,4,-2,-491;-457,-803,613,-92,-206,-2,87,-117;281,262,-156,-595,235,-491,-117,746],[662,-401,-344,169,-494,-266,58,-462;-401,282,-394,-578,583,-777,129,-408;-344,-394,130,-422,-675,-224,-202,844;169,-578,-422,-772,46,-336,285,193;-494,583,-675,46,257,519,-626,361;-266,-777,-224,-336,519,-710,-395,-567;58,129,-202,285,-626,-395,197,-529;-462,-408,844,193,361,-567,-529,825],[771,-245,-364,456,818,466,-355,418;-245,683,63,841,-615,-647,-229,-571;-364,63,-904,-357,-173,248,-72,-122;456,841,-357,551,-822,-150,-466,-277;818,-615,-173,-822,26,-44,590,-105;466,-647,248,-150,-44,697,-201,462;-355,-229,-72,-466,590,-201,200,-273;418,-571,-122,-277,-105,462,-273,-389],[965,-217,305,-118,-647,45,-167,309;-217,400,-58,-466,871,47,24,-351;305,-58,600,440,81,-628,392,-551;-118,-466,440,821,30,408,-66,334;-647,871,81,30,372,-576,599,-252;45,47,-628,408,-576,-48,120,-643;-167,24,392,-66,599,120,376,-424;309,-351,-551,334,-252,-643,-424,353],[-551,-129,218,172,224,294,-114,759;-129,786,-11,-40,-258,-180,216,-302;218,-11,-593,339,-345,464,297,-39;172,-40,339,918,403,-652,524,-436;224,-258,-345,403,304,-88,731,-248;294,-180,464,-652,-88,-967,180,-17;-114,216,297,524,731,180,-709,369;759,-302,-39,-436,-248,-17,369,671],[751,511,288,32,-487,-406,560,-452;511,694,174,-578,-261,78,740,-114;288,174,-655,-159,93,-592,171,-450;32,-578,-159,-300,-98,-871,-337,414;-487,-261,93,-98,-360,130,114,734;-406,78,-592,-871,130,-107,-67,-138;560,740,171,-337,114,-67,-524,-192;-452,-114,-450,414,734,-138,-192,-172],[-409,-70,-354,16,302,674,-392,37;-70,812,-82,-106,-660,443,52,-681;-354,-82,-971,-380,676,0,78,-649;16,-106,-380,209,826,238,-415,-588;302,-660,676,826,691,-912,-414,392;674,443,0,238,-912,271,-704,-648;-392,52,78,-415,-414,-704,-564,238;37,-681,-649,-588,392,-648,238,143],[49,-361,-254,183,596,77,-489,223;-361,690,-97,731,-794,321,218,-377;-254,-97,-213,-178,50,-583,-87,-61;183,731,-178,-75,478,-828,194,635;596,-794,50,478,443,-66,-569,482;77,321,-583,-828,-66,-710,-145,152;-489,218,-87,194,-569,-145,-186,76;223,-377,-61,635,482,152,76,280],[12,-62,256,-318,-301,163,517,676;-62,140,-179,192,722,422,-51,460;256,-179,865,256,-222,223,512,-360;-318,192,256,-693,-478,-147,-717,-12;-301,722,-222,-478,356,-483,-401,58;163,422,223,-147,-483,615,-348,208;517,-51,512,-717,-401,-348,-94,658;676,460,-360,-12,58,208,658,774],[-482,-99,101,290,699,779,444,4;-99,-530,-619,805,-731,303,494,432;101,-619,35,-658,283,-201,776,133;290,805,-658,149,-429,40,117,-153;699,-731,283,-429,501,-178,-100,457;779,303,-201,40,-178,795,7,151;444,494,776,117,-100,7,790,-32;4,432,133,-153,457,151,-32,450],[-102,-121,606,747,-445,650,-248,-322;-121,-324,623,449,-222,79,-5,284;606,623,638,-378,-312,306,-624,223;747,449,-378,426,317,-322,-254,789;-445,-222,-312,317,80,-69,-729,-560;650,79,306,-322,-69,-4,19,290;-248,-5,-624,-254,-729,19,-786,717;-322,284,223,789,-560,290,717,536],[769,728,83,-893,-123,303,-727,73;728,2,44,-400,-118,-698,-106,462;83,44,611,395,-65,253,-311,-104;-893,-400,395,-888,-445,221,-342,454;-123,-118,-65,-445,-498,-643,-461,396;303,-698,253,221,-643,-309,-84,-275;-727,-106,-311,-342,-461,-84,-77,-83;73,462,-104,454,396,-275,-83,-915],[-264,-34,-773,-380,-165,-238,-451,233;-34,411,276,-418,-599,-411,-329,-122;-773,276,-527,-522,-863,-540,-534,-267;-380,-418,-522,-922,143,-219,-640,719;-165,-599,-863,143,-8,-426,-780,688;-238,-411,-540,-219,-426,956,578,525;-451,-329,-534,-640,-780,578,-482,611;233,-122,-267,719,688,525,611,-91],[-727,-204,-407,561,715,523,97,403;-204,321,6,-311,-835,-57,-320,-651;-407,6,-734,328,-513,-315,-684,467;561,-311,328,472,389,-406,158,144;715,-835,-513,389,-670,293,-288,243;523,-57,-315,-406,293,-126,-424,3;97,-320,-684,158,-288,-424,-20,-409;403,-651,467,144,243,3,-409,-404],[585,-649,-20,-788,-492,233,-3,-459;-649,592,-444,-52,108,-208,60,-471;-20,-444,-670,-284,112,-614,437,-51;-788,-52,-284,-851,-380,-418,-83,313;-492,108,112,-380,659,484,-148,-851;233,-208,-614,-418,484,-878,-229,-51;-3,60,437,-83,-148,-229,856,-48;-459,-471,-51,313,-851,-51,-48,-736],[-632,792,-88,-409,-516,253,57,7;792,-950,26,-138,-687,-384,-321,221;-88,26,395,-111,124,78,-866,9;-409,-138,-111,485,-381,-61,-227,-21;-516,-687,124,-381,-621,-608,-847,-447;253,-384,78,-61,-608,-807,-31,289;57,-321,-866,-227,-847,-31,-293,1;7,221,9,-21,-447,289,1,537],[-809,-182,-507,-173,66,-252,384,362;-182,973,76,-203,132,-386,-237,-167;-507,76,768,580,-290,-558,479,-341;-173,-203,580,561,346,469,-259,55;66,132,-290,346,-992,-268,-890,-687;-252,-386,-558,469,-268,770,382,-15;384,-237,479,-259,-890,382,735,-448;362,-167,-341,55,-687,-15,-448,-161],[862,-108,755,-38,-596,137,-448,-350;-108,763,-551,-180,-255,-748,-630,298;755,-551,543,495,442,833,91,-214;-38,-180,495,24,-157,-970,-101,-680;-596,-255,442,-157,468,-23,830,-133;137,-748,833,-970,-23,-377,-425,67;-448,-630,91,-101,830,-425,-360,-172;-350,298,-214,-680,-133,67,-172,-555],[445,-67,205,766,-107,-244,645,-225;-67,-335,16,578,-516,561,37,159;205,16,566,-155,79,35,336,12;766,578,-155,-980,-589,-244,278,-707;-107,-516,79,-589,604,149,-175,487;-244,561,35,-244,149,996,333,-445;645,37,336,278,-175,333,552,167;-225,159,12,-707,487,-445,167,-196],[719,465,663,-460,488,254,289,543;465,696,-397,462,-45,-60,-52,-414;663,-397,-498,-795,-1,85,-641,542;-460,462,-795,448,149,-162,-191,103;488,-45,-1,149,846,-310,151,-451;254,-60,85,-162,-310,-209,329,-401;289,-52,-641,-191,151,329,523,-535;543,-414,542,103,-451,-401,-535,-482],[686,168,490,158,-28,-255,-603,-335;168,81,80,586,-518,-173,-347,-52;490,80,681,-523,-47,726,175,-173;158,586,-523,-623,633,-510,-341,240;-28,-518,-47,633,-244,6,163,680;-255,-173,726,-510,6,-38,-308,536;-603,-347,175,-341,163,-308,373,-285;-335,-52,-173,240,680,536,-285,928],[-645,493,252,544,490,-55,678,489;493,300,175,264,592,-118,-149,162;252,175,506,-71,-783,476,-311,-383;544,264,-71,807,15,310,5,-54;490,592,-783,15,-208,-24,24,602;-55,-118,476,310,-24,-661,-438,622;678,-149,-311,5,24,-438,-191,-717;489,162,-383,-54,602,622,-717,633],[-649,492,-617,-501,436,492,68,420;492,-527,158,451,-751,-511,-27,362;-617,158,47,-742,287,-440,-207,-633;-501,451,-742,60,3,591,-272,576;436,-751,287,3,987,171,-341,216;492,-511,-440,591,171,754,-589,72;68,-27,-207,-272,-341,-589,-457,-540;420,362,-633,576,216,72,-540,-671],[-987,-794,-212,262,437,361,75,10;-794,-864,54,258,-749,196,-740,559;-212,54,-981,347,117,-94,-148,270;262,258,347,-102,186,251,-199,617;437,-749,117,186,308,-212,244,-56;361,196,-94,251,-212,630,404,-369;75,-740,-148,-199,244,404,-236,-387;10,559,270,617,-56,-369,-387,216],[460,-64,-595,-579,468,780,626,353;-64,-439,223,-29,-324,286,748,-228;-595,223,727,867,481,106,670,90;-579,-29,867,120,-139,-151,35,144;468,-324,481,-139,-673,229,347,552;780,286,106,-151,229,319,273,210;626,748,670,35,347,273,646,-330;353,-228,90,144,552,210,-330,-173]];} TEST(deb=1,fin=6)= { for(i=deb,fin, print("dim=",i+2); for(j=1,100, Q=M[i,j]; s=qfsolve(Q); if(type(s)=="t_INT", print([j,s]), if(s~*Q*s, error(Q))); ); ); } TEST() G = [1,0,0;0,1,0;0,0,-34]; qfparam(G, qfsolve(G)) qfparam(G, qfsolve(G),1) qfparam(G, qfsolve(G),2) qfsolve(Mat(0)) qfsolve(Mat(1)) qfsolve([1,2;2,1]) qfsolve([0,1;1,1]) qfsolve([35, 46; 46, 60]) qfparam(matdiagonal([1,1,-1]),[1,0,1]) qfsolve(matdiagonal([1,1,-25])) qfsolve([1,0,0;0,3,0;0,0,-2]) qfparam([0,0,-12;0,-12,0;-12,0,-1],[1,0,0]~,3) q=[-1,-4,-8;-4,-15,-31;-8,-31,-62]/4; qfparam(q,qfsolve(q)) qfminimize(matdiagonal([13,17,221])) qfminimize(matdiagonal([650, -104329, -104329])) \\#1661 qfsolve([1,0,0;0,1,1;0,0,1]); \\#1725 qfsolve(matdiagonal([1,1,1,1,1,1,-7])) Q= { [-2,1,-1,1,1,1,1,-1,0,0; 1,1,1,0,-1,0,0,0,0,0; -1,1,1,0,1,1,1,-1,0,0; 1,0,0,1,-1,0,0,1,0,0; 1,-1,1,-1,1,-1,0,1,0,0; 1,0,1,0,-1,1,0,0,0,0; 1,0,1,0,0,0,1,1,0,0; -1,0,-1,1,1,0,1,1,0,0; 0,0,0,0,0,0,0,0,1,0; 0,0,0,0,0,0,0,0,0,1]; } qfsolve(Q) \\ errors M=matdiagonal([1,1,1,-5^4*17]/5);F=factor(matdet(M));qfsolve([M,F]) pari-2.17.2/src/test/in/chinese0000644000175000017500000000052614760123736014715 0ustar billbillchinese(Mod(x,x^2+1),Mod(x,x^2+1)) chinese(Mod(x,x^2+1),Mod(x,x^2-1)) chinese(Mod(1,2)*x+Mod(1,2), Mod(2,3)*x^2+Mod(1,3)*x+Mod(1,3)) chinese([Mod(1,2),Mod(1,3)], [Mod(1,4),Mod(1,2)]) chinese(1) chinese([]) chinese(Mod(1+x,x^2),Mod(0,1)) chinese(Mod(1+x,x^2),Mod(1,2)) chinese(Mod(0,1),Mod(1+x,x^2)) chinese(Mod(1,3)*(x^2+x+2),Mod(1,5)*(x-1)) pari-2.17.2/src/test/in/factormod0000644000175000017500000000364314676526175015272 0ustar billbilldefault(parisize, 350M); print(lift(factorcantor(x^1024+1,12289))) check(P,p)= { my(F=factormod(P,p)); my(G=factorcantor(P,p)); if(F!=G || factorback(F)!=P,error(P)); F[,1]=apply(poldegree,F[,1]); F~; } setrand(4); check(y^3-3*y-1,2238004061) \\#1451 check(x^31+x^30+x^29+x^28+x^26+x^24+x^23+x^21+x^16+x^15+x^14+x^11+x^10+x^9+x^8+x^7+x^3+x^2+x,2) localbitprec(1000);check(Polrev(binary(round(Pi*2^1000))),2) polrootsmod(x^16-1,41) polrootsmod(x^5+x^2-4*x+2,5) polrootsmod(Pol(1),2) factorcantor(x^3+x,2) factormod(Pol(0),2) factormod(Pol(0),2,1) factormod(Pol(1),2) factormod(Pol(1),2,1) f=(x^2+x+1)*(x^3+x); factormod(f,2,1) factormodSQF(f,2) factormodDDF(x^4+x,2) polrootsmod(x^5+4*x^4+2*x^3+x^2+4*x+2,7) p=2^64+13; polrootsmod(Pol(1),p) polrootsmod(x,p) polrootsmod(2*x+1,p) factormod(x^2+1,p) factormod(x^2+1,p,1) factormod(x^2+3,p,1) factormod(x^4+1,p) factormod(x^4+1,p,1) factormod(x^4+3,p,1) factorcantor(x^2+1,p) factorcantor(Pol(0),p) factorcantor(Pol(1),p) factormodSQF(Pol(1),p) factormodDDF(Pol(1),p) polisirreducible((x^2+x+1)*Mod(1,2)) polisirreducible((x^2+1)*Mod(1,p)) polisirreducible(Mod(x^4+x^2+x,2)) \\#2037 factormod((x+1)^2, 10^20+39) { P = concat([primes(100),primes([2^32-100,2^32+100]), primes([2^64-200,2^64+200])]); foreach(P, p, for(i=1,100, if (i % p == 0, next); my(T = polcyclo(i), v = factormodcyclo(i,p), t = factormodcyclo(i,p,1)); if (factorback(v) != T, error([p,i])); if (!setsearch(Set(v), t), error([p,i,1])))); } if(factorback(factormodcyclo(4879, 29))!=polcyclo(4879),error([29,4879])) if(factorback(factormodcyclo(15015, 2^64+375361))!=polcyclo(15015),error()) if(factorback(factormodcyclo(15857, 2^64+5789871))!=polcyclo(15857),error()) \\ errors, keep at end of file polrootsmod(x^3-1, 2^101-1) polrootsmod(x^10-1, 1023) polrootsmod(Pol(0),p) polrootsmod(Pol(0),2) factormod(x,0) factormod(x^3+1,[y^2+1,2]) factormod(x^3+1,[y^2+1,5]) pari-2.17.2/src/test/in/lfuntype0000644000175000017500000000663114676526175015162 0ustar billbilldefault(parisize,"32M"); zet=1; Z(a)=lfuncreate([(p,n)->1/(1-p^a*x),0,[-a],2*a+1,1,1,[[a+1,1/x+O(1)]]]); N=nfinit(x^10-2*x^8-9*x^6+57*x^4-69*x^2+47); G=galoisinit(N); E=ellinit([0,-1,1,-10,-20]); \\ 11a1 VALL={ [zet, lfuncreate([n->vector(n,i,kronecker(i,857)),0,[0],1,857,1]), lfunthetainit(zet), lfuninit(zet,[1,1,2],2), \\5 lfuninit(x^3-x-1,[1,1,2],2), lfuninit(x^4-2,[1,1,2],2), lfuninit(x^6+108,[1,1,2],2), lfuninit(polsubcyclo(11,5),[1,1,2],2), x^3-x-1, \\10 x^4-2, polsubcyclo(11,5), 17, -4, 857, \\15 [znstar(5,1),2], E, ellinit([1,1]), ellinit([-7,3]), lfunetaquo([1,1;3,1;5,1;15,1]), \\20 lfunmul(-4,-3), lfundiv(x^3-x-1,1), bnfinit(x^4+2*x^2+5), [bnrinit(bnfinit(x^3+x^2+2*x+1),4),[1]], Z(2), \\25 lfunqf(matid(4)), lfunqf(matdiagonal([1,2,3,4])), lfunartin(N,G,[2,0,-y^3-y^2-1,y^3+y^2],5), lfunartin(N,G,[['a,0;0,'a^4],[0,1;1,0]],5), if(1,my(E1=ellinit([0,0,1,-1,0]),E2=ellinit([0,1,1,-23,-50])); lfuncreate([n->lfunan(E1,n)+lfunan(E2,n),n->-lfunan(E1,n)+lfunan(E2,n),[0,1],2,37,1])), \\30 if(1,my(K3=nfinit(a^2-a-9)); ellinit([0,2,1,-19-8*a,28+11*a],K3)), if(1,my(E=ellinit([0,-1,1,-10,-20])); \\11a1 lfuncreate([n->my(V=ellan(E,n));vector(n,i,V[i]/sqrt(i)),0,[1/2,3/2],1,11,1])), lfuntwist(E, Mod(2,5)), lfunsympow(E,2), lfunsympow(E,3), \\35 if(1,localprec(19); lfuncreate(()->[n->lfunan(Mod(2,7),n),1,[0],1,7,((-13-3*sqrt(-3))/14)^(1/6)])), if(1,my(bnf=bnfinit('a^2+47),bnr=bnrinit(bnf,1)); lfuncreate([bnr,[[1],[2]]])), if(1,my(G=znstar(44,1)); lfuncreate([G,[[3,0],[9,0]]])), lfunshift(x^2+1,1), lfunshift(x^2+1,-1/2), \\40 lfunshift(x^2+1,1,1), lfunhgm(hgminit([5]),1), if(1,my(bnf=bnfinit(x^2-x+2), gc=gcharinit(bnf,idealprimedec(bnf,11)[1]),chi=[1,-1,-1/2]~); lfuncreate([gc,chi])), if(1,my(bnf=bnfinit(a^2-a-9), bnr=bnrinit(bnf,[2,[0,0]])); lfuncreate([bnr,matdiagonal(bnr.cyc)])), lfuninit(1, []), \\45 lfuninit(x^2+1, []) ]; } \p36 chk(s,i,a,b, laxist = 0) = { my (v, cvt = 0, B = getlocalbitprec()); if (type(a)!="t_VEC", a=[a]; b=[b]; cvt=1); v = vector(#a,i, my(e); round((a[i]-b[i]) / b[i], &e); e); if (type(a[1])=="t_COMPLEX" && exponent(imag(a)) < -B, a = real(a)); if (cvt, a = a[1]); if (vecmax(v) > if (laxist, laxist, 15 - B), error("bug in lfuntype:", s, ":", i, ":", v) , print(i," (",s,"): ",a)); } { for(i=1,#VALL, ldata=VALL[i]; L=lfuninit(ldata,[1,1,2],2); a=lfun(L,2+2*I); b=lfun(ldata,2+2*I); chk("lfun(2+2*I)",i,a,b); iferr( a=lfun(L,2); b=lfun(ldata,2); chk("lfun",i,a,b); b=lfun(lfuncreate(ldata),2); chk("lfuncreate",i,a,b), E, print(E)); iferr( a=lfun(L,2,2); b=lfun(ldata,2,2); chk("lfunderiv",i,a,b), E, print(E)); iferr( a=lfunlambda(L,2); b=lfunlambda(ldata,2); chk("lfunlambda",i,a,b), E, print(E)); iferr( a=lfunlambda(L,2,2); b=lfunlambda(ldata,2,2); chk("lfunderivlambda",i,a,b), E, print(E)); a=lfuncheckfeq(L); b=lfuncheckfeq(ldata); chk("lfuncheckfeq",i,a,b, 1); \\ we may have a != b a=lfuncheckfeq(lfundual(L)); b=lfuncheckfeq(lfundual(ldata)); chk("lfuncheckfeq(lfundual)",i,a,b, 1); \\ we may have a != b a=lfunhardy(L,2); b=lfunhardy(ldata,2); chk("lfunhardy",i,a,b); print(i," (lfunorderzero): ",iferr(lfunorderzero(L),E,E)); L=lfunthetainit(ldata); a=lfuntheta(L,2); b=lfuntheta(ldata,2); chk("lfuntheta",i,a,b); print(i," (lfunan): ",lfunan(ldata,10)); print(i," (lfuneuler): ",iferr(lfuneuler(ldata,3),E,E)); print(i," (lfuneuler): ",iferr(lfuneuler(ldata,7),E,E)); ) } pari-2.17.2/src/test/in/bessel0000644000175000017500000000330714676526175014566 0ustar billbilldefault(seriesprecision,6); besseljh(1,2^64) besseljh(10,x) NU = [x,0,1,1/2,sqrt(2),10,1+I]; ARG = [x,1,1/2,1+I]; F=[besselh1,besselh2,besseli,besselj,besseljh,besselk,bessely]; test(f)= { print(f); for (i=1,#NU, for (j=1,#ARG, print([i,j],": ", iferr(f(NU[i],ARG[j]), E,E)); ) ); } for(i=1,#F,test(F[i])); for(i=1,#F,print(F[i](1,Mod(x,x^2+1)))); for(i=1,#F,print(F[i](1,[1]))); for(i=1,#F,print(F[i](1,[1]~))); for(i=1,#F,print(F[i](1,Mat(1)))); besseljh(2,0.) besseljh(2,1e-50) besselk(1,1000) besseli(1,1000) besselj(1,1000) besseln(1,1000) besselk(1e-5,20) besselk(I,1000) besseli(I,1000) besselj(I,1000) besseln(I,1000) besseljh(100,I) besselj(80,66) besselk(0,O(x^3)) v = powers(exp(I*Pi/4),7); v[3] = I; v[5] = -1; v[7] = -I; NU = v / 7; ARG = v * 1000; F=[besseli,besselj,besselk,bessely]; clean(z) = { my([x,y]=[abs(real(z)),abs(imag(z))]); if (!x || !y, return(z)); x = exponent(x); y = exponent(y); if (x < y - 127, return (I*imag(z))); if (y < x - 127, return (real(z))); return (z); } test(f)= { print(f); for (i=1,#NU, for (j=1,#ARG, print([i,j],": ", clean(f(NU[i],ARG[j]))); ) ); } for(i=1,#F,test(F[i])) besselk(1e-20,1e-5) besseljzero(0, 1) besseljzero(0, 10) besselyzero(0, 1) besselyzero(0, 10) for (i=1,20, print(i,":", besseljzero(i))) for (i=1,20, print(i,":", besselyzero(i))) for(i=1,10, print(i,":",vector(5,j,besseljzero(i,j)))) for(i=1,10, print(i,":",vector(5,j,besselyzero(i,j)))) besselj(220, 112) besseli(220, 112) besselk(220, 112) besseln(220, 112) \\ ERRORS for(i=1,#F,print(iferr(F[i](O(2),1),E,E))); for(i=1,#F,print(iferr(F[i]("",1),E,E))); for(i=1,#F,print(iferr(F[i](1,O(2)),E,E))); for(i=1,#F,print(iferr(F[i](1,""),E,E))); besseljzero(0,-1) besselyzero(0,-1) pari-2.17.2/src/test/in/ploth0000644000175000017500000000533214676526175014437 0ustar billbill\e \p19 default(parisize,"16M"); \\ Needed for --graphic=svg t=plothsizes(); plotinit(0,t[1]-11,t[2]-11) plotscale(0,0,1000,0,1000); plotbox(0,500,500) plotdraw(0) write("pari0.svg", plotexport("svg", 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=-1,1,floor(x)) plot(x=-1,1,-floor(x)) plot(x=0,1,-0.29) plot(x=-5,5,sin(x)) ploth(x=-5,5,sin(x)) ploth(t=0,2*Pi,[sin(5*t),sin(7*t)]) ploth(t=0,2*Pi,[sin(5*t),sin(7*t)],"Parametric",100) ploth(t=0,2*Pi,[sin(5*t),sin(7*t)],"Parametric|Recursive",100) plothraw(vector(501,k,k-1),vector(501,k,(k-1)*(k-1)/500)); plothraw(vector(501,k,k-1),vector(501,k,(k-1)*(k-1)/500),1); plotpoints(0,225,334) plotpoints(0,vector(10,k,10*k),vector(10,k,5*k*k)) write("pari1.svg", plothexport("svg", x=-5,5,sin(x))); write("pari2.svg", plothrawexport("svg", 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]) write("pari3.svg", plotexport("svg",[0,10,10])) ploth(x=0,1, x^3,"Splines") ploth(x=0,1, [x^2,x^3],"Parametric|Splines") plotinit(1); plotcopy(0,1, 300,0); plotclip(1); plotdraw([1,10,10]); plotkill(1); plotinit(1); plotcopy(0,1, 1/2,0, 1); plotclip(1); plotdraw([1,10,10]); plotkill(1); plotinit(1); plotcopy(0,1, 1/2,1/3, 3); plotclip(1); plotdraw([1,10,10]); plotkill(1); plotinit(1); plotcopy(0,1, 1/3,1/3, 5); plotclip(1); plotdraw([1,10,10]); plotkill(1); plotinit(1); plotcopy(0,1, 1/3,1/3, 7); plotclip(1); plotdraw([1,10,10]); s = plothsizes(); plotinit(1,s[1]-1,s[2]-1); plotscale(1,-3,3,-3,3); plotrecthraw(1, [[-3.0+6/100*j,-3.0+6/100*j] | j<-[0..100]]); plotdraw(1); plotinit(1,s[1]-1,s[2]-1); plotscale(1,-3,3,-3,3); v=vector(100,j,-3+6/100*j); plotrecthraw(1, [v,v,apply(sqr,v),apply(x->x^3,v)]); plotdraw(1); plotinit(1,s[1]-1,s[2]-1); plotscale(1,-3,3,-3,3); plotrecthraw(1, [apply(sqr,v),apply(x->x^3,v), apply(cos,v), apply(sin,v)],1); plotdraw(1); plotinit(1,s[1]-1,s[2]-1); plotscale(1,-3,3,-3,3); plotrecthraw(1, [apply(x->exp(I*x),v),apply(x->x*exp(I*x),v)],4096); plotdraw(1); /*errors*/ plotinit(-1) plotinit(100) plotmove(-1,0,0) plotmove(100,0,0) plotcopy(0,1,2,1,1) plotcopy(0,1,-1,1,1) plotcopy(0,1,1,2,1) plotcopy(0,1,1,-1,1) ploth(x=0,2*Pi,if (x <1, [cos(x),sin(x)], 1),"Parametric") ploth(t=0,2*Pi,[sin(5*t),sin(7*t)],"Recursive",100) ploth(x=0,2*Pi,1,"Parametric") ploth(x=0,1,x,,1) default(graphcolormap,["white","black","gray","violetred","red","green","blue","gainsboro","purple"]) default(graphcolors,[7,4,9,8,5,6]) ploth(X=-1,9,vector(6,k,sin(X+k))) pari-2.17.2/src/test/in/nfsplitting0000644000175000017500000000104414567450071015634 0ustar billbillnfsplitting(1) nfsplitting(Pol(0)) nfsplitting(Pol(1)) nfsplitting(x) nfsplitting(y) nfsplitting(x^5-x-1) nfsplitting(x^6-8) nfsplitting((x^2+1)^2) nfsplitting(x^8+3) nfsplitting(x^8+3,32) nfsplitting(x^8+3,32,1) nfsplitting(nfinit(x^8+3)) nfsplitting(nfinit(x^8+3),,1) nfsplitting(x^9+3,,1) nfsplitting(nfinit(x^9+3),,1) nfsplitting(x^5+5/4*x+1) nfsplitting(polcyclo(23)) nfsplitting(x^7-2) nfsplitting(x^7-2,42) nfsplitting(x^7-2,43) nfsplitting(x^6-8,,1) nfsplitting(x^5+5/4*x+1,,1) galoissplittinginit(x); \\ ERROR galoissplittinginit(x^2); pari-2.17.2/src/test/in/ellissupersingular0000644000175000017500000000363714676526175017253 0ustar billbillforprime(p=2,1000,if(!ellissupersingular(ellsupersingularj(p)),error(p))) p = 7; e = 5; g = ffprimroot(ffgen([p,e])); S = [g^n | n <- [1 .. p^e - 1], ellissupersingular(g^n)]; if (S != [6] || ellissupersingular(0 * g^0), error("Bad result")); p = 7; e = 4; g = ffprimroot(ffgen([p,e])); S = [g^n | n <- [1 .. p^e - 1], ellissupersingular(g^n)]; if (S != [6] || ellissupersingular(0 * g^0), error("Bad result")); S = [g^n | n <- [1 .. p^e - 1], ellissupersingular(ellinit([g^n]))]; if (S != [6], error("Bad result")); if(!ellissupersingular(ellsupersingularj(g)),error("Bad result")); p = 43; S = [j | j <- [0 .. p - 1], ellissupersingular(Mod(j,p))]; if (S != [8, 41], error("Bad result")); if(!ellissupersingular(ellsupersingularj(p)),error("Bad result")); e = 2; T = ffgen([p,2], 't); g = (28*T + 6); \\ Fix primitive root: always get the same ordering in S S = [g^n | n <- [1 .. p^e - 1], ellissupersingular(g^n)]; if (S != [41, 8, 38*T + 31, 5*T + 36], error("Bad result")); if(!ellissupersingular(ellsupersingularj(T)),error("Bad result")); if([j | p<-primes(5);j<-[0..p-1],ellissupersingular(Mod(j,p))]!=[0,0,0,6,0,1],\ error("Bad result")); E=ellinit([1,0,1,-6,4]); if([ellissupersingular(E,p)|p<-primes(5)]!=[0,0,1,0,0], error("Bad result")); a4 = 66769864309396989186219319899455305602854066404762376449738762528262768931769607684129276313553; a6 = 348116536806166027198165409499561123661407423910749290282025451118909597813412918432599467486475; p = 512458910477613158057639788896927028629704334700832943238108853005887899986044384024365532075481; E = ellinit([a4,a6],p); if(ellissupersingular(E),error("Bad result")); if(!ellissupersingular(ellsupersingularj(p)),error("Bad result")); iferr(ellissupersingular(""), err, Vec(err)); K = nfinit(y^3-2); f(E,p) = [ ellissupersingular(E, P) | P <- idealprimedec(E.nf,p) ]; P = [2,3,5,47,53,59] E = ellinit([y,1],K); [f(E,p) | p <- P] E = ellinit([1,y,1,y,y+1],K); [f(E,p) | p <- P] pari-2.17.2/src/test/in/partition0000644000175000017500000000163214567450071015307 0ustar billbilltest(N) = /* pentagonal numbers recurrence */ { my(s,t,p); p = vector(N); p[1] = 1; for (n=1, N-1, s = 0; t = n+1; for (k=1, n, t -= 2*k-1; /* n+1 - k(3k-1)/2 */ if (t<=0,break); s -= (-1)^k*p[t]; t -= k; /* n+1 - k(3k+1)/2 */ if (t<=0,break); s -= (-1)^k*p[t] ); p[n+1] = s; if (s != numbpart(n), error([n, s])) ); } test(10^4); numbpart(0) numbpart(52602) numbpart(147007) numbpart(10^15+2) partitions(0) partitions(1) partitions(9) partitions(9,3) partitions(-1) partitions(5,[3,4],[1,2]) for(i=1,5,print(partitions(i,[0,5],[3,4]))) forpart(v=-1,) forpart(v=5,print(Vec(v)),4,3) forpart(v=5,print(Vec(v)),[0,5],[2,4]) my(i=0); forpart(x=55,i++); i forpart(x=9,print(Vec(x))); forpart(x=11,print(Vec(x)),,5); forpart(x=12,print(Vec(x)),,[2,6]); forpart(x=23,print(Vec(x)),[3,6]); forpart(x=5, print(Vec(x)),[0,3]); forpart(x=15, print(Vec(x)),[0,3],7); pari-2.17.2/src/test/in/logint0000644000175000017500000000057514567450071014577 0ustar billbilllogint(2^99,2) logint(2^100,2,&z) z logint(5^100,2,&z) z logint(5^100,3) logint(5^100,4) logint(5^100,5) logint(2^64-1, 2^32) logint(2^64-1, 2^16) x=Pi^1000; logint(x, 2) logint(x, 2, &z) z logint(x, 3) logint(x, 3, &z) z x=quadgen(5)^100; logint(x, 2) logint(x, 2, &z) z x=(3/2)^10; logint(x, 2) logint(x, 2, &z) z \\ ERRORS logint(-Pi, 2) logint(-quadgen(5), 2) logint(-1/2, 2) pari-2.17.2/src/test/in/mspolygon0000644000175000017500000000135614567450071015330 0ustar billbilltry(a, as, N)= { my(as1 = Mat([as[,2],-as[,1]])); my(g = a * as1^(-1)); if (matdet(g) != 1, error("not in Gamma0(N)")); if (denominator(g) == 1 && g[2,1] % N == 0, return); g = as1 * [0,-1;1,-1] * as1^(-1); if (g[2,1] % N, error("not in Gamma0(N)")); } check(A, N)= { my ([V,Ast] = A); for (i = 1, #V, my(d = Ast[i] - i); if (d <= 0, next); if (d == 1, try(V[i],V[i+1], N), d == 2, try(V[i],V[i+2], N), error("d > 2"))); } do(N) = check(mspolygon(N,1), N); for (N = 2, 40, do(N)) do(49) do(217) do(247) M = msinit(12,2); mspolygon(M,1) mspolygon(M) mspolygon(1) testlattice(N, k) = mslattice(msinit(N,k)); testlattice(11,2) testlattice(11,4) testlattice(30,4) M = msinit(8,4); mslattice(M, mseisenstein(M)[1]) pari-2.17.2/src/test/in/hypergeom0000644000175000017500000001237014676526175015310 0ustar billbilldefault(parisize,"10M") \\ 8M overflows testF(v, D0, D) = { for(i=1,#v, my (a,b,e, [n,d,z] = v[i]); localbitprec(D); a = hypergeom(n,d,z); localbitprec(D + 64); b = hypergeom(n,d,z); e = exponent(a/b - 1); if (e > -D0, print(i,": ", e)); ); } { localbitprec(320); v11=[ [0.1,0.2,0.5], [-0.1,0.2,0.5], [0.1,0.2,-0.5+I], [1+I,1+I,1-I], /*5*/ [10^(-8),10^(-8),10^(-10)], [10^(-8),10^(-12),-10^(-10)+10^(-12)*I], [1,1,10+10^(-9)*I], [1,3,10], [500,511,10], /*10*/ [8.1,10.1,100], [1,2,600], [100,1.5,2.5], [-60,1,10], [60,1,10], /*15*/ [60,1,-10], [-60,1,-10], [1000,1,10^(-3)], [10^(-3),1,700], [500,1,-5], /*20*/ [-500,1,5], [20,-10+10^(-9),-2.5], [20,10-10^(-9),2.5], [-20,-10+10^(-12),2.5], [50,10,200*I], /*25*/ [-5,(-5+10^(-9))*(1+I),-1], [4,80,200], [-4,500,300], [5,0.1,-2+300*I], [-5,0.1,2+300*I], /*30*/ [2+8*I,-150+I,150], [5,2,100-1000*I], [-5,2,-100+1000*I], [-5,-2-I,1+(2-10^(-10))*I], [1,10^(-12),1], /*35*/ [10,10^(-12),10], [1,-1+10^(-12)*I,1], [1000,1,-1000], [-1000,1,1000], [-10+500*I,5*I,10], /*40*/ [20,10+1000*I,-5]]; } print("1F1"); testF(v11, 128, 128) testF(v11, 256, 256) hypergeom([],[],-3.5) hypergeom(1.5,[],0.5) hypergeom(-0.5,[],3) hypergeom([],2.5,15) hypergeom([],2.5,-15) hypergeom([],2.5,15*I) v20=[[[1,1],[],-3], [[1,1],[],-3+10^-20*I], [[1,3/2],[],-3], [[1,-1],[],10^-4]]; print("2F0"); testF(v20, 128, 128) {localbitprec(320); v21=[ [[0.1,0.2],0.3,0.5], [[-0.1,0.2],0.3,0.5], [[0.1,0.2],-0.3,-0.5+0.5*I], [[10^(-8),10^(-8)],10^(-8),10^(-6)], [[10^(-8),-10^(-6)],10^(-12),-10^(-10)+10^(-12)*I], [[1,10],1,0.5+10^(-9)*I], [[1,-1+10^(-12)*I],1,-0.8], [[2+8*I,3-5*I],sqrt(2)-Pi*I,0.75], [[100,200],350,I], /*10*/ [[2+10^(-9),3],5,-0.75], [[-2,-3],-5+10^(-9),0.5], [[-1,-1.5],-2-10^(-15),0.5], [[500,-500],500,0.75], [[500,500],500,-0.6], [[-1000,-2000],-4000.1,-0.5], [[-100,-200],-300+10^(-9),0.5*sqrt(2)], [[300,10],5,0.5], [[5,-300],10,0.5], [[10,5],-300.5,0.5], /*20*/ [[2+200*I,5],10,0.6], [[2+200*I,5-100*I],10+500*I,0.8], [[2,5],10-500*I,-0.8], [[2.25,3.75],-0.5,-1], [[1,2],4+3*I,0.6-0.8*I], [[1,0.9],2,exp(I*Pi/3)], [[1,2.5],5,exp(I*Pi/3)], [[-1,0.9],2,exp(-I*Pi/3)], [[4,1.1],2,0.5+(0.5*sqrt(3)-0.01)*I], [[5,2.2],-2.5,0.49+0.5*sqrt(3)*I], /*30*/ [[2/3,1],4/3,exp(I*Pi/3)], [[1/2,5/2],5,3/4], [[1/2,1/5],3,3/5+9/10*I], [[1/2,1/5],3,3/5+I], [[-2,-4/5],-9/5,3/5], [[1,2],4,1], [[-1/2,-3/2],4,99/100], [[10,-1],2,1+I], [[1,-10],2,1+2*I], [[-2,1/2],1,100], /*40*/ [[-2,1/2],1,-100], [[3/2,3/2],1,0.97], [[3/2,3/2],1,1.03], [[3/2,-1/2],4/3,exp(I*Pi/3)], [[1/2,1/3],11/6, 101/100 + I/2^30] ]; } print("2F1"); testF(v21, 125, 128) testF(v21, 250, 256) v31=[[[1,1,2],[3],-3], [[1,1,2],[3],-3+10^-20*I], [[1,3/2,2],[3],-3], [[1,-1,2],[3],10^-4]]; print("3F1"); testF(v31, 128, 128) v32=[[[1,1,2],[3,I],-3], [[1,1,2],[3,I],-3+10^-20*I], [[1,3/2,2],[3,I],-3], [[1,-1,2],[3,I],10^-4]]; print("3F2"); testF(v32, 128, 128) localprec(115); hyperu(5/6,5/3,230) \\ cancellation in F11 hypergeom([1,1],2,-1.000000000000001) f(a,c)=exponent( hypergeom([a,2],c,(c-2)/(a-1)) - (a-1)*(c-1)/(a+1-c) ); for(j=28,32,print(j/5,": ",f(3,j/5))); f(4,1/5) hypergeom([3,2],3.4,0.7) hypergeom([1.5,2.1],[-3.5,1.1],1) a=sqrt(Pi)*(1-erfc(sqrt(2)))/sqrt(2)+exp(-2)/2-1/2; b=hypergeom([1/2,1],[3/2,2],-2); exponent(a-b) a=5/3; T1=hypergeom([1,1,1],[a,a],1); hypergeom([1,1,1],[a,a],-1) T2=hypergeom([2,1,1],[a+1,a+1],1) T3=hypergeom([2*a-1,1,1],[a+1,a+1],1) b=T1+(a-1)^2/(a^2*(2*a-3))*(T2-2*(a-1)*T3)-gamma(a)^2/((2*a-3)*gamma(2*a-2)); exponent(b) <= -122 airy(0) airy(I) airy(1) airy(100)[1] airy(-100)[2] hypergeom([1,1,1,1/2],[3/4,3/2,3/2],1) hypergeom([1,2,1,1,1,1/2],[1,2,3/4,3/2,3/2],1) F(k,a)=Pi^(k-1/2)*gamma(a)/(2^(3*k-1)*gamma(a+1/2))*hypergeom(concat(vector(k,j,1),1/2),concat(a+1/2,vector(k-1,j,3/2)),1); L=lfuninit(lfunetaquo([4,2;8,2]),[1,6,1],2); lindep([lfun(L,3),F(3,5/4),F(3,3/4),F(3,1/4)]) hypergeom([1/6,2/3],1/2,2) hypergeom([],[],x) hypergeom([2],[],x) hypergeom([2],[],1/2+x) hypergeom([2],[],1/2+x^2) hypergeom([2,1],[3],x) hypergeom([2,1],[3],1/2+x) hypergeom([2,1],[3],1/2+x^2) hypergeom([1/12,1/12],2/3,3) hypergeom([1/12,5/12],1/2,1323/1331) hypergeom([1/12,7/12],2/3,125/121) \\ #2382 f(a, b, c, r, t) = { my(A,B,C,R,T,z,Z); A = round(10*a)/10; B = round(10*b)/10; C = round(10*c)/10; R = round(10*r)/10; T = round(10*t)/10; z = 1 - r*exp(t*I*Pi); Z = 1 - R*exp(T*I*Pi); exponent(hypergeom([a,b],[c],z) - hypergeom([A,B],[C],Z)); } f(1.1, 1.3, 1.4, 0.8, -0.3) f(1.1, 0.3, 3.4, 0.1, -0.4) f(1.1, 0.3, 4.4, -0.3, 0.8) f(1.2, 0.3, 3.5, 0.2, -0.4) f(1.2, 0.3, 4.5, -0.3, 0.8) f(1.2, 1.2, 1.4, -0.3, 0.7) hypergeom([0,0],[1],2) \\ #2425 hypergeom([-1/3,-1/5], -1/3-1/5+1, 1+10^-10) hypergeom(,,4+O(2^10)) hypergeom([1,1],[1],3+O(3^10)) hypergeom([1,1],[1/3],1+O(3^10)) R=hypergeom([1/12,5/12],1/2,1323/1331+O(7^30)) algdep(R,4) hypergeom([1/6,2/3],5/6,80/81+O(5^160)) R=hypergeom([1/3,1/3],5/6,-4+O(2^100)) algdep(R,6) 3*hypergeom([1/3,1/2],5/6,4+O(2^80))+1 5*hypergeom([1/3,1/3],1/2,81+O(2^100))+1 hypergeom([1],['a,'b,'b],-x/256+O(x^4)) \\ #2551 b=9/10; hypergeom([b+2, b], 2*b, 2/3) \\ Errors, keep at end airy(O(x)) hypergeom("","",O(x)) hypergeom([2,1],0,1) hypergeom([2,1],[2,-1],1) hypergeom([2,3],1,1) hypergeom([1/2,1/2,1/2],[1/3,1/3], 1 - 10^-6) hypergeom([1,2,3,4],[],1/2) hypergeom(,,2+O(2^10)) hypergeom([1,1/3],1,3+O(3^10)) hypergeom([1/2,1/2],5/6,-4+O(2^80)) pari-2.17.2/src/test/in/ispower0000644000175000017500000000715214710142650014760 0ustar billbilldo(n)= my(k,z); if (k=ispower(n,,&z), print([k,z])); {v = [ 3^101*2^20, 3^101*2^101, 3^101*2^101*5, 2^20*3^15*5^5, 2^3*103^6, 2^5*103^10, 2^7*103^10, 2^15*103^10, 2^21*103^42, 2^35*103^70, 2^105*103^210, 103^100003, 541^121 ]; } for (i=1, #v, do(v[i])) for (i=1, 10^6, do(i)) \\#1259 do(-16) do(-64) do(-8) do(-8 * 103^6) do(-1/64) ispower(2,2^64) ispower(1/2,2^64) ispower(27,2^60) \\ #2145 for (i=1, #v, if (!ispowerful(v[i]), print(i))) ispowerful(5^3*(10^1000+1)^2) v = [1, 2^10, 2^15, 2^32, 2^64, 2^128]; /* correct = vector(#v); { for (k = 1, #v, my(u = v[k], s,t); for(i=u, u+10^4, if ((a = ispower(i,,&p)) && isprime(p), s += a; t += p); if (isprime(i), s ++; t += i); ); correct[k] = [s,t]; ) } */ { for (k = 1, #v, my(u = v[k], s,t); s = sum(i=u, u+10^4, isprimepower(i)); t = 0;for (i = u, u+10^4, if (isprimepower(i,&p), t += p)); print([s,t]); \\ if ([s,t] != correct[k], error(k)) ) } n=(2^100+277)^10; ispseudoprimepower(n) ispseudoprimepower(n,&p) p isprimepower(541^121) ispowerful(4) p = 10^6+3; q = 10^6+33; r = 10^6+37; v = [Mod(p, p^2*q), Mod(6*p, q*(p*r)^2), Mod(6, p^2*q), Mod(4*p, 8*p^2*q)]; [ispower(a,2) | a<-v] [ispower(a,3) | a<-v] [if(ispower(a,2,&b), b) | a<-v] [if(ispower(a,3,&b), b) | a<-v] [if(issquare(a^2,&b), b) | a<-v] [if(ispower(a^3,3,&b), b) | a<-v] ispower(Mod(2, 7*5^3), 7, &z); z issquare(Mod(1,2)) issquare(Mod(0,2),&s);s issquare(Mod(2,3)) issquare(Mod(13,121)) issquare(Mod(Mod(1,2)*y,y^3+y^2+1)) if (issquare(Mod(Mod(1,2)*y,y^3+y^2+1),&b),b) issquare(Mod(Mod(1,5)*y+2,y^3+y^2+1)) if (issquare(Mod(Mod(1,5)*y,y^3+y^2+1),&b),b) if (issquare(Mod(Mod(4,5),y^3+y^2+1),&b),b) if(issquare(Pol(0),&z),z) issquare(Pol(4)) issquare(x^2+x) issquare(y^2*x^0) issquare(x^0/4) if(issquare(y^2*x^0,&z),z) issquare(2*x^4+x^3+Mod(1,2)) issquare(x^2+Mod(1,2)) if(issquare(x^2+Mod(1,2),&z),z) t=ffgen(2^3,'t); if(issquare((t*x^2+(1+t)*x+1)^2,&z),z) if(issquare((x^4+x^3+3*x^2+2*x+4)*Mod(1,5),&z),z) if(issquare(4/x^2,&z),z) issquare(1.5) if(issquare(1.5,&z),z) issquare(4/9) issquare(4/3) issquare(I) issquare(ffgen(2^3,'t)) if(issquare(ffgen(2^3,'t),&z),z) issquare(ffgen(3^2),&z) issquare(O(x)) issquare(x+O(x^2)) issquare(4*x^2+O(x^3)) issquare(4/x^2) if (issquare(x^0/4,&z),z) if (issquare((x+1/2)^2,&z),z) if (issquare(x^0/4,&z),z) issquare(Mod(1,4)*x^2) issquare(Mod(1,4)*(x+1)^2) issquare(Mod(x,Mod(x^2+x+2,3))) ispower(-8,4) if(ispower(-8,3,&z),z) ispower(-8/27,3) if(ispower(-8/27,3,&z),z) ispower(Pol(0),3) ispower(x^2,3) ispower(x^3+x,3) ispower(x^3+4,3) if(ispower(Pol(8),3,&z),z) if(ispower((2+x)^3,3,&z),z) ispower((2+x)^3-1,3) ispower(1009^11) ispower(-1.,3) ispower(I,3) if(ispower(1/(2*x)^3,3,&z), z) if(ispower(1+x+O(x^2),3,&z), z) if(ispower((-2/3)^5,5,&z),z) ispower(3^(11^2)) ispower((2/3)^(11^2)) ispower(30011^(17*11)) issquare(Mod(3,22)) \\#2578 issquare(Mod(474761,2925306656167)) \\#1703 ispower(-167^10) \\#1782 isprimepower(30011^(17*3)) do(f,k) = ispower(f,k,&z) && z^k == f; test(t) = { my(T = 5*t*(x^3+x^2+t)*(x^2+t*x+1)^3); [do(T,3), do(T^6,3), do(T^9,3), do(T^18,3), do(T^18,9), do(T^18,18)]; } test(Mod(1,2)) test(Mod(1,3)) test(Mod(1,17)) test(Mod(1,nextprime(2^100))) test(ffgen(2^3,'t)) test(ffgen(3^3,'t)) test(ffgen([nextprime(2^100),3],'t)) test(Mod(Mod(1,2),y^3+y^2+1)) ispower(Mod(x,x^2+1), 2, &y) ispower(Mod(x,x^2+1), 2) p=2^1500+1465; ispower(p^11) ispower(p^29) ispower(p^101) \\#1915 issquare(Mod(1,67)*x^4+Mod(14,67)*x^2+Mod(49,67)) \\#2289 if (issquare((-1+2*x-x^2)/(-4+4*x-x^2),&z), z) issquare((-1+2*x-x^2)/(-4+4*x-x^2)) if (ispower(-(1+x)^20/-(2+x)^20,20,&z), z) ispower(-(1+x)^20/-(2+x)^20,20) \\#2543 a=22548^7516; ispower(a^3, 3) ispower(a^5, 5) ispower(a^31, 31) pari-2.17.2/src/test/in/characteristic0000644000175000017500000000046214567450071016266 0ustar billbillv=[1,1.,Mod(1,6),1/2,I+Mod(1,3), O(2), quadgen(5)*Mod(1,3), Mod(1,x)]; for (i=1,#v, print(characteristic(v[i]))) characteristic(v) characteristic(matid(2)*Mod(1,2)) characteristic([]) characteristic(List()) characteristic(ffgen(2^3)) characteristic([ffgen(2),ffgen(3)]) characteristic([ffgen(2),Mod(1,3)]) pari-2.17.2/src/test/in/genus20000644000175000017500000000015514676526175014512 0ustar billbillC=[x^6+a*x+b,x^5+a*x+b,[x^6,x^3+a*x+b]]; L=2*[0..5]; foreach(C,c,foreach(L,l,print([c,l,genus2igusa(c,l)]))) pari-2.17.2/src/test/in/gchar-lfun0000644000175000017500000002335514676526175015344 0ustar billbilldefault(parisize,"78M"); \\ overflows 76M lfunrobustcheckfeq(ldata) = { my(bit = getlocalbitprec(), extrabit = 0); while(1, localbitprec(bit + extrabit); my(t = lfuntheta(ldata, 3/Pi)); if (exponent(t) + extrabit >= 0, return (lfuncheckfeq(ldata, 3/Pi))); extrabit = -exponent(t)+5); } print("Watkins 6.3"); bnf = bnfinit(polcyclo(5),1); pr = idealadd(bnf,5,x-1); gc1 = gcharinit(bnf,idealpow(bnf,pr,2)); {c = gcharidentify(gc1,[1,2],[ [4,172.18925621407521183008840153751455639], [3,-172.18925621407521183008840153751455639] ])}; gcharconductor(gc1,c) gcharconductor(gc1,5*c) gcharconductor(gc1,20*c) J = idealprimedec(bnf,163)[1]; bestappr(gchareval(gc1,c,J),10^6) dec = idealprimedec(bnf,11); t1 = dec[3]; t2 = dec[4]; t3 = dec[2]; t4 = dec[1]; exponent(nfeltembed(bnf,x) - [exp(2*I*Pi*2/5),exp(2*I*Pi/5)]) < -100 [chi] = gcharalgebraic(gc1,[[1,2],[3,0]]); chi[#chi] round(10^10*gchareval(gc1,chi,t1)) round(10^10*gchareval(gc1,chi,t3)) exponent(gchareval(gc1,chi,t4)/conj(gchareval(gc1,chi,t1)) - 1) < -100 exponent(gchareval(gc1,chi,t3)/conj(gchareval(gc1,chi,t2)) - 1) < -100 L = lfuncreate([gc1,chi]); lfunparams(L) lfunrootres(L)[3] == 1 {exponent(lfun(L,2) - gamma(1/5)^3*gamma(2/5)^3/(5^(7/2)*gamma(3/5)^2*gamma(4/5)^2)) < -100} gcharalgebraic(gcharinit(bnf,1),[[2,1],[3,0]]) gc = gcharinit(bnf,pr); [chi] = gcharalgebraic(gc,[[2,1],[3,0]]); chi[#chi] L = lfuncreate([gc,chi]); lfunparams(L) lfunrootres(L)[3] == 1 {exponent(lfun(L,2) - Pi*gamma(1/5)^(7/2)*gamma(3/5)^(1/2)/ (5^(15/4)*gamma(4/5)^(7/2)*gamma(2/5)^(1/2))) < -100} gc2 = gcharinit(bnf,idealpow(bnf,pr,2)); c = gcharidentify(gc2,[1,2],[[-1,0],[3,0]]); c=concat(c,-3/2); gcharconductor(gc2,c) t = idealadd(bnf,11,x-5); bestappr(gchareval(gc2,c,t),10^6) LL = lfuncreate([gc2,c]); lfuncheckfeq(LL) + 110 < 0 {c = gcharidentify(gc2,[1,2],[ [0,-1.6321256513182484533657668392181474539], [0,1.6321256513182484533657668392181474539] ])}; gcharconductor(gc2,c) gcharconductor(gc2,4*c) print("Watkins 3.7 & 6.1"); bnf = bnfinit(x^2+23); gc = gcharinit(bnf,1); pr = idealprimedec(bnf,31)[2]; c0 = gcharidentify(gc,[1,pr],[[0,0],1/3]); /* class group char, order 3 */ J = idealprimedec(bnf,23)[1]; bestappr(gchareval(gc,c0,J),10^6) p = nextprime(1010); J = idealadd(bnf,p,x-459); bestappr(gchareval(gc,c0,J),10^6) bestappr(gchareval(gc,c0,J)^3,10^6) l0=lfuncreate([gc,c0]); lfuncheckfeq(l0) + 110 < 0 gcharconductor(gc,c0) round(10^10*lfun(l0,1)) print("c of infinity type (2,0)"); c1 = gcharidentify(gc,[1,pr],[[2,0],0.32447859496968861348669094505138887338]); c2 = c1+c0; c3 = c1+2*c0; J = idealadd(bnf, 1013, x-459); bestappr(gchareval(gc,c1,J),10^6) bestappr(gchareval(gc,c2,J),10^6) bestappr(gchareval(gc,c3,J),10^6) J = idealprimedec(bnf,23)[1]; bestappr(gchareval(gc,c1,J),10^6) bestappr(gchareval(gc,c2,J),10^6) bestappr(gchareval(gc,c3,J),10^6) J = idealadd(bnf, 10007, x-4917); bestappr(gchareval(gc,c1,J),10^6) bestappr(gchareval(gc,c2,J),10^6) bestappr(gchareval(gc,c3,J),10^6) l1=lfuncreate([gc,c1]); lfuncheckfeq(l1) + 110 < 0 l2=lfuncreate([gc,c2]); l3=lfuncreate([gc,c3]); lfun(l1,1)*lfun(l2,1)*lfun(l3,1); gcharconductor(gc,c1) gcharconductor(gc,c2) gcharconductor(gc,c3) [chi] = gcharalgebraic(gc,[[2,0]]) ps = [1,0,0]~; v1 = lfun([gc,chi+2*ps],2); round(10^10*v1) v2 = lfun([gc,chi],2); round(10^10*v2) v3 = lfun([gc,chi+ps],2); round(10^10*v3) {exponent(v1*v2*v3 - Pi^3/(23^3*3*sqrt(23))*prod(i=1,22,gamma(i/23)^kronecker(i,23))) < -100 } exponent(v1*v2*v3 - Pi^2/5*lfun([gc,3*chi],4)) < -100 p23 = idealprimedec(bnf,23)[1]; round(10^10*gchareval(gc,chi,p23)) lfunrootres(lfuncreate([gc,chi]))[3] == 1 print("Watkins examples 6.2"); bnf = bnfinit(x^2+59); p59 = idealprimedec(bnf,59)[1]; p3 = idealismaximal(bnf,idealadd(bnf,3,(x+1)/2)); gc = gcharinit(bnf,p59); chi0 = gcharidentify(gc,[1,p3],[[-3,0],-0.36762114624267865716245886781141036535]); chi = concat(chi0,-3/2); gcharisalgebraic(gc,chi,&pq) pq L = lfuncreate([gc,chi]); lfunparams(L) lfunrootres(L)[3] == 1 round(10^30*lfun(L,2)) == 0 round(10^30*lfun(L,2,1)) == 0 round(10^20*lfun(L,2,2)) print("S intersects mod"); pol = x^3 + 4*x - 1; K = bnfinit(pol); pr2 = idealprimedec(K, 2)[1]; N1 = idealpow(K,pr2,2); gc1 = gcharinit(K,N1); pr = idealprimedec(K, 31)[1]; c1 = gcharidentify(gc1,[2,pr],[[0,0],1/2]); {c3 = gcharidentify(gc1,[2,pr],[ [0,2.2418452596254755362005770232711966272], -0.45978232175146932821099066000626766106 ])}; {c4 = gcharidentify(gc1,[2,pr],[ [1,-0.58227723543626532811523658572496519901], 0.16449709689005690003280624571231977687 ])}; J = idealhnf(K,29); bestappr(gchareval(gc1,c1,J),10^6) bestappr(gchareval(gc1,c3,J),10^6) bestappr(gchareval(gc1,c4,J),10^6) J = idealadd(K, 31, x+7); bestappr(gchareval(gc1,c1,J),10^6) bestappr(gchareval(gc1,c3,J),10^6) bestappr(gchareval(gc1,c4,J),10^6) J = idealadd(K, 37, x^2+7*x+16); bestappr(gchareval(gc1,c1,J),10^6) bestappr(gchareval(gc1,c3,J),10^6) bestappr(gchareval(gc1,c4,J),10^6) lfuncheckfeq(lfuncreate([gc1,c1])) + 110 < 0 lfuncheckfeq(lfuncreate([gc1,c3])) + 100 < 0 lfuncheckfeq(lfuncreate([gc1,c4])) + 100 < 0 gcharconductor(gc1,c1) gcharconductor(gc1,c3) gcharconductor(gc1,c4) gcharconductor(gc1,2*c4) print("billtest"); K = bnfinit(x^3 - x^2 - 2*x + 1,1); gc1 = gcharinit(K,1); {chi1 = gcharidentify(gc1,[1,2],[ [0,-1.4673521224309881879754400022419048262], [0,-4.1066886637013372713813245582861326619] ])}; gcharconductor(gc1,chi1) L1 = lfuncreate([gc1,chi1]); lfuncheckfeq(L1) + 100 < 0 gc2 = gcharinit(K, [1, [1,1,0]]); {chi2 = gcharidentify(gc2,[1,2],[ [1,0.73367606121549409398772000112095241311], [1,2.0533443318506686356906622791430663310] ])}; L2 = lfuncreate([gc2,chi2]); gcharconductor(gc2,chi2) gcharconductor(gc2,2*chi2) lfuncheckfeq(L2) + 100 < 0 L2 = lfuncreate([gc2,2*chi2]); lfuncheckfeq(L2) + 100 < 0 gc3 = gcharinit(K,[4,[1,1,1]]); {chi3 = gcharidentify(gc3,[1,2,3],[ [1,2.0533443318506686356906622791430663310], [1,-2.7870203930661627296783822802640187441], [1,0.73367606121549409398772000112095241312] ])}; L3 = lfuncreate([gc3,chi3]); gcharconductor(gc3,chi3) gcharconductor(gc3,2*chi3) lfuncheckfeq(L3) + 100 < 0 L3b = lfuncreate([gc3,concat(chi3,[1])]); lfuncheckfeq(L3b) + 100 < 0 {chi4 = gcharidentify(gc3,[1,2,3],[ [1,4.1066886637013372713813245582861326619], [1,-5.5740407861323254593567645605280374882], [1,1.4673521224309881879754400022419048262] ])}; gcharconductor(gc3,chi4) gcharconductor(gc3,2*chi4) L4 = lfuncreate([gc3,chi4]); lfunrobustcheckfeq(L4) + 120 < 0 print("L function with imaginary shifts"); \\[gc,chi]=gcharfromlabel("4.2.507.1/1.1/3/1.0.0") gc = gcharinit(x^4 - x^3 - x^2 - x + 1,[1,[1,1]]); round(gc.cyc) {chi1 = gcharidentify(gc,[1,3],[ [1,-1.3147344210693290321693125780535053706], [0,1.3147344210693290321693125780535053706] ])}; lfuncheckfeq([gc,chi1]) < -100 {chi2 = gcharidentify(gc,[1,3],[ [0,-7.0946607083506471720248332314490400999], [0,1.3147344210693290321693125780535053706] ])}; lfunrobustcheckfeq([gc,chi2]) < -105 {chi3 = gcharidentify(gc,[1,3],[ [0,2.7549396985213395830142521579776520629], [1,-0.65736721053466451608465628902675268531] ])}; lfuncheckfeq([gc,chi3]) < -100 lfunrobustcheckfeq([gc,10*chi1-chi2]) < -90 /* FIXME: precision loss */ print("need to increase prec II"); pol = x^4 - 2*x^3 + 5*x^2 - 2*x - 1; bnf = bnfinit(pol); N = (2*5)^2; gc = gcharinit(bnf,N); pr1 = idealprimedec(bnf,101)[1]; pr2 = idealprimedec(bnf,103)[1]; pr3 = idealprimedec(bnf,107)[1]; {chi = gcharidentify(gc,[1,2,3,pr1,pr2,pr3],[ [0,-0.35297367876409751322089068292993762448], [0,-0.041073660200364481585974033215524566169], [0,0.39404733896446199480686471614546219065], -0.40535854092646927907556107107771780521, 0.24130145922641757913465361319347185751, 0.49348754119067815440785147793690542365 ])}; pr4 = idealadd(bnf, 127, x-53); bestappr(gchareval(gc,chi,pr4,0),10^6) gcharconductor(gc,chi) L=lfuncreate([gc,chi]); \\L[3..5] lfuncheckfeq(L) < -100 print("bug"); bnf = bnfinit(y,1); gc = gcharinit(bnf,2^5*3^2); /* FIXME workaround bug 2335 */ localbitprec(gc[8][1][2]*64);gc[2][7][6] = [0.]; p1 = idealprimedec(bnf,101)[1]; p2 = idealprimedec(bnf,127)[1]; c = gcharidentify(gc,[p1,p2],[1/4,0]); print(gcharconductor(gc,c)); L = lfuncreate([gc,c]); lfunrobustcheckfeq(L)+120<0 c = gcharidentify(gc,[p1,p2],[3/8,0]); print(gcharconductor(gc,c)); L = lfuncreate([gc,c]); lfunrobustcheckfeq(L)+120 < 0 c = gcharidentify(gc,[p1,p2],[1/24,-1/2]); print(gcharconductor(gc,c)); L = lfuncreate([gc,c]); lfunrobustcheckfeq(L)+120<0 bnf = bnfinit(y^2-5); N = idealadd(bnf, 10, y+5); gc = gcharinit(bnf,N); c = gcharidentify(gc,[1],[[0,-1.0880837675454989689105112261454316359]]); L = lfuncreate([gc,c]); round(gchareval(gc,c,3)) lfunrobustcheckfeq(L)+120<0 N = idealadd(bnf, 142, y+125); gc = gcharinit(bnf,N); print("bug from Atelier demo"); bnf = bnfinit(x^2+5,1); gc = gcharinit(bnf,1); chi = [1,0,-1]~; L = lfuncreate([gc,chi]); round(lfunan(L,5)) print("norm component fix"); bnf = bnfinit(x^2-5); gc = gcharinit(bnf,1); chi = [1,-1]~; L = lfuncreate([gc,chi]); round(10^6*lfunparams(L)) round(lfunan(L,10)) print("over Q"); bnf = bnfinit(y,1); gc = gcharinit(bnf,1); chi = [1]~; L = lfuncreate([gc,chi]); lfunparams(L) lfunan(L,10) lfuncheckfeq(L) < -100 gc = gcharinit(bnf,4); chi = [1]~; L = lfuncreate([gc,chi]); lfunparams(L) lfunan(L,10) lfuncheckfeq(L) < -100 gc = gcharinit(bnf,60); chi = [0,0,1]~; L = lfuncreate([gc,chi]); lfunparams(L) lfunan(L,10) lfuncheckfeq(L) < -100 print("shifted zeta_K"); bnf = bnfinit(x^2-5,1); gc = gcharinit(bnf,1); chi = [0,1]~; L = lfuncreate([gc,chi]); lfunparams(L) lfunan(L,10) lfuncheckfeq(L) < -100 gc = gcharinit(bnf,60); chi = [0,0,0,1]~; L = lfuncreate([gc,chi]); lfunparams(L) lfunan(L,10) lfuncheckfeq(L) < -100 print("bad inputs"); bnf = bnfinit(x^4 - x^3 + 3*x^2 + 2*x + 1, 1); gc = gcharinit(bnf, 1); lfuncreate([gc,[1]~]); lfuncreate([gc,[1,0,0,'x]~]); lfuncreate([gc,[1,0,0,0,I]~]); \\don't put tests after the errors pari-2.17.2/src/test/in/nflist0000644000175000017500000000662114676526175014612 0ustar billbilldefault(parisize,"28M"); \\ overflows 26M on aarch64 do(G, lim)= { my(B = [1, 10^lim], field, D, v, T); print("group = ",G); nflist(G,1); nflist(G,1,0); nflist(G,1,1); nflist(G,1,2); nflist(G,1,-2); v = nflist(G,B,-2); print(apply(length,v)); print(vector(#v, i, #nflist(G,B,i-1))); v = concat(v); if (!#v, return); T = v[1]; print([field,cond]=nfresolvent(T,1)); print(nfresolvent(T,2)); v = nflist(G,B,,field); if (G == "D4", v = apply(polredabs,v)); \\ avoid 32 bit difference print(if (#v > 10, #v, v)); print(D = abs(nfdisc(T))); print(nflist(G,D)); print(nflist(G,D,,field)); } { vG=[ ["C1",1], ["C2",4], ["C3",10],["S3",4], ["C4",8],["V4",8],["D4",3],["A4",5],["S4",3.85], ["C5",10],["D5",4],["F5",5], ["C6",10],[[6,2],8],[[6,3],5],[[6,4],7],[[6,5],5],[[6,6],6],[[6,7],5], [[6,8],6],[[6,9],5.5],[[6,10],6],[[6,11],5],[[6,13],4.5], ["C7",15],["D7",6],["M21",9],["M42",6], ["C9",12],[[9,2],12],["D9",9], ["C11",17],["D11",10] ];} for(i=1,#vG,my([GP,lim]=vG[i]); do(GP,lim)); nflist([11,1], 41426511213649) nfresolvent(x) T=x^5-x^4+2*x^2-2*x+2; nfresolvent(T) T=polsubcyclo(53,13); nfresolvent(T,1) T=x^13-x^12-50*x^11+25*x^10+722*x^9-226*x^8-4207*x^7+1158*x^6+10465*x^5-2535*x^4-9399*x^3+1079*x^2+1316*x-49; nfresolvent(T,1) T=x^4+14*x^2+1; nfresolvent(T,3) T=x^7-8*x^5-2*x^4+16*x^3+6*x^2-6*x-2;nfresolvent(T,3) T=x^7-2;nfresolvent(T,3) T=x^7-2*x^6-2*x^5+x^4+6*x^3-x-4;nfresolvent(T,3) T=x^6+2*x^5-9*x^4-14*x^3+10*x^2+8*x+1;nfresolvent(T) nfresolvent(T,3) T=x^6-3*x^5+7*x^4-9*x^3+7*x^2-3*x+1;nfresolvent(T,3) T=x^9-15*x^7-4*x^6+54*x^5+12*x^4-38*x^3-9*x^2+6*x+1;nfresolvent(T,3) nfresolvent(x^5-x-1) nfresolvent(x^9-6669*x^7-40014*x^6+13304655*x^5+124923708*x^4-7296039387*x^3-42603746094*x^2+931129781400*x+6414841742400) \\ regression tests nflist("C2",[3.5,4.5]) nflist("D5",10^6) nflist("D5",[717000,717409],2) nflist("D5",6250000) #nflist("D4",[201,1000]) #nflist("C6",[1,10^10],,x^2-2) nflist("C6",16807,-2) nflist("C2",125,-2) nflist("C4",8000,-2) nflist("S3",756,-2) nflist("S3",,-2) nflist("S4",193) nflist("F5",2382032,-2) nflist([6,3],91125,-2) nflist("C9",31381059609,-2) nflist("D9",775511104,-2) nflist("D9",6740083091889) #nflist([6,6],[100000,150000]) #nflist([6,11],[20000,30000]) #nflist([6,11],[1,100]) #nflist([6,10],[802816, 2175624]) nflist("D2") nflist("D3") #nflist("C4", [5000,10000], 0) nflist("C4",0) nflist("C4",[0,0]) nflist("C2",2^64+1) nflist("C2",2^64+3) nflist("C2",2^64) nflist("C2",2^64+4) nflist("C2",2^64+8) nflist("C2",2^64+12) nflist("C4",(2^64+1)^3) nflist("C4",(2^64+8)^3) nflist("C4",2^192) nflist("D4",100,,x^2+1) nflist("D4",21^2,,x^2+x+1) nflist("A4",[1,10^4],,x^3-x-1) nflist("C6",1229312,,x^3-x^2-2*x+1) nflist("C6",[1229312,2*10^6],,x^3-x^2-2*x+1) nflist([6,2],29791,,x^2-x+8) nflist([6,2],[29791,30000],,x^2-x+8) nflist([6,3],[1,10^5],,x^3+x-1) nflist([6,7],[52441,52442]) nflist("S4",404*(37*43*97)^2,,x^3-x^2-5*x-1) nflist("S4",404*(11*43*97)^2,,x^3-x^2-5*x-1) nflist("S4",7537*(13*37*79)^2,,x^3-7*x^2-8*x+1) nflist("S3",2673) nflist("C11",,-2) nflist([5,3],,-2) nflist("C1") nflist("C3") nflist("C4") nflist("V4") #nflist("D4") nflist("A4") nflist("S4") nflist("C5") nflist("D5") nflist("F5") \\ #2567 nflist([6,1],64827) nflist([6,8],12167); nflist([6,10],36192256) \\ ERRORS nflist("S3",-1) nflist("S3",[-1,2]) nflist("S3",[1,-2]) nflist("S5") nflist([10,1]) nflist([9,9]) nflist([11,3]) nflist("M21",[1,10^4],,x) nflist("C3",x) nflist("C3",[x]) pari-2.17.2/src/test/in/lambert0000644000175000017500000000300114676526175014726 0ustar billbilldo(y,k)=my(x = lambertw(y,k)); exponent(exp(x)*x / y-1); do(-1) do(I) do(2) mie = -exp(-1); vecmax(vector(64, k, do(mie - 2^-k))) <= -112 default(realprecision,211); do(1e14) <= -700 DO(y)= { my(x = lambertw(y), e = normlp(Vec(exp(x)*x - y))); if (e > 2e-37, error([e, y])); } default(realprecision,38); DO(O(x^10)) DO(O(x^30)) DO(3+O(x^10)) DO(3+O(x^30)) DO(x) DO(x+O(x^10)) DO(x+O(x^30)) DO(3+O(x)) DO(3+x) DO(3+x+O(x^10)) DO(3+x+O(x^30)) DO(x^2-2*x^3) DO(x^2-2*x^3+O(x^10)) DO(x^2-2*x^3+O(x^30)) DO(3+x^2-2*x^3) DO(3+x^2-2*x^3+O(x^10)) DO(3+x^2-2*x^3+O(x^30)) serlaplace(sin(lambertw(x + O(x^5)))) lambertw(mie + x^2 + O(x^10)) \p115 do(-2^(-600),-1) for(b=-4,4,print(lambertw(-0.1,b))); do(-0.3678,0) <= -383 do(-0.3678,-1) <= -383 lambertw(-10^(-100),0) lambertw(-10^(-100),-1) do(lambertw(precision(-0.1,38),-1)) \p38 lambertw(10^1000) \\ #2429 vector(10,mul,round(10^4*abs(lambertw(mie,mul)))) vector(10,mul,round(10^4*abs(lambertw(mie,10*mul)))) bra(y,k)=if(k!=-1||imag(y)||y>0||y=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=random([-1000,30000]); Q=qfbsolve(q,r,1);Q2=qfbsolve(q2,r,1)); if(Q2==0||!chk(q2,Q2,r),print("qfbsolve(",q2,",",r,")!=",Q2);break); if(Q==0 ||!chk(q,Q,r),print("qfbsolve(",q,",",r,")!=",Q);break)); } bqfb(); test(v,N,flag=1)= { my([a,b,c]=v, q=Qfb(a,b,c)); for(i=-N,N,my(Q=qfbsolve(q,i,flag)); if(Q,if(!chk(q,if(flag%2,Q,[Q]),i),error([v,N])); print(v,":",i,":",Q))); } test([1,1,1],30); test([1,29,271],300); test([1,29,271],300,2); test([1,29,271],300,3); test([2,1,3],30); test([3,4,5],30); test([3,4,5],30,2); test([3,4,5],30,3); test([5,1,-9],30); test([5,16,7],30); test([5,16,7],30,2); test([5,16,7],30,3); N=2^128+1; F=[59649589127497217,1;5704689200685129054721,1]; qfbsolve(Qfb(1,0,1),F) qfbsolve(Qfb(1,0,1),F,1) qfbsolve(Qfb(1,0,1),[N,F]) qfbsolve(Qfb(1,0,1),[N,F],1) qfbsolve(Qfb(5,16,7),factor(-30),1) qfbsolve(Qfb(1,0,7*16),128,1) qfbcornacchia(1,113) qfbcornacchia(1,4*113) qfbcornacchia(1,4*109) qfbcornacchia(24, 122838793181521) forprime(p=2,100,if (v=qfbcornacchia(3,4*p),print([p,v]))) forprime(p=10^3,10^4,if (v=qfbcornacchia(1009,p),print([p,v]))) \\ incorrect factorization qfbsolve(Qfb(1,0,1),Mat([2^198-3,1])) qfbsolve(Qfb(1,0,1),Mat([2^198-3,1]),1) \\ ERRORS qfbsolve(Qfb(1,0,1),1,4) pari-2.17.2/src/test/in/lindep0000644000175000017500000000216614567450071014554 0ustar billbilllindep([sqrt(2), sqrt(3), sqrt(2)+sqrt(3)]) lindep([1, 2 + 3 + 3^2 + 3^3 + 3^4 + O(3^5)]) lindep([1,2,3;4,5,6;7,8,9]) lindep([x*y, x^2 + y, x^2*y + x*y^2, 1]) lindep([0*x]) z = sqrt(1+5*y+y^2+y^3); seralgdep(z, 2,3) seralgdep(z, 2,2) seralgdep(1/(1-y+O(y^5)), 1,1) seralgdep(1+5*y+O(y^3), 1,10) seralgdep(Ser([0,1,0,u]*Mod(1,(u^2+u+1)*Mod(1,2)),y),2,2) S=sum(i=0,50,binomial(3*i,i)*T^i)+O(T^51); seralgdep(S, 3, 3) serdiffdep(S, 3, 3) serdiffdep(exp(T^2)+T^2,3,3) lindep([]) lindep([0]) lindep([1]) lindep([1,I]) algdep(1,0) algdep(1,-1) z=sqrt(2+O(7^4)); algdep(z,2) z=Mod(-85995*a-52515,a^2-a-1); algdep(z,1) algdep(z,2) lindep(Mod([E*x, E*x + E, E^2*x^2 + E*x + 2*E], E^3)) lindep([[1,0,0],[0,1,0],[1,1,0]]) lindep([[1,0,0]~,[0,1,0]~,[1,1,0]~]) lindep([[1,0,0]~,[0,1,0]~,[1,1,1]~]) lindep([[1,0,0]~,[0,1,0],[1,1,0]]) lindep([[1,0,0]~,[0,1,0]~,[1,1,0]~]) T=polcyclo(5,'t); zT = polroots(T)[1]; bestapprnf(sqrt(5), T) bestapprnf(x*zT+sqrt(5), T, zT) bestapprnf([exp(2*I*Pi/5)+2], T, zT) z=sqrt(2); bestapprnf(z+1, x^2-2) bestapprnf(z+1, 4*x^2-2) T=x^3-2; vT=polroots(T); z=3*2^(1/3)+1; bestapprnf(z, T, vT[1]) type(bestapprnf(z, T, vT[2])) pari-2.17.2/src/test/in/variable0000644000175000017500000000063514567450071015065 0ustar billbillv=[1,O(3),x,O(x),Mod(y,y^2+1),1/y,[y,z],Mat(z),List(),List([y,z])]; { for(i=1,#v, print(iferr(variable(v[i]), E,E)) ) } variable() varhigher("y"); tt=varlower("y"); variable() zz=varhigher("y",x); variable() varhigher("y",zz); variable() varlower("y",zz); variable() varlower("y",tt); variable() varlower("tt",y); varhigher("y",y); variable() varhigher("zzz",y);1/0 variable() variables([v,tt,zz]) variables() pari-2.17.2/src/test/in/subcyclo0000644000175000017500000000133414567450071015120 0ustar billbillpolsubcyclo(8,1) polsubcyclo(1048,2) polsubcyclo(11,3) polsubcyclo(15,4) polsubcyclo(16,4) polsubcyclo(13*17*29,4) polsubcyclofast(11,3) polsubcyclofast(15,4) polsubcyclofast(15,4,1) polsubcyclofast(15,4,-1) polsubcyclofast(16,4) polsubcyclofast(16,4,1) polsubcyclofast(16,4,-1) polsubcyclofast(16,4,,1) polsubcyclofast(13*17*29,4) polsubcyclofast(13*17*29,4,1) polsubcyclofast(13*17*29,4,1,1) polsubcyclofast(13*17*29,4,-1) polsubcyclofast(13*17*29,4,-1,1) polsubcyclofast(13*17*29,-4) polsubcyclofast(13*17*29,-4,1) polsubcyclofast(13*17*29,-4,-1) polsubcyclofast(13*17*29,-4,,1) polsubcyclofast(10^17+21,5) polsubcyclofast((10^17+21),5,,1) polsubcyclofast(10^17+3,7) polsubcyclofast(10^7+189,11) polsubcyclofast(10^5+153,13) pari-2.17.2/src/test/in/bit0000644000175000017500000000123314567450071014051 0ustar billbillhammingweight(15) hammingweight(x^100 + 2*x + 1) hammingweight([Mod(1,2), 2, Mod(0,3)]) hammingweight(Vecsmall([0,1,2,3])) hammingweight(matid(100)) hammingweight(I) N = 2^128+2^64+1; [bittest(N, i) | i<-[60..70]] { args = [0, 3, -3, 2^65-1, N, -N, I]; funs = [bitand, bitnegimply, bitor, bitxor]; for (a=1,#funs, my (f = funs[a]); print("#", f); for (i=1,#args, for (j=i,#args, my(u=args[i], v=args[j]); print([u,v,iferr(f(u,v),E,E)]) ) ) ); print("#bitneg"); for (i=1, #args, my (u=args[i]); print(iferr([u, bitneg(u,65),bitneg(u)],E,E)) ) } bittest(-1,10) bitneg(-2,64) bitneg(1,-2) bitneg(1,128) pari-2.17.2/src/test/in/multivar-mul0000644000175000017500000000077214567450071015740 0ustar billbill/* Multivariable Laurent polynomial bug finding */ /* 05 Jul 2007 Michael Somos */ x;y;z; pol(N, v)= { my(t = vector(N+1)); t[N+1] = 1; for (i=1,#v, my(n = v[i]); if (n < 1, t[1] = 1 , t[(n-1) \ 2 + 1] = if (n%2,1/y,1/z))); Polrev(t); } /* Attempt to multiply two polynomials in x */ f(N,M,v,w)= iferr(pol(N,v)*pol(M,w); 0, E, 1); {doit(N,M)= forvec(v=[[0,2*N],[0,2*N],[0,2*N]], forvec(w=[[0,2*M],[0,2*M]], if(f(N,M,v,w), print([N,M],v,w)),2),2); } doit(9,9); pari-2.17.2/src/test/in/mathnf0000644000175000017500000000546014760137375014562 0ustar billbill\e mathnf([0,2]) mathnf([0,2], 1) mathnf([0,x]) mathnf([0,x], 1) mathnf([x;1]) mathnf([x;1], 1) mathnf([x,x^2+1; x^3+x+1, x+2]*Mod(1,5)) v=[116085838, 181081878, 314252913,10346840]; [H,U]=mathnf(v, 1); [v*U, norml2(U)] [H,U]=mathnf(v, 5); [v*U, norml2(U)] M=[0,0,0,0,0,0,0,0,0,13;0,0,0,0,0,0,0,0,23,6;0,0,0,0,0,0,0,23,-4,-7;0,0,0,0,0,0,17,-3,5,-5;0,0,0,0,0,56,16,-16,-15,-17;0,0,0,0,57,24,-16,-25,2,-21;0,0,0,114,9,56,51,-52,25,-55;0,0,113,-31,-11,24,0,28,34,-16;0,50,3,2,16,-6,-2,7,-19,-21;118,43,51,23,37,-52,18,38,51,28]; mathnf(M) M=[16*x^9-224*x^8+1176*x^7-2744*x^6+2401*x^5,0,0,0,0,0,16*x^9-224*x^8+1176*x^7-2744*x^6+2401*x^5,0,0,0,0,0,16*x^9-224*x^8+1176*x^7-2744*x^6+2401*x^5,0,0,0,0,0;0,-32*x^9+560*x^8-3920*x^7+13720*x^6-24010*x^5+16807*x^4,0,0,0,0,0,-32*x^10+560*x^9-3920*x^8+13720*x^7-24010*x^6+16807*x^5,0,0,0,422576*x^9-5916064*x^8+31059336*x^7-72471784*x^6+63412811*x^5,0,-32*x^10+560*x^9-3920*x^8+13720*x^7-24010*x^6+16807*x^5,0,0,0,0;0,0,64*x^9-1344*x^8+11760*x^7-54880*x^6+144060*x^5-201684*x^4+117649*x^3,0,0,0,0,0,32*x^10-560*x^9+3920*x^8-13720*x^7+24010*x^6-16807*x^5,0,0,0,0,0,64*x^11-1344*x^10+11760*x^9-54880*x^8+144060*x^7-201684*x^6+117649*x^5,0,0,0;0,0,0,-128*x^9+3136*x^8-32928*x^7+192080*x^6-672280*x^5+1411788*x^4-1647086*x^3+823543*x^2,0,0,0,0,0,-32*x^10+560*x^9-3920*x^8+13720*x^7-24010*x^6+16807*x^5,0,0,0,0,0,-128*x^12+3136*x^11-32928*x^10+192080*x^9-672280*x^8+1411788*x^7-1647086*x^6+823543*x^5,0,0;0,0,0,0,256*x^9-7168*x^8+87808*x^7-614656*x^6+2689120*x^5-7529536*x^4+13176688*x^3-13176688*x^2+5764801*x,0,0,0,0,0,32*x^10-560*x^9+3920*x^8-13720*x^7+24010*x^6-16807*x^5,0,0,0,0,0,256*x^13-7168*x^12+87808*x^11-614656*x^10+2689120*x^9-7529536*x^8+13176688*x^7-13176688*x^6+5764801*x^5,0;0,0,0,0,0,-512*x^9+16128*x^8-225792*x^7+1843968*x^6-9680832*x^5+33882912*x^4-79060128*x^3+118590192*x^2-103766418*x+40353607,0,0,0,0,0,-512*x^10+8960*x^9-62720*x^8+219520*x^7-384160*x^6+268912*x^5,0,0,0,0,0,-512*x^14+16128*x^13-225792*x^12+1843968*x^11-9680832*x^10+33882912*x^9-79060128*x^8+118590192*x^7-103766418*x^6+40353607*x^5]; [H,U]=mathnf(M,1); M*U[,1..12]==0 M*U[,13..18]==H mathnf([]) mathnf([],1) mathnf([;]) mathnf([;],1) mathnfmodid(matrix(0,2), []) mathnfmodid([0,7;-1,0;-1,-1], [6,2,2]) mathnfmodid([;],[2]) matsolvemod([;],[]~,[]~,1) matsolvemod([;],[],[]~,1) matsolvemod([;],[]~,[],1) matsolvemod([;],2,[1]~,1) matsolvemod([;],[2]~,[1]~,1) matsolvemod([;],[2]~,1,1) matsolvemod([;],1,1,1) matsolvemod([1,2;3,4],1,2,1) M=[2,1,1,0,0,-1,0,-1,1,0,-1,1,0,0,0,0;0,0,0,0,0,0,0,0,0,-2,0,0,-1,0,0,0;0,0,0,0,0,0,0,-1,-1,0,0,-1,0,0,0,0;0,0,0,0,0,0,0,0,0,0,0,-2,0,2,0,0;0,0,0,0,0,0,0,-1,1,0,0,-1,0,0,0,0;0,0,0,0,0,0,0,0,0,0,0,0,0,-2,0,0;0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0;2,0,0,1,1,1,0,2,2,0,2,0,2,2,3,2]; E=[0,0,0,0,0,0,0,2]~; B=[0,0,0,0,0,0,0,0]~; matsolvemod(M,B,E,0) \\ Errors, keep at end of file matsolvemod([;],[2]~,[2,3]~,1) pari-2.17.2/src/test/tune.c0000644000175000017500000007164714676526175014113 0ustar billbill/* Copyright (C) 2001 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* 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 "pari.h" #include "paripriv.h" int option_trace = 0; double Step_Factor = .01; /* small steps by default */ ulong DFLT_mod, DFLT_mod2, DFLT_deg; GEN LARGE_mod; typedef struct { ulong reps, type; long *var, *var_disable, *var_enable, var_enable_min, size, enabled; GEN x, y; ulong l; GEN T, 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; long *var_enable; } tune_param; /* ========================================================== */ /* To use GMP cycle counting functions, look for GMP in Oxxx/Makefile */ #ifdef GMP_TIMER /* needed to link with gmp-4.0/tune/{time,freq}.o */ int speed_option_verbose = 0; extern double speed_unittime; extern int speed_precision; void speed_starttime(void); double speed_endtime(void); #else static pari_timer __T; static double speed_unittime = 1e-4; static int speed_precision= 1000; static void speed_starttime() { timer_start(&__T); } static double speed_endtime() { return (double)timer_delay(&__T)/1000.; } #endif /* ========================================================== */ /* int, n words, odd */ static GEN rand_INT(long n) { pari_sp av = avma; GEN x, N = int2n(n*BITS_IN_LONG); do x = randomi(N); while (lgefint(x) != n+2); if (!mpodd(x)) x = addis(x,1); /*For Barrett REDC */ return gerepileuptoint(av, x); } /* real, n words */ static GEN rand_REAL(long n) { return gmul2n(itor(rand_INT(n), bit_accuracy(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_F2x(long n) { GEN x; do x = random_F2x(BITS_IN_LONG*(n+1), 0); 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; } static GEN rand_F2xqX(long n, GEN T) { GEN x; do x = random_F2xqX(n+1, 0, T); while (degpol(x) < n); return x; } static GEN rand_FlxqX(long n, GEN T, ulong l) { GEN x; do x = random_FlxqX(n+1, 0, T, l); while (degpol(x) < n); return x; } static GEN rand_FpXQX(long n, GEN T) { GEN x; do x = random_FpXQX(n+1, 0, T, LARGE_mod); while (degpol(x) < n); return x; } /* normalized Fpx, degree n */ static GEN rand_NFpX(long n) { pari_sp av = avma; GEN x = gadd(pol_xn(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); } static GEN rand_NF2xqX(long n, GEN T) { pari_sp av = avma; GEN x = F2xX_add(monomial(pol1_F2x(0),n,0), random_F2xqX(n, 0, T)); return gerepileupto(av, x); } static GEN rand_NFlxqX(long n, GEN T, long l) { pari_sp av = avma; GEN x = FlxX_add(monomial(pol1_Flx(0),n,0), random_FlxqX(n, 0, T, l), l); return gerepileupto(av, x); } static GEN rand_NFpXQX(long n, GEN T) { pari_sp av = avma; GEN x = gadd(pol_xn(n,0), random_FpXQX(n, 0, T, LARGE_mod)); return gerepileupto(av, x); } #define t_F2x 100 #define t_Flx 200 #define t_Fl2x 201 #define t_NFlx 210 #define t_NFl2x 211 #define t_FpX 300 #define t_NFpX 310 #define t_F2xqX 400 #define t_NF2xqX 410 #define t_FlxqX 500 #define t_NFlxqX 510 #define t_FpXQX 600 #define t_NFpXQX 610 static GEN rand_g(speed_param *s) { long n = s->size; switch (s->type) { case t_INT: return rand_INT(n); case t_REAL: return rand_REAL(n); case t_F2x: return rand_F2x(n); case t_Flx: return rand_Flx(n,DFLT_mod); case t_Fl2x: return rand_Flx(n,DFLT_mod2); case t_NFlx: return rand_NFlx(n,DFLT_mod); case t_NFl2x: return rand_NFlx(n,DFLT_mod2); case t_FpX: return rand_FpX(n); case t_NFpX: return rand_NFpX(n); case t_F2xqX: return rand_F2xqX(n, s->T); case t_NF2xqX: return rand_NF2xqX(n, s->T); case t_FlxqX: return rand_FlxqX(n, s->T, s->l); case t_NFlxqX: return rand_NFlxqX(n, s->T, s->l); case t_FpXQX: return rand_FpXQX(n, s->T); case t_NFpXQX: return rand_NFpXQX(n, s->T); } return NULL; } static void dft_F2xq(speed_param *s) { pari_sp av = avma; do { avma = av; s->T = random_F2x(BITS_IN_LONG*2, 0); } while (!F2x_is_irred(s->T)); s->T[1] = evalvarn(1); s->T = F2x_get_red(s->T); } static void dft_Flxq(speed_param *s) { pari_sp av = avma; do { avma = av; s->T = rand_NFlx(DFLT_deg, s->l); } while (!Flx_is_irred(s->T, s->l)); s->T[1] = evalvarn(1); s->T = Flx_get_red(s->T, s->l); } static void dft_FpXQ(speed_param *s) { pari_sp av = avma; do { avma = av; s->T = rand_NFpX(DFLT_deg); } while (!FpX_is_irred(s->T, LARGE_mod)); setvarn(s->T, 1); s->T = FpX_get_red(s->T, s->p); } static void dftmod(speed_param *s) { switch (s->type) { case t_Flx: s->l=DFLT_mod; return; case t_Fl2x: s->l=DFLT_mod2; return; case t_NFlx: s->l=DFLT_mod; return; case t_NFl2x: s->l=DFLT_mod2; return; case t_FpX: s->p=LARGE_mod; return; case t_NFpX: s->p=LARGE_mod; return; case t_F2xqX: s->l=2; dft_F2xq(s); return; case t_NF2xqX: s->l=2; dft_F2xq(s); return; case t_FlxqX: s->l=DFLT_mod; dft_Flxq(s); return; case t_NFlxqX: s->l=DFLT_mod; dft_Flxq(s); return; case t_FpXQX: s->p=LARGE_mod; dft_FpXQ(s); return; case t_NFpXQX: s->p=LARGE_mod; dft_FpXQ(s); return; } } /* ========================================================== */ #define TIME_FUN(call) {\ { \ pari_sp av = avma; \ int i; \ speed_starttime(); \ i = (s)->reps; \ do { call; set_avma(av); } while (--i); \ } \ return speed_endtime(); \ } #define m_menable_REAL(s,var,min) (*(s->var)=bit_accuracy(minss(lg(s->x),s->min+2))) #define m_enable_REAL(s,var) (*(s->var)=bit_accuracy(lg(s->x)-2))/* enable asymptotically fastest */ #define m_disable_REAL(s,var) (*(s->var)=bit_accuracy(lg(s->x)+1))/* disable asymptotically fastest */ #define m_menable(s,var,min) (*(s->var)=minss(lg(s->x)-2,s->min)) #define m_enable(s,var) (*(s->var)=lg(s->x)-2)/* enable asymptotically fastest */ #define m_disable(s,var) (*(s->var)=lg(s->x)+1)/* disable asymptotically fastest */ static void enable(speed_param *s) { if (s->type==t_REAL) { m_enable_REAL(s,var); s->enabled = 1; if (s->var_disable) m_disable_REAL(s,var_disable); if (s->var_enable) m_menable_REAL(s,var_enable,var_enable_min); } else { m_enable(s,var); s->enabled = 1; if (s->var_disable) m_disable(s,var_disable); if (s->var_enable) m_menable(s,var_enable,var_enable_min); } } static void disable(speed_param *s) { if (s->type==t_REAL) { m_disable_REAL(s,var); s->enabled = 0; if (s->var_disable) m_disable_REAL(s,var_disable); if (s->var_enable) m_menable_REAL(s,var_enable,var_enable_min); } else { m_disable(s,var); s->enabled = 0; if (s->var_disable) m_disable(s,var_disable); if (s->var_enable) m_menable(s,var_enable,var_enable_min); } } static double speed_mulrr(speed_param *s) { TIME_FUN(mulrr(s->x, s->y)); } static double speed_sqrr(speed_param *s) { TIME_FUN(sqrr(s->x)); } static double speed_mulii(speed_param *s) { TIME_FUN(mulii(s->x, s->y)); } static double speed_sqri (speed_param *s) { TIME_FUN(sqri(s->x)); } static double speed_extgcdii(speed_param *s) { GEN u,v; TIME_FUN(bezout(s->x, s->y, &u, &v)); } static double speed_gcdii(speed_param *s) { TIME_FUN(gcdii(s->x, s->y)); } static double speed_halfgcdii(speed_param *s) { TIME_FUN(halfgcdii(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_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_F2x_mul(speed_param *s) { TIME_FUN(F2x_mul(s->x, s->y)); } static double speed_Flx_sqr(speed_param *s) { TIME_FUN(Flx_sqr(s->x, s->l)); } static double speed_Flx_inv(speed_param *s) { TIME_FUN(Flx_invBarrett(s->x, s->l)); } static double speed_Flx_mul(speed_param *s) { TIME_FUN(Flx_mul(s->x, s->y, s->l)); } static double speed_Flx_divrem(speed_param *s) { GEN r, x = rand_NFlx((degpol(s->x)-1)*2, s->l); TIME_FUN(Flx_divrem(x, s->x, s->l, &r)); } static double speed_Flx_rem(speed_param *s) { GEN x = rand_NFlx((degpol(s->x)-1)*2, s->l); TIME_FUN(Flx_rem(x, s->x, s->l)); } static double speed_Flxq_red(speed_param *s) { GEN x = rand_NFlx((degpol(s->x)-1)*2, s->l); GEN q = Flx_get_red(s->x, s->l); TIME_FUN(Flx_rem(x, q, s->l)); } static double speed_Flx_halfgcd(speed_param *s) { TIME_FUN(Flx_halfgcd(s->x, s->y, s->l)); } static double speed_Flx_gcd(speed_param *s) { TIME_FUN(Flx_gcd(s->x, s->y, s->l)); } static double speed_Flx_extgcd(speed_param *s) { GEN u,v; TIME_FUN(Flx_extgcd(s->x, s->y, s->l, &u, &v)); } static double speed_FpX_inv(speed_param *s) { TIME_FUN(FpX_invBarrett(s->x, s->p)); } static double speed_FpX_divrem(speed_param *s) { GEN r, x = rand_NFpX((degpol(s->x)-1)*2); TIME_FUN(FpX_divrem(x, s->x, s->p, &r)); } static double speed_FpX_rem(speed_param *s) { GEN x = rand_NFpX((degpol(s->x)-1)*2); TIME_FUN(FpX_rem(x, s->x, s->p)); } static double speed_FpXQ_red(speed_param *s) { GEN x = rand_NFpX((degpol(s->x)-1)*2); GEN q = FpX_get_red(s->x, s->p); TIME_FUN(FpX_rem(x, q, s->p)); } static double speed_FpX_halfgcd(speed_param *s) { TIME_FUN(FpX_halfgcd(s->x, s->y, s->p)); } static double speed_FpX_gcd(speed_param *s) { TIME_FUN(FpX_gcd(s->x, s->y, s->p)); } static double speed_FpX_extgcd(speed_param *s) { GEN u,v; TIME_FUN(FpX_extgcd(s->x, s->y, s->p, &u, &v)); } static double speed_F2xqX_inv(speed_param *s) { TIME_FUN(F2xqX_invBarrett(s->x, s->T)); } static double speed_F2xqX_divrem(speed_param *s) { GEN r, x = rand_NF2xqX((degpol(s->x)-1)*2, s->T); TIME_FUN(F2xqX_divrem(x, s->x, s->T, &r)); } static double speed_F2xqX_rem(speed_param *s) { GEN x = rand_NF2xqX((degpol(s->x)-1)*2, s->T); TIME_FUN(F2xqX_rem(x, s->x, s->T)); } static double speed_F2xqXQ_red(speed_param *s) { GEN x = rand_NF2xqX((degpol(s->x)-1)*2, s->T); GEN q = F2xqX_get_red(s->x, s->T); TIME_FUN(F2xqX_rem(x, q, s->T)); } static double speed_F2xqX_halfgcd(speed_param *s) { TIME_FUN(F2xqX_halfgcd(s->x, s->y, s->T)); } static double speed_F2xqX_extgcd(speed_param *s) { GEN u,v; TIME_FUN(F2xqX_extgcd(s->x, s->y, s->T, &u, &v)); } static double speed_F2xqX_gcd(speed_param *s) { TIME_FUN(F2xqX_gcd(s->x, s->y, s->T)); } static double speed_FlxqX_inv(speed_param *s) { TIME_FUN(FlxqX_invBarrett(s->x, s->T, s->l)); } static double speed_FlxqX_divrem(speed_param *s) { GEN r, x = rand_NFlxqX((degpol(s->x)-1)*2, s->T, s->l); TIME_FUN(FlxqX_divrem(x, s->x, s->T, s->l, &r)); } static double speed_FlxqX_rem(speed_param *s) { GEN x = rand_NFlxqX((degpol(s->x)-1)*2, s->T, s->l); TIME_FUN(FlxqX_rem(x, s->x, s->T, s->l)); } static double speed_FlxqXQ_red(speed_param *s) { GEN x = rand_NFlxqX((degpol(s->x)-1)*2, s->T, s->l); GEN q = FlxqX_get_red(s->x, s->T, s->l); TIME_FUN(FlxqX_rem(x, q, s->T, s->l)); } static double speed_FlxqX_halfgcd(speed_param *s) { TIME_FUN(FlxqX_halfgcd(s->x, s->y, s->T, s->l)); } static double speed_FlxqX_extgcd(speed_param *s) { GEN u,v; TIME_FUN(FlxqX_extgcd(s->x, s->y, s->T, s->l, &u, &v)); } static double speed_FlxqX_gcd(speed_param *s) { TIME_FUN(FlxqX_gcd(s->x, s->y, s->T, s->l)); } static double speed_FpXQX_inv(speed_param *s) { TIME_FUN(FpXQX_invBarrett(s->x, s->T, s->p)); } static double speed_FpXQX_divrem(speed_param *s) { GEN r, x = rand_NFpXQX((degpol(s->x)-1)*2, s->T); TIME_FUN(FpXQX_divrem(x, s->x, s->T, s->p, &r)); } static double speed_FpXQX_rem(speed_param *s) { GEN x = rand_NFpXQX((degpol(s->x)-1)*2, s->T); TIME_FUN(FpXQX_rem(x, s->x, s->T, s->p)); } static double speed_FpXQXQ_red(speed_param *s) { GEN x = rand_NFpXQX((degpol(s->x)-1)*2, s->T); GEN q = FpXQX_get_red(s->x, s->T, s->p); TIME_FUN(FpXQX_rem(x, q, s->T, s->p)); } static double speed_FpXQX_halfgcd(speed_param *s) { TIME_FUN(FpXQX_halfgcd(s->x, s->y, s->T, s->p)); } static double speed_FpXQX_extgcd(speed_param *s) { GEN u,v; TIME_FUN(FpXQX_extgcd(s->x, s->y, s->T, s->p, &u, &v)); } static double speed_FpXQX_gcd(speed_param *s) { TIME_FUN(FpXQX_gcd(s->x, s->y, s->T, s->p)); } static double speed_ZM2_mul(speed_param *s) { TIME_FUN(ZM2_mul(mkmat22(s->x,s->y,s->y,s->x), mkmat22(s->x,s->x,s->y,s->x))); } /* small coeffs: earlier thresholds for more complicated rings */ static double speed_RgX_sqr(speed_param *s) { TIME_FUN(RgX_sqr_i(s->x)); } static double speed_RgX_mul(speed_param *s) { TIME_FUN(RgX_mul_i(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(ZM2_MUL_LIMIT), t_INT, 6,0, speed_ZM2_mul,0.02}, {0, var(HALFGCD_LIMIT), t_INT, 6,0, speed_halfgcdii,0.02}, {PARI,var(EXTGCD_HALFGCD_LIMIT), t_INT, 5,0, speed_extgcdii,0.02}, {PARI,var(GCD_HALFGCD_LIMIT), t_INT, 5,0, speed_gcdii,0.02}, {0, var(MULRR_MULII_LIMIT), t_REAL,4,0, speed_mulrr}, {0, var(SQRR_SQRI_LIMIT), t_REAL,4,0, speed_sqrr}, {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(F2x_MUL_KARATSUBA_LIMIT),t_F2x,3,0, speed_F2x_mul,0,0,&F2x_MUL_MULII_LIMIT}, {0, var(F2x_MUL_MULII_LIMIT), t_F2x,20,20000, speed_F2x_mul}, {0, var(Flx_MUL_KARATSUBA_LIMIT),t_Flx,5,0, speed_Flx_mul,0,0,&Flx_MUL_MULII_LIMIT}, {0, var(Flx_SQR_KARATSUBA_LIMIT),t_Flx,5,0, speed_Flx_sqr,0,0,&Flx_SQR_SQRI_LIMIT}, {0, var(Flx_MUL2_KARATSUBA_LIMIT),t_Fl2x,5,0, speed_Flx_mul,0,0,&Flx_MUL2_MULII_LIMIT}, {0, var(Flx_SQR2_KARATSUBA_LIMIT),t_Fl2x,5,0, speed_Flx_sqr,0,0,&Flx_SQR2_SQRI_LIMIT}, {0, var(Flx_MUL_MULII_LIMIT), t_Flx,5,0, speed_Flx_mul}, {0, var(Flx_SQR_SQRI_LIMIT), t_Flx,5,0, speed_Flx_sqr}, {0, var(Flx_MUL2_MULII_LIMIT), t_Fl2x,5,20000, speed_Flx_mul,0.05}, {0, var(Flx_SQR2_SQRI_LIMIT), t_Fl2x,5,20000, speed_Flx_sqr,0.05}, {0, var(Flx_INVBARRETT_LIMIT), t_NFlx, 5,0, speed_Flx_inv}, {0, var(Flx_INVBARRETT2_LIMIT),t_NFl2x,5,0, speed_Flx_inv}, {0, var(Flx_DIVREM_BARRETT_LIMIT) ,t_NFlx,10,0, speed_Flx_divrem,0.05}, {0, var(Flx_DIVREM2_BARRETT_LIMIT),t_NFl2x,10,0, speed_Flx_divrem,0.05}, {0, var(Flx_REM_BARRETT_LIMIT), t_NFlx,10,0, speed_Flx_rem,0.05}, {0, var(Flx_REM2_BARRETT_LIMIT), t_NFl2x,10,0, speed_Flx_rem,0.05}, {0, var(Flx_BARRETT_LIMIT), t_NFlx, 5,0, speed_Flxq_red}, {0, var(Flx_BARRETT2_LIMIT),t_NFl2x,5,0, speed_Flxq_red}, {0, var(Flx_HALFGCD_LIMIT), t_Flx, 10,0, speed_Flx_halfgcd}, {0, var(Flx_HALFGCD2_LIMIT),t_Fl2x,10,0, speed_Flx_halfgcd}, {0, var(Flx_GCD_LIMIT), t_Flx,10,0, speed_Flx_gcd,0.1}, {0, var(Flx_GCD2_LIMIT), t_Fl2x,10,0, speed_Flx_gcd,0.1}, {0, var(Flx_EXTGCD_LIMIT), t_Flx,10,0, speed_Flx_extgcd}, {0, var(Flx_EXTGCD2_LIMIT), t_Fl2x,10,0, speed_Flx_extgcd}, {0, var(F2xqX_INVBARRETT_LIMIT),t_NF2xqX,10,0, speed_F2xqX_inv,0.05}, {0, var(F2xqX_BARRETT_LIMIT), t_NF2xqX,10,0, speed_F2xqXQ_red,0.05}, {0, var(F2xqX_DIVREM_BARRETT_LIMIT), t_NF2xqX,10,0, speed_F2xqX_divrem,0.05}, {0, var(F2xqX_REM_BARRETT_LIMIT), t_NF2xqX,10,0, speed_F2xqX_rem,0.05}, {0, var(F2xqX_HALFGCD_LIMIT), t_F2xqX,10,0, speed_F2xqX_halfgcd,0.05}, {0, var(F2xqX_GCD_LIMIT), t_F2xqX,10,0, speed_F2xqX_gcd,0.1}, {0, var(F2xqX_EXTGCD_LIMIT), t_F2xqX,10,0, speed_F2xqX_extgcd,0.05}, {0, var(FlxqX_INVBARRETT_LIMIT),t_NFlxqX,10,0, speed_FlxqX_inv,0.05}, {0, var(FlxqX_BARRETT_LIMIT), t_NFlxqX,10,0, speed_FlxqXQ_red,0.05}, {0, var(FlxqX_DIVREM_BARRETT_LIMIT), t_NFlxqX,10,0, speed_FlxqX_divrem,0.05}, {0, var(FlxqX_REM_BARRETT_LIMIT), t_NFlxqX,10,0, speed_FlxqX_rem,0.05}, {0, var(FlxqX_HALFGCD_LIMIT), t_FlxqX,10,0, speed_FlxqX_halfgcd,0.05}, {0, var(FlxqX_GCD_LIMIT), t_FlxqX,10,0, speed_FlxqX_gcd,0.05}, {0, var(FlxqX_EXTGCD_LIMIT), t_FlxqX,10,0, speed_FlxqX_extgcd,0.05}, {0, var(FpX_INVBARRETT_LIMIT), t_NFpX,10,0, speed_FpX_inv,0.05}, {0, var(FpX_DIVREM_BARRETT_LIMIT),t_NFpX,10,0, speed_FpX_divrem,0.05}, {0, var(FpX_REM_BARRETT_LIMIT), t_NFpX,10,0, speed_FpX_rem,0.05}, {0, var(FpX_BARRETT_LIMIT), t_NFpX,10,0, speed_FpXQ_red}, {0, var(FpX_HALFGCD_LIMIT), t_FpX,10,0, speed_FpX_halfgcd}, {0, var(FpX_GCD_LIMIT), t_FpX,10,0, speed_FpX_gcd,0.1}, {0, var(FpX_EXTGCD_LIMIT), t_FpX,10,0, speed_FpX_extgcd}, {0, var(FpXQX_INVBARRETT_LIMIT),t_NFpXQX,10,0, speed_FpXQX_inv,0.05}, {0, var(FpXQX_BARRETT_LIMIT), t_NFpXQX,10,0, speed_FpXQXQ_red,0.05}, {0, var(FpXQX_DIVREM_BARRETT_LIMIT), t_NFpXQX,10,0, speed_FpXQX_divrem,0.05}, {0, var(FpXQX_REM_BARRETT_LIMIT), t_NFpXQX,10,0, speed_FpXQX_rem,0.05}, {0, var(FpXQX_HALFGCD_LIMIT), t_FpXQX,10,0, speed_FpXQX_halfgcd,0.05}, {0, var(FpXQX_GCD_LIMIT), t_FpXQX,10,0, speed_FpXQX_gcd,0.05}, {0, var(FpXQX_EXTGCD_LIMIT), t_FpXQX,10,0, speed_FpXQX_extgcd,0.05}, {0, var(RgX_MUL_LIMIT), t_FpX, 4,0, speed_RgX_mul}, {0, var(RgX_SQR_LIMIT), t_FpX, 4,0, speed_RgX_sqr}, }; /* ========================================================== */ int ndat = 0, allocdat = 0; struct dat_t { long size; double d; } *dat = NULL; int double_cmp_ptr(double *x, double *y) { return (int)(*x - *y); } double time_fun(speed_function_t fun, speed_param *s, long enabled) { const double TOLERANCE = 1.005; /* 0.5% */ pari_sp av = avma; double t[30]; ulong i, j, e; s->reps = 1; if (enabled) enable(s); else disable(s); for (i = 0; i < numberof(t); i++) { for (;;) { double reps_d; t[i] = fun(s); if (!t[i]) { s->reps *= 10; continue; } if (t[i] >= speed_unittime * speed_precision) break; /* go to a value of reps to make t[i] >= precision */ reps_d = ceil (1.1 * s->reps * speed_unittime * speed_precision / maxdd(t[i], speed_unittime)); if (reps_d > 2e9 || reps_d < 1.0) pari_err(e_MISC, "Fatal error: new reps bad: %.2f", reps_d); s->reps = (ulong)reps_d; } t[i] /= s->reps; /* require 3 values within TOLERANCE when >= 2 secs, 4 when below */ e = (t[0] >= 2.0)? 3: 4; /* Look for e many t[]'s within TOLERANCE of each other to consider a valid measurement. Return smallest among them. */ if (i >= e) { qsort (t, i+1, sizeof(t[0]), (QSCOMP)double_cmp_ptr); for (j = e-1; j < i; j++) if (t[j] <= t[j-e+1] * TOLERANCE) return gc_double(av, t[j-e+1]); } } pari_err(e_MISC,"couldn't measure time"); return -1.0; /* LCOV_EXCL_LINE */ } int cmpdat(const void *a, const void *b) { struct dat_t *da =(struct dat_t *)a; struct dat_t *db =(struct dat_t *)b; return da->size-db->size; } void add_dat(long size, double d) { if (ndat == allocdat) { allocdat += maxss(allocdat, 100); pari_realloc_ip((void**)&dat, allocdat * sizeof(dat[0])); } dat[ndat].size = size; dat[ndat].d = d; ndat++; qsort(dat, ndat, sizeof(*dat), cmpdat); } void diag(const char *format, ...) { va_list ap; va_start(ap, format); vfprintf(stderr, format, ap); va_end(ap); } void fdiag(FILE *stream, const char *format, ...) { va_list ap; va_start(ap, format); vfprintf(stream, format, ap); va_end(ap); } void print_define(tune_param *param, long value) { if (param->type==t_REAL && value > 0) value = bit_accuracy(value); printf("#define __%-30s %ld\n", param->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, long linear) { int since_positive, since_change, thresh, new_thresh; speed_param s; long save_var_disable = -1; pari_timer T; pari_sp av=avma; long good = -1, bad = param->min_size; if (param->kernel == AVOID) { print_define(param, -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); if (param->var_enable) s.var_enable_min = *(param->var_enable); s.type = param->type; s.size = param->min_size; s.var = param->var; s.var_disable = param->var_disable; s.var_enable = param->var_enable; dftmod(&s); ndat = since_positive = since_change = thresh = 0; if (option_trace >= 1) { timer_start(&T); diag("\nSetting %s... (default %ld)\n", param->name, *(param->var)); } if (option_trace >= 2) { diag(" algorithm-A algorithm-B ratio possible\n"); diag(" (seconds) (seconds) diff thresh\n"); } for(;;) { pari_sp av=avma; double t1, t2, d; s.x = rand_g(&s); s.y = rand_g(&s); t1 = time_fun(param->fun, &s, 0); t2 = time_fun(param->fun, &s, 1); set_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 if (linear) { /* 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); } else { if (t2 <= t1) new_thresh = good = s.size; else bad = s.size; if (bad == -1) linear = 1; else if (good == -1) { long new_size = minss(2*s.size,param->max_size-1); if (new_size==s.size) linear = 1; s.size = new_size; } else if (good-bad <= maxss(1,(long)(20*param->step_factor*bad))) { linear = 1; new_thresh = s.size = bad + 1; } else s.size = (good+bad)/2; } if (s.size >= param->max_size) { if (option_trace >= 1) diag("Stop: max_size (%ld). Disable Algorithm B?\n",param->max_size); break; } } thresh = dat[analyze_dat(1)].size; if (option_trace >= 1) diag("Total time: %gs\n", (double)timer_delay(&T)/1000.); print_define(param, thresh); *(param->var) = thresh; /* set to optimal value for next tests */ if (param->var_disable) *(param->var_disable) = save_var_disable; if (param->var_enable) *(param->var_enable) = s.var_enable_min; set_avma(av); } void error(int err, char **argv) { long i; FILE *stream = err ? stderr: stdout; fdiag(stream, "This is the PARI/GP tuning utility. Usage: tune [OPTION] var1 var2...\n"); fdiag(stream, "Options:\n"); fdiag(stream, " -h: this help\n"); fdiag(stream, " -t: verbose output\n"); fdiag(stream, " -tt: very verbose output\n"); fdiag(stream, " -ttt: output everything\n"); fdiag(stream, " -l: use linear search (slower)\n"); fdiag(stream, " -d xxx: set finite field degree to xxx (default 10)\n"); fdiag(stream, " -p xxx: set Flx modulus to xxx (default 27449)\n"); fdiag(stream, " -s xxx: set step factor between successive sizes to xxx (default 0.01)\n"); fdiag(stream, " -u xxx: set speed_unittime to xxx (default 1e-4s)\n"); fdiag(stream, "Tunable variables (omitting variable indices tunes everybody):\n"); for (i = 0; i < (long)numberof(param); i++) fdiag(stream, " %2ld: %-25s (default %4ld)\n", i, param[i].name, *(param[i].var)); exit(err); } int main(int argc, char **argv) { int i, r, n = 0; int linear = 0; GEN v; pari_init(160000000, 2); LARGE_mod=subis(powuu(3,128),62); DFLT_mod = unextprime((1UL<<((BITS_IN_LONG-2)>>1))+1); DFLT_mod2 = unextprime((1UL<<(BITS_IN_LONG-1))+1); DFLT_deg = 10; v = new_chunk(argc); for (i = 1; i < argc; i++) { char *s = argv[i]; if (*s == '-') { switch(*++s) { case 't': option_trace++; while (*++s == 't') option_trace++; break; case 'l': linear = 1-linear; break; case 'd': if (!*++s) { if (++i == argc) error(1,argv); s = argv[i]; } DFLT_deg = itou(gp_read_str(s)); break; case 'h': error(0,argv); break; case 'p': if (!*++s) { if (++i == argc) error(1,argv); s = argv[i]; } DFLT_mod = itou(gp_read_str(s)); break; case 's': if (!*++s) { if (++i == argc) error(1,argv); s = argv[i]; } Step_Factor = atof(s); break; case 'u': s++; if (!*++s) { if (++i == argc) error(1,argv); s = argv[i]; } speed_unittime = atof(s); break; default: error(1,argv); } } else { if (!isdigit((unsigned char)*s)) error(1,argv); r = atol(s); if (r >= (long)numberof(param) || r < 0) error(1,argv); v[n++] = r; } } if (n) { for (i = 0; i < n; i++) Test(¶m[ v[i] ], linear); return 0; } n = numberof(param); for (i = 0; i < n; i++) Test(¶m[i], linear); return 0; } pari-2.17.2/src/test/dummy.c0000644000175000017500000000075414567450071014250 0ustar billbillvoid nchar2nlong(){} void newblock(){} void remsBIL(){} void bit_accuracy(){} void is_bigint(){} void divsBIL(){} void copy_bin(){} void pari_free(){} void pari_malloc(){} void shiftaddress(){} void shiftaddress_canon(){} void powuu(){} void gerepilemanysp(){} void ceilr(){} void roundr(){} void pari_err(){} void pari_err_BUG(){} void pari_err_INV(){} void pari_err_OVERFLOW(){} void pari_err_PREC(){} void pari_warn(){} void quadratic_prec_mask(){} void prec2nbits(){} void nbits2prec(){} pari-2.17.2/src/gp/0000755000175000017500000000000014760315601012364 5ustar billbillpari-2.17.2/src/gp/texmacs.c0000644000175000017500000001372114676526175014220 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*******************************************************************/ /* */ /* TEXMACS-SPECIFIC STUFF */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" #include "gp.h" #define DATA_BEGIN ((char) 2) #define DATA_END ((char) 5) #define DATA_ESCAPE ((char) 27) /*******************************************************************/ /* */ /* READLINE INTERFACE */ /* */ /*******************************************************************/ #ifdef READLINE static pari_rl_interface pari_rl; #endif static int did_complete = 0; #ifdef READLINE BEGINEXTERN #include ENDEXTERN static void print_escape_string(char *s) { long l = strlen(s); char *t, *t0 = (char*)pari_malloc(l * 3 + 3); t = t0; *t++ = '"'; for ( ;*s; *t++ = *s++) switch(*s) { case DATA_BEGIN: case DATA_END: case DATA_ESCAPE: *t++ = DATA_ESCAPE; continue; case '\\': case '"': *t++ = '\\'; continue; } *t++ = '"'; *t = '\0'; puts(t0); pari_free(t0); } /* completion required, cursor on s + pos. Complete wrt strict left prefix */ static void tm_completion(const char *s, long pos) { char **matches, *text; long w; matches = pari_completion_matches(&pari_rl, s, pos, &w); text = *pari_rl.line_buffer + w; printf("%cscheme:(tuple",DATA_BEGIN); if (matches) { long i, prelen = (rl_line_buffer+pos) - text; char *t = (char*)pari_malloc(prelen+1); strncpy(t, text, prelen); t[prelen] = 0; /* prefix */ printf(" "); print_escape_string(t); pari_free(t); for (i = matches[1]? 1: 0; matches[i]; i++) { printf(" "); print_escape_string(matches[i] + prelen); pari_free(matches[i]); } pari_free(matches); } printf(")%c", DATA_END); fflush(stdout); } #else /* no-op */ static void tm_completion(const char *s, long pos) { (void)s; (void)pos; } #endif typedef struct { char *cmd; long n; /* number of args */ char **v; /* args */ } tm_cmd; static void tm_parse_command(tm_cmd *c, const char *ch) { long l = strlen(ch); char *t, *s = (char*)ch, *send = s+l-1; char **A; pari_stack s_A; if (*s != DATA_BEGIN || *send-- != DATA_END) pari_err(e_MISC, "missing DATA_[BEGIN | END] in TeXmacs command"); s++; if (strncmp(s, "special:", 8)) pari_err(e_MISC, "unrecognized TeXmacs command"); s += 8; if (*s != '(' || *send-- != ')') pari_err(e_MISC, "missing enclosing parentheses for TeXmacs command"); s++; t = s; pari_skip_alpha(&s); c->cmd = pari_strndup(t, s - t); pari_stack_init(&s_A,sizeof(*A),(void**)&A); for (c->n = 0; s <= send; c->n++) { char *u = (char*)pari_malloc(strlen(s) + 1); pari_skip_space(&s); if (*s == '"') s = pari_translate_string(s, u, t); else { /* read integer */ t = s; while (isdigit((unsigned char)*s)) s++; strncpy(u, t, s - t); u[s-t] = 0; } pari_stack_pushp(&s_A, u); } c->v = A; } static void tm_free_cmd(tm_cmd *c) { while (c->n--) pari_free((void*)c->v[c->n]); pari_free((void*)c->v); } static void tm_handle_command(const char *s) { tm_cmd c; tm_parse_command(&c, s); if (strcmp(c.cmd, "complete")) pari_err(e_MISC,"Texmacs command %s not implemented", c.cmd); if (c.n != 2) pari_err(e_MISC,"was expecting 2 arguments for Texmacs command"); tm_completion(c.v[0], atol(c.v[1])); tm_free_cmd(&c); did_complete = 1; } /****/ int tm_is_interactive(void) { return 0; } static int tm_is_waiting = 0; /* tell TeXmacs GP will start outputing data */ void tm_start_output(void) { if (!tm_is_waiting) { printf("%cverbatim:",DATA_BEGIN); fflush(stdout); } tm_is_waiting = 1; } /* tell TeXmacs GP is done and is waiting for new data */ void tm_end_output(void) { if (tm_is_waiting) { printf("%c", DATA_END); fflush(stdout); } tm_is_waiting = 0; } char * tm_fgets(char *s, int n, FILE *f) { if (!did_complete) { /* we need input */ tm_start_output(); tm_end_output(); } return fgets(s,n,f); } int tm_get_line(const char *prompt, const char *prompt_cont, filtre_t *F) { int res = get_line_from_file(prompt, F, pari_infile); (void)prompt_cont; if (res) { char *s = F->buf->buf; did_complete = 0; if (pari_infile == stdin && *s == DATA_BEGIN) { tm_handle_command(s); *s = 0; } else tm_start_output(); } return res; } static void tm_output(long n) { char *sz = GENtoTeXstr(pari_get_hist(n)); printf("%clatex:", DATA_BEGIN); printf("\\magenta\\%%%lu = ", n); printf("$\\blue %s$%c", sz,DATA_END); pari_free(sz); fflush(stdout); pari_flush(); } void init_texmacs(void) { #ifdef READLINE printf("%ccommand:(cas-supports-completions-set! \"pari\")%c\n", DATA_BEGIN, DATA_END); pari_use_readline(pari_rl); #endif cb_pari_fgets_interactive = tm_fgets; cb_pari_get_line_interactive = tm_get_line; cb_pari_start_output = tm_start_output; cb_pari_end_output = tm_end_output; cb_pari_is_interactive = tm_is_interactive; cb_pari_display_hist = tm_output; disable_color = 1; tm_start_output(); } pari-2.17.2/src/gp/gp.h0000644000175000017500000000276514760123736013163 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*************************************************************************/ /* */ /* GP-SPECIFIC DECLARATIONS */ /* */ /*************************************************************************/ BEGINEXTERN void init_emacs(void); void init_readline(void); void init_texmacs(void); /* gp specific routines */ void dbg_down(long k); void dbg_up(long k); GEN dbg_err(void); void gp_quit(long exitcode); void pari_breakpoint(void); int whatnow(PariOUT *out, const char *s, int silent); extern void (*cb_gp_output)(GEN z); extern void (*cb_pari_end_output)(void); extern entree functions_gp[]; /* architecture-dependent plot files (src/graph/plot*.c) */ void gp_get_plot(PARI_plot *T); ENDEXTERN pari-2.17.2/src/gp/gp.c0000644000175000017500000004130714760123736013151 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*******************************************************************/ /** **/ /** PARI CALCULATOR **/ /** **/ /*******************************************************************/ #ifdef _WIN32 # include "../systems/mingw/pwinver.h" # include # include "../systems/mingw/mingw.h" #endif #ifdef DEBUG_FLOATS # undef _GNU_SOURCE # define _GNU_SOURCE # include /* check for cpp symbol conflict */ # include #endif #include "pari.h" #include "paripriv.h" #include "gp.h" static jmp_buf *env; static pari_stack s_env; void (*cb_pari_end_output)(void) = NULL; static void gp_ask_confirm(const char *s) { err_printf(s); err_printf(". OK ? (^C if not)\n"); pari_hit_return(); } /* numerr < 0: after changing PARI stack size * numerr > 0: normal error, including SIGINT */ static void gp_err_recover(long numerr) { longjmp(env[s_env.n-1], numerr); } /* numerr >= 0 */ static void gp_pre_recover(long numerr) { out_puts(pariErr, "\n"); pariErr->flush(); gp_err_recover(numerr); } static void reset_ctrlc(void) { #if defined(_WIN32) || defined(__CYGWIN32__) win32ctrlc = 0; #endif } static int is_silent(char *s) { return s[strlen(s) - 1] == ';'; } static int stdin_isatty = 0; static int is_interactive(void) { return pari_infile == stdin && stdin_isatty; } /*******************************************************************/ /** **/ /** INITIALIZATION **/ /** **/ /*******************************************************************/ 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 void usage(char *s) { printf("### Usage: %s [options] [GP files]\n", s); printf("Available options:\n"); printf(" [-f,--fast]\t\tFast start: do not read .gprc\n"); printf(" [-q,--quiet]\t\tQuiet mode: do not print banner and history numbers\n"); printf(" [-s stacksize]\tStart with the PARI stack of given size (in bytes)\n"); printf(" [--default key=val]\tExecute default(key,val) on startup\n"); printf(" [--emacs]\t\tRun as if in Emacs shell\n"); printf(" [--help]\t\tPrint this message\n"); printf(" [--test]\t\tTest mode. No history, wrap long lines (bench only)\n"); printf(" [--texmacs]\t\tRun as if using TeXmacs frontend\n"); printf(" [--version]\t\tOutput version info and exit\n"); printf(" [--version-short]\tOutput version number and exit\n\n"); exit(0); } static void gp_head(void) { ulong p, f; pari_print_version(); pari_putc('\n'); pari_center("Copyright (C) 2000-2024 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"); pari_printf("Type ?%d for how to get moral" " (and possibly technical) support.\n", pari_community()); p = GP_DATA->primelimit; f = GP_DATA->factorlimit; if (pari_mainstack->vsize) pari_printf("\nparisizemax = %lu, primelimit = %lu, factorlimit = %lu", pari_mainstack->vsize, p, f); else pari_printf("\nparisize = %lu, primelimit = %lu, factorlimit = %lu", pari_mainstack->rsize, p, f); pari_putc('\n'); } static char * read_arg(long *nread, char *t, long argc, char **argv) { long i = *nread; if (isdigit((unsigned char)*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((unsigned char)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; pari_mainstack->size = s; pari_mainstack->bot = (pari_sp)pari_malloc(s); avma = pari_mainstack->top = pari_mainstack->bot + s; } static void free_trivial_stack(void) { free((void*)pari_mainstack->bot); } typedef struct { char *key, *val; } pair_t; /* If ab of the form key=val, record pair in new stack entry * P[n].key must be freed by caller to avoid memory leak */ static void record_default(pari_stack *s_P, char *ab) { pair_t *P = (pair_t*)*pari_stack_base(s_P); char *k, *v; long n; ab = pari_strdup(ab); parse_key_val(ab, &k, &v); n = pari_stack_new(s_P); P[n].key = k; P[n].val = v; } static void read_opt(pari_stack *p_A, long argc, char **argv) { pair_t *P; pari_stack s_P; /* key / value to record default() settings */ char *b = NULL, *p = NULL, *s = NULL; ulong f = GP_DATA->flags; long i = 1, initrc = 1; (void)&p; (void)&b; (void)&s; /* -Wall gcc-2.95 */ pari_stack_init(&s_P,sizeof(*P),(void**)&P); pari_stack_alloc(&s_P, 64); pari_outfile = stderr; while (i < argc) { char *t = argv[i]; if (*t++ != '-') break; i++; START: switch(*t++) { case 'p': p = read_arg(&i,t,argc,argv); break; case 's': s = read_arg(&i,t,argc,argv); break; case 'e': f |= gpd_EMACS; if (*t) goto START; break; case 'q': f |= gpd_QUIET; if (*t) goto START; break; case 't': f |= gpd_TEST; if (*t) goto START; break; case 'f': initrc = 0; if (*t) goto START; break; case 'D': if (*t || i == argc) usage(argv[0]); record_default(&s_P, argv[i++]); break; case '-': if (strcmp(t, "version-short") == 0) { print_shortversion(); exit(0); } if (strcmp(t, "version") == 0) { init_trivial_stack(); pari_print_version(); free_trivial_stack(); exit(0); } if (strcmp(t, "default") == 0) { if (i == argc) usage(argv[0]); record_default(&s_P, argv[i++]); break; } if (strcmp(t, "texmacs") == 0) { f |= gpd_TEXMACS; break; } if (strcmp(t, "emacs") == 0) { f |= gpd_EMACS; break; } if (strcmp(t, "test") == 0) { f |= gpd_TEST; initrc = 0; break; } if (strcmp(t, "quiet") == 0) { f |= gpd_QUIET; break; } if (strcmp(t, "fast") == 0) { initrc = 0; break; } if (strncmp(t, "primelimit",10) == 0) {p = read_arg_equal(&i,t+10,argc,argv); break; } if (strncmp(t, "stacksize",9) == 0) {s = read_arg_equal(&i,t+9,argc,argv); break; } /* fall through */ default: usage(argv[0]); } } if (f & gpd_TEST) stdin_isatty = 0; GP_DATA->flags = f; #ifdef READLINE GP_DATA->use_readline = stdin_isatty; #endif if (!is_interactive()) GP_DATA->breakloop = 0; if (initrc) gp_initrc(p_A); for ( ; i < argc; i++) pari_stack_pushp(p_A, pari_strdup(argv[i])); /* override the values from gprc */ if (p) (void)sd_primelimit(p, d_INITRC); if (s) (void)sd_parisize(s, d_INITRC); for (i = 0; i < s_P.n; i++) { setdefault(P[i].key, P[i].val, d_INITRC); free((void*)P[i].key); } pari_stack_delete(&s_P); pari_outfile = stdout; } /*******************************************************************/ /** **/ /** TEST MODE **/ /** **/ /*******************************************************************/ static int test_is_interactive(void) { return 0; } static void test_output(long n) { init_linewrap(76); gen_output(pari_get_hist(n)); } void init_test(void) { disable_color = 1; init_linewrap(76); pari_errfile = stdout; cb_pari_display_hist = test_output; cb_pari_is_interactive = test_is_interactive; } static GEN gp_main_loop(long ismain) { VOLATILE GEN z = gnil; VOLATILE long t = 0, r = 0; VOLATILE pari_sp av = avma; filtre_t F; Buffer *b = filtered_buffer(&F); struct gp_context rec; long er; if ((er = setjmp(env[s_env.n-1]))) { /* recover: jump from error [ > 0 ] or allocatemem [ -1 ] */ if (er > 0) { /* true error */ if (!(GP_DATA->recover)) exit(1); gp_context_restore(&rec); /* true error not from main instance, let caller sort it out */ if (!ismain) { kill_buffers_upto_including(b); return NULL; } } else { /* allocatemem */ tmp_restore(rec.file.file); gp_context_save(&rec); } set_avma(av = pari_mainstack->top); parivstack_reset(); kill_buffers_upto(b); pari_alarm(0); } for(;;) { gp_context_save(&rec); if (! gp_read_line(&F, NULL)) { if (popinfile()) gp_quit(0); if (ismain) continue; pop_buffer(); return z; } if (ismain) { reset_ctrlc(); timer_start(GP_DATA->T); walltimer_start(GP_DATA->Tw); pari_set_last_newline(1); } if (gp_meta(b->buf,ismain)) continue; z = pari_compile_str(b->buf); z = closure_evalres(z); if (!ismain) continue; t = timer_delay(GP_DATA->T); r = walltimer_delay(GP_DATA->Tw); if (!pari_last_was_newline()) pari_putc('\n'); pari_alarm(0); if (t && GP_DATA->chrono) { if (pari_mt_nbthreads==1) { pari_puts("time = "); pari_puts(gp_format_time(t)); } else { pari_puts("cpu time = "); pari_puts(gp_format_time(t)); pari_puts(", real time = "); pari_puts(gp_format_time(r)); } pari_puts(".\n"); } if (GP_DATA->simplify) z = simplify_shallow(z); pari_add_hist(z, t, r); if (z != gnil && ! is_silent(b->buf) ) gp_display_hist(GP_DATA->hist->total); set_avma(av); parivstack_reset(); } } /* as gp_read_file, before running the main gp instance */ static void read_main(const char *s) { GEN z; if (setjmp(env[s_env.n-1])) z = NULL; else { FILE *f = switchin(s); if (file_is_binary(f)) { z = readbin(s,f, NULL); popinfile(); } else z = gp_main_loop(0); } if (!z) err_printf("... skipping file '%s'\n", s); set_avma(pari_mainstack->top); } static const char * break_loop_prompt(long n) { return n==0 ? "GP prompt" : n==1? "break> ": stack_sprintf("break[%ld]> ", n); } static long frame_level=0, dbg_level = 0; static int break_loop(int numerr) { filtre_t F; Buffer *b; int sigint = numerr<0, go_on = sigint; struct gp_context rec1, rec2; const char *prompt, *msg; long nenv, oldframe_level = frame_level; pari_sp av; if (numerr == e_SYNTAX) return 0; if (numerr == e_STACK) { evalstate_clone(); set_avma(pari_mainstack->top); } gp_context_save(&rec1); b = filtered_buffer(&F); nenv=pari_stack_new(&s_env); prompt = gp_format_prompt(break_loop_prompt(nenv)); iferr_env = NULL; dbg_level = 0; frame_level = closure_context(oldframe_level, dbg_level); pari_infile = newfile(stdin, "stdin", mf_IN)->file; term_color(c_ERR); pari_putc('\n'); if (sigint) msg = "Break loop: to continue; 'break' to go back to %s"; else msg = "Break loop: type 'break' to go back to %s"; msg = stack_sprintf(msg, break_loop_prompt(nenv-1)); print_errcontext(pariOut, msg, NULL, NULL); term_color(c_NONE); av = avma; for(;;) { GEN x; long er, br_status; set_avma(av); gp_context_save(&rec2); if ((er=setjmp(env[nenv]))) { if (er < 0) { s_env.n = 1; frame_level = oldframe_level; longjmp(env[s_env.n-1], er); } gp_context_restore(&rec2); iferr_env = NULL; closure_err(dbg_level); compilestate_restore(&rec1.eval.comp); (void) closure_context(oldframe_level, dbg_level); pari_infile = newfile(stdin, "stdin", mf_IN)->file; } term_color(c_NONE); if (!gp_read_line(&F, prompt)) br_status = br_BREAK; /* EOF */ else { /* Empty input ? Continue if entry on sigint (exit debugger frame) */ if (! *(b->buf) && sigint) break; reset_ctrlc(); if (gp_meta(b->buf,0)) continue; x = pari_compile_str(b->buf); x = closure_evalbrk(x, &br_status); } switch (br_status) { case br_NEXT: case br_MULTINEXT: popinfile(); /* exit frame. Don't exit debugger if s_env.n > 2 */ go_on = 0; goto BR_EXIT; case br_BREAK: case br_RETURN: killallfiles(); /* completely exit the debugger */ go_on = 0; goto BR_EXIT; } if (x!=gnil && !is_silent(b->buf)) { term_color(c_OUTPUT); gen_output(x); } } BR_EXIT: s_env.n=nenv; frame_level = oldframe_level; gp_context_restore(&rec1); pop_buffer(); return go_on; } #ifdef __CYGWIN32__ void cyg_environment(int argc, char ** argv) { char *ti_dirs = getenv("TERMINFO_DIRS"); char *argv0, *p; char *newdir; long n; if (!argc || !argv) return; argv0 = *argv; if (!argv0 || !*argv0) return; p = strrchr(argv0, '/'); if (!p) p = argv0 = ""; else p++; n = p - argv0; if (ti_dirs) { n += 14 + strlen(ti_dirs) + 1 + 8 + 1; newdir = malloc(n); if (!newdir) return; snprintf(newdir, n-8, "TERMINFO_DIRS=%s:%s", ti_dirs, argv0); } else { n += 14 + 8 + 1; newdir = malloc(n); if (!newdir) return; snprintf(newdir, n-8, "TERMINFO_DIRS=%s", argv0); } strcpy(newdir+n-9,"terminfo"); putenv(newdir); } #endif int main(int argc, char **argv) { char **A; pari_stack s_A; GP_DATA = default_gp_data(); pari_stack_init(&s_env, sizeof(*env), (void**)&env); (void)pari_stack_new(&s_env); if (setjmp(env[s_env.n-1])) { puts("### Errors on startup, exiting...\n\n"); exit(1); } #ifdef DEBUG_FLOATS feenableexcept(FE_INVALID); #endif #ifdef __CYGWIN32__ cyg_environment(argc, argv); #endif stdin_isatty = pari_stdin_isatty(); pari_init_defaults(); pari_library_path = DL_DFLT_NAME; pari_stack_init(&s_A,sizeof(*A),(void**)&A); /* must be defined here in case an error is raised in pari_init_opts, e.g. * when parsing function prototypes */ cb_pari_err_recover = gp_err_recover; pari_init_opts(8000000, 0, INIT_SIGm | INIT_noPRIMEm | INIT_noIMTm); cb_pari_pre_recover = gp_pre_recover; cb_pari_break_loop = break_loop; cb_pari_is_interactive = is_interactive; read_opt(&s_A, argc,argv); pari_init_primes(GP_DATA->primelimit); #ifdef SIGALRM (void)os_signal(SIGALRM,gp_alarm_handler); #endif pari_add_module(functions_gp); pari_set_plot_engine(gp_get_plot); cb_pari_quit = gp_quit; cb_pari_whatnow = whatnow; cb_pari_sigint = gp_sigint_fun; cb_pari_handle_exception = gp_handle_exception; cb_pari_ask_confirm = gp_ask_confirm; pari_init_paths(); pari_mt_init(); /* MPI: will not return on slaves (pari_MPI_rank = 0) */ #ifdef _WIN32 if (stdin_isatty) win32_set_codepage(); #endif #ifdef READLINE init_readline(); #endif if (GP_DATA->flags & gpd_EMACS) init_emacs(); if (GP_DATA->flags & gpd_TEXMACS) init_texmacs(); timer_start(GP_DATA->T); walltimer_start(GP_DATA->Tw); if (!(GP_DATA->flags & gpd_QUIET)) gp_head(); if (GP_DATA->flags & gpd_TEST) init_test(); if (s_A.n) { FILE *l = pari_logfile; long i; pari_logfile = NULL; for (i = 0; i < s_A.n; pari_free(A[i]),i++) read_main(A[i]); /* Reading one of the input files above can set pari_logfile. * Don't restore in that case. */ if (!pari_logfile) pari_logfile = l; } pari_stack_delete(&s_A); (void)gp_main_loop(1); gp_quit(0); return 0; /* LCOV_EXCL_LINE */ } void dbg_down(long k) { if (k<0) k=0; dbg_level -= k; if (dbg_level<0) dbg_level=0; gp_err_recover(e_NONE); } GEN dbg_err(void) { GEN E = pari_err_last(); return E? gcopy(E):gnil; } void dbg_up(long k) { if (k<0) k=0; dbg_level += k; if (dbg_level>frame_level) dbg_level=frame_level; gp_err_recover(e_NONE); } void gp_quit(long code) { pari_kill_plot_engine(); pari_close(); kill_buffers_upto(NULL); if (!(GP_DATA->flags & gpd_QUIET)) pari_puts("Goodbye!\n"); if (cb_pari_end_output) cb_pari_end_output(); exit(code); } void whatnow0(char *s) { whatnow(pariOut, s,0); } #include "gp_init.h" pari-2.17.2/src/gp/whatnow.h0000644000175000017500000005147214567450071014243 0ustar billbilltypedef struct whatnow_t { const char *old, *name, *oldarg, *newarg; } whatnow_t; #define SAME NULL #define REMOV (char *)1L #define _REMOV REMOV,NULL,NULL #define _SAME SAME,NULL,NULL static const whatnow_t whatnowlist[]={ {"!_",_SAME}, {"#_",_SAME}, {"%",_SAME}, {"+_",_SAME}, {"-_",_SAME}, {"_!",_SAME}, {"_!=_",_SAME}, {"_%=_",_SAME}, {"_%_",_SAME}, {"_&&_",_SAME}, {"_'",_SAME}, {"_*=_",_SAME}, {"_*_",_SAME}, {"_++",_SAME}, {"_+=_",_SAME}, {"_+_",_SAME}, {"_--",_SAME}, {"_-=_",_SAME}, {"_-_",_SAME}, {"_.a1",_SAME}, {"_.a2",_SAME}, {"_.a3",_SAME}, {"_.a4",_SAME}, {"_.a6",_SAME}, {"_.area",_SAME}, {"_.b2",_SAME}, {"_.b4",_SAME}, {"_.b6",_SAME}, {"_.b8",_SAME}, {"_.bid",_SAME}, {"_.bnf",_SAME}, {"_.c4",_SAME}, {"_.c6",_SAME}, {"_.clgp",_SAME}, {"_.codiff",_SAME}, {"_.cyc",_SAME}, {"_.diff",_SAME}, {"_.disc",_SAME}, {"_.e",_SAME}, {"_.eta",_SAME}, {"_.f",_SAME}, {"_.fu",_SAME}, {"_.futu",_SAME}, {"_.gen",_SAME}, {"_.group",_SAME}, {"_.index",_SAME}, {"_.j",_SAME}, {"_.mod",_SAME}, {"_.nf",_SAME}, {"_.no",_SAME}, {"_.omega",_SAME}, {"_.orders",_SAME}, {"_.p",_SAME}, {"_.pol",_SAME}, {"_.r1",_SAME}, {"_.r2",_SAME}, {"_.reg",_SAME}, {"_.roots",_SAME}, {"_.sign",_SAME}, {"_.t2",_SAME}, {"_.tate",_SAME}, {"_.tu",_SAME}, {"_.tufu",_SAME}, {"_.zk",_SAME}, {"_.zkst",_SAME}, {"_/=_",_SAME}, {"_/_",_SAME}, {"_<<=_",_SAME}, {"_<<_",_SAME}, {"_<=_",_SAME}, {"_<_",_SAME}, {"_==_",_SAME}, {"_>=_",_SAME}, {"_>>=_",_SAME}, {"_>>_",_SAME}, {"_>_",_SAME}, {"_[_.._,_.._]",_SAME}, {"_[_.._]",_SAME}, {"_\\/=_",_SAME}, {"_\\/_",_SAME}, {"_\\=_",_SAME}, {"_\\_",_SAME}, {"_^_",_SAME}, {"_^s",_SAME}, {"__",_SAME}, {"_derivfun",_SAME}, {"_eval_mnemonic",_SAME}, {"_multi_if",_SAME}, {"_void_if",_SAME}, {"_||_",_SAME}, {"_~",_SAME}, {"O",_SAME}, {"O(_^_)",_SAME}, {"Str",_SAME}, {"abs",_SAME}, {"acos",_SAME}, {"acosh",_SAME}, {"addell","elladd","(e,z1,z2)","(e,z1,z2)"}, {"addprimes",_SAME}, {"adj","matadjoint","(x)","(x)"}, {"agm",_SAME}, {"akell","ellak","(e,n)","(e,n)"}, {"algdep",_SAME}, {"algdep2","algdep","(x,n,dec)","(x,n,dec)"}, {"algtobasis","nfalgtobasis","(nf,x)","(nf,x)"}, {"anell","ellan","(e,n)","(e,n)"}, {"apell","ellap","(e,n)","(e,n)"}, {"apell2","ellap","(e,n)","(e,n)"}, {"apprpadic","padicappr","(x,a)","(x,a)"}, {"arg",_SAME}, {"asin",_SAME}, {"asinh",_SAME}, {"assmat","matcompanion","(x)","(x)"}, {"atan",_SAME}, {"atanh",_SAME}, {"basis","nfbasis","(x)","(x)"}, {"basis2","nfbasis","(x)","(x,2)"}, {"basistoalg","nfbasistoalg","(nf,x)","(nf,x)"}, {"bernreal",_SAME}, {"bernvec",_SAME}, {"bestappr",_SAME}, {"bezout","gcdext","(a,b)","(a,b)"}, {"bezoutres",_SAME}, {"bigomega",_SAME}, {"bilhell","ellbil","(e,z1,z2)","(e,z1,z2)"}, {"bin","binomial","(x,y)","(x,y)"}, {"binary",_SAME}, {"bittest",_SAME}, {"boundcf","contfrac","(x,lmax)","(x,,lmax)"}, {"boundfact","factor","(x,lim)","(x,lim)"}, {"buchcertify","bnfcertify","(bnf)","(bnf)"}, {"buchfu",_REMOV}, {"buchgen",_REMOV}, {"buchgenforcefu",_REMOV}, {"buchgenfu",_REMOV}, {"buchimag","quadclassunit","(D,c1,c2,g)","(D,,[c1,c2,g])"}, {"buchinit","bnfinit","(P)","(P,2)"}, {"buchinitforcefu","bnfinit","(P)","(P,1)"}, {"buchinitfu","bnfinit","(P)","(P)"}, {"buchnarrow","bnfnarrow","(bnf)","(bnf)"}, {"buchray","bnrinit","(bnf,ideal)","(bnf,ideal)"}, {"buchrayinit","bnrinit","(bnf,ideal)","(bnf,ideal)"}, {"buchrayinitgen","bnrinit","(bnf,ideal)","(bnf,ideal,1)"}, {"buchreal","quadclassunit","(D)","(D)"}, {"bytesize","sizebyte","(x)","(x)"}, {"ceil",_SAME}, {"centerlift",_SAME}, {"cf","contfrac","(x)","(x)"}, {"cf2","contfrac","(b,x)","(x,b)"}, {"changevar",_REMOV}, {"char","charpoly","(x,y)","(x,y)"}, {"char1","charpoly","(x,y)","(x,y,1)"}, {"char2","charpoly","(x,y)","(x,y,2)"}, {"chell","ellchangecurve","(x,y)","(x,y)"}, {"chinese",_SAME}, {"chptell","ellchangepoint","(x,y)","(x,y)"}, {"classno","qfbclassno","(x)","(x)"}, {"classno2","qfbclassno","(x)","(x,1)"}, {"coeff","polcoeff","(x,s)","(x,s)"}, {"compimag","x*y","(x,y)",""}, {"compo","component","(x,s)","(x,s)"}, {"compositum","polcompositum","(pol1,pol2)","(pol1,pol2)"}, {"compositum2","polcompositum","(pol1,pol2)","(pol1,pol2,1)"}, {"comprealraw","qfbcompraw","(x,y)","(x,y)"}, {"concat",_SAME}, {"conductor","bnrconductor","(a1)","(a1)"}, {"conductorofchar","bnrconductorofchar","(bnr,chi)","(bnr,chi)"}, {"conj",_SAME}, {"conjvec",_SAME}, {"content",_SAME}, {"convol","serconvol","(x,y)","(x,y)"}, {"core",_SAME}, {"core2","core","(x)","(x,1)"}, {"coredisc",_SAME}, {"coredisc2","coredisc","(x)","(x,1)"}, {"cos",_SAME}, {"cosh",_SAME}, {"cvtoi","truncate","(x)","(x,&e)"}, {"cyclo","polcyclo","(n)","(n)"}, {"decodefactor","factorback","(fa)","(fa)"}, {"decodemodule","bnfdecodemodule","(nf,fa)","(nf,fa)"}, {"degree","poldegree","(x)","(x)"}, {"denom","denominator","(x)","(x)"}, {"deplin","lindep","(x)","(x,-1)"}, {"deriv",_SAME}, {"det","matdet","(x)","(x)"}, {"det2","matdet","(x)","(x,1)"}, {"detint","matdetint","(x)","(x)"}, {"diagonal","matdiagonal","(x)","(x)"}, {"dilog",_SAME}, {"dirdiv",_SAME}, {"direuler",_SAME}, {"dirmul",_SAME}, {"dirzetak",_SAME}, {"disc","poldisc","(x)","(x)"}, {"discf","nfdisc","(x)","(x)"}, {"discf2","nfdisc","(x)","(x,2)"}, {"discrayabs","bnrdisc","(bnr,subgroup)","(bnr,subgroup)"}, {"discrayabscond","bnrdisc","(bnr)","(bnr,,,2)"}, {"discrayabslist","bnrdisclist","(bnf,list)","(bnf,list)"}, {"discrayabslistarch","bnrdisclist","(bnf,arch,bound)","(bnf,bound,arch)"}, {"discrayabslistarchall","bnrdisclist","(bnf,bound)","(bnf,bound,,1)"}, {"discrayabslistlong","bnrdisclist","(bnf,bound)","(bnf,bound)"}, {"discrayrel","bnrdisc","(bnr,subgroup)","(bnr,subgroup,,1)"}, {"discrayrelcond","bnrdisc","(bnr,subgroup)","(bnr,subgroup,,3)"}, {"divisors",_SAME}, {"divres","divrem","(x,y)","(x,y)"}, {"divsum","sumdiv","(n,X,expr)","(n,X,expr)"}, {"eigen","mateigen","(x)","(x)"}, {"eint1",_SAME}, {"erfc",_SAME}, {"eta",_SAME}, {"euler","Euler","",""}, {"eval",_SAME}, {"exp",_SAME}, {"extract","vecextract","(x,y)","(x,y)"}, {"fact","factorial","(x)","(x)"}, {"factcantor","factorcantor","(x,p)","(x,p)"}, {"factfq","factorff","(x,p,a)","(x,p,a)"}, {"factmod","factormod","(x,p)","(x,p)"}, {"factor",_SAME}, {"factoredbasis","nfbasis","(x,p)","(x,,p)"}, {"factoreddiscf","nfdisc","(x,p)","(x,,p)"}, {"factoredpolred","polred","(x,p)","(x,,p)"}, {"factoredpolred2","polred","(x,p)","(x,2,p)"}, {"factornf",_SAME}, {"factorpadic",_SAME}, {"factorpadic2","factorpadic","(x,p,r)","(x,p,r,1)"}, {"factpol","factor","(x,l,hint)","(x)"}, {"factpol2","factor","(x,l,hint)","(x)"}, {"fibo","fibonacci","(x)","(x)"}, {"floor",_SAME}, {"for",_SAME}, {"fordiv",_SAME}, {"forprime",_SAME}, {"forstep",_SAME}, {"forvec",_SAME}, {"fpn","ffinit","(p,n)","(p,n)"}, {"frac",_SAME}, {"galois","polgalois","(x)","(x)"}, {"galoisapply","nfgaloisapply","(nf,aut,x)","(nf,aut,x)"}, {"galoisconj","nfgaloisconj","(nf)","(nf)"}, {"galoisconj1","nfgaloisconj","(nf)","(nf,2)"}, {"galoisconjforce","nfgaloisconj","","(nf,1)"}, {"gamh","gammah","(x)","(x)"}, {"gamma",_SAME}, {"gauss","matsolve","(a,b)","(a,b)"}, {"gaussmodulo","matsolvemod","(M,D,Y)","(M,D,Y)"}, {"gaussmodulo2","matsolvemod","(M,D,Y)","(M,D,Y,1)"}, {"gcd",_SAME}, {"getheap",_SAME}, {"getrand",_SAME}, {"getstack",_SAME}, {"gettime",_SAME}, {"globalred","ellglobalred","(x,y)","(x,y)"}, {"goto",_REMOV}, {"hclassno","qfbhclassno","(x)","(x)"}, {"hell","ellheight","(e,x)","(e,x)"}, {"hell2","ellheight","(e,x)","(e,x,1)"}, {"hermite","mathnf","(x)","(x)"}, {"hermite2","mathnf","(x)","(x,1)"}, {"hermitehavas",_REMOV}, {"hermitemod","mathnfmod","(x,d)","(x,d)"}, {"hermitemodid","mathnfmodid","(x,d)","(x,d)"}, {"hermiteperm","mathnf","(x)","(x,3)"}, {"hess","mathess","(x)","(x)"}, {"hilb","hilbert","(x,y)","(x,y)"}, {"hilbert","mathilbert","(n)","(n)"}, {"hilbp","hilbert","(x,y,p)","(x,y,p)"}, {"hvector","vector","(n,X,expr)","(n,X,expr)"}, {"hyperu",_SAME}, {"i","I","",""}, {"idealadd",_SAME}, {"idealaddmultone","idealaddtoone","(nf,list)","(nf,list)"}, {"idealaddone","idealaddtoone","(nf,x,y)","(nf,x,y)"}, {"idealappr",_SAME}, {"idealapprfact","idealappr","(nf,x)","(nf,x,1)"}, {"idealchinese",_SAME}, {"idealcoprime",_SAME}, {"idealdiv",_SAME}, {"idealdivexact","idealdiv","(nf,x,y)","(nf,x,y,1)"}, {"idealfactor",_SAME}, {"idealhermite","idealhnf","(nf,x)","(nf,x)"}, {"idealhermite2","idealhnf","(nf,x)","(nf,x)"}, {"idealintersect",_SAME}, {"idealinv",_SAME}, {"idealinv2","idealinv","(nf,x)","(nf,x,1)"}, {"ideallist",_SAME}, {"ideallistarch",_SAME}, {"ideallistarchgen","ideallistarch","(nf,list,arch)","(nf,list,arch)"}, {"ideallistunit","ideallist","(nf,list)","(nf,list,2)"}, {"ideallistunitarch","ideallistarch","","(nf,list,arch)"}, {"ideallistunitarchgen","ideallistarch","","(nf,list,arch)"}, {"ideallistunitgen","ideallist","","(nf,list,3)"}, {"ideallistzstar","ideallist","(nf,bound)","(nf,bound)"}, {"ideallistzstargen","ideallist","(nf,bound)","(nf,bound,1)"}, {"ideallllred","idealred","(nf,x,vdir)","(nf,x,vdir)"}, {"idealmul",_SAME}, {"idealmulred","idealmul","(nf,x,y)","(nf,x,y,1)"}, {"idealnorm",_SAME}, {"idealpow",_SAME}, {"idealpowred","idealpow","(nf,x,y)","(nf,x,y,1)"}, {"idealtwoelt",_SAME}, {"idealtwoelt2","idealtwoelt","(nf,x,a)","(nf,x,a)"}, {"idealval",_SAME}, {"idmat","matid","(n)","(n)"}, {"if",_SAME}, {"imag",_SAME}, {"image","matimage","(x)","(x)"}, {"image2","matimage","(x)","(x,1)"}, {"imagecompl","matimagecompl","(x)","(x)"}, {"incgam",_SAME}, {"incgam1",_REMOV}, {"incgam2",_REMOV}, {"incgam3",_REMOV}, {"incgam4","incgam","(s,x,y)","(s,x,y)"}, {"indexrank","matindexrank","(x)","(x)"}, {"indsort","vecsort","(x)","(x,,1)"}, {"initalg","nfinit","(pol)","(pol)"}, {"initalgred","nfinit","(x)","(x,2)"}, {"initalgred2","nfinit","(x)","(x,3)"}, {"initell","ellinit","(x)","(x)"}, {"initzeta",_REMOV}, {"integ","intformal","(x,y)","(x,y)"}, {"intersect","matintersect","(x,y)","(x,y)"}, {"intgen","intnum","(x=a,b,s)","(x=a,b,s,1)"}, {"intinf","intnum","(x=a,b,s)","(x=a,b,s,2)"}, {"intnum",_SAME}, {"intopen","intnum","(x=a,b,s)","(x=a,b,s,3)"}, {"inverseimage","matinverseimage","(x,y)","(x,y)"}, {"isdiagonal","matisdiagonal","(x)","(x)"}, {"isfund","isfundamental","(x)","(x)"}, {"isideal","nfisideal","(nf,x)","(nf,x)"}, {"isincl","nfisincl","(x,y)","(x,y)"}, {"isinclfast","nfisincl","(nf1,nf2)","(nf1,nf2,1)"}, {"isirreducible","polisirreducible","(x)","(x)"}, {"isisom","nfisisom","(x,y)","(x,y)"}, {"isisomfast","nfisisom","(x,y)","(x,y)"}, {"isoncurve","ellisoncurve","(e,x)","(e,x)"}, {"isprime",_SAME}, {"isprincipal","bnfisprincipal","(bnf,x)","(bnf,x,0)"}, {"isprincipalforce","bnfisprincipal","(bnf,x)","(bnf,x,2)"}, {"isprincipalgen","bnfisprincipal","(bnf,x)","(bnf,x)"}, {"isprincipalgenforce","bnfisprincipal","(bnf,x)","(bnf,x,3)"}, {"isprincipalray","bnrisprincipal","(bnf,x)","(bnf,x)"}, {"isprincipalraygen",_SAME}, {"ispsp","ispseudoprime","(x)","(x)"}, {"isqrt","sqrtint","(x)","(x)"}, {"isset","setisset","(x)","(x)"}, {"issqfree","issquarefree","(x)","(x)"}, {"issquare",_SAME}, {"isunit","bnfisunit","(bnf,x)","(bnf,x)"}, {"jacobi","qfjacobi","(x)","(x)"}, {"jbesselh","besseljh","(n,x)","(n,x)"}, {"jell","ellj","(x)","(x)"}, {"karamul",_REMOV}, {"kbessel","besselk","(nu,x)","(nu,x)"}, {"kbessel2","besselk","(nu,x)","(nu,x)"}, {"ker","matker","(x)","(x)"}, {"keri","matker","(x)","(x,1)"}, {"kerint","matkerint","(x)","(x)"}, {"kerint1","matkerint","(x)","(x,1)"}, {"kerint2",_REMOV}, {"kro","kronecker","(x,y)","(x,y)"}, {"label",_REMOV}, {"lambdak",_REMOV}, {"laplace","serlaplace","(x)","(x)"}, {"lcm",_SAME}, {"legendre","pollegendre","(n)","(n)"}, {"length",_SAME}, {"lex",_SAME}, {"lexsort","vecsort","(x)","(x,,2)"}, {"lift",_SAME}, {"lindep",_SAME}, {"lindep2","lindep","(x)","(x,1)"}, {"lll","qflll","(x)","(x)"}, {"lll1",_REMOV}, {"lllgen","qflll","(x)","(x,8)"}, {"lllgram","qflllgram","(x)","(x)"}, {"lllgram1",_REMOV}, {"lllgramgen","qflllgram","(x)","(x,8)"}, {"lllgramint","qflllgram","(x)","(x,1)"}, {"lllgramkerim","qflllgram","(x)","(x,4)"}, {"lllgramkerimgen","qflllgram","(x)","(x,5)"}, {"lllint","qflll","(x)","(x,1)"}, {"lllintpartial","qflll","(x)","(x,2)"}, {"lllkerim","qflll","(x)","(x,4)"}, {"lllkerimgen","qflll","(x)","(x,5)"}, {"lllrat",_REMOV}, {"ln","log","(x)","(x)"}, {"lngamma",_SAME}, {"localred","elllocalred","(e)","(e)"}, {"log",_SAME}, {"logagm","log","(x)","(x,1)"}, {"lseriesell","elllseries","(e,s,N,A)","(e,s,A)"}, {"makebigbnf","bnfinit","(sbnf)","(sbnf)"}, {"mat","Mat","(x)","(x)"}, {"matextract","vecextract","(x,y,z)","(x,y,z)"}, {"mathell","ellheightmatrix","(e,x)","(e,x)"}, {"matrix",_SAME}, {"matrixqz",_SAME}, {"matrixqz2","matrixqz","(x,p)","(x,-1)"}, {"matrixqz3","matrixqz","(x,p)","(x,-2)"}, {"matsize",_SAME}, {"max",_SAME}, {"min",_SAME}, {"minideal","idealmin","(nf,ix,vdir)","(nf,ix,vdir)"}, {"minim","qfminim","(x,bound,maxnum)","(x,bound,maxnum)"}, {"minim2","qfminim","(x,bound)","(x,bound,,1)"}, {"mod","Mod","(x,y)","(x,y)"}, {"modp","Mod","(x,y,p)","(x,y)"}, {"modreverse",_SAME}, {"modulargcd","gcd","(x,y)","(x,y,1)"}, {"mu","moebius","(n)","(n)"}, {"newtonpoly",_SAME}, {"nextprime",_SAME}, {"nfdetint",_SAME}, {"nfdiv","nfeltdiv","(nf,a,b)","(nf,a,b)"}, {"nfdiveuc","nfeltdiveuc","(nf,a,b)","(nf,a,b)"}, {"nfdivres","nfeltdivrem","(nf,a,b)","(nf,a,b)"}, {"nfhermite","nfhnf","(nf,x)","(nf,x)"}, {"nfhermitemod","nfhnfmod","(nf,x,detx)","(nf,x,detx)"}, {"nfmod","nfeltmod","(nf,a,b)","(nf,a,b)"}, {"nfmul","nfeltmul","(nf,a,b)","(nf,a,b)"}, {"nfpow","nfeltpow","(nf,a,k)","(nf,a,k)"}, {"nfreduce","nfeltreduce","(nf,a,id)","(nf,a,id)"}, {"nfsmith","nfsnf","(nf,x)","(nf,x)"}, {"nfval","nfeltval","(nf,a,pr)","(nf,a,pr)"}, {"norm",_SAME}, {"norml2",_SAME}, {"nucomp","qfbnucomp","(x,y,l)","(x,y,l)"}, {"numdiv",_SAME}, {"numer","numerator","(x)","(x)"}, {"nupow","qfbnupow","(x,n)","(x,n)"}, {"o","O","(x)","(x)"}, {"omega",_SAME}, {"ordell","ellordinate","(e,x)","(e,x)"}, {"order","znorder","(x)","(x)"}, {"orderell","ellorder","(e,x)","(e,x)"}, {"ordred","polredord","(x)","(x)"}, {"padicprec",_SAME}, {"pascal","matpascal","(n)","(n)"}, {"perf","qfperfection","(a)","(a)"}, {"permutation","numtoperm","(n,k)","(n,k)"}, {"permutation2num","permtonum","(vect)","(vect)"}, {"pf","qfbprimeform","(x,p)","(x,p)"}, {"phi","eulerphi","(x)","(x)"}, {"pi","Pi","",""}, {"pnqn","contfracpnqn","(x)","(x)"}, {"pointell","ellztopoint","(e,z)","(e,z)"}, {"polint","polinterpolate","(xa,ya,x)","(xa,ya,p)"}, {"polred",_SAME}, {"polred2","polred","(x)","(x,2)"}, {"polredabs",_SAME}, {"polredabs2","polredabs","(x)","(x,1)"}, {"polredabsall","polredabs","(x)","(x,4)"}, {"polredabsfast","polredabs","(x)","(x,8)"}, {"polredabsnored","polredabs","(x)","(x,2)"}, {"polsym",_SAME}, {"polvar","variable","(x)","(x)"}, {"poly","Pol","(x,v)","(x,v)"}, {"polylog",_SAME}, {"polylogd","polylog","(m,x)","(m,x,1)"}, {"polylogdold","polylog","(m,x)","(m,x,2)"}, {"polylogp","polylog","(m,x)","(m,x,3)"}, {"polyrev","Polrev","(x,v)","(x,v)"}, {"polzag","polzagier","(n,m)","(n,m)"}, {"powell","ellmul","(e,x,n)","(e,x,n)"}, {"powrealraw","qfbpowraw","(x,n)","(x,n)"}, {"prec","precision","(x,n)","(x,n)"}, {"precision",_SAME}, {"prime",_SAME}, {"primedec","idealprimedec","(nf,p)","(nf,p)"}, {"primes",_SAME}, {"primroot","znprimroot","(n)","(n)"}, {"principalideal",_REMOV}, {"principalidele",_REMOV}, {"prod","prod","(x,X=a,b,expr)","(X=a,b,expr,x)"}, {"prodeuler",_SAME}, {"prodinf",_SAME}, {"prodinf1","prodinf","(X=a,expr)","(X=a,expr,1)"}, {"psi",_SAME}, {"qfi","Qfb","(a,b,c)","(a,b,c)"}, {"qfr","Qfb","(a,b,c,d)","(a,b,c,d)"}, {"quaddisc",_SAME}, {"quadgen",_SAME}, {"quadpoly",_SAME}, {"random",_SAME}, {"rank","matrank","(x)","(x)"}, {"rayclassno","bnrclassno","(bnf,x)","(bnf,x)"}, {"rayclassnolist","bnrclassnolist","(bnf,liste)","(bnf,liste)"}, {"real",_SAME}, {"recip","polrecip","(x)","(x)"}, {"redimag","qfbred","(x)","(x)"}, {"redreal","qfbred","(x)","(x)"}, {"redrealnod","qfbred","(x,d)","(x,2,,d)"}, {"reduceddisc","poldiscreduced","(f)","(f)"}, {"regula","quadregulator","(x)","(x)"}, {"reorder",_REMOV}, {"resultant","polresultant","(x,y)","(x,y)"}, {"resultant2","polresultant","(x,y)","(x,y,1)"}, {"reverse","serreverse","(x)","(x)"}, {"rhoreal","qfbred","(x)","(x,1)"}, {"rhorealnod","qfbred","(x,d)","(x,3,,d)"}, {"rndtoi","round","(x)","(x,&e)"}, {"rnfbasis",_SAME}, {"rnfdiscf","rnfdisc","(nf,pol)","(nf,pol)"}, {"rnfequation",_SAME}, {"rnfequation2","rnfequation","(nf,pol)","(nf,pol,1)"}, {"rnfhermitebasis","rnfhnfbasis","(bnf,order)","(bnf,order)"}, {"rnfisfree",_SAME}, {"rnflllgram",_SAME}, {"rnfpolred",_SAME}, {"rnfpseudobasis",_SAME}, {"rnfsteinitz",_SAME}, {"rootmod","polrootsmod","(x,p)","(x,p)"}, {"rootmod2","polrootsmod","(x,p)","(x,p)"}, {"rootpadic","polrootspadic","(x,p,r)","(x,p,r)"}, {"roots","polroots","(x)","(x)"}, {"rootsof1","nfrootsof1","(nf)","(nf)"}, {"rootsold",_REMOV}, {"round",_SAME}, {"rounderror","round","(x)","(x,&e)"}, {"series","Ser","(x,v)","(x,v)"}, {"set","Set","(x)","(x)"}, {"setintersect",_SAME}, {"setminus",_SAME}, {"setrand",_SAME}, {"setsearch",_SAME}, {"setunion",_SAME}, {"shift",_SAME}, {"shiftmul",_SAME}, {"sigma",_SAME}, {"sigmak","sigma","(k,x)","(x,k)"}, {"sign",_SAME}, {"signat","qfsign","(x)","(x)"}, {"signunit","bnfsignunit","(bnf)","(bnf)"}, {"simplefactmod","factormod","(x,p)","(x,p,1)"}, {"simplify",_SAME}, {"sin",_SAME}, {"sinh",_SAME}, {"size","sizedigit","(x)","(x)"}, {"smallbasis","nfbasis","(x)","(x,1)"}, {"smallbuchinit",_REMOV}, {"smalldiscf","nfdisc","(x)","(x,1)"}, {"smallfact","factor","(x)","(x,0)"}, {"smallinitell","ellinit","(x)","(x,1)"}, {"smallpolred","polred","(x)","(x,1)"}, {"smallpolred2","polred","(x)","(x,3)"}, {"smith","matsnf","(x)","(x)"}, {"smith2","matsnf","(x)","(x,1)"}, {"smithclean","matsnf","(x)","(x,4)"}, {"smithpol","matsnf","(x)","(x,2)"}, {"solve",_SAME}, {"sort","vecsort","(x)","(x)"}, {"sqr",_SAME}, {"sqred","qfgaussred","(x)","(x)"}, {"sqrt",_SAME}, {"srgcd","gcd","(x,y)","(x,y,2)"}, {"sturm","polsturm","(x)","(x)"}, {"sturmpart","polsturm","(x,a,b)","(x,a,b)"}, {"subcyclo","polsubcyclo","(p,d)","(p,d)"}, {"subell","ellsub","(e,a,b)","(e,a,b)"}, {"subst",_SAME}, {"sum","sum","(x,X=a,b,expr)","(X=a,b,expr,x)"}, {"sumalt",_SAME}, {"sumalt2","sumalt","(X=a,expr)","(X=a,expr,1)"}, {"suminf",_SAME}, {"sumpos",_SAME}, {"sumpos2","sumpos","(X=a,expr)","(X=a,expr,1)"}, {"supplement","matsupplement","(x)","(x)"}, {"sylvestermatrix","polsylvestermatrix","(x,y)","(x,y)"}, {"system",_SAME}, {"tan",_SAME}, {"tanh",_SAME}, {"taniyama","elltaniyama","(e)","(e)"}, {"taylor",_SAME}, {"tchebi","polchebyshev","(n)","(n)"}, {"teich","teichmuller","(x)","(x)"}, {"theta",_SAME}, {"thetanullk",_SAME}, {"threetotwo",_REMOV}, {"threetotwo2",_REMOV}, {"torsell","elltors","(e)","(e)"}, {"trace",_SAME}, {"trans","mattranspose","(x)","(x)"}, {"trunc","truncate","(x)","(x)"}, {"tschirnhaus","poltschirnhaus","(x)","(x)"}, {"twototwo",_REMOV}, {"unit","quadunit","(x)","(x)"}, {"until",_SAME}, {"valuation",_SAME}, {"vec","Vec","(x)","(x)"}, {"vecindexsort","vecsort","(x)","(x,,1)"}, {"veclexsort","vecsort","(x)","(x,,2)"}, {"vecmax",_SAME}, {"vecmin",_SAME}, {"vecsort",_SAME}, {"vector",_SAME}, {"vvector","vectorv","(n,X,expr)","(n,X,expr)"}, {"weipell","ellwp","(e)","(e)"}, {"wf","weber","(x)","(x)"}, {"wf2","weber","(x)","(x,2)"}, {"while",_SAME}, {"zell","ellpointtoz","(e,P)","(e,P)"}, {"zeta",_SAME}, {"zetak","lfun","(nfz,s)","(L,s)"}, {"zideallog","ideallog","(nf,x,bid)","(nf,x,bid)"}, {"zidealstar","idealstar","(nf,I)","(nf,I)"}, {"zidealstarinit","idealstar","(nf,id)","(nf,id,1)"}, {"zidealstarinitgen","idealstar","(nf,id)","(nf,id,2)"}, {"znstar",_SAME}, {"allocatemem",_SAME}, {"box","plotbox","(x,a)","(x,a)"}, {"color","plotcolor","(w,c)","(w,c)"}, {"cursor","plotcursor","(w)","(w)"}, {"default",_SAME}, {"draw","plotdraw","(list)","(list)"}, {"plotinit","plotinit","(w,x,y)","(w,x,y)"}, {"kill",_SAME}, {"plotkill","plotkill","(w)","(w)"}, {"line","plotlines","(w,x2,y2)","(w,x2,y2)"}, {"lines","plotlines","(w,x2,y2)","(w,x2,y2)"}, {"move","plotmove","(w,x,y)","(w,x,y)"}, {"plot",_SAME}, {"ploth",_SAME}, {"ploth2","ploth","(X=a,b,expr)","(X=a,b,expr,1)"}, {"plothmult","ploth","(X=a,b,expr)","(X=a,b,expr)"}, {"plothraw",_SAME}, {"point","plotpoints","(w,x,y)","(w,x,y)"}, {"points","plotpoints","(w,x,y)","(w,x,y)"}, {"psdraw","psdraw","(list)","(list)"}, {"psploth","psploth","(X=a,b,expr)","(X=a,b,expr)"}, {"postploth2","psploth","(X=a,b,expr)","(X=a,b,expr,1)"}, {"psplothraw","psplothraw","(listx,listy)","(listx,listy)"}, {"pprint",_REMOV}, {"pprint1",_REMOV}, {"print",_SAME}, {"print1",_SAME}, {"rbox","plotrbox","(w,dx,dy)","(w,dx,dy)"}, {"read","input","(x)","(x)"}, {"rline","plotrline","(w,dx,dy)","(w,dx,dy)"}, {"rlines","plotrlines","(w,dx,dy)","(w,dx,dy,1)"}, {"rmove","plotrmove","(w,dx,dy)","(w,dx,dy)"}, {"rpoint","plotrpoint","(w,dx,dy)","(w,dx,dy)"}, {"rpoints","plotrpoints","(w,dx,dy)","(w,dx,dy)"}, {"scale","plotscale","(w,x1,x2,y1,y2)","(w,x1,x2,y1,y2)"}, {"setprecision","default","(n)","(realprecision,n)"}, {"setserieslength","default","(n)","(seriesprecision,n)"}, {"settype","type","(x,t)","(x,t)"}, {"string","plotstring","(w,x)","(w,x)"}, {"texprint","printtex","(x)","(x)"}, {"type",_SAME}, /* not in 1.39.15 */ {"intfouriercos",_REMOV}, {"intfouriersin",_REMOV}, {"intfourierexp",_REMOV}, {"intlaplaceinv",_REMOV}, {"intmellininv",_REMOV}, {"intmellininvshort",_REMOV}, {"zetakinit","lfuninit","(T)","(T,sdom)"}, {NULL,_SAME} }; pari-2.17.2/src/gp/whatnow.c0000644000175000017500000000440314567450071014226 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #include "gp.h" #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) { const char *def; const whatnow_t *wp = whatnowlist; entree *ep; while (wp->old && strcmp(wp->old,s)) wp++; /* Above linear search is slow, esp. if the symbol is not found. BUT no * point in wasting time by preallocating [ or autoloading ] a hashtable: * whatnow() is never used in a case where speed would be necessary */ if (!wp->old) { if (!flag) msg(out, "This function did not exist in Pari 1.39"); return 0; } 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. Please update your script."); out_putc(out, '\n'); } if (def == REMOV) { msg(out, "This function no longer exists"); return 0; } /* special case compimag -> x*y */ if (!strcmp(def,"x*y")) def = "_*_"; ep = is_entry(def); if (!ep) pari_err_BUG("whatnow"); out_puts(out, "New syntax: "); out_term_color(out, c_ERR); out_printf(out, "%s%s ===> %s%s\n\n", s, wp->oldarg, wp->name, wp->newarg); msg(out, ep->help); out_term_color(out, c_NONE); return 1; } pari-2.17.2/src/gp/emacs.c0000644000175000017500000000214414567450071013627 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*******************************************************************/ /* */ /* EMACS FRONTEND */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" #include "gp.h" void init_emacs(void) { GP_DATA->breakloop = 0; disable_color = 1; } pari-2.17.2/src/gp/gp_rl.c0000644000175000017500000003111114676526175013650 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*******************************************************************/ /* */ /* 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 */ BEGINEXTERN /* otherwise C++ compilers will choke on rl_message() prototype */ #define USE_VARARGS #define PREFER_STDARG #include #include ENDEXTERN /**************************************************************************/ static pari_rl_interface pari_rl; static int did_init_matched = 0; static int change_state(const char *msg, ulong flag, int count) { int c = (GP_DATA->readline_state & flag) != 0; ulong state = GP_DATA->readline_state; switch(count) { default: c = 0; break; /* off */ case -1: c = 1; break; /* on */ case -2: c = 1 - c; /* toggle */ } if (c) GP_DATA->readline_state |= flag; else { GP_DATA->readline_state &= ~flag; if (!GP_DATA->readline_state && state) GP_DATA->readline_state = 1; } rl_save_prompt(); rl_message("[%s: %s] ", msg, c? "on": "off"); c = rl_read_key(); rl_restore_prompt(); rl_clear_message(); rl_stuff_char(c); return 1; } /* Wrapper around rl_complete to allow toggling insertion of arguments */ static int pari_rl_complete(int count, int key) { int ret; pari_rl.back = 0; if (count <= 0) return change_state("complete args", DO_ARGS_COMPLETE, count); rl_begin_undo_group(); if (rl_last_func == pari_rl_complete) rl_last_func = (RLCI) rl_complete; /* Make repeated TABs different */ ret = ((RLCI)rl_complete)(count,key); if (pari_rl.back && (pari_rl.back <= rl_point)) rl_point -= pari_rl.back; rl_end_undo_group(); return ret; } static int did_matched_insert; static int pari_rl_matched_insert_suspend(int count, int key) { ulong state = GP_DATA->readline_state; (void)count; (void)key; did_matched_insert = (GP_DATA->readline_state & DO_MATCHED_INSERT); GP_DATA->readline_state &= ~DO_MATCHED_INSERT; if (!GP_DATA->readline_state && state) GP_DATA->readline_state = 1; return 1; } static int pari_rl_matched_insert_restore(int count, int key) { (void)count; (void)key; if (did_matched_insert) GP_DATA->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] || !(GP_DATA->readline_state & DO_MATCHED_INSERT) || GP_DATA->flags & gpd_EMACS) return ((RLCI)rl_insert)(count,key); rl_begin_undo_group(); ((RLCI)rl_insert)(count,key); 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; GP_DATA->readline_state |= DO_MATCHED_INSERT; } return pari_rl_matched_insert(count, key); } static int pari_rl_forward_sexp(int count, int key) { int deep = 0, dir = 1, move_point = 0, lfail; (void)key; if (count < 0) { count = -count; dir = -1; if (!rl_point) goto fail; rl_point--; } while (count || deep) { move_point = 1; /* Need to move point if moving left. */ lfail = 0; /* Do not need to fail left movement yet. */ while ( !is_keyword_char(rl_line_buffer[rl_point]) && !strchr("\"([{}])",rl_line_buffer[rl_point]) && !( (dir == 1) ? (rl_point >= rl_end) : (rl_point <= 0 && (lfail = 1)))) rl_point += dir; if (lfail || !rl_line_buffer[rl_point]) goto fail; if (is_keyword_char(rl_line_buffer[rl_point])) { while ( is_keyword_char(rl_line_buffer[rl_point]) && (!((dir == 1) ? (rl_point >= rl_end) : (rl_point <= 0 && (lfail = 1))) || (move_point = 0))) rl_point += dir; if (deep && lfail) goto fail; if (!deep) count--; } else if (strchr(paropen,rl_line_buffer[rl_point])) { if (deep == 0 && dir == -1) goto fail; /* We are already out of pars. */ rl_point += dir; deep++; if (!deep) count--; } else if (strchr(parclose,rl_line_buffer[rl_point])) { if (deep == 0 && dir == 1) { rl_point++; goto fail; /* Get out of pars. */ } rl_point += dir; deep--; if (!deep) count--; } else if (rl_line_buffer[rl_point] == '\"') { int bad = 1; rl_point += dir; while ( ((rl_line_buffer[rl_point] != '\"') || (bad = 0)) && (!((dir == 1) ? (rl_point >= rl_end) : (rl_point <= 0)) || (move_point = 0)) ) rl_point += dir; if (bad) goto fail; rl_point += dir; /* Skip the other delimiter */ if (!deep) count--; } else { fail: rl_ding(); return 1; } } if (dir != 1 && move_point) rl_point++; return 1; } static int pari_rl_backward_sexp(int count, int key) { return pari_rl_forward_sexp(-count, key); } static void rl_print_aide(char *s, int flag) { int p = rl_point, e = rl_end; FILE *save = pari_outfile; rl_point = 0; rl_end = 0; pari_outfile = rl_outstream; rl_save_prompt(); rl_message("%s",""); /* rl_message("") ==> "zero length format" warning */ gp_help(s, flag); rl_restore_prompt(); rl_point = p; rl_end = e; pari_outfile = save; rl_clear_message(); rl_refresh_line(0,0); } /* 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) { char *h = GP_DATA->histfile; if (h && read_history(h)) write_history(h); } /*******************************************************************/ /* */ /* GET LINE FROM READLINE */ /* */ /*******************************************************************/ static int history_is_new(char *s) { HIST_ENTRY *e; if (!*s) return 0; if (!history_length) return 1; e = history_get(history_base+history_length-1); /* 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,GP_DATA->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) { pari_sp av = avma; Buffer *b = F->buf; ulong used = *endp - b->buf; ulong left = b->len - used, l; const char *p; char *s, *t; if (first) p = IM->prompt; else { p = F->in_comment ? GP_DATA->prompt_comment: IM->prompt_cont; p = gp_format_prompt(p); } if (! (s = readline(p)) ) { set_avma(av); return NULL; } /* EOF */ gp_add_history(s); /* Makes a copy */ l = strlen(s) + 1; /* put back \n that readline stripped. This is needed for * { print("a * b"); } * and conforms with the other input methods anyway. */ t = (char*)pari_malloc(l + 1); memcpy(t, s, l-1); pari_free(s); /* readline use malloc */ 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; } set_avma(av); 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; if (!GP_DATA->use_readline) { pari_puts(prompt); pari_flush(); return get_line_from_file(prompt, F, pari_infile); } IM.prompt = prompt; IM.prompt_cont = prompt_cont; IM.getline = &gprl_input; 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); } gp_echo_and_log(prompt, s); } return 1; } static char** gp_completion(char *text, int START, int END) { return pari_completion(&pari_rl, text, START, END); } void init_readline(void) { static int init_done = 0; if (init_done) return; pari_use_readline(pari_rl); if (! GP_DATA->use_readline) GP_DATA->readline_state = 0; init_done = 1; init_histfile(); cb_pari_init_histfile = init_histfile; cb_pari_get_line_interactive = get_line_from_readline; /* Allow conditional parsing of the ~/.inputrc file. */ rl_readline_name = "Pari-GP"; /* added ~, ? and , */ rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{(?~"; rl_special_prefixes = "~"; /* custom completer */ rl_attempted_completion_function = (rl_completion_func_t*) gp_completion; /* we always want the whole list of completions under emacs */ if (GP_DATA->flags & gpd_EMACS) rl_completion_query_items = 0x8fff; rl_add_defun("short-help", rl_short_help, -1); rl_add_defun("long-help", rl_long_help, -1); rl_add_defun("pari-complete", pari_rl_complete, '\t'); rl_add_defun("pari-matched-insert", pari_rl_default_matched_insert, -1); rl_add_defun("pari-matched-insert-suspend", pari_rl_matched_insert_suspend, -1); rl_add_defun("pari-matched-insert-restore", pari_rl_matched_insert_restore, -1); rl_add_defun("pari-forward-sexp", pari_rl_forward_sexp, -1); rl_add_defun("pari-backward-sexp", pari_rl_backward_sexp, -1); rl_bind_key_in_map('h', rl_short_help, emacs_meta_keymap); rl_bind_key_in_map('H', rl_long_help, emacs_meta_keymap); #define KSbind(s,f,k) rl_generic_bind(ISFUNC, (s), (char*)(f), (k)) KSbind("OP", rl_short_help, emacs_meta_keymap); /* f1, vt100 */ KSbind("[11~", rl_short_help, emacs_meta_keymap); /* f1, xterm */ KSbind("OP", rl_short_help, vi_movement_keymap); /* f1, vt100 */ KSbind("[11~", rl_short_help, vi_movement_keymap); /* f1, xterm */ /* XTerm may signal start/end of paste by emitting F200/F201 * TODO: check to what extent this patch has been applied */ /* FIXME: For vi mode something more intelligent is needed - to switch to the insert mode - and back when restoring. */ KSbind("[200~", pari_rl_matched_insert_suspend, emacs_meta_keymap); /* pre-paste xterm */ KSbind("[200~", pari_rl_matched_insert_suspend, vi_movement_keymap); /* pre-paste xterm */ KSbind("[201~", pari_rl_matched_insert_restore, emacs_meta_keymap); /* post-paste xterm */ KSbind("[201~", pari_rl_matched_insert_restore, vi_movement_keymap); /* post-paste xterm */ rl_bind_key_in_map('(', pari_rl_matched_insert, emacs_standard_keymap); rl_bind_key_in_map('[', pari_rl_matched_insert, emacs_standard_keymap); rl_bind_key_in_map(6, pari_rl_forward_sexp, emacs_meta_keymap); /* M-C-f */ rl_bind_key_in_map(2, pari_rl_backward_sexp, emacs_meta_keymap); /* M-C-b */ } #endif pari-2.17.2/src/gp/gp_init.h0000644000175000017500000000140714760125440014170 0ustar billbill/* This file is autogenerated from the database. */ /* See src/desc/gen_proto */ /* Do not edit*/ entree functions_gp[]={ {"dbg_down",0,(void*)dbg_down,1,"vD1,L,","dbg_down({n=1}): (break loop) go down n frames. Cancel a previous dbg_up."}, {"dbg_err",0,(void*)dbg_err,1,"","dbg_err(): (break loop) return the error data of the current error, if any."}, {"dbg_up",0,(void*)dbg_up,1,"vD1,L,","dbg_up({n=1}): (break loop) go up n frames, which allows to inspect data of the parent function."}, {"quit",0,(void*)gp_quit,1,"vD0,L,","quit({status = 0}): quit, return to the system with exit status 'status'."}, {"whatnow",0,(void*)whatnow0,1,"vr","whatnow(key): if key was present in GP version 1.39.15, gives the new function name."}, {NULL,0,NULL,0,NULL,NULL} /* sentinel */ }; pari-2.17.2/src/basemath/0000755000175000017500000000000014760315601013542 5ustar billbillpari-2.17.2/src/basemath/dirichlet.c0000644000175000017500000006372314760123736015676 0ustar billbill/* Copyright (C) 2015 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /********************************************************************/ /** **/ /** Dirichlet series through Euler product **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" static void err_direuler(GEN x) { pari_err_DOMAIN("direuler","constant term","!=", gen_1,x); } /* s = t_POL (tolerate t_SER of valuation 0) of constant term = 1 * d = minimal such that p^d > X * V indexed by 1..X will contain the a_n * v[1..n] contains the indices nj such that V[nj] != 0 */ static long dirmuleuler_small(GEN V, GEN v, long n, ulong p, GEN s, long d) { long i, j, m = n, D = minss(d+2, lg(s)); ulong q = 1, X = lg(V)-1; for (i = 3, q = p; i < D; i++, q *= p) /* q*p does not overflow */ { GEN aq = gel(s,i); if (gequal0(aq)) continue; /* j = 1 */ gel(V,q) = aq; v[++n] = q; for (j = 2; j <= m; j++) { ulong nj = umuluu_le(uel(v,j), q, X); if (!nj) continue; gel(V,nj) = gmul(aq, gel(V,v[j])); v[++n] = nj; } } return n; } /* ap != 0 for efficiency, p > sqrt(X) */ static void dirmuleuler_large(GEN V, ulong p, GEN ap) { long j, jp, X = lg(V)-1; gel(V,p) = ap; for (j = 2, jp = 2*p; jp <= X; j++, jp += p) gel(V,jp) = gmul(ap, gel(V,j)); } static ulong direulertou(GEN a, GEN fl(GEN)) { if (typ(a) != t_INT) { a = fl(a); if (typ(a) != t_INT) pari_err_TYPE("direuler", a); } return signe(a)<=0 ? 0: itou(a); } static GEN direuler_Sbad(GEN V, GEN v, GEN Sbad, ulong *n) { long i, l = lg(Sbad); ulong X = lg(V)-1; GEN pbad = gen_1; for (i = 1; i < l; i++) { GEN ai = gel(Sbad,i); ulong q; if (typ(ai) != t_VEC || lg(ai) != 3) pari_err_TYPE("direuler [bad primes]",ai); q = gtou(gel(ai,1)); if (q <= X) { long d = ulogint(X, q) + 1; GEN s = direuler_factor(gel(ai,2), d); *n = dirmuleuler_small(V, v, *n, q, s, d); pbad = muliu(pbad, q); } } return pbad; } GEN direuler_bad(void *E, GEN (*eval)(void *,GEN,long), GEN a,GEN b,GEN c, GEN Sbad) { ulong au, bu, X, sqrtX, n, p; pari_sp av0 = avma; GEN gp, v, V; forprime_t T; au = direulertou(a, gceil); bu = direulertou(b, gfloor); X = c ? direulertou(c, gfloor): bu; if (X == 0) return cgetg(1,t_VEC); if (bu > X) bu = X; if (!u_forprime_init(&T, au, bu)) { set_avma(av0); return mkvec(gen_1); } v = vecsmall_ei(X, 1); V = vec_ei(X, 1); n = 1; if (Sbad) Sbad = direuler_Sbad(V, v, Sbad, &n); p = 1; gp = cgetipos(3); sqrtX = usqrt(X); while (p <= sqrtX && (p = u_forprime_next(&T))) if (!Sbad || umodiu(Sbad, p)) { long d = ulogint(X, p) + 1; /* minimal d such that p^d > X */ GEN s; gp[2] = p; s = eval(E, gp, d); n = dirmuleuler_small(V, v, n, p, s, d); } while ((p = u_forprime_next(&T))) /* sqrt(X) < p <= X */ if (!Sbad || umodiu(Sbad, p)) { GEN s; gp[2] = p; s = eval(E, gp, 2); /* s either t_POL or t_SER of val 0 */ if (lg(s) > 3 && !gequal0(gel(s,3))) dirmuleuler_large(V, p, gel(s,3)); } return gerepilecopy(av0,V); } /* return a t_SER or a truncated t_POL to precision n */ GEN direuler_factor(GEN s, long n) { long t = typ(s); if (is_scalar_t(t)) { if (!gequal1(s)) err_direuler(s); return scalarpol_shallow(s,0); } switch(t) { case t_POL: break; /* no need to RgXn_red */ case t_RFRAC: { GEN p = gel(s,1), q = gel(s,2); q = RgXn_red_shallow(q,n); s = RgXn_inv(q, n); if (typ(p) == t_POL && varn(p) == varn(q)) { p = RgXn_red_shallow(p, n); s = RgXn_mul(s, p, n); } else if (!gequal1(p)) s = RgX_Rg_mul(s, p); if (!signe(s) || !gequal1(gel(s,2))) err_direuler(s); break; } case t_SER: if (!signe(s) || valser(s) || !gequal1(gel(s,2))) err_direuler(s); break; default: pari_err_TYPE("direuler", s); } return s; } struct eval_bad { void *E; GEN (*eval)(void *, GEN); }; static GEN eval_bad(void *E, GEN p, long n) { struct eval_bad *d = (struct eval_bad*) E; return direuler_factor(d->eval(d->E, p), n); } GEN direuler(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, GEN c) { struct eval_bad d; d.E= E; d.eval = eval; return direuler_bad((void*)&d, eval_bad, a, b, c, NULL); } static GEN primelist(forprime_t *T, GEN Sbad, long n, long *running) { GEN P = cgetg(n+1, t_VECSMALL); long i, j; for (i = 1, j = 1; i <= n; i++) { ulong p = u_forprime_next(T); if (!p) { *running = 0; break; } if (Sbad && umodiu(Sbad, p)==0) continue; uel(P,j++) = p; } setlg(P, j); return P; } GEN pardireuler(GEN worker, GEN a, GEN b, GEN c, GEN Sbad) { ulong au, bu, X, sqrtX, n, snX, nX; pari_sp av0 = avma; GEN v, V; forprime_t T; struct pari_mt pt; long running = 1, pending = 0; au = direulertou(a, gceil); bu = direulertou(b, gfloor); X = c ? direulertou(c, gfloor): bu; if (X == 0) return cgetg(1,t_VEC); if (bu > X) bu = X; if (!u_forprime_init(&T, au, bu)) { set_avma(av0); return mkvec(gen_1); } v = vecsmall_ei(X, 1); V = vec_ei(X, 1); n = 1; if (Sbad) Sbad = direuler_Sbad(V, v, Sbad, &n); sqrtX = usqrt(X); snX = uprimepi(sqrtX); nX = uprimepi(X); if (snX) { GEN P = primelist(&T, Sbad, snX, &running); GEN R = gel(closure_callgenvec(worker, mkvec2(P, utoi(X))), 2); long i, l = lg(P); for (i = 1; i < l; i++) { GEN s = gel(R,i); n = dirmuleuler_small(V, v, n, uel(P,i), s, lg(s)); } } else snX = 1; mt_queue_start_lim(&pt, worker, (nX+snX-1)/snX); while (running || pending) { GEN done; GEN P = running? primelist(&T, Sbad, snX, &running): NULL; mt_queue_submit(&pt, 0, P ? mkvec2(P, utoi(X)): NULL); done = mt_queue_get(&pt, NULL, &pending); if (done) { GEN P = gel(done,1), R = gel(done,2); long j, l = lg(P); for (j=1; j>= 1; Bk = B * k; for (i = 1; i <= N; i += 2) gel(v, i << k) = shifti(gel(v, i), Bk); } } return v; } v = const_vec(N, NULL); u_forprime_init(&T, 3, N); while ((p = u_forprime_next(&T))) { long m, pk, oldpk; gel(v,p) = powuu(p, B); for (pk = p, oldpk = p; pk; oldpk = pk, pk = umuluu_le(pk,p,N)) { if (pk != p) gel(v,pk) = mulii(gel(v,oldpk), gel(v,p)); for (m = N/pk; m > 1; m--) if (gel(v,m) && m%p) gel(v, m*pk) = mulii(gel(v,m), gel(v,pk)); } } gel(v,1) = gen_1; for (i = 2; i <= N; i+=2) { long vi = vals(i); gel(v,i) = shifti(gel(v,i >> vi), B * vi); } return v; } /* does x^s require log(x) ? */ static long get_needlog(GEN s) { switch(typ(s)) { case t_REAL: return 2; /* yes but not powcx */ case t_COMPLEX: return 1; /* yes using powcx */ default: return 0; /* no */ } } /* [1^B,...,N^B] */ GEN vecpowug(long N, GEN B, long prec) { GEN v, logp = NULL; long gp[] = {evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3),0}; long p, precp = 2, prec0, prec1, needlog; forprime_t T; if (N == 1) return mkvec(gen_1); if (typ(B) == t_INT && lgefint(B) <= 3 && signe(B) >= 0) return vecpowuu(N, itou(B)); needlog = get_needlog(B); prec1 = prec0 = prec; if (needlog == 1) prec1 = powcx_prec(log2((double)N), B, prec); u_forprime_init(&T, 2, N); v = const_vec(N, NULL); gel(v,1) = gen_1; while ((p = u_forprime_next(&T))) { long m, pk, oldpk; GEN u; gp[2] = p; if (needlog) { if (!logp) logp = logr_abs(utor(p, prec1)); else { /* Assuming p and precp are odd, * log p = log(precp) + 2 atanh((p - precp) / (p + precp)) */ ulong a = p >> 1, b = precp >> 1; /* p = 2a + 1, precp = 2b + 1 */ GEN z = atanhuu(a - b, a + b + 1, prec1); /* avoid overflow */ shiftr_inplace(z, 1); logp = addrr(logp, z); } u = needlog == 1? powcx(gp, logp, B, prec0) : mpexp(gmul(B, logp)); if (p == 2) logp = NULL; /* reset: precp must be odd */ } else u = gpow(gp, B, prec0); precp = p; gel(v,p) = u; /* p^B */ if (prec0 != prec) gel(v,p) = gprec_wtrunc(gel(v,p), prec); for (pk = p, oldpk = p; pk; oldpk = pk, pk = umuluu_le(pk,p,N)) { if (pk != p) gel(v,pk) = gmul(gel(v,oldpk), gel(v,p)); for (m = N/pk; m > 1; m--) if (gel(v,m) && m%p) gel(v, m*pk) = gmul(gel(v,m), gel(v,pk)); } } return v; } GEN dirpowers(long n, GEN x, long prec) { pari_sp av; GEN v; if (n <= 0) return cgetg(1, t_VEC); av = avma; v = vecpowug(n, x, prec); if (typ(x) == t_INT && lgefint(x) <= 3 && signe(x) >= 0 && cmpiu(x, 2) <= 0) return v; return gerepilecopy(av, v); } /* f is a totally multiplicative function of modulus 0 or 1 * (essentially a Dirichlet character). Compute simultaneously * sum_{0 < n <= N} f(n)n^s and sum_{0 < n <= N} f(n)n^{-1-conj(s)} * Warning: s is conjugated, but not f. Main application for Riemann-Siegel, * where we need R(chi,s) and conj(R(chi,1-conj(s))). */ static GEN vecmulsqlv(GEN Q, GEN V) { long l, i; GEN W; if (typ(V) != t_VEC) return RgV_Rg_mul(Q, V); l = lg(Q); W = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(W, i) = vecmul(gel(Q, i), V); return W; } /* P = prime divisors of (squarefree) n, V[i] = i^s for i <= sq. * Return NULL if n is not sq-smooth, else f(n)n^s */ static GEN smallfact(ulong n, GEN P, ulong sq, GEN V) { long i, l; ulong p, m, o; GEN c; if (n <= sq) return gel(V,n); l = lg(P); m = p = uel(P, l-1); if (p > sq) return NULL; for (i = l-2; i > 1; i--, m = o) { p = uel(P,i); o = m*p; if (o > sq) break; } c = gel(V,m); n /= m; /* m <= sq, o = m * p > sq */ if (n > sq) { c = vecmul(c, gel(V,p)); n /= p; } return vecmul(c, gel(V,n)); } static GEN _Qtor(GEN x, long prec) { return typ(x) == t_FRAC? fractor(x, prec): x; } static GEN Qtor(GEN x, long prec) { long tx = typ(x); if (tx == t_VEC || tx == t_COL) pari_APPLY_same(_Qtor(gel(x, i), prec)); return tx == t_FRAC? fractor(x, prec): x; } static GEN vecf(long N, void *E, GEN (*f)(void *, ulong, long), long prec) { GEN v; long n; if (!f) return NULL; v = cgetg(N + 1, t_VEC); for (n = 1; n <= N; n++) gel(v,n) = f(E, n, prec); return v; } /* Here #V = #F > 0 is small. Analogous to dotproduct, with following * semantic differences: uses V[1] = 1; V has scalar values but F may have * vector values */ static GEN naivedirpowerssum(GEN V, GEN F, long prec) { GEN S; if (!F) S = RgV_sum(V); else { long n, l = lg(V); S = gel(F,1); /* V[1] = 1 */ for (n = 2; n < l; n++) S = gadd(S, gmul(gel(V, n), gel(F, n))); } return Qtor(S, prec); } static GEN smalldirpowerssum(long N, GEN s, void *E, GEN (*f)(void *, ulong, long), long both, long prec) { GEN F, V, S, SB, sb; if (!N) { if (!f) return both? mkvec2(gen_0, gen_0): gen_0; return gmul(gen_0, f(E, 1, prec)); } V = vecpowug(N, s, prec); F = vecf(N, E, f, prec); S = naivedirpowerssum(V, F, prec); if (!both) return S; sb = conj_i(gsubsg(-1, s)); if ((both==2 || !f) && gequal(s,sb)) SB = S; else { GEN VB = cgetg(N+1, t_VEC), FB = (both == 1 && F)? conj_i(F): F; long n; gel(VB, 1) = gel(V, 1); /* = 1 */ for (n = 2; n <= N; n++) gel(VB, n) = ginv(gmulsg(n, gel(V, n))); SB = naivedirpowerssum(VB, FB, prec); } return mkvec2(S, SB); } static void v2unpack(GEN v, GEN *pV, GEN *pVB) { if (typ(v) == t_COL) { *pV = gel(v,1); *pVB = gel(v,2); } else { *pV = v; *pVB = NULL; } } static GEN v2pack(GEN V, GEN VB) { return VB? mkcol2(V,VB): V; } static GEN dirpowsuminit(GEN s, GEN onef, GEN zerf, void *E, GEN (*f)(void *, ulong, long), GEN data, long both) { long needlog = data[1], prec0 = data[2], prec1 = data[3]; ulong a, b, c, e, q, n, sq = usqrt(data[4]); GEN V = cgetg(sq+1, t_VEC), W = cgetg(sq+1, t_VEC), VB = NULL, WB = NULL; GEN Q = cgetg(sq+1, t_VEC), Z = cgetg(sq+1, t_VEC), QB = NULL, ZB = NULL; GEN logp, c2, Q2, Q3, Q6, c2B = NULL, Q2B = NULL, Q3B = NULL, Q6B = NULL; long gp[] = {evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3),0}; if (both == 1 || (both == 2 && !gequal(real_i(s), gneg(ghalf)))) { VB = cgetg(sq+1, t_VEC); WB = cgetg(sq+1, t_VEC); QB = cgetg(sq+1, t_VEC);} gel(V, 1) = gel(W, 1) = gel(Q, 1) = onef; if (VB) { gel(VB, 1) = gel(WB, 1) = gel(QB, 1) = onef; } c2 = gpow(gen_2, s, prec0); if (VB) c2B = ginv(gmul2n(conj_i(c2), 1)); if (f) { GEN tmp2 = f(E, 2, prec0); c2 = gmul(c2, tmp2); if (VB) c2B = gmul(c2B, tmp2); } gel(V,2) = c2; /* f(2) 2^s */ gel(W,2) = Qtor(gadd(c2, onef), prec0); gel(Q,2) = Qtor(gadd(vecsqr(c2), onef), prec0); if (VB) { gel(VB, 2) = c2B; gel(WB, 2) = Qtor(gadd(c2B, onef), prec0); gel(QB, 2) = Qtor(gadd(vecsqr(c2B), onef), prec0); } logp = NULL; for (n = 3; n <= sq; n++) { GEN u = NULL, uB = NULL, ks = f ? f(E, n, prec0) : gen_1; if (gequal0(ks)) ks = NULL; if (odd(n)) { gp[2] = n; if (needlog) { if (!logp) logp = logr_abs(utor(n, prec1)); else { /* log n = log(n-2) + 2 atanh(1 / (n - 1)) */ GEN z = atanhuu(1, n - 1, prec1); shiftr_inplace(z, 1); logp = addrr(logp, z); } if (ks) u = needlog == 1? powcx(gp, logp, s, prec0) : mpexp(gmul(s, logp)); } else if (ks) u = gpow(gp, s, prec0); if (ks) { if (VB) uB = gmul(ginv(gmulsg(n, conj_i(u))), ks); u = gmul(u, ks); /* f(n) n^s */ } } else { u = vecmul(c2, gel(V, n >> 1)); if (VB) uB = vecmul(c2B, gel(VB, n >> 1)); } if (ks) { gel(V,n) = u; /* f(n) n^s */ gel(W,n) = gadd(gel(W, n-1), gel(V,n)); /*= sum_{i<=n} f(i)i^s */ gel(Q,n) = gadd(gel(Q, n-1), vecsqr(gel(V,n)));/*= sum_{i<=n} f(i^2)i^2s*/ if (VB) { gel(VB,n) = uB; gel(WB,n) = gadd(gel(WB,n-1), gel(VB,n)); gel(QB,n) = gadd(gel(QB,n-1), vecsqr(gel(VB,n))); } } else { gel(V,n) = zerf; gel(W,n) = gel(W, n-1); gel(Q,n) = gel(Q, n-1); if (VB) { gel(VB,n) = zerf; gel(WB,n) = gel(WB, n-1); gel(QB,n) = gel(QB, n-1); } } } Q2 = vecmulsqlv(Q, gel(V,2)); Q3 = vecmulsqlv(Q, gel(V,3)); Q6 = vecmulsqlv(Q, gel(V,6)); if (VB) { Q2B = vecmulsqlv(QB, gel(VB,2)); Q3B = vecmulsqlv(QB, gel(VB,3)); Q6B = vecmulsqlv(QB, gel(VB,6)); } /* a,b,c,e = sqrt(q), sqrt(q/2), sqrt(q/3), sqrt(q/6) * Z[q] = Q[a] + 2^s Q[b] + 3^s Q[c] + 6^s Q[e], with Q[0] = 0 */ gel(Z, 1) = onef; gel(Z, 2) = gel(W, 2); gel(Z, 3) = gel(W, 3); gel(Z, 4) = gel(Z, 5) = gel(W, 4); gel(Z, 6) = gel(Z, 7) = gadd(gel(W, 4), gel(V, 6)); if (VB) { ZB = cgetg(sq+1, t_VEC); gel(ZB, 1) = onef; gel(ZB, 2) = gel(WB, 2); gel(ZB, 3) = gel(WB, 3); gel(ZB, 4) = gel(ZB, 5) = gel(WB, 4); gel(ZB, 6) = gel(ZB, 7) = gadd(gel(WB, 4), gel(VB, 6)); } a = 2; b = c = e = 1; for (q = 8; q <= sq; q++) { /* Gray code: at most one of a,b,c,d differs (by 1) from previous value */ GEN z = gel(Z, q - 1), zB = NULL; ulong na, nb, nc, ne, na2, nb2, nc2, ne2; if (VB) zB = gel(ZB, q - 1); if ((na = usqrt(q)) != a) { a = na; na2 = na * na; z = gadd(z, gel(V, na2)); if (VB) zB = gadd(zB, gel(VB, na2)); } else if ((nb = usqrt(q / 2)) != b) { b = nb; nb2 = 2 * nb * nb; z = gadd(z, gel(V, nb2)); if (VB) zB = gadd(zB, gel(VB, nb2)); } else if ((nc = usqrt(q / 3)) != c) { c = nc; nc2 = 3 * nc * nc; z = gadd(z, gel(V, nc2)); if (VB) zB = gadd(zB, gel(VB, nc2)); } else if ((ne = usqrt(q / 6)) != e) { e = ne; ne2 = 6 * ne * ne; z = gadd(z, gel(V, ne2)); if (VB) zB = gadd(zB, gel(VB, ne2)); } gel(Z, q) = z; if (VB) gel(ZB, q) = zB; } return v2pack(mkvecn(7, V, W, Q, Q2, Q3, Q6, Z), VB? mkvecn(7, VB, WB, QB, Q2B, Q3B, Q6B, ZB): NULL); } static GEN sumprimeloop(forprime_t *pT, GEN s, long N, GEN data, GEN S, GEN W, GEN WB, void *E, GEN (*f)(void *, ulong, long)) { pari_sp av = avma; long needlog = data[1], prec0 = data[2], prec1 = data[3]; long gp[] = {evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3),0}; ulong p, precp = 0; GEN logp = NULL, SB = WB? S: NULL; while ((p = u_forprime_next(pT))) { GEN u = NULL, ks; if (!f) ks = gen_1; else { ks = f(E, p, prec1); if (gequal0(ks)) ks = NULL; if (ks && gequal1(ks)) ks = gen_1; } gp[2] = p; if (needlog) { if (!logp) logp = logr_abs(utor(p, prec1)); else { /* Assuming p and precp are odd, * log p = log(precp) + 2 atanh((p - precp) / (p + precp)) */ ulong a = p >> 1, b = precp >> 1; /* p = 2a + 1, precp = 2b + 1 */ GEN z = atanhuu(a - b, a + b + 1, prec1); /* avoid overflow */ shiftr_inplace(z, 1); logp = addrr(logp, z); } if (ks) u = needlog == 1? powcx(gp, logp, s, prec0) : mpexp(gmul(s, logp)); } else if (ks) u = gpow(gp, s, prec0); if (ks) { S = gadd(S, vecmul(gel(W, N / p), ks == gen_1? u: gmul(ks, u))); if (WB) { GEN w = gel(WB, N / p); if (ks != gen_1) w = vecmul(ks, w); SB = gadd(SB, gdiv(w, gmulsg(p, conj_i(u)))); } } precp = p; if ((p & 0x1ff) == 1) { if (!logp) gerepileall(av, SB? 2: 1, &S, &SB); else gerepileall(av, SB? 3: 2, &S, &logp, &SB); } } return v2pack(S, SB); } static GEN add4(GEN a, GEN b, GEN c, GEN d) { return gadd(gadd(a,b), gadd(c,d)); } static const long step = 2048; static int mksqfloop(long N, long x1, GEN R, GEN RB, GEN *pS, GEN *pSB) { GEN V = gel(R,1), Q = gel(R,3), Q2 = gel(R,4); GEN Q3 = gel(R,5), Q6 = gel(R,6), Z = gel(R,7); GEN v, VB = NULL, QB = NULL, Q2B = NULL, Q3B = NULL, Q6B = NULL, ZB = NULL; long x2, j, lv, sq = lg(V)-1; if (RB) { VB = gel(RB,1); QB = gel(RB,3); Q2B = gel(RB,4); Q3B = gel(RB,5), Q6B = gel(RB,6); ZB = gel(RB,7); } /* beware overflow, fuse last two bins (avoid a tiny remainder) */ x2 = (N >= 2*step && N - 2*step >= x1)? x1-1 + step: N; v = vecfactorsquarefreeu_coprime(x1, x2, mkvecsmall2(2, 3)); lv = lg(v); for (j = 1; j < lv; j++) if (gel(v,j)) { ulong d = x1 - 1 + j; /* squarefree, coprime to 6 */ GEN t = smallfact(d, gel(v,j), sq, V), u; GEN tB = NULL, uB = NULL; /* = f(d) d^s */ long a, b, c, e, q; if (!t || gequal0(t)) continue; if (VB) tB = vecinv(gmulsg(d, conj_i(t))); /* warning: gives 1/conj(f(d)) d^(-1-conj(s)), equal to f(d) d^(-1-conj(s)) only if |f(d)|=1. */ /* S += f(d) * d^s * Z[q] */ q = N / d; if (q == 1) { *pS = gadd(*pS, t); if (VB) *pSB = gadd(*pSB, tB); continue; } if (q <= sq) { u = gel(Z, q); if (VB) uB = gel(ZB, q); } else { a = usqrt(q); b = usqrt(q / 2); c = usqrt(q / 3); e = usqrt(q / 6); u = add4(gel(Q,a), gel(Q2,b), gel(Q3,c), gel(Q6,e)); if (VB) uB = add4(gel(QB,a), gel(Q2B,b), gel(Q3B,c), gel(Q6B,e)); } *pS = gadd(*pS, vecmul(t, u)); if (VB) *pSB = gadd(*pSB, vecmul(tB, uB)); } return x2 == N; } static GEN mkdata(long N, GEN s, long prec) { long needlog, prec0, prec1, m = mt_nbthreads(), STEP = maxss(N / (m * m), 1); prec1 = prec0 = prec + EXTRAPRECWORD; needlog = get_needlog(s); if (needlog == 1) prec1 = powcx_prec(log2((double)N), s, prec); return mkvecsmalln(5, needlog, prec0, prec1, N, STEP); } static GEN gp_callUp(void *E, ulong x, long prec) { long n[] = {evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3),0}; n[2] = x; return gp_callprec(E, n, prec); } /* set *p0 and *p1 to 0 and 1 in the algebra where f takes its values */ static int mk01(void *E, GEN (*f)(void*,ulong,long), long prec, GEN *p0, GEN *p1) { *p0 = gen_0; *p1 = gen_1; if (!f) return 1; *p1 = f(E, 1, prec); if (is_vec_t(typ(*p1))) { long l = lg(*p1); if (l == 1) { *p0 = *p1 = NULL; return 0; } *p0 = const_vec(l-1, gen_0); } return 1; } static GEN mktrivial(long both) { if (!both) return cgetg(1, t_VEC); return mkvec2(cgetg(1,t_VEC), cgetg(1,t_VEC)); } /* both is * 0: sum_{n<=N}f(n)n^s * 1: sum for (f,s) and (conj(f),-1-s) * 2: sum for (f,s) and (f,-1-s), assuming |f(n)| in {0,1} */ static GEN dirpowerssumfun_i(ulong N, GEN s, void *E, GEN (*f)(void *, ulong, long), long both, long prec) { forprime_t T; pari_sp av; GEN onef, zerf, R, RB, W, WB, S, SB, data; ulong x1; if ((f && N < 49) || (!f && N < 1000)) return smalldirpowerssum(N, s, E, f, both, prec); if (!mk01(E, f, prec, &zerf, &onef)) return mktrivial(both); data = mkdata(N, s, prec); s = gprec_w(s, prec + EXTRAPRECWORD); v2unpack(dirpowsuminit(s, onef, zerf, E, f, data, both), &R, &RB); W = gel(R,2); WB = RB? gel(RB,2): NULL; av = avma; u_forprime_init(&T, lg(W), N); v2unpack(sumprimeloop(&T, s, N, data, zerf, W, WB, E, f), &S, &SB); for(x1 = 1;; x1 += step) { if (mksqfloop(N, x1, R, RB, &S, &SB)) return both? mkvec2(S, conj_i(SB? SB: S)): S; gerepileall(av, SB? 2: 1, &S, &SB); } } GEN dirpowerssumfun(ulong N, GEN s, void *E, GEN (*f)(void *, ulong, long), long both, long prec) { pari_sp av = avma; return gerepilecopy(av, dirpowerssumfun_i(N, s, E, f, both, prec)); } GEN dirpowerssum(ulong N, GEN s, long both, long prec) { return dirpowerssumfun(N, s, NULL, NULL, both, prec); } GEN dirpowerssum0(GEN N, GEN s, GEN f, long both, long prec) { if (typ(N) != t_INT) pari_err_TYPE("dirpowerssum", N); if (signe(N) <= 0) N = gen_0; if (!f) return dirpowerssum(itou(N), s, both, prec); if (typ(f) != t_CLOSURE) pari_err_TYPE("dirpowerssum", f); return dirpowerssumfun(itou(N), s, (void*)f, gp_callUp, both, prec); } GEN parsqf_worker(GEN gk, GEN vR, GEN gN) { pari_sp av = avma; GEN R, RB, onef, S, SB; long k = itou(gk), N = itou(gN), x1 = 1 + step * k; v2unpack(vR, &R, &RB); onef = gmael(R,1,1); S = SB = is_vec_t(typ(onef)) ? zerovec(lg(onef) - 1): gen_0; (void)mksqfloop(N, x1, R, RB, &S, &SB); return gerepilecopy(av, v2pack(S, RB? SB: NULL)); } static GEN mycallvec(void *f, ulong n, long prec) { GEN F = (GEN)f; if (!f) return gen_1; if (typ(F) == t_CLOSURE) return gp_callUp(f, n, prec); return gel(F, (n-1) % (lg(F)-1) + 1); } GEN parsumprimefun_worker(GEN gk, GEN s, GEN zerf, GEN data, GEN vW, GEN f) { pari_sp av = avma; forprime_t T; GEN W, WB, S; long k = itou(gk), sq, N = data[4], STEP = data[5]; v2unpack(vW, &W, &WB); sq = lg(W)-1; if (isintzero(f)) f = NULL; u_forprime_init(&T, k * STEP + sq + 1, minss(N, (k + 1) * STEP + sq)); S = sumprimeloop(&T, s, N, data, zerf, W, WB, (void*)f, mycallvec); return gerepilecopy(av, S); } static GEN vR_get_vW(GEN vR) { GEN R, RB, W, WB; v2unpack(vR, &R, &RB); W = gel(R,2); WB = RB? gel(RB,2): NULL; return v2pack(W, WB); } static GEN halfconj(long both, GEN V) { return both ? mkvec2(gel(V, 1), gconj(gel(V, 2))) : V; } static GEN pardirpowerssumfun_i(GEN f, ulong N, GEN s, long both, long prec) { GEN worker, worker2, data, vR, onef, zerf; if ((f && N < 49) || (!f && N < 10000UL)) return smalldirpowerssum(N, s, (void*)f, mycallvec, both, prec); if (!mk01((void*)f, mycallvec, prec, &zerf, &onef)) return mktrivial(both); data = mkdata(N, s, prec); s = gprec_w(s, prec + EXTRAPRECWORD); vR = dirpowsuminit(s, onef, zerf, (void*)f, mycallvec, data, both); worker = snm_closure(is_entry("_parsumprimefun_worker"), mkvecn(5, s, zerf, data, vR_get_vW(vR), f? f: gen_0)); worker2 = snm_closure(is_entry("_parsqf_worker"), mkvec2(vR, utoi(N))); return halfconj(both, gadd(parsum(gen_0, utoipos((N-1) / data[5]), worker), parsum(gen_0, utoipos(maxss((N-1) / step - 1, 0)), worker2))); } GEN pardirpowerssumfun(GEN f, ulong N, GEN s, long both, long prec) { pari_sp av = avma; return gerepilecopy(av, pardirpowerssumfun_i(f, N, s, both, prec)); } GEN pardirpowerssum0(GEN N, GEN s, GEN f, long both, long prec) { if (typ(N) != t_INT) pari_err_TYPE("pardirpowerssum", N); return pardirpowerssumfun(f, itou(N), s, both, prec); } GEN pardirpowerssum(ulong N, GEN s, long prec) { return pardirpowerssumfun(NULL, N, s, 0, prec); } pari-2.17.2/src/basemath/ZX.c0000644000175000017500000010152414760123736014260 0ustar billbill/* Copyright (C) 2007 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" /*******************************************************************/ /* */ /* ZX */ /* */ /*******************************************************************/ void RgX_check_QX(GEN x, const char *s) { if (!RgX_is_QX(x)) pari_err_TYPE(stack_strcat(s," [not in Q[X]]"), x); } void RgX_check_ZX(GEN x, const char *s) { if (!RgX_is_ZX(x)) pari_err_TYPE(stack_strcat(s," [not in Z[X]]"), x); } long ZX_max_lg(GEN x) { long i, l = 0, lx = lg(x); for (i = 2; i < lx; i++) l = maxss(l, lgefint(gel(x,i))); return l; } 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; i1; i--) /* z[i] = a[i+1] + z[i+1] */ { GEN t = addii(gel(a0--,0), gel(z0--,0)); gel(z0,0) = t; } if (r) *r = addii(gel(a0,0), gel(z0,0)); return z; } /* return P(X + c) using destructive Horner, optimize for c = 1,-1 */ static GEN ZX_translate_basecase(GEN P, GEN c) { pari_sp av = avma; GEN Q, R; long i, k, n; if (!signe(P) || !signe(c)) return ZX_copy(P); Q = leafcopy(P); R = Q+2; n = degpol(P); if (equali1(c)) { for (i=1; i<=n; i++) { for (k=n-i; k1) pari_warn(warnmem,"ZX_translate(1), i = %ld/%ld", i,n); Q = gerepilecopy(av, Q); R = Q+2; } } } else if (equalim1(c)) { for (i=1; i<=n; i++) { for (k=n-i; k1) pari_warn(warnmem,"ZX_translate(-1), i = %ld/%ld", i,n); Q = gerepilecopy(av, Q); R = Q+2; } } } else { for (i=1; i<=n; i++) { for (k=n-i; k1) pari_warn(warnmem,"ZX_translate, i = %ld/%ld", i,n); Q = gerepilecopy(av, Q); R = Q+2; } } } return gerepilecopy(av, Q); } static GEN Z_Xpm1_powu(long n, long s, long v) { long d, k; GEN C; if (!n) return pol_1(v); d = (n + 1) >> 1; C = cgetg(n+3, t_POL); C[1] = evalsigne(1)| evalvarn(v); gel(C,2) = gen_1; gel(C,3) = utoipos(n); for (k=2; k <= d; k++) gel(C,k+2) = diviuexact(mului(n-k+1, gel(C,k+1)), k); if (s < 0) for (k = odd(n)? 0: 1; k <= d; k += 2) togglesign_safe(&gel(C,k+2)); if (s > 0 || !odd(n)) for (k = d+1; k <= n; k++) gel(C,k+2) = gel(C,n-k+2); else for (k = d+1; k <= n; k++) gel(C,k+2) = negi(gel(C,n-k+2)); return C; } /* return (x+u)^n */ static GEN Z_XpN_powu(GEN u, long n, long v) { pari_sp av; long k; GEN B, C, V; if (!n) return pol_1(v); if (is_pm1(u)) return Z_Xpm1_powu(n, signe(u), v); av = avma; V = gpowers(u, n); B = vecbinomial(n); C = cgetg(n+3, t_POL); C[1] = evalsigne(1)| evalvarn(v); for (k=1; k <= n+1; k++) gel(C,k+1) = mulii(gel(V,n+2-k), gel(B,k)); return gerepileupto(av, C); } GEN ZX_translate(GEN P, GEN c) { pari_sp av = avma; long n = degpol(P); if (n < 220) return ZX_translate_basecase(P, c); else { long d = n >> 1; GEN Q = ZX_translate(RgX_shift_shallow(P, -d), c); GEN R = ZX_translate(RgXn_red_shallow(P, d), c); GEN S = Z_XpN_powu(c, d, varn(P)); return gerepileupto(av, ZX_add(ZX_mul(Q, S), R)); } } /* P(ax + b) */ GEN ZX_affine(GEN P, GEN a, GEN b) { if (signe(b)) P = ZX_translate(P, b); return ZX_unscale(P, a); } GEN ZX_Z_eval(GEN x, GEN y) { long i = lg(x)-1, j; pari_sp av = avma; GEN t, r; if (i<=2) return (i==2)? icopy(gel(x,2)): gen_0; if (!signe(y)) return icopy(gel(x,2)); t = gel(x,i); i--; #if 0 /* standard Horner's rule */ for ( ; i>=2; i--) t = addii(mulii(t,y),gel(x,i)); #endif /* specific attention to sparse polynomials */ for ( ; i>=2; i = j-1) { for (j = i; !signe(gel(x,j)); j--) if (j==2) { if (i != j) y = powiu(y, i-j+1); return gerepileuptoint(av, mulii(t,y)); } r = (i==j)? y: powiu(y, i-j+1); t = addii(mulii(t,r), gel(x,j)); if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"ZX_Z_eval: i = %ld",i); t = gerepileuptoint(av, t); } } return gerepileuptoint(av, t); } /* Return 2^(n degpol(P)) P(x >> n) */ GEN ZX_rescale2n(GEN P, long n) { long i, l = lg(P), ni = n; GEN Q; if (l==2) return pol_0(varn(P)); Q = cgetg(l,t_POL); gel(Q,l-1) = icopy(gel(P,l-1)); for (i=l-2; i>=2; i--) { gel(Q,i) = shifti(gel(P,i), ni); ni += n; } Q[1] = P[1]; return Q; } /* Return h^deg(P) P(x / h), not memory clean. h integer, P ZX */ GEN ZX_rescale(GEN P, GEN h) { long l = lg(P); GEN Q = cgetg(l,t_POL); if (l != 2) { long i = l-1; GEN hi = h; gel(Q,i) = gel(P,i); if (l != 3) { i--; gel(Q,i) = mulii(gel(P,i), h); } for (i--; i>=2; i--) { hi = mulii(hi,h); gel(Q,i) = mulii(gel(P,i), hi); } } Q[1] = P[1]; return Q; } /* Return h^(deg(P)-1) P(x / h), P!=0, h=lt(P), memory unclean; monic result */ GEN ZX_rescale_lt(GEN P) { long l = lg(P); GEN Q = cgetg(l,t_POL); gel(Q,l-1) = gen_1; if (l != 3) { long i = l-1; GEN h = gel(P,i), hi = h; i--; gel(Q,i) = gel(P,i); if (l != 4) { i--; gel(Q,i) = mulii(gel(P,i), h); } for (i--; i>=2; i--) { hi = mulii(hi,h); gel(Q,i) = mulii(gel(P,i), hi); } } Q[1] = P[1]; return Q; } /*Eval x in 2^(k*BIL) in linear time*/ static GEN ZX_eval2BILspec(GEN x, long k, long nx) { pari_sp av = avma; 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; pol[1] = evalsigne(1); for (i=0; i 0 ?adduispec_offset(carry, x, offset, lz): utoi(carry); if (lgefint(z) == 3+bs) { carry = 1; z = gen_0;} else { carry = (lgefint(z) == 2+bs && (HIGHBIT & *int_W(z,bs-1))); if (carry) z = gerepileuptoint(av, (sx==-1)? subii(s1,z): subii(z,s1)); else if (sx==-1) togglesign(z); } gel(pol,i+2) = z; } return ZX_renormalize(pol,l); } static GEN ZX_sqrspec_sqri(GEN x, long nx, long ex, long v) { long e = 2*ex + expu(nx) + 3; long N = divsBIL(e)+1; GEN z = sqri(ZX_eval2BILspec(x,N,nx)); return Z_mod2BIL_ZX(z, N, nx*2-2, v); } static GEN ZX_mulspec_mulii(GEN x, GEN y, long nx, long ny, long ex, long ey, long v) { long e = ex + ey + expu(minss(nx,ny)) + 3; long N = divsBIL(e)+1; GEN z = mulii(ZX_eval2BILspec(x,N,nx), ZX_eval2BILspec(y,N,ny)); return Z_mod2BIL_ZX(z, N, nx+ny-2, v); } INLINE GEN ZX_sqrspec_basecase_limb(GEN x, long a, long i) { pari_sp av = avma; GEN s = gen_0; long j, l = (i+1)>>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 1) gel(z, i--) = gen_0; return z; } #if 0 /* generically slower even when degrees differ a lot; sometimes about twice * faster when bitsize is moderate */ if (DEBUGVAR) return RgX_mulspec(x - vx, y - vy, nx + vx, ny + vy); #endif av = avma; ex = ZX_expispec(x, nx); ey = ZX_expispec(y, ny); return gerepileupto(av, ZX_mulspec_mulii(x,y,nx,ny,ex,ey,v)); } GEN ZX_mul(GEN x, GEN y) { GEN z; if (x == y) return ZX_sqr(x); z = ZX_mulspec(x+2,y+2,lgpol(x),lgpol(y)); z[1] = x[1]; if (!signe(y)) z[1] &= VARNBITS; return z; } /* x,y two ZX in the same variable; assume y is monic */ GEN ZX_rem(GEN x, GEN y) { long vx, dx, dy, dz, i, j, sx, lr; pari_sp av0, av; GEN z,p1,rem; vx = varn(x); dy = degpol(y); dx = degpol(x); if (dx < dy) return ZX_copy(x); if (!dy) return pol_0(vx); /* y is constant */ av0 = avma; dz = dx-dy; z=cgetg(dz+3,t_POL); z[1] = x[1]; x += 2; y += 2; z += 2; p1 = gel(x,dx); gel(z,dz) = icopy(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))); 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; set_avma(av); } lr=i+3; rem -= lr; rem[0] = evaltyp(t_POL) | _evallg(lr); rem[1] = z[-1]; p1 = gerepileuptoint((pari_sp)rem, p1); rem += 2; gel(rem,i) = p1; for (i--; i>=0; i--) { av=avma; p1 = gel(x,i); for (j=0; j<=i && j<=dz; j++) p1 = subii(p1, mulii(gel(z,j),gel(y,i-j))); gel(rem,i) = avma == av? icopy(p1): gerepileuptoint(av, p1); } rem -= 2; if (!sx) (void)ZX_renormalize(rem, lr); return gerepileupto(av0,rem); } /* return x(1) */ GEN ZX_eval1(GEN x) { pari_sp av = avma; long i = lg(x)-1; GEN s; if (i < 2) return gen_0; s = gel(x,i); i--; if (i == 1) return icopy(s); for ( ; i>=2; i--) { GEN c = gel(x,i); if (signe(c)) s = addii(s, c); } return gerepileuptoint(av,s); } /* reduce T mod X^n - 1. Shallow function */ GEN ZX_mod_Xnm1(GEN T, ulong n) { long i, j, L = lg(T), l = n+2; GEN S; if (L <= l) return T; S = cgetg(l, t_POL); S[1] = T[1]; for (i = 2; i < l; i++) gel(S,i) = gel(T,i); for (j = 2; i < L; i++) { gel(S,j) = addii(gel(S,j), gel(T,i)); if (++j == l) j = 2; } return normalizepol_lg(S, l); } static GEN _ZX_mul(void* E, GEN x, GEN y) { (void) E; return ZX_mul(x, y); } static GEN _ZX_sqr(void *E, GEN x) { (void) E; return ZX_sqr(x); } static GEN _ZX_divrem(void * E, GEN x, GEN y, GEN *r) { (void) E; return RgX_divrem(x, y, r); } static GEN _ZX_add(void * E, GEN x, GEN y) { (void) E; return ZX_add(x, y); } static struct bb_ring ZX_ring = { _ZX_add,_ZX_mul,_ZX_sqr }; GEN ZX_digits(GEN x, GEN T) { long d = degpol(T), n = (lgpol(x)+d-1)/d; return gen_digits(x, T, n, NULL, &ZX_ring, _ZX_divrem); } GEN ZXV_ZX_fromdigits(GEN x, GEN T) { return gen_fromdigits(x,T, NULL, &ZX_ring); } /*******************************************************************/ /* */ /* ZXV */ /* */ /*******************************************************************/ int ZXV_equal(GEN V, GEN W) { long l = lg(V); if (l!=lg(W)) return 0; while (--l > 0) if (!ZX_equal(gel(V,l), gel(W,l))) return 0; return 1; } GEN ZXV_Z_mul(GEN x, GEN y) { pari_APPLY_same(ZX_Z_mul(gel(x,i), y)) } GEN ZXV_remi2n(GEN x, long N) { pari_APPLY_same(ZX_remi2n(gel(x,i), N)) } GEN ZXV_dotproduct(GEN x, GEN y) { pari_sp av = avma; long i, lx = lg(x); GEN c; if (lx == 1) return pol_0(varn(x)); c = ZX_mul(gel(x,1), gel(y,1)); for (i = 2; i < lx; i++) { GEN t = ZX_mul(gel(x,i), gel(y,i)); if (signe(t)) c = ZX_add(c, t); } return gerepileupto(av, c); } GEN ZXC_to_FlxC(GEN x, ulong p, long sv) { pari_APPLY_type(t_COL,typ(gel(x,i))==t_INT ? Z_to_Flx(gel(x,i), p, sv): ZX_to_Flx(gel(x,i), p)) } GEN ZXM_to_FlxM(GEN x, ulong p, long sv) { pari_APPLY_same(ZXC_to_FlxC(gel(x,i), p, sv)) } /*******************************************************************/ /* */ /* ZXQM */ /* */ /*******************************************************************/ GEN ZXn_mul(GEN x, GEN y, long n) { return RgXn_red_shallow(ZX_mul(x, y), n); } GEN ZXn_sqr(GEN x, long n) { return RgXn_red_shallow(ZX_sqr(x), n); } /*******************************************************************/ /* */ /* ZXQM */ /* */ /*******************************************************************/ static long ZX_expi(GEN x) { if (signe(x)==0) return 0; if (typ(x)==t_INT) return expi(x); return ZX_expispec(x+2, lgpol(x)); } static long ZXC_expi(GEN x) { long i, l = lg(x), m=0; for(i = 1; i < l; i++) { long e = ZX_expi(gel(x,i)); if (e > m) m = e; } return m; } static long ZXM_expi(GEN x) { long i, l = lg(x), m=0; for(i = 1; i < l; i++) { long e = ZXC_expi(gel(x,i)); if (e > m) m = e; } return m; } static GEN ZX_eval2BIL(GEN x, long k) { if (signe(x)==0) return gen_0; if (typ(x)==t_INT) return x; return ZX_eval2BILspec(x+2, k, lgpol(x)); } /*Eval x in 2^(k*BIL) in linear time*/ static GEN ZXC_eval2BIL(GEN x, long k) { long i, lx = lg(x); GEN A = cgetg(lx, t_COL); for (i=1; i1; k--) { GEN t = gel(x,k); switch(typ(t)) { case t_INT: break; case t_POL: if (RgX_is_ZX(t)) break; /* fall through */ default: pari_err_TYPE(stack_strcat(s, " not in Z[X,Y]"),x); } } } /*Renormalize (in place) polynomial with t_INT or ZX coefficients.*/ GEN ZXX_renormalize(GEN x, long lx) { long i; for (i = lx-1; i>1; i--) if (signe(gel(x,i))) break; stackdummy((pari_sp)(x + lg(x)), (pari_sp)(x + (i+1))); setlg(x, i+1); setsigne(x, i!=1); return x; } GEN ZXX_evalx0(GEN y) { long i, l = lg(y); GEN z = cgetg(l,t_POL); z[1] = y[1]; for(i=2; i prec) prec = l; } return prec; } GEN ZXX_Z_mul(GEN y, GEN x) { long i, l = lg(y); GEN z = cgetg(l,t_POL); z[1] = y[1]; for(i=2; i ZX: * P(X,Y) = sum_{0<=i= n) pari_err_BUG("RgXX_to_Kronecker, P is not reduced mod Q"); for (j=2; j < l; j++) gel(y,k++) = gel(c,j); } if (i == lP-1) break; for ( ; j < N; j++) gel(y,k++) = gen_0; } y-=2; setlg(y, k+2); y[1] = evalsigne(1); return y; } /* shallow, n = deg(T) */ GEN Kronecker_to_ZXX(GEN z, long n, long v) { long i,j,lx,l, N = (n<<1)+1; GEN x, t; l = lg(z); lx = (l-2) / (N-2); x = cgetg(lx+3,t_POL); x[1] = z[1]; for (i=2; i>1; set_vexp(v, m); set_vexp(v, l-m); } /* return all needed B^i for DAC algorithm, for lz digits */ static GEN get_vB(GEN T, long lz, void *E, struct bb_ring *r) { GEN vB, vexp = const_vecsmall(lz, 0); long i, l = (lz+1) >> 1; vexp[1] = 1; vexp[2] = 1; set_vexp(vexp, lz); vB = zerovec(lz); /* unneeded entries remain = 0 */ gel(vB, 1) = T; for (i = 2; i <= l; i++) if (vexp[i]) { long j = i >> 1; GEN B2j = r->sqr(E, gel(vB,j)); gel(vB,i) = odd(i)? r->mul(E, B2j, T): B2j; } return vB; } static void gen_digits_dac(GEN x, GEN vB, long l, GEN *z, void *E, GEN div(void *E, GEN a, GEN b, GEN *r)) { GEN q, r; long m = l>>1; if (l==1) { *z=x; return; } q = div(E, x, gel(vB,m), &r); gen_digits_dac(r, vB, m, z, E, div); gen_digits_dac(q, vB, l-m, z+m, E, div); } static GEN gen_fromdigits_dac(GEN x, GEN vB, long i, long l, void *E, GEN add(void *E, GEN a, GEN b), GEN mul(void *E, GEN a, GEN b)) { GEN a, b; long m = l>>1; if (l==1) return gel(x,i); a = gen_fromdigits_dac(x, vB, i, m, E, add, mul); b = gen_fromdigits_dac(x, vB, i+m, l-m, E, add, mul); return add(E, a, mul(E, b, gel(vB, m))); } static GEN gen_digits_i(GEN x, GEN B, long n, void *E, struct bb_ring *r, GEN (*div)(void *E, GEN x, GEN y, GEN *r)) { GEN z, vB; if (n==1) retmkvec(gcopy(x)); vB = get_vB(B, n, E, r); z = cgetg(n+1, t_VEC); gen_digits_dac(x, vB, n, (GEN*)(z+1), E, div); return z; } GEN gen_digits(GEN x, GEN B, long n, void *E, struct bb_ring *r, GEN (*div)(void *E, GEN x, GEN y, GEN *r)) { pari_sp av = avma; return gerepilecopy(av, gen_digits_i(x, B, n, E, r, div)); } GEN gen_fromdigits(GEN x, GEN B, void *E, struct bb_ring *r) { pari_sp av = avma; long n = lg(x)-1; GEN vB = get_vB(B, n, E, r); GEN z = gen_fromdigits_dac(x, vB, 1, n, E, r->add, r->mul); return gerepilecopy(av, z); } static GEN _addii(void *data /* ignored */, GEN x, GEN y) { (void)data; return addii(x,y); } static GEN _sqri(void *data /* ignored */, GEN x) { (void)data; return sqri(x); } static GEN _mulii(void *data /* ignored */, GEN x, GEN y) { (void)data; return mulii(x,y); } static GEN _dvmdii(void *data /* ignored */, GEN x, GEN y, GEN *r) { (void)data; return dvmdii(x,y,r); } static struct bb_ring Z_ring = { _addii, _mulii, _sqri }; /* does not affect stack unless B = NULL */ static GEN check_basis(GEN B) { if (!B) return utoipos(10); if (typ(B)!=t_INT) pari_err_TYPE("digits",B); if (abscmpiu(B,2)<0) pari_err_DOMAIN("digits","abs(B)","<",gen_2,B); return B; } /* x has l digits in base B, write them to z[0..l-1], vB[i] = B^i */ static void digits_dacsmall(GEN x, GEN vB, long l, ulong* z) { pari_sp av = avma; GEN q,r; long m; if (l==1) { *z=itou(x); return; } m=l>>1; q = dvmdii(x, gel(vB,m), &r); digits_dacsmall(q,vB,l-m,z); digits_dacsmall(r,vB,m,z+l-m); set_avma(av); } /* x t_INT */ static GEN digits_pos(GEN x, GEN B) { long lz; GEN z; if (abscmpii(x,B)<0) retmkvec(absi(x)); if (Z_ispow2(B)) { pari_sp av = avma; long k = expi(B); if (k == 1) return binaire(x); if (k >= BITS_IN_LONG) return binary_2k(x, k); (void)new_chunk(4*(expi(x) + 2)); /* HACK */ z = binary_2k_nv(x, k); set_avma(av); return Flv_to_ZV(z); } x = absi_shallow(x); lz = logint(x,B) + 1; if (lgefint(B) > 3) { z = gen_digits_i(x, B, lz, NULL, &Z_ring, _dvmdii); vecreverse_inplace(z); return z; } else { pari_sp av = avma; GEN vB = get_vB(B, lz, NULL, &Z_ring); (void)new_chunk(3*lz); /* HACK */ z = zero_zv(lz); digits_dacsmall(x,vB,lz,(ulong*)(z+1)); set_avma(av); return Flv_to_ZV(z); } } static GEN digits_neg(GEN n, GEN B) { GEN V = digits_pos(n,B); long i, l = lg(V), carry = 0, s = signe(n)==-1; for (i = 1; i < l; i++) { GEN u = odd(i+s) ? addsi(carry, gel(V, l-i)): subsi(carry,gel(V, l-i)); if (signe(u) < 0) { u = addii(u, B); carry=1; } else if (cmpii(u, B) >= 0) { u = subii(u, B); carry=-1; } else carry = 0; gel(V,l-i) = u; } if (carry > 0) V = vec_prepend(V, stoi(carry)); else if (carry < 0) V = shallowconcat(mkvec2(gen_1,addsi(carry, B)),V); return V; } /* x t_INT */ static GEN digits_i(GEN x, GEN B) { pari_sp av = avma; B = check_basis(B); if (!signe(x)) {set_avma(av); return cgetg(1,t_VEC); } if (signe(B) > 0) return gerepilecopy(av, digits_pos(x, B)); return gerepilecopy(av, digits_neg(x, negi(B))); } GEN digits(GEN x, GEN B) { pari_sp av = avma; long v = 0; if (typ(x) == t_INT) return digits_i(x, B); if (typ(x) != t_PADIC || (v = valp(x)) < 0 || (B && !gequal(B, gel(x,2)))) pari_err_TYPE("digits",x); if (!signe(gel(x, 4))) return cgetg(1, t_VEC); x = digits_i(gel(x, 4), gel(x, 2)); vecreverse_inplace(x); if (!v) return x; return gerepileupto(av, concat(zerovec(v), x)); } static GEN fromdigitsu_dac(GEN x, GEN vB, long i, long l) { GEN a, b; long m = l>>1; if (l==1) return utoi(uel(x,i)); if (l==2) return addui(uel(x,i), mului(uel(x,i+1), gel(vB, m))); a = fromdigitsu_dac(x, vB, i, m); b = fromdigitsu_dac(x, vB, i+m, l-m); return addii(a, mulii(b, gel(vB, m))); } static GEN fromdigitsu_i(GEN x, GEN B) { long n = lg(x)-1; GEN vB; if (n == 0) return gen_0; vB = get_vB(B, n, NULL, &Z_ring); return fromdigitsu_dac(x, vB, 1, n); } GEN fromdigitsu(GEN x, GEN B) { pari_sp av = avma; return gerepileuptoint(av, fromdigitsu_i(x, B)); } static int ZV_in_range(GEN v, GEN B) { long i, l = lg(v); for (i = 1; i < l; i++) { GEN vi = gel(v, i); if (signe(vi) < 0 || cmpii(vi, B) >= 0) return 0; } return 1; } static int zv_nonnegative(GEN v) { long i, l = lg(v); for (i = 1; i < l; i++) if (v[i] < 0) return 0; return 1; } GEN fromdigits(GEN x, GEN B) { pari_sp av = avma; long tx = typ(x); if (tx == t_VECSMALL) { if (lg(x)==1) return gen_0; if (zv_nonnegative(x)) { B = check_basis(B); x = vecsmall_reverse(x); return gerepileuptoint(av, fromdigitsu_i(x, B)); } x = zv_to_ZV(x); } else if (!is_vec_t(tx) || !RgV_is_ZV(x)) pari_err_TYPE("fromdigits",x); if (lg(x) == 1) return gen_0; B = check_basis(B); if (Z_ispow2(B) && ZV_in_range(x, B)) return fromdigits_2k(x, expi(B)); x = vecreverse(x); return gerepileuptoint(av, gen_fromdigits(x, B, NULL, &Z_ring)); } static const ulong digsum[] ={ 0,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,10,2,3,4,5,6,7,8,9,10,11,3,4,5,6,7,8, 9,10,11,12,4,5,6,7,8,9,10,11,12,13,5,6,7,8,9,10,11,12,13,14,6,7,8,9,10,11, 12,13,14,15,7,8,9,10,11,12,13,14,15,16,8,9,10,11,12,13,14,15,16,17,9,10,11, 12,13,14,15,16,17,18,1,2,3,4,5,6,7,8,9,10,2,3,4,5,6,7,8,9,10,11,3,4,5,6,7,8, 9,10,11,12,4,5,6,7,8,9,10,11,12,13,5,6,7,8,9,10,11,12,13,14,6,7,8,9,10,11, 12,13,14,15,7,8,9,10,11,12,13,14,15,16,8,9,10,11,12,13,14,15,16,17,9,10,11, 12,13,14,15,16,17,18,10,11,12,13,14,15,16,17,18,19,2,3,4,5,6,7,8,9,10,11,3, 4,5,6,7,8,9,10,11,12,4,5,6,7,8,9,10,11,12,13,5,6,7,8,9,10,11,12,13,14,6,7,8, 9,10,11,12,13,14,15,7,8,9,10,11,12,13,14,15,16,8,9,10,11,12,13,14,15,16,17, 9,10,11,12,13,14,15,16,17,18,10,11,12,13,14,15,16,17,18,19,11,12,13,14,15, 16,17,18,19,20,3,4,5,6,7,8,9,10,11,12,4,5,6,7,8,9,10,11,12,13,5,6,7,8,9,10, 11,12,13,14,6,7,8,9,10,11,12,13,14,15,7,8,9,10,11,12,13,14,15,16,8,9,10,11, 12,13,14,15,16,17,9,10,11,12,13,14,15,16,17,18,10,11,12,13,14,15,16,17,18, 19,11,12,13,14,15,16,17,18,19,20,12,13,14,15,16,17,18,19,20,21,4,5,6,7,8,9, 10,11,12,13,5,6,7,8,9,10,11,12,13,14,6,7,8,9,10,11,12,13,14,15,7,8,9,10,11, 12,13,14,15,16,8,9,10,11,12,13,14,15,16,17,9,10,11,12,13,14,15,16,17,18,10, 11,12,13,14,15,16,17,18,19,11,12,13,14,15,16,17,18,19,20,12,13,14,15,16,17, 18,19,20,21,13,14,15,16,17,18,19,20,21,22,5,6,7,8,9,10,11,12,13,14,6,7,8,9, 10,11,12,13,14,15,7,8,9,10,11,12,13,14,15,16,8,9,10,11,12,13,14,15,16,17,9, 10,11,12,13,14,15,16,17,18,10,11,12,13,14,15,16,17,18,19,11,12,13,14,15,16, 17,18,19,20,12,13,14,15,16,17,18,19,20,21,13,14,15,16,17,18,19,20,21,22,14, 15,16,17,18,19,20,21,22,23,6,7,8,9,10,11,12,13,14,15,7,8,9,10,11,12,13,14, 15,16,8,9,10,11,12,13,14,15,16,17,9,10,11,12,13,14,15,16,17,18,10,11,12,13, 14,15,16,17,18,19,11,12,13,14,15,16,17,18,19,20,12,13,14,15,16,17,18,19,20, 21,13,14,15,16,17,18,19,20,21,22,14,15,16,17,18,19,20,21,22,23,15,16,17,18, 19,20,21,22,23,24,7,8,9,10,11,12,13,14,15,16,8,9,10,11,12,13,14,15,16,17,9, 10,11,12,13,14,15,16,17,18,10,11,12,13,14,15,16,17,18,19,11,12,13,14,15,16, 17,18,19,20,12,13,14,15,16,17,18,19,20,21,13,14,15,16,17,18,19,20,21,22,14, 15,16,17,18,19,20,21,22,23,15,16,17,18,19,20,21,22,23,24,16,17,18,19,20,21, 22,23,24,25,8,9,10,11,12,13,14,15,16,17,9,10,11,12,13,14,15,16,17,18,10,11, 12,13,14,15,16,17,18,19,11,12,13,14,15,16,17,18,19,20,12,13,14,15,16,17,18, 19,20,21,13,14,15,16,17,18,19,20,21,22,14,15,16,17,18,19,20,21,22,23,15,16, 17,18,19,20,21,22,23,24,16,17,18,19,20,21,22,23,24,25,17,18,19,20,21,22,23, 24,25,26,9,10,11,12,13,14,15,16,17,18,10,11,12,13,14,15,16,17,18,19,11,12, 13,14,15,16,17,18,19,20,12,13,14,15,16,17,18,19,20,21,13,14,15,16,17,18,19, 20,21,22,14,15,16,17,18,19,20,21,22,23,15,16,17,18,19,20,21,22,23,24,16,17, 18,19,20,21,22,23,24,25,17,18,19,20,21,22,23,24,25,26,18,19,20,21,22,23,24, 25,26,27 }; ulong sumdigitsu(ulong n) { ulong s = 0; while (n) { s += digsum[n % 1000]; n /= 1000; } return s; } /* res=array of 9-digits integers, return sum_{0 <= i < l} sumdigits(res[i]) */ static ulong sumdigits_block(ulong *res, long l) { ulong s = sumdigitsu(*--res); while (--l > 0) s += sumdigitsu(*--res); return s; } GEN sumdigits(GEN n) { const long L = (long)(ULONG_MAX / 81); pari_sp av = avma; ulong *res; long l; if (typ(n) != t_INT) pari_err_TYPE("sumdigits", n); switch(lgefint(n)) { case 2: return gen_0; case 3: return utoipos(sumdigitsu(n[2])); } res = convi(n, &l); if (l < L) { ulong s = sumdigits_block(res, l); return gc_utoipos(av, s); } else /* Huge. Overflows ulong */ { GEN S = gen_0; while (l > L) { S = addiu(S, sumdigits_block(res, L)); res += L; l -= L; } if (l) S = addiu(S, sumdigits_block(res, l)); return gerepileuptoint(av, S); } } GEN sumdigits0(GEN x, GEN B) { pari_sp av = avma; GEN z; long lz; if (!B) return sumdigits(x); if (typ(x) != t_INT) pari_err_TYPE("sumdigits", x); B = check_basis(B); if (signe(B)<0) return gerepileuptoint(av, ZV_sum(digits_neg(x,negi(B)))); if (Z_ispow2(B)) { long k = expi(B); if (k == 1) return gc_utoi(av,hammingweight(x)); if (k < BITS_IN_LONG) { GEN z = binary_2k_nv(x, k); if (lg(z)-1 > 1L<<(BITS_IN_LONG-k)) /* may overflow */ return gerepileuptoint(av, ZV_sum(Flv_to_ZV(z))); return gc_utoi(av,zv_sum(z)); } return gerepileuptoint(av, ZV_sum(binary_2k(x, k))); } if (!signe(x)) { set_avma(av); return gen_0; } if (abscmpii(x,B)<0) { set_avma(av); return absi(x); } if (absequaliu(B,10)) { set_avma(av); return sumdigits(x); } x = absi_shallow(x); lz = logint(x,B) + 1; z = gen_digits_i(x, B, lz, NULL, &Z_ring, _dvmdii); return gerepileuptoint(av, ZV_sum(z)); } pari-2.17.2/src/basemath/ellpadic.c0000644000175000017500000007274614760123736015511 0ustar billbill/* Copyright (C) 2011 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pari.h" #include "paripriv.h" static GEN precp_fix(GEN h, long v) { return (precp(h) > v)? cvtop(h,gel(h,2),v): h; } /* TATE CURVE */ /* a1, b1 are t_PADICs, a1/b1 = 1 (mod p) if p odd, (mod 2^4) otherwise. * Let (A_n, B_n) be defined by A_1 = a1/p^v, B_1 = b1/p^v, v=v(a1)=v(a2); * A_{n+1} = (A_n + B_n + 2 B_{n+1}) / 4 * B_{n+1} = B_n sqrt(A_n / B_n) = square root of A_n B_n congruent to B_n * R_n = p^v( A_n - B_n ) = r_{n+1} * Return [An,Bn,Rn]. N.B. lim An = M2(a1,b1) = M(sqrt(a1),sqrt(b1))^2 */ GEN Qp_agm2_sequence(GEN a1, GEN b1) { GEN bp, pmod, p = gel(a1,2), q = gel(a1,3), An, Bn, Rn; long pp = precp(a1), v = valp(a1), i; int pis2 = absequaliu(p,2); a1 = gel(a1,4); b1 = gel(b1,4); if (pis2) pmod = utoipos(8); else pmod = p; bp = modii(b1, pmod); An = cgetg(pp+1, t_VEC); /* overestimate: rather log_2(pp) */ Bn = cgetg(pp+1, t_VEC); Rn = cgetg(pp+1, t_VEC); for(i = 1;; i++) { GEN a = a1, b = b1, r; long vr; gel(An, i) = a; gel(Bn, i) = b; r = subii(a,b); if (!signe(r)) break; vr = Z_pvalrem(r,p,&r); if (vr >= pp) break; r = cvtop(r, p, pp - vr); setvalp(r, vr+v); gel(Rn, i) = r; b1 = Zp_sqrt(Fp_mul(a,b,q), p, pp); if (!b1) pari_err_PREC("p-adic AGM"); if (!equalii(modii(b1,pmod), bp)) b1 = Fp_neg(b1, q); /* a1 = (a+b+2sqrt(ab))/4 */ if (pis2) { b1 = remi2n(b1, pp-1); a1 = shifti(addii(addii(a,b), shifti(b1,1)),-2); a1 = remi2n(a1, pp-2); pp -= 2; } else a1 = modii(Fp_halve(addii(Fp_halve(addii(a,b),q), b1), q), q); } setlg(An,i+1); setlg(Bn,i+1); setlg(Rn,i); return mkvec4(An, Bn, Rn, stoi(v)); } void Qp_descending_Landen(GEN AB, GEN *ptx, GEN *pty) { GEN R = gel(AB,3); long i, n = lg(R)-1; GEN x = *ptx; if (isintzero(x)) { i = 2; x = gmul2n(gel(R,1),-2); if (pty) { GEN A = gel(AB,1); if (n == 1) *pty = gmul(x, Qp_sqrt(gadd(x,gel(A,2)))); else *pty = Qp_sqrt(gmul(gmul(x, gadd(x,gel(A,2))), gadd(x,gel(R,2)))); if (!*pty) pari_err_PREC("Qp_descending_Landen"); } } else i = 1; for (; i <= n; i++) { GEN r = gel(R,i), t; if (gequal0(x)) pari_err_PREC("Qp_descending_Landen"); t = Qp_sqrt(gaddsg(1, gdiv(r,x))); /* = 1 (mod p) */ if (!t) pari_err_PREC("Qp_descending_Landen"); if (i == n) { GEN p = gel(r,2); long v, vx = valp(x), vr = valp(r); if (vx >= vr) pari_err_PREC("Qp_descending_Landen"); /* last loop, take into account loss of accuracy from multiplication * by \prod_{j > n} sqrt(1+r_j/x_j); since vx < vr, j = n+1 is enough */ v = 2*vr - vx; /* |r_{n+1}| <= |(r_n)^2 / 8| + 1 bit for sqrt loss */ if (absequaliu(p,2)) v -= 4; /* tail is 1 + O(p^v) */ if (v < precp(x)) x = cvtop(x,p,v); } /* x_{n+1} = x_n ((1 + sqrt(1 + r_n/x_n)) / 2)^2 */ x = gmul(x, gsqr(gmul2n(gaddsg(1,t),-1))); /* y_{n+1} = y_n / (1 - (r_n/4x_{n+1})^2) */ if (pty) *pty = gdiv(*pty, gsubsg(1, gsqr(gdiv(r,gmul2n(x,2))))); } *ptx = x; } void Qp_ascending_Landen(GEN AB, GEN *ptx, GEN *pty) { GEN A = gel(AB,1), R = gel(AB,3), x = *ptx, p, r; long n = lg(R)-1, va = itos(gel(AB,4)), v, i; r = gel(R,n); v = 2*valp(r) + va; if (typ(x) == t_PADIC) v -= 2*valp(x); else v -= valp(gnorm(x)); /* v(x) = v(Nx) / (e*f), here ef = 2 */ p = gel(r,2); if (absequaliu(p,2)) v -= 3; /* |r_{n+1}| <= |(r_n)^2 / 8| */ /* v = v(A[n+1] R[n+1] / x_{n+1}^2) */ if (v <= 0) pari_err_PREC("Qp_ascending_Landen"); /* v > 0 => v = v(x_oo) = ... = v(x_{n+1}) */ x = gsub(x, gmul2n(r,-1)); if (padicprec_relative(x) > v) x = gcvtop(x, p, v); /* x = x_n */ for (i = n; i > 1; i--) { GEN ar = gmul(gel(A,i),gel(R,i)), xp; setvalp(ar, valp(ar)+va); /* A_i = A[i] * p^va */ /* x_{i-1} = x_i + a_i r_i / x_i - r_{i-1}/2 */ xp = gsub(gadd(x, gdiv(ar, x)), gmul2n(gel(R,i-1),-1)); /* y_{i-1} = y_i (1 - a_i r_i / x^2) */ if (pty) *pty = gmul(*pty, gsubsg(1, gdiv(ar,gsqr(x)))); x = xp; } *ptx = x; } /* Let T = 4x^3 + b2 x^2 + 2b4 x + b6, where T has a unique p-adic root 'a'. * Return a lift of a to padic accuracy prec. We have * 216 T = 864 X^3 - 18 c4X - c6, where X = x + b2/12 */ static GEN doellQp_root(GEN E, long prec) { GEN c4=ell_get_c4(E), c6=ell_get_c6(E), j=ell_get_j(E), p=ellQp_get_p(E); GEN c6p, T, a; long alpha; int pis2 = absequaliu(p, 2); if (Q_pval(j, p) >= 0) pari_err_DOMAIN(".root", "v_p(j)", ">=", gen_0, j); /* v(j) < 0 => v(c4^3) = v(c6^2) = 2 alpha */ alpha = Q_pvalrem(ell_get_c4(E), p, &c4) >> 1; if (alpha) (void)Q_pvalrem(ell_get_c6(E), p, &c6); /* Renormalized so that v(c4) = v(c6) = 0; multiply by p^alpha at the end */ if (prec < 4 && pis2) prec = 4; c6p = modii(c6,p); if (pis2) { /* Use 432T(X/4) = 27X^3 - 9c4 X - 2c6 to have integral root; a=0 mod 2 */ T = mkpoln(4, utoipos(27), gen_0, mulis(c4,-9), mulis(c6, -2)); /* v_2(root a) = 1, i.e. will lose one bit of accuracy: prec+1 */ a = ZpX_liftroot(T, gen_0, p, prec+1); alpha -= 2; } else if (absequaliu(p, 3)) { /* Use 216T(X/3) = 32X^3 - 6c4 X - c6 to have integral root; a=-c6 mod 3 */ a = Fp_neg(c6p, p); T = mkpoln(4, utoipos(32), gen_0, mulis(c4, -6), negi(c6)); a = ZX_Zp_root(T, a, p, prec); switch(lg(a)-1) { case 1: /* single root */ a = gel(a,1); break; case 3: /* three roots, e.g. "15a1", choose the right one */ { GEN a1 = gel(a,1), a2 = gel(a,2), a3 = gel(a,3); long v1 = Z_lval(subii(a2, a3), 3); long v2 = Z_lval(subii(a1, a3), 3); long v3 = Z_lval(subii(a1, a2), 3); if (v1 == v2) a = a3; else if (v1 == v3) a = a2; else a = a1; } break; } alpha--; } else { /* p != 2,3: T = 4(x-a)(x-b)^2 = 4x^3 - 3a^2 x - a^3 when b = -a/2 * (so that the trace coefficient vanishes) => a = c6/6c4 (mod p)*/ GEN c4p = modii(c4,p); a = Fp_div(c6p, Fp_mulu(c4p, 6, p), p); T = mkpoln(4, utoipos(864), gen_0, mulis(c4, -18), negi(c6)); a = ZpX_liftroot(T, a, p, prec); } a = cvtop(a, p, prec); if (alpha) setvalp(a, valp(a)+alpha); return gsub(a, gdivgu(ell_get_b2(E), 12)); } GEN ellQp_root(GEN E, long prec) { return obj_checkbuild_padicprec(E, Qp_ROOT, &doellQp_root, prec); } /* compute a,b such that E1: y^2 = x(x-a)(x+a-b) ~ E */ static void doellQp_ab(GEN E, GEN *pta, GEN *ptb, long prec) { GEN b2 = ell_get_b2(E), b4 = ell_get_b4(E), e1 = ellQp_root(E, prec); GEN w, u, t = gadd(gdivgu(b2,4), gmulsg(3,e1)), p = ellQp_get_p(E); w = Qp_sqrt(gmul2n(gadd(b4,gmul(e1,gadd(b2,gmulsg(6,e1)))),1)); u = gadd(t,w); /* Decide between w and -w: we want v(a-b) > v(b) */ if (absequaliu(p,2)) { if (valp(u)-1 <= valp(w)) w = gneg_i(w); } else { if (valp(u) <= valp(w)) w = gneg_i(w); } /* w^2 = 2b4 + 2b2 e1 + 12 e1^2 = 4(e1-e2)(e1-e3) */ *pta = gmul2n(gsub(w,t),-2); *ptb = gmul2n(w,-1); } static GEN doellQp_Tate(GEN E, long prec0) { GEN p = ellQp_get_p(E), j = ell_get_j(E); GEN L, u, u2, q, x1, a, b, d, s, t, AB, A, M2; long v, n, pp, prec = prec0+3; int split = -1; /* unknown */ int pis2 = equaliu(p,2); if (Q_pval(j, p) >= 0) pari_err_DOMAIN(".tate", "v_p(j)", ">=", gen_0, j); START: doellQp_ab(E, &a, &b, prec); d = gsub(a,b); v = prec0 - precp(d); if (v > 0) { prec += v; goto START; } AB = Qp_agm2_sequence(a,b); A = gel(AB,1); n = lg(A)-1; /* AGM iterations */ pp = minss(precp(a),precp(b)); M2 = cvtop(gel(A,n), p, pis2? pp-2*n: pp); setvalp(M2, valp(a)); u2 = ginv(gmul2n(M2, 2)); if (split < 0) split = issquare(u2); x1 = gen_0; Qp_descending_Landen(AB,&x1,NULL); t = gaddsg(1, ginv(gmul2n(gmul(u2,x1),1))); s = Qp_sqrt(gsubgs(gsqr(t), 1)); q = gadd(t,s); if (gequal0(q)) q = gsub(t,s); v = prec0 - precp(q); if (split) { /* we want log q at precision prec0 */ GEN q0 = leafcopy(q); setvalp(q0, 0); v += valp(gsubgs(q0,1)); } if (v > 0) { prec += v; goto START; } if (valp(q) < 0) q = ginv(q); if (split) { u = Qp_sqrt(u2); L = gdivgs(Qp_log(q), valp(q)); } else { GEN T = mkpoln(3, gen_1, gen_0, gneg(u2)); u = mkpolmod(pol_x(0), T); L = gen_1; } return mkvecn(6, u2, u, q, mkvec2(a, b), L, AB); } static long Tate_prec(GEN T) { return padicprec_relative(gel(T,3)); } GEN ellQp_Tate_uniformization(GEN E, long prec) { return obj_checkbuild_prec(E,Qp_TATE,&doellQp_Tate, &Tate_prec,prec); } GEN ellQp_u(GEN E, long prec) { GEN T = ellQp_Tate_uniformization(E, prec); return gel(T,2); } GEN ellQp_u2(GEN E, long prec) { GEN T = ellQp_Tate_uniformization(E, prec); return gel(T,1); } GEN ellQp_q(GEN E, long prec) { GEN T = ellQp_Tate_uniformization(E, prec); return gel(T,3); } GEN ellQp_ab(GEN E, long prec) { GEN T = ellQp_Tate_uniformization(E, prec); return gel(T,4); } GEN ellQp_L(GEN E, long prec) { GEN T = ellQp_Tate_uniformization(E, prec); return gel(T,5); } GEN ellQp_AGM(GEN E, long prec) { GEN T = ellQp_Tate_uniformization(E, prec); return gel(T,6); } /* FORMAL GROUP */ /* t to w := -1/y */ GEN ellformalw(GEN e, long n, long v) { pari_sp av = avma, av2; GEN a1,a2,a3,a4,a6, a63; GEN w = cgetg(3, t_SER), t, U, V, W, U2; ulong mask, nold = 1; if (v < 0) v = 0; if (n <= 0) pari_err_DOMAIN("ellformalw","precision","<=",gen_0,stoi(n)); mask = quadratic_prec_mask(n); t = pol_x(v); checkell(e); a1 = ell_get_a1(e); a2 = ell_get_a2(e); a3 = ell_get_a3(e); a4 = ell_get_a4(e); a6 = ell_get_a6(e); a63 = gmulgu(a6,3); w[1] = evalsigne(1)|evalvarn(v)|evalvalser(3); gel(w,2) = gen_1; /* t^3 + O(t^4) */ /* use Newton iteration, doubling accuracy at each step * * w^3 a6 + w^2(a4 t + a3) + w (a2 t^2 + a1 t - 1) + t^3 * w <- w - ----------------------------------------------------- * w^2 (3a6) + w (2a4 t + 2a3) + (a2 t^2 + a1 t - 1) * * w^3 a6 + w^2 U + w V + W * =: w - ----------------------- * w^2 (3a6) + 2w U + V */ U = gadd(gmul(a4,t), a3); U2 = gmul2n(U,1); V = gsubgs(gadd(gmul(a2,gsqr(t)), gmul(a1,t)), 1); W = gpowgs(t,3); av2 = avma; while (mask > 1) { /* nold correct terms in w */ ulong i, nnew = nold << 1; GEN num, den, wnew, w2, w3; if (mask & 1) nnew--; mask >>= 1; wnew = cgetg(nnew+2, t_SER); wnew[1] = w[1]; for (i = 2; i < nold+2; i++) gel(wnew,i) = gel(w,i); for ( ; i < nnew+2; i++) gel(wnew,i) = gen_0; w = wnew; w2 = gsqr(w); w3 = gmul(w2,w); num = gadd(gmul(a6,w3), gadd(gmul(U,w2), gadd(gmul(V,w), W))); den = gadd(gmul(a63,w2), gadd(gmul(w,U2), V)); w = gerepileupto(av2, gsub(w, gdiv(num, den))); nold = nnew; } return gerepilecopy(av, w); } static GEN ellformalpoint_i(GEN w, GEN wi) { return mkvec2(gmul(pol_x(varn(w)),wi), gneg(wi)); } /* t to [x,y] */ GEN ellformalpoint(GEN e, long n, long v) { pari_sp av = avma; GEN w = ellformalw(e, n, v), wi = ser_inv(w); return gerepilecopy(av, ellformalpoint_i(w, wi)); } static GEN ellformaldifferential_i(GEN e, GEN w, GEN wi, GEN *px) { GEN x, w1; if (gequal0(ell_get_a1(e)) && gequal0(ell_get_a3(e))) { /* dx/2y = dx * -w/2, avoid division */ x = gmul(pol_x(varn(w)), wi); w1 = gmul(derivser(x), gneg(gmul2n(w,-1))); } else { GEN P = ellformalpoint_i(w, wi); x = gel(P,1); w1 = gdiv(derivser(x), ec_dmFdy_evalQ(e, P)); } *px = x; return w1; } /* t to [ dx / (2y + a1 x + a3), x * ... ]*/ GEN ellformaldifferential(GEN e, long n, long v) { pari_sp av = avma; GEN w = ellformalw(e, n, v), wi = ser_inv(w), x; GEN w1 = ellformaldifferential_i(e, w, wi, &x); return gerepilecopy(av, mkvec2(w1,gmul(x,w1))); } /* t to z, dz = w1 dt */ GEN ellformallog(GEN e, long n, long v) { pari_sp av = avma; GEN w = ellformalw(e, n, v), wi = ser_inv(w), x; GEN w1 = ellformaldifferential_i(e, w, wi, &x); return gerepileupto(av, integser(w1)); } /* z to t */ GEN ellformalexp(GEN e, long n, long v) { pari_sp av = avma; return gerepileupto(av, serreverse(ellformallog(e,n,v))); } /* [log_p (sigma(t) / t), log_E t], as power series, d (log_E t) := w1 dt; * As a fonction of z: odd, = e.b2/12 * z + O(z^3). * sigma(z) = ellsigma(e) exp(e.b2/24*z^2) * log_p(sigma(t)/t)=log(subst(sigma(z), x, ellformallog(e))/x) */ static GEN ellformallogsigma_t(GEN e, long n) { pari_sp av = avma; GEN w = ellformalw(e, n, 0), wi = ser_inv(w), t = pol_x(0); GEN x, s = ellformaldifferential_i(e, w, wi, &x); GEN f = gmul(s, gadd(integser(gmul(x,s)), gmul2n(ell_get_a1(e),-1))); return gerepilecopy(av, mkvec2(integser( gsub(ginv(gneg(t)), f) ), integser(s))); } /* P-ADIC HEIGHTS */ /* m >= 0, T = b6^2, g4 = b6^2 - b4 b8, return g_m(xP) mod N, in Mazur-Tate's * notation (Duke 1991)*/ static GEN rellg(hashtable *H, GEN m, GEN T, GEN g4, GEN b8, GEN N) { hashentry *h; GEN n, z, np2, np1, nm2, nm1, fp2, fp1, fm2, fm1, f; ulong m4; if (abscmpiu(m, 4) <= 0) switch(itou(m)) { case 0: return gen_0; case 1: return gen_1; case 2: return subiu(N,1); case 3: return b8; case 4: return g4; } if ((h = hash_search(H, (void*)m))) return (GEN)h->val; m4 = mod4(m); n = shifti(m, -1); f = rellg(H,n,T,g4,b8,N); np2 = addiu(n, 2); fp2 = rellg(H,np2,T,g4,b8,N); np1 = addiu(n, 1); fp1 = rellg(H,np1,T,g4,b8,N); nm2 = subiu(n, 2); fm2 = rellg(H,nm2,T,g4,b8,N); nm1 = subiu(n, 1); fm1 = rellg(H,nm1,T,g4,b8,N); if (odd(m4)) { GEN t1 = Fp_mul(fp2, Fp_powu(f,3,N), N); GEN t2 = Fp_mul(fm1, Fp_powu(fp1,3,N), N); if (mpodd(n)) t2 = Fp_mul(T,t2,N); else t1 = Fp_mul(T,t1,N); z = Fp_sub(t1, t2, N); } else { GEN t1 = Fp_mul(fm2, Fp_sqr(fp1,N), N); GEN t2 = Fp_mul(fp2, Fp_sqr(fm1,N), N); z = Fp_mul(f, Fp_sub(t1, t2, N), N); } hash_insert(H, (void*)m, (void*)z); return z; } static GEN addii3(GEN x, GEN y, GEN z) { return addii(x,addii(y,z)); } static GEN addii4(GEN x, GEN y, GEN z, GEN t) { return addii(x,addii3(y,z,t)); } static GEN addii5(GEN x, GEN y, GEN z, GEN t, GEN u) { return addii(x,addii4(y,z,t,u)); } /* xP = [n,d] (corr. to n/d, coprime), such that the reduction of the point * P = [xP,yP] is non singular at all places. Return x([m] P) mod N as * [num,den] (coprime) */ static GEN xmP(GEN e, GEN xP, GEN m, GEN N) { pari_sp av = avma; ulong k = expi(m); hashtable *H = hash_create((5+k)*k, (ulong(*)(void*))&hash_GEN, (int(*)(void*,void*))&gidentical, 1); GEN b2 = ell_get_b2(e), b4 = ell_get_b4(e), n = gel(xP,1), d = gel(xP,2); GEN b6 = ell_get_b6(e), b8 = ell_get_b8(e); GEN B4, B6, B8, T, g4; GEN d2 = Fp_sqr(d,N), d3 = Fp_mul(d2,d,N), d4 = Fp_sqr(d2,N); GEN n2 = Fp_sqr(n,N), n3 = Fp_mul(n2,n,N), n4 = Fp_sqr(n2,N); GEN nd = Fp_mul(n,d,N), n2d2 = Fp_sqr(nd,N); GEN b2nd = Fp_mul(b2,nd, N), b2n2d = Fp_mul(b2nd,n,N); GEN b6d3 = Fp_mul(b6,d3,N), g,gp1,gm1, C,D; B8 = addii5(muliu(n4,3), mulii(b2n2d,n), mulii(muliu(b4,3), n2d2), mulii(muliu(b6d3,3), n), mulii(b8,d4)); B6 = addii4(muliu(n3,4), mulii(b2nd,n), shifti(mulii(b4,Fp_mul(n,d2,N)), 1), b6d3); B4 = addii3(muliu(n2,6), b2nd, mulii(b4,d2)); B4 = modii(B4,N); B6 = modii(B6,N); B8 = modii(B8,N); g4 = Fp_sub(sqri(B6), mulii(B4,B8), N); T = Fp_sqr(B6,N); g = rellg(H, m, T,g4,B8, N); gp1 = rellg(H, addiu(m,1), T,g4,B8, N); gm1 = rellg(H, subiu(m,1), T,g4,B8, N); C = Fp_sqr(g, N); D = Fp_mul(gp1,gm1, N); if (mpodd(m)) { n = Fp_sub(mulii(C,n), mulii(D,B6), N); d = Fp_mul(C,d, N); } else { n = Fp_sub(Fp_mul(Fp_mul(B6,C,N), n, N), D, N); d = Fp_mul(Fp_mul(C,d,N), B6, N); } return gerepilecopy(av, mkvec2(n,d)); } /* given [n,d2], x = n/d2 (coprime, d2 = d^2), p | den, * return t = -x/y + O(p^v) */ static GEN tfromx(GEN e, GEN x, GEN p, long v, GEN N, GEN *pd) { GEN n = gel(x,1), d2 = gel(x,2), d; GEN a1, a3, b2, b4, b6, B, C, d4, d6, Y; if (!signe(n)) { *pd = gen_1; return zeropadic_shallow(p, v); } a1 = ell_get_a1(e); b2 = ell_get_b2(e); a3 = ell_get_a3(e); b4 = ell_get_b4(e); b6 = ell_get_b6(e); d = Qp_sqrt(cvtop(d2, p, v - Z_pval(d2,p))); if (!d) pari_err_BUG("ellpadicheight"); /* Solve Y^2 = 4n^3 + b2 n^2 d2+ 2b4 n d2^2 + b6 d2^3, * Y = 2y + a1 n d + a3 d^3 */ d4 = Fp_sqr(d2, N); d6 = Fp_mul(d4, d2, N); B = gmul(d, Fp_add(mulii(a1,n), mulii(a3,d2), N)); C = mkpoln(4, utoipos(4), Fp_mul(b2, d2, N), Fp_mul(shifti(b4,1), d4, N), Fp_mul(b6,d6,N)); C = FpX_eval(C, n, N); if (!signe(C)) Y = zeropadic_shallow(p, v >> 1); else Y = Qp_sqrt(cvtop(C, p, v - Z_pval(C,p))); if (!Y) pari_err_BUG("ellpadicheight"); *pd = d; return gdiv(gmulgs(gmul(n,d), -2), gsub(Y,B)); } /* return minimal i s.t. -v_p(j+1) - log_p(j-1) + (j+1)*t >= v for all j>=i */ static long logsigma_prec(GEN p, long v, long t) { double log2p = dbllog2(p); long j, i = ceil((v - t) / (t - 2*M_LN2/(3*log2p)) + 0.01); if (absequaliu(p,2) && i < 5) i = 5; /* guaranteed to work, now optimize */ for (j = i-1; j >= 2; j--) { if (- u_pval(j+1,p) - log2(j-1)/log2p + (j+1)*t + 0.01 < v) break; i = j; } if (j == 1) { if (- absequaliu(p,2) + 2*t + 0.01 >= v) i = 1; } return i; } /* return minimal i s.t. -v_p(j+1) + (j+1)*t >= v for all j>=i */ static long log_prec(GEN p, long v, long t) { double log2p = dbllog2(p); long j, i = ceil(v / (t - M_LN2/(2*log2p)) + 0.01); /* guaranteed to work, now optimize */ for (j = i-1; j >= 1; j--) { if (- u_pval(j+1,p) + (j+1)*t + 0.01 < v) break; i = j; } return i; } /* P = rational point of exact denominator d. Is Q singular on E(Fp) ? */ static int FpE_issingular(GEN E, GEN P, GEN d, GEN p) { pari_sp av = avma; GEN t, x, y, a1, a2, a3, a4; if (ell_is_inf(E) || dvdii(d,p)) return 0; /* 0_E is smooth */ P = Q_muli_to_int(P,d); x = gel(P,1); y = gel(P,2); a1 = ell_get_a1(E); a3 = ell_get_a3(E); t = addii(shifti(y,1), addii(mulii(a1,x), mulii(a3,d))); if (!dvdii(t,p)) return gc_bool(av, 0); a2 = ell_get_a2(E); a4 = ell_get_a4(E); d = Fp_inv(d, p); x = Fp_mul(x,d,p); y = Fp_mul(y,d,p); t = subii(mulii(a1,y), addii(a4, mulii(x, addii(gmul2n(a2,1), muliu(x,3))))); return gc_bool(av, dvdii(t,p)); } /* E/Q, P on E(Q). Let g > 0 minimal such that the image of R = [g]P in a * minimal model is everywhere nonsingular; return [R,g] */ GEN ellnonsingularmultiple(GEN e, GEN P) { pari_sp av = avma; GEN ch, E = ellanal_globalred(e, &ch), NP, L, S, d, g = gen_1; long i, l; checkellpt(P); if (ell_is_inf(P)) retmkvec2(gcopy(P), gen_1); if (E != e) P = ellchangepoint(P, ch); S = obj_check(E, Q_GLOBALRED); NP = gmael(S,3,1); L = gel(S,4); l = lg(NP); d = Q_denom(P); for (i = 1; i < l; i++) { GEN G = gel(L,i), p = gel(NP,i);/* prime of bad reduction */ long kod; if (!FpE_issingular(E, P, d, p)) continue; kod = itos(gel(G,2)); /* Kodaira type */ if (kod >= 5) /* I_nu */ { long nu = kod - 4; long n = minss(Q_pval(ec_dmFdy_evalQ(E,P), p), nu/2); nu /= ugcd(nu, n); g = muliu(g, nu); P = ellmul(E, P, utoipos(nu)); d = Q_denom(P); } else if (kod <= -5) /* I^*_nu */ { /* either 2 or 4 */ long nu = - kod - 4; P = elladd(E, P,P); d = Q_denom(P); g = shifti(g,1); if (odd(nu) && FpE_issingular(E, P, d, p)) { /* it's 4 */ P = elladd(E, P,P); d = Q_denom(P); g = shifti(g,1); } } else { GEN c = gel(G, 4); /* Tamagawa number at p */ if (absequaliu(c, 4)) c = gen_2; P = ellmul(E, P, c); d = Q_denom(P); g = mulii(g, c); } } if (E != e) P = ellchangepointinv(P, ch); return gerepilecopy(av, mkvec2(P,g)); } GEN ellpadicheight(GEN e, GEN p, long v0, GEN P) { pari_sp av = avma; GEN N, H, h, t, ch, g, E, x, D, ls, lt, S, a,b; long v, vd; int is2; checkellpt(P); if (v0<=0) pari_err_DOMAIN("ellpadicheight","precision","<=",gen_0,stoi(v0)); checkell_Q(e); if (typ(p) != t_INT) pari_err_TYPE("ellpadicheight",p); if (cmpiu(p,2) < 0) pari_err_PRIME("ellpadicheight",p); if (ellorder_Q(e,P)) return mkvec2(gen_0,gen_0); E = ellanal_globalred(e, &ch); if (E != e) P = ellchangepoint(P, ch); S = ellnonsingularmultiple(E, P); P = gel(S,1); g = gel(S,2); v = v0 + 2*Z_pval(g, p); is2 = absequaliu(p,2); if (is2) v += 2; x = Q_remove_denom(gel(P,1), &b); x = mkvec2(x, b? b: gen_1); vd = Z_pval(gel(x,2), p); if (!vd) { /* P not in kernel of reduction mod p */ GEN d, m, X, Pp, Ep = ellinit(E, mkintmod(gen_0,p), 0); long w = v+2; Pp = RgV_to_FpV(P, p); if (lg(Ep) != 1) m = ellorder(Ep, Pp, NULL); else { /* E has bad reduction at p */ m = ellcard(E, p); if (equalii(m, p)) pari_err_TYPE("ellpadicheight: additive reduction", E); } g = mulii(g,m); for(;;) { N = powiu(p, w); X = xmP(E, x, m, N); d = gel(X,2); if (!signe(d)) w <<= 1; else { vd = Z_pval(d, p); if (w >= v+2*vd + is2) break; w = v+2*vd + is2; } } x = X; } /* we will want t mod p^(v+vd) because of t/D in H later, and * we lose p^vd in tfromx because of sqrt(d) (p^(vd+1) if p=2)*/ v += 2*vd + is2; N = powiu(p,v); t = tfromx(E, x, p, v, N, &D); /* D^2=denom(x)=x[2] */ S = ellformallogsigma_t(E, logsigma_prec(p, v-vd, valp(t)) + 1); ls = ser2rfrac_i(gel(S,1)); /* log_p (sigma(T)/T) */ lt = ser2rfrac_i(gel(S,2)); /* log_E (T) */ /* evaluate our formal power series at t */ H = gadd(poleval(ls, t), glog(gdiv(t, D), 0)); h = gsqr(poleval(lt, t)); g = sqri(g); a = gdiv(gmulgs(H,-2), g); b = gdiv(gneg(h), g); if (E != e) { GEN u = gel(ch,1), r = gel(ch,2); a = gdiv(gadd(a, gmul(r,b)), u); b = gmul(u,b); } H = mkvec2(a,b); gel(H,1) = precp_fix(gel(H,1),v0); gel(H,2) = precp_fix(gel(H,2),v0); return gerepilecopy(av, H); } GEN ellpadiclog(GEN E, GEN p, long n, GEN P) { pari_sp av = avma; long vt; GEN t, x, y, L; checkellpt(P); if (ell_is_inf(P)) return gen_0; x = gel(P,1); y = gel(P,2); t = gneg(gdiv(x,y)); vt = gvaluation(t, p); /* can be a t_INT, t_FRAC or t_PADIC */ if (vt <= 0) pari_err_DOMAIN("ellpadiclog","P","not in the kernel of reduction at",p,P); L = ser2rfrac_i(ellformallog(E, log_prec(p, n, vt) + 1, 0)); return gerepileupto(av, poleval(L, cvtop(t, p, n))); } /* E/Qp has multiplicative reduction, Tate curve */ static GEN ellpadics2_tate(GEN Ep, long n) { pari_sp av; GEN u2 = ellQp_u2(Ep, n), q = ellQp_q(Ep, n), pn = gel(q,3); GEN qm, s, b2 = ell_get_b2(Ep), v = vecfactoru_i(1, n); long m; qm = Fp_powers(padic_to_Fp(q, pn), n, pn); s = gel(qm, 2); av = avma; for (m = 2; m <= n; m++) /* sum sigma(m) q^m */ { s = addii(s, mulii(gel(qm,m+1), usumdiv_fact(gel(v,m)))); if ((m & 31) == 0) s = gerepileuptoint(av, s); } s = subui(1, muliu(s,24)); s = gdivgu(gsub(b2, gdiv(s,u2)), 12); return precp_fix(s,n); } GEN ellpadicfrobenius(GEN E, ulong p, long n) { checkell(E); if (p < 2) pari_err_DOMAIN("ellpadicfrobenius","p", "<", gen_2, utoipos(p)); switch(ell_get_type(E)) { case t_ELL_Q: break; case t_ELL_Qp: if (equaliu(ellQp_get_p(E), p)) break; default: pari_err_TYPE("ellpadicfrobenius", E); } return hyperellpadicfrobenius(ec_bmodel(E,0), p, n); } /* s2 = (b_2-E_2)/12 */ GEN ellpadics2(GEN E, GEN p, long n) { pari_sp av = avma; GEN l, F, a,b,d, ap; ulong pp; if (typ(p) != t_INT) pari_err_TYPE("ellpadics2",p); if (cmpis(p,2) < 0) pari_err_PRIME("ellpadics2",p); checkell(E); if (Q_pval(ell_get_j(E), p) < 0) { GEN Ep; if (ell_get_type(E) == t_ELL_Qp) Ep = E; else Ep = ellinit(E, zeropadic_shallow(p,n), 0); l = ellpadics2_tate(Ep, n); if (Ep != E) obj_free(Ep); return gerepilecopy(av, l); } pp = itou(p); F = ellpadicfrobenius(E, pp, n); a = gcoeff(F,1,1); b = gcoeff(F,1,2); d = gcoeff(F,2,2); ap = gadd(a,d); if (valp(ap) > 0) pari_err_DOMAIN("ellpadics2","E","is supersingular at",p,E); if (pp == 2 || (pp <= 13 && n == 1)) /* 2sqrt(p) > p/2: ambiguity */ ap = ellap(E,p); else { /* either 2sqrt(p) < p/2 or n > 1 and 2sqrt(p) < p^2/2 (since p!=2) */ GEN q = pp <= 13? utoipos(pp * pp): p; ap = padic_to_Fp(ap, q); ap = Fp_center_i(ap, q, shifti(q,-1)); } l = mspadic_unit_eigenvalue(ap, 2, p, n); return gerepileupto(av, gdiv(b, gsub(l, a))); /* slope of eigenvector */ } /* symbol and modular symbol space attached to E to later compute * ellpadicL(E,p,, s,,D) */ static GEN ellpadicL_symbol(GEN E, GEN p, GEN s, GEN D) { GEN s1, s2, ap; long sign; checkell(E); if (ell_get_type(E) != t_ELL_Q) pari_err_TYPE("ellpadicL",E); ap = ellap(E,p); if (D && typ(D) != t_INT) pari_err_TYPE("ellpadicL",D); if (D && !Z_isfundamental(D)) pari_err_DOMAIN("ellpadicL", "isfundamental(D)", "=", gen_0, D); if (!D) D = gen_1; if (Z_pval(ellQ_get_N(E), p) >= 2) pari_err_IMPL("additive reduction in ellpadicL"); mspadic_parse_chi(s, &s1,&s2); sign = signe(D); if (mpodd(s2)) sign = -sign; return shallowconcat(msfromell(E, sign), mkvec4(ap, p, s, D)); } /* W an ellpadicL_symbol, initialize for ellpadicL(E,p,n,s,,D) */ static GEN ellpadicL_init(GEN W, long n) { GEN Wp, den, M = gel(W,1), xpm = gel(W,2), ap = gel(W,3), s = gel(W,5); long p = itos(gel(W,4)), D = itos(gel(W,6)); xpm = Q_remove_denom(xpm,&den); if (!den) den = gen_1; n += Z_lval(den,p); Wp = mspadicinit(M, p, n, Z_lval(ap,p)); return mkvec3(mspadicmoments(Wp,xpm,D), den, s); } /* v from ellpadicL_init, compute ellpadicL(E,p,n,s,r,D) */ static GEN ellpadic_i(GEN v, long r) { GEN oms = gel(v,1), den = gel(v,2), s = gel(v,3); return gdiv(mspadicL(oms,s,r), den); } GEN ellpadicL(GEN E, GEN p, long n, GEN s, long r, GEN D) { pari_sp av = avma; GEN W, v; if (r < 0) pari_err_DOMAIN("ellpadicL","r","<",gen_0,stoi(r)); if (n <= 0) pari_err_DOMAIN("ellpadicL","precision","<=",gen_0,stoi(n)); W = ellpadicL_symbol(E, p, s, D); v = ellpadicL_init(W, n); return gerepileupto(av, ellpadic_i(v, r)); } static long torsion_order(GEN E) { GEN T = elltors(E); return itos(gel(T,1)); } /* E given by a minimal model; D != 0. Compare Euler factor of L(E,(D/.),1) * with L(E^D,1). Return * \prod_{p|D} (p-a_p(E)+eps_{E}(p)) / p, * where eps(p) = 0 if p | N_E and 1 otherwise */ static GEN get_Euler(GEN E, GEN D) { GEN a = gen_1, b = gen_1, P = gel(absZ_factor(D), 1); long i, l = lg(P); for (i = 1; i < l; i++) { GEN p = gel(P,i); a = mulii(a, ellcard(E, p)); b = mulii(b, p); } return Qdivii(a, b); } GEN ellpadicbsd(GEN E, GEN p, long n, GEN D) { const long MAXR = 30; pari_sp av = avma; GEN D0, W, ED, tam, ND, C, apD, U = NULL;/*-Wall*/ long r, vN; checkell(E); if (D && isint1(D)) D = NULL; D0 = ellminimaltwistcond(E); if (isint1(D0)) D0 = NULL; if (D0) { E = elltwist(E, D0); D = D? coredisc(mulii(D, D0)): D0; } W = ellpadicL_symbol(E, p, gen_0, D); ED = D? elltwist(E, D): E; ED = ellanal_globalred_all(ED, NULL, &ND, &tam); vN = Z_pval(ND, p); /* additive reduction ? */ if (vN >= 2) pari_err_DOMAIN("ellpadicbsd","v_p(N(E_D))",">",gen_1,stoi(vN)); if (n < 5) n = 5; for(;; n <<= 1) { pari_sp av2 = avma; GEN v = ellpadicL_init(W, n); for (r = 0; r < MAXR; r++) { U = ellpadic_i(v, r); if (!gequal0(U)) break; } if (r < MAXR) break; set_avma(av2); } apD = ellap(ED, p); if (typ(U) == t_COL) { /* p | a_p(E_D), frobenius on E_D */ GEN F = mkmat22(gen_0, negi(p), gen_1, apD); U = RgM_RgC_mul(gpowgs(gsubsg(1, gdiv(F,p)), -2), U); settyp(U, t_VEC); } else if (dvdii(ND,p)) { if (equalim1(apD)) /* divide by 1-1/a_p */ U = gdivgu(U, 2); else { /* ap = 1 */ GEN EDp = ellinit(ED, zeropadic_shallow(p,n), 0); U = gdiv(U, ellQp_L(EDp,n)); obj_free(EDp); } } else { GEN a = mspadic_unit_eigenvalue(apD, 2, p, n); U = gmul(U, gpowgs(gsubsg(1, ginv(a)), -2)); } C = mulii(tam, mpfact(r)); if (D) C = gmul(C, get_Euler(ED, D)); C = gdiv(sqru(torsion_order(ED)), C); if (D) obj_free(ED); return gerepilecopy(av, mkvec2(utoi(r), gmul(U, C))); } GEN ellpadicregulator(GEN E, GEN p, long n, GEN S) { pari_sp av = avma; GEN FG = ellpadicheightmatrix(E,p,n,S); /* forbids additive reduction */ /* [F,G]: height in basis [omega, eta] */ GEN R, F = gel(FG,1), G = gel(FG,2), ap = ellap(E,p); if (dvdii(ap, p)) { /* supersingular */ GEN f = ellpadicfrobenius(E, itou(p), n); GEN x = gcoeff(f,1,1), y = gcoeff(f,2,1); /* [A,B]: regulator height in basis [omega, eta] */ GEN A = det(F), B = det(gadd(F,G)), C; C = gdiv(gsub(B,A), y); /* R: regulator height in basis [omega, F.omega] */ R = mkvec2(gsub(A, gmul(x,C)), C); } else { GEN s2; if (equali1(ap) && dvdii(ell_get_disc(E),p)) { /* split multiplicative reduction */ GEN Ep = ellinit(E, zeropadic_shallow(p,n), 0); GEN q = ellQp_q(Ep,n), u2 = ellQp_u2(Ep,n); s2 = ellpadics2_tate(Ep, n); s2 = gsub(s2, ginv(gmul(Qp_log(q), u2))); /*extended MW group contrib*/ obj_free(Ep); } else s2 = ellpadics2(E,p,n); R = det( RgM_sub(F, RgM_Rg_mul(G,s2)) ); } return gerepilecopy(av, R); } pari-2.17.2/src/basemath/kummer.c0000644000175000017500000012732514760123736015226 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*******************************************************************/ /* */ /* KUMMER EXTENSIONS */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_bnrclassfield 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, powg; 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; /* REDUCTION MOD ell-TH POWERS */ /* make b integral by multiplying by t in (Q^*)^ell */ static GEN reduce_mod_Qell(GEN nf, GEN b, ulong ell) { GEN c; b = nf_to_scalar_or_basis(nf, b); b = Q_primitive_part(b, &c); if (c) { GEN d, fa = Q_factor_limit(c, 1000000); d = factorback2(gel(fa,1), ZV_to_Flv(gel(fa,2), ell)); b = typ(b) == t_INT? mulii(b,d): ZC_Z_mul(b, d); } return b; } static GEN reducebeta(GEN bnfz, GEN b, long ell) { GEN t, cb, fu, nf = bnf_get_nf(bnfz); if (DEBUGLEVEL>1) err_printf("reducing beta = %Ps\n",b); b = reduce_mod_Qell(nf, b, ell); t = idealredmodpower(nf, b, ell, 1000000); if (!isint1(t)) b = nfmul(nf, b, nfpow_u(nf, t, ell)); if (DEBUGLEVEL>1) err_printf("beta reduced via ell-th root = %Ps\n",b); b = Q_primitive_part(b, &cb); if (cb && nfispower(nf, b, ell, NULL)) return cb; if ((fu = bnf_build_cheapfu(bnfz))) { /* log. embeddings of fu^ell */ GEN elllogfu = gmulgs(real_i(bnf_get_logfu(bnfz)), ell); long prec = nf_get_prec(nf); for (;;) { GEN ex, y, z = nflogembed(nf, b, NULL, prec); if (z && (ex = RgM_Babai(elllogfu, z))) { if (ZV_equal0(ex)) break; y = nffactorback(nf, fu, ZC_z_mul(ex,ell)); b = nfdiv(nf, b, y); break; } prec = precdbl(prec); if (DEBUGLEVEL) pari_warn(warnprec,"reducebeta",prec); nf = nfnewprec_shallow(nf,prec); } } return cb? gmul(b, cb): b; } struct rnfkummer { GEN bnfz, cycgenmod, u, vecC, tQ, vecW; ulong mgi, g, ell; long rc; compo_s COMPO; tau_s tau; toK_s T; }; /* set kum->tau; compute Gal(K(\zeta_l)/K) */ static void get_tau(struct rnfkummer *kum) { /* compute action of tau: q^g + kp */ compo_s *C = &kum->COMPO; GEN U = RgX_add(RgXQ_powu(C->q, kum->g, C->R), RgX_muls(C->p, C->k)); kum->tau.x = RgX_RgXQ_eval(C->rev, U, C->R); kum->tau.R = C->R; kum->tau.zk = nfgaloismatrix(bnf_get_nf(kum->bnfz), kum->tau.x); } static GEN tauofvec(GEN x, tau_s *tau); static GEN tauofelt(GEN x, tau_s *tau) { switch(typ(x)) { case t_INT: case t_FRAC: return x; case t_COL: return RgM_RgC_mul(tau->zk, x); case t_MAT: return mkmat2(tauofvec(gel(x,1), tau), gel(x,2)); default: pari_err_TYPE("tauofelt",x); return NULL;/*LCOV_EXCL_LINE*/ } } static GEN tauofvec(GEN x, tau_s *tau) { long i, l; GEN y = cgetg_copy(x, &l); for (i=1; itau; long i, m = T->m; GEN y = trivial_fact(), powg = T->powg; /* powg[i] = g^i */ for (i=1; izk, id), gcoeff(id, 1,1)); } static int prconj(GEN P, GEN Q, tau_s *tau) { GEN p = pr_get_p(P), x = pr_get_gen(P); for(;;) { if (ZC_prdvd(x,Q)) return 1; x = FpC_red(tauofelt(x, tau), p); if (ZC_prdvd(x,P)) return 0; } } static int prconj_in_list(GEN S, GEN P, tau_s *tau) { long i, l, e, f; GEN p, x; if (!tau) return 0; p = pr_get_p(P); x = pr_get_gen(P); e = pr_get_e(P); f = pr_get_f(P); l = lg(S); for (i = 1; i < l; i++) { GEN Q = gel(S, i); if (equalii(p, pr_get_p(Q)) && e == pr_get_e(Q) && f == pr_get_f(Q)) if (ZV_equal(x, pr_get_gen(Q)) || prconj(gel(S,i), P, tau)) return 1; } return 0; } /* >= ell */ static long get_z(GEN pr, long ell) { return ell * (pr_get_e(pr) / (ell-1)); } /* zeta_ell in nfz */ static void list_Hecke(GEN *pSp, GEN *pvsprk, GEN nfz, GEN fa, GEN gell, tau_s *tau) { GEN P = gel(fa,1), E = gel(fa,2), faell, Sl, S, Sl1, Sl2, Vl, Vl2; long i, l = lg(P), ell = gell[2]; S = vectrunc_init(l); Sl1= vectrunc_init(l); Sl2= vectrunc_init(l); Vl2= vectrunc_init(l); for (i = 1; i < l; i++) { GEN pr = gel(P,i); if (!equaliu(pr_get_p(pr), ell)) { if (!prconj_in_list(S,pr,tau)) vectrunc_append(S,pr); } else { /* pr | ell */ long a = get_z(pr, ell) + 1 - itou(gel(E,i)); if (!a) { if (!prconj_in_list(Sl1,pr,tau)) vectrunc_append(Sl1, pr); } else if (a != 1 && !prconj_in_list(Sl2,pr,tau)) { vectrunc_append(Sl2, pr); vectrunc_append(Vl2, log_prk_init(nfz, pr, a, gell)); } } } faell = idealprimedec(nfz, gell); l = lg(faell); Vl = vectrunc_init(l); Sl = vectrunc_init(l); for (i = 1; i < l; i++) { GEN pr = gel(faell,i); if (!tablesearch(P, pr, cmp_prime_ideal) && !prconj_in_list(Sl, pr, tau)) { vectrunc_append(Sl, pr); vectrunc_append(Vl, log_prk_init(nfz, pr, get_z(pr,ell), gell)); } } *pvsprk = shallowconcat(Vl2, Vl); /* divide ell */ *pSp = shallowconcat(S, Sl1); } /* Return a Flm, sprk mod pr^k, pr | ell, k >= 2 */ static GEN logall(GEN nf, GEN v, long lW, long mgi, GEN gell, GEN sprk) { long i, ell = gell[2], l = lg(v); GEN M = cgetg(l,t_MAT); for (i = 1; i < l; i++) { GEN c = log_prk(nf, gel(v,i), sprk, gell); /* ell-rank = #c */ c = ZV_to_Flv(c, ell); if (i < lW) c = Flv_Fl_mul(c, mgi, ell); gel(M,i) = c; } return M; } static GEN matlogall(GEN nf, GEN v, long lW, long mgi, GEN gell, GEN vsprk) { GEN M = NULL; long i, l = lg(vsprk); for (i = 1; i < l; i++) M = vconcat(M, logall(nf, v, lW, mgi, gell, gel(vsprk,i))); return M; } /* id = (b) prod_{i <= rc} bnfz.gen[i]^v[i] (mod K^*)^ell, * - i <= rc: gen[i]^cyc[i] = (cycgenmod[i]); ell | cyc[i] * - i > rc: gen[i]^(u[i]*cyc[i]) = (cycgenmod[i]); u[i] cyc[i] = 1 mod ell */ static void isprincipalell(GEN bnfz, GEN id, GEN cycgenmod, ulong ell, long rc, GEN *pv, GEN *pb) { long i, l = lg(cycgenmod); GEN y = bnfisprincipal0(bnfz, id, nf_FORCE|nf_GENMAT); GEN v = ZV_to_Flv(gel(y,1), ell), b = gel(y,2); for (i = rc+1; i < l; i++) b = famat_mulpows_shallow(b, gel(cycgenmod,i), v[i]); setlg(v,rc+1); *pv = v; *pb = b; } static GEN compute_beta(GEN X, GEN vecWB, GEN ell, GEN bnfz) { GEN be = famat_reduce(famatV_zv_factorback(vecWB, X)); if (typ(be) == t_MAT) { gel(be,2) = centermod(gel(be,2), ell); be = nffactorback(bnfz, be, NULL); } be = reducebeta(bnfz, be, itou(ell)); if (DEBUGLEVEL>1) err_printf("beta reduced = %Ps\n",be); return be; } 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; ip, C->R); } /* lift ideal id in nf to nfz */ static GEN ideallifttoKz(GEN nfz, GEN nf, GEN id, compo_s *C) { GEN I = idealtwoelt(nf,id); GEN x = nf_to_scalar_or_alg(nf, gel(I,2)); 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 GEN prlifttoKz_i(GEN nfz, GEN nf, GEN pr, compo_s *C) { GEN p = pr_get_p(pr), T = nf_get_pol(nfz); if (nf_get_degree(nf) != 1) { /* restrict to primes above pr */ GEN t = pr_get_gen(pr); t = Q_primpart( lifttoKz(nf,t,C) ); T = FpX_gcd(FpX_red(T,p), FpX_red(t,p), p); T = FpX_normalize(T, p); } return gel(FpX_factor(T, p), 1); } /* lift ideal pr in nf to ONE prime in nfz (the others are conjugate under tau * and bring no further information on e_1 W). Assume pr coprime to * index of both nf and nfz, and unramified in Kz/K (minor simplification) */ static GEN prlifttoKz(GEN nfz, GEN nf, GEN pr, compo_s *C) { GEN P = prlifttoKz_i(nfz, nf, pr, C); return idealprimedec_kummer(nfz, gel(P,1), pr_get_e(pr), pr_get_p(pr)); } static GEN prlifttoKzall(GEN nfz, GEN nf, GEN pr, compo_s *C) { GEN P = prlifttoKz_i(nfz, nf, pr, C), p = pr_get_p(pr), vP; long l = lg(P), e = pr_get_e(pr), i; vP = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(vP,i) = idealprimedec_kummer(nfz,gel(P,i), e, p); return vP; } static GEN get_badbnf(GEN bnf) { long i, l; GEN bad = gen_1, gen = bnf_get_gen(bnf); l = lg(gen); for (i = 1; i < l; i++) { GEN g = gel(gen,i); bad = lcmii(bad, gcoeff(g,1,1)); } return bad; } /* test whether H has index p */ static int H_is_good(GEN H, GEN p) { long l = lg(H), status = 0, i; for (i = 1; i < l; i++) if (equalii(gcoeff(H,i,i), p) && ++status > 1) return 0; return status == 1; } static GEN bid_primes(GEN bid) { return prV_primes(gel(bid_get_fact(bid),1)); } /* Let K base field, L/K described by bnr (conductor F) + H. Return a list of * primes coprime to f*ell of degree 1 in K whose images in Cl_f(K) together * with ell*Cl_f(K), generate H: * thus they all split in Lz/Kz; t in Kz is such that * t^(1/p) generates Lz => t is an ell-th power in k(pr) for all such primes. * Restrict to primes not dividing * - the index of the polynomial defining Kz, * - the modulus, * - ell, * - a generator in bnf.gen or bnfz.gen. * If ell | F and Kz != K, set compute the congruence group Hz over Kz * and set *pfa to the conductor factorization. */ static GEN get_prlist(GEN bnr, GEN H, GEN gell, GEN *pfa, struct rnfkummer *kum) { pari_sp av0 = avma; GEN Hz = NULL, bnrz = NULL, cycz = NULL, nfz = NULL; GEN cyc = bnr_get_cyc(bnr), nf = bnr_get_nf(bnr), F = gel(bnr_get_mod(bnr),1); GEN bad, Hsofar, L = cgetg(1, t_VEC); forprime_t T; ulong p, ell = gell[2]; int Ldone = 0; bad = get_badbnf(bnr_get_bnf(bnr)); if (kum) { GEN bnfz = kum->bnfz, ideal = gel(bnr_get_mod(bnr), 1); GEN badz = lcmii(get_badbnf(bnfz), nf_get_index(bnf_get_nf(bnfz))); bad = lcmii(bad,badz); nfz = bnf_get_nf(bnfz); ideal = ideallifttoKz(nfz, nf, ideal, &kum->COMPO); *pfa = idealfactor_partial(nfz, ideal, bid_primes(bnr_get_bid(bnr))); if (dvdiu(idealdown(nf, ideal), ell)) { /* ell | N(ideal), need Hz = Ker N: Cl_Kz(bothz) -> Cl_K(ideal)/H * to update conductor */ bnrz = Buchraymod(bnfz, *pfa, nf_INIT, gell); cycz = bnr_get_cyc(bnrz); Hz = diagonal_shallow(ZV_snf_gcd(cycz, gell)); if (H_is_good(Hz, gell)) { *pfa = gel(bnrconductor_factored(bnrz, Hz), 2); return gc_all(av0, 2, &L, pfa); } } } bad = lcmii(gcoeff(F,1,1), bad); cyc = ZV_snf_gcd(cyc, gell); Hsofar = diagonal_shallow(cyc); if (H_is_good(Hsofar, gell)) { if (!Hz) return gc_all(av0, pfa? 2: 1, &L, pfa); Ldone = 1; } /* restrict to primes not dividing bad and 1 mod ell */ u_forprime_arith_init(&T, 2, ULONG_MAX, 1, ell); while ((p = u_forprime_next(&T))) { GEN LP; long i, l; if (!umodiu(bad, p)) continue; LP = idealprimedec_limit_f(nf, utoipos(p), 1); l = lg(LP); for (i = 1; i < l; i++) { pari_sp av = avma; GEN M, P = gel(LP,i), v = bnrisprincipalmod(bnr, P, gell, 0); if (!hnf_invimage(H, v)) { set_avma(av); continue; } /* P in H */ M = ZM_hnfmodid(shallowconcat(Hsofar, v), cyc); if (Hz) { /* N_{Kz/K} P in H hence P in Hz */ GEN vP = prlifttoKzall(nfz, nf, P, &kum->COMPO); long j, lv = lg(vP); for (j = 1; j < lv; j++) { v = bnrisprincipalmod(bnrz, gel(vP,j), gell, 0); if (!ZV_equal0(v)) { Hz = ZM_hnfmodid(shallowconcat(Hz,v), cycz); if (H_is_good(Hz, gell)) { *pfa = gel(bnrconductor_factored(bnrz, Hz), 2); if (!Ldone) L = vec_append(L, gel(vP,1)); return gc_all(av0, 2, &L, pfa); } } } P = gel(vP,1); } else if (kum) P = prlifttoKz(nfz, nf, P, &kum->COMPO); if (Ldone || ZM_equal(M, Hsofar)) continue; L = vec_append(L, P); Hsofar = M; if (H_is_good(Hsofar, gell)) { if (!Hz) return gc_all(av0, pfa? 2: 1, &L, pfa); Ldone = 1; } } } pari_err_BUG("rnfkummer [get_prlist]"); return NULL;/*LCOV_EXCL_LINE*/ } /*Lprz list of prime ideals in Kz that must split completely in Lz/Kz, vecWA * generators for the S-units used to build the Kummer generators. Return * matsmall M such that \prod WA[j]^x[j] ell-th power mod pr[i] iff * \sum M[i,j] x[j] = 0 (mod ell) */ static GEN subgroup_info(GEN bnfz, GEN Lprz, GEN gell, GEN vecWA) { GEN M, nfz = bnf_get_nf(bnfz), Lell = mkvec(gell); long i, j, ell = gell[2], l = lg(vecWA), lz = lg(Lprz); M = cgetg(l, t_MAT); for (j=1; j rc && r[i] != 1) c = muliu(c, Fl_inv(r[i], ell)); q = divis(c, ell); /* remainder = 0 (i <= rc) or 1 */ /* compute (b) = g^c mod ell-th powers */ G = equali1(q)? g: idealpowred(nf, g, q); /* lose principal part */ G = idealpows(nf, G, ell); if (i > rc) G = idealmul(nf, G, g); gel(B,i) = gel(bnfisprincipal0(bnf, G, nf_GENMAT|nf_FORCE), 2); } *pselmer = shallowconcat(futu(bnf), vecslice(B,1,rc)); return B; } static GEN rnfkummersimple(GEN bnr, GEN H, long ell) { long j, lSp, rc; GEN bnf, nf,bid, cycgenmod, Sp, vsprk, matP; GEN be, M, K, vecW, vecWB, vecBp, gell = utoipos(ell); /* primes landing in H must be totally split */ GEN Lpr = get_prlist(bnr, H, gell, NULL, NULL); bnf = bnr_get_bnf(bnr); if (!bnf_get_sunits(bnf)) bnf_build_units(bnf); nf = bnf_get_nf(bnf); bid = bnr_get_bid(bnr); list_Hecke(&Sp, &vsprk, nf, bid_get_fact2(bid), gell, NULL); cycgenmod = bnf_cycgenmod(bnf, ell, &vecW, &rc); lSp = lg(Sp); vecBp = cgetg(lSp, t_VEC); matP = cgetg(lSp, t_MAT); for (j = 1; j < lSp; j++) isprincipalell(bnf,gel(Sp,j), cycgenmod,ell,rc, &gel(matP,j),&gel(vecBp,j)); vecWB = shallowconcat(vecW, vecBp); M = matlogall(nf, vecWB, 0, 0, gell, vsprk); M = vconcat(M, shallowconcat(zero_Flm(rc,lg(vecW)-1), matP)); M = vconcat(M, subgroup_info(bnf, Lpr, gell, vecWB)); K = Flm_ker(M, ell); if (ell == 2) { GEN msign = nfsign(nf, vecWB), y; GEN arch = ZV_to_zv(bid_get_arch(bid)); /* the conductor */ msign = Flm_mul(msign, K, 2); y = Flm_ker(msign, 2); y = zv_equal0(arch)? gel(y,1): Flm_Flc_invimage(msign, arch, 2); K = Flm_Flc_mul(K, y, 2); } else K = gel(K,1); be = compute_beta(K, vecWB, gell, bnf); be = nf_to_scalar_or_alg(nf, be); if (typ(be) == t_POL) be = mkpolmod(be, nf_get_pol(nf)); return gsub(pol_xn(ell, 0), be); } static ulong nf_to_logFl(GEN nf, GEN x, GEN modpr, ulong g, ulong q, ulong ell, ulong p) { x = nf_to_Fp_coprime(nf, x, modpr); return Fl_log(Fl_powu(umodiu(x, p), q, p), g, ell, p); } static GEN nfV_to_logFlv(GEN nf, GEN x, GEN modpr, ulong g, ulong q, ulong ell, ulong p) { pari_APPLY_long(nf_to_logFl(nf, gel(x,i), modpr, g, q, ell, p)); } /* Compute e_1 Cl(K)/Cl(K)^ell. If u = w^ell a virtual unit, compute * discrete log mod ell on units.gen + bnf.gen (efficient variant of algo * 5.3.11) by finding ru degree 1 primes Pj coprime to everything, and gj * in k(Pj)^* of order ell such that * log_gj(u_i^((Pj.p - 1) / ell) mod Pj), j = 1..ru * has maximal F_ell rank ru then solve linear system */ static GEN kervirtualunit(struct rnfkummer *kum, GEN vselmer) { GEN bnf = kum->bnfz, cyc = bnf_get_cyc(bnf), nf = bnf_get_nf(bnf); GEN W, B, vy, vz, M, U1, U2, vtau, vell, SUnits = bnf_get_sunits(bnf); long i, j, r, l = lg(vselmer), rc = kum->rc, ru = l-1 - rc, ell = kum->ell; long LIMC = SUnits? itou(gel(SUnits,4)): 1; ulong p; forprime_t T; vtau = cgetg(l, t_VEC); vell = cgetg(l, t_VEC); for (j = 1; j < l; j++) { GEN t = gel(vselmer,j); if (typ(t) == t_MAT) { GEN ct; t = nffactorback(bnf, gel(t,1), ZV_to_Flv(gel(t,2), ell)); t = Q_primitive_part(t, &ct); if (ct) { GEN F = Q_factor(ct); ct = factorback2(gel(F,1), ZV_to_Flv(gel(F,2), ell)); t = (typ(t) == t_INT)? ct: ZC_Z_mul(t, ct); } } gel(vell,j) = t; /* integral, not too far from primitive */ gel(vtau,j) = tauofelt(t, &kum->tau); } U1 = vecslice(vell, 1, ru); /* units */ U2 = vecslice(vell, ru+1, ru+rc); /* cycgen (mod ell-th powers) */ B = nf_get_index(nf); /* bad primes; from 1 to ru are LIMC-units */ for (i = 1; i <= rc; i++) B = mulii(B, nfnorm(nf, gel(U2,i))); if (LIMC > 1) { GEN U, fa = absZ_factor_limit_strict(B, LIMC, &U), P = gel(fa,1); long lP = lg(P); B = U? gel(U,1): gen_1; if (lP > 1 && cmpiu(gel(P,lP-1), LIMC) >= 0) B = mulii(B, gel(P,lP-1)); } if (is_pm1(B)) B = NULL; vy = cgetg(l, t_MAT); for (j = 1; j <= ru; j++) gel(vy,j) = zero_Flv(rc); /* units */ for ( ; j < l; j++) { GEN y, w, u = gel(vtau, j); /* virtual unit */ if (!idealispower(nf, u, ell, &w)) pari_err_BUG("kervirtualunit"); y = isprincipal(bnf, w); setlg(y, rc+1); if (!ZV_equal0(y)) for (i = 1; i <= rc; i++) gel(y,i) = diviiexact(mului(ell,gel(y,i)), gel(cyc,i)); gel(vy,j) = ZV_to_Flv(y, ell); } u_forprime_arith_init(&T, LIMC+1, ULONG_MAX, 1, ell); M = cgetg(ru+1, t_MAT); r = 1; setlg(M,2); vz = cgetg(ru+1, t_MAT); while ((p = u_forprime_next(&T))) if (!B || umodiu(B,p)) { GEN P = idealprimedec_limit_f(nf, utoipos(p), 1); long nP = lg(P)-1; ulong g = rootsof1_Fl(ell, p), q = p / ell; /* (p-1) / ell */ for (i = 1; i <= nP; i++) { GEN modpr = zkmodprinit(nf, gel(P,i)); GEN z, v2; gel(M, r) = nfV_to_logFlv(nf, U1, modpr, g, q, ell, p); /* log futu */ if (Flm_rank(M, ell) < r) continue; /* discard */ v2 = nfV_to_logFlv(nf, U2, modpr, g, q, ell, p); /* log alpha[1..rc] */ gel(vz, r) = z = nfV_to_logFlv(nf, vtau, modpr, g, q, ell, p); for (j = ru+1; j < l; j++) uel(z,j) = Fl_sub(uel(z,j), Flv_dotproduct(v2, gel(vy,j), ell), ell); if (r == ru) break; r++; setlg(M, r+1); } if (i < nP) break; } if (r != ru) pari_err_BUG("kervirtualunit"); /* Solve prod_k U[k]^x[j,k] = vtau[j] / prod_i alpha[i]^vy[j,i] mod (K^*)^ell * for 1 <= j <= #vtau. I.e. for a fixed j: M x[j] = vz[j] (mod ell) */ M = Flm_inv(Flm_transpose(M), ell); vz = Flm_transpose(vz); /* now ru x #vtau */ for (j = 1; j < l; j++) gel(vy,j) = shallowconcat(Flm_Flc_mul(M, gel(vz,j), ell), gel(vy,j)); W = Flm_ker(Flm_Fl_sub(vy, kum->g, ell), ell); l = lg(W); for (j = 1; j < l; j++) gel(W,j) = famat_reduce(famatV_zv_factorback(vselmer, gel(W,j))); settyp(W, t_VEC); return W; } /* - mu_b = sum_{0 <= i < m} floor(r_b r_{m-1-i} / ell) tau^i. * Note that i is in fact restricted to i < m-1 */ static GEN get_mmu(long b, GEN r, long ell) { long i, m = lg(r)-1; GEN M = cgetg(m, t_VECSMALL); for (i = 0; i < m-1; i++) M[i+1] = (r[b + 1] * r[m - i]) / ell; return M; } /* max_b zv_sum(mu_b) < m ell */ static long max_smu(GEN r, long ell) { long i, s = 0, z = vecsmall_max(r), l = lg(r); for (i = 2; i < l; i++) s += (z * r[i]) / ell; return s; } /* coeffs(x, a..b) in variable 0 >= varn(x) */ static GEN split_pol(GEN x, long a, long b) { long i, l = degpol(x); GEN y = x + a, z; if (l < b) b = l; if (a > b || varn(x) != 0) return pol_0(0); l = b-a + 3; z = cgetg(l, t_POL); z[1] = x[1]; for (i = 2; i < l; i++) gel(z,i) = gel(y,i); return normalizepol_lg(z, l); } /* return (ad * z) mod (T^ell - an/ad), assuming deg_T(z) < 2*ell * allow ad to be NULL (= 1) */ static GEN mod_Xell_a(GEN z, long ell, GEN an, GEN ad, GEN T) { GEN z1 = split_pol(z, ell, degpol(z)); GEN z0 = split_pol(z, 0, ell-1); /* z = v^ell z1 + z0*/ if (ad) z0 = ZXX_Z_mul(z0, ad); return gadd(z0, ZXQX_ZXQ_mul(z1, an, T)); } /* D*basistoalg(nfz, c), in variable v. Result is integral */ static GEN to_alg(GEN nfz, GEN c, GEN D) { if (typ(c) != t_COL) return D? mulii(D,c): c; return RgV_dotproduct(nf_get_zkprimpart(nfz), c); } /* assume x in alg form */ static GEN downtoK(toK_s *T, GEN x) { if (typ(x) != t_POL) return x; x = RgM_RgC_mul(T->invexpoteta1, RgX_to_RgC(x, lg(T->invexpoteta1) - 1)); return mkpolmod(RgV_to_RgX(x, varn(T->polnf)), T->polnf); } /* th. 5.3.5. and prop. 5.3.9. */ static GEN compute_polrel(struct rnfkummer *kum, GEN be) { toK_s *T = &kum->T; long i, k, MU = 0, ell = kum->ell, m = T->m; GEN r = Fl_powers(kum->g, m-1, ell); /* r[i+1] = g^i mod ell */ GEN D, S, root, numa, powtau_Ninvbe, Ninvbe, Dinvbe; GEN C, prim_Rk, C_Rk, prim_root, C_root, mell = utoineg(ell); GEN nfz = bnf_get_nf(kum->bnfz), Tz = nf_get_pol(nfz), Dz = nf_get_zkden(nfz); pari_timer ti; if (DEBUGLEVEL>1) { err_printf("Computing Newton sums: "); timer_start(&ti); } if (equali1(Dz)) Dz = NULL; D = Dz; Ninvbe = Q_remove_denom(nfinv(nfz, be), &Dinvbe); powtau_Ninvbe = powtau(Ninvbe, m-1, T->tau); if (Dinvbe) { MU = max_smu(r, ell); D = mul_denom(Dz, powiu(Dinvbe, MU)); } root = cgetg(ell + 2, t_POL); /* compute D*root, will correct at the end */ root[1] = evalsigne(1) | evalvarn(0); gel(root,2) = gen_0; gel(root,3) = D? D: gen_1; for (i = 2; i < ell; i++) gel(root,2+i) = gen_0; for (i = 1; i < m; i++) { /* compute (1/be) ^ (-mu) instead of be^mu [mu < 0]. * 1/be = Ninvbe / Dinvbe */ GEN mmu = get_mmu(i, r, ell), t; t = to_alg(nfz, nffactorback(nfz, powtau_Ninvbe, mmu), Dz);/* Ninvbe^-mu */ if (Dinvbe) { long a = MU - zv_sum(mmu); if (a) t = gmul(t, powiu(Dinvbe, a)); } gel(root, 2 + r[i+1]) = t; /* root += D * (z_ell*T)^{r_i} be^mu_i */ } root = ZXX_renormalize(root, ell+2); /* Other roots are as above with z_ell -> z_ell^j. * Treat all contents (C_*) and principal parts (prim_*) separately */ prim_root = Q_primitive_part(root, &C_root); C_root = div_content(C_root, D); /* theta^ell = be^( sum tau^a r_{d-1-a} ) = a = numa / Dz */ numa = to_alg(nfz, nffactorback(nfz, powtau(be, m, T->tau), vecsmall_reverse(r)), Dz); if (DEBUGLEVEL>1) err_printf("root(%ld) ", timer_delay(&ti)); /* Compute mod (X^ell - t, nfz.pol) */ C_Rk = C_root; prim_Rk = prim_root; C = div_content(C_root, Dz); S = cgetg(ell+3, t_POL); /* Newton sums */ S[1] = evalsigne(1) | evalvarn(0); gel(S,2) = gen_0; for (k = 2; k <= ell; k++) { /* compute the k-th Newton sum; here C_Rk ~ C_root */ pari_sp av = avma; GEN z, C_z, d, Rk = ZXQX_mul(prim_Rk, prim_root, Tz); Rk = mod_Xell_a(Rk, ell, numa, Dz, Tz); /* (mod X^ell - a, nfz.pol) */ prim_Rk = Q_primitive_part(Rk, &d); /* d C_root ~ 1 */ C_Rk = mul_content(C_Rk, mul_content(d, C)); /* root^k = prim_Rk * C_Rk */ z = Q_primitive_part(gel(prim_Rk,2), &C_z); /* C_z ~ 1/C_root ~ 1/C_Rk */ z = downtoK(T, z); C_z = mul_content(mul_content(C_z, C_Rk), mell); z = gmul(z, C_z); /* C_z ~ 1 */ gerepileall(av, C_Rk? 3: 2, &z, &prim_Rk, &C_Rk); if (DEBUGLEVEL>1) err_printf("%ld(%ld) ", k, timer_delay(&ti)); gel(S,k+1) = z; /* - Newton sum */ } gel(S,ell+2) = gen_m1; if (DEBUGLEVEL>1) err_printf("\n"); return RgX_recip(RgXn_expint(S,ell+1)); } 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) ); z = polredbest(a, nf_ORIG); 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); } /* 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); } } /* set kum->vecC, kum->tQ */ static void _rnfkummer_step4(struct rnfkummer *kum, long d, long m) { long i, j, rc = kum->rc; GEN Q, vT, vB, vC, vz, B = cgetg(rc+1,t_VEC), T = cgetg(rc+1,t_MAT); GEN gen = bnf_get_gen(kum->bnfz), cycgenmod = kum->cycgenmod; ulong ell = kum->ell; for (j = 1; j <= rc; j++) { GEN t = tauofideal(gel(gen,j), &kum->tau); isprincipalell(kum->bnfz, t, cycgenmod,ell,rc, &gel(T,j), &gel(B,j)); } Q = Flm_ker(Flm_Fl_sub(Flm_transpose(T), kum->g, ell), ell); kum->tQ = lg(Q) == 1? NULL: Flm_transpose(Q); kum->vecC = vC = cgetg(rc+1, t_VEC); /* T = rc x rc matrix */ vT = Flm_powers(T, m-2, ell); vB = cgetg(m, t_VEC); vz = cgetg(rc+1, t_VEC); for (i = 1; i <= rc; i++) gel(vz, i) = cgetg(m, t_VEC); for (j = 1; j < m; j++) { GEN Tj = Flm_Fl_mul(gel(vT,m-j), Fl_mul(j,d,ell), ell); gel(vB, j) = tauofvec(j == 1? B: gel(vB, j-1), &kum->tau); for (i = 1; i <= rc; i++) gmael(vz, i, j) = gel(Tj, i); } vB = shallowconcat1(vB); for (i = 1; i <= rc; i++) { GEN z = shallowconcat1(gel(vz,i)); gel(vC,i) = famat_reduce(famatV_zv_factorback(vB, z)); } } /* alg 5.3.5 */ static void rnfkummer_init(struct rnfkummer *kum, GEN bnf, GEN P, ulong ell, long prec) { compo_s *COMPO = &kum->COMPO; toK_s *T = &kum->T; GEN nf = bnf_get_nf(bnf), polnf = nf_get_pol(nf), vselmer, bnfz, nfz; long degK, degKz, m, d; ulong g; pari_timer ti; if (DEBUGLEVEL>2) err_printf("Step 1\n"); if (DEBUGLEVEL) timer_start(&ti); compositum_red(COMPO, polnf, polcyclo(ell, varn(polnf))); if (DEBUGLEVEL) { timer_printf(&ti, "[rnfkummer] compositum"); if (DEBUGLEVEL>1) err_printf("polred(compositum) = %Ps\n",COMPO->R); } if (DEBUGLEVEL>2) err_printf("Step 2\n"); degK = degpol(polnf); degKz = degpol(COMPO->R); m = degKz / degK; /* > 1 */ d = (ell-1) / m; g = Fl_powu(pgener_Fl(ell), d, ell); if (Fl_powu(g, m, ell*ell) == 1) g += ell; /* ord(g) = m in all (Z/ell^k)^* */ if (DEBUGLEVEL>2) err_printf("Step 3\n"); nfz = nfinit(mkvec2(COMPO->R, P), prec); if (lg(nfcertify(nfz)) > 1) nfz = nfinit(COMPO->R, prec); /* paranoia */ kum->bnfz = bnfz = Buchall(nfz, nf_FORCE, prec); if (DEBUGLEVEL) timer_printf(&ti, "[rnfkummer] bnfinit(Kz)"); kum->cycgenmod = bnf_cycgenmod(bnfz, ell, &vselmer, &kum->rc); kum->ell = ell; kum->g = g; kum->mgi = Fl_div(m, g, ell); get_tau(kum); if (DEBUGLEVEL>2) err_printf("Step 4\n"); if (kum->rc) _rnfkummer_step4(kum, d, m); else { kum->vecC = cgetg(1, t_VEC); kum->tQ = NULL; } if (DEBUGLEVEL>2) err_printf("Step 5\n"); kum->vecW = kervirtualunit(kum, vselmer); if (DEBUGLEVEL>2) err_printf("Step 8\n"); /* left inverse */ T->invexpoteta1 = QM_inv(RgXQ_matrix_pow(COMPO->p, degKz, degK, COMPO->R)); T->polnf = polnf; T->tau = &kum->tau; T->m = m; T->powg = Fl_powers(g, m, ell); } static GEN rnfkummer_ell(struct rnfkummer *kum, GEN bnr, GEN H) { ulong ell = kum->ell; GEN bnfz = kum->bnfz, nfz = bnf_get_nf(bnfz), gell = utoipos(ell); GEN vecC = kum->vecC, vecW = kum->vecW, cycgenmod = kum->cycgenmod; long lW = lg(vecW), rc = kum->rc, j, lSp; toK_s *T = &kum->T; GEN K, be, P, faFz, vsprk, Sp, vecAp, vecBp, matP, vecWA, vecWB, M, lambdaWB; /* primes landing in H must be totally split */ GEN Lpr = get_prlist(bnr, H, gell, &faFz, kum); if (DEBUGLEVEL>2) err_printf("Step 9, 10 and 11\n"); list_Hecke(&Sp, &vsprk, nfz, faFz, gell, T->tau); if (DEBUGLEVEL>2) err_printf("Step 12\n"); lSp = lg(Sp); vecAp = cgetg(lSp, t_VEC); vecBp = cgetg(lSp, t_VEC); matP = cgetg(lSp, t_MAT); for (j = 1; j < lSp; j++) { GEN e, a; isprincipalell(bnfz, gel(Sp,j), cycgenmod,ell,rc, &e, &a); gel(matP,j) = e; gel(vecBp,j) = famat_mul_shallow(famatV_zv_factorback(vecC, zv_neg(e)), a); gel(vecAp,j) = lambdaofelt(gel(vecBp,j), T); } if (DEBUGLEVEL>2) err_printf("Step 13\n"); vecWA = shallowconcat(vecW, vecAp); vecWB = shallowconcat(vecW, vecBp); if (DEBUGLEVEL>2) err_printf("Step 14, 15 and 17\n"); M = matlogall(nfz, vecWA, lW, kum->mgi, gell, vsprk); if (kum->tQ) { GEN QtP = Flm_mul(kum->tQ, matP, ell); M = vconcat(M, shallowconcat(zero_Flm(lgcols(kum->tQ)-1,lW-1), QtP)); } lambdaWB = shallowconcat(lambdaofvec(vecW, T), vecAp);/*vecWB^lambda*/ M = vconcat(M, subgroup_info(bnfz, Lpr, gell, lambdaWB)); if (DEBUGLEVEL>2) err_printf("Step 16\n"); K = Flm_ker(M, ell); if (DEBUGLEVEL>2) err_printf("Step 18\n"); be = compute_beta(gel(K,1), vecWB, gell, kum->bnfz); P = compute_polrel(kum, be); nfX_Z_normalize(bnr_get_nf(bnr), P); if (DEBUGLEVEL>1) err_printf("polrel(beta) = %Ps\n", P); return P; } static void bnrclassfield_sanitize(GEN *pbnr, GEN *pH) { GEN T; bnr_subgroup_sanitize(pbnr, pH); T = nf_get_pol(bnr_get_nf(*pbnr)); if (!varn(T)) pari_err_PRIORITY("bnrclassfield", T, "=", 0); } static GEN _rnfkummer(GEN bnr, GEN H, long prec) { ulong ell; GEN gell, bnf, nf, P; struct rnfkummer kum; bnrclassfield_sanitize(&bnr, &H); gell = H? ZM_det(H): ZV_prod(bnr_get_cyc(bnr)); ell = itou(gell); if (ell == 1) return pol_x(0); if (!uisprime(ell)) pari_err_IMPL("rnfkummer for composite relative degree"); if (bnf_get_tuN(bnr_get_bnf(bnr)) % ell == 0) return rnfkummersimple(bnr, H, ell); bnf = bnr_get_bnf(bnr); nf = bnf_get_nf(bnf); P = ZV_union_shallow(nf_get_ramified_primes(nf), mkvec(gell)); rnfkummer_init(&kum, bnf, P, ell, maxss(prec,BIGDEFAULTPREC)); return rnfkummer_ell(&kum, bnr, H); } GEN rnfkummer(GEN bnr, GEN H, long prec) { pari_sp av = avma; return gerepilecopy(av, _rnfkummer(bnr, H, prec)); } /*******************************************************************/ /* bnrclassfield */ /*******************************************************************/ /* TODO: could be exported */ static void gsetvarn(GEN x, long v) { long i; switch(typ(x)) { case t_POL: case t_SER: setvarn(x, v); return; case t_LIST: x = list_data(x); if (!x) return; /* fall through t_VEC */ case t_VEC: case t_COL: case t_MAT: for (i = lg(x)-1; i > 0; i--) gsetvarn(gel(x,i), v); } } /* emb root of pol as polmod modulo pol2, return relative polynomial */ static GEN relative_pol(GEN pol, GEN emb, GEN pol2) { GEN eqn, polrel; if (degree(pol)==1) return pol2; eqn = gsub(liftpol_shallow(emb), pol_x(varn(pol))); eqn = Q_remove_denom(eqn, NULL); polrel = nfgcd(pol2, eqn, pol, NULL); return RgX_Rg_div(polrel, leading_coeff(polrel)); } /* pol defines K/nf */ static GEN bnrclassfield_tower(GEN bnr, GEN subgroup, GEN TB, GEN p, long finaldeg, long absolute, long prec) { pari_sp av = avma; GEN nf, nf2, rnf, bnf, bnf2, bnr2, q, H, dec, cyc, pk, sgpk, pol2, emb, emb2, famod, fa, Lbad; long i, r1, ell, sp, spk, last; forprime_t iter; bnf = bnr_get_bnf(bnr); nf = bnf_get_nf(bnf); rnf = rnfinit0(nf, TB, 1); nf2 = rnf_build_nfabs(rnf, prec); gsetvarn(nf2, varn(nf_get_pol(nf))); if (lg(nfcertify(nf2)) > 1) { rnf = rnfinit0(nf, gel(TB,1), 1); nf2 = rnf_build_nfabs(rnf, prec); gsetvarn(nf2, varn(nf_get_pol(nf))); } r1 = nf_get_r1(nf2); bnf2 = Buchall(nf2, nf_FORCE, prec); sp = itos(p); spk = sp * rnf_get_degree(rnf); pk = stoi(spk); sgpk = hnfmodid(subgroup,pk); last = spk==finaldeg; /* compute conductor */ famod = gel(bid_get_fact2(bnr_get_bid(bnr)),1); if (lg(famod)==1) { fa = trivial_fact(); Lbad = cgetg(1, t_VECSMALL); } else { long j=1; fa = cgetg(3, t_MAT); gel(fa,1) = cgetg(lg(famod), t_VEC); Lbad = cgetg(lg(famod), t_VEC); for(i=1; i lg(cyc)+3) { H = Flm_image(H, sp); if (lg(cyc)-lg(H) == 1) break; } } H = hnfmodid(shallowconcat(zm_to_ZM(H), diagonal_shallow(cyc)), p); /* polynomial over nf2 */ pol2 = _rnfkummer(bnr2, H, prec); /* absolute polynomial */ pol2 = rnfequation2(nf2, pol2); emb2 = gel(pol2,2); /* generator of nf2 as polmod modulo pol2 */ pol2 = gel(pol2,1); /* polynomial over nf */ if (!absolute || !last) { emb = rnf_get_alpha(rnf); /* generator of nf as polynomial in nf2 */ emb = poleval(emb, emb2); /* generator of nf as polmod modulo pol2 */ pol2 = relative_pol(nf_get_pol(nf), emb, pol2); } if (!last) pol2 = rnfpolredbest(nf, pol2, 0); obj_free(rnf); pol2 = gerepilecopy(av, pol2); if (last) return pol2; TB = mkvec2(pol2, gel(TB,2)); return bnrclassfield_tower(bnr, subgroup, TB, p, finaldeg, absolute, prec); } /* subgroups H_i of bnr s.t. bnr/H_i is cyclic and inter_i H_i = subgroup */ static GEN cyclic_compos(GEN subgroup) { pari_sp av = avma; GEN Ui, L, pe, D = ZM_snf_group(subgroup, NULL, &Ui); long i, l = lg(D); L = cgetg(l, t_VEC); if (l == 1) return L; pe = gel(D,1); for (i = 1; i < l; i++) gel(L,i) = hnfmodid(shallowconcat(subgroup, vecsplice(Ui,i)),pe); return gerepilecopy(av, L); } /* p prime; set pkum=NULL if p-th root of unity in base field * absolute=1 allowed if extension is cyclic with exponent>1 */ static GEN bnrclassfield_primepower(struct rnfkummer *pkum, GEN bnr, GEN subgroup, GEN p, GEN P, long absolute, long prec) { GEN res, subs = cyclic_compos(subgroup); long i, l = lg(subs); res = cgetg(l,t_VEC); for (i = 1; i < l; i++) { GEN H = gel(subs,i), cnd = bnrconductormod(bnr, hnfmodid(H,p), p); GEN pol, pe, bnr2 = gel(cnd,2), Hp = gel(cnd,3); if (pkum) pol = rnfkummer_ell(pkum, bnr2, Hp); else pol = rnfkummersimple(bnr2, Hp, itos(p)); pe = ZM_det_triangular(H); if (!equalii(p,pe)) pol = bnrclassfield_tower(bnr, H, mkvec2(pol,P), p, itos(pe), absolute, prec); gel(res,i) = pol; } return res; } /* partition of v into two subsets whose products are as balanced as possible */ /* assume v sorted */ static GEN vecsmall_balance(GEN v) { forvec_t T; GEN xbounds, x, vuniq, mult, ind, prod, prodbest = gen_0, bound, xbest = NULL, res1, res2; long i=1, j, k1, k2; if (lg(v) == 3) return mkvec2(mkvecsmall(1), mkvecsmall(2)); vuniq = cgetg(lg(v), t_VECSMALL); mult = cgetg(lg(v), t_VECSMALL); ind = cgetg(lg(v), t_VECSMALL); vuniq[1] = v[1]; mult[1] = 1; ind[1] = 1; for (j=2; j0) { prodbest = prod; xbest = gcopy(x); } } res1 = cgetg(lg(v), t_VECSMALL); res2 = cgetg(lg(v), t_VECSMALL); for (i=1,k1=1,k2=1; i 1 */ res = cgetg(lPN, t_VEC); for (i = 1; i < lPN; i++) { GEN p = gel(PN,i), H = hnfmodid(H0, powii(p, gel(EN,i))); long sp = itos(p); if (absolute) absolute = FpM_rank(H,p)==lg(H)-2; /* cyclic */ gel(res,i) = bnrclassfield_primepower(vkum[sp], bnr, H, p, bad, absolute, prec); } res = liftpol_shallow(shallowconcat1(res)); res = gen_sort_shallow(res, (void*)cmp_RgX, gen_cmp_RgX); if (flag) { GEN nf = bnr_get_nf(bnr); res = nfcompositumall(nf, res); if (flag==2 && !absolute) res = rnfequation(nf, res); } return res; } /* for a vector of subgroups */ static GEN bnrclassfieldvec(GEN bnr, GEN v, long flag, long prec) { long j, lv = lg(v); GEN vH, vfa, vP, P, w = cgetg(lv, t_VEC); struct rnfkummer **vkum = NULL; if (lv == 1) return w; vH = cgetg(lv, t_VEC); vP = cgetg(lv, t_VEC); vfa = cgetg(lv, t_VEC); for (j = 1; j < lv; j++) { GEN N, fa, H = bnr_subgroup_check(bnr, gel(v,j), &N); if (is_bigint(N)) pari_err_OVERFLOW("bnrclassfield [too large degree]"); if (!H) H = diagonal_shallow(bnr_get_cyc(bnr)); gel(vH,j) = H; gel(vfa,j) = fa = Z_factor(N); gel(vP,j) = ZV_to_zv(gel(fa, 1)); } vP = shallowconcat1(vP); vecsmall_sort(vP); vP = vecsmall_uniq_sorted(vP); P = disc_primes(bnr); if (lg(vP) > 1) vkum = rnfkummer_initall(bnr, vP, P, prec); for (j = 1; j < lv; j++) gel(w,j) = bnrclassfield_H(vkum, bnr, P, gel(vH,j), gel(vfa,j), flag, prec); return w; } /* flag: * 0 t_VEC of polynomials whose compositum is the extension * 1 single polynomial * 2 single absolute polynomial */ GEN bnrclassfield(GEN bnr, GEN subgroup, long flag, long prec) { pari_sp av = avma; GEN N, fa, P; struct rnfkummer **vkum; if (flag<0 || flag>2) pari_err_FLAG("bnrclassfield [must be 0,1 or 2]"); if (subgroup && typ(subgroup) == t_VEC) { if (nftyp(bnr)==typ_BNF) bnr = Buchray(bnr, gen_1, nf_INIT); else checkbnr(bnr); if (!char_check(bnr_get_cyc(bnr), subgroup)) return gerepilecopy(av, bnrclassfieldvec(bnr, subgroup, flag, prec)); } bnrclassfield_sanitize(&bnr, &subgroup); N = ZM_det_triangular(subgroup); if (equali1(N)) switch(flag) { case 0: set_avma(av); retmkvec(pol_x(0)); case 1: set_avma(av); return pol_x(0); default: /* 2 */ P = shallowcopy(nf_get_pol(bnr_get_nf(bnr))); setvarn(P,0); return gerepilecopy(av,P); } if (is_bigint(N)) pari_err_OVERFLOW("bnrclassfield [too large degree]"); fa = Z_factor(N); P = disc_primes(bnr); vkum = rnfkummer_initall(bnr, ZV_to_zv(gel(fa,1)), P, prec); return gerepilecopy(av, bnrclassfield_H(vkum, bnr, P, subgroup, fa, flag, prec)); } pari-2.17.2/src/basemath/matperm.c0000644000175000017500000001015014567450071015356 0ustar billbill/* Copyright (C) 2016 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /********************************************************************/ /** **/ /** MATRIX PERMANENT, via RYSER'S FORMULA **/ /** (initial implementation: C. Greathouse) **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" /* Ryser's formula */ GEN matpermanent(GEN M) { pari_sp av; long n = lg(M)-1, i, x, upper; GEN p, in; if (typ(M) != t_MAT) pari_err_TYPE("matpermanent", M); if (!n) return gen_1; if (n != nbrows(M)) pari_err_DIM("matpermanent"); #ifdef LONG_IS_64BIT /* because of vals(long x) => x <= LONG_MAX */ if (n > 63) pari_err_IMPL("large matrix permanent"); #else if (n > 31) pari_err_IMPL("large matrix permanent"); #endif if (n == 1) return gcopy(gcoeff(M,1,1)); av = avma; if (RgM_is_QM(M)) { GEN cM; M = Q_primitive_part(M, &cM); p = ZM_permanent(M); if (cM) p = gerepileupto(av, gmul(p, gpowgs(cM,n))); return p; } p = gen_0; in = zerovec(n); upper = 1L << n; for (x = 1; x < upper; x++) { long gray = x ^ (x>>1), k = vals(x); GEN col = gel(M,k+1); if (gray & (1L<>1), k = vals(x); GEN c, col = gel(M, k+1); if (gray & (1L<>1); long i, k = vals(x); GEN c, col = gel(M, k+1); if (gray & (1UL<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; i 1) /* do not compare variables, V[1] */ if (V[l] != W[l]) return 0; return 1; } GEN random_Flx(long d1, long vs, ulong p) { long i, d = d1+2; GEN y = cgetg(d,t_VECSMALL); y[1] = vs; for (i=2; ilx) swapspec(x,y, lx,ly); lz = lx+2; z = cgetg(lz, t_VECSMALL); for (i=0; ilx) swapspec(x,y, lx,ly); lz = lx; z = cgetg(lz, t_VECSMALL); z[1]=x[1]; for (i=2; i=0 and a\x^(-n) if n<0 */ GEN Flx_shift(GEN a, long n) { long i, l = lg(a); GEN b; if (l==2 || !n) return Flx_copy(a); if (l+n<=2) return pol0_Flx(a[1]); b = cgetg(l+n, t_VECSMALL); b[1] = a[1]; if (n < 0) for (i=2-n; i 0, shallow if x == 0*/ static GEN Flx_addshift(GEN x, GEN y, ulong p, long d) { GEN xd,yd,zd = (GEN)avma; long a,lz,ny = lgpol(y), nx = lgpol(x); long vs = x[1]; if (nx == 0) return y; x += 2; y += 2; a = ny-d; if (a <= 0) { lz = (a>nx)? ny+2: nx+d+2; (void)new_chunk(lz); xd = x+nx; yd = y+ny; while (xd > x) *--zd = *--xd; x = zd + a; while (zd > x) *--zd = 0; } else { xd = new_chunk(d); yd = y+d; x = Flx_addspec(x,yd,p, nx,a); lz = (a>nx)? ny+2: lg(x)+d; x += 2; while (xd > x) *--zd = *--xd; } while (yd > y) *--zd = *--yd; *--zd = vs; *--zd = evaltyp(t_VECSMALL) | evallg(lz); return zd; } /* shift polynomial + gerepile */ /* Do not set evalvarn*/ static GEN Flx_shiftip(pari_sp av, GEN x, long v) { long i, lx = lg(x), ly; GEN y; if (!v || lx==2) return gerepileuptoleaf(av, x); ly = lx + v; /* result length */ (void)new_chunk(ly); /* check that result fits */ x += lx; y = (GEN)av; for (i = 2; i> 1) #define QUARTMASK ((1UL<> BITS_IN_QUARTULONG) & QUARTMASK) #define LHQUARTWORD(x) (((x) >> (2*BITS_IN_QUARTULONG)) & QUARTMASK) #define HHQUARTWORD(x) (((x) >> (3*BITS_IN_QUARTULONG)) & QUARTMASK) INLINE long maxbitcoeffpol(ulong p, long n) { GEN z = muliu(sqru(p - 1), n); long b = expi(z) + 1; /* only do expensive bit-packing if it saves at least 1 limb */ if (b <= BITS_IN_QUARTULONG) { if (nbits2nlong(n*b) == (n + 3)>>2) b = BITS_IN_QUARTULONG; } else if (b <= BITS_IN_HALFULONG) { if (nbits2nlong(n*b) == (n + 1)>>1) b = BITS_IN_HALFULONG; } else { long l = lgefint(z) - 2; if (nbits2nlong(n*b) == n*l) b = l*BITS_IN_LONG; } return b; } INLINE ulong Flx_mullimb_ok(GEN x, GEN y, ulong p, long a, long b) { /* Assume OK_ULONG*/ ulong p1 = 0; long i; for (i=a; i= ny > 0 */ static GEN Flx_mulspec_basecase(GEN x, GEN y, ulong p, ulong pi, 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 (!pi) { for (i=0; i>1UL; GEN V = cgetipos(2+n); GEN w; for (w = int_LSW(V), j=0; j+1>2UL; GEN V = cgetipos(2+n); GEN w; for (w = int_LSW(V), j=0; j+3= get_Fl_threshold(p, Flx_MUL_MULII_LIMIT, Flx_MUL2_MULII_LIMIT)) { long m = maxbitcoeffpol(p,nb); switch (m) { case BITS_IN_QUARTULONG: return Flx_shiftip(av,Flx_mulspec_quartmulii(a,b,p,na,nb), v); case BITS_IN_HALFULONG: return Flx_shiftip(av,Flx_mulspec_halfmulii(a,b,p,na,nb), v); case BITS_IN_LONG: return Flx_shiftip(av,Flx_mulspec_mulii(a,b,p,na,nb), v); case 2*BITS_IN_LONG: return Flx_shiftip(av,Flx_mulspec_mulii_inflate(a,b,2,p,na,nb), v); case 3*BITS_IN_LONG: return Flx_shiftip(av,Flx_mulspec_mulii_inflate(a,b,3,p,na,nb), v); default: return Flx_shiftip(av,Flx_mulspec_Kronecker(a,b,m,p,na,nb), v); } } if (nb < get_Fl_threshold(p, Flx_MUL_KARATSUBA_LIMIT, Flx_MUL2_KARATSUBA_LIMIT)) return Flx_shiftip(av,Flx_mulspec_basecase(a,b,p,pi,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,pi,n0a,n0b); c0 = Flx_mulspec(a0,b0,p,pi,na,nb); c2 = Flx_addspec(a0,a,p,na,n0a); c1 = Flx_addspec(b0,b,p,nb,n0b); c1 = Flx_mul_pre(c1,c2,p,pi); 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,pi,n0a,nb); c0 = Flx_mulspec(a0,b,p,pi,na,nb); } c0 = Flx_addshift(c0,c,p,n0); return Flx_shiftip(av,c0, v); } GEN Flx_mul_pre(GEN x, GEN y, ulong p, ulong pi) { GEN z = Flx_mulspec(x+2,y+2,p, pi, lgpol(x),lgpol(y)); z[1] = x[1]; return z; } GEN Flx_mul(GEN x, GEN y, ulong p) { return Flx_mul_pre(x, y, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } static GEN Flx_sqrspec_basecase(GEN x, ulong p, ulong pi, 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 (!pi) { 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_pre(x[0], p, pi); for (i=1; i>1); p1 = Fl_add(p1, p1, p); if ((i&1) == 0) p1 = Fl_add(p1, Fl_sqr_pre(x[i>>1], p, pi), p); z[i] = p1; } for ( ; i>1); p1 = Fl_add(p1, p1, p); if ((i&1) == 0) p1 = Fl_add(p1, Fl_sqr_pre(x[i>>1], p, pi), 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_quartsqri(GEN a, ulong p, long na) { GEN z = sqri(Flx_to_int_quartspec(a,na)); return int_to_Flx_quart(z,p); } static GEN Flx_sqrspec_sqri_inflate(GEN x, long N, ulong p, long nx) { pari_sp av = avma; GEN z = sqri(Flx_eval2BILspec(x,N,nx)); return gerepileupto(av, Z_mod2BIL_Flx(z, N, (nx-1)*2, p)); } static GEN Flx_sqrspec(GEN a, ulong p, ulong pi, long na) { GEN a0, c, c0; long n0, n0a, i, v = 0, m; pari_sp av; while (na && !a[0]) { a++; na--; v += 2; } if (!na) return pol0_Flx(0); av = avma; if (na >= get_Fl_threshold(p, Flx_SQR_SQRI_LIMIT, Flx_SQR2_SQRI_LIMIT)) { m = maxbitcoeffpol(p,na); switch(m) { case BITS_IN_QUARTULONG: return Flx_shiftip(av, Flx_sqrspec_quartsqri(a,p,na), v); case BITS_IN_HALFULONG: return Flx_shiftip(av, Flx_sqrspec_halfsqri(a,p,na), v); case BITS_IN_LONG: return Flx_shiftip(av, Flx_sqrspec_sqri(a,p,na), v); case 2*BITS_IN_LONG: return Flx_shiftip(av, Flx_sqrspec_sqri_inflate(a,2,p,na), v); case 3*BITS_IN_LONG: return Flx_shiftip(av, Flx_sqrspec_sqri_inflate(a,3,p,na), v); default: return Flx_shiftip(av, Flx_sqrspec_Kronecker(a,m,p,na), v); } } if (na < get_Fl_threshold(p, Flx_SQR_KARATSUBA_LIMIT, Flx_SQR2_KARATSUBA_LIMIT)) return Flx_shiftip(av, Flx_sqrspec_basecase(a,p,pi,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,pi,n0a); c0= Flx_sqrspec(a0,p,pi,na); if (p == 2) n0 *= 2; else { GEN c1, t = Flx_addspec(a0,a,p,na,n0a); t = Flx_sqr_pre(t,p,pi); 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_pre(GEN x, ulong p, ulong pi) { GEN z = Flx_sqrspec(x+2,p, pi, lgpol(x)); z[1] = x[1]; return z; } GEN Flx_sqr(GEN x, ulong p) { return Flx_sqr_pre(x, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } GEN Flx_powu_pre(GEN x, ulong n, ulong p, ulong pi) { GEN y = pol1_Flx(x[1]), z; ulong m; if (n == 0) return y; m = n; z = x; for (;;) { if (m&1UL) y = Flx_mul_pre(y,z, p, pi); m >>= 1; if (!m) return y; z = Flx_sqr_pre(z, p, pi); } } GEN Flx_powu(GEN x, ulong n, ulong p) { if (n == 0) return pol1_Flx(x[1]); return Flx_powu_pre(x, n, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } GEN Flx_halve(GEN y, ulong p) { GEN z; long i, l; z = cgetg_copy(y, &l); z[1] = y[1]; for(i=2; i=2; i--) { Q[i] = Fl_mul(P[i], hi, p); if (i == 2) break; hi = Fl_mul(hi,h, p); } Q[1] = P[1]; return Q; } /* x/polrecip(P)+O(x^n); allow pi = 0 */ static GEN Flx_invBarrett_basecase(GEN T, ulong p, ulong pi) { long i, l=lg(T)-1, lr=l-1, k; GEN r=cgetg(lr,t_VECSMALL); r[1] = T[1]; r[2] = 1; if (!pi) for (i=3;i=0; i--) if (x[i]) break; return i+1; } /* allow pi = 0 */ static GEN Flx_invBarrett_Newton(GEN T, ulong p, ulong pi) { long nold, lx, lz, lq, l = degpol(T), lQ; GEN q, y, z, x = zero_zv(l+1) + 2; ulong mask = quadratic_prec_mask(l-2); /* assume l > 2 */ pari_sp av; y = T+2; q = Flx_recipspec(y,l+1,l+1); lQ = lgpol(q); q+=2; av = avma; /* We work on _spec_ Flx's, all the l[xzq12] below are lgpol's */ /* initialize */ x[0] = Fl_inv(q[0], p); if (lQ>1 && q[1]) { ulong u = q[1]; if (x[0] != 1) u = Fl_mul(u, Fl_sqr(x[0],p), p); x[1] = p - u; lx = 2; } else lx = 1; nold = 1; for (; mask > 1; set_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, pi, 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, pi, 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; } /* allow pi = 0 */ static GEN Flx_invBarrett_pre(GEN T, ulong p, ulong pi) { pari_sp ltop = avma; long l = lgpol(T); GEN r; if (l < 3) return pol0_Flx(T[1]); if (l < get_Fl_threshold(p, Flx_INVBARRETT_LIMIT, Flx_INVBARRETT2_LIMIT)) { ulong c = T[l+1]; if (c != 1) { ulong ci = Fl_inv(c,p); T = Flx_Fl_mul_pre(T, ci, p, pi); r = Flx_invBarrett_basecase(T, p, pi); r = Flx_Fl_mul_pre(r, ci, p, pi); } else r = Flx_invBarrett_basecase(T, p, pi); } else r = Flx_invBarrett_Newton(T, p, pi); return gerepileuptoleaf(ltop, r); } GEN Flx_invBarrett(GEN T, ulong p) { return Flx_invBarrett_pre(T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } /* allow pi = 0 */ GEN Flx_get_red_pre(GEN T, ulong p, ulong pi) { if (typ(T)!=t_VECSMALL || lgpol(T) < get_Fl_threshold(p, Flx_BARRETT_LIMIT, Flx_BARRETT2_LIMIT)) return T; retmkvec2(Flx_invBarrett_pre(T, p, pi),T); } GEN Flx_get_red(GEN T, ulong p) { if (typ(T)!=t_VECSMALL || lgpol(T) < get_Fl_threshold(p, Flx_BARRETT_LIMIT, Flx_BARRETT2_LIMIT)) return T; retmkvec2(Flx_invBarrett_pre(T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)),T); } /* separate from Flx_divrem for maximal speed. */ static GEN Flx_rem_basecase(GEN x, GEN y, ulong p, ulong pi) { pari_sp av; GEN z, c; long dx,dy,dy1,dz,i,j; ulong p1,inv; long vs=x[1]; dy = degpol(y); if (!dy) return pol0_Flx(x[1]); dx = degpol(x); dz = dx-dy; if (dz < 0) return Flx_copy(x); x += 2; y += 2; inv = y[dy]; if (inv != 1UL) inv = Fl_inv(inv,p); for (dy1=dy-1; dy1>=0 && !y[dy1]; dy1--); 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 (!pi) { 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-dy1; 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-dy1; j<=i && j<=dz; j++) p1 = Fl_addmul_pre(p1, z[j], y[i - j], p, pi); z[i-dy] = p1? Fl_mul_pre(p - p1, inv, p, pi): 0; } for (i=0; i=0 && !c[i]) i--; set_avma(av); return Flx_renormalize(c-2, i+3); } /* as FpX_divrem but working only on ulong types. * if relevant, *pr is the last object on stack */ static GEN Flx_divrem_basecase(GEN x, GEN y, ulong p, ulong pi, GEN *pr) { GEN z,q,c; long dx,dy,dy1,dz,i,j; ulong p1,inv; long sv=x[1]; dy = degpol(y); if (dy<0) pari_err_INV("Flx_divrem",y); if (pr == ONLY_REM) return Flx_rem_basecase(x, y, p, pi); if (!dy) { if (pr && pr != ONLY_DIVIDES) *pr = pol0_Flx(sv); if (y[2] == 1UL) return Flx_copy(x); return Flx_Fl_mul_pre(x, Fl_inv(y[2], p), p, pi); } dx = degpol(x); dz = dx-dy; if (dz < 0) { q = pol0_Flx(sv); if (pr && pr != ONLY_DIVIDES) *pr = Flx_copy(x); return q; } x += 2; y += 2; z = cgetg(dz + 3, t_VECSMALL); z[1] = sv; z += 2; inv = uel(y, dy); if (inv != 1UL) inv = Fl_inv(inv,p); for (dy1=dy-1; dy1>=0 && !y[dy1]; dy1--); 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-dy1; 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 - uel(x,i); for (j=i-dy1; j<=i && j<=dz; j++) p1 = Fl_add(p1, Fl_mul(z[j],y[i-j],p), p); z[i-dy] = p1? Fl_mul(p - p1, inv, p): 0; } } q = Flx_renormalize(z-2, dz+3); if (!pr) return q; c = cgetg(dy + 3, t_VECSMALL); c[1] = sv; c += 2; if (SMALL_ULONG(p)) { for (i=0; i=0 && !c[i]) i--; c = Flx_renormalize(c-2, i+3); if (pr == ONLY_DIVIDES) { if (lg(c) != 2) return NULL; } else *pr = c; return q; } /* Compute x mod T where 2 <= degpol(T) <= l+1 <= 2*(degpol(T)-1) * and mg is the Barrett inverse of T. */ static GEN Flx_divrem_Barrettspec(GEN x, long l, GEN mg, GEN T, ulong p, ulong pi, GEN *pr) { GEN q, r; long lt = degpol(T); /*We discard the leading term*/ long ld, lm, lT, lmg; ld = l-lt; lm = minss(ld, lgpol(mg)); lT = Flx_lgrenormalizespec(T+2,lt); lmg = Flx_lgrenormalizespec(mg+2,lm); q = Flx_recipspec(x+lt,ld,ld); /* q = rec(x) lz<=ld*/ q = Flx_mulspec(q+2,mg+2,p,pi,lgpol(q),lmg); /* q = rec(x) * mg lz<=ld+lm*/ q = Flx_recipspec(q+2,minss(ld,lgpol(q)),ld);/* q = rec (rec(x) * mg) lz<=ld*/ if (!pr) return q; r = Flx_mulspec(q+2,T+2,p,pi,lgpol(q),lT); /* r = q*pol lz<=ld+lt*/ r = Flx_subspec(x,r+2,p,lt,minss(lt,lgpol(r)));/* r = x - q*pol lz<=lt */ if (pr == ONLY_REM) return r; *pr = r; return q; } static GEN Flx_divrem_Barrett(GEN x, GEN mg, GEN T, ulong p, ulong pi, GEN *pr) { GEN q = NULL, r = Flx_copy(x); long l = lgpol(x), lt = degpol(T), lm = 2*lt-1, v = T[1]; long i; if (l <= lt) { if (pr == ONLY_REM) return Flx_copy(x); if (pr == ONLY_DIVIDES) return lgpol(x)? NULL: pol0_Flx(v); if (pr) *pr = Flx_copy(x); return pol0_Flx(v); } if (lt <= 1) return Flx_divrem_basecase(x,T,p,pi,pr); if (pr != ONLY_REM && l>lm) { q = zero_zv(l-lt+1); q[1] = T[1]; } while (l>lm) { GEN zr, zq = Flx_divrem_Barrettspec(r+2+l-lm,lm,mg,T,p,pi,&zr); long lz = lgpol(zr); if (pr != ONLY_REM) { long lq = lgpol(zq); for(i=0; i lt) r = Flx_divrem_Barrettspec(r+2,l,mg,T,p,pi,ONLY_REM); else r = Flx_renormalize(r, l+2); r[1] = v; return r; } if (l > lt) { GEN zq = Flx_divrem_Barrettspec(r+2,l,mg,T,p,pi, pr ? &r: NULL); if (!q) q = zq; else { long lq = lgpol(zq); for(i=0; ip = p; D->pi = pi; D->T = Flx_get_red_pre(T, p, pi); } static void set_Flxq(struct _Flxq *D, GEN T, ulong p) { set_Flxq_pre(D, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } static GEN _Flx_divrem(void * E, GEN x, GEN y, GEN *r) { struct _Flxq *D = (struct _Flxq*) E; return Flx_divrem_pre(x, y, D->p, D->pi, r); } static GEN _Flx_add(void * E, GEN x, GEN y) { struct _Flxq *D = (struct _Flxq*) E; return Flx_add(x, y, D->p); } static GEN _Flx_mul(void *E, GEN x, GEN y) { struct _Flxq *D = (struct _Flxq*) E; return Flx_mul_pre(x, y, D->p, D->pi); } static GEN _Flx_sqr(void *E, GEN x) { struct _Flxq *D = (struct _Flxq*) E; return Flx_sqr_pre(x, D->p, D->pi); } static struct bb_ring Flx_ring = { _Flx_add,_Flx_mul,_Flx_sqr }; GEN Flx_digits(GEN x, GEN T, ulong p) { struct _Flxq D; long d = degpol(T), n = (lgpol(x)+d-1)/d; D.p = p; D.pi = SMALL_ULONG(p)? 0: get_Fl_red(p); return gen_digits(x,T,n,(void *)&D, &Flx_ring, _Flx_divrem); } GEN FlxV_Flx_fromdigits(GEN x, GEN T, ulong p) { struct _Flxq D; D.p = p; D.pi = SMALL_ULONG(p)? 0: get_Fl_red(p); return gen_fromdigits(x,T,(void *)&D, &Flx_ring); } long Flx_val(GEN x) { long i, l=lg(x); if (l==2) return LONG_MAX; for (i=2; i= 0) { if (res->lc != 1) { if (pi) { res->lc = Fl_powu_pre(res->lc, da - dr, p, pi); res->res = Fl_mul_pre(res->res, res->lc, p, pi); } else { res->lc = Fl_powu(res->lc, da - dr, p); res->res = Fl_mul(res->res, res->lc, p); } } if (both_odd(da + res->off, db + res->off)) res->res = Fl_neg(res->res, p); } else { if (db == 0) { if (res->lc != 1) { if (pi) { res->lc = Fl_powu_pre(res->lc, da, p, pi); res->res = Fl_mul_pre(res->res, res->lc, p, pi); } else { res->lc = Fl_powu(res->lc, da, p); res->res = Fl_mul(res->res, res->lc, p); } } } else res->res = 0; } } static GEN Flx_halfres_basecase(GEN a, GEN b, ulong p, ulong pi, GEN *pa, GEN *pb, struct Flx_res *res) { pari_sp av = avma; GEN u, u1, v, v1, M; long vx = a[1], n = lgpol(a)>>1; u1 = v = pol0_Flx(vx); u = v1 = pol1_Flx(vx); while (lgpol(b)>n) { GEN r, q; q = Flx_divrem_pre(a,b,p,pi, &r); if (res) { long da = degpol(a), db=degpol(b), dr = degpol(r); res->lc = b[db+2]; if (dr >= n) Flx_halfres_update_pre(da, db, dr, p, pi, res); else { res->deg0 = da; res->deg1 = db; } } 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 (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"Flx_halfgcd (d = %ld)",degpol(b)); gerepileall(av,6, &a,&b,&u1,&v1,&u,&v); } } M = mkmat22(u,v,u1,v1); *pa = a; *pb = b; return gc_all(av,3, &M, pa, pb); } static GEN Flx_halfres_i(GEN x, GEN y, ulong p, ulong pi, GEN *a, GEN *b, struct Flx_res *res); static GEN Flx_halfres_split(GEN x, GEN y, ulong p, ulong pi, GEN *a, GEN *b, struct Flx_res *res) { pari_sp av = avma; GEN R, S, T, V1, V2; GEN x1, y1, r, q; long l = lgpol(x), n = l>>1, k; if (lgpol(y) <= n) { *a = Flx_copy(x); *b = Flx_copy(y); return matid2_FlxM(x[1]); } if (res) { res->lc = Flx_lead(y); res->deg0 -= n; res->deg1 -= n; res->off += n; } R = Flx_halfres_i(Flx_shift(x,-n),Flx_shift(y,-n),p,pi,a,b,res); if (res) { res->off -= n; res->deg0 += n; res->deg1 += n; } V1 = FlxM_Flx_mul2(R, Flxn_red(x,n), Flxn_red(y,n), p, pi); x1 = Flx_add(Flx_shift(*a,n), gel(V1,1), p); y1 = Flx_add(Flx_shift(*b,n), gel(V1,2), p); if (lgpol(y1) <= n) { *a = x1; *b = y1; return gc_all(av, 3, &R, a, b); } k = 2*n-degpol(y1); q = Flx_divrem_pre(x1, y1, p, pi, &r); if (res) { long dx1 = degpol(x1), dy1 = degpol(y1), dr = degpol(r); if (dy1 < degpol(y)) Flx_halfres_update_pre(res->deg0, res->deg1, dy1, p, pi, res); res->lc = uel(y1, dy1+2); res->deg0 = dx1; res->deg1 = dy1; if (dr >= n) { Flx_halfres_update_pre(dx1, dy1, dr, p, pi, res); res->deg0 = dy1; res->deg1 = dr; } res->deg0 -= k; res->deg1 -= k; res->off += k; } S = Flx_halfres_i(Flx_shift(y1,-k), Flx_shift(r,-k), p, pi, a, b, res); if (res) { res->deg0 += k; res->deg1 += k; res->off -= k; } T = FlxM_mul2(S, Flx_FlxM_qmul(q, R, p,pi), p, pi); V2 = FlxM_Flx_mul2(S, Flxn_red(y1,k), Flxn_red(r,k), p, pi); *a = Flx_add(Flx_shift(*a,k), gel(V2,1), p); *b = Flx_add(Flx_shift(*b,k), gel(V2,2), p); return gc_all(av, 3, &T, a, b); } static GEN Flx_halfres_i(GEN x, GEN y, ulong p, ulong pi, GEN *a, GEN *b, struct Flx_res *res) { if (lgpol(x) < get_Fl_threshold(p, Flx_HALFGCD_LIMIT, Flx_HALFGCD2_LIMIT)) return Flx_halfres_basecase(x, y, p, pi, a, b, res); return Flx_halfres_split(x, y, p, pi, a, b, res); } static GEN Flx_halfgcd_all_i(GEN x, GEN y, ulong p, ulong pi, GEN *pa, GEN *pb) { GEN a, b, R; R = Flx_halfres_i(x, y, p, pi, &a, &b, NULL); if (pa) *pa = a; if (pb) *pb = b; return R; } /* Return M in GL_2(Fl[X]) such that: if [a',b']~=M*[a,b]~ then degpol(a')>= (lgpol(a)>>1) >degpol(b') */ GEN Flx_halfgcd_all_pre(GEN x, GEN y, ulong p, ulong pi, GEN *a, GEN *b) { pari_sp av; GEN R, q ,r; long lx = lgpol(x), ly = lgpol(y); if (!lx) { if (a) *a = Flx_copy(y); if (b) *b = Flx_copy(x); return matJ2_FlxM(x[1]); } if (ly < lx) return Flx_halfgcd_all_i(x, y, p, pi, a, b); av = avma; q = Flx_divrem(y,x,p,&r); R = Flx_halfgcd_all_i(x, r, p, pi, a, b); gcoeff(R,1,1) = Flx_sub(gcoeff(R,1,1), Flx_mul_pre(q,gcoeff(R,1,2), p,pi), p); gcoeff(R,2,1) = Flx_sub(gcoeff(R,2,1), Flx_mul_pre(q,gcoeff(R,2,2), p,pi), p); return !a && b ? gc_all(av, 2, &R, b): gc_all(av, 1+!!a+!!b, &R, a, b); } GEN Flx_halfgcd_all(GEN x, GEN y, ulong p, GEN *a, GEN *b) { return Flx_halfgcd_all_pre(x, y, p, SMALL_ULONG(p)? 0: get_Fl_red(p), a, b); } GEN Flx_halfgcd_pre(GEN x, GEN y, ulong p, ulong pi) { return Flx_halfgcd_all_pre(x, y, p, pi, NULL, NULL); } GEN Flx_halfgcd(GEN x, GEN y, ulong p) { return Flx_halfgcd_pre(x, y, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } /*Do not garbage collect*/ static GEN Flx_gcd_basecase(GEN a, GEN b, ulong p, ulong pi) { pari_sp av = avma; ulong iter = 0; if (lg(b) > lg(a)) swap(a, b); while (lgpol(b)) { GEN c = Flx_rem_pre(a,b,p,pi); iter++; a = b; b = c; if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"Flx_gcd (d = %ld)",degpol(c)); gerepileall(av,2, &a,&b); } } return iter < 2 ? Flx_copy(a) : a; } GEN Flx_gcd_pre(GEN x, GEN y, ulong p, ulong pi) { pari_sp av = avma; long lim; if (!lgpol(x)) return Flx_copy(y); lim = get_Fl_threshold(p, Flx_GCD_LIMIT, Flx_GCD2_LIMIT); while (lgpol(y) >= lim) { if (lgpol(y)<=(lgpol(x)>>1)) { GEN r = Flx_rem_pre(x, y, p, pi); x = y; y = r; } (void) Flx_halfgcd_all_pre(x, y, p, pi, &x, &y); if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"Flx_gcd (y = %ld)",degpol(y)); gerepileall(av,2,&x,&y); } } return gerepileuptoleaf(av, Flx_gcd_basecase(x,y,p,pi)); } GEN Flx_gcd(GEN x, GEN y, ulong p) { return Flx_gcd_pre(x, y, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } int Flx_is_squarefree(GEN z, ulong p) { pari_sp av = avma; GEN d = Flx_gcd(z, Flx_deriv(z,p) , p); return gc_bool(av, degpol(d) == 0); } static long Flx_is_smooth_squarefree(GEN f, long r, ulong p, ulong pi) { pari_sp av = avma; long i; GEN sx = polx_Flx(f[1]), a = sx; for(i=1;;i++) { if (degpol(f)<=r) return gc_long(av,1); a = Flxq_powu_pre(Flx_rem_pre(a,f,p,pi), p, f, p, pi); if (Flx_equal(a, sx)) return gc_long(av,1); if (i==r) return gc_long(av,0); f = Flx_div_pre(f, Flx_gcd_pre(Flx_sub(a,sx,p),f,p,pi),p,pi); } } static long Flx_is_l_pow(GEN x, ulong p) { ulong i, lx = lgpol(x); for (i=1; i1) pari_warn(warnmem,"Flx_extgcd (d = %ld)",degpol(a)); gerepileall(av,ptu ? 6: 4, &a,&b,&v,&v1,&u,&u1); } } if (ptu) *ptu = u; *ptv = v; return a; } static GEN Flx_extgcd_halfgcd(GEN x, GEN y, ulong p, ulong pi, GEN *ptu, GEN *ptv) { GEN u, v; long lim = get_Fl_threshold(p, Flx_EXTGCD_LIMIT, Flx_EXTGCD2_LIMIT); GEN V = cgetg(expu(lgpol(y))+2,t_VEC); long i, n = 0, vs = x[1]; while (lgpol(y) >= lim) { if (lgpol(y)<=(lgpol(x)>>1)) { GEN r, q = Flx_divrem_pre(x, y, p, pi, &r); x = y; y = r; gel(V,++n) = mkmat22(pol0_Flx(vs),pol1_Flx(vs),pol1_Flx(vs),Flx_neg(q,p)); } else gel(V,++n) = Flx_halfgcd_all_pre(x, y, p, pi, &x, &y); } y = Flx_extgcd_basecase(x,y,p,pi,&u,&v); for (i = n; i>1; i--) { GEN R = gel(V,i); GEN u1 = Flx_addmulmul(u, v, gcoeff(R,1,1), gcoeff(R,2,1), p, pi); GEN v1 = Flx_addmulmul(u, v, gcoeff(R,1,2), gcoeff(R,2,2), p, pi); u = u1; v = v1; } { GEN R = gel(V,1); if (ptu) *ptu = Flx_addmulmul(u, v, gcoeff(R,1,1), gcoeff(R,2,1), p, pi); *ptv = Flx_addmulmul(u, v, gcoeff(R,1,2), gcoeff(R,2,2), p, pi); } 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_pre(GEN x, GEN y, ulong p, ulong pi, GEN *ptu, GEN *ptv) { pari_sp av = avma; GEN d; long lim = get_Fl_threshold(p, Flx_EXTGCD_LIMIT, Flx_EXTGCD2_LIMIT); if (lgpol(y) >= lim) d = Flx_extgcd_halfgcd(x, y, p, pi, ptu, ptv); else d = Flx_extgcd_basecase(x, y, p, pi, ptu, ptv); return gc_all(av, ptu?3:2, &d, ptv, ptu); } GEN Flx_extgcd(GEN x, GEN y, ulong p, GEN *ptu, GEN *ptv) { return Flx_extgcd_pre(x, y, p, SMALL_ULONG(p)? 0: get_Fl_red(p), ptu, ptv); } static GEN Flx_halfres_pre(GEN x, GEN y, ulong p, ulong pi, GEN *a, GEN *b, ulong *r) { struct Flx_res res; GEN R; long dB; res.res = *r; res.lc = Flx_lead(y); res.deg0 = degpol(x); res.deg1 = degpol(y); res.off = 0; R = Flx_halfres_i(x, y, p, pi, a, b, &res); dB = degpol(*b); if (dB < degpol(y)) Flx_halfres_update_pre(res.deg0, res.deg1, dB, p, pi, &res); *r = res.res; return R; } static ulong Flx_resultant_basecase_pre(GEN a, GEN b, ulong p, ulong pi) { pari_sp av; long da,db,dc; ulong lb, res = 1UL; GEN c; 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 */ av = avma; while (db) { lb = b[db+2]; c = Flx_rem_pre(a,b, p,pi); a = b; b = c; dc = degpol(c); if (dc < 0) return gc_long(av,0); if (both_odd(da,db)) res = p - res; if (lb != 1) res = Fl_mul(res, Fl_powu_pre(lb, da - dc, p, pi), p); if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"Flx_resultant (da = %ld)",da); gerepileall(av,2, &a,&b); } da = db; /* = degpol(a) */ db = dc; /* = degpol(b) */ } return gc_ulong(av, Fl_mul(res, Fl_powu_pre(b[2], da, p, pi), p)); } ulong Flx_resultant_pre(GEN x, GEN y, ulong p, ulong pi) { pari_sp av = avma; long lim; ulong res = 1; long dx = degpol(x), dy = degpol(y); if (dx < 0 || dy < 0) return 0; if (dx < dy) { swap(x,y); if (both_odd(dx, dy)) res = Fl_neg(res, p); } lim = get_Fl_threshold(p, Flx_GCD_LIMIT, Flx_GCD2_LIMIT); while (lgpol(y) >= lim) { if (lgpol(y)<=(lgpol(x)>>1)) { GEN r = Flx_rem_pre(x, y, p, pi); long dx = degpol(x), dy = degpol(y), dr = degpol(r); ulong ly = y[dy+2]; if (ly != 1) res = Fl_mul(res, Fl_powu_pre(ly, dx - dr, p, pi), p); if (both_odd(dx, dy)) res = Fl_neg(res, p); x = y; y = r; } (void) Flx_halfres_pre(x, y, p, pi, &x, &y, &res); if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"Flx_res (y = %ld)",degpol(y)); gerepileall(av,2,&x,&y); } } return gc_ulong(av, Fl_mul(res, Flx_resultant_basecase_pre(x, y, p, pi), p)); } ulong Flx_resultant(GEN a, GEN b, ulong p) { return Flx_resultant_pre(a, b, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } /* If resultant is 0, *ptU and *ptV are not set */ static ulong Flx_extresultant_basecase(GEN a, GEN b, ulong p, ulong pi, 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]; u = pol0_Flx(vs); v = pol1_Flx(vs); /* v = 1 */ dx = degpol(x); dy = degpol(y); while (dy) { /* b u = x (a), b v = y (a) */ lb = y[dy+2]; q = Flx_divrem_pre(x,y, p, pi, &z); x = y; y = z; /* (x,y) = (y, x - q y) */ dz = degpol(z); if (dz < 0) return gc_ulong(av,0); z = Flx_sub(u, Flx_mul_pre(q,v, p, pi), 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_pre(lb, dx-dz, p, pi), p); dx = dy; /* = degpol(x) */ dy = dz; /* = degpol(y) */ } res = Fl_mul(res, Fl_powu_pre(y[2], dx, p, pi), p); lb = Fl_mul(res, Fl_inv(y[2],p), p); v = gerepileuptoleaf(av, Flx_Fl_mul_pre(v, lb, p, pi)); av = avma; u = Flx_sub(Fl_to_Flx(res,vs), Flx_mul_pre(b,v,p,pi), p); u = gerepileuptoleaf(av, Flx_div_pre(u,a,p,pi)); /* = (res - b v) / a */ *ptU = u; *ptV = v; return res; } ulong Flx_extresultant_pre(GEN x, GEN y, ulong p, ulong pi, GEN *ptU, GEN *ptV) { pari_sp av=avma; GEN u, v, R; long lim = get_Fl_threshold(p, Flx_EXTGCD_LIMIT, Flx_EXTGCD2_LIMIT); ulong res = 1, res1; long dx = degpol(x), dy = degpol(y); if (dy > dx) { swap(x,y); lswap(dx,dy); if (both_odd(dx,dy)) res = p-res; R = matJ2_FlxM(x[1]); } else R = matid2_FlxM(x[1]); if (dy < 0) return 0; while (lgpol(y) >= lim) { GEN M; if (lgpol(y)<=(lgpol(x)>>1)) { GEN r, q = Flx_divrem_pre(x, y, p, pi, &r); long dx = degpol(x), dy = degpol(y), dr = degpol(r); ulong ly = y[dy+2]; if (ly != 1) res = Fl_mul(res, Fl_powu_pre(ly, dx - dr, p, pi), p); if (both_odd(dx, dy)) res = Fl_neg(res, p); x = y; y = r; R = Flx_FlxM_qmul(q, R, p,pi); } M = Flx_halfres_pre(x, y, p, pi, &x, &y, &res); if (!res) return gc_ulong(av, 0); R = FlxM_mul2(M, R, p, pi); gerepileall(av,3,&x,&y,&R); } res1 = Flx_extresultant_basecase(x,y,p,pi,&u,&v); if (!res1) return gc_ulong(av, 0); *ptU = Flx_Fl_mul_pre(Flx_addmulmul(u, v, gcoeff(R,1,1), gcoeff(R,2,1), p, pi), res, p, pi); *ptV = Flx_Fl_mul_pre(Flx_addmulmul(u, v, gcoeff(R,1,2), gcoeff(R,2,2), p, pi), res, p, pi); gerepileall(av, 2, ptU, ptV); return Fl_mul(res1,res,p); } ulong Flx_extresultant(GEN a, GEN b, ulong p, GEN *ptU, GEN *ptV) { return Flx_extresultant_pre(a, b, p, SMALL_ULONG(p)? 0: get_Fl_red(p), ptU, ptV); } /* allow pi = 0 (SMALL_ULONG) */ ulong Flx_eval_powers_pre(GEN x, GEN y, ulong p, ulong pi) { ulong l0, l1, h0, h1, v1, i = 1, lx = lg(x)-1; if (lx == 1) return 0; x++; if (pi) { LOCAL_OVERFLOW; LOCAL_HIREMAINDER; l1 = mulll(uel(x,i), uel(y,i)); h1 = hiremainder; v1 = 0; while (++i < lx) { l0 = mulll(uel(x,i), uel(y,i)); h0 = hiremainder; l1 = addll(l0, l1); h1 = addllx(h0, h1); v1 += overflow; } return v1? remlll_pre(v1, h1, l1, p, pi) : remll_pre(h1, l1, p, pi); } else { l1 = x[i] * y[i]; while (++i < lx) { l1 += x[i] * y[i]; if (l1 & HIGHBIT) l1 %= p; } return l1 % p; } } /* allow pi = 0 (SMALL_ULONG) */ ulong Flx_eval_pre(GEN x, ulong y, ulong p, ulong pi) { long i, n = degpol(x); ulong t; if (n <= 0) return n? 0: x[2]; if (n > 15) { pari_sp av = avma; GEN v = Fl_powers_pre(y, n, p, pi); return gc_ulong(av, Flx_eval_powers_pre(x, v, p, pi)); } i = n+2; t = x[i]; if (pi) { for (i--; i>=2; i--) t = Fl_addmul_pre(uel(x, i), t, y, p, pi); return t; } for (i--; i>=2; i--) t = (t * y + x[i]) % p; return t %= p; } ulong Flx_eval(GEN x, ulong y, ulong p) { return Flx_eval_pre(x, y, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } ulong Flv_prod_pre(GEN x, ulong p, ulong pi) { pari_sp ltop = avma; GEN v; long i,k,lx = lg(x); if (lx == 1) return 1UL; if (lx == 2) return uel(x,1); v = cgetg(1+(lx << 1), t_VECSMALL); k = 1; for (i=1; i 2) { lx = k; k = 1; for (i=1; i 1; --i) { ulong t = Fl_mul_pre(u, c[i-1], p, pi); u = Fl_mul_pre(u, w[i], p, pi); v[i] = t; } v[1] = u; set_avma(av); } void Flv_inv_pre_inplace(GEN v, ulong p, ulong pi) { Flv_inv_pre_indir(v,v, p, pi); } GEN Flv_inv_pre(GEN w, ulong p, ulong pi) { GEN v = cgetg(lg(w), t_VECSMALL); Flv_inv_pre_indir(w, v, p, pi); return v; } /* set v[i] = w[i]^{-1}; may be called with w = v, suitable for SMALL_ULONG p */ INLINE void Flv_inv_indir(GEN w, GEN v, ulong p) { pari_sp av = avma; long n = lg(w), i; ulong u; GEN c; if (n == 1) return; c = cgetg(n, t_VECSMALL); c[1] = w[1]; for (i = 2; i < n; ++i) c[i] = Fl_mul(w[i], c[i-1], p); i = n-1; u = Fl_inv(c[i], p); for ( ; i > 1; --i) { ulong t = Fl_mul(u, c[i-1], p); u = Fl_mul(u, w[i], p); v[i] = t; } v[1] = u; set_avma(av); } static void Flv_inv_i(GEN v, GEN w, ulong p) { if (SMALL_ULONG(p)) Flv_inv_indir(w, v, p); else Flv_inv_pre_indir(w, v, p, get_Fl_red(p)); } void Flv_inv_inplace(GEN v, ulong p) { Flv_inv_i(v, v, p); } GEN Flv_inv(GEN w, ulong p) { GEN v = cgetg(lg(w), t_VECSMALL); Flv_inv_i(v, w, p); return v; } GEN Flx_div_by_X_x(GEN a, ulong x, ulong p, ulong *rem) { long l = lg(a), i; GEN a0, z0, z; if (l <= 3) { if (rem) *rem = l == 2? 0: a[2]; return zero_Flx(a[1]); } z = cgetg(l-1,t_VECSMALL); z[1] = a[1]; a0 = a + l-1; z0 = z + l-2; *z0 = *a0--; if (SMALL_ULONG(p)) { for (i=l-3; i>1; 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; } /* xa, ya = t_VECSMALL */ static GEN Flv_producttree(GEN xa, GEN s, ulong p, ulong pi, long vs) { long n = lg(xa)-1; long m = n==1 ? 1: expu(n-1)+1; long i, j, k, ls = lg(s); GEN T = cgetg(m+1, t_VEC); GEN t = cgetg(ls, t_VEC); for (j=1, k=1; j>1)+1, t_VEC); for (j=1, k=1; k=1; i--) { GEN u = gel(T, i), v = gel(Tp, i+1); long n = lg(u)-1; t = cgetg(n+1, t_VEC); for (j=1, k=1; kT, s->p, s->pi); } #if 0 static GEN _Flx_sub(void *E, GEN x, GEN y) { struct _Flxq *s = (struct _Flxq *)E; return Flx_sub(x,y,s->p); } #endif static GEN _Flxq_sqr(void *data, GEN x) { struct _Flxq *D = (struct _Flxq*)data; return Flxq_sqr_pre(x, D->T, D->p, D->pi); } static GEN _Flxq_mul(void *data, GEN x, GEN y) { struct _Flxq *D = (struct _Flxq*)data; return Flxq_mul_pre(x,y, D->T, D->p, D->pi); } static GEN _Flxq_one(void *data) { struct _Flxq *D = (struct _Flxq*)data; return pol1_Flx(get_Flx_var(D->T)); } static GEN _Flxq_powu_i(struct _Flxq *D, GEN x, ulong n) { return gen_powu_i(x, n, (void*)D, &_Flxq_sqr, &_Flxq_mul); } static GEN _Flxq_powu(struct _Flxq *D, GEN x, ulong n) { pari_sp av = avma; return gerepileuptoleaf(av, _Flxq_powu_i(D, x, n)); } /* n-Power of x in Z/pZ[X]/(T), as t_VECSMALL. */ GEN Flxq_powu_pre(GEN x, ulong n, GEN T, ulong p, ulong pi) { pari_sp av; struct _Flxq D; switch(n) { case 0: return pol1_Flx(get_Flx_var(T)); case 1: return Flx_copy(x); case 2: return Flxq_sqr_pre(x, T, p, pi); } av = avma; set_Flxq_pre(&D, T, p, pi); return gerepileuptoleaf(av, _Flxq_powu_i(&D, x, n)); } GEN Flxq_powu(GEN x, ulong n, GEN T, ulong p) { return Flxq_powu_pre(x, n, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } /* n-Power of x in Z/pZ[X]/(T), as t_VECSMALL. */ GEN Flxq_pow_pre(GEN x, GEN n, GEN T, ulong p, ulong pi) { pari_sp av = avma; struct _Flxq D; GEN y; long s = signe(n); if (!s) return pol1_Flx(get_Flx_var(T)); if (s < 0) x = Flxq_inv_pre(x,T,p,pi); if (is_pm1(n)) return s < 0 ? x : Flx_copy(x); set_Flxq_pre(&D, T, p, pi); y = gen_pow_i(x, n, (void*)&D, &_Flxq_sqr, &_Flxq_mul); return gerepileuptoleaf(av, y); } GEN Flxq_pow(GEN x, GEN n, GEN T, ulong p) { return Flxq_pow_pre(x, n, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } GEN Flxq_pow_init_pre(GEN x, GEN n, long k, GEN T, ulong p, ulong pi) { struct _Flxq D; set_Flxq_pre(&D, T, p, pi); return gen_pow_init(x, n, k, (void*)&D, &_Flxq_sqr, &_Flxq_mul); } GEN Flxq_pow_init(GEN x, GEN n, long k, GEN T, ulong p) { return Flxq_pow_init_pre(x, n, k, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } GEN Flxq_pow_table_pre(GEN R, GEN n, GEN T, ulong p, ulong pi) { struct _Flxq D; set_Flxq_pre(&D, T, p, pi); return gen_pow_table(R, n, (void*)&D, &_Flxq_one, &_Flxq_mul); } GEN Flxq_pow_table(GEN R, GEN n, GEN T, ulong p) { return Flxq_pow_table_pre(R, n, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } /* Inverse of x in Z/lZ[X]/(T) or NULL if inverse doesn't exist * not stack clean. */ GEN Flxq_invsafe_pre(GEN x, GEN T, ulong p, ulong pi) { GEN V, z = Flx_extgcd_pre(get_Flx_mod(T), x, p, pi, NULL, &V); ulong iz; if (degpol(z)) return NULL; iz = Fl_inv(uel(z,2), p); return Flx_Fl_mul_pre(V, iz, p, pi); } GEN Flxq_invsafe(GEN x, GEN T, ulong p) { return Flxq_invsafe_pre(x, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } GEN Flxq_inv_pre(GEN x, GEN T, ulong p, ulong pi) { pari_sp av=avma; GEN U = Flxq_invsafe_pre(x, T, p, pi); if (!U) pari_err_INV("Flxq_inv",Flx_to_ZX(x)); return gerepileuptoleaf(av, U); } GEN Flxq_inv(GEN x, GEN T, ulong p) { return Flxq_inv_pre(x, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } GEN Flxq_div_pre(GEN x, GEN y, GEN T, ulong p, ulong pi) { pari_sp av = avma; return gerepileuptoleaf(av, Flxq_mul_pre(x,Flxq_inv_pre(y,T,p,pi),T,p,pi)); } GEN Flxq_div(GEN x, GEN y, GEN T, ulong p) { return Flxq_div_pre(x, y, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } GEN Flxq_powers_pre(GEN x, long l, GEN T, ulong p, ulong pi) { int use_sqr = 2*degpol(x) >= get_Flx_degree(T); struct _Flxq D; set_Flxq_pre(&D, T, p, pi); return gen_powers(x, l, use_sqr, (void*)&D, &_Flxq_sqr, &_Flxq_mul, &_Flxq_one); } GEN Flxq_powers(GEN x, long l, GEN T, ulong p) { return Flxq_powers_pre(x, l, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } GEN Flxq_matrix_pow_pre(GEN y, long n, long m, GEN P, ulong l, ulong li) { return FlxV_to_Flm(Flxq_powers_pre(y,m-1,P,l,li),n); } GEN Flxq_matrix_pow(GEN y, long n, long m, GEN P, ulong l) { return Flxq_matrix_pow_pre(y, n, m, P, l, SMALL_ULONG(l)? 0: get_Fl_red(l)); } GEN Flx_Frobenius_pre(GEN T, ulong p, ulong pi) { return Flxq_powu_pre(polx_Flx(get_Flx_var(T)), p, T, p, pi); } GEN Flx_Frobenius(GEN T, ulong p) { return Flx_Frobenius_pre(T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } GEN Flx_matFrobenius_pre(GEN T, ulong p, ulong pi) { long n = get_Flx_degree(T); return Flxq_matrix_pow_pre(Flx_Frobenius_pre(T, p, pi), n, n, T, p, pi); } GEN Flx_matFrobenius(GEN T, ulong p) { return Flx_matFrobenius_pre(T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } static GEN Flx_blocks_Flm(GEN P, long n, long m) { GEN z = cgetg(m+1,t_MAT); long i,j, k=2, l = lg(P); for(i=1; i<=m; i++) { GEN zi = cgetg(n+1,t_VECSMALL); gel(z,i) = zi; for(j=1; j<=n; j++) uel(zi, j) = k==l ? 0 : uel(P,k++); } return z; } GEN Flx_blocks(GEN P, long n, long m) { GEN z = cgetg(m+1,t_VEC); long i,j, k=2, l = lg(P); for(i=1; i<=m; i++) { GEN zi = cgetg(n+2,t_VECSMALL); zi[1] = P[1]; gel(z,i) = zi; for(j=2; j0; i--) { S = Flx_add(Flxq_mul_pre(S, g, T, p, pi), Flv_to_Flx(gel(C,i), sv), p); if (gc_needed(btop,1)) S = gerepileuptoleaf(btop, S); } return gerepileuptoleaf(av, S); } GEN Flx_FlxqV_eval(GEN Q, GEN x, GEN T, ulong p) { return Flx_FlxqV_eval_pre(Q, x, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } /* allow pi = 0 (SMALL_ULONG) */ GEN Flx_Flxq_eval_pre(GEN Q, GEN x, GEN T, ulong p, ulong pi) { pari_sp av = avma; GEN z, V; long d = degpol(Q), rtd; if (d < 0) return pol0_Flx(get_Flx_var(T)); rtd = (long) sqrt((double)d); T = Flx_get_red_pre(T, p, pi); V = Flxq_powers_pre(x, rtd, T, p, pi); z = Flx_FlxqV_eval_pre(Q, V, T, p, pi); return gerepileupto(av, z); } GEN Flx_Flxq_eval(GEN Q, GEN x, GEN T, ulong p) { return Flx_Flxq_eval_pre(Q, x, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } /* allow pi = 0 (SMALL_ULONG) */ GEN FlxC_FlxqV_eval_pre(GEN x, GEN v, GEN T, ulong p, ulong pi) { pari_APPLY_type(t_COL, Flx_FlxqV_eval_pre(gel(x,i), v, T, p, pi)) } GEN FlxC_FlxqV_eval(GEN x, GEN v, GEN T, ulong p) { return FlxC_FlxqV_eval_pre(x, v, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } /* allow pi = 0 (SMALL_ULONG) */ GEN FlxC_Flxq_eval_pre(GEN x, GEN F, GEN T, ulong p, ulong pi) { long d = brent_kung_optpow(get_Flx_degree(T)-1,lg(x)-1,1); GEN Fp = Flxq_powers_pre(F, d, T, p, pi); return FlxC_FlxqV_eval_pre(x, Fp, T, p, pi); } GEN FlxC_Flxq_eval(GEN x, GEN F, GEN T, ulong p) { return FlxC_Flxq_eval_pre(x, F, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } #if 0 static struct bb_algebra Flxq_algebra = { _Flxq_red, _Flx_add, _Flx_sub, _Flxq_mul, _Flxq_sqr, _Flxq_one, _Flxq_zero}; #endif static GEN Flxq_autpow_sqr(void *E, GEN x) { struct _Flxq *D = (struct _Flxq*)E; return Flx_Flxq_eval_pre(x, x, D->T, D->p, D->pi); } static GEN Flxq_autpow_msqr(void *E, GEN x) { struct _Flxq *D = (struct _Flxq*)E; return Flx_FlxqV_eval_pre(Flxq_autpow_sqr(E, x), D->aut, D->T, D->p, D->pi); } GEN Flxq_autpow_pre(GEN x, ulong n, GEN T, ulong p, ulong pi) { pari_sp av = avma; struct _Flxq D; long d; if (n==0) return Flx_rem_pre(polx_Flx(x[1]), T, p, pi); if (n==1) return Flx_rem_pre(x, T, p, pi); set_Flxq_pre(&D, T, p, pi); d = brent_kung_optpow(get_Flx_degree(T), hammingl(n)-1, 1); D.aut = Flxq_powers_pre(x, d, T, p, D.pi); x = gen_powu_fold_i(x,n,(void*)&D,Flxq_autpow_sqr,Flxq_autpow_msqr); return gerepilecopy(av, x); } GEN Flxq_autpow(GEN x, ulong n, GEN T, ulong p) { return Flxq_autpow_pre(x, n, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } GEN Flxq_autpowers(GEN x, ulong l, GEN T, ulong p) { long d, vT = get_Flx_var(T), dT = get_Flx_degree(T); ulong i, pi; pari_sp av = avma; GEN xp, V = cgetg(l+2,t_VEC); gel(V,1) = polx_Flx(vT); if (l==0) return V; gel(V,2) = gcopy(x); if (l==1) return V; pi = SMALL_ULONG(p)? 0: get_Fl_red(p); T = Flx_get_red_pre(T, p, pi); d = brent_kung_optpow(dT-1, l-1, 1); xp = Flxq_powers_pre(x, d, T, p, pi); for(i = 3; i < l+2; i++) gel(V,i) = Flx_FlxqV_eval_pre(gel(V,i-1), xp, T, p, pi); return gerepilecopy(av, V); } static GEN Flxq_autsum_mul(void *E, GEN x, GEN y) { struct _Flxq *D = (struct _Flxq*)E; GEN T = D->T; ulong p = D->p, pi = D->pi; GEN phi1 = gel(x,1), a1 = gel(x,2); GEN phi2 = gel(y,1), a2 = gel(y,2); ulong d = brent_kung_optpow(maxss(degpol(phi1),degpol(a1)),2,1); GEN V2 = Flxq_powers_pre(phi2, d, T, p, pi); GEN phi3 = Flx_FlxqV_eval_pre(phi1, V2, T, p, pi); GEN aphi = Flx_FlxqV_eval_pre(a1, V2, T, p, pi); GEN a3 = Flxq_mul_pre(aphi, a2, T, p, pi); return mkvec2(phi3, a3); } static GEN Flxq_autsum_sqr(void *E, GEN x) { return Flxq_autsum_mul(E, x, x); } static GEN Flxq_autsum_pre(GEN x, ulong n, GEN T, ulong p, ulong pi) { pari_sp av = avma; struct _Flxq D; set_Flxq_pre(&D, T, p, pi); x = gen_powu_i(x,n,(void*)&D,Flxq_autsum_sqr,Flxq_autsum_mul); return gerepilecopy(av, x); } GEN Flxq_autsum(GEN x, ulong n, GEN T, ulong p) { return Flxq_autsum_pre(x, n, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } static GEN Flxq_auttrace_mul(void *E, GEN x, GEN y) { struct _Flxq *D = (struct _Flxq*)E; GEN T = D->T; ulong p = D->p, pi = D->pi; GEN phi1 = gel(x,1), a1 = gel(x,2); GEN phi2 = gel(y,1), a2 = gel(y,2); ulong d = brent_kung_optpow(maxss(degpol(phi1),degpol(a1)),2,1); GEN V1 = Flxq_powers_pre(phi1, d, T, p, pi); GEN phi3 = Flx_FlxqV_eval_pre(phi2, V1, T, p, pi); GEN aphi = Flx_FlxqV_eval_pre(a2, V1, T, p, pi); GEN a3 = Flx_add(a1, aphi, p); return mkvec2(phi3, a3); } static GEN Flxq_auttrace_sqr(void *E, GEN x) { return Flxq_auttrace_mul(E, x, x); } GEN Flxq_auttrace_pre(GEN x, ulong n, GEN T, ulong p, ulong pi) { pari_sp av = avma; struct _Flxq D; set_Flxq_pre(&D, T, p, pi); x = gen_powu_i(x,n,(void*)&D,Flxq_auttrace_sqr,Flxq_auttrace_mul); return gerepilecopy(av, x); } GEN Flxq_auttrace(GEN x, ulong n, GEN T, ulong p) { return Flxq_auttrace_pre(x, n, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } static long bounded_order(ulong p, GEN b, long k) { GEN a = modii(utoipos(p), b); long i; for(i = 1; i < k; i++) { if (equali1(a)) return i; a = modii(muliu(a,p),b); } return 0; } /* n = (p^d-a)\b b = bb*p^vb p^k = 1 [bb] d = m*k+r+vb u = (p^k-1)/bb; v = (p^(r+vb)-a)/b; w = (p^(m*k)-1)/(p^k-1) n = p^r*w*u+v w*u = p^vb*(p^(m*k)-1)/b n = p^(r+vb)*(p^(m*k)-1)/b+(p^(r+vb)-a)/b */ static GEN Flxq_pow_Frobenius(GEN x, GEN n, GEN aut, GEN T, ulong p, ulong pi) { pari_sp av=avma; long d = get_Flx_degree(T); GEN an = absi_shallow(n), z, q; if (abscmpiu(an,p)<0 || cmpis(an,d)<=0) return Flxq_pow_pre(x, n, T, p, pi); q = powuu(p, d); if (dvdii(q, n)) { long vn = logint(an, utoipos(p)); GEN autvn = vn==1 ? aut: Flxq_autpow_pre(aut,vn,T,p,pi); z = Flx_Flxq_eval_pre(x,autvn,T,p,pi); } else { GEN b = diviiround(q, an), a = subii(q, mulii(an,b)); GEN bb, u, v, autk; long vb = Z_lvalrem(b,p,&bb); long m, r, k = is_pm1(bb)? 1: bounded_order(p,bb,d); if (!k || d-vb < k) return Flxq_pow_pre(x,n, T,p,pi); m = (d-vb)/k; r = (d-vb)%k; u = diviiexact(subiu(powuu(p,k),1),bb); v = diviiexact(subii(powuu(p,r+vb),a),b); autk = k==1 ? aut: Flxq_autpow_pre(aut,k,T,p,pi); if (r) { GEN autr = r==1 ? aut: Flxq_autpow_pre(aut,r,T,p,pi); z = Flx_Flxq_eval_pre(x,autr,T,p,pi); } else z = x; if (m > 1) z = gel(Flxq_autsum_pre(mkvec2(autk, z), m, T, p, pi), 2); if (!is_pm1(u)) z = Flxq_pow_pre(z, u, T, p, pi); if (signe(v)) z = Flxq_mul_pre(z, Flxq_pow_pre(x, v, T, p, pi), T, p, pi); } return gerepileupto(av,signe(n)>0 ? z : Flxq_inv_pre(z,T,p,pi)); } static GEN _Flxq_pow(void *data, GEN x, GEN n) { struct _Flxq *D = (struct _Flxq*)data; return Flxq_pow_Frobenius(x, n, D->aut, D->T, D->p, D->pi); } static GEN _Flxq_rand(void *data) { pari_sp av=avma; struct _Flxq *D = (struct _Flxq*)data; GEN z; do { set_avma(av); z = random_Flx(get_Flx_degree(D->T),get_Flx_var(D->T),D->p); } while (lgpol(z)==0); return z; } /* discrete log in FpXQ for a in Fp^*, g in FpXQ^* of order ord */ static GEN Fl_Flxq_log(ulong a, GEN g, GEN o, GEN T, ulong p) { pari_sp av = avma; GEN q,n_q,ord,ordp, op; if (a == 1UL) return gen_0; /* p > 2 */ ordp = utoi(p - 1); ord = get_arith_Z(o); if (!ord) ord = T? subiu(powuu(p, get_FpX_degree(T)), 1): ordp; if (a == p - 1) /* -1 */ return gerepileuptoint(av, shifti(ord,-1)); ordp = gcdii(ordp, ord); op = typ(o)==t_MAT ? famat_Z_gcd(o, ordp) : ordp; q = NULL; if (T) { /* we want < g > = Fp^* */ if (!equalii(ord,ordp)) { q = diviiexact(ord,ordp); g = Flxq_pow(g,q,T,p); } } n_q = Fp_log(utoi(a), utoipos(uel(g,2)), op, utoipos(p)); if (lg(n_q)==1) return gerepileuptoleaf(av, n_q); if (q) n_q = mulii(q, n_q); return gerepileuptoint(av, n_q); } static GEN Flxq_easylog(void* E, GEN a, GEN g, GEN ord) { struct _Flxq *f = (struct _Flxq *)E; GEN T = f->T; ulong p = f->p; long d = get_Flx_degree(T); if (Flx_equal1(a)) return gen_0; if (Flx_equal(a,g)) return gen_1; if (!degpol(a)) return Fl_Flxq_log(uel(a,2), g, ord, T, p); if (typ(ord)!=t_INT || d <= 4 || d == 6 || abscmpiu(ord,1UL<<27)<0) return NULL; return Flxq_log_index(a, g, ord, T, p); } static const struct bb_group Flxq_star={_Flxq_mul,_Flxq_pow,_Flxq_rand,hash_GEN,Flx_equal,Flx_equal1,Flxq_easylog}; const struct bb_group * get_Flxq_star(void **E, GEN T, ulong p) { struct _Flxq *e = (struct _Flxq *) stack_malloc(sizeof(struct _Flxq)); e->T = T; e->p = p; e->pi = SMALL_ULONG(p)? 0: get_Fl_red(p); e->aut = Flx_Frobenius_pre(T, p, e->pi); *E = (void*)e; return &Flxq_star; } GEN Flxq_order(GEN a, GEN ord, GEN T, ulong p) { void *E; const struct bb_group *S = get_Flxq_star(&E,T,p); return gen_order(a,ord,E,S); } GEN Flxq_log(GEN a, GEN g, GEN ord, GEN T, ulong p) { void *E; pari_sp av = avma; const struct bb_group *S = get_Flxq_star(&E,T,p); GEN v = get_arith_ZZM(ord), F = gmael(v,2,1); if (lg(F) > 1 && Flxq_log_use_index(veclast(F), T, p)) v = mkvec2(gel(v, 1), ZM_famat_limit(gel(v, 2), int2n(27))); return gerepileuptoleaf(av, gen_PH_log(a, g, v, E, S)); } GEN Flxq_sqrtn(GEN a, GEN n, GEN T, ulong p, GEN *zeta) { if (!lgpol(a)) { if (signe(n) < 0) pari_err_INV("Flxq_sqrtn",a); if (zeta) *zeta=pol1_Flx(get_Flx_var(T)); return pol0_Flx(get_Flx_var(T)); } else { void *E; pari_sp av = avma; const struct bb_group *S = get_Flxq_star(&E,T,p); GEN o = subiu(powuu(p,get_Flx_degree(T)), 1); GEN s = gen_Shanks_sqrtn(a,n,o,zeta,E,S); if (!s) return gc_NULL(av); return gc_all(av, zeta?2:1, &s, zeta); } } GEN Flxq_sqrt_pre(GEN z, GEN T, ulong p, ulong pi) { pari_sp av = avma; if (p==2) { GEN r = F2xq_sqrt(Flx_to_F2x(z), Flx_to_F2x(get_Flx_mod(T))); return gerepileupto(av, F2x_to_Flx(r)); } if (get_Flx_degree(T)==2) { GEN P = get_Flx_mod(T), s; ulong c = uel(P,2), b = uel(P,3), a = uel(P,4); ulong y = degpol(z)<1 ? 0: uel(z,3); if (a==1 && b==0) { ulong x = degpol(z)<1 ? Flx_constant(z): uel(z,2); GEN r = Fl2_sqrt_pre(mkvecsmall2(x, y), Fl_neg(c, p), p, pi); if (!r) return gc_NULL(av); s = mkvecsmall3(P[1], uel(r,1), uel(r,2)); } else { ulong b2 = Fl_halve(b, p), t = Fl_div(b2, a, p); ulong D = Fl_sub(Fl_sqr(b2, p), Fl_mul(a, c, p), p); ulong x = degpol(z)<1 ? Flx_constant(z): Fl_sub(uel(z,2), Fl_mul(uel(z,3), t, p), p); GEN r = Fl2_sqrt_pre(mkvecsmall2(x, y), D, p, pi); if (!r) return gc_NULL(av); s = mkvecsmall3(P[1], Fl_add(uel(r,1), Fl_mul(uel(r,2),t,p), p), uel(r,2)); } return gerepileuptoleaf(av, Flx_renormalize(s, 4)); } else return Flxq_sqrtn(z, gen_2, T, p, NULL); } GEN Flxq_sqrt(GEN a, GEN T, ulong p) { return Flxq_sqrt_pre(a, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } /* assume T irreducible mod p */ int Flxq_issquare(GEN x, GEN T, ulong p) { if (lgpol(x) == 0 || p == 2) return 1; return krouu(Flxq_norm(x,T,p), p) == 1; } /* assume T irreducible mod p */ int Flxq_is2npower(GEN x, long n, GEN T, ulong p) { pari_sp av; GEN m; if (n==1) return Flxq_issquare(x, T, p); if (lgpol(x) == 0 || p == 2) return 1; av = avma; m = shifti(subiu(powuu(p, get_Flx_degree(T)), 1), -n); return gc_bool(av, Flx_equal1(Flxq_pow(x, m, T, p))); } GEN Flxq_lroot_fast_pre(GEN a, GEN sqx, GEN T, long p, ulong pi) { pari_sp av=avma; GEN A = Flx_splitting(a,p); return gerepileuptoleaf(av, FlxqV_dotproduct_pre(A,sqx,T,p,pi)); } GEN Flxq_lroot_fast(GEN a, GEN sqx, GEN T, long p) { return Flxq_lroot_fast_pre(a, sqx, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } GEN Flxq_lroot_pre(GEN a, GEN T, long p, ulong pi) { pari_sp av=avma; long n = get_Flx_degree(T), d = degpol(a); GEN sqx, V; if (n==1) return leafcopy(a); if (n==2) return Flxq_powu_pre(a, p, T, p, pi); sqx = Flxq_autpow_pre(Flx_Frobenius_pre(T, p, pi), n-1, T, p, pi); if (d==1 && a[2]==0 && a[3]==1) return gerepileuptoleaf(av, sqx); if (d>=p) { V = Flxq_powers_pre(sqx,p-1,T,p,pi); return gerepileuptoleaf(av, Flxq_lroot_fast_pre(a,V,T,p,pi)); } else return gerepileuptoleaf(av, Flx_Flxq_eval_pre(a,sqx,T,p,pi)); } GEN Flxq_lroot(GEN a, GEN T, long p) { return Flxq_lroot_pre(a, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } ulong Flxq_norm(GEN x, GEN TB, ulong p) { GEN T = get_Flx_mod(TB); ulong y = Flx_resultant(T, x, p), L = Flx_lead(T); if (L==1 || lgpol(x)==0) return y; return Fl_div(y, Fl_powu(L, (ulong)degpol(x), p), p); } ulong Flxq_trace(GEN x, GEN TB, ulong p) { pari_sp av = avma; ulong t; GEN T = get_Flx_mod(TB); long n = degpol(T)-1; GEN z = Flxq_mul(x, Flx_deriv(T, p), TB, p); t = degpol(z)v(tau*z) that is, v*(M_tau) */ static GEN Flxq_transmul_init(GEN tau, GEN T, ulong p, ulong pi) { GEN bht; GEN h, Tp = get_Flx_red(T, &h); long n = degpol(Tp), vT = Tp[1]; GEN ft = Flx_recipspec(Tp+2, n+1, n+1); GEN bt = Flx_recipspec(tau+2, lgpol(tau), n); ft[1] = vT; bt[1] = vT; if (h) bht = Flxn_mul_pre(bt, h, n-1, p, pi); else { GEN bh = Flx_div_pre(Flx_shift(tau, n-1), T, p, pi); bht = Flx_recipspec(bh+2, lgpol(bh), n-1); bht[1] = vT; } return mkvec3(bt, bht, ft); } static GEN Flxq_transmul(GEN tau, GEN a, long n, ulong p, ulong pi) { pari_sp ltop = avma; GEN t1, t2, t3, vec; GEN bt = gel(tau, 1), bht = gel(tau, 2), ft = gel(tau, 3); if (lgpol(a)==0) return pol0_Flx(a[1]); t2 = Flx_shift(Flx_mul_pre(bt, a, p, pi),1-n); if (lgpol(bht)==0) return gerepileuptoleaf(ltop, t2); t1 = Flx_shift(Flx_mul_pre(ft, a, p, pi),-n); t3 = Flxn_mul_pre(t1, bht, n-1, p, pi); vec = Flx_sub(t2, Flx_shift(t3, 1), p); return gerepileuptoleaf(ltop, vec); } GEN Flxq_minpoly_pre(GEN x, GEN T, ulong p, ulong pi) { pari_sp ltop = avma; long vT = get_Flx_var(T), n = get_Flx_degree(T); GEN v_x; GEN g = pol1_Flx(vT), tau = pol1_Flx(vT); T = Flx_get_red_pre(T, p, pi); v_x = Flxq_powers_pre(x, usqrt(2*n), T, p, pi); while (lgpol(tau) != 0) { long i, j, m, k1; GEN M, v, tr, g_prime, c; if (degpol(g) == n) { tau = pol1_Flx(vT); g = pol1_Flx(vT); } v = random_Flx(n, vT, p); tr = Flxq_transmul_init(tau, T, p, pi); v = Flxq_transmul(tr, v, n, p, pi); m = 2*(n-degpol(g)); k1 = usqrt(m); tr = Flxq_transmul_init(gel(v_x,k1+1), T, p, pi); c = cgetg(m+2,t_VECSMALL); c[1] = vT; for (i=0; i , i = 0..m-1 */ M = Flx_halfgcd_pre(monomial_Flx(1, m, vT), c, p, pi); g_prime = gmael(M, 2, 2); if (degpol(g_prime) < 1) continue; g = Flx_mul_pre(g, g_prime, p, pi); tau = Flxq_mul_pre(tau, Flx_FlxqV_eval_pre(g_prime, v_x, T,p,pi), T,p,pi); } g = Flx_normalize(g,p); return gerepileuptoleaf(ltop,g); } GEN Flxq_minpoly(GEN x, GEN T, ulong p) { return Flxq_minpoly_pre(x, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } GEN Flxq_conjvec(GEN x, GEN T, ulong p) { long i, l = 1+get_Flx_degree(T); GEN z = cgetg(l,t_COL); struct _Flxq D; set_Flxq(&D, T, p); gel(z,1) = Flx_copy(x); for (i=2; i 3) { ulong t = p_1 >> vals(p_1); GEN P = gel(factoru(t), 1); L = cgetg_copy(P, &i); while (--i) L[i] = p_1 / P[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); pi = SMALL_ULONG(p)? 0: get_Fl_red(p); F = Flx_Frobenius_pre(T, p, pi); for (av = avma;; set_avma(av)) { GEN tt; g = random_Flx(f, vT, p); if (degpol(g) < 1) continue; if (p == 2) tt = g; else { ulong t = Flxq_norm(g, T, p); if (t == 1 || !is_gener_Fl(t, p, p_1, L)) continue; tt = Flxq_powu_pre(g, p_1>>1, T, p, pi); } for (i = 1; i < j; i++) { GEN a = Flxq_pow_Frobenius(tt, gel(L2,i), F, T, p, pi); if (!degpol(a) && uel(a,2) == p_1) break; } if (i == j) break; } if (!po) { set_avma((pari_sp)g); g = gerepileuptoleaf(av0, g); } else { *po = mkvec2(subiu(powuu(p,f), 1), o); gerepileall(av0, 2, &g, po); } return g; } static GEN _Flxq_neg(void *E, GEN x) { struct _Flxq *s = (struct _Flxq *)E; return Flx_neg(x,s->p); } static GEN _Flxq_rmul(void *E, GEN x, GEN y) { struct _Flxq *s = (struct _Flxq *)E; return Flx_mul_pre(x,y,s->p,s->pi); } static GEN _Flxq_inv(void *E, GEN x) { struct _Flxq *s = (struct _Flxq *)E; return Flxq_inv(x,s->T,s->p); } static int _Flxq_equal0(GEN x) { return lgpol(x)==0; } static GEN _Flxq_s(void *E, long x) { struct _Flxq *s = (struct _Flxq *)E; ulong u = x<0 ? s->p+x: (ulong)x; return Fl_to_Flx(u, get_Flx_var(s->T)); } static const struct bb_field Flxq_field={_Flxq_red,_Flx_add,_Flxq_rmul,_Flxq_neg, _Flxq_inv,_Flxq_equal0,_Flxq_s}; const struct bb_field *get_Flxq_field(void **E, GEN T, ulong p) { GEN z = new_chunk(sizeof(struct _Flxq)); set_Flxq((struct _Flxq *)z, T, p); *E = (void*)z; return &Flxq_field; } /***********************************************************************/ /** Flxn **/ /***********************************************************************/ GEN Flx_invLaplace(GEN x, ulong p) { long i, d = degpol(x); ulong t; GEN y; if (d <= 1) return Flx_copy(x); t = Fl_inv(factorial_Fl(d, p), p); y = cgetg(d+3, t_VECSMALL); y[1] = x[1]; for (i=d; i>=2; i--) { uel(y,i+2) = Fl_mul(uel(x,i+2), t, p); t = Fl_mul(t, i, p); } uel(y,3) = uel(x,3); uel(y,2) = uel(x,2); return y; } GEN Flx_Laplace(GEN x, ulong p) { long i, d = degpol(x); ulong t = 1; GEN y; if (d <= 1) return Flx_copy(x); y = cgetg(d+3, t_VECSMALL); y[1] = x[1]; uel(y,2) = uel(x,2); uel(y,3) = uel(x,3); for (i=2; i<=d; i++) { t = Fl_mul(t, i%p, p); uel(y,i+2) = Fl_mul(uel(x,i+2), t, p); } return y; } GEN Flxn_red(GEN a, long n) { long i, L, l = lg(a); GEN b; if (l == 2 || !n) return zero_Flx(a[1]); L = n+2; if (L > l) L = l; b = cgetg(L, t_VECSMALL); b[1] = a[1]; for (i=2; i assume g==1 */ GEN Flxn_div_pre(GEN g, GEN f, long e, ulong p, ulong pi) { pari_sp av = avma, av2; ulong mask; GEN W; long n = 1; if (lg(f) <= 2) pari_err_INV("Flxn_inv",f); W = Fl_to_Flx(Fl_inv(uel(f,2),p), f[1]); mask = quadratic_prec_mask(e); av2 = avma; for (;mask>1;) { GEN u, fr; long n2 = n; n<<=1; if (mask & 1) n--; mask >>= 1; fr = Flxn_red(f, n); if (mask>1 || !g) { u = Flxn_mul_pre(W, Flxn_mulhigh(fr, W, n2, n, p, pi), n-n2, p, pi); W = Flx_sub(W, Flx_shift(u, n2), p); } else { GEN y = Flxn_mul_pre(g, W, n, p, pi), yt = Flxn_red(y, n-n2); u = Flxn_mul_pre(yt, Flxn_mulhigh(fr, W, n2, n, p, pi), n-n2, p, pi); W = Flx_sub(y, Flx_shift(u, n2), p); } if (gc_needed(av2,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"Flxn_div, e = %ld", n); W = gerepileupto(av2, W); } } return gerepileupto(av, W); } GEN Flxn_div(GEN g, GEN f, long e, ulong p) { return Flxn_div_pre(g, f, e, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } GEN Flxn_inv(GEN f, long e, ulong p) { return Flxn_div(NULL, f, e, p); } GEN Flxn_expint(GEN h, long e, ulong p) { pari_sp av = avma, av2; long v = h[1], n=1; GEN f = pol1_Flx(v), g = pol1_Flx(v); ulong mask = quadratic_prec_mask(e), pi = SMALL_ULONG(p)? 0: get_Fl_red(p); av2 = avma; for (;mask>1;) { GEN u, w; long n2 = n; n<<=1; if (mask & 1) n--; mask >>= 1; u = Flxn_mul_pre(g, Flx_mulhigh_i(f, Flxn_red(h, n2-1), n2-1, p,pi), n-n2, p,pi); u = Flx_add(u, Flx_shift(Flxn_red(h, n-1), 1-n2), p); w = Flxn_mul_pre(f, Flx_integXn(u, n2-1, p), n-n2, p, pi); f = Flx_add(f, Flx_shift(w, n2), p); if (mask<=1) break; u = Flxn_mul_pre(g, Flxn_mulhigh(f, g, n2, n, p, pi), n-n2, p, pi); g = Flx_sub(g, Flx_shift(u, n2), p); if (gc_needed(av2,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"Flxn_exp, e = %ld", n); gerepileall(av2, 2, &f, &g); } } return gerepileupto(av, f); } GEN Flxn_exp(GEN h, long e, ulong p) { if (degpol(h)<1 || uel(h,2)!=0) pari_err_DOMAIN("Flxn_exp","valuation", "<", gen_1, h); return Flxn_expint(Flx_deriv(h, p), e, p); } INLINE GEN Flxn_recip(GEN x, long n) { GEN z=Flx_recipspec(x+2,lgpol(x),n); z[1]=x[1]; return z; } GEN Flx_Newton(GEN P, long n, ulong p) { pari_sp av = avma; long d = degpol(P); GEN dP = Flxn_recip(Flx_deriv(P, p), d); GEN Q = Flxn_div(dP, Flxn_recip(P, d+1), n, p); return gerepileuptoleaf(av, Q); } GEN Flx_fromNewton(GEN P, ulong p) { pari_sp av = avma; ulong n = Flx_constant(P)+1; GEN z = Flx_neg(Flx_shift(P, -1), p); GEN Q = Flxn_recip(Flxn_expint(z, n, p), n); return gerepileuptoleaf(av, Q); } static void init_invlaplace(long d, ulong p, GEN *pt_P, GEN *pt_V) { long i; ulong e; GEN P = cgetg(d+1, t_VECSMALL); GEN V = cgetg(d+1, t_VECSMALL); for (i=1, e=1; i<=d; i++, e++) { if (e==p) { e = 0; V[i] = u_lvalrem(i, p, &uel(P,i)); } else { V[i] = 0; uel(P,i) = i; } } *pt_P = P; *pt_V = V; } /* return p^val * FpX_invLaplace(1+x+...x^(n-1), q), with q a power of p and * val large enough to compensate for the power of p in the factorials */ static GEN ZpX_invLaplace_init(long n, GEN q, ulong p, long v, long sv) { pari_sp av = avma; long i, d = n-1, w; GEN y, W, E, t; init_invlaplace(d, p, &E, &W); t = Fp_inv(FpV_prod(Flv_to_ZV(E), q), q); w = zv_sum(W); if (v > w) t = Fp_mul(t, powuu(p, v-w), q); y = cgetg(d+3,t_POL); y[1] = evalsigne(1) | sv; for (i=d; i>=1; i--) { gel(y,i+2) = t; t = Fp_mulu(t, uel(E,i), q); if (uel(W,i)) t = Fp_mul(t, powuu(p, uel(W,i)), q); } gel(y,2) = t; return gerepilecopy(av, ZX_renormalize(y, d+3)); } GEN Flx_composedsum(GEN P, GEN Q, ulong p) { pari_sp av = avma; long n = 1 + degpol(P)*degpol(Q); ulong lead = Fl_mul(Fl_powu(Flx_lead(P), degpol(Q), p), Fl_powu(Flx_lead(Q), degpol(P), p), p); GEN R; if (p >= (ulong)n) { GEN Pl = Flx_invLaplace(Flx_Newton(P,n,p), p); GEN Ql = Flx_invLaplace(Flx_Newton(Q,n,p), p); GEN L = Flx_Laplace(Flxn_mul(Pl, Ql, n, p), p); R = Flx_fromNewton(L, p); } else { long v = factorial_lval(n-1, p); long w = 1 + ulogint(n-1, p); GEN pv = powuu(p, v); GEN qf = powuu(p, w), q = mulii(pv, qf), q2 = mulii(q, pv); GEN iL = ZpX_invLaplace_init(n, q, p, v, P[1]); GEN Pl = FpX_convol(iL, FpX_Newton(Flx_to_ZX(P), n, qf), q); GEN Ql = FpX_convol(iL, FpX_Newton(Flx_to_ZX(Q), n, qf), q); GEN Ln = ZX_Z_divexact(FpXn_mul(Pl, Ql, n, q2), pv); GEN L = ZX_Z_divexact(FpX_Laplace(Ln, q), pv); R = ZX_to_Flx(FpX_fromNewton(L, qf), p); } return gerepileuptoleaf(av, Flx_Fl_mul(R, lead, p)); } static GEN _Flx_composedsum(void *E, GEN a, GEN b) { return Flx_composedsum(a, b, (ulong)E); } GEN FlxV_composedsum(GEN V, ulong p) { return gen_product(V, (void *)p, &_Flx_composedsum); } GEN Flx_composedprod(GEN P, GEN Q, ulong p) { pari_sp av = avma; long n = 1+ degpol(P)*degpol(Q); ulong lead = Fl_mul(Fl_powu(Flx_lead(P), degpol(Q), p), Fl_powu(Flx_lead(Q), degpol(P), p), p); GEN R; if (p >= (ulong)n) { GEN L = Flx_convol(Flx_Newton(P,n,p), Flx_Newton(Q,n,p), p); R = Flx_fromNewton(L, p); } else { long w = 1 + ulogint(n, p); GEN qf = powuu(p, w); GEN Pl = FpX_convol(FpX_Newton(Flx_to_ZX(P), n, qf), FpX_Newton(Flx_to_ZX(Q), n, qf), qf); R = ZX_to_Flx(FpX_fromNewton(Pl, qf), p); } return gerepileuptoleaf(av, Flx_Fl_mul(R, lead, p)); } /* (x+1)^n mod p; assume 2 <= n < 2p prime */ static GEN Fl_Xp1_powu(ulong n, ulong p, long v) { ulong k, d = (n + 1) >> 1; GEN C, V = identity_zv(d); Flv_inv_inplace(V, p); /* could restrict to odd integers in [3,d] */ C = cgetg(n+3, t_VECSMALL); C[1] = v; uel(C,2) = 1UL; uel(C,3) = n%p; uel(C,4) = Fl_mul(odd(n)? n: n-1, n >> 1, p); /* binom(n,k) = binom(n,k-1) * (n-k+1) / k */ if (SMALL_ULONG(p)) for (k = 3; k <= d; k++) uel(C,k+2) = Fl_mul(Fl_mul(n-k+1, uel(C,k+1), p), uel(V,k), p); else { ulong pi = get_Fl_red(p); for (k = 3; k <= d; k++) uel(C,k+2) = Fl_mul_pre(Fl_mul(n-k+1, uel(C,k+1), p), uel(V,k), p, pi); } for ( ; k <= n; k++) uel(C,2+k) = uel(C,2+n-k); return C; /* normalized */ } /* p arbitrary */ GEN Flx_translate1_basecase(GEN P, ulong p) { GEN R = Flx_copy(P); long i, k, n = degpol(P); for (i = 1; i <= n; i++) for (k = n-i; k < n; k++) uel(R,k+2) = Fl_add(uel(R,k+2), uel(R,k+3), p); return R; } static int translate_basecase(long n, ulong p) { #ifdef LONG_IS_64BIT if (p <= 19) return n < 40; if (p < 1UL<<30) return n < 58; if (p < 1UL<<59) return n < 100; if (p < 1UL<<62) return n < 120; if (p < 1UL<<63) return n < 240; return n < 250; #else if (p <= 13) return n < 18; if (p <= 17) return n < 22; if (p <= 29) return n < 39; if (p <= 67) return n < 69; if (p < 1UL<< 15) return n < 80; if (p < 1UL<< 16) return n < 100; if (p < 1UL<< 28) return n < 300; return n < 650; #endif } /* assume p prime */ GEN Flx_translate1(GEN P, ulong p) { long d, n = degpol(P); GEN R, Q, S; if (translate_basecase(n, p)) return Flx_translate1_basecase(P, p); /* n > 0 */ d = n >> 1; if ((ulong)n < p) { R = Flx_translate1(Flxn_red(P, d), p); Q = Flx_translate1(Flx_shift(P, -d), p); S = Fl_Xp1_powu(d, p, P[1]); return Flx_add(Flx_mul(Q, S, p), R, p); } else { ulong q; if ((ulong)d > p) (void)ulogintall(d, p, &q); else q = p; R = Flx_translate1(Flxn_red(P, q), p); Q = Flx_translate1(Flx_shift(P, -q), p); S = Flx_add(Flx_shift(Q, q), Q, p); return Flx_add(S, R, p); /* P(x+1) = Q(x+1) (x^q+1) + R(x+1) */ } } static GEN zl_Xp1_powu(ulong n, ulong p, ulong q, long e, long vs) { ulong k, d = n >> 1, c, v = 0; GEN C, V, W, U = upowers(p, e-1); init_invlaplace(d, p, &V, &W); Flv_inv_inplace(V, q); C = cgetg(n+3, t_VECSMALL); C[1] = vs; uel(C,2) = 1UL; uel(C,3) = n%q; v = u_lvalrem(n, p, &c); for (k = 2; k <= d; k++) { ulong w; v += u_lvalrem(n-k+1, p, &w) - W[k]; c = Fl_mul(Fl_mul(w%q, c, q), uel(V,k), q); uel(C,2+k) = v >= (ulong)e ? 0: v==0 ? c : Fl_mul(c, uel(U, v+1), q); } for ( ; k <= n; k++) uel(C,2+k) = uel(C,2+n-k); return C; /* normalized */ } GEN zlx_translate1(GEN P, ulong p, long e) { ulong d, q = upowuu(p,e), n = degpol(P); GEN R, Q, S; if (translate_basecase(n, q)) return Flx_translate1_basecase(P, q); /* n > 0 */ d = n >> 1; R = zlx_translate1(Flxn_red(P, d), p, e); Q = zlx_translate1(Flx_shift(P, -d), p, e); S = zl_Xp1_powu(d, p, q, e, P[1]); return Flx_add(Flx_mul(Q, S, q), R, q); } /***********************************************************************/ /** Fl2 **/ /***********************************************************************/ /* Fl2 objects are Flv of length 2 [a,b] representing a+bsqrt(D) for * a nonsquare D. */ INLINE GEN mkF2(ulong a, ulong b) { return mkvecsmall2(a,b); } /* allow pi = 0 */ GEN Fl2_mul_pre(GEN x, GEN y, ulong D, ulong p, ulong pi) { ulong xaya, xbyb, Db2, mid, z1, z2; ulong x1 = x[1], x2 = x[2], y1 = y[1], y2 = y[2]; if (pi) { xaya = Fl_mul_pre(x1,y1,p,pi); if (x2==0 && y2==0) return mkF2(xaya,0); if (x2==0) return mkF2(xaya,Fl_mul_pre(x1,y2,p,pi)); if (y2==0) return mkF2(xaya,Fl_mul_pre(x2,y1,p,pi)); xbyb = Fl_mul_pre(x2,y2,p,pi); mid = Fl_mul_pre(Fl_add(x1,x2,p), Fl_add(y1,y2,p),p,pi); Db2 = Fl_mul_pre(D, xbyb, p,pi); } else if (p & HIGHMASK) { xaya = Fl_mul(x1,y1,p); if (x2==0 && y2==0) return mkF2(xaya,0); if (x2==0) return mkF2(xaya,Fl_mul(x1,y2,p)); if (y2==0) return mkF2(xaya,Fl_mul(x2,y1,p)); xbyb = Fl_mul(x2,y2,p); mid = Fl_mul(Fl_add(x1,x2,p), Fl_add(y1,y2,p),p); Db2 = Fl_mul(D, xbyb, p); } else { xaya = (x1 * y1) % p; if (x2==0 && y2==0) return mkF2(xaya,0); if (x2==0) return mkF2(xaya, (x1 * y2) % p); if (y2==0) return mkF2(xaya, (x2 * y1) % p); xbyb = (x2 * y2) % p; mid = (Fl_add(x1,x2,p) * Fl_add(y1,y2,p)) % p; Db2 = (D * xbyb) % p; } z1 = Fl_add(xaya,Db2,p); z2 = Fl_sub(mid,Fl_add(xaya,xbyb,p),p); return mkF2(z1,z2); } /* allow pi = 0 */ GEN Fl2_sqr_pre(GEN x, ulong D, ulong p, ulong pi) { ulong a = x[1], b = x[2]; ulong a2, Db2, ab; if (pi) { a2 = Fl_sqr_pre(a,p,pi); if (b==0) return mkF2(a2,0); Db2= Fl_mul_pre(D, Fl_sqr_pre(b,p,pi), p,pi); ab = Fl_mul_pre(a,b,p,pi); } else if (p & HIGHMASK) { a2 = Fl_sqr(a,p); if (b==0) return mkF2(a2,0); Db2= Fl_mul(D, Fl_sqr(b,p), p); ab = Fl_mul(a,b,p); } else { a2 = (a * a) % p; if (b==0) return mkF2(a2,0); Db2= (D * ((b * b) % p)) % p; ab = (a * b) % p; } return mkF2(Fl_add(a2,Db2,p), Fl_double(ab,p)); } /* allow pi = 0 */ ulong Fl2_norm_pre(GEN x, ulong D, ulong p, ulong pi) { ulong a = x[1], b = x[2], a2; if (pi) { a2 = Fl_sqr_pre(a,p,pi); return b? Fl_sub(a2, Fl_mul_pre(D, Fl_sqr_pre(b, p,pi), p,pi), p): a2; } else if (p & HIGHMASK) { a2 = Fl_sqr(a,p); return b? Fl_sub(a2, Fl_mul(D, Fl_sqr(b, p), p), p): a2; } else { a2 = (a * a) % p; return b? Fl_sub(a2, (D * ((b * b) % p)) % p, p): a2; } } /* allow pi = 0 */ GEN Fl2_inv_pre(GEN x, ulong D, ulong p, ulong pi) { ulong a = x[1], b = x[2], n, ni; if (b == 0) return mkF2(Fl_inv(a,p), 0); b = Fl_neg(b, p); if (pi) { n = Fl_sub(Fl_sqr_pre(a, p,pi), Fl_mul_pre(D, Fl_sqr_pre(b, p,pi), p,pi), p); ni = Fl_inv(n,p); return mkF2(Fl_mul_pre(a, ni, p,pi), Fl_mul_pre(b, ni, p,pi)); } else if (p & HIGHMASK) { n = Fl_sub(Fl_sqr(a, p), Fl_mul(D, Fl_sqr(b, p), p), p); ni = Fl_inv(n,p); return mkF2(Fl_mul(a, ni, p), Fl_mul(b, ni, p)); } else { n = Fl_sub((a * a) % p, (D * ((b * b) % p)) % p, p); ni = Fl_inv(n,p); return mkF2((a * ni) % p, (b * ni) % p); } } int Fl2_equal1(GEN x) { return x[1]==1 && x[2]==0; } struct _Fl2 { ulong p, pi, D; }; static GEN _Fl2_sqr(void *data, GEN x) { struct _Fl2 *D = (struct _Fl2*)data; return Fl2_sqr_pre(x, D->D, D->p, D->pi); } static GEN _Fl2_mul(void *data, GEN x, GEN y) { struct _Fl2 *D = (struct _Fl2*)data; return Fl2_mul_pre(x,y, D->D, D->p, D->pi); } /* n-Power of x in Z/pZ[X]/(T), as t_VECSMALL; allow pi = 0 */ GEN Fl2_pow_pre(GEN x, GEN n, ulong D, ulong p, ulong pi) { pari_sp av = avma; struct _Fl2 d; GEN y; long s = signe(n); if (!s) return mkF2(1,0); if (s < 0) x = Fl2_inv_pre(x,D,p,pi); if (is_pm1(n)) return s < 0 ? x : zv_copy(x); d.p = p; d.pi = pi; d.D=D; y = gen_pow_i(x, n, (void*)&d, &_Fl2_sqr, &_Fl2_mul); return gerepileuptoleaf(av, y); } static GEN _Fl2_pow(void *data, GEN x, GEN n) { struct _Fl2 *D = (struct _Fl2*)data; return Fl2_pow_pre(x, n, D->D, D->p, D->pi); } static GEN _Fl2_rand(void *data) { struct _Fl2 *D = (struct _Fl2*)data; ulong a = random_Fl(D->p), b=random_Fl(D->p-1)+1; return mkF2(a,b); } GEN Fl2_sqrt_pre(GEN z, ulong D, ulong p, ulong pi) { ulong a = uel(z,1), b = uel(z,2), as2, u, v, s; ulong y = Fl_2gener_pre_i(D, p, pi); if (b == 0) return krouu(a, p)==1 ? mkF2(Fl_sqrt_pre_i(a, y, p, pi), 0) : mkF2(0, Fl_sqrt_pre_i(Fl_div(a, D, p), y, p, pi)); s = Fl_sqrt_pre_i(Fl2_norm_pre(z, D, p, pi), y, p, pi); if (s==~0UL) return NULL; as2 = Fl_halve(Fl_add(a, s, p), p); if (krouu(as2, p)==-1) as2 = Fl_sub(as2, s, p); u = Fl_sqrt_pre_i(as2, y, p, pi); v = Fl_div(b, Fl_double(u, p), p); return mkF2(u,v); } static const struct bb_group Fl2_star={_Fl2_mul, _Fl2_pow, _Fl2_rand, hash_GEN, zv_equal, Fl2_equal1, NULL}; /* allow pi = 0 */ GEN Fl2_sqrtn_pre(GEN a, GEN n, ulong D, ulong p, ulong pi, GEN *zeta) { struct _Fl2 E; GEN o; if (a[1]==0 && a[2]==0) { if (signe(n) < 0) pari_err_INV("Flxq_sqrtn",a); if (zeta) *zeta=mkF2(1,0); return zv_copy(a); } E.p=p; E.pi = pi; E.D = D; o = subiu(powuu(p,2), 1); return gen_Shanks_sqrtn(a,n,o,zeta,(void*)&E,&Fl2_star); } /* allow pi = 0 */ GEN Flx_Fl2_eval_pre(GEN x, GEN y, ulong D, ulong p, ulong pi) { GEN p1; long i = lg(x)-1; if (i <= 2) return mkF2(i == 2? x[2]: 0, 0); p1 = mkF2(x[i], 0); for (i--; i>=2; i--) { p1 = Fl2_mul_pre(p1, y, D, p, pi); uel(p1,1) = Fl_add(uel(p1,1), uel(x,i), p); } return p1; } /***********************************************************************/ /** FlxV **/ /***********************************************************************/ /* 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;ipp[i] divides n, and lasta = a_{n/p}. * Call fun(E, N, a_N), for all N, n | N, P^+(N) <= p, a_N != 0, * i.e. assumes that fun accumulates a_N * w(N) */ static void gen_BG_add(void *E, bg_fun *fun, struct bg_data *bg, GEN n, long i, GEN a, GEN lasta) { pari_sp av = avma; long j; ulong nn = itou_or_0(n); if (nn && nn <= bg->rootbnd) bg->an[nn] = itos(a); if (signe(a)) { fun(E, n, a); 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->an[p]); if (i == j && umodiu(bg->N, p)) nexta = subii(nexta, mului(p, lasta)); gen_BG_add(E, fun, bg, pn, j, nexta, a); set_avma(av); } } static void gen_BG_init(struct bg_data *bg, GEN E, GEN N, GEN bnd) { bg->E = E; bg->N = N; bg->bnd = bnd; bg->rootbnd = itou(sqrtint(bnd)); bg->p = primes_upto_zv(bg->rootbnd); bg->an = ellanQ_zv(E, bg->rootbnd); } static void gen_BG_rec(void *E, bg_fun *fun, struct bg_data *bg) { long i, j, lp = lg(bg->p)-1; GEN bndov2 = shifti(bg->bnd, -1); pari_sp av = avma, av2; GEN p; forprime_t S; (void)forprime_init(&S, utoipos(bg->p[lp]+1), bg->bnd); av2 = avma; 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->an[pp]; gen_BG_add(E, fun, bg, utoipos(pp), i, stoi(ap), gen_1); set_avma(av2); } if (DEBUGLEVEL) err_printf("2nd stage, looping for p <= %Ps\n", bndov2); while ( (p = forprime_next(&S)) ) { long jmax; GEN ap = ellap(bg->E, p); pari_sp av3 = avma; if (!signe(ap)) continue; jmax = itou( divii(bg->bnd, p) ); /* 2 <= jmax <= el->rootbound */ fun(E, p, ap); 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, n, a); set_avma(av3); } set_avma(av2); if (abscmpii(p, bndov2) >= 0) break; } if (DEBUGLEVEL) err_printf("3nd stage, looping for p <= %Ps\n", bg->bnd); while ( (p = forprime_next(&S)) ) { GEN ap = ellap(bg->E, p); if (!signe(ap)) continue; fun(E, p, ap); set_avma(av2); } set_avma(av); } /****************************************************************** * * L functions of elliptic curves * Pascal Molin (molin.maths@gmail.com) 2014 * ******************************************************************/ struct lcritical { GEN h; /* real */ long cprec; /* computation prec */ long L; /* number of points */ GEN K; /* length of series */ long real; }; static double logboundG0(long e, double aY) { double cla, loggam; cla = 1 + 1/sqrt(aY); if (e) cla = ( cla + 1/(2*aY) ) / (2*sqrt(aY)); loggam = (e) ? M_LN2-aY : -aY + log( log( 1+1/aY) ); return log(cla) + loggam; } static void param_points(GEN N, double Y, double tmax, long bprec, long *cprec, long *L, GEN *K, double *h) { double D, a, aY, X, logM; long d = 2, w = 1; tmax *= d; D = bprec * M_LN2 + M_PI/4*tmax + 2; *cprec = nbits2prec(ceil(D / M_LN2) + 5); a = 2 * M_PI / sqrt(gtodouble(N)); aY = a * cos(M_PI/2*Y); logM = 2*M_LN2 + logboundG0(w+1, aY) + tmax * Y * M_PI/2; *h = ( 2 * M_PI * M_PI / 2 * Y ) / ( D + logM ); X = log( D / a); *L = ceil( X / *h); *K = ceil_safe(dbltor( D / a )); } static GEN vecF2_lk(GEN E, GEN K, GEN rbnd, GEN Q, GEN sleh, long prec) { pari_sp av; long l, L = lg(K)-1; GEN a = ellanQ_zv(E, itos(gel(K,1))); GEN S = cgetg(L+1, t_VEC); for (l = 1; l <= L; l++) gel(S,l) = cgetr(prec); av = avma; for (l = 1; l <= L; l++) { GEN e1, Sl, z, zB; long aB, b, A, B, Kl = itou(gel(K,l)); pari_sp av2; /* FIXME: could reduce prec here (useful for large prec) */ e1 = gel(Q, l); Sl = real_0(prec);; /* baby-step giant step */ B = A = rbnd[l]; z = powersr(e1, B); zB = gel(z, B+1); av2 = avma; for (aB = A*B; aB >= 0; aB -= B) { GEN s = real_0(prec); /* could change also prec here */ for (b = B; b > 0; --b) { long k = aB+b; if (k <= Kl && a[k]) s = addrr(s, mulsr(a[k], gel(z, b+1))); if (gc_needed(av2, 1)) gerepileall(av2, 2, &s, &Sl); } Sl = addrr(mulrr(Sl, zB), s); } affrr(mulrr(Sl, gel(sleh,l)), gel(S, l)); /* to avoid copying all S */ set_avma(av); } return S; } /* Return C, C[i][j] = Q[j]^i, i = 1..nb */ static void baby_init(struct baby_giant *bb, GEN Q, GEN bnd, GEN rbnd, long prec) { long i, j, l = lg(Q); GEN R, C, r0; C = cgetg(l,t_VEC); for (i = 1; i < l; ++i) gel(C, i) = powersr(gel(Q, i), rbnd[i]); R = cgetg(l,t_VEC); r0 = real_0(prec); for (i = 1; i < l; ++i) { gel(R, i) = cgetg(rbnd[i]+1, t_VEC); gmael(R, i, 1) = cgetr(prec); affrr(gmael(C, i, 2),gmael(R, i, 1)); for (j = 2; j <= rbnd[i]; j++) { gmael(R, i, j) = cgetr(prec); affrr(r0, gmael(R, i, j)); } } bb->baby = C; bb->giant = R; bb->bnd = bnd; bb->rbnd = rbnd; } static long baby_size(GEN rbnd, long Ks, long prec) { long i, s, m, l = lg(rbnd); for (s = 0, i = 1; i < l; ++i) s += rbnd[i]; m = 2*s*prec + 3*l + s; if (DEBUGLEVEL) err_printf("ellL1: BG_add: %ld words, ellan: %ld words\n", m, Ks); return m; } static void ellL1_add(void *E, GEN n, GEN a) { pari_sp av = avma; struct baby_giant *bb = (struct baby_giant*) E; long j, l = lg(bb->giant); for (j = 1; j < l; j++) if (cmpii(n, gel(bb->bnd,j)) <= 0) { ulong r, q = uabsdiviu_rem(n, bb->rbnd[j], &r); GEN giant = gel(bb->giant, j), baby = gel(bb->baby, j); affrr(addrr(gel(giant, q+1), mulri(gel(baby, r+1), a)), gel(giant, q+1)); set_avma(av); } else break; } static GEN vecF2_lk_bsgs(GEN E, GEN bnd, GEN rbnd, GEN Q, GEN sleh, GEN N, long prec) { struct bg_data bg; struct baby_giant bb; long k, L = lg(bnd)-1; GEN S; baby_init(&bb, Q, bnd, rbnd, prec); gen_BG_init(&bg, E, N, gel(bnd,1)); gen_BG_rec((void*) &bb, ellL1_add, &bg); S = cgetg(L+1, t_VEC); for (k = 1; k <= L; ++k) { pari_sp av = avma; long j, g = rbnd[k]; GEN giant = gmael(bb.baby, k, g+1), Sl = gmael(bb.giant, k, g); for (j = g-1; j >=1; j--) Sl = addrr(mulrr(Sl, giant), gmael(bb.giant,k,j)); gel(S, k) = gerepileuptoleaf(av, mulrr(gel(sleh,k), Sl)); } return S; } static long _sqrt(GEN x) { pari_sp av = avma; return gc_long(av, itou(sqrtint(x))); } static GEN vecF(struct lcritical *C, GEN E) { pari_sp av = avma; long prec = C->cprec, Ks = itos_or_0(C->K), L = C->L, l; GEN N = ellQ_get_N(E), PiN; GEN e = mpexp(C->h), elh = powersr(e, L-1), Q, bnd, rbnd, vec; PiN = divrr(Pi2n(1,prec), sqrtr_abs(itor(N, prec))); setsigne(PiN, -1); /* - 2Pi/sqrt(N) */ bnd = gpowers0(invr(e), L-1, C->K); /* bnd[i] = K exp(-(i-1)h) */ rbnd = cgetg(L+1, t_VECSMALL); Q = cgetg(L+1, t_VEC); for (l = 1; l <= L; l++) { gel(bnd,l) = ceil_safe(gel(bnd,l)); rbnd[l] = _sqrt(gel(bnd,l)) + 1; gel(Q, l) = mpexp(mulrr(PiN, gel(elh, l))); } if (Ks && baby_size(rbnd, Ks, prec) > (Ks>>1)) vec = vecF2_lk(E, bnd, rbnd, Q, elh, prec); else vec = vecF2_lk_bsgs(E, bnd, rbnd, Q, elh, N, prec); return gerepileupto(av, vec); } /* Lambda function by Fourier inversion. vec is a grid, t a scalar or t_SER */ static GEN glambda(GEN t, GEN vec, GEN h, long real, long prec) { GEN z, r, e = gexp(gmul(mkcomplex(gen_0,h), t), prec); long n = lg(vec)-1, i; r = real == 1? gmul2n(real_i(gel(vec, 1)), -1): gen_0; z = real == 1? e: gmul(powIs(3), e); /* FIXME: summing backward may be more stable */ for (i = 2; i <= n; i++) { r = gadd(r, real_i(gmul(gel(vec,i), z))); if (i < n) z = gmul(z, e); } return gmul(mulsr(4, h), r); } static GEN Lpoints(struct lcritical *C, GEN e, double tmax, long bprec) { double h = 0, Y = .97; GEN N = ellQ_get_N(e); param_points(N, Y, tmax, bprec, &C->cprec, &C->L, &C->K, &h); C->real = ellrootno_global(e); C->h = rtor(dbltor(h), C->cprec); return vecF(C, e); } static GEN Llambda(GEN vec, struct lcritical *C, GEN t, long prec) { GEN lambda = glambda(gprec_w(t, C->cprec), vec, C->h, C->real, C->cprec); return gprec_w(lambda, prec); } /* 2*(2*Pi)^(-s)*gamma(s)*N^(s/2); */ static GEN ellgammafactor(GEN N, GEN s, long prec) { GEN c = gpow(divrr(gsqrt(N,prec), Pi2n(1,prec)), s, prec); return gmul(gmul2n(c,1), ggamma(s, prec)); } static GEN ellL1_eval(GEN e, GEN vec, struct lcritical *C, GEN t, long prec) { GEN g = ellgammafactor(ellQ_get_N(e), gaddgs(gmul(gen_I(),t), 1), prec); return gdiv(Llambda(vec, C, t, prec), g); } static GEN ellL1_der(GEN e, GEN vec, struct lcritical *C, GEN t, long der, long prec) { GEN r = polcoef_i(ellL1_eval(e, vec, C, t, prec), der, 0); r = gmul(r,powIs(C->real == 1 ? -der: 1-der)); return gmul(real_i(r), mpfact(der)); } GEN ellL1(GEN E, long r, long bitprec) { pari_sp av = avma; struct lcritical C; long prec = nbits2prec(bitprec); GEN e, vec, t; if (r < 0) pari_err_DOMAIN("ellL1", "derivative order", "<", gen_0, stoi(r)); e = ellanal_globalred(E, NULL); if (r == 0 && ellrootno_global(e) < 0) { set_avma(av); return gen_0; } vec = Lpoints(&C, e, 0., bitprec); t = r ? scalarser(gen_1, 0, r): zeroser(0, 0); setvalser(t, 1); return gerepileupto(av, ellL1_der(e, vec, &C, t, r, prec)); } GEN ellanalyticrank(GEN E, GEN eps, long bitprec) { pari_sp av = avma, av2; long prec = nbits2prec(bitprec); struct lcritical C; pari_timer ti; GEN e, vec; long rk; if (DEBUGLEVEL) timer_start(&ti); if (!eps) eps = real2n(-bitprec/2+1, DEFAULTPREC); else if (typ(eps) != t_REAL) { eps = gtofp(eps, DEFAULTPREC); if (typ(eps) != t_REAL) pari_err_TYPE("ellanalyticrank", eps); } e = ellanal_globalred(E, NULL); vec = Lpoints(&C, e, 0., bitprec); if (DEBUGLEVEL) timer_printf(&ti, "init L"); av2 = avma; for (rk = C.real>0 ? 0: 1; ; rk += 2) { GEN Lrk; GEN t = rk ? scalarser(gen_1, 0, rk): zeroser(0, 0); setvalser(t, 1); Lrk = ellL1_der(e, vec, &C, t, rk, prec); if (DEBUGLEVEL) timer_printf(&ti, "L^(%ld)=%Ps", rk, Lrk); if (abscmprr(Lrk, eps) > 0) return gerepilecopy(av, mkvec2(stoi(rk), Lrk)); set_avma(av2); } } /* Heegner point computation This section is a C version by Bill Allombert of a GP script by Christophe Delaunay which was based on a GP script by John Cremona. Reference: Henri Cohen's book GTM 239. */ static void heegner_L1_bg(void*E, GEN n, GEN a) { struct baby_giant *bb = (struct baby_giant*) E; long j, l = lg(bb->giant); for (j = 1; j < l; j++) if (cmpii(n, gel(bb->bnd,j)) <= 0) { ulong r, q = uabsdiviu_rem(n, bb->rbnd[j], &r); GEN giant = gel(bb->giant, j), baby = gel(bb->baby, j); gaffect(gadd(gel(giant, q+1), gdiv(gmul(gel(baby, r+1), a), n)), gel(giant, q+1)); } } static void heegner_L1(void*E, GEN n, GEN a) { struct baby_giant *bb = (struct baby_giant*) E; long j, l = lg(bb->giant); for (j = 1; j < l; j++) if (cmpii(n, gel(bb->bnd,j)) <= 0) { ulong r, q = uabsdiviu_rem(n, bb->rbnd[j], &r); GEN giant = gel(bb->giant, j), baby = gel(bb->baby, j); GEN ex = mulreal(gel(baby, r+1), gel(giant, q+1)); affrr(addrr(gel(bb->sum, j), divri(mulri(ex, a), n)), gel(bb->sum, j)); } } /* Return C, C[i][j] = Q[j]^i, i = 1..nb */ static void baby_init2(struct baby_giant *bb, GEN Q, GEN bnd, GEN rbnd, long prec) { long i, j, l = lg(Q); GEN R, C, r0; C = cgetg(l,t_VEC); for (i = 1; i < l; ++i) gel(C, i) = gpowers(gel(Q, i), rbnd[i]); R = cgetg(l,t_VEC); r0 = mkcomplex(real_0(prec),real_0(prec)); for (i = 1; i < l; ++i) { gel(R, i) = cgetg(rbnd[i]+1, t_VEC); gmael(R, i, 1) = cgetc(prec); gaffect(gmael(C, i, 2),gmael(R, i, 1)); for (j = 2; j <= rbnd[i]; j++) { gmael(R, i, j) = cgetc(prec); gaffect(r0, gmael(R, i, j)); } } bb->baby = C; bb->giant = R; bb->bnd = bnd; bb->rbnd = rbnd; } /* Return C, C[i][j] = Q[j]^i, i = 1..nb */ static void baby_init3(struct baby_giant *bb, GEN Q, GEN bnd, GEN rbnd, long prec) { long i, l = lg(Q); GEN R, C, S; C = cgetg(l,t_VEC); for (i = 1; i < l; ++i) gel(C, i) = gpowers(gel(Q, i), rbnd[i]); R = cgetg(l,t_VEC); for (i = 1; i < l; ++i) gel(R, i) = gpowers(gmael(C, i, 1+rbnd[i]), rbnd[i]); S = cgetg(l,t_VEC); for (i = 1; i < l; ++i) { gel(S, i) = cgetr(prec); affrr(real_i(gmael(C, i, 2)), gel(S, i)); } bb->baby = C; bb->giant = R; bb->sum = S; bb->bnd = bnd; bb->rbnd = rbnd; } /* ymin a t_REAL */ static GEN heegner_psi(GEN E, GEN N, GEN points, long bitprec) { pari_sp av = avma, av2; struct baby_giant bb; struct bg_data bg; long l, k, L = lg(points)-1, prec = nbits2prec(bitprec)+EXTRAPREC64; GEN Q, pi2 = Pi2n(1, prec), bnd, rbnd, bndmax; GEN B = divrr(mulur(bitprec,mplog2(DEFAULTPREC)), pi2); rbnd = cgetg(L+1, t_VECSMALL); av2 = avma; bnd = cgetg(L+1, t_VEC); Q = cgetg(L+1, t_VEC); for (l = 1; l <= L; ++l) { gel(bnd,l) = ceil_safe(divrr(B,imag_i(gel(points, l)))); rbnd[l] = itou(sqrtint(gel(bnd,l)))+1; gel(Q, l) = expIxy(pi2, gel(points, l), prec); } gerepileall(av2, 2, &bnd, &Q); bndmax = gel(bnd,vecindexmax(bnd)); gen_BG_init(&bg, E, N, bndmax); if (bitprec >= 1900) { GEN S = cgetg(L+1, t_VEC); baby_init2(&bb, Q, bnd, rbnd, prec); gen_BG_rec((void*)&bb, heegner_L1_bg, &bg); for (k = 1; k <= L; ++k) { pari_sp av2 = avma; long j, g = rbnd[k]; GEN giant = gmael(bb.baby, k, g+1), Sl = real_0(prec); for (j = g; j >=1; j--) Sl = gadd(gmul(Sl, giant), gmael(bb.giant,k,j)); gel(S, k) = gerepileupto(av2, real_i(Sl)); } return gerepileupto(av, S); } else { baby_init3(&bb, Q, bnd, rbnd, prec); gen_BG_rec((void*)&bb, heegner_L1, &bg); return gerepilecopy(av, bb.sum); } } /*Returns lambda_bad list for one prime p, nv = localred(E, p) */ static GEN lambda1(GEN E, GEN nv, GEN p, long prec) { pari_sp av; GEN res, lp; long kod = itos(gel(nv, 2)); if (kod==2 || kod ==-2) return cgetg(1,t_VEC); av = avma; lp = glog(p, prec); if (kod > 4) { long n = Z_pval(ell_get_disc(E), p); long j, m = kod - 4, nl = 1 + (m >> 1L); res = cgetg(nl, t_VEC); for (j = 1; j < nl; j++) gel(res, j) = gmul(lp, gsubgs(gdivgu(sqru(j), n), j)); /* j^2/n - j */ } else if (kod < -4) res = mkvec2(negr(lp), shiftr(mulrs(lp, kod), -2)); else { const long lam[] = {8,9,0,6,0,0,0,3,4}; long m = -lam[kod+4]; res = mkvec(divru(mulrs(lp, m), 6)); } return gerepilecopy(av, res); } static GEN lambdalist(GEN E, long prec) { pari_sp ltop = avma; GEN glob = ellglobalred(E), plist = gmael(glob,4,1), L = gel(glob,5); GEN res, v, D = ell_get_disc(E); long i, j, k, l, m, n, np = lg(plist), lr = 1; v = cgetg(np, t_VEC); for (j = 1, i = 1 ; j < np; ++j) { GEN p = gel(plist, j); if (dvdii(D, sqri(p))) { GEN la = lambda1(E, gel(L,j), p, prec); gel(v, i++) = la; lr *= lg(la); } } np = i; res = cgetg(lr+1, t_VEC); gel(res, 1) = gen_0; n = 1; m = 1; for (j = 1; j < np; ++j) { GEN w = gel(v, j); long lw = lg(w); for (k = 1; k <= n; k++) { GEN t = gel(res, k); for (l = 1, m = n; l < lw; l++, m+=n) gel(res, k + m) = mpadd(t, gel(w, l)); } n = m; } return gerepilecopy(ltop, res); } /* P a t_INT or t_FRAC, return its logarithmic height */ static GEN heightQ(GEN P, long prec) { long s; if (typ(P) == t_FRAC) { GEN a = gel(P,1), b = gel(P,2); P = abscmpii(a,b) > 0 ? a: b; } s = signe(P); if (!s) return real_0(prec); if (s < 0) P = negi(P); return glog(P, prec); } /* t a t_INT or t_FRAC, returns max(1, log |t|), returns a t_REAL */ static GEN logplusQ(GEN t, long prec) { if (typ(t) == t_INT) { if (!signe(t)) return real_1(prec); t = absi_shallow(t); } else { GEN a = gel(t,1), b = gel(t,2); if (abscmpii(a, b) < 0) return real_1(prec); if (signe(a) < 0) t = gneg(t); } return glog(t, prec); } /* See GTM239, p532, Th 8.1.18 * Return M such that h_naive <= M */ GEN hnaive_max(GEN ell, GEN ht) { const long prec = LOWDEFAULTPREC; /* minimal accuracy */ GEN b2 = ell_get_b2(ell), j = ell_get_j(ell); GEN logd = glog(absi_shallow(ell_get_disc(ell)), prec); GEN logj = logplusQ(j, prec); GEN hj = heightQ(j, prec); GEN logb2p = signe(b2)? addrr(logplusQ(gdivgu(b2, 12),prec), mplog2(prec)) : real_1(prec); GEN mu = addrr(divru(addrr(logd, logj),6), logb2p); return addrs(addrr(addrr(ht, divru(hj,12)), mu), 2); } static GEN qfb_root(GEN Q, GEN vDi) { GEN a2 = shifti(gel(Q, 1),1), b = gel(Q, 2); return mkcomplex(gdiv(negi(b),a2),divri(vDi,a2)); } static GEN qimag2(GEN Q) { pari_sp av = avma; GEN z = gdiv(negi(qfb_disc(Q)), shifti(sqri(gel(Q, 1)),2)); return gerepileupto(av, z); } /***************************************************/ /*Routines for increasing the imaginary parts using*/ /*Atkin-Lehner operators */ /***************************************************/ static GEN qfb_mult(GEN Q, GEN a, GEN b, GEN c, GEN d) { GEN A = gel(Q, 1) , B = gel(Q, 2), C = gel(Q, 3), D = qfb_disc(Q); GEN a2 = sqri(a), b2 = sqri(b), c2 = sqri(c), d2 = sqri(d); GEN ad = mulii(d, a), bc = mulii(b, c), e = subii(ad, bc); GEN W1 = addii(addii(mulii(a2, A), mulii(mulii(c, a), B)), mulii(c2, C)); GEN W3 = addii(addii(mulii(b2, A), mulii(mulii(d, b), B)), mulii(d2, C)); GEN W2 = addii(addii(mulii(mulii(shifti(b,1), a), A), mulii(addii(ad, bc), B)), mulii(mulii(shifti(d,1), c), C)); if (!equali1(e)) { W1 = diviiexact(W1,e); W2 = diviiexact(W2,e); W3 = diviiexact(W3,e); } return mkqfb(W1, W2, W3, D); } #ifdef DEBUG static void best_point_old(GEN Q, GEN NQ, GEN f, GEN *u, GEN *v) { long n, k; GEN U, c, d, A = gel(f,1), B = gel(f,2), C = gel(f,3), D = qfb_disc(f); GEN q = mkqfb(mulii(NQ, C), negi(B), diviiexact(A, NQ), D); redimagsl2(q, &U); *u = c = gcoeff(U, 1, 1); *v = d = gcoeff(U, 2, 1); if (equali1(gcdii(mulii(*u, NQ), mulii(*v, Q)))) return; for (n = 1;; n++) { for (k = -n; k <= n; k++) { *u = addis(c, k); *v = addiu(d, n); if (equali1(gcdii(mulii(*u, NQ), mulii(*v, Q)))) return; *v = subiu(d, n); if (equali1(gcdii(mulii(*u, NQ), mulii(*v, Q)))) return; *u = addiu(c, n); *v = addis(d, k); if (equali1(gcdii(mulii(*u, NQ), mulii(*v, Q)))) return; *u = subiu(c, n); if (equali1(gcdii(mulii(*u, NQ), mulii(*v, Q)))) return; } } } /* q(x,y) = ax^2 + bxy + cy^2 */ static GEN qfb_eval(GEN q, GEN x, GEN y) { GEN a = gel(q,1), b = gel(q,2), c = gel(q,3); GEN x2 = sqri(x), y2 = sqri(y), xy = mulii(x,y); return addii(addii(mulii(a, x2), mulii(b,xy)), mulii(c, y2)); } #endif static long nexti(long i) { return i>0 ? -i : 1-i; } /* q0 + i q1 + i^2 q2 */ static GEN qfmin_eval(GEN q0, GEN q1, GEN q2, long i) { return addii(mulis(addii(mulis(q2, i), q1), i), q0); } /* assume a > 0, return gcd(a,b,c) */ static ulong gcduii(ulong a, GEN b, GEN c) { a = ugcdiu(b, a); return a == 1? 1: ugcdiu(c, a); } static void best_point(GEN Q, GEN NQ, GEN f, GEN *pu, GEN *pv) { GEN a = mulii(NQ, gel(f,3)), b = negi(gel(f,2)), c = diviiexact(gel(f,1), NQ); GEN D = qfb_disc(f); GEN U, qr = redimagsl2(mkqfb(a, b, c, D), &U); GEN A = gel(qr,1), B = gel(qr,2), A2 = shifti(A,1), AA4 = sqri(A2); GEN V, best; long y; D = absi_shallow(D); /* 4A qr(x,y) = (2A x + By)^2 + D y^2 * Write x = x0(y) + i, where x0 is an integer minimum * (the smallest in case of tie) of x-> qr(x,y), for given y. * 4A qr(x,y) = ((2A x0 + By)^2 + Dy^2) + 4A i (2A x0 + By) + 4A^2 i^2 * = q0(y) + q1(y) i + q2 i^2 * Loop through (x,y), y>0 by (roughly) increasing values of qr(x,y) */ /* We must test whether [X,Y]~ := U * [x,y]~ satisfy (X NQ, Y Q) = 1 * This is equivalent to (X,Y) = 1 (note that (X,Y) = (x,y)), and * (X, Q) = (Y, NQ) = 1. * We have U * [x0+i, y]~ = U * [x0,y]~ + i U[,1] =: V0 + i U[,1] */ /* try [1,0]~ = first minimum */ V = gel(U,1); /* U *[1,0]~ */ *pu = gel(V,1); *pv = gel(V,2); if (is_pm1(gcdii(*pu, Q)) && is_pm1(gcdii(*pv, NQ))) return; /* try [0,1]~ = second minimum */ V = gel(U,2); /* U *[0,1]~ */ *pu = gel(V,1); *pv = gel(V,2); if (is_pm1(gcdii(*pu, Q)) && is_pm1(gcdii(*pv, NQ))) return; /* (X,Y) = (1, \pm1) always works. Try to do better now */ best = subii(addii(a, c), absi_shallow(b)); *pu = gen_1; *pv = signe(b) < 0? gen_1: gen_m1; for (y = 1;; y++) { GEN Dy2, r, By, x0, q0, q1, V0; long i; if (y > 1) { if (gcduii(y, gcoeff(U,1,1), Q) != 1) continue; if (gcduii(y, gcoeff(U,2,1), NQ) != 1) continue; } Dy2 = mulii(D, sqru(y)); if (cmpii(Dy2, best) >= 0) break; /* we won't improve. STOP */ By = muliu(B,y), x0 = truedvmdii(negi(By), A2, &r); if (cmpii(r, A) >= 0) { x0 = subiu(x0,1); r = subii(r, A2); } /* (2A x + By)^2 + Dy^2, minimal at x = x0. Assume A2 > 0 */ /* r = 2A x0 + By */ q0 = addii(sqri(r), Dy2); /* minimal value for this y, at x0 */ if (cmpii(q0, best) >= 0) continue; /* we won't improve for this y */ q1 = shifti(mulii(A2, r), 1); V0 = ZM_ZC_mul(U, mkcol2(x0, utoipos(y))); for (i = 0;; i = nexti(i)) { pari_sp av2 = avma; GEN x, N = qfmin_eval(q0, q1, AA4, i); if (cmpii(N , best) >= 0) break; x = addis(x0, i); if (ugcdiu(x, y) == 1) { GEN u, v; V = ZC_add(V0, ZC_z_mul(gel(U,1), i)); /* [X, Y] */ u = gel(V,1); v = gel(V,2); if (is_pm1(gcdii(u, Q)) && is_pm1(gcdii(v, NQ))) { *pu = u; *pv = v; best = N; break; } } set_avma(av2); } } #ifdef DEBUG { GEN oldu, oldv, F = mkqfb(a, b, c, qfb_disc(f)); best_point_old(Q, NQ, f, &oldu, &oldv); if (!equalii(oldu, *pu) || !equalii(oldv, *pv)) { if (!equali1(gcdii(mulii(*pu, NQ), mulii(*pv, Q)))) pari_err_BUG("best_point (gcd)"); if (cmpii(qfb_eval(F, *pu,*pv), qfb_eval(F, oldu, oldv)) > 0) { pari_warn(warner, "%Ps,%Ps,%Ps, %Ps > %Ps", Q,NQ,f, mkvec2(*pu,*pv), mkvec2(oldu,oldv)); pari_err_BUG("best_point (too large)"); } } } #endif } static GEN best_lift(GEN Q, GEN NQ, GEN f) { GEN a, b, c, d, dQ, cNQ; best_point(Q, NQ, f, &c, &d); dQ = mulii(d, Q); cNQ = mulii(NQ, c); (void)bezout(dQ, cNQ, &a, &b); return qfb_mult(f, dQ, b, mulii(negi(Q),cNQ), mulii(a,Q)); } static GEN lift_points(GEN listQ, GEN f, GEN *pt, GEN *pQ) { pari_sp av = avma; GEN yf = gen_0, tf = NULL, Qf = NULL; long k, l = lg(listQ); for (k = 1; k < l; ++k) { GEN c = gel(listQ, k), Q = gel(c,1), NQ = gel(c,2); GEN t = best_lift(Q, NQ, f), y = qimag2(t); if (gcmp(y, yf) > 0) { yf = y; Qf = Q; tf = t; } } *pt = tf; *pQ = Qf; return gc_all(av, 3, &yf, pt, pQ); } /***************************/ /* Twists */ /***************************/ static GEN ltwist1(GEN E, GEN d, long bitprec) { pari_sp av = avma; GEN Ed = elltwist(E, d), z = ellL1(Ed, 0, bitprec); obj_free(Ed); return gerepileuptoleaf(av, z); } /* Return O_re*c(E)/(4*O_vol*|E_t|^2) */ static GEN heegner_indexmult(GEN om, long t, GEN tam, long prec) { pari_sp av = avma; GEN Ovr = gabs(imag_i(gel(om, 2)), prec); /* O_vol/O_re, t_REAL */ return gerepileupto(av, divru(divir(tam, Ovr), 4*t*t)); } /* omega(gcd(D, N)), given faN = factor(N) */ static long omega_N_D(GEN faN, ulong D) { GEN P = gel(faN, 1); long i, l = lg(P), w = 0; for (i = 1; i < l; i++) if (dvdui(D, gel(P,i))) w++; return w; } static GEN heegner_indexmultD(GEN faN, GEN a, long D, GEN sqrtD) { pari_sp av = avma; GEN c; long w; switch(D) { case -3: w = 9; break; case -4: w = 4; break; default: w = 1; } c = shifti(stoi(w), omega_N_D(faN,-D)); /* (w(D)/2)^2 * 2^omega(gcd(D,N)) */ return gerepileupto(av, mulri(mulrr(a, sqrtD), c)); } static GEN nf_to_basis(GEN nf, GEN x) { x = nf_to_scalar_or_basis(nf, x); if (typ(x)!=t_COL) x = scalarcol(x, nf_get_degree(nf)); return x; } static GEN etnf_to_basis(GEN et, GEN x) { long i, l = lg(et); GEN V = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(V,i) = nf_to_basis(gel(et,i), x); return shallowconcat1(V); } static GEN etnf_get_M(GEN et) { long i, l = lg(et); GEN V = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(V,i)=nf_get_M(gel(et,i)); return shallowmatconcat(diagonal(V)); } static long etnf_get_varn(GEN et) { return nf_get_varn(gel(et,1)); } static GEN heegner_descent_try_point(GEN nfA, GEN z, GEN den, long prec) { pari_sp av = avma; GEN etal = gel(nfA,1), A = gel(nfA,2), cb = gel(nfA,3); GEN al = gel(nfA,4), th = gel(nfA, 5); GEN et = gel(etal,1), zk = gel(etal, 2), T = gel(etal,3); GEN M = etnf_get_M(et); long i, j, n = lg(th)-1, l = lg(al); GEN u2 = gsqr(gel(cb,1)), r = gel(cb,2); GEN zz = gdiv(gsub(z,r), u2); GEN be = cgetg(n+1, t_COL); for (j = 1; j < l; j++) { GEN aj = gel(al, j), Aj = gel(A,j); for (i = 1; i <= n; i++) gel(be,i) = gsqrt(gmul(gsub(zz, gel(th,i)), gel(aj,i)), prec); for (i = 0; i <= (1<<(n-1))-1; i++) { long eps; GEN s = gmul(den, RgM_solve_realimag(M, be)); GEN S = grndtoi(s, &eps), V, S2; gel(be,1+odd(i)) = gneg(gel(be,1+odd(i))); if (eps > -7) continue; S2 = QXQ_sqr(RgV_RgC_mul(zk, S), T); V = gdiv(QXQ_mul(S2, Aj, T), sqri(den)); if (typ(V) != t_POL || degpol(V) != 1) continue; if (gequalm1(gel(V,3))) return gerepileupto(av,gadd(gmul(gel(V,2),u2),r)); } } return gc_NULL(av); } static GEN heegner_try_point(GEN E, GEN nfA, GEN lambdas, GEN ht, GEN z, long prec) { long l = lg(lambdas); long i, eps; GEN P = real_i(pointell(E, z, prec)), x = gel(P,1); GEN rh = subrr(ht, shiftr(ellheightoo(E, P, prec),1)); for (i = 1; i < l; ++i) { GEN logd = shiftr(gsub(rh, gel(lambdas, i)), -1); GEN d, approxd = gexp(logd, prec); d = grndtoi(approxd, &eps); if (signe(d) > 0 && eps<-10) { GEN X, ylist; if (DEBUGLEVEL > 2) err_printf("\nTrying lambda number %ld, logd=%Ps, approxd=%Ps\n", i, logd, approxd); X = heegner_descent_try_point(nfA, x, d, prec); if (X) { ylist = ellordinate(E, X, prec); if (lg(ylist) > 1) { GEN P = mkvec2(X, gel(ylist, 1)); GEN hp = ellheight(E,P,prec); if (signe(hp) && cmprr(hp, shiftr(ht,1)) < 0 && cmprr(hp, shiftr(ht,-1)) > 0) return P; if (DEBUGLEVEL) err_printf("found non-Heegner point %Ps\n", P); } } } } return NULL; } static GEN heegner_find_point(GEN e, GEN nfA, GEN om, GEN ht, GEN z1, long k, long prec) { GEN lambdas = lambdalist(e, prec); pari_sp av = avma; long m; GEN Ore = gel(om, 1), Oim = gel(om, 2); if (DEBUGLEVEL) err_printf("%ld*%ld multipliers to test: ",k,lg(lambdas)-1); for (m = 0; m < k; m++) { GEN P, z2 = divru(addrr(z1, mulsr(m, Ore)), k); if (DEBUGLEVEL > 2) err_printf("%ld ",m); P = heegner_try_point(e, nfA, lambdas, ht, z2, prec); if (P) return P; if (signe(ell_get_disc(e)) > 0) { z2 = gadd(z2, gmul2n(Oim, -1)); P = heegner_try_point(e, nfA, lambdas, ht, z2, prec); if (P) return P; } set_avma(av); } pari_err_BUG("ellheegner, point not found"); return NULL; /* LCOV_EXCL_LINE */ } /* N > 1, fa = factor(N), return factor(4*N) */ static GEN fa_shift2(GEN fa) { GEN P = gel(fa,1), E = gel(fa,2); if (absequaliu(gcoeff(fa,1,1), 2)) { E = shallowcopy(E); gel(E,1) = addiu(gel(E,1), 2); } else { P = shallowconcat(gen_2, P); E = shallowconcat(gen_2, E); } return mkmat2(P, E); } /* P = prime divisors of N(E). Return the product of primes p in P, a_p != -1 * HACK: restrict to small primes since large ones won't divide our C-long * discriminants */ static GEN get_bad(GEN E, GEN P) { long k, l = lg(P), ibad = 1; GEN B = cgetg(l, t_VECSMALL); for (k = 1; k < l; k++) { GEN p = gel(P,k); long pp = itos_or_0(p); if (!pp) break; if (! equalim1(ellap(E,p))) B[ibad++] = pp; } setlg(B, ibad); return ibad == 1? NULL: zv_prod_Z(B); } /* list of pairs [Q,N/Q], where Q | N and gcd(Q,N/Q) = 1 */ static GEN find_div(GEN N, GEN faN) { GEN listQ = divisors(faN); long j, k, l = lg(listQ); gel(listQ, 1) = mkvec2(gen_1, N); for (j = k = 2; k < l; ++k) { GEN Q = gel(listQ, k), NQ = diviiexact(N, Q); if (is_pm1(gcdii(Q,NQ))) gel(listQ, j++) = mkvec2(Q,NQ); } setlg(listQ, j); return listQ; } static long testDisc(GEN bad, long d) { return !bad || ugcdiu(bad, -d) == 1; } /* bad = product of bad primes. Return the NDISC largest fundamental * discriminants D < d such that (D,bad) = 1 and d is a square mod 4N */ static GEN listDisc(GEN fa4N, GEN bad, long d, long ndisc) { GEN v = cgetg(ndisc+1, t_VECSMALL); pari_sp av = avma; long j = 1; for(;;) { d -= odd(d)? 1: 3; if (testDisc(bad,d) && unegisfundamental(-d) && Zn_issquare(stoi(d), fa4N)) { v[j++] = d; if (j > ndisc) break; } set_avma(av); } set_avma(av); return v; } /* L = vector of [q1,q2] or [q1,q2,q2'] * cd = (b^2 - D)/(4N) */ static void listfill(GEN N, GEN b, GEN c, GEN d, GEN D, GEN L, long *s) { long k, l = lg(L); GEN add, frm2, a = mulii(d, N), V = mkqfb(a,b,c,D), frm = qfbred_i(V); for (k = 1; k < l; ++k) { /* Lk = [v,frm] or [v,frm,frm2] */ GEN Lk = gel(L,k); long i; for (i = 2; i < lg(Lk); i++) /* 1 or 2 elements */ if (gequal(frm, gel(Lk,i))) { GEN v = gel(Lk, 1); if (cmpii(a, gel(v,1)) < 0) gel(Lk,1) = V; return; } } frm2 = qfbred_i(mkqfb(d, negi(b), mulii(c,N), D)); add = gequal(frm, frm2)? mkvec2(V,frm): mkvec3(V,frm,frm2); vectrunc_append(L, add); *s += lg(add) - 2; } /* faN4 = factor(4*N) */ static GEN listheegner(GEN N, GEN faN4, GEN listQ, GEN D) { pari_sp av = avma; const long kmin = 30; long h = itos(quadclassno(D)); GEN ymin, b = Zn_sqrt(D, faN4), L = vectrunc_init(h+1); long l, k, s = 0; for (k = 0; k < kmin || s < h; k++) { GEN bk = addii(b, mulsi(2*k, N)); GEN C = diviiexact(shifti(subii(sqri(bk), D), -2), N); GEN div = divisors(C); long i, l = lg(div); for (i = 1; i < l; i++) { GEN d = gel(div, i), c = gel(div, l-i); /* cd = C */ listfill(N, bk, c, d, D, L, &s); } } l = lg(L); ymin = NULL; for (k = 1; k < l; k++) { GEN t, Q, Lk = gel(L,k), f = gel(Lk,1); GEN y = lift_points(listQ, f, &t, &Q); gel(L, k) = mkvec3(t, stoi(lg(Lk) - 2), Q); if (!ymin || gcmp(y, ymin) < 0) ymin = y; } if (DEBUGLEVEL > 1) err_printf("Disc %Ps : N*ymin = %Pg\n", D, gmul(gsqrt(ymin, DEFAULTPREC),N)); return gerepilecopy(av, mkvec3(ymin, L, D)); } /* Q | N, P = prime divisors of N, R[i] = local epsilon-factor at P[i]. * Return \prod_{p | Q} R[i] */ static long rootno(GEN Q, GEN P, GEN R) { long s = 1, i, l = lg(P); for (i = 1; i < l; i++) if (dvdii(Q, gel(P,i))) s *= R[i]; return s; } static void heegner_find_disc(GEN *points, GEN *coefs, long *pind, GEN E, GEN indmult, long ndisc, long prec) { long d = 0; GEN faN4, bad, N, faN, listQ, listR; ellQ_get_Nfa(E, &N, &faN); faN4 = fa_shift2(faN); listQ = find_div(N, faN); bad = get_bad(E, gel(faN, 1)); listR = gel(obj_check(E, Q_ROOTNO), 2); for(;;) { pari_sp av = avma; GEN list, listD = listDisc(faN4, bad, d, ndisc); long k, l = lg(listD); list = cgetg(l, t_VEC); for (k = 1; k < l; ++k) gel(list, k) = listheegner(N, faN4, listQ, stoi(listD[k])); list = vecsort0(list, gen_1, 0); for (k = l-1; k > 0; --k) { long bprec = 8; GEN Lk = gel(list,k), D = gel(Lk,3); GEN sqrtD = sqrtr_abs(itor(D, prec)); /* sqrt(|D|) */ GEN indmultD = heegner_indexmultD(faN, indmult, itos(D), sqrtD); do { GEN mulf, indr; pari_timer ti; if (DEBUGLEVEL) timer_start(&ti); mulf = ltwist1(E, D, bprec+expo(indmultD)); if (DEBUGLEVEL) timer_printf(&ti,"ellL1twist"); indr = mulrr(indmultD, mulf); if (DEBUGLEVEL) err_printf("Disc = %Ps, Index^2 = %Ps\n", D, indr); if (signe(indr)>0 && expo(indr) >= -1) /* indr >=.5 */ { long e, i, l; GEN pts, cfs, L, indi = grndtoi(sqrtr_abs(indr), &e); if (e > expi(indi)-7) { bprec++; pari_warn(warnprec, "ellL1",bprec); continue; } *pind = itos(indi); L = gel(Lk, 2); l = lg(L); pts = cgetg(l, t_VEC); cfs = cgetg(l, t_VECSMALL); for (i = 1; i < l; ++i) { GEN P = gel(L,i), z = gel(P,2), Q = gel(P,3); /* [1 or 2, Q] */ long c; gel(pts, i) = qfb_root(gel(P,1), sqrtD); c = rootno(Q, gel(faN,1), listR); if (!equali1(z)) c *= 2; cfs[i] = c; } if (DEBUGLEVEL) err_printf("N = %Ps, ymin*N = %Ps\n",N, gmul(gsqrt(gel(Lk, 1), prec),N)); *coefs = cfs; *points = pts; return; } } while(0); } d = listD[l-1]; set_avma(av); } } GEN ellanal_globalred_all(GEN e, GEN *cb, GEN *N, GEN *tam) { GEN E = ellanal_globalred(e, cb), red = obj_check(E, Q_GLOBALRED); *N = gel(red, 1); *tam = gel(red,2); if (signe(ell_get_disc(E))>0) *tam = shifti(*tam,1); return E; } static GEN vecelnfembed(GEN x, GEN M, GEN et) { pari_APPLY_same(gmul(M, etnf_to_basis(et, gel(x,i)))) } static GEN QXQV_inv(GEN x, GEN T) { pari_APPLY_same(QXQ_inv(gel(x,i), T)) } static GEN etnfnewprec(GEN x, long prec) { pari_APPLY_same(nfnewprec(gel(x,i),prec)) } static GEN vec_etnf_to_basis(GEN et, GEN x) { pari_APPLY_same(etnf_to_basis(et,gel(x,i))) } static GEN makenfA(GEN sel, GEN A, GEN cb) { GEN etal = gel(sel,1), T = gel(etal,3); GEN et = gel(etal,1), M = etnf_get_M(et); long v = etnf_get_varn(et); GEN al = vecelnfembed(A, M, et); GEN th = gmul(M, etnf_to_basis(et, pol_x(v))); return mkvec5(etal,QXQV_inv(A, T),cb,al,th); } GEN ellheegner(GEN E) { pari_sp av = avma; GEN z, P, ht, points, coefs, s, om, indmult; GEN sel, etal, et, cbb, A, dAi, T, Ag, At; long ind, indx, lint, k, l, wtor, etor, ndisc, ltors2, selrank; long bitprec = 16, prec = nbits2prec(bitprec) + EXTRAPRECWORD; pari_timer ti; GEN N, cb, tam, torsion, nfA; E = ellanal_globalred_all(E, &cb, &N, &tam); if (ellrootno_global(E) == 1) pari_err_DOMAIN("ellheegner", "(analytic rank)%2","=",gen_0,E); torsion = elltors(E); wtor = itos( gel(torsion,1) ); /* #E(Q)_tor */ etor = wtor > 1? itou(gmael(torsion, 2, 1)): 1; /* exponent of E(Q)_tor */ sel = ell2selmer_basis(E, &cbb, prec); etal = gel(sel,1); A = gel(sel,2); et = gel(etal,1); T = gel(etal,3); ltors2 = lg(et)-2; selrank = lg(A)-1; Ag = selrank > ltors2+1 ? pol_1(etnf_get_varn(et)): gel(A,selrank); At = vecslice(A,1,ltors2); dAi = gsupnorm(vec_etnf_to_basis(et,A),prec); while (1) { GEN hnaive, l1; long bitneeded; if (DEBUGLEVEL) timer_start(&ti); l1 = ellL1(E, 1, bitprec); if (DEBUGLEVEL) timer_printf(&ti,"ellL1"); if (expo(l1) < 1 - bitprec/2) pari_err_DOMAIN("ellheegner", "analytic rank",">",gen_1,E); om = ellR_omega(E,prec); ht = divrr(mulru(l1, wtor * wtor), mulri(gel(om,1), tam)); if (DEBUGLEVEL) err_printf("Expected height=%Ps\n", ht); hnaive = hnaive_max(E, ht); if (DEBUGLEVEL) err_printf("Naive height <= %Ps\n", hnaive); hnaive = gadd(shiftr(hnaive,-1),glog(dAi,prec)); bitneeded = itos(gceil(divrr(hnaive, mplog2(prec)))) + 32; if (DEBUGLEVEL) err_printf("precision = %ld\n", bitneeded); if (bitprec>=bitneeded) break; bitprec = bitneeded; prec = nbits2prec(bitprec) + EXTRAPRECWORD; } indmult = heegner_indexmult(om, wtor, tam, prec); ndisc = maxss(10, (long) rtodbl(ht)/10); heegner_find_disc(&points, &coefs, &ind, E, indmult, ndisc, prec); if (DEBUGLEVEL) timer_start(&ti); s = heegner_psi(E, N, points, bitprec); if (DEBUGLEVEL) timer_printf(&ti,"heegner_psi"); l = lg(points); z = mulsr(coefs[1], gel(s, 1)); for (k = 2; k < l; ++k) z = addrr(z, mulsr(coefs[k], gel(s, k))); z = gsub(z, gmul(gel(om,1), ground(gdiv(z, gel(om,1))))); if (DEBUGLEVEL) err_printf("z=%.*Pg\n",nbits2ndec(bitprec), z); lint = wtor > 1 ? ugcd(ind, etor): 1; indx = lint*2*ind; if (vals(indx) >= vals(etor)) A = mkvec(Ag); else A = mkvec2(Ag, QXQ_mul(Ag, gel(At,1), T)); gmael(sel,1,1) = etnfnewprec(et, prec); nfA = makenfA(sel, A, cbb); P = heegner_find_point(E, nfA, om, ht, gmulsg(2*lint, z), indx, prec); if (DEBUGLEVEL) timer_printf(&ti,"heegner_find_point"); if (cb) P = ellchangepointinv(P, cb); return gerepilecopy(av, P); } /* Modular degree */ static GEN ellisobound(GEN e) { GEN M = gel(ellisomat(e,0,1),2); return vecmax(gel(M,1)); } /* 4Pi^2 / E.area */ static GEN getA(GEN E, long prec) { return mpdiv(sqrr(Pi2n(1,prec)), ellR_area(E, prec)); } /* Modular degree of elliptic curve e over Q, assuming Manin constant = 1 * (otherwise multiply by square of Manin constant). */ GEN ellmoddegree(GEN E) { pari_sp av = avma; GEN N, tam, mc2, d; long b; E = ellanal_globalred_all(E, NULL, &N, &tam); mc2 = sqri(ellisobound(E)); b = expi(mulii(N, mc2)) + maxss(0, expo(getA(E, LOWDEFAULTPREC))) + 16; for(;;) { long prec = nbits2prec(b), e, s; GEN deg = mulri(mulrr(lfunellmfpeters(E, b), getA(E, prec)), mc2); d = grndtoi(deg, &e); if (DEBUGLEVEL) err_printf("ellmoddegree: %Ps, bit=%ld, err=%ld\n",deg,b,e); s = expo(deg); if (e <= -8 && s <= b-8) return gerepileupto(av, gdiv(d,mc2)); b = maxss(s, b+e) + 16; } } pari-2.17.2/src/basemath/polarit1.c0000644000175000017500000004254414760123736015460 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; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /***********************************************************************/ /** **/ /** ARITHMETIC OPERATIONS ON POLYNOMIALS **/ /** (first part) **/ /** **/ /***********************************************************************/ #include "pari.h" #include "paripriv.h" /*******************************************************************/ /* */ /* POLYNOMIAL EUCLIDEAN DIVISION */ /* */ /*******************************************************************/ /* 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, a, T = gel(x,1); if (RgX_equal(T, y)) return gcopy(x); z = cgetg(3,t_POLMOD); T = RgX_gcd(T,y); a = gel(x,2); gel(z,1) = T; gel(z,2) = (typ(a)==t_POL && varn(a)==varn(T))? RgX_rem(a, T): gcopy(a); return z; } /* x,y two "scalars", return 0 with type info */ static GEN rem_scal_scal(GEN x, GEN y) { pari_sp av = avma; GEN z = gadd(gmul(gen_0,x), gmul(gen_0,y)); if (gequal0(y)) pari_err_INV("grem",y); return gerepileupto(av, simplify(z)); } /* x pol, y "scalar", return 0 with type info */ static GEN rem_pol_scal(GEN x, GEN y) { pari_sp av = avma; if (gequal0(y)) pari_err_INV("grem",y); return gerepileupto(av, simplify(gmul(Rg_get_0(x),y))); } /* x "scalar", y pol, return x % y with type info */ static GEN rem_scal_pol(GEN x, GEN y) { if (degpol(y)) { if (!signe(y)) pari_err_INV("grem",y); return gmul(x, Rg_get_1(y)); } y = gel(y,2); return rem_scal_scal(x,y); } GEN poldivrem(GEN x, GEN y, GEN *pr) { const char *f = "euclidean division"; long tx = typ(x), ty = typ(y), vx = gvar(x), vy = gvar(y); GEN z; if (!is_extscalar_t(tx) || !is_extscalar_t(ty)) pari_err_TYPE2(f,x,y); if (vx == vy && ((tx==t_POLMOD) ^ (ty==t_POLMOD))) pari_err_TYPE2(f,x,y); if (ty != t_POL || varncmp(vx, vy) < 0) /* y "scalar" */ { if (!pr || pr == ONLY_DIVIDES) return gdiv(x,y); if (tx != t_POL || varncmp(vy, vx) < 0) /* x "scalar" */ z = rem_scal_scal(x,y); else z = rem_pol_scal(x,y); if (pr == ONLY_REM) return z; *pr = z; return gdiv(x,y); } if (tx != t_POL || varncmp(vx, vy) > 0) /* x "scalar" */ { if (!degpol(y)) /* constant t_POL, treat as scalar */ { y = gel(y,2); if (!pr || pr == ONLY_DIVIDES) gdiv(x,y); z = rem_scal_scal(x,y); if (pr == ONLY_REM) return z; *pr = z; return gdiv(x,y); } if (!signe(y)) pari_err_INV("poldivrem",y); if (!pr || pr == ONLY_DIVIDES) return gequal0(x)? Rg_get_0(y): NULL; z = gmul(x, Rg_get_1(y)); if (pr == ONLY_REM) return z; *pr = z; return Rg_get_0(y); } return RgX_divrem(x,y,pr); } GEN gdeuc(GEN x, GEN y) { const char *f = "euclidean division"; long tx = typ(x), ty = typ(y), vx = gvar(x), vy = gvar(y); if (!is_extscalar_t(tx) || !is_extscalar_t(ty)) pari_err_TYPE2(f,x,y); if (vx == vy && ((tx==t_POLMOD) ^ (ty==t_POLMOD))) pari_err_TYPE2(f,x,y); if (ty != t_POL || varncmp(vx, vy) < 0) return gdiv(x,y); /* y "scalar" */ if (tx != t_POL || varncmp(vx, vy) > 0) { /* x "scalar" */ if (!signe(y)) pari_err_INV("gdeuc",y); if (!degpol(y)) return gdiv(x, gel(y,2)); /* constant */ return Rg_get_0(y); } return RgX_div(x,y); } GEN grem(GEN x, GEN y) { const char *f = "euclidean division"; long tx = typ(x), ty = typ(y), vx = gvar(x), vy = gvar(y); if (ty == t_POL) { if (varncmp(vx,vy) >= 0) { pari_sp av; GEN z; if (!signe(y)) pari_err_INV("grem",y); if (vx != vy) return rem_scal_pol(x,y); switch(tx) { case t_POLMOD: return polmod_mod(x,y); case t_POL: return RgX_rem(x,y); case t_RFRAC: { GEN a = gel(x,1), b = gel(x,2), p, pol; if (typ(a) == t_POL && RgX_is_ZX(y) && ZX_is_monic(y)) { long pa, t = RgX_type2(a,b, &p,&pol,&pa); if (t == t_FRAC || t == t_INT) return QXQ_div(a, b, y); } av = avma; z = RgXQ_inv(RgX_rem(b, y), y); return gerepileupto(av, grem(gmul(a, z), y)); } case t_SER: if (RgX_is_monomial(y)) { if (lg(x)-2 + valser(x) < degpol(y)) pari_err_OP("%",x,y); av = avma; return gerepileupto(av, gmod(ser2rfrac_i(x), y)); } default: pari_err_TYPE2("%",x,y); } } else switch(tx) { case t_POL: case t_RFRAC: return rem_pol_scal(x,y); default: pari_err_TYPE2("%",x,y); } } if (!is_extscalar_t(tx) || !is_extscalar_t(ty)) pari_err_TYPE2(f,x,y); if (vx == vy && ty==t_POLMOD) pari_err_TYPE2(f,x,y); if (tx != t_POL || varncmp(vx,vy) > 0) { /* x a "scalar" */ if (ty != t_POL || varncmp(vx, vy) < 0) return rem_scal_scal(x,y); return rem_scal_pol(x,y); } if (ty != t_POL || varncmp(vx, vy) < 0) /* y a "scalar" */ return rem_pol_scal(x,y); return RgX_rem(x,y); } /*******************************************************************/ /* */ /* CONVERSIONS RELATED TO p-ADICS */ /* */ /*******************************************************************/ /* x t_PADIC, p a prime or NULL (unset). Consistency check */ static void check_padic_p(GEN x, GEN p) { GEN q = gel(x,2); if (p && !equalii(p, q)) pari_err_MODULUS("Zp_to_Z", p,q); } /* shallow */ static GEN Zp_to_Z(GEN x, GEN p) { switch(typ(x)) { case t_INT: break; case t_PADIC: check_padic_p(x, p); x = gtrunc(x); break; default: pari_err_TYPE("Zp_to_Z",x); } return x; } /* shallow */ static GEN ZpX_to_ZX(GEN f, GEN p) { long i, l = lg(f); GEN F = cgetg_copy(f, &l); F[1] = f[1]; for (i=2; i= prec */ GEN ZX_Zp_root(GEN f, GEN a, GEN p, long prec) { GEN z, R; long i, j, k; if (signe(FpX_eval(FpX_deriv(f, p), a, p))) { /* simple zero mod p, go all the way to p^prec */ if (prec > 1) a = ZpX_liftroot(f, a, p, prec); return mkcol(a); } f = ZX_unscale_div(ZX_translate(f,a), p); /* f(pX + a) / p */ (void)ZX_pvalrem(f,p,&f); 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); } /* assume f(a) = 0 (mod T,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); } f = RgX_unscale(RgXQX_translate(f, a, T), p); f = RgX_Rg_div(f, powiu(p, gvaluation(f,p))); z = cgetg(degpol(f)+1,t_COL); R = FpXQX_roots(FqX_red(f,T,p), T, p); lR = lg(R); for(j=i=1; i n2, is undefined! */ GEN iLP; /* iLP[p] = i such that LV[p] = [LP[i],...] */ GEN L_jid; /* indexes of "useful" prime ideals for rnd_rel */ long KC, KCZ, KCZ2; GEN prodZ; /* product of the primes in KCZ*/ GEN subFB; /* LP o subFB = part of FB used to build random relations */ int sfb_chg; /* need to change subFB ? */ GEN perm; /* permutation of LP used to represent relations [updated by hnfspec/hnfadd: dense rows come first] */ GEN idealperm; /* permutation of ideals under field automorphisms */ GEN minidx; /* minidx[i] min ideal in orbit of LP[i] under field autom */ subFB_t *allsubFB; /* all subFB's used */ GEN embperm; /* permutations of the complex embeddings */ long MAXDEPSIZESFB; /* # trials before increasing subFB */ long MAXDEPSFB; /* MAXDEPSIZESFB / DEPSFBDIV, # trials befor rotating subFB */ double ballvol; } 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 nonzero 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 emb; /* archimedean embeddings */ GEN junk[2]; /*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 we allow */ GEN basis; /* mod p basis (generating family actually) */ ulong missing; /* missing vectors in generating family above */ } RELCACHE_t; typedef struct FP_t { double **q, *v, *y, *z; GEN x; } FP_t; static void wr_rel(GEN e) { long i, l = lg(e); for (i = 1; i < l; i++) if (e[i]) err_printf("%ld^%ld ",i,e[i]); } static void dbg_newrel(RELCACHE_t *cache) { if (DEBUGLEVEL > 1) { err_printf("\n++++ cglob = %ld\nrel = ", cache->last - cache->base); wr_rel(cache->last->R); err_printf("\n"); } else err_printf("%ld ", cache->last - cache->base); } 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) gunclone(rel->m); } pari_free((void*)M->base); M->base = NULL; } static void delete_FB(FB_t *F) { subFB_t *s, *sold; for (s = F->allsubFB; s; s = sold) { sold = s->old; pari_free(s); } gunclone(F->minidx); gunclone(F->idealperm); } static void reallocate(RELCACHE_t *M, long len) { M->len = len; if (!M->base) M->base = (REL_t*)pari_malloc((len+1) * sizeof(REL_t)); else { size_t l = M->last - M->base, c = M->chk - M->base, e = M->end - M->base; pari_realloc_ip((void**)&M->base, (len+1) * sizeof(REL_t)); M->last = M->base + l; M->chk = M->base + c; M->end = M->base + e; } } #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 = gel(F->LV,p); return (isclone(LP) && t == F->iLP[p] + lg(LP)-1); } static void assign_subFB(FB_t *F, GEN yes, long iyes) { long i, lv = sizeof(subFB_t) + iyes*sizeof(long); /* for struct + GEN */ subFB_t *s = (subFB_t *)pari_malloc(lv); s->subFB = (GEN)&s[1]; s->old = F->allsubFB; F->allsubFB = s; for (i = 0; i < iyes; i++) s->subFB[i] = yes[i]; F->subFB = s->subFB; F->MAXDEPSIZESFB = (iyes-1) * DEPSIZESFBMULT; F->MAXDEPSFB = F->MAXDEPSIZESFB / DEPSFBDIV; } /* Determine the permutation of the ideals made by each field automorphism */ static GEN FB_aut_perm(FB_t *F, GEN auts, GEN cyclic) { long i, j, m, KC = F->KC, nauts = lg(auts)-1; GEN minidx, perm = zero_Flm_copy(KC, nauts); if (!nauts) { F->minidx = gclone(identity_zv(KC)); return cgetg(1,t_MAT); } minidx = zero_Flv(KC); 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_smallp(P); f = pr_get_f(P); do { if (++i > KC) break; P = gel(F->LP, i); } while (p == pr_get_smallp(P) && 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] && ZC_prdvd(img, gel(F->LP, l))) { seen[l] = 1; permk0[j] = l; break; } } set_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; minidx[j] = j; for (i = 1; i <= nauts; i++) minidx[coeff(perm, j, i)] = j; } F->minidx = gclone(minidx); return perm; } /* 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 void subFBgen(FB_t *F, 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 = gel(F->LV,F->FB[i]); long l = lg(LP); for (j = 1; j < l; j++) { GEN P = gel(LP,j); k++; gel(y,k) = pr_norm(P); gel(F->LP,k) = P; } } /* perm sorts LP by increasing norm */ perm = indexsort(y); no = cgetg(lv, t_VECSMALL); ino = 1; yes = cgetg(lv, t_VECSMALL); iyes = 1; prod = 1.0; for (i = 1; i < lv; i++) { long t = perm[i]; if (bad_subFB(F, t)) { no[ino++] = t; continue; } yes[iyes++] = t; prod *= (double)itos(gel(y,t)); if (iyes > minsFB && prod > PROD) break; } setlg(yes, iyes); for (j=1; jperm[j] = yes[j]; for (i=1; iperm[j] = no[i]; for ( ; jperm[j] = perm[j]; F->allsubFB = NULL; F->idealperm = gclone(FB_aut_perm(F, auts, cyclic)); if (iyes) assign_subFB(F, yes, iyes); set_avma(av); } static int subFB_change(FB_t *F) { long i, iyes, minsFB, lv = F->KC + 1, l = lg(F->subFB)-1; pari_sp av = avma; GEN yes, L_jid = F->L_jid, present = zero_zv(lv-1); switch (F->sfb_chg) { case sfb_INCREASE: minsFB = l + 1; break; default: minsFB = l; break; } yes = cgetg(minsFB+1, t_VECSMALL); iyes = 1; if (L_jid) { for (i = 1; i < lg(L_jid); i++) { long l = L_jid[i]; if (bad_subFB(F, l)) continue; yes[iyes++] = l; present[l] = 1; if (iyes > minsFB) break; } } else i = 1; if (iyes <= minsFB) { for ( ; i < lv; i++) { long l = F->perm[i]; if (present[l] || bad_subFB(F, l)) continue; yes[iyes++] = l; if (iyes > minsFB) break; } if (i == lv) return 0; } if (zv_equal(F->subFB, yes)) { if (DEBUGLEVEL) err_printf("\n*** NOT Changing sub factor base\n"); } else { if (DEBUGLEVEL) err_printf("\n*** Changing sub factor base\n"); assign_subFB(F, yes, iyes); } F->sfb_chg = 0; return gc_bool(av, 1); } /* make sure enough room to store n more relations */ static void pre_allocate(RELCACHE_t *cache, size_t n) { size_t len = (cache->last - cache->base) + n; if (len >= cache->len) reallocate(cache, len << 1); } void init_GRHcheck(GRHcheck_t *S, long N, long R1, double LOGD) { const double c1 = M_PI*M_PI/2; const double c2 = 3.663862376709; const double c3 = 3.801387092431; /* Euler + log(8*Pi)*/ S->clone = 0; S->cN = R1*c2 + N*c1; S->cD = LOGD - N*c3 - R1*M_PI/2; S->maxprimes = 16000; /* sufficient for LIMC=176081*/ S->primes = (GRHprime_t*)pari_malloc(S->maxprimes*sizeof(*S->primes)); S->nprimes = 0; S->limp = 0; u_forprime_init(&S->P, 2, ULONG_MAX); } void free_GRHcheck(GRHcheck_t *S) { if (S->clone) { long i = S->nprimes; GRHprime_t *pr; for (pr = S->primes, i = S->nprimes; i > 0; pr++, i--) gunclone(pr->dec); } pari_free(S->primes); } int GRHok(GRHcheck_t *S, double L, double SA, double SB) { return (S->cD + (S->cN + 2*SB) / L - 2*SA < -1e-8); } /* Return factorization pattern of p: [f,n], where n[i] primes of * residue degree f[i] */ static GEN get_fs(GEN nf, GEN P, GEN index, ulong p) { long j, k, f, n, l; GEN fs, ns; if (umodiu(index, p)) { /* easy case: p does not divide index */ GEN F = Flx_degfact(ZX_to_Flx(P,p), p); fs = gel(F,1); l = lg(fs); } else { GEN F = idealprimedec(nf, utoipos(p)); l = lg(F); fs = cgetg(l, t_VECSMALL); for (j = 1; j < l; j++) fs[j] = pr_get_f(gel(F,j)); } ns = cgetg(l, t_VECSMALL); f = fs[1]; n = 1; for (j = 2, k = 1; j < l; j++) if (fs[j] == f) n++; else { ns[k] = n; fs[k] = f; k++; f = fs[j]; n = 1; } ns[k] = n; fs[k] = f; k++; setlg(fs, k); setlg(ns, k); return mkvec2(fs,ns); } /* cache data for all rational primes up to the LIM */ static void cache_prime_dec(GRHcheck_t *S, ulong LIM, GEN nf) { pari_sp av = avma; GRHprime_t *pr; GEN index, P; double nb; if (S->limp >= LIM) return; S->clone = 1; nb = primepi_upper_bound((double)LIM); /* #{p <= LIM} <= nb */ GRH_ensure(S, nb+1); /* room for one extra prime */ P = nf_get_pol(nf); index = nf_get_index(nf); for (pr = S->primes + S->nprimes;;) { ulong p = u_forprime_next(&(S->P)); pr->p = p; pr->logp = log((double)p); pr->dec = gclone(get_fs(nf, P, index, p)); S->nprimes++; pr++; set_avma(av); /* store up to nextprime(LIM) included */ if (p >= LIM) { S->limp = p; break; } } } static double tailresback(long R1, long R2, double rK, long C, double C2, double C3, double r1K, double r2K, double logC, double logC2, double logC3) { const double rQ = 1.83787706641; const double r1Q = 1.98505372441; const double r2Q = 1.07991541347; return fabs((R1+R2-1)*(12*logC3+4*logC2-9*logC-6)/(2*C*logC3) + (rK-rQ)*(6*logC2 + 5*logC + 2)/(C*logC3) - R2*(6*logC2+11*logC+6)/(C2*logC2) - 2*(r1K-r1Q)*(3*logC2 + 4*logC + 2)/(C2*logC3) + (R1+R2-1)*(12*logC3+40*logC2+45*logC+18)/(6*C3*logC3) + (r2K-r2Q)*(2*logC2 + 3*logC + 2)/(C3*logC3)); } static double tailres(long R1, long R2, double al2K, double rKm, double rKM, double r1Km, double r1KM, double r2Km, double r2KM, double C, long i) { /* C >= 3*2^i, lower bound for eint1(log(C)/2) */ /* for(i=0,30,print(eint1(log(3*2^i)/2))) */ static double tab[] = { 0.50409264803, 0.26205336997, 0.14815491171, 0.08770540561, 0.05347651832, 0.03328934284, 0.02104510690, 0.01346475900, 0.00869778586, 0.00566279855, 0.00371111950, 0.00244567837, 0.00161948049, 0.00107686891, 0.00071868750, 0.00048119961, 0.00032312188, 0.00021753772, 0.00014679818, 9.9272855581E-5, 6.7263969995E-5, 4.5656812967E-5, 3.1041124593E-5, 2.1136011590E-5, 1.4411645381E-5, 9.8393304088E-6, 6.7257395409E-6, 4.6025878272E-6, 3.1529719271E-6, 2.1620490021E-6, 1.4839266071E-6 }; const double logC = log(C), logC2 = logC*logC, logC3 = logC*logC2; const double C2 = C*C, C3 = C*C2; double E1 = i >30? 0: tab[i]; return al2K*((33*logC2+22*logC+8)/(8*logC3*sqrt(C))+15*E1/16) + maxdd(tailresback(rKm,r1KM,r2Km, C,C2,C3,R1,R2,logC,logC2,logC3), tailresback(rKM,r1Km,r2KM, C,C2,C3,R1,R2,logC,logC2,logC3))/2 + ((R1+R2-1)*4*C+R2)*(C2+6*logC)/(4*C2*C2*logC2); } static long primeneeded(long N, long R1, long R2, double LOGD) { const double lim = 0.25; /* should be log(2)/2 == 0.34657... */ const double al2K = 0.3526*LOGD - 0.8212*N + 4.5007; const double rKm = -1.0155*LOGD + 2.1042*N - 8.3419; const double rKM = -0.5 *LOGD + 1.2076*N + 1; const double r1Km = - LOGD + 1.4150*N; const double r1KM = - LOGD + 1.9851*N; const double r2Km = - LOGD + 0.9151*N; const double r2KM = - LOGD + 1.0800*N; long Cmin = 3, Cmax = 3, i = 0; while (tailres(R1, R2, al2K, rKm, rKM, r1Km, r1KM, r2Km, r2KM, Cmax, i) > lim) { Cmin = Cmax; Cmax *= 2; i++; } i--; while (Cmax - Cmin > 1) { long t = (Cmin + Cmax)/2; if (tailres(R1, R2, al2K, rKm, rKM, r1Km, r1KM, r2Km, r2KM, t, i) > lim) Cmin = t; else Cmax = t; } return Cmax; } /* ~ 1 / Res(s = 1, zeta_K) */ static GEN compute_invres(GRHcheck_t *S, long LIMC) { pari_sp av = avma; double loginvres = 0.; GRHprime_t *pr; long i; double logLIMC = log((double)LIMC); double logLIMC2 = logLIMC*logLIMC, denc; double c0, c1, c2; denc = 1/(pow((double)LIMC, 3.) * logLIMC * logLIMC2); c2 = ( logLIMC2 + 3 * logLIMC / 2 + 1) * denc; denc *= LIMC; c1 = (3 * logLIMC2 + 4 * logLIMC + 2) * denc; denc *= LIMC; c0 = (3 * logLIMC2 + 5 * logLIMC / 2 + 1) * denc; for (pr = S->primes, i = S->nprimes; i > 0; pr++, i--) { GEN dec, fs, ns; long addpsi; double addpsi1, addpsi2; double logp = pr->logp, NPk; long j, k, limp = logLIMC/logp; ulong p = pr->p, p2 = p*p; if (limp < 1) break; dec = pr->dec; fs = gel(dec, 1); ns = gel(dec, 2); loginvres += 1./p; /* NB: limp = 1 nearly always and limp > 2 for very few primes */ for (k=2, NPk = p; k <= limp; k++) { NPk *= p; loginvres += 1/(k * NPk); } addpsi = limp; addpsi1 = p *(pow((double)p , (double)limp)-1)/(p -1); addpsi2 = p2*(pow((double)p2, (double)limp)-1)/(p2-1); j = lg(fs); while (--j > 0) { long f, nb, kmax; double NP, NP2, addinvres; f = fs[j]; if (f > limp) continue; nb = ns[j]; NP = pow((double)p, (double)f); addinvres = 1/NP; kmax = limp / f; for (k=2, NPk = NP; k <= kmax; k++) { NPk *= NP; addinvres += 1/(k*NPk); } NP2 = NP*NP; loginvres -= nb * addinvres; addpsi -= nb * f * kmax; addpsi1 -= nb*(f*NP *(pow(NP ,(double)kmax)-1)/(NP -1)); addpsi2 -= nb*(f*NP2*(pow(NP2,(double)kmax)-1)/(NP2-1)); } loginvres -= (addpsi*c0 - addpsi1*c1 + addpsi2*c2)*logp; } return gerepileuptoleaf(av, mpexp(dbltor(loginvres))); } static long nthideal(GRHcheck_t *S, GEN nf, long n) { pari_sp av = avma; GEN P = nf_get_pol(nf); ulong p = 0, *vecN = (ulong*)const_vecsmall(n, LONG_MAX); long i, N = poldegree(P, -1); for (i = 0; ; i++) { GRHprime_t *pr; GEN fs; cache_prime_dec(S, p+1, nf); pr = S->primes + i; fs = gel(pr->dec, 1); p = pr->p; if (fs[1] != N) { GEN ns = gel(pr->dec, 2); long k, l, j = lg(fs); while (--j > 0) { ulong NP = upowuu(p, fs[j]); long nf; if (!NP) continue; for (k = 1; k <= n; k++) if (vecN[k] > NP) break; if (k > n) continue; /* vecN[k] <= NP */ nf = ns[j]; /*#{primes of norme NP} = nf, insert them here*/ for (l = k+nf; l <= n; l++) vecN[l] = vecN[l-nf]; for (l = 0; l < nf && k+l <= n; l++) vecN[k+l] = NP; while (l <= k) vecN[l++] = NP; } } if (p > vecN[n]) break; } return gc_long(av, vecN[n]); } /* volume of unit ball in R^n: \pi^{n/2} / \Gamma(n/2 + 1) */ static double ballvol(long n) { double v = odd(n)? 2: 1; for (; n > 1; n -= 2) v *= (2 * M_PI) / n; return v; } /* Compute FB, LV, iLP + KC*. Reset perm * C2: bound for norm of tested prime ideals (includes be_honest()) * C1: bound for p, such that P|p (NP <= C2) used to build relations */ static void FBgen(FB_t *F, GEN nf, long N, ulong C1, ulong C2, GRHcheck_t *S) { GRHprime_t *pr; long i, ip; GEN prim; const double L = log((double)C2 + 0.5); cache_prime_dec(S, C2, nf); pr = S->primes; F->sfb_chg = 0; F->FB = cgetg(C2+1, t_VECSMALL); F->iLP = cgetg(C2+1, t_VECSMALL); F->LV = zerovec(C2); prim = icopy(gen_1); i = ip = 0; F->KC = F->KCZ = 0; for (;; pr++) /* p <= C2 */ { ulong p = pr->p; long k, l, m; GEN LP, nb, f; if (!F->KC && p > C1) { F->KCZ = i; F->KC = ip; } if (p > C2) break; if (DEBUGLEVEL>1) err_printf(" %ld",p); f = gel(pr->dec, 1); nb = gel(pr->dec, 2); if (f[1] == N) { if (p == C2) break; continue; /* p inert */ } l = (long)(L/pr->logp); /* p^f <= C2 <=> f <= l */ for (k=0, m=1; m < lg(f) && f[m]<=l; m++) k += nb[m]; if (!k) { /* too inert to appear in FB */ if (p == C2) break; continue; } prim[2] = p; LP = idealprimedec_limit_f(nf,prim, l); /* keep noninert ideals with Norm <= C2 */ if (m == lg(f)) setisclone(LP); /* flag it: all prime divisors in FB */ F->FB[++i]= p; gel(F->LV,p) = LP; F->iLP[p] = ip; ip += k; if (p == C2) break; } if (!F->KC) { F->KCZ = i; F->KC = ip; } /* Note F->KC > 0 otherwise GRHchk is false */ setlg(F->FB, F->KCZ+1); F->KCZ2 = i; F->prodZ = zv_prod_Z(F->FB); 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,gel(F->LV,F->FB[i])); } } F->perm = NULL; F->L_jid = NULL; F->ballvol = ballvol(nf_get_degree(nf)); } static int GRHchk(GEN nf, GRHcheck_t *S, ulong LIMC) { double logC = log((double)LIMC), SA = 0, SB = 0; GRHprime_t *pr = S->primes; cache_prime_dec(S, LIMC, nf); for (pr = S->primes;; pr++) { ulong p = pr->p; GEN dec, fs, ns; double logCslogp; long j; if (p > LIMC) break; dec = pr->dec; fs = gel(dec, 1); ns = gel(dec,2); logCslogp = logC/pr->logp; for (j = 1; j < lg(fs); j++) { long f = fs[j], M, nb; double logNP, q, A, B; if (f > logCslogp) break; logNP = f * pr->logp; q = 1/sqrt((double)upowuu(p, f)); A = logNP * q; B = logNP * A; M = (long)(logCslogp/f); if (M > 1) { double inv1_q = 1 / (1-q); A *= (1 - pow(q, (double)M)) * inv1_q; B *= (1 - pow(q, (double)M)*(M+1 - M*q)) * inv1_q * inv1_q; } nb = ns[j]; SA += nb * A; SB += nb * B; } if (p == LIMC) break; } return GRHok(S, logC, SA, SB); } /* SMOOTH IDEALS */ static void store(long i, long e, FACT *fact) { ++fact[0].pr; fact[fact[0].pr].pr = i; /* index */ fact[fact[0].pr].ex = e; /* exponent */ } /* divide out m by all P|p, k = v_p(Nm) */ static int divide_p_elt(GEN LP, long ip, long k, GEN m, FACT *fact) { long j, l = lg(LP); for (j=1; j 0 */ k -= v * pr_get_f(P); if (!k) return 1; } return 0; } /* divide out I by all P|p, k = v_p(NI) */ static int divide_p_id(GEN LP, long ip, long k, GEN nf, GEN I, FACT *fact) { long j, l = lg(LP); for (j=1; j 0 */ k -= v * pr_get_f(P); if (!k) return 1; } return 0; } /* divide out m/I by all P|p, k = v_p(Nm/NI) */ static int divide_p_quo(GEN LP, long ip, long k, GEN nf, GEN I, GEN m, FACT *fact) { long j, l = lg(LP); for (j=1; j 0 */ k -= v * pr_get_f(P); if (!k) return 1; } return 0; } static int divide_p(FB_t *F, long p, long k, GEN nf, GEN I, GEN m, FACT *fact) { GEN LP = gel(F->LV,p); long ip = F->iLP[p]; if (!m) return divide_p_id (LP,ip,k,nf,I,fact); if (!I) return divide_p_elt(LP,ip,k,m,fact); return divide_p_quo(LP,ip,k,nf,I,m,fact); } /* Let x = m if I == NULL, * I if m == NULL, * m/I otherwise. * Can we factor the integral primitive ideal x ? |N| = Norm x > 0 */ static long can_factor(FB_t *F, GEN nf, GEN I, GEN m, GEN N, FACT *fact) { GEN f, p, e; long i, l; fact[0].pr = 0; if (is_pm1(N)) return 1; if (!is_pm1(Z_ppo(N, F->prodZ))) return 0; f = absZ_factor(N); p = gel(f,1); e = gel(f,2); l = lg(p); for (i = 1; i < l; i++) if (!divide_p(F, itou(gel(p,i)), itou(gel(e,i)), nf, I, m, fact)) { if (DEBUGLEVEL > 1) err_printf("."); return 0; } return 1; } /* 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; GEN Nm = embed_norm(RgM_RgC_mul(nf_get_M(nf),m), nf_get_r1(nf)); GEN N = grndtoi(NI? divri(Nm, NI): Nm, &e); /* ~ N(m/I) */ if (e > -32) { if (DEBUGLEVEL > 1) err_printf("+"); return 0; } return can_factor(F, nf, I, m, N, fact); } /* FUNDAMENTAL UNITS */ /* a, y real. Return (Re(x) + a) + I * (Im(x) % y) */ static GEN addRe_modIm(GEN x, GEN a, GEN y, GEN iy) { GEN z; if (typ(x) == t_COMPLEX) { GEN re, im = modRr_i(gel(x,2), y, iy); if (!im) return NULL; re = gadd(gel(x,1), a); z = gequal0(im)? re: mkcomplex(re, im); } else z = gadd(x, a); return z; } static GEN modIm(GEN x, GEN y, GEN iy) { if (typ(x) == t_COMPLEX) { GEN im = modRr_i(gel(x,2), y, iy); if (!im) return NULL; x = gequal0(im)? gel(x,1): mkcomplex(gel(x,1), im); } return x; } /* clean archimedean components. ipi = 2^n / pi (n arbitrary); its * exponent may be modified */ static GEN cleanarch(GEN x, long N, GEN ipi, long prec) { long i, l, R1, RU; GEN s, y = cgetg_copy(x, &l); if (!ipi) ipi = invr(mppi(prec)); if (typ(x) == t_MAT) { for (i = 1; i < l; i++) if (!(gel(y,i) = cleanarch(gel(x,i), N, ipi, prec))) return NULL; return y; } RU = l-1; R1 = (RU<<1) - N; s = gdivgs(RgV_sum(real_i(x)), -N); /* -log |norm(x)| / N */ i = 1; if (R1) { GEN pi2 = Pi2n(1, prec); setexpo(ipi, -3); /* 1/(2pi) */ for (; i <= R1; i++) if (!(gel(y,i) = addRe_modIm(gel(x,i), s, pi2, ipi))) return NULL; } if (i <= RU) { GEN pi4 = Pi2n(2, prec), s2 = gmul2n(s, 1); setexpo(ipi, -4); /* 1/(4pi) */ for (; i <= RU; i++) if (!(gel(y,i) = addRe_modIm(gel(x,i), s2, pi4, ipi))) return NULL; } return y; } GEN nf_cxlog_normalize(GEN nf, GEN x, long prec) { long N = nf_get_degree(nf); return cleanarch(x, N, NULL, prec); } /* clean unit archimedean components. ipi = 2^n / pi (n arbitrary); its * exponent may be modified */ static GEN cleanarchunit(GEN x, long N, GEN ipi, long prec) { long i, l, R1, RU; GEN y = cgetg_copy(x, &l); if (!ipi) ipi = invr(mppi(prec)); if (typ(x) == t_MAT) { for (i = 1; i < l; i++) if (!(gel(y,i) = cleanarchunit(gel(x,i), N, ipi, prec))) return NULL; return y; } if (gexpo(RgV_sum(real_i(x))) > -10) return NULL; RU = l-1; R1 = (RU<<1) - N; i = 1; if (R1) { GEN pi2 = Pi2n(1, prec); setexpo(ipi, -3); /* 1/(2pi) */ for (; i <= R1; i++) if (!(gel(y,i) = modIm(gel(x,i), pi2, ipi))) return NULL; } if (i <= RU) { GEN pi4 = Pi2n(2, prec); setexpo(ipi, -4); /* 1/(4pi) */ for (; i <= RU; i++) if (!(gel(y,i) = modIm(gel(x,i), pi4, ipi))) 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 NULL; } /* check whether exp(x) will 1) get too big (real(x) large), 2) require * large accuracy for argument reduction (imag(x) large) */ static long expbitprec(GEN x, long *e) { GEN re, im; if (typ(x) != t_COMPLEX) re = x; else { im = gel(x,2); *e = maxss(*e, expo(im) + 5 - bit_prec(im)); re = gel(x,1); } return (expo(re) <= 20); } static long RgC_expbitprec(GEN x) { long l = lg(x), i, e = - (long)HIGHEXPOBIT; for (i = 1; i < l; i++) if (!expbitprec(gel(x,i), &e)) return LONG_MAX; return e; } static long RgM_expbitprec(GEN x) { long i, j, I, J, e = - (long)HIGHEXPOBIT; RgM_dimensions(x, &I,&J); for (j = 1; j <= J; j++) for (i = 1; i <= I; i++) if (!expbitprec(gcoeff(x,i,j), &e)) return LONG_MAX; return e; } static GEN FlxqX_chinese_unit(GEN X, GEN U, GEN invzk, GEN D, GEN T, ulong p) { long i, lU = lg(U), lX = lg(X), d = lg(invzk)-1; GEN M = cgetg(lU, t_MAT); if (D) { D = Flv_inv(D, p); for (i = 1; i < lX; i++) if (uel(D, i) != 1) gel(X,i) = Flx_Fl_mul(gel(X,i), uel(D,i), p); } for (i = 1; i < lU; i++) { GEN H = FlxqV_factorback(X, gel(U, i), T, p); gel(M, i) = Flm_Flc_mul(invzk, Flx_to_Flv(H, d), p); } return M; } static GEN chinese_unit_slice(GEN A, GEN U, GEN B, GEN D, GEN C, GEN P, GEN *mod) { pari_sp av = avma; long i, n = lg(P)-1, v = varn(C); GEN H, T; if (n == 1) { ulong p = uel(P,1); GEN a = ZXV_to_FlxV(A, p), b = ZM_to_Flm(B, p), c = ZX_to_Flx(C, p); GEN d = D ? ZV_to_Flv(D, p): NULL; GEN Hp = FlxqX_chinese_unit(a, U, b, d, c, p); H = gerepileupto(av, Flm_to_ZM(Hp)); *mod = utoi(p); return H; } T = ZV_producttree(P); A = ZXC_nv_mod_tree(A, P, T, v); B = ZM_nv_mod_tree(B, P, T); D = D ? ZV_nv_mod_tree(D, P, T): NULL; C = ZX_nv_mod_tree(C, P, T); H = cgetg(n+1, t_VEC); for(i=1; i <= n; i++) { ulong p = P[i]; GEN a = gel(A,i), b = gel(B,i), c = gel(C,i), d = D ? gel(D,i): NULL; gel(H,i) = FlxqX_chinese_unit(a, U, b, d, c, p); } H = nmV_chinese_center_tree_seq(H, P, T, ZV_chinesetree(P, T)); *mod = gmael(T, lg(T)-1, 1); return gc_all(av, 2, &H, mod); } GEN chinese_unit_worker(GEN P, GEN A, GEN U, GEN B, GEN D, GEN C) { GEN V = cgetg(3, t_VEC); gel(V,1) = chinese_unit_slice(A, U, B, isintzero(D) ? NULL: D, C, P, &gel(V,2)); return V; } /* Let x = \prod X[i]^E[i] = u, return u. * If dX != NULL, X[i] = nX[i] / dX[i] where nX[i] is a ZX, dX[i] in Z */ static GEN chinese_unit(GEN nf, GEN nX, GEN dX, GEN U, ulong bnd) { pari_sp av = avma; GEN f = nf_get_index(nf), T = nf_get_pol(nf), invzk = nf_get_invzk(nf); GEN H, mod; forprime_t S; GEN worker = snm_closure(is_entry("_chinese_unit_worker"), mkcol5(nX, U, invzk, dX? dX: gen_0, T)); init_modular_big(&S); H = gen_crt("chinese_units", worker, &S, f, bnd, 0, &mod, nmV_chinese_center, FpM_center); settyp(H, t_VEC); return gerepilecopy(av, H); } /* *pE a ZM */ static void ZM_remove_unused(GEN *pE, GEN *pX) { long j, k, l = lg(*pX); GEN E = *pE, v = cgetg(l, t_VECSMALL); for (j = k = 1; j < l; j++) if (!ZMrow_equal0(E, j)) v[k++] = j; if (k < l) { setlg(v, k); *pX = vecpermute(*pX,v); *pE = rowpermute(E,v); } } /* s = -log|norm(x)|/N */ static GEN fixarch(GEN x, GEN s, long R1) { long i, l; GEN y = cgetg_copy(x, &l); for (i = 1; i <= R1; i++) gel(y,i) = gadd(s, gel(x,i)); for ( ; i < l; i++) gel(y,i) = gadd(s, gmul2n(gel(x,i),-1)); return y; } static GEN getfu(GEN nf, GEN *ptA, GEN *ptU, long prec) { GEN U, y, matep, A, T = nf_get_pol(nf), M = nf_get_M(nf); long e, j, R1, RU, N = degpol(T); R1 = nf_get_r1(nf); RU = (N+R1) >> 1; if (RU == 1) return cgetg(1,t_VEC); A = *ptA; matep = cgetg(RU,t_MAT); for (j = 1; j < RU; j++) { GEN Aj = gel(A,j), s = gdivgs(RgV_sum(real_i(Aj)), -N); gel(matep,j) = fixarch(Aj, s, R1); } U = lll(real_i(matep)); if (lg(U) < RU) return not_given(fupb_PRECI); if (ptU) { *ptU = U; *ptA = A = RgM_ZM_mul(A,U); } y = RgM_ZM_mul(matep,U); e = RgM_expbitprec(y); if (e >= 0) return not_given(e == LONG_MAX? fupb_LARGE: fupb_PRECI); 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); if (e >= 0) return not_given(fupb_PRECI); settyp(y, t_VEC); if (!ptU) *ptA = A = RgM_ZM_mul(A, U); for (j = 1; j < RU; j++) { /* y[i] are hopefully unit generators. Normalize: smallest T2 norm */ GEN u = gel(y,j), v = zk_inv(nf, u); if (!v || !is_pm1(Q_denom(v)) || ZV_isscalar(u)) return not_given(fupb_PRECI); if (gcmp(RgC_fpnorml2(v,DEFAULTPREC), RgC_fpnorml2(u,DEFAULTPREC)) < 0) { gel(A,j) = RgC_neg(gel(A,j)); if (ptU) gel(U,j) = ZC_neg(gel(U,j)); u = v; } gel(y,j) = nf_to_scalar_or_alg(nf, u); } return y; } static void err_units() { pari_err_PREC("makeunits [cannot get units, use bnfinit(,1)]"); } /* bound for log2 |sigma(u)|, sigma complex embedding, u fundamental unit * attached to bnf_get_logfu */ static double log2fubound(GEN bnf) { GEN LU = bnf_get_logfu(bnf); long i, j, l = lg(LU), r1 = nf_get_r1(bnf_get_nf(bnf)); double e = 0.0; for (j = 1; j < l; j++) { GEN u = gel(LU,j); for (i = 1; i <= r1; i++) { GEN E = real_i(gel(u,i)); e = maxdd(e, gtodouble(E)); } for ( ; i <= l; i++) { GEN E = real_i(gel(u,i)); e = maxdd(e, gtodouble(E) / 2); } } return e / M_LN2; } /* bound for log2(|RgM_solve_realimag(M, y)|_oo / |y|_oo)*/ static double log2Mbound(GEN nf) { GEN G = nf_get_G(nf), D = nf_get_disc(nf); long r2 = nf_get_r2(nf), l = lg(G), i; double e, d = dbllog2(D)/2 - r2 * M_LN2; /* log2 |det(split_realimag(M))| */ e = log2(nf_get_degree(nf)); for (i = 2; i < l; i++) e += dbllog2(gnorml2(gel(G,i))); /* Hadamard bound */ return e / 2 - d; } static GEN vec_chinese_units(GEN bnf) { GEN nf = bnf_get_nf(bnf), SUnits = bnf_get_sunits(bnf); double bnd = ceil(log2Mbound(nf) + log2fubound(bnf)); GEN X, dX, Y, U, f = nf_get_index(nf); long j, l, v = nf_get_varn(nf); if (!SUnits) err_units(); /* no compact units */ Y = gel(SUnits,1); U = gel(SUnits,2); ZM_remove_unused(&U, &Y); l = lg(Y); X = cgetg(l, t_VEC); if (is_pm1(f)) f = dX = NULL; else dX = cgetg(l, t_VEC); for (j = 1; j < l; j++) { GEN t = nf_to_scalar_or_alg(nf, gel(Y,j)); if (f) { GEN den; t = Q_remove_denom(t, &den); gel(dX,j) = den ? den: gen_1; } gel(X,j) = typ(t) == t_INT? scalarpol_shallow(t,v): t; } if (dblexpo(bnd) >= BITS_IN_LONG) pari_err_OVERFLOW("vec_chinese_units [units too large]"); return chinese_unit(nf, X, dX, U, (ulong)bnd); } static GEN makeunits(GEN bnf) { GEN nf = bnf_get_nf(bnf), fu = bnf_get_fu_nocheck(bnf); GEN tu = nf_to_scalar_or_basis(nf, bnf_get_tuU(bnf)); fu = (typ(fu) == t_MAT)? vec_chinese_units(bnf): matalgtobasis(nf, fu); return vec_prepend(fu, tu); } /*******************************************************************/ /* */ /* PRINCIPAL IDEAL ALGORITHM (DISCRETE LOG) */ /* */ /*******************************************************************/ /* G: prime ideals, E: vector of nonnegative exponents. * C = possible extra prime (^1) or NULL * Return Norm (product) */ static GEN get_norm_fact_primes(GEN G, GEN E, GEN C) { pari_sp av=avma; GEN N = gen_1, P, p; long i, c = lg(E); for (i=1; i 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->prodZ = zv_prod_Z(F->FB); F->LV = LV; F->iLP= iLP; return L; } /* add v^e to factorization */ static void add_to_fact(long v, long e, FACT *fact) { long i, n = fact[0].pr; for (i=1; i<=n; i++) if (fact[i].pr == v) { fact[i].ex += e; return; } store(v, e, fact); } static void inv_fact(FACT *fact) { long i, n = fact[0].pr; for (i=1; i<=n; i++) fact[i].ex = -fact[i].ex; } /* 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(gel(F->LV,p), pr); } /* x, y 2 extended ideals whose first component is an integral HNF and second * a famat */ static GEN idealHNF_mulred(GEN nf, GEN x, GEN y) { GEN A = idealHNF_mul(nf, gel(x,1), gel(y,1)); GEN F = famat_mul_shallow(gel(x,2), gel(y,2)); return idealred(nf, mkvec2(A, F)); } /* idealred(x * pr^n), n > 0 is small, x extended ideal. Reduction in order to * avoid prec pb: don't let id become too large as lgsub increases */ static GEN idealmulpowprime2(GEN nf, GEN x, GEN pr, ulong n) { GEN A = idealmulpowprime(nf, gel(x,1), pr, utoipos(n)); return mkvec2(A, gel(x,2)); } static GEN init_famat(GEN x) { return mkvec2(x, trivial_fact()); } /* optimized idealfactorback + reduction; z = init_famat() */ static GEN genback(GEN z, GEN nf, GEN P, GEN E) { long i, l = lg(E); GEN I = NULL; for (i = 1; i < l; i++) if (signe(gel(E,i))) { GEN J; gel(z,1) = gel(P,i); J = idealpowred(nf, z, gel(E,i)); I = I? idealHNF_mulred(nf, I, J): J; } return I; /* != NULL since a generator */ } static GEN SPLIT_i(FB_t *F, GEN nf, GEN G, GEN x, GEN xred, GEN Nx, FACT *fact) { pari_sp av = avma; GEN L = idealpseudominvec(xred, G); long k, l = lg(L); for(k = 1; k < l; k++) if (factorgen(F, nf, x, Nx, gel(L,k), fact)) return gel(L,k); return gc_NULL(av); } /* 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, 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 */ if (expi(gcoeff(x,1,1)) < 100 && can_factor(F, nf, x, NULL, Nx, fact)) return NULL; if ((y = SPLIT_i(F, nf, nf_get_roundG(nf), x, x, Nx, fact))) return y; /* 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 < minss(8, lg(Vbase)-1)) { 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); } } } INLINE GEN bnf_get_W(GEN bnf) { return gel(bnf,1); } INLINE GEN bnf_get_B(GEN bnf) { return gel(bnf,2); } INLINE GEN bnf_get_C(GEN bnf) { return gel(bnf,4); } INLINE GEN bnf_get_vbase(GEN bnf) { return gel(bnf,5); } INLINE GEN bnf_get_Ur(GEN bnf) { return gmael(bnf,9,1); } INLINE GEN bnf_get_ga(GEN bnf) { return gmael(bnf,9,2); } INLINE GEN bnf_get_GD(GEN bnf) { return gmael(bnf,9,3); } /* Return y (as an elt of K or a t_MAT representing an elt in Z[K]) * such that x / (y) is smooth and store the exponents of its factorization * on g_W and g_B in Wex / Bex; return NULL for y = 1 */ static GEN split_ideal(GEN bnf, GEN x, GEN *pWex, GEN *pBex) { GEN L, y, Vbase = bnf_get_vbase(bnf); GEN Wex, W = bnf_get_W(bnf); GEN Bex, B = bnf_get_B(bnf); long p, j, i, l, nW, nB; FACT *fact; FB_t F; L = recover_partFB(&F, Vbase, lg(x)-1); fact = (FACT*)stack_malloc((F.KC+1)*sizeof(FACT)); y = SPLIT(&F, bnf_get_nf(bnf), x, Vbase, fact); nW = lg(W)-1; *pWex = Wex = zero_zv(nW); nB = lg(B)-1; *pBex = Bex = zero_zv(nB); l = lg(F.FB); p = j = 0; /* -Wall */ for (i = 1; i <= fact[0].pr; i++) { /* decode index C = ip+j --> (p,j) */ long a, b, t, C = fact[i].pr; for (t = 1; t < l; t++) { long q = F.FB[t], k = C - F.iLP[q]; if (k <= 0) break; p = q; j = k; } a = gel(L, p)[j]; b = a - nW; if (b <= 0) Wex[a] = y? -fact[i].ex: fact[i].ex; else Bex[b] = y? -fact[i].ex: fact[i].ex; } return y; } 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_MAT); for (i=1; i e) e = f; } return e; } /* col = archimedian components of x, Nx its norm, dx a multiple of 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, prec = gprecision(col); bnf = checkbnf(bnf); nf = bnf_get_nf(bnf); M = nf_get_M(nf); if (!prec) prec = prec_arch(bnf); *pe = 128; logfu = bnf_get_logfu(bnf); N = nf_get_degree(nf); if (!(col = cleanarch(col,N,NULL,prec))) return NULL; if (lg(col) > 2) { /* reduce mod units */ GEN u, z = init_red_mod_units(bnf,prec); if (!(u = red_mod_units(col,z))) return NULL; col = RgC_add(col, RgM_RgC_mul(logfu, u)); if (!(col = cleanarch(col,N,NULL,prec))) return NULL; } s = divru(mulir(e, glog(kNx,prec)), N); col = fixarch(col, s, nf_get_r1(nf)); if (RgC_expbitprec(col) >= 0) return NULL; col = gexp(col, 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 64) return 0; /* U large */ x = Q_remove_denom(x, &d); return (d && expi(d) > 32) || gexpo(x) > 32; } /* assume x in HNF; cf class_group_gen for notations. Return NULL iff * flag & nf_FORCE and computation of principal ideal generator fails */ static GEN isprincipalall(GEN bnf, GEN x, long *pprec, long flag) { GEN xar, Wex, Bex, gen, xc, col, A, Q, R, UA, SUnits; GEN C = bnf_get_C(bnf), nf = bnf_get_nf(bnf), cyc = bnf_get_cyc(bnf); long nB, nW, e; if (lg(cyc) == 1 && !(flag & (nf_GEN|nf_GENMAT|nf_GEN_IF_PRINCIPAL))) return cgetg(1,t_COL); if (lg(x) == 2) { /* nf = Q */ col = gel(x,1); if (flag & nf_GENMAT) col = Q_to_famat(gel(col,1)); return (flag & nf_GEN_IF_PRINCIPAL)? col: mkvec2(cgetg(1,t_COL), col); } x = Q_primitive_part(x, &xc); if (equali1(gcoeff(x,1,1))) /* trivial ideal */ { R = zerocol(lg(cyc)-1); if (!(flag & (nf_GEN|nf_GENMAT|nf_GEN_IF_PRINCIPAL))) return R; if (flag & nf_GEN_IF_PRINCIPAL) return scalarcol_shallow(xc? xc: gen_1, nf_get_degree(nf)); if (flag & nf_GENMAT) col = xc? Q_to_famat(xc): trivial_fact(); else col = scalarcol_shallow(xc? xc: gen_1, nf_get_degree(nf)); return mkvec2(R, col); } xar = split_ideal(bnf, x, &Wex, &Bex); /* x = g_W Wex + g_B Bex + [xar] = g_W (Wex - B*Bex) + [xar] + [C_B]Bex */ A = zc_to_ZC(Wex); nB = lg(Bex)-1; if (nB) A = ZC_sub(A, ZM_zc_mul(bnf_get_B(bnf), Bex)); UA = Ur_ZC_mul(bnf, A); Q = ZV_divrem(UA, cyc, &R); /* g_W (Wex - B*Bex) = G Ur A - [ga]A = G R + [GD]Q - [ga]A * Finally: x = G R + [xar] + [C_B]Bex + [GD]Q - [ga]A */ if (!(flag & (nf_GEN|nf_GENMAT|nf_GEN_IF_PRINCIPAL))) return R; if ((flag & nf_GEN_IF_PRINCIPAL) && !ZV_equal0(R)) return gen_0; nW = lg(Wex)-1; gen = bnf_get_gen(bnf); col = NULL; SUnits = bnf_get_sunits(bnf); if (lg(R) == 1 || abscmpiu(gel(R,vecindexmax(R)), 4 * (*pprec)) < 0) { /* q = N (x / prod gj^ej) = N(alpha), denom(alpha) | d */ GEN d, q = gdiv(ZM_det_triangular(x), get_norm_fact(gen, R, &d)); col = xar? nf_cxlog(nf, xar, *pprec): NULL; if (nB) col = add(col, act_arch(Bex, nW? vecslice(C,nW+1,lg(C)-1): C)); if (nW) col = add(col, RgC_sub(act_arch(Q, bnf_get_GD(bnf)), act_arch(A, bnf_get_ga(bnf)))); col = isprincipalarch(bnf, col, q, gen_1, d, &e); if (col && (dump_gen(SUnits, col, flag) || !fact_ok(nf,x, col,gen,R))) col = NULL; } if (!col && (flag & nf_GENMAT)) { if (SUnits) { GEN X = gel(SUnits,1), U = gel(SUnits,2), C = gel(SUnits,3); GEN v = gel(bnf,9), Ge = gel(v,4), M1 = gel(v,5), M2 = gel(v,6); GEN z = NULL, F = NULL; if (nB) { GEN C2 = nW? vecslice(C, nW+1, lg(C)-1): C; z = ZM_zc_mul(C2, Bex); } if (nW) { /* [GD]Q - [ga]A = ([X]M1 - [Ge]D) Q - ([X]M2 - [Ge]Ur) A */ GEN C1 = vecslice(C, 1, nW); GEN v = ZC_sub(ZM_ZC_mul(M1,Q), ZM_ZC_mul(M2,A)); z = add(z, ZM_ZC_mul(C1, v)); F = famat_reduce(famatV_factorback(Ge, ZC_sub(UA, ZV_mul(cyc,Q)))); if (lgcols(F) == 1) F = NULL; } /* reduce modulo units and Q^* */ if (lg(U) != 1) z = ZC_sub(z, ZM_ZC_mul(U, RgM_Babai(U,z))); col = mkmat2(X, z); if (F) col = famat_mul_shallow(col, F); col = famat_remove_trivial(col); if (xar) col = famat_mul_shallow(col, xar); } else if (!ZV_equal0(R)) { /* in case isprincipalfact calls bnfinit() due to prec trouble...*/ GEN y = isprincipalfact(bnf, x, gen, ZC_neg(R), flag); if (typ(y) != t_VEC) return y; col = gel(y,2); } } if (col) { /* add back missing content */ if (typ(col) == t_MAT) { if (xc) col = famat_mul_shallow(col, xc); } else if (flag & nf_GENMAT) { GEN c; if (RgV_isscalar(col)) col = Q_to_famat(mul_content(xc, gel(col,1))); else { col = Q_primitive_part(col, &c); col = to_famat_shallow(col, gen_1); xc = mul_content(xc, c); if (xc) col = famat_mul(col, Q_to_famat(xc)); } } else { if (xc) col = RgC_Rg_mul(col,xc); } } else { if (e < 0) e = 0; *pprec += nbits2extraprec(e + 128); if (flag & nf_FORCE) { if (DEBUGLEVEL) pari_warn(warner,"precision too low for generators, e = %ld",e); return NULL; } pari_warn(warner,"precision too low for generators, not given"); col = cgetg(1, t_COL); } return (flag & nf_GEN_IF_PRINCIPAL)? col: mkvec2(R, col); } static GEN triv_gen(GEN bnf, GEN x, long flag) { pari_sp av = avma; GEN nf = bnf_get_nf(bnf); long c; if (flag & nf_GEN_IF_PRINCIPAL) { if (!(flag & nf_GENMAT)) return algtobasis(nf,x); x = nf_to_scalar_or_basis(nf,x); if (typ(x) == t_INT && is_pm1(x)) return trivial_fact(); return gerepilecopy(av, to_famat_shallow(x, gen_1)); } c = lg(bnf_get_cyc(bnf)) - 1; if (flag & nf_GENMAT) retmkvec2(zerocol(c), to_famat_shallow(algtobasis(nf,x), gen_1)); if (flag & nf_GEN) retmkvec2(zerocol(c), algtobasis(nf,x)); return zerocol(c); } GEN bnfisprincipal0(GEN bnf,GEN x,long flag) { pari_sp av = avma; GEN c, nf; long pr; bnf = checkbnf(bnf); nf = bnf_get_nf(bnf); switch( idealtyp(&x, NULL) ) { case id_PRINCIPAL: if (gequal0(x)) pari_err_DOMAIN("bnfisprincipal","ideal","=",gen_0,x); return triv_gen(bnf, x, flag); case id_PRIME: if (pr_is_inert(x)) return triv_gen(bnf, pr_get_p(x), flag); x = pr_hnf(nf, x); break; case id_MAT: if (lg(x)==1) pari_err_DOMAIN("bnfisprincipal","ideal","=",gen_0,x); if (nf_get_degree(nf) != lg(x)-1) pari_err_TYPE("idealtyp [dimension != degree]", x); } pr = prec_arch(bnf); /* precision of unit matrix */ c = getrand(); for (;;) { pari_sp av1 = avma; GEN y = isprincipalall(bnf,x,&pr,flag); if (y) return gerepilecopy(av, y); if (DEBUGLEVEL) pari_warn(warnprec,"isprincipal",pr); set_avma(av1); bnf = bnfnewprec_shallow(bnf,pr); setrand(c); } } GEN isprincipal(GEN bnf,GEN x) { return bnfisprincipal0(bnf,x,0); } /* FIXME: OBSOLETE */ GEN isprincipalgen(GEN bnf,GEN x) { return bnfisprincipal0(bnf,x,nf_GEN); } GEN isprincipalforce(GEN bnf,GEN x) { return bnfisprincipal0(bnf,x,nf_FORCE); } GEN isprincipalgenforce(GEN bnf,GEN x) { return bnfisprincipal0(bnf,x,nf_GEN | nf_FORCE); } /* lg(u) > 1 */ static int RgV_is1(GEN u) { return isint1(gel(u,1)) && RgV_isscalar(u); } static GEN add_principal_part(GEN nf, GEN u, GEN v, long flag) { if (flag & nf_GENMAT) return (typ(u) == t_COL && RgV_is1(u))? v: famat_mul_shallow(v,u); else return nfmul(nf, v, u); } #if 0 /* compute C prod P[i]^e[i], e[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; im; long i; arch = typ(z) == t_COL? RgM_RgC_mul(M, z): const_col(nbrows(M), z); C = cgetg(RU+1, t_COL); arch = glog(arch, prec); for (i=1; i<=R1; i++) gel(C,i) = gel(arch,i); for ( ; i<=RU; i++) gel(C,i) = gmul2n(gel(arch,i), 1); return C; } static GEN rel_embed(REL_t *rel, FB_t *F, GEN embs, long ind, GEN M, long RU, long R1, long prec) { GEN C, D, perm; long i, n; if (!rel->relaut) return get_log_embed(rel, M, RU, R1, prec); /* image of another relation by automorphism */ C = gel(embs, ind - rel->relorig); perm = gel(F->embperm, rel->relaut); D = cgetg_copy(C, &n); for (i = 1; i < n; i++) { long v = perm[i]; gel(D,i) = (v > 0)? gel(C,v): conj_i(gel(C,-v)); } return D; } static GEN get_embs(FB_t *F, RELCACHE_t *cache, GEN nf, GEN embs, long PREC) { long ru, j, k, l = cache->last - cache->chk + 1, r1 = nf_get_r1(nf); GEN M = nf_get_M(nf), nembs = cgetg(cache->last - cache->base+1, t_MAT); REL_t *rel; for (k = 1; k <= cache->chk - cache->base; k++) gel(nembs,k) = gel(embs,k); embs = nembs; ru = nbrows(M); for (j=1,rel = cache->chk + 1; j < l; rel++,j++,k++) gel(embs,k) = rel_embed(rel, F, embs, k, M, ru, r1, PREC); return embs; } static void set_rel_alpha(REL_t *rel, GEN auts, GEN vA, long ind) { GEN u; if (!rel->relaut) u = rel->m; else u = ZM_ZC_mul(gel(auts, rel->relaut), gel(vA, ind - rel->relorig)); gel(vA, ind) = u; } static GEN set_fact(FB_t *F, FACT *fact, GEN e, long *pnz) { long i, n = fact[0].pr, nz = F->KC + 1; GEN c = zero_Flv(F->KC); for (i = 1; i <= n; i++) { long p = fact[i].pr; if (p < nz) nz = p; c[p] = fact[i].ex; } if (e) { long l = lg(e); for (i = 1; i < l; i++) if (e[i]) { long v = F->subFB[i]; c[v] += e[i]; if (v < nz) nz = v; } } *pnz = nz; return c; } /* Is cols already in the cache ? bs = index of first non zero coeff in cols * General check for colinearity useless since exceedingly rare */ static int already_known(RELCACHE_t *cache, long bs, GEN cols) { REL_t *r; long l = lg(cols); for (r = cache->last; r > cache->base; r--) if (bs == r->nz) { GEN coll = r->R; long b = bs; while (b < l && cols[b] == coll[b]) b++; if (b == l) return 1; } return 0; } /* Add relation R to cache, nz = index of first non zero coeff in R. * If relation is a linear combination of the previous ones, return 0. * Otherwise, update basis and return > 0. Compute mod p (much faster) * so some kernel vector might not be genuine. */ static int add_rel_i(RELCACHE_t *cache, GEN R, long nz, GEN m, long orig, long aut, REL_t **relp, long in_rnd_rel) { long i, k, n = lg(R)-1; if (nz == n+1) { k = 0; goto ADD_REL; } if (already_known(cache, nz, R)) return -1; if (cache->last >= cache->base + cache->len) return 0; if (DEBUGLEVEL>6) { err_printf("adding vector = %Ps\n",R); err_printf("generators =\n%Ps\n", cache->basis); } if (cache->missing) { GEN a = leafcopy(R), basis = cache->basis; k = lg(a); do --k; while (!a[k]); while (k) { GEN c = gel(basis, k); if (c[k]) { long ak = a[k]; for (i=1; i < k; i++) if (c[i]) a[i] = (a[i] + ak*(mod_p-c[i])) % mod_p; a[k] = 0; do --k; while (!a[k]); /* k cannot go below 0: codeword is a sentinel */ } else { ulong invak = Fl_inv(uel(a,k), mod_p); /* Cleanup a */ for (i = k; i-- > 1; ) { long j, ai = a[i]; c = gel(basis, i); if (!ai || !c[i]) continue; ai = mod_p-ai; for (j = 1; j < i; j++) if (c[j]) a[j] = (a[j] + ai*c[j]) % mod_p; a[i] = 0; } /* Insert a/a[k] as k-th column */ c = gel(basis, k); for (i = 1; imissing--; break; } } } else k = (cache->last - cache->base) + 1; if (k || cache->relsup > 0 || (m && in_rnd_rel)) { REL_t *rel; ADD_REL: rel = ++cache->last; if (!k && cache->relsup && nz < n+1) { cache->relsup--; k = (rel - cache->base) + cache->missing; } rel->R = gclone(R); rel->m = m ? gclone(m) : NULL; rel->nz = nz; if (aut) { rel->relorig = (rel - cache->base) - orig; rel->relaut = aut; } else rel->relaut = 0; if (relp) *relp = rel; if (DEBUGLEVEL) dbg_newrel(cache); } return k; } /* m a t_INT or primitive t_COL */ 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 lauts = lg(F->idealperm), KC = F->KC; k = add_rel_i(cache, R, nz, m, 0, 0, &rel, in_rnd_rel); if (k > 0 && typ(m) != t_INT) { GEN Rl = cgetg(KC+1, t_VECSMALL); reln = rel - cache->base; for (l = 1; l < lauts; 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; } 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 double Fincke_Pohst_bound(double T, GEN r) { pari_sp av = avma; GEN zT = dbltor(T * T), p = gmael(r,1,1), B = real_1(DEFAULTPREC); long i, n = lg(r)-1; double g; for (i = 2; i <= n; i++) { p = gmul(p, gmael(r,i,i)); B = sqrtnr(gmul(zT,p), i); if (i == n || cmprr(B, gmael(r,i+1,i+1)) < 0) break; } if (!gisdouble(B,&g)) return gc_double(av, 0.); return gc_double(av, rtodbl(B)); } static void fact_update(GEN R, FB_t *F, long ipr, GEN c) { GEN pr = gel(F->LP,ipr), p = pr_get_p(pr); long v = Z_lval(c, itou(p)); if (v) R[ipr] -= pr_get_e(pr) * v; } static long Fincke_Pohst_ideal(RELCACHE_t *cache, FB_t *F, GEN nf, GEN I, GEN NI, FACT *fact, long Nrelid, FP_t *fp, GEN rex, long jid, long jid0, long e0, long *Nsmall, long *Nfact) { pari_sp av; GEN G = nf_get_G(nf), G0 = nf_get_roundG(nf), r, u, gx, cgx, inc, ideal; long prec = nf_get_prec(nf), N = nf_get_degree(nf); long j, k, skipfirst, relid = 0, try_factor = 0; long try_elt = 0, maxtry_ELEMENT = 4*maxtry_FACT*maxtry_FACT; double BOUND, B1, B2; inc = const_vecsmall(N, 1); u = ZM_lll(ZM_mul(G0, I), 0.99, LLL_IM); ideal = ZM_mul(I,u); /* approximate T2-LLL reduction */ r = gaussred_from_QR(RgM_mul(G, ideal), prec); /* Cholesky for T2 | ideal */ if (!r) pari_err_BUG("small_norm (precision too low)"); for (k=1; k<=N; k++) { if (!gisdouble(gcoeff(r,k,k),&(fp->v[k]))) return 0; for (j=1; jq[j][k]))) return 0; if (DEBUGLEVEL>3) err_printf("v[%ld]=%.4g ",k,fp->v[k]); } B1 = fp->v[1]; /* T2(ideal[1]) */ B2 = fp->v[2] + B1 * fp->q[1][2] * fp->q[1][2]; /* T2(ideal[2]) */ skipfirst = ZV_isscalar(gel(ideal,1)); BOUND = maxdd(2*B2, Fincke_Pohst_bound(4 * maxtry_FACT / F->ballvol, r)); if (DEBUGLEVEL>1) { if (DEBUGLEVEL>3) err_printf("\n"); err_printf("BOUND = %.4g\n",BOUND); } k = N; fp->y[N] = fp->z[N] = 0; fp->x[N] = 0; for (av = avma;; set_avma(av), step(fp->x,fp->y,inc,k)) { GEN R; long nz; do { /* look for primitive element of small norm, cf minim00 */ int fl = 0; double p; if (k > 1) { long l = k-1; fp->z[l] = 0; for (j=k; j<=N; j++) fp->z[l] += fp->q[l][j]*fp->x[j]; p = (double)fp->x[k] + fp->z[k]; fp->y[l] = fp->y[k] + p*p*fp->v[k]; if (l <= skipfirst && !fp->y[1]) fl = 1; fp->x[l] = (long)floor(-fp->z[l] + 0.5); k = l; } for(;; step(fp->x,fp->y,inc,k)) { if (!fl) { if (++try_elt > maxtry_ELEMENT) goto END_Fincke_Pohst_ideal; p = (double)fp->x[k] + fp->z[k]; if (fp->y[k] + p*p*fp->v[k] <= BOUND) break; step(fp->x,fp->y,inc,k); p = (double)fp->x[k] + fp->z[k]; if (fp->y[k] + p*p*fp->v[k] <= BOUND) break; } fl = 0; inc[k] = 1; if (++k > N) goto END_Fincke_Pohst_ideal; } } while (k > 1); /* element complete */ if (zv_content(fp->x) !=1) continue; /* not primitive */ gx = ZM_zc_mul(ideal,fp->x); if (ZV_isscalar(gx)) continue; if (++try_factor > maxtry_FACT) break; if (DEBUGLEVEL && Nsmall) (*Nsmall)++; if (!factorgen(F,nf,I,NI,gx,fact)) continue; if (!Nrelid) return 1; if (jid == jid0) add_to_fact(jid, 1 + e0, fact); else { add_to_fact(jid, 1, fact); if (jid0) add_to_fact(jid0, e0, fact); } /* smooth element */ R = set_fact(F, fact, rex, &nz); cgx = Z_content(gx); if (cgx) { /* relatively rare, compute relation attached to gx/cgx */ long i, n = fact[0].pr; gx = Q_div_to_int(gx, cgx); for (i = 1; i <= n; i++) fact_update(R, F, fact[i].pr, cgx); if (rex) { long l = lg(rex); for (i = 1; i < l; i++) if (rex[i]) { long t, ipr = F->subFB[i]; for (t = 1; t <= n; t++) if (fact[t].pr == ipr) break; if (t > n) fact_update(R, F, ipr, cgx); } } } if (DEBUGLEVEL && Nfact) (*Nfact)++; /* make sure we get maximal rank first, then allow all relations */ if (add_rel(cache, F, R, nz, gx, rex? 1: 0) <= 0) { /* probably Q-dependent from previous ones: forget it */ if (DEBUGLEVEL>1) err_printf("*"); continue; } if (cache->last >= cache->end) return 1; /* we have enough */ if (++relid == Nrelid) break; } END_Fincke_Pohst_ideal: return 0; } static void small_norm(RELCACHE_t *cache, FB_t *F, GEN nf, long Nrelid, FACT *fact, long j0) { const long N = nf_get_degree(nf); FP_t fp; pari_sp av; GEN L_jid = F->L_jid, Np0 = NULL, p0 = j0? gel(F->LP,j0): NULL; long Nsmall, Nfact, n = lg(L_jid), e0 = 0; pari_timer T; if (DEBUGLEVEL) { timer_start(&T); err_printf("#### Look for %ld relations in %ld ideals (small_norm)\n", cache->end - cache->last, lg(L_jid)-1); if (p0) err_printf("Look in p0 = %Ps\n", vecslice(p0,1,4)); } Nsmall = Nfact = 0; minim_alloc(N+1, &fp.q, &fp.x, &fp.y, &fp.z, &fp.v); if (p0) { GEN n = pr_norm(p0); e0 = logint0(sqri(pr_norm(veclast(F->LP))), n, NULL); p0 = idealpows(nf, p0, e0); Np0 = powiu(n,e0); } for (av = avma; --n; set_avma(av)) { long j = L_jid[n]; GEN id = gel(F->LP, j), Nid; if (DEBUGLEVEL>1) err_printf("\n*** Ideal no %ld: %Ps\n", j, vecslice(id,1,4)); if (p0) { if (j == j0) { /* avoid trivial relation */ long e = pr_get_e(id); if ((e0 + 1) % e == 0 && e * pr_get_f(id) == N) continue; } Nid = mulii(Np0, pr_norm(id)); id = idealmul(nf, p0, id); } else { Nid = pr_norm(id); id = pr_hnf(nf, id);} if (Fincke_Pohst_ideal(cache, F, nf, id, Nid, fact, Nrelid, &fp, NULL, j, j0, e0, &Nsmall, &Nfact)) break; } if (DEBUGLEVEL && Nsmall) { if (DEBUGLEVEL == 1) { if (Nfact) err_printf("\n"); } else err_printf(" \nnb. fact./nb. small norm = %ld/%ld = %.3f\n", Nfact,Nsmall,((double)Nfact)/Nsmall); if (timer_get(&T)>1) timer_printf(&T,"small_norm"); } } static GEN get_random_ideal(FB_t *F, GEN nf, GEN ex) { long i, l = lg(ex); for (;;) { GEN I = NULL; for (i = 1; i < l; i++) if ((ex[i] = random_bits(RANDOM_BITS))) { GEN pr = gel(F->LP, F->subFB[i]), e = utoipos(ex[i]); I = I? idealmulpowprime(nf, I, pr, e): idealpow(nf, pr, e); } if (I && !ZM_isscalar(I,NULL)) return I; /* != (n)Z_K */ } } static void rnd_rel(RELCACHE_t *cache, FB_t *F, GEN nf, FACT *fact) { pari_timer T; GEN L_jid = F->L_jid, R, NR, ex; long i, l = lg(L_jid), Nfact = 0; FP_t fp; pari_sp av; if (DEBUGLEVEL) { timer_start(&T); err_printf("#### Look for %ld relations in %ld ideals (rnd_rel)\n", cache->end - cache->last, l-1); } ex = cgetg(lg(F->subFB), t_VECSMALL); R = get_random_ideal(F, nf, ex); /* random product from subFB */ NR = ZM_det_triangular(R); minim_alloc(nf_get_degree(nf)+1, &fp.q, &fp.x, &fp.y, &fp.z, &fp.v); for (av = avma, i = 1; i < l; i++, set_avma(av)) { /* try P[j] * base */ long j = L_jid[i]; GEN P = gel(F->LP, j), Nid = mulii(NR, pr_norm(P)); if (DEBUGLEVEL>1) err_printf("\n*** Ideal %ld: %Ps\n", j, vecslice(P,1,4)); if (Fincke_Pohst_ideal(cache, F, nf, idealHNF_mul(nf, R, P), Nid, fact, RND_REL_RELPID, &fp, ex, j, 0, 0, NULL, &Nfact)) break; } if (DEBUGLEVEL) { if (Nfact) err_printf("\n"); if (timer_get(&T)>=0) timer_printf(&T,"rnd_rel"); } } static GEN automorphism_perms(GEN M, GEN auts, GEN cyclic, long r1, long r2, long N) { long L = lgcols(M), lauts = lg(auts), lcyc = lg(cyclic), i, j, l, m; GEN Mt, perms = cgetg(lauts, t_VEC); pari_sp av; for (l = 1; l < lauts; l++) gel(perms, l) = cgetg(L, t_VECSMALL); av = avma; Mt = shallowtrans(gprec_w(M, LOWDEFAULTPREC)); Mt = shallowconcat(Mt, conj_i(vecslice(Mt, r1+1, r1+r2))); for (l = 1; l < lcyc; l++) { GEN thiscyc = gel(cyclic, l), thisperm, perm, prev, Nt; long k = thiscyc[1]; Nt = RgM_mul(shallowtrans(gel(auts, k)), Mt); perm = gel(perms, k); for (i = 1; i < L; i++) { GEN v = gel(Nt, i), minD; minD = gnorml2(gsub(v, gel(Mt, 1))); perm[i] = 1; for (j = 2; j <= N; j++) { GEN D = gnorml2(gsub(v, gel(Mt, j))); if (gcmp(D, minD) < 0) { minD = D; perm[i] = j >= L ? r2-j : j; } } } for (prev = perm, m = 2; m < lg(thiscyc); m++, prev = thisperm) { thisperm = gel(perms, thiscyc[m]); for (i = 1; i < L; i++) { long pp = labs(prev[i]); thisperm[i] = prev[i] < 0 ? -perm[pp] : perm[pp]; } } } set_avma(av); return perms; } /* Determine the field automorphisms as matrices on the integral basis */ static GEN automorphism_matrices(GEN nf, GEN *cycp) { pari_sp av = avma; GEN auts = galoisconj(nf, NULL), mats, cyclic, cyclicidx; long nauts = lg(auts)-1, i, j, k, l; cyclic = cgetg(nauts+1, t_VEC); cyclicidx = zero_Flv(nauts); for (l = 1; l <= nauts; l++) { GEN aut = gel(auts, l); if (gequalX(aut)) { swap(gel(auts, l), gel(auts, nauts)); break; } } /* trivial automorphism is last */ 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); cyc[1] = cyclicidx[l] = 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; } 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++) gel(mats, cyc[i]) = Mi = ZM_mul(Mi, M); } gerepileall(av, 2, &mats, &cyclic); if (cycp) *cycp = cyclic; return mats; } /* vP a list of maximal ideals above the same p from idealprimedec: f(P/p) is * increasing; 1 <= j <= #vP; orbit a zc of length <= #vP; auts a vector of * automorphisms in ZM form. * Set orbit[i] = 1 for all vP[i], i >= j, in the orbit of pr = vP[j] wrt auts. * N.B.1 orbit need not be initialized to 0: useful to incrementally run * through successive orbits * N.B.2 i >= j, so primes with index < j will be missed; run incrementally * starting from j = 1 ! */ static void pr_orbit_fill(GEN orbit, GEN auts, GEN vP, long j) { GEN pr = gel(vP,j), gen = pr_get_gen(pr); long i, l = lg(auts), J = lg(orbit), f = pr_get_f(pr); orbit[j] = 1; for (i = 1; i < l; i++) { GEN g = ZM_ZC_mul(gel(auts,i), gen); long k; for (k = j+1; k < J; k++) { GEN prk = gel(vP,k); if (pr_get_f(prk) > f) break; /* f(P[k]) increases with k */ /* don't check that e matches: (almost) always 1 ! */ if (!orbit[k] && ZC_prdvd(g, prk)) { orbit[k] = 1; break; } } } } /* remark: F->KCZ changes if be_honest() fails */ static int be_honest(FB_t *F, GEN nf, GEN auts, FACT *fact) { long i, iz, nbtest; long lgsub = lg(F->subFB), KCZ0 = F->KCZ, N = nf_get_degree(nf); FP_t fp; pari_sp av; if (DEBUGLEVEL) { err_printf("Be honest for %ld primes from %ld to %ld\n", F->KCZ2 - F->KCZ, F->FB[ F->KCZ+1 ], F->FB[ F->KCZ2 ]); } minim_alloc(N+1, &fp.q, &fp.x, &fp.y, &fp.z, &fp.v); if (lg(auts) == 1) auts = NULL; av = avma; for (iz=F->KCZ+1; iz<=F->KCZ2; iz++, set_avma(av)) { long p = F->FB[iz]; GEN pr_orbit, P = gel(F->LV,p); long j, J = lg(P); /* > 1 */ /* the P|p, NP > C2 are assumed in subgroup generated by FB + last P * with NP <= C2 is unramified --> check all but last */ if (pr_get_e(gel(P,J-1)) == 1) J--; if (J == 1) continue; if (DEBUGLEVEL>1) err_printf("%ld ", p); pr_orbit = auts? zero_zv(J-1): NULL; for (j = 1; j < J; j++) { GEN Nid, id, id0; if (pr_orbit) { if (pr_orbit[j]) continue; /* discard all primes in automorphism orbit simultaneously */ pr_orbit_fill(pr_orbit, auts, P, j); } id = id0 = pr_hnf(nf,gel(P,j)); Nid = pr_norm(gel(P,j)); for (nbtest=0;;) { if (Fincke_Pohst_ideal(NULL, F, nf, id, Nid, fact, 0, &fp, NULL, 0, 0, 0, NULL, NULL)) break; if (++nbtest > maxtry_HONEST) { if (DEBUGLEVEL) pari_warn(warner,"be_honest() failure on prime %Ps\n", gel(P,j)); return 0; } /* occurs at most once in the whole function */ for (i = 1, id = id0; i < lgsub; i++) { long ex = random_bits(RANDOM_BITS); if (ex) { GEN pr = gel(F->LP, F->subFB[i]); id = idealmulpowprime(nf, id, pr, utoipos(ex)); } } if (!equali1(gcoeff(id,N,N))) id = Q_primpart(id); if (expi(gcoeff(id,1,1)) > 100) id = idealred(nf, id); Nid = ZM_det_triangular(id); } } F->KCZ++; /* SUCCESS, "enlarge" factorbase */ } F->KCZ = KCZ0; return gc_bool(av,1); } /* all primes with N(P) <= BOUND factor on factorbase ? */ void bnftestprimes(GEN bnf, GEN BOUND) { pari_sp av0 = avma, av; ulong count = 0; GEN auts, p, nf = bnf_get_nf(bnf), Vbase = bnf_get_vbase(bnf); GEN fb = gen_sort_shallow(Vbase, (void*)&cmp_prime_ideal, cmp_nodata); ulong pmax = pr_get_smallp(veclast(fb)); /*largest p in factorbase*/ forprime_t S; FACT *fact; FB_t F; (void)recover_partFB(&F, Vbase, nf_get_degree(nf)); fact = (FACT*)stack_malloc((F.KC+1)*sizeof(FACT)); forprime_init(&S, gen_2, BOUND); auts = automorphism_matrices(nf, NULL); if (lg(auts) == 1) auts = NULL; av = avma; while (( p = forprime_next(&S) )) { GEN pr_orbit, vP; long j, J; if (DEBUGLEVEL == 1 && ++count > 1000) { err_printf("passing p = %Ps / %Ps\n", p, BOUND); count = 0; } set_avma(av); vP = idealprimedec_limit_norm(nf, p, BOUND); J = lg(vP); /* if last is unramified, all P|p in subgroup generated by FB: skip last */ if (J > 1 && pr_get_e(gel(vP,J-1)) == 1) J--; if (J == 1) continue; if (DEBUGLEVEL>1) err_printf("*** p = %Ps\n",p); pr_orbit = auts? zero_zv(J-1): NULL; for (j = 1; j < J; j++) { GEN P = gel(vP,j); long k = 0; if (pr_orbit) { if (pr_orbit[j]) continue; /* discard all primes in automorphism orbit simultaneously */ pr_orbit_fill(pr_orbit, auts, vP, j); } if (abscmpiu(p, pmax) > 0 || !(k = tablesearch(fb, P, &cmp_prime_ideal))) (void)SPLIT(&F, nf, pr_hnf(nf,P), Vbase, fact); if (DEBUGLEVEL>1) { err_printf(" Testing P = %Ps\n",P); if (k) err_printf(" #%ld in factor base\n",k); else err_printf(" is %Ps\n", isprincipal(bnf,P)); } } } set_avma(av0); } /* A t_MAT of complex floats, in fact reals. Extract a submatrix B * whose columns are definitely nonzero, i.e. gexpo(A[j]) >= -2 * * If possible precision problem (t_REAL 0 with large exponent), set * *precpb to 1 */ static GEN clean_cols(GEN A, int *precpb) { long l = lg(A), h, i, j, k; GEN B; *precpb = 0; if (l == 1) return A; h = lgcols(A);; B = cgetg(l, t_MAT); for (i = k = 1; i < l; i++) { GEN Ai = gel(A,i); int non0 = 0; for (j = 1; j < h; j++) { GEN c = gel(Ai,j); if (gexpo(c) >= -2) { if (gequal0(c)) *precpb = 1; else non0 = 1; } } if (non0) gel(B, k++) = Ai; } setlg(B, k); return B; } static long compute_multiple_of_R_pivot(GEN X, GEN x0/*unused*/, long ix, GEN c) { GEN x = gel(X,ix); long i, k = 0, ex = - (long)HIGHEXPOBIT, lx = lg(x); (void)x0; for (i=1; i ex) { ex = e; k = i; } } return (k && ex > -32)? k: lx; } /* Ar = (log |sigma_i(u_j)|) for units (u_j) found so far; * RU = R1+R2 = target rank for unit matrix, after adding [1 x r1, 2 x r2]; * 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 Ar, long RU, long N, long *pneed, long *bit, GEN *ptL) { GEN T, d, mdet, Im_mdet, kR, L; long i, j, r, R1 = 2*RU - N; int precpb; pari_sp av = avma; if (RU == 1) { *ptL = zeromat(0, lg(Ar)-1); return gen_1; } if (DEBUGLEVEL) err_printf("\n#### Computing regulator multiple\n"); mdet = clean_cols(Ar, &precpb); /* will cause precision to increase on later failure, but we may succeed! */ *ptL = precpb? NULL: gen_1; T = cgetg(RU+1,t_COL); for (i=1; i<=R1; i++) gel(T,i) = gen_1; for ( ; i<=RU; i++) gel(T,i) = gen_2; mdet = shallowconcat(T, mdet); /* det(Span(mdet)) = N * R */ /* could be using indexrank(), but need custom "get_pivot" function */ d = RgM_pivots(mdet, NULL, &r, &compute_multiple_of_R_pivot); /* # of independent columns = target rank ? */ if (lg(mdet)-1 - r != RU) { if (DEBUGLEVEL) err_printf("Units matrix target rank = %ld < %ld\n",lg(mdet)-1 - r, RU); *pneed = RU - (lg(mdet)-1-r); return gc_NULL(av); } Im_mdet = cgetg(RU+1, t_MAT); /* extract independent columns */ /* N.B: d[1] = 1, corresponding to T above */ gel(Im_mdet, 1) = T; for (i = j = 2; i <= RU; j++) if (d[j]) gel(Im_mdet, i++) = gel(mdet,j); /* integral multiple of R: the cols we picked form a Q-basis, they have an * index in the full lattice. First column is T */ kR = divru(det2(Im_mdet), N); /* R > 0.2 uniformly */ if (!signe(kR) || expo(kR) < -3) { if (DEBUGLEVEL) err_printf("Regulator is zero.\n"); *pneed = 0; return gc_NULL(av); } d = det2(rowslice(vecslice(Im_mdet, 2, RU), 2, RU)); setabssign(d); setabssign(kR); if (gexpo(gsub(d,kR)) - gexpo(d) > -20) { *ptL = NULL; return gc_NULL(av); } L = RgM_inv(Im_mdet); /* estimate # of correct bits in result */ if (!L || (*bit = -gexpo(RgM_Rg_sub_shallow(RgM_mul(L,Im_mdet), gen_1))) < 16) { *ptL = NULL; return gc_NULL(av); } *ptL = RgM_mul(rowslice(L,2,RU), Ar); /* approximate rational entries */ return gc_all(av,2, &kR, ptL); } /* leave small integer n as is, convert huge n to t_REAL (for readability) */ static GEN i2print(GEN n) { return lgefint(n) <= DEFAULTPREC? n: itor(n,LOWDEFAULTPREC); } static long bad_check(GEN c) { long ec = gexpo(c); if (DEBUGLEVEL) err_printf("\n ***** check = %.28Pg\n",c); /* safe check for c < 0.75 : avoid underflow in gtodouble() */ if (ec < -1 || (ec == -1 && gtodouble(c) < 0.75)) return fupb_PRECI; /* safe check for c > 1.3 : avoid overflow */ if (ec > 0 || (ec == 0 && gtodouble(c) > 1.3)) return fupb_RELAT; return fupb_NONE; } /* 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, *ptL = numerator(units) (in terms of lambda) */ static long compute_R(GEN lambda, GEN z, GEN *ptL, GEN *ptkR) { pari_sp av = avma; long bit, r, reason, RU = lg(lambda) == 1? 1: lgcols(lambda); GEN L, H, D, den, R, c; *ptL = NULL; if (RU == 1) { *ptkR = gen_1; *ptL = lambda; return bad_check(z); } D = gmul2n(mpmul(*ptkR,z), 1); /* bound for denom(lambda) */ if (expo(D) < 0 && rtodbl(D) < 0.95) return fupb_PRECI; L = bestappr(lambda,D); if (lg(L) == 1) { if (DEBUGLEVEL) err_printf("truncation error in bestappr\n"); return fupb_PRECI; } den = Q_denom(L); if (mpcmp(den,D) > 0) { if (DEBUGLEVEL) err_printf("D = %Ps\nden = %Ps\n",D, i2print(den)); return fupb_PRECI; } bit = -gexpo(gsub(L, lambda)); /* input accuracy */ L = Q_muli_to_int(L, den); if (gexpo(L) + expi(den) > bit - 32) { if (DEBUGLEVEL) err_printf("dubious bestappr; den = %Ps\n", i2print(den)); return fupb_PRECI; } H = ZM_hnf(L); r = lg(H)-1; if (!r || r != nbrows(H)) R = gen_0; /* wrong rank */ else R = gmul(*ptkR, gdiv(ZM_det_triangular(H), powiu(den, r))); /* R = tentative regulator; regulator > 0.2 uniformly */ if (gexpo(R) < -3) { if (DEBUGLEVEL) err_printf("\n#### Tentative regulator: %.28Pg\n", R); return gc_long(av, fupb_PRECI); } c = gmul(R,z); /* should be n (= 1 if we are done) */ if (DEBUGLEVEL) err_printf("\n#### Tentative regulator: %.28Pg\n", R); if ((reason = bad_check(c))) return gc_long(av, reason); *ptkR = R; *ptL = L; return fupb_NONE; } static GEN get_clg2(GEN cyc, GEN Ga, GEN C, GEN Ur, GEN Ge, GEN M1, GEN M2) { GEN GD = gsub(act_arch(M1, C), diagact_arch(cyc, Ga)); GEN ga = gsub(act_arch(M2, C), act_arch(Ur, Ga)); return mkvecn(6, Ur, ga, GD, Ge, M1, M2); } /* compute class group (clg1) + data for isprincipal (clg2) */ static GEN class_group_gen(GEN nf,GEN W,GEN C,GEN Vbase,long prec, GEN *pclg2) { GEN M1, M2, z, G, Ga, Ge, cyc, X, Y, D, U, V, Ur, Ui, Uir; long j, l; D = ZM_snfall(W,&U,&V); /* UWV=D, D diagonal, G = g Ui (G=new gens, g=old) */ Ui = ZM_inv(U, NULL); l = lg(D); cyc = cgetg(l, t_VEC); /* elementary divisors */ for (j = 1; j < l; j++) { gel(cyc,j) = gcoeff(D,j,j); /* strip useless components */ if (is_pm1(gel(cyc,j))) break; } l = j; Ur = ZM_hnfdivrem(U, D, &Y); Uir = ZM_hnfdivrem(Ui,W, &X); /* {x} = logarithmic embedding of x (arch. component) * NB: [J,z] = idealred(I) --> I = y J, with {y} = - z * G = g Uir - {Ga}, Uir = Ui + WX * g = G Ur - {ga}, Ur = U + DY */ G = cgetg(l,t_VEC); Ga= cgetg(l,t_MAT); Ge= cgetg(l,t_COL); z = init_famat(NULL); for (j = 1; j < l; j++) { GEN I = genback(z, nf, Vbase, gel(Uir,j)); gel(G,j) = gel(I,1); /* generator, order cyc[j] */ gel(Ge,j)= gel(I,2); gel(Ga,j)= nf_cxlog(nf, gel(I,2), prec); if (!gel(Ga,j)) pari_err_PREC("class_group_gen"); } /* {ga} = {GD}Y + G U - g = {GD}Y - {Ga} U + gW X U = gW (X Ur + V Y) - {Ga}Ur */ M2 = ZM_add(ZM_mul(X,Ur), ZM_mul(V,Y)); setlg(cyc,l); setlg(V,l); setlg(D,l); /* G D =: {GD} = g (Ui + W X) D - {Ga}D = g W (V + X D) - {Ga}D * NB: Ui D = W V. gW is given by (first l-1 cols of) C */ M1 = ZM_add(V, ZM_mul(X,D)); *pclg2 = get_clg2(cyc, Ga, C, Ur, Ge, M1, M2); return mkvec3(ZV_prod(cyc), cyc, G); } /* compute principal ideals corresponding to (gen[i]^cyc[i]) */ static GEN makecycgen(GEN bnf) { GEN cyc = bnf_get_cyc(bnf), gen = bnf_get_gen(bnf), nf = bnf_get_nf(bnf); GEN h, y, GD = bnf_get_GD(bnf), W = bnf_get_W(bnf); /* HNF */ GEN Sunits = bnf_get_sunits(bnf); GEN X = Sunits? gel(Sunits,1): NULL, C = Sunits? gel(Sunits,3): NULL; long e, i, l; if (DEBUGLEVEL) pari_warn(warner,"completing bnf (building cycgen)"); h = cgetg_copy(gen, &l); for (i = 1; i < l; i++) { GEN gi = gel(gen,i), ci = gel(cyc,i); if (X && equalii(ci, gcoeff(W,i,i))) { long j; for (j = i+1; j < l; j++) if (signe(gcoeff(W,i,j))) break; if (j == i) { gel(h,i) = mkmat2(X, gel(C,i)); continue; } } if (abscmpiu(ci, 5) < 0) { GEN N = ZM_det_triangular(gi); y = isprincipalarch(bnf,gel(GD,i), N, ci, gen_1, &e); if (y && fact_ok(nf,y,NULL,mkvec(gi),mkvec(ci))) { gel(h,i) = to_famat_shallow(y,gen_1); continue; } } y = isprincipalfact(bnf, NULL, mkvec(gi), mkvec(ci), nf_GENMAT|nf_FORCE); gel(h,i) = gel(y,2); } return h; } static GEN get_y(GEN bnf, GEN W, GEN B, GEN C, GEN pFB, long j) { GEN y, nf = bnf_get_nf(bnf); long e, lW = lg(W)-1; GEN ex = (j<=lW)? gel(W,j): gel(B,j-lW); GEN P = (j<=lW)? NULL: gel(pFB,j); if (C) { /* archimedean embeddings known: cheap trial */ GEN Nx = get_norm_fact_primes(pFB, ex, P); y = isprincipalarch(bnf,gel(C,j), Nx,gen_1, gen_1, &e); if (y && fact_ok(nf,y,P,pFB,ex)) return y; } y = isprincipalfact_or_fail(bnf, P, pFB, ex); return typ(y) == t_INT? y: gel(y,2); } /* compute principal ideals corresponding to bnf relations */ static GEN makematal(GEN bnf) { GEN W = bnf_get_W(bnf), B = bnf_get_B(bnf), C = bnf_get_C(bnf); GEN pFB, ma, retry; long lma, j, prec = 0; if (DEBUGLEVEL) pari_warn(warner,"completing bnf (building matal)"); lma=lg(W)+lg(B)-1; pFB = bnf_get_vbase(bnf); ma = cgetg(lma,t_VEC); retry = vecsmalltrunc_init(lma); for (j=lma-1; j>0; j--) { pari_sp av = avma; GEN y = get_y(bnf, W, B, C, pFB, j); if (typ(y) == t_INT) { long E = itos(y); if (DEBUGLEVEL>1) err_printf("\n%ld done later at prec %ld\n",j,E); set_avma(av); vecsmalltrunc_append(retry, j); if (E > prec) prec = E; } else { if (DEBUGLEVEL>1) err_printf("%ld ",j); gel(ma,j) = gerepileupto(av,y); } } if (prec) { long k, l = lg(retry); GEN y, nf = bnf_get_nf(bnf); if (DEBUGLEVEL) pari_warn(warnprec,"makematal",prec); nf = nfnewprec_shallow(nf,prec); bnf = Buchall(nf, nf_FORCE, prec); if (DEBUGLEVEL) err_printf("makematal, adding missing entries:"); for (k=1; k1) err_printf("%ld ",j); gel(ma,j) = gerepileupto(av,y); } } if (DEBUGLEVEL>1) err_printf("\n"); return ma; } enum { MATAL = 1, CYCGEN, UNITS }; GEN bnf_build_cycgen(GEN bnf) { return obj_checkbuild(bnf, CYCGEN, &makecycgen); } GEN bnf_build_matalpha(GEN bnf) { return obj_checkbuild(bnf, MATAL, &makematal); } GEN bnf_build_units(GEN bnf) { return obj_checkbuild(bnf, UNITS, &makeunits); } /* return fu in compact form if available; in terms of a fixed basis * of S-units */ GEN bnf_compactfu_mat(GEN bnf) { GEN X, U, SUnits = bnf_get_sunits(bnf); if (!SUnits) return NULL; X = gel(SUnits,1); U = gel(SUnits,2); ZM_remove_unused(&U, &X); return mkvec2(X, U); } /* return fu in compact form if available; individually as famat */ GEN bnf_compactfu(GEN bnf) { GEN fu, X, U, SUnits = bnf_get_sunits(bnf); long i, l; if (!SUnits) return NULL; X = gel(SUnits,1); U = gel(SUnits,2); l = lg(U); fu = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(fu,i) = famat_remove_trivial(mkmat2(X, gel(U,i))); return fu; } /* return expanded fu if available */ GEN bnf_has_fu(GEN bnf) { GEN fu = obj_check(bnf, UNITS); if (fu) return vecsplice(fu, 1); fu = bnf_get_fu_nocheck(bnf); return (typ(fu) == t_MAT)? NULL: fu; } /* return expanded fu if available; build if cheap */ GEN bnf_build_cheapfu(GEN bnf) { GEN fu, SUnits; if ((fu = bnf_has_fu(bnf))) return fu; if ((SUnits = bnf_get_sunits(bnf))) { pari_sp av = avma; long e = gexpo(real_i(bnf_get_logfu(bnf))); set_avma(av); if (e < 13) return vecsplice(bnf_build_units(bnf), 1); } return NULL; } static GEN get_regulator(GEN A) { pari_sp av = avma; GEN R; if (lg(A) == 1) return gen_1; R = det( rowslice(real_i(A), 1, lgcols(A)-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, l = lg(x); GEN M = cgetg(l, t_MAT); if (l == 1) return M; N = nf_get_degree(nf); for (k = 1; k < l; k++) { pari_sp av = avma; GEN c = nf_cxlog(nf, gel(x,k), prec); if (!c || (!units && !(c = cleanarch(c, N, NULL,prec)))) return NULL; gel(M,k) = gerepilecopy(av, c); } return M; } static void Sunits_archclean(GEN nf, GEN Sunits, GEN *pmun, GEN *pC, long prec) { GEN ipi, M, X = gel(Sunits,1), U = gel(Sunits,2), G = gel(Sunits,3); long k, N = nf_get_degree(nf), l = lg(X); M = cgetg(l, t_MAT); for (k = 1; k < l; k++) if (!(gel(M,k) = nf_cxlog(nf, gel(X,k), prec))) return; ipi = invr(mppi(prec)); *pmun = cleanarch(RgM_ZM_mul(M, U), N, ipi, prec); /* not cleanarchunit ! */ if (*pmun) *pC = cleanarch(RgM_ZM_mul(M, G), N, ipi, prec); } GEN bnfnewprec_shallow(GEN bnf, long prec) { GEN nf0 = bnf_get_nf(bnf), nf, v, fu, matal, y, A, C; GEN Sunits = bnf_get_sunits(bnf), Ur, Ga, Ge, M1, M2; long r1, r2, prec0 = prec; nf_get_sign(nf0, &r1, &r2); if (Sunits) { fu = matal = NULL; prec += nbits2extraprec(gexpo(Sunits)); } else { fu = bnf_build_units(bnf); fu = vecslice(fu, 2, lg(fu)-1); if (r1 + r2 > 1) { long e = gexpo(bnf_get_logfu(bnf)) + 1 - TWOPOTBITS_IN_LONG; if (e >= 0) prec += nbits2extraprec(e); } matal = bnf_build_matalpha(bnf); } if (DEBUGLEVEL && prec0 != prec) pari_warn(warnprec,"bnfnewprec",prec); for(C = NULL;;) { pari_sp av = avma; nf = nfnewprec_shallow(nf0,prec); if (Sunits) Sunits_archclean(nf, Sunits, &A, &C, prec); else { A = get_archclean(nf, fu, prec, 1); if (A) C = get_archclean(nf, matal, prec, 0); } if (C) break; set_avma(av); prec = precdbl(prec); if (DEBUGLEVEL) pari_warn(warnprec,"bnfnewprec(extra)",prec); } y = leafcopy(bnf); gel(y,3) = A; gel(y,4) = C; gel(y,7) = nf; gel(y,8) = v = leafcopy(gel(bnf,8)); gel(v,2) = get_regulator(A); v = gel(bnf,9); if (lg(v) < 7) pari_err_TYPE("bnfnewprec [obsolete bnf format]", bnf); Ur = gel(v,1); Ge = gel(v,4); Ga = nfV_cxlog(nf, Ge, prec); M1 = gel(v,5); M2 = gel(v,6); gel(y,9) = get_clg2(bnf_get_cyc(bnf), Ga, C, Ur, Ge, M1, M2); 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 GEN buchall_end(GEN nf,GEN res, GEN clg2, GEN W, GEN B, GEN A, GEN C,GEN Vbase) { GEN z = obj_init(9, 3); 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; return z; } GEN bnfinit0(GEN P, long flag, GEN data, long prec) { double c1 = 0., c2 = 0.; long fl, relpid = BNF_RELPID; if (data) { long lx = lg(data); if (typ(data) != t_VEC || lx > 5) pari_err_TYPE("bnfinit",data); switch(lx) { case 4: relpid = itos(gel(data,3)); case 3: c2 = gtodouble(gel(data,2)); case 2: c1 = gtodouble(gel(data,1)); } } switch(flag) { case 2: case 0: fl = 0; break; case 1: fl = nf_FORCE; break; default: pari_err_FLAG("bnfinit"); return NULL; /* LCOV_EXCL_LINE */ } return Buchall_param(P, c1, c2, relpid, fl, prec); } GEN Buchall(GEN P, long flag, long prec) { return Buchall_param(P, 0., 0., BNF_RELPID, flag & nf_FORCE, prec); } static GEN Buchall_deg1(GEN nf) { GEN v = cgetg(1,t_VEC), m = cgetg(1,t_MAT); GEN res, W, A, B, C, Vbase = cgetg(1,t_COL); GEN fu = v, R = gen_1, zu = mkvec2(gen_2, gen_m1); GEN clg1 = mkvec3(gen_1,v,v), clg2 = mkvecn(6, m,m,m,v,m,m); W = A = B = C = m; res = mkvec5(clg1, R, gen_1, 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 */ set_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 */ 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 = gel(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, pr_get_p(gel(P,1)), 0); } } /* Let z = \zeta_n in nf. List of not-obviously-dependent generators for * cyclotomic units modulo torsion in Q(z) [independent when n a prime power]: * - z^a - 1, n/(a,n) not a prime power, a \nmid n unless a=1, 1 <= a < n/2 * - (Z^a - 1)/(Z - 1), p^k || n, Z = z^{n/p^k}, (p,a) = 1, 1 < a <= (p^k-1)/2 */ GEN nfcyclotomicunits(GEN nf, GEN zu) { long n = itos(gel(zu, 1)), n2, lP, i, a; GEN z, fa, P, E, L, mz, powz; if (n <= 6) return cgetg(1, t_VEC); z = algtobasis(nf,gel(zu, 2)); if ((n & 3) == 2) { n = n >> 1; z = ZC_neg(z); } /* ensure n != 2 (mod 4) */ n2 = n/2; mz = zk_multable(nf, z); /* multiplication by z */ powz = cgetg(n2, t_VEC); gel(powz,1) = z; for (i = 2; i < n2; i++) gel(powz,i) = ZM_ZC_mul(mz, gel(powz,i-1)); /* powz[i] = z^i */ L = vectrunc_init(n); fa = factoru(n); P = gel(fa,1); lP = lg(P); E = gel(fa,2); for (i = 1; i < lP; i++) { /* second kind */ long p = P[i], k = E[i], pk = upowuu(p,k), pk2 = (pk-1) / 2; GEN u = gen_1; for (a = 2; a <= pk2; a++) { u = nfadd(nf, u, gel(powz, (n/pk) * (a-1))); /* = (Z^a-1)/(Z-1) */ if (a % p) vectrunc_append(L, u); } } if (lP > 2) for (a = 1; a < n2; a++) { /* first kind, when n not a prime power */ ulong p; if (a > 1 && (n % a == 0 || uisprimepower(n/ugcd(a,n), &p))) continue; vectrunc_append(L, nfadd(nf, gel(powz, a), gen_m1)); } return L; } static void add_cyclotomic_units(GEN nf, GEN zu, RELCACHE_t *cache, FB_t *F) { pari_sp av = avma; GEN L = nfcyclotomicunits(nf, zu); long i, l = lg(L); if (l > 1) { GEN R = zero_Flv(F->KC); for(i = 1; i < l; i++) add_rel(cache, F, R, F->KC+1, gel(L,i), 0); } set_avma(av); } static GEN trim_list(FB_t *F) { pari_sp av = avma; GEN v, L_jid = F->L_jid, minidx = F->minidx, present = zero_Flv(F->KC); long i, j, imax = minss(lg(L_jid), F->KC + 1); v = cgetg(imax, t_VECSMALL); for (i = j = 1; i < imax; i++) { long k = minidx[ L_jid[i] ]; if (!present[k]) { v[j++] = L_jid[i]; present[k] = 1; } } setlg(v, j); return gerepileuptoleaf(av, v); } /* x t_INT or primitive ZC */ static void try_elt(RELCACHE_t *cache, FB_t *F, GEN nf, GEN x, FACT *fact) { pari_sp av = avma; long nz; GEN R; if (typ(x) == t_INT /* 2nd path can't fail */ || !can_factor(F, nf, NULL, x, nfnorm(nf, x), fact)) return; /* smooth element */ R = set_fact(F, fact, NULL, &nz); /* make sure we get maximal rank first, then allow all relations */ (void)add_rel(cache, F, R, nz, x, 0); set_avma(av); } static void matenlarge(GEN C, long h) { GEN _0 = zerocol(h); long i; for (i = lg(C); --i; ) gel(C,i) = shallowconcat(gel(C,i), _0); } /* E = floating point embeddings */ static GEN matbotidembs(RELCACHE_t *cache, GEN E) { long w = cache->last - cache->chk, h = cache->last - cache->base; long j, d = h - w, hE = nbrows(E); GEN y = cgetg(w+1,t_MAT), _0 = zerocol(h); for (j = 1; j <= w; j++) { GEN c = shallowconcat(gel(E,j), _0); if (d + j >= 1) gel(c, d + j + hE) = gen_1; gel(y,j) = c; } return y; } static GEN matbotid(RELCACHE_t *cache) { long w = cache->last - cache->chk, h = cache->last - cache->base; long j, d = h - w; GEN y = cgetg(w+1,t_MAT); for (j = 1; j <= w; j++) { GEN c = zerocol(h); if (d + j >= 1) gel(c, d + j) = gen_1; gel(y,j) = c; } return y; } static long myprecdbl(long prec, GEN C) { long p = prec < 1280? precdbl(prec): (long)(prec * 1.5); if (C) p = maxss(p, minss(3*p, prec + nbits2extraprec(gexpo(C)))); return p; } static GEN _nfnewprec(GEN nf, long prec, long *isclone) { GEN NF = gclone(nfnewprec_shallow(nf, prec)); if (*isclone) gunclone(nf); *isclone = 1; return NF; } /* Nrelid = nb relations per ideal, possibly 0. If flag is set, keep data in * algebraic form. */ GEN Buchall_param(GEN P, double cbach, double cbach2, long Nrelid, long flag, long prec) { pari_timer T; pari_sp av0 = avma, av, av2; long PREC, N, R1, R2, RU, low, high, LIMC0, LIMC, LIMC2, LIMCMAX, zc, i; long LIMres, bit = 0, flag_nfinit = 0, nfisclone = 0; long nreldep, sfb_trials, need, old_need, precdouble = 0, TRIES = 0; long done_small, small_fail, fail_limit, squash_index; double LOGD, LOGD2, lim; GEN computed = NULL, fu = NULL, zu, nf, D, A, W, R, h, Ce, PERM; GEN small_multiplier, auts, cyclic, embs, SUnits; GEN res, L, invhr, B, C, lambda, dep, clg1, clg2, Vbase; const char *precpb = NULL; REL_t *old_cache = NULL; nfmaxord_t nfT; RELCACHE_t cache; FB_t F; GRHcheck_t GRHcheck; FACT *fact; if (DEBUGLEVEL) timer_start(&T); P = get_nfpol(P, &nf); if (degpol(P)==2) Nrelid = 0; if (nf) D = nf_get_disc(nf); else { nfinit_basic(&nfT, P); D = nfT.dK; if (!ZX_is_monic(nfT.T0)) { pari_warn(warner,"nonmonic polynomial in bnfinit, using polredbest"); flag_nfinit = nf_RED; } } PREC = maxss(DEFAULTPREC, prec); N = degpol(P); if (N <= 1) { if (!nf) nf = nfinit_complete(&nfT, flag_nfinit, PREC); return gerepilecopy(av0, Buchall_deg1(nf)); } D = absi_shallow(D); LOGD = dbllog2(D) * M_LN2; LOGD2 = LOGD*LOGD; LIMCMAX = (long)(4.*LOGD2); if (nf) PREC = maxss(PREC, nf_get_prec(nf)); PREC = maxss(PREC, nbits2prec((long)(LOGD2 * 0.02) + N*N)); if (DEBUGLEVEL) err_printf("PREC = %ld\n", PREC); if (!nf) nf = nfinit_complete(&nfT, flag_nfinit, PREC); else if (nf_get_prec(nf) < PREC) nf = nfnewprec_shallow(nf, PREC); zu = nfrootsof1(nf); gel(zu,2) = nf_to_scalar_or_alg(nf, gel(zu,2)); nf_get_sign(nf, &R1, &R2); RU = R1+R2; auts = automorphism_matrices(nf, &cyclic); F.embperm = automorphism_perms(nf_get_M(nf), auts, cyclic, R1, R2, N); if (DEBUGLEVEL) { timer_printf(&T, "nfinit & nfrootsof1"); err_printf("%s bnf: R1 = %ld, R2 = %ld\nD = %Ps\n", flag? "Algebraic": "Floating point", R1,R2, D); } if (LOGD < 20.) { /* tiny disc, Minkowski may be smaller than Bach */ lim = exp(-N + R2 * log(4/M_PI) + LOGD/2) * sqrt(2*M_PI*N); if (lim < 3) lim = 3; } else /* to be ignored */ lim = -1; if (cbach > 12.) { if (cbach2 < cbach) cbach2 = cbach; cbach = 12.; } if (cbach < 0.) pari_err_DOMAIN("Buchall","Bach constant","<",gen_0,dbltor(cbach)); cache.base = NULL; F.subFB = NULL; F.LP = NULL; SUnits = Ce = NULL; init_GRHcheck(&GRHcheck, N, R1, LOGD); high = low = LIMC0 = maxss((long)(cbach2*LOGD2), 1); while (!GRHchk(nf, &GRHcheck, high)) { low = high; high *= 2; } while (high - low > 1) { long test = (low+high)/2; if (GRHchk(nf, &GRHcheck, test)) high = test; else low = test; } LIMC2 = (high == LIMC0+1 && GRHchk(nf, &GRHcheck, LIMC0))? LIMC0: high; if (LIMC2 > LIMCMAX) LIMC2 = LIMCMAX; /* Assuming GRH, {P, NP <= LIMC2} generate Cl(K) */ if (DEBUGLEVEL) err_printf("LIMC2 = %ld\n", LIMC2); LIMC0 = (long)(cbach*LOGD2); /* initial value for LIMC */ LIMC = cbach? LIMC0: LIMC2; /* use {P, NP <= LIMC} as a factorbase */ LIMC = maxss(LIMC, nthideal(&GRHcheck, nf, N)); if (DEBUGLEVEL) timer_printf(&T, "computing Bach constant"); LIMres = primeneeded(N, R1, R2, LOGD); cache_prime_dec(&GRHcheck, LIMres, nf); /* invhr ~ 2^r1 (2pi)^r2 / sqrt(D) w * Res(zeta_K, s=1) = 1 / hR */ invhr = gmul(gdiv(gmul2n(powru(mppi(DEFAULTPREC), R2), RU), mulri(gsqrt(D,DEFAULTPREC),gel(zu,1))), compute_invres(&GRHcheck, LIMres)); if (DEBUGLEVEL) timer_printf(&T, "computing inverse of hR"); av = avma; START: if (DEBUGLEVEL) timer_start(&T); if (TRIES) LIMC = bnf_increase_LIMC(LIMC,LIMCMAX); if (DEBUGLEVEL && LIMC > LIMC0) err_printf("%s*** Bach constant: %f\n", TRIES?"\n":"", LIMC/LOGD2); if (cache.base) { REL_t *rel; for (i = 1, rel = cache.base + 1; rel < cache.last; rel++) if (rel->m) i++; computed = cgetg(i, t_VEC); for (i = 1, rel = cache.base + 1; rel < cache.last; rel++) if (rel->m) gel(computed, i++) = rel->m; computed = gclone(computed); delete_cache(&cache); } TRIES++; set_avma(av); if (F.LP) delete_FB(&F); if (LIMC2 < LIMC) LIMC2 = LIMC; if (DEBUGLEVEL) { err_printf("LIMC = %ld, LIMC2 = %ld\n",LIMC,LIMC2); } FBgen(&F, nf, N, LIMC, LIMC2, &GRHcheck); if (!F.KC) goto START; av = avma; subFBgen(&F,auts,cyclic,lim < 0? LIMC2: mindd(lim,LIMC2),MINSFB); if (lg(F.subFB) == 1) goto START; if (DEBUGLEVEL) timer_printf(&T, "factorbase (#subFB = %ld) and ideal permutations", lg(F.subFB)-1); fact = (FACT*)stack_malloc((F.KC+1)*sizeof(FACT)); PERM = leafcopy(F.perm); /* to be restored in case of precision increase */ cache.basis = zero_Flm_copy(F.KC,F.KC); small_multiplier = zero_Flv(F.KC); done_small = small_fail = squash_index = zc = sfb_trials = nreldep = 0; fail_limit = F.KC + 1; W = A = R = NULL; av2 = avma; init_rel(&cache, &F, RELSUP + RU-1); old_need = need = cache.end - cache.last; add_cyclotomic_units(nf, zu, &cache, &F); if (DEBUGLEVEL) err_printf("\n"); cache.end = cache.last + need; if (computed) { for (i = 1; i < lg(computed); i++) try_elt(&cache, &F, nf, gel(computed, i), fact); gunclone(computed); if (DEBUGLEVEL && i > 1) timer_printf(&T, "including already computed relations"); need = 0; } do { GEN Ar, C0; do { pari_sp av4 = avma; if (need > 0) { long oneed = cache.end - cache.last; /* Test below can be true if small_norm did not find enough linearly * dependent relations */ if (need < oneed) need = oneed; pre_allocate(&cache, need+lg(auts)-1+(R ? lg(W)-1 : 0)); cache.end = cache.last + need; F.L_jid = trim_list(&F); } if (need > 0 && Nrelid > 0 && (done_small <= F.KC+1 || A) && small_fail <= fail_limit && cache.last < cache.base + 2*F.KC+2*RU+RELSUP /* heuristic */) { long j, k, LIE = (R && lg(W) > 1 && (done_small % 2)); REL_t *last = cache.last; pari_sp av3 = avma; if (LIE) { /* We have full rank for class group and unit. The following tries to * improve the prime group lattice by looking for relations involving * the primes generating the class group. */ long n = lg(W)-1; /* need n relations to squash the class group */ F.L_jid = vecslice(F.perm, 1, n); cache.end = cache.last + n; /* Lie to the add_rel subsystem: pretend we miss relations involving * the primes generating the class group (and only those). */ cache.missing = n; for ( ; n > 0; n--) mael(cache.basis, F.perm[n], F.perm[n]) = 0; } j = done_small % (F.KC+1); if (j && !A) { /* Prevent considering both P_iP_j and P_jP_i in small_norm */ /* Not all elements end up in F.L_jid (eliminated by hnfspec/add or * by trim_list): keep track of which ideals are being considered * at each run. */ long mj = small_multiplier[j]; for (i = k = 1; i < lg(F.L_jid); i++) if (F.L_jid[i] > mj) { small_multiplier[F.L_jid[i]] = j; F.L_jid[k++] = F.L_jid[i]; } setlg(F.L_jid, k); } if (lg(F.L_jid) > 1) small_norm(&cache, &F, nf, Nrelid, fact, j); F.L_jid = F.perm; set_avma(av3); if (!A && cache.last != last) small_fail = 0; else small_fail++; if (LIE) { /* restore add_rel subsystem: undo above lie */ long n = lg(W) - 1; for ( ; n > 0; n--) mael(cache.basis, F.perm[n], F.perm[n]) = 1; cache.missing = 0; } cache.end = cache.last; done_small++; need = F.sfb_chg = 0; } if (need > 0) { /* Random relations */ if (++nreldep > F.MAXDEPSIZESFB) { if (++sfb_trials > SFB_MAX && LIMC < LIMCMAX/2) goto START; F.sfb_chg = sfb_INCREASE; nreldep = 0; } else if (!(nreldep % F.MAXDEPSFB)) F.sfb_chg = sfb_CHANGE; if (F.sfb_chg && !subFB_change(&F)) goto START; rnd_rel(&cache, &F, nf, fact); F.L_jid = F.perm; } if (DEBUGLEVEL) timer_start(&T); if (precpb) { REL_t *rel; if (DEBUGLEVEL) { char str[64]; sprintf(str,"Buchall_param (%s)",precpb); pari_warn(warnprec,str,PREC); } nf = _nfnewprec(nf, PREC, &nfisclone); precdouble++; precpb = NULL; if (flag) { /* recompute embs only, no need to redo HNF */ long j, le = lg(embs), lC = lg(C); GEN E, M = nf_get_M(nf); set_avma(av4); for (rel = cache.base+1, i = 1; i < le; i++,rel++) gel(embs,i) = rel_embed(rel, &F, embs, i, M, RU, R1, PREC); E = RgM_ZM_mul(embs, rowslice(C, RU+1, nbrows(C))); for (j = 1; j < lC; j++) for (i = 1; i <= RU; i++) gcoeff(C,i,j) = gcoeff(E,i,j); av4 = avma; } else { /* recompute embs + HNF */ for(i = 1; i < lg(PERM); i++) F.perm[i] = PERM[i]; cache.chk = cache.base; W = NULL; } if (DEBUGLEVEL) timer_printf(&T, "increasing accuracy"); } set_avma(av4); if (cache.chk != cache.last) { /* Reduce relation matrices */ long l = cache.last - cache.chk + 1, j; GEN mat = cgetg(l, t_MAT); REL_t *rel; for (j=1,rel = cache.chk + 1; j < l; rel++,j++) gel(mat,j) = rel->R; if (!flag || W) { embs = get_embs(&F, &cache, nf, embs, PREC); if (DEBUGLEVEL && timer_get(&T) > 1) timer_printf(&T, "floating point embeddings"); } if (!W) { /* never reduced before */ C = flag? matbotid(&cache): embs; W = hnfspec_i(mat, F.perm, &dep, &B, &C, F.subFB ? lg(F.subFB)-1:0); if (DEBUGLEVEL) timer_printf(&T, "hnfspec [%ld x %ld]", lg(F.perm)-1, l-1); if (flag) { PREC += nbits2extraprec(gexpo(C)); if (nf_get_prec(nf) < PREC) nf = _nfnewprec(nf, PREC, &nfisclone); embs = get_embs(&F, &cache, nf, embs, PREC); C = vconcat(RgM_ZM_mul(embs, C), C); } if (DEBUGLEVEL) timer_printf(&T, "hnfspec floating points"); } else { long k = lg(embs); GEN E = vecslice(embs, k-l+1,k-1); if (flag) { E = matbotidembs(&cache, E); matenlarge(C, cache.last - cache.chk); } W = hnfadd_i(W, F.perm, &dep, &B, &C, mat, E); if (DEBUGLEVEL) timer_printf(&T, "hnfadd (%ld + %ld)", l-1, lg(dep)-1); } gerepileall(av2, 5, &W,&C,&B,&dep,&embs); cache.chk = cache.last; } else if (!W) { need = old_need; F.L_jid = vecslice(F.perm, 1, need); continue; } need = F.KC - (lg(W)-1) - (lg(B)-1); if (!need && cache.missing) { /* The test above will never be true except if 27449|class number. * Ensure that if we have maximal rank for the ideal lattice, then * cache.missing == 0. */ for (i = 1; cache.missing; i++) if (!mael(cache.basis, i, i)) { long j; cache.missing--; mael(cache.basis, i, i) = 1; 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 (RU-1-zc > 0) need = minss(need + RU-1-zc, F.KC); /* for units */ if (need) { /* dependent rows */ F.L_jid = vecslice(F.perm, 1, need); vecsmall_sort(F.L_jid); if (need != old_need) { nreldep = 0; old_need = need; } } else { /* If the relation lattice is too small, check will be > 1 and we will * do a new run of small_norm/rnd_rel asking for 1 relation. This often * gives a relation involving L_jid[1]. We rotate the first element of * L_jid in order to increase the probability of finding relations that * increases the lattice. */ long j, n = lg(W) - 1; if (n > 1 && squash_index % n) { F.L_jid = leafcopy(F.perm); for (j = 1; j <= n; j++) F.L_jid[j] = F.perm[1 + (j + squash_index - 1) % n]; } else F.L_jid = F.perm; squash_index++; } } while (need); if (!A) { small_fail = old_need = 0; fail_limit = maxss(F.KC / FAIL_DIVISOR, MINFAIL); } A = vecslice(C, 1, zc); /* cols corresponding to units */ if (flag) A = rowslice(A, 1, RU); Ar = real_i(A); R = compute_multiple_of_R(Ar, RU, N, &need, &bit, &lambda); if (need < old_need) small_fail = 0; #if 0 /* A good idea if we are indeed stuck but needs tuning */ /* we have computed way more relations than should be necessary */ if (TRIES < 3 && LIMC < LIMCMAX / 8 && cache.last - cache.base > 10 * F.KC) goto START; #endif old_need = need; if (!lambda) { precpb = "bestappr"; PREC = myprecdbl(PREC, flag? C: NULL); continue; } if (!R) { /* not full rank for units */ if (!need) { precpb = "regulator"; PREC = myprecdbl(PREC, flag? C: NULL); } continue; } if (cache.last==old_cache) { need=1; continue; } old_cache = cache.last; h = ZM_det_triangular(W); if (DEBUGLEVEL) err_printf("\n#### Tentative class number: %Ps\n", h); i = compute_R(lambda, mulir(h,invhr), &L, &R); if (DEBUGLEVEL) { err_printf("\n"); timer_printf(&T, "computing regulator and check"); } switch(i) { case fupb_RELAT: need = 1; /* not enough relations */ continue; case fupb_PRECI: /* prec problem unless we cheat on Bach constant */ if ((precdouble&7) == 7 && LIMC <= LIMCMAX/2) goto START; precpb = "compute_R"; PREC = myprecdbl(PREC, flag? C: NULL); continue; } /* DONE */ if (F.KCZ2 > F.KCZ) { if (F.sfb_chg && !subFB_change(&F)) goto START; if (!be_honest(&F, nf, auts, fact)) goto START; if (DEBUGLEVEL) timer_printf(&T, "to be honest"); } F.KCZ2 = 0; /* be honest only once */ /* fundamental units */ { GEN AU, CU, U, v = extract_full_lattice(L); /* L may be large */ CU = NULL; if (v) { A = vecpermute(A, v); L = vecpermute(L, v); } /* arch. components of fund. units */ U = ZM_lll(L, 0.99, LLL_IM); U = ZM_mul(U, lll(RgM_ZM_mul(real_i(A), U))); if (DEBUGLEVEL) timer_printf(&T, "units LLL"); AU = RgM_ZM_mul(A, U); A = cleanarchunit(AU, N, NULL, PREC); if (RU > 1 /* if there are fund units, test we have correct regulator */ && (!A || lg(A) < RU || expo(subrr(get_regulator(A), R)) > -1)) { long add = nbits2extraprec( gexpo(AU) + 64 ) - gprecision(AU); long t = maxss(PREC * 0.15, add); if (!A && DEBUGLEVEL) err_printf("### Incorrect units lognorm"); precpb = "cleanarch"; PREC += maxss(t, EXTRAPREC64); continue; } if (flag) { long l = lgcols(C) - RU; REL_t *rel; SUnits = cgetg(l, t_COL); for (rel = cache.base+1, i = 1; i < l; i++,rel++) set_rel_alpha(rel, auts, SUnits, i); if (RU > 1) { GEN c = v? vecpermute(C,v): vecslice(C,1,zc); CU = ZM_mul(rowslice(c, RU+1, nbrows(c)), U); } } if (DEBUGLEVEL) err_printf("\n#### Computing fundamental units\n"); fu = getfu(nf, &A, CU? &U: NULL, PREC); CU = CU? ZM_mul(CU, U): cgetg(1, t_MAT); if (DEBUGLEVEL) timer_printf(&T, "getfu"); Ce = vecslice(C, zc+1, lg(C)-1); if (flag) SUnits = mkvec4(SUnits, CU, rowslice(Ce, RU+1, nbrows(Ce)), utoipos(LIMC)); } /* class group generators */ if (flag) Ce = rowslice(Ce, 1, RU); C0 = Ce; Ce = cleanarch(Ce, N, NULL, PREC); if (!Ce) { long add = nbits2extraprec( gexpo(C0) + 64 ) - gprecision(C0); precpb = "cleanarch"; PREC += maxss(add, 1); } if (DEBUGLEVEL) timer_printf(&T, "cleanarch"); } while (need || precpb); Vbase = vecpermute(F.LP, F.perm); if (!fu) fu = cgetg(1, t_MAT); if (!SUnits) SUnits = gen_1; clg1 = class_group_gen(nf,W,Ce,Vbase,PREC, &clg2); res = mkvec5(clg1, R, SUnits, zu, fu); res = buchall_end(nf,res,clg2,W,B,A,Ce,Vbase); delete_FB(&F); res = gerepilecopy(av0, res); if (flag) obj_insert_shallow(res, MATAL, cgetg(1,t_VEC)); if (nfisclone) gunclone(nf); delete_cache(&cache); free_GRHcheck(&GRHcheck); return res; } pari-2.17.2/src/basemath/alglin1.c0000644000175000017500000042302614760123736015252 0ustar billbill/* Copyright (C) 2000, 2012 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /********************************************************************/ /** **/ /** LINEAR ALGEBRA **/ /** (first part) **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_mat /*******************************************************************/ /* */ /* GEREPILE */ /* */ /*******************************************************************/ static void gerepile_mat(pari_sp av, pari_sp tetpil, GEN x, long k, long m, long n, long t) { pari_sp A, bot = pari_mainstack->bot; long u, i; size_t dec; (void)gerepile(av,tetpil,NULL); dec = av-tetpil; for (u=t+1; u<=m; u++) { A = (pari_sp)coeff(x,u,k); if (A < av && A >= bot) coeff(x,u,k) += dec; } for (i=k+1; i<=n; i++) for (u=1; u<=m; u++) { A = (pari_sp)coeff(x,u,i); if (A < av && A >= bot) coeff(x,u,i) += dec; } } static void gen_gerepile_gauss_ker(GEN x, long k, long t, pari_sp av, void *E, GEN (*copy)(void*, GEN)) { pari_sp tetpil = avma; long u,i, n = lg(x)-1, m = n? nbrows(x): 0; if (DEBUGMEM > 1) pari_warn(warnmem,"gauss_pivot_ker. k=%ld, n=%ld",k,n); for (u=t+1; u<=m; u++) gcoeff(x,u,k) = copy(E,gcoeff(x,u,k)); for (i=k+1; i<=n; i++) for (u=1; u<=m; u++) gcoeff(x,u,i) = copy(E,gcoeff(x,u,i)); gerepile_mat(av,tetpil,x,k,m,n,t); } /* special gerepile for huge matrices */ #define COPY(x) {\ GEN _t = (x); if (!is_universal_constant(_t)) x = gcopy(_t); \ } INLINE GEN _copy(void *E, GEN x) { (void) E; COPY(x); return x; } static void gerepile_gauss_ker(GEN x, long k, long t, pari_sp av) { gen_gerepile_gauss_ker(x, k, t, av, NULL, &_copy); } static void gerepile_gauss(GEN x,long k,long t,pari_sp av, long j, GEN c) { pari_sp tetpil = avma, A, bot; long u,i, n = lg(x)-1, m = n? nbrows(x): 0; size_t dec; if (DEBUGMEM > 1) pari_warn(warnmem,"gauss_pivot. k=%ld, n=%ld",k,n); for (u=t+1; u<=m; u++) if (u==j || !c[u]) COPY(gcoeff(x,u,k)); for (u=1; u<=m; u++) if (u==j || !c[u]) for (i=k+1; i<=n; i++) COPY(gcoeff(x,u,i)); (void)gerepile(av,tetpil,NULL); dec = av-tetpil; bot = pari_mainstack->bot; for (u=t+1; u<=m; u++) if (u==j || !c[u]) { A=(pari_sp)coeff(x,u,k); if (A=bot) coeff(x,u,k)+=dec; } for (u=1; u<=m; u++) if (u==j || !c[u]) for (i=k+1; i<=n; i++) { A=(pari_sp)coeff(x,u,i); if (A=bot) coeff(x,u,i)+=dec; } } /*******************************************************************/ /* */ /* GENERIC */ /* */ /*******************************************************************/ GEN gen_ker(GEN x, long deplin, void *E, const struct bb_field *ff) { pari_sp av0 = avma, av, tetpil; GEN y, c, d; long i, j, k, r, t, n, m; n=lg(x)-1; if (!n) return cgetg(1,t_MAT); m=nbrows(x); r=0; x = RgM_shallowcopy(x); c = zero_zv(m); d=new_chunk(n+1); av=avma; for (k=1; k<=n; k++) { for (j=1; j<=m; j++) if (!c[j]) { gcoeff(x,j,k) = ff->red(E, gcoeff(x,j,k)); if (!ff->equal0(gcoeff(x,j,k))) break; } if (j>m) { if (deplin) { GEN c = cgetg(n+1, t_COL), g0 = ff->s(E,0), g1=ff->s(E,1); for (i=1; ired(E, gcoeff(x,d[i],k)); gel(c,k) = g1; for (i=k+1; i<=n; i++) gel(c,i) = g0; return gerepileupto(av0, c); } r++; d[k]=0; for(j=1; jneg(E,ff->inv(E,gcoeff(x,j,k))); c[j] = k; d[k] = j; gcoeff(x,j,k) = ff->s(E,-1); for (i=k+1; i<=n; i++) gcoeff(x,j,i) = ff->red(E,ff->mul(E,piv,gcoeff(x,j,i))); for (t=1; t<=m; t++) { if (t==j) continue; piv = ff->red(E,gcoeff(x,t,k)); if (ff->equal0(piv)) continue; gcoeff(x,t,k) = ff->s(E,0); for (i=k+1; i<=n; i++) gcoeff(x,t,i) = ff->red(E, ff->add(E, gcoeff(x,t,i), ff->mul(E,piv,gcoeff(x,j,i)))); if (gc_needed(av,1)) gen_gerepile_gauss_ker(x,k,t,av,E,ff->red); } } } if (deplin) return gc_NULL(av0); tetpil=avma; y=cgetg(r+1,t_MAT); for (j=k=1; j<=r; j++,k++) { GEN C = cgetg(n+1,t_COL); GEN g0 = ff->s(E,0), g1 = ff->s(E,1); gel(y,j) = C; while (d[k]) k++; for (i=1; ired(E,p1); gunclone(p1); } else gel(C,i) = g0; gel(C,k) = g1; for (i=k+1; i<=n; i++) gel(C,i) = g0; } return gerepile(av0,tetpil,y); } GEN gen_Gauss_pivot(GEN x, long *rr, void *E, const struct bb_field *ff) { pari_sp av; GEN c, d; long i, j, k, r, t, m, n = lg(x)-1; if (!n) { *rr = 0; return NULL; } m=nbrows(x); r=0; d = cgetg(n+1, t_VECSMALL); x = RgM_shallowcopy(x); c = zero_zv(m); av=avma; for (k=1; k<=n; k++) { for (j=1; j<=m; j++) if (!c[j]) { gcoeff(x,j,k) = ff->red(E,gcoeff(x,j,k)); if (!ff->equal0(gcoeff(x,j,k))) break; } if (j>m) { r++; d[k]=0; } else { GEN piv = ff->neg(E,ff->inv(E,gcoeff(x,j,k))); GEN g0 = ff->s(E,0); c[j] = k; d[k] = j; for (i=k+1; i<=n; i++) gcoeff(x,j,i) = ff->red(E,ff->mul(E,piv,gcoeff(x,j,i))); for (t=1; t<=m; t++) { if (c[t]) continue; /* already a pivot on that line */ piv = ff->red(E,gcoeff(x,t,k)); if (ff->equal0(piv)) continue; gcoeff(x,t,k) = g0; for (i=k+1; i<=n; i++) gcoeff(x,t,i) = ff->red(E, ff->add(E,gcoeff(x,t,i), ff->mul(E,piv,gcoeff(x,j,i)))); if (gc_needed(av,1)) gerepile_gauss(x,k,t,av,j,c); } for (i=k; i<=n; i++) gcoeff(x,j,i) = g0; /* dummy */ } } *rr = r; return gc_const((pari_sp)d, d); } GEN gen_det(GEN a, void *E, const struct bb_field *ff) { pari_sp av = avma; long i,j,k, s = 1, nbco = lg(a)-1; GEN x = ff->s(E,1); if (!nbco) return x; a = RgM_shallowcopy(a); for (i=1; ired(E,gcoeff(a,k,i)); if (!ff->equal0(gcoeff(a,k,i))) break; } if (k > nbco) return gerepileupto(av, gcoeff(a,i,i)); if (k != i) { /* exchange the lines s.t. k = i */ for (j=i; j<=nbco; j++) swap(gcoeff(a,i,j), gcoeff(a,k,j)); s = -s; } q = gcoeff(a,i,i); x = ff->red(E,ff->mul(E,x,q)); q = ff->inv(E,q); for (k=i+1; k<=nbco; k++) { GEN m = ff->red(E,gcoeff(a,i,k)); if (ff->equal0(m)) continue; m = ff->neg(E, ff->red(E,ff->mul(E,m, q))); for (j=i+1; j<=nbco; j++) gcoeff(a,j,k) = ff->red(E, ff->add(E, gcoeff(a,j,k), ff->mul(E, m, gcoeff(a,j,i)))); } if (gc_needed(av,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"det. col = %ld",i); gerepileall(av,2, &a,&x); } } if (s < 0) x = ff->neg(E,x); return gerepileupto(av, ff->red(E,ff->mul(E, x, gcoeff(a,nbco,nbco)))); } INLINE void _gen_addmul(GEN b, long k, long i, GEN m, void *E, const struct bb_field *ff) { gel(b,i) = ff->red(E,gel(b,i)); gel(b,k) = ff->add(E,gel(b,k), ff->mul(E,m, gel(b,i))); } static GEN _gen_get_col(GEN a, GEN b, long li, void *E, const struct bb_field *ff) { GEN u = cgetg(li+1,t_COL); pari_sp av = avma; long i, j; gel(u,li) = gerepileupto(av, ff->red(E,ff->mul(E,gel(b,li), gcoeff(a,li,li)))); for (i=li-1; i>0; i--) { pari_sp av = avma; GEN m = gel(b,i); for (j=i+1; j<=li; j++) m = ff->add(E,m, ff->neg(E,ff->mul(E,gcoeff(a,i,j), gel(u,j)))); m = ff->red(E, m); gel(u,i) = gerepileupto(av, ff->red(E,ff->mul(E,m, gcoeff(a,i,i)))); } return u; } GEN gen_Gauss(GEN a, GEN b, void *E, const struct bb_field *ff) { long i, j, k, li, bco, aco; GEN u, g0 = ff->s(E,0); pari_sp av = avma; a = RgM_shallowcopy(a); b = RgM_shallowcopy(b); aco = lg(a)-1; bco = lg(b)-1; li = nbrows(a); for (i=1; i<=aco; i++) { GEN invpiv; for (k = i; k <= li; k++) { GEN piv = ff->red(E,gcoeff(a,k,i)); if (!ff->equal0(piv)) { gcoeff(a,k,i) = ff->inv(E,piv); break; } gcoeff(a,k,i) = g0; } /* found a pivot on line k */ if (k > li) return NULL; if (k != i) { /* swap lines so that k = i */ for (j=i; j<=aco; j++) swap(gcoeff(a,i,j), gcoeff(a,k,j)); for (j=1; j<=bco; j++) swap(gcoeff(b,i,j), gcoeff(b,k,j)); } if (i == aco) break; invpiv = gcoeff(a,i,i); /* 1/piv mod p */ for (k=i+1; k<=li; k++) { GEN m = ff->red(E,gcoeff(a,k,i)); gcoeff(a,k,i) = g0; if (ff->equal0(m)) continue; m = ff->red(E,ff->neg(E,ff->mul(E,m, invpiv))); for (j=i+1; j<=aco; j++) _gen_addmul(gel(a,j),k,i,m,E,ff); for (j=1 ; j<=bco; j++) _gen_addmul(gel(b,j),k,i,m,E,ff); } if (gc_needed(av,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"gen_Gauss. i=%ld",i); gerepileall(av,2, &a,&b); } } if(DEBUGLEVEL>4) err_printf("Solving the triangular system\n"); u = cgetg(bco+1,t_MAT); for (j=1; j<=bco; j++) gel(u,j) = _gen_get_col(a, gel(b,j), aco, E, ff); return u; } /* compatible t_MAT * t_COL, lgA = lg(A) = lg(B) > 1, l = lgcols(A) */ static GEN gen_matcolmul_i(GEN A, GEN B, ulong lgA, ulong l, void *E, const struct bb_field *ff) { GEN C = cgetg(l, t_COL); ulong i; for (i = 1; i < l; i++) { pari_sp av = avma; GEN e = ff->mul(E, gcoeff(A, i, 1), gel(B, 1)); ulong k; for(k = 2; k < lgA; k++) e = ff->add(E, e, ff->mul(E, gcoeff(A, i, k), gel(B, k))); gel(C, i) = gerepileupto(av, ff->red(E, e)); } return C; } GEN gen_matcolmul(GEN A, GEN B, void *E, const struct bb_field *ff) { ulong lgA = lg(A); if (lgA != (ulong)lg(B)) pari_err_OP("operation 'gen_matcolmul'", A, B); if (lgA == 1) return cgetg(1, t_COL); return gen_matcolmul_i(A, B, lgA, lgcols(A), E, ff); } static GEN gen_matmul_classical(GEN A, GEN B, long l, long la, long lb, void *E, const struct bb_field *ff) { long j; GEN C = cgetg(lb, t_MAT); for(j = 1; j < lb; j++) gel(C, j) = gen_matcolmul_i(A, gel(B, j), la, l, E, ff); return C; } /* Strassen-Winograd algorithm */ /* Return A[ma+1..ma+da, na+1..na+ea] - B[mb+1..mb+db, nb+1..nb+eb] as an (m x n)-matrix, padding the input with zeroes as necessary. */ static GEN add_slices(long m, long n, GEN A, long ma, long da, long na, long ea, GEN B, long mb, long db, long nb, long eb, void *E, const struct bb_field *ff) { long min_d = minss(da, db), min_e = minss(ea, eb), i, j; GEN M = cgetg(n + 1, t_MAT), C; for (j = 1; j <= min_e; j++) { gel(M, j) = C = cgetg(m + 1, t_COL); for (i = 1; i <= min_d; i++) gel(C, i) = ff->add(E, gcoeff(A, ma + i, na + j), gcoeff(B, mb + i, nb + j)); for (; i <= da; i++) gel(C, i) = gcoeff(A, ma + i, na + j); for (; i <= db; i++) gel(C, i) = gcoeff(B, mb + i, nb + j); for (; i <= m; i++) gel(C, i) = ff->s(E, 0); } for (; j <= ea; j++) { gel(M, j) = C = cgetg(m + 1, t_COL); for (i = 1; i <= da; i++) gel(C, i) = gcoeff(A, ma + i, na + j); for (; i <= m; i++) gel(C, i) = ff->s(E, 0); } for (; j <= eb; j++) { gel(M, j) = C = cgetg(m + 1, t_COL); for (i = 1; i <= db; i++) gel(C, i) = gcoeff(B, mb + i, nb + j); for (; i <= m; i++) gel(C, i) = ff->s(E, 0); } for (; j <= n; j++) { gel(M, j) = C = cgetg(m + 1, t_COL); for (i = 1; i <= m; i++) gel(C, i) = ff->s(E, 0); } return M; } /* Return A[ma+1..ma+da, na+1..na+ea] - B[mb+1..mb+db, nb+1..nb+eb] as an (m x n)-matrix, padding the input with zeroes as necessary. */ static GEN subtract_slices(long m, long n, GEN A, long ma, long da, long na, long ea, GEN B, long mb, long db, long nb, long eb, void *E, const struct bb_field *ff) { long min_d = minss(da, db), min_e = minss(ea, eb), i, j; GEN M = cgetg(n + 1, t_MAT), C; for (j = 1; j <= min_e; j++) { gel(M, j) = C = cgetg(m + 1, t_COL); for (i = 1; i <= min_d; i++) gel(C, i) = ff->add(E, gcoeff(A, ma + i, na + j), ff->neg(E, gcoeff(B, mb + i, nb + j))); for (; i <= da; i++) gel(C, i) = gcoeff(A, ma + i, na + j); for (; i <= db; i++) gel(C, i) = ff->neg(E, gcoeff(B, mb + i, nb + j)); for (; i <= m; i++) gel(C, i) = ff->s(E, 0); } for (; j <= ea; j++) { gel(M, j) = C = cgetg(m + 1, t_COL); for (i = 1; i <= da; i++) gel(C, i) = gcoeff(A, ma + i, na + j); for (; i <= m; i++) gel(C, i) = ff->s(E, 0); } for (; j <= eb; j++) { gel(M, j) = C = cgetg(m + 1, t_COL); for (i = 1; i <= db; i++) gel(C, i) = ff->neg(E, gcoeff(B, mb + i, nb + j)); for (; i <= m; i++) gel(C, i) = ff->s(E, 0); } for (; j <= n; j++) { gel(M, j) = C = cgetg(m + 1, t_COL); for (i = 1; i <= m; i++) gel(C, i) = ff->s(E, 0); } return M; } static GEN gen_matmul_i(GEN A, GEN B, long l, long la, long lb, void *E, const struct bb_field *ff); static GEN gen_matmul_sw(GEN A, GEN B, long m, long n, long p, void *E, const struct bb_field *ff) { pari_sp av = avma; long m1 = (m + 1)/2, m2 = m/2, n1 = (n + 1)/2, n2 = n/2, p1 = (p + 1)/2, p2 = p/2; GEN A11, A12, A22, B11, B21, B22, S1, S2, S3, S4, T1, T2, T3, T4, M1, M2, M3, M4, M5, M6, M7, V1, V2, V3, C11, C12, C21, C22, C; T2 = subtract_slices(n1, p2, B, 0, n1, p1, p2, B, n1, n2, p1, p2, E, ff); S1 = subtract_slices(m2, n1, A, m1, m2, 0, n1, A, 0, m2, 0, n1, E, ff); M2 = gen_matmul_i(S1, T2, m2 + 1, n1 + 1, p2 + 1, E, ff); if (gc_needed(av, 1)) gerepileall(av, 2, &T2, &M2); /* destroy S1 */ T3 = subtract_slices(n1, p1, T2, 0, n1, 0, p2, B, 0, n1, 0, p1, E, ff); if (gc_needed(av, 1)) gerepileall(av, 2, &M2, &T3); /* destroy T2 */ S2 = add_slices(m2, n1, A, m1, m2, 0, n1, A, m1, m2, n1, n2, E, ff); T1 = subtract_slices(n1, p1, B, 0, n1, p1, p2, B, 0, n1, 0, p2, E, ff); M3 = gen_matmul_i(S2, T1, m2 + 1, n1 + 1, p2 + 1, E, ff); if (gc_needed(av, 1)) gerepileall(av, 4, &M2, &T3, &S2, &M3); /* destroy T1 */ S3 = subtract_slices(m1, n1, S2, 0, m2, 0, n1, A, 0, m1, 0, n1, E, ff); if (gc_needed(av, 1)) gerepileall(av, 4, &M2, &T3, &M3, &S3); /* destroy S2 */ A11 = matslice(A, 1, m1, 1, n1); B11 = matslice(B, 1, n1, 1, p1); M1 = gen_matmul_i(A11, B11, m1 + 1, n1 + 1, p1 + 1, E, ff); if (gc_needed(av, 1)) gerepileall(av, 5, &M2, &T3, &M3, &S3, &M1); /* destroy A11, B11 */ A12 = matslice(A, 1, m1, n1 + 1, n); B21 = matslice(B, n1 + 1, n, 1, p1); M4 = gen_matmul_i(A12, B21, m1 + 1, n2 + 1, p1 + 1, E, ff); if (gc_needed(av, 1)) gerepileall(av, 6, &M2, &T3, &M3, &S3, &M1, &M4); /* destroy A12, B21 */ C11 = add_slices(m1, p1, M1, 0, m1, 0, p1, M4, 0, m1, 0, p1, E, ff); if (gc_needed(av, 1)) gerepileall(av, 6, &M2, &T3, &M3, &S3, &M1, &C11); /* destroy M4 */ M5 = gen_matmul_i(S3, T3, m1 + 1, n1 + 1, p1 + 1, E, ff); S4 = subtract_slices(m1, n2, A, 0, m1, n1, n2, S3, 0, m1, 0, n2, E, ff); if (gc_needed(av, 1)) gerepileall(av, 7, &M2, &T3, &M3, &M1, &C11, &M5, &S4); /* destroy S3 */ T4 = add_slices(n2, p1, B, n1, n2, 0, p1, T3, 0, n2, 0, p1, E, ff); if (gc_needed(av, 1)) gerepileall(av, 7, &M2, &M3, &M1, &C11, &M5, &S4, &T4); /* destroy T3 */ V1 = subtract_slices(m1, p1, M1, 0, m1, 0, p1, M5, 0, m1, 0, p1, E, ff); if (gc_needed(av, 1)) gerepileall(av, 6, &M2, &M3, &S4, &T4, &C11, &V1); /* destroy M1, M5 */ B22 = matslice(B, n1 + 1, n, p1 + 1, p); M6 = gen_matmul_i(S4, B22, m1 + 1, n2 + 1, p2 + 1, E, ff); if (gc_needed(av, 1)) gerepileall(av, 6, &M2, &M3, &T4, &C11, &V1, &M6); /* destroy S4, B22 */ A22 = matslice(A, m1 + 1, m, n1 + 1, n); M7 = gen_matmul_i(A22, T4, m2 + 1, n2 + 1, p1 + 1, E, ff); if (gc_needed(av, 1)) gerepileall(av, 6, &M2, &M3, &C11, &V1, &M6, &M7); /* destroy A22, T4 */ V3 = add_slices(m1, p2, V1, 0, m1, 0, p2, M3, 0, m2, 0, p2, E, ff); C12 = add_slices(m1, p2, V3, 0, m1, 0, p2, M6, 0, m1, 0, p2, E, ff); if (gc_needed(av, 1)) gerepileall(av, 6, &M2, &M3, &C11, &V1, &M7, &C12); /* destroy V3, M6 */ V2 = add_slices(m2, p1, V1, 0, m2, 0, p1, M2, 0, m2, 0, p2, E, ff); if (gc_needed(av, 1)) gerepileall(av, 5, &M3, &C11, &M7, &C12, &V2); /* destroy V1, M2 */ C21 = add_slices(m2, p1, V2, 0, m2, 0, p1, M7, 0, m2, 0, p1, E, ff); if (gc_needed(av, 1)) gerepileall(av, 5, &M3, &C11, &C12, &V2, &C21); /* destroy M7 */ C22 = add_slices(m2, p2, V2, 0, m2, 0, p2, M3, 0, m2, 0, p2, E, ff); if (gc_needed(av, 1)) gerepileall(av, 4, &C11, &C12, &C21, &C22); /* destroy V2, M3 */ C = mkmat2(mkcol2(C11, C21), mkcol2(C12, C22)); return gerepileupto(av, matconcat(C)); } /* Strassen-Winograd used for dim >= gen_matmul_sw_bound */ static const long gen_matmul_sw_bound = 24; static GEN gen_matmul_i(GEN A, GEN B, long l, long la, long lb, void *E, const struct bb_field *ff) { if (l <= gen_matmul_sw_bound || la <= gen_matmul_sw_bound || lb <= gen_matmul_sw_bound) return gen_matmul_classical(A, B, l, la, lb, E, ff); else return gen_matmul_sw(A, B, l - 1, la - 1, lb - 1, E, ff); } GEN gen_matmul(GEN A, GEN B, void *E, const struct bb_field *ff) { ulong lgA, lgB = lg(B); if (lgB == 1) return cgetg(1, t_MAT); lgA = lg(A); if (lgA != (ulong)lgcols(B)) pari_err_OP("operation 'gen_matmul'", A, B); if (lgA == 1) return zeromat(0, lgB - 1); return gen_matmul_i(A, B, lgcols(A), lgA, lgB, E, ff); } static GEN gen_colneg(GEN A, void *E, const struct bb_field *ff) { long i, l; GEN B = cgetg_copy(A, &l); for (i = 1; i < l; i++) gel(B, i) = ff->neg(E, gel(A, i)); return B; } static GEN gen_matneg(GEN A, void *E, const struct bb_field *ff) { long i, l; GEN B = cgetg_copy(A, &l); for (i = 1; i < l; i++) gel(B, i) = gen_colneg(gel(A, i), E, ff); return B; } static GEN gen_colscalmul(GEN A, GEN b, void *E, const struct bb_field *ff) { long i, l; GEN B = cgetg_copy(A, &l); for (i = 1; i < l; i++) gel(B, i) = ff->red(E, ff->mul(E, gel(A, i), b)); return B; } static GEN gen_matscalmul(GEN A, GEN b, void *E, const struct bb_field *ff) { long i, l; GEN B = cgetg_copy(A, &l); for (i = 1; i < l; i++) gel(B, i) = gen_colscalmul(gel(A, i), b, E, ff); return B; } static GEN gen_colsub(GEN A, GEN C, void *E, const struct bb_field *ff) { long i, l; GEN B = cgetg_copy(A, &l); for (i = 1; i < l; i++) gel(B, i) = ff->add(E, gel(A, i), ff->neg(E, gel(C, i))); return B; } static GEN gen_matsub(GEN A, GEN C, void *E, const struct bb_field *ff) { long i, l; GEN B = cgetg_copy(A, &l); for (i = 1; i < l; i++) gel(B, i) = gen_colsub(gel(A, i), gel(C, i), E, ff); return B; } static GEN gen_zerocol(long n, void* data, const struct bb_field *R) { GEN C = cgetg(n+1,t_COL), zero = R->s(data, 0); long i; for (i=1; i<=n; i++) gel(C,i) = zero; return C; } static GEN gen_zeromat(long m, long n, void* data, const struct bb_field *R) { GEN M = cgetg(n+1,t_MAT); long i; for (i=1; i<=n; i++) gel(M,i) = gen_zerocol(m, data, R); return M; } static GEN gen_colei(long n, long i, void *E, const struct bb_field *S) { GEN y = cgetg(n+1,t_COL), _0, _1; long j; if (n < 0) pari_err_DOMAIN("gen_colei", "dimension","<",gen_0,stoi(n)); _0 = S->s(E,0); _1 = S->s(E,1); for (j=1; j<=n; j++) gel(y, j) = i==j ? _1: _0; return y; } /* assume dim A >= 1, A invertible + upper triangular */ static GEN gen_matinv_upper_ind(GEN A, long index, void *E, const struct bb_field *ff) { long n = lg(A) - 1, i, j; GEN u = cgetg(n + 1, t_COL); for (i = n; i > index; i--) gel(u, i) = ff->s(E, 0); gel(u, i) = ff->inv(E, gcoeff(A, i, i)); for (i--; i > 0; i--) { pari_sp av = avma; GEN m = ff->neg(E, ff->mul(E, gcoeff(A, i, i + 1), gel(u, i + 1))); for (j = i + 2; j <= n; j++) m = ff->add(E, m, ff->neg(E, ff->mul(E, gcoeff(A, i, j), gel(u, j)))); gel(u, i) = gerepileupto(av, ff->red(E, ff->mul(E, m, ff->inv(E, gcoeff(A, i, i))))); } return u; } static GEN gen_matinv_upper(GEN A, void *E, const struct bb_field *ff) { long i, l; GEN B = cgetg_copy(A, &l); for (i = 1; i < l; i++) gel(B,i) = gen_matinv_upper_ind(A, i, E, ff); return B; } /* find z such that A z = y. Return NULL if no solution */ GEN gen_matcolinvimage(GEN A, GEN y, void *E, const struct bb_field *ff) { pari_sp av = avma; long i, l = lg(A); GEN M, x, t; M = gen_ker(shallowconcat(A, y), 0, E, ff); i = lg(M) - 1; if (!i) return gc_NULL(av); x = gel(M, i); t = gel(x, l); if (ff->equal0(t)) return gc_NULL(av); t = ff->neg(E, ff->inv(E, t)); setlg(x, l); for (i = 1; i < l; i++) gel(x, i) = ff->red(E, ff->mul(E, t, gel(x, i))); return gerepilecopy(av, x); } /* find Z such that A Z = B. Return NULL if no solution */ GEN gen_matinvimage(GEN A, GEN B, void *E, const struct bb_field *ff) { pari_sp av = avma; GEN d, x, X, Y; long i, j, nY, nA, nB; x = gen_ker(shallowconcat(gen_matneg(A, E, ff), B), 0, E, ff); /* AX = BY, Y in strict upper echelon form with pivots = 1. * We must find T such that Y T = Id_nB then X T = Z. This exists * iff Y has at least nB columns and full rank. */ nY = lg(x) - 1; nB = lg(B) - 1; if (nY < nB) return gc_NULL(av); nA = lg(A) - 1; Y = rowslice(x, nA + 1, nA + nB); /* nB rows */ d = cgetg(nB + 1, t_VECSMALL); for (i = nB, j = nY; i >= 1; i--, j--) { for (; j >= 1; j--) if (!ff->equal0(gcoeff(Y, i, j))) { d[i] = j; break; } if (!j) return gc_NULL(av); } /* reduce to the case Y square, upper triangular with 1s on diagonal */ Y = vecpermute(Y, d); x = vecpermute(x, d); X = rowslice(x, 1, nA); return gerepileupto(av, gen_matmul(X, gen_matinv_upper(Y, E, ff), E, ff)); } static GEN image_from_pivot(GEN x, GEN d, long r) { GEN y; long j, k; if (!d) return gcopy(x); /* d left on stack for efficiency */ r = lg(x)-1 - r; /* = dim Im(x) */ y = cgetg(r+1,t_MAT); for (j=k=1; j<=r; k++) if (d[k]) gel(y,j++) = gcopy(gel(x,k)); return y; } /* r = dim Ker x, n = nbrows(x) */ static GEN get_suppl(GEN x, GEN d, long n, long r, GEN(*ei)(long,long)) { pari_sp av; GEN y, c; long j, k, rx = lg(x)-1; /* != 0 due to init_suppl() */ if (rx == n && r == 0) return gcopy(x); y = cgetg(n+1, t_MAT); av = avma; c = zero_zv(n); /* c = lines containing pivots (could get it from gauss_pivot, but cheap) * In theory r = 0 and d[j] > 0 for all j, but why take chances? */ for (k = j = 1; j<=rx; j++) if (d[j]) { c[ d[j] ] = 1; gel(y,k++) = gel(x,j); } for (j=1; j<=n; j++) if (!c[j]) gel(y,k++) = (GEN)j; /* HACK */ set_avma(av); rx -= r; for (j=1; j<=rx; j++) gel(y,j) = gcopy(gel(y,j)); for ( ; j<=n; j++) gel(y,j) = ei(n, y[j]); return y; } /* 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; } /*******************************************************************/ /* */ /* Echelon form and CUP decomposition */ /* */ /*******************************************************************/ /* By Peter Bruin, based on C.-P. Jeannerod, C. Pernet and A. Storjohann, Rank-profile revealing Gaussian elimination and the CUP matrix decomposition. J. Symbolic Comput. 56 (2013), 46-68. Decompose an m x n-matrix A of rank r as C*U*P, with - C: m x r-matrix in column echelon form (not necessarily reduced) with all pivots equal to 1 - U: upper-triangular r x n-matrix - P: permutation matrix The pivots of C and the known zeroes in C and U are not necessarily filled in; instead, we also return the vector R of pivot rows. Instead of the matrix P, we return the permutation p of [1..n] (t_VECSMALL) such that P[i,j] = 1 if and only if j = p[i]. */ /* complement of a strictly increasing subsequence of (1, 2, ..., n) */ static GEN indexcompl(GEN v, long n) { long i, j, k, m = lg(v) - 1; GEN w = cgetg(n - m + 1, t_VECSMALL); for (i = j = k = 1; i <= n; i++) if (j <= m && v[j] == i) j++; else w[k++] = i; return w; } static GEN gen_solve_upper_1(GEN U, GEN B, void *E, const struct bb_field *ff) { return gen_matscalmul(B, ff->inv(E, gcoeff(U, 1, 1)), E, ff); } static GEN gen_rsolve_upper_2(GEN U, GEN B, void *E, const struct bb_field *ff) { GEN a = gcoeff(U, 1, 1), b = gcoeff(U, 1, 2), d = gcoeff(U, 2, 2); GEN D = ff->red(E, ff->mul(E, a, d)), Dinv = ff->inv(E, D); GEN ainv = ff->red(E, ff->mul(E, d, Dinv)); GEN dinv = ff->red(E, ff->mul(E, a, Dinv)); GEN B1 = rowslice(B, 1, 1); GEN B2 = rowslice(B, 2, 2); GEN X2 = gen_matscalmul(B2, dinv, E, ff); GEN X1 = gen_matscalmul(gen_matsub(B1, gen_matscalmul(X2, b, E, ff), E, ff), ainv, E, ff); return vconcat(X1, X2); } /* solve U*X = B, U upper triangular and invertible */ static GEN gen_rsolve_upper(GEN U, GEN B, void *E, const struct bb_field *ff, GEN (*mul)(void *E, GEN a, GEN)) { long n = lg(U) - 1, n1; GEN U2, U11, U12, U22, B1, B2, X1, X2, X; pari_sp av = avma; if (n == 0) return B; if (n == 1) return gen_solve_upper_1(U, B, E, ff); if (n == 2) return gen_rsolve_upper_2(U, B, E, ff); n1 = (n + 1)/2; U2 = vecslice(U, n1 + 1, n); U11 = matslice(U, 1,n1, 1,n1); U12 = rowslice(U2, 1, n1); U22 = rowslice(U2, n1 + 1, n); B1 = rowslice(B, 1, n1); B2 = rowslice(B, n1 + 1, n); X2 = gen_rsolve_upper(U22, B2, E, ff, mul); B1 = gen_matsub(B1, mul(E, U12, X2), E, ff); if (gc_needed(av, 1)) gerepileall(av, 3, &B1, &U11, &X2); X1 = gen_rsolve_upper(U11, B1, E, ff, mul); X = vconcat(X1, X2); if (gc_needed(av, 1)) X = gerepilecopy(av, X); return X; } static GEN gen_lsolve_upper_2(GEN U, GEN B, void *E, const struct bb_field *ff) { GEN a = gcoeff(U, 1, 1), b = gcoeff(U, 1, 2), d = gcoeff(U, 2, 2); GEN D = ff->red(E, ff->mul(E, a, d)), Dinv = ff->inv(E, D); GEN ainv = ff->red(E, ff->mul(E, d, Dinv)), dinv = ff->red(E, ff->mul(E, a, Dinv)); GEN B1 = vecslice(B, 1, 1); GEN B2 = vecslice(B, 2, 2); GEN X1 = gen_matscalmul(B1, ainv, E, ff); GEN X2 = gen_matscalmul(gen_matsub(B2, gen_matscalmul(X1, b, E, ff), E, ff), dinv, E, ff); return shallowconcat(X1, X2); } /* solve X*U = B, U upper triangular and invertible */ static GEN gen_lsolve_upper(GEN U, GEN B, void *E, const struct bb_field *ff, GEN (*mul)(void *E, GEN a, GEN)) { long n = lg(U) - 1, n1; GEN U2, U11, U12, U22, B1, B2, X1, X2, X; pari_sp av = avma; if (n == 0) return B; if (n == 1) return gen_solve_upper_1(U, B, E, ff); if (n == 2) return gen_lsolve_upper_2(U, B, E, ff); n1 = (n + 1)/2; U2 = vecslice(U, n1 + 1, n); U11 = matslice(U, 1,n1, 1,n1); U12 = rowslice(U2, 1, n1); U22 = rowslice(U2, n1 + 1, n); B1 = vecslice(B, 1, n1); B2 = vecslice(B, n1 + 1, n); X1 = gen_lsolve_upper(U11, B1, E, ff, mul); B2 = gen_matsub(B2, mul(E, X1, U12), E, ff); if (gc_needed(av, 1)) gerepileall(av, 3, &B2, &U22, &X1); X2 = gen_lsolve_upper(U22, B2, E, ff, mul); X = shallowconcat(X1, X2); if (gc_needed(av, 1)) X = gerepilecopy(av, X); return X; } static GEN gen_rsolve_lower_unit_2(GEN L, GEN A, void *E, const struct bb_field *ff) { GEN X1 = rowslice(A, 1, 1); GEN X2 = gen_matsub(rowslice(A, 2, 2), gen_matscalmul(X1, gcoeff(L, 2, 1), E, ff), E, ff); return vconcat(X1, X2); } /* solve L*X = A, L lower triangular with ones on the diagonal * (at least as many rows as columns) */ static GEN gen_rsolve_lower_unit(GEN L, GEN A, void *E, const struct bb_field *ff, GEN (*mul)(void *E, GEN a, GEN)) { long m = lg(L) - 1, m1, n; GEN L1, L11, L21, L22, A1, A2, X1, X2, X; pari_sp av = avma; if (m == 0) return zeromat(0, lg(A) - 1); if (m == 1) return rowslice(A, 1, 1); if (m == 2) return gen_rsolve_lower_unit_2(L, A, E, ff); m1 = (m + 1)/2; n = nbrows(L); L1 = vecslice(L, 1, m1); L11 = rowslice(L1, 1, m1); L21 = rowslice(L1, m1 + 1, n); A1 = rowslice(A, 1, m1); X1 = gen_rsolve_lower_unit(L11, A1, E, ff, mul); A2 = rowslice(A, m1 + 1, n); A2 = gen_matsub(A2, mul(E, L21, X1), E, ff); if (gc_needed(av, 1)) gerepileall(av, 2, &A2, &X1); L22 = matslice(L, m1+1,n, m1+1,m); X2 = gen_rsolve_lower_unit(L22, A2, E, ff, mul); X = vconcat(X1, X2); if (gc_needed(av, 1)) X = gerepilecopy(av, X); return X; } static GEN gen_lsolve_lower_unit_2(GEN L, GEN A, void *E, const struct bb_field *ff) { GEN X2 = vecslice(A, 2, 2); GEN X1 = gen_matsub(vecslice(A, 1, 1), gen_matscalmul(X2, gcoeff(L, 2, 1), E, ff), E, ff); return shallowconcat(X1, X2); } /* solve L*X = A, L lower triangular with ones on the diagonal * (at least as many rows as columns) */ static GEN gen_lsolve_lower_unit(GEN L, GEN A, void *E, const struct bb_field *ff, GEN (*mul)(void *E, GEN a, GEN)) { long m = lg(L) - 1, m1; GEN L1, L2, L11, L21, L22, A1, A2, X1, X2, X; pari_sp av = avma; if (m <= 1) return A; if (m == 2) return gen_lsolve_lower_unit_2(L, A, E, ff); m1 = (m + 1)/2; L2 = vecslice(L, m1 + 1, m); L22 = rowslice(L2, m1 + 1, m); A2 = vecslice(A, m1 + 1, m); X2 = gen_lsolve_lower_unit(L22, A2, E, ff, mul); if (gc_needed(av, 1)) X2 = gerepilecopy(av, X2); L1 = vecslice(L, 1, m1); L21 = rowslice(L1, m1 + 1, m); A1 = vecslice(A, 1, m1); A1 = gen_matsub(A1, mul(E, X2, L21), E, ff); L11 = rowslice(L1, 1, m1); if (gc_needed(av, 1)) gerepileall(av, 3, &A1, &L11, &X2); X1 = gen_lsolve_lower_unit(L11, A1, E, ff, mul); X = shallowconcat(X1, X2); if (gc_needed(av, 1)) X = gerepilecopy(av, X); return X; } /* destroy A */ static long gen_CUP_basecase(GEN A, GEN *R, GEN *C, GEN *U, GEN *P, void *E, const struct bb_field *ff) { long i, j, k, m = nbrows(A), n = lg(A) - 1, pr, pc; pari_sp av; GEN u, v; if (P) *P = identity_perm(n); *R = cgetg(m + 1, t_VECSMALL); av = avma; for (j = 1, pr = 0; j <= n; j++) { for (pr++, pc = 0; pr <= m; pr++) { for (k = j; k <= n; k++) { v = ff->red(E, gcoeff(A, pr, k)); gcoeff(A, pr, k) = v; if (!pc && !ff->equal0(v)) pc = k; } if (pc) break; } if (!pc) break; (*R)[j] = pr; if (pc != j) { swap(gel(A, j), gel(A, pc)); if (P) lswap((*P)[j], (*P)[pc]); } u = ff->inv(E, gcoeff(A, pr, j)); for (i = pr + 1; i <= m; i++) { v = ff->red(E, ff->mul(E, gcoeff(A, i, j), u)); gcoeff(A, i, j) = v; v = ff->neg(E, v); for (k = j + 1; k <= n; k++) gcoeff(A, i, k) = ff->add(E, gcoeff(A, i, k), ff->red(E, ff->mul(E, gcoeff(A, pr, k), v))); } if (gc_needed(av, 2)) A = gerepilecopy(av, A); } setlg(*R, j); *C = vecslice(A, 1, j - 1); if (U) *U = rowpermute(A, *R); return j - 1; } static const long gen_CUP_LIMIT = 5; static long gen_CUP(GEN A, GEN *R, GEN *C, GEN *U, GEN *P, void *E, const struct bb_field *ff, GEN (*mul)(void *E, GEN a, GEN)) { long m = nbrows(A), m1, n = lg(A) - 1, i, r1, r2, r; GEN R1, C1, U1, P1, R2, C2, U2, P2; GEN A1, A2, B2, C21, U11, U12, T21, T22; pari_sp av = avma; if (m < gen_CUP_LIMIT || n < gen_CUP_LIMIT) /* destroy A; not called at the outermost recursion level */ return gen_CUP_basecase(A, R, C, U, P, E, ff); m1 = (minss(m, n) + 1)/2; A1 = rowslice(A, 1, m1); A2 = rowslice(A, m1 + 1, m); r1 = gen_CUP(A1, &R1, &C1, &U1, &P1, E, ff, mul); if (r1 == 0) { r2 = gen_CUP(A2, &R2, &C2, &U2, &P2, E, ff, mul); *R = cgetg(r2 + 1, t_VECSMALL); for (i = 1; i <= r2; i++) (*R)[i] = R2[i] + m1; *C = vconcat(gen_zeromat(m1, r2, E, ff), C2); *U = U2; *P = P2; r = r2; } else { U11 = vecslice(U1, 1, r1); U12 = vecslice(U1, r1 + 1, n); T21 = vecslicepermute(A2, P1, 1, r1); T22 = vecslicepermute(A2, P1, r1 + 1, n); C21 = gen_lsolve_upper(U11, T21, E, ff, mul); if (gc_needed(av, 1)) gerepileall(av, 7, &R1, &C1, &P1, &U11, &U12, &T22, &C21); B2 = gen_matsub(T22, mul(E, C21, U12), E, ff); r2 = gen_CUP(B2, &R2, &C2, &U2, &P2, E, ff, mul); r = r1 + r2; *R = cgetg(r + 1, t_VECSMALL); for (i = 1; i <= r1; i++) (*R)[i] = R1[i]; for ( ; i <= r; i++) (*R)[i] = R2[i - r1] + m1; *C = shallowconcat(vconcat(C1, C21), vconcat(gen_zeromat(m1, r2, E, ff), C2)); *U = shallowconcat(vconcat(U11, gen_zeromat(r2, r1, E, ff)), vconcat(vecpermute(U12, P2), U2)); *P = cgetg(n + 1, t_VECSMALL); for (i = 1; i <= r1; i++) (*P)[i] = P1[i]; for ( ; i <= n; i++) (*P)[i] = P1[P2[i - r1] + r1]; } if (gc_needed(av, 1)) gerepileall(av, 4, R, C, U, P); return r; } /* column echelon form */ static long gen_echelon(GEN A, GEN *R, GEN *C, void *E, const struct bb_field *ff, GEN (*mul)(void*, GEN, GEN)) { long j, j1, j2, m = nbrows(A), n = lg(A) - 1, n1, r, r1, r2; GEN A1, A2, R1, R1c, C1, R2, C2; GEN A12, A22, B2, C11, C21, M12; pari_sp av = avma; if (m < gen_CUP_LIMIT || n < gen_CUP_LIMIT) return gen_CUP_basecase(shallowcopy(A), R, C, NULL, NULL, E, ff); n1 = (n + 1)/2; A1 = vecslice(A, 1, n1); A2 = vecslice(A, n1 + 1, n); r1 = gen_echelon(A1, &R1, &C1, E, ff, mul); if (!r1) return gen_echelon(A2, R, C, E, ff, mul); if (r1 == m) { *R = R1; *C = C1; return r1; } R1c = indexcompl(R1, m); C11 = rowpermute(C1, R1); C21 = rowpermute(C1, R1c); A12 = rowpermute(A2, R1); A22 = rowpermute(A2, R1c); M12 = gen_rsolve_lower_unit(C11, A12, E, ff, mul); B2 = gen_matsub(A22, mul(E, C21, M12), E, ff); r2 = gen_echelon(B2, &R2, &C2, E, ff, mul); if (!r2) { *R = R1; *C = C1; r = r1; } else { R2 = perm_mul(R1c, R2); C2 = rowpermute(vconcat(gen_zeromat(r1, r2, E, ff), C2), perm_inv(vecsmall_concat(R1, R1c))); r = r1 + r2; *R = cgetg(r + 1, t_VECSMALL); *C = cgetg(r + 1, t_MAT); for (j = j1 = j2 = 1; j <= r; j++) if (j2 > r2 || (j1 <= r1 && R1[j1] < R2[j2])) { gel(*C, j) = gel(C1, j1); (*R)[j] = R1[j1++]; } else { gel(*C, j) = gel(C2, j2); (*R)[j] = R2[j2++]; } } if (gc_needed(av, 1)) gerepileall(av, 2, R, C); return r; } static GEN gen_pivots_CUP(GEN x, long *rr, void *E, const struct bb_field *ff, GEN (*mul)(void*, GEN, GEN)) { pari_sp av; long i, n = lg(x) - 1, r; GEN R, C, U, P, d = zero_zv(n); av = avma; r = gen_CUP(x, &R, &C, &U, &P, E, ff, mul); for(i = 1; i <= r; i++) d[P[i]] = R[i]; set_avma(av); *rr = n - r; return d; } static GEN gen_det_CUP(GEN a, void *E, const struct bb_field *ff, GEN (*mul)(void*, GEN, GEN)) { pari_sp av = avma; GEN R, C, U, P, d; long i, n = lg(a) - 1, r; r = gen_CUP(a, &R, &C, &U, &P, E, ff, mul); if (r < n) d = ff->s(E, 0); else { d = ff->s(E, perm_sign(P) == 1 ? 1: - 1); for (i = 1; i <= n; i++) d = ff->red(E, ff->mul(E, d, gcoeff(U, i, i))); } return gerepileupto(av, d); } static long gen_matrank(GEN x, void *E, const struct bb_field *ff, GEN (*mul)(void*, GEN, GEN)) { pari_sp av = avma; long r; if (lg(x) - 1 >= gen_CUP_LIMIT && nbrows(x) >= gen_CUP_LIMIT) { GEN R, C; return gc_long(av, gen_echelon(x, &R, &C, E, ff, mul)); } (void) gen_Gauss_pivot(x, &r, E, ff); return gc_long(av, lg(x)-1 - r); } static GEN gen_invimage_CUP(GEN A, GEN B, void *E, const struct bb_field *ff, GEN (*mul)(void*, GEN, GEN)) { pari_sp av = avma; GEN R, Rc, C, U, P, B1, B2, C1, C2, X, Y, Z; long r = gen_CUP(A, &R, &C, &U, &P, E, ff, mul); Rc = indexcompl(R, nbrows(B)); C1 = rowpermute(C, R); C2 = rowpermute(C, Rc); B1 = rowpermute(B, R); B2 = rowpermute(B, Rc); Z = gen_rsolve_lower_unit(C1, B1, E, ff, mul); if (!gequal(mul(E, C2, Z), B2)) return NULL; Y = vconcat(gen_rsolve_upper(vecslice(U, 1, r), Z, E, ff, mul), gen_zeromat(lg(A) - 1 - r, lg(B) - 1, E, ff)); X = rowpermute(Y, perm_inv(P)); return gerepilecopy(av, X); } static GEN gen_ker_echelon(GEN x, void *E, const struct bb_field *ff, GEN (*mul)(void*, GEN, GEN)) { pari_sp av = avma; GEN R, Rc, C, C1, C2, S, K; long n = lg(x) - 1, r; r = gen_echelon(shallowtrans(x), &R, &C, E, ff, mul); Rc = indexcompl(R, n); C1 = rowpermute(C, R); C2 = rowpermute(C, Rc); S = gen_lsolve_lower_unit(C1, C2, E, ff, mul); K = vecpermute(shallowconcat(gen_matneg(S, E, ff), gen_matid(n - r, E, ff)), perm_inv(vecsmall_concat(R, Rc))); K = shallowtrans(K); return gerepilecopy(av, K); } static GEN gen_deplin_echelon(GEN x, void *E, const struct bb_field *ff, GEN (*mul)(void*, GEN, GEN)) { pari_sp av = avma; GEN R, Rc, C, C1, C2, s, v; long i, n = lg(x) - 1, r; r = gen_echelon(shallowtrans(x), &R, &C, E, ff, mul); if (r == n) return gc_NULL(av); Rc = indexcompl(R, n); i = Rc[1]; C1 = rowpermute(C, R); C2 = rowslice(C, i, i); s = row(gen_lsolve_lower_unit(C1, C2, E, ff, mul), 1); settyp(s, t_COL); v = vecpermute(shallowconcat(gen_colneg(s, E, ff), gen_colei(n - r, 1, E, ff)), perm_inv(vecsmall_concat(R, Rc))); return gerepilecopy(av, v); } static GEN gen_gauss_CUP(GEN a, GEN b, void *E, const struct bb_field *ff, GEN (*mul)(void*, GEN, GEN)) { GEN R, C, U, P, Y; long n = lg(a) - 1, r; if (nbrows(a) < n || (r = gen_CUP(a, &R, &C, &U, &P, E, ff, mul)) < n) return NULL; Y = gen_rsolve_lower_unit(rowpermute(C, R), rowpermute(b, R), E, ff, mul); return rowpermute(gen_rsolve_upper(U, Y, E, ff, mul), perm_inv(P)); } static GEN gen_gauss(GEN a, GEN b, void *E, const struct bb_field *ff, GEN (*mul)(void*, GEN, GEN)) { if (lg(a) - 1 >= gen_CUP_LIMIT) return gen_gauss_CUP(a, b, E, ff, mul); return gen_Gauss(a, b, E, ff); } static GEN gen_ker_i(GEN x, long deplin, void *E, const struct bb_field *ff, GEN (*mul)(void*, GEN, GEN)) { if (lg(x) - 1 >= gen_CUP_LIMIT && nbrows(x) >= gen_CUP_LIMIT) return deplin? gen_deplin_echelon(x, E, ff, mul): gen_ker_echelon(x, E, ff, mul); return gen_ker(x, deplin, E, ff); } static GEN gen_invimage(GEN A, GEN B, void *E, const struct bb_field *ff, GEN (*mul)(void*, GEN, GEN)) { long nA = lg(A)-1, nB = lg(B)-1; if (!nB) return cgetg(1, t_MAT); if (nA + nB >= gen_CUP_LIMIT && nbrows(B) >= gen_CUP_LIMIT) return gen_invimage_CUP(A, B, E, ff, mul); return gen_matinvimage(A, B, E, ff); } /* find z such that A z = y. Return NULL if no solution */ static GEN gen_matcolinvimage_i(GEN A, GEN y, void *E, const struct bb_field *ff, GEN (*mul)(void*, GEN, GEN)) { pari_sp av = avma; long i, l = lg(A); GEN M, x, t; M = gen_ker_i(shallowconcat(A, y), 0, E, ff, mul); i = lg(M) - 1; if (!i) return gc_NULL(av); x = gel(M, i); t = gel(x, l); if (ff->equal0(t)) return gc_NULL(av); t = ff->neg(E, ff->inv(E, t)); setlg(x, l); for (i = 1; i < l; i++) gel(x, i) = ff->red(E, ff->mul(E, t, gel(x, i))); return gerepilecopy(av, x); } static GEN gen_det_i(GEN a, void *E, const struct bb_field *ff, GEN (*mul)(void*, GEN, GEN)) { if (lg(a) - 1 >= gen_CUP_LIMIT) return gen_det_CUP(a, E, ff, mul); else return gen_det(a, E, ff); } static GEN gen_pivots(GEN x, long *rr, void *E, const struct bb_field *ff, GEN (*mul)(void*, GEN, GEN)) { if (lg(x) - 1 >= gen_CUP_LIMIT && nbrows(x) >= gen_CUP_LIMIT) return gen_pivots_CUP(x, rr, E, ff, mul); return gen_Gauss_pivot(x, rr, E, ff); } /* r = dim Ker x, n = nbrows(x) */ static GEN gen_get_suppl(GEN x, GEN d, long n, long r, void *E, const struct bb_field *ff) { GEN y, c; long j, k, rx = lg(x)-1; /* != 0 due to init_suppl() */ if (rx == n && r == 0) return gcopy(x); c = zero_zv(n); y = cgetg(n+1, t_MAT); /* c = lines containing pivots (could get it from gauss_pivot, but cheap) * In theory r = 0 and d[j] > 0 for all j, but why take chances? */ for (k = j = 1; j<=rx; j++) if (d[j]) { c[ d[j] ] = 1; gel(y,k++) = gcopy(gel(x,j)); } for (j=1; j<=n; j++) if (!c[j]) gel(y,k++) = gen_colei(n, j, E, ff); return y; } static GEN gen_suppl(GEN x, void *E, const struct bb_field *ff, GEN (*mul)(void*, GEN, GEN)) { GEN d; long n = nbrows(x), r; if (lg(x) == 1) pari_err_IMPL("suppl [empty matrix]"); d = gen_pivots(x, &r, E, ff, mul); return gen_get_suppl(x, d, n, r, E, ff); } /*******************************************************************/ /* */ /* MATRIX MULTIPLICATION MODULO P */ /* */ /*******************************************************************/ GEN F2xqM_F2xqC_mul(GEN A, GEN B, GEN T) { void *E; const struct bb_field *ff = get_F2xq_field(&E, T); return gen_matcolmul(A, B, E, ff); } GEN FlxqM_FlxqC_mul(GEN A, GEN B, GEN T, ulong p) { void *E; const struct bb_field *ff = get_Flxq_field(&E, T, p); return gen_matcolmul(A, B, E, ff); } GEN FqM_FqC_mul(GEN A, GEN B, GEN T, GEN p) { void *E; const struct bb_field *ff = get_Fq_field(&E, T, p); return gen_matcolmul(A, B, E, ff); } GEN F2xqM_mul(GEN A, GEN B, GEN T) { void *E; const struct bb_field *ff = get_F2xq_field(&E, T); return gen_matmul(A, B, E, ff); } GEN FlxqM_mul(GEN A, GEN B, GEN T, ulong p) { void *E; const struct bb_field *ff; long n = lg(A) - 1; if (n == 0) return cgetg(1, t_MAT); if (n > 1) return FlxqM_mul_Kronecker(A, B, T, p); ff = get_Flxq_field(&E, T, p); return gen_matmul(A, B, E, ff); } GEN FqM_mul(GEN A, GEN B, GEN T, GEN p) { void *E; long n = lg(A) - 1; const struct bb_field *ff; if (n == 0) return cgetg(1, t_MAT); if (n > 1) return FqM_mul_Kronecker(A, B, T, p); ff = get_Fq_field(&E, T, p); return gen_matmul(A, B, E, ff); } /*******************************************************************/ /* */ /* LINEAR ALGEBRA MODULO P */ /* */ /*******************************************************************/ static GEN _F2xqM_mul(void *E, GEN A, GEN B) { return F2xqM_mul(A, B, (GEN) E); } struct _Flxq { GEN aut; GEN T; ulong p; }; static GEN _FlxqM_mul(void *E, GEN A, GEN B) { struct _Flxq *D = (struct _Flxq*)E; return FlxqM_mul(A, B, D->T, D->p); } static GEN _FpM_mul(void *E, GEN A, GEN B) { return FpM_mul(A, B, (GEN) E); } struct _Fq_field { GEN T, p; }; static GEN _FqM_mul(void *E, GEN A, GEN B) { struct _Fq_field *D = (struct _Fq_field*) E; return FqM_mul(A, B, D->T, D->p); } static GEN FpM_init(GEN a, GEN p, ulong *pp) { if (lgefint(p) == 3) { *pp = uel(p,2); return (*pp==2)? ZM_to_F2m(a): ZM_to_Flm(a, *pp); } *pp = 0; return a; } static GEN FpM_init3(GEN a, GEN p, ulong *pp) { if (lgefint(p) == 3) { *pp = uel(p,2); switch(*pp) { case 2: return ZM_to_F2m(a); case 3: return ZM_to_F3m(a); default:return ZM_to_Flm(a, *pp); } } *pp = 0; return a; } GEN RgM_Fp_init(GEN a, GEN p, ulong *pp) { if (lgefint(p) == 3) { *pp = uel(p,2); return (*pp==2)? RgM_to_F2m(a): RgM_to_Flm(a, *pp); } *pp = 0; return RgM_to_FpM(a,p); } static GEN RgM_Fp_init3(GEN a, GEN p, ulong *pp) { if (lgefint(p) == 3) { *pp = uel(p,2); switch(*pp) { case 2: return RgM_to_F2m(a); case 3: return RgM_to_F3m(a); default:return RgM_to_Flm(a, *pp); } } *pp = 0; return RgM_to_FpM(a,p); } static GEN FpM_det_gen(GEN a, GEN p) { void *E; const struct bb_field *S = get_Fp_field(&E,p); return gen_det_i(a, E, S, _FpM_mul); } GEN FpM_det(GEN a, GEN p) { pari_sp av = avma; ulong pp, d; a = FpM_init(a, p, &pp); switch(pp) { case 0: return FpM_det_gen(a, p); case 2: d = F2m_det_sp(a); break; default:d = Flm_det_sp(a,pp); break; } return gc_utoi(av, d); } GEN F2xqM_det(GEN a, GEN T) { void *E; const struct bb_field *S = get_F2xq_field(&E, T); return gen_det_i(a, E, S, _F2xqM_mul); } GEN FlxqM_det(GEN a, GEN T, ulong p) { void *E; const struct bb_field *S = get_Flxq_field(&E, T, p); return gen_det_i(a, E, S, _FlxqM_mul); } GEN FqM_det(GEN x, GEN T, GEN p) { void *E; const struct bb_field *S = get_Fq_field(&E,T,p); return gen_det_i(x, E, S, _FqM_mul); } static GEN FpM_gauss_pivot_gen(GEN x, GEN p, long *rr) { void *E; const struct bb_field *S = get_Fp_field(&E,p); return gen_pivots(x, rr, E, S, _FpM_mul); } static GEN FpM_gauss_pivot(GEN x, GEN p, long *rr) { ulong pp; if (lg(x)==1) { *rr = 0; return NULL; } x = FpM_init(x, p, &pp); switch(pp) { case 0: return FpM_gauss_pivot_gen(x, p, rr); case 2: return F2m_gauss_pivot(x, rr); default:return Flm_pivots(x, pp, rr, 1); } } static GEN F2xqM_gauss_pivot(GEN x, GEN T, long *rr) { void *E; const struct bb_field *S = get_F2xq_field(&E,T); return gen_pivots(x, rr, E, S, _F2xqM_mul); } static GEN FlxqM_gauss_pivot(GEN x, GEN T, ulong p, long *rr) { void *E; const struct bb_field *S = get_Flxq_field(&E, T, p); return gen_pivots(x, rr, E, S, _FlxqM_mul); } static GEN FqM_gauss_pivot_gen(GEN x, GEN T, GEN p, long *rr) { void *E; const struct bb_field *S = get_Fq_field(&E,T,p); return gen_pivots(x, rr, E, S, _FqM_mul); } static GEN FqM_gauss_pivot(GEN x, GEN T, GEN p, long *rr) { if (lg(x)==1) { *rr = 0; return NULL; } if (!T) return FpM_gauss_pivot(x, p, rr); if (lgefint(p) == 3) { pari_sp av = avma; ulong pp = uel(p,2); GEN Tp = ZXT_to_FlxT(T, pp); GEN d = FlxqM_gauss_pivot(ZXM_to_FlxM(x, pp, get_Flx_var(Tp)), Tp, pp, rr); return d ? gerepileuptoleaf(av, d): d; } return FqM_gauss_pivot_gen(x, T, p, rr); } GEN FpM_image(GEN x, GEN p) { long r; GEN d = FpM_gauss_pivot(x,p,&r); /* d left on stack for efficiency */ return image_from_pivot(x,d,r); } GEN Flm_image(GEN x, ulong p) { long r; GEN d = Flm_pivots(x, p, &r, 0); /* d left on stack for efficiency */ return image_from_pivot(x,d,r); } GEN F2m_image(GEN x) { long r; GEN d = F2m_gauss_pivot(F2m_copy(x),&r); /* d left on stack for efficiency */ return image_from_pivot(x,d,r); } GEN F2xqM_image(GEN x, GEN T) { long r; GEN d = F2xqM_gauss_pivot(x,T,&r); /* d left on stack for efficiency */ return image_from_pivot(x,d,r); } GEN FlxqM_image(GEN x, GEN T, ulong p) { long r; GEN d = FlxqM_gauss_pivot(x, T, p, &r); /* d left on stack for efficiency */ return image_from_pivot(x,d,r); } GEN FqM_image(GEN x, GEN T, GEN p) { long r; GEN d = FqM_gauss_pivot(x,T,p,&r); /* d left on stack for efficiency */ return image_from_pivot(x,d,r); } long FpM_rank(GEN x, GEN p) { pari_sp av = avma; long r; (void)FpM_gauss_pivot(x,p,&r); return gc_long(av, lg(x)-1 - r); } long F2xqM_rank(GEN x, GEN T) { pari_sp av = avma; long r; (void)F2xqM_gauss_pivot(x,T,&r); return gc_long(av, lg(x)-1 - r); } long FlxqM_rank(GEN x, GEN T, ulong p) { void *E; const struct bb_field *S = get_Flxq_field(&E, T, p); return gen_matrank(x, E, S, _FlxqM_mul); } long FqM_rank(GEN x, GEN T, GEN p) { pari_sp av = avma; long r; (void)FqM_gauss_pivot(x,T,p,&r); return gc_long(av, lg(x)-1 - r); } static GEN FpM_invimage_gen(GEN A, GEN B, GEN p) { void *E; const struct bb_field *ff = get_Fp_field(&E, p); return gen_invimage(A, B, E, ff, _FpM_mul); } GEN FpM_invimage(GEN A, GEN B, GEN p) { pari_sp av = avma; ulong pp; GEN y; A = FpM_init(A, p, &pp); switch(pp) { case 0: return FpM_invimage_gen(A, B, p); case 2: y = F2m_invimage(A, ZM_to_F2m(B)); if (!y) return gc_NULL(av); y = F2m_to_ZM(y); return gerepileupto(av, y); default: y = Flm_invimage_i(A, ZM_to_Flm(B, pp), pp); if (!y) return gc_NULL(av); y = Flm_to_ZM(y); return gerepileupto(av, y); } } GEN F2xqM_invimage(GEN A, GEN B, GEN T) { void *E; const struct bb_field *ff = get_F2xq_field(&E, T); return gen_invimage(A, B, E, ff, _F2xqM_mul); } GEN FlxqM_invimage(GEN A, GEN B, GEN T, ulong p) { void *E; const struct bb_field *ff = get_Flxq_field(&E, T, p); return gen_invimage(A, B, E, ff, _FlxqM_mul); } GEN FqM_invimage(GEN A, GEN B, GEN T, GEN p) { void *E; const struct bb_field *ff = get_Fq_field(&E, T, p); return gen_invimage(A, B, E, ff, _FqM_mul); } static GEN FpM_FpC_invimage_gen(GEN A, GEN y, GEN p) { void *E; const struct bb_field *ff = get_Fp_field(&E, p); return gen_matcolinvimage_i(A, y, E, ff, _FpM_mul); } GEN FpM_FpC_invimage(GEN A, GEN x, GEN p) { pari_sp av = avma; ulong pp; GEN y; A = FpM_init(A, p, &pp); switch(pp) { case 0: return FpM_FpC_invimage_gen(A, x, p); case 2: y = F2m_F2c_invimage(A, ZV_to_F2v(x)); if (!y) return y; y = F2c_to_ZC(y); return gerepileupto(av, y); default: y = Flm_Flc_invimage(A, ZV_to_Flv(x, pp), pp); if (!y) return y; y = Flc_to_ZC(y); return gerepileupto(av, y); } } GEN F2xqM_F2xqC_invimage(GEN A, GEN B, GEN T) { void *E; const struct bb_field *ff = get_F2xq_field(&E, T); return gen_matcolinvimage_i(A, B, E, ff, _F2xqM_mul); } GEN FlxqM_FlxqC_invimage(GEN A, GEN B, GEN T, ulong p) { void *E; const struct bb_field *ff = get_Flxq_field(&E, T, p); return gen_matcolinvimage_i(A, B, E, ff, _FlxqM_mul); } GEN FqM_FqC_invimage(GEN A, GEN B, GEN T, GEN p) { void *E; const struct bb_field *ff = get_Fq_field(&E, T, p); return gen_matcolinvimage_i(A, B, E, ff, _FqM_mul); } static GEN FpM_ker_gen(GEN x, GEN p, long deplin) { void *E; const struct bb_field *S = get_Fp_field(&E,p); return gen_ker_i(x, deplin, E, S, _FpM_mul); } static GEN FpM_ker_i(GEN x, GEN p, long deplin) { pari_sp av = avma; ulong pp; GEN y; if (lg(x)==1) return cgetg(1,t_MAT); x = FpM_init3(x, p, &pp); switch(pp) { case 0: return FpM_ker_gen(x,p,deplin); case 2: y = F2m_ker_sp(x, deplin); if (!y) return gc_NULL(av); y = deplin? F2c_to_ZC(y): F2m_to_ZM(y); return gerepileupto(av, y); case 3: y = F3m_ker_sp(x, deplin); if (!y) return gc_NULL(av); y = deplin? F3c_to_ZC(y): F3m_to_ZM(y); return gerepileupto(av, y); default: y = Flm_ker_sp(x, pp, deplin); if (!y) return gc_NULL(av); y = deplin? Flc_to_ZC(y): Flm_to_ZM(y); return gerepileupto(av, y); } } GEN FpM_ker(GEN x, GEN p) { return FpM_ker_i(x,p,0); } static GEN F2xqM_ker_i(GEN x, GEN T, long deplin) { const struct bb_field *ff; void *E; if (lg(x)==1) return cgetg(1,t_MAT); ff = get_F2xq_field(&E,T); return gen_ker_i(x,deplin, E, ff, _F2xqM_mul); } GEN F2xqM_ker(GEN x, GEN T) { return F2xqM_ker_i(x, T, 0); } static GEN FlxqM_ker_i(GEN x, GEN T, ulong p, long deplin) { void *E; const struct bb_field *S = get_Flxq_field(&E, T, p); return gen_ker_i(x, deplin, E, S, _FlxqM_mul); } GEN FlxqM_ker(GEN x, GEN T, ulong p) { return FlxqM_ker_i(x, T, p, 0); } static GEN FqM_ker_gen(GEN x, GEN T, GEN p, long deplin) { void *E; const struct bb_field *S = get_Fq_field(&E,T,p); return gen_ker_i(x,deplin,E,S,_FqM_mul); } static GEN FqM_ker_i(GEN x, GEN T, GEN p, long deplin) { if (!T) return FpM_ker_i(x,p,deplin); if (lg(x)==1) return cgetg(1,t_MAT); if (lgefint(p)==3) { pari_sp av = avma; ulong l = p[2]; GEN Tl = ZXT_to_FlxT(T,l); GEN Ml = ZXM_to_FlxM(x, l, get_Flx_var(Tl)); GEN K = FlxqM_ker_i(Ml, Tl, l, deplin); if (!deplin) K = FlxM_to_ZXM(K); else if (!K) return gc_NULL(av); else K = FlxC_to_ZXC(K); return gerepileupto(av, K); } return FqM_ker_gen(x, T, p, deplin); } GEN FqM_ker(GEN x, GEN T, GEN p) { return FqM_ker_i(x,T,p,0); } GEN FpM_deplin(GEN x, GEN p) { return FpM_ker_i(x,p,1); } GEN F2xqM_deplin(GEN x, GEN T) { return F2xqM_ker_i(x, T, 1); } GEN FlxqM_deplin(GEN x, GEN T, ulong p) { return FlxqM_ker_i(x, T, p, 1); } GEN FqM_deplin(GEN x, GEN T, GEN p) { return FqM_ker_i(x,T,p,1); } static GEN FpM_gauss_gen(GEN a, GEN b, GEN p) { void *E; const struct bb_field *S = get_Fp_field(&E,p); return gen_gauss(a,b, E, S, _FpM_mul); } /* a an FpM, lg(a)>1; b an FpM or NULL (replace by identity) */ static GEN FpM_gauss_i(GEN a, GEN b, GEN p, ulong *pp) { long n = nbrows(a); a = FpM_init(a,p,pp); switch(*pp) { case 0: if (!b) b = matid(n); return FpM_gauss_gen(a,b,p); case 2: if (b) b = ZM_to_F2m(b); else b = matid_F2m(n); return F2m_gauss_sp(a,b); default: if (b) b = ZM_to_Flm(b, *pp); else b = matid_Flm(n); return Flm_gauss_sp(a,b, NULL, *pp); } } GEN FpM_gauss(GEN a, GEN b, GEN p) { pari_sp av = avma; ulong pp; GEN u; if (lg(a) == 1 || lg(b)==1) return cgetg(1, t_MAT); u = FpM_gauss_i(a, b, p, &pp); if (!u) return gc_NULL(av); switch(pp) { case 0: return gerepilecopy(av, u); case 2: u = F2m_to_ZM(u); break; default: u = Flm_to_ZM(u); break; } return gerepileupto(av, u); } static GEN F2xqM_gauss_gen(GEN a, GEN b, GEN T) { void *E; const struct bb_field *S = get_F2xq_field(&E, T); return gen_gauss(a, b, E, S, _F2xqM_mul); } GEN F2xqM_gauss(GEN a, GEN b, GEN T) { pari_sp av = avma; long n = lg(a)-1; GEN u; if (!n || lg(b)==1) { set_avma(av); return cgetg(1, t_MAT); } u = F2xqM_gauss_gen(a, b, T); if (!u) return gc_NULL(av); return gerepilecopy(av, u); } static GEN FlxqM_gauss_i(GEN a, GEN b, GEN T, ulong p) { void *E; const struct bb_field *S = get_Flxq_field(&E, T, p); return gen_gauss(a, b, E, S, _FlxqM_mul); } GEN FlxqM_gauss(GEN a, GEN b, GEN T, ulong p) { pari_sp av = avma; long n = lg(a)-1; GEN u; if (!n || lg(b)==1) { set_avma(av); return cgetg(1, t_MAT); } u = FlxqM_gauss_i(a, b, T, p); if (!u) return gc_NULL(av); return gerepilecopy(av, u); } static GEN FqM_gauss_gen(GEN a, GEN b, GEN T, GEN p) { void *E; const struct bb_field *S = get_Fq_field(&E,T,p); return gen_gauss(a,b,E,S,_FqM_mul); } GEN FqM_gauss(GEN a, GEN b, GEN T, GEN p) { pari_sp av = avma; GEN u; long n; if (!T) return FpM_gauss(a,b,p); n = lg(a)-1; if (!n || lg(b)==1) return cgetg(1, t_MAT); u = FqM_gauss_gen(a,b,T,p); if (!u) return gc_NULL(av); return gerepilecopy(av, u); } GEN FpM_FpC_gauss(GEN a, GEN b, GEN p) { pari_sp av = avma; ulong pp; GEN u; if (lg(a) == 1) return cgetg(1, t_COL); u = FpM_gauss_i(a, mkmat(b), p, &pp); if (!u) return gc_NULL(av); switch(pp) { case 0: return gerepilecopy(av, gel(u,1)); case 2: u = F2c_to_ZC(gel(u,1)); break; default: u = Flc_to_ZC(gel(u,1)); break; } return gerepileupto(av, u); } GEN F2xqM_F2xqC_gauss(GEN a, GEN b, GEN T) { pari_sp av = avma; GEN u; if (lg(a) == 1) return cgetg(1, t_COL); u = F2xqM_gauss_gen(a, mkmat(b), T); if (!u) return gc_NULL(av); return gerepilecopy(av, gel(u,1)); } GEN FlxqM_FlxqC_gauss(GEN a, GEN b, GEN T, ulong p) { pari_sp av = avma; GEN u; if (lg(a) == 1) return cgetg(1, t_COL); u = FlxqM_gauss_i(a, mkmat(b), T, p); if (!u) return gc_NULL(av); return gerepilecopy(av, gel(u,1)); } GEN FqM_FqC_gauss(GEN a, GEN b, GEN T, GEN p) { pari_sp av = avma; GEN u; if (!T) return FpM_FpC_gauss(a,b,p); if (lg(a) == 1) return cgetg(1, t_COL); u = FqM_gauss_gen(a,mkmat(b),T,p); if (!u) return gc_NULL(av); return gerepilecopy(av, gel(u,1)); } GEN FpM_inv(GEN a, GEN p) { pari_sp av = avma; ulong pp; GEN u; if (lg(a) == 1) return cgetg(1, t_MAT); u = FpM_gauss_i(a, NULL, p, &pp); if (!u) return gc_NULL(av); switch(pp) { case 0: return gerepilecopy(av, u); case 2: u = F2m_to_ZM(u); break; default: u = Flm_to_ZM(u); break; } return gerepileupto(av, u); } GEN F2xqM_inv(GEN a, GEN T) { pari_sp av = avma; GEN u; if (lg(a) == 1) { set_avma(av); return cgetg(1, t_MAT); } u = F2xqM_gauss_gen(a, matid_F2xqM(nbrows(a),T), T); if (!u) return gc_NULL(av); return gerepilecopy(av, u); } GEN FlxqM_inv(GEN a, GEN T, ulong p) { pari_sp av = avma; GEN u; if (lg(a) == 1) { set_avma(av); return cgetg(1, t_MAT); } u = FlxqM_gauss_i(a, matid_FlxqM(nbrows(a),T,p), T,p); if (!u) return gc_NULL(av); return gerepilecopy(av, u); } GEN FqM_inv(GEN a, GEN T, GEN p) { pari_sp av = avma; GEN u; if (!T) return FpM_inv(a,p); if (lg(a) == 1) return cgetg(1, t_MAT); u = FqM_gauss_gen(a,matid(nbrows(a)),T,p); if (!u) return gc_NULL(av); return gerepilecopy(av, u); } GEN FpM_intersect_i(GEN x, GEN y, GEN p) { long j, lx = lg(x); GEN z; if (lx == 1 || lg(y) == 1) return cgetg(1,t_MAT); if (lgefint(p) == 3) { ulong pp = p[2]; return Flm_to_ZM(Flm_intersect_i(ZM_to_Flm(x,pp), ZM_to_Flm(y,pp), pp)); } z = FpM_ker(shallowconcat(x,y), p); for (j=lg(z)-1; j; j--) setlg(gel(z,j),lx); return FpM_mul(x,z,p); } GEN FpM_intersect(GEN x, GEN y, GEN p) { pari_sp av = avma; GEN z; if (lgefint(p) == 3) { ulong pp = p[2]; z = Flm_to_ZM(Flm_image(Flm_intersect_i(ZM_to_Flm(x,pp), ZM_to_Flm(y,pp), pp), pp)); } else z = FpM_image(FpM_intersect_i(x,y,p), p); return gerepileupto(av, z); } static void init_suppl(GEN x) { if (lg(x) == 1) pari_err_IMPL("suppl [empty matrix]"); /* HACK: avoid overwriting d from gauss_pivot() after set_avma(av) */ (void)new_chunk(lgcols(x) * 2); } GEN FpM_suppl(GEN x, GEN p) { GEN d; long r; init_suppl(x); d = FpM_gauss_pivot(x,p, &r); return get_suppl(x,d,nbrows(x),r,&col_ei); } GEN F2m_suppl(GEN x) { GEN d; long r; init_suppl(x); d = F2m_gauss_pivot(F2m_copy(x), &r); return get_suppl(x,d,mael(x,1,1),r,&F2v_ei); } GEN Flm_suppl(GEN x, ulong p) { GEN d; long r; init_suppl(x); d = Flm_pivots(x, p, &r, 0); return get_suppl(x,d,nbrows(x),r,&vecsmall_ei); } GEN F2xqM_suppl(GEN x, GEN T) { void *E; const struct bb_field *S = get_F2xq_field(&E, T); return gen_suppl(x, E, S, _F2xqM_mul); } GEN FlxqM_suppl(GEN x, GEN T, ulong p) { void *E; const struct bb_field *S = get_Flxq_field(&E, T, p); return gen_suppl(x, E, S, _FlxqM_mul); } 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); set_avma(av); return get_suppl(x,d,nbrows(x),r,&col_ei); } static void init_indexrank(GEN x) { (void)new_chunk(3 + 2*lg(x)); /* HACK */ } 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); set_avma(av); return indexrank0(lg(x)-1, r, d); } GEN Flm_indexrank(GEN x, ulong p) { pari_sp av = avma; long r; GEN d; init_indexrank(x); d = Flm_pivots(x, p, &r, 0); set_avma(av); return indexrank0(lg(x)-1, r, d); } GEN F2m_indexrank(GEN x) { pari_sp av = avma; long r; GEN d; init_indexrank(x); d = F2m_gauss_pivot(F2m_copy(x),&r); set_avma(av); return indexrank0(lg(x)-1, r, d); } GEN F2xqM_indexrank(GEN x, GEN T) { pari_sp av = avma; long r; GEN d; init_indexrank(x); d = F2xqM_gauss_pivot(x, T, &r); set_avma(av); return indexrank0(lg(x) - 1, r, d); } GEN FlxqM_indexrank(GEN x, GEN T, ulong p) { pari_sp av = avma; long r; GEN d; init_indexrank(x); d = FlxqM_gauss_pivot(x, T, p, &r); set_avma(av); return indexrank0(lg(x) - 1, r, d); } GEN FqM_indexrank(GEN x, GEN T, GEN p) { pari_sp av = avma; long r; GEN d; init_indexrank(x); d = FqM_gauss_pivot(x, T, p, &r); set_avma(av); return indexrank0(lg(x) - 1, r, d); } /*******************************************************************/ /* */ /* Solve A*X=B (Gauss pivot) */ /* */ /*******************************************************************/ /* 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 cx_approx0(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; } /* bk -= m * bi */ static void _submul(GEN b, long k, long i, GEN m) { gel(b,k) = gsub(gel(b,k), gmul(m, gel(b,i))); } static int init_gauss(GEN a, GEN *b, long *aco, long *li, int *iscol) { *iscol = *b ? (typ(*b) == t_COL): 0; *aco = lg(a) - 1; if (!*aco) /* a empty */ { if (*b && lg(*b) != 1) pari_err_DIM("gauss"); *li = 0; return 0; } *li = nbrows(a); if (*li < *aco) pari_err_INV("gauss [no left inverse]", a); if (*b) { switch(typ(*b)) { case t_MAT: if (lg(*b) == 1) return 0; *b = RgM_shallowcopy(*b); break; case t_COL: *b = mkmat( leafcopy(*b) ); break; default: pari_err_TYPE("gauss",*b); } if (nbrows(*b) != *li) pari_err_DIM("gauss"); } else *b = matid(*li); return 1; } static GEN RgM_inv_FpM(GEN a, GEN p) { ulong pp; a = RgM_Fp_init(a, p, &pp); switch(pp) { case 0: a = FpM_inv(a,p); if (a) a = FpM_to_mod(a, p); break; case 2: a = F2m_inv(a); if (a) a = F2m_to_mod(a); break; default: a = Flm_inv_sp(a, NULL, pp); if (a) a = Flm_to_mod(a, pp); } return a; } static GEN RgM_inv_FqM(GEN x, GEN pol, GEN p) { pari_sp av = avma; GEN b, T = RgX_to_FpX(pol, p); if (signe(T) == 0) pari_err_OP("^",x,gen_m1); b = FqM_inv(RgM_to_FqM(x, T, p), T, p); if (!b) return gc_NULL(av); return gerepileupto(av, FqM_to_mod(b, T, p)); } #define code(t1,t2) ((t1 << 6) | t2) static GEN RgM_inv_fast(GEN x) { GEN p, pol; long pa; long t = RgM_type(x, &p,&pol,&pa); switch(t) { case t_INT: /* Fall back */ case t_FRAC: return QM_inv(x); case t_FFELT: return FFM_inv(x, pol); case t_INTMOD: return RgM_inv_FpM(x, p); case code(t_POLMOD, t_INTMOD): return RgM_inv_FqM(x, pol, p); default: return gen_0; } } #undef code static GEN RgM_RgC_solve_FpC(GEN a, GEN b, GEN p) { pari_sp av = avma; ulong pp; a = RgM_Fp_init(a, p, &pp); switch(pp) { case 0: b = RgC_to_FpC(b, p); a = FpM_FpC_gauss(a,b,p); return a ? gerepileupto(av, FpC_to_mod(a, p)): NULL; case 2: b = RgV_to_F2v(b); a = F2m_F2c_gauss(a,b); return a ? gerepileupto(av, F2c_to_mod(a)): NULL; default: b = RgV_to_Flv(b, pp); a = Flm_Flc_gauss(a, b, pp); return a ? gerepileupto(av, Flc_to_mod(a, pp)): NULL; } } static GEN RgM_solve_FpM(GEN a, GEN b, GEN p) { pari_sp av = avma; ulong pp; a = RgM_Fp_init(a, p, &pp); switch(pp) { case 0: b = RgM_to_FpM(b, p); a = FpM_gauss(a,b,p); return a ? gerepileupto(av, FpM_to_mod(a, p)): NULL; case 2: b = RgM_to_F2m(b); a = F2m_gauss(a,b); return a ? gerepileupto(av, F2m_to_mod(a)): NULL; default: b = RgM_to_Flm(b, pp); a = Flm_gauss(a,b,pp); return a ? gerepileupto(av, Flm_to_mod(a, pp)): NULL; } } /* Gaussan Elimination. If a is square, return a^(-1)*b; * if a has more rows than columns and b is NULL, return c such that c a = Id. * a is a (not necessarily square) matrix * b is a matrix or column vector, NULL meaning: take the identity matrix, * effectively returning the inverse of a * If a and b are empty, the result is the empty matrix. * * li: number of rows of a and b * aco: number of columns of a * bco: number of columns of b (if matrix) */ static GEN RgM_solve_basecase(GEN a, GEN b) { pari_sp av = avma; long i, j, k, li, bco, aco; int iscol; pivot_fun pivot; GEN p, u, data; set_avma(av); if (lg(a)-1 == 2 && nbrows(a) == 2) { /* 2x2 matrix, start by inverting a */ GEN u = gcoeff(a,1,1), v = gcoeff(a,1,2); GEN w = gcoeff(a,2,1), x = gcoeff(a,2,2); GEN D = gsub(gmul(u,x), gmul(v,w)), ainv; if (gequal0(D)) return NULL; ainv = mkmat2(mkcol2(x, gneg(w)), mkcol2(gneg(v), u)); ainv = gmul(ainv, ginv(D)); if (b) ainv = gmul(ainv, b); return gerepileupto(av, ainv); } if (!init_gauss(a, &b, &aco, &li, &iscol)) return cgetg(1, iscol?t_COL:t_MAT); pivot = get_pivot_fun(a, a, &data); a = RgM_shallowcopy(a); bco = lg(b)-1; if(DEBUGLEVEL>4) err_printf("Entering gauss\n"); p = NULL; /* gcc -Wall */ for (i=1; i<=aco; i++) { /* k is the line where we find the pivot */ k = pivot(a, data, i, NULL); if (k > li) return NULL; if (k != i) { /* exchange the lines s.t. k = i */ for (j=i; j<=aco; j++) swap(gcoeff(a,i,j), gcoeff(a,k,j)); for (j=1; j<=bco; j++) swap(gcoeff(b,i,j), gcoeff(b,k,j)); } p = gcoeff(a,i,i); if (i == aco) break; for (k=i+1; k<=li; k++) { GEN m = gcoeff(a,k,i); if (!gequal0(m)) { m = gdiv(m,p); for (j=i+1; j<=aco; j++) _submul(gel(a,j),k,i,m); for (j=1; j<=bco; j++) _submul(gel(b,j),k,i,m); } } if (gc_needed(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); } static GEN RgM_RgC_solve_fast(GEN x, GEN y) { GEN p, pol; long pa; long t = RgM_RgC_type(x, y, &p,&pol,&pa); switch(t) { case t_INT: return ZM_gauss(x, y); case t_FRAC: return QM_gauss(x, y); case t_INTMOD: return RgM_RgC_solve_FpC(x, y, p); case t_FFELT: return FFM_FFC_gauss(x, y, pol); default: return gen_0; } } static GEN RgM_solve_fast(GEN x, GEN y) { GEN p, pol; long pa; long t = RgM_type2(x, y, &p,&pol,&pa); switch(t) { case t_INT: return ZM_gauss(x, y); case t_FRAC: return QM_gauss(x, y); case t_INTMOD: return RgM_solve_FpM(x, y, p); case t_FFELT: return FFM_gauss(x, y, pol); default: return gen_0; } } GEN RgM_solve(GEN a, GEN b) { pari_sp av = avma; GEN u; if (!b) return RgM_inv(a); u = typ(b)==t_MAT ? RgM_solve_fast(a, b): RgM_RgC_solve_fast(a, b); if (!u) return gc_NULL(av); if (u != gen_0) return u; return RgM_solve_basecase(a, b); } GEN RgM_div(GEN a, GEN b) { pari_sp av = avma; GEN u = RgM_solve(shallowtrans(b), shallowtrans(a)); if (!u) return gc_NULL(av); return gerepilecopy(av, shallowtrans(u)); } GEN RgM_inv(GEN a) { GEN b = RgM_inv_fast(a); return b==gen_0? RgM_solve_basecase(a, NULL): b; } /* 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 0) retmkmat2(mkcol2(icopy(d), negi(c)), mkcol2(negi(b), icopy(a))); else retmkmat2(mkcol2(negi(d), icopy(c)), mkcol2(icopy(b), negi(a))); } /* to be used when denom(M^(-1)) << det(M) and a sharp multiple is * not available. Return H primitive such that M*H = den*Id */ GEN ZM_inv_ratlift(GEN M, GEN *pden) { pari_sp av2, av = avma; GEN Hp, q, H; ulong p; long m = lg(M)-1; forprime_t S; pari_timer ti; if (m == 0) return ZM_inv0(M,pden); if (m == 1 && nbrows(M)==1) return ZM_inv1(M,pden); if (m == 2 && nbrows(M)==2) return ZM_inv2(M,pden); if (DEBUGLEVEL>5) timer_start(&ti); init_modular_big(&S); av2 = avma; H = NULL; while ((p = u_forprime_next(&S))) { GEN Mp, B, Hr; Mp = ZM_to_Flm(M,p); Hp = Flm_inv_sp(Mp, NULL, p); if (!Hp) continue; if (!H) { H = ZM_init_CRT(Hp, p); q = utoipos(p); } else ZM_incremental_CRT(&H, Hp, &q, p); B = sqrti(shifti(q,-1)); Hr = FpM_ratlift(H,q,B,B,NULL); if (DEBUGLEVEL>5) timer_printf(&ti,"ZM_inv mod %lu (ratlift=%ld)", p,!!Hr); if (Hr) {/* DONE ? */ GEN Hl = Q_remove_denom(Hr, pden); if (ZM_isscalar(ZM_mul(Hl, M), *pden)) { H = Hl; break; } } if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"ZM_inv_ratlift"); gerepileall(av2, 2, &H, &q); } } if (!*pden) *pden = gen_1; return gc_all(av, 2, &H, pden); } GEN FpM_ratlift_worker(GEN A, GEN mod, GEN B) { long l, i; GEN H = cgetg_copy(A, &l); for (i = 1; i < l; i++) { GEN c = FpC_ratlift(gel(A,i), mod, B, B, NULL); gel(H,i) = c? c: gen_0; } return H; } static int can_ratlift(GEN x, GEN mod, GEN B) { pari_sp av = avma; GEN a, b; return gc_bool(av, Fp_ratlift(x, mod, B, B, &a,&b)); } static GEN FpM_ratlift_parallel(GEN A, GEN mod, GEN B) { pari_sp av = avma; GEN worker; long i, l = lg(A), m = mt_nbthreads(); int test = !!B; if (l == 1 || lgcols(A) == 1) return gcopy(A); if (!B) B = sqrti(shifti(mod,-1)); if (m == 1 || l == 2 || lgcols(A) < 10) { A = FpM_ratlift(A, mod, B, B, NULL); return A? A: gc_NULL(av); } /* test one coefficient first */ if (test && !can_ratlift(gcoeff(A,1,1), mod, B)) return gc_NULL(av); worker = snm_closure(is_entry("_FpM_ratlift_worker"), mkvec2(mod,B)); A = gen_parapply_slice(worker, A, m); for (i = 1; i < l; i++) if (typ(gel(A,i)) != t_COL) return gc_NULL(av); return A; } static GEN ZM_adj_ratlift(GEN A, GEN H, GEN mod, GEN T) { pari_sp av = avma; GEN B, D, g; D = ZMrow_ZC_mul(H, gel(A,1), 1); if (T) D = mulii(T, D); g = gcdii(D, mod); if (!equali1(g)) { mod = diviiexact(mod, g); H = FpM_red(H, mod); } D = Fp_inv(Fp_red(D, mod), mod); /* test 1 coeff first */ B = sqrti(shifti(mod,-1)); if (!can_ratlift(Fp_mul(D, gcoeff(A,1,1), mod), mod, B)) return gc_NULL(av); H = FpM_Fp_mul(H, D, mod); H = FpM_ratlift_parallel(H, mod, B); return H? H: gc_NULL(av); } /* if (T) return T A^(-1) in Mn(Q), else B in Mn(Z) such that A B = den*Id */ static GEN ZM_inv_i(GEN A, GEN *pden, GEN T) { pari_sp av = avma; long m = lg(A)-1, n, k1 = 1, k2; GEN H = NULL, D, H1 = NULL, mod1 = NULL, worker; ulong bnd, mask; forprime_t S; pari_timer ti; if (m == 0) return ZM_inv0(A,pden); if (pden) *pden = gen_1; if (nbrows(A) < m) return NULL; if (m == 1 && nbrows(A)==1 && !T) return ZM_inv1(A,pden); if (m == 2 && nbrows(A)==2 && !T) return ZM_inv2(A,pden); if (DEBUGLEVEL>=5) timer_start(&ti); init_modular_big(&S); bnd = expi(RgM_true_Hadamard(A)); worker = snm_closure(is_entry("_ZM_inv_worker"), mkvec(A)); gen_inccrt("ZM_inv_r", worker, NULL, k1, 0, &S, &H1, &mod1, nmV_chinese_center, FpM_center); n = (bnd+1)/expu(S.p)+1; if (DEBUGLEVEL>=5) timer_printf(&ti,"inv (%ld/%ld primes)", k1, n); mask = quadratic_prec_mask(n); for (k2 = 0;;) { GEN Hr; if (k2 > 0) { gen_inccrt("ZM_inv_r", worker, NULL, k2, 0, &S, &H1, &mod1,nmV_chinese_center,FpM_center); k1 += k2; if (DEBUGLEVEL>=5) timer_printf(&ti,"CRT (%ld/%ld primes)", k1, n); } if (mask == 1) break; k2 = (mask&1UL) ? k1-1: k1; mask >>= 1; Hr = ZM_adj_ratlift(A, H1, mod1, T); if (DEBUGLEVEL>=5) timer_printf(&ti,"ratlift (%ld/%ld primes)", k1, n); if (Hr) {/* DONE ? */ GEN Hl = Q_primpart(Hr), R = ZM_mul(Hl, A), d = gcoeff(R,1,1); if (gsigne(d) < 0) { d = gneg(d); Hl = ZM_neg(Hl); } if (DEBUGLEVEL>=5) timer_printf(&ti,"mult (%ld/%ld primes)", k1, n); if (equali1(d)) { if (ZM_isidentity(R)) { H = Hl; break; } } else if (ZM_isscalar(R, d)) { if (T) T = gdiv(T,d); else if (pden) *pden = d; H = Hl; break; } } } if (!H) { GEN d; H = H1; D = ZMrow_ZC_mul(H, gel(A,1), 1); if (signe(D)==0) pari_err_INV("ZM_inv", A); if (T) T = gdiv(T, D); else { d = gcdii(Q_content_safe(H), D); if (signe(D) < 0) d = negi(d); if (!equali1(d)) { H = ZM_Z_divexact(H, d); D = diviiexact(D, d); } if (pden) *pden = D; } } if (T && !isint1(T)) H = ZM_Q_mul(H, T); return gc_all(av, pden? 2: 1, &H, pden); } GEN ZM_inv(GEN A, GEN *pden) { return ZM_inv_i(A, pden, NULL); } /* same as above, M rational */ GEN QM_inv(GEN M) { pari_sp av = avma; GEN den, dM, K; M = Q_remove_denom(M, &dM); K = ZM_inv_i(M, &den, dM); if (!K) return gc_NULL(av); if (den && !equali1(den)) K = ZM_Q_mul(K, ginv(den)); return gerepileupto(av, K); } static GEN ZM_ker_filter(GEN A, GEN P) { long i, j, l = lg(A), n = 1, d = lg(gmael(A,1,1)); GEN B, Q, D = gmael(A,1,2); for (i=2; i di || (di==d && c>0)) { n = 1; d = di; D = Di; } } B = cgetg(n+1, t_VEC); Q = cgetg(n+1, typ(P)); for (i=1, j=1; i 1 */ static GEN ZM_ker_i(GEN A) { pari_sp av; long k, m = lg(A)-1; GEN HD = NULL, mod = gen_1, worker; forprime_t S; if (m >= 2*nbrows(A)) { GEN v = ZM_indexrank(A), y = gel(v,2), z = indexcompl(y, m); GEN B, A1, A1i, d; A = rowpermute(A, gel(v,1)); /* same kernel */ A1 = vecpermute(A, y); /* maximal rank submatrix */ B = vecpermute(A, z); A1i = ZM_inv(A1, &d); if (!d) d = gen_1; B = vconcat(ZM_mul(ZM_neg(A1i), B), scalarmat_shallow(d, lg(B)-1)); if (!gequal(y, identity_perm(lg(y)-1))) B = rowpermute(B, perm_inv(shallowconcat(y,z))); return vec_Q_primpart(B); } init_modular_big(&S); worker = snm_closure(is_entry("_ZM_ker_worker"), mkvec(A)); av = avma; for (k = 1;; k <<= 1) { pari_timer ti; GEN H, Hr; gen_inccrt_i("ZM_ker", worker, NULL, (k+1)>>1, 0, &S, &HD, &mod, ZM_ker_chinese, NULL); gerepileall(av, 2, &HD, &mod); H = gel(HD, 1); if (lg(H) == 1) return H; if (DEBUGLEVEL >= 4) timer_start(&ti); Hr = FpM_ratlift_parallel(H, mod, NULL); if (DEBUGLEVEL >= 4) timer_printf(&ti,"ZM_ker: ratlift (%ld)",!!Hr); if (Hr) { GEN MH; Hr = vec_Q_primpart(Hr); MH = ZM_mul(A, Hr); if (DEBUGLEVEL >= 4) timer_printf(&ti,"ZM_ker: QM_mul"); if (ZM_equal0(MH)) return Hr; } } } GEN ZM_ker(GEN M) { pari_sp av = avma; long l = lg(M)-1; if (l==0) return cgetg(1, t_MAT); if (lgcols(M)==1) return matid(l); return gerepilecopy(av, ZM_ker_i(M)); } static GEN ZM_gauss_slice(GEN A, GEN B, GEN P, GEN *mod) { pari_sp av = avma; long i, n = lg(P)-1; GEN H, T; if (n == 1) { ulong p = uel(P,1); GEN Hp = Flm_gauss(ZM_to_Flm(A, p) , ZM_to_Flm(B, p) ,p); if (!Hp) { *mod=gen_1; return zeromat(lg(A)-1,lg(B)-1); } Hp = gerepileupto(av, Flm_to_ZM(Hp)); *mod = utoipos(p); return Hp; } T = ZV_producttree(P); A = ZM_nv_mod_tree(A, P, T); B = ZM_nv_mod_tree(B, P, T); H = cgetg(n+1, t_VEC); for(i=1; i <= n; i++) { GEN Hi = Flm_gauss(gel(A, i), gel(B,i), uel(P,i)); gel(H,i) = Hi ? Hi: zero_Flm(lg(A)-1,lg(B)-1); if (!Hi) uel(P,i)=1; } H = nmV_chinese_center_tree_seq(H, P, T, ZV_chinesetree(P,T)); *mod = gmael(T, lg(T)-1, 1); return gc_all(av, 2, &H, mod); } GEN ZM_gauss_worker(GEN P, GEN A, GEN B) { GEN V = cgetg(3, t_VEC); gel(V,1) = ZM_gauss_slice(A, B, P, &gel(V,2)); return V; } /* assume lg(A) > 1 */ static GEN ZM_gauss_i(GEN A, GEN B) { pari_sp av; long k, m, ncol; int iscol; GEN y, y1, y2, Hr, H = NULL, mod = gen_1, worker; forprime_t S; if (!init_gauss(A, &B, &m, &ncol, &iscol)) return cgetg(1, iscol?t_COL:t_MAT); init_modular_big(&S); y = ZM_indexrank(A); y1 = gel(y,1); y2 = gel(y,2); if (lg(y2)-1 != m) return NULL; A = rowpermute(A, y1); B = rowpermute(B, y1); /* a is square and invertible */ ncol = lg(B); worker = snm_closure(is_entry("_ZM_gauss_worker"), mkvec2(A,B)); av = avma; for (k = 1;; k <<= 1) { pari_timer ti; gen_inccrt_i("ZM_gauss", worker, NULL, (k+1)>>1 , m, &S, &H, &mod, nmV_chinese_center, FpM_center); gerepileall(av, 2, &H, &mod); if (DEBUGLEVEL >= 4) timer_start(&ti); Hr = FpM_ratlift_parallel(H, mod, NULL); if (DEBUGLEVEL >= 4) timer_printf(&ti,"ZM_gauss: ratlift (%ld)",!!Hr); if (Hr) { GEN MH, c; MH = ZM_mul(A, Q_remove_denom(Hr, &c)); if (DEBUGLEVEL >= 4) timer_printf(&ti,"ZM_gauss: QM_mul"); if (ZM_equal(MH, c ? ZM_Z_mul(B, c): B)) break; } } return iscol ? gel(Hr, 1): Hr; } GEN ZM_gauss(GEN A, GEN B) { pari_sp av = avma; GEN C = ZM_gauss_i(A,B); return C ? gerepilecopy(av, C): NULL; } GEN QM_ker(GEN M) { pari_sp av = avma; long l = lg(M)-1; if (l==0) return cgetg(1, t_MAT); if (lgcols(M)==1) return matid(l); return gerepilecopy(av, ZM_ker_i(row_Q_primpart(M))); } /* x a ZM. Return a multiple of the determinant of the lattice generated by * the columns of x. From Algorithm 2.2.6 in GTM138 */ GEN detint(GEN A) { if (typ(A) != t_MAT) pari_err_TYPE("detint",A); RgM_check_ZM(A, "detint"); return ZM_detmult(A); } GEN ZM_detmult(GEN A) { pari_sp av1, av = avma; GEN B, c, v, piv; long rg, i, j, k, m, n = lg(A) - 1; if (!n) return gen_1; m = nbrows(A); if (n < m) return gen_0; c = zero_zv(m); av1 = avma; B = zeromatcopy(m,m); v = cgetg(m+1, t_COL); piv = gen_1; rg = 0; for (k=1; k<=n; k++) { GEN pivprec = piv; long t = 0; for (i=1; i<=m; i++) { pari_sp av2 = avma; GEN vi; if (c[i]) continue; vi = mulii(piv, gcoeff(A,i,k)); for (j=1; j<=m; j++) if (c[j]) vi = addii(vi, mulii(gcoeff(B,j,i),gcoeff(A,j,k))); if (!t && signe(vi)) t = i; gel(v,i) = gerepileuptoint(av2, vi); } if (!t) continue; /* at this point c[t] = 0 */ if (++rg >= m) { /* full rank; mostly done */ GEN det = gel(v,t); /* last on stack */ if (++k > n) det = absi(det); else { /* improve further; at this point c[i] is set for all i != t */ gcoeff(B,t,t) = piv; v = centermod(gel(B,t), det); for ( ; k<=n; k++) det = gcdii(det, ZV_dotproduct(v, gel(A,k))); } 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 (gc_needed(av,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"detint. k=%ld",k); gerepileall(av1, 2, &piv,&B); v = zerovec(m); } } return gc_const(av, gen_0); } /* Reduce x modulo (invertible) y */ GEN closemodinvertible(GEN x, GEN y) { return gmul(y, ground(RgM_solve(y,x))); } GEN reducemodinvertible(GEN x, GEN y) { return gsub(x, closemodinvertible(x,y)); } GEN reducemodlll(GEN x,GEN y) { return reducemodinvertible(x, ZM_lll(y, 0.75, LLL_INPLACE)); } /*******************************************************************/ /* */ /* KERNEL of an m x n matrix */ /* return n - rk(x) linearly independent vectors */ /* */ /*******************************************************************/ static GEN RgM_deplin_i(GEN x0) { pari_sp av = avma, av2; long i, j, k, nl, nc = lg(x0)-1; GEN D, x, y, c, l, d, ck; if (!nc) return NULL; nl = nbrows(x0); c = zero_zv(nl); l = cgetg(nc+1, t_VECSMALL); /* not initialized */ av2 = avma; x = RgM_shallowcopy(x0); d = const_vec(nl, gen_1); /* pivot list */ ck = NULL; /* gcc -Wall */ for (k=1; k<=nc; k++) { ck = gel(x,k); for (j=1; j nl) break; if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"deplin k = %ld/%ld",k,nc); gerepileall(av2, 2, &x, &d); ck = gel(x,k); } gel(d,k) = gel(ck,i); c[i] = k; l[k] = i; /* pivot d[k] in x[i,k] */ } if (k > nc) return gc_NULL(av); if (k == 1) { set_avma(av); return scalarcol_shallow(gen_1,nc); } y = cgetg(nc+1,t_COL); gel(y,1) = gcopy(gel(ck, l[1])); for (D=gel(d,1),j=2; j>1); x = zc_to_ZC(x); break; } return gerepileupto(av, x); } /* FIXME: implement direct modular ZM_deplin ? */ static GEN QM_deplin(GEN M) { pari_sp av = avma; long l = lg(M)-1; GEN k; if (l==0) return NULL; if (lgcols(M)==1) return col_ei(l, 1); k = ZM_ker_i(row_Q_primpart(M)); if (lg(k)== 1) return gc_NULL(av); return gerepilecopy(av, gel(k,1)); } static GEN RgM_deplin_FqM(GEN x, GEN pol, GEN p) { pari_sp av = avma; GEN b, T = RgX_to_FpX(pol, p); if (signe(T) == 0) pari_err_OP("deplin",x,pol); b = FqM_deplin(RgM_to_FqM(x, T, p), T, p); if (!b) return gc_NULL(av); return gerepileupto(av, b); } #define code(t1,t2) ((t1 << 6) | t2) static GEN RgM_deplin_fast(GEN x) { GEN p, pol; long pa; long t = RgM_type(x, &p,&pol,&pa); switch(t) { case t_INT: /* fall through */ case t_FRAC: return QM_deplin(x); case t_FFELT: return FFM_deplin(x, pol); case t_INTMOD: return RgM_deplin_FpM(x, p); case code(t_POLMOD, t_INTMOD): return RgM_deplin_FqM(x, pol, p); default: return gen_0; } } #undef code static GEN RgM_deplin(GEN x) { GEN z = RgM_deplin_fast(x); if (z!= gen_0) return z; return RgM_deplin_i(x); } GEN deplin(GEN x) { switch(typ(x)) { case t_MAT: { GEN z = RgM_deplin(x); if (z) return z; return cgetg(1, t_COL); } case t_VEC: return RgV_deplin(x); default: pari_err_TYPE("deplin",x); } return NULL;/*LCOV_EXCL_LINE*/ } /*******************************************************************/ /* */ /* GAUSS REDUCTION OF MATRICES (m lines x n cols) */ /* (kernel, image, complementary image, rank) */ /* */ /*******************************************************************/ /* return the transform of x under a standard Gauss pivot. * x0 is a reference point when guessing whether x[i,j] ~ 0 * (iff x[i,j] << x0[i,j]) * Set r = dim ker(x). d[k] contains the index of the first nonzero pivot * in column k */ static GEN gauss_pivot_ker(GEN x, GEN x0, GEN *dd, long *rr) { GEN c, d, p, data; pari_sp av; long i, j, k, r, t, n, m; pivot_fun pivot; n=lg(x)-1; if (!n) { *dd=NULL; *rr=0; return cgetg(1,t_MAT); } m=nbrows(x); r=0; pivot = get_pivot_fun(x, x0, &data); x = RgM_shallowcopy(x); c = zero_zv(m); d = cgetg(n+1,t_VECSMALL); av=avma; for (k=1; k<=n; k++) { j = pivot(x, data, k, c); if (j > m) { r++; d[k]=0; for(j=1; j m) { r++; d[k] = 0; } else { c[j] = k; d[k] = j; p = gdiv(gen_m1, gcoeff(x,j,k)); for (i=k+1; i<=n; i++) gcoeff(x,j,i) = gmul(p,gcoeff(x,j,i)); for (t=1; t<=m; t++) if (!c[t]) /* no pivot on that line yet */ { p = gcoeff(x,t,k); gcoeff(x,t,k) = gen_0; for (i=k+1; i<=n; i++) gcoeff(x,t,i) = gadd(gcoeff(x,t,i), gmul(p, gcoeff(x,j,i))); if (gc_needed(av,1)) gerepile_gauss(x,k,t,av,j,c); } for (i=k; i<=n; i++) gcoeff(x,j,i) = gen_0; /* dummy */ } } *rr = r; return gc_const((pari_sp)d, d); } static long ZM_count_0_cols(GEN M) { long i, l = lg(M), n = 0; for (i = 1; i < l; i++) if (ZV_equal0(gel(M,i))) n++; return n; } static void indexrank_all(long m, long n, long r, GEN d, GEN *prow, GEN *pcol); /* As RgM_pivots, integer entries. Set *rr = dim Ker M0 */ GEN ZM_pivots(GEN M0, long *rr) { GEN d, dbest = NULL; long m, mm, n, nn, i, imax, rmin, rbest, zc; int beenthere = 0; pari_sp av, av0 = avma; forprime_t S; rbest = n = lg(M0)-1; if (n == 0) { *rr = 0; return NULL; } zc = ZM_count_0_cols(M0); if (n == zc) { *rr = zc; return zero_zv(n); } m = nbrows(M0); rmin = maxss(zc, n-m); init_modular_small(&S); if (n <= m) { nn = n; mm = m; } else { nn = m; mm = n; } imax = (nn < 16)? 1: (nn < 64)? 2: 3; /* heuristic */ for(;;) { GEN row, col, M, KM, IM, RHS, X, cX; long rk; for (av = avma, i = 0;; set_avma(av), i++) { ulong p = u_forprime_next(&S); long rp; if (!p) pari_err_OVERFLOW("ZM_pivots [ran out of primes]"); d = Flm_pivots(ZM_to_Flm(M0, p), p, &rp, 1); if (rp == rmin) { rbest = rp; goto END; } /* maximal rank, return */ if (rp < rbest) { /* save best r so far */ rbest = rp; guncloneNULL(dbest); dbest = gclone(d); if (beenthere) break; } if (!beenthere && i >= imax) break; } beenthere = 1; /* Dubious case: there is (probably) a non trivial kernel */ indexrank_all(m,n, rbest, dbest, &row, &col); M = rowpermute(vecpermute(M0, col), row); rk = n - rbest; /* (probable) dimension of image */ if (n > m) M = shallowtrans(M); IM = vecslice(M,1,rk); KM = vecslice(M,rk+1, nn); M = rowslice(IM, 1,rk); /* square maximal rank */ X = ZM_gauss(M, rowslice(KM, 1,rk)); RHS = rowslice(KM,rk+1,mm); M = rowslice(IM,rk+1,mm); X = Q_remove_denom(X, &cX); if (cX) RHS = ZM_Z_mul(RHS, cX); if (ZM_equal(ZM_mul(M, X), RHS)) { d = vecsmall_copy(dbest); goto END; } set_avma(av); } END: *rr = rbest; guncloneNULL(dbest); return gerepileuptoleaf(av0, d); } /* set *pr = dim Ker x */ static GEN gauss_pivot(GEN x, long *pr) { GEN data; pivot_fun pivot = get_pivot_fun(x, x, &data); return RgM_pivots(x, data, pr, pivot); } /* compute ker(x), x0 is a reference point when guessing whether x[i,j] ~ 0 * (iff x[i,j] << x0[i,j]) */ static GEN ker_aux(GEN x, GEN x0) { pari_sp av = avma; GEN d,y; long i,j,k,r,n; x = gauss_pivot_ker(x,x0,&d,&r); if (!r) { set_avma(av); return cgetg(1,t_MAT); } n = lg(x)-1; y=cgetg(r+1,t_MAT); for (j=k=1; j<=r; j++,k++) { GEN p = cgetg(n+1,t_COL); gel(y,j) = p; while (d[k]) k++; for (i=1; i= 1; i--, j--) { for (; j>=1; j--) if (!gequal0(gcoeff(Y,i,j))) { d[i] = j; break; } if (!j) return gc_NULL(av); } /* reduce to the case Y square, upper triangular with 1s on diagonal */ Y = vecpermute(Y, d); x = vecpermute(x, d); X = rowslice(x, 1, nA); return gerepileupto(av, RgM_mul(X, RgM_inv_upper(Y))); } static GEN RgM_suppl_FpM(GEN x, GEN p) { pari_sp av = avma; ulong pp; x = RgM_Fp_init(x, p, &pp); switch(pp) { case 0: x = FpM_to_mod(FpM_suppl(x,p), p); break; case 2: x = F2m_to_mod(F2m_suppl(x)); break; default:x = Flm_to_mod(Flm_suppl(x,pp), pp); break; } return gerepileupto(av, x); } static GEN RgM_suppl_fast(GEN x) { GEN p, pol; long pa; long t = RgM_type(x,&p,&pol,&pa); switch(t) { case t_INTMOD: return RgM_suppl_FpM(x, p); case t_FFELT: return FFM_suppl(x, pol); default: return NULL; } } /* 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, M; long r; if (typ(x)!=t_MAT) pari_err_TYPE("suppl",x); M = RgM_suppl_fast(x); if (M) return M; init_suppl(x); d = gauss_pivot(x,&r); set_avma(av); return get_suppl(x,d,nbrows(x),r,&col_ei); } GEN image2(GEN x) { pari_sp av = avma; long k, n, i; GEN A, B; if (typ(x)!=t_MAT) pari_err_TYPE("image2",x); if (lg(x) == 1) return cgetg(1,t_MAT); A = ker(x); k = lg(A)-1; if (!k) { set_avma(av); return gcopy(x); } A = suppl(A); n = lg(A)-1; B = cgetg(n-k+1, t_MAT); for (i = k+1; i <= n; i++) gel(B,i-k) = RgM_RgC_mul(x, gel(A,i)); return gerepileupto(av, B); } GEN matimage0(GEN x,long flag) { switch(flag) { case 0: return image(x); case 1: return image2(x); default: pari_err_FLAG("matimage"); } return NULL; /* LCOV_EXCL_LINE */ } static long RgM_rank_FpM(GEN x, GEN p) { pari_sp av = avma; ulong pp; long r; x = RgM_Fp_init(x,p,&pp); switch(pp) { case 0: r = FpM_rank(x,p); break; case 2: r = F2m_rank(x); break; default:r = Flm_rank(x,pp); break; } return gc_long(av, r); } static long RgM_rank_FqM(GEN x, GEN pol, GEN p) { pari_sp av = avma; long r; GEN T = RgX_to_FpX(pol, p); if (signe(T) == 0) pari_err_OP("rank",x,pol); r = FqM_rank(RgM_to_FqM(x, T, p), T, p); return gc_long(av,r); } #define code(t1,t2) ((t1 << 6) | t2) static long RgM_rank_fast(GEN x) { GEN p, pol; long pa; long t = RgM_type(x,&p,&pol,&pa); switch(t) { case t_INT: return ZM_rank(x); case t_FRAC: return QM_rank(x); case t_INTMOD: return RgM_rank_FpM(x, p); case t_FFELT: return FFM_rank(x, pol); case code(t_POLMOD, t_INTMOD): return RgM_rank_FqM(x, pol, p); default: return -1; } } #undef code long rank(GEN x) { pari_sp av = avma; long r; if (typ(x)!=t_MAT) pari_err_TYPE("rank",x); r = RgM_rank_fast(x); if (r >= 0) return r; (void)gauss_pivot(x, &r); return gc_long(av, lg(x)-1 - r); } /* d a t_VECSMALL of integers in 1..n. Return the vector of the d[i] * followed by the missing indices */ static GEN perm_complete(GEN d, long n) { GEN y = cgetg(n+1, t_VECSMALL); long i, j = 1, k = n, l = lg(d); pari_sp av = avma; char *T = stack_calloc(n+1); for (i = 1; i < l; i++) T[d[i]] = 1; for (i = 1; i <= n; i++) if (T[i]) y[j++] = i; else y[k--] = i; return gc_const(av, y); } /* n = dim x, r = dim Ker(x), d from gauss_pivot */ static GEN indeximage0(long n, long r, GEN d) { long i, j; GEN v; r = n - r; /* now r = dim Im(x) */ v = cgetg(r+1,t_VECSMALL); if (d) for (i=j=1; j<=n; j++) if (d[j]) v[i++] = j; return v; } /* x an m x n t_MAT, n > 0, r = dim Ker(x), d from gauss_pivot */ static void indexrank_all(long m, long n, long r, GEN d, GEN *prow, GEN *pcol) { GEN IR = indexrank0(n, r, d); *prow = perm_complete(gel(IR,1), m); *pcol = perm_complete(gel(IR,2), n); } static GEN RgM_indexrank_FpM(GEN x, GEN p) { pari_sp av = avma; ulong pp; GEN r; x = RgM_Fp_init(x,p,&pp); switch(pp) { case 0: r = FpM_indexrank(x,p); break; case 2: r = F2m_indexrank(x); break; default: r = Flm_indexrank(x,pp); break; } return gerepileupto(av, r); } static GEN RgM_indexrank_FqM(GEN x, GEN pol, GEN p) { pari_sp av = avma; GEN r, T = RgX_to_FpX(pol, p); if (signe(T) == 0) pari_err_OP("indexrank",x,pol); r = FqM_indexrank(RgM_to_FqM(x, T, p), T, p); return gerepileupto(av, r); } #define code(t1,t2) ((t1 << 6) | t2) static GEN RgM_indexrank_fast(GEN x) { GEN p, pol; long pa; long t = RgM_type(x,&p,&pol,&pa); switch(t) { case t_INT: return ZM_indexrank(x); case t_FRAC: return QM_indexrank(x); case t_INTMOD: return RgM_indexrank_FpM(x, p); case t_FFELT: return FFM_indexrank(x, pol); case code(t_POLMOD, t_INTMOD): return RgM_indexrank_FqM(x, pol, p); default: return NULL; } } #undef code GEN indexrank(GEN x) { pari_sp av; long r; GEN d; if (typ(x)!=t_MAT) pari_err_TYPE("indexrank",x); d = RgM_indexrank_fast(x); if (d) return d; av = avma; init_indexrank(x); d = gauss_pivot(x, &r); set_avma(av); return indexrank0(lg(x)-1, r, d); } GEN ZM_indeximage(GEN x) { pari_sp av = avma; long r; GEN d; init_indexrank(x); d = ZM_pivots(x,&r); set_avma(av); return indeximage0(lg(x)-1, r, d); } long ZM_rank(GEN x) { pari_sp av = avma; long r; (void)ZM_pivots(x,&r); return gc_long(av, lg(x)-1-r); } GEN ZM_indexrank(GEN x) { pari_sp av = avma; long r; GEN d; init_indexrank(x); d = ZM_pivots(x,&r); set_avma(av); return indexrank0(lg(x)-1, r, d); } long QM_rank(GEN x) { pari_sp av = avma; long r = ZM_rank(Q_primpart(x)); set_avma(av); return r; } GEN QM_indexrank(GEN x) { pari_sp av = avma; GEN r = ZM_indexrank(Q_primpart(x)); return gerepileupto(av, r); } /*******************************************************************/ /* */ /* ZabM */ /* */ /*******************************************************************/ static GEN FpXM_ratlift(GEN a, GEN q) { GEN B, y; long i, j, l = lg(a), n; B = sqrti(shifti(q,-1)); y = cgetg(l, t_MAT); if (l==1) return y; n = lgcols(a); for (i=1; i>1; ulong p= 1 + m - (m % n); long lM = lg(M); if (lM == 1) { *pden = gen_1; return cgetg(1,t_MAT); } av2 = avma; H = NULL; for(;;) { GEN Hp, Pp, Mp, Hr; do p += n; while(!uisprime(p)); Pp = ZX_to_Flx(P, p); Mp = ZXM_to_FlxM(M, p, get_Flx_var(Pp)); Hp = FlkM_inv(Mp, Pp, p); if (!Hp) continue; if (!H) { H = ZXM_init_CRT(Hp, degpol(P)-1, p); q = utoipos(p); } else ZXM_incremental_CRT(&H, Hp, &q, p); Hr = FpXM_ratlift(H, q); if (DEBUGLEVEL>5) err_printf("ZabM_inv mod %ld (ratlift=%ld)\n", p,!!Hr); if (Hr) {/* DONE ? */ GEN Hl = Q_remove_denom(Hr, pden); GEN MH = ZXQM_mul(Hl, M, P); if (*pden) { if (RgM_isscalar(MH, *pden)) { H = Hl; break; }} else { if (RgM_isidentity(MH)) { H = Hl; *pden = gen_1; break; } } } if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"ZabM_inv"); gerepileall(av2, 2, &H, &q); } } return gc_all(av, 2, &H, pden); } static GEN FlkM_ker(GEN M, GEN P, ulong p) { ulong PI = get_Fl_red(p), pi = SMALL_ULONG(p)? 0: PI; GEN R = Flx_roots_pre(P, p, pi); long l = lg(R), i, dP = degpol(P), r; GEN M1, K, D; GEN W = Flv_invVandermonde(R, 1UL, p); GEN V = cgetg(l, t_VEC); M1 = FlxM_eval_powers_pre(M, Fl_powers_pre(uel(R,1), dP, p, PI), p, pi); K = Flm_ker_sp(M1, p, 2); r = lg(gel(K,1)); D = gel(K,2); gel(V, 1) = gel(K,1); for(i=2; i>1; ulong p = 1 + m - (m % n); if (DEBUGLEVEL>5) timer_start(&ti); for(;;) { GEN Kp, Hp, Dp, Pp, Mp, Hr; do p += n; while(!uisprime(p)); Pp = ZX_to_Flx(P, p); Mp = ZXM_to_FlxM(M, p, get_Flx_var(Pp)); Kp = FlkM_ker(Mp, Pp, p); if (!Kp) continue; Hp = gel(Kp,1); Dp = gel(Kp,2); if (H && (lg(Hp)>lg(H) || (lg(Hp)==lg(H) && vecsmall_lexcmp(Dp,D)>0))) continue; if (!H || (lg(Hp)5) timer_printf(&ti,"ZabM_ker mod %ld (ratlift=%ld)", p,!!Hr); if (Hr) {/* DONE ? */ GEN Hl = vec_Q_primpart(Hr); if (ZabM_ker_check(M, Hl, p, P, n)) { H = Hl; break; } } if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"ZabM_ker"); gerepileall(av, 3, &H, &D, &q); } } return gerepilecopy(av, H); } GEN ZabM_indexrank(GEN M, GEN P, long n) { pari_sp av = avma; ulong m = LONG_MAX>>1; ulong p = 1+m-(m%n), D = degpol(P); long lM = lg(M), lmax = 0, c = 0; GEN v; for(;;) { GEN R, Pp, Mp, K; ulong pi; long l; do p += n; while (!uisprime(p)); pi = (p & HIGHMASK)? get_Fl_red(p): 0; Pp = ZX_to_Flx(P, p); R = Flx_roots_pre(Pp, p, pi); Mp = ZXM_to_FlxM(M, p, get_Flx_var(Pp)); K = FlxM_eval_powers_pre(Mp, Fl_powers_pre(uel(R,1), D,p,pi), p,pi); v = Flm_indexrank(K, p); l = lg(gel(v,2)); if (l == lM) break; if (lmax >= 0 && l > lmax) { lmax = l; c = 0; } else c++; if (c > 2) { /* probably not maximal rank, expensive check */ lM -= lg(ZabM_ker(M, P, n))-1; /* actual rank (+1) */ if (lmax == lM) break; lmax = -1; /* disable check */ } } return gerepileupto(av, v); } #if 0 GEN ZabM_gauss(GEN M, GEN P, long n, GEN *den) { pari_sp av = avma; GEN v, S, W; v = ZabM_indexrank(M, P, n); S = shallowmatextract(M,gel(v,1),gel(v,2)); W = ZabM_inv(S, P, n, den); return gc_all(av,2,&W,den); } #endif GEN ZabM_pseudoinv(GEN M, GEN P, long n, GEN *pv, GEN *den) { GEN v = ZabM_indexrank(M, P, n); if (pv) *pv = v; M = shallowmatextract(M,gel(v,1),gel(v,2)); return ZabM_inv(M, P, n, den); } GEN ZM_pseudoinv(GEN M, GEN *pv, GEN *den) { GEN v = ZM_indexrank(M); if (pv) *pv = v; M = shallowmatextract(M,gel(v,1),gel(v,2)); return ZM_inv(M, den); } /*******************************************************************/ /* */ /* Structured Elimination */ /* */ /*******************************************************************/ static void rem_col(GEN c, long i, GEN iscol, GEN Wrow, long *rcol, long *rrow) { long lc = lg(c), k; iscol[i] = 0; (*rcol)--; for (k = 1; k < lc; ++k) { Wrow[c[k]]--; if (Wrow[c[k]]==0) (*rrow)--; } } static void rem_singleton(GEN M, GEN iscol, GEN Wrow, long idx, long *rcol, long *rrow) { long i, j; long nbcol = lg(iscol)-1, last; do { last = 0; for (i = 1; i <= nbcol; ++i) if (iscol[i]) { GEN c = idx ? gmael(M, i, idx): gel(M,i); long lc = lg(c); for (j = 1; j < lc; ++j) if (Wrow[c[j]] == 1) { rem_col(c, i, iscol, Wrow, rcol, rrow); last=1; break; } } } while (last); } static GEN fill_wcol(GEN M, GEN iscol, GEN Wrow, long *w, GEN wcol) { long nbcol = lg(iscol)-1; long i, j, m, last; GEN per; for (m = 2, last=0; !last ; m++) { for (i = 1; i <= nbcol; ++i) { wcol[i] = 0; if (iscol[i]) { GEN c = gmael(M, i, 1); long lc = lg(c); for (j = 1; j < lc; ++j) if (Wrow[c[j]] == m) { wcol[i]++; last = 1; } } } } per = vecsmall_indexsort(wcol); *w = wcol[per[nbcol]]; return per; } /* M is a RgMs with nbrow rows, A a list of row indices. Eliminate rows of M with a single entry that do not belong to A, and the corresponding columns. Also eliminate columns until #colums=#rows. Return pcol and prow: pcol is a map from the new columns indices to the old one. prow is a map from the old rows indices to the new one (0 if removed). */ void RgMs_structelim_col(GEN M, long nbcol, long nbrow, GEN A, GEN *p_col, GEN *p_row) { long i, j, k, lA = lg(A); GEN prow = cgetg(nbrow+1, t_VECSMALL); GEN pcol = zero_zv(nbcol); pari_sp av = avma; long rcol = nbcol, rrow = 0, imin = nbcol - usqrt(nbcol); GEN iscol = const_vecsmall(nbcol, 1); GEN Wrow = zero_zv(nbrow); GEN wcol = cgetg(nbcol+1, t_VECSMALL); pari_sp av2 = avma; for (i = 1; i <= nbcol; ++i) { GEN F = gmael(M, i, 1); long l = lg(F)-1; for (j = 1; j <= l; ++j) Wrow[F[j]]++; } for (j = 1; j < lA; ++j) { if (Wrow[A[j]] == 0) { *p_col=NULL; return; } Wrow[A[j]] = -1; } for (i = 1; i <= nbrow; ++i) if (Wrow[i]) rrow++; rem_singleton(M, iscol, Wrow, 1, &rcol, &rrow); if (rcol < rrow) pari_err_BUG("RgMs_structelim, rcol rrow) { long w; GEN per = fill_wcol(M, iscol, Wrow, &w, wcol); for (i = nbcol; i>=imin && wcol[per[i]]>=w && rcol>rrow; i--) rem_col(gmael(M, per[i], 1), per[i], iscol, Wrow, &rcol, &rrow); rem_singleton(M, iscol, Wrow, 1, &rcol, &rrow); set_avma(av2); } for (j = 1, i = 1; i <= nbcol; ++i) if (iscol[i]) pcol[j++] = i; setlg(pcol,j); for (k = 1, i = 1; i <= nbrow; ++i) prow[i] = Wrow[i]? k++: 0; *p_col = pcol; *p_row = prow; set_avma(av); } void RgMs_structelim(GEN M, long nbrow, GEN A, GEN *p_col, GEN *p_row) { RgMs_structelim_col(M, lg(M)-1, nbrow, A, p_col, p_row); } GEN F2Ms_colelim(GEN M, long nbrow) { long i,j, nbcol = lg(M)-1, rcol = nbcol, rrow = 0; GEN pcol = zero_zv(nbcol); pari_sp av = avma; GEN iscol = const_vecsmall(nbcol, 1), Wrow = zero_zv(nbrow); for (i = 1; i <= nbcol; ++i) { GEN F = gel(M, i); long l = lg(F)-1; for (j = 1; j <= l; ++j) Wrow[F[j]]++; } rem_singleton(M, iscol, Wrow, 0, &rcol, &rrow); for (j = 1, i = 1; i <= nbcol; ++i) if (iscol[i]) pcol[j++] = i; fixlg(pcol,j); return gc_const(av, pcol); } /*******************************************************************/ /* */ /* EIGENVECTORS */ /* (independent eigenvectors, sorted by increasing eigenvalue) */ /* */ /*******************************************************************/ /* assume x is square of dimension > 0 */ static int RgM_is_symmetric_cx(GEN x, long bit) { pari_sp av = avma; long i, j, l = lg(x); for (i = 1; i < l; i++) for (j = 1; j < i; j++) { GEN a = gcoeff(x,i,j), b = gcoeff(x,j,i), c = gsub(a,b); if (!gequal0(c) && gexpo(c) - gexpo(a) > -bit) return gc_long(av,0); } return gc_long(av,1); } static GEN eigen_err(int exact, GEN x, long flag, long prec) { pari_sp av = avma; GEN y; if (RgM_is_symmetric_cx(x, prec - 10)) { /* approximately symmetric: recover */ x = jacobi(x, prec); if (flag) return x; return gerepilecopy(av, gel(x,2)); } if (!exact) x = bestappr(x, NULL); y = mateigen(x, flag, precdbl(prec)); if (exact) y = gprec_wtrunc(y, prec); else if (flag) y = mkvec2(RgV_gtofp(gel(y,1), prec), RgM_gtofp(gel(y,2), prec)); else y = RgM_gtofp(y, prec); return gerepilecopy(av, y); } GEN mateigen(GEN x, long flag, long prec) { GEN y, R, T; long k, l, ex, n = lg(x); int exact; pari_sp av = avma; if (typ(x)!=t_MAT) pari_err_TYPE("eigen",x); if (n != 1 && n != lgcols(x)) pari_err_DIM("eigen"); if (flag < 0 || flag > 1) pari_err_FLAG("mateigen"); if (n == 1) { if (flag) retmkvec2(cgetg(1,t_COL), cgetg(1,t_MAT)); return cgetg(1,t_MAT); } if (n == 2) { if (flag) retmkvec2(mkcolcopy(gcoeff(x,1,1)), matid(1)); return matid(1); } ex = 16 - prec; T = charpoly(x,0); exact = RgX_is_QX(T); if (exact) { T = ZX_radical( Q_primpart(T) ); R = nfrootsQ(T); settyp(R, t_COL); if (lg(R)-1 < degpol(T)) { /* add missing complex roots */ GEN r = cleanroots(RgX_div(T, roots_to_pol(R, 0)), prec); R = shallowconcat(R, r); } } else { GEN r1, v = vectrunc_init(lg(T)); long e; R = cleanroots(T,prec); r1 = NULL; for (k = 1; k < lg(R); k++) { GEN r2 = gel(R,k), r = grndtoi(r2, &e); if (e < ex) r2 = r; if (r1) { r = gsub(r1,r2); if (gequal0(r) || gexpo(r) < ex) continue; } vectrunc_append(v, r2); r1 = r2; } R = v; } /* R = distinct complex roots of charpoly(x) */ l = lg(R); y = cgetg(l, t_VEC); for (k = 1; k < l; k++) { GEN F = ker_aux(RgM_Rg_sub_shallow(x, gel(R,k)), x); long d = lg(F)-1; if (!d) { set_avma(av); return eigen_err(exact, x, flag, prec); } gel(y,k) = F; if (flag) gel(R,k) = const_col(d, gel(R,k)); } y = shallowconcat1(y); if (lg(y) > n) { set_avma(av); return eigen_err(exact, x, flag, prec); } /* lg(y) < n if x is not diagonalizable */ if (flag) y = mkvec2(shallowconcat1(R), y); return gerepilecopy(av,y); } GEN eigen(GEN x, long prec) { return mateigen(x, 0, prec); } /*******************************************************************/ /* */ /* DETERMINANT */ /* */ /*******************************************************************/ GEN det0(GEN a,long flag) { switch(flag) { case 0: return det(a); case 1: return det2(a); default: pari_err_FLAG("matdet"); } return NULL; /* LCOV_EXCL_LINE */ } /* M a 2x2 matrix, returns det(M) */ static GEN RgM_det2(GEN M) { pari_sp av = avma; GEN a = gcoeff(M,1,1), b = gcoeff(M,1,2); GEN c = gcoeff(M,2,1), d = gcoeff(M,2,2); return gerepileupto(av, gsub(gmul(a,d), gmul(b,c))); } /* M a 2x2 ZM, returns det(M) */ static GEN ZM_det2(GEN M) { pari_sp av = avma; GEN a = gcoeff(M,1,1), b = gcoeff(M,1,2); GEN c = gcoeff(M,2,1), d = gcoeff(M,2,2); return gerepileuptoint(av, subii(mulii(a,d), mulii(b, c))); } /* M a 3x3 ZM, return det(M) */ static GEN ZM_det3(GEN M) { pari_sp av = avma; GEN a = gcoeff(M,1,1), b = gcoeff(M,1,2), c = gcoeff(M,1,3); GEN d = gcoeff(M,2,1), e = gcoeff(M,2,2), f = gcoeff(M,2,3); GEN g = gcoeff(M,3,1), h = gcoeff(M,3,2), i = gcoeff(M,3,3); GEN t, D = signe(i)? mulii(subii(mulii(a,e), mulii(b,d)), i): gen_0; if (signe(g)) { t = mulii(subii(mulii(b,f), mulii(c,e)), g); D = addii(D, t); } if (signe(h)) { t = mulii(subii(mulii(c,d), mulii(a,f)), h); D = addii(D, t); } return gerepileuptoint(av, D); } static GEN det_simple_gauss(GEN a, GEN data, pivot_fun pivot) { pari_sp av = avma; long i,j,k, s = 1, nbco = lg(a)-1; GEN p, x = gen_1; a = RgM_shallowcopy(a); for (i=1; i nbco) return gerepilecopy(av, gcoeff(a,i,i)); if (k != i) { /* exchange the lines s.t. k = i */ for (j=i; j<=nbco; j++) swap(gcoeff(a,i,j), gcoeff(a,k,j)); s = -s; } p = gcoeff(a,i,i); x = gmul(x,p); for (k=i+1; k<=nbco; k++) { GEN m = gcoeff(a,i,k); if (gequal0(m)) continue; m = gdiv(m,p); for (j=i+1; j<=nbco; j++) gcoeff(a,j,k) = gsub(gcoeff(a,j,k), gmul(m,gcoeff(a,j,i))); } if (gc_needed(av,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"det. col = %ld",i); gerepileall(av,2, &a,&x); } } if (s < 0) x = gneg_i(x); return gerepileupto(av, gmul(x, gcoeff(a,nbco,nbco))); } GEN det2(GEN a) { GEN data; pivot_fun pivot; long n = lg(a)-1; if (typ(a)!=t_MAT) pari_err_TYPE("det2",a); if (!n) return gen_1; if (n != nbrows(a)) pari_err_DIM("det2"); if (n == 1) return gcopy(gcoeff(a,1,1)); if (n == 2) return RgM_det2(a); pivot = get_pivot_fun(a, a, &data); return det_simple_gauss(a, data, pivot); } /* 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; 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++) { GEN ck = gel(a,k), m = gel(ck,i); if (gequal0(m)) { if (gequal1(p)) { if (diveuc) gel(a,k) = gdiv(gel(a,k), pprec); } else for (j=i+1; j<=nbco; j++) { GEN p1 = gmul(p, gel(ck,j)); if (diveuc) p1 = gdiv(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 = gdiv(p1,pprec); gel(ck,j) = gerepileupto(av2, p1); } if (gc_needed(av,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"det. col = %ld",i); gerepileall(av,2, &a,&pprec); ci = gel(a,i); p = gcoeff(a,i,i); } } } p = gcoeff(a,nbco,nbco); p = (s < 0)? gneg(p): gcopy(p); return gerepileupto(av, p); } /* count nonzero 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 nonzero entries in row i, at most 'max' of them. * Return their indices */ static GEN row_count_non_zero(GEN a, long i, long max) { GEN v = cgetg(max+1, t_VECSMALL); long j, l = lg(a), k = 1; for (j = 1; j < l; j++) if (!gequal0(gcoeff(a,i,j))) { if (k > max) return NULL; /* fail */ v[k++] = j; } setlg(v, k); return v; } static GEN det_develop(GEN a, long max, double bound); /* (-1)^(i+j) a[i,j] * det RgM_minor(a,i,j) */ static GEN coeff_det(GEN a, long i, long j, long max, double bound) { GEN c = gcoeff(a, i, j); c = gmul(c, det_develop(RgM_minor(a, i,j), max, bound)); if (odd(i+j)) c = gneg(c); return c; } /* a square t_MAT, 'bound' a rough upper bound for the number of * multiplications we are willing to pay while developing rows/columns before * switching to Gaussian elimination */ static GEN det_develop(GEN M, long max, double bound) { pari_sp av = avma; long i,j, n = lg(M)-1, lbest = max+2, best_col = 0, best_row = 0; GEN best = NULL; if (bound < 1.) return det_bareiss(M); /* too costly now */ switch(n) { case 0: return gen_1; case 1: return gcopy(gcoeff(M,1,1)); case 2: return RgM_det2(M); } if (max > ((n+2)>>1)) max = (n+2)>>1; for (j = 1; j <= n; j++) { pari_sp av2 = avma; GEN v = col_count_non_zero(M, j, max); long lv; if (!v || (lv = lg(v)) >= lbest) { set_avma(av2); continue; } if (lv == 1) { set_avma(av); return gen_0; } if (lv == 2) { set_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) { set_avma(av2); continue; } if (lv == 1) { set_avma(av); return gen_0; } if (lv == 2) { set_avma(av); return gerepileupto(av, coeff_det(M,i,v[1],max,bound)); } best = v; lbest = lv; best_row = i; } if (best_row) { double d = lbest-1; GEN s = NULL; long k; bound /= d*d*d; for (k = 1; k < lbest; k++) { GEN c = coeff_det(M, best_row, best[k], max, bound); s = s? gadd(s, c): c; } return gerepileupto(av, s); } if (best_col) { double d = lbest-1; GEN s = NULL; long k; bound /= d*d*d; for (k = 1; k < lbest; k++) { GEN c = coeff_det(M, best[k], best_col, max, bound); s = s? gadd(s, c): c; } return gerepileupto(av, s); } return det_bareiss(M); } /* area of parallelogram bounded by (v1,v2) */ static GEN parallelogramarea(GEN v1, GEN v2) { return gsub(gmul(gnorml2(v1), gnorml2(v2)), gsqr(RgV_dotproduct(v1, v2))); } /* Square of Hadamard bound for det(a), a square matrix. * Slight improvement: instead of using the column norms, use the area of * the parallelogram formed by pairs of consecutive vectors */ GEN RgM_Hadamard(GEN a) { pari_sp av = avma; long n = lg(a)-1, i; GEN B; if (n == 0) return gen_1; if (n == 1) return gsqr(gcoeff(a,1,1)); a = RgM_gtofp(a, LOWDEFAULTPREC); B = gen_1; for (i = 1; i <= n/2; i++) B = gmul(B, parallelogramarea(gel(a,2*i-1), gel(a,2*i))); if (odd(n)) B = gmul(B, gnorml2(gel(a, n))); return gerepileuptoint(av, ceil_safe(B)); } /* If B=NULL, assume B=A' */ static GEN ZM_det_slice(GEN A, GEN P, GEN *mod) { pari_sp av = avma; long i, n = lg(P)-1; GEN H, T; if (n == 1) { ulong Hp, p = uel(P,1); GEN a = ZM_to_Flm(A, p); Hp = Flm_det_sp(a, p); set_avma(av); *mod = utoipos(p); return utoi(Hp); } T = ZV_producttree(P); A = ZM_nv_mod_tree(A, P, T); H = cgetg(n+1, t_VECSMALL); for(i=1; i <= n; i++) { ulong p = P[i]; GEN a = gel(A,i); H[i] = Flm_det_sp(a, p); } H = ZV_chinese_tree(H, P, T, ZV_chinesetree(P,T)); *mod = gmael(T, lg(T)-1, 1); return gc_all(av, 2, &H, mod); } GEN ZM_det_worker(GEN P, GEN A) { GEN V = cgetg(3, t_VEC); gel(V,1) = ZM_det_slice(A, P, &gel(V,2)); return V; } GEN ZM_det(GEN M) { pari_sp av, av2; long n = lg(M)-1; ulong p, Dp; forprime_t S; pari_timer ti; GEN H, mod, h, q, worker; #ifdef LONG_IS_64BIT const ulong PMAX = 18446744073709551557UL; #else const ulong PMAX = 4294967291UL; #endif switch(n) { case 0: return gen_1; case 1: return icopy(gcoeff(M,1,1)); case 2: return ZM_det2(M); case 3: return ZM_det3(M); } if (DEBUGLEVEL>=4) timer_start(&ti); av = avma; h = RgM_Hadamard(M); /* |D| <= sqrt(h) */ if (!signe(h)) { set_avma(av); return gen_0; } h = sqrti(h); if (lgefint(h) == 3 && (ulong)h[2] <= (PMAX >> 1)) { /* h < p/2 => direct result */ p = PMAX; Dp = Flm_det_sp(ZM_to_Flm(M, p), p); set_avma(av); if (!Dp) return gen_0; return (Dp <= (p>>1))? utoipos(Dp): utoineg(p - Dp); } q = gen_1; Dp = 1; init_modular_big(&S); p = 0; /* -Wall */ while (cmpii(q, h) <= 0 && (p = u_forprime_next(&S))) { av2 = avma; Dp = Flm_det_sp(ZM_to_Flm(M, p), p); set_avma(av2); if (Dp) break; q = muliu(q, p); } if (!p) pari_err_OVERFLOW("ZM_det [ran out of primes]"); if (!Dp) { set_avma(av); return gen_0; } worker = snm_closure(is_entry("_ZM_det_worker"), mkvec(M)); H = gen_crt("ZM_det", worker, &S, NULL, expi(h)+1, 0, &mod, ZV_chinese, NULL); /* H = det(M) modulo mod, (mod,D) = 1; |det(M) / D| <= h */ H = Fp_center(H, mod, shifti(mod,-1)); return gerepileuptoint(av, H); } static GEN RgM_det_FpM(GEN a, GEN p) { pari_sp av = avma; ulong pp, d; a = RgM_Fp_init(a,p,&pp); switch(pp) { case 0: return gerepileupto(av, Fp_to_mod(FpM_det(a,p),p)); break; case 2: d = F2m_det_sp(a); break; default:d = Flm_det_sp(a, pp); break; } set_avma(av); return mkintmodu(d, pp); } static GEN RgM_det_FqM(GEN x, GEN pol, GEN p) { pari_sp av = avma; GEN b, T = RgX_to_FpX(pol, p); if (signe(T) == 0) pari_err_OP("%",x,pol); b = FqM_det(RgM_to_FqM(x, T, p), T, p); if (!b) return gc_NULL(av); return gerepilecopy(av, mkpolmod(FpX_to_mod(b, p), FpX_to_mod(T, p))); } #define code(t1,t2) ((t1 << 6) | t2) static GEN RgM_det_fast(GEN x) { GEN p, pol; long pa; long t = RgM_type(x, &p,&pol,&pa); switch(t) { case t_INT: return ZM_det(x); case t_FRAC: return QM_det(x); case t_FFELT: return FFM_det(x, pol); case t_INTMOD: return RgM_det_FpM(x, p); case code(t_POLMOD, t_INTMOD): return RgM_det_FqM(x, pol, p); default: return NULL; } } #undef code static long det_init_max(long n) { if (n > 100) return 0; if (n > 50) return 1; if (n > 30) return 4; return 7; } GEN det(GEN a) { long n = lg(a)-1; double B; GEN data, b; pivot_fun pivot; if (typ(a)!=t_MAT) pari_err_TYPE("det",a); if (!n) return gen_1; if (n != nbrows(a)) pari_err_DIM("det"); if (n == 1) return gcopy(gcoeff(a,1,1)); if (n == 2) return RgM_det2(a); b = RgM_det_fast(a); if (b) return b; pivot = get_pivot_fun(a, a, &data); if (pivot != gauss_get_pivot_NZ) return det_simple_gauss(a, data, pivot); B = (double)n; return det_develop(a, det_init_max(n), B*B*B); } GEN QM_det(GEN M) { pari_sp av = avma; GEN cM, pM = Q_primitive_part(M, &cM); GEN b = ZM_det(pM); if (cM) b = gmul(b, gpowgs(cM, lg(M)-1)); return gerepileupto(av, b); } pari-2.17.2/src/basemath/lfunutils.c0000644000175000017500000025713314760123736015754 0ustar billbill/* Copyright (C) 2015 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /********************************************************************/ /** **/ /** L-functions: Applications **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_lfun static GEN tag(GEN x, long t) { return mkvec2(mkvecsmall(t), x); } /* v a t_VEC of length > 1 */ static int is_tagged(GEN v) { GEN T = gel(v,1); return (typ(T)==t_VEC && lg(T)==3 && typ(gel(T,1))==t_VECSMALL); } /* rough check */ static long is_ldata(GEN L) { long l = lg(L); return typ(L) == t_VEC && (l == 7 || l == 8); } /* thorough check */ static void checkldata(GEN ldata) { GEN vga, w, N; #if 0 /* assumed already checked and true */ if (!is_ldata(ldata) || !is_tagged(ldata)) pari_err_TYPE("checkldata", ldata); #endif vga = ldata_get_gammavec(ldata); if (typ(vga) != t_VEC) pari_err_TYPE("checkldata [gammavec]",vga); w = gel(ldata, 4); /* FIXME */ switch(typ(w)) { case t_INT: case t_FRAC: break; case t_VEC: if (lg(w) == 3 && is_rational_t(typ(gel(w,1)))) break; default: pari_err_TYPE("checkldata [weight]",w); } N = ldata_get_conductor(ldata); if (typ(N) != t_INT) pari_err_TYPE("checkldata [conductor]",N); } /* tag as t_LFUN_GENERIC */ static void lfuncreate_tag(GEN L) { if (is_tagged(L)) return; gel(L,1) = tag(gel(L,1), t_LFUN_GENERIC); if (typ(gel(L,2)) != t_INT) gel(L,2) = tag(gel(L,2), t_LFUN_GENERIC); } /* shallow */ static GEN closure2ldata(GEN C, long prec) { GEN L = closure_callgen0prec(C, prec); if (is_ldata(L)) { checkldata(L); lfuncreate_tag(L); } else L = lfunmisc_to_ldata_shallow(L); return L; } /* data may be either an object (polynomial, elliptic curve, etc...) * or a description vector [an,sd,Vga,k,conductor,rootno,{poles}]. */ GEN lfuncreate(GEN data) { if (is_ldata(data)) { GEN L = gcopy(data); lfuncreate_tag(L); checkldata(L); return L; } if (typ(data) == t_CLOSURE && closure_arity(data)==0) { pari_sp av = avma; GEN L = closure2ldata(data, DEFAULTPREC); gel(L,1) = tag(data, t_LFUN_CLOSURE0); return gerepilecopy(av, L); } return lfunmisc_to_ldata(data); } GEN lfunparams(GEN L, long prec) { pari_sp av = avma; GEN k, N, v; long p; if (!is_ldata(L) || !is_tagged(L)) L = lfunmisc_to_ldata_shallow(L); N = ldata_get_conductor(L); k = ldata_get_k(L); v = ldata_get_gammavec(L); p = gprecision(v); if (p > prec) v = gprec_wtrunc(v, prec); else if (p < prec) { GEN van = ldata_get_an(L), an = gel(van,2); long t = mael(van,1,1); if (t == t_LFUN_CLOSURE0) L = closure2ldata(an, prec); } return gerepilecopy(av, mkvec3(N, k, v)); } /********************************************************************/ /** Simple constructors **/ /********************************************************************/ static GEN ldata_eulerf(GEN van, GEN p, long prec); static GEN vecan_conj(GEN an, long n, long prec) { GEN p1 = ldata_vecan(gel(an,1), n, prec); return typ(p1) == t_VEC? conj_i(p1): p1; } static GEN eulerf_conj(GEN an, GEN p, long prec) { GEN p1 = ldata_eulerf(gel(an,1), p, prec); return conj_i(p1); } static GEN vecan_mul(GEN an, long n, long prec) { GEN p1 = ldata_vecan(gel(an,1), n, prec); GEN p2 = ldata_vecan(gel(an,2), n, prec); if (typ(p1) == t_VECSMALL) p1 = vecsmall_to_vec(p1); if (typ(p2) == t_VECSMALL) p2 = vecsmall_to_vec(p2); return dirmul(p1, p2); } static GEN eulerf_mul(GEN an, GEN p, long prec) { GEN p1 = ldata_eulerf(gel(an,1), p, prec); GEN p2 = ldata_eulerf(gel(an,2), p, prec); return gmul(p1, p2); } static GEN lfunconvol(GEN a1, GEN a2) { return tag(mkvec2(a1, a2), t_LFUN_MUL); } static GEN vecan_div(GEN an, long n, long prec) { GEN p1 = ldata_vecan(gel(an,1), n, prec); GEN p2 = ldata_vecan(gel(an,2), n, prec); if (typ(p1) == t_VECSMALL) p1 = vecsmall_to_vec(p1); if (typ(p2) == t_VECSMALL) p2 = vecsmall_to_vec(p2); return dirdiv(p1, p2); } static GEN eulerf_div(GEN an, GEN p, long prec) { GEN p1 = ldata_eulerf(gel(an,1), p, prec); GEN p2 = ldata_eulerf(gel(an,2), p, prec); return gdiv(p1, p2); } static GEN lfunconvolinv(GEN a1, GEN a2) { return tag(mkvec2(a1,a2), t_LFUN_DIV); } static GEN lfunconj(GEN a1) { return tag(mkvec(a1), t_LFUN_CONJ); } static GEN lfuncombdual(GEN (*fun)(GEN, GEN), GEN ldata1, GEN ldata2) { GEN a1 = ldata_get_an(ldata1), a2 = ldata_get_an(ldata2); GEN b1 = ldata_get_dual(ldata1), b2 = ldata_get_dual(ldata2); if (typ(b1)==t_INT && typ(b2)==t_INT) return utoi(signe(b1) || signe(b2)); else { if (typ(b1)==t_INT) b1 = signe(b1) ? lfunconj(a1): a1; if (typ(b2)==t_INT) b2 = signe(b2) ? lfunconj(a2): a2; return fun(b1, b2); } } static GEN vecan_twist(GEN an, long n, long prec) { GEN p1 = ldata_vecan(gel(an,1), n, prec); GEN p2 = ldata_vecan(gel(an,2), n, prec); long i; GEN V; if (typ(p1) == t_VECSMALL) p1 = vecsmall_to_vec(p1); if (typ(p2) == t_VECSMALL) p2 = vecsmall_to_vec(p2); V = cgetg(n+1, t_VEC); for(i = 1; i <= n ; i++) gel(V, i) = gmul(gel(p1, i), gel(p2, i)); return V; } static GEN eulerf_twist(GEN an, GEN p, long prec) { GEN p1 = ldata_eulerf(gel(an,1), p, prec); GEN p2 = ginv(ldata_eulerf(gel(an,2), p, prec)); if (typ(p2)!=t_POL || degpol(p2)==0) return poleval(p1,pol_0(0)); if (degpol(p2)!=1) pari_err_IMPL("lfuneuler"); return poleval(p1,monomial(gneg(gel(p2,3)),1,0)); } static GEN vecan_shift(GEN an, long n, long prec) { GEN p1 = ldata_vecan(gel(an,1), n, prec); GEN s = gel(an,2); long i; GEN V; if (typ(p1) == t_VECSMALL) p1 = vecsmall_to_vec(p1); V = cgetg(n+1, t_VEC); if (typ(s)==t_INT) { if (equali1(s)) for(i = 1; i <= n ; i++) { GEN gi = gel(p1, i); gel(V, i) = gequal0(gi)? gi: gmulgu(gi, i); } else for(i = 1; i <= n ; i++) { GEN gi = gel(p1, i); gel(V, i) = gequal0(gi)? gi: gmul(gi, powgi(utoi(i), s)); } } else { GEN D = dirpowers(n, s, prec); for(i = 1; i <= n ; i++) gel(V, i) = gmul(gel(p1,i), gel(D,i)); } return V; } static GEN eulerf_shift(GEN an, GEN p, long prec) { GEN p1 = ldata_eulerf(gel(an,1), p, prec); GEN s = gel(an,2); return gsubst(p1, 0, monomial(gpow(p, s, prec), 1, 0)); } static GEN eulerf_hgm(GEN an, GEN p) { GEN H = gel(an,1), t = gel(an,2); if (typ(t)==t_VEC && lg(t)==3) { GEN L = gel(t,2); long i, l = lg(L); t = gel(t,1); for (i = 1; i < l; i++) /* wild primes */ if (equalii(p, gmael(L, i, 1))) break; if (i=1; i--) { GEN al = gel(gam, i); if (al) { GEN N = gadd(w,gmul2n(real_i(al),1)); if (gcmpgs(N,2) > 0) { GEN bl = gsubgs(al, 1); for (j=1; j < i; j++) if (gel(gam,j) && gequal(gel(gam,j), bl)) { gel(gam,j) = NULL; break; } if (j==i) return NULL; gel(g, k++) = al; gel(g, k++) = bl; } else if (gequal0(N)) gel(g, k++) = gaddgs(al, 1); else if (gequal1(N)) gel(g, k++) = gsubgs(al, 1); else return NULL; } } return sort(g); } GEN lfuntwist(GEN ldata1, GEN chi, long bitprec) { pari_sp ltop = avma; GEN k, L, N, N1, N2, a, a1, a2, b, b1, b2, gam, gam1, gam2; GEN ldata2; long d1, t; long prec = nbits2prec(bitprec); ldata1 = ldata_newprec(lfunmisc_to_ldata_shallow(ldata1), prec); ldata2 = lfunmisc_to_ldata_shallow(chi); t = ldata_get_type(ldata2); a1 = ldata_get_an(ldata1); a2 = ldata_get_an(ldata2); if (t == t_LFUN_ZETA) return gerepilecopy(ltop, ldata1); if (t != t_LFUN_CHIZ && t != t_LFUN_KRONECKER && ( t != t_LFUN_CHIGEN || nf_get_degree(bnr_get_nf(gmael(a2,2,1))) != 1)) pari_err_TYPE("lfuntwist", chi); N1 = ldata_get_conductor(ldata1); N2 = ldata_get_conductor(ldata2); if (!gequal1(gcdii(N1, N2))) pari_err_IMPL("lfuntwist (conductors not coprime)"); k = ldata_get_k(ldata1); d1 = ldata_get_degree(ldata1); N = gmul(N1, gpowgs(N2, d1)); gam1 = ldata_get_gammavec(ldata1); gam2 = ldata_get_gammavec(ldata2); if (gequal0(gel(gam2, 1))) gam = gam1; else gam = gamma_imagchi(ldata_get_gammavec(ldata1), gaddgs(k,-1)); if (!gam) pari_err_IMPL("lfuntwist (gammafactors)"); b1 = ldata_get_dual(ldata1); b2 = ldata_get_dual(ldata2); a = tag(mkvec2(a1, a2), t_LFUN_TWIST); if (typ(b1)==t_INT) b = signe(b1) && signe(b2) ? gen_0: gen_1; else b = tag(mkvec2(b1,lfunconj(a2)), t_LFUN_TWIST); L = mkvecn(6, a, b, gam, k, N, gen_0); return gerepilecopy(ltop, L); } static GEN lfundualpoles(GEN ldata, GEN reno) { long l, j; GEN k = ldata_get_k(ldata); GEN r = gel(reno,2), eno = gel(reno,3), R; R = cgetg_copy(r, &l); for (j = 1; j < l; j++) { GEN b = gmael(r,j,1), e = gmael(r,j,2); long v = varn(e); GEN E = gsubst(gdiv(e, eno), v, gneg(pol_x(v))); gel(R,l-j) = mkvec2(gsub(k,b), E); } return R; } static GEN ginvvec(GEN x) { if (is_vec_t(typ(x))) pari_APPLY_same(ginv(gel(x,i))) else return ginv(x); } GEN lfundual(GEN L, long bitprec) { pari_sp av = avma; long prec = nbits2prec(bitprec); GEN ldata = ldata_newprec(lfunmisc_to_ldata_shallow(L), prec); GEN a = ldata_get_an(ldata), b = ldata_get_dual(ldata); GEN e = ldata_get_rootno(ldata); GEN ldual, ad, bd, ed, Rd = NULL; if (typ(b) == t_INT) { ad = equali1(b) ? lfunconj(a): a; bd = b; } else { ad = b; bd = a; } if (lg(ldata)==8) { GEN reno = lfunrootres(ldata, bitprec); e = gel(reno,3); Rd = lfundualpoles(ldata, reno); } ed = isintzero(e) ? e: ginvvec(e); ldual = mkvecn(Rd ? 7:6, ad, bd, gel(ldata,3), gel(ldata,4), gel(ldata,5), ed, Rd); return gerepilecopy(av, ldual); } static GEN RgV_Rg_translate(GEN x, GEN s) { pari_APPLY_same(gadd(gel(x,i),s)) } static GEN pole_translate(GEN x, GEN s, GEN Ns) { x = shallowcopy(x); gel(x,1) = gadd(gel(x,1), s); if (Ns) gel(x,2) = gmul(gel(x,2), Ns); return x; } static GEN poles_translate(GEN x, GEN s, GEN Ns) { pari_APPLY_same(pole_translate(gel(x,i), s, Ns)) } /* r / x + O(1) */ static GEN simple_pole(GEN r) { GEN S; if (isintzero(r)) return gen_0; S = deg1ser_shallow(gen_0, r, 1); setvalser(S, -1); return S; } GEN lfunshift(GEN ldata, GEN s, long flag, long bitprec) { pari_sp ltop = avma; GEN k, k1, L, N, a, b, gam, eps, res; long prec = nbits2prec(bitprec); if (!is_rational_t(typ(s))) pari_err_TYPE("lfunshift",s); ldata = ldata_newprec(lfunmisc_to_ldata_shallow(ldata), prec); a = ldata_get_an(ldata); b = ldata_get_dual(ldata); gam = RgV_Rg_translate(ldata_get_gammavec(ldata), gneg(s)); k = gadd(ldata_get_k(ldata), gmul2n(s, 1)); k1 = gadd(ldata_get_k1(ldata), s); N = ldata_get_conductor(ldata); eps = ldata_get_rootno(ldata); res = ldata_get_residue(ldata); a = tag(mkvec2(a, s), t_LFUN_SHIFT); if (typ(b) != t_INT) b = tag(mkvec2(b, s), t_LFUN_SHIFT); if (res) switch(typ(res)) { case t_VEC: res = poles_translate(res, s, NULL); break; case t_COL: res = poles_translate(res, s, gpow(N, gmul2n(s, -1), prec)); break; default: res = mkvec(mkvec2(gsub(k, s), simple_pole(res))); } L = mkvecn(res ? 7: 6, a, b, gam, mkvec2(k, k1), N, eps, res); if (flag) L = lfunmul_k(ldata, L, gsub(k, s), bitprec); return gerepilecopy(ltop, L); } /*****************************************************************/ /* L-series from closure */ /*****************************************************************/ static GEN localfactor(void *E, GEN p, long n) { GEN s = closure_callgen2((GEN)E, p, utoi(n)); return direuler_factor(s, n); } static GEN vecan_closure(GEN a, long L, long prec) { long ta = typ(a); GEN gL, Sbad = NULL; if (!L) return cgetg(1,t_VEC); if (ta == t_VEC) { long l = lg(a); if (l == 1) pari_err_TYPE("vecan_closure", a); ta = typ(gel(a,1)); /* regular vector, return it */ if (ta != t_CLOSURE) return vecslice(a, 1, minss(L,l-1)); if (l != 3) pari_err_TYPE("vecan_closure", a); Sbad = gel(a,2); if (typ(Sbad) != t_VEC) pari_err_TYPE("vecan_closure", a); a = gel(a,1); } else if (ta != t_CLOSURE) pari_err_TYPE("vecan_closure", a); push_localprec(prec); gL = stoi(L); switch(closure_arity(a)) { case 2: a = direuler_bad((void*)a, localfactor, gen_2, gL,gL, Sbad); break; case 1: a = closure_callgen1(a, gL); if (typ(a) != t_VEC) pari_err_TYPE("vecan_closure", a); break; default: pari_err_TYPE("vecan_closure [wrong arity]", a); a = NULL; /*LCOV_EXCL_LINE*/ } pop_localprec(); return a; } static GEN eulerf_closure(GEN a, GEN p, long prec) { long ta = typ(a); GEN Sbad = NULL, f; if (ta == t_VEC) { long l = lg(a); if (l == 1) pari_err_TYPE("vecan_closure", a); ta = typ(gel(a,1)); /* regular vector, return it */ if (ta != t_CLOSURE) return NULL; if (l != 3) pari_err_TYPE("vecan_closure", a); Sbad = gel(a,2); if (typ(Sbad) != t_VEC) pari_err_TYPE("vecan_closure", a); a = gel(a,1); } else if (ta != t_CLOSURE) pari_err_TYPE("vecan_closure", a); push_localprec(prec); switch(closure_arity(a)) { case 2: f = closure_callgen2(a, p, mkoo()); break; case 1: f = NULL; break; default: f = NULL; pari_err_TYPE("vecan_closure", a); } pop_localprec(); return f; } /*****************************************************************/ /* L-series of Dirichlet characters. */ /*****************************************************************/ static GEN lfunzeta(void) { GEN zet = mkvecn(7, NULL, gen_0, NULL, gen_1, gen_1, gen_1, gen_1); gel(zet,1) = tag(gen_1, t_LFUN_ZETA); gel(zet,3) = mkvec(gen_0); return zet; } static GEN vecan_Kronecker(GEN D, long n) { GEN v = cgetg(n+1, t_VECSMALL); ulong Du = itou_or_0(D); long i, id, d = Du ? minuu(Du, n): n; for (i = 1; i <= d; i++) v[i] = krois(D,i); for (id = i; i <= n; i++,id++) /* periodic mod d */ { if (id > d) id = 1; gel(v, i) = gel(v, id); } return v; } static GEN lfunchiquad(GEN D) { GEN r; D = coredisc(D); if (equali1(D)) return lfunzeta(); if (!isfundamental(D)) pari_err_TYPE("lfunchiquad [not primitive]", D); r = mkvecn(6, NULL, gen_0, NULL, gen_1, NULL, gen_1); gel(r,1) = tag(icopy(D), t_LFUN_KRONECKER); gel(r,3) = mkvec(signe(D) < 0? gen_1: gen_0); gel(r,5) = mpabs(D); return r; } /* Begin Hecke characters. Here a character is assumed to be given by a vector on the generators of the ray class group clgp of CL_m(K). If clgp = [h,[d1,...,dk],[g1,...,gk]] with dk|...|d2|d1, a character chi is given by [a1,a2,...,ak] such that chi(gi)=\zeta_di^ai. */ /* Value of CHI on x, coprime to bnr.mod */ static GEN chigeneval_i(GEN logx, GEN d, GEN nchi, GEN z, long prec) { pari_sp av = avma; GEN e = FpV_dotproduct(nchi, logx, d); if (!is_vec_t(typ(z))) return gerepileupto(av, gpow(z, e, prec)); else { ulong i = itou(e); set_avma(av); return gel(z, i+1); } } static GEN chigenevalvec(GEN logx, GEN nchi, GEN z, long prec, long multi) { GEN d = gel(nchi,1), x = gel(nchi, 2); if (multi) pari_APPLY_same(chigeneval_i(logx, d, gel(x,i), z, prec)) else return chigeneval_i(logx, d, x, z, prec); } /* return x + yz; y != 0; z = 0,1 "often"; x = 0 "often" */ static GEN gaddmul(GEN x, GEN y, GEN z) { pari_sp av; if (typ(z) == t_INT) { if (!signe(z)) return x; if (equali1(z)) return gadd(x,y); } if (isintzero(x)) return gmul(y,z); av = avma; return gerepileupto(av, gadd(x, gmul(y,z))); } static GEN gaddmulvec(GEN x, GEN y, GEN z, long multi) { if (multi) pari_APPLY_same(gaddmul(gel(x,i),gel(y,i),gel(z,i))) else return gaddmul(x,y,z); } static GEN mkvchi(GEN chi, long n) { GEN v; if (lg(chi) > 1 && is_vec_t(typ(gel(chi,1)))) { long d = lg(chi)-1; v = const_vec(n, zerovec(d)); gel(v,1) = const_vec(d, gen_1); } else v = vec_ei(n, 1); return v; } static GEN vecan_chiZ(GEN an, long n, long prec) { forprime_t iter; GEN G = gel(an,1); GEN nchi = gel(an,2), gord = gel(nchi,1), chi = gel(nchi,2), z; GEN gp = cgetipos(3), v = mkvchi(chi, n); GEN N = znstar_get_N(G); long ord = itos_or_0(gord); ulong Nu = itou_or_0(N); long i, id, d = Nu ? minuu(Nu, n): n; long multichi= (lg(chi) > 1 && is_vec_t(typ(gel(chi,1)))); ulong p; if (!multichi && ord && n > (ord>>4)) { GEN w = ncharvecexpo(G, nchi); z = grootsof1(ord, prec); for (i = 1; i <= d; i++) if (w[i] >= 0) gel(v, i) = gel(z, w[i]+1); } else { z = rootsof1_cx(gord, prec); u_forprime_init(&iter, 2, d); while ((p = u_forprime_next(&iter))) { GEN ch; ulong k; if (!umodiu(N,p)) continue; gp[2] = p; ch = chigenevalvec(znconreylog(G, gp), nchi, z, prec, multichi); gel(v, p) = ch; for (k = 2*p; k <= (ulong)d; k += p) gel(v, k) = gaddmulvec(gel(v, k), ch, gel(v, k/p), multichi); } } for (id = i = d+1; i <= n; i++,id++) /* periodic mod d */ { if (id > d) id = 1; gel(v, i) = gel(v, id); } return v; } static GEN eulerf_chiZ(GEN an, GEN p, long prec) { GEN G = gel(an,1); GEN nchi = gel(an,2), gord = gel(nchi,1), chi = gel(nchi,2); long multichi= (lg(chi) > 1 && is_vec_t(typ(gel(chi,1)))); GEN z = rootsof1_cx(gord, prec); GEN N = znstar_get_N(G); GEN ch = dvdii(N,p) ? gen_0: chigenevalvec(znconreylog(G, p), nchi, z, prec, multichi); return mkrfrac(gen_1, deg1pol_shallow(gneg(ch), gen_1,0)); } static GEN vecan_chigen(GEN an, long n, long prec) { forprime_t iter; GEN bnr = gel(an,1), nf = bnr_get_nf(bnr); GEN nchi = gel(an,2), gord = gel(nchi,1), chi = gel(nchi,2), z; GEN gp = cgetipos(3), v = mkvchi(chi, n); GEN N = gel(bnr_get_mod(bnr), 1), NZ = gcoeff(N,1,1); long ord = itos_or_0(gord); long multichi= (lg(chi) > 1 && is_vec_t(typ(gel(chi,1)))); ulong p; if (ord && n > (ord>>4)) z = grootsof1(ord, prec); else z = rootsof1_cx(gord, prec); if (nf_get_degree(nf) == 1) { ulong Nu = itou_or_0(NZ); long i, id, d = Nu ? minuu(Nu, n): n; u_forprime_init(&iter, 2, d); while ((p = u_forprime_next(&iter))) { GEN ch; ulong k; if (!umodiu(NZ,p)) continue; gp[2] = p; ch = chigenevalvec(isprincipalray(bnr,gp), nchi, z, prec, multichi); gel(v, p) = ch; for (k = 2*p; k <= (ulong)d; k += p) gel(v, k) = gaddmulvec(gel(v, k), ch, gel(v, k/p), multichi); } for (id = i = d+1; i <= n; i++,id++) /* periodic mod d */ { if (id > d) id = 1; gel(v, i) = gel(v, id); } } else { GEN BOUND = stoi(n); u_forprime_init(&iter, 2, n); while ((p = u_forprime_next(&iter))) { GEN L; long j; int check = !umodiu(NZ,p); gp[2] = p; L = idealprimedec_limit_norm(nf, gp, BOUND); for (j = 1; j < lg(L); j++) { GEN pr = gel(L, j), ch; ulong k, q; if (check && idealval(nf, N, pr)) continue; ch = chigenevalvec(isprincipalray(bnr,pr), nchi, z, prec, multichi); q = upr_norm(pr); gel(v, q) = gadd(gel(v, q), ch); for (k = 2*q; k <= (ulong)n; k += q) gel(v, k) = gaddmulvec(gel(v, k), ch, gel(v, k/q), multichi); } } } return v; } static GEN eulerf_chigen(GEN an, GEN p, long prec) { GEN bnr = gel(an,1), nf = bnr_get_nf(bnr); GEN nchi = gel(an,2), gord = gel(nchi,1), chi = gel(nchi,2), z; GEN N = gel(bnr_get_mod(bnr), 1), NZ = gcoeff(N,1,1), f; long multichi= (lg(chi) > 1 && is_vec_t(typ(gel(chi,1)))); z = rootsof1_cx(gord, prec); if (nf_get_degree(nf) == 1) { GEN ch; if (dvdii(NZ,p)) ch = gen_0; else { ch = chigenevalvec(isprincipalray(bnr,p), nchi, z, prec, multichi); if (typ(ch)==t_VEC) return NULL; } f = deg1pol_shallow(gneg(ch), gen_1, 0); } else { int check = dvdii(NZ,p); GEN L = idealprimedec(nf, p); long j, lL = lg(L); f = pol_1(0); for (j = 1; j < lL; j++) { GEN pr = gel(L, j), ch; if (check && idealval(nf, N, pr)) ch = gen_0; else ch = chigenevalvec(isprincipalray(bnr,pr), nchi, z, prec, multichi); if (typ(ch)==t_VEC) return NULL; f = gmul(f, gsub(gen_1, monomial(ch, pr_get_f(pr), 0))); } } return mkrfrac(gen_1,f); } static GEN vec01(long r1, long r2) { long d = r1+r2, i; GEN v = cgetg(d+1,t_VEC); for (i = 1; i <= r1; i++) gel(v,i) = gen_0; for ( ; i <= d; i++) gel(v,i) = gen_1; return v; } /* true nf or t_POL */ static GEN lfunzetak_i(GEN T) { GEN Vga, N; long r1, r2; if (typ(T) == t_POL) { T = nfinit0(T, nf_NOLLL, DEFAULTPREC); if (lg(T) == 3) T = gel(T,1); /* [nf,change of var] */ } if (nf_get_degree(T) == 1) return lfunzeta(); nf_get_sign(T,&r1,&r2); Vga = vec01(r1+r2,r2); N = absi_shallow(nf_get_disc(T)); return mkvecn(7, tag(T,t_LFUN_NF), gen_0, Vga, gen_1, N, gen_1, gen_0); } /* truen nf or t_POL */ static GEN lfunzetak(GEN T) { pari_sp av = avma; return gerepilecopy(av, lfunzetak_i(T)); } /* v = vector of normalized characters of order dividing o; renormalize * so that all have same apparent order o */ static GEN char_renormalize(GEN v, GEN o) { long i, l; GEN w = cgetg_copy(v, &l); for (i = 1; i < l; i++) { GEN C = gel(v,i), oc = gel(C,1), c = gel(C,2); if (!equalii(o, oc)) c = gmul(c, diviiexact(o, oc)); gel(w,i) = c; } return w; } /* G is a bid of nftyp typ_BIDZ */ static GEN lfunchiZ(GEN G, GEN CHI) { pari_sp av = avma; GEN sig = NULL, N = bid_get_ideal(G), nchi, r; int real; long s; if (typ(N) != t_INT) pari_err_TYPE("lfunchiZ", G); if (typ(CHI) == t_VEC && !RgV_is_ZV(CHI)) { GEN C, G0 = G, o = gen_1; long i, l = lg(CHI); nchi = cgetg(l, t_VEC); N = znconreyconductor(G, gel(CHI,1), &C); if (typ(N) != t_INT) G = znstar0(N, 1); s = zncharisodd(G, C); for (i = 1; i < l; i++) { if (i > 1) { if (!gequal(N, znconreyconductor(G0, gel(CHI,i), &C)) || zncharisodd(G, C) != s) pari_err_TYPE("lfuncreate [different conductors]", CHI); } C = znconreylog_normalize(G, C); o = lcmii(o, gel(C,1)); /* lcm with charorder */ gel(nchi,i) = C; } nchi = mkvec2(o, char_renormalize(nchi, o)); if (typ(N) != t_INT) N = gel(N,1); } else { N = znconreyconductor(G, CHI, &CHI); if (typ(N) != t_INT) { if (equali1(gel(N,1))) { set_avma(av); return lfunzeta(); } G = znstar0(N, 1); N = gel(N,1); } /* CHI now primitive on G */ switch(itou_or_0(zncharorder(G, CHI))) { case 1: set_avma(av); return lfunzeta(); case 2: if (zncharisodd(G,CHI)) N = negi(N); return gerepileupto(av, lfunchiquad(N)); } nchi = znconreylog_normalize(G, CHI); s = zncharisodd(G, CHI); } sig = mkvec(s? gen_1: gen_0); real = abscmpiu(gel(nchi,1), 2) <= 0; r = mkvecn(6, tag(mkvec2(G,nchi), t_LFUN_CHIZ), real? gen_0: gen_1, sig, gen_1, N, gen_0); return gerepilecopy(av, r); } static GEN lfunchigen(GEN bnr, GEN CHI) { pari_sp av = avma; GEN N, sig, Ldchi, nf, nchi, NN; long r1, r2, n1; int real; if (typ(CHI) == t_VEC && !RgV_is_ZV(CHI)) { long map, i, l = lg(CHI); GEN bnr0 = bnr, D, chi = gel(CHI,1), o = gen_1; nchi = cgetg(l, t_VEC); bnr_char_sanitize(&bnr, &chi); D = cyc_normalize(bnr_get_cyc(bnr)); N = bnr_get_mod(bnr); map = (bnr != bnr0); for (i = 1; i < l; i++) { if (i > 1) { chi = gel(CHI,i); if (!map) { if (!bnrisconductor(bnr, chi)) pari_err_TYPE("lfuncreate [different conductors]", CHI); } else { if (!gequal(bnrconductor_raw(bnr0, chi), N)) pari_err_TYPE("lfuncreate [different conductors]", CHI); chi = bnrchar_primitive_raw(bnr0, bnr, chi); } } chi = char_normalize(chi, D); o = lcmii(o, gel(chi,1)); /* lcm with charorder */ gel(nchi,i) = chi; } nchi = mkvec2(o, char_renormalize(nchi, o)); } else { bnr_char_sanitize(&bnr, &CHI); nchi = NULL; /* now CHI is primitive wrt bnr */ } N = bnr_get_mod(bnr); nf = bnr_get_nf(bnr); n1 = lg(vec01_to_indices(gel(N,2))) - 1; /* vecsum(N[2]) */ N = gel(N,1); NN = mulii(idealnorm(nf, N), absi_shallow(nf_get_disc(nf))); if (!nchi) { if (equali1(NN)) { set_avma(av); return lfunzeta(); } if (ZV_equal0(CHI)) return gerepilecopy(av, lfunzetak_i(bnr_get_nf(bnr))); nchi = char_normalize(CHI, cyc_normalize(bnr_get_cyc(bnr))); } real = abscmpiu(gel(nchi,1), 2) <= 0; nf_get_sign(nf, &r1, &r2); sig = vec01(r1+r2-n1, r2+n1); Ldchi = mkvecn(6, tag(mkvec2(bnr, nchi), t_LFUN_CHIGEN), real? gen_0: gen_1, sig, gen_1, NN, gen_0); return gerepilecopy(av, Ldchi); } /* Find all characters of clgp whose kernel contain group given by HNF H. * Set *pcnj[i] to the conductor */ static GEN chigenkerfind(GEN bnr, GEN H, GEN *pcnj) { GEN res, cnj, L = bnrchar(bnr, H, NULL); long i, k, l = lg(L); res = cgetg(l, t_VEC); *pcnj = cnj = cgetg(l, t_VEC); for (i = k = 1; i < l; i++) { GEN chi = gel(L,i); gel(res, k) = chi; gel(cnj, k) = ZV_equal0(chi)? gen_0: bnrconductor_raw(bnr, chi); k++; } setlg(cnj, k); setlg(res, k); return res; } static GEN vec_classes(GEN A, GEN F) { GEN w = vec_equiv(F); long i, l = lg(w); GEN V = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(V,i) = vecpermute(A,gel(w,i)); return V; } static GEN abelrel_pfactor(GEN bnr, GEN pr, GEN U, GEN D, GEN h) { GEN v = bnrisprincipalmod(bnr, pr, h, 0); GEN E = ZV_ZV_mod(ZM_ZC_mul(U, v), D); ulong o = itou(charorder(D, E)), f = pr_get_f(pr); return gpowgs(gsub(gen_1, monomial(gen_1, f * o, 0)), itou(h) / o); } static GEN abelrel_factor(GEN bnr, GEN C, GEN p, GEN mod, GEN U, GEN D, GEN h) { GEN nf = bnr_get_nf(bnr), F = pol_1(0), prid = idealprimedec(nf,p); GEN mod2 = shallowcopy(mod); long i, l = lg(prid); for (i = 1; i < l; i++) { GEN pr = gel(prid, i), Fpr; long v = idealval(nf,mod,pr); if (v > 0) { GEN bnr2, C2, U2, D2, h2; gel(mod2, 1) = idealdivpowprime(nf, gel(mod, 1), pr, utoi(v)); bnr2 = bnrinitmod(bnr, mod2, 0, h); C2 = bnrmap(bnrmap(bnr, bnr2), C); D2 = ZM_snfall_i(C2, &U2, NULL, 1); h2 = ZV_prod(D2); Fpr = abelrel_pfactor(bnr2, pr, U2, D2, h2); } else Fpr = abelrel_pfactor(bnr, pr, U, D, h); F = ZX_mul(F, Fpr); } return gcopy(mkrfrac(gen_1, F)); } static GEN eulerf_abelrel(GEN an, GEN p) { GEN bnr = gel(an,1), C = gel(an,2), mod = gel(an,3); GEN U, D = ZM_snfall_i(C, &U, NULL, 1), h = ZV_prod(D); return abelrel_factor(bnr, C, p, mod, U, D, h); } struct direuler_abelrel { GEN bnr, C, mod, U, D, h; }; static GEN _direuler_abelrel(void *E, GEN p) { struct direuler_abelrel *s = (struct direuler_abelrel*) E; return abelrel_factor(s->bnr, s->C, p, s->mod, s->U, s->D, s->h); } static GEN vecan_abelrel(GEN an, long N) { struct direuler_abelrel s; s.bnr = gel(an,1); s.C = gel(an,2); s.mod = gel(an,3); s.D = ZM_snfall_i(s.C, &s.U, NULL, 1); s.h = ZV_prod(s.D); return direuler((void*)&s, _direuler_abelrel, gen_1, stoi(N), NULL); } static GEN lfunabelrel_i(GEN bnr, GEN H, GEN mod) { GEN NrD = bnrdisc(bnr, H, 0), N = absi_shallow(gel(NrD,3)); long n = itos(gel(NrD,1)), r1 = itos(gel(NrD,2)), r2 = (n-r1)>>1; if (!mod) mod = bnrconductor(bnr, H, 0); return mkvecn(7, tag(mkvec3(bnr,H,mod),t_LFUN_ABELREL), gen_0, vec01(r1+r2, r2), gen_1, N, gen_1, gen_0); } static GEN lfunabelrel(GEN bnr, GEN H, GEN mod) { pari_sp av = avma; return gerepilecopy(av, lfunabelrel_i(bnr, H, mod)); } GEN lfunabelianrelinit(GEN bnr, GEN H, GEN dom, long der, long bitprec) { GEN X, cnj, M, D,C ; long l, i; C = chigenkerfind(bnr, H, &cnj); C = vec_classes (C, cnj); X = cgetg_copy(C,&l); for (i = 1; i < l; ++i) { GEN chi = gel(C,i); GEN L = lfunchigen(bnr, lg(chi)==2 ? gel(chi,1): chi); gel(X,i) = lfuninit(L, dom, der, bitprec); } M = mkvec3(X, const_vecsmall(l-1, 1), const_vecsmall(l-1, 0)); D = mkvec2(dom, mkvecsmall2(der, bitprec)); return lfuninit_make(t_LDESC_PRODUCT, lfunabelrel_i(bnr, H, NULL), M, D); } /*****************************************************************/ /* Dedekind zeta functions */ /*****************************************************************/ /* true nf */ static GEN dirzetak0(GEN nf, ulong N) { GEN vect, c, c2, T = nf_get_pol(nf), index = nf_get_index(nf); pari_sp av = avma, av2; const ulong SQRTN = usqrt(N); ulong i, p, lx; long court[] = {evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3),0}; forprime_t S; c = cgetalloc(N+1, t_VECSMALL); c2 = cgetalloc(N+1, t_VECSMALL); c2[1] = c[1] = 1; for (i=2; i<=N; i++) c[i] = 0; u_forprime_init(&S, 2, N); av2 = avma; while ( (p = u_forprime_next(&S)) ) { set_avma(av2); if (umodiu(index, p)) /* p does not divide index */ vect = gel(Flx_degfact(ZX_to_Flx(T,p), p),1); else { court[2] = p; vect = idealprimedec_degrees(nf,court); } lx = lg(vect); if (p <= SQRTN) for (i=1; i N) break; memcpy(c2 + 2, c + 2, (N-1)*sizeof(long)); /* c2[i] <- c[i] + sum_{k = 1}^{v_q(i)} c[i/q^k] for all i <= N */ for (qn = q; qn <= N; qn *= q) { ulong k0 = N/qn, k, k2; /* k2 = k*qn */ for (k = k0, k2 = k*qn; k > 0; k--, k2 -=qn) c2[k2] += c[k]; if (q > k0) break; /* <=> q*qn > N */ } swap(c, c2); } else /* p > sqrt(N): simpler */ for (i=1; i 1) break; /* c2[i] <- c[i] + sum_{k = 1}^{v_q(i)} c[i/q^k] for all i <= N */ for (k = N/p, k2 = k*p; k > 0; k--, k2 -= p) c[k2] += c[k]; } } set_avma(av); pari_free(c2); return c; } static GEN eulerf_zetak(GEN nf, GEN p) { GEN v, f = pol_1(0); long i, l; if (dvdii(nf_get_index(nf), p)) /* p does not divide index */ v = idealprimedec_degrees(nf,p); else v = gel(FpX_degfact(nf_get_pol(nf), p), 1); l = lg(v); for (i = 1; i < l; i++) f = ZX_sub(f, RgX_shift_shallow(f, v[i])); retmkrfrac(gen_1, ZX_copy(f)); } GEN dirzetak(GEN nf, GEN b) { GEN z, c; long n; if (typ(b) != t_INT) pari_err_TYPE("dirzetak",b); if (signe(b) <= 0) return cgetg(1,t_VEC); nf = checknf(nf); n = itou_or_0(b); if (!n) pari_err_OVERFLOW("dirzetak"); c = dirzetak0(nf, n); z = vecsmall_to_vec(c); pari_free(c); return z; } static GEN linit_get_mat(GEN linit) { if (linit_get_type(linit)==t_LDESC_PRODUCT) return lfunprod_get_fact(linit_get_tech(linit)); else return mkvec3(mkvec(linit), mkvecsmall(1), mkvecsmall(0)); } static GEN lfunproduct(GEN ldata, GEN linit1, GEN linit2, GEN domain) { GEN M1 = linit_get_mat(linit1); GEN M2 = linit_get_mat(linit2); GEN M3 = mkvec3(shallowconcat(gel(M1, 1), gel(M2, 1)), vecsmall_concat(gel(M1, 2), gel(M2, 2)), vecsmall_concat(gel(M1, 3), gel(M2, 3))); return lfuninit_make(t_LDESC_PRODUCT, ldata, M3, domain); } static GEN lfunzetakinit_artin(GEN nf, GEN gal, GEN dom, long der, long bit); /* true nf */ static GEN lfunzetakinit_quotient(GEN nf, GEN polk, GEN dom, long der, long bitprec) { GEN ak, an, nfk, Vga, ldata, N, Lk, LKk, domain; long r1k, r2k, r1, r2; nf_get_sign(nf,&r1,&r2); nfk = nfinit(polk, nbits2prec(bitprec)); Lk = lfunzetakinit(nfk, dom, der, bitprec); /* zeta_k */ nf_get_sign(nfk,&r1k,&r2k); Vga = vec01((r1+r2) - (r1k+r2k), r2-r2k); N = absi_shallow(diviiexact(nf_get_disc(nf), nf_get_disc(nfk))); ak = nf_get_degree(nf)==1 ? tag(gen_1, t_LFUN_ZETA): tag(nfk, t_LFUN_NF); an = tag(mkvec2(tag(nf,t_LFUN_NF), ak), t_LFUN_DIV); ldata = mkvecn(6, an, gen_0, Vga, gen_1, N, gen_1); LKk = lfuninit(ldata, dom, der, bitprec); /* zeta_K/zeta_k */ domain = mkvec2(dom, mkvecsmall2(der, bitprec)); return lfunproduct(lfunzetak_i(nf), Lk, LKk, domain); } /* true nf */ GEN lfunzetakinit(GEN nf, GEN dom, long der, long bitprec) { long n, d = nf_get_degree(nf); GEN L, Q, R, T = nf_get_pol(nf); if (d == 1) return lfuninit(lfunzeta(), dom, der, bitprec); if (d > 2) { GEN G = galoisinit(nf, NULL); if (isintzero(G)) { /* not Galois */ GEN S = nfsubfields(nf, 0); n = lg(S)-1; return lfunzetakinit_quotient(nf, gmael(S,n-1,1), dom, der, bitprec); } if (!group_isabelian(galois_group(G))) /* Galois, not Abelian */ return lfunzetakinit_artin(nf, G, dom, der, bitprec); } /* Abelian over Q */ Q = Buchall(pol_x(1), 0, nbits2prec(bitprec)); T = shallowcopy(T); setvarn(T,0); R = rnfconductor0(Q, T, 1); L = lfunabelianrelinit(gel(R,2), gel(R,3), dom, der, bitprec); delete_var(); return L; } /***************************************************************/ /* Elliptic Curves and Modular Forms */ /***************************************************************/ static GEN lfunellnf(GEN e) { pari_sp av = avma; GEN ldata = cgetg(7, t_VEC), nf = ellnf_get_nf(e); GEN N = gel(ellglobalred(e), 1); long n = nf_get_degree(nf); gel(ldata, 1) = tag(e, t_LFUN_ELL); gel(ldata, 2) = gen_0; gel(ldata, 3) = vec01(n, n); gel(ldata, 4) = gen_2; gel(ldata, 5) = mulii(idealnorm(nf,N), sqri(nf_get_disc(nf))); gel(ldata, 6) = stoi(ellrootno_global(e)); return gerepilecopy(av, ldata); } static GEN lfunellQ(GEN e) { pari_sp av = avma; GEN ldata = cgetg(7, t_VEC); gel(ldata, 1) = tag(ellanal_globalred(e, NULL), t_LFUN_ELL); gel(ldata, 2) = gen_0; gel(ldata, 3) = mkvec2(gen_0, gen_1); gel(ldata, 4) = gen_2; gel(ldata, 5) = ellQ_get_N(e); gel(ldata, 6) = stoi(ellrootno_global(e)); return gerepilecopy(av, ldata); /* ellanal_globalred not gerepile-safe */ } static GEN lfunell(GEN e) { long t = ell_get_type(e); switch(t) { case t_ELL_Q: return lfunellQ(e); case t_ELL_NF:return lfunellnf(e); } pari_err_TYPE("lfun",e); return NULL; /*LCOV_EXCL_LINE*/ } static GEN ellsympow_gamma(long m) { GEN V = cgetg(m+2, t_VEC); long i = 1, j; if (!odd(m)) gel(V, i++) = stoi(-2*(m>>2)); for (j = (m+1)>>1; j > 0; i+=2, j--) { gel(V,i) = stoi(1-j); gel(V,i+1) = stoi(1-j+1); } return V; } static GEN ellsympow_trace(GEN p, GEN t, long m) { long k, n = m >> 1; GEN tp = gpowers0(sqri(t), n, odd(m)? t: NULL); GEN pp = gen_1, b = gen_1, r = gel(tp,n+1); for(k=1; k<=n; k++) { GEN s; pp = mulii(pp, p); b = diviuexact(muliu(b, (m-(2*k-1))*(m-(2*k-2))), k*(m-(k-1))); s = mulii(mulii(b, gel(tp,1+n-k)), pp); r = odd(k) ? subii(r, s): addii(r, s); } return r; } static GEN ellsympow_abelian(GEN p, GEN ap, long m, long o) { pari_sp av = avma; long i, M, n = (m+1)>>1; GEN pk, tv, pn, pm, F, v; if (!odd(o)) { if (odd(m)) return pol_1(0); M = m >> 1; o >>= 1; } else M = m * ((o+1) >> 1); pk = gpowers(p,n); pn = gel(pk,n+1); tv = cgetg(m+2,t_VEC); gel(tv, 1) = gen_2; gel(tv, 2) = ap; for (i = 3; i <= m+1; i++) gel(tv,i) = subii(mulii(ap,gel(tv,i-1)), mulii(p,gel(tv,i-2))); pm = odd(m)? mulii(gel(pk,n), pn): sqri(pn); /* cheap p^m */ F = deg2pol_shallow(pm, gen_0, gen_1, 0); v = odd(m) ? pol_1(0): deg1pol_shallow(negi(pn), gen_1, 0); for (i = M % o; i < n; i += o) /* o | m-2*i */ { gel(F,3) = negi(mulii(gel(tv,m-2*i+1), gel(pk,i+1))); v = ZX_mul(v, F); } return gerepilecopy(av, v); } static GEN ellsympow(GEN E, ulong m, GEN p, long n) { pari_sp av = avma; GEN ap = ellap(E, p); if (n <= 2) { GEN t = ellsympow_trace(p, ap, m); return deg1pol_shallow(t, gen_1, 0); } else return gerepileupto(av, RgXn_inv_i(ellsympow_abelian(p, ap, m, 1), n)); } GEN direllsympow_worker(GEN P, ulong X, GEN E, ulong m) { pari_sp av = avma; long i, l = lg(P); GEN W = cgetg(l, t_VEC); for(i = 1; i < l; i++) { ulong p = uel(P,i); long d = ulogint(X, p) + 1; /* minimal d such that p^d > X */ gel(W,i) = ellsympow(E, m, utoi(uel(P,i)), d); } return gerepilecopy(av, mkvec2(P,W)); } static GEN eulerf_bad(GEN bad, GEN p) { long i, l = lg(bad); for (i = 1; i < l; i++) if (equalii(gmael(bad,i,1), p)) return gmael(bad,i,2); return NULL; } static GEN vecan_ellsympow(GEN an, long n) { GEN nn = utoi(n), crvm = gel(an,1), bad = gel(an,2); GEN worker = snm_closure(is_entry("_direllsympow_worker"), crvm); return pardireuler(worker, gen_2, nn, nn, bad); } static GEN eulerf_ellsympow(GEN an, GEN p) { GEN crvm = gel(an,1), bad = gel(an,2), E = gel(crvm,1); GEN f = eulerf_bad(bad, p); if (f) return f; retmkrfrac(gen_1,ellsympow_abelian(p, ellap(E, p), itos(gel(crvm,2)), 1)); } static long ellsympow_betam(long o, long m) { const long c3[]={3, -1, 1}; const long c12[]={6, -2, 2, 0, 4, -4}; const long c24[]={12, -2, -4, 6, 4, -10}; if (!odd(o) && odd(m)) return 0; switch(o) { case 1: return m+1; case 2: return m+1; case 3: case 6: return (m+c3[m%3])/3; case 4: return m%4 == 0 ? (m+2)/2: m/2; case 8: return m%4 == 0 ? (m+4)/4: (m-2)/4; case 12: return (m+c12[(m%12)/2])/6; case 24: return (m+c24[(m%12)/2])/12; } return 0; } static long ellsympow_epsm(long o, long m) { return m + 1 - ellsympow_betam(o, m); } static GEN ellsympow_multred(GEN E, GEN p, long m, long vN, long *cnd, long *w) { if (vN == 1 || !odd(m)) { GEN s = (odd(m) && signe(ellap(E,p)) < 0)? gen_1: gen_m1; *cnd = m; *w = odd(m)? ellrootno(E, p): 1; return deg1pol_shallow(s, gen_1, 0); } else { *cnd = equaliu(p,2)? ((m+1)>>1) * vN: m+1; *w = (m & 3) == 1? ellrootno(E, p): 1; return pol_1(0); } } static GEN ellsympow_nonabelian(GEN p, long m, long bet) { GEN q = powiu(p, m >> 1), q2 = sqri(q), F; if (odd(m)) { q2 = mulii(q2, p); /* p^m */ return gpowgs(deg2pol_shallow(q2, gen_0, gen_1, 0), bet>>1); } togglesign_safe(&q2); F = gpowgs(deg2pol_shallow(q2, gen_0, gen_1, 0), bet>>1); if (!odd(bet)) return F; if (m%4 != 2) togglesign_safe(&q); return gmul(F, deg1pol_shallow(q, gen_1, 0)); } static long safe_Z_pvalrem(GEN n, GEN p, GEN *pr) { return signe(n)==0? -1: Z_pvalrem(n, p, pr); } static GEN c4c6_ap(GEN c4, GEN c6, GEN p) { GEN N = Fp_ellcard(Fp_muls(c4, -27, p), Fp_muls(c6, -54, p), p); return subii(addiu(p, 1), N); } static GEN ellsympow_abelian_twist(GEN E, GEN p, long m, long o) { GEN ap, c4t, c6t, c4 = ell_get_c4(E), c6 = ell_get_c6(E); long v4 = safe_Z_pvalrem(c4, p, &c4t); long v6 = safe_Z_pvalrem(c6, p, &c6t); if (v6>=0 && (v4==-1 || 3*v4>=2*v6)) c6 = c6t; if (v4>=0 && (v6==-1 || 3*v4<=2*v6)) c4 = c4t; ap = c4c6_ap(c4, c6, p); return ellsympow_abelian(p, ap, m, o); } static GEN ellsympow_goodred(GEN E, GEN p, long m, long *cnd, long *w) { long o = 12/cgcd(12, Z_pval(ell_get_disc(E), p)); long bet = ellsympow_betam(o, m); long eps = m + 1 - bet; *w = odd(m) && odd(eps>>1) ? ellrootno(E,p): 1; *cnd = eps; if (umodiu(p, o) == 1) return ellsympow_abelian_twist(E, p, m, o); else return ellsympow_nonabelian(p, m, bet); } static long ellsympow_inertia3(GEN E, long vN) { long vD = Z_lval(ell_get_disc(E), 3); if (vN==2) return vD%2==0 ? 2: 4; if (vN==4) return vD%4==0 ? 3: 6; if (vN==3 || vN==5) return 12; return 0; } static long ellsympow_deltam3(long o, long m, long vN) { if (o==3 || o==6) return ellsympow_epsm(3, m); if (o==12 && vN ==3) return (ellsympow_epsm(3, m))/2; if (o==12 && vN ==5) return (ellsympow_epsm(3, m))*3/2; return 0; } static long ellsympow_isabelian3(GEN E) { ulong c4 = umodiu(ell_get_c4(E),81), c6 = umodiu(ell_get_c6(E), 243); return (c4 == 27 || (c4%27==9 && (c6==108 || c6==135))); } static long ellsympow_rootno3(GEN E, GEN p, long o, long m) { const long w6p[]={1,-1,-1,-1,1,1}; const long w6n[]={-1,1,-1,1,-1,1}; const long w12p[]={1,1,-1,1,1,1}; const long w12n[]={-1,-1,-1,-1,-1,1}; long w = ellrootno(E, p), mm = (m%12)>>1; switch(o) { case 2: return m%4== 1 ? -1: 1; case 6: return w == 1 ? w6p[mm]: w6n[mm]; case 12: return w == 1 ? w12p[mm]: w12n[mm]; default: return 1; } } static GEN ellsympow_goodred3(GEN E, GEN F, GEN p, long m, long vN, long *cnd, long *w) { long o = ellsympow_inertia3(E, vN); long bet = ellsympow_betam(o, m); *cnd = m + 1 - bet + ellsympow_deltam3(o, m, vN); *w = odd(m)? ellsympow_rootno3(E, p, o, m): 1; if (o==1 || o==2) return ellsympow_abelian(p, ellap(F, p), m, o); if ((o==3 || o==6) && ellsympow_isabelian3(F)) return ellsympow_abelian(p, p, m, o); else return ellsympow_nonabelian(p, m, bet); } static long ellsympow_inertia2(GEN F, long vN) { long vM = itos(gel(elllocalred(F, gen_2),1)); GEN c6 = ell_get_c6(F); long v6 = signe(c6) ? vali(c6): 24; if (vM==0) return vN==0 ? 1: 2; if (vM==2) return vN==2 ? 3: 6; if (vM==5) return 8; if (vM==8) return v6>=9? 8: 4; if (vM==3 || vN==7) return 24; return 0; } static long ellsympow_deltam2(long o, long m, long vN) { if ((o==2 || o==6) && vN==4) return ellsympow_epsm(2, m); if ((o==2 || o==6) && vN==6) return 2*ellsympow_epsm(2, m); if (o==4) return 2*ellsympow_epsm(4, m)+ellsympow_epsm(2, m); if (o==8 && vN==5) return ellsympow_epsm(8, m)+ellsympow_epsm(2, m)/2; if (o==8 && vN==6) return ellsympow_epsm(8, m)+ellsympow_epsm(2, m); if (o==8 && vN==8) return ellsympow_epsm(8, m)+ellsympow_epsm(4, m)+ellsympow_epsm(2, m); if (o==24 && vN==3) return (2*ellsympow_epsm(8, m)+ellsympow_epsm(2, m))/6; if (o==24 && vN==4) return (ellsympow_epsm(8, m)+ellsympow_epsm(2, m)*2)/3; if (o==24 && vN==6) return (ellsympow_epsm(8, m)+ellsympow_epsm(2, m)*5)/3; if (o==24 && vN==7) return (ellsympow_epsm(8, m)*10+ellsympow_epsm(2, m)*5)/6; return 0; } static long ellsympow_isabelian2(GEN F) { return umodi2n(ell_get_c4(F),7) == 96; } static long ellsympow_rootno2(GEN E, long vN, long m, long bet) { long eps2 = (m + 1 - bet)>>1; long eta = odd(vN) && m%8==3 ? -1 : 1; long w2 = odd(eps2) ? ellrootno(E, gen_2): 1; return eta == w2 ? 1 : -1; } static GEN ellsympow_goodred2(GEN E, GEN F, GEN p, long m, long vN, long *cnd, long *w) { long o = ellsympow_inertia2(F, vN); long bet = ellsympow_betam(o, m); *cnd = m + 1 - bet + ellsympow_deltam2(o, m, vN); *w = odd(m) ? ellsympow_rootno2(E, vN, m, bet): 1; if (o==1 || o==2) return ellsympow_abelian(p, ellap(F, p), m, o); if (o==4 && ellsympow_isabelian2(F)) return ellsympow_abelian(p, p, m, o); else return ellsympow_nonabelian(p, m, bet); } static GEN ellminimaldotwist(GEN E, GEN *pD) { GEN D = ellminimaltwistcond(E), Et = elltwist(E, D), Etmin; if (pD) *pD = D; Etmin = ellminimalmodel(Et, NULL); obj_free(Et); return Etmin; } /* Based on Symmetric powers of elliptic curve L-functions, Phil Martin and Mark Watkins, ANTS VII with thanks to Mark Watkins. BA20180402 */ static GEN lfunellsympow(GEN e, ulong m) { pari_sp av = avma; GEN B, N, Nfa, pr, ex, ld, bad, ejd, et, pole; long i, l, mero, w = (m&7)==1 || (m&7)==3 ? -1: 1; checkell_Q(e); e = ellminimalmodel(e, NULL); ejd = Q_denom(ell_get_j(e)); mero = m==0 || (m%4==0 && ellQ_get_CM(e)<0); ellQ_get_Nfa(e, &N, &Nfa); pr = gel(Nfa,1); ex = gel(Nfa,2); l = lg(pr); if (ugcd(umodiu(N,6), 6) == 1) et = NULL; else et = ellminimaldotwist(e, NULL); B = gen_1; bad = cgetg(l, t_VEC); for (i=1; i>1)),gen_0)): NULL; ld = mkvecn(mero? 7: 6, tag(mkvec2(mkvec2(e,utoi(m)),bad), t_LFUN_SYMPOW_ELL), gen_0, ellsympow_gamma(m), stoi(m+1), B, stoi(w), pole); if (et) obj_free(et); return gerepilecopy(av, ld); } GEN lfunsympow(GEN ldata, ulong m) { ldata = lfunmisc_to_ldata_shallow(ldata); if (ldata_get_type(ldata) != t_LFUN_ELL) pari_err_IMPL("lfunsympow"); return lfunellsympow(gel(ldata_get_an(ldata), 2), m); } static GEN lfunmfspec_i(GEN lmisc, long bit) { GEN linit, ldataf, v, ve, vo, om, op, B, dom; long k, k2, j; ldataf = lfunmisc_to_ldata_shallow(lmisc); if (!gequal(ldata_get_gammavec(ldataf), mkvec2(gen_0,gen_1))) pari_err_TYPE("lfunmfspec", lmisc); k = gtos(ldata_get_k(ldataf)); if (k == 1) return mkvec2(cgetg(1, t_VEC), gen_1); dom = mkvec3(dbltor(k/2.), dbltor((k-2)/2.), gen_0); if (is_linit(lmisc) && linit_get_type(lmisc) == t_LDESC_INIT && sdomain_isincl((double)k, dom, lfun_get_dom(linit_get_tech(lmisc)))) linit = lmisc; else linit = lfuninit(ldataf, dom, 0, bit); B = int2n(bit/4); v = cgetg(k, t_VEC); for (j = 1; j < k; j++) gel(v,j) = lfunlambda(linit, utoi(j), bit); om = gel(v,1); if (odd(k)) return mkvec2(bestappr(gdiv(v, om), B), om); k2 = k/2; ve = cgetg(k2, t_VEC); vo = cgetg(k2+1, t_VEC); gel(vo,1) = om; for (j = 1; j < k2; j++) { gel(ve,j) = gel(v,2*j); gel(vo,j+1) = gel(v,2*j+1); } if (k2 == 1) { om = gen_1; op = gel(v,1); } else { om = gel(v,2); op = gel(v,3); } if (maxss(gexpo(imag_i(om)), gexpo(imag_i(op))) > -bit/2) pari_err_TYPE("lfunmfspec", lmisc); ve = gdiv(ve, om); vo = gdiv(vo, op); return mkvec4(bestappr(ve,B), bestappr(vo,B), om, op); } GEN lfunmfspec(GEN lmisc, long bit) { pari_sp av = avma; return gerepilecopy(av, lfunmfspec_i(lmisc, bit)); } static long ellsymsq_bad2(GEN c4, GEN c6, long e) { switch (e) { case 2: return 1; case 3: return 0; case 5: return 0; case 7: return 0; case 8: if (!umodi2n(c6,9)) return 0; return umodi2n(c4,7)==32 ? 1 : -1; default: return 0; } } static long ellsymsq_bad3(GEN c4, GEN c6, long e) { long c6_243, c4_81; switch (e) { case 2: return 1; case 3: return 0; case 5: return 0; case 4: c4_81 = umodiu(c4,81); if (c4_81 == 27) return -1; if (c4_81%27 != 9) return 1; c6_243 = umodiu(c6,243); return (c6_243==108 || c6_243==135)? -1: 1; default: return 0; } } static int c4c6_testp(GEN c4, GEN c6, GEN p) { GEN p2 = sqri(p); return (dvdii(c6,p2) && !dvdii(c4,p2)); } /* assume e = v_p(N) >= 2 */ static long ellsymsq_badp(GEN c4, GEN c6, GEN p, long e) { if (absequaliu(p, 2)) return ellsymsq_bad2(c4, c6, e); if (absequaliu(p, 3)) return ellsymsq_bad3(c4, c6, e); switch(umodiu(p, 12UL)) { case 1: return -1; case 5: return c4c6_testp(c4,c6,p)? -1: 1; case 7: return c4c6_testp(c4,c6,p)? 1:-1; default:return 1; /* p%12 = 11 */ } } static GEN lfunellsymsqmintwist(GEN e) { pari_sp av = avma; GEN N, Nfa, P, E, V, c4, c6, ld; long i, l, k; checkell_Q(e); e = ellminimalmodel(e, NULL); ellQ_get_Nfa(e, &N, &Nfa); c4 = ell_get_c4(e); c6 = ell_get_c6(e); P = gel(Nfa,1); l = lg(P); E = gel(Nfa,2); V = cgetg(l, t_VEC); for (i=k=1; i vt */ if (absequaliu(p, 2)) { if (vt == 0 && v >= 4) r = shifti(subsi(9, sqri(ellap(Et, p))), v-3); /* 9=(2+1)^2 */ else if (vt == 1) r = gmul2n(utoipos(3), v-3); /* not in Z if v=2 */ else if (vt >= 2) r = int2n(v-vt); else r = gen_1; /* vt = 0, 1 <= v <= 3 */ } else if (vt >= 1) r = gdiv(subiu(sqri(p), 1), p); else r = gdiv(mulii(subiu(p, 1), subii(sqri(addiu(p, 1)), sqri(ellap(Et, p)))), p); f = gmul(f, r); } return f; } GEN lfunellmfpeters(GEN E, long bitprec) { pari_sp ltop = avma; GEN D, Et = ellminimaldotwist(E, &D); GEN nor = lfunellmfpetersmintwist(Et, bitprec); GEN nor2 = gmul(nor, elldiscfix(E, Et, D)); obj_free(Et); return gerepileupto(ltop, nor2); } /*************************************************************/ /* Genus 2 curves */ /*************************************************************/ static void Flv_diffnext(GEN d, ulong p) { long j, n = lg(d)-1; for(j = n; j>=2; j--) uel(d,j) = Fl_add(uel(d,j), uel(d,j-1), p); } static GEN Flx_difftable(GEN P, ulong p) { long i, n = degpol(P); GEN V = cgetg(n+2, t_VECSMALL); uel(V, n+1) = Flx_constant(P); for(i = n; i >= 1; i--) { P = Flx_diff1(P, p); uel(V, i) = Flx_constant(P); } return V; } static long Flx_genus2trace_naive(GEN H, ulong p) { pari_sp av = avma; ulong i, j; long a, n = degpol(H); GEN k = const_vecsmall(p, -1), d; k[1] = 0; for (i=1, j=1; i < p; i += 2, j = Fl_add(j, i, p)) k[j+1] = 1; a = n == 5 ? 0: k[1+Flx_lead(H)]; d = Flx_difftable(H, p); for (i=0; i < p; i++) { a += k[1+uel(d,n+1)]; Flv_diffnext(d, p); } set_avma(av); return a; } static GEN dirgenus2(GEN Q, GEN p, long n) { pari_sp av = avma; GEN f; if (n > 2) f = RgX_recip(hyperellcharpoly(gmul(Q,gmodulo(gen_1, p)))); else { ulong pp = itou(p); GEN Qp = ZX_to_Flx(Q, pp); long t = Flx_genus2trace_naive(Qp, pp); f = deg1pol_shallow(stoi(t), gen_1, 0); } return gerepileupto(av, RgXn_inv_i(f, n)); } GEN dirgenus2_worker(GEN P, ulong X, GEN Q) { pari_sp av = avma; long i, l = lg(P); GEN V = cgetg(l, t_VEC); for(i = 1; i < l; i++) { ulong p = uel(P,i); long d = ulogint(X, p) + 1; /* minimal d such that p^d > X */ gel(V,i) = dirgenus2(Q, utoi(uel(P,i)), d); } return gerepilecopy(av, mkvec2(P,V)); } static GEN vecan_genus2(GEN an, long L) { GEN Q = gel(an,1), bad = gel(an, 2); GEN worker = snm_closure(is_entry("_dirgenus2_worker"), mkvec(Q)); return pardireuler(worker, gen_2, stoi(L), NULL, bad); } static GEN eulerf_genus2(GEN an, GEN p) { GEN Q = gel(an,1), bad = gel(an, 2); GEN f = eulerf_bad(bad, p); if (f) return f; f = RgX_recip(hyperellcharpoly(gmul(Q,gmodulo(gen_1, p)))); return mkrfrac(gen_1,f); } static GEN genus2_redmodel(GEN P, GEN p) { GEN M = FpX_factor(P, p); GEN F = gel(M,1), E = gel(M,2); long i, k, r = lg(F); GEN U = scalarpol(leading_coeff(P), varn(P)); GEN G = cgetg(r, t_COL); for (i=1, k=0; i1) gel(G,++k) = gel(F,i); if (odd(E[i])) U = FpX_mul(U, gel(F,i), p); } setlg(G,++k); return mkvec2(G,U); } static GEN oneminusxd(long d) { return gsub(gen_1, pol_xn(d, 0)); } static GEN ellfromeqncharpoly(GEN P, GEN Q, GEN p) { long v; GEN E, F, t, y; v = fetch_var(); y = pol_x(v); F = gsub(gadd(ZX_sqr(y), gmul(y, Q)), P); E = ellinit(ellfromeqn(F), p, DEFAULTPREC); delete_var(); t = ellap(E, p); obj_free(E); return mkpoln(3, gen_1, negi(t), p); } static GEN nfellcharpoly(GEN e, GEN T, GEN p) { GEN nf, E, t; nf = nfinit(mkvec2(T, mkvec(p)), DEFAULTPREC); E = ellinit(e, nf, DEFAULTPREC); if (lg(E)==1) return NULL; t = elleulerf(E, p); obj_free(E); return t; } static GEN genus2_red5(GEN P, GEN T, GEN p) { long vx = varn(P), vy = varn(T); GEN f = shallowcopy(T); setvarn(f, vx); while(1) { GEN Pr, R, r, Rs; (void) ZXX_pvalrem(P, p, &Pr); R = FpXQX_roots_mult(Pr, 3, T, p); if (lg(R)==1) return P; r = FpX_center(gel(R,1), p, shifti(p,-1)); r = gel(R,1); P = RgX_affine(P, p, r); setvarn(r, vx); f = RgX_Rg_div(gsub(f, r), p); Rs = RgX_rem(RgXY_swap(P, 3, vy), gsub(f, pol_x(vy))); P = RgXY_swap(Rs, 3, vy); (void) ZXX_pvalrem(P, sqri(p), &P); } } static GEN genus2_type5(GEN P, GEN p) { GEN E, F, T, a, a2, Q; long v; (void) ZX_pvalrem(P, p, &F); F = FpX_red(F, p); if (degpol(F) < 1) return NULL; F = FpX_factor(F, p); if (mael(F,2,1) != 3 || degpol(gmael(F,1,1)) != 2) return NULL; T = gmael(F, 1, 1); v = fetch_var_higher(); Q = RgV_to_RgX(ZX_digits(P, T), v); Q = genus2_red5(Q, T, p); a = gel(Q,5); a2 = ZX_sqr(a); E = mkvec5(gen_0, gel(Q,4), gen_0, ZX_mul(gel(Q,3),a), ZX_mul(gel(Q,2),a2)); delete_var(); return nfellcharpoly(E, T, p); } /* Assume P has semistable reduction at p */ static GEN genus2_eulerfact_semistable(GEN P, GEN p) { GEN Pp = FpX_red(P, p); GEN GU = genus2_redmodel(Pp, p); long d = 6-degpol(Pp), v = d/2, w = odd(d); GEN abe, tor; GEN ki, kp = pol_1(0), kq = pol_1(0); GEN F = gel(GU,1), Q = gel(GU,2); long dQ = degpol(Q), lF = lg(F)-1; abe = dQ >= 5 ? RgX_recip(hyperellcharpoly(gmul(Q,gmodulo(gen_1,p)))) : dQ >= 3 ? RgX_recip(ellfromeqncharpoly(Q,gen_0,p)) : pol_1(0); ki = dQ != 0 ? oneminusxd(1) : Fp_issquare(gel(Q,2),p) ? ZX_sqr(oneminusxd(1)) : oneminusxd(2); if (lF) { long i; for(i=1; i <= lF; i++) { GEN Fi = gel(F, i); long d = degpol(Fi); GEN e = FpX_rem(Q, Fi, p); GEN kqf = lgpol(e)==0 ? oneminusxd(d): FpXQ_issquare(e, Fi, p) ? ZX_sqr(oneminusxd(d)) : oneminusxd(2*d); kp = gmul(kp, oneminusxd(d)); kq = gmul(kq, kqf); } } if (v) { GEN kqoo = w==1 ? oneminusxd(1): Fp_issquare(leading_coeff(Q), p)? ZX_sqr(oneminusxd(1)) : oneminusxd(2); kp = gmul(kp, oneminusxd(1)); kq = gmul(kq, kqoo); } tor = RgX_div(ZX_mul(oneminusxd(1), kq), ZX_mul(ki, kp)); return ginv( ZX_mul(abe, tor) ); } static GEN genus2_eulerfact(GEN P, GEN p) { pari_sp av = avma; GEN W, R = genus2_type5(P, p), E; if (R) return R; W = hyperellextremalmodels(P, 2, p); if (lg(W) < 3) return genus2_eulerfact_semistable(P,p); E = gmul(genus2_eulerfact_semistable(gel(W,1),p), genus2_eulerfact_semistable(gel(W,2),p)); return gerepileupto(av, E); } static GEN F2x_genus2_find_trans(GEN P, GEN Q, GEN F) { pari_sp av = avma; long i, d = F2x_degree(F), v = P[1]; GEN M, C, V; M = cgetg(d+1, t_MAT); for (i=1; i<=d; i++) { GEN Mi = F2x_rem(F2x_add(F2x_shift(Q,i-1), monomial_F2x(2*i-2,v)), F); gel(M,i) = F2x_to_F2v(Mi, d); } C = F2x_to_F2v(F2x_rem(P, F), d); V = F2m_F2c_invimage(M, C); return gerepileuptoleaf(av, F2v_to_F2x(V, v)); } static GEN F2x_genus2_trans(GEN P, GEN Q, GEN H) { return F2x_add(P,F2x_add(F2x_mul(H,Q), F2x_sqr(H))); } static GEN F2x_genus_redoo(GEN P, GEN Q, long k) { if (F2x_degree(P)==2*k) { long c = F2x_coeff(P,2*k-1), dQ = F2x_degree(Q); if ((dQ==k-1 && c==1) || (dQ0) { GEN M = gel(F2x_factor(F),1); long i, l = lg(M); for(i=1; i 0) { GEN d = F2xq_div(c, F2xq_sqr(b, T), T); return F2xq_trace(d, T)? 0: 2; } else return 1; } static GEN genus2_eulerfact2_semistable(GEN PQ) { GEN V = F2x_genus_red(ZX_to_F2x(gel(PQ, 1)), ZX_to_F2x(gel(PQ, 2))); GEN P = gel(V, 1), Q = gel(V, 2); GEN F = gel(V, 3), v = gel(V, 4); GEN abe, tor; GEN ki, kp = pol_1(0), kq = pol_1(0); long dP = F2x_degree(P), dQ = F2x_degree(Q), d = maxss(dP, 2*dQ); if (!lgpol(F)) return pol_1(0); ki = dQ!=0 || dP>0 ? oneminusxd(1): dP==-1 ? ZX_sqr(oneminusxd(1)): oneminusxd(2); abe = d>=5? RgX_recip(hyperellcharpoly(gmul(PQ,gmodulss(1,2)))): d>=3? RgX_recip(ellfromeqncharpoly(F2x_to_ZX(P), F2x_to_ZX(Q), gen_2)): pol_1(0); if (lgpol(F)) { GEN M = gel(F2x_factor(F), 1); long i, lF = lg(M)-1; for(i=1; i <= lF; i++) { GEN Fi = gel(M, i); long d = F2x_degree(Fi); long nb = F2xqX_quad_nbroots(F2x_rem(Q, Fi), F2x_rem(P, Fi), Fi); GEN kqf = nb==1 ? oneminusxd(d): nb==2 ? ZX_sqr(oneminusxd(d)) : oneminusxd(2*d); kp = gmul(kp, oneminusxd(d)); kq = gmul(kq, kqf); } } if (maxss(v[1],2*v[2])<5) { GEN kqoo = v[1]>2*v[2] ? oneminusxd(1): v[1]<2*v[2] ? ZX_sqr(oneminusxd(1)) : oneminusxd(2); kp = gmul(kp, oneminusxd(1)); kq = gmul(kq, kqoo); } tor = RgX_div(ZX_mul(oneminusxd(1),kq), ZX_mul(ki, kp)); return ginv( ZX_mul(abe, tor) ); } static GEN genus2_eulerfact2(GEN F, GEN PQ) { pari_sp av = avma; GEN W, R = genus2_type5(F, gen_2), E; if (R) return R; W = hyperellextremalmodels(PQ, 2, gen_2); if (lg(W) < 3) return genus2_eulerfact2_semistable(PQ); E = gmul(genus2_eulerfact2_semistable(gel(W,1)), genus2_eulerfact2_semistable(gel(W,2))); return gerepileupto(av, E); } GEN lfungenus2(GEN G) { pari_sp ltop = avma; GEN Ldata; GEN gr = genus2red(G, NULL); GEN N = gel(gr, 1), M = gel(gr, 2), PQ = gel(gr, 3), L = gel(gr, 4); GEN e, F = gadd(gsqr(gel(PQ, 2)), gmul2n(gel(PQ, 1), 2)); long i, lL = lg(L), ram2; ram2 = absequaliu(gmael(M,1,1),2); if (ram2 && equalis(gmael(M,2,1),-1)) pari_warn(warner,"unknown valuation of conductor at 2"); e = cgetg(lL+(ram2?0:1), t_VEC); gel(e,1) = mkvec2(gen_2, ram2 ? genus2_eulerfact2(F, PQ) : ginv( RgX_recip(hyperellcharpoly(gmul(PQ,gmodulss(1,2))))) ); for(i = ram2? 2: 1; i < lL; i++) { GEN Li = gel(L, i); GEN p = gel(Li, 1); gel(e, ram2 ? i: i+1) = mkvec2(p, genus2_eulerfact(F,p)); } Ldata = mkvecn(6, tag(mkvec2(F,e), t_LFUN_GENUS2), gen_0, mkvec4(gen_0, gen_0, gen_1, gen_1), gen_2, N, gen_0); return gerepilecopy(ltop, Ldata); } /*************************************************************/ /* ETA QUOTIENTS */ /* An eta quotient is a matrix with 2 columns [m, r_m] with */ /* m >= 1 representing f(\tau)=\prod_m\eta(m\tau)^{r_m}. */ /*************************************************************/ /* eta(x^v) + O(x^L) */ GEN eta_ZXn(long v, long L) { long n, k = 0, v2 = 2*v, bn = v, cn = 0; GEN P; if (!L) return zeropol(0); P = cgetg(L+2,t_POL); P[1] = evalsigne(1); for(n = 0; n < L; n++) gel(P,n+2) = gen_0; for(n = 0;; n++, bn += v2, cn += v) { /* k = v * (3*n-1) * n / 2; bn = v * (2*n+1); cn = v * n */ long k2; gel(P, k+2) = odd(n)? gen_m1: gen_1; k2 = k+cn; if (k2 >= L) break; k = k2; /* k = v * (3*n+1) * n / 2 */; gel(P, k+2) = odd(n)? gen_m1: gen_1; k2 = k+bn; if (k2 >= L) break; k = k2; } setlg(P, k+3); return P; } GEN eta_product_ZXn(GEN eta, long L) { pari_sp av = avma; GEN P = NULL, D = gel(eta,1), R = gel(eta,2); long i, l = lg(D); for (i = 1; i < l; ++i) { GEN Q = eta_ZXn(D[i], L); long r = R[i]; if (r < 0) { Q = RgXn_inv_i(Q, L); r = -r; } if (r != 1) Q = RgXn_powu_i(Q, r, L); P = P? ZXn_mul(P, Q, L): Q; if (gc_needed(av,1) && i > 1) { if (DEBUGMEM>1) pari_warn(warnmem,"eta_product_ZXn"); P = gerepilecopy(av, P); } } return P; } static GEN vecan_eta(GEN an, long L) { long v = itos(gel(an, 3)); GEN t; if (v > L) return zerovec(L); t = eta_product_ZXn(an, L - v); if (v) t = RgX_shift_shallow(t, v); return RgX_to_RgV(t, L); } /* return 1 if cuspidal, 0 if holomorphic, -1 otherwise */ static int etacuspidal(GEN N, GEN k, GEN B, GEN R, GEN NB) { long i, j, lD, l, cusp = 1; pari_sp av = avma; GEN D; if (gsigne(k) < 0) return -1; D = divisors(N); lD = lg(D); l = lg(B); for (i = 1; i < lD; i++) { GEN t = gen_0, d = gel(D,i); long s; for (j = 1; j < l; j++) t = addii(t, mulii(gel(NB,j), mulii(gel(R,j), sqri(gcdii(d, gel(B,j)))))); s = signe(t); if (s < 0) return -1; if (!s) cusp = 0; } return gc_bool(av, cusp); } /* u | 24, level N = u*N0, N0 = lcm(B), NB[i] = N0/B[i] */ static int etaselfdual(GEN B, GEN R, GEN NB, ulong u) { pari_sp av = avma; long i, l = lg(B); for (i = 1; i < l; i++) { long j = ZV_search(B, muliu(gel(NB,i), u)); /* search for N / B[i] */ set_avma(av); if (!j || !equalii(gel(R,i),gel(R,j))) return 0; } return 1; } /* return Nebentypus of eta quotient, k2 = 2*k integral */ static GEN etachar(GEN B, GEN R, GEN k2) { long i, l = lg(B); GEN P = gen_1; for (i = 1; i < l; ++i) if (mpodd(gel(R,i))) P = mulii(P, gel(B,i)); switch(Mod4(k2)) { case 0: break; case 2: P = negi(P); break; default: P = shifti(P, 1); break; } return coredisc(P); } /* Return 0 if not on gamma_0(N). Sets conductor, modular weight, character, * canonical matrix, v_q(eta), sd = 1 iff self-dual, cusp = 1 iff cuspidal * [0 if holomorphic at all cusps, else -1] */ long etaquotype(GEN *peta, GEN *pN, GEN *pk, GEN *CHI, long *pv, long *sd, long *cusp) { GEN B, R, S, T, N, NB, eta = *peta; long l, i, u, S24; if (lg(eta) != 3) pari_err_TYPE("lfunetaquo", eta); switch(typ(eta)) { case t_VEC: eta = mkmat2(mkcol(gel(eta,1)), mkcol(gel(eta,2))); break; case t_MAT: break; default: pari_err_TYPE("lfunetaquo", eta); } if (!RgV_is_ZVpos(gel(eta,1)) || !RgV_is_ZV(gel(eta,2))) pari_err_TYPE("lfunetaquo", eta); *peta = eta = famat_reduce(eta); B = gel(eta,1); l = lg(B); /* sorted in increasing order */ R = gel(eta,2); N = ZV_lcm(B); NB = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(NB,i) = diviiexact(N, gel(B,i)); S = gen_0; T = gen_0; u = 0; for (i = 1; i < l; ++i) { GEN b = gel(B,i), r = gel(R,i); S = addii(S, mulii(b, r)); T = addii(T, r); u += umodiu(r,24) * umodiu(gel(NB,i), 24); } S = divis_rem(S, 24, &S24); if (S24) return 0; /* nonintegral valuation at oo */ u = 24 / ugcd(24, u % 24); *pN = muliu(N, u); /* level */ *pk = gmul2n(T,-1); /* weight */ *pv = itos(S); /* valuation */ if (cusp) *cusp = etacuspidal(*pN, *pk, B, R, NB); if (sd) *sd = etaselfdual(B, R, NB, u); if (CHI) *CHI = etachar(B, R, T); return 1; } GEN lfunetaquo(GEN eta0) { pari_sp ltop = avma; GEN Ldata, N, BR, k, eta = eta0; long v, sd, cusp; if (!etaquotype(&eta, &N, &k, NULL, &v, &sd, &cusp)) pari_err_TYPE("lfunetaquo", eta0); if (!cusp) pari_err_IMPL("noncuspidal eta quotient"); if (!sd) pari_err_IMPL("non self-dual eta quotient"); if (typ(k) != t_INT) pari_err_TYPE("lfunetaquo [nonintegral weight]", eta0); BR = mkvec3(ZV_to_zv(gel(eta,1)), ZV_to_zv(gel(eta,2)), stoi(v - 1)); Ldata = mkvecn(6, tag(BR,t_LFUN_ETA), gen_0, mkvec2(gen_0,gen_1), k,N, gen_1); return gerepilecopy(ltop, Ldata); } static GEN vecan_qf(GEN Q, long L) { GEN v, w = qfrep0(Q, utoi(L), 1); long i; v = cgetg(L+1, t_VEC); for (i = 1; i <= L; i++) gel(v,i) = utoi(2 * w[i]); return v; } long qfiseven(GEN M) { long i, l = lg(M); for (i=1; i 0) { set_avma(av); return g; } for (i = 1; i<=r; i++) { GEN h = gel(grp, i); long t = h[1]; while (h[t]!=1) t = h[t]; F2v_set(b, h[g[t]]); } set_avma(av); } } pari_err_BUG("galois_get_conj"); return NULL;/*LCOV_EXCL_LINE*/ } static GEN cyclotoi(GEN v) { return simplify_shallow(lift_shallow(v)); } static long cyclotos(GEN v) { return gtos(cyclotoi(v)); } static long char_dim(GEN ch) { return cyclotos(gel(ch,1)); } static GEN artin_gamma(GEN N, GEN G, GEN ch) { long a, t, d = char_dim(ch); if (nf_get_r2(N) == 0) return vec01(d, 0); a = galois_get_conj(G)[1]; t = cyclotos(gel(ch,a)); return vec01((d+t) / 2, (d-t) / 2); } static long artin_dim(GEN ind, GEN ch) { long n = lg(ch)-1; GEN elts = group_elts(ind, n); long i, d = lg(elts)-1; GEN s = gen_0; for(i=1; i<=d; i++) s = gadd(s, gel(ch, gel(elts,i)[1])); return gtos(gdivgu(cyclotoi(s), d)); } static GEN artin_ind(GEN elts, GEN ch, GEN p) { long i, d = lg(elts)-1; GEN s = gen_0; for(i=1; i<=d; i++) s = gadd(s, gel(ch, gmul(gel(elts,i),p)[1])); return gdivgu(s, d); } static GEN artin_ram(GEN nf, GEN gal, GEN aut, GEN pr, GEN ramg, GEN ch, long d) { pari_sp av = avma; long i, v, n; GEN p, q, V, elts; if (d==0) return pol_1(0); n = degpol(gal_get_pol(gal)); q = p = idealramfrobenius_aut(nf, gal, pr, ramg, aut); elts = group_elts(gel(ramg,2), n); v = fetch_var_higher(); V = cgetg(d+2, t_POL); V[1] = evalsigne(1)|evalvarn(v); for(i=1; i<=d; i++) { gel(V,i+1) = artin_ind(elts, ch, q); q = gmul(q, p); } delete_var(); V = RgXn_expint(RgX_neg(V),d+1); setvarn(V,0); return gerepileupto(av, ginv(V)); } /* N true nf; [Artin conductor, vec of [p, Lp]] */ static GEN artin_badprimes(GEN N, GEN G, GEN aut, GEN ch) { pari_sp av = avma; long i, d = char_dim(ch); GEN P = gel(absZ_factor(nf_get_disc(N)), 1); long lP = lg(P); GEN B = cgetg(lP, t_VEC), C = cgetg(lP, t_VEC); for (i = 1; i < lP; ++i) { GEN p = gel(P, i), pr = idealprimedec_galois(N, p); GEN J = idealramgroups_aut(N, G, pr, aut); GEN G0 = gel(J,2); /* inertia group */ long lJ = lg(J); long sdec = artin_dim(G0, ch); long ndec = group_order(G0); long j, v = ndec * (d - sdec); for (j = 3; j < lJ; ++j) { GEN Jj = gel(J, j); long s = artin_dim(Jj, ch); v += group_order(Jj) * (d - s); } gel(C, i) = powiu(p, v/ndec); gel(B, i) = mkvec2(p, artin_ram(N, G, aut, pr, J, ch, sdec)); } return gerepilecopy(av, mkvec2(ZV_prod(C), B)); } /* p does not divide nf.index */ static GEN idealfrobenius_easy(GEN nf, GEN gal, GEN aut, GEN T, GEN p) { long i, l = lg(aut), f = degpol(T); GEN D, Dzk, DzkT, DXp, grp = gal_get_group(gal); pari_sp av = avma; if (f==1) return gel(grp,1); Dzk = nf_get_zkprimpart(nf); D = modii(nf_get_zkden(nf), p); DzkT = RgV_to_RgM(FqV_red(Dzk, T, p), f); DXp = RgX_to_RgC(FpX_Frobenius(T, p), f); if (!equali1(D)) DXp = FpC_Fp_mul(DXp, D, p); for(i=1; i < l; i++) { GEN g = gel(grp,i); if (perm_orderu(g) == (ulong)f) { GEN A = FpM_FpC_mul(DzkT, gel(aut,g[1]), p); if (ZV_equal(A, DXp)) {set_avma(av); return g; } } } return NULL; /* LCOV_EXCL_LINE */ } /* true nf; p divides nf.index, pr/p unramified */ static GEN idealfrobenius_hard(GEN nf, GEN gal, GEN aut, GEN pr) { long i, l = lg(aut), f = pr_get_f(pr); GEN modpr, p, T, X, Xp, pi, grp = gal_get_group(gal); pari_sp av = avma; if (f==1) return gel(grp,1); pi = pr_get_gen(pr); modpr = zkmodprinit(nf, pr); p = modpr_get_p(modpr); T = modpr_get_T(modpr); X = modpr_genFq(modpr); Xp = FpX_Frobenius(T, p); for (i = 1; i < l; i++) { GEN g = gel(grp,i); if (perm_orderu(g) == (ulong)f) { GEN S = gel(aut,g[1]); GEN A = nf_to_Fq(nf, zk_galoisapplymod(nf,X,S,p), modpr); /* sigma(X) = X^p (mod pr) and sigma(pi) in pr */ if (ZX_equal(A, Xp) && (f == nf_get_degree(nf) || ZC_prdvd(zk_galoisapplymod(nf,pi,S,p),pr))) { set_avma(av); return g; } } } return NULL; /* LCOV_EXCL_LINE */ } /* true nf */ static GEN dirartin(GEN nf, GEN G, GEN V, GEN aut, GEN p, long n) { pari_sp av = avma; GEN pr, frob; /* pick one maximal ideal in the conjugacy class above p */ GEN T = nf_get_pol(nf); if (!dvdii(nf_get_index(nf), p)) { /* simple case */ GEN F = FpX_factor(T, p), P = gmael(F,1,1); frob = idealfrobenius_easy(nf, G, aut, P, p); } else { pr = idealprimedec_galois(nf,p); frob = idealfrobenius_hard(nf, G, aut, pr); } set_avma(av); return n ? RgXn_inv(gel(V, frob[1]), n): gel(V, frob[1]); } GEN dirartin_worker(GEN P, ulong X, GEN nf, GEN G, GEN V, GEN aut) { pari_sp av = avma; long i, l = lg(P); GEN W = cgetg(l, t_VEC); for(i = 1; i < l; i++) { ulong p = uel(P,i); long d = ulogint(X, p) + 1; /* minimal d such that p^d > X */ gel(W,i) = dirartin(nf, G, V, aut, utoi(uel(P,i)), d); } return gerepilecopy(av, mkvec2(P,W)); } static GEN vecan_artin(GEN an, long L, long prec) { GEN A, Sbad = gel(an,5); long n = itos(gel(an,6)), isreal = lg(an)<8 ? 0: !itos(gel(an,7)); GEN worker = snm_closure(is_entry("_dirartin_worker"), vecslice(an,1,4)); A = lift_shallow(pardireuler(worker, gen_2, stoi(L), NULL, Sbad)); A = RgXV_RgV_eval(A, grootsof1(n, prec)); if (isreal) A = real_i(A); return A; } static GEN eulerf_artin(GEN an, GEN p, long prec) { GEN nf = gel(an,1), G = gel(an,2), V = gel(an,3), aut = gel(an,4); GEN Sbad = gel(an,5); long n = itos(gel(an,6)), isreal = lg(an)<8 ? 0: !itos(gel(an,7)); GEN f = eulerf_bad(Sbad, p); if (!f) f = mkrfrac(gen_1,dirartin(nf, G, V, aut, p, 0)); f = gsubst(liftpol(f),1, rootsof1u_cx(n, prec)); if (isreal) f = real_i(f); return f; } static GEN char_expand(GEN conj, GEN ch) { long i, l = lg(conj); GEN V = cgetg(l, t_COL); for (i=1; i1 && typ(gel(ch,1))==t_MAT) chx = artin_charfromgens(gal, gmul(ch,mod)); else { if (lg(repr) != lg(ch)) pari_err_DIM("lfunartin"); chx = char_expand(conj, gmul(ch,mod)); } chx = handle_zeta(nf_get_degree(nf), chx, &tmult); ch = shallowextract(chx, repr); if (!gequal0(chx)) { GEN real = char_is_real(chx, gel(mod,1))? gen_0: gen_1; aut = nfgaloispermtobasis(nf, gal); V = gmul(char_expand(conj, galoischarpoly(gal, ch, o)), mod); bc = artin_badprimes(nf, gal, aut, chx); Ldata = mkvecn(6, tag(mkcoln(7, nf, gal, V, aut, gel(bc, 2), stoi(o), real), t_LFUN_ARTIN), real, artin_gamma(nf, gal, chx), gen_1, gel(bc,1), gen_0); } if (tmult==0 && Ldata==NULL) pari_err_TYPE("lfunartin",ch); if (tmult) { long i; if (Ldata==NULL) { Ldata = lfunzeta(); tmult--; } for(i=1; i<=tmult; i++) Ldata = lfunmul(Ldata, gen_1, bitprec); } return gerepilecopy(av, Ldata); } /* true nf */ static GEN lfunzetakinit_artin(GEN nf, GEN gal, GEN dom, long der, long bitprec) { GEN F, E, M, domain, To = galoischartable(gal), T = gel(To, 1); long i, o = itos(gel(To, 2)), l = lg(T); F = cgetg(l, t_VEC); E = cgetg(l, t_VECSMALL); for (i = 1; i < l; ++i) { GEN L = lfunartin(nf, gal, gel(T,i), o, bitprec); gel(F, i) = lfuninit(L, dom, der, bitprec); E[i] = char_dim(gel(T,i)); } domain = mkvec2(dom, mkvecsmall2(der, bitprec)); M = mkvec3(F, E, zero_zv(l-1)); return lfuninit_make(t_LDESC_PRODUCT, lfunzetak_i(nf), M, domain); } /********************************************************************/ /** High-level Constructors **/ /********************************************************************/ enum { t_LFUNMISC_POL, t_LFUNMISC_CHIQUAD, t_LFUNMISC_CHICONREY, t_LFUNMISC_CHIGEN, t_LFUNMISC_ELLINIT, t_LFUNMISC_ETAQUO, t_LFUNMISC_GCHAR, t_LFUNMISC_ABELREL }; static long lfundatatype(GEN data) { switch(typ(data)) { case t_INT: return t_LFUNMISC_CHIQUAD; case t_INTMOD: return t_LFUNMISC_CHICONREY; case t_POL: return t_LFUNMISC_POL; case t_VEC: switch(lg(data)) { case 17: return t_LFUNMISC_ELLINIT; case 10: return t_LFUNMISC_POL; case 3: if (typ(gel(data,1)) != t_VEC) break; return is_gchar_group(gel(data,1)) ? t_LFUNMISC_GCHAR : typ(gel(data,2))==t_MAT ? t_LFUNMISC_ABELREL : t_LFUNMISC_CHIGEN; } break; } return -1; } static GEN lfunmisc_to_ldata_i(GEN ldata, long shallow) { GEN x; if (is_linit(ldata)) ldata = linit_get_ldata(ldata); if (is_ldata(ldata) && is_tagged(ldata)) { if (!shallow) ldata = gcopy(ldata); checkldata(ldata); return ldata; } x = checknf_i(ldata); if (x) return lfunzetak(x); switch (lfundatatype(ldata)) { case t_LFUNMISC_POL: return lfunzetak(ldata); case t_LFUNMISC_CHIQUAD: return lfunchiquad(ldata); case t_LFUNMISC_CHICONREY: { GEN G = znstar0(gel(ldata,1), 1); return lfunchiZ(G, gel(ldata,2)); } case t_LFUNMISC_CHIGEN: { GEN G = gel(ldata,1), chi = gel(ldata,2); switch(nftyp(G)) { case typ_BIDZ: return lfunchiZ(G, chi); case typ_BNR: return lfunchigen(G, chi); } } break; case t_LFUNMISC_GCHAR: return lfungchar(gel(ldata,1), gel(ldata,2)); case t_LFUNMISC_ABELREL: return lfunabelrel(gel(ldata,1), gel(ldata,2), lg(ldata)==3? NULL: gel(ldata,3)); case t_LFUNMISC_ELLINIT: return lfunell(ldata); } if (shallow != 2) pari_err_TYPE("lfunmisc_to_ldata",ldata); return NULL; } GEN lfunmisc_to_ldata(GEN ldata) { return lfunmisc_to_ldata_i(ldata, 0); } GEN lfunmisc_to_ldata_shallow(GEN ldata) { return lfunmisc_to_ldata_i(ldata, 1); } GEN lfunmisc_to_ldata_shallow_i(GEN ldata) { return lfunmisc_to_ldata_i(ldata, 2); } /********************************************************************/ /** High-level an expansion **/ /********************************************************************/ /* van is the output of ldata_get_an: return a_1,...a_L at precision prec */ GEN ldata_vecan(GEN van, long L, long prec) { GEN an = gel(van, 2); long t = mael(van,1,1); pari_timer ti; if (DEBUGLEVEL >= 1) err_printf("Lfun: computing %ld coeffs, prec %ld, type %ld\n", L, prec, t); if (DEBUGLEVEL >= 2) timer_start(&ti); if (L < 0) L = 0; switch (t) { long n; case t_LFUN_GENERIC: an = vecan_closure(an, L, prec); n = lg(an)-1; if (n < L) { pari_warn(warner, "#an = %ld < %ld, results may be imprecise", n, L); an = shallowconcat(an, zerovec(L-n)); } break; case t_LFUN_CLOSURE0: pari_err_BUG("ldata_vecan: please call ldata_newprec");/*LCOV_EXCL_LINE*/ case t_LFUN_ZETA: an = const_vecsmall(L, 1); break; case t_LFUN_NF: an = dirzetak(an, stoi(L)); break; case t_LFUN_ELL: an = (ell_get_type(an) == t_ELL_Q) ? ellanQ_zv(an, L): ellan(an, L); break; case t_LFUN_KRONECKER: an = vecan_Kronecker(an, L); break; case t_LFUN_ABELREL: an = vecan_abelrel(an, L); break; case t_LFUN_CHIZ: an = vecan_chiZ(an, L, prec); break; case t_LFUN_CHIGEN: an = vecan_chigen(an, L, prec); break; case t_LFUN_HECKE: an = vecan_gchar(an, L, prec); break; case t_LFUN_ARTIN: an = vecan_artin(an, L, prec); break; case t_LFUN_ETA: an = vecan_eta(an, L); break; case t_LFUN_QF: an = vecan_qf(an, L); break; case t_LFUN_DIV: an = vecan_div(an, L, prec); break; case t_LFUN_MUL: an = vecan_mul(an, L, prec); break; case t_LFUN_CONJ: an = vecan_conj(an, L, prec); break; case t_LFUN_SYMPOW_ELL: an = vecan_ellsympow(an, L); break; case t_LFUN_GENUS2: an = vecan_genus2(an, L); break; case t_LFUN_HGM: an = hgmcoefs(gel(an,1), gel(an,2), L); break; case t_LFUN_MFCLOS: { GEN F = gel(an,1), E = gel(an,2), c = gel(an,3); an = mfcoefs(F,L,1) + 1; /* skip a_0 */ an[0] = evaltyp(t_VEC)|_evallg(L+1); an = mfvecembed(E, an); if (!isint1(c)) an = RgV_Rg_mul(an,c); break; } case t_LFUN_TWIST: an = vecan_twist(an, L, prec); break; case t_LFUN_SHIFT: an = vecan_shift(an, L, prec); break; default: pari_err_TYPE("ldata_vecan", van); } if (DEBUGLEVEL >= 2) timer_printf(&ti, "ldata_vecan"); return an; } /* shallow */ GEN ldata_newprec(GEN ldata, long prec) { GEN van = ldata_get_an(ldata), an = gel(van, 2); long t = mael(van,1,1); switch (t) { case t_LFUN_CLOSURE0: return closure2ldata(an, prec); case t_LFUN_HECKE: { GEN gc = gel(an, 1), chiw = gel(an, 2); gc = gcharnewprec(gc, prec); return gchari_lfun(gc, chiw, gen_0); /* chi in internal format */ } case t_LFUN_QF: { GEN eno = ldata_get_rootno(ldata); if (typ(eno)==t_REAL && realprec(eno) < prec) return lfunqf(an, prec); break; } } return ldata; } GEN ldata_eulerf(GEN van, GEN p, long prec) { GEN an = gel(van, 2), f = gen_0; long t = mael(van,1,1); switch (t) { case t_LFUN_GENERIC: f = eulerf_closure(an, p, prec); break; case t_LFUN_CLOSURE0: pari_err_BUG("ldata_vecan: please call ldata_newprec");/*LCOV_EXCL_LINE*/ case t_LFUN_ZETA: f = mkrfrac(gen_1,deg1pol(gen_m1, gen_1,0)); break; case t_LFUN_NF: f = eulerf_zetak(an, p); break; case t_LFUN_ELL: f = elleulerf(an, p); break; case t_LFUN_KRONECKER: f = mkrfrac(gen_1, deg1pol_shallow(stoi(-kronecker(an, p)), gen_1, 0)); break; case t_LFUN_ABELREL: f = eulerf_abelrel(an, p); break; case t_LFUN_CHIZ: f = eulerf_chiZ(an, p, prec); break; case t_LFUN_CHIGEN: f = eulerf_chigen(an, p, prec); break; case t_LFUN_HECKE: f = eulerf_gchar(an, p, prec); break; case t_LFUN_ARTIN: f = eulerf_artin(an, p, prec); break; case t_LFUN_DIV: f = eulerf_div(an, p, prec); break; case t_LFUN_MUL: f = eulerf_mul(an, p, prec); break; case t_LFUN_CONJ: f = eulerf_conj(an, p, prec); break; case t_LFUN_SYMPOW_ELL: f = eulerf_ellsympow(an, p); break; case t_LFUN_GENUS2: f = eulerf_genus2(an, p); break; case t_LFUN_TWIST: f = eulerf_twist(an, p, prec); break; case t_LFUN_SHIFT: f = eulerf_shift(an, p, prec); break; case t_LFUN_HGM: f = eulerf_hgm(an, p); break; default: f = NULL; break; } if (!f) pari_err_DOMAIN("lfuneuler", "L", "Euler product", strtoGENstr("unknown"), an); return f; } GEN lfuneuler(GEN ldata, GEN p, long prec) { pari_sp av = avma; if (typ(p)!=t_INT || signe(p)<=0) pari_err_TYPE("lfuneuler", p); ldata = ldata_newprec(lfunmisc_to_ldata_shallow(ldata), prec); return gerepilecopy(av, ldata_eulerf(ldata_get_an(ldata), p, prec)); } pari-2.17.2/src/basemath/subgroup.c0000644000175000017500000004056414567450071015573 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_subgrouplist typedef struct slist { struct slist *next; long *data; long prec; } slist; typedef struct { GEN cyc, gen; ulong count; slist *list; } sublist_t; /* SUBGROUPS * G = Gp x I, with Gp a p-Sylow (I assumed small). * Compute subgroups of I by recursive calls * Loop through subgroups Hp of Gp using Birkhoff's algorithm. * If (I is non trivial) * lift Hp to G (mul by exponent of I) * for each subgp of I, lift it to G (mult by exponent of Gp) * consider the group generated by the two subgroups (concat) * * type(H) = mu --> H = Z/p^mu[1] x ... x Z/p^mu[len(mu)] */ typedef struct subgp_iter { long *M, *L; /* mu = p-subgroup type, lambda = p-group type */ GEN *powlist; /* [i] = p^i, i = 0.. */ long *c, *maxc; GEN *a, *maxa, **g, **maxg; long *available; GEN **H; /* p-subgroup of type mu, in matrix form */ GEN cyc; /* cyclic factors of G */ GEN subq;/* subgrouplist(I) */ GEN subqpart; /* J in subq s.t [I:J][Gp:Hp] <= indexbound */ GEN bound; /* if != NULL, impose a "bound" on [G:H] (see boundtype) */ long boundtype; long countsub; /* number of subgroups of type M (so far) */ long count; /* number of p-subgroups so far [updated when M completed] */ GEN expoI; /* exponent of I */ long(*fun)(void*, GEN); /* callback applied to each subgroup */ void *fundata; /* data for fun */ long stop; } subgp_iter; /* MAX: [G:H] <= bound, EXACT: [G:H] = bound, TYPE: type(H) = bound */ enum { b_NONE, b_MAX, b_EXACT, b_TYPE }; #define len(x) (x)[0] #define setlen(x,l) len(x)=(l) static void printtyp(const long *typ) /*Used only for ddebugging */ { long i, l = len(typ); for (i=1; i<=l; i++) err_printf(" %ld ",typ[i]); err_printf("\n"); } /* compute conjugate partition of typ */ static long* conjugate(long *typ) { long *t, i, k = len(typ), l, last; if (!k) { t = new_chunk(1); setlen(t,0); return t; } l = typ[1]; t = new_chunk(l+2); t[1] = k; last = k; for (i=2; i<=l; i++) { while (typ[last] < i) last--; t[i] = last; } t[i] = 0; setlen(t,l); return t; } /* ----subgp_iter 'fun' attached to subgrouplist ------------- */ static void addcell(sublist_t *S, GEN H) { long *pt,i,j,L, n = lg(H)-1; slist *cell; L = 3; for (j=1; j<=n; j++) { /* H in HNF, largest entries are on diagonal */ long l = lgefint(gcoeff(H,j,j)); if (l > L) L = l; } L -= 2; cell = (slist*) pari_malloc(sizeof(slist) + ((n*(n+1)) >> 1) * sizeof(long) * L); S->list->next = cell; cell->data = pt = (long*) (cell + 1); cell->prec = L; for (j=1; j<=n; j++) for(i=1; i<=j; i++) { GEN z = gcoeff(H,i,j); long h, lz = lgefint(z) - 2; for (h = 0; h < L - lz; h++) *pt++ = 0; for (h = 0; h < lz; h++) *pt++ = z[h+2]; } S->list = cell; S->count++; } static long list_fun(void *E, GEN x) { sublist_t *S = (sublist_t*)E; GEN H = ZM_hnfmodid(x, S->cyc); if (!S->gen || subgroup_conductor_ok(H, S->gen)) addcell(S, H); return 0; } /* -------------------------------------------------------------- */ /* treat subgroup Hp (not in HNF, T->fun should do it if desired) */ static void treatsub(subgp_iter *T, GEN H) { long i; if (!T->subq) {T->stop = T->fun(T->fundata, H); T->countsub++; } else { /* not a p group, add the trivial part */ GEN Hp = gmul(T->expoI, H); /* lift H to G */ long n = lg(T->subqpart)-1; for (i=1; i<=n; i++) if (T->fun(T->fundata, shallowconcat(Hp, gel(T->subqpart,i)))) { T->stop = 1; break; } T->countsub += n; } } /* x a t_INT, x++. Could be optimized... */ static void inc(GEN x) { affii(addiu(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); set_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); set_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) )); set_avma(av); return; } if (l==1) /* imply t = 1 */ { GEN p1 = gtomat(T->powlist[T->L[1]-T->M[1]]); treatsub(T, p1); set_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); set_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); set_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 (!absequaliu(p1,T->countsub)) { err_printf(" alpha = %Ps\n",p1); pari_err_BUG("forsubgroup (alpha != countsub)"); } } } } } static void set_bound(subgp_iter *T, GEN B) { GEN b; T->bound = B; if (!B) { T->boundtype = b_NONE; return; } switch(typ(B)) { case t_INT: /* upper bound */ T->boundtype = b_MAX; break; case t_VEC: /* exact value */ b = gel(B,1); if (lg(B) != 2 || typ(b) != t_INT) pari_err_TYPE("subgroup", B); T->boundtype = b_EXACT; T->bound = b; break; case t_COL: /* exact type */ pari_err_IMPL("exact type in subgrouplist"); if (lg(B) > len(T->L)+1) pari_err_TYPE("subgroup",B); T->boundtype = b_TYPE; break; default: pari_err_TYPE("subgroup",B); } if (signe(T->bound) <= 0) pari_err_DOMAIN("subgroup", "index bound", "<=", gen_0, T->bound); } static GEN expand_sub(GEN x, long n) { long i,j, m = lg(x); GEN p = matid(n-1), q,c; for (i=1; icyc; long i, j, k, imax, lprim, n = lg(cyc); if (n == 1) { switch(T->boundtype) { case b_EXACT: if (!is_pm1(T->bound)) break; default: T->fun(T->fundata, cyc); } set_avma(av); return; } P = gel(Z_factor(cyc_get_expo(cyc)), 1); listL = cgetg_copy(P, &lprim); imax = k = 0; for (i=1; i k) { k = j; imax = i; } gel(listL,i) = L; } L = gel(listL,imax); p = gel(P,imax); k = L[1]; T->L = L; T->powlist = (GEN*)init_powlist(k, p); B = T->bound; if (lprim == 2) { T->subq = NULL; if (T->boundtype == b_EXACT) { (void)Z_pvalrem(T->bound,p,&B); if (!is_pm1(B)) { set_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); set_avma(av); } static GEN get_snf(GEN x, long *N) { GEN cyc; long n; switch(typ(x)) { case t_MAT: if (!RgM_isdiagonal(x)) return NULL; cyc = RgM_diagonal_shallow(x); break; case t_VEC: if (lg(x) == 4 && typ(gel(x,2)) == t_VEC) x = gel(x,2); case t_COL: cyc = leafcopy(x); break; default: return NULL; } *N = lg(cyc)-1; for (n = *N; n > 0; n--) /* take care of trailing 1s */ { GEN c = gel(cyc,n); if (typ(c) != t_INT || signe(c) <= 0) return NULL; if (!is_pm1(c)) break; } setlg(cyc, n+1); for ( ; n > 0; n--) { GEN c = gel(cyc,n); if (typ(c) != t_INT || signe(c) <= 0 || (n != *N && !dvdii(c, gel(cyc,n+1)))) return NULL; } return cyc; } void forsubgroup(void *E, long call(void*, GEN), GEN cyc, GEN bound) { subgp_iter T; long N; T.fun = call; T.cyc = get_snf(cyc,&N); if (!T.cyc) pari_err_TYPE("forsubgroup [not a finite group]",cyc); set_bound(&T, bound); T.fundata = E; T.stop = 0; subgroup_engine(&T); } void forsubgroup0(GEN cyc, GEN bound, GEN code) { EXPRVOID_WRAP(code, forsubgroup(EXPR_ARGVOID, cyc, bound)) } static GEN packtoi(long *pt, long L) { long i, l; GEN z; for (i=0; i 0; n--) if (!is_pm1(gel(c,n))) break; setlg(c, n+1); } static GEN update_cyc(subgp_iter *T, GEN cyc) { ulong k; switch(T->boundtype) { case b_EXACT: cyc = ZV_snf_gcd(cyc, T->bound); snf_clean(cyc); break; case b_MAX: if ((k = itos_or_0(T->bound))) { GEN fa = absZ_factor_limit_strict(cyc_get_expo(cyc), k + 1, NULL); cyc = T->cyc = ZV_snf_gcd(cyc, factorback(fa)); snf_clean(cyc); break; } } return cyc; } static GEN subgrouplist_i(GEN CYC, GEN bound, GEN expoI, GEN gen) { pari_sp av = avma; subgp_iter T; sublist_t S; slist *list, *sublist; long ii,i,j,nbsub,n,N = 0; /* -Wall */ GEN z, H, cyc; cyc = get_snf(CYC, &N); if (!cyc) pari_err_TYPE("subgrouplist [not a finite group]",CYC); set_bound(&T, bound); cyc = update_cyc(&T, cyc); n = lg(cyc)-1; /* not necessarily = N */ S.list = sublist = (slist*) pari_malloc(sizeof(slist)); S.cyc = cyc; S.gen = gen; S.count = 0; T.fun = &list_fun; T.fundata = (void*)&S; T.stop = 0; T.cyc = cyc; T.expoI = expoI; subgroup_engine(&T); nbsub = (long)S.count; set_avma(av); z = cgetg(nbsub+1,t_VEC); for (ii=1; ii<=nbsub; ii++) { long *pt, L; list = sublist; sublist = list->next; 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.17.2/src/basemath/ZV.c0000644000175000017500000012125314760123736014257 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" static int check_ZV(GEN x, long l) { long i; for (i=1; i 1 */ static long ZV_max_lg_i(GEN x, long m) { long i, l = lgefint(gel(x,1)); for (i = 2; i < m; i++) l = maxss(l, lgefint(gel(x,i))); return l; } long ZV_max_lg(GEN x) { long m = lg(x); return m == 1? 2: ZV_max_lg_i(x, m); } /* assume n > 1 and m > 1 */ static long ZM_max_lg_i(GEN x, long n, long m) { long j, l = ZV_max_lg_i(gel(x,1), m); for (j = 2; j < n; j++) l = maxss(l, ZV_max_lg_i(gel(x,j), m)); return l; } long ZM_max_lg(GEN x) { long n = lg(x), m; if (n == 1) return 2; m = lgcols(x); return m == 1? 2: ZM_max_lg_i(x, n, m); } /* assume m > 1 */ static long ZV_max_expi_i(GEN x, long m) { long i, prec = expi(gel(x,1)); for (i = 2; i < m; i++) prec = maxss(prec, expi(gel(x,i))); return prec; } long ZV_max_expi(GEN x) { long m = lg(x); return m == 1? 2: ZV_max_expi_i(x, m); } /* assume n > 1 and m > 1 */ static long ZM_max_expi_i(GEN x, long n, long m) { long j, prec = ZV_max_expi_i(gel(x,1), m); for (j = 2; j < n; j++) prec = maxss(prec, ZV_max_expi_i(gel(x,j), m)); return prec; } long ZM_max_expi(GEN x) { long n = lg(x), m; if (n == 1) return 2; m = lgcols(x); return m == 1? 2: ZM_max_expi_i(x, n, m); } GEN ZM_supnorm(GEN x) { long i, j, h, lx = lg(x); GEN s = gen_0; if (lx == 1) return gen_1; h = lgcols(x); for (j=1; j 0) s = c; } } return absi(s); } /********************************************************************/ /** **/ /** MULTIPLICATION **/ /** **/ /********************************************************************/ /* x nonempty ZM, y a compatible nc (dimension > 0). */ static GEN ZM_nc_mul_i(GEN x, GEN y, long c, long l) { long i, j; pari_sp av; GEN z = cgetg(l,t_COL), s; for (i=1; i 0). */ static GEN ZM_zc_mul_i(GEN x, GEN y, long c, long l) { long i, j; GEN z = cgetg(l,t_COL); for (i=1; i 0). */ GEN zv_ZM_mul(GEN x, GEN y) { long i,j, lx = lg(x), ly = lg(y); GEN z; if (lx == 1) return zerovec(ly-1); z = cgetg(ly,t_VEC); for (j=1; j 0). */ GEN ZM_zm_mul(GEN x, GEN y) { long j, c, l = lg(x), ly = lg(y); GEN z = cgetg(ly, t_MAT); if (l == 1) return z; c = lgcols(x); for (j = 1; j < ly; j++) gel(z,j) = ZM_zc_mul_i(x, gel(y,j), l,c); return z; } /* x ZM, y a compatible zn (dimension > 0). */ GEN ZM_nm_mul(GEN x, GEN y) { long j, c, l = lg(x), ly = lg(y); GEN z = cgetg(ly, t_MAT); if (l == 1) return z; c = lgcols(x); for (j = 1; j < ly; j++) gel(z,j) = ZM_nc_mul_i(x, gel(y,j), l,c); return z; } /* Strassen-Winograd algorithm */ /* Return A[ma+1..ma+da, na+1..na+ea] - B[mb+1..mb+db, nb+1..nb+eb] * as an (m x n)-matrix, padding the input with zeroes as necessary. */ static GEN add_slices(long m, long n, GEN A, long ma, long da, long na, long ea, GEN B, long mb, long db, long nb, long eb) { long min_d = minss(da, db), min_e = minss(ea, eb), i, j; GEN M = cgetg(n + 1, t_MAT), C; for (j = 1; j <= min_e; j++) { gel(M, j) = C = cgetg(m + 1, t_COL); for (i = 1; i <= min_d; i++) gel(C, i) = addii(gcoeff(A, ma + i, na + j), gcoeff(B, mb + i, nb + j)); for (; i <= da; i++) gel(C, i) = gcoeff(A, ma + i, na + j); for (; i <= db; i++) gel(C, i) = gcoeff(B, mb + i, nb + j); for (; i <= m; i++) gel(C, i) = gen_0; } for (; j <= ea; j++) { gel(M, j) = C = cgetg(m + 1, t_COL); for (i = 1; i <= da; i++) gel(C, i) = gcoeff(A, ma + i, na + j); for (; i <= m; i++) gel(C, i) = gen_0; } for (; j <= eb; j++) { gel(M, j) = C = cgetg(m + 1, t_COL); for (i = 1; i <= db; i++) gel(C, i) = gcoeff(B, mb + i, nb + j); for (; i <= m; i++) gel(C, i) = gen_0; } for (; j <= n; j++) gel(M, j) = zerocol(m); return M; } /* Return A[ma+1..ma+da, na+1..na+ea] - B[mb+1..mb+db, nb+1..nb+eb] * as an (m x n)-matrix, padding the input with zeroes as necessary. */ static GEN subtract_slices(long m, long n, GEN A, long ma, long da, long na, long ea, GEN B, long mb, long db, long nb, long eb) { long min_d = minss(da, db), min_e = minss(ea, eb), i, j; GEN M = cgetg(n + 1, t_MAT), C; for (j = 1; j <= min_e; j++) { gel(M, j) = C = cgetg(m + 1, t_COL); for (i = 1; i <= min_d; i++) gel(C, i) = subii(gcoeff(A, ma + i, na + j), gcoeff(B, mb + i, nb + j)); for (; i <= da; i++) gel(C, i) = gcoeff(A, ma + i, na + j); for (; i <= db; i++) gel(C, i) = negi(gcoeff(B, mb + i, nb + j)); for (; i <= m; i++) gel(C, i) = gen_0; } for (; j <= ea; j++) { gel(M, j) = C = cgetg(m + 1, t_COL); for (i = 1; i <= da; i++) gel(C, i) = gcoeff(A, ma + i, na + j); for (; i <= m; i++) gel(C, i) = gen_0; } for (; j <= eb; j++) { gel(M, j) = C = cgetg(m + 1, t_COL); for (i = 1; i <= db; i++) gel(C, i) = negi(gcoeff(B, mb + i, nb + j)); for (; i <= m; i++) gel(C, i) = gen_0; } for (; j <= n; j++) gel(M, j) = zerocol(m); return M; } static GEN ZM_mul_i(GEN x, GEN y, long l, long lx, long ly); /* Strassen-Winograd matrix product A (m x n) * B (n x p) */ static GEN ZM_mul_sw(GEN A, GEN B, long m, long n, long p) { pari_sp av = avma; long m1 = (m + 1)/2, m2 = m/2, n1 = (n + 1)/2, n2 = n/2, p1 = (p + 1)/2, p2 = p/2; GEN A11, A12, A22, B11, B21, B22, S1, S2, S3, S4, T1, T2, T3, T4, M1, M2, M3, M4, M5, M6, M7, V1, V2, V3, C11, C12, C21, C22, C; T2 = subtract_slices(n1, p2, B, 0, n1, p1, p2, B, n1, n2, p1, p2); S1 = subtract_slices(m2, n1, A, m1, m2, 0, n1, A, 0, m2, 0, n1); M2 = ZM_mul_i(S1, T2, m2 + 1, n1 + 1, p2 + 1); if (gc_needed(av, 1)) gerepileall(av, 2, &T2, &M2); /* destroy S1 */ T3 = subtract_slices(n1, p1, T2, 0, n1, 0, p2, B, 0, n1, 0, p1); if (gc_needed(av, 1)) gerepileall(av, 2, &M2, &T3); /* destroy T2 */ S2 = add_slices(m2, n1, A, m1, m2, 0, n1, A, m1, m2, n1, n2); T1 = subtract_slices(n1, p1, B, 0, n1, p1, p2, B, 0, n1, 0, p2); M3 = ZM_mul_i(S2, T1, m2 + 1, n1 + 1, p2 + 1); if (gc_needed(av, 1)) gerepileall(av, 4, &M2, &T3, &S2, &M3); /* destroy T1 */ S3 = subtract_slices(m1, n1, S2, 0, m2, 0, n1, A, 0, m1, 0, n1); if (gc_needed(av, 1)) gerepileall(av, 4, &M2, &T3, &M3, &S3); /* destroy S2 */ A11 = matslice(A, 1, m1, 1, n1); B11 = matslice(B, 1, n1, 1, p1); M1 = ZM_mul_i(A11, B11, m1 + 1, n1 + 1, p1 + 1); if (gc_needed(av, 1)) gerepileall(av, 5, &M2, &T3, &M3, &S3, &M1); /* destroy A11, B11 */ A12 = matslice(A, 1, m1, n1 + 1, n); B21 = matslice(B, n1 + 1, n, 1, p1); M4 = ZM_mul_i(A12, B21, m1 + 1, n2 + 1, p1 + 1); if (gc_needed(av, 1)) gerepileall(av, 6, &M2, &T3, &M3, &S3, &M1, &M4); /* destroy A12, B21 */ C11 = add_slices(m1, p1, M1, 0, m1, 0, p1, M4, 0, m1, 0, p1); if (gc_needed(av, 1)) gerepileall(av, 6, &M2, &T3, &M3, &S3, &M1, &C11); /* destroy M4 */ M5 = ZM_mul_i(S3, T3, m1 + 1, n1 + 1, p1 + 1); S4 = subtract_slices(m1, n2, A, 0, m1, n1, n2, S3, 0, m1, 0, n2); if (gc_needed(av, 1)) gerepileall(av, 7, &M2, &T3, &M3, &M1, &C11, &M5, &S4); /* destroy S3 */ T4 = add_slices(n2, p1, B, n1, n2, 0, p1, T3, 0, n2, 0, p1); if (gc_needed(av, 1)) gerepileall(av, 7, &M2, &M3, &M1, &C11, &M5, &S4, &T4); /* destroy T3 */ V1 = subtract_slices(m1, p1, M1, 0, m1, 0, p1, M5, 0, m1, 0, p1); if (gc_needed(av, 1)) gerepileall(av, 6, &M2, &M3, &S4, &T4, &C11, &V1); /* destroy M1, M5 */ B22 = matslice(B, n1 + 1, n, p1 + 1, p); M6 = ZM_mul_i(S4, B22, m1 + 1, n2 + 1, p2 + 1); if (gc_needed(av, 1)) gerepileall(av, 6, &M2, &M3, &T4, &C11, &V1, &M6); /* destroy S4, B22 */ A22 = matslice(A, m1 + 1, m, n1 + 1, n); M7 = ZM_mul_i(A22, T4, m2 + 1, n2 + 1, p1 + 1); if (gc_needed(av, 1)) gerepileall(av, 6, &M2, &M3, &C11, &V1, &M6, &M7); /* destroy A22, T4 */ V3 = add_slices(m1, p2, V1, 0, m1, 0, p2, M3, 0, m2, 0, p2); C12 = add_slices(m1, p2, V3, 0, m1, 0, p2, M6, 0, m1, 0, p2); if (gc_needed(av, 1)) gerepileall(av, 6, &M2, &M3, &C11, &V1, &M7, &C12); /* destroy V3, M6 */ V2 = add_slices(m2, p1, V1, 0, m2, 0, p1, M2, 0, m2, 0, p2); if (gc_needed(av, 1)) gerepileall(av, 5, &M3, &C11, &M7, &C12, &V2); /* destroy V1, M2 */ C21 = add_slices(m2, p1, V2, 0, m2, 0, p1, M7, 0, m2, 0, p1); if (gc_needed(av, 1)) gerepileall(av, 5, &M3, &C11, &C12, &V2, &C21); /* destroy M7 */ C22 = add_slices(m2, p2, V2, 0, m2, 0, p2, M3, 0, m2, 0, p2); if (gc_needed(av, 1)) gerepileall(av, 4, &C11, &C12, &C21, &C22); /* destroy V2, M3 */ C = shallowconcat(vconcat(C11, C21), vconcat(C12, C22)); return gerepilecopy(av, C); } /* x[i,]*y. Assume lg(x) > 1 and 0 < i < lgcols(x) */ static GEN ZMrow_ZC_mul_i(GEN x, GEN y, long i, long lx) { pari_sp av = avma; GEN c = mulii(gcoeff(x,i,1), gel(y,1)), ZERO = gen_0; long k; for (k = 2; k < lx; k++) { GEN t = mulii(gcoeff(x,i,k), gel(y,k)); if (t != ZERO) c = addii(c, t); } return gerepileuptoint(av, c); } GEN ZMrow_ZC_mul(GEN x, GEN y, long i) { return ZMrow_ZC_mul_i(x, y, i, lg(x)); } /* return x * y, 1 < lx = lg(x), l = lgcols(x) */ static GEN ZM_ZC_mul_i(GEN x, GEN y, long lx, long l) { GEN z = cgetg(l,t_COL); long i; for (i=1; i B */ static long sw_bound(long s) { return s > 60 ? 2: s > 25 ? 4: s > 15 ? 8 : s > 8 ? 16 : 32; } /* assume lx > 1 and ly > 1; x is (l-1) x (lx-1), y is (lx-1) x (ly-1). * Return x * y */ static GEN ZM_mul_i(GEN x, GEN y, long l, long lx, long ly) { long sx, sy, B; #ifdef LONG_IS_64BIT /* From Flm_mul_i */ long Flm_sw_bound = 70; #else long Flm_sw_bound = 120; #endif if (l == 1) return zeromat(0, ly-1); if (lx==2 && l==2 && ly==2) { retmkmat(mkcol(mulii(gcoeff(x,1,1), gcoeff(y,1,1)))); } if (lx==3 && l==3 && ly==3) return ZM2_mul(x, y); sx = ZM_max_lg_i(x, lx, l); sy = ZM_max_lg_i(y, ly, lx); /* Use modular reconstruction if Flm_mul would use Strassen and the input * sizes look balanced */ if (lx > Flm_sw_bound && ly > Flm_sw_bound && l > Flm_sw_bound && sx <= 10 * sy && sy <= 10 * sx) return ZM_mul_fast(x,y, lx,ly, sx,sy); B = sw_bound(minss(sx, sy)); if (l <= B || lx <= B || ly <= B) return ZM_mul_classical(x, y, l, lx, ly); else return ZM_mul_sw(x, y, l - 1, lx - 1, ly - 1); } GEN ZM_mul(GEN x, GEN y) { long lx = lg(x), ly = lg(y); if (ly == 1) return cgetg(1,t_MAT); if (lx == 1) return zeromat(0, ly-1); return ZM_mul_i(x, y, lgcols(x), lx, ly); } static GEN ZM_sqr_slice(GEN A, GEN P, GEN *mod) { pari_sp av = avma; long i, n = lg(P)-1; GEN H, T; if (n == 1) { ulong p = uel(P,1); GEN a = ZM_to_Flm(A, p); GEN Hp = gerepileupto(av, Flm_to_ZM(Flm_sqr(a, p))); *mod = utoi(p); return Hp; } T = ZV_producttree(P); A = ZM_nv_mod_tree(A, P, T); H = cgetg(n+1, t_VEC); for(i=1; i <= n; i++) gel(H,i) = Flm_sqr(gel(A,i), P[i]); H = nmV_chinese_center_tree_seq(H, P, T, ZV_chinesetree(P, T)); *mod = gmael(T, lg(T)-1, 1); return gc_all(av, 2, &H, mod); } GEN ZM_sqr_worker(GEN P, GEN A) { GEN V = cgetg(3, t_VEC); gel(V,1) = ZM_sqr_slice(A, P, &gel(V,2)); return V; } static GEN ZM_sqr_fast(GEN A, long l, long s) { pari_sp av = avma; forprime_t S; GEN H, worker; long h; if (s == 2) return zeromat(l-1,l-1); h = 1 + (2*s - 4) * BITS_IN_LONG + expu(l-1); init_modular_big(&S); worker = snm_closure(is_entry("_ZM_sqr_worker"), mkvec(A)); H = gen_crt("ZM_sqr", worker, &S, NULL, h, 0, NULL, nmV_chinese_center, FpM_center); return gerepileupto(av, H); } GEN QM_mul(GEN x, GEN y) { GEN dx, nx = Q_primitive_part(x, &dx); GEN dy, ny = Q_primitive_part(y, &dy); GEN z = ZM_mul(nx, ny); if (dx || dy) { GEN d = dx ? dy ? gmul(dx, dy): dx : dy; if (!gequal1(d)) z = ZM_Q_mul(z, d); } return z; } GEN QM_sqr(GEN x) { GEN dx, nx = Q_primitive_part(x, &dx); GEN z = ZM_sqr(nx); if (dx) z = ZM_Q_mul(z, gsqr(dx)); return z; } GEN QM_QC_mul(GEN x, GEN y) { GEN dx, nx = Q_primitive_part(x, &dx); GEN dy, ny = Q_primitive_part(y, &dy); GEN z = ZM_ZC_mul(nx, ny); if (dx || dy) { GEN d = dx ? dy ? gmul(dx, dy): dx : dy; if (!gequal1(d)) z = ZC_Q_mul(z, d); } return z; } /* assume result is symmetric */ GEN ZM_multosym(GEN x, GEN y) { long j, lx, ly = lg(y); GEN M; if (ly == 1) return cgetg(1,t_MAT); lx = lg(x); /* = lgcols(y) */ if (lx == 1) return cgetg(1,t_MAT); /* ly = lgcols(x) */ M = 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); } /* x~ * y, assuming result is symmetric */ GEN ZM_transmultosym(GEN x, GEN y) { long i, j, l, ly = lg(y); GEN M; if (ly == 1) return cgetg(1,t_MAT); /* lg(x) = ly */ l = lgcols(y); /* = lgcols(x) */ M = cgetg(ly, t_MAT); for (i=1; i 1; x is (l-1) x (l-1), return x^2. * FIXME: we ultimately rely on Strassen-Winograd which uses 7M + 15A. * Should use Bodrato's variant of Winograd, using 3M + 4S + 11A */ static GEN ZM_sqr_i(GEN x, long l) { long s; if (l == 2) { retmkmat(mkcol(sqri(gcoeff(x,1,1)))); } if (l == 3) return ZM2_sqr(x); s = ZM_max_lg_i(x, l, l); if (l > 70) return ZM_sqr_fast(x, l, s); if (l <= sw_bound(s)) return ZM_mul_classical(x, x, l, l, l); else return ZM_mul_sw(x, x, l - 1, l - 1, l - 1); } GEN ZM_sqr(GEN x) { long lx=lg(x); if (lx==1) return cgetg(1,t_MAT); return ZM_sqr_i(x, lx); } GEN ZM_ZC_mul(GEN x, GEN y) { long lx = lg(x); return lx==1? cgetg(1,t_COL): ZM_ZC_mul_i(x, y, lx, lgcols(x)); } GEN ZC_Z_div(GEN x, GEN c) { pari_APPLY_type(t_COL, Qdivii(gel(x,i), c)) } GEN ZM_Z_div(GEN x, GEN c) { pari_APPLY_same(ZC_Z_div(gel(x, i), c)) } GEN ZC_Q_mul(GEN A, GEN z) { pari_sp av = avma; long i, l = lg(A); GEN d, n, Ad, B, u; if (typ(z)==t_INT) return ZC_Z_mul(A,z); n = gel(z, 1); d = gel(z, 2); Ad = FpC_red(A, d); u = gcdii(d, FpV_factorback(Ad, NULL, d)); B = cgetg(l, t_COL); if (equali1(u)) { for(i=1; i 0)? ZC_copy(x): ZC_neg(x); pari_APPLY_type(t_COL, mulii(gel(x,i), c)) } GEN ZC_z_mul(GEN x, long c) { if (!c) return zerocol(lg(x)-1); if (c == 1) return ZC_copy(x); if (c ==-1) return ZC_neg(x); pari_APPLY_type(t_COL, mulsi(c, gel(x,i))) } GEN zv_z_mul(GEN x, long n) { pari_APPLY_long(x[i]*n) } /* return a ZM */ GEN nm_Z_mul(GEN X, GEN c) { long i, j, h, l = lg(X), s = signe(c); GEN A; if (l == 1) return cgetg(1, t_MAT); h = lgcols(X); if (!s) return zeromat(h-1, l-1); if (is_pm1(c)) { if (s > 0) return Flm_to_ZM(X); X = Flm_to_ZM(X); ZM_togglesign(X); return X; } A = cgetg(l, t_MAT); for (j = 1; j < l; j++) { GEN a = cgetg(h, t_COL), x = gel(X, j); for (i = 1; i < h; i++) gel(a,i) = muliu(c, x[i]); gel(A,j) = a; } return A; } GEN ZM_Z_mul(GEN X, GEN c) { long i, j, h, l = lg(X); GEN A; if (l == 1) return cgetg(1, t_MAT); h = lgcols(X); if (!signe(c)) return zeromat(h-1, l-1); if (is_pm1(c)) return (signe(c) > 0)? ZM_copy(X): ZM_neg(X); A = cgetg(l, t_MAT); for (j = 1; j < l; j++) { GEN a = cgetg(h, t_COL), x = gel(X, j); for (i = 1; i < h; i++) gel(a,i) = mulii(c, gel(x,i)); gel(A,j) = a; } return A; } void ZC_lincomb1_inplace_i(GEN X, GEN Y, GEN v, long n) { long i; for (i = n; i; i--) gel(X,i) = addmulii_inplace(gel(X,i), gel(Y,i), v); } /* X <- X + v Y (elementary col operation) */ void ZC_lincomb1_inplace(GEN X, GEN Y, GEN v) { if (lgefint(v) != 2) return ZC_lincomb1_inplace_i(X, Y, v, lg(X)-1); } void Flc_lincomb1_inplace(GEN X, GEN Y, ulong v, ulong q) { long i; if (!v) return; /* v = 0 */ for (i = lg(X)-1; i; i--) X[i] = Fl_add(X[i], Fl_mul(Y[i], v, q), q); } /* X + v Y, wasteful if (v = 0) */ static GEN ZC_lincomb1(GEN v, GEN x, GEN y) { pari_APPLY_type(t_COL, addmulii(gel(x,i), gel(y,i), v)) } /* -X + vY */ static GEN ZC_lincomb_1(GEN v, GEN x, GEN y) { pari_APPLY_type(t_COL, mulsubii(gel(y,i), v, gel(x,i))) } /* X,Y compatible ZV; u,v in Z. Returns A = u*X + v*Y */ GEN ZC_lincomb(GEN u, GEN v, GEN X, GEN Y) { long su, sv; GEN A; su = signe(u); if (!su) return ZC_Z_mul(Y, v); sv = signe(v); if (!sv) return ZC_Z_mul(X, u); if (is_pm1(v)) { if (is_pm1(u)) { if (su != sv) A = ZC_sub(X, Y); else A = ZC_add(X, Y); if (su < 0) ZV_togglesign(A); /* in place but was created above */ } else { if (sv > 0) A = ZC_lincomb1 (u, Y, X); else A = ZC_lincomb_1(u, Y, X); } } else if (is_pm1(u)) { if (su > 0) A = ZC_lincomb1 (v, X, Y); else A = ZC_lincomb_1(v, X, Y); } else { /* not cgetg_copy: x may be a t_VEC */ long i, lx = lg(X); A = cgetg(lx,t_COL); for (i=1; i 0) gel(M,l) = negi(gel(M,l)); } GEN ZC_neg(GEN x) { pari_APPLY_type(t_COL, negi(gel(x,i))) } GEN zv_neg(GEN x) { pari_APPLY_long(-x[i]) } GEN zv_neg_inplace(GEN M) { long l = lg(M); while (--l > 0) M[l] = -M[l]; return M; } GEN zv_abs(GEN x) { pari_APPLY_ulong(labs(x[i])) } GEN ZM_neg(GEN x) { pari_APPLY_same(ZC_neg(gel(x,i))) } void ZV_togglesign(GEN M) { long l = lg(M); while (--l > 0) togglesign_safe(&gel(M,l)); } void ZM_togglesign(GEN M) { long l = lg(M); while (--l > 0) ZV_togglesign(gel(M,l)); } /********************************************************************/ /** **/ /** "DIVISION" mod HNF **/ /** **/ /********************************************************************/ /* Reduce ZC x modulo ZM y in HNF, may return x itself (not a copy) */ GEN ZC_hnfremdiv(GEN x, GEN y, GEN *Q) { long i, l = lg(x); GEN q; if (Q) *Q = cgetg(l,t_COL); if (l == 1) return cgetg(1,t_COL); for (i = l-1; i>0; i--) { q = diviiround(gel(x,i), gcoeff(y,i,i)); if (signe(q)) { togglesign(q); x = ZC_lincomb(gen_1, q, x, gel(y,i)); } if (Q) gel(*Q, i) = q; } return x; } /* x = y Q + R, may return some columns of x (not copies) */ GEN ZM_hnfdivrem(GEN x, GEN y, GEN *Q) { long lx = lg(x), i; GEN R = cgetg(lx, t_MAT); if (Q) { GEN q = cgetg(lx, t_MAT); *Q = q; for (i=1; i 0) if (V[l]) return 0; return 1; } int ZV_equal0(GEN V) { long l = lg(V); while (--l > 0) if (signe(gel(V,l))) return 0; return 1; } int ZMrow_equal0(GEN V, long i) { long l = lg(V); while (--l > 0) if (signe(gcoeff(V,i,l))) return 0; return 1; } static int ZV_equal_lg(GEN V, GEN W, long l) { while (--l > 0) if (!equalii(gel(V,l), gel(W,l))) return 0; return 1; } int ZV_equal(GEN V, GEN W) { long l = lg(V); if (lg(W) != l) return 0; return ZV_equal_lg(V, W, l); } int ZM_equal(GEN A, GEN B) { long i, m, l = lg(A); if (lg(B) != l) return 0; if (l == 1) return 1; m = lgcols(A); if (lgcols(B) != m) return 0; for (i = 1; i < l; i++) if (!ZV_equal_lg(gel(A,i), gel(B,i), m)) return 0; return 1; } int ZM_equal0(GEN A) { long i, j, m, l = lg(A); if (l == 1) return 1; m = lgcols(A); for (j = 1; j < l; j++) for (i = 1; i < m; i++) if (signe(gcoeff(A,i,j))) return 0; return 1; } int zv_equal(GEN V, GEN W) { long l = lg(V); if (lg(W) != l) return 0; while (--l > 0) if (V[l] != W[l]) return 0; return 1; } int zvV_equal(GEN V, GEN W) { long l = lg(V); if (lg(W) != l) return 0; while (--l > 0) if (!zv_equal(gel(V,l),gel(W,l))) return 0; return 1; } int ZM_ishnf(GEN x) { long i,j, lx = lg(x); for (i=1; i=0) return 0; } } return 1; } int ZM_isidentity(GEN x) { long i,j, lx = lg(x); if (lx == 1) return 1; if (lx != lgcols(x)) return 0; for (j=1; j> 1; V = cgetg(m + (odd(n)? 2: 1), t_VEC); for (k = n; k; k--) /* start from the end: v is usually sorted */ if (v[k] & HIGHMASK) { stop = 1; break; } while (!stop) { /* HACK: handle V as a t_VECSMALL; gain a few iterations */ for (k = 1; k <= m; k++) { V[k] = uel(v,k<<1) * uel(v,(k<<1)-1); if (V[k] & HIGHMASK) stop = 1; /* last "free" iteration */ } if (odd(n)) { if (n == 1) { set_avma(av); return utoi(v[1]); } V[++m] = v[n]; } v = V; n = m; m = n >> 1; } /* n > 1; m > 0 */ if (n == 2) { set_avma(av); return muluu(v[1], v[2]); } for (k = 1; k <= m; k++) gel(V,k) = muluu(v[k<<1], v[(k<<1)-1]); if (odd(n)) gel(V, ++m) = utoipos(v[n]); setlg(V, m+1); /* HACK: now V is a bona fide t_VEC */ return gerepileuptoint(av, gen_product(V, NULL, &_mulii)); } GEN vecsmall_prod(GEN v) { pari_sp av = avma; long k, m, n = lg(v)-1; GEN V; switch (n) { case 0: return gen_1; case 1: return stoi(v[1]); case 2: return mulss(v[1], v[2]); } m = n >> 1; V = cgetg(m + (odd(n)? 2: 1), t_VEC); for (k = 1; k <= m; k++) gel(V,k) = mulss(v[k<<1], v[(k<<1)-1]); if (odd(n)) gel(V,k) = stoi(v[n]); return gerepileuptoint(av, gen_product(V, NULL, &_mulii)); } GEN ZV_prod(GEN v) { pari_sp av = avma; long i, l = lg(v); GEN n; if (l == 1) return gen_1; if (l > 7) return gerepileuptoint(av, gen_product(v, NULL, _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; } /* assumes no overflow and 0 <= n <= #v */ long zv_sumpart(GEN v, long n) { long i, p; if (!n) return 0; p = v[1]; for (i = 2; i <= n; i++) p += v[i]; return p; } 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.17.2/src/basemath/ellrank.c0000644000175000017500000016771414760123736015364 0ustar billbill/* Copyright (C) 2020 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_ellrank static long LIM1 = 10000; static long LIMTRIV = 10000; /*******************************************************************/ /* NFHILBERT and LOCAL SOLUBILITY */ /* adapted from Denis Simon's original C implementation */ /*******************************************************************/ /* p > 2, T ZX, p prime, x t_INT */ static long lemma6(GEN T, GEN p, long nu, GEN x) { long la, mu; GEN y = ZX_Z_eval(T, x); if (Zp_issquare(y, p)) return 1; la = Z_pval(y, p); y = ZX_Z_eval(ZX_deriv(T), x); if (!signe(y)) return la >= (nu<<1)? 0: -1; mu = Z_pval(y,p); if (la > (mu<<1)) return 1; return (la >= (nu<<1) && mu >= nu)? 0: -1; } static long lemma7_aux(long nu, long la, long r) { long nu2 = nu << 1; return (la >= nu2 || (la == nu2 - 2 && r == 1))? 0: -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 r, la, mu; GEN y = ZX_Z_eval(T, x); if (!signe(y)) return 1; la = Z_lvalrem(y, 2, &y); r = Mod8(y); if (!odd(la) && r == 1) return 1; r &= 3; /* T(x) / 2^oo mod 4 */ y = ZX_Z_eval(ZX_deriv(T), x); if (!signe(y)) return lemma7_aux(nu, la, r); mu = vali(y); if (la > mu<<1) return 1; if (nu <= mu) return lemma7_aux(nu, la, r); /* la <= 2mu, mu < nu */ if (!odd(la) && mu + nu - la <= (r == 1? 2: 1)) return 1; 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, btop; GEN x, pnup; res = absequaliu(p,2)? lemma7(T,nu,x0): lemma6(T,p,nu,x0); set_avma(av); if (res== 1) return 1; if (res==-1) return 0; x = x0; pnup = mulii(pnu,p); btop = avma; for (i=0; i < itos(p); i++) { x = addii(x,pnu); if (zpsol(T,p,nu+1,pnup,x)) return gc_long(av,1); if (gc_needed(btop, 2)) { x = gerepileupto(btop, x); if (DEBUGMEM > 1) pari_warn(warnmem, "hyperell_locally_soluble: %ld/%Ps",i,p); } } return gc_long(av,0); } /* return 1 if equation y^2=T(x) has a rational p-adic solution (possibly * infinite), 0 otherwise. */ long hyperell_locally_soluble(GEN T,GEN p) { pari_sp av = avma; long res; if (typ(T)!=t_POL) pari_err_TYPE("hyperell_locally_soluble",T); if (typ(p)!=t_INT) pari_err_TYPE("hyperell_locally_soluble",p); RgX_check_ZX(T, "hyperell_locally_soluble"); res = zpsol(T,p,0,gen_1,gen_0) || zpsol(RgX_recip_i(T), p, 1, p, gen_0); return gc_long(av, 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 T, p, modpr = zk_to_Fq_init(nf, &pr,&T,&p); return Fq_issquare(nf_to_Fq(nf,t,modpr), T, p)? 1: -1; } /* quad_char(x), x in Z, nonzero mod p */ static long Z_quad_char(GEN x, GEN pr) { long f = pr_get_f(pr); if (!odd(f)) return 1; return kronecker(x, pr_get_p(pr)); } /* (pr,2) = 1. return 1 if x in Z_K is a square in Z_{K_pr}, 0 otherwise. * modpr = zkmodprinit(nf,pr) */ static long psquarenf(GEN nf,GEN x,GEN pr,GEN modpr) { pari_sp av = avma; GEN p = pr_get_p(pr); long v; x = nf_to_scalar_or_basis(nf, x); if (typ(x) == t_INT) { if (!signe(x)) return 1; v = Z_pvalrem(x, p, &x) * pr_get_e(pr); if (v&1) return 0; v = (Z_quad_char(x, pr) == 1); } else { v = ZC_nfvalrem(x, pr, &x); if (v&1) return 0; v = (quad_char(nf, x, modpr) == 1); } return gc_long(av,v); } static long ZV_iseven(GEN zlog) { long i, l = lg(zlog); for (i = 1; i < l; i++) if (mpodd(gel(zlog,i))) return 0; return 1; } /* pr | 2, project to principal units (trivializes later discrete log) */ static GEN to_principal_unit(GEN nf, GEN x, GEN pr, GEN sprk) { if (pr_get_f(pr) != 1) { GEN prk = gel(sprk,3); x = nfpowmodideal(nf, x, gmael(sprk,5,1), prk); } return x; } /* pr | 2. Return 1 if x in Z_K is square in Z_{K_pr}, 0 otherwise */ static int psquare2nf(GEN nf, GEN x, GEN pr, GEN sprk) { long v = nfvalrem(nf, x, pr, &x); if (v == LONG_MAX) return 1; /* x = 0 */ /* (x,pr) = 1 */ if (odd(v)) return 0; x = to_principal_unit(nf, x, pr, sprk); /* = 1 mod pr */ return ZV_iseven(sprk_log_prk1(nf, x, sprk)); } /* pr above an odd prime */ static long lemma6nf(GEN nf, GEN T, GEN pr, long nu, GEN x, GEN modpr) { long la, mu; GEN y = nfpoleval(nf, T, x); if (psquarenf(nf,y,pr,modpr)) return 1; la = nfval(nf, y, pr); y = nfpoleval(nf, RgX_deriv(T), x); if (gequal0(y)) return la >= (nu<<1)? 0: -1; mu = nfval(nf, y, pr); if (la > (mu<<1)) return 1; return (la >= (nu<<1) && mu >= nu)? 0: -1; } /* pr above 2 */ static long lemma7nf(GEN nf, GEN T, GEN pr, long nu, GEN x, GEN sprk) { long i, res, la, mu, q, e, v; GEN M, y, gpx, loggx = NULL, gx = nfpoleval(nf, T, x); la = nfvalrem(nf, gx, pr, &gx); /* gx /= pi^la, pi a pr-uniformizer */ if (la == LONG_MAX) return 1; if (!odd(la)) { gx = to_principal_unit(nf, gx, pr, sprk); /* now 1 mod pr */ loggx = sprk_log_prk1(nf, gx, sprk); /* cheap */ if (ZV_iseven(loggx)) return 1; } gpx = nfpoleval(nf, RgX_deriv(T), x); mu = gequal0(gpx)? la+nu+1 /* oo */: nfval(nf,gpx,pr); if (la > (mu << 1)) return 1; if (nu > mu) { if (odd(la)) return -1; q = mu+nu-la; res = 1; } else { q = (nu << 1) - la; if (q <= 0) return 0; if (odd(la)) return -1; res = 0; } /* la even */ e = pr_get_e(pr); if (q > e << 1) return -1; if (q == 1) return res; /* gx = 1 mod pr; square mod pi^q ? */ v = nfvalrem(nf, nfadd(nf, gx, gen_m1), pr, &y); if (v >= q) return res; /* 1 + pi^v y = (1 + pi^vz z)^2 mod pr^q ? v < q <= 2e => vz < e => vz = vy/2 * => y = x^2 mod pr^(min(q-v, e+v/2)), (y,pr) = 1 */ if (odd(v)) return -1; /* e > 1 */ M = cgetg(2*e+1 - q + 1, t_VEC); for (i = q+1; i <= 2*e+1; i++) gel(M, i-q) = sprk_log_gen_pr(nf, sprk, i); M = ZM_hnfmodid(shallowconcat1(M), gen_2); return hnf_solve(M,loggx)? res: -1; } /* zinit either a sprk (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); set_avma(av); if (res== 1) return 1; if (res==-1) return 0; pnup = nfmul(nf, pnu, pr_get_gen(pr)); nu++; for (i=1; i3) err_printf("nfhilbert not soluble at real place %ld\n",i); return gc_long(av,-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]); return gc_long(av,-1); } return gc_long(av,1); } long nfhilbert0(GEN nf,GEN a,GEN b,GEN p) { nf = checknf(nf); if (p) { checkprid(p); if (gequal0(a)) pari_err_DOMAIN("nfhilbert", "a", "=", gen_0, a); if (gequal0(b)) pari_err_DOMAIN("nfhilbert", "b", "=", gen_0, b); return nfhilbertp(nf,a,b,p); } return nfhilbert(nf,a,b); } /*******************************************************************/ /* HYPERELL_LOCAL_SOLVE */ /*******************************************************************/ /* Based on T.A. Fisher and G.F. Sills Local solubility and height bounds for coverings of elliptic curves https://www.dpmms.cam.ac.uk/~taf1000/papers/htbounds.pdf */ static int FpX_issquare(GEN q, GEN p) { GEN F = FpX_factor_squarefree(q,p); long i, l = lg(F); for (i = 1; i < l; i+=2) if (degpol(gel(F,i)) > 0) return 0; return 1; } static GEN hyperell_red(GEN q, GEN p) { GEN Q; long v = ZX_pvalrem(q, p, &Q); if (v == 1) return q; return odd(v)? ZX_Z_mul(Q, p): Q; } static GEN hyperell_reg_point(GEN q, GEN p) { GEN Q, F; long i, l, v = ZX_pvalrem(q, p, &Q); if (v != 1) q = odd(v)? ZX_Z_mul(Q, p): Q; if (!odd(v)) { GEN qr = FpX_red(q, p); if (!FpX_issquare(qr,p) || Fp_issquare(leading_coeff(qr), p)) return mkvec2s(0,1); } F = FpX_roots(Q, p); l = lg(F); for (i = 1; i < l; i++) { GEN r = gel(F,i), s = hyperell_reg_point(ZX_affine(q, p, r), p); if (s) retmkvec2(addii(r,mulii(gel(s,1),p)), mulii(gel(s,2),p)); } return NULL; } static GEN hyperell_lift(GEN q, GEN x, GEN p) { long e; GEN qy2 = ZX_Z_sub(q, sqri(p)); for (e = 2; ; e<<=1) { pari_sp av = avma; GEN z = ZpX_liftroot(qy2, x, p, e); if (signe(z) == 0) z = powiu(p, e); if (Zp_issquare(poleval(q, z), p)) return z; set_avma(av); } } static GEN affine_apply(GEN r, GEN x) { return addii(mulii(gel(r,2),x), gel(r,1)); } static GEN Qp_hyperell_solve_odd(GEN q, GEN p) { GEN qi = RgX_recip_shallow(q); GEN r = hyperell_reg_point(q, p), qr = NULL, qrp = NULL; GEN s = hyperell_reg_point(qi, p), qs = NULL, qsp = NULL; if (!r && !s) return NULL; if (r) { qr = hyperell_red(ZX_affine(q, gel(r,2), gel(r,1)), p); qrp = FpX_deriv(qr, p); } if (s) { qs = hyperell_red(ZX_affine(qi, gel(s,2), gel(s,1)), p); qsp = FpX_deriv(qs, p); } while(1) { GEN x = randomi(p); if (r) { GEN y2 = FpX_eval(qr, x, p); if (Fp_issquare(y2,p)) { if (signe(y2)) return affine_apply(r,x); if (signe(FpX_eval(qrp, x, p))) { x = hyperell_lift(qr, x, p); return affine_apply(r,x); } } } if (s) { GEN y2 = FpX_eval(qs, x, p); if (Fp_issquare(y2,p)) { if (signe(x)==0) x = p; if (signe(y2)) return ginv(affine_apply(s,x)); if (signe(FpX_eval(qsp, x, p))) { GEN xl = hyperell_lift(qs, x, p); return ginv(affine_apply(s,xl)); } } } } } static GEN Q2_hyperell_lift(GEN p, GEN q, long x, long y) { GEN T, h; long e; if (y==0) y = 2; T = ZX_sub(p, ZX_Z_add(ZX_mulu(q, y), sqru(y))); h = ZX_add(ZX_sqr(q), ZX_shifti(p, 2)); for (e = 3; ; e++) { pari_sp av = avma; GEN r = ZpX_liftroot(T, utoi(x), gen_2, e); if (signe(r) == 0) r = int2n(e); if (Zp_issquare(poleval(h, r), gen_2)) return r; set_avma(av); } return NULL;/*LCOV_EXCL_LINE*/ } static GEN Q2_hyperell_regpoint(GEN P, GEN Q) { long x; GEN p = ZX_to_F2x(P), dp = F2x_deriv(p); GEN q = ZX_to_F2x(Q), dq = F2x_deriv(q); for (x = 0; x <= 1; x++) { long px = F2x_eval(p,x), qx = F2x_eval(q,x); long dpx, dqx; if (qx == 1) { if(px == 0) return x==0 ? gen_2: gen_1; continue; } dpx = F2x_eval(dp,x); dqx = F2x_eval(dq,x); if (odd(dqx * px + dpx)) return Q2_hyperell_lift(P, Q, x, px); } return NULL; } static GEN Q2_hyperell_solve_affine(GEN p, GEN q) { pari_sp av = avma; GEN R, p4, q4; long x; while(1) { GEN pp, p0, p1; long vp = ZX_lval(p, 2); long vq = ZX_lval(q, 2); long w = minss(vp>>1, vq); p = ZX_shifti(p, -2*w); q = ZX_shifti(q, -w); if (ZX_lval(q,2)==0) break; pp = RgX_splitting(p,2); p0 = gel(pp,1); p1 = gel(pp,2); if (ZX_lval(p1,2)==0 || ZX_lval(p0,2)>=1) break; p = ZX_sub(p, ZX_mul(p0, ZX_add(q, p0))); q = ZX_add(q, ZX_shifti(p0, 1)); } R = Q2_hyperell_regpoint(p, q); if (R) return gerepileuptoint(av, R); p4 = ZX_to_Flx(p,4); q4 = ZX_to_Flx(q,4); for (x = 0; x <= 1; x++) { ulong px = Flx_eval(p4, x, 4); ulong qx = Flx_eval(q4, x, 4); if (px == 0 || (1+qx+3*px)%4==0) { GEN p2 = ZX_affine(p, gen_2, utoi(x)); GEN q2 = ZX_affine(q, gen_2, utoi(x)); GEN S = Q2_hyperell_solve_affine(p2, q2); if (S) return gerepileuptoint(av, addiu(shifti(S,1),x)); } } return gc_NULL(av); } static GEN Q2_hyperell_solve(GEN P) { long v = varn(P); GEN S = Q2_hyperell_solve_affine(P, pol_0(v)); if (!S) S = ginv(Q2_hyperell_solve_affine(RgX_recip(P), pol_0(v))); return S; } static GEN hyperell_local_solve(GEN q, GEN p) { if (equaliu(p,2)) return Q2_hyperell_solve(q); return Qp_hyperell_solve_odd(q, p); } /*******************************************************************/ /* BINARY QUARTIC */ /*******************************************************************/ static int Qp_issquare(GEN a, GEN p) { GEN b = typ(a) == t_INT? a: mulii(gel(a,1), gel(a,2)); return Zp_issquare(b, p); } static GEN quartic_IJ(GEN g) { GEN a = gel(g, 6), b = gel(g, 5), c = gel(g, 4), d = gel(g, 3), e = gel(g, 2); GEN ae = gmul(a,e), bd = gmul(b,d), c2 = gsqr(c); /* 12ae - 3bd + c^2 */ GEN I = gadd(gsub(gmulsg(12, ae), gmulsg(3, bd)), c2); /* c(72ae + 9bd - 2c^2) - 27ad^2 - 27eb^2*/ GEN J = gsub(gmul(c, gsub(gadd(gmulsg(72,ae), gmulsg(9,bd)), gmul2n(c2,1))), gmulsg(27, gadd(gmul(a, gsqr(d)), gmul(gsqr(b), e)))); return mkvec2(I, J); } static GEN quartic_hessiandd(GEN g) { GEN a = gel(g, 6), b = gel(g, 5), c = gel(g, 4), d = gel(g, 3), e = gel(g, 2); GEN a8 = gmul2n(a, 3), p4 = gsub(gmulsg(3, gsqr(b)), gmul(a8, c)); GEN p3 = gsub(gmul(b, c), gmul(gmulsg(6, a), d)); GEN p2 = gsub(gmulsg(8, gsqr(c)), gmulsg(12, gadd(gmul(b, d), gmul(a8, e)))); return deg2pol_shallow(gmulgu(p4,12), gmulgu(p3,24), p2, 1); } static GEN quartic_cubic(GEN g, long v) { GEN a = gel(g, 6), b = gel(g, 5), c = gel(g, 4); GEN a3 = gdivgu(a,3); return deg1pol(gmul2n(a3,2), gsub(gsqr(b),gmul2n(gmul(a3,c),3)), v); } static GEN quarticinv_pol(GEN IJ) { GEN I = gel(IJ,1), J = gel(IJ,2); return mkpoln(4, gen_1, gen_0, gmulgs(I,-3), J); } static GEN quartic_H(GEN g, GEN *pT) { GEN a = gel(g, 6), b = gel(g, 5), c = gel(g, 4); GEN IJ = quartic_IJ(g), I = gel(IJ, 1); GEN ddh = quartic_hessiandd(g); GEN ddg = deg2pol_shallow(gmulgu(a,12), gmulgu(b,6), gmulgu(c,2), 1); *pT = quarticinv_pol(IJ); return deg2pol_shallow(stoi(-8), gmul2n(ddg,2), gadd(ddh,gmul2n(I,3)),0); } static GEN quartic_disc(GEN q) { GEN IJ = quartic_IJ(q), I = gel(IJ,1), J = gel(IJ,2); return gsub(gmul2n(gpowgs(I, 3), 2), gsqr(J)); } static GEN quartic_minim_all(GEN F, GEN discF) { GEN IJ = quartic_IJ(F), I = gel(IJ,1), J = gel(IJ,2); GEN g = Z_ppo(gcdii(I,J), gel(discF,1)); GEN plist = ZV_sort_uniq_shallow(shallowconcat(gel(absZ_factor(g),1),gel(discF,2))); GEN W, C, PQ = hyperellminimalmodel(F, &C, plist); GEN P = gel(PQ,1), Q = gel(PQ,2); if (signe(Q)==0) W = mkvec2(P, C); else W = mkvec2(ZX_add(ZX_shifti(P,2),ZX_sqr(Q)),mkvec2(shifti(gel(C,1),-1),gel(C,2))); return W; } /*******************************************************************/ /* Cassels' pairing */ /*******************************************************************/ static GEN nfsqrt(GEN nf, GEN z) { long v = fetch_var_higher(); GEN R = nfroots(nf, deg2pol_shallow(gen_m1, gen_0, z, v)); delete_var(); return lg(R)==1 ? NULL: gel(R,1); } static GEN nfsqrt_safe(GEN nf, GEN z) { GEN r = nfsqrt(nf, z); if (!r) pari_err_BUG("ellrank"); return r; } static GEN vecnfsqrtmod(GEN x, GEN P) { pari_APPLY_same(gmodulo(nfsqrt_safe(gel(x,i), P), gel(x,i))) } static GEN enfsqrt(GEN T, GEN P) { GEN F = gel(ZX_factor(T),1); return liftpol(chinese1(vecnfsqrtmod(F,P))); } /* Quartic q, at most quadratic g s.t. lc(g) > 0. There exist a real r s.t. * q(r) > 0 and g(r) != 0. Return sign(g(r)) */ static int cassels_oo_solve_i(GEN q, GEN g) { long dg = degpol(g); GEN D, a, b, c; if (dg == 0 || signe(leading_coeff(q)) > 0) return 1; if (signe(gel(q,2)) > 0) return signe(gel(g,2)); c = gel(g,2); b = gel(g,3); /* g = bx+c, b>0, is negative on I=]-oo,-c/b[: if q has a root there, * then g(r) < 0. Else it has the sign of q(oo) < 0 on I */ if (dg == 1) return ZX_sturmpart(q, mkvec2(mkmoo(), gdiv(negi(c), b)))? -1: 1; a = gel(g,4); D = subii(sqri(b), shifti(mulii(a,c), 2)); /* g = ax^2+bx+c */ if (signe(D) <= 0) return 1; /* sign(g) = 1 is constant */ /* Rescale q and g: x->(x - b)/2a; roots of new g are \pm sqrt(D) */ q = ZX_translate(ZX_rescale(q, shifti(a,1)), negi(b)); /* Now g has sign -1 in I=[-sqrt(D),sqrt(D)] and 1 elsewhere. * Check if q vanishes in I <=> Graeffe(q) vanishes on [0,D]. * If so or if q(0) > 0 we take r in there; else r is outside of I */ return (signe(gel(q,2)) > 0 || ZX_sturmpart(ZX_graeffe(q), mkvec2(gen_0, D)))? -1: 1; } static int cassels_oo_solve(GEN q, GEN g) { pari_sp av = avma; return gc_int(av, cassels_oo_solve_i(q, g)); } static GEN cassels_Qp_solve(GEN q, GEN gam, GEN p) { pari_sp av = avma; GEN a = hyperell_local_solve(q, p); GEN c = poleval(gam,a); long e; if (!gequal0(c)) return c; for (e = 2; ; e++) { GEN b = gadd(a, powiu(p,e)); if (Qp_issquare(poleval(q, b), p)) { c = poleval(gam, b); if (!gequal0(c)) return gerepileupto(av,c); } } } static GEN to_ZX(GEN a, long v) { return typ(a)==t_INT? scalarpol_shallow(a,v): a; } static GEN quartic_findunit(GEN D, GEN q) { GEN T = quarticinv_pol(quartic_IJ(q)); while(1) { pari_sp av = avma; GEN z = quartic_cubic(q,0); if (signe(QXQ_norm(z,T))) return absequalii(quartic_disc(q), D)? q: ZX_shifti(q, 2); set_avma(av); q = ZX_translate(RgX_recip(q), gen_1); } } /* Crude implementation of an algorithm by Tom Fisher * On binary quartics and the Cassels-Tate pairing * https://www.dpmms.cam.ac.uk/~taf1000/papers/bq-ctp.pdf */ /* FD = primes | 2*3*5*7*D, q1,q2,q3 have discriminant D */ static long casselspairing(GEN FD, GEN q1, GEN q2, GEN q3) { pari_sp av = avma; GEN T, H = quartic_H(q1, &T); GEN z1 = quartic_cubic(q1, 0); GEN z2 = quartic_cubic(q2, 0); GEN z3 = quartic_cubic(q3, 0); GEN m = to_ZX(enfsqrt(T, QXQ_mul(QX_mul(z1,z2),z3,T)), 0); GEN Hm = RgXQ_mul(QXQ_div(m, z1, T), H, T); /* deg(Hm) >= 2 */ GEN gam = to_ZX(Q_primpart(gel(Hm,4)),1); GEN a = leading_coeff(q2), Fa = gel(absZ_factor(a),1); GEN F = ZV_sort_uniq_shallow(shallowconcat1(mkvec2(Fa, FD))); long i, e = 0, lF = lg(F); if (signe(a) <= 0) { if (signe(leading_coeff(gam)) < 0) gam = ZX_neg(gam); if (cassels_oo_solve(q1, gam) < 0) e = 1; } for (i = 1; i < lF; i++) { GEN p = gel(F, i); GEN c = cassels_Qp_solve(q1, gam, p); if (hilbert(c, a, p) < 0) e = !e; } return gc_long(av,e); } static GEN matcassels(GEN F, GEN M) { long i, j, n = lg(M)-1; GEN C = zero_F2m_copy(n,n); pari_sp av = avma; for (i = 1; i <= n; i++) { GEN Mii = gcoeff(M,i,i); if (isintzero(Mii)) continue; for (j = 1; j < i; j++) { GEN Mjj = gcoeff(M,j,j); if (!isintzero(Mjj) && casselspairing(F, Mii, Mjj, gcoeff(M,i,j))) { F2m_set(C,i,j); F2m_set(C,j,i); } } } if (DEBUGLEVEL>=2) err_printf("Cassels Pairing: %Ps\n", F2m_to_ZM(C)); return gc_const(av, C); } /*******************************************************************/ /* ELLRANK */ /*******************************************************************/ /* This section is a port by Bill Allombert of ellQ.gp by Denis Simon * Copyright (C) 2019 Denis Simon * Distributed under the terms of the GNU General Public License (GPL) */ /* \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ */ /* FUNCTIONS FOR POLYNOMIALS \\ */ /* \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ */ static GEN ell2pol(GEN ell) { return mkpoln(4, gen_1, ell_get_a2(ell), ell_get_a4(ell), ell_get_a6(ell)); } /* find point (x:y:z) on y^2 = pol, return [x,z]~ and set *py = y */ static GEN projratpointxz(GEN pol, long lim, GEN *py) { pari_timer ti; GEN P; if (issquareall(leading_coeff(pol), py)) return mkcol2(gen_1, gen_0); if (DEBUGLEVEL) timer_start(&ti); P = hyperellratpoints(pol, stoi(lim), 1); if (DEBUGLEVEL) timer_printf(&ti,"hyperellratpoints(%ld)",lim); if (lg(P) == 1) return NULL; P = gel(P,1); *py = gel(P,2); return mkcol2(gel(P,1), gen_1); } /* P a list of integers (actually primes) one of which divides x; return * the first one */ static GEN first_divisor(GEN x, GEN P) { long i, n = lg(P); for (i = 1; i < n; i++) if (dvdii(x, gel(P,i))) return gel(P,i); return gel(P,i); } /* find point (x:y:z) on y^2 = pol, return [x,z]~ and set *py = y */ static GEN projratpointxz2(GEN pol, long lim, long effort, GEN *py) { pari_sp av = avma; GEN list = mkvec(mkvec4(pol, matid(2), gen_1, gen_1)); long i, j, c; long ntry = effort * 10; for (i = 1, c = 1; i < lg(list) && c <= ntry; i++,c++) { GEN K, k, ff, co, p, M, C, r, pol, L = gel(list, i); long lr; list = vecsplice(list, i); i--; pol = Q_primitive_part(gel(L,1), &K); M = gel(L,2); K = K? mulii(gel(L,3), K): gel(L,3); C = gel(L,4); if (Z_issquareall(K, &k)) { GEN xz, y, aux, U; if (c==1) continue; pol = ZX_hyperellred(pol, &U); if (DEBUGLEVEL>1) err_printf(" reduced quartic(%ld): Y^2 = %Ps\n", i, pol); xz = projratpointxz(pol, lim, &y); if (!xz) continue; *py = gmul(y, mulii(C, k)); aux = RgM_RgC_mul(ZM2_mul(M, U), xz); if (gequal0(gel(aux, 2))) return mkcol2(gel(aux,1), gen_0); *py = gdiv(*py, gpowgs(gel(aux, 2), degpol(pol)>>1)); return mkcol2(gdiv(gel(aux, 1), gel(aux, 2)), gen_1); } ff = Z_factor(K); co = core2(mkvec2(K, ff)); K = gel(co,1); /* > 1 */ p = first_divisor(K, gel(ff,1)); K = diviiexact(K, p); C = mulii(mulii(C, gel(co,2)), p); /* root at infinity */ if (dvdii(leading_coeff(pol), p)) { GEN U = mkmat2(gel(M,1), ZC_Z_mul(gel(M,2), p)); if (equali1(content(U))) { GEN t = ZX_rescale(pol, p); list = vec_append(list, mkvec4(ZX_Z_divexact(t,p), U, K, C)); } } r = FpC_center(FpX_roots(pol, p), p, shifti(p,-1)); lr = lg(r); for (j = 1; j < lr; j++) { GEN U = ZM2_mul(M, mkmat22(p, gel(r, j), gen_0, gen_1)); if (equali1(content(U))) { GEN t = ZX_unscale_div(ZX_translate(pol, gel(r,j)), p); list = vec_append(list, mkvec4(t, U, K, C)); } } if (gc_needed(av, 1)) gerepileall(av, 2, &pol, &list); } return NULL; } static GEN polrootsmodpn(GEN pol, GEN p) { pari_sp av = avma, av2; long j, l, i = 1, vd = Z_pval(ZX_disc(pol), p); GEN v, r, P; if (!vd) { set_avma(av); retmkvec(zerovec(2)); } pol = Q_primpart(pol); P = gpowers0(p, vd-1, p); av2 = avma; v = FpX_roots(pol, p); l = lg(v); for (j = 1; j < l; j++) gel(v,j) = mkvec2(gel(v,j), gen_1); while (i < lg(v)) { GEN pol2, pe, roe = gel(v, i), ro = gel(roe,1); long e = itou(gel(roe,2)); if (e >= vd) { i++; continue; } pe = gel(P, e); (void)ZX_pvalrem(ZX_affine(pol, pe, ro), p, &pol2); r = FpX_roots(pol2, p); l = lg(r); if (l == 1) { i++; continue; } for (j = 1; j < l; j++) gel(r, j) = mkvec2(addii(ro, mulii(pe, gel(r, j))), utoi(e + 1)); /* roots with higher precision = ro + r*p^(e+1) */ if (l > 2) v = shallowconcat(v, vecslice(r, 2, l-1)); gel(v, i) = gel(r, 1); if (gc_needed(av2, 1)) gerepileall(av2, 1, &v); } if (lg(v) == 1) { set_avma(av); retmkvec(zerovec(2)); } return gerepilecopy(av, v); } /* \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ */ /* FUNCTIONS FOR LOCAL COMPUTATIONS \\ */ /* \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ */ /* z is integral; sprk true (pr | 2) [t_VEC] or modpr structure (pr | p odd) * [t_COL] */ static GEN kpmodsquares1(GEN nf, GEN z, GEN sprk) { GEN modpr = (typ(sprk) == t_VEC)? gmael(sprk, 4, 1): sprk; GEN pr = modpr_get_pr(modpr), p = pr_get_p(pr); long v = nfvalrem(nf, z, pr, &z); if (equaliu(p, 2)) { GEN c; z = to_principal_unit(nf, z, pr, sprk); /* = 1 mod pr */ c = ZV_to_Flv(sprk_log_prk1(nf, z, sprk), 2); return vecsmall_prepend(c, odd(v)); } else { GEN T = modpr_get_T(modpr); long c = !Fq_issquare(nf_to_Fq(nf, z, modpr), T, p); return mkvecsmall2(odd(v), c); } } static GEN kpmodsquares(GEN vnf, GEN z, GEN PP) { pari_sp av = avma; long i, j, l = lg(vnf); GEN dz, vchar = cgetg(l, t_VEC); z = Q_remove_denom(z, &dz); if (dz) z = ZX_Z_mul(z, dz); for (i = 1; i < l; i++) { GEN nf = gel(vnf, i), pp = gel(PP, i); GEN kp, delta = ZX_rem(z, nf_get_pol(nf)); long lp = lg(pp); kp = cgetg(lp, t_VEC); for (j = 1; j < lp; j++) gel(kp, j) = kpmodsquares1(nf, delta, gel(pp,j)); gel(vchar, i) = shallowconcat1(kp); } return gerepileuptoleaf(av, shallowconcat1(vchar)); } static GEN veckpmodsquares(GEN x, GEN vnf, GEN PP) { pari_APPLY_type(t_MAT, kpmodsquares(vnf, gel(x, i), PP)) } /* \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ */ /* GENERIC FUNCTIONS FOR ELLIPTIC CURVES \\ */ /* \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ */ static GEN ellabs(GEN P) { return ell_is_inf(P) ? P: mkvec2(gel(P,1), Q_abs_shallow(gel(P,2))); } static GEN vecellabs(GEN x) { pari_APPLY_same(ellabs(gel(x,i))) } /* y^2 = x^3 + K a2 x + K^2 a4 x + K^3 a6 */ static GEN elltwistequation(GEN ell, GEN K) { GEN K2, a2, a4, a6; if (!K || equali1(K)) return ell; K2 = sqri(K); a2 = mulii(ell_get_a2(ell), K); a4 = mulii(ell_get_a4(ell), K2); a6 = mulii(ell_get_a6(ell), mulii(K, K2)); return ellinit(mkvec5(gen_0, a2, gen_0, a4, a6), NULL, DEFAULTPREC); } /* P=[x,y] a point on Ky^2 = pol(x); [Kx, K^2y] point on Y^2 = K^3pol(X/K) */ static GEN elltwistpoint(GEN P, GEN K, GEN K2) { if (ell_is_inf(P)) return ellinf(); return mkvec2(gmul(gel(P,1), K), gmul(gel(P,2), K2)); } static GEN elltwistpoints(GEN x, GEN K) { GEN K2; if (!K || gequal1(K)) return x; K2 = gsqr(K); pari_APPLY_same(elltwistpoint(gel(x,i), K, K2)) } /* \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ */ /* FUNCTIONS FOR NUMBER FIELDS \\ */ /* \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ */ /* return a set S2 of prime ideals disjoint from S such that * Cl_{S \cup S2}(K) has no p-torsion */ static GEN bestS(GEN bnf,GEN S, ulong p) { GEN v, S2, h = bnf_get_no(bnf), cyc = bnf_get_cyc(bnf); long i, lS2; ulong l, vD; forprime_t P; if (!dvdiu(h, p)) return cgetg(1,t_VEC); if (!S) { v = diagonal_shallow(cyc); vD = Z_lval(h, p); } else { long lS = lg(S); v = cgetg(lS,t_MAT); for (i = 1; i < lS; i++) gel(v,i) = isprincipal(bnf, gel(S,i)); v = ZM_hnfmodid(v, cyc); vD = Z_lval(ZM_det(v), p); if (!vD) return cgetg(1, t_VEC); } S2 = cgetg(vD+2, t_VEC); lS2 = 1; u_forprime_init(&P,2,ULONG_MAX); while ((l = u_forprime_next(&P))) { pari_sp av = avma; GEN w, Sl = idealprimedec(bnf, utoi(l)); long nSl = lg(Sl)-1; ulong vDl; for (i = 1; i < nSl; i++) /* remove one prime ideal */ { w = ZM_hnf(shallowconcat(v, isprincipal(bnf, gel(Sl,i)))); vDl = Z_lval(ZM_det(w), p); if (vDl < vD) { gel(S2,lS2++) = gel(Sl,i); vD = vDl; v = w; av = avma; if (!vD) { setlg(S2, lS2); return S2; } } } set_avma(av); } return NULL;/*LCOV_EXCL_LINE*/ } static GEN nfC_prV_val(GEN nf, GEN G, GEN P) { long i, j, lG = lg(G), lP = lg(P); GEN M = cgetg(lG, t_MAT); for (i = 1; i < lG; i++) { GEN V = cgetg(lP, t_COL); for (j = 1; j < lP; j++) gel(V,j) = gpnfvalrem(nf, gel(G,i), gel(P,j), NULL); gel(M,i) = V; } return M; } static GEN _factorbackmod(GEN nf, GEN g, GEN e, ulong p) { GEN y = nffactorback(nf, g, e), den; GEN z = nfmul(nf, y, nfsqr(nf, idealredmodpower(nf, y, p, 0))); z = Q_remove_denom(z, &den); if (den) { if (p != 2) den = powiu(den, p-1); z = gmul(z, den); } return z; } static GEN nfV_factorbackmod(GEN nf, GEN x, ulong p) { long i, l = lg(x); GEN v = cgetg(l, t_VEC); for (i = 1; i < l; i++) { GEN y = gel(x,i), g = gel(y,1), e = gel(y,2); gel(v,i) = _factorbackmod(nf, g, ZV_to_Flv(e,p), p); } return v; } static GEN nfV_zm_factorback(GEN nf, GEN G, GEN x, long p) { pari_APPLY_type(t_VEC, _factorbackmod(nf, G, gel(x,i), p)) } static GEN prV_ZM_factorback(GEN nf, GEN S, GEN x) { pari_APPLY_type(t_VEC,idealfactorback(nf, S, gel(x,i), 0)) } /* shortcut for bnf = Q and p = 2 */ static GEN bnfselmerQ(GEN S) { GEN g = vec_prepend(prV_primes(S), gen_m1), e; long n = lg(S)-1; e = n? shallowconcat(zerocol(n), matid(n)): zeromat(0, 1); return mkvec3(g, e, const_vec(n + 1, gen_1)); } static GEN bnfselmer(GEN bnf, GEN S) { const long p = 2; pari_sp av = avma; GEN nf = bnf_get_nf(bnf), S2, S3, e, f, e2, kerval, LS2gen, LS2fu, LS2all; long n = lg(S)-1, n3, n2all, r; S2 = bestS(bnf, S, p); S3 = shallowconcat(S, S2); LS2all = nfV_factorbackmod(nf, gel(bnfunits(bnf, S3), 1), p); n3 = lg(S3)-1; n2all = lg(LS2all)-1; LS2gen = vecslice(LS2all,1,n3); LS2fu = vecslice(LS2all,n3+1, n2all-1); e2 = nfC_prV_val(nf, LS2gen, S2); kerval = Flm_ker(ZM_to_Flm(e2, p), p); LS2gen = nfV_zm_factorback(nf, LS2gen, kerval, p); e = nfC_prV_val(nf, LS2gen, S); e2 = ZM_divexactu(ZM_zm_mul(e2, kerval), p); f = prV_ZM_factorback(nf, S2, e2); LS2gen = shallowconcat(LS2fu, LS2gen); LS2gen = nfV_to_scalar_or_alg(nf, vec_prepend(LS2gen, bnf_get_tuU(bnf))); r = n2all - n3; e = shallowconcat(zeromat(n, r), e); f = shallowconcat(const_vec(r, gen_1), f); return gerepilecopy(av, mkvec3(LS2gen,e,f)); } static GEN get_kerval(GEN nf, GEN S2, GEN LS2gen) { long i, j, lS2 = lg(S2), l = lg(LS2gen); GEN e = cgetg(l, t_MAT); for (i = 1; i < l; i++) { GEN v = cgetg(lS2, t_VECSMALL); for (j=1; j < lS2; j++) v[j] = odd(idealval(nf, gel(LS2gen, i), gel(S2,j))); gel(e, i) = Flv_to_F2v(v); } return F2m_ker(e); } static GEN nf2selmer_quad(GEN nf, GEN S) { pari_sp ltop = avma; GEN D = nf_get_disc(nf), factD = nf_get_ramified_primes(nf); GEN SlistQ = prV_primes(S), QS2gen, gen, Hlist, H, KerH, LS2gen; GEN chpol, Q, kerval, S2, G, e, f, b, c, bad; long lS = lg(S), l, lHlist, i, j, k; GEN nfa = nf_get_ramified_primes(nf); QS2gen = vec_prepend(SlistQ, gen_m1); bad = ZV_sort_uniq_shallow(shallowconcat(factD, SlistQ)); Hlist = ZV_search(bad, gen_2)? bad: vec_prepend(bad, gen_2); l = lg(QS2gen); lHlist = lg(Hlist); H = cgetg(l, t_MAT); for (j = 1; j < l; j++) { GEN v = cgetg(lHlist, t_VECSMALL); for (i = 1; i < lHlist; i++) v[i] = hilbertii(D, gel(QS2gen, j), gel(Hlist, i)) < 0; gel(H, j) = Flv_to_F2v(v); } KerH = F2m_ker(H); l = lg(KerH); LS2gen = cgetg(l, t_VEC); chpol = QXQ_charpoly(gel(nf_get_zk(nf), 2), nf_get_pol(nf), 0); b = negi(gel(chpol, 3)); c = shifti(gel(chpol, 2),1); Q = mkmat3(mkcol3(gen_2, b, gen_0), mkcol3(b, c, gen_0), mkcol3(gen_0, gen_0, gen_0)); for (k = 1; k < l; k++) { GEN P = RgV_F2v_extract_shallow(QS2gen, gel(KerH, k)); GEN F = ZV_sort_uniq_shallow(shallowconcat(nfa, P)), sol; gcoeff(Q, 3, 3) = mulis(ZV_prod(P), -2); sol = qfsolve(mkvec2(Q, F)); /* must be solvable */ sol = Q_primpart(mkcol2(gel(sol,1), gel(sol,2))); gel(LS2gen, k) = basistoalg(nf, sol); } if (equalis(D, -4)) G = bad; else { G = vecsplice(bad, ZV_search(bad, veclast(factD))); G = vec_prepend(G, gen_m1); } LS2gen = shallowconcat(G, LS2gen); l = lg(SlistQ); S2 = cgetg(l, t_VEC); if (l > 1) { for (i = 1; i < l; i++) gel(S2, i) = idealprimedec(nf, gel(SlistQ, i)); S2 = setminus(shallowconcat1(S2), S); } kerval = get_kerval(nf, S2, LS2gen); l = lg(kerval); gen = cgetg(l, t_VEC); e = cgetg(l, t_MAT); f = cgetg(l, t_VEC); for (i = 1; i < l; i++) { GEN id, ei, x = nffactorback(nf, LS2gen, F2v_to_Flv(gel(kerval, i))); gel(e,i) = ei = cgetg(lS, t_COL); for (j = 1; j < lS; j++) gel(ei,j) = stoi(idealval(nf, x, gel(S,j))); id = idealdiv(nf, x, idealfactorback(nf, S, gel(e,i), 0)); if (!idealispower(nf, id, 2, &gel(f,i))) pari_err_BUG("nf2selmer_quad"); gel(gen, i) = nf_to_scalar_or_alg(nf, x); } return gerepilecopy(ltop, mkvec3(gen, e, f)); } static GEN makevbnf(GEN ell, long prec) { GEN vbnf, P = gel(ZX_factor(ell2pol(ell)), 1); long k, l = lg(P); vbnf = cgetg(l, t_VEC); for (k = 1; k < l; k++) { GEN t = gel(P,k); gel(vbnf,k) = degpol(t) <= 2? nfinit(t, prec): Buchall(t, nf_FORCE, prec); } return vbnf; } static GEN kernorm(GEN G, GEN S, GEN pol, GEN signs) { long i, j, lS = lg(S), lG = lg(G), lv = signs? lS+2: lS+1; GEN M = cgetg(lG, t_MAT); for (j = 1; j < lG; j++) { GEN v, N = QXQ_norm(gel(G,j), pol); gel(M, j) = v = cgetg(lv, t_VECSMALL); v[1] = gsigne(N) < 0; for (i = 1; i < lS; i++) v[i+1] = odd(Q_pvalrem(N, gel(S,i), &N)); if (signs) v[i+1] = signs[j]; } return Flm_ker(M, 2); } /* \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ */ /* FUNCTIONS FOR 2-DESCENT \\ */ /* \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ */ /* vector of t_VEC; return total number of entries */ static long RgVV_nb(GEN v) { long i, l = lg(v), n = 0; for (i = 1; i < l; i++) n += lg(gel(v,i)) - 1; return n; } /* return an Fp basis */ static GEN elllocalimage(GEN pol, GEN K, GEN vnf, GEN p, GEN pp, GEN pts) { long n, p2 = RgVV_nb(pp), prank = equaliu(p, 2)? p2: p2 - 1; GEN R = polrootsmodpn(pol, p), bound = addiu(p, 6); for(n = 1;; n++) { pari_sp btop; GEN x, y2, d; pts = Flm_image(pts, 2); if (lg(pts)-1 == prank) break; if ((n & 0xf) == 0) bound = mulii(bound, p); btop = avma; do { GEN r = gel(R, random_Fl(lg(R)-1)+1); long pprec = random_Fl(itou(gel(r, 2)) + 3) - 2; /* >= -2 */ set_avma(btop); x = gadd(gel(r, 1), gmul(powis(p, pprec), randomi(bound))); y2 = gmul(K, poleval(pol, x)); } while (gequal0(y2) || !Qp_issquare(y2, p)); d = deg1pol_shallow(negi(K), gmul(K, x), 0); pts = vec_append(pts, kpmodsquares(vnf, d, pp)); } return pts; } static GEN ellLS2image(GEN pol, GEN vP, GEN K, GEN vpol, GEN vcrt) { long i, l = lg(vP); GEN v; if (l == 1) return cgetg(1, t_VEC); v = cgetg(l, t_VEC); for (i = 1; i < l; i++) { GEN P = gel(vP, i), x, t; if (ell_is_inf(P)) { gel(v, i) = gen_1; continue; } x = gel(P,1); t = deg1pol_shallow(negi(K), gmul(K, x), 0); if (gequal0(gel(P,2))) { /* 2-torsion, x now integer and a root of exactly one linear vpol[k]=T */ long k, lp = lg(vpol); GEN a; for (k = 1; k < lp; k++) { GEN T = gel(vpol,k), z = gel(T,2); if (absequalii(x, z) && signe(x) == -signe(z)) break; /* T = X-x */ } a = ZX_Z_eval(ZX_deriv(pol), x); t = gadd(a, gmul(gel(vcrt,k), gsub(t, a))); /* a mod T, t mod pol/T*/ } gel(v, i) = t; } return v; } /* find small points on ell; 2-torsion points must be returned first */ static GEN ellsearchtrivialpoints(GEN ell, GEN lim, GEN help) { pari_sp av = avma; GEN tors2 = gel(elltors_psylow(ell,2),3); GEN triv = lim ? ellratpoints(ell, lim, 0): cgetg(1,t_VEC); if (help) triv = shallowconcat(triv, help); return gerepilecopy(av, shallowconcat(tors2, triv)); } GEN ellrankinit(GEN ell, long prec) { pari_sp av = avma; GEN urst; checkell_Q(ell); ell = ellminimalbmodel(ell, &urst); return gerepilecopy(av, mkvec3(ell, urst, makevbnf(ell, prec))); } INLINE GEN ZV_isneg(GEN x) { pari_APPLY_long(signe(gel(x,i)) < 0) } static GEN selmersign(GEN x, GEN vpol, GEN L) { pari_APPLY_same(ZV_isneg(nfeltsign(gel(x, i), RgX_rem(L, gel(vpol, i)), NULL))) } static GEN matselmersign(GEN vnf, GEN vpol, GEN x) { pari_APPLY_type(t_MAT, shallowconcat1(selmersign(vnf, vpol, gel(x, i)))) } static GEN _trace(GEN z, GEN T) { long n = degpol(T)-1; if (degpol(z) < n) return gen_0; return gdiv(gel(z, 2+n), gel(T, 3+n)); } static GEN tracematrix(GEN zc, GEN b, GEN T) { long i, j; GEN q = cgetg(4, t_MAT); for (j = 1; j <= 3; j++) gel(q,j) = cgetg(4, t_COL); for (j = 1; j <= 3; j++) { for (i = 1; i < j; i++) gcoeff(q,i,j) = gcoeff(q,j,i) = _trace(QXQ_mul(zc, QXQ_mul(gel(b,i), gel(b,j), T), T), T); gcoeff(q,i,i) = _trace(QXQ_mul(zc, QXQ_sqr(gel(b,i), T), T), T); } return q; } static GEN RgXV_cxeval(GEN x, GEN r, GEN ri) { pari_APPLY_same(RgX_cxeval(gel(x,i), r, ri)) } static GEN redquadric(GEN base, GEN pol, GEN zc) { pari_sp av = avma; long prec = nbits2prec(gexpo(pol)+gexpo(zc)) + EXTRAPRECWORD; for (;;) { GEN R = roots(pol, prec), s = NULL; long i, l = lg(R); for (i = 1; i < l; ++i) { GEN r = gel(R,i), ri = gexpo(r) > 1? ginv(r): NULL; GEN b = RgXV_cxeval(base, r, ri), z = RgX_cxeval(zc, r, ri); GEN M = RgC_RgV_mulrealsym(RgV_Rg_mul(b, gabs(z, prec)), gconj(b)); s = s? RgM_add(s, M): M; } s = RgM_Cholesky(s, prec); if (s) return gerepileupto(av, lll(s)); prec = precdbl(prec); set_avma(av); } } static GEN RgX_homogenous_evaldeg(GEN P, GEN A, GEN B) { long i, d = degpol(P), e = lg(B)-1; GEN s = gmul(gel(P, d+2), gel(B,e-d)); for (i = d-1; i >= 0; i--) s = gadd(gmul(s, A), gmul(gel(B,e-i), gel(P,i+2))); return s; } static GEN RgXV_homogenous_evaldeg(GEN x, GEN a, GEN b) { pari_APPLY_same(RgX_homogenous_evaldeg(gel(x,i), a, b)) } static void check_oncurve(GEN ell, GEN v) { long i, l = lg(v); for (i = 1; i < l; i++) { GEN P = gel(v, i); if (lg(P) != 3 || !oncurve(ell,P)) pari_err_TYPE("ellrank",P); } } static GEN basis(GEN nf, GEN x, GEN crt, GEN pol) { long i, l = lg(x); GEN b = cgetg(l, t_COL); for (i = 1; i < l; i++) { GEN z = nf_to_scalar_or_alg(nf, gel(x, i)); gel(b, i) = grem(gsub(z, gmul(crt, z)), pol); /* z mod T, 0 mod (pol/T) */ } return b; } static GEN vecsmallbasis(GEN x, GEN vcrt, GEN pol) { pari_APPLY_same(basis(gel(x,i), nf_get_zk(gel(x,i)), gel(vcrt,i), pol)) } static GEN ZC_shifti(GEN x, long n) { pari_APPLY_type(t_COL, shifti(gel(x,i), n)) } /* true nf */ static GEN selmerbasis(GEN nf, GEN ek, GEN sqrtLS2, GEN factLS2, GEN badprimes, GEN crt, GEN pol) { GEN sqrtzc = idealfactorback(nf, sqrtLS2, zv_neg(ek), 0); GEN E = ZC_shifti(ZM_zc_mul(factLS2, ek), -1); if (ZV_equal0(E)) sqrtzc = idealhnf_shallow(nf, sqrtzc); else sqrtzc = idealmul(nf, sqrtzc, idealfactorback(nf, badprimes, ZC_neg(E), 0)); return basis(nf, sqrtzc, crt, pol); } static long randu(void) { return random_Fl(127) - 63; } static GEN randS(GEN b) { return gadd(gmulgs(gel(b,1), randu()), gadd(gmulgs(gel(b,2), randu()), gmulgs(gel(b,3), randu()))); } static GEN liftselmerinit(GEN expo, GEN vnf, GEN sqrtLS2, GEN factLS2, GEN badprimes, GEN vcrt, GEN pol) { long n = lg(vnf)-1, k, t; GEN b = cgetg(n+1, t_VEC); for (k = t = 1; k <= n; k++) { GEN fak = gel(factLS2,k), ek; long m = lg(fak)-1; ek = vecslice(expo, t, t + m-1); t += m; gel(b,k) = selmerbasis(gel(vnf,k), ek, gel(sqrtLS2,k), fak, gel(badprimes,k), gel(vcrt,k), pol); } return shallowconcat1(b); } static GEN qf_disc_fact(GEN q, GEN L) { GEN D = ZM_det(q), P, E; GEN H = Z_smoothen(D, L, &P, &E); if (H) P = shallowconcat(P, gel(Z_factor(H),1)); return mkvec2(q, P); } static GEN liftselmer_cover(GEN b, GEN expo, GEN LS2, GEN pol, GEN discF, GEN K) { GEN P, Q, Q4, R, den, q0, q1, q2, xz, x, y, y2m, U, param, newb; GEN ttheta, tttheta, zc, polprime; GEN QM, zden; zc = RgXQV_factorback(LS2, expo, pol); if (typ(zc)==t_INT) zc = scalarpol(zc, varn(pol)); ttheta = RgX_shift_shallow(pol,-2); tttheta = RgX_shift_shallow(pol, -1); polprime = ZX_deriv(pol); q2 = Q_primpart(tracematrix(zc, b, pol)); U = redquadric(b, pol, QXQ_div(zc, polprime, pol)); q2 = qf_RgM_apply(q2, U); newb = RgV_RgM_mul(b, U); param = Q_primpart(qfparam(q2, qfsolve(qf_disc_fact(q2,gel(discF,2))), 1)); param = RgM_to_RgXV_reverse(shallowtrans(param), 0); q1 = RgM_neg(tracematrix(QXQ_mul(zc, ttheta, pol), newb, pol)); q1 = Q_remove_denom(qfeval(q1, param), &den); if (den) q1 = ZX_Z_mul(q1, den); if (!equali1(K)) q1 = RgX_Rg_mul(q1, K); QM = quartic_minim_all(q1, discF); q1 = gel(QM,1); zden = gmael(QM,2,1); Q = ZX_hyperellred(q1, &R); R = gmul(gmael(QM,2,2), R); if (DEBUGLEVEL>1) err_printf(" reduced quartic: Y^2 = %Ps\n", Q); xz = mkcol2(pol_x(0),gen_1); P = RgM_RgC_mul(R, xz); x = gel(P,1); y = gel(P,2); param = RgXV_homogenous_evaldeg(param, x, gpowers(y, 2)); param = gmul(param, gdiv(den? mulii(K, den): K, zden)); q0 = tracematrix(QXQ_mul(zc, tttheta, pol), newb, pol); x = gdiv(qfeval(q0, param), K); Q4 = gpowers(Q,4); y2m = gmul(RgX_homogenous_evaldeg(pol, x, Q4), Q); if (!issquareall(gdiv(y2m, K), &y)) pari_err_BUG("liftselmer_cover"); y = gdiv(y, gel(Q4,2)); P = mkvec2(gdiv(gmul(K,x),pol_xn(2,1)),gdiv(gmul(gsqr(K),y),pol_xn(3,1))); return mkvec2(Q,P); } static GEN liftselmer(GEN b, GEN expo, GEN sbase, GEN LS2, GEN pol, GEN discF, GEN K, long ntry, GEN *pt_Q) { pari_sp av = avma, av2; long t, lim = ntry * LIM1; GEN ttheta, tttheta, z, polprime; hashtable h; hash_init_GEN(&h, ntry, ZX_equal, 1); z = RgXQV_factorback(LS2, expo, pol); ttheta = RgX_shift_shallow(pol,-2); tttheta = RgX_shift_shallow(pol, -1); polprime = ZX_deriv(pol); av2 = avma; for (t = 1; t <= ntry; t++, set_avma(av2)) { GEN P, Q, Qk, R, den, q0, q1, q2, xz, x, y, zz, zc, U, param, newb, zden, QM; long idx; if (t == 1) zc = z; else { GEN r; do r = randS(sbase); while (degpol(QX_gcd(r, pol))); zc = QXQ_mul(z, QXQ_sqr(r, pol), pol); } q2 = Q_primpart(tracematrix(zc, b, pol)); U = redquadric(b, pol, QXQ_div(zc, polprime, pol)); if (lg(U) < 4) continue; q2 = qf_RgM_apply(q2, U); newb = RgV_RgM_mul(b, U); param = Q_primpart(qfparam(q2, qfsolve(qf_disc_fact(q2,gel(discF,2))), 1)); param = RgM_to_RgXV_reverse(shallowtrans(param), 0); q1 = RgM_neg(tracematrix(QXQ_mul(zc, ttheta, pol), newb, pol)); q1 = Q_remove_denom(qfeval(q1, param), &den); if (den) q1 = ZX_Z_mul(q1, den); if (!equali1(K)) q1 = RgX_Rg_mul(q1, K); QM = quartic_minim_all(q1, discF); q1 = gel(QM,1); zden = gmael(QM,2,1); Q = ZX_hyperellred(q1, &R); R = gmul(gmael(QM,2,2), R); if (pt_Q) *pt_Q = Q; Qk = shallowcopy(Q); (void) ZX_canon_neg(Qk); if (hash_haskey_long(&h, (void*)Qk, &idx)) continue; hash_insert_long(&h, (void*)Qk, 1); av2 = avma; if (DEBUGLEVEL>1) err_printf(" reduced quartic: Y^2 = %Ps\n", Q); xz = projratpointxz(Q, lim, &zz); if (!xz) { xz = projratpointxz2(Q, lim, ntry, &zz); if (!xz) { if (pt_Q) return NULL; else continue; } } P = RgM_RgC_mul(R, xz); x = gel(P,1); y = gel(P,2); param = RgXV_homogenous_evaldeg(param, x, gpowers(y, 2)); param = gmul(param, gdiv(den? mulii(K, den): K, gmul(zz, zden))); q0 = tracematrix(QXQ_mul(zc, tttheta, pol), newb, pol); x = gdiv(qfeval(q0, param), K); if (!issquareall(gdiv(poleval(pol, x), K), &y)) /* K y^2 = pol(x) */ pari_err_BUG("ellrank"); P = mkvec2(x, y); if (DEBUGLEVEL) err_printf("Found point: %Ps\n", P); if (pt_Q) *pt_Q = gen_0; return gerepilecopy(av, P); } return NULL; } static void gtoset_inplace(GEN x) { gen_sort_inplace(x, (void*)&cmp_universal, cmp_nodata, NULL); } /* FIXME: export */ static void setlgall(GEN x, long L) { long i, l = lg(x); for(i = 1; i < l; i++) setlg(gel(x,i), L); } static long dim_selmer(GEN p, GEN pol, GEN K, GEN vnf, GEN LS2, GEN helpLS2, GEN *selmer, GEN *LS2chars, GEN *helpchars) { pari_sp av; long dim, k, lvnf = lg(vnf); GEN X, L, LS2image, helpimage, pp = cgetg(lvnf, t_VEC); int pis2 = equaliu(p, 2); for (k = 1; k < lvnf; k++) { GEN v, nf = gel(vnf,k), PR = idealprimedec(nf, p); long j, l = lg(PR); gel(pp, k) = v = cgetg(l, t_VEC); for (j = 1; j < l; j++) { GEN pr = gel(PR,j); gel(v,j) = pis2? log_prk_init(nf, pr, 1 + 2 * pr_get_e(pr), NULL) : zkmodprinit(nf, pr); } } LS2image = veckpmodsquares(LS2, vnf, pp); *LS2chars = vconcat(*LS2chars, LS2image); helpimage = veckpmodsquares(helpLS2, vnf, pp); *helpchars = vconcat(*helpchars, helpimage); av = avma; L = elllocalimage(pol, K, vnf, p, pp, helpimage); X = Flm_ker(shallowconcat(LS2image, L), 2); setlgall(X, lg(LS2image)); /* intersect(LS2image, locim) = LS2image.X */ *selmer = Flm_intersect_i(*selmer, shallowconcat(Flm_ker(LS2image,2), X), 2); *selmer = gerepileupto(av, Flm_image(*selmer, 2)); dim = lg(*selmer)-1; return (dim == Flm_rank(helpimage,2))? dim: -1; } /* Assume there are 3 real roots, if K>0 return the smallest, otherwise the largest */ static long get_row(GEN vnf, GEN K) { long k, sK = signe(K), n = lg(vnf)-1; GEN R; if (n == 1) return sK > 0? 1: 3; if (n == 2) { GEN P = nf_get_pol(gel(vnf,2)); GEN z = negi(constant_coeff(nf_get_pol(gel(vnf,1)))); GEN y = poleval(P,z); GEN b = gel(P,3), a = gel(P,4); if (signe(y) != signe(a)) /* 1 is between 2 and 3 */ return sK > 0? 2: 3; else if (cmpii(mulii(z,mulis(a,-2)), b) == signe(a)) return sK > 0? 1: 3; else return sK > 0? 2: 1; } R = cgetg(4, t_VEC); for (k = 1; k <= 3; k++) gel(R, k) = gel(nf_get_roots(gel(vnf,k)), 1); return sK > 0? vecindexmin(R): vecindexmax(R); } static GEN Z_factor_addprimes(GEN N, GEN P) { GEN Pnew, Enew; GEN H = Z_smoothen(N, P, &Pnew, &Enew); return H ? shallowconcat(P, gel(Z_factor(H),1)): P; } static GEN vbnf_discfactors(GEN vbnf) { long n = lg(vbnf)-1; switch (n) { case 1: { GEN nf = bnf_get_nf(gel(vbnf,1)); GEN L = shallowtrans(nf_get_ramified_primes(nf)); return Z_factor_addprimes(nf_get_index(nf), L); } case 2: { GEN nf = gel(vbnf,2), R; GEN L = shallowtrans(nf_get_ramified_primes(nf)); L = Z_factor_addprimes(nf_get_index(nf), L); R = absi(ZX_resultant(nf_get_pol(gel(vbnf,1)), nf_get_pol(nf))); return Z_factor_addprimes(R, L); } case 3: { GEN P1 = nf_get_pol(gel(vbnf,1)); GEN P2 = nf_get_pol(gel(vbnf,2)); GEN P3 = nf_get_pol(gel(vbnf,3)); GEN L = gel(Z_factor(absi(ZX_resultant(P1,P2))),1); L = Z_factor_addprimes(absi(ZX_resultant(P2,P3)),L); return Z_factor_addprimes(absi(ZX_resultant(P3,P1)),L); } default: pari_err_BUG("vbnf_discfactors"); return NULL;/*LCOV_EXCL_LINE*/ } } static GEN ell2selmer(GEN ell, GEN ell_K, GEN help, GEN K, GEN vbnf, long effort, long flag, long prec) { GEN KP, pol, vnf, vpol, vcrt, sbase, LS2, factLS2, sqrtLS2, signs; GEN selmer, helpLS2, LS2chars, helpchars, newselmer, factdisc, badprimes; GEN helplist, listpoints, p, covers, disc, discF; long i, k, n, tors2, mwrank, dim, nbpoints, lfactdisc, t, u, sha2 = 0; forprime_t T; pol = ell2pol(ell); help = ellsearchtrivialpoints(ell_K, flag ? NULL:muluu(LIMTRIV,effort+1), help); help = elltwistpoints(help, ginv(K)); /* points on K Y^2 = pol(X) */ n = lg(vbnf) - 1; tors2 = n - 1; KP = gel(absZ_factor(K), 1); disc = ZX_disc(pol); factdisc = mkvec3(KP, mkcol(gen_2), vbnf_discfactors(vbnf)); factdisc = ZV_sort_uniq_shallow(shallowconcat1(factdisc)); discF = mkvec2(gmul(K,disc), factdisc); badprimes = cgetg(n+1, t_VEC); vnf = cgetg(n+1, t_VEC); vpol = cgetg(n+1, t_VEC); vcrt = cgetg(n+1, t_VEC); LS2 = cgetg(n+1, t_VEC); factLS2 = cgetg(n+1, t_VEC); sqrtLS2 = cgetg(n+1, t_VEC); for (k = 1; k <= n; k++) { GEN T, Tinv, id, f, sel, L, S, nf, NF = gel(vbnf,k); long i, lk; nf = (n == 1)? bnf_get_nf(NF): NF; gel(vnf, k) = nf; gel(vpol, k) = T = nf_get_pol(nf); Tinv = RgX_div(pol, gel(vpol, k)); gel(vcrt, k) = QX_mul(QXQ_inv(T, Tinv), T); /* 0 mod T, 1 mod pol/T */ id = idealadd(nf, nf_get_index(nf), ZX_deriv(T)); f = nf_pV_to_prV(nf, KP); settyp(f, t_COL); f = mkvec3(gel(idealfactor_partial(nf, Tinv, factdisc), 1), gel(idealfactor(nf, id), 1), f); gel(badprimes, k) = S = gtoset(shallowconcat1(f)); if (n == 1) { sel = bnfselmer(NF, S); obj_free(NF); /* units */ } else if (degpol(T) == 1) sel = bnfselmerQ(S); else /* degree 2 */ sel = nf2selmer_quad(NF, S); gel(LS2, k) = L = gel(sel, 1); lk = lg(L); gel(factLS2, k) = gel(sel, 2); gel(sqrtLS2, k) = gel(sel, 3); for (i = 1; i < lk; i++) { GEN z = gel(L,i); /* z mod T, 1 mod (pol/T) */ gel(L,i) = grem(gadd(z, gmul(gsubsg(1,z), gel(vcrt,k))), pol); } } sbase = shallowconcat1(vecsmallbasis(vnf, vcrt, pol)); if (DEBUGLEVEL>2) err_printf(" local badprimes = %Ps\n", badprimes); LS2 = shallowconcat1(LS2); helpLS2 = ellLS2image(pol, help, K, vpol, vcrt); LS2chars = matselmersign(vnf, vpol, LS2); helpchars = matselmersign(vnf, vpol, helpLS2); signs = NULL; if (signe(ell_get_disc(ell)) > 0) signs = Flm_row(LS2chars, get_row(vnf,K)); selmer = kernorm(LS2, factdisc, pol, signs); forprime_init(&T, gen_2, NULL); lfactdisc = lg(factdisc); dim = -1; for (i = 1; dim < 0 && i < lfactdisc; i++) dim = dim_selmer(gel(factdisc,i), pol, K, vnf, LS2, helpLS2, &selmer,&LS2chars,&helpchars); while (dim < 0 && Flm_rank(Flm_mul(LS2chars, selmer, 2), 2) < lg(selmer)-1) { while ((p = forprime_next(&T)) && ZV_search(factdisc, p)); dim = dim_selmer(p, pol, K, vnf, LS2, helpLS2, &selmer,&LS2chars,&helpchars); } /* transpose the matrix to get the solution that contains 1..tors2*/ helplist = gel(Flm_indexrank(Flm_transpose(helpchars),2), 1); help = shallowextract(help, helplist); helpchars = shallowextract(helpchars, helplist); dim = lg(selmer)-1; if (DEBUGLEVEL) err_printf("Selmer rank: %ld\n", dim); newselmer = Flm_invimage(Flm_mul(LS2chars, selmer, 2), helpchars, 2); if (!newselmer) pari_err_BUG("ellrank, wrong nfeltsign"); nbpoints = lg(help) - 1; if (flag==1) { GEN u = nbpoints? Flm_mul(selmer,Flm_suppl(newselmer,2), 2): selmer; long l = lg(u); GEN z = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(z,i) = RgXQV_factorback(LS2, gel(u,i), pol); return mkvec2(mkvec3(vnf,sbase,pol), z); } else if (flag==2) { GEN u = nbpoints ? Flm_mul(selmer,Flm_suppl(newselmer,2), 2): selmer; long l = lg(u); GEN P = cgetg(l, t_VEC), b; for (i = 1; i < l; i++) { b = liftselmerinit(gel(u,i), vnf, sqrtLS2, factLS2, badprimes, vcrt, pol); gel(P,i) = liftselmer_cover(b, gel(u,i), LS2, pol, discF, K); } return P; } listpoints = vec_lengthen(help, dim); /* points on ell */ covers = zerovec(dim); for (i=1; i <= dim; i++) { GEN b, P, expo, vec = vecsmall_ei(dim, i); if (Flm_Flc_invimage(newselmer, vec, 2)) continue; expo = Flm_Flc_mul(selmer, vec, 2); b = liftselmerinit(expo, vnf, sqrtLS2, factLS2, badprimes, vcrt, pol); P = liftselmer(b, expo, sbase, LS2, pol, discF, K, 1, &gel(covers,i)); if (P) { gel(listpoints, ++nbpoints) = P; /* new point on ell */ gel(newselmer, nbpoints) = vec; setlg(newselmer, nbpoints+1); } } if (nbpoints < dim) { long i, j; GEN M = cgetg(dim+1, t_MAT), selker; GEN D = mulii(muliu(absi(disc), 27*4096), powiu(K,6)); GEN FD = ZV_sort_uniq_shallow(shallowconcat1(mkvec2(mkcol3s(3,5,7), factdisc))); for (i = 1; i <= dim; i++) gel(M,i) = cgetg(dim+1, t_COL); for (i = 1; i <= dim; i++) for (j = 1; j <= i; j++) { GEN Q; if (isintzero(gel(covers,i))) Q = gen_0; else if (i==j) Q = quartic_findunit(D, gel(covers,i)); else { GEN e = Flv_add(gel(selmer,i), gel(selmer,j), 2); GEN b = liftselmerinit(e, vnf, sqrtLS2, factLS2, badprimes, vcrt, pol); Q = quartic_findunit(D, gel(liftselmer_cover(b, e, LS2, pol, discF, K),1)); } gmael(M,j,i) = gmael(M,i,j) = Q; } selker = F2m_to_Flm(F2m_ker(matcassels(FD, M))); sha2 = dim - (lg(selker)-1); dim = lg(selker)-1; for (t=1, u=1; nbpoints < dim && effort > 0; t++) { pari_sp btop = avma; GEN expo, b, P, vec; do vec = Flm_Flc_mul(selker,random_Flv(dim, 2), 2); while (zv_equal0(vec) || Flm_Flc_invimage(newselmer, vec, 2)); expo = Flm_Flc_mul(selmer, vec, 2); b = liftselmerinit(expo, vnf, sqrtLS2, factLS2, badprimes, vcrt, pol); P = liftselmer(b, expo, sbase, LS2, pol, discF, K, u, NULL); if (P) { gel(listpoints, ++nbpoints) = P; gel(newselmer, nbpoints) = vec; setlg(newselmer, nbpoints+1); } else set_avma(btop); if (t == dim) { t = 0; u++; effort--; } } } setlg(listpoints, nbpoints+1); mwrank = nbpoints - tors2; if (odd(dim - nbpoints)) mwrank++; listpoints = vecslice(listpoints,tors2+1, nbpoints); listpoints = elltwistpoints(listpoints, K); listpoints = vecellabs(ellQ_genreduce(ell_K, listpoints, NULL, prec)); gtoset_inplace(listpoints); return mkvec4(utoi(mwrank), utoi(dim-tors2), utoi(sha2), listpoints); } GEN ell2selmer_basis(GEN ell, GEN *cb, long prec) { GEN E = ellminimalbmodel(ell, cb); GEN S = ell2selmer(E, E, NULL, gen_1, makevbnf(E, prec), 0, 1, prec); obj_free(E); return S; } static void ellrank_get_nudur(GEN E, GEN F, GEN *nu, GEN *du, GEN *r) { GEN ea2 = ell_get_a2(E), ea2t = ell_get_a2(F); GEN ec4 = ell_get_c4(E), ec4t = ell_get_c4(F); GEN ec6 = ell_get_c6(E), ec6t = ell_get_c6(F); GEN N, D, d; if (signe(ec4)==0) { if (!Z_ispowerall(mulii(ec6,sqri(ec6t)),3,&N)) pari_err_TYPE("ellrank",F); D = ec6t; } else if (signe(ec6)==0) { if (!Z_issquareall(mulii(ec4,ec4t),&N)) pari_err_TYPE("ellrank",F); D = ec4t; } else { GEN d46 = mulii(gcdii(ec4,ec4t),gcdii(ec6,ec6t)); N = diviiexact(mulii(ec6,ec4t),d46); D = diviiexact(mulii(ec6t,ec4),d46); } d = gcdii(N, D); *nu = diviiexact(N, d); *du = diviiexact(D, d); *r = diviuexact(subii(mulii(*nu,ea2t),mulii(*du,ea2)),3); } static GEN ellrank_flag(GEN e, long effort, GEN help, long flag, long prec) { pari_sp ltop = avma; GEN urst, v, vbnf, eK; GEN et = NULL, K = gen_1, nu = NULL, du = NULL, r = NULL, urstK = NULL; long newell = 0; if (lg(e)==3 && typ(e)==t_VEC) { et = gel(e,2); e = gel(e,1); } if (lg(e)==4 && typ(e)==t_VEC) { vbnf = gel(e,3); urst = gel(e,2); e = gel(e,1); checkell_Q(e); if (!ell_is_integral(e)) pari_err_TYPE("ellrank [nonintegral model]",e); if (signe(ell_get_a1(e))) pari_err_TYPE("ellrank [a1 != 0]", e); if (signe(ell_get_a3(e))) pari_err_TYPE("ell2rank [a3 != 0]", e); } else { checkell_Q(e); e = ellminimalbmodel(e, &urst); newell = 1; vbnf = makevbnf(e, prec); } if (et) { checkell_Q(et); if (!gequal(ell_get_j(et),ell_get_j(e))) pari_err_TYPE("ellrank",et); et = ellminimalbmodel(et, &urst); ellrank_get_nudur(e, et, &nu, &du, &r); K = mulii(nu, du); urstK = mkvec4(nu, mulii(nu,r), gen_0, gen_0); } if (help) { if (urst) help = ellchangepoint(help, urst); if (et) help = ellchangepointinv(help, urstK); } eK = elltwistequation(e, K); /* help is a vector of rational points [x,y] satisfying K y^2 = pol(x) */ /* [Kx, K^2y] is on eK: Y^2 = K^3 pol(X/K) */ if (help) check_oncurve(eK, help); v = ell2selmer(e, eK, help, K, vbnf, effort, flag, prec); if (flag==0) { if (et) gel(v,4) = ellchangepoint(gel(v,4), urstK); if (urst) gel(v,4) = ellchangepointinv(gel(v,4), urst); } else { long i, l = lg(v); for (i = 1; i < l; i++) { if (et) gmael(v,i,2) = ellchangepoint(gmael(v,i,2), urstK); if (urst) gmael(v,i,2) = ellchangepointinv(gmael(v,i,2), urst); } } if (newell) obj_free(e); if (eK != e) obj_free(eK); return gerepilecopy(ltop, v); } GEN ellrank(GEN e, long effort, GEN help, long prec) { return ellrank_flag(e, effort, help, 0, prec); } GEN ell2cover(GEN ell, long prec) { return ellrank_flag(ell, 0, NULL, 2, prec); } pari-2.17.2/src/basemath/Ser.c0000644000175000017500000002041614676526175014462 0ustar billbill/* Copyright (C) 2000, 2012 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" /*******************************************************************/ /* */ /* Conversion --> t_SER */ /* */ /*******************************************************************/ static GEN RgX_to_ser_i(GEN x, long l, long v, int copy) { long i = 2, lx = lg(x), vx = varn(x); GEN y; if (lx == 2) return zeroser(vx, minss(l - 2, v)); if (l <= 2) { if (l == 2 && v != LONG_MAX) return zeroser(vx, v); pari_err_BUG("RgX_to_ser (l < 2)"); } y = cgetg(l,t_SER); if (v == LONG_MAX) { v = 1; lx = 3; } /* e.g. Mod(0,3) * x^0 */ else if (v) { long w = v; while (isrationalzero(gel(x,2))) { x++; w--; } lx -= v; if (w) { /* keep type information, e.g. Mod(0,3) + x */ GEN z = gel(x,2); /* = 0 */ if (lx <= 2) gel(y,2) = copy? gcopy(z): z; else { x += w; gel(y,2) = gadd(gel(x,2), z); } i++; } } y[1] = evalvarn(vx) | evalvalser(v); /* must come here because of LONG_MAX */ if (lx > l) lx = l; /* 2 <= lx <= l */ if (copy) for (; i 2) gel(d,2) = gadd(gel(d,2), z); else d = scalarpol_shallow(z, varn(d)); *pd = d; return v; } static GEN _rfrac_to_ser(GEN x, long l, long copy) { GEN a = gel(x,1), d = gel(x,2); long warn = 0, v = varn(d), e; if (l == 2) return zeroser(v, gvaluation(x, pol_x(v))); e = - RgX_valrem(d, &d); e -= RgX_valrem_type(&d, &warn); if (!signe(d)) pari_err_INV("rfrac_to_ser", gel(x,2)); if (typ(a) != t_POL || varn(a) != v) { a = RgX_Rg_mul(RgXn_inv(d, l - 2), a); e += RgX_valrem_type(&a, &warn); } else { e += RgX_valrem(a, &a); e += RgX_valrem_type(&a, &warn); a = RgXn_div(a, d, l - 2); } if (warn) pari_warn(warner,"normalizing a series with 0 leading term"); a = RgX_to_ser_i(a, l, 0, copy); setvalser(a, valser(a) + e); return a; } GEN rfrac_to_ser(GEN x, long l) { return _rfrac_to_ser(x, l, 1); } GEN rfrac_to_ser_i(GEN x, long l) { return _rfrac_to_ser(x, l, 0); } static GEN RgV_to_ser_i(GEN x, long v, long l, int copy) { long j, lx = minss(lg(x), l-1); GEN y; if (lx == 1) return zeroser(v, l-2); y = cgetg(l, t_SER); y[1] = evalsigne(1)|evalvarn(v)|evalvalser(0); x--; if (copy) for (j = 2; j <= lx; j++) gel(y,j) = gcopy(gel(x,j)); else for (j = 2; j <= lx; j++) gel(y,j) = gel(x,j); for ( ; j < l; j++) gel(y,j) = gen_0; return normalizeser(y); } GEN RgV_to_ser(GEN x, long v, long l) { return RgV_to_ser_i(x, v, l, 0); } /* x a t_SER, prec >= 0 */ GEN sertoser(GEN x, long prec) { long i, lx = lg(x), l; GEN y; if (lx == 2) return zeroser(varn(x), prec); l = prec+2; lx = minss(lx, l); y = cgetg(l,t_SER); y[1] = x[1]; for (i = 2; i < lx; i++) gel(y,i) = gel(x,i); for ( ; i < l; i++) gel(y,i) = gen_0; return y; } /* R(1/x) = x^v * n/d, val(n) = val(d) = 0 */ long rfracrecip(GEN *pn, GEN *pd) { long v = degpol(*pd); if (typ(*pn) == t_POL && varn(*pn) == varn(*pd)) { v -= degpol(*pn); (void)RgX_valrem(*pn, pn); *pn = RgX_recip(*pn); } (void)RgX_valrem(*pd, pd); *pd = RgX_recip(*pd); return v; } /* R(1/x) + O(x^N) */ GEN rfracrecip_to_ser_absolute(GEN R, long N) { GEN n = gel(R,1), d = gel(R,2); long v = rfracrecip(&n, &d); /* R(1/x) = x^v * n/d, val(n) = val(d) = 0 */ if (N <= v) return zeroser(varn(d), N); R = rfrac_to_ser_i(mkrfrac(n, d), N-v+2); setvalser(R, v); return R; } /* assume prec >= 0 */ GEN scalarser(GEN x, long v, long prec) { long i, l, s; GEN y; if (isexactzero(x)) { if (isrationalzero(x)) return zeroser(v, prec); y = cgetg(3, t_SER); y[1] = evalsigne(0) | _evalvalser(prec) | evalvarn(v); gel(y,2) = gcopy(x); return y; } l = prec + 2; y = cgetg(l, t_SER); s = !gequal0(x); y[1] = evalsigne(s) | _evalvalser(0) | evalvarn(v); gel(y,2) = gcopy(x); for (i=3; i 0) return scalarser(x, v, prec); return RgX_to_ser_i(x, prec+2, RgX_val(x), 1); } /* x a t_RFRAC */ static GEN rfractoser(GEN x, long v, long prec) { long s = varncmp(varn(gel(x,2)), v); pari_sp av; if (s < 0) err_ser_priority(x,v); if (s > 0) return scalarser(x, v, prec); av = avma; return gerepileupto(av, rfrac_to_ser(x, prec+2)); } GEN toser_i(GEN x) { switch(typ(x)) { case t_SER: return x; case t_POL: return RgX_to_ser_inexact(x, precdl+2); case t_RFRAC: return rfrac_to_ser_i(x, precdl+2); } return NULL; } /* conversion: prec ignored if t_VEC or t_SER in variable v */ GEN gtoser(GEN x, long v, long prec) { long tx = typ(x); if (v < 0) v = 0; if (prec < 0) pari_err_DOMAIN("Ser", "precision", "<", gen_0, stoi(prec)); if (tx == t_SER) { long s = varncmp(varn(x), v); if (s < 0) return coefstoser(x, v, prec); else if (s > 0) return scalarser(x, v, prec); return gcopy(x); } if (is_scalar_t(tx)) return scalarser(x,v,prec); switch(tx) { case t_POL: return poltoser(x, v, prec); case t_RFRAC: return rfractoser(x, v, prec); case t_QFB: return RgV_to_ser_i(x, v, 4+1, 1); case t_VECSMALL: x = zv_to_ZV(x);/*fall through*/ case t_VEC: case t_COL: if (varncmp(gvar(x), v) <= 0) pari_err_PRIORITY("Ser", x, "<=", v); return RgV_to_ser_i(x, v, lg(x)+1, 1); } pari_err_TYPE("Ser",x); return NULL; /* LCOV_EXCL_LINE */ } /* impose prec */ GEN gtoser_prec(GEN x, long v, long prec) { pari_sp av = avma; if (v < 0) v = 0; if (prec < 0) pari_err_DOMAIN("Ser", "precision", "<", gen_0, stoi(prec)); switch(typ(x)) { case t_SER: if (varn(x) != v) break; return gerepilecopy(av, sertoser(x, prec)); case t_QFB: x = RgV_to_ser_i(mkvec3(gel(x,1),gel(x,2),gel(x,3)), v, prec+2, 1); return gerepileupto(av, x); case t_VECSMALL: x = zv_to_ZV(x);/*fall through*/ case t_VEC: case t_COL: if (varncmp(gvar(x), v) <= 0) pari_err_PRIORITY("Ser", x, "<=", v); return RgV_to_ser_i(x, v, prec+2, 1); } return gtoser(x, v, prec); } GEN Ser0(GEN x, long v, GEN d, long prec) { if (!d) return gtoser(x, v, prec); if (typ(d) != t_INT) { d = gceil(d); if (typ(d) != t_INT) pari_err_TYPE("Ser [precision]",d); } return gtoser_prec(x, v, itos(d)); } pari-2.17.2/src/basemath/trans3.c0000644000175000017500000026173514676526175015156 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /********************************************************************/ /** **/ /** TRANSCENDENTAL FONCTIONS **/ /** (part 3) **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_trans #define HALF_E 1.3591409 /* exp(1) / 2 */ /***********************************************************************/ /** **/ /** BESSEL FUNCTIONS **/ /** **/ /***********************************************************************/ static GEN _abs(GEN x) { return gabs(gtofp(x,LOWDEFAULTPREC), LOWDEFAULTPREC); } /* can we use asymptotic expansion ? */ static int bessel_asymp(GEN n, GEN z, long bit) { GEN Z, N; long t = typ(n); if (!is_real_t(t) && t != t_COMPLEX) return 0; Z = _abs(z); N = gaddgs(_abs(n), 1); return gcmpgs(gdiv(Z, gsqr(N)), (bit+10)/2) >= 0; } /* Region I: 0 < Arg z <= Pi, II: -Pi < Arg z <= 0 */ static int regI(GEN z) { long s = gsigne(imag_i(z)); return (s > 0 || (s == 0 && gsigne(real_i(z)) < 0)) ? 1 : 2; } /* Region 1: Re(z) >= 0, 2: Re(z) < 0, Im(z) >= 0, 3: Re(z) < 0, Im(z) < 0 */ static int regJ(GEN z) { if (gsigne(real_i(z)) >= 0) return 1; return gsigne(imag_i(z)) >= 0 ? 2 : 3; } /* Hankel's expansions: * a_k(n) = \prod_{0 <= j < k} (4n^2 - (2j+1)^2) * C(k)[n,z] = a_k(n) / (k! (8 z)^k) * A(z) = exp(-z) sum_{k >= 0} C(k) * A(-z) = exp(z) sum_{k >= 0} (-1)^k C(k) * J_n(z) ~ [1] (A(z/i) / r + A(-z/i) r) / sqrt(2Pi z) * [2] (A(z/i) r^3 + A(-z/i) r) / sqrt(2Pi z) * [3] (A(z/i) / r + A(-z/i) / r^3) / sqrt(2Pi z) * Y_n(z) ~ [1] i(A(z/i) / r + A(-z/i) r) / sqrt(2Pi z) * [2] i(A(z/i) (r^3-2/r) + A(-z/i) r) / sqrt(2Pi z) * [3] i(-A(z/i)/r + A(-z/i)(2r-1/r^3)) / sqrt(2Pi z) * K_n(z) ~ A(z) Pi / sqrt(2 Pi z) * I_n(z) ~ [I] (A(-z) + r^2 A(z)) / sqrt(2 Pi z) * [II](A(-z) + r^(-2) A(z)) / sqrt(2 Pi z) */ /* set [A(z), A(-z), exp((2*nu+1)*I*Pi/4)] */ static void hankel_ABr(GEN *pA, GEN *pB, GEN *pr, GEN n, GEN z, long bit) { GEN E, P, C, Q = gen_0, zi = ginv(gmul2n(z, 3)); GEN K = gaddgs(_abs(n), 1), n2 = gmul2n(gsqr(n),2); long prec = nbits2prec(bit), B = bit + 4, m; P = C = real_1_bit(bit); for (m = 1;; m += 2) { C = gmul(C, gdivgu(gmul(gsub(n2, sqru(2*m - 1)), zi), m)); Q = gadd(Q, C); C = gmul(C, gdivgu(gmul(gsub(n2, sqru(2*m + 1)), zi), m + 1)); P = gadd(P, C); if (gexpo(C) < -B && gcmpgs(K, m) <= 0) break; } E = gexp(z, prec); *pA = gdiv(gadd(P, Q), E); *pB = gmul(gsub(P, Q), E); *pr = gexp(mulcxI(gmul(gaddgs(gmul2n(n,1), 1), Pi2n(-2, prec))), prec); } /* sqrt(2*Pi*z) */ static GEN sqz(GEN z, long bit) { long prec = nbits2prec(bit); return gsqrt(gmul(Pi2n(1, prec), z), prec); } static GEN besskasymp(GEN nu, GEN z, long bit) { GEN A, B, r; long prec = nbits2prec(bit); hankel_ABr(&A,&B,&r, nu, z, bit); return gdiv(gmul(A, mppi(prec)), sqz(z, bit)); } static GEN bessiasymp(GEN nu, GEN z, long bit) { GEN A, B, r, R, r2; hankel_ABr(&A,&B,&r, nu, z, bit); r2 = gsqr(r); R = regI(z) == 1 ? gmul(A, r2) : gdiv(A, r2); return gdiv(gadd(B, R), sqz(z, bit)); } static GEN bessjasymp(GEN nu, GEN z, long bit) { GEN A, B, r, R; long reg = regJ(z); hankel_ABr(&A,&B,&r, nu, mulcxmI(z), bit); if (reg == 1) R = gadd(gdiv(A, r), gmul(B, r)); else if (reg == 2) R = gadd(gmul(A, gpowgs(r, 3)), gmul(B, r)); else R = gadd(gdiv(A, r), gdiv(B, gpowgs(r, 3))); return gdiv(R, sqz(z, bit)); } static GEN bessyasymp(GEN nu, GEN z, long bit) { GEN A, B, r, R; long reg = regJ(z); hankel_ABr(&A,&B,&r, nu, mulcxmI(z), bit); if (reg == 1) R = gsub(gmul(B, r), gdiv(A, r)); else if (reg == 2) R = gadd(gmul(A, gsub(gpowgs(r, 3), gmul2n(ginv(r), 1))), gmul(B, r)); else R = gsub(gmul(B, gsub(gmul2n(r, 1), ginv(gpowgs(r, 3)))), gdiv(A, r)); return gdiv(mulcxI(R), sqz(z, bit)); } /* n! sum_{0 <= k <= m} x^k / (k!*(k+n)!) */ static GEN _jbessel(GEN n, GEN x, long m) { pari_sp av = avma; GEN s = gen_1; long k; for (k = m; k >= 1; k--) { s = gaddsg(1, gdiv(gmul(x,s), gmulgu(gaddgs(n, k), k))); if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"besselj"); s = gerepileupto(av, s); } } return s; } /* max(2, L * approximate solution to x log x = B) */ static long bessel_get_lim(double B, double L) { return maxss(2, L * exp(dbllambertW0(B))); } static GEN vjbesselh(void* E, GEN z, long prec){return jbesselh((GEN)E,z,prec);} static GEN vjbessel(void* E, GEN z, long prec) {return jbessel((GEN)E,z,prec);} static GEN vibessel(void* E, GEN z, long prec) {return ibessel((GEN)E,z,prec);} static GEN vnbessel(void* E, GEN z, long prec) {return nbessel((GEN)E,z,prec);} static GEN vkbessel(void* E, GEN z, long prec) {return kbessel((GEN)E,z,prec);} /* if J != 0 BesselJ, else BesselI. */ static GEN jbesselintern(GEN n, GEN z, long J, long prec) { const char *f = J? "besselj": "besseli"; long i, ki; pari_sp av = avma; GEN y; switch(typ(z)) { case t_INT: case t_FRAC: case t_REAL: case t_COMPLEX: { int flz0 = gequal0(z); long lim, k, precnew, bit; GEN p1, p2; double az, L; i = precision(z); if (i) prec = i; if (flz0 && gequal0(n)) return real_1(prec); bit = prec2nbits(prec); if (bessel_asymp(n, z, bit)) { GEN R = J? bessjasymp(n, z, bit): bessiasymp(n, z, bit); if (typ(R) == t_COMPLEX && isexactzero(imag_i(n)) && gsigne(real_i(z)) > 0 && isexactzero(imag_i(z))) R = gcopy(gel(R,1)); return gerepileupto(av, R); } p2 = gpow(gmul2n(z,-1),n,prec); p2 = gdiv(p2, ggamma(gaddgs(n,1),prec)); if (flz0) return gerepileupto(av, p2); az = dblmodulus(z); L = HALF_E * az; precnew = prec; if (az >= 1.0) precnew += 1 + nbits2extraprec((long)(az/M_LN2)); 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); lim = bessel_get_lim(prec2nbits_mul(prec,M_LN2/2) / L, L); z = gmul2n(gsqr(z),-2); if (J) z = gneg(z); p1 = gprec_wtrunc(_jbessel(n,z,lim), prec); return gerepileupto(av, gmul(p2,p1)); } case t_PADIC: pari_err_IMPL(stack_strcat("p-adic ",f)); default: { long v, k, m; if (!(y = toser_i(z))) break; if (issmall(n,&ki)) n = utoi(labs(ki)); y = gmul2n(gsqr(y),-2); if (J) y = gneg(y); v = valser(y); if (v < 0) pari_err_DOMAIN(f, "valuation", "<", gen_0, z); if (v == 0) pari_err_IMPL(stack_strcat(f, " around a!=0")); m = lg(y) - 2; k = m - (v >> 1); if (k <= 0) { set_avma(av); return scalarser(gen_1, varn(z), v); } setlg(y, k+2); return gerepileupto(av, _jbessel(n, y, m)); } } return trans_evalgen(f, (void*)n, J? vjbessel: vibessel, z, prec); } GEN jbessel(GEN n, GEN z, long prec) { return jbesselintern(n,z,1,prec); } GEN ibessel(GEN n, GEN z, long prec) { return jbesselintern(n,z,0,prec); } /* k > 0 */ static GEN _jbesselh(long k, GEN z, long prec) { GEN s, c, p0, p1, zinv = ginv(z); long i; gsincos(z,&s,&c,prec); p1 = gmul(zinv,s); p0 = p1; p1 = gmul(zinv,gsub(p0,c)); for (i = 2; i <= k; i++) { GEN p2 = gsub(gmul(gmulsg(2*i-1,zinv), p1), p0); p0 = p1; p1 = p2; } return p1; } /* J_{n+1/2}(z) */ GEN jbesselh(GEN n, GEN z, long prec) { long k, i; pari_sp av; GEN y; if (typ(n)!=t_INT) pari_err_TYPE("jbesselh",n); k = itos(n); if (k < 0) return jbessel(gadd(ghalf,n), z, prec); switch(typ(z)) { case t_INT: case t_FRAC: case t_REAL: case t_COMPLEX: { long pr; GEN p1; if (gequal0(z)) { av = avma; p1 = gmul(gsqrt(gdiv(z,mppi(prec)),prec),gpowgs(z,k)); p1 = gdiv(p1, mulu_interval(k+1, 2*k+1)); /* x k! / (2k+1)! */ return gerepileupto(av, gmul2n(p1,2*k)); } if ( (pr = precision(z)) ) prec = pr; if (bessel_asymp(n, z, prec2nbits(prec))) return jbessel(gadd(ghalf,n), z, prec); y = cgetc(prec); av = avma; p1 = gsqrt(gdiv(z, Pi2n(-1,prec)), prec); if (!k) p1 = gmul(p1, gsinc(z, prec)); else { long bits = BITS_IN_LONG + 2*k * (log2(k) - dbllog2(z)); if (bits > 0) { prec += nbits2extraprec(bits); if (pr) z = gtofp(z, prec); } p1 = gmul(p1, _jbesselh(k,z,prec)); } set_avma(av); return affc_fixlg(p1, y); } case t_PADIC: pari_err_IMPL("p-adic jbesselh function"); default: { long t, v; av = avma; if (!(y = toser_i(z))) break; if (gequal0(y)) return gerepileupto(av, gpowgs(y,k)); v = valser(y); if (v < 0) pari_err_DOMAIN("besseljh","valuation", "<", gen_0, z); t = lg(y)-2; if (v) y = sertoser(y, t + (2*k+1)*v); if (!k) y = gsinc(y,prec); else { GEN T, a = _jbesselh(k, y, prec); if (v) y = sertoser(y, t + k*v); /* lower precision */ y = gdiv(a, gpowgs(y, k)); T = cgetg(k+1, t_VECSMALL); for (i = 1; i <= k; i++) T[i] = 2*i+1; y = gmul(y, zv_prod_Z(T)); } return gerepileupto(av, y); } } return trans_evalgen("besseljh",(void*)n, vjbesselh, z, prec); } static GEN kbessel2(GEN nu, GEN x, long prec) { pari_sp av = avma; GEN p1, a, x2 = gshift(x,1); a = gtofp(gaddgs(gshift(nu,1), 1), prec); p1 = hyperu(gshift(a,-1), a, x2, prec); p1 = gmul(gmul(p1, gpow(x2,nu,prec)), sqrtr(mppi(prec))); return gerepileupto(av, gmul(p1, gexp(gneg(x),prec))); } /* special case of hyperu */ static GEN kbessel1(GEN nu, GEN gx, long prec) { GEN x, y, zf, r, u, pi, nu2; long bit, k, k2, n2, n, l = (typ(gx)==t_REAL)? realprec(gx): prec; pari_sp av; if (typ(nu)==t_COMPLEX) return kbessel2(nu, gx, l); y = cgetr(l); av = avma; x = gtofp(gx, l); nu = gtofp(nu,l); nu2 = sqrr(nu); shiftr_inplace(nu2,2); togglesign(nu2); /* nu2 = -4nu^2 */ n = (long) (prec2nbits_mul(l,M_LN2) + M_PI*fabs(rtodbl(nu))) / 2; bit = prec2nbits(l) - 1; l += EXTRAPREC64; pi = mppi(l); n2 = n<<1; r = gmul2n(x,1); if (cmprs(x, n) < 0) { pari_sp av2 = avma; GEN q, v, c, s = real_1(l), t = real_0(l); for (k = n2, k2 = 2*n2-1; k > 0; k--, k2 -= 2) { GEN ak = divri(addri(nu2, sqru(k2)), mulss(n2<<2, -k)); s = addsr(1, mulrr(ak,s)); t = addsr(k2,mulrr(ak,t)); if (gc_needed(av2,3)) gerepileall(av2, 2, &s,&t); } shiftr_inplace(t, -1); q = utor(n2, l); zf = sqrtr(divru(pi,n2)); u = gprec_wensure(mulrr(zf, s), l); v = gprec_wensure(divrs(addrr(mulrr(t,zf),mulrr(u,nu)),-n2), l); for(;;) { GEN p1, e, f, d = real_1(l); pari_sp av3; c = divur(5,q); if (expo(c) >= -1) c = real2n(-1,l); p1 = subsr(1, divrr(r,q)); if (cmprr(c,p1)>0) c = p1; togglesign(c); av3 = avma; e = u; f = v; for (k = 1;; k++) { 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)))); u = divru(mulrr(q,v), k); v = divru(w,k); d = mulrr(d,c); e = addrr(e, mulrr(d,u)); f = addrr(f, p1 = mulrr(d,v)); if (expo(p1) - expo(f) <= 1-prec2nbits(realprec(p1))) break; if (gc_needed(av3,3)) gerepileall(av3,5,&u,&v,&d,&e,&f); } u = e; v = f; q = mulrr(q, addrs(c,1)); if (expo(r) - expo(subrr(q,r)) >= bit) break; gerepileall(av2, 3, &u,&v,&q); } u = mulrr(u, gpow(divru(x,n),nu,prec)); } else { GEN s, zz = ginv(gmul2n(r,2)); pari_sp av2 = avma; s = real_1(l); for (k = n2, k2 = 2*n2-1; k > 0; k--, k2 -= 2) { GEN ak = divru(mulrr(addri(nu2, sqru(k2)), zz), k); s = subsr(1, mulrr(ak,s)); if (gc_needed(av2,3)) s = gerepileuptoleaf(av2, s); } zf = sqrtr(divrr(pi,r)); u = mulrr(s, zf); } affrr(mulrr(u, mpexp(negr(x))), y); set_avma(av); return y; } /* sum_{k=0}^m x^k (H(k)+H(k+n)) / (k! (k+n)!) * + sum_{k=0}^{n-1} (-x)^(k-n) (n-k-1)!/k! */ static GEN _kbessel(long n, GEN x, long m, long prec) { GEN p1, p2, s, H; long k, M = m + n, exact = (M <= prec2nbits(prec)); pari_sp av; H = cgetg(M+2,t_VEC); gel(H,1) = gen_0; if (exact) { gel(H,2) = s = gen_1; for (k=2; k<=M; k++) gel(H,k+1) = s = gdivgu(gaddsg(1,gmulsg(k,s)),k); } else { gel(H,2) = s = real_1(prec); for (k=2; k<=M; k++) gel(H,k+1) = s = divru(addsr(1,mulur(k,s)),k); } s = gadd(gel(H,m+1), gel(H,M+1)); av = avma; for (k = m; k > 0; k--) { s = gadd(gadd(gel(H,k),gel(H,k+n)), gdiv(gmul(x,s),mulss(k,k+n))); if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"_kbessel"); s = gerepileupto(av, s); } } p1 = exact? mpfact(n): mpfactr(n,prec); s = gdiv(s,p1); if (n) { x = gneg(ginv(x)); p2 = gmulsg(n, gdiv(x,p1)); s = gadd(s,p2); for (k=n-1; k>0; k--) { p2 = gmul(p2, gmul(mulss(k,n-k),x)); s = gadd(s,p2); } } return s; } /* N = 1: Bessel N, else Bessel K */ static GEN kbesselintern(GEN n, GEN z, long N, long prec) { const char *f = N? "besseln": "besselk"; long i, k, ki, lim, precnew, fl2, ex, bit; pari_sp av = avma; GEN p1, p2, y, p3, pp, pm, s, c; double az; switch(typ(z)) { case t_INT: case t_FRAC: case t_REAL: case t_COMPLEX: if (gequal0(z)) pari_err_DOMAIN(f, "argument", "=", gen_0, z); i = precision(z); if (i) prec = i; i = precision(n); if (i && prec > i) prec = i; bit = prec2nbits(prec); if (bessel_asymp(n, z, bit)) { GEN R = N? bessyasymp(n, z, bit): besskasymp(n, z, bit); if (typ(R) == t_COMPLEX && isexactzero(imag_i(n)) && gsigne(real_i(z)) > 0 && isexactzero(imag_i(z))) R = gcopy(gel(R,1)); return gerepileupto(av, R); } /* heuristic threshold */ if (!N && !gequal0(n) && gexpo(z) > bit/16 + gexpo(n)) return kbessel1(n,z,prec); az = dblmodulus(z); precnew = prec; if (az >= 1) precnew += 1 + nbits2extraprec((long)((N?az:2*az)/M_LN2)); z = gtofp(z, precnew); if (issmall(n,&ki)) { GEN z2 = gmul2n(z, -1), Z; double B, L = HALF_E * az; k = labs(ki); B = prec2nbits_mul(prec,M_LN2/2) / L; if (!N) B += 0.367879; /* exp(-1) */ lim = bessel_get_lim(B, L); Z = gsqr(z2); if (N) Z = gneg(Z); p1 = gmul(gpowgs(z2,k), _kbessel(k, Z, lim, precnew)); p2 = gadd(mpeuler(precnew), glog(z2,precnew)); p3 = jbesselintern(stoi(k),z,N,precnew); p2 = gsub(gmul2n(p1,-1),gmul(p2,p3)); p2 = gprec_wtrunc(p2, prec); if (N) { p2 = gdiv(p2, Pi2n(-1,prec)); if (ki >= 0 || !odd(k)) p2 = gneg(p2); } else if (odd(k)) 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) precnew += nbits2extraprec(N? -ex: -2*ex); if (i && i < precnew) { n = gtofp(n,precnew); z = gtofp(z,precnew); gsincos(gmul(n,mppi(precnew)), &s,&c,precnew); } pp = jbesselintern(n, z,N,precnew); pm = jbesselintern(gneg(n),z,N,precnew); if (N) p1 = gsub(gmul(c,pp),pm); else p1 = gmul(gsub(pm,pp), Pi2n(-1,precnew)); p1 = gdiv(p1, s); return gerepilecopy(av, gprec_wtrunc(p1,prec)); case t_PADIC: pari_err_IMPL(stack_strcat("p-adic ",f)); default: if (!(y = toser_i(z))) break; if (issmall(n,&ki)) { long v, mv, k = labs(ki), m = lg(y)-2; y = gmul2n(gsqr(y),-2); if (N) y = gneg(y); v = valser(y); if (v < 0) pari_err_DOMAIN(f, "valuation", "<", gen_0, z); if (v == 0) pari_err_IMPL(stack_strcat(f, " around a!=0")); mv = m - (v >> 1); if (mv <= 0) { set_avma(av); return scalarser(gen_1, varn(z), v); } setlg(y, mv+2); return gerepilecopy(av, _kbessel(k, y, m, prec)); } if (!issmall(gmul2n(n,1),&ki)) pari_err_DOMAIN(f, "2n mod Z", "!=", gen_0, n); k = labs(ki); n = gmul2n(stoi(k),-1); fl2 = (k&3)==1; pm = jbesselintern(gneg(n), y, N, prec); if (N) p1 = pm; else { pp = jbesselintern(n, y, N, prec); p2 = gpowgs(y,-k); if (fl2 == 0) p2 = gneg(p2); p3 = gmul2n(diviiexact(mpfact(k + 1),mpfact((k + 1) >> 1)),-(k + 1)); p3 = gdivgu(gmul2n(gsqr(p3),1),k); p2 = gmul(p2,p3); p1 = gsub(pp,gmul(p2,pm)); } return gerepileupto(av, fl2? gneg(p1): gcopy(p1)); } return trans_evalgen(f, (void*)n, N? vnbessel: vkbessel, z, prec); } GEN kbessel(GEN n, GEN z, long prec) { return kbesselintern(n,z,0,prec); } GEN ybessel(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; GEN J = jbessel(n,z,prec); GEN Y = ybessel(n,z,prec); return gerepileupto(av, gadd(J, mulcxI(Y))); } /* J - iN */ GEN hbessel2(GEN n, GEN z, long prec) { pari_sp av = avma; GEN J = jbessel(n,z,prec); GEN Y = ybessel(n,z,prec); return gerepileupto(av, gadd(J, mulcxmI(Y))); } static GEN besselrefine(GEN z, GEN nu, GEN (*B)(GEN,GEN,long), long bit) { GEN z0 = gprec_w(z, DEFAULTPREC), nu1 = gaddgs(nu, 1), t; long e, n, c, j, prec = DEFAULTPREC; t = gdiv(B(nu1, z0, prec), B(nu, z0, prec)); t = gadd(z0, gdiv(gsub(gsqr(z0), gsqr(nu)), gsub(gdiv(nu, z0), t))); e = gexpo(t) - 2 * gexpo(z0) - 1; if (e < 0) e = 0; n = expu(bit + 32 - e); c = 1 + e + ((bit - e) >> n); for (j = 1; j <= n; j++) { c = 2 * c - e; prec = nbits2prec(c); z = gprec_w(z, prec); t = gdiv(B(nu1, z, prec), B(nu, z, prec)); z = gsub(z, ginv(gsub(gdiv(nu, z), t))); } return gprec_w(z, nbits2prec(bit)); } /* solve tan(fi) - fi = y, y >= 0; Temme's method */ static double fi(double y) { double p, pp, r; if (y == 0) return 0; if (y > 100000) return M_PI/2; if (y < 1) { p = pow(3*y, 1.0/3); pp = p * p; p = p * (1 + pp * (-210 * pp + (27 - 2*pp)) / 1575); } else { p = 1 / (y + M_PI/2); pp = p * p; p = M_PI/2 - p*(1 + pp*(2310 + pp*(3003 + pp*(4818 + pp*(8591 + pp*16328)))) / 3465); } pp = (y + p) * (y + p); r = (p - atan(p + y)) / pp; return p - (1 + pp) * r * (1 + r / (p + y)); } static GEN besselzero(GEN nu, long n, GEN (*B)(GEN,GEN,long), long bit) { pari_sp av = avma; long prec = nbits2prec(bit); int J = B == jbessel; GEN z; if (n <= 0) pari_err_DOMAIN("besselzero", "n", "<=", gen_0, stoi(n)); if (n > LONG_MAX / 4) pari_err_OVERFLOW("besselzero"); if (is_real_t(typ(nu)) && gsigne(nu) >= 0) { /* Temme */ double x, c, b, a = gtodouble(nu), t = J? 0.25: 0.75; if (n >= 3*a - 8) { double aa = a*a, mu = 4*aa, mu2 = mu*mu, p, p0, p1, q1; p = 7 * mu - 31; p0 = mu-1; if (1 + p == p) /* p large */ p1 = q1 = 0; else { p1 = 4 * (253 * mu2 - 3722 * mu + 17869) / (15 * p); q1 = 1.6 * (83 * mu2 - 982 * mu + 3779) / p; } b = (n + a/2 - t) * M_PI; c = 1 / (64 * b * b); x = b - p0 * (1 - p1 * c) / (8 * b * (1 - q1 * c)); } else { double u, v, w, xx, bb = a >= 3? pow(a, -2./3): 1; if (n == 1) x = J? -2.33811: -1.17371; else { double pp1 = 5./48, qq1 = -5./36, y = 3./8 * M_PI; x = 4 * y * (n - t); v = 1 / (x*x); x = - pow(x, 2.0/3) * (1 + v * (pp1 + qq1 * v)); } u = x * bb; v = fi(2.0/3 * pow(-u, 1.5)); w = 1 / cos(v); xx = 1 - w*w; c = sqrt(u/xx); x = w * (a + c / (48*a*u) * (-5/u-c * (-10/xx + 6))); } z = dbltor(x); } else { /* generic, hope for the best */ long a = 4 * n - (J? 1: 3); GEN b, m; b = gmul(mppi(prec), gmul2n(gaddgs(gmul2n(nu,1), a), -2)); m = gmul2n(gsqr(nu),2); z = gsub(b, gdiv(gsubgs(m, 1), gmul2n(b, 3))); } return gerepilecopy(av, besselrefine(z, nu, B, bit)); } GEN besseljzero(GEN nu, long k, long b) { return besselzero(nu, k, jbessel, b); } GEN besselyzero(GEN nu, long k, long b) { return besselzero(nu, k, ybessel, b); } /***********************************************************************/ /** INCOMPLETE GAMMA FUNCTION **/ /***********************************************************************/ /* mx ~ |x|, b = bit accuracy */ static int gamma_use_asymp(GEN x, long b) { long e; if (is_real_t(typ(x))) { pari_sp av = avma; return gc_int(av, gcmpgs(R_abs_shallow(x), 3*b / 4) >= 0); } e = gexpo(x); return e >= b || dblmodulus(x) >= 3*b / 4; } /* x a t_REAL */ static GEN eint1r_asymp(GEN x, GEN expx, long prec) { pari_sp av = avma, av2; GEN S, q, z, ix; long oldeq = LONG_MAX, esx = -prec2nbits(prec), j; if (realprec(x) < prec + EXTRAPREC64) x = rtor(x, prec+EXTRAPREC64); ix = invr(x); q = z = negr(ix); av2 = avma; S = addrs(q, 1); for (j = 2;; j++) { long eq = expo(q); if (eq < esx) break; if ((j & 3) == 0) { /* guard against divergence */ if (eq > oldeq) return gc_NULL(av); /* regressing, abort */ oldeq = eq; } q = mulrr(q, mulru(z, j)); S = addrr(S, q); if (gc_needed(av2, 1)) gerepileall(av2, 2, &S, &q); } if (DEBUGLEVEL > 2) err_printf("eint1: using asymp\n"); S = expx? divrr(S, expx): mulrr(S, mpexp(negr(x))); return gerepileuptoleaf(av, mulrr(S, ix)); } /* cf incgam_asymp(0, x); z = -1/x * exp(-x)/x * (1 + z + 2! z^2 + ...) */ static GEN eint1_asymp(GEN x, GEN expx, long prec) { pari_sp av = avma, av2; GEN S, q, z, ix; long oldeq = LONG_MAX, esx = -prec2nbits(prec), j; if (typ(x) != t_REAL) x = gtofp(x, prec+EXTRAPREC64); if (typ(x) == t_REAL) return eint1r_asymp(x, expx, prec); ix = ginv(x); q = z = gneg_i(ix); av2 = avma; S = gaddgs(q, 1); for (j = 2;; j++) { long eq = gexpo(q); if (eq < esx) break; if ((j & 3) == 0) { /* guard against divergence */ if (eq > oldeq) return gc_NULL(av); /* regressing, abort */ oldeq = eq; } q = gmul(q, gmulgu(z, j)); S = gadd(S, q); if (gc_needed(av2, 1)) gerepileall(av2, 2, &S, &q); } if (DEBUGLEVEL > 2) err_printf("eint1: using asymp\n"); S = expx? gdiv(S, expx): gmul(S, gexp(gneg_i(x), prec)); return gerepileupto(av, gmul(S, ix)); } /* eint1(x) = incgam(0, x); typ(x) = t_REAL, x > 0 */ static GEN eint1p(GEN x, GEN expx) { pari_sp av; long l = realprec(x), bit = prec2nbits(l), prec, i; double mx; GEN z, S, t, H, run; if (gamma_use_asymp(x, bit) && (z = eint1r_asymp(x, expx, l))) return z; mx = rtodbl(x); prec = l + nbits2extraprec((mx+log(mx))/M_LN2 + 10); bit = prec2nbits(prec); run = real_1(prec); x = rtor(x, prec); av = avma; S = z = t = H = run; for (i = 2; expo(S) - expo(t) <= bit; i++) { H = addrr(H, divru(run,i)); /* H = sum_{k<=i} 1/k */ z = divru(mulrr(x,z), i); /* z = x^(i-1)/i! */ t = mulrr(z, H); S = addrr(S, t); if ((i & 0x1ff) == 0) gerepileall(av, 4, &z,&t,&S,&H); } return subrr(mulrr(x, divrr(S,expx? expx: mpexp(x))), addrr(mplog(x), mpeuler(prec))); } /* eint1(x) = incgam(0, x); typ(x) = t_REAL, x < 0 * rewritten from code contributed by Manfred Radimersky */ static GEN eint1m(GEN x, GEN expx) { GEN p1, q, S, y, z = cgetg(3, t_COMPLEX); long l = realprec(x), n = prec2nbits(l), j; pari_sp av = avma; y = rtor(x, l + EXTRAPREC64); setsigne(y,1); /* |x| */ if (gamma_use_asymp(y, n)) { /* ~eint1_asymp: asymptotic expansion */ p1 = q = invr(y); S = addrs(q, 1); for (j = 2; expo(q) >= -n; j++) { q = mulrr(q, mulru(p1, j)); S = addrr(S, q); } y = mulrr(p1, expx? divrr(S, expx): mulrr(S, mpexp(y))); } else { p1 = q = S = y; for (j = 2; expo(q) - expo(S) >= -n; j++) { p1 = mulrr(y, divru(p1, j)); /* (-x)^j/j! */ q = divru(p1, j); S = addrr(S, q); } y = addrr(S, addrr(logr_abs(x), mpeuler(l))); } y = gerepileuptoleaf(av, y); togglesign(y); gel(z, 1) = y; y = mppi(l); setsigne(y, -1); gel(z, 2) = y; return z; } /* real(z*log(z)-z), z = x+iy */ static double mygamma(double x, double y) { if (x == 0.) return -(M_PI/2)*fabs(y); return (x/2)*log(x*x+y*y)-x-y*atan(y/x); } /* x^s exp(-x) */ static GEN expmx_xs(GEN s, GEN x, GEN logx, long prec) { GEN z; long ts = typ(s); if (ts == t_INT || (ts == t_FRAC && absequaliu(gel(s,2), 2))) z = gmul(gexp(gneg(x), prec), gpow(x, s, prec)); else z = gexp(gsub(gmul(s, logx? logx: glog(x,prec+EXTRAPREC64)), x), prec); return z; } /* Not yet: doesn't work at low accuracy #define INCGAM_CF */ #ifdef INCGAM_CF /* Is s very close to a nonpositive integer ? */ static int isgammapole(GEN s, long bitprec) { pari_sp av = avma; GEN t = imag_i(s); long e, b = bitprec - 10; if (gexpo(t) > - b) return 0; s = real_i(s); if (gsigne(s) > 0 && gexpo(s) > -b) return 0; (void)grndtoi(s, &e); return gc_bool(av, e < -b); } /* incgam using the continued fraction. x a t_REAL or t_COMPLEX, mx ~ |x|. * Assume precision(s), precision(x) >= prec */ static GEN incgam_cf(GEN s, GEN x, double mx, long prec) { GEN ms, y, S; long n, i, j, LS, bitprec = prec2nbits(prec); double rs, is, m; if (typ(s) == t_COMPLEX) { rs = gtodouble(gel(s,1)); is = gtodouble(gel(s,2)); } else { rs = gtodouble(s); is = 0.; } if (isgammapole(s, bitprec)) LS = 0; else { double bit, LGS = mygamma(rs,is); LS = LGS <= 0 ? 0: ceil(LGS); bit = (LGS - (rs-1)*log(mx) + mx)/M_LN2; if (bit > 0) { prec += nbits2extraprec((long)bit); x = gtofp(x, prec); if (isinexactreal(s)) s = gtofp(s, prec); } } /* |ln(2*gamma(s)*sin(s*Pi))| <= ln(2) + |lngamma(s)| + |Im(s)*Pi|*/ m = bitprec*M_LN2 + LS + M_LN2 + fabs(is)*M_PI + mx; if (rs < 1) m += (1 - rs)*log(mx); m /= 4; n = (long)(1 + m*m/mx); y = expmx_xs(gsubgs(s,1), x, NULL, prec); if (rs >= 0 && bitprec >= 512) { GEN A = cgetg(n+1, t_VEC), B = cgetg(n+1, t_VEC); ms = gsubsg(1, s); for (j = 1; j <= n; ++j) { gel(A,j) = ms; gel(B,j) = gmulsg(j, gsubgs(s,j)); ms = gaddgs(ms, 2); } S = contfraceval_inv(mkvec2(A,B), x, -1); } else { GEN x_s = gsub(x, s); pari_sp av2 = avma; S = gdiv(gsubgs(s,n), gaddgs(x_s,n<<1)); for (i=n-1; i >= 1; i--) { S = gdiv(gsubgs(s,i), gadd(gaddgs(x_s,i<<1),gmulsg(i,S))); if (gc_needed(av2,3)) { if(DEBUGMEM>1) pari_warn(warnmem,"incgam_cf"); S = gerepileupto(av2, S); } } S = gaddgs(S,1); } return gmul(y, S); } #endif static double findextraincgam(GEN s, GEN x) { double sig = gtodouble(real_i(s)), t = gtodouble(imag_i(s)); double xr = gtodouble(real_i(x)), xi = gtodouble(imag_i(x)); double exd = 0., Nx = xr*xr + xi*xi, D = Nx - t*t; long n; if (xr < 0) { long ex = gexpo(x); if (ex > 0 && ex > gexpo(s)) exd = sqrt(Nx)*log(Nx)/2; /* |x| log |x| */ } if (D <= 0.) return exd; n = (long)(sqrt(D)-sig); if (n <= 0) return exd; return maxdd(exd, (n*log(Nx)/2 - mygamma(sig+n, t) + mygamma(sig, t)) / M_LN2); } /* use exp(-x) * (x^s/s) * sum_{k >= 0} x^k / prod(i=1, k, s+i) */ static GEN incgamc_i(GEN s, GEN x, long *ptexd, long prec) { GEN S, t, y; long l, n, i, exd; pari_sp av = avma, av2; if (gequal0(x)) { if (ptexd) *ptexd = 0.; return gtofp(x, prec); } l = precision(x); if (!l) l = prec; n = -prec2nbits(l)-1; exd = (long)findextraincgam(s, x); if (ptexd) *ptexd = exd; if (exd > 0) { long p = l + nbits2extraprec(exd); x = gtofp(x, p); if (isinexactreal(s)) s = gtofp(s, p); } else x = gtofp(x, l+EXTRAPREC64); av2 = avma; S = gdiv(x, gaddsg(1,s)); t = gaddsg(1, S); for (i=2; gexpo(S) >= n; i++) { S = gdiv(gmul(x,S), gaddsg(i,s)); /* x^i / ((s+1)...(s+i)) */ t = gadd(S,t); if (gc_needed(av2,3)) { if(DEBUGMEM>1) pari_warn(warnmem,"incgamc"); gerepileall(av2, 2, &S, &t); } } y = expmx_xs(s, x, NULL, prec); return gerepileupto(av, gmul(gdiv(y,s), t)); } GEN incgamc(GEN s, GEN x, long prec) { return incgamc_i(s, x, NULL, prec); } /* incgamma using asymptotic expansion: * exp(-x)x^(s-1)(1 + (s-1)/x + (s-1)(s-2)/x^2 + ...) */ static GEN incgam_asymp(GEN s, GEN x, long prec) { pari_sp av = avma, av2; GEN S, q, cox, invx; long oldeq = LONG_MAX, eq, esx, j; int flint = (typ(s) == t_INT && signe(s) > 0); x = gtofp(x,prec+EXTRAPREC64); invx = ginv(x); esx = -prec2nbits(prec); av2 = avma; q = gmul(gsubgs(s,1), invx); S = gaddgs(q, 1); for (j = 2;; j++) { eq = gexpo(q); if (eq < esx) break; if (!flint && (j & 3) == 0) { /* guard against divergence */ if (eq > oldeq) return gc_NULL(av); /* regressing, abort */ oldeq = eq; } q = gmul(q, gmul(gsubgs(s,j), invx)); S = gadd(S, q); if (gc_needed(av2, 1)) gerepileall(av2, 2, &S, &q); } if (DEBUGLEVEL > 2) err_printf("incgam: using asymp\n"); cox = expmx_xs(gsubgs(s,1), x, NULL, prec); return gerepileupto(av, gmul(cox, S)); } /* gasx = incgam(s-n,x). Compute incgam(s,x) * = (s-1)(s-2)...(s-n)gasx + exp(-x)x^(s-1) * * (1 + (s-1)/x + ... + (s-1)(s-2)...(s-n+1)/x^(n-1)) */ static GEN incgam_asymp_partial(GEN s, GEN x, GEN gasx, long n, long prec) { pari_sp av; GEN S, q, cox, invx, s1 = gsubgs(s, 1), sprod; long j; cox = expmx_xs(s1, x, NULL, prec); if (n == 1) return gadd(cox, gmul(s1, gasx)); invx = ginv(x); av = avma; q = gmul(s1, invx); S = gaddgs(q, 1); for (j = 2; j < n; j++) { q = gmul(q, gmul(gsubgs(s, j), invx)); S = gadd(S, q); if (gc_needed(av, 2)) gerepileall(av, 2, &S, &q); } sprod = gmul(gmul(q, gpowgs(x, n-1)), gsubgs(s, n)); return gadd(gmul(cox, S), gmul(sprod, gasx)); } /* Assume s != 0; called when Re(s) <= 1/2 */ static GEN incgamspec(GEN s, GEN x, GEN g, long prec) { GEN q, S, cox = gen_0, P, sk, S1, S2, S3, F3, logx, mx; long n, esk, E, k = itos(ground(gneg(real_i(s)))); /* >= 0 */ if (k && gexpo(x) > 0) { GEN xk = gdivgu(x, k); long bitprec = prec2nbits(prec); double d = (gexpo(xk) > bitprec)? bitprec*M_LN2: log(dblmodulus(xk)); d = k * (d + 1) / M_LN2; if (d > 0) prec += nbits2extraprec((long)d); if (isinexactreal(s)) s = gtofp(s, prec); } x = gtofp(x, maxss(precision(x), prec) + EXTRAPREC64); sk = gaddgs(s, k); /* |Re(sk)| <= 1/2 */ logx = glog(x, prec); mx = gneg(x); if (k == 0) { S = gen_0; P = gen_1; } else { long j; q = ginv(s); S = q; P = s; for (j = 1; j < k; j++) { GEN sj = gaddgs(s, j); q = gmul(q, gdiv(x, sj)); S = gadd(S, q); P = gmul(P, sj); } cox = expmx_xs(s, x, logx, prec); /* x^s exp(-x) */ S = gmul(S, gneg(cox)); } if (k && gequal0(sk)) return gadd(S, gdiv(eint1(x, prec), P)); esk = gexpo(sk); if (esk > -7) { GEN a, b, PG = gmul(sk, P); if (g) g = gmul(g, PG); a = incgam0(gaddgs(sk,1), x, g, prec); if (k == 0) cox = expmx_xs(s, x, logx, prec); b = gmul(gpowgs(x, k), cox); return gadd(S, gdiv(gsub(a, b), PG)); } E = prec2nbits(prec) + 1; if (gexpo(x) > 0) { long X = (long)(dblmodulus(x)/M_LN2); prec += 2*nbits2extraprec(X); x = gtofp(x, prec); mx = gneg(x); logx = glog(x, prec); sk = gtofp(sk, prec); E += X; } if (isinexactreal(sk)) sk = gtofp(sk, prec+EXTRAPREC64); /* |sk| < 2^-7 is small, guard against cancellation */ F3 = gexpm1(gmul(sk, logx), prec); /* ( gamma(1+sk) - exp(sk log(x))) ) / sk */ S1 = gdiv(gsub(ggamma1m1(sk, prec+EXTRAPREC64), F3), sk); q = x; S3 = gdiv(x, gaddsg(1,sk)); for (n = 2; gexpo(q) - gexpo(S3) > -E; n++) { q = gmul(q, gdivgu(mx, n)); S3 = gadd(S3, gdiv(q, gaddsg(n, sk))); } S2 = gadd(gadd(S1, S3), gmul(F3, S3)); return gadd(S, gdiv(S2, P)); } /* return |x| */ double dblmodulus(GEN x) { if (typ(x) == t_COMPLEX) { double a = gtodouble(gel(x,1)); double b = gtodouble(gel(x,2)); return sqrt(a*a + b*b); } else return fabs(gtodouble(x)); } /* Driver routine. If g != NULL, assume that g=gamma(s,prec). */ GEN incgam0(GEN s, GEN x, GEN g, long prec) { pari_sp av; long E, l; GEN z, rs, is; if (gequal0(x)) return g? gcopy(g): ggamma(s,prec); if (gequal0(s)) return eint1(x, prec); l = precision(s); if (!l) l = prec; E = prec2nbits(l); if (gamma_use_asymp(x, E) || (typ(s) == t_INT && signe(s) > 0 && gexpo(x) >= expi(s))) if ((z = incgam_asymp(s, x, l))) return z; av = avma; E++; rs = real_i(s); is = imag_i(s); #ifdef INCGAM_CF /* Can one use continued fraction ? */ if (gequal0(is) && gequal0(imag_i(x)) && gsigne(x) > 0) { double sd = gtodouble(rs), LB, UB; double xd = gtodouble(real_i(x)); if (sd > 0) { LB = 15 + 0.1205*E; UB = 5 + 0.752*E; } else { LB = -6 + 0.1205*E; UB = 5 + 0.752*E + fabs(sd)/54.; } if (xd >= LB && xd <= UB) { if (DEBUGLEVEL > 2) err_printf("incgam: using continued fraction\n"); return gerepileupto(av, incgam_cf(s, x, xd, prec)); } } #endif if (gsigne(rs) > 0 && gexpo(rs) >= -1) { /* use complementary incomplete gamma */ long n, egs, exd, precg, es = gexpo(s); if (es < 0) { l += nbits2extraprec(-es) + 1; x = gtofp(x, l); if (isinexactreal(s)) s = gtofp(s, l); } n = itos(gceil(rs)); if (n > 100) { GEN gasx; n -= 100; if (es > 0) { es = mygamma(gtodouble(rs) - n, gtodouble(is)) / M_LN2; if (es > 0) { l += nbits2extraprec(es); x = gtofp(x, l); if (isinexactreal(s)) s = gtofp(s, l); } } gasx = incgam0(gsubgs(s, n), x, NULL, prec); return gerepileupto(av, incgam_asymp_partial(s, x, gasx, n, prec)); } if (DEBUGLEVEL > 2) err_printf("incgam: using power series 1\n"); /* egs ~ expo(gamma(s)) */ precg = g? precision(g): 0; egs = g? gexpo(g): (long)(mygamma(gtodouble(rs), gtodouble(is)) / M_LN2); if (egs > 0) { l += nbits2extraprec(egs) + 1; x = gtofp(x, l); if (isinexactreal(s)) s = gtofp(s, l); if (precg < l) g = NULL; } z = incgamc_i(s, x, &exd, l); if (exd > 0) { l += nbits2extraprec(exd); if (isinexactreal(s)) s = gtofp(s, l); if (precg < l) g = NULL; } else { /* gamma(s) negligible ? Compute to lower accuracy */ long e = gexpo(z) - egs; if (e > 3) { E -= e; if (E <= 0) g = gen_0; else if (!g) g = ggamma(s, nbits2prec(E)); } } /* worry about possible cancellation */ if (!g) g = ggamma(s, maxss(l,precision(z))); return gerepileupto(av, gsub(g,z)); } if (DEBUGLEVEL > 2) err_printf("incgam: using power series 2\n"); return gerepileupto(av, incgamspec(s, x, g, l)); } GEN incgam(GEN s, GEN x, long prec) { return incgam0(s, x, NULL, prec); } /* x a t_REAL */ GEN mpeint1(GEN x, GEN expx) { long s = signe(x); pari_sp av; GEN z; if (!s) pari_err_DOMAIN("eint1", "x","=",gen_0, x); if (s < 0) return eint1m(x, expx); z = cgetr(realprec(x)); av = avma; affrr(eint1p(x, expx), z); set_avma(av); return z; } static GEN cxeint1(GEN x, long prec) { pari_sp av = avma, av2; GEN q, S, run, z, H; long n, E = prec2nbits(prec); if (gamma_use_asymp(x, E) && (z = eint1_asymp(x, NULL, prec))) return z; E++; if (gexpo(x) > 0) { /* take cancellation into account, log2(\sum |x|^n / n!) = |x| / log(2) */ double dbx = dblmodulus(x); long X = (long)((dbx + log(dbx))/M_LN2 + 10); prec += nbits2extraprec(X); x = gtofp(x, prec); E += X; } if (DEBUGLEVEL > 2) err_printf("eint1: using power series\n"); run = real_1(prec); av2 = avma; S = z = q = H = run; for (n = 2; gexpo(q) - gexpo(S) >= -E; n++) { H = addrr(H, divru(run, n)); /* H = sum_{k<=n} 1/k */ z = gdivgu(gmul(x,z), n); /* z = x^(n-1)/n! */ q = gmul(z, H); S = gadd(S, q); if ((n & 0x1ff) == 0) gerepileall(av2, 4, &z, &q, &S, &H); } S = gmul(gmul(x, S), gexp(gneg_i(x), prec)); return gerepileupto(av, gsub(S, gadd(glog(x, prec), mpeuler(prec)))); } GEN eint1(GEN x, long prec) { switch(typ(x)) { case t_COMPLEX: return cxeint1(x, prec); case t_REAL: break; default: x = gtofp(x, prec); } return mpeint1(x,NULL); } GEN veceint1(GEN C, GEN nmax, long prec) { if (!nmax) return eint1(C,prec); if (typ(nmax) != t_INT) pari_err_TYPE("veceint1",nmax); if (typ(C) != t_REAL) { C = gtofp(C, prec); if (typ(C) != t_REAL) pari_err_TYPE("veceint1",C); } if (signe(C) <= 0) pari_err_DOMAIN("veceint1", "argument", "<=", gen_0,C); return mpveceint1(C, NULL, itos(nmax)); } /* j > 0, a t_REAL. Return sum_{m >= 0} a^m / j(j+1)...(j+m)). * Stop when expo(summand) < E; note that s(j-1) = (a s(j) + 1) / (j-1). */ static GEN mp_sum_j(GEN a, long j, long E, long prec) { pari_sp av = avma; GEN q = divru(real_1(prec), j), s = q; long m; for (m = 0;; m++) { if (expo(q) < E) break; q = mulrr(q, divru(a, m+j)); s = addrr(s, q); } return gerepileuptoleaf(av, s); } /* Return the s_a(j), j <= J */ static GEN sum_jall(GEN a, long J, long prec) { GEN s = cgetg(J+1, t_VEC); long j, E = -prec2nbits(prec) - 5; gel(s, J) = mp_sum_j(a, J, E, prec); for (j = J-1; j; j--) gel(s,j) = divru(addrs(mulrr(a, gel(s,j+1)), 1), j); return s; } /* T a dense t_POL with t_REAL coeffs. Return T(n) [faster than poleval] */ static GEN rX_s_eval(GEN T, long n) { long i = lg(T)-1; GEN c = gel(T,i); for (i--; i>=2; i--) c = gadd(mulrs(c,n),gel(T,i)); return c; } /* C>0 t_REAL, eC = exp(C). Return eint1(n*C) for 1<=n<=N. Absolute accuracy */ GEN mpveceint1(GEN C, GEN eC, long N) { const long prec = realprec(C); long Nmin = 15; /* >= 1. E.g. between 10 and 30, but little effect */ GEN en, v, w = cgetg(N+1, t_VEC); pari_sp av0; double DL; long n, j, jmax, jmin; if (!N) return w; for (n = 1; n <= N; n++) gel(w,n) = cgetr(prec); av0 = avma; if (N < Nmin) Nmin = N; if (!eC) eC = mpexp(C); en = eC; affrr(eint1p(C, en), gel(w,1)); for (n = 2; n <= Nmin; n++) { pari_sp av2; en = mulrr(en,eC); /* exp(n C) */ av2 = avma; affrr(eint1p(mulru(C,n), en), gel(w,n)); set_avma(av2); } if (Nmin == N) { set_avma(av0); return w; } DL = prec2nbits_mul(prec, M_LN2) + 5; jmin = ceil(DL/log((double)N)) + 1; jmax = ceil(DL/log((double)Nmin)) + 1; v = sum_jall(C, jmax, prec); en = powrs(eC, -N); /* exp(-N C) */ affrr(eint1p(mulru(C,N), invr(en)), gel(w,N)); for (j = jmin, n = N-1; j <= jmax; j++) { long limN = maxss((long)ceil(exp(DL/j)), Nmin); GEN polsh; setlg(v, j+1); polsh = RgV_to_RgX_reverse(v, 0); for (; n >= limN; n--) { pari_sp av2 = avma; GEN S = divri(mulrr(en, rX_s_eval(polsh, -n)), powuu(n,j)); /* w[n+1] - exp(-n C) * polsh(-n) / (-n)^j */ GEN c = odd(j)? addrr(gel(w,n+1), S) : subrr(gel(w,n+1), S); affrr(c, gel(w,n)); set_avma(av2); en = mulrr(en,eC); /* exp(-n C) */ } } set_avma(av0); return w; } /* erfc via numerical integration : assume real(x)>=1 */ static GEN cxerfc_r1(GEN x, long prec) { GEN h, h2, eh2, denom, res, lambda; long u, v; const double D = prec2nbits_mul(prec, M_LN2); const long npoints = (long)ceil(D/M_PI)+1; pari_sp av = avma; { double t = exp(-2*M_PI*M_PI/D); /* ~exp(-2*h^2) */ v = 30; /* bits that fit in both long and double mantissa */ u = (long)floor(t*(1L< 0 || (s == 0 && signe(xi) >= 0)) { if (cmprs(xr, 1) > 0) /* use numerical integration */ z = cxerfc_r1(x, prec); else { /* erfc(x) = incgam(1/2,x^2)/sqrt(Pi) */ GEN sqrtpi = sqrtr(mppi(prec)); z = incgam0(ghalf, gsqr(x), sqrtpi, prec); z = gdiv(z, sqrtpi); } } else { /* erfc(-x)=2-erfc(x) */ /* FIXME could decrease prec long size = nbits2extraprec((imag(x)^2-real(x)^2)/log(2)); 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+EXTRAPREC64), gerfc(gneg(x), prec)); } set_avma(av); return affc_fixlg(z, res); } /***********************************************************************/ /** **/ /** RIEMANN ZETA FUNCTION **/ /** **/ /***********************************************************************/ 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 + M_PI/2.0; for(;;) { y0 = x0*x0; x1 = (beta+atan(x0)) * (1+y0) / y0 - 1/x0; if (0.99*x0 < x1) return x1; x0 = x1; } } /* optimize for zeta( s + it, prec ), assume |s-1| > 0.1 * (if gexpo(u = s-1) < -5, we use the functional equation s->1-s) */ static int optim_zeta(GEN S, long prec, long *pp, long *pn) { double s, t, alpha, beta, n, B; long p; if (typ(S) == t_REAL) { t = 0.; s = rtodbl(S); } else { t = fabs( rtodbl(gel(S,2)) ); if (t > 2500) return 0; /* lfunlarge */ s = rtodbl(gel(S,1)); } B = prec2nbits_mul(prec, M_LN2); if (s > 0 && !t) /* positive real input */ { beta = B + 0.61 + s*(log2PI - log(s)); if (beta > 0) { p = (long)ceil(beta / 2.0); n = fabs(s + 2*p-1)/(2*M_PI); } else { p = 0; n = exp((B - M_LN2) / s); } } else if (s <= 0 || t < 0.01) /* s < 0 may occur if s ~ 0 */ { /* TODO: the crude bounds below are generally valid. Optimize ? */ double l,l2, la = 1.; /* heuristic */ double rlog, ilog; dcxlog(s-1,t, &rlog,&ilog); l2 = (s - 0.5)*rlog - t*ilog; /* = Re( (S - 1/2) log (S-1) ) */ l = (B - l2 + s*log2PI) / (2. * (1.+ log((double)la))); l2 = dabs(s, t)/2; if (l < l2) l = l2; p = (long) ceil(l); if (p < 2) p = 2; n = 1 + dabs(p+s/2.-.25, t/2) * la / M_PI; } else { double sn = dabs(s, t), L = log(sn/s); alpha = B - 0.39 + L + s*(log2PI - log(sn)); beta = (alpha+s)/t - atan(s/t); p = 0; if (beta > 0) { beta = 1.0 - s + t * get_xinf(beta); if (beta > 0) p = (long)ceil(beta / 2.0); } else if (s < 1.0) p = 1; n = p? dabs(s + 2*p-1, t) / (2*M_PI) : exp((B-M_LN2+L) / s); } *pp = p; *pn = (long)ceil(n); if (*pp < 0 || *pn < 0) pari_err_OVERFLOW("zeta"); return 1; } /* zeta(a*j+b), j=0..N-1, b>1, using sumalt. Johansonn's thesis, Algo 4.7.1 */ static GEN veczetas(long a, long b, long N, long prec) { const long n = ceil(2 + prec2nbits_mul(prec, M_LN2/1.7627)); pari_sp av = avma; GEN c, d, z = zerovec(N); long j, k; c = d = int2n(2*n-1); for (k = n; k > 1; k--) { GEN u, t = divii(d, powuu(k,b)); if (!odd(k)) t = negi(t); gel(z,1) = addii(gel(z,1), t); u = powuu(k,a); for (j = 1; j < N; j++) { t = divii(t,u); if (!signe(t)) break; gel(z,j+1) = addii(gel(z,j+1), t); } c = muluui(k,2*k-1,c); c = diviuuexact(c, 2*(n-k+1),n+k-1); d = addii(d,c); if (gc_needed(av,3)) { if(DEBUGMEM>1) pari_warn(warnmem,"zetaBorwein, k = %ld", k); gerepileall(av, 3, &c,&d,&z); } } /* k = 1 */ for (j = 1; j <= N; j++) gel(z,j) = addii(gel(z,j), d); d = addiu(d, 1); for (j = 0, k = b - 1; j < N; j++, k += a) gel(z,j+1) = rdivii(shifti(gel(z,j+1), k), subii(shifti(d,k), d), prec); return z; } /* zeta(a*j+b), j=0..N-1, b>1, using sumalt */ GEN veczeta(GEN a, GEN b, long N, long prec) { pari_sp av = avma; long n, j, k; GEN L, c, d, z = zerovec(N); if (typ(a) == t_INT && typ(b) == t_INT) return gerepilecopy(av, veczetas(itos(a), itos(b), N, prec)); n = ceil(2 + prec2nbits_mul(prec, M_LN2/1.7627)); c = d = int2n(2*n-1); for (k = n; k; k--) { GEN u, t; L = logr_abs(utor(k, prec)); /* log(k) */ t = gdiv(d, gexp(gmul(b, L), prec)); /* d / k^b */ if (!odd(k)) t = gneg(t); gel(z,1) = gadd(gel(z,1), t); u = gexp(gmul(a, L), prec); for (j = 1; j < N; j++) { t = gdiv(t,u); if (gexpo(t) < 0) break; gel(z,j+1) = gadd(gel(z,j+1), t); } c = muluui(k,2*k-1,c); c = diviuuexact(c, 2*(n-k+1),n+k-1); d = addii(d,c); if (gc_needed(av,3)) { if(DEBUGMEM>1) pari_warn(warnmem,"veczeta, k = %ld", k); gerepileall(av, 3, &c,&d,&z); } } L = mplog2(prec); for (j = 0; j < N; j++) { GEN u = gsubgs(gadd(b, gmulgu(a,j)), 1); GEN w = gexp(gmul(u, L), prec); /* 2^u */ gel(z,j+1) = gdiv(gmul(gel(z,j+1), w), gmul(d,gsubgs(w,1))); } return gerepilecopy(av, z); } GEN constzeta(long n, long prec) { GEN o = zetazone, z; long l = o? lg(o): 0; pari_sp av; if (l > n) { long p = realprec(gel(o,1)); if (p >= prec) return o; } n = maxss(n, l + 15); av = avma; z = veczetas(1, 2, n-1, prec); zetazone = gclone(vec_prepend(z, mpeuler(prec))); set_avma(av); guncloneNULL(o); return zetazone; } /* zeta(s) using sumalt, case h=0,N=1. Assume s > 1 */ static GEN zetaBorwein(long s, long prec) { pari_sp av = avma; const long n = ceil(2 + prec2nbits_mul(prec, M_LN2/1.7627)); long k; GEN c, d, z = gen_0; c = d = int2n(2*n-1); for (k = n; k; k--) { GEN t = divii(d, powuu(k,s)); z = odd(k)? addii(z,t): subii(z,t); c = muluui(k,2*k-1,c); c = diviuuexact(c, 2*(n-k+1),n+k-1); d = addii(d,c); if (gc_needed(av,3)) { if(DEBUGMEM>1) pari_warn(warnmem,"zetaBorwein, k = %ld", k); gerepileall(av, 3, &c,&d,&z); } } return rdivii(shifti(z, s-1), subii(shifti(d,s-1), d), prec); } /* assume k != 1 */ GEN szeta(long k, long prec) { pari_sp av = avma; GEN z; if (!k) { z = real2n(-1, prec); setsigne(z,-1); return z; } if (k < 0) { if (!odd(k)) return gen_0; /* the one value such that k < 0 and 1 - k < 0, due to overflow */ if ((ulong)k == (HIGHBIT | 1)) pari_err_OVERFLOW("zeta [large negative argument]"); k = 1-k; z = bernreal(k, prec); togglesign(z); return gerepileuptoleaf(av, divru(z, k)); } /* k > 1 */ if (k > prec2nbits(prec)+1) return real_1(prec); if (zetazone && realprec(gel(zetazone,1)) >= prec && lg(zetazone) > k) return rtor(gel(zetazone, k), prec); if (!odd(k)) { GEN B; if (!bernzone) constbern(0); if (k < lg(bernzone)) B = gel(bernzone, k>>1); else { if (bernbitprec(k) > prec2nbits(prec)) return gerepileupto(av, invr(inv_szeta_euler(k, prec))); B = bernfrac(k); } /* B = B_k */ z = gmul(powru(Pi2n(1, prec + EXTRAPREC64), k), B); z = divrr(z, mpfactr(k,prec)); setsigne(z, 1); shiftr_inplace(z, -1); } else { double p = prec2nbits_mul(prec,0.393); /* bit / log_2(3+sqrt(8)) */ p = log2(p * log(p)); z = (p * k > prec2nbits(prec))? invr(inv_szeta_euler(k, prec)) : zetaBorwein(k, prec); } return gerepileuptoleaf(av, z); } /* Ensure |1-s| >= 1/32 and (|s| <= 1/32 or real(s) >= 1/2) */ static int zeta_funeq(GEN *ps) { GEN s = *ps, u; if (typ(s) == t_REAL) { u = subsr(1, s); if (expo(u) >= -5 && ((signe(s) > 0 && expo(s) >= -1) || expo(s) <= -5)) return 0; } else { GEN sig = gel(s,1); if (fabs(rtodbl(gel(s,2))) > 2500) return 0; /* lfunlarge */ u = gsubsg(1, s); if (gexpo(u) >= -5 && ((signe(sig) > 0 && expo(sig) >= -1) || gexpo(s) <= -5)) return 0; } *ps = u; return 1; } /* 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) */ static GEN czeta(GEN s0, long prec) { GEN ms, s, u, y, res, tes, sig, tau, invn2, ns, Ns, funeq_factor = NULL; long i, nn, lim, lim2; pari_sp av0 = avma, av, av2; pari_timer T; if (DEBUGLEVEL>2) timer_start(&T); s = trans_fix_arg(&prec,&s0,&sig,&tau,&av,&res); if (typ(s0) == t_INT) return gerepileupto(av0, gzeta(s0, prec)); if (zeta_funeq(&s)) /* s -> 1-s */ { /* Gamma(s) (2Pi)^-s 2 cos(Pi s/2) [new s] */ GEN t = gmul(ggamma(s,prec), pow2Pis(gsubgs(s0,1), prec)); sig = real_i(s); funeq_factor = gmul2n(gmul(t, gsin(gmul(Pi2n(-1,prec),s0), prec)), 1); } if (gcmpgs(sig, prec2nbits(prec) + 1) > 0) { /* zeta(s) = 1 */ if (!funeq_factor) { set_avma(av0); return real_1(prec); } return gerepileupto(av0, funeq_factor); } if (!optim_zeta(s, prec, &lim, &nn)) { long bit = prec2nbits(prec); y = lfun(lfuninit(gen_1, cgetg(1,t_VEC), 0, bit), s, bit); if (funeq_factor) y = gmul(y, funeq_factor); set_avma(av); return affc_fixlg(y,res); } if (DEBUGLEVEL>2) err_printf("lim, nn: [%ld, %ld]\n", lim, nn); ms = gneg(s); if (umuluu_le(nn, prec, 10000000)) { incrprec(prec); /* one extra word of precision */ Ns = vecpowug(nn, ms, prec); ns = gel(Ns,nn); setlg(Ns, nn); y = gadd(gmul2n(ns, -1), RgV_sum(Ns)); } else { Ns = dirpowerssum(nn, ms, 0, prec); incrprec(prec); /* one extra word of precision */ ns = gpow(utor(nn, prec), ms, prec); y = gsub(Ns, gmul2n(ns, -1)); } if (DEBUGLEVEL>2) timer_printf(&T,"sum from 1 to N"); constbern(lim); if (DEBUGLEVEL>2) timer_start(&T); invn2 = divri(real_1(prec), sqru(nn)); lim2 = lim<<1; tes = bernfrac(lim2); { GEN s1, s2, s3, s4, s5; s2 = gmul(s, gsubgs(s,1)); s3 = gmul2n(invn2,3); av2 = avma; s1 = gsubgs(gmul2n(s,1), 1); 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(bernfrac(i), gdivgunextu(gmul(s5,tes), i+1)); if (gc_needed(av2,3)) { if(DEBUGMEM>1) pari_warn(warnmem,"czeta i = %ld", i); 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(ns, gsubgs(s,1)))); if (funeq_factor) y = gmul(y, funeq_factor); set_avma(av); return affc_fixlg(y,res); } /* v a t_VEC/t_COL */ int RgV_is_arithprog(GEN v, GEN *a, GEN *b) { pari_sp av = avma, av2; long i, n = lg(v)-1; if (n == 0) { *a = *b = gen_0; return 1; } *a = gel(v,1); if (n == 1) { * b = gen_0; return 1; } *b = gsub(gel(v,2), *a); av2 = avma; for (i = 2; i < n; i++) if (!gequal(*b, gsub(gel(v,i+1), gel(v,i)))) return gc_int(av,0); return gc_int(av2,1); } GEN gzeta(GEN x, long prec) { pari_sp av = avma; GEN y; if (gequal1(x)) pari_err_DOMAIN("zeta", "argument", "=", gen_1, x); switch(typ(x)) { case t_INT: if (is_bigint(x)) { if (signe(x) > 0) return real_1(prec); if (mod2(x) == 0) return real_0(prec); pari_err_OVERFLOW("zeta [large negative argument]"); } return szeta(itos(x),prec); case t_REAL: case t_COMPLEX: return czeta(x,prec); case t_PADIC: return Qp_zeta(x); case t_VEC: case t_COL: { GEN a, b; long n = lg(x) - 1; if (n > 1 && RgV_is_arithprog(x, &a, &b)) { if (!is_real_t(typ(a)) || !is_real_t(typ(b)) || gcmpgs(a, 1) <= 0) { set_avma(av); break; } a = veczeta(b, a, n, prec); settyp(a, typ(x)); return a; } } default: if (!(y = toser_i(x))) break; if (gequal1(y)) pari_err_DOMAIN("zeta", "argument", "=", gen_1, y); return gerepileupto(av, lfun(gen_1,y,prec2nbits(prec))); } return trans_eval("zeta",gzeta,x,prec); } /***********************************************************************/ /** **/ /** FONCTIONS POLYLOGARITHME **/ /** **/ /***********************************************************************/ /* smallish k such that bernbitprec(K) > bit + Kdz, K = 2k+4 */ static long get_k(double dz, long bit) { long a, b; for (b = 128;; b <<= 1) if (bernbitprec(b) > bit + b*dz) break; if (b == 128) return 128; a = b >> 1; while (b - a > 64) { long c = (a+b) >> 1; if (bernbitprec(c) > bit + c*dz) b = c; else a = c; } return b >> 1; } /* m >= 2. Validity domain |log x| < 2*Pi, contains log |x| < 5.44, * Li_m(x = e^z) = sum_{n >= 0} zeta(m-n) z^n / n! * with zeta(1) := H_{m-1} - log(-z) */ static GEN cxpolylog(long m, GEN x, long prec) { long li, n, k, ksmall, real; GEN vz, z, Z, h, q, s, S; pari_sp av; double dz; pari_timer T; 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)); vz = constzeta(m, prec); z = glog(x,prec); /* n = 0 */ q = gen_1; s = gel(vz, m); for (n=1; n < m-1; n++) { q = gdivgu(gmul(q,z),n); s = gadd(s, gmul(gel(vz,m-n), real? real_i(q): q)); } /* n = m-1 */ q = gdivgu(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 = gdivgu(gmul(q,z),m); s = gadd(s, gdivgs(real? real_i(q): q, -2)); /* zeta(0) = -1/2 */ /* n = m+1 */ q = gdivgu(gmul(q,z),m+1); /* = z^(m+1) / (m+1)! */ s = gadd(s, gdivgs(real? real_i(q): q, -12)); /* zeta(-1) = -1/12 */ li = -(prec2nbits(prec)+1); if (DEBUGLEVEL) timer_start(&T); dz = dbllog2(z) - log2PI; /* ~ log2(|z|/2Pi) */ /* sum_{k >= 1} zeta(-1-2k) * z^(2k+m+1) / (2k+m+1)! * = 2 z^(m-1) sum_{k >= 1} zeta(2k+2) * Z^(k+1) / (2k+2)..(2k+1+m)), where * Z = -(z/2Pi)^2. Stop at 2k = (li - (m-1)*Lz - m) / dz, Lz = log2 |z| */ /* We cut the sum in two: small values of k first */ Z = gsqr(z); av = avma; ksmall = get_k(dz, prec2nbits(prec)); constbern(ksmall); for(k = 1; k < ksmall; k++) { GEN t = q = gdivgunextu(gmul(q,Z), 2*k+m); /* z^(2k+m+1)/(2k+m+1)! */ if (real) t = real_i(t); t = gmul(t, gdivgu(bernfrac(2*k+2), 2*k+2)); /* - t * zeta(1-(2k+2)) */ s = gsub(s, t); if (gexpo(t) < li) return s; /* large values ? */ if ((k & 0x1ff) == 0) gerepileall(av, 2, &s, &q); } if (DEBUGLEVEL>2) timer_printf(&T, "polylog: small k <= %ld", k); Z = gneg(gsqr(gdiv(z, Pi2n(1,prec)))); q = gmul(gpowgs(z, m-1), gpowgs(Z, k+1)); /* Z^(k+1) * z^(m-1) */ S = gen_0; av = avma; for(;; k++) { GEN t = q; long b; if (real) t = real_i(t); b = prec + gexpo(t) / BITS_IN_LONG; /* decrease accuracy */ if (b == 2) break; /* t * zeta(2k+2) / (2k+2)..(2k+1+m) */ t = gdiv(t, mulri(inv_szeta_euler(2*k+2, b), mulu_interval(2*k+2, 2*k+1+m))); S = gadd(S, t); if (gexpo(t) < li) break; q = gmul(q, Z); if ((k & 0x1ff) == 0) gerepileall(av, 2, &S, &q); } if (DEBUGLEVEL>2) timer_printf(&T, "polylog: large k <= %ld", k); return gadd(s, gmul2n(S,1)); } static GEN Li1(GEN x, long prec) { return gneg(glog(gsubsg(1, x), prec)); } static GEN polylog(long m, GEN x, long prec) { long l, e, i, G, sx; pari_sp av, av1; GEN X, Xn, z, p1, p2, y, res; if (m < 0) pari_err_DOMAIN("polylog", "index", "<", gen_0, stoi(m)); if (!m) return mkfrac(gen_m1,gen_2); if (gequal0(x)) return gcopy(x); if (m==1) { av = avma; return gerepileupto(av, Li1(x, prec)); } l = precision(x); if (!l) l = prec; else prec = l; res = cgetc(l); av = avma; x = gtofp(x, l+EXTRAPREC64); e = gexpo(gnorm(x)); if (!e || e == -1) { y = cxpolylog(m,x,prec); set_avma(av); return affc_fixlg(y, res); } X = (e > 0)? ginv(x): x; G = -prec2nbits(l); av1 = avma; 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 (gc_needed(av1,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"polylog"); gerepileall(av1,2, &y, &Xn); } } if (e < 0) { set_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), vz = constzeta(m, l); p1 = mkfrac(gen_m1,gen_2); for (i = m-2; i >= 0; i -= 2) p1 = gadd(gel(vz, m-i), gmul(p1, gdivgunextu(logx2, i+1))); 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); set_avma(av); return affc_fixlg(y, res); } static GEN RIpolylog(long m, GEN x, long real, long prec) { GEN y = polylog(m, x, prec); return real? real_i(y): imag_i(y); } GEN dilog(GEN x, long prec) { return gpolylog(2, x, prec); } /* x a floating point number, t_REAL or t_COMPLEX of t_REAL */ static GEN logabs(GEN x) { GEN y; if (typ(x) == t_COMPLEX) { y = logr_abs( cxnorm(x) ); shiftr_inplace(y, -1); } else y = logr_abs(x); return y; } static GEN polylogD(long m, GEN x, long flag, long prec) { long fl = 0, k, l, 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); if (signe(p1) > 0) { x = ginv(x); fl = !m2; } else setabssign(p1); /* |x| <= 1, p1 = - log|x| >= 0 */ p2 = gen_1; y = RIpolylog(m, x, m2, l); for (k = 1; k < m; k++) { GEN t = RIpolylog(m-k, x, m2, l); p2 = gdivgu(gmul(p2,p1), k); /* (-log|x|)^k / k! */ y = gadd(y, gmul(p2, t)); } if (m2) { p1 = flag? gdivgs(p1, -2*m): gdivgs(logabs(gsubsg(1,x)), m); y = gadd(y, gmul(p2, p1)); } if (fl) y = gneg(y); return gerepileupto(av, y); } static GEN polylogP(long m, GEN x, long prec) { long fl = 0, k, l, m2; pari_sp av; GEN p1,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); if (signe(p1) > 0) { x = ginv(x); fl = !m2; setsigne(p1, -1); } /* |x| <= 1 */ y = RIpolylog(m, x, m2, l); if (m==1) { shiftr_inplace(p1, -1); /* log |x| / 2 */ y = gadd(y, p1); } else { /* m >= 2, \sum_{0 <= k <= m} 2^k B_k/k! (log |x|)^k Li_{m-k}(x), with Li_0(x) := -1/2 */ GEN u, t = RIpolylog(m-1, x, m2, l); u = gneg_i(p1); /* u = 2 B1 log |x| */ y = gadd(y, gmul(u, t)); if (m > 2) { GEN p2; shiftr_inplace(p1, 1); /* 2log|x| <= 0 */ constbern(m>>1); p1 = sqrr(p1); p2 = shiftr(p1,-1); for (k = 2; k < m; k += 2) { if (k > 2) p2 = gdivgunextu(gmul(p2,p1),k-1); /* 2^k/k! log^k |x|*/ t = RIpolylog(m-k, x, m2, l); u = gmul(p2, bernfrac(k)); y = gadd(y, gmul(u, t)); } } } if (fl) y = gneg(y); return gerepileupto(av, y); } static GEN gpolylog_i(void *E, GEN x, long prec) { pari_sp av = avma; long i, n, v, m = (long)E; GEN a, y; if (m <= 0) { a = gmul(x, poleval(eulerianpol(-m, 0), x)); return gerepileupto(av, gdiv(a, gpowgs(gsubsg(1, x), 1-m))); } switch(typ(x)) { case t_REAL: case t_COMPLEX: return polylog(m,x,prec); case t_INTMOD: case t_PADIC: pari_err_IMPL( "padic polylogarithm"); default: av = avma; if (!(y = toser_i(x))) break; if (!m) { set_avma(av); return mkfrac(gen_m1,gen_2); } if (m==1) return gerepileupto(av, Li1(y, prec)); if (gequal0(y)) return gerepilecopy(av, y); v = valser(y); if (v < 0) pari_err_DOMAIN("polylog","valuation", "<", gen_0, x); if (v > 0) { n = (lg(y)-3 + v) / v; a = zeroser(varn(y), lg(y)-2); for (i=n; i>=1; i--) a = gmul(y, gadd(a, powis(utoipos(i),-m))); } else { /* v == 0 */ long vy = varn(y); GEN a0 = polcoef_i(y, 0, -1), t = gdiv(derivser(y), y); a = Li1(y, prec); for (i=2; i<=m; i++) a = gadd(gpolylog(i, a0, prec), integ(gmul(t, a), vy)); } return gerepileupto(av, a); } return trans_evalgen("polylog", E, gpolylog_i, x, prec); } GEN gpolylog(long m, GEN x, long prec) { return gpolylog_i((void*)m, x, prec); } GEN polylog0(long m, GEN x, long flag, long prec) { switch(flag) { case 0: return gpolylog(m,x,prec); case 1: return polylogD(m,x,0,prec); case 2: return polylogD(m,x,1,prec); case 3: return polylogP(m,x,prec); default: pari_err_FLAG("polylog"); } return NULL; /* LCOV_EXCL_LINE */ } GEN upper_to_cx(GEN x, long *prec) { long tx = typ(x), l; if (tx == t_QUAD) { x = quadtofp(x, *prec); tx = typ(x); } switch(tx) { case t_COMPLEX: if (gsigne(gel(x,2)) > 0) break; /*fall through*/ case t_REAL: case t_INT: case t_FRAC: pari_err_DOMAIN("modular function", "Im(argument)", "<=", gen_0, x); default: pari_err_TYPE("modular function", x); } l = precision(x); if (l) *prec = l; return x; } /* sqrt(3)/2 */ static GEN sqrt32(long prec) { GEN z = sqrtr_abs(utor(3,prec)); setexpo(z, -1); return z; } /* exp(i x), x = k pi/12 */ static GEN e12(ulong k, long prec) { int s, sPi, sPiov2; GEN z, t; k %= 24; if (!k) return gen_1; if (k == 12) return gen_m1; if (k >12) { s = 1; k = 24 - k; } else s = 0; /* x -> 2pi - x */ if (k > 6) { sPi = 1; k = 12 - k; } else sPi = 0; /* x -> pi - x */ if (k > 3) { sPiov2 = 1; k = 6 - k; } else sPiov2 = 0; /* x -> pi/2 - x */ z = cgetg(3, t_COMPLEX); switch(k) { case 0: gel(z,1) = icopy(gen_1); gel(z,2) = gen_0; break; case 1: t = gmul2n(addrs(sqrt32(prec), 1), -1); gel(z,1) = sqrtr(t); gel(z,2) = gmul2n(invr(gel(z,1)), -2); break; case 2: gel(z,1) = sqrt32(prec); gel(z,2) = real2n(-1, prec); break; case 3: gel(z,1) = sqrtr_abs(real2n(-1,prec)); gel(z,2) = rcopy(gel(z,1)); break; } if (sPiov2) swap(gel(z,1), gel(z,2)); if (sPi) togglesign(gel(z,1)); if (s) togglesign(gel(z,2)); return z; } /* z a t_FRAC */ static GEN expIPifrac(GEN z, long prec) { GEN n = gel(z,1), d = gel(z,2); ulong r, q = uabsdivui_rem(12, d, &r); if (!r) return e12(q * umodiu(n, 24), prec); /* 12 | d */ n = centermodii(n, shifti(d,1), d); return expIr(divri(mulri(mppi(prec), n), d)); } /* exp(i Pi z), z a t_INT or t_FRAC */ static GEN expIPiQ(GEN z, long prec) { if (typ(z) == t_INT) return mpodd(z)? gen_m1: gen_1; return expIPifrac(z, prec); } /* convert power of 2 t_REAL to rational */ static GEN real2nQ(GEN x) { long e = expo(x); GEN z; if (e < 0) z = mkfrac(signe(x) < 0? gen_m1: gen_1, int2n(-e)); else { z = int2n(e); if (signe(x) < 0) togglesign_safe(&z); } return z; } /* x a real number */ GEN expIPiR(GEN x, long prec) { if (typ(x) == t_REAL && absrnz_equal2n(x)) x = real2nQ(x); switch(typ(x)) { case t_INT: return mpodd(x)? gen_m1: gen_1; case t_FRAC: return expIPifrac(x, prec); } return expIr(mulrr(mppi(prec), x)); } /* z a t_COMPLEX */ GEN expIPiC(GEN z, long prec) { GEN pi, r, x, y; if (typ(z) != t_COMPLEX) return expIPiR(z, prec); x = gel(z,1); y = gel(z,2); if (gequal0(y)) return expIPiR(x, prec); pi = mppi(prec); r = gmul(pi, y); togglesign(r); r = mpexp(r); /* exp(-pi y) */ if (typ(x) == t_REAL && absrnz_equal2n(x)) x = real2nQ(x); switch(typ(x)) { case t_INT: if (mpodd(x)) togglesign(r); return r; case t_FRAC: return gmul(r, expIPifrac(x, prec)); } return gmul(r, expIr(mulrr(pi, x))); } /* exp(I x y), more efficient for x in R, y pure imaginary */ GEN expIxy(GEN x, GEN y, long prec) { return gexp(gmul(x, mulcxI(y)), prec); } static GEN qq(GEN x, long prec) { long tx = typ(x); GEN y; if (is_scalar_t(tx)) { if (tx == t_PADIC) return x; x = upper_to_cx(x, &prec); return cxtoreal(expIPiC(gmul2n(x,1), prec)); /* e(x) */ } if (! ( y = toser_i(x)) ) pari_err_TYPE("modular function", x); return y; } /* return (y * X^d) + x. Assume d > 0, x != 0, valser(x) = 0 */ static GEN ser_addmulXn(GEN y, GEN x, long d) { long i, lx, ly, l = valser(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 s.t. q(0) != 0, v > 0, Q = x^v*q; return \prod_i (1-Q^i) */ static GEN RgXn_eta(GEN q, long v, long lim) { pari_sp av = avma; GEN qn, ps, y; ulong vps, vqn, n; if (!degpol(q) && isint1(gel(q,2))) return eta_ZXn(v, lim+v); 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 = lim + v - vt + 1; k2 = k1 - vqn; /* = lim + v - vps + 1 */ if (k1 <= 0) break; t = RgX_mul(q, RgX_sqr(qn)); t = RgXn_red_shallow(t, k1); t = RgX_mul(ps,t); t = RgXn_red_shallow(t, k1); t = RgX_neg(t); /* t = (-1)^(n+1) q^(n(3n+1)/2 + 2n+1) */ t = gerepileupto(av2, t); y = RgX_addmulXn_shallow(t, y, vt); if (k2 <= 0) break; qn = RgX_mul(qn,q); ps = RgX_mul(t,qn); ps = RgXn_red_shallow(ps, k2); y = RgX_addmulXn_shallow(ps, y, vps); if (gc_needed(av,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"eta, n = %ld", n); gerepileall(av, 3, &y, &qn, &ps); } } return y; } static GEN inteta(GEN q) { long tx = typ(q); GEN ps, qn, y; y = gen_1; qn = gen_1; ps = gen_1; if (tx==t_PADIC) { if (valp(q) <= 0) pari_err_DOMAIN("eta", "v_p(q)", "<=",gen_0,q); for(;;) { GEN t = gneg_i(gmul(ps,gmul(q,gsqr(qn)))); y = gadd(y,t); qn = gmul(qn,q); ps = gmul(t,qn); t = y; y = gadd(y,ps); if (gequal(t,y)) return y; } } if (tx == t_SER) { ulong vps, vqn; long l = lg(q), v, n; pari_sp av; v = valser(q); /* handle valuation separately to avoid overflow */ if (v <= 0) pari_err_DOMAIN("eta", "v_p(q)", "<=",gen_0,q); y = ser2pol_i(q, l); /* t_SER inefficient when input has low degree */ n = degpol(y); if (n <= (l>>2)) { GEN z = RgXn_eta(y, v, l-2); setvarn(z, varn(y)); return RgX_to_ser(z, l+v); } q = leafcopy(q); av = avma; setvalser(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); vqn += v; vps = vt + vqn; k = l+v - vps; if (k <= 2) return y; qn = gmul(qn,q); ps = gmul(t,qn); y = ser_addmulXn(ps, y, vps); setlg(q, k); setlg(qn, k); setlg(ps, k); if (gc_needed(av,3)) { if(DEBUGMEM>1) pari_warn(warnmem,"eta"); gerepileall(av, 3, &y, &qn, &ps); } } } { long l = -prec2nbits(precision(q)); pari_sp av = avma; for(;;) { GEN t = gneg_i(gmul(ps,gmul(q,gsqr(qn)))); /* qn = q^n * ps = (-1)^n q^(n(3n+1)/2) * t = (-1)^(n+1) q^(n(3n+1)/2 + 2n+1) */ y = gadd(y,t); qn = gmul(qn,q); ps = gmul(t,qn); y = gadd(y,ps); if (gexpo(ps)-gexpo(y) < l) return y; if (gc_needed(av,3)) { if(DEBUGMEM>1) pari_warn(warnmem,"eta"); gerepileall(av, 3, &y, &qn, &ps); } } } } GEN eta(GEN x, long prec) { pari_sp av = avma; GEN z = inteta( qq(x,prec) ); if (typ(z) == t_SER) return gerepilecopy(av, z); return gerepileupto(av, z); } /* s(h,k) = sum(n = 1, k-1, (n/k)*(frac(h*n/k) - 1/2)) * Knuth's algorithm. h integer, k integer > 0, (h,k) = 1 */ GEN sumdedekind_coprime(GEN h, GEN k) { pari_sp av = avma; GEN s2, s1, p, pp; long s; if (lgefint(k) == 3 && uel(k,2) <= (2*(ulong)LONG_MAX) / 3) { ulong kk = k[2], hh = umodiu(h, kk); long s1, s2; GEN v; if (signe(k) < 0) { k = negi(k); hh = Fl_neg(hh, kk); } v = u_sumdedekind_coprime(hh, kk); s1 = v[1]; s2 = v[2]; return gerepileupto(av, gdiv(addis(mulis(k,s1), s2), muluu(12, kk))); } s = 1; s1 = gen_0; p = gen_1; pp = gen_0; s2 = h = modii(h, k); while (signe(h)) { GEN r, nexth, a = dvmdii(k, h, &nexth); if (is_pm1(h)) s2 = s == 1? addii(s2, p): subii(s2, p); s1 = s == 1? addii(s1, a): subii(s1, a); s = -s; k = h; h = nexth; r = addii(mulii(a,p), pp); pp = p; p = r; } /* at this point p = original k */ if (s == -1) s1 = subiu(s1, 3); return gerepileupto(av, gdiv(addii(mulii(p,s1), s2), muliu(p,12))); } /* as above, for ulong arguments. * k integer > 0, 0 <= h < k, (h,k) = 1. Returns [s1,s2] such that * s(h,k) = (s2 + k s1) / (12k). Requires max(h + k/2, k) < LONG_MAX * to avoid overflow, in particular k <= LONG_MAX * 2/3 is fine */ GEN u_sumdedekind_coprime(long h, long k) { long s = 1, s1 = 0, s2 = h, p = 1, pp = 0; while (h) { long r, nexth = k % h, a = k / h; /* a >= 1, a >= 2 if h = 1 */ if (h == 1) s2 += p * s; /* occurs exactly once, last step */ s1 += a * s; s = -s; k = h; h = nexth; r = a*p + pp; pp = p; p = r; /* p >= pp >= 0 */ } /* in the above computation, p increases from 1 to original k, * -k/2 <= s2 <= h + k/2, and |s1| <= k */ if (s < 0) s1 -= 3; /* |s1| <= k+3 ? */ /* But in fact, |s2 + p s1| <= k^2 + 1/2 - 3k; if (s < 0), we have * |s2| <= k/2 and it follows that |s1| < k here as well */ /* p = k; s(h,k) = (s2 + p s1)/12p. */ return mkvecsmall2(s1, s2); } GEN sumdedekind(GEN h, GEN k) { pari_sp av = avma; GEN d; if (typ(h) != t_INT) pari_err_TYPE("sumdedekind",h); if (typ(k) != t_INT) pari_err_TYPE("sumdedekind",k); d = gcdii(h,k); if (!is_pm1(d)) { h = diviiexact(h, d); k = diviiexact(k, d); } return gerepileupto(av, sumdedekind_coprime(h,k)); } /* eta(x); assume Im x >> 0 (e.g. x in SL2's standard fundamental domain) */ static GEN eta_reduced(GEN x, long prec) { GEN z = expIPiC(gdivgu(x, 12), prec); /* e(x/24) */ if (24 * gexpo(z) >= -prec2nbits(prec)) z = gmul(z, inteta( gpowgs(z,24) )); return z; } /* x = U.z (flag = 1), or x = U^(-1).z (flag = 0) * Return [s,t] such that eta(z) = eta(x) * sqrt(s) * exp(I Pi t) */ static GEN eta_correction(GEN x, GEN U, long flag) { GEN a,b,c,d, s,t; long sc; a = gcoeff(U,1,1); b = gcoeff(U,1,2); c = gcoeff(U,2,1); d = gcoeff(U,2,2); /* replace U by U^(-1) */ if (flag) { swap(a,d); togglesign_safe(&b); togglesign_safe(&c); } sc = signe(c); if (!sc) { if (signe(d) < 0) togglesign_safe(&b); s = gen_1; t = uutoQ(umodiu(b, 24), 12); } else { if (sc < 0) { togglesign_safe(&a); togglesign_safe(&b); togglesign_safe(&c); togglesign_safe(&d); } /* now c > 0 */ s = mulcxmI(gadd(gmul(c,x), d)); t = gadd(gdiv(addii(a,d),muliu(c,12)), sumdedekind_coprime(negi(d),c)); /* correction : exp(I Pi (((a+d)/12c) + s(-d,c)) ) sqrt(-i(cx+d)) */ } return mkvec2(s, t); } /* returns the true value of eta(x) for Im(x) > 0, using reduction to * standard fundamental domain */ GEN trueeta(GEN x, long prec) { pari_sp av = avma; GEN U, st, s, t; if (!is_scalar_t(typ(x))) pari_err_TYPE("trueeta",x); x = upper_to_cx(x, &prec); x = cxredsl2(x, &U); st = eta_correction(x, U, 1); x = eta_reduced(x, prec); s = gel(st, 1); t = gel(st, 2); x = gmul(x, expIPiQ(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); } /* eta(q) = 1 + \sum_{n>0} (-1)^n * (q^(n(3n-1)/2) + q^(n(3n+1)/2)) */ static GEN ser_eta(long prec) { GEN e = cgetg(prec+2, t_SER), ed = e+2; long n, j; e[1] = evalsigne(1)|_evalvalser(0)|evalvarn(0); gel(ed,0) = gen_1; for (n = 1; n < prec; n++) gel(ed,n) = gen_0; for (n = 1, j = 0; n < prec; n++) { GEN s; j += 3*n-2; /* = n*(3*n-1) / 2 */; if (j >= prec) break; s = odd(n)? gen_m1: gen_1; gel(ed, j) = s; if (j+n >= prec) break; gel(ed, j+n) = s; } return e; } static GEN coeffEu(GEN fa) { pari_sp av = avma; return gerepileuptoint(av, mului(65520, usumdivk_fact(fa,11))); } /* E12 = 1 + q*E/691 */ static GEN ser_E(long prec) { GEN e = cgetg(prec+2, t_SER), ed = e+2; GEN F = vecfactoru_i(2, prec); /* F[n] = factoru(n+1) */ long n; e[1] = evalsigne(1)|_evalvalser(0)|evalvarn(0); gel(ed,0) = utoipos(65520); for (n = 1; n < prec; n++) gel(ed,n) = coeffEu(gel(F,n)); return e; } /* j = E12/Delta + 432000/691, E12 = 1 + q*E/691 */ static GEN ser_j2(long prec, long v) { pari_sp av = avma; GEN iD = gpowgs(ginv(ser_eta(prec)), 24); /* q/Delta */ GEN J = gmul(ser_E(prec), iD); setvalser(iD,-1); /* now 1/Delta */ J = gadd(gdivgu(J, 691), iD); J = gerepileupto(av, J); if (prec > 1) gel(J,3) = utoipos(744); setvarn(J,v); return J; } /* j(q) = \sum_{n >= -1} c(n)q^n, * \sum_{n = -1}^{N-1} c(n) (-10n \sigma_3(N-n) + 21 \sigma_5(N-n)) * = c(N) (N+1)/24 */ static GEN ser_j(long prec, long v) { GEN j, J, S3, S5, F; long i, n; if (prec > 64) return ser_j2(prec, v); S3 = cgetg(prec+1, t_VEC); S5 = cgetg(prec+1,t_VEC); F = vecfactoru_i(1, prec); for (n = 1; n <= prec; n++) { GEN fa = gel(F,n); gel(S3,n) = mului(10, usumdivk_fact(fa,3)); gel(S5,n) = mului(21, usumdivk_fact(fa,5)); } J = cgetg(prec+2, t_SER), J[1] = evalvarn(v)|evalsigne(1)|evalvalser(-1); j = J+3; gel(j,-1) = gen_1; gel(j,0) = utoipos(744); gel(j,1) = utoipos(196884); for (n = 2; n < prec; n++) { pari_sp av = avma; GEN c, s3 = gel(S3,n+1), s5 = gel(S5,n+1); c = addii(s3, s5); for (i = 0; i < n; i++) { s3 = gel(S3,n-i); s5 = gel(S5,n-i); c = addii(c, mulii(gel(j,i), subii(s5, mului(i,s3)))); } gel(j,n) = gerepileuptoint(av, diviuexact(muliu(c,24), n+1)); } return J; } GEN jell(GEN x, long prec) { long tx = typ(x); pari_sp av = avma; GEN q, h, U; if (!is_scalar_t(tx)) { long v; if (gequalX(x)) return ser_j(precdl, varn(x)); q = toser_i(x); if (!q) pari_err_TYPE("ellj",x); v = fetch_var_higher(); h = ser_j(lg(q)-2, v); h = gsubst(h, v, q); delete_var(); return gerepileupto(av, h); } if (tx == t_PADIC) { GEN p2, p1 = gdiv(inteta(gsqr(x)), inteta(x)); p1 = gmul2n(gsqr(p1),1); p1 = gmul(x,gpowgs(p1,12)); p2 = gaddsg(768,gadd(gsqr(p1),gdivsg(4096,p1))); p1 = gmulsg(48,p1); return gerepileupto(av, gadd(p2,p1)); } /* Let h = Delta(2x) / Delta(x), then j(x) = (1 + 256h)^3 / h */ x = upper_to_cx(x, &prec); x = cxredsl2(x, &U); /* forget about Ua : j has weight 0 */ { /* cf eta_reduced, raised to power 24 * Compute * t = (inteta(q(2x)) / inteta(q(x))) ^ 24; * then * h = t * (q(2x) / q(x) = t * q(x); * but inteta(q) costly and useless if expo(q) << 1 => inteta(q) = 1. * log_2 ( exp(-2Pi Im tau) ) < -prec2nbits(prec) * <=> Im tau > prec2nbits(prec) * log(2) / 2Pi */ long C = (long)prec2nbits_mul(prec, M_LN2/(2*M_PI)); q = expIPiC(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, GEN D) { return mkqfb(a, w, diviiexact(C, a), D); } static GEN form_to_quad(GEN f, GEN sqrtD) { long a = itos(gel(f,1)), a2 = a << 1; GEN b = gel(f,2); return mkcomplex(gdivgs(b, -a2), gdivgs(sqrtD, a2)); } static GEN eta_form(GEN f, GEN sqrtD, GEN *s_t, long prec) { GEN U, t = form_to_quad(redimagsl2(f, &U), sqrtD); *s_t = eta_correction(t, U, 0); return eta_reduced(t, prec); } /* eta(t/p)eta(t/q) / (eta(t)eta(t/pq)), t = (-w + sqrt(D)) / 2a */ GEN double_eta_quotient(GEN a, GEN w, GEN D, long p, long q, GEN pq, GEN sqrtD) { GEN C = shifti(subii(sqri(w), D), -2); GEN d, t, z, zp, zq, zpq, s_t, s_tp, s_tpq, s, sp, spq; long prec = realprec(sqrtD); z = eta_form(to_form(a, w, C, D), sqrtD, &s_t, prec); s = gel(s_t, 1); zp = eta_form(to_form(mului(p, a), w, C, D), sqrtD, &s_tp, prec); sp = gel(s_tp, 1); zpq = eta_form(to_form(mulii(pq, a), w, C, D), 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, D), 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, expIPiQ(t, prec)); } typedef struct { GEN u; long v, t; } cxanalyze_t; /* Check whether a t_COMPLEX, t_REAL or t_INT z != 0 can be written as * z = u * 2^(v/2) * exp(I Pi/4 t), u > 0, v = 0,1 and -3 <= t <= 4. * Allow z t_INT/t_REAL to simplify handling of eta_correction() output */ static int cxanalyze(cxanalyze_t *T, GEN z) { GEN a, b; long ta, tb; T->u = z; T->v = 0; if (is_intreal_t(typ(z))) { T->u = mpabs_shallow(z); T->t = signe(z) < 0? 4: 0; return 1; } a = gel(z,1); ta = typ(a); b = gel(z,2); tb = typ(b); T->t = 0; if (ta == t_INT && !signe(a)) { T->u = R_abs_shallow(b); T->t = gsigne(b) < 0? -2: 2; return 1; } if (tb == t_INT && !signe(b)) { T->u = R_abs_shallow(a); T->t = gsigne(a) < 0? 4: 0; return 1; } if (ta != tb || ta == t_REAL) return 0; /* a,b both non zero, both t_INT or t_FRAC */ if (ta == t_INT) { if (!absequalii(a, b)) return 0; T->u = absi_shallow(a); T->v = 1; if (signe(a) == signe(b)) { T->t = signe(a) < 0? -3: 1; } else { T->t = signe(a) < 0? 3: -1; } } else { if (!absequalii(gel(a,2), gel(b,2)) || !absequalii(gel(a,1),gel(b,1))) return 0; T->u = absfrac_shallow(a); T->v = 1; a = gel(a,1); b = gel(b,1); if (signe(a) == signe(b)) { T->t = signe(a) < 0? -3: 1; } else { T->t = signe(a) < 0? 3: -1; } } return 1; } /* z * sqrt(st_b) / sqrt(st_a) exp(I Pi (t + t0)). Assume that * sqrt2 = gsqrt(gen_2, prec) or NULL */ static GEN apply_eta_correction(GEN z, GEN st_a, GEN st_b, GEN t0, GEN sqrt2, long prec) { GEN t, s_a = gel(st_a, 1), s_b = gel(st_b, 1); cxanalyze_t Ta, Tb; int ca, cb; t = gsub(gel(st_b,2), gel(st_a,2)); if (t0 != gen_0) t = gadd(t, t0); ca = cxanalyze(&Ta, s_a); cb = cxanalyze(&Tb, s_b); if (ca || cb) { /* compute sqrt(s_b) / sqrt(s_a) in a more efficient way: * sb = ub sqrt(2)^vb exp(i Pi/4 tb) */ GEN u = gdiv(Tb.u,Ta.u); switch(Tb.v - Ta.v) { case -1: u = gmul2n(u,-1); /* fall through: write 1/sqrt2 = sqrt2/2 */ case 1: u = gmul(u, sqrt2? sqrt2: sqrtr_abs(real2n(1, prec))); } if (!isint1(u)) z = gmul(z, gsqrt(u, prec)); t = gadd(t, gmul2n(stoi(Tb.t - Ta.t), -3)); } else { z = gmul(z, gsqrt(s_b, prec)); z = gdiv(z, gsqrt(s_a, prec)); } return gmul(z, expIPiQ(t, prec)); } /* sqrt(2) eta(2x) / eta(x) */ GEN weberf2(GEN x, long prec) { pari_sp av = avma; GEN z, sqrt2, a,b, Ua,Ub, st_a,st_b; x = upper_to_cx(x, &prec); a = cxredsl2(x, &Ua); b = cxredsl2(gmul2n(x,1), &Ub); if (gequal(a,b)) /* not infrequent */ z = gen_1; else z = gdiv(eta_reduced(b,prec), eta_reduced(a,prec)); st_a = eta_correction(a, Ua, 1); st_b = eta_correction(b, Ub, 1); sqrt2 = sqrtr_abs(real2n(1, prec)); z = apply_eta_correction(z, st_a, st_b, gen_0, sqrt2, prec); return gerepileupto(av, gmul(z, sqrt2)); } /* eta(x/2) / eta(x) */ GEN weberf1(GEN x, long prec) { pari_sp av = avma; GEN z, a,b, Ua,Ub, st_a,st_b; x = upper_to_cx(x, &prec); a = cxredsl2(x, &Ua); b = cxredsl2(gmul2n(x,-1), &Ub); if (gequal(a,b)) /* not infrequent */ z = gen_1; else z = gdiv(eta_reduced(b,prec), eta_reduced(a,prec)); st_a = eta_correction(a, Ua, 1); st_b = eta_correction(b, Ub, 1); z = apply_eta_correction(z, st_a, st_b, gen_0, NULL, prec); return gerepileupto(av, z); } /* exp(-I*Pi/24) * eta((x+1)/2) / eta(x) */ GEN weberf(GEN x, long prec) { pari_sp av = avma; GEN z, t0, a,b, Ua,Ub, st_a,st_b; x = upper_to_cx(x, &prec); a = cxredsl2(x, &Ua); b = cxredsl2(gmul2n(gaddgs(x,1),-1), &Ub); if (gequal(a,b)) /* not infrequent */ z = gen_1; else z = gdiv(eta_reduced(b,prec), eta_reduced(a,prec)); st_a = eta_correction(a, Ua, 1); st_b = eta_correction(b, Ub, 1); t0 = mkfrac(gen_m1, utoipos(24)); z = apply_eta_correction(z, st_a, st_b, t0, NULL, prec); if (typ(z) == t_COMPLEX && isexactzero(real_i(x))) z = gerepilecopy(av, gel(z,1)); else z = gerepileupto(av, z); return z; } GEN weber0(GEN x, long flag,long prec) { switch(flag) { case 0: return weberf(x,prec); case 1: return weberf1(x,prec); case 2: return weberf2(x,prec); default: pari_err_FLAG("weber"); } return NULL; /* LCOV_EXCL_LINE */ } /* check |q| < 1 */ static GEN check_unit_disc(const char *fun, GEN q, long prec) { GEN Q = gtofp(q, prec), Qlow; Qlow = (prec > LOWDEFAULTPREC)? gtofp(Q,LOWDEFAULTPREC): Q; if (gcmp(gnorm(Qlow), gen_1) >= 0) pari_err_DOMAIN(fun, "abs(q)", ">=", gen_1, q); return Q; } GEN theta(GEN q, GEN z, long prec) { long l, n; pari_sp av = avma, av2; GEN s, c, snz, cnz, s2z, c2z, ps, qn, y, zy, ps2, k, zold; l = precision(q); n = precision(z); if (n && n < l) l = n; if (l) prec = l; z = gtofp(z, prec); q = check_unit_disc("theta", q, prec); zold = NULL; /* gcc -Wall */ zy = imag_i(z); if (gequal0(zy)) k = gen_0; else { GEN lq = glog(q,prec); k = roundr(divrr(zy, real_i(lq))); if (signe(k)) { zold = z; z = gadd(z, mulcxmI(gmul(lq,k))); } } qn = gen_1; ps2 = gsqr(q); ps = gneg_i(ps2); gsincos(z, &s, &c, prec); s2z = gmul2n(gmul(s,c),1); /* sin 2z */ c2z = gsubgs(gmul2n(gsqr(c),1), 1); /* cos 2z */ snz = s; cnz = c; y = s; av2 = avma; for (n = 3;; n += 2) { long e; s = gadd(gmul(snz, c2z), gmul(cnz,s2z)); qn = gmul(qn,ps); y = gadd(y, gmul(qn, s)); e = gexpo(s); if (e < 0) e = 0; if (gexpo(qn) + e < -prec2nbits(prec)) break; ps = gmul(ps,ps2); c = gsub(gmul(cnz, c2z), gmul(snz,s2z)); snz = s; /* sin nz */ cnz = c; /* cos nz */ if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"theta (n = %ld)", n); gerepileall(av2, 5, &snz, &cnz, &ps, &qn, &y); } } if (signe(k)) { y = gmul(y, gmul(powgi(q,sqri(k)), gexp(gmul(mulcxI(zold),shifti(k,1)), prec))); if (mod2(k)) y = gneg_i(y); } return gerepileupto(av, gmul(y, gmul2n(gsqrt(gsqrt(q,prec),prec),1))); } GEN thetanullk(GEN q, long k, long prec) { long l, n; pari_sp av = avma; GEN p1, ps, qn, y, ps2; if (k < 0) pari_err_DOMAIN("thetanullk", "k", "<", gen_0, stoi(k)); l = precision(q); if (l) prec = l; q = check_unit_disc("thetanullk", q, prec); if (!odd(k)) { set_avma(av); return gen_0; } qn = gen_1; ps2 = gsqr(q); ps = gneg_i(ps2); y = gen_1; for (n = 3;; n += 2) { GEN t; qn = gmul(qn,ps); ps = gmul(ps,ps2); t = gmul(qn, powuu(n, k)); y = gadd(y, t); if (gexpo(t) < -prec2nbits(prec)) break; } p1 = gmul2n(gsqrt(gsqrt(q,prec),prec),1); if (k&2) y = gneg_i(y); return gerepileupto(av, gmul(p1, y)); } /* q2 = q^2 */ static GEN vecthetanullk_loop(GEN q2, long k, long prec) { GEN ps, qn = gen_1, y = const_vec(k, gen_1); pari_sp av = avma; const long bit = prec2nbits(prec); long i, n; if (gexpo(q2) < -2*bit) return y; ps = gneg_i(q2); for (n = 3;; n += 2) { GEN t = NULL/*-Wall*/, P = utoipos(n), N2 = sqru(n); qn = gmul(qn,ps); ps = gmul(ps,q2); for (i = 1; i <= k; i++) { t = gmul(qn, P); gel(y,i) = gadd(gel(y,i), t); P = mulii(P, N2); } if (gexpo(t) < -bit) return y; if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"vecthetanullk_loop, n = %ld",n); gerepileall(av, 3, &qn, &ps, &y); } } } /* [d^i theta/dz^i(q, 0), i = 1, 3, .., 2*k - 1] */ GEN vecthetanullk(GEN q, long k, long prec) { long i, l = precision(q); pari_sp av = avma; GEN p1, y; if (l) prec = l; q = check_unit_disc("vecthetanullk", q, prec); y = vecthetanullk_loop(gsqr(q), k, prec); p1 = gmul2n(gsqrt(gsqrt(q,prec),prec),1); for (i = 2; i <= k; i += 2) gel(y,i) = gneg_i(gel(y,i)); return gerepileupto(av, gmul(p1, y)); } /* [d^i theta/dz^i(q, 0), i = 1, 3, .., 2*k - 1], q = exp(2iPi tau) */ GEN vecthetanullk_tau(GEN tau, long k, long prec) { long i, l = precision(tau); pari_sp av = avma; GEN q4, y; if (l) prec = l; if (typ(tau) != t_COMPLEX || gsigne(gel(tau,2)) <= 0) pari_err_DOMAIN("vecthetanullk_tau", "imag(tau)", "<=", gen_0, tau); q4 = expIPiC(gmul2n(tau,-1), prec); /* q^(1/4) */ y = vecthetanullk_loop(gpowgs(q4,8), k, prec); for (i = 2; i <= k; i += 2) gel(y,i) = gneg_i(gel(y,i)); return gerepileupto(av, gmul(gmul2n(q4,1), y)); } /* Return E_k(tau). Slow if tau is not in standard fundamental domain */ GEN cxEk(GEN tau, long k, long prec) { pari_sp av; GEN q, y, qn; long n, b, l = precision(tau); if (l) prec = l; b = prec2nbits(prec); /* sum n^(k-1) x^n <= x(1 + (k!-1)x) / (1-x)^k (cf Eulerian polynomials) * S = \sum_{n > 0} n^(k-1) |q^n/(1-q^n)| <= x(1+(k!-1)x) / (1-x)^(k+1), * where x = |q| = exp(-2Pi Im(tau)) < 1. Neglegt 2/zeta(1-k) * S if * (2Pi)^k/(k-1)! x < 2^(-b-1) and k! x < 1. Use log2((2Pi)^k/(k-1)!) < 10 */ if (gcmpgs(imag_i(tau), (M_LN2 / (2*M_PI)) * (b+1+10)) > 0) return real_1(prec); if (k == 2) { /* -theta^(3)(tau/2) / theta^(1)(tau/2). Assume that Im tau > 0 */ y = vecthetanullk_loop(qq(tau,prec), 2, prec); return gdiv(gel(y,2), gel(y,1)); } q = cxtoreal(expIPiC(gneg(gmul2n(tau,1)), prec)); av = avma; y = gen_0; qn = q; for(n = 1;; n++) { /* compute y := sum_{n>0} n^(k-1) / (q^n-1) */ GEN t = gdiv(powuu(n,k-1), gsubgs(qn,1)); if (gequal0(t) || gexpo(t) <= - prec2nbits(prec) - 5) break; y = gadd(y, t); qn = gmul(q,qn); if (gc_needed(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)))); } pari-2.17.2/src/basemath/buch3.c0000644000175000017500000024261414760123736014731 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*******************************************************************/ /* */ /* RAY CLASS FIELDS */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_bnr static GEN bnr_get_El(GEN bnr) { return gel(bnr,3); } static GEN bnr_get_U(GEN bnr) { return gel(bnr,4); } static GEN bnr_get_Ui(GEN bnr) { return gmael(bnr,4,3); } /* faster than Buchray */ GEN bnfnarrow(GEN bnf) { GEN nf, cyc, gen, Cyc, Gen, A, GD, v, w, H, invpi, L, R, u, U0, Uoo, archp, sarch; long r1, j, l, t, RU; pari_sp av; bnf = checkbnf(bnf); nf = bnf_get_nf(bnf); r1 = nf_get_r1(nf); if (!r1) return gcopy( bnf_get_clgp(bnf) ); /* simplified version of nfsign_units; r1 > 0 so bnf.tu = -1 */ av = avma; archp = identity_perm(r1); A = bnf_get_logfu(bnf); RU = lg(A)+1; invpi = invr( mppi(nf_get_prec(nf)) ); v = cgetg(RU,t_MAT); gel(v, 1) = const_vecsmall(r1, 1); /* nfsign(-1) */ for (j=2; j 1 */ GEN basecl = cgetg(l,t_VEC), G; G = mkvec2(NULL, trivial_fact()); for (j = 1; j < l; j++) { GEN z = NULL; for (i = 1; i < h; i++) { GEN g, e = gcoeff(U,i,j); if (!signe(e)) continue; g = gel(gen,i); if (typ(g) != t_MAT) { if (z) gel(z,2) = famat_mulpow_shallow(gel(z,2), g, e); else z = mkvec2(NULL, to_famat_shallow(g, e)); continue; } gel(G,1) = g; g = idealpowred(nf,G,e); z = z? idealmulred(nf,z,g): g; } gel(z,2) = famat_reduce(gel(z,2)); gel(basecl,j) = z; } return basecl; } static int too_big(GEN nf, GEN bet) { GEN x = nfnorm(nf,bet); switch (typ(x)) { case t_INT: return abscmpii(x, gen_1); case t_FRAC: return abscmpii(gel(x,1), gel(x,2)); } pari_err_BUG("wrong type in too_big"); return 0; /* LCOV_EXCL_LINE */ } /* true nf; GTM 193: Algo 4.3.4. Reduce x mod divisor */ static GEN idealmoddivisor_aux(GEN nf, GEN x, GEN f, GEN sarch) { pari_sp av = avma; GEN a, A; if ( is_pm1(gcoeff(f,1,1)) ) /* f = 1 */ { A = idealred(nf, mkvec2(x, gen_1)); A = nfinv(nf, gel(A,2)); } else {/* given coprime integral ideals x and f (f HNF), compute "small" * G in x, such that G = 1 mod (f). GTM 193: Algo 4.3.3 */ GEN G = idealaddtoone_raw(nf, x, f); GEN D = idealaddtoone_i(nf, idealdiv(nf,G,x), f); A = nfdiv(nf,D,G); } if (too_big(nf,A) > 0) return gc_const(av, x); a = set_sign_mod_divisor(nf, NULL, A, sarch); if (a != A && too_big(nf,A) > 0) return gc_const(av, x); return idealmul(nf, a, x); } GEN idealmoddivisor(GEN bnr, GEN x) { GEN nf = bnr_get_nf(bnr), bid = bnr_get_bid(bnr); return idealmoddivisor_aux(nf, x, bid_get_ideal(bid), bid_get_sarch(bid)); } /* v_pr(L0 * cx) */ static long fast_val(GEN L0, GEN cx, GEN pr) { pari_sp av = avma; long v = typ(L0) == t_INT? 0: ZC_nfval(L0,pr); if (cx) { long w = Q_pval(cx, pr_get_p(pr)); if (w) v += w * pr_get_e(pr); } return gc_long(av,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; } /* uniformizer pi for pr, coprime to F/p */ static GEN get_pi(GEN F, GEN pr, GEN *v) { if (!*v) *v = pr_uniformizer(pr, F); return *v; } /* true nf */ static GEN bnr_grp(GEN nf, GEN U, GEN gen, GEN cyc, GEN bid) { GEN h = ZV_prod(cyc); GEN f, fZ, basecl, fa, pr, t, EX, sarch, F, P, vecpi, vecpinvpi; long i,j,l,lp; if (lg(U) == 1) return mkvec3(h, cyc, cgetg(1, t_VEC)); basecl = compute_fact(nf, U, gen); /* generators in factored form */ EX = gel(bid_get_cyc(bid),1); /* exponent of (O/f)^* */ f = bid_get_ideal(bid); fZ = gcoeff(f,1,1); fa = bid_get_fact(bid); sarch = bid_get_sarch(bid); P = gel(fa,1); F = prV_lcm_capZ(P); lp = lg(P); vecpinvpi = cgetg(lp, t_VEC); vecpi = cgetg(lp, t_VEC); for (i=1; i 0) { pinvpi = get_pinvpi(nf, fZ, p, pi, &gel(vecpinvpi,j)); t = nfpow_u(nf,pinvpi, (ulong)v); LL = nfmul(nf, LL, t); LL = gdiv(LL, powiu(p, v)); } else { t = nfpow_u(nf,pi,(ulong)(-v)); LL = nfmul(nf, LL, t); } } LL = make_integral(nf,LL,f,P); 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 = typ(G) == t_COL? ZC_hnfrem(G, ZM_Z_mul(f, dmulI)) : modii(G, mulii(fZ,dmulI)); G = RgC_Rg_div(G, dmulI); } G = set_sign_mod_divisor(nf,A,G,sarch); I = idealmul(nf,I,G); /* more or less useless, but cheap at this point */ I = idealmoddivisor_aux(nf,I,f,sarch); gel(basecl,i) = gerepilecopy(av, I); } return mkvec3(h, cyc, basecl); } /********************************************************************/ /** **/ /** INIT RAY CLASS GROUP **/ /** **/ /********************************************************************/ GEN bnr_subgroup_check(GEN bnr, GEN H, GEN *pdeg) { GEN no = bnr_get_no(bnr); if (H && isintzero(H)) H = NULL; if (H) { GEN h, cyc = bnr_get_cyc(bnr); switch(typ(H)) { case t_INT: H = scalarmat_shallow(H, lg(cyc)-1); /* fall through */ case t_MAT: RgM_check_ZM(H, "bnr_subgroup_check"); H = ZM_hnfmodid(H, cyc); break; case t_VEC: if (char_check(cyc, H)) { H = charker(cyc, H); break; } default: pari_err_TYPE("bnr_subgroup_check", H); } h = ZM_det_triangular(H); if (equalii(h, no)) H = NULL; else no = h; } if (pdeg) *pdeg = no; return H; } void bnr_subgroup_sanitize(GEN *pbnr, GEN *pH) { GEN D, cnd, mod, cyc, bnr = *pbnr, H = *pH; if (nftyp(bnr)==typ_BNF) bnr = Buchray(bnr, gen_1, nf_INIT); else checkbnr(bnr); cyc = bnr_get_cyc(bnr); if (!H) mod = cyc_get_expo(cyc); else switch(typ(H)) { case t_INT: mod = H; break; case t_VEC: if (!char_check(cyc, H)) pari_err_TYPE("bnr_subgroup_sanitize [character]", H); H = charker(cyc, H); /* character -> subgroup */ case t_MAT: H = hnfmodid(H, cyc); /* make sure H is a left divisor of Mat(cyc) */ D = ZM_snf(H); /* structure of Cl_f / H */ mod = lg(D) == 1? gen_1: gel(D,1); break; default: pari_err_TYPE("bnr_subroup_sanitize [subgroup]", H); mod = NULL; } cnd = bnrconductormod(bnr, H, mod); *pbnr = gel(cnd,2); *pH = gel(cnd,3); } void bnr_char_sanitize(GEN *pbnr, GEN *pchi) { GEN cnd, cyc, bnr = *pbnr, chi = *pchi; if (nftyp(bnr)==typ_BNF) bnr = Buchray(bnr, gen_1, nf_INIT); else checkbnr(bnr); cyc = bnr_get_cyc(bnr); if (typ(chi) != t_VEC || !char_check(cyc, chi)) pari_err_TYPE("bnr_char_sanitize [character]", chi); cnd = bnrconductormod(bnr, chi, charorder(cyc, chi)); *pbnr = gel(cnd,2); *pchi = gel(cnd,3); } /* c a rational content (NULL or t_INT or t_FRAC), return u*c as a ZM/d */ static GEN ZM_content_mul(GEN u, GEN c, GEN *pd) { *pd = gen_1; if (c) { if (typ(c) == t_FRAC) { *pd = gel(c,2); c = gel(c,1); } if (!is_pm1(c)) u = ZM_Z_mul(u, c); } return u; } /* bnr natural generators: bnf gens made coprime to modulus + bid gens. * Beware: if bnr includes MOD, we may have #El < #bnf.ge*/ static GEN get_Gen(GEN bnf, GEN bid, GEN El) { GEN nf = bnf_get_nf(bnf), gen = bnf_get_gen(bnf), Gen; long i, l = lg(El); if (lg(gen) > l) gen = vec_shorten(gen, l-1); Gen = shallowconcat(gen, bid_get_gen(bid)); for (i = 1; i < l; i++) { GEN e = gel(El,i); if (!isint1(e)) gel(Gen,i) = idealmul(nf, gel(El,i), gel(Gen,i)); } return Gen; } static GEN Buchraymod_i(GEN bnf, GEN module, long flag, GEN MOD) { GEN nf, cyc0, cyc, gen, Cyc, clg, h, logU, U, Ui, vu; GEN bid, cycbid, H, El; long RU, Ri, j, ngen; const long add_gen = flag & nf_GEN; const long do_init = flag & nf_INIT; if (MOD && typ(MOD) != t_INT) pari_err_TYPE("bnrinit [incorrect cycmod]", MOD); bnf = checkbnf(bnf); nf = bnf_get_nf(bnf); RU = lg(nf_get_roots(nf))-1; /* #K.futu */ El = NULL; /* gcc -Wall */ cyc = cyc0 = bnf_get_cyc(bnf); gen = bnf_get_gen(bnf); ngen = lg(cyc)-1; bid = checkbid_i(module); if (!bid) bid = Idealstarmod(nf,module,nf_GEN|nf_INIT, MOD); cycbid = bid_get_cyc(bid); if (MOD) cyc = ZV_snfclean(ZV_snf_gcd(cyc, MOD)); Ri = lg(cycbid)-1; if (Ri || add_gen || do_init) { GEN fx = bid_get_fact(bid); long n = Ri? ngen: lg(cyc)-1; El = cgetg(n+1, t_VEC); for (j = 1; j <= n; j++) { GEN c = idealcoprimefact(nf, gel(gen,j), fx); gel(El,j) = nf_to_scalar_or_basis(nf,c); } } if (!Ri) { GEN no, Gen = add_gen? get_Gen(bnf, bid, El): NULL; if (MOD) { ngen = lg(cyc)-1; no = ZV_prod(cyc); } else no = bnf_get_no(bnf); clg = add_gen? mkvec3(no, cyc, Gen): mkvec2(no, cyc); if (!do_init) return clg; U = matid(ngen); U = mkvec3(U, cgetg(1,t_MAT), U); vu = mkvec3(cgetg(1,t_MAT), matid(RU), gen_1); return mkvecn(6, bnf, bid, El, U, clg, vu); } logU = ideallog_units0(bnf, bid, MOD); if (do_init) { /* (log(Units)|D) * u = (0 | H) */ GEN c1,c2, u,u1,u2, Hi, D = shallowconcat(logU, diagonal_shallow(cycbid)); H = ZM_hnfall_i(D, &u, 1); u1 = matslice(u, 1,RU, 1,RU); u2 = matslice(u, 1,RU, RU+1,lg(u)-1); /* log(Units) (u1|u2) = (0|H) (mod D), H HNF */ u1 = ZM_lll(u1, 0.99, LLL_INPLACE); Hi = Q_primitive_part(RgM_inv_upper(H), &c1); u2 = ZM_mul(ZM_reducemodmatrix(u2,u1), Hi); u2 = Q_primitive_part(u2, &c2); u2 = ZM_content_mul(u2, mul_content(c1,c2), &c2); vu = mkvec3(u2,u1,c2); /* u2/c2 = H^(-1) (mod Im u1) */ } else { H = ZM_hnfmodid(logU, cycbid); vu = NULL; /* -Wall */ } if (!ngen) h = H; else { GEN L = cgetg(ngen+1, t_MAT), cycgen = bnf_build_cycgen(bnf); for (j=1; j<=ngen; j++) { GEN c = gel(cycgen,j), e = gel(El,j); if (!equali1(e)) c = famat_mulpow_shallow(c, e, gel(cyc0,j)); gel(L,j) = ideallogmod(nf, c, bid, MOD); /* = log(Gen[j]^cyc[j]) */ } /* [cyc0, 0; -L, H] = relation matrix for generators Gen of Cl_f */ h = shallowconcat(vconcat(diagonal_shallow(cyc0), ZM_neg(L)), vconcat(zeromat(ngen, Ri), H)); h = MOD? ZM_hnfmodid(h, MOD): ZM_hnf(h); } Cyc = ZM_snf_group(h, &U, &Ui); /* Gen = clg.gen*U, clg.gen = Gen*Ui */ clg = add_gen? bnr_grp(nf, Ui, get_Gen(bnf, bid, El), Cyc, bid) : mkvec2(ZV_prod(Cyc), Cyc); if (!do_init) return clg; U = mkvec3(vecslice(U, 1,ngen), vecslice(U,ngen+1,lg(U)-1), Ui); return mkvecn(6, bnf, bid, El, U, clg, vu); } GEN Buchray(GEN bnf, GEN f, long flag) { return Buchraymod(bnf, f, flag, NULL); } GEN Buchraymod(GEN bnf, GEN f, long flag, GEN MOD) { pari_sp av = avma; return gerepilecopy(av, Buchraymod_i(bnf, f, flag, MOD)); } GEN bnrinitmod(GEN bnf, GEN f, long flag, GEN MOD) { switch(flag) { case 0: flag = nf_INIT; break; case 1: flag = nf_INIT | nf_GEN; break; default: pari_err_FLAG("bnrinit"); } return Buchraymod(bnf, f, flag, MOD); } GEN bnrinit0(GEN bnf, GEN ideal, long flag) { return bnrinitmod(bnf, ideal, flag, NULL); } GEN bnrclassno(GEN bnf,GEN ideal) { GEN h, D, bid, cycbid; pari_sp av = avma; bnf = checkbnf(bnf); h = bnf_get_no(bnf); bid = checkbid_i(ideal); if (!bid) bid = Idealstar(bnf_get_nf(bnf), ideal, nf_INIT); cycbid = bid_get_cyc(bid); if (lg(cycbid) == 1) { set_avma(av); return icopy(h); } D = ideallog_units(bnf, bid); /* (Z_K/f)^* / units ~ Z^n / D */ D = ZM_hnfmodid(D,cycbid); return gerepileuptoint(av, mulii(h, ZM_det_triangular(D))); } GEN bnrclassno0(GEN A, GEN B, GEN C) { pari_sp av = avma; GEN h, H = NULL; /* adapted from ABC_to_bnr, avoid costly bnrinit if possible */ if (typ(A) == t_VEC) switch(lg(A)) { case 7: /* bnr */ checkbnr(A); H = B; break; case 11: /* bnf */ if (!B) pari_err_TYPE("bnrclassno [bnf+missing conductor]",A); if (!C) return bnrclassno(A, B); A = Buchray(A, B, nf_INIT); H = C; break; default: checkbnf(A);/*error*/ } else checkbnf(A);/*error*/ H = bnr_subgroup_check(A, H, &h); if (!H) { set_avma(av); return icopy(h); } return gerepileuptoint(av, h); } /* ZMV_ZCV_mul for two matrices U = [Ux,Uy], it may have more components * (ignored) and vectors x,y */ static GEN ZM2_ZC2_mul(GEN U, GEN x, GEN y) { GEN Ux = gel(U,1), Uy = gel(U,2); if (lg(Ux) == 1) return ZM_ZC_mul(Uy,y); if (lg(Uy) == 1) return ZM_ZC_mul(Ux,x); return ZC_add(ZM_ZC_mul(Ux,x), ZM_ZC_mul(Uy,y)); } GEN bnrisprincipalmod(GEN bnr, GEN x, GEN MOD, long flag) { pari_sp av = avma; GEN E, G, clgp, bnf, nf, bid, ex, cycray, alpha, El; int trivialbid; checkbnr(bnr); El = bnr_get_El(bnr); cycray = bnr_get_cyc(bnr); if (MOD && flag) pari_err_FLAG("bnrisprincipalmod [MOD!=NULL and flag!=0]"); if (lg(cycray) == 1 && !(flag & nf_GEN)) return cgetg(1,t_COL); if (MOD) cycray = ZV_snf_gcd(cycray, MOD); bnf = bnr_get_bnf(bnr); nf = bnf_get_nf(bnf); bid = bnr_get_bid(bnr); trivialbid = lg(bid_get_cyc(bid)) == 1; if (trivialbid) { ex = isprincipal(bnf, x); setlg(ex, lg(cycray)); /* can happen with MOD */ } else { GEN v = bnfisprincipal0(bnf, x, nf_FORCE|nf_GENMAT); GEN e = gel(v,1), b = gel(v,2); long i, j = lg(e); for (i = 1; i < j; i++) /* modify b as if bnf.gen were El*bnf.gen */ if (typ(gel(El,i)) != t_INT && signe(gel(e,i))) /* <==> != 1 */ b = famat_mulpow_shallow(b, gel(El,i), negi(gel(e,i))); if (!MOD && !(flag & nf_GEN)) MOD = gel(cycray,1); ex = ZM2_ZC2_mul(bnr_get_U(bnr), e, ideallogmod(nf, b, bid, MOD)); } ex = ZV_ZV_mod(ex, cycray); if (!(flag & (nf_GEN|nf_GENMAT))) return gerepileupto(av, ex); /* compute generator */ E = ZC_neg(ex); clgp = bnr_get_clgp(bnr); if (lg(clgp) == 4) G = abgrp_get_gen(clgp); else { G = get_Gen(bnf, bid, El); E = ZM_ZC_mul(bnr_get_Ui(bnr), E); } alpha = isprincipalfact(bnf, x, G, E, nf_GENMAT|nf_GEN_IF_PRINCIPAL|nf_FORCE); if (alpha == gen_0) pari_err_BUG("isprincipalray"); if (!trivialbid) { 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, alpha, bid)); if (!is_pm1(du2)) y = ZC_Z_divexact(y,du2); y = ZC_reducemodmatrix(y, u1); if (!ZV_equal0(y)) { GEN U = shallowcopy(bnf_build_units(bnf)); settyp(U, t_COL); alpha = famat_div_shallow(alpha, mkmat2(U,y)); } } alpha = famat_reduce(alpha); if (!(flag & nf_GENMAT)) alpha = nffactorback(nf, alpha, NULL); return gerepilecopy(av, mkvec2(ex,alpha)); } GEN bnrisprincipal(GEN bnr, GEN x, long flag) { return bnrisprincipalmod(bnr, x, NULL, flag); } 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_shallow(D),prec)); return gerepileuptoleaf(av, c); } /* N = [K:Q] > 1, D = disc(K) */ static GEN zimmertbound(GEN D, long N, long R2) { pari_sp av = avma; GEN w; if (N > 20) w = minkowski_bound(D, N, R2, DEFAULTPREC); else { 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(absi_shallow(D),DEFAULTPREC)); } return gerepileuptoint(av, ceil_safe(w)); } /* return \gamma_n^n if known, an upper bound otherwise */ GEN Hermite_bound(long n, long prec) { GEN h,h1; pari_sp av; switch(n) { case 1: return gen_1; case 2: retmkfrac(utoipos(4), utoipos(3)); case 3: return gen_2; case 4: return utoipos(4); case 5: return utoipos(8); case 6: retmkfrac(utoipos(64), utoipos(3)); case 7: return utoipos(64); case 8: return utoipos(256); case 24: return int2n(48); } av = avma; h = powru(divur(2,mppi(prec)), n); h1 = sqrr(ggamma(uutoQ(n+4,2),prec)); return gerepileuptoleaf(av, mulrr(h,h1)); } /* 1 if L (= nf != Q) primitive for sure, 0 if MAYBE imprimitive (may have a * subfield K) */ static long isprimitive(GEN nf) { long p, i, l, ep, N = nf_get_degree(nf); GEN D, fa; p = ucoeff(factoru(N), 1,1); /* smallest prime | N */ if (p == N) return 1; /* prime degree */ /* N = [L:Q] = product of primes >= p, same is true for [L:K] * d_L = t d_K^[L:K] --> check that some q^p divides d_L */ D = nf_get_disc(nf); fa = gel(absZ_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_shallow(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, Hermite_bound(R, DEFAULTPREC))); if (DEBUGLEVEL>1) err_printf("Mahler bound for regulator: %Ps\n",p1); return gmax_shallow(p1, dbltor(0.2)); } static int is_unit(GEN M, long r1, GEN x) { pari_sp av = avma; GEN Nx = ground( embed_norm(RgM_zc_mul(M,x), r1) ); return gc_bool(av, is_pm1(Nx)); } /* True nf. FIXME: should use smallvectors */ static double minimforunits(GEN nf, long BORNE, ulong w) { const long prec = MEDDEFAULTPREC; long n, r1, i, j, k, *x, cnt = 0; pari_sp av = avma; GEN r, M; double p, norme, normin; 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); } n = nf_get_degree(nf); r1 = nf_get_r1(nf); minim_alloc(n+1, &q, &x, &y, &z, &v); M = gprec_w(nf_get_M(nf), prec); r = gaussred_from_QR(nf_get_G(nf), prec); for (j=1; j<=n; j++) { v[j] = gtodouble(gcoeff(r,j,j)); for (i=1; i1) { long l = k-1; z[l] = 0; for (j=k; j<=n; j++) z[l] += q[l][j]*x[j]; p = (double)x[k] + z[k]; y[l] = y[k] + p*p*v[k]; x[l] = (long)floor(sqrt((BOUND-y[l])/v[l])-z[l]); k = l; } for(;;) { p = (double)x[k] + z[k]; if (y[k] + p*p*v[k] <= BOUND) break; k++; x[k]--; } } while (k>1); if (!x[1] && y[1]<=eps) break; if (DEBUGLEVEL>8) err_printf("."); if (++cnt == 5000) return -1.; /* too expensive */ p = (double)x[1] + z[1]; norme = y[1] + p*p*v[1]; if (is_unit(M, r1, x) && norme < normin) { /* exclude roots of unity */ if (norme < 2*n) { GEN t = nfpow_u(nf, zc_to_ZC(x), w); if (typ(t) != t_COL || ZV_isscalar(t)) continue; } normin = norme*(1-eps); if (DEBUGLEVEL>=2) err_printf("*"); } } if (DEBUGLEVEL>=2) err_printf("\n"); set_avma(av); return normin; } #undef NBMAX static int is_zero(GEN x, long bitprec) { return (gexpo(x) < -bitprec); } static int is_complex(GEN x, long bitprec) { return !is_zero(imag_i(x), bitprec); } /* assume M_star t_REAL * FIXME: what does this do ? To be rewritten */ static GEN compute_M0(GEN M_star,long N) { long m1,m2,n1,n2,n3,lr,lr1,lr2,i,j,l,vx,vy,vz,vM; GEN pol,p1,p2,p3,p4,p5,p6,p7,p8,p9,u,v,w,r,r1,r2,M0,M0_pro,S,P,M; GEN f1,f2,f3,g1,g2,g3,pg1,pg2,pg3,pf1,pf2,pf3,X,Y,Z; long bitprec = 24; if (N == 2) return gmul2n(sqrr(gacosh(gmul2n(M_star,-1),0)), -1); vx = fetch_var(); X = pol_x(vx); vy = fetch_var(); Y = pol_x(vy); vz = fetch_var(); Z = pol_x(vz); vM = fetch_var(); M = pol_x(vM); M0 = NULL; m1 = N/3; for (n1=1; n1<=m1; n1++) /* 1 <= n1 <= n2 <= n3 < N */ { m2 = (N-n1)>>1; for (n2=n1; n2<=m2; n2++) { pari_sp av = avma; n3=N-n1-n2; if (n1==n2 && n1==n3) /* n1 = n2 = n3 = m1 = N/3 */ { p1 = divru(M_star, m1); p4 = sqrtr_abs( mulrr(addsr(1,p1),subrs(p1,3)) ); p5 = subrs(p1,1); u = gen_1; v = gmul2n(addrr(p5,p4),-1); w = gmul2n(subrr(p5,p4),-1); M0_pro=gmul2n(mulur(m1,addrr(sqrr(logr_abs(v)),sqrr(logr_abs(w)))), -2); if (DEBUGLEVEL>2) err_printf("[ %ld, %ld, %ld ]: %.28Pg\n",n1,n2,n3,M0_pro); if (!M0 || gcmp(M0_pro,M0) < 0) M0 = M0_pro; } else if (n1==n2 || n2==n3) { /* n3 > N/3 >= n1 */ long k = N - 2*n2; p2 = deg1pol_shallow(stoi(-n2), M_star, vx); /* M* - n2 X */ p3 = gmul(powuu(k,k), gpowgs(gsubgs(RgX_Rg_mul(p2, M_star), k*k), n2)); pol = gsub(p3, RgX_mul(monomial(powuu(n2,n2), n2, vx), gpowgs(p2, N-n2))); r = roots(pol, DEFAULTPREC); lr = lg(r); for (i=1; i2) err_printf("[ %ld, %ld, %ld ]: %.28Pg\n",n1,n2,n3,M0_pro); if (!M0 || gcmp(M0_pro,M0) < 0) M0 = M0_pro; } } else { f1 = gsub(gadd(gmulsg(n1,X),gadd(gmulsg(n2,Y),gmulsg(n3,Z))), M); f2 = gmulsg(n1,gmul(Y,Z)); f2 = gadd(f2,gmulsg(n2,gmul(X,Z))); f2 = gadd(f2,gmulsg(n3,gmul(X,Y))); f2 = gsub(f2,gmul(M,gmul(X,gmul(Y,Z)))); f3 = gsub(gmul(gpowgs(X,n1),gmul(gpowgs(Y,n2),gpowgs(Z,n3))), gen_1); /* f1 = n1 X + n2 Y + n3 Z - M */ /* f2 = n1 YZ + n2 XZ + n3 XY */ /* f3 = X^n1 Y^n2 Z^n3 - 1*/ g1=resultant(f1,f2); g1=primpart(g1); g2=resultant(f1,f3); g2=primpart(g2); g3=resultant(g1,g2); g3=primpart(g3); pf1=gsubst(f1,vM,M_star); pg1=gsubst(g1,vM,M_star); pf2=gsubst(f2,vM,M_star); pg2=gsubst(g2,vM,M_star); pf3=gsubst(f3,vM,M_star); pg3=gsubst(g3,vM,M_star); /* g3 = Res_Y,Z(f1,f2,f3) */ r = roots(pg3,DEFAULTPREC); lr = lg(r); for (i=1; i2) err_printf("[ %ld, %ld, %ld ]: %.28Pg\n",n1,n2,n3,M0_pro); if (!M0 || gcmp(M0_pro,M0) < 0) M0 = M0_pro; } } } } if (!M0) set_avma(av); else M0 = gerepilecopy(av, M0); } } for (i=1;i<=4;i++) (void)delete_var(); return M0? M0: gen_0; } static GEN lowerboundforregulator(GEN bnf, GEN units) { long i, N, R2, RU = lg(units)-1; GEN nf, M0, M, G, minunit; double bound; if (!RU) return gen_1; nf = bnf_get_nf(bnf); N = nf_get_degree(nf); R2 = nf_get_r2(nf); G = nf_get_G(nf); minunit = gnorml2(RgM_RgC_mul(G, gel(units,1))); /* T2(units[1]) */ for (i=2; i<=RU; i++) { GEN t = gnorml2(RgM_RgC_mul(G, gel(units,i))); if (gcmp(t,minunit) < 0) minunit = t; } if (gexpo(minunit) > 30) return NULL; bound = minimforunits(nf, itos(gceil(minunit)), bnf_get_tuN(bnf)); if (bound < 0) return NULL; if (DEBUGLEVEL>1) err_printf("M* = %Ps\n", dbltor(bound)); M0 = compute_M0(dbltor(bound), N); if (DEBUGLEVEL>1) err_printf("M0 = %.28Pg\n",M0); M = gmul2n(divru(gdiv(powrs(M0,RU),Hermite_bound(RU, DEFAULTPREC)),N),R2); if (cmprr(M, dbltor(0.04)) < 0) return NULL; M = sqrtr(M); if (DEBUGLEVEL>1) err_printf("(lower bound for regulator) M = %.28Pg\n",M); return M; } /* upper bound for the index of bnf.fu in the full unit group */ static GEN bound_unit_index(GEN bnf, GEN units) { pari_sp av = avma; GEN x = lowerboundforregulator(bnf, units); if (!x) { set_avma(av); x = regulatorbound(bnf); } return gerepileuptoint(av, ground(gdiv(bnf_get_reg(bnf), x))); } /* Compute a square matrix of rank #beta attached 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. nf = true nf */ static void primecertify(GEN nf, GEN beta, ulong p, GEN bad) { long lb = lg(beta), rmax = lb - 1; GEN M, vQ, L; ulong q; forprime_t T; if (p == 2) L = cgetg(1,t_VECSMALL); else L = mkvecsmall(p); (void)u_forprime_arith_init(&T, 1, ULONG_MAX, 1, p); M = cgetg(lb,t_MAT); setlg(M,1); while ((q = u_forprime_next(&T))) { GEN qq, gg, og; long lQ, i, j; ulong g, m; if (!umodiu(bad,q)) continue; qq = utoipos(q); vQ = idealprimedec_limit_f(nf,qq,1); lQ = lg(vQ); if (lQ == 1) continue; /* cf rootsof1_Fl */ g = pgener_Fl_local(q, L); m = (q-1) / p; gg = utoipos( Fl_powu(g, m, q) ); /* order p in (Z/q)^* */ og = mkmat2(mkcol(utoi(p)), mkcol(gen_1)); /* order of g */ if (DEBUGLEVEL>3) err_printf(" generator of (Zk/Q)^*: %lu\n", g); for (i = 1; i < lQ; i++) { GEN C = cgetg(lb, t_VECSMALL); GEN Q = gel(vQ,i); /* degree 1 */ GEN modpr = zkmodprinit(nf, Q); long r; for (j = 1; j < lb; j++) { GEN t = nf_to_Fp_coprime(nf, gel(beta,j), modpr); t = utoipos( Fl_powu(t[2], m, q) ); C[j] = itou( Fp_log(t, gg, og, qq) ) % p; } r = lg(M); gel(M,r) = C; setlg(M, r+1); if (Flm_rank(M, p) != r) { setlg(M,r); continue; } if (DEBUGLEVEL>2) { if (DEBUGLEVEL>3) { err_printf(" prime ideal Q: %Ps\n",Q); err_printf(" matrix log(b_j mod Q_i): %Ps\n", M); } err_printf(" new rank: %ld\n",r); } if (r == rmax) return; } } pari_err_BUG("primecertify"); } 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 nf, 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); primecertify(nf, beta, p, S->bad); set_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 N; GEN nf, cyc, B, U; ulong bound, p; struct check_pr S; forprime_t T; bnf = checkbnf(bnf); nf = bnf_get_nf(bnf); N = nf_get_degree(nf); if (N==1) return 1; B = zimmertbound(nf_get_disc(nf), N, nf_get_r2(nf)); if (is_bigint(B)) pari_warn(warner,"Zimmert's bound is large (%Ps), certification will take a long time", B); if (!is_pm1(nf_get_index(nf))) { GEN D = nf_get_diff(nf), L; if (DEBUGLEVEL>1) err_printf("**** Testing Different = %Ps\n",D); L = bnfisprincipal0(bnf, D, nf_FORCE); if (DEBUGLEVEL>1) err_printf(" is %Ps\n", L); } if (DEBUGLEVEL) { err_printf("PHASE 1 [CLASS GROUP]: are all primes good ?\n"); err_printf(" Testing primes <= %Ps\n", B); } bnftestprimes(bnf, B); if (flag) return 1; U = bnf_build_units(bnf); cyc = bnf_get_cyc(bnf); S.w = bnf_get_tuN(bnf); S.mu = gel(U,1); S.fu = vecslice(U,2,lg(U)-1); S.cyc = cyc; S.cycgen = bnf_build_cycgen(bnf); init_bad(&S, nf, bnf_get_gen(bnf)); B = bound_unit_index(bnf, S.fu); if (DEBUGLEVEL) { err_printf("PHASE 2 [UNITS/RELATIONS]: are all primes good ?\n"); err_printf(" Testing primes <= %Ps\n", B); } bound = itou_or_0(B); if (!bound) pari_err_OVERFLOW("bnfcertify [too many primes to check]"); if (u_forprime_init(&T, 2, bound)) while ( (p = u_forprime_next(&T)) ) check_prime(p, nf, &S); if (lg(cyc) > 1) { GEN f = Z_factor(cyc_get_expo(cyc)), P = gel(f,1); long i; if (DEBUGLEVEL>1) err_printf(" Primes dividing h(K)\n\n"); for (i = lg(P)-1; i; i--) { p = itou(gel(P,i)); if (p <= bound) break; check_prime(p, nf, &S); } } return gc_long(av,1); } long bnfcertify(GEN bnf) { return bnfcertify0(bnf, 0); } /*******************************************************************/ /* */ /* RAY CLASS FIELDS: CONDUCTORS AND DISCRIMINANTS */ /* */ /*******************************************************************/ /* \chi(gen[i]) = zeta_D^chic[i]) * denormalize: express chi(gen[i]) in terms of zeta_{cyc[i]} */ GEN char_denormalize(GEN cyc, GEN D, GEN chic) { long i, l = lg(chic); GEN chi = cgetg(l, t_VEC); /* \chi(gen[i]) = e(chic[i] / D) = e(chi[i] / cyc[i]) * hence chi[i] = chic[i]cyc[i]/ D mod cyc[i] */ for (i = 1; i < l; ++i) { GEN di = gel(cyc, i), t = diviiexact(mulii(di, gel(chic,i)), D); gel(chi, i) = modii(t, di); } return chi; } static GEN bnrchar_i(GEN bnr, GEN g, GEN v) { long i, h, l = lg(g), t = typ_NULL; GEN CH, D, U, U2, H, cycD, dv, dchi, cyc = NULL; if (checkbnr_i(bnr)) { t = typ_BNR; cyc = bnr_get_cyc(bnr); } else if (checkznstar_i(bnr)) { t = typ_BIDZ; cyc = znstar_get_cyc(bnr); } else if (typ(bnr) == t_VEC && RgV_is_ZV(bnr)) cyc = bnr; else pari_err_TYPE("bnrchar", bnr); switch(typ(g)) { GEN G; case t_VEC: G = cgetg(l, t_MAT); if (t == typ_BNR) { for (i = 1; i < l; i++) gel(G,i) = isprincipalray(bnr, gel(g,i)); cyc = bnr_get_cyc(bnr); } else for (i = 1; i < l; i++) gel(G,i) = Zideallog(bnr, gel(g,i)); g = G; break; case t_MAT: if (RgM_is_ZM(g)) break; default: pari_err_TYPE("bnrchar",g); } H = ZM_hnfall_i(shallowconcat(g,diagonal_shallow(cyc)), v? &U: NULL, 1); dv = NULL; if (v) { GEN w = Q_remove_denom(v, &dv); if (typ(v)!=t_VEC || lg(v)!=l || !RgV_is_ZV(w)) pari_err_TYPE("bnrchar",v); if (!dv) v = NULL; else { U = rowslice(U, 1, l-1); w = FpV_red(ZV_ZM_mul(w, U), dv); for (i = 1; i < l; i++) if (signe(gel(w,i))) pari_err_TYPE("bnrchar [inconsistent values]",v); v = vecslice(w,l,lg(w)-1); } } /* chi defined on subgroup H, chi(H[i]) = e(v[i] / dv) * unless v = NULL: chi|H = 1*/ h = itos( ZM_det_triangular(H) ); /* #(clgp/H) = number of chars */ if (h == 1) /* unique character, H = Id */ { if (v) v = char_denormalize(cyc,dv,v); else v = zerovec(lg(cyc)-1); /* trivial char */ return mkvec(v); } /* chi defined on a subgroup of index h > 1; U H V = D diagonal, * Z^#H / (H) = Z^#H / (D) ~ \oplus (Z/diZ) */ D = ZM_snfall_i(H, &U, NULL, 1); cycD = cyc_normalize(D); gel(cycD,1) = gen_1; /* cycD[i] = d1/di */ dchi = gel(D,1); U2 = ZM_diag_mul(cycD, U); if (v) { GEN Ui = ZM_inv(U, NULL); GEN Z = hnf_solve(H, ZM_mul_diag(Ui, D)); v = ZV_ZM_mul(ZV_ZM_mul(v, Z), U2); dchi = mulii(dchi, dv); U2 = ZM_Z_mul(U2, dv); } CH = cyc2elts(D); for (i = 1; i <= h; i++) { GEN c = zv_ZM_mul(gel(CH,i), U2); if (v) c = ZC_add(c, v); gel(CH,i) = char_denormalize(cyc, dchi, c); } return CH; } GEN bnrchar(GEN bnr, GEN g, GEN v) { pari_sp av = avma; return gerepilecopy(av, bnrchar_i(bnr,g,v)); } /* Let bnr1, bnr2 be such that mod(bnr2) | mod(bnr1), compute surjective map * p: Cl(bnr1) ->> Cl(bnr2). * Write (bnr gens) for the concatenation of the bnf [corrected by El] and bid * generators; and bnr.gen for the SNF generators. Then * bnr.gen = (bnf.gen*bnr.El | bid.gen) bnr.Ui * (bnf.gen*bnr.El | bid.gen) = bnr.gen * bnr.U */ GEN bnrsurjection(GEN bnr1, GEN bnr2) { GEN bnf = bnr_get_bnf(bnr2), nf = bnf_get_nf(bnf); GEN M, U = bnr_get_U(bnr2), bid2 = bnr_get_bid(bnr2); GEN gen1 = bid_get_gen(bnr_get_bid(bnr1)); GEN cyc2 = bnr_get_cyc(bnr2), e2 = cyc_get_expo(cyc2); long i, l = lg(bnf_get_cyc(bnf)), lb = lg(gen1); /* p(bnr1.gen) = p(bnr1 gens) * bnr1.Ui * = (bnr2 gens) * P * bnr1.Ui * = bnr2.gen * (bnr2.U * P * bnr1.Ui) */ /* p(bid1.gen) on bid2.gen */ M = cgetg(lb, t_MAT); for (i = 1; i < lb; i++) gel(M,i) = ideallogmod(nf, gel(gen1,i), bid2, e2); /* [U[1], U[2]] * [Id, 0; N, M] = [U[1] + U[2]*N, U[2]*M] */ M = ZM_mul(gel(U,2), M); if (l > 1) { /* non trivial class group */ /* p(bnf.gen * bnr1.El) in terms of bnf.gen * bnr2.El and bid2.gen */ GEN El2 = bnr_get_El(bnr2), El1 = bnr_get_El(bnr1); long ngen2 = lg(bid_get_gen(bid2))-1; if (!ngen2) M = gel(U,1); else { GEN U1 = gel(U,1), U2 = gel(U,2), T = cgetg(l, t_MAT); /* T = U1 + U2 log(El2/El1) */ for (i = 1; i < l; i++) { /* bnf gen in bnr1 is bnf.gen * El1 = bnf gen in bnr 2 * El1/El2 */ GEN c = gel(U1,i); if (typ(gel(El1,i)) != t_INT) /* else El1[i] = 1 => El2[i] = 1 */ { GEN z = nfdiv(nf,gel(El1,i),gel(El2,i)); c = ZC_add(c, ZM_ZC_mul(U2, ideallogmod(nf, z, bid2, e2))); } gel(T,i) = c; } M = shallowconcat(T, M); } } M = ZM_ZV_mod(ZM_mul(M, bnr_get_Ui(bnr1)), cyc2); return mkvec3(M, bnr_get_cyc(bnr1), cyc2); } /* nchi a normalized character, S a surjective map ; return S(nchi) * still normalized wrt the original cyclic structure (S[2]) */ static GEN abmap_nchar_image(GEN S, GEN nchi) { GEN U, M = gel(S,1), Mc = diagonal_shallow(gel(S,3)); long l = lg(M); (void)ZM_hnfall_i(shallowconcat(M, Mc), &U, 1); /* identity */ U = matslice(U,1,l-1, l,lg(U)-1); return char_simplify(gel(nchi,1), ZV_ZM_mul(gel(nchi,2), U)); } static GEN abmap_char_image(GEN S, GEN chi) { GEN nchi = char_normalize(chi, cyc_normalize(gel(S,2))); GEN DC = abmap_nchar_image(S, nchi); return char_denormalize(gel(S,3), gel(DC,1), gel(DC,2)); } GEN bnrmap(GEN A, GEN B) { pari_sp av = avma; GEN KA, KB, M, c, C; if ((KA = checkbnf_i(A))) { checkbnr(A); checkbnr(B); KB = bnr_get_bnf(B); if (!gidentical(KA, KB)) pari_err_TYPE("bnrmap [different fields]", mkvec2(KA,KB)); return gerepilecopy(av, bnrsurjection(A,B)); } if (lg(A) != 4 || typ(A) != t_VEC) pari_err_TYPE("bnrmap [not a map]", A); M = gel(A,1); c = gel(A,2); C = gel(A,3); if (typ(M) != t_MAT || !RgM_is_ZM(M) || typ(c) != t_VEC || typ(C) != t_VEC || lg(c) != lg(M) || (lg(M) > 1 && lgcols(M) != lg(C))) pari_err_TYPE("bnrmap [not a map]", A); switch(typ(B)) { case t_INT: /* subgroup */ B = scalarmat_shallow(B, lg(C)-1); B = ZM_hnfmodid(B, C); break; case t_MAT: /* subgroup */ if (!RgM_is_ZM(B)) pari_err_TYPE("bnrmap [not a subgroup]", B); B = ZM_hnfmodid(B, c); B = abmap_subgroup_image(A, B); break; case t_VEC: /* character */ if (!char_check(c, B)) pari_err_TYPE("bnrmap [not a character mod mA]", B); B = abmap_char_image(A, B); break; case t_COL: /* discrete log mod mA */ if (lg(B) != lg(c) || !RgV_is_ZV(B)) pari_err_TYPE("bnrmap [not a discrete log]", B); B = ZV_ZV_mod(ZM_ZC_mul(M, B), C); return gerepileupto(av, B); } return gerepilecopy(av, B); } /* Given normalized chi on bnr.clgp of conductor bnrc.mod, * compute primitive character chic on bnrc.clgp equivalent to chi, * still normalized wrt. bnr: * chic(genc[i]) = zeta_C^chic[i]), C = cyc_normalize(bnr.cyc)[1] */ GEN bnrchar_primitive(GEN bnr, GEN nchi, GEN bnrc) { return abmap_nchar_image(bnrsurjection(bnr, bnrc), nchi); } /* s: = Cl_f -> Cl_f2 -> 0, H subgroup of Cl_f (generators given as * HNF on [gen]). Return subgroup s(H) in Cl_f2 */ static GEN imageofgroup(GEN bnr, GEN bnr2, GEN H) { if (!H) return diagonal_shallow(bnr_get_cyc(bnr2)); return abmap_subgroup_image(bnrsurjection(bnr, bnr2), H); } GEN bnrchar_primitive_raw(GEN bnr, GEN bnrc, GEN chi) { return abmap_char_image(bnrsurjection(bnr, bnrc), chi); } /* convert A,B,C to [bnr, H] */ GEN ABC_to_bnr(GEN A, GEN B, GEN C, GEN *H, int gen) { if (typ(A) == t_VEC) switch(lg(A)) { case 7: /* bnr */ *H = B; return A; case 11: /* bnf */ if (!B) pari_err_TYPE("ABC_to_bnr [bnf+missing conductor]",A); *H = C; return Buchray(A,B, gen? nf_INIT | nf_GEN: nf_INIT); } pari_err_TYPE("ABC_to_bnr",A); *H = NULL; return NULL; /* LCOV_EXCL_LINE */ } /* OBSOLETE */ GEN bnrconductor0(GEN A, GEN B, GEN C, long flag) { pari_sp av = avma; GEN H, bnr = ABC_to_bnr(A,B,C,&H, 0); return gerepilecopy(av, 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 ideallog_to_bnr_i(GEN Ubid, GEN cyc, GEN z) { return (lg(Ubid)==1)? zerocol(lg(cyc)-1): ZV_ZV_mod(ZM_ZC_mul(Ubid,z), cyc); } /* return bnrisprincipal(bnr, (x)), assuming z = ideallog(x); allow a * t_MAT for z, understood as a collection of ideallog(x_i) */ static GEN ideallog_to_bnr(GEN bnr, GEN z) { GEN U = gel(bnr_get_U(bnr), 2); /* bid part */ GEN y, cyc = bnr_get_cyc(bnr); long i, l; if (typ(z) == t_COL) return ideallog_to_bnr_i(U, cyc, z); y = cgetg_copy(z, &l); for (i = 1; i < l; i++) gel(y,i) = ideallog_to_bnr_i(U, cyc, gel(z,i)); return y; } static GEN bnr_log_gen_pr(GEN bnr, zlog_S *S, long e, long index) { return ideallog_to_bnr(bnr, log_gen_pr(S, index, bnr_get_nf(bnr), 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); } /* finite part of the conductor of H is S.P^e2*/ static GEN cond0_e(GEN bnr, GEN H, zlog_S *S) { long j, k, l = lg(S->k), iscond0 = S->no2; GEN e = S->k, 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, j, k))) break; iscond0 = 0; } gel(e2,k) = utoi(j); } return iscond0? NULL: e2; } /* infinite part of the conductor of H in archp form */ static GEN condoo_archp(GEN bnr, GEN H, zlog_S *S) { GEN archp = S->archp, archp2 = leafcopy(archp); long j, k, l = lg(archp); for (k = j = 1; k < l; k++) { if (!contains(H, bnr_log_gen_arch(bnr, S, k))) { archp2[j++] = archp[k]; continue; } } if (j == l) return S->archp; setlg(archp2, j); return archp2; } /* MOD useless in this function */ static GEN bnrconductor_factored_i(GEN bnr, GEN H, long raw) { GEN nf, bid, ideal, arch, archp, e, fa, cond = NULL; zlog_S S; checkbnr(bnr); bid = bnr_get_bid(bnr); init_zlog(&S, bid); nf = bnr_get_nf(bnr); H = bnr_subgroup_check(bnr, H, NULL); e = cond0_e(bnr, H, &S); /* in terms of S.P */ archp = condoo_archp(bnr, H, &S); ideal = e? factorbackprime(nf, S.P, e): bid_get_ideal(bid); if (archp == S.archp) { if (!e) cond = bnr_get_mod(bnr); arch = bid_get_arch(bid); } else arch = indices_to_vec01(archp, nf_get_r1(nf)); if (!cond) cond = mkvec2(ideal, arch); if (raw) return cond; fa = e? famat_remove_trivial(mkmat2(S.P, e)): bid_get_fact(bid); return mkvec2(cond, fa); } GEN bnrconductor_factored(GEN bnr, GEN H) { return bnrconductor_factored_i(bnr, H, 0); } GEN bnrconductor_raw(GEN bnr, GEN H) { return bnrconductor_factored_i(bnr, H, 1); } /* (see bnrdisc_i). Given a bnr, and a subgroup * H0 (possibly given as a character chi, in which case H0 = ker chi) of the * ray class group, compute the conductor of H if flag=0. If flag > 0, compute * also the corresponding H' and output * if flag = 1: [[ideal,arch],[hm,cyc,gen],H'] * if flag = 2: [[ideal,arch],newbnr,H'] */ GEN bnrconductormod(GEN bnr, GEN H0, GEN MOD) { GEN nf, bid, arch, archp, bnrc, e, H, cond = NULL; int ischi; zlog_S S; checkbnr(bnr); bid = bnr_get_bid(bnr); init_zlog(&S, bid); nf = bnr_get_nf(bnr); H = bnr_subgroup_check(bnr, H0, NULL); e = cond0_e(bnr, H, &S); archp = condoo_archp(bnr, H, &S); if (archp == S.archp) { if (!e) cond = bnr_get_mod(bnr); arch = gel(bnr_get_mod(bnr), 2); } else arch = indices_to_vec01(archp, nf_get_r1(nf)); /* character or subgroup ? */ ischi = H0 && typ(H0) == t_VEC; if (cond) { /* same conductor */ bnrc = bnr; if (ischi) H = H0; else if (!H) H = diagonal_shallow(bnr_get_cyc(bnr)); } else { long fl = lg(bnr_get_clgp(bnr)) == 4? nf_INIT | nf_GEN: nf_INIT; GEN fa = famat_remove_trivial(mkmat2(S.P, e? e: S.k)), bid; bid = Idealstarmod(nf, mkvec2(fa, arch), nf_INIT | nf_GEN, MOD); bnrc = Buchraymod_i(bnr, bid, fl, MOD); cond = bnr_get_mod(bnrc); if (ischi) H = bnrchar_primitive_raw(bnr, bnrc, H0); else H = imageofgroup(bnr, bnrc, H); } return mkvec3(cond, bnrc, H); } /* OBSOLETE */ GEN bnrconductor_i(GEN bnr, GEN H, long flag) { GEN v; if (flag == 0) return bnrconductor_raw(bnr, H); v = bnrconductormod(bnr, H, NULL); if (flag == 1) gel(v,2) = bnr_get_clgp(gel(v,2)); return v; } /* OBSOLETE */ GEN bnrconductor(GEN bnr, GEN H, long flag) { pari_sp av = avma; if (flag > 2 || flag < 0) pari_err_FLAG("bnrconductor"); return gerepilecopy(av, bnrconductor_i(bnr, H, flag)); } long bnrisconductor(GEN bnr, GEN H0) { pari_sp av = avma; long j, k, l; GEN archp, e, H; zlog_S S; checkbnr(bnr); init_zlog(&S, bnr_get_bid(bnr)); if (!S.no2) return 0; H = bnr_subgroup_check(bnr, H0, NULL); archp = S.archp; e = S.k; l = lg(e); for (k = 1; k < l; k++) { j = itos(gel(e,k)); if (contains(H, bnr_log_gen_pr(bnr, &S, j, k))) return gc_long(av,0); } l = lg(archp); for (k = 1; k < l; k++) if (contains(H, bnr_log_gen_arch(bnr, &S, k))) return gc_long(av,0); return gc_long(av,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 */ static GEN rnfnormgroup_i(GEN bnr, GEN polrel) { long i, j, degrel, degnf, k; GEN bnf, index, discnf, nf, G, detG, fa, gdegrel; GEN fac, col, cnd; forprime_t S; ulong p; checkbnr(bnr); bnf = bnr_get_bnf(bnr); nf = bnf_get_nf(bnf); cnd = gel(bnr_get_mod(bnr), 1); polrel = RgX_nffix("rnfnormgroup", nf_get_pol(nf),polrel,1); if (!gequal1(leading_coeff(polrel))) pari_err_IMPL("rnfnormgroup for nonmonic polynomials"); degrel = degpol(polrel); if (umodiu(bnr_get_no(bnr), degrel)) return NULL; /* degrel-th powers are in norm group */ gdegrel = utoipos(degrel); G = ZV_snf_gcd(bnr_get_cyc(bnr), gdegrel); detG = ZV_prod(G); k = abscmpiu(detG,degrel); if (k < 0) return NULL; if (!k) return diagonal(G); G = diagonal_shallow(G); discnf = nf_get_disc(nf); index = nf_get_index(nf); degnf = nf_get_degree(nf); u_forprime_init(&S, 2, ULONG_MAX); while ( (p = u_forprime_next(&S)) ) { long oldf, nfa; /* If all pr are unramified and have the same residue degree, p =prod pr * and including last pr^f or p^f is the same, but the last isprincipal * is much easier! oldf is used to track this */ if (!umodiu(index, p)) continue; /* can't be treated efficiently */ /* primes of degree 1 are enough, and simpler */ fa = idealprimedec_limit_f(nf, utoipos(p), 1); nfa = lg(fa)-1; if (!nfa) continue; /* all primes above p included ? */ oldf = (nfa == degnf)? -1: 0; for (i=1; i<=nfa; i++) { GEN pr = gel(fa,i), pp, T, polr, modpr; long f, nfac; /* if pr (probably) ramified, we have to use all (unramified) P | pr */ if (idealval(nf,cnd,pr)) { oldf = 0; continue; } modpr = zk_to_Fq_init(nf, &pr, &T, &pp); /* T = NULL, pp ignored */ polr = nfX_to_FqX(polrel, nf, modpr); /* in Fp[X] */ polr = ZX_to_Flx(polr, p); if (!Flx_is_squarefree(polr, p)) { oldf = 0; continue; } fac = gel(Flx_factor(polr, p), 1); f = degpol(gel(fac,1)); if (f == degrel) continue; /* degrel-th powers already included */ nfac = lg(fac)-1; /* check decomposition of pr has Galois type */ for (j=2; j<=nfac; j++) if (degpol(gel(fac,j)) != f) return NULL; if (oldf < 0) oldf = f; else if (oldf != f) oldf = 0; /* last prime & all pr^f, pr | p, included. Include p^f instead */ if (oldf && i == nfa && degrel == nfa*f && !umodiu(discnf, p)) pr = utoipos(p); /* pr^f = N P, P | pr, hence is in norm group */ col = bnrisprincipalmod(bnr,pr,gdegrel,0); if (f > 1) col = ZC_z_mul(col, f); G = ZM_hnf(shallowconcat(G, col)); detG = ZM_det_triangular(G); k = abscmpiu(detG,degrel); if (k < 0) return NULL; if (!k) { cgiv(detG); return G; } } } return NULL; } GEN rnfnormgroup(GEN bnr, GEN polrel) { pari_sp av = avma; GEN G = rnfnormgroup_i(bnr, polrel); if (!G) { set_avma(av); return cgetg(1,t_MAT); } return gerepileupto(av, G); } GEN nf_deg1_prime(GEN nf) { GEN z, T = nf_get_pol(nf), D = nf_get_disc(nf), f = nf_get_index(nf); long degnf = degpol(T); forprime_t S; pari_sp av; ulong p; u_forprime_init(&S, degnf, ULONG_MAX); av = avma; while ( (p = u_forprime_next(&S)) ) { ulong r; if (!umodiu(D, p) || !umodiu(f, p)) continue; r = Flx_oneroot(ZX_to_Flx(T,p), p); if (r != p) { z = utoi(Fl_neg(r, p)); z = deg1pol_shallow(gen_1, z, varn(T)); return idealprimedec_kummer(nf, z, 1, utoipos(p)); } set_avma(av); } return NULL; } /* Given bnf and T defining an abelian relative extension, compute the * corresponding conductor and congruence subgroup. Return * [cond,bnr(cond),H] where cond=[ideal,arch] is the conductor. */ GEN rnfconductor0(GEN bnf, GEN T, long flag) { pari_sp av = avma; GEN P, E, D, nf, module, bnr, H, lim, Tr, MOD; long i, l, degT; if (flag < 0 || flag > 2) pari_err_FLAG("rnfconductor"); bnf = checkbnf(bnf); nf = bnf_get_nf(bnf); Tr = rnfdisc_get_T(nf, T, &lim); T = nfX_to_monic(nf, Tr, NULL); degT = degpol(T); if (!lim) D = rnfdisc_factored(nf, T, NULL); else { D = nfX_disc(nf, Q_primpart(Tr)); if (gequal0(D)) pari_err_DOMAIN("rnfconductor","issquarefree(pol)","=",gen_0, Tr); D = idealfactor_partial(nf, D, lim); } P = gel(D,1); l = lg(P); E = gel(D,2); for (i = 1; i < l; i++) /* cheaply update tame primes */ { /* v_pr(f) = 1 + \sum_{0 < i < l} g_i/g_0 <= 1 + max_{i>0} g_i/(g_i-1) \sum_{0 < i < l} g_i -1 <= 1 + (p/(p-1)) * v_P(e(L/K, pr)), P | pr | p */ GEN pr = gel(P,i), p = pr_get_p(pr), e = gen_1; ulong q, e0 = itou(gel(E,i)); if (e0 > 1 && cmpiu(p, degT) <= 0) { long v, pp = itou(p); if ((v = u_lvalrem(degT, pp, &q))) { /* e = e_tame * e_wild, e_wild | p^v */ ulong t = ugcd(umodiu(subiu(pr_norm(pr),1), q), q); /* e_tame | t */ /* upper bound for 1 + p/(p-1) * v * e(L/Q,p) */ e0 = minuu(e0, 1 + (pp * v * pr_get_e(pr) * upowuu(pp,v) * t) / (pp-1)); e = utoipos(e0); } } gel(E,i) = e; } module = mkvec2(D, identity_perm(nf_get_r1(nf))); MOD = flag? utoipos(degpol(T)): NULL; bnr = Buchraymod_i(bnf, module, nf_INIT|nf_GEN, MOD); H = rnfnormgroup_i(bnr,T); if (!H) return gc_const(av,gen_0); return gerepilecopy(av, flag == 2? bnrconductor_factored(bnr, H) : bnrconductormod(bnr, H, MOD)); } GEN rnfconductor(GEN bnf, GEN T) { return rnfconductor0(bnf, T, 0); } static GEN prV_norms(GEN v) { long i, l; GEN w = cgetg_copy(v, &l); for (i = 1; i < l; i++) gel(w,i) = pr_norm(gel(v,i)); return w; } /* Given a number field bnf=bnr[1], a ray class group structure bnr, and a * subgroup H (HNF form) of the ray class group, compute [n, r1, dk] * attached to H. If flag & rnf_COND, abort (return NULL) if module is not the * conductor. If flag & rnf_REL, return relative data, else absolute */ static GEN bnrdisc_i(GEN bnr, GEN H, long flag) { const long flcond = flag & rnf_COND; GEN nf, clhray, E, ED, dk; long k, d, l, n, r1; zlog_S S; checkbnr(bnr); init_zlog(&S, bnr_get_bid(bnr)); nf = bnr_get_nf(bnr); H = bnr_subgroup_check(bnr, H, &clhray); d = itos(clhray); if (!H) H = diagonal_shallow(bnr_get_cyc(bnr)); E = S.k; ED = cgetg_copy(E, &l); for (k = 1; k < l; k++) { long j, e = itos(gel(E,k)), eD = e*d; GEN H2 = H; for (j = e; j > 0; j--) { GEN z = bnr_log_gen_pr(bnr, &S, j, k); long d2; H2 = ZM_hnf(shallowconcat(H2, z)); d2 = itos( ZM_det_triangular(H2) ); if (flcond && j==e && d2 == d) return NULL; if (d2 == 1) { eD -= j; break; } eD -= d2; } gel(ED,k) = utoi(eD); /* v_{P[k]}(relative discriminant) */ } l = lg(S.archp); r1 = nf_get_r1(nf); for (k = 1; k < l; k++) { if (!contains(H, bnr_log_gen_arch(bnr, &S, k))) { r1--; continue; } if (flcond) return NULL; } /* d = relative degree * r1 = number of unramified real places; * [P,ED] = factorization of relative discriminant */ if (flag & rnf_REL) { n = d; dk = factorbackprime(nf, S.P, ED); } else { n = d * nf_get_degree(nf); r1= d * r1; dk = factorback2(prV_norms(S.P), ED); if (((n-r1)&3) == 2) dk = negi(dk); /* (2r2) mod 4 = 2: r2(relext) is odd */ dk = mulii(dk, powiu(absi_shallow(nf_get_disc(nf)), d)); } return mkvec3(utoipos(n), utoi(r1), dk); } GEN bnrdisc(GEN bnr, GEN H, long flag) { pari_sp av = avma; GEN D = bnrdisc_i(bnr, H, flag); return D? gerepilecopy(av, D): gc_const(av, gen_0); } 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); } /* Given a number field bnf=bnr[1], a ray class group structure bnr and a * vector chi representing a character on the generators bnr[2][3], compute * the conductor of chi. */ GEN bnrconductorofchar(GEN bnr, GEN chi) { pari_sp av = avma; return gerepilecopy(av, bnrconductor_raw(bnr, chi)); } /* \sum U[i]*y[i], U[i],y[i] ZM, we allow lg(y) > lg(U). */ static GEN ZMV_mul(GEN U, GEN y) { long i, l = lg(U); GEN z = NULL; if (l == 1) return cgetg(1,t_MAT); for (i = 1; i < l; i++) { GEN u = ZM_mul(gel(U,i), gel(y,i)); z = z? ZM_add(z, u): u; } return z; } /* t = [bid,U], h = #Cl(K) */ static GEN get_classno(GEN t, GEN h) { GEN bid = gel(t,1), m = gel(t,2), cyc = bid_get_cyc(bid), U = bid_get_U(bid); return mulii(h, ZM_det_triangular(ZM_hnfmodid(ZMV_mul(U,m), cyc))); } static void chk_listBU(GEN L, const char *s) { if (typ(L) != t_VEC) pari_err_TYPE(s,L); if (lg(L) > 1) { GEN z = gel(L,1); if (typ(z) != t_VEC) pari_err_TYPE(s,z); if (lg(z) == 1) return; z = gel(z,1); /* [bid,U] */ if (typ(z) != t_VEC || lg(z) != 3) pari_err_TYPE(s,z); checkbid(gel(z,1)); } } /* Given lists of [bid, unit ideallogs], return lists of ray class numbers */ GEN bnrclassnolist(GEN bnf,GEN L) { pari_sp av = avma; long i, l = lg(L); GEN 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++) { GEN v, z = gel(L,i); long j, lz = lg(z); gel(V,i) = v = cgetg(lz,t_VEC); for (j=1; j 0) { gel(P,c) = gel(P1,i); gel(E,c) = p1; c++; } } } setlg(P, c); setlg(E, c); return mkmat2(P, E); } /* remove index k */ static GEN factorsplice(GEN fa, long k) { GEN p = gel(fa,1), e = gel(fa,2), P, E; long i, l = lg(p) - 1; P = cgetg(l, typ(p)); E = cgetg(l, typ(e)); for (i=1; iidealrelinit; GEN mod = gel(z,3), Fa = gel(z,1); GEN P = gel(Fa,1), E = gel(Fa,2); long k, nz, clhray = z[2], lP = lg(P); for (k=1; kbnf, gel(mod,1), gel(mod,2), clhray); return get_NR1D(N, clhray, D->degk, nz, D->fadk, idealrel); } /* Given a list of bids and attached unit log matrices, return the * list of discrayabs. Only keep moduli which are conductors. */ GEN discrayabslist(GEN bnf, GEN L) { pari_sp av = avma; long i, l = lg(L); GEN nf, V, D, h; disc_data ID; chk_listBU(L, "discrayabslist"); if (l == 1) return cgetg(1, t_VEC); ID.bnf = bnf = checkbnf(bnf); nf = bnf_get_nf(bnf); h = bnf_get_no(bnf); ID.degk = nf_get_degree(nf); ID.fadk = absZ_factor(nf_get_disc(nf)); ID.idealrelinit = trivial_fact(); V = cgetg(l, t_VEC); D = cgetg(l, t_VEC); for (i = 1; i < l; i++) { GEN z = gel(L,i), v, d; long j, lz = lg(z); gel(V,i) = v = cgetg(lz,t_VEC); gel(D,i) = d = cgetg(lz,t_VEC); for (j=1; j>=1) if (kk&1) rowsel[nba++] = nc + jj; setlg(rowsel, nba); rowselect_p(m, mm, rowsel, nc+1); H[k+1] = hdet(h, mm); } H = gerepileuptoleaf(av, H); gel(L,j) = mkvec2(gel(b,1), H); } return L; } static int is_module(GEN v) { if (lg(v) != 3 || (typ(v) != t_MAT && typ(v) != t_VEC)) return 0; return typ(gel(v,1)) == t_VECSMALL && typ(gel(v,2)) == t_VECSMALL; } GEN decodemodule(GEN nf, GEN fa) { long n, nn, k; pari_sp av = avma; GEN G, E, id, pr; nf = checknf(nf); if (!is_module(fa)) pari_err_TYPE("decodemodule [not a factorization]", fa); n = nf_get_degree(nf); nn = n*n; id = NULL; G = gel(fa,1); E = gel(fa,2); for (k=1; k15) pari_err_IMPL("r1>15 in discrayabslistarch"); arch = const_vec(r1, gen_1); } else if (lg(arch)-1 != r1) pari_err_TYPE("Idealstar [incorrect archimedean component]",arch); U = log_prk_units_init(bnf); archp = vec01_to_indices(arch); nba = lg(archp)-1; sgnU = zm_to_ZM( nfsign_units(bnf, archp, 1) ); if (!allarch) sgnU = mkvec2(const_vec(nba,gen_2), sgnU); empty = cgetg(1,t_VEC); /* what follows was rewritten from Ideallist */ BOUND = utoipos(bound); p = cgetipos(3); u_forprime_init(&S, 2, bound); av = avma; sqbou = (long)sqrt((double)bound) + 1; Z = const_vec(bound, empty); gel(Z,1) = mkvec(zsimp()); if (DEBUGLEVEL>1) err_printf("Starting zidealstarunits computations\n"); /* The goal is to compute Ray (lists of bnrclassno). Z contains "zsimps", * simplified bid, from which bnrclassno is easy to compute. * Once p > sqbou, delete Z[i] for i > sqbou and compute directly Ray */ Ray = Z; while ((p[2] = u_forprime_next(&S))) { if (!flbou && p[2] > sqbou) { flbou = 1; if (DEBUGLEVEL>1) err_printf("\nStarting bnrclassno computations\n"); Z = gerepilecopy(av,Z); Ray = cgetg(bound+1, t_VEC); for (i=1; i<=bound; i++) gel(Ray,i) = bnrclassno_all(gel(Z,i),h,sgnU); Z = vecslice(Z, 1, sqbou); } fa = idealprimedec_limit_norm(nf,p,BOUND); for (j=1; j 1 && v[lv-1] == prcode) break; gel(p2,++c) = zsimpjoin(z,sprk,U_pr,prcode,l); } setlg(p2, c+1); pz = gel(Ray,iQ); if (flbou) p2 = bnrclassno_all(p2,h,sgnU); if (lg(pz) > 1) p2 = shallowconcat(pz,p2); gel(Ray,iQ) = p2; } Q = itou_or_0( muluu(Q, q) ); if (!Q || Q > bound) break; } } if (gc_needed(av,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"[1]: discrayabslistarch"); gerepileall(av, flbou? 2: 1, &Z, &Ray); } } if (!flbou) /* occurs iff bound = 1,2,4 */ { if (DEBUGLEVEL>1) err_printf("\nStarting bnrclassno computations\n"); Ray = cgetg(bound+1, t_VEC); for (i=1; i<=bound; i++) gel(Ray,i) = bnrclassno_all(gel(Z,i),h,sgnU); } 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 */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_qfsolve /* LINEAR ALGEBRA */ /* complete by 0s, assume l-1 <= n */ static GEN vecextend(GEN v, long n) { long i, l = lg(v); GEN w = cgetg(n+1, t_COL); for (i = 1; i < l; i++) gel(w,i) = gel(v,i); for ( ; i <=n; i++) gel(w,i) = gen_0; return w; } /* Gives a unimodular matrix with the last column(s) equal to Mv. * Mv can be a column vector or a rectangular matrix. * redflag = 0 or 1. If redflag = 1, LLL-reduce the n-#v first columns. */ static GEN completebasis(GEN Mv, long redflag) { GEN U; long m, n; if (typ(Mv) == t_COL) Mv = mkmat(Mv); n = lg(Mv)-1; m = nbrows(Mv); /* m x n */ if (m == n) return Mv; (void)ZM_hnfall_i(shallowtrans(Mv), &U, 0); U = ZM_inv(shallowtrans(U),NULL); if (m==1 || !redflag) return U; /* LLL-reduce the m-n first columns */ return shallowconcat(ZM_lll(vecslice(U,1,m-n), 0.99, LLL_INPLACE), vecslice(U, m-n+1,m)); } /* Return U in GLn(Z) whose first d columns span Ker (M mod p). */ static GEN kermodp(GEN M, GEN p, long *d) { long j, l; GEN K, B, U; K = FpM_center(FpM_ker(M, p), p, shifti(p,-1)); B = completebasis(K,0); l = lg(M); U = cgetg(l, t_MAT); for (j = 1; j < l; j++) gel(U,j) = gel(B,l-j); *d = lg(K)-1; return U; } /* INVARIANTS COMPUTATIONS */ static GEN principal_minor(GEN G, long i) { return matslice(G,1,i,1,i); } static GEN det_minors(GEN G) { long i, l = lg(G); GEN v = cgetg(l+1, t_VEC); gel(v,1) = gen_1; for (i = 2; i <= l; i++) gel(v,i) = ZM_det(principal_minor(G,i-1)); return v; } static GEN hilberts(GEN a, GEN b, GEN P) { long i, lP = lg(P); GEN v = cgetg(lP, t_VECSMALL); for (i = 1; i < lP; i++) v[i] = hilbertii(a, b, gel(P,i)) < 0; return v; } /* 4 | disc(q); special case of gtomat */ static GEN qfbmat(GEN q) { GEN a = gel(q,1), b = shifti(gel(q,2), -1), c = gel(q,3); retmkmat22(a, b, b, c); } /* 2*qfbmat(q) */ static GEN qfbmat2(GEN q) { GEN a = shifti(gel(q,1), 1), b = gel(q,2), c = shifti(gel(q,3), 1); retmkmat22(a, b, b, c); } /* Given a symmetric matrix G over Z, compute the Witt invariant of G at p * v = det_minors(G) [G diagonalized]; assume that none of the v[i] is 0. */ static long witt(GEN v, GEN p) { long k = lg(v)-2, h = hilbertii(gel(v,k), gel(v,k+1), p); for (k--; k >= 1; k--) if (hilbertii(negi(gel(v,k)), gel(v,k+1),p) < 0) h = -h; return h; } /* QUADRATIC FORM REDUCTION */ /* private version of qfgaussred: * - early abort if k-th principal minor is singular, return stoi(k) * - else return a matrix whose upper triangular part is qfgaussred(a) */ static GEN partialgaussred(GEN a) { long n = lg(a)-1, k; a = RgM_shallowcopy(a); for(k = 1; k < n; k++) { GEN ak, p = gcoeff(a,k,k); long i, j; if (isintzero(p)) return stoi(k); ak = row(a, k); for (i=k+1; i<=n; i++) gcoeff(a,k,i) = gdiv(gcoeff(a,k,i), p); for (i=k+1; i<=n; i++) { GEN c = gel(ak,i); if (gequal0(c)) continue; for (j=i; j<=n; j++) gcoeff(a,i,j) = gsub(gcoeff(a,i,j), gmul(c,gcoeff(a,k,j))); } } if (isintzero(gcoeff(a,n,n))) return stoi(n); return a; } /* LLL-reduce a positive definite qf QD bounding the indefinite G, dim G > 1. * Then finishes by looking for trivial solution */ static GEN qftriv(GEN G, GEN z, long base); static GEN qflllgram_indef(GEN G, long base, int *fail) { GEN M, R, g, DM, S, dR; long i, j, n = lg(G)-1; *fail = 0; R = partialgaussred(G); if (typ(R) == t_INT) return qftriv(G, R, base); R = Q_remove_denom(R, &dR); /* avoid rational arithmetic */ M = zeromatcopy(n,n); DM = zeromatcopy(n,n); for (i = 1; i <= n; i++) { GEN d = absi_shallow(gcoeff(R,i,i)); if (dR) { gcoeff(M,i,i) = dR; gcoeff(DM,i,i) = mulii(d,dR); } else { gcoeff(M,i,i) = gen_1; gcoeff(DM,i,i) = d; } for (j = i+1; j <= n; j++) { gcoeff(M,i,j) = gcoeff(R,i,j); gcoeff(DM,i,j) = mulii(d, gcoeff(R,i,j)); } } /* G = M~*D*M, D diagonal, DM=|D|*M, g = M~*|D|*M */ g = ZM_transmultosym(M,DM); S = lllgramint(Q_primpart(g)); R = qftriv(qf_ZM_apply(G,S), NULL, base); switch(typ(R)) { case t_COL: return ZM_ZC_mul(S,R); case t_MAT: *fail = 1; return mkvec2(R, S); default: gel(R,2) = ZM_mul(S, gel(R,2)); return R; } } /* G symmetric, i < j, let E = E_{i,j}(a), G <- E~*G*E, U <- U*E. * Everybody integral */ static void qf_apply_transvect_Z(GEN G, GEN U, long i, long j, GEN a) { long k, n = lg(G)-1; gel(G, j) = ZC_lincomb(gen_1, a, gel(G,j), gel(G,i)); for (k = 1; k < n; k++) gcoeff(G, j, k) = gcoeff(G, k, j); gcoeff(G,j,j) = addmulii(gcoeff(G,j,j), a, addmulii(gcoeff(G,i,j), a,gcoeff(G,i,i))); gel(U, j) = ZC_lincomb(gen_1, a, gel(U,j), gel(U,i)); } /* LLL reduction of the quadratic form G (Gram matrix) * where we go on, even if an isotropic vector is found. */ static GEN qflllgram_indefgoon(GEN G) { GEN red, U, A, U1,U2,U3,U5,U6, V, B, G2,G3,G4,G5, G6, a, g; long i, j, n = lg(G)-1; int fail; red = qflllgram_indef(G,1, &fail); if (fail) return red; /*no isotropic vector found: nothing to do*/ /* otherwise a solution is found: */ U1 = gel(red,2); G2 = gel(red,1); /* G2[1,1] = 0 */ U2 = gel(ZV_extgcd(row(G2,1)), 2); G3 = qf_ZM_apply(G2,U2); U = ZM_mul(U1,U2); /* qf_apply(G,U) = G3 */ /* G3[1,] = [0,...,0,g], g^2 | det G */ g = gcoeff(G3,1,n); a = diviiround(negi(gcoeff(G3,n,n)), shifti(g,1)); if (signe(a)) qf_apply_transvect_Z(G3,U,1,n,a); /* G3[n,n] reduced mod 2g */ if (n == 2) return mkvec2(G3,U); V = rowpermute(vecslice(G3, 2,n-1), mkvecsmall2(1,n)); A = mkmat22(gcoeff(G3,1,1),gcoeff(G3,1,n),gcoeff(G3,1,n),gcoeff(G3,2,2)); B = ground(RgM_neg(QM_mul(QM_inv(A), V))); U3 = matid(n); for (j = 2; j < n; j++) { gcoeff(U3,1,j) = gcoeff(B,1,j-1); gcoeff(U3,n,j) = gcoeff(B,2,j-1); } G4 = qf_ZM_apply(G3,U3); /* the last column of G4 is reduced */ U = ZM_mul(U,U3); if (n == 3) return mkvec2(G4,U); red = qflllgram_indefgoon(matslice(G4,2,n-1,2,n-1)); if (typ(red) == t_MAT) return mkvec2(G4,U); /* Let U5:=matconcat(diagonal[1,red[2],1]) * return [qf_ZM_apply(G5, U5), U*U5] */ G5 = gel(red,1); U5 = gel(red,2); G6 = cgetg(n+1,t_MAT); gel(G6,1) = gel(G4,1); gel(G6,n) = gel(G4,n); for (j=2; j= lg(f)) pari_err_BUG("update_fm"); for (k = 1; k < v; k++) { u = QM_mul(gel(f, k+1), u); gel(f,k+1) = gen_0; /* for gerepileall */ } gel(f,v+1) = u; } } static GEN prod_fm(GEN f, long i) { long v = vals(i), k; GEN u = gel(f, ++v); for (i >>= v, k = v+1; i; i >>= 1, k++) if (odd(i)) u = QM_mul(gel(f,k), u); return u; } /* Minimization of the quadratic form G, deg G != 0, dim n >= 2 * G symmetric integral * Returns [G',U,factd] with U in GLn(Q) such that G'=U~*G*U*constant * is integral and has minimal determinant. * In dimension 3 or 4, may return a prime p if the reduction at p is * impossible because of local nonsolvability. * P,E = factor(+/- det(G)), d = det(G) "prime" -1 is ignored, * Either E or d should be NULL, but not both */ static GEN qfminimize_fact(GEN G, GEN P, GEN E, GEN d, long loc) { GEN U = NULL, Ker = NULL, faE, faP; long n = lg(G)-1, lP = lg(P), i; faP = vectrunc_init(lP); faE = vecsmalltrunc_init(lP); for (i = 1; i < lP; i++) { long Ei, vp, wp; GEN p = gel(P,i); if (is_pm1(p)) continue; Ei = E ? E[i]: Z_pval(d, p); vp = Ei; wp = vp; if (!vp) continue; if (DEBUGLEVEL >= 3) err_printf("qfminimize: for %Ps^%ld:", p,vp); while (vp) { long idx = 0, dimKer = 0; /* -Wall */ GEN d, sol = NULL, FU = zerovec(2*expu(vp)+100); pari_sp av = avma; while (vp) /* loop until vp <= n */ { if (DEBUGLEVEL>=3 && vp <= wp) { err_printf(" %ld%%", (Ei-vp)*100/Ei); wp -= Ei/100; } /* The case vp = 1 can be minimized only if n is odd. */ if (vp == 1 && !odd(n)) break; Ker = kermodp(G,p, &dimKer); /* dimKer <= vp */ if (DEBUGLEVEL >= 4) err_printf(" dimKer = %ld\n",dimKer); if (dimKer == n) break; G = qf_ZM_apply(G, Ker); /* 1st case: dimKer < vp */ /* then the kernel mod p contains a kernel mod p^2 */ if (dimKer >= vp) break; if (DEBUGLEVEL >= 4) err_printf(" case 1: dimker < vp\n"); if (dimKer == 1) { long j; gcoeff(G,1,1) = diviiexact(gcoeff(G,1,1), sqri(p)); for (j = 2; j <= n; j++) gcoeff(G,1,j) = gcoeff(G,j,1) = diviiexact(gcoeff(G,j,1), p); gel(Ker,1) = RgC_Rg_div(gel(Ker,1), p); vp -= 2; } else { GEN A, B, C, K2; long j, dimKer2; blocks4(G, dimKer,n, &A,&B,&C); A = ZsymM_Z_divexact(A, p); K2 = kermodp(A, p, &dimKer2); /* Write G = [pA,B;B~,C] and apply [K2/p,0;0,Id] by blocks */ A = qf_ZM_apply(A,K2); ZsymM_Z_divexact_partial(A, dimKer2, p); B = ZM_transmul(B,K2); for (j = 1; j <= dimKer2; j++) gel(B,j) = ZC_Z_divexact(gel(B,j), p); G = shallowmatconcat(mkmat22(A,shallowtrans(B),B,C)); /* Ker *= [K2,0;0,Id] */ B = ZM_mul(vecslice(Ker,1,dimKer),K2); for (j = 1; j <= dimKer2; j++) gel(B,j) = RgC_Rg_div(gel(B,j), p); Ker = shallowconcat(B, vecslice(Ker,dimKer+1,n)); vp -= 2*dimKer2; } update_fm(FU, Ker, idx++); if (gc_needed(av, 1)) { if (DEBUGMEM >= 2) pari_warn(warnmem,"qfminimize"); gerepileall(av, 2, &G, &FU); } } if (idx) { GEN PU = prod_fm(FU, idx); U = U ? QM_mul(U, PU): PU; } if (vp == 0) break; if (vp == 1 && !odd(n)) { vectrunc_append(faP, p); vecsmalltrunc_append(faE, 1); break; } if (dimKer == n) { /* trivial case: dimKer = n */ if (DEBUGLEVEL >= 4) err_printf(" case 0: dimKer = n\n"); G = ZsymM_Z_divexact(G, p); vp -= n; continue; } U = U ? QM_mul(U, Ker): Ker; /* vp = dimKer * 2nd case: kernel has dim >= 2 and contains an elt of norm 0 mod p^2, * find it */ if (dimKer > 2) { if (DEBUGLEVEL >= 4) err_printf(" case 2.1\n"); dimKer = 3; sol = qfsolvemodp(ZsymM_Z_divexact(principal_minor(G,3),p), p); sol = FpC_red(sol, p); } else if (dimKer == 2) { GEN a = modii(diviiexact(gcoeff(G,1,1),p), p); GEN b = modii(diviiexact(gcoeff(G,1,2),p), p); GEN c = modii(diviiexact(gcoeff(G,2,2),p), p); GEN D = modii(subii(sqri(b), mulii(a,c)), p); if (kronecker(D,p) >= 0) { if (DEBUGLEVEL >= 4) err_printf(" case 2.2\n"); sol = signe(a)? mkcol2(Fp_sub(Fp_sqrt(D,p), b, p), a): vec_ei(2,1); } } if (sol) { long j; sol = FpC_center(sol, p, shifti(p,-1)); sol = Q_primpart(sol); if (DEBUGLEVEL >= 4) err_printf(" sol = %Ps\n", sol); Ker = completebasis(vecextend(sol,n), 1); G = qf_ZM_apply(G, Ker); for (j = 1; j < n; j++) gcoeff(G,n,j) = gcoeff(G,j,n) = diviiexact(gcoeff(G,j,n), p); gcoeff(G,n,n) = diviiexact(gcoeff(G,n,n), sqri(p)); U = QM_mul(U,Ker); gel(U,n) = RgC_Rg_div(gel(U,n), p); vp -= 2; continue; } /* Now 0 < vp = dimKer < 3 and kernel contains no vector with norm p^2 */ /* exchanging kernel and image makes minimization easier ? */ d = ZM_det(G); if (odd((n-3) / 2)) d = negi(d); if ((vp==1 && kronecker(gmod(gdiv(negi(d), gcoeff(G,1,1)),p), p) >= 0) || (vp==2 && odd(n) && n >= 5) || (vp==2 && !odd(n) && kronecker(modii(diviiexact(d,sqri(p)), p),p) < 0)) { long j; if (DEBUGLEVEL >= 4) err_printf(" case 3\n"); ZsymM_Z_divexact_partial(G, dimKer, p); for (j = dimKer+1; j <= n; j++) gel(U,j) = RgC_Rg_mul(gel(U,j), p); vp -= 2*dimKer-n; continue; } /* Minimization was not possible so far. */ /* If n == 3 or 4, this proves the local nonsolubility at p. */ if (loc && (n == 3 || n == 4)) { if (DEBUGLEVEL >= 1) err_printf(" no local solution at %Ps\n",p); return p; } vectrunc_append(faP, p); vecsmalltrunc_append(faE, vp); break; } if (DEBUGLEVEL >= 3) err_printf("\n"); } if (!U) U = matid(n); else { /* apply LLL to avoid coefficient explosion */ GEN u = ZM_lll(Q_primpart(U), .99, LLL_IM); G = qf_ZM_apply(G, u); U = QM_mul(U, u); } return mkvec4(G, U, faP, faE); } /* assume G square integral */ static void check_symmetric(GEN G) { long i,j, l = lg(G); for (i = 1; i < l; i++) for(j = 1; j < i; j++) if (!equalii(gcoeff(G,i,j), gcoeff(G,j,i))) pari_err_TYPE("qfsolve [not symmetric]",G); } /* assume G symmetric and integral */ static void symmetric_non0_coeff(GEN G, long *pi, long *pj) { long i, j, l = lg(G); *pi = *pj = 0; for (i = 1; i < l; i++) for (j = 1; j <= i; j++) if (signe(gcoeff(G,i,j))) { *pi = i; *pj = j; return; } } GEN qfminimize(GEN G) { pari_sp av = avma; GEN c, d, F, H, U; long i, j, n = lg(G)-1; if (typ(G) != t_MAT) pari_err_TYPE("qfminimize", G); if (n == 0) pari_err_DOMAIN("qfminimize", "dimension" , "=", gen_0, G); if (n != nbrows(G)) pari_err_DIM("qfminimize"); G = Q_primpart(G); RgM_check_ZM(G, "qfminimize"); check_symmetric(G); d = ZM_det(G); if (!signe(d)) pari_err_DOMAIN("qfminimize", "det" , "=", gen_0, gen_0); F = absZ_factor(d); H = qfminimize_fact(G, gel(F,1), ZV_to_zv(gel(F,2)), NULL, 0); symmetric_non0_coeff(G, &i, &j); U = gel(H,2); H = gel(H,1); c = gdiv(gcoeff(H,i,j), RgV_dotproduct(gel(U,i), RgM_RgC_mul(G, gel(U,j)))); return gerepilecopy(av, mkvec3(H, U, c)); } /* CLASS GROUP COMPUTATIONS */ /* Compute the square root of the quadratic form q of discriminant D = 4 * md * Not fully implemented; only works for D squarefree except at 2, where the * valuation is 2 or 3. Finally, [P,E] = factor(2*abs(D)) if valuation is 3 and * factor(abs(D / 4)) otherwise */ static GEN qfbsqrt(GEN D, GEN md, GEN q, GEN P) { GEN a = gel(q,1), b = shifti(gel(q,2),-1), c = gel(q,3), B = negi(b); GEN m, n, Q, M, N, d = negi(md); /* ac - b^2 */ long i, lP = lg(P); /* 1) solve m^2 = a, m*n = -b, n^2 = c in Z/dZ => q(n,m) = 0 mod d */ M = cgetg(lP, t_VEC); N = cgetg(lP, t_VEC); for (i = 1; i < lg(P); i++) { GEN p = gel(P,i); if (dvdii(a,p)) { n = Fp_sqrt(c, p); m = Fp_div(B, n, p); } else { m = Fp_sqrt(a, p); n = Fp_div(B, m, p); } gel(M, i) = m; gel(N, i) = n; } m = ZV_chinese_center(M, P, NULL); n = ZV_chinese_center(N, P, NULL); /* 2) build Q, with det=-1 such that Q(x,y,0) = G(x,y) */ N = diviiexact(addii(mulii(a,n), mulii(b,m)), d); M = diviiexact(addii(mulii(b,n), mulii(c,m)), d); Q = diviiexact(subiu(addii(mulii(m,M), mulii(n,N)), 1), d); /*(q(n,m)-d)/d^2 */ Q = mkmat3(mkcol3(a,b,N), mkcol3(b,c,M), mkcol3(N,M,Q)); /* det = -1 */ /* 3) reduce Q to [0,0,-1; 0,1,0; -1,0,0] */ M = qflllgram_indefgoon2(Q); if (signe(gel(M,1)) < 0) M = ZC_neg(M); a = gel(M,1); b = gel(M,2); c = gel(M,3); if (!mpodd(a)) { swap(a, c); togglesign_safe(&b); } return mkqfb(a, shifti(b,1), shifti(c,1), D); } /* \prod gen[i]^e[i] as a Qfb, e in {0,1}^n nonzero */ static GEN qfb_factorback(GEN gen, GEN e, GEN isqrtD) { GEN q = NULL; long j, l = lg(gen), n = 0; for (j = 1; j < l; j++) if (e[j]) { n++; q = q? qfbcompraw(q, gel(gen,j)): gel(gen,j); } return (n <= 1)? q: qfbred0(q, 0, isqrtD, NULL); } /* unit form discriminant 4d */ static GEN id(GEN d) { retmkmat22(gen_1, gen_0, gen_0, negi(d)); } /* Shanks/Bosma-Stevenhagen algorithm to compute the 2-Sylow of the class * group of discriminant D. Only works for D = fundamental discriminant. * When D = 1(4), work with 4D. * P2D,E2D = factor(abs(2*D)) * Pm2D = factor(-abs(2*D))[,1]. * Return a form having Witt invariants W at Pm2D */ static GEN quadclass2(GEN D, GEN P2D, GEN E2D, GEN Pm2D, GEN W, int n_is_4) { GEN U2 = NULL, gen, Wgen, isqrtD, d; long i, r, m; int splice2 = mpodd(D); if (!splice2) d = shifti(D,-2); else { d = D; D = shifti(D,2); } /* D = 4d */ if (zv_equal0(W)) return id(d); r = lg(Pm2D) - 4; /* >= 0 since W != 0 */ m = (signe(D) > 0)? r+1: r; if (n_is_4) { /* n = 4: look among forms of type q or 2*q, since Q can be imprimitive */ U2 = hilberts(gen_2, d, Pm2D); if (zv_equal(U2,W)) return gmul2n(id(d),1); } gen = cgetg(m+2, t_VEC); for (i = 1; i <= m; i++) { /* no need to look at P2D[1]=2*/ GEN q = powiu(gel(P2D,i+1), E2D[i+1]); gel(gen,i) = mkqfb(q, gen_0, negi(diviiexact(d,q)), D); } if (!mpodd(d)) { gel(gen, ++m) = mkqfb(gen_2, gen_0, negi(shifti(d,-1)), D); r++; } else if (Mod4(d) != 1) { gel(gen, ++m) = mkqfb(gen_2, gen_2, shifti(subsi(1,d),-1), D); r++; } else setlg(gen, m+1); if (!r) return id(d); /* remove 2^3; leave alone 2^4 */ if (splice2) P2D = vecsplice(P2D, 1); Wgen = cgetg(m+1, t_MAT); for (i = 1; i <= m; i++) gel(Wgen,i) = hilberts(gmael(gen,i,1), d, Pm2D); isqrtD = signe(D) > 0? sqrti(D) : NULL; for(;;) { GEN Wgen2, gen2, Ker, indexim = gel(Flm_indexrank(Wgen,2), 2); long dKer; if (lg(indexim)-1 >= r) { GEN W2 = Wgen, V; if (lg(indexim) < lg(Wgen)) W2 = vecpermute(Wgen,indexim); if (U2) W2 = vec_append(W2,U2); V = Flm_Flc_invimage(W2, W, 2); if (V) { GEN Q = qfb_factorback(vecpermute(gen,indexim), V, isqrtD); return (U2 && V[lg(V)-1])? qfbmat2(Q): qfbmat(Q); } } Ker = Flm_ker(Wgen,2); dKer = lg(Ker)-1; gen2 = cgetg(m+1, t_VEC); Wgen2 = cgetg(m+1, t_MAT); for (i = 1; i <= dKer; i++) { GEN q = qfb_factorback(gen, gel(Ker,i), isqrtD); gel(gen2,i) = q = qfbsqrt(D, d, q, P2D); gel(Wgen2,i) = hilberts(gel(q,1), d, Pm2D); } for (; i <=m; i++) { long j = indexim[i-dKer]; gel(gen2,i) = gel(gen,j); gel(Wgen2,i) = gel(Wgen,j); } gen = gen2; Wgen = Wgen2; } } /* QUADRATIC EQUATIONS */ /* is x*y = -1 ? */ static int both_pm1(GEN x, GEN y) { return is_pm1(x) && is_pm1(y) && signe(x) == -signe(y); } /* Try to solve G = 0 with small coefficients. This is proved to work if * - det(G) = 1, dim <= 6 and G is LLL reduced * Returns G if no solution is found. * Exit with a norm 0 vector if one such is found. * If base == 1 and norm 0 is obtained, returns [H~*G*H,H] where * the 1st column of H is a norm 0 vector */ static GEN qftriv(GEN G, GEN R, long base) { long n = lg(G)-1, i; GEN s, H; /* case 1: A basis vector is isotropic */ for (i = 1; i <= n; i++) if (!signe(gcoeff(G,i,i))) { if (!base) return col_ei(n,i); H = matid(n); swap(gel(H,1), gel(H,i)); return mkvec2(qf_apply_tau(G,1,i),H); } /* case 2: G has a block +- [1,0;0,-1] on the diagonal */ for (i = 2; i <= n; i++) if (!signe(gcoeff(G,i-1,i)) && both_pm1(gcoeff(G,i-1,i-1),gcoeff(G,i,i))) { s = col_ei(n,i); gel(s,i-1) = gen_m1; if (!base) return s; H = matid(n); gel(H,i) = gel(H,1); gel(H,1) = s; return mkvec2(qf_ZM_apply(G,H),H); } if (!R) return G; /* fail */ /* case 3: a principal minor is 0 */ s = ZM_ker(principal_minor(G, itos(R))); s = vecextend(Q_primpart(gel(s,1)), n); if (!base) return s; H = completebasis(s, 0); gel(H,n) = ZC_neg(gel(H,1)); gel(H,1) = s; return mkvec2(qf_ZM_apply(G,H),H); } /* p a prime number, G 3x3 symmetric. Finds X!=0 such that X^t G X = 0 mod p. * Allow returning a shorter X: to be completed with 0s. */ static GEN qfsolvemodp(GEN G, GEN p) { GEN a,b,c,d,e,f, v1,v2,v3,v4,v5, x1,x2,x3,N1,N2,N3,s,r; /* principal_minor(G,3) = [a,b,d; b,c,e; d,e,f] */ a = modii(gcoeff(G,1,1), p); if (!signe(a)) return mkcol(gen_1); v1 = a; b = modii(gcoeff(G,1,2), p); c = modii(gcoeff(G,2,2), p); v2 = modii(subii(mulii(a,c), sqri(b)), p); if (!signe(v2)) return mkcol2(Fp_neg(b,p), a); d = modii(gcoeff(G,1,3), p); e = modii(gcoeff(G,2,3), p); f = modii(gcoeff(G,3,3), p); v4 = modii(subii(mulii(c,d), mulii(e,b)), p); v5 = modii(subii(mulii(a,e), mulii(d,b)), p); v3 = subii(mulii(v2,f), addii(mulii(v4,d), mulii(v5,e))); /* det(G) */ v3 = modii(v3, p); N1 = Fp_neg(v2, p); x3 = mkcol3(v4, v5, N1); if (!signe(v3)) return x3; /* now, solve in dimension 3... reduction to the diagonal case: */ x1 = mkcol3(gen_1, gen_0, gen_0); x2 = mkcol3(negi(b), a, gen_0); if (kronecker(N1,p) == 1) return ZC_lincomb(Fp_sqrt(N1,p),gen_1,x1,x2); N2 = Fp_div(Fp_neg(v3,p), v1, p); if (kronecker(N2,p) == 1) return ZC_lincomb(Fp_sqrt(N2,p),gen_1,x2,x3); N3 = Fp_mul(v2, N2, p); if (kronecker(N3,p) == 1) return ZC_lincomb(Fp_sqrt(N3,p),gen_1,x1,x3); r = gen_1; for(;;) { s = Fp_sub(gen_1, Fp_mul(N1,Fp_sqr(r,p),p), p); if (kronecker(s, p) <= 0) break; r = randomi(p); } s = Fp_sqrt(Fp_div(s,N3,p), p); return ZC_add(x1, ZC_lincomb(r,s,x2,x3)); } /* Given a square rational matrix G of dimension n >= 1, solves over Z the * quadratic equation X^tGX = 0. The solution is a t_VEC (a solution) or a * t_MAT (totally isotropic subspace). If no solution exists, returns an * integer: a prime p (no local solution at p), or -1 (no real solution), or * -2 (n = 2 and -deg(G) not a square). */ static GEN qfsolve_i(GEN G) { GEN M, signG, Min, U, G1, M1, G2, M2, solG2, P = NULL, E = NULL; GEN solG1, sol, Q, d, dQ, detG2; long n, np, codim, dim; int fail; if (typ(G) == t_VEC && lg(G)==3) { P = gel(G,2); G = gel(G,1); if (typ(P)==t_MAT) { if (!is_Z_factornon0(P)) pari_err_TYPE("qfsolve", P); P = gel(P,1); } else if (!is_vec_t(typ(P)) || !RgV_is_ZVnon0(P)) pari_err_TYPE("qfsolve", P); } if (typ(G) != t_MAT) pari_err_TYPE("qfsolve", G); n = lg(G)-1; if (n == 0) pari_err_DOMAIN("qfsolve", "dimension" , "=", gen_0, G); if (n != nbrows(G)) pari_err_DIM("qfsolve"); G = Q_primpart(G); RgM_check_ZM(G, "qfsolve"); check_symmetric(G); /* Trivial case: det = 0 */ d = ZM_det(G); if (!signe(d)) { if (n == 1) return mkcol(gen_1); sol = ZM_ker(G); if (lg(sol) == 2) sol = gel(sol,1); return sol; } /* Small dimension: n <= 2 */ if (n == 1) return gen_m1; if (n == 2) { GEN t, a = gcoeff(G,1,1); if (!signe(a)) return mkcol2(gen_1, gen_0); if (signe(d) > 0) return gen_m1; /* no real solution */ if (!Z_issquareall(negi(d), &t)) return gen_m2; return mkcol2(subii(t,gcoeff(G,1,2)), a); } /* 1st reduction of the coefficients of G */ M = qflllgram_indef(G,0,&fail); if (typ(M) == t_COL) return M; G = gel(M,1); M = gel(M,2); /* real solubility */ signG = ZV_to_zv(qfsign(G)); { long r = signG[1], s = signG[2]; if (!r || !s) return gen_m1; if (r < s) { G = ZM_neg(G); signG = mkvecsmall2(s,r); } } /* factorization of the determinant */ if (!P) { GEN F = absZ_factor(d); P = gel(F,1); E = ZV_to_zv(gel(F,2)); } /* Minimization and local solubility */ Min = qfminimize_fact(G, P, E, d, 1); if (typ(Min) == t_INT) return Min; M = QM_mul(M, gel(Min,2)); G = gel(Min,1); P = gel(Min,3); E = gel(Min,4); /* P,E = factor(|det(G))| */ /* Now, we know that local solutions exist (except maybe at 2 if n==4) * if n==3, det(G) = +-1 * if n==4, or n is odd, det(G) is squarefree. * if n>=6, det(G) has all its valuations <=2. */ /* Reduction of G and search for trivial solutions. */ /* When |det G|=1, such trivial solutions always exist. */ U = qflllgram_indef(G,0,&fail); if (typ(U) == t_COL) return Q_primpart(RgM_RgC_mul(M,U)); G = gel(U,1); M = QM_mul(M, gel(U,2)); /* P,E = factor(|det(G))| */ /* If n >= 6 is even, need to increment the dimension by 1 to suppress all * squares from det(G) */ np = lg(P)-1; if (n < 6 || odd(n) || !np) { codim = 0; G1 = G; M1 = NULL; } else { GEN aux; long i; codim = 1; n++; aux = gen_1; for (i = 1; i <= np; i++) if (E[i] == 2) { aux = mulii(aux, gel(P,i)); E[i] = 3; } /* aux = largest square divisor of d; choose sign(aux) so as to balance * the signature of G1 */ if (signG[1] > signG[2]) { signG[2]++; aux = negi(aux); } else signG[1]++; G1 = shallowmatconcat(diagonal_shallow(mkvec2(G,aux))); /* P,E = factor(|det G1|) */ Min = qfminimize_fact(G1, P, E, NULL, 1); G1 = gel(Min,1); M1 = gel(Min,2); P = gel(Min,3); E = gel(Min,4); np = lg(P)-1; } /* now, d is squarefree */ if (!np) { G2 = G1; M2 = NULL; } /* |d| = 1 */ else { /* |d| > 1: increment dimension by 2 */ GEN factdP, factdE, W, v = NULL; long i, lfactdP, lP; codim += 2; d = ZV_prod(P); /* d = abs(matdet(G1)); */ if (odd(signG[2])) togglesign_safe(&d); /* d = matdet(G1); */ if (n == 4) { /* solubility at 2, the only remaining bad prime */ v = det_minors(G1); if (Mod8(d) == 1 && witt(v, gen_2) == 1) return gen_2; } P = shallowconcat(mpodd(d)? mkvec2(NULL,gen_2): mkvec(NULL), P); /* build a binary quadratic form with given Witt invariants */ lP = lg(P); W = const_vecsmall(lP-1, 0); /* choose signature of Q (real invariant and sign of the discriminant) */ dQ = absi(d); if (signG[1] > signG[2]) togglesign_safe(&dQ); /* signQ = [2,0]; */ if (n == 4 && Mod4(dQ) != 1) dQ = shifti(dQ,2); if (n >= 5) dQ = shifti(dQ,3); /* p-adic invariants */ if (n == 4) { togglesign(gel(v,2)); togglesign(gel(v,4)); /* v = det_minors(-G1) */ for (i = 3; i < lP; i++) W[i] = witt(v, gel(P,i)) < 0; } else { long s = signe(dQ) == signe(d)? 1: -1; GEN t; if (odd((n-3)/2)) s = -s; t = s > 0? utoipos(8): utoineg(8); for (i = 3; i < lP; i++) W[i] = hilbertii(t, gel(P,i), gel(P,i)) > 0; } W[2] = Flv_sum(W, 2); /* for p = 2, use product formula */ /* Construction of the 2-class group of discriminant dQ until some product * of the generators gives the desired invariants. */ factdP = vecsplice(P, 1); lfactdP = lg(factdP); factdE = cgetg(lfactdP, t_VECSMALL); for (i = 1; i < lfactdP; i++) factdE[i] = Z_pval(dQ, gel(factdP,i)); factdE[1]++; /* factdP,factdE = factor(2|dQ|), P = factor(-2|dQ|)[,1] */ Q = quadclass2(dQ, factdP,factdE, P, W, n == 4); /* Build a form of dim=n+2 potentially unimodular */ G2 = shallowmatconcat(diagonal_shallow(mkvec2(G1,ZM_neg(Q)))); /* Minimization of G2 */ detG2 = mulii(d, ZM_det(Q)); /* factdP,factdE = factor(|det G2|) */ Min = qfminimize_fact(G2, factdP, NULL, detG2, 1); M2 = gel(Min,2); G2 = gel(Min,1); } /* |det(G2)| = 1, find a totally isotropic subspace for G2 */ solG2 = qflllgram_indefgoon(G2); /* G2 must have a subspace of solutions of dimension > codim */ dim = codim+1; while(gequal0(principal_minor(gel(solG2,1), dim))) dim ++; if (dim == codim+1) pari_err_IMPL("qfsolve, dim >= 10"); solG2 = vecslice(gel(solG2,2), 1, dim-1); if (!M2) solG1 = solG2; else { /* solution of G1 is simultaneously in solG2 and x[n+1] = x[n+2] = 0*/ GEN K; solG1 = QM_mul(M2,solG2); K = QM_ker(rowslice(solG1,n+1,n+2)); solG1 = QM_mul(rowslice(solG1,1,n), K); } if (!M1) sol = solG1; else { /* solution of G1 is simultaneously in solG2 and x[n] = 0 */ GEN K; sol = QM_mul(M1,solG1); K = QM_ker(rowslice(sol,n,n)); sol = QM_mul(rowslice(sol,1,n-1), K); } sol = Q_primpart(QM_mul(M, sol)); if (lg(sol) == 2) sol = gel(sol,1); return sol; } GEN qfsolve(GEN G) { pari_sp av = avma; return gerepilecopy(av, qfsolve_i(G)); } /* G is a symmetric 3x3 matrix, and sol a solution of sol~*G*sol=0. * Returns a parametrization of the solutions with the good invariants, * as a 3x3 matrix, where each line contains the coefficients of each of the 3 * quadratic forms. If fl!=0, the fl-th form is reduced. */ GEN qfparam(GEN G, GEN sol, long fl) { pari_sp av = avma; GEN U, G1, G2, a, b, c, d, e; long n, tx = typ(sol); if (typ(G) != t_MAT) pari_err_TYPE("qfsolve", G); if (!is_vec_t(tx)) pari_err_TYPE("qfsolve", G); if (tx == t_VEC) sol = shallowtrans(sol); n = lg(G)-1; if (n == 0) pari_err_DOMAIN("qfsolve", "dimension" , "=", gen_0, G); if (n != nbrows(G) || n != 3 || lg(sol) != 4) pari_err_DIM("qfsolve"); G = Q_primpart(G); RgM_check_ZM(G,"qfsolve"); check_symmetric(G); sol = Q_primpart(sol); RgV_check_ZV(sol,"qfsolve"); /* build U such that U[,3] = sol, and |det(U)| = 1 */ U = completebasis(sol,1); G1 = qf_ZM_apply(G,U); /* G1 has a 0 at the bottom right corner */ a = shifti(gcoeff(G1,1,2),1); b = shifti(negi(gcoeff(G1,1,3)),1); c = shifti(negi(gcoeff(G1,2,3)),1); d = gcoeff(G1,1,1); e = gcoeff(G1,2,2); G2 = mkmat3(mkcol3(b,gen_0,d), mkcol3(c,b,a), mkcol3(gen_0,c,e)); sol = ZM_mul(U,G2); if (fl) { GEN v = row(sol,fl); int fail; a = gel(v,1); b = gmul2n(gel(v,2),-1); c = gel(v,3); U = qflllgram_indef(mkmat22(a, b, b, c), 1, &fail); U = gel(U,2); a = gcoeff(U,1,1); b = gcoeff(U,1,2); c = gcoeff(U,2,1); d = gcoeff(U,2,2); U = mkmat3(mkcol3(sqri(a),mulii(a,c),sqri(c)), mkcol3(shifti(mulii(a,b),1), addii(mulii(a,d),mulii(b,c)), shifti(mulii(c,d),1)), mkcol3(sqri(b),mulii(b,d),sqri(d))); sol = ZM_mul(sol,U); } return gerepileupto(av, sol); } pari-2.17.2/src/basemath/factcyclo.c0000644000175000017500000016176414676526175015714 0ustar billbill/* Copyright (C) 2000, 2012 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* written by Takashi Fukuda * 2019.10.27 : Flx_factcyclo_gen, FpX_factcyclo_gen * 2019.10.28 : Flx_factcyclo_lift, FpX_factcyclo_lift * 2019.11.3 : Flx_factcyclo_newton, FpX_factcyclo_newton * 2019.11.12 : gausspol for prime * 2019.11.13 : gausspol for prime power * 2019.11.14 : ZpX_roots_nonsep with ZX_Zp_root * 2019.11.15 : test ZpX_roots_nonsep with polrootspadic * 2019.11.16 : accept variable number * 2019.11.17 : gen_ascent * 2019.11.20 : ZpX_roots_nonsep with FpX_roots * 2021.7.19 : Flx_factcyclo_newton_general * 2021.7.22 : Flx_conductor_lift */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_factcyclo #define GENERAL 1 #define NEWTON_POWER 2 #define NEWTON_GENERAL 4 #define NEWTON_GENERAL_NEW 8 #define ASCENT 16 #define Flx_polcyclo(n, p) ZX_to_Flx(polcyclo(n, 0), p) #define FpX_polcyclo(n, p) FpX_red(polcyclo(n, 0), p) /* 0 <= z[i] <= ULONG_MAX */ static GEN ZX_to_nx(GEN z) { long i, r = lg(z); GEN x = cgetg(r, t_VECSMALL); x[1] = ((ulong) z[1])&VARNBITS; for (i = 2; i < r; i++) x[i] = itou(gel(z, i)); return x; } static long QX_den_pval(GEN x, GEN p) { long i, vmax = 0, l = lg(x); for (i = 2; i < l; i++) { GEN z = gel(x, i); long v; if (typ(z)==t_FRAC && (v = Z_pval(gel(z, 2), p)) > vmax) vmax = v; } return vmax; } static long QXV_den_pval(GEN vT, GEN kT, GEN p) { long k, vmax = 0, l = lg(kT); for (k = 1; k < l; k++) { long v = QX_den_pval(gel(vT, kT[k]), p); if (v > vmax) vmax = v; } return vmax; } /* n=el^e, p^d=1 (mod n), d is in [1,el-1], phi(n)=d*f. * E[i] : 1 <= i <= n-1 * E[g^i*p^j mod n] = i+1 (0 <= i <= f-1, 0 <= j <= d-1) * We use E[i] (1 <= i <= d). Namely i < el. */ static GEN set_E(long pmodn, long n, long d, long f, long g) { long i, j; GEN E = const_vecsmall(n-1, 0); pari_sp av = avma; GEN C = Fl_powers(g, f-1, n); for (i = 1; i <= f; i++) { ulong x = C[i]; for (j = 1; j <= d; j++) { x = Fl_mul(x, pmodn, n); E[x] = i; } } return gc_const(av, E); } /* x1, x2 of the same degree; gcd(p1,p2) = 1, m = p1*p2, m2 = m >> 1*/ static GEN ZX_chinese_center(GEN x1, GEN p1, GEN x2, GEN p2, GEN m, GEN m2) { long i, l = lg(x1); GEN x = cgetg(l, t_POL); GEN y1, y2, q1, q2; (void)bezout(p1, p2, &q1, &q2); y1 = Fp_mul(p2, q2, m); y2 = Fp_mul(p1, q1, m); for (i = 2; i < l; i++) { GEN y = Fp_add(mulii(gel(x1, i), y1), mulii(gel(x2, i), y2), m); if (cmpii(y, m2) > 0) y = subii(y, m); gel(x, i) = y; } x[1] = x1[1]; return x; } /* find n_el primes el such that el=1 (mod n) and el does not divide d(T) */ static GEN list_el_n(ulong el0, ulong n, GEN d1, long n_el) { GEN v = cgetg(n_el + 1, t_VECSMALL); forprime_t T; long i; u_forprime_arith_init(&T, el0+n, ULONG_MAX, 1, n); for (i = 1; i <= n_el; i++) { ulong el; do el = u_forprime_next(&T); while (dvdiu(d1, el)); v[i] = el; } return v; } /* return min el s.t. 2^6310) second++; if (start>100) { start++; second++; } if (start>500) { start++; second++; } if (start>1000) { start++; second++; } *psec = second; return start; } static long FpX_degsub(GEN P, GEN Q, GEN p) { pari_sp av = avma; long d = degpol(FpX_sub(P, Q, p)); return gc_long(av, d); } /* n=odd prime power, F=Q(zeta_n), G=G(F/Q)=(Z/nZ)^*, H=

, K <--> H, * t_k=Tr_{F/K}(zeta_n^k), T=minimal pol. of t_1 over Q. * g is a given generator of G(K/Q). * There exists a unique G(x) in Q[x] s.t. t_g=G(t_1). * return G(x) mod el assuming that el does not divide d(T), in which case * T(x) is separable over F_el and so Vandermonde mod el is regular. */ static GEN gausspol_el(GEN H, ulong n, ulong d, ulong f, ulong g, ulong el) { ulong j, k, z_n = rootsof1_Fl(n, el); GEN vz_n, L = cgetg(1+f, t_VECSMALL), x = cgetg(1+f, t_VECSMALL), X; vz_n = Fl_powers(z_n, n-1, el)+1; for (k = 0; k < f; k++) { ulong gk = Fl_powu(g, k, n), t = 0; for (j = 1; j <= d; j++) t = Fl_add(t, vz_n[Fl_mul(H[j], gk, n)], el); L[1+k] = t; x[1+(k+f-1)%f] = t; } X = Flv_invVandermonde(L, 1, el); return Flv_to_Flx(Flm_Flc_mul(X, x, el), 0); } static GEN get_G(GEN H, GEN d0, GEN d1, GEN N, long k, ulong *pel, GEN *pM) { long n = N[1], d = N[2], f = N[3], g = N[4], i; GEN POL = cgetg(1+k, t_VEC), EL, G, M, x; pari_timer ti; if (DEBUGLEVEL >= 6) timer_start(&ti); EL = list_el_n(*pel, n, d1, k); for (i = 1; i <= k; i++) { ulong el = uel(EL,i); x = gausspol_el(H, n, d, f, g, el); gel(POL, i) = Flx_Fl_mul(x, umodiu(d0, el), el); } if (DEBUGLEVEL >= 6) timer_printf(&ti, "get_G : make data k=%ld",k); G = nxV_chinese_center(POL, EL, &M); if (DEBUGLEVEL >= 6) timer_printf(&ti, "get_G : nxV_chinese_center k=%ld",k); *pel = EL[k]; *pM = M; return G; } static long Q_size(GEN z) { if (typ(z)==t_INT) return lgefint(z) - 2; return maxss(lgefint(gel(z,1)), lgefint(gel(z,2))) - 2; } /* return max log_a(|x[i]|), a=2^(BITS_IN_LONG-1) */ static long ZX_size(GEN x) { long i, l = lg(x), max = 0; for (i = 2; i < l; i++) { long y = lgefint(gel(x,i)) - 2; if (y > max) max = y; } return max; } /* d0 is a multiple of (O_K:Z[t_1]). i.e. d0*T_k(x) is in Z[x]. * d1 has the same prime factors as d(T); d0 d1 = d(T)^2 */ static GEN get_d0_d1(GEN T, GEN P) { long i, l = lg(P); GEN x, y, dT = ZX_disc(T); x = y = dT; setsigne(dT, 1); for (i = 1; i < l; i++) if (odd(Z_lvalrem(dT, P[i], &dT))) { x = diviuexact(x, P[i]); y = muliu(y, P[i]); } return mkvec2(sqrti(x), sqrti(y)); /* x and y are square */ } static GEN gausspol(GEN T, GEN H, GEN N, ulong d, ulong f, ulong g) { long n = N[1], el0 = N[2]; GEN F, G1, M1, d0, d1, Data, d0d1 = get_d0_d1(T, mkvecsmall(el0)); ulong el, n_el, start, second; pari_timer ti; d0 = gel(d0d1,1); /* d0*F is in Z[X] */ d1 = gel(d0d1,2); /* d1 has same prime factors as disc(T) */ Data = mkvecsmall4(n, d, f, g); start = get_n_el(d0, &second); el = start_el_n(n); if (DEBUGLEVEL >= 6) timer_start(&ti); if (DEBUGLEVEL == 2) err_printf("gausspol:start=(%ld,%ld)\n",start,second); G1 = get_G(H, d0, d1, Data, start, &el, &M1); for (n_el=second; n_el; n_el++) { GEN m, G2, M2; G2 = get_G(H, d0, d1, Data, n_el, &el, &M2); if (FpX_degsub(G1, G2, M2) < 0) break; /* G1 = G2 (mod M2) */ if (DEBUGLEVEL == 2) err_printf("G1:%ld, G2:%ld\n",ZX_size(G1), ZX_size(G2)); if (DEBUGLEVEL >= 6) timer_start(&ti); m = mulii(M1, M2); G2 = ZX_chinese_center(G1, M1, G2, M2, m, shifti(m,-1)); if (DEBUGLEVEL >= 6) timer_printf(&ti, "ZX_chinese_center"); G1 = G2; M1 = m; } F = RgX_Rg_div(G1, d0); if (DEBUGLEVEL == 2) err_printf("G1:%ld, d0:%ld, M1:%ld, F:%ld\n", ZX_size(G1), Q_size(d0), Q_size(M1), ZX_size(F)); if (DEBUGLEVEL >= 6) timer_printf(&ti, "gausspol"); return F; } /* Data = [H, GH, i_t, d0d1, kT, [n, d, f, n_T, mitk]] * v_t_el[k]=t_k mod el, 1<= k <= n-1 */ static GEN mk_v_t_el(GEN vT, GEN Data, ulong el) { pari_sp av = avma; GEN H = gel(Data, 1), GH = gel(Data,2), i_t = gel(Data, 3), N=gel(Data, 6); ulong n = N[1], d = N[2], mitk = N[5], f = N[3], i, k; ulong z_n = rootsof1_Fl(n, el); GEN vz_n = Fl_powers(z_n, n-1, el)+1; GEN v_t_el = const_vecsmall(n-1, 0); for (k = 1; k <= mitk; k++) { if (k > 1 && !isintzero(gel(vT, k))) continue; /* k=1 is always handled */ for (i=1; i<=f; i++) { ulong j, t = 0, x = Fl_mul(k, GH[i], n); long y = i_t[x]; /* x!=0, y!=0 */ if (v_t_el[y]) continue; for (j = 1; j <= d; j++) t = Fl_add(t, vz_n[Fl_mul(x, H[j], n)], el); v_t_el[y] = t; } } return gerepileuptoleaf(av, v_t_el); } /* G=[[G_1,...,G_d],M,el] * Data = [H, GH, i_t, d0d1, kT, [n, d, f, n_T, mitk]] */ static GEN get_vG(GEN vT, GEN Data, long n_el, ulong *pel, GEN *pM) { GEN GH = gel(Data, 2), i_t = gel(Data, 3); GEN d0 = gmael(Data, 4, 1), d1 = gmael(Data, 4, 2); GEN kT = gel(Data, 5), N = gel(Data, 6); long n = N[1], f = N[3], n_T = N[4], mitk = N[5]; GEN G = const_vec(mitk, gen_0), vPOL = cgetg(1+mitk, t_VEC); GEN EL, M, X, v_t_el; GEN L = cgetg(1+f, t_VECSMALL), x = cgetg(1+f, t_VECSMALL); long i, j, k; for (k=1; k<=mitk; k++) gel(vPOL, k) = cgetg(1+n_el, t_VEC); EL = list_el_n(*pel, n, d1, n_el); for (i=1; i<=n_el; i++) { ulong el = uel(EL,i), d0model = umodiu(d0, el); v_t_el = mk_v_t_el(vT, Data, el); for (j = 1; j <= f; j++) L[j] = v_t_el[i_t[GH[j]]]; X = Flv_invVandermonde(L, 1, el); for (k = 1; k <= n_T; k++) { GEN y; long itk = kT[k]; if (!isintzero(gel(vT, itk))) continue; for (j = 1; j <= f; j++) x[j] = v_t_el[i_t[Fl_mul(itk, GH[j], n)]]; y = Flv_to_Flx(Flm_Flc_mul(X, x, el), 0); gmael(vPOL, itk, i) = Flx_Fl_mul(y, d0model, el); } } for (k = 1; k <= n_T; k++) { long itk = kT[k]; if (!isintzero(gel(vT, itk))) continue; gel(G, itk) = nxV_chinese_center(gel(vPOL, itk), EL, &M); } *pel = EL[n_el]; *pM = M; return G; } /* F=Q(zeta_n), H=

in (Z/nZ)^*, K<-->H, t_k=Tr_{F/K}(zeta_n^k). * i_t[i]=k ==> iH=kH, i.e. t_i=t_k. We use t_k instead of t_i: * the number of k << the number of i. */ static GEN get_i_t(long n, long p) { long a; GEN v_t = const_vecsmall(n-1, 0); GEN i_t = cgetg(n, t_VECSMALL); /* access i_t[a] with 1 <= a <= n-1 */ for (a = 1; a < n; a++) { long b; while (a < n && v_t[a]) a++; if (a==n) break; b = a; do { v_t[b] = 1; i_t[b] = a; b = Fl_mul(b, p, n); } while (b != a); } return i_t; } /* get T_k(x) 1<= k <= d. d0*T_k(x) is in Z[x]. * T_0(x)=T_n(x)=f. * Data = [H, GH, i_t, d0d1, kT, [n, d, f, n_T, mitk]] */ static GEN get_vT(GEN Data, int NEW) { pari_sp av = avma; GEN d0 = gmael(Data, 4, 1), kT = gel(Data, 5), N = gel(Data, 6); ulong k, n = N[1], n_T = N[4], mitk = N[5]; GEN G1, M1, vT = const_vec(mitk, gen_0); /* vT[k]!=NULL ==> vT[k]=T_k */ ulong n_k = 0, el, n_el, start, second; pari_timer ti; if (DEBUGLEVEL >= 6) timer_start(&ti); if (!NEW) { gel(vT, 1) = pol_x(0); n_k++; } start = get_n_el(d0, &second); el = start_el_n(n); if (DEBUGLEVEL == 2) err_printf("get_vT: start=(%ld,%ld)\n",start,second); G1 = get_vG(vT, Data, start, &el, &M1); for (n_el = second;; n_el++) { GEN G2, M2, m, m2; G2 = get_vG(vT, Data, n_el, &el, &M2); m = mulii(M1, M2); m2 = shifti(m,-1); for (k = 1; k <= n_T; k++) { long j = kT[k]; if (!isintzero(gel(vT,j))) continue; if (FpX_degsub(gel(G1,j), gel(G2,j), M2) < 0) /* G1=G2 (mod M2) */ { gel(vT,j) = RgX_Rg_div(gel(G1,j), d0); n_k++; if (DEBUGLEVEL == 2) err_printf("G1:%ld, d0:%ld, M1:%ld, vT[%ld]:%ld words\n", ZX_size(gel(G1,j)), Q_size(d0), Q_size(M1), j, ZX_size(gel(vT,j))); } else { if (DEBUGLEVEL == 2) err_printf("G1:%ld, G2:%ld\n", ZX_size(gel(G1,j)),ZX_size(gel(G2,j))); gel(G1, j) = ZX_chinese_center(gel(G1,j),M1, gel(G2,j),M2, m,m2); } } if (n_k == n_T) break; M1 = m; } if (DEBUGLEVEL >= 6) timer_printf(&ti, "get_vT"); return gerepilecopy(av, vT); } /* return sorted kT={i_t[k] | 1<=k<=d} * {T_k(x) | k in kT} are all the different T_k(x) (1<=k<=d) */ static GEN get_kT(GEN i_t, long d) { return vecsmall_uniq(vecsmall_shorten(i_t, d)); } static GEN get_kT_all(GEN GH, GEN i_t, long n, long d, long m) { long i, j, k = 0; GEN x = const_vecsmall(d*m, 0); for (i = 1; i <= m; i++) for (j = 1; j <= d; j++) x[++k] = i_t[Fl_mul(GH[i], j, n)]; return vecsmall_uniq(x); } static GEN kT_from_kt_new(GEN gGH, GEN kt, GEN i_t, long n) { GEN EL = gel(gGH, 1); long i, k = 0, lEL = lg(EL), lkt = lg(kt); GEN x = cgetg(lEL+lkt, t_VECSMALL); for (i = 1; i < lEL; i++) x[++k] = i_t[EL[i]]; for (i = 2; i < lkt; i++) if (n%kt[i]==0) x[++k] = kt[i]; setlg(x, k+1); return vecsmall_uniq(x); } static GEN get_kTdiv(GEN kT, long n) { long i, k = 0, l = lg(kT); GEN div = cgetg(l, t_VECSMALL); for (i = 1; i < l; i++) if (n%kT[i]==0) div[++k] = kT[i]; setlg(div, k+1); return div; } /* T is separable over Zp but not separable over Fp. * receive all roots mod p^s and return all roots mod p^(s+1) */ static GEN ZpX_roots_nonsep(GEN T, GEN R0, GEN p, GEN ps, GEN ps1) { long i, j, n = 0, lr = lg(R0); GEN v = cgetg(lr, t_VEC), R; for (i = 1; i < lr; i++) { GEN z, f = ZX_unscale_div(ZX_translate(T, gel(R0, i)), ps); (void)ZX_pvalrem(f, p, &f); gel(v, i) = z = FpX_roots(f, p); n += lg(z)-1; } R = cgetg(n+1, t_VEC); n = 0; for (i = 1; i < lr; i++) { GEN z = gel(v, i); long lz = lg(z); for (j=1; j= 6) timer_start(&ti); v = FpX_roots(T, p); /* FpX_roots returns sorted roots */ if (DEBUGLEVEL >= 6) timer_printf(&ti, "FpX_roots, deg=%ld", degpol(T)); ps = NULL; ps1 = p; for (s = 1; lg(v) != f+1; s++) { ps = ps1; ps1 = mulii(ps1, p); /* p^s, p^(s+1) */ v = ZpX_roots_nonsep(T, v, p, ps, ps1); if (gc_needed(av, 1)) gerepileall(av, 3, &v, &ps, &ps1); } *ptrs = s; return v; } /* x : roots of T in Zp. r < n. * receive vec of x mod p^r and return vec of x mod p^n. * under the assumtion lg(v)-1==degpol(T), x is uniquely determined by * x mod p^r. Namely, x mod p^n is unique. */ static GEN ZX_Zp_liftroots(GEN T, GEN v, GEN p, long r, long n) { long i, l = lg(v); GEN R = cgetg(l, t_VEC); GEN pr = powiu(p, r), pn = powiu(p, n); pari_timer ti; if (DEBUGLEVEL >= 6) timer_start(&ti); for (i=1; i= 6) timer_printf(&ti, "ZX_Zp_liftroots"); return R; } static GEN set_R(GEN T, GEN F, GEN Rs, GEN p, long nf, long r, long s, long u) { long i; GEN x, pr = powiu(p, r), prs = powiu(p, r+s), R = cgetg(1+nf, t_VEC), Rrs; Rrs = r ? ZX_Zp_liftroots(T, Rs, p, s, r+s) : Rs; x = gel(Rrs, 1); for (i = 1; i <= nf; i++) { x = FpX_eval(F, x, prs); if (r) x = gel(Rrs, ZV_search(Rs, diviiexact(x, pr))); gel(R, i) = x; /* R[i]=t_1^(g^i), t_1=Rrs[1], mod p^(r+s) */ } if (r+s < u) R = ZX_Zp_liftroots(T, R, p, r+s, u); else if (r+s > u) R = FpV_red(R, powiu(p, u)); return R; /* mod p^u, accuracy for pol_newton */ } /* Preparation for factoring polcyclo(el^e) mod p * f_0(x) : irred factor of polcyclo(el^e0) mod p * f_1(x)=f_0(x^(el^e1)) : irred factor of polcyclo(el^e) mod p * * p^d0 = 1 (mod el^e0), p^d = 1 (mod el^e) * * case el=2, 2^s || (p-1), s>=2 * d=1 (1 <= e <= s), d=2^(e-s) (s < e) * e0=e, e1=0 if e <= s * e0=s, e1=e-s if s < e * d0=1 * * case el=2, 2^s || (p+1), s>=2 * d=1 (e == 1), d=2 (2 <= e <= s), d=2^(e-s) (s < e) * e0=e, e1=0 if e <= s+1 * e0=s+1, e1=e-s-1 if s+1 < e * d0=1 if e==1, d0=2 if e>1 * * case el>2, el^s || (p^d0-1) * d=d0 (1 <= e <= s), d=d0*el^(e-s) (s < e) * e0=e, e1=0 if e <= s * e0=s, e1=e-s if s < e * d0 is min d s.t. p^d=1 (mod el) * * We do not need d. So d is not returned. */ static GEN set_e0_e1(ulong el, ulong e, GEN p) { ulong s, d0, e0, e1, f0, n, phin, g, up = itou_or_0(p); if (el == 2) { ulong pmod4 = up ? up&3 : mod4(p); if (pmod4 == 3) /* p+1 = 0 (mod 4) */ { s = up ? vals(up+1) : vali(addiu(p, 1)); if (e <= s+1) { e0 = e; e1 = 0;} else { e0 = s+1; e1= e-s-1;} d0 = e == 1? 1: 2; } else /* p-1 = 0 (mod 4) */ { s = up ? vals(up-1) : vali(subiu(p, 1)); if (e <= s) { e0 = e; e1 = 0; } else { e0 = s; e1 = e-s; } d0 = 1; } phin = 1L<<(e0-1); } else /* el is odd */ { ulong pmodel = up ? up%el : umodiu(p, el); d0 = Fl_order(pmodel, el-1, el); s = Z_lval(subiu(powiu(p, d0), 1), el); if (e <= s) { e0 = e; e1 = 0; } else { e0 = s; e1 = e-s; } phin = (el-1)*upowuu(el, e0-1); } n = upowuu(el, e0); f0 = phin/d0; g = (el==2) ? 1 : pgener_Zl(el); return mkvecsmalln(7, n, e0, e1, phin, g, d0, f0); } /* return 1 if newton is fast, return 0 if gen is fast */ static int use_newton(long d, long f) { if (2*d <= f) return 0; else if (f <= d) return 1; else if (d <= 50) return 0; else if (f <= 60) return 1; else if (d <= 90) return 0; else if (f <= 150) return 1; else if (d <= 150) return 0; else if (f <= 200) return 1; else if (200*d <= f*f) return 0; else return 1; } /* return 1 if newton_general is fast, return 0 otherwise. Assume f > 40 */ static int use_newton_general(long d, long f, long maxdeg) { if (maxdeg < 20) return 0; else if (f <= 50) return 1; else if (maxdeg < 30) return 0; else if (f <= 60) return 1; else if (maxdeg < 40) return 0; else if (f <= 70) return 1; else if (maxdeg < 50) return 0; else if (f <= 80) return 1; else if (d < 200) return 0; else if (f <= 100) return 1; else if (d < 300) return 0; else if (f <= 120) return 1; else if (6*maxdeg < f*f) return 0; else return 1; } static int use_general(long d, long maxdeg) { if (d <= 50) return 1; else if (maxdeg <= 3*d) return 0; else if (d <= 200) return 1; else if (maxdeg <= 10*d) return 0; else if (d <= 500) return 1; else if (maxdeg <= 20*d) return 0; else if (d <= 1000) return 1; else return 0; } static void update_dfm(long *pd, long *pf, long *pm, long di, long fi) { long c = ugcd(*pd,di), d1 = *pd * di, f1 = *pf * fi; *pd = d1 / c; *pf = c * f1; *pm += d1 * d1 * f1; if (DEBUGLEVEL == 4) err_printf("(%ld,%ld), ",d1,f1); } /* assume ord(p mod f) > 1 */ static ulong set_action(GEN fn, GEN p, long d, long f) { GEN EL = gel(fn, 1), E = gel(fn, 2); long i, d0, f0, m0, m1, maxdeg, max, l = lg(EL); ulong action = 0, up = itou_or_0(p); GEN D = cgetg(l, t_VECSMALL), F = cgetg(l, t_VECSMALL); d += 10*(lgefint(p)-3); if (l == 2) { /* n is a prime power */ action |= (EL[1]==2 || !use_newton(d, f))? GENERAL: NEWTON_POWER; return action; } if (f <= 2) action |= NEWTON_GENERAL; else if (d <= 10) action |= GENERAL; else if (f <= 10) action |= NEWTON_GENERAL; else if (d <= 20) action |= GENERAL; else if (f <= 20) action |= NEWTON_GENERAL_NEW; else if (d <= 30) action |= GENERAL; else if (f <= 30) action |= NEWTON_GENERAL_NEW; else if (d <= 40) action |= GENERAL; else if (f <= 40) action |= NEWTON_GENERAL_NEW; if (action) return action; /* can assume that d > 40 and f > 40 */ maxdeg = max = 1; for (i = 1; i < l; i++) { long x, el = EL[i], e = E[i]; long q = upowuu(el, e-1), ni = q * el, phini = ni - q; long di = Fl_order(umodiu(p, ni), phini, ni); D[i] = di; F[i] = phini / di; x = ugcd(max, di); max = max * (di / x); /* = lcm(d1,..di) */ if (x > 1) maxdeg = max*x; if (DEBUGLEVEL == 4) err_printf("(%ld,%ld), ", D[i], F[i]); } if (maxdeg == 1) return action; if (up != 2) { if (use_newton_general(d, f, maxdeg)) { /* does not decompose n */ action |= (20 < d)? NEWTON_GENERAL_NEW: NEWTON_GENERAL; return action; } if (use_general(d, maxdeg)) action |= GENERAL; } if (l < 4) return action; /* n has two factors */ d0 = f0 = 1; m0 = 0; for (i = 1; i < l; i++) update_dfm(&d0, &f0, &m0, D[i], F[i]); if (DEBUGLEVEL == 4) err_printf("(d0,f0)=(%ld,%ld)\n",d0,f0); d0 = f0 = 1; m1 = 0; for (i = l-1; i >= 1; i--) update_dfm(&d0, &f0, &m1, D[i], D[i]); if (DEBUGLEVEL == 4) err_printf("(d0,f0)=(%ld,%ld)\n",d0,f0); if (DEBUGLEVEL == 4) err_printf("(m0,m1)=(%lu,%lu) %ld\n",m0,m1,m0<=m1); if (m0 <= m1) action |= ASCENT; return action; } static GEN FpX_Newton_perm(long d, GEN R, GEN v, GEN pu, GEN p) { GEN S = cgetg(d+2, t_VEC); long k; gel(S,1) = utoi(d); for (k = 1; k <= d; k++) gel(S, k+1) = gel(R, v[k]); return FpX_red(FpX_fromNewton(RgV_to_RgX(S, 0), pu), p); } static GEN Flx_Newton_perm(long d, GEN R, GEN v, ulong pu, ulong p) { GEN S = cgetg(d+2, t_VEC); long k; S[1] = d; for (k = 1; k <= d; k++) gel(S, k+1) = gel(R, v[k]); return Flx_red(Flx_fromNewton(Flv_to_Flx(S, 0), pu), p); } /* Data = [H, GH, i_t, d0, kT, [n, d, f, n_T, mitk]] N2 = [p, pr, pu, pru] */ static GEN FpX_pol_newton_general(GEN Data, GEN N2, GEN vT, GEN x) { GEN i_t = gel(Data, 3), kT = gel(Data, 5), N = gel(Data, 6); long k, d = N[2], n_T = N[4], mitk = N[5]; GEN p = gel(N2,1), pr = gel(N2,2), pu = gel(N2,3), pru = gel(N2,4); GEN R = cgetg(1+mitk, t_VEC); for (k = 1; k <= n_T; k++) gel(R, kT[k]) = diviiexact(FpX_eval(gel(vT, kT[k]), x, pru), pr); return FpX_Newton_perm(d, R, i_t, pu, p); } /* n is any integer prime to p, but must be equal to the conductor * of the splitting field of p in Q(zeta_n). * GH=G/H={g_1, ... ,g_f} * Data = [GHgen, GH, fn, p, [n, d, f, m]] */ static GEN FpX_factcyclo_newton_general(GEN Data) { GEN GH = gel(Data, 2), fn = gel(Data, 3), p = gel(Data, 4); long n = mael(Data, 5, 1), d = mael(Data, 5, 2), f = mael(Data, 5, 3); long m = mael(Data, 5, 4), pmodn = umodiu(p, n); long i, k, n_T, mitk, r, s = 0, u = 1; GEN vT, kT, H, i_t, T, d0d1, Data2, Data3, R, Rs, pr, pu, pru; pari_timer ti; if (m != 1) m = f; for (pu = p; cmpiu(pu,d) <= 0; u++) pu = mulii(pu, p); /* d */ i_t = get_i_t(n, pmodn); /* i_t[1+i]=k ==> t_i=t_k */ kT = get_kT(i_t, d); n_T = lg(kT)-1; mitk = kT[n_T]; if (DEBUGLEVEL == 2) err_printf("kT=%Ps %ld elements\n",kT,n_T); if (DEBUGLEVEL >= 6) timer_start(&ti); T = galoissubcyclo(utoi(n), utoi(pmodn), 0, 0); if (DEBUGLEVEL >= 6) timer_printf(&ti, "galoissubcyclo"); d0d1 = get_d0_d1(T, gel(fn,1)); /* d0*T_k(x) is in Z[x] */ Data2 = mkvecn(6, H, GH, i_t, d0d1, kT, mkvecsmalln(5, n, d, f, n_T, mitk)); vT = get_vT(Data2, 0); if (DEBUGLEVEL == 4) err_printf("vT=%Ps\n",vT); r = QXV_den_pval(vT, kT, p); Rs = ZpX_roots_all(T, p, f, &s); if (DEBUGLEVEL >= 2) err_printf("(u,s,r)=(%ld,%ld,%ld)\n",u,s,r); if (r+u < s) pari_err_BUG("FpX_factcyclo_newton_general (T is not separable mod p^(r+u))"); /* R and vT are mod p^(r+u) */ R = (r+u==s) ? Rs : ZX_Zp_liftroots(T, Rs, p, s, r+u); pr = powiu(p, r); pru = powiu(p, r+u); /* Usually, r=0, s=1, pr=1, pru=p */ for (k = 1; k<=n_T; k++) { long itk = kT[k]; GEN z = r? RgX_Rg_mul(gel(vT, itk), pr): gel(vT, itk); gel(vT, itk) = RgX_to_FpX(z, pru); } Data3 = mkvec4(p, pr, pu, pru); if (DEBUGLEVEL >= 6) timer_start(&ti); for (i=1; i<=m; i++) gel(R,i) = FpX_pol_newton_general(Data2, Data3, vT, gel(R,i)); if (DEBUGLEVEL >= 6) timer_printf(&ti, "FpX_pol_newton_general"); return R; } /* Data = [vT, gGH, Rs, Rrs, i_t, kt, p, pu, pr, prs, [n, r, s, n_t,mitk], div] */ static void Fp_next_gen3(long x, long i, GEN v_t_p, GEN t, GEN Data) { GEN vT = gel(Data, 1), gGH = gel(Data, 2), Rs = gel(Data, 3); GEN Rrs = gel(Data, 4), i_t = gel(Data, 5); GEN pu = gel(Data, 8), pr = gel(Data, 9), prs = gel(Data, 10); GEN EL = gel(gGH, 1), E = gel(gGH, 2), div = gel(Data, 12); long n = mael(Data, 11, 1), r = mael(Data, 11, 2), mitk = mael(Data, 11, 5); long j, k, l = lg(EL), ld = lg(div); if (i >= l) return; for (j = 0; j < E[i]; j++) { if (j > 0) { long itx = i_t[x]; t = FpX_eval(gel(vT, i_t[EL[i]]), t, prs); /* mod p^(r+s) */ if (r) t = gel(Rrs, ZV_search(Rs, diviiexact(t, pr))); /* mod p^(r+s) */ if (itx <= mitk) gel(v_t_p, itx) = Fp_red(t, pu); /* mod p^u */ for (k = 1; k mitk || !isintzero(gel(v_t_p, ity))) continue; v = FpX_eval(gel(vT, i_t[div[k]]), t, prs); /* mod p^(r+s) */ if (r) v = diviiexact(v, pr); /* mod p^s */ gel(v_t_p, ity) = Fp_red(v, pu); } } Fp_next_gen3(x, i+1, v_t_p, t, Data); x = Fl_mul(x, EL[i], n); } } /* Data = [vT, gGH, Rs, Rrs, i_t, kt, p, pu, pr, prs, [n, r, s, n_t, mitk], div] */ static GEN Fp_mk_v_t_p3(GEN Data, long i) { /* v_t_p[k] != gen_0 => v_t_p[k] = t_k mod p^u */ GEN Rs = gel(Data, 3), Rrs = gel(Data, 4); GEN pu = gel(Data, 8), pr = gel(Data, 9), prs = gel(Data, 10); GEN vT = gel(Data, 1), i_t = gel(Data, 5), div = gel(Data, 12); long k, r = mael(Data, 11, 2), mitk = mael(Data, 11, 5), ld = lg(div); GEN v_t_p = const_vec(mitk, gen_0); gel(v_t_p, 1) = Fp_red(gel(Rs, i), pu); /* mod p^u, guaranteed u<=s */ Fp_next_gen3(1, 1, v_t_p, gel(Rrs, i), Data); for (k = 1; k= l) return; for (j = 0; j < E[i]; j++) { if (j > 0) { long itx = i_t[x]; t = Flx_eval(gel(vT, i_t[EL[i]]), t, prs); /* mod p^(r+s) */ if (r) t = Rrs[zv_search(Rs, t/pr)]; /* mod p^(r+s) */ if (itx <= mitk) v_t_p[itx] = t%pu; /* mod p^u */ for (k = 1; k < ld; k++) { ulong y = Fl_mul(x, div[k], n), v; long ity = i_t[y]; if (ity > mitk || v_t_p[ity]) continue; v = Flx_eval(gel(vT, i_t[div[k]]), t, prs); /* mod p^(r+s) */ if (r) v /= pr; /* mod p^s */ v_t_p[ity] = v%pu; } } Fl_next_gen3(x, i+1, v_t_p, t, Data); x = Fl_mul(x, EL[i], n); } } /* Data = [vT, gGH, Rs, Rrs, i_t, kt, p, pu, pr, prs, [n, r, s, n_t, mitk], div] */ static GEN Fl_mk_v_t_p3(GEN Data, long i) { /* v_t_p[k] != 0 => v_t_p[k] = t_k mod p^u */ GEN Rs = gel(Data, 3), Rrs = gel(Data, 4); ulong pu = mael(Data, 8, 2), pr = mael(Data, 9, 2), prs = mael(Data, 10, 2); GEN vT = gel(Data, 1), i_t = gel(Data, 5), div = gel(Data, 12); long k, r = mael(Data, 11, 2), mitk = mael(Data, 11, 5), ld = lg(div); GEN v_t_p = const_vecsmall(mitk, 0); v_t_p[1] = Rs[i] % pu; /* mod p^u, guaranteed u<=s */ Fl_next_gen3(1, 1, v_t_p, Rrs[i], Data); for (k = 1; k < ld; k++) { ulong itk = i_t[div[k]], x = Flx_eval(gel(vT, itk), Rrs[i], prs); if (r) x /= pr; /* mod p^s */ v_t_p[itk] = x % pu; } return v_t_p; } /* Data = [GHgen, GH, fn, p, [n, d, f, m]] */ static GEN newton_general_new_pre3(GEN Data) { GEN gGH = gel(Data, 1), GH = gel(Data, 2), fn = gel(Data, 3); GEN p = gel(Data, 4); long n = mael(Data, 5, 1), d = mael(Data, 5, 2), f = mael(Data, 5, 3); long pmodn = umodiu(p, n); long k, n_t, n_T, mitk, miTk, r, s = 0, u = 1; GEN vT, kt, kT, H, i_t, T, d0d1, Data2, Rs, Rrs, kTdiv; GEN pr, pu, prs; pari_timer ti; for (pu = p; cmpiu(pu,d)<=0; u++) pu = mulii(pu, p); /* d */ i_t = get_i_t(n, pmodn); /* i_t[1+i]=k ==> t_i=t_k */ kt = get_kT_all(GH, i_t, n, d, 1); n_t = lg(kt)-1; mitk = kt[n_t]; kT = kT_from_kt_new(gGH, kt, i_t, n); n_T = lg(kT)-1; miTk = kT[n_T]; kTdiv = get_kTdiv(kT, n); if (DEBUGLEVEL == 2) err_printf("kt=%Ps %ld elements\nkT=%Ps %ld elements\n",kt,n_t,kT,n_T); if (DEBUGLEVEL == 2) err_printf("kTdiv=%Ps\n",kTdiv); if (DEBUGLEVEL >= 6) timer_start(&ti); T = galoissubcyclo(utoi(n), utoi(pmodn), 0, 0); if (DEBUGLEVEL >= 6) timer_printf(&ti, "galoissubcyclo"); d0d1 = get_d0_d1(T, gel(fn,1)); /* d0*T_k(x) is in Z[x] */ Data2 = mkvecn(6, H, GH, i_t, d0d1, kT, mkvecsmalln(5, n, d, f, n_T, miTk)); vT = get_vT(Data2, 1); if (DEBUGLEVEL == 4) err_printf("vT=%Ps\n",vT); r = QXV_den_pval(vT, kT, p); Rs = ZpX_roots_all(T, p, f, &s); if (DEBUGLEVEL >= 2) err_printf("(u,s,r)=(%ld,%ld,%ld)\n",u,s,r); if (s < u) { Rs = ZV_sort_shallow(ZX_Zp_liftroots(T, Rs, p, s, u)); s = u; } /* Rs : mod p^s, Rrs : mod p^(r+s), vT : mod p^(r+s) */ Rrs = r ? ZX_Zp_liftroots(T, Rs, p, s, r+s) : Rs; pr = powiu(p, r); prs = powiu(p, r+s); /* Usually, r=0, s=1, pr=1, pru=p */ if (lgefint(prs)>3) /* ULONG_MAX < p^(r+s), usually occur */ { for (k = 1; k <= n_T; k++) { long itk = kT[k]; GEN z = r? RgX_Rg_mul(gel(vT, itk), pr): gel(vT, itk); gel(vT, itk) = RgX_to_FpX(z, prs); } } else /* p^(r+s) < ULONG_MAX, frequently occur */ { ulong upr = itou(pr), uprs = itou(prs); for (k = 1; k <= n_T; k++) { long itk = kT[k]; GEN z = r? RgX_muls(gel(vT, itk), upr): gel(vT, itk); gel(vT, itk) = RgX_to_Flx(z, uprs); } Rs = ZV_to_nv(Rs); Rrs = ZV_to_nv(Rrs); } return mkvecn(12, vT, gGH, Rs, Rrs, i_t, kt, p, pu, pr, prs, mkvecsmalln(6, n, r, s, n_t, mitk, d), kTdiv); } /* Data=[vT, gGH, Rs, Rrs, i_t, kt, p, pu, pr, prs, * [n, r, s, n_t, mitk, d], div] */ static GEN FpX_pol_newton_general_new3(GEN Data, long k) { GEN i_t = gel(Data, 5), p = gel(Data, 7), pu = gel(Data, 8); long d = mael(Data, 11, 6); GEN v_t_p = Fp_mk_v_t_p3(Data, k); if (DEBUGLEVEL == 3) err_printf("v_t_p=%Ps\n",v_t_p); return FpX_Newton_perm(d, v_t_p, i_t, pu, p); } /* Data = [GHgen, GH, fn, p, [n, d, f, m]] */ static GEN FpX_factcyclo_newton_general_new3(GEN Data) { long i, f = mael(Data, 5, 3), m = mael(Data, 5, 4); GEN Data2, pols; pari_timer ti; if (m != 1) m = f; pols = cgetg(1+m, t_VEC); Data2 = newton_general_new_pre3(Data); /* Data2 = [vT, gGH, Rs, Rrs, i_t, kt, p, pu, pr, prs, [n, r, s, n_t, mitk, d], div] */ if (DEBUGLEVEL >= 6) timer_start(&ti); for (i = 1; i <= m; i++) gel(pols, i) = FpX_pol_newton_general_new3(Data2, i); if (DEBUGLEVEL >= 6) timer_printf(&ti, "FpX_pol_newton_general_new3"); return pols; } /* return normalized z(-x) */ static GEN FpX_1st_lift_2(GEN z, GEN p) { long i, r = lg(z); GEN x = cgetg(r, t_POL); x[1] = evalsigne(1) | evalvarn(0); if (odd(r)) for (i = 2; i < r; i++) gel(x,i) = odd(i)? Fp_neg(gel(z,i), p): gel(z,i); else for (i = 2; i < r; i++) gel(x,i) = odd(i)? gel(z,i): Fp_neg(gel(z,i), p); return x; } static GEN FpX_1st_lift(GEN z, GEN p, ulong e, ulong el, GEN vP) { GEN z2, z3, P = gel(vP, e); if (!gel(vP, e)) P = gel(vP, e) = FpX_polcyclo(e, p); z2 = RgX_inflate(z, el); z3 = FpX_normalize(FpX_gcd(P, z2, p), p); return FpX_div(z2, z3, p); } static GEN FpX_lift(GEN z, GEN p, ulong e, ulong el, ulong r, ulong s, GEN vP) { if (s == 0) { z = (el==2) ? FpX_1st_lift_2(z, p) : FpX_1st_lift(z, p, e, el, vP); if (r >= 2) z = RgX_inflate(z, upowuu(el, r-1)); } else z = RgX_inflate(z, upowuu(el, r-s)); return z; } /* e is the conductor of the splitting field of p in Q(zeta_n) */ static GEN FpX_conductor_lift(GEN z, GEN p, GEN fn, ulong e, GEN vP) { GEN EL = gel(fn, 1), En = gel(fn, 2); long i, r = lg(EL), new_e = e; for (i = 1; i < r; i++) { long el = EL[i], en = En[i], ee = u_lval(e, el); if (ee < en) { z = FpX_lift(z, p, new_e, el, en, ee, vP); new_e *= upowuu(el, en-ee); } } return z; } /* R0 is mod p^u, d < p^u */ static GEN FpX_pol_newton(long j, GEN R0, GEN E, GEN D3, long d, long f, GEN p) { long i, u = D3[3]; GEN R = cgetg(1+f, t_VEC); for (i = 1; i <= f; i++) gel(R, i) = gel(R0, 1+(i+j)%f); return FpX_Newton_perm(d, R, E, powiu(p, u), p); } /* Data = [T, F, Rs, [d, nf, g, r, s, u]], nf>1 */ static GEN FpX_factcyclo_newton_pre(GEN Data, GEN N, GEN p, ulong m) { GEN T = gel(Data, 1), F = gel(Data, 2), Rs = gel(Data, 3), D4 = gel(Data, 4); long d = D4[1], nf = D4[2], g = D4[3], r = D4[4], s = D4[5], u = D4[6]; GEN pols, E, R, Data3; ulong i, n = N[1], pmodn = umodiu(p, n); pari_timer ti; if (m!=1) m = nf; pols = cgetg(1+m, t_VEC); E = set_E(pmodn, n, d, nf, g); R = set_R(T, F, Rs, p, nf, r, s, u); Data3 = mkvecsmall3(r, s, u); if (DEBUGLEVEL >= 6) timer_start(&ti); for (i = 1; i <= m; i++) gel(pols, i) = FpX_pol_newton(i, R,E,Data3, d,nf,p); if (DEBUGLEVEL >= 6) timer_printf(&ti, "FpX_pol_newton"); return pols; } /* gcd(n1,n2)=1, e = gcd(d1,d2). * phi(n1) = d1*nf1, phi(n2) = d2*nf2. * d = lcm(d1,d2) = d1*d2/e, nf = phi(n1)*phi(n2)/d = nf1*nf2*e. */ static GEN FpX_factcyclo_lift(long n1, GEN v1, long n2, GEN v2, GEN p, long m) { pari_sp av = avma; long d1 = degpol(gel(v1, 1)), lv1 = lg(v1), nf1 = eulerphiu(n1)/d1; long d2 = degpol(gel(v2, 1)), lv2 = lg(v2), nf2 = eulerphiu(n2)/d2; long e = ugcd(d1, d2), nf = nf1*nf2*e, need_factor = (e!=1); long i, j, k = 0; GEN z = NULL, v; pari_timer ti; if (DEBUGLEVEL >= 6) timer_start(&ti); if (m != 1) m = nf; v = cgetg(1+m, t_VEC); if (m == 1) { GEN x1 = gel(v1, 1), x2 = gel(v2, 1); z = FpX_gcd(RgX_inflate(x1, n2), RgX_inflate(x2, n1), p); z = FpX_normalize(z, p); /* FpX_gcd sometimes returns non-monic */ gel(v, 1) = (!need_factor)? z : gmael(FpX_factor(z, p), 1, 1); } else { for (i = 1; i < lv1; i++) for (j = 1; j < lv2; j++) { GEN x1 = gel(v1, i), x2 = gel(v2, j); z = FpX_gcd(RgX_inflate(x1, n2), RgX_inflate(x2, n1), p); z = FpX_normalize(z, p); /* needed */ if (!need_factor) gel(v, ++k) = z; else { GEN z1 = gel(FpX_factor(z, p), 1); long i, l = lg(z1); for (i = 1; i < l; i++) gel(v, ++k) = gel(z1, i); } } } if (DEBUGLEVEL >= 6) timer_printf(&ti, "FpX_factcyclo_lift (%ld,%ld)*(%ld,%ld)-->(%ld,%ld)-->(%ld,%ld)", d1, nf1, d2, nf2, degpol(z), nf1*nf2, d1*d2/e, nf); return gerepilecopy(av, v); } /* n is any integer prime to p; d>1 and f>1 */ static GEN FpX_factcyclo_gen(GEN GH, ulong n, GEN p, long m) { GEN fn = factoru(n), fa = zm_to_ZM(fn); GEN A, T, X, pd_n, v, pols; long i, j, pmodn = umodiu(p, n), phin = eulerphiu_fact(fn); long d = Fl_order(pmodn, phin, n), f = phin/d; pari_timer ti; if (m != 1) m = f; if (m != 1 && GH==NULL) /* FpX_factcyclo_fact is used */ { GEN H = znstar_generate(n, mkvecsmall(pmodn)); GH = znstar_cosets(n, phin, H); /* representatives of G/H */ } pols = cgetg(1+m, t_VEC); v = cgetg(1+d, t_VEC); pd_n = diviuexact(subis(powiu(p, d), 1), n); /* (p^d-1)/n */ T = init_Fq(p, d, 1); A = pol_x(1); /* A is a generator of F_q, q=p^d */ if (d == 1) A = FpX_rem(A, T, p); random_FpX(degpol(T), varn(T), p); /* skip 1st one */ if (DEBUGLEVEL >= 6) timer_start(&ti); do X = FpXQ_pow(random_FpX(degpol(T), varn(T), p), pd_n, T, p); while(lg(X)<3 || equaliu(FpXQ_order(X, fa, T, p), n)==0); /* find zeta_n */ if (DEBUGLEVEL >= 6) timer_printf(&ti, "find X"); if (m == 1) { for (j = 1; j <= d; j++) { gel(v, j) = pol_x(0); gmael(v, j, 2) = FpX_neg(X, p); if (j < d) X = FpXQ_pow(X, p, T, p); } gel(pols, 1) = ZXX_evalx0(FpXQXV_prod(v, T, p)); } else { GEN vX, vp; if (DEBUGLEVEL >= 6) timer_start(&ti); vX = FpXQ_powers(X, n, T, p)+1; vp = Fl_powers(pmodn, d, n); for (i = 1; i <= m; i++) { for (j = 1; j <= d; j++) { gel(v, j) = pol_x(0); gmael(v, j, 2) = FpX_neg(gel(vX, Fl_mul(GH[i], vp[j], n)), p); } gel(pols, i) = ZXX_evalx0(FpXQXV_prod(v, T, p)); } if (DEBUGLEVEL >= 6) timer_printf(&ti, "FpXQXV_prod"); } return pols; } static GEN Flx_factcyclo_newton_pre(GEN Data, GEN N, ulong p, ulong m); /* n is an odd prime power prime to p and equal to the conductor * of the splitting field of p in Q(zeta_n). d>1 and nf>1 */ static GEN FpX_factcyclo_newton_power(GEN N, GEN p, ulong m, int small) { GEN Rs, H, T, F, pr, prs, pu, Data; long n = N[1], el = N[2], phin = N[4], g = N[5]; long pmodn = umodiu(p, n), pmodel = umodiu(p, el); long d = Fl_order(pmodel, el-1, el), nf = phin/d; long r, s = 0, u = 1; if (m != 1) m = nf; for (pu = p; cmpiu(pu,d) <= 0; u++) pu = mulii(pu,p); /* d= 2) err_printf("(u,s,r)=(%ld,%ld,%ld)\n",u,s,r); pr = powiu(p, r); prs = powiu(p, r+s); /* Usually, r=0, s=1, pr=1, prs=p */ F = r ? RgX_to_FpX(RgX_Rg_mul(F, pr), prs) : RgX_to_FpX(F, prs); Data = mkvec4(T, F, Rs, mkvecsmalln(6, d, nf, g, r, s, u)); if (small && lgefint(pu) == 3) return Flx_factcyclo_newton_pre(Data, N, uel(p,2), m); else return FpX_factcyclo_newton_pre(Data, N, p, m); } static GEN FpX_split(ulong n, GEN p, ulong m) { ulong i, j; GEN v, C, vx, z = rootsof1u_Fp(n, p); if (m == 1) return mkvec(deg1pol_shallow(gen_1, Fp_neg(z,p), 0)); v = cgetg(m+1, t_VEC); C = coprimes_zv(n); vx = Fp_powers(z, n-1, p); for (i = j = 1; i <= n; i++) if (C[i]) gel(v, j++) = deg1pol_shallow(gen_1, Fp_neg(gel(vx,i+1), p), 0); return gen_sort(v, (void*)cmpii, &gen_cmp_RgX); } /* n is a prime power prime to p. n is not necessarily equal to the * conductor of the splitting field of p in Q(zeta_n). */ static GEN FpX_factcyclo_prime_power_i(long el, long e, GEN p, long m) { GEN z = set_e0_e1(el, e, p), v; long n = z[1], e0 = z[2], e1 = z[3], phin = z[4], g = z[5]; long d = z[6], f = z[7]; /* d and f for n=el^e0 */ if (f == 1) v = mkvec(FpX_polcyclo(n, p)); else if (d == 1) v = FpX_split(n, p, (m==1)? 1: f); else if (el == 2) v = FpX_factcyclo_gen(NULL, n, p, m); /* d==2 in this case */ else if (!use_newton(d,f)) v = FpX_factcyclo_gen(NULL, n, p, m); else { GEN N = mkvecsmall5(n, el, e0, phin, g); v = FpX_factcyclo_newton_power(N, p, m, 0); } if (e1) { long i, l = lg(v), ele1 = upowuu(el, e1); for (i = 1; i < l; i++) gel(v, i) = RgX_inflate(gel(v, i), ele1); } return v; } static GEN FpX_factcyclo_prime_power(long el, long e, GEN p, long m) { pari_sp av = avma; return gerepilecopy(av, FpX_factcyclo_prime_power_i(el, e, p, m)); } static GEN FpX_factcyclo_fact(GEN fn, GEN p, ulong m, long ascent) { GEN EL = gel(fn, 1), E = gel(fn, 2), v1 = NULL; long i, l = lg(EL), n1 = 1; for (i = 1; i < l; i++) { long j = ascent? i: l-i, n2 = upowuu(EL[j], E[j]); GEN v2 = FpX_factcyclo_prime_power(EL[j], E[j], p, m); v1 = v1? FpX_factcyclo_lift(n1, v1, n2, v2, p, m): v2; n1 *= n2; } return v1; } static GEN Flv_FlvV_factorback(GEN g, GEN x, ulong q) { pari_APPLY_ulong(Flv_factorback(g, gel(x,i), q)) } /* return the structure and the generators of G/H. G=(Z/nZ)^, H=

. * For efficiency assume p mod n != 1 (trivial otherwise) */ static GEN get_GH_gen(long n, long pmodn) { GEN G = znstar0(utoipos(n), 1), cycG = znstar_get_cyc(G); GEN cycGH, gG, gGH, Ui, P; ulong expG; P = hnfmodid(mkmat(Zideallog(G, utoi(pmodn))), cycG); cycGH = ZV_to_nv(ZM_snf_group(P, NULL, &Ui)); expG = itou(cyc_get_expo(cycG)); gG = ZV_to_Flv(znstar_get_gen(G), n); gGH = Flv_FlvV_factorback(gG, ZM_to_Flm(Ui, expG), n); return mkvec2(gGH, cycGH); } /* 1st output */ static void header(GEN fn, long n, long d, long f, GEN p) { GEN EL = gel(fn, 1), E = gel(fn, 2); long i, l = lg(EL)-1; err_printf("n=%lu=", n); for (i = 1; i <= l; i++) { long el = EL[i], e = E[i]; err_printf("%ld", el); if (e > 1) err_printf("^%ld", e); if (i < l) err_printf("*"); } err_printf(", p=%Ps, phi(%lu)=%lu*%lu\n", p, n, d, f); err_printf("(n,d,f) : (%ld,%ld,%ld) --> ",n,d,f); } static ulong FpX_factcyclo_just_conductor_init(GEN *pData, ulong n, GEN p, ulong m) { GEN fn = factoru(n), GH = NULL, GHgen = NULL; long phin = eulerphiu_fact(fn), pmodn = umodiu(p, n); long d = Fl_order(pmodn, phin, n), f = phin/d; /* d > 1 */ ulong action = set_action(fn, p, d, f); if (action & ~NEWTON_POWER) { /* needed for GENERAL* */ GEN H = znstar_generate(n, mkvecsmall(pmodn)); GH = znstar_cosets(n, phin, H); /* representatives of G/H */ if (action & (NEWTON_GENERAL_NEW | NEWTON_GENERAL)) GHgen = get_GH_gen(n, pmodn); /* gen and order of G/H */ } *pData = mkvec5(GHgen, GH, fn, p, mkvecsmall4(n, d, f, m)); if (DEBUGLEVEL >= 1) { err_printf("(%ld,%ld,%ld) action=%ld\n", n, d, f, action); if (GHgen) { GEN cycGH = gel(GHgen,2), gGH = gel(GHgen,1); err_printf("G(K/Q)=%Ps gen=%Ps\n", zv_to_ZV(cycGH), zv_to_ZV(gGH)); } } return action; } static GEN FpX_factcyclo_just_conductor(ulong n, GEN p, ulong m) { GEN Data, fn; ulong action = FpX_factcyclo_just_conductor_init(&Data, n, p, m); fn = gel(Data,3); if (action & GENERAL) return FpX_factcyclo_gen(gel(Data,2), n, p, m); else if (action & NEWTON_POWER) return FpX_factcyclo_prime_power_i(ucoeff(fn,1,1), ucoeff(fn,1,2), p, m); else if (action & NEWTON_GENERAL) return FpX_factcyclo_newton_general(Data); else if (action & NEWTON_GENERAL_NEW) return FpX_factcyclo_newton_general_new3(Data); else return FpX_factcyclo_fact(fn, p, m, action & ASCENT); } static GEN FpX_factcyclo_i(ulong n, GEN p, long fl) { GEN fn = factoru(n), z; long phin = eulerphiu_fact(fn), pmodn = umodiu(p, n); ulong d = Fl_order(pmodn, phin, n), f = phin/d, fK; if (DEBUGLEVEL >= 1) header(fn, n, d, f, p); if (f == 1) { z = FpX_polcyclo(n, p); return fl? z: mkvec(z); } else if (d == 1) /* p=1 (mod n), zeta_n in Z_p */ { z = FpX_split(n, p, fl? 1: f); return fl? gel(z,1): z; } fK = znstar_conductor(znstar_generate(n, mkvecsmall(pmodn))); if (fK != n && umodiu(p, fK) == 1) z = FpX_split(fK, p, fl? 1: f); else z = FpX_factcyclo_just_conductor(fK, p, fl? 1: f); if (n > fK) { GEN vP = const_vec(n, NULL); long i, l = fl? 2: lg(z); for (i = 1; i < l; i++) gel(z, i) = FpX_conductor_lift(gel(z, i), p, fn, fK, vP); } return fl? gel(z,1): gen_sort(z,(void*)cmpii, &gen_cmp_RgX); } GEN FpX_factcyclo(ulong n, GEN p, ulong m) { pari_sp av = avma; return gerepilecopy(av, FpX_factcyclo_i(n, p, m)); } /* Data = [H, GH, i_t, d0, kT, [n, d, f, n_T, mitk]] * N2 = [p, pr, pu, pru] */ static GEN Flx_pol_newton_general(GEN Data, GEN N2, GEN vT, ulong x) { GEN i_t = gel(Data, 3), kT = gel(Data, 5), N = gel(Data, 6); long k, d = N[2], n_T = N[4], mitk = N[5]; long p = N2[1], pr = N2[2], pu = N2[3], pru = N2[4]; GEN R = cgetg(1+mitk, t_VECSMALL); for (k = 1; k <= n_T; k++) uel(R,kT[k]) = Flx_eval(gel(vT, kT[k]), x, pru) / pr; return Flx_Newton_perm(d, R, i_t, pu, p); } /* n is any integer prime to p, but must be equal to the conductor * of the splitting field of p in Q(zeta_n). * GH=G/H={g_1, ... ,g_f} * Data = [GHgen, GH, fn, p, [n, d, f, m]] */ static GEN Flx_factcyclo_newton_general(GEN Data) { GEN GH = gel(Data, 2), fn = gel(Data, 3), p = gel(Data, 4); ulong up = p[2], n = mael(Data, 5, 1), pmodn = up%n; long d = mael(Data, 5, 2), f = mael(Data, 5, 3), m = mael(Data, 5, 4); long i, k, n_T, mitk, r, s = 0, u = 1; GEN vT, kT, H, i_t, T, d0d1, Data2, Data3, R, Rs, pr, pu, pru; pari_timer ti; if (m != 1) m = f; for (pu = p; cmpiu(pu,d) <= 0; u++) pu = muliu(pu, up); /* d */ i_t = get_i_t(n, pmodn); /* i_t[1+i]=k ==> t_i=t_k */ kT = get_kT(i_t, d); n_T = lg(kT)-1; mitk = kT[n_T]; if (DEBUGLEVEL == 2) err_printf("kT=%Ps %ld elements\n",kT,n_T); if (DEBUGLEVEL >= 6) timer_start(&ti); T = galoissubcyclo(utoi(n), utoi(pmodn), 0, 0); if (DEBUGLEVEL >= 6) timer_printf(&ti, "galoissubcyclo"); d0d1 = get_d0_d1(T, gel(fn,1)); /* d0*T_k(x) is in Z[x] */ Data2 = mkvecn(6, H, GH, i_t, d0d1, kT, mkvecsmalln(5, n, d, f, n_T, mitk)); vT = get_vT(Data2, 0); if (DEBUGLEVEL == 4) err_printf("vT=%Ps\n",vT); r = QXV_den_pval(vT, kT, p); Rs = ZpX_roots_all(T, p, f, &s); if (DEBUGLEVEL >= 2) err_printf("(u,s,r)=(%ld,%ld,%ld)\n",u,s,r); if (r+u < s) pari_err_BUG("Flx_factcyclo_newton_general, T is not separable mod p^(r+u)"); /* R and vT are mod p^(r+u) */ R = (r+u==s) ? Rs : ZV_sort_shallow(ZX_Zp_liftroots(T, Rs, p, s, r+u)); pr = powiu(p, r); pru = powiu(p, r+u); /* Usually, r=0, s=1, pr=1, pru=p */ if (lgefint(pru) > 3) /* ULONG_MAX < p^(r+u), probably won't occur */ { for (k = 1; k <= n_T; k++) { long itk = kT[k]; GEN z = r? RgX_Rg_mul(gel(vT, itk), pr): gel(vT, itk); gel(vT, itk) = RgX_to_FpX(z, pru); } Data3 = mkvec4(p, pr, pu, pru); for (i = 1; i <= m; i++) gel(R,i) = ZX_to_nx(FpX_pol_newton_general(Data2, Data3, vT, gel(R,i))); if (DEBUGLEVEL >= 6) timer_printf(&ti, "FpX_pol_newton_general"); } else { ulong upr = itou(pr), upru = itou(pru), upu = itou(pu); for (k = 1; k <= n_T; k++) { long itk = kT[k]; GEN z = r? RgX_muls(gel(vT, itk), upr): gel(vT, itk); gel(vT, itk) = RgX_to_Flx(z, upru); } Data3 = mkvecsmall4(up, upr, upu, upru); if (DEBUGLEVEL >= 6) timer_start(&ti); for (i = 1; i <= m; i++) gel(R,i) = Flx_pol_newton_general(Data2, Data3, vT, itou(gel(R,i))); if (DEBUGLEVEL >= 6) timer_printf(&ti, "Flx_pol_newton_general"); } return R; } /* Data=[vT, gGH, Rs, Rrs, i_t, kt, p, pu, pr, prs, * [n, r, s, n_t, mitk, d], div] */ static GEN Flx_pol_newton_general_new3(GEN Data, long k) { GEN i_t = gel(Data,5), p = gel(Data,7), pu = gel(Data,8), prs = gel(Data,10); long d = mael(Data, 11, 6); GEN v_t_p = (lgefint(prs)>3)? ZV_to_nv(Fp_mk_v_t_p3(Data, k)) : Fl_mk_v_t_p3(Data, k); if (DEBUGLEVEL == 3) err_printf("v_t_p=%Ps\n",v_t_p); return Flx_Newton_perm(d, v_t_p, i_t, pu[2], p[2]); } /* Data = [GHgen, GH, fn, p, [n, d, f, m]] */ static GEN Flx_factcyclo_newton_general_new3(GEN Data) { long i, f = mael(Data, 5, 3), m = mael(Data, 5, 4); GEN Data2, pu, pols; pari_timer ti; if (m != 1) m = f; pols = cgetg(1+m, t_VEC); Data2 = newton_general_new_pre3(Data); pu = gel(Data2, 8); /* Data2 = [vT, gGH, Rs, Rrs, i_t, kt, p, pu, pr, prs, [n, r, s, n_t, mitk, d], div] */ if (DEBUGLEVEL >= 6) timer_start(&ti); if (lgefint(pu) > 3) /* ULONG_MAX < p^u, probably won't occur */ { for (i = 1; i <= m; i++) gel(pols, i) = ZX_to_nx(FpX_pol_newton_general_new3(Data2, i)); if (DEBUGLEVEL >= 6) timer_printf(&ti, "FpX_pol_newton_general_new3"); } else { for (i = 1; i <= m; i++) gel(pols, i) = Flx_pol_newton_general_new3(Data2, i); if (DEBUGLEVEL >= 6) timer_printf(&ti, "Flx_pol_newton_general_new3"); } return pols; } /* return normalized z(-x) */ static GEN Flx_1st_lift_2(GEN z, ulong p) { long i, r = lg(z); GEN x = cgetg(r, t_VECSMALL); x[1] = z[1]; if (odd(r)) for (i = 2; i= 2) z = Flx_inflate(z, upowuu(el, r-1)); } else z = Flx_inflate(z, upowuu(el, r-s)); return z; } /* e is the conductor of the splitting field of p in Q(zeta_n) */ static GEN Flx_conductor_lift(GEN z, ulong p, GEN fn, ulong e, GEN vP) { GEN EL = gel(fn, 1), En = gel(fn, 2); long i, r = lg(EL), new_e = e; for (i = 1; i < r; i++) { long el = EL[i], en = En[i], ee = u_lval(e, el); if (ee < en) { z = Flx_lift(z, p, new_e, el, en, ee, vP); new_e *= upowuu(el, en-ee); } } return z; } /* R0 is mod p^u, d < p^u */ static GEN Flx_pol_newton(long j, GEN R0, GEN E, GEN D3, long d, long f, ulong p) { ulong u = D3[3]; GEN R = cgetg(f+1, t_VECSMALL); long i; for (i = 1; i <= f; i++) R[i] = R0[1+(i+j)%f]; return Flx_Newton_perm(d, R, E, upowuu(p,u), p); } /* Data = [T, F, Rs, [d, nf, g, r, s, u]], nf>1 */ static GEN Flx_factcyclo_newton_pre(GEN Data, GEN N, ulong p, ulong m) { GEN T = gel(Data, 1), F = gel(Data, 2), Rs = gel(Data, 3), D4 = gel(Data, 4); long d = D4[1], nf = D4[2], g = D4[3], r = D4[4], s = D4[5], u = D4[6]; GEN pols, E, R, p0 = utoi(p), Data3; ulong i, n = N[1], pmodn = p%n; pari_timer ti; if (m != 1) m = nf; pols = cgetg(1+m, t_VEC); E = set_E(pmodn, n, d, nf, g); R = set_R(T, F, Rs, p0, nf, r, s, u); R = ZV_to_nv(R); Data3 = mkvecsmall3(r, s, u); if (DEBUGLEVEL >= 6) timer_start(&ti); for (i = 1; i <= m; i++) gel(pols, i) = Flx_pol_newton(i, R,E,Data3, d,nf,p); if (DEBUGLEVEL >= 6) timer_printf(&ti, "Flx_pol_newton"); return pols; } /* gcd(n1,n2)=1, e = gcd(d1,d2). * phi(n1) = d1*nf1, phi(n2) = d2*nf2. * d = lcm(d1,d2) = d1*d2/e, nf = phi(n1)*phi(n2)/d = nf1*nf2*e. */ static GEN Flx_factcyclo_lift(long n1, GEN v1, long n2, GEN v2, long p, long m) { pari_sp av = avma; long d1 = degpol(gel(v1, 1)), lv1 = lg(v1), nf1 = eulerphiu(n1)/d1; long d2 = degpol(gel(v2, 1)), lv2 = lg(v2), nf2 = eulerphiu(n2)/d2; long e = ugcd(d1, d2), nf = nf1*nf2*e, need_factor = (e!=1); long i, j, k = 0; GEN v, z = NULL; pari_timer ti; if (DEBUGLEVEL >= 6) timer_start(&ti); if (m != 1) m = nf; v = cgetg(1+m, t_VEC); if (m == 1) { GEN x1 = gel(v1, 1), x2 = gel(v2, 1); z = Flx_gcd(Flx_inflate(x1, n2), Flx_inflate(x2, n1), p); z = Flx_normalize(z, p); /* Flx_gcd sometimes returns non-monic */ gel(v, 1) = (!need_factor)? z : gmael(Flx_factor(z, p), 1, 1); } else for (i = 1; i < lv1; i++) for (j = 1; j < lv2; j++) { GEN x1 = gel(v1, i), x2 = gel(v2, j); z = Flx_gcd(Flx_inflate(x1, n2), Flx_inflate(x2, n1), p); z = Flx_normalize(z, p); /* needed */ if (!need_factor) gel(v, ++k) = z; else { GEN z1 = gel(Flx_factor(z, p), 1); long i, l = lg(z1); for (i = 1; i < l; i++) gel(v, ++k) = gel(z1, i); } } if (DEBUGLEVEL >= 6) timer_printf(&ti, "Flx_factcyclo_lift (%ld,%ld)*(%ld,%ld)-->(%ld,%ld)-->(%ld,%ld)", d1, nf1, d2, nf2, degpol(z), nf1*nf2, d1*d2/e, nf); return gerepilecopy(av, v); } /* factor polcyclo(n) mod p based on an idea of Bill Allombert; d>1 and nf>1 */ static GEN Flx_factcyclo_gen(GEN GH, ulong n, ulong p, ulong m) { GEN fu = factoru(n), fa = zm_to_ZM(fu), p0 = utoi(p); GEN T, X, pd_n, v, pols; ulong i, j, pmodn = p%n, phin = eulerphiu_fact(fu); ulong d = Fl_order(pmodn, phin, n), nf = phin/d; pari_timer ti; if (m != 1) m = nf; if (m != 1 && !GH) /* Flx_factcyclo_fact is used */ { GEN H = znstar_generate(n, mkvecsmall(pmodn)); GH = znstar_cosets(n, phin, H); /* representatives of G/H */ } pols = cgetg(1+m, t_VEC); v = cgetg(1+d, t_VEC); pd_n = diviuexact(subis(powiu(p0, d), 1), n); /* (p^d-1)/n */ T = ZX_to_Flx(init_Fq(p0, d, evalvarn(1)), p); random_Flx(degpol(T), T[1], p); /* skip 1st one */ if (DEBUGLEVEL >= 6) timer_start(&ti); do X = Flxq_pow(random_Flx(degpol(T), T[1], p), pd_n, T, p); while (lg(X)<3 || equaliu(Flxq_order(X, fa, T, p), n)==0); /* find zeta_n */ if (DEBUGLEVEL >= 6) timer_printf(&ti, "find X"); if (m == 1) { for (j = 1; j <= d; j++) { gel(v, j) = polx_FlxX(0, 1); gmael(v, j, 2) = Flx_neg(X, p); if (j < d) X = Flxq_powu(X, p, T, p); } gel(pols, 1) = FlxX_to_Flx(FlxqXV_prod(v, T, p)); } else { GEN vX, vp; if (DEBUGLEVEL >= 6) timer_start(&ti); vX = Flxq_powers(X, n, T, p)+1; vp = Fl_powers(pmodn, d, n); for (i = 1; i <= m; i++) { for (j = 1; j <= d; j++) { gel(v, j) = polx_FlxX(0, 1); gmael(v, j, 2) = Flx_neg(gel(vX, Fl_mul(GH[i], vp[j], n)), p); } gel(pols, i) = FlxX_to_Flx(FlxqXV_prod(v, T, p)); } if (DEBUGLEVEL >= 6) timer_printf(&ti, "FlxqXV_prod"); } return pols; } static int cmpGuGu(GEN a, GEN b) { return (ulong)a < (ulong)b? -1: (a == b? 0: 1); } /* p=1 (mod n). If m!=1, then m=phi(n) */ static GEN Flx_split(ulong n, ulong p, ulong m) { ulong i, j, z = rootsof1_Fl(n, p); GEN v, C, vx; if (m == 1) return mkvec(mkvecsmall3(0, Fl_neg(z,p), 1)); v = cgetg(m+1, t_VEC); C = coprimes_zv(n); vx = Fl_powers(z, n-1, p); for (i = j = 1; i <= n; i++) if (C[i]) gel(v, j++) = mkvecsmall3(0, Fl_neg(vx[i+1], p), 1); return gen_sort(v, (void*)cmpGuGu, &gen_cmp_RgX); } /* d==1 or f==1 occurs */ static GEN Flx_factcyclo_prime_power_i(long el, long e, long p, long m) { GEN p0 = utoipos(p), z = set_e0_e1(el, e, p0), v; long n = z[1], e0 = z[2], e1 = z[3], phin = z[4], g = z[5]; long d = z[6], f = z[7]; /* d and f for n=el^e0 */ if (f == 1) v = mkvec(Flx_polcyclo(n, p)); else if (d == 1) v = Flx_split(n, p, (m==1)?1:f); else if (el == 2) v = Flx_factcyclo_gen(NULL, n, p, m);/* d==2 in this case */ else if (!use_newton(d, f)) v = Flx_factcyclo_gen(NULL, n, p, m); else { GEN N = mkvecsmall5(n, el, e0, phin, g); v = FpX_factcyclo_newton_power(N, p0, m, 1); if (typ(gel(v,1)) == t_POL) { /* ZX: convert to Flx */ long i, l = lg(v); for (i = 1; i < l; i++) gel(v,i) = ZX_to_nx(gel(v,i)); } } if (e1) { long i, l = lg(v), ele1 = upowuu(el, e1); for (i = 1; i < l; i++) gel(v, i) = Flx_inflate(gel(v, i), ele1); } return v; } static GEN Flx_factcyclo_prime_power(long el, long e, long p, long m) { pari_sp av = avma; return gerepilecopy(av, Flx_factcyclo_prime_power_i(el, e, p, m)); } static GEN Flx_factcyclo_fact(GEN fn, ulong p, ulong m, long ascent) { GEN EL = gel(fn, 1), E = gel(fn, 2), v1, v2; long l = lg(EL), i, j, n1, n2; j = ascent? 1: l-1; n1 = upowuu(EL[j], E[j]); v1 = Flx_factcyclo_prime_power(EL[j], E[j], p, m); for (i = 2; i < l; i++) { j = ascent? i: l-i; n2 = upowuu(EL[j], E[j]); v2 = Flx_factcyclo_prime_power(EL[j], E[j], p, m); v1 = Flx_factcyclo_lift(n1, v1, n2, v2, p, m); n1 *= n2; } return v1; } static GEN Flx_factcyclo_just_conductor(ulong n, ulong p, ulong m) { GEN Data, fn; ulong action = FpX_factcyclo_just_conductor_init(&Data, n, utoipos(p), m); fn = gel(Data,3); if (action & GENERAL) return Flx_factcyclo_gen(gel(Data,2), n, p, m); else if (action & NEWTON_POWER) return Flx_factcyclo_prime_power_i(ucoeff(fn,1,1), ucoeff(fn,1,2), p, m); else if (action & NEWTON_GENERAL) return Flx_factcyclo_newton_general(Data); else if (action & NEWTON_GENERAL_NEW) return Flx_factcyclo_newton_general_new3(Data); else return Flx_factcyclo_fact(fn, p, m, action & ASCENT); } static GEN Flx_factcyclo_i(ulong n, ulong p, ulong fl) { GEN fn = factoru(n), z; ulong phin = eulerphiu_fact(fn), pmodn = p%n; ulong d = Fl_order(pmodn, phin, n), f = phin/d, fK; if (DEBUGLEVEL >= 1) header(fn, n, d, f, utoi(p)); if (f == 1) { z = Flx_polcyclo(n, p); return fl? z: mkvec(z); } if (d == 1) /* p=1 (mod n), zeta_n in Z_p */ { z = Flx_split(n, p, fl? 1: f); return fl? gel(z,1): z; } fK = znstar_conductor(znstar_generate(n, mkvecsmall(pmodn))); if (fK != n && p % fK == 1) z = Flx_split(fK, p, fl? 1: f); else z = Flx_factcyclo_just_conductor(fK, p, fl? 1: f); if (n > fK) { GEN vP = const_vec(n, NULL); long i, l = fl? 2: lg(z); for (i = 1; i < l; i++) gel(z, i) = Flx_conductor_lift(gel(z, i), p, fn, fK, vP); } return fl? gel(z,1): gen_sort(z,(void*)cmpGuGu, &gen_cmp_RgX); } GEN Flx_factcyclo(ulong n, ulong p, ulong m) { pari_sp av = avma; return gerepilecopy(av, Flx_factcyclo_i(n, p, m)); } GEN factormodcyclo(long n, GEN p, long fl, long v) { const char *fun = "factormodcyclo"; pari_sp av = avma; long i, l; GEN z; if (v < 0) v = 0; if (fl < 0 || fl > 1) pari_err_FLAG(fun); if (n <= 0) pari_err_DOMAIN(fun, "n", "<=", gen_0, stoi(n)); if (typ(p) != t_INT) pari_err_TYPE(fun, p); if (dvdui(n, p)) pari_err_COPRIME(fun, stoi(n), p); if (fl) { if (lgefint(p) == 3) z = Flx_to_ZX(Flx_factcyclo_i(n, p[2], 1)); else z = FpX_factcyclo_i(n, p, 1); setvarn(z, v); return gerepileupto(av, FpX_to_mod(z, p)); } else { if (lgefint(p) == 3) z = FlxC_to_ZXC(Flx_factcyclo_i(n, p[2], 0)); else z = FpX_factcyclo_i(n, p, 0); l = lg(z); for (i = 1; i < l; i++) setvarn(gel(z, i), v); return gerepileupto(av, FpXC_to_mod(z, p)); } } pari-2.17.2/src/basemath/random.c0000644000175000017500000002251314567450071015177 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /********************************************************************/ /* */ /* 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 */ #ifdef LONG_IS_64BIT typedef ulong u64; #else typedef unsigned long long u64; static u64 _32to64(ulong a, ulong b) { u64 v = a; return (v<<32)|b; } static void _64to32(u64 v, ulong *a, ulong *b) { *a = v>>32; *b = v&0xFFFFFFFF; } #endif static THREAD u64 state[64]; static THREAD u64 xorgen_w; static THREAD int xorgen_i; /* weyl = odd approximation to 2^64*(sqrt(5)-1)/2. */ static const u64 weyl = (((u64)0x61c88646U)<<32)|((u64)0x80b583ebU); static u64 block(void) { const int r = 64; const int a = 33, b = 26, c = 27, d = 29, s = 53; u64 t, v, w; xorgen_i = (xorgen_i+1)&(r-1); t = state[xorgen_i]; v = state[(xorgen_i+(r-s))&(r-1)]; /* index is (i-s) mod r */ t ^= t<>b; /* (I + L^a)(I + R^b) */ v ^= v<>d; /* (I + L^c)(I + R^d) */ w = t^v; return state[xorgen_i] = w; /* update circular array */ } /* v > 0 */ static void init_xor4096i(u64 v) { const int r = 64; int k; for (k = r; k > 0; k--) {/* avoid correlations for close seeds */ v ^= v<<10; v ^= v>>15; /* recurrence has period 2**64-1 */ v ^= v<<4; v ^= v>>13; } for (xorgen_w = v, k = 0; k < r; k++) { /* initialise circular array */ v ^= v<<10; v ^= v>>15; v ^= v<<4; v ^= v>>13; state[k] = v + (xorgen_w+=weyl); } /* discard first 4*r results */ for (xorgen_i = r-1, k = 4*r; k > 0; k--) (void)block(); } void pari_init_rand(void) { init_xor4096i(1UL); } static u64 rand64(void) { u64 v = block(); xorgen_w += weyl; /* update Weyl generator */ return v + (xorgen_w ^ (xorgen_w>>27)); } /* One random number uniformly distributed in [0..2**BIL) is returned, where * BIL = 8*sizeof(ulong) = 32 or 64. */ ulong pari_rand(void) { return rand64(); } void setrand(GEN x) { const int r2 = numberof(state); long i, lx; u64 v; GEN xp; if (typ(x)!=t_INT) pari_err_TYPE("setrand",x); if (signe(x) <= 0) pari_err_DOMAIN("setrand","n", "<=", gen_0, x); lx = lgefint(x); if (lx == 3) { v = x[2]; init_xor4096i(v); return; } #ifndef LONG_IS_64BIT if (lx == 4) { v = _32to64(*int_W(x,1),*int_W(x,0)); init_xor4096i(v); return; } #endif xp = int_LSW(x); #ifdef LONG_IS_64BIT if (lx != 2 + r2+2) pari_err_DOMAIN("setrand", "n", "!=", strtoGENstr("getrand()"), x); for (i = 0; i < r2; i++, xp = int_nextW(xp)) state[i] = *xp; xorgen_w = *xp; xp = int_nextW(xp); #else if (lx != 2 + 2*r2+3) pari_err_DOMAIN("setrand", "n", "!=", strtoGENstr("getrand()"), x); for (i = 0; i < r2; i++, xp = int_nextW(int_nextW(xp))) state[i] = _32to64(*int_nextW(xp), *xp); xorgen_w = _32to64(*int_nextW(xp), *xp); xp = int_nextW(int_nextW(xp)); #endif xorgen_i = (*xp) & 63; } GEN getrand(void) { const int r2 = numberof(state); GEN x; ulong *xp; long i; if (xorgen_i < 0) init_xor4096i(1UL); #ifdef LONG_IS_64BIT x = cgetipos(2+r2+2); xp = (ulong *) int_LSW(x); for (i = 0; i < r2; i++, xp = int_nextW(xp)) *xp = state[i]; *xp = xorgen_w; xp = int_nextW(xp); #else x = cgetipos(2+2*r2+3); xp = (ulong *) int_LSW(x); for (i = 0; i < r2; i++, xp = int_nextW(int_nextW(xp))) _64to32(state[i], int_nextW(xp), xp); _64to32(xorgen_w, int_nextW(xp), xp); xp = int_nextW(int_nextW(xp)); #endif *xp = xorgen_i? xorgen_i: 64; return x; } /* assume 0 <= k <= BITS_IN_LONG. Return uniform random 0 <= x < (1<> (64-k); } /********************************************************************/ /* */ /* GENERIC ROUTINES */ /* */ /********************************************************************/ /* assume n > 0 */ ulong random_Fl(ulong n) { ulong d; int shift; #ifdef LONG_IS_64BIT int SHIFT = 0; #else int SHIFT = 32; #endif if (n == 1) return 0; shift = bfffo(n); /* 2^(BIL-shift) > n >= 2^(BIL-shift-1)*/ /* if N a power of 2, increment shift. No reject */ if ((n << shift) == HIGHBIT) return rand64() >> (SHIFT+shift+1); for (;;) { d = rand64() >> (SHIFT+shift); /* d < 2^(64-shift) uniformly distributed */ /* reject strategy: proba success = n 2^(shift-64), in [1/2, 1[ */ if (d < n) return d; } } /* assume N > 0, see random_Fl() for algorithm. Make sure that 32-bit and * 64-bit architectures produce the same integers (consuming random bits * by packets of 64) */ GEN randomi(GEN N) { long lx = lgefint(N); GEN x, d; int shift; if (lx == 3) return utoi( random_Fl(N[2]) ); shift = bfffo(*int_MSW(N)); /* if N a power of 2, increment shift */ if (Z_ispow2(N) && ++shift == BITS_IN_LONG) { shift = 0; lx--; } x = cgetipos(lx); for (;;) { GEN y, MSW = int_MSW(x), STOP = MSW; #ifdef LONG_IS_64BIT for (d = int_LSW(x); d != STOP; d = int_nextW(d)) *d = rand64(); *d = rand64() >> shift; #else if (!odd(lx)) STOP = int_precW(STOP); /* STOP points to where MSW would in 64-bit */ for (d = int_LSW(x); d != STOP; d = int_nextW(d)) { ulong a, b; _64to32(rand64(), &a,&b); *d = b; d = int_nextW(d); *d = a; } { ulong a, b; _64to32(rand64() >> shift, &a,&b); if (d == MSW) /* 32 bits needed */ *d = a; else { /* 64 bits needed */ *d = b; d = int_nextW(d); *d = a; } } #endif y = int_normalize(x, 0); if (abscmpii(y, N) < 0) return y; } } GEN random_F2x(long d, long vs) { ulong db, dl = dvmduBIL(d,&db); long i, l = 2 + dl + !!db; GEN y = cgetg(l,t_VECSMALL); y[1] = vs; #ifdef LONG_IS_64BIT for (i=2; i>32); } if (i b)", N); return gerepileuptoint(av, addii(a, randomi(addiu(d,1)))); } return ellrandom(N); default: pari_err_TYPE("genrand",N); return NULL;/*LCOV_EXCL_LINE*/ } } pari-2.17.2/src/basemath/alglin3.c0000644000175000017500000006274014760123736015256 0ustar billbill/* Copyright (C) 2012 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /********************************************************************/ /** **/ /** LINEAR ALGEBRA **/ /** (third part) **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_mat /*******************************************************************/ /* */ /* SUM */ /* */ /*******************************************************************/ GEN vecsum(GEN v) { pari_sp av = avma; long i, l; GEN p; if (!is_vec_t(typ(v))) pari_err_TYPE("vecsum", v); l = lg(v); if (l == 1) return gen_0; p = gel(v,1); if (l == 2) return gcopy(p); for (i=2; i1) pari_warn(warnmem,"sum"); p = gerepileupto(av, p); } } return gerepileupto(av, p); } /*******************************************************************/ /* */ /* TRANSPOSE */ /* */ /*******************************************************************/ /* A[x0,]~ */ static GEN row_transpose(GEN A, long x0) { long i, lB = lg(A); GEN B = cgetg(lB, t_COL); for (i=1; imax) return 0; } if (*s == '.') { s++; if (*s != '.') return 0; do s++; while (isspace((unsigned char)*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 shallowmatextract(GEN x, GEN l1, GEN l2) { long i, j, n1 = lg(l1), n2 = lg(l2); GEN M = cgetg(n2, t_MAT); for(i=1; i < n2; i++) { long ii = l2[i]; GEN C = cgetg(n1, t_COL); for (j=1; j < n1; j++) { long jj = l1[j]; gel(C, j) = gmael(x, ii, jj); } gel(M, i) = C; } return M; } GEN shallowextract(GEN x, GEN L) { long i,j, tl = typ(L), tx = typ(x), lx = lg(x); GEN y; switch(tx) { case t_VEC: case t_COL: case t_MAT: case t_VECSMALL: break; default: pari_err_TYPE("extract",x); } if (tl==t_INT) { /* extract components of x as per the bits of mask L */ long k, l, ix, iy, maxj; GEN Ld; if (!signe(L)) return cgetg(1,tx); y = new_chunk(lx); l = lgefint(L)-1; ix = iy = 1; maxj = BITS_IN_LONG - bfffo(*int_MSW(L)); if ((l-2) * BITS_IN_LONG + maxj >= lx) pari_err_TYPE("vecextract [mask too large]", L); for (k = 2, Ld = int_LSW(L); k < l; k++, Ld = int_nextW(Ld)) { ulong B = *Ld; for (j = 0; j < BITS_IN_LONG; j++, B >>= 1, ix++) if (B & 1) y[iy++] = x[ix]; } { /* k = l */ ulong B = *Ld; for (j = 0; j < maxj; j++, B >>= 1, ix++) if (B & 1) y[iy++] = x[ix]; } y[0] = evaltyp(tx) | evallg(iy); return y; } if (tl==t_STR) { char *s = GSTR(L); long first, last, cmpl, d; if (! get_range(s, &first, &last, &cmpl, lx)) pari_err_TYPE("vecextract [incorrect range]", L); if (lx == 1) return cgetg(1,tx); d = last - first; if (cmpl) { if (d >= 0) { y = cgetg(lx - (1+d),tx); for (j=1; jfirst; i--,j++) gel(y,j) = gel(x,i); for (i=last-1; i>0; i--,j++) gel(y,j) = gel(x,i); } } else { if (d >= 0) { y = cgetg(d+2,tx); for (i=first,j=1; i<=last; i++,j++) gel(y,j) = gel(x,i); } else { y = cgetg(2-d,tx); for (i=first,j=1; i>=last; i--,j++) gel(y,j) = gel(x,i); } } return y; } if (is_vec_t(tl)) { long ll=lg(L); y=cgetg(ll,tx); for (i=1; i=",stoi(lx),stoi(j)); gel(y,i) = gel(x,j); } return y; } if (tl == t_VECSMALL) { long ll=lg(L); y=cgetg(ll,tx); for (i=1; i=",stoi(lx),stoi(j)); gel(y,i) = gel(x,j); } return y; } pari_err_TYPE("vecextract [mask]", L); return NULL; /* LCOV_EXCL_LINE */ } /* does the component selector l select 0 component ? */ static int select_0(GEN l) { switch(typ(l)) { case t_INT: return (!signe(l)); case t_VEC: case t_COL: case t_VECSMALL: return (lg(l) == 1); } return 0; } GEN extract0(GEN x, GEN l1, GEN l2) { pari_sp av = avma, av2; GEN y; if (! l2) { y = shallowextract(x, l1); if (lg(y) == 1 || typ(y) == t_VECSMALL) return y; av2 = avma; y = gcopy(y); } else { if (typ(x) != t_MAT) pari_err_TYPE("extract",x); y = shallowextract(x,l2); if (select_0(l1)) { set_avma(av); return zeromat(0, lg(y)-1); } if (lg(y) == 1 && lg(x) > 1) { if (!extract_selector_ok(lgcols(x), l1)) pari_err_TYPE("vecextract [incorrect mask]", l1); set_avma(av); return cgetg(1, t_MAT); } y = shallowextract(shallowtrans(y), l1); av2 = avma; y = gtrans(y); } stackdummy(av, av2); return y; } static long vecslice_parse_arg(long lA, long *y1, long *y2, long *skip) { *skip=0; if (*y1==LONG_MAX) { if (*y2!=LONG_MAX) { if (*y2<0) *y2 += lA; if (*y2<0 || *y2==LONG_MAX || *y2>=lA) pari_err_DIM("_[..]"); *skip=*y2; } *y1 = 1; *y2 = lA-1; } else if (*y2==LONG_MAX) *y2 = *y1; if (*y1<=0) *y1 += lA; if (*y2<0) *y2 += lA; if (*y1<=0 || *y1>*y2+1 || *y2>=lA) pari_err_DIM("_[..]"); return *y2 - *y1 + 2 - !!*skip; } static GEN vecslice_i(GEN A, long t, long lB, long y1, long skip) { GEN B = cgetg(lB, t); long i; for (i=1; i0) return cgetg(1,t_VEC); l = itos(subii(b,a))+1; a = setloop(a); y = cgetg(l+1, t_VEC); for (i=1; i<=l; a = incloop(a), i++) gel(y,i) = icopy(a); return y; } GEN vecrangess(long a, long b) { GEN y; long i, l; if (a>b) return cgetg(1,t_VEC); l = b-a+1; y = cgetg(l+1, t_VEC); for (i=1; i<=l; a++, i++) gel(y,i) = stoi(a); return y; } GEN genindexselect(void *E, long (*f)(void* E, GEN x), GEN A) { long l, i, lv; GEN v, z; pari_sp av; switch(typ(A)) { case t_LIST: z = list_data(A); l = z? lg(z): 1; if (list_typ(A)==t_LIST_MAP) { av = avma; return gerepilecopy(av, mapselect_shallow(E, f, A)); } break; case t_VEC: case t_COL: case t_MAT: l = lg(A); z = A; break; default: pari_err_TYPE("select",A); return NULL;/*LCOV_EXCL_LINE*/ } v = cgetg(l, t_VECSMALL); av = avma; clone_lock(A); for (i = lv = 1; i < l; i++) { if (f(E, gel(z,i))) v[lv++] = i; set_avma(av); } clone_unlock_deep(A); fixlg(v, lv); return v; } static GEN extract_copy(GEN A, GEN v) { long i, l = lg(v); GEN B = cgetg(l, typ(A)); for (i = 1; i < l; i++) gel(B,i) = gcopy(gel(A,v[i])); return B; } /* as genselect, but treat A [ t_VEC,t_COL, or t_MAT] as a t_VEC */ GEN vecselect(void *E, long (*f)(void* E, GEN x), GEN A) { GEN v; clone_lock(A); v = genindexselect(E, f, A); A = extract_copy(A, v); settyp(A, t_VEC); clone_unlock_deep(A); return A; } GEN genselect(void *E, long (*f)(void* E, GEN x), GEN A) { pari_sp av = avma; GEN y, z, v;/* v left on stack for efficiency */ clone_lock(A); switch(typ(A)) { case t_LIST: z = list_data(A); if (!z) y = mklist(); else { if (list_typ(A)==t_LIST_MAP) { long i, l = z? lg(z): 1, lv=1; GEN v1 = cgetg(l, t_COL); GEN v2 = cgetg(l, t_COL); for (i = lv = 1; i < l; i++) { if (f(E, gmael3(z,i,1,2))) { gel(v1,lv) = gmael3(z,i,1,1); gel(v2,lv) = gmael3(z,i,1,2); lv++; } } fixlg(v1, lv); fixlg(v2, lv); y = gtomap(mkmat2(v1,v2)); } else { GEN B; y = cgetg(3, t_LIST); v = genindexselect(E, f, z); B = extract_copy(z, v); y[1] = lg(B)-1; list_data(y) = B; } } break; case t_VEC: case t_COL: case t_MAT: v = genindexselect(E, f, A); y = extract_copy(A, v); break; default: pari_err_TYPE("select",A); return NULL;/*LCOV_EXCL_LINE*/ } clone_unlock_deep(A); return gerepileupto(av, y); } static void check_callgen1(GEN f, const char *s) { if (typ(f) != t_CLOSURE || closure_is_variadic(f) || closure_arity(f) < 1) pari_err_TYPE(s, f); } GEN select0(GEN f, GEN x, long flag) { check_callgen1(f, "select"); switch(flag) { case 0: return genselect((void *) f, gp_callbool, x); case 1: return genindexselect((void *) f, gp_callbool, x); default: pari_err_FLAG("select"); return NULL;/*LCOV_EXCL_LINE*/ } } GEN parselect(GEN C, GEN D, long flag) { pari_sp av, av2; long lv, l = lg(D), i, pending = 0, workid; GEN V, done; struct pari_mt pt; check_callgen1(C, "parselect"); if (!is_vec_t(typ(D))) pari_err_TYPE("parselect",D); V = cgetg(l, t_VECSMALL); av = avma; mt_queue_start_lim(&pt, C, l-1); av2 = avma; for (i=1; i=percent) { long per = (long)(cnt*100./(l-1)); lcnt = cnt; if (per > lper) { err_printf("%ld%% ",per); lper = per; } } } } mt_queue_end(&pt); return V; } GEN gen_parapply(GEN worker, GEN D) { return gen_parapply_percent(worker, D, 0); } GEN parapply(GEN C, GEN D) { pari_sp av = avma; check_callgen1(C, "parapply"); if (!is_vec_t(typ(D))) pari_err_TYPE("parapply",D); return gerepileupto(av, gen_parapply(C, D)); } GEN genfold(void *E, GEN (*f)(void* E, GEN x, GEN y), GEN x) { pari_sp av = avma; GEN z; long i, l = lg(x); if (!is_vec_t(typ(x))|| l==1 ) pari_err_TYPE("fold",x); clone_lock(x); z = gel(x,1); for (i=2; i1) pari_warn(warnmem,"fold"); z = gerepilecopy(av, z); } } clone_unlock_deep(x); return gerepilecopy(av, z); } GEN fold0(GEN f, GEN x) { if (typ(f) != t_CLOSURE || closure_arity(f) < 2) pari_err_TYPE("fold",f); return genfold((void *) f, gp_call2, x); } /*******************************************************************/ /* */ /* SCALAR-MATRIX OPERATIONS */ /* */ /*******************************************************************/ GEN gtomat(GEN x) { long lx, i; GEN y; if (!x) return cgetg(1, t_MAT); switch(typ(x)) { case t_LIST: if (list_typ(x)==t_LIST_MAP) return maptomat(x); x = list_data(x); if (!x) return cgetg(1, t_MAT); /* fall through */ case t_VEC: { lx=lg(x); y=cgetg(lx,t_MAT); if (lx == 1) break; if (typ(gel(x,1)) == t_COL) { long h = lgcols(x); for (i=2; ia4, ell->p); } static GEN _FpJ_add(void *E, GEN P, GEN Q) { struct _FpE *ell=(struct _FpE *) E; return FpJ_add(P, Q, ell->a4, ell->p); } static GEN _FpJ_mul(void *E, GEN P, GEN n) { pari_sp av = avma; struct _FpE *e=(struct _FpE *) E; long s = signe(n); if (!s || signe(gel(P,3))==0) return ellinf_FpJ(); if (s < 0) P = FpJ_neg(P, e->p); if (is_pm1(n)) return s > 0 ? gcopy(P): P; return gerepilecopy(av, gen_pow_i(P, n, e, &_FpJ_dbl, &_FpJ_add)); } GEN FpJ_mul(GEN P, GEN n, GEN a4, GEN p) { struct _FpE E; E.a4= a4; E.p = p; return _FpJ_mul(&E, P, n); } /***********************************************************************/ /** **/ /** FpE **/ /** **/ /***********************************************************************/ /* These functions deal with point over elliptic curves over Fp defined * by an equation of the form y^2=x^3+a4*x+a6. * Most of the time a6 is omitted since it can be recovered from any point * on the curve. */ GEN RgE_to_FpE(GEN x, GEN p) { if (ell_is_inf(x)) return x; retmkvec2(Rg_to_Fp(gel(x,1),p),Rg_to_Fp(gel(x,2),p)); } GEN FpE_to_mod(GEN x, GEN p) { if (ell_is_inf(x)) return x; retmkvec2(Fp_to_mod(gel(x,1),p),Fp_to_mod(gel(x,2),p)); } GEN FpE_changepoint(GEN P, GEN ch, GEN p) { pari_sp av = avma; GEN c, z, u, r, s, t, v, v2, v3; if (ell_is_inf(P)) return P; if (lgefint(p) == 3) { ulong pp = p[2]; z = Fle_changepoint(ZV_to_Flv(P, pp), ZV_to_Flv(ch, pp), pp); return gerepileupto(av, Flv_to_ZV(z)); } u = gel(ch,1); r = gel(ch,2); s = gel(ch,3); t = gel(ch,4); v = Fp_inv(u, p); v2 = Fp_sqr(v,p); v3 = Fp_mul(v,v2,p); c = Fp_sub(gel(P,1),r,p); z = cgetg(3,t_VEC); gel(z,1) = Fp_mul(v2, c, p); gel(z,2) = Fp_mul(v3, Fp_sub(gel(P,2), Fp_add(Fp_mul(s,c, p),t, p),p),p); return gerepileupto(av, z); } GEN FpE_changepointinv(GEN P, GEN ch, GEN p) { GEN u, r, s, t, u2, u3, c, z; if (ell_is_inf(P)) return P; if (lgefint(p) == 3) { ulong pp = p[2]; z = Fle_changepointinv(ZV_to_Flv(P, pp), ZV_to_Flv(ch, pp), pp); return Flv_to_ZV(z); } u = gel(ch,1); r = gel(ch,2); s = gel(ch,3); t = gel(ch,4); u2 = Fp_sqr(u, p); u3 = Fp_mul(u,u2,p); c = Fp_mul(u2, gel(P,1), p); z = cgetg(3, t_VEC); gel(z,1) = Fp_add(c,r,p); gel(z,2) = Fp_add(Fp_mul(u3,gel(P,2),p), Fp_add(Fp_mul(s,c,p), t, p), p); return z; } static GEN random_nonsquare_Fp(GEN p) { pari_sp av = avma; GEN a; switch(mod8(p)) { /* easy special cases */ case 3: case 5: return gen_2; case 7: return subiu(p, 1); } do { set_avma(av); a = randomi(p); } while (kronecker(a, p) >= 0); return a; } void Fp_elltwist(GEN a4, GEN a6, GEN p, GEN *pt_a4, GEN *pt_a6) { GEN d = random_nonsquare_Fp(p), d2 = Fp_sqr(d, p), d3 = Fp_mul(d2, d, p); *pt_a4 = Fp_mul(a4, d2, p); *pt_a6 = Fp_mul(a6, d3, p); } static GEN FpE_dbl_slope(GEN P, GEN a4, GEN p, GEN *slope) { GEN x, y, Q; if (ell_is_inf(P) || !signe(gel(P,2))) return ellinf(); x = gel(P,1); y = gel(P,2); *slope = Fp_div(Fp_add(Fp_mulu(Fp_sqr(x,p), 3, p), a4, p), Fp_mulu(y, 2, p), p); Q = cgetg(3,t_VEC); gel(Q, 1) = Fp_sub(Fp_sqr(*slope, p), Fp_mulu(x, 2, p), p); gel(Q, 2) = Fp_sub(Fp_mul(*slope, Fp_sub(x, gel(Q, 1), p), p), y, p); return Q; } GEN FpE_dbl(GEN P, GEN a4, GEN p) { pari_sp av = avma; GEN slope; return gerepileupto(av, FpE_dbl_slope(P,a4,p,&slope)); } static GEN FpE_add_slope(GEN P, GEN Q, GEN a4, GEN p, GEN *slope) { GEN Px, Py, Qx, Qy, R; if (ell_is_inf(P)) return Q; if (ell_is_inf(Q)) return P; Px = gel(P,1); Py = gel(P,2); Qx = gel(Q,1); Qy = gel(Q,2); if (equalii(Px, Qx)) { if (equalii(Py, Qy)) return FpE_dbl_slope(P, a4, p, slope); else return ellinf(); } *slope = Fp_div(Fp_sub(Py, Qy, p), Fp_sub(Px, Qx, p), p); R = cgetg(3,t_VEC); gel(R, 1) = Fp_sub(Fp_sub(Fp_sqr(*slope, p), Px, p), Qx, p); gel(R, 2) = Fp_sub(Fp_mul(*slope, Fp_sub(Px, gel(R, 1), p), p), Py, p); return R; } GEN FpE_add(GEN P, GEN Q, GEN a4, GEN p) { pari_sp av = avma; GEN slope; return gerepileupto(av, FpE_add_slope(P,Q,a4,p,&slope)); } static GEN FpE_neg_i(GEN P, GEN p) { if (ell_is_inf(P)) return P; return mkvec2(gel(P,1), Fp_neg(gel(P,2), p)); } GEN FpE_neg(GEN P, GEN p) { if (ell_is_inf(P)) return ellinf(); return mkvec2(gcopy(gel(P,1)), Fp_neg(gel(P,2), p)); } GEN FpE_sub(GEN P, GEN Q, GEN a4, GEN p) { pari_sp av = avma; GEN slope; return gerepileupto(av, FpE_add_slope(P, FpE_neg_i(Q, p), a4, p, &slope)); } 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); GEN Q; 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; if (equalis(n,2)) return _FpE_dbl(E, P); Q = gen_pow_i(FpE_to_FpJ(P), n, e, &_FpJ_dbl, &_FpJ_add); return gerepileupto(av, FpJ_to_FpE(Q, e->p)); } 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 nonsingular point on E */ GEN random_FpE(GEN a4, GEN a6, GEN p) { pari_sp ltop = avma; GEN x, x2, y, rhs; do { set_avma(ltop); x = randomi(p); /* x^3+a4*x+a6 = x*(x^2+a4)+a6 */ x2 = Fp_sqr(x, p); rhs = Fp_add(Fp_mul(x, Fp_add(x2, a4, p), p), a6, p); } while ((!signe(rhs) && !signe(Fp_add(Fp_mulu(x2,3,p),a4,p))) || kronecker(rhs, p) < 0); y = Fp_sqrt(rhs, p); if (!y) pari_err_PRIME("random_FpE", p); return gerepilecopy(ltop, mkvec2(x, y)); } static GEN _FpE_rand(void *E) { struct _FpE *e=(struct _FpE *) E; return random_FpE(e->a4, e->a6, e->p); } static const struct bb_group FpE_group={_FpE_add,_FpE_mul,_FpE_rand,hash_GEN,ZV_equal,ell_is_inf,NULL}; const struct bb_group * get_FpE_group(void ** pt_E, GEN a4, GEN a6, GEN p) { struct _FpE *e = (struct _FpE *) stack_malloc(sizeof(struct _FpE)); e->a4 = a4; e->a6 = a6; e->p = p; *pt_E = (void *) e; return &FpE_group; } GEN FpE_order(GEN z, GEN o, GEN a4, GEN p) { pari_sp av = avma; struct _FpE e; GEN r; if (lgefint(p) == 3) { ulong pp = p[2]; r = Fle_order(ZV_to_Flv(z, pp), o, umodiu(a4,pp), pp); } else { e.a4 = a4; e.p = p; r = gen_order(z, o, (void*)&e, &FpE_group); } return gerepileuptoint(av, r); } GEN FpE_log(GEN a, GEN b, GEN o, GEN a4, GEN p) { pari_sp av = avma; struct _FpE e; GEN r; if (lgefint(p) == 3) { ulong pp = p[2]; r = Fle_log(ZV_to_Flv(a,pp), ZV_to_Flv(b,pp), o, umodiu(a4,pp), pp); } else { e.a4 = a4; e.p = p; r = gen_PH_log(a, b, o, (void*)&e, &FpE_group); } return gerepileuptoint(av, r); } /***********************************************************************/ /** **/ /** Pairings **/ /** **/ /***********************************************************************/ /* Derived from APIP from and by Jerome Milan, 2012 */ static GEN FpE_vert(GEN P, GEN Q, GEN a4, GEN p) { if (ell_is_inf(P)) return gen_1; if (!equalii(gel(Q, 1), gel(P, 1))) return Fp_sub(gel(Q, 1), gel(P, 1), p); if (signe(gel(P,2))!=0) return gen_1; return Fp_inv(Fp_add(Fp_mulu(Fp_sqr(gel(P,1),p), 3, p), a4, p), p); } static GEN FpE_Miller_line(GEN R, GEN Q, GEN slope, GEN a4, GEN p) { GEN x = gel(Q, 1), y = gel(Q, 2); GEN tmp1 = Fp_sub(x, gel(R, 1), p); GEN tmp2 = Fp_add(Fp_mul(tmp1, slope, p), gel(R,2), p); if (!equalii(y, tmp2)) return Fp_sub(y, tmp2, p); if (signe(y) == 0) return gen_1; else { GEN s1, s2; GEN y2i = Fp_inv(Fp_mulu(y, 2, p), p); s1 = Fp_mul(Fp_add(Fp_mulu(Fp_sqr(x, p), 3, p), a4, p), y2i, p); if (!equalii(s1, slope)) return Fp_sub(s1, slope, p); s2 = Fp_mul(Fp_sub(Fp_mulu(x, 3, p), Fp_sqr(s1, p), p), y2i, p); return signe(s2)!=0 ? s2: y2i; } } /* Computes the equation of the line tangent to R and returns its evaluation at the point Q. Also doubles the point R. */ static GEN FpE_tangent_update(GEN R, GEN Q, GEN a4, GEN p, GEN *pt_R) { if (ell_is_inf(R)) { *pt_R = ellinf(); return gen_1; } else if (signe(gel(R,2)) == 0) { *pt_R = ellinf(); return FpE_vert(R, Q, a4, p); } else { GEN slope; *pt_R = FpE_dbl_slope(R, a4, p, &slope); return FpE_Miller_line(R, Q, slope, a4, p); } } /* Computes the equation of the line through R and P, and returns its evaluation at the point Q. Also adds P to the point R. */ static GEN FpE_chord_update(GEN R, GEN P, GEN Q, GEN a4, GEN p, GEN *pt_R) { if (ell_is_inf(R)) { *pt_R = gcopy(P); return FpE_vert(P, Q, a4, p); } else if (ell_is_inf(P)) { *pt_R = gcopy(R); return FpE_vert(R, Q, a4, p); } else if (equalii(gel(P, 1), gel(R, 1))) { if (equalii(gel(P, 2), gel(R, 2))) return FpE_tangent_update(R, Q, a4, p, pt_R); else { *pt_R = ellinf(); return FpE_vert(R, Q, a4, p); } } else { GEN slope; *pt_R = FpE_add_slope(P, R, a4, p, &slope); return FpE_Miller_line(R, Q, slope, a4, p); } } struct _FpE_miller { GEN p, a4, P; }; static GEN FpE_Miller_dbl(void* E, GEN d) { struct _FpE_miller *m = (struct _FpE_miller *)E; GEN p = m->p, a4 = m->a4, P = m->P; GEN v, line; GEN N = Fp_sqr(gel(d,1), p); GEN D = Fp_sqr(gel(d,2), p); GEN point = gel(d,3); line = FpE_tangent_update(point, P, a4, p, &point); N = Fp_mul(N, line, p); v = FpE_vert(point, P, a4, p); D = Fp_mul(D, v, p); return mkvec3(N, D, point); } static GEN FpE_Miller_add(void* E, GEN va, GEN vb) { struct _FpE_miller *m = (struct _FpE_miller *)E; GEN p = m->p, a4= m->a4, P = m->P; GEN v, line, point; GEN na = gel(va,1), da = gel(va,2), pa = gel(va,3); GEN nb = gel(vb,1), db = gel(vb,2), pb = gel(vb,3); GEN N = Fp_mul(na, nb, p); GEN D = Fp_mul(da, db, p); line = FpE_chord_update(pa, pb, P, a4, p, &point); N = Fp_mul(N, line, p); v = FpE_vert(point, P, a4, p); D = Fp_mul(D, v, p); return mkvec3(N, D, point); } /* Returns the Miller function f_{m, Q} evaluated at the point P using * the standard Miller algorithm. */ static GEN FpE_Miller(GEN Q, GEN P, GEN m, GEN a4, GEN p) { pari_sp av = avma; struct _FpE_miller d; GEN v, N, D; d.a4 = a4; d.p = p; d.P = P; v = gen_pow_i(mkvec3(gen_1,gen_1,Q), m, (void*)&d, FpE_Miller_dbl, FpE_Miller_add); N = gel(v,1); D = gel(v,2); return gerepileuptoint(av, Fp_div(N, D, p)); } GEN FpE_weilpairing(GEN P, GEN Q, GEN m, GEN a4, GEN p) { pari_sp av = avma; GEN N, D, w; if (ell_is_inf(P) || ell_is_inf(Q) || ZV_equal(P,Q)) return gen_1; if (lgefint(p)==3 && lgefint(m)==3) { ulong pp = p[2]; GEN Pp = ZV_to_Flv(P, pp), Qp = ZV_to_Flv(Q, pp); ulong w = Fle_weilpairing(Pp, Qp, itou(m), umodiu(a4, pp), pp); return gc_utoi(av, w); } N = FpE_Miller(P, Q, m, a4, p); D = FpE_Miller(Q, P, m, a4, p); w = Fp_div(N, D, p); if (mpodd(m)) w = Fp_neg(w, p); return gerepileuptoint(av, w); } GEN FpE_tatepairing(GEN P, GEN Q, GEN m, GEN a4, GEN p) { if (ell_is_inf(P) || ell_is_inf(Q)) return gen_1; if (lgefint(p)==3 && lgefint(m)==3) { pari_sp av = avma; ulong pp = p[2]; GEN Pp = ZV_to_Flv(P, pp), Qp = ZV_to_Flv(Q, pp); ulong w = Fle_tatepairing(Pp, Qp, itou(m), umodiu(a4, pp), pp); return gc_utoi(av,w); } return FpE_Miller(P, Q, m, a4, p); } /***********************************************************************/ /** **/ /** CM by principal order **/ /** **/ /***********************************************************************/ /* is jn/jd = J (mod p) */ static int is_CMj(long J, GEN jn, GEN jd, GEN p) { return dvdii(subii(mulis(jd,J), jn), p); } #ifndef LONG_IS_64BIT /* is jn/jd = -(2^32 a + b) (mod p) */ static int u2_is_CMj(ulong a, ulong b, GEN jn, GEN jd, GEN p) { GEN mJ = uu32toi(a,b); return dvdii(addii(mulii(jd,mJ), jn), p); } #endif static long Fp_ellj_get_CM(GEN jn, GEN jd, GEN p) { #define CHECK(CM,J) if (is_CMj(J,jn,jd,p)) return CM; CHECK(-3, 0); CHECK(-4, 1728); CHECK(-7, -3375); CHECK(-8, 8000); CHECK(-11, -32768); CHECK(-12, 54000); CHECK(-16, 287496); CHECK(-19, -884736); CHECK(-27, -12288000); CHECK(-28, 16581375); CHECK(-43, -884736000); #ifdef LONG_IS_64BIT CHECK(-67, -147197952000L); CHECK(-163, -262537412640768000L); #else if (u2_is_CMj(0x00000022UL,0x45ae8000UL,jn,jd,p)) return -67; if (u2_is_CMj(0x03a4b862UL,0xc4b40000UL,jn,jd,p)) return -163; #endif #undef CHECK return 0; } /***********************************************************************/ /** **/ /** issupersingular **/ /** **/ /***********************************************************************/ /* assume x reduced mod p, monic. Return one root, or NULL if irreducible */ static GEN FqX_quad_root(GEN x, GEN T, GEN p) { GEN b = gel(x,3), c = gel(x,2); GEN D = Fq_sub(Fq_sqr(b, T, p), Fq_mulu(c,4, T, p), T, p); GEN s = Fq_sqrt(D,T, p); if (!s) return NULL; return Fq_halve(Fq_sub(s, b, T, p), T, p); } static GEN FpX_quad_root(GEN x, GEN p) { GEN s, b = gel(x,3), c = gel(x,2); GEN D = Fp_sub(Fp_sqr(b, p), shifti(c,2), p); if (kronecker(D,p) == -1) return NULL; s = Fp_sqrt(D,p); return Fp_halve(Fp_sub(s, b, p), p); } /* * pol is the modular polynomial of level 2 modulo p. * * (T, p) defines the field FF_{p^2} in which j_prev and j live. */ static long Fq_path_extends_to_floor(GEN j_prev, GEN j, GEN T, GEN p, GEN Phi2, long max_len) { pari_sp ltop = avma; long d, i, l = lg(j); /* A path made its way to the floor if (i) its length was cut off * before reaching max_path_len, or (ii) it reached max_path_len but * only has one neighbour. */ for (d = 1; d <= max_len; ++d) { for (i = 1; i < l; i++) { GEN Phi2_j = FqX_div_by_X_x(FqXY_evalx(Phi2, gel(j,i), T, p), gel(j_prev,i), T, p, NULL); GEN j_next = FqX_quad_root(Phi2_j, T, p); if (!j_next) return gc_long(ltop, 1); gel(j_prev,i) = gel(j, i); gel(j,i) = j_next; } if (gc_needed(ltop, 2)) gerepileall(ltop, 2, &j, &j_prev); } return gc_long(ltop, 0); } static long Fp_path_extends_to_floor(GEN j_prev, GEN j, GEN p, GEN Phi2, long max_len, GEN *pt_j, GEN *pt_j_prev) { pari_sp ltop = avma; long d, i, l = lg(j); /* A path made its way to the floor if (i) its length was cut off * before reaching max_path_len, or (ii) it reached max_path_len but * only has one neighbour. */ for (d = 1; d <= max_len; ++d) { for (i = 1; i < l; i++) { GEN Phi2_j = FpX_div_by_X_x(FpXY_evalx(Phi2, gel(j,i), p), gel(j_prev,i), p, NULL); GEN j_next = FpX_quad_root(Phi2_j, p); if (!j_next) { *pt_j = gel(j,i); *pt_j_prev = gel(j_prev,i); return 1; } gel(j_prev,i) = gel(j, i); gel(j,i) = j_next; } if (gc_needed(ltop, 2)) gerepileall(ltop, 2, &j, &j_prev); } return gc_long(ltop, 0); } static int Fp_jissupersingular(GEN j, GEN p) { long max_path_len = expi(p)+1; GEN Phi2 = FpXX_red(polmodular_ZXX(2,0,0,1), p); GEN Phi2_j = FpXY_evalx(Phi2, j, p); GEN roots = FpX_roots(Phi2_j, p); long nbroots = lg(roots)-1; GEN S, j_prev = NULL; /* Every node in a supersingular L-volcano has L + 1 neighbours. */ /* Note: a multiple root only occur when j has CM by sqrt(-15). */ if (nbroots==0) return 0; S = deg2pol_shallow(gen_1, gen_0, Fp_neg(Fp_2gener(p),p),1); if (nbroots==1 && FpX_is_squarefree(Phi2_j, p)) { j_prev = j; j = FqX_quad_root(FpX_div_by_X_x(Phi2_j, gel(roots,1), p, NULL), S, p); } else if (!Fp_path_extends_to_floor(const_vec(nbroots,j), roots, p, Phi2, max_path_len, &j, &j_prev)) return 1; return !Fq_path_extends_to_floor(mkvec(j_prev), mkvec(j), S, p, Phi2, max_path_len); } static int jissupersingular(GEN j, GEN S, GEN p) { long max_path_len = expi(p)+1; GEN Phi2 = FpXX_red(polmodular_ZXX(2,0,0,1), p); GEN Phi2_j = FqXY_evalx(Phi2, j, S, p); GEN roots = FpXQX_roots(Phi2_j, S, p); long nbroots = lg(roots)-1; /* Every node in a supersingular L-volcano has L + 1 neighbours. */ /* Note: a multiple root only occur when j has CM by sqrt(-15). */ if (nbroots==0 || (nbroots==1 && FqX_is_squarefree(Phi2_j, S, p))) return 0; else return !Fq_path_extends_to_floor(const_vec(nbroots,j), roots, S, p, Phi2, max_path_len); } int Fp_elljissupersingular(GEN j, GEN p) { long CM; if (abscmpiu(p, 5) <= 0) return signe(j) == 0; /* valid if p <= 5 */ CM = Fp_ellj_get_CM(j, gen_1, p); if (CM < 0) return krosi(CM, p) < 0; /* valid if p > 3 */ else return Fp_jissupersingular(j, p); } /***********************************************************************/ /** **/ /** Cardinal **/ /** **/ /***********************************************************************/ /*assume a4,a6 reduced mod p odd */ static ulong Fl_elltrace_naive(ulong a4, ulong a6, ulong p) { ulong i, j; long a = 0; long d0, d1, d2, d3; GEN k = const_vecsmall(p, -1); k[1] = 0; for (i=1, j=1; i < p; i += 2, j = Fl_add(j, i, p)) k[j+1] = 1; d0 = 6%p; d1 = d0; d2 = Fl_add(a4, 1, p); d3 = a6; for(i=0;; i++) { a -= k[1+d3]; if (i==p-1) break; d3 = Fl_add(d3, d2, p); d2 = Fl_add(d2, d1, p); d1 = Fl_add(d1, d0, p); } return a; } /* z1 <-- z1 + z2, with precomputed inverse */ static void FpE_add_ip(GEN z1, GEN z2, GEN a4, GEN p, GEN p2inv) { GEN p1,x,x1,x2,y,y1,y2; x1 = gel(z1,1); y1 = gel(z1,2); x2 = gel(z2,1); y2 = gel(z2,2); if (x1 == x2) p1 = Fp_add(a4, mulii(x1,mului(3,x1)), p); else p1 = Fp_sub(y2,y1, p); p1 = Fp_mul(p1, p2inv, p); x = Fp_sub(sqri(p1), addii(x1,x2), p); y = Fp_sub(mulii(p1,subii(x1,x)), y1, p); affii(x, x1); affii(y, y1); } /* make sure *x has lgefint >= 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 c */ static GEN closest_lift(GEN a, GEN b, GEN c) { return addii(a, mulii(b, diviiround(subii(c,a), b))); } static long get_table_size(GEN pordmin, GEN B) { pari_sp av = avma; GEN t = ceilr( sqrtr( divri(itor(pordmin, DEFAULTPREC), B) ) ); if (is_bigint(t)) pari_err_OVERFLOW("ellap [large prime: install the 'seadata' package]"); set_avma(av); return itos(t) >> 1; } /* Find x such that kronecker(u = x^3+c4x+c6, p) is KRO. * Return point [x*u,u^2] on E (KRO=1) / E^twist (KRO=-1) */ static GEN Fp_ellpoint(long KRO, ulong *px, GEN c4, GEN c6, GEN p) { ulong x = *px; GEN u; for(;;) { x++; /* u = x^3 + c4 x + c6 */ u = modii(addii(c6, mului(x, addii(c4, sqru(x)))), p); if (kronecker(u,p) == KRO) break; } *px = x; return mkvec2(modii(mului(x,u),p), Fp_sqr(u,p)); } static GEN Fl_ellpoint(long KRO, ulong *px, ulong c4, ulong c6, ulong p) { ulong t, u, x = *px; for(;;) { if (++x >= p) pari_err_PRIME("ellap",utoi(p)); t = Fl_add(c4, Fl_sqr(x,p), p); u = Fl_add(c6, Fl_mul(x, t, p), p); if (krouu(u,p) == KRO) break; } *px = x; return mkvecsmall2(Fl_mul(x,u,p), Fl_sqr(u,p)); } static GEN ap_j1728(GEN a4,GEN p); /* compute a_p using Shanks/Mestre + Montgomery's trick. Assume p > 457 */ static GEN Fp_ellcard_Shanks(GEN c4, GEN c6, GEN p) { pari_timer T; long *tx, *ty, *ti, pfinal, i, j, s, KRO, nb; ulong x; pari_sp av = avma, av2; GEN p1, P, mfh, h, F,f, fh,fg, pordmin, u, v, p1p, p2p, A, B, a4, pts; tx = NULL; ty = ti = NULL; /* gcc -Wall */ if (!signe(c6)) { GEN ap = ap_j1728(c4, p); return gerepileuptoint(av, subii(addiu(p,1), ap)); } if (DEBUGLEVEL >= 6) timer_start(&T); /* once #E(Fp) is know mod B >= pordmin, it is completely determined */ pordmin = addiu(sqrti(gmul2n(p,4)), 1); /* ceil( 4sqrt(p) ) */ p1p = addiu(p, 1); p2p = shifti(p1p, 1); x = 0; KRO = 0; /* 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 */ } for(;;) { h = closest_lift(A, B, p1p); if (!KRO) /* first time, initialize */ { KRO = kronecker(c6,p); f = mkvec2(gen_0, Fp_sqr(c6,p)); } else { KRO = -KRO; f = Fp_ellpoint(KRO, &x, c4,c6,p); } /* [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) */ 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); /* 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 = evaltyp(t_VECSMALL) | evallg(s+1); /* 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)); } set_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 >= 6) timer_printf(&T, "[Fp_ellcard_Shanks] baby steps, s = %ld",s); /* giant steps: fg = s.F */ fg = FpE_add(P,F,a4,p); if (ell_is_inf(fg)) { h = mului(s,B); goto FOUND; } pfinal = mod2BIL(p); av2 = avma; /* Goal of the following: sort points by increasing x-coordinate hash. * Done in a complicated way to avoid allocating a large temp vector */ p1 = vecsmall_indexsort(tx); /* = permutation sorting tx */ for (i=1; i<=s; i++) ti[i] = tx[p1[i]]; /* ti = tx sorted */ for (i=1; i<=s; i++) { tx[i] = ti[i]; ti[i] = ty[p1[i]]; } /* tx is sorted. ti = ty sorted */ for (i=1; i<=s; i++) { ty[i] = ti[i]; ti[i] = p1[i]; } /* ty is sorted. ti = permutation sorting tx */ if (DEBUGLEVEL >= 6) timer_printf(&T, "[Fp_ellcard_Shanks] sorting"); set_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 */ set_avma(av2); fg = gcopy(gel(pts,nb)); /* copy: we modify (temporarily) pts[nb] below */ av2 = avma; for (i=1,j=1; ; i++) { GEN ftest = gel(pts,j); long m, l = 1, r = s+1; long k, k2, j2; set_avma(av2); k = mod2BIL(gel(ftest,1)); while (l < r) { m = (l+r) >> 1; if (tx[m] < k) l = m+1; else r = m; } if (r <= s && tx[r] == k) { while (r && tx[r] == k) r--; k2 = mod2BIL(gel(ftest,2)); for (r++; r <= s && tx[r] == k; r++) if (ty[r] == k2 || ty[r] == pfinal - k2) { /* [h+j2] f == +/- ftest (= [i.s] f)? */ j2 = ti[r] - 1; if (DEBUGLEVEL >=6) timer_printf(&T, "[Fp_ellcard_Shanks] giant steps, i = %ld",i); P = FpE_add(FpE_mul(F,stoi(j2),a4,p),fh,a4,p); if (equalii(gel(P,1), gel(ftest,1))) { if (equalii(gel(P,2), gel(ftest,2))) i = -i; h = addii(h, mulii(addis(mulss(s,i), j2), B)); goto FOUND; } } } if (++j > nb) { /* compute next nb points */ long save = 0; /* gcc -Wall */; for (j=1; j<=nb; j++) { P = gel(pts,j); gel(u,j) = subii(gel(fg,1), gel(P,1)); if (gel(u,j) == gen_0) /* occurs once: i = j = nb, P == fg */ { gel(u,j) = shifti(gel(P,2),1); save = fg[1]; fg[1] = P[1]; } } v = FpV_inv(u, p); for (j=1; j<=nb; j++) FpE_add_ip(gel(pts,j),fg,a4,p, gel(v,j)); if (i == nb) { fg[1] = save; } j = 1; } } FOUND: /* found a point of exponent h on E_u */ h = FpE_order(f, h, a4, p); /* h | #E_u(Fp) = A (mod B) */ A = Z_chinese_all(A, gen_0, B, h, &B); if (cmpii(B, pordmin) >= 0) break; /* not done: update A mod B for the _next_ curve, isomorphic to * the quadratic twist of this one */ A = remii(subii(p2p,A), B); /* #E(Fp)+#E'(Fp) = 2p+2 */ } if (tx) killblock(tx); h = closest_lift(A, B, p1p); return gerepileuptoint(av, KRO==1? h: subii(p2p,h)); } typedef struct { ulong x,y,i; } multiple; static int compare_multiples(multiple *a, multiple *b) { return a->x > b->x? 1:a->xx?-1:0; } /* find x such that h := a + b x is closest to c and return h: * x = round((c-a) / b) = floor( (2(c-a) + b) / 2b ) * Assume 0 <= a < b < c and b + 2c < 2^BIL */ static ulong uclosest_lift(ulong a, ulong b, ulong c) { ulong x = (b + ((c-a) << 1)) / (b << 1); return a + b * x; } static long Fle_dbl_inplace(GEN P, ulong a4, ulong p) { ulong x, y, slope; if (!P[2]) return 1; x = P[1]; y = P[2]; slope = Fl_div(Fl_add(Fl_triple(Fl_sqr(x,p), p), a4, p), Fl_double(y, p), p); P[1] = Fl_sub(Fl_sqr(slope, p), Fl_double(x, p), p); P[2] = Fl_sub(Fl_mul(slope, Fl_sub(x, P[1], p), p), y, p); return 0; } static long Fle_add_inplace(GEN P, GEN Q, ulong a4, ulong p) { ulong Px, Py, Qx, Qy, slope; if (ell_is_inf(Q)) return 0; Px = P[1]; Py = P[2]; Qx = Q[1]; Qy = Q[2]; if (Px==Qx) return Py==Qy ? Fle_dbl_inplace(P, a4, p): 1; slope = Fl_div(Fl_sub(Py, Qy, p), Fl_sub(Px, Qx, p), p); P[1] = Fl_sub(Fl_sub(Fl_sqr(slope, p), Px, p), Qx, p); P[2] = Fl_sub(Fl_mul(slope, Fl_sub(Px, P[1], p), p), Py, p); return 0; } /* assume 99 < p < 2^(BIL-1) - 2^((BIL+1)/2) and e has good reduction at p. * Should use Barett reduction + multi-inverse. See Fp_ellcard_Shanks() */ static long Fl_ellcard_Shanks(ulong c4, ulong c6, ulong p) { GEN f, fh, fg, ftest, F; ulong i, l, r, s, h, x, cp4, p1p, p2p, pordmin,A,B; long KRO; pari_sp av = avma; multiple *table; if (!c6) { GEN ap = ap_j1728(utoi(c4), utoipos(p)); return gc_long(av, p+1 - itos(ap)); } pordmin = (ulong)(1 + 4*sqrt((double)p)); p1p = p+1; p2p = p1p << 1; x = 0; KRO = 0; switch(Flx_nbroots(mkvecsmall5(0L, c6,c4,0L,1L), p)) { case 3: A = 0; B = 4; break; case 1: A = 0; B = 2; break; default: A = 1; B = 2; break; /* 0 */ } for(;;) { /* see comments in Fp_ellcard_Shanks */ h = uclosest_lift(A, B, p1p); if (!KRO) /* first time, initialize */ { KRO = krouu(c6,p); /* != 0 */ f = mkvecsmall2(0, Fl_sqr(c6,p)); } else { KRO = -KRO; f = Fl_ellpoint(KRO, &x, c4,c6,p); } cp4 = Fl_mul(c4, f[2], p); fh = Fle_mulu(f, h, cp4, p); if (ell_is_inf(fh)) goto FOUND; s = (ulong) (sqrt(((double)pordmin)/B) / 2); if (!s) s = 1; table = (multiple *) stack_malloc((s+1) * sizeof(multiple)); F = Fle_mulu(f, B, cp4, p); for (i=0; i < s; i++) { table[i].x = fh[1]; table[i].y = fh[2]; table[i].i = i; if (Fle_add_inplace(fh, F, cp4, p)) { h += B*(i+1); goto FOUND; } } qsort(table,s,sizeof(multiple),(QSCOMP)compare_multiples); fg = Fle_mulu(F, s, cp4, p); ftest = zv_copy(fg); if (ell_is_inf(ftest)) { if (!uisprime(p)) pari_err_PRIME("ellap",utoi(p)); pari_err_BUG("ellap (f^(i*s) = 1)"); } for (i=1; ; i++) { l=0; r=s; while (l> 1; if (table[m].x < uel(ftest,1)) l=m+1; else r=m; } if (r < s && table[r].x == uel(ftest,1)) break; if (Fle_add_inplace(ftest, fg, cp4, p)) pari_err_PRIME("ellap",utoi(p)); } h += table[r].i * B; if (table[r].y == uel(ftest,2)) h -= s * i * B; else h += s * i * B; FOUND: h = itou(Fle_order(f, utoipos(h), cp4, p)); /* h | #E_u(Fp) = A (mod B) */ { GEN C; A = itou( Z_chinese_all(gen_0, utoi(A), utoipos(h), utoipos(B), &C) ); if (abscmpiu(C, pordmin) >= 0) { /* uclosest_lift could overflow */ h = itou( closest_lift(utoi(A), C, utoipos(p1p)) ); break; } B = itou(C); } A = (p2p - A) % B; set_avma(av); } return gc_long(av, KRO==1? h: p2p-h); } /** ellap from CM (original code contributed by Mark Watkins) **/ static GEN ap_j0(GEN a6,GEN p) { GEN a, b, e, d; if (umodiu(p,3) != 1) return gen_0; (void)cornacchia2(utoipos(27),p, &a,&b); if (umodiu(a, 3) == 1) a = negi(a); d = mulis(a6,-108); e = diviuexact(shifti(p,-1), 3); /* (p-1) / 6 */ return centermod(mulii(a, Fp_pow(d, e, p)), p); } static GEN ap_j1728(GEN a4,GEN p) { GEN a, b, e; if (mod4(p) != 1) return gen_0; (void)cornacchia2(utoipos(4),p, &a,&b); if (Mod4(a)==0) a = b; if (Mod2(a)==1) a = shifti(a,1); if (Mod8(a)==6) a = negi(a); e = shifti(p,-2); /* (p-1) / 4 */ return centermod(mulii(a, Fp_pow(a4, e, p)), p); } static GEN ap_j8000(GEN a6, GEN p) { GEN a, b; long r = mod8(p), s = 1; if (r != 1 && r != 3) return gen_0; (void)cornacchia2(utoipos(8),p, &a,&b); switch(Mod16(a)) { case 2: case 6: if (Mod4(b)) s = -s; break; case 10: case 14: if (!Mod4(b)) s = -s; break; } if (kronecker(mulis(a6, 42), p) < 0) s = -s; return s > 0? a: negi(a); } static GEN ap_j287496(GEN a6, GEN p) { GEN a, b; long s = 1; if (mod4(p) != 1) return gen_0; (void)cornacchia2(utoipos(4),p, &a,&b); if (Mod4(a)==0) a = b; if (Mod2(a)==1) a = shifti(a,1); if (Mod8(a)==6) s = -s; if (krosi(2,p) < 0) s = -s; if (kronecker(mulis(a6, -14), p) < 0) s = -s; return s > 0? a: negi(a); } static GEN ap_cm(int CM, long A6B, GEN a6, GEN p) { GEN a, b; long s = 1; if (krosi(CM,p) < 0) return gen_0; (void)cornacchia2(utoipos(-CM),p, &a, &b); if ((CM&3) == 0) CM >>= 2; if ((krois(a, -CM) > 0) ^ (CM == -7)) s = -s; if (kronecker(mulis(a6,A6B), p) < 0) s = -s; return s > 0? a: negi(a); } static GEN ec_ap_cm(int CM, GEN a4, GEN a6, GEN p) { switch(CM) { case -3: return ap_j0(a6, p); case -4: return ap_j1728(a4, p); case -8: return ap_j8000(a6, p); case -16: return ap_j287496(a6, p); case -7: return ap_cm(CM, -2, a6, p); case -11: return ap_cm(CM, 21, a6, p); case -12: return ap_cm(CM, 22, a6, p); case -19: return ap_cm(CM, 1, a6, p); case -27: return ap_cm(CM, 253, a6, p); case -28: return ap_cm(-7, -114, a6, p); /* yes, -7 ! */ case -43: return ap_cm(CM, 21, a6, p); case -67: return ap_cm(CM, 217, a6, p); case -163:return ap_cm(CM, 185801, a6, p); default: return NULL; } } static GEN Fp_ellj_nodiv(GEN a4, GEN a6, GEN p) { GEN a43 = Fp_mulu(Fp_powu(a4, 3, p), 4, p); GEN a62 = Fp_mulu(Fp_sqr(a6, p), 27, p); return mkvec2(Fp_mulu(a43, 1728, p), Fp_add(a43, a62, p)); } GEN Fp_ellj(GEN a4, GEN a6, GEN p) { pari_sp av = avma; GEN z; if (lgefint(p) == 3) { ulong pp = p[2]; return utoi(Fl_ellj(umodiu(a4,pp), umodiu(a6,pp), pp)); } z = Fp_ellj_nodiv(a4, a6, p); return gerepileuptoint(av,Fp_div(gel(z,1),gel(z,2),p)); } void Fp_ellj_to_a4a6(GEN j, GEN p, GEN *pt_a4, GEN *pt_a6) { j = modii(j, p); if (signe(j) == 0) { *pt_a4 = gen_0; *pt_a6 = gen_1; } else if (equaliu(j,umodui(1728,p))) { *pt_a4 = gen_1; *pt_a6 = gen_0; } else { GEN k = Fp_sub(utoi(1728), j, p); GEN kj = Fp_mul(k, j, p); GEN k2j = Fp_mul(kj, k, p); *pt_a4 = Fp_mulu(kj, 3, p); *pt_a6 = Fp_double(k2j, p); } } static GEN /* Only compute a mod p, so assume p>=17 */ Fp_ellcard_CM(GEN a4, GEN a6, GEN p) { pari_sp av = avma; GEN a; if (!signe(a4)) a = ap_j0(a6,p); else if (!signe(a6)) a = ap_j1728(a4,p); else { GEN j = Fp_ellj_nodiv(a4, a6, p); long CM = Fp_ellj_get_CM(gel(j,1), gel(j,2), p); if (!CM) return gc_NULL(av); a = ec_ap_cm(CM,a4,a6,p); } return gerepileuptoint(av, subii(addiu(p,1),a)); } GEN Fp_ellcard(GEN a4, GEN a6, GEN p) { long lp = expi(p); ulong pp = p[2]; if (lp < 11) return utoi(pp+1 - Fl_elltrace_naive(umodiu(a4,pp), umodiu(a6,pp), pp)); { GEN a = Fp_ellcard_CM(a4,a6,p); if (a) return a; } if (lp >= 56) return Fp_ellcard_SEA(a4, a6, p, 0); if (lp <= BITS_IN_LONG-2) return utoi(Fl_ellcard_Shanks(umodiu(a4,pp), umodiu(a6,pp), pp)); return Fp_ellcard_Shanks(a4, a6, p); } long Fl_elltrace(ulong a4, ulong a6, ulong p) { pari_sp av; long lp; GEN a; if (p < (1<<11)) return Fl_elltrace_naive(a4, a6, p); lp = expu(p); if (lp <= minss(56, BITS_IN_LONG-2)) return p+1-Fl_ellcard_Shanks(a4, a6, p); av = avma; a = subui(p+1, Fp_ellcard(utoi(a4), utoi(a6), utoipos(p))); return gc_long(av, itos(a)); } long Fl_elltrace_CM(long CM, ulong a4, ulong a6, ulong p) { pari_sp av; GEN a; if (!CM) return Fl_elltrace(a4,a6,p); if (p < (1<<11)) return Fl_elltrace_naive(a4, a6, p); av = avma; a = ec_ap_cm(CM, utoi(a4), utoi(a6), utoipos(p)); return gc_long(av, itos(a)); } static GEN _FpE_pairorder(void *E, GEN P, GEN Q, GEN m, GEN F) { struct _FpE *e = (struct _FpE *) E; return Fp_order(FpE_weilpairing(P,Q,m,e->a4,e->p), F, e->p); } GEN Fp_ellgroup(GEN a4, GEN a6, GEN N, GEN p, GEN *pt_m) { struct _FpE e; e.a4=a4; e.a6=a6; e.p=p; return gen_ellgroup(N, subiu(p,1), pt_m, (void*)&e, &FpE_group, _FpE_pairorder); } GEN Fp_ellgens(GEN a4, GEN a6, GEN ch, GEN D, GEN m, GEN p) { GEN P; pari_sp av = avma; struct _FpE e; e.a4=a4; e.a6=a6; e.p=p; switch(lg(D)-1) { case 1: P = gen_gener(gel(D,1), (void*)&e, &FpE_group); P = mkvec(FpE_changepoint(P, ch, p)); break; default: P = gen_ellgens(gel(D,1), gel(D,2), m, (void*)&e, &FpE_group, _FpE_pairorder); gel(P,1) = FpE_changepoint(gel(P,1), ch, p); gel(P,2) = FpE_changepoint(gel(P,2), ch, p); break; } return gerepilecopy(av, P); } /* Not so fast arithmetic with points over elliptic curves over FpXQ */ /***********************************************************************/ /** **/ /** FpXQE **/ /** **/ /***********************************************************************/ /* Theses functions deal with point over elliptic curves over FpXQ defined * by an equation of the form y^2=x^3+a4*x+a6. * Most of the time a6 is omitted since it can be recovered from any point * on the curve. */ GEN RgE_to_FpXQE(GEN x, GEN T, GEN p) { if (ell_is_inf(x)) return x; retmkvec2(Rg_to_FpXQ(gel(x,1),T,p),Rg_to_FpXQ(gel(x,2),T,p)); } GEN FpXQE_changepoint(GEN x, GEN ch, GEN T, GEN p) { pari_sp av = avma; GEN p1,z,u,r,s,t,v,v2,v3; if (ell_is_inf(x)) return x; u = gel(ch,1); r = gel(ch,2); s = gel(ch,3); t = gel(ch,4); v = FpXQ_inv(u, T, p); v2 = FpXQ_sqr(v, T, p); v3 = FpXQ_mul(v,v2, T, p); p1 = FpX_sub(gel(x,1),r, p); z = cgetg(3,t_VEC); gel(z,1) = FpXQ_mul(v2, p1, T, p); gel(z,2) = FpXQ_mul(v3, FpX_sub(gel(x,2), FpX_add(FpXQ_mul(s,p1, T, p),t, p), p), T, p); return gerepileupto(av, z); } GEN FpXQE_changepointinv(GEN x, GEN ch, GEN T, GEN p) { GEN u, r, s, t, X, Y, u2, u3, u2X, z; if (ell_is_inf(x)) return x; X = gel(x,1); Y = gel(x,2); u = gel(ch,1); r = gel(ch,2); s = gel(ch,3); t = gel(ch,4); u2 = FpXQ_sqr(u, T, p); u3 = FpXQ_mul(u,u2, T, p); u2X = FpXQ_mul(u2,X, T, p); z = cgetg(3, t_VEC); gel(z,1) = FpX_add(u2X,r, p); gel(z,2) = FpX_add(FpXQ_mul(u3,Y, T, p), FpX_add(FpXQ_mul(s,u2X, T, p), t, p), p); return z; } static GEN random_nonsquare_FpXQ(GEN T, GEN p) { pari_sp av = avma; long n = degpol(T), v = varn(T); GEN a; if (odd(n)) { GEN z = cgetg(3, t_POL); z[1] = evalsigne(1) | evalvarn(v); gel(z,2) = random_nonsquare_Fp(p); return z; } do { set_avma(av); a = random_FpX(n, v, p); } while (FpXQ_issquare(a, T, p)); return a; } void FpXQ_elltwist(GEN a4, GEN a6, GEN T, GEN p, GEN *pt_a4, GEN *pt_a6) { GEN d = random_nonsquare_FpXQ(T, p); GEN d2 = FpXQ_sqr(d, T, p), d3 = FpXQ_mul(d2, d, T, p); *pt_a4 = FpXQ_mul(a4, d2, T, p); *pt_a6 = FpXQ_mul(a6, d3, T, p); } static GEN FpXQE_dbl_slope(GEN P, GEN a4, GEN T, GEN p, GEN *slope) { GEN x, y, Q; if (ell_is_inf(P) || !signe(gel(P,2))) return ellinf(); x = gel(P,1); y = gel(P,2); *slope = FpXQ_div(FpX_add(FpX_mulu(FpXQ_sqr(x, T, p), 3, p), a4, p), FpX_mulu(y, 2, p), T, p); Q = cgetg(3,t_VEC); gel(Q, 1) = FpX_sub(FpXQ_sqr(*slope, T, p), FpX_mulu(x, 2, p), p); gel(Q, 2) = FpX_sub(FpXQ_mul(*slope, FpX_sub(x, gel(Q, 1), p), T, p), y, p); return Q; } GEN FpXQE_dbl(GEN P, GEN a4, GEN T, GEN p) { pari_sp av = avma; GEN slope; return gerepileupto(av, FpXQE_dbl_slope(P,a4,T,p,&slope)); } static GEN FpXQE_add_slope(GEN P, GEN Q, GEN a4, GEN T, GEN p, GEN *slope) { GEN Px, Py, Qx, Qy, R; if (ell_is_inf(P)) return Q; if (ell_is_inf(Q)) return P; Px = gel(P,1); Py = gel(P,2); Qx = gel(Q,1); Qy = gel(Q,2); if (ZX_equal(Px, Qx)) { if (ZX_equal(Py, Qy)) return FpXQE_dbl_slope(P, a4, T, p, slope); else return ellinf(); } *slope = FpXQ_div(FpX_sub(Py, Qy, p), FpX_sub(Px, Qx, p), T, p); R = cgetg(3,t_VEC); gel(R, 1) = FpX_sub(FpX_sub(FpXQ_sqr(*slope, T, p), Px, p), Qx, p); gel(R, 2) = FpX_sub(FpXQ_mul(*slope, FpX_sub(Px, gel(R, 1), p), T, p), Py, p); return R; } GEN FpXQE_add(GEN P, GEN Q, GEN a4, GEN T, GEN p) { pari_sp av = avma; GEN slope; return gerepileupto(av, FpXQE_add_slope(P,Q,a4,T,p,&slope)); } static GEN FpXQE_neg_i(GEN P, GEN p) { if (ell_is_inf(P)) return P; return mkvec2(gel(P,1), FpX_neg(gel(P,2), p)); } GEN FpXQE_neg(GEN P, GEN T, GEN p) { (void) T; if (ell_is_inf(P)) return ellinf(); return mkvec2(gcopy(gel(P,1)), FpX_neg(gel(P,2), p)); } GEN FpXQE_sub(GEN P, GEN Q, GEN a4, GEN T, GEN p) { pari_sp av = avma; GEN slope; return gerepileupto(av, FpXQE_add_slope(P, FpXQE_neg_i(Q, p), a4, T, p, &slope)); } struct _FpXQE { GEN a4,a6,T,p; }; static GEN _FpXQE_dbl(void *E, GEN P) { struct _FpXQE *ell = (struct _FpXQE *) E; return FpXQE_dbl(P, ell->a4, ell->T, ell->p); } static GEN _FpXQE_add(void *E, GEN P, GEN Q) { struct _FpXQE *ell=(struct _FpXQE *) E; return FpXQE_add(P, Q, ell->a4, ell->T, ell->p); } static GEN _FpXQE_mul(void *E, GEN P, GEN n) { pari_sp av = avma; struct _FpXQE *e=(struct _FpXQE *) E; long s = signe(n); if (!s || ell_is_inf(P)) return ellinf(); if (s<0) P = FpXQE_neg(P, e->T, e->p); if (is_pm1(n)) return s>0? gcopy(P): P; return gerepilecopy(av, gen_pow_i(P, n, e, &_FpXQE_dbl, &_FpXQE_add)); } GEN FpXQE_mul(GEN P, GEN n, GEN a4, GEN T, GEN p) { struct _FpXQE E; E.a4= a4; E.T = T; E.p = p; return _FpXQE_mul(&E, P, n); } /* Finds a random nonsingular point on E */ GEN random_FpXQE(GEN a4, GEN a6, GEN T, GEN p) { pari_sp ltop = avma; GEN x, x2, y, rhs; long v = get_FpX_var(T), d = get_FpX_degree(T); do { set_avma(ltop); x = random_FpX(d,v,p); /* x^3+a4*x+a6 = x*(x^2+a4)+a6 */ x2 = FpXQ_sqr(x, T, p); rhs = FpX_add(FpXQ_mul(x, FpX_add(x2, a4, p), T, p), a6, p); } while ((!signe(rhs) && !signe(FpX_add(FpX_mulu(x2,3,p), a4, p))) || !FpXQ_issquare(rhs, T, p)); y = FpXQ_sqrt(rhs, T, p); if (!y) pari_err_PRIME("random_FpE", p); return gerepilecopy(ltop, mkvec2(x, y)); } static GEN _FpXQE_rand(void *E) { struct _FpXQE *e=(struct _FpXQE *) E; return random_FpXQE(e->a4, e->a6, e->T, e->p); } static const struct bb_group FpXQE_group={_FpXQE_add,_FpXQE_mul,_FpXQE_rand,hash_GEN,ZXV_equal,ell_is_inf}; const struct bb_group * get_FpXQE_group(void ** pt_E, GEN a4, GEN a6, GEN T, GEN p) { struct _FpXQE *e = (struct _FpXQE *) stack_malloc(sizeof(struct _FpXQE)); e->a4 = a4; e->a6 = a6; e->T = T; e->p = p; *pt_E = (void *) e; return &FpXQE_group; } GEN FpXQE_order(GEN z, GEN o, GEN a4, GEN T, GEN p) { pari_sp av = avma; struct _FpXQE e; e.a4=a4; e.T=T; e.p=p; return gerepileuptoint(av, gen_order(z, o, (void*)&e, &FpXQE_group)); } GEN FpXQE_log(GEN a, GEN b, GEN o, GEN a4, GEN T, GEN p) { pari_sp av = avma; struct _FpXQE e; e.a4=a4; e.T=T; e.p=p; return gerepileuptoint(av, gen_PH_log(a, b, o, (void*)&e, &FpXQE_group)); } /***********************************************************************/ /** **/ /** Pairings **/ /** **/ /***********************************************************************/ /* Derived from APIP from and by Jerome Milan, 2012 */ static GEN FpXQE_vert(GEN P, GEN Q, GEN a4, GEN T, GEN p) { long vT = get_FpX_var(T); if (ell_is_inf(P)) return pol_1(get_FpX_var(T)); if (!ZX_equal(gel(Q, 1), gel(P, 1))) return FpX_sub(gel(Q, 1), gel(P, 1), p); if (signe(gel(P,2))!=0) return pol_1(vT); return FpXQ_inv(FpX_add(FpX_mulu(FpXQ_sqr(gel(P,1), T, p), 3, p), a4, p), T, p); } static GEN FpXQE_Miller_line(GEN R, GEN Q, GEN slope, GEN a4, GEN T, GEN p) { long vT = get_FpX_var(T); GEN x = gel(Q, 1), y = gel(Q, 2); GEN tmp1 = FpX_sub(x, gel(R, 1), p); GEN tmp2 = FpX_add(FpXQ_mul(tmp1, slope, T, p), gel(R, 2), p); if (!ZX_equal(y, tmp2)) return FpX_sub(y, tmp2, p); if (signe(y) == 0) return pol_1(vT); else { GEN s1, s2; GEN y2i = FpXQ_inv(FpX_mulu(y, 2, p), T, p); s1 = FpXQ_mul(FpX_add(FpX_mulu(FpXQ_sqr(x, T, p), 3, p), a4, p), y2i, T, p); if (!ZX_equal(s1, slope)) return FpX_sub(s1, slope, p); s2 = FpXQ_mul(FpX_sub(FpX_mulu(x, 3, p), FpXQ_sqr(s1, T, p), p), y2i, T, p); return signe(s2)!=0 ? s2: y2i; } } /* Computes the equation of the line tangent to R and returns its evaluation at the point Q. Also doubles the point R. */ static GEN FpXQE_tangent_update(GEN R, GEN Q, GEN a4, GEN T, GEN p, GEN *pt_R) { if (ell_is_inf(R)) { *pt_R = ellinf(); return pol_1(get_FpX_var(T)); } else if (!signe(gel(R,2))) { *pt_R = ellinf(); return FpXQE_vert(R, Q, a4, T, p); } else { GEN slope; *pt_R = FpXQE_dbl_slope(R, a4, T, p, &slope); return FpXQE_Miller_line(R, Q, slope, a4, T, p); } } /* Computes the equation of the line through R and P, and returns its evaluation at the point Q. Also adds P to the point R. */ static GEN FpXQE_chord_update(GEN R, GEN P, GEN Q, GEN a4, GEN T, GEN p, GEN *pt_R) { if (ell_is_inf(R)) { *pt_R = gcopy(P); return FpXQE_vert(P, Q, a4, T, p); } else if (ell_is_inf(P)) { *pt_R = gcopy(R); return FpXQE_vert(R, Q, a4, T, p); } else if (ZX_equal(gel(P, 1), gel(R, 1))) { if (ZX_equal(gel(P, 2), gel(R, 2))) return FpXQE_tangent_update(R, Q, a4, T, p, pt_R); else { *pt_R = ellinf(); return FpXQE_vert(R, Q, a4, T, p); } } else { GEN slope; *pt_R = FpXQE_add_slope(P, R, a4, T, p, &slope); return FpXQE_Miller_line(R, Q, slope, a4, T, p); } } struct _FpXQE_miller { GEN p, T, a4, P; }; static GEN FpXQE_Miller_dbl(void* E, GEN d) { struct _FpXQE_miller *m = (struct _FpXQE_miller *)E; GEN p = m->p; GEN T = m->T, a4 = m->a4, P = m->P; GEN v, line; GEN N = FpXQ_sqr(gel(d,1), T, p); GEN D = FpXQ_sqr(gel(d,2), T, p); GEN point = gel(d,3); line = FpXQE_tangent_update(point, P, a4, T, p, &point); N = FpXQ_mul(N, line, T, p); v = FpXQE_vert(point, P, a4, T, p); D = FpXQ_mul(D, v, T, p); return mkvec3(N, D, point); } static GEN FpXQE_Miller_add(void* E, GEN va, GEN vb) { struct _FpXQE_miller *m = (struct _FpXQE_miller *)E; GEN p = m->p; GEN T = m->T, a4 = m->a4, P = m->P; GEN v, line, point; GEN na = gel(va,1), da = gel(va,2), pa = gel(va,3); GEN nb = gel(vb,1), db = gel(vb,2), pb = gel(vb,3); GEN N = FpXQ_mul(na, nb, T, p); GEN D = FpXQ_mul(da, db, T, p); line = FpXQE_chord_update(pa, pb, P, a4, T, p, &point); N = FpXQ_mul(N, line, T, p); v = FpXQE_vert(point, P, a4, T, p); D = FpXQ_mul(D, v, T, p); return mkvec3(N, D, point); } /* Returns the Miller function f_{m, Q} evaluated at the point P using * the standard Miller algorithm. */ static GEN FpXQE_Miller(GEN Q, GEN P, GEN m, GEN a4, GEN T, GEN p) { pari_sp av = avma; struct _FpXQE_miller d; GEN v, N, D, g1; d.a4 = a4; d.T = T; d.p = p; d.P = P; g1 = pol_1(get_FpX_var(T)); v = gen_pow_i(mkvec3(g1,g1,Q), m, (void*)&d, FpXQE_Miller_dbl, FpXQE_Miller_add); N = gel(v,1); D = gel(v,2); return gerepileupto(av, FpXQ_div(N, D, T, p)); } GEN FpXQE_weilpairing(GEN P, GEN Q, GEN m, GEN a4, GEN T, GEN p) { pari_sp av = avma; GEN N, D, w; if (ell_is_inf(P) || ell_is_inf(Q) || ZXV_equal(P,Q)) return pol_1(get_FpX_var(T)); N = FpXQE_Miller(P, Q, m, a4, T, p); D = FpXQE_Miller(Q, P, m, a4, T, p); w = FpXQ_div(N, D, T, p); if (mpodd(m)) w = FpX_neg(w, p); return gerepileupto(av, w); } GEN FpXQE_tatepairing(GEN P, GEN Q, GEN m, GEN a4, GEN T, GEN p) { if (ell_is_inf(P) || ell_is_inf(Q)) return pol_1(get_FpX_var(T)); return FpXQE_Miller(P, Q, m, a4, T, p); } /***********************************************************************/ /** **/ /** issupersingular **/ /** **/ /***********************************************************************/ GEN FpXQ_ellj(GEN a4, GEN a6, GEN T, GEN p) { if (absequaliu(p,3)) return pol_0(get_FpX_var(T)); else { pari_sp av=avma; GEN a43 = FpXQ_mul(a4,FpXQ_sqr(a4,T,p),T,p); GEN a62 = FpXQ_sqr(a6,T,p); GEN num = FpX_mulu(a43,6912,p); GEN den = FpX_add(FpX_mulu(a43,4,p),FpX_mulu(a62,27,p),p); return gerepileuptoleaf(av, FpXQ_div(num, den, T, p)); } } static GEN FpXQ_is_quad(GEN x, GEN T, GEN p) { pari_sp av = avma; GEN K; long d = degpol(T); x = FpXQ_red(x,T,p); if (lgpol(x)<=1) return NULL; if (d==2) return FpXQ_minpoly(x, T, p); if (odd(degpol(T))) return NULL; K = FpM_ker(FpXQ_matrix_pow(x, d, 3, T, p), p); if (lg(K)!=2) return gc_NULL(av); return RgV_to_RgX(gel(K,1), get_FpX_var(T)); } int FpXQ_elljissupersingular(GEN j, GEN T, GEN p) { pari_sp ltop = avma; /* All supersingular j-invariants are in FF_{p^2}, so we first check * whether j is in FF_{p^2}. If d is odd, then FF_{p^2} is not a * subfield of FF_{p^d} so the j-invariants are all in FF_p. Hence * the j-invariants are in FF_{p^{2 - e}}. */ ulong d = get_FpX_degree(T); GEN S; if (degpol(j) <= 0) return Fp_elljissupersingular(constant_coeff(j), p); j = FpXQ_red(j, T, p); if (degpol(j) <= 0) return gc_bool(ltop, Fp_elljissupersingular(constant_coeff(j), p)); /* Now j is not in F_p */ if (abscmpiu(p, 5) <= 0) return gc_bool(ltop,0); /* j != 0*/ if (odd(d)) return 0; /* Set S so that FF_p[T]/(S) is isomorphic to FF_{p^2}: */ if (d == 2) S = T; else /* d > 2 */ { S = FpXQ_is_quad(j, T, p); if (!S) return gc_bool(ltop,0); j = pol_x(varn(S)); } return gc_bool(ltop, jissupersingular(j,S,p)); } int Fq_elljissupersingular(GEN j, GEN T, GEN p) { return typ(j)==t_INT? Fp_elljissupersingular(j, p) : FpXQ_elljissupersingular(j, T, p); } /* p > 5 prime; return d such that (-d/p) = -1 */ static ulong find_inert_disc(GEN p) { long s = mod4(p) == 1? -1: 1; /* - (-1/p) */ ulong d = 3; while(1) { if (kroui(d,p) == s) return d; /* = 3 mod (16) */ d++; if (kroui(d>>2,p) == s) return d; /* = 4 mod (16) */ d += 3; if (kroui(d,p) == s) return d; /* = 7 mod (16) */ d++; if (kroui(d>>2,p) == s) return d; /* = 8 mod (16) */ d += 3; if (kroui(d,p) == s) return d; /* = 11 mod (16) */ d += 4; if (kroui(d,p) == s) return d; /* = 15 mod (16) */ d += 4; } } /* p > 5 */ static GEN ellsupersingularj_easy_FpXQ(GEN T, GEN p) { long d = find_inert_disc(p); GEN R = FpXQX_roots(polclass(stoi(-d), 0, 0), T, p); return gel(R,1); } GEN ellsupersingularj_FpXQ(GEN T, GEN p) { GEN j, j2, R, Phi2; long i, ep, lp; if (cmpiu(p, 5) <= 0) return pol_0(get_FpX_var(T)); j2 = ellsupersingularj_easy_FpXQ(T, p); Phi2 = polmodular_ZXX(2,0,0,1); R = FpXQX_roots(FqXY_evalx(Phi2, j2, T, p), T, p); j = gel(R,1+random_Fl(lg(R)-1)); ep = expi(p); lp = ep + random_Fl(ep); for (i = 1; i <= lp; i++) { GEN Phi2_j = FqX_div_by_X_x(FqXY_evalx(Phi2, j, T, p), j2, T, p, NULL); R = FqX_quad_root(Phi2_j, T, p); if (!R) pari_err_PRIME("ellsupersingularj",p); j2 = j; j = random_bits(1) ? R: Fq_neg(Fq_add(gel(Phi2_j,3), R, T, p), T, p); } return j; } /***********************************************************************/ /** **/ /** Point counting **/ /** **/ /***********************************************************************/ GEN elltrace_extension(GEN t, long n, GEN q) { pari_sp av = avma; GEN v = RgX_to_RgC(RgXQ_powu(pol_x(0), n, mkpoln(3,gen_1,negi(t),q)),2); GEN te = addii(shifti(gel(v,1),1), mulii(t,gel(v,2))); return gerepileuptoint(av, te); } GEN Fp_ffellcard(GEN a4, GEN a6, GEN q, long n, GEN p) { pari_sp av = avma; GEN ap = subii(addiu(p, 1), Fp_ellcard(a4, a6, p)); GEN te = elltrace_extension(ap, n, p); return gerepileuptoint(av, subii(addiu(q, 1), te)); } static GEN FpXQ_ellcardj(GEN a4, GEN a6, GEN j, GEN T, GEN q, GEN p, long n) { GEN q1 = addiu(q,1); if (signe(j)==0) { GEN W, w, t, N; if (umodiu(q,6)!=1) return q1; N = Fp_ffellcard(gen_0,gen_1,q,n,p); t = subii(q1, N); W = FpXQ_pow(a6,diviuexact(shifti(q,-1), 3),T,p); if (degpol(W)>0) /*p=5 mod 6*/ return ZX_equal1(FpXQ_powu(W,3,T,p)) ? addii(q1,shifti(t,-1)): subii(q1,shifti(t,-1)); w = modii(gel(W,2),p); if (equali1(w)) return N; if (equalii(w,subiu(p,1))) return addii(q1,t); else /*p=1 mod 6*/ { GEN u = shifti(t,-1), v = sqrtint(diviuexact(subii(q,sqri(u)),3)); GEN a = addii(u,v), b = shifti(v,1); if (equali1(Fp_powu(w,3,p))) { if (dvdii(addmulii(a, w, b), p)) return subii(q1,subii(shifti(b,1),a)); else return addii(q1,addii(a,b)); } else { if (dvdii(submulii(a, w, b), p)) return subii(q1,subii(a,shifti(b,1))); else return subii(q1,addii(a,b)); } } } else if (equalii(j,modsi(1728,p))) { GEN w, W, N, t; if (mod4(q)==3) return q1; W = FpXQ_pow(a4,shifti(q,-2),T,p); if (degpol(W)>0) return q1; /*p=3 mod 4*/ w = modii(gel(W,2),p); N = Fp_ffellcard(gen_1,gen_0,q,n,p); if (equali1(w)) return N; t = subii(q1, N); if (equalii(w,subiu(p,1))) return addii(q1,t); else /*p=1 mod 4*/ { GEN u = shifti(t,-1), v = sqrtint(subii(q,sqri(u))); if (dvdii(addmulii(u, w, v), p)) return subii(q1,shifti(v,1)); else return addii(q1,shifti(v,1)); } } else { GEN g = Fp_div(j, Fp_sub(utoi(1728), j, p), p); GEN l = FpXQ_div(FpX_mulu(a6,3,p),FpX_mulu(a4,2,p),T,p); GEN N = Fp_ffellcard(Fp_mulu(g,3,p),Fp_double(g,p),q,n,p); if (FpXQ_issquare(l,T,p)) return N; return subii(shifti(q1,1),N); } } static GEN FpXQ_ffellcard(GEN a4, GEN a6, GEN M, GEN q, GEN T, GEN p, long n) { long m = degpol(M); GEN j = pol_x(get_FpX_var(T)); GEN g = FpXQ_div(j, Fp_FpX_sub(utoi(1728), j, p), M, p); GEN N = FpXQ_ellcard(FpX_mulu(g,3,p),FpX_mulu(g,2,p),M,p); GEN qm = powiu(p, m), q1 = addiu(q, 1), qm1 = addiu(qm, 1); GEN l = FpXQ_mul(FpX_mulu(a6,3,p),FpX_mulu(a4,2,p),T,p); GEN te = elltrace_extension(subii(qm1, N), n/m, qm); return FpXQ_issquare(l,T,p) ? subii(q1, te): addii(q1, te); } static int FpXQ_is4power(GEN x, GEN T, GEN p) { long d = get_FpX_degree(T); if (lg(x) == 2 || absequalui(2, p)) return 1; if (Mod4(p)==1) return equali1(Fp_pow(FpXQ_norm(x,T,p),shifti(p,-2), p)); if (odd(d)) return FpXQ_issquare(x, T, p); return ZX_equal1(FpXQ_pow(x, shifti(powiu(p, d),-2), T, p)); } /* http://www.numdam.org/article/ASENS_1969_4_2_4_521_0.pdf */ GEN FpXQ_ellcard_supersingular(GEN a4, GEN a6, GEN T, GEN p) { pari_sp av = avma; long d = get_FpX_degree(T); GEN r; if (equaliu(p,3)) r = Flxq_ellcard(ZX_to_Flx(a4,3), ZX_to_Flx(a6,3), ZXT_to_FlxT(T,3), 3); else if (signe(a4)==0) r = FpXQ_ellcardj(a4, a6, gen_0, T, powiu(p, d), p, d); else if (signe(a6)==0) r = FpXQ_ellcardj(a4, a6, modsi(1728,p), T, powiu(p, d), p, d); else { GEN q, q2, t, D; long qm4 = (odd(d>>1) && Mod4(p)==3); if (odd(d)) return gen_0; q2 = powiu(p, d>>1); q = sqri(q2); t = shifti(q2, 1); D = FpX_sub(FpX_Fp_mul(FpXQ_powu(a4,3,T,p), stoi(-4), p), FpX_mulu(FpXQ_sqr(a6,T,p), 27, p), p); r = qm4 ^ FpXQ_is4power(D, T, p) ? subii(addiu(q, 1), t) : addii(addiu(q, 1), t); } return gerepileuptoint(av, r); } GEN Fq_ellcard_supersingular(GEN a4, GEN a6, GEN T, GEN p) { return T ? FpXQ_ellcard_supersingular(a4, a6, T, p) : addiu(p, 1); } static GEN FpXQ_ellcard_i(GEN a4, GEN a6, GEN T, GEN p) { long n = get_FpX_degree(T); GEN q = powiu(p, n); if (degpol(a4)<=0 && degpol(a6)<=0) return Fp_ffellcard(constant_coeff(a4),constant_coeff(a6),q,n,p); if (lgefint(p)==3) { ulong pp = p[2]; return Flxq_ellcard(ZX_to_Flx(a4,pp),ZX_to_Flx(a6,pp),ZX_to_Flx(T,pp),pp); } else { GEN J = FpXQ_ellj(a4,a6,T,p), M; if (degpol(J) <= 0) return FpXQ_ellcardj(a4,a6,constant_coeff(J),T,q,p,n); M = FpXQ_minpoly(J,T,p); if (degpol(M) < degpol(T)) return FpXQ_ffellcard(a4, a6, M, q, T, p, n); return Fq_ellcard_SEA(a4, a6, q, T, p, 0); } } GEN FpXQ_ellcard(GEN a4, GEN a6, GEN T, GEN p) { pari_sp av = avma; return gerepileuptoint(av, FpXQ_ellcard_i(a4, a6, T, p)); } static GEN _FpXQE_pairorder(void *E, GEN P, GEN Q, GEN m, GEN F) { struct _FpXQE *e = (struct _FpXQE *) E; return FpXQ_order(FpXQE_weilpairing(P,Q,m,e->a4,e->T,e->p), F, e->T, e->p); } GEN FpXQ_ellgroup(GEN a4, GEN a6, GEN N, GEN T, GEN p, GEN *pt_m) { struct _FpXQE e; GEN q = powiu(p, get_FpX_degree(T)); e.a4=a4; e.a6=a6; e.T=T; e.p=p; return gen_ellgroup(N, subiu(q,1), pt_m, (void*)&e, &FpXQE_group, _FpXQE_pairorder); } GEN FpXQ_ellgens(GEN a4, GEN a6, GEN ch, GEN D, GEN m, GEN T, GEN p) { GEN P; pari_sp av = avma; struct _FpXQE e; e.a4=a4; e.a6=a6; e.T=T; e.p=p; switch(lg(D)-1) { case 1: P = gen_gener(gel(D,1), (void*)&e, &FpXQE_group); P = mkvec(FpXQE_changepoint(P, ch, T, p)); break; default: P = gen_ellgens(gel(D,1), gel(D,2), m, (void*)&e, &FpXQE_group, _FpXQE_pairorder); gel(P,1) = FpXQE_changepoint(gel(P,1), ch, T, p); gel(P,2) = FpXQE_changepoint(gel(P,2), ch, T, p); break; } return gerepilecopy(av, P); } pari-2.17.2/src/basemath/quad.c0000644000175000017500000010204014676526175014655 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_arith /*********************************************************************/ /** **/ /** FUNDAMENTAL DISCRIMINANTS **/ /** **/ /*********************************************************************/ static long fa_isfundamental(GEN F) { GEN P = gel(F,1), E = gel(F,2); long i, s, l = lg(P); if (l == 1) return 1; s = signe(gel(P,1)); /* = signe(x) */ if (!s) return 0; if (s < 0) { l--; P = vecslice(P,2,l); E = vecslice(E,2,l); } if (l == 1) return 0; if (!absequaliu(gel(P,1), 2)) i = 1; /* need x = 1 mod 4 */ else { i = 2; switch(itou(gel(E,1))) { case 2: s = -s; break; /* need x/4 = 3 mod 4 */ case 3: s = 0; break; /* no condition mod 4 */ default: return 0; } } for(; i < l; i++) { if (!equali1(gel(E,i))) return 0; if (s && Mod4(gel(P,i)) == 3) s = -s; } return s >= 0; } long isfundamental(GEN x) { if (typ(x) != t_INT) { pari_sp av = avma; long v = fa_isfundamental(check_arith_all(x,"isfundamental")); return gc_long(av,v); } return Z_isfundamental(x); } /* x fundamental ? */ long uposisfundamental(ulong x) { ulong r = x & 15; /* x mod 16 */ if (!r) return 0; switch(r & 3) { /* x mod 4 */ case 0: return (r == 4)? 0: uissquarefree(x >> 2); case 1: return uissquarefree(x); default: return 0; } } /* -x fundamental ? */ long unegisfundamental(ulong x) { ulong r = x & 15; /* x mod 16 */ if (!r) return 0; switch(r & 3) { /* x mod 4 */ case 0: return (r == 12)? 0: uissquarefree(x >> 2); case 3: return uissquarefree(x); default: return 0; } } long sisfundamental(long x) { return x < 0? unegisfundamental((ulong)(-x)): uposisfundamental(x); } long Z_isfundamental(GEN x) { long r; switch(lgefint(x)) { case 2: return 0; case 3: return signe(x) < 0? unegisfundamental(x[2]) : uposisfundamental(x[2]); } r = mod16(x); if (!r) return 0; if ((r & 3) == 0) { pari_sp av; r >>= 2; /* |x|/4 mod 4 */ if (signe(x) < 0) r = 4-r; if (r == 1) return 0; av = avma; r = Z_issquarefree( shifti(x,-2) ); return gc_long(av, r); } r &= 3; /* |x| mod 4 */ if (signe(x) < 0) r = 4-r; return (r==1) ? Z_issquarefree(x) : 0; } static GEN fa_quaddisc(GEN f) { GEN P = gel(f,1), E = gel(f,2), s = gen_1; long i, l = lg(P); for (i = 1; i < l; i++) /* possibly including -1 */ if (mpodd(gel(E,i))) s = mulii(s, gel(P,i)); if (Mod4(s) > 1) s = shifti(s,2); return s; } GEN quaddisc(GEN x) { const pari_sp av = avma; long tx = typ(x); GEN F; if (is_rational_t(tx)) F = factor(x); else { F = check_arith_all(x,"quaddisc"); if (tx == t_VEC && typ(gel(x,1)) == t_INT && Z_issquarefree_fact(gel(x,2))) { x = gel(x,1); return (Mod4(x) > 1)? shifti(x, 2): icopy(x); } } return gerepileuptoint(av, fa_quaddisc(F)); } /***********************************************************************/ /** **/ /** FUNDAMENTAL UNIT AND REGULATOR (QUADRATIC FIELDS) **/ /** **/ /***********************************************************************/ /* replace f by f * [u,1; 1,0] */ static void update_f(GEN f, GEN u) { GEN a = gcoeff(f,1,1), b = gcoeff(f,1,2); GEN c = gcoeff(f,2,1), d = gcoeff(f,2,2); gcoeff(f,1,1) = addmulii(b, u,a); gcoeff(f,1,2) = a; gcoeff(f,2,1) = addmulii(d, u,c); gcoeff(f,2,2) = c; } /* f is a vector of matrices and i an index whose bits give the non-zero * entries; the product of the non zero entries is the actual result. * if i odd, f[1] may be an int: implicitely represent [f[1],1;1,0] */ static long update_fm(GEN f, GEN a, long i) { #ifdef LONG_IS_64BIT const long LIM = 10; #else const long LIM = 18; #endif pari_sp av = avma; long k, v; GEN u; if (!odd(i)) { gel(f,1) = a; return i+1; } u = gel(f, 1); if (typ(u) == t_INT) /* [u,1;1,0] * [a,1;1,0] */ { gel(f,1) = mkmat22(addiu(mulii(a, u), 1), u, a, gen_1); return i; } update_f(u, a); if (lgefint(gcoeff(u,1,1)) < LIM) return i; v = vals(i+1); gel(f,1) = gen_0; for (k = 1; k < v; k++) { u = ZM2_mul(gel(f,k+1), u); gel(f,k+1) = gen_0; } if (v != 1) u = gerepileupto(av, u); gel(f,v+1) = u; return i+1; } /* \prod f[j]; if first only return column 1 */ static GEN prod_fm(GEN f, long i, long first) { long k, v = vals(i) + 1; GEN u = gel(f, v); /* i a power of 2: f[1] can't be a t_INT */ if (!(i >>= v)) return first? gel(u,1): u; for (k = v+1; i; i >>= 1, k++) if (odd(i)) { GEN w = gel(f,k); switch(typ(u)) { case t_INT: update_f(w, u); u = first? gel(w,1): w; break; case t_COL: /* implies 'first' */ u = ZM_ZC_mul(w, u); break; default: /* t_MAT */ u = first? ZM_ZC_mul(w, gel(u,1)): ZM2_mul(w, u); break; } } return u; } GEN quadunit0(GEN x, long v) { GEN y = quadunit(x); if (v==-1) v = fetch_user_var("w"); setvarn(gel(y,1), v); return y; } struct uimod { GEN N, T; }; static GEN ui_pow(void *E, GEN x, GEN n) { struct uimod *S = (struct uimod*)E; return FpXQ_pow(x, n, S->T, S->N); } static int ui_equal1(GEN x) { return degpol(x) < 1; } static const struct bb_group ui_group={ NULL,ui_pow,NULL,NULL,NULL,ui_equal1,NULL}; static void quadunit_uvmod(GEN D, GEN d, GEN N, GEN *pu, GEN *pv) { GEN u1, u2, v1, v2, p, q, q1, u, v; int m = mpodd(D), first = 1; pari_sp av = avma; p = (mpodd(d) == m)? d: subiu(d, 1); u1 = negi(p); u2 = gen_2; v1 = gen_1; v2 = gen_0; q = gen_2; q1 = shifti(subii(D, sqri(p)), -1); for(;;) { GEN r, A = dvmdii(addii(p, d), q, &r), p1 = p, t; p = subii(d, r); if (equalii(p1, p) && !first) { /* even period */ u = addmulii(sqri(u2), D, sqri(v2)); v = shifti(mulii(u2,v2), 1); break; } first = 0; t = Fp_addmul(u1, A, u2, N); u1 = u2; u2 = t; t = Fp_addmul(v1, A, v2, N); v1 = v2; v2 = t; t = q; q = submulii(q1, A, subii(p, p1)); q1 = t; if (equalii(q, t)) { /* odd period */ u = addmulii(mulii(u1,u2), D, mulii(v1,v2)); v = addmulii(mulii(u1,v2), u2, v1); break; } if (gc_needed(av, 2)) { if(DEBUGMEM>1) pari_warn(warnmem,"quadunit_uvmod"); gerepileall(av, 7, &p, &u1,&u2,&v1,&v2, &q,&q1); } } *pu = modii(u, N); *pv = modii(v, N); if (m) *pu = Fp_sub(*pu, *pv, N); } /* fundamental unit is u + vx mod quadpoly(D); always called with D * fundamental and relatively small but would work in all cases. Should be * called whenever the fundamental unit is so "small" that asymptotically * fast multiplication is not used in the continued fraction loop */ static void quadunit_uv_basecase(GEN D, GEN *pu, GEN *pv) { GEN u1, u2, v1, v2, p, q, q1, u, v, a, b, c, d = sqrtremi(D, &a); int m = mpodd(D); long first = 1; p = d; q1 = shifti(a, -1); q = gen_2; if (mpodd(d) != m) { p = subiu(d,1); q1 = addii(q1,d); } /* q1 = (D-p^2)/2 */ u1 = gen_2; u2 = p; v1 = gen_0; v2 = gen_1; for(;;) { GEN t = q; if (first) { first = 0; q = q1; } else { GEN r, A = dvmdii(addii(p, d), q, &r), p1 = p; p = subii(d, r); if (equalii(p1, p)) /* even period */ { a = sqri(u2); b = sqri(v2); c = sqri(addii(u2, v2)); break; } r = addmulii(u1, A, u2); u1 = u2; u2 = r; r = addmulii(v1, A, v2); v1 = v2; v2 = r; q = submulii(q1, A, subii(p, p1)); } q1 = t; if (equalii(q, t)) { /* odd period */ a = mulii(u1, u2); b = mulii(v1, v2); c = mulii(addii(u1, v1), addii(u2, v2)); break; } } u = diviiexact(addmulii(a, D, b), q); v = diviiexact(subii(c, addii(a, b)), q); if (m == 1) u = subii(u, v); *pu = shifti(u, -1); *pv = v; } /* D > 0, d = sqrti(D) */ static GEN quadunit_q(GEN D, GEN d, long *pN) { pari_sp av = avma; GEN p, q, q1; long first = 1; p = (Mod2(d) == Mod2(D))? d: subiu(d, 1); q = gen_2; q1 = shifti(subii(D, sqri(p)), -1); for(;;) { GEN r, A = dvmdii(addii(p, d), q, &r), p1 = p, t; p = subii(d, r); if (!first && equalii(p1, p)) { *pN = 1; return q; } /* even period */ first = 0; t = q; q = submulii(q1, A, subii(p, p1)); q1 = t; if (equalii(q, t)) { *pN = -1; return q; } /* odd period */ if (gc_needed(av, 2)) { if(DEBUGMEM>1) pari_warn(warnmem,"quadunitnorm"); gerepileall(av, 3, &p, &q, &q1); } } } /* fundamental unit mod N */ static GEN quadunit_mod(GEN D, GEN N) { GEN q, u, v, d = sqrti(D); pari_sp av = avma; long s; q = gerepileuptoint(av, quadunit_q(D, d, &s)); if (mpodd(N) && equali1(gcdii(q, N))) { quadunit_uvmod(D, d, N, &u, &v); q = Fp_inv(shifti(q, 1), N); u = Fp_mul(u, q, N); v = Fp_mul(v, q, N); v = modii(shifti(v, 1), N); } else { GEN M = shifti(mulii(q, N), 1); quadunit_uvmod(D, d, M, &u, &v); u = diviiexact(u, q); v = modii(diviiexact(v, q), N); u = shifti(u,-1); } return deg1pol_shallow(v, u, 0); } /* f \prod_{p|f} [ 1 - (D/p) p^-1 ] = \prod_{p^e||f} p^(e-1) [ p - (D/p) ] */ static GEN quadclassnoEuler_fact(GEN D, GEN P, GEN E) { long i, l = lg(P); GEN H; if (typ(E) != t_VECSMALL) E = vec_to_vecsmall(E); for (i = 1, H = gen_1; i < l; i++) { GEN p = gel(P,i); long e = E[i], s = kronecker(D,p); if (!s) H = mulii(H, e == 1? p: powiu(p, e)); else { H = mulii(H, subis(p, s)); if (e >= 2) H = mulii(H, e == 2? p: powiu(p,e-1)); } } return H; } /* D > 0; y mod (N,T) congruent to fundamental unit of maximal order and * disc D. Return unit index of order of conductor N */ static GEN quadunitindex_ii(GEN D, GEN N, GEN F, GEN y, GEN T) { GEN H = quadclassnoEuler_fact(D, gel(F,1), gel(F,2)); GEN P, E, a = Z_smoothen(H, gel(F,1), &P, &E), faH = mkmat2(P, E); struct uimod S; if (a) faH = ZM_merge_factor(Z_factor(a), faH); /* multiple of unit index, in [H, factor(H)] format */ S.N = N; S.T = FpX_red(T, N); return gen_order(y, mkvec2(H,faH), (void*)&S, &ui_group); } static GEN quadunitindex_i(GEN D, GEN N, GEN F) { return quadunitindex_ii(D, N, F, quadunit_mod(D, N), quadpoly_i(D)); } GEN quadunitindex(GEN D, GEN N) { pari_sp av = avma; long r, s; GEN F; check_quaddisc(D, &s, &r, "quadunitindex"); if ((F = check_arith_pos(N,"quadunitindex"))) N = typ(N) == t_VEC? gel(N,1): factorback(F); if (equali1(N)) return gen_1; if (s < 0) switch(itos_or_0(D)) { case -3: return utoipos(3); case -4: return utoipos(2); default: return gen_1; } return gerepileuptoint(av, quadunitindex_i(D, N, F? F: Z_factor(N))); } /* fundamental unit is u + vx mod quadpoly(D); always called with D * fundamental but would work in all cases. Same algorithm as basecase, * except we compute the product of elementary matrices with a product tree */ static void quadunit_uv(GEN D, GEN *pu, GEN *pv) { GEN a, b, c, u, v, p, q, q1, f, d = sqrtremi(D, &a); pari_sp av = avma; long i = 0; int m = mpodd(D); p = d; q1 = shifti(a, -1); q = gen_2; if (mpodd(d) != m) { p = subiu(d,1); q1 = addii(q1,d); } /* q1 = (D-p^2)/2 */ f = zerovec(2 + (expi(D)>>1)); gel(f,1) = mkmat22(p, gen_2, gen_1, gen_0); for(;;) { GEN t = q, u1,u2, v1,v2; if (!i) { i = 1; q = q1; } else { GEN r, A = dvmdii(addii(p, d), q, &r), p1 = p; p = subii(d, r); if (equalii(p1, p)) { /* even period */ f = prod_fm(f, i, 1); u2 = gel(f,1); v2 = gel(f,2); a = sqri(u2); b = sqri(v2); c = sqri(addii(u2, v2)); break; } i = update_fm(f, A, i); q = submulii(q1, A, subii(p, p1)); } q1 = t; if (equalii(q, t)) { /* odd period */ f = prod_fm(f, i, 0); u2 = gcoeff(f,1,1); u1 = gcoeff(f,1,2); a = mulii(u1, u2); v2 = gcoeff(f,2,1); v1 = gcoeff(f,2,2); b = mulii(v1, v2); c = mulii(addii(u1, v1), addii(u2, v2)); break; } if (gc_needed(av, 2)) { if(DEBUGMEM>1) pari_warn(warnmem,"quadunit (%ld)", i); gerepileall(av, 4, &p, &f, &q,&q1); } } u = diviiexact(addmulii(a, D, b), q); v = diviiexact(subii(c, addii(a, b)), q); if (m == 1) u = subii(u, v); *pu = shifti(u, -1); *pv = v; } GEN quadunit(GEN D0) { pari_sp av = avma; GEN P, E, D, u, v; long s = signe(D0); /* check_quaddisc_real omitting test for squares */ if (typ(D0) != t_INT) pari_err_TYPE("quadunit", D0); if (s <= 0) pari_err_DOMAIN("quadunit", "disc","<=",gen_0,D0); if (mod4(D0) > 1) pari_err_DOMAIN("quadunit","disc % 4",">", gen_1,D0); D = coredisc2_fact(Z_factor(D0), s, &P, &E); /* test for squares done here for free */ if (equali1(D)) pari_err_DOMAIN("quadunit","issquare(disc)","=", gen_1,D0); if (cmpiu(D, 2000000) < 0) quadunit_uv_basecase(D, &u, &v); else quadunit_uv(D, &u, &v); if (lg(P) != 1) { /* non-trivial conductor N > 1 */ GEN N = factorback2(P,E), qD = quadpoly_i(D); GEN n, y = deg1pol_shallow(v, u, 0); /* maximal order fund unit */ n = quadunitindex_ii(D, N, mkvec2(P,E), FpX_red(y,N), qD); /* unit index */ y = ZXQ_powu(y, itou(n), qD); /* fund unit of order of conductor N */ v = gel(y,3); u = gel(y,2); /* u + v w_D */ if (mpodd(D)) { /* w_D = (1+sqrt(D))/2 */ if (mpodd(D0)) { /* w_D0 = (1 + N sqrt(D)) / 2 */ GEN v0 = v; v = diviiexact(v, N); u = addii(u, shifti(subii(v0, v), -1)); } else { /* w_D0 = N sqrt(D)/2, N is even */ v = shifti(v, -1); u = addii(u, v); v = diviiexact(v, shifti(N,-1)); } } else /* w_D = sqrt(D), w_D0 = N sqrt(D) */ v = diviiexact(v, N); } return gerepilecopy(av, mkquad(quadpoly_i(D0), u, v)); } long quadunitnorm(GEN D) { pari_sp av = avma; long s, r; check_quaddisc(D, &s, &r, "quadunitnorm"); if (s < 0) return 1; (void)quadunit_q(D, sqrti(D), &s); return gc_long(av, s); } GEN quadregulator(GEN x, long prec) { pari_sp av = avma, av2; GEN R, rsqd, u, v, sqd; long r, e; check_quaddisc_real(x, &r, "quadregulator"); sqd = sqrti(x); rsqd = gsqrt(x,prec); av2 = avma; e = 0; R = real2n(1, prec); u = utoi(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 = mulrr(sqrr(R), divri(addir(u1,rsqd),v)); break; } if (equalii(u,u1)) { R = sqrr(R); break; } R = mulrr(R, divri(addir(u1,rsqd),v)); e += expo(R); setexpo(R,0); u = u1; v = v1; if (e & ~EXPOBITS) pari_err_OVERFLOW("quadregulator [exponent]"); if (gc_needed(av2,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"quadregulator"); gerepileall(av2,3, &R,&u,&v); } } R = divri(R, v); e = 2*e - 1; /* avoid loss of accuracy */ if (!((e + expo(R)) & ~EXPOBITS)) { setexpo(R, e + expo(R)); e = 0; } R = logr_abs(R); if (e) R = addrr(R, mulsr(e, mplog2(prec))); return gerepileuptoleaf(av, R); } /*************************************************************************/ /** **/ /** CLASS NUMBER **/ /** **/ /*************************************************************************/ int qfb_equal1(GEN f) { return equali1(gel(f,1)); } static GEN qfi_pow(void *E, GEN f, GEN n) { return E? nupow(f,n,(GEN)E): qfbpow_i(f,n); } static GEN qfi_comp(void *E, GEN f, GEN g) { return E? nucomp(f,g,(GEN)E): qfbcomp_i(f,g); } static const struct bb_group qfi_group={ qfi_comp,qfi_pow,NULL,hash_GEN, gidentical,qfb_equal1,NULL}; GEN qfi_order(GEN q, GEN o) { return gen_order(q, o, NULL, &qfi_group); } GEN qfi_log(GEN a, GEN g, GEN o) { return gen_PH_log(a, g, o, NULL, &qfi_group); } GEN qfi_Shanks(GEN a, GEN g, long n) { pari_sp av = avma; GEN T, X; long rt_n, c; a = qfbred_i(a); g = qfbred_i(g); rt_n = sqrt((double)n); c = n / rt_n; c = (c * rt_n < n + 1) ? c + 1 : c; T = gen_Shanks_init(g, rt_n, NULL, &qfi_group); X = gen_Shanks(T, a, c, NULL, &qfi_group); return X? gerepileuptoint(av, X): gc_NULL(av); } GEN qfbclassno0(GEN x,long flag) { switch(flag) { case 0: return map_proto_G(classno,x); case 1: return map_proto_G(classno2,x); default: pari_err_FLAG("qfbclassno"); } return NULL; /* LCOV_EXCL_LINE */ } /* f^h = 1, return order(f). Set *pfao to its factorization */ static GEN find_order(void *E, GEN f, GEN h, GEN *pfao) { GEN v = gen_factored_order(f, h, E, &qfi_group); *pfao = gel(v,2); return gel(v,1); } static int ok_q(GEN q, GEN h, GEN d2, long r2) { if (d2) { if (r2 <= 2 && !mpodd(q)) return 0; return is_pm1(Z_ppo(q,d2)); } else { if (r2 <= 1 && !mpodd(q)) return 0; return is_pm1(Z_ppo(q,h)); } } /* a,b given by their factorizations. Return factorization of lcm(a,b). * Set A,B such that A*B = lcm(a, b), (A,B)=1, A|a, B|b */ static GEN split_lcm(GEN a, GEN Fa, GEN b, GEN Fb, GEN *pA, GEN *pB) { GEN P = ZC_union_shallow(gel(Fa,1), gel(Fb,1)); GEN A = gen_1, B = gen_1; long i, l = lg(P); GEN E = cgetg(l, t_COL); for (i=1; i= 2) H *= upowuu(p, e-1); } } if (l == 1) return H; if (s < 0) { switch(d) { /* divide by [ O_K^* : O^* ] */ case 4: H >>= 1; break; case 3: H /= 3; break; } } else { GEN fa = mkmat2(zc_to_ZC(P), zc_to_ZC(E)); H /= itou(quadunitindex_i(utoipos(d), factorback(fa), fa)); } return H; } GEN quadclassnoF_fact(GEN D, GEN P, GEN E) { GEN H = quadclassnoEuler_fact(D, P, E); if (lg(P) == 1) return H; if (signe(D) < 0) { switch(itou_or_0(D)) { /* divide by [ O_K^* : O^* ] */ case 4: H = shifti(H,-1); break; case 3: H = diviuexact(H,3); break; } } else { GEN fa = mkvec2(P, E); H = diviiexact(H, quadunitindex_i(D, factorback2(P, E), fa)); } return H; } static ulong quadclassnoF_u(ulong x, long s, ulong *pD) { pari_sp av = avma; GEN P, E; ulong D = coredisc2u_fact(factoru(x), s, &P, &E); long H = uquadclassnoF_fact(D, s, P, E); *pD = D; return gc_ulong(av, H); } ulong unegquadclassnoF(ulong x, ulong *pD) { return quadclassnoF_u(x, -1, pD); } ulong uposquadclassnoF(ulong x, ulong *pD) { return quadclassnoF_u(x, 1, pD); } /* *pD = coredisc(x), *pR = regulator (x > 0) or NULL */ GEN quadclassnoF(GEN x, GEN *pD) { GEN D, P, E; if (lgefint(x) == 3) { long s = signe(x); ulong d, h = quadclassnoF_u(x[2], s, &d); if (pD) *pD = s > 0? utoipos(d): utoineg(d); return utoipos(h); } D = coredisc2_fact(absZ_factor(x), signe(x), &P, &E); if (pD) *pD = D; return quadclassnoF_fact(D, P, E); } static long two_rank(GEN x) { GEN p = gel(absZ_factor(x),1); long l = lg(p)-1; #if 0 /* positive disc not needed */ if (signe(x) > 0) { long i; for (i=1; i<=l; i++) if (mod4(gel(p,i)) == 3) { l--; break; } } #endif return l-1; } static GEN sqr_primeform(GEN x, ulong p) { return qfbsqr_i(primeform_u(x, p)); } /* return a set of forms hopefully generating Cl(K)^2; set L ~ L(chi_D,1) */ static GEN get_forms(GEN D, GEN *pL) { const long MAXFORM = 20; GEN L, sqrtD = gsqrt(absi_shallow(D),DEFAULTPREC); GEN forms = vectrunc_init(MAXFORM+1); long s, nforms = 0; ulong p; forprime_t S; L = mulrr(divrr(sqrtD,mppi(DEFAULTPREC)), dbltor(1.005));/*overshoot by 0.5%*/ s = itos_or_0( truncr(shiftr(sqrtr(sqrtD), 1)) ); if (!s) pari_err_OVERFLOW("classno [discriminant too large]"); if (s < 10) s = 200; else if (s < 20) s = 1000; else if (s < 5000) s = 5000; u_forprime_init(&S, 2, s); while ( (p = u_forprime_next(&S)) ) { long d, k = kroiu(D,p); pari_sp av2; if (!k) continue; if (k > 0) { if (++nforms < MAXFORM) vectrunc_append(forms, sqr_primeform(D,p)); d = p-1; } else d = p+1; av2 = avma; affrr(divru(mulur(p,L),d), L); set_avma(av2); } *pL = L; return forms; } /* h ~ #G, return o = order of f, set fao = its factorization */ static GEN Shanks_order(void *E, GEN f, GEN h, GEN *pfao) { long s = minss(itos(sqrti(h)), 10000); GEN T = gen_Shanks_init(f, s, E, &qfi_group); GEN v = gen_Shanks(T, ginv(f), ULONG_MAX, E, &qfi_group); return find_order(E, f, addiu(v,1), pfao); } /* if g = 1 in G/ ? */ static int equal1(void *E, GEN T, ulong N, GEN g) { return !!gen_Shanks(T, g, N, E, &qfi_group); } /* Order of 'a' in G/, T = gen_Shanks_init(f,n), order(f) < n*N * FIXME: should be gen_order, but equal1 has the wrong prototype */ static GEN relative_order(void *E, GEN a, GEN o, ulong N, GEN T) { pari_sp av = avma; long i, l; GEN m; m = get_arith_ZZM(o); if (!m) pari_err_TYPE("gen_order [missing order]",a); o = gel(m,1); m = gel(m,2); l = lgcols(m); for (i = l-1; i; i--) { GEN t, y, p = gcoeff(m,i,1); long j, e = itos(gcoeff(m,i,2)); if (l == 2) { t = gen_1; y = a; } else { t = diviiexact(o, powiu(p,e)); y = powgi(a, t); } if (equal1(E, T,N,y)) o = t; else { for (j = 1; j < e; j++) { y = powgi(y, p); if (equal1(E, T,N,y)) break; } if (j < e) { if (j > 1) p = powiu(p, j); o = mulii(t, p); } } } return gerepilecopy(av, o); } /* h(x) for x<0 using Baby Step/Giant Step. * Assumes G is not too far from being cyclic. * * Compute G^2 instead of G so as to kill most of the noncyclicity */ GEN classno(GEN x) { pari_sp av = avma; long r2, k, s, i, l; GEN forms, hin, Hf, D, g1, d1, d2, q, L, fad1, order_bound; void *E; if (signe(x) >= 0) return classno2(x); check_quaddisc(x, &s, &k, "classno"); if (abscmpiu(x,12) <= 0) return gen_1; Hf = quadclassnoF(x, &D); if (abscmpiu(D,12) <= 0) return gerepilecopy(av, Hf); forms = get_forms(D, &L); r2 = two_rank(D); hin = roundr(shiftr(L, -r2)); /* rough approximation for #G, G = Cl(K)^2 */ l = lg(forms); order_bound = const_vec(l-1, NULL); E = expi(D) > 60? (void*)sqrtnint(shifti(absi_shallow(D),-2),4): NULL; g1 = gel(forms,1); gel(order_bound,1) = d1 = Shanks_order(E, g1, hin, &fad1); q = diviiround(hin, d1); /* approximate order of G/ */ d2 = NULL; /* not computed yet */ if (is_pm1(q)) goto END; for (i=2; i < l; i++) { GEN o, fao, a, F, fd, f = gel(forms,i); fd = qfbpow_i(f, d1); if (is_pm1(gel(fd,1))) continue; F = qfbpow_i(fd, q); a = gel(F,1); o = is_pm1(a)? find_order(E, fd, q, &fao): Shanks_order(E, fd, q, &fao); /* f^(d1 q) = 1 */ fao = ZM_merge_factor(fad1,fao); o = find_order(E, f, fao, &fao); gel(order_bound,i) = o; /* o = order of f, fao = factor(o) */ update_g1(&g1,&d1,&fad1, f,o,fao); q = diviiround(hin, d1); if (is_pm1(q)) goto END; } /* very probably d1 = expo(Cl^2(K)), q ~ #Cl^2(K) / d1 */ if (expi(q) > 3) { /* q large: compute d2, 2nd elt divisor */ ulong N, n = 2*itou(sqrti(d1)); GEN D = d1, T = gen_Shanks_init(g1, n, E, &qfi_group); d2 = gen_1; N = itou( gceil(gdivgu(d1,n)) ); /* order(g1) <= n*N */ for (i = 1; i < l; i++) { GEN d, f = gel(forms,i), B = gel(order_bound,i); if (!B) B = find_order(E, f, fad1, /*junk*/&d); f = qfbpow_i(f,d2); if (equal1(E, T,N,f)) continue; B = gdiv(B,d2); if (typ(B) == t_FRAC) B = gel(B,1); /* f^B = 1 */ d = relative_order(E, f, B, N,T); d2= mulii(d,d2); D = mulii(d1,d2); q = diviiround(hin,D); if (is_pm1(q)) { d1 = D; goto END; } } /* very probably, d2 is the 2nd elementary divisor */ d1 = D; /* product of first two elt divisors */ } /* impose q | d2^oo (d1^oo if d2 not computed), and compatible with known * 2-rank */ if (!ok_q(q,d1,d2,r2)) { GEN q0 = q; long d; if (cmpii(mulii(q,d1), hin) < 0) { /* try q = q0+1,-1,+2,-2 */ d = 1; do { q = addis(q0,d); d = d>0? -d: 1-d; } while(!ok_q(q,d1,d2,r2)); } else { /* q0-1,+1,-2,+2 */ d = -1; do { q = addis(q0,d); d = d<0? -d: -1-d; } while(!ok_q(q,d1,d2,r2)); } } d1 = mulii(d1,q); END: return gerepileuptoint(av, shifti(mulii(d1,Hf), r2)); } /* use Euler products */ GEN classno2(GEN x) { pari_sp av = avma; const long prec = DEFAULTPREC; long n, i, s; GEN p1, p2, S, p4, p5, p7, Hf, Pi, logd, sqrtd, D, half, reg = NULL; check_quaddisc(x, &s, NULL, "classno2"); if (s < 0 && abscmpiu(x,12) <= 0) return gen_1; Hf = quadclassnoF(x, &D); if (s < 0 && abscmpiu(D,12) <= 0) return gerepilecopy(av, Hf); /* |D| < 12*/ Pi = mppi(prec); sqrtd = sqrtr_abs(itor(D, prec)); logd = logr_abs(sqrtd); shiftr_inplace(logd,1); p1 = sqrtr_abs(divrr(mulir(D,logd), gmul2n(Pi,1))); if (s > 0) { GEN invlogd = invr(logd); reg = quadregulator(D, prec); p2 = subsr(1, shiftr(mulrr(logr_abs(reg),invlogd),1)); if (cmprr(sqrr(p2), shiftr(invlogd,1)) >= 0) p1 = mulrr(p2,p1); } n = itos_or_0( mptrunc(p1) ); if (!n) pari_err_OVERFLOW("classno [discriminant too large]"); p4 = divri(Pi, D); setsigne(p4, 1); p7 = invr(sqrtr_abs(Pi)); half = real2n(-1, prec); if (s > 0) { /* i = 1, shortcut */ p1 = sqrtd; p5 = subsr(1, mulrr(p7,incgamc(half,p4,prec))); S = addrr(mulrr(p1,p5), eint1(p4,prec)); for (i=2; i<=n; i++) { long k = kroiu(D,i); if (!k) continue; p2 = mulir(sqru(i), p4); p5 = subsr(1, mulrr(p7,incgamc(half,p2,prec))); p5 = addrr(divru(mulrr(p1,p5),i), eint1(p2,prec)); S = (k>0)? addrr(S,p5): subrr(S,p5); } S = shiftr(divrr(S,reg),-1); } else { /* i = 1, shortcut */ p1 = gdiv(sqrtd, Pi); p5 = subsr(1, mulrr(p7,incgamc(half,p4,prec))); S = addrr(p5, divrr(p1, mpexp(p4))); for (i=2; i<=n; i++) { long k = kroiu(D,i); if (!k) continue; p2 = mulir(sqru(i), p4); p5 = subsr(1, mulrr(p7,incgamc(half,p2,prec))); p5 = addrr(p5, divrr(p1, mulur(i, mpexp(p2)))); S = (k>0)? addrr(S,p5): subrr(S,p5); } } return gerepileuptoint(av, mulii(Hf, roundr(S))); } /* 1 + q + ... + q^v, v > 0 */ static GEN geomsumu(ulong q, long v) { GEN u = utoipos(1+q); for (; v > 1; v--) u = addui(1, mului(q, u)); return u; } static GEN geomsum(GEN q, long v) { GEN u; if (lgefint(q) == 3) return geomsumu(q[2], v); u = addiu(q,1); for (; v > 1; v--) u = addui(1, mulii(q, u)); return u; } /* 1+p+...+p^(e-1), e >= 1; assuming result fits in an ulong */ static ulong usumpow(ulong p, long e) { ulong q; long i; if (p == 2) return (1UL << e) - 1; /* also OK if e = BITS_IN_LONG */ e--; for (i = 1, q = p + 1; i < e; i++) q = p*q + 1; return q; } long uhclassnoF_fact(GEN faF, long D) { GEN P = gel(faF,1), E = gel(faF,2); long i, t, l = lg(P); for (i = t = 1; i < l; i++) { long p = P[i], e = E[i], s = kross(D,p); if (e == 1) { t *= 1 + p - s; continue; } if (s == 1) { t *= upowuu(p,e); continue; } t *= 1 + usumpow(p, e) * (p - s); } return t; } /* Hurwitz(D F^2)/ Hurwitz(D) * = \sum_{f|F} f \prod_{p|f} (1-kro(D/p)/p) * = \prod_{p^e || F} (1 + (p^e-1) / (p-1) * (p-kro(D/p))) */ GEN hclassnoF_fact(GEN P, GEN E, GEN D) { GEN H; long i, l = lg(P); if (l == 1) return gen_1; for (i = 1, H = NULL; i < l; i++) { GEN t, p = gel(P,i); long e = E[i], s = kronecker(D,p); if (e == 1) t = addiu(p, 1-s); else if (s == 1) t = powiu(p, e); else t = addui(1, mulii(subis(p, s), geomsum(p, e-1))); H = H? mulii(H,t): t; } return H; } static GEN hclassno6_large(GEN x) { GEN H = NULL, P, E, D = coredisc2_fact(absZ_factor(x), -1, &P, &E); long l = lg(P); if (l > 1 && lgefint(x) == 3) { /* F != 1, second chance */ ulong h = hclassno6u_no_cache(x[2]); if (h) H = utoipos(h); } if (!H) { H = quadclassno(D); switch(itou_or_0(D)) { case 3: H = shifti(H,1);break; case 4: H = muliu(H,3); break; default:H = muliu(H,6); break; } } return mulii(H, hclassnoF_fact(P, E, D)); } /* x > 0, x = 0,3 (mod 4). Return 6*hclassno(x), an integer */ GEN hclassno6(GEN x) { ulong d = itou_or_0(x); if (d) { /* create cache if d small */ ulong h = d < 500000 ? hclassno6u(d): hclassno6u_no_cache(d); if (h) return utoipos(h); } return hclassno6_large(x); } GEN hclassno(GEN x) { long a, s; if (typ(x) != t_INT) pari_err_TYPE("hclassno",x); s = signe(x); if (s < 0) return gen_0; if (!s) return gdivgs(gen_1, -12); a = mod4(x); if (a == 1 || a == 2) return gen_0; return gdivgu(hclassno6(x), 6); } /* return [N',v]; v contains all x mod N' s.t. x^2 + B x + C = 0 modulo N */ GEN Zn_quad_roots(GEN N, GEN B, GEN C) { pari_sp av = avma; GEN fa = NULL, D, w, v, P, E, F0, Q0, F, mF, A, Q, T, R, Np, N4; long l, i, j, ct; if ((fa = check_arith_non0(N,"Zn_quad_roots"))) { N = typ(N) == t_VEC? gel(N,1): factorback(N); fa = clean_Z_factor(fa); } N = absi_shallow(N); N4 = shifti(N,2); D = modii(subii(sqri(B), shifti(C,2)), N4); if (!signe(D)) { /* (x + B/2)^2 = 0 (mod N), D = B^2-4C = 0 (4N) => B even */ if (!fa) fa = Z_factor(N); P = gel(fa,1); E = ZV_to_zv(gel(fa,2)); l = lg(P); for (i = 1; i < l; i++) E[i] = (E[i]+1) >> 1; Np = factorback2(P, E); /* x = -B mod N' */ B = shifti(B,-1); return gerepilecopy(av, mkvec2(Np, mkvec(Fp_neg(B,Np)))); } if (!fa) fa = Z_factor(N4); else /* convert to factorization of N4 = 4*N */ fa = famat_reduce(famat_mulpows_shallow(fa, gen_2, 2)); P = gel(fa,1); l = lg(P); E = ZV_to_zv(gel(fa,2)); F = cgetg(l, t_VEC); mF= cgetg(l, t_VEC); F0 = gen_0; Q = cgetg(l, t_VEC); Q0 = gen_1; for (i = j = 1, ct = 0; i < l; i++) { GEN p = gel(P,i), q, f, mf, D0; long t2, s = E[i], t = Z_pvalrem(D, p, &D0), d = s - t; if (d <= 0) { q = powiu(p, (s+1)>>1); Q0 = mulii(Q0, q); continue; } /* d > 0 */ if (odd(t)) return NULL; t2 = t >> 1; if (i > 1) { /* p > 2 */ if (kronecker(D0, p) == -1) return NULL; q = powiu(p, s - t2); f = Zp_sqrt(D0, p, d); if (!f) return NULL; /* p was not actually prime... */ if (t2) f = mulii(powiu(p,t2), f); mf = Fp_neg(f, q); } else { /* p = 2 */ if (d <= 3) { if (d == 3 && Mod8(D0) != 1) return NULL; if (d == 2 && Mod4(D0) != 1) return NULL; Q0 = int2n(1+t2); F0 = NULL; continue; } if (Mod8(D0) != 1) return NULL; q = int2n(d - 1 + t2); f = Z2_sqrt(D0, d); if (t2) f = shifti(f, t2); mf = Fp_neg(f, q); } gel(Q,j) = q; gel(F,j) = f; gel(mF,j)= mf; j++; } setlg(Q,j); setlg(F,j); setlg(mF,j); if (is_pm1(Q0)) A = leafcopy(F); else { /* append the fixed congruence (F0 mod Q0) */ if (!F0) F0 = shifti(Q0,-1); A = shallowconcat(F, F0); Q = shallowconcat(Q, Q0); } ct = 1 << (j-1); T = ZV_producttree(Q); R = ZV_chinesetree(Q,T); Np = gmael(T, lg(T)-1, 1); B = modii(B, Np); if (!signe(B)) B = NULL; Np = shifti(Np, -1); /* N' = (\prod_i Q[i]) / 2 */ w = cgetg(3, t_VEC); gel(w,1) = icopy(Np); gel(w,2) = v = cgetg(ct+1, t_VEC); l = lg(F); for (j = 1; j <= ct; j++) { pari_sp av2 = avma; long m = j - 1; GEN u; for (i = 1; i < l; i++) { gel(A,i) = (m&1L)? gel(mF,i): gel(F,i); m >>= 1; } u = ZV_chinese_tree(A,Q,T,R); /* u mod N' st u^2 = B^2-4C modulo 4N */ if (B) u = subii(u,B); gel(v,j) = gerepileuptoint(av2, modii(shifti(u,-1), Np)); } return gerepileupto(av, w); } pari-2.17.2/src/basemath/pclgp.c0000644000175000017500000035063714676526175015051 0ustar billbill/* Copyright (C) 2000, 2012 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_subcyclo /* written by Takashi Fukuda */ #define onevec(x) const_vec(x,gen_1) #define nullvec() cgetg(1, t_VEC) #define order_f_x(f, x) Fl_order(x%f, eulerphiu(f), f) #define USE_MLL (1L<<0) #define NO_PLUS_PART (1L<<1) #define NO_MINUS_PART (1L<<2) #define SKIP_PROPER (1L<<3) #define SAVE_MEMORY (1L<<4) #define USE_FULL_EL (1L<<5) #define USE_BASIS (1L<<6) #define USE_FACTOR (1L<<7) #define USE_GALOIS_POL (1L<<8) #define USE_F (1L<<9) static ulong _get_d(GEN H) { return umael(H, 2, 1);} static ulong _get_f(GEN H) { return umael(H, 2, 2);} static ulong _get_h(GEN H) { return umael(H, 2, 3);} static long _get_s(GEN H) { return umael(H, 2, 4);} static long _get_g(GEN H) { return umael(H, 2, 5);} static GEN _get_H(GEN H) { return gel(H, 3);} static ulong K_get_d(GEN K) { return _get_d(gel(K,1)); } static ulong K_get_f(GEN K) { return _get_f(gel(K,1)); } static ulong K_get_h(GEN K) { return _get_h(gel(K,1)); } static long K_get_s(GEN K) { return _get_s(gel(K,1)); } static ulong K_get_g(GEN K) { return _get_g(gel(K,1)); } static GEN K_get_H(GEN K) { return _get_H(gel(K,1)); } static ulong K_get_dchi(GEN K) { return gel(K,6)[1]; } static ulong K_get_nconj(GEN K) { return gel(K,6)[2]; } /* G= is a cyclic group of order n and t=s^(-1). * convert sum_i a_i*s^i to sum_i b_i*t^i */ static GEN Flx_recip1_inplace(GEN x, long pn) { long i, lx = lg(x); if(lx-2 != pn) /* This case scarcely occurs */ { long ly = pn+2; GEN y = const_vecsmall(ly, 0); y[1] = x[1];y[2] = x[2]; for(i=3;i>1; for(i=3;i<=mid;i++) { t = x[i];x[i] = x[lx+2-i];x[lx+2-i] = t; } return Flx_renormalize(x, lx); } } /* Return h^degpol(P) P(x / h) */ static GEN Flx_rescale_inplace(GEN P, ulong h, ulong p) { long i, l = lg(P); ulong hi = h; for (i=l-2; i>=2; i--) { P[i] = Fl_mul(P[i], hi, p); if (i == 2) break; hi = Fl_mul(hi,h, p); } return P; } static GEN zx_to_Flx_inplace(GEN x, ulong p) { long i, lx = lg(x); for (i=2; i= n; determine K,L and reduce n if possible */ static GEN vecsmall2vec2(GEN e, long n) { long L = e[n+1] - e[n], K = e[n+1] - L*n; n--; while (n >= 0 && e[n+1] - L*n == K) n--; if (n < 0) e = nullvec(); else { setlg(e, n+2); e = zv_to_ZV(e); } return mkvec3(utoi(L), stoi(K), e); /* L >= 0 */ } /* z=zeta_{p^n}; return k s.t. (z-1)^k || f(z) assuming deg(f) a^2=b^2 mod 2^(n+2) <==> a=b,-b mod 2^(n+2) * g_n(a)=g_n(1+q0)^k <==> a=x(1+q0)^k x=1,-1 * gam[1+a]=k, k<0 ==> g_n(a)=0 * k>=0 ==> g_n(a)^(-1)=gamma^k, gamma=g_n(1+q0) */ static GEN set_gam2(long q01, long n) { long i, x, x1, pn, pn2; GEN gam; pn = (1L< a^(p-1)=b^(p-1) mod p^(n+1) <==> a=xb x= * g_n(a)=g_n(1+q0)^k <==> a=x(1+q0)^k x= * gam[1+a]=k, k<0 ==> g_n(a)=0 * k>=0 ==> g_n(a)^(-1)=gamma^k, gamma=g_n(1+q0) */ static GEN set_gam(long q01, long p, long n) { long i, j, g, g1, x, x1, p1, pn, pn1; GEN A, gam; p1 = p-1; pn = upowuu(p, n); pn1 = p*pn; gam = const_vecsmall(pn1, -1); g = pgener_Zl(p); g1 = Fl_powu(g, pn, pn1); A = Fl_powers(g1, p1-1, pn1); /* A[1+i]=g^(i*p^n) mod p^(n+1), 0<=i<=p-2 */ x = Fl_inv(q01, pn1); x1 = 1; for (i=0; i d */ cs = cgetg(2+phipn, t_VECSMALL); cs[1] = evalvarn(0); x = cgetg(1+lx, t_VECSMALL); gs = Fl_powers(g, phipn1-1, pn1); /* gs[1+i]=g^i(mod p^(n+1)), 0<=i d */ *++px = (y*gs[(s%pn_1)+ipnpn])%d; } } B = vecsmall_uniq(x); A = set_A(B, chi); for (s=0; s= d) ipn1d -= d; if ((sgn = chi[ipn1d])==0) continue; deg = Chi[jp]; /* jp!=0 because j0>=0 */ if (sgn>0) xij0[deg] += i; else xij0[deg] -= i; } } for (i=0; i0) x2[a1]+=a; else x2[a1]-=a; } for (i=0; i0)?f0<<1:2; else if (f==4) den = (chi[p%f]>0)?f0<<1:f0; else den = f0<<1; for (j=1; j=f) ipn1-=f; if ((sgn = chi[ipn1])>0) x2[j0]+=i; else if (sgn<0) x2[j0]-=i; } } for (i=0; i0) x2[a1]+=a; else x2[a1]-=a; } for (i=0; i=3 * f = conductor of Q(sqrt(m)) * q0 = lcm(f,p) = f0*p * qn = q0*p^n = f0*p^(n+1) * xi_n = qn^(-1)*sum_{1<=a<=qn,(a,qn)=1} a*chi(a)^(-1)*(Q_n/Q,a)^(-1) */ static GEN quadstkp(long p, long m, long n, int *chi) { long f, f0, pn, pn1, q0; GEN gam; f = ((m-1)%4==0)?labs(m):4*labs(m); pn = upowuu(p, n); pn1 = p*pn; if (f % p) { q0 = f * p; f0 = f; } else { q0 = f; f0 = f / p; } gam = set_gam((1+q0)%pn1, p, n); #ifdef DEBUG_QUADSTK return quadstkp_by_def(chi, gam, n, p, f, f0); #else return (f0!=1)?quadstkp1(chi, gam, n, p, f, f0):quadstkp2(chi, gam, n, p); #endif } /* p=2 */ static GEN quadstk2(long m, long n, int *chi) { long i, j, j0, f, f0, pn, pn1, pn2, pn2f, q0; GEN x, x2, gam; f = ((m-1)%4==0)?labs(m):4*labs(m); pn = 1L<=f) ipn2-=f; if ((sgn=chi[ipn2])>0) x2[j0]+=i; else if (sgn<0) x2[j0]-=i; } } for (f0<<=1, i=0; i Chin(a)=0 * k>=0 ==> Chin(a)=zeta_{p^n}^k */ static GEN set_chin(long p, long n) { long i, j, x = 1, g, gpn, pn, pn1; GEN chin, chin1; pn = upowuu(p, n); pn1 = p*pn; chin = const_vecsmall(pn1, -1); chin1 = chin+1; g = pgener_Zl(p); gpn = Fl_powu(g, pn, pn1); for (i=0; i>1; B = const_vecsmall(pn+1, 0); B2 = B+2; for (a=x=y=1; a <= qn1; a++) /* x=a%d, y=a%pn1 */ { int sgn = chi[x]; if (sgn) { long k = chin[y]; if (k >= 0) { if (sgn > 0) B2[k]++; else B2[k]--; } } if (++x == d) x = 0; if (++y == pn1) y = 0; } B = zx_renormalize(B, pn+2); e = (n==1)? zx_p_val(B, p, n) : ZX_p_val(ZX_rem(zx_to_ZX(B), polcyclo(pn, 0)), p, n); if (p==3 && chi[2] < 0) e--; /* 2 is a primitive root of 3^n (n>=1) */ return gc_long(av, e); } #ifdef DEBUG static int* set_quad_chi_slow(long m) { long a, d = (m-1) % 4? 4*m: m, f = labs(d); int *chi = (int*)stack_calloc(sizeof(int)*f); for (a=1; a kross(d,gi)=-1 (1<=i<=r), gi=proot(pi) */ static int* set_quad_chi(long m) { long d = (m-1) % 4? 4*m: m, f = labs(d); GEN fa = factoru(f), P = gel(fa, 1), E = gel(fa,2), u, v; long i, j, np, nm, l = lg(P); int *chi = (int*)stack_calloc(sizeof(int)*f); pari_sp av = avma; int *plus = (int*)stack_calloc(sizeof(int)*f), *p0 = plus; int *minus = (int*)stack_calloc(sizeof(int)*f), *p1 = minus; u = cgetg(32, t_VECSMALL); v = cgetg(32, t_VECSMALL); for (i = 1; i < l; i++) { ulong q = upowuu(P[i], E[i]), fq = f / q; u[i] = q * Fl_inv(q % fq, fq); /* 1 mod f/q, 0 mod q */ v[i] = Fl_sub(1, u[i], f); /* => gv + u is 1 mod f/q and g mod q */ } if (E[1]==2) /* f=4*(-m) */ { *p0++ = Fl_add(v[1], u[1], f); *p1++ = Fl_add(Fl_mul(3, v[1], f), u[1], f); i = 2; } else if (E[1]==3) /* f=8*(-m) */ { ulong a; *p0++ = Fl_add(v[1], u[1], f); a = Fl_add(Fl_mul(3, v[1], f), u[1], f); if (kross(d, a) > 0) *p0++ = a; else *p1++ = a; a = Fl_add(Fl_mul(5, v[1], f), u[1], f); if (kross(d, a) > 0) *p0++ = a; else *p1++ = a; a = Fl_add(Fl_mul(7, v[1], f), u[1], f); if (kross(d, a) > 0) *p0++ = a; else *p1++ = a; i = 2; } else /* f=-m */ {*p0++ = 1; i = 1; } for (; i < l; i++) { ulong gn, g = pgener_Fl(P[i]); gn = g = Fl_add(Fl_mul(g, v[i], f), u[i], f); np = p0-plus; nm = p1-minus; for (;;) { for (j = 0; j < np; j++) *p1++ = Fl_mul(plus[j], gn, f); for (j = 0; j < nm; j++) *p0++ = Fl_mul(minus[j], gn, f); gn = Fl_mul(gn, g, f); if (gn == 1) break; for (j= 0; j < np; j++) *p0++ = Fl_mul(plus[j], gn, f); for (j = 0; j < nm; j++) *p1++ = Fl_mul(minus[j], gn, f); gn = Fl_mul(gn, g, f); if (gn == 1) break; } } np = p0-plus; nm = p1-minus; for (i = 0; i < np; i++) chi[plus[i]] = 1; for (i = 0; i < nm; i++) chi[minus[i]] = -1; set_avma(av); return chi; } static long srh_x(GEN T, long n, long x) { for (; x. * chi, chi^p, ... , chi^(p^(d_chi-1)) are conjugate. * {chi^j | j in C} are repre. of Q_p-congacy classes of inj. chars. * * C is a set of representatives of H/

, where H=(Z/dZ)^* */ static GEN set_C(long p, long d, long d_chi, long n_conj) { long i, j, x, y, pmodd = p%d; GEN T = const_vecsmall(d, 0)+1; GEN C = cgetg(1+n_conj, t_VECSMALL); if (n_conj==1) { C[1] = 1; return C; } for (i=0, x=1; x >= 0; x = srh_x(T, d, x)) { if (cgcd(x, d)==1) C[++i] = x; for (j=0, y=x; j= 0)? gerepileuptoint(av, subii(z, m)): z; } return x; } /* assume 0 <= x[i], y[j] <= m-1 */ static GEN FpV_shift_sub(GEN x, GEN y, GEN m, long start, long end) { long i, j; for (i=start, j=1; i<=end; i++, j++) { pari_sp av = avma; GEN z = subii(gel(x, i), gel(y, j)); gel(x, i) = (signe(z) < 0)? gerepileuptoint(av, addii(z, m)): z; } return x; } /* assume 0 <= x[i], y[j] <= m-1 */ static GEN Flv_shift_add(GEN x, GEN y, ulong m, long start, long end) { long i, j; for (i=start, j=1; i<=end; i++, j++) { ulong xi = x[i], yj = y[j]; x[i] = Fl_add(xi, yj, m); } return x; } /* assume 0 <= x[i], y[j] <= m-1 */ static GEN Flv_shift_sub(GEN x, GEN y, ulong m, long start, long end) { long i, j; for (i=start, j=1; i<=end; i++, j++) { ulong xi = x[i], yj = y[j]; x[i] = Fl_sub(xi, yj, m); } return x; } /* return 0 if p|x. else return 1 */ INLINE long Flx_divcheck(GEN x, ulong p) { long i, l = lg(x); for (i=2; i=pn) d = pn; return d; } /* Flx_translate1_basecase(g, pn) becomes slow when degpol(g)>1000. * So I wrote Flxn_translate1(). * I need lambda to truncate pol. * But I need to translate T --> 1+T to know lambda. * Though the code has a little overhead, it is still fast. */ static GEN Flxn_translate1(GEN g, long p, long n) { long i, j, d, lam, pn, start; if (n==1) start = 3; else if (n==2) start = 9; else start = 10; pn = upowuu(p, n); for (lam=start; lam; lam<<=1) /* least upper bound is 3 */ { GEN z; d = deg_trunc(lam, p, n, pn); z = const_vecsmall(d+1, 0); /* z[2],...,z[d+1] <--> a_0,...,a_{d-1} */ for (i=degpol(g); i>=0; i--) { for (j=d+1; j>2; j--) z[j] = Fl_add(z[j], z[j-1], pn); /* z = z*(1+T) */ z[2] = Fl_add(z[2], g[2+i], pn); } z = Flx_renormalize(z, d+2); if (Flx_weier_deg(z, p) <= lam) return z; } return NULL; /*LCOV_EXCL_LINE*/ } static GEN FlxXn_translate1(GEN g, long p, long n) { long i, j, d, lam, pn, start; GEN z; if (n==1) start = 3; else if (n==2) start = 9; else start = 10; pn = upowuu(p, n); for (lam=start; lam; lam<<=1) /* least upper bound is 3 */ { d = deg_trunc(lam, p, n, pn); z = const_vec(d+1, pol0_Flx(0)); /* z[2],...,z[d+1] <--> a_0,...,a_{d-1} */ settyp(z, t_POL); z[1] = evalsigne(1) | evalvarn(0); for (i=degpol(g); i>=0; i--) { for (j=d+1; j>2; j--) gel(z, j) = Flx_add(gel(z, j), gel(z, j-1), pn); gel(z, 2) = Flx_add(gel(z, 2), gel(g, 2+i), pn); } z = FlxX_renormalize(z, d+2); if (FlxX_weier_deg(z, p) <= lam) return z; } return NULL; /*LCOV_EXCL_LINE*/ } /* lam < 0 => error (lambda can't be determined) * lam = 0 => return 1 * lam > 0 => return dist. poly. of degree lam. */ static GEN Flxn_Weierstrass_prep(GEN g, long p, long n, long d_chi) { long i, r0, d, dg = degpol(g), lam, pn, t; ulong lam0; GEN U, UINV, P, PU, g0, g1, gp, gU; if ((lam = Flx_weier_deg(g, p))==0) return(pol1_Flx(0)); else if (lam<0) pari_err(e_MISC,"Flxn_Weierstrass_prep: precision too low. Increase n!"); lam0 = lam/d_chi; pn = upowuu(p, n); d = deg_trunc(lam, p, n, pn); if (d>dg) d = dg; if (d<=lam) d=1+lam; for (r0=1; upowuu(p, r0) output xi_n * (flag&2)!=0 ==> output power series * (flag&4)!=0 ==> output Iwasawa polynomial */ static GEN imagquadstkpol(long p, long m, long n) { long pn = upowuu(p, n); GEN pol, stk, stk2; int *chi; if (p==2 && (m==-1 || m==-2 || m==-3 || m==-6)) return nullvec(); if (p==3 && m==-3) return nullvec(); if (p==2 && m%2==0) m /= 2; chi = set_quad_chi(m); stk = (p==2)? quadstk2(m, n, chi): quadstkp(p, m, n, chi); stk2 = zx_to_Flx(stk, pn); pol = Flxn_Weierstrass_prep(zlx_translate1(stk2, p, n), p, n, 1); return degpol(pol)? mkvec(Flx_to_ZX(pol)): nullvec(); } /* a mod p == g^i mod p ==> omega(a)=zeta_(p-1)^(-i) * Chi[g^i mod p]=i (0 <= i <= p-2) */ static GEN get_teich(long p, long g) { long i, gi = 1, p1 = p-1; GEN Chi = cgetg(p, t_VECSMALL); for (i=0; i (1+T)(1+q0)^(-1) */ static GEN realquadstkpol(long p, long m, long n) { int *chi; long pnm1 = upowuu(p, n-1),pn = p*pnm1, pn1 = p*pn, d, q0; GEN stk, ser, pol; if (m==1) pari_err_DOMAIN("quadstkpol", "m", "=", gen_1, gen_1); if (p==2 && (m&1)==0) m>>=1; d = ((m&3)==1)?m:m<<2; q0 = ulcm((p==2)?4:p, d); if (p==2) { chi = set_quad_chi(-m); stk = quadstk2(-m, n, chi); stk = zx_to_Flx_inplace(stk, pn); } else if (p==3 && m%3==0 && kross(-m/3,3)==1) { long m3 = m/3; chi = set_quad_chi(-m3); stk = quadstkp(3, -m3, n, chi); stk = zx_to_Flx_inplace(stk, pn); } else { long g = pgener_Zl(p); long x = Fl_powu(Fl_inv(g, p), pnm1, pn); GEN Chi = get_teich(p, g); GEN Gam = set_gam((1+q0)%pn1, p, n); chi = set_quad_chi(m); stk = quadteichstk(Chi, chi, Gam, p, m, n); /* exact */ stk = zxX_to_FlxX(stk, pn); /* approx. */ stk = FlxY_evalx(stk, x, pn); } stk = Flx_rescale_inplace(Flx_recip1_inplace(stk, pn), (1+q0)%pn, pn); ser = Flxn_translate1(stk, p, n); pol = Flxn_Weierstrass_prep(ser, p, n, 1); return degpol(pol)? mkvec(Flx_to_ZX(pol)): nullvec(); } /* m > 0 square-free. lambda_2(Q(sqrt(-m))) * Kida, Tohoku Math. J. vol.31 (1979), 91-96, Theorem 1. */ static GEN quadlambda2(long m) { long i, l, L; GEN P; if ((m&1)==0) m >>= 1; /* lam_2(Q(sqrt(-m)))=lam_2(Q(sqrt(-2*m))) */ if (m <= 3) return mkvecs(0); P = gel(factoru(m), 1); l = lg(P); for (L = -1,i = 1; i < l; i++) L += 1L << (-3 + vals(P[i]-1) + vals(P[i]+1)); return mkvecs(L); } /* Iwasawa lambda invariant of Q(sqrt(m)) (m<0) for p * |A_n|=p^(e[n]) * kross(m,p)!=1 : e[n]-e[n-1] lambda=e[n]-e[n-1] * kross(m,p)==1 : e[n]-e[n-1]<=eulerphi(p^n) ==> lambda=e[n]-e[n-1] * Gold, Acta Arith. XXVI (1974), p.25, Cor. 3 * Gold, Acta Arith. XXVI (1975), p.237, Cor. */ static GEN quadlambda(long p, long m) { long flag, n, phipn; GEN e = cgetg(31, t_VECSMALL); int *chi; if (m>0) pari_err_IMPL("plus part of lambda invariant in quadlambda()"); if (p==2) return quadlambda2(-m); if (p==3 && m==-3) return mkvec3(gen_0, gen_0, nullvec()); flag = kross(m, p); e[1] = Z_lval(quadclassno(quaddisc(stoi(m))), p); if (flag!=1 && e[1]==0) return mkvec3(gen_0, gen_0, nullvec()); chi = set_quad_chi(m); phipn = p-1; /* phipn=phi(p^n) */ for (n=1; n; n++, phipn *= p) { long L = flag? ediff(p, m, n, chi): ediff_ber(p, m, n, chi); e[n+1] = e[n] + L; if ((flag!=1 && (L < phipn))|| (flag==1 && (L <= phipn))) break; } return vecsmall2vec2(e, n); } /* factor n-th cyclotomic polynomial mod p^r and return a minimal * polynomial of zeta_n over Q_p. * phi(n)=deg*n_conj, n_conj == 1 <=> polcyclo(n) is irred mod p. */ static GEN set_minpol(ulong n, GEN p, ulong r, long n_conj) { GEN z, v, pol, pr; pari_timer ti; if (umodiu(p, n)==1) /* zeta_n in Z_p, faster than polcyclo() */ { GEN prm1 = powiu(p, r-1), pr = mulii(prm1, p); /* pr=p^r */ GEN prn = diviuexact(subii(pr, prm1), n); /* prn=phi(p^r)/n */ z = Fp_pow(pgener_Fp(p), prn, pr); return deg1pol_shallow(gen_1, Fp_neg(z, pr), 0); } pr = powiu(p, r); pol = polcyclo(n, 0); if (n_conj==1) return FpX_red(pol, pr); if (DEBUGLEVEL>3) timer_start(&ti); z = FpX_one_cyclo(n, p); if (DEBUGLEVEL>3) timer_printf(&ti, "FpX_one_cyclo:n=%ld ", n); v = ZpX_liftfact(pol, mkvec2(z, FpX_div(pol, z, p)), pr, p, r); return gel(v, 1); } static GEN set_minpol_teich(ulong g_K, GEN p, ulong r) { GEN prm1 = powiu(p, r-1), pr = mulii(prm1, p), z; z = Fp_pow(Fp_inv(utoi(g_K), p), prm1, pr); return deg1pol_shallow(gen_1, Fp_neg(z, pr), 0); } static long srh_1(GEN H) { GEN bits = gel(H, 3); ulong f = bits[1]; return F2v_coeff(bits, f-1); } /* (1/f)sum_{1<=a<=f}a*chi^{-1}(a) = -(1/(2-chi(a)))sum_{1<=a<=f/2} chi^{-1}(a) * does not overflow */ static GEN zx_ber_num(GEN Chi, long f, long d) { long i, f2 = f>>1; GEN x = const_vecsmall(d+1, 0), x2 = x+2; for (i = 1; i <= f2; i++) if (Chi[i] >= 0) x2[Chi[i]] ++; return zx_renormalize(x, d+2); } /* x a zx * zx_ber_num is O(f). ZX[FpX,Flx]_ber_conj is O(d). Sometimes d<=0) gel(x2, Fl_neg(Fl_mul(Chi[2], j, d), d)) = gen_1; gel(x2, 0) = subiu(gel(x2, 0), 2); return ZX_renormalize(x, d+2); } static GEN Flx_ber_den(GEN Chi, long j, long d, ulong p) { GEN x = const_vecsmall(d+1, 0), x2 = x+2; if (Chi[2]>=0) x2[Fl_neg(Fl_mul(Chi[2], j, d), d)] = 1; x2[0] = Fl_sub(x2[0], 2, p); return Flx_renormalize(x, d+2); } /* x is ZX of deg <= d-1 */ static GEN ber_conj(GEN x, long k, long d) { long i, deg = degpol(x); GEN z = pol_zero(d); if (k==1) for (i=0; i<=deg; i++) gel(z, 2+i) = gel(x, 2+i); else for (i=0; i<=deg; i++) gel(z, 2+Fl_mul(i, k, d)) = gel(x, 2+i); return ZX_renormalize(z, d+2); } /* The computation is fast when p^n and el=1+k*f*p^n are less than 2^64 * for m <= n <= M * We believe M>=3 is enough when f%p=0 and M>=2 is enough for other case * because we expect that p^2 does not divide |A_{K,psi}| for a large p. * FIXME: M should be set according to p and f. */ static void set_p_f(GEN pp, ulong f, long *pm, long *pM) { ulong p = itou_or_0(pp); if (!p || p >= 2000000) { *pm=2; *pM = dvdui(f, pp)? 3: 2; } else if (p == 3) { *pm=5; *pM=20; } else if (p == 5) { *pm=5; *pM=13; } else if (p == 7) { *pm=5; *pM=11; } else if (p == 11) { *pm=5; *pM=9; } else if (p == 13) { *pm=5; *pM=8; } else if (p < 400) { *pm=5; *pM=7; } else if (p < 5000) { *pm=3; *pM=5; } else if (p < 50000) { *pm=2; *pM=4; } else { *pm=2; *pM=3; } } static GEN subgp2ary(GEN H, long n) { GEN v = gel(H, 3), w = cgetg(n+1, t_VECSMALL); long i, j, f = v[1]; for (i = 1, j = 0; i <= f; i++) if (F2v_coeff(v,i)) w[++j] = i; return w; } static GEN Flv_FlvV_factorback(GEN g, GEN x, ulong q) { pari_APPLY_ulong(Flv_factorback(g, gel(x,i), q)) } /* lift chi character on G/H to character on G */ static GEN zncharlift(GEN chi, GEN ncycGH, GEN U, GEN cycG) { GEN nchi = char_normalize(chi, ncycGH); GEN c = ZV_ZM_mul(gel(nchi, 2), U), d = gel(nchi, 1); return char_denormalize(cycG, d, c); } /* 0 <= c[i] < d, i=1..r; (c[1],...,c[r], d) = 1; find e[i] such that * sum e[i]*c[i] = 1 mod d */ static GEN Flv_extgcd(GEN c, ulong d) { long i, j, u, f, l = lg(c); GEN e = zero_zv(l-1); if (l == 1) return e; for (f = d, i = 1; f != 1 && i < l; i++) { f = cbezout(f, itou(gel(c,i)), &u, &e[i]); if (!e[i]) continue; e[i] = umodsu(e[i], d); u = umodsu(u, d); if (u != 1) for (j = 1; j < i; j++) e[j] = Fl_mul(e[j], u, d); } return e; } /* f!=p; return exact xi. */ static GEN get_xi_1(GEN Chi, GEN Gam, long p, long f, long n, long d, ulong pm) { GEN Gam1 = Gam+1, xi; long i, j, j0, f0, pn, pn1, deg, pn1f; f0 = (f%p)?f:f/p; pn = upowuu(p, n); pn1 = p*pn; pn1f = pn1%f; xi = cgetg(pn+2, t_POL); xi[1] = evalsigne(1) | evalvarn(0); for (i=0; i= f) ipn1 -= f; if (ipn1==0 || (deg = Chi[ipn1])<0) continue; xij0[deg] += i; } } for (i=0; i1) timer_start(&ti); ser = (d_chi==1) ? Flxn_translate1(xi_conj, p, n) : FlxXn_translate1(xi_conj, p, n); if (DEBUGLEVEL>1) timer_printf(&ti, "Flx%sn_translate1",(d_chi==1)?"":"X"); wd = (d_chi==1)?Flx_weier_deg(ser, p):FlxX_weier_deg(ser, p); if (wd<0) pari_err(e_MISC,"pol_chi_xi: precision too low. Increase n!\n"); else if (wd==0) return pol_1(0); /* wd>0, convert to dist. poly. */ if (d_chi>1) /* f!=p. minpolpow==n */ { ser = FlxqX_xi_norm(ser, MinPol2, p, d, upowuu(p, n)); ser = FlxX_to_Flx(ser); } pol = Flx_to_ZX(Flxn_Weierstrass_prep(ser, p, n, d_chi)); setvarn(pol, fetch_user_var("T")); #ifdef DEBUG if (wd>0 && d_chi>1) err_printf("(wd,d_chi,p,f,d,j,H)=(%ld,%ld,%ld,%ld,%ld,%ld,%Ps)\n", wd,d_chi,p,f,d,j,gmael3(K, 1, 1, 1)); #endif return gerepilecopy(av, pol); } /* return 0 if lam_psi (psi=chi^j) is determined to be zero. * else return -1. * If psi(p)!=1, then N_{Q(zeta_d)/Q}(1-psi(p))!=0 (mod p) */ static long lam_chi_ber(GEN K, long p, long j) { pari_sp av = avma; GEN B1, B2, Chi = gel(K, 2), MinPol2 = gel(K, 7), B_num = gel(K, 8); long x, p2 = p*p, d = K_get_d(K), f = K_get_f(K); if (f == d+1 && p == f && j == 1) return 0; /* Teichmuller */ B1 = Flx_rem(Flx_ber_conj(B_num, j, d, p2), MinPol2, p2); B2 = Flx_rem(Flx_ber_den(Chi, j, d, p2), MinPol2, p2); if (degpol(B1)<0 || degpol(B2)<0) return gc_long(av, -1); /* 0 mod p^2 */ x = zx_lval(B1, p) - zx_lval(B2, p); if (x<0) pari_err_BUG("subcycloiwasawa [Bernoulli number]"); return gc_long(av, x==0 ? 0: -1); } static long lam_chi_xi(GEN K, long p, long j, long n) { pari_sp av = avma; GEN xi_conj, z, MinPol2 = gel(K, 7), xi = gel(K, 8); long d = K_get_d(K), f = K_get_f(K), d_chi = K_get_dchi(K); long wd, minpolpow = (f==p)?n+2:1, pm = upowuu(p, minpolpow); /* xi is FlxX mod p^m, MinPol2 is Flx mod p^m, xi_conj is FlxqX. */ xi_conj = FlxqX_xi_conj(xi, MinPol2, j, d, pm); if (d_chi==1) /* d_chi==1 if f==p */ { xi_conj = FlxX_to_Flx(xi_conj); if (f==p) xi_conj = zx_z_divexact(xi_conj, upowuu(p, n+1)); } /* Now xi_conj is mod p^n */ z = (d_chi==1) ? Flxn_translate1(xi_conj, p, n) : FlxXn_translate1(xi_conj, p, n); wd = (d_chi==1)?Flx_weier_deg(z, p):FlxX_weier_deg(z, p); #ifdef DEBUG if (wd>0 && d_chi>1) err_printf("(wd,d_chi,p,f,d,j,H)=(%ld,%ld,%ld,%ld,%ld,%ld,%Ps)\n", wd,d_chi,p,f,d,j,gmael3(K, 1, 1, 1)); #endif return gc_long(av, wd<0 ? -1 : wd*d_chi); } /* K = [H1, Chi, Minpol, C, [d_chi, n_conj]] */ static GEN imag_cyc_pol(GEN K, long p, long n) { pari_sp av = avma; GEN Chi = gel(K, 2), MinPol = gel(K, 3), C = gel(K, 4), MinPol2; long d_K = K_get_d(K), f = K_get_f(K), n_conj = K_get_nconj(K); long i, q0, pn1, pM, pmodf = p%f, n_done = 0; GEN z = nullvec(), Gam, xi, Lam, K2; Lam = const_vecsmall(n_conj, -1); if (pmodf==0 || Chi[pmodf]) /* mark trivial chi-part using Bernoulli number */ { MinPol2 = ZX_to_Flx(MinPol, p*p); /* p^2 for B_{1,chi} */ K2 = shallowconcat(K, mkvec2(MinPol2, zx_ber_num(Chi, f, d_K))); for (i=1; i<=n_conj; i++) if ((Lam[i] = lam_chi_ber(K2, p, C[i])) == 0) n_done++; if (n_conj==n_done) return gerepilecopy(av, z); /* all chi-parts trivial */ } q0 = (f%p)? f*p: f; pn1 = upowuu(p, n+1); Gam = set_gam((1+q0)%pn1, p, n); pM = upowuu(p, (f==p)? 2*n+1: n); MinPol2 = ZX_to_Flx(MinPol, pM); xi = (f==p)? get_xi_2(Chi, Gam, p, f, n, d_K, pM) : get_xi_1(Chi, Gam, p, f, n, d_K, pM); K2 = shallowconcat(K, mkvec2(MinPol2, xi)); for (i=1; i<=n_conj; i++) { GEN z1; if (Lam[i]>=0) continue; z1 = pol_chi_xi(K2, p, C[i], n); if (degpol(z1)) z = vec_append(z, z1); /* degpol(z1) may be zero */ } return gerepilecopy(av, z); } /* K is an imaginary cyclic extension of degree d contained in Q(zeta_f) * H is the subgr of G=(Z/fZ)^* corresponding to K * h=|H|, d*h=phi(f) * G/H= i.e. g^d \in H * d_chi=[Q_p(zeta_d):Q_p], i.e. p^d_chi=1 (mod d) * An inj. char. of G(K/Q) is automatically imaginary. * * G(K/Q)=G/H=, chi:G(K/Q) -> overline{Q_p} s.t. chi(g)=zeta_d^(-1) * Chi[a]=k, k<0 => chi(a)=0 * k>=0 => chi(a)=zeta_d^(-k) * psi=chi^j, j in C : repre. of inj. odd char. * psi(p)==1 <=> chi(p)^j==0 <=> j*Chi[p]=0 (mod d) <=> Chi[p]==0 * * K = [H1, Chi, Minpol, C, [d_chi, n_conj]] */ static long imag_cyc_lam(GEN K, long p) { pari_sp av = avma; GEN Chi = gel(K, 2), MinPol = gel(K, 3), C = gel(K, 4), MinPol2; long d_K = K_get_d(K), f = K_get_f(K), n_conj = K_get_nconj(K); long i, q0, n, pmodf = p%f, n_done = 0; ulong pn1, pM; GEN p0 = utoi(p), Gam, Lam, xi, K2; q0 = (f%p)? f*p: f; Lam = const_vecsmall(n_conj, -1); if (pmodf==0 || Chi[pmodf]) /* 1st trial is Bernoulli number */ { MinPol2 = ZX_to_Flx(MinPol, p*p); /* p^2 for B_{1,chi} */ K2 = shallowconcat(K, mkvec2(MinPol2, zx_ber_num(Chi, f, d_K))); for (i=1; i<=n_conj; i++) if ((Lam[i] = lam_chi_ber(K2, p, C[i])) == 0) n_done++; if (n_conj==n_done) return gc_long(av, 0); /* all chi-parts trivial */ } pM = pn1 = p; for (n=1; n>=0; n++) /* 2nd trial is Stickelberger element */ { pn1 *= p; /* p^(n+1) */ if (f == p) { /* do not use set_minpol: it returns a new pol for each call */ GEN fac, cofac, v, pol = polcyclo(d_K, 0); pM = pn1 * p; /* p^(n+2) */ fac = FpX_red(MinPol, p0); cofac = FpX_div(pol, fac, p0); v = ZpX_liftfact(pol, mkvec2(fac, cofac), utoipos(pM), p0, n+2); MinPol2 = gel(v, 1); } Gam = set_gam((1+q0)%pn1, p, n); MinPol2 = ZX_to_Flx(MinPol, pM); xi = (f==p)? get_xi_2(Chi, Gam, p, f, n, d_K, pM) : get_xi_1(Chi, Gam, p, f, n, d_K, pM); K2 = shallowconcat(K, mkvec2(MinPol2, xi)); for (i=1; i<=n_conj; i++) if (Lam[i]<0 && (Lam[i] = lam_chi_xi(K2, p, C[i], n)) >= 0) n_done++; if (n_conj==n_done) break; } return gc_long(av, zv_sum(Lam)); } static GEN GHinit(long f, GEN HH, GEN *pcycGH) { GEN G = znstar0(utoipos(f), 1); GEN U, Ui, cycG, cycGH, ncycGH, gG, gGH, vChar, vH1, P, gH = gel(HH, 1); long i, expG, n_f, lgH = lg(gH); /* gens. of H */ P = cgetg(lgH, t_MAT); for (i = 1; i < lgH; i++) gel(P,i) = Zideallog(G, utoi(gH[i])); /* group structure of G/H */ cycG = znstar_get_cyc(G); expG = itou(gel(cycG, 1)); /* gG generators of G, gGH generators of G/H: gGH = g.Ui, g = gGH.U */ cycGH = ZM_snf_group(hnfmodid(P, cycG), &U, &Ui); ncycGH = cyc_normalize(cycGH); gG = ZV_to_Flv(znstar_get_gen(G), f); /* gens. of G */ /* generators of G/H */ gGH = Flv_FlvV_factorback(gG, ZM_to_Flm(Ui, expG), f); vChar = chargalois(cycGH, NULL); n_f = lg(vChar)-2; vH1 = cgetg(n_f+1, t_VEC); for (i = 1; i <= n_f; i++) { /* skip trivial character */ GEN chi = gel(vChar,i+1), nchi = char_normalize(chi, ncycGH); GEN chiG, E, H1, C = gel(nchi, 2); long e, he, gen, d = itou(gel(nchi, 1)); /* chi(prod g[i]^e[i]) = e(sum e[i]*C[i] / d), chi has order d = #(G/H1)*/ E = Flv_extgcd(C, d); /* \sum C[i]*E[i] = 1 in Z/dZ */ chiG = zncharlift(chi, ncycGH, U, cycG); H1 = charker(cycG, chiG); /* H1 < G with G/H1 cyclic */ e = itou( zncharconductor(G, chiG) ); /* cond H1 = cond chi */ H1 = Flv_FlvV_factorback(zv_to_Flv(gG, e), ZM_to_Flm(H1, expG), e); gen = Flv_factorback(zv_to_Flv(gGH, e), E, e); H1 = znstar_generate(e, H1); /* G/H1 = , chi(gen) = e(1/d) */ he = eulerphiu(e) / d; /* G/H1 = cyclic of index d, e = cond(H1) */ gel(vH1,i) = mkvec3(H1, mkvecsmall5(d,e,he,srh_1(H1), gen), subgp2ary(H1, he)); } if (pcycGH) *pcycGH = cycGH; return vH1; } /* aH=g^iH ==> chi(a)=zeta_n^(-i); Chi[g^iH]=i; Chi[0] is never accessed */ static GEN get_chi(GEN H1) { GEN H = _get_H(H1); long i, j, gi, d = _get_d(H1), f = _get_f(H1), h = _get_h(H1), g = _get_g(H1); GEN Chi = const_vecsmall(f-1, -1); for (j=1; j<=h; j++) Chi[H[j]] = 0; /* i = 0 */ for (i = 1, gi = g; i < d; i++) { for (j=1; j<=h; j++) Chi[Fl_mul(gi, H[j], f)] = i; gi = Fl_mul(gi, g, f); } return Chi; } static void errpdiv(const char *f, GEN p, long d) { pari_err_DOMAIN(f, "p", "divides", strtoGENstr(stack_sprintf("[F:Q] = %ld", d)), p); } /* p odd doesn't divide degF; return lambda invariant if n==0 and * iwasawa polynomials if n>=1 */ static GEN abeliwasawa(long p, long f, GEN HH, long degF, long n) { long lam = 0, i, n_f; GEN vH1, vData, z = nullvec(), p0 = utoi(p) ; vH1 = GHinit(f, HH, NULL); n_f = lg(vH1)-1; vData = const_vec(degF, NULL); for (i=1; i<=n_f; i++) /* prescan. set Teichmuller */ { GEN H1 = gel(vH1,i); long d_K = _get_d(H1), f_K = _get_f(H1), g_K = _get_g(H1); if (f_K == d_K+1 && p == f_K) /* found K=Q(zeta_p) */ { long d_chi = 1, n_conj = eulerphiu(d_K); GEN C = set_C(p, d_K, d_chi, n_conj); long minpow = n? 2*n+1: 2; GEN MinPol = set_minpol_teich(g_K, p0, minpow); gel(vData, d_K) = mkvec4(MinPol, C, NULL, mkvecsmall2(d_chi, n_conj)); break; } } for (i=1; i<=n_f; i++) { GEN H1 = gel(vH1,i), z1, Chi, K; long d_K = _get_d(H1), s = _get_s(H1); if (s) continue; /* F is real */ #ifdef DEBUG err_printf(" handling %s cyclic subfield K, deg(K)=%ld, cond(K)=%ld\n", s? "a real": "an imaginary", d_K, _get_f(H1)); #endif if (!gel(vData, d_K)) { long d_chi = order_f_x(d_K, p), n_conj = eulerphiu(d_K)/d_chi; GEN C = set_C(p, d_K, d_chi, n_conj); long minpow = n? n+1: 2; GEN MinPol = set_minpol(d_K, p0, minpow, n_conj); gel(vData, d_K) = mkvec4(MinPol, C, NULL, mkvecsmall2(d_chi, n_conj)); } Chi = get_chi(H1); K = shallowconcat(mkvec2(H1, Chi), gel(vData, d_K)); if (n==0) lam += imag_cyc_lam(K, p); else if (lg(z1 = imag_cyc_pol(K, p, n)) > 1) z = shallowconcat(z, z1); } return n? z: mkvecs(lam); } static GEN ary2mat(GEN x, long n) { long i, j; GEN z = cgetg(n+1,t_MAT); for (i=1; i<=n; i++) { gel(z,i) = cgetg(n+1,t_COL); for (j=1; j<=n; j++) gmael(z, i, j) = utoi(x[(i-1)*n+j-1]); } return z; } static long is_cyclic(GEN x) { GEN y = gel(x, 2); long i, l = lg(y), n = 0; for (i = 1; i < l; i++) if (signe(gel(y,i))) n++; return n <= 1; } static GEN make_p_part(GEN y, ulong p, long d_pow) { long i, l = lg(y); GEN z = cgetg(l, t_VECSMALL); for (i = 1; i < l; i++) z[i] = signe(gel(y,i))? Z_lval(gel(y,i), p): d_pow; return z; } static GEN structure_MLL(GEN y, long d_pow) { long y0, i, l = lg(y); GEN x = gen_0, E = cgetg(l, t_VEC); for (i = 1; i < l; i++) { if ((y0 = d_pow-y[i]) < 0) y0 = 0; x = addiu(x, y0); gel(E, l-i) = utoi(y0); } return mkvec2(x, E); } static long find_del_el(GEN *oldgr, GEN newgr, long n, long n_el, long d_chi) { if (n_el==1) return 1; if (equalis(gmael(newgr, 2, 1), n_el)) return n; if (cmpii(gel(*oldgr, 1), gel(newgr, 1)) >= 0) return n; if (n > 1 && is_cyclic(newgr)) { *oldgr = newgr; return n-1; } if (n == n_el) return n; if (cmpis(gel(newgr, 1), n*d_chi) < 0) return n; return 0; } static GEN subgr2vecsmall(GEN H, long h, long f) { long i; GEN z = const_vecsmall(f-1, 0); /* f=lg(z) */ for (i=1; i<=h; i++) z[H[i]] = 1; /* H[i]!=0 */ return z; } /* K is the subfield of Q(zeta_f) with degree d corresponding to the subgroup * H in (Z/fZ)^*; for a divisor e of f, zeta_e \in K <=> H \subset He. */ static long root_of_1(long f, GEN H) { GEN g = gel(H, 1); /* generators */ long e = f, i, l = lg(g); for (i = 1; i < l; i++) { e = cgcd(e, g[i] - 1); if (e <= 2) return 2; } return odd(e)? (e<<1): e; } static long find_ele(GEN H) { long i, f=lg(H); for (i=1; i0; i++) { coset[1+i] = j; delete_ele(H2, j, el); } if (i != k) pari_err_BUG("failed to find coset\n"); return coset; } static long srh_pol(GEN xpows, GEN vn, GEN pols, long el, long k, long f) { pari_sp av = avma; long i, j, l = lg(pols), d = degpol(gel(pols, 1)); GEN pol = gel(pols, 1); for (i=1; i>1; for (i=1; i<=d_K; i++) { GEN y = real_1(prec); for (j=1; j<=h2; j++) { GEN z = gmael(vz_f, 1+Fl_mul(H[j], g, f), 1); y = mulrr(y, shiftr(subsr(1, z), 1)); } gel(xi, i) = y; g = Fl_mul(g, g_K, f); } return gerepilecopy(av, xi); } static GEN theta_xi_el(GEN K, ulong el) { pari_sp av = avma; GEN H = K_get_H(K); ulong d_K = K_get_d(K), f = K_get_f(K), h = K_get_h(K), g_K = K_get_g(K); GEN theta = cgetg(d_K+1, t_VECSMALL), xi = cgetg(d_K+1, t_VECSMALL), vz_f; ulong i, j, g = 1, x, y, g_el, z_f; g_el = pgener_Fl(el); z_f = Fl_powu(g_el, (el-1)/f, el); vz_f = Fl_powers(z_f, f-1, el); for (i=1; i<=d_K; i++) { x = 0; y = 1; for (j=1; j<=h; j++) { ulong z = vz_f[1+Fl_mul(H[j], g, f)]; x = Fl_add(x, z, el); y = Fl_mul(y, z-1, el); } theta[i] = x; xi[i] = y; g = Fl_mul(g, g_K, f); } return gerepilecopy(av, mkvec2(theta, xi)); } static GEN make_Xi(GEN xi, long d) { long i, j; GEN Xi = cgetg(d+1, t_MAT); for (j=0; j>1; for (i=1; i<=d_K; i++) { GEN x = real_0(prec), y = real_1(prec); for (j=1; j<=h2; j++) { GEN z = gmael(vz_f, 1+Fl_mul(H[j], g, f), 1); x = addrr(x, z); y = mulrr(y, shiftr(subsr(1, z), 1)); } gel(theta, i) = shiftr(x, 1); gel(xi, i) = y; g = Fl_mul(g, g_K, f); } return gerepilecopy(av, mkvec2(theta, xi)); } static GEN bound_coeff_xi(GEN K, GEN tInvA) { pari_sp av = avma; long d_K = K_get_d(K), prec = MEDDEFAULTPREC, i; GEN tInvV, R = cgetg(d_K+1, t_MAT), theta_xi = theta_xi_approx(K, prec); GEN theta = gel(theta_xi, 1), xi = gel(theta_xi, 2), x1, x2, bound; for (i=1; i<=d_K; i++) { GEN z = gpowers(gel(theta, i), d_K-1); settyp(z, t_COL); gel(R, i) = z; } tInvV = RgM_mul(RgM_inv(R), tInvA); x1 = gsupnorm(tInvV, prec); x2 = gsupnorm(xi, prec); bound = mulrs(mulrr(x1, x2), 3*d_K); return gerepilecopy(av, bound); } static GEN get_Xi(GEN K, GEN tInvA) { pari_sp av = avma; GEN M0, XI, EL, Xi; ulong f = K_get_f(K), el, e, n, i; forprime_t T0; M0 = bound_coeff_xi(K, tInvA); e = expo(M0)+1; n = e/(BITS_IN_LONG-1); n++; EL = cgetg(1+n, t_VECSMALL); XI = cgetg(1+n, t_VEC); u_forprime_arith_init(&T0, LONG_MAX, ULONG_MAX, 1, f); for (i=1; i<=n; i++) { el = u_forprime_next(&T0); while ((Xi=Xi_el(K, tInvA, el))==NULL) el = u_forprime_next(&T0); gel(XI, i) = Xi; EL[i] = el; } return gerepileupto(av, nmV_chinese_center(XI, EL, NULL)); } /* K is a cyclic field of conductor f with degree d=d_K * xi = Norm_{Q(zeta_f)/K}(1-zeta_f) * 1: T, min poly of a=Tr_{Q(zeta_f)/K}(zeta_f) over Q * 2: B, power basis of K with respect to a * 3: A, rational matrix s.t. t(v_1,...v_d) = A*t(1,a,...,a^{d-1}) * 4: Xi, integer matrix s.t. t(xi^(1),...,xi^(d)) = Xi*t(v_1,...,v_d) */ static GEN xi_data_basis(GEN K) { pari_sp av = avma; GEN T = minpol_theta(K); GEN InvA, A, M, Xi, A_den; GEN D, B = nfbasis(T, &D); pari_timer ti; if (DEBUGLEVEL>1) timer_start(&ti); A = RgXV_to_RgM(B, lg(B)-1); M = gmael(A, 1, 1); if (!equali1(M)) A = RgM_Rg_div(A, M); InvA = QM_inv(A); A = Q_remove_denom(A, &A_den); if (A_den==NULL) A_den = gen_1; Xi = get_Xi(K, shallowtrans(InvA)); if (DEBUGLEVEL>1) timer_printf(&ti, "xi_data_basis"); return gerepilecopy(av, mkvec5(T, B, shallowtrans(A), Xi, A_den)); } /* When factorization of polcyclo mod el is difficult, one can try to * check the condition of el using an integral basis of K. * This is useful when d_K is small. */ static long chk_el_real_basis(GEN K, long p, long d_pow, long el, long j0) { pari_sp av = avma; GEN xi = gel(K, 7), T = gel(xi, 1), A = gel(xi, 3), Xi = gel(xi, 4); GEN A_den = gel(xi, 5); ulong i, j, x, found = 0; GEN v_el, xi_el; GEN e_chi, xi_e_chi; ulong d_K, d, dp, el1dp; if (dvdiu(A_den, el)) return 0; d = upowuu(p, d_pow); dp = d*p; el1dp = (el-1)/dp; e_chi = get_e_chi(K, j0, dp, &d_K); xi_e_chi = cgetg(d_K+1, t_VECSMALL)+1; if (DEBUGLEVEL>1) err_printf("chk_el_real_basis: d_K=%ld el=%ld\n",d_K,el); A = ZM_to_Flm(A, el); A = Flm_Fl_mul(A, Fl_inv(umodiu(A_den, el), el), el); x = Flx_oneroot_split(ZX_to_Flx(T, el), el); v_el = Flm_Flc_mul(A, Fl_powers(x, d_K-1, el), el); xi_el = Flm_Flc_mul(ZM_to_Flm(Xi, el), v_el, el); if (DEBUGLEVEL>2) err_printf("el=%ld xi_el=%Ps\n", el, xi_el); for (i=0; i2) err_printf("xi_e_chi=%Ps\n", xi_e_chi-1); for (i=0; i * G is not necessarily a direct product. * If p^e || n, then p^e || |H_i| for some i. * return a generator of G. */ static GEN find_gen(GEN perms, long n) { GEN fa = factoru(n), P = gel(fa, 1), E = gel(fa, 2); long i, j, l = lg(perms), r = lg(P); GEN gen = cgetg(r, t_VEC), orders = cgetg(l, t_VECSMALL), perm; for (i=1; i1) timer_start(&ti); T = minpol_xi(K); if (DEBUGLEVEL>1) timer_printf(&ti, "minpol_xi"); G = galoisinit(T, NULL); if (DEBUGLEVEL>1) timer_printf(&ti, "galoisinit"); perms = gal_get_gen(G); perm = (lg(perms)==2)?gel(perms, 1):find_gen(perms, d_K); if (DEBUGLEVEL>1) timer_start(&ti); pol = galoispermtopol(G, perm); if (DEBUGLEVEL>1) timer_printf(&ti, "galoispermtopol"); pol = Q_remove_denom(pol, &Den); if (Den==NULL) Den = gen_1; k = find_conj_el(K, pol, Den); if (DEBUGLEVEL>1) timer_printf(&ti,"find_conj"); pol2 = galoispermtopol(G, perm_powu(perm, k)); pol2 = Q_remove_denom(pol2, &Den); if (Den==NULL) Den = gen_1; return gerepilecopy(av, mkvec3(T, pol2, Den)); } /* If g(X)\in Q[X] s.t. g(xi)=xi^{g_K} was found, * then we fix an integer x_0 s.t. xi=x_0 (mod el) and construct x_i * s.t. xi^{g_K^i}=x_i (mod el) using g(X). */ static long chk_el_real_galois(GEN K, long p, long d_pow, long el, long j0) { pari_sp av = avma; GEN xi = gel(K, 7), T = gel(xi, 1), F = gel(xi, 2), Den = gel(xi, 3); GEN Fel, xi_el, xi_e_chi, e_chi; ulong i, j, x, found = 0; ulong d_K, d, dp, el1dp; if (dvdiu(Den, el)) return 0; d = upowuu(p, d_pow); dp = d*p; el1dp = (el-1)/dp; e_chi = get_e_chi(K, j0, dp, &d_K); xi_el = cgetg(d_K+1, t_VECSMALL)+1; xi_e_chi = cgetg(d_K+1, t_VECSMALL)+1; if (DEBUGLEVEL>1) err_printf("chk_el_real_galois: d_K=%ld el=%ld\n",d_K,el); Fel = ZX_to_Flx(F, el); Fel = Flx_Fl_mul(Fel, Fl_inv(umodiu(Den, el), el), el); x = Flx_oneroot_split(ZX_to_Flx(T, el), el); for (i=0; i2) err_printf("el=%ld xi_el=%Ps\n", el, xi_el-1); for (i=0; i2) err_printf("xi_e_chi=%Ps\n", xi_e_chi-1); for (i=0; i1) err_printf("chk_el_real_factor: f=%ld el=%ld\n",f,el); coset = get_coset(H, h, f, el); if (DEBUGLEVEL>1) { timer_start(&ti); err_printf("factoring polyclo(d) (mod %ld)\n",f, el); } pols = Flx_factcyclo(f, el, 0); if (DEBUGLEVEL>1) timer_printf(&ti,"Flx_factcyclo(%lu,%lu)",f,el); n_coset = lg(coset)-1; n_g = lg(pols)-1; vn_g = identity_perm(n_g); polnum = const_vec(d_K, NULL); for (i=1; i<=d_K; i++) gel(polnum, i) = const_vecsmall(n_coset, 0); xpows = Flxq_powers(polx_Flx(0), f-1, gel(pols, 1), el); for (gi=1,i=1; i<=d_K; i++) { for (j=1; j<=n_coset; j++) { long x, conj = Fl_mul(gi, coset[j], f); x = srh_pol(xpows, vn_g, pols, el, conj, f); gel(polnum, i)[j] = x; } gi = Fl_mul(gi, g_K, f); } G_K = const_vec(d_K, NULL); for (i=1; i<=d_K; i++) { GEN z = pol1_Flx(0); for (j=1; j<=n_coset; j++) z = Flx_mul(z, gel(pols, gel(polnum,i)[j]), el); gel(G_K, i) = z; } if (DEBUGLEVEL>2) err_printf("G_K(x)=%Ps\n",Flx_to_ZX(gel(G_K, 1))); for (k=0; k O(el*log(el)) by FFT */ if (1000 < h && el < h) { el = (h/D)*D+1; if (el < h) el += D; } if (flag&USE_F) /* el=1 (mod f) */ { for (;; el += D) if (uisprime(el) && chk_el_real_f(K, p, d_pow, el, j0)) break; } else { for (;; el += D) if (Chi[el%f]==0 && uisprime(el) && chk_el_real_chi(K, p, d_pow, el, j0, flag)) break; } return mkvecsmall2(el, pgener_Fl(el)); } static GEN next_ell_real(GEN K, GEN ellg, long d2, GEN df0l, long j0) { GEN ell = gel(ellg, 1); for (ell = addii(ell, df0l);; ell = addii(ell, df0l)) if (BPSW_psp(ell) && chk_ell_real(K, d2, ell, j0)) return mkvec2(ell, pgener_Fp(ell)); } /* #velg >= n */ static long delete_el(GEN velg, long n) { long i, l; if (DEBUGLEVEL>1) err_printf("deleting %ld ...\n", gmael(velg, n, 1)); for (l = lg(velg)-1; l >= 1; l--) if (gel(velg, l)) break; for (i = n; i < l; i++) gel(velg, i) = gel(velg, i+1); return l; } /* velg has n components */ static GEN set_ell_real(GEN K, GEN velg, long n, long d_chi, long d2, long f0, long j0) { long i, n_ell = n*d_chi; GEN z = cgetg(n_ell + 1, t_VEC); GEN df0l = muluu(d2, f0), ellg = mkvec2(gen_1, gen_1); for (i=1; i<=n; i++) df0l = muliu(df0l, gel(velg, i)[1]); for (i=1; i<=n_ell; i++) ellg = gel(z, i)= next_ell_real(K, ellg, d2, df0l, j0); return z; } static GEN G_K_vell(GEN K, GEN vellg, ulong gk) { pari_sp av = avma; GEN H = K_get_H(K); ulong f = K_get_f(K), h = K_get_h(K); GEN z_f, vz_f, A, P, M, z = cgetg(h+1, t_VEC); ulong i, lv = lg(vellg); A=cgetg(lv, t_VEC); P=cgetg(lv, t_VEC); for (i=1; i * G_K[1+i]=minimal polynomial of zeta_f^{g_k^i} over K mod M, 0 <= i < d_K */ static GEN make_G_K(GEN K, GEN vellg) { ulong d_K = K_get_d(K), f = K_get_f(K), g_K = K_get_g(K); GEN G_K = cgetg(d_K+1, t_VEC); ulong i, g = 1; for (i=0; i=el) i2%=el; } for (k=0; k=el) i2%=el; } if (DEBUGLEVEL>2) timer_start(&ti); ww = ZX_mul(u, v); if (DEBUGLEVEL>2) timer_printf(&ti, "ZX_mul:%ld/%ld h*el=%ld*%ld", k, d_K, h, el); dwel = degpol(ww)-el; for (i=0; i<=dwel; i++) gel(w, 1+i) = addii(gel(ww, 2+i), gel(ww, 2+i+el)); for (; i=el) i2%=el; } gd = Fl_powu(g_el, d, el); /* a bit faster */ gi = g_el; for (i=1; i=el) i2%=el; /* i2=(i*i)%el */ } for (k=0; k2) timer_start(&ti); G_K = (vG_K==NULL)?G_K_l(K, ellg, gk):ZX_to_Flx(gel(vG_K, 1+k), ell); if (DEBUGLEVEL>2) timer_printf(&ti, "G_K_l"); for (i=i2=0; i<=h; i++) { v[2+i] = Fl_mul(G_K[2+i], vz_el[i2], ell); if ((i2+=i+i+1)>=el) i2%=el; /* i2=(i*i)%el */ } if (DEBUGLEVEL>2) timer_start(&ti); ww = Flx_mul(u, v, ell); if (DEBUGLEVEL>2) timer_printf(&ti, "Flx_mul:%ld/%ld h*el=%ld*%ld", k, d_K, h, el); dwel=degpol(ww)-el; /* dwel=h-1 */ for (i=0; i<=dwel; i++) w[1+i] = Fl_add(ww[2+i], ww[2+i+el], ell); for (; i=el) i2%=el; /* i2=(i*i)%el */ } gd = Fl_powu(g_el, d, el); /* a bit faster */ gi = g_el; for (i=1; i=el) i2%=el; } for (k=0; k2) timer_start(&ti); G_K = (vG_K==NULL) ? G_K_p(K, ellg, gk):RgX_to_FpX(gel(vG_K, 1+k), ell); if (DEBUGLEVEL>2) timer_printf(&ti, "G_K_p"); for (i=i2=0; i<=h; i++) { gel(v, 2+i) = Fp_mul(gel(G_K, 2+i), gel(vz_el, i2), ell); if ((i2+=i+i+1)>=el) i2%=el; } if (DEBUGLEVEL>2) timer_start(&ti); ww = ZX_mul(u, v); if (DEBUGLEVEL>2) timer_printf(&ti, "ZX_mul:%ld/%ld h*el=%ld*%ld", k, d_K, h, el); dwel = degpol(ww)-el; for (i=0; i<=dwel; i++) gel(w, 1+i) = addii(gel(ww, 2+i), gel(ww, 2+i+el)); for (; i=el) i2%=el; } gd = Fl_powu(g_el, d, el); /* a bit faster */ gi = g_el; for (i=1; i1) timer_start(&ti); z = (h1) timer_printf(&ti, "subcyclopclgp:[D_xi_el]"); if (DEBUGLEVEL>2) err_printf("z=%Ps\n", z); nz = lg(z)-1; for (k = 1; k <= nz; k++) for (j=1; j<=row; j++) y[(j-1)*row+(i-1)*nz+k-1] = get_y(gel(z, k), gel(vellg, j), d); set_avma(av); } } static void real_MLL1(long *y, GEN K, ulong p, ulong d_pow, GEN velg, GEN vellg, ulong j0) { ulong h = gmael(K, 1, 2)[3], d = upowuu(p, d_pow); GEN elg = gel(velg, 1), ellg = gel(vellg, 1), z; ulong el = elg[1]; pari_timer ti; if (DEBUGLEVEL>2) timer_start(&ti); z = h < el? D_xi_el_ZX_mul(K, elg, ellg, NULL, d, j0) : D_xi_el_sl(K, elg, ellg, d, j0); if (DEBUGLEVEL>2) timer_printf(&ti, "subcyclopclgp:[D_xi_el]"); if (DEBUGLEVEL>2) err_printf("z=%Ps\n", z); y[0] = get_y(gel(z, 1), ellg, d); } static void real_MLL(long *y, GEN K, ulong p, ulong d_pow, ulong n, GEN velg, GEN vellg, GEN vG_K, ulong j0) { ulong i, j, k, d = upowuu(p, d_pow), h = gmael(K, 1, 2)[3]; ulong row = lg(vellg)-1; for (j=1; j<=row; j++) { GEN ellg = gel(vellg, j); for (i=1; i<=n; i++) { pari_sp av2 = avma; GEN elg = gel(velg, i), z; ulong el = elg[1], nz; pari_timer ti; if (DEBUGLEVEL>2) timer_start(&ti); z = h < el? D_xi_el_ZX_mul(K, elg, ellg, vG_K, d, j0) : D_xi_el_sl(K, elg, ellg, d, j0); if (DEBUGLEVEL>2) timer_printf(&ti, "subcyclopclgp:[D_xi_el]"); if (DEBUGLEVEL>3) err_printf("z=%Ps\n", z); nz = lg(z)-1; for (k = 1; k <= nz; k++) y[(j-1)*row+(i-1)*nz+k-1] = get_y(gel(z, k), ellg, d); set_avma(av2); } } } static long use_basis(long d_K, long f) { return (d_K<=10 || (d_K<=30 && f<=5000)); } static long use_factor(ulong f) { GEN fa = factoru(f), P = gel(fa, 1); return (P[lg(P)-1]<500); } /* group structure, destroy gr */ static GEN get_str(GEN gr) { GEN z = gel(gr,2); long i, j, l = lg(z); for (i = j = 1; i < l; i++) if (lgefint(gel(z, i)) > 2) gel(z,j++) = gel(z,i); setlg(z, j); return z; } static GEN cyc_real_MLL(GEN K, ulong p, long d_pow, long j0, long flag) { ulong d_K = K_get_d(K), f = K_get_f(K), d_chi = K_get_dchi(K); ulong n, n0 = 1, f0, n_el = d_pow, d = upowuu(p, d_pow), rank = n_el*d_chi; GEN velg = const_vec(n_el, NULL), vellg = NULL; GEN oldgr = mkvec2(gen_0, NULL), newgr = mkvec2(gen_0, NULL); long *y0 = (long*)stack_calloc(sizeof(long)*rank*rank); if (DEBUGLEVEL>1) err_printf("cyc_real_MLL:p=%ld d_pow=%ld deg(K)=%ld cond(K)=%ld g_K=%ld\n", p, d_pow, d_K, f, K_get_g(K)); gel(K, 2) = get_chi(gel(K,1)); if (f-1 <= (d_K<<1)) flag |= USE_F; else if (use_basis(d_K, f)) flag |= USE_BASIS; else if (use_factor(f)) flag |= USE_FACTOR; else flag |= USE_GALOIS_POL; if (flag&USE_BASIS) K = vec_append(K, xi_data_basis(K)); else if (flag&USE_GALOIS_POL) K = vec_append(K, xi_data_galois(K)); f0 = f%p?f:f/p; gel(velg, 1) = next_el_real(K, p, d_pow, mkvecsmall2(1, 1), j0, flag); if (flag&USE_FULL_EL) { for (n=2; n<=n_el; n++) gel(velg, n) = next_el_real(K, p, d_pow, gel(velg, n+1), j0, flag); n0 = n_el; } for (n=n0; n<=n_el; n++) /* loop while structure is unknown */ { pari_sp av2 = avma; long n_ell, m, M; GEN y; pari_timer ti; if (DEBUGLEVEL>2) timer_start(&ti); vellg = set_ell_real(K, velg, n, d_chi, d*d, f0, j0); n_ell = lg(vellg) -1; /* equal to n*d_chi */ if (DEBUGLEVEL>2) timer_printf(&ti, "set_ell_real"); if (DEBUGLEVEL>3) err_printf("vel=%Ps\nvell=%Ps\n", velg, vellg); if (n_ell==1) real_MLL1(y0, K, p, d_pow, velg, vellg, j0); else { GEN vG_K; if (DEBUGLEVEL>2) timer_start(&ti); vG_K = make_G_K(K, vellg); if (DEBUGLEVEL>2) timer_printf(&ti, "make_G_K"); if (lgefint(gmael(vellg, n_ell, 1))<=3 || (flag&SAVE_MEMORY)) real_MLL(y0, K, p, d_pow, n, velg, vellg, vG_K, j0); else real_MLLn(y0, K, p, d_pow, n, velg, vellg, vG_K, j0); } set_avma(av2); y = ary2mat(y0, n_ell); if (DEBUGLEVEL>3) err_printf("y=%Ps\n", y); y = ZM_snf(y); if (DEBUGLEVEL>3) err_printf("y=%Ps\n", y); y = make_p_part(y, p, d_pow); if (DEBUGLEVEL>3) err_printf("y=%Ps\n", y); newgr = structure_MLL(y, d_pow); if (DEBUGLEVEL>3) err_printf("d_pow=%ld d_chi=%ld old=%Ps new=%Ps\n",d_pow,d_chi,oldgr,newgr); if (equalsi(d_pow*d_chi, gel(newgr, 1))) break; if ((m = find_del_el(&oldgr, newgr, n, n_el, d_chi))) { M = m = delete_el(velg, m); n--; } else { M = n+1; m = n; } gel(velg, M) = next_el_real(K, p, d_pow, gel(velg, m), j0, flag); } return get_str(newgr); } static GEN cyc_buch(long dK, GEN p, long d_pow) { GEN z = Buchquad(stoi(dK), 0.0, 0.0, 0), cyc = gel(z,2); long i, l = lg(cyc); if (Z_pval(gel(z,1), p) != d_pow) pari_err_BUG("subcyclopclgp [Buchquad]"); for (i = 1; i < l; i++) { long x = Z_pval(gel(cyc, i), p); if (!x) break; gel(cyc, i) = utoipos(x); } setlg(cyc, i); return cyc; } static void verbose_output(GEN K, GEN p, long pow, long j) { long d = K_get_d(K), f = K_get_f(K), s = K_get_s(K), d_chi = K_get_dchi(K); err_printf("|A_K_psi|=%Ps^%ld, psi=chi^%ld, d_psi=%ld, %s,\n\ [K:Q]=%ld, [f,H]=[%ld, %Ps]\n", p,pow*d_chi,j,d_chi,s?"real":"imaginary",d,f,zv_to_ZV(gmael3(K,1,1,1))); } static int cyc_real_pre(GEN K, GEN xi, ulong p, ulong j, long el) { pari_sp av = avma; ulong i, d_K, x = 1; GEN e_chi = get_e_chi(K, j, p, &d_K); xi++; for (i = 0; i < d_K; i++) x = Fl_mul(x, Fl_powu(xi[i], e_chi[i], el), el); return gc_ulong(av, Fl_powu(x, (el-1)/p, el)); } /* return vec[-1,[],0], vec[0,[],0], vec[1,[1],0], vec[2,[1,1],0] etc */ static GEN cyc_real_ss(GEN K, GEN xi, ulong p, long j, long pow, long el, ulong pn, long flag) { ulong d_chi = K_get_dchi(K); if (cyc_real_pre(K, xi, pn, j, el) == 1) return NULL; /* not determined */ if (--pow==0) return mkvec3(gen_0, nullvec(), gen_0); /* trivial */ if (DEBUGLEVEL) verbose_output(K, utoi(p), pow, j); if (flag&USE_MLL) { pari_sp av = avma; GEN gr = (K_get_d(K) == 2)? cyc_buch(K_get_f(K), utoi(p), pow) : cyc_real_MLL(K, p, pow, j, flag); return gerepilecopy(av, mkvec3(utoipos(d_chi * pow), gr, gen_0)); } if (pow==1) return mkvec3(utoi(d_chi), onevec(d_chi), gen_0); return mkvec3(utoi(pow*d_chi), nullvec(), gen_0); } static GEN cyc_real_ll(GEN K, GEN xi, GEN p, long j, long pow, GEN el, GEN pn, long flag) { pari_sp av = avma; ulong i, d_K = K_get_d(K), d_chi = K_get_dchi(K); GEN e_chi = get_e_chi_ll(K, j, pn), x = gen_1; xi++; for (i = 0; i < d_K; i++) x = Fp_mul(x, Fp_pow(gel(xi, i), gel(e_chi, i), el), el); x = Fp_pow(x, diviiexact(subiu(el, 1), pn), el); /* x = x^(el-1)/pn mod el */ set_avma(av); if (equali1(x)) return NULL; /* not determined */ if (--pow==0) return mkvec3(gen_0, nullvec(), gen_0); /* trivial */ if (DEBUGLEVEL) verbose_output(K, p, pow, j); if (flag&USE_MLL) pari_err_IMPL(stack_sprintf("flag=%ld for large prime", USE_MLL)); if (pow==1) return mkvec3(utoi(d_chi), onevec(d_chi), gen_0); return mkvec3(utoi(pow*d_chi), nullvec(), gen_0); } /* xi[1+i] = xi^(g^i), 0 <= i <= d-1 */ static GEN xi_conj_s(GEN K, ulong el) { pari_sp av = avma; GEN H = K_get_H(K); long d = K_get_d(K), f = K_get_f(K), h = K_get_h(K), g = K_get_g(K); long i, gi = 1, z = Fl_powu(pgener_Fl(el), (el-1)/f, el); GEN vz = Fl_powers(z, f, el)+1, xi = cgetg(d+1, t_VECSMALL); for (i=1; i<=d; i++) { long j, x = 1; for (j=1; j<=h; j++) x = Fl_mul(x, vz[Fl_mul(H[j], gi, f)]-1, el); xi[i] = x; gi = Fl_mul(gi, g, f); } return gerepilecopy(av, xi); } static GEN xi_conj_l(GEN K, GEN el) { pari_sp av = avma; GEN H = K_get_H(K); long d = K_get_d(K), f = K_get_f(K), h = K_get_h(K), g = K_get_g(K); long i, gi = 1; GEN z = Fp_pow(pgener_Fp(el), diviuexact(subiu(el, 1), f), el); GEN vz = Fp_powers(z, f, el)+1, xi = cgetg(d+1, t_VEC); for (i=1; i<=d; i++) { long j; GEN x = gen_1; for (j=1; j<=h; j++) x = Fp_mul(x, subiu(gel(vz, Fl_mul(H[j], gi, f)), 1), el); gel(xi, i) = x; gi = Fl_mul(gi, g, f); } return gerepilecopy(av, xi); } static GEN pclgp_cyc_real(GEN K, GEN p, long max_pow, long flag) { const long NUM_EL = 20; GEN C = gel(K, 5); long f_K = K_get_f(K), n_conj = K_get_nconj(K); long i, pow, n_el, n_done = 0; GEN gr = nullvec(), Done = const_vecsmall(n_conj, 0), xi; long first = 1; for (pow=1; pow<=max_pow; pow++) { GEN pn = powiu(p, pow), fpn = muliu(pn, f_K), el = addiu(fpn, 1); for (n_el = 0; n_el < NUM_EL; el = addii(el, fpn)) { ulong uel; if (!BPSW_psp(el)) continue; n_el++; uel = itou_or_0(el); if (uel) { xi = xi_conj_s(K, uel); if (first && n_conj > 10) /* mark trivial chi-part */ { for (i = 1; i <= n_conj; i++) { if (cyc_real_pre(K, xi, p[2], C[i], uel) == 1) continue; Done[i] = 1; if (++n_done == n_conj) return gr; } first = 0; continue; } } else xi = xi_conj_l(K, el); for (i = 1; i <= n_conj; i++) { GEN z; if (Done[i]) continue; if (uel) z = cyc_real_ss(K, xi, p[2], C[i], pow, uel, itou(pn), flag); else z = cyc_real_ll(K, xi, p, C[i], pow, el, pn, flag); if (!z) continue; Done[i] = 1; if (!isintzero(gel(z, 1))) gr = vec_append(gr, z); if (++n_done == n_conj) return gr; } } } pari_err_BUG("pclgp_cyc_real: max_pow is not enough"); return NULL; /*LCOV_EXCL_LINE*/ } /* return (el, g_el) */ static GEN next_el_imag(GEN elg, long f) { long el = elg[1]; if (odd(f)) f<<=1; while (!uisprime(el+=f)); return mkvecsmall2(el, pgener_Fl(el)); } /* return (ell, g_ell) */ static GEN next_ell_imag(GEN ellg, GEN df0l) { GEN ell = gel(ellg, 1); while (!BPSW_psp(ell = addii(ell, df0l))); return mkvec2(ell, pgener_Fp(ell)); } static GEN set_ell_imag(GEN velg, long n, long d_chi, GEN df0) { long i, n_ell = n*d_chi; GEN z = cgetg(n_ell + 1, t_VEC); GEN df0l = shifti(df0, 1), ellg = mkvec2(gen_1, gen_1); for (i=1; i<=n; i++) df0l = muliu(df0l, gel(velg, i)[1]); for (i=1; i<=n_ell; i++) ellg = gel(z, i)= next_ell_imag(ellg, df0l); return z; } /* U(X)=u(x)+u(X)*X^f+...+f(X)*X^((m-1)f) or u(x)-u(X)*X^f+... * U(X)V(X)=u(X)V(X)(1+X^f+...+X^((m-1)f)) * =w_0+w_1*X+...+w_{f+el-3}*X^(f+el-3) * w_i (1 <= i <= f+el-2) are needed. * w_{f+el-2}=0 if el-1 == f. * W_i = w_i + w_{i+el-1} (1 <= i <= f-1). */ static GEN gauss_Flx_mul(ulong f, GEN elg, GEN ellg) { pari_sp av = avma; ulong el = elg[1], g_el= elg[2]; ulong el_1 = el-1, f2 = f<<1, lv = el_1, lu = f, m = el_1/f; ulong ell = itou(gel(ellg, 1)), g_ell = itou(gel(ellg, 2)); ulong z_2f = Fl_powu(g_ell, (ell - 1) / f2, ell); ulong z_el = Fl_powu(g_ell, (ell - 1) / el, ell); ulong i, i2, gi; GEN W = cgetg(f+1, t_VECSMALL), vz_2f, vz_el; GEN u = cgetg(lu+2, t_VECSMALL), v = cgetg(lv+2, t_VECSMALL), w0; u[1] = evalsigne(1); v[1] = evalsigne(1); vz_2f = Fl_powers(z_2f, f2-1, ell); vz_el = Fl_powers(z_el, el_1, ell); for (i=i2=0; i=f2) i2-=f2; /* same as i2%=f2 */ } for (gi=1,i=i2=0; i=f2) i2%=f2; /* i2-=f2 does not work */ } w0 = Flx_mul(u, v, ell) + 1; if (m==1) { /* el_1=f */ for (i=1; i=f2) i2%=f2; } /* W[r]=tau_{LL}^{sigma_r}, 1<= r <= f-1 */ return gerepilecopy(av, Flv_to_ZV(W)); } static GEN gauss_ZX_mul(ulong f, GEN elg, GEN ellg) { pari_sp av = avma, av2; ulong el, g_el, el_1, f2, lv, lu, m, i, i2, gi; GEN ell = gel(ellg, 1), g_ell, ell_1, z_2f, z_el, W, vz_2f, vz_el, u, v, w0; if (lgefint(ell) == 3) return gauss_Flx_mul(f, elg, ellg); g_ell = gel(ellg, 2); ell_1 = subiu(ell, 1); el = elg[1]; g_el = elg[2]; el_1 = el-1; f2 = f<<1; lv=el_1; lu=f; m=el_1/f; z_2f = Fp_pow(g_ell, diviuexact(ell_1, f2), ell); vz_2f = Fp_powers(z_2f, f2-1, ell); W = cgetg(f+1, t_VEC); av2 = avma; z_el = Fp_pow(g_ell, diviuexact(ell_1, el), ell); vz_el = Fp_powers(z_el, el_1, ell); u = cgetg(lu+2, t_POL); u[1] = evalsigne(1) | evalvarn(0); v = cgetg(lv+2, t_POL); v[1] = evalsigne(1) | evalvarn(0); for (gi=1,i=i2=0; i=f2) i2-=f2; } for (gi=1,i=i2=0; i=f2) i2%=f2; } w0 = gerepileupto(av2, FpX_mul(u, v, ell)) + 1; av2 = avma; if (m==1) { for (i=1; i < f; i++) gel(W,i) = Fp_add(gel(w0, i), gel(w0, i+lv), ell); gel(W, f) = gel(w0, f); } else { ulong start = 1+f, end = f+el-1; GEN w = cgetg(end+1, t_VEC); for (i=1; i= f2) i2 %= f2; } return gerepilecopy(av, W); /* W[r]=tau_{LL}^{sigma_r}, 1<= r <= f-1 */ } /* fast but consumes memory */ static GEN gauss_el_vell(ulong f, GEN elg, GEN vellg, GEN vz_2f) { pari_sp av = avma, av2; ulong el = elg[1], g_el = elg[2], el_1 = el-1; ulong lv=el_1, f2=f<<1, lu=f, m=el_1/f; GEN W = cgetg(f+1, t_VEC), vz_el, u, v, w0, M; ulong i, i2, gi; av2 = avma; vz_el = vz_vell(el, vellg, &M); u = cgetg(lu+2, t_POL); u[1] = evalsigne(1) | evalvarn(0); v = cgetg(lv+2, t_POL); v[1] = evalsigne(1) | evalvarn(0); for (i=i2=0; i=f2) i2%=f2; } for (gi=1,i=i2=0; i=f2) i2%=f2; } M = gclone(M); w0 = gerepileupto(av2, FpX_mul(u, v, M)) + 1; u = M; M = icopy(M); gunclone(u); av2 = avma; if (m==1) { /* el_1=f */ for (i=1; i < f; i++) gel(W,i) = Fp_add(gel(w0, i), gel(w0, i+lv), M); gel(W, f) = gel(w0, f); } else { ulong start = 1+f, end = f+el-1; GEN w = cgetg(end+1, t_VEC); for (i=1; i= f2) i2 %= f2; } return gerepilecopy(av, W); /* W[r]=tau_{LL}^{sigma_r}, 1<= r <= f-1 */ } static GEN norm_chi(GEN K, GEN TAU, ulong p, long d_pow, GEN ell, long j0) { pari_sp av = avma; GEN H = K_get_H(K); ulong d_K, f_K = K_get_f(K), h = K_get_h(K), g_K = K_get_g(K); ulong i, j, gi, pd = upowuu(p, d_pow), d_chi = K_get_dchi(K); GEN z = const_vec(d_chi, gen_1); GEN e_chi = get_e_chi(K, j0, pd, &d_K); for (gi=1, i=0; i1) err_printf("(f,el-1)=(%ld,%ld*%ld)\n", f,(elg[1]-1)/f,f); g = gauss_el_vell(f, elg, vellg, vz_2f); z = norm_chi(K, g, p, d_pow, M, j0); nz = lg(z)-1; for (k = 1; k <= nz; k++) for (j = 1; j <= row; j++) y[(j-1)*row+(i-1)*nz+k-1] = get_y(gel(z, k), gel(vellg, j), d); set_avma(av); } } static void imag_MLL1(long *y, GEN K, ulong p, long d_pow, GEN velg, GEN vellg, long j0) { long f = K_get_f(K), d = upowuu(p, d_pow); GEN elg = gel(velg, 1), ellg = gel(vellg, 1), ell = gel(ellg, 1), g, z; if (DEBUGLEVEL>1) err_printf("(f,el-1)=(%ld,%ld*%ld)\n", f, (elg[1]-1)/f, f); g = gauss_ZX_mul(f, elg, ellg); z = norm_chi(K, g, p, d_pow, ell, j0); y[0] = get_y(gel(z, 1), ellg, d); } static void imag_MLL(long *y, GEN K, ulong p, long d_pow, long n, GEN velg, GEN vellg, long j0) { pari_sp av = avma; long i, j, f = K_get_f(K), d = upowuu(p, d_pow), row = lg(vellg)-1; for (j=1; j<=row; j++) { GEN ellg = gel(vellg, j), ell = gel(ellg, 1); for (i=1; i<=n; i++) { GEN elg = gel(velg, i), g, z; ulong k, nz; if (DEBUGLEVEL>1) err_printf("(f,el-1)=(%ld,%ld*%ld)\n",f,(elg[1]-1)/f,f); g = gauss_ZX_mul(f, elg, ellg); z = norm_chi(K, g, p, d_pow, ell, j0); nz = lg(z)-1; for (k = 1; k <= nz; k++) y[(j-1)*row+(i-1)*nz+k-1] = get_y(gel(z, k), ellg, d); set_avma(av); } } } /* return an upper bound >= 0 if one was found, otherwise return -1. * set chi-part to be (1) if chi is Teichmuller character. * B_{1,omega^(-1)} is not p-adic integer. */ static GEN cyc_imag_MLL(GEN K, ulong p, long d_pow, long j, long flag) { long f = K_get_f(K), d_chi = K_get_dchi(K); long n, n0 = 1, n_el = d_pow, d = upowuu(p, d_pow), rank = n_el*d_chi; GEN df0, velg = const_vec(n_el, NULL), vellg = NULL; GEN oldgr = mkvec2(gen_0, NULL), newgr = mkvec2(gen_0, NULL); long *y0 = (long*)stack_calloc(sizeof(long)*rank*rank); if (DEBUGLEVEL>1) err_printf("cyc_imag_MLL:p=%ld d_pow=%ld deg(K)=%ld cond(K)=%ld avma=%ld\n", p, d_pow, K_get_d(K), f, avma); df0 = muluu(d, f%p?f:f/p); gel(velg, 1) = next_el_imag(mkvecsmall2(1, 1), f); if (flag&USE_FULL_EL) { for (n=2; n<=n_el; n++) gel(velg, n) = next_el_imag(gel(velg, n-1), f); n0 = n_el; } for (n=n0; n<=n_el; n++) /* loop while structure is unknown */ { pari_sp av2 = avma; pari_timer ti; long n_ell, m, M; GEN y; vellg = set_ell_imag(velg, n, d_chi, df0); n_ell = lg(vellg)-1; /* equal to n*d_chi */ if (DEBUGLEVEL>2) err_printf("velg=%Ps\nvellg=%Ps\n", velg, vellg); if (DEBUGLEVEL>2) timer_start(&ti); if (n_ell==1) imag_MLL1(y0, K, p, d_pow, velg, vellg, j); else if (lgefint(gmael(vellg, n, 1))<=3 || (flag&SAVE_MEMORY)) imag_MLL(y0, K, p, d_pow, n, velg, vellg, j); else imag_MLLn(y0, K, p, d_pow, n, velg, vellg, j); set_avma(av2); if (DEBUGLEVEL>2) timer_printf(&ti, "gauss sum"); y = ary2mat(y0, n_ell); if (DEBUGLEVEL>3) err_printf("y=%Ps\n", y); y = ZM_snf(y); if (DEBUGLEVEL>3) err_printf("y=%Ps\n", y); y = make_p_part(y, p, d_pow); if (DEBUGLEVEL>3) err_printf("y=%Ps\n", y); newgr = structure_MLL(y, d_pow); if (DEBUGLEVEL>3) err_printf("d_pow=%ld d_chi=%ld old=%Ps new=%Ps\n",d_pow,d_chi,oldgr,newgr); if (equalsi(d_pow*d_chi, gel(newgr, 1))) break; if ((m = find_del_el(&oldgr, newgr, n, n_el, d_chi))) { M = m = delete_el(velg, m); n--; } else { M = n+1; m = n; } gel(velg, M) = next_el_imag(gel(velg, m), f); } return get_str(newgr); } /* When |A_psi|=p^e, A_psi=(p^e1,...,p^er) (psi=chi^j), * return vec[e, [e1, ... ,er], 1]. * If gr str is not determined, return vec[e, [], 1]. * If |A_chi|=1, return vec[0, [], 1]. * If |A_chi|=p, return vec[1, [1], 1]. * If e is not determined, return vec[-1, [], 1]. * If psi is Teichmuller, return vec[0, [], 1]. * B_{1,omega^(-1)} is not p-adic integer. */ static GEN cyc_imag(GEN K, GEN B, GEN p, long j, GEN powp, long flag) { pari_sp av = avma; GEN MinPol = gel(K, 3), Chi = gel(K, 2), B1, B2, gr; long x, d_K = K_get_d(K), f_K = K_get_f(K), d_chi = K_get_dchi(K); if (f_K == d_K+1 && equaliu(p, f_K) && j == 1) /* Teichmuller */ return mkvec3(gen_0, nullvec(), gen_1); B1 = FpX_rem(ZX_ber_conj(B, j, d_K), MinPol, powp); B2 = FpX_rem(ZX_ber_den(Chi, j, d_K), MinPol, powp); if (degpol(B1)<0 || degpol(B2)<0) { set_avma(av); return mkvec3(gen_m1, nullvec(), gen_1); /* B=0(mod p^pow) */ } x = ZX_pval(B1, p) - ZX_pval(B2, p); set_avma(av); if (x<0) pari_err_BUG("subcyclopclgp [Bernoulli number]"); if (DEBUGLEVEL && x) verbose_output(K, p, x, j); if (x==0) return mkvec3(gen_0, nullvec(), gen_1); /* trivial */ if (x==1) return mkvec3(utoi(d_chi), onevec(d_chi), gen_1); if ((flag&USE_MLL)==0) return mkvec3(utoi(x*d_chi), nullvec(), gen_1); gr = d_K == 2? cyc_buch(-f_K, p, x): cyc_imag_MLL(K, itou(p), x, j, flag); return gerepilecopy(av, mkvec3(utoipos(d_chi * x), gr, gen_1)); } /* handle representatives of all injective characters, d_chi=[Q_p(zeta_d):Q_p], * d=d_K */ static GEN pclgp_cyc_imag(GEN K, GEN p, long start_pow, long max_pow, long flag) { GEN C = gel(K, 5), Chi = gel(K, 2); long n_conj = K_get_nconj(K), d_K = K_get_d(K), f_K = K_get_f(K); long i, pow, n_done = 0; GEN gr = nullvec(), Done = const_vecsmall(n_conj, 0); GEN B = zx_ber_num(Chi, f_K, d_K), B_num; if (lgefint(p)==3 && n_conj>10) /* mark trivial chi-part by pre-calculation */ { ulong up = itou(p); GEN minpol = ZX_to_Flx(gel(K, 3), up); for (i=1; i<=n_conj; i++) { pari_sp av = avma; long degB; B_num = Flx_rem(Flx_ber_conj(B, C[i], d_K, up), minpol, up); degB = degpol(B_num); set_avma(av); if (degB<0) continue; Done[i] = 1; if (++n_done == n_conj) return gr; } } for (pow = start_pow; pow<=max_pow; pow++) { GEN powp = powiu(p, pow); for (i = 1; i <= n_conj; i++) { GEN z; if (Done[i]) continue; z = cyc_imag(K, B, p, C[i], powp, flag); if (equalim1(gel(z, 1))) continue; Done[i] = 1; if (!isintzero(gel(z, 1))) gr = vec_append(gr, z); if (++n_done == n_conj) return gr; } } pari_err_BUG("pclgp_cyc_imag: max_pow is not enough"); return NULL; /*LCOV_EXCL_LINE*/ } static GEN gather_part(GEN g, long sgn) { long i, j, l = lg(g), ord = 0, flag = 1; GEN z2 = cgetg(l, t_VEC); for (i = j = 1; i < l; i++) { GEN t = gel(g,i); if (equaliu(gel(t, 3), sgn)) { ord += itou(gel(t, 1)); if (lg(gel(t, 2)) == 1) flag = 0; gel(z2, j++) = gel(t, 2); } } if (flag==0 || ord==0) z2 = nullvec(); else { setlg(z2, j); z2 = shallowconcat1(z2); ZV_sort_inplace(z2); vecreverse_inplace(z2); } return mkvec2(utoi(ord), z2); } #ifdef DEBUG static void handling(GEN K) { long d_K = K_get_d(K), f_K = K_get_f(K), s_K = K_get_s(K), g_K = K_get_g(K); long d_chi = K_get_dchi(K); err_printf(" handling %s cyclic subfield K,\ deg(K)=%ld, cond(K)=%ld g_K=%ld d_chi=%ld H=%Ps\n", s_K? "a real": "an imaginary",d_K,f_K,g_K,d_chi,zv_to_ZV(gmael3(K,1,1,1))); } #endif /* HH a t_VECSMALL listing group generators * Aoki and Fukuda, LNCS vol.4076 (2006), 56-74. */ static GEN pclgp(GEN p0, long f, GEN HH, long degF, long flag) { long start_pow, max_pow, ip, lp, i, n_f; GEN vH1, z, vData, cycGH, vp = typ(p0) == t_INT? mkvec(p0): p0; vH1 = GHinit(f, HH, &cycGH); n_f = lg(vH1)-1; #ifdef DEBUG err_printf("F is %s, deg(F)=%ld, ", srh_1(HH)? "real": "imaginary", degF); err_printf("cond(F)=%ld, G(F/Q)=%Ps\n",f, cycGH); err_printf("F has %ld cyclic subfield%s except for Q.\n", n_f,n_f>1?"s":""); #endif lp = lg(vp); z = cgetg(lp, t_MAT); for (ip = 1; ip < lp; ip++) { pari_sp av = avma; long n_sub=0, n_chi=0; GEN gr=nullvec(), p = gel(vp, ip), zi; /* find conductor e of cyclic subfield K and set the subgroup HE of (Z/eZ)^* * corresponding to K */ set_p_f(p, f, &start_pow, &max_pow); vData = const_vec(degF, NULL); for (i=1; i<=n_f; i++) /* prescan. set Teichmuller */ { GEN H1 = gel(vH1, i); long d_K = _get_d(H1), f_K = _get_f(H1), g_K = _get_g(H1); if (f_K == d_K+1 && equaliu(p, f_K)) /* found K=Q(zeta_p) */ { pari_timer ti; GEN pnmax = powiu(p, max_pow), vNewton, C, MinPol; long d_chi = 1, n_conj = eulerphiu(d_K); ulong pmodd = umodiu(p, d_K); C = set_C(pmodd, d_K, d_chi, n_conj); MinPol = set_minpol_teich(g_K, p, max_pow); if (DEBUGLEVEL>3) timer_start(&ti); vNewton = FpX_Newton(MinPol, d_K+1, pnmax); if (DEBUGLEVEL>3) timer_printf(&ti, "FpX_Newton: teich: %ld %ld", degpol(MinPol), d_K); gel(vData, d_K) = mkvec4(MinPol, vNewton, C, mkvecsmall2(d_chi, n_conj)); break; } } for (i=1; i<=n_f; i++) /* handle all cyclic K */ { GEN H1 = gel(vH1, i), K, z1, Chi; long d_K = _get_d(H1), s_K = _get_s(H1); pari_sp av2; if ((flag&SKIP_PROPER) && degF != d_K) continue; if (!gel(vData, d_K)) { pari_timer ti; GEN pnmax = powiu(p, max_pow), vNewton, C, MinPol; ulong pmodd = umodiu(p, d_K); long d_chi = order_f_x(d_K, pmodd), n_conj = eulerphiu(d_K)/d_chi; C = set_C(pmodd, d_K, d_chi, n_conj); MinPol = set_minpol(d_K, p, max_pow, n_conj); if (DEBUGLEVEL>3) timer_start(&ti); /* vNewton[2+i] = vNewton[2+i+d_K]. We need vNewton[2+i] for * 0 <= i < d_K. But vNewton[2+d_K-1] may be 0 and will be deleted. * So we need vNewton[2+d_K] not to delete vNewton[2+d_K-1]. */ vNewton = FpX_Newton(MinPol, d_K+1, pnmax); if (DEBUGLEVEL>3) timer_printf(&ti, "FpX_Newton: %ld %ld", degpol(MinPol), d_K); gel(vData, d_K) = mkvec4(MinPol, vNewton, C, mkvecsmall2(d_chi, n_conj)); } av2 = avma; Chi = s_K? NULL: get_chi(H1); K = shallowconcat(mkvec2(H1, Chi), gel(vData, d_K)); #ifdef DEBUG handling(K); #endif if (s_K && !(flag&NO_PLUS_PART)) z1 = pclgp_cyc_real(K, p, max_pow, flag); else if (!s_K && !(flag&NO_MINUS_PART)) z1 = pclgp_cyc_imag(K, p, start_pow, max_pow, flag); else { set_avma(av2); continue; } n_sub++; n_chi += gmael(vData, d_K, 4)[2]; /* += n_conj */ if (lg(z1) == 1) set_avma(av2); else gr = gerepilecopy(av2, shallowconcat(gr, z1)); } zi = mkcol(p); zi = vec_append(zi, (flag&NO_PLUS_PART)?nullvec():gather_part(gr, 0)); zi = vec_append(zi, (flag&NO_MINUS_PART)?nullvec():gather_part(gr, 1)); zi = shallowconcat(zi, mkcol3(cycGH, utoi(n_sub), utoi(n_chi))); gel(z, ip) = gerepilecopy(av, zi); } return typ(p0) == t_INT? shallowtrans(gel(z,1)): shallowtrans(z); } static GEN reduce_gcd(GEN x1, GEN x2) { GEN d = gcdii(x1, x2); x1 = diviiexact(x1, d); x2 = diviiexact(x2, d); return mkvec2(x1, x2); } /* norm of x0 (= pol of zeta_d with deg <= d-1) by g of order n * x0^{1+g+g^2+...+g^(n-1)} */ static GEN ber_norm_cyc(GEN x0, long g, long n, long d) { pari_sp av = avma; long i, ei, di, fi = 0, l = ulogint(n, 2); GEN xi = x0; ei = 1L << l; di = n / ei; for (i = 1; i <= l; i++) { if (odd(di)) fi += ei; ei = 1L << (l-i); di = n / ei; xi = ZX_mod_Xnm1(ZX_mul(xi, ber_conj(xi, Fl_powu(g, ei, d), d)), d); if (odd(di)) xi = ZX_mod_Xnm1(ZX_mul(xi, ber_conj(x0, Fl_powu(g, fi, d), d)), d); } return gerepilecopy(av, xi); } /* x0 a ZX of deg < d */ static GEN ber_norm_by_cyc(GEN x0, long d, GEN MinPol) { pari_sp av=avma; GEN x = x0, z = znstar(utoi(d)), cyc = gel(z, 2), gen = gel(z, 3); long i, l = lg(cyc); pari_timer ti; if (DEBUGLEVEL>1) timer_start(&ti); for (i = 1; i < l; i++) x = ber_norm_cyc(x, itou(gmael(gen, i, 2)), itou(gel(cyc, i)), d); if (DEBUGLEVEL>1) timer_printf(&ti, "ber_norm_by_cyc [ber_norm_cyc]"); x = ZX_rem(x, MinPol); /* slow */ if (DEBUGLEVEL>1) timer_printf(&ti, "ber_norm_by_cyc [ZX_rem]"); if (lg(x) != 3) pari_err_BUG("subcyclohminus [norm of Bernoulli number]"); return gerepilecopy(av, gel(x, 2)); } /* MinPol = polcyclo(d_K, 0). * MinPol = fac*cofac (mod p). * B is zv. * K : H1, MinPol, [fac, cofac], C, [d_chi, n_conj] */ static long ber_norm_by_val(GEN K, GEN B, GEN p) { pari_sp av = avma; GEN MinPol = gel(K, 2), C = gel(K, 4); GEN vfac = gel(K, 3), fac = gel(vfac, 1), cofac = gel(vfac, 2); long d_chi = K_get_dchi(K), n_conj = K_get_nconj(K), d_K = K_get_d(K); long i, r, n_done = 0, x = 0, dcofac = degpol(cofac); GEN pr, Done; Done = const_vecsmall(n_conj, 0); if (lgefint(p)==3) { /* mark trivial chi-part by pre-calculation */ ulong up = itou(p); GEN facs = ZX_to_Flx(fac, up); for (i = 1; i <= n_conj; i++) { pari_sp av2 = avma; GEN B_conj = Flx_rem(Flx_ber_conj(B, C[i], d_K, up), facs, up); long degB = degpol(B_conj); set_avma(av2); if (degB < 0) continue; Done[i] = 1; if (++n_done == n_conj) return gc_long(av, x); } } else { for (i = 1; i <= n_conj; i++) { pari_sp av2 = avma; GEN B_conj = FpX_rem(FpX_ber_conj(B, C[i], d_K, p), fac, p); long degB = degpol(B_conj); set_avma(av2); if (degB < 0) continue; Done[i] = 1; if (++n_done == n_conj) return gc_long(av, x); } } for (pr = p, r = 2; r; r <<= 1) { GEN polr; pr = sqri(pr); /* p^r */ polr = (dcofac==0)? FpX_red(MinPol, pr) : gel(ZpX_liftfact(MinPol, vfac, pr, p, r), 1); for (i = 1; i <= n_conj; i++) { pari_sp av2 = avma; GEN B_conj; long degB; if (Done[i]) continue; B_conj = FpX_rem(FpX_ber_conj(B, C[i], d_K, pr), polr, pr); degB = degpol(B_conj); set_avma(av2); if (degB < 0) continue; x += d_chi * ZX_pval(B_conj, p); Done[i] = 1; if (++n_done == n_conj) return gc_long(av, x); } } pari_err_BUG("ber_norm_by_val"); return 0;/*LCOV_EXCL_LINE*/ } /* n > 2, p = odd prime not dividing n, e > 0, pe = p^e; d = n*p^e * return generators of the subgroup H of (Z/dZ)^* corresponding to * Q(zeta_{p^e}): H = {1<=a<=d | gcd(a,n)=1, a=1(mod p^e)} */ static GEN znstar_subgr(ulong n, ulong pe, ulong d) { GEN z = znstar(utoi(n)), g = gel(z, 3), G; long i, l = lg(g); G = cgetg(l, t_VECSMALL); for (i=1; i=4 is even). * x a ZX of deg < n*p^e. */ static long ber_norm_with_val(GEN x, long n, ulong p, ulong e) { pari_sp av = avma; long i, j, r, degx, pe = upowuu(p, e), d = n*pe; GEN z, gr, gen, y = cgetg(pe+2, t_POL), MinPol = polcyclo(n, 0); y[1] = evalsigne(1) | evalvarn(0); z = znstar_subgr(n, pe, d); gr = gel(z, 1); gen = gel(z, 2); r = lg(gr)-1; for (i=1; i<=r; i++) x = ber_norm_cyc(x, itou(gel(gen, i)), itou(gel(gr, i)), d); degx = degpol(x); for (j=0; jdegx) break; gel(t, 2+a%n) = gel(x, 2+a); a += pe; } z = ZX_rem(ZX_renormalize(t, 2+n), MinPol); if (degpol(z)<0) gel(y, 2+j) = gen_0; else if (degpol(z)==0) gel(y, 2+j) = gel(z, 2); else pari_err_BUG("ber_norm_subgr"); } y = ZX_renormalize(y, pe+2); if (e>1) y = ZX_rem(y, polcyclo(pe, 0)); return gc_long(av, ZX_p_val(y, p, e)); } /* K is a cyclic extension of degree 2*p^e. x a ZX of deg < 2*p^e. In most * cases, deg(x)=2*p^e-1. But deg(x) can be any value in [0, 2*p^e-1]. */ static long ber_norm_with_val2(GEN x, ulong p, ulong e) { pari_sp av = avma; long i, d = degpol(x), pe = upowuu(p, e); GEN y = pol_zero(pe); if (d == 2*pe-1) { for (i = 0; i < pe; i++) gel(y, 2+i) = odd(i)? subii(gel(x, 2+i+pe), gel(x, 2+i)) : subii(gel(x, 2+i), gel(x, 2+i+pe)); } else { for (i = 0; i < pe && i <= d; i++) gel(y, 2+i) = odd(i)? negi(gel(x, 2+i)): gel(x, 2+i); for (i = pe; i <= d; i++) gel(y, 2+i-pe) = odd(i)? subii(gel(y, 2+i-pe), gel(x, 2+i)) : addii(gel(y, 2+i-pe), gel(x, 2+i)); } y = ZX_renormalize(y, 2+pe); if (e > 1) y = ZX_rem(y, polcyclo(pe, 0)); return gc_long(av, ZX_p_val(y, p, e)); } /* K : H1, MinPol, [fac, cofac], C, [d_chi, n_conj] */ static GEN ber_cyc5(GEN K, GEN p) { pari_sp av = avma; GEN MinPol = gel(K, 2), H = K_get_H(K); long d = K_get_d(K), f = K_get_f(K), h = K_get_h(K), g = K_get_g(K); GEN x, x1, x2, y, B = const_vecsmall(d+1, 0); long i, j, gi, e, f2 = f>>1, dMinPol = degpol(MinPol), chi2 = -1, *B2 = B+2; /* get_chi inlined here to save memory */ for (j=1; j<=h; j++) /* i = 0 */ { if (H[j] == 2) chi2 = 0; if (H[j] <= f2) B2[0]++; /* Chi[H[j]] = 0 */ } for (i = 1, gi = g; i < d; i++) { for (j=1; j<=h; j++) { long t = Fl_mul(gi, H[j], f); /* Chi[t] = i */ if (t == 2) chi2 = i; if (t <= f2) B2[i]++; } gi = Fl_mul(gi, g, f); } y = zx_to_ZX(zx_renormalize(B, d+2)); if (p) { ulong n; e = u_pvalrem(d, p, &n); if (e == 0) x1 = utoi(ber_norm_by_val(K, B, p)); else if (n > 2) x1 = utoi(ber_norm_with_val(y, n, itou(p), e)); else x1 = utoi(ber_norm_with_val2(y, itou(p), e)); } else { if (dMinPol > 100) x1 = ber_norm_by_cyc(y, d, MinPol); else x1 = ZX_resultant(MinPol, ZX_rem(y, MinPol)); } if (chi2 < 0) /* chi2 = Chi[2] */ x2 = shifti(gen_1, 2*dMinPol); else if (chi2 == 0) x2 = shifti(gen_1, dMinPol); else { long e = d/ugcd(chi2, d); x2 = powiu(polcyclo_eval(e, gen_2), eulerphiu(d)/eulerphiu(e)); x2 = shifti(x2, dMinPol); } if (p) x = stoi(itou(x1)-Z_pval(x2, p)); else x = reduce_gcd(x1, x2); return gerepilecopy(av, x); } /* Hirabayashi-Yoshino, Manuscripta Math. vol.60, 423-436 (1988), Theorem 1 * * F is a subfield of Q(zeta_f) * f=p^a => Q=1 * If F=Q(zeta_f), Q=1 <=> f=p^a * If f=4*p^a, p^a*q^b (p,q are odd primes), Q=2 <=> [Q(zeta_f):F] is odd */ static long unit_index(ulong d, ulong f) { ulong r, d_f; GEN fa = factoru(f), P = gel(fa, 1), E = gel(fa, 2); r = lg(P)-1; if (r==1) return 1; /* f=P^a */ d_f = eulerphiu_fact(fa); if (d==d_f) return 2; /* F=Q(zeta_f) */ if (r==2 && ((P[1]==2 && E[1]==2) || P[1]>2)) return odd(d_f/d)?2:1; return 0; } /* Compute relative class number h of the subfield K of Q(zeta_f) * corresponding to the subgroup HH of (Z/fZ)^*. * If p!=NULL, then return valuation(h,p). */ static GEN rel_class_num(long f, GEN HH, long degF, GEN p) { long i, n_f, W, Q; GEN vH1, vData, x, z = gen_1, z1 = gen_0, z2 = mkvec2(gen_1, gen_1); vH1 = GHinit(f, HH, NULL); n_f = lg(vH1)-1; vData = const_vec(degF, NULL); for (i=1; i<=n_f; i++) { GEN H1 = gel(vH1, i), K; long d_K = _get_d(H1), s = _get_s(H1); if (s) continue; /* F is real */ #ifdef DEBUG err_printf(" handling %s cyclic subfield K, deg(K)=%ld, cond(K)=%ld\n", s? "a real": "an imaginary", d_K, _get_f(H1)); #endif if (!gel(vData, d_K)) { GEN C, MinPol, fac, cofac; ulong d_chi, n_conj; MinPol = polcyclo(d_K,0); if (p && umodui(d_K, p)) { ulong pmodd = umodiu(p, d_K); GEN MinPol_p = FpX_red(MinPol, p); d_chi = order_f_x(d_K, pmodd); n_conj = eulerphiu(d_K)/d_chi; if (n_conj==1) fac = MinPol_p; /* polcyclo(d_K) is irred mod p */ else fac = FpX_one_cyclo(d_K, p); cofac = FpX_div(MinPol_p, fac, p); C = set_C(pmodd, d_K, d_chi, n_conj); } else { fac = cofac = C = NULL; d_chi = n_conj = 0; } gel(vData, d_K) = mkvec5(MinPol, mkvec2(fac, cofac), C, NULL, mkvecsmall2(d_chi, n_conj)); } K = vec_prepend(gel(vData, d_K), H1); z = ber_cyc5(K, p); if (p) z1 = addii(z1, z); else { gel(z2, 1) = mulii(gel(z2, 1), gel(z, 1)); gel(z2, 2) = mulii(gel(z2, 2), gel(z, 2)); } } W = root_of_1(f, HH); if (p) return addiu(z1, z_pval(W, p)); Q = unit_index(degF, f); x = dvmdii(muliu(gel(z2,1), 2 * W), gel(z2,2), &z1); if (signe(z1)) pari_err_BUG("subcyclohminus [norm of Bernoulli number]"); if (!Q && mpodd(x)) Q = 2; /* FIXME: can this happen ? */ if (Q == 1) x = shifti(x, -1); return mkvec2(x, utoi(Q)); } static void checkp(const char *fun, long degF, GEN p) { if (!BPSW_psp(p)) pari_err_PRIME(fun, p); if (equaliu(p, 2)) pari_err_DOMAIN(fun,"p","=", gen_2, p); if (degF && dvdsi(degF, p)) errpdiv(fun, p, degF); } /* if flag is set, handle quadratic fields specially (don't set H) */ static long subcyclo_init(const char *fun, GEN FH, long *pdegF, GEN *pH, long flag) { long f = 0, degF = 2; GEN F = NULL, H = NULL; if (typ(FH) == t_POL) { degF = degpol(FH); if (degF < 1 || !RgX_is_ZX(FH)) pari_err_TYPE(fun, FH); if (flag && degF == 2) { F = coredisc(ZX_disc(FH)); if (is_bigint(F)) pari_err_IMPL(stack_sprintf("conductor f > %lu in %s", ULONG_MAX, fun)); f = itos(F); if (f == 1) degF = 1; } else { GEN z, bnf = Buchall(pol_x(fetch_var()), 0, DEFAULTPREC); z = rnfconductor(bnf, FH); H = gel(z,3); f = subcyclo_nH(fun, gel(z,2), &H); delete_var(); H = znstar_generate(f, H); /* group elements */ } } else { long l = lg(FH), fH; if (typ(FH) == t_INT) F = FH; else if (typ(FH) == t_VEC && (l == 2 || l == 3)) { F = gel(FH, 1); if (l == 3) H = gel(FH, 2); } else pari_err_TYPE(fun, FH); f = subcyclo_nH(fun, F, &H); H = znstar_generate(f, H); /* group elements */ fH = znstar_conductor(H); if (fH == 1) degF = 1; else { if (fH != f) { H = znstar_reduce_modulus(H, fH); f = fH; } degF = eulerphiu(f) / zv_prod(gel(H, 2)); } } *pH = H; *pdegF = degF; return f; } GEN subcyclopclgp(GEN FH, GEN p, long flag) { pari_sp av = avma; GEN H; long degF, f = subcyclo_init("subcyclopclgp", FH, °F, &H, 0); if (typ(p) == t_VEC) { long i, l = lg(p); for (i = 1; i < l; i++) checkp("subcyclopclgp", degF, gel(p, i)); if (f == 1) { set_avma(av); return const_vec(l-1, nullvec()); } } else { checkp("subcyclopclgp", degF, p); if (f == 1) { set_avma(av); return nullvec(); } } if (flag >= USE_BASIS) pari_err_FLAG("subcyclopclgp"); return gerepilecopy(av, pclgp(p, f, H, degF, flag)); } static GEN subcycloiwasawa_i(GEN FH, GEN P, long n) { long B, p, f, degF; GEN H; const char *fun = "subcycloiwasawa"; if (typ(P) != t_INT) pari_err_TYPE(fun, P); if (n < 0) pari_err_DOMAIN(fun, "n", "<", gen_0, stoi(n)); B = 1L << (BITS_IN_LONG/4); if (is_bigint(P) || cmpiu(P, B) > 0) pari_err_IMPL(stack_sprintf("prime p > %ld in %s", B, fun)); p = itos(P); if (p <= 1 || !uisprime(p)) pari_err_PRIME(fun, P); if (!upowuu(p, n+1)) pari_err_IMPL(stack_sprintf("p^n > 2^%ld in %s", BITS_IN_LONG, fun)); f = subcyclo_init(fun, FH, °F, &H, 1); if (degF == 1) return NULL; if (degF == 2) { long m = ((f & 3) == 0)? f / 4: f; if (H && !srh_1(H)) m = -m; if (!n) return quadlambda(p, m); return m < 0? imagquadstkpol(p, m, n): realquadstkpol(p, m, n); } if (p == 2) pari_err_DOMAIN(fun, "p", "=", gen_2, gen_2); if (srh_1(H)) return NULL; if (degF % p == 0) errpdiv("abeliwasawa", P, degF); return abeliwasawa(p, f, H, degF, n); } GEN subcycloiwasawa(GEN FH, GEN P, long n) { pari_sp av = avma; GEN z = subcycloiwasawa_i(FH, P, n); if (!z) { set_avma(av); return n? nullvec(): mkvec(gen_0); } return gerepilecopy(av, z); } GEN subcyclohminus(GEN FH, GEN P) { const char *fun = "subcyclohminus"; pari_sp av = avma; GEN H; long degF, f = subcyclo_init(fun, FH, °F, &H, 0); if (P) { if (typ(P) != t_INT) pari_err_TYPE(fun, P); if (isintzero(P)) P = NULL; else checkp(fun, 0, P); } if (degF == 1 || srh_1(H) == 1) return gen_1; return gerepilecopy(av, rel_class_num(f, H, degF, P)); } pari-2.17.2/src/basemath/FlxX.c0000644000175000017500000021115714677207232014605 0ustar billbill/* Copyright (C) 2019 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" /***********************************************************************/ /** **/ /** FlxX **/ /** **/ /***********************************************************************/ /* FlxX are t_POL with Flx coefficients. * Normally the variable ordering should be respected.*/ /*Similar to normalizepol, in place*/ /*FlxX_renormalize=zxX_renormalize */ GEN FlxX_renormalize(GEN /*in place*/ x, long lx) { long i; for (i = lx-1; i>1; i--) if (lgpol(gel(x,i))) break; stackdummy((pari_sp)(x + lg(x)), (pari_sp)(x + i+1)); setlg(x, i+1); setsigne(x, i!=1); return x; } GEN pol1_FlxX(long v, long sv) { GEN z = cgetg(3, t_POL); z[1] = evalsigne(1) | evalvarn(v); gel(z,2) = pol1_Flx(sv); return z; } GEN polx_FlxX(long v, long sv) { GEN z = cgetg(4, t_POL); z[1] = evalsigne(1) | evalvarn(v); gel(z,2) = pol0_Flx(sv); gel(z,3) = pol1_Flx(sv); return z; } long FlxY_degreex(GEN b) { long deg = 0, i; if (!signe(b)) return -1; for (i = 2; i < lg(b); ++i) deg = maxss(deg, degpol(gel(b, i))); return deg; } /*Lift coefficient of B to constant Flx, to give a FlxY*/ GEN Fly_to_FlxY(GEN B, long sv) { long lb=lg(B); long i; GEN b=cgetg(lb,t_POL); b[1]=evalsigne(1)|(((ulong)B[1])&VARNBITS); for (i=2; i N+1) l = N+1; /* truncate higher degree terms */ z = cgetg(N+1,t_COL); for (i=1; i P(Y,X), n is the degree in Y */ GEN FlxX_swap(GEN x, long n, long ws) { long j, lx = lg(x), ly = n+3; GEN y = cgetg(ly, t_POL); y[1] = x[1]; for (j=2; j= n) pari_err_BUG("zxX_to_Kronecker, P is not reduced mod Q"); for (j=2; j < l; j++) y[k++] = c[j]; if (i == lp-1) break; for ( ; j < N; j++) y[k++] = 0; } y -= 2; y[1] = 0; setlg(y, k+2); return y; } GEN zxX_to_Kronecker(GEN P, GEN Q) { GEN z = zxX_to_Kronecker_spec(P+2, lg(P)-2, degpol(Q)); z[1] = P[1]; return z; } GEN FlxX_add(GEN x, GEN y, ulong p) { long i,lz; GEN z; long lx=lg(x); long ly=lg(y); if (ly>lx) swapspec(x,y, lx,ly); lz = lx; z = cgetg(lz, t_POL); z[1]=x[1]; for (i=2; i= ly) { z[1] = x[1]; for (i=2; i1) pari_warn(warnmem,"FlxY_Flx_translate, i = %ld/%ld", i,n); Q = gerepilecopy(av, Q); } } return gerepilecopy(av, Q); } /* allow pi = 0 */ GEN FlxY_evalx_powers_pre(GEN pol, GEN ypowers, ulong p, ulong pi) { long i, len = lg(pol); GEN res = cgetg(len, t_VECSMALL); res[1] = pol[1] & VARNBITS; for (i = 2; i < len; ++i) res[i] = Flx_eval_powers_pre(gel(pol, i), ypowers, p, pi); return Flx_renormalize(res, len); } /* allow pi = 0 */ ulong FlxY_eval_powers_pre(GEN pol, GEN ypowers, GEN xpowers, ulong p, ulong pi) { pari_sp av = avma; GEN t = FlxY_evalx_powers_pre(pol, ypowers, p, pi); return gc_ulong(av, Flx_eval_powers_pre(t, xpowers, p, pi)); } GEN FlxY_FlxqV_evalx_pre(GEN P, GEN x, GEN T, ulong p, ulong pi) { long i, lP = lg(P); GEN res = cgetg(lP,t_POL); res[1] = P[1]; for(i=2; i=2; i--) { gel(y,i+2) = Flx_Fl_mul(gel(x,i+2), t, p); t = Fl_mul(t, i, p); } gel(y,3) = Flx_copy(gel(x,3)); gel(y,2) = Flx_copy(gel(x,2)); return FlxX_renormalize(y, d+3); } GEN FlxX_Laplace(GEN x, ulong p) { long i, d = degpol(x); ulong t = 1; GEN y; if (d <= 1) return gcopy(x); y = cgetg(d+3, t_POL); y[1] = x[1]; gel(y,2) = Flx_copy(gel(x,2)); gel(y,3) = Flx_copy(gel(x,3)); for (i=2; i<=d; i++) { t = Fl_mul(t, i%p, p); gel(y,i+2) = Flx_Fl_mul(gel(x,i+2), t, p); } return FlxX_renormalize(y, d+3); } /***********************************************************************/ /** **/ /** FlxXV **/ /** **/ /***********************************************************************/ GEN FlxXC_sub(GEN x, GEN y, ulong p) { pari_APPLY_same(FlxX_sub(gel(x, i), gel(y,i), p)) } static GEN FlxXV_to_FlxM_lg(GEN x, long m, long n, long sv) { long i; GEN y = cgetg(n+1, t_MAT); for (i=1; i<=n; i++) gel(y,i) = FlxX_to_FlxC(gel(x,i), m, sv); return y; } GEN FlxXV_to_FlxM(GEN v, long n, long sv) { return FlxXV_to_FlxM_lg(v, n, lg(v)-1, sv); } GEN FlxXC_to_ZXXC(GEN x) { pari_APPLY_type(t_COL, FlxX_to_ZXX(gel(x,i))) } GEN FlxXM_to_ZXXM(GEN x) { pari_APPLY_same(FlxXC_to_ZXXC(gel(x,i))) } /***********************************************************************/ /** **/ /** FlxqX **/ /** **/ /***********************************************************************/ static GEN get_FlxqX_red(GEN T, GEN *B) { if (typ(T)!=t_VEC) { *B=NULL; return T; } *B = gel(T,1); return gel(T,2); } GEN RgX_to_FlxqX(GEN x, GEN T, ulong 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_Flxq(gel(x,i), T, p); return FlxX_renormalize(z, l); } /* FlxqX are t_POL with Flxq coefficients. * Normally the variable ordering should be respected.*/ GEN random_FlxqX(long d1, long v, GEN T, ulong p) { long dT = get_Flx_degree(T), vT = get_Flx_var(T); long i, d = d1+2; GEN y = cgetg(d,t_POL); y[1] = evalsigne(1) | evalvarn(v); for (i=2; iT,d->p,d->pi); } static GEN _FlxqX_sqr(void *data,GEN a) { struct _FlxqX *d=(struct _FlxqX*)data; return FlxqX_sqr_pre(a,d->T,d->p,d->pi); } GEN FlxqX_powu_pre(GEN V, ulong n, GEN T, ulong p, ulong pi) { struct _FlxqX d; d.p = p; d.pi = pi; d.T = T; return gen_powu(V, n, (void*)&d, &_FlxqX_sqr, &_FlxqX_mul); } GEN FlxqX_powu(GEN V, ulong n, GEN T, ulong p) { return FlxqX_powu_pre(V, n, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } /* x and y in Z[Y][X]. Assume T irreducible mod p */ static GEN FlxqX_divrem_basecase(GEN x, GEN y, GEN T, ulong p, ulong pi, GEN *pr) { long vx, dx, dy, dz, i, j, sx, lr; pari_sp av0, av, tetpil; GEN z,p1,rem,lead; if (!signe(y)) pari_err_INV("FlxqX_divrem",y); vx=varn(x); dy=degpol(y); dx=degpol(x); if (dx < dy) { if (pr) { av0 = avma; x = FlxqX_red_pre(x, T, p, pi); if (pr == ONLY_DIVIDES) { set_avma(av0); return signe(x)? NULL: pol_0(vx); } if (pr == ONLY_REM) return x; *pr = x; } return pol_0(vx); } lead = leading_coeff(y); if (!dy) /* y is constant */ { if (pr && pr != ONLY_DIVIDES) { if (pr == ONLY_REM) return pol_0(vx); *pr = pol_0(vx); } if (Flx_equal1(lead)) return gcopy(x); av0 = avma; x = FlxqX_Flxq_mul_pre(x,Flxq_inv(lead,T,p),T,p,pi); return gerepileupto(av0,x); } av0 = avma; dz = dx-dy; lead = Flx_equal1(lead)? NULL: gclone(Flxq_inv_pre(lead,T,p,pi)); set_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, Flxq_mul_pre(p1,lead, T,p,pi)): 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 = Flx_sub(p1, Flx_mul_pre(gel(z,j),gel(y,i-j),p,pi),p); if (lead) p1 = Flx_mul_pre(p1, lead,p,pi); tetpil=avma; gel(z,i-dy) = gerepile(av,tetpil,Flx_rem_pre(p1,T,p,pi)); } if (!pr) { guncloneNULL(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_pre(gel(z,j),gel(y,i-j),p,pi),p); tetpil=avma; p1 = Flx_rem_pre(p1, T,p,pi); if (lgpol(p1)) { sx = 1; break; } if (!i) break; set_avma(av); } if (pr == ONLY_DIVIDES) { guncloneNULL(lead); if (sx) return gc_NULL(av0); return gc_const((pari_sp)rem, 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_pre(gel(z,j),gel(y,i-j),p,pi), p); tetpil=avma; gel(rem,i) = gerepile(av,tetpil, Flx_rem_pre(p1, T,p,pi)); } rem -= 2; guncloneNULL(lead); if (!sx) (void)FlxX_renormalize(rem, lr); if (pr == ONLY_REM) return gerepileupto(av0,rem); *pr = rem; return z-2; } static GEN FlxqX_invBarrett_basecase(GEN T, GEN Q, ulong p, ulong pi) { long i, l=lg(T)-1, lr = l-1, k; long sv=Q[1]; GEN r=cgetg(lr,t_POL); r[1]=T[1]; gel(r,2) = pol1_Flx(sv); for (i=3;i=0; i--) if (lgpol(gel(x,i))) break; return i+1; } static GEN FlxqX_invBarrett_Newton(GEN S, GEN T, ulong p, ulong pi) { pari_sp av = avma; long nold, lx, lz, lq, l = degpol(S), i, lQ; GEN q, y, z, x = cgetg(l+2, t_POL) + 2; long dT = get_Flx_degree(T), vT = get_Flx_var(T); ulong mask = quadratic_prec_mask(l-2); /* assume l > 2 */ for (i=0;i1 && degpol(gel(q,1)) >= dT) gel(q,1) = Flx_rem_pre(gel(q,1), T, p, pi); if (lQ>1 && lgpol(gel(q,1))) { GEN u = gel(q, 1); if (!Flx_equal1(gel(x,0))) u = Flxq_mul_pre(u, Flxq_sqr_pre(gel(x,0), T,p,pi), T,p,pi); 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,pi, lx, lq); /* FIXME: high product */ lz = lgpol(z); if (lz > lnew) lz = lnew; z += 2; /* subtract 1 [=>first nold words are 0]: renormalize so that z(0) != 0 */ for (i = nold; i < lz; i++) if (lgpol(gel(z,i))) break; nold = nnew; if (i >= lz) continue; /* z-1 = 0(t^(nnew + 1)) */ /* z + i represents (x*q - 1) / t^i */ lz = FlxX_lgrenormalizespec (z+i, lz-i); z = FlxqX_mulspec(x, z+i, T,p,pi, lx, lz); /* FIXME: low product */ lz = lgpol(z); z += 2; if (lz > lnew-i) lz = FlxX_lgrenormalizespec(z, lnew-i); lx = lz+ i; y = x + i; /* x -= z * t^i, in place */ for (i = 0; i < lz; i++) gel(y,i) = Flx_neg(gel(z,i), p); } x -= 2; setlg(x, lx + 2); x[1] = S[1]; return gerepilecopy(av, x); } GEN FlxqX_invBarrett_pre(GEN T, GEN Q, ulong p, ulong pi) { pari_sp ltop=avma; long l=lg(T), v = varn(T); GEN r; GEN c = gel(T,l-1); if (l<5) return pol_0(v); if (l<=FlxqX_INVBARRETT_LIMIT) { if (!Flx_equal1(c)) { GEN ci = Flxq_inv_pre(c,Q,p,pi); T = FlxqX_Flxq_mul_pre(T, ci, Q, p, pi); r = FlxqX_invBarrett_basecase(T,Q,p,pi); r = FlxqX_Flxq_mul_pre(r,ci,Q,p,pi); } else r = FlxqX_invBarrett_basecase(T,Q,p,pi); } else r = FlxqX_invBarrett_Newton(T,Q,p,pi); return gerepileupto(ltop, r); } GEN FlxqX_invBarrett(GEN T, GEN Q, ulong p) { return FlxqX_invBarrett_pre(T, Q, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } GEN FlxqX_get_red_pre(GEN S, GEN T, ulong p, ulong pi) { if (typ(S)==t_POL && lg(S)>FlxqX_BARRETT_LIMIT) retmkvec2(FlxqX_invBarrett_pre(S, T, p, pi), S); return S; } GEN FlxqX_get_red(GEN S, GEN T, ulong p) { if (typ(S)==t_POL && lg(S)>FlxqX_BARRETT_LIMIT) retmkvec2(FlxqX_invBarrett(S, T, p), S); return S; } /* Compute x mod S where 2 <= degpol(S) <= l+1 <= 2*(degpol(S)-1) * * and mg is the Barrett inverse of S. */ static GEN FlxqX_divrem_Barrettspec(GEN x, long l, GEN mg, GEN S, GEN T, ulong p, ulong pi, GEN *pr) { GEN q, r; long lt = degpol(S); /*We discard the leading term*/ long ld, lm, lT, lmg; ld = l-lt; lm = minss(ld, lgpol(mg)); lT = FlxX_lgrenormalizespec(S+2,lt); lmg = FlxX_lgrenormalizespec(mg+2,lm); q = FlxX_recipspec(x+lt,ld,ld,0); /* = rec(x) lq<=ld*/ q = FlxqX_mulspec(q+2,mg+2,T,p,pi,lgpol(q),lmg); /* = rec(x)*mg lq<=ld+lm*/ q = FlxX_recipspec(q+2,minss(ld,lgpol(q)),ld,0); /* = rec(rec(x)*mg) lq<=ld*/ if (!pr) return q; r = FlxqX_mulspec(q+2,S+2,T,p,pi,lgpol(q),lT); /* = q*pol lr<=ld+lt*/ r = FlxX_subspec(x,r+2,p,lt,minss(lt,lgpol(r)));/* = x - r lr<=lt */ if (pr == ONLY_REM) return r; *pr = r; return q; } static GEN FlxqX_divrem_Barrett(GEN x, GEN mg, GEN S, GEN T, ulong p, ulong pi, GEN *pr) { GEN q = NULL, r = FlxqX_red_pre(x, T, p, pi); long l = lgpol(r), lt = degpol(S), lm = 2*lt-1, v = varn(S); long i; if (l <= lt) { if (pr == ONLY_REM) return r; if (pr == ONLY_DIVIDES) return signe(r)? NULL: pol_0(v); if (pr) *pr = r; return pol_0(v); } if (lt <= 1) return FlxqX_divrem_basecase(x,S,T,p,pi,pr); if (pr != ONLY_REM && l>lm) { long vT = get_Flx_var(T); q = cgetg(l-lt+2, t_POL); q[1] = S[1]; for (i=0;ilm) { GEN zr, zq = FlxqX_divrem_Barrettspec(r+2+l-lm,lm,mg,S,T,p,pi,&zr); long lz = lgpol(zr); if (pr != ONLY_REM) { long lq = lgpol(zq); for(i=0; i lt) r = FlxqX_divrem_Barrettspec(r+2,l,mg,S,T,p,pi,ONLY_REM); else r = FlxX_renormalize(r, l+2); setvarn(r, v); return r; } if (l > lt) { GEN zq = FlxqX_divrem_Barrettspec(r+2,l,mg,S,T,p,pi,pr? &r: NULL); if (!q) q = zq; else { long lq = lgpol(zq); for(i=0; i1; i--) /* z[i] = a[i+1] + x*z[i+1] */ gel(z, i) = Flxq_addmul_pre(gel(a,i+1), x, gel(z,i+1), T, p, pi); if (r) *r = Flxq_addmul_pre(gel(a,2), x, gel(z,2), T, p, pi); return z; } GEN FlxqX_div_by_X_x(GEN a, GEN x, GEN T, ulong p, GEN *r) { return FlxqX_div_by_X_x_pre(a, x, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p), r); } static GEN FlxqX_addmulmul(GEN u, GEN v, GEN x, GEN y, GEN T, ulong p, ulong pi) { return FlxX_add(FlxqX_mul_pre(u, x, T, p, pi), FlxqX_mul_pre(v, y, T, p, pi), p); } static GEN FlxqXM_FlxqX_mul2(GEN M, GEN x, GEN y, GEN T, ulong p, ulong pi) { GEN res = cgetg(3, t_COL); gel(res, 1) = FlxqX_addmulmul(gcoeff(M,1,1), gcoeff(M,1,2), x, y, T, p, pi); gel(res, 2) = FlxqX_addmulmul(gcoeff(M,2,1), gcoeff(M,2,2), x, y, T, p, pi); return res; } static GEN FlxqXM_mul2(GEN A, GEN B, GEN T, ulong p, ulong pi) { GEN A11=gcoeff(A,1,1),A12=gcoeff(A,1,2), B11=gcoeff(B,1,1),B12=gcoeff(B,1,2); GEN A21=gcoeff(A,2,1),A22=gcoeff(A,2,2), B21=gcoeff(B,2,1),B22=gcoeff(B,2,2); GEN M1 = FlxqX_mul_pre(FlxX_add(A11,A22, p), FlxX_add(B11,B22, p), T, p, pi); GEN M2 = FlxqX_mul_pre(FlxX_add(A21,A22, p), B11, T, p, pi); GEN M3 = FlxqX_mul_pre(A11, FlxX_sub(B12,B22, p), T, p, pi); GEN M4 = FlxqX_mul_pre(A22, FlxX_sub(B21,B11, p), T, p, pi); GEN M5 = FlxqX_mul_pre(FlxX_add(A11,A12, p), B22, T, p, pi); GEN M6 = FlxqX_mul_pre(FlxX_sub(A21,A11, p), FlxX_add(B11,B12, p), T, p, pi); GEN M7 = FlxqX_mul_pre(FlxX_sub(A12,A22, p), FlxX_add(B21,B22, p), T, p, pi); GEN T1 = FlxX_add(M1,M4, p), T2 = FlxX_sub(M7,M5, p); GEN T3 = FlxX_sub(M1,M2, p), T4 = FlxX_add(M3,M6, p); retmkmat22(FlxX_add(T1,T2, p), FlxX_add(M3,M5, p), FlxX_add(M2,M4, p), FlxX_add(T3,T4, p)); } /* Return [0,1;1,-q]*M */ static GEN FlxqX_FlxqXM_qmul(GEN q, GEN M, GEN T, ulong p, ulong pi) { GEN u = FlxqX_mul_pre(gcoeff(M,2,1), q, T,p,pi); GEN v = FlxqX_mul_pre(gcoeff(M,2,2), q, T,p,pi); retmkmat22(gcoeff(M,2,1), gcoeff(M,2,2), FlxX_sub(gcoeff(M,1,1), u, p), FlxX_sub(gcoeff(M,1,2), v, p)); } static GEN matid2_FlxXM(long v, long sv) { retmkmat22(pol1_FlxX(v, sv),pol_0(v),pol_0(v),pol1_FlxX(v, sv)); } static GEN matJ2_FlxXM(long v, long sv) { retmkmat22(pol_0(v),pol1_FlxX(v, sv),pol1_FlxX(v, sv),pol_0(v)); } struct FlxqX_res { GEN res, lc; long deg0, deg1, off; }; INLINE void FlxqX_halfres_update(long da, long db, long dr, GEN T, ulong p, ulong pi, struct FlxqX_res *res) { if (dr >= 0) { if (!Flx_equal1(res->lc)) { res->lc = Flxq_powu_pre(res->lc, da - dr, T, p, pi); res->res = Flxq_mul_pre(res->res, res->lc, T, p, pi); } if (both_odd(da + res->off, db + res->off)) res->res = Flx_neg(res->res, p); } else { if (db == 0) { if (!Flx_equal1(res->lc)) { res->lc = Flxq_powu_pre(res->lc, da, T, p, pi); res->res = Flxq_mul_pre(res->res, res->lc, T, p, pi); } } else res->res = pol0_Flx(get_Flx_var(T)); } } static GEN FlxqX_halfres_basecase(GEN a, GEN b, GEN T, ulong p, ulong pi, GEN *pa, GEN *pb, struct FlxqX_res *res) { pari_sp av=avma; GEN u,u1,v,v1, M; long vx = varn(a), vT = get_Flx_var(T), n = lgpol(a)>>1; u1 = v = pol_0(vx); u = v1 = pol1_FlxX(vx, vT); while (lgpol(b)>n) { GEN r, q; q = FlxqX_divrem(a,b, T, p, &r); if (res) { long da = degpol(a), db = degpol(b), dr = degpol(r); res->lc = gel(b,db+2); if (dr >= n) FlxqX_halfres_update(da, db, dr, T, p, pi, res); else { res->deg0 = da; res->deg1 = db; } } a = b; b = r; swap(u,u1); swap(v,v1); u1 = FlxX_sub(u1, FlxqX_mul_pre(u, q, T, p, pi), p); v1 = FlxX_sub(v1, FlxqX_mul_pre(v, q, T, p, pi), p); if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"FlxqX_halfgcd (d = %ld)",degpol(b)); if (res) gerepileall(av, 8, &a,&b,&u1,&v1,&u,&v,&res->res,&res->lc); else gerepileall(av, 6, &a,&b,&u1,&v1,&u,&v); } } M = mkmat22(u,v,u1,v1); *pa = a; *pb = b; return res ? gc_all(av, 5, &M, pa, pb, &res->res, &res->lc) : gc_all(av, 3, &M, pa, pb); } static GEN FlxqX_halfres_i(GEN x, GEN y, GEN T, ulong p, ulong pi, GEN *a, GEN *b, struct FlxqX_res *res); static GEN FlxqX_halfres_split(GEN x, GEN y, GEN T, ulong p, ulong pi, GEN *a, GEN *b, struct FlxqX_res *res) { pari_sp av = avma; GEN Q, R, S, V1, V2; GEN x1, y1, r, q; long l = lgpol(x), n = l>>1, k, vT = get_Flx_var(T); if (lgpol(y) <= n) { *a = RgX_copy(x); *b = RgX_copy(y); return matid2_FlxXM(varn(x), vT); } if (res) { res->lc = leading_coeff(y); res->deg0 -= n; res->deg1 -= n; res->off += n; } R = FlxqX_halfres_i(FlxX_shift(x,-n, vT),FlxX_shift(y,-n, vT), T, p, pi, a, b, res); if (res) { res->off -= n; res->deg0 += n; res->deg1 += n; } V1 = FlxqXM_FlxqX_mul2(R, Flxn_red(x,n), Flxn_red(y,n), T, p, pi); x1 = FlxX_add(FlxX_shift(*a,n,vT), gel(V1,1), p); y1 = FlxX_add(FlxX_shift(*b,n,vT), gel(V1,2), p); if (lgpol(y1) <= n) { *a = x1; *b = y1; return res ? gc_all(av, 5, &R, a, b, &res->res, &res->lc) : gc_all(av, 3, &R, a, b); } k = 2*n-degpol(y1); q = FlxqX_divrem(x1, y1, T, p, &r); if (res) { long dx1 = degpol(x1), dy1 = degpol(y1), dr = degpol(r); if (dy1 < degpol(y)) FlxqX_halfres_update(res->deg0, res->deg1, dy1, T, p, pi, res); res->lc = leading_coeff(y1); res->deg0 = dx1; res->deg1 = dy1; if (dr >= n) { FlxqX_halfres_update(dx1, dy1, dr, T, p, pi, res); res->deg0 = dy1; res->deg1 = dr; } res->deg0 -= k; res->deg1 -= k; res->off += k; } S = FlxqX_halfres_i(FlxX_shift(y1,-k, vT), FlxX_shift(r,-k, vT), T, p, pi, a, b, res); if (res) { res->deg0 += k; res->deg1 += k; res->off -= k; } Q = FlxqXM_mul2(S, FlxqX_FlxqXM_qmul(q, R, T, p, pi), T, p, pi); V2 = FlxqXM_FlxqX_mul2(S, FlxXn_red(y1,k), FlxXn_red(r,k), T, p, pi); *a = FlxX_add(FlxX_shift(*a,k,vT), gel(V2,1), p); *b = FlxX_add(FlxX_shift(*b,k,vT), gel(V2,2), p); return res ? gc_all(av, 5, &Q, a, b, &res->res, &res->lc) : gc_all(av, 3, &Q, a, b); } static GEN FlxqX_halfres_i(GEN x, GEN y, GEN T, ulong p, ulong pi, GEN *a, GEN *b, struct FlxqX_res *res) { if (lgpol(x) < FlxqX_HALFGCD_LIMIT) return FlxqX_halfres_basecase(x, y, T, p, pi, a, b, res); return FlxqX_halfres_split(x, y, T, p, pi, a, b, res); } static GEN FlxqX_halfgcd_all_i(GEN x, GEN y, GEN T, ulong p, ulong pi, GEN *pa, GEN *pb) { GEN a, b; GEN R = FlxqX_halfres_i(x, y, T, p, pi, &a, &b, NULL); if (pa) *pa = a; if (pb) *pb = b; return R; } /* Return M in GL_2(Fp[X]/(T)[Y]) such that: if [a',b']~=M*[a,b]~ then degpol(a')>= (lgpol(a)>>1) >degpol(b') */ GEN FlxqX_halfgcd_all_pre(GEN x, GEN y, GEN T, ulong p, ulong pi, GEN *a, GEN *b) { pari_sp av = avma; GEN R,q,r; if (!signe(x)) { if (a) *a = RgX_copy(y); if (b) *b = RgX_copy(x); return matJ2_FlxXM(varn(x),get_Flx_var(T)); } if (degpol(y)1) pari_warn(warnmem,"FlxqX_gcd (d = %ld)",degpol(b)); gerepileall(av0,2, &a,&b); } av = avma; c = FlxqX_rem_pre(a, b, T, p, pi); a=b; b=c; } return gc_const(av, a); } GEN FlxqX_gcd_pre(GEN x, GEN y, GEN T, ulong p, ulong pi) { pari_sp av = avma; x = FlxqX_red_pre(x, T, p, pi); y = FlxqX_red_pre(y, T, p, pi); if (!signe(x)) return gerepileupto(av, y); while (lgpol(y)>=FlxqX_GCD_LIMIT) { if (lgpol(y)<=(lgpol(x)>>1)) { GEN r = FlxqX_rem_pre(x, y, T, p, pi); x = y; y = r; } (void) FlxqX_halfgcd_all_pre(x,y, T, p, pi, &x, &y); if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"FlxqX_gcd (y = %ld)",degpol(y)); gerepileall(av,2,&x,&y); } } return gerepileupto(av, FlxqX_gcd_basecase(x, y, T, p, pi)); } GEN FlxqX_gcd(GEN x, GEN y, GEN T, ulong p) { return FlxqX_gcd_pre(x, y, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } static GEN FlxqX_extgcd_basecase(GEN a, GEN b, GEN T, ulong p,ulong pi, GEN *ptu, GEN *ptv) { pari_sp av=avma; GEN u,v,d,d1,v1; long vx = varn(a); d = a; d1 = b; v = pol_0(vx); v1 = pol1_FlxX(vx, get_Flx_var(T)); while (signe(d1)) { GEN r, q = FlxqX_divrem_pre(d, d1, T, p, pi, &r); v = FlxX_sub(v, FlxqX_mul_pre(q,v1,T, p, pi),p); u=v; v=v1; v1=u; u=r; d=d1; d1=u; if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"FlxqX_extgcd (d = %ld)",degpol(d)); gerepileall(av,5, &d,&d1,&u,&v,&v1); } } if (ptu) *ptu = FlxqX_div_pre(FlxX_sub(d,FlxqX_mul_pre(b,v, T,p,pi), p), a, T,p,pi); *ptv = v; return d; } static GEN FlxqX_extgcd_halfgcd(GEN x, GEN y, GEN T, ulong p, ulong pi, GEN *ptu, GEN *ptv) { GEN u,v; GEN V = cgetg(expu(lgpol(y))+2,t_VEC); long i, n = 0, vs = varn(x), vT = get_Flx_var(T); while (lgpol(y) >= FlxqX_EXTGCD_LIMIT) { if (lgpol(y)<=(lgpol(x)>>1)) { GEN r, q = FlxqX_divrem_pre(x, y, T, p, pi, &r); x = y; y = r; gel(V,++n) = mkmat22(pol_0(vs),pol1_FlxX(vs,vT),pol1_FlxX(vs,vT),FlxX_neg(q,p)); } else gel(V,++n) = FlxqX_halfgcd_all_pre(x, y, T, p, pi, &x, &y); } y = FlxqX_extgcd_basecase(x,y, T, p, pi, &u,&v); for (i = n; i>1; i--) { GEN R = gel(V,i); GEN u1 = FlxqX_addmulmul(u, v, gcoeff(R,1,1), gcoeff(R,2,1), T, p, pi); GEN v1 = FlxqX_addmulmul(u, v, gcoeff(R,1,2), gcoeff(R,2,2), T, p, pi); u = u1; v = v1; } { GEN R = gel(V,1); if (ptu) *ptu = FlxqX_addmulmul(u, v, gcoeff(R,1,1), gcoeff(R,2,1), T, p, pi); *ptv = FlxqX_addmulmul(u, v, gcoeff(R,1,2), gcoeff(R,2,2), T, p, pi); } return y; } /* 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 FlxqX_extgcd_pre(GEN x, GEN y, GEN T, ulong p, ulong pi, GEN *ptu, GEN *ptv) { pari_sp av = avma; GEN d; x = FlxqX_red_pre(x, T, p, pi); y = FlxqX_red_pre(y, T, p, pi); if (lgpol(y)>=FlxqX_EXTGCD_LIMIT) d = FlxqX_extgcd_halfgcd(x, y, T, p, pi, ptu, ptv); else d = FlxqX_extgcd_basecase(x, y, T, p, pi, ptu, ptv); return gc_all(av, ptu?3:2, &d, ptv, ptu); } GEN FlxqX_extgcd(GEN x, GEN y, GEN T, ulong p, GEN *ptu, GEN *ptv) { ulong pi = SMALL_ULONG(p)? 0: get_Fl_red(p); return FlxqX_extgcd_pre(x, y, T, p, pi, ptu, ptv); } static GEN FlxqX_saferem(GEN P, GEN Q, GEN T, ulong p, ulong pi) { GEN U = Flxq_invsafe_pre(leading_coeff(Q), T, p, pi); if (!U) return NULL; Q = FlxqX_Flxq_mul_to_monic_pre(Q,U,T,p,pi); return FlxqX_rem_pre(P,Q,T,p,pi); } GEN FlxqX_eval(GEN x, GEN y, GEN T, ulong p) { pari_sp av; GEN p1, r; long j, i=lg(x)-1; if (i<=2) return (i==2)? gcopy(gel(x,2)): pol0_Flx(get_Flx_var(T)); 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; lg(gel(x,j))==1; j--) if (j==2) { if (i!=j) y = Flxq_powu(y, i-j+1, T, p); return gerepileupto(av, Flxq_mul(p1,y, T, p)); } r = (i==j)? y: Flxq_powu(y, i-j+1, T, p); p1 = Flx_add(Flxq_mul(p1,r,T,p), gel(x,j), p); } return gerepileupto(av, p1); } GEN FlxqX_safegcd(GEN P, GEN Q, GEN T, ulong p) { pari_sp av = avma; ulong pi; GEN U; if (!signe(P)) return gcopy(Q); if (!signe(Q)) return gcopy(P); pi = SMALL_ULONG(p)? 0: get_Fl_red(p); T = Flx_get_red_pre(T,p,pi); for(;;) { P = FlxqX_saferem(P,Q,T,p,pi); if (!P) return gc_NULL(av); if (!signe(P)) break; if (gc_needed(av, 1)) { if (DEBUGMEM>1) pari_warn(warnmem,"FlxqX_safegcd"); gerepileall(av, 2, &P,&Q); } swap(P, Q); } U = Flxq_invsafe_pre(leading_coeff(Q), T, p, pi); if (!U) return gc_NULL(av); Q = FlxqX_Flxq_mul_to_monic_pre(Q,U,T,p,pi); return gerepileupto(av, Q); } /* Res(A,B) = Res(B,R) * lc(B)^(a-r) * (-1)^(ab), with R=A%B, a=deg(A) ...*/ GEN FlxqX_saferesultant(GEN a, GEN b, GEN T, ulong p) { long vT = get_Flx_var(T), da,db,dc; ulong pi; pari_sp av; GEN c,lb, res = pol1_Flx(vT); if (!signe(a) || !signe(b)) return pol0_Flx(vT); da = degpol(a); db = degpol(b); if (db > da) { swapspec(a,b, da,db); if (both_odd(da,db)) res = Flx_neg(res, p); } if (!da) return pol1_Flx(vT); /* = res * a[2] ^ db, since 0 <= db <= da = 0 */ pi = SMALL_ULONG(p)? 0: get_Fl_red(p); av = avma; while (db) { lb = gel(b,db+2); c = FlxqX_saferem(a,b, T,p,pi); if (!c) return gc_NULL(av); a = b; b = c; dc = degpol(c); if (dc < 0) { set_avma(av); return pol0_Flx(vT); } if (both_odd(da,db)) res = Flx_neg(res, p); if (!Flx_equal1(lb)) res = Flxq_mul_pre(res, Flxq_powu_pre(lb, da - dc, T, p, pi), T, p, pi); if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"FlxqX_resultant (da = %ld)",da); gerepileall(av,3, &a,&b,&res); } da = db; /* = degpol(a) */ db = dc; /* = degpol(b) */ } res = Flxq_mul_pre(res, Flxq_powu_pre(gel(b,2), da, T, p, pi), T, p, pi); return gerepileupto(av, res); } static GEN FlxqX_halfres(GEN x, GEN y, GEN T, ulong p, ulong pi, GEN *a, GEN *b, GEN *r) { struct FlxqX_res res; GEN V; long dB; res.res = *r; res.lc = leading_coeff(y); res.deg0 = degpol(x); res.deg1 = degpol(y); res.off = 0; V = FlxqX_halfres_i(x, y, T, p, pi, a, b, &res); dB = degpol(*b); if (dB < degpol(y)) FlxqX_halfres_update(res.deg0, res.deg1, dB, T, p, pi, &res); *r = res.res; return V; } static GEN FlxqX_resultant_basecase(GEN a, GEN b, GEN T, ulong p, ulong pi) { pari_sp av = avma; long vT = get_Flx_var(T), da,db,dc; GEN c,lb, res = pol1_Flx(vT); if (!signe(a) || !signe(b)) return pol0_Flx(vT); da = degpol(a); db = degpol(b); if (db > da) { swapspec(a,b, da,db); if (both_odd(da,db)) res = Flx_neg(res, p); } if (!da) return pol1_Flx(vT); /* = res * a[2] ^ db, since 0 <= db <= da = 0 */ while (db) { lb = gel(b,db+2); c = FlxqX_rem_pre(a,b, T,p,pi); a = b; b = c; dc = degpol(c); if (dc < 0) { set_avma(av); return pol0_Flx(vT); } if (both_odd(da,db)) res = Flx_neg(res, p); if (!Flx_equal1(lb)) res = Flxq_mul_pre(res, Flxq_powu_pre(lb, da - dc, T,p,pi), T,p,pi); if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"FlxqX_resultant (da = %ld)",da); gerepileall(av,3, &a,&b,&res); } da = db; /* = degpol(a) */ db = dc; /* = degpol(b) */ } res = Flxq_mul_pre(res, Flxq_powu_pre(gel(b,2), da, T,p,pi), T,p,pi); return gerepileupto(av, res); } /* Res(A,B) = Res(B,R) * lc(B)^(a-r) * (-1)^(ab), with R=A%B, a=deg(A) ...*/ GEN FlxqX_resultant_pre(GEN x, GEN y, GEN T, ulong p, ulong pi) { pari_sp av = avma; long dx, dy, vT = get_Flx_var(T); GEN res = pol1_Flx(vT); if (!signe(x) || !signe(y)) return pol0_Flx(vT); dx = degpol(x); dy = degpol(y); if (dx < dy) { swap(x,y); if (both_odd(dx, dy)) res = Flx_neg(res, p); } while (lgpol(y) >= FlxqX_GCD_LIMIT) { if (lgpol(y)<=(lgpol(x)>>1)) { GEN r = FlxqX_rem_pre(x, y, T, p, pi); long dx = degpol(x), dy = degpol(y), dr = degpol(r); GEN ly = gel(y,dy+2); if (!Flx_equal1(ly)) res = Flxq_mul_pre(res, Flxq_powu_pre(ly, dx - dr, T, p, pi), T, p, pi); if (both_odd(dx, dy)) res = Flx_neg(res, p); x = y; y = r; } (void) FlxqX_halfres(x, y, T, p, pi, &x, &y, &res); if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"FlxqX_resultant (y = %ld)",degpol(y)); gerepileall(av,3,&x,&y,&res); } } res = Flxq_mul_pre(res, FlxqX_resultant_basecase(x, y, T, p, pi), T, p, pi); return gerepileupto(av, res); } GEN FlxqX_resultant(GEN x, GEN y, GEN T, ulong p) { return FlxqX_resultant_pre(x, y, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } /* disc P = (-1)^(n(n-1)/2) lc(P)^(n - deg P' - 2) Res(P,P'), n = deg P */ GEN FlxqX_disc(GEN P, GEN T, ulong p) { pari_sp av = avma; GEN L, dP = FlxX_deriv(P, p), D = FlxqX_resultant(P, dP, T, p); long dd; if (!lgpol(D)) return pol0_Flx(get_Flx_var(T)); dd = degpol(P) - 2 - degpol(dP); /* >= -1; > -1 iff p | deg(P) */ L = leading_coeff(P); if (dd && !Flx_equal1(L)) { ulong pi = SMALL_ULONG(p)? 0: get_Fl_red(p); D = (dd == -1)? Flxq_div_pre(D,L,T,p,pi) : Flxq_mul_pre(D, Flxq_powu_pre(L, dd, T,p,pi), T,p,pi); } if (degpol(P) & 2) D = Flx_neg(D, p); return gerepileupto(av, D); } INLINE GEN FlxXn_recip(GEN x, long n, long v) { return FlxX_recipspec(x+2, minss(lgpol(x), n), n, v); } GEN FlxqX_Newton_pre(GEN P, long n, GEN T, ulong p, ulong pi) { pari_sp av = avma; long d = degpol(P), vT = get_Flx_var(T); GEN dP = FlxXn_recip(FlxX_deriv(P, p), d, vT); GEN Q = FlxqXn_mul_pre(FlxqXn_inv_pre(FlxXn_recip(P, d+1, vT), n, T,p,pi), dP, n, T, p, pi); return gerepilecopy(av, Q); } GEN FlxqX_Newton(GEN P, long n, GEN T, ulong p) { return FlxqX_Newton_pre(P, n, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } GEN FlxqX_fromNewton_pre(GEN P, GEN T, ulong p, ulong pi) { pari_sp av = avma; long vT = get_Flx_var(T); long n = Flx_constant(constant_coeff(P))+1; GEN z = FlxX_neg(FlxX_shift(P, -1, vT), p); GEN Q = FlxXn_recip(FlxqXn_expint_pre(z, n, T, p, pi), n, vT); return gerepilecopy(av, Q); } GEN FlxqX_fromNewton(GEN P, GEN T, ulong p) { return FlxqX_fromNewton_pre(P, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } GEN FlxqX_composedsum(GEN P, GEN Q, GEN T, ulong p) { pari_sp av = avma; ulong pi = SMALL_ULONG(p)? 0: get_Fl_red(p); long n = 1+ degpol(P)*degpol(Q); GEN Pl = FlxX_invLaplace(FlxqX_Newton_pre(P,n, T,p,pi), p); GEN Ql = FlxX_invLaplace(FlxqX_Newton_pre(Q,n, T,p,pi), p); GEN L = FlxX_Laplace(FlxqXn_mul_pre(Pl, Ql, n, T,p,pi), p); GEN R = FlxqX_fromNewton_pre(L, T, p, pi); GEN lead = Flxq_mul_pre(Flxq_powu_pre(leading_coeff(P),degpol(Q), T,p,pi), Flxq_powu_pre(leading_coeff(Q),degpol(P), T,p,pi), T, p, pi); return gerepileupto(av, FlxqX_Flxq_mul_pre(R, lead, T, p, pi)); } GEN FlxqXV_prod(GEN V, GEN T, ulong p) { struct _FlxqX d; d.p=p; d.T=T; d.pi = SMALL_ULONG(p)? 0: get_Fl_red(p); return gen_product(V, (void*)&d, &_FlxqX_mul); } static GEN FlxqV_roots_to_deg1(GEN x, GEN T, ulong p, long v) { long sv = get_Flx_var(T); pari_APPLY_same(deg1pol_shallow(pol1_Flx(sv),Flx_neg(gel(x,i),p),v)) } GEN FlxqV_roots_to_pol(GEN V, GEN T, ulong p, long v) { pari_sp ltop = avma; GEN W = FlxqV_roots_to_deg1(V, T, p, v); return gerepileupto(ltop, FlxqXV_prod(W, T, p)); } /*******************************************************************/ /* */ /* (Fl[X]/T(X))[Y] / S(Y) */ /* */ /*******************************************************************/ GEN FlxqXQ_mul_pre(GEN x, GEN y, GEN S, GEN T, ulong p, ulong pi) { return FlxqX_rem_pre(FlxqX_mul_pre(x,y,T,p,pi),S,T,p,pi); } GEN FlxqXQ_mul(GEN x, GEN y, GEN S, GEN T, ulong p) { return FlxqXQ_mul_pre(x, y, S, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } GEN FlxqXQ_sqr_pre(GEN x, GEN S, GEN T, ulong p, ulong pi) { return FlxqX_rem_pre(FlxqX_sqr_pre(x,T,p,pi),S,T,p,pi); } GEN FlxqXQ_sqr(GEN x, GEN S, GEN T, ulong p) { return FlxqXQ_sqr_pre(x, S, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } GEN FlxqXQ_invsafe_pre(GEN x, GEN S, GEN T, ulong p, ulong pi) { GEN V, z = FlxqX_extgcd_pre(get_FlxqX_mod(S), x, T, p, pi, NULL, &V); if (degpol(z)) return NULL; z = Flxq_invsafe_pre(gel(z,2),T,p,pi); if (!z) return NULL; return FlxqX_Flxq_mul_pre(V, z, T, p, pi); } GEN FlxqXQ_invsafe(GEN x, GEN S, GEN T, ulong p) { return FlxqXQ_invsafe_pre(x, S, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } GEN FlxqXQ_inv_pre(GEN x, GEN S, GEN T, ulong p, ulong pi) { pari_sp av = avma; GEN U = FlxqXQ_invsafe_pre(x, S, T, p, pi); if (!U) pari_err_INV("FlxqXQ_inv",x); return gerepileupto(av, U); } GEN FlxqXQ_inv(GEN x, GEN S, GEN T,ulong p) { return FlxqXQ_inv_pre(x, S, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } GEN FlxqXQ_div_pre(GEN x, GEN y, GEN S, GEN T, ulong p, ulong pi) { return FlxqXQ_mul_pre(x, FlxqXQ_inv_pre(y,S,T,p,pi),S,T,p,pi); } GEN FlxqXQ_div(GEN x, GEN y, GEN S, GEN T, ulong p) { return FlxqXQ_div_pre(x, y, S, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } struct _FlxqXQ { GEN T, S; ulong p, pi; }; static GEN _FlxqXQ_add(void *data, GEN x, GEN y) { struct _FlxqXQ *d = (struct _FlxqXQ*) data; return FlxX_add(x,y, d->p); } static GEN _FlxqXQ_sub(void *data, GEN x, GEN y) { struct _FlxqXQ *d = (struct _FlxqXQ*) data; return FlxX_sub(x,y, d->p); } #if 0 static GEN _FlxqXQ_cmul(void *data, GEN P, long a, GEN x) { struct _FlxqXQ *d = (struct _FlxqXQ*) data; return FlxX_Flx_mul(x,gel(P,a+2), d->p); } #endif static GEN _FlxqXQ_red(void *data, GEN x) { struct _FlxqXQ *d = (struct _FlxqXQ*) data; return FlxqX_red_pre(x, d->T, d->p, d->pi); } static GEN _FlxqXQ_mul(void *data, GEN x, GEN y) { struct _FlxqXQ *d = (struct _FlxqXQ*) data; return FlxqXQ_mul_pre(x,y, d->S,d->T, d->p, d->pi); } static GEN _FlxqXQ_sqr(void *data, GEN x) { struct _FlxqXQ *d = (struct _FlxqXQ*) data; return FlxqXQ_sqr_pre(x, d->S,d->T, d->p, d->pi); } static GEN _FlxqXQ_one(void *data) { struct _FlxqXQ *d = (struct _FlxqXQ*) data; return pol1_FlxX(get_FlxqX_var(d->S),get_Flx_var(d->T)); } static GEN _FlxqXQ_zero(void *data) { struct _FlxqXQ *d = (struct _FlxqXQ*) data; return pol_0(get_FlxqX_var(d->S)); } static struct bb_algebra FlxqXQ_algebra = { _FlxqXQ_red, _FlxqXQ_add, _FlxqXQ_sub, _FlxqXQ_mul, _FlxqXQ_sqr, _FlxqXQ_one, _FlxqXQ_zero }; const struct bb_algebra * get_FlxqXQ_algebra(void **E, GEN S, GEN T, ulong p) { ulong pi = SMALL_ULONG(p)? 0: get_Fl_red(p); GEN z = new_chunk(sizeof(struct _FlxqXQ)); struct _FlxqXQ *e = (struct _FlxqXQ *) z; e->T = Flx_get_red_pre(T, p, pi); e->S = FlxqX_get_red_pre(S, e->T, p, pi); e->p = p; e->pi= pi; *E = (void*)e; return &FlxqXQ_algebra; } /* x over Fq, return lift(x^n) mod S */ GEN FlxqXQ_pow_pre(GEN x, GEN n, GEN S, GEN T, ulong p, ulong pi) { pari_sp av = avma; struct _FlxqXQ D; long s = signe(n); if (!s) return pol1_FlxX(get_FlxqX_var(S),get_Flx_var(T)); if (s < 0) x = FlxqXQ_inv_pre(x,S,T,p,pi); if (is_pm1(n)) return s < 0 ? x : gcopy(x); if (degpol(x) >= get_FlxqX_degree(S)) x = FlxqX_rem_pre(x,S,T,p,pi); T = Flx_get_red_pre(T, p, pi); S = FlxqX_get_red_pre(S, T, p, pi); D.S = S; D.T = T; D.p = p; D.pi = pi; x = gen_pow_i(x, n, (void*)&D, &_FlxqXQ_sqr, &_FlxqXQ_mul); return gerepilecopy(av, x); } GEN FlxqXQ_pow(GEN x, GEN n, GEN S, GEN T, ulong p) { return FlxqXQ_pow_pre(x, n, S, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } /* x over Fq, return lift(x^n) mod S */ GEN FlxqXQ_powu_pre(GEN x, ulong n, GEN S, GEN T, ulong p, ulong pi) { pari_sp av = avma; struct _FlxqXQ D; switch(n) { case 0: return pol1_FlxX(get_FlxqX_var(S),get_Flx_var(T)); case 1: return gcopy(x); case 2: return FlxqXQ_sqr_pre(x, S, T, p, pi); } T = Flx_get_red_pre(T, p, pi); S = FlxqX_get_red_pre(S, T, p, pi); D.S = S; D.T = T; D.p = p; D.pi = pi; x = gen_powu_i(x, n, (void*)&D, &_FlxqXQ_sqr, &_FlxqXQ_mul); return gerepilecopy(av, x); } GEN FlxqXQ_powu(GEN x, ulong n, GEN S, GEN T, ulong p) { return FlxqXQ_powu_pre(x, n, S, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } GEN FlxqXQ_powers_pre(GEN x, long l, GEN S, GEN T, ulong p, ulong pi) { struct _FlxqXQ D; int use_sqr = 2*degpol(x) >= get_FlxqX_degree(S); T = Flx_get_red_pre(T, p, pi); S = FlxqX_get_red_pre(S, T, p, pi); D.S = S; D.T = T; D.p = p; D.pi = pi; return gen_powers(x, l, use_sqr, (void*)&D, &_FlxqXQ_sqr, &_FlxqXQ_mul,&_FlxqXQ_one); } GEN FlxqXQ_powers(GEN x, long l, GEN S, GEN T, ulong p) { return FlxqXQ_powers_pre(x, l, S, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } /* Let v a linear form, return the linear form z->v(tau*z) that is, v*(M_tau) */ static GEN FlxqXQ_transmul_init(GEN tau, GEN S, GEN T, ulong p, ulong pi) { GEN bht; GEN h, Sp = get_FlxqX_red(S, &h); long n = degpol(Sp), vS = varn(Sp), vT = get_Flx_var(T); GEN ft = FlxX_recipspec(Sp+2, n+1, n+1, vT); GEN bt = FlxX_recipspec(tau+2, lgpol(tau), n, vT); setvarn(ft, vS); setvarn(bt, vS); if (h) bht = FlxqXn_mul_pre(bt, h, n-1, T, p, pi); else { GEN bh = FlxqX_div_pre(FlxX_shift(tau, n-1, vT), S, T, p, pi); bht = FlxX_recipspec(bh+2, lgpol(bh), n-1, vT); setvarn(bht, vS); } return mkvec3(bt, bht, ft); } static GEN FlxqXQ_transmul(GEN tau, GEN a, long n, GEN T, ulong p, ulong pi) { pari_sp ltop = avma; GEN t1, t2, t3, vec; GEN bt = gel(tau, 1), bht = gel(tau, 2), ft = gel(tau, 3); long vT = get_Flx_var(T); if (signe(a)==0) return pol_0(varn(a)); t2 = FlxX_shift(FlxqX_mul_pre(bt, a, T, p, pi),1-n,vT); if (signe(bht)==0) return gerepilecopy(ltop, t2); t1 = FlxX_shift(FlxqX_mul_pre(ft, a, T, p, pi),-n,vT); t3 = FlxqXn_mul_pre(t1, bht, n-1, T, p, pi); vec = FlxX_sub(t2, FlxX_shift(t3, 1, vT), p); return gerepileupto(ltop, vec); } static GEN polxn_FlxX(long n, long v, long vT) { long i, a = n+2; GEN p = cgetg(a+1, t_POL); p[1] = evalsigne(1)|evalvarn(v); for (i = 2; i < a; i++) gel(p,i) = pol0_Flx(vT); gel(p,a) = pol1_Flx(vT); return p; } GEN FlxqXQ_minpoly_pre(GEN x, GEN S, GEN T, ulong p, ulong pi) { pari_sp ltop = avma; long vS, vT, n; GEN v_x, g, tau; vS = get_FlxqX_var(S); vT = get_Flx_var(T); n = get_FlxqX_degree(S); g = pol1_FlxX(vS,vT); tau = pol1_FlxX(vS,vT); S = FlxqX_get_red_pre(S, T, p, pi); v_x = FlxqXQ_powers_pre(x, usqrt(2*n), S, T, p, pi); while(signe(tau) != 0) { long i, j, m, k1; GEN M, v, tr; GEN g_prime, c; if (degpol(g) == n) { tau = pol1_FlxX(vS, vT); g = pol1_FlxX(vS, vT); } v = random_FlxqX(n, vS, T, p); tr = FlxqXQ_transmul_init(tau, S, T, p, pi); v = FlxqXQ_transmul(tr, v, n, T, p, pi); m = 2*(n-degpol(g)); k1 = usqrt(m); tr = FlxqXQ_transmul_init(gel(v_x,k1+1), S, T, p, pi); c = cgetg(m+2,t_POL); c[1] = evalsigne(1)|evalvarn(vS); for (i=0; i , i = 0..m-1 */ M = FlxqX_halfgcd_pre(polxn_FlxX(m, vS, vT), c, T, p, pi); g_prime = gmael(M, 2, 2); if (degpol(g_prime) < 1) continue; g = FlxqX_mul_pre(g, g_prime, T, p, pi); tau = FlxqXQ_mul_pre(tau, FlxqX_FlxqXQV_eval_pre(g_prime, v_x, S, T,p,pi), S, T, p,pi); } g = FlxqX_normalize_pre(g,T,p,pi); return gerepilecopy(ltop,g); } GEN FlxqXQ_minpoly(GEN x, GEN S, GEN T, ulong p) { return FlxqXQ_minpoly_pre(x, S, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } GEN FlxqXQ_matrix_pow(GEN y, long n, long m, GEN S, GEN T, ulong p) { return FlxXV_to_FlxM(FlxqXQ_powers(y,m-1,S,T,p), n, get_Flx_var(T)); } static GEN FlxX_blocks_FlxM(GEN P, long n, long m, long v) { GEN z = cgetg(m+1,t_MAT); long i,j, k=2, l = lg(P); for(i=1; i<=m; i++) { GEN zi = cgetg(n+1,t_COL); gel(z,i) = zi; for(j=1; j<=n; j++) gel(zi, j) = k==l ? pol0_Flx(v) : gel(P,k++); } return z; } GEN FlxqX_FlxqXQV_eval_pre(GEN Q, GEN x, GEN S, GEN T, ulong p, ulong pi) { pari_sp btop, av = avma; long v = get_FlxqX_var(S), m = get_FlxqX_degree(S); long vT = get_Flx_var(T); long i, l = lg(x)-1, lQ = lgpol(Q), n, d; GEN A, B, C, R, g; if (lQ == 0) return pol_0(v); if (lQ <= l) { n = l; d = 1; } else { n = l-1; d = (lQ+n-1)/n; } A = FlxXV_to_FlxM_lg(x, m, n, vT); B = FlxX_blocks_FlxM(Q, n, d, vT); C = gerepileupto(av, FlxqM_mul(A, B, T, p)); g = gel(x, l); T = Flx_get_red_pre(T, p, pi); S = FlxqX_get_red_pre(S, T, p, pi); btop = avma; R = FlxV_to_FlxX(gel(C, d), v); for (i = d-1; i>0; i--) { R = FlxX_add(FlxqXQ_mul_pre(R, g, S, T,p,pi), FlxV_to_FlxX(gel(C,i), v), p); if (gc_needed(btop,1)) R = gerepileupto(btop, R); } return gerepilecopy(av, R); } GEN FlxqX_FlxqXQV_eval(GEN Q, GEN x, GEN S, GEN T, ulong p) { return FlxqX_FlxqXQV_eval_pre(Q,x,S,T,p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } GEN FlxqX_FlxqXQ_eval_pre(GEN Q, GEN x, GEN S, GEN T, ulong p, ulong pi) { pari_sp av = avma; GEN z, V; long d = degpol(Q), rtd; if (d < 0) return pol_0(get_FlxqX_var(S)); rtd = (long) sqrt((double)d); T = Flx_get_red_pre(T, p, pi); S = FlxqX_get_red_pre(S, T, p, pi); V = FlxqXQ_powers_pre(x, rtd, S, T, p, pi); z = FlxqX_FlxqXQV_eval_pre(Q, V, S, T, p, pi); return gerepileupto(av, z); } GEN FlxqX_FlxqXQ_eval(GEN Q, GEN x, GEN S, GEN T, ulong p) { return FlxqX_FlxqXQ_eval_pre(Q, x, S, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } GEN FlxqXC_FlxqXQV_eval_pre(GEN x, GEN v, GEN S, GEN T, ulong p, ulong pi) { pari_APPLY_type(t_COL, FlxqX_FlxqXQV_eval_pre(gel(x,i), v, S, T, p, pi)) } GEN FlxqXC_FlxqXQV_eval(GEN x, GEN v, GEN S, GEN T, ulong p) { return FlxqXC_FlxqXQV_eval_pre(x, v, S, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } GEN FlxqXC_FlxqXQ_eval(GEN x, GEN F, GEN S, GEN T, ulong p) { long d = brent_kung_optpow(get_FlxqX_degree(S)-1,lg(x)-1,1); ulong pi = SMALL_ULONG(p)? 0: get_Fl_red(p); GEN Fp = FlxqXQ_powers_pre(F, d, S, T, p, pi); return FlxqXC_FlxqXQV_eval_pre(x, Fp, S, T, p, pi); } static GEN FlxqXQ_autpow_sqr(void * E, GEN x) { struct _FlxqXQ *D = (struct _FlxqXQ *)E; GEN S = D->S, T = D->T; ulong p = D->p, pi = D->pi; GEN phi = gel(x,1), S1 = gel(x,2); long n = brent_kung_optpow(get_Flx_degree(T)-1,lgpol(S1)+1,1); GEN V = Flxq_powers_pre(phi, n, T, p, pi); GEN phi2 = Flx_FlxqV_eval_pre(phi, V, T, p, pi); GEN Sphi = FlxY_FlxqV_evalx_pre(S1, V, T, p, pi); GEN S2 = FlxqX_FlxqXQ_eval_pre(Sphi, S1, S, T, p, pi); return mkvec2(phi2, S2); } static GEN FlxqXQ_autpow_mul(void * E, GEN x, GEN y) { struct _FlxqXQ *D = (struct _FlxqXQ *)E; GEN S = D->S, T = D->T; ulong p = D->p, pi = D->pi; GEN phi1 = gel(x,1), S1 = gel(x,2); GEN phi2 = gel(y,1), S2 = gel(y,2); long n = brent_kung_optpow(get_Flx_degree(T)-1,lgpol(S1)+1,1); GEN V = Flxq_powers_pre(phi2, n, T, p, pi); GEN phi3 = Flx_FlxqV_eval_pre(phi1, V, T, p, pi); GEN Sphi = FlxY_FlxqV_evalx_pre(S1, V, T, p, pi); GEN S3 = FlxqX_FlxqXQ_eval_pre(Sphi, S2, S, T, p, pi); return mkvec2(phi3, S3); } GEN FlxqXQ_autpow_pre(GEN aut, long n, GEN S, GEN T, ulong p, ulong pi) { pari_sp av = avma; struct _FlxqXQ D; T = Flx_get_red_pre(T, p, pi); S = FlxqX_get_red_pre(S, T, p, pi); D.S = S; D.T = T; D.p = p; D.pi = pi; aut = gen_powu_i(aut,n,&D,FlxqXQ_autpow_sqr,FlxqXQ_autpow_mul); return gerepilecopy(av, aut); } GEN FlxqXQ_autpow(GEN aut, long n, GEN S, GEN T, ulong p) { return FlxqXQ_autpow_pre(aut, n, S, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } static GEN FlxqXQ_autsum_mul(void *E, GEN x, GEN y) { struct _FlxqXQ *D = (struct _FlxqXQ *)E; GEN S = D->S, T = D->T; ulong p = D->p, pi = D->pi; GEN phi1 = gel(x,1), S1 = gel(x,2), a1 = gel(x,3); GEN phi2 = gel(y,1), S2 = gel(y,2), a2 = gel(y,3); long n2 = brent_kung_optpow(get_Flx_degree(T)-1, lgpol(S1)+lgpol(a1)+1,1); GEN V2 = Flxq_powers_pre(phi2, n2, T, p, pi); GEN phi3 = Flx_FlxqV_eval_pre(phi1, V2, T, p, pi); GEN Sphi = FlxY_FlxqV_evalx_pre(S1, V2, T, p, pi); GEN aphi = FlxY_FlxqV_evalx_pre(a1, V2, T, p, pi); long n = brent_kung_optpow(maxss(degpol(Sphi),degpol(aphi)),2,1); GEN V = FlxqXQ_powers_pre(S2, n, S, T, p, pi); GEN S3 = FlxqX_FlxqXQV_eval_pre(Sphi, V, S, T, p, pi); GEN aS = FlxqX_FlxqXQV_eval_pre(aphi, V, S, T, p, pi); GEN a3 = FlxqXQ_mul_pre(aS, a2, S, T, p, pi); return mkvec3(phi3, S3, a3); } static GEN FlxqXQ_autsum_sqr(void * T, GEN x) { return FlxqXQ_autsum_mul(T, x, x); } GEN FlxqXQ_autsum_pre(GEN aut, long n, GEN S, GEN T, ulong p, ulong pi) { pari_sp av = avma; struct _FlxqXQ D; T = Flx_get_red_pre(T, p, pi); S = FlxqX_get_red_pre(S, T, p, pi); D.S=S; D.T=T; D.p=p; D.pi=pi; aut = gen_powu_i(aut,n,&D,FlxqXQ_autsum_sqr,FlxqXQ_autsum_mul); return gerepilecopy(av, aut); } GEN FlxqXQ_autsum(GEN aut, long n, GEN S, GEN T, ulong p) { return FlxqXQ_autsum_pre(aut, n, S, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } static GEN FlxqXQ_auttrace_mul(void *E, GEN x, GEN y) { struct _FlxqXQ *D = (struct _FlxqXQ *)E; GEN S = D->S, T = D->T; ulong p = D->p, pi = D->pi; GEN S1 = gel(x,1), a1 = gel(x,2); GEN S2 = gel(y,1), a2 = gel(y,2); long n = brent_kung_optpow(maxss(degpol(S1),degpol(a1)),2,1); GEN V = FlxqXQ_powers_pre(S2, n, S, T, p, pi); GEN S3 = FlxqX_FlxqXQV_eval_pre(S1, V, S, T, p, pi); GEN aS = FlxqX_FlxqXQV_eval_pre(a1, V, S, T, p, pi); GEN a3 = FlxX_add(aS, a2, p); return mkvec2(S3, a3); } static GEN FlxqXQ_auttrace_sqr(void *E, GEN x) { return FlxqXQ_auttrace_mul(E, x, x); } GEN FlxqXQ_auttrace_pre(GEN x, ulong n, GEN S, GEN T, ulong p, ulong pi) { pari_sp av = avma; struct _FlxqXQ D; T = Flx_get_red_pre(T, p, pi); S = FlxqX_get_red_pre(S, T, p, pi); D.S=S; D.T=T; D.p=p; D.pi = pi; x = gen_powu_i(x,n,(void*)&D,FlxqXQ_auttrace_sqr,FlxqXQ_auttrace_mul); return gerepilecopy(av, x); } GEN FlxqXQ_auttrace(GEN x, ulong n, GEN S, GEN T, ulong p) { return FlxqXQ_auttrace_pre(x, n, S, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } /*******************************************************************/ /* */ /* FlxYqQ */ /* */ /*******************************************************************/ /*Preliminary implementation to speed up FpX_ffisom*/ typedef struct { GEN S, T; ulong p, pi; } FlxYqq_muldata; /* reduce x in Fl[X, Y] in the algebra Fl[X, Y]/ (P(X),Q(Y)) */ static GEN FlxYqq_redswap(GEN x, GEN S, GEN T, ulong p, ulong pi) { pari_sp ltop=avma; long n = get_Flx_degree(S); long m = get_Flx_degree(T); long w = get_Flx_var(T); GEN V = FlxX_swap(x,m,w); V = FlxqX_red_pre(V,S,p,pi); V = FlxX_swap(V,n,w); return gerepilecopy(ltop,V); } static GEN FlxYqq_sqr(void *data, GEN x) { FlxYqq_muldata *D = (FlxYqq_muldata*)data; return FlxYqq_redswap(FlxqX_sqr_pre(x,D->T,D->p,D->pi),D->S,D->T,D->p,D->pi); } static GEN FlxYqq_mul(void *data, GEN x, GEN y) { FlxYqq_muldata *D = (FlxYqq_muldata*)data; return FlxYqq_redswap(FlxqX_mul_pre(x,y, D->T,D->p,D->pi),D->S,D->T,D->p,D->pi); } /* 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) { FlxYqq_muldata D; D.S = S; D.T = T; D.p = p; D.pi = SMALL_ULONG(p)? 0: get_Fl_red(p); return gen_pow(x, n, (void*)&D, &FlxYqq_sqr, &FlxYqq_mul); } /*******************************************************************/ /* */ /* FlxqXn */ /* */ /*******************************************************************/ GEN FlxXn_red(GEN a, long n) { long i, L = n+2, l = lg(a); GEN b; if (L >= l) return a; /* deg(x) < n */ b = cgetg(L, t_POL); b[1] = a[1]; for (i=2; i1;) { GEN u, fr; long n2 = n; n<<=1; if (mask & 1) n--; mask >>= 1; fr = FlxXn_red(f, n); u = FlxqXn_mul_pre(W, FlxqXn_mulhigh(fr, W, n2, n, T,p,pi), n-n2, T,p,pi); W = FlxX_sub(W, FlxX_shift(u, n2, vT), p); if (gc_needed(av2,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"FlxqXn_inv, e = %ld", n); W = gerepileupto(av2, W); } } return gerepileupto(av, W); } GEN FlxqXn_inv(GEN f, long e, GEN T, ulong p) { return FlxqXn_inv_pre(f, e, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } /* Compute intformal(x^n*S)/x^(n+1) */ static GEN FlxX_integXn(GEN x, long n, ulong p) { long i, lx = lg(x); GEN y; if (lx == 2) return gcopy(x); y = cgetg(lx, t_POL); y[1] = x[1]; for (i=2; i1;) { GEN u, w; long n2 = n; n<<=1; if (mask & 1) n--; mask >>= 1; u = FlxqXn_mul_pre(g, FlxqX_mulhigh_i(f, FlxXn_red(h, n2-1), n2-1, T,p,pi), n-n2, T,p,pi); u = FlxX_add(u, FlxX_shift(FlxXn_red(h, n-1), 1-n2, vT), p); w = FlxqXn_mul_pre(f, FlxX_integXn(u, n2-1, p), n-n2, T, p, pi); f = FlxX_add(f, FlxX_shift(w, n2, vT), p); if (mask<=1) break; u = FlxqXn_mul_pre(g, FlxqXn_mulhigh(f, g, n2, n, T,p,pi), n-n2, T,p,pi); g = FlxX_sub(g, FlxX_shift(u, n2, vT), p); if (gc_needed(av2,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"FlxqXn_exp, e = %ld", n); gerepileall(av2, 2, &f, &g); } } return gerepileupto(av, f); } GEN FlxqXn_expint(GEN h, long e, GEN T, ulong p) { return FlxqXn_expint_pre(h, e, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } pari-2.17.2/src/basemath/polclass.c0000644000175000017500000020764314676526175015562 0ustar billbill/* Copyright (C) 2014 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_polclass #define dbg_printf(lvl) if (DEBUGLEVEL >= (lvl) + 3) err_printf static GEN pcp_get_L(GEN G) { return gmael(G,1,1)+1; } static GEN pcp_get_n(GEN G) { return gmael(G,1,2)+1; } static GEN pcp_get_m(GEN G) { return gmael(G,1,4)+1; } static GEN pcp_get_o(GEN G) { return gmael(G,1,3)+1; } static GEN pcp_get_r(GEN G) { return gmael(G,1,5)+1; } static GEN pcp_get_orient_p(GEN G) { return gmael(G,3,1)+1; } static GEN pcp_get_orient_q(GEN G) { return gmael(G,3,2)+1; } static GEN pcp_get_orient_reps(GEN G) { return gmael(G,3,3)+1; } static long pcp_get_L0(GEN G) { return mael(G,2,1); } static long pcp_get_k(GEN G) { return mael(G,2,2); } static long pcp_get_h(GEN G) { return mael(G,4,1); } static long pcp_get_inv(GEN G) { return mael(G,4,2); } static long pcp_get_D(GEN G) { return mael(G,4,3); } static long pcp_get_D0(GEN G) { return mael(G,4,4); } static long pcp_get_u(GEN G) { return mael(G,4,5); } static GEN pcp_get_fau(GEN G) { return gel(G,5); } /* SECTION: Functions dedicated to finding a j-invariant with a given * trace. */ static void hasse_bounds(long *low, long *high, long p) { long u = usqrt(4*p); *low = p + 1 - u; *high = p + 1 + u; } /* a / b : a and b are from factoru and b must divide a exactly */ INLINE GEN famatsmall_divexact(GEN a, GEN b) { GEN a1 = gel(a,1), a2 = gel(a,2), c1, c2; GEN b1 = gel(b,1), b2 = gel(b,2); long i, j, k, la = lg(a1); c1 = cgetg(la, t_VECSMALL); c2 = cgetg(la, t_VECSMALL); for (i = j = k = 1; j < la; j++) { c1[k] = a1[j]; c2[k] = a2[j]; if (a1[j] == b1[i]) { c2[k] -= b2[i++]; if (!c2[k]) continue; } k++; } setlg(c1, k); setlg(c2, k); return mkvec2(c1,c2); } /* This is Sutherland, 2009, TestCurveOrder. * * [a4, a6] and p specify an elliptic curve over FF_p. N0,N1 are the two * possible curve orders (N0+N1 = 2p+2), and n0,n1 their factoru */ static long test_curve_order(norm_eqn_t ne, ulong a4, ulong a6, long N0, long N1, GEN n0, GEN n1, long hasse_low, long hasse_high) { pari_sp ltop = avma, av; ulong a4t, a6t, p = ne->p, pi = ne->pi, T = ne->T; long m0, m1; int swapped = 0, first = 1; if (p <= 11) { long card = (long)p + 1 - Fl_elltrace(a4, a6, p); return card == N0 || card == N1; } m0 = m1 = 1; for (av = avma;;) { long a1, x, n_s; GEN Q = random_Flj_pre(a4, a6, p, pi); if (m0 == 1) n_s = Flj_order_ufact(Q, N0, n0, a4, p, pi); else if (N0 % m0) n_s = 0; else { /* m0 | N0 */ GEN fa0 = famatsmall_divexact(n0, factoru(m0)); Q = Flj_mulu_pre(Q, m0, a4, p, pi); n_s = Flj_order_ufact(Q, N0 / m0, fa0, a4, p, pi); } if (n_s == 0) { /* If m0 divides N1 and m1 divides N0 and N0 < N1, then swap */ if (swapped || N1 % m0 || N0 % m1) return gc_long(ltop,0); swapspec(n0, n1, N0, N1); swapped = 1; continue; } m0 *= n_s; a1 = (2 * p + 2) % m1; for (x = ceildivuu(hasse_low, m0) * m0; x <= hasse_high; x += m0) if ((x % m1) == a1 && x != N0 && x != N1) break; /* every x was either N0 or N1, so we return true */ if (x > hasse_high) return gc_long(ltop,1); /* [a4, a6] is the given curve and [a4t, a6t] is its quadratic twist */ if (first) { Fl_elltwist_disc(a4, a6, T, p, &a4t, &a6t); first = 0; } lswap(a4, a4t); lswap(a6, a6t); lswap(m0, m1); set_avma(av); } } static GEN random_FleV(GEN x, GEN a6, ulong p, ulong pi) { pari_APPLY_type(t_VEC, random_Fle_pre(uel(x,i), uel(a6,i), p, pi)) } /* START Code from AVSs "torcosts.h" */ struct torctab_rec { int m; int fix2, fix3; int N; int s2_flag; int t3_flag; double rating; }; /* These costs assume p=2 mod 3, 3 mod 4 and not 1 mod N */ static struct torctab_rec torctab1[] = { { 11, 1, 1, 11, 1, 1, 0.047250 }, { 33, 1, 0, 11, 1, 2, 0.047250 }, { 22, 1, 1, 11, 3, 1, 0.055125 }, { 66, 1, 0, 11, 3, 2, 0.055125 }, { 11, 1, 0, 11, 1, 0, 0.058000 }, { 13, 1, 1, 13, 1, 1, 0.058542 }, { 39, 1, 0, 13, 1, 2, 0.058542 }, { 22, 0, 1, 11, 2, 1, 0.061333 }, { 66, 0, 0, 11, 2, 2, 0.061333 }, { 22, 1, 0, 11, 3, 0, 0.061750 }, { 14, 1, 1, 14, 3, 1, 0.062500 }, { 42, 1, 0, 14, 3, 2, 0.062500 }, { 26, 1, 1, 13, 3, 1, 0.064583 }, { 78, 1, 0, 13, 3, 2, 0.064583 }, { 28, 0, 1, 14, 4, 1, 0.065625 }, { 84, 0, 0, 14, 4, 2, 0.065625 }, { 7, 1, 1, 7, 1, 1, 0.068750 }, { 13, 1, 0, 13, 1, 0, 0.068750 }, { 21, 1, 0, 7, 1, 2, 0.068750 }, { 26, 1, 0, 13, 3, 0, 0.069583 }, { 17, 1, 1, 17, 1, 1, 0.069687 }, { 51, 1, 0, 17, 1, 2, 0.069687 }, { 11, 0, 1, 11, 0, 1, 0.072500 }, { 33, 0, 0, 11, 0, 2, 0.072500 }, { 44, 1, 0, 11, 130, 0, 0.072667 }, { 52, 0, 1, 13, 4, 1, 0.073958 }, { 156, 0, 0, 13, 4, 2, 0.073958 }, { 34, 1, 1, 17, 3, 1, 0.075313 }, { 102, 1, 0, 17, 3, 2, 0.075313 }, { 15, 1, 0, 15, 1, 0, 0.075625 }, { 13, 0, 1, 13, 0, 1, 0.076667 }, { 39, 0, 0, 13, 0, 2, 0.076667 }, { 44, 0, 0, 11, 4, 0, 0.076667 }, { 30, 1, 0, 15, 3, 0, 0.077188 }, { 22, 0, 0, 11, 2, 0, 0.077333 }, { 34, 1, 0, 17, 3, 0, 0.077969 }, { 17, 1, 0, 17, 1, 0, 0.078750 }, { 14, 0, 1, 14, 0, 1, 0.080556 }, { 28, 0, 0, 14, 4, 0, 0.080556 }, { 42, 0, 0, 14, 0, 2, 0.080556 }, { 7, 1, 0, 7, 1, 0, 0.080833 }, { 9, 1, 0, 9, 1, 0, 0.080833 }, { 68, 0, 1, 17, 4, 1, 0.081380 }, { 204, 0, 0, 17, 4, 2, 0.081380 }, { 52, 0, 0, 13, 4, 0, 0.082292 }, { 10, 1, 1, 10, 3, 1, 0.084687 }, { 17, 0, 1, 17, 0, 1, 0.084687 }, { 51, 0, 0, 17, 0, 2, 0.084687 }, { 20, 0, 1, 10, 4, 1, 0.085938 }, { 60, 0, 0, 10, 4, 2, 0.085938 }, { 19, 1, 1, 19, 1, 1, 0.086111 }, { 57, 1, 0, 19, 1, 2, 0.086111 }, { 68, 0, 0, 17, 4, 0, 0.088281 }, { 38, 1, 1, 19, 3, 1, 0.089514 }, { 114, 1, 0, 19, 3, 2, 0.089514 }, { 20, 0, 0, 10, 4, 0, 0.090625 }, { 36, 0, 0, 18, 4, 0, 0.090972 }, { 26, 0, 0, 13, 2, 0, 0.091667 }, { 11, 0, 0, 11, 0, 0, 0.092000 }, { 19, 1, 0, 19, 1, 0, 0.092778 }, { 38, 1, 0, 19, 3, 0, 0.092778 }, { 14, 1, 0, 7, 3, 0, 0.092917 }, { 18, 1, 0, 9, 3, 0, 0.092917 }, { 76, 0, 1, 19, 4, 1, 0.095255 }, { 228, 0, 0, 19, 4, 2, 0.095255 }, { 10, 0, 1, 10, 0, 1, 0.096667 }, { 13, 0, 0, 13, 0, 0, 0.096667 }, { 30, 0, 0, 10, 0, 2, 0.096667 }, { 19, 0, 1, 19, 0, 1, 0.098333 }, { 57, 0, 0, 19, 0, 2, 0.098333 }, { 17, 0, 0, 17, 0, 0, 0.100000 }, { 23, 1, 1, 23, 1, 1, 0.100227 }, { 69, 1, 0, 23, 1, 2, 0.100227 }, { 7, 0, 1, 7, 0, 1, 0.100833 }, { 21, 0, 0, 7, 0, 2, 0.100833 }, { 76, 0, 0, 19, 4, 0, 0.102083 }, { 14, 0, 0, 14, 0, 0, 0.102222 }, { 18, 0, 0, 9, 2, 0, 0.102222 }, { 5, 1, 1, 5, 1, 1, 0.103125 }, { 46, 1, 1, 23, 3, 1, 0.104318 }, { 138, 1, 0, 23, 3, 2, 0.104318 }, { 23, 1, 0, 23, 1, 0, 0.105682 }, { 46, 1, 0, 23, 3, 0, 0.106705 }, { 92, 0, 1, 23, 4, 1, 0.109091 }, { 276, 0, 0, 23, 4, 2, 0.109091 }, { 19, 0, 0, 19, 0, 0, 0.110000 }, { 23, 0, 1, 23, 0, 1, 0.112273 }, { 69, 0, 0, 23, 0, 2, 0.112273 }, { 7, 0, 0, 7, 0, 0, 0.113333 }, { 9, 0, 0, 9, 0, 0, 0.113333 }, { 92, 0, 0, 23, 4, 0, 0.113826 }, { 16, 0, 1, 16, 0, 1, 0.118125 }, { 48, 0, 0, 16, 0, 2, 0.118125 }, { 5, 1, 0, 5, 1, 0, 0.121250 }, { 15, 0, 0, 15, 0, 0, 0.121250 }, { 10, 0, 0, 10, 0, 0, 0.121667 }, { 23, 0, 0, 23, 0, 0, 0.123182 }, { 12, 0, 0, 12, 0, 0, 0.141667 }, { 5, 0, 1, 5, 0, 1, 0.145000 }, { 16, 0, 0, 16, 0, 0, 0.145000 }, { 8, 0, 1, 8, 0, 1, 0.151250 }, { 29, 1, 1, 29, 1, 1, 0.153036 }, { 87, 1, 0, 29, 1, 2, 0.153036 }, { 25, 0, 0, 25, 0, 0, 0.155000 }, { 58, 1, 1, 29, 3, 1, 0.156116 }, { 174, 1, 0, 29, 3, 2, 0.156116 }, { 29, 1, 0, 29, 1, 0, 0.157500 }, { 58, 1, 0, 29, 3, 0, 0.157500 }, { 116, 0, 1, 29, 4, 1, 0.161086 }, { 29, 0, 1, 29, 0, 1, 0.163393 }, { 87, 0, 0, 29, 0, 2, 0.163393 }, { 116, 0, 0, 29, 4, 0, 0.163690 }, { 5, 0, 0, 5, 0, 0, 0.170000 }, { 8, 0, 0, 8, 0, 0, 0.170000 }, { 29, 0, 0, 29, 0, 0, 0.171071 }, { 31, 1, 1, 31, 1, 1, 0.186583 }, { 93, 1, 0, 31, 1, 2, 0.186583 }, { 62, 1, 1, 31, 3, 1, 0.189750 }, { 186, 1, 0, 31, 3, 2, 0.189750 }, { 31, 1, 0, 31, 1, 0, 0.191333 }, { 62, 1, 0, 31, 3, 0, 0.192167 }, { 124, 0, 1, 31, 4, 1, 0.193056 }, { 31, 0, 1, 31, 0, 1, 0.195333 }, { 93, 0, 0, 31, 0, 2, 0.195333 }, { 124, 0, 0, 31, 4, 0, 0.197917 }, { 2, 1, 1, 2, 3, 1, 0.200000 }, { 6, 1, 0, 2, 3, 2, 0.200000 }, { 31, 0, 0, 31, 0, 0, 0.206667 }, { 4, 1, 1, 4, 130, 1, 0.214167 }, { 6, 0, 0, 6, 0, 0, 0.226667 }, { 3, 1, 0, 3, 1, 0, 0.230000 }, { 4, 0, 1, 4, 0, 1, 0.241667 }, { 4, 1, 0, 2, 130, 0, 0.266667 }, { 4, 0, 0, 4, 0, 0, 0.283333 }, { 3, 0, 0, 3, 0, 0, 0.340000 }, { 1, 1, 1, 1, 1, 1, 0.362500 }, { 2, 0, 1, 2, 0, 1, 0.386667 }, { 1, 1, 0, 1, 1, 0, 0.410000 }, { 2, 0, 0, 2, 0, 0, 0.453333 }, }; static struct torctab_rec torctab2[] = { { 11, 1, 1, 11, 1, 1, 0.047250 }, { 33, 1, 0, 11, 1, 2, 0.047250 }, { 22, 1, 1, 11, 3, 1, 0.055125 }, { 66, 1, 0, 11, 3, 2, 0.055125 }, { 13, 1, 1, 13, 1, 1, 0.057500 }, { 39, 1, 0, 13, 1, 2, 0.057500 }, { 11, 1, 0, 11, 1, 0, 0.058000 }, { 22, 0, 1, 11, 2, 1, 0.061333 }, { 66, 0, 0, 11, 2, 2, 0.061333 }, { 14, 1, 1, 14, 3, 1, 0.061458 }, { 42, 1, 0, 14, 3, 2, 0.061458 }, { 22, 1, 0, 11, 3, 0, 0.061750 }, { 26, 1, 1, 13, 3, 1, 0.064062 }, { 78, 1, 0, 13, 3, 2, 0.064062 }, { 28, 0, 1, 14, 4, 1, 0.065625 }, { 84, 0, 0, 14, 4, 2, 0.065625 }, { 13, 1, 0, 13, 1, 0, 0.066667 }, { 26, 1, 0, 13, 3, 0, 0.069583 }, { 17, 1, 1, 17, 1, 1, 0.069687 }, { 51, 1, 0, 17, 1, 2, 0.069687 }, { 11, 0, 1, 11, 0, 1, 0.070000 }, { 33, 0, 0, 11, 0, 2, 0.070000 }, { 7, 1, 1, 7, 1, 1, 0.070417 }, { 21, 1, 0, 7, 1, 2, 0.070417 }, { 15, 1, 0, 15, 1, 0, 0.072500 }, { 52, 0, 1, 13, 4, 1, 0.073090 }, { 156, 0, 0, 13, 4, 2, 0.073090 }, { 34, 1, 1, 17, 3, 1, 0.074219 }, { 102, 1, 0, 17, 3, 2, 0.074219 }, { 7, 1, 0, 7, 1, 0, 0.076667 }, { 13, 0, 1, 13, 0, 1, 0.076667 }, { 39, 0, 0, 13, 0, 2, 0.076667 }, { 44, 0, 0, 11, 4, 0, 0.076667 }, { 17, 1, 0, 17, 1, 0, 0.077188 }, { 22, 0, 0, 11, 2, 0, 0.077333 }, { 34, 1, 0, 17, 3, 0, 0.077969 }, { 30, 1, 0, 15, 3, 0, 0.080312 }, { 14, 0, 1, 14, 0, 1, 0.080556 }, { 28, 0, 0, 14, 4, 0, 0.080556 }, { 42, 0, 0, 14, 0, 2, 0.080556 }, { 9, 1, 0, 9, 1, 0, 0.080833 }, { 68, 0, 1, 17, 4, 1, 0.081380 }, { 204, 0, 0, 17, 4, 2, 0.081380 }, { 52, 0, 0, 13, 4, 0, 0.082292 }, { 10, 1, 1, 10, 3, 1, 0.083125 }, { 20, 0, 1, 10, 4, 1, 0.083333 }, { 60, 0, 0, 10, 4, 2, 0.083333 }, { 17, 0, 1, 17, 0, 1, 0.084687 }, { 51, 0, 0, 17, 0, 2, 0.084687 }, { 19, 1, 1, 19, 1, 1, 0.084722 }, { 57, 1, 0, 19, 1, 2, 0.084722 }, { 11, 0, 0, 11, 0, 0, 0.087000 }, { 68, 0, 0, 17, 4, 0, 0.088281 }, { 38, 1, 1, 19, 3, 1, 0.090139 }, { 114, 1, 0, 19, 3, 2, 0.090139 }, { 36, 0, 0, 18, 4, 0, 0.090972 }, { 19, 1, 0, 19, 1, 0, 0.091389 }, { 26, 0, 0, 13, 2, 0, 0.091667 }, { 13, 0, 0, 13, 0, 0, 0.092500 }, { 38, 1, 0, 19, 3, 0, 0.092778 }, { 14, 1, 0, 7, 3, 0, 0.092917 }, { 18, 1, 0, 9, 3, 0, 0.092917 }, { 20, 0, 0, 10, 4, 0, 0.095833 }, { 76, 0, 1, 19, 4, 1, 0.096412 }, { 228, 0, 0, 19, 4, 2, 0.096412 }, { 17, 0, 0, 17, 0, 0, 0.096875 }, { 19, 0, 1, 19, 0, 1, 0.098056 }, { 57, 0, 0, 19, 0, 2, 0.098056 }, { 23, 1, 1, 23, 1, 1, 0.100682 }, { 69, 1, 0, 23, 1, 2, 0.100682 }, { 7, 0, 1, 7, 0, 1, 0.100833 }, { 21, 0, 0, 7, 0, 2, 0.100833 }, { 30, 0, 0, 15, 2, 0, 0.100833 }, { 76, 0, 0, 19, 4, 0, 0.102083 }, { 14, 0, 0, 14, 0, 0, 0.102222 }, { 5, 1, 1, 5, 1, 1, 0.103125 }, { 46, 1, 1, 23, 3, 1, 0.104034 }, { 138, 1, 0, 23, 3, 2, 0.104034 }, { 23, 1, 0, 23, 1, 0, 0.104545 }, { 7, 0, 0, 7, 0, 0, 0.105000 }, { 10, 0, 1, 10, 0, 1, 0.105000 }, { 16, 0, 1, 16, 0, 1, 0.105417 }, { 48, 0, 0, 16, 0, 2, 0.105417 }, { 46, 1, 0, 23, 3, 0, 0.106705 }, { 18, 0, 0, 9, 2, 0, 0.107778 }, { 92, 0, 1, 23, 4, 1, 0.108239 }, { 276, 0, 0, 23, 4, 2, 0.108239 }, { 19, 0, 0, 19, 0, 0, 0.110000 }, { 23, 0, 1, 23, 0, 1, 0.111136 }, { 69, 0, 0, 23, 0, 2, 0.111136 }, { 9, 0, 0, 9, 0, 0, 0.113333 }, { 10, 0, 0, 10, 0, 0, 0.113333 }, { 92, 0, 0, 23, 4, 0, 0.113826 }, { 5, 1, 0, 5, 1, 0, 0.115000 }, { 15, 0, 0, 15, 0, 0, 0.115000 }, { 23, 0, 0, 23, 0, 0, 0.120909 }, { 8, 0, 1, 8, 0, 1, 0.126042 }, { 24, 0, 0, 8, 0, 2, 0.126042 }, { 16, 0, 0, 16, 0, 0, 0.127188 }, { 8, 0, 0, 8, 0, 0, 0.141667 }, { 25, 0, 1, 25, 0, 1, 0.144000 }, { 5, 0, 1, 5, 0, 1, 0.151250 }, { 12, 0, 0, 12, 0, 0, 0.152083 }, { 29, 1, 1, 29, 1, 1, 0.153929 }, { 87, 1, 0, 29, 1, 2, 0.153929 }, { 25, 0, 0, 25, 0, 0, 0.155000 }, { 58, 1, 1, 29, 3, 1, 0.155045 }, { 174, 1, 0, 29, 3, 2, 0.155045 }, { 29, 1, 0, 29, 1, 0, 0.156429 }, { 58, 1, 0, 29, 3, 0, 0.157857 }, { 116, 0, 1, 29, 4, 1, 0.158631 }, { 116, 0, 0, 29, 4, 0, 0.163542 }, { 29, 0, 1, 29, 0, 1, 0.164286 }, { 87, 0, 0, 29, 0, 2, 0.164286 }, { 29, 0, 0, 29, 0, 0, 0.169286 }, { 5, 0, 0, 5, 0, 0, 0.170000 }, { 31, 1, 1, 31, 1, 1, 0.187000 }, { 93, 1, 0, 31, 1, 2, 0.187000 }, { 62, 1, 1, 31, 3, 1, 0.188500 }, { 186, 1, 0, 31, 3, 2, 0.188500 }, { 31, 1, 0, 31, 1, 0, 0.191333 }, { 62, 1, 0, 31, 3, 0, 0.192083 }, { 124, 0, 1, 31, 4, 1, 0.193472 }, { 31, 0, 1, 31, 0, 1, 0.196167 }, { 93, 0, 0, 31, 0, 2, 0.196167 }, { 124, 0, 0, 31, 4, 0, 0.197083 }, { 2, 1, 1, 2, 3, 1, 0.200000 }, { 6, 1, 0, 2, 3, 2, 0.200000 }, { 31, 0, 0, 31, 0, 0, 0.205000 }, { 6, 0, 0, 6, 0, 0, 0.226667 }, { 3, 1, 0, 3, 1, 0, 0.230000 }, { 4, 0, 1, 4, 0, 1, 0.241667 }, { 4, 0, 0, 4, 0, 0, 0.283333 }, { 3, 0, 0, 3, 0, 0, 0.340000 }, { 1, 1, 1, 1, 1, 1, 0.362500 }, { 2, 0, 1, 2, 0, 1, 0.370000 }, { 1, 1, 0, 1, 1, 0, 0.385000 }, { 2, 0, 0, 2, 0, 0, 0.453333 }, }; static struct torctab_rec torctab3[] = { { 66, 1, 0, 11, 3, 2, 0.040406 }, { 33, 1, 0, 11, 1, 2, 0.043688 }, { 78, 1, 0, 13, 3, 2, 0.045391 }, { 132, 1, 0, 11, 130, 2, 0.046938 }, { 39, 1, 0, 13, 1, 2, 0.047656 }, { 102, 1, 0, 17, 3, 2, 0.049922 }, { 42, 1, 0, 14, 3, 2, 0.050000 }, { 51, 1, 0, 17, 1, 2, 0.051680 }, { 132, 0, 0, 11, 4, 2, 0.052188 }, { 156, 1, 0, 13, 130, 2, 0.053958 }, { 156, 0, 0, 13, 4, 2, 0.054818 }, { 84, 1, 0, 14, 130, 2, 0.055000 }, { 15, 1, 0, 15, 1, 0, 0.056719 }, { 204, 0, 0, 17, 4, 2, 0.057227 }, { 114, 1, 0, 19, 3, 2, 0.057500 }, { 11, 1, 0, 11, 1, 0, 0.058000 }, { 66, 0, 0, 11, 2, 2, 0.058000 }, { 57, 1, 0, 19, 1, 2, 0.059062 }, { 30, 1, 0, 15, 3, 0, 0.059063 }, { 84, 0, 0, 14, 4, 2, 0.060677 }, { 22, 1, 0, 11, 3, 0, 0.061750 }, { 78, 0, 0, 13, 2, 2, 0.063542 }, { 228, 0, 0, 19, 4, 2, 0.063889 }, { 21, 1, 0, 7, 1, 2, 0.065000 }, { 138, 1, 0, 23, 3, 2, 0.065028 }, { 69, 1, 0, 23, 1, 2, 0.066903 }, { 13, 1, 0, 13, 1, 0, 0.068750 }, { 102, 0, 0, 17, 2, 2, 0.068906 }, { 26, 1, 0, 13, 3, 0, 0.069583 }, { 51, 0, 0, 17, 0, 2, 0.070312 }, { 60, 1, 0, 15, 130, 0, 0.071094 }, { 276, 0, 0, 23, 4, 2, 0.071236 }, { 39, 0, 0, 13, 0, 2, 0.071250 }, { 33, 0, 0, 11, 0, 2, 0.072750 }, { 44, 1, 0, 11, 130, 0, 0.073500 }, { 60, 0, 0, 15, 4, 0, 0.073828 }, { 9, 1, 0, 9, 1, 0, 0.074097 }, { 30, 0, 0, 15, 2, 0, 0.075625 }, { 57, 0, 0, 19, 0, 2, 0.075625 }, { 7, 1, 0, 7, 1, 0, 0.076667 }, { 44, 0, 0, 11, 4, 0, 0.076667 }, { 22, 0, 0, 11, 2, 0, 0.077333 }, { 17, 1, 0, 17, 1, 0, 0.078750 }, { 34, 1, 0, 17, 3, 0, 0.078750 }, { 69, 0, 0, 23, 0, 2, 0.079943 }, { 28, 0, 0, 14, 4, 0, 0.080556 }, { 42, 0, 0, 14, 0, 2, 0.080833 }, { 52, 0, 0, 13, 4, 0, 0.082292 }, { 14, 1, 1, 14, 3, 1, 0.083333 }, { 36, 0, 0, 18, 4, 0, 0.083391 }, { 18, 1, 0, 9, 3, 0, 0.085174 }, { 68, 0, 0, 17, 4, 0, 0.089583 }, { 15, 0, 0, 15, 0, 0, 0.090938 }, { 19, 1, 0, 19, 1, 0, 0.091389 }, { 26, 0, 0, 13, 2, 0, 0.091667 }, { 11, 0, 0, 11, 0, 0, 0.092000 }, { 13, 0, 0, 13, 0, 0, 0.092500 }, { 38, 1, 0, 19, 3, 0, 0.092778 }, { 14, 1, 0, 7, 3, 0, 0.092917 }, { 18, 0, 0, 9, 2, 0, 0.093704 }, { 174, 1, 0, 29, 3, 2, 0.095826 }, { 20, 0, 0, 10, 4, 0, 0.095833 }, { 96, 1, 0, 16, 133, 2, 0.096562 }, { 21, 0, 0, 21, 0, 0, 0.096875 }, { 87, 1, 0, 29, 1, 2, 0.096964 }, { 17, 0, 0, 17, 0, 0, 0.100000 }, { 348, 0, 0, 29, 4, 2, 0.100558 }, { 76, 0, 0, 19, 4, 0, 0.100926 }, { 14, 0, 0, 14, 0, 0, 0.102222 }, { 9, 0, 0, 9, 0, 0, 0.103889 }, { 46, 1, 0, 23, 3, 0, 0.105114 }, { 23, 1, 0, 23, 1, 0, 0.105682 }, { 48, 0, 0, 16, 0, 2, 0.106406 }, { 87, 0, 0, 29, 0, 2, 0.107545 }, { 19, 0, 0, 19, 0, 0, 0.107778 }, { 7, 0, 0, 7, 0, 0, 0.113333 }, { 10, 0, 0, 10, 0, 0, 0.113333 }, { 92, 0, 0, 23, 4, 0, 0.113636 }, { 12, 0, 0, 12, 0, 0, 0.114062 }, { 5, 1, 0, 5, 1, 0, 0.115000 }, { 186, 1, 0, 31, 3, 2, 0.115344 }, { 93, 1, 0, 31, 1, 2, 0.118125 }, { 23, 0, 0, 23, 0, 0, 0.120909 }, { 93, 0, 0, 31, 0, 2, 0.128250 }, { 16, 0, 0, 16, 0, 0, 0.138750 }, { 25, 0, 0, 25, 0, 0, 0.155000 }, { 58, 1, 0, 29, 3, 0, 0.155714 }, { 29, 1, 0, 29, 1, 0, 0.158214 }, { 3, 1, 0, 3, 1, 0, 0.163125 }, { 116, 0, 0, 29, 4, 0, 0.163690 }, { 5, 0, 0, 5, 0, 0, 0.170000 }, { 6, 0, 0, 6, 0, 0, 0.170000 }, { 8, 0, 0, 8, 0, 0, 0.170000 }, { 29, 0, 0, 29, 0, 0, 0.172857 }, { 31, 1, 0, 31, 1, 0, 0.191333 }, { 62, 1, 0, 31, 3, 0, 0.191750 }, { 124, 0, 0, 31, 4, 0, 0.197917 }, { 31, 0, 0, 31, 0, 0, 0.201667 }, { 3, 0, 0, 3, 0, 0, 0.236250 }, { 4, 0, 0, 4, 0, 0, 0.262500 }, { 2, 1, 1, 2, 3, 1, 0.317187 }, { 1, 1, 0, 1, 1, 0, 0.410000 }, { 2, 0, 0, 2, 0, 0, 0.453333 }, }; static struct torctab_rec torctab4[] = { { 66, 1, 0, 11, 3, 2, 0.041344 }, { 33, 1, 0, 11, 1, 2, 0.042750 }, { 78, 1, 0, 13, 3, 2, 0.045781 }, { 39, 1, 0, 13, 1, 2, 0.046875 }, { 264, 1, 0, 11, 131, 2, 0.049043 }, { 42, 1, 0, 14, 3, 2, 0.050000 }, { 102, 1, 0, 17, 3, 2, 0.050508 }, { 51, 1, 0, 17, 1, 2, 0.051094 }, { 528, 1, 0, 11, 132, 2, 0.052891 }, { 132, 0, 0, 11, 4, 2, 0.052969 }, { 168, 1, 0, 14, 131, 2, 0.053965 }, { 156, 0, 0, 13, 4, 2, 0.054948 }, { 336, 1, 0, 14, 132, 2, 0.056120 }, { 15, 1, 0, 15, 1, 0, 0.056719 }, { 66, 0, 0, 11, 2, 2, 0.057000 }, { 114, 1, 0, 19, 3, 2, 0.057812 }, { 11, 1, 0, 11, 1, 0, 0.058000 }, { 204, 0, 0, 17, 4, 2, 0.058203 }, { 57, 1, 0, 19, 1, 2, 0.058542 }, { 84, 0, 0, 14, 4, 2, 0.059375 }, { 30, 1, 0, 15, 3, 0, 0.061406 }, { 22, 1, 0, 11, 3, 0, 0.063000 }, { 78, 0, 0, 13, 2, 2, 0.063542 }, { 138, 1, 0, 23, 3, 2, 0.064815 }, { 21, 1, 0, 7, 1, 2, 0.065000 }, { 228, 0, 0, 19, 4, 2, 0.065104 }, { 69, 1, 0, 23, 1, 2, 0.066477 }, { 13, 1, 0, 13, 1, 0, 0.068750 }, { 102, 0, 0, 17, 2, 2, 0.068906 }, { 51, 0, 0, 17, 0, 2, 0.069141 }, { 26, 1, 0, 13, 3, 0, 0.070625 }, { 276, 0, 0, 23, 4, 2, 0.071236 }, { 39, 0, 0, 13, 0, 2, 0.071250 }, { 33, 0, 0, 11, 0, 2, 0.072750 }, { 60, 0, 0, 15, 4, 0, 0.073828 }, { 9, 1, 0, 9, 1, 0, 0.074097 }, { 57, 0, 0, 19, 0, 2, 0.074583 }, { 30, 0, 0, 15, 2, 0, 0.075625 }, { 44, 0, 0, 11, 4, 0, 0.076667 }, { 17, 1, 0, 17, 1, 0, 0.077188 }, { 22, 0, 0, 11, 2, 0, 0.077333 }, { 69, 0, 0, 23, 0, 2, 0.080114 }, { 36, 0, 0, 18, 4, 0, 0.080208 }, { 34, 1, 0, 17, 3, 0, 0.080312 }, { 28, 0, 0, 14, 4, 0, 0.080556 }, { 7, 1, 0, 7, 1, 0, 0.080833 }, { 52, 0, 0, 13, 4, 0, 0.082292 }, { 42, 0, 0, 14, 0, 2, 0.082500 }, { 14, 1, 1, 14, 3, 1, 0.083333 }, { 15, 0, 0, 15, 0, 0, 0.086250 }, { 18, 1, 0, 9, 3, 0, 0.087083 }, { 26, 0, 0, 13, 2, 0, 0.088889 }, { 68, 0, 0, 17, 4, 0, 0.089583 }, { 48, 1, 0, 16, 132, 2, 0.089844 }, { 19, 1, 0, 19, 1, 0, 0.091389 }, { 11, 0, 0, 11, 0, 0, 0.092000 }, { 38, 1, 0, 19, 3, 0, 0.092917 }, { 18, 0, 0, 9, 2, 0, 0.093704 }, { 14, 1, 0, 7, 3, 0, 0.095000 }, { 96, 1, 0, 16, 133, 2, 0.095391 }, { 20, 0, 0, 10, 4, 0, 0.095833 }, { 174, 1, 0, 29, 3, 2, 0.095893 }, { 13, 0, 0, 13, 0, 0, 0.096667 }, { 17, 0, 0, 17, 0, 0, 0.096875 }, { 21, 0, 0, 21, 0, 0, 0.096875 }, { 87, 1, 0, 29, 1, 2, 0.097366 }, { 48, 0, 0, 16, 0, 2, 0.097969 }, { 24, 1, 0, 12, 131, 0, 0.098789 }, { 76, 0, 0, 19, 4, 0, 0.100926 }, { 348, 0, 0, 29, 4, 2, 0.101116 }, { 14, 0, 0, 14, 0, 0, 0.102222 }, { 9, 0, 0, 9, 0, 0, 0.103889 }, { 23, 1, 0, 23, 1, 0, 0.104545 }, { 46, 1, 0, 23, 3, 0, 0.105682 }, { 12, 0, 0, 12, 0, 0, 0.106250 }, { 87, 0, 0, 29, 0, 2, 0.108348 }, { 19, 0, 0, 19, 0, 0, 0.110000 }, { 7, 0, 0, 7, 0, 0, 0.113333 }, { 10, 0, 0, 10, 0, 0, 0.113333 }, { 92, 0, 0, 23, 4, 0, 0.113826 }, { 186, 1, 0, 31, 3, 2, 0.116094 }, { 93, 1, 0, 31, 1, 2, 0.116813 }, { 23, 0, 0, 23, 0, 0, 0.120909 }, { 5, 1, 0, 5, 1, 0, 0.121250 }, { 93, 0, 0, 31, 0, 2, 0.127625 }, { 16, 0, 0, 16, 0, 0, 0.132917 }, { 8, 0, 0, 8, 0, 0, 0.141667 }, { 25, 0, 0, 25, 0, 0, 0.152500 }, { 58, 1, 0, 29, 3, 0, 0.157946 }, { 29, 1, 0, 29, 1, 0, 0.158393 }, { 116, 0, 0, 29, 4, 0, 0.162946 }, { 3, 1, 0, 3, 1, 0, 0.163125 }, { 29, 0, 0, 29, 0, 0, 0.169286 }, { 5, 0, 0, 5, 0, 0, 0.170000 }, { 6, 0, 0, 6, 0, 0, 0.170000 }, { 31, 1, 0, 31, 1, 0, 0.191333 }, { 62, 1, 0, 31, 3, 0, 0.192083 }, { 124, 0, 0, 31, 4, 0, 0.196389 }, { 31, 0, 0, 31, 0, 0, 0.205000 }, { 3, 0, 0, 3, 0, 0, 0.255000 }, { 4, 0, 0, 4, 0, 0, 0.262500 }, { 2, 1, 1, 2, 3, 1, 0.325000 }, { 1, 1, 0, 1, 1, 0, 0.385000 }, { 2, 0, 0, 2, 0, 0, 0.420000 }, }; #define TWIST_DOUBLE_RATIO (9.0/16.0) static long torsion_constraint(struct torctab_rec *torctab, long ltorc, double tormod[], long n, long m) { long i, b = -1; double rb = -1.; for (i = 0 ; i < ltorc ; i++) { struct torctab_rec *ti = torctab + i; if ( ! (n%ti->m) && ( !ti->fix2 || (n%(2*ti->m)) ) && ( ! ti->fix3 || (n%(3*ti->m)) ) ) if ( n == m || ( ! (m%ti->m) && ( !ti->fix2 || (m%(2*ti->m)) ) && ( ! ti->fix3 || (m%(3*ti->m)) ) ) ) { double ri = ti->rating*tormod[ti->N]; if ( b < 0 || ri < rb ) { b = i; rb = ri; } } } if (b < 0) pari_err_BUG("find_rating"); return b; } /* p > 3 prime */ static void best_torsion_constraint(ulong p, long t, int *ptwist, ulong *ptor) { struct torctab_rec *torctab; double tormod[32]; long ltorc, n1, n2, b, b1, b2, b12, i; switch(p % 12) { case 11:torctab = torctab1; ltorc = numberof(torctab1); break; case 5: torctab = torctab2; ltorc = numberof(torctab2); break; case 7: torctab = torctab3; ltorc = numberof(torctab3); break; default/*1*/: torctab = torctab4; ltorc = numberof(torctab4); break; } for ( i = 0 ; i < 32 ; i++ ) tormod[i] = 1.0; if (p%5 == 1) tormod[5] = tormod[10] = tormod[15] = 6.0/5.0; if (p%7 == 1) tormod[7] = tormod[14] = 8.0/7.0; if (p%11 == 1) tormod[11] = 12.0/11.0; if (p%13 == 1) tormod[13] = 14.0/13.0; if (p%17 == 1) tormod[17] = 18.0/17.0; if (p%19 == 1) tormod[19] = 20.0/19.0; if (p%23 == 1) tormod[23] = 24.0/23.0; if (p%29 == 1) tormod[29] = 30.0/29.0; if (p%31 == 1) tormod[31] = 32.0/31.0; n1 = p+1-t; n2 = p+1+t; b1 = torsion_constraint(torctab, ltorc, tormod, n1, n1); b2 = torsion_constraint(torctab, ltorc, tormod, n2, n2); b12 = torsion_constraint(torctab, ltorc, tormod, n1, n2); if (b1 > b2) { if (torctab[b2].rating / TWIST_DOUBLE_RATIO > torctab[b12].rating) *ptwist = 3; else *ptwist = 2; } else if (torctab[b1].rating / TWIST_DOUBLE_RATIO > torctab[b12].rating) *ptwist = 3; else *ptwist = 1; b = *ptwist ==1 ? b1: *ptwist ==2 ? b2: b12; *ptor = torctab[b].N; } /* This is Sutherland 2009 Algorithm 1.1 */ static long find_j_inv_with_given_trace( ulong *j_t, norm_eqn_t ne, long rho_inv, long max_curves) { pari_sp ltop = avma, av; long tested = 0, t = ne->t, batch_size, N0, N1, hasse_low, hasse_high, i; GEN n0, n1, A4, A6, tx, ty; ulong p = ne->p, pi = ne->pi, p1 = p + 1, a4, a6, m, N; int twist; if (p == 2 || p == 3) { if (t == 0) pari_err_BUG("find_j_inv_with_given_trace"); *j_t = t; return 1; } N0 = (long)p1 - t; n0 = factoru(N0); N1 = (long)p1 + t; n1 = factoru(N1); best_torsion_constraint(p, t, &twist, &m); switch(twist) { case 1: N = N0; break; case 2: N = N1; break; default: N = p1; } /* Select batch size so that we have roughly a 50% chance of finding * a good curve in a batch. */ batch_size = 1.0 + rho_inv / (2.0 * m); A4 = cgetg(batch_size + 1, t_VECSMALL); A6 = cgetg(batch_size + 1, t_VECSMALL); tx = cgetg(batch_size + 1, t_VECSMALL); ty = cgetg(batch_size + 1, t_VECSMALL); dbg_printf(2)(" Selected torsion constraint m = %lu and batch " "size = %ld\n", m, batch_size); hasse_bounds(&hasse_low, &hasse_high, p); av = avma; while (max_curves <= 0 || tested < max_curves) { GEN Pp1, Pt; random_curves_with_m_torsion((ulong *)(A4 + 1), (ulong *)(A6 + 1), (ulong *)(tx + 1), (ulong *)(ty + 1), batch_size, m, p, pi); Pp1 = random_FleV(A4, A6, p, pi); Pt = gcopy(Pp1); FleV_mulu_pre_inplace(Pp1, N, A4, p, pi); if (twist >= 3) FleV_mulu_pre_inplace(Pt, t, A4, p, pi); for (i = 1; i <= batch_size; ++i) { ++tested; a4 = A4[i]; a6 = A6[i]; if (a4 == 0 || a6 == 0) continue; if (( (twist >= 3 && mael(Pp1,i,1) == mael(Pt,i,1)) || (twist < 3 && umael(Pp1,i,1) == p)) && test_curve_order(ne, a4, a6, N0,N1, n0,n1, hasse_low,hasse_high)) { *j_t = Fl_ellj_pre(a4, a6, p, pi); return gc_long(ltop, tested); } } set_avma(av); } return gc_long(ltop, tested); } /* SECTION: Functions for dealing with polycyclic presentations. */ static GEN next_generator(GEN DD, long D, ulong u, long filter, GEN *genred, long *P) { pari_sp av = avma; ulong p = (ulong)*P; while (1) { p = unextprime(p + 1); if (p > LONG_MAX) pari_err_BUG("next_generator"); if (kross(D, (long)p) != -1 && u % p != 0 && filter % p != 0) { GEN gen = primeform_u(DD, p); /* If gen is in the principal class, skip it */ *genred = qfbred_i(gen); if (!equali1(gel(*genred,1))) { *P = (long)p; return gen; } set_avma(av); } } } INLINE long * evec_ri_mutate(long r[], long i) { return r + (i * (i - 1) >> 1); } INLINE const long * evec_ri(const long r[], long i) { return r + (i * (i - 1) >> 1); } /* Reduces evec e so that e[i] < n[i] (assume e[i] >= 0) using pcp(n,r,k). * No check for overflow, this could be an issue for large groups */ INLINE void evec_reduce(long e[], const long n[], const long r[], long k) { long i, j, q; const long *ri; if (!k) return; for (i = k - 1; i > 0; i--) { if (e[i] >= n[i]) { q = e[i] / n[i]; ri = evec_ri(r, i); for (j = 0; j < i; j++) e[j] += q * ri[j]; e[i] -= q * n[i]; } } e[0] %= n[0]; } /* Computes e3 = log(a^e1*a^e2) in terms of the given polycyclic * presentation (here a denotes the implicit vector of generators) */ INLINE void evec_compose(long e3[], const long e1[], const long e2[], const long n[],const long r[], long k) { long i; for (i = 0; i < k; i++) e3[i] = e1[i] + e2[i]; evec_reduce(e3, n, r, k); } /* Converts an evec to an integer index corresponding to the * multi-radix representation of the evec with moduli corresponding to * the subgroup orders m[i] */ INLINE long evec_to_index(const long e[], const long m[], long k) { long i, index = e[0]; for (i = 1; i < k; i++) index += e[i] * m[i - 1]; return index; } INLINE void evec_copy(long f[], const long e[], long k) { long i; for (i = 0; i < k; ++i) f[i] = e[i]; } INLINE void evec_clear(long e[], long k) { long i; for (i = 0; i < k; ++i) e[i] = 0; } /* e1 and e2 may overlap */ /* Note that this function is not very efficient because it does not know the * orders of the elements in the presentation, only the relative orders */ INLINE void evec_inverse(long e2[], const long e1[], const long n[], const long r[], long k) { pari_sp av = avma; long i, *e3, *e4; e3 = new_chunk(k); e4 = new_chunk(k); evec_clear(e4, k); evec_copy(e3, e1, k); /* We have e1 + e4 = e3 which we maintain throughout while making e1 * the zero vector */ for (i = k - 1; i >= 0; i--) if (e3[i]) { e4[i] += n[i] - e3[i]; evec_reduce(e4, n, r, k); e3[i] = n[i]; evec_reduce(e3, n, r, k); } evec_copy(e2, e4, k); set_avma(av); } /* e1 and e2 may overlap */ /* This is a faster way to compute inverses, if the presentation * element orders are known (these are specified in the array o, the * array n holds the relative orders) */ INLINE void evec_inverse_o( long e2[], const long e1[], const long n[], const long o[], const long r[], long k) { long j; for (j = 0; j < k; j++) e2[j] = (e1[j] ? o[j] - e1[j] : 0); evec_reduce(e2, n, r, k); } /* Computes the order of the group element a^e using the pcp (n,r,k) */ INLINE long evec_order(const long e[], const long n[], const long r[], long k) { pari_sp av = avma; long *f = new_chunk(k); long i, j, o, m; evec_copy(f, e, k); for (o = 1, i = k - 1; i >= 0; i--) if (f[i]) { m = n[i] / ugcd(f[i], n[i]); for (j = 0; j < k; j++) f[j] *= m; evec_reduce(f, n, r, k); o *= m; } return gc_long(av,o); } /* Computes orders o[] for each generator using relative orders n[] * and power relations r[] */ INLINE void evec_orders(long o[], const long n[], const long r[], long k) { pari_sp av = avma; long i, *e = new_chunk(k); evec_clear(e, k); for (i = 0; i < k; i++) { e[i] = 1; if (i) e[i - 1] = 0; o[i] = evec_order(e, n, r, k); } set_avma(av); } INLINE int evec_equal(const long e1[], const long e2[], long k) { long j; for (j = 0; j < k; ++j) if (e1[j] != e2[j]) break; return j == k; } INLINE void index_to_evec(long e[], long index, const long m[], long k) { long i; for (i = k - 1; i > 0; --i) { e[i] = index / m[i - 1]; index -= e[i] * m[i - 1]; } e[0] = index; } INLINE void evec_n_to_m(long m[], const long n[], long k) { long i; m[0] = n[0]; for (i = 1; i < k; ++i) m[i] = m[i - 1] * n[i]; } /* Based on logfac() in Sutherland's classpoly package. * Ramanujan approximation to log(n!), accurate to O(1/n^3) */ INLINE double logfac(long n) { const double HALFLOGPI = 0.57236494292470008707171367567653; return n * log((double) n) - (double) n + log((double) n * (1.0 + 4.0 * n * (1.0 + 2.0 * n))) / 6.0 + HALFLOGPI; } /* This is based on Sutherland 2009, Lemma 8 (p31). */ static double upper_bound_on_classpoly_coeffs(long D, long h, GEN qfinorms) { double B, logbinom, lnMk, lnMh = 0, C = 2114.567, t = M_PI * sqrt((double)-D); ulong maxak = 0; long k, m; for (k = 1, B = 0.0; k <= h; ++k) { ulong ak = uel(qfinorms, k); double tk = t / ak; lnMk = tk + log(1.0 + C * exp(-tk)); B += lnMk; if (ak > maxak) { maxak = ak; lnMh = lnMk; } } m = floor((h + 1)/(exp(lnMh) + 1.0)); /* log(binom(h, m)); 0 unless D <= -1579751 */ logbinom = (m > 0 && m < h)? logfac(h) - logfac(m) - logfac(h - m): 0; return (B + logbinom - m * lnMh) * (1 / M_LN2) + 2.0; } INLINE long distinct_inverses(const long f[], const long ef[], const long ei[], const long n[], const long o[], const long r[], long k, long L0, long i) { pari_sp av = avma; long j, *e2, *e3; if ( ! ef[i] || (L0 && ef[0])) return 0; for (j = i + 1; j < k; ++j) if (ef[j]) break; if (j < k) return 0; e2 = new_chunk(k); evec_copy(e2, ef, i); e2[i] = o[i] - ef[i]; for (j = i + 1; j < k; ++j) e2[j] = 0; evec_reduce(e2, n, r, k); if (evec_equal(ef, e2, k)) return gc_long(av,0); e3 = new_chunk(k); evec_inverse_o(e3, ef, n, o, r, k); if (evec_equal(e2, e3, k)) return gc_long(av,0); if (f) { evec_compose(e3, f, ei, n, r, k); if (evec_equal(e2, e3, k)) return gc_long(av,0); evec_inverse_o(e3, e3, n, o, r, k); if (evec_equal(e2, e3, k)) return gc_long(av,0); } return gc_long(av,1); } INLINE long next_prime_evec(long *qq, long f[], const long m[], long k, hashtable *tbl, long D, GEN DD, long u, long lvl, long ubound) { pari_sp av = avma; hashentry *he; GEN P; long idx, q = *qq; do q = unextprime(q + 1); while (!(u % q) || kross(D, q) == -1 || !(lvl % q) || !(D % (q * q))); if (q > ubound) return 0; *qq = q; /* Get evec f corresponding to q */ P = qfbred_i(primeform_u(DD, q)); he = hash_search(tbl, P); if (!he) pari_err_BUG("next_prime_evec"); idx = (long)he->val; index_to_evec(f, idx, m, k); return gc_long(av,1); } /* Return 1 on success, 0 on failure. */ static int orient_pcp(GEN G, long *ni, long D, long u, hashtable *tbl) { pari_sp av = avma; /* 199 seems to suffice, but can be increased if necessary */ enum { MAX_ORIENT_P = 199 }; const long *L = pcp_get_L(G), *n = pcp_get_n(G), *r = pcp_get_r(G), *m = pcp_get_m(G), *o = pcp_get_o(G); long i, *ps = pcp_get_orient_p(G), *qs = pcp_get_orient_q(G), *reps = pcp_get_orient_reps(G); long *ef, *e, *ei, *f, k = pcp_get_k(G), lvl = modinv_level(pcp_get_inv(G)); GEN DD = stoi(D); long L0 = pcp_get_L0(G); memset(ps, 0, k * sizeof(long)); memset(qs, 0, k * sizeof(long)); memset(reps, 0, k * k * sizeof(long)); for (i = 0; i < k; ++i) { ps[i] = -1; if (o[i] > 2) break; } for (++i; i < k; ++i) ps[i] = (o[i] > 2) ? 0 : -1; /* ps[i] = -!(o[i] > 2); */ e = new_chunk(k); ei = new_chunk(k); f = new_chunk(k); for (i = 0; i < k; ++i) { long p; if (ps[i]) continue; p = L[i]; ef = &reps[i * k]; while (!ps[i]) { if (!next_prime_evec(&p, ef, m, k, tbl, D, DD, u, lvl, MAX_ORIENT_P)) break; evec_inverse_o(ei, ef, n, o, r, k); if (!distinct_inverses(NULL, ef, ei, n, o, r, k, L0, i)) continue; ps[i] = p; qs[i] = 1; } if (ps[i]) continue; p = unextprime(L[i] + 1); while (!ps[i]) { long q; if (!next_prime_evec(&p, e, m, k, tbl, D, DD, u, lvl, MAX_ORIENT_P)) break; evec_inverse_o(ei, e, n, o, r, k); q = L[i]; while (!qs[i]) { if (!next_prime_evec(&q, f, m, k, tbl, D, DD, u, lvl, p - 1)) break; evec_compose(ef, e, f, n, r, k); if (!distinct_inverses(f, ef, ei, n, o, r, k, L0, i)) continue; ps[i] = p; qs[i] = q; } } if (!ps[i]) return 0; } if (ni) { GEN N = qfb_nform(D, *ni); hashentry *he = hash_search(tbl, N); if (!he) pari_err_BUG("orient_pcp"); *ni = (long)he->val; } return gc_bool(av,1); } /* We must avoid situations where L_i^{+/-2} = L_j^2 (or = L_0*L_j^2 * if ell0 flag is set), with |L_i| = |L_j| = 4 (or have 4th powers in * but not 2nd powers in ) and j < i */ /* These cases cause problems when enumerating roots via gcds */ /* returns the index of the first bad generator, or -1 if no bad * generators are found */ static long classgp_pcp_check_generators(const long *n, long *r, long k, long L0) { pari_sp av = avma; long *e1, i, i0, j, s; const long *ei; s = !!L0; e1 = new_chunk(k); for (i = s + 1; i < k; i++) { if (n[i] != 2) continue; ei = evec_ri(r, i); for (j = s; j < i; j++) if (ei[j]) break; if (j == i) continue; for (i0 = s; i0 < i; i0++) { if ((4 % n[i0])) continue; evec_clear(e1, k); e1[i0] = 4; evec_reduce(e1, n, r, k); for (j = s; j < i; j++) if (e1[j]) break; if (j < i) continue; /* L_i0^4 is not trivial or in */ evec_clear(e1, k); e1[i0] = 2; evec_reduce(e1, n, r, k); /* compute L_i0^2 */ for (j = s; j < i; j++) if (e1[j] != ei[j]) break; if (j == i) return i; evec_inverse(e1, e1, n, r, k); /* compute L_i0^{-2} */ for (j = s; j < i; j++) if (e1[j] != ei[j]) break; if (j == i) return i; } } return gc_long(av,-1); } /* This is Sutherland 2009, Algorithm 2.2 (p16). */ static GEN classgp_make_pcp(double *height, long *ni, long h, long D, long D0, ulong u, GEN Pu, GEN Eu, long inv, long Lfilter, long orient) { const long MAX_GENS = 16, lvl = modinv_level(inv); pari_sp av, av2; long curr_p, nelts, L0, enum_cnt, GLfilter, i, k, L1, L2; GEN G, DD, ident, T, v, L, m, n, o, r, orient_p, orient_q, orient_reps; hashtable *tbl; L = zero_zv(MAX_GENS); m = zero_zv(MAX_GENS); n = zero_zv(MAX_GENS); o = zero_zv(MAX_GENS); r = zero_zv(MAX_GENS * (MAX_GENS-1) / 2); orient_p = zero_zv(MAX_GENS); orient_q = zero_zv(MAX_GENS); orient_reps = zero_zv(MAX_GENS*MAX_GENS); G = mkvec5(mkvec5(L, n, o, m, r), mkvecsmall3(0, 0, 0), mkvec3(orient_p, orient_q, orient_reps), mkvecsmall5(h, inv, D, D0, u), mkmat2(Pu, Eu)); av = avma; if (h == 1) { *height = upper_bound_on_classpoly_coeffs(D, h, mkvecsmall(1)); return gc_const(av, G); /* no need to set *ni when h = 1 */ } if (!modinv_is_double_eta(inv) || !modinv_ramified(D, inv, &L0)) L0 = 0; enum_cnt = h / (1 + !!L0); GLfilter = ulcm(Lfilter, lvl); DD = stoi(D); av2 = avma; while (1) { k = 0; /* Hash table has an imaginary QFB as a key and the index of that * form in T as its value */ tbl = hash_create(h, (ulong(*)(void*)) hash_GEN, (int(*)(void*,void*))&gidentical, 1); ident = primeform(DD, gen_1); hash_insert(tbl, ident, (void*)0); T = vectrunc_init(h + 1); vectrunc_append(T, ident); nelts = 1; curr_p = 1; while (nelts < h) { GEN gamma_i = NULL, beta; hashentry *e; long N = lg(T)-1, ri = 1; if (k == MAX_GENS) pari_err_IMPL("classgp_pcp"); if (nelts == 1 && L0) { curr_p = L0; gamma_i = qfb_nform(D, curr_p); beta = qfbred_i(gamma_i); if (equali1(gel(beta, 1))) { curr_p = 1; gamma_i = NULL; } } if (!gamma_i) gamma_i = next_generator(DD, D, u, GLfilter, &beta, &curr_p); while ((e = hash_search(tbl, beta)) == NULL) { long j; for (j = 1; j <= N; ++j) { GEN t = qfbcomp_i(beta, gel(T, j)); vectrunc_append(T, t); hash_insert(tbl, t, (void*)tbl->nb); } beta = qfbcomp_i(beta, gamma_i); ++ri; } if (ri > 1) { long j, si; L[k+1] = curr_p; n[k+1] = ri; nelts *= ri; /* This is to reset the curr_p counter when we have L0 != 0 * in the first position of L. */ if (curr_p == L0) curr_p = 1; N = 1; si = (long)e->val; for (j = 1; j <= k; ++j) { evec_ri_mutate(r, k)[j] = (si / N) % n[j]; N *= n[j]; } ++k; } } if ((i = classgp_pcp_check_generators(n+1, r+1, k, L0)) < 0) { mael(G,2,1) = L0; mael(G,2,2) = k; mael(G,2,3) = enum_cnt; evec_orders(o+1, n+1, r+1, k); evec_n_to_m(m+1, n+1, k); if (!orient || orient_pcp(G, ni, D, u, tbl)) break; GLfilter *= L[1]; } else { GLfilter = umuluu_or_0(GLfilter, L[i+1]); if (!GLfilter) pari_err_IMPL("classgp_pcp"); } set_avma(av2); } v = cgetg(h + 1, t_VECSMALL); v[1] = 1; for (i = 2; i <= h; ++i) uel(v,i) = itou(gmael(T,i,1)); *height = upper_bound_on_classpoly_coeffs(D, enum_cnt, v); /* The norms of the last one or two generators. */ L1 = L[k]; L2 = k > 1 ? L[k - 1] : 1; /* 4 * L1^2 * L2^2 must fit in a ulong */ if (2 * (1 + log2(L1) + log2(L2)) >= BITS_IN_LONG) pari_err_IMPL("classgp_pcp"); if (L0 && (L[1] != L0 || o[1] != 2)) pari_err_BUG("classgp_pcp"); return gc_const(av, G); } /* SECTION: Functions for calculating class polynomials. */ static const long SMALL_PRIMES[11] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 }; /* Encodes prime divisors of smooth integers <= 1200 P = primes(11); V = vector(31, i, vecsearch(P, i)); vfactor(v) = { if (v == 1, return (0)); my(q = factor(v)[,1]); if (vecmax(q) > 31, return (-1)); \\ not smooth sum(i = 1, #P, 1 << (V[q[i]]-1)); } vector(1200, v, vfactor(v)) */ static const long SMOOTH_INTS[] = { -1, /* 0 */ 0,1,2,1,4,3,8,1,2,5,16,3,32,9,6,1,64,3,128,5,10,17,256,3,4,33,2,9,512,7,1024,1, 18,65,12,3,-1,129,34,5,-1,11,-1,17,6,257,-1,3,8,5,66,33,-1,3,20,9,130,513,-1,7, -1,1025,10,1,36,19,-1,65,258,13,-1,3,-1,-1,6,129,24,35,-1,5,2,-1,-1,11,68,-1, 514,17,-1,7,40,257,1026,-1,132,3,-1,9,18,5,-1,67,-1,33,14,-1,-1,3,-1,21,-1,9,-1, 131,260,513,34,-1,72,7,16,-1,-1,1025,4,11,-1,1,-1,37,-1,19,136,-1,6,65,-1,259, -1,13,-1,-1,48,3,516,-1,10,-1,-1,7,-1,129,66,25,1028,35,-1,-1,-1,5,264,3,-1,-1, 22,-1,-1,11,32,69,130,-1,-1,515,12,17,-1,-1,-1,7,-1,41,-1,257,-1,1027,80,-1,10, 133,-1,3,-1,-1,38,9,-1,19,-1,5,-1,-1,520,67,-1,-1,258,33,144,15,-1,-1,-1,-1,-1, 3,1032,-1,-1,21,96,-1,-1,9,6,-1,-1,131,-1,261,26,513,-1,35,-1,-1,-1,73,-1,7,-1, 17,2,-1,12,-1,160,1025,-1,5,-1,11,272,-1,70,1,-1,-1,-1,37,514,-1,-1,19,-1,137, -1,-1,-1,7,-1,65,42,-1,20,259,-1,-1,1026,13,-1,-1,-1,-1,134,49,-1,3,64,517,-1, -1,-1,11,-1,-1,18,-1,288,7,-1,-1,-1,129,-1,67,-1,25,-1,1029,-1,35,-1,-1,14,-1, -1,-1,528,5,-1,265,192,3,36,-1,-1,-1,-1,23,-1,-1,-1,-1,-1,11,-1,33,-1,69,1040, 131,8,-1,262,-1,-1,515,-1,13,34,17,-1,-1,-1,-1,74,-1,-1,7,128,-1,18,41,-1,-1,-1, 257,-1,-1,-1,1027,-1,81,6,-1,544,11,-1,133,-1,-1,-1,3,28,-1,-1,-1,-1,39,320,9, -1,-1,-1,19,-1,-1,138,5,-1,-1,1056,-1,6,521,-1,67,-1,-1,-1,-1,-1,259,-1,33,-1, 145,-1,15,-1,-1,-1,-1,68,-1,-1,-1,50,-1,-1,3,-1,1033,518,-1,384,-1,-1,21,10,97, -1,-1,-1,-1,-1,9,-1,7,-1,-1,-1,-1,44,131,-1,-1,66,261,-1,27,-1,513,1030,-1,-1, 35,-1,-1,-1,-1,-1,-1,132,73,-1,-1,-1,7,-1,-1,266,17,-1,3,-1,-1,-1,13,-1,-1,576, 161,22,1025,-1,-1,-1,5,-1,-1,-1,11,-1,273,34,-1,-1,71,-1,1,130,-1,-1,-1,-1,-1, -1,37,-1,515,-1,-1,14,-1,1088,19,256,-1,-1,137,-1,-1,-1,-1,-1,-1,24,7,-1,-1,-1, 65,-1,43,-1,-1,-1,21,640,259,-1,-1,-1,-1,-1,1027,-1,13,82,-1,-1,-1,-1,-1,10,-1, -1,135,-1,49,-1,-1,260,3,-1,65,-1,517,-1,-1,-1,-1,38,-1,-1,11,1152,-1,-1,-1,-1, 19,76,-1,-1,289,-1,7,-1,-1,-1,-1,20,-1,-1,129,522,-1,-1,67,-1,-1,-1,25,-1,-1,-1, 1029,258,-1,-1,35,4,-1,146,-1,-1,15,-1,-1,-1,-1,-1,-1,40,529,-1,5,-1,-1,-1,265, -1,193,-1,3,-1,37,1034,-1,-1,-1,-1,-1,-1,-1,-1,23,-1,-1,98,-1,140,-1,768,-1,-1, -1,-1,11,-1,-1,6,33,-1,-1,-1,69,-1,1041,-1,131,-1,9,-1,-1,-1,263,-1,-1,26,-1,-1, 515,-1,-1,-1,13,-1,35,-1,17,-1,-1,-1,-1,-1,-1,-1,-1,1280,75,52,-1,-1,-1,-1,7,-1, 129,-1,-1,516,19,-1,41,2,-1,-1,-1,-1,-1,14,257,-1,-1,-1,-1,162,-1,-1,1027,-1,-1, -1,81,-1,7,-1,-1,-1,545,-1,11,-1,-1,274,133,-1,-1,-1,-1,70,-1,-1,3,-1,29,-1,-1, -1,-1,1028,-1,-1,-1,-1,39,-1,321,514,9,-1,-1,-1,-1,-1,-1,-1,19,-1,-1,-1,-1,-1, 139,-1,5,-1,-1,-1,-1,268,1057,-1,-1,-1,7,-1,521,-1,-1,-1,67,-1,-1,42,-1,-1,-1, -1,-1,22,-1,-1,259,-1,-1,-1,33,72,-1,-1,145,1026,-1,-1,15,512,-1,-1,-1,36,-1,24, -1,-1,69,-1,-1,-1,-1,134,-1,-1,51,-1,-1,-1,-1,-1,3,-1,-1,66,1033,-1,519,-1,-1, -1,385,12,-1,-1,-1,-1,21,-1,11,-1,97,-1,-1,-1,-1,-1,-1,18,-1,-1,-1,-1,9,290,-1, 1536,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,45,-1,131,-1,-1,-1,-1,-1,67,-1,261,-1,-1,-1, 27,-1,-1,-1,513,-1,1031,136,-1,-1,-1,84,35,-1,-1,-1,-1,-1,-1,-1,-1,14,-1,-1,-1, -1,133,-1,73,-1,-1,-1,-1,530,-1,-1,7,1024,-1,-1,-1,-1,267,-1,17,194,-1,-1,3,-1, -1,38,-1,-1,-1,-1,13,-1,-1,-1,-1,-1,577,-1,161,-1,23,-1,1025,-1,-1,-1,-1,-1,-1, -1,5,56,-1,-1,-1,-1,-1,-1,11,-1,-1,-1,273,-1,35,524,-1,-1,-1,-1,71,-1,-1,1042,1, -1,131,-1,-1,10,-1,-1,-1,-1,-1,262,-1,-1,-1,-1,37,-1,-1,-1,515,148,-1,-1,-1,-1, 15,-1,-1,34,1089,-1,19,-1,257,-1,-1,-1,-1,-1,137,-1,-1,-1,-1,-1,-1,74,-1,-1,-1, -1,-1,-1,25,-1,7,-1,-1,130,-1,1036,-1,-1,65,18,-1,-1,43,-1,-1,-1,-1,-1,-1,-1,21, -1,641,-1,259,100,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1027,-1,-1,-1,13,-1,83,-1,-1,6, -1,264,-1,-1,-1,546,-1,-1,11,-1,-1,-1,-1,-1,135,-1,-1,-1,49,-1,-1,-1,-1,-1,261, -1,3,-1,-1,30,65,-1,-1,-1,517,-1,-1,-1,-1,-1,-1,-1,-1,-1,39,-1,-1,322,-1,-1,11, -1,1153,-1,-1,-1,-1,40,-1,-1,-1,-1,19,-1,77,-1,-1,-1,-1,-1,289,138,-1,-1,7 }; /* Upper bound for H(v^2 d) / H(d) = \prod_{p | v} (p + 1) / (p - 1) * We actually store ceil(128 * bound) P = primes(11); V = vector(31, i, vecsearch(P, i)); hbound(v) = { my(q = factor(v)[,1]); if (q && vecmax(q) > 31, return (0)); ceil(prod(i = 1, #q, (q[i] + 1)/(q[i] - 1), 1.) * 128); } vector(1200, v, hbound(v)) */ static const long HURWITZ_RATIO[] = { 128,384,256,384,192,768,171,384,256,576,154,768,150,512,384, 384,144,768,143,576,342,461,140,768,192,448,256,512,138,1152, 137,384,308,432,256,768,0,427,299,576,0,1024,0,461,384,419,0, 768,171,576,288,448,0,768,231,512,285,412,0,1152,0,410,342, 384,224,922,0,432,280,768,0,768,0,0,384,427,205,896,0,576, 256,0,0,1024,216,0,275,461,0,1152,200,419,274,0,214,768,0, 512,308,576,0,864,0,448,512,0,0,768,0,692,0,512,0,854,210, 412,299,0,192,1152,154,0,0,410,192,1024,0,384,0,672,0,922, 190,0,384,432,0,838,0,768,0,0,180,768,206,0,342,0,0,1152,0, 427,288,615,205,896,0,0,0,576,187,768,0,0,461,0,0,1024,150, 648,285,0,0,823,256,461,0,0,0,1152,0,598,0,419,0,820,173,0, 342,640,0,768,0,0,448,512,0,922,0,576,0,0,183,864,0,0,280, 448,171,1536,0,0,0,0,0,768,183,0,0,692,168,0,0,512,384,0, 0,854,0,629,410,412,0,896,0,0,0,576,0,1152,0,461,256,0,256, 0,166,410,0,576,0,1024,168,0,432,384,0,0,0,672,275,0,0,922, 0,569,0,0,0,1152,0,432,399,0,231,838,0,0,274,768,0,0,0,0, 427,538,0,768,144,618,0,0,0,1024,0,0,308,0,163,1152,0,0,0, 427,0,864,0,615,0,615,0,896,0,0,512,0,0,0,165,576,0,559, 160,768,224,0,0,0,0,1383,0,0,0,0,0,1024,0,448,0,648,164, 854,171,0,419,0,0,823,0,768,299,461,0,0,0,0,384,0,0,1152, 143,0,308,598,0,0,0,419,0,0,0,820,0,519,384,0,160,1024,0, 640,0,0,0,768,308,0,0,0,0,1344,158,512,0,0,0,922,0,0,380, 576,0,0,160,0,384,549,0,864,0,0,0,0,0,838,0,448,0,512,0, 1536,0,0,0,0,216,0,0,0,359,0,0,768,0,547,412,0,156,0,0, 692,342,504,0,0,0,0,0,512,0,1152,0,0,0,0,299,854,0,0,288, 629,0,1229,0,412,410,0,0,896,0,0,0,0,0,0,214,576,0,0,0, 1152,0,0,373,461,0,768,0,0,0,768,0,0,155,498,461,410,0,0, 0,576,0,0,0,1024,0,503,299,0,0,1296,0,384,285,0,0,0,0,0, 0,672,0,823,0,0,512,0,154,922,140,0,0,569,0,0,0,0,0,0, 205,1152,0,0,0,432,0,1195,0,0,0,692,153,838,0,0,0,0,0,820, 0,768,346,0,0,0,0,0,342,0,0,1280,0,538,0,0,210,768,0,432, 0,618,0,0,0,0,448,0,0,1024,152,0,0,0,0,922,288,0,0,489,0, 1152,0,0,0,0,231,0,0,427,366,0,0,864,0,0,0,615,0,0,0,615, 280,0,0,896,192,0,342,0,0,1536,0,0,0,0,0,0,200,494,0,576, 0,0,0,559,0,480,0,768,0,672,365,0,0,0,0,0,0,0,0,1383,0, 0,336,0,285,0,150,0,0,0,0,1024,0,0,384,448,0,0,0,648,0, 492,0,854,0,512,0,0,0,1257,0,0,410,0,0,823,0,0,0,768,0, 896,0,461,0,0,0,0,0,0,0,0,149,1152,269,0,0,0,0,1152,0, 427,0,0,206,922,0,598,256,0,0,0,0,0,512,419,0,0,0,0,332, 0,0,820,0,0,0,519,0,1152,0,0,0,480,0,1024,0,0,336,640,0, 0,0,0,432,0,0,768,0,922,0,0,0,0,205,0,0,0,0,1344,0,472, 275,512,0,0,0,0,0,0,0,922,0,0,0,0,0,1138,0,576,0,0,0,0, 280,478,0,0,0,1152,0,549,0,0,0,864,0,0,399,0,0,0,0,0,461, 0,0,838,0,0,0,448,192,0,0,512,274,0,0,1536,138,0,0,0,224, 0,205,0,0,648,0,0,0,0,427,0,0,1076,0,0,0,0,0,768,0,0, 288,547,0,1235,0,0,0,466,256,0,0,0,0,692,0,1024,0,504,0,0, 0,0,0,0,308,0,0,0,0,512,326,0,147,1152,0,0,0,0,0,0,0,0, 0,896,0,854,0,0,0,0,0,864,0,629,0,0,0,1229,0,0,0,412,0, 1229,190,0,0,0,260,896,0,0,0,0,0,0,0,0,512,0,0,0,0,640, 0,576,0,0,0,0,330,0,0,1152,137,0,0,0,0,1118,0,461,320,0, 0,768,0,0,448,0,0,0,0,768,0,0,0,0,0,463,0,498,0,1383,0, 410,0,0,0,0,0,0,0,576,239,0,0,0,0,0,0,1024,0,0,0,503,0, 896,275,0,0,0,0,1296,0,0,328,384,0,854,0,0,342,0,0,0,0,0, 419,0,0,0,0,672,0,0,0,823,256,0,0,0,0,1536,0,0,299,461,0, 922,0,419,0,0,0,0,0,569,0,0,0,0,0,0,384,0,0,0,0,0,0, 615,0,1152,0,0,285,0,274,0,0,432,308,0,0,1195,0,0,0,0,0, 0,0,692,0,458,0,838,252,0,0,0,0,0,0,0,0,0,0,820,0,0,0, 768,0,1037,0,0,384,0,187,0,0,0,320,0,0,1024,0,0,0,0,0, 1280,0,0,0,538,0,0,0,0,0,629,0,768,0,0,615,432,0,0,0,618, 0,0,0,0,0,0,0,0,0,1344,0,0,315,0,0,1024,0,456,0,0,0,0, 200,0,0,0,0,922,0,864,0,0,0,0,0,489,380,0,0,1152 }; /* Hurwitz class number of Df^2, D < 0; h = classno(D), Faf = factoru(f) */ static double hclassno_wrapper(long h, long D, GEN Faf) { pari_sp av; if (lg(gel(Faf,1)) == 1) switch(D) { case -3: return 1. / 3; case -4: return 1. / 2; default: return (double)h; } av = avma; return (double)gc_long(av, h * uhclassnoF_fact(Faf, D)); } /* return factor(u*v) */ static GEN factor_uv(GEN fau, ulong v, ulong vfactors) { GEN P, E; long i; if (!vfactors) return fau; P = gel(fau,1); E = gel(fau,2); for (i = 0; vfactors; i++, vfactors >>= 1) if (vfactors & 1UL) { long p = SMALL_PRIMES[i]; P = vecsmall_append(P, p); E = vecsmall_append(E, u_lvalrem(v, p, &v)); if (v == 1) break; } return famatsmall_reduce(mkmat2(P, E)); } /* This is Sutherland 2009, Algorithm 2.1 (p8); delta > 0 */ static GEN select_classpoly_prime_pool(double min_bits, double delta, GEN G) { /* Sutherland defines V_MAX to be 1200 without saying why */ const long V_MAX = 1200; double bits = 0.0, hurwitz, z; ulong t_size_lim, d = (ulong)-pcp_get_D(G); long ires, inv = pcp_get_inv(G); GEN fau = pcp_get_fau(G); GEN res, t_min; /* t_min[v] = lower bound for the t we look at for that v */ #ifdef LONG_IS_64BIT long L = pcp_get_L(G)[!!pcp_get_L0(G)]; #endif hurwitz = hclassno_wrapper(pcp_get_h(G), pcp_get_D0(G), fau); res = cgetg(128+1, t_VEC); ires = 1; /* Initialise t_min to be all 2's. This avoids trace 0 and trace 1 curves */ t_min = const_vecsmall(V_MAX-1, 2); /* maximum possible trace = sqrt(2^BIL + D) */ t_size_lim = 2.0 * sqrt((double)((1UL << (BITS_IN_LONG - 2)) - (d >> 2))); for (z = d / (2.0 * hurwitz); ; z *= delta + 1.0) { double v_bound_aux = 4.0 * z * hurwitz; /* = 4 z H(d) */ ulong v; dbg_printf(1)("z = %.2f\n", z); for (v = 1; v < V_MAX; v++) #ifdef LONG_IS_64BIT if (L<=2 || v%L) #endif { ulong p, t, t_max, vfactors, v2d, vd; double hurwitz_ratio_bound, max_p, H; long ires0; GEN faw; if ((long)(vfactors = SMOOTH_INTS[v]) < 0) continue; hurwitz_ratio_bound = HURWITZ_RATIO[v] / 128.0; vd = v * d; if (vd >= v_bound_aux * hurwitz_ratio_bound) break; v2d = v * vd; faw = factor_uv(fau, v, vfactors); H = hclassno_wrapper(pcp_get_h(G), pcp_get_D0(G), faw); /* t <= 2 sqrt(p) and p <= z H(v^2 d) and * H(v^2 d) < v H(d) \prod_{p | v} (p+1)/(p-1) * This last term is v * hurwitz * hurwitz_ratio_bound. */ max_p = z * v * hurwitz * hurwitz_ratio_bound; t_max = 2.0 * sqrt(mindd((1UL<<(BITS_IN_LONG-2)) - (v2d>>2), max_p)); t = t_min[v]; if ((t & 1) != (v2d & 1)) t++; p = (t * t + v2d) >> 2; ires0 = ires; for (; t <= t_max; p += t+1, t += 2) /* 4p = t^2 + v^2*d */ if (modinv_good_prime(inv,p) && uisprime(p)) { if (ires == lg(res)) res = vec_lengthen(res, lg(res) << 1); gel(res, ires++) = mkvec2(mkvecsmall5(p,t,v,(long)(p/H),vfactors), faw); bits += log2(p); } t_min[v] = t; if (ires - ires0) { dbg_printf(2)(" Found %lu primes for v = %lu.\n", ires - ires0, v); } if (bits > min_bits) { dbg_printf(1)("Found %ld primes; total size %.2f bits.\n", ires-1,bits); setlg(res, ires); return res; } } if (uel(t_min,1) >= t_size_lim) { /* exhausted all solutions that fit in ulong */ char *err = stack_sprintf("class polynomial of discriminant %ld", pcp_get_D(G)); pari_err(e_ARCH, err); } } } static int primecmp(void *data, GEN v1, GEN v2) { (void)data; return cmpss(gel(v1,1)[4], gel(v2,1)[4]); } static long height_margin(long inv, long D) { (void)D; /* NB: avs just uses a height margin of 256 for everyone and everything. */ if (inv == INV_F) return 64; /* checked for discriminants up to -350000 */ if (inv == INV_G2) return 5; if (inv != INV_J) return 256; /* TODO: This should be made more accurate */ return 0; } static GEN select_classpoly_primes(ulong *vfactors, ulong *biggest_v, double delta, GEN G, double height) { const long k = 2; pari_sp av = avma; long i, s, D = pcp_get_D(G), inv = pcp_get_inv(G); ulong biggest_p; double prime_bits, min_prime_bits, b; GEN prime_pool; s = modinv_height_factor(inv); b = height / s + height_margin(inv, D); dbg_printf(1)("adjusted height = %.2f\n", b); min_prime_bits = k * b; prime_pool = select_classpoly_prime_pool(min_prime_bits, delta, G); /* FIXME: Apply torsion constraints */ /* FIXME: Rank elts of res according to cost/benefit ratio */ gen_sort_inplace(prime_pool, NULL, primecmp, NULL); prime_bits = 0.0; biggest_p = *biggest_v = *vfactors = 0; for (i = 1; i < lg(prime_pool); i++) { GEN q = gmael(prime_pool, i, 1); ulong p = q[1], v = q[3]; *vfactors |= q[5]; prime_bits += log2(p); if (p > biggest_p) biggest_p = p; if (v > *biggest_v) *biggest_v = v; if (prime_bits > b) break; } dbg_printf(1)("Selected %ld primes; largest is %lu ~ 2^%.2f\n", i, biggest_p, log2(biggest_p)); return gerepilecopy(av, vecslice(prime_pool, 1, i)); } /* This is Sutherland 2009 Algorithm 1.2. */ static long oneroot_of_classpoly( ulong *j_endo, int *endo_cert, ulong j, norm_eqn_t ne, GEN jdb) { pari_sp av = avma; long nfactors, L_bound, i; ulong p = ne->p, pi = ne->pi; GEN factors, vdepths; if (j == 0 || j == 1728 % p) pari_err_BUG("oneroot_of_classpoly"); *endo_cert = 1; factors = gel(ne->faw, 1); nfactors = lg(factors) - 1; if (!nfactors) { *j_endo = j; return 1; } vdepths = gel(ne->faw, 2); /* FIXME: This should be bigger */ L_bound = maxdd(log((double) -ne->D), (double)ne->v); /* Iterate over the primes L dividing w */ for (i = 1; i <= nfactors; ++i) { pari_sp av2 = avma; GEN phi; long jlvl, lvl_diff, depth = vdepths[i], L = factors[i]; if (L > L_bound) { *endo_cert = 0; break; } phi = polmodular_db_getp(jdb, L, p); /* TODO: See if I can reuse paths created in j_level_in_volcano() * later in {ascend,descend}_volcano(), perhaps by combining the * functions into one "adjust_level" function. */ jlvl = j_level_in_volcano(phi, j, p, pi, L, depth); lvl_diff = z_lval(ne->u, L) - jlvl; if (lvl_diff < 0) /* j's level is less than v(u) so we must ascend */ j = ascend_volcano(phi, j, p, pi, jlvl, L, depth, -lvl_diff); else if (lvl_diff > 0) /* otherwise j's level is greater than v(u) so we descend */ j = descend_volcano(phi, j, p, pi, jlvl, L, depth, lvl_diff); set_avma(av2); } /* Prob(j has the wrong endomorphism ring) ~ \sum_{p|u_compl} 1/p * (and u_compl > L_bound), so just return it and rely on detection code in * enum_j_with_endo_ring(). Detection is that we hit a previously found * j-invariant earlier than expected. OR, we evaluate class polynomials of * the suborders at j and if any are zero then j must be chosen again. */ set_avma(av); *j_endo = j; return j != 0 && j != 1728 % p; } INLINE long vecsmall_isin_skip(GEN v, long x, long k) { long i, l = lg(v); for (i = k; i < l; ++i) if (v[i] == x) return i; return 0; } void norm_eqn_set(norm_eqn_t ne, long D, long t, long u, long v, GEN faw, ulong p) { ne->D = D; ne->u = u; ne->t = t; ne->v = v; ne->faw = faw; ne->p = p; ne->pi = get_Fl_red(ne->p); ne->s2 = Fl_2gener_pre(ne->p, ne->pi); /* select twisting parameter */ do ne->T = random_Fl(p); while (krouu(ne->T, p) != -1); } INLINE ulong Flv_powsum_pre(GEN v, ulong n, ulong p, ulong pi) { long i, l = lg(v); ulong psum = 0; for (i = 1; i < l; ++i) psum = Fl_add(psum, Fl_powu_pre(uel(v,i), n, p, pi), p); return psum; } INLINE int modinv_has_sign_ambiguity(long inv) { switch (inv) { case INV_F: case INV_F3: case INV_W2W3E2: case INV_W2W7E2: case INV_W2W3: case INV_W2W5: case INV_W2W7: case INV_W3W3: case INV_W2W13: case INV_W3W7: return 1; } return 0; } INLINE int modinv_units(int inv) { return modinv_is_double_eta(inv) || modinv_is_Weber(inv); } INLINE int adjust_signs(GEN js, ulong p, ulong pi, long inv, GEN T, long e) { long negate = 0; long h = lg(js) - 1; if ((h & 1) && modinv_units(inv)) { ulong prod = Flv_prod_pre(js, p, pi); if (prod != p - 1) { if (prod != 1) pari_err_BUG("adjust_signs: constant term is not +/-1"); negate = 1; } } else { ulong tp, t; tp = umodiu(T, p); t = Flv_powsum_pre(js, e, p, pi); if (t == 0) return 0; if (t != tp) { if (Fl_neg(t, p) != tp) pari_err_BUG("adjust_signs: incorrect trace"); negate = 1; } } if (negate) Flv_neg_inplace(js, p); return 1; } static ulong find_jinv( long *trace_tries, long *endo_tries, int *cert, norm_eqn_t ne, long inv, long rho_inv, GEN jdb) { long found, ok = 1; ulong j, r; do { do { long tries; ulong j_t = 0; /* TODO: Set batch size according to expected number of tries and * experimental cost/benefit analysis. */ tries = find_j_inv_with_given_trace(&j_t, ne, rho_inv, 0); if (j_t == 0) pari_err_BUG("polclass0: Couldn't find j-invariant with given trace."); dbg_printf(2)(" j-invariant %ld has trace +/-%ld (%ld tries, 1/rho = %ld)\n", j_t, ne->t, tries, rho_inv); *trace_tries += tries; found = oneroot_of_classpoly(&j, cert, j_t, ne, jdb); ++*endo_tries; } while (!found); if (modinv_is_double_eta(inv)) ok = modfn_unambiguous_root(&r, inv, j, ne, jdb); else r = modfn_root(j, ne, inv); } while (!ok); return r; } static GEN polclass_roots_modp(long *n_trace_curves, norm_eqn_t ne, long rho_inv, GEN G, GEN db) { pari_sp av; ulong j = 0; long inv = pcp_get_inv(G), endo_tries = 0; int endo_cert; GEN res, jdb, fdb, vshape = factoru(ne->v); jdb = polmodular_db_for_inv(db, INV_J); fdb = polmodular_db_for_inv(db, inv); dbg_printf(2)("p = %ld, t = %ld, v = %ld\n", ne->p, ne->t, ne->v); av = avma; do { j = find_jinv(n_trace_curves,&endo_tries,&endo_cert, ne, inv, rho_inv, jdb); res = enum_roots(j, ne, fdb, G, vshape); if (!res && endo_cert) pari_err_BUG("polclass_roots_modp"); if (res && !endo_cert && vecsmall_isin_skip(res, res[1], 2)) { set_avma(av); res = NULL; } } while (!res); dbg_printf(2)(" j-invariant %ld has correct endomorphism ring " "(%ld tries)\n", j, endo_tries); dbg_printf(4)(" all such j-invariants: %Ps\n", res); return res; } INLINE int modinv_inverted_involution(long inv) { return modinv_is_double_eta(inv); } INLINE int modinv_negated_involution(long inv) { /* determined by trial and error */ return inv == INV_F || inv == INV_W3W5 || inv == INV_W3W7 || inv == INV_W3W3 || inv == INV_W5W7; } /* Return true iff Phi_L(j0, j1) = 0. */ INLINE long verify_edge(ulong j0, ulong j1, ulong p, ulong pi, long L, GEN fdb) { pari_sp av = avma; GEN phi = polmodular_db_getp(fdb, L, p); GEN f = Flm_Fl_polmodular_evalx(phi, L, j1, p, pi); return gc_long(av, Flx_eval_pre(f, j0, p, pi) == 0); } INLINE long verify_2path( ulong j1, ulong j2, ulong p, ulong pi, long L1, long L2, GEN fdb) { pari_sp av = avma; GEN phi1 = polmodular_db_getp(fdb, L1, p); GEN phi2 = polmodular_db_getp(fdb, L2, p); GEN f = Flm_Fl_polmodular_evalx(phi1, L1, j1, p, pi); GEN g = Flm_Fl_polmodular_evalx(phi2, L2, j2, p, pi); GEN d = Flx_gcd(f, g, p); long n = degpol(d); if (n >= 2) n = Flx_nbroots(d, p); return gc_long(av, n); } static long oriented_n_action( const long *ni, GEN G, GEN v, ulong p, ulong pi, GEN fdb) { pari_sp av = avma; long i, j, k = pcp_get_k(G); long nr = k * (k - 1) / 2; const long *n = pcp_get_n(G), *m = pcp_get_m(G), *o = pcp_get_o(G), *r = pcp_get_r(G), *ps = pcp_get_orient_p(G), *qs = pcp_get_orient_q(G), *reps = pcp_get_orient_reps(G); long *signs = new_chunk(k); long *e = new_chunk(k); long *rels = new_chunk(nr); evec_copy(rels, r, nr); for (i = 0; i < k; ++i) { /* If generator doesn't require orientation, continue; power rels already * copied to *rels in initialisation */ if (ps[i] <= 0) { signs[i] = 1; continue; } /* Get rep of orientation element and express it in terms of the * (partially) oriented presentation */ for (j = 0; j < i; ++j) { long t = reps[i * k + j]; e[j] = (signs[j] < 0 ? o[j] - t : t); } e[j] = reps[i * k + j]; for (++j; j < k; ++j) e[j] = 0; evec_reduce(e, n, rels, k); j = evec_to_index(e, m, k); /* FIXME: These calls to verify_edge recalculate powers of v[0] * and v[j] over and over again, they also reduce Phi_{ps[i]} modulo p over * and over again. Need to cache these things! */ if (qs[i] > 1) signs[i] = (verify_2path(uel(v,1), uel(v,j+1), p, pi, ps[i], qs[i], fdb) ? 1 : -1); else /* Verify ps[i]-edge to orient ith generator */ signs[i] = (verify_edge(uel(v,1), uel(v,j+1), p, pi, ps[i], fdb) ? 1 : -1); /* Update power relation */ for (j = 0; j < i; ++j) { long t = evec_ri(r, i)[j]; e[j] = (signs[i] * signs[j] < 0 ? o[j] - t : t); } while (j < k) e[j++] = 0; evec_reduce(e, n, rels, k); for (j = 0; j < i; ++j) evec_ri_mutate(rels, i)[j] = e[j]; /* TODO: This is a sanity check, can be removed if everything is working */ for (j = 0; j <= i; ++j) { long t = reps[i * k + j]; e[j] = (signs[j] < 0 ? o[j] - t : t); } while (j < k) e[j++] = 0; evec_reduce(e, n, rels, k); j = evec_to_index(e, m, k); if (qs[i] > 1) { if (!verify_2path(uel(v,1), uel(v, j+1), p, pi, ps[i], qs[i], fdb)) pari_err_BUG("oriented_n_action"); } else { if (!verify_edge(uel(v,1), uel(v, j+1), p, pi, ps[i], fdb)) pari_err_BUG("oriented_n_action"); } } /* Orient representation of [N] relative to the torsor */ for (i = 0; i < k; ++i) e[i] = (signs[i] < 0 ? o[i] - ni[i] : ni[i]); evec_reduce(e, n, rels, k); return gc_long(av, evec_to_index(e,m,k)); } /* F = double_eta_raw(inv) */ INLINE void adjust_orientation(GEN F, long inv, GEN v, long e, ulong p, ulong pi) { ulong j0 = uel(v, 1), je = uel(v, e); if (!modinv_j_from_2double_eta(F, inv, j0, je, p, pi)) { if (modinv_inverted_involution(inv)) Flv_inv_pre_inplace(v, p, pi); if (modinv_negated_involution(inv)) Flv_neg_inplace(v, p); } } static void polclass_psum( GEN *psum, long *d, GEN roots, GEN primes, GEN pilist, ulong h, long inv) { /* Number of consecutive CRT stabilisations before we assume we have * the correct answer. */ enum { MIN_STAB_CNT = 3 }; pari_sp av = avma, btop; GEN ps, psum_sqr, P; long i, e, stabcnt, nprimes = lg(primes) - 1; if ((h & 1) && modinv_units(inv)) { *psum = gen_1; *d = 0; return; } e = -1; ps = cgetg(nprimes+1, t_VECSMALL); do { e += 2; for (i = 1; i <= nprimes; ++i) { GEN roots_modp = gel(roots, i); ulong p = uel(primes, i), pi = uel(pilist, i); uel(ps, i) = Flv_powsum_pre(roots_modp, e, p, pi); } btop = avma; psum_sqr = Z_init_CRT(0, 1); P = gen_1; for (i = 1, stabcnt = 0; stabcnt < MIN_STAB_CNT && i <= nprimes; ++i) { ulong p = uel(primes, i), pi = uel(pilist, i); ulong ps2 = Fl_sqr_pre(uel(ps, i), p, pi); ulong stab = Z_incremental_CRT(&psum_sqr, ps2, &P, p); /* stabcnt = stab * (stabcnt + 1) */ if (stab) ++stabcnt; else stabcnt = 0; if (gc_needed(av, 2)) gerepileall(btop, 2, &psum_sqr, &P); } if (stabcnt == 0 && nprimes >= MIN_STAB_CNT) pari_err_BUG("polclass_psum"); } while (!signe(psum_sqr)); if ( ! Z_issquareall(psum_sqr, psum)) pari_err_BUG("polclass_psum"); dbg_printf(1)("Classpoly power sum (e = %ld) is %Ps; found with %.2f%% of the primes\n", e, *psum, 100 * (i - 1) / (double) nprimes); *psum = gerepileupto(av, *psum); *d = e; } static GEN polclass_small_disc(long D, long inv, long vx) { if (D == -3) return pol_x(vx); if (D == -4) { switch (inv) { case INV_J: return deg1pol(gen_1, stoi(-1728), vx); case INV_G2:return deg1pol(gen_1, stoi(-12), vx); default: /* no other invariants for which we can calculate H_{-4}(X) */ pari_err_BUG("polclass_small_disc"); } } return NULL; } static ulong quadnegclassnou(long D, long *pD0, GEN *pP, GEN *pE) { ulong d = (ulong)-D, d0 = coredisc2u_fact(factoru(d), -1, pP, pE); ulong h = uquadclassnoF_fact(d0, -1, *pP, *pE) * quadclassnos(-(long)d0); *pD0 = -(long)d0; return h; } GEN polclass_worker(GEN q, GEN G, GEN db) { GEN T = cgetg(3, t_VEC), z, P = gel(q,1), faw = gel(q,2); long n_curves_tested = 0, t = P[2], v = P[3], rho_inv = P[4]; ulong p = (ulong)P[1]; pari_sp av = avma; norm_eqn_t ne; norm_eqn_set(ne, pcp_get_D(G), t, pcp_get_u(G), v, faw, p); z = polclass_roots_modp(&n_curves_tested, ne, rho_inv, G, db); gel(T,1) = gerepileuptoleaf(av, z); gel(T,2) = mkvecsmall3(ne->p, ne->pi, n_curves_tested); return T; } GEN polclass0(long D, long inv, long vx, GEN *db) { pari_sp av = avma; GEN primes, H, plist, pilist, Pu, Eu; long n_curves_tested = 0, filter = 1, pending = 0, cnt = 0; long D0, nprimes, s, i, j, del, ni, orient, h, p1, p2, k; ulong u, vfactors, biggest_v; GEN G, worker, vec; double height; static const double delta = 0.5; struct pari_mt pt; if (D >= -4) return polclass_small_disc(D, inv, vx); h = quadnegclassnou(D, &D0, &Pu, &Eu); u = D == D0? 1: (ulong)sqrt(D / D0); /* u = \prod Pu[i]^Eu[i] */ dbg_printf(1)("D = %ld, conductor = %ld, inv = %ld\n", D, u, inv); ni = modinv_degree(&p1, &p2, inv); orient = modinv_is_double_eta(inv) && kross(D, p1) && kross(D, p2); G = classgp_make_pcp(&height, &ni, h, D, D0, u, Pu, Eu, inv, filter, orient); primes = select_classpoly_primes(&vfactors, &biggest_v, delta, G, height); /* Prepopulate *db with all the modpolys we might need */ if (u > 1) { /* L_bound in oneroot_of_classpoly() */ long l = lg(Pu), maxL = maxdd(log((double) -D), (double)biggest_v); for (i = 1; i < l; i++) { long L = Pu[i]; if (L > maxL) break; polmodular_db_add_level(db, L, INV_J); } } for (i = 0; vfactors; ++i) { if (vfactors & 1UL) polmodular_db_add_level(db, SMALL_PRIMES[i], INV_J); vfactors >>= 1; } if (p1 > 1) polmodular_db_add_level(db, p1, INV_J); if (p2 > 1) polmodular_db_add_level(db, p2, INV_J); s = !!pcp_get_L0(G); k = pcp_get_k(G); polmodular_db_add_levels(db, pcp_get_L(G) + s, k - s, inv); if (orient) { GEN orient_p = pcp_get_orient_p(G); GEN orient_q = pcp_get_orient_q(G); for (i = 0; i < k; ++i) { if (orient_p[i] > 1) polmodular_db_add_level(db, orient_p[i], inv); if (orient_q[i] > 1) polmodular_db_add_level(db, orient_q[i], inv); } } nprimes = lg(primes) - 1; worker = snm_closure(is_entry("_polclass_worker"), mkvec2(G, *db)); H = cgetg(nprimes + 1, t_VEC); plist = cgetg(nprimes + 1, t_VECSMALL); pilist = cgetg(nprimes + 1, t_VECSMALL); vec = cgetg(2, t_VEC); dbg_printf(0)("Calculating class polynomial of disc %ld and inv %ld:", D, inv); mt_queue_start_lim(&pt, worker, nprimes); for (i = 1; i <= nprimes || pending; i++) { long workid; GEN done; if (i <= nprimes) gel(vec,1) = gel(primes,i); mt_queue_submit(&pt, i, i <= nprimes? vec: NULL); done = mt_queue_get(&pt, &workid, &pending); if (done) { gel(H, workid) = gel(done,1); uel(plist, workid) = mael(done,2,1); uel(pilist, workid) = mael(done,2,2); n_curves_tested += mael(done,2,3); cnt++; if (DEBUGLEVEL>2 && (cnt & 3L)==0) err_printf(" %ld%%", cnt*100/nprimes); } } mt_queue_end(&pt); dbg_printf(0)(" done\n"); if (orient) { GEN nvec = new_chunk(k); GEN fdb = polmodular_db_for_inv(*db, inv); GEN F = double_eta_raw(inv); index_to_evec((long *)nvec, ni, pcp_get_m(G), k); for (i = 1; i <= nprimes; ++i) { GEN v = gel(H, i); ulong p = uel(plist, i), pi = uel(pilist, i); long oni = oriented_n_action(nvec, G, v, p, pi, fdb); adjust_orientation(F, inv, v, oni + 1, p, pi); } } if (modinv_has_sign_ambiguity(inv)) { GEN psum; long e; polclass_psum(&psum, &e, H, plist, pilist, h, inv); for (i = 1; i <= nprimes; ++i) { GEN v = gel(H, i); ulong p = uel(plist, i), pi = uel(pilist, i); if (!adjust_signs(v, p, pi, inv, psum, e)) uel(plist, i) = 0; } } for (i = 1, j = 1, del = 0; i <= nprimes; ++i) { pari_sp av2 = avma; ulong p = uel(plist, i); long l; GEN v; if (!p) { del++; continue; } v = Flv_roots_to_pol(gel(H,i), p, vx); l = lg(v); *++v = evaltyp(t_VECSMALL) | _evallg(l-1); /* Flx_to_Flv inplace */ uel(plist, j) = p; gel(H, j++) = gerepileuptoleaf(av2, v); } setlg(H,nprimes+1-del); setlg(plist,nprimes+1-del); dbg_printf(1)("Total number of curves tested: %ld\n", n_curves_tested); H = ncV_chinese_center(H, plist, NULL); dbg_printf(1)("Result height: %.2f\n", dbllog2(gsupnorm(H, DEFAULTPREC))); return gerepilecopy(av, RgV_to_RgX(H, vx)); } void check_modinv(long inv) { switch (inv) { case INV_J: case INV_F: case INV_F2: case INV_F3: case INV_F4: case INV_G2: case INV_W2W3: case INV_F8: case INV_W3W3: case INV_W2W5: case INV_W2W7: case INV_W3W5: case INV_W3W7: case INV_W2W3E2: case INV_W2W5E2: case INV_W2W13: case INV_W2W7E2: case INV_W3W3E2: case INV_W5W7: case INV_W3W13: break; default: pari_err_DOMAIN("polmodular", "inv", "invalid invariant", stoi(inv), gen_0); } } GEN polclass(GEN DD, long inv, long vx) { GEN db, H; long D; if (vx < 0) vx = 0; check_quaddisc_imag(DD, NULL, "polclass"); check_modinv(inv); D = itos(DD); if (!modinv_good_disc(inv, D)) pari_err_DOMAIN("polclass", "D", "incompatible with given invariant", stoi(inv), DD); db = polmodular_db_init(inv); H = polclass0(D, inv, vx, &db); gunclone_deep(db); return H; } pari-2.17.2/src/basemath/QX_factor.c0000644000175000017500000011276414676526175015627 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_factor /* 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 && abscmpii(p1, B) > 0) return NULL; p1 = gerepileuptoint(av, p1); gel(z,i-dy) = p1; } av = avma; for (; i >= 0; i--) { p1 = gel(x,i); /* we always enter this loop at least once */ for (j=0; j<=i && j<=dz; j++) p1 = subii(p1, mulii(gel(z,j),gel(y,i-j))); if (signe(p1)) return NULL; set_avma(av); } return z - 2; } static GEN ZX_divides(GEN x, GEN y) { return ZX_divides_i(x,y,NULL); } #if 0 /* cf Beauzamy et al: upper bound for * lc(x) * [2^(5/8) / pi^(3/8)] e^(1/4n) 2^(n/2) sqrt([x]_2)/ n^(3/8) * where [x]_2 = sqrt(\sum_i=0^n x[i]^2 / binomial(n,i)). One factor has * all coeffs less than then bound */ static GEN two_factor_bound(GEN x) { long i, j, n = lg(x) - 3; pari_sp av = avma; GEN *invbin, c, r = cgetr(LOWDEFAULTPREC), z; x += 2; invbin = (GEN*)new_chunk(n+1); z = real_1(LOWDEFAULTPREC); /* invbin[i] = 1 / binomial(n, i) */ for (i=0,j=n; j >= i; i++,j--) { invbin[i] = invbin[j] = z; z = divru(mulru(z, i+1), n-i); } z = invbin[0]; /* = 1 */ for (i=0; i<=n; i++) { c = gel(x,i); if (!signe(c)) continue; affir(c, r); z = addrr(z, mulrr(sqrr(r), invbin[i])); } z = shiftr(sqrtr(z), n); z = divrr(z, dbltor(pow((double)n, 0.75))); z = roundr_safe(sqrtr(z)); z = mulii(z, absi_shallow(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_coeff(S), bin = vecbinomial(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 = vecbinomial(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(utor(3,prec), 3 + 2*d); /* 3^{3/2 + d} */ C = divrr(mulrr(C, s), mulur(4*d, mppi(prec))); lS = absi_shallow(leading_coeff(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_shallow(a, b))); } /* Naive recombination of modular factors: combine up to maxK modular * factors, degree <= klim * * target = polynomial we want to factor * famod = array of modular factors. Product should be congruent to * target/lc(target) modulo p^a * For true factors: S1,S2 <= p^b, with b <= a and p^(b-a) < 2^31 */ static GEN cmbf(GEN pol, GEN famod, GEN bound, GEN p, long a, long b, long klim, long *pmaxK, int *done) { long K = 1, cnt = 1, i,j,k, curdeg, lfamod = lg(famod)-1; ulong spa_b, spa_bs2, Sbound; GEN lc, lcpol, pa = powiu(p,a), pas2 = shifti(pa,-1); GEN trace1 = cgetg(lfamod+1, t_VECSMALL); GEN trace2 = cgetg(lfamod+1, t_VECSMALL); GEN ind = cgetg(lfamod+1, t_VECSMALL); GEN deg = cgetg(lfamod+1, t_VECSMALL); GEN degsofar = cgetg(lfamod+1, t_VECSMALL); GEN listmod = cgetg(lfamod+1, t_VEC); GEN fa = cgetg(lfamod+1, t_VEC); *pmaxK = cmbf_maxK(lfamod); lc = absi_shallow(leading_coeff(pol)); if (equali1(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); } uel(trace1,i) = itou(diviiround(T1, pb)); uel(trace2,i) = itou(diviiround(T2, pb)); } spa_b = uel(pa_b,2); /* < 2^31 */ spa_bs2 = uel(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=uel(trace1,ind[1]),i=2; i<=K; i++) t = Fl_add(t, uel(trace1,ind[i]), spa_b); if (t > spa_bs2) t = spa_b - t; if (t > Sbound) { if (DEBUGLEVEL>6) err_printf("."); goto NEXT; } /* d - 2 test */ for (t=uel(trace2,ind[1]),i=2; i<=K; i++) t = Fl_add(t, uel(trace2,ind[i]), spa_b); if (t > spa_bs2) t = spa_b - t; if (t > Sbound) { if (DEBUGLEVEL>6) err_printf("|"); goto NEXT; } av = avma; /* check trailing coeff */ y = lc; for (i=1; i<=K; i++) { GEN q = constant_coeff(gel(famod,ind[i])); if (y) q = mulii(y, q); y = centermodii(q, pa, pas2); } if (!signe(y) || !dvdii(constant_coeff(lcpol), y)) { if (DEBUGLEVEL>3) err_printf("T"); set_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("*"); set_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_coeff(y)); for (i=j=k=1; i <= lfamod; i++) { /* remove used factors */ if (j <= K && i == ind[j]) j++; else { gel(famod,k) = gel(famod,i); uel(trace1,k) = uel(trace1,i); uel(trace2,k) = uel(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_shallow(leading_coeff(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_coeff(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); } /* recombination of modular factors: van Hoeij's algorithm */ /* Q in Z[X], return Q(2^n) */ static GEN shifteval(GEN Q, long n) { pari_sp av = avma; long i, l = lg(Q); GEN s; if (!signe(Q)) return gen_0; s = gel(Q,l-1); for (i = l-2; i > 1; i--) { s = addii(gel(Q,i), shifti(s, n)); if (gc_needed(av,1)) s = gerepileuptoint(av, s); } 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_shallow(leading_coeff(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_shallow(gel(Q,k)); k = (long)(fujiwara_bound(P0)); 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; set_avma(av); } if (k < 0) k = 0; y = int2n(k+1); if (d > 2000) return y; /* likely to be expensive, don't bother */ x = int2n(k); for(k=0; ; k++) { z = shifti(addii(x,y), -1); if (equalii(x,z) || k > 5) break; if (cmpii(ZX_Z_eval(Q,z), mulii(lP, powiu(z, d))) < 0) y = z; else x = z; } return y; } GEN chk_factors_get(GEN lt, GEN famod, GEN c, GEN T, GEN N) { long i = 1, j, l = lg(famod); GEN V = cgetg(l, t_VEC); for (j = 1; j < l; j++) if (signe(gel(c,j))) gel(V,i++) = gel(famod,j); if (lt && 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 = ZM_hnf_knapsack(M_L); if (!piv) return NULL; if (DEBUGLEVEL>7) err_printf("ZM_hnf_knapsack output:\n%Ps\n",piv); r = lg(piv)-1; list = cgetg(r+1, t_VEC); lt = absi_shallow(leading_coeff(pol)); if (equali1(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_i(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_coeff(y)); lt = absi_shallow(leading_coeff(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 | LLL_NOFLATTER, &norm); if (DEBUGLEVEL>2) *ti_LLL += timer_delay(&T); for (R=lg(m)-1; R > 0; R--) if (cmprr(gel(norm,R), Bnorm) < 0) break; for (i=1; i<=R; i++) setlg(u[i], n0+1); if (R <= 1) { if (!R) pari_err_BUG("LLL_cmbf [no factor]"); return NULL; /* irreducible */ } setlg(u, R+1); return u; } static ulong next2pow(ulong a) { ulong b = 1; while (b < a) b <<= 1; return b; } /* Recombination phase of Berlekamp-Zassenhaus algorithm using a variant of * van Hoeij's knapsack * * P = squarefree in Z[X]. * famod = array of (lifted) modular factors mod p^a * bound = Mignotte bound for the size of divisors of P (for the sup norm) * previously recombined all set of factors with less than rec elts */ static GEN LLL_cmbf(GEN P, GEN famod, GEN p, GEN pa, GEN bound, long a, long rec) { const long N0 = 1; /* # of traces added at each step */ double BitPerFactor = 0.4; /* nb bits in p^(a-b) / modular factor */ long i,j,tmax,n0,C, dP = degpol(P); double logp = log((double)itos(p)), LOGp2 = M_LN2/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; long ti_LLL = 0, ti_CF = 0; lP = absi_shallow(leading_coeff(P)); if (equali1(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; 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, pa, p, a); for (i=1; i<=n0; i++) TT[i] = 0; } for (i=1; i<=n0; i++) { GEN p1 = gel(Tra,i); GEN p2 = polsym_gen(gel(famod,i), gel(TT,i), tnew, NULL, pa); gel(TT,i) = p2; p2 += 1+tmax; /* ignore traces number 0...tmax */ for (j=1; j<=N0; j++) gel(p1,j) = gel(p2,j); if (lP) { /* make Newton sums integral */ GEN lPpow = powiu(lP, tmax); for (j=1; j<=N0; j++) { lPpow = mulii(lPpow,lP); gel(p1,j) = mulii(gel(p1,j), lPpow); } } } /* compute truncation parameter */ if (DEBUGLEVEL>2) { timer_start(&ti2); timer_start(&TI); } oldCM_L = CM_L; av2 = avma; delta = b = 0; /* -Wall */ AGAIN: M_L = Q_div_to_int(CM_L, utoipos(C)); T2 = centermod( ZM_mul(Tra, M_L), pa ); if (first) { /* initialize lattice, using few p-adic digits for traces */ double t = gexpo(T2) - maxdd(32.0, BitPerFactor*r); bgood = (long) (t * LOGp2); b = maxss(bmin, bgood); delta = a - b; } else { /* add more p-adic digits and continue reduction */ long b0 = (long)(gexpo(T2) * LOGp2); if (b0 < b) b = b0; b = maxss(b-delta, bmin); if (b - delta/2 < bmin) b = bmin; /* near there. Go all the way */ } q = powiu(p, b); m = vconcat( CM_L, gdivround(T2, q) ); if (first) { GEN P1 = scalarmat(powiu(p, a-b), N0); first = 0; m = shallowconcat( m, vconcat(ZERO, P1) ); /* [ C M_L 0 ] * m = [ ] square matrix * [ T2' p^(a-b) I_N0 ] T2' = Tra * M_L truncated */ } CM_L = LLL_check_progress(Bnorm, n0, m, b == bmin, /*dbg:*/ &ti_LLL); if (DEBUGLEVEL>2) err_printf("LLL_cmbf: (a,b) =%4ld,%4ld; r =%3ld -->%3ld, time = %ld\n", a,b, lg(m)-1, CM_L? lg(CM_L)-1: 1, timer_delay(&TI)); if (!CM_L) { list = mkvec(P); break; } if (b > bmin) { CM_L = gerepilecopy(av2, CM_L); goto AGAIN; } if (DEBUGLEVEL>2) timer_printf(&ti2, "for this block of traces"); i = lg(CM_L) - 1; if (i == r && ZM_equal(CM_L, oldCM_L)) { CM_L = oldCM_L; set_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 (gc_needed(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 * M_LN2/gtodouble(glog(q,DEFAULTPREC)) - 1e-5); int fl = 0; b = logintall(B, q, qb) + 1; *qb = mulii(*qb, q); amin = b + d; if (gcmp(powiu(q, amin), A) <= 0) { a = logintall(A, q, qa) + 1; *qa = mulii(*qa, q); 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_shallow(leading_coeff(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, pa, p, a); if (DEBUGLEVEL>2) timer_printf(&T, "Hensel lift (mod %Ps^%ld)", p,a); L = cmbf(target, famod, A, p, a, b, klim, &maxK, &done); if (DEBUGLEVEL>2) timer_printf(&T, "Naive recombination"); res = gel(L,1); listmod = gel(L,2); l = lg(listmod)-1; famod = gel(listmod,l); if (maxK > 0 && lg(famod)-1 > 2*maxK) { if (l!=1) A = factor_bound(gel(res,l)); if (DEBUGLEVEL > 4) err_printf("last factor still to be checked\n"); L = LLL_cmbf(gel(res,l), famod, p, pa, A, a, maxK); if (DEBUGLEVEL>2) timer_printf(&T,"Knapsack"); /* remove last elt, possibly unfactored. Add all new ones. */ setlg(res, l); res = shallowconcat(res, L); } return res; } /* Assume 'a' a squarefree ZX; return 0 if no root (fl=1) / irreducible (fl=0). * Otherwise return prime p such that a mod p has fewest roots / factors */ static ulong pick_prime(GEN a, long fl, pari_timer *T) { pari_sp av = avma, av1; const long MAXNP = 7, da = degpol(a); long nmax = da+1, np; ulong chosenp = 0; GEN lead = gel(a,da+2); forprime_t S; if (equali1(lead)) lead = NULL; u_forprime_init(&S, 2, ULONG_MAX); av1 = avma; for (np = 0; np < MAXNP; set_avma(av1)) { ulong p = u_forprime_next(&S); long nfacp; GEN z; if (!p) pari_err_OVERFLOW("DDF [out of small primes]"); if (lead && !umodiu(lead,p)) continue; z = ZX_to_Flx(a, p); if (!Flx_is_squarefree(z, p)) continue; if (fl==1) { nfacp = Flx_nbroots(z, p); if (!nfacp) { chosenp = 0; break; } /* no root */ } else if(fl==0) { nfacp = Flx_nbfact(z, p); if (nfacp == 1) { chosenp = 0; break; } /* irreducible */ } else { GEN f = gel(Flx_degfact(z, p),1); nfacp = lg(f)-1; if (f[1] > fl) { chosenp = 0; break; } /* no small factors */ } if (DEBUGLEVEL>4) err_printf("...tried prime %3lu (%-3ld %s). Time = %ld\n", p, nfacp, fl==1? "roots": "factors", timer_delay(T)); if (nfacp < nmax) { nmax = nfacp; chosenp = p; if (da > 100 && nmax < 5) break; /* large degree, few factors. Enough */ } np++; } return gc_ulong(av, chosenp); } /* Assume A a squarefree ZX; return the vector of its rational roots */ static GEN DDF_roots(GEN A) { GEN p, lc, lcpol, z, pe, pes2, bound; long i, m, e, lz; ulong pp; pari_sp av; pari_timer T; if (DEBUGLEVEL>2) timer_start(&T); pp = pick_prime(A, 1, &T); if (!pp) return cgetg(1,t_COL); /* no root */ p = utoipos(pp); lc = leading_coeff(A); if (is_pm1(lc)) { lc = NULL; lcpol = A; } else { lc = absi_shallow(lc); lcpol = ZX_Z_mul(A, lc); } bound = root_bound(A); if (lc) bound = mulii(lc, bound); e = logintall(addiu(shifti(bound, 1), 1), p, &pe) + 1; pe = mulii(pe, p); pes2 = shifti(pe, -1); if (DEBUGLEVEL>2) timer_printf(&T, "Root bound"); av = avma; z = ZpX_roots(A, p, e); lz = lg(z); z = deg1_from_roots(z, varn(A)); if (DEBUGLEVEL>2) timer_printf(&T, "Hensel lift (mod %lu^%ld)", pp,e); for (m=1, i=1; i < lz; i++) { 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 = q; r = negi( constant_coeff(y) ); if (lc) { r = gdiv(r,lc); lcpol = Q_primpart(lcpol); lc = absi_shallow( leading_coeff(lcpol) ); if (is_pm1(lc)) lc = NULL; else lcpol = ZX_Z_mul(lcpol, lc); } gel(z,m++) = r; if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"DDF_roots, m = %ld", m); gerepileall(av, lc? 3:2, &z, &lcpol, &lc); } } if (DEBUGLEVEL>2) timer_printf(&T, "Recombination"); setlg(z, m); return z; } /* Assume a squarefree ZX, deg(a) > 0, return rational factors. * In fact, a(0) != 0 but we don't use this * if dmax>0, Only look for factor of degree at most dmax */ GEN ZX_DDF_max(GEN a, long dmax) { GEN ap, prime, famod, z; long ti = 0; ulong p = 0; pari_sp av = avma; pari_timer T, T2; if (DEBUGLEVEL>2) { timer_start(&T); timer_start(&T2); } p = pick_prime(a, dmax, &T2); if (!p) return mkvec(a); prime = utoipos(p); ap = Flx_normalize(ZX_to_Flx(a, p), p); famod = gel(Flx_factor(ap, p), 1); if (DEBUGLEVEL>2) { if (DEBUGLEVEL>4) timer_printf(&T2, "splitting mod p = %lu", p); ti = timer_delay(&T); err_printf("Time setup: %ld\n", ti); } z = combine_factors(a, FlxV_to_ZXV(famod), prime, degpol(a)-1); if (DEBUGLEVEL>2) err_printf("Total Time: %ld\n===========\n", ti + timer_delay(&T)); return gerepilecopy(av, z); } /* Distinct Degree Factorization (deflating first) * Assume x squarefree, degree(x) > 0, x(0) != 0 */ GEN ZX_DDF(GEN x) { GEN L; long m; x = ZX_deflate_max(x, &m); L = ZX_DDF_max(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 RgX_gcd) * f = prod Q[i]^E[i], E[1] < E[2] < ..., and Q[i] squarefree and coprime. * Return Q, set *pE = E. For efficiency, caller should have used ZX_valrem * so that f(0) != 0 */ GEN ZX_squff(GEN f, GEN *pE) { GEN T, V, P, E; long i, k, n = 1 + degpol(f); if (signe(leading_coeff(f)) < 0) f = ZX_neg(f); E = cgetg(n, t_VECSMALL); P = cgetg(n, t_COL); T = ZX_gcd_all(f, ZX_deriv(f), &V); for (k = i = 1;; k++) { GEN W = ZX_gcd_all(T,V, &T); /* V and W are squarefree */ long dW = degpol(W), dV = degpol(V); /* f = prod_i T_i^{e_i} * W = prod_{i: e_i > k} T_i, * V = prod_{i: e_i >= k} T_i, * T = prod_{i: e_i > k} T_i^{e_i - k} */ if (!dW) { if (dV) { gel(P,i) = Q_primpart(V); E[i] = k; i++; } break; } if (dW == dV) { GEN U; while ( (U = ZX_divides(T, V)) ) { k++; T = U; } } else { gel(P,i) = Q_primpart(RgX_div(V,W)); E[i] = k; i++; V = W; } } setlg(P,i); setlg(E,i); *pE = E; return P; } static GEN fact_from_DDF(GEN Q, GEN E, long n) { GEN v,w, y = cgetg(3, t_MAT); long i,j,k, l = lg(Q); 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 < l; i++) { GEN L = gel(Q,i), e = utoipos(E[i]); long J = lg(L); for (j = 1; j < J; j++,k++) { gel(v,k) = ZX_copy(gel(L,j)); gel(w,k) = e; } } return y; } /* Factor T in Z[x] */ static GEN ZX_factor_i(GEN T) { GEN Q, E, y; long n, i, l, v; if (!signe(T)) return prime_fact(T); v = ZX_valrem(T, &T); Q = ZX_squff(T, &E); l = lg(Q); for (i = 1, n = 0; i < l; i++) { gel(Q,i) = ZX_DDF(gel(Q,i)); n += lg(gel(Q,i)) - 1; } if (v) { Q = vec_append(Q, mkvec(pol_x(varn(T)))); E = vecsmall_append(E, v); n++; } y = fact_from_DDF(Q, E, n); return sort_factor_pol(y, cmpii); } GEN ZX_factor(GEN x) { pari_sp av = avma; return gerepileupto(av, ZX_factor_i(x)); } GEN QX_factor(GEN x) { pari_sp av = avma; return gerepileupto(av, ZX_factor_i(Q_primpart(x))); } long ZX_is_irred(GEN x) { pari_sp av = avma; long l = lg(x); GEN y; if (l <= 3) return 0; /* degree < 1 */ if (l == 4) return 1; /* degree 1 */ if (ZX_val(x)) return 0; if (!ZX_is_squarefree(x)) return 0; y = ZX_DDF(x); set_avma(av); return (lg(y) == 2); } GEN nfrootsQ(GEN x) { pari_sp av = avma; GEN z; long val; if (typ(x)!=t_POL) pari_err_TYPE("nfrootsQ",x); if (!signe(x)) pari_err_ROOTS0("nfrootsQ"); x = Q_primpart(x); RgX_check_ZX(x,"nfrootsQ"); val = ZX_valrem(x, &x); z = DDF_roots( ZX_radical(x) ); if (val) z = vec_append(z, gen_0); return gerepileupto(av, sort(z)); } /************************************************************************ * GCD OVER Z[X] / Q[X] * ************************************************************************/ int ZX_is_squarefree(GEN x) { pari_sp av = avma; GEN d; long m; if (lg(x) == 2) return 0; m = ZX_deflate_order(x); if (m > 1) { if (!signe(gel(x,2))) return 0; x = RgX_deflate(x, m); } d = ZX_gcd(x,ZX_deriv(x)); return gc_bool(av, lg(d) == 3); } static int ZX_gcd_filter(GEN *pt_A, GEN *pt_P) { GEN A = *pt_A, P = *pt_P; long i, j, l = lg(A), n = 1, d = degpol(gel(A,1)); GEN B, Q; for (i=2; i di) { n=1; d = di; } } if (n == l-1) return 0; B = cgetg(n+1, t_VEC); Q = cgetg(n+1, typ(P)); for (i=1, j=1; i>1, 0, &S, &H, &mod, ZX_gcd_chinese, NULL); gerepileall(av, 2, &H, &mod); Hp = ZX_to_Flx(H, pp); if (lgpol(Flx_rem(Ap, Hp, pp)) || lgpol(Flx_rem(Bp, Hp, pp))) continue; if (!ZX_divides(Bg, H)) continue; R = ZX_divides(Ag, H); if (R) break; } /* lead(H) = g */ if (g) H = Q_primpart(H); if (c) H = ZX_Z_mul(H,c); if (DEBUGLEVEL>5) err_printf("done\n"); if (Anew) *Anew = RgX_shift_shallow(R, valA); return valH? RgX_shift_shallow(H, valH): H; } #if 0 /* ceil( || p ||_oo / lc(p) ) */ static GEN maxnorm(GEN p) { long i, n = degpol(p), av = avma; GEN x, m = gen_0; p += 2; for (i=0; i 0) m = x; } m = divii(m, gel(p,n)); return gerepileuptoint(av, addiu(absi_shallow(m),1)); } #endif GEN ZX_gcd(GEN A, GEN B) { pari_sp av = avma; return gerepilecopy(av, ZX_gcd_all(A,B,NULL)); } GEN ZX_radical(GEN A) { GEN B; (void)ZX_gcd_all(A,ZX_deriv(A),&B); return B; } 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)) set_avma(av2); else D = ZX_Q_mul(D, a); return gerepileupto(av, D); } /***************************************************************************** * Variants of the Bradford-Davenport algorithm: look for cyclotomic * * factors, and decide whether a ZX is cyclotomic or a product of cyclotomic * *****************************************************************************/ /* f of degree 1, return a cyclotomic factor (Phi_1 or Phi_2) or NULL */ static GEN BD_deg1(GEN f) { GEN a = gel(f,3), b = gel(f,2); /* f = ax + b */ if (!absequalii(a,b)) return NULL; return polcyclo((signe(a) == signe(b))? 2: 1, varn(f)); } /* f a squarefree ZX; not divisible by any Phi_n, n even */ static GEN BD_odd(GEN f) { while(degpol(f) > 1) { GEN f1 = ZX_graeffe(f); /* contain all cyclotomic divisors of f */ if (ZX_equal(f1, f)) return f; /* product of cyclotomics */ f = ZX_gcd(f, f1); } if (degpol(f) == 1) return BD_deg1(f); return NULL; /* no cyclotomic divisor */ } static GEN myconcat(GEN v, GEN x) { if (typ(x) != t_VEC) x = mkvec(x); if (!v) return x; return shallowconcat(v, x); } /* Bradford-Davenport algorithm. * f a squarefree ZX of degree > 0, return NULL or a vector of coprime * cyclotomic factors of f [ possibly reducible ] */ static GEN BD(GEN f) { GEN G = NULL, Gs = NULL, Gp = NULL, Gi = NULL; GEN fs2, fp, f2, f1, fe, fo, fe1, fo1; RgX_even_odd(f, &fe, &fo); fe1 = ZX_eval1(fe); fo1 = ZX_eval1(fo); if (absequalii(fe1, fo1)) /* f(1) = 0 or f(-1) = 0 */ { long i, v = varn(f); if (!signe(fe1)) G = mkvec2(polcyclo(1, v), polcyclo(2, v)); /* both 0 */ else if (signe(fe1) == signe(fo1)) G = mkvec(polcyclo(2, v)); /*f(-1) = 0*/ else G = mkvec(polcyclo(1, v)); /*f(1) = 0*/ for (i = lg(G)-1; i; i--) f = RgX_div(f, gel(G,i)); } /* f no longer divisible by Phi_1 or Phi_2 */ if (degpol(f) <= 1) return G; f1 = ZX_graeffe(f); /* has at most square factors */ if (ZX_equal(f1, f)) return myconcat(G,f); /* f = product of Phi_n, n odd */ fs2 = ZX_gcd_all(f1, ZX_deriv(f1), &f2); /* fs2 squarefree */ if (degpol(fs2)) { /* fs contains all Phi_n | f, 4 | n; and only those */ /* In that case, Graeffe(Phi_n) = Phi_{n/2}^2, and Phi_n = Phi_{n/2}(x^2) */ GEN fs = RgX_inflate(fs2, 2); (void)ZX_gcd_all(f, fs, &f); /* remove those Phi_n | f, 4 | n */ Gs = BD(fs2); if (Gs) { long i; for (i = lg(Gs)-1; i; i--) gel(Gs,i) = RgX_inflate(gel(Gs,i), 2); /* prod Gs[i] is the product of all Phi_n | f, 4 | n */ G = myconcat(G, Gs); } /* f2 = f1 / fs2 */ f1 = RgX_div(f2, fs2); /* f1 / fs2^2 */ } fp = ZX_gcd(f, f1); /* contains all Phi_n | f, n > 1 odd; and only those */ if (degpol(fp)) { Gp = BD_odd(fp); /* Gp is the product of all Phi_n | f, n odd */ if (Gp) G = myconcat(G, Gp); f = RgX_div(f, fp); } if (degpol(f)) { /* contains all Phi_n originally dividing f, n = 2 mod 4, n > 2; * and only those * In that case, Graeffe(Phi_n) = Phi_{n/2}, and Phi_n = Phi_{n/2}(-x) */ Gi = BD_odd(ZX_z_unscale(f, -1)); if (Gi) { /* N.B. Phi_2 does not divide f */ Gi = ZX_z_unscale(Gi, -1); /* Gi is the product of all Phi_n | f, n = 2 mod 4 */ G = myconcat(G, Gi); } } return G; } /* Let f be a nonzero QX, return the (squarefree) product of cyclotomic * divisors of f */ GEN polcyclofactors(GEN f) { pari_sp av = avma; if (typ(f) != t_POL || !signe(f)) pari_err_TYPE("polcyclofactors",f); (void)RgX_valrem(f, &f); f = Q_primpart(f); RgX_check_ZX(f,"polcyclofactors"); if (degpol(f)) { f = BD(ZX_radical(f)); if (f) return gerepilecopy(av, f); } set_avma(av); return cgetg(1,t_VEC); } /* list of all squarefree odd x such that phi(x) = n, P^-(x) > m. Unsorted */ static GEN invphi(ulong n, ulong m) { GEN C, D; long l, i; if (n == 1) return mkvecsmall(1); D = divisorsu(n); l = lg(D); C = cgetg(1, t_VECSMALL); for (i = 2; i < l; i++) /* skip 1 */ { ulong d = D[i], p; if (d < m) continue; p = d + 1; if (!uisprime(p)) continue; C = vecsmall_concat(C, zv_z_mul(invphi(D[l-i], p), p)); } return C; } long poliscyclo(GEN f) { const ulong p = 2147483647; /* prime */ pari_sp av; long i, n, e, l; ulong f3, fm3; GEN D, fp, _3; if (typ(f) != t_POL) pari_err_TYPE("poliscyclo", f); n = degpol(f); if (n <= 0 || !RgX_is_ZX(f)) return 0; if (!equali1(gel(f,n+2)) || !is_pm1(gel(f,2))) return 0; if (n == 1) return signe(gel(f,2)) > 0? 2: 1; av = avma; f = ZX_deflate_max(f, &e); if (e != 1) n = degpol(f); D = invphi(n, 1); /* squareefree odd d s.t. phi(d) = n */ l = lg(D); _3 = gmodulss(3, p); fp = ZX_to_Flx(f, p); f3 = Flx_eval(fp, 3, p); fm3 = Flx_eval(fp, p-3, p); /* f(x^e) is cyclotomic (= Phi_{de}) iff f = Phi_d, where all prime dividing * e also divide d. */ for (i = 1; i < l; i++) { long d = D[i]; /* squarefree odd */ if (odd(e)) { if (e == 1 || u_ppo(e, d) == 1) { /* early abort: check whether f(3) = Phi_d(3) or Phi_2d(3) = Phi_d(-3) * mod p before checking in Z. N.B. phi(d) and value at 3 mod p * determine Phi_d for all d <= 10^7 */ ulong F3 = Rg_to_Fl(polcyclo_eval(d, _3), p); if (F3 == f3 && ZX_equal(f, polcyclo(d, varn(f)))) return gc_long(av, d * e); if (F3 == fm3 && ZX_equal(f, polcyclo(2*d, varn(f)))) return gc_long(av, 2* d * e); } } else { if (u_ppo(e, 2*d) == 1) { /* early abort: check whether f(3) = Phi_2d(3) mod p */ ulong F3 = Rg_to_Fl(polcyclo_eval(2*d, _3), p); if (F3 == f3 && ZX_equal(f, polcyclo(2*d, varn(f)))) return gc_long(av, 2* d * e); } } } return gc_long(av, 0); } long poliscycloprod(GEN f) { pari_sp av = avma; long i, d = degpol(f); if (typ(f) != t_POL) pari_err_TYPE("poliscycloprod",f); if (!RgX_is_ZX(f)) return 0; if (!ZX_is_monic(f) || !is_pm1(constant_coeff(f))) return 0; if (d < 2) return (d == 1); if ( degpol(ZX_gcd_all(f, ZX_deriv(f), &f)) ) { d = degpol(f); if (d == 1) return 1; } f = BD(f); if (!f) return 0; for (i = lg(f)-1; i; i--) d -= degpol(gel(f,i)); return gc_long(av, d == 0); } pari-2.17.2/src/basemath/ifactor1.c0000644000175000017500000042507214760123736015436 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_factorint /***********************************************************************/ /** PRIMES IN SUCCESSION **/ /***********************************************************************/ /* 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 /* nonprime 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 */ }; /* 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, }; static int unextprime_overflow(ulong n) { #ifdef LONG_IS_64BIT return (n > (ulong)-59); #else return (n > (ulong)-5); #endif } /* return 0 for overflow */ ulong unextprime(ulong n) { long rc, rc0, 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; } if (n <= maxprime()) { long i = PRIMES_search(n); return i > 0? n: pari_PRIMES[-i]; } if (unextprime_overflow(n)) return 0; /* 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; n += prc210_d1[rcn]; if (++rcn > 47) rcn = 0; } return n; } GEN nextprime(GEN n) { long rc, rc0, rcn; pari_sp av = avma; if (typ(n) != t_INT) { n = gceil(n); if (typ(n) != t_INT) pari_err_TYPE("nextprime",n); } if (signe(n) <= 0) { set_avma(av); return gen_2; } if (lgefint(n) == 3) { ulong k = unextprime(uel(n,2)); set_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 = addui(1,n); rc = rc0 = umodiu(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 = addui(rc - rc0, n); /* now find an actual (pseudo)prime */ for(;;) { if (BPSW_psp(n)) break; n = addui(prc210_d1[rcn], n); if (++rcn > 47) rcn = 0; } if (avma == av) return icopy(n); return gerepileuptoint(av, n); } ulong uprecprime(ulong n) { long rc, rc0, rcn; { /* check if n <= 10 */ if (n <= 1) return 0; if (n == 2) return 2; if (n <= 4) return 3; if (n <= 6) return 5; if (n <= 10) return 7; } if (n <= maxprimelim()) { long i = PRIMES_search(n); return i > 0? n: pari_PRIMES[-i-1]; } /* here n >= 11 */ if (!(n % 2)) n--; rc = rc0 = n % 210; /* find previous prime residue class mod 210 */ for(;;) { rcn = (long)(prc210_no[rc>>1]); if (rcn != NPRC) break; rc -= 2; /* cannot wrap since 1 is coprime and rc odd */ } if (rc < rc0) n += rc - rc0; /* now find an actual (pseudo)prime */ for(;;) { if (uisprime(n)) break; if (--rcn < 0) rcn = 47; n -= prc210_d1[rcn]; } return n; } GEN precprime(GEN n) { long rc, rc0, rcn; pari_sp av = avma; if (typ(n) != t_INT) { n = gfloor(n); if (typ(n) != t_INT) pari_err_TYPE("nextprime",n); } if (signe(n) <= 0) { set_avma(av); return gen_0; } if (lgefint(n) <= 3) { ulong k = uel(n,2); return gc_utoi(av, uprecprime(k)); } if (!mod2(n)) n = subiu(n,1); rc = rc0 = umodiu(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 (rc0 > rc) n = subiu(n, rc0 - rc); /* now find an actual (pseudo)prime */ for(;;) { if (BPSW_psp(n)) break; if (--rcn < 0) rcn = 47; n = subiu(n, prc210_d1[rcn]); } if (avma == av) return icopy(n); return gerepileuptoint(av, n); } /* Find next single-word prime strictly larger than p. * If *n < pari_PRIMES[0], p is *n-th prime, 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 prime 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 */ static ulong snextpr(ulong p, long *n, long *rcn, long *q, int (*ispsp)(ulong)) { if (*n < pari_PRIMES[0]) { ulong t, p1 = t = pari_PRIMES[++*n]; /* nextprime(p + 1) */ if (*rcn != NPRC) { while (t > p) { t -= prc210_d1[*rcn]; if (++*rcn > 47) { *rcn = 0; if (q) (*q)++; } } /* assert(d1 == p) */ } return p1; } if (unextprime_overflow(p)) pari_err_OVERFLOW("snextpr"); /* we are beyond the prime table, initialize if needed */ if (*rcn == NPRC) *rcn = prc210_no[(p % 210) >> 1]; /* != NPRC */ /* look for the next one */ do { p += prc210_d1[*rcn]; if (++*rcn > 47) { *rcn = 0; if (q) (*q)++; } } while (!ispsp(p)); return p; } /********************************************************************/ /** **/ /** 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 tridiv_bound(N) **/ /** 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 */ static const ulong TB1[] = { 142,172,208,252,305,370,450,545,661,801,972,1180,1430, 1735,2100,2550,3090,3745,4540,5505,6675,8090,9810,11900, 14420,17490,21200,25700,31160,37780UL,45810UL,55550UL,67350UL, 81660UL,99010UL,120050UL,145550UL,176475UL,213970UL,259430UL, 314550UL,381380UL,462415UL,560660UL,679780UL,824220UL,999340UL, 1211670UL,1469110UL,1781250UL,2159700UL,2618600UL,3175000UL, 3849600UL,4667500UL,5659200UL,6861600UL,8319500UL,10087100UL, 12230300UL,14828900UL,17979600UL,21799700UL,26431500UL, 32047300UL,38856400UL, /* 110 times that still fits into 32bits */ #ifdef LONG_IS_64BIT 47112200UL,57122100UL,69258800UL,83974200UL,101816200UL, 123449000UL,149678200UL,181480300UL,220039400UL,266791100UL, 323476100UL,392204900UL,475536500UL,576573500UL,699077800UL, 847610500UL,1027701900UL,1246057200UL,1510806400UL,1831806700UL, 2221009800UL,2692906700UL,3265067200UL,3958794400UL,4799917500UL #endif }; static const ulong TB1_for_stage[] = { /* Start below the optimal B1 for finding factors which would just have been * missed by pollardbrent(), and escalate, changing curves to give good * coverage of the small factor ranges. Entries grow faster than what would * be optimal but a table instead of a 2D array keeps the code simple */ 500,520,560,620,700,800,900,1000,1150,1300,1450,1600,1800,2000, 2200,2450,2700,2950,3250,3600,4000,4400,4850,5300,5800,6400, 7100,7850,8700,9600,10600,11700,12900,14200,15700,17300, 19000,21000,23200,25500,28000,31000,34500UL,38500UL,43000UL, 48000UL,53800UL,60400UL,67750UL,76000UL,85300UL,95700UL, 107400UL,120500UL,135400UL,152000UL,170800UL,191800UL,215400UL, 241800UL,271400UL,304500UL,341500UL,383100UL,429700UL,481900UL, 540400UL,606000UL,679500UL,761800UL,854100UL,957500UL,1073500UL }; /* addition/doubling/multiplication of a point on an 'elliptic curve mod N' * may result in one of three things: * - a new bona fide point * - a point at infinity (denominator divisible by N) * - a point at infinity mod some p | N but finite mod q | N betraying itself * by a denominator which has nontrivial gcd with N. * * In the second case, addition/doubling aborts, copying one of the summands * to the destination array of points unless they coincide. * Multiplication will stop at some unpredictable intermediate stage: The * destination will contain _some_ multiple of the input point, but not * necessarily the desired one, which doesn't matter. As long as we're * multiplying (B1 phase) we simply carry on with the next multiplier. * During the B2 phase, the only additions are the giant steps, and the * worst that can happen here is that we lose one residue class mod 210 * of prime multipliers on 4 of the curves, so again, we ignore the problem * and just carry on.) * * Idea: select nbc curves mod N and one point P on each of them. For each * such P, compute [M]P = Q where M is the product of all powers <= B2 of * primes <= nextprime(B1). Then check whether [p]Q for p < nextprime(B2) * betrays a factor. This second stage looks separately at the primes in * each residue class mod 210, four curves at a time, and steps additively * to ever larger multipliers, by comparing X coordinates of points which we * would need to add in order to reach another prime multiplier in the same * residue class. 'Comparing' means that we accumulate a product of * differences of X coordinates, and from time to time take a gcd of this * product with N. Montgomery's multi-inverse trick is used heavily. */ /* *** auxiliary functions for ellfacteur: *** */ /* (Rx,Ry) <- (Px,Py)+(Qx,Qy) over Z/NZ, z=1/(Px-Qx). If Ry = NULL, don't set */ static void FpE_add_i(GEN N, GEN z, GEN Px, GEN Py, GEN Qx, GEN Qy, GEN *Rx, GEN *Ry) { GEN slope = modii(mulii(subii(Py, Qy), z), N); GEN t = subii(sqri(slope), addii(Qx, Px)); affii(modii(t, N), *Rx); if (Ry) { t = subii(mulii(slope, subii(Px, *Rx)), Py); affii(modii(t, N), *Ry); } } /* X -> Z; cannot add on one of the curves: make sure Z contains * something useful before letting caller proceed */ static void ZV_aff(long n, GEN *X, GEN *Z) { if (X != Z) { long k; for (k = n; k--; ) affii(X[k],Z[k]); } } /* Parallel addition on nbc curves, assigning the result to locations at and * following *X3, *Y3. (If Y-coords of result not desired, set Y=NULL.) * Safe even if (X3,Y3) = (X2,Y2), _not_ if (X1,Y1). It is also safe to * overwrite Y2 with X3. If nbc1 < nbc, the first summand is * assumed to hold only nbc1 distinct points, repeated as often as we need * them (to add one point on each of a few curves to several other points on * the same curves): only used with nbc1 = nbc or nbc1 = 4 | nbc. * * Return 0 [SUCCESS], 1 [N | den], 2 [gcd(den, N) is a factor of N, preserved * in gl. * Stack space is bounded by a constant multiple of lgefint(N)*nbc: * - Phase 2 creates 12 items on the stack per iteration, of which 4 are twice * as long and 1 is thrice as long as N, i.e. 18 units per iteration. * - Phase 1 creates 4 units. * Total can be as large as 4*nbcmax + 18*8 units; ecm_elladd2() is * just as bad, and elldouble() comes to 3*nbcmax + 29*8 units. */ static int ecm_elladd0(GEN N, GEN *gl, long nbc, long nbc1, GEN *X1, GEN *Y1, GEN *X2, GEN *Y2, GEN *X3, GEN *Y3) { const ulong mask = (nbc1 == 4)? 3: ~0UL; /*nbc1 = 4 or nbc*/ GEN W[2*nbcmax], *A = W+nbc; /* W[0],A[0] unused */ long i; pari_sp av = avma; W[1] = subii(X1[0], X2[0]); for (i=1; i copy Y2->Y3 */ ZV_aff(2*nbc, X5,X6); /* also copy Y5->Y6 */ return gc_int(av,1); } while (j--) /* nbc times */ { pari_sp av2 = avma; GEN Px = X4[j], Py = Y4[j], Qx = X5[j], Qy = Y5[j]; GEN z = mulii(*gl,W[--i]); /*1/(Px-Qx)*/ FpE_add_i(N,z, Px,Py, Qx,Qy, X6+j,Y6+j); set_avma(av2); *gl = modii(mulii(*gl, A[i]), N); } while (i--) /* nbc times */ { pari_sp av2 = avma; GEN Px = X1[i], Py = Y1[i], Qx = X2[i], Qy = Y2[i]; GEN z = i? mulii(*gl, W[i]): *gl; /*1/(Px-Qx)*/ FpE_add_i(N,z, Px,Py, Qx,Qy, X3+i,Y3+i); if (!i) break; set_avma(av2); *gl = modii(mulii(*gl, A[i]), N); } return gc_int(av,0); } /* Parallel doubling on nbc curves, assigning the result to locations at * and following *X2. Safe to be called with X2 equal to X1. Return * value as for ecm_elladd. If we find a point at infinity mod N, * and if X1 != X2, we copy the points at X1 to X2. */ static int elldouble(GEN N, GEN *gl, long nbc, GEN *X1, GEN *X2) { GEN *Y1 = X1+nbc, *Y2 = X2+nbc; GEN W[nbcmax+1]; /* W[0] unused */ long i; pari_sp av = avma; /*W[0] = gen_1;*/ W[1] = Y1[0]; for (i=1; iY2 */ return gc_int(av,1); } while (i--) /* nbc times */ { pari_sp av2; GEN v, w, L, z = i? mulii(*gl,W[i]): *gl; if (i) *gl = modii(mulii(*gl, Y1[i]), N); av2 = avma; L = modii(mulii(addui(1, mului(3, Fp_sqr(X1[i],N))), z), N); if (signe(L)) /* half of zero is still zero */ L = shifti(mod2(L)? addii(L, N): L, -1); v = modii(subii(sqri(L), shifti(X1[i],1)), N); w = modii(subii(mulii(L, subii(X1[i], v)), Y1[i]), N); affii(v, X2[i]); affii(w, Y2[i]); set_avma(av2); } return gc_int(av,0); } /* Parallel multiplication by an odd prime k on nbc curves, storing the * result to locations at and following *X2. Safe to be called with X2 = X1. * Return values as ecm_elladd. Uses (a simplified variant of) Montgomery's * PRAC algorithm; see ftp://ftp.cwi.nl/pub/pmontgom/Lucas.ps.gz . * With thanks to Paul Zimmermann for the reference. --GN1998Aug13 */ static int get_rule(ulong d, ulong e) { if (d <= e + (e>>2)) /* floor(1.25*e) */ { if ((d+e)%3 == 0) return 0; /* rule 1 */ if ((d-e)%6 == 0) return 1; /* rule 2 */ } /* d <= 4*e but no ofl */ if ((d+3)>>2 <= e) return 2; /* rule 3, common case */ if ((d&1)==(e&1)) return 1; /* rule 4 = rule 2 */ if (!(d&1)) return 3; /* rule 5 */ if (d%3 == 0) return 4; /* rule 6 */ if ((d+e)%3 == 0) return 5; /* rule 7 */ if ((d-e)%3 == 0) return 6; /* rule 8 */ /* when we get here, e is even, otherwise one of rules 4,5 would apply */ return 7; /* rule 9 */ } /* PRAC implementation notes - main changes against the paper version: * (1) The general function [m+n]P = f([m]P,[n]P,[m-n]P) collapses (for m!=n) * to an ecm_elladd() which does not depend on the third argument; thus * references to the third variable (C in the paper) can be eliminated. * (2) Since our multipliers are prime, the outer loop of the paper * version executes only once, and thus is invisible above. * (3) The first step in the inner loop of the paper version will always be * rule 3, but the addition requested by this rule amounts to a doubling, and * will always be followed by a swap, so we have unrolled this first iteration. * (4) Simplifications in rules 6 and 7 are possible given the above, and we * save one addition in each of the two cases. NB none of the other * ecm_elladd()s in the loop can ever degenerate into an elldouble. * (5) I tried to optimize for rule 3, which is used more frequently than all * others together, but it didn't improve things, so I removed the nested * tight loop again. --GN */ /* The main loop body of ellfacteur() runs _slower_ under PRAC than under a * straightforward left-shift binary multiplication when N has <30 digits and * B1 is small; PRAC wins when N and B1 get larger. Weird. --GN */ /* k>2 assumed prime, XAUX = scratchpad */ static int ellmult(GEN N, GEN *gl, long nbc, ulong k, GEN *X1, GEN *X2, GEN *XAUX) { ulong r, d, e, e1; int res; GEN *A = X2, *B = XAUX, *T = XAUX + 2*nbc; ZV_aff(2*nbc,X1,XAUX); /* first doubling picks up X1; after this we'll be working in XAUX and * X2 only, mostly via A and B and T */ if ((res = elldouble(N, gl, nbc, X1, X2)) != 0) return res; /* split the work at the golden ratio */ r = (ulong)(k*0.61803398875 + .5); d = k - r; e = r - d; /* d+e == r, so no danger of ofl below */ while (d != e) { /* apply one of the nine transformations from PM's Table 4. */ switch(get_rule(d,e)) { case 0: /* rule 1 */ if ( (res = ecm_elladd(N, gl, nbc, A, B, T)) ) return res; if ( (res = ecm_elladd2(N, gl, nbc, T, A, A, T, B, B)) != 0) return res; e1 = d - e; d = (d + e1)/3; e = (e - e1)/3; break; case 1: /* rules 2 and 4 */ if ( (res = ecm_elladd(N, gl, nbc, A, B, B)) ) return res; if ( (res = elldouble(N, gl, nbc, A, A)) ) return res; d = (d-e)>>1; break; case 3: /* rule 5 */ if ( (res = elldouble(N, gl, nbc, A, A)) ) return res; d >>= 1; break; case 4: /* rule 6 */ if ( (res = elldouble(N, gl, nbc, A, T)) ) return res; if ( (res = ecm_elladd(N, gl, nbc, T, A, A)) ) return res; if ( (res = ecm_elladd(N, gl, nbc, A, B, B)) ) return res; d = d/3 - e; break; case 2: /* rule 3 */ if ( (res = ecm_elladd(N, gl, nbc, A, B, B)) ) return res; d -= e; break; case 5: /* rule 7 */ if ( (res = elldouble(N, gl, nbc, A, T)) ) return res; if ( (res = ecm_elladd2(N, gl, nbc, T, A, A, T, B, B)) != 0) return res; d = (d - 2*e)/3; break; case 6: /* rule 8 */ if ( (res = ecm_elladd(N, gl, nbc, A, B, B)) ) return res; if ( (res = elldouble(N, gl, nbc, A, T)) ) return res; if ( (res = ecm_elladd(N, gl, nbc, T, A, A)) ) return res; d = (d - e)/3; break; case 7: /* rule 9 */ if ( (res = elldouble(N, gl, nbc, B, B)) ) return res; e >>= 1; break; } /* swap d <-> e and A <-> B if necessary */ if (d < e) { lswap(d,e); pswap(A,B); } } return ecm_elladd(N, gl, nbc, XAUX, X2, X2); } struct ECM { pari_timer T; long nbc, nbc2, seed; GEN *X, *XAUX, *XT, *XD, *XB, *XB2, *XH, *Xh, *Yh; }; /* memory layout in ellfacteur(): a large array of GEN pointers, and one * huge chunk of memory containing all the actual GEN (t_INT) objects. * nbc is constant throughout the invocation: * - The B1 stage of each iteration through the main loop needs little * space: enough for the X and Y coordinates of the current points, * and twice as much again as scratchpad for ellmult(). * - The B2 stage, starting from some current set of points Q, needs, in * succession: * + space for [2]Q, [4]Q, ..., [10]Q, and [p]Q for building the helix; * + space for 48*nbc X and Y coordinates to hold the helix. This could * re-use [2]Q,...,[8]Q, but only with difficulty, since we don't * know in advance which residue class mod 210 our p is going to be in. * It can and should re-use [p]Q, though; * + space for (temporarily [30]Q and then) [210]Q, [420]Q, and several * further doublings until the giant step multiplier is reached. This * can re-use the remaining cells from above. The computation of [210]Q * will have been the last call to ellmult() within this iteration of the * main loop, so the scratchpad is now also free to be re-used. We also * compute [630]Q by a parallel addition; we'll need it later to get the * baby-step table bootstrapped a little faster. * + Finally, for no more than 4 curves at a time, room for up to 1024 X * coordinates only: the Y coordinates needed whilst setting up this baby * step table are temporarily stored in the upper half, and overwritten * during the last series of additions. * * Graphically: after end of B1 stage (X,Y are the coords of Q): * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-- * | X Y | scratch | [2]Q| [4]Q| [6]Q| [8]Q|[10]Q| ... | ... * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-- * *X *XAUX *XT *XD *XB * * [30]Q is computed from [10]Q. [210]Q can go into XY, etc: * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-- * |[210]|[420]|[630]|[840]|[1680,3360,6720,...,2048*210] |bstp table... * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-- * *X *XAUX *XT *XD [*XG, somewhere here] *XB .... *XH * * So we need (13 + 48) * 2 * nbc slots here + 4096 slots for the baby step * table (not all of which will be used when we start with a small B1, but * better to allocate and initialize ahead of time all the slots that might * be needed later). * * Note on memory locality: During the B2 phase, accesses to the helix * (once it is set up) will be clustered by curves (4 out of nbc at a time). * Accesses to the baby steps table will wander from one end of the array to * the other and back, one such cycle per giant step, and during a full cycle * we would expect on the order of 2E4 accesses when using the largest giant * step size. Thus we shouldn't be doing too bad with respect to thrashing * a 512KBy L2 cache. However, we don't want the baby step table to grow * larger than this, even if it would reduce the number of EC operations by a * few more per cent for very large B2, lest cache thrashing slow down * everything disproportionally. --GN */ /* Auxiliary routines need < (3*nbc+240)*lN words on the PARI stack, in * addition to the spc*(lN+1) words occupied by our main table. */ static void ECM_alloc(struct ECM *E, long lN) { const long bstpmax = 1024; /* max number of baby step table entries */ long spc = (13 + 48) * E->nbc2 + bstpmax * 4; long len = spc + 385 + spc*lN; long i, tw = _evallg(lN) | evaltyp(t_INT); GEN w, *X = (GEN*)new_chunk(len); /* hack for X[i] = cgeti(lN). X = current point in B1 phase */ w = (GEN)(X + spc + 385); for (i = spc-1; i >= 0; i--) { X[i] = w; *w = tw; w += lN; } E->X = X; E->XAUX = E->X + E->nbc2; /* scratchpad for ellmult() */ E->XT = E->XAUX + E->nbc2; /* ditto, will later hold [3*210]Q */ E->XD = E->XT + E->nbc2; /* room for various multiples */ E->XB = E->XD + 10*E->nbc2; /* start of baby steps table */ E->XB2 = E->XB + 2 * bstpmax; /* middle of baby steps table */ E->XH = E->XB2 + 2 * bstpmax; /* end of bstps table, start of helix */ E->Xh = E->XH + 48*E->nbc2; /* little helix, X coords */ E->Yh = E->XH + 192; /* ditto, Y coords */ /* XG,YG set inside the main loop, since they depend on B2 */ /* E.Xh range of 384 pointers not set; these will later duplicate the pointers * in the E.XH range, 4 curves at a time. Some of the cells reserved here for * the E.XB range will never be used, instead, we'll warp the pointers to * connect to (read-only) GENs in the X/E.XD range */ } /* N.B. E->seed is not initialized here */ static void ECM_init(struct ECM *E, GEN N, long nbc) { if (nbc < 0) { /* choose a sensible default */ const long size = expi(N) + 1; nbc = ((size >> 3) << 2) - 80; if (nbc < 8) nbc = 8; } if (nbc > nbcmax) nbc = nbcmax; E->nbc = nbc; E->nbc2 = nbc << 1; ECM_alloc(E, lgefint(N)); } static GEN ECM_loop(struct ECM *E, GEN N, ulong B1) { const ulong B2 = 110 * B1, B2_rt = usqrt(B2); const ulong nbc = E->nbc, nbc2 = E->nbc2; pari_sp av1, avtmp; long i, np, np0, gse, gss, bstp, bstp0, rcn0, rcn; ulong B2_p, m, p, p0; GEN g, *XG, *YG; GEN *X = E->X, *XAUX = E->XAUX, *XT = E->XT, *XD = E->XD; GEN *XB = E->XB, *XB2 = E->XB2, *XH = E->XH, *Xh = E->Xh, *Yh = E->Yh; /* pick curves */ for (i = nbc2; i--; ) affui(E->seed++, X[i]); /* pick giant step exponent and size */ gse = B1 < 656 ? (B1 < 200? 5: 6) : (B1 < 10500 ? (B1 < 2625? 7: 8) : (B1 < 42000? 9: 10)); gss = 1UL << gse; /* With 32 baby steps, a giant step corresponds to 32*420 = 13440, * appropriate for the smallest B2s. With 1024, a giant step will be 430080; * appropriate for B1 >~ 42000, where 512 baby steps would imply roughly * the same number of curve additions. */ 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: B1 = %4lu,", timer_delay(&E->T), B1); err_printf("\tB2 = %6lu,\tgss = %4ld*420\n", B2, gss); } p = 2; np = 1; /* p is np-th prime */ /* ---B1 PHASE--- */ /* treat p=2 separately */ B2_p = B2 >> 1; for (m=1; m<=B2_p; m<<=1) { int fl = elldouble(N, &g, nbc, X, X); if (fl > 1) return g; else if (fl) break; } rcn = NPRC; /* multipliers begin at the beginning */ /* p=3,...,nextprime(B1) */ while (p < B1 && p <= B2_rt) { pari_sp av2 = avma; p = snextpr(p, &np, &rcn, NULL, uisprime); B2_p = B2/p; /* beware integer overflow on 32-bit CPUs */ for (m=1; m<=B2_p; m*=p) { int fl = ellmult(N, &g, nbc, p, X, X, XAUX); if (fl > 1) return g; else if (fl) break; set_avma(av2); } set_avma(av2); } /* primes p larger than sqrt(B2) appear only to the 1st power */ while (p < B1) { pari_sp av2 = avma; p = snextpr(p, &np, &rcn, NULL, uisprime); if (ellmult(N, &g, nbc, p, X, X, XAUX) > 1) return g; set_avma(av2); } if (DEBUGLEVEL >= 4) { err_printf("ECM: time = %6ld ms, B1 phase done, ", timer_delay(&E->T)); err_printf("p = %lu, setting up for B2\n", p); } /* ---B2 PHASE--- */ /* compute [2]Q,...,[10]Q, needed to build the helix */ if (elldouble(N, &g, nbc, X, XD) > 1) return g; /*[2]Q*/ if (elldouble(N, &g, nbc, XD, XD + nbc2) > 1) return g; /*[4]Q*/ if (ecm_elladd(N, &g, nbc, XD, XD + nbc2, XD + (nbc<<2)) > 1) return g; /* [6]Q */ if (ecm_elladd2(N, &g, nbc, XD, XD + (nbc<<2), XT + (nbc<<3), XD + nbc2, XD + (nbc<<2), XD + (nbc<<3)) > 1) return g; /* [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, &np, &rcn, NULL, uisprime); /* make sure we have the residue class number (mod 210) */ if (rcn == NPRC) { rcn = prc210_no[(p % 210) >> 1]; if (rcn == NPRC) { err_printf("ECM: %lu should have been prime but isn\'t\n", p); pari_err_BUG("ellfacteur"); } } /* compute [p]Q and put it into its place in the helix */ if (ellmult(N, &g, nbc, p, X, XH + rcn*nbc2, XAUX) > 1) return g; if (DEBUGLEVEL >= 7) err_printf("\t(got [p]Q, p = %lu = prc210_rp[%ld] mod 210)\n", p, rcn); /* save current p, np, and rcn; we'll need them more than once below */ p0 = p; np0 = np; rcn0 = rcn; bstp0 = 0; /* p is at baby-step offset 0 from itself */ /* fill up the helix, stepping forward through the prime residue classes * mod 210 until we're back at the r'class of p0. Keep updating p so * that we can print meaningful diagnostics if a factor shows up; don't * bother checking which of these p's are in fact prime */ for (i = 47; i; i--) /* 47 iterations */ { ulong dp = (ulong)prc210_d1[rcn]; p += dp; if (rcn == 47) { /* wrap mod 210 */ if (ecm_elladd(N, &g, nbc, XT+dp*nbc, XH+rcn*nbc2, XH) > 1) return g; rcn = 0; continue; } if (ecm_elladd(N, &g, nbc, XT+dp*nbc, XH+rcn*nbc2, XH+rcn*nbc2+nbc2) > 1) return g; rcn++; } if (DEBUGLEVEL >= 7) err_printf("\t(got initial helix)\n"); /* compute [210]Q etc, needed for the baby step table */ if (ellmult(N, &g, nbc, 3, XD + (nbc<<3), X, XAUX) > 1) return g; if (ellmult(N, &g, nbc, 7, X, X, XAUX) > 1) return g; /* [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, &g, nbc, X, XAUX) > 1) return g; /* [420]Q */ if (ecm_elladd(N, &g, nbc, X, XAUX, XT) > 1) return g;/*[630]Q*/ if (ecm_elladd(N, &g, nbc, X, XT, XD) > 1) return g; /*[840]Q*/ for (i=1; i <= gse; i++) if (elldouble(N, &g, nbc, XT + i*nbc2, XD + i*nbc2) > 1) return g; /* (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(&E->T), p); for (i = nbc - 4; i >= 0; i -= 4) { /* loop over small sets of 4 curves at a time */ GEN *Xb; long j, k; if (DEBUGLEVEL >= 6) err_printf("ECM: finishing curves %ld...%ld\n", i, i+3); /* Copy relevant pointers from XH to Xh. Memory layout in XH: * nbc X coordinates, nbc Y coordinates for residue class * 1 mod 210, then the same for r.c. 11 mod 210, etc. Memory layout for * Xh is: four X coords for 1 mod 210, four for 11 mod 210, ..., four * for 209 mod 210, then the corresponding Y coordinates in the same * order. This allows a giant step on Xh using just three calls to * ecm_elladd0() each acting on 64 points in parallel */ for (j = 48; j--; ) { k = nbc2*j + i; m = j << 2; /* X coordinates */ Xh[m] = XH[k]; Xh[m+1] = XH[k+1]; Xh[m+2] = XH[k+2]; Xh[m+3] = XH[k+3]; k += nbc; /* Y coordinates */ Yh[m] = XH[k]; Yh[m+1] = XH[k+1]; Yh[m+2] = XH[k+2]; Yh[m+3] = XH[k+3]; } /* Build baby step table of X coords of multiples of [210]Q. XB[4*j] * will point at X coords on four curves from [(j+1)*210]Q. Until * we're done, we need some Y coords as well, which we keep in the * second half of the table, overwriting them at the end when gse=10. * Multiples which we already have (by 1,2,3,4,8,16,...,2^gse) are * entered simply by copying the pointers, ignoring the few slots in w * that were initially reserved for them. Here are the initial entries */ for (Xb=XB,k=2,j=i; k--; Xb=XB2,j+=nbc) /* first X, then Y coords */ { Xb[0] = X[j]; Xb[1] = X[j+1]; /* [210]Q */ Xb[2] = X[j+2]; Xb[3] = X[j+3]; Xb[4] = XAUX[j]; Xb[5] = XAUX[j+1]; /* [420]Q */ Xb[6] = XAUX[j+2]; Xb[7] = XAUX[j+3]; Xb[8] = XT[j]; Xb[9] = XT[j+1]; /* [630]Q */ Xb[10] = XT[j+2]; Xb[11] = XT[j+3]; Xb += 4; /* points at [420]Q */ /* ... entries at powers of 2 times 210 .... */ for (m = 2; m < (ulong)gse+k; m++) /* omit Y coords of [2^gse*210]Q */ { long m2 = m*nbc2 + j; Xb += (2UL<= 7) err_printf("\t(extracted precomputed helix / baby step entries)\n"); /* ... glue in between, up to 16*210 ... */ if (ecm_elladd0(N, &g, 12, 4, /* 12 pts + (4 pts replicated thrice) */ XB + 12, XB2 + 12, XB, XB2, XB + 16, XB2 + 16) > 1) return g; /*4+{1,2,3} = {5,6,7}*/ if (ecm_elladd0(N, &g, 28, 4, /* 28 pts + (4 pts replicated 7fold) */ XB + 28, XB2 + 28, XB, XB2, XB + 32, XB2 + 32) > 1) return g;/*8+{1...7} = {9...15}*/ /* ... and the remainder of the lot */ for (m = 5; m <= (ulong)gse; m++) { /* fill in from 2^(m-1)+1 to 2^m-1 in chunks of 64 and 60 points */ ulong m2 = 2UL << m; /* will point at 2^(m-1)+1 */ for (j = 0; (ulong)j < m2-64; j+=64) /* executed 0 times when m = 5 */ { if (ecm_elladd0(N, &g, 64, 4, XB + m2-4, XB2 + m2-4, XB + j, XB2 + j, XB + m2+j, (m<(ulong)gse? XB2+m2+j: NULL)) > 1) return g; } /* j = m2-64 here, 60 points left */ if (ecm_elladd0(N, &g, 60, 4, XB + m2-4, XB2 + m2-4, XB + j, XB2 + j, XB + m2+j, (m<(ulong)gse? XB2+m2+j: NULL)) > 1) return g; /* 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; np = np0; rcn = rcn0; g = gen_1; av1 = avma; /* scratchspace for prod (x_i-x_j) */ avtmp = (pari_sp)new_chunk(8 * lgefint(N)); /* The correct entry in XB to use depends on bstp and on where we are * on the helix. As we skip from prime to prime, bstp is incremented * by snextpr each time we wrap around through residue class number 0 * (1 mod 210), but the baby step should not be taken until rcn>=rcn0, * i.e. until we pass again the residue class of p0. * * The correct signed multiplier is thus k = bstp - (rcn < rcn0), * and the offset from XB is four times (|k| - 1). When k=0, we ignore * the current prime: if it had led to a factorization, this * would have been noted during the last giant step, or -- when we * first get here -- whilst initializing the helix. When k > gss, * we must do a giant step and bump bstp back by -2*gss. * * The gcd of the product of X coord differences against N is taken just * before we do a giant step. */ while (p < B2) {/* loop over probable primes p0 < p <= nextprime(B2), inserting giant * steps as necessary */ p = snextpr(p, &np, &rcn, &bstp, uis2psp); /* next probable prime */ /* work out the corresponding baby-step multiplier */ k = bstp - (rcn < rcn0 ? 1 : 0); if (k > gss) { /* giant-step time, take gcd */ g = gcdii(g, N); if (!is_pm1(g) && !equalii(g, N)) return g; g = gen_1; set_avma(av1); while (k > gss) { /* giant step */ if (DEBUGLEVEL >= 7) err_printf("\t(giant step at p = %lu)\n", p); if (ecm_elladd0(N, &g, 64, 4, XG + i, YG + i, Xh, Yh, Xh, Yh) > 1) return g; if (ecm_elladd0(N, &g, 64, 4, XG + i, YG + i, Xh + 64, Yh + 64, Xh + 64, Yh + 64) > 1) return g; if (ecm_elladd0(N, &g, 64, 4, XG + i, YG + i, Xh + 128, Yh + 128, Xh + 128, Yh + 128) > 1) return g; 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; don't use set_avma */ g = modii(mulii(g, subii(XB[m], Xh[j])), N); g = modii(mulii(g, subii(XB[m+1], Xh[j+1])), N); g = modii(mulii(g, subii(XB[m+2], Xh[j+2])), N); g = mulii(g, subii(XB[m+3], Xh[j+3])); set_avma(av1); g = modii(g, N); } set_avma(av1); } return NULL; } /* ellfacteur() tuned to be useful as a first stage before MPQS, especially for * large arguments, when 'insist' is false, and now also for the case when * 'insist' is true, vaguely following suggestions by Paul Zimmermann * (http://www.loria.fr/~zimmerma/records/ecmnet.html). --GN 1998Jul,Aug */ static GEN ellfacteur(GEN N, int insist) { const long size = expi(N) + 1; pari_sp av = avma; struct ECM E; long nbc, dsn, dsnmax, rep = 0; if (insist) { const long DSNMAX = numberof(TB1)-1; dsnmax = (size >> 2) - 10; if (dsnmax < 0) dsnmax = 0; else if (dsnmax > DSNMAX) dsnmax = DSNMAX; E.seed = 1 + (nbcmax<<7)*(size&0xffff); /* seed for choice of curves */ dsn = (size >> 3) - 5; if (dsn < 0) dsn = 0; else if (dsn > 47) dsn = 47; /* pick up the torch where noninsistent stage would have given up */ nbc = dsn + (dsn >> 2) + 9; /* 8 or more curves in parallel */ nbc &= ~3; /* 4 | nbc */ } else { dsn = (size - 140) >> 3; if (dsn < 0) { #ifndef __EMX__ /* unless DOS/EMX: MPQS's disk access is abysmally slow */ if (DEBUGLEVEL >= 4) err_printf("ECM: number too small to justify this stage\n"); return NULL; /* too small, decline the task */ #endif dsn = 0; } else if (dsn > 12) dsn = 12; rep = (size <= 248 ? (size <= 176 ? (size - 124) >> 4 : (size - 148) >> 3) : (size - 224) >> 1); #ifdef __EMX__ /* DOS/EMX: extra rounds (shun MPQS) */ rep += 20; #endif dsnmax = 72; /* Use disjoint sets of curves for non-insist and insist phases; moreover, * repeated calls acting on factors of the same original number should try * to use fresh curves. The following achieves this */ E.seed = 1 + (nbcmax<<3)*(size & 0xf); nbc = -1; } ECM_init(&E, N, nbc); if (DEBUGLEVEL >= 4) { timer_start(&E.T); err_printf("ECM: working on %ld curves at a time; initializing", E.nbc); if (!insist) { if (rep == 1) err_printf(" for one round"); else err_printf(" for up to %ld rounds", rep); } err_printf("...\n"); } if (dsn > dsnmax) dsn = dsnmax; for(;;) { ulong B1 = insist? TB1[dsn]: TB1_for_stage[dsn]; GEN g = ECM_loop(&E, N, B1); if (g) { if (DEBUGLEVEL >= 4) err_printf("ECM: time = %6ld ms\n\tfound factor = %Ps\n", timer_delay(&E.T), g); return gerepilecopy(av, g); } if (dsn < dsnmax) { if (insist) dsn++; else { dsn += 2; if (dsn > dsnmax) dsn = dsnmax; } } if (!insist && !--rep) { if (DEBUGLEVEL >= 4) err_printf("ECM: time = %6ld ms,\tellfacteur giving up.\n", timer_delay(&E.T)); return gc_NULL(av); } } } /* assume rounds >= 1, seed >= 1, B1 <= ULONG_MAX / 110 */ GEN Z_ECM(GEN N, long rounds, long seed, ulong B1) { pari_sp av = avma; struct ECM E; long i; E.seed = seed; ECM_init(&E, N, -1); if (DEBUGLEVEL >= 4) timer_start(&E.T); for (i = rounds; i--; ) { GEN g = ECM_loop(&E, N, B1); if (g) return gerepilecopy(av, g); } return gc_NULL(av); } /***********************************************************************/ /** **/ /** FACTORIZATION (Pollard-Brent rho) --GN1998Jun18-26 **/ /** pollardbrent() returns a nontrivial factor of n, assuming n is **/ /** composite and has no small prime divisor, or NULL if going on **/ /** would take more time than we want to spend. Sometimes it finds **/ /** more than one factor, and returns a structure suitable for **/ /** interpretation by ifac_crack. (Cf Algo 8.5.2 in ACiCNT) **/ /** **/ /***********************************************************************/ #define VALUE(x) gel(x,0) #define EXPON(x) gel(x,1) #define CLASS(x) gel(x,2) INLINE void INIT(GEN x, GEN v, GEN e, GEN c) { VALUE(x) = v; EXPON(x) = e; CLASS(x) = c; } static void ifac_delete(GEN x) { INIT(x,NULL,NULL,NULL); } static void rho_dbg(pari_timer *T, long c, long msg_mask) { if (c & msg_mask) return; err_printf("Rho: time = %6ld ms,\t%3ld round%s\n", timer_delay(T), c, (c==1?"":"s")); } static void one_iter(GEN *x, GEN *P, GEN x1, GEN n, long delta) { *x = addis(remii(sqri(*x), n), delta); *P = modii(mulii(*P, subii(x1, *x)), n); } /* 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. Result * is not gerepile-able (contains NULL) */ static GEN pollardbrent_i(GEN n, long size, long c0, long retries) { long tf = lgefint(n), delta, msg_mask, c, k, k1, l; pari_sp av; GEN x, x1, y, P, g, g1, res; pari_timer T; if (DEBUGLEVEL >= 4) timer_start(&T); c = c0 << 5; /* 2^5 iterations per round */ msg_mask = (size >= 448? 0x1fff: (size >= 192? (256L<<((size-128)>>6))-1: 0xff)); y = cgeti(tf); x1= cgeti(tf); av = avma; 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); } x = gen_2; P = gen_1; g1 = NULL; k = 1; l = 1; affui(2, y); affui(2, x1); for (;;) /* terminated under the control of c */ { /* use the polynomial x^2 + delta */ one_iter(&x, &P, x1, n, delta); 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)); return NULL; } P = gen_1; if (DEBUGLEVEL >= 4) rho_dbg(&T, c0-(c>>5), msg_mask); affii(x,y); x = y; set_avma(av); } 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)); return NULL; } c &= ~0x1f; /* keep it on multiples of 32 */ /* Fast forward loop */ affii(x, x1); set_avma(av); 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); for (k1=k; k1; k1--) { one_iter(&x, &P, x1, n, delta); if ((k1 & 0x1f) == 0) gerepileall(av, 2, &x, &P); } 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)); affii(x,y); P = gerepileuptoint(av, P); x = y; } /* forever */ fin: /* An accumulated gcd was > 1 */ if (!equalii(g,n)) { /* if it isn't n, and looks prime, return it */ if (MR_Jaeschke(g)) { if (DEBUGLEVEL >= 4) { rho_dbg(&T, c0-(c>>5), 0); err_printf("\tfound factor = %Ps\n",g); } return g; } set_avma(av); g1 = icopy(g); /* known composite, keep it safe */ av = 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"); x = y; for(;;) { /* backtrack until period recovered. Must terminate */ x = addis(remii(sqri(x), g1), delta); g = gcdii(subii(x1, x), g1); if (!is_pm1(g)) break; if (DEBUGLEVEL >= 4 && (--c & 0x1f) == 0) rho_dbg(&T, c0-(c>>5), msg_mask); } 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"); } if (++retries >= 4) pari_err_BUG(""); 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); } res = cgetg(7, t_VEC); /* g^1: known composite when g1!=n */ INIT(res+1, 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, 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", gel(res,1), gel(res,4), gel(res,7)); } return res; } /* 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. */ static GEN pollardbrent(GEN n) { const long tune_pb_min = 14; /* even 15 seems too much. */ long c0, size = expi(n) + 1; 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 <= 96) return NULL; 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 */ return pollardbrent_i(n, size, c0, 0); } GEN Z_pollardbrent(GEN n, long rounds, long seed) { pari_sp av = avma; GEN v = pollardbrent_i(n, expi(n)+1, rounds, seed); if (!v) return NULL; if (typ(v) == t_INT) v = mkvec2(v, diviiexact(n,v)); else if (lg(v) == 7) v = mkvec2(gel(v,1), gel(v,4)); else v = mkvec3(gel(v,1), gel(v,4), gel(v,7)); return gerepilecopy(av, v); } /***********************************************************************/ /** 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, qa, qc, qcb, a0, b0, b1, c0; long cnt = 0; /* count reduction steps on the cycle */ q = (dd + (B>>1)) / a; qa = q * a; b = (qa - B) + qa; /* avoid overflow */ { pari_sp av = avma; c = itos(divis(shifti(subii(D, sqrs(b)), -2), a)); set_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 */ static 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 && uel(n,2) >= (1UL << 46))) #else /* 32 bits */ if (tf > 4 || (tf == 4 && (ulong)(*int_MSW(n)) >= (1UL << 17))) /* 49 */ #endif return NULL; /* n too large */ /* now we have 5 < n < 2^59 */ nm4 = mod4(n); if (nm4 == 1) { /* n = 1 (mod4): run one iteration on D1 = n, another on D2 = 5n */ D1 = n; D2 = mului(5,n); d2 = itou(sqrti(D2)); dd2 = (long)((d2>>1) + (d2&1)); b2 = (long)((d2-1) | 1); /* b1, b2 will always stay odd */ } else { /* n = 3 (mod4): run one iteration on D1 = 3n, another on D2 = 4n */ D1 = mului(3,n); D2 = shifti(n,2); dd2 = itou(sqrti(n)); d2 = dd2 << 1; b2 = (long)(d2 & (~1UL)); /* largest even below d2, will stay even */ } d1 = itou(sqrti(D1)); b1 = (long)((d1-1) | 1); /* largest odd number not exceeding d1 */ c1 = itos(shifti(subii(D1, sqru((ulong)b1)), -2)); if (!c1) pari_err_BUG("squfof [caller of] (n or 3n is a square)"); c2 = itos(shifti(subii(D2, sqru((ulong)b2)), -2)); if (!c2) pari_err_BUG("squfof [caller of] (5n is a square)"); L1 = (long)usqrt(d1); L2 = (long)usqrt(d2); /* dd1 used to compute floor((d1+b1)/2) as dd1+floor(b1/2), without * overflowing the 31bit signed integer size limit. Same for dd2. */ dd1 = (long) ((d1>>1) + (d1&1)); a1 = a2 = 1; /* The two (identity) forms (a1,b1,-c1) and (a2,b2,-c2) are now set up. * * a1 and c1 represent the absolute values of the a,c coefficients; we keep * track of the sign separately, via the iteration counter cnt: when cnt is * even, c is understood to be negative, else c is positive and a < 0. * * L1, L2 are the limits for blacklisting small leading coefficients * on the principal cycle, to guarantee that when we find a square form, * its square root will belong to an ambiguous cycle (i.e. won't be an * earlier form on the principal cycle). * * When n = 3(mod 4), D2 = 12(mod 16), and b^2 is always 0 or 4 mod 16. * It follows that 4*a*c must be 4 or 8 mod 16, respectively, so at most * one of a,c can be divisible by 2 at most to the first power. This fact * is used a couple of times below. * * The flags act1, act2 remain true while the respective cycle is still * active; we drop them to false when we return to the identity form with- * out having found a square form (or when the blacklist overflows, which * shouldn't happen). */ if (DEBUGLEVEL >= 4) err_printf("SQUFOF: entering main loop with forms\n" "\t(1, %ld, %ld) and (1, %ld, %ld)\n\tof discriminants\n" "\t%Ps and %Ps, respectively\n", b1, -c1, b2, -c2, D1, D2); /* MAIN LOOP: walk around the principal cycle looking for a square form. * Blacklist small leading coefficients. * * The reduction operator can be computed entirely in 32-bit arithmetic: * Let q = floor(floor((d1+b1)/2)/c1) (when c1>dd1, q=1, which happens * often enough to special-case it). Then the new b1 = (q*c1-b1) + q*c1, * which does not overflow, and the new c1 = a1 - q*(q*c1-b1), which is * bounded by d1 in abs size since both the old and the new a1 are positive * and bounded by d1. */ while (act1 || act2) { if (act1) { /* send first form through reduction operator if active */ c = c1; q = (c > dd1)? 1: (dd1 + (b1>>1)) / c; if (q == 1) { qcb = c - b1; b1 = c + qcb; c1 = a1 - qcb; } else { qc = q*c; qcb = qc - b1; b1 = qc + qcb; c1 = a1 - q*qcb; } a1 = c; if (a1 <= L1) { /* blacklist this */ if (blp1 >= SQUFOF_BLACKLIST_SZ) /* overflows: shouldn't happen */ act1 = 0; /* silently */ else { if (DEBUGLEVEL >= 6) err_printf("SQUFOF: blacklisting a = %ld on first cycle\n", a1); blacklist1[blp1++] = a1; } } } if (act2) { /* send second form through reduction operator if active */ c = c2; q = (c > dd2)? 1: (dd2 + (b2>>1)) / c; if (q == 1) { qcb = c - b2; b2 = c + qcb; c2 = a2 - qcb; } else { qc = q*c; qcb = qc - b2; b2 = qc + qcb; c2 = a2 - q*qcb; } a2 = c; if (a2 <= L2) { /* blacklist this */ if (blp2 >= SQUFOF_BLACKLIST_SZ) /* overflows: shouldn't happen */ act2 = 0; /* silently */ else { if (DEBUGLEVEL >= 6) err_printf("SQUFOF: blacklisting a = %ld on second cycle\n", a2); blacklist2[blp2++] = a2; } } } /* bump counter, loop if this is an odd iteration (i.e. if the real * leading coefficients are negative) */ if (++cnt & 1) continue; /* second half of main loop entered only when the leading coefficients * are positive (i.e., during even-numbered iterations) */ /* examine first form if active */ if (act1 && a1 == 1) /* back to identity */ { /* drop this discriminant */ act1 = 0; if (DEBUGLEVEL >= 4) err_printf("SQUFOF: first cycle exhausted after %ld iterations,\n" "\tdropping it\n", cnt); } if (act1) { if (uissquareall((ulong)a1, (ulong*)&a)) { /* square form */ if (DEBUGLEVEL >= 4) err_printf("SQUFOF: square form (%ld^2, %ld, %ld) on first cycle\n" "\tafter %ld iterations\n", a, b1, -c1, cnt); if (a <= L1) { /* blacklisted? */ long j; for (j = 0; j < blp1; j++) if (a == blacklist1[j]) { a = 0; break; } } if (a > 0) { /* not blacklisted */ q = ugcd(a, b1); /* imprimitive form? */ if (q > 1) { /* q^2 divides D1 hence n [ assuming n % 3 != 0 ] */ set_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) return gc_utoipos(av, 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 ] */ set_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) return gc_utoipos(av, 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"); return gc_NULL(av); } /***********************************************************************/ /* DETECTING ODD POWERS --GN1998Jun28 */ /* Factoring engines like MPQS which ultimately rely on computing */ /* gcd(N, x^2-y^2) to find a nontrivial factor of N can't split */ /* N = p^k for an odd prime p, since (Z/p^k)^* is then cyclic. Here */ /* is an analogue of Z_issquareall() for 3rd, 5th and 7th powers. */ /* The general case is handled by is_kth_power */ /***********************************************************************/ /* Multistage sieve. First stages work mod 211, 209, 61, 203 in this order * (first reduce mod the product of these and then take the remainder apart). * Second stages use 117, 31, 43, 71. Moduli which are no longer interesting * are skipped. Everything is encoded in a table of 106 24-bit masks. We only * need the first half of the residues. Three bits per modulus indicate which * residues are 7th (bit 2), 5th (bit 1) or 3rd (bit 0) powers; the eight * moduli above are assigned right-to-left. The table was generated using: */ #if 0 L = [71, 43, 31, [O(3^2),O(13)], [O(7),O(29)], 61, [O(11),O(19)], 211]; ispow(x, N, k)= { if (type(N) == "t_INT", return (ispower(Mod(x,N), k))); for (i = 1, #N, if (!ispower(x + N[i], k), return (0))); 1 } check(r) = { print1(" 0"); for (i=1,#L, N = 0; if (ispow(r, L[i], 3), N += 1); if (ispow(r, L[i], 5), N += 2); if (ispow(r, L[i], 7), N += 4); print1(N); ); print("ul, /* ", r, " */") } for (r = 0, 105, check(r)) #endif static ulong powersmod[106] = { 077777777ul, /* 0 */ 077777777ul, /* 1 */ 013562440ul, /* 2 */ 012402540ul, /* 3 */ 013562440ul, /* 4 */ 052662441ul, /* 5 */ 016603440ul, /* 6 */ 016463450ul, /* 7 */ 013573551ul, /* 8 */ 012462540ul, /* 9 */ 012462464ul, /* 10 */ 013462771ul, /* 11 */ 012406473ul, /* 12 */ 012463641ul, /* 13 */ 052463646ul, /* 14 */ 012503446ul, /* 15 */ 013562440ul, /* 16 */ 052466440ul, /* 17 */ 012472451ul, /* 18 */ 012462454ul, /* 19 */ 032463550ul, /* 20 */ 013403664ul, /* 21 */ 013463460ul, /* 22 */ 032562565ul, /* 23 */ 012402540ul, /* 24 */ 052662441ul, /* 25 */ 032672452ul, /* 26 */ 013573551ul, /* 27 */ 012467541ul, /* 28 */ 012567640ul, /* 29 */ 032706450ul, /* 30 */ 012762452ul, /* 31 */ 033762662ul, /* 32 */ 012502562ul, /* 33 */ 032463562ul, /* 34 */ 013563440ul, /* 35 */ 016663440ul, /* 36 */ 036662550ul, /* 37 */ 012462552ul, /* 38 */ 033502450ul, /* 39 */ 012462643ul, /* 40 */ 033467540ul, /* 41 */ 017403441ul, /* 42 */ 017463462ul, /* 43 */ 017472460ul, /* 44 */ 033462470ul, /* 45 */ 052566450ul, /* 46 */ 013562640ul, /* 47 */ 032403640ul, /* 48 */ 016463450ul, /* 49 */ 016463752ul, /* 50 */ 033402440ul, /* 51 */ 012462540ul, /* 52 */ 012472540ul, /* 53 */ 053562462ul, /* 54 */ 012463465ul, /* 55 */ 012663470ul, /* 56 */ 052607450ul, /* 57 */ 012566553ul, /* 58 */ 013466440ul, /* 59 */ 012502741ul, /* 60 */ 012762744ul, /* 61 */ 012763740ul, /* 62 */ 012763443ul, /* 63 */ 013573551ul, /* 64 */ 013462471ul, /* 65 */ 052502460ul, /* 66 */ 012662463ul, /* 67 */ 012662451ul, /* 68 */ 012403550ul, /* 69 */ 073567540ul, /* 70 */ 072463445ul, /* 71 */ 072462740ul, /* 72 */ 012472442ul, /* 73 */ 012462644ul, /* 74 */ 013406650ul, /* 75 */ 052463471ul, /* 76 */ 012563474ul, /* 77 */ 013503460ul, /* 78 */ 016462441ul, /* 79 */ 016462440ul, /* 80 */ 012462540ul, /* 81 */ 013462641ul, /* 82 */ 012463454ul, /* 83 */ 013403550ul, /* 84 */ 057563540ul, /* 85 */ 017466441ul, /* 86 */ 017606471ul, /* 87 */ 053666573ul, /* 88 */ 012562561ul, /* 89 */ 013473641ul, /* 90 */ 032573440ul, /* 91 */ 016763440ul, /* 92 */ 016702640ul, /* 93 */ 033762552ul, /* 94 */ 012562550ul, /* 95 */ 052402451ul, /* 96 */ 033563441ul, /* 97 */ 012663561ul, /* 98 */ 012677560ul, /* 99 */ 012462464ul, /* 100 */ 032562642ul, /* 101 */ 013402551ul, /* 102 */ 032462450ul, /* 103 */ 012467445ul, /* 104 */ 032403440ul, /* 105 */ }; static int check_res(ulong x, ulong N, int shift, ulong *mask) { long r = x%N; if ((ulong)r> (N>>1)) r = N - r; *mask &= (powersmod[r] >> shift); return *mask; } /* is x mod 211*209*61*203*117*31*43*71 a 3rd, 5th or 7th power ? */ int uis_357_powermod(ulong x, ulong *mask) { if ( !check_res(x, 211UL, 0, mask)) return 0; if (*mask & 3 && !check_res(x, 209UL, 3, mask)) return 0; if (*mask & 3 && !check_res(x, 61UL, 6, mask)) return 0; if (*mask & 5 && !check_res(x, 203UL, 9, mask)) return 0; if (*mask & 1 && !check_res(x, 117UL,12, mask)) return 0; if (*mask & 3 && !check_res(x, 31UL,15, mask)) return 0; if (*mask & 5 && !check_res(x, 43UL,18, mask)) return 0; if (*mask & 6 && !check_res(x, 71UL,21, mask)) return 0; return 1; } /* asume x > 0 and pt != NULL */ int uis_357_power(ulong x, ulong *pt, ulong *mask) { double logx; if (!odd(x)) { long v = vals(x); if (v % 7) *mask &= ~4; if (v % 5) *mask &= ~2; if (v % 3) *mask &= ~1; if (!*mask) return 0; } if (!uis_357_powermod(x, mask)) return 0; logx = log((double)x); while (*mask) { long e, b; ulong y, ye; if (*mask & 1) { b = 1; e = 3; } else if (*mask & 2) { b = 2; e = 5; } else { b = 4; e = 7; } y = (ulong)(exp(logx / e) + 0.5); ye = upowuu(y,e); if (ye == x) { *pt = y; return e; } #ifdef LONG_IS_64BIT if (ye > x) y--; else y++; ye = upowuu(y,e); if (ye == x) { *pt = y; return e; } #endif *mask &= ~b; /* turn the bit off */ } return 0; } #ifndef LONG_IS_64BIT /* as above, split in two functions */ /* is x mod 211*209*61*203 a 3rd, 5th or 7th power ? */ static int uis_357_powermod_32bit_1(ulong x, ulong *mask) { if ( !check_res(x, 211UL, 0, mask)) return 0; if (*mask & 3 && !check_res(x, 209UL, 3, mask)) return 0; if (*mask & 3 && !check_res(x, 61UL, 6, mask)) return 0; if (*mask & 5 && !check_res(x, 203UL, 9, mask)) return 0; return 1; } /* is x mod 117*31*43*71 a 3rd, 5th or 7th power ? */ static int uis_357_powermod_32bit_2(ulong x, ulong *mask) { if (*mask & 1 && !check_res(x, 117UL,12, mask)) return 0; if (*mask & 3 && !check_res(x, 31UL,15, mask)) return 0; if (*mask & 5 && !check_res(x, 43UL,18, mask)) return 0; if (*mask & 6 && !check_res(x, 71UL,21, mask)) return 0; return 1; } #endif /* Returns 3, 5, or 7 if x is a cube (but not a 5th or 7th power), a 5th * power (but not a 7th), or a 7th power, and in this case creates the * base on the stack and assigns its address to *pt. Otherwise returns 0. * x must be of type t_INT and positive; this is not checked. The *mask * argument tells us which things to check -- bit 0: 3rd, bit 1: 5th, * bit 2: 7th pwr; set a bit to have the corresponding power examined -- * and is updated appropriately for a possible follow-up call */ int is_357_power(GEN x, GEN *pt, ulong *mask) { long lx = lgefint(x); ulong r; pari_sp av; GEN y; if (!*mask) return 0; /* useful when running in a loop */ if (DEBUGLEVEL>4) err_printf("OddPwrs: examining %ld-bit integer\n", expi(x)+1); if (lgefint(x) == 3) { ulong t; long e = uis_357_power(x[2], &t, mask); if (e) { if (pt) *pt = utoi(t); return e; } return 0; } #ifdef LONG_IS_64BIT r = (lx == 3)? uel(x,2): umodiu(x, 6046846918939827UL); if (!uis_357_powermod(r, mask)) return 0; #else r = (lx == 3)? uel(x,2): umodiu(x, 211*209*61*203); if (!uis_357_powermod_32bit_1(r, mask)) return 0; r = (lx == 3)? uel(x,2): umodiu(x, 117*31*43*71); if (!uis_357_powermod_32bit_2(r, mask)) return 0; #endif av = avma; while (*mask) { long e, b; /* priority to higher powers: if we have a 21st, it is easier to rediscover * that its 7th root is a cube than that its cube root is a 7th power */ if (*mask & 4) { b = 4; e = 7; } else if (*mask & 2) { b = 2; e = 5; } else { b = 1; e = 3; } y = mpround( sqrtnr(itor(x, nbits2prec(64 + bit_accuracy(lx) / e)), e) ); if (equalii(powiu(y,e), x)) { if (!pt) return gc_int(av,e); set_avma((pari_sp)y); *pt = gerepileuptoint(av, y); return e; } *mask &= ~b; /* turn the bit off */ set_avma(av); } return 0; } /* Is x a n-th power ? If pt != NULL, it receives the n-th root */ ulong is_kth_power(GEN x, ulong n, GEN *pt) { forprime_t T; long j; ulong q, residue; GEN y; pari_sp av = avma; (void)u_forprime_arith_init(&T, odd(n)? 2*n+1: n+1, ULONG_MAX, 1,n); /* we'll start at q, smallest prime >= n */ /* Modular checks, use small primes q congruent 1 mod n */ /* A non n-th power nevertheless passes the test with proba n^(-#checks), * We'd like this < 1e-6 but let j = floor(log(1e-6) / log(n)) which * ensures much less. */ if (n < 16) j = 5; else if (n < 32) j = 4; else if (n < 101) j = 3; else if (n < 1001) j = 2; else if (n < 17886697) /* smallest such that smallest suitable q is > 2^32 */ j = 1; else j = 0; for (; j > 0; j--) { if (!(q = u_forprime_next(&T))) break; /* q a prime = 1 mod n */ residue = umodiu(x, q); if (residue == 0) { if (Z_lval(x,q) % n) return gc_ulong(av,0); continue; } /* n-th power mod q ? */ if (Fl_powu(residue, (q-1)/n, q) != 1) return gc_ulong(av,0); } set_avma(av); if (DEBUGLEVEL>4) err_printf("\nOddPwrs: [%lu] passed modular checks\n",n); /* go to the horse's mouth... */ y = roundr( sqrtnr(itor(x, nbits2prec(expi(x)/n + 16)), n) ); if (!equalii(powiu(y, n), x)) { if (DEBUGLEVEL>4) err_printf("\tBut it wasn't a pure power.\n"); return gc_ulong(av,0); } if (!pt) set_avma(av); else { set_avma((pari_sp)y); *pt = gerepileuptoint(av,y); } return 1; } /* is x a p^i-th power, p >= 11 prime ? Similar to is_357_power(), but instead * of the mask, we keep the current test exponent around. Cut off when * log_2 x^(1/k) < cutoffbits since we would have found it by trial division. * Everything needed here (primitive roots etc.) is computed from scratch on * the fly; compared to the size of numbers under consideration, these * word-sized computations take negligible time. * Any cutoffbits > 0 is safe, but direct root extraction attempts are faster * when trial division has been used to discover very small bases. We become * competitive at cutoffbits ~ 10 */ int is_pth_power(GEN x, GEN *pt, forprime_t *T, ulong cutoffbits) { long cnt=0, size = expi(x) /* not +1 */; ulong p; pari_sp av = avma; while ((p = u_forprime_next(T)) && size/p >= cutoffbits) { long v = 1; if (DEBUGLEVEL>5 && cnt++==2000) { cnt=0; err_printf("%lu%% ", 100*p*cutoffbits/size); } while (is_kth_power(x, p, pt)) { v *= p; x = *pt; size = expi(x); } if (v > 1) { if (DEBUGLEVEL>5) err_printf("\nOddPwrs: is a %ld power\n",v); return v; } } if (DEBUGLEVEL>5) err_printf("\nOddPwrs: not a power\n",p); return gc_int(av,0); /* give up */ } /***********************************************************************/ /** FACTORIZATION (master iteration) **/ /** Driver for the various methods of finding large factors **/ /** (after trial division has cast out the very small ones). **/ /** GN1998Jun24--30 **/ /***********************************************************************/ /* Direct use: * ifac_start_hint(n,moebius,hint) registers with the iterative factorizer * - an integer n (without prime factors < tridiv_bound(n)) * - registers whether or not we should terminate early if we find a square * factor, * - a hint about which method(s) to use. * This must always be called first. If input is not composite, oo loop. * The routine decomposes n nontrivially into a product of two factors except * in squarefreeness ('Moebius') mode. * * ifac_start(n,moebius) same using default hint. * * ifac_primary_factor() returns a prime divisor (not necessarily the * smallest) and the corresponding exponent. * * Encapsulated user interface: Many arithmetic functions have a 'contributor' * ifac_xxx, to be called on any large composite cofactor left over after trial * division by small primes: xxx is one of moebius, issquarefree, totient, etc. * * We never test whether the input number is prime or composite, since * presumably it will have come out of the small factors finder stage * (which doesn't really exist yet but which will test the left-over * cofactor for primality once it does). */ /* The data structure in which we preserve whatever we know about our number N * is kept on the PARI stack, and updated as needed. * This makes the machinery re-entrant, and avoids memory leaks when a lengthy * factorization is interrupted. We try to keep the whole affair connected, * and the parent object is always older than its children. This may in * rare cases lead to some extra copying around, and knowing what is garbage * at any given time is not trivial. See below for examples how to do it right. * (Connectedness is destroyed if callers of ifac_main() create stuff on the * stack in between calls. This is harmless as long as ifac_realloc() is used * to re-create a connected object at the head of the stack just before * collecting garbage.) * A t_INT may well have > 10^6 distinct prime factors larger than 2^16. Since * we need not find factors in order of increasing size, we must be prepared to * drag a very large amount of data around. We start with a small structure * and extend it when necessary. */ /* The idea of the algorithm is: * Let N0 be whatever is currently left of N after dividing off all the * prime powers we have already returned to the caller. Then we maintain * N0 as a product * (1) N0 = \prod_i P_i^{e_i} * \prod_j Q_j^{f_j} * \prod_k C_k^{g_k} * where the P_i and Q_j are distinct primes, each C_k is known composite, * none of the P_i divides any C_k, and we also know the total ordering * of all the P_i, Q_j and C_k; in particular, we will never try to divide * a C_k by a larger Q_j. Some of the C_k may have common factors. * * Caveat implementor: Taking gcds among C_k's is very likely to cost at * least as much time as dividing off any primes as we find them, and book- * keeping would be tough (since D=gcd(C_1,C_2) can still have common factors * with both C_1/D and C_2/D, and so on...). * * At startup, we just initialize the structure to * (2) N = C_1^1 (composite). * * Whenever ifac_primary_factor() or one of the arithmetic user interface * routines needs a primary factor, and the smallest thing in our list is P_1, * we return that and its exponent, and remove it from our list. (When nothing * is left, we return a sentinel value -- gen_1. And in Moebius mode, when we * see something with exponent > 1, whether prime or composite, we return gen_0 * or 0, depending on the function). In all other cases, ifac_main() iterates * the following steps until we have a P_1 in the smallest position. * * When the smallest item is C_1, as it is initially: * (3.1) Crack C_1 into a nontrivial product U_1 * U_2 by whatever method * comes to mind for this size. (U for 'unknown'.) Cracking will detect * perfect powers, so we may instead see a power of some U_1 here, or even * something of the form U_1^k*U_2^k; of course the exponent already attached * to C_1 is taken into account in the following. * (3.2) If we have U_1*U_2, sort the two factors (distinct: squares are caught * in stage 3.1). N.B. U_1 and U_2 are smaller than anything else in our list. * (3.3) Check U_1 and U_2 for primality, and flag them accordingly. * (3.4) Iterate. * * When the smallest item is Q_1: * This is the unpleasant case. We go through the entire list and try to * divide Q_1 off each of the current C_k's, which usually fails, but may * succeed several times. When a division was successful, the corresponding * C_k is removed from our list, and the cofactor becomes a U_l for the moment * unless it is 1 (which happens when C_k was a power of Q_1). When we're * through we upgrade Q_1 to P_1 status, then do a primality check on each U_l * and sort it back into the list either as a Q_j or as a C_k. If during the * insertion sort we discover that some U_l equals some P_i or Q_j or C_k we * already have, we just add U_l's exponent to that of its twin. (The sorting * therefore happens before the primality test). Since this may produce one or * more elements smaller than the P_1 we just confirmed, we may have to repeat * the iteration. * A trick avoids some Q_1 instances: just after the sweep classifying * all current unknowns as either composites or primes, we do another downward * sweep beginning with the largest current factor and stopping just above the * largest current composite. Every Q_j we pass is turned into a P_i. * (Different primes are automatically coprime among each other, and primes do * not divide smaller composites.) * NB: We have no use for comparing the square of a prime to N0. Normally * we will get called after casting out only the smallest primes, and * since we cannot guarantee that we see the large prime factors in as- * cending order, we cannot stop when we find one larger than sqrt(N0). */ /* Data structure: We keep everything in a single t_VEC of t_INTs. The * first 2 components are read-only: * 1) the first records whether we're doing full (NULL) or Moebius (gen_1) * factorization; in the latter case subroutines return a sentinel value as * soon as they spot an exponent > 1. * 2) the second records the hint from factorint()'s optional flag, for use by * ifac_crack(). * * The remaining components (initially 15) are used in groups of three: * [ factor (t_INT), exponent (t_INT), factor class ], where factor class is * NULL : unknown * gen_0: known composite C_k * gen_1: known prime Q_j awaiting trial division * gen_2: finished prime P_i. * When during the division stage we re-sort a C_k-turned-U_l to a lower * position, we rotate any intervening material upward towards its old * slot. When a C_k was divided down to 1, its slot is left empty at * first; similarly when the re-sorting detects a repeated factor. * After the sorting phase, we de-fragment the list and squeeze all the * occupied slots together to the high end, so that ifac_crack() has room * for new factors. When this doesn't suffice, we abandon the current vector * and allocate a somewhat larger one, defragmenting again while copying. * * For internal use: note that all exponents will fit into C longs, given * PARI's lgefint field size. When we work with them, we sometimes read * out the GEN pointer, and sometimes do an itos, whatever is more con- * venient for the task at hand. */ /*** Overview ***/ /* The '*where' argument in the following points into *partial at the first of * the three fields of the first occupied slot. It's there because the caller * would already know where 'here' is, so we don't want to search for it again. * We do not preserve this from one user-interface call to the next. */ /* In the most 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) /* y <- x */ INLINE void SHALLOWCOPY(GEN x, GEN y) { VALUE(y) = VALUE(x); EXPON(y) = EXPON(x); CLASS(y) = CLASS(x); } /* y <- x */ INLINE void COPY(GEN x, GEN y) { icopyifstack(VALUE(x), VALUE(y)); icopyifstack(EXPON(x), EXPON(y)); CLASS(y) = CLASS(x); } /* Diagnostics */ static void ifac_factor_dbg(GEN x) { GEN c = CLASS(x), v = VALUE(x); if (c == gen_2) err_printf("IFAC: factor %Ps\n\tis prime (finished)\n", v); else if (c == gen_1) err_printf("IFAC: factor %Ps\n\tis prime\n", v); else if (c == gen_0) err_printf("IFAC: factor %Ps\n\tis composite\n", v); } static void ifac_check(GEN partial, GEN where) { if (!where || where < FIRST(partial) || where > LAST(partial)) pari_err_BUG("ifac_check ['where' out of bounds]"); } static void ifac_print(GEN part, GEN where) { long l = lg(part); GEN p; err_printf("ifac partial factorization structure: %ld slots, ", (l-3)/3); if (MOEBIUS(part)) err_printf("Moebius mode, "); err_printf("hint = %ld\n", itos(HINT(part))); ifac_check(part, where); for (p = part+3; p < part + l; p += 3) { GEN v = VALUE(p), e = EXPON(p), c = CLASS(p); const char *s = ""; if (!v) { err_printf("[empty slot]\n"); continue; } if (c == NULL) s = "unknown"; else if (c == gen_0) s = "composite"; else if (c == gen_1) s = "unfinished prime"; else if (c == gen_2) s = "prime"; else pari_err_BUG("unknown factor class"); err_printf("[%Ps, %Ps, %s]\n", v, e, s); } err_printf("Done.\n"); } static const long decomp_default_hint = 0; /* assume n > 0, which we can assign to */ /* 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); /* fill first slot at the top end */ here = part + ifac_initial_length - 3; /* LAST(part) */ INIT(here, n,gen_1,gen_0); /* n^1: composite */ while ((here -= 3) > part) ifac_delete(here); return part; } GEN ifac_start(GEN n, int moebius) { return ifac_start_hint(n,moebius,decomp_default_hint); } /* Return next nonempty slot after 'here', NULL if none exist */ static GEN ifac_find(GEN partial) { GEN scan, end = partial + lg(partial); #ifdef IFAC_DEBUG ifac_check(partial, partial); #endif for (scan = partial+3; scan < end; scan += 3) if (VALUE(scan)) return scan; return NULL; } /* Defragment: squeeze out unoccupied slots above *where. Unoccupied slots * arise when a composite factor dissolves completely whilst dividing off a * prime, or when ifac_resort() spots a coincidence and merges two factors. * Update *where */ static void ifac_defrag(GEN *partial, GEN *where) { GEN scan_new = LAST(*partial), scan_old; for (scan_old = scan_new; scan_old >= *where; scan_old -= 3) { if (!VALUE(scan_old)) continue; /* empty slot */ if (scan_old < scan_new) SHALLOWCOPY(scan_old, scan_new); scan_new -= 3; /* point at next slot to be written */ } scan_new += 3; /* back up to last slot written */ *where = scan_new; while ((scan_new -= 3) > *partial) ifac_delete(scan_new); /* erase junk */ } /* Move to a larger main vector, updating *where if it points into it, and * *partial in any case. Can be used as a specialized gcopy before * a gerepileupto() (pass 0 as the new length). Normally, one would pass * new_lg=1 to let this function guess the new size. To be used sparingly. * Complex version of ifac_defrag(), combined with reallocation. If new_lg * is 0, use the old length, so this acts just like gcopy except that the * 'where' pointer is carried along; if it is 1, we make an educated guess. * Exception: If new_lg is 0, the vector is full to the brim, and the first * entry is composite, we make it longer to avoid being called again a * microsecond later. It is safe to call this with *where = NULL: * if it doesn't point anywhere within the old structure, it is left alone */ static void ifac_realloc(GEN *partial, GEN *where, long new_lg) { long old_lg = lg(*partial); GEN newpart, scan_new, scan_old; if (new_lg == 1) new_lg = 2*old_lg - 6; /* from 7 slots to 13 to 25... */ else if (new_lg <= old_lg) /* includes case new_lg == 0 */ { GEN first = *partial + 3; new_lg = old_lg; /* structure full and first entry composite or unknown */ if (VALUE(first) && (CLASS(first) == gen_0 || CLASS(first)==NULL)) new_lg += 6; /* give it a little more breathing space */ } newpart = cgetg(new_lg, t_VEC); if (DEBUGMEM >= 3) err_printf("IFAC: new partial factorization structure (%ld slots)\n", (new_lg - 3)/3); MOEBIUS(newpart) = MOEBIUS(*partial); icopyifstack(HINT(*partial), HINT(newpart)); /* Downward sweep through the old *partial. Pick up 'where' and carry it * over if we pass it. (Only useful if it pointed at a nonempty slot.) * Factors are COPY'd so that we again have a nice object (parent older * than children, connected), except the one factor that may still be living * in a clone where n originally was; exponents are similarly copied if they * aren't global constants; class-of-factor fields are global constants so we * need only copy them as pointers. Caller may then do a gerepileupto() */ scan_new = newpart + new_lg - 3; /* LAST(newpart) */ scan_old = *partial + old_lg - 3; /* LAST(*partial) */ for (; scan_old > *partial + 2; scan_old -= 3) { if (*where == scan_old) *where = scan_new; if (!VALUE(scan_old)) continue; /* skip empty slots */ COPY(scan_old, scan_new); scan_new -= 3; } scan_new += 3; /* back up to last slot written */ while ((scan_new -= 3) > newpart) ifac_delete(scan_new); *partial = newpart; } /* Re-sort one (typically unknown) entry from washere to a new position, * rotating intervening entries upward to fill the vacant space. If the new * position is the same as the old one, or the new value of the entry coincides * with a value already occupying a lower slot, then we just add exponents (and * use the 'more known' class, and return 1 immediately when in Moebius mode). * Slots between *where and washere must be in sorted order, so a sweep using * this to re-sort several unknowns must proceed upward, see ifac_resort(). * Bubble-sort-of-thing sort. Won't be exercised frequently, so this is ok */ static void ifac_sort_one(GEN *where, GEN washere) { GEN old, scan = washere - 3; GEN value, exponent, class0, class1; long cmp_res; if (scan < *where) return; /* nothing to do, washere==*where */ value = VALUE(washere); exponent = EXPON(washere); class0 = CLASS(washere); cmp_res = -1; /* sentinel */ while (scan >= *where) /* at least once */ { if (VALUE(scan)) { /* current slot nonempty, check against where */ cmp_res = cmpii(value, VALUE(scan)); if (cmp_res >= 0) break; /* have found where to stop */ } /* copy current slot upward by one position and move pointers down */ SHALLOWCOPY(scan, scan+3); scan -= 3; } scan += 3; /* At this point there are the following possibilities: * 1) cmp_res == -1. Either value is less than that at *where, or *where was * pointing at vacant slots and any factors we saw en route were larger than * value. At any rate, scan == *where now, and scan is pointing at an empty * slot, into which we'll stash our entry. * 2) cmp_res == 0. The entry at scan-3 is the one, we compare class0 * fields and add exponents, and put it all into the vacated scan slot, * NULLing the one at scan-3 (and possibly updating *where). * 3) cmp_res == 1. The slot at scan is the one to store our entry into. */ if (cmp_res) { if (cmp_res < 0 && scan != *where) pari_err_BUG("ifact_sort_one [misaligned partial]"); INIT(scan, value, exponent, class0); return; } /* case cmp_res == 0: repeated factor detected */ if (DEBUGLEVEL >= 4) err_printf("IFAC: repeated factor %Ps\n\tin ifac_sort_one\n", value); old = scan - 3; /* if old class0 was composite and new is prime, or vice versa, complain * (and if one class0 was unknown and the other wasn't, use the known one) */ class1 = CLASS(old); if (class0) /* should never be used */ { if (class1) { if (class0 == gen_0 && class1 != gen_0) pari_err_BUG("ifac_sort_one (composite = prime)"); else if (class0 != gen_0 && class1 == gen_0) pari_err_BUG("ifac_sort_one (prime = composite)"); else if (class0 == gen_2) CLASS(scan) = class0; } else CLASS(scan) = class0; } /* else stay with the existing known class0 */ CLASS(scan) = class1; /* in any case, add exponents */ if (EXPON(old) == gen_1 && exponent == gen_1) EXPON(scan) = gen_2; else EXPON(scan) = addii(EXPON(old), exponent); /* move the value over and null out the vacated slot below */ old = scan - 3; *scan = *old; ifac_delete(old); /* finally, see whether *where should be pulled in */ if (old == *where) *where += 3; } /* Sort all current unknowns downward to where they belong. Sweeps in the * upward direction. Not needed after ifac_crack(), only when ifac_divide() * returned true. Update *where. */ static void ifac_resort(GEN *partial, GEN *where) { GEN scan, end; ifac_defrag(partial, where); end = LAST(*partial); for (scan = *where; scan <= end; scan += 3) if (VALUE(scan) && !CLASS(scan)) ifac_sort_one(where, scan); /*unknown*/ ifac_defrag(partial, where); /* remove newly created gaps */ } /* Let x be a t_INT known not to have small divisors (< 661, and < 2^14 for huge * x > 2^512). Return 0 if x is a proven composite. Return 1 if we believe it * to be prime (fully proven prime if factor_proven is set). */ int ifac_isprime(GEN x) { if (!BPSW_psp_nosmalldiv(x)) return 0; /* composite */ if (factor_proven && ! BPSW_isprime(x)) { pari_warn(warner, "IFAC: pseudo-prime %Ps\n\tis not prime. PLEASE REPORT!\n", x); return 0; } return 1; } static int ifac_checkprime(GEN x) { int res = ifac_isprime(VALUE(x)); CLASS(x) = res? gen_1: gen_0; if (DEBUGLEVEL>2) ifac_factor_dbg(x); return res; } /* Determine primality or compositeness of all current unknowns, and set * class Q primes to finished (class P) if everything larger is already * known to be prime. When after_crack >= 0, only look at the * first after_crack things in the list (do nothing when it's 0) */ static void ifac_whoiswho(GEN *partial, GEN *where, long after_crack) { GEN scan, scan_end = LAST(*partial); #ifdef IFAC_DEBUG ifac_check(*partial, *where); #endif if (after_crack == 0) return; if (after_crack > 0) /* check at most after_crack entries */ scan = *where + 3*(after_crack - 1); /* assert(scan <= scan_end) */ else for (scan = scan_end; scan >= *where; scan -= 3) { if (CLASS(scan)) { /* known class of factor */ if (CLASS(scan) == gen_0) break; if (CLASS(scan) == gen_1) { if (DEBUGLEVEL>=3) { err_printf("IFAC: factor %Ps\n\tis prime (no larger composite)\n", VALUE(*where)); err_printf("IFAC: prime %Ps\n\tappears with exponent = %ld\n", VALUE(*where), itos(EXPON(*where))); } CLASS(scan) = gen_2; } continue; } if (!ifac_checkprime(scan)) break; /* must disable Q-to-P */ CLASS(scan) = gen_2; /* P_i, finished prime */ if (DEBUGLEVEL>2) ifac_factor_dbg(scan); } /* go on, Q-to-P trick now disabled */ for (; scan >= *where; scan -= 3) { if (CLASS(scan)) continue; (void)ifac_checkprime(scan); /* Qj | Ck */ } } /* Divide all current composites by first (prime, class Q) entry, updating its * exponent, and turning it into a finished prime (class P). Return 1 if any * such divisions succeeded (in Moebius mode, the update may then not have * been completed), or 0 if none of them succeeded. Doesn't modify *where. * Here we normally do not check that the first entry is a not-finished * prime. Stack management: we may allocate a new exponent */ static long ifac_divide(GEN *partial, GEN *where, long moebius_mode) { GEN scan, scan_end = LAST(*partial); long res = 0, exponent, newexp, otherexp; #ifdef IFAC_DEBUG ifac_check(*partial, *where); if (CLASS(*where) != gen_1) pari_err_BUG("ifac_divide [division by composite or finished prime]"); if (!VALUE(*where)) pari_err_BUG("ifac_divide [division by nothing]"); #endif newexp = exponent = itos(EXPON(*where)); if (exponent > 1 && moebius_mode) return 1; /* should've been caught by caller */ for (scan = *where+3; scan <= scan_end; scan += 3) { if (CLASS(scan) != gen_0) continue; /* the other thing ain't composite */ otherexp = 0; /* divide in place to keep stack clutter minimal */ while (dvdiiz(VALUE(scan), VALUE(*where), VALUE(scan))) { if (moebius_mode) return 1; /* immediately */ if (!otherexp) otherexp = itos(EXPON(scan)); newexp += otherexp; } if (newexp > exponent) /* did anything happen? */ { EXPON(*where) = (newexp == 2 ? gen_2 : utoipos(newexp)); exponent = newexp; if (is_pm1((GEN)*scan)) /* factor dissolved completely */ { ifac_delete(scan); if (DEBUGLEVEL >= 4) err_printf("IFAC: a factor was a power of another prime factor\n"); } else { CLASS(scan) = NULL; /* at any rate it's Unknown now */ if (DEBUGLEVEL >= 4) err_printf("IFAC: a factor was divisible by another prime factor,\n" "\tleaving a cofactor = %Ps\n", VALUE(scan)); } res = 1; if (DEBUGLEVEL >= 5) err_printf("IFAC: prime %Ps\n\tappears at least to the power %ld\n", VALUE(*where), newexp); } } /* for */ CLASS(*where) = gen_2; /* make it a finished prime */ if (DEBUGLEVEL >= 3) err_printf("IFAC: prime %Ps\n\tappears with exponent = %ld\n", VALUE(*where), newexp); return res; } /* found out our integer was factor^exp. Update */ static void update_pow(GEN where, GEN factor, long exp, pari_sp *av) { GEN ex = EXPON(where); if (DEBUGLEVEL>3) err_printf("IFAC: found %Ps =\n\t%Ps ^%ld\n", *where, factor, exp); affii(factor, VALUE(where)); set_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 * hint & 2 : avoid first-stage ECM (may fall back to ECM if MPQS gives up) * hint & 4 : avoid Pollard and SQUFOF stages. * hint & 8 : avoid final ECM; may flag a composite as prime. */ #define get_hint(partial) (itos(HINT(*partial)) & 15) /* 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. Returns the * number of factors actually written, which may be less than #facvec if there * are duplicates. Vectors of factors (cf pollardbrent() or mpqs()) contain * 'slots' of 3 GENs per factor, interpreted as in our partial factorization * data structure. Thus engines can tell us what they already know about * factors being prime/composite or appearing to a power larger than thefirst. * Don't collect garbage. No diagnostics: engine has printed what it found. * facvec contains slots of three components per factor; repeated factors are * allowed (their classes shouldn't contradict each other whereas their * exponents will be added up) */ static long ifac_insert_multiplet(GEN *partial, GEN *where, GEN facvec, long moebius_mode) { long j,k=1, lfv=lg(facvec)-1, nf=lfv/3, room=(long)(*where-*partial); /* one of the factors will go into the *where slot, so room is now 3 times * the number of slots we can use */ long needroom = lfv - room; GEN newexp, cur, sorted, auxvec = cgetg(nf+1, t_VEC), factor; long E = 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) ifac_realloc(partial, where, lg(*partial) + needroom); /* create sort permutation from the values of the factors */ for (j=nf; j; j--) gel(auxvec,j) = gel(facvec,3*j-2); sorted = ZV_indexsort(auxvec); /* store factors, beginning at *where, and catching any duplicates */ cur = facvec + 3*sorted[nf]-2; /* adjust for triple spacing */ VALUE(*where) = VALUE(cur); newexp = EXPON(cur); /* if new exponent is 1, the old exponent already in place will do */ if (newexp != gen_1) EXPON(*where) = mului(E,newexp); CLASS(*where) = CLASS(cur); if (DEBUGLEVEL >= 6) err_printf("\tstored (largest) factor no. %ld...\n", nf); for (j=nf-1; j; j--) { GEN e; cur = facvec + 3*sorted[j]-2; 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 = addiu(EXPON(*where), E * itou(newexp)); else if (EXPON(*where) == gen_1 && E == 1) e = gen_2; else e = addiu(EXPON(*where), E); EXPON(*where) = e; if (moebius_mode) return 0; /* stop now, with exponent updated */ continue; } *where -= 3; CLASS(*where) = CLASS(cur); /* class as given */ newexp = EXPON(cur); if (newexp != gen_1) /* new exp > 1 */ e = (E == 1 && newexp == gen_2)? gen_2: mului(E, newexp); else /* inherit parent's exponent */ e = (E == 1 ? gen_1 : (E == 2 ? gen_2 : utoipos(E))); EXPON(*where) = e; /* keep components younger than *partial */ icopyifstack(factor, VALUE(*where)); k++; if (DEBUGLEVEL >= 6) err_printf("\tfactor no. %ld was unique%s\n", j, j>1? " (so far)...": ""); } return k; } /* Split the first (composite) entry. There _must_ already be room for another * factor below *where, and *where is updated. Two cases: * - entry = factor^k is a pure power: factor^k is inserted, leaving *where * unchanged; * - entry = factor * cofactor (not necessarily coprime): both factors are * inserted in the correct order, updating *where * The inserted factors class is set to unknown, they inherit the exponent * (or a multiple thereof) of their ancestor. * * Returns number of factors written into the structure, normally 2 (1 if pure * power, maybe > 2 if a factoring engine returned a vector of factors instead * of a single factor). Can reallocate the data structure in the * vector-of-factors case, not in the most common single-factor case. * Stack housekeeping: this routine may create one or more objects (a new * factor, or possibly several, and perhaps one or more new exponents > 2) */ static long ifac_crack(GEN *partial, GEN *where, long moebius_mode) { long cmp_res, hint = get_hint(partial); GEN factor, exponent; #ifdef IFAC_DEBUG ifac_check(*partial, *where); if (*where < *partial + 6) pari_err_BUG("ifac_crack ['*where' out of bounds]"); if (!(VALUE(*where)) || typ(VALUE(*where)) != t_INT) pari_err_BUG("ifac_crack [incorrect VALUE(*where)]"); if (CLASS(*where) != gen_0) pari_err_BUG("ifac_crack [operand not known composite]"); #endif if (DEBUGLEVEL>2) { err_printf("IFAC: cracking composite\n\t%Ps\n", **where); if (DEBUGLEVEL>3) err_printf("IFAC: checking for pure square\n"); } /* MPQS cannot factor prime powers. Look for pure powers even if MPQS is * blocked by hint: fast and useful in bounded factorization */ { forprime_t T; ulong exp = 1, mask = 7; long good = 0; pari_sp av = avma; (void)u_forprime_init(&T, 11, ULONG_MAX); /* crack squares */ while (Z_issquareall(VALUE(*where), &factor)) { good = 1; /* remember we succeeded once */ update_pow(*where, factor, 2, &av); if (moebius_mode) return 0; /* no need to carry on */ } while ( (exp = is_357_power(VALUE(*where), &factor, &mask)) ) { good = 1; /* remember we succeeded once */ update_pow(*where, factor, exp, &av); if (moebius_mode) return 0; /* no need to carry on */ } /* cutoff at 14 bits: OK if tridiv_bound >= 2^14 OR if >= 661 for * an integer < 701^11 (103 bits). */ while ( (exp = is_pth_power(VALUE(*where), &factor, &T, 15)) ) { good = 1; /* remember we succeeded once */ update_pow(*where, factor, exp, &av); if (moebius_mode) return 0; /* no need to carry on */ } if (good && hint != 15 && ifac_checkprime(*where)) { /* our composite was a prime power */ if (DEBUGLEVEL>3) err_printf("IFAC: factor %Ps\n\tis prime\n", VALUE(*where)); return 0; /* bypass subsequent ifac_whoiswho() call */ } } /* pure power stage */ factor = NULL; if (!(hint & 4)) { /* pollardbrent() Rho usually gets a first chance */ if (DEBUGLEVEL >= 4) err_printf("IFAC: trying Pollard-Brent rho method\n"); factor = pollardbrent(VALUE(*where)); if (!factor) { /* Shanks' squfof() */ if (DEBUGLEVEL >= 4) err_printf("IFAC: trying Shanks' SQUFOF, will fail silently if input\n" " is too large for it.\n"); factor = squfof(VALUE(*where)); } } if (!factor && !(hint & 2)) { /* First ECM stage */ if (DEBUGLEVEL >= 4) err_printf("IFAC: trying Lenstra-Montgomery ECM\n"); factor = ellfacteur(VALUE(*where), 0); /* do not insist */ } if (!factor && !(hint & 1)) { /* MPQS stage */ if (DEBUGLEVEL >= 4) err_printf("IFAC: trying MPQS\n"); factor = mpqs(VALUE(*where)); } if (!factor) { if (!(hint & 8)) { /* still no luck? Final ECM stage, guaranteed to succeed */ if (DEBUGLEVEL >= 4) err_printf("IFAC: forcing ECM, may take some time\n"); factor = ellfacteur(VALUE(*where), 1); } else { /* limited factorization */ if (DEBUGLEVEL >= 2) { if (hint != 15) pari_warn(warner, "IFAC: unfactored composite declared prime"); else pari_warn(warner, "IFAC: untested integer declared prime"); /* don't print it out at level 3 or above, where it would appear * several times before and after this message already */ if (DEBUGLEVEL == 2) err_printf("\t%Ps\n", VALUE(*where)); } CLASS(*where) = gen_1; /* might as well trial-divide by it... */ return 1; } } if (typ(factor) == t_VEC) /* delegate this case */ return ifac_insert_multiplet(partial, where, factor, moebius_mode); /* typ(factor) == t_INT */ /* got single integer back: work out the cofactor (in place) */ if (!dvdiiz(VALUE(*where), factor, VALUE(*where))) { err_printf("IFAC: factoring %Ps\n", VALUE(*where)); err_printf("\tyielded 'factor' %Ps\n\twhich isn't!\n", factor); pari_err_BUG("factoring"); } /* factoring engines report the factor found; tell about the cofactor */ if (DEBUGLEVEL >= 4) err_printf("IFAC: cofactor = %Ps\n", VALUE(*where)); /* The two factors are 'factor' and VALUE(*where), find out which is larger */ cmp_res = cmpii(factor, VALUE(*where)); CLASS(*where) = NULL; /* mark factor /cofactor 'unknown' */ exponent = EXPON(*where); *where -= 3; CLASS(*where) = NULL; /* mark factor /cofactor 'unknown' */ icopyifstack(exponent, EXPON(*where)); if (cmp_res < 0) VALUE(*where) = factor; /* common case */ else if (cmp_res > 0) { /* factor > cofactor, rearrange */ GEN old = *where + 3; VALUE(*where) = VALUE(old); /* move cofactor pointer to lowest slot */ VALUE(old) = factor; /* save factor */ } else pari_err_BUG("ifac_crack [Z_issquareall miss]"); return 2; } /* main loop: iterate until smallest entry is a finished prime; returns * a 'where' pointer, or NULL if nothing left, or gen_0 in Moebius mode if * we aren't squarefree */ static GEN ifac_main(GEN *partial) { const long moebius_mode = !!MOEBIUS(*partial); GEN here = ifac_find(*partial); long nf; if (!here) return NULL; /* nothing left */ /* loop until first entry is a finished prime. May involve reallocations, * thus updates of *partial */ while (CLASS(here) != gen_2) { if (CLASS(here) == gen_0) /* composite: crack it */ { /* make sure there's room for another factor */ if (here < *partial + 6) { ifac_defrag(partial, &here); if (here < *partial + 6) ifac_realloc(partial, &here, 1); /* no luck */ } nf = ifac_crack(partial, &here, moebius_mode); if (moebius_mode && EXPON(here) != gen_1) /* that was a power */ { if (DEBUGLEVEL >= 3) err_printf("IFAC: main loop: repeated new factor\n\t%Ps\n", *here); return gen_0; } /* deal with the new unknowns. No sort: ifac_crack did it */ ifac_whoiswho(partial, &here, nf); continue; } if (CLASS(here) == gen_1) /* prime but not yet finished: finish it */ { if (ifac_divide(partial, &here, moebius_mode)) { if (moebius_mode) { if (DEBUGLEVEL >= 3) err_printf("IFAC: main loop: another factor was divisible by\n" "\t%Ps\n", *here); return gen_0; } ifac_resort(partial, &here); /* sort new cofactors down */ ifac_whoiswho(partial, &here, -1); } continue; } pari_err_BUG("ifac_main [nonexistent factor class]"); } /* while */ if (moebius_mode && EXPON(here) != gen_1) { if (DEBUGLEVEL >= 3) err_printf("IFAC: after main loop: repeated old factor\n\t%Ps\n", *here); return gen_0; } if (DEBUGLEVEL >= 4) { nf = (*partial + lg(*partial) - here - 3)/3; if (nf) err_printf("IFAC: main loop: %ld factor%s left\n", nf, (nf>1)? "s": ""); else err_printf("IFAC: main loop: this was the last factor\n"); } if (factor_add_primes && !(get_hint(partial) & 8)) { GEN p = VALUE(here); if (lgefint(p)>3 || uel(p,2) > 0x1000000UL) (void)addprimes(p); } return here; } /* Encapsulated routines */ /* prime/exponent pairs need to appear contiguously on the stack, but we also * need our data structure somewhere, and we don't know in advance how many * primes will turn up. The following discipline achieves this: When * ifac_decomp() is called, n should point at an object older than the oldest * small prime/exponent pair (ifactor() guarantees this). * We allocate sufficient space to accommodate several pairs -- eleven pairs * ought to fit in a space not much larger than n itself -- before calling * ifac_start(). If we manage to complete the factorization before we run out * of space, we free the data structure and cull the excess reserved space * before returning. When we do run out, we have to leapfrog to generate more * (guesstimating the requirements from what is left in the partial * factorization structure); room for fresh pairs is allocated at the head of * the stack, followed by an ifac_realloc() to reconnect the data structure and * move it out of the way, followed by a few pointer tweaks to connect the new * pairs space to the old one. This whole affair translates into a surprisingly * compact routine. */ /* find primary factors of n; destroy n */ static long ifac_decomp(GEN n, long hint) { pari_sp av = avma; long nb = 0; GEN part, here, workspc, pairs = (GEN)av; /* workspc will be doled out in pairs of smaller t_INTs. For n = prod p^{e_p} * (p not necessarily prime), need room to store all p and e_p [ cgeti(3) ], * bounded by * sum_{p | n} ( log_{2^BIL} (p) + 6 ) <= log_{2^BIL} n + 6 log_2 n */ workspc = new_chunk((expi(n) + 1) * 7); part = ifac_start_hint(n, 0, hint); for (;;) { here = ifac_main(&part); if (!here) break; if (gc_needed(av,1)) { long offset; if(DEBUGMEM>1) { pari_warn(warnmem,"[2] ifac_decomp"); ifac_print(part, here); } ifac_realloc(&part, &here, 0); offset = here - part; part = gerepileupto((pari_sp)workspc, part); here = part + offset; } nb++; pairs = icopy_avma(VALUE(here), (pari_sp)pairs); pairs = icopy_avma(EXPON(here), (pari_sp)pairs); ifac_delete(here); } set_avma((pari_sp)pairs); if (DEBUGLEVEL >= 3) err_printf("IFAC: found %ld large prime (power) factor%s.\n", nb, (nb>1? "s": "")); return nb; } /***********************************************************************/ /** ARITHMETIC FUNCTIONS WITH EARLY-ABORT **/ /** needing direct access to the factoring machinery to avoid work: **/ /** e.g. if we find a square factor, moebius returns 0, core doesn't **/ /** need to factor it, etc. **/ /***********************************************************************/ /* memory management */ static void ifac_GC(pari_sp av, GEN *part) { GEN here = NULL; if(DEBUGMEM>1) pari_warn(warnmem,"ifac_xxx"); ifac_realloc(part, &here, 0); *part = gerepileupto(av, *part); } /* destroys n */ static long ifac_moebius(GEN n) { long mu = 1; pari_sp av = avma; GEN part = ifac_start(n, 1); for(;;) { long v; GEN p; if (!ifac_next(&part,&p,&v)) return v? 0: mu; mu = -mu; if (gc_needed(av,1)) ifac_GC(av,&part); } } int ifac_read(GEN part, GEN *p, long *e) { GEN here = ifac_find(part); if (!here) return 0; *p = VALUE(here); *e = EXPON(here)[2]; return 1; } void ifac_skip(GEN part) { GEN here = ifac_find(part); if (here) ifac_delete(here); } /* destroys n */ static int ifac_ispowerful(GEN n) { pari_sp av = avma; GEN part = ifac_start(n, 0); for(;;) { long e; GEN p; if (!ifac_read(part,&p,&e)) return 1; /* power: skip */ if (e != 1 || Z_isanypower(p,NULL)) { ifac_skip(part); continue; } if (!ifac_next(&part,&p,&e)) return 1; if (e == 1) return 0; if (gc_needed(av,1)) ifac_GC(av,&part); } } /* destroys n */ static GEN ifac_core(GEN n) { GEN m = gen_1, c = cgeti(lgefint(n)); pari_sp av = avma; GEN part = ifac_start(n, 0); for(;;) { long e; GEN p; if (!ifac_read(part,&p,&e)) return m; /* square: skip */ if (!odd(e) || Z_issquare(p)) { ifac_skip(part); continue; } if (!ifac_next(&part,&p,&e)) return m; if (odd(e)) m = mulii(m, p); if (gc_needed(av,1)) { affii(m,c); m=c; ifac_GC(av,&part); } } } /* must be >= 661 (various functions assume it in order to call uisprime_661 * instead of uisprime, and Z_isanypower_nosmalldiv instead of Z_isanypower) */ ulong tridiv_boundu(ulong n) { long e = expu(n); if(e<30) return 1UL<<12; #ifdef LONG_IS_64BIT if(e<34) return 1UL<<13; if(e<37) return 1UL<<14; if(e<42) return 1UL<<15; if(e<47) return 1UL<<16; if(e<56) return 1UL<<17; if(e<56) return 1UL<<18; if(e<62) return 1UL<<19; return 1UL<<18; #else return 1UL<<13; #endif } /* Where to stop trial dividing in factorization. Must be >= 661. * If further n > 2^512, must be >= 2^14 */ ulong tridiv_bound(GEN n) { if (lgefint(n)==3) return tridiv_boundu(n[2]); else { ulong l = (ulong)expi(n) + 1; if (l <= 512) return (l-16) << 10; return 1UL<<19; /* Rho is generally faster above this */ } } /* destroys n */ static void ifac_factoru(GEN n, long hint, GEN P, GEN E, long *pi) { GEN part = ifac_start_hint(n, 0, hint); for(;;) { long v; GEN p; if (!ifac_next(&part,&p,&v)) return; P[*pi] = itou(p); E[*pi] = v; (*pi)++; } } /* destroys n */ static long ifac_moebiusu(GEN n) { GEN part = ifac_start(n, 1); long s = 1; for(;;) { long v; GEN p; if (!ifac_next(&part,&p,&v)) return v? 0: s; s = -s; } } INLINE ulong u_forprime_next_fast(forprime_t *T) { if (++T->n <= pari_PRIMES[0]) { T->p = pari_PRIMES[T->n]; return T->p > T->b ? 0: T->p; } return u_forprime_next(T); } /* uisprime(n) knowing n has no prime divisor <= lim */ static int uisprime_nosmall(ulong n, ulong lim) { return (lim >= 661)? uisprime_661(n): uisprime(n); } /* Factor n and output [p,e] where * p, e are vecsmall with n = prod{p[i]^e[i]}. If all != 0: * if pU1 is not NULL, set *pU1 and *pU2 so that unfactored composite is * U1^U2 with U1 not a pure power; else include it in factorization */ static GEN factoru_sign(ulong n, ulong all, long hint, ulong *pU1, ulong *pU2) { GEN f, E, E2, P, P2; pari_sp av; ulong p, lim = 0; long i, oldi = -1; forprime_t S; if (pU1) *pU1 = *pU2 = 1; if (n == 0) retmkvec2(mkvecsmall(0), mkvecsmall(1)); if (n == 1) retmkvec2(cgetg(1,t_VECSMALL), cgetg(1,t_VECSMALL)); f = cgetg(3,t_VEC); av = avma; /* enough room to store <= 15 primes and exponents (OK if n < 2^64) */ (void)new_chunk(16*2); P = cgetg(16, t_VECSMALL); i = 1; E = cgetg(16, t_VECSMALL); if (!all || all > 2) { ulong maxp; long v = vals(n); if (v) { P[1] = 2; E[1] = v; i = 2; n >>= v; if (n == 1) goto END; } maxp = maxprime(); if (n <= maxp && PRIMES_search(n) > 0) { P[i] = n; E[i] = 1; i++; goto END; } lim = minss(usqrt(n), all? all-1: tridiv_boundu(n)); if (!(hint & 16) && lim >= 128) /* expu(lim) >= 7 */ { /* fast trial division */ GEN PR = prodprimes(); long nPR = lg(PR)-1, b = minss(nPR, expu(lim)-6); ulong nr = ugcd(n, umodiu(gel(PR,b), n)); if (nr != 1) { GEN F = factoru_sign(nr, all, 1 + 2 + 16, NULL, NULL), Q = gel(F,1); long j, l = lg(Q); for (j = 1; j < l; j++) { ulong p = uel(Q,j); if (all && p >= all) break; /* may occur for last p */ E[i] = u_lvalrem(n, p, &n); /* > 0 */ P[i] = p; i++; } if (n == 1) goto END; if (n <= maxp && PRIMES_search(n) > 0) { P[i] = n; E[i] = 1; i++; goto END; } } maxp = GP_DATA->factorlimit; } else { maxp = lim; u_forprime_init(&S, 3, lim); while ( (p = u_forprime_next_fast(&S)) ) { int stop; /* tiny integers without small factors are often primes */ if (p == 673) { if (uisprime_661(n)) { P[i] = n; E[i] = 1; i++; goto END; } oldi = i; } v = u_lvalrem_stop(&n, p, &stop); if (v) { P[i] = p; E[i] = v; i++; } if (stop) { if (n != 1) { P[i] = n; E[i] = 1; i++; } goto END; } } } if (lim > maxp) { /* second pass usually empty, outside fast trial division range */ long v; u_forprime_init(&S, maxp+1, lim); while ((p = u_forprime_next(&S))) { int stop; v = u_lvalrem_stop(&n, p, &stop); if (v) { P[i] = p; E[i] = v; i++; } if (stop) { if (n != 1) { P[i] = n; E[i] = 1; i++; } goto END; } } } } /* if i > oldi (includes oldi = -1) we don't know that n is composite */ if (all) { /* smallfact: look for easy pure powers then stop */ #ifdef LONG_IS_64BIT ulong mask = all > 563 ? (all > 7129 ? 1: 3): 7; #else ulong mask = all > 22 ? (all > 83 ? 1: 3): 7; #endif long k = 1, ex; while (uissquareall(n, &n)) k <<= 1; while ( (ex = uis_357_power(n, &n, &mask)) ) k *= ex; if (pU1 && (i == oldi || !uisprime_nosmall(n, lim))) { *pU1 = n; *pU2 = (ulong)k; } else { P[i] = n; E[i] = k; i++; } goto END; } /* we don't known that n is composite ? */ if (oldi != i && uisprime_nosmall(n, lim)) { P[i]=n; E[i]=1; i++; goto END; } { GEN perm; ifac_factoru(utoipos(n), hint, P, E, &i); setlg(P, i); perm = vecsmall_indexsort(P); P = vecsmallpermute(P, perm); E = vecsmallpermute(E, perm); } END: set_avma(av); P2 = cgetg(i, t_VECSMALL); gel(f,1) = P2; E2 = cgetg(i, t_VECSMALL); gel(f,2) = E2; while (--i >= 1) { P2[i] = P[i]; E2[i] = E[i]; } return f; } GEN factoru(ulong n) { return factoru_sign(n, 0, decomp_default_hint, NULL, NULL); } ulong radicalu(ulong n) { pari_sp av = avma; return gc_long(av, zv_prod(gel(factoru(n),1))); } long moebiusu_fact(GEN f) { GEN E = gel(f,2); long i, l = lg(E); for (i = 1; i < l; i++) if (E[i] > 1) return 0; return odd(l)? 1: -1; } long moebiusu(ulong n) { pari_sp av; ulong p; long s, v, test_prime; forprime_t S; switch(n) { case 0: (void)check_arith_non0(gen_0,"moebius");/*error*/ case 1: return 1; case 2: return -1; } v = vals(n); if (v == 0) s = 1; else { if (v > 1) return 0; n >>= 1; s = -1; } av = avma; u_forprime_init(&S, 3, tridiv_boundu(n)); test_prime = 0; while ((p = u_forprime_next_fast(&S))) { int stop; /* tiny integers without small factors are often primes */ if (p == 673) { test_prime = 0; if (uisprime_661(n)) return gc_long(av,-s); } v = u_lvalrem_stop(&n, p, &stop); if (v) { if (v > 1) return gc_long(av,0); test_prime = 1; s = -s; } if (stop) return gc_long(av, n==1? s: -s); } set_avma(av); if (test_prime && uisprime_661(n)) return -s; else { long t = ifac_moebiusu(utoipos(n)); set_avma(av); if (t == 0) return 0; return (s == t)? 1: -1; } } long moebius(GEN n) { pari_sp av = avma; GEN F; ulong p; long i, l, s, v; forprime_t S; if ((F = check_arith_non0(n,"moebius"))) { GEN E; F = clean_Z_factor(F); E = gel(F,2); l = lg(E); for(i = 1; i < l; i++) if (!equali1(gel(E,i))) return gc_long(av,0); return gc_long(av, odd(l)? 1: -1); } if (lgefint(n) == 3) return moebiusu(uel(n,2)); p = mod4(n); if (!p) return 0; if (p == 2) { s = -1; n = shifti(n, -1); } else { s = 1; n = icopy(n); } setabssign(n); u_forprime_init(&S, 3, tridiv_bound(n)); while ((p = u_forprime_next_fast(&S))) { int stop; v = Z_lvalrem_stop(&n, p, &stop); if (v) { if (v > 1) return gc_long(av,0); s = -s; if (stop) return gc_long(av, is_pm1(n)? s: -s); } } l = lg(primetab); for (i = 1; i < l; i++) { v = Z_pvalrem(n, gel(primetab,i), &n); if (v) { if (v > 1) return gc_long(av,0); s = -s; if (is_pm1(n)) return gc_long(av,s); } } if (ifac_isprime(n)) return gc_long(av,-s); /* large composite without small factors */ v = ifac_moebius(n); return gc_long(av, s < 0? -v: v); /* correct also if v==0 */ } long ispowerful(GEN n) { pari_sp av = avma; GEN F; ulong p, bound; long i, l, v; forprime_t S; if ((F = check_arith_all(n, "ispowerful"))) { GEN p, P = gel(F,1), E = gel(F,2); if (lg(P) == 1) return 1; /* 1 */ p = gel(P,1); if (!signe(p)) return 1; /* 0 */ i = is_pm1(p)? 2: 1; /* skip -1 */ l = lg(E); for (; i < l; i++) if (equali1(gel(E,i))) return 0; return 1; } if (!signe(n)) return 1; if (mod4(n) == 2) return 0; n = shifti(n, -vali(n)); if (is_pm1(n)) return 1; setabssign(n); bound = tridiv_bound(n); u_forprime_init(&S, 3, bound); while ((p = u_forprime_next_fast(&S))) { int stop; v = Z_lvalrem_stop(&n, p, &stop); if (v) { if (v == 1) return gc_long(av,0); if (stop) return gc_long(av, is_pm1(n)); } } l = lg(primetab); for (i = 1; i < l; i++) { v = Z_pvalrem(n, gel(primetab,i), &n); if (v) { if (v == 1) return gc_long(av,0); if (is_pm1(n)) return gc_long(av,1); } } /* no need to factor: must be p^2 or not powerful */ if (cmpii(powuu(bound+1, 3), n) > 0) return gc_long(av, Z_issquare(n)); if (ifac_isprime(n)) return gc_long(av,0); /* large composite without small factors */ return gc_long(av, ifac_ispowerful(n)); } ulong coreu_fact(GEN f) { GEN P = gel(f,1), E = gel(f,2); long i, l = lg(P), m = 1; for (i = 1; i < l; i++) { ulong p = P[i], e = E[i]; if (e & 1) m *= p; } return m; } ulong coreu(ulong n) { pari_sp av; if (n == 0) return 0; av = avma; return gc_ulong(av, coreu_fact(factoru(n))); } GEN core(GEN n) { pari_sp av = avma; GEN m, F; ulong p; long i, l, v; forprime_t S; if ((F = check_arith_all(n, "core"))) { GEN p, x, P = gel(F,1), E = gel(F,2); long j = 1; if (lg(P) == 1) return gen_1; p = gel(P,1); if (!signe(p)) return gen_0; l = lg(P); x = cgetg(l, t_VEC); for (i = 1; i < l; i++) if (mpodd(gel(E,i))) gel(x,j++) = gel(P,i); setlg(x, j); return ZV_prod(x); } switch(lgefint(n)) { case 2: return gen_0; case 3: p = coreu(uel(n,2)); return signe(n) > 0? utoipos(p): utoineg(p); } m = signe(n) < 0? gen_m1: gen_1; n = absi_shallow(n); u_forprime_init(&S, 2, tridiv_bound(n)); while ((p = u_forprime_next_fast(&S))) { int stop; v = Z_lvalrem_stop(&n, p, &stop); if (v) { if (v & 1) m = muliu(m, p); if (stop) { if (!is_pm1(n)) m = mulii(m, n); return gerepileuptoint(av, m); } } } l = lg(primetab); for (i = 1; i < l; i++) { GEN q = gel(primetab,i); v = Z_pvalrem(n, q, &n); if (v) { if (v & 1) m = mulii(m, q); if (is_pm1(n)) return gerepileuptoint(av, m); } } if (ifac_isprime(n)) { m = mulii(m, n); return gerepileuptoint(av, m); } if (m == gen_1) n = icopy(n); /* ifac_core destroys n */ /* large composite without small factors */ return gerepileuptoint(av, mulii(m, ifac_core(n))); } long Z_issmooth(GEN m, ulong lim) { pari_sp av = avma; ulong p = 2; forprime_t S; u_forprime_init(&S, 2, lim); while ((p = u_forprime_next_fast(&S))) { int stop; (void)Z_lvalrem_stop(&m, p, &stop); if (stop) return gc_long(av, abscmpiu(m,lim) <= 0); } return gc_long(av,0); } GEN Z_issmooth_fact(GEN m, ulong lim) { pari_sp av = avma; GEN F, P, E; ulong p; long i = 1, l = expi(m)+1; forprime_t S; P = cgetg(l, t_VECSMALL); E = cgetg(l, t_VECSMALL); F = mkmat2(P,E); if (l == 1) return F; /* m == 1 */ u_forprime_init(&S, 2, lim); while ((p = u_forprime_next_fast(&S))) { long v; int stop; if ((v = Z_lvalrem_stop(&m, p, &stop))) { P[i] = p; E[i] = v; i++; if (stop) { if (abscmpiu(m,lim) > 0) break; if (m[2] > 1) { P[i] = m[2]; E[i] = 1; i++; } setlg(P, i); setlg(E, i); return gc_const((pari_sp)F, F); } } } return gc_NULL(av); } /***********************************************************************/ /** **/ /** COMPUTING THE MATRIX OF PRIME DIVISORS AND EXPONENTS **/ /** **/ /***********************************************************************/ static GEN aux_end(GEN M, GEN n, long nb) { GEN P,E, z = (GEN)avma; long i; guncloneNULL(n); P = cgetg(nb+1,t_COL); E = cgetg(nb+1,t_COL); for (i=nb; i; i--) { /* allow a stackdummy in the middle */ while (typ(z) != t_INT) z += lg(z); gel(E,i) = z; z += lg(z); gel(P,i) = z; z += lg(z); } gel(M,1) = P; gel(M,2) = E; return sort_factor(M, (void*)&abscmpii, cmp_nodata); } static void STORE(long *nb, GEN x, long e) { (*nb)++; (void)x; (void)utoipos(e); } static void STOREu(long *nb, ulong x, long e) { STORE(nb, utoipos(x), e); } static void STOREi(long *nb, GEN x, long e) { STORE(nb, icopy(x), e); } /* no prime less than p divides n; return 1 if factored completely */ static int special_primes(GEN n, ulong p, long *nb, GEN T) { long i, l = lg(T); if (l > 1) { /* pp = square of biggest p tried so far */ long pp[] = { evaltyp(t_INT)|_evallg(4), 0,0,0 }; pari_sp av = avma; affii(sqru(p), pp); set_avma(av); for (i = 1; i < l; i++) if (dvdiiz(n, gel(T,i), n)) { long k = 1; while (dvdiiz(n, gel(T,i), n)) k++; STOREi(nb, gel(T,i), k); if (abscmpii(pp, n) > 0) { if (!is_pm1(n)) STOREi(nb, n, 1); return 1; } } } return 0; } /* factor(sn*|n|), where sn = -1 or 1. * all != 0 : only look for prime divisors < all. If pU is not NULL, * set it to unfactored composite */ static GEN ifactor_sign(GEN n, ulong all, long hint, long sn, GEN *pU) { GEN M, N; pari_sp av; long nb = 0, nb0 = -1, i; ulong lim; forprime_t T; if (lgefint(n) == 3) { /* small integer */ GEN f, Pf, Ef, P, E, F = cgetg(3, t_MAT); ulong U1, U2; long l; av = avma; /* enough room to store <= 15 primes and exponents (OK if n < 2^64) */ (void)new_chunk((15*3 + 15 + 1) * 2); f = factoru_sign(uel(n,2), all, hint, pU? &U1: NULL, pU? &U2: NULL); set_avma(av); Pf = gel(f,1); Ef = gel(f,2); l = lg(Pf); if (sn < 0) { /* add sign */ long L = l+1; gel(F,1) = P = cgetg(L, t_COL); gel(F,2) = E = cgetg(L, t_COL); gel(P,1) = gen_m1; P++; gel(E,1) = gen_1; E++; } else { gel(F,1) = P = cgetg(l, t_COL); gel(F,2) = E = cgetg(l, t_COL); } for (i = 1; i < l; i++) { gel(P,i) = utoipos(Pf[i]); gel(E,i) = utoipos(Ef[i]); } if (pU) *pU = U1 == 1? NULL: mkvec2(utoipos(U1), utoipos(U2)); return F; } if (pU) *pU = NULL; M = cgetg(3,t_MAT); if (sn < 0) STORE(&nb, utoineg(1), 1); if (is_pm1(n)) return aux_end(M,NULL,nb); n = N = gclone(n); setabssign(n); /* trial division bound; look for primes <= lim; nb is the number of * distinct prime factors so far; if nb0 >= 0, it records the value of nb * for which we made a successful compositeness test: if later nb = nb0, * we know that n is composite */ lim = 1; if (!all || all > 2) { /* trial divide p < all if all != 0, else p <= tridiv_bound() */ ulong maxp, p; pari_sp av2; i = vali(n); if (i) { STOREu(&nb, 2, i); av = avma; affii(shifti(n,-i), n); set_avma(av); } if (is_pm1(n)) return aux_end(M,n,nb); lim = all? all-1: tridiv_bound(n); if (!(hint & 16) && lim >= 128) /* expu(lim) >= 7 */ { /* fast trial division */ GEN nr, PR = prodprimes(); long nPR = lg(PR)-1, b = minss(nPR, expu(lim)-6); av = avma; maxp = GP_DATA->factorlimit; nr = gcdii(gel(PR,b), n); if (is_pm1(nr)) { set_avma(av); av2 = av; } else { GEN F = ifactor_sign(nr, all, 1 + 2 + 16, 1, NULL), P = gel(F,1); long l = lg(P); av2 = avma; for (i = 1; i < l; i++) { pari_sp av3 = avma; GEN gp = gel(P,i); ulong p = gp[2]; long k; if (lgefint(gp)>3 || (all && p>=all)) break; /* may occur for last p */ k = Z_lvalrem(n, p, &n); /* > 0 */ affii(n, N); n = N; set_avma(av3); STOREu(&nb, p, k); } if (is_pm1(n)) { stackdummy(av, av2); return aux_end(M,n,nb); } } } else { /* naive trial division */ av = avma; maxp = maxprime(); u_forprime_init(&T, 3, minss(lim, maxp)); av2 = avma; /* first pass: known to fit in private prime table */ while ((p = u_forprime_next_fast(&T))) { pari_sp av3 = avma; int stop; long k = Z_lvalrem_stop(&n, p, &stop); if (k) { affii(n, N); n = N; set_avma(av3); STOREu(&nb, p, k); } /* prodeuler(p=2,16381,1-1/p) ~ 0.0578; if probability of being prime * knowing P^-(n) > 16381 is at least 10%, try BPSW */ if (!stop && p == 16381) { if (bit_accuracy_mul(lgefint(n), 0.0578 * M_LN2) < 10) { nb0 = nb; stop = ifac_isprime(n); } } if (stop) { if (!is_pm1(n)) STOREi(&nb, n, 1); stackdummy(av, av2); return aux_end(M,n,nb); } } } stackdummy(av, av2); if (lim > maxp) { /* second pass usually empty, outside fast trial division range */ av = avma; u_forprime_init(&T, maxp+1, lim); av2 = avma; while ((p = u_forprime_next(&T))) { pari_sp av3 = avma; int stop; long k = Z_lvalrem_stop(&n, p, &stop); if (k) { affii(n, N); n = N; set_avma(av3); STOREu(&nb, p, k); } if (stop) { if (!is_pm1(n)) STOREi(&nb, n, 1); stackdummy(av, av2); return aux_end(M,n,nb); } } stackdummy(av, av2); } } if (special_primes(n, lim, &nb, primetab)) return aux_end(M,n, nb); /* if nb > nb0 (includes nb0 = -1) we don't know that n is composite */ if (all) { /* smallfact: look for easy pure powers then stop. Cf Z_isanypower */ GEN x; long k, e = expu(lim); av = avma; k = e >= 10? Z_isanypower_nosmalldiv(n, e, &x) : Z_isanypower(n, &x); if (k > 1) { affii(x, n); nb0 = -1; } else if (k < 1) k = 1; if (pU) { GEN F; if (abscmpiu(n, lim) <= 0 || cmpii(n, sqru(lim)) <= 0 || ((e >= 14) && (nb>nb0 && bit_accuracy(lgefint(n))<2048 && ifac_isprime(n)))) { set_avma(av); STOREi(&nb, n, k); return aux_end(M,n, nb); } set_avma(av); F = aux_end(M, NULL, nb); /* don't destroy n */ *pU = mkvec2(icopy(n), utoipos(k)); /* composite cofactor */ gunclone(n); return F; } set_avma(av); STOREi(&nb, n, k); if (DEBUGLEVEL >= 2) { pari_warn(warner, "IFAC: untested %ld-bit integer declared prime", expi(n)+1); if (expi(n) <= 256) err_printf("\t%Ps\n", n); } } else if (nb > nb0 && ifac_isprime(n)) STOREi(&nb, n, 1); else nb += ifac_decomp(n, hint); return aux_end(M,n, nb); } static GEN ifactor(GEN n, ulong all, long hint) { long s = signe(n); if (!s) retmkmat2(mkcol(gen_0), mkcol(gen_1)); return ifactor_sign(n, all, hint, s, NULL); } int ifac_next(GEN *part, GEN *p, long *e) { GEN here = ifac_main(part); if (here == gen_0) { *p = NULL; *e = 1; return 0; } if (!here) { *p = NULL; *e = 0; return 0; } *p = VALUE(here); *e = EXPON(here)[2]; ifac_delete(here); return 1; } /* see before ifac_crack for current semantics of 'hint' (factorint's 'flag') */ GEN factorint(GEN n, long flag) { GEN F; if ((F = check_arith_all(n,"factorint"))) return gcopy(F); return ifactor(n,0,flag); } GEN Z_factor_limit(GEN n, ulong all) { if (!all) all = GP_DATA->factorlimit + 1; return ifactor(n, all, decomp_default_hint); } GEN absZ_factor_limit_strict(GEN n, ulong all, GEN *pU) { GEN F, U; if (!signe(n)) { if (pU) *pU = NULL; retmkmat2(mkcol(gen_0), mkcol(gen_1)); } if (!all) all = GP_DATA->factorlimit + 1; F = ifactor_sign(n, all, decomp_default_hint, 1, &U); if (pU) *pU = U; return F; } GEN absZ_factor_limit(GEN n, ulong all) { if (!signe(n)) retmkmat2(mkcol(gen_0), mkcol(gen_1)); if (!all) all = GP_DATA->factorlimit + 1; return ifactor_sign(n, all, decomp_default_hint, 1, NULL); } GEN Z_factor(GEN n) { return ifactor(n,0,decomp_default_hint); } GEN absZ_factor(GEN n) { if (!signe(n)) retmkmat2(mkcol(gen_0), mkcol(gen_1)); return ifactor_sign(n, 0, decomp_default_hint, 1, NULL); } /* Factor until the unfactored part is smaller than limit. Return the * factored part. Hence factorback(output) may be smaller than n */ GEN Z_factor_until(GEN n, GEN limit) { pari_sp av = avma; long s = signe(n), eq; GEN q, F, U; if (!s) retmkmat2(mkcol(gen_0), mkcol(gen_1)); F = ifactor_sign(n, tridiv_bound(n), decomp_default_hint, s, &U); if (!U) return F; q = gel(U,1); /* composite, q^eq = unfactored part */ eq = itou(gel(U,2)); if (cmpii(eq == 1? q: powiu(q, eq), limit) > 0) { /* factor further */ long l2 = expi(q)+1; GEN P2, E2, F2, part; if (eq > 1) limit = sqrtnint(limit, eq); P2 = coltrunc_init(l2); E2 = coltrunc_init(l2); F2 = mkmat2(P2,E2); part = ifac_start(icopy(q), 0); /* ifac_next would destroy q */ for(;;) { long e; GEN p; if (!ifac_next(&part,&p,&e)) break; vectrunc_append(P2, p); vectrunc_append(E2, utoipos(e * eq)); q = diviiexact(q, powiu(p, e)); if (cmpii(q, limit) <= 0) break; } F2 = sort_factor(F2, (void*)&abscmpii, cmp_nodata); F = merge_factor(F, F2, (void*)&abscmpii, cmp_nodata); } return gerepilecopy(av, F); } static void matsmalltrunc_append(GEN m, ulong p, ulong e) { GEN P = gel(m,1), E = gel(m,2); long l = lg(P); P[l] = p; lg_increase(P); E[l] = e; lg_increase(E); } static GEN matsmalltrunc_init(long l) { GEN P = vecsmalltrunc_init(l); GEN E = vecsmalltrunc_init(l); return mkvec2(P,E); } /* return optimal N s.t. omega(b) <= N for all b <= x */ long maxomegau(ulong x) { /* P=primes(15); for(i=1,15, print([i, vecprod(P[1..i])])) */ if (x < 30030UL)/* rare trivial cases */ { if (x < 2UL) return 0; if (x < 6UL) return 1; if (x < 30UL) return 2; if (x < 210UL) return 3; if (x < 2310UL) return 4; return 5; } if (x < 510510UL) return 6; /* most frequent case */ if (x < 9699690UL) return 7; if (x < 223092870UL) return 8; #ifdef LONG_IS_64BIT if (x < 6469693230UL) return 9; if (x < 200560490130UL) return 10; if (x < 7420738134810UL) return 11; if (x < 304250263527210UL) return 12; if (x < 13082761331670030UL) return 13; if (x < 614889782588491410UL) return 14; return 15; #else return 9; #endif } /* return optimal N s.t. omega(b) <= N for all odd b <= x */ long maxomegaoddu(ulong x) { /* P=primes(15+1); for(i=1,15, print([i, vecprod(P[2..i+1])])) */ if (x < 255255UL)/* rare trivial cases */ { if (x < 3UL) return 0; if (x < 15UL) return 1; if (x < 105UL) return 2; if (x < 1155UL) return 3; if (x < 15015UL) return 4; return 5; } if (x < 4849845UL) return 6; /* most frequent case */ if (x < 111546435UL) return 7; if (x < 3234846615UL) return 8; #ifdef LONG_IS_64BIT if (x < 100280245065UL) return 9; if (x < 3710369067405UL) return 10; if (x < 152125131763605UL) return 11; if (x < 6541380665835015UL) return 12; if (x < 307444891294245705UL) return 13; if (x < 16294579238595022365UL) return 14; return 15; #else return 9; #endif } /* If a <= c <= b , factoru(c) = L[c-a+1] */ GEN vecfactoru_i(ulong a, ulong b) { ulong k, p, n = b-a+1, N = maxomegau(b) + 1; GEN v = const_vecsmall(n, 1); GEN L = cgetg(n+1, t_VEC); forprime_t T; for (k = 1; k <= n; k++) gel(L,k) = matsmalltrunc_init(N); u_forprime_init(&T, 2, usqrt(b)); while ((p = u_forprime_next(&T))) { /* p <= sqrt(b) */ ulong pk = p, K = ulogint(b, p); for (k = 1; k <= K; k++) { ulong j, t = a / pk, ap = t * pk; if (ap < a) { ap += pk; t++; } /* t = (j+a-1) \ pk */ t %= p; for (j = ap-a+1; j <= n; j += pk) { if (t) { v[j] *= pk; matsmalltrunc_append(gel(L,j), p,k); } if (++t == p) t = 0; } pk *= p; } } /* complete factorisation of non-sqrt(b)-smooth numbers */ for (k = 1, N = a; k <= n; k++, N++) if (uel(v,k) != N) matsmalltrunc_append(gel(L,k), N/uel(v,k),1UL); return L; } GEN vecfactoru(ulong a, ulong b) { pari_sp av = avma; return gerepilecopy(av, vecfactoru_i(a,b)); } /* Assume a and b odd, return L s.t. L[k] = factoru(a + 2*(k-1)) * If a <= c <= b odd, factoru(c) = L[(c-a)>>1 + 1] */ GEN vecfactoroddu_i(ulong a, ulong b) { ulong k, p, n = ((b-a)>>1) + 1, N = maxomegaoddu(b) + 1; GEN v = const_vecsmall(n, 1); GEN L = cgetg(n+1, t_VEC); forprime_t T; for (k = 1; k <= n; k++) gel(L,k) = matsmalltrunc_init(N); u_forprime_init(&T, 3, usqrt(b)); while ((p = u_forprime_next(&T))) { /* p <= sqrt(b) */ ulong pk = p, K = ulogint(b, p); for (k = 1; k <= K; k++) { ulong j, t = (a / pk) | 1UL, ap = t * pk; /* t and ap are odd, ap multiple of pk = p^k */ if (ap < a) { ap += pk<<1; t+=2; } /* c=t*p^k by steps of 2*p^k; factorization of c*=p^k if (t,p)=1 */ t %= p; for (j = ((ap-a)>>1)+1; j <= n; j += pk) { if (t) { v[j] *= pk; matsmalltrunc_append(gel(L,j), p,k); } t += 2; if (t >= p) t -= p; } pk *= p; } } /* complete factorisation of non-sqrt(b)-smooth numbers */ for (k = 1, N = a; k <= n; k++, N+=2) if (uel(v,k) != N) matsmalltrunc_append(gel(L,k), N/uel(v,k),1UL); return L; } GEN vecfactoroddu(ulong a, ulong b) { pari_sp av = avma; return gerepilecopy(av, vecfactoroddu_i(a,b)); } /* If 0 <= a <= c <= b; L[c-a+1] = factoru(c)[,1] if c squarefree, else NULL */ GEN vecfactorsquarefreeu(ulong a, ulong b) { ulong k, p, n = b-a+1, N = maxomegau(b) + 1; GEN v = const_vecsmall(n, 1); GEN L = cgetg(n+1, t_VEC); forprime_t T; for (k = 1; k <= n; k++) gel(L,k) = vecsmalltrunc_init(N); u_forprime_init(&T, 2, usqrt(b)); while ((p = u_forprime_next(&T))) { /* p <= sqrt(b), kill nonsquarefree */ ulong j, pk = p*p, t = a / pk, ap = t * pk; if (ap < a) ap += pk; for (j = ap-a+1; j <= n; j += pk) gel(L,j) = NULL; t = a / p; ap = t * p; if (ap < a) { ap += p; t++; } for (j = ap-a+1; j <= n; j += p, t++) if (gel(L,j)) { v[j] *= p; vecsmalltrunc_append(gel(L,j), p); } } /* complete factorisation of non-sqrt(b)-smooth numbers */ for (k = 1, N = a; k <= n; k++, N++) if (gel(L,k) && uel(v,k) != N) vecsmalltrunc_append(gel(L,k), N/uel(v,k)); return L; } /* If 0 <= a <= c <= b; L[c-a+1] = factoru(c)[,1] if c squarefree and coprime * to all the primes in sorted zv P, else NULL */ GEN vecfactorsquarefreeu_coprime(ulong a, ulong b, GEN P) { ulong k, p, n = b-a+1, sqb = usqrt(b), N = maxomegau(b) + 1; GEN v = const_vecsmall(n, 1); GEN L = cgetg(n+1, t_VEC); forprime_t T; for (k = 1; k <= n; k++) gel(L,k) = vecsmalltrunc_init(N); u_forprime_init(&T, 2, sqb); while ((p = u_forprime_next(&T))) { /* p <= sqrt(b), kill nonsquarefree */ ulong j, t, ap, bad = zv_search(P, p), pk = bad ? p: p * p; t = a / pk; ap = t * pk; if (ap < a) ap += pk; for (j = ap-a+1; j <= n; j += pk) gel(L,j) = NULL; if (bad) continue; t = a / p; ap = t * p; if (ap < a) { ap += p; t++; } for (j = ap-a+1; j <= n; j += p, t++) if (gel(L,j)) { v[j] *= p; vecsmalltrunc_append(gel(L,j), p); } } if (uel(P,lg(P)-1) <= sqb) P = NULL; /* complete factorisation of non-sqrt(b)-smooth numbers */ for (k = 1, N = a; k <= n; k++, N++) if (gel(L,k) && uel(v,k) != N) { ulong q = N / uel(v,k); if (!P || !zv_search(P, q)) vecsmalltrunc_append(gel(L,k), q); } return L; } GEN vecsquarefreeu(ulong a, ulong b) { ulong j, k, p, n = b-a+1; GEN L = const_vecsmall(n, 1); forprime_t T; u_forprime_init(&T, 2, usqrt(b)); while ((p = u_forprime_next(&T))) { /* p <= sqrt(b), kill nonsquarefree */ ulong pk = p*p, t = a / pk, ap = t * pk; if (ap < a) { ap += pk; t++; } /* t = (j+a-1) \ pk */ for (j = ap-a+1; j <= n; j += pk, t++) L[j] = 0; } for (k = j = 1; k <= n; k++) if (L[k]) L[j++] = a+k-1; setlg(L,j); return L; } pari-2.17.2/src/basemath/Flv.c0000644000175000017500000007671714567450071014465 0ustar billbill/* Copyright (C) 2000-2019 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" GEN Flv_to_ZV(GEN x) { pari_APPLY_type(t_VEC, utoi(x[i])) } GEN Flc_to_ZC(GEN x) { pari_APPLY_type(t_COL, utoi(x[i])) } GEN Flm_to_ZM(GEN x) { pari_APPLY_type(t_MAT, Flc_to_ZC(gel(x,i))) } GEN Flc_to_ZC_inplace(GEN z) { long i, l = lg(z); for (i=1; i r2 || (j1 <= r1 && R1[j1] < R2[j2])) { gel(*C, j) = gel(C1, j1); (*R)[j] = R1[j1++]; } else { gel(*C, j) = gel(C2, j2); (*R)[j] = R2[j2++]; } } if (gc_needed(av, 1)) gerepileall(av, 2, R, C); return r; } static void /* assume m < p */ _Fl_addmul(GEN b, long k, long i, ulong m, ulong p, ulong pi) { uel(b,k) = Fl_addmul_pre(uel(b, k), m, uel(b, i), p, pi); } static void /* same m = 1 */ _Fl_add(GEN b, long k, long i, ulong p) { uel(b,k) = Fl_add(uel(b,k), uel(b,i), p); } static void /* assume m < p && SMALL_ULONG(p) && (! (b[i] & b[k] & HIGHMASK)) */ _Fl_addmul_OK(GEN b, long k, long i, ulong m, ulong p) { uel(b,k) += m * uel(b,i); if (uel(b,k) & HIGHMASK) uel(b,k) %= p; } static void /* assume SMALL_ULONG(p) && (! (b[i] & b[k] & HIGHMASK)) */ _Fl_add_OK(GEN b, long k, long i, ulong p) { uel(b,k) += uel(b,i); if (uel(b,k) & HIGHMASK) uel(b,k) %= p; } /* assume 0 <= a[i,j] < p */ static GEN Fl_get_col_OK(GEN a, GEN b, long li, ulong p) { GEN u = cgetg(li+1,t_VECSMALL); ulong m = uel(b,li) % p; long i,j; uel(u,li) = (m * ucoeff(a,li,li)) % p; for (i = li-1; i > 0; i--) { m = p - uel(b,i)%p; for (j = i+1; j <= li; j++) { if (m & HIGHBIT) m %= p; m += ucoeff(a,i,j) * uel(u,j); /* 0 <= u[j] < p */ } m %= p; if (m) m = ((p-m) * ucoeff(a,i,i)) % p; uel(u,i) = m; } return u; } static GEN Fl_get_col(GEN a, GEN b, long li, ulong p) { GEN u = cgetg(li+1,t_VECSMALL); ulong m = uel(b,li) % p; long i,j; uel(u,li) = Fl_mul(m, ucoeff(a,li,li), p); for (i=li-1; i>0; i--) { m = b[i]%p; for (j = i+1; j <= li; j++) m = Fl_sub(m, Fl_mul(ucoeff(a,i,j), uel(u,j), p), p); if (m) m = Fl_mul(m, ucoeff(a,i,i), p); uel(u,i) = m; } return u; } static GEN Flm_ker_gauss_OK(GEN x, ulong p, long deplin) { GEN y, c, d; long i, j, k, r, t, m, n; ulong a; n = lg(x)-1; m=nbrows(x); r=0; c = zero_zv(m); d = cgetg(n+1, t_VECSMALL); a = 0; /* for gcc -Wall */ for (k=1; k<=n; k++) { for (j=1; j<=m; j++) if (!c[j]) { a = ucoeff(x,j,k) % p; if (a) break; } if (j > m) { if (deplin==1) { c = cgetg(n+1, t_VECSMALL); for (i=1; i m) { if (deplin==1) { c = cgetg(n+1, t_VECSMALL); for (i=1; i= Flm_CUP_LIMIT && nbrows(x) >= Flm_CUP_LIMIT) switch(deplin) { case 0: return Flm_ker_echelon(x, p, 0); case 1: return Flm_deplin_echelon(x, p); case 2: return Flm_ker_echelon(x, p, 1); } return Flm_ker_gauss(inplace? x: Flm_copy(x), p, deplin); } GEN Flm_ker_sp(GEN x, ulong p, long deplin) { return Flm_ker_i(x, p, deplin, 1); } GEN Flm_ker(GEN x, ulong p) { return Flm_ker_i(x, p, 0, 0); } GEN Flm_deplin(GEN x, ulong p) { return Flm_ker_i(x, p, 1, 0); } /* in place, destroy a, SMALL_ULONG(p) is TRUE */ static ulong Flm_det_gauss_OK(GEN a, long nbco, ulong p) { long i,j,k, s = 1; ulong q, x = 1; for (i=1; i nbco) return ucoeff(a,i,i); if (k != i) { /* exchange the lines s.t. k = i */ for (j=i; j<=nbco; j++) lswap(ucoeff(a,i,j), ucoeff(a,k,j)); s = -s; } q = ucoeff(a,i,i); if (x & HIGHMASK) x %= p; x *= q; q = Fl_inv(q,p); for (k=i+1; k<=nbco; k++) { ulong m = ucoeff(a,i,k) % p; if (!m) continue; m = p - ((m*q)%p); for (j=i+1; j<=nbco; j++) { ulong c = ucoeff(a,j,k); if (c & HIGHMASK) c %= p; ucoeff(a,j,k) = c + m*ucoeff(a,j,i); } } } if (x & HIGHMASK) x %= p; q = ucoeff(a,nbco,nbco); if (q & HIGHMASK) q %= p; x = (x*q) % p; if (s < 0 && x) x = p - x; return x; } /* in place, destroy a */ static ulong Flm_det_gauss(GEN a, ulong p) { long i,j,k, s = 1, nbco = lg(a)-1; ulong pi, q, x = 1; if (SMALL_ULONG(p)) return Flm_det_gauss_OK(a, nbco, p); pi = get_Fl_red(p); for (i=1; i nbco) return ucoeff(a,i,i); if (k != i) { /* exchange the lines s.t. k = i */ for (j=i; j<=nbco; j++) lswap(ucoeff(a,i,j), ucoeff(a,k,j)); s = -s; } q = ucoeff(a,i,i); x = Fl_mul_pre(x, q, p, pi); q = Fl_inv(q,p); for (k=i+1; k<=nbco; k++) { ulong m = ucoeff(a,i,k); if (!m) continue; m = Fl_mul_pre(m, q, p, pi); for (j=i+1; j<=nbco; j++) ucoeff(a,j,k) = Fl_sub(ucoeff(a,j,k), Fl_mul_pre(m,ucoeff(a,j,i), p, pi), p); } } if (s < 0) x = Fl_neg(x, p); return Fl_mul(x, ucoeff(a,nbco,nbco), p); } static ulong Flm_det_CUP(GEN a, ulong p) { GEN R, C, U, P; long i, n = lg(a) - 1, r; ulong d; ulong pi = get_Fl_red(p); r = Flm_CUP_pre(a, &R, &C, &U, &P, p, pi); if (r < n) d = 0; else { d = perm_sign(P) == 1? 1: p-1; for (i = 1; i <= n; i++) d = Fl_mul_pre(d, ucoeff(U, i, i), p, pi); } return d; } static ulong Flm_det_i(GEN x, ulong p, long inplace) { pari_sp av = avma; ulong d; if (lg(x) - 1 >= Flm_CUP_LIMIT) d = Flm_det_CUP(x, p); else d = Flm_det_gauss(inplace? x: Flm_copy(x), p); return gc_ulong(av, d); } ulong Flm_det_sp(GEN x, ulong p) { return Flm_det_i(x, p, 1); } ulong Flm_det(GEN x, ulong p) { return Flm_det_i(x, p, 0); } /* Destroy x */ static GEN Flm_gauss_pivot(GEN x, ulong p, long *rr) { GEN c,d; long i,j,k,r,t,n,m; n=lg(x)-1; if (!n) { *rr=0; return NULL; } m=nbrows(x); r=0; d=cgetg(n+1,t_VECSMALL); c = zero_zv(m); for (k=1; k<=n; k++) { for (j=1; j<=m; j++) if (!c[j]) { ucoeff(x,j,k) %= p; if (ucoeff(x,j,k)) break; } if (j>m) { r++; d[k]=0; } else { ulong piv = p - Fl_inv(ucoeff(x,j,k), p); c[j]=k; d[k]=j; for (i=k+1; i<=n; i++) ucoeff(x,j,i) = Fl_mul(piv, ucoeff(x,j,i), p); for (t=1; t<=m; t++) if (!c[t]) /* no pivot on that line yet */ { piv = ucoeff(x,t,k); if (piv) { ucoeff(x,t,k) = 0; for (i=k+1; i<=n; i++) ucoeff(x,t,i) = Fl_add(ucoeff(x,t,i), Fl_mul(piv,ucoeff(x,j,i),p),p); } } for (i=k; i<=n; i++) ucoeff(x,j,i) = 0; /* dummy */ } } *rr = r; return gc_const((pari_sp)d, d); } static GEN Flm_pivots_CUP(GEN x, ulong p, long *rr) { long i, n = lg(x) - 1, r; GEN R, C, U, P, d = zero_zv(n); ulong pi = get_Fl_red(p); r = Flm_CUP_pre(x, &R, &C, &U, &P, p, pi); for(i = 1; i <= r; i++) d[P[i]] = R[i]; *rr = n - r; return gc_const((pari_sp)d, d); } GEN Flm_pivots(GEN x, ulong p, long *rr, long inplace) { if (lg(x) - 1 >= Flm_CUP_LIMIT && nbrows(x) >= Flm_CUP_LIMIT) return Flm_pivots_CUP(x, p, rr); return Flm_gauss_pivot(inplace? x: Flm_copy(x), p, rr); } long Flm_rank(GEN x, ulong p) { pari_sp av = avma; long r; if (lg(x) - 1 >= Flm_CUP_LIMIT && nbrows(x) >= Flm_CUP_LIMIT) { GEN R, C; ulong pi = get_Fl_red(p); return gc_long(av, Flm_echelon_pre(x, &R, &C, p, pi)); } (void) Flm_pivots(x, p, &r, 0); return gc_long(av, lg(x)-1 - r); } /* assume dim A >= 1, A invertible + upper triangular, 1s on diagonal, * reduced mod p */ static GEN Flm_inv_upper_1_ind(GEN A, long index, ulong p) { long n = lg(A)-1, i = index, j; GEN u = const_vecsmall(n, 0); u[i] = 1; if (SMALL_ULONG(p)) for (i--; i>0; i--) { ulong m = ucoeff(A,i,i+1) * uel(u,i+1); /* j = i+1 */ for (j=i+2; j<=n; j++) { if (m & HIGHMASK) m %= p; m += ucoeff(A,i,j) * uel(u,j); } u[i] = Fl_neg(m % p, p); } else for (i--; i>0; i--) { ulong m = Fl_mul(ucoeff(A,i,i+1),uel(u,i+1), p); /* j = i+1 */ for (j=i+2; j<=n; j++) m = Fl_add(m, Fl_mul(ucoeff(A,i,j),uel(u,j),p), p); u[i] = Fl_neg(m, p); } return u; } static GEN Flm_inv_upper_1(GEN A, ulong p) { long i, l; GEN B = cgetg_copy(A, &l); for (i = 1; i < l; i++) gel(B,i) = Flm_inv_upper_1_ind(A, i, p); return B; } /* destroy a, b */ static GEN Flm_gauss_sp_OK(GEN a, GEN b, ulong *detp, ulong p) { long i, j, k, li, bco, aco = lg(a)-1, s = 1; ulong det = 1; GEN u; li = nbrows(a); bco = lg(b)-1; for (i=1; i<=aco; i++) { ulong invpiv; /* Fl_get_col wants 0 <= a[i,j] < p for all i,j */ for (k = 1; k < i; k++) ucoeff(a,k,i) %= p; for (k = i; k <= li; k++) { ulong piv = ( ucoeff(a,k,i) %= p ); if (piv) { ucoeff(a,k,i) = Fl_inv(piv, p); if (detp) { if (det & HIGHMASK) det %= p; det *= piv; } break; } } /* found a pivot on line k */ if (k > li) return NULL; if (k != i) { /* swap lines so that k = i */ s = -s; for (j=i; j<=aco; j++) swap(gcoeff(a,i,j), gcoeff(a,k,j)); for (j=1; j<=bco; j++) swap(gcoeff(b,i,j), gcoeff(b,k,j)); } if (i == aco) break; invpiv = p - 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_add_OK(gel(a,j),k,i, p); for (j=1; j<=bco; j++) _Fl_add_OK(gel(b,j),k,i, p); } else { for (j=i+1; j<=aco; j++) _Fl_addmul_OK(gel(a,j),k,i,m, p); for (j=1; j<=bco; j++) _Fl_addmul_OK(gel(b,j),k,i,m, p); } } } if (detp) { det %= p; if (s < 0 && det) det = p - det; *detp = det; } u = cgetg(bco+1,t_MAT); for (j=1; j<=bco; j++) gel(u,j) = Fl_get_col_OK(a,gel(b,j), aco,p); return u; } /* destroy a, b */ static GEN Flm_gauss_sp_i(GEN a, GEN b, ulong *detp, ulong p) { long i, j, k, li, bco, aco = lg(a)-1, s = 1; ulong det = 1; GEN u; ulong pi; if (!aco) { if (detp) *detp = 1; return cgetg(1,t_MAT); } if (SMALL_ULONG(p)) return Flm_gauss_sp_OK(a, b, detp, p); pi = get_Fl_red(p); li = nbrows(a); bco = lg(b)-1; for (i=1; i<=aco; i++) { ulong invpiv; /* Fl_get_col wants 0 <= a[i,j] < p for all i,j */ for (k = i; k <= li; k++) { ulong piv = ucoeff(a,k,i); if (piv) { ucoeff(a,k,i) = Fl_inv(piv, p); if (detp) det = Fl_mul_pre(det, piv, p, pi); break; } } /* found a pivot on line k */ if (k > li) return NULL; if (k != i) { /* swap lines so that k = i */ s = -s; for (j=i; j<=aco; j++) swap(gcoeff(a,i,j), gcoeff(a,k,j)); for (j=1; j<=bco; j++) swap(gcoeff(b,i,j), gcoeff(b,k,j)); } if (i == aco) break; invpiv = p - ucoeff(a,i,i); /* -1/piv mod p */ for (k=i+1; k<=li; k++) { ulong m = ucoeff(a,k,i); if (!m) continue; m = Fl_mul_pre(m, invpiv, p, pi); if (m == 1) { for (j=i+1; j<=aco; j++) _Fl_add(gel(a,j),k,i, p); for (j=1; j<=bco; j++) _Fl_add(gel(b,j),k,i, p); } else { for (j=i+1; j<=aco; j++) _Fl_addmul(gel(a,j),k,i,m, p, pi); for (j=1; j<=bco; j++) _Fl_addmul(gel(b,j),k,i,m, p, pi); } } } if (detp) { if (s < 0 && det) det = p - det; *detp = det; } u = cgetg(bco+1,t_MAT); for (j=1; j<=bco; j++) gel(u,j) = Fl_get_col(a,gel(b,j), aco,p); return u; } static GEN Flm_gauss_from_CUP(GEN b, GEN R, GEN C, GEN U, GEN P, ulong p, ulong pi, ulong *detp) { GEN Y = Flm_rsolve_lower_unit_pre(rowpermute(C, R), rowpermute(b, R), p, pi); GEN X = rowpermute(Flm_rsolve_upper_pre(U, Y, p, pi), perm_inv(P)); if (detp) { ulong d = perm_sign(P) == 1? 1: p-1; long i, r = lg(R); for (i = 1; i < r; i++) d = Fl_mul_pre(d, ucoeff(U, i, i), p, pi); *detp = d; } return X; } static GEN Flm_gauss_CUP(GEN a, GEN b, ulong *detp, ulong p) { GEN R, C, U, P; long n = lg(a) - 1, r; ulong pi = get_Fl_red(p); if (nbrows(a) < n || (r = Flm_CUP_pre(a, &R, &C, &U, &P, p, pi)) < n) return NULL; return Flm_gauss_from_CUP(b, R, C, U, P, p, pi, detp); } GEN Flm_gauss_sp(GEN a, GEN b, ulong *detp, ulong p) { pari_sp av = avma; GEN x; if (lg(a) - 1 >= Flm_CUP_LIMIT) x = Flm_gauss_CUP(a, b, detp, p); else x = Flm_gauss_sp_i(a, b, detp, p); if (!x) return gc_NULL(av); return gerepileupto(av, x); } GEN Flm_gauss(GEN a, GEN b, ulong p) { pari_sp av = avma; GEN x; if (lg(a) - 1 >= Flm_CUP_LIMIT) x = Flm_gauss_CUP(a, b, NULL, p); else { a = RgM_shallowcopy(a); b = RgM_shallowcopy(b); x = Flm_gauss_sp(a, b, NULL, p); } if (!x) return gc_NULL(av); return gerepileupto(av, x); } static GEN Flm_inv_i(GEN a, ulong *detp, ulong p, long inplace) { pari_sp av = avma; long n = lg(a) - 1; GEN b, x; if (n == 0) return cgetg(1, t_MAT); b = matid_Flm(nbrows(a)); if (n >= Flm_CUP_LIMIT) x = Flm_gauss_CUP(a, b, detp, p); else { if (!inplace) a = RgM_shallowcopy(a); x = Flm_gauss_sp(a, b, detp, p); } if (!x) return gc_NULL(av); return gerepileupto(av, x); } GEN Flm_inv_sp(GEN a, ulong *detp, ulong p) { return Flm_inv_i(a, detp, p, 1); } GEN Flm_inv(GEN a, ulong p) { return Flm_inv_i(a, NULL, p, 0); } GEN Flm_Flc_gauss(GEN a, GEN b, ulong p) { pari_sp av = avma; GEN z = Flm_gauss(a, mkmat(b), p); if (!z) return gc_NULL(av); if (lg(z) == 1) { set_avma(av); return cgetg(1,t_VECSMALL); } return gerepileuptoleaf(av, gel(z,1)); } GEN Flm_adjoint(GEN A, ulong p) { pari_sp av = avma; GEN R, C, U, P, C1, U1, v, c, d; long r, i, q, n = lg(A)-1, m; ulong D; ulong pi = get_Fl_red(p); if (n == 0) return cgetg(1, t_MAT); r = Flm_CUP_pre(A, &R, &C, &U, &P, p, pi); m = nbrows(A); if (r == n) { GEN X = Flm_gauss_from_CUP(matid_Flm(m), R, C, U, P, p, pi, &D); return gerepileupto(av, Flm_Fl_mul_pre(X, D, p, pi)); } if (r < n-1) return zero_Flm(n, m); for (q = n, i = 1; i < n; i++) if (R[i] != i) { q = i; break; } C1 = matslice(C, 1, q-1, 1, q-1); c = vecslice(Flm_row(C, q), 1, q-1); c = Flm_lsolve_lower_unit_pre(C1, Flm_transpose(mkmat(c)), p, pi); d = cgetg(m+1, t_VECSMALL); for (i=1; i= Flm_CUP_LIMIT && nbrows(B) >= Flm_CUP_LIMIT) return Flm_invimage_CUP(A, B, p); x = Flm_ker(shallowconcat(Flm_neg(A,p), B), p); /* AX = BY, Y in strict upper echelon form with pivots = 1. * We must find T such that Y T = Id_nB then X T = Z. This exists iff * Y has at least nB columns and full rank */ nY = lg(x)-1; if (nY < nB) return NULL; Y = rowslice(x, nA+1, nA+nB); /* nB rows */ d = cgetg(nB+1, t_VECSMALL); for (i = nB, j = nY; i >= 1; i--, j--) { for (; j>=1; j--) if (coeff(Y,i,j)) { d[i] = j; break; } if (!j) return NULL; } /* reduce to the case Y square, upper triangular with 1s on diagonal */ Y = vecpermute(Y, d); x = vecpermute(x, d); X = rowslice(x, 1, nA); return Flm_mul(X, Flm_inv_upper_1(Y,p), p); } GEN Flm_invimage(GEN A, GEN B, ulong p) { pari_sp av = avma; GEN X = Flm_invimage_i(A,B,p); if (!X) return gc_NULL(av); return gerepileupto(av, X); } GEN Flm_Flc_invimage(GEN A, GEN y, ulong p) { pari_sp av = avma; long i, l = lg(A); GEN M, x; ulong t; if (l==1) return NULL; if (lg(y) != lgcols(A)) pari_err_DIM("Flm_Flc_invimage"); M = cgetg(l+1,t_MAT); for (i=1; i= 1 and #VC = F, the conductor of the character or multicharacter X. * VC contains [X(1),X(2),...X(F)] */ static GEN mycall(GEN VC, long n) { long F = lg(VC) - 1; GEN z = n <= F ? gel(VC, n) : gel(VC, ((n - 1) % F) + 1); return gequal0(z)? NULL: z; } static GEN get_chivec(GEN VCALL) { return gel(VCALL, 1); } static long get_modulus(GEN VCALL) { return itos(gel(VCALL, 2)); } static GEN get_signat(GEN VCALL) { return gel(VCALL, 3); } static GEN get_gauss(GEN VCALL) { return gel(VCALL, 4); } static GEN get_chiZ(GEN VCALL) { return gel(VCALL, 5); } /* (-1)^A[i] * conj(B[i]) */ static GEN gnegconj(GEN A, GEN B) { long i, l = lg(A); GEN W = cgetg(l, t_VEC); for (i = 1; i < l; i++) { GEN b = gconj(gel(B,i)); gel(W,i) = A[i]? gneg(b): b; } return W; } /* g(conj(CHI)) */ static GEN gaussconj(GEN VCALL) { return gnegconj(get_signat(VCALL), get_gauss(VCALL)); } static GEN myinitconj(GEN VCALL) { GEN CONJ = shallowcopy(VCALL); gel(CONJ, 1) = gconj(get_chivec(VCALL)); gel(CONJ, 4) = gaussconj(VCALL); return CONJ; } /********************************************************************/ /* Driver Program */ /********************************************************************/ /* assume |Im(s)| >> 1, in particular s is not a negative integer */ static GEN applyfuneq(GEN gau, GEN s, GEN z, long odd, long q, long bitprec) { GEN t, S; long prec; if (!gequal0(s)) bitprec += maxss(gexpo(s), 0); prec = nbits2prec(bitprec); if (odd) gau = mulcxmI(gau); S = gmul(Pi2n(-1, prec), gsubgs(s, odd)); t = ginv(gmul2n(gmul(gcos(S, prec), ggamma(s, prec)), 1)); t = gmul(gpow(gdivgs(Pi2n(1, prec), q), s, prec), t); return gmul(gmul(gau, t), z); } static GEN RZchi(GEN VCALL, GEN s, long prec); /* VCALL already initialized */ static GEN lfunlarge_char(GEN VCALL, GEN s, long bitprec) { pari_sp av = avma; GEN sig, tau, z; long funeq = 0, ts = typ(s), stau, flconj, q; if (!is_real_t(ts) && ts != t_COMPLEX) pari_err_TYPE("lfunlarge_char", s); sig = real_i(s); tau = imag_i(s); if (gexpo(tau) < 1) pari_err_DOMAIN("lfun","im(s)", "<", gen_2, tau); stau = gsigne(tau); if (stau < 0) { tau = gneg(tau); VCALL = myinitconj(VCALL); } if (gcmp(sig, ghalf) < 0) { funeq = 1; sig = gsubsg(1, sig); } flconj = ((stau > 0 && funeq) || (stau < 0 && !funeq)); q = get_modulus(VCALL); bitprec += gexpo(stoi(q)); z = RZchi(VCALL, mkcomplex(sig, tau), nbits2prec(bitprec)); if (flconj) z = gconj(z); if (funeq) { GEN odd = get_signat(VCALL), gau = get_gauss(VCALL), Vz; long lC = lg(gau), j; Vz = cgetg(lC, t_VEC); for (j = 1; j < lC; j++) gel(Vz,j) = applyfuneq(gel(gau,j), s, gel(z,j), odd[j], q, bitprec); z = Vz; } return gerepilecopy(av, z); } static GEN lfungetchars(GEN pol) { GEN L, F, v, bnf = Buchall(pol_x(1), 0, LOWDEFAULTPREC); GEN w, condall, bnr; long i, l, lc; condall = rnfconductor(bnf, pol); bnr = gel(condall, 2); L = bnrchar(bnr, gel(condall, 3), NULL); lc = lg(L); F = cgetg(lc, t_VEC); for (i = 1; i < lc; i++) { GEN chi = gel(L, i), cond = bnrconductor_raw(bnr, chi); gel(F, i) = gcoeff(gel(cond,1), 1, 1); } w = vec_equiv(F); l = lg(w); v = cgetg(l, t_COL); for (i = 1; i < l; i++) { GEN wi = gel(w, i), vi; long j, li = lg(wi); gel(v,i) = vi = cgetg(li, t_VEC); if (li == 2 && equali1(gel(F, wi[1]))) /* common conductor is 1 */ gel(vi,1) = lfunmisc_to_ldata_shallow(gen_1); else { for (j = 1; j < li; j++) gel(vi,j) = lfunmisc_to_ldata_shallow(mkvec2(bnr, gel(L, wi[j]))); } } return v; } /********************************************************************/ /* NEW RS IMPLEMENTATION FROM SANDEEP TYAGI */ /********************************************************************/ /* See arXiv:2203.02509v2 */ static long m_n0(GEN sel) { return itos(gel(sel, 1)); } static GEN m_r0(GEN sel) { return gel(sel, 2); } static GEN m_al(GEN sel) { return gel(sel, 3); } static GEN m_aleps(GEN sel) { return gel(sel, 4); } static GEN m_h(GEN sel) { return gel(sel, 5); } static GEN m_lin(GEN sel) { return gel(sel, 6); } static long m_np(GEN sel) { return itou(gel(sel, 7)); } static GEN phi_hat(GEN x, long prec) { GEN y; if (gsigne(imag_i(x)) > 0) y = gneg(gexpm1(gneg(gmul(PiI2(prec), x)), prec)); else y = gexpm1(gmul(PiI2(prec), x), prec); return ginv(y); } static GEN phi_hat_h0(GEN sel, long k, long prec) { GEN t = gdiv(gsubsg(m_n0(sel) + k, m_r0(sel)), m_aleps(sel)); return phi_hat(gdiv(gasinh(t, prec), m_h(sel)), prec); } /* v[i] = A[i] * (a + (-1)^E[i] b) */ static GEN mul_addsub(GEN A, GEN a, GEN b, GEN E) { long i, l = lg(E); GEN v = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(v,i) = gmul(gel(A,i), E[i]? gsub(a, b): gadd(a, b)); return v; } static GEN wd(GEN VCALL, GEN pmd, GEN x, long prec) { GEN VC = get_chivec(VCALL), E = get_signat(VCALL), Z = get_chiZ(VCALL); GEN ex, emx, xpmd = gmul(x, pmd), y = NULL; long md = get_modulus(VCALL), N = 2*md, k; ex = gexp(mulcxI(xpmd), prec); emx = ginv(ex); for (k = 1; k <= (md-1) / 2; k++) { GEN xc = mycall(VC, k); if (xc) { GEN p3, p2, p1 = gmul(xc, gel(Z, Fl_neg(Fl_sqr(k,N), N) + 1)); GEN a = gmul(ex, gel(Z, N - k + 1)), b = gmul(emx, gel(Z, k + 1)); GEN c = gmul(ex, gel(Z, k + 1)), d = gmul(emx, gel(Z, N - k + 1)); if (odd(md)) { p2 = ginv(mulcxmI(gmul2n(gsub(a,b), -1))); /* 1 / sin(xpmd - kpmd) */ p3 = ginv(mulcxmI(gmul2n(gsub(c,d), -1))); /* 1 / sin(xpmd + kpmd) */ } else { p2 = mulcxI(gdiv(gadd(a,b), gsub(a,b))); /* cotan(xpmd - kpmd) */ p3 = mulcxI(gdiv(gadd(c,d), gsub(c,d))); /* cotan(xpmd + kpmd) */ } p1 = mul_addsub(p1, p2, p3, E); y = y ? gadd(y, p1) : p1; } } return mulcxmI(gdivgs(y, N)); } static GEN series_h0(long n0, GEN s, GEN VCALL, long fl, long prec) { GEN C = get_modulus(VCALL) == 1? NULL: get_chivec(VCALL); GEN R = pardirpowerssumfun(C, n0, gneg(s), fl, prec); if (C) return R; if (fl) return mkvec2(mkvec(gel(R,1)), mkvec(gel(R,2))); return mkvec(R); } static GEN series_residues_h0(GEN sel, GEN s, GEN VCALL, long prec) { long n0 = m_n0(sel), np = m_np(sel), k; GEN val = gen_0, VC = get_chivec(VCALL); for (k = maxss(1 - np, 1 - n0); k <= 1 + np; k++) { GEN nk = mycall(VC, n0 + k); /* n0 + k > 0 */ if (nk) val = gadd(val, gmul(gmul(phi_hat_h0(sel, k, prec), nk), gpow(stoi(n0 + k), gneg(s), prec))); } return val; } static GEN integrand_h0(GEN sel, GEN s, GEN VCALL, GEN x, long prec) { pari_sp av = avma; long md = get_modulus(VCALL); GEN r0 = m_r0(sel), aleps = m_aleps(sel), zn, p1; GEN pmd = divru(mppi(prec), md), ix = ginv(x); zn = gadd(r0, gdivgs(gmul(aleps, gsub(x, ix)), 2)); p1 = gmul(expIxy(pmd, gsqr(zn), prec), gmul(gpow(zn, gneg(s), prec), gmul(aleps, gadd(x, ix)))); if (md == 1) p1 = gdiv(mkvec(mulcxI(p1)), gmul2n(gsin(gmul(pmd, zn), prec), 2)); else p1 = gdivgs(gmul(p1, wd(VCALL, pmd, zn, prec)), -2); return gerepileupto(av, p1); } static GEN integral_h0(GEN sel, GEN s, GEN VCALL, long prec) { GEN lin_grid = m_lin(sel), S = gen_0; pari_sp av = avma; long j, l = lg(lin_grid); for (j = 1; j < l; j++) { S = gadd(S, integrand_h0(sel, s, VCALL, gel(lin_grid, j), prec)); if ((j & 0xff) == 0) S = gerepileupto(av, S); } return gerepileupto(av, gmul(m_h(sel), S)); } /* a + log |x|, a t_REAL, low accuracy */ static GEN addrlogabs(GEN a, GEN x) { long prec = DEFAULTPREC; if (gequal0(x)) return real_m2n(64, prec); /* -oo */ switch(typ(x)) { case t_COMPLEX: return gmul2n(glog(cxnorm(x), prec), -1); case t_REAL: break; default: x = gtofp(x, prec); } return addrr(a, logr_abs(x)); } struct fun_q_t { GEN sel, s, VCALL, B; }; static GEN fun_q(void *E, GEN x) { struct fun_q_t *S = (struct fun_q_t *)E; GEN z = integrand_h0(S->sel,S->s,S->VCALL, gexp(x,DEFAULTPREC), DEFAULTPREC); if (typ(z) == t_VEC) z = vecsum(z); return addrlogabs(S->B, z); } static GEN brent_q(void *E, GEN (*f)(void*,GEN), GEN q_low, GEN q_hi) { if (gsigne(f(E, q_low)) * gsigne(f(E, q_hi)) >= 0) return NULL; return zbrent(E, f, q_low, q_hi, LOWDEFAULTPREC); } static GEN findq(void *E, GEN (*f)(void*,GEN), GEN lq, long B) { GEN q_low, q_hi, q_right, q_left, q_est = gasinh(lq, LOWDEFAULTPREC); q_low = gdivgs(gmulsg(4, q_est), 5); q_hi = gdivgs(gmulsg(3, q_est), 2); q_right = brent_q(E, f, q_low, q_hi); if (!q_right) q_right = q_est; q_left = brent_q(E, f, gneg(q_low), gneg(q_hi)); if (!q_left) q_left = q_est; return bitprecision0(gmax(q_right, q_left), B); } static GEN set_q_value(GEN sel, GEN s, GEN VCALL, long prec) { struct fun_q_t E; GEN al = m_al(sel), lq; long md = get_modulus(VCALL), LD = DEFAULTPREC; E.sel = sel; E.s = s; E.VCALL = VCALL, E.B = mulur(prec, mplog2(LD)); lq = gdiv(gsqrt(gdiv(gmulsg(md, E.B), Pi2n(1, LD)), LD), al); return findq((void*)&E, &fun_q, lq, prec); } static GEN setlin_grid_exp(GEN h, long m, long prec) { GEN w, vex = gpowers(gexp(h, prec), (m - 1)/2); long i; w = cgetg(m+1, t_VEC); gel(w, (m + 1)/2) = gen_1; for (i = (m + 3)/2; i <= m; i++) { GEN t1 = gel(vex, i - ((m - 1)/2)); gel(w, i) = t1; gel(w, (m + 1) - i) = ginv(t1); } return w; } static long get_m(GEN q, long prec) { GEN t = divrr(mulur(4 * prec2nbits(prec), mplog2(prec)), sqrr(mppi(prec))); return 2*itos(gfloor(mulrr(q, t))) + 1; } static GEN RZinit(GEN s, GEN VCALL, GEN numpoles, long prec) { GEN sel, al, aleps, n0, r0, q, h; long md = get_modulus(VCALL), m; al = gcmpgs(gabs(imag_i(s), prec), 100) < 0 ? ginv(stoi(4)) : gen_1; r0 = gsqrt(gdiv(gmulgs(s, md), PiI2(prec)), prec); n0 = gfloor(gsub(real_i(r0), imag_i(r0))); aleps = gmul(al, gexp(PiI2n(-2, prec), prec)); sel = mkvecn(7, n0, r0, al, aleps, NULL, NULL, numpoles); q = set_q_value(sel, s, VCALL, prec); m = get_m(q, prec); gel(sel,5) = h = divru(q, (m - 1) >> 1); gel(sel,6) = setlin_grid_exp(h, m, prec); return sel; } static GEN xpquo_one(GEN s, GEN cs, GEN ga, long odd, long md, long prec) { GEN rho, a = odd? gen_1: gen_0, z = divsr(md, mppi(prec)); rho = gmul(gdiv(gpow(gen_I(), gdivgs(gneg(a), 2), prec), gsqrt(ga, prec)), gpow(stoi(md), ginv(stoi(4)), prec)); return gmul(gdiv(gconj(gmul(rho, gpow(z, gdivgs(cs, 2), prec))), gmul(rho, gpow(z, gdivgs(s, 2), prec))), gexp(gsub(gconj(glngamma(gdivgs(gadd(cs, a), 2), prec)), glngamma(gdivgs(gadd(s, a), 2), prec)), prec)); } static GEN xpquo(GEN s, GEN VCALL, long prec) { long md = get_modulus(VCALL), n, lve, i; GEN cd = NULL, z, pz, cs, VC = get_chivec(VCALL), ve, R; if (!gequal0(s)) prec = nbits2prec(prec2nbits(prec) + maxss(gexpo(s), 0)); z = gexp(gdivgs(PiI2(prec), -md), prec); if (md == 1) return gmul(gpow(mppi(prec), gsub(s, ghalf), prec), gexp(gsub(glngamma(gdivgs(gsubsg(1, s), 2), prec), glngamma(gdivgs(s, 2), prec)), prec)); pz = gpowers(z, md - 1); for (n = 1; n < md; n++) { GEN xn = mycall(VC, n); if (xn) { GEN tmp = gmul(xn, gel(pz, n + 1)); cd = cd ? gadd(cd, tmp) : tmp; } } cs = gsubsg(1, gconj(s)); ve = get_signat(VCALL); lve = lg(ve); R = cgetg(lve, t_VEC); for (i = 1; i < lve; i++) gel(R, i) = xpquo_one(s, cs, gel(cd, i), ve[i], md, prec); if (lve == 2) R = gel(R, 1); return R; } static GEN total_value(GEN serh0, GEN sel, GEN s, GEN VCALL, long prec) { return gadd(integral_h0(sel, s, VCALL, prec), gsub(serh0, series_residues_h0(sel, s, VCALL, prec))); } static GEN dirichlet_ours(GEN s, GEN VCALL, long prec) { int fl = !gequal(real_i(s), ghalf); GEN sel = RZinit(s, VCALL, gen_1, prec); GEN S1, S2, serh0 = series_h0(m_n0(sel), s, VCALL, fl, prec); if (!fl) S2 = S1 = total_value(serh0, sel, s, VCALL, prec); else { S1 = total_value(gel(serh0,1), sel, s, VCALL, prec); S2 = total_value(gconj(gel(serh0,2)), sel, gsubsg(1, gconj(s)), VCALL, prec); } return gadd(S1, vecmul(xpquo(s, VCALL, prec), gconj(S2))); } /* assume |Im(s)| > 2^-bitprec */ static GEN RZchi(GEN VCALL, GEN s, long prec) { long prec2 = prec + EXTRAPREC64; return gprec_wtrunc(dirichlet_ours(gprec_w(s, prec2), VCALL, prec2), prec); } /********************************************************************/ /* Utility Functions */ /********************************************************************/ /* lam = 0, return L(s); else Lambda(s) */ static GEN lfuncharall(GEN VCALL, GEN s, long lam, long bitprec) { GEN ve, P, Q, R, z = lfunlarge_char(VCALL, s, bitprec); long l, i, q, prec; if (!lam) return z; ve = get_signat(VCALL); l = lg(ve); q = get_modulus(VCALL); prec = nbits2prec(bitprec); R = cgetg(l, t_VEC); Q = divur(q, mppi(prec)); P = (q == 1 || zv_equal0(ve))? NULL: gsqrt(utoipos(q), prec); for (i = 1; i < l; i++) { GEN se = gmul2n(gaddgs(s, ve[i]), -1), r; if (lam == 1) { r = gmul(gpow(Q, se, prec), ggamma(se, prec)); if (P && ve[i]) r = gdiv(r, P); } else { r = gadd(gmul(se, glog(Q, prec)), glngamma(se, prec)); if (P && ve[i]) r = gsub(r, glog(P, prec)); } gel(R, i) = r; } return lam == 1 ? vecmul(R, z) : gadd(R, glog(z, prec)); } static GEN lfunlargeall_from_chars(GEN v, GEN s, long lam, long bit) { long i, l = lg(v); for (i = 1; i < l; i++) { GEN w = mycharinit(gel(v, i), bit), L = lfuncharall(w, s, lam, bit); gel(v, i) = lam==-1 ? vecsum(L): vecprod(L); } return lam==-1 ? vecsum(v): vecprod(v); } static GEN lfunlargeall(GEN ldata, GEN s, long lam, long bit) { GEN w, an; if (lg(ldata) == 2) { /* HACK: ldata[1] a t_DESC_PRODUCT from lfunabelianrelinit / Q */ GEN v = lfunprod_get_fact(linit_get_tech(gel(ldata,1))); long i, l; v = shallowcopy(gel(v,1)); l = lg(v); for (i = 1; i < l; i++) gel(v,i) = mkvec(gel(v,i)); return lfunlargeall_from_chars(v, s, lam, bit); } an = gel(ldata_get_an(ldata), 2); switch(ldata_get_type(ldata)) { case t_LFUN_NF: { GEN v = lfungetchars(nf_get_pol(an)); return lfunlargeall_from_chars(v, s, lam, bit); } case t_LFUN_CHIGEN: { GEN chi = gmael(an, 2, 2); if (lg(chi) > 1 && is_vec_t(typ(gel(chi,1)))) { /* multi char */ w = mycharinit(mkcol(ldata), bit); return lfuncharall(w, s, lam, bit); } } default: /* single char */ w = mycharinit(mkcol(ldata), bit); return gel(lfuncharall(w, s, lam, bit), 1); } } GEN lfunlarge(GEN CHI, GEN s, long bit) { return lfunlargeall(CHI, s, 0, bit); } GEN lfunlambdalarge(GEN CHI, GEN s, long bit) { return lfunlargeall(CHI, s, 1, bit); } GEN lfunloglambdalarge(GEN CHI, GEN s, long bit) { return lfunlargeall(CHI, s, -1, bit); } /********************************************************************/ /* LERCH RS IMPLEMENTATION FROM SANDEEP TYAGI */ /********************************************************************/ static GEN double_exp_residue_pos_h(GEN selsm, long k, long ind, long prec) { long nk = itos(gel(selsm, 1)) + k; GEN r = gel(selsm, 2), ale = gel(selsm, 3), aor = gel(selsm, 4); GEN h = gel(selsm, 5), t = gen_0; switch(ind) { case 0: t = gaddsg(nk, aor); break; case 1: t = gneg(gaddsg(nk, aor)); break; case 2: t = gsubsg(nk, aor); break; } return gdiv(gasinh(gdiv(gsub(t, r), ale), prec), h); } static GEN phi_hat_h(GEN selsm, long m, long ind, long prec) { return phi_hat(double_exp_residue_pos_h(selsm, m, ind, prec), prec); } static long myex(GEN is) { return gequal0(is) ? 0 : maxss(0, 2 + gexpo(is)); } static GEN gaminus(GEN s, long prec) { GEN is = imag_i(s), tmp; long B = prec2nbits(prec); if (gcmpgs(is, -5*B) < 0) return gen_0; prec = nbits2prec(B + myex(is)); tmp = gexp(gsub(glngamma(s, prec), gmul(PiI2n(-1, prec), s)), prec); return bitprecision0(tmp, B); } static GEN gaplus(GEN s, long prec) { GEN is = imag_i(s), tmp; long B = prec2nbits(prec); if (gcmpgs(is, 5*B) > 0) return gen_0; prec = nbits2prec(B + myex(is)); tmp = gexp(gadd(glngamma(s, prec), gmul(PiI2n(-1, prec), s)), prec); return bitprecision0(tmp, B); } GEN serh_worker(GEN k, GEN z, GEN a, GEN ns, GEN gprec) { long prec = itou(gprec); return gmul(gpow(z, k, prec), gpow(gadd(a, k), ns, prec)); } static void set_arg(GEN worker, GEN z, GEN a, GEN ns, long prec) { gel(worker, 7) = mkvec4(z, a, ns, stoi(prec)); } static GEN series_h0l(GEN worker, long n0, GEN s, GEN a, GEN lam, long prec) { GEN z = typ(lam) == t_INT ? gen_1 : gexp(gmul(PiI2(prec), lam), prec); set_arg(worker, z, a, gneg(s), prec); return parsum(gen_0, utoi(n0), worker); } static GEN series_h1(GEN worker, long n1, GEN s, GEN a, GEN lam, long prec) { GEN mP, pre_factor, z, sn = gsubgs(s, 1); GEN ini = gequal0(lam) ? gen_1 : gen_0; pre_factor = gaplus(gneg(sn), prec); if (gequal0(pre_factor)) return gen_0; mP = gneg(PiI2(prec)); pre_factor = gmul(gmul(pre_factor, gexp(gmul(mP, gmul(a, lam)), prec)), gpow(Pi2n(1, prec), sn, prec)); z = typ(a) == t_INT ? gen_1 : gexp(gmul(mP, a), prec); set_arg(worker, z, lam, sn, prec); return gmul(pre_factor, parsum(ini, stoi(n1 - 1), worker)); } static GEN series_h2(GEN worker, long n2, GEN s, GEN a, GEN lam, long prec) { GEN P, pre_factor, z, sn = gsubgs(s, 1); pre_factor = gaminus(gneg(sn), prec); if (gequal0(pre_factor)) return gen_0; P = PiI2(prec); pre_factor = gmul(gmul(pre_factor, gexp(gmul(gneg(P), gmul(a, lam)), prec)), gpow(Pi2n(1, prec), sn, prec)); z = typ(a) == t_INT ? gen_1 : gexp(gmul(P, a), prec); set_arg(worker, z, gneg(lam), sn, prec); return gmul(pre_factor, parsum(gen_1, stoi(n2), worker)); } static GEN series_residues_h0l(long numpoles, GEN selsm0, GEN s, GEN a, GEN lam, long prec) { GEN P, val = gen_0, ra = real_i(a); long n0 = m_n0(selsm0), k; P = PiI2(prec); for (k = -numpoles + 1; k <= numpoles; k++) if (gsigne(gaddsg(n0 + k, ra)) > 0) val = gadd(val, gmul(gmul(phi_hat_h(selsm0, k, 0, prec), gexp(gmul(P, gmulgs(lam, n0 + k)), prec)), gpow(gaddsg(n0 + k, a), gneg(s), prec))); return val; } static GEN series_residues_h1(long numpoles, GEN selsm1, GEN s, GEN a, GEN lam, long prec) { GEN mP, val = gen_0, rlam = real_i(lam), pre_factor, sn = gsubgs(s, 1); long n1 = m_n0(selsm1), k; pre_factor = gaplus(gneg(sn), prec); if (gequal0(pre_factor)) return gen_0; mP = gneg(PiI2(prec)); pre_factor = gmul(gmul(pre_factor, gexp(gmul(mP, gmul(a, lam)), prec)), gpow(Pi2n(1, prec), sn, prec)); for (k = -numpoles; k <= numpoles - 1; k++) if (gsigne(gaddsg(n1 + k, rlam)) > 0) val = gadd(val, gmul(gmul(phi_hat_h(selsm1, k, 1, prec), gexp(gmul(mP, gmulgs(a, n1 + k)), prec)), gpow(gaddsg(n1 + k, lam), sn, prec))); return gmul(pre_factor, val); } static GEN series_residues_h2(long numpoles, GEN selsm2, GEN s, GEN a, GEN lam, long prec) { GEN P, val = gen_0, rlam = real_i(lam), pre_factor, sn = gsubgs(s, 1); long n2 = m_n0(selsm2), k; pre_factor = gaminus(gneg(sn), prec); if (gequal0(pre_factor)) return gen_0; P = PiI2(prec); pre_factor = gmul(gmul(pre_factor, gexp(gmul(gneg(P), gmul(a, lam)), prec)), gpow(Pi2n(1, prec), sn, prec)); for (k = -numpoles + 1; k <= numpoles; k++) if (gsigne(gsubsg(n2 + k, rlam)) > 0) val = gsub(val, gmul(gmul(phi_hat_h(selsm2, k, 2, prec), gexp(gmul(P, gmulgs(a, n2 + k)), prec)), gpow(gsubsg(n2 + k, lam), sn, prec))); return gmul(pre_factor, val); } static GEN integrand_h0l(GEN selsm0, GEN s, GEN alam1, GEN x, long prec) { GEN r0 = gel(selsm0, 2), ale = gel(selsm0, 3), a = gel(selsm0, 4); GEN ix = ginv(x), zn = gadd(r0, gmul2n(gmul(ale, gsub(x, ix)), -1)); GEN P = PiI2n(0, prec), den, num; den = gexpm1(gmul(P, gmul2n(gsub(zn,a), 1)), prec); num = gexp(gmul(gmul(P, zn), gsub(alam1, zn)), prec); num = gmul(gmul(gmul(num, ale), gmul2n(gadd(x, ix), -1)), gpow(zn, gneg(s), prec)); return gdiv(num, den); } static GEN integrand_h12(GEN selsm1, GEN s, GEN alam1, GEN x, long prec) { GEN r1 = gel(selsm1, 2), ale = gel(selsm1, 3), lam = gel(selsm1, 4); GEN ix = ginv(x), zn = gadd(r1, gmul2n(gmul(ale, gsub(x, ix)), -1)); GEN P = PiI2n(0, prec), den, num, y; den = gexpm1(gmul(P, gmul2n(gadd(zn,lam), 1)), prec); num = gexp(gmul(gmul(P, zn), gadd(alam1, zn)), prec); num = gmul(gmul(gmul(num, ale), gmul2n(gadd(x, ix), -1)), gpow(zn, gsubgs(s, 1), prec)); y = gdiv(num, den); if (gcmp(garg(zn, prec), Pi2n(-2, prec)) > 0) y = gmul(y, gexp(gmul(PiI2(prec), gsubsg(1, s)), prec)); return y; } static GEN integral_h0l(GEN lin_grid, GEN selsm0, GEN s, GEN a, GEN lam, long prec) { GEN A = gaddgs(gmul2n(gadd(a, lam),1), 1), S = gen_0; pari_sp av = avma; long j, l = lg(lin_grid); for (j = 1; j < l; j++) { S = gadd(S, integrand_h0l(selsm0, s, A, gel(lin_grid, j), prec)); if ((j & 0xff) == 0) S = gerepileupto(av, S); } S = gmul(m_h(selsm0), S); A = gmul(a, gaddsg(1, gadd(a, gmul2n(lam, 1)))); return gmul(S, gexp(gneg(gmul(PiI2n(0, prec), A)), prec)); } /* do not forget a minus sign for index 2 */ static GEN integral_h12(GEN lin_grid, GEN selsm1, GEN s, GEN a, GEN lam, long prec) { GEN A, E, S = gen_0, ga = gaminus(gsubsg(1, s), prec); pari_sp av = avma; long j, l = lg(lin_grid); if (gequal0(ga)) return S; A = gaddgs(gmul2n(gadd(a,lam), 1), 1); for (j = 1; j < l; j++) { S = gadd(S, integrand_h12(selsm1, s, A, gel(lin_grid, j), prec)); if ((j & 0xff) == 0) S = gerepileupto(av, S); } if (gequal0(S)) return gen_0; S = gmul(m_h(selsm1), S); E = gexp(gmul(PiI2n(0, prec), gmul(lam, gaddgs(lam, 1))), prec); return gmul(gmul(gmul(S, ga), E), gpow(Pi2n(1, prec), gsubgs(s, 1), prec)); } struct _fun_q0_t { GEN sel, s, alam1, B; }; static GEN _fun_q0(void *E, GEN x) { struct _fun_q0_t *S = (struct _fun_q0_t*)E; GEN z = integrand_h0l(S->sel, S->s, S->alam1, x, DEFAULTPREC); return addrlogabs(S->B, z); } static GEN _fun_q12(void *E, GEN x) { struct _fun_q0_t *S = (struct _fun_q0_t*)E; GEN z = integrand_h12(S->sel, S->s, S->alam1, x, DEFAULTPREC); return addrlogabs(S->B, z); } static GEN RZLERinit(GEN s, GEN a, GEN lam, GEN al, GEN numpoles, long prec) { GEN eps, r0, r1, r2, h, lin_grid, q, q0, q1, q2, sel0, sel1, sel2, lq; GEN pinv = ginv(PiI2(prec)), c = gmul2n(gadd(a, lam), -1), n0, n1, n2, c2; long m; struct _fun_q0_t E; if (!al || gequal0(al)) al = gcmpgs(gabs(imag_i(s), prec), 100) < 0 ? ginv(stoi(4)) : gen_1; c2 = gsub(gsqr(c), gmul(s, pinv)); r0 = gadd(c, gsqrt(c2, prec)); r1 = gsqrt(gadd(c2, pinv), prec); r2 = gsub(r1, c); r1 = gneg(gadd(r1, c)); n0 = gfloor(gsub(gadd(real_i(r0), imag_i(r0)), a)); n1 = gneg(gfloor(gadd(gsub(real_i(r1), imag_i(r1)), real_i(lam)))); n2 = gfloor(gadd(gsub(real_i(r2), imag_i(r2)), real_i(lam))); E.s = s; E.alam1 = gaddgs(gmul2n(gadd(a, lam), 1), 1); E.B = mulur(prec, mplog2(prec)); lq = gmul(al, sqrtr_abs(mulrr(divsr(prec, Pi2n(1, DEFAULTPREC)), mplog2(DEFAULTPREC)))); eps = gexp(PiI2n(-2, prec), prec); E.sel = sel0 = mkvec5(n0, r0, gdiv(al, eps), a, gen_0); q0 = findq(&E, &_fun_q0, lq, prec); if (!gequal1(al)) lq = gdiv(lq, gsqr(al)); E.sel = sel1 = mkvec5(n1, r1, gmul(al, eps), lam, gen_0); q1 = findq(&E, &_fun_q12, lq, prec); E.sel = sel2 = mkvec5(n2, r2, gmul(al, eps), lam, gen_0); q2 = findq(&E, &_fun_q12, lq, prec); q = vecmax(mkvec3(q0, q1, q2)); m = get_m(q, prec); gel(sel0, 5) = gel(sel1, 5) = gel(sel2, 5) = h = divru(q, (m-1) >> 1); lin_grid = setlin_grid_exp(h, m, prec); if (!numpoles) numpoles = gen_1; return mkvec5(sel0, sel1, sel2, lin_grid, numpoles); } static GEN add3(GEN x, GEN y, GEN z) { return gadd(x, gadd(y,z)); } static GEN addsub(GEN x, GEN y, GEN z) { return gadd(x, gsub(y,z)); } static GEN lerch_ours(GEN sel, GEN s, GEN a, GEN lam, long prec) { GEN selsm0 = gel(sel, 1), selsm1 = gel(sel, 2), selsm2 = gel(sel, 3); GEN lin_grid = gel(sel, 4), v0, v1, v2; long numpoles = itos(gel(sel, 5)); GEN worker = snm_closure(is_entry("_serh_worker"), mkvec4(NULL, NULL, NULL, NULL)); v0 = add3(series_h0l(worker, m_n0(selsm0), s, a, lam, prec), series_residues_h0l(numpoles, selsm0, s, a, lam, prec), integral_h0l(lin_grid, selsm0, s, a, lam, prec)); v1 = add3(series_h1(worker, m_n0(selsm1), s, a, lam, prec), series_residues_h1(numpoles, selsm1, s, a, lam, prec), integral_h12(lin_grid, selsm1, s, a, lam, prec)); v2 = addsub(series_h2(worker, m_n0(selsm2), s, a, lam, prec), series_residues_h2(numpoles, selsm2, s, a, lam, prec), integral_h12(lin_grid, selsm2, s, a, lam, prec)); return add3(v0, v1, v2); } static GEN RZlerch_easy(GEN s, GEN a, GEN lam, long prec) { pari_sp av = avma; GEN z, y, N; long B = prec2nbits(prec), LD = LOWDEFAULTPREC; N = gdiv(gmulsg(B + 5, mplog2(LD)), gmul(Pi2n(1, LD), imag_i(lam))); if (gexpo(N) > 40) pari_err_IMPL("precision too large in lerchzeta"); N = gceil(N); prec += EXTRAPREC64; z = typ(lam) == t_INT ? gen_1 : gexp(gmul(PiI2(prec), lam), prec); y = parsum(gen_0, N, snm_closure(is_entry("_serh_worker"), mkvec4(z, a, gneg(s), stoi(prec)))); return gerepilecopy(av, gprec_wtrunc(y, prec)); } static GEN mygfrac(GEN z) { return typ(z) == t_COMPLEX ? mkcomplex(gfrac(real_i(z)), imag_i(z)) : gfrac(z); } static GEN lerchlarge(GEN s, GEN a, GEN lam, GEN al, GEN numpoles, long prec) { pari_sp av = avma; GEN val, sel, imlam = imag_i(lam); long prec2; switch(gsigne(imlam)) { case -1: pari_err_IMPL("imag(lam) < 0"); case 1: if (gexpo(imlam) >= -16) return RZlerch_easy(s, a, lam, prec); } if (gcmpgs(real_i(a), 1) < 0) { GEN P = gexp(gmul(PiI2(prec), lam), prec); GEN L = lerchlarge(s, gaddgs(a, 1), lam, al, numpoles, prec); return gerepileupto(av, gadd(gpow(a, gneg(s), prec), gmul(P, L))); } if (gcmpgs(real_i(a), 2) >= 0) { GEN L, P = gexp(gneg(gmul(PiI2(prec), lam)), prec); a = gsubgs(a, 1); L = lerchlarge(s, a, lam, al, numpoles, prec); return gerepileupto(av, gmul(P, gsub(L, gpow(a, gneg(s), prec)))); } if (gsigne(imag_i(s)) > 0) { GEN L; lam = mygfrac(gneg(gconj(lam))); L = lerchlarge(gconj(s), a, lam, al, numpoles, prec); return gerepileupto(av, gconj(L)); } prec2 = prec + EXTRAPREC64; a = gprec_w(a, prec2); s = gprec_w(s, prec2); lam = gprec_w(lam, prec2); sel = RZLERinit(s, a, lam, al, numpoles, prec2); val = lerch_ours(sel, s, a, lam, prec2); return gerepilecopy(av, gprec_wtrunc(val, prec)); } GEN zetahurwitzlarge(GEN s, GEN a, long prec) { return lerchlarge(s, a, gen_0, gen_1, gen_1, prec); } GEN lerchzetalarge(GEN s, GEN a, GEN lam, long prec) { return lerchlarge(s, a, lam, gen_1, gen_1, prec); } pari-2.17.2/src/basemath/FpV.c0000644000175000017500000012460514760123736014417 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_mat /********************************************************************/ /** **/ /** REDUCTION **/ /** **/ /********************************************************************/ /* z in Z^n, return lift(Col(z) * Mod(1,p)) */ GEN FpC_red(GEN x, GEN p) { pari_APPLY_type(t_COL, modii(gel(x,i), p)) } /* z in Z^n, return lift(Vec(z) * Mod(1,p)) */ GEN FpV_red(GEN x, GEN p) { pari_APPLY_type(t_VEC, modii(gel(x,i), p)) } GEN FpC_center(GEN x, GEN p, GEN pov2) { pari_APPLY_type(t_COL, Fp_center(gel(x,i), p, pov2)) } GEN Flv_center(GEN x, ulong p, ulong ps2) { pari_APPLY_ulong(Fl_center(uel(x,i),p,ps2)) } /* z in Mat m,n(Z), return lift(z * Mod(1,p)) */ GEN FpM_red(GEN x, GEN p) { pari_APPLY_same(FpC_red(gel(x,i), p)) } GEN FpM_center(GEN x, GEN p, GEN pov2) { pari_APPLY_same(FpC_center(gel(x,i), p,pov2)) } /* p != 3; assume entries in [0,p[ and ps2 = p>>1. */ static void _FpC_center_inplace(GEN z, GEN p, GEN ps2) { long i, l = lg(z); for (i = 1; i < l; i++) { /* HACK: assume p != 3, which ensures u = gen_[0-2] is never written to */ GEN u = gel(z,i); if (abscmpii(u, ps2) > 0) subiiz(u, p, u); } } static void _F3C_center_inplace(GEN z) { long i, l = lg(z); for (i = 1; i < l; i++) /* z[i] = 0, 1 : no-op */ if (equaliu(gel(z,i), 2)) gel(z,i) = gen_m1; } void FpC_center_inplace(GEN z, GEN p, GEN ps2) { if (equaliu(p, 3)) _F3C_center_inplace(z); else _FpC_center_inplace(z, p, ps2); } void FpM_center_inplace(GEN z, GEN p, GEN pov2) { long i, l = lg(z); if (equaliu(p, 3)) for (i = 1; i < l; i++) _F3C_center_inplace(gel(z,i)); else for (i = 1; i < l; i++) _FpC_center_inplace(gel(z,i), p, pov2); } GEN Flm_center(GEN x, ulong p, ulong ps2) { pari_APPLY_same(Flv_center(gel(x,i), p,ps2)) } GEN random_FpV(long d, GEN p) { long i; GEN y = cgetg(d+1,t_VEC); for (i=1; i<=d; i++) gel(y,i) = randomi(p); return y; } GEN random_FpC(long d, GEN p) { long i; GEN y = cgetg(d+1,t_COL); for (i=1; i<=d; i++) gel(y,i) = randomi(p); return y; } GEN random_Flv(long n, ulong p) { GEN y = cgetg(n+1, t_VECSMALL); long i; for (i=1; i<=n; i++) uel(y,i) = random_Fl(p); return y; } /********************************************************************/ /** **/ /** ADD, SUB **/ /** **/ /********************************************************************/ GEN FpC_add(GEN x, GEN y, GEN p) { pari_APPLY_type(t_COL, Fp_add(gel(x,i), gel(y,i), p)) } GEN FpV_add(GEN x, GEN y, GEN p) { pari_APPLY_type(t_VEC, Fp_add(gel(x,i), gel(y,i), p)) } GEN FpM_add(GEN x, GEN y, GEN p) { pari_APPLY_same(FpC_add(gel(x,i), gel(y,i), p)) } GEN Flv_add(GEN x, GEN y, ulong p) { if (p==2) pari_APPLY_ulong(x[i]^y[i]) else pari_APPLY_ulong(Fl_add(x[i], y[i], p)) } void Flv_add_inplace(GEN x, GEN y, ulong p) { long i, l = lg(x); if (p==2) for (i = 1; i < l; i++) x[i] ^= y[i]; else for (i = 1; i < l; i++) x[i] = Fl_add(x[i], y[i], p); } ulong Flv_sum(GEN x, ulong p) { long i, l = lg(x); ulong s = 0; if (p==2) for (i = 1; i < l; i++) s ^= x[i]; else for (i = 1; i < l; i++) s = Fl_add(s, x[i], p); return s; } GEN FpC_sub(GEN x, GEN y, GEN p) { pari_APPLY_type(t_COL, Fp_sub(gel(x,i), gel(y,i), p)) } GEN FpV_sub(GEN x, GEN y, GEN p) { pari_APPLY_type(t_VEC, Fp_sub(gel(x,i), gel(y,i), p)) } GEN FpM_sub(GEN x, GEN y, GEN p) { pari_APPLY_same(FpC_sub(gel(x,i), gel(y,i), p)) } GEN Flv_sub(GEN x, GEN y, ulong p) { pari_APPLY_ulong(Fl_sub(uel(x,i), uel(y,i), p)) } void Flv_sub_inplace(GEN x, GEN y, ulong p) { long i, l = lg(x); for (i = 1; i < l; i++) x[i] = Fl_sub(x[i], y[i], p); } GEN Flm_Fl_add(GEN x, ulong y, ulong p) { long l = lg(x), i, j; GEN z = cgetg(l,t_MAT); if (l==1) return z; if (l != lgcols(x)) pari_err_OP( "+", x, utoi(y)); for (i=1; i 1 and 0 < i < lgcols(x) */ static GEN ZMrow_ZC_mul_i(GEN x, GEN y, long lx, long i) { GEN c = mulii(gcoeff(x,i,1), gel(y,1)); long k; for (k = 2; k < lx; k++) { GEN t = mulii(gcoeff(x,i,k), gel(y,k)); if (signe(t)) c = addii(c, t); } return c; } static long zmrow_zc_mul(GEN x, GEN y, long lx, long i) { long k; long c = coeff(x,i,1) * y[1]; for (k = 2; k < lx; k++) c += coeff(x,i,k) * y[k]; return c; } GEN zm_zc_mul(GEN x, GEN y) { long lx = lg(x), l, i; GEN z; if (lx == 1) return cgetg(1, t_VECSMALL); l = lg(gel(x,1)); z = cgetg(l,t_VECSMALL); for (i=1; i= ZM_sw_bound */ static GEN Flm_mul_i(GEN x, GEN y, long l, long lx, long ly, ulong p, ulong pi) { ulong e = expu(p); #ifdef LONG_IS_64BIT /* Beware to update ZM_mul_i if this changes */ long Flm_sw_bound = e <= 29 ? 140: e <=62 ? 40: 70; #else long Flm_sw_bound = e <= 12 ? 230: e <=14 ? 170 : e <=17 ? 110: 120; #endif if (l <= Flm_sw_bound || lx <= Flm_sw_bound || ly <= Flm_sw_bound) return Flm_mul_classical(x, y, l, lx, ly, p, pi); else return Flm_mul_sw(x, y, l - 1, lx - 1, ly - 1, p, pi); } GEN Flm_mul_pre(GEN x, GEN y, ulong p, ulong pi) { long lx=lg(x), ly=lg(y); if (ly==1) return cgetg(1,t_MAT); if (lx==1) return zero_Flm(0, ly-1); return Flm_mul_i(x, y, lgcols(x), lx, ly, p, pi); } GEN Flm_mul(GEN x, GEN y, ulong p) { long lx=lg(x), ly=lg(y); if (ly==1) return cgetg(1,t_MAT); if (lx==1) return zero_Flm(0, ly-1); return Flm_mul_i(x, y, lgcols(x), lx, ly, p, get_Fl_red(p)); } GEN Flm_sqr(GEN x, ulong p) { long lx = lg(x); if (lx==1) return cgetg(1,t_MAT); return Flm_mul_i(x, x, lx, lx, lx, p, get_Fl_red(p)); } struct _Flm { ulong p; long n; }; static GEN _Flm_mul(void *E , GEN x, GEN y) { return Flm_mul(x,y,((struct _Flm*)E)->p); } static GEN _Flm_sqr(void *E, GEN x) { return Flm_sqr(x,((struct _Flm*)E)->p); } static GEN _Flm_one(void *E) { return matid_Flm(((struct _Flm*)E)->n); } GEN Flm_powu(GEN x, ulong n, ulong p) { struct _Flm d; if (!n) return matid(lg(x)-1); d.p = p; return gen_powu(x, n, (void*)&d, &_Flm_sqr, &_Flm_mul); } GEN Flm_powers(GEN x, ulong n, ulong p) { struct _Flm d; d.p = p; d.n = lg(x)-1; return gen_powers(x, n, 1, (void*)&d, &_Flm_sqr, &_Flm_mul, &_Flm_one); } static GEN _FpM_mul(void *p , GEN x, GEN y) { return FpM_mul(x,y,(GEN)p); } static GEN _FpM_sqr(void *p, GEN x) { return FpM_mul(x,x,(GEN)p); } GEN FpM_powu(GEN x, ulong n, GEN p) { if (!n) return matid(lg(x)-1); if (lgefint(p) == 3) { pari_sp av = avma; ulong pp = uel(p,2); GEN z; if (pp == 2) z = F2m_to_ZM(F2m_powu(ZM_to_F2m(x),n)); else z = Flm_to_ZM(Flm_powu(ZM_to_Flm(x, pp), n, pp)); return gerepileupto(av, z); } return gen_powu(x, n, (void*)p, &_FpM_sqr, &_FpM_mul); } /*Multiple a column vector by a line vector to make a matrix*/ GEN Flc_Flv_mul(GEN x, GEN y, ulong p) { 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++) { GEN zj = cgetg(lx,t_VECSMALL); for (i=1; is(E,0); _1 = S->s(E,1); for (i=1; i<=n; i++) { GEN z = const_col(n, _0); gel(z,i) = _1; gel(y, i) = z; } return y; } GEN matid_F2xqM(long n, GEN T) { void *E; const struct bb_field *S = get_F2xq_field(&E, T); return gen_matid(n, E, S); } GEN matid_FlxqM(long n, GEN T, ulong p) { void *E; const struct bb_field *S = get_Flxq_field(&E, T, p); return gen_matid(n, E, S); } GEN matid_Flm(long n) { GEN y = cgetg(n+1,t_MAT); long i; if (n < 0) pari_err_DOMAIN("matid_Flm", "dimension","<",gen_0,stoi(n)); for (i=1; i<=n; i++) { gel(y,i) = zero_zv(n); ucoeff(y, i,i) = 1; } return y; } GEN scalar_Flm(long s, long n) { long i; GEN y = cgetg(n+1,t_MAT); for (i=1; i<=n; i++) { gel(y,i) = zero_Flv(n); coeff(y, i,i) = s; } return y; } /********************************************************************/ /** **/ /** CONVERSIONS **/ /** **/ /********************************************************************/ GEN ZV_to_Flv(GEN x, ulong p) { pari_APPLY_ulong(umodiu(gel(x,i), p)) } GEN ZM_to_Flm(GEN x, ulong p) { pari_APPLY_same(ZV_to_Flv(gel(x,i), p)) } GEN ZMV_to_FlmV(GEN x, ulong m) { pari_APPLY_type(t_VEC,ZM_to_Flm(gel(x,i), m)) } /* TO INTMOD */ static GEN to_intmod(GEN x, GEN p) { retmkintmod(modii(x, p), p); } static GEN Fl_to_intmod(ulong x, GEN p) { retmkintmod(utoi(x), p); } GEN Fp_to_mod(GEN z, GEN p) { retmkintmod(modii(z, p), icopy(p)); } GEN FpX_to_mod_raw(GEN z, GEN p) { long i, l = lg(z); GEN x; if (l == 2) { x = cgetg(3,t_POL); x[1] = z[1]; gel(x,2) = mkintmod(gen_0,p); return x; } x = cgetg(l,t_POL); x[1] = z[1]; for (i=2; i1) pari_warn(warnmem,"Wiedemann: first loop, %ld",i); W = gerepileupto(av, W); } } b = FpX_renormalize(b, m+2); if (lgpol(b)==0) {set_avma(btop); continue; } M = FpX_halfgcd(b, pol_xn(m, 0), p); Q = FpX_neg(FpX_normalize(gcoeff(M, 2, 1),p),p); W = B; lQ =lg(Q); if (DEBUGLEVEL) err_printf("Wiedemann: deg. minpoly: %ld\n",lQ-3); V = FpC_Fp_mul(W, gel(Q, lQ-2), p); av = avma; for (i = lQ-3; i > 1; i--) { W = f(E, W); V = ZC_lincomb(gen_1, gel(Q,i), V, W); if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"Wiedemann: second loop, %ld",i); gerepileall(av, 2, &V, &W); } } V = FpC_red(V, p); W = FpC_sub(f(E,V), B, p); if (ZV_equal0(W)) return gerepilecopy(ltop, V); av = avma; for (i = 1; i <= n; ++i) { V = W; W = f(E, V); if (ZV_equal0(W)) return gerepilecopy(ltop, shallowtrans(V)); gerepileall(av, 2, &V, &W); } set_avma(btop); } return NULL; } GEN zMs_ZC_mul(GEN M, GEN B) { long i, j; long n = lg(B)-1; GEN V = zerocol(n); for (i = 1; i <= n; ++i) if (signe(gel(B, i))) { GEN R = gel(M, i), C = gel(R, 1), E = gel(R, 2); long l = lg(C); for (j = 1; j < l; ++j) { long k = C[j]; switch(E[j]) { case 1: gel(V, k) = gel(V,k)==gen_0 ? gel(B,i) : addii(gel(V, k), gel(B,i)); break; case -1: gel(V, k) = gel(V,k)==gen_0 ? negi(gel(B,i)) : subii(gel(V, k), gel(B,i)); break; default: gel(V, k) = gel(V,k)==gen_0 ? mulis(gel(B, i), E[j]) : addii(gel(V, k), mulis(gel(B, i), E[j])); break; } } } return V; } GEN FpMs_FpC_mul(GEN M, GEN B, GEN p) { return FpC_red(zMs_ZC_mul(M, B), p); } GEN FpV_FpMs_mul(GEN B, GEN M, GEN p) { long i, j, lM = lg(M); GEN V = cgetg(lM,t_VEC); for (i = 1; i < lM; ++i) { GEN z, R = gel(M, i), C = gel(R, 1), E = gel(R, 2); pari_sp av = avma; long lC = lg(C); if (lC == 1) { gel(V,i) = gen_0; continue; } z = mulis(gel(B, C[1]), E[1]); for (j = 2; j < lC; ++j) { GEN b = gel(B, C[j]); switch(E[j]) { case 1: z = addii(z, b); break; case -1: z = subii(z, b); break; default: z = addii(z, mulis(b, E[j])); break; } } gel(V,i) = gerepileuptoint(av, p? Fp_red(z, p): z); } return V; } GEN ZV_zMs_mul(GEN B, GEN M) { return FpV_FpMs_mul(B, M, NULL); } GEN ZlM_gauss(GEN a, GEN b, ulong p, long e, GEN C) { pari_sp av = avma, av2; GEN xi, xb, pi = gen_1, P; long i; if (!C) { C = Flm_inv(ZM_to_Flm(a, p), p); if (!C) pari_err_INV("ZlM_gauss", a); } P = utoipos(p); av2 = avma; xi = Flm_mul(C, ZM_to_Flm(b, p), p); xb = Flm_to_ZM(xi); for (i = 2; i <= e; i++) { pi = muliu(pi, p); /* = p^(i-1) */ b = ZM_Z_divexact(ZM_sub(b, ZM_nm_mul(a, xi)), P); if (gc_needed(av,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"ZlM_gauss. i=%ld/%ld",i,e); gerepileall(av2,3, &pi,&b,&xb); } xi = Flm_mul(C, ZM_to_Flm(b, p), p); xb = ZM_add(xb, nm_Z_mul(xi, pi)); } return gerepileupto(av, xb); } struct wrapper_modp_s { GEN (*f)(void*, GEN); void *E; GEN p; }; /* compute f(x) mod p */ static GEN wrap_relcomb_modp(void *E, GEN x) { struct wrapper_modp_s *W = (struct wrapper_modp_s*)E; return FpC_red(W->f(W->E, x), W->p); } static GEN wrap_relcomb(void*E, GEN x) { return zMs_ZC_mul((GEN)E, x); } static GEN wrap_relker(void*E, GEN x) { struct wrapper_modp_s *W = (struct wrapper_modp_s*)E; return FpV_FpMs_mul(x, (GEN) W->E, W->p); } /* Solve f(X) = B (mod p^e); blackbox version of ZlM_gauss */ GEN gen_ZpM_Dixon_Wiedemann(void *E, GEN (*f)(void*, GEN), GEN B, GEN p, long e) { struct wrapper_modp_s W; pari_sp av = avma; GEN xb, xi, pi = gen_1; long i; W.E = E; W.f = f; W.p = p; xi = gen_FpM_Wiedemann((void*)&W, wrap_relcomb_modp, FpC_red(B, p), p); /* f^(-1) B */ if (!xi || e == 1 || typ(xi) == t_VEC) return xi; xb = xi; for (i = 2; i <= e; i++) { pi = mulii(pi, p); /* = p^(i-1) */ B = ZC_Z_divexact(ZC_sub(B, f(E, xi)), p); if (gc_needed(av,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"gen_ZpM_Dixon_Wiedemann. i=%ld",i); gerepileall(av,3, &pi,&B,&xb); } xi = gen_FpM_Wiedemann((void*)&W, wrap_relcomb_modp, FpC_red(B, p), p); if (!xi) return NULL; if (typ(xi) == t_VEC) return gerepileupto(av, xi); xb = ZC_add(xb, ZC_Z_mul(xi, pi)); } return gerepileupto(av, xb); } static GEN vecprow(GEN A, GEN prow) { return mkvec2(vecsmallpermute(prow,gel(A,1)), gel(A,2)); } /* Solve the equation MX = A. Return either a solution as a t_COL, * or the index of a column which is linearly dependent from the others as a * t_VECSMALL with a single component. */ GEN ZpMs_ZpCs_solve(GEN M, GEN A, long nbrow, GEN p, long e) { pari_sp av = avma; GEN pcol, prow; long nbi=lg(M)-1, lR; long i, n; GEN Mp, Ap, Rp; pari_timer ti; if (DEBUGLEVEL) timer_start(&ti); RgMs_structelim(M, nbrow, gel(A, 1), &pcol, &prow); if (!pcol) return gc_NULL(av); if (DEBUGLEVEL) timer_printf(&ti,"structured elimination (%ld -> %ld)",nbi,lg(pcol)-1); n = lg(pcol)-1; Mp = cgetg(n+1, t_MAT); for(i=1; i<=n; i++) gel(Mp, i) = vecprow(gel(M,pcol[i]), prow); Ap = zCs_to_ZC(vecprow(A, prow), n); if (DEBUGLEVEL) timer_start(&ti); Rp = gen_ZpM_Dixon_Wiedemann((void*)Mp,wrap_relcomb, Ap, p, e); if (DEBUGLEVEL) timer_printf(&ti,"linear algebra"); if (!Rp) return gc_NULL(av); lR = lg(Rp)-1; if (typ(Rp) == t_COL) { GEN R = zerocol(nbi+1); for (i=1; i<=lR; i++) gel(R,pcol[i]) = gel(Rp,i); return gerepilecopy(av, R); } for (i = 1; i <= lR; ++i) if (signe(gel(Rp, i))) return gerepileuptoleaf(av, mkvecsmall(pcol[i])); return NULL; /* LCOV_EXCL_LINE */ } GEN FpMs_FpCs_solve(GEN M, GEN A, long nbrow, GEN p) { return ZpMs_ZpCs_solve(M, A, nbrow, p, 1); } GEN FpMs_FpCs_solve_safe(GEN M, GEN A, long nbrow, GEN p) { GEN res; pari_CATCH(e_INV) { GEN E = pari_err_last(); GEN x = err_get_compo(E,2); if (typ(x) != t_INTMOD) pari_err(0,E); if (DEBUGLEVEL) pari_warn(warner,"FpMs_FpCs_solve_safe, impossible inverse %Ps", x); res = NULL; } pari_TRY { res = ZpMs_ZpCs_solve(M, A, nbrow, p, 1); } pari_ENDCATCH return res; } static GEN FpMs_structelim_back(GEN M, GEN V, GEN prow, GEN p) { long i, j, oldf = 0, f = 0; long lrow = lg(prow), lM = lg(M); GEN W = const_vecsmall(lM-1,1); GEN R = cgetg(lrow, t_VEC); for (i=1; i=2) continue; if (c==1) { pari_sp av = avma; GEN s = gen_0; for(j=1; j %ld)",nbcol,lg(pcol)-1); n = lg(pcol)-1; Mp = cgetg(n+1, t_MAT); for (i=1; i<=n; i++) gel(Mp, i) = vecprow(gel(M,pcol[i]), prow); W.E = (void*)Mp; W.p = p; av2 = avma; for(;; set_avma(av2)) { GEN R, Rp, B = random_FpV(n, p), MB = FpV_FpMs_mul(B, Mp, p); if (DEBUGLEVEL) timer_start(&ti); pari_CATCH(e_INV) { GEN E = pari_err_last(), x = err_get_compo(E,2); if (typ(x) != t_INTMOD) pari_err(0,E); if (DEBUGLEVEL) pari_warn(warner,"FpMs_leftkernel_elt, impossible inverse %Ps", x); Rp = NULL; } pari_TRY { Rp = gen_FpM_Wiedemann((void*)&W, wrap_relker, MB, p); } pari_ENDCATCH if (!Rp) continue; if (typ(Rp)==t_COL) { Rp = FpC_sub(Rp,B,p); if (ZV_equal0(Rp)) continue; } R = FpMs_structelim_back(M, Rp, prow, p); if (DEBUGLEVEL) timer_printf(&ti,"Wiedemann left kernel"); return gerepilecopy(av, R); } } GEN FpMs_leftkernel_elt(GEN M, long nbrow, GEN p) { return FpMs_leftkernel_elt_col(M, lg(M)-1, nbrow, p); } pari-2.17.2/src/basemath/polarit2.c0000644000175000017500000033035514760123736015461 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /***********************************************************************/ /** **/ /** ARITHMETIC OPERATIONS ON POLYNOMIALS **/ /** (second part) **/ /** **/ /***********************************************************************/ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_pol /* compute Newton sums S_1(P), ... , S_n(P). S_k(P) = sum a_j^k, a_j root of P * If N != NULL, assume p-adic roots and compute mod N [assume integer coeffs] * If T != NULL, compute mod (T,N) [assume integer coeffs if N != NULL] * If y0!= NULL, precomputed i-th powers, i=1..m, m = length(y0). * Not memory clean in the latter case */ GEN polsym_gen(GEN P, GEN y0, long n, GEN T, GEN N) { long dP=degpol(P), i, k, m; pari_sp av1, av2; GEN s,y,P_lead; if (n<0) pari_err_IMPL("polsym of a negative n"); if (typ(P) != t_POL) pari_err_TYPE("polsym",P); if (!signe(P)) pari_err_ROOTS0("polsym"); y = cgetg(n+2,t_COL); if (y0) { if (typ(y0) != t_COL) pari_err_TYPE("polsym_gen",y0); m = lg(y0)-1; for (i=1; i<=m; i++) gel(y,i) = gel(y0,i); /* not memory clean */ } else { m = 1; gel(y,1) = stoi(dP); } P += 2; /* strip codewords */ P_lead = gel(P,dP); if (gequal1(P_lead)) P_lead = NULL; if (P_lead) { if (N) P_lead = Fq_inv(P_lead,T,N); else if (T) P_lead = QXQ_inv(P_lead,T); } for (k=m; k<=n; k++) { av1 = avma; s = (dP>=k)? gmulsg(k,gel(P,dP-k)): gen_0; for (i=1; i 0) y = subii(y, p); break; case -1: if (!po2 || abscmpii(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 0) { long j; for(j = 1;;j++) { v = RgX_gcd(r, t); tv = RgX_div(t, v); if (degpol(tv) > 0) gel(u, j*q) = tv; if (degpol(v) <= 0) break; r = RgX_div(r, v); t = v; } if (degpol(r) == 0) break; } if (!p) break; f = RgX_Frobenius_deflate(r, p); if (!f) { gel(u, q) = r; break; } } for (i = n; i; i--) if (degpol(gel(u,i))) break; setlg(u,i+1); return u; } /* Lmod contains modular factors of *F (NULL codes an empty slot: used factor) * Lfac accumulates irreducible factors as they are found. * p is a product of modular factors in Lmod[1..i-1] (NULL for p = 1), not * a rational factor of *F * Find an irreducible factor of *F divisible by p (by including * exhaustively further factors from Lmod[i..]); return 0 on failure, else 1. * Update Lmod, Lfac and *F */ static int RgX_cmbf(GEN p, long i, GEN BLOC, GEN Lmod, GEN Lfac, GEN *F) { pari_sp av; GEN q; if (i == lg(Lmod)) return 0; if (RgX_cmbf(p, i+1, BLOC, Lmod, Lfac, F) && p) return 1; if (!gel(Lmod,i)) return 0; p = p? RgX_mul(p, gel(Lmod,i)): gel(Lmod,i); av = avma; q = RgV_to_RgX(RgX_digits(p, BLOC), varn(*F)); if (degpol(q)) { GEN R, Q = RgX_divrem(*F, q, &R); if (signe(R)==0) { vectrunc_append(Lfac, q); *F = Q; return 1; } } set_avma(av); if (RgX_cmbf(p, i+1, BLOC, Lmod, Lfac, F)) { gel(Lmod,i) = NULL; return 1; } return 0; } static GEN factor_domain(GEN x, GEN flag); static GEN ok_bloc(GEN f, GEN BLOC, ulong c) { GEN F = poleval(f, BLOC); return issquarefree(c ? gmul(F,mkintmodu(1,c)): F)? F: NULL; } static GEN random_FpX_monic(long n, long v, GEN p) { long i, d = n + 2; GEN y = cgetg(d + 1, t_POL); y[1] = evalsigne(1) | evalvarn(v); for (i = 2; i < d; i++) gel(y,i) = randomi(p); gel(y,i) = gen_1; return y; } static GEN RgXY_factor_squarefree(GEN f, GEN dom) { pari_sp av = avma; ulong i, c = itou_or_0(residual_characteristic(f)); long vy = gvar2(f), val = RgX_valrem(f, &f), n = RgXY_degreex(f); GEN y, Lmod, F = NULL, BLOC = NULL, Lfac = coltrunc_init(degpol(f)+2); GEN gc = c? utoipos(c): NULL; if (val) { GEN x = pol_x(varn(f)); if (dom) { GEN c = Rg_get_1(dom); if (typ(c) != t_INT) x = RgX_Rg_mul(x, c); } vectrunc_append(Lfac, x); if (!degpol(f)) return Lfac; } y = pol_x(vy); for(;;) { for (i = 0; !c || i < c; i++) { BLOC = gpowgs(gaddgs(y, i), n+1); if ((F = ok_bloc(f, BLOC, c))) break; if (c) { BLOC = random_FpX_monic(n, vy, gc); if ((F = ok_bloc(f, BLOC, c))) break; } } if (!c || i < c) break; n++; } if (DEBUGLEVEL >= 2) err_printf("bifactor: bloc:(x+%ld)^%ld, deg f=%ld\n",i,n,RgXY_degreex(f)); Lmod = gel(factor_domain(F,dom),1); if (DEBUGLEVEL >= 2) err_printf("bifactor: %ld local factors\n",lg(Lmod)-1); (void)RgX_cmbf(NULL, 1, BLOC, Lmod, Lfac, &f); if (degpol(f)) vectrunc_append(Lfac, f); return gerepilecopy(av, Lfac); } static GEN FE_matconcat(GEN F, GEN E, long l) { setlg(E,l); E = shallowconcat1(E); setlg(F,l); F = shallowconcat1(F); return mkmat2(F,E); } static int gen_cmp_RgXY(void *data, GEN x, GEN y) { long vx = varn(x), vy = varn(y); return (vx == vy)? gen_cmp_RgX(data, x, y): -varncmp(vx, vy); } static GEN RgXY_factor(GEN f, GEN dom) { pari_sp av = avma; GEN C, F, E, cf, V; long i, j, l; if (dom) { GEN c = Rg_get_1(dom); if (typ(c) != t_INT) f = RgX_Rg_mul(f,c); } cf = content(f); V = RgXY_squff(gdiv(f, cf)); l = lg(V); C = factor_domain(cf, dom); F = cgetg(l+1, t_VEC); gel(F,1) = gel(C,1); E = cgetg(l+1, t_VEC); gel(E,1) = gel(C,2); for (i=1, j=2; i < l; i++) { GEN v = gel(V,i); if (degpol(v)) { gel(F,j) = v = RgXY_factor_squarefree(v, dom); gel(E,j) = const_col(lg(v)-1, utoipos(i)); j++; } } f = FE_matconcat(F,E,j); (void)sort_factor(f,(void*)cmp_universal, &gen_cmp_RgXY); return gerepilecopy(av, f); } /***********************************************************************/ /** **/ /** FACTORIZATION **/ /** **/ /***********************************************************************/ static long RgX_settype(GEN x, long *t, GEN *p, GEN *pol, long *pa, GEN *ff, long *t2, long *var); #define assign_or_fail(x,y) { GEN __x = x;\ if (!*y) *y=__x; else if (!gequal(__x,*y)) return 0;\ } #define update_prec(x,y) { long __x = x; if (__x < *y) *y=__x; } static const long tsh = 6; #define code(t1,t2) ((t1 << 6) | t2) void RgX_type_decode(long x, long *t1, long *t2) { *t1 = x >> tsh; *t2 = (x & ((1L<= tsh; } static int settype(GEN c, long *t, GEN *p, GEN *pol, long *pa, GEN *ff, long *t2, long *var) { long j; switch(typ(c)) { case t_INT: break; case t_FRAC: t[1]=1; break; break; case t_REAL: update_prec(precision(c), pa); t[2]=1; break; case t_INTMOD: assign_or_fail(gel(c,1),p); t[3]=1; break; case t_FFELT: if (!*ff) *ff=c; else if (!FF_samefield(c,*ff)) return 0; assign_or_fail(FF_p_i(c),p); t[5]=1; break; case t_COMPLEX: for (j=1; j<=2; j++) { GEN d = gel(c,j); switch(typ(d)) { case t_INT: case t_FRAC: if (!*t2) *t2 = t_COMPLEX; t[1]=1; break; case t_REAL: update_prec(precision(d), pa); if (!*t2) *t2 = t_COMPLEX; t[2]=1; break; case t_INTMOD: assign_or_fail(gel(d,1),p); if (!signe(*p) || mod4(*p) != 3) return 0; if (!*t2) *t2 = t_COMPLEX; t[3]=1; break; case t_PADIC: update_prec(precp(d)+valp(d), pa); assign_or_fail(gel(d,2),p); if (!*t2) *t2 = t_COMPLEX; t[7]=1; break; default: return 0; } } if (!t[2]) assign_or_fail(mkpoln(3, gen_1,gen_0,gen_1), pol); /*x^2+1*/ break; case t_PADIC: update_prec(precp(c)+valp(c), pa); assign_or_fail(gel(c,2),p); t[7]=1; break; case t_QUAD: assign_or_fail(gel(c,1),pol); for (j=2; j<=3; j++) { GEN d = gel(c,j); switch(typ(d)) { case t_INT: case t_FRAC: t[8]=1; break; case t_INTMOD: assign_or_fail(gel(d,1),p); if (*t2 != t_POLMOD) *t2 = t_QUAD; t[3]=1; break; case t_PADIC: update_prec(precp(d)+valp(d), pa); assign_or_fail(gel(d,2),p); if (*t2 != t_POLMOD) *t2 = t_QUAD; t[7]=1; break; default: return 0; } } break; case t_POLMOD: assign_or_fail(gel(c,1),pol); if (typ(gel(c,2))==t_POL && varn(gel(c,2))!=varn(gel(c,1))) return 0; for (j=1; j<=2; j++) { GEN pbis, polbis; long pabis; *t2 = t_POLMOD; switch(Rg_type(gel(c,j),&pbis,&polbis,&pabis)) { case t_INT: break; case t_FRAC: t[1]=1; break; case t_INTMOD: t[3]=1; break; case t_PADIC: t[7]=1; update_prec(pabis,pa); break; default: return 0; } if (pbis) assign_or_fail(pbis,p); if (polbis) assign_or_fail(polbis,pol); } break; case t_RFRAC: t[10] = 1; if (!settype(gel(c,1),t,p,pol,pa,ff,t2,var)) return 0; c = gel(c,2); /* fall through */ case t_POL: t[10] = 1; if (!RgX_settype(c,t,p,pol,pa,ff,t2,var)) return 0; if (*var == NO_VARIABLE) { *var = varn(c); break; } /* if more than one free var, ensure varn() == *var fails. FIXME: should * keep the list of all variables, later t_POLMOD may cancel them */ if (*var != varn(c)) *var = MAXVARN+1; break; default: return 0; } return 1; } /* t[0] unused. Other values, if set, indicate a coefficient of type * t[1] : t_FRAC * t[2] : t_REAL * t[3] : t_INTMOD * t[4] : Unused * t[5] : t_FFELT * t[6] : Unused * t[7] : t_PADIC * t[8] : t_QUAD of rationals (t_INT/t_FRAC) * t[9]: Unused * t[10]: t_POL (recursive factorisation) */ /* if t2 != 0: t_POLMOD/t_QUAD/t_COMPLEX of modular (t_INTMOD/t_PADIC, * given by t) */ static long choosetype(long *t, long t2, GEN ff, GEN *pol, long var) { if (t[10] && (!*pol || var!=varn(*pol))) return t_POL; if (t2) /* polmod/quad/complex of intmod/padic */ { if (t[2] && (t[3]||t[7])) return 0; if (t[3]) return code(t2,t_INTMOD); if (t[7]) return code(t2,t_PADIC); if (t[2]) return t_COMPLEX; if (t[1]) return code(t2,t_FRAC); return code(t2,t_INT); } if (t[5]) /* ffelt */ { if (t[2]||t[8]||t[9]) return 0; *pol=ff; return t_FFELT; } if (t[2]) /* inexact, real */ { if (t[3]||t[7]||t[9]) return 0; return t_REAL; } if (t[10]) return t_POL; if (t[8]) return code(t_QUAD,t_INT); if (t[3]) return t_INTMOD; if (t[7]) return t_PADIC; if (t[1]) return t_FRAC; return t_INT; } static long RgX_settype(GEN x, long *t, GEN *p, GEN *pol, long *pa, GEN *ff, long *t2, long *var) { long i, lx = lg(x); for (i=2; i (impose imag(x) >= 0) */ static GEN Qi_normal(GEN x) { if (typ(x) != t_COMPLEX) return absi_shallow(x); if (signe(gel(x,1)) < 0) x = gneg(x); if (signe(gel(x,2)) < 0) x = mulcxI(x); return x; } static GEN Qi_factor(GEN x) { pari_sp av = avma; GEN a = real_i(x), b = imag_i(x), 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 = real_i(y); t1 = typ(a); b = imag_i(y); t2 = typ(b); } if (t1 != t_INT || t2 != t_INT) return NULL; y = Qi_primpart(y, &n); fa = factor(cxnorm(y)); P = gel(fa,1); E = gel(fa,2); l = lg(P); P2 = cgetg(l, t_COL); E2 = cgetg(l, t_COL); for (j = 1, i = l-1; i > 0; i--) /* remove largest factors first */ { /* either p = 2 (ramified) or those factors split in Q(i) */ GEN p = gel(P,i), w, w2, t, we, pe; long v, e = itos(gel(E,i)); int is2 = absequaliu(p, 2); w = is2? mkcomplex(gen_1,gen_1): Qi_factor_p(p); w2 = Qi_normal( conj_i(w) ); /* w * w2 * I^3 = p, w2 = conj(w) * I */ pe = powiu(p, e); we = gpowgs(w, e); t = Qi_primpart_try( gmul(y, conj_i(we)), pe ); if (t) y = t; /* y /= w^e */ else { /* y /= conj(w)^e, should be y /= w2^e */ y = Qi_primpart_try( gmul(y, we), pe ); swap(w, w2); exp -= e; /* += 3*e mod 4 */ } gel(P,i) = w; v = Z_pvalrem(n, p, &n); if (v) { exp -= v; /* += 3*v mod 4 */ if (is2) v <<= 1; /* 2 = w^2 I^3 */ else { gel(P2,j) = w2; gel(E2,j) = utoipos(v); j++; } gel(E,i) = stoi(e + v); } v = Z_pvalrem(d, p, &d); if (v) { exp += v; /* -= 3*v mod 4 */ if (is2) v <<= 1; /* 2 is ramified */ else { gel(P2,j) = w2; gel(E2,j) = utoineg(v); j++; } gel(E,i) = stoi(e - v); } exp &= 3; } if (j > 1) { long k = 1; GEN P1 = cgetg(l, t_COL); GEN E1 = cgetg(l, t_COL); /* remove factors with exponent 0 */ for (i = 1; i < l; i++) if (signe(gel(E,i))) { gel(P1,k) = gel(P,i); gel(E1,k) = gel(E,i); k++; } setlg(P1, k); setlg(E1, k); setlg(P2, j); setlg(E2, j); fa = famat_mul_shallow(mkmat2(P1,E1), mkmat2(P2,E2)); } if (!equali1(n) || !equali1(d)) { GEN Fa = factor(Qdivii(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): Qi_factor_p(p); gel(P,i) = w; if (is2) gel(E,i) = stoi(2*e); else { P = vec_append(P, Qi_normal( conj_i(w) )); E = vec_append(E, gel(E,i)); } exp -= e; /* += 3*e mod 4 */ exp &= 3; } gel(Fa,1) = P; gel(Fa,2) = E; fa = famat_mul_shallow(fa, Fa); } fa = sort_factor(fa, (void*)&Qi_cmp, &cmp_nodata); y = gmul(y, powIs(exp)); if (!gequal1(y)) { gel(fa,1) = vec_prepend(gel(fa,1), y); gel(fa,2) = vec_prepend(gel(fa,2), gen_1); } return gerepilecopy(av, fa); } GEN Q_factor_limit(GEN x, ulong lim) { pari_sp av = avma; GEN a, b; if (typ(x) == t_INT) return Z_factor_limit(x, lim); a = Z_factor_limit(gel(x,1), lim); b = Z_factor_limit(gel(x,2), lim); gel(b,2) = ZC_neg(gel(b,2)); return gerepilecopy(av, ZM_merge_factor(a,b)); } GEN Q_factor(GEN x) { pari_sp av = avma; GEN a, b; if (typ(x) == t_INT) return Z_factor(x); a = Z_factor(gel(x,1)); b = Z_factor(gel(x,2)); gel(b,2) = ZC_neg(gel(b,2)); return gerepilecopy(av, ZM_merge_factor(a,b)); } /* replace t_QUAD/t_COMPLEX coeffs by t_POLMOD in T */ static GEN RgX_fix_quad(GEN x, GEN T) { long i, l, v = varn(T); GEN y = cgetg_copy(x,&l); for (i = 2; i < l; i++) { GEN c = gel(x,i); switch(typ(c)) { case t_QUAD: c++;/* fall through */ case t_COMPLEX: c = deg1pol_shallow(gel(c,2),gel(c,1),v); } gel(y,i) = c; } y[1] = x[1]; return y; } static GEN RgX_factor(GEN x, GEN dom) { pari_sp av; long pa, v, lx, r1, i; GEN p, pol, y, p1, p2; long tx = dom ? RgX_Rg_type(x,dom,&p,&pol,&pa): RgX_type(x,&p,&pol,&pa); switch(tx) { case 0: pari_err_IMPL("factor for general polynomials"); case t_POL: return RgXY_factor(x, dom); case t_INT: return ZX_factor(x); case t_FRAC: return QX_factor(x); case t_INTMOD: return factmod(x,p); case t_PADIC: return factorpadic(x,p,pa); case t_FFELT: return FFX_factor(x,pol); case t_COMPLEX: y = cgetg(3,t_MAT); av = avma; p1 = deg1_from_roots(roots(x,pa), varn(x)); gel(y,1) = p1 = gerepileupto(av, p1); gel(y,2) = const_col(lg(p1)-1, gen_1); return y; case t_REAL: y=cgetg(3,t_MAT); v=varn(x); av=avma; p1=cleanroots(x,pa); lx = lg(p1); for (r1 = 1; r1 < lx; r1++) if (typ(gel(p1,r1)) == t_COMPLEX) break; lx=(r1+lx)>>1; p2=cgetg(lx,t_COL); for (i = 1; i < r1; i++) gel(p2,i) = deg1pol_shallow(gen_1, negr(gel(p1,i)), v); for ( ; i < lx; i++) { GEN a = gel(p1,2*i-r1); p = cgetg(5, t_POL); gel(p2,i) = p; p[1] = x[1]; gel(p,2) = gnorm(a); gel(p,3) = gmul2n(gel(a,1),1); togglesign(gel(p,3)); gel(p,4) = gen_1; } gel(y,1) = gerepileupto(av,p2); gel(y,2) = const_col(lx-1, gen_1); return y; default: { GEN w = NULL, T = pol; long t1, t2; av = avma; RgX_type_decode(tx, &t1, &t2); if (t1 == t_COMPLEX) w = gen_I(); else if (t1 == t_QUAD) w = mkquad(pol,gen_0,gen_1); if (w) { /* substitute I or w by t_POLMOD */ T = leafcopy(pol); setvarn(T, fetch_var()); x = RgX_fix_quad(x, T); } switch (t2) { case t_INT: case t_FRAC: p1 = nffactor(T,x); break; case t_INTMOD: T = RgX_to_FpX(T,p); if (FpX_is_irred(T,p)) { p1 = factmod(x,mkvec2(p,T)); break; } /*fall through*/ default: if (w) (void)delete_var(); pari_err_IMPL("factor for general polynomial"); return NULL; /* LCOV_EXCL_LINE */ } if (t1 == t_POLMOD) return gerepileupto(av, p1); /* substitute back I or w */ gel(p1,1) = gsubst(liftpol_shallow(gel(p1,1)), varn(T), w); (void)delete_var(); return gerepilecopy(av, p1); } } } static GEN factor_domain(GEN x, GEN dom) { long tx = typ(x); long tdom = dom ? typ(dom): 0; pari_sp av; if (gequal0(x)) switch(tx) { case t_INT: case t_COMPLEX: case t_POL: case t_RFRAC: return prime_fact(x); default: pari_err_TYPE("factor",x); } av = avma; switch(tx) { case t_POL: return RgX_factor(x, dom); case t_RFRAC: { GEN a = gel(x,1), b = gel(x,2); GEN y = famat_inv_shallow(RgX_factor(b, dom)); if (typ(a)==t_POL) y = famat_mul_shallow(RgX_factor(a, dom), y); return gerepilecopy(av, sort_factor_pol(y, cmp_universal)); } case t_INT: if (tdom==0 || tdom==t_INT) return Z_factor(x); case t_FRAC: if (tdom==0 || tdom==t_INT) return Q_factor(x); case t_COMPLEX: /* fall through */ if (tdom==0 || tdom==t_COMPLEX) { GEN y = Qi_factor(x); if (y) return y; } /* fall through */ } pari_err_TYPE("factor",x); return NULL; /* LCOV_EXCL_LINE */ } GEN factor(GEN x) { return factor_domain(x, NULL); } /*******************************************************************/ /* */ /* ROOTS --> MONIC POLYNOMIAL */ /* */ /*******************************************************************/ static GEN normalized_mul(void *E, GEN x, GEN y) { long a = gel(x,1)[1], b = gel(y,1)[1]; (void) E; return mkvec2(mkvecsmall(a + b), RgX_mul_normalized(gel(x,2),a, gel(y,2),b)); } /* L = [Vecsmall([a]), A], with a > 0, A an RgX, deg(A) < a; return X^a + A */ static GEN normalized_to_RgX(GEN L) { long i, a = gel(L,1)[1]; GEN A = gel(L,2); GEN z = cgetg(a + 3, t_POL); z[1] = evalsigne(1) | evalvarn(varn(A)); for (i = 2; i < lg(A); i++) gel(z,i) = gcopy(gel(A,i)); for ( ; i < a+2; i++) gel(z,i) = gen_0; gel(z,i) = gen_1; return z; } static GEN roots_to_pol_FpV(GEN x, long v, GEN p) { pari_sp av = avma; GEN r; if (lgefint(p) == 3) { ulong pp = uel(p, 2); r = Flx_to_ZX_inplace(Flv_roots_to_pol(RgV_to_Flv(x, pp), pp, v< 0? ei: negi(ei), Tp, p); if (s > 0) H = H? Flxq_mul(H, x, Tp, p): x; else Hi = Hi? Flxq_mul(Hi, x, Tp, p): x; } if (!Hi) { if (!H) { set_avma(av); return mkvecsmall2(v,1); } return gerepileuptoleaf(av, H); } Hi = Flxq_inv(Hi, Tp, p); return gerepileuptoleaf(av, H? Flxq_mul(H,Hi,Tp,p): Hi); } GEN FqV_factorback(GEN L, GEN e, GEN Tp, GEN p) { pari_sp av = avma; GEN Hi = NULL, H = NULL; long i, l = lg(L), small = typ(e) == t_VECSMALL; for (i = 1; i < l; i++) { GEN x; long s; if (small) { s = e[i]; if (!s) continue; x = Fq_powu(gel(L,i), labs(s), Tp, p); } else { GEN ei = gel(e,i); s = signe(ei); if (!s) continue; x = Fq_pow(gel(L,i), s > 0? ei: negi(ei), Tp, p); } if (s > 0) H = H? Fq_mul(H, x, Tp, p): x; else Hi = Hi? Fq_mul(Hi, x, Tp, p): x; } if (Hi) { Hi = Fq_inv(Hi, Tp, p); H = H? Fq_mul(H,Hi,Tp,p): Hi; } else if (!H) return gc_const(av, gen_1); return gerepileupto(av, H); } GEN factorback2(GEN L, GEN e) { return gen_factorback(L, e, NULL, &mul, &powi, NULL); } GEN factorback(GEN fa) { return factorback2(fa, NULL); } GEN vecprod(GEN v) { pari_sp av = avma; if (!is_vec_t(typ(v))) pari_err_TYPE("vecprod", v); if (lg(v) == 1) return gen_1; return gerepilecopy(av, gen_product(v, NULL, mul)); } static int RgX_is_irred_i(GEN x) { GEN y, p, pol; long l = lg(x), pa; if (!signe(x) || l <= 3) return 0; switch(RgX_type(x,&p,&pol,&pa)) { case t_INTMOD: return FpX_is_irred(RgX_to_FpX(x,p), p); case t_COMPLEX: return l == 4; case t_REAL: if (l == 4) return 1; if (l > 5) return 0; return gsigne(RgX_disc(x)) > 0; } y = RgX_factor(x, NULL); return (lg(gcoeff(y,1,1))==l); } static int RgX_is_irred(GEN x) { pari_sp av = avma; return gc_bool(av, RgX_is_irred_i(x)); } long polisirreducible(GEN x) { long tx = typ(x); if (tx == t_POL) return RgX_is_irred(x); if (!is_scalar_t(tx)) pari_err_TYPE("polisirreducible",x); return 0; } /*******************************************************************/ /* */ /* GENERIC GCD */ /* */ /*******************************************************************/ /* x is a COMPLEX or a QUAD */ static GEN triv_cont_gcd(GEN x, GEN y) { pari_sp av = avma; GEN c; if (typ(x)==t_COMPLEX) { GEN a = gel(x,1), b = gel(x,2); if (typ(a) == t_REAL || typ(b) == t_REAL) return gen_1; c = ggcd(a,b); } else c = ggcd(gel(x,2),gel(x,3)); return gerepileupto(av, ggcd(c,y)); } /* y is a PADIC, x a rational number or an INTMOD */ static GEN padic_gcd(GEN x, GEN y) { GEN p = gel(y,2); long v = gvaluation(x,p), w = valp(y); if (w < v) v = w; return powis(p, v); } static void Zi_mul3(GEN xr, GEN xi, GEN yr, GEN yi, GEN *zr, GEN *zi) { GEN p3 = addii(xr,xi); GEN p4 = addii(yr,yi); GEN p1 = mulii(xr,yr); GEN p2 = mulii(xi,yi); p3 = mulii(p3,p4); p4 = addii(p2,p1); *zr = subii(p1,p2); *zi = subii(p3,p4); } static GEN Zi_rem(GEN x, GEN y) { GEN xr = real_i(x), xi = imag_i(x); GEN yr = real_i(y), yi = imag_i(y); GEN n = addii(sqri(yr), sqri(yi)); GEN ur, ui, zr, zi; Zi_mul3(xr, xi, yr, negi(yi), &ur, &ui); Zi_mul3(yr, yi, diviiround(ur, n), diviiround(ui, n), &zr, &zi); return mkcomplex(subii(xr,zr), subii(xi,zi)); } static GEN Qi_gcd(GEN x, GEN y) { pari_sp av = avma, btop; GEN dx, dy; x = Q_remove_denom(x, &dx); y = Q_remove_denom(y, &dy); btop = avma; while (!gequal0(y)) { GEN z = Zi_rem(x,y); x = y; y = z; if (gc_needed(btop,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"Qi_gcd"); gerepileall(btop,2, &x,&y); } } x = Qi_normal(x); if (typ(x) == t_COMPLEX) { if (gequal0(gel(x,2))) x = gel(x,1); else if (gequal0(gel(x,1))) x = gel(x,2); } if (!dx && !dy) return gerepilecopy(av, x); return gerepileupto(av, gdiv(x, dx? (dy? lcmii(dx, dy): dx): dy)); } static int c_is_rational(GEN x) { return is_rational_t(typ(gel(x,1))) && is_rational_t(typ(gel(x,2))); } static GEN c_zero_gcd(GEN c) { GEN x = gel(c,1), y = gel(c,2); long tx = typ(x), ty = typ(y); if (tx == t_REAL || ty == t_REAL) return gen_1; if (tx == t_PADIC || tx == t_INTMOD || ty == t_PADIC || ty == t_INTMOD) return ggcd(x, y); return Qi_gcd(c, gen_0); } /* gcd(x, 0) */ static GEN zero_gcd(GEN x) { pari_sp av; switch(typ(x)) { case t_INT: return absi(x); case t_FRAC: return absfrac(x); case t_COMPLEX: return c_zero_gcd(x); case t_REAL: return gen_1; case t_PADIC: return powis(gel(x,2), valp(x)); case t_SER: return pol_xnall(valser(x), varn(x)); case t_POLMOD: { GEN d = gel(x,2); if (typ(d) == t_POL && varn(d) == varn(gel(x,1))) return content(d); return isinexact(d)? zero_gcd(d): gcopy(d); } case t_POL: if (!isinexact(x)) break; av = avma; return gerepileupto(av, monomialcopy(content(x), RgX_val(x), varn(x))); case t_RFRAC: if (!isinexact(x)) break; av = avma; return gerepileupto(av, gdiv(zero_gcd(gel(x,1)), gel(x,2))); } return gcopy(x); } /* z is an exact zero, t_INT, t_INTMOD or t_FFELT */ static GEN zero_gcd2(GEN y, GEN z) { pari_sp av; switch(typ(z)) { case t_INT: return zero_gcd(y); case t_INTMOD: av = avma; return gerepileupto(av, gmul(y, mkintmod(gen_1,gel(z,1)))); case t_FFELT: av = avma; return gerepileupto(av, gmul(y, FF_1(z))); default: pari_err_TYPE("zero_gcd", z); return NULL;/*LCOV_EXCL_LINE*/ } } static GEN cont_gcd_pol_i(GEN x, GEN y) { return scalarpol(ggcd(content(x),y), varn(x));} /* tx = t_POL, y considered as constant */ static GEN cont_gcd_pol(GEN x, GEN y) { pari_sp av = avma; return gerepileupto(av, cont_gcd_pol_i(x,y)); } /* tx = t_RFRAC, y considered as constant */ static GEN cont_gcd_rfrac(GEN x, GEN y) { pari_sp av = avma; GEN cx; x = primitive_part(x, &cx); /* e.g. Mod(1,2) / (2*y+1) => primitive_part = Mod(1,2)*y^0 */ if (typ(x) != t_RFRAC) x = cont_gcd_pol_i(x, y); else x = gred_rfrac_simple(ggcd(cx? cx: gen_1, y), gel(x,2)); return gerepileupto(av, x); } /* !is_const_t(tx), tx != t_POL,t_RFRAC, y considered as constant */ static GEN cont_gcd_gen(GEN x, GEN y) { pari_sp av = avma; return gerepileupto(av, ggcd(content(x),y)); } /* !is_const(tx), y considered as constant */ static GEN cont_gcd(GEN x, long tx, GEN y) { switch(tx) { case t_RFRAC: return cont_gcd_rfrac(x,y); case t_POL: return cont_gcd_pol(x,y); default: return cont_gcd_gen(x,y); } } static GEN gcdiq(GEN x, GEN y) { GEN z; if (!signe(x)) return Q_abs(y); z = cgetg(3,t_FRAC); gel(z,1) = gcdii(x,gel(y,1)); gel(z,2) = icopy(gel(y,2)); return z; } static GEN gcdqq(GEN x, GEN y) { GEN z = cgetg(3,t_FRAC); gel(z,1) = gcdii(gel(x,1), gel(y,1)); gel(z,2) = lcmii(gel(x,2), gel(y,2)); return z; } /* assume x,y t_INT or t_FRAC */ GEN Q_gcd(GEN x, GEN y) { long tx = typ(x), ty = typ(y); if (tx == t_INT) { return (ty == t_INT)? gcdii(x,y): gcdiq(x,y); } else { return (ty == t_INT)? gcdiq(y,x): gcdqq(x,y); } } GEN ggcd(GEN x, GEN y) { long vx, vy, tx = typ(x), ty = typ(y); pari_sp av, tetpil; GEN p1,z; if (is_noncalc_t(tx) || is_matvec_t(tx) || is_noncalc_t(ty) || is_matvec_t(ty)) pari_err_TYPE2("gcd",x,y); if (tx>ty) { swap(x,y); lswap(tx,ty); } /* tx <= ty */ z = gisexactzero(x); if (z) return zero_gcd2(y,z); z = gisexactzero(y); if (z) return zero_gcd2(x,z); 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 (!equali1(p1)) { p1 = gcdii(p1,gel(y,2)); if (equalii(p1, gel(z,1))) { cgiv(p1); p1 = gen_0; } else p1 = gerepileuptoint(av, p1); } gel(z,2) = p1; } return z; case t_FRAC: return gcdqq(x,y); case t_FFELT: if (!FF_samefield(x,y)) pari_err_OP("gcd",x,y); return FF_equal0(x) && FF_equal0(y)? FF_zero(y): FF_1(y); case t_COMPLEX: if (c_is_rational(x) && c_is_rational(y)) return Qi_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) { set_avma(av); return gcopy(y); } tetpil=avma; return gerepile(av,tetpil, gdiv(y,gel(p1,2))); } if (typ(gel(p1,2))==t_INT && typ(gel(p1,3))==t_INT) {set_avma(av); return gcopy(y);} p1 = ginv(p1); set_avma(av); if (typ(gel(p1,2))==t_INT && typ(gel(p1,3))==t_INT) return gcopy(x); return triv_cont_gcd(y,x); default: return gen_1; /* t_REAL */ } if (is_const_t(ty)) switch(tx) { case t_INT: switch(ty) { case t_INTMOD: z = cgetg(3,t_INTMOD); gel(z,1) = icopy(gel(y,1)); av = avma; p1 = gcdii(gel(y,1),gel(y,2)); if (!equali1(p1)) { p1 = gcdii(x,p1); if (equalii(p1, gel(z,1))) { cgiv(p1); p1 = gen_0; } else p1 = gerepileuptoint(av, p1); } gel(z,2) = p1; return z; case t_REAL: return gen_1; case t_FRAC: return gcdiq(x,y); case t_COMPLEX: if (c_is_rational(y)) return Qi_gcd(x,y); return triv_cont_gcd(y,x); case t_FFELT: if (!FF_equal0(y)) return FF_1(y); return dvdii(x, gel(y,4))? FF_zero(y): FF_1(y); case t_PADIC: return padic_gcd(x,y); case t_QUAD: return triv_cont_gcd(y,x); default: pari_err_TYPE2("gcd",x,y); } case t_REAL: switch(ty) { case t_INTMOD: case t_FFELT: case t_PADIC: pari_err_TYPE2("gcd",x,y); default: return gen_1; } case t_INTMOD: switch(ty) { case t_FRAC: av = avma; p1=gcdii(gel(x,1),gel(y,2)); set_avma(av); if (!equali1(p1)) pari_err_OP("gcd",x,y); return ggcd(gel(y,1), x); case t_FFELT: { GEN p = gel(y,4); if (!dvdii(gel(x,1), p)) pari_err_OP("gcd",x,y); if (!FF_equal0(y)) return FF_1(y); return dvdii(gel(x,2),p)? FF_zero(y): FF_1(y); } case t_COMPLEX: case t_QUAD: return triv_cont_gcd(y,x); case t_PADIC: return padic_gcd(x,y); default: pari_err_TYPE2("gcd",x,y); } case t_FRAC: switch(ty) { case t_COMPLEX: if (c_is_rational(y)) return Qi_gcd(x,y); case t_QUAD: return triv_cont_gcd(y,x); case t_FFELT: { GEN p = gel(y,4); if (dvdii(gel(x,2), p)) pari_err_OP("gcd",x,y); if (!FF_equal0(y)) return FF_1(y); return dvdii(gel(x,1),p)? FF_zero(y): FF_1(y); } case t_PADIC: return padic_gcd(x,y); default: pari_err_TYPE2("gcd",x,y); } case t_FFELT: switch(ty) { case t_PADIC: { GEN p = gel(y,2); long v = valp(y); if (!equalii(p, gel(x,4)) || v < 0) pari_err_OP("gcd",x,y); return (v && FF_equal0(x))? FF_zero(x): FF_1(x); } default: pari_err_TYPE2("gcd",x,y); } case t_COMPLEX: switch(ty) { case t_PADIC: case t_QUAD: return triv_cont_gcd(x,y); default: pari_err_TYPE2("gcd",x,y); } case t_PADIC: switch(ty) { case t_QUAD: return triv_cont_gcd(y,x); default: pari_err_TYPE2("gcd",x,y); } default: return gen_1; /* tx = t_REAL */ } return cont_gcd(y,ty, x); } if (tx == t_POLMOD) { if (ty == t_POLMOD) { GEN T = gel(x,1), Ty = gel(y,1); z = cgetg(3,t_POLMOD); if (varn(T)==varn(Ty)) T = RgX_equal(T,Ty)? RgX_copy(T): RgX_gcd(T, Ty); else if(varn(T) 0) return cont_gcd(x,tx, y); /* vx = vy: same main variable */ switch(tx) { case t_POL: switch(ty) { case t_POL: return RgX_gcd(x,y); case t_SER: z = ggcd(content(x), content(y)); return monomialcopy(z, minss(valser(y),gval(x,vx)), vx); case t_RFRAC: av = avma; z = gred_rfrac_simple(ggcd(gel(y,1), x), gel(y,2)); return gerepileupto(av, z); } break; case t_SER: z = ggcd(content(x), content(y)); switch(ty) { case t_SER: return monomialcopy(z, minss(valser(x),valser(y)), vx); case t_RFRAC: return monomialcopy(z, minss(valser(x),gval(y,vx)), vx); } break; case t_RFRAC: { GEN xd = gel(x,2), yd = gel(y,2); if (ty != t_RFRAC) pari_err_TYPE2("gcd",x,y); z = cgetg(3,t_RFRAC); av = avma; gel(z,2) = gerepileupto(av, RgX_mul(xd, RgX_div(yd, RgX_gcd(xd, yd)))); gel(z,1) = ggcd(gel(x,1), gel(y,1)); return z; } } pari_err_TYPE2("gcd",x,y); return NULL; /* LCOV_EXCL_LINE */ } GEN ggcd0(GEN x, GEN y) { return y? ggcd(x,y): content(x); } static GEN fix_lcm(GEN x) { GEN t; switch(typ(x)) { case t_INT: x = absi_shallow(x); break; case t_POL: if (lg(x) <= 2) break; t = leading_coeff(x); if (typ(t) == t_INT && signe(t) < 0) x = gneg(x); } return x; } GEN glcm0(GEN x, GEN y) { if (!y) return fix_lcm(gassoc_proto(glcm,x,y)); return glcm(x,y); } GEN ZV_lcm(GEN x) { return fix_lcm(gassoc_proto(lcmii,x,NULL)); } GEN glcm(GEN x, GEN y) { pari_sp av; GEN z; if (typ(x)==t_INT && typ(y)==t_INT) return lcmii(x,y); av = avma; z = ggcd(x,y); if (!gequal1(z)) { if (gequal0(z)) { set_avma(av); return gmul(x,y); } y = gdiv(y,z); } return gerepileupto(av, fix_lcm(gmul(x,y))); } /* x + r ~ x ? Assume x,r are t_POL, deg(r) <= deg(x) */ static int pol_approx0(GEN r, GEN x, int exact) { long i, l; if (exact) return !signe(r); l = minss(lg(x), lg(r)); for (i = 2; i < l; i++) if (!cx_approx0(gel(r,i), gel(x,i))) return 0; return 1; } GEN RgX_gcd_simple(GEN x, GEN y) { pari_sp av1, av = avma; GEN r, yorig = y; int exact = !(isinexactreal(x) || isinexactreal(y)); for(;;) { av1 = avma; r = RgX_rem(x,y); if (pol_approx0(r, x, exact)) { set_avma(av1); if (y == yorig) return RgX_copy(y); y = normalizepol_approx(y, lg(y)); if (lg(y) == 3) { set_avma(av); return pol_1(varn(x)); } return gerepileupto(av,y); } x = y; y = r; if (gc_needed(av,1)) { if(DEBUGMEM>1) 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; } GEN ghalfgcd(GEN x, GEN y) { long tx = typ(x), ty = typ(y); if (tx==t_INT && ty==t_INT) return halfgcdii(x, y); if (tx==t_POL && ty==t_POL && varn(x)==varn(y)) { pari_sp av = avma; GEN a, b, M = RgX_halfgcd_all(x, y, &a, &b); return gerepilecopy(av, mkvec2(M, mkcol2(a,b))); } pari_err_OP("halfgcd", x, y); return NULL; /* LCOV_EXCL_LINE */ } /*******************************************************************/ /* */ /* 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); 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): 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_0; break; case t_MAT: { long hx, j; lx = lg(x); if (lx == 1) return gen_0; hx = lgcols(x); if (hx == 1) return gen_0; if (lx == 2) { x = gel(x,1); lx = lg(x); break; } if (hx == 2) { x = row_i(x, 1, 1, lx-1); break; } c = content(gel(x,1)); for (j=2; j lx) { /* integer coeffs */ while (lx-- > lontyp[tx]) { c = gcdii(c, gel(x,lx)); if (equali1(c)) return gc_const(av, gen_1); } } else { if (isinexact(c)) c = zero_gcd(c); while (lx-- > lontyp[tx]) { GEN d = gel(x,lx); t = typ(d); if (is_matvec_t(t)) d = content(d); c = ggcd(c, d); } if (isinexact(c)) return gc_const(av, gen_1); } switch(typ(c)) { case t_INT: c = absi_shallow(c); break; case t_VEC: case t_COL: case t_MAT: pari_err_TYPE("content",x); } return av==avma? gcopy(c): gerepileupto(av,c); } GEN primitive_part(GEN x, GEN *ptc) { pari_sp av = avma; GEN c = content(x); if (gequal1(c)) { set_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); } static GEN Q_content_v(GEN x, long imin, long l) { pari_sp av = avma; long i = l-1; GEN d = Q_content_safe(gel(x,i)); if (!d) return NULL; for (i--; i >= imin; i--) { GEN c = Q_content_safe(gel(x,i)); if (!c) return NULL; d = Q_gcd(d, c); if (gc_needed(av,1)) d = gerepileupto(av, d); } return gerepileupto(av, d); } /* As content(), but over Q. Treats polynomial as elts of Q[x1,...xn], instead * of Q(x2,...,xn)[x1] */ GEN Q_content_safe(GEN x) { long l; switch(typ(x)) { case t_INT: return absi(x); case t_FRAC: return absfrac(x); case t_COMPLEX: case t_VEC: case t_COL: case t_MAT: l = lg(x); return l==1? gen_1: Q_content_v(x, 1, l); case t_POL: l = lg(x); return l==2? gen_0: Q_content_v(x, 2, l); case t_POLMOD: return Q_content_safe(gel(x,2)); case t_RFRAC: { GEN a, b; a = Q_content_safe(gel(x,1)); if (!a) return NULL; b = Q_content_safe(gel(x,2)); if (!b) return NULL; return gdiv(a, b); } } return NULL; } GEN Q_content(GEN x) { GEN c = Q_content_safe(x); if (!c) pari_err_TYPE("Q_content",x); return c; } GEN ZX_content(GEN x) { long i, l = lg(x); GEN d; pari_sp av; if (l == 2) return gen_0; d = gel(x,2); if (l == 3) return absi(d); av = avma; for (i=3; !is_pm1(d) && i 2; i--, e += BITS_IN_LONG) if (c[i]) break; e += vals(c[i]); break; /* e[2] != 0 */ case t_INT: if (!signe(c)) return; e = expi(c); break; case t_FRAC: e = expi(gel(c,1)) - expi(gel(c,2)); if (*exact) *D = lcmii(*D, gel(c,2)); break; default: pari_err_TYPE("rescale_to_int",c); return; /* LCOV_EXCL_LINE */ } if (e < *emin) *emin = e; } GEN RgM_rescale_to_int(GEN x) { long lx = lg(x), i,j, hx, emin; GEN D; int exact; if (lx == 1) return cgetg(1,t_MAT); hx = lgcols(x); exact = 1; emin = HIGHEXPOBIT; D = gen_1; for (j = 1; j < lx; j++) for (i = 1; i < hx; i++) rescale_init(gcoeff(x,i,j), &exact, &emin, &D); if (exact) return D == gen_1 ? x: Q_muli_to_int(x, D); return grndtoi(gmul2n(x, -emin), NULL); } GEN RgX_rescale_to_int(GEN x) { long lx = lg(x), i, emin; GEN D; int exact; if (lx == 2) return gcopy(x); /* rare */ exact = 1; emin = HIGHEXPOBIT; D = gen_1; for (i = 2; i < lx; i++) rescale_init(gel(x,i), &exact, &emin, &D); if (exact) return D == gen_1 ? x: Q_muli_to_int(x, D); return grndtoi(gmul2n(x, -emin), NULL); } /* return x * n/d. x: rational; d,n,result: integral; d,n coprime */ static GEN Q_divmuli_to_int(GEN x, GEN d, GEN n) { long i, l; GEN y, xn, xd; pari_sp av; switch(typ(x)) { case t_INT: av = avma; y = diviiexact(x,d); return gerepileuptoint(av, mulii(y,n)); case t_FRAC: xn = gel(x,1); xd = gel(x,2); av = avma; y = mulii(diviiexact(xn, d), diviiexact(n, xd)); return gerepileuptoint(av, y); case t_VEC: case t_COL: case t_MAT: y = cgetg_copy(x, &l); for (i=1; i 3); } /* compute U, V s.t Ux + Vy = resultant(x,y) */ static GEN subresext_i(GEN x, GEN y, GEN *U, GEN *V) { pari_sp av, av2; long dx, dy, du, signh, tx = typ(x), ty = typ(y); GEN r, z, g, h, p1, cu, cv, u, v, um1, uze, vze; if (!is_extscalar_t(tx)) pari_err_TYPE("subresext",x); if (!is_extscalar_t(ty)) pari_err_TYPE("subresext",y); if (gequal0(x) || gequal0(y)) { *U = *V = gen_0; return gen_0; } if (tx != t_POL) { if (ty != t_POL) { *U = ginv(x); *V = gen_0; return gen_1; } return scalar_res(y,x,V,U); } if (ty != t_POL) return scalar_res(x,y,U,V); if (varn(x) != varn(y)) return varncmp(varn(x), varn(y)) < 0? scalar_res(x,y,U,V) : scalar_res(y,x,V,U); if (gequal0(leading_coeff(x))) x = RgX_renormalize(x); if (gequal0(leading_coeff(y))) y = RgX_renormalize(y); 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; um1 = gen_1; uze = gen_0; for(;;) { if (!subres_step(&u, &v, &g, &h, &uze, &um1, &signh)) break; if (gc_needed(av2,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"subresext, dr = %ld", degpol(v)); gerepileall(av2,6, &u,&v,&g,&h,&uze,&um1); } } /* uze an RgX */ if (!u) { *U = *V = gen_0; return gc_const(av, gen_0); } z = gel(v,2); du = degpol(u); if (du > 1) { /* z = gdivexact(gpowgs(z,du), gpowgs(h,du-1)); */ p1 = gpowgs(gdiv(z,h),du-1); z = gmul(z,p1); uze = RgX_Rg_mul(uze, p1); } if (signh < 0) { z = gneg_i(z); uze = RgX_neg(uze); } vze = RgX_divrem(Rg_RgX_sub(z, RgX_mul(uze,x)), y, &r); if (signe(r)) pari_warn(warner,"inexact computation in subresext"); /* uze ppart(x) + vze ppart(y) = z = resultant(ppart(x), ppart(y)), */ p1 = gen_1; if (cu) p1 = gmul(p1, gpowgs(cu,dy)); if (cv) p1 = gmul(p1, gpowgs(cv,dx)); cu = cu? gdiv(p1,cu): p1; cv = cv? gdiv(p1,cv): p1; z = gmul(z,p1); *U = RgX_Rg_mul(uze,cu); *V = RgX_Rg_mul(vze,cv); return z; } GEN subresext(GEN x, GEN y, GEN *U, GEN *V) { pari_sp av = avma; GEN z = subresext_i(x, y, U, V); return gc_all(av, 3, &z, U, V); } 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_coeff(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; } static GEN gc_gcdext(pari_sp av, GEN r, GEN *u, GEN *v) { if (!u && !v) return gerepileupto(av, r); if (u && v) return gc_all(av, 3, &r, u, v); return gc_all(av, 2, &r, u ? u: v); } static GEN RgX_extgcd_FpX(GEN x, GEN y, GEN p, GEN *u, GEN *v) { pari_sp av = avma; GEN r = FpX_extgcd(RgX_to_FpX(x, p), RgX_to_FpX(y, p), p, u, v); if (u) *u = FpX_to_mod(*u, p); if (v) *v = FpX_to_mod(*v, p); return gc_gcdext(av, FpX_to_mod(r, p), u, v); } static GEN RgX_extgcd_FpXQX(GEN x, GEN y, GEN pol, GEN p, GEN *U, GEN *V) { pari_sp av = avma; GEN r, T = RgX_to_FpX(pol, p); r = FpXQX_extgcd(RgX_to_FpXQX(x, T, p), RgX_to_FpXQX(y, T, p), T, p, U, V); return gc_gcdext(av, FpXQX_to_mod(r, T, p), U, V); } static GEN RgX_extgcd_fast(GEN x, GEN y, GEN *U, GEN *V) { GEN p, pol; long pa; long t = RgX_type(x, &p,&pol,&pa); switch(t) { case t_FFELT: return FFX_extgcd(x, y, pol, U, V); case t_INTMOD: return RgX_extgcd_FpX(x, y, p, U, V); case code(t_POLMOD, t_INTMOD): return RgX_extgcd_FpXQX(x, y, pol, p, U, V); default: return NULL; } } /* 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; long signh; /* junk */ long dx, dy, vx, tx = typ(x), ty = typ(y); GEN r, z, g, h, p1, cu, cv, u, v, um1, uze, vze, *gptr[3]; if (tx!=t_POL) pari_err_TYPE("RgX_extgcd",x); if (ty!=t_POL) pari_err_TYPE("RgX_extgcd",y); if ( varncmp(varn(x),varn(y))) pari_err_VAR("RgX_extgcd",x,y); vx=varn(x); if (!signe(x)) { if (signe(y)) return zero_extgcd(y,U,V,vx); *U = pol_0(vx); *V = pol_0(vx); return pol_0(vx); } if (!signe(y)) return zero_extgcd(x,V,U,vx); r = RgX_extgcd_fast(x, y, U, V); if (r) return r; 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; um1 = gen_1; uze = gen_0; for(;;) { if (!subres_step(&u, &v, &g, &h, &uze, &um1, &signh)) break; if (gc_needed(av2,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"RgX_extgcd, dr = %ld",degpol(v)); gerepileall(av2,6,&u,&v,&g,&h,&uze,&um1); } } 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; } static GEN RgX_halfgcd_all_i(GEN a, GEN b, GEN *pa, GEN *pb) { pari_sp av=avma; long m = degpol(a), va = varn(a); GEN R, u,u1,v,v1; u1 = v = pol_0(va); u = v1 = pol_1(va); if (degpol(a)= m) { GEN r, q = RgX_pseudodivrem(a,b,&r); GEN l = gpowgs(leading_coeff(b), degpol(a)-degpol(b)+1); GEN g = ggcd(l, content(r)); q = RgX_Rg_div(q, g); r = RgX_Rg_div(r, g); l = gdiv(l, g); a = b; b = r; swap(u,v); swap(u1,v1); v = RgX_sub(gmul(l,v), RgX_mul(u, q)); v1 = RgX_sub(gmul(l,v1), RgX_mul(u1, q)); if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"halfgcd (d = %ld)",degpol(b)); gerepileall(av,6, &a,&b,&u1,&v1,&u,&v); } } if (pa) *pa = a; if (pb) *pb = b; R = mkmat22(u,u1,v,v1); return !pa && pb ? gc_all(av, 2, &R, pb): gc_all(av, 1+!!pa+!!pb, &R, pa, pb); } static GEN RgX_halfgcd_all_FpX(GEN x, GEN y, GEN p, GEN *a, GEN *b) { pari_sp av = avma; GEN M; if (lgefint(p) == 3) { ulong pp = uel(p, 2); GEN xp = RgX_to_Flx(x, pp), yp = RgX_to_Flx(y, pp); M = Flx_halfgcd_all(xp, yp, pp, a, b); M = FlxM_to_ZXM(M); *a = Flx_to_ZX(*a); *b = Flx_to_ZX(*b); } else { x = RgX_to_FpX(x, p); y = RgX_to_FpX(y, p); M = FpX_halfgcd_all(x, y, p, a, b); } return !a && b ? gc_all(av, 2, &M, b): gc_all(av, 1+!!a+!!b, &M, a, b); } static GEN RgX_halfgcd_all_FpXQX(GEN x, GEN y, GEN pol, GEN p, GEN *a, GEN *b) { pari_sp av = avma; GEN M, T = RgX_to_FpX(pol, p); if (signe(T)==0) pari_err_OP("halfgcd", x, y); x = RgX_to_FpXQX(x, T, p); y = RgX_to_FpXQX(y, T, p); M = FpXQX_halfgcd_all(x, y, T, p, a, b); if (a) *a = FqX_to_mod(*a, T, p); if (b) *b = FqX_to_mod(*b, T, p); M = FqXM_to_mod(M, T, p); return !a && b ? gc_all(av, 2, &M, b): gc_all(av, 1+!!a+!!b, &M, a, b); } static GEN RgX_halfgcd_all_fast(GEN x, GEN y, GEN *a, GEN *b) { GEN p, pol; long pa; long t = RgX_type2(x,y, &p,&pol,&pa); switch(t) { case t_FFELT: return FFX_halfgcd_all(x, y, pol, a, b); case t_INTMOD: return RgX_halfgcd_all_FpX(x, y, p, a, b); case code(t_POLMOD, t_INTMOD): return RgX_halfgcd_all_FpXQX(x, y, pol, p, a, b); default: return NULL; } } GEN RgX_halfgcd_all(GEN x, GEN y, GEN *a, GEN *b) { GEN z = RgX_halfgcd_all_fast(x, y, a, b); if (z) return z; return RgX_halfgcd_all_i(x, y, a, b); } GEN RgX_halfgcd(GEN x, GEN y) { return RgX_halfgcd_all(x, y, NULL, NULL); } int RgXQ_ratlift(GEN x, GEN T, long amax, long bmax, GEN *P, GEN *Q) { pari_sp av = avma, av2, tetpil; long signh; /* junk */ long vx; GEN g, h, p1, cu, cv, u, v, um1, uze, *gptr[2]; if (typ(x)!=t_POL) pari_err_TYPE("RgXQ_ratlift",x); if (typ(T)!=t_POL) pari_err_TYPE("RgXQ_ratlift",T); if ( varncmp(varn(x),varn(T)) ) pari_err_VAR("RgXQ_ratlift",x,T); if (bmax < 0) pari_err_DOMAIN("ratlift", "bmax", "<", gen_0, stoi(bmax)); if (!signe(T)) { if (degpol(x) <= amax) { *P = RgX_copy(x); *Q = pol_1(varn(x)); return 1; } return 0; } if (amax+bmax >= degpol(T)) pari_err_DOMAIN("ratlift", "amax+bmax", ">=", stoi(degpol(T)), mkvec3(stoi(amax), stoi(bmax), T)); vx = varn(T); u = x = primitive_part(x, &cu); v = T = primitive_part(T, &cv); g = h = gen_1; av2 = avma; 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)) return gc_bool(av,0); if (typ(v)!=t_POL || degpol(v)<=amax) break; if (gc_needed(av2,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"RgXQ_ratlift, dr = %ld", degpol(v)); gerepileall(av2,6,&u,&v,&g,&h,&uze,&um1); } } if (uze == gen_0) { set_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; } GEN RgX_chinese_coprime(GEN x, GEN y, GEN Tx, GEN Ty, GEN Tz) { pari_sp av = avma; GEN ax = RgX_mul(RgXQ_inv(Tx,Ty), Tx); GEN p1 = RgX_mul(ax, RgX_sub(y,x)); p1 = RgX_add(x,p1); if (!Tz) Tz = RgX_mul(Tx,Ty); p1 = RgX_rem(p1, Tz); return gerepileupto(av,p1); } /*******************************************************************/ /* */ /* RESULTANT USING DUCOS VARIANT */ /* */ /*******************************************************************/ /* x^n / y^(n-1), assume n > 0 */ static GEN Lazard(GEN x, GEN y, long n) { long a; GEN c; if (n == 1) return x; a = 1 << expu(n); /* a = 2^k <= n < 2^(k+1) */ c=x; n-=a; while (a>1) { a>>=1; c=gdivexact(gsqr(c),y); if (n>=a) { c=gdivexact(gmul(c,x),y); n -= a; } } return c; } /* F (x/y)^(n-1), assume n >= 1 */ static GEN Lazard2(GEN F, GEN x, GEN y, long n) { if (n == 1) return F; return RgX_Rg_divexact(RgX_Rg_mul(F, Lazard(x,y,n-1)), y); } static GEN RgX_neg_i(GEN x, long lx) { long i; GEN y = cgetg(lx, t_POL); y[1] = x[1]; for (i=2; i 1 && gequal0(gel(x,i))) i--; return i+1; } #define addshift(x,y) RgX_addmulXn_shallow((x),(y),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_coeff(Z); long p, q, j, lP, lQ; pari_sp av; p = degpol(P); p0 = gel(P,p+2); lP = reductum_lg(P,lg(P)); q = degpol(Q); q0 = gel(Q,q+2); lQ = reductum_lg(Q,lg(Q)); /* p > q. Very often p - 1 = q */ av = avma; /* 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 (gc_needed(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); } #undef addshift static GEN RgX_pseudodenom(GEN x) { GEN m = NULL; long l = lg(x), i; for (i = 2; i < l; i++) { GEN xi = gel(x, i); if (typ(xi) == t_RFRAC) { GEN d = denom_i(xi); if (!m || signe(RgX_pseudorem(m, d))) m = m ? gmul(m, d): d; } } return m; } /* Ducos's subresultant */ GEN RgX_resultant_all(GEN P, GEN Q, GEN *sol) { pari_sp av, av2; long dP, dQ, delta, sig = 1; GEN DP, DQ, 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 Rg_get_0(P); s = gpowgs(gel(Q,2), dP); if (sig == -1) s = gerepileupto(av, gneg(s)); return s; } if (dQ == 1) { if (sol) *sol = Q; s = RgX_homogenous_evalpow(P, gel(Q,2), gpowers(gneg(gel(Q,3)), dP)); if (sig==-1) s = gneg(s); return gc_all(av, sol ? 2: 1, &s, sol); } /* primitive_part is also possible here, but possibly very costly, * and hardly ever worth it */ DP = RgX_pseudodenom(P); if (DP) P = gmul(P,DP); DQ = RgX_pseudodenom(Q); if (DQ) Q = gmul(Q,DQ); P = Q_primitive_part(P, &cP); Q = Q_primitive_part(Q, &cQ); av2 = avma; s = gpowgs(leading_coeff(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_coeff(Q), s, delta); if (both_odd(degpol(P), degpol(Q))) sig = -sig; Q = nextSousResultant(P, Q, Z, s); P = Z; if (gc_needed(av,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"resultant_all, degpol Q = %ld",degpol(Q)); gerepileall(av2,2,&P,&Q); } s = leading_coeff(P); } if (!signe(Q)) { set_avma(av); return Rg_get_0(Q); } s = Lazard(leading_coeff(Q), s, degpol(P)); if (sig == -1) s = gneg(s); if (DP) s = gdiv(s, gpowgs(DP,dQ)); if (DQ) s = gdiv(s, gpowgs(DQ,dP)); if (cP) s = gmul(s, gpowgs(cP,dQ)); if (cQ) s = gmul(s, gpowgs(cQ,dP)); if (!sol) return gerepilecopy(av, s); *sol = P; return gc_all(av, 2, &s, sol); } static GEN RgX_resultant_FpX(GEN x, GEN y, GEN p) { pari_sp av = avma; GEN r; if (lgefint(p) == 3) { ulong pp = uel(p, 2); r = utoi(Flx_resultant(RgX_to_Flx(x, pp), RgX_to_Flx(y, pp), pp)); } else r = FpX_resultant(RgX_to_FpX(x, p), RgX_to_FpX(y, p), p); return gerepileupto(av, Fp_to_mod(r, p)); } static GEN RgX_resultant_FpXQX(GEN x, GEN y, GEN pol, GEN p) { pari_sp av = avma; GEN r, T = RgX_to_FpX(pol, p); r = FpXQX_resultant(RgX_to_FpXQX(x, T, p), RgX_to_FpXQX(y, T, p), T, p); return gerepileupto(av, FpX_to_mod(r, p)); } static GEN resultant_fast(GEN x, GEN y) { GEN p, pol; long pa, t; p = init_resultant(x,y); if (p) return p; t = RgX_type2(x,y, &p,&pol,&pa); switch(t) { case t_INT: return ZX_resultant(x,y); case t_FRAC: return QX_resultant(x,y); case t_FFELT: return FFX_resultant(x,y,pol); case t_INTMOD: return RgX_resultant_FpX(x, y, p); case code(t_POLMOD, t_INTMOD): return RgX_resultant_FpXQX(x, y, pol, p); default: return NULL; } } static GEN RgX_resultant_sylvester(GEN x, GEN y) { pari_sp av = avma; return gerepileupto(av, det(RgX_sylvestermatrix(x,y))); } /* Return resultant(P,Q). * 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(GEN P, GEN Q) { GEN z = resultant_fast(P,Q); if (z) return z; if (isinexact(P) || isinexact(Q)) return RgX_resultant_sylvester(P,Q); return RgX_resultant_all(P, Q, NULL); } /*******************************************************************/ /* */ /* RESULTANT USING SYLVESTER MATRIX */ /* */ /*******************************************************************/ static GEN syl_RgC(GEN x, long j, long d, long D, long cp) { GEN c = cgetg(d+1,t_COL); long i; for (i=1; i< j; i++) gel(c,i) = gen_0; for ( ; i<=D; i++) { GEN t = gel(x,D-i+2); gel(c,i) = cp? gcopy(t): t; } for ( ; i<=d; i++) gel(c,i) = gen_0; return c; } static GEN syl_RgM(GEN x, GEN y, long cp) { long j, d, dx = degpol(x), dy = degpol(y); GEN M; if (dx < 0) return dy < 0? cgetg(1,t_MAT): zeromat(dy,dy); if (dy < 0) return zeromat(dx,dx); d = dx+dy; M = cgetg(d+1,t_MAT); for (j=1; j<=dy; j++) gel(M,j) = syl_RgC(x,j,d,j+dx, cp); for (j=1; j<=dx; j++) gel(M,j+dy) = syl_RgC(y,j,d,j+dy, cp); return M; } GEN RgX_sylvestermatrix(GEN x, GEN y) { return syl_RgM(x,y,0); } GEN sylvestermatrix(GEN x, GEN y) { if (typ(x)!=t_POL) pari_err_TYPE("sylvestermatrix",x); if (typ(y)!=t_POL) pari_err_TYPE("sylvestermatrix",y); if (varn(x) != varn(y)) pari_err_VAR("sylvestermatrix",x,y); return syl_RgM(x,y,1); } GEN resultant2(GEN x, GEN y) { GEN r = init_resultant(x,y); return r? r: RgX_resultant_sylvester(x,y); } /* let vx = main variable of x, v0 a variable of highest priority; * return a t_POL in variable v0: * if vx <= v, return subst(x, v, pol_x(v0)) * if vx > v, return scalarpol(x, v0) */ static GEN fix_pol(GEN x, long v, long v0) { long vx, tx = typ(x); if (tx != t_POL) vx = gvar(x); else { /* shortcut: almost nothing to do */ vx = varn(x); if (v == vx) { if (v0 != v) { x = leafcopy(x); setvarn(x, v0); } return x; } } if (varncmp(v, vx) > 0) { x = gsubst(x, v, pol_x(v0)); if (typ(x) != t_POL) vx = gvar(x); else { vx = varn(x); if (vx == v0) return x; } } if (varncmp(vx, v0) <= 0) pari_err_TYPE("polresultant", x); return scalarpol_shallow(x, v0); } /* 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) { pari_sp av = avma; if (v >= 0) { long v0 = fetch_var_higher(); x = fix_pol(x,v, v0); y = fix_pol(y,v, v0); } switch(flag) { case 2: case 0: x=resultant(x,y); break; case 1: x=resultant2(x,y); break; default: pari_err_FLAG("polresultant"); } if (v >= 0) (void)delete_var(); return gerepileupto(av,x); } static GEN RgX_extresultant_FpX(GEN x, GEN y, GEN p, GEN *u, GEN *v) { pari_sp av = avma; GEN r = FpX_extresultant(RgX_to_FpX(x, p), RgX_to_FpX(y, p), p, u, v); if (signe(r) == 0) { *u = gen_0; *v = gen_0; return gc_const(av, gen_0); } if (u) *u = FpX_to_mod(*u, p); if (v) *v = FpX_to_mod(*v, p); return gc_gcdext(av, Fp_to_mod(r, p), u, v); } static GEN RgX_extresultant_fast(GEN x, GEN y, GEN *U, GEN *V) { GEN p, pol; long pa; long t = RgX_type2(x, y, &p,&pol,&pa); switch(t) { case t_INTMOD: return RgX_extresultant_FpX(x, y, p, U, V); default: return NULL; } } GEN polresultantext0(GEN x, GEN y, long v) { GEN R = NULL, U, V; pari_sp av = avma; if (v >= 0) { long v0 = fetch_var_higher(); x = fix_pol(x,v, v0); y = fix_pol(y,v, v0); } if (typ(x)==t_POL && typ(y)==t_POL) R = RgX_extresultant_fast(x, y, &U, &V); if (!R) R = subresext_i(x,y, &U,&V); if (v >= 0) { (void)delete_var(); if (typ(U) == t_POL && varn(U) != v) U = poleval(U, pol_x(v)); if (typ(V) == t_POL && varn(V) != v) V = poleval(V, pol_x(v)); } return gerepilecopy(av, mkvec3(U,V,R)); } GEN polresultantext(GEN x, GEN y) { return polresultantext0(x,y,-1); } /*******************************************************************/ /* */ /* CHARACTERISTIC POLYNOMIAL USING RESULTANT */ /* */ /*******************************************************************/ static GEN RgXQ_charpoly_FpXQ(GEN x, GEN T, GEN p, long v) { pari_sp av = avma; GEN r; if (lgefint(p)==3) { ulong pp = p[2]; r = Flx_to_ZX(Flxq_charpoly(RgX_to_Flx(x, pp), RgX_to_Flx(T, pp), pp)); } else r = FpXQ_charpoly(RgX_to_FpX(x, p), RgX_to_FpX(T, p), p); r = FpX_to_mod(r, p); setvarn(r, v); return gerepileupto(av, r); } static GEN RgXQ_charpoly_fast(GEN x, GEN T, long v) { GEN p, pol; long pa, t = RgX_type2(x,T, &p,&pol,&pa); switch(t) { case t_INT: return ZXQ_charpoly(x, T, v); case t_FRAC: return QXQ_charpoly(x, T, v); case t_INTMOD: return RgXQ_charpoly_FpXQ(x, T, p, v); default: return NULL; } } /* (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)); } GEN RgXQ_charpoly_i(GEN x, GEN T, long v) { pari_sp av = avma; long d = degpol(T), dx = degpol(x), v0; GEN ch, L; if (dx >= degpol(T)) { x = RgX_rem(x, T); dx = degpol(x); } if (dx <= 0) return dx? pol_xn(d, v): caract_const(av, gel(x,2), v, d); v0 = fetch_var_higher(); x = RgX_neg(x); gel(x,2) = gadd(gel(x,2), pol_x(v)); setvarn(x, v0); T = leafcopy(T); setvarn(T, v0); ch = resultant(T, x); (void)delete_var(); /* test for silly input: x mod (deg 0 polynomial) */ if (typ(ch) != t_POL) pari_err_PRIORITY("RgXQ_charpoly", pol_x(v), "<", gvar(ch)); L = leading_coeff(ch); if (!gequal1(L)) ch = RgX_Rg_div(ch, L); return gerepileupto(av, ch); } /* return caract(Mod(x,T)) in variable v */ GEN RgXQ_charpoly(GEN x, GEN T, long v) { GEN ch = RgXQ_charpoly_fast(x, T, v); if (ch) return ch; return RgXQ_charpoly_i(x, T, v); } /* characteristic polynomial (in v) of x over nf, where x is an element of the * algebra nf[t]/(Q(t)) */ GEN rnfcharpoly(GEN nf, GEN Q, GEN x, long v) { const char *f = "rnfcharpoly"; long dQ = degpol(Q); pari_sp av = avma; GEN T; if (v < 0) v = 0; nf = checknf(nf); T = nf_get_pol(nf); Q = RgX_nffix(f, T,Q,0); switch(typ(x)) { case t_INT: case t_FRAC: return caract_const(av, x, v, dQ); case t_POLMOD: x = polmod_nffix2(f,T,Q, x,0); break; case t_POL: x = varn(x) == varn(T)? Rg_nffix(f,T,x,0): RgX_nffix(f, T,x,0); break; default: pari_err_TYPE(f,x); } if (typ(x) != t_POL) return caract_const(av, x, v, dQ); /* x a t_POL in variable vQ */ if (degpol(x) >= dQ) x = RgX_rem(x, Q); if (dQ <= 1) return caract_const(av, constant_coeff(x), v, 1); return gerepilecopy(av, lift_if_rational( RgXQ_charpoly(x, Q, v) )); } /*******************************************************************/ /* */ /* GCD USING SUBRESULTANT */ /* */ /*******************************************************************/ static int inexact(GEN x, int *simple); static int isinexactall(GEN x, int *simple) { long i, lx = lg(x); for (i=2; i 0) x = RgX_gcd_simple(x,y); else { dx = lg(x); dy = lg(y); if (dx < dy) { swap(x,y); lswap(dx,dy); } if (dy==3) { d = ggcd(gel(y,2), content(x)); return gerepileupto(av, scalarpol(d, varn(x))); } u = primitive_part(x, &p1); if (!p1) p1 = gen_1; v = primitive_part(y, &p2); if (!p2) p2 = gen_1; d = ggcd(p1,p2); av1 = avma; g = h = gen_1; for(;;) { GEN r = RgX_pseudorem(u,v); long degq, du, dv, dr = lg(r); if (!signe(r)) break; if (dr <= 3) { set_avma(av1); return gerepileupto(av, scalarpol(d, varn(x))); } du = lg(u); dv = lg(v); degq = du-dv; u = v; p1 = g; g = leading_coeff(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 (gc_needed(av1,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"RgX_gcd, dr = %ld", degpol(r)); 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); } /* disc P = (-1)^(n(n-1)/2) lc(P)^(n - deg P' - 2) Res(P,P'), n = deg P */ static GEN RgX_disc_i(GEN P) { long n = degpol(P), dd; GEN N, D, L, y; if (!signe(P) || !n) return Rg_get_0(P); if (n == 1) return Rg_get_1(P); if (n == 2) { GEN a = gel(P,4), b = gel(P,3), c = gel(P,2); return gsub(gsqr(b), gmul2n(gmul(a,c),2)); } y = RgX_deriv(P); N = characteristic(P); if (signe(N)) y = gmul(y, mkintmod(gen_1,N)); if (!signe(y)) return Rg_get_0(y); dd = n - 2 - degpol(y); if (isinexact(P)) D = resultant2(P,y); else { D = RgX_resultant_all(P, y, NULL); if (D == gen_0) return Rg_get_0(y); } L = leading_coeff(P); if (dd && !gequal1(L)) D = (dd == -1)? gdiv(D, L): gmul(D, gpowgs(L, dd)); if (n & 2) D = gneg(D); return D; } static GEN RgX_disc_FpX(GEN x, GEN p) { pari_sp av = avma; GEN r = FpX_disc(RgX_to_FpX(x, p), p); return gerepileupto(av, Fp_to_mod(r, p)); } static GEN RgX_disc_FpXQX(GEN x, GEN pol, GEN p) { pari_sp av = avma; GEN r, T = RgX_to_FpX(pol, p); r = FpXQX_disc(RgX_to_FpXQX(x, T, p), T, p); return gerepileupto(av, FpX_to_mod(r, p)); } static GEN RgX_disc_fast(GEN x) { GEN p, pol; long pa; long t = RgX_type(x, &p,&pol,&pa); switch(t) { case t_INT: return ZX_disc(x); case t_FRAC: return QX_disc(x); case t_FFELT: return FFX_disc(x, pol); case t_INTMOD: return RgX_disc_FpX(x, p); case code(t_POLMOD, t_INTMOD): return RgX_disc_FpXQX(x, pol, p); default: return NULL; } } GEN RgX_disc(GEN x) { pari_sp av; GEN z = RgX_disc_fast(x); if (z) return z; av = avma; return gerepileupto(av, RgX_disc_i(x)); } GEN poldisc0(GEN x, long v) { long v0, tx = typ(x); pari_sp av; GEN D; if (tx == t_POL && (v < 0 || v == varn(x))) return RgX_disc(x); switch(tx) { case t_QUAD: return quad_disc(x); case t_POLMOD: if (v >= 0 && varn(gel(x,1)) != v) break; return RgX_disc(gel(x,1)); case t_QFB: return icopy(qfb_disc(x)); case t_VEC: case t_COL: case t_MAT: { long i; GEN z = cgetg_copy(x, &i); for (i--; i; i--) gel(z,i) = poldisc0(gel(x,i), v); return z; } } if (v < 0) pari_err_TYPE("poldisc",x); av = avma; v0 = fetch_var_higher(); x = fix_pol(x,v, v0); D = RgX_disc(x); (void)delete_var(); return gerepileupto(av, D); } GEN reduceddiscsmith(GEN x) { long j, n = degpol(x); pari_sp av = avma; GEN xp, M; if (typ(x) != t_POL) pari_err_TYPE("poldiscreduced",x); if (n<=0) pari_err_CONSTPOL("poldiscreduced"); RgX_check_ZX(x,"poldiscreduced"); if (!gequal1(gel(x,n+2))) pari_err_IMPL("nonmonic polynomial in poldiscreduced"); M = cgetg(n+1,t_MAT); xp = ZX_deriv(x); for (j=1; j<=n; j++) { gel(M,j) = RgX_to_RgC(xp, n); if (j 0) { d = (vx == NO_VARIABLE)? ginv(x): gred_rfrac_simple(gen_1, x); return scalarpol(d, vy); } if (lg(x)!=3) pari_err_INV("RgXQ_inv",mkpolmod(x,y)); x = gel(x,2); vx = gvar(x); } av = avma; d = subresext_i(x,y,&u,&v/*junk*/); if (gequal0(d)) pari_err_INV("RgXQ_inv",mkpolmod(x,y)); d = gdiv(u,d); if (typ(d) != t_POL || varn(d) != vy) d = scalarpol(d, vy); return gerepileupto(av, d); } /*Assume x is a polynomial and y is not */ static GEN scalar_bezout(GEN x, GEN y, GEN *U, GEN *V) { long vx = varn(x); int xis0 = signe(x)==0, yis0 = gequal0(y); if (xis0 && yis0) { *U = *V = pol_0(vx); return pol_0(vx); } if (yis0) { *U=pol_1(vx); *V = pol_0(vx); return RgX_copy(x);} *U=pol_0(vx); *V= ginv(y); return pol_1(vx); } /* Assume x==0, y!=0 */ static GEN zero_bezout(GEN y, GEN *U, GEN *V) { *U=gen_0; *V = ginv(y); return gen_1; } GEN gbezout(GEN x, GEN y, GEN *u, GEN *v) { long tx=typ(x), ty=typ(y), vx; if (tx == t_INT && ty == t_INT) return bezout(x,y,u,v); if (tx != t_POL) { if (ty == t_POL) return scalar_bezout(y,x,v,u); else { int xis0 = gequal0(x), yis0 = gequal0(y); if (xis0 && yis0) { *u = *v = gen_0; return gen_0; } if (xis0) return zero_bezout(y,u,v); else return zero_bezout(x,v,u); } } else if (ty != t_POL) return scalar_bezout(x,y,u,v); vx = varn(x); if (vx != varn(y)) return varncmp(vx, varn(y)) < 0? scalar_bezout(x,y,u,v) : scalar_bezout(y,x,v,u); return RgX_extgcd(x,y,u,v); } GEN gcdext0(GEN x, GEN y) { GEN z=cgetg(4,t_VEC); gel(z,3) = gbezout(x,y,(GEN*)(z+1),(GEN*)(z+2)); return z; } /*******************************************************************/ /* */ /* GENERIC (modular) INVERSE */ /* */ /*******************************************************************/ GEN ginvmod(GEN x, GEN y) { long tx=typ(x); switch(typ(y)) { case t_POL: if (tx==t_POL) return RgXQ_inv(x,y); if (is_scalar_t(tx)) return ginv(x); break; case t_INT: if (tx==t_INT) return Fp_inv(x,y); if (tx==t_POL) return gen_0; } pari_err_TYPE2("ginvmod",x,y); return NULL; /* LCOV_EXCL_LINE */ } /***********************************************************************/ /** **/ /** NEWTON POLYGON **/ /** **/ /***********************************************************************/ /* assume leading coeff of x is nonzero */ GEN newtonpoly(GEN x, GEN p) { pari_sp av = avma; long n, ind, a, b; GEN y, vval; if (typ(x) != t_POL) pari_err_TYPE("newtonpoly",x); n = degpol(x); if (n<=0) return cgetg(1,t_VEC); vval = new_chunk(n+1); y = cgetg(n+1,t_VEC); x += 2; /* now x[i] = term of degree i */ for (a = 0; a <= n; a++) vval[a] = gvaluation(gel(x,a),p); for (a = 0, ind = 1; a < n; a++) { if (vval[a] != LONG_MAX) break; gel(y,ind++) = mkoo(); } for (b = a+1; b <= n; a = b, b = a+1) { long u1, u2, c; while (vval[b] == LONG_MAX) b++; u1 = vval[a] - vval[b]; u2 = b - a; for (c = b+1; c <= n; c++) { long r1, r2; if (vval[c] == LONG_MAX) continue; r1 = vval[a] - vval[c]; r2 = c - a; if (u1*r2 <= u2*r1) { u1 = r1; u2 = r2; b = c; } } while (ind <= b) gel(y,ind++) = sstoQ(u1,u2); } stackdummy((pari_sp)vval, av); return y; } static GEN RgXQ_mul_FpXQ(GEN x, GEN y, GEN T, GEN p) { pari_sp av = avma; GEN r; if (lgefint(p) == 3) { ulong pp = uel(p, 2); r = Flx_to_ZX_inplace(Flxq_mul(RgX_to_Flx(x, pp), RgX_to_Flx(y, pp), RgX_to_Flx(T, pp), pp)); } else r = FpXQ_mul(RgX_to_FpX(x, p), RgX_to_FpX(y, p), RgX_to_FpX(T, p), p); return gerepileupto(av, FpX_to_mod(r, p)); } static GEN RgXQ_sqr_FpXQ(GEN x, GEN y, GEN p) { pari_sp av = avma; GEN r; if (lgefint(p) == 3) { ulong pp = uel(p, 2); r = Flx_to_ZX_inplace(Flxq_sqr(RgX_to_Flx(x, pp), RgX_to_Flx(y, pp), pp)); } else r = FpXQ_sqr(RgX_to_FpX(x, p), RgX_to_FpX(y, p), p); return gerepileupto(av, FpX_to_mod(r, p)); } static GEN RgXQ_inv_FpXQ(GEN x, GEN y, GEN p) { pari_sp av = avma; GEN r; if (lgefint(p) == 3) { ulong pp = uel(p, 2); r = Flx_to_ZX_inplace(Flxq_inv(RgX_to_Flx(x, pp), RgX_to_Flx(y, pp), pp)); } else r = FpXQ_inv(RgX_to_FpX(x, p), RgX_to_FpX(y, p), p); return gerepileupto(av, FpX_to_mod(r, p)); } static GEN RgXQ_mul_FpXQXQ(GEN x, GEN y, GEN S, GEN pol, GEN p) { pari_sp av = avma; GEN r; GEN T = RgX_to_FpX(pol, p); if (signe(T)==0) pari_err_OP("*",x,y); if (lgefint(p) == 3) { ulong pp = uel(p, 2); GEN Tp = ZX_to_Flx(T, pp); r = FlxX_to_ZXX(FlxqXQ_mul(RgX_to_FlxqX(x, Tp, pp), RgX_to_FlxqX(y, Tp, pp), RgX_to_FlxqX(S, Tp, pp), Tp, pp)); } else r = FpXQXQ_mul(RgX_to_FpXQX(x, T, p), RgX_to_FpXQX(y, T, p), RgX_to_FpXQX(S, T, p), T, p); return gerepileupto(av, FpXQX_to_mod(r, T, p)); } static GEN RgXQ_sqr_FpXQXQ(GEN x, GEN y, GEN pol, GEN p) { pari_sp av = avma; GEN r; GEN T = RgX_to_FpX(pol, p); if (signe(T)==0) pari_err_OP("*",x,x); if (lgefint(p) == 3) { ulong pp = uel(p, 2); GEN Tp = ZX_to_Flx(T, pp); r = FlxX_to_ZXX(FlxqXQ_sqr(RgX_to_FlxqX(x, Tp, pp), RgX_to_FlxqX(y, Tp, pp), Tp, pp)); } else r = FpXQXQ_sqr(RgX_to_FpXQX(x, T, p), RgX_to_FpXQX(y, T, p), T, p); return gerepileupto(av, FpXQX_to_mod(r, T, p)); } static GEN RgXQ_inv_FpXQXQ(GEN x, GEN y, GEN pol, GEN p) { pari_sp av = avma; GEN r; GEN T = RgX_to_FpX(pol, p); if (signe(T)==0) pari_err_OP("^",x,gen_m1); if (lgefint(p) == 3) { ulong pp = uel(p, 2); GEN Tp = ZX_to_Flx(T, pp); r = FlxX_to_ZXX(FlxqXQ_inv(RgX_to_FlxqX(x, Tp, pp), RgX_to_FlxqX(y, Tp, pp), Tp, pp)); } else r = FpXQXQ_inv(RgX_to_FpXQX(x, T, p), RgX_to_FpXQX(y, T, p), T, p); return gerepileupto(av, FpXQX_to_mod(r, T, p)); } static GEN RgXQ_mul_fast(GEN x, GEN y, GEN T) { GEN p, pol; long pa; long t = RgX_type3(x,y,T, &p,&pol,&pa); switch(t) { case t_INT: return ZX_is_monic(T) ? ZXQ_mul(x,y,T): NULL; case t_FRAC: return RgX_is_ZX(T) && ZX_is_monic(T) ? QXQ_mul(x,y,T): NULL; case t_FFELT: return FFXQ_mul(x, y, T, pol); case t_INTMOD: return RgXQ_mul_FpXQ(x, y, T, p); case code(t_POLMOD, t_INTMOD): return RgXQ_mul_FpXQXQ(x, y, T, pol, p); default: return NULL; } } GEN RgXQ_mul(GEN x, GEN y, GEN T) { GEN z = RgXQ_mul_fast(x, y, T); if (!z) z = RgX_rem(RgX_mul(x, y), T); return z; } static GEN RgXQ_sqr_fast(GEN x, GEN T) { GEN p, pol; long pa; long t = RgX_type2(x, T, &p,&pol,&pa); switch(t) { case t_INT: return ZX_is_monic(T) ? ZXQ_sqr(x,T): NULL; case t_FRAC: return RgX_is_ZX(T) && ZX_is_monic(T) ? QXQ_sqr(x,T): NULL; case t_FFELT: return FFXQ_sqr(x, T, pol); case t_INTMOD: return RgXQ_sqr_FpXQ(x, T, p); case code(t_POLMOD, t_INTMOD): return RgXQ_sqr_FpXQXQ(x, T, pol, p); default: return NULL; } } GEN RgXQ_sqr(GEN x, GEN T) { GEN z = RgXQ_sqr_fast(x, T); if (!z) z = RgX_rem(RgX_sqr(x), T); return z; } static GEN RgXQ_inv_fast(GEN x, GEN y) { GEN p, pol; long pa; long t = RgX_type2(x,y, &p,&pol,&pa); switch(t) { case t_INT: return QXQ_inv(x,y); case t_FRAC: return RgX_is_ZX(y)? QXQ_inv(x,y): NULL; case t_FFELT: return FFXQ_inv(x, y, pol); case t_INTMOD: return RgXQ_inv_FpXQ(x, y, p); case code(t_POLMOD, t_INTMOD): return RgXQ_inv_FpXQXQ(x, y, pol, p); default: return NULL; } } GEN RgXQ_inv(GEN x, GEN y) { GEN z = RgXQ_inv_fast(x, y); if (!z) z = RgXQ_inv_i(x, y); return z; } pari-2.17.2/src/basemath/lerch.c0000644000175000017500000004506314760123736015021 0ustar billbill/* Copyright (C) 2022 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_trans /********************************************************/ /* Hurwitz zeta function */ /********************************************************/ struct Qp_zetahurwitz_t { GEN B, _1, s1; }; static void Qp_zetahurwitz_init(struct Qp_zetahurwitz_t *S, long prec, GEN s) { GEN B, C = gen_1, s1 = gsubgs(s, 1), p = gel(s, 2); long j, J = ((equaliu(p,2)? (prec >> 1): prec) + 2) >> 1; if (gequal0(s1)) s1 = NULL; B = bernvec(J); for (j = 1; j <= J; j++) { GEN t = (j == 1 && !s1)? s: gmul(gaddgs(s, 2*j-3), gaddgs(s, 2*j-2)); C = gdivgunextu(gmul(C, t), 2*j-1); gel(B, j+1) = gmul(gel(B, j+1), C); /* B_{2j} * binomial(1-s, 2j) */ } S->_1 = cvtop(gen_1, p, prec); S->s1 = s1; S->B = B; } /* v_p(x) < (p==2)?-1: 0; s1 = s-1 or NULL (if s=1) */ static GEN Qp_zetahurwitz_0(struct Qp_zetahurwitz_t *S, GEN x) { GEN z, x2, x2j, s1 = S->s1; long j, J = lg(S->B) - 2; x = cvtop2(ginv(x), S->_1); z = gmul2n(x, -1); z = s1? gmul(s1, z): gadd(Qp_log(x), z); x2j = x2 = gsqr(x); z = gaddgs(z, 1); for (j = 1;; j++) { z = gadd(z, gmul(gel(S->B, j + 1), x2j)); if (j == J) break; x2j = gmul(x2, x2j); } if (s1) z = gmul(gdiv(z, s1), Qp_exp(gmul(s1, Qp_log(x)))); return z; } /* private (absolute) padicprec */ static long pprec(GEN x) { return maxss(valp(x) + precp(x), 1); } /* L_p(s, (D, .)); assume s != 1 if D = 1 */ static GEN Qp_zeta_i(GEN s, long D) { pari_sp av = avma; GEN z, va, gp = gel(s,2); ulong a, p = itou(gp), m; long prec = pprec(s); struct Qp_zetahurwitz_t S; if (D <= 0) pari_err_DOMAIN("p-adic L-function", "D", "<=", gen_0, stoi(D)); if (!uposisfundamental(D)) pari_err_TYPE("p-adic L-function [D not fundamental]", stoi(D)); Qp_zetahurwitz_init(&S, prec, s); m = ulcm(D, p == 2? 4: p); va = coprimes_zv(m); for (a = 1, z = gen_0; a <= (m >> 1); a++) if (va[a]) { GEN h = Qp_zetahurwitz_0(&S, uutoQ(a, m)); if (D != 1 && kross(D, a) < 0) h = gneg(h); z = gadd(z, h); } z = gdivgs(gmul2n(z, 1), m); if (D != 1) z = gmul(z, Qp_exp(gmul(gsubsg(1, s), Qp_log(cvstop2(m, s))))); return gerepileupto(av, z); } GEN Qp_zeta(GEN s) { return Qp_zeta_i(s, 1); } /* s a t_PADIC; gerepileupto-safe. Could be exported */ static GEN Qp_zetahurwitz_ii(GEN s, GEN x, long k) { GEN gp = gel(s,2); long p = itou(gp), prec = pprec(s); struct Qp_zetahurwitz_t S; Qp_zetahurwitz_init(&S, prec, s); if (typ(x) != t_PADIC) x = gadd(x, zeropadic_shallow(gp, prec)); if (valp(x) >= ((p==2)? -1: 0)) { GEN z = gen_0; long j, M = (p==2)? 4: p; for (j = 0; j < M; j++) { GEN y = gaddsg(j, x); if (valp(y) <= 0) { GEN tmp = Qp_zetahurwitz_0(&S, gdivgu(y, M)); if (k) tmp = gmul(tmp, gpowgs(teich(y), k)); z = gadd(z, tmp); } } return gdivgu(z, M); } if (valp(s) < 0) pari_err_DOMAIN("Qp_zetahurwitz", "v(s)", "<", gen_0, s); return Qp_zetahurwitz_0(&S, x); } /* x or s must be p-adic */ static GEN Qp_zetahurwitz_i(GEN s, GEN x, long k) { if (typ(x) == t_PADIC) { pari_sp av = avma; GEN p = gel(x,2); long e = pprec(x); e += sdivsi(e, subis(p, 1)); s = gadd(s, zeropadic_shallow(p, e)); return gerepileupto(av, Qp_zetahurwitz_ii(s, x, k)); } return Qp_zetahurwitz_ii(s, x, k); } GEN Qp_zetahurwitz(GEN s, GEN x, long k) { pari_sp av = avma; return gerepileupto(av, Qp_zetahurwitz_i(s, x, k)); } static void binsplit(GEN *pP, GEN *pR, GEN aN2, GEN isqaN, GEN s, long j, long k, long prec) { if (j + 1 == k) { long j2 = j << 1; GEN P; if (!j) P = gdiv(s, aN2); else { P = gmul(gaddgs(s, j2-1), gaddgs(s, j2)); P = gdivgunextu(gmul(P, isqaN), j2+1); } if (pP) *pP = P; if (pR) *pR = gmul(bernreal(j2+2, prec), P); } else { GEN P1, R1, P2, R2; binsplit(&P1,pR? &R1: NULL, aN2, isqaN, s, j, (j+k) >> 1, prec); binsplit(pP? &P2: NULL, pR? &R2: NULL, aN2, isqaN, s, (j+k) >> 1, k, prec); if (pP) *pP = gmul(P1,P2); if (pR) *pR = gadd(R1, gmul(P1, R2)); } } /* a0 + a1 x + O(x^e), e >= 0 */ static GEN deg1ser_shallow(GEN a1, GEN a0, long v, long e) { return RgX_to_ser(deg1pol_shallow(a1, a0, v), e+2); } static long hurwitz_cutoff(GEN s, long bit) { return typ(s) == t_COMPLEX && fabs(gtodouble(gel(s,2))) > 5.37 * pow(bit, 1.4) / mt_nbthreads(); } /* New zetahurwitz, from Fredrik Johansson. */ GEN zetahurwitz(GEN s, GEN x, long der, long bitprec) { pari_sp av = avma, av2; GEN a, ra, ra0, Nx, S1, S2, S3, N2, rx, sch = NULL, s0 = s, x0 = x, y; long j, k, m, N, prec0 = nbits2prec(bitprec), prec = prec0, fli = 0; pari_timer T; if (der < 0) pari_err_DOMAIN("zetahurwitz", "der", "<", gen_0, stoi(der)); if (der) { GEN z; if (!is_scalar_t(typ(s))) { z = deriv(zetahurwitz(s, x, der - 1, bitprec), -1); z = gdiv(z, deriv(s, -1)); } else { if (gequal1(s)) pari_err_DOMAIN("zetahurwitz", "s", "=", gen_1, s0); s = deg1ser_shallow(gen_1, s, 0, der+2); z = zetahurwitz(s, x, 0, bitprec + der * log2(der)); z = gmul(mpfact(der), polcoef_i(z, der, -1)); } return gerepileupto(av,z); } if (typ(s) == t_PADIC || typ(x) == t_PADIC) return gerepileupto(av, Qp_zetahurwitz_i(s, x, 0)); switch(typ(x)) { case t_INT: case t_REAL: case t_FRAC: case t_COMPLEX: break; default: if (!(y = toser_i(x))) pari_err_TYPE("zetahurwitz", x); x = y; x0 = polcoef_i(x, 0, -1); break; } rx = real_i(x0); if (typ(x) != t_SER && typ(rx) == t_INT && signe(rx) <= 0 && gequal0(imag_i(x0))) pari_err_DOMAIN("zetahurwitz","x", "=", strtoGENstr("nonpositive integer"), x0); rx = grndtoi(rx, NULL); if (typ(rx) != t_INT) pari_err_TYPE("zetahurwitz", x); switch (typ(s)) { long v, pr; case t_INT: case t_REAL: case t_FRAC: case t_COMPLEX: if (!der && hurwitz_cutoff(s, bitprec)) return zetahurwitzlarge(s, x, prec); break; default: if (!(y = toser_i(s))) pari_err_TYPE("zetahurwitz", s); if (valser(y) < 0) pari_err_DOMAIN("zetahurwitz", "val(s)", "<", gen_0, s); s0 = polcoef_i(y, 0, -1); switch(typ(s0)) { case t_INT: case t_REAL: case t_FRAC: case t_COMPLEX: break; case t_PADIC: pari_err_IMPL("zetahurwitz(t_SER of t_PADIC)"); default: pari_err_TYPE("zetahurwitz", s0); } sch = gequal0(s0)? y: serchop0(y); v = valser(sch); pr = (lg(y) + v + 1) / v; if (gequal1(s0)) pr += v; s = deg1ser_shallow(gen_1, s0, 0, pr); } a = gneg(s0); ra = real_i(a); ra0 = ground(ra); if (gequal1(s0) && (!sch || gequal0(sch))) pari_err_DOMAIN("zetahurwitz", "s", "=", gen_1, s0); fli = (gsigne(ra0) >= 0 && gexpo(gsub(a, ra0)) < 17 - bitprec); if (!sch && fli) { /* a ~ non negative integer */ k = itos(gceil(ra)) + 1; if (odd(k)) k++; N = 1; } else { GEN C, ix = imag_i(x0); double c = (typ(s) == t_INT)? 1: 20 * log((double)bitprec); double rs = gtodouble(ra) + 1; long k0; if (fli) a = gadd(a, ghalf); /* hack */ if (rs > 0) { bitprec += (long)ceil(rs * expu(bitprec)); prec = nbits2prec(bitprec); x = gprec_w(x, prec); s = gprec_w(s, prec); if (sch) sch = gprec_w(sch, prec); } k = bitprec * M_LN2 / (1 + dbllambertW0(M_PI / c)); k0 = itos(gceil(gadd(ra, ghalf))) + 1; k = maxss(k0, k); if (odd(k)) k++; /* R_k < 2 |binom(a,k+1) B_{k+2}/(k+2)| */ C = binomial(a, k+1); C = polcoef_i(C, 0, -1); C = gmul(C, gdivgu(bernfrac(k+2), k+2)); C = gmul2n(gabs(C,LOWDEFAULTPREC), bitprec + 1); C = gpow(C, ginv(gsubsg(k+1, ra)), LOWDEFAULTPREC); /* need |N + x - 1|^2 > C^2 */ if (!gequal0(ix)) { GEN tmp = gsub(gsqr(C), gsqr(ix)); if (gsigne(tmp) >= 0) C = gsqrt(tmp, LOWDEFAULTPREC); } /* need |N + re(x) - 1| > C */ C = gceil(gadd(C, gsubsg(1, rx))); if (typ(C) != t_INT) pari_err_TYPE("zetahurwitz",s); N = signe(C) > 0? itos(C) : 1; if (N == 1 && signe(a) > 0) { /* May reduce k if 2Pix > a */ /* Need 2 |x^(-K) (B_K/K) binom(a, K-1)| < 2^-bit |x|^-rs |zeta(s,x)| * with K = k+2; N = 1; |zeta(s,x)| ~ |x|^(rs-1); * if a > 0, (B_K/K) binom(a, K-1) < 2 |a / 2Pi|^K */ double dx = dbllog2(x0), d = 1 + dx + log2(M_PI) - dbllog2(s0); if (d > 0) { /* d ~ log2 |2Pi x / a| */ long K = (long)ceil((bitprec + 1 + dx) / d); K = maxss(k0, K); if (odd(K)) K++; if (K < k) k = K; } } } if (gsigne(rx) < 0) N = maxss(N, 1 - itos(rx)); a = gneg(s); if (DEBUGLEVEL>2) timer_start(&T); incrprec(prec); Nx = gaddsg(N - 1, x); Nx = typ(Nx) == t_SER? RgX_gtofp(Nx, prec): gtofp(Nx, prec); S1 = S3 = gpow(Nx, a, prec); av2 = avma; if (gequal1(x)) S1 = dirpowerssum(N, a, 0, prec); else for (m = N - 2; m >= 0; m--) { S1 = gadd(S1, gpow(gaddsg(m,x), a, prec)); if ((m & 0xff) == 0) S1 = gerepileupto(av2, S1); } if (DEBUGLEVEL>2) timer_printf(&T,"sum from 0 to N - 1"); constbern(k >> 1); N2 = ginv(gsqr(Nx)); if (typ(s0) == t_INT) { S2 = divru(bernreal(k, prec), k); for (j = k - 2; j >= 2; j -= 2) { GEN t = gsubgs(a, j), u = gmul(t, gaddgs(t, 1)); u = gmul(gdivgunextu(u, j), gmul(S2, N2)); S2 = gadd(divru(bernreal(j, prec), j), u); } S2 = gmul(S2, gdiv(a, Nx)); } else { binsplit(NULL,&S2, gmul2n(Nx,1), N2, s, 0, k >> 1, prec); S2 = gneg(S2); } S2 = gadd(ghalf, S2); if (DEBUGLEVEL>2) timer_printf(&T,"Bernoulli sum"); S2 = gmul(S3, gadd(gdiv(Nx, gaddsg(1, a)), S2)); S1 = gprec_wtrunc(gsub(S1, S2), prec0); if (sch) return gerepileupto(av, gsubst(S1, 0, sch)); return gerepilecopy(av, S1); } /* New Lerch, inspired by Fredrik Johansson. */ GEN lerch_worker(GEN t, GEN E) { GEN n, d, T, s = gel(E,1), a = gmul(gel(E,2), t), z = gel(E,3); long p = itos(gel(E,4)), prec = labs(p); d = gadd(gexp(t, prec), z); T = p > 0? t: gneg(t); if (typ(s) == t_INT) n = gmul(gpow(T, s, prec), gexp(a, prec)); else /* save one exp */ n = gexp(gadd(gmul(s, glog(T, prec)), a), prec); return gdiv(n, d); } /* tab already computed with N = #tab[1] even */ static GEN parintnumgauss(GEN f, GEN a, GEN b, GEN tab, long prec) { GEN R = gel(tab, 1), W = gel(tab, 2), bma, bpa, S = gen_0, VP, VM, V; long n = lg(R) - 1, i, prec2 = prec + EXTRAPREC64; a = gprec_wensure(a, prec2); b = gprec_wensure(b, prec2); VP = cgetg(n + 1, t_VEC); bma = gmul2n(gsub(b, a), -1); VM = cgetg(n + 1, t_VEC); bpa = gadd(bma, a); for (i = 1; i <= n; i++) { GEN h = gmul(bma, gel(R, i)); gel(VP, i) = gadd(bpa, h); gel(VM, i) = gsub(bpa, h); } V = gadd(parapply(f, VP), parapply(f, VM)); for (i = 1; i <= n; i++) { S = gadd(S, gmul(gel(W, i), gel(V, i))); S = gprec_wensure(S, prec2); } return gprec_wtrunc(gmul(bma, S), prec); } /* Assume tab computed and a >= 0 */ static GEN parintnum(GEN f, GEN a, GEN tab) { pari_sp av; GEN tabx0 = gel(tab, 2), tabw0 = gel(tab, 3), tabxm = gel(tab, 6); GEN tabxp = gel(tab, 4), tabwp = gel(tab, 5), tabwm = gel(tab, 7); GEN VP = tabxp, VM = tabxm, x0 = tabx0, S; long prec = gprecision(tabw0), L = lg(tabxp), i, fla = 0; if (!gequal0(a)) { if (gexpo(a) <= 0) { x0 = gadd(a, x0); for (i = 1; i < L; i++) { gel(VP, i) = gadd(a, gel(VP, i)); gel(VM, i) = gadd(a, gel(VM, i)); } } else { x0 = gmul(a, gaddsg(1, x0)); fla = 1; for (i = 1; i < L; i++) { gel(VP, i) = gmul(a, gaddsg(1, gel(VP, i))); gel(VM, i) = gmul(a, gaddsg(1, gel(VM, i))); } } } VP = parapply(f, VP); VM = parapply(f, VM); av = avma; S = gmul(tabw0, closure_callgen1(f, x0)); for (i = 1; i < L; i++) { S = gadd(S, gadd(gmul(gel(tabwp, i), gel(VP, i)), gmul(gel(tabwm, i), gel(VM, i)))); if ((i & 0x7f) == 1) S = gerepileupto(av, S); S = gprec_wensure(S, prec); } if (fla) S = gmul(S, a); return gmul(S, gel(tab, 1)); } static GEN refine(GEN A) { long n = lg(A) - 1, i; GEN B = cgetg(2 * n, t_VEC); for (i = 1; i < n; i++) { gel(B, 2 * i - 1) = gel(A, i); gel(B, 2 * i) = gmul2n(gadd(gel(A, i), gel(A, i + 1)), -1); } gel(B, 2 * n - 1) = gel(A, n); return B; } /* Here L = [a1, a2, a3,...] integration vertices. Refine by splitting * intervals. */ static GEN parintnumgaussadapt(GEN f, GEN L, GEN tab, long bit) { GEN Rold = gen_0, Rnew; long i, ct = 0, prec = nbits2prec(bit); while (ct <= 5) { Rnew = gen_0; for (i = 1; i < lg(L) - 1; i++) Rnew = gadd(Rnew, parintnumgauss(f, gel(L, i), gel(L, i + 1), tab, prec)); if (ct && gexpo(gsub(Rnew, Rold)) - gexpo(Rnew) < 10 - bit) return Rnew; ct++; Rold = Rnew; L = refine(L); } if (DEBUGLEVEL) err_printf("intnumgaussadapt: possible accuracy loss"); return Rnew; /* Possible accuracy loss */ } /* Here b = [oo, r], so refine by increasing integration step m */ static GEN parintnumadapt(GEN f, GEN a, GEN b, GEN tab, long bit) { GEN Rold = gen_0, Rnew; long m = 0, prec = nbits2prec(bit); if (!tab) tab = intnuminit(gen_0, b, 0, prec); while (m <= 5) { Rnew = parintnum(f, a, tab); if (m && gexpo(gsub(Rnew, Rold)) - gexpo(Rnew) < 10 - bit) return Rnew; m++; Rold = Rnew; tab = intnuminit(gen_0, b, m, prec); } if (DEBUGLEVEL) err_printf("intnumadapt: possible accuracy loss"); return Rnew; /* Possible accuracy loss */ } static int iscplx(GEN z) { long t = typ(z); return is_real_t(t) || t == t_COMPLEX; } static GEN lerch_easy(GEN z, GEN s, GEN a, long B) { long n, prec = nbits2prec(B + 32); GEN zn, ms = gneg(s), S = gpow(a, ms, prec); zn = z = gtofp(z, prec); for (n = 1;; n++, zn = gmul(zn, z)) { S = gadd(S, gmul(zn, gpow(gaddgs(a, n), ms, prec))); if (gexpo(zn) <= - B - 5) return S; } } static GEN _lerchphi(GEN z, GEN s, GEN a, long prec) { GEN res = NULL, L, LT, J, rs, mleft, left, right, top, w, Linf, tabg; GEN E, f, fm; long B = prec2nbits(prec), MB = 3 - B, NB, prec2; entree *ep; if (gexpo(z) < MB) return gpow(a, gneg(s), prec); if (gexpo(gsubgs(z, 1)) < MB) return zetahurwitz(s, a, 0, B); /* z ~ 1 */ if (gexpo(gaddgs(z, 1)) < MB) /* z ~ -1 */ { GEN tmp = gsub(zetahurwitz(s, gmul2n(a, -1), 0, B), zetahurwitz(s, gmul2n(gaddgs(a, 1), -1), 0, B)); return gmul(gpow(gen_2, gneg(s), prec), tmp); } if (gcmpgs(gmulsg(10, gabs(z, prec)), 9) <= 0) /* |z| <= 9/10 */ return lerch_easy(z, s, a, B); if (gcmpgs(real_i(a), 2) < 0) return gadd(gpow(a, gneg(s), prec), gmul(z, _lerchphi(z, s, gaddgs(a, 1), prec))); NB = (long)ceil(B + M_PI * fabs(gtodouble(imag_i(s)))); prec2 = nbits2prec(NB); z = gprec_w(z, prec2); /* |z| > 9/10 */ s = gprec_w(s, prec2); a = gprec_w(a, prec2); /* Re(a) >= 2 */ rs = ground(real_i(s)); L = glog(z, prec2); /* Re(L) > -0.11 */ ep = is_entry("_lerch_worker"); E = mkvec4(gsubgs(s, 1), gsubsg(1, a), gneg(z), stoi(prec2)); f = snm_closure(ep, mkvec(E)); E = shallowcopy(E); gel(E,4) = stoi(-prec2); fm = snm_closure(ep, mkvec(E)); Linf = mkvec2(mkoo(), real_i(a)); if (gexpo(gsub(s, rs)) < MB && gcmpgs(rs, 1) >= 0) { /* s ~ positive integer */ if (gcmp(gabs(imag_i(L), prec2), sstoQ(1, 4)) < 0 && gsigne(real_i(L)) >= 0) { /* Re(L) >= 0, |Im(L)| < 1/4 */ GEN t = gsigne(imag_i(z)) > 0 ? gen_m1: gen_1; GEN LT1 = gaddgs(gabs(L, prec2), 1); LT = mkvec4(gen_0, mkcomplex(gen_0, t), mkcomplex(LT1, t), LT1); tabg = intnumgaussinit(2*(NB >> 2) + 60, prec2); J = parintnumgaussadapt(f, LT, tabg, NB); J = gadd(J, parintnumadapt(f, LT1, Linf, NULL, NB)); } else J = parintnumadapt(f, gen_0, Linf, NULL, NB); return gdiv(J, ggamma(s, prec2)); } tabg = intnumgaussinit(2*(NB >> 2) + 60, prec2); if (gcmp(gabs(imag_i(L), prec2), ghalf) > 0) /* |Im(L)| > 1/2 */ left = right = top = gmin(gmul2n(gabs(imag_i(L), prec2), -1), gen_1); else { res = gdiv(gpow(gneg(L), s, prec2), gmul(L, gpow(z, a, prec2))); left = gaddgs(gmax(gen_0, gneg(real_i(L))), 1); top = gaddgs(gabs(imag_i(L), prec2), 1); right = gaddgs(gabs(L, prec2), 1); } w = expIPiC(gsubgs(s, 1), prec2); mleft = gneg(left); if (gexpo(imag_i(z)) < MB && gexpo(imag_i(a)) < MB && gexpo(imag_i(s)) < MB && gcmpgs(real_i(z), 1) < 0) { /* (z, s, a) real, z < 1 */ LT = mkvec3(right, mkcomplex(right, top), mkcomplex(mleft, top)); J = imag_i(gdiv(parintnumgaussadapt(f, LT, tabg, NB), w)); LT = mkvec2(mkcomplex(mleft, top), mleft); J = gmul2n(gadd(J, imag_i(parintnumgaussadapt(fm, LT, tabg, NB))), 1); J = mulcxI(J); } else { GEN mtop = gneg(top); LT = mkvec3(right, mkcomplex(right, top), mkcomplex(mleft, top)); J = gdiv(parintnumgaussadapt(f, LT, tabg, NB), w); LT = mkvec2(mkcomplex(mleft, top), mkcomplex(mleft, mtop)); J = gadd(J, parintnumgaussadapt(fm, LT, tabg, NB)); LT = mkvec3(mkcomplex(mleft, mtop), mkcomplex(right, mtop), right); J = gadd(J, gmul(parintnumgaussadapt(f, LT, tabg, NB), w)); } J = gadd(J, gmul(gsub(w, ginv(w)), parintnumadapt(f, right, Linf, NULL, NB))); J = gdiv(J, PiI2(prec2)); if (res) J = gadd(J, res); return gneg(gmul(ggamma(gsubsg(1, s), prec2), J)); } /* lerchphi(z,-k,a)= * -1/(z-1)*sum(q=0,k,(z/(z-1))^q*sum(j=0,q,(-1)^j*(j+a)^k*binomial(q,j))) * zetahurwitz(-k,a)=-B(k+1,a)/(k+1) */ GEN lerchphi(GEN z, GEN s, GEN a, long prec) { pari_sp av = avma; if (!iscplx(z)) pari_err_TYPE("lerchphi", z); if (!iscplx(s)) pari_err_TYPE("lerchphi", s); if (!iscplx(a)) pari_err_TYPE("lerchphi", a); return gerepileupto(av, _lerchphi(z, s, a, prec)); } GEN lerchzeta(GEN s, GEN a, GEN lam, long prec) { pari_sp av = avma; GEN z = gexp(gmul(PiI2(prec), lam), prec); if (!iscplx(z)) pari_err_TYPE("lerchzeta", z); if (!iscplx(s)) pari_err_TYPE("lerchzeta", s); if (!iscplx(a)) pari_err_TYPE("lerchzeta", a); if (hurwitz_cutoff(s, prec)) return lerchzetalarge(s, a, lam, prec); return gerepileupto(av, _lerchphi(z, s, a, prec)); } pari-2.17.2/src/basemath/polarit3.c0000644000175000017500000026120414760137411015451 0ustar billbill/* Copyright (C) 2000-2005 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /***********************************************************************/ /** **/ /** ARITHMETIC OPERATIONS ON POLYNOMIALS **/ /** (third part) **/ /** **/ /***********************************************************************/ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_pol /************************************************************************ ** ** ** Ring membership ** ** ** ************************************************************************/ struct charact { GEN q; int isprime; }; static void char_update_prime(struct charact *S, GEN p) { if (!S->isprime) { S->isprime = 1; S->q = p; } if (!equalii(p, S->q)) pari_err_MODULUS("characteristic", S->q, p); } static void char_update_int(struct charact *S, GEN n) { if (S->isprime) { if (dvdii(n, S->q)) return; pari_err_MODULUS("characteristic", S->q, n); } S->q = gcdii(S->q, n); } static void charact(struct charact *S, GEN x) { const long tx = typ(x); long i, l; switch(tx) { case t_INTMOD:char_update_int(S, gel(x,1)); break; case t_FFELT: char_update_prime(S, gel(x,4)); break; case t_COMPLEX: case t_QUAD: case t_POLMOD: case t_POL: case t_SER: case t_RFRAC: case t_VEC: case t_COL: case t_MAT: l = lg(x); for (i=lontyp[tx]; i < l; i++) charact(S,gel(x,i)); break; case t_LIST: x = list_data(x); if (x) charact(S, x); break; } } static void charact_res(struct charact *S, GEN x) { const long tx = typ(x); long i, l; switch(tx) { case t_INTMOD:char_update_int(S, gel(x,1)); break; case t_FFELT: char_update_prime(S, gel(x,4)); break; case t_PADIC: char_update_prime(S, gel(x,2)); break; case t_COMPLEX: case t_QUAD: case t_POLMOD: case t_POL: case t_SER: case t_RFRAC: case t_VEC: case t_COL: case t_MAT: l = lg(x); for (i=lontyp[tx]; i < l; i++) charact_res(S,gel(x,i)); break; case t_LIST: x = list_data(x); if (x) charact_res(S, x); break; } } GEN characteristic(GEN x) { struct charact S; S.q = gen_0; S.isprime = 0; charact(&S, x); return S.q; } GEN residual_characteristic(GEN x) { struct charact S; S.q = gen_0; S.isprime = 0; charact_res(&S, x); return S.q; } int Rg_is_Fp(GEN x, GEN *pp) { GEN mod; switch(typ(x)) { case t_INTMOD: mod = gel(x,1); if (!*pp) *pp = mod; else if (mod != *pp && !equalii(mod, *pp)) { if (DEBUGLEVEL) pari_warn(warner,"different moduli in Rg_is_Fp"); return 0; } return 1; case t_INT: return 1; default: return 0; } } int RgX_is_FpX(GEN x, GEN *pp) { long i, lx = lg(x); for (i=2; i 0 a t_INT, return lift(x * Mod(1,p)). * If x is an INTMOD, assume modulus is a multiple of p. */ GEN Rg_to_Fp(GEN x, GEN p) { if (lgefint(p) == 3) return utoi(Rg_to_Fl(x, uel(p,2))); switch(typ(x)) { case t_INT: return modii(x, p); case t_FRAC: { pari_sp av = avma; GEN z = modii(gel(x,1), p); if (z == gen_0) return gen_0; return gerepileuptoint(av, remii(mulii(z, Fp_inv(gel(x,2), p)), p)); } case t_PADIC: return padic_to_Fp(x, p); case t_INTMOD: { GEN q = gel(x,1), a = gel(x,2); if (equalii(q, p)) return icopy(a); if (!dvdii(q,p)) pari_err_MODULUS("Rg_to_Fp", q, p); return remii(a, p); } default: pari_err_TYPE("Rg_to_Fp",x); return NULL; /* LCOV_EXCL_LINE */ } } /* 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 = get_FpX_var(T); GEN a, b; if (is_const_t(tx)) { if (tx == t_FFELT) { GEN z = FF_to_FpXQ(x); setvarn(z, v); return z; } return scalar_ZX(degpol(T)? Rg_to_Fp(x, p): gen_0, v); } switch(tx) { case t_POLMOD: b = gel(x,1); a = gel(x,2); ta = typ(a); if (is_const_t(ta)) return scalar_ZX(degpol(T)? Rg_to_Fp(a, p): gen_0, v); b = RgX_to_FpX(b, p); if (varn(b) != v) break; a = RgX_to_FpX(a, p); if (ZX_equal(b,get_FpX_mod(T)) || signe(FpX_rem(b,T,p))==0) return FpX_rem(a, T, p); break; case t_POL: if (varn(x) != v) break; return FpX_rem(RgX_to_FpX(x,p), T, p); case t_RFRAC: a = Rg_to_FpXQ(gel(x,1), T,p); b = Rg_to_FpXQ(gel(x,2), T,p); return FpXQ_div(a,b, T,p); } pari_err_TYPE("Rg_to_FpXQ",x); return NULL; /* LCOV_EXCL_LINE */ } GEN RgX_to_FpX(GEN x, GEN p) { long i, l; GEN z = cgetg_copy(x, &l); z[1] = x[1]; for (i = 2; i < l; i++) gel(z,i) = Rg_to_Fp(gel(x,i), p); return FpX_renormalize(z, l); } GEN RgV_to_FpV(GEN x, GEN p) { pari_APPLY_type(t_VEC, Rg_to_Fp(gel(x,i), p)) } GEN RgC_to_FpC(GEN x, GEN p) { pari_APPLY_type(t_COL, Rg_to_Fp(gel(x,i), p)) } GEN RgM_to_FpM(GEN x, GEN p) { pari_APPLY_same(RgC_to_FpC(gel(x,i), p)) } GEN RgV_to_Flv(GEN x, ulong p) { pari_APPLY_ulong(Rg_to_Fl(gel(x,i), p)) } GEN RgM_to_Flm(GEN x, ulong p) { pari_APPLY_same(RgV_to_Flv(gel(x,i), p)) } 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 FpXQX_renormalize(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]; if (T) for (i = 2; i < l; i++) gel(z,i) = Rg_to_FpXQ(gel(x,i), T, p); else for (i = 2; i < l; i++) gel(z,i) = Rg_to_Fp(gel(x,i), p); return FpXQX_renormalize(z, l); } GEN RgC_to_FqC(GEN x, GEN T, GEN p) { long i, l = lg(x); GEN z = cgetg(l, t_COL); if (T) for (i = 1; i < l; i++) gel(z,i) = Rg_to_FpXQ(gel(x,i), T, p); else for (i = 1; i < l; i++) gel(z,i) = Rg_to_Fp(gel(x,i), p); return z; } GEN RgM_to_FqM(GEN x, GEN T, GEN p) { pari_APPLY_same(RgC_to_FqC(gel(x, i), T, p)) } /* 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 3) /* nonconstant */ return FqX_Fq_mul_to_monic(z, Fq_inv(lc,T,p), T,p); /* constant */ lc = gel(lc,2); z = shallowcopy(z); gel(z, lg(z)-1) = lc; } /* lc a t_INT */ if (equali1(lc)) return z; return FqX_Fq_mul_to_monic(z, Fp_inv(lc,p), T,p); } GEN FqX_eval(GEN x, GEN y, GEN T, GEN p) { pari_sp av; GEN p1, r; long j, i=lg(x)-1; if (i<=2) return (i==2)? Fq_red(gel(x,2), T, p): gen_0; av=avma; p1=gel(x,i); /* specific attention to sparse polynomials (see poleval)*/ /*You've guessed it! It's a copy-paste(tm)*/ for (i--; i>=2; i=j-1) { for (j=i; !signe(gel(x,j)); j--) if (j==2) { if (i!=j) y = Fq_pow(y,utoipos(i-j+1), T, p); return gerepileupto(av, Fq_mul(p1,y, T, p)); } r = (i==j)? y: Fq_pow(y, utoipos(i-j+1), T, p); p1 = Fq_add(Fq_mul(p1,r,T,p), gel(x,j), T, p); } return gerepileupto(av, p1); } GEN FqXY_evalx(GEN Q, GEN x, GEN T, GEN p) { long i, lb = lg(Q); GEN z; if (!T) return FpXY_evalx(Q, x, p); z = cgetg(lb, t_POL); z[1] = Q[1]; for (i=2; iT, s->p); } static GEN _Fq_add(void *E, GEN x, GEN y) { (void) E; switch((typ(x)==t_POL)|((typ(y)==t_POL)<<1)) { case 0: return addii(x,y); case 1: return ZX_Z_add(x,y); case 2: return ZX_Z_add(y,x); default: return ZX_add(x,y); } } static GEN _Fq_neg(void *E, GEN x) { (void) E; return typ(x)==t_POL?ZX_neg(x):negi(x); } static GEN _Fq_mul(void *E, GEN x, GEN y) { (void) E; switch((typ(x)==t_POL)|((typ(y)==t_POL)<<1)) { case 0: return mulii(x,y); case 1: return ZX_Z_mul(x,y); case 2: return ZX_Z_mul(y,x); default: return ZX_mul(x,y); } } static GEN _Fq_inv(void *E, GEN x) { struct _Fq_field *s = (struct _Fq_field *)E; return Fq_inv(x,s->T,s->p); } static int _Fq_equal0(GEN x) { return signe(x)==0; } static GEN _Fq_s(void *E, long x) { (void) E; return stoi(x); } static const struct bb_field Fq_field={_Fq_red,_Fq_add,_Fq_mul,_Fq_neg, _Fq_inv,_Fq_equal0,_Fq_s}; const struct bb_field *get_Fq_field(void **E, GEN T, GEN p) { if (!T) return get_Fp_field(E, p); else { GEN z = new_chunk(sizeof(struct _Fq_field)); struct _Fq_field *e = (struct _Fq_field *) z; e->T = T; e->p = p; *E = (void*)e; return &Fq_field; } } /*******************************************************************/ /* */ /* Fq[X] */ /* */ /*******************************************************************/ /* P(X + c) */ GEN FpX_translate(GEN P, GEN c, GEN p) { pari_sp av = avma; GEN Q, *R; long i, k, n; if (!signe(P) || !signe(c)) return ZX_copy(P); Q = leafcopy(P); R = (GEN*)(Q+2); n = degpol(P); for (i=1; i<=n; i++) { for (k=n-i; k1) pari_warn(warnmem,"FpX_translate, i = %ld/%ld", i,n); Q = gerepilecopy(av, Q); R = (GEN*)Q+2; } } return gerepilecopy(av, FpX_renormalize(Q, lg(Q))); } /* P(X + c), c an Fq */ GEN FqX_translate(GEN P, GEN c, GEN T, GEN p) { pari_sp av = avma; GEN Q, *R; long i, k, n; /* signe works for t_(INT|POL) */ if (!signe(P) || !signe(c)) return RgX_copy(P); Q = leafcopy(P); R = (GEN*)(Q+2); n = degpol(P); for (i=1; i<=n; i++) { for (k=n-i; k1) pari_warn(warnmem,"FqX_translate, i = %ld/%ld", i,n); Q = gerepilecopy(av, Q); R = (GEN*)Q+2; } } return gerepilecopy(av, FpXQX_renormalize(Q, lg(Q))); } GEN FqV_roots_to_pol(GEN V, GEN T, GEN p, long v) { pari_sp ltop = avma; long k; GEN W; if (lgefint(p) == 3) { ulong pp = p[2]; GEN Tl = ZX_to_Flx(T, pp); GEN Vl = ZXC_to_FlxC(V, pp, get_Flx_var(Tl)); 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 x, GEN T, GEN p) { pari_APPLY_same(Fq_red(gel(x,i), T, p)) } GEN FqC_add(GEN x, GEN y, GEN T, GEN p) { if (!T) return FpC_add(x, y, p); pari_APPLY_type(t_COL, Fq_add(gel(x,i), gel(y,i), T, p)) } GEN FqC_sub(GEN x, GEN y, GEN T, GEN p) { if (!T) return FpC_sub(x, y, p); pari_APPLY_type(t_COL, Fq_sub(gel(x,i), gel(y,i), T, p)) } GEN FqC_Fq_mul(GEN x, GEN y, GEN T, GEN p) { if (!T) return FpC_Fp_mul(x, y, p); pari_APPLY_type(t_COL, Fq_mul(gel(x,i),y,T,p)) } GEN FqC_FqV_mul(GEN x, GEN y, GEN T, GEN p) { 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++) { GEN zj = cgetg(lx,t_COL); for (i=1; i 4) { timer_start(&ti); err_printf("%s: nb primes: %ld\n",str, n); } if (m == 1) { GEN P = primelist(S, n, dB); GEN done = closure_callgen1(worker, P); H = gel(done,1); mod = gel(done,2); if (!*pH && center) H = center(H, mod, shifti(mod,-1)); if (DEBUGLEVEL>4) timer_printf(&ti,"%s: modular", str); } else { long i, s = (n+m-1)/m, r = m - (m*s-n), di = 0; struct pari_mt pt; long pending = 0; H = cgetg(m+1, t_VEC); P = cgetg(m+1, t_VEC); mt_queue_start_lim(&pt, worker, m); for (i=1; i<=m || pending; i++) { GEN done; GEN pr = i <= m ? mkvec(primelist(S, i<=r ? s: s-1, dB)): NULL; mt_queue_submit(&pt, i, pr); done = mt_queue_get(&pt, NULL, &pending); if (done) { di++; gel(H, di) = gel(done,1); gel(P, di) = gel(done,2); if (DEBUGLEVEL>5) err_printf("%ld%% ",100*di/m); } } mt_queue_end(&pt); if (DEBUGLEVEL>5) err_printf("\n"); if (DEBUGLEVEL>4) timer_printf(&ti,"%s: modular", str); H = crt(H, P, &mod); if (DEBUGLEVEL>4) timer_printf(&ti,"%s: chinese", str); } if (*pH) H = crt(mkvec2(*pH, H), mkvec2(*pmod, mod), &mod); *pH = H; *pmod = mod; } void gen_inccrt(const char *str, GEN worker, GEN dB, long n, long mmin, forprime_t *S, GEN *pH, GEN *pmod, GEN crt(GEN, GEN, GEN*), GEN center(GEN, GEN, GEN)) { pari_sp av = avma; gen_inccrt_i(str, worker, dB, n, mmin, S, pH, pmod, crt, center); gerepileall(av, 2, pH, pmod); } GEN gen_crt(const char *str, GEN worker, forprime_t *S, GEN dB, ulong bound, long mmin, GEN *pmod, GEN crt(GEN, GEN, GEN*), GEN center(GEN, GEN, GEN)) { GEN mod = gen_1, H = NULL; ulong e; bound++; while (bound > (e = expi(mod))) { long n = (bound - e) / expu(S->p) + 1; gen_inccrt(str, worker, dB, n, mmin, S, &H, &mod, crt, center); } if (pmod) *pmod = mod; return H; } /*******************************************************************/ /* */ /* MODULAR GCD */ /* */ /*******************************************************************/ /* return z = a mod q, b mod p (p,q) = 1; qinv = 1/q mod p; a in ]-q,q] */ static GEN Fl_chinese_coprime(GEN a, ulong b, GEN q, ulong p, ulong qinv, GEN pq, GEN pq2) { ulong d, amod = umodiu(a, p); pari_sp av = avma; GEN ax; if (b == amod) return NULL; d = Fl_mul(Fl_sub(b, amod, p), qinv, p); /* != 0 */ if (d >= 1 + (p>>1)) ax = subii(a, mului(p-d, q)); else { ax = addii(a, mului(d, q)); /* in ]0, pq[ assuming a in ]-q,q[ */ if (cmpii(ax,pq2) > 0) ax = subii(ax,pq); } return gerepileuptoint(av, ax); } 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 c, cp, H = cgetg(l, t_MAT); if (l==1) return H; m = lgcols(Hp); for (j=1; j lp) { /* degree decreases */ GEN x = cgetg(l, t_VECSMALL); for (i=1; i>1), n; H = cgetg(l, t_MAT); if (l==1) return H; m = lgcols(Hp); n = deg + 3; for (j=1; j 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 (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"Flx_resultant_all"); gerepileall(av, 2, &a,&b); } db = dc; /* = degpol(b) */ } if (ind+1 > lg(dglist)) setlg(dglist,ind+1); set_avma(av); } /* 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; *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]) return gc_ulong(av,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 (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"Flx_resultant_all"); gerepileall(av, 2, &a,&b); } } if (da > 1) return 0; /* Failure */ /* last nonconstant 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; return gc_ulong(av,res); } /* Q a vector of polynomials representing B in Fp[X][Y], evaluate at X = x, * Return 0 in case of degree drop. */ static GEN FlxY_evalx_drop(GEN Q, ulong x, ulong p) { GEN z; long i, lb = lg(Q); ulong leadz = Flx_eval(leading_coeff(Q), x, p); long vs=mael(Q,2,1); if (!leadz) return zero_Flx(vs); z = cgetg(lb, t_VECSMALL); z[1] = vs; for (i=2; i=2; i--) { GEN c = gel(Q,i); z = FqX_Fq_mul(z, y, T, p); z = typ(c) == t_INT? FqX_Fq_add(z,c,T,p): FqX_add(z,c,T,p); } return gerepileupto(av, z); } static GEN ZX_norml1(GEN x) { long i, l = lg(x); GEN s; if (l == 2) return gen_0; s = gel(x, l-1); /* != 0 */ for (i = l-2; i > 1; i--) { GEN xi = gel(x,i); if (!signe(xi)) continue; s = addii_sign(s,1, xi,1); } return s; } /* x >= 0, y != 0, return x + |y| */ static GEN addii_abs(GEN x, GEN y) { if (!signe(x)) return absi_shallow(y); return addii_sign(x,1, y,1); } /* x a ZX, return sum_{i >= k} |x[i]| binomial(i, k) */ static GEN ZX_norml1_1(GEN x, long k) { long i, d = degpol(x); GEN s, C; /* = binomial(i, k) */ if (!d || k > d) return gen_0; s = absi_shallow(gel(x, k+2)); /* may be 0 */ C = gen_1; for (i = k+1; i <= d; i++) { GEN xi = gel(x,i+2); if (k) C = diviuexact(muliu(C, i), i-k); if (signe(xi)) s = addii_abs(s, mulii(C, xi)); } return s; } /* x has non-negative real coefficients */ static GEN RgX_norml1_1(GEN x, long k) { long i, d = degpol(x); GEN s, C; /* = binomial(i, k) */ if (!d || k > d) return gen_0; s = gel(x, k+2); /* may be 0 */ C = gen_1; for (i = k+1; i <= d; i++) { GEN xi = gel(x,i+2); if (k) C = diviuexact(muliu(C, i), i-k); if (!gequal0(xi)) s = gadd(s, gmul(C, xi)); } return s; } /* N_2(A)^2 */ static GEN sqrN2(GEN A, long prec) { pari_sp av = avma; long i, l = lg(A); GEN a = gen_0; for (i = 2; i < l; i++) { a = gadd(a, gabs(gnorm(gel(A,i)), prec)); if (gc_needed(av,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"RgX_RgXY_ResBound i = %ld",i); a = gerepileupto(av, a); } } return a; } /* 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 */ static GEN RgX_RgXY_ResBound(GEN A, GEN B, long prec) { pari_sp av = avma; GEN b = gen_0, bnd; long i, lB = lg(B); for (i=2; i1) pari_warn(warnmem,"RgX_RgXY_ResBound i = %ld",i); b = gerepileupto(av, b); } } bnd = gsqrt(gmul(gpowgs(sqrN2(A,prec), degpol(B)), gpowgs(b, degpol(A))), prec); return gerepileupto(av, bnd); } /* A,B in C[X] return RgX_RgXY_ResBound(A, B(x+y)) */ static GEN RgX_RgXY_ResBound_1(GEN A, GEN B, long prec) { pari_sp av = avma, av2; GEN b = gen_0, bnd; long i, lB = lg(B); B = shallowcopy(B); for (i=2; i1) pari_warn(warnmem,"RgX_RgXY_ResBound i = %ld",i); b = gerepileupto(av2, b); } } bnd = gsqrt(gmul(gpowgs(sqrN2(A,prec), degpol(B)), gpowgs(b, degpol(A))), prec); return gerepileupto(av, bnd); } /* log2 N_2(A)^2 */ static double log2N2(GEN A) { pari_sp av = avma; long i, l = lg(A); GEN a = gen_0; for (i=2; i < l; i++) { a = addii(a, sqri(gel(A,i))); if (gc_needed(av,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"ZX_ZXY_ResBound i = %ld",i); a = gerepileupto(av, a); } } return gc_double(av, dbllog2(a)); } /* 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 b = gen_0; long i, lB = lg(B); double logb; for (i=2; i1) pari_warn(warnmem,"ZX_ZXY_ResBound i = %ld",i); b = gerepileupto(av, b); } } logb = dbllog2(b); if (dB) logb -= 2 * dbllog2(dB); i = (long)((degpol(B) * log2N2(A) + degpol(A) * logb) / 2); return gc_ulong(av, (i <= 0)? 1: 1 + (ulong)i); } /* A,B ZX. Return ZX_ZXY_ResBound(A(x), B(x+y)) */ static ulong ZX_ZXY_ResBound_1(GEN A, GEN B) { pari_sp av = avma; GEN b = gen_0; long i, lB = lg(B); for (i=2; i1) pari_warn(warnmem,"ZX_ZXY_ResBound i = %ld",i); b = gerepileupto(av, b); } } i = (long)((degpol(B) * log2N2(A) + degpol(A) * dbllog2(b)) / 2); return gc_ulong(av, (i <= 0)? 1: 1 + (ulong)i); } /* special case B = A' */ static ulong ZX_discbound(GEN A) { pari_sp av = avma; GEN a = gen_0, b = gen_0; long i , lA = lg(A), dA = degpol(A); double loga, logb; for (i = 2; i < lA; i++) { GEN c = sqri(gel(A,i)); a = addii(a, c); if (i > 2) b = addii(b, mulii(c, sqru(i-2))); if (gc_needed(av,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"ZX_discbound i = %ld",i); gerepileall(av, 2, &a, &b); } } loga = dbllog2(a); logb = dbllog2(b); set_avma(av); i = (long)(((dA-1) * loga + dA * logb) / 2); return (i <= 0)? 1: 1 + (ulong)i; } /* return Res(a(Y), b(n,Y)) over Fp. la = leading_coeff(a) [for efficiency] */ static ulong Flx_FlxY_eval_resultant(GEN a, GEN b, ulong n, ulong p, ulong pi, ulong la) { GEN ev = FlxY_evalx_pre(b, n, p, pi); long drop = lg(b) - lg(ev); ulong r = Flx_resultant_pre(a, ev, p, pi); if (drop && la != 1) r = Fl_mul(r, Fl_powu_pre(la, drop, p, pi), p); return r; } static GEN FpX_FpXY_eval_resultant(GEN a, GEN b, GEN n, GEN p, GEN la, long db, long vX) { GEN ev = FpXY_evaly(b, n, p, vX); long drop = db-degpol(ev); GEN r = FpX_resultant(a, ev, p); if (drop && !gequal1(la)) r = Fp_mul(r, Fp_powu(la, drop,p),p); return r; } /* assume dres := deg(Res_X(a,b), Y) <= deg(a,X) * deg(b,Y) < p */ /* Return a Fly */ static GEN Flx_FlxY_resultant_polint(GEN a, GEN b, ulong p, ulong pi, long dres, long sx) { long i; ulong n, la = Flx_lead(a); GEN x = cgetg(dres+2, t_VECSMALL); GEN y = cgetg(dres+2, t_VECSMALL); /* 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++) { x[++i] = n; y[i] = Flx_FlxY_eval_resultant(a,b, x[i], p,pi,la); x[++i] = p-n; y[i] = Flx_FlxY_eval_resultant(a,b, x[i], p,pi,la); } if (i == dres) { x[++i] = 0; y[i] = Flx_FlxY_eval_resultant(a,b, x[i], p,pi,la); } return Flv_polint(x,y, p, sx); } static GEN FlxX_pseudorem(GEN x, GEN y, ulong p, ulong pi) { long vx = varn(x), dx, dy, dz, i, lx, dp; pari_sp av = avma, av2; if (!signe(y)) pari_err_INV("FlxX_pseudorem",y); (void)new_chunk(2); dx=degpol(x); x = RgX_recip_i(x)+2; dy=degpol(y); y = RgX_recip_i(y)+2; dz=dx-dy; dp = dz+1; av2 = avma; for (;;) { gel(x,0) = Flx_neg(gel(x,0), p); dp--; for (i=1; i<=dy; i++) gel(x,i) = Flx_add( Flx_mul_pre(gel(y,0), gel(x,i), p, pi), Flx_mul_pre(gel(x,0), gel(y,i), p, pi), p ); for ( ; i<=dx; i++) gel(x,i) = Flx_mul_pre(gel(y,0), gel(x,i), p, pi); do { x++; dx--; } while (dx >= 0 && lg(gel(x,0))==2); if (dx < dy) break; if (gc_needed(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_i(x); if (dp) { /* multiply by y[0]^dp [beware dummy vars from FpX_FpXY_resultant] */ GEN t = Flx_powu_pre(gel(y,0), dp, p, pi); for (i=2; i1) pari_warn(warnmem,"FlxX_resultant, dr = %ld",dr); gerepileall(av2,4, &u, &v, &g, &h); } } z = gel(v,2); if (dv > 1) z = Flx_div_pre(Flx_powu_pre(z,dv,p,pi), Flx_powu_pre(h,dv-1,p,pi), p, pi); 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= p) z = FlxX_resultant(Fly_to_FlxY(a, sy), b, p, sx); else { ulong pi = SMALL_ULONG(p)? 0: get_Fl_red(p); z = Flx_FlxY_resultant_polint(a, b, p, pi, (ulong)dres, sy); } return gerepileupto(ltop,z); } /* return a t_POL (in variable v >= 0) whose coeffs are the coeffs of b, * in variable v. This is an incorrect PARI object if initially varn(b) << v. * We could return a vector of coeffs, but it is convenient to have degpol() * and friends available. Even in that case, it will behave nicely with all * functions treating a polynomial as a vector of coeffs (eg poleval). * FOR INTERNAL USE! */ GEN swap_vars(GEN b0, long v) { long i, n = RgX_degree(b0, v); GEN b, x; if (n < 0) return pol_0(v); b = cgetg(n+3, t_POL); x = b + 2; b[1] = evalsigne(1) | evalvarn(v); for (i=0; i<=n; i++) gel(x,i) = polcoef_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, db, vY = varn(b), vX = varn(a); GEN la,x,y; if (lgefint(p) == 3) { ulong pp = uel(p,2); b = ZXX_to_FlxX(b, pp, vX); a = ZX_to_Flx(a, pp); x = Flx_FlxY_resultant(a, b, pp); return Flx_to_ZX(x); } db = RgXY_degreex(b); dres = degpol(a)*degpol(b); la = leading_coeff(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,db,vY); gel(x,++i) = subiu(p,n); gel(y,i) = FpX_FpXY_eval_resultant(a,b,gel(x,i),p,la,db,vY); } if (i == dres) { gel(x,++i) = gen_0; gel(y,i) = FpX_FpXY_eval_resultant(a,b, gel(x,i), p,la,db,vY); } return FpV_polint(x,y, p, vY); } GEN FpX_composedsum(GEN P, GEN Q, GEN p) { pari_sp av = avma; if (lgefint(p)==3) { ulong pp = p[2]; GEN z = Flx_composedsum(ZX_to_Flx(P, pp), ZX_to_Flx(Q, pp), pp); return gerepileupto(av, Flx_to_ZX(z)); } else { long n = 1+ degpol(P)*degpol(Q); GEN Pl = FpX_invLaplace(FpX_Newton(P,n,p), p); GEN Ql = FpX_invLaplace(FpX_Newton(Q,n,p), p); GEN L = FpX_Laplace(FpXn_mul(Pl, Ql, n, p), p); GEN lead = Fp_mul(Fp_powu(leading_coeff(P),degpol(Q), p), Fp_powu(leading_coeff(Q),degpol(P), p), p); GEN R = FpX_fromNewton(L, p); return gerepileupto(av, FpX_Fp_mul(R, lead, p)); } } GEN FpX_composedprod(GEN P, GEN Q, GEN p) { pari_sp av = avma; if (lgefint(p)==3) { ulong pp = p[2]; GEN z = Flx_composedprod(ZX_to_Flx(P, pp), ZX_to_Flx(Q, pp), pp); return gerepileupto(av, Flx_to_ZX(z)); } else { long n = 1+ degpol(P)*degpol(Q); GEN L = FpX_convol(FpX_Newton(P,n,p), FpX_Newton(Q,n,p), p); return gerepileupto(av,FpX_fromNewton(L, p)); } } static GEN _FpX_composedsum(void *E, GEN a, GEN b) { return FpX_composedsum(a,b, (GEN)E); } GEN FpXV_composedsum(GEN V, GEN p) { if (lgefint(p)==3) { ulong pp = p[2]; return Flx_to_ZX(FlxV_composedsum(ZXV_to_FlxV(V, pp), pp)); } return gen_product(V, (void *)p, &_FpX_composedsum); } /* 0, 1, -1, 2, -2, ... */ #define next_lambda(a) (a>0 ? -a : 1-a) /* Assume A in Z[Y], B in Q[Y][X], B squarefree in (Q[Y]/(A))[X] and * Res_Y(A, B) in Z[X]. Find a small lambda (start from *lambda, use * next_lambda successively) such that C(X) = Res_Y(A(Y), B(X + lambda Y)) * is squarefree, reset *lambda to the chosen value and return C. Set LERS to * the Last nonconstant polynomial in the Euclidean Remainder Sequence */ static GEN ZX_ZXY_resultant_LERS(GEN A, GEN B0, long *plambda, GEN *LERS) { ulong bound, dp; pari_sp av = avma, av2 = 0; long lambda = *plambda, degA = degpol(A), dres = degA*degpol(B0); long stable, checksqfree, i,n, cnt, degB; long v, vX = varn(B0), vY = varn(A); /* vY < vX */ GEN x, y, dglist, B, q, a, b, ev, H, H0, H1, Hp, H0p, H1p, C0, C1; forprime_t S; if (degA == 1) { GEN a1 = gel(A,3), a0 = gel(A,2); B = lambda? RgX_translate(B0, monomial(stoi(lambda), 1, vY)): B0; H = gsubst(B, vY, gdiv(gneg(a0),a1)); if (!equali1(a1)) H = RgX_Rg_mul(H, powiu(a1, poldegree(B,vY))); *LERS = mkvec2(scalarpol_shallow(a0,vX), scalarpol_shallow(a1,vX)); return gc_all(av, 2, &H, LERS); } dglist = Hp = H0p = H1p = C0 = C1 = NULL; /* gcc -Wall */ 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); B0 = leafcopy(B0); A = leafcopy(A); B = B0; v = fetch_var_higher(); setvarn(A,v); /* make sure p large enough */ INIT: /* always except the first time */ if (av2) { set_avma(av2); lambda = next_lambda(lambda); } if (lambda) B = RgX_translate(B0, monomial(stoi(lambda), 1, vY)); B = swap_vars(B, vY); setvarn(B,v); /* B0(lambda v + x, v) */ if (DEBUGLEVEL>4) err_printf("Trying lambda = %ld\n", lambda); av2 = avma; if (degA <= 3) { /* sub-resultant faster for small degrees */ H = RgX_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); if (!ZX_is_squarefree(H)) goto INIT; goto END; } H = H0 = H1 = NULL; degB = degpol(B); bound = ZX_ZXY_ResBound(A, B, NULL); if (DEBUGLEVEL>4) err_printf("bound for resultant coeffs: 2^%ld\n",bound); dp = 1; init_modular_big(&S); for(cnt = 0, checksqfree = 1;;) { ulong p = u_forprime_next(&S); GEN Hi; a = ZX_to_Flx(A, p); b = ZXX_to_FlxX(B, p, varn(A)); if (degpol(a) < degA || degpol(b) < degB) 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) */ } Hi = Flv_Flm_polint(x, mkvec3(y,C0,C1), p, 0); Hp = gel(Hi,1); H0p = gel(Hi,2); H1p = gel(Hi,3); 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); H0= ZX_init_CRT(H0p, p,vX); H1= ZX_init_CRT(H1p, p,vX); } else { GEN qp = muliu(q,p); stable = ZX_incremental_CRT_raw(&H, Hp, q,qp, p) & ZX_incremental_CRT_raw(&H0,H0p, q,qp, p) & ZX_incremental_CRT_raw(&H1,H1p, q,qp, p); q = qp; } /* could make it probabilistic for H ? [e.g if stable twice, etc] * Probabilistic anyway for H0, H1 */ if (DEBUGLEVEL>5 && (stable || ++cnt==100)) { cnt=0; err_printf("%ld%%%s ",100*expi(q)/bound,stable?"s":""); } if (stable && (ulong)expi(q) >= bound) break; /* DONE */ if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"ZX_ZXY_rnfequation"); gerepileall(av2, 4, &H, &q, &H0, &H1); } } END: if (DEBUGLEVEL>5) err_printf(" done\n"); setvarn(H, vX); (void)delete_var(); *LERS = mkvec2(H0,H1); *plambda = lambda; return gc_all(av, 2, &H, LERS); } GEN ZX_ZXY_resultant_all(GEN A, GEN B, long *plambda, GEN *LERS) { if (LERS) { if (!plambda) pari_err_BUG("ZX_ZXY_resultant_all [LERS != NULL needs lambda]"); return ZX_ZXY_resultant_LERS(A, B, plambda, LERS); } return ZX_ZXY_rnfequation(A, B, plambda); } /* 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 = constant_coeff(A); 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 (varncmp(varn(T), 0) <= 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_coeff(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_i(A,T,v): ZXQ_charpoly_sqf(A,T, NULL, v); } GEN QXQ_charpoly(GEN A, GEN T, long v) { pari_sp av = avma; GEN den, B = Q_remove_denom(A, &den); GEN P = ZXQ_charpoly(B, Q_primpart(T), v); return gerepilecopy(av, den ? RgX_rescale(P, ginv(den)): P); } static ulong ZX_resultant_prime(GEN a, GEN b, GEN dB, long degA, long degB, ulong p) { long dropa = degA - degpol(a), dropb = degB - degpol(b); ulong H, dp; if (dropa && dropb) return 0; /* p | lc(A), p | lc(B) */ H = Flx_resultant(a, b, p); if (dropa) { /* multiply by ((-1)^deg B lc(B))^(deg A - deg a) */ ulong c = b[degB+2]; /* lc(B) */ if (odd(degB)) c = p - c; c = Fl_powu(c, dropa, p); if (c != 1) H = Fl_mul(H, c, p); } else if (dropb) { /* multiply by lc(A)^(deg B - deg b) */ ulong c = a[degA+2]; /* lc(A) */ c = Fl_powu(c, dropb, p); if (c != 1) H = Fl_mul(H, c, p); } dp = dB ? umodiu(dB, p): 1; if (dp != 1) H = Fl_mul(H, Fl_powu(Fl_inv(dp,p), degA, p), p); return H; } /* If B=NULL, assume B=A' */ static GEN ZX_resultant_slice(GEN A, GEN B, GEN dB, GEN P, GEN *mod) { pari_sp av = avma, av2; long degA, degB, i, n = lg(P)-1; GEN H, T; degA = degpol(A); degB = B? degpol(B): degA - 1; if (n == 1) { ulong Hp, p = uel(P,1); GEN a = ZX_to_Flx(A, p), b = B? ZX_to_Flx(B, p): Flx_deriv(a, p); Hp = ZX_resultant_prime(a, b, dB, degA, degB, p); set_avma(av); *mod = utoipos(p); return utoi(Hp); } T = ZV_producttree(P); A = ZX_nv_mod_tree(A, P, T); if (B) B = ZX_nv_mod_tree(B, P, T); H = cgetg(n+1, t_VECSMALL); av2 = avma; for(i=1; i <= n; i++, set_avma(av2)) { ulong p = P[i]; GEN a = gel(A,i), b = B? gel(B,i): Flx_deriv(a, p); H[i] = ZX_resultant_prime(a, b, dB, degA, degB, p); } H = ZV_chinese_tree(H, P, T, ZV_chinesetree(P,T)); *mod = gmael(T, lg(T)-1, 1); return gc_all(av, 2, &H, mod); } GEN ZX_resultant_worker(GEN P, GEN A, GEN B, GEN dB) { GEN V = cgetg(3, t_VEC); if (typ(B) == t_INT) B = NULL; if (!signe(dB)) dB = NULL; gel(V,1) = ZX_resultant_slice(A, B, dB, P, &gel(V,2)); return V; } /* Compute Res(A, B/dB) in Z, assuming A,B in Z[X], dB in Z or NULL (= 1) * If B=NULL, take B = A' and assume deg A > 1 and 'bound' is set */ GEN ZX_resultant_all(GEN A, GEN B, GEN dB, ulong bound) { pari_sp av = avma; forprime_t S; GEN H, worker; if (!B && degpol(A)==2) { GEN a = gel(A,4), b = gel(A,3), c = gel(A,2); H = mulii(a, subii(shifti(mulii(a, c), 2), sqri(b))); if (dB) H = diviiexact(H, sqri(dB)); return gerepileuptoint(av, H); } if (B) { long a = degpol(A), b = degpol(B); if (a < 0 || b < 0) return gen_0; if (!a) return powiu(gel(A,2), b); if (!b) return powiu(gel(B,2), a); if (minss(a, b) <= 1) { H = RgX_resultant_all(A, B, NULL); if (dB) H = diviiexact(H, powiu(dB, a)); return gerepileuptoint(av, H); } if (!bound) bound = ZX_ZXY_ResBound(A, B, dB); } worker = snm_closure(is_entry("_ZX_resultant_worker"), mkvec3(A, B? B: gen_0, dB? dB: gen_0)); init_modular_big(&S); H = gen_crt("ZX_resultant_all", worker, &S, dB, bound, 0, NULL, ZV_chinese_center, Fp_center); return gerepileuptoint(av, 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)) { set_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_coeff(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_coeff(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; long s, d = degpol(x); GEN l, R; if (d <= 1) return d == 1? gen_1: gen_0; s = (d & 2) ? -1: 1; l = leading_coeff(x); if (!bound) bound = ZX_discbound(x); R = ZX_resultant_all(x, NULL, 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); } static GEN ZXQX_resultant_prime(GEN a, GEN b, GEN dB, long degA, long degB, GEN T, ulong p) { long dropa = degA - degpol(a), dropb = degB - degpol(b); GEN H, dp; if (dropa && dropb) return pol0_Flx(T[1]); /* p | lc(A), p | lc(B) */ H = FlxqX_saferesultant(a, b, T, p); if (!H) return NULL; if (dropa) { /* multiply by ((-1)^deg B lc(B))^(deg A - deg a) */ GEN c = gel(b,degB+2); /* lc(B) */ if (odd(degB)) c = Flx_neg(c, p); c = Flxq_powu(c, dropa, T, p); if (!Flx_equal1(c)) H = Flxq_mul(H, c, T, p); } else if (dropb) { /* multiply by lc(A)^(deg B - deg b) */ GEN c = gel(a,degA+2); /* lc(A) */ c = Flxq_powu(c, dropb, T, p); if (!Flx_equal1(c)) H = Flxq_mul(H, c, T, p); } dp = dB ? ZX_to_Flx(dB, p): pol1_Flx(T[1]); if (!Flx_equal1(dp)) { GEN idp = Flxq_invsafe(dp, T, p); if (!idp) return NULL; H = Flxq_mul(H, Flxq_powu(idp, degA, T, p), T, p); } return H; } /* If B=NULL, assume B=A' */ static GEN ZXQX_resultant_slice(GEN A, GEN B, GEN U, GEN dB, GEN P, GEN *mod) { pari_sp av = avma; long degA, degB, i, n = lg(P)-1; GEN H, T; long v = varn(U), redo = 0; degA = degpol(A); degB = B? degpol(B): degA - 1; if (n == 1) { ulong p = uel(P,1); GEN a = ZXX_to_FlxX(A, p, v), b = B? ZXX_to_FlxX(B, p, v): FlxX_deriv(a, p); GEN u = ZX_to_Flx(U, p); GEN Hp = ZXQX_resultant_prime(a, b, dB, degA, degB, u, p); if (!Hp) { set_avma(av); *mod = gen_1; return pol_0(v); } Hp = gerepileupto(av, Flx_to_ZX(Hp)); *mod = utoipos(p); return Hp; } T = ZV_producttree(P); A = ZXX_nv_mod_tree(A, P, T, v); if (B) B = ZXX_nv_mod_tree(B, P, T, v); U = ZX_nv_mod_tree(U, P, T); H = cgetg(n+1, t_VEC); for(i=1; i <= n; i++) { ulong p = P[i]; GEN a = gel(A,i), b = B? gel(B,i): FlxX_deriv(a, p), u = gel(U, i); GEN h = ZXQX_resultant_prime(a, b, dB, degA, degB, u, p); if (!h) { gel(H,i) = pol_0(v); P[i] = 1; redo = 1; } else gel(H,i) = h; } if (redo) T = ZV_producttree(P); H = nxV_chinese_center_tree(H, P, T, ZV_chinesetree(P, T)); *mod = gmael(T, lg(T)-1, 1); return gc_all(av, 2, &H, mod); } GEN ZXQX_resultant_worker(GEN P, GEN A, GEN B, GEN T, GEN dB) { GEN V = cgetg(3, t_VEC); if (isintzero(B)) B = NULL; if (!signe(dB)) dB = NULL; gel(V,1) = ZXQX_resultant_slice(A, B, T, dB, P, &gel(V,2)); return V; } static ulong ZXQX_resultant_bound_i(GEN nf, GEN A, GEN B, GEN (*f)(GEN,GEN,long)) { pari_sp av = avma; GEN r, M = nf_L2_bound(nf, NULL, &r); long v = nf_get_varn(nf), i, l = lg(r); GEN a = cgetg(l, t_COL); for (i = 1; i < l; i++) gel(a, i) = f(gsubst(A, v, gel(r,i)), gsubst(B, v, gel(r,i)), DEFAULTPREC); return gc_ulong(av, (ulong) dbllog2(gmul(M,RgC_fpnorml2(a, DEFAULTPREC)))); } static ulong ZXQX_resultant_bound(GEN nf, GEN A, GEN B) { return ZXQX_resultant_bound_i(nf, A, B, &RgX_RgXY_ResBound); } static GEN _ZXQ_powu(GEN x, ulong u, GEN T) { return typ(x) == t_INT? powiu(x, u): ZXQ_powu(x, u, T); } /* Compute Res(A, B/dB) in Z[X]/T, assuming A,B in Z[X,Y], dB in Z or NULL (= 1) * If B=NULL, take B = A' and assume deg A > 1 */ static GEN ZXQX_resultant_all(GEN A, GEN B, GEN T, GEN dB, ulong bound) { pari_sp av = avma; forprime_t S; GEN H, worker; if (B) { long a = degpol(A), b = degpol(B); if (a < 0 || b < 0) return gen_0; if (!a) return _ZXQ_powu(gel(A,2), b, T); if (!b) return _ZXQ_powu(gel(B,2), a, T); } else if (!bound) B = RgX_deriv(A); if (!bound) bound = ZXQX_resultant_bound(nfinit(T, DEFAULTPREC), A, B); worker = snm_closure(is_entry("_ZXQX_resultant_worker"), mkvec4(A, B? B: gen_0, T, dB? dB: gen_0)); init_modular_big(&S); H = gen_crt("ZXQX_resultant_all", worker, &S, dB, bound, 0, NULL, nxV_chinese_center, FpX_center); if (DEBUGLEVEL) err_printf("ZXQX_resultant_all: a priori bound: %lu, a posteriori: %lu\n", bound, expi(gsupnorm(H, DEFAULTPREC))); return gerepileupto(av, H); } GEN nfX_resultant(GEN nf, GEN x, GEN y) { pari_sp av = avma; GEN cx, cy, D, T = nf_get_pol(nf); long dx = degpol(x), dy = degpol(y); if (dx < 0 || dy < 0) return gen_0; x = Q_primitive_part(x, &cx); if (cx) cx = gpowgs(cx, dy); y = Q_primitive_part(y, &cy); if (cy) cy = gpowgs(cy, dx); if (!dx) D = _ZXQ_powu(gel(x,2), dy, T); else if (!dy) D = _ZXQ_powu(gel(y,2), dx, T); else { ulong bound = ZXQX_resultant_bound(nf, x, y); D = ZXQX_resultant_all(x, y, T, NULL, bound); } cx = mul_content(cx, cy); if (cx) D = gmul(D, cx); return gerepileupto(av, D); } static GEN to_ZX(GEN a, long v) { return typ(a)==t_INT? scalarpol(a,v): a; } static GEN ZXQX_disc_all(GEN x, GEN T, ulong bound) { pari_sp av = avma; long s, d = degpol(x), v = varn(T); GEN l, R; if (d <= 1) return d == 1? pol_1(v): pol_0(v); s = (d & 2) ? -1: 1; l = leading_coeff(x); R = ZXQX_resultant_all(x, NULL, T, NULL, bound); if (!gequal1(l)) R = QXQ_div(R, to_ZX(l,v), T); if (s == -1) R = RgX_neg(R); return gerepileupto(av, R); } 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); } GEN nfX_disc(GEN nf, GEN x) { pari_sp av = avma; GEN c, D, T = nf_get_pol(nf); ulong bound; long d = degpol(x), v = varn(T); if (d <= 1) return d == 1? pol_1(v): pol_0(v); x = Q_primitive_part(x, &c); bound = ZXQX_resultant_bound(nf, x, RgX_deriv(x)); D = ZXQX_disc_all(x, T, bound); if (c) D = gmul(D, gpowgs(c, 2*d - 2)); return gerepileupto(av, D); } GEN QXQ_mul(GEN x, GEN y, GEN T) { GEN dx, nx = Q_primitive_part(x, &dx); GEN dy, ny = Q_primitive_part(y, &dy); GEN z = ZXQ_mul(nx, ny, T); if (dx || dy) { GEN d = dx ? dy ? gmul(dx, dy): dx : dy; if (!gequal1(d)) z = ZX_Q_mul(z, d); } return z; } GEN QXQ_sqr(GEN x, GEN T) { GEN dx, nx = Q_primitive_part(x, &dx); GEN z = ZXQ_sqr(nx, T); if (dx) z = ZX_Q_mul(z, gsqr(dx)); return z; } static GEN QXQ_inv_slice(GEN A, GEN B, GEN P, GEN *mod) { pari_sp av = avma; long i, n = lg(P)-1, v = varn(A), redo = 0; GEN H, T; if (n == 1) { ulong p = uel(P,1); GEN a = ZX_to_Flx(A, p), b = ZX_to_Flx(B, p); GEN U = Flxq_invsafe(a, b, p); if (!U) { set_avma(av); *mod = gen_1; return pol_0(v); } H = gerepilecopy(av, Flx_to_ZX(U)); *mod = utoipos(p); return H; } T = ZV_producttree(P); A = ZX_nv_mod_tree(A, P, T); B = ZX_nv_mod_tree(B, P, T); H = cgetg(n+1, t_VEC); for(i=1; i <= n; i++) { ulong p = P[i]; GEN a = gel(A,i), b = gel(B,i); GEN U = Flxq_invsafe(a, b, p); if (!U) { gel(H,i) = pol_0(v); P[i] = 1; redo = 1; } else gel(H,i) = U; } if (redo) T = ZV_producttree(P); H = nxV_chinese_center_tree(H, P, T, ZV_chinesetree(P, T)); *mod = gmael(T, lg(T)-1, 1); return gc_all(av, 2, &H, mod); } GEN QXQ_inv_worker(GEN P, GEN A, GEN B) { GEN V = cgetg(3, t_VEC); gel(V,1) = QXQ_inv_slice(A, B, P, &gel(V,2)); return V; } /* lift(1 / Mod(A,B)). B a ZX, A a scalar or a QX */ GEN QXQ_inv(GEN A, GEN B) { GEN D, Ap, Bp; ulong pp; pari_sp av2, av = avma; forprime_t S; GEN worker, U, H = NULL, mod = gen_1; pari_timer ti; long k, dA, dB; if (is_scalar_t(typ(A))) return scalarpol(ginv(A), varn(B)); /* A a QX, B a ZX */ A = Q_primitive_part(A, &D); dA = degpol(A); dB= degpol(B); /* A, B in Z[X] */ init_modular_small(&S); do { pp = u_forprime_next(&S); Ap = ZX_to_Flx(A, pp); Bp = ZX_to_Flx(B, pp); } while (degpol(Ap) != dA || degpol(Bp) != dB); if (degpol(Flx_gcd(Ap, Bp, pp)) != 0 && degpol(ZX_gcd(A,B))!=0) pari_err_INV("QXQ_inv",mkpolmod(A,B)); worker = snm_closure(is_entry("_QXQ_inv_worker"), mkvec2(A, B)); av2 = avma; for (k = 1; ;k *= 2) { GEN res, b, N, den; gen_inccrt_i("QXQ_inv", worker, NULL, (k+1)>>1, 0, &S, &H, &mod, nxV_chinese_center, FpX_center); gerepileall(av2, 2, &H, &mod); b = sqrti(shifti(mod,-1)); if (DEBUGLEVEL>5) timer_start(&ti); U = FpX_ratlift(H, mod, b, b, NULL); if (DEBUGLEVEL>5) timer_printf(&ti,"QXQ_inv: ratlift"); if (!U) continue; N = Q_remove_denom(U, &den); if (!den) den = gen_1; res = Flx_rem(Flx_Fl_sub(Flx_mul(Ap, ZX_to_Flx(N,pp), pp), umodiu(den, pp), pp), Bp, pp); if (degpol(res) >= 0) continue; res = ZX_Z_sub(ZX_mul(A, N), den); res = ZX_is_monic(B) ? ZX_rem(res, B): RgX_pseudorem(res, B); if (DEBUGLEVEL>5) timer_printf(&ti,"QXQ_inv: final check"); if (degpol(res)<0) { if (D) U = RgX_Rg_div(U, D); return gerepilecopy(av, U); } } } static GEN QXQ_div_slice(GEN A, GEN B, GEN C, GEN P, GEN *mod) { pari_sp av = avma; long i, n = lg(P)-1, v = varn(A), redo = 0; GEN H, T; if (n == 1) { ulong p = uel(P,1); GEN a = ZX_to_Flx(A, p), b = ZX_to_Flx(B, p), c = ZX_to_Flx(C, p); GEN bi = Flxq_invsafe(b, c, p), U; if (!bi) { set_avma(av); *mod = gen_1; return pol_0(v); } U = Flxq_mul(a, bi, c, p); H = gerepilecopy(av, Flx_to_ZX(U)); *mod = utoipos(p); return H; } T = ZV_producttree(P); A = ZX_nv_mod_tree(A, P, T); B = ZX_nv_mod_tree(B, P, T); C = ZX_nv_mod_tree(C, P, T); H = cgetg(n+1, t_VEC); for(i=1; i <= n; i++) { ulong p = P[i]; GEN a = gel(A,i), b = gel(B,i), c = gel(C, i); GEN bi = Flxq_invsafe(b, c, p); if (!bi) { gel(H,i) = pol_0(v); P[i] = 1; redo = 1; } else gel(H,i) = Flxq_mul(a, bi, c, p); } if (redo) T = ZV_producttree(P); H = nxV_chinese_center_tree(H, P, T, ZV_chinesetree(P, T)); *mod = gmael(T, lg(T)-1, 1); return gc_all(av, 2, &H, mod); } GEN QXQ_div_worker(GEN P, GEN A, GEN B, GEN C) { GEN V = cgetg(3, t_VEC); gel(V,1) = QXQ_div_slice(A, B, C, P, &gel(V,2)); return V; } /* lift(Mod(A/B, C)). C a ZX, A, B a scalar or a QX */ GEN QXQ_div(GEN A, GEN B, GEN C) { GEN DA, DB, Ap, Bp, Cp; ulong pp; pari_sp av2, av = avma; forprime_t S; GEN worker, U, H = NULL, mod = gen_1; pari_timer ti; long k, dA, dB, dC; if (is_scalar_t(typ(A))) return scalarpol(ginv(A), varn(B)); /* A a QX, B a ZX */ A = Q_primitive_part(A, &DA); B = Q_primitive_part(B, &DB); dA = degpol(A); dB = degpol(B); dC = degpol(C); /* A, B in Z[X] */ init_modular_small(&S); do { pp = u_forprime_next(&S); Ap = ZX_to_Flx(A, pp); Bp = ZX_to_Flx(B, pp); Cp = ZX_to_Flx(C, pp); } while (degpol(Ap) != dA || degpol(Bp) != dB || degpol(Cp) != dC); if (degpol(Flx_gcd(Bp, Cp, pp)) != 0 && degpol(ZX_gcd(B,C))!=0) pari_err_INV("QXQ_div",mkpolmod(B,C)); worker = snm_closure(is_entry("_QXQ_div_worker"), mkvec3(A, B, C)); av2 = avma; for (k = 1; ;k *= 2) { GEN res, b, N, den; gen_inccrt_i("QXQ_div", worker, NULL, (k+1)>>1, 0, &S, &H, &mod, nxV_chinese_center, FpX_center); gerepileall(av2, 2, &H, &mod); b = sqrti(shifti(mod,-1)); if (DEBUGLEVEL>5) timer_start(&ti); U = FpX_ratlift(H, mod, b, b, NULL); if (DEBUGLEVEL>5) timer_printf(&ti,"QXQ_div: ratlift"); if (!U) continue; N = Q_remove_denom(U, &den); if (!den) den = gen_1; res = Flx_rem(Flx_sub(Flx_mul(Bp, ZX_to_Flx(N,pp), pp), Flx_Fl_mul(Ap, umodiu(den, pp), pp), pp), Cp, pp); if (degpol(res) >= 0) continue; res = ZX_sub(ZX_mul(B, N), ZX_Z_mul(A,den)); res = ZX_is_monic(C) ? ZX_rem(res, C): RgX_pseudorem(res, C); if (DEBUGLEVEL>5) timer_printf(&ti,"QXQ_div: final check"); if (degpol(res)<0) { if (DA && DB) U = RgX_Rg_mul(U, gdiv(DA,DB)); else if (DA) U = RgX_Rg_mul(U, DA); else if (DB) U = RgX_Rg_div(U, DB); return gerepilecopy(av, U); } } } /************************************************************************ * * * ZXQ_minpoly * * * ************************************************************************/ static GEN ZXQ_minpoly_slice(GEN A, GEN B, long d, GEN P, GEN *mod) { pari_sp av = avma; long i, n = lg(P)-1, v = evalvarn(varn(B)); GEN H, T; if (n == 1) { ulong p = uel(P,1); GEN a = ZX_to_Flx(A, p), b = ZX_to_Flx(B, p); GEN Hp = Flxq_minpoly(a, b, p); if (degpol(Hp) != d) { p = 1; Hp = pol0_Flx(v); } H = gerepileupto(av, Flx_to_ZX(Hp)); *mod = utoipos(p); return H; } T = ZV_producttree(P); A = ZX_nv_mod_tree(A, P, T); B = ZX_nv_mod_tree(B, P, T); H = cgetg(n+1, t_VEC); for(i=1; i <= n; i++) { ulong p = P[i]; GEN a = gel(A,i), b = gel(B,i); GEN m = Flxq_minpoly(a, b, p); if (degpol(m) != d) { P[i] = 1; m = pol0_Flx(v); } gel(H, i) = m; } H = nxV_chinese_center_tree(H, P, T, ZV_chinesetree(P, T)); *mod = gmael(T, lg(T)-1, 1); return gc_all(av, 2, &H, mod); } GEN ZXQ_minpoly_worker(GEN P, GEN A, GEN B, long d) { GEN V = cgetg(3, t_VEC); gel(V,1) = ZXQ_minpoly_slice(A, B, d, P, &gel(V,2)); return V; } GEN ZXQ_minpoly(GEN A, GEN B, long d, ulong bound) { pari_sp av = avma; GEN worker, H, dB; forprime_t S; B = Q_remove_denom(B, &dB); worker = strtoclosure("_ZXQ_minpoly_worker", 3, A, B, stoi(d)); init_modular_big(&S); H = gen_crt("ZXQ_minpoly", worker, &S, dB, bound, 0, NULL, nxV_chinese_center, FpX_center_i); return gerepilecopy(av, H); } /************************************************************************ * * * ZX_ZXY_resultant * * * ************************************************************************/ static GEN ZX_ZXY_resultant_prime(GEN a, GEN b, ulong dp, ulong p, long degA, long degB, long dres, long sX) { long dropa = degA - degpol(a), dropb = degB - degpol(b); ulong pi = SMALL_ULONG(p)? 0: get_Fl_red(p); GEN Hp = Flx_FlxY_resultant_polint(a, b, p, pi, 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,degB+2); /* lc(B) */ if (odd(degB)) c = Flx_neg(c, p); if (!Flx_equal1(c)) { c = Flx_powu_pre(c, dropa, p, pi); if (!Flx_equal1(c)) Hp = Flx_mul_pre(Hp, c, p, pi); } } else if (dropb) { /* multiply by lc(A)^(deg B - deg b) */ ulong c = uel(a, degA+2); /* lc(A) */ c = Fl_powu(c, dropb, p); if (c != 1) Hp = Flx_Fl_mul_pre(Hp, c, p, pi); } } if (dp != 1) Hp = Flx_Fl_mul_pre(Hp, Fl_powu_pre(Fl_inv(dp,p), degA, p, pi), p, pi); return Hp; } static GEN ZX_ZXY_resultant_slice(GEN A, GEN B, GEN dB, long degA, long degB, long dres, GEN P, GEN *mod, long sX, long vY) { pari_sp av = avma; long i, n = lg(P)-1; GEN H, T, D; if (n == 1) { ulong p = uel(P,1); ulong dp = dB ? umodiu(dB, p): 1; GEN a = ZX_to_Flx(A, p), b = ZXX_to_FlxX(B, p, vY); GEN Hp = ZX_ZXY_resultant_prime(a, b, dp, p, degA, degB, dres, sX); H = gerepileupto(av, Flx_to_ZX(Hp)); *mod = utoipos(p); return H; } T = ZV_producttree(P); A = ZX_nv_mod_tree(A, P, T); B = ZXX_nv_mod_tree(B, P, T, vY); D = dB ? Z_ZV_mod_tree(dB, P, T): NULL; H = cgetg(n+1, t_VEC); for(i=1; i <= n; i++) { ulong p = P[i]; GEN a = gel(A,i), b = gel(B,i); ulong dp = D ? uel(D, i): 1; gel(H,i) = ZX_ZXY_resultant_prime(a, b, dp, p, degA, degB, dres, sX); } H = nxV_chinese_center_tree(H, P, T, ZV_chinesetree(P, T)); *mod = gmael(T, lg(T)-1, 1); return gc_all(av, 2, &H, mod); } GEN ZX_ZXY_resultant_worker(GEN P, GEN A, GEN B, GEN dB, GEN v) { GEN V = cgetg(3, t_VEC); if (isintzero(dB)) dB = NULL; gel(V,1) = ZX_ZXY_resultant_slice(A, B, dB, v[1], v[2], v[3], P, &gel(V,2), v[4], v[5]); return V; } GEN ZX_ZXY_resultant(GEN A, GEN B) { pari_sp av = avma; forprime_t S; ulong bound; long v = fetch_var_higher(); long degA = degpol(A), degB, dres = degA * degpol(B); long vX = varn(B), vY = varn(A); /* assume vY has lower priority */ long sX = evalvarn(vX); GEN worker, H, dB; B = Q_remove_denom(B, &dB); if (!dB) B = leafcopy(B); A = leafcopy(A); setvarn(A,v); B = swap_vars(B, vY); setvarn(B,v); degB = degpol(B); bound = ZX_ZXY_ResBound(A, B, dB); if (DEBUGLEVEL>4) err_printf("bound for resultant coeffs: 2^%ld\n",bound); worker = snm_closure(is_entry("_ZX_ZXY_resultant_worker"), mkvec4(A, B, dB? dB: gen_0, mkvecsmall5(degA, degB, dres, sX, vY))); init_modular_big(&S); H = gen_crt("ZX_ZXY_resultant_all", worker, &S, dB, bound, 0, NULL, nxV_chinese_center, FpX_center_i); setvarn(H, vX); (void)delete_var(); return gerepilecopy(av, H); } static long ZX_ZXY_rnfequation_lambda(GEN A, GEN B0, long lambda) { pari_sp av = avma; long degA = degpol(A), degB, dres = degA*degpol(B0); long v = fetch_var_higher(); long vX = varn(B0), vY = varn(A); /* assume vY has lower priority */ long sX = evalvarn(vX); GEN dB, B, a, b, Hp; forprime_t S; B0 = Q_remove_denom(B0, &dB); if (!dB) B0 = leafcopy(B0); A = leafcopy(A); B = B0; setvarn(A,v); INIT: if (lambda) B = RgX_translate(B0, monomial(stoi(lambda), 1, vY)); B = swap_vars(B, vY); setvarn(B,v); /* B0(lambda v + x, v) */ if (DEBUGLEVEL>4) err_printf("Trying lambda = %ld\n", lambda); degB = degpol(B); init_modular_big(&S); while (1) { ulong p = u_forprime_next(&S); ulong dp = dB ? umodiu(dB, p): 1; if (!dp) continue; a = ZX_to_Flx(A, p); b = ZXX_to_FlxX(B, p, v); Hp = ZX_ZXY_resultant_prime(a, b, dp, p, degA, degB, dres, sX); if (degpol(Hp) != dres) continue; if (dp != 1) Hp = Flx_Fl_mul(Hp, Fl_powu(Fl_inv(dp,p), degA, p), p); if (!Flx_is_squarefree(Hp, p)) { lambda = next_lambda(lambda); goto INIT; } if (DEBUGLEVEL>4) err_printf("Final lambda = %ld\n", lambda); (void)delete_var(); return gc_long(av,lambda); } } GEN ZX_ZXY_rnfequation(GEN A, GEN B, long *lambda) { if (lambda) { *lambda = ZX_ZXY_rnfequation_lambda(A, B, *lambda); if (*lambda) B = RgX_translate(B, monomial(stoi(*lambda), 1, varn(A))); } return ZX_ZXY_resultant(A,B); } static GEN ZX_composedsum_slice(GEN A, GEN B, GEN P, GEN *mod) { pari_sp av = avma; long i, n = lg(P)-1; GEN H, T; if (n == 1) { ulong p = uel(P,1); GEN a = ZX_to_Flx(A, p), b = ZX_to_Flx(B, p); GEN Hp = Flx_composedsum(a, b, p); H = gerepileupto(av, Flx_to_ZX(Hp)); *mod = utoipos(p); return H; } T = ZV_producttree(P); A = ZX_nv_mod_tree(A, P, T); B = ZX_nv_mod_tree(B, P, T); H = cgetg(n+1, t_VEC); for(i=1; i <= n; i++) { ulong p = P[i]; GEN a = gel(A,i), b = gel(B,i); gel(H,i) = Flx_composedsum(a, b, p); } H = nxV_chinese_center_tree(H, P, T, ZV_chinesetree(P, T)); *mod = gmael(T, lg(T)-1, 1); return gc_all(av, 2, &H, mod); } GEN ZX_composedsum_worker(GEN P, GEN A, GEN B) { GEN V = cgetg(3, t_VEC); gel(V,1) = ZX_composedsum_slice(A, B, P, &gel(V,2)); return V; } static GEN ZX_composedsum_i(GEN A, GEN B, GEN lead) { pari_sp av = avma; forprime_t S; ulong bound; GEN H, worker, mod; if (degpol(A) < degpol(B)) swap(A, B); if (!lead) lead = mulii(leading_coeff(A),leading_coeff(B)); bound = ZX_ZXY_ResBound_1(A, B); worker = snm_closure(is_entry("_ZX_composedsum_worker"), mkvec2(A,B)); init_modular_big(&S); H = gen_crt("ZX_composedsum", worker, &S, lead, bound, 0, &mod, nxV_chinese_center, FpX_center); return gerepileupto(av, H); } static long ZX_compositum_lambda(GEN A, GEN B, GEN lead, long lambda) { pari_sp av = avma; forprime_t S; ulong p; init_modular_big(&S); p = u_forprime_next(&S); while (1) { GEN Hp, a; if (DEBUGLEVEL>4) err_printf("Trying lambda = %ld\n", lambda); if (lead && dvdiu(lead,p)) { p = u_forprime_next(&S); continue; } a = ZX_to_Flx(ZX_rescale(A, stoi(-lambda)), p); Hp = Flx_composedsum(a, ZX_to_Flx(B, p), p); if (!Flx_is_squarefree(Hp, p)) { lambda = next_lambda(lambda); continue; } if (DEBUGLEVEL>4) err_printf("Final lambda = %ld\n", lambda); return gc_long(av, lambda); } } GEN ZX_compositum(GEN A, GEN B, long *lambda) { GEN lead = mulii(leading_coeff(A),leading_coeff(B)); if (lambda) { *lambda = ZX_compositum_lambda(A, B, lead, *lambda); A = ZX_rescale(A, stoi(-*lambda)); } return ZX_composedsum_i(A, B, lead); } GEN ZX_composedsum(GEN A, GEN B) { return ZX_composedsum_i(A, B, NULL); } static GEN ZXQX_composedsum_slice(GEN A, GEN B, GEN C, GEN P, GEN *mod) { pari_sp av = avma; long i, n = lg(P)-1, dC = degpol(C), v = varn(C); GEN H, T; if (n == 1) { ulong p = uel(P,1); GEN a = ZXX_to_FlxX(A, p, v), b = ZXX_to_FlxX(B, p, v); GEN c = ZX_to_Flx(C, p); GEN Hp = FlxX_to_Flm(FlxqX_composedsum(a, b, c, p), dC); H = gerepileupto(av, Flm_to_ZM(Hp)); *mod = utoipos(p); return H; } T = ZV_producttree(P); A = ZXX_nv_mod_tree(A, P, T, v); B = ZXX_nv_mod_tree(B, P, T, v); C = ZX_nv_mod_tree(C, P, T); H = cgetg(n+1, t_VEC); for(i=1; i <= n; i++) { ulong p = P[i]; GEN a = gel(A,i), b = gel(B,i), c = gel(C,i); gel(H,i) = FlxX_to_Flm(FlxqX_composedsum(a, b, c, p), dC); } H = nmV_chinese_center_tree_seq(H, P, T, ZV_chinesetree(P, T)); *mod = gmael(T, lg(T)-1, 1); return gc_all(av, 2, &H, mod); } GEN ZXQX_composedsum_worker(GEN P, GEN A, GEN B, GEN C) { GEN V = cgetg(3, t_VEC); gel(V,1) = ZXQX_composedsum_slice(A, B, C, P, &gel(V,2)); return V; } static GEN ZXQX_composedsum(GEN A, GEN B, GEN T, ulong bound) { pari_sp av = avma; forprime_t S; GEN H, worker, mod; GEN lead = mulii(Q_content(leading_coeff(A)), Q_content(leading_coeff(B))); worker = snm_closure(is_entry("_ZXQX_composedsum_worker") , mkvec3(A,B,T)); init_modular_big(&S); H = gen_crt("ZXQX_composedsum", worker, &S, lead, bound, 0, &mod, nmV_chinese_center, FpM_center); if (DEBUGLEVEL > 4) err_printf("nfcompositum: a priori bound: %lu, a posteriori: %lu\n", bound, expi(gsupnorm(H, DEFAULTPREC))); return gerepilecopy(av, RgM_to_RgXX(H, varn(A), varn(T))); } static long ZXQX_composedsum_bound(GEN nf, GEN A, GEN B) { return ZXQX_resultant_bound_i(nf, A, B, &RgX_RgXY_ResBound_1); } GEN nf_direct_compositum(GEN nf, GEN A, GEN B) { ulong bnd = ZXQX_composedsum_bound(nf, A, B); return ZXQX_composedsum(A, B, nf_get_pol(nf), bnd); } /************************************************************************ * * * 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(pol_xn(n, 0), random_FpX(n-1,0, p)); if (FpX_is_irred(pol, p)) return pol; set_avma(av); } } /* return an extension of degree 2^l of F_2, assume l > 0 * Not stack clean. */ static GEN ffinit_Artin_Schreier_2(long l) { GEN Q, T, S; long i, v; if (l == 1) return mkvecsmall4(0,1,1,1); /*x^2 + x + 1*/ v = fetch_var_higher(); S = mkvecsmall5(0, 0, 0, 1, 1); /* y(y^2 + y) */ Q = mkpoln(3, pol1_Flx(0), pol1_Flx(0), S); /* x^2 + x + y(y^2+y) */ setvarn(Q, v); /* x^4+x+1, irred over F_2, minimal polynomial of a root of Q */ T = mkvecsmalln(6,evalvarn(v),1UL,1UL,0UL,0UL,1UL); /* Q = x^2 + x + a(y) irred. over K = F2[y] / (T(y)) * ==> x^2 + x + a(y) b irred. over K for any root b of Q * ==> x^2 + x + (b^2+b)b */ for (i=2; i 0 * Not stack clean. */ GEN ffinit_Artin_Schreier(ulong p, long l) { long i, v; GEN Q, R, S, T, xp; if (p==2) return ffinit_Artin_Schreier_2(l); xp = polxn_Flx(p,0); /* x^p */ T = Flx_sub(xp, mkvecsmall3(0,1,1),p); /* x^p - x - 1 */ if (l == 1) return T; v = evalvarn(fetch_var_higher()); xp[1] = v; R = Flx_sub(polxn_Flx(2*p-1,0), polxn_Flx(p,0),p); S = Flx_sub(xp, polx_Flx(0), p); Q = FlxX_Flx_sub(Flx_to_FlxX(S, v), R, p); /* x^p - x - (y^(2p-1)-y^p) */ for (i = 2; i <= l; ++i) T = Flx_FlxY_resultant(T, Q, p); (void)delete_var(); T[1] = 0; return T; } static long flinit_check(ulong p, long n, long l) { ulong q; if (!uisprime(n)) return 0; q = p % n; if (!q) return 0; return ugcd((n-1)/Fl_order(q, n-1, n), l) == 1; } static GEN flinit(ulong p, long l) { ulong n = 1+l; while (!flinit_check(p,n,l)) n += l; if (DEBUGLEVEL>=4) err_printf("FFInit: using polsubcyclo(%ld, %ld)\n",n,l); return ZX_to_Flx(polsubcyclo(n,l,0), p); } static GEN ffinit_fact_Flx(ulong p, long n) { GEN P, F = factoru_pow(n), Fp = gel(F,1), Fe = gel(F,2), Fm = gel(F,3); long i, l = lg(Fm); P = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(P,i) = p==uel(Fp,i) ? ffinit_Artin_Schreier(p, Fe[i]) : flinit(p, uel(Fm,i)); return FlxV_composedsum(P, p); } static GEN init_Flxq_i(ulong p, long n, long sv) { GEN P; if (!odd(p) && p != 2) pari_err_PRIME("ffinit", utoi(p)); if (n == 1) return polx_Flx(sv); if (flinit_check(p, n+1, n)) { P = const_vecsmall(n+2,1); P[1] = sv; return P; } P = ffinit_fact_Flx(p,n); P[1] = sv; return P; } GEN init_Flxq(ulong p, long n, long v) { pari_sp av = avma; return gerepileupto(av, init_Flxq_i(p, n, v)); } /* 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 ugcd((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 = factoru_pow(n), Fp = gel(F,1), Fe = gel(F,2), Fm = gel(F,3); long i, l = lg(Fm); P = cgetg(l, t_VEC); for (i = 1; i < l; ++i) gel(P,i) = absequaliu(p, Fp[i]) ? Flx_to_ZX(ffinit_Artin_Schreier(Fp[i], Fe[i])) : fpinit(p, Fm[i]); return FpXV_composedsum(P, p); } static GEN init_Fq_i(GEN p, long n, long v) { GEN P; if (n <= 0) pari_err_DOMAIN("ffinit", "degree", "<=", gen_0, stoi(n)); if (typ(p) != t_INT) pari_err_TYPE("ffinit",p); if (cmpiu(p, 2) < 0) pari_err_PRIME("ffinit",p); if (v < 0) v = 0; if (n == 1) return pol_x(v); if (lgefint(p) == 3) return Flx_to_ZX(init_Flxq_i(p[2], n, evalvarn(v))); if (!mpodd(p)) pari_err_PRIME("ffinit", p); if (fpinit_check(p, n+1, n)) return polcyclo(n+1, v); P = ffinit_fact(p,n); setvarn(P, v); return P; } GEN init_Fq(GEN p, long n, long v) { pari_sp av = avma; return gerepileupto(av, init_Fq_i(p, n, v)); } GEN ffinit(GEN p, long n, long v) { pari_sp av = avma; return gerepileupto(av, FpX_to_mod(init_Fq_i(p, n, v), p)); } GEN ffnbirred(GEN p, long n) { pari_sp av = avma; GEN s = powiu(p,n), F = factoru(n), D = divisorsu_moebius(gel(F, 1)); long j, l = lg(D); for (j = 2; j < l; j++) /* skip d = 1 */ { long md = D[j]; /* mu(d) * d, d squarefree */ GEN pd = powiu(p, n / labs(md)); /* p^{n/d} */ s = md > 0? addii(s, pd): subii(s,pd); } return gerepileuptoint(av, diviuexact(s, n)); } GEN ffsumnbirred(GEN p, long n) { pari_sp av = avma, av2; GEN q, t = p, v = vecfactoru_i(1, n); long i; q = cgetg(n+1,t_VEC); gel(q,1) = p; for (i=2; i<=n; i++) gel(q,i) = mulii(gel(q,i-1), p); av2 = avma; for (i=2; i<=n; i++) { GEN s = gel(q,i), F = gel(v,i), D = divisorsu_moebius(gel(F,1)); long j, l = lg(D); for (j = 2; j < l; j++) /* skip 1 */ { long md = D[j]; GEN pd = gel(q, i / labs(md)); /* p^{i/d} */ s = md > 0? addii(s, pd): subii(s, pd); } t = gerepileuptoint(av2, addii(t, diviuexact(s, i))); } return gerepileuptoint(av, t); } GEN ffnbirred0(GEN p, long n, long flag) { if (typ(p) != t_INT) pari_err_TYPE("ffnbirred", p); if (n <= 0) pari_err_DOMAIN("ffnbirred", "degree", "<=", gen_0, stoi(n)); switch(flag) { case 0: return ffnbirred(p, n); case 1: return ffsumnbirred(p, n); } pari_err_FLAG("ffnbirred"); return NULL; /* LCOV_EXCL_LINE */ } static void checkmap(GEN m, const char *s) { if (typ(m)!=t_VEC || lg(m)!=3 || typ(gel(m,1))!=t_FFELT) pari_err_TYPE(s,m); } GEN ffembed(GEN a, GEN b) { pari_sp av = avma; GEN p, Ta, Tb, g, r = NULL; if (typ(a)!=t_FFELT) pari_err_TYPE("ffembed",a); if (typ(b)!=t_FFELT) pari_err_TYPE("ffembed",b); p = FF_p_i(a); g = FF_gen(a); if (!equalii(p, FF_p_i(b))) pari_err_MODULUS("ffembed",a,b); Ta = FF_mod(a); Tb = FF_mod(b); if (degpol(Tb)%degpol(Ta)!=0) pari_err_DOMAIN("ffembed",GENtostr_raw(a),"is not a subfield of",b,a); r = gel(FFX_roots(Ta, b), 1); return gerepilecopy(av, mkvec2(g,r)); } GEN ffextend(GEN a, GEN P, long v) { pari_sp av = avma; long n; GEN p, T, R, g, m; if (typ(a)!=t_FFELT) pari_err_TYPE("ffextend",a); T = a; p = FF_p_i(a); if (typ(P)!=t_POL || !RgX_is_FpXQX(P,&T,&p)) pari_err_TYPE("ffextend", P); if (!FF_samefield(a, T)) pari_err_MODULUS("ffextend",a,T); if (v < 0) v = varn(P); n = FF_f(T) * degpol(P); R = ffinit(p, n, v); g = ffgen(R, v); m = ffembed(a, g); R = FFX_roots(ffmap(m, P),g); return gerepilecopy(av, mkvec2(gel(R,1), m)); } GEN fffrobenius(GEN a, long n) { if (typ(a)!=t_FFELT) pari_err_TYPE("fffrobenius",a); retmkvec2(FF_gen(a), FF_Frobenius(a, n)); } GEN ffinvmap(GEN m) { pari_sp av = avma; long i, l; GEN T, F, a, g, r, f = NULL; checkmap(m, "ffinvmap"); a = gel(m,1); r = gel(m,2); if (typ(r) != t_FFELT) pari_err_TYPE("ffinvmap", m); g = FF_gen(a); T = FF_mod(r); F = gel(FFX_factor(T, a), 1); l = lg(F); for(i=1; i= 1 && RgX_is_FpXQX(r,&a,&p) && a && typ(a)==t_FFELT) return a; pari_err_TYPE(s, r); return NULL; /* LCOV_EXCL_LINE */ } static GEN ffeltmap_i(GEN m, GEN x) { GEN r = gel(m,2); if (!FF_samefield(x, gel(m,1))) pari_err_DOMAIN("ffmap","m","domain does not contain", x, r); if (typ(r)==t_FFELT) return FF_map(r, x); else return FFX_preimage(x, r, ffpartmapimage("ffmap", r)); } static GEN ffmap_i(GEN m, GEN x) { GEN y; long i, lx, tx = typ(x); switch(tx) { case t_FFELT: return ffeltmap_i(m, x); case t_POL: case t_RFRAC: case t_SER: case t_VEC: case t_COL: case t_MAT: y = cgetg_copy(x, &lx); for (i = 1; i < lontyp[tx]; i++) y[i] = x[i]; for (; i < lx; i++) { GEN yi = ffmap_i(m, gel(x,i)); if (!yi) return NULL; gel(y,i) = yi; } return y; } return gcopy(x); } GEN ffmap(GEN m, GEN x) { pari_sp ltop = avma; GEN y; checkmap(m, "ffmap"); y = ffmap_i(m, x); if (y) return y; set_avma(ltop); return cgetg(1,t_VEC); } static GEN ffeltmaprel_i(GEN m, GEN x) { GEN g = gel(m,1), r = gel(m,2); if (!FF_samefield(x, g)) pari_err_DOMAIN("ffmap","m","domain does not contain", x, r); if (typ(r)==t_FFELT) retmkpolmod(FF_map(r, x), pol_x(FF_var(g))); else retmkpolmod(FFX_preimagerel(x, r, ffpartmapimage("ffmap", r)), gcopy(r)); } static GEN ffmaprel_i(GEN m, GEN x) { GEN y; long i, lx, tx = typ(x); switch(tx) { case t_FFELT: return ffeltmaprel_i(m, x); case t_POL: case t_RFRAC: case t_SER: case t_VEC: case t_COL: case t_MAT: y = cgetg_copy(x, &lx); for (i=1; i 0)? 0: n>>1); return v; } if (!isint1(Q_denom(x))) { set_avma(av); return cgetg(1,t_COL); } } r1 = nf_get_r1(nf); prec = nf_get_prec(nf); for (i = 1;; i++) { GEN rlog; nf = bnf_get_nf(bnf); logunit = bnf_get_logfu(bnf); rlog = real_i(logunit); rx = nflogembed(nf,x,&emb, prec); if (rx) { GEN logN = RgV_sum(rx); /* log(Nx), should be ~ 0 */ if (gexpo(logN) > -20) { /* precision problem ? */ if (typ(logN) != t_REAL) { set_avma(av); return cgetg(1,t_COL); } /*no*/ if (i == 1 && typ(x) != t_MAT && !is_pm1(nfnorm(nf, x))) { set_avma(av); return cgetg(1, t_COL); } } else { ex = RU == 1? cgetg(1,t_COL) : RgM_solve(rlog, rx); /* ~ fundamental units exponents */ if (ex) { ex = grndtoi(ex, &e); if (e < -4) break; } } } if (i == 1) prec = nbits2prec(gexpo(x) + 128); else { if (i > 4) pari_err_PREC("bnfisunit"); prec = precdbl(prec); } if (DEBUGLEVEL) pari_warn(warnprec,"bnfisunit",prec); bnf = bnfnewprec_shallow(bnf, prec); } /* choose a large embedding => small relative error */ for (i = 1; i < RU; i++) if (signe(gel(rx,i)) > -1) break; if (RU == 1) t = gen_0; else { t = imag_i( row_i(logunit,i, 1,RU-1) ); t = RgV_dotproduct(t, ex); if (i > r1) t = gmul2n(t, -1); } if (typ(emb) != t_MAT) arg = garg(gel(emb,i), prec); else { GEN p = gel(emb,1), e = gel(emb,2); long j, l = lg(p); arg = NULL; for (j = 1; j < l; j++) { GEN a = gmul(gel(e,j), garg(gel(gel(p,j),i), prec)); arg = arg? gadd(arg, a): a; } } t = gsub(arg, t); /* = arg(the missing root of 1) */ pi2_sur_w = divru(mppi(prec), n>>1); /* 2pi / n */ e = umodiu(roundr(divrr(t, 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), i), z); GEN p2 = roundr(divrr(garg(ro, prec), pi2_sur_w)); e *= Fl_inv(umodiu(p2,n), n); e %= n; } gel(ex,RU) = utoi(e); setlg(ex, RU+1); return gerepilecopy(av, ex); } /* split M a square ZM in HNF as [H, B; 0, Id], H in HNF without 1-eigenvalue */ static GEN hnfsplit(GEN M, GEN *pB) { long i, l = lg(M); for (i = l-1; i; i--) if (!equali1(gcoeff(M,i,i))) break; if (!i) { *pB = zeromat(0, l-1); return cgetg(1, t_MAT); } *pB = matslice(M, 1, i, i+1, l-1); return matslice(M, 1, i, 1, i); } /* S a list of prime ideal in idealprimedec format. If pH != NULL, set it to * the HNF of the S-class group and return bnfsunit, else return bnfunits */ static GEN bnfsunit_i(GEN bnf, GEN S, GEN *pH, GEN *pA, GEN *pden) { long FLAG, i, lS = lg(S); GEN M, U1, U2, U, V, H, Sunit, B, g; if (!is_vec_t(typ(S))) pari_err_TYPE("bnfsunit",S); bnf = checkbnf(bnf); if (lS == 1) { *pA = cgetg(1,t_MAT); *pden = gen_1; return cgetg(1,t_VEC); } M = cgetg(lS,t_MAT); /* relation matrix for the S class group */ g = cgetg(lS,t_MAT); /* principal part */ FLAG = pH ? 0: nf_GENMAT; for (i = 1; i < lS; i++) { GEN pr = gel(S,i); checkprid(pr); if (pH) gel(M,i) = isprincipal(bnf, pr); else { GEN v = bnfisprincipal0(bnf, pr, FLAG); gel(M,i) = gel(v,1); gel(g,i) = gel(v,2); } } /* S class group and S units, use ZM_hnflll to get small 'U' */ M = shallowconcat(M, diagonal_shallow(bnf_get_cyc(bnf))); H = ZM_hnflll(M, &U, 1); setlg(U, lS); if (pH) *pH = H; U1 = rowslice(U,1, lS-1); U2 = rowslice(U,lS, lg(M)-1); /* (M | cyc) [U1; U2] = 0 */ H = ZM_hnflll(U1, pH? NULL: &V, 0); /* U1 = upper left corner of U, invertible. S * U1 = principal ideals * whose generators generate the S-units */ H = hnfsplit(H, &B); /* [ H B ] [ H^-1 - H^-1 B ] * U1 * V = HNF(U1) = [ 0 Id ], inverse = [ 0 Id ] * S * HNF(U1) = integral generators for S-units = Sunit */ Sunit = cgetg(lS, t_VEC); if (pH) { long nH = lg(H) - 1; FLAG = nf_FORCE | nf_GEN; for (i = 1; i < lS; i++) { GEN C = NULL, E; if (i <= nH) E = gel(H,i); else { C = gel(S,i), E = gel(B,i-nH); } gel(Sunit,i) = gel(isprincipalfact(bnf, C, S, E, FLAG), 2); } } else { GEN cycgen = bnf_build_cycgen(bnf); U1 = ZM_mul(U1, V); U2 = ZM_mul(U2, V); FLAG = nf_FORCE | nf_GENMAT; for (i = 1; i < lS; i++) { GEN a = famatV_factorback(g, gel(U1,i)); GEN b = famatV_factorback(cycgen, ZC_neg(gel(U2,i))); gel(Sunit,i) = famat_reduce(famat_mul(a, b)); } } H = ZM_inv(H, pden); *pA = shallowconcat(H, ZM_neg(ZM_mul(H,B))); /* top inverse * den */ return Sunit; } GEN bnfsunit(GEN bnf,GEN S,long prec) { pari_sp av = avma; long i, l = lg(S); GEN v, R, nf, A, den, U, cl, H = NULL; bnf = checkbnf(bnf); nf = bnf_get_nf(bnf); v = cgetg(7, t_VEC); gel(v,1) = U = bnfsunit_i(bnf, S, &H, &A, &den); gel(v,2) = mkvec2(A, den); gel(v,3) = cgetg(1,t_VEC); /* dummy */ R = bnf_get_reg(bnf); cl = bnf_get_clgp(bnf); if (l != 1) { GEN u,A, G = bnf_get_gen(bnf), D = ZM_snf_group(H,NULL,&u), h = ZV_prod(D); long lD = lg(D); A = cgetg(lD, t_VEC); for(i = 1; i < lD; i++) gel(A,i) = idealfactorback(nf, G, gel(u,i), 1); cl = mkvec3(h, D, A); R = mpmul(R, h); for (i = 1; i < l; i++) { GEN pr = gel(S,i), p = pr_get_p(pr); long f = pr_get_f(pr); R = mpmul(R, logr_abs(itor(p,prec))); if (f != 1) R = mulru(R, f); gel(U,i) = nf_to_scalar_or_alg(nf, gel(U,i)); } } gel(v,4) = R; gel(v,5) = cl; gel(v,6) = S; return gerepilecopy(av, v); } GEN bnfunits(GEN bnf, GEN S) { pari_sp av = avma; GEN A, den, U, fu, tu; bnf = checkbnf(bnf); U = bnfsunit_i(bnf, S? S: cgetg(1,t_VEC), NULL, &A, &den); if (!S) S = cgetg(1,t_VEC); fu = bnf_compactfu(bnf); if (!fu) { long i, l; fu = bnf_has_fu(bnf); if (!fu) bnf_build_units(bnf); fu = shallowcopy(fu); l = lg(fu); for (i = 1; i < l; i++) gel(fu,i) = to_famat_shallow(gel(fu,i),gen_1); } tu = nf_to_scalar_or_basis(bnf_get_nf(bnf), bnf_get_tuU(bnf)); U = shallowconcat(U, vec_append(fu, to_famat_shallow(tu,gen_1))); return gerepilecopy(av, mkvec4(U, S, A, den)); } GEN sunits_mod_units(GEN bnf, GEN S) { pari_sp av = avma; GEN A, den; bnf = checkbnf(bnf); return gerepilecopy(av, bnfsunit_i(bnf, S, NULL, &A, &den)); } /* v_S(x), x in famat form */ static GEN sunit_famat_val(GEN nf, GEN S, GEN x) { long i, l = lg(S); GEN v = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(v,i) = famat_nfvalrem(nf, x, gel(S,i), NULL); return v; } /* v_S(x), x algebraic number */ static GEN sunit_val(GEN nf, GEN S, GEN x, GEN N) { long i, l = lg(S); GEN v = zero_zv(l-1), N0 = N; for (i = 1; i < l; i++) { GEN P = gel(S,i), p = pr_get_p(P); if (dvdii(N, p)) { v[i] = nfval(nf,x,P); (void)Z_pvalrem(N0, p, &N0); } } return is_pm1(N0)? v: NULL; } /* if *px a famat, assume it's an S-unit */ static GEN make_unit(GEN nf, GEN U, GEN *px) { GEN den, v, w, A, gen = gel(U,1), S = gel(U,2), x = *px; long cH, i, l = lg(S); if (l == 1) return cgetg(1, t_COL); A = gel(U,3); den = gel(U,4); cH = nbrows(A); if (typ(x) == t_MAT && lg(x) == 3) { w = sunit_famat_val(nf, S, x); /* x = S v */ v = ZM_ZC_mul(A, w); w += cH; w[0] = evaltyp(t_COL) | _evallg(lg(A) - cH); } else { GEN N; x = nf_to_scalar_or_basis(nf,x); switch(typ(x)) { case t_INT: N = x; if (!signe(N)) return NULL; break; case t_FRAC: N = mulii(gel(x,1),gel(x,2)); break; default: { GEN d = Q_denom(x); N = mulii(idealnorm(nf,gmul(x,d)), d); } } /* relevant primes divide N */ if (is_pm1(N)) return zerocol(l-1); w = sunit_val(nf, S, x, N); if (!w) return NULL; v = ZM_zc_mul(A, w); w += cH; w[0] = evaltyp(t_VECSMALL) | _evallg(lg(A) - cH); w = zc_to_ZC(w); } if (!is_pm1(den)) for (i = 1; i <= cH; i++) { GEN r; gel(v,i) = dvmdii(gel(v,i), den, &r); if (r != gen_0) return NULL; } v = shallowconcat(v, w); /* append bottom of w (= [0 Id] part) */ for (i = 1; i < l; i++) { GEN e = gel(v,i); if (signe(e)) x = famat_mulpow_shallow(x, gel(gen,i), negi(e)); } *px = x; return v; } static GEN bnfissunit_i(GEN bnf, GEN x, GEN U) { GEN w, nf, v = NULL; bnf = checkbnf(bnf); nf = bnf_get_nf(bnf); if ( (w = make_unit(nf, U, &x)) ) v = bnfisunit(bnf, x); if (!v || lg(v) == 1) return NULL; return mkvec2(v, w); } static int checkU(GEN U) { if (typ(U) != t_VEC || lg(U) != 5) return 0; return typ(gel(U,1)) == t_VEC && is_vec_t(typ(gel(U,2))) && typ(gel(U,4))==t_INT; } GEN bnfisunit0(GEN bnf, GEN x, GEN U) { pari_sp av = avma; GEN z; if (!U) return bnfisunit(bnf, x); if (!checkU(U)) pari_err_TYPE("bnfisunit",U); z = bnfissunit_i(bnf, x, U); if (!z) { set_avma(av); return cgetg(1,t_COL); } return gerepilecopy(av, shallowconcat(gel(z,2), gel(z,1))); } /* OBSOLETE */ static int checkbnfS_i(GEN v) { GEN S, g, w; if (typ(v) != t_VEC || lg(v) != 7) return 0; g = gel(v,1); w = gel(v,2); S = gel(v,6); if (typ(g) != t_VEC || !is_vec_t(typ(S)) || lg(S) != lg(g)) return 0; return typ(w) == t_VEC && lg(w) == 3; } /* OBSOLETE */ GEN bnfissunit(GEN bnf, GEN bnfS, GEN x) { pari_sp av = avma; GEN z, U; if (!checkbnfS_i(bnfS)) pari_err_TYPE("bnfissunit",bnfS); U = mkvec4(gel(bnfS,1), gel(bnfS,6), gmael(bnfS,2,1), gmael(bnfS,2,2)); z = bnfissunit_i(bnf, x, U); if (!z) { set_avma(av); return cgetg(1,t_COL); } return gerepilecopy(av, shallowconcat(gel(z,1), gel(z,2))); } pari-2.17.2/src/basemath/elltors.c0000644000175000017500000005275114760123736015412 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /********************************************************************/ /** **/ /** TORSION OF ELLIPTIC CURVES over NUMBER FIELDS **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" static int smaller_x(GEN p, GEN q) { int s = abscmpii(denom_i(p), denom_i(q)); return (s<0 || (s==0 && abscmpii(numer_i(p),numer_i(q)) < 0)); } /* best generator in cycle of length k */ static GEN best_in_cycle(GEN e, GEN p, long k) { GEN p0 = p,q = p; long i; for (i=2; i+i = E_tors, possibly NULL (= oo), p,q independent unless NULL * order p = k, order q = 2 unless NULL */ static GEN tors(GEN e, long k, GEN p, GEN q, GEN v) { GEN r; if (q) { long n = k>>1; GEN p1, best = q, np = ellmul(e,p,utoipos(n)); if (n % 2 && smaller_x(gel(np,1), gel(best,1))) best = np; p1 = elladd(e,q,np); if (smaller_x(gel(p1,1), gel(best,1))) q = p1; else if (best == np) { p = elladd(e,p,q); q = np; } p = best_in_cycle(e,p,k); if (v) { p = ellchangepointinv(p,v); q = ellchangepointinv(q,v); } r = cgetg(4,t_VEC); gel(r,1) = utoipos(2*k); gel(r,2) = mkvec2(utoipos(k), gen_2); gel(r,3) = mkvec2copy(p, q); } else { if (p) { p = best_in_cycle(e,p,k); if (v) p = ellchangepointinv(p,v); r = cgetg(4,t_VEC); gel(r,1) = utoipos(k); gel(r,2) = mkvec( gel(r,1) ); gel(r,3) = mkvec( gcopy(p) ); } else { r = cgetg(4,t_VEC); gel(r,1) = gen_1; gel(r,2) = cgetg(1,t_VEC); gel(r,3) = cgetg(1,t_VEC); } } return r; } /* Finds a multiplicative upper bound for #E_tor (p-Sylow if p != 0); * assume integral model */ static long torsbound(GEN e, ulong p) { GEN D = ell_get_disc(e); pari_sp av = avma, av2; long m, b, bold, nb, CM = ellQ_get_CM(e); forprime_t S; nb = expi(D) >> 3; /* number of primes to try ~ 1 prime every 8 bits in D */ switch (p) { case 0: b = 5040; break; case 2: b = 16; break; case 3: b = 9; break; case 5: case 7: b = p; break; default: return 1; } bold = b; m = 0; /* p > 2 has good reduction => E(Q) injects in E(Fp) */ (void)u_forprime_init(&S, 3, ULONG_MAX); av2 = avma; while (m < nb || (b > 12 && b != 16)) { ulong p = u_forprime_next(&S); if (!p) pari_err_BUG("torsbound [ran out of primes]"); if (!umodiu(D, p)) continue; b = ugcd(b, p+1 - ellap_CM_fast(e,p,CM)); set_avma(av2); if (b == 1) break; if (b == bold) m++; else { bold = b; m = 0; } } return gc_long(av,b); } /* return a rational point of order pk = p^k on E, or NULL if E(Q)[k] = O. * *fk is either NULL (pk = 4 or prime) or elldivpol(p^(k-1)). * Set *fk to elldivpol(p^k) */ static GEN tpoint(GEN E, long pk, GEN *fk) { GEN f = elldivpol(E,pk,0), g = *fk, v; long i, l; *fk = f; if (g) f = RgX_div(f, g); v = nfrootsQ(f); l = lg(v); for (i = 1; i < l; i++) { GEN x = gel(v,i); GEN y = ellordinate(E,x,0); if (lg(y) != 1) return mkvec2(x,gel(y,1)); } return NULL; } /* return E(Q)[2] */ static GEN t2points(GEN E, GEN *f2) { long i, l; GEN v; *f2 = ec_bmodel(E,0); v = nfrootsQ(*f2); l = lg(v); for (i = 1; i < l; i++) { GEN x = gel(v,i); GEN y = ellordinate(E,x,0); if (lg(y) != 1) gel(v,i) = mkvec2(x,gel(y,1)); } return v; } /* psylow = 0 or prime (return p-Sylow subgroup) */ static GEN ellQtors(GEN E, long psylow) { GEN T2 = NULL, p, P, Q, v; long v2, r2, B; E = ellintegralmodel_i(E, &v); B = torsbound(E, psylow); /* #E_tor | B */ if (B == 1) return tors(E,1,NULL,NULL, v); v2 = vals(B); /* bound for v_2(point order) */ B >>= v2; p = const_vec(9, NULL); r2 = 0; if (v2) { GEN f; T2 = t2points(E, &f); switch(lg(T2)-1) { case 0: v2 = 0; break; case 1: r2 = 1; if (v2 == 4) v2 = 3; break; default: r2 = 2; v2--; break; /* 3 */ } if (v2) gel(p,2) = gel(T2,1); /* f = f2 */ if (v2 > 1) { gel(p,4) = tpoint(E,4, &f); if (!gel(p,4)) v2 = 1; } /* if (v2>1) now f = f4 */ if (v2 > 2) { gel(p,8) = tpoint(E,8, &f); if (!gel(p,8)) v2 = 2; } } B <<= v2; if (B % 3 == 0) { GEN f3 = NULL; gel(p,3) = tpoint(E,3,&f3); if (!gel(p,3)) B /= (B%9)? 3: 9; if (gel(p,3) && B % 9 == 0) { gel(p,9) = tpoint(E,9,&f3); if (!gel(p,9)) B /= 3; } } if (B % 5 == 0) { GEN junk = NULL; gel(p,5) = tpoint(E,5,&junk); if (!gel(p,5)) B /= 5; } if (B % 7 == 0) { GEN junk = NULL; gel(p,7) = tpoint(E,7,&junk); if (!gel(p,7)) B /= 7; } /* B is the exponent of E_tors(Q), r2 is the rank of its 2-Sylow, * for i > 1, p[i] is a point of order i if one exists and i is a prime power * and NULL otherwise */ if (r2 == 2) /* 2 cyclic factors */ { /* C2 x C2 */ if (B == 2) return tors(E,2, gel(T2,1), gel(T2,2), v); else if (B == 6) { /* C2 x C6 */ P = elladd(E, gel(p,3), gel(T2,1)); Q = gel(T2,2); } else { /* C2 x C4 or C2 x C8 */ P = gel(p, B); Q = gel(T2,2); if (gequal(Q, ellmul(E, P, utoipos(B>>1)))) Q = gel(T2,1); } } else /* cyclic */ { Q = NULL; if (v2) { if (B>>v2 == 1) P = gel(p, B); else P = elladd(E, gel(p, B>>v2), gel(p,1<> 3); if (g > 20) g = 20; /* P | p such that e(P/p) < p-1 => E(K) injects in E(k(P)) [otherwise * we may lose some p-torsion]*/ (void)u_forprime_init(&S, 3, ULONG_MAX); av = avma; while (k < g) /* k = number of good primes already used */ { ulong p = u_forprime_next(&S); GEN P, gp; long j, l; if (!umodiu(ND,p)) continue; gp = utoipos(p); /* primes of degree 1 are easier and give smaller bounds */ if (typ(D) != t_POLMOD) /* E/Q */ { P = primedec_deg1(K, gp); /* single P|p has all the information */ if (!P) continue; P = mkvec(P); } else P = idealprimedec_limit_f(K, utoipos(p), 1); l = lg(P); for (j = 1; j < l; j++,k++) { GEN Q = gel(P,j), EQ, cyc; long n; if ((ulong)pr_get_e(Q) >= p-1) continue; EQ = ellinit(E,zkmodprinit(K,Q),0); cyc = ellgroup(EQ, NULL); n = lg(cyc)-1; if (n == 0) return mkvec2(gen_1,gen_1); B1 = gcdii(B1,gel(cyc,1)); B2 = (n == 1)? gen_1: gcdii(B2,gel(cyc,2)); obj_free(EQ); /* division by 2 is cheap when it fails, no need to have a sharp bound */ if (psylow==0 && Z_ispow2(B1)) return mkvec2(B1,B2); } if ((g & 15) == 0) gerepileall(av, 2, &B1, &B2); } if (abscmpiu(B2, 2) > 0) { /* if E(K) has full n-torsion then K contains the n-th roots of 1 */ GEN n = gel(nfrootsof1(K), 1); B2 = gcdii(B2,n); } if (psylow) { B1 = powuu(psylow, Z_lval(B1, psylow)); B2 = powuu(psylow, Z_lval(B2, psylow)); } return mkvec2(B1,B2); } /* Checks whether the point P != oo is divisible by n in E(K), where xn is * [phi_n, psi_n^2]. If so, returns a point Q such that nQ = P or -P. * Else, returns NULL */ static GEN ellnfis_divisible_by(GEN E, GEN K, GEN P, GEN xn) { GEN R = nfroots(K, RgX_sub(RgX_Rg_mul(gel(xn,2), gel(P,1)), gel(xn,1))); long i, l = lg(R); for (i = 1; i < l; i++) { GEN x = gel(R,i), y = ellordinate(E,x,0); if (lg(y) != 1) return mkvec2(x, gel(y,1)); } return NULL; } /* Q is not the point at infinity; do we have Q = [n]Q' on curve C/K ? * return P such that [n] P = \pm Q or NULL if none exist */ static GEN ellnfis_divisible_by_i(GEN C, GEN K, GEN Q, GEN n, long v) { GEN xn; if (!isprimepower(absi_shallow(n), NULL)) { GEN f = absZ_factor(n), P = gel(f,1), E = gel(f,2); long i, l = lg(P); for (i = 1; i < l; i++) { GEN q = powii(gel(P,i), gel(E,i)); xn = ellxn(C, itou(q), v); if (!(Q = ellnfis_divisible_by(C, K, Q, xn))) return 0; } return Q; } xn = ellxn(C, itou(n), v); return ellnfis_divisible_by(C, K, Q, xn); } static GEN ellorder_nf(GEN E, GEN P, GEN B); long ellisdivisible(GEN E, GEN Q, GEN n, GEN *pQ) { pari_sp av = avma; GEN P = NULL, N = NULL, K = NULL; long v; checkell(E); checkellpt(Q); switch(ell_get_type(E)) { case t_ELL_Q: break; case t_ELL_NF: K = ellnf_get_nf(E); break; default: pari_err_TYPE("ellisdivisible",E); } if (ell_is_inf(Q)) { if (pQ) *pQ = ellinf(); return 1; } switch(typ(n)) { case t_INT: if (!signe(n)) return 0; if (is_bigint(n)) { /* only possible if P is torsion */ GEN x, o, ex = cyc_get_expo(abgrp_get_cyc(elltors(E))); if (equali1(ex)) return gc_long(av, 0); o = K? ellorder_nf(E, Q, ex): ellorder(E, Q, NULL); if (isintzero(o)) return gc_long(av, 0); x = Z_ppo(n, o); Q = ellmul(E, Q, Fp_inv(x, o)); n = diviiexact(n, x); /* all primes dividing n divide o = ord(Q) | ex */ if (!dvdii(diviiexact(ex,o), n)) return gc_long(av, 0); if (is_bigint(n)) pari_err_IMPL("ellisdivisible for huge torsion"); if (!ellisdivisible(E, Q, n, pQ)) return gc_long(av, 0); if (!pQ) return gc_long(av, 1); *pQ = gerepilecopy(av, *pQ); return 1; } if (!K) { /* could use elltors instead of a multiple ? */ ulong nn = itou(n), n2 = u_ppo(nn, torsbound(E, 0)); if (n2 > 1) { /* n2 coprime to torsion */ if (!(Q = ellQ_isdivisible(E, Q, n2))) return 0; if (signe(n) < 0) Q = ellneg(E, Q); if (nn == n2) { if (pQ) *pQ = Q; return 1; } /* we may have changed n into |n/n2| (and Q in -Q if n < 0) */ n = utoipos(nn/n2); } } v = fetch_var_higher(); P = ellnfis_divisible_by_i(E, K, Q, n, v); delete_var(); N = n; break; case t_VEC: if (lg(n) == 3 && typ(gel(n,1)) == t_POL && typ(gel(n,2)) == t_POL) { /* ellxn */ long d, d2 = degpol(gel(n,1)); if (d2 < 0) return gc_long(av, 0); if (!uissquareall(d2,(ulong*)&d)) pari_err_TYPE("ellisdivisible",n); P = ellnfis_divisible_by(E, K, Q, n); N = utoi(d); break; } /* fall through */ default: pari_err_TYPE("ellisdivisible",n); break; } if (!P) return gc_long(av, 0); if (!pQ) return gc_long(av, 1); if (gequal(Q, ellmul(E, P, N))) P = gerepilecopy(av, P); else P = gerepileupto(av, ellneg(E, P)); *pQ = P; return 1; } /* 2-torsion point of abscissa x */ static GEN tor2(GEN E, GEN x) { return mkvec2(x, gmul2n(gneg(ec_h_evalx(E,x)), -1)); } static GEN ptor0(void) { return mkvec2(mkvec(gen_1),cgetg(1,t_VEC)); } static GEN ptor1(long p, long n, GEN P) { return mkvec2(mkvec(powuu(p,n)), mkvec(P)); } static GEN ptor2(long p, long n1, long n2, GEN P1, GEN P2) { return mkvec2(mkvec2(powuu(p,n1), powuu(p,n2)), mkvec2(P1,P2)); } /* Computes the p-primary torsion in E(K). Assume that p is small, should use * Weil pairing otherwise. * N1, N2 = upper bounds on the integers n1 >= n2 such that * E(K)[p^oo] = Z/p^n1 x Z/p^n2 * Returns [cyc,gen], where E(K)[p^oo] = sum Z/cyc[i] gen[i] */ static GEN ellnftorsprimary(GEN E, long p, long N1, long N2, long v) { GEN X, P1, P2, Q1, Q2, xp, K = ellnf_get_nf(E); long n1, n2; /* compute E[p] = < P1 > or < P1, P2 > */ X = nfroots(K, elldivpol(E,p,v)); if (lg(X) == 1) return ptor0(); P2 = ellinf(); if (p==2) { P1 = tor2(E, gel(X,1)); if (lg(X) > 2) P2 = tor2(E, gel(X,2)); /* E[2] = (Z/2Z)^2 */ } else { long j, l = lg(X), nT, a; GEN T = vectrunc_init(l); for(j=1; j < l; j++) { GEN a = gel(X,j), Y = ellordinate(E,a,0); if (lg(Y) != 1) vectrunc_append(T, mkvec2(a,gel(Y,1))); } nT = lg(T)-1; if (!nT) return ptor0(); P1 = gel(T,1); a = (p-1)/2; if (nT != a) { /* E[p] = (Z/pZ)^2 */ GEN Z = cgetg(a+1,t_VEC), Q1 = P1; long k; gel(Z,1) = Q1; for (k=2; k <= a; k++) gel(Z,k) = elladd(E,Q1,P1); gen_sort_inplace(Z, (void*)&cmp_universal, &cmp_nodata, NULL); while (tablesearch(Z, gel(T,k), &cmp_universal)) k++; P2 = gel(T,k); } } xp = ellxn(E, p, v); if (ell_is_inf(P2)) { /* E[p^oo] is cyclic, start from P1 and divide by p while possible */ for (n1 = 1; n1 < N1; n1++) { GEN Q = ellnfis_divisible_by(E,K,P1,xp); if (!Q) break; P1 = Q; } return ptor1(p, n1, P1); } /* E[p] = (Z/pZ)^2, compute n2 and E[p^n2] */ Q1 = NULL; for (n2 = 1; n2 < N2; n2++) { Q1 = ellnfis_divisible_by(E,K,P1,xp); Q2 = ellnfis_divisible_by(E,K,P2,xp); if (!Q1 || !Q2) break; P1 = Q1; P2 = Q2; } /* compute E[p^oo] = < P1, P2 > */ n1 = n2; if (n2 == N2) { if (N1 == N2) return ptor2(p, n2,n2, P1,P2); Q1 = ellnfis_divisible_by(E,K,P1,xp); } if (Q1) { P1 = Q1; n1++; } else { Q2 = ellnfis_divisible_by(E,K,P2,xp); if (Q2) { P2 = P1; P1 = Q2; n1++; } else { long k; for (k = 1; k < p; k++) { P1 = elladd(E,P1,P2); Q1 = ellnfis_divisible_by(E,K,P1,xp); if (Q1) { P1 = Q1; n1++; break; } } if (k == p) return ptor2(p, n2,n2, P1,P2); } } /* P1,P2 of order p^n1,p^n2 with n1=n2+1. * Keep trying to divide P1 + k P2 with 0 <= k < p by p */ while (n1 < N1) { Q1 = ellnfis_divisible_by(E,K,P1,xp); if (Q1) { P1 = Q1; n1++; } else { long k; for (k = 1; k < p; k++) { P1 = elladd(E,P1,P2); Q1 = ellnfis_divisible_by(E,K,P1,xp); if (Q1) { P1 = Q1; n1++; break; } } if (k == p) break; } } return ptor2(p, n1,n2, P1,P2); } /* P affine point */ static GEN nfpt(GEN e, GEN P) { GEN T = nf_get_pol(ellnf_get_nf(e)); GEN x = gel(P,1), y = gel(P,2); long tx = typ(x), ty = typ(y); if (tx == ty) return P; if (tx != t_POLMOD) x = mkpolmod(x,T); else y = mkpolmod(y,T); return mkvec2(x,y); } /* Computes the torsion subgroup of E(K), as [order, cyc, gen] */ static GEN ellnftors(GEN e, ulong psylow) { GEN B = nftorsbound(e, psylow), B1 = gel(B,1), B2 = gel(B,2), d1,d2, P1,P2; GEN f = Z_factor(B1), P = gel(f,1), E = gel(f,2); long i, l = lg(P), v = fetch_var_higher(); d1 = d2 = gen_1; P1 = P2 = ellinf(); for (i=1; i= n1 */ long N2 = Z_lval(B2,p); /* >= n2 */ GEN T = ellnftorsprimary(e, p, N1, N2, v), cyc = gel(T,1), gen = gel(T,2); if (is_pm1(gel(cyc,1))) continue; /* update generators P1,P2 and their respective orders d1,d2 */ P1 = elladd(e, P1, gel(gen,1)); d1 = mulii(d1, gel(cyc,1)); if (lg(cyc) > 2) { P2 = elladd(e, P2, gel(gen,2)); d2 = mulii(d2, gel(cyc,2)); } } (void)delete_var(); if (is_pm1(d1)) return mkvec3(gen_1,cgetg(1,t_VEC),cgetg(1,t_VEC)); if (is_pm1(d2)) return mkvec3(d1, mkvec(d1), mkvec(nfpt(e,P1))); return mkvec3(mulii(d1,d2), mkvec2(d1,d2), mkvec2(nfpt(e,P1),nfpt(e,P2))); } GEN elltors(GEN e) { pari_sp av = avma; GEN t = NULL; checkell(e); switch(ell_get_type(e)) { case t_ELL_Q: t = ellQtors(e, 0); break; case t_ELL_NF: t = ellnftors(e, 0); break; case t_ELL_Fp: case t_ELL_Fq: return ellgroup0(e,NULL,1); default: pari_err_TYPE("elltors",e); } return gerepilecopy(av, t); } GEN elltors0(GEN e, long flag) { (void)flag; return elltors(e); } GEN elltors_psylow(GEN e, ulong p) { pari_sp av = avma; GEN t = NULL; checkell(e); switch(ell_get_type(e)) { case t_ELL_Q: t = ellQtors(e, p); break; case t_ELL_NF: t = ellnftors(e, p); break; default: pari_err_TYPE("elltors_psylow",e); } return gerepilecopy(av, t); } /********************************************************************/ /** **/ /** ORDER OF POINTS over NUMBER FIELDS **/ /** **/ /********************************************************************/ /* E a t_ELL_Q (use Mazur's theorem) */ long ellorder_Q(GEN E, GEN P) { pari_sp av = avma; GEN dx, dy, d4, d6, D, Pp, Q; forprime_t S; ulong a4, p; long k; if (ell_is_inf(P)) return 1; if (gequal(P, ellneg(E,P))) return 2; dx = Q_denom(gel(P,1)); dy = Q_denom(gel(P,2)); if (ell_is_integral(E)) /* integral model, try Nagell Lutz */ if (abscmpiu(dx, 4) > 0 || abscmpiu(dy, 8) > 0) return 0; d4 = Q_denom(ell_get_c4(E)); d6 = Q_denom(ell_get_c6(E)); D = ell_get_disc (E); /* choose not too small prime p dividing neither a coefficient of the short Weierstrass form nor of P and leading to good reduction */ u_forprime_init(&S, 100003, ULONG_MAX); while ( (p = u_forprime_next(&S)) ) if (umodiu(d4, p) && umodiu(d6, p) && Rg_to_Fl(D, p) && umodiu(dx, p) && umodiu(dy, p)) break; /* transform E into short Weierstrass form Ep modulo p and P to Pp on Ep, * check whether the order of Pp on Ep is <= 12 */ Pp = point_to_a4a6_Fl(E, P, p, &a4); for (Q = Fle_dbl(Pp, a4, p), k = 2; !ell_is_inf(Q) && k <= 12; Q = Fle_add(Q, Pp, a4, p), k++) /* empty */; if (k == 13) k = 0; else { /* check whether [k]P = O over Q. Save potentially costly last elladd */ GEN R; Q = ellmul(E, P, utoipos(k>>1)); R = odd(k)? elladd(E, P,Q): Q; if (!gequal(Q, ellneg(E,R))) k = 0; } return gc_long(av,k); } /* E a t_ELL_NF, B a multiplicative bound for exponent(E_tor) or NULL */ static GEN ellorder_nf(GEN E, GEN P, GEN B) { GEN K = ellnf_get_nf(E); pari_sp av = avma; GEN dx, dy, d4, d6, D, ND, Ep, Pp, Q, gp, modpr, pr, T, k; forprime_t S; ulong a4, p; if (ell_is_inf(P)) return gen_1; if (gequal(P, ellneg(E,P))) return gen_2; if (!B) B = gel(nftorsbound(E, 0), 1); dx = Q_denom(gel(P,1)); dy = Q_denom(gel(P,2)); d4 = Q_denom(ell_get_c4(E)); d6 = Q_denom(ell_get_c6(E)); D = ell_get_disc(E); ND = idealnorm(K,D); if (typ(ND) == t_FRAC) ND = gel(ND,1); /* choose not too small prime p of degree 1 dividing neither a coefficient of * the short Weierstrass form nor of P and leading to good reduction */ u_forprime_init(&S, 100003, ULONG_MAX); while ( (p = u_forprime_next(&S)) ) { if (!umodiu(d4, p) || !umodiu(d6, p) || !umodiu(ND, p) || !umodiu(dx, p) || !umodiu(dy, p)) continue; gp = utoipos(p); pr = primedec_deg1(K, gp); if (pr) break; } modpr = nf_to_Fq_init(K, &pr,&T,&gp); Ep = ellinit(E, pr, 0); Pp = nfV_to_FqV(P, K, modpr); /* transform E into short Weierstrass form Ep modulo p and P to Pp on Ep, * check whether the order of Pp on Ep divides B */ Pp = point_to_a4a6_Fl(Ep, Pp, p, &a4); if (!ell_is_inf(Fle_mul(Pp, B, a4, p))) { set_avma(av); return gen_0; } k = Fle_order(Pp, B, a4, p); { /* check whether [k]P = O over K. Save potentially costly last elladd */ GEN R; Q = ellmul(E, P, shifti(k,-1)); R = mod2(k)? elladd(E, P,Q): Q; if (!gequal(Q, ellneg(E,R))) k = gen_0; } return gerepileuptoint(av, k); } GEN ellorder(GEN E, GEN P, GEN o) { pari_sp av = avma; GEN fg, r, E0 = E; checkell(E); checkellpt(P); if (ell_is_inf(P)) return gen_1; if (ell_get_type(E)==t_ELL_Q) { long tx = typ(gel(P,1)), ty = typ(gel(P,2)); GEN p = NULL; if (is_rational_t(tx) && is_rational_t(ty)) return utoi(ellorder_Q(E, P)); if (tx == t_INTMOD || tx == t_FFELT) p = gel(P,1); if (!p && (ty == t_INTMOD || ty == t_FFELT)) p = gel(P,2); if (p) { E = ellinit(E,p,0); if (lg(E)==1) pari_err_IMPL("ellorder for curve with singular reduction"); } } if (ell_get_type(E)==t_ELL_NF) return ellorder_nf(E, P, NULL); checkell_Fq(E); fg = ellff_get_field(E); if (!o) o = ellff_get_o(E); if (typ(fg)==t_FFELT) r = FF_ellorder(E, P, o); else { GEN p = fg, e = ellff_get_a4a6(E); GEN Pp = FpE_changepointinv(RgE_to_FpE(P,p), gel(e,3), p); r = FpE_order(Pp, o, gel(e,1), p); } if (E != E0) obj_free(E); return gerepileuptoint(av, r); } GEN orderell(GEN e, GEN z) { return ellorder(e,z,NULL); } pari-2.17.2/src/basemath/ellsea.c0000644000175000017500000020430714676526175015201 0ustar billbill/* Copyright (C) 2008 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* This file is a C version by Bill Allombert of the 'ellsea' GP package * whose copyright statement is as follows: Authors: Christophe Doche Sylvain Duquesne Universite Bordeaux I, Laboratoire A2X For the AREHCC project, see http://www.arehcc.com/ Contributors: Karim Belabas (code cleanup and package release, faster polynomial arithmetic) 'ellsea' is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. */ /* Extension to non prime finite fields by Bill Allombert 2012 */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_ellsea static THREAD GEN modular_eqn; void pari_set_seadata(GEN mod) { modular_eqn = mod; } GEN pari_get_seadata(void) { return modular_eqn; } static char * seadata_filename(ulong ell) { return stack_sprintf("%s/seadata/sea%ld", pari_datadir, ell); } static GEN get_seadata(ulong ell) { pari_sp av = avma; GEN eqn; char *s = seadata_filename(ell); pariFILE *F = pari_fopengz(s); if (!F) return NULL; if (ell) /* large single polynomial */ eqn = gp_read_stream(F->file); else { /* table of polynomials of small level */ eqn = gp_readvec_stream(F->file); modular_eqn = eqn = gclone(eqn); set_avma(av); } pari_fclose(F); return eqn; } /*Builds the modular equation corresponding to the vector list. Shallow */ static GEN list_to_pol(GEN list, long vx, long vy) { long i, l = lg(list); GEN P = cgetg(l, t_VEC); for (i = 1; i < l; i++) { GEN L = gel(list,i); if (typ(L) == t_VEC) L = RgV_to_RgX_reverse(L, vy); gel(P, i) = L; } return RgV_to_RgX_reverse(P, vx); } struct meqn { char type; GEN eq, eval; long vx,vy; }; static GEN seadata_cache(ulong ell) { long n = uprimepi(ell)-1; GEN C; if (!modular_eqn && !get_seadata(0)) C = NULL; else if (n && n < lg(modular_eqn)) C = gel(modular_eqn, n); else C = get_seadata(ell); return C; } /* C = [prime level, type "A" or "C", pol. coeffs] */ static void seadata_parse(struct meqn *M, GEN C, long vx, long vy) { M->type = *GSTR(gel(C,2)); M->eq = list_to_pol(gel(C,3), vx, vy); } static void get_modular_eqn(struct meqn *M, ulong ell, long vx, long vy) { GEN C = seadata_cache(ell); M->vx = vx; M->vy = vy; M->eval = gen_0; if (C) seadata_parse(M, C, vx, vy); else { M->type = 'J'; /* j^(1/3) for ell != 3, j for 3 */ M->eq = polmodular_ZXX(ell, ell==3? 0: 5, vx, vy); } } GEN ellmodulareqn(long ell, long vx, long vy) { pari_sp av = avma; struct meqn meqn; GEN C; if (vx < 0) vx = 0; if (vy < 0) vy = 1; if (varncmp(vx,vy) >= 0) pari_err_PRIORITY("ellmodulareqn", pol_x(vx), ">=", vy); if (ell < 2 || !uisprime(ell)) pari_err_PRIME("ellmodulareqn (level)", stoi(ell)); C = seadata_cache(ell); if (!C) pari_err_FILE("seadata file", seadata_filename(ell)); seadata_parse(&meqn, C, vx, vy); return gerepilecopy(av, mkvec2(meqn.eq, meqn.type=='A'? gen_1: gen_0)); } /***********************************************************************/ /** **/ /** FqE_group **/ /** **/ /***********************************************************************/ static GEN Fq_to_Flx(GEN a4, GEN T, ulong p) { return typ(a4)==t_INT ? Z_to_Flx(a4, p, get_Flx_var(T)): ZX_to_Flx(a4, p); } /*FIXME: the name of the function does not quite match what it does*/ static const struct bb_group * get_FqE_group(void ** pt_E, GEN a4, GEN a6, GEN T, GEN p) { if (!T) return get_FpE_group(pt_E,a4,a6,p); else if (lgefint(p)==3) { ulong pp = uel(p,2); GEN Tp = ZXT_to_FlxT(T,pp); return get_FlxqE_group(pt_E, Fq_to_Flx(a4, Tp, pp), Fq_to_Flx(a6, Tp, pp), Tp, pp); } return get_FpXQE_group(pt_E,a4,a6,T,p); } /***********************************************************************/ /** **/ /** Handle curves with CM by small order **/ /** **/ /***********************************************************************/ /* l odd prime. Return the list of discriminants D such that * polclass(D) | poldisc(polmodular(l)) */ static GEN list_singular_discs(long l) { const long _4l2 = 4*l*l; long v; GEN V = zero_F2v(_4l2); /* special cased for efficiency + remove factor l^2 from conductor */ F2v_set(V, 4); /* v = 0 */ F2v_set(V, 3); /* v = l */ for (v = 1; v < 2*l; v++) if (v != l) { /* l does not divide _4l2 - v*v */ GEN F = factoru(_4l2 - v*v), P, E, c; ulong d = coredisc2u_fact(F, -1, &P, &E); long i, lc; c = divisorsu_fact(mkvec2(P,E)); lc = lg(c); for (i = 1; i < lc; i++) F2v_set(V, d * uel(c,i)*uel(c,i)); } return V; } /* l odd prime. Find D such that j has CM by D, assuming * subst(polmodular(l),x,j) has a double root */ static long find_CM(long l, GEN j, GEN T, GEN p) { const long inv = 0; GEN v = list_singular_discs(l); long i, n = v[1]; GEN db = polmodular_db_init(inv); for (i = 1; i < n; i++) if (F2v_coeff(v,i)) { GEN C = polclass0(-i, inv, 0, &db); GEN F = FqX_eval(C, j, T, p); if (signe(F)==0) break; } gunclone_deep(db); return i < n ? -i: 0; } static GEN vecpoints_to_vecx(GEN x, GEN q1) { pari_APPLY_type(t_COL, gadd(q1, signe(gmael(x,i,2)) > 0 ? gmael(x,i,1) : negi(gmael(x,i,1)))); } static GEN Fq_ellcard_CM(long disc, GEN a4, GEN a6, GEN T, GEN p) { const struct bb_group *grp; void *E; long d = T ? degpol(T): 1; GEN q = powiu(p, d), q1 = addiu(q, 1), Q, S; Q = qfbsolve(Qfb0(gen_1,gen_0,stoi(-disc)), mkmat22(gen_2, gen_2, p, utoi(d)), 3); if (lg(Q)==1) return q1; S = vecpoints_to_vecx(Q, q1); grp = get_FqE_group(&E, a4, a6, T, p); return gen_select_order(S, E, grp); } /***********************************************************************/ /** **/ /** n-division polynomial **/ /** **/ /***********************************************************************/ static GEN divpol(GEN t, GEN r2, long n, void *E, const struct bb_algebra *ff); /* f_n^2, return ff->(zero|one) or a clone */ static GEN divpol_f2(GEN t, GEN r2, long n, void *E, const struct bb_algebra *ff) { if (n==0) return ff->zero(E); if (n<=2) return ff->one(E); if (gmael(t,2,n)) return gmael(t,2,n); gmael(t,2,n) = gclone(ff->sqr(E,divpol(t,r2,n,E,ff))); return gmael(t,2,n); } /* f_n f_{n-2}, return ff->zero or a clone */ static GEN divpol_ff(GEN t, GEN r2, long n, void *E, const struct bb_algebra *ff) { if (n<=2) return ff->zero(E); if (gmael(t,3,n)) return gmael(t,3,n); if (n<=4) return divpol(t,r2,n,E,ff); gmael(t,3,n) = gclone(ff->mul(E,divpol(t,r2,n,E,ff), divpol(t,r2,n-2,E,ff))); return gmael(t,3,n); } /* f_n, return ff->zero or a clone */ static GEN divpol(GEN t, GEN r2, long n, void *E, const struct bb_algebra *ff) { long m = n/2; pari_sp av = avma; GEN f; if (n==0) return ff->zero(E); if (gmael(t,1,n)) return gmael(t,1,n); switch(n) { case 1: case 2: f = ff->one(E); break; default: if (odd(n)) if (odd(m)) f = ff->sub(E, ff->mul(E, divpol_ff(t,r2,m+2,E,ff), divpol_f2(t,r2,m,E,ff)), ff->mul(E, r2, ff->mul(E,divpol_ff(t,r2,m+1,E,ff), divpol_f2(t,r2,m+1,E,ff)))); else f = ff->sub(E, ff->mul(E, r2, ff->mul(E, divpol_ff(t,r2,m+2,E,ff), divpol_f2(t,r2,m,E,ff))), ff->mul(E, divpol_ff(t,r2,m+1,E,ff), divpol_f2(t,r2,m+1,E,ff))); else f = ff->sub(E, ff->mul(E, divpol_ff(t,r2,m+2,E,ff), divpol_f2(t,r2,m-1,E,ff)), ff->mul(E, divpol_ff(t,r2,m,E,ff), divpol_f2(t,r2,m+1,E,ff))); } gmael(t,1,n) = f = gclone( ff->red(E, f) ); set_avma(av); return f; } static void divpol_free(GEN t) { long i, l = lg(gel(t,1)); for (i=1; iff = ff; d->E = E; d->t = mkvec3(const_vec(k, NULL),const_vec(k, NULL),const_vec(k, NULL)); if (k>=3) gmael(d->t,1,3) = gclone(D3); if (k>=4) gmael(d->t,1,4) = gclone(D4); d->r2 = ff->sqr(E, RHS); } static void Fq_elldivpolmod_init(struct divpolmod_red *d, GEN a4, GEN a6, long n, GEN h, GEN T, GEN p) { void *E; const struct bb_algebra *ff; GEN RHS, D3 = NULL, D4 = NULL; long v = h ? get_FpXQX_var(h): 0; D3 = n>=0 ? Fq_elldivpol34(3, a4, a6, h, T, p): NULL; D4 = n>=1 ? Fq_elldivpol34(4, a4, a6, h, T, p): NULL; RHS = rhs(a4, a6, v); RHS = h ? FqX_rem(RHS, h, T, p): RHS; RHS = FqX_mulu(RHS, 4, T, p); ff = h ? T ? get_FpXQXQ_algebra(&E, h, T, p): get_FpXQ_algebra(&E, h, p): T ? get_FpXQX_algebra(&E, T, p, v): get_FpX_algebra(&E, p, v); divpolmod_init(d, D3, D4, RHS, n, E, ff); } static void Flxq_elldivpolmod_init(struct divpolmod_red *d, GEN a4, GEN a6, long n, GEN h, GEN T, ulong p) { void *E; const struct bb_algebra *ff; GEN RHS, D3 = NULL, D4 = NULL; long v = get_FlxqX_var(h), vT = get_Flx_var(T); D3 = n>=0 ? Flxq_elldivpol34(3, a4, a6, h, T, p): NULL; D4 = n>=1 ? Flxq_elldivpol34(4, a4, a6, h, T, p): NULL; RHS = FlxX_Fl_mul(FlxqX_rem(Flxq_rhs(a4, a6, v, vT), h, T, p), 4, p); ff = get_FlxqXQ_algebra(&E, h, T, p); divpolmod_init(d, D3, D4, RHS, n, E, ff); } /*Computes the n-division polynomial modulo the polynomial h \in Fq[x] */ GEN Flxq_elldivpolmod(GEN a4, GEN a6, long n, GEN h, GEN T, ulong p) { struct divpolmod_red d; pari_sp ltop = avma; GEN res; Flxq_elldivpolmod_init(&d, a4, a6, n, h, T, p); res = gcopy(divpol(d.t,d.r2,n,d.E,d.ff)); divpol_free(d.t); return gerepileupto(ltop, res); } /*Computes the n-division polynomial modulo the polynomial h \in Fq[x] */ GEN Fq_elldivpolmod(GEN a4, GEN a6, long n, GEN h, GEN T, GEN p) { struct divpolmod_red d; pari_sp ltop = avma; GEN res; if (lgefint(p)==3 && T) { ulong pp = p[2]; GEN a4p = ZX_to_Flx(a4,pp), a6p = ZX_to_Flx(a6,pp); GEN hp = ZXX_to_FlxX(h, pp, get_FpX_var(T)), Tp = ZXT_to_FlxT(T , pp); res = Flxq_elldivpolmod(a4p, a6p, n, hp, Tp, pp); return gerepileupto(ltop, FlxX_to_ZXX(res)); } Fq_elldivpolmod_init(&d, a4, a6, n, h, T, p); res = gcopy(divpol(d.t,d.r2,n,d.E,d.ff)); divpol_free(d.t); return gerepileupto(ltop, res); } GEN FpXQ_elldivpol(GEN a4, GEN a6, long n, GEN T, GEN p) { return Fq_elldivpolmod(a4,a6,n,NULL,T,p); } GEN Fp_elldivpol(GEN a4, GEN a6, long n, GEN p) { return Fq_elldivpolmod(a4,a6,n,NULL,NULL,p); } static GEN Fq_ellyn(struct divpolmod_red *d, long k) { pari_sp av = avma; void *E = d->E; const struct bb_algebra *ff = d->ff; if (k==1) return mkvec2(ff->one(E), ff->one(E)); else { GEN t = d->t, r2 = d->r2; GEN pn2 = divpol(t,r2,k-2,E,ff); GEN pp2 = divpol(t,r2,k+2,E,ff); GEN pn12 = divpol_f2(t,r2,k-1,E,ff); GEN pp12 = divpol_f2(t,r2,k+1,E,ff); GEN on = ff->red(E,ff->sub(E, ff->mul(E,pp2,pn12), ff->mul(E,pn2,pp12))); GEN f = divpol(t,r2,k,E,ff); GEN f2 = divpol_f2(t,r2,k,E,ff); GEN f3 = ff->mul(E,f,f2); if (!odd(k)) f3 = ff->mul(E,f3,r2); return gerepilecopy(av,mkvec2(on, f3)); } } static void Fq_elldivpolmod_close(struct divpolmod_red *d) { divpol_free(d->t); } static GEN Fq_elldivpol2(GEN a4, GEN a6, GEN T, GEN p) { return mkpoln(4, utoi(4), gen_0, Fq_mulu(a4, 4, T, p), Fq_mulu(a6, 4, T, p)); } static GEN Fq_elldivpol2d(GEN a4, GEN T, GEN p) { return mkpoln(3, utoi(6), gen_0, Fq_mulu(a4, 2, T, p)); } static GEN FqX_numer_isog_abscissa(GEN h, GEN a4, GEN a6, GEN T, GEN p, long vx) { GEN mp1, dh, ddh, t, u, t1, t2, t3, t4, f0; long m = degpol(h); mp1 = gel(h, m + 1); /* negative of first power sum */ dh = FqX_deriv(h, T, p); ddh = FqX_deriv(dh, T, p); t = Fq_elldivpol2(a4, a6, T, p); u = Fq_elldivpol2d(a4, T, p); t1 = FqX_sub(FqX_sqr(dh, T, p), FqX_mul(ddh, h, T, p), T, p); t2 = FqX_mul(u, FqX_mul(h, dh, T, p), T, p); t3 = FqX_mul(FqX_sqr(h, T, p), deg1pol_shallow(stoi(2*m), Fq_mulu(mp1, 2, T, p), vx), T, p); f0 = FqX_add(FqX_sub(FqX_mul(t, t1, T, p), t2, T, p), t3, T, p); t4 = FqX_mul(pol_x(vx), FqX_sqr(h, T, p), T, p); return FqX_add(t4, f0, T, p); } static GEN Zq_inv(GEN b, GEN T, GEN p, long e) { return e==1 ? Fq_inv(b, T, p): typ(b)==t_INT ? Zp_inv(b, p, e): ZpXQ_inv(b, T, p, e); } static GEN Zq_div(GEN a, GEN b, GEN T, GEN q, GEN p, long e) { if (e==1) return Fq_div(a, b, T, p); return Fq_mul(a, Zq_inv(b, T, p, e), T, q); } static GEN Zq_sqrt(GEN b, GEN T, GEN p, long e) { return e==1 ? Fq_sqrt(b, T, p): typ(b)==t_INT ? Zp_sqrt(b, p, e): ZpXQ_sqrt(b, T, p, e); } static GEN Zq_divexact(GEN a, GEN b) { return typ(a)==t_INT ? diviiexact(a, b): ZX_Z_divexact(a, b); } static long Zq_pval(GEN a, GEN p) { return typ(a)==t_INT ? Z_pval(a, p): ZX_pval(a, p); } static GEN Zq_divu_safe(GEN a, ulong b, GEN T, GEN q, GEN p, long e) { long v, w; if (e==1) return Fq_div(a, utoi(b), T, q); v = u_pvalrem(b, p, &b); if (v > 0) { if (signe(a)==0) return gen_0; w = Zq_pval(a, p); if (v > w) return NULL; a = Zq_divexact(a, powiu(p,v)); } return Fq_Fp_mul(a, Fp_inv(utoi(b), q), T, q); } static GEN FqX_shift(GEN P,long n) { return RgX_shift_shallow(P, n); } static GEN FqX_mulhigh_i(GEN f, GEN g, long n, GEN T, GEN p) { return FqX_shift(FqX_mul(f,g,T, p),-n); } static GEN FqX_mulhigh(GEN f, GEN g, long n2, long n, GEN T, GEN p) { GEN F = RgX_blocks(f, n2, 2), fl = gel(F,1), fh = gel(F,2); return FqX_add(FqX_mulhigh_i(fl, g, n2, T, p), FqXn_mul(fh, g, n - n2, T, p), T, p); } static GEN FqX_invlift1(GEN Q, GEN P, long t1, long t2, GEN T, GEN p) { GEN H = FqXn_mul(FqX_mulhigh(Q, P, t1, t2, T, p), Q, t2-t1, T, p); return FqX_sub(Q, FqX_shift(H, t1), T, p); } static GEN FqX_invsqrtlift1(GEN Q, GEN P, long t1, long t2, GEN T, GEN p) { GEN D = FqX_mulhigh(P, FqX_sqr(Q, T, p), t1, t2, T, p); GEN H = FqXn_mul(Q, FqX_halve(D, T, p), t2-t1, T, p); return FqX_sub(Q, FqX_shift(H, t1), T, p); } /* Q(x^2) = intformal(subst(x^N*P,x,x^2)) */ static GEN ZqX_integ2Xn(GEN P, long N, GEN T, GEN p, GEN pp, long e) { long d = degpol(P), v = varn(P); long k; GEN Q; if(d==-1) return pol_0(v); Q = cgetg(d+3,t_POL); Q[1] = evalsigne(1) | evalvarn(v); for (k = 0; k <= d; k++) { GEN q = Zq_divu_safe(gel(P,2+k), 2*(k+N)+1, T, p, pp, e); if (!q) return NULL; gel(Q, 2+k) = q; } return ZXX_renormalize(Q,d+3); } /* solution of G*(S'^2)=(S/x)*(HoS) mod x^m */ static GEN Zq_Weierstrass(GEN a4, GEN a6, GEN b4, GEN b6, long m, GEN T, GEN p, GEN pp, long n) { pari_sp av = avma; long v = 0; ulong mask = quadratic_prec_mask(m); GEN iGdS2 = pol_1(v); GEN G = mkpoln(4, a6, a4, gen_0, gen_1); GEN GdS2 = G, S = pol_x(v), sG = pol_1(v), isG = sG, dS = sG; long N = 1; for (;mask>1;) { GEN S2, HS, K, dK, E; long N2 = N, d; N<<=1; if (mask & 1) N--; mask >>= 1; d = N-N2; S2 = FqX_sqr(S, T, p); HS = FqX_Fq_add(FqX_Fq_mul(S, b6, T, p), b4, T, p); HS = FqX_Fq_add(FqXn_mul(S2, HS, N, T, p), gen_1, T, p); HS = FqXn_mul(HS, FqX_shift(S,-1), N, T, p); sG = FqXn_mul(G, isG, N2, T, p); /* (HS-Gds2)/(Gds2*sG) */ dK = FqXn_mul(FqX_shift(FqX_sub(HS, GdS2, T, p), -N2), FqXn_mul(iGdS2, isG, d, T, p), d, T, p); K = ZqX_integ2Xn(dK, N2, T, p, pp, n); if (!K) return gc_NULL(av); E = FqXn_mul(FqXn_mul(K, sG, d, T, p), dS, d, T, p); S = FqX_add(S, FqX_shift(E, N2+1), T, p); if (mask <= 1) break; isG = FqX_invsqrtlift1(isG, G, N2, N, T, p); dS = FqX_deriv(S, T, p); GdS2 = FqX_mul(G, FqX_sqr(dS, T, p), T, p); iGdS2 = FqX_invlift1(iGdS2, GdS2, N2, N, T, p); } return gerepileupto(av, S); } static GEN ZqXn_WNewton(GEN S, long l, GEN a4, GEN a6, GEN pp1, GEN T, GEN p, GEN pp, long e) { long d = degpol(S); long k; GEN Ge = cgetg(2+d,t_POL); Ge[1] = evalsigne(1); gel(Ge,2) = pp1; if (d >= 2) { GEN g = Zq_divu_safe(Fq_sub(gel(S,4), Fq_mulu(a4,(l-1),T,p),T,p), 6,T,p,pp,e); if (!g) return NULL; gel(Ge, 3) = g; } if (d >= 3) { GEN g = Zq_divu_safe(Fq_sub(Fq_sub(gel(S,5), Fq_mul(a4,Fq_mulu(pp1,6,T,p),T,p),T,p), Fq_mulu(a6,(l-1)*2,T,p),T,p),10,T,p,pp,e); if (!g) return NULL; gel(Ge, 4) = g; } for (k = 4; k <= d; k++) { GEN g = Zq_divu_safe(Fq_sub(Fq_sub(gel(S,4+k-2), Fq_mul(a4,Fq_mulu(gel(Ge,k-1),4*k-6,T,p),T,p),T,p), Fq_mul(a6,Fq_mulu(gel(Ge,k-2),4*k-8,T,p),T,p),T,p), 4*k-2, T, p, pp, e); if (!g) return NULL; gel(Ge, k+1) = g; } return ZXX_renormalize(Ge, 2+d); } /****************************************************************************/ /* SIMPLE ELLIPTIC CURVE OVER Fq */ /****************************************************************************/ static GEN Fq_ellj(GEN a4, GEN a6, GEN T, GEN p) { pari_sp ltop=avma; GEN a43 = Fq_mulu(Fq_powu(a4, 3, T, p), 4, T, p); GEN j = Fq_div(Fq_mulu(a43, 1728, T, p), Fq_add(a43, Fq_mulu(Fq_sqr(a6, T, p), 27, T, p), T, p), T, p); return gerepileupto(ltop, j); } static GEN Zq_ellj(GEN a4, GEN a6, GEN T, GEN p, GEN pp, long e) { pari_sp ltop=avma; GEN a43 = Fq_mulu(Fq_powu(a4, 3, T, p), 4, T, p); GEN j = Zq_div(Fq_mulu(a43, 1728, T, p), Fq_add(a43, Fq_mulu(Fq_sqr(a6, T, p), 27, T, p), T, p), T, p, pp, e); return gerepileupto(ltop, j); } /****************************************************************************/ /* EIGENVALUE */ /****************************************************************************/ static GEN Flxq_find_eigen_Frobenius(GEN a4, GEN a6, GEN h, GEN T, ulong p) { long v = get_FlxqX_var(h), vT = get_Flx_var(T); GEN RHS = FlxqX_rem(Flxq_rhs(a4, a6, v, vT), h, T, p); return FlxqXQ_halfFrobenius(RHS, h, T, p); } static GEN Fq_find_eigen_Frobenius(GEN a4, GEN a6, GEN h, GEN T, GEN p) { long v = T ? get_FpXQX_var(h): get_FpX_var(h); GEN RHS = FqX_rem(rhs(a4, a6, v), h, T, p); return T ? FpXQXQ_halfFrobenius(RHS, h, T, p): FpXQ_pow(RHS, shifti(p, -1), h, p); } /*Finds the eigenvalue of the Frobenius given E, ell odd prime, h factor of the *ell-division polynomial, p and tr the possible values for the trace *(useful for primes with one root)*/ static ulong find_eigen_value_oneroot(GEN a4, GEN a6, ulong ell, GEN tr, GEN h, GEN T, GEN p) { pari_sp ltop = avma; ulong t; struct divpolmod_red d; GEN f, Dy, Gy; h = FqX_get_red(h, T, p); Gy = Fq_find_eigen_Frobenius(a4, a6, h, T, p); t = Fl_div(tr[1], 2, ell); if (t < (ell>>1)) t = ell - t; Fq_elldivpolmod_init(&d, a4, a6, t, h, T, p); f = Fq_ellyn(&d, t); Dy = FqXQ_mul(Gy, gel(f,2), h, T, p); if (!gequal(gel(f,1), Dy)) t = ell-t; Fq_elldivpolmod_close(&d); return gc_ulong(ltop, t); } static ulong Flxq_find_eigen_value_power(GEN a4, GEN a6, ulong ell, long k, ulong lambda, GEN h, GEN T, ulong p) { pari_sp ltop = avma; ulong t, ellk1 = upowuu(ell, k-1), ellk = ell*ellk1; pari_timer ti; struct divpolmod_red d; GEN Gy; timer_start(&ti); h = FlxqX_get_red(h, T, p); Gy = Flxq_find_eigen_Frobenius(a4, a6, h, T, p); if (DEBUGLEVEL>2) err_printf(" (%ld ms)",timer_delay(&ti)); Flxq_elldivpolmod_init(&d, a4, a6, ellk, h, T, p); for (t = lambda; t < ellk; t += ellk1) { GEN f = Fq_ellyn(&d, t); GEN Dr = FlxqXQ_mul(Gy, gel(f,2), h, T, p); if (varn(gel(f,1))!=varn(Dr)) pari_err_BUG("find_eigen_value_power"); if (gequal(gel(f,1), Dr)) break; if (gequal(gel(f,1), FlxX_neg(Dr,p))) { t = ellk-t; break; } } if (DEBUGLEVEL>2) err_printf(" (%ld ms)",timer_delay(&ti)); Fq_elldivpolmod_close(&d); return gc_ulong(ltop, 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 Fq_find_eigen_value_power(GEN a4, GEN a6, ulong ell, long k, ulong lambda, GEN h, GEN T, GEN p) { pari_sp ltop = avma; ulong t, ellk1 = upowuu(ell, k-1), ellk = ell*ellk1; pari_timer ti; struct divpolmod_red d; GEN Gy; timer_start(&ti); h = FqX_get_red(h, T, p); Gy = Fq_find_eigen_Frobenius(a4, a6, h, T, p); if (DEBUGLEVEL>2) err_printf(" (%ld ms)",timer_delay(&ti)); Fq_elldivpolmod_init(&d, a4, a6, ellk, h, T, p); for (t = lambda; t < ellk; t += ellk1) { GEN f = Fq_ellyn(&d, t); GEN Dr = FqXQ_mul(Gy, gel(f,2), h, T, p); if (varn(gel(f,1))!=varn(Dr)) pari_err_BUG("find_eigen_value_power"); if (gequal(gel(f,1), Dr)) break; if (gequal(gel(f,1), FqX_neg(Dr,T,p))) { t = ellk-t; break; } } if (DEBUGLEVEL>2) err_printf(" (%ld ms)",timer_delay(&ti)); Fq_elldivpolmod_close(&d); return gc_ulong(ltop, t); } static ulong find_eigen_value_power(GEN a4, GEN a6, ulong ell, long k, ulong lambda, GEN hq, GEN T, GEN p) { ulong pp = itou_or_0(p); if (pp && T) { GEN a4p = ZX_to_Flx(a4, pp); GEN a6p = ZX_to_Flx(a6, pp); GEN hp = ZXXT_to_FlxXT(hq, pp,varn(a4)); GEN Tp = ZXT_to_FlxT(T, pp); return Flxq_find_eigen_value_power(a4p, a6p, ell, k, lambda, hp, Tp, pp); } return Fq_find_eigen_value_power(a4, a6, ell, k, lambda, hq, T, p); } static GEN find_kernel(GEN a4, GEN a6, long l, GEN b4, GEN b6, GEN pp1, GEN T, GEN p, GEN pp, long e) { GEN Ge, S, Sd; long d = ((l+1)>>1)+1; if(l==3) return deg1pol(gen_1, Fq_neg(pp1, T, p), 0); S = Zq_Weierstrass(a4, a6, b4, b6, d + 1, T, p, pp, e); if (S==NULL) return NULL; S = FqX_shift(S, -1); Sd = FqXn_inv(S, d, T, p); Ge = ZqXn_WNewton(Sd, l, a4, a6, pp1, T, p, pp, e); if (!Ge) return NULL; Ge = FqX_neg(Ge, T, p); Ge = T && lgefint(pp)==3 ? ZlXQXn_expint(Ge, d, T, p, pp[2]) : FqXn_expint(Ge, d, T, p); Ge = RgX_recip(FqX_red(Ge, T, pp)); if (degpol(Ge)==(l-1)>>1) return Ge; return NULL; } static GEN compute_u(GEN gprime, GEN Dxxg, GEN DxJg, GEN DJJg, GEN j, GEN pJ, GEN px, ulong q, GEN E4, GEN E6, GEN T, GEN p, GEN pp, long e) { pari_sp ltop = avma; GEN dxxgj = FqX_eval(Dxxg, j, T, p); GEN dxJgj = FqX_eval(DxJg, j, T, p); GEN dJJgj = FqX_eval(DJJg, j, T, p); GEN E42 = Fq_sqr(E4, T, p), E6ovE4 = Zq_div(E6, E4, T, p, pp, e); GEN a = Fq_mul(gprime, dxxgj, T, p); GEN b = Fq_mul(Fq_mul(Fq_mulu(j,2*q, T, p), dxJgj, T, p), E6ovE4, T, p); GEN c = Fq_mul(Zq_div(Fq_sqr(E6ovE4, T, p), gprime, T, p, pp, e), j, T, p); GEN d = Fq_mul(Fq_mul(c,sqru(q), T, p), Fq_add(pJ, Fq_mul(j, dJJgj, T, p), T, p), T, p); GEN f = Fq_sub(Fq_div(E6ovE4,utoi(3), T, p), Zq_div(E42, Fq_mulu(E6,2,T, p), T, p, pp, e), T, p); GEN g = Fq_sub(Fq_sub(b,a,T,p), d, T, p); return gerepileupto(ltop, Fq_add(Zq_div(g,px,T,p,pp,e), Fq_mulu(f,q,T,p), T, p)); } static void a4a6t(GEN *a4t, GEN *a6t, ulong l, GEN E4t, GEN E6t, GEN T, GEN p) { GEN l2 = modii(sqru(l), p), l4 = Fp_sqr(l2, p), l6 = Fp_mul(l4, l2, p); *a4t = Fq_mul(E4t, Fp_muls(l4, -3, p), T, p); *a6t = Fq_mul(E6t, Fp_muls(l6, -2, p), T, p); } static void a4a6t_from_J(GEN *a4t, GEN *a6t, ulong l, GEN C4t, GEN C6t, GEN T, GEN p) { GEN l2 = modii(sqru(l), p), l4 = Fp_sqr(l2, p), l6 = Fp_mul(l4, l2, p); GEN v = Fp_inv(stoi(-864), p), u = Fp_mulu(v, 18, p); *a4t = Fq_mul(C4t, Fp_mul(u, l4, p), T, p); *a6t = Fq_mul(C6t, Fp_mul(v, l6, p), T, p); } /* Finds the isogenous EC, and the sum of the x-coordinates of the points in * the kernel of the isogeny E -> Eb * E: elliptic curve, ell: a prime, meqn: Atkin modular equation * g: root of meqn defining isogenous curve Eb. */ static GEN find_isogenous_from_Atkin(GEN a4, GEN a6, ulong ell, struct meqn *MEQN, GEN g, GEN T, GEN pp, long e) { pari_sp ltop = avma, btop; GEN meqn = MEQN->eq, meqnx, Dmeqnx, Roots, gprime, u1; long k, vJ = MEQN->vy; GEN p = e==1 ? pp: powiu(pp, e); GEN j = Zq_ellj(a4, a6, T, p, pp, e); GEN E4 = Fq_div(a4, stoi(-3), T, p); GEN E6 = Fq_neg(Fq_halve(a6, T, p), T, p); GEN Dx = RgX_deriv(meqn); GEN DJ = deriv(meqn, vJ); GEN Dxg = FpXY_Fq_evaly(Dx, g, T, p, vJ); GEN px = FqX_eval(Dxg, j, T, p), dx = Fq_mul(px, g, T, p); GEN DJg = FpXY_Fq_evaly(DJ, g, T, p, vJ); GEN pJ = FqX_eval(DJg, j, T, p), dJ = Fq_mul(pJ, j, T, p); GEN Dxx = RgX_deriv(Dx); GEN DxJg = FqX_deriv(Dxg, T, p); GEN Dxxg = FpXY_Fq_evaly(Dxx, g, T, p, vJ); GEN DJJg = FqX_deriv(DJg, T, p); GEN a, b; if (!signe(Fq_red(dJ,T,pp)) || !signe(Fq_red(dx,T,pp))) { if (DEBUGLEVEL>0) err_printf("[A: d%c=0]",signe(dJ)? 'x': 'J'); return gc_NULL(ltop); } a = Fq_mul(dJ, Fq_mul(g, E6, T, p), T, p); b = Fq_mul(E4, dx, T, p); gprime = Zq_div(a, b, T, p, pp, e); u1 = compute_u(gprime, Dxxg, DxJg, DJJg, j, pJ, px, 1, E4, E6, T, p, pp, e); meqnx = FpXY_Fq_evaly(meqn, g, T, p, vJ); Dmeqnx = FqX_deriv(meqnx, T, pp); Roots = FqX_roots(meqnx, T, pp); btop = avma; for (k = lg(Roots)-1; k >= 1; k--, set_avma(btop)) { GEN jt = gel(Roots, k); if (signe(FqX_eval(Dmeqnx, jt, T, pp))==0) continue; if (e > 1) jt = ZqX_liftroot(meqnx, gel(Roots, k), T, pp, e); if (signe(Fq_red(jt, T, pp)) == 0 || signe(Fq_sub(jt, utoi(1728), T, pp)) == 0) { if (DEBUGLEVEL>0) err_printf("[A: jt=%ld]",signe(Fq_red(jt,T,p))? 1728: 0); return gc_NULL(ltop); } else { GEN pxstar = FqX_eval(Dxg, jt, T, p); GEN dxstar = Fq_mul(pxstar, g, T, p); GEN pJstar = FqX_eval(DJg, jt, T, p); GEN dJstar = Fq_mul(Fq_mulu(jt, ell, T, p), pJstar, T, p); GEN u = Fq_mul(Fq_mul(dxstar, dJ, T, p), E6, T, p); GEN v = Fq_mul(Fq_mul(dJstar, dx, T, p), E4, T, p); GEN E4t = Zq_div(Fq_mul(Fq_sqr(u, T, p), jt, T, p), Fq_mul(Fq_sqr(v, T, p), Fq_sub(jt, utoi(1728), T, p), T, p), T, p, pp, e); GEN E6t = Zq_div(Fq_mul(u, E4t, T, p), v, T, p, pp, e); GEN u2 = compute_u(gprime, Dxxg, DxJg, DJJg, jt, pJstar, pxstar, ell, E4t, E6t, T, p, pp, e); GEN pp1 = Fq_mulu(Fq_sub(u1, u2, T, p), 3*ell, T, p); GEN a4t, a6t, h; a4a6t(&a4t, &a6t, ell, E4t, E6t, T, p); h = find_kernel(a4, a6, ell, a4t, a6t, pp1, T, p, pp, e); if (h && signe(Fq_elldivpolmod(a4, a6, ell, h, T, pp))==0) return gerepilecopy(ltop, mkvec3(a4t, a6t, h)); } } pari_err_BUG("find_isogenous_from_Atkin, kernel not found"); return NULL;/*LCOV_EXCL_LINE*/ } /* 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, ulong ell, struct meqn *MEQN, GEN g, GEN T, GEN pp, long e) { pari_sp ltop = avma; GEN meqn = MEQN->eq; long vJ = MEQN->vy; GEN p = e==1 ? pp: powiu(pp, e); GEN h; GEN E4 = Fq_div(a4, stoi(-3), T, p); GEN E6 = Fq_neg(Fq_halve(a6, T, p), T, p); GEN E42 = Fq_sqr(E4, T, p); GEN E43 = Fq_mul(E4, E42, T, p); GEN E62 = Fq_sqr(E6, T, p); GEN delta = Fq_div(Fq_sub(E43, E62, T, p), utoi(1728), T, p); GEN j = Zq_div(E43, delta, T, p, pp, e); GEN Dx = RgX_deriv(meqn); GEN DJ = deriv(meqn, vJ); GEN Dxg = FpXY_Fq_evaly(Dx, g, T, p, vJ); GEN px = FqX_eval(Dxg, j, T, p), dx = Fq_mul(px, g, T, p); GEN DJg = FpXY_Fq_evaly(DJ, g, T, p, vJ); GEN pJ = FqX_eval(DJg, j, T, p), dJ = Fq_mul(j, pJ, T, p); GEN Dxx = RgX_deriv(Dx); GEN DxJg = FqX_deriv(Dxg, T, p); GEN ExJ = FqX_eval(DxJg, j, T, p); ulong tis = ugcd(12, ell-1), is = 12 / tis; GEN itis = Fq_inv(stoi(-tis), T, p); GEN deltal = Fq_div(Fq_mul(delta, Fq_powu(g, tis, T, p), T, p), powuu(ell, 12), T, p); GEN E4l, E6l, a4t, a6t, p_1; if (signe(Fq_red(dx,T, pp))==0) { if (DEBUGLEVEL>0) err_printf("[C: dx=0]"); return gc_NULL(ltop); } if (signe(Fq_red(dJ, T, pp))==0) { GEN jl; if (DEBUGLEVEL>0) err_printf("[C: dJ=0]"); E4l = Fq_div(E4, sqru(ell), T, p); jl = Zq_div(Fq_powu(E4l, 3, T, p), deltal, T, p, pp, e); E6l = Zq_sqrt(Fq_mul(Fq_sub(jl, utoi(1728), T, p), deltal, T, p), T, pp, e); p_1 = gen_0; } else { GEN jl, f, fd, Dgs, Djs, jld; GEN E2s = Zq_div(Fq_mul(Fq_neg(Fq_mulu(E6, 12, T, p), T, p), dJ, T, p), Fq_mul(Fq_mulu(E4, is, T, p), dx, T, p), T, p, pp, e); GEN gd = Fq_mul(Fq_mul(E2s, itis, T, p), g, T, p); GEN jd = Zq_div(Fq_mul(Fq_neg(E42, T, p), E6, T, p), delta, T, p, pp, e); GEN E0b = Zq_div(E6, Fq_mul(E4, E2s, T, p), T, p, pp, e); GEN Dxxgj = FqXY_eval(Dxx, g, j, T, p); GEN Dgd = Fq_add(Fq_mul(gd, px, T, p), Fq_mul(g, Fq_add(Fq_mul(gd, Dxxgj, T, p), Fq_mul(jd, ExJ, T, p), T, p), T, p), T, p); GEN DJgJj = FqX_eval(FqX_deriv(DJg, T, p), j, T, p); GEN Djd = Fq_add(Fq_mul(jd, pJ, T, p), Fq_mul(j, Fq_add(Fq_mul(jd, DJgJj, T, p), Fq_mul(gd, ExJ, T, p), T, p), T, p), T, p); GEN E0bd = Zq_div(Fq_sub(Fq_mul(Dgd, itis, T, p), Fq_mul(E0b, Djd, T, p), T, p), dJ, T, p, pp, e); E4l = Fq_div(Fq_sub(E4, Fq_mul(E2s, Fq_sub(Fq_sub(Fq_add(Zq_div(Fq_mulu(E0bd, 12, T, p), E0b, T, p, pp, e), Zq_div(Fq_mulu(E42, 6, T, p), E6, T, p, pp, e), T, p), Zq_div(Fq_mulu(E6, 4, T, p), E4, T, p, pp, e), T, p), E2s, T, p), T, p), T, p), sqru(ell), T, p); jl = Zq_div(Fq_powu(E4l, 3, T, p), deltal, T, p, pp, e); if (signe(Fq_red(jl,T,pp))==0) { if (DEBUGLEVEL>0) err_printf("[C: jl=0]"); return gc_NULL(ltop); } f = Zq_div(powuu(ell, is), g, T, p, pp, e); fd = Fq_neg(Fq_mul(Fq_mul(E2s, f, T, p), itis, T, p), T, p); Dgs = FqXY_eval(Dx, f, jl, T, p); Djs = FqXY_eval(DJ, f, jl, T, p); jld = Zq_div(Fq_mul(Fq_neg(fd, T, p), Dgs, T, p), Fq_mulu(Djs, ell, T, p), T, p, pp, e); E6l = Zq_div(Fq_mul(Fq_neg(E4l, T, p), jld, T, p), jl, T, p, pp, e); p_1 = Fq_neg(Fq_halve(Fq_mulu(E2s, ell, T, p), T, p),T,p); } a4a6t(&a4t, &a6t, ell, E4l, E6l, T, p); h = find_kernel(a4, a6, ell, a4t, a6t, p_1, T, p, pp, e); if (!h) return NULL; return gerepilecopy(ltop, mkvec3(a4t, a6t, h)); } static GEN corr(GEN c4, GEN c6, GEN T, GEN p, GEN pp, long e) { GEN c46 = Zq_div(Fq_sqr(c4, T, p), c6, T, p, pp, e); GEN c64 = Zq_div(c6, c4, T, p, pp, e); GEN a = Fp_divu(gen_2, 3, p); return Fq_add(Fq_halve(c46, T, p), Fq_mul(a, c64, T, p), T, p); } static GEN RgXY_deflatex(GEN H, long n, long d) { long i, l = lg(H); GEN R = cgetg(l, t_POL); R[1] = H[1]; for(i = 2; i < l; i++) { GEN Hi = gel(H, i); gel(R,i) = typ(Hi)==t_POL? RgX_deflate(RgX_shift_shallow(Hi, d), n): Hi; } return RgX_renormalize_lg(R, l); } static GEN Fq_polmodular_eval(GEN meqn, GEN j, long N, GEN T, GEN p, long vJ) { pari_sp av = avma; GEN R, dR, ddR; long t0 = N%3 == 1 ? 2: 0; long t2 = N%3 == 1 ? 0: 2; if (N == 3) { GEN P = FpXX_red(meqn, p); GEN dP = deriv(P, -1), ddP = deriv(dP, -1); R = FpXY_Fq_evaly(P, j, T, p, vJ); dR = FpXY_Fq_evaly(dP, j, T, p, vJ); ddR = FpXY_Fq_evaly(ddP, j, T, p, vJ); return gerepilecopy(av, mkvec3(R,dR,ddR)); } else { GEN P5 = FpXX_red(meqn, p); GEN H = RgX_splitting(P5, 3); GEN H0 = RgXY_deflatex(gel(H,1), 3, -t0); GEN H1 = RgXY_deflatex(gel(H,2), 3, -1); GEN H2 = RgXY_deflatex(gel(H,3), 3, -t2); GEN h0 = FpXY_Fq_evaly(H0, j, T, p, vJ); GEN h1 = FpXY_Fq_evaly(H1, j, T, p, vJ); GEN h2 = FpXY_Fq_evaly(H2, j, T, p, vJ); GEN dH0 = RgX_deriv(H0); GEN dH1 = RgX_deriv(H1); GEN dH2 = RgX_deriv(H2); GEN ddH0 = RgX_deriv(dH0); GEN ddH1 = RgX_deriv(dH1); GEN ddH2 = RgX_deriv(dH2); GEN d0 = FpXY_Fq_evaly(dH0, j, T, p, vJ); GEN d1 = FpXY_Fq_evaly(dH1, j, T, p, vJ); GEN d2 = FpXY_Fq_evaly(dH2, j, T, p, vJ); GEN dd0 = FpXY_Fq_evaly(ddH0, j, T, p, vJ); GEN dd1 = FpXY_Fq_evaly(ddH1, j, T, p, vJ); GEN dd2 = FpXY_Fq_evaly(ddH2, j, T, p, vJ); GEN h02, h12, h22, h03, h13, h23, h012, dh03, dh13, dh23, dh012; GEN ddh03, ddh13, ddh23, ddh012; GEN R1, dR1, ddR1, ddR2; h02 = FqX_sqr(h0, T, p); h12 = FqX_sqr(h1, T, p); h22 = FqX_sqr(h2, T, p); h03 = FqX_mul(h0, h02, T, p); h13 = FqX_mul(h1, h12, T, p); h23 = FqX_mul(h2, h22, T, p); h012 = FqX_mul(FqX_mul(h0, h1, T, p), h2, T, p); dh03 = FqX_mul(FqX_mulu(d0, 3, T, p), h02, T, p); dh13 = FqX_mul(FqX_mulu(d1, 3, T, p), h12, T, p); dh23 = FqX_mul(FqX_mulu(d2, 3, T, p), h22, T, p); dh012 = FqX_add(FqX_add(FqX_mul(FqX_mul(d0, h1, T, p), h2, T, p), FqX_mul(FqX_mul(h0, d1, T, p), h2, T, p), T, p), FqX_mul(FqX_mul(h0, h1, T, p), d2, T, p), T, p); R1 = FqX_sub(h13, FqX_mulu(h012, 3, T, p), T, p); R = FqX_add(FqX_add(FqX_Fq_mul(RgX_shift_shallow(h23, t2), Fq_sqr(j, T, p), T, p), FqX_Fq_mul(RgX_shift_shallow(R1, 1), j, T, p), T, p), RgX_shift_shallow(h03, t0), T, p); dR1 = FqX_sub(dh13, FqX_mulu(dh012, 3, T, p), T, p); dR = FqX_add(FqX_add(RgX_shift_shallow(FqX_add(FqX_Fq_mul(dh23, Fq_sqr(j, T, p), T, p), FqX_Fq_mul(h23, Fq_mulu(j, 2, T, p), T, p), T, p), t2), RgX_shift_shallow(FqX_add(FqX_Fq_mul(dR1, j, T, p), R1, T, p), 1), T, p), RgX_shift_shallow(dh03, t0), T, p); ddh03 = FqX_mulu(FqX_add(FqX_mul(dd0, h02, T, p), FqX_mul(FqX_mulu(FqX_sqr(d0, T, p), 2, T, p), h0, T, p), T, p), 3, T, p); ddh13 = FqX_mulu(FqX_add(FqX_mul(dd1, h12, T, p), FqX_mul(FqX_mulu(FqX_sqr(d1, T, p), 2, T, p), h1, T, p), T, p), 3, T, p); ddh23 = FqX_mulu(FqX_add(FqX_mul(dd2, h22, T, p), FqX_mul(FqX_mulu(FqX_sqr(d2, T, p), 2, T, p), h2, T, p), T, p), 3, T, p); ddh012 = FqX_add(FqX_add(FqX_add(FqX_mul(FqX_mul(dd0, h1, T, p), h2, T, p), FqX_mul(FqX_mul(h0, dd1, T, p), h2, T, p), T, p), FqX_mul(FqX_mul(h0, h1, T, p), dd2, T, p), T, p), FqX_mulu(FqX_add(FqX_add(FqX_mul(FqX_mul(d0, d1, T, p), h2, T, p), FqX_mul(FqX_mul(d0, h1, T, p), d2, T, p), T, p), FqX_mul(FqX_mul(h0, d1, T, p), d2, T, p), T, p), 2, T, p), T, p); ddR1 = FqX_sub(ddh13, FqX_mulu(ddh012, 3, T, p), T, p); ddR2 = FqX_add(FqX_add(FqX_Fq_mul(ddh23, Fq_sqr(j, T, p), T, p), FqX_Fq_mul(dh23, Fq_mulu(j, 4, T, p), T, p), T, p), FqX_mulu(h23, 2, T, p), T, p); ddR = FqX_add(FqX_add(RgX_shift_shallow(ddR2, t2), RgX_shift_shallow(FqX_add(FqX_mulu(dR1, 2, T, p), FqX_Fq_mul(ddR1, j, T, p), T, p), 1), T, p), RgX_shift_shallow(ddh03, t0), T, p); return gerepilecopy(av, mkvec3(R ,dR ,ddR)); } } static GEN meqn_j(struct meqn *MEQN, GEN j, long ell, GEN T, GEN p) { if (MEQN->type=='J') { MEQN->eval = Fq_polmodular_eval(MEQN->eq, j, ell, T, p, MEQN->vy); return gel(MEQN->eval, 1); } else return FqXY_evalx(MEQN->eq, j, T, p); } static GEN find_isogenous_from_J(GEN a4, GEN a6, ulong ell, struct meqn *MEQN, GEN g, GEN T, GEN pp, long e) { pari_sp ltop = avma; GEN meqn = MEQN->eval; GEN p = e==1 ? pp: powiu(pp, e); GEN h, a4t, a6t; GEN C4, C6, C4t, C6t; GEN j, jp, jtp, jtp2, jtp3; GEN Py, Pxy, Pyy, Pxj, Pyj, Pxxj, Pxyj, Pyyj; GEN s0, s1, s2, s3; GEN den, D, co, cot, c0, p_1; if (signe(g) == 0 || signe(Fq_sub(g, utoi(1728), T, p)) == 0) { if (DEBUGLEVEL>0) err_printf("[J: g=%ld]",signe(g)==0 ?0: 1728); return gc_NULL(ltop); } C4 = Fq_mul(a4, stoi(-48), T, p); C6 = Fq_mul(a6, stoi(-864), T, p); if (signe(C4)==0 || signe(C6)==0) { if (DEBUGLEVEL>0) err_printf("[J: C%ld=0]",signe(C4)==0 ?4: 6); return gc_NULL(ltop); } j = Zq_ellj(a4, a6, T, p, pp, e); jp = Fq_mul(j, Zq_div(C6, C4, T, p, pp, e), T, p); co = corr(C4, C6, T, p, pp, e); Py = RgX_deriv(gel(meqn, 1)); Pxy = RgX_deriv(gel(meqn,2)); Pyy = RgX_deriv(Py); Pxj = FqX_eval(gel(meqn, 2), g, T, p); if (signe(Pxj)==0) { if (DEBUGLEVEL>0) err_printf("[J: Pxj=0]"); return gc_NULL(ltop); } Pyj = FqX_eval(Py, g, T, p); Pxxj = FqX_eval(gel(meqn, 3), g, T, p); Pxyj = FqX_eval(Pxy, g, T, p); Pyyj = FqX_eval(Pyy, g, T, p); jtp = Fq_div(Fq_mul(jp, Zq_div(Pxj, Pyj, T, p, pp, e), T, p), utoineg(ell), T, p); jtp2 = Fq_sqr(jtp,T,p); jtp3 = Fq_mul(jtp,jtp2,T,p); den = Fq_mul(Fq_sqr(g,T,p),Fq_sub(g,utoi(1728),T,p),T, p); D = Zq_inv(den, T, pp, e); C4t = Fq_mul(jtp2,Fq_mul(g, D, T, p), T, p); C6t = Fq_mul(jtp3, D, T, p); s0 = Fq_mul(Fq_sqr(jp, T, p), Pxxj, T, p); s1 = Fq_mul(Fq_mulu(Fq_mul(jp,jtp,T,p),2*ell,T,p), Pxyj, T, p); s2 = Fq_mul(Fq_mulu(jtp2,ell*ell,T,p), Pyyj, T, p); s3 = Zq_div(Fq_add(s0, Fq_add(s1, s2, T, p), T, p),Fq_mul(jp, Pxj, T, p),T,p,pp,e); cot = corr(C4t, C6t, T, p, pp, e); c0 = Fq_sub(co,Fq_mulu(cot,ell,T,p),T,p); p_1 = Fq_div(Fq_mulu(Fq_add(s3, c0, T, p),ell,T,p),stoi(-4),T,p); a4a6t_from_J(&a4t, &a6t, ell, C4t, C6t, T, p); h = find_kernel(a4, a6, ell, a4t, a6t, p_1, T, p, pp, e); if (!h) return NULL; return gerepilecopy(ltop, mkvec3(a4t, a6t, h)); } static GEN find_isogenous(GEN a4,GEN a6, ulong ell, struct meqn *MEQN, GEN g, GEN T,GEN p) { ulong pp = itou_or_0(p); long e = pp ? ulogint(((ell+1)>>1)+1, pp) + ulogint(2*ell+4, pp) + 1: 1; if (signe(a4)==0 || signe(a6)==0) { if (DEBUGLEVEL>0) err_printf("[%c: j=%ld]",MEQN->type,signe(a4)==0 ?0: 1728); return NULL; } if (e > 1) { GEN pe = powiu(p, e); GEN meqnj = meqn_j(MEQN, Zq_ellj(a4, a6, T, pe, p, e), ell, T, pe); g = ZqX_liftroot(meqnj, g, T, p, e); } switch(MEQN->type) { case 'C': return find_isogenous_from_canonical(a4,a6,ell, MEQN, g, T,p,e); case 'A': return find_isogenous_from_Atkin(a4,a6,ell, MEQN, g, T,p,e); default: return find_isogenous_from_J(a4,a6,ell, MEQN, g, T,p,e); } } static GEN FqX_homogenous_eval(GEN P, GEN A, GEN B, GEN T, GEN p) { long d = degpol(P), i, v = varn(A); GEN s = scalar_ZX_shallow(gel(P, d+2), v), Bn = pol_1(v); for (i = d-1; i >= 0; i--) { Bn = FqX_mul(Bn, B, T, p); s = FqX_add(FqX_mul(s, A, T, p), FqX_Fq_mul(Bn, gel(P,i+2), T, p), T, p); } return s; } static GEN FqX_homogenous_div(GEN P, GEN Q, GEN A, GEN B, GEN T, GEN p) { GEN z = cgetg(3, t_RFRAC); long d = degpol(Q)-degpol(P); gel(z, 1) = FqX_homogenous_eval(P, A, B, T, p); gel(z, 2) = FqX_homogenous_eval(Q, A, B, T, p); if (d > 0) gel(z, 1) = FqX_mul(gel(z, 1), FqX_powu(B, d, T, p), T, p); else if (d < 0) gel(z, 2) = FqX_mul(gel(z, 2), FqX_powu(B, -d, T, p), T, p); return z; } static GEN find_kernel_power(GEN Eba4, GEN Eba6, GEN Eca4, GEN Eca6, ulong ell, struct meqn *MEQN, GEN kpoly, GEN Ib, GEN T, GEN p) { pari_sp ltop = avma, btop; GEN a4t, a6t, gtmp; GEN num_iso = FqX_numer_isog_abscissa(kpoly, Eba4, Eba6, T, p, 0); GEN mpoly = meqn_j(MEQN, Fq_ellj(Eca4, Eca6, T, p), ell, T, p); GEN mroots = FqX_roots(mpoly, T, p); GEN kpoly2 = FqX_sqr(kpoly, T, p); long i, l1 = lg(mroots); btop = avma; for (i = 1; i < l1; i++) { GEN h; GEN tmp = find_isogenous(Eca4, Eca6, ell, MEQN, gel(mroots, i), T, p); if (!tmp) return gc_NULL(ltop); a4t = gel(tmp, 1); a6t = gel(tmp, 2); gtmp = gel(tmp, 3); /*check that the kernel kpoly is the good one */ h = FqX_homogenous_eval(gtmp, num_iso, kpoly2, T, p); if (signe(Fq_elldivpolmod(Eba4, Eba6, ell, h, T, p))) { GEN Ic = FqX_homogenous_div(num_iso,kpoly2, numer_i(Ib),denom_i(Ib), T,p); GEN kpoly_new = FqX_homogenous_eval(gtmp, numer_i(Ic),denom_i(Ic), T,p); return gerepilecopy(ltop, mkvecn(5, a4t, a6t, kpoly_new, gtmp, Ic)); } set_avma(btop); } return gc_NULL(ltop); } /****************************************************************************/ /* TRACE */ /****************************************************************************/ enum mod_type {MTcm, MTpathological, MTAtkin, MTElkies, MTone_root, MTroots}; static GEN Flxq_study_eqn(GEN mpoly, GEN T, ulong p, long *pt_dG, long *pt_r) { GEN Xq = FlxqX_Frobenius(mpoly, T, p); GEN G = FlxqX_gcd(FlxX_sub(Xq, pol_x(0), p), mpoly, T, p); *pt_dG = degpol(G); if (!*pt_dG) { *pt_r = FlxqX_ddf_degree(mpoly, Xq, T, p); return NULL; } return gel(FlxqX_roots(G, T, p), 1); } static GEN Fp_study_eqn(GEN mpoly, GEN p, long *pt_dG, long *pt_r) { GEN T = FpX_get_red(mpoly, p); GEN XP = FpX_Frobenius(T, p); GEN G = FpX_gcd(FpX_sub(XP, pol_x(0), p), mpoly, p); *pt_dG = degpol(G); if (!*pt_dG) { *pt_r = FpX_ddf_degree(T, XP, p); return NULL; } return FpX_oneroot(G, p); } static GEN Fq_study_eqn(GEN mpoly, GEN T, GEN p, long *pt_dG, long *pt_r) { GEN G; if (!T) return Fp_study_eqn(mpoly, p, pt_dG, pt_r); if (lgefint(p)==3) { ulong pp = p[2]; GEN Tp = ZXT_to_FlxT(T,pp); GEN mpolyp = ZXX_to_FlxX(mpoly,pp,get_FpX_var(T)); G = Flxq_study_eqn(mpolyp, Tp, pp, pt_dG, pt_r); return G ? Flx_to_ZX(G): NULL; } else { GEN Xq = FpXQX_Frobenius(mpoly, T, p); G = FpXQX_gcd(FpXX_sub(Xq, pol_x(0), p), mpoly, T, p); *pt_dG = degpol(G); if (!*pt_dG) { *pt_r = FpXQX_ddf_degree(mpoly, Xq, T, p); return NULL; } return gel(FpXQX_roots(G, T, p), 1); } } /* Berlekamp variant */ static GEN study_modular_eqn(long ell, GEN mpoly, GEN T, GEN p, enum mod_type *mt, long *ptr_r) { pari_sp ltop = avma; GEN g = gen_0; *ptr_r = 0; /*gcc -Wall*/ if (!FqX_is_squarefree(mpoly, T, p)) *mt = MTcm; else { long dG; g = Fq_study_eqn(mpoly, T, p, &dG, ptr_r); switch(dG) { case 0: *mt = MTAtkin; break; case 1: *mt = MTone_root; break; case 2: *mt = MTElkies; break; default: *mt = (dG == ell + 1)? MTroots: MTpathological; } } if (DEBUGLEVEL) switch(*mt) { case MTone_root: err_printf("One root\t"); break; case MTElkies: err_printf("Elkies\t"); break; case MTroots: err_printf("l+1 roots\t"); break; case MTAtkin: err_printf("Atkin\t"); break; case MTpathological: err_printf("Pathological\n"); break; case MTcm: err_printf("CM\t"); break; } return g ? gerepilecopy(ltop, g): NULL; } /*Returns the trace modulo ell^k when ell is an Elkies prime */ static GEN find_trace_Elkies_power(GEN a4, GEN a6, ulong ell, long *pt_k, struct meqn *MEQN, GEN g, GEN tr, GEN q, GEN T, GEN p, long smallfact, pari_timer *ti) { pari_sp ltop = avma, btop; GEN tmp, Eba4, Eba6, Eca4, Eca6, Ib, kpoly; long k = *pt_k; ulong lambda, ellk = upowuu(ell, k), pellk = umodiu(q, ellk); long cnt; if (DEBUGLEVEL) { err_printf("mod %ld", ell); } Eba4 = a4; Eba6 = a6; tmp = find_isogenous(a4,a6, ell, MEQN, g, T, p); if (!tmp) return gc_NULL(ltop); Eca4 = gel(tmp, 1); Eca6 = gel(tmp, 2); kpoly = gel(tmp, 3); Ib = pol_x(0); lambda = tr ? find_eigen_value_oneroot(a4, a6, ell, tr, kpoly, T, p): find_eigen_value_power(a4, a6, ell, 1, 1, kpoly, T, p); if (DEBUGLEVEL>1) err_printf(" [%ld ms]", timer_delay(ti)); if (smallfact && smallfact%(long)ell!=0) { ulong pell = pellk%ell; ulong ap = Fl_add(lambda, Fl_div(pell, lambda, ell), ell); if (Fl_sub(pell, ap, ell)==ell-1) { set_avma(ltop); return mkvecsmall(ap); } if (smallfact < 0 && Fl_add(pell, ap, ell)==ell-1) { set_avma(ltop); return mkvecsmall(ap); } } btop = avma; for (cnt = 2; cnt <= k; cnt++) { GEN tmp = find_kernel_power(Eba4, Eba6, Eca4, Eca6, ell, MEQN, kpoly, Ib, T, p); if (!tmp) { k = cnt-1; break; } if (DEBUGLEVEL) err_printf(", %Ps", powuu(ell, cnt)); lambda = find_eigen_value_power(a4, a6, ell, cnt, lambda, gel(tmp,3), T, p); Eba4 = Eca4; Eba6 = Eca6; Eca4 = gel(tmp,1); Eca6 = gel(tmp,2); kpoly = gel(tmp,4); Ib = gel(tmp, 5); if (gc_needed(btop, 1)) { if(DEBUGMEM>1) pari_warn(warnmem,"find_trace_Elkies_power"); gerepileall(btop, 6, &Eba4, &Eba6, &Eca4, &Eca6, &kpoly, &Ib); } if (DEBUGLEVEL>1) err_printf(" [%ld ms]", timer_delay(ti)); } set_avma(ltop); ellk = upowuu(ell, k); pellk = umodiu(q, ellk); *pt_k = k; return mkvecsmall(Fl_add(lambda, Fl_div(pellk, lambda, ellk), ellk)); } /*Returns the possible values of the trace when ell is an Atkin prime, */ /*given r the splitting degree of the modular equation at J = E.j */ static GEN find_trace_Atkin(ulong ell, long r, GEN q) { pari_sp ltop = avma; long nval = 0; ulong teta, pell = umodiu(q, ell), invp = Fl_inv(pell, ell); GEN val_pos = cgetg(1+ell, t_VECSMALL), P = gel(factoru(r), 1); GEN S = mkvecsmall4(0, pell, 0, 1); GEN U = mkvecsmall3(0, ell-1, 0); pari_sp btop = avma; if (r==2 && krouu(ell-pell, ell) < 0) val_pos[++nval] = 0; for (teta = 1; teta < ell; teta++, set_avma(btop)) { ulong disc = Fl_sub(Fl_sqr(teta,ell), Fl_mul(4UL,pell,ell), ell); GEN a; if (krouu(disc, ell) >= 0) continue; S[3] = Fl_neg(teta, ell); U[3] = Fl_mul(invp, teta, ell); a = Flxq_powu(U, r/P[1], S, ell); if (!Flx_equal1(a) && Flx_equal1(Flxq_powu(a, P[1], S, ell))) { pari_sp av = avma; long i, l=lg(P); for (i = 2; i < l; i++, set_avma(av)) if (Flx_equal1(Flxq_powu(U, r/P[i], S, ell))) break; if (i==l) val_pos[++nval] = teta; } } return gerepileupto(ltop, vecsmall_shorten(val_pos, nval)); } /*Returns the possible traces when there is only one root */ static GEN find_trace_one_root(ulong ell, GEN q) { ulong a = Fl_double(Fl_sqrt(umodiu(q,ell), ell), ell); return mkvecsmall2(a, ell - a); } static GEN find_trace_lp1_roots(long ell, GEN q) { ulong ell2 = ell * ell, pell = umodiu(q, ell2); ulong a = Fl_sqrt(pell%ell, ell); ulong pa = Fl_add(Fl_div(pell, a, ell2), a, ell2); return mkvecsmall2(pa, ell2 - pa); } /*ell odd prime; trace modulo ell^k: [], [t] or [t1,...,td] */ static GEN find_trace(GEN a4, GEN a6, GEN j, ulong ell, GEN q, GEN T, GEN p, long *ptr_kt, long smallfact, long vx, long vy) { pari_sp ltop = avma; GEN g, meqnj, tr, tr2; long kt, r; enum mod_type mt; struct meqn MEQN; pari_timer ti; kt = maxss((long)(log(expi(q)*M_LN2)/log((double)ell)), 1); if (DEBUGLEVEL) { err_printf("SEA: Prime %5ld ", ell); timer_start(&ti); } get_modular_eqn(&MEQN, ell, vx, vy); meqnj = meqn_j(&MEQN, j, ell, T, p); g = study_modular_eqn(ell, meqnj, T, p, &mt, &r); /* If l is an Elkies prime, search for a factor of the l-division polynomial. * Then deduce the trace by looking for eigenvalues of the Frobenius by * computing modulo this factor */ switch (mt) { case MTone_root: tr2 = find_trace_one_root(ell, q); tr = find_trace_Elkies_power(a4,a6,ell, &kt, &MEQN, g, tr2, q, T, p, smallfact, &ti); if (!tr) { tr = tr2; kt = 1; } break; case MTElkies: /* Contrary to MTone_root, may look mod higher powers of ell */ if (abscmpiu(p, 2*ell+3) <= 0) kt = 1; /* Not implemented in this case */ tr = find_trace_Elkies_power(a4,a6,ell, &kt, &MEQN, g, NULL, q, T, p, smallfact, &ti); if (!tr) { if (DEBUGLEVEL) err_printf("[fail]\n"); return gc_NULL(ltop); } break; case MTroots: tr = find_trace_lp1_roots(ell, q); kt = 2; break; case MTAtkin: tr = find_trace_Atkin(ell, r, q); if (lg(tr)==1) pari_err_PRIME("ellap",p); kt = 1; break; case MTcm: { long D = find_CM(ell, j, T, p); GEN C = Fq_ellcard_CM(D, a4, a6, T, p); if (DEBUGLEVEL>1) err_printf(" D=%ld [%ld ms]\n", D, timer_delay(&ti)); return gc_const(ltop, C); } default: /* case MTpathological: */ return gc_NULL(ltop); } if (DEBUGLEVEL) { long n = lg(tr)-1; if (n > 1 || mt == MTAtkin) { err_printf("%3ld trace(s)",n); if (DEBUGLEVEL>1) err_printf(" [%ld ms]", timer_delay(&ti)); } if (n > 1) 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; 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) { 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 ZV_sort_uniq_shallow(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, NULL, cmp_atkin); if (k > 0 || (k = -k) > l) return; for (i = l; i > k; i--) gel(atkin,i) = gel(atkin,i-1); if (typ(gel(atkin,l))==t_INT) (*nb)++; gel(atkin,k) = trace; } /* V = baby / giant, P = Pb / Pg */ static GEN BSGS_pre(GEN *pdiff, GEN V, GEN P, void *E, const struct bb_group *grp) { GEN diff = compute_diff(V); GEN pre = cgetg(lg(diff), t_VEC); long i, l = lg(diff); gel(pre, 1) = grp->pow(E, P, gel(diff, 1)); /* what we'd _really_ want here is a hashtable diff[i] -> pre[i] */ for (i = 2; i < l; i++) { pari_sp av = avma; GEN d = subii(gel(diff, i), gel(diff, i-1)); GEN Q = grp->mul(E, gel(pre, i-1), grp->pow(E, P, d)); gel(pre, i) = gerepilecopy(av, Q); } *pdiff = diff; return pre; } /* u = trace_elkies, Mu = prod_elkies. Let caller collect garbage */ /* Match & sort: variant from Lercier's thesis, section 11.2.3 */ /* baby/giant/table updated in place: this routines uses * size(baby)+size(giant)+size(table)+size(table_ind) + O(log p) * bits of stack */ static GEN match_and_sort(GEN compile_atkin, GEN Mu, GEN u, GEN q, void *E, const struct bb_group *grp) { pari_sp av1, av2; GEN baby, giant, SgMb, Mb, Mg, den, Sg, dec_inf, div, pp1 = addiu(q,1); GEN P, Pb, Pg, point, diff, pre, table, table_ind; long best_i, i, lbaby, lgiant, k = lg(compile_atkin)-1; GEN bound = sqrti(shifti(q, 2)), card; const long lcard = 100; long lq = lgefint(q), nbcard; pari_timer ti; if (k == 1) { /*only one Atkin prime, check the cardinality with random points */ GEN r = gel(compile_atkin, 1), r1 = gel(r,1), r2 = gel(r,2); long l = lg(r2), j; GEN card = cgetg(l, t_VEC), Cs2, C, U; Z_chinese_pre(Mu, r1, &C,&U, NULL); Cs2 = shifti(C, -1); for (j = 1, i = 1; i < l; i++) { GEN t = Z_chinese_post(u, stoi(r2[i]), C, U, NULL); t = Fp_center_i(t, C, Cs2); if (abscmpii(t, bound) <= 0) gel(card, j++) = subii(pp1, t); } setlg(card, j); return gen_select_order(card, E, grp); } if (DEBUGLEVEL>=2) timer_start(&ti); av1 = avma; best_i = separation( get_lgatkin(compile_atkin, k) ); set_avma(av1); baby = possible_traces(compile_atkin, utoi(best_i), &Mb, 1); giant = possible_traces(compile_atkin, subiu(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++, set_avma(av2)) affii(Fp_mul(gel(giant,i), den, Mg), gel(giant,i)); ZV_sort_inplace(giant); 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++, set_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)); } ZV_sort_inplace(baby); SgMb = mulii(Sg, Mb); card = cgetg(lcard+1,t_VEC); for (i = 1; i <= lcard; i++) gel(card,i) = cgetipos(lq+1); av2 = avma; MATCH_RESTART: set_avma(av2); nbcard = 0; P = grp->rand(E); point = grp->pow(E,P, Mu); Pb = grp->pow(E,point, Mg); Pg = grp->pow(E,point, Mb); /* Precomputation for babies */ pre = BSGS_pre(&diff, baby, Pb, E, grp); /*Now we compute the table of babies, this table contains only the */ /*lifted x-coordinate of the points in order to use less memory */ table = cgetg(lbaby, t_VECSMALL); av1 = avma; /* (p+1 - u - Mu*Mb*Sg) P - (baby[1]) Pb */ point = grp->pow(E,P, subii(subii(pp1, u), mulii(Mu, addii(SgMb, mulii(Mg, gel(baby,1)))))); table[1] = grp->hash(gel(point,1)); for (i = 2; i < lbaby; i++) { GEN d = subii(gel(baby, i), gel(baby, i-1)); point = grp->mul(E, point, grp->pow(E, gel(pre, ZV_search(diff, d)), gen_m1)); table[i] = grp->hash(gel(point,1)); if (gc_needed(av1,3)) { if(DEBUGMEM>1) pari_warn(warnmem,"match_and_sort, baby = %ld", i); point = gerepileupto(av1, point); } } set_avma(av1); /* Precomputations for giants */ pre = BSGS_pre(&diff, giant, Pg, E, grp); /* Look for a collision among the x-coordinates */ table_ind = vecsmall_indexsort(table); table = perm_mul(table,table_ind); av1 = avma; point = grp->pow(E, Pg, gel(giant, 1)); for (i = 1; ; i++) { GEN d; long h = grp->hash(gel(point, 1)); long s = zv_search(table, h); if (s) { while (table[s] == h && s) s--; for (s++; s < lbaby && table[s] == h; s++) { GEN B = gel(baby,table_ind[s]), G = gel(giant,i); GEN GMb = mulii(G, Mb), BMg = mulii(B, Mg); GEN Be = subii(subii(pp1, u), mulii(Mu, addii(SgMb, BMg))); GEN Bp = grp->pow(E,P, Be); /* p+1 - u - Mu (Sg Mb + GIANT Mb + BABY Mg) */ if (gequal(gel(Bp,1),gel(point,1))) { GEN card1 = subii(Be, mulii(Mu, GMb)); GEN card2 = addii(card1, mulii(mulsi(2,Mu), GMb)); if (abscmpii(subii(pp1, card1), bound) <= 0) affii(card1, gel(card, ++nbcard)); if (nbcard >= lcard) goto MATCH_RESTART; if (abscmpii(subii(pp1, card2), bound) <= 0) affii(card2, gel(card, ++nbcard)); if (nbcard >= lcard) goto MATCH_RESTART; } } } if (i==lgiant-1) break; d = subii(gel(giant, i+1), gel(giant, i)); point = grp->mul(E,point, gel(pre, ZV_search(diff, d))); if (gc_needed(av1,3)) { if(DEBUGMEM>1) pari_warn(warnmem,"match_and_sort, giant = %ld", i); point = gerepileupto(av1, point); } } setlg(card, nbcard+1); if (DEBUGLEVEL>=2) timer_printf(&ti,"match_and_sort"); return gen_select_order(card, E, grp); } static GEN get_bound_bsgs(long lp) { GEN B; if (lp <= 160) B = divru(powru(dbltor(1.048), lp), 9); else if (lp <= 192) B = divrr(powru(dbltor(1.052), lp), dbltor(16.65)); else B = mulrr(powru(dbltor(1.035), minss(lp,307)), dbltor(1.35)); return mulru(B, 1000000); } /* 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 of the order, not dividing smallfact, * is detected. Useful when searching for a good curve for cryptographic * applications */ GEN Fq_ellcard_SEA(GEN a4, GEN a6, GEN q, GEN T, GEN p, long smallfact) { const long MAX_ATKIN = 21; pari_sp ltop = avma, btop; long ell, i, nb_atkin, vx,vy; GEN TR, TR_mod, compile_atkin, bound, bound_bsgs, champ; GEN prod_atkin = gen_1, max_traces = gen_0; GEN j; double bound_gr = 1.; const double growth_factor = 1.26; forprime_t TT; j = Fq_ellj(a4, a6, T, p); if (signe(j) == 0 || signe(Fq_sub(j, utoi(1728), T, p)) == 0) return T ? FpXQ_ellcard(Fq_to_FpXQ(a4, T, p), Fq_to_FpXQ(a6, T, p), T, p) : Fp_ellcard(a4, a6, p); if (Fq_elljissupersingular(j, T, p)) return Fq_ellcard_supersingular(a4, a6, T, p); /*First compute the trace modulo 2 */ switch(FqX_nbroots(rhs(a4, a6, 0), T, p)) { case 3: /* bonus time: 4 | #E(Fq) = q+1 - t */ i = mod4(q)+1; if (i > 2) i -= 4; TR_mod = utoipos(4); TR = stoi(i); break; case 1: TR_mod = gen_2; TR = gen_0; break; default : /* 0 */ TR_mod = gen_2; TR = gen_1; break; } if (odd(smallfact) && !mpodd(TR)) { if (DEBUGLEVEL) err_printf("Aborting: #E(Fq) divisible by 2\n"); set_avma(ltop); return gen_0; } vy = fetch_var(); vx = fetch_var_higher(); /* compile_atkin is a vector containing informations about Atkin primes, * informations about Elkies primes lie in Mod(TR, TR_mod). */ u_forprime_init(&TT, 3, ULONG_MAX); bound = sqrti(shifti(q, 4)); bound_bsgs = get_bound_bsgs(expi(q)); compile_atkin = zerovec(MAX_ATKIN); nb_atkin = 0; btop = avma; while ( (ell = u_forprime_next(&TT)) ) { long ellkt, kt = 1, nbtrace; GEN trace_mod; if (absequalui(ell, p)) continue; trace_mod = find_trace(a4, a6, j, ell, q, T, p, &kt, smallfact, vx,vy); if (!trace_mod) continue; if (typ(trace_mod)==t_INT) { delete_var(); delete_var(); return gerepileuptoint(ltop, trace_mod); } nbtrace = lg(trace_mod) - 1; ellkt = (long)upowuu(ell, kt); if (nbtrace == 1) { long t_mod_ellkt = trace_mod[1]; if (smallfact && smallfact%ell!=0) { /* does ell divide q + 1 - t ? */ long q_mod_ell_plus_one = umodiu(q,ell) + 1; ulong card_mod_ell = umodsu(q_mod_ell_plus_one - t_mod_ellkt, ell); ulong tcard_mod_ell = 1; if (card_mod_ell && smallfact < 0) tcard_mod_ell = umodsu(q_mod_ell_plus_one + t_mod_ellkt, ell); if (!card_mod_ell || !tcard_mod_ell) { if (DEBUGLEVEL) err_printf("\nAborting: #E%s(Fq) divisible by %ld\n", tcard_mod_ell ? "" : "_twist", ell); delete_var(); delete_var(); return gc_const(ltop, gen_0); } } (void)Z_incremental_CRT(&TR, t_mod_ellkt, &TR_mod, ellkt); if (DEBUGLEVEL) err_printf(", missing %ld bits\n",expi(bound)-expi(TR_mod)); } else { add_atkin(compile_atkin, mkvec2(utoipos(ellkt), trace_mod), &nb_atkin); prod_atkin = value(-1, compile_atkin, nb_atkin); } if (cmpii(mulii(TR_mod, prod_atkin), bound) > 0) { GEN bound_tr; if (!nb_atkin) { delete_var(); delete_var(); return gerepileuptoint(ltop, subii(addiu(q, 1), TR)); } bound_tr = mulrr(bound_bsgs, dbltor(bound_gr)); bound_gr *= growth_factor; if (signe(max_traces)) { max_traces = divis(muliu(max_traces,nbtrace), ellkt); if (DEBUGLEVEL>=3) err_printf("At least %Ps remaining possibilities.\n",max_traces); } if (cmpir(max_traces, bound_tr) < 0) { GEN bound_atkin = truedivii(bound, TR_mod); champ = champion(compile_atkin, nb_atkin, bound_atkin); max_traces = gel(champ,2); if (DEBUGLEVEL>=2) err_printf("%Ps remaining possibilities.\n", max_traces); if (cmpir(max_traces, bound_tr) < 0) { GEN res, cat = shallowextract(compile_atkin, gel(champ,1)); const struct bb_group *grp; void *E; if (DEBUGLEVEL) err_printf("Match and sort for %Ps possibilities.\n", max_traces); delete_var(); delete_var(); grp = get_FqE_group(&E,a4,a6,T,p); res = match_and_sort(cat, TR_mod, TR, q, E, grp); return gerepileuptoint(ltop, res); } } } if (gc_needed(btop, 1)) gerepileall(btop,5, &TR,&TR_mod, &compile_atkin, &max_traces, &prod_atkin); } return NULL;/*LCOV_EXCL_LINE*/ } GEN Fp_ellcard_SEA(GEN a4, GEN a6, GEN p, long smallfact) { return Fq_ellcard_SEA(a4, a6, p, NULL, p, smallfact); } pari-2.17.2/src/basemath/base5.c0000644000175000017500000017717714676526175014751 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*******************************************************************/ /* */ /* RNF STRUCTURE AND OPERATIONS */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_rnf /* eq is an rnfeq; must return a t_POL */ GEN eltreltoabs(GEN eq, GEN x) { GEN Pabs = gel(eq,1), a = gel(eq,2), k = gel(eq,3), T = gel(eq,4), b, s; long i, v = varn(Pabs); pari_sp av = avma; if (varncmp(gvar(x), v) > 0) x = scalarpol(x,v); x = RgX_nffix("eltreltoabs", T, x, 1); /* Mod(X - k a, Pabs(X)) is a root of the relative polynomial */ if (signe(k)) x = RgXQX_translate(x, deg1pol_shallow(negi(k), gen_0, varn(T)), T); b = pol_x(v); s = gen_0; for (i=lg(x)-1; i>1; i--) { GEN c = gel(x,i); if (typ(c) == t_POL) c = RgX_RgXQ_eval(c, a, Pabs); s = RgX_rem(gadd(c, gmul(b,s)), Pabs); } return gerepileupto(av, s); } GEN rnfeltreltoabs(GEN rnf,GEN x) { const char *f = "rnfeltreltoabs"; GEN pol; checkrnf(rnf); pol = rnf_get_polabs(rnf); switch(typ(x)) { case t_INT: return icopy(x); case t_FRAC: return gcopy(x); case t_POLMOD: if (RgX_equal_var(gel(x,1), pol)) { /* already in 'abs' form, unless possibly if nf = Q */ if (rnf_get_nfdegree(rnf) == 1) { GEN y = gel(x,2); pari_sp av = avma; y = simplify_shallow(liftpol_shallow(y)); return gerepilecopy(av, mkpolmod(y, pol)); } return gcopy(x); } x = polmod_nffix(f,rnf,x,0); if (typ(x) == t_POLMOD) return rnfeltup(rnf,x); retmkpolmod(eltreltoabs(rnf_get_map(rnf), x), ZX_copy(pol)); case t_POL: if (varn(x) == rnf_get_nfvarn(rnf)) return rnfeltup(rnf,x); retmkpolmod(eltreltoabs(rnf_get_map(rnf), x), ZX_copy(pol)); } pari_err_TYPE(f,x); return NULL;/*LCOV_EXCL_LINE*/ } GEN eltabstorel_lift(GEN rnfeq, GEN P) { GEN k, T = gel(rnfeq,4), R = gel(rnfeq,5); if (is_scalar_t(typ(P))) return P; k = gel(rnfeq,3); P = lift_shallow(P); if (signe(k)) P = RgXQX_translate(P, deg1pol_shallow(k, gen_0, varn(T)), T); P = RgXQX_rem(P, R, T); return QXQX_to_mod_shallow(P, T); } /* rnfeq = [pol,a,k,T,R], P a t_POL or scalar * Return Mod(P(x + k Mod(y, T(y))), pol(x)) */ GEN eltabstorel(GEN rnfeq, GEN P) { GEN T = gel(rnfeq,4), R = gel(rnfeq,5); return mkpolmod(eltabstorel_lift(rnfeq,P), QXQX_to_mod_shallow(R,T)); } GEN rnfeltabstorel(GEN rnf,GEN x) { const char *f = "rnfeltabstorel"; pari_sp av = avma; GEN pol, T, P, NF; checkrnf(rnf); T = rnf_get_nfpol(rnf); P = rnf_get_pol(rnf); pol = rnf_get_polabs(rnf); switch(typ(x)) { case t_INT: return icopy(x); case t_FRAC: return gcopy(x); case t_POLMOD: if (RgX_equal_var(P, gel(x,1))) { x = polmod_nffix(f, rnf, x, 0); P = QXQX_to_mod_shallow(P,T); return gerepilecopy(av, mkpolmod(x,P)); } if (RgX_equal_var(T, gel(x,1))) { x = Rg_nffix(f, T, x, 0); goto END; } if (!RgX_equal_var(pol, gel(x,1))) pari_err_MODULUS(f, gel(x,1),pol); x = gel(x,2); break; case t_POL: break; case t_COL: NF = obj_check(rnf, rnf_NFABS); if (!NF) pari_err_TYPE("rnfeltabstorel, apply nfinit(rnf)",x); x = nf_to_scalar_or_alg(NF,x); break; default: pari_err_TYPE(f,x); return NULL;/*LCOV_EXCL_LINE*/ } switch(typ(x)) { case t_INT: return icopy(x); case t_FRAC: return gcopy(x); case t_POL: break; default: pari_err_TYPE(f, x); } RgX_check_QX(x,f); if (varn(x) != varn(pol)) { if (varn(x) == varn(T)) { x = Rg_nffix(f,T,x,0); goto END; } pari_err_VAR(f, x,pol); } switch(lg(x)) { case 2: return gc_const(av, gen_0); case 3: return gerepilecopy(av, gel(x,2)); } END: return gerepilecopy(av, eltabstorel(rnf_get_map(rnf), x)); } /* x a t_VEC of rnf elements in 'alg' form (t_POL). Assume maximal rank or 0 */ static GEN modulereltoabs(GEN rnf, GEN x) { GEN W=gel(x,1), I=gel(x,2), rnfeq = rnf_get_map(rnf), polabs = gel(rnfeq,1); long i, j, k, m, N = lg(W)-1; GEN zknf, dzknf, M; if (!N) return cgetg(1, t_VEC); zknf = rnf_get_nfzk(rnf); dzknf = gel(zknf,1); m = rnf_get_nfdegree(rnf); M = cgetg(N*m+1, t_VEC); for (k=i=1; i<=N; i++) { GEN c0, cid, w = gel(W,i), id = gel(I,i); if (lg(id) == 1) continue; /* must be a t_MAT */ id = Q_primitive_part(id, &cid); w = Q_primitive_part(eltreltoabs(rnfeq,w), &c0); c0 = div_content(mul_content(c0,cid), dzknf); if (typ(id) == t_INT) for (j=1; j<=m; j++) { GEN z = RgX_rem(gmul(w, gel(zknf,j)), polabs); if (c0) z = RgX_Rg_mul(z, c0); gel(M,k++) = z; } else for (j=1; j<=m; j++) { GEN c, z = Q_primitive_part(RgV_RgC_mul(zknf,gel(id,j)), &c); z = RgX_rem(gmul(w, z), polabs); c = mul_content(c, c0); if (c) z = RgX_Rg_mul(z, c); gel(M,k++) = z; } } setlg(M, k); return M; } /* Z-basis for absolute maximal order: [NF.pol, NF.zk] */ GEN rnf_zkabs(GEN rnf) { GEN d, v, M = modulereltoabs(rnf, rnf_get_zk(rnf)); GEN T = rnf_get_polabs(rnf); long n = degpol(T); M = Q_remove_denom(M, &d); /* t_VEC of t_POL */ if (d) { M = RgXV_to_RgM(M,n); M = ZM_hnfmodall(M, d, hnf_MODID|hnf_CENTER); M = RgM_Rg_div(M, d); } else M = matid(n); v = rnf_get_ramified_primes(rnf); if (lg(v) == 1) { GEN D = gel(rnf_get_disc(rnf),1); if (!isint1(D)) pari_err_TYPE("rnf_zkabs (old style rnf)", rnf); } v = shallowconcat(nf_get_ramified_primes(rnf_get_nf(rnf)), v); return mkvec3(T, RgM_to_RgXV(M, varn(T)), ZV_sort_uniq_shallow(v)); } static GEN mknfabs(GEN rnf, long prec) { GEN NF; if ((NF = obj_check(rnf,rnf_NFABS))) { if (nf_get_prec(NF) < prec) NF = nfnewprec_shallow(NF,prec); } else NF = nfinit(rnf_zkabs(rnf), prec); return NF; } static GEN mkupdown(GEN NF, GEN rnf) { GEN M, zknf, dzknf; long i, l; zknf = rnf_get_nfzk(rnf); dzknf = gel(zknf,1); if (gequal1(dzknf)) dzknf = NULL; l = lg(zknf); M = cgetg(l, t_MAT); gel(M,1) = vec_ei(nf_get_degree(NF), 1); for (i = 2; i < l; i++) { GEN c = poltobasis(NF, gel(zknf,i)); if (dzknf) c = gdiv(c, dzknf); gel(M,i) = c; } return Qevproj_init(M); } GEN rnf_build_nfabs(GEN rnf, long prec) { GEN NF = obj_checkbuild_prec(rnf, rnf_NFABS, &mknfabs, &nf_get_prec, prec); GEN O = obj_check(rnf, rnf_MAPS); if (!O) { pari_sp av = avma; O = obj_insert(rnf, rnf_MAPS, mkupdown(NF, rnf)); set_avma(av); } return NF; } void rnfcomplete(GEN rnf) { (void)rnf_build_nfabs(rnf, nf_get_prec(rnf_get_nf(rnf))); } GEN nf_nfzk(GEN nf, GEN rnfeq) { GEN pol = gel(rnfeq,1), a = gel(rnfeq,2); return Q_primpart(QXV_QXQ_eval(nf_get_zkprimpart(nf), a, pol)); } static GEN rnfdisc_get_T_i(GEN P, GEN *lim) { *lim = NULL; if (typ(P) == t_VEC && lg(P) == 3) { GEN L = gel(P,2); long i, l; *lim = L; switch(typ(L)) { case t_INT: if (signe(L) <= 0) return NULL; break; case t_VEC: case t_COL: l = lg(L); for (i = 1; i < l; i++) { GEN p = gel(L,i); if (typ(p) == t_INT) { if (signe(p) <= 0) return NULL; } else checkprid(p); } break; default: return NULL; } P = gel(P,1); } return (typ(P) == t_POL)? P: NULL; } /* true nf */ GEN rnfdisc_get_T(GEN nf, GEN P, GEN *lim) { GEN T = rnfdisc_get_T_i(P, lim); if (!T) pari_err_TYPE("rnfdisc",P); return RgX_nffix("rnfdisc", nf_get_pol(nf), T, 1); } GEN rnfpseudobasis(GEN nf, GEN pol) { pari_sp av = avma; GEN D, z, lim; nf = checknf(nf); pol = rnfdisc_get_T(nf, pol, &lim); z = rnfallbase(nf, pol, lim, NULL, &D, NULL, NULL); return gerepilecopy(av, shallowconcat(z,D)); } GEN rnfinit0(GEN nf, GEN T, long flag) { pari_sp av = avma; GEN lim, bas, D, f, B, DKP, rnfeq, rnf = obj_init(11, 2); nf = checknf(nf); T = rnfdisc_get_T(nf, T, &lim); gel(rnf,11) = rnfeq = nf_rnfeq(nf,T); gel(rnf,2) = nf_nfzk(nf, rnfeq); bas = rnfallbase(nf, T, lim, rnf, &D, &f, &DKP); B = matbasistoalg(nf,gel(bas,1)); gel(bas,1) = lift_if_rational( RgM_to_RgXV(B,varn(T)) ); gel(rnf,1) = T; gel(rnf,3) = D; gel(rnf,4) = f; gel(rnf,5) = DKP; gel(rnf,6) = cgetg(1, t_VEC); /* dummy */ gel(rnf,7) = bas; gel(rnf,8) = lift_if_rational( RgM_inv_upper(B) ); gel(rnf,9) = typ(f) == t_INT? powiu(f, nf_get_degree(nf)) : RgM_det_triangular(f); gel(rnf,10)= nf; rnf = gerepilecopy(av, rnf); if (flag) rnfcomplete(rnf); return rnf; } GEN rnfinit(GEN nf, GEN T) { return rnfinit0(nf,T,0); } GEN rnfeltup0(GEN rnf, GEN x, long flag) { pari_sp av = avma; GEN zknf, nf, NF, POL; long tx = typ(x); checkrnf(rnf); if (flag) rnfcomplete(rnf); NF = obj_check(rnf,rnf_NFABS); POL = rnf_get_polabs(rnf); if (tx == t_POLMOD && RgX_equal_var(gel(x,1), POL)) { if (flag) x = nf_to_scalar_or_basis(NF,x); return gerepilecopy(av, x); } nf = rnf_get_nf(rnf); if (NF && tx == t_COL && lg(x)-1 == degpol(POL) && nf_get_degree(rnf) > 1) { x = flag? nf_to_scalar_or_basis(NF,x) : mkpolmod(nf_to_scalar_or_alg(NF,x), POL); return gerepilecopy(av, x); } if (NF) { GEN d, proj; x = nf_to_scalar_or_basis(nf, x); if (typ(x) != t_COL) return gerepilecopy(av, x); proj = obj_check(rnf,rnf_MAPS); x = Q_remove_denom(x,&d); x = ZM_ZC_mul(gel(proj,1), x); if (d) x = gdiv(x,d); if (!flag) x = basistoalg(NF,x); } else { zknf = rnf_get_nfzk(rnf); x = nfeltup(nf, x, zknf); if (typ(x) == t_POL) x = mkpolmod(x, POL); } return gerepilecopy(av, x); } GEN rnfeltup(GEN rnf, GEN x) { return rnfeltup0(rnf,x,0); } GEN nfeltup(GEN nf, GEN x, GEN zknf) { GEN c, dzknf = gel(zknf,1); x = nf_to_scalar_or_basis(nf, x); if (typ(x) != t_COL) return x; x = Q_primitive_part(x, &c); if (!RgV_is_ZV(x)) pari_err_TYPE("rnfeltup", x); if (gequal1(dzknf)) dzknf = NULL; c = div_content(c, dzknf); x = RgV_RgC_mul(zknf, x); if (c) x = RgX_Rg_mul(x, c); return x; } static void fail(const char *f, GEN x) { pari_err_DOMAIN(f,"element","not in", strtoGENstr("the base field"),x); } /* x t_COL of length degabs */ static GEN eltdown(GEN rnf, GEN x, long flag) { GEN y, d, proj = obj_check(rnf,rnf_MAPS); GEN M = gel(proj,1), iM = gel(proj,2), diM = gel(proj,3), perm = gel(proj,4); x = Q_remove_denom(x,&d); if (!RgV_is_ZV(x)) pari_err_TYPE("rnfeltdown", x); y = ZM_ZC_mul(iM, vecpermute(x, perm)); if (!ZV_equal(ZM_ZC_mul(M,y), isint1(diM)? x: ZC_Z_mul(x,diM))) fail("rnfeltdown",x); d = mul_denom(d, diM); if (d) y = gdiv(y,d); if (!flag) y = basistoalg(rnf_get_nf(rnf), y); return y; } GEN rnfeltdown0(GEN rnf, GEN x, long flag) { const char *f = "rnfeltdown"; pari_sp av = avma; GEN z, T, NF, nf; long v; checkrnf(rnf); NF = obj_check(rnf,rnf_NFABS); nf = rnf_get_nf(rnf); T = nf_get_pol(nf); v = varn(T); switch(typ(x)) { /* directly belonging to base field ? */ case t_INT: return icopy(x); case t_FRAC:return gcopy(x); case t_POLMOD: if (RgX_equal_var(gel(x,1), rnf_get_polabs(rnf))) { if (degpol(T) == 1) { x = simplify_shallow(liftpol_shallow(gel(x,2))); if (typ(x) != t_POL) return gerepilecopy(av,x); } break; } x = polmod_nffix(f,rnf,x,0); /* x was defined mod the relative polynomial & non constant => fail */ if (typ(x) == t_POL) fail(f,x); if (flag) x = nf_to_scalar_or_basis(nf,x); return gerepilecopy(av, x); case t_POL: if (varn(x) != v) break; x = Rg_nffix(f,T,x,0); if (flag) x = nf_to_scalar_or_basis(nf,x); return gerepilecopy(av, x); case t_COL: { long n = lg(x)-1; if (n == degpol(T) && RgV_is_QV(x)) { if (RgV_isscalar(x)) return gcopy(gel(x,1)); if (!flag) return gcopy(x); return basistoalg(nf,x); } if (NF) break; } default: pari_err_TYPE(f, x); } /* x defined mod the absolute equation */ if (NF) { x = nf_to_scalar_or_basis(NF, x); if (typ(x) == t_COL) x = eltdown(rnf,x,flag); return gerepilecopy(av, x); } z = rnfeltabstorel(rnf,x); switch(typ(z)) { case t_INT: case t_FRAC: return z; } /* typ(z) = t_POLMOD, varn of both components is rnf_get_varn(rnf) */ z = gel(z,2); if (typ(z) == t_POL) { if (lg(z) != 3) fail(f,x); z = gel(z,2); } return gerepilecopy(av, z); } GEN rnfeltdown(GEN rnf, GEN x) { return rnfeltdown0(rnf,x,0); } /* vector of rnf elt -> matrix of nf elts */ static GEN rnfV_to_nfM(GEN rnf, GEN x) { long i, l = lg(x); GEN y = cgetg(l, t_MAT); for (i = 1; i < l; i++) gel(y,i) = rnfalgtobasis(rnf,gel(x,i)); return y; } static GEN rnfprincipaltohnf(GEN rnf,GEN x) { pari_sp av = avma; GEN bas = rnf_get_zk(rnf), nf = rnf_get_nf(rnf); x = rnfbasistoalg(rnf,x); x = gmul(x, gmodulo(gel(bas,1), rnf_get_pol(rnf))); return gerepileupto(av, nfhnf(nf, mkvec2(rnfV_to_nfM(rnf,x), gel(bas,2)))); } /* pseudo-basis for the 0 ideal */ static GEN rnfideal0(void) { retmkvec2(cgetg(1,t_MAT),cgetg(1,t_VEC)); } GEN rnfidealhnf(GEN rnf, GEN x) { GEN z, nf, bas; checkrnf(rnf); nf = rnf_get_nf(rnf); switch(typ(x)) { case t_INT: case t_FRAC: if (isintzero(x)) return rnfideal0(); bas = rnf_get_zk(rnf); z = cgetg(3,t_VEC); gel(z,1) = matid(rnf_get_degree(rnf)); gel(z,2) = gmul(x, gel(bas,2)); return z; case t_VEC: if (lg(x) == 3 && typ(gel(x,1)) == t_MAT) return nfhnf(nf, x); case t_MAT: return rnfidealabstorel(rnf, x); case t_POLMOD: case t_POL: case t_COL: return rnfprincipaltohnf(rnf,x); } pari_err_TYPE("rnfidealhnf",x); return NULL; /* LCOV_EXCL_LINE */ } static GEN prodidnorm(GEN nf, GEN I) { long i, l = lg(I); GEN z; if (l == 1) return gen_1; z = idealnorm(nf, gel(I,1)); for (i=2; i vector of 2 generators (relative polmods) */ GEN rnfidealtwoelement(GEN rnf, GEN x) { pari_sp av = avma; GEN y, cy, z, NF; y = rnfidealreltoabs_i(rnf,x); rnfcomplete(rnf); NF = obj_check(rnf,rnf_NFABS); y = matalgtobasis(NF, y); settyp(y, t_MAT); y = Q_primitive_part(y, &cy); y = ZM_hnf(y); if (lg(y) == 1) { set_avma(av); return mkvec2(gen_0, gen_0); } y = idealtwoelt(NF, y); if (cy) y = RgV_Rg_mul(y, cy); z = gel(y,2); if (typ(z) == t_COL) z = rnfeltabstorel(rnf, nf_to_scalar_or_alg(NF, z)); return gerepilecopy(av, mkvec2(gel(y,1), z)); } GEN rnfidealmul(GEN rnf,GEN x,GEN y) { pari_sp av = avma; GEN nf, z, x1, x2, p1, p2, bas; y = rnfidealtwoelement(rnf,y); if (isintzero(gel(y,1))) { set_avma(av); return rnfideal0(); } nf = rnf_get_nf(rnf); bas = rnf_get_zk(rnf); x = rnfidealhnf(rnf,x); x1 = gmodulo(gmul(gel(bas,1), matbasistoalg(nf,gel(x,1))), rnf_get_pol(rnf)); x2 = gel(x,2); p1 = gmul(gel(y,1), gel(x,1)); p2 = rnfV_to_nfM(rnf, gmul(gel(y,2), x1)); z = mkvec2(shallowconcat(p1, p2), shallowconcat(x2, x2)); return gerepileupto(av, nfhnf(nf,z)); } /* prK wrt NF ~ Q[x]/(polabs) */ static GEN rnfidealprimedec_1(GEN rnf, GEN SL, GEN prK) { GEN v, piL, piK = pr_get_gen(prK); long i, c, l; if (pr_is_inert(prK)) return SL; piL = rnfeltup0(rnf, piK, 1); v = cgetg_copy(SL, &l); for (i = c = 1; i < l; i++) { GEN P = gel(SL,i); if (ZC_prdvd(piL, P)) gel(v,c++) = P; } setlg(v, c); return v; } GEN rnfidealprimedec(GEN rnf, GEN pr) { pari_sp av = avma; GEN p, z, NF, nf, SL; checkrnf(rnf); rnfcomplete(rnf); NF = obj_check(rnf,rnf_NFABS); nf = rnf_get_nf(rnf); if (typ(pr) == t_INT) { p = pr; pr = NULL; } else { checkprid(pr); p = pr_get_p(pr); } SL = idealprimedec(NF, p); if (pr) z = rnfidealprimedec_1(rnf, SL, pr); else { GEN vK = idealprimedec(nf, p), vL; long l = lg(vK), i; vL = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(vL,i) = rnfidealprimedec_1(rnf, SL, gel(vK,i)); z = mkvec2(vK, vL); } return gerepilecopy(av, z); } GEN rnfidealfactor(GEN rnf, GEN x) { pari_sp av = avma; GEN NF; checkrnf(rnf); rnfcomplete(rnf); NF = obj_check(rnf,rnf_NFABS); return gerepileupto(av, idealfactor(NF, rnfidealreltoabs0(rnf, x, 1))); } GEN rnfequationall(GEN A, GEN B, long *pk, GEN *pLPRS) { long lA, lB; GEN nf, C; A = get_nfpol(A, &nf); lA = lg(A); if (!nf) { if (lA<=3) pari_err_CONSTPOL("rnfequation"); RgX_check_ZX(A,"rnfequation"); } B = RgX_nffix("rnfequation", A,B,1); lB = lg(B); if (lB<=3) pari_err_CONSTPOL("rnfequation"); B = Q_primpart(B); if (!nfissquarefree(A,B)) pari_err_DOMAIN("rnfequation","issquarefree(B)","=",gen_0,B); *pk = 0; C = ZX_ZXY_resultant_all(A, B, pk, pLPRS); if (signe(leading_coeff(C)) < 0) C = ZX_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 = QXQ_div(mH0, H1, C); C = mkvec3(C, mkpolmod(a, C), stoi(k)); } return gerepilecopy(av, C); } GEN rnfequation(GEN nf, GEN pol) { return rnfequation0(nf,pol,0); } GEN rnfequation2(GEN nf, GEN pol) { return rnfequation0(nf,pol,1); } GEN nf_rnfeq(GEN nf, GEN R) { GEN pol, a, k, junk, eq; R = liftpol_shallow(R); eq = rnfequation2(nf, R); pol = gel(eq,1); a = gel(eq,2); if (typ(a) == t_POLMOD) a = gel(a,2); k = gel(eq,3); return mkvec5(pol,a,k,get_nfpol(nf, &junk),R); } /* only allow abstorel */ GEN nf_rnfeqsimple(GEN nf, GEN R) { long sa; GEN junk, pol; R = liftpol_shallow(R); pol = rnfequationall(nf, R, &sa, NULL); return mkvec5(pol,gen_0/*dummy*/,stoi(sa),get_nfpol(nf, &junk),R); } /*******************************************************************/ /* */ /* RELATIVE LLL */ /* */ /*******************************************************************/ static GEN nftau(long r1, GEN x) { long i, l = lg(x); GEN s = r1? gel(x,1): gmul2n(real_i(gel(x,1)),1); for (i=2; i<=r1; i++) s = gadd(s, gel(x,i)); for ( ; i < l; i++) s = gadd(s, gmul2n(real_i(gel(x,i)),1)); return s; } static GEN initmat(long l) { GEN x = cgetg(l, t_MAT); long i; for (i = 1; i < l; i++) gel(x,i) = cgetg(l, t_COL); return x; } static GEN nftocomplex(GEN nf, GEN x) { GEN M = nf_get_M(nf); x = nf_to_scalar_or_basis(nf,x); if (typ(x) != t_COL) return const_col(nbrows(M), x); return RgM_RgC_mul(M, x); } /* assume x a square t_MAT, return a t_VEC of embeddings of its columns */ static GEN mattocomplex(GEN nf, GEN x) { long i,j, l = lg(x); GEN v = cgetg(l, t_VEC); for (j=1; j= 0) return NULL; /* precision problem */ m = ZM_ZC_mul(x, m); if (cx) m = ZC_Q_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 = conj_i(muf); Bf = gadd(gel(B,k), vecmul(real_i(vecmul(muf,mufc)), gel(B,k-1))); if (check_0(Bf)) return 1; /* precision problem */ p1 = vecdiv(gel(B,k-1),Bf); gcoeff(mu,k,k-1) = vecmul(mufc,p1); temp = gel(MCS,k-1); gel(MCS,k-1) = gadd(gel(MCS,k), vecmul(muf,gel(MCS,k-1))); gel(MCS,k) = gsub(vecmul(vecdiv(gel(B,k),Bf), temp), vecmul(gcoeff(mu,k,k-1), gel(MCS,k))); gel(B,k) = vecmul(gel(B,k),p1); gel(B,k-1) = Bf; for (i=k+1; i<=kmax; i++) { temp = gcoeff(mu,i,k); gcoeff(mu,i,k) = gsub(gcoeff(mu,i,k-1), vecmul(muf, gcoeff(mu,i,k))); gcoeff(mu,i,k-1) = gadd(temp, vecmul(gcoeff(mu,k,k-1),gcoeff(mu,i,k))); } return 1; } static GEN rel_T2(GEN nf, GEN pol, long lx, long prec) { long ru, i, j, k, l; GEN T2, s, unro, roorder, powreorder; roorder = nf_all_roots(nf, pol, prec); if (!roorder) return NULL; ru = lg(roorder); unro = cgetg(lx,t_COL); for (i=1; i kmax) { /* Incremental Gram-Schmidt */ kmax = k; gel(MCS,k) = gel(MC,k); for (j=1; j 2) k--; } else { for (l=k-2; l; l--) if (!RED(k, l, h, mu, MC, nf, I, &Ik_inv)) goto PRECPB; k++; } if (gc_needed(av,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"rnflllgram"); gerepileall(av, H?10:9, &nf,&mth,&h,&MPOL,&B,&MC,&MCS,&mu,&I,&H); } } 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, nfpol, bnf = checkbnf_i(nf); if (typ(pol)!=t_POL) pari_err_TYPE("rnfpolred",pol); nf = bnf? bnf_get_nf(bnf): checknf(nf); 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_shallow(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--) gel(a,i) = nf_to_scalar_or_alg(nf, gel(a,i)); 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_coeff(newpol); gel(w,j) = (typ(L) == t_POL)? RgXQX_div(newpol, L, nfpol) : RgX_Rg_div(newpol, L); } return gerepilecopy(av,w); } /*******************************************************************/ /* */ /* LINEAR ALGEBRA OVER Z_K (HNF,SNF) */ /* */ /*******************************************************************/ /* A torsion-free module M over Z_K is given by [A,I]. * I=[a_1,...,a_k] is a row vector of k fractional ideals given in HNF. * A is an n x k matrix (same k) such that if A_j is the j-th column of A then * M=a_1 A_1+...+a_k A_k. We say that [A,I] is a pseudo-basis if k=n */ /* Given an element x and an ideal I in HNF, gives an r such that x-r is in H * and r is small */ GEN nfreduce(GEN nf, GEN x, GEN I) { pari_sp av = avma; x = nf_to_scalar_or_basis(checknf(nf), x); if (idealtyp(&I, NULL) != id_MAT || lg(I)==1) pari_err_TYPE("nfreduce",I); if (typ(x) != t_COL) x = scalarcol( gmod(x, gcoeff(I,1,1)), lg(I)-1 ); else x = reducemodinvertible(x, I); return gerepileupto(av, x); } /* Given an element x and an ideal in HNF, gives an a in ideal such that * x-a is small. No checks */ static GEN element_close(GEN nf, GEN x, GEN ideal) { pari_sp av = avma; GEN y = gcoeff(ideal,1,1); x = nf_to_scalar_or_basis(nf, x); if (typ(y) == t_INT && is_pm1(y)) return ground(x); if (typ(x) == t_COL) x = closemodinvertible(x, ideal); else x = gmul(y, gdivround(x,y)); return gerepileupto(av, x); } /* A + v B */ static GEN colcomb1(GEN nf, GEN v, GEN A, GEN B) { if (isintzero(v)) return A; return RgC_to_nfC(nf, RgC_add(A, nfC_nf_mul(nf,B,v))); } /* u A + v B */ static GEN colcomb(GEN nf, GEN u, GEN v, GEN A, GEN B) { if (isintzero(u)) return nfC_nf_mul(nf,B,v); if (u != gen_1) A = nfC_nf_mul(nf,A,u); return colcomb1(nf, v, A, B); } /* return m[i,1..lim] * x */ static GEN element_mulvecrow(GEN nf, GEN x, GEN m, long i, long lim) { long j, l = minss(lg(m), lim+1); GEN dx, y = cgetg(l, t_VEC); x = nf_to_scalar_or_basis(nf, x); if (typ(x) == t_COL) { x = zk_multable(nf, Q_remove_denom(x, &dx)); for (j=1; jidef; i--) { GEN d, di = NULL; j=def; while (j>=1 && isintzero(gcoeff(A,i,j))) j--; if (!j) { /* no pivot on line i */ if (idef) idef--; continue; } if (j==def) j--; else { swap(gel(A,j), gel(A,def)); swap(gel(I,j), gel(I,def)); if (U) swap(gel(U,j), gel(U,def)); } for ( ; j; j--) { GEN a,b, u,v,w, S, T, S0, T0 = gel(A,j); b = gel(T0,i); if (isintzero(b)) continue; S0 = gel(A,def); a = gel(S0,i); d = nfbezout(nf, a,b, gel(I,def),gel(I,j), &u,&v,&w,&di,1); S = colcomb(nf, u,v, S0,T0); T = colcomb(nf, a,gneg(b), T0,S0); gel(A,def) = S; gel(A,j) = T; gel(I,def) = d; gel(I,j) = w; if (U) { S0 = gel(U,def); T0 = gel(U,j); gel(U,def) = colcomb(nf, u,v, S0,T0); gel(U,j) = colcomb(nf, a,gneg(b), T0,S0); } } y = gcoeff(A,i,def); if (!isint1(y)) { GEN yi = nfinv(nf,y); gel(A,def) = nfC_nf_mul(nf, gel(A,def), yi); gel(I,def) = idealmul(nf, y, gel(I,def)); if (U) gel(U,def) = nfC_nf_mul(nf, gel(U,def), yi); di = NULL; } if (!di) di = idealinv(nf,gel(I,def)); d = gel(I,def); gel(J,def) = di; for (j=def+1; j<=n; j++) { GEN mc, c = gcoeff(A,i,j); if (isintzero(c)) continue; c = element_close(nf, c, idealmul(nf,d,gel(J,j))); mc = gneg(c); gel(A,j) = colcomb1(nf, mc, gel(A,j),gel(A,def)); if (U) gel(U,j) = colcomb1(nf, mc, gel(U,j),gel(U,def)); } def--; if (gc_needed(av,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"nfhnf, i = %ld", i); gerepileall(av,U?4:3, &A,&I,&J,&U); } } n -= def; A += def; A[0] = evaltyp(t_MAT)|_evallg(n+1); I += def; I[0] = evaltyp(t_VEC)|_evallg(n+1); idV_simplify(I); x = mkvec2(A,I); if (U) x = mkvec2(x,U); return gerepilecopy(av0, x); } GEN nfhnf(GEN nf, GEN x) { return nfhnf0(nf, x, 0); } static long RgV_find_denom(GEN x) { long i, l = lg(x); for (i = 1; i < l; i++) if (Q_denom(gel(x,i)) != gen_1) return i; return 0; } /* A torsion module M over Z_K will be given by a row vector [A,I,J] with * three components. I=[b_1,...,b_n] is a row vector of n fractional ideals * given in HNF, J=[a_1,...,a_n] is a row vector of n fractional ideals in * HNF. A is an nxn matrix (same n) such that if A_j is the j-th column of A * and e_n is the canonical basis of K^n, then * M=(b_1e_1+...+b_ne_n)/(a_1A_1+...a_nA_n) */ /* x=[A,I,J] a torsion module as above. Output the * smith normal form as K=[c_1,...,c_n] such that x = Z_K/c_1+...+Z_K/c_n */ GEN nfsnf0(GEN nf, GEN x, long flag) { long i, j, k, l, n, m; pari_sp av; GEN z,u,v,w,d,dinv,A,I,J, U,V; nf = checknf(nf); if (typ(x)!=t_VEC || lg(x)!=4) pari_err_TYPE("nfsnf",x); A = gel(x,1); I = gel(x,2); J = gel(x,3); if (typ(A)!=t_MAT) pari_err_TYPE("nfsnf",A); n = lg(A)-1; if (typ(I)!=t_VEC) pari_err_TYPE("nfsnf",I); if (typ(J)!=t_VEC) pari_err_TYPE("nfsnf",J); if (lg(I)!=n+1 || lg(J)!=n+1) pari_err_DIM("nfsnf"); RgM_dimensions(A, &m, &n); if (!n || n != m) pari_err_IMPL("nfsnf for empty or non square matrices"); av = avma; if (!flag) U = V = NULL; else { U = matid(m); V = matid(n); } A = RgM_to_nfM(nf, A); I = leafcopy(I); J = leafcopy(J); for (i = 1; i <= n; i++) gel(J,i) = idealinv(nf, gel(J,i)); z = zerovec(n); for (i=n; i>=1; i--) { GEN Aii, a, b, db; long c = 0; for (j=i-1; j>=1; j--) { GEN S, T, S0, T0 = gel(A,j); b = gel(T0,i); if (gequal0(b)) continue; S0 = gel(A,i); a = gel(S0,i); d = nfbezout(nf, a,b, gel(J,i),gel(J,j), &u,&v,&w,&dinv,1); S = colcomb(nf, u,v, S0,T0); T = colcomb(nf, a,gneg(b), T0,S0); gel(A,i) = S; gel(A,j) = T; gel(J,i) = d; gel(J,j) = w; if (V) { T0 = gel(V,j); S0 = gel(V,i); gel(V,i) = colcomb(nf, u,v, S0,T0); gel(V,j) = colcomb(nf, a,gneg(b), T0,S0); } } for (j=i-1; j>=1; j--) { GEN ri, rj; b = gcoeff(A,j,i); if (gequal0(b)) continue; a = gcoeff(A,i,i); d = nfbezout(nf, a,b, gel(I,i),gel(I,j), &u,&v,&w,&dinv,1); ri = rowcomb(nf, u,v, i,j, A, i); rj = rowcomb(nf, a,gneg(b), j,i, A, i); for (k=1; k<=i; k++) { gcoeff(A,j,k) = gel(rj,k); gcoeff(A,i,k) = gel(ri,k); } if (U) { ri = rowcomb(nf, u,v, i,j, U, m); rj = rowcomb(nf, a,gneg(b), j,i, U, m); for (k=1; k<=m; k++) { gcoeff(U,j,k) = gel(rj,k); gcoeff(U,i,k) = gel(ri,k); } } gel(I,i) = d; gel(I,j) = w; c = 1; } if (c) { i++; continue; } Aii = gcoeff(A,i,i); if (gequal0(Aii)) continue; gel(J,i) = idealmul(nf, gel(J,i), Aii); gcoeff(A,i,i) = gen_1; if (V) gel(V,i) = nfC_nf_mul(nf, gel(V,i), nfinv(nf,Aii)); gel(z,i) = idealmul(nf,gel(J,i),gel(I,i)); b = Q_remove_denom(gel(z,i), &db); for (k=1; k1) pari_warn(warnmem,"nfsnf"); gerepileall(av,U?6:4, &A,&I,&J,&z,&U,&V); } if (c) i++; /* iterate on row/column i */ } if (U) z = mkvec3(z,U,V); return gerepilecopy(av, z); } GEN nfsnf(GEN nf, GEN x) { return nfsnf0(nf,x,0); } /* Given a pseudo-basis x, outputs a multiple of its ideal determinant */ GEN nfdetint(GEN nf, GEN x) { GEN pass,c,v,det1,piv,pivprec,vi,p1,A,I,id,idprod; long i, j, k, rg, n, m, m1, cm=0, N; pari_sp av = avma, av1; nf = checknf(nf); N = nf_get_degree(nf); check_ZKmodule(x, "nfdetint"); A = gel(x,1); I = gel(x,2); n = lg(A)-1; if (!n) return gen_1; m1 = lgcols(A); m = m1-1; id = matid(N); c = new_chunk(m1); for (k=1; k<=m; k++) c[k] = 0; piv = pivprec = gen_1; av1 = avma; det1 = idprod = gen_0; /* dummy for gerepileall */ pass = cgetg(m1,t_MAT); v = cgetg(m1,t_COL); for (j=1; j<=m; j++) { gel(pass,j) = zerocol(m); gel(v,j) = gen_0; /* dummy */ } for (rg=0,k=1; k<=n; k++) { long t = 0; for (i=1; i<=m; i++) if (!c[i]) { vi=nfmul(nf,piv,gcoeff(A,i,k)); for (j=1; j<=m; j++) if (c[j]) vi=gadd(vi,nfmul(nf,gcoeff(pass,i,j),gcoeff(A,j,k))); gel(v,i) = vi; if (!t && !gequal0(vi)) t=i; } if (t) { pivprec = piv; if (rg == m-1) { if (!cm) { cm=1; idprod = id; for (i=1; i<=m; i++) if (i!=t) idprod = (idprod==id)? gel(I,c[i]) : idealmul(nf,idprod,gel(I,c[i])); } p1 = idealmul(nf,gel(v,t),gel(I,k)); c[t]=0; det1 = (typ(det1)==t_INT)? p1: idealadd(nf,p1,det1); } else { rg++; piv=gel(v,t); c[t]=k; for (i=1; i<=m; i++) if (!c[i]) { for (j=1; j<=m; j++) if (c[j] && j!=t) { p1 = gsub(nfmul(nf,piv,gcoeff(pass,i,j)), nfmul(nf,gel(v,i),gcoeff(pass,t,j))); gcoeff(pass,i,j) = rg>1? nfdiv(nf,p1,pivprec) : p1; } gcoeff(pass,i,t) = gneg(gel(v,i)); } } } if (gc_needed(av1,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"nfdetint"); gerepileall(av1,6, &det1,&piv,&pivprec,&pass,&v,&idprod); } } if (!cm) { set_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) { GEN DZ, DZ2, dD; long i; D = Q_remove_denom(D, &dD); DZ = gcoeff(D,1,1); DZ2 = shifti(DZ, -1); for (i = 1; i <= lim; i++) { GEN c = nf_to_scalar_or_basis(nf, gel(x,i)); switch(typ(c)) /* c = centermod(c, D) */ { case t_INT: if (!signe(c)) break; if (dD) c = mulii(c, dD); c = centermodii(c, DZ, DZ2); if (dD) c = Qdivii(c,dD); break; case t_FRAC: { GEN dc = gel(c,2), nc = gel(c,1), N = mulii(DZ, dc); if (dD) nc = mulii(nc, dD); c = centermodii(nc, N, shifti(N,-1)); c = Qdivii(c, dD ? mulii(dc,dD): dc); break; } case t_COL: { GEN dc; c = Q_remove_denom(c, &dc); if (dD) c = ZC_Z_mul(c, dD); c = ZC_hnfrem(c, dc? ZM_Z_mul(D,dc): D); dc = mul_content(dc, dD); if (ZV_isscalar(c)) { c = gel(c,1); if (dc) c = Qdivii(c,dc); } else if (dc) c = RgC_Rg_div(c, dc); break; } } gel(x,i) = c; } } GEN nfhnfmod(GEN nf, GEN x, GEN D) { long li, co, i, j, def, ldef; pari_sp av0=avma, av; GEN dA, dI, d0, w, p1, d, u, v, A, I, J, di; nf = checknf(nf); check_ZKmodule(x, "nfhnfmod"); A = gel(x,1); I = gel(x,2); co = lg(A); if (co==1) return cgetg(1,t_MAT); li = lgcols(A); if (typ(D)!=t_MAT) D = idealhnf_shallow(nf, D); D = Q_remove_denom(D, NULL); RgM_check_ZM(D, "nfhnfmod"); av = avma; A = RgM_to_nfM(nf, A); A = Q_remove_denom(A, &dA); I = Q_remove_denom(leafcopy(I), &dI); dA = mul_denom(dA,dI); if (dA) D = ZM_Z_mul(D, powiu(dA, minss(li,co))); def = co; ldef = (li>co)? li-co+1: 1; for (i=li-1; i>=ldef; i--) { def--; j=def; while (j>=1 && isintzero(gcoeff(A,i,j))) j--; if (!j) continue; if (j==def) j--; else { swap(gel(A,j), gel(A,def)); swap(gel(I,j), gel(I,def)); } for ( ; j; j--) { GEN a, b, S, T, S0, T0 = gel(A,j); b = gel(T0,i); if (isintzero(b)) continue; S0 = gel(A,def); a = gel(S0,i); d = nfbezout(nf, a,b, gel(I,def),gel(I,j), &u,&v,&w,&di,0); 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,D,di)); nfcleanmod(nf, T, i, idealdiv(nf,D,w)); gel(A,def) = S; gel(A,j) = T; gel(I,def) = d; gel(I,j) = w; } if (gc_needed(av,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"[1]: nfhnfmod, i = %ld", i); gerepileall(av,dA? 4: 3, &A,&I,&D,&dA); } } def--; d0 = D; A += def; A[0] = evaltyp(t_MAT)|_evallg(li); I += def; I[0] = evaltyp(t_VEC)|_evallg(li); J = cgetg(li,t_VEC); for (i=li-1; i>=1; i--) { GEN b = gcoeff(A,i,i); d = nfbezout(nf, gen_1,b, d0,gel(I,i), &u,&v,&w,&di,0); p1 = nfC_nf_mul(nf,gel(A,i),v); if (i > 1) { d0 = idealmul(nf,d0,di); nfcleanmod(nf, p1, i, d0); } gel(A,i) = p1; gel(p1,i) = gen_1; gel(I,i) = d; gel(J,i) = di; } for (i=li-2; i>=1; i--) { d = gel(I,i); for (j=i+1; j1) pari_warn(warnmem,"[2]: nfhnfmod, i = %ld", i); gerepileall(av,dA? 4: 3, &A,&I,&J,&dA); } } idV_simplify(I); if (dA) I = gdiv(I,dA); return gerepilecopy(av0, mkvec2(A, I)); } static long decind(GEN nf, GEN p) { pari_sp av = avma; GEN dec = idealprimedec(nf, p); long i, l = lg(dec), s = 0; GEN v = cgetg(l, t_VECSMALL); for (i=1; i= 3 && typ(gel(M,1)) == t_MAT && typ(gel(M,2)) == t_VEC && lgcols(M) == lg(gel(M,2))); } void check_ZKmodule(GEN M, const char *s) { if (!check_ZKmodule_i(M)) pari_err_TYPE(s, M); } static long typv6(GEN x) { if (typ(gel(x,1)) == t_VEC && lg(gel(x,3)) == 3) { GEN t = gel(x,3); if (typ(t) != t_VEC) return typ_NULL; t = gel(x,5); switch(typ(gel(x,5))) { case t_VEC: return typ_BID; case t_MAT: return typ_BIDZ; default: return typ_NULL; } } if (typ(gel(x,2)) == t_COL && typ(gel(x,3)) == t_INT) return typ_PRID; if (typ(gel(x,1)) == t_INT && typ(gel(x,2)) == t_VEC) return typ_QUA; return typ_NULL; } 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: if (typ(gel(x,1)) != t_INT) break; *t = typ_QUA; return NULL; case 6: *t = typv6(x); return NULL; case 7: *t = typ_BNR; x = bnr_get_bnf(x); if (!rawcheckbnf(x)) break; return x; case 9: if (!v9checkgal(x)) break; *t = typ_GAL; return NULL; case 10: if (!v10checknf(x)) break; *t = typ_NF; return NULL; case 11: if (!v11checkbnf(x)) break; *t = typ_BNF; return x; case 13: if (v13checkgchar(x)) { *t = typ_GCHAR; return gchar_get_bnf(x); } if (!v13checkrnf(x)) break; *t = typ_RNF; return NULL; case 17: *t = typ_ELL; return NULL; } break; case t_COL: if (get_prid(x)) { *t = typ_MODPR; return NULL; } break; } *t = typ_NULL; return NULL; } GEN get_nf(GEN x, long *t) { switch(typ(x)) { case t_POL : *t = typ_POL; return NULL; case t_QUAD: *t = typ_Q ; return NULL; case t_VEC: switch(lg(x)) { case 3: if (typ(gel(x,2)) != t_POLMOD) break; return get_nf(gel(x,1),t); case 5: if (typ(gel(x,1)) != t_INT) break; *t = typ_QUA; return NULL; case 6: *t = typv6(x); return NULL; case 7: x = bnr_get_bnf(x); if (!rawcheckbnf(x) || !rawchecknf(x = bnf_get_nf(x))) break; *t = typ_BNR; return x; case 9: if (!v9checkgal(x)) break; *t = typ_GAL; return NULL; case 10: if (!v10checknf(x)) break; *t = typ_NF; return x; case 11: if (!rawchecknf(x = bnf_get_nf(x))) break; *t = typ_BNF; return x; case 13: if (v13checkgchar(x)) { *t = typ_GCHAR; return gchar_get_nf(x); } if (!v13checkrnf(x)) break; *t = typ_RNF; return NULL; case 17: *t = typ_ELL; return NULL; } break; case t_QFB: *t = typ_QFB; return NULL; case t_COL: if (get_prid(x)) { *t = typ_MODPR; return NULL; } break; } *t = typ_NULL; return NULL; } long nftyp(GEN x) { switch(typ(x)) { case t_POL : return typ_POL; case t_QUAD: return typ_Q; case t_VEC: switch(lg(x)) { case 13: if (v13checkgchar(x)) return typ_GCHAR; if (!v13checkrnf(x)) break; return typ_RNF; case 10: if (!v10checknf(x)) break; return typ_NF; case 11: if (!v11checkbnf(x)) break; return typ_BNF; case 7: x = bnr_get_bnf(x); if (!rawcheckbnf(x) || !v11checkbnf(x)) break; return typ_BNR; case 6: return typv6(x); case 9: if (!v9checkgal(x)) break; return typ_GAL; case 17: return typ_ELL; } } return typ_NULL; } /*************************************************************************/ /** **/ /** GALOIS GROUP **/ /** **/ /*************************************************************************/ GEN tschirnhaus(GEN x) { pari_sp av = avma, av2; long a, v = varn(x); GEN u, y = cgetg(5,t_POL); if (typ(x)!=t_POL) pari_err_TYPE("tschirnhaus",x); if (lg(x) < 4) pari_err_CONSTPOL("tschirnhaus"); if (v) { u = leafcopy(x); setvarn(u,0); x=u; } y[1] = evalsigne(1)|evalvarn(0); do { a = random_bits(2); if (a==0) a = 1; gel(y,4) = stoi(a); a = random_bits(3); if (a>=4) a -= 8; gel(y,3) = stoi(a); a = random_bits(3); if (a>=4) a -= 8; gel(y,2) = stoi(a); u = RgXQ_charpoly(y,x,v); av2 = avma; } while (degpol(RgX_gcd(u,RgX_deriv(u)))); /* while u not separable */ if (DEBUGLEVEL>1) err_printf("Tschirnhaus transform. New pol: %Ps",u); set_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; if (ptk) *ptk = gen_1; if (!n) return 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)) return pol; } sk = signe(k); if (!sk) return pol; /* monomial! */ fa = absZ_factor_limit(k, 0); k = gen_1; P = gel(fa,1); E = gel(fa,2); POL = leafcopy(pol); a = POL+2; for (i = lg(P)-1; i > 0; i--) { GEN p = gel(P,i), pv, pvj; long vmin = itos(gel(E,i)); /* find v_p(k) = min floor( v_p(a[i]) / (n-i)) */ for (j=n-1; j>=0; j--) { long v; if (!signe(gel(a,j))) continue; v = Z_pval(gel(a,j), p) / (n - j); if (v < vmin) vmin = v; } if (!vmin) continue; pvj = pv = powiu(p,vmin); k = mulii(k, pv); /* a[j] /= p^(v*(n-j)) */ for (j=n-1; j>=0; j--) { if (j < n-1) pvj = mulii(pvj, pv); gel(a,j) = diviiexact(gel(a,j), pvj); } } if (ptk) *ptk = k; return POL; } /* Assume pol != 0 in Z[X]. Find C in Q, L in Z such that POL = C pol(x/L) monic * in Z[X]. Return POL and set *pL = L. Wasteful (but correct) if pol is not * primitive: better if caller used Q_primpart already. No GC. */ GEN ZX_primitive_to_monic(GEN pol, GEN *pL) { long i,j, n = degpol(pol); GEN lc = leading_coeff(pol), L, fa, P, E, a, POL; if (is_pm1(lc)) { if (pL) *pL = gen_1; return signe(lc) < 0? ZX_neg(pol): pol; } if (signe(lc) < 0) POL = ZX_neg(pol); else POL = leafcopy(pol); a = POL+2; lc = gel(a,n); fa = absZ_factor_limit(lc,0); L = gen_1; P = gel(fa,1); E = gel(fa,2); for (i = lg(P)-1; i > 0; i--) { GEN p = gel(P,i), pk, pku; long v, j0, e = itos(gel(E,i)), k = e/n, d = k*n - e; if (d < 0) { k++; d += n; } /* k = ceil(e[i] / n); find d, k such that p^d pol(x / p^k) monic */ for (j=n-1; j>0; j--) { if (!signe(gel(a,j))) continue; v = Z_pval(gel(a,j), p); while (v + d < k * j) { k++; d += n; } } pk = powiu(p,k); j0 = d/k; L = mulii(L, pk); pku = powiu(p,d - k*j0); /* a[j] *= p^(d - kj) */ for (j=j0; j>=0; j--) { if (j < j0) pku = mulii(pku, pk); gel(a,j) = mulii(gel(a,j), pku); } j0++; pku = powiu(p,k*j0 - d); /* a[j] /= p^(kj - d) */ for (j=j0; j<=n; j++) { if (j > j0) pku = mulii(pku, pk); gel(a,j) = diviiexact(gel(a,j), pku); } } if (pL) *pL = L; return POL; } /* Assume pol != 0 in Z[X]. Find C,L in Q such that POL = C pol(x/L) * monic in Z[X]. Return POL and set *pL = L. * Wasteful (but correct) if pol is not primitive: better if caller used * Q_primpart already. No GC. */ GEN ZX_Q_normalize(GEN pol, GEN *pL) { GEN lc, POL = ZX_primitive_to_monic(pol, &lc); POL = ZX_Z_normalize(POL, pL); if (pL) *pL = gdiv(lc, *pL); return POL; } GEN ZX_Q_mul(GEN A, GEN z) { pari_sp av = avma; long i, l = lg(A); GEN d, n, Ad, B, u; if (typ(z)==t_INT) return ZX_Z_mul(A,z); n = gel(z, 1); d = gel(z, 2); Ad = RgX_to_RgC(FpX_red(A, d), l-2); u = gcdii(d, FpV_factorback(Ad, NULL, d)); B = cgetg(l, t_POL); B[1] = A[1]; if (equali1(u)) { for(i=2; i 0? T: ZX_neg(T); } return ZX_primitive_to_monic(Q_primpart(T), L); } GEN poltomonic(GEN T, GEN *L) { pari_sp av = avma; if (typ(T) != t_POL || !RgX_is_QX(T)) pari_err_TYPE("poltomonic", T); if (degpol(T) < 0) pari_err_ROOTS0("poltomonic"); T = ZX_Q_normalize(Q_primpart(T), L); return gc_all(av, L? 2: 1, &T, L); } GEN ZXX_Q_mul(GEN A, GEN z) { long i, l; GEN B; if (typ(z)==t_INT) return ZXX_Z_mul(A,z); B = cgetg_copy(A, &l); B[1] = A[1]; for (i=2; i=2; i--) res = nfadd(nf, nfmul(nf, s, res), gel(pol,i)); return gerepileupto(av, res); } static GEN QX_table_nfpoleval(GEN nf, GEN pol, GEN m) { pari_sp av = avma; long i = lg(pol)-1; GEN res, den; if (i==1) return gen_0; pol = Q_remove_denom(pol, &den); res = scalarcol_shallow(gel(pol,i), nf_get_degree(nf)); for (i-- ; i>=2; i--) res = ZC_Z_add(ZM_ZC_mul(m, res), gel(pol,i)); if (den) res = RgC_Rg_div(res, den); return gerepileupto(av, res); } GEN FpX_FpC_nfpoleval(GEN nf, GEN pol, GEN a, GEN p) { pari_sp av=avma; long i=lg(pol)-1, n=nf_get_degree(nf); GEN res, Ma; if (i==1) return zerocol(n); Ma = FpM_red(zk_multable(nf, a), p); res = scalarcol(gel(pol,i),n); for (i-- ; i>=2; i--) { res = FpM_FpC_mul(Ma, res, p); gel(res,1) = Fp_add(gel(res,1), gel(pol,i), p); } return gerepileupto(av, res); } /* compute s(x), not stack clean */ static GEN ZC_galoisapply(GEN nf, GEN s, GEN x) { x = nf_to_scalar_or_alg(nf, x); if (typ(x) != t_POL) return scalarcol(x, nf_get_degree(nf)); return QX_table_nfpoleval(nf, x, zk_multable(nf, s)); } /* true nf; S = automorphism in basis form, return an FpC = S(z) mod p */ GEN zk_galoisapplymod(GEN nf, GEN z, GEN S, GEN p) { GEN den, pe, pe1, denpe, R; z = nf_to_scalar_or_alg(nf, z); if (typ(z) != t_POL) return z; if (gequalX(z)) return FpC_red(S, p); /* common, e.g. modpr_genFq */ z = Q_remove_denom(z,&den); denpe = pe = NULL; pe1 = p; if (den) { ulong e = Z_pvalrem(den, p, &den); if (e) { pe = powiu(p, e); pe1 = mulii(pe, p); } denpe = Zp_inv(den, p, e+1); } R = FpX_FpC_nfpoleval(nf, FpX_red(z, pe1), FpC_red(S, pe1), pe1); if (denpe) R = FpC_Fp_mul(R, denpe, pe1); if (pe) R = gdivexact(R, pe); return R; } /* true nf */ static GEN pr_make(GEN nf, GEN p, GEN u, GEN e, GEN f) { GEN t = FpM_deplin(zk_multable(nf, u), p); t = zk_scalar_or_multable(nf, t); return mkvec5(p, u, e, f, t); } static GEN pr_galoisapply(GEN nf, GEN pr, GEN aut) { GEN p = pr_get_p(pr), u = zk_galoisapplymod(nf, pr_get_gen(pr), aut, p); return pr_make(nf, p, u, gel(pr,3), gel(pr,4)); } static GEN pr_galoismatrixapply(GEN nf, GEN pr, GEN M) { GEN p = pr_get_p(pr), u = FpC_red(ZM_ZC_mul(M, pr_get_gen(pr)), p); return pr_make(nf, p, u, gel(pr,3), gel(pr,4)); } static GEN vecgaloisapply(GEN nf, GEN aut, GEN x) { pari_APPLY_same(galoisapply(nf, aut, gel(x,i))); } static GEN vecgaloismatrixapply(GEN nf, GEN aut, GEN x) { pari_APPLY_same(nfgaloismatrixapply(nf, aut, gel(x,i))); } /* x: famat or standard algebraic number, aut automorphism in ZC form * simplified from general galoisapply */ static GEN elt_galoisapply(GEN nf, GEN aut, GEN x) { pari_sp av = avma; switch(typ(x)) { case t_INT: return icopy(x); case t_FRAC: return gcopy(x); case t_POLMOD: x = gel(x,2); /* fall through */ case t_POL: { GEN y = basistoalg(nf, ZC_galoisapply(nf, aut, x)); return gerepileupto(av,y); } case t_COL: return gerepileupto(av, ZC_galoisapply(nf, aut, x)); case t_MAT: switch(lg(x)) { case 1: return cgetg(1, t_MAT); case 3: retmkmat2(vecgaloisapply(nf,aut,gel(x,1)), ZC_copy(gel(x,2))); } } pari_err_TYPE("galoisapply",x); return NULL; /* LCOV_EXCL_LINE */ } /* M automorphism in matrix form */ static GEN elt_galoismatrixapply(GEN nf, GEN M, GEN x) { if (typ(x) == t_MAT) switch(lg(x)) { case 1: return cgetg(1, t_MAT); case 3: retmkmat2(vecgaloismatrixapply(nf,M,gel(x,1)), ZC_copy(gel(x,2))); } return nfgaloismatrixapply(nf, M, x); } GEN galoisapply(GEN nf, GEN aut, GEN x) { pari_sp av = avma; long lx; 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: if (pr_is_inert(x)) { set_avma(av); return gcopy(x); } return gerepilecopy(av, pr_galoisapply(nf, x, aut)); case 3: y = cgetg(3,t_VEC); gel(y,1) = galoisapply(nf, aut, gel(x,1)); gel(y,2) = elt_galoisapply(nf, aut, gel(x,2)); return gerepileupto(av, y); } break; case t_COL: aut = algtobasis(nf, aut); return gerepileupto(av, ZC_galoisapply(nf, aut, x)); case t_MAT: /* ideal */ lx = lg(x); if (lx==1) return cgetg(1,t_MAT); if (nbrows(x) != nf_get_degree(nf)) break; y = RgM_mul(nfgaloismatrix(nf,aut), x); return gerepileupto(av, idealhnf_shallow(nf,y)); } pari_err_TYPE("galoisapply",x); return NULL; /* LCOV_EXCL_LINE */ } /* M automorphism in galoismatrix form */ GEN nfgaloismatrixapply(GEN nf, GEN M, GEN x) { pari_sp av = avma; long lx; 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: x = algtobasis(nf, x); return gerepileupto(av, basistoalg(nf, RgM_RgC_mul(M, x))); case t_VEC: switch(lg(x)) { case 6: if (pr_is_inert(x)) { set_avma(av); return gcopy(x); } return gerepilecopy(av, pr_galoismatrixapply(nf, x, M)); case 3: y = cgetg(3,t_VEC); gel(y,1) = nfgaloismatrixapply(nf, M, gel(x,1)); gel(y,2) = elt_galoismatrixapply(nf, M, gel(x,2)); return gerepileupto(av, y); } break; case t_COL: return RgM_RgC_mul(M, x); case t_MAT: /* ideal */ lx = lg(x); if (lx==1) return cgetg(1,t_MAT); if (nbrows(x) != nf_get_degree(nf)) break; return gerepileupto(av, idealhnf_shallow(nf,RgM_mul(M, x))); } pari_err_TYPE("galoisapply",x); return NULL; /* LCOV_EXCL_LINE */ } /* compute action of automorphism s on nf.zk */ GEN nfgaloismatrix(GEN nf, GEN s) { pari_sp av2, av = avma; GEN zk, D, M, H, m; long k, n; nf = checknf(nf); zk = nf_get_zkprimpart(nf); n = lg(zk)-1; M = cgetg(n+1, t_MAT); gel(M,1) = col_ei(n, 1); /* s(1) = 1 */ if (n == 1) return M; av2 = avma; if (typ(s) != t_COL) s = algtobasis(nf, s); D = nf_get_zkden(nf); H = RgV_to_RgM(zk, n); if (n == 2) { GEN t = gel(H,2); /* D * s(w_2) */ t = ZC_Z_add(ZC_Z_mul(s, gel(t,2)), gel(t,1)); gel(M,2) = gerepileupto(av2, gdiv(t, D)); return M; } m = zk_multable(nf, s); gel(M,2) = s; /* M[,k] = s(x^(k-1)) */ for (k = 3; k <= n; k++) gel(M,k) = ZM_ZC_mul(m, gel(M,k-1)); M = ZM_mul(M, H); if (!equali1(D)) M = ZM_Z_divexact(M, D); return gerepileupto(av, M); } static GEN get_aut(GEN nf, GEN gal, GEN aut, GEN g) { return aut ? gel(aut, g[1]): poltobasis(nf, galoispermtopol(gal, g)); } static GEN idealquasifrob(GEN nf, GEN gal, GEN grp, GEN pr, GEN subg, GEN *S, GEN aut) { pari_sp av = avma; long i, n = nf_get_degree(nf), f = pr_get_f(pr); GEN pi = pr_get_gen(pr); for (i=1; i<=n; i++) { GEN g = gel(grp,i); if ((!subg && perm_orderu(g) == (ulong)f) || (subg && perm_relorder(g, subg)==f)) { *S = get_aut(nf, gal, aut, g); if (ZC_prdvd(ZC_galoisapply(nf, *S, pi), pr)) return g; set_avma(av); } } pari_err_BUG("idealquasifrob [Frobenius not found]"); return NULL;/*LCOV_EXCL_LINE*/ } GEN nfgaloispermtobasis(GEN nf, GEN gal) { GEN grp = gal_get_group(gal); long i, n = lg(grp)-1; GEN aut = cgetg(n+1, t_VEC); for(i=1; i<=n; i++) { pari_sp av = avma; GEN g = gel(grp, i); GEN vec = poltobasis(nf, galoispermtopol(gal, g)); gel(aut, g[1]) = gerepileupto(av, vec); } return aut; } static void gal_check_pol(const char *f, GEN x, GEN y) { if (!RgX_equal_var(x,y)) pari_err_MODULUS(f,x,y); } /* true nf */ GEN idealfrobenius_aut(GEN nf, GEN gal, GEN pr, GEN aut) { pari_sp av = avma; GEN S=NULL, g=NULL; /*-Wall*/ GEN T, p, a, b, modpr; long f, n, s; f = pr_get_f(pr); n = nf_get_degree(nf); if (f==1) { set_avma(av); return identity_perm(n); } g = idealquasifrob(nf, gal, gal_get_group(gal), pr, NULL, &S, aut); if (f==2) return gerepileuptoleaf(av, g); modpr = zk_to_Fq_init(nf,&pr,&T,&p); a = pol_x(nf_get_varn(nf)); b = nf_to_Fq(nf, zk_galoisapplymod(nf, modpr_genFq(modpr), S, p), modpr); for (s = 1; s < f-1; s++) { a = Fq_pow(a, p, T, p); if (ZX_equal(a, b)) break; } g = perm_powu(g, Fl_inv(s, f)); return gerepileupto(av, g); } GEN idealfrobenius(GEN nf, GEN gal, GEN pr) { nf = checknf(nf); checkgal(gal); checkprid(pr); gal_check_pol("idealfrobenius",nf_get_pol(nf),gal_get_pol(gal)); if (pr_get_e(pr)>1) pari_err_DOMAIN("idealfrobenius","pr.e", ">", gen_1,pr); return idealfrobenius_aut(nf, gal, pr, NULL); } /* true nf */ GEN idealramfrobenius_aut(GEN nf, GEN gal, GEN pr, GEN ram, GEN aut) { pari_sp av = avma; GEN S=NULL, g=NULL; /*-Wall*/ GEN T, p, a, b, modpr; GEN isog, deco; long f, n, s; f = pr_get_f(pr); n = nf_get_degree(nf); if (f==1) { set_avma(av); return identity_perm(n); } modpr = zk_to_Fq_init(nf,&pr,&T,&p); deco = group_elts(gel(ram,1), nf_get_degree(nf)); isog = group_set(gel(ram,2), nf_get_degree(nf)); g = idealquasifrob(nf, gal, deco, pr, isog, &S, aut); a = pol_x(nf_get_varn(nf)); b = nf_to_Fq(nf, zk_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_powu(g, Fl_inv(s, f)); return gerepileupto(av, g); } GEN idealramfrobenius(GEN nf, GEN gal, GEN pr, GEN ram) { return idealramfrobenius_aut(nf, gal, pr, ram, NULL); } static GEN idealinertiagroup(GEN nf, GEN gal, GEN aut, GEN pr) { long i, n = nf_get_degree(nf); GEN p, T, modpr = zk_to_Fq_init(nf,&pr,&T,&p); GEN b = modpr_genFq(modpr); long e = pr_get_e(pr), coprime = ugcd(e, pr_get_f(pr)) == 1; GEN grp = gal_get_group(gal), pi = pr_get_gen(pr); pari_sp ltop = avma; for (i=1; i<=n; i++) { GEN iso = gel(grp,i); if (perm_orderu(iso) == (ulong)e) { GEN S = get_aut(nf, gal, aut, iso); if (ZC_prdvd(ZC_galoisapply(nf, S, pi), pr) && (coprime || gequalX(nf_to_Fq(nf, galoisapply(nf,S,b), modpr)))) return iso; set_avma(ltop); } } pari_err_BUG("idealinertiagroup [no isotropic element]"); return NULL;/*LCOV_EXCL_LINE*/ } static GEN idealramgroupstame(GEN nf, GEN gal, GEN aut, GEN pr) { pari_sp av = avma; GEN iso, frob, giso, isog, S, res; long e = pr_get_e(pr), f = pr_get_f(pr); GEN grp = gal_get_group(gal); if (e == 1) { if (f==1) return cgetg(1,t_VEC); frob = idealquasifrob(nf, gal, grp, pr, NULL, &S, aut); set_avma(av); res = cgetg(2, t_VEC); gel(res, 1) = cyclicgroup(frob, f); return res; } res = cgetg(3, t_VEC); av = avma; iso = idealinertiagroup(nf, gal, aut, pr); set_avma(av); giso = cyclicgroup(iso, e); gel(res, 2) = giso; if (f==1) { gel(res, 1) = giso; return res; } av = avma; isog = group_set(giso, nf_get_degree(nf)); frob = idealquasifrob(nf, gal, grp, pr, isog, &S, aut); set_avma(av); gel(res, 1) = dicyclicgroup(iso,frob,e,f); return res; } /* true nf, p | e */ static GEN idealramgroupswild(GEN nf, GEN gal, GEN aut, GEN pr) { pari_sp av2, av = avma; GEN p, T, idx, g, gbas, pi, pibas, Dpi, modpr = zk_to_Fq_init(nf,&pr,&T,&p); long bound, i, vDpi, vDg, n = nf_get_degree(nf); long e = pr_get_e(pr); long f = pr_get_f(pr); ulong nt,rorder; GEN pg, ppi, grp = gal_get_group(gal); /* G_i = {s: v(s(pi) - pi) > i} trivial for i > bound; * v_pr(Diff) = sum_{i = 0}^{bound} (#G_i - 1) >= e-1 + bound*(p-1)*/ bound = (idealval(nf, nf_get_diff(nf), pr) - (e-1)) / (itou(p)-1); (void) u_pvalrem(n,p,&nt); rorder = e*f*(n/nt); idx = const_vecsmall(n,-1); pg = NULL; vDg = 0; if (f == 1) g = gbas = NULL; else { GEN Dg; g = nf_to_scalar_or_alg(nf, modpr_genFq(modpr)); if (!gequalX(g)) /* p | nf.index */ { g = Q_remove_denom(g, &Dg); vDg = Z_pval(Dg,p); pg = powiu(p, vDg + 1); g = FpX_red(g, pg); } gbas = nf_to_scalar_or_basis(nf, g); } pi = nf_to_scalar_or_alg(nf, pr_get_gen(pr)); pi = Q_remove_denom(pi, &Dpi); vDpi = Dpi ? Z_pval(Dpi, p): 0; ppi = powiu(p, vDpi + (bound + e)/e); pi = FpX_red(pi, ppi); pibas = nf_to_scalar_or_basis(nf, pi); av2 = avma; for (i = 2; i <= n; i++) { GEN S, Spi, piso, iso = gel(grp, i); long j, o, ix = iso[1]; if (idx[ix] >= 0 || rorder % (o = (long)perm_orderu(iso))) continue; piso = iso; S = get_aut(nf, gal, aut, iso); Spi = FpX_FpC_nfpoleval(nf, pi, FpC_red(S, ppi), ppi); /* Computation made knowing that the valuation is <= bound + 1. Correct * to maximal value if reduction mod ppi altered this */ idx[ix] = minss(bound+1, idealval(nf, gsub(Spi,pibas), pr) - e*vDpi); if (idx[ix] == 0) idx[ix] = -1; else if (g) { GEN Sg = pg? FpX_FpC_nfpoleval(nf, g, FpC_red(S, pg), pg): S; if (vDg) { if (nfval(nf, gsub(Sg, gbas), pr) - e*vDg <= 0) idx[ix] = 0; } else /* same, more efficient */ { if (!ZC_prdvd(gsub(Sg, gbas), pr)) idx[ix] = 0; } } for (j = 2; j < o; j++) { piso = perm_mul(piso,iso); if (ugcd(j,o)==1) idx[ piso[1] ] = idx[ix]; } set_avma(av2); } return gerepileuptoleaf(av, idx); } GEN idealramgroups_aut(GEN nf, GEN gal, GEN pr, GEN aut) { pari_sp av = avma; GEN tbl, idx, res, set, sub; long i, j, e, n, maxm, p; ulong et; nf = checknf(nf); checkgal(gal); checkprid(pr); gal_check_pol("idealramgroups",nf_get_pol(nf),gal_get_pol(gal)); e = pr_get_e(pr); n = nf_get_degree(nf); p = itos(pr_get_p(pr)); if (e%p) return idealramgroupstame(nf, gal, aut, pr); (void) u_lvalrem(e,p,&et); idx = idealramgroupswild(nf, gal, aut, pr); sub = galoissubgroups(gal); tbl = subgroups_tableset(sub, n); maxm = vecsmall_max(idx)+1; res = cgetg(maxm+1,t_VEC); set = zero_F2v(n); F2v_set(set,1); for(i=maxm; i>0; i--) { long ix; for(j=1;j<=n;j++) if (idx[j]==i-1) F2v_set(set,j); ix = tableset_find_index(tbl, set); if (ix==0) pari_err_BUG("idealramgroups"); gel(res,i) = gel(sub, ix); } return gerepilecopy(av, res); } GEN idealramgroups(GEN nf, GEN gal, GEN pr) { return idealramgroups_aut(nf, gal, pr, NULL); } /* x = relative polynomial nf = absolute nf, bnf = absolute bnf */ GEN get_bnfpol(GEN x, GEN *bnf, GEN *nf) { *bnf = checkbnf_i(x); *nf = checknf_i(x); if (*nf) x = nf_get_pol(*nf); if (typ(x) != t_POL) pari_err_TYPE("get_bnfpol",x); return x; } GEN get_nfpol(GEN x, GEN *nf) { if (typ(x) == t_POL) { *nf = NULL; return x; } *nf = checknf(x); return nf_get_pol(*nf); } static GEN incl_disc(GEN nfa, GEN a, int nolocal) { GEN d; if (nfa) return nf_get_disc(nfa); if (nolocal) return NULL; d = ZX_disc(a); if (!signe(d)) pari_err_IRREDPOL("nfisincl",a); return d; } static int badp(GEN fa, GEN db, long q) { GEN P = gel(fa,1), E = gel(fa,2); long i, l = lg(P); for (i = 1; i < l; i++) if (mod2(gel(E,i)) && !dvdii(db, powiu(gel(P,i),q))) return 1; return 0; } /* is isomorphism / inclusion (a \subset b) compatible with what we know about * basic invariants ? (degree, signature, discriminant); test for isomorphism * if fliso is set and for inclusion otherwise */ static int tests_OK(GEN a, GEN nfa, GEN b, GEN nfb, long fliso) { GEN da2, da, db, fa, P, U; long i, l, q, m = degpol(a), n = degpol(b); if (m <= 0) pari_err_IRREDPOL("nfisincl",a); if (n <= 0) pari_err_IRREDPOL("nfisincl",b); q = n / m; /* relative degree */ if (fliso) { if (n != m) return 0; } else { if (n % m) return 0; } if (m == 1) return 1; /*local test expensive if n^2 >> m^4 <=> q = n/m >> m */ db = incl_disc(nfb, b, q > m); da = db? incl_disc(nfa, a, 0): NULL; if (nfa && nfb) /* both nf structures available */ { long r1a = nf_get_r1(nfa), r1b = nf_get_r1(nfb); return fliso ? (r1a == r1b && equalii(da, db)) : (r1b <= r1a * q && dvdii(db, powiu(da, q))); } if (!db) return 1; if (fliso) return issquare(gdiv(da,db)); if (nfa) { P = nf_get_ramified_primes(nfa); l = lg(P); for (i = 1; i < l; i++) if (Z_pval(db, gel(P,i)) < q * Z_pval(da, gel(P,i))) return 0; return 1; } else if (nfb) { P = nf_get_ramified_primes(nfb); l = lg(P); for (i = 1; i < l; i++) { GEN p = gel(P,i); long va = Z_pval(nfdisc(mkvec2(a, mkvec(p))), p); if (va && Z_pval(db, gel(P,i)) < va * q) return 0; } return 1; } /* da = dK A^2, db = dL B^2, dL = dK^q * N(D) * da = da1 * da2, da2 maximal s.t. (da2, db) = 1: let p a prime divisor of * da2 then p \nmid da1 * dK and p | A => v_p(da) = v_p(da2) is even */ da2 = Z_ppo(da, db); if (!is_pm1(da2)) { /* replace da by da1 all of whose prime divisors divide db */ da2 = absi_shallow(da2); if (!Z_issquare(da2)) return 0; da = diviiexact(da, da2); } if (is_pm1(da)) return 1; fa = absZ_factor_limit_strict(da, 0, &U); if (badp(fa, db, q)) return 0; if (U && mod2(gel(U,2)) && expi(gel(U,1)) < 150) { /* cofactor is small, finish */ fa = absZ_factor(gel(U,1)); if (badp(fa, db, q)) return 0; } return 1; } GEN nfisisom(GEN a, GEN b) { pari_sp av = avma; long i, va, vb, lx; GEN nfa, nfb, y, la, lb; int newvar, sw = 0; a = get_nfpol(a, &nfa); b = get_nfpol(b, &nfb); if (!nfa) { a = Q_primpart(a); RgX_check_ZX(a, "nfisisom"); } if (!nfb) { b = Q_primpart(b); RgX_check_ZX(b, "nfisisom"); } if (ZX_equal(a, b)) { y = galoisconj(nfb? nfb: b, NULL); settyp(y, t_VEC); return gerepilecopy(av,y); } if (nfa && !nfb) { swap(a,b); nfb = nfa; nfa = NULL; sw = 1; } if (!tests_OK(a, nfa, b, nfb, 1)) { set_avma(av); return gen_0; } if (nfb) lb = gen_1; else nfb = b = ZX_Q_normalize(b,&lb); if (nfa) la = gen_1; else nfa = a = ZX_Q_normalize(a,&la); va = varn(a); vb = varn(b); newvar = (varncmp(vb,va) <= 0); if (newvar) { a = leafcopy(a); setvarn(a, fetch_var_higher()); } y = lift_shallow(nfroots(nfb,a)); if (newvar) (void)delete_var(); lx = lg(y); if (lx==1) { set_avma(av); return gen_0; } if (sw) { vb = va; b = leafcopy(b); setvarn(b, vb); } for (i=1; i 3) pari_err_FLAG("nfisincl"); a = get_nfpol(fa, &nfa); b = get_nfpol(fb, &nfb); if (!nfa) { a = Q_primpart(a); RgX_check_ZX(a, "nsisincl"); } if (!nfb) { b = Q_primpart(b); RgX_check_ZX(b, "nsisincl"); } if (ZX_equal(a, b) && flag<=1) { if (flag==1) { x = pol_x(varn(b)); return degpol(b) > 1 ? x: RgX_rem(x,b); } x = galoisconj(fb, NULL); settyp(x, t_VEC); return gerepilecopy(av,x); } if (flag==0 && !tests_OK(a, nfa, b, nfb, 0)) { set_avma(av); return gen_0; } if (nfb) lb = gen_1; else nfb = b = ZX_Q_normalize(b,&lb); if (nfa) la = gen_1; else nfa = a = ZX_Q_normalize(a,&la); vb = varn(b); newvar = (varncmp(varn(a),vb) <= 0); if (newvar) { b = leafcopy(b); setvarn(b, fetch_var_higher()); } y = lift_shallow(gel(nffactor(nfa,b),1)); if (flag==2) x = nfisincl_from_fact_frac(a, b, la, lb, vb, y); else x = nfisincl_from_fact(nfa, degpol(a), b, la, lb, vb, y, flag); if (newvar) (void)delete_var(); return gerepilecopy(av,x); } GEN nfisincl(GEN fa, GEN fb) { return nfisincl0(fa, fb, 0); } static GEN RgF_to_Flxq(GEN F, GEN T, ulong p) { GEN N, D, iD; if (typ(F)==t_POL) return RgX_to_Flx(F, p); N = RgX_to_Flx(gel(F,1), p); D = RgX_to_Flx(gel(F,2), p); iD = Flxq_invsafe(D, T, p); if (!iD) return NULL; return Flxq_mul(N, iD, T, p); } #define pari_APPLY_abort(EXPR)\ { \ long i, _l; \ GEN _y = cgetg_copy(x, &_l);\ for (i=1; i<_l; i++) \ { GEN _z = EXPR;\ if (!_z) return _z;\ gel(_y,i) = _z;\ } return _y;\ } static GEN RgFV_to_FlxqV(GEN x, GEN T, ulong p) { pari_APPLY_abort(RgF_to_Flxq(gel(x,i), T, p)) } static GEN nfsplitting_auto(GEN g, GEN R) { pari_sp av; forprime_t T; long i, d = degpol(g); ulong p; GEN P, K, N, G, q, den = Q_denom(R), Rp, Gp; u_forprime_init(&T, d*maxss(expu(d)-3, 2), ULONG_MAX); av = avma; for(;; set_avma(av)) { p = u_forprime_next(&T); if (dvdiu(den,p)) continue; Gp = ZX_to_Flx(g, p); if (!Flx_is_totally_split(Gp, p)) continue; P = Flx_roots(Gp, p); Rp = RgFV_to_FlxqV(R, Gp, p); if (Rp) break; if (DEBUGLEVEL) err_printf("nfsplitting_auto: bad p : %lu\n",p); } if (d == 1) return mkvec3(g, mkcol(gel(Rp,1)), utoi(p)); K = Flm_Flc_invimage(FlxV_to_Flm(Rp, d), vecsmall_ei(d, 2), p); if (!K) pari_err_BUG("nfsplitting_auto"); N = Flm_transpose(FlxV_Flv_multieval(Rp, P, p)); q = perm_inv(vecsmall_indexsort(gel(N,1))); G = cgetg(d+1, t_COL); for (i=1; i<=d; i++) { GEN r = perm_mul(vecsmall_indexsort(gel(N,i)), q); gel(G,i) = FlxV_Flc_mul(Rp, vecsmallpermute(K, r), p); } return mkvec3(g, G, utoi(p)); } static GEN nfsplitting_composite(GEN P) { GEN F = gel(ZX_factor(P), 1), Q = NULL; long i, n = lg(F)-1; for (i = 1; i <= n; i++) { GEN Fi = gel(F, i); if (degpol(Fi) == 1) continue; Q = Q ? veclast(compositum(Q, Fi)): Fi; } return Q ? Q: pol_x(varn(P)); } GEN nfsplitting0(GEN T0, GEN D, long flag) { pari_sp av = avma; long d, Ds, v; GEN T, F, K, N = NULL, lT = NULL; if (flag < 0 || flag > 3) pari_err_FLAG("nfsplitting"); T = T0 = get_nfpol(T0, &K); if (!K) { GEN c; if (typ(T) != t_POL) pari_err_TYPE("nfsplitting",T); T = Q_primitive_part(T, &c); lT = leading_coeff(T); if (isint1(lT)) lT = NULL; if (flag && (c || lT)) pari_err_TYPE("nfsplitting", T0); RgX_check_ZX(T,"nfsplitting"); } T = nfsplitting_composite(T); if (flag && !ZX_equal(T, T0)) pari_err_IRREDPOL("nfsplitting", T0); d = degpol(T); v = varn(T); if (d <= 1 && !flag) { set_avma(av); return pol_x(v); } if (!K) { if (lT) T = polredbest(T,0); K = T; } if (D) { if (typ(D) != t_INT || signe(D) < 1) pari_err_TYPE("nfsplitting",D); } else if (d <= 7 || (d <= 11 && pari_is_dir(stack_strcat(pari_datadir, "/galdata")))) D = gel(polgalois(T,DEFAULTPREC), 1); else D = mpfact(d); Ds = itos_or_0(D); T = leafcopy(T); setvarn(T, fetch_var_higher()); for(F = T;;) { GEN P = gel(nffactor(K, F), 1), Q = veclast(P); if (degpol(gel(P,1)) == degpol(Q)) { if (!flag) break; P = liftall_shallow(P); if (flag==1) N = nfisincl_from_fact(K, d, F, gen_1, gen_1, v, P, flag); else N = nfisincl_from_fact_frac(T0, F, gen_1, gen_1, v, P); break; } F = rnfequation(K,Q); if (degpol(F) == Ds && !flag) break; } if (umodiu(D,degpol(F))) { char *sD = itostr(D); pari_warn(warner,stack_strcat("ignoring incorrect degree bound ",sD)); } setvarn(F, v); (void)delete_var(); if (flag) F = flag == 3? nfsplitting_auto(F, N): mkvec2(F, N); return gerepilecopy(av, F); } GEN nfsplitting(GEN T, GEN D) { return nfsplitting0(T, D, 0); } /*************************************************************************/ /** **/ /** INITALG **/ /** **/ /*************************************************************************/ typedef struct { GEN T; GEN ro; /* roots of T */ long r1; GEN basden; long prec; long extraprec; /* possibly -1 = irrelevant or not computed */ GEN M, G; /* possibly NULL = irrelevant or not computed */ } nffp_t; static GEN get_roots(GEN x, long r1, long prec) { long i, ru; GEN z; if (typ(x) != t_POL) { z = leafcopy(x); ru = (lg(z)-1 + r1) >> 1; } else { long n = degpol(x); z = (r1 == n)? ZX_realroots_irred(x, prec): QX_complex_roots(x,prec); ru = (n+r1)>>1; } for (i=r1+1; i<=ru; i++) gel(z,i) = gel(z, (i<<1)-r1); z[0]=evaltyp(t_VEC)|_evallg(ru+1); return z; } GEN nf_get_allroots(GEN nf) { return embed_roots(nf_get_roots(nf), nf_get_r1(nf)); } /* For internal use. compute trace(x mod pol), sym=polsym(pol,deg(pol)-1) */ static 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 && gel(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 */ static 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; ibasis */ static GEN nf_multable(nfmaxord_t *S, GEN invbas) { GEN T = S->T, w = gel(S->basden,1), den = gel(S->basden,2); long i,j, n = degpol(T); GEN mul = cgetg(n*n+1,t_MAT); /* i = 1 split for efficiency, assume w[1] = 1 */ for (j=1; j<=n; j++) gel(mul,j) = gel(mul,1+(j-1)*n) = col_ei(n, j); for (i=2; i<=n; i++) for (j=i; j<=n; j++) { pari_sp av = avma; GEN z = (i == j)? ZXQ_sqr(gel(w,i), T): ZXQ_mul(gel(w,i),gel(w,j), T); z = ZM_ZX_mul(invbas, z); /* integral column */ if (den) { GEN d = mul_denom(gel(den,i), gel(den,j)); if (d) z = ZC_Z_divexact(z, d); } gel(mul,j+(i-1)*n) = gel(mul,i+(j-1)*n) = gerepileupto(av,z); } return mul; } /* as get_Tr, mul_table not precomputed */ static GEN make_Tr(nfmaxord_t *S) { GEN T = S->T, w = gel(S->basden,1), den = gel(S->basden,2); long i,j, n = degpol(T); GEN c, t, d, M = cgetg(n+1,t_MAT), sym = polsym(T, n-1); /* W[i] = w[i]/den[i]; assume W[1] = 1, case i = 1 split for efficiency */ c = cgetg(n+1,t_COL); gel(M,1) = c; gel(c, 1) = utoipos(n); for (j=2; j<=n; j++) { pari_sp av = avma; t = quicktrace(gel(w,j), sym); if (den) { d = gel(den,j); if (d) t = diviiexact(t, d); } gel(c,j) = gerepileuptoint(av, t); } for (i=2; i<=n; i++) { c = cgetg(n+1,t_COL); gel(M,i) = c; for (j=1; jbasden,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; j 1)? ginv(r): NULL; 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); if (r1 == l-1) { F->G = M; return; } G = cgetg(l, t_MAT); for (j = 1; j < l; j++) { GEN g, m = gel(M,j); gel(G,j) = g = cgetg(l, t_COL); for (k = i = 1; i <= r1; i++) gel(g,k++) = gel(m,i); for ( ; k < l; i++) { GEN r = gel(m,i); if (typ(r) == t_COMPLEX) { GEN a = gel(r,1), b = gel(r,2); gel(g,k++) = mpadd(a, b); gel(g,k++) = mpsub(a, b); } else { gel(g,k++) = r; gel(g,k++) = r; } } } F->G = G; } static long prec_fix(long prec) { #ifndef LONG_IS_64BIT /* make sure that default accuracy is the same on 32/64bit */ if (odd(prec2lg(prec))) prec+=EXTRAPRECWORD; #endif return prec; } static void make_M_G(nffp_t *F, int trunc) { long n, eBD, prec; if (F->extraprec < 0) { /* not initialized yet; compute roots so that absolute accuracy * of M & G >= prec */ double er; n = degpol(F->T); eBD = 1 + gexpo(gel(F->basden,1)); er = F->ro? (1+gexpo(F->ro)): fujiwara_bound(F->T); if (er < 0) er = 0; F->extraprec = nbits2extraprec(n*er + eBD + log2(n)); } prec = prec_fix(F->prec + F->extraprec); if (!F->ro || gprecision(gel(F->ro,1)) < prec) F->ro = get_roots(F->T, F->r1, prec); make_M(F, trunc); make_G(F); } static void nffp_init(nffp_t *F, nfmaxord_t *S, long prec) { F->T = S->T; F->r1 = S->r1; F->basden = S->basden; F->ro = NULL; F->extraprec = -1; F->prec = prec; } /* let bas a t_VEC of QX giving a Z-basis of O_K. Return the index of the * basis. Assume bas[1] = 1 and that the leading coefficient of elements * of bas are of the form 1/b for a t_INT b */ static GEN get_nfindex(GEN bas) { pari_sp av = avma; long n = lg(bas)-1, i; GEN D, d, mat; /* assume bas[1] = 1 */ D = gel(bas,1); if (! is_pm1(simplify_shallow(D))) pari_err_TYPE("get_nfindex", D); D = gen_1; for (i = 2; i <= n; i++) { /* 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: if (is_pm1(gel(lc,1)) ) {D = mulii(D, gel(lc,2)); continue;} default: pari_err_TYPE("get_nfindex", B); } } if (i <= n) { /* not triangular after all */ bas = vecslice(bas,i,n); bas = Q_remove_denom(bas, &d); if (!d) return D; mat = RgV_to_RgM(bas, n); mat = rowslice(mat, i,n); D = mulii(D, diviiexact(powiu(d, n-i+1), absi_shallow(ZM_det(mat)))); } return gerepileuptoint(av, D); } /* make sure all components of S are initialized */ static void nfmaxord_complete(nfmaxord_t *S) { if (!S->dT) S->dT = ZX_disc(S->T); if (!S->index) { if (S->dK) /* fast */ S->index = sqrti( diviiexact(S->dT, S->dK) ); else S->index = get_nfindex(S->basis); } if (!S->dK) S->dK = diviiexact(S->dT, sqri(S->index)); if (S->r1 < 0) S->r1 = ZX_sturm_irred(S->T); if (!S->basden) S->basden = get_bas_den(S->basis); } GEN nfmaxord_to_nf(nfmaxord_t *S, GEN ro, long prec) { GEN nf = cgetg(10,t_VEC); GEN T = S->T, Tr, D, w, A, dA, MDI, mat = cgetg(9,t_VEC); long n = degpol(T); nffp_t F; nfmaxord_complete(S); nffp_init(&F,S,prec); F.ro = ro; make_M_G(&F, 0); gel(nf,1) = S->T; gel(nf,2) = mkvec2s(S->r1, (n - S->r1)>>1); gel(nf,3) = S->dK; gel(nf,4) = S->index; gel(nf,5) = mat; if (gprecision(gel(F.ro,1)) > prec) F.ro = gprec_wtrunc(F.ro, prec); gel(nf,6) = F.ro; w = S->basis; if (!is_pm1(S->index)) w = Q_remove_denom(w, NULL); gel(nf,7) = w; gel(nf,8) = ZM_inv(RgV_to_RgM(w,n), NULL); gel(nf,9) = nf_multable(S, nf_get_invzk(nf)); gel(mat,1) = F.M; gel(mat,2) = F.G; Tr = get_Tr(gel(nf,9), T, S->basden); gel(mat,6) = A = ZM_inv(Tr, &dA); /* dA T^-1, primitive */ A = ZM_hnfmodid(A, dA); /* CAVEAT: nf is not complete yet, but the fields needed for * idealtwoelt, zk_scalar_or_multable and idealinv are present ! */ MDI = idealtwoelt(nf, A); gel(MDI,2) = zk_scalar_or_multable(nf, gel(MDI,2)); gel(mat,7) = MDI; if (is_pm1(S->index)) { /* principal ideal (T'), whose norm is |dK| */ D = zk_scalar_or_multable(nf, ZX_deriv(T)); if (typ(D) == t_MAT) D = ZM_hnfmod(D, absi_shallow(S->dK)); } else { GEN c = diviiexact(dA, gcoeff(A,1,1)); D = idealHNF_inv_Z(nf, A); /* (A\cap Z) / A */ if (!is_pm1(c)) D = ZM_Z_mul(D, c); } gel(mat,3) = RM_round_maxrank(F.G); gel(mat,4) = Tr; gel(mat,5) = D; w = S->dKP; if (!w) { w = gel(absZ_factor(S->dK), 1); settyp(w, t_VEC); } gel(mat,8) = w; return nf; } static GEN primes_certify(GEN dK, GEN dKP) { long i, l = lg(dKP); GEN v, w, D = dK; v = vectrunc_init(l); w = vectrunc_init(l); for (i = 1; i < l; i++) { GEN p = gel(dKP,i); vectrunc_append(isprime(p)? w: v, p); (void)Z_pvalrem(D, p, &D); } if (!is_pm1(D)) { D = absi_shallow(D); vectrunc_append(isprime(D)? w: v, D); } return mkvec2(v,w); } GEN nfcertify(GEN nf) { pari_sp av = avma; GEN vw; nf = checknf(nf); vw = primes_certify(nf_get_disc(nf), nf_get_ramified_primes(nf)); return gerepilecopy(av, gel(vw,1)); } /* set *pro to roots of S->T */ static GEN get_red_G(nfmaxord_t *S, GEN *pro) { pari_sp av = avma; GEN G, u, u0 = NULL; long prec, n = degpol(S->T); nffp_t F; prec = nbits2prec(n+32); nffp_init(&F, S, prec); for (;;) { F.prec = prec; make_M_G(&F, 0); G = F.G; if (u0) G = RgM_mul(G, u0); if (DEBUGLEVEL) err_printf("get_red_G: starting LLL, prec = %ld (%ld + %ld)\n", prec + F.extraprec, prec, F.extraprec); if ((u = lllfp(G, 0.99, LLL_KEEP_FIRST))) { if (lg(u)-1 == n) break; /* singular ==> loss of accuracy */ if (u0) u0 = gerepileupto(av, RgM_mul(u0,u)); else u0 = gerepilecopy(av, u); } prec = precdbl(prec) + nbits2extraprec(gexpo(u0)); F.ro = NULL; if (DEBUGLEVEL) pari_warn(warnprec,"get_red_G", prec); } if (u0) u = RgM_mul(u0,u); *pro = F.ro; return u; } /* Compute an LLL-reduced basis for the integer basis of nf(T). * set *pro = roots of x if computed [NULL if not computed] */ static void set_LLL_basis(nfmaxord_t *S, GEN *pro, long flag, double DELTA) { GEN B = S->basis; long N = degpol(S->T); if (S->r1 < 0) { S->r1 = ZX_sturm_irred(S->T); if (odd(N - S->r1)) pari_err_IRREDPOL("set_LLL_basis", S->T); } if (!S->basden) S->basden = get_bas_den(B); *pro = NULL; if (flag & nf_NOLLL) return; if (S->r1 == N) { pari_sp av = avma; GEN u = ZM_lll(make_Tr(S), DELTA, LLL_GRAM|LLL_KEEP_FIRST|LLL_IM); B = gerepileupto(av, RgV_RgM_mul(B, u)); } else B = RgV_RgM_mul(B, get_red_G(S, pro)); S->basis = B; S->basden = get_bas_den(B); } /* = 1 iff |a| > |b| or equality and a > 0 */ static int cmpii_polred(GEN a, GEN b) { int fl = abscmpii(a, b); long sa, sb; if (fl) return fl; sa = signe(a); sb = signe(b); if (sa == sb) return 0; return sa == 1? 1: -1; } static int ZX_cmp(GEN x, GEN y) { return gen_cmp_RgX((void*)cmpii_polred, x, y); } /* current best: ZX x of discriminant *dx, is ZX y better than x ? * (if so update *dx); both x and y are monic */ static int ZX_is_better(GEN y, GEN x, GEN *dx) { pari_sp av; int cmp; GEN d; if (!*dx) *dx = ZX_disc(x); av = avma; d = ZX_disc(y); cmp = abscmpii(d, *dx); if (cmp < 0) { *dx = d; return 1; } return gc_bool(av, cmp? 0: (ZX_cmp(y, x) < 0)); } static void polredbest_aux(nfmaxord_t *S, GEN *pro, GEN *px, GEN *pdx, GEN *pa); /* Seek a simpler, polynomial pol defining the same number field as * x (assumed to be monic at this point) */ static GEN nfpolred(nfmaxord_t *S, GEN *pro) { GEN x = S->T, dx, b, rev; long n = degpol(x), v = varn(x); if (n == 1) { S->T = pol_x(v); *pro = NULL; return scalarpol_shallow(negi(gel(x,2)), v); } polredbest_aux(S, pro, &x, &dx, &b); if (x == S->T) return NULL; /* no improvement */ if (DEBUGLEVEL>1) err_printf("xbest = %Ps\n",x); /* update T */ rev = QXQ_reverse(b, S->T); S->basis = QXV_QXQ_eval(S->basis, rev, x); S->index = sqrti( diviiexact(dx,S->dK) ); S->basden = get_bas_den(S->basis); S->dT = dx; S->T = x; *pro = NULL; /* reset */ return rev; } /* Either nf type or ZX or [monic ZX, data], where data is either an integral * basis (deprecated), or listP data (nfbasis input format) to specify * a set of primes at with the basis order must be maximal. * 1) nf type (or unrecognized): return t_VEC * 2) ZX or [ZX, listP]: return t_POL * 3) [ZX, order basis]: return 0 (deprecated) * incorrect: return -1 */ static long nf_input_type(GEN x) { GEN T, V, DKP = NULL; long i, d, v; switch(typ(x)) { case t_POL: return t_POL; case t_VEC: switch(lg(x)) { case 4: DKP = gel(x,3); case 3: break; default: return t_VEC; /* nf or incorrect */ } T = gel(x,1); V = gel(x,2); if (typ(T) != t_POL) return -1; switch(typ(V)) { case t_INT: case t_MAT: return t_POL; case t_VEC: case t_COL: if (RgV_is_ZV(V)) return t_POL; break; default: return -1; } d = degpol(T); v = varn(T); if (d<1 || !RgX_is_ZX(T) || !isint1(gel(T,d+2)) || lg(V)-1!=d) return -1; for (i = 1; i <= d; i++) { /* check integer basis */ GEN c = gel(V,i); switch(typ(c)) { case t_INT: break; case t_POL: if (varn(c) == v && RgX_is_QX(c) && degpol(c) < d) break; /* fall through */ default: return -1; } } if (DKP && (typ(DKP) != t_VEC || !RgV_is_ZV(DKP))) return -1; return 0; } return t_VEC; /* nf or incorrect */ } /* cater for obsolete nf_PARTIALFACT flag */ static void nfinit_basic_partial(nfmaxord_t *S, GEN T) { if (typ(T) == t_POL) { nfmaxord(S, mkvec2(T,utoipos(500000)), 0); } else nfinit_basic(S, T); } static void nfinit_basic_flag(nfmaxord_t *S, GEN x, long flag) { if (flag & nf_PARTIALFACT) nfinit_basic_partial(S, x); else nfinit_basic(S, x); } /* true nf */ static GEN nf_basden(GEN nf) { GEN zkD = nf_get_zkprimpart(nf), D = nf_get_zkden(nf); D = equali1(D)? NULL: const_vec(lg(zkD)-1, D); return mkvec2(zkD, D); } void nfinit_basic(nfmaxord_t *S, GEN T) { switch (nf_input_type(T)) { case t_POL: nfmaxord(S, T, 0); return; case t_VEC: { /* nf, bnf, bnr */ GEN nf = checknf(T); S->T = S->T0 = nf_get_pol(nf); S->basis = nf_get_zk(nf); /* probably useless */ S->basden = nf_basden(nf); S->index = nf_get_index(nf); S->dK = nf_get_disc(nf); S->dKP = nf_get_ramified_primes(nf); S->dT = mulii(S->dK, sqri(S->index)); S->r1 = nf_get_r1(nf); break; } case 0: /* monic integral polynomial + integer basis (+ ramified primes)*/ S->T = S->T0 = gel(T,1); S->basis = gel(T,2); S->basden = NULL; S->index = NULL; S->dK = NULL; S->dKP = NULL; if (lg(T) == 4) { GEN v = gel(T,3); if (typ(v) == t_COL) v = shallowtrans(v); S->dKP = v; } S->dT = NULL; S->r1 = -1; break; default: /* -1 */ pari_err_TYPE("nfinit_basic", T); } S->dTP = S->dTE = S->dKE = NULL; S->unscale = gen_1; } GEN nfinit_complete(nfmaxord_t *S, long flag, long prec) { GEN nf, unscale = S->unscale, rev = NULL; if (!ZX_is_irred(S->T)) pari_err_IRREDPOL("nfinit",S->T); if (!(flag & nf_RED) && !ZX_is_monic(S->T0)) { pari_warn(warner,"nonmonic polynomial. Result of the form [nf,c]"); flag |= nf_RED | nf_ORIG; } if (!(flag & nf_RED) && !isint1(unscale)) { /* implies lc(x0) = 1 and L := 1/unscale is integral */ long d = degpol(S->T0); GEN L = ginv(unscale); /* x = L^(-deg(x)) x0(L X) */ GEN f = powiu(L, (d*(d-1)) >> 1); S->T = S->T0; /* restore original user-supplied x0, unscale data */ S->unscale = gen_1; S->dT = gmul(S->dT, sqri(f)); S->basis = RgXV_unscale(S->basis, unscale); S->index = gmul(S->index, f); } nfmaxord_complete(S); /* more expensive after set_LLL_basis */ if (flag & nf_RED) { GEN ro; /* lie to polred: more efficient to update *after* modreverse, than to * unscale in the polred subsystem */ S->unscale = gen_1; rev = nfpolred(S, &ro); nf = nfmaxord_to_nf(S, ro, prec); S->unscale = unscale; /* restore */ } else { GEN ro; set_LLL_basis(S, &ro, flag, 0.99); nf = nfmaxord_to_nf(S, ro, prec); } if (flag & nf_ORIG) { if (!rev) { /* no improvement */ long v = varn(S->T); rev = degpol(S->T) == 1? pol_0(v): pol_x(v); } if (!isint1(unscale)) rev = RgX_Rg_div(rev, unscale); nf = mkvec2(nf, mkpolmod(rev, S->T)); } return nf; } /* Initialize the number field defined by the polynomial x (in variable v) * flag & nf_RED: try a polred first. * flag & nf_ORIG: return [nfinit(x), Mod(a,red)], where * Mod(a,red) = Mod(v,x) (i.e return the base change). */ GEN nfinit0(GEN x, long flag,long prec) { const pari_sp av = avma; nfmaxord_t S; if (flag < 0 || flag > 7) pari_err_FLAG("nfinit"); if (checkrnf_i(x)) return rnf_build_nfabs(x, prec); nfinit_basic(&S, x); return gerepilecopy(av, nfinit_complete(&S, flag, prec)); } GEN nfinitred(GEN x, long prec) { return nfinit0(x, nf_RED, prec); } GEN nfinitred2(GEN x, long prec) { return nfinit0(x, nf_RED|nf_ORIG, prec); } GEN nfinit(GEN x, long prec) { return nfinit0(x, 0, prec); } /* 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; } /* true nf */ GEN nfnewprec_shallow(GEN nf, long prec) { GEN m, NF = leafcopy(nf); nffp_t F; F.T = nf_get_pol(nf); F.ro = NULL; F.r1 = nf_get_r1(nf); F.basden = nf_basden(nf); F.extraprec = -1; F.prec = prec; make_M_G(&F, 0); gel(NF,5) = m = leafcopy(gel(NF,5)); gel(m,1) = F.M; gel(m,2) = F.G; gel(NF,6) = F.ro; return NF; } /* true rnf */ GEN rnfnewprec_shallow(GEN rnf, long prec) { GEN RNF = leafcopy(rnf); gel(RNF,10) = nfnewprec_shallow(gel(RNF,10), prec); if (obj_check(RNF, rnf_NFABS)) rnfcomplete(RNF); return RNF; } GEN rnfnewprec(GEN rnf, long prec) { pari_sp av = avma; checkrnf(rnf); return gerepilecopy(av, rnfnewprec_shallow(rnf, prec)); } GEN nfnewprec(GEN nf, long prec) { pari_sp av = avma; GEN z; switch(nftyp(nf)) { default: pari_err_TYPE("nfnewprec", nf); case typ_RNF: z = rnfnewprec_shallow(nf,prec); break; case typ_BNF: z = bnfnewprec_shallow(nf,prec); break; case typ_NF: z = nfnewprec_shallow(nf, prec); break; case typ_BNR: return bnrnewprec(nf,prec); } return gerepilecopy(av, z); } /********************************************************************/ /** **/ /** POLRED **/ /** **/ /********************************************************************/ GEN embednorm_T2(GEN x, long r1) { pari_sp av = avma; GEN p = RgV_sumpart(x, r1); GEN q = RgV_sumpart2(x,r1+1, lg(x)-1); if (q != gen_0) p = gadd(p, gmul2n(q,1)); return avma == av? gcopy(p): gerepileupto(av, p); } /* simplified version of gnorm for scalar, noncomplex inputs, without GC */ static GEN real_norm(GEN x) { switch(typ(x)) { case t_INT: return sqri(x); case t_REAL: return sqrr(x); case t_FRAC: return sqrfrac(x); } pari_err_TYPE("real_norm", x); return NULL;/*LCOV_EXCL_LINE*/ } /* simplified version of gnorm, without GC */ static GEN complex_norm(GEN x) { return typ(x) == t_COMPLEX? cxnorm(x): real_norm(x); } /* return T2(x), argument r1 needed in case x has components whose type * is unexpected, e.g. all of them t_INT for embed(gen_1) */ GEN embed_T2(GEN x, long r1) { pari_sp av = avma; long i, l = lg(x); GEN c, s = NULL, t = NULL; if (typ(gel(x,1)) == t_INT) return muliu(gel(x,1), 2*(l-1)-r1); for (i = 1; i <= r1; i++) { c = real_norm(gel(x,i)); s = s? gadd(s, c): c; } for (; i < l; i++) { c = complex_norm(gel(x,i)); t = t? gadd(t, c): c; } if (t) { t = gmul2n(t,1); s = s? gadd(s,t): t; } return gerepileupto(av, s); } /* return N(x) */ GEN embed_norm(GEN x, long r1) { pari_sp av = avma; long i, l = lg(x); GEN c, s = NULL, t = NULL; if (typ(gel(x,1)) == t_INT) return powiu(gel(x,1), 2*(l-1)-r1); for (i = 1; i <= r1; i++) { c = gel(x,i); s = s? gmul(s, c): c; } for (; i < l; i++) { c = complex_norm(gel(x,i)); t = t? gmul(t, c): c; } if (t) s = s? gmul(s,t): t; return gerepileupto(av, s); } typedef struct { long r1, v, prec; GEN ZKembed; /* embeddings of fincke-pohst-reduced Zk basis */ GEN u; /* matrix giving fincke-pohst-reduced Zk basis */ GEN M; /* embeddings of initial (LLL-reduced) Zk basis */ GEN bound; /* T2 norm of the polynomial defining nf */ long expo_best_disc; /* expo(disc(x)), best generator so far */ } CG_data; /* characteristic pol of x (given by embeddings) */ static GEN get_pol(CG_data *d, GEN x) { long e; GEN g = grndtoi(roots_to_pol_r1(x, d->v, d->r1), &e); return (e > -5)? NULL: g; } /* characteristic pol of x (given as vector on (w_i)) */ static GEN get_polchar(CG_data *d, GEN x) { return get_pol(d, RgM_RgC_mul(d->ZKembed,x)); } /* Choose a canonical polynomial in the pair { Pmin_a, Pmin_{-a} }, i.e. * { z(X), (-1)^(deg z) z(-Z) } and keeping the smallest wrt cmpii_polred * Either leave z alone (return 1) or set z <- (-1)^n z(-X). In place. */ int ZX_canon_neg(GEN z) { long i, s; for (i = lg(z)-2; i >= 2; i -= 2) { /* examine the odd (resp. even) part of z if deg(z) even (resp. odd). */ s = signe(gel(z,i)); if (!s) continue; /* non trivial */ if (s < 0) break; /* z(X) < (-1)^n z(-X) */ for (; i>=2; i-=2) gel(z,i) = negi(gel(z,i)); return 1; } return 0; } /* return a defining polynomial for Q(alpha), v = embeddings of alpha. * Return NULL on failure: discriminant too large or non primitive */ static GEN try_polmin(CG_data *d, nfmaxord_t *S, GEN v, long flag, GEN *ai) { const long best = flag & nf_ABSOLUTE; long ed; pari_sp av = avma; GEN g; if (best) { ed = expo(embed_disc(v, d->r1, LOWDEFAULTPREC)); set_avma(av); if (d->expo_best_disc < ed) return NULL; } else ed = 0; g = get_pol(d, v); /* accuracy too low, compute algebraically */ if (!g) { set_avma(av); g = ZXQ_charpoly(*ai, S->T, varn(S->T)); } g = ZX_radical(g); if (best && degpol(g) != degpol(S->T)) return gc_NULL(av); g = gerepilecopy(av, g); d->expo_best_disc = ed; if (flag & nf_ORIG) { if (ZX_canon_neg(g)) *ai = RgX_neg(*ai); if (!isint1(S->unscale)) *ai = RgX_unscale(*ai, S->unscale); } else (void)ZX_canon_neg(g); if (DEBUGLEVEL>3) err_printf("polred: generator %Ps\n", g); return g; } /* does x generate the correct field ? */ static GEN chk_gen(void *data, GEN x) { pari_sp av = avma, av1; GEN h, g = get_polchar((CG_data*)data,x); if (!g) pari_err_PREC("chk_gen"); av1 = avma; h = ZX_gcd(g, ZX_deriv(g)); if (degpol(h)) return gc_NULL(av); if (DEBUGLEVEL>3) err_printf(" generator: %Ps\n",g); set_avma(av1); return gerepileupto(av, g); } static long chk_gen_prec(long N, long bit) { return prec_fix(nbits2prec(10 + (long)log2((double)N) + bit)); } /* v = [P,A] two vectors (of ZX and ZV resp.) of same length; remove duplicate * polynomials in P, updating A, in place. Among elements having the same * characteristic pol, choose the smallest according to ZV_abscmp */ static void remove_duplicates(GEN v) { GEN x, a, P = gel(v,1), A = gel(v,2); long k, i, l = lg(P); pari_sp av = avma; if (l < 2) return; (void)sort_factor_pol(mkvec2(P, A), cmpii); x = gel(P,1); a = gel(A,1); for (k=1,i=2; iT); double log2rho; GEN ro; set_LLL_basis(S, &ro, 0, 0.9999); /* || polchar ||_oo < 2^e ~ 2 (n * rho)^n, rho = max modulus of root */ log2rho = ro ? (double)gexpo(ro): fujiwara_bound(S->T); e = n * (long)(log2rho + log2((double)n)) + 1; if (e < 0) e = 0; /* can occur if n = 1 */ prec = chk_gen_prec(n, e); nffp_init(F,S,prec); F->ro = ro; make_M_G(F, 1); d->v = varn(S->T); d->expo_best_disc = -1; d->ZKembed = NULL; d->M = NULL; d->u = NULL; d->r1= S->r1; } static GEN findmindisc(GEN y) { GEN x = gel(y,1), dx = NULL; long i, l = lg(y); for (i = 2; i < l; i++) { GEN yi = gel(y,i); if (ZX_is_better(yi,x,&dx)) x = yi; } return x; } /* filter [y,b] from polred_aux: keep a single polynomial of degree n in y * [ the best wrt discriminant ordering ], but keep all imprimitive * polynomials */ static void filter(GEN y, GEN b, long n) { GEN x, a, dx; long i, k = 1, l = lg(y); a = x = dx = NULL; for (i = 1; i < l; i++) { GEN yi = gel(y,i), ai = gel(b,i); if (degpol(yi) == n) { if (!dx) dx = ZX_disc(yi); else if (!ZX_is_better(yi,x,&dx)) continue; x = yi; a = ai; continue; } gel(y,k) = yi; gel(b,k) = ai; k++; } if (dx) { gel(y,k) = x; gel(b,k) = a; k++; } setlg(y, k); setlg(b, k); } static GEN polred_aux(nfmaxord_t *S, GEN *pro, long flag) { /* only keep polynomials of max degree and best discriminant */ const long best = flag & nf_ABSOLUTE; const long orig = flag & nf_ORIG; GEN M, b, y, x = S->T; long maxi, i, j, k, v = varn(x), n = lg(S->basis)-1; nffp_t F; CG_data d; if (n == 1) { if (!best) { GEN X = pol_x(v); return orig? mkmat2(mkcol(X),mkcol(gen_1)): mkvec(X); } else return orig? trivial_fact(): cgetg(1,t_VEC); } polred_init(S, &F, &d); if (pro) *pro = F.ro; M = F.M; if (best) { if (!S->dT) S->dT = ZX_disc(S->T); d.expo_best_disc = expi(S->dT); } /* n + 2 sum_{1 <= i <= n} n-i = n + n(n-1) = n*n */ y = cgetg(n*n + 1, t_VEC); b = cgetg(n*n + 1, t_COL); k = 1; if (!best) { gel(y,1) = pol_x(v); gel(b,1) = gen_0; k++; } for (i = 2; i <= n; i++) { GEN ch, ai; ai = gel(S->basis,i); ch = try_polmin(&d, S, gel(M,i), flag, &ai); if (ch) { gel(y,k) = ch; gel(b,k) = ai; k++; } } maxi = minss(n, 3); for (i = 1; i <= maxi; i++) for (j = i+1; j <= n; j++) { GEN ch, ai, v; ai = gadd(gel(S->basis,i), gel(S->basis,j)); v = RgV_add(gel(M,i), gel(M,j)); /* defining polynomial for Q(w_i+w_j) */ ch = try_polmin(&d, S, v, flag, &ai); if (ch) { gel(y,k) = ch; gel(b,k) = ai; k++; } ai = gsub(gel(S->basis,i), gel(S->basis,j)); v = RgV_sub(gel(M,i), gel(M,j)); /* defining polynomial for Q(w_i-w_j) */ ch = try_polmin(&d, S, v, flag, &ai); if (ch) { gel(y,k) = ch; gel(b,k) = ai; k++; } } setlg(y, k); setlg(b, k); filter(y, b, n); if (!orig) return gen_sort_uniq(y, (void*)cmpii, &gen_cmp_RgX); settyp(y, t_COL); (void)sort_factor_pol(mkmat2(y, b), cmpii); return mkmat2(b, y); } /* FIXME: obsolete */ static GEN Polred(GEN x, long flag, GEN fa) { pari_sp av = avma; nfmaxord_t S; if (fa) nfinit_basic(&S, mkvec2(x,fa)); else nfinit_basic_flag(&S, x, flag); return gerepilecopy(av, polred_aux(&S, NULL, flag)); } /* finds "best" polynomial in polred_aux list, defaulting to S->T if none of * them is primitive. *px a ZX, characteristic polynomial of Mod(*pb,S->T), * *pdx its discriminant if pdx != NULL. Set *pro = polroots(S->T) */ static void polredbest_aux(nfmaxord_t *S, GEN *pro, GEN *px, GEN *pdx, GEN *pb) { GEN y, dx, x = S->T; /* default value */ long i, l; y = polred_aux(S, pro, pb? nf_ORIG|nf_ABSOLUTE: nf_ABSOLUTE); dx = S->dT; if (pb) { GEN a, b = deg1pol_shallow(S->unscale, gen_0, varn(x)); a = gel(y,1); l = lg(a); y = gel(y,2); for (i=1; i 1) pari_err_FLAG("polredbest"); return gerepilecopy(av, polredbest_i(T, flag)); } /* DEPRECATED: backward compatibility */ GEN polred0(GEN x, long flag, GEN fa) { long fl = 0; if (flag & 1) fl |= nf_PARTIALFACT; if (flag & 2) fl |= nf_ORIG; return Polred(x, fl, fa); } GEN polredord(GEN x) { pari_sp av = avma; GEN v, lt; long i, n, vx; if (typ(x) != t_POL) pari_err_TYPE("polredord",x); x = Q_primpart(x); RgX_check_ZX(x,"polredord"); n = degpol(x); if (n <= 0) pari_err_CONSTPOL("polredord"); if (n == 1) return gerepilecopy(av, mkvec(x)); lt = leading_coeff(x); vx = varn(x); if (is_pm1(lt)) { if (signe(lt) < 0) x = ZX_neg(x); v = pol_x_powers(n, vx); } else { GEN L; /* basis for Dedekind order */ v = cgetg(n+1, t_VEC); gel(v,1) = scalarpol_shallow(lt, vx); for (i = 2; i <= n; i++) gel(v,i) = RgX_Rg_add(RgX_mulXn(gel(v,i-1), 1), gel(x,n+3-i)); gel(v,1) = pol_1(vx); x = ZX_Q_normalize(x, &L); v = gsubst(v, vx, monomial(ginv(L),1,vx)); for (i=2; i <= n; i++) if (Q_denom(gel(v,i)) == gen_1) gel(v,i) = pol_xn(i-1, vx); } return gerepileupto(av, polred(mkvec2(x, v))); } GEN polred(GEN x) { return Polred(x, 0, NULL); } GEN smallpolred(GEN x) { return Polred(x, nf_PARTIALFACT, NULL); } GEN factoredpolred(GEN x, GEN fa) { return Polred(x, 0, fa); } GEN polred2(GEN x) { return Polred(x, nf_ORIG, NULL); } GEN smallpolred2(GEN x) { return Polred(x, nf_PARTIALFACT|nf_ORIG, NULL); } GEN factoredpolred2(GEN x, GEN fa) { return Polred(x, nf_PARTIALFACT, fa); } /********************************************************************/ /** **/ /** POLREDABS **/ /** **/ /********************************************************************/ /* set V[k] := matrix of multiplication by nk.zk[k] */ static GEN set_mulid(GEN V, GEN M, GEN Mi, long r1, long r2, long N, long k) { GEN v, Mk = cgetg(N+1, t_MAT); long i, e; for (i = 1; i < k; i++) gel(Mk,i) = gmael(V, i, k); for ( ; i <=N; i++) { v = vecmul(gel(M,k), gel(M,i)); v = RgM_RgC_mul(Mi, split_realimag(v, r1, r2)); gel(Mk,i) = grndtoi(v, &e); if (e > -5) return NULL; } gel(V,k) = Mk; return Mk; } static GEN ZM_image_shallow(GEN M, long *pr) { long j, k, r; GEN y, d = ZM_pivots(M, &k); r = lg(M)-1 - k; y = cgetg(r+1,t_MAT); for (j=k=1; j<=r; k++) if (d[k]) gel(y,j++) = gel(M,k); *pr = r; return y; } /* U = base change matrix, R = Cholesky form of the quadratic form [matrix * Q from algo 2.7.6] */ static GEN chk_gen_init(FP_chk_fun *chk, GEN R, GEN U) { CG_data *d = (CG_data*)chk->data; GEN P, V, D, inv, bound, S, M; long N = lg(U)-1, r1 = d->r1, r2 = (N-r1)>>1; long i, j, prec, firstprim = 0, skipfirst = 0; pari_sp av; d->u = U; d->ZKembed = M = RgM_mul(d->M, U); av = avma; bound = d->bound; D = cgetg(N+1, t_VECSMALL); for (i = 1; i <= N; i++) { pari_sp av2 = avma; P = get_pol(d, gel(M,i)); if (!P) pari_err_PREC("chk_gen_init"); P = gerepilecopy(av2, ZX_radical(P)); D[i] = degpol(P); if (D[i] == N) { /* primitive element */ GEN B = embed_T2(gel(M,i), r1); if (!firstprim) firstprim = i; /* index of first primitive element */ if (DEBUGLEVEL>2) err_printf("chk_gen_init: generator %Ps\n",P); if (gcmp(B,bound) < 0) bound = gerepileuptoleaf(av2, B); } else { if (DEBUGLEVEL>2) err_printf("chk_gen_init: subfield %Ps\n",P); if (firstprim) { /* cycle basis vectors so that primitive elements come last */ GEN u = d->u, e = M; GEN te = gel(e,i), tu = gel(u,i), tR = gel(R,i); long tS = D[i]; for (j = i; j > firstprim; j--) { u[j] = u[j-1]; e[j] = e[j-1]; R[j] = R[j-1]; D[j] = D[j-1]; } gel(u,firstprim) = tu; gel(e,firstprim) = te; gel(R,firstprim) = tR; D[firstprim] = tS; firstprim++; } } } if (!firstprim) { /* try (a little) to find primitive elements to improve bound */ GEN x = cgetg(N+1, t_VECSMALL); if (DEBUGLEVEL>1) err_printf("chk_gen_init: difficult field, trying random elements\n"); for (i = 0; i < 10; i++) { GEN e, B; for (j = 1; j <= N; j++) x[j] = (long)random_Fl(7) - 3; e = RgM_zc_mul(M, x); B = embed_T2(e, r1); if (gcmp(B,bound) >= 0) continue; P = get_pol(d, e); if (!P) pari_err_PREC( "chk_gen_init"); if (!ZX_is_squarefree(P)) continue; if (DEBUGLEVEL>2) err_printf("chk_gen_init: generator %Ps\n",P); bound = B ; } } if (firstprim != 1) { inv = ginv( split_realimag(M, r1, r2) ); /*TODO: use QR?*/ V = gel(inv,1); for (i = 2; i <= r1+r2; i++) V = gadd(V, gel(inv,i)); /* V corresponds to 1_Z */ V = grndtoi(V, &j); if (j > -5) pari_err_BUG("precision too low in chk_gen_init"); S = mkmat(V); /* 1 */ V = cgetg(N+1, t_VEC); for (i = 1; i <= N; i++,skipfirst++) { /* S = Q-basis of subfield generated by nf.zk[1..i-1] */ GEN Mx, M2; long j, k, h, rkM, dP = D[i]; if (dP == N) break; /* primitive */ Mx = set_mulid(V, M, inv, r1, r2, N, i); if (!Mx) break; /* prec. problem. Stop */ if (dP == 1) continue; rkM = lg(S)-1; M2 = cgetg(N+1, t_MAT); /* we will add to S the elts of M2 */ gel(M2,1) = col_ei(N, i); /* nf.zk[i] */ k = 2; for (h = 1; h < dP; h++) { long r; /* add to M2 the elts of S * nf.zk[i] */ for (j = 1; j <= rkM; j++) gel(M2,k++) = ZM_ZC_mul(Mx, gel(S,j)); setlg(M2, k); k = 1; S = ZM_image_shallow(shallowconcat(S,M2), &r); if (r == rkM) break; if (r > rkM) { rkM = r; if (rkM == N) break; } } if (rkM == N) break; /* Q(w[1],...,w[i-1]) is a strict subfield of nf */ } } /* x_1,...,x_skipfirst generate a strict subfield [unless N=skipfirst=1] */ chk->skipfirst = skipfirst; if (DEBUGLEVEL>2) err_printf("chk_gen_init: skipfirst = %ld\n",skipfirst); /* should be DEF + gexpo( max_k C^n_k (bound/k)^(k/2) ) */ bound = gerepileuptoleaf(av, bound); prec = chk_gen_prec(N, (gexpo(bound)*N)/2); if (DEBUGLEVEL) err_printf("chk_gen_init: new prec = %ld (initially %ld)\n", prec, d->prec); if (prec > d->prec) pari_err_BUG("polredabs (precision problem)"); if (prec < d->prec) d->ZKembed = gprec_w(M, prec); return bound; } static GEN polredabs_i(GEN x, nfmaxord_t *S, GEN *u, long flag) { FP_chk_fun chk = { &chk_gen, &chk_gen_init, NULL, NULL, 0 }; nffp_t F; CG_data d; GEN v, y, a; long i, l; nfinit_basic_flag(S, x, flag); x = S->T0; if (degpol(x) == 1) { long vx = varn(x); *u = NULL; return mkvec2(mkvec( pol_x(vx) ), mkvec( deg1pol_shallow(gen_1, negi(gel(S->T,2)), vx) )); } chk.data = (void*)&d; polred_init(S, &F, &d); d.bound = embed_T2(F.ro, d.r1); if (realprec(d.bound) > F.prec) d.bound = rtor(d.bound, F.prec); for (;;) { GEN R = R_from_QR(F.G, F.prec); if (R) { d.prec = F.prec; d.M = F.M; v = fincke_pohst(mkvec(R),NULL,-1, 0, &chk); if (v) break; } F.prec = precdbl(F.prec); F.ro = NULL; make_M_G(&F, 1); if (DEBUGLEVEL) pari_warn(warnprec,"polredabs0",F.prec); } y = gel(v,1); a = gel(v,2); l = lg(a); for (i = 1; i < l; i++) /* normalize wrt z -> -z */ if (ZX_canon_neg(gel(y,i)) && (flag & (nf_ORIG|nf_RAW))) gel(a,i) = ZC_neg(gel(a,i)); *u = d.u; return v; } GEN polredabs0(GEN x, long flag) { pari_sp av = avma; GEN Y, A, u, v; nfmaxord_t S; long i, l; v = polredabs_i(x, &S, &u, flag); remove_duplicates(v); Y = gel(v,1); A = gel(v,2); l = lg(A); if (l == 1) pari_err_BUG("polredabs (missing vector)"); if (DEBUGLEVEL) err_printf("Found %ld minimal polynomials.\n",l-1); if (!(flag & nf_ALL)) { GEN y = findmindisc(Y); for (i = 1; i < l; i++) if (ZX_equal(gel(Y,i), y)) break; Y = mkvec(gel(Y,i)); A = mkvec(gel(A,i)); l = 2; } if (flag & (nf_RAW|nf_ORIG)) for (i = 1; i < l; i++) { GEN y = gel(Y,i), a = gel(A,i); if (u) a = RgV_RgC_mul(S.basis, ZM_ZC_mul(u, a)); if (flag & nf_ORIG) { a = QXQ_reverse(a, S.T); if (!isint1(S.unscale)) a = gdiv(a, S.unscale); /* not RgX_Rg_div */ a = mkpolmod(a,y); } gel(Y,i) = mkvec2(y, a); } return gerepilecopy(av, (flag & nf_ALL)? Y: gel(Y,1)); } GEN polredabsall(GEN x, long flun) { return polredabs0(x, flun | nf_ALL); } GEN polredabs(GEN x) { return polredabs0(x,0); } GEN polredabs2(GEN x) { return polredabs0(x,nf_ORIG); } /* relative polredabs/best. Returns relative polynomial by default (flag = 0) * flag & nf_ORIG: + element (base change) * flag & nf_ABSOLUTE: absolute polynomial */ static GEN rnfpolred_i(GEN nf, GEN R, long flag, long best) { const char *f = best? "rnfpolredbest": "rnfpolredabs"; const long abs = ((flag & nf_ORIG) && (flag & nf_ABSOLUTE)); GEN listP = NULL, red, pol, A, P, T, rnfeq; pari_sp av = avma; long even = 0; if (typ(R) == t_VEC) { if (lg(R) != 3) pari_err_TYPE(f,R); listP = gel(R,2); R = gel(R,1); } if (typ(R) != t_POL) pari_err_TYPE(f,R); nf = checknf(nf); T = nf_get_pol(nf); R = RgX_nffix(f, T, R, 0); if (best || (flag & nf_PARTIALFACT)) { rnfeq = abs? nf_rnfeq(nf, R): nf_rnfeqsimple(nf, R); pol = gel(rnfeq,1); if (listP) pol = mkvec2(pol, listP); red = best? polredbest_i(pol, abs? 1: 2) : polredabs0(pol, (abs? nf_ORIG: nf_RAW)|nf_PARTIALFACT); P = gel(red,1); A = gel(red,2); } else { nfmaxord_t S; GEN rnf, u, v, y, a; long i, j, l; pari_timer ti; if (DEBUGLEVEL>1) timer_start(&ti); rnf = rnfinit(nf, R); rnfeq = rnf_get_map(rnf); pol = rnf_zkabs(rnf); if (DEBUGLEVEL>1) timer_printf(&ti, "absolute basis"); v = polredabs_i(pol, &S, &u, nf_ORIG); pol = gel(pol,1); y = gel(v,1); P = findmindisc(y); a = gel(v,2); l = lg(y); A = cgetg(l, t_VEC); for (i = j = 1; i < l; i++) if (ZX_equal(gel(y,i),P)) gel(A,j++) = gel(a,i); setlg(A,j); /* mod(A[i], pol) are all roots of P in Q[X]/(pol) */ even = j > 2 && !odd(degpol(P)) && !odd(ZX_deflate_order(P)); for (i = 1; i < j; i++) { GEN t = gel(A,i); if (u) t = ZM_ZC_mul(u,t); gel(A,i) = RgV_RgC_mul(S.basis, t); } } if (DEBUGLEVEL>1) err_printf("reduced absolute generator: %Ps\n",P); if (flag & nf_ABSOLUTE) { if (flag & nf_ORIG) { GEN a = gel(rnfeq,2); /* Mod(a,pol) root of T */ GEN k = gel(rnfeq,3); /* Mod(variable(R),R) + k*a root of pol */ if (typ(A) == t_VEC) A = gel(A,1); /* any root will do */ a = RgX_RgXQ_eval(a, lift_shallow(A), P); /* Mod(a, P) root of T */ P = mkvec3(P, mkpolmod(a,P), gsub(A, gmul(k,a))); } return gerepilecopy(av, P); } if (typ(A) != t_VEC) { A = eltabstorel_lift(rnfeq, A); P = lift_if_rational( RgXQ_charpoly(A, R, varn(R)) ); } else { /* canonical factor */ long i, l = lg(A), v = varn(R); GEN besta = NULL; for (i = 1; i < l; i++) { GEN a = eltabstorel_lift(rnfeq, gel(A,i)); GEN p = lift_if_rational( RgXQ_charpoly(a, R, v) ); if (even) { GEN q = RgX_unscale(p, gen_m1); if (cmp_universal(q, p) < 0) { p = q; a = gneg(a); } } if (i == 1 || cmp_universal(p, P) < 0) { P = p; besta = a; } } A = besta; } if (flag & nf_ORIG) P = mkvec2(P, mkpolmod(RgXQ_reverse(A,R),P)); return gerepilecopy(av, P); } GEN rnfpolredabs(GEN nf, GEN R, long flag) { return rnfpolred_i(nf,R,flag, 0); } GEN rnfpolredbest(GEN nf, GEN R, long flag) { if (flag < 0 || flag > 3) pari_err_FLAG("rnfpolredbest"); return rnfpolred_i(nf,R,flag, 1); } pari-2.17.2/src/basemath/gen2.c0000644000175000017500000022546414760137411014557 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /********************************************************************/ /** **/ /** GENERIC OPERATIONS **/ /** (second part) **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" /*********************************************************************/ /** **/ /** MAP FUNCTIONS WITH GIVEN PROTOTYPES **/ /** **/ /*********************************************************************/ GEN map_proto_G(GEN (*f)(GEN), GEN x) { if (is_matvec_t(typ(x))) pari_APPLY_same(map_proto_G(f, gel(x,i))); return f(x); } GEN map_proto_lG(long (*f)(GEN), GEN x) { if (is_matvec_t(typ(x))) pari_APPLY_same(map_proto_lG(f, gel(x,i))); return stoi(f(x)); } GEN map_proto_lGL(long (*f)(GEN,long), GEN x, long y) { if (is_matvec_t(typ(x))) pari_APPLY_same(map_proto_lGL(f,gel(x,i),y)); return stoi(f(x,y)); } static GEN _domul(void *data, GEN x, GEN y) { GEN (*mul)(GEN,GEN)=(GEN (*)(GEN,GEN)) data; return mul(x,y); } GEN gassoc_proto(GEN (*f)(GEN,GEN), GEN x, GEN y) { if (!y) { pari_sp av = avma; switch(typ(x)) { case t_LIST: x = list_data(x); if (!x) return gen_1; case t_VEC: case t_COL: break; default: pari_err_TYPE("association",x); } return gerepileupto(av, gen_product(x, (void *)f, _domul)); } return f(x,y); } /*******************************************************************/ /* */ /* CREATION OF A P-ADIC GEN */ /* */ /*******************************************************************/ GEN cgetp(GEN x) { GEN y = cgetg(5,t_PADIC); y[1] = (x[1]&PRECPBITS) | _evalvalp(0); gel(y,2) = icopy(gel(x,2)); gel(y,3) = icopy(gel(x,3)); gel(y,4) = cgeti(lgefint(gel(x,3))); return y; } /*******************************************************************/ /* */ /* SIZES */ /* */ /*******************************************************************/ long glength(GEN x) { long tx = typ(x); switch(tx) { case t_INT: return lgefint(x)-2; case t_LIST: { GEN L = list_data(x); return L? lg(L)-1: 0; } case t_REAL: return signe(x)? lg(x)-2: 0; case t_STR: return strlen( GSTR(x) ); case t_VECSMALL: return lg(x)-1; } return lg(x) - lontyp[tx]; } long gtranslength(GEN x) { switch(typ(x)) { case t_VEC: case t_COL: return lg(x)-1; case t_MAT: return lg(x)==1 ? 0: nbrows(x); default: pari_err_TYPE("trans",x); return 0; /* LCOV_EXCL_LINE */ } } GEN matsize(GEN x) { long L = lg(x) - 1; switch(typ(x)) { case t_VEC: return mkvec2s(1, L); case t_COL: return mkvec2s(L, 1); case t_MAT: return mkvec2s(L? nbrows(x): 0, L); } pari_err_TYPE("matsize",x); return NULL; /* LCOV_EXCL_LINE */ } /*******************************************************************/ /* */ /* CONVERSION GEN --> 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; return gc_long(av, itos(ground(x))); } case t_COMPLEX: if (gequal0(gel(x,2))) return gtolong(gel(x,1)); break; case t_QUAD: if (gequal0(gel(x,3))) return gtolong(gel(x,2)); break; } pari_err_TYPE("gtolong",x); return 0; /* LCOV_EXCL_LINE */ } /*******************************************************************/ /* */ /* COMPARISONS */ /* */ /*******************************************************************/ static void chk_true_err() { GEN E = pari_err_last(); switch(err_get_num(E)) { case e_STACK: case e_MEM: case e_ALARM: pari_err(0, E); /* rethrow */ } } /* x - y == 0 or undefined */ static int gequal_try(GEN x, GEN y) { int i; pari_CATCH(CATCH_ALL) { chk_true_err(); return 0; } pari_TRY { i = gequal0(gadd(x, gneg_i(y))); } pari_ENDCATCH; return i; } /* x + y == 0 or undefined */ static int gmequal_try(GEN x, GEN y) { int i; pari_CATCH(CATCH_ALL) { chk_true_err(); return 0; } pari_TRY { i = gequal0(gadd(x, y)); } pari_ENDCATCH; return i; } 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; } GEN gisexactzero(GEN g) { long i, lx; GEN a, b; switch (typ(g)) { case t_INT: return !signe(g)? g: NULL; case t_INTMOD: return !signe(gel(g,2))? g: NULL; case t_COMPLEX: a = gisexactzero(gel(g,1)); if (!a) return NULL; b = gisexactzero(gel(g,2)); if (!b) return NULL; return ggcd(a,b); case t_FFELT: return FF_equal0(g)? g: NULL; case t_QUAD: a = gisexactzero(gel(g,2)); if (!a) return NULL; b = gisexactzero(gel(g,3)); if (!b) return NULL; return ggcd(a,b); case t_POLMOD: return gisexactzero(gel(g,2)); case t_POL: lx = lg(g); /* cater for Mod(0,2)*x^0 */ if (lx == 2) return gen_0; if (lx == 3) return gisexactzero(gel(g,2)); return NULL; case t_RFRAC: return gisexactzero(gel(g,1)); /* may occur: Mod(0,2)/x */ case t_VEC: case t_COL: case t_MAT: a = gen_0; for (i=lg(g)-1; i; i--) { b = gisexactzero(gel(g,i)); if (!b) return NULL; a = ggcd(a, b); } return a; } return NULL; } int isrationalzero(GEN g) { long i; switch (typ(g)) { case t_INT: return !signe(g); case t_COMPLEX: return isintzero(gel(g,1)) && isintzero(gel(g,2)); case t_QUAD: return isintzero(gel(g,2)) && isintzero(gel(g,3)); case t_POLMOD: return isrationalzero(gel(g,2)); case t_POL: return lg(g) == 2; case t_VEC: case t_COL: case t_MAT: for (i=lg(g)-1; i; i--) if (!isrationalzero(gel(g,i))) return 0; return 1; } return 0; } int gequal0(GEN x) { switch(typ(x)) { case t_INT: case t_REAL: case t_POL: case t_SER: return !signe(x); case t_INTMOD: return !signe(gel(x,2)); case t_FFELT: return FF_equal0(x); case t_COMPLEX: /* is 0 iff norm(x) would be 0 (can happen with Re(x) and Im(x) != 0 * only if Re(x) and Im(x) are of type t_REAL). See mp.c:addrr(). */ if (gequal0(gel(x,1))) { if (gequal0(gel(x,2))) return 1; if (typ(gel(x,1))!=t_REAL || typ(gel(x,2))!=t_REAL) return 0; return (expo(gel(x,1))>=expo(gel(x,2))); } if (gequal0(gel(x,2))) { if (typ(gel(x,1))!=t_REAL || typ(gel(x,2))!=t_REAL) return 0; return (expo(gel(x,2))>=expo(gel(x,1))); } return 0; case t_PADIC: return !signe(gel(x,4)); case t_QUAD: return gequal0(gel(x,2)) && gequal0(gel(x,3)); case t_POLMOD: return gequal0(gel(x,2)); case t_RFRAC: return gequal0(gel(x,1)); case t_VEC: case t_COL: case t_MAT: { long i; for (i=lg(x)-1; i; i--) if (!gequal0(gel(x,i))) return 0; return 1; } } return 0; } /* x a t_POL or t_SER, return 1 if test(coeff(X,d)) is true and * coeff(X,i) = 0 for all i != d. Return 0 (false) otherwise */ static int is_monomial_test(GEN x, long d, int(*test)(GEN)) { long i, l = lg(x); if (typ(x) == t_SER) { /* "0" * x^v * (1+O(x)) ? v <= 0 or null ring */ if (l == 3 && isexactzero(gel(x,2))) return d >= 2 || test(gel(x,2)); if (d < 2) return 0; /* v > 0 */ } if (d >= l) { if (typ(x) == t_POL) return 0; /* l = 2 */ /* t_SER, v = 2-d <= 0 */ if (!signe(x)) return 1; } else if (!test(gel(x,d))) return 0; for (i = 2; i < l; i++) /* 2 <= d < l */ if (i != d && !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 || !test(gel(x,1))) return 0; for (i = 2; i < l; i++) if (!gequal0(gel(x,i))) return 0; return 1; } static int mat_test(GEN x, int(*test)(GEN)) { long i, j, l = lg(x); if (l == 1) return 1; if (l != lgcols(x)) return 0; for (i = 1; i < l; i++) for (j = 1; j < l; j++) if (i == j) { if (!test(gcoeff(x,i,i))) return 0; } else { if (!gequal0(gcoeff(x,i,j))) return 0; } return 1; } /* returns 1 whenever x = 1, and 0 otherwise */ int gequal1(GEN x) { switch(typ(x)) { case t_INT: return equali1(x); case t_REAL: { long s = signe(x); if (!s) return expo(x) >= 0; return s > 0 ? absrnz_equal1(x): 0; } case t_INTMOD: return is_pm1(gel(x,2)) || is_pm1(gel(x,1)); case t_POLMOD: return !degpol(gel(x,1)) || 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: if (!signe(gel(x,4))) return valp(x) <= 0; return valp(x) == 0 && gequal1(gel(x,4)); case t_QUAD: return gequal1(gel(x,2)) && gequal0(gel(x,3)); case t_POL: return is_monomial_test(x, 2, &gequal1); case t_SER: return is_monomial_test(x, 2 - valser(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; GEN t; switch(typ(x)) { case t_INT: return equalim1(x); case t_REAL: { long s = signe(x); if (!s) return expo(x) >= 0; return s < 0 ? absrnz_equal1(x): 0; } case t_INTMOD: av = avma; return gc_bool(av, equalii(addui(1,gel(x,2)), gel(x,1))); 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: t = gel(x,4); if (!signe(t)) return valp(x) <= 0; av = avma; return gc_bool(av, !valp(x) && equalii(addui(1,t), gel(x,3))); case t_POLMOD: return !degpol(gel(x,1)) || gequalm1(gel(x,2)); case t_POL: return is_monomial_test(x, 2, &gequalm1); case t_SER: return is_monomial_test(x, 2 - valser(x), &gequalm1); case t_RFRAC: av = avma; return gc_bool(av, gmequal_try(gel(x,1), gel(x,2))); case t_COL: return col_test(x, &gequalm1); case t_MAT: return mat_test(x, &gequalm1); } return 0; } int gequalX(GEN x) { return typ(x) == t_POL && lg(x) == 4 && isintzero(gel(x,2)) && isint1(gel(x,3)); } static int cmp_str(const char *x, const char *y) { int f = strcmp(x, y); return f > 0? 1 : f? -1: 0; } static int cmp_universal_rec(GEN x, GEN y, long i0) { long i, lx = lg(x), ly = lg(y); if (lx < ly) return -1; if (lx > ly) return 1; for (i = i0; i < lx; i++) { int f = cmp_universal(gel(x,i), gel(y,i)); if (f) return f; } return 0; } /* Universal "meaningless" comparison function. Transitive, returns 0 iff * gidentical(x,y) */ int cmp_universal(GEN x, GEN y) { long lx, ly, i, tx = typ(x), ty = typ(y); if (tx < ty) return -1; if (ty < tx) return 1; switch(tx) { case t_INT: return cmpii(x,y); case t_STR: return cmp_str(GSTR(x),GSTR(y)); case t_REAL: case t_VECSMALL: lx = lg(x); ly = lg(y); if (lx < ly) return -1; if (lx > ly) return 1; for (i = 1; i < lx; i++) { if (x[i] < y[i]) return -1; if (x[i] > y[i]) return 1; } return 0; case t_POL: { long X = x[1] & (VARNBITS|SIGNBITS); long Y = y[1] & (VARNBITS|SIGNBITS); if (X < Y) return -1; if (X > Y) return 1; return cmp_universal_rec(x, y, 2); } 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: { long tx = list_typ(x), ty = list_typ(y); GEN vx, vy; pari_sp av; if (tx < ty) return -1; if (tx > ty) return 1; vx = list_data(x); vy = list_data(y); if (!vx) return vy? -1: 0; if (!vy) return 1; av = avma; if (tx == t_LIST_MAP) { vx = maptomat_shallow(x); vy = maptomat_shallow(y); } return gc_int(av, cmp_universal_rec(vx, vy, 1)); } default: return cmp_universal_rec(x, y, lontyp[tx]); } } static int cmpfrac(GEN x, GEN y) { pari_sp av = avma; GEN a = gel(x,1), b = gel(x,2); GEN c = gel(y,1), d = gel(y,2); return gc_bool(av, cmpii(mulii(a, d), mulii(b, c))); } static int cmpifrac(GEN a, GEN y) { pari_sp av = avma; GEN c = gel(y,1), d = gel(y,2); return gc_int(av, cmpii(mulii(a, d), c)); } static int cmprfrac(GEN a, GEN y) { pari_sp av = avma; GEN c = gel(y,1), d = gel(y,2); return gc_int(av, cmpri(mulri(a, d), c)); } static int cmpgen(GEN x, GEN y) { pari_sp av = avma; return gc_int(av, gsigne(gsub(x,y))); } /* returns the sign of x - y when it makes sense. 0 otherwise */ int gcmp(GEN x, GEN y) { long tx = typ(x), ty = typ(y); if (tx == ty) /* generic case */ switch(tx) { case t_INT: return cmpii(x, y); case t_REAL: return cmprr(x, y); case t_FRAC: return cmpfrac(x, y); case t_QUAD: return cmpgen(x, y); case t_STR: return cmp_str(GSTR(x), GSTR(y)); case t_INFINITY: { long sx = inf_get_sign(x), sy = inf_get_sign(y); if (sx < sy) return -1; if (sx > sy) return 1; return 0; } } if (ty == t_INFINITY) return -inf_get_sign(y); switch(tx) { case t_INT: switch(ty) { case t_REAL: return cmpir(x, y); case t_FRAC: return cmpifrac(x, y); case t_QUAD: return cmpgen(x, y); } break; case t_REAL: switch(ty) { case t_INT: return cmpri(x, y); case t_FRAC: return cmprfrac(x, y); case t_QUAD: return cmpgen(x, y); } break; case t_FRAC: switch(ty) { case t_INT: return -cmpifrac(y, x); case t_REAL: return -cmprfrac(y, x); case t_QUAD: return cmpgen(x, y); } break; case t_QUAD: return cmpgen(x, y); case t_INFINITY: return inf_get_sign(x); } pari_err_TYPE2("comparison",x,y); return 0;/*LCOV_EXCL_LINE*/ } int gcmpsg(long s, GEN y) { switch(typ(y)) { case t_INT: return cmpsi(s,y); case t_REAL: return cmpsr(s,y); case t_FRAC: { pari_sp av = avma; return gc_int(av, cmpii(mulsi(s,gel(y,2)), gel(y,1))); } case t_QUAD: { pari_sp av = avma; return gc_int(av, gsigne(gsubsg(s, y))); } case t_INFINITY: return -inf_get_sign(y); } pari_err_TYPE2("comparison",stoi(s),y); return 0; /* LCOV_EXCL_LINE */ } static long roughtype(GEN x) { switch(typ(x)) { case t_MAT: return t_MAT; case t_VEC: case t_COL: return t_VEC; case t_VECSMALL: return t_VECSMALL; default: return t_INT; } } static int lexcmpsg(long x, GEN y); static int lexcmpgs(GEN x, long y) { return -lexcmpsg(y,x); } /* lexcmp(stoi(x),y), y t_VEC/t_COL/t_MAT */ static int lexcmp_s_matvec(long x, GEN y) { int fl; if (lg(y)==1) return 1; fl = lexcmpsg(x,gel(y,1)); if (fl) return fl; return -1; } /* x a scalar, y a t_VEC/t_COL/t_MAT */ static int lexcmp_scal_matvec(GEN x, GEN y) { int fl; if (lg(y)==1) return 1; fl = lexcmp(x,gel(y,1)); if (fl) return fl; return -1; } /* x a scalar, y a t_VECSMALL */ static int lexcmp_scal_vecsmall(GEN x, GEN y) { int fl; if (lg(y)==1) return 1; fl = lexcmpgs(x, y[1]); if (fl) return fl; return -1; } /* tx = ty = t_MAT, or x and y are both vect_t */ static int lexcmp_similar(GEN x, GEN y) { long i, lx = lg(x), ly = lg(y), l = minss(lx,ly); for (i=1; i y[1])? 1: -1; default: return gcmpsg(x,y); } } /* as gcmp for vector/matrices, using lexicographic ordering on components */ static int lexcmp_i(GEN x, GEN y) { const long tx = roughtype(x), ty = roughtype(y); if (tx == ty) switch(tx) { case t_MAT: case t_VEC: return lexcmp_similar(x,y); case t_VECSMALL: return vecsmall_lexcmp(x,y); default: return gcmp(x,y); } if (tx == t_VECSMALL) return lexcmp_vecsmall_other(x,y,ty); if (ty == t_VECSMALL) return -lexcmp_vecsmall_other(y,x,tx); if (tx == t_INT) return lexcmp_scal_matvec(x,y); /*scalar*/ if (ty == t_INT) return -lexcmp_scal_matvec(y,x); if (ty==t_MAT) return lexcmp_vec_mat(x,y); return -lexcmp_vec_mat(y,x); /*tx==t_MAT*/ } int lexcmp(GEN x, GEN y) { pari_sp av = avma; if (typ(x) == t_COMPLEX) { x = mkvec2(gel(x,1), gel(x,2)); if (typ(y) == t_COMPLEX) y = mkvec2(gel(y,1), gel(y,2)); else y = mkvec2(y, gen_0); } else if (typ(y) == t_COMPLEX) { x = mkvec2(x, gen_0); y = mkvec2(gel(y,1), gel(y,2)); } return gc_int(av, lexcmp_i(x, y)); } /*****************************************************************/ /* */ /* EQUALITY */ /* returns 1 if x == y, 0 otherwise */ /* */ /*****************************************************************/ /* x,y t_POL */ static int polidentical(GEN x, GEN y) { long lx; if (x[1] != y[1]) return 0; lx = lg(x); if (lg(y) != lg(x)) return 0; for (lx--; lx >= 2; lx--) if (!gidentical(gel(x,lx), gel(y,lx))) return 0; return 1; } /* x,y t_SER */ static int seridentical(GEN x, GEN y) { return polidentical(x,y); } /* typ(x) = typ(y) = t_VEC/COL/MAT */ static int vecidentical(GEN x, GEN y) { long i; if ((x[0] ^ y[0]) & (TYPBITS|LGBITS)) return 0; for (i = lg(x)-1; i; i--) if (! gidentical(gel(x,i),gel(y,i)) ) return 0; return 1; } static int identicalrr(GEN x, GEN y) { long i, lx = lg(x); if (lg(y) != lx) return 0; if (x[1] != y[1]) return 0; i=2; while (i ly) if (!gequal0(gel(x,--lx))) return 0; while (ly > lx) if (!gequal0(gel(y,--ly))) return 0; for (lx--; lx >= 2; lx--) if (!gequal(gel(x,lx), gel(y,lx))) return 0; return 1; } /* x,y t_SER in the same variable */ static int serequal(GEN x, GEN y) { long LX, LY, lx, ly, vx, vy; if (!signe(x) && !signe(y)) return 1; lx = lg(x); vx = valser(x); LX = lx + vx; ly = lg(y); vy = valser(y); LY = ly + vy; if (LX > LY) lx = LY - vx; else ly = LX - vy; while (lx >= 3 && ly >= 3) if (!gequal(gel(x,--lx), gel(y,--ly))) return 0; while(--ly >= 2) if (!gequal0(gel(y,ly))) return 0; while(--lx >= 2) if (!gequal0(gel(x,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; } int gequal(GEN x, GEN y) { pari_sp av; GEN A, B, a, b; long tx, ty; 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: return equalii(gel(x,2), gel(y,2)) && equalii(gel(x,1), gel(y,1)); case t_INTMOD: A = gel(x,1); B = gel(y,1); a = gel(x,2); b = gel(y,2); if (equalii(A, B)) return equalii(a, b); av = avma; A = gcdii(A, B); return gc_bool(av, equalii(modii(a,A), modii(b,A))); 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; return gc_bool(av, gequal0(gsub(x,y))); case t_POLMOD: A = gel(x,1); B = gel(y,1); if (varn(A) != varn(B)) break; a = gel(x,2); b = gel(y,2); if (RgX_equal_var(A, B)) return gequal(a,b); av = avma; A = ggcd(A, B); return gc_bool(av, gequal(gmod(a,A), gmod(b,A))); case t_POL: if (varn(x) != varn(y)) break; return polequal(x,y); case t_SER: if (varn(x) != varn(y)) break; return serequal(x,y); case t_FFELT: return FF_equal(x,y); case t_QFB: 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; a = simplify_shallow(gmul(a,d)); b = simplify_shallow(gmul(b,c)); return gc_bool(av, gequal(a,b)); } 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: return list_cmp(x, y, gequal); case t_CLOSURE: return closure_identical(x,y); case t_INFINITY: return gequal(gel(x,1),gel(y,1)); } if (is_noncalc_t(tx) || is_noncalc_t(ty)) return 0; if (tx == t_INT && !signe(x)) return gequal0(y); if (ty == t_INT && !signe(y)) return gequal0(x); (void)&av; av = avma; /* emulate volatile */ return gc_bool(av, gequal_try(x, y)); } int gequalsg(long s, GEN x) { pari_sp av = avma; return gc_bool(av, gequal(stoi(s), x)); } /* a and b are t_INT, t_FRAC, t_REAL or t_COMPLEX of those. Check whether * a-b is invertible */ int cx_approx_equal(GEN a, GEN b) { pari_sp av = avma; GEN d; if (a == b) return 1; d = gsub(a,b); return gc_bool(av, gequal0(d) || (typ(d)==t_COMPLEX && gequal0(cxnorm(d)))); } static int r_approx0(GEN x, long e) { return e - expo(x) > bit_prec(x); } /* x ~ 0 compared to reference y */ int cx_approx0(GEN x, GEN y) { GEN a, b; long e; switch(typ(x)) { case t_COMPLEX: a = gel(x,1); b = gel(x,2); if (typ(a) != t_REAL) { if (!gequal0(a)) return 0; a = NULL; } else if (!signe(a)) a = NULL; if (typ(b) != t_REAL) { if (!gequal0(b)) return 0; if (!a) return 1; b = NULL; } else if (!signe(b)) { if (!a) return 1; b = NULL; } /* a or b is != NULL iff it is non-zero t_REAL; one of them is */ e = gexpo(y); return (!a || r_approx0(a, e)) && (!b || r_approx0(b, e)); case t_REAL: return !signe(x) || r_approx0(x, gexpo(y)); default: return gequal0(x); } } /*******************************************************************/ /* */ /* VALUATION */ /* p is either a t_INT or a t_POL. */ /* returns the largest exponent of p dividing x when this makes */ /* sense : error for types real, integermod and polymod if p does */ /* not divide the modulus, q-adic if q!=p. */ /* */ /*******************************************************************/ static long minval(GEN x, GEN p) { long i,k, val = LONG_MAX, lx = lg(x); for (i=lontyp[typ(x)]; i 0) return 0; } return minval(x,p); } case t_SER: { if (tp == t_POL) { long vp = varn(p), vx = varn(x); if (vp == vx) { long val = RgX_val(p); if (!val) pari_err_DOMAIN("gvaluation", "p", "=", p, p); return (long)(valser(x) / val); } if (varncmp(vx, vp) > 0) return 0; } return minval(x,p); } case t_RFRAC: return gvaluation(gel(x,1),p) - gvaluation(gel(x,2),p); case t_COMPLEX: case t_QUAD: case t_VEC: case t_COL: case t_MAT: return minval(x,p); } pari_err_OP("valuation", x,p); return 0; /* LCOV_EXCL_LINE */ } GEN gpvaluation(GEN x, GEN p) { long v = gvaluation(x,p); return v == LONG_MAX? mkoo(): stoi(v); } /* x is nonzero */ 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, uel(p,2)); } /* assume |p| > 1 */ long z_pvalrem(long s, GEN p, long *py) { if (lgefint(p) > 3) { *py = s; return 0; } return z_lvalrem(s, uel(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(uel(x,2), p); av = avma; for(vx = 0;;) { ulong r; GEN q = absdiviu_rem(x, p, &r); if (r) break; vx++; x = q; if (vx == VAL_DC_THRESHOLD) { if (p == 1) pari_err_DOMAIN("Z_lval", "p", "=", gen_1, gen_1); vx += Z_pvalrem_DC(x, sqru(p), &x) << 1; q = absdiviu_rem(x, p, &r); if (!r) vx++; break; } } return gc_long(av,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(uel(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 = absdiviu_rem(x, p, &r); if (r) break; vx++; x = q; if (vx == VAL_DC_THRESHOLD) { if (p == 1) pari_err_DOMAIN("Z_lvalrem", "p", "=", gen_1, gen_1); vx += Z_pvalrem_DC(x, sqru(p), &x) << 1; q = absdiviu_rem(x, p, &r); if (!r) { vx++; x = q; } break; } } set_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 && uel(q,2) <= p); } long u_lvalrem_stop(ulong *n, ulong p, int *stop) { ulong N = *n, q = N / p, r = N % p; /* gcc makes a single div */ long v = 0; if (!r) { do { v++; N = q; q = N / p; r = N % p; } while (!r); *n = N; } *stop = q <= p; return v; } /* Assume n > 0. Return v_p(n), set *n := n/p^v_p(n). Set 'stop' if now * n < p^2 [implies n prime if no prime < p divides n] */ long Z_lvalrem_stop(GEN *n, ulong p, int *stop) { pari_sp av; long v; ulong r; GEN N, q; if (lgefint(*n) == 3) { r = (*n)[2]; v = u_lvalrem_stop(&r, p, stop); if (v) *n = utoipos(r); return v; } av = avma; v = 0; q = absdiviu_rem(*n, p, &r); if (r) set_avma(av); else { do { v++; N = q; if (v == VAL_DC_THRESHOLD) { v += Z_pvalrem_DC(N,sqru(p),&N) << 1; q = absdiviu_rem(N, p, &r); if (!r) { v++; N = q; } break; } q = absdiviu_rem(N, p, &r); } while (!r); *n = N; } *stop = isless_iu(q,p); return v; } /* x is a nonzero 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, uel(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) { set_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, uel(p,2), py); *py = x; return 0; } long u_pval(ulong x, GEN p) { if (lgefint(p) == 3) return u_lval(x, uel(p,2)); return 0; } long Z_pval(GEN x, GEN p) { long vx; pari_sp av; if (lgefint(p) == 3) return Z_lval(x, uel(p,2)); if (lgefint(x) == 3) return 0; av = avma; vx = 0; for(;;) { GEN r, q = dvmdii(x,p,&r); if (r != gen_0) return gc_long(av,vx); vx++; x = q; } } /* return v_p(n!) = [n/p] + [n/p^2] + ... */ long factorial_lval(ulong n, ulong p) { ulong q, v; if (p == 2) return n - hammingl(n); 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) { set_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) = absdiviu_rem(xi, q, &r); if (r) { set_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) { *py = x; return gc_long(av,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) = absdiviu_rem(gel(y,i), p, &r); if (r) return gc_long(av,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); } long zx_lval(GEN f, long p) { long i, l = lg(f), x = LONG_MAX; for(i=2; i=0)? stoi(s): gcopy(x); } GEN gmin(GEN x, GEN y) { return gcopy(gmin_shallow(x,y)); } GEN gmings(GEN x, long s) { return (gcmpsg(s,x)>0)? gcopy(x): stoi(s); } long vecindexmax(GEN x) { long lx = lg(x), i0, i; GEN s; if (lx==1) pari_err_DOMAIN("vecindexmax", "empty argument", "=", x,x); switch(typ(x)) { case t_VEC: case t_COL: s = gel(x,i0=1); for (i=2; i 0) s = gel(x,i0=i); return i0; case t_VECSMALL: return vecsmall_indexmax(x); default: pari_err_TYPE("vecindexmax",x); } /* LCOV_EXCL_LINE */ return 0; } long vecindexmin(GEN x) { long lx = lg(x), i0, i; GEN s; if (lx==1) pari_err_DOMAIN("vecindexmin", "empty argument", "=", x,x); switch(typ(x)) { case t_VEC: case t_COL: s = gel(x,i0=1); for (i=2; i= vy) { set_avma(av); return gen_0; } z = gel(x,4); if (!signe(z) || vy > vx + precp(x)) pari_err_OP("",x, mkintmod(gen_1,Y)); if (vx) z = mulii(z, powiu(p,vx)); return gerepileuptoint(av, remii(z, Y)); } ulong padic_to_Fl(GEN x, ulong Y) { GEN p = gel(x,2); ulong u, z; long vy, vx = valp(x); vy = u_pvalrem(Y,p, &u); if (vx < 0 || u != 1) pari_err_OP("",x, mkintmodu(1,Y)); /* Y = p^vy */ if (vx >= vy) return 0; z = umodiu(gel(x,4), Y); if (!z || vy > vx + precp(x)) pari_err_OP("",x, mkintmodu(1,Y)); if (vx) { ulong pp = p[2]; z = Fl_mul(z, upowuu(pp,vx), Y); /* p^vx < p^vy = Y */ } return z; } static void croak(const char *s) { char *t; t = stack_sprintf("gaffect [overwriting universal object: %s]",s); pari_err_BUG(t); } void gaffect(GEN x, GEN y) { long vx, i, lx, ly, tx = typ(x), ty = typ(y); pari_sp av; GEN p1, num, den; if (tx == ty) switch(tx) { case t_INT: if (!is_universal_constant(y)) { affii(x,y); return; } /* y = gen_0, gnil, gen_1 or gen_2 */ if (y==gen_0) croak("gen_0"); if (y==gen_1) croak("gen_1"); if (y==gen_m1) croak("gen_m1"); if (y==gen_m2) croak("gen_m2"); if (y==gen_2) croak("gen_2"); croak("gnil)"); case t_REAL: affrr(x,y); return; case t_INTMOD: if (!dvdii(gel(x,1),gel(y,1))) pari_err_OP("",x,y); modiiz(gel(x,2),gel(y,1),gel(y,2)); return; case t_FRAC: affii(gel(x,1),gel(y,1)); affii(gel(x,2),gel(y,2)); return; case t_COMPLEX: gaffect(gel(x,1),gel(y,1)); gaffect(gel(x,2),gel(y,2)); return; case t_PADIC: if (!equalii(gel(x,2),gel(y,2))) pari_err_OP("",x,y); modiiz(gel(x,4),gel(y,3),gel(y,4)); setvalp(y,valp(x)); return; case t_QUAD: if (! ZX_equal(gel(x,1),gel(y,1))) pari_err_OP("",x,y); affii(gel(x,2),gel(y,2)); affii(gel(x,3),gel(y,3)); return; case t_VEC: case t_COL: case t_MAT: lx = lg(x); if (lx != lg(y)) pari_err_DIM("gaffect"); for (i=1; i REAL, COMPLEX OR P-ADIC */ /* */ /*******************************************************************/ GEN quadtofp(GEN x, long prec) { GEN b, D, z, u = gel(x,2), v = gel(x,3); pari_sp av; if (prec < LOWDEFAULTPREC) prec = LOWDEFAULTPREC; if (isintzero(v)) return cxcompotor(u, prec); av = avma; D = quad_disc(x); b = gel(gel(x,1),3); /* 0 or -1 */ /* u + v (-b + sqrt(D)) / 2 */ if (!signe(b)) b = NULL; if (b) u = gadd(gmul2n(u,1), v); z = sqrtr_abs(itor(D, prec)); if (!b) shiftr_inplace(z, -1); z = gmul(v, z); if (signe(D) < 0) { z = mkcomplex(cxcompotor(u, prec), z); if (!b) return gerepilecopy(av, z); z = gmul2n(z, -1); } else { /* if (b) x ~ (u + z) / 2 and quadnorm(x) ~ (u^2 - z^2) / 4 * else x ~ u + z and quadnorm(x) ~ u^2 - z^2 */ long s = gsigne(u); if (s == -gsigne(v)) /* conjugate expression avoids cancellation */ { z = gdiv(quadnorm(x), gsub(u, z)); if (b) shiftr_inplace(z, 1); } else { if (s) z = gadd(u, z); if (b) shiftr_inplace(z, -1); } } return gerepileupto(av, 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 (absequaliu(p,2)) d += 2; z = Qp_sqrt(cvtop(D,p,d)); if (!z) pari_err_SQRTN("Qp_sqrt",D); z = gmul2n(gsub(z, b), -1); z = gadd(u, gmul(v, z)); if (typ(z) != t_PADIC) /* t_INTMOD for t_QUAD of t_INTMODs... */ z = cvtop(z, p, d); return gerepileupto(av, z); } static GEN ctop(GEN x, GEN p, long d) { pari_sp av = avma; GEN z, u = gel(x,1), v = gel(x,2); if (isrationalzero(v)) return cvtop(u, p, d); z = Qp_sqrt(cvtop(gen_m1, p, d - gvaluation(v, p))); /* = I */ if (!z) pari_err_SQRTN("Qp_sqrt",gen_m1); z = gadd(u, gmul(v, z)); if (typ(z) != t_PADIC) /* t_INTMOD for t_COMPLEX of t_INTMODs... */ z = cvtop(z, p, d); return gerepileupto(av, z); } /* cvtop2(stoi(s), y) */ GEN cvstop2(long s, GEN y) { GEN z, p = gel(y,2); long v, d = signe(gel(y,4))? precp(y): 0; if (!s) return zeropadic_shallow(p, d); v = z_pvalrem(s, p, &s); if (d <= 0) return zeropadic_shallow(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; } static GEN itop2_coprime(GEN x, GEN y, long v, long d) { GEN z = cgetg(5, t_PADIC); z[1] = evalprecp(d) | evalvalp(v); gel(z,2) = gel(y,2); gel(z,3) = gel(y,3); gel(z,4) = modii(x, gel(y,3)); return z; } /* cvtop(x, gel(y,2), precp(y)), shallow */ GEN cvtop2(GEN x, GEN y) { GEN p = gel(y,2); long v, d = signe(gel(y,4))? precp(y): 0; switch(typ(x)) { case t_INT: if (!signe(x)) return zeropadic_shallow(p, d); if (d <= 0) return zeropadic_shallow(p, Z_pval(x,p)); v = Z_pvalrem(x, p, &x); return itop2_coprime(x, y, v, d); 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, den; if (d <= 0) return zeropadic_shallow(p, Q_pval(x,p)); num = gel(x,1); v = Z_pvalrem(num, p, &num); den = gel(x,2); if (!v) v = -Z_pvalrem(den, p, &den); if (!is_pm1(den)) num = mulii(num, Fp_inv(den, gel(y,3))); return itop2_coprime(num, y, v, d); } case t_COMPLEX: return ctop(x, p, d); case t_QUAD: return qtop(x, p, d); case t_PADIC: if (!signe(gel(x,4))) return zeropadic_shallow(p, d); if (precp(x) <= d) return x; return itop2_coprime(gel(x,4), y, valp(x), d); /* reduce accuracy */ } pari_err_TYPE("cvtop2",x); return NULL; /* LCOV_EXCL_LINE */ } /* assume is_const_t(tx) */ GEN cvtop(GEN x, GEN p, long d) { GEN z; long v; if (typ(p) != t_INT) pari_err_TYPE("cvtop",p); switch(typ(x)) { case t_INT: if (!signe(x)) return zeropadic(p, d); if (d <= 0) return zeropadic(p, Z_pval(x,p)); v = Z_pvalrem(x, p, &x); 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, den; if (d <= 0) return zeropadic(p, Q_pval(x,p)); num = gel(x,1); v = Z_pvalrem(num, p, &num); den = gel(x,2); if (!v) v = -Z_pvalrem(den, p, &den); 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: p = gel(x,2); /* override */ if (!signe(gel(x,4))) return zeropadic(p, d); z = cgetg(5,t_PADIC); z[1] = x[1]; setprecp(z,d); gel(z,2) = icopy(p); gel(z,3) = powiu(p, d); gel(z,4) = modii(gel(x,4), gel(z,3)); return z; case t_QUAD: return qtop(x, p, d); } pari_err_TYPE("cvtop",x); return NULL; /* LCOV_EXCL_LINE */ } 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; } return -1-(long)HIGHEXPOBIT; } long gexpo(GEN x) { long e = gexpo_safe(x); if (e < -(long)HIGHEXPOBIT) pari_err_TYPE("gexpo",x); return e; } GEN gpexponent(GEN x) { long e = gexpo(x); return e == -(long)HIGHEXPOBIT? mkmoo(): stoi(e); } long sizedigit(GEN x) { return gequal0(x)? 0: (long) ((gexpo(x)+1) * LOG10_2) + 1; } /* normalize series. avma is not updated */ GEN normalizeser(GEN x) { long i, lx = lg(x), vx=varn(x), vp=valser(x); GEN y, z; if (lx == 2) { setsigne(x,0); return x; } if (lx == 3) { z = gel(x,2); if (!gequal0(z)) { setsigne(x,1); return x; } if (isrationalzero(z)) return zeroser(vx,vp+1); if (isexactzero(z)) { /* dangerous case: already normalized ? */ if (!signe(x)) return x; setvalser(x,vp+1); /* no: normalize */ } setsigne(x,0); return x; } for (i=2; i1; i--) if (! gequal0(gel(x,i))) break; stackdummy((pari_sp)(x + lg(x)), (pari_sp)(x + i+1)); setlg(x, i+1); setsigne(x, i!=1); return x; } GEN normalizepol_lg(GEN x, long lx) { long i, LX = 0; GEN KEEP = NULL; for (i = lx-1; i>1; i--) { GEN z = gel(x,i); if (! gequal0(z) ) { if (!LX) LX = i+1; stackdummy((pari_sp)(x + lg(x)), (pari_sp)(x + LX)); x[0] = evaltyp(t_POL) | _evallg(LX); setsigne(x,1); return x; } else if (!isexactzero(z)) { if (!LX) LX = i+1; /* to be kept as leading coeff */ } else if (!isrationalzero(z)) KEEP = z; /* to be kept iff all other coeffs are exact 0s */ } if (!LX) { if (KEEP) { /* e.g. Pol(Mod(0,2)) */ gel(x,2) = KEEP; LX = 3; } else LX = 2; /* Pol(0) */ } stackdummy((pari_sp)(x + lg(x)), (pari_sp)(x + LX)); x[0] = evaltyp(t_POL) | _evallg(LX); setsigne(x,0); return x; } /* normalize polynomial x in place */ GEN normalizepol(GEN x) { return normalizepol_lg(x, lg(x)); } int gsigne(GEN x) { switch(typ(x)) { case t_INT: case t_REAL: return signe(x); case t_FRAC: return signe(gel(x,1)); case t_QUAD: { pari_sp av = avma; GEN T = gel(x,1), a = gel(x,2), b = gel(x,3); long sa, sb; if (signe(gel(T,2)) > 0) break; a = gmul2n(a,1); if (signe(gel(T,3))) a = gadd(a,b); /* a + b sqrt(D) > 0 ? */ sa = gsigne(a); sb = gsigne(b); if (sa == sb) return gc_int(av,sa); if (sa == 0) return gc_int(av,sb); if (sb == 0) return gc_int(av,sa); /* different signs, take conjugate expression */ sb = gsigne(gsub(gsqr(a), gmul(quad_disc(x), gsqr(b)))); return gc_int(av, sb*sa); } case t_INFINITY: return inf_get_sign(x); } pari_err_TYPE("gsigne",x); return 0; /* LCOV_EXCL_LINE */ } /*******************************************************************/ /* */ /* 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), i, lw; GEN v, w; if (l <= nmax) return; if (nmax) { nmax <<= 1; if (l > nmax) nmax = l; w = list_data(L); lw = lg(w); v = newblock(nmax+1); v[0] = w[0]; for (i=1; i < lw; i++) gel(v,i) = gel(w, i); killblock(w); } else /* unallocated */ { nmax = 32; if (list_data(L)) pari_err(e_MISC, "store list in variable before appending elements"); v = newblock(nmax+1); v[0] = evaltyp(t_VEC) | _evallg(1); } list_data(L) = v; L[1] = evaltyp(list_typ(L))|evallg(nmax); } void listkill(GEN L) { if (typ(L) != t_LIST) pari_err_TYPE("listkill",L); if (list_nmax(L)) { GEN v = list_data(L); long i, l = lg(v); for (i=1; i= l) { ensure_nb(L, l); z = list_data(L); /* it may change ! */ index = l; l++; } else gunclone_deep( gel(z, index) ); gel(z,index) = x; z[0] = evaltyp(t_VEC) | evallg(l); /*must be after gel(z,index) is set*/ return gel(z,index); } GEN listput0(GEN L, GEN x, long index) { if (typ(L) != t_LIST || list_typ(L) != t_LIST_RAW) pari_err_TYPE("listput",L); (void) listput(L, x, index); return x; } GEN listinsert(GEN L, GEN x, long index) { long l, i; GEN z; z = list_data(L); l = z? lg(z): 1; if (index <= 0) pari_err_COMPONENT("listinsert", "<=", gen_0, stoi(index)); if (index > l) index = l; ensure_nb(L, l); BLOCK_SIGINT_START z = list_data(L); for (i=l; i > index; i--) gel(z,i) = gel(z,i-1); z[0] = evaltyp(t_VEC) | evallg(l+1); gel(z,index) = gclone(x); BLOCK_SIGINT_END return gel(z,index); } GEN listinsert0(GEN L, GEN x, long index) { if (typ(L) != t_LIST || list_typ(L) != t_LIST_RAW) pari_err_TYPE("listinsert",L); (void) listinsert(L, x, index); return x; } void listpop(GEN L, long index) { long l, i; GEN z; if (typ(L) != t_LIST) pari_err_TYPE("listinsert",L); if (index < 0) pari_err_COMPONENT("listpop", "<", gen_0, stoi(index)); z = list_data(L); if (!z || (l = lg(z)-1) == 0) return; if (!index || index > l) index = l; BLOCK_SIGINT_START gunclone_deep( gel(z, index) ); z[0] = evaltyp(t_VEC) | _evallg(l); for (i=index; i < l; i++) z[i] = z[i+1]; BLOCK_SIGINT_END } void listpop0(GEN L, long index) { if (typ(L) != t_LIST || list_typ(L) != t_LIST_RAW) pari_err_TYPE("listpop",L); listpop(L, index); } /* return a copy fully allocated on stack. gclone from changevalue is * supposed to malloc() it */ GEN gtolist(GEN x) { GEN y; if (!x) return mklist(); switch(typ(x)) { case t_VEC: case t_COL: y = mklist(); if (lg(x) == 1) return y; list_data(y) = gcopy(x); settyp(list_data(y), t_VEC); return y; case t_LIST: y = mklist(); list_data(y) = list_data(x)? gcopy(list_data(x)): NULL; return y; default: return mklistcopy(x); } } void listsort(GEN L, long flag) { long i, l; pari_sp av = avma; GEN perm, v, vnew; if (typ(L) != t_LIST) pari_err_TYPE("listsort",L); v = list_data(L); l = v? lg(v): 1; if (l < 3) return; if (flag) { long lnew; perm = gen_indexsort_uniq(L, (void*)&cmp_universal, cmp_nodata); lnew = lg(perm); /* may have changed since 'uniq' */ vnew = cgetg(lnew,t_VEC); for (i=1; i>1); return gerepileupto(av, C); } static int zv_canon(GEN V) { long l = lg(V), j, k; for (j = 1; j < l && V[j] == 0; ++j); if (j < l && V[j] < 0) { for (k = j; k < l; ++k) V[k] = -V[k]; return -1; } return 1; } static GEN ZM_to_zm_canon(GEN V) { GEN W = ZM_to_zm(V); long i, l = lg(W); for (i=1; i I && Wj[k] == mael3(F,k,J,J); k++) for (i = 1; i <= I; i++) /* check scalar products with basis vectors */ if (zv_dotproduct(Vj,gmael(Ftr,k,per[i])) != mael(gel(F,k),J,per[i])) break; if (k == f+1 && i > I) ++count; /* same for the negative vector */ i = I+1; for (k = 1; k <= f && i > I && Wj[k] == mael3(F,k,J,J); k++) for (i = 1; i <= I ; i++) if (zv_dotproduct(Vj,gmael(Ftr,k,per[i])) != -mael(gel(F,k),J,per[i])) break; if (k == f+1 && i > I) ++count; } return count; } static void fingerprint(struct fingerprint *fp, struct qfauto *qf) { pari_sp av; GEN V=qf->V, W=qf->W, F=qf->F, Mf, Ftr; long i, j, k, min, dim = qf->dim, n = lg(V)-1, f = lg(F)-1; fp->per = identity_perm(dim); fp->e = cgetg(dim+1, t_VECSMALL); fp->diag = cgetg(dim+1, t_VECSMALL); av = avma; Ftr = cgetg(f+1,t_VEC); for (i = 1; i <= f; i++) gel(Ftr,i) = zm_transpose(gel(F,i)); Mf = zero_Flm_copy(dim, dim); /* the first row of the fingerprint has as entry nr. i the number of vectors, which have the same length as the i-th basis-vector with respect to every invariant form */ for (j = 1; j <= n; j++) { GEN Wj = gel(W,j); for (i = 1; i <= dim; i++) { for (k = 1; k <= f && Wj[k] == mael3(F,k,i,i); ++k); if (k == f+1) mael(Mf,1,i) += 2; } } for (i = 1; i <= dim-1; ++i) { /* a minimal entry != 0 in the i-th row is chosen */ min = i; for (j = i+1; j <= dim; j++) if (mael(Mf,i,fp->per[j]) < mael(Mf,i,fp->per[min])) min = j; lswap(fp->per[i],fp->per[min]); /* the column below the minimal entry is set to 0 */ for (j = i+1; j <= dim; j++) mael(Mf,j,fp->per[i]) = 0; /* compute the row i+1 of the fingerprint */ for (j = i+1; j <= dim; j++) mael(Mf,i+1,fp->per[j]) = possible(F, Ftr, V, W, fp->per, i, fp->per[j]); } for (i = 1; i <= dim; i++) { fp->diag[i] = mael(Mf,i,fp->per[i]); /* only diag(f) is needed later */ if ((fp->e[i] = vecvecsmall_search(V,vecsmall_ei(dim,fp->per[i]))) < 0) pari_err_BUG("qfisom, standard basis vector not found"); } set_avma(av); } /* The Bacher polynomial for v[I] with scalar product S is defined as follows: * let L be the vectors with same length as v[I] and scalar product S with v[I]; * for each vector w in L let nw be the number of pairs (y,z) of vectors in L, * such that all scalar products between w,y and z are S, then the Bacher * polynomial is the sum over the w in list of the monomials X^nw */ static GEN bacher(long I, long S, struct qfauto *qf) { pari_sp av = avma; GEN V=qf->V, W=qf->W, Fv=gel(qf->v,1), list, listxy, counts, vI, coef; long i, j, k, nlist, nxy, sum, mind, maxd, n = lg(V)-1; I = labs(I); /* Bacher polynomials of v[I] and -v[I] are equal */ vI = gel(V,I); list = zero_Flv(2*n); /* vectors that have scalar product S with v[I] */ nlist = 0; for (i = 1; i <= n; ++i) if (mael(W,i,1) == mael(W,I,1)) { long s = zv_dotproduct(vI, gel(Fv,i)); if (s == S) list[++nlist] = i; if (-s == S) list[++nlist] = -i; } /* there are nlist vectors that have scalar product S with v[I] */ sum = nlist; if (nlist==0) retmkvec2(mkvecsmall3(0,0,0),cgetg(1,t_VEC)); counts = cgetg(nlist+1, t_VECSMALL); listxy = cgetg(nlist+1, t_VECSMALL); for (i = 1; i <= nlist; ++i) { long S1; /* listxy is the list of the nxy vectors from list that have scalar product S with v[list[i]] */ for (j = 1; j <= nlist; ++j) listxy[j] = 0; nxy = 0; S1 = list[i] > 0 ? S : -S; for (j = 1; j <= nlist; ++j) { long S2 = list[j] > 0 ? S1 : -S1; /* note: for i > 0 is v[-i] = -v[i] */ if (zv_dotproduct(gel(V,labs(list[i])), gel(Fv,labs(list[j]))) == S2) listxy[++nxy] = list[j]; } /* counts[i] is the number of pairs for the vector v[list[i]] */ counts[i] = 0; for (j = 1; j <= nxy; ++j) { long S1 = listxy[j] > 0 ? S : -S; GEN Vj = gel(V, labs(listxy[j])); for (k = j+1; k <= nxy; ++k) { long S2 = listxy[k] > 0 ? S1 : -S1, lk = labs(listxy[k]); if (zv_dotproduct(Vj, gel(Fv,lk)) == S2) counts[i]++; } } } /* maxd = max degree of the Bacher-polynomial, mind = min degree */ mind = maxd = counts[1]; for (i = 2; i <= nlist; i++) { if (counts[i] > maxd) maxd = counts[i]; else if (counts[i] < mind) mind = counts[i]; } coef = zero_Flv(maxd - mind + 1); for (i = 1; i <= nlist; i++) coef[1+counts[i] - mind] += 1; if (DEBUGLEVEL) err_printf("QFIsom: mind=%ld maxd=%ld sum=%ld\n",mind,maxd,sum); /* Bacher polynomial = sum_{mind <= i <= maxd} coef[i - mind] * X^i */ return gerepilecopy(av, mkvec2(mkvecsmall3(sum, mind, maxd), coef)); } static GEN init_bacher(long bachdep, struct fingerprint *fp, struct qfauto *qf) { GEN z = cgetg(bachdep+1,t_VEC); long i; for (i=1;i<=bachdep;i++) { long bachscp = mael(qf->W,fp->e[i],1) / 2; gel(z,i) = bacher(fp->e[i], bachscp, qf); } return z; } /* checks, whether the vector v[I] has Bacher polynomial pol */ static long bachcomp(GEN pol, long I, GEN V, GEN W, GEN Fv) { pari_sp av = avma; GEN co, list, listxy, vI, coef = gel(pol,2); long i, j, k, nlist, nxy, count; const long n = lg(V)-1, S = mael(W,I,1) / 2; long sum = mael(pol,1,1), mind = mael(pol,1,2), maxd = mael(pol,1,3); vI = gel(V,I); list = zero_Flv(sum); nlist = 0; /* nlist should be equal to pol.sum */ for (i = 1; i <= n && nlist <= sum; i++) if (mael(W,i,1) == mael(W,I,1)) { long s = zv_dotproduct(vI, gel(Fv,i)); if (s == S) { if (nlist < sum) list[nlist+1] = i; nlist++; } if (-s == S) { if (nlist < sum) list[nlist+1] = -i; nlist++; } } /* the number of vectors with scalar product S is already different */ if (nlist != sum) return gc_long(av,0); if (nlist == 0) return gc_long(av,1); /* listxy is the list of the nxy vectors from list that have scalar product S with v[list[i]] */ listxy = cgetg(nlist+1,t_VECSMALL); co = zero_Flv(maxd - mind + 1); for (i = 1; i <= nlist; i++) { long S1 = list[i] > 0 ? S : -S; GEN Vi = gel(V, labs(list[i])); for (j = 1; j <= nlist; j++) listxy[j] = 0; nxy = 0; for (j = 1; j <= nlist; j++) { long S2 = list[j] > 0 ? S1 : -S1; if (zv_dotproduct(Vi, gel(Fv,labs(list[j]))) == S2) listxy[++nxy] = list[j]; } count = 0; /* number of pairs */ for (j = 1; j <= nxy && count <= maxd; j++) { long S1 = listxy[j] > 0 ? S : -S; GEN Vj = gel(V, labs(listxy[j])); for (k = j+1; k <= nxy && count <= maxd; k++) { long S2 = listxy[k] > 0 ? S1 : -S1, lk = labs(listxy[k]); if (zv_dotproduct(Vj, gel(Fv,lk)) == S2) count++; } } /* Bacher polynomials can not be equal */ if (count < mind || count > maxd || co[count-mind+1] >= coef[count-mind+1]) return gc_long(av, 0); co[count-mind+1]++; } return gc_long(av, 1); /* Bacher-polynomials are equal */ } static GEN checkvecs(GEN V, GEN F, GEN norm) { long i, j, k, n = lg(V)-1, f = lg(F)-1; GEN W = cgetg(n+1, t_MAT); j = 0; for (i = 1; i <= n; i++) { GEN normvec = cgetg(f+1, t_VECSMALL), Vi = gel(V,i); for (k = 1; k <= f; ++k) normvec[k] = scp(Vi, gel(F,k), Vi); if (vecvecsmall_search(norm,normvec) < 0) ++j; else { gel(V,i-j) = Vi; gel(W,i-j) = normvec; } } setlg(V, n+1-j); setlg(W, n+1-j); return W; } static long operate(long nr, GEN A, GEN V) { pari_sp av = avma; long im,eps; GEN w = zm_zc_mul(A,gel(V,labs(nr))); eps = zv_canon(w); if (nr < 0) eps = -eps; /* -w */ if ((im = vecvecsmall_search(V,w)) < 0) pari_err_BUG("qfauto, image of vector not found"); return gc_long(av, eps * im); } static GEN orbit(GEN pt, long ipt, long npt, GEN H, GEN V) { pari_sp av = avma; long i, cnd, im, n = lg(V)-1, nH = lg(H)-1, no = npt; GEN flag = zero_Flv(2*n+1)+n+1; /* need negative indices */ GEN orb = cgetg(2*n+1,t_VECSMALL); for (i = 1; i <= npt; ++i) { orb[i] = pt[ipt+i]; flag[pt[ipt+i]] = 1; } for (cnd=1; cnd <= no; ++cnd) for (i = 1; i <= nH; ++i) { im = operate(orb[cnd], gel(H,i), V); /* image is a new point in the orbit */ if (flag[im] == 0) { orb[++no] = im; flag[im] = 1; } } setlg(orb,no+1); return gerepileuptoleaf(av, orb); } /* return the length of the orbit of pt under the first nG matrices in G */ static long orbitlen(long pt, long orblen, GEN G, long nG, GEN V) { pari_sp av = avma; long i, len, cnd, n = lg(V)-1; GEN orb, flag; /* if flag[i + n+1] = 1, -n <= i <= n, then i is already in the orbit */ flag = zero_F2v(2*n + 1); orb = zero_Flv(orblen); orb[1] = pt; F2v_set(flag,pt+n+1); len = 1; for (cnd = 1; cnd <= len && len < orblen; cnd++) for (i = 1; i <= nG && len < orblen; i++) { long im = operate(orb[cnd], gel(G,i), V); /* image is a new point in the orbit */ if (!F2v_coeff(flag,im+n+1)) { orb[++len] = im; F2v_set(flag,im+n+1); } } return gc_long(av, len); } /* delete the elements in orb2 from orb1, an entry 0 marks the end of the * list, returns the length of orb1 */ static long orbdelete(GEN orb1, GEN orb2) { long i, j, len, l1 = lg(orb1)-1, l2 = lg(orb2)-1; for (i = 1; i <= l1 && orb1[i] != 0; ++i); len = i - 1; for (i = 1; i <= l2 && orb2[i] != 0; ++i) { long o2i = orb2[i]; for (j = 1; j <= len && orb1[j] != o2i; ++j); /* orb1[j] = orb2[i], hence delete orb1[j] from orb1 */ if (j <= len) { orb1[j] = orb1[len]; orb1[len--] = 0; } } return len; } static long orbsubtract(GEN Cs, GEN pt, long ipt, long npt, GEN H, GEN V, long *len) { pari_sp av = avma; GEN orb = orbit(pt, ipt, npt, H, V); if (len) *len = lg(orb)-1; return gc_long(av, orbdelete(Cs, orb)); } /* Generates the matrix X whose per[i]-th row is the vector V[x[i]] */ static GEN matgen(GEN x, GEN per, GEN V) { long i, j, n = lg(x)-1; GEN X = cgetg(n+1,t_MAT); for (i = 1; i <= n; i++) { GEN Xp = cgetg(n+1,t_VECSMALL); long xi = x[i]; for (j = 1; j <= n; j++) Xp[j] = xi > 0? mael(V,xi,j): -mael(V,-xi,j); gel(X, per[i]) = Xp; } return X; } /* x1 corresponds to an element X1 mapping some vector e on p1, x2 to an * element X2 mapping e on p2 and G is a generator mapping p1 on p2, then * S = X1*G*X2^-1 stabilizes e */ static GEN stabil(GEN x1, GEN x2, GEN per, GEN G, GEN V, ulong p) { pari_sp av = avma; long i, n = lg(x1)-1; GEN XG, X2, x = cgetg(n+1,t_VECSMALL); for (i = 1; i <= n; i++) x[i] = operate(x1[i], G, V); /* XG is the composite mapping of the matrix corresponding to x1 and G */ XG = matgen(x, per, V); X2 = matgen(x2, per, V); return gerepileupto(av, zm_divmod(X2,XG,p)); } /* computes the orbit of fp.e[I] under the generators in G->g[I]...G->g[n-1] * and elements stabilizing fp.e[I], has some heuristic break conditions, the * generators in G->g[i] stabilize fp.e[0]...fp.e[i-1] but not fp.e[i], * G->ng[i] is the number of generators in G->g[i], the first G->nsg[i] of * which are elements which are obtained as stabilizer elements in * g[0],...,G->g[i-1]>, G->ord[i] is the orbit length of fp.e[i] under * g[i],...,G->g[n-1]> */ static void stab(long I, struct group *G, struct fingerprint *fp, GEN V, ulong p) { GEN orb, w, flag, H, Hj, S; long len, cnd, i, j, k, l, im, nH, fail; long Maxfail, Rest, dim = lg(fp->diag)-1, n = lg(V)-1; /* Heuristic break conditions for the computation of stabilizer elements: * it is too expensive to calculate all the stabilizer generators, which are * obtained from the orbit, since this is highly redundant. On the other hand * every new generator which enlarges the group is cheaper than one obtained * from the backtrack, after Maxfail subsequent stabilizer elements, that do * not enlarge the group, Rest more elements are calculated even if they * leave the group unchanged, since it turned out that this is often useful * in the following steps. Increasing the parameters may decrease the number * of generators for the group while increasing the running time. */ for (Rest = 0, i = I; i <= dim; i++) if (fp->diag[i] > 1 && G->ord[i] < fp->diag[i]) ++Rest; for (Maxfail = Rest, i = 1; i <= dim; i++) if (fp->diag[i] > 1) ++Maxfail; for (nH = 0, i = I; i <= dim; i++) nH += G->ng[i]; /* generators of the group in which the stabilizer is computed */ H = cgetg(nH+1,t_MAT); Hj = cgetg(nH+2,t_MAT); for (i = I, k = 0; i <= dim; i++) for (j = 1; j <= G->ng[i]; j++) gel(H,++k) = gmael(G->g,i,j); /* in w[V.n+i] an element is stored that maps fp.e[I] on v[i] */ w = cgetg(2*n+2,t_VEC); orb = zero_Flv(2*n); /* the orbit of fp.e[I] */ flag = zero_F2v(2*n+1); /* if flag[i + V.n], then i is already in orbit */ orb[1] = fp->e[I]; F2v_set(flag,orb[1]+n+1); gel(w,orb[1]+n+1) = cgetg(dim+1,t_VECSMALL); for (i = 1; i <= dim; i++) mael(w,orb[1]+n+1,i) = fp->e[i]; cnd = len = 1; fail = 0; /* number of successive failures */ while (cnd <= len && fail < Maxfail+Rest) { for (i = 1; i <= nH && fail < Maxfail+Rest; ++i) { if (fail >= Maxfail) /* already Maxfail successive failures: apply a random generator to a * random point of the orbit to get Rest more stabilizer elements */ { cnd = 1+(long)random_Fl(len); i = 1+(long)random_Fl(nH); } im = operate(orb[cnd], gel(H,i), V); if (F2v_coeff(flag,im+n+1) == 0) { /* found new element, appended to the orbit; an element mapping * fp.e[I] to im is stored in w[im+V.n] */ GEN wim; orb[++len] = im; F2v_set(flag,im+n+1); wim = cgetg(dim+1,t_VECSMALL); gel(w,im+n+1) = wim; for (j = 1; j <= dim; ++j) wim[j] = operate(mael(w,orb[cnd]+n+1,j), gel(H,i), V); } else /* image was already in the orbit */ { /* j = first index where images of old and new element mapping e[I] on * im differ */ for (j = I; j <= dim; j++) if (operate(mael(w,orb[cnd]+n+1,j), gel(H,i), V) != mael(w,im+n+1,j)) break; if (j <= dim && (G->ord[j] < fp->diag[j] || fail >= Maxfail)) { GEN wo = gel(w,orb[cnd]+n+1); long tmplen, nHj = 1; /* new stabilizer element S = w[orb[cnd]+V.n] * H[i] * (w[im+V.n])^-1 */ S = stabil(wo, gel(w,im+n+1), fp->per, gel(H,i), V, p); gel(Hj,1) = S; for (k = j; k <= dim; k++) for (l = 1; l <= G->ng[k]; l++) gel(Hj, ++nHj) = gmael(G->g,k,l); tmplen = orbitlen(fp->e[j], fp->diag[j], Hj, nHj, V); if (tmplen > G->ord[j] || fail >= Maxfail) /* the new stabilizer element S either enlarges the orbit of e[j] or it is one of the additional elements after MAXFAIL failures */ { GEN Ggj; G->ord[j] = tmplen; G->ng[j]++; G->nsg[j]++; /* allocate memory for new generator */ gel(G->g,j) = vec_lengthen(gel(G->g,j),G->ng[j]); Ggj = gel(G->g,j); /* new generator is inserted as stabilizer element nsg[j]-1 */ for (k = G->ng[j]; k > G->nsg[j]; k--) gel(Ggj,k) = gel(Ggj,k-1); gel(Ggj,G->nsg[j]) = S; nH++; H = vec_lengthen(H, nH); Hj = vec_lengthen(Hj, nH+1); gel(H,nH) = gel(Ggj,G->nsg[j]); /* append new generator to H */ if (fail < Maxfail) fail = 0; /* number of failures is reset to 0 */ else ++fail; } else /* new stabilizer element S does not enlarge the orbit of e[j] */ ++fail; } else if ((j < dim && fail < Maxfail) || (j == dim && fail >= Maxfail)) ++fail; /* if S is the identity and fail < Maxfail, nothing is done */ } } if (fail < Maxfail) ++cnd; } } /* tests, whether x[1],...,x[I-1] is a partial automorphism, using scalar * product combinations and Bacher-polynomials depending on the chosen options, * puts the candidates for x[I] (i.e. the vectors vec such that the scalar * products of x[1],...,x[I-1],vec are correct) on CI, returns their number * (should be fp.diag[I]) */ static long qfisom_candidates_novec(GEN CI, long I, GEN x, struct qfauto *qf, struct qfauto *qff, struct fingerprint *fp) { pari_sp av = avma; long i, j, k, okp, okm, nr, fail; GEN vec, F =qf->F, V=qff->V, W=qff->W, v=qff->v; long n = lg(V)-1, f = lg(F)-1; vec = cgetg(I,t_VECSMALL); for (i = 1; i <= fp->diag[I]; i++) CI[i] = 0; /* list for the candidates */ nr = fail = 0; for (j = 1; j <= n && fail == 0; j++) { GEN Vj = gel(V,j), Wj = gel(W, j); okp = okm = 0; for (i = 1; i <= f; i++) { GEN FAiI = gmael(F,i,fp->per[I]), FFvi = gel(v,i); /* vec is the vector of scalar products of V.v[j] with the first I base vectors x[0]...x[I-1] */ for (k = 1; k < I; k++) { long xk = x[k]; if (xk > 0) vec[k] = zv_dotproduct(Vj, gel(FFvi,xk)); else vec[k] = -zv_dotproduct(Vj, gel(FFvi,-xk)); } for (k = 1; k < I && vec[k] == FAiI[fp->per[k]]; k++); if (k == I && Wj[i] == FAiI[fp->per[I]]) ++okp; /* V.v[j] is a candidate for x[I] with respect to the form F.A[i] */ for (k = 1; k < I && vec[k] == -FAiI[fp->per[k]]; k++); if (k == I && Wj[i] == FAiI[fp->per[I]]) ++okm; /* -V.v[j] is a candidate for x[I] with respect to the form F.A[i] */ } if (okp == f) /* V.v[j] is a candidate for x[I] */ { if (nr < fp->diag[I]) CI[++nr] = j; else fail = 1; /* too many candidates */ } if (okm == f) /* -V.v[j] is a candidate for x[I] */ { if (nr < fp->diag[I]) CI[++nr] = -j; else fail = 1; /* too many candidates */ } } return gc_long(av, fail? 0: nr); } static long qfisom_candidates(GEN CI, long I, GEN x, struct qfauto *qf, struct qfauto *qff, struct fingerprint *fp, struct qfcand *qfcand) { pari_sp av = avma; GEN vec, xvec, xbase, Fxbase, scpvec, com, list, trans, ccoef, cF; GEN F =qf->F, V=qff->V, W=qff->W, v=qff->v, FF= qff->F; long i, j, k, okp, okm, nr, nc, vj, rank, num; long dim = qf->dim, n = lg(V)-1, f = lg(F)-1; long DEP = qfcand->cdep, len = f * DEP; if (I >= 2 && I <= lg(qfcand->bacher_pol)) { long t = labs(x[I-1]); GEN bpolI = gel(qfcand->bacher_pol,I-1); if (bachcomp(bpolI, t, V, W, gel(v,1)) == 0) return 0; } if (I==1 || DEP ==0) return qfisom_candidates_novec(CI,I,x,qf,qff,fp); vec = cgetg(I,t_VECSMALL); scpvec = cgetg(len+1,t_VECSMALL); com = gel(qfcand->comb,I-1); list=gel(com,1); trans = gel(com,2); ccoef = gel(com,3); cF=gel(com,4); rank = lg(trans)-1; nc = lg(list)-2; /* xvec is the list of vector sums which are computed with respect to the partial basis in x */ xvec = zero_Flm_copy(dim,nc+1); /* xbase should be a basis for the lattice generated by the vectors in xvec, it is obtained via the transformation matrix comb[I-1].trans */ xbase = cgetg(rank+1,t_MAT); for (i = 1; i <= rank; ++i) gel(xbase,i) = cgetg(dim+1,t_VECSMALL); Fxbase = cgetg(rank+1,t_MAT); /* product of a form F with the base xbase */ for (i = 1; i <= rank; ++i) gel(Fxbase,i) = cgetg(dim+1,t_VECSMALL); for (i = 1; i <= fp->diag[I]; ++i) CI[i] = 0; /* list for the candidates */ nr = 0; for (j = 1; j <= n; ++j) { long sign; GEN Vj = gel(V,j), Wj = gel(W, j); okp = okm = 0; for (k = 1; k <= len; ++k) scpvec[k] = 0; for (i = 1; i <= f; ++i) { GEN FAiI = gmael(F,i,fp->per[I]), FFvi = gel(v,i); /* vec is the vector of scalar products of V.v[j] with the first I base vectors x[0]...x[I-1] */ for (k = 1; k < I; ++k) { long xk = x[k]; if (xk > 0) vec[k] = zv_dotproduct(Vj, gel(FFvi,xk)); else vec[k] = -zv_dotproduct(Vj, gel(FFvi,-xk)); } for (k = 1; k < I && vec[k] == FAiI[fp->per[k]]; ++k); if (k == I && Wj[i] == FAiI[fp->per[I]]) ++okp; /* V.v[j] is a candidate for x[I] with respect to the form F.A[i] */ for (k = 1; k < I && vec[k] == -FAiI[fp->per[k]]; ++k); if (k == I && Wj[i] == FAiI[fp->per[I]]) ++okm; /* -V.v[j] is a candidate for x[I] with respect to the form F.A[i] */ for (k = I-1; k >= 1 && k > I-1-DEP; --k) scpvec[(i-1)*DEP+I-k] = vec[k]; } /* check, whether the scalar product combination scpvec is contained in the list comb[I-1].list */ if (!zv_equal0(scpvec)) { sign = zv_canon(scpvec); /* x[0..I-1] not a partial automorphism ? */ if ((num = vecvecsmall_search(list,scpvec)) < 0) return gc_long(av,0); else { GEN xnum = gel(xvec,num); for (k = 1; k <= dim; ++k) xnum[k] += sign * Vj[k]; } } if (okp == f) /* V.v[j] is a candidate for x[I] */ { if (nr >= fp->diag[I]) return gc_long(av,0); /* too many candidates */ CI[++nr] = j; } if (okm == f) /* -V.v[j] is a candidate for x[I] */ { if (nr >= fp->diag[I]) return gc_long(av,0); /* too many candidates */ CI[++nr] = -j; } } if (nr == fp->diag[I]) { /* compute the basis of the lattice generated by the vectors in xvec via the transformation matrix comb[I-1].trans */ for (i = 1; i <= rank; ++i) { GEN comtri = gel(trans,i); for (j = 1; j <= dim; ++j) { long xbij = 0; for (k = 1; k <= nc+1; ++k) xbij += comtri[k] * mael(xvec,k,j); mael(xbase,i,j) = xbij; } } /* check, whether the base xbase has the right scalar products */ for (i = 1; i <= f; ++i) { for (j = 1; j <= rank; ++j) for (k = 1; k <= dim; ++k) mael(Fxbase,j,k) = zv_dotproduct(gmael(FF,i,k), gel(xbase,j)); for (j = 1; j <= rank; ++j) for (k = 1; k <= j; ++k) /* a scalar product is wrong ? */ if (zv_dotproduct(gel(xbase,j), gel(Fxbase,k)) != mael3(cF,i,j,k)) return gc_long(av, 0); } for (i = 1; i <= nc+1; ++i) { GEN comcoi = gel(ccoef,i); for (j = 1; j <= dim; ++j) { vj = 0; for (k = 1; k <= rank; ++k) vj += comcoi[k] * mael(xbase,k,j); if (vj != mael(xvec,i,j)) return gc_long(av,0); /* an entry is wrong */ } } } return gc_long(av, nr); } static long aut(long step, GEN x, GEN C, struct group *G, struct qfauto *qf, struct fingerprint *fp, struct qfcand *cand) { long dim = qf->dim; GEN orb; /* found new automorphism */ if (step == dim && mael(C,dim,1)) { x[dim] = mael(C,dim,1); return 1; } orb = cgetg(2,t_VECSMALL); while (mael(C,step,1)) { long nbc; /* choose the image of the base-vector nr. step */ x[step] = mael(C,step,1); /* check, whether x[0..step] is a partial automorphism and compute the candidates for x[step+1] */ nbc = qfisom_candidates(gel(C,step+1), step+1, x, qf, qf, fp, cand); if (nbc == fp->diag[step+1] && aut(step+1, x, C, G, qf, fp, cand)) return 1; orb[1] = x[step]; /* delete chosen vector from list of candidates */ (void)orbdelete(gel(C,step), orb); } return 0; } /* search new automorphisms until on all levels representatives for all orbits * have been tested */ static void autom(struct group *G, struct qfauto *qf, struct fingerprint *fp, struct qfcand *cand) { long i, j, step, im, nC, found, tries, nbad; GEN x, bad, H, V = qf->V; long dim = qf->dim, n = lg(V)-1, STAB = 1; GEN C = cgetg(dim+1,t_VEC); /* C[i] is the list of candidates for the image of the i-th base-vector */ for (i = 1; i <= dim; ++i) gel(C,i) = cgetg(fp->diag[i]+1, t_VECSMALL); /* x is the new base i.e. x[i] is the index in V.v of the i-th base-vector */ x = cgetg(dim+1, t_VECSMALL); for (step = STAB; step <= dim; ++step) { long nH = 0; if (DEBUGLEVEL) err_printf("QFAuto: Step %ld/%ld\n",step,dim); for (nH = 0, i = step; i <= dim; ++i) nH += G->ng[i]; H = cgetg(nH+1,t_VEC); for (nH = 0, i = step; i <= dim; ++i) for (j = 1; j <= G->ng[i]; ++j) gel(H,++nH) = gmael(G->g,i,j); bad = zero_Flv(2*n); nbad = 0; /* the first step base-vectors are fixed */ for (i = 1; i < step; ++i) x[i] = fp->e[i]; /* compute the candidates for x[step] */ if (fp->diag[step] > 1) /* if fp.diag[step] > 1 compute the candidates for x[step] */ nC = qfisom_candidates(gel(C,step), step, x, qf, qf, fp, cand); else /* if fp.diag[step] == 1, fp.e[step] is the only candidate */ { mael(C,step,1) = fp->e[step]; nC = 1; } /* delete the orbit of the step-th base-vector from the candidates */ nC = orbsubtract(gel(C,step), fp->e, step-1, 1, H, V, &(G->ord[step])); while (nC > 0 && (im = mael(C,step,1)) != 0) { found = 0; /* tries vector V.v[im] as image of the step-th base-vector */ x[step] = im; if (step < dim) { long nbc; /* check, whether x[0]...x[step] is a partial basis and compute the candidates for x[step+1] */ nbc = qfisom_candidates(gel(C,step+1), step+1, x, qf, qf, fp, cand); if (nbc == fp->diag[step+1]) /* go into the recursion */ found = aut(step+1, x, C, G, qf, fp, cand); else found = 0; } else found = 1; if (!found) /* x[0..step] can not be continued to an automorphism */ { /* delete the orbit of im from the candidates for x[step] */ nC = orbsubtract(gel(C,step),mkvecsmall(im), 0, 1, H, V, NULL); bad[++nbad] = im; } else { /* new generator has been found */ GEN Gstep; ++G->ng[step]; /* append new generator to G->g[step] */ Gstep = vec_lengthen(gel(G->g,step),G->ng[step]); gel(Gstep,G->ng[step]) = matgen(x, fp->per, V); gel(G->g,step) = Gstep; ++nH; H = cgetg(nH+1, t_VEC); for (nH = 0, i = step; i <= dim; i++) for (j = 1; j <= G->ng[i]; j++) gel(H,++nH) = gmael(G->g,i,j); nC = orbsubtract(gel(C,step), fp->e, step-1, 1, H, V, &(G->ord[step])); nC = orbsubtract(gel(C,step), bad, 0, nbad, H, V, NULL); } } /* test, whether on step STAB some generators may be omitted */ if (step == STAB) for (tries = G->nsg[step]+1; tries <= G->ng[step]; tries++) { nH = 0; for (j = 1; j < tries; j++) gel(H,++nH) = gmael(G->g,step,j); for (j = tries+1; j <= G->ng[step]; j++) gel(H,++nH) = gmael(G->g,step,j); for (i = step+1; i <= dim; i++) for (j = 1; j <= G->ng[i]; j++) gel(H,++nH) = gmael(G->g,i,j); if (orbitlen(fp->e[step], G->ord[step], H, nH, V) == G->ord[step]) { /* generator g[step][tries] can be omitted */ G->ng[step]--; for (i = tries; i <= G->ng[step]; ++i) gmael(G->g,step,i) = gmael(G->g,step,i+1); tries--; } } /* calculate stabilizer elements fixing basis-vectors fp.e[0..step] */ if (step < dim && G->ord[step] > 1) stab(step, G, fp, V, qf->p); } } #define MAXENTRY (1L<<((BITS_IN_LONG-2)>>1)) #define MAXNORM (1L<<(BITS_IN_LONG-2)) static long zm_maxdiag(GEN A) { long dim = lg(A)-1, max = coeff(A,1,1), i; for (i = 2; i <= dim; ++i) if (coeff(A,i,i) > max) max = coeff(A,i,i); return max; } static GEN init_qfauto(GEN F, GEN U, long max, struct qfauto *qf, GEN norm, GEN minvec) { GEN V = minvec ? ZM_to_zm_canon(minvec) : gel(minim_zm(zm_to_ZM(gel(F,1)), stoi(max), NULL), 3); GEN W, v; long i, j, k, n = lg(V)-1, f = lg(F)-1, dim = lg(gel(F,1))-1; for (i = 1; i <= n; i++) { GEN Vi = gel(V,i); for (k = 1; k <= dim; k++) { long l = labs(Vi[k]); if (l > max) max = l; } } if (max > MAXENTRY) pari_err_OVERFLOW("qfisom [lattice too large]"); qf->p = unextprime(2*max+1); V = vecvecsmall_sort_uniq(V); if (!norm) { norm = cgetg(dim+1,t_VEC); for (i = 1; i <= dim; i++) { GEN Ni = cgetg(f+1,t_VECSMALL); for (k = 1; k <= f; k++) Ni[k] = mael3(F,k,i,i); gel(norm,i) = Ni; } norm = vecvecsmall_sort_uniq(norm); } W = checkvecs(V, F, norm); v = cgetg(f+1,t_VEC); /* the product of the maximal entry in the short vectors with the maximal entry in v[i] should not exceed MAXNORM to avoid overflow */ max = MAXNORM / max; for (i = 1; i <= f; ++i) { GEN Fi = gel(F,i), vi = cgetg(n+1,t_MAT); gel(v,i) = vi; for (j = 1; j <= n; ++j) { GEN Vj = gel(V,j), vij = cgetg(dim+1, t_VECSMALL); gel(vi,j) = vij; for (k = 1; k <= dim; ++k) { vij[k] = zv_dotproduct(gel(Fi,k), Vj); if (labs(vij[k]) > max) pari_err_OVERFLOW("qfisom [lattice too large]"); } } } qf->dim = dim; qf->F = F; qf->V = V; qf->W = W; qf->v = v; qf->U = U; return norm; } static void init_qfgroup(struct group *G, struct fingerprint *fp, struct qfauto *qf) { GEN H, M, V = qf->V; long nH, i, j, k, dim = qf->dim; G->ng = zero_Flv(dim+1); G->nsg = zero_Flv(dim+1); G->ord = cgetg(dim+1,t_VECSMALL); G->g = cgetg(dim+1,t_VEC); for (i = 1; i <= dim; ++i) gel(G->g,i) = mkvec(gen_0); M = matid_Flm(dim); gmael(G->g,1,1) = M; G->ng[1] = 1; /* -Id is always an automorphism */ for (i = 1; i <= dim; i++) mael(M,i,i) = -1; nH = 0; for (i = 1; i <= dim; i++) nH += G->ng[i]; H = cgetg(nH+1,t_MAT); /* calculate the orbit lengths under the automorphisms known so far */ for (i = 1; i <= dim; ++i) { if (G->ng[i] > 0) { nH = 0; for (j = i; j <= dim; j++) for (k = 1; k <= G->ng[j]; k++) gel(H,++nH) = gmael(G->g,j,k); G->ord[i] = orbitlen(fp->e[i], fp->diag[i], H, nH, V); } else G->ord[i] = 1; } } /* calculates the scalar products of the vector w with the base vectors * v[b[I]] down to v[b[I-dep+1]] with respect to all invariant forms and puts * them on scpvec */ static GEN scpvector(GEN w, GEN b, long I, long dep, GEN v) { long i, j, n = lg(v)-1; GEN scpvec = zero_Flv(dep*n); for (i = I; i >= 1 && i > I-dep; i--) { long bi = b[i]; if (bi > 0) for (j = 1; j <= n; j++) scpvec[1+(j-1)*dep + I-i] = zv_dotproduct(w, gmael(v,j,bi)); else for (j = 1; j <= n; j++) scpvec[1+(j-1)*dep + I-i] = -zv_dotproduct(w, gmael(v,j,-bi)); } return scpvec; } /* computes the list of scalar product combinations of the vectors * in V.v with the basis-vectors in b */ static GEN scpvecs(GEN *pt_vec, long I, GEN b, long dep, struct qfauto *qf) { GEN list, vec, V = qf->V, F = qf->F, v = qf->v; long j, n = lg(V)-1, dim = lg(gel(F,1))-1, len = (lg(F)-1)*dep; /* the first vector in the list is the 0-vector and is not counted */ list = mkvec(zero_Flv(len)); vec = mkvec(zero_Flv(dim)); for (j = 1; j <= n; ++j) { GEN Vvj = gel(V,j), scpvec = scpvector(Vvj, b, I, dep, v); long i, nr, sign; if (zv_equal0(scpvec)) continue; sign = zv_canon(scpvec); nr = vecvecsmall_search(list, scpvec); if (nr > 0) /* scpvec already in list */ { GEN vecnr = gel(vec,nr); for (i = 1; i <= dim; i++) vecnr[i] += sign * Vvj[i]; } else /* scpvec is a new scalar product combination */ { nr = -nr; list = vec_insert(list,nr,scpvec); vec = vec_insert(vec,nr,sign < 0 ? zv_neg(Vvj) : zv_copy(Vvj)); } } settyp(list,t_MAT); settyp(vec,t_MAT); *pt_vec = vec; return list; } /* com->F[i] is the Gram-matrix of the basis b with respect to F.A[i] */ static GEN scpforms(GEN b, struct qfauto *qf) { GEN F = qf->F; long i, j, k, n = lg(F)-1, dim = lg(gel(F,1))-1, nb = lg(b)-1; GEN gram = cgetg(n+1, t_VEC), Fbi = cgetg(nb+1, t_MAT); /* list of products of F.A[i] with the vectors in b */ for (j = 1; j <= nb; j++) gel(Fbi, j) = cgetg(dim+1, t_VECSMALL); for (i = 1; i <= n; i++) { GEN FAi = gel(F,i); gel(gram, i) = cgetg(nb+1, t_MAT); for (j = 1; j <= nb; j++) for (k = 1; k <= dim; k++) mael(Fbi,j,k) = zv_dotproduct(gel(FAi,k), gel(b,j)); for (j = 1; j <= nb; j++) { GEN Gij = cgetg(nb+1, t_VECSMALL); for (k = 1; k <= nb; k++) Gij[k] = zv_dotproduct(gel(b,j), gel(Fbi,k)); gmael(gram,i,j) = Gij; } } return gram; } static GEN gen_comb(long cdep, GEN A, GEN e, struct qfauto *qf, long lim) { long i, dim = lg(A)-1; GEN comb = cgetg(dim+1,t_VEC); for (i = 1; i <= dim; ++i) { pari_sp av = avma; GEN trans, ccoef, cF, B, BI, sumveclist, sumvecbase; GEN list = scpvecs(&sumveclist, i, e, cdep, qf); GEN M = zm_to_ZM(sumveclist); GEN T = ZM_lll(qf_ZM_apply(A,M), .99, LLL_NOFLATTER | LLL_IM | LLL_GRAM); if (lim && lg(T)-1>=lim) return NULL; B = ZM_mul(M,T); BI = RgM_inv(B); sumvecbase = ZM_trunc_to_zm(B); trans = ZM_trunc_to_zm(T); ccoef = ZM_trunc_to_zm(RgM_mul(BI,M)); cF = scpforms(sumvecbase, qf); gel(comb,i) = gerepilecopy(av, mkvec4(list, trans, ccoef, cF)); } return comb; } static void init_comb(struct qfcand *cand, GEN A, GEN e, struct qfauto *qf) { long dim = lg(A)-1; GEN Am = zm_to_ZM(A); for (cand->cdep = 1; ; cand->cdep++) { cand->comb = gen_comb(cand->cdep, Am, e, qf, (dim+1)>>1); if (!cand->comb) break; } cand->cdep= maxss(1, cand->cdep-1); cand->comb = gen_comb(cand->cdep, Am, e, qf, 0); } static void init_flags(struct qfcand *cand, GEN A, struct fingerprint *fp, struct qfauto *qf, GEN flags) { if (!flags) { init_comb(cand, A, fp->e, qf); cand->bacher_pol = init_bacher(0, fp, qf); } else { long cdep, bach; if (typ(flags)!=t_VEC || lg(flags)!=3) pari_err_TYPE("qfisominit",flags); cdep = gtos(gel(flags,1)); bach = minss(gtos(gel(flags,2)), lg(fp->e)-1); if (cdep<0 || bach<0) pari_err_FLAG("qfisom"); cand->cdep = cdep; cand->comb = cdep? gen_comb(cdep, zm_to_ZM(A), fp->e, qf, 0): NULL; cand->bacher_pol = init_bacher(bach, fp, qf); } } static GEN gen_group(struct group *G, GEN U) { GEN V, o = gen_1; long i, j, n, dim = lg(G->ord)-1; for (i = 1; i <= dim; i++) o = muliu(o, G->ord[i]); for (i = n = 1; i <= dim; i++) n += G->ng[i] - G->nsg[i]; V = cgetg(n, t_VEC); for (i = n = 1; i <= dim; ++i) for (j=G->nsg[i]+1; j<=G->ng[i]; j++) gel(V,n++) = U ? zm_mul(gel(U,1), zm_mul(gmael(G->g,i,j), gel(U,2))) : gmael(G->g,i,j); return mkvec2(o, V); } static long is_qfisom(GEN F) { return (lg(F)==6 && typ(F)==t_VEC && typ(gel(F,1))==t_VEC && typ(gel(F,3))==t_VEC && typ(gel(F,4))==t_VEC); } static GEN unpack_qfisominit(GEN F, GEN *norm, struct qfauto *qf, struct fingerprint *fp, struct qfcand *cand) { GEN QF = gel(F,3); qf->F = gel(QF,1); qf->V = gel(QF,2); qf->W = gel(QF,3); qf->v = gel(QF,4); qf->p = itou(gel(QF,5)); qf->U = lg(QF)>6 ? gel(QF,6):NULL; QF = gel(F,4); fp->diag = gel(QF,1); fp->per = gel(QF,2); fp->e = gel(QF,3); QF = gel(F,5); cand->cdep =itos(gel(QF,1)); cand->comb = gel(QF,2); cand->bacher_pol = gel(QF,3); *norm = gel(F,2); qf->dim = lg(gmael(F,1,1))-1; return qf->F; } static GEN qfisom_bestmat(GEN A, long *pt_max) { long max = zm_maxdiag(A), max2; GEN A2, A1 = zm_to_ZM(A), U = lllgramint(A1); if (lg(U) != lg(A1)) pari_err_DOMAIN("qfisom","form","is not", strtoGENstr("positive definite"), A1); A2 = ZM_to_zm(qf_ZM_apply(A1, U)); max2 = zm_maxdiag(A2); if (max2 >= max) { *pt_max = max; return NULL; } *pt_max = max2; return mkvec2(ZM_to_zm(U), ZM_to_zm(ZM_inv(U,NULL))); } static GEN init_qfisom(GEN F, struct fingerprint *fp, struct qfcand *cand, struct qfauto *qf, GEN flags, long *max, GEN minvec) { GEN U, A, norm; if (is_qfisom(F)) { F = unpack_qfisominit(F, &norm, qf, fp, cand); A = gel(F,1); *max = zm_maxdiag(A); if (flags) init_flags(cand, A, fp, qf, flags); } else { if (lg(F)<2) pari_err_TYPE("qfisom",F); A = gel(F,1); if (lg(A)<2) pari_err_TYPE("qfisom",A); if (!minvec) { U = qfisom_bestmat(A, max); if (DEBUGLEVEL) err_printf("QFIsom: max=%ld\n",*max); if (U) F = zmV_apply_zm(F, gel(U,1)); } else { *max = zm_maxdiag(A); U = NULL; if (typ(minvec)==t_VEC && lg(minvec)==4 && typ(gel(minvec,2))==t_INT) { long n = itos(gel(minvec,2)); if (n != *max) pari_err_DOMAIN("qfisominit","m[2]","!=",stoi(*max),stoi(n)); minvec = gel(minvec, 3); } if (typ(minvec)!=t_MAT || lg(gel(minvec,1))!=lg(A)) pari_err_TYPE("qfisominit",minvec); } norm = init_qfauto(F, U, *max, qf, NULL, minvec); fingerprint(fp, qf); if (DEBUGLEVEL) err_printf("QFIsom: fp=%Ps\n",fp->diag); init_flags(cand, A, fp, qf, flags); } return norm; } GEN qfauto(GEN F, GEN flags) { pari_sp av = avma; struct fingerprint fp; struct group G; struct qfcand cand; struct qfauto qf; long max; (void)init_qfisom(F, &fp, &cand, &qf, flags, &max, NULL); init_qfgroup(&G, &fp, &qf); autom(&G, &qf, &fp, &cand); return gerepilecopy(av, gen_group(&G, qf.U)); } static GEN qf_to_zmV(GEN F) { switch(typ(F)) { case t_MAT: return RgM_is_ZM(F)? mkvec(ZM_to_zm(F)): NULL; case t_VEC: return RgV_is_ZMV(F)? ZMV_to_zmV(F): NULL; } return NULL; } GEN qfauto0(GEN x, GEN flags) { pari_sp av = avma; GEN F, G; if (is_qfisom(x)) F = x; else { F = qf_to_zmV(x); if (!F) pari_err_TYPE("qfauto",x); } G = qfauto(F, flags); return gerepilecopy(av, mkvec2(gel(G,1), zmV_to_ZMV(gel(G,2)))); } /* computes the orbit of V.v[pt] under the generators G[0],...,G[nG-1] and * elements stabilizing V.v[pt], which are stored in H, returns the number of * generators in H */ static GEN isostab(long pt, GEN G, GEN V, long Maxfail, ulong p) { pari_sp av = avma; long i, im, nH, fail, len, cnd, orblen, rpt; long dim = lg(gel(V,1))-1, n = lg(V)-1, nG = lg(G)-1; GEN w, flag, orb, H; H = cgetg(2,t_VEC); /* generators of the stabilizer of V.v[pt] */ nH = 0; w = cgetg(2*n+2,t_MAT); /* w[i+V.n] is a matrix that maps V.v[pt] on V.v[i] */ orb = zero_Flv(2*n); orblen = 1; /* length of the orbit of a random vector in V.v */ flag = zero_Flv(2*n+1); /* if flag[i+V.n] = 1, then i is already in orbit */ orb[1] = pt; flag[orb[1]+n+1] = 1; /* w[pt+V.n] is the Identity */ gel(w,orb[1]+n+1) = matid_Flm(dim); cnd = len = 1; fail = 0; /* number of successive failures */ while (cnd <= len && fail < Maxfail) { for (i = 1; i <= nG && fail < Maxfail; i++) { im = operate(orb[cnd], gel(G,i), V); if (flag[im+n+1] == 0) { /* new element is found, append to the orbit and store an element * mapping V.v[pt] to im in w[im+V.n] */ orb[++len] = im; flag[im+n+1] = 1; gel(w,im+n+1) = zm_mul(gel(G,i), gel(w,orb[cnd]+n+1)); } else { /* image was already in orbit */ GEN B = zm_mul(gel(G,i), gel(w,orb[cnd]+n+1)); /* check whether the old and the new element mapping pt on im differ */ if (!zvV_equal(B, gel(w,im+n+1))) { long tmplen; gel(H,nH+1) = zm_divmod(gel(w,im+n+1),B,p); rpt = 1+(long)random_Fl(n); tmplen = orbitlen(rpt, 2*n, H, nH+1, V); while (tmplen < orblen) { /* orbit of this vector is shorter than a previous one: * choose new random vector */ rpt = 1+(long)random_Fl(n); tmplen = orbitlen(rpt, 2*n, H, nH+1, V); } if (tmplen > orblen) { /* new stabilizer element H[nH] enlarges the group generated by H */ orblen = tmplen; H = vec_lengthen(H, (++nH)+1); /* allocate for new generator */ fail = 0; } else /* new stabilizer element does not enlarge random vector orbit */ ++fail; } /* if H[nH] is the identity, do nothing */ } } ++cnd; } setlg(H, nH+1); return gerepilecopy(av, H); } /* the heart of the program: the recursion */ static long iso(long step, GEN x, GEN C, struct qfauto *qf, struct qfauto *qff, struct fingerprint *fp, GEN G, struct qfcand *cand) { long dim = qf->dim; /* found isomorphism */ if (step == dim && mael(C,dim,1)) { x[dim] = mael(C,dim,1); return 1; } while (mael(C,step,1)) { long nbc; /* choose the image of the base-vector nr. step */ x[step] = mael(C,step,1); /* check whether x[0]...x[step] is a partial automorphism and compute the candidates for x[step+1] */ nbc = qfisom_candidates(gel(C,step+1), step+1, x, qf, qff, fp, cand); if (nbc == fp->diag[step+1]) { /* go deeper into the recursion */ long i, Maxfail = 0; GEN H; /* heuristic value of Maxfail for break condition in isostab */ for (i = 1; i <= step; ++i) if (fp->diag[i] > 1) Maxfail++; for (; i <= dim; ++i) if (fp->diag[i] > 1) Maxfail += 2; /* compute the stabilizer H of x[step] in G */ H = isostab(x[step], G, qff->V, Maxfail,qff->p); if (iso(step+1, x, C, qf, qff, fp, H, cand)) return 1; } /* delete the orbit of the chosen vector from the list of candidates */ orbsubtract(gel(C,step), x, step-1, 1, G, qff->V, NULL); } return 0; } /* search for an isometry */ static GEN isometry(struct qfauto *qf, struct qfauto *qff, struct fingerprint *fp, GEN G, struct qfcand *cand) { long i, dim = qf->dim; GEN x, C = cgetg(dim+1,t_VEC); /* C[i] is the list of candidates for the image of the i-th base-vector */ for (i = 1; i <= dim; ++i) gel(C,i) = cgetg(fp->diag[i]+1, t_VECSMALL); x = cgetg(dim+1, t_VECSMALL); /* compute the candidates for x[1] */ qfisom_candidates(gel(C,1), 1, x, qf, qff, fp, cand); return iso(1, x, C, qf, qff, fp, G, cand)? matgen(x, fp->per, qff->V): NULL; } GEN qfisominit(GEN F, GEN flags, GEN minvec) { pari_sp av = avma; struct fingerprint fp; struct qfauto qf; struct qfcand cand; long max; GEN norm = init_qfisom(F, &fp, &cand, &qf, flags, &max, minvec); return gerepilecopy(av, mkvec5(F, norm, mkvecn(qf.U?6:5, qf.F, qf.V, qf.W, qf.v, utoi(qf.p), qf.U), mkvec3(fp.diag, fp.per, fp.e), mkvec3(stoi(cand.cdep),cand.comb?cand.comb:cgetg(1,t_VEC), cand.bacher_pol))); } GEN qfisominit0(GEN x, GEN flags, GEN minvec) { pari_sp av = avma; GEN F = qf_to_zmV(x); if (!F) pari_err_TYPE("qfisom",x); return gerepileupto(av, qfisominit(F, flags, minvec)); } GEN qfisom(GEN F, GEN FF, GEN flags, GEN G) { pari_sp av = avma; struct fingerprint fp; GEN res, detf, detff; struct qfauto qf, qff; struct qfcand cand; long max; GEN norm = init_qfisom(F, &fp, &cand, &qf, flags, &max, NULL); init_qfauto(FF, NULL, max, &qff, norm, NULL); detf = ZM_det(zm_to_ZM(gel(qf.F,1))); detff = ZM_det(zm_to_ZM(gel(qff.F,1))); if (lg(qf.W)!=lg(qff.W) || !equalii(detf, detff) || !zvV_equal(vecvecsmall_sort_shallow(qf.W), vecvecsmall_sort_shallow(qff.W))) return gc_const(av,gen_0); if (!G) G = mkvec(scalar_Flm(-1, qff.dim)); res = isometry(&qf, &qff, &fp, G, &cand); if (!res) return gc_const(av, gen_0); return gerepilecopy(av, zm_to_ZM(qf.U? zm_mul(res,gel(qf.U, 2)): res)); } static GEN check_qfauto(GEN G) { if (typ(G)==t_VEC && lg(G)==3 && typ(gel(G,1))==t_INT) G = gel(G,2); return qf_to_zmV(G); } GEN qfisom0(GEN x, GEN y, GEN flags, GEN G) { pari_sp av = avma; GEN F, FF; if (is_qfisom(x)) F = x; else { F = qf_to_zmV(x); if (!F) pari_err_TYPE("qfisom",x); } FF = qf_to_zmV(y); if (!FF) pari_err_TYPE("qfisom",y); if (G) G = check_qfauto(G); return gerepileupto(av, qfisom(F, FF, flags, G)); } static GEN ZM_to_GAP(GEN M) { pari_sp av = avma; long i, j, c, rows = nbrows(M), cols = lg(M)-1; GEN comma = strtoGENstr(", "), bra = strtoGENstr("["), ket = strtoGENstr("]"); GEN s = cgetg(2*rows*cols+2*rows+2,t_VEC); gel(s,1) = bra; c=2; for (i = 1; i <= rows; i++) { if (i > 1) gel(s,c++) = comma; gel(s,c++) = bra; for (j = 1; j <= cols; j++) { if (j > 1) gel(s,c++) = comma; gel(s,c++) = GENtoGENstr(gcoeff(M,i,j)); } gel(s,c++) = ket; } gel(s,c++) = ket; return gerepilecopy(av, shallowconcat1(s)); } GEN qfautoexport(GEN G, long flag) { pari_sp av = avma; long i, lgen, c = 2; GEN gen, str, comma = strtoGENstr(", "); if (typ(G)!=t_VEC || lg(G)!=3) pari_err_TYPE("qfautoexport", G); if (flag!=0 && flag!=1) pari_err_FLAG("qfautoexport"); gen = gel(G,2); lgen = lg(gen)-1; str = cgetg(2+2*lgen,t_VEC); /* in GAP or MAGMA the matrix group is called BG */ if (flag == 0) gel(str,1) = strtoGENstr("Group("); else { long dim = lg(gmael(gen,1,1))-1; gel(str,1) = gsprintf("MatrixGroup<%d, Integers() |",dim); } for (i = 1; i <= lgen; i++) { if (i!=1) gel(str,c++) = comma; gel(str,c++) = ZM_to_GAP(gel(gen,i)); } gel(str,c++) = strtoGENstr(flag ? ">":")"); return gerepilecopy(av, shallowconcat1(str)); } GEN qforbits(GEN G, GEN V) { pari_sp av = avma; GEN gen, w, W, p, v, orb, o; long i, j, n, ng, nborbits = 0; gen = check_qfauto(G); if (!gen) pari_err_TYPE("qforbits", G); if (typ(V)==t_VEC && lg(V)==4 && typ(gel(V,1))==t_INT && typ(gel(V,2))==t_INT) V = gel(V,3); if (typ(V)!=t_MAT || !RgM_is_ZM(V)) pari_err_TYPE("qforbits", V); n = lg(V)-1; ng = lg(gen)-1; W = ZM_to_zm_canon(V); p = vecvecsmall_indexsort(W); v = vecpermute(W, p); w = zero_zv(n); orb = cgetg(n+1, t_VEC); o = cgetg(n+1, t_VECSMALL); if (lg(v) != lg(V)) return gen_0; for (i = 1; i <= n; i++) { long cnd, no = 1; GEN T; if (w[i]) continue; w[i] = ++nborbits; o[1] = i; for (cnd=1; cnd <= no; ++cnd) for (j=1; j <= ng; j++) { GEN Vij = zm_zc_mul(gel(gen, j), gel(v, o[cnd])); long k; (void) zv_canon(Vij); if ((k = vecvecsmall_search(v, Vij)) < 0) return gc_const(av, gen_0); if (w[k] == 0) { o[++no] = k; w[k] = nborbits; } } gel(orb, nborbits) = T = cgetg(no+1, t_VEC); for (j=1; j<=no; j++) gel(T,j) = gel(V,p[o[j]]); } setlg(orb, nborbits+1); return gerepilecopy(av, orb); } pari-2.17.2/src/basemath/lfunquad.c0000644000175000017500000004370214676526175015553 0ustar billbill/* Copyright (C) 2018 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /********************************************************************/ /** L-functions: values at integers of L-functions **/ /** of primitive quadratic characters **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" static GEN RCpol(long k, long t, GEN c) { GEN P = cgetg(k+3, t_POL); long l; gel(P,k+2) = c; for(l = 0; l < k; l++) { c = diviiexact(mulii(c, muluu(2*k-1 - 2*l, k-l)), mulss(l+1, 2*l-t)); gel(P,k-l+1) = c; } P[1] = evalsigne(1) | evalvarn(0); return P; } static GEN vecRCpol(long r, long d) { long k, K = d - 1, t = 2*r - 3; GEN v = cgetg(d + 1, t_VEC), c = int2n(2*K); for (k = 0; k <= K; k++) { /* c = 2^(2K) binomial(n/2,k), an integer */ gel(v,k+1) = RCpol(k, t, c); if (k == K) break; c = diviuexact(muliu(c, t - 2*k), 2*k + 2); } return v; } static GEN euler_sumdiv(GEN q, long v) { GEN u = addui(1, q); for (; v > 1; v--) u = addui(1, mulii(q, u)); return u; } /* [p^{k-1},p^{k-3},...,p^{k-2(d-1)-1}] * (s/p), s = 1 or -1 */ static GEN vpowp(long k, long d, long p, long s) { GEN v = cgetg(d + 1, t_VEC), p2 = sqru(p); long j; gel(v, d) = powuu(p, k - 2*d + 1); if (s == -1 && (p & 3L) == 3) togglesign_safe(&gel(v,d)); for (j = d-1; j >= 1; j--) gel(v, j) = mulii(p2, gel(v, j+1)); return v; } static GEN usumdivk_0_all(long k, long d) { GEN v = cgetg(d + 1, t_COL); long j; constbern(k >> 1); for (j = 1; j <= d; j++) { long n = k + 2 - 2*j; gel(v,j) = gdivgs(bernfrac(n), - (n << 1)); } return v; } static GEN usumdivk_fact_all(GEN fa, long k, long d) { GEN res, P, E, pow; long i, j, l; res = cgetg(d + 1, t_COL); P = gel(fa, 1); l = lg(P); E = gel(fa, 2); pow = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(pow, i) = vpowp(k, d, P[i], 1); for (j = 1; j <= d; j++) { GEN v = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(v,i) = euler_sumdiv(gmael(pow,i,j), E[i]); gel(res, j) = ZV_prod(v); } return res; } /* Hadamard product */ static GEN RgV_mul(GEN a, GEN b) { long j, l = lg(a); GEN v = cgetg(l, t_COL); for (j = 1; j < l; j++) gel(v,j) = gmul(gel(a,j), gel(b,j)); return v; } static GEN RgV_multwist(GEN a, GEN P, long k, long dim, long d, long v2, long N4) { GEN v = cgetg(dim+1, t_COL); long j; for (j = 1; j <= d; j++) { GEN z; gel(v,j) = z = gmul(gel(a,j), gel(P,j)); if (j + d <= dim) { if (N4 == 3) z = negi(z); if (v2) z = shifti(z, (k - 2*j + 1)*v2); gel(v, j + d) = z; } } return v; } /* r = k - 2*j, 0<=j> 1); GEN v, P = gsubst(vPD, 0, utoi(s*s)); if (vs) v = gel(vs, Ds+1); else v = Ds? usumdivk_fact_all(factoru(Ds), k, d) : usumdivk_0_all(k,d); v = RgV_mul(v, P); if (!s) keep0 = gclone(v); else S = gadd(S, v); if (gc_needed(av, 1)) S = gerepileupto(av, S); } S = gmul2n(S, 1); if (keep0) { S = gadd(S, keep0); gunclone(keep0); } return S; } static GEN sigsum4(long k, long d, long D, GEN vs, GEN vP) { return sigsum(k, d, 2, odd(D), D, 4, vs, vP); } /* D != 5 (mod 8) */ static GEN sigsum8(long k, long d, long D, GEN vs, GEN vP) { if (D&1L) return gmul2n(sigsum(k, d, 2, 1, D, 8, vs, vP), -1); return sigsum(k, d, 4, 2*odd(D >> 2), D, 8, vs, vP); } /* D = 0 (mod 3) */ static GEN sigsum12(long k, long d, long D, GEN vs, GEN vP) { return sigsum(k, d, 6, 3*odd(D), D, 12, vs, vP); } /* D = 1 (mod 3) */ static GEN sigsumm12(long k, long d, long D, GEN vs, GEN vP) { long fl = odd(D); GEN res = sigsum(k, d, 6, 4 + fl, D, 12, vs, vP); res = gadd(res, sigsum(k, d, 6, 2 - fl, D, 12, vs, vP)); return gmul2n(res, -1); } /* D = 1 (mod 8) */ static GEN sigsum16(long k, long d, long D, GEN vs, GEN vP) { long fl = (D&15L) == 1; GEN res = sigsum(k, d, 8, 5 + 2*fl, D, 16, vs, vP); return gadd(res, sigsum(k, d, 8, 3 - 2*fl, D, 16, vs, vP)); } /* N = 4 (as above), 8 (factor (1+(D/2))), 12 (factor (1+(D/3))), 16 (only D=1 mod 8). */ static GEN Dpos(long d, long N, long B) { GEN vD = cgetg(maxss(B, d) + 1, t_VECSMALL); long D, step, c; switch(N) { case 4: D = 5; step = 1; break; case 8: D = 8; step = 4; break; case 12: D = 12; step = 3; break; case 16: D = 17; step = 8; break; default: D = 13; step = 3; break; /* -12 */ } for (c = 1; c <= d || D <= B; D += step) if (sisfundamental(D)) vD[c++] = D; setlg(vD, c); return vD; } typedef GEN (*SIGMA_F)(long,long,long,GEN,GEN); static SIGMA_F get_S_even(long N) { switch(N) { case 4: return sigsum4; case 8: return sigsum8; case 12:return sigsum12; case 16:return sigsum16; default:return sigsumm12; /* -12 */ } } static GEN mfDcoefs(GEN F, GEN vD, long d) { long l = lg(vD), i; GEN v = mfcoefs(F, vD[l-1], d), w = cgetg(l, t_COL); if (d == 4) for (i = 1; i < l; i++) gel(w, i) = gel(v, (vD[i]>>2)+1); else for (i = 1; i < l; i++) gel(w, i) = gel(v, vD[i]+1); return w; } static GEN myinverseimage(GEN M, GEN R, GEN *pden) { GEN c = Q_remove_denom(QM_gauss_i(M, R, 1), pden);/* M*res / den = R */ if (!c) pari_err_BUG("theta brackets"); return c; } static GEN Lfeq(long D, long k); static GEN Hcol(GEN k, long r, GEN vD, long d, long N2) { long i, l = lg(vD); GEN v; if (r < 5) { v = mfDcoefs(mfEH(k),vD,d); for (i = 1; i < l; i++) if (N2 != 1 && vD[i] % N2) gel(v,i) = gmul2n(gel(v,i), 1); return v; } v = cgetg(l, t_COL); for (i = 1; i < l; i++) { pari_sp av = avma; GEN c = Lfeq(odd(r)? -vD[i]: vD[i], r); /* fundamental */ if (N2 != 1 && vD[i] % N2) c = gmul2n(c, 1); gel(v, i) = gerepileupto(av, c); } return v; } /***********************************************************/ /* Modular form method using Half-Integral Weight forms */ /* Case D > 0 */ /***********************************************************/ static long dimeven(long r, long N) { switch(N) { case 4: return r / 6 + 1; case 12: return r / 3 + 1; default: return r / 4 + 1; } } static long muleven(long N) { return (N == 4)? 1: 2; } /* L(\chi_D, 1-r) for D > 0 and r > 0 even. */ static GEN modulareven(long D, long r, long N0) { long B, d, i, l, N = labs(N0); GEN V, vs, R, M, C, den, L, vP, vD, k = uutoQ(2*r+1, 2); SIGMA_F S = get_S_even(N0); d = dimeven(r, N); B = muleven(N) * mfsturmNgk(N, k); vD = Dpos(d, N0, B); vP = vecRCpol(r, d); l = lg(vD); B = vD[l-1] / N; V = vecfactoru_i(1, B); vs = cgetg(B+2, t_VEC); gel(vs,1) = usumdivk_0_all(r, d); for (i = 1; i <= B; i++) gel(vs, i+1) = usumdivk_fact_all(gel(V,i), r, d); M = cgetg(l, t_MAT); for (i = 1; i < l; i++) { pari_sp av = avma; gel(M,i) = gerepileupto(av, S(r, d, vD[i], vs, vP)); } M = shallowtrans(M); if (r == 2*d) { /* r = 2 or (r = 4 and N = 4) */ GEN v = mfDcoefs(mfderiv(mfTheta(NULL), d+1), vD, 1); gel(M, d) = gadd(gel(M, d), gdivgu(v, N*(2*d - 1))); } R = Hcol(k, r, vD, 1, (N == 8 || N0 == 12)? N >> 2: 1); /* Cost is O(d^2) * bitsize(result) ~ O(d^3.8) [heuristic] */ C = myinverseimage(M, R, &den); /* Cost: O( sqrt(D)/c d^3 log(D) ), c from findNeven */ L = RgV_dotproduct(C, S(r, lg(C)-1, D, NULL, vP)); return den? gdiv(L, den): L; } /***********************************************************/ /* Modular form method using Half-Integral Weight forms */ /* Case D < 0 */ /***********************************************************/ static long dimodd(long r, long kro, long N) { switch(N) { case 1: switch (kro) { case -1:return (r + 3) >> 2; case 0: return (r + 2)/3; case 1: return (r + 1) >> 2; } case 3: return kro? (r + 1) >> 1: ((r << 1) + 2)/3; case 5: switch (kro) { case -1:return (3*r + 2) >> 2; case 0: return r; case 1: return (3*r - 1) >> 2; } case 6: return kro == 1 ? (r + 1) >> 1 : r; default: return r; } } static GEN Dneg(long n, long kro, long d, long N) { GEN vD = cgetg(maxss(n, d) + 1, t_VECSMALL); long D, c, step, N2 = odd(N)? N: N>> 1; switch(kro) { case -1: D = -3; step = 8; break; case 1: D = -7; step = 8; break; default: D = -8; step = 4; break; } for (c = 1; D >= -n || c <= d; D -= step) if (kross(-D, N2) != -1 && sisfundamental(D)) vD[c++] = -D; setlg(vD, c); return vD; } static GEN div4(GEN V) { long l = lg(V), i; GEN W = cgetg(l, t_VECSMALL); for (i = 1; i < l; i++) W[i] = V[i] >> 2; return W; } static GEN usumdivktwist_fact_all(GEN fa, long k, long d) { GEN V, P, E, pow, res = cgetg(d + 1, t_VEC); long i, j, l; P = gel(fa, 1); l = lg(P); E = gel(fa, 2); if (l > 1 && P[1] == 2) { l--; P++; E++; } /* odd part */ pow = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(pow, i) = vpowp(k, d, P[i], -1); V = cgetg(l, t_VEC); for (j = 1; j <= d; j++) { for (i = 1; i < l; i++) gel(V,i) = euler_sumdiv(gmael(pow,i,j), E[i]); gel(res, j) = ZV_prod(V); } return res; } static long mulodd(long N, long kro) { if (N == 1 || N == 2) return 1; if (kro != 1) return kro? 5: 7; if (N == 3) return 4; if (N == 5) return 5; return 2; } /* Cost: O( sqrt(D)/a d^3 log(D) ) */ static GEN sigsumtwist(long k, long dim, long a, long b, long Da, long N, GEN vs, GEN vP) { GEN vPD, S = zerocol(dim), keep0 = NULL; long D2, n, c1, c2, s, lim = usqrt(Da), d; pari_sp av; if (N > 2 && kross(Da, N == 6 ? 3 : N) == -1) return S; d = (dim + 1) >> 1; vPD = RgXV_rescale(vP, stoi(Da)); D2 = (Da - b*b)/N; c1 = (2*a*b)/N; c2 = (a*a)/N; av = avma; for (s = b, n = 0; s <= lim; s += a, n++) { long v2, D4, Ds2, Ds = D2 - n*(c2*n + c1); /* (Da - s^2) / N */ GEN v, P; if (!Ds) continue; v2 = vals(Ds); Ds2 = Ds >> v2; D4 = Ds2 & 3L; /* (Ds/2^oo) mod 4 */ if (vs) v = gel(vs, Ds+1); else v = usumdivktwist_fact_all(factoru(Ds2), k, d); P = gsubst(vPD, 0, utoi(s*s)); v = RgV_multwist(v, P, k, dim, d, v2, D4); if (!s) keep0 = gclone(v); else S = gadd(S, v); if (gc_needed(av, 1)) S = gerepileupto(av, S); } S = gmul2n(S, 1); if (keep0) { S = gadd(S, keep0); gunclone(keep0); } return gmul2n(S, -2*(d-1)); } /* Da = |D|; [sum sigma_r^(1)(Da-s^2), sum sigma_r^(2)(Da-s^2)], N = 1 */ static GEN sigsumtwist11(long k, long dim, long Da, long N, GEN vs, GEN vP) { return sigsumtwist(k, dim, 1, 0, Da, N, vs, vP); } /* Da = |D| or |D|/4 */ /* [sum sigma_r^(1)((Da-s^2)/N), sum sigma_r^(2)((Da-s^2)/N)] */ /* Case N|Da; N not necessarily prime. */ static GEN sigsumtwist12p0(long k, long dim, long Da, long N, GEN vs, GEN vP) { return sigsumtwist(k, dim, N, 0, Da, N, vs, vP); } /* [sum sigma_r^(1)((Da-s^2)/p), sum sigma_r^(2)((Da-s^2)/p)] */ /* Case p\nmid Da */ /* p = 3: s = +-1 mod 3; * p = 5: s = +-1 mod 5 if Da = 1 mod 5, s = +-2 mod 5 if Da = 2 mod 5; * p = 7: s=+-1, +-2, +-3 if Da=1,4,2 mod 7; * p = 6: s=+-1, +-2, +-3 if Da=1,4,3 mod 6 */ static GEN sigsumtwist12pt(long k, long dim, long Da, long N, GEN vs, GEN vP) { long t = Da%N, e = 0; GEN res; if (t == 1) e = 1; else if (t == 4) e = 2; else if (t == 2 || t == 3) e = 3; res = sigsumtwist(k, dim, N, N-e, Da, N, vs, vP); if (N-e != e) res = gadd(res, sigsumtwist(k, dim, N, e, Da, N, vs, vP)); return res; } static GEN sigsumtwist12_6(long r, long dim, long Da, long N, GEN vs, GEN vP) { if (Da%12 == 6) return sigsumtwist12p0(r, dim, Da, N, vs, vP); return sigsumtwist12pt(r, dim, Da, N, vs, vP); } static GEN sigsumtwist12_N(long r, long dim, long Da, long N, GEN vs, GEN vP) { if (Da%N == 0) return sigsumtwist12p0(r, dim, Da, N, vs, vP); return sigsumtwist12pt(r, dim, Da, N, vs, vP); } typedef GEN (*SIGMA_Fodd)(long,long,long,long,GEN,GEN); static SIGMA_Fodd get_S_odd(long N) { if (N == 1) return sigsumtwist11; if (N == 6) return sigsumtwist12_6; return sigsumtwist12_N; } /* L(\chi_D, 1-r) for D < 0 and r > 0 odd. */ static GEN modularodd(long D, long r, long N0) { long B, d, i, l, dim, kro = kross(D, 2), Da = labs(D), N = labs(N0); GEN V, vs, R, M, C, den, L, vP, vD, vD4, k = uutoQ(2*r+1, 2); SIGMA_Fodd S = get_S_odd(N); dim = dimodd(r, kro, N); d = (dim + 1) >> 1; vP = vecRCpol(r, d); B = mulodd(N, kro) * mfsturmNgk(4*N, k); vD = Dneg(B, kro, dim + 5, N); vD4 = kro ? vD : div4(vD); l = lg(vD); B = vD4[l-1] / N; V = vecfactoru_i(1, B); vs = cgetg(B+2, t_VEC); gel(vs,1) = NULL; /* unused */ for (i = 1; i <= B; i++) gel(vs,i+1) = usumdivktwist_fact_all(gel(V,i), r, d); M = cgetg(l, t_MAT); for (i = 1; i < l; i++) { pari_sp av = avma; gel(M,i) = gerepileupto(av, S(r, dim, vD4[i], N, vs, vP)); } M = shallowtrans(M); R = Hcol(k, r, vD, kro? 1: 4, odd(N)? N: N >>1); /* Cost O(d^2) * bitsize(result) ~ O(d^3.7) [heuristic] */ C = myinverseimage(M, R, &den); if (!kro) Da >>= 2; /* Cost: O( sqrt(D)/c d^3 log(D) ), c from findNodd */ L = RgV_dotproduct(C, S(r, lg(C)-1, Da, N, NULL, vP)); if (N0 < 0 && (N0 != -6 || Da%3)) den = den? shifti(den,1): gen_2; return den? gdiv(L, den): L; } /********************************************************/ /* Using the Full Functional Equation */ /********************************************************/ /* prod_p (1 - (D/p)p^(-k)) * Cost O( D/log(D) (k log(kD))^mu ), mu = multiplication exponent */ static GEN Linv(long D, long k, ulong den) { pari_sp av; long s, bit, lim, Da = labs(D), prec; double km = k - 1, B = (k-0.5) * log(km*Da/17.079) + 12; /* 17.079 ~ 2Pi e */ forprime_t iter; ulong p; GEN P, Q; if (den) B += log((double)den); bit = maxss((long)(B * k)/(M_LN2 * km), 32) + 32; prec = nbits2prec(bit); lim = (long)exp( (B-log(km)) / km ); /* ~ D / (2Pi e) */ u_forprime_init(&iter, 3, lim); av = avma; s = kross(D, 2); if (!s) P = real_1(prec); else { Q = real2n(-k, nbits2prec(bit - k)); P = (s == 1)? subir(gen_1, Q): addir(gen_1, Q); } while ((p = u_forprime_next(&iter))) { long bitnew; GEN Q; s = kross(D, p); if (!s) continue; bitnew = (long)(bit - k * log2(p)); Q = divrr(P, rpowuu(p, k, nbits2prec(maxss(64, bitnew)))); P = s == 1? subrr(P, Q): addrr(P, Q); if (gc_needed(av,1)) P = gerepileuptoleaf(av, P); } return P; } static GEN myround(GEN z, ulong d) { long e; if (d) z = mulru(z, d); z = grndtoi(z, &e); if (e >= -4) pari_err_BUG("lfunquad"); return d? Qdiviu(z, d): z; } /* D != 1, k > 2; L(\chi_D, 1-k) using func. eq. */ static GEN Lfeq(long D, long k) { GEN z, res; long Da, prec, den = 0; if ((D > 0 && odd(k)) || (D < 0 && !odd(k))) return gen_0; Da = labs(D); if (Da & 3) { long d = (Da - 1) >> 1, kd = k / d; if (odd(kd) && !(k % d) && uisprime(Da)) den = kd * Da; } else if (Da == 4) den = 2; z = Linv(D, k, den); prec = realprec(z); z = mulrr(z, powrs(divru(Pi2n(1, prec), Da), k)); if (Da != 4) { z = mulrr(z, sqrtr_abs(utor(Da,prec))); shiftr_inplace(z,-1); } res = divrr(mpfactr(k-1, prec), z); if (odd(k/2)) togglesign(res); return myround(res, den); } /* heuristic */ static long usefeq(long D, long k, double c) { if (k == 2) return 0; if (D < 0) { k = 2*k; D = -D; } return sqrt(D*c) <= k; } static long findNeven(long D, double *c) { long r = D%3; if (!r) { *c = 3; return 12; } if ((D&7L) == 1) { *c = 2; return 16; } if (!odd(D)) { *c = 2; return 8; } if (r == 1) { *c = 1.5; return -12; } *c = 1; return 4; } static long findNodd(long D, long k, double *c) { long Dmod8 = D&7L, r; if (log(k) > 0.7 * log((double)-D)) { *c = 1; return odd(D)? 2: 1; } if (D%7 == 0 && Dmod8 == 5) { *c = 3.5; return 7; } if (D%6 == 0) { *c = 3; return 6; } if (D%5 == 0) { *c = 2.5; return 5; } if (D%3 == 0) { *c = 1.5; return 3; } if (Dmod8 == 5) { r = smodss(D, 7); if (r!=1 && r!=2 && r!=4) { *c = 7./6; return -7; } } if (smodss(D, 3) != 1 && !odd(D)) { *c = 1.5; return -6; } r = smodss(D, 5); if (r != 2 && r != 3) { *c = 5./4; return -5; } *c = 1; return 2; } /* k <= 0 */ static GEN lfunquadneg_i(long D, long k) { double c; long N; if (D == 1) return k == 0 ? gneg(ghalf) : gdivgs(bernfrac(1-k), k-1); if (!sisfundamental(D)) pari_err_TYPE("lfunquad [D not fundamental]",stoi(D)); if (k == 0) return D < 0? hclassno(stoi(-D)): gen_0; if ((D > 0 && !odd(k)) || (D < 0 && odd(k))) return gen_0; if (D == -4) return gmul2n(eulerfrac(-k), -1); k = 1 - k; N = D < 0? findNodd(D, k, &c): findNeven(D, &c); if (usefeq(D, k, c)) return Lfeq(D, k); return D < 0? modularodd(D,k,N): modulareven(D,k,N); } /* need k <= 0 and D fundamental */ GEN lfunquadneg(long D, long k) { pari_sp av = avma; return gerepileupto(av, lfunquadneg_i(D, k)); } pari-2.17.2/src/basemath/zetamult.c0000644000175000017500000007167214676526175015610 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /********************************************************************/ /** **/ /** MULTIPLE ZETA VALUES **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_zetamult /********************************************************************/ /** CONVERSIONS **/ /********************************************************************/ /* vecsmall to binary */ static long fd(GEN evec, long a, long b) { long i, s = 0; for (i = a; i <= b; i++) s = evec[i] | (s << 1); return s; } /* 2^(b-a+1) + fd(evec) */ static long fd1(GEN evec, long a, long b) { long i, s = 1; for (i = a; i <= b; i++) s = evec[i] | (s << 1); return s; } /* m > 0 */ static GEN mtoevec(GEN m) { GEN e = vecsmall_append(binary_zv(m), 1); e[1] = 0; return e; } static GEN etoindex(GEN evec) { return utoipos(fd1(evec, 2, lg(evec)-2)); } /* dual of evec[1..l-1] */ static GEN revslice(GEN evec, long l) { GEN res = cgetg(l, t_VECSMALL); long i; for (i = 1; i < l; i++) res[i] = 1 - evec[l-i]; return res; } /* N.B. evec[ne] = 1 */ static GEN etoa(GEN evec) { long c = 0, cold = 0, i = 1, l = lg(evec); GEN avec = cgetg(l, t_VECSMALL); while (++c < l) if (evec[c] == 1) { avec[i++] = c - cold; cold = c; } setlg(avec, i); return avec; } static GEN atoe(GEN avec) { long i, j, l = lg(avec), n = zv_sum(avec); GEN evec = zero_zv(n); for (i = 1, j = 0; i < l; i++) { long a = avec[i]; j += a; evec[j] = 1; } return evec; } /* Conversions: types are evec, avec, m (if evec=0y1, m=(1y)_2). fl is respectively 0, 1, 2. Type of a is autodetected. */ static GEN zetamultconvert_i(GEN a, long fl) { long i, l; if (fl < 0 || fl > 2) pari_err_FLAG("zetamultconvert"); switch(typ(a)) { case t_INT: if (signe(a) <= 0) pari_err_TYPE("zetamultconvert",a); switch (fl) { case 0: a = mtoevec(a); break; case 1: a = etoa(mtoevec(a)); break; case 2: a = icopy(a); break; } break; case t_VEC: case t_COL: case t_VECSMALL: a = gtovecsmall(a); l = lg(a); if (a[1] == 0) { if (!a[l-1]) pari_err_TYPE("zetamultconvert", a); for (i = 1; i < l; i++) if (a[i] & ~1UL) pari_err_TYPE("zetamultconvert", a); switch (fl) { case 1: a = etoa(a); break; case 2: a = etoindex(a); } } else { if (a[1] < 2) pari_err_TYPE("zetamultconvert", a); for (i = 2; i < l; i++) if (a[i] <= 0) pari_err_TYPE("zetamultconvert", a); switch (fl) { case 0: a = atoe(a); break; case 2: a = etoindex(atoe(a)); } } break; default: pari_err_TYPE("zetamultconvert", a); } return a; } GEN zetamultconvert(GEN a, long fl) { pari_sp av = avma; return gerepileuptoleaf(av, zetamultconvert_i(a, fl)); } GEN zetamultdual(GEN s) { pari_sp av = avma; GEN e = zetamultconvert_i(s, 0); return gerepileuptoleaf(av, etoa(revslice(e, lg(e)))); } /********************************************************************/ /** AVEC -> LIST OF STAR AVECS **/ /********************************************************************/ /* all star avecs corresponding to given t_VECSMALL avec */ static GEN allstar(GEN avec) { long i, la = lg(avec), K = 1 << (la - 2); GEN w = cgetg(K + 1, t_VEC); gel(w, 1) = avec; for (i = 2; i < la; i++) { long L = 1 << (i - 2), j; for (j = 1; j <= L; j++) { GEN u = gel(w,j), v; long k, l = lg(u) - 1, ind = l - la + i; gel(w, L + j) = v = cgetg(l, t_VECSMALL); for (k = 1; k < ind; k++) v[k] = u[k]; v[ind] = u[ind] + u[ind + 1]; for (k = ind + 1; k < l; k++) v[k] = u[k+1]; } } return w; } /* same for multipolylogs */ static GEN allstar2(GEN avec, GEN zvec) { long la = lg(avec), i, K = 1 << (la - 2); GEN W = cgetg(K + 1, t_VEC), Z = cgetg(K + 1, t_VEC); gel(W, 1) = avec; gel(Z, 1) = zvec = gtovec(zvec); for (i = 2; i < la; i++) { long L = 1 << (i - 2), j; for (j = 1; j <= L; j++) { GEN u = gel(W, j), w, y = gel(Z, j), z; long l = lg(u) - 1, ind = l - la + i, k; w = cgetg(l, t_VECSMALL); z = cgetg(l, t_VEC); for (k = 1; k < ind; k++) { w[k] = u[k]; gel(z, k) = gel(y, k); } w[ind] = u[ind] + u[ind + 1]; gel(z, ind) = gmul(gel(y, ind), gel(y, ind + 1)); for (k = ind + 1; k < l; k++) { w[k] = u[k+1]; gel(z, k) = gel(y, k+1); } gel(W, L + j) = w; gel(Z, L + j) = z; } } return mkvec2(W, Z); } /**************************************************************/ /* ZAGIER & RADCHENKO'S ALGORITHM */ /**************************************************************/ /* accuracy 2^(-b); s << (b/log b)^2, l << b/sqrt(log b) */ static void zparams(long *s, long *l, long b) { double D = b * LOG10_2, E = 3*D/2 / log(3*D); *s = (long)floor(E*E); *l = (long)floor(sqrt(*s * log((double)*s)/2.)); } static GEN zetamult_Zagier(GEN avec, long bit, long prec) { pari_sp av; GEN ze, z = NULL, b; long h, r, n, s, l, t = lg(avec) - 1; zparams(&s, &l, bit); ze= cgetg(s + 1, t_VEC); b = cgetg(l + 1, t_VEC); for (r = 1; r <= s; r++) gel(ze,r) = cgetr(prec); for (r = 1; r <= l; r++) gel(b,r) = utor(0, prec); affur(1, gel(b,1)); av = avma; for (r = 1, h = -1; r <= t; r++) { long m, j = avec[r]; GEN q; h += j - 1; z = gen_0; q = h? invr(itor(powuu(s,h), prec)): real_1(prec); for (m = 1; m <= l; m++) { pari_sp av2; GEN S = gel(b, m), C; q = divru(q, s); av2 = avma; C = binomialuu(h + m, m); for (n = 1; n < m; n++) { /* C = binom(h+m, m-n+1) */ S = gsub(S, mulir(C, gel(b, n))); C = diviuexact(muliu(C, m-n+1), h+n); } affrr(divru(S, h+m), gel(b,m)); set_avma(av2); z = gadd(z, gmul(gel(b, m), q)); } for (m = s; m >= 1; m--) { GEN z1 = r == 1? ginv(powuu(m,j)): gdiv(gel(ze, m), powuu(m,j)); z1 = gadd(z, z1); affrr(z, gel(ze, m)); z = z1; } set_avma(av); } return z; } /* Compute t-mzvs; slower than Zagier's code for t=0 */ static GEN zetamult_interpolate2_i(GEN avec, GEN t, long prec) { pari_sp av; GEN a, b, ze, _1; long i, j, n, s, l; zparams(&s, &l, prec2nbits(prec)); n = lg(avec) - 1; a = zeromatcopy(n + 1, l); b = zerovec(l + 1); for (i = 1; i <= n; i++) { long h = avec[n + 1 - i]; if (i == 1) gel(b, h) = gen_1; else for (j = l + 1; j >= 1; j--) { if (j <= h) gel(b, j) = gen_0; else gel(b, j) = gadd(gcoeff(a, i, j-h), gmul(t, gel(b, j-h))); } gcoeff(a, i+1, 1) = gel(b, 2); /* j = 1 */ for (j = 2; j <= l; j++) { /* b[j+1] - sum_{0 <= u < j-1} binom(j,u) a[i+1,u+1]*/ pari_sp av = avma; GEN S = gel(b, j + 1); S = gsub(S, gcoeff(a, i+1, 1)); /* u = 0 */ if (j > 2) S = gsub(S, gmulgu(gcoeff(a, i+1, 2), j)); /* u = 1 */ if (j >= 4) { GEN C = utoipos(j*(j-1) / 2); long u, U = (j-1)/2; for (u = 2; u <= U; u++) { /* C = binom(j, u) = binom(j, j-u) */ GEN A = gadd(gcoeff(a, i+1, u+1), gcoeff(a, i+1, j-u+1)); S = gsub(S, gmul(C, A)); C = diviuexact(muliu(C, j-u), u+1); } if (!odd(j)) S = gsub(S, gmul(C, gcoeff(a,i+1, j/2+1))); } gcoeff(a, i+1, j) = gerepileupto(av, gdivgu(S, j)); } } _1 = real_1(prec + EXTRAPREC64); av = avma; ze = cgetg(n+1, t_VEC); for (i = 1; i <= n; i++) { GEN S = gdivgu(gcoeff(a, n+2-i, 1), s), sj = utoipos(s); for (j = 2; j <= l; j++) { sj = muliu(sj, s); /* = s^j */ S = gadd(S, gdiv(gcoeff(a, n+2-i, j), sj)); } gel(ze, i) = S; } for (i = s; i >= 1; i--) { GEN b0 = divri(_1, powuu(i, avec[n])), z; z = gel(ze,n); gel(ze,n) = gadd(z, b0); for (j = n-1; j >= 1; j--) { b0 = gdiv(gadd(gmul(t, b0), z), powuu(i, avec[j])); z = gel(ze,j); gel(ze,j) = gadd(gel(ze,j), b0); } if (gc_needed(av, 1)) { if (DEBUGMEM>1) pari_warn(warnmem,"zetamult: i = %ld", i); ze = gerepilecopy(av, ze); } } return gel(ze, 1); } /********************************************************************/ /** AKHILESH ALGORITHM **/ /********************************************************************/ /* a t_VECSMALL, upper bound for -log2(zeta(a)) */ static long log2zeta_bound(GEN a) { return ceil(-dbllog2(zetamult_Zagier(a, 32, LOWDEFAULTPREC))); } /* ibin[n+1] = 1 / binom(2n, n) as a t_REAL */ static void get_ibin(GEN *pibin, GEN *pibin1, long N, long prec) { GEN ibin, ibin1; long n; *pibin = ibin = cgetg(N + 2, t_VEC); *pibin1= ibin1= cgetg(N + 2, t_VEC); gel(ibin,1) = gel(ibin1,1) = gen_0; /* unused */ gel(ibin,2) = gel(ibin1,2) = real2n(-1,prec); for (n = 2; n <= N; n++) { gel(ibin, n+1) = divru(mulru(gel(ibin, n), n), 4*n-2); gel(ibin1, n+1) = divru(gel(ibin, n+1), n); } } /**************************************************************/ /* ALL MZV's */ /**************************************************************/ /* Generalization to Multiple Polylogarithms. The basic function is polylogmult which takes two arguments avec, as above, and zvec, the vector of z_j, and the result is $\sum_{n_1>n_2>...>n_r>0}z_1^{n_1}...z_r^{n_r}/(n_1^a_1...n_r^{a_r})$. */ /* Given admissible evec = xe_2....e_{k-1}y, (k>=2), compute a,b,v such that evec = x{1}_{a-1}v{0}_{b-1}y with v empty or admissible. Input: vector w=evec Output: v=wmid, wini, wfin */ static void findabvgen(GEN evec, long _0, long _1, GEN *pwmid, GEN *pwini, GEN *pwfin, long *pa, long *pb) { long s = lg(evec) - 1, m, a, b, j, x = evec[1], y = evec[s]; GEN wmid, wini, wfin; if (s == 2) { *pwmid = cgetg(1, t_VECSMALL); *pwini = mkvecsmall(x); *pwfin = mkvecsmall(y); *pa = *pb = 1; return; } a = s - 1; for (j = 1; j <= s - 2; j++) if (evec[j + 1] != _1) { a = j; break; } *pa = a; b = s - 1; for (j = s - 2; j >= 1; j--) if (evec[j + 1] != _0) { b = s - 1 - j; break; } *pb = b; *pwmid = wmid = a+b < s? vecslice(evec, a+1, s-b): cgetg(1, t_VECSMALL); m = lg(wmid) - 1; *pwini = wini = cgetg(a + m + 1, t_VECSMALL); wini[1] = x; for (j = 2; j <= a; j++) wini[j] = _1; for (; j <= a + m; j++) wini[j] = wmid[j-a]; *pwfin = wfin = cgetg(b + m + 1, t_VECSMALL); for (j = 1; j <= m; j++) wfin[j] = wmid[j]; for (; j < b + m; j++) wfin[j] = _0; wfin[j] = y; } /* y != 0,1 */ static GEN filllg1(GEN ibin1, GEN r1, GEN y, long N, long prec) { GEN v, y1 = gsubgs(gmulsg(2, y), 1), y3 = gmul(y, gsubsg(1, y)); long n; v = cgetg(N + 2, t_VEC); gel(v, N + 1) = gen_0; if (gcmpgs(gnorm(y3),1) > 0) { GEN y2 = gdiv(r1, y3); for (n = N; n >= 1; n--) { pari_sp av2 = avma; GEN z = gmul(y2, gsub(gel(v, n+1), gmul(y1, gel(ibin1, n+1)))); gel(v, n) = gerepileupto(av2, z); } } else { pari_sp av0 = avma; gel(v, 1) = gerepileupto(av0, glog(gdiv(y, gsubgs(y, 1)), prec)); for (n = 1; n < N; n++) { pari_sp av2 = avma; GEN z = gadd(gmul(y3, gel(v, n)), gmul(y1, gel(ibin1, n+1))); gel(v, n + 1) = gerepileupto(av2, z); } } return v; } static GEN fillrec(hashtable *H, GEN evec, long _0, long _1, GEN X, GEN pab, GEN r1, long N) { long n, a, b, s, x0; GEN xy1, x, y, r, wmid, wini, wfin, mid, ini, fin; hashentry *ep = hash_search(H, evec); if (ep) return (GEN)ep->val; findabvgen(evec, _0, _1, &wmid, &wini, &wfin, &a, &b); x = gel(X, evec[1]); s = lg(evec)-1; /* > 1 */ y = gel(X, evec[s]); mid = fillrec(H, wmid, _0, _1, X, pab, r1, N); ini = fillrec(H, wini, _0, _1, X, pab, r1, N); fin = fillrec(H, wfin, _0, _1, X, pab, r1, N); if (evec[1] == _0) { x0 = 1; xy1 = gdiv(r1, y); } else { x0 = 0; xy1 = gdiv(r1, gmul(gsubsg(1, x), y)); } r = cgetg(N+2, t_VEC); gel(r, N+1) = gen_0; for (n = N; n > 1; n--) { pari_sp av = avma; GEN t = gmul(gel(ini, n+1), gmael(pab, n, a)); GEN u = gadd(gmul(gel(fin, n+1), gmael(pab, n, b)), gel(mid, n+1)); GEN v = gdiv(x0? gadd(t, u): gsub(t, u), gmael(pab, n, a+b)); gel(r, n) = gerepileupto(av, gmul(xy1, gadd(gel(r, n+1), v))); } { /* n = 1 */ pari_sp av = avma; GEN t = gel(ini, 2), u = gadd(gel(fin, 2), gel(mid, 2)); GEN v = x0? gadd(t, u): gsub(t, u); gel(r,1) = gerepileupto(av, gmul(xy1, gadd(gel(r,2), v))); } hash_insert(H, (void*)evec, (void*)r); return r; } static GEN aztoe(GEN avec, GEN zvec, long prec) { GEN y, E, u = subsr(1, real2n(10-prec2nbits(prec), LOWDEFAULTPREC)); long i, l = lg(avec); E = cgetg(l, t_VEC); if (l == 1) return E; y = gen_1; for (i = 1; i < l; i++) { long a = avec[i]; GEN e, zi = gel(zvec, i); if (a <= 0 || (a == 1 && i == 1 && gequal1(zi))) pari_err_TYPE("polylogmult [divergent]", avec); if (gequal0(zi)) return NULL; gel(E, i) = e = zerovec(a); gel(e, a) = y = gdiv(y, zi); if (gcmp(gnorm(y), u) < 0) pari_err_TYPE("polylogmult [divergent]", zvec); } return shallowconcat1(E); } /***********************************************************/ /* Special case of zvec = [1,1,...], i.e., zetamult. */ /***********************************************************/ static void findabvgens(GEN evec, GEN *pwmid, GEN *pwini, GEN *pwfin, long *pa, long *pb) { GEN wmid, wini, wfin; long s = lg(evec) - 1, a, b, j, m; if (s == 2) { *pwmid = cgetg(1, t_VECSMALL); *pwini = mkvecsmall(0); *pwfin = mkvecsmall(1); *pa = *pb = 1; return; } a = s - 1; for (j = 1; j <= s - 2; j++) if (!evec[j + 1]) { a = j; break; } *pa = a; b = s - 1; for (j = s - 2; j >= 1; j--) if (evec[j + 1]) { b = s - 1 - j; break; } *pb = b; *pwmid = wmid = a+b < s? vecslice(evec, a+1, s-b): cgetg(1, t_VECSMALL); m = lg(wmid) - 1; *pwini = wini = cgetg(a + m + 1, t_VECSMALL); wini[1] = 0; for (j = 2; j <= a; j++) wini[j] = 1; for (; j <= a + m; j++) wini[j] = wmid[j-a]; *pwfin = wfin = cgetg(b + m + 1, t_VECSMALL); for (j = 1; j <= m; j++) wfin[j] = wmid[j]; for (; j < b + m; j++) wfin[j] = 0; wfin[j] = 1; } static GEN fillrecs(hashtable *H, GEN evec, GEN pab, long N, long prec) { long n, a, b; GEN r, wmid, wini, wfin, mid, ini, fin; hashentry *ep = hash_search(H, evec); if (ep) return (GEN)ep->val; findabvgens(evec, &wmid, &wini, &wfin, &a, &b); mid = fillrecs(H, wmid, pab, N, prec); ini = fillrecs(H, wini, pab, N, prec); fin = fillrecs(H, wfin, pab, N, prec); r = cgetg(N + 2, t_VEC); gel(r, N+1) = gen_0; for (n = N; n > 1; n--) { GEN z = cgetr(prec); pari_sp av = avma; GEN t = mpmul(gel(ini, n+1), gmael(pab, n, a)); GEN u = mpadd(mpmul(gel(fin, n+1), gmael(pab, n, b)), gel(mid,n+1)); GEN v = mpdiv(mpadd(t, u), gmael(pab, n, a+b)); mpaff(mpadd(gel(r, n+1), v), z); set_avma(av); gel(r,n) = z; } { /* n = 1 */ GEN z = cgetr(prec); pari_sp av = avma; GEN t = gel(ini,2), u = mpadd(gel(fin,2), gel(mid,2)), v = mpadd(t, u); mpaff(mpadd(gel(r, 2), v), z); set_avma(av); gel(r,1) = z; } hash_insert(H, (void*)evec, (void*)r); return r; } /* [n, ..., n^k] */ static GEN powersu(ulong n, long k) { GEN v, gn = utoipos(n); long i, l = k+1; v = cgetg(l, t_VEC); gel(v,1) = gn; for (i = 2; i < l; i++) gel(v,i) = muliu(gel(v,i-1), n); return v; } /* n^a = pab[n][a] */ static GEN get_pab(long N, long k) { GEN v = cgetg(N+1, t_VEC); long j; gel(v, 1) = gen_0; /* not needed */ for (j = 2; j <= N; j++) gel(v, j) = powersu(j, k); return v; } static hashtable * zetamult_hash(long _0, long _1, GEN ibin, GEN ibin1) { hashtable *H = hash_create(4096, (ulong(*)(void*))&hash_zv, (int(*)(void*,void*))&zv_equal, 1); hash_insert(H, (void*)cgetg(1, t_VECSMALL), (void*)ibin); hash_insert(H, (void*)mkvecsmall(_0), (void*)ibin1); hash_insert(H, (void*)mkvecsmall(_1), (void*)ibin1); return H; } /* Akhilesh recursive algorithm, #a > 1; * e t_VECSMALL, prec final precision, bit required bitprecision */ static GEN zetamult_Akhilesh(GEN e, long bit, long prec) { long k = lg(e) - 1, N = 1 + bit/2, prec2 = nbits2prec(bit); GEN r, pab, ibin, ibin1; hashtable *H; get_ibin(&ibin, &ibin1, N, prec2); pab = get_pab(N, k); H = zetamult_hash(0, 1, ibin, ibin1); r = fillrecs(H, e, pab, lg(pab)-1, prec2); if (DEBUGLEVEL) err_printf("polylogmult: k = %ld, %ld nodes\n", k, H->nb); return gprec_wtrunc(gel(r,1), prec); } /* lump together close entries + round to 1 entries that are ~ 1 */ static GEN vec_round(GEN V, long b) { GEN v = shallowcopy(V), w = shallowcopy(v); long i, j, l = lg(v); for (i = 1; i < l; i++) { long e; if (!gel(v,i)) continue; if (gexpo(gsubgs(gel(v,i), 1)) < b) gel(w,i) = gel(v,i) = gen_1; e = gexpo(gel(v,i)); for (j = i+1; j < l; j++) if (gel(v,j) && gexpo(gsub(gel(v,i), gel(v,j))) - e < b) { gel(v,j) = NULL; gel(w,j) = gel(w,i); } } return w; } /* evec t_VEC */ static GEN zetamultevec(GEN evec, long prec) { pari_sp av = avma; double *x, *y, z = 0; long b, i, j, l, lH, bitprec, prec2, N, _0 = 0, _1 = 0, k = lg(evec) - 1; GEN r1, r, pab, ibin, ibin1, X, Evec, v; hashtable *H; if (k == 0) return gen_1; evec = vec_round(evec, 3 - prec2nbits(prec)); v = vec_equiv(evec); l = lg(v); Evec = cgetg(k+1, t_VECSMALL); X = cgetg(l + 2, t_VEC); /* our alphabet */ for (i = lH = 1; i < l; i++) { GEN vi = gel(v,i), xi = gel(evec, vi[1]); long li = lg(vi); gel(X,i) = xi; if (!_0 && gequal0(xi)) _0 = i; else if (!_1 && gequal1(xi)) _1 = i; for (j = 1; j < li; j++) Evec[vi[j]] = i; } /* add 0,1 if needed */ if (!_0) { gel(X, i) = gen_0; _0 = i++; } if (!_1) { gel(X, i) = gen_1; _1 = i++; } l = i; setlg(X, l); av = avma; x = (double*)stack_malloc_align(l * sizeof(double), sizeof(double)); y = (double*)stack_malloc_align(l * sizeof(double), sizeof(double)); for (j = 1; j < l; j++) { GEN t = gel(X,j); x[j] = (j == _1)? 0: -dbllog2(gsubsg(1, t)); y[j] = (j == _0)? 0: -dbllog2(t); } for (i = 1; i < l; i++) for (j = i+1; j < l; j++) z = maxdd(z, x[i] + y[j]); b = 0; for (i = 1; i < l; i++) { GEN t = real_i(gel(X,i)); long e = -gexpo(gsubgs(gmul2n(t,1), 1)); b = maxss(b, e); } set_avma(av); if (z >= 2) pari_err_IMPL("polylogmult in this range"); bitprec = prec2nbits(prec) + 64*(1 + (k >> 5)); N = 1 + bitprec / (2 - z); bitprec += z * N; prec2 = nbits2prec(bitprec + b); X = gprec_wensure(X, prec2); get_ibin(&ibin, &ibin1, N, prec2); pab = get_pab(N, k); H = zetamult_hash(_0, _1, ibin, ibin1); r1 = real_1(prec2); for (i = 1; i < l; i++) if (i != _0 && i != _1) hash_insert(H, mkvecsmall(i), filllg1(ibin1, r1, gel(X,i), N, prec2)); r = fillrec(H, Evec, _0, _1, X, pab, r1, N); if (DEBUGLEVEL) err_printf("polylogmult: k = %ld, %ld nodes\n", k, H->nb); return gprec_wtrunc(gel(r,1), prec); } /* a t_VECSMALL */ static GEN zetamult_i(GEN a, long prec) { long r = lg(a)-1, k, bit; if (r == 0) return gen_1; if (r == 1) return szeta(a[1], prec); bit = prec2nbits(prec); if (bit <= 128) return zetamult_Zagier(a, bit, prec + EXTRAPREC64); k = zv_sum(a); if (((double)r) / (k*k) * bit / log((double)10*bit) < 0.5) return zetamult_Zagier(a, bit, prec + EXTRAPREC64); bit += maxss(log2zeta_bound(a), 64); return zetamult_Akhilesh(atoe(a), bit, prec); } GEN zetamult(GEN s, long prec) { pari_sp av0 = avma, av; GEN z, avec, r = cgetr(prec); av = avma; avec = zetamultconvert_i(s,1); if (lg(avec) == 1) return gc_const(av0, gen_1); z = zetamult_i(avec, prec); affrr(z, r); return gc_const(av, r); } /* If star = NULL: MZV, otherwise Yamamoto interpolation (MZSV for t=1) */ GEN zetamult_interpolate(GEN s, GEN t, long prec) { pari_sp av = avma, av2; long i, k, l, la, bit; GEN avec, v, V; if (lg(s) == 1) return gen_1; if (!t) return zetamult(s, prec); avec = zetamultconvert_i(s, 1); k = zv_sum(avec); bit = prec2nbits(prec); if (bit <= 128 || k > 20 || (bit >> k) < 4) return zetamult_interpolate2_i(vecsmall_reverse(avec), t, prec); v = allstar(avec); l = lg(v); la = lg(avec); V = cgetg(la, t_VEC); for (i = 1; i < la; i++) gel(V,i) = utor(0, prec + EXTRAPREC64); av2 = avma; for (i = 1; i < l; i++, set_avma(av2)) { GEN a = gel(v,i); /* avec */ long n = lg(a)-1; /* > 0 */ affrr(addrr(gel(V,n), zetamult_i(a, prec)), gel(V,n)); } return gerepileupto(av, poleval(vecreverse(V),t)); } GEN polylogmult_interpolate(GEN a, GEN z, GEN t, long prec) { pari_sp av = avma; GEN V, avec, A, AZ, Z; long i, la, l; switch(typ(a)) { case t_VEC: case t_COL: a = gtovecsmall(a); break; case t_VECSMALL: break; default: pari_err_TYPE("polylogmult", a); return NULL;/*LCOV_EXCL_LINE*/ } if (!z) return zetamult_interpolate(a, t, prec); switch (typ(z)) { case t_INT: case t_FRAC: case t_REAL: case t_COMPLEX: z = mkvec(z); break; case t_VEC: case t_COL: break; case t_VECSMALL: z = zv_to_ZV(z); break; default: pari_err_TYPE("polylogmult [z]", z); } if (lg(z) != lg(a)) pari_err_TYPE("polylogmult [#s != #z]", mkvec2(a,z)); if (!t) return gerepilecopy(av, zetamultevec(aztoe(a,z,prec), prec)); avec = zetamultconvert_i(a, 1); la = lg(avec); AZ = allstar2(avec, z); A = gel(AZ, 1); l = lg(A); Z = gel(AZ, 2); V = zerovec(la-1); for (i = 1; i < l; i++) { pari_sp av2 = avma; GEN ai = gel(A,i), e = aztoe(ai, gel(Z,i), prec); long n = lg(ai)-1; /* > 0 */ gel(V,n) = gerepileupto(av2, gadd(gel(V,n), zetamultevec(e, prec))); } return gerepileupto(av, poleval(vecreverse(V),t)); } GEN polylogmult(GEN a, GEN z, long prec) { return polylogmult_interpolate(a, z, NULL, prec); } /**************************************************************/ /* ALL MZV's */ /**************************************************************/ /* Given admissible evec w = 0e_2....e_{k-1}1, compute a,b,v such that * w=0{1}_{b-1}v{0}_{a-1}1 with v empty or admissible. * Input: binary vector evec */ static void findabv(GEN w, long *pa, long *pb, long *pminit, long *pmmid, long *pmfin) { long le = lg(w) - 2; if (le == 0) { *pa = 1; *pb = 1; *pminit = 2; *pmfin = 2; *pmmid = 1; } else { long a, b, j, lv; for (j = 1; j <= le; j++) if (!w[j+1]) break; *pb = b = j; for (j = le; j >= 1; j--) if (w[j+1]) break; *pa = a = le + 1 - j; lv = le + 2 - a - b; if (lv > 0) { long v = fd(w, b + 1, le - a + 2), u = v + (1 << (lv-1)); *pminit = (((1 << b) - 1) << (lv - 1)) + (v/2) + 2; *pmfin = (u << (a - 1)) + 2; *pmmid = (u >> 1) + 2; } else { *pminit = (1 << (b - 1)) + 1; *pmfin = (a == 1) ? 2 : (1 << (a - 2)) + 2; *pmmid = 1; } } } /* Returns L: * L[1] contains zeta(emptyset)_{n-1,n-1}, * L[2] contains zeta({0})_{n-1,n-1}=zeta({1})_{n-1,n-1} for n >= 2, * L[m+2][n] : 1 <= m < 2^{k-2}, 1 <= n <= N + 1 * contains zeta(w)_{n-1,n-1}, w corresponding to m,n * L[m+2] : 2^{k-2} <= m < 2^{k-1} contains zeta(w), w corresponding to m (code: w=0y1 iff m=1y). */ static GEN fillL(long k, long bitprec) { long N = 1 + bitprec/2, prec = nbits2prec(bitprec); long s, j, n, m, K = 1 << (k - 1), K2 = K/2; GEN p1, p2, pab = get_pab(N, k), L = cgetg(K + 2, t_VEC); get_ibin(&gel(L,1), &gel(L,2), N, prec); for (m = 1; m < K2; m++) { gel(L, m+2) = p1 = cgetg(N+1, t_VEC); for (n = 1; n < N; n++) gel(p1, n) = cgetr(prec); gel(p1, n) = gen_0; } for (m = K2; m < K; m++) gel(L, m+2) = utor(0, prec); for (s = 2; s <= k; s++) { /* Assume length evec < s filled */ /* If evec = 0e_2...e_{s-1}1 then m = (1e_2...e_{s-1})_2 */ GEN w = cgetg(s, t_VECSMALL); long M = 1 << (s - 2); pari_sp av = avma; for (m = M; m < 2*M; m++) { GEN pinit, pfin, pmid; long comp, a, b, mbar, minit, mfin, mmid, mc; p1 = gel(L, m + 2); for (j = s - 1, mc = m, mbar = 1; j >= 2; j--, mc >>= 1) { w[j] = mc & 1; mbar = (1 - w[j]) | (mbar << 1); } /* m, mbar are dual; handle smallest, copy the other */ comp = mbar - m; if (comp < 0) continue; /* m > mbar */ if (comp) { p2 = gel(L, mbar + 2); setisclone(p2); /* flag as dual */ } else p2 = NULL; /* no copy needed if m = mbar */ findabv(w, &a,&b,&minit,&mmid,&mfin); pinit= gel(L, minit); pfin = gel(L, mfin); pmid = gel(L, mmid); for (n = N-1; n > 1; n--, set_avma(av)) { GEN t = mpmul(gel(pinit,n+1), gmael(pab, n, b)); GEN u = mpmul(gel(pfin, n+1), gmael(pab, n, a)); GEN v = gel(pmid, n+1), S = s < k ? gel(p1, n+1): p1; S = mpadd(S, mpdiv(mpadd(mpadd(t, u), v), gmael(pab, n, a+b))); mpaff(S, s < k ? gel(p1, n) : p1); if (p2 && s < k) mpaff(S, gel(p2, n)); } { /* n = 1: same formula simplifies */ GEN t = gel(pinit,2), u = gel(pfin,2), v = gel(pmid,2); GEN S = s < k ? gel(p1,2): p1; S = mpadd(S, mpadd(mpadd(t, u), v)); mpaff(S, s < k ? gel(p1,1) : p1); if (p2 && s < k) mpaff(S, gel(p2, 1)); set_avma(av); } if (p2 && s == k) mpaff(p1, p2); } } return L; } /* bit 1 of flag unset: full, otherwise up to duality (~ half) * bit 2 of flag unset: all <= k, otherwise only k * half: 2^(k-3)+ delta_{k even} * 2^(k/2-2), sum = 2^(k-2)+2^(floor(k/2)-1)-1 * full: 2^(k-2); sum = 2^(k-1)-1 */ static GEN zetamultall_i(long k, long flag, long prec) { GEN res, ind, L = fillL(k, prec2nbits(prec) + 32); long m, K2 = 1 << (k-2), n = lg(L) - 1, m0 = (flag & 4L) ? K2 : 1; if (!(flag & 2L)) { res = cgetg(n - m0, t_VEC); ind = cgetg(n - m0, t_VECSMALL); for (m = m0; m < n - 1; m++) { gel(res, m - m0 + 1) = m < K2 ? gmael(L, m + 2, 1) : gel(L, m + 2); ind[m - m0 + 1] = m; } } else { /* up to duality */ long nres, c; if (k == 2) nres = 1; else if (!(flag & 2L)) nres = (1 << (k - 2)) + (1 << ((k/2) - 1)) - 1; else nres = (1 << (k - 1)); res = cgetg(nres + 1, t_VEC); ind = cgetg(nres + 1, t_VECSMALL); for (m = m0, c = 1; m < n - 1; m++) { GEN z = gel(L,m+2); if (isclone(z)) continue; /* dual */ if (m < K2) z = gel(z,1); gel(res, c) = z; ind[c] = m; c++; } setlg(res, c); setlg(ind, c); } return mkvec2(res, ind); } /* fd(e, 2, lg(e)-2), e = atoe(avec) */ static long atom(GEN avec) { long i, m, l = lg(avec); if (l < 3) return 0; m = 1; /* avec[1] != 0 */ for (i = 2; i < l-1; i++) m = (m << avec[i]) + 1; return m << (avec[i]-1); } static long atoind(GEN avec, long flag) { return atom(avec) + (flag? 1: (1 << (zv_sum(avec) - 2))); } /* If flag is unset, L has all k1 <= k, otherwise only k */ static GEN zetamultstar_i(GEN L, GEN avec, long flag) { GEN s = allstar(avec), S = gen_0; long i, l = lg(s); for (i = 1; i < l; i++) S = gadd(S, gel(L, atoind(gel(s,i), flag))); return S; } /* bit 0: notstar/star * bit 1: full/half (ignored if star, always full) * bit 2: all <= k / only k * bit 3: without / with index */ GEN zetamultall(long k, long flag, long prec) { pari_sp av = avma; GEN Lind, L, res; long K, k1, ct, fl; if (flag < 0 || flag > 15) pari_err_FLAG("zetamultall"); if (k < 1) pari_err_DOMAIN("zetamultall", "k", "<", gen_1, stoi(k)); if (k == 1) return cgetg(1, t_VEC); if (k >= 64) pari_err_OVERFLOW("zetamultall"); if (!(flag & 1L)) { /* not star */ Lind = zetamultall_i(k, flag, prec); res = (flag & 8L)? Lind : gel(Lind, 1); return gerepilecopy(av, res); } /* star */ fl = flag & 4L; /* 4 if k, else 0 (all <= k) */ Lind = gerepilecopy(av, zetamultall_i(k, fl, prec)); /* full */ L = gel(Lind, 1); K = 1 << (k - 2); res = cgetg(fl? K+1: 2*K, t_VEC); for (ct = 1, k1 = fl? k: 2; k1 <= k; k1++) { GEN w = cgetg(k1 + 1, t_VECSMALL); long M = 1 << (k1 - 1), m; for (m = 1; m <= M; m += 2) { pari_sp av = avma; long j, mc = m; for (j = k1; j >= 1; j--) { w[j] = mc & 1; mc >>= 1; } gel(res, ct++) = gerepileupto(av, zetamultstar_i(L, etoa(w), fl)); } } if (flag & 8L) res = mkvec2(res, gel(Lind, 2)); return gerepilecopy(av, res); } pari-2.17.2/src/basemath/ramanujantau.c0000644000175000017500000001474514567450071016415 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" /******************************************************************/ /* */ /* RAMANUJAN's TAU FUNCTION */ /* */ /******************************************************************/ /* 4|N > 0, not fundamental at 2; 6 * Hurwitz class number in level 2, * equal to 6*(H(N)+2H(N/4)), H=qfbhclassno */ static GEN Hspec(GEN N) { long v2 = Z_lvalrem(N, 2, &N), v2f = v2 >> 1; GEN t; if (odd(v2)) { v2f--; N = shifti(N,3); } else if (mod4(N)!=3) { v2f--; N = shifti(N,2); } /* N fundamental at 2, v2f = v2(f) s.t. N = f^2 D, D fundamental */ t = addui(3, muliu(subiu(int2n(v2f+1), 3), 2 - kroiu(N,2))); return mulii(t, hclassno6(N)); } static GEN tauprime_i(ulong t, GEN p2_7, GEN p_9, GEN p, ulong tin) { GEN h, a, t2 = sqru(t), D = shifti(subii(p, t2), 2); /* 4(p-t^2) */ /* t mod 2 != tin <=> D not fundamental at 2 */ h = ((t&1UL) == tin)? hclassno6(D): Hspec(D); a = mulii(powiu(t2,3), addii(p2_7, mulii(t2, subii(shifti(t2,2), p_9)))); return mulii(a, h); } GEN ramanujantau_worker(GEN T, GEN p2_7, GEN p_9, GEN p) { ulong tin = mod4(p) == 3? 1: 0; long i, l = lg(T); GEN s = gen_0; for (i = 1; i < l; i++) s = addii(s, tauprime_i(T[i], p2_7, p_9, p, tin)); return s; } /* B <- {a + k * m : k = 0, ..., (b-a)/m)} */ static void arithprogset(GEN B, ulong a, ulong b, ulong m) { long k; for (k = 1; a <= b; a += m, k++) B[k] = a; setlg(B, k); } /* sum_{1 <= t <= N} f(t), f has integer values */ static GEN parsum_u(ulong N, GEN worker) { long a, r, pending = 0, m = usqrt(N); struct pari_mt pt; GEN v, s = gen_0; pari_sp av; mt_queue_start_lim(&pt, worker, m); v = mkvec(cgetg(m + 2, t_VECSMALL)); av = avma; for (r = 1, a = 1; r <= m || pending; r++) { long workid; GEN done; if (r <= m) { arithprogset(gel(v,1), a, N, m); a++; } mt_queue_submit(&pt, 0, r <= m? v: NULL); done = mt_queue_get(&pt, &workid, &pending); if (done) s = gerepileuptoint(av, addii(s, done)); } mt_queue_end(&pt); return s; } static int tau_parallel(GEN n) { return mt_nbthreads() > 1 && expi(n) > 18; } /* Ramanujan tau function for p prime */ static GEN tauprime(GEN p) { pari_sp av = avma; GEN s, p2, p2_7, p_9, T; ulong lim; if (absequaliu(p, 2)) return utoineg(24); /* p > 2 */ p2 = sqri(p); p2_7 = mului(7, p2); p_9 = mului(9, p); lim = itou(sqrtint(p)); if (tau_parallel(p)) { GEN worker = snm_closure(is_entry("_ramanujantau_worker"), mkvec3(p2_7, p_9, p)); s = parsum_u(lim, worker); } else { pari_sp av2 = avma; ulong tin = mod4(p) == 3? 1: 0, t; s = gen_0; for (t = 1; t <= lim; t++) { s = addii(s, tauprime_i(t, p2_7, p_9, p, tin)); if (!(t & 255)) s = gerepileuptoint(av2, s); } } /* 28p^3 - 28p^2 - 90p - 35 */ T = subii(shifti(mulii(p2_7, subiu(p,1)), 2), addiu(mului(90,p), 35)); s = shifti(diviuexact(s, 3), 6); return gerepileuptoint(av, subii(mulii(mulii(p2, p), T), addui(1, s))); } static GEN taugen_n_i(ulong t, GEN G, GEN n4) { GEN t2 = sqru(t); return mulii(mfrhopol_eval(G, t2), hclassno6(subii(n4, t2))); } GEN taugen_n_worker(GEN T, GEN G, GEN n4) { long i, l = lg(T); GEN s = gen_0; for (i = 1; i < l; i++) s = addii(s, taugen_n_i(T[i], G, n4)); return s; } static GEN taugen_n(GEN n, GEN G) { GEN S, r, n4 = shifti(n, 2); ulong t, lim = itou(sqrtremi(n4, &r)); if (r == gen_0) lim--; G = ZX_unscale(G, n); if (tau_parallel(n)) { GEN worker = snm_closure(is_entry("_taugen_n_worker"), mkvec2(G, n4)); S = parsum_u(lim, worker); } else { pari_sp av2 = avma; S = gen_0; for (t = 1; t <= lim; t++) { S = addii(S, taugen_n_i(t, G, n4)); if (!(t & 255)) S = gerepileuptoint(av2, S); } } S = addii(shifti(S,1), mulii(leading_coeff(G), hclassno6(n4))); return gdivgu(S, 12); } /* ell != 12 */ static GEN newtrace(GEN fan, GEN n, long ell) { pari_sp av = avma; GEN D = divisors(fan), G = mfrhopol(ell-2), T = taugen_n(n, G); long i, l = lg(D); for (i = 1; i < l; i++) { GEN d = gel(D, i), q; long c = cmpii(sqri(d), n); if (c > 0) break; q = powiu(d, ell-1); if (c < 0) T = gadd(T, q); else /* d^2 = n */ { T = gadd(T, gmul2n(q, -1)); T = gsub(T, gdivgu(mulii(diviiexact(q,d), mfrhopol_eval(G, utoipos(4))), 12)); break; } } return gerepileuptoint(av, negi(T)); } #ifdef DEBUG static void checkellcong(GEN T, GEN n, long ell) { long V[] = { 0, 691, 0, 3617, 43867, 283*617, 131*593, 0, 657931 }; if (typ(T) != t_INT || umodiu(subii(T, sumdivk(n, ell-1)), V[ell / 2 - 5])) pari_err_BUG("ramanujantau"); } #endif /* Ramanujan tau function for weights ell = 12, 16, 18, 20, 22, 26, * return 0 for <= 0 */ GEN ramanujantau(GEN n, long ell) { pari_sp av = avma; GEN T, P, E, G, F = check_arith_all(n, "ramanujantau"); long j, lP; if (ell < 12 || ell == 14 || odd(ell)) return gen_0; if (!F) { if (signe(n) <= 0) return gen_0; F = Z_factor(n); P = gel(F,1); } else { P = gel(F,1); if (lg(P) == 1 || signe(gel(P,1)) <= 0) return gen_0; n = typ(n) == t_VEC? gel(n,1): NULL; } if (ell > 26 || ell == 24) return newtrace(F, n? n: factorback(F), ell); /* dimension 1: tau is multiplicative */ E = gel(F,2); lP = lg(P); T = gen_1; G = ell == 12? NULL: mfrhopol(ell - 2); for (j = 1; j < lP; j++) { GEN p = gel(P,j), q = powiu(p, ell-1), t, t1, t0 = gen_1; long k, e = itou(gel(E,j)); t1 = t = G? subsi(-1, taugen_n(p, G)) : tauprime(p); for (k = 1; k < e; k++) { GEN t2 = subii(mulii(t, t1), mulii(q, t0)); t0 = t1; t1 = t2; } T = mulii(T, t1); } #ifdef DEBUG checkellcong(T, n, ell); #endif return gerepileuptoint(av, T); } pari-2.17.2/src/basemath/bit.c0000644000175000017500000004141014567450071014472 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" /*********************************************************************/ /** **/ /** BINARY DECOMPOSITION **/ /** **/ /*********************************************************************/ INLINE GEN inegate(GEN z) { return subsi(-1,z); } GEN binary_zv(GEN x) { GEN xp, z; long i, k, lx; if (!signe(x)) return cgetg(1,t_VECSMALL); xp = int_LSW(x); lx = lgefint(x); k = expi(x)+2; z = cgetg(k, t_VECSMALL); k--; for(i = 2; i < lx; i++) { ulong u = *xp; long j; for (j=0; j>j)&1UL; if (!k) break; xp = int_nextW(xp); } return z; } static GEN F2v_to_ZV_inplace(GEN v) { long i, l = lg(v); v[0] = evaltyp(t_VEC) | _evallg(l); for (i = 1; i < l; i++) gel(v,i) = v[i]? gen_1: gen_0; return v; } /* "vector" of l bits (possibly no code word) to nonnegative t_INT */ GEN bits_to_int(GEN x, long l) { long i, j, lz; GEN z, zp; if (!l) return gen_0; lz = nbits2lg(l); z = cgetg(lz, t_INT); z[1] = evalsigne(1) | evallgefint(lz); zp = int_LSW(z); *zp = 0; for(i=l,j=0; i; i--,j++) { if (j==BITS_IN_LONG) { j=0; zp = int_nextW(zp); *zp = 0; } if (x[i]) *zp |= 1UL<> (BITS_IN_LONG - *r)); } else { **w = a; *w = int_nextW(*w); } } /* set k bits starting at word *w plus *r bits, * clearing subsequent bits in the last word touched */ INLINE void int_set_bits(ulong a, long k, GEN *w, long *r) { if (*r) { **w |= a << *r; a >>= BITS_IN_LONG - *r; } else { **w = a; a = 0; } *r += k; if (*r >= BITS_IN_LONG) { *w = int_nextW(*w); *r -= BITS_IN_LONG; for (; *r >= BITS_IN_LONG; *r -= BITS_IN_LONG) { **w = a; a = 0; *w = int_nextW(*w); } if (*r) **w = a; } } /* set k bits from z (t_INT) starting at word *w plus *r bits, * clearing subsequent bits in the last word touched */ INLINE void int_set_int(GEN z, long k, GEN *w, long *r) { long l = lgefint(z) - 2; GEN y; if (!l) { int_set_bits(0, k, w, r); return; } y = int_LSW(z); for (; l > 1; l--) { int_set_ulong((ulong) *y, w, r); y = int_nextW(y); k -= BITS_IN_LONG; } if (k) int_set_bits((ulong) *y, k, w, r); } GEN nv_fromdigits_2k(GEN x, long k) { long l = lg(x) - 1, r; GEN w, z; if (k == 1) return bits_to_int(x, l); if (!l) return gen_0; z = cgetipos(nbits2lg(k * l)); w = int_LSW(z); r = 0; for (; l; l--) int_set_bits(uel(x, l), k, &w, &r); return int_normalize(z, 0); } GEN fromdigits_2k(GEN x, long k) { long l, m; GEN w, y, z; for (l = lg(x) - 1; l && !signe(gel(x, 1)); x++, l--); if (!l) return gen_0; m = expi(gel(x, 1)) + 1; z = cgetipos(nbits2lg(k * (l - 1) + m)); w = int_LSW(z); if (!(k & (BITS_IN_LONG - 1))) { long i, j, t = k >> TWOPOTBITS_IN_LONG; for (; l; l--) { j = lgefint(gel(x, l)) - 2; y = int_LSW(gel(x, l)); for (i = 0; i < j; i++, y = int_nextW(y), w = int_nextW(w)) *w = *y; if (l > 1) for (; i < t; i++, w = int_nextW(w)) *w = 0; } } else { long r = 0; for (; l > 1; l--) int_set_int(gel(x, l), k, &w, &r); int_set_int(gel(x,1), m, &w, &r); } return int_normalize(z, 0); } GEN binaire(GEN x) { ulong m,u; long i,lx,ex,ly,tx=typ(x); GEN y,p1,p2; switch(tx) { case t_INT: return F2v_to_ZV_inplace( binary_zv(x) ); case t_REAL: ex = expo(x); if (!signe(x)) return zerovec(maxss(-ex,0)); lx=lg(x); y=cgetg(3,t_VEC); if (ex > bit_prec(x)) pari_err_PREC("binary"); p1 = cgetg(maxss(ex,0)+2,t_VEC); p2 = cgetg(bit_prec(x)-ex,t_VEC); gel(y,1) = p1; gel(y,2) = p2; ly = -ex; ex++; m = HIGHBIT; if (ex<=0) { gel(p1,1) = gen_0; for (i=1; i <= -ex; i++) gel(p2,i) = gen_0; i=2; } else { ly=1; for (i=2; i>=1) && ly<=ex); } ly=1; if (m) i--; else m=HIGHBIT; } for (; i>=1); m=HIGHBIT; } break; case t_VEC: case t_COL: case t_MAT: y = cgetg_copy(x, &lx); for (i=1; i> *r) & mask; *r += k; if (*r >= BITS_IN_LONG) { *r -= BITS_IN_LONG; *w = int_nextW(*w); if (*r) a |= ((ulong)**w << (k - *r)) & mask; } return a; } /* extract BITS_IN_LONG bits starting at word *w plus *r bits */ INLINE ulong int_get_ulong(GEN *w, long *r) { ulong a = ((ulong) **w) >> *r; *w = int_nextW(*w); if (*r) a |= ((ulong)**w << (BITS_IN_LONG - *r)); return a; } /* extract k bits (as t_INT) starting at word *w plus *r bits */ INLINE GEN int_get_int(long k, GEN *w, long *r) { GEN z = cgetipos(nbits2lg(k)); GEN y = int_LSW(z); for (; k >= BITS_IN_LONG; k -= BITS_IN_LONG) { *y = int_get_ulong(w, r); y = int_nextW(y); } if (k) *y = int_get_bits(k, w, r); return int_normalize(z, 0); } /* assume k < BITS_IN_LONG */ GEN binary_2k_nv(GEN x, long k) { long l, n, r; GEN v, w; if (k == 1) return binary_zv(x); if (!signe(x)) return cgetg(1, t_VECSMALL); n = expi(x) + 1; l = (n + k - 1) / k; v = cgetg(l + 1, t_VECSMALL); w = int_LSW(x); r = 0; for (; l > 1; l--) { uel(v, l) = int_get_bits(k, &w, &r); n -= k; } uel(v, 1) = int_get_bits(n, &w, &r); return v; } GEN binary_2k(GEN x, long k) { long l, n; GEN v, w, y, z; if (k == 1) return binaire(x); if (!signe(x)) return cgetg(1, t_VEC); n = expi(x) + 1; l = (n + k - 1) / k; v = cgetg(l + 1, t_VEC); w = int_LSW(x); if (!(k & (BITS_IN_LONG - 1))) { long m, t = k >> TWOPOTBITS_IN_LONG, u = lgefint(x) - 2; for (; l; l--) { m = minss(t, u); z = cgetipos(m + 2); y = int_LSW(z); for (; m; m--) { *y = *w; y = int_nextW(y); w = int_nextW(w); } gel(v, l) = int_normalize(z, 0); u -= t; } } else { long r = 0; for (; l > 1; l--, n -= k) gel(v, l) = int_get_int(k, &w, &r); gel(v, 1) = int_get_int(n, &w, &r); } return v; } /* return 1 if bit n of x is set, 0 otherwise */ long bittest(GEN x, long n) { if (typ(x) != t_INT) pari_err_TYPE("bittest",x); if (!signe(x) || n < 0) return 0; if (signe(x) < 0) { pari_sp ltop=avma; long b = !int_bit(inegate(x),n); set_avma(ltop); return b; } return int_bit(x, n); } 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 nonnegative 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_TYPE("bitwise negation",x); if (bits < -1) pari_err_DOMAIN("bitwise negation","exponent","<",gen_m1,stoi(bits)); 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 = nbits2lg(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)); } static void checkint2(const char *f,GEN x, GEN y) { if (typ(x)!=t_INT || typ(y)!=t_INT) pari_err_TYPE2(f,x,y); } GEN gbitor(GEN x, GEN y) { pari_sp ltop = avma; GEN z; checkint2("bitwise or",x,y); switch (signs(x, y)) { case 3: /*1,1*/ return ibitor(x,y); case 2: /*1,-1*/ z = ibitnegimply(inegate(y),x); break; case 1: /*-1,1*/ z = ibitnegimply(inegate(x),y); break; default: /*-1,-1*/ z = ibitand(inegate(x),inegate(y)); break; } return gerepileuptoint(ltop, inegate(z)); } GEN gbitand(GEN x, GEN y) { pari_sp ltop = avma; GEN z; checkint2("bitwise and",x,y); switch (signs(x, y)) { case 3: /*1,1*/ return ibitand(x,y); case 2: /*1,-1*/ z = ibitnegimply(x,inegate(y)); break; case 1: /*-1,1*/ z = ibitnegimply(y,inegate(x)); break; default: /*-1,-1*/ z = inegate(ibitor(inegate(x),inegate(y))); break; } return gerepileuptoint(ltop, z); } GEN gbitxor(GEN x, GEN y) { pari_sp ltop = avma; GEN z; checkint2("bitwise xor",x,y); switch (signs(x, y)) { case 3: /*1,1*/ return ibitxor(x,y); case 2: /*1,-1*/ z = inegate(ibitxor(x,inegate(y))); break; case 1: /*-1,1*/ z = inegate(ibitxor(inegate(x),y)); break; default: /*-1,-1*/ z = ibitxor(inegate(x),inegate(y)); break; } return gerepileuptoint(ltop,z); } /* x & ~y */ GEN gbitnegimply(GEN x, GEN y) { pari_sp ltop = avma; GEN z; checkint2("bitwise negated imply",x,y); switch (signs(x, y)) { case 3: /*1,1*/ return ibitnegimply(x,y); case 2: /*1,-1*/ z = ibitand(x,inegate(y)); break; case 1: /*-1,1*/ z = inegate(ibitor(y,inegate(x))); break; default: /*-1,-1*/ z = ibitnegimply(inegate(y),inegate(x)); break; } return gerepileuptoint(ltop,z); } long hammingl(ulong w) { #if 0 return __builtin_popcountl(w); #endif static long byte_weight[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 }; long sum = 0; while (w) { sum += byte_weight[w & 255]; w >>= 8; } return sum; } /* number of nonzero entries among x[a], ..., x[b] */ static long hamming_slice(GEN x, long a, long b) { long i, nb = 0; for (i = a; i <= b; i++) if (!gequal0(gel(x,i))) nb++; return nb; } static long hamming_mat(GEN x) { long i, lx = lg(x), nb = 0; for (i = 1; i < lx; i++) nb += hammingweight(gel(x,i)); return nb; } static long hamming_vecsmall(GEN x) { long i, lx = lg(x), nb = 0; for (i = 1; i < lx; i++) if (x[i]) nb++; return nb; } static long hamming_int(GEN n) { long lx = lgefint(n), i, sum; if (lx == 2) return 0; sum = hammingl(n[2]); for (i = 3; i < lx; i++) sum += hammingl(n[i]); return sum; } long hammingweight(GEN n) { switch(typ(n)) { case t_INT: return hamming_int(n); case t_VEC: case t_COL: return hamming_slice(n, 1, lg(n)-1); case t_POL: return hamming_slice(n, 2, lg(n)-1); case t_VECSMALL: return hamming_vecsmall(n); case t_MAT: return hamming_mat(n); } pari_err_TYPE("hammingweight", n); return 0;/*LCOV_EXCL_LINE*/ } pari-2.17.2/src/basemath/bnflog.c0000644000175000017500000003331714567450071015172 0ustar billbill/* Copyright (C) 2016 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" /*******************************************************************/ /* LOGARITHMIC CLASS GROUP */ /*******************************************************************/ /* min(v, v(Log_p Norm_{F_\p/Q_p}(x))) */ static long vlognorm(GEN nf, GEN T, GEN x, GEN p, long v) { GEN a = nf_to_scalar_or_alg(nf, x); GEN N = RgXQ_norm(a, T); if (typ(N) != t_PADIC) N = cvtop(N, p, v); return minss(v, valp( Qp_log(N) )); } /* K number field, pr a maximal ideal, let K_pr be the attached local * field, K_pr = Q_p[X] / (T), T irreducible. Return \tilde{e}(K_pr/Q_p) */ static long etilde(GEN nf, GEN pr, GEN T) { GEN gp = pr_get_p(pr); ulong e = pr_get_e(pr); long v, voo, vmin, p, k; if (!u_pval(e, gp)) { v = u_pval(pr_get_f(pr), gp); return itou( mului(e, powiu(gp, v)) ); } p = itou(gp); k = e / (p-1) + 1; /* log Norm_{F_P/Q_p} (1 + P^k) = Tr(P^k) = p^[(k + v(Diff))/ e] Z_p */ voo = (k + idealval(nf, nf_get_diff(nf), pr)) / e; vmin = vlognorm(nf, T, pr_get_gen(pr), gp, voo); if (k > 1) { GEN U = idealprincipalunits(nf, pr, k); GEN gen = abgrp_get_gen(U), cyc = abgrp_get_cyc(U); long i, l = lg(cyc); for (i = 1; i < l; i++) { if (voo - Z_lval(gel(cyc,i), p) >= vmin) break; vmin = vlognorm(nf, T, gel(gen,i), gp, vmin); } } v = u_lval(degpol(T), p) + (p == 2UL? 2 : 1) - vmin; (void)u_lvalrem(e, p, &e); return e * upowuu(p,v); } static long ftilde_from_e(GEN pr, long e) { return pr_get_e(pr) * pr_get_f(pr) / e; } /* true nf */ static long ftilde(GEN nf, GEN pr, GEN T) { return ftilde_from_e(pr, etilde(nf, pr, T)); } static long get_ZpX_index(GEN K, GEN pr, GEN T) { GEN p, pi; long j, l = lg(T); if (l == 2) return 1; p = pr_get_p(pr); pi = nf_to_scalar_or_alg(K, pr_get_gen(pr)); for (j = 1; j < l; j++) { GEN t = gel(T,j); if (t && gvaluation(RgXQ_norm(pi, t), p)) return j; } return 0; } /* Given a number field K and a prime p, return * S = places of K above p [primedec] * R = corresponding p-adic factors of K.pol (mod p^k), in the same order */ static GEN padicfact(GEN K, GEN S, long k) { GEN R, p = pr_get_p(gel(S,1)); GEN T = gel(factorpadic(nf_get_pol(K), p, k), 1); long l, i; S = idealprimedec(K, p); R = cgetg_copy(S, &l); for (i = 1; i < l; i++) { long j = get_ZpX_index(K, gel(S,i), T); gel(R,i) = gel(T,j); gel(T,j) = NULL; } return R; } /* K a bnf, compute Cl'(K) = ell-Sylow of Cl(K) / (places above ell). * Return [D, u, R0, U0, ordS] * - D: cyclic factors for Cl'(K) * - u: generators of cyclic factors (all coprime to ell) * - R0: subgroup isprincipal() (divides K.cyc) * - U0: generators of R0 are of the form S . U0 * - ordS[i] = order of S[i] in CL(K) */ static GEN CL_prime(GEN K, GEN ell, GEN Sell) { GEN g, ordS, R0, U0, U, D, u, cyc = bnf_get_cyc(K); long i, l, lD, lS = lg(Sell); g = leafcopy(bnf_get_gen(K)); l = lg(g); for (i = 1; i < l; i++) { GEN A = gel(g,i), a = gcoeff(A,1,1); long v = Z_pvalrem(a, ell, &a); if (v) gel(g,i) = hnfmodid(A, a); /* make coprime to ell */ } R0 = cgetg(lS, t_MAT); ordS = cgetg(lS, t_VEC); for (i = 1; i < lS; i++) { gel(R0,i) = isprincipal(K, gel(Sell,i)); gel(ordS,i) = charorder(cyc, gel(R0,i)); /* order of Sell[i] */ } R0 = shallowconcat(R0, diagonal_shallow(cyc)); /* R0 = subgroup generated by S in Cl(K) [ divides diagonal(K.cyc) ]*/ R0 = ZM_hnfall(R0, &U0, 2); /* [S | cyc] * U0 = R0 in HNF */ D = ZM_snfall(R0, &U,NULL); D = RgM_diagonal_shallow(D); lD = lg(D); u = ZM_inv(U, NULL); settyp(u, t_VEC); for (i = 1; i < lD; i++) gel(u,i) = idealfactorback(K,g,gel(u,i),1); setlg(U0, l); U0 = rowslice(U0,1,lS-1); /* restrict to 'S' part */ return mkvec5(D, u, R0, U0, ordS); } static GEN ell1(GEN ell) { return equaliu(ell,2)? utoipos(5): addiu(ell,1); } /* log N_{F_P/Q_p}(x) */ static GEN vtilde_i(GEN K, GEN x, GEN T, GEN ell, long prec) { GEN N, cx; if (typ(x) != t_POL) x = nf_to_scalar_or_alg(K, x); if (typ(x) != t_POL) { cx = x; N = NULL; } else { x = Q_primitive_part(x,&cx); N = resultant(RgX_rem(x,T), T); N = cvtop(N,ell,prec); } if (cx) { (void)Q_pvalrem(cx, ell, &cx); if (!isint1(cx)) { cx = gpowgs(cvtop(cx,ell,prec), degpol(T)); N = N? gmul(N, cx): cx; } } return N? Qp_log(N): gen_0; } static GEN vecvtilde_i(GEN K, GEN x, GEN T, GEN ell, long prec) { pari_APPLY_same(vtilde_i(K, gel(x,i), T, ell, prec)); } static GEN vtilde(GEN K, GEN x, GEN T, GEN deg, GEN ell, long prec) { pari_sp av; GEN v, G, E; if (typ(x) != t_MAT) return gdiv(vtilde_i(K,x,T,ell,prec), deg); G = gel(x,1); E = gel(x,2); av = avma; v = vecvtilde_i(K,G,T,ell,prec); return gerepileupto(av, gdiv(RgV_dotproduct(E, v), deg)); } /* v[i] = deg S[i] mod p^prec */ static GEN get_vdegS(GEN Ftilde, GEN ell, long prec) { long i, l = lg(Ftilde); GEN v = cgetg(l, t_VEC), degell = Qp_log( cvtop(ell1(ell), ell, prec) ); for (i = 1; i < l; i++) gel(v,i) = gmulsg(Ftilde[i], degell); return v; } /* K a bnf. Compute kernel \tilde{Cl}_K(ell); return cyclic factors. * Set *pM to (vtilde_S[i](US[j]))_{i,j} */ static GEN CL_tilde(GEN K, GEN US, GEN ell, GEN T, long imin, GEN vdegS, GEN *pM, long prec) { long i, j, k, lD, l = lg(T), lU = lg(US); GEN D, M, ellk; /* p = P^e: \tilde{Cl}(l) = (1) */ if (l == 2) { *pM = cgetg(1, t_MAT); return cgetg(1, t_VEC); } M = cgetg(lU, t_MAT); for (j = 1; j < lU; j++) { GEN c = cgetg(l, t_COL), a = gel(US,j); for (i = 1; i < l; i++) gel(c,i) = vtilde(K, a, gel(T,i), gel(vdegS,i), ell, prec); gel(M,j) = c; } k = padicprec(M, ell); ellk = powiu(ell, k); *pM = M = gmod(M, ellk); M = ZM_hnfmodid(rowsplice(M, imin), ellk); D = matsnf0(M, 4); lD = lg(D); if (lD > 1 && Z_pval(gel(D,1), ell) >= k) return NULL; return D; } /* [L:K] = ell^k; return 1 if L/K is locally cyclotomic at ell, 0 otherwise */ long rnfislocalcyclo(GEN rnf) { pari_sp av = avma; GEN K, L, S, SK, TK, SLs, SL2, TL, ell; ulong ll; long i, j, k, lk, lSK; checkrnf(rnf); lk = rnf_get_degree(rnf); if (lk == 1) return 1; k = uisprimepower(lk, &ll); if (!k) pari_err_IMPL("rnfislocalcyclo for non-l-extensions"); ell = utoi(ll); K = rnf_get_nf(rnf); L = rnf_build_nfabs(rnf, nf_get_prec(K)); S = rnfidealprimedec(rnf, ell); SK = gel(S,1); SLs = gel(S,2); SL2 = shallowconcat1(SLs); TK = padicfact(K, SK, 100); lSK = lg(SK); TL = padicfact(L, SL2, 100); for (i = 1; i < lSK; i++) { long eK = etilde(K, gel(SK,i), gel(TK,i)); GEN SL = gel(SLs,i); long lSL = lg(SL); for (j = 1; j < lSL; j++) { long iS = gen_search(SL2, gel(SL,j), (void*)&cmp_prime_over_p, &cmp_nodata); long eL = etilde(L, gel(SL,j), gel(TL,iS)); if (dvdui(eL/eK, ell)) return gc_long(av,0); } }; return gc_long(av,1); } #if 0 /* Return 1 if L/Q is locally cyclotomic at ell */ static int islocalcycloQ(GEN L, GEN ell) { GEN SL = idealprimedec(L,ell), TL; long i, lSL = lg(SL); TL = padicfact(L, SL, 100); for (i = 1; i < lSL; i++) { long eL = etilde(L, gel(SL,i), gel(TL,i)); if (dvdui(eL,ell)) return 0; } return 1; } #endif /* true nf, pr a prid */ static long nfislocalpower_i(GEN nf, GEN pr, GEN a, GEN n) { long v, e, t; GEN p, G, L; a = nf_to_scalar_or_basis(nf,a); if (!signe(n)) return isint1(a); v = nfvalrem(nf, a, pr, &a); if (!dvdsi(v, n)) return 0; p = pr_get_p(pr); v = Z_pvalrem(n, p, &n); if (!equali1(n)) { GEN T, modpr = zk_to_Fq_init(nf, &pr, &T, &p); GEN ap = nf_to_Fq(nf, a, modpr); if (!Fq_ispower(ap, n, T, p)) return 0; } if (!v) return 1; e = pr_get_e(pr); if (v == 1) /* optimal formula */ t = itos( divii(mului(e,p), subiu(p,1)) ) + 1; else /* straight Hensel */ t = 2 * e * v + 1; G = Idealstarprk(nf, pr, t, nf_INIT); L = ideallogmod(nf, a, G, powiu(p, v)); return ZV_equal0(L) || ZV_pval(L, p) >= v; } long nfislocalpower(GEN nf, GEN pr, GEN a, GEN n) { pari_sp av = avma; if (typ(n) != t_INT) pari_err_TYPE("nfislocalpower",n); nf = checknf(nf); checkprid(pr); return gc_long(av, nfislocalpower_i(nf, pr, a, n)); } /* v_ell( exponent(D) ) */ static long ellexpo(GEN D, GEN ell) { return lg(D) == 1? 0: Z_pval(gel(D,1), ell); } static GEN ellsylow(GEN cyc, GEN ell) { long i, l; GEN d = cgetg_copy(cyc, &l); for (i = 1; i < l; i++) { GEN c = gel(cyc,i), a; if (!Z_pvalrem(c, ell, &a)) break; gel(d,i) = diviiexact(c, a); } setlg(d, i); return d; } static long vnorm_x(GEN nf, GEN x, GEN ell) { x = nf_to_scalar_or_alg(nf,x); if (typ(x) != t_POL) return 0; x = Q_primpart(x); return Q_pval(nfnorm(nf,x), ell); } static long vtilde_prec_x(GEN nf, GEN x, GEN ell) { long i, l, v; GEN G; if (typ(x) != t_MAT) return vnorm_x(nf,x,ell); G = gel(x,1); l = lg(G); v = 0; for (i = 1; i < l; i++) v = maxss(v, vnorm_x(nf,gel(G,i),ell)); return v; } /* upper bound for \delta(vec): estimate loss of accuracy when evaluating * \tilde{v} on the vec[i] */ static long vtilde_prec(GEN nf, GEN vec, GEN ell) { long v0 = 0, i, l = lg(vec); for (i = 1; i < l; i++) v0 = maxss(v0, vtilde_prec_x(nf, gel(vec,i), ell)); return 3 + v0 + z_pval(nf_get_degree(nf), ell); } static GEN get_Ftilde(GEN nf, GEN S, GEN T, GEN ell, long *pimin) { long j, lS = lg(S), vmin = lS; GEN Ftilde = cgetg(lS, t_VECSMALL); *pimin = 1; for (j = 1; j < lS; j++) { long f = ftilde(nf, gel(S,j), gel(T,j)), v = z_pval(f, ell); Ftilde[j] = f; if (v < vmin) { vmin = v; *pimin = j; } } return Ftilde; } static GEN bnflog_i(GEN bnf, GEN ell) { long prec0, prec; GEN nf, US, vdegS, S, T, M, CLp, CLt, Ftilde, vtG, ellk; GEN D, Ap, cycAp, fu; long imin, i, j, lvAp; bnf = checkbnf(bnf); nf = bnf_get_nf(bnf); S = idealprimedec(nf, ell); US = sunits_mod_units(bnf, S); prec0 = maxss(30, vtilde_prec(nf, US, ell)); if (!(fu = bnf_build_cheapfu(bnf)) && !(fu = bnf_compactfu(bnf))) bnf_build_units(bnf); US = shallowconcat(fu, US); settyp(US, t_COL); T = padicfact(nf, S, prec0); Ftilde = get_Ftilde(nf, S, T, ell, &imin); CLp = CL_prime(bnf, ell, S); cycAp = gel(CLp,1); Ap = gel(CLp,2); for(;;) { vdegS = get_vdegS(Ftilde, ell, prec0); CLt = CL_tilde(nf, US, ell, T, imin, vdegS, &vtG, prec0); if (CLt) break; prec0 <<= 1; T = padicfact(nf, S, prec0); } prec = ellexpo(cycAp, ell) + ellexpo(CLt,ell) + 1; if (prec == 1) return mkvec3(cgetg(1,t_VEC), cgetg(1,t_VEC), cgetg(1,t_VEC)); ellk = powiu(ell, prec); lvAp = lg(Ap); if (lvAp > 1) { long lS = lg(S); GEN Kcyc = bnf_get_cyc(bnf); GEN C = zeromatcopy(lvAp-1, lS-1); GEN Rell = gel(CLp,3), Uell = gel(CLp,4), ordS = gel(CLp,5); for (i = 1; i < lvAp; i++) { GEN a, b, bi, A = gel(Ap,i), d = gel(cycAp,i); bi = isprincipal(bnf, A); a = ZV_ZV_mod(ZC_Z_mul(bi,d), Kcyc); /* a in subgroup generated by S = Rell; hence b integral */ b = hnf_invimage(Rell, a); b = ZV_ZV_mod(ZM_ZC_mul(Uell, ZC_neg(b)), ordS); A = mkvec2(A, trivial_fact()); A = idealpowred(nf, A, d); /* find a principal representative of A_i^cycA_i up to elements of S */ a = isprincipalfact(bnf,gel(A,1),S,b,nf_GENMAT|nf_FORCE); if (!gequal0(gel(a,1))) pari_err_BUG("bnflog"); a = famat_mul_shallow(gel(A,2), gel(a,2)); /* principal part */ if (lg(a) == 1) continue; for (j = 1; j < lS; j++) gcoeff(C,i,j) = vtilde(nf, a, gel(T,j), gel(vdegS,j), ell, prec0); } C = gmod(gneg(C),ellk); C = shallowtrans(C); M = mkmat2(mkcol2(diagonal_shallow(cycAp), C), mkcol2(gen_0, vtG)); M = shallowmatconcat(M); /* relation matrix */ } else M = vtG; M = ZM_hnfmodid(M, ellk); D = matsnf0(M, 4); if (lg(D) == 1 || !dvdii(gel(D,1), ellk)) pari_err_BUG("bnflog [missing Z_l component]"); D = vecslice(D,2,lg(D)-1); return mkvec3(D, CLt, ellsylow(cycAp, ell)); } GEN bnflog(GEN bnf, GEN ell) { pari_sp av = avma; return gerepilecopy(av, bnflog_i(bnf, ell)); } GEN bnflogef(GEN nf, GEN pr) { pari_sp av = avma; long e, f, ef; GEN p; checkprid(pr); p = pr_get_p(pr); nf = checknf(nf); e = pr_get_e(pr); f = pr_get_f(pr); ef = e*f; if (u_pval(ef, p)) { GEN T = gel(factorpadic(nf_get_pol(nf), p, 100), 1); long j = get_ZpX_index(nf, pr, T); e = etilde(nf, pr, gel(T,j)); f = ef / e; } set_avma(av); return mkvec2s(e,f); } GEN bnflogdegree(GEN nf, GEN A, GEN ell) { pari_sp av = avma; GEN AZ, A0Z, NA0; long vAZ; if (typ(ell) != t_INT) pari_err_TYPE("bnflogdegree", ell); nf = checknf(nf); A = idealhnf_shallow(nf, A); AZ = gcoeff(A,1,1); vAZ = Z_pvalrem(AZ, ell, &A0Z); if (is_pm1(A0Z)) NA0 = gen_1; else (void)Z_pvalrem(idealnorm(nf,A), ell, &NA0); if (vAZ) { GEN Aell = ZM_hnfmodid(A, powiu(ell,vAZ)); GEN S = idealprimedec(nf, ell), T; long l, i, s = 0; T = padicfact(nf, S, 100); l = lg(S); for (i = 1; i < l; i++) { GEN P = gel(S,i); long v = idealval(nf, Aell, P); if (v) s += v * ftilde(nf, P, gel(T,i)); } if (s) NA0 = gmul(NA0, gpowgs(ell1(ell), s)); } return gerepileupto(av, NA0); } pari-2.17.2/src/basemath/nflistQT.c0000644000175000017500000002224714567450071015467 0ustar billbill/* Copyright (C) 2021 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the 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 GEN strtoint(char *s) { long neg = (*s == '-'); GEN n; if (!neg) return strtoi(s); n = strtoi(s+1); togglesign(n); return n; } /* export ? */ static GEN mkZVn(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) = strtoint(va_arg(ap, char*)); va_end(ap); return x; } static GEN /* -t */ pol_mx(long v) { return deg1pol_shallow(gen_m1, gen_0, v); } static GEN QT4(long k, long v) { switch(k) { case 1: return mkpoln(5, gen_1, pol_x(v), stoi(-6), pol_mx(v), gen_1); case 2: return mkpoln(5, gen_1, gen_0, pol_x(v), gen_0, gen_1); case 3: return mkpoln(5, gen_1, pol_x(v), gen_0, pol_x(v), gen_1); default: return NULL; }} static GEN QT5(long k, long v) { GEN a3, a2, a1, a0; switch(k) { case 1: a3 = mkpoln(4, stoi(-2), stoi(-6), stoi(-10), stoi(-10)); setvarn(a3,v); a2 = mkpoln(5, gen_1, stoi(5), stoi(11), stoi(15), stoi(5)); setvarn(a2,v); a1 = mkpoln(4, gen_1, stoi(4), stoi(10), stoi(10)); setvarn(a1,v); return mkpoln(6, gen_1, pol_xn(2,v), a3, a2, a1, gen_1); case 2: a3 = deg1pol_shallow(gen_m1, stoi(-50), v); a1 = deg1pol_shallow(stoi(5), stoi(625), v); a0 = deg1pol_shallow(stoi(-3), gen_0, v); return mkpoln(6, gen_1, gen_0, a3, pol_mx(v), a1, a0); case 3: a2 = deg1pol_shallow(stoi(5), gen_0, v); a0 = deg2pol_shallow(gen_1, gen_m1, stoi(16), v); return mkpoln(6, gen_1, gen_0, stoi(10), a2, stoi(-15), a0); default: return NULL; }} static GEN QT6(long k, long v) { GEN a5, a4, a3, a2, a1, a0; switch(k) { case 1: a5 = deg1pol_shallow(gen_2, gen_0, v); a4 = deg1pol_shallow(stoi(-5), stoi(-15), v); a2 = deg1pol_shallow(stoi(5), gen_0, v); a1 = deg1pol_shallow(gen_m2, stoi(-6), v); return mkpoln(7, gen_1, a5, a4, stoi(20), a2, a1, gen_1); case 2: a0 = deg2pol_shallow(stoi(3), gen_0, stoi(4), v); return mkpoln(7, gen_1, gen_0, stoi(6), gen_0, stoi(9), gen_0, a0); case 3: return mkpoln(7, gen_1, gen_0, stoi(6), gen_0, stoi(9), gen_0, pol_mx(v)); case 4: a2 = deg1pol_shallow(gen_1, stoi(-3), v); return mkpoln(7, gen_1, gen_0, pol_x(v), gen_0, a2, gen_0, gen_m1); case 5: a4 = deg1pol_shallow(gen_1, stoi(-6), v); a3 = deg1pol_shallow(gen_2, gen_m2, v); a2 = deg1pol_shallow(gen_1, stoi(9), v); return mkpoln(7, gen_1, gen_0, a4, a3, a2, stoi(6), gen_1); case 6: a2 = mkpoln(5,stoi(-12),gen_0,stoi(-36),gen_0,gen_0); setvarn(a2,v); a0 = mkpoln(7,stoi(16),gen_0,stoi(48),gen_0,gen_0,gen_0,gen_0); setvarn(a0,v); return mkpoln(7, gen_1, gen_0, gen_0, gen_0, a2, gen_0, a0); case 7: return mkpoln(7, gen_1,gen_0,gen_0,gen_0,pol_x(v),gen_0,gen_m1); case 8: a0 = deg2pol_shallow(stoi(3), gen_0, stoi(4), v); return mkpoln(7, gen_1,gen_0,stoi(-3),gen_0,gen_0,gen_0,a0); case 9: a4 = deg2pol_shallow(stoi(3), gen_0, stoi(-6), v); a3 = deg2pol_shallow(gen_m2, gen_0, stoi(4), v); return mkpoln(7, gen_1,gen_0,a4,a3,stoi(9),stoi(-12),stoi(4)); case 10: a0 = deg2pol_shallow(gen_m1, gen_0, stoi(-1024), v); return mkpoln(7, gen_1,stoi(-12),stoi(36),gen_0,gen_0,gen_0,a0); case 11: a0 = deg1pol_shallow(gen_1, stoi(4), v); return mkpoln(7, gen_1,gen_0,stoi(-3),gen_0,gen_0,gen_0,a0); case 12: a5 = deg2pol_shallow(stoi(10), gen_0, stoi(-50), v); a4 = gtopoly(mkvecsmall5(55, 0,-550, 0, 1375), v); a3 = gtopoly(mkvecsmalln(7, 140L, 0L,-2100L, 0L, 10500L, 0L,-17500L), v); a2 = gtopoly(mkvecsmalln(9, 175L, 0L,-3500L, 0L, 26250L, 0L,-87500L, 0L, 109375L), v); a1 = gtopoly(mkvecsmalln(11, 106L, 0L,-1370L, 0L, 900L, 0L, 59500L, 0L,-308750L, 0L, 468750L), v); a0 = gtopoly(mkvecsmalln(13, 25L, 0L,-750L, 0L, 9375L, 0L,-62500L, 0L, 234375L, 0L,-468750L, 0L, 390625L), v); return mkpoln(7, gen_1,a5,a4,a3,a2,a1,a0); case 13: return mkpoln(7, gen_1,gen_m2,gen_1,gen_0,gen_0,gen_0,pol_mx(v)); case 14: return mkpoln(7, gen_1,stoi(4),stoi(20),gen_0,gen_0,pol_mx(v),pol_x(v)); default: return NULL; }} static GEN QT7(long k, long v) { GEN a6, a5, a4, a3, a2, a1, a0; switch(k) { case 1: a6 = gtopoly(mkvecsmall4(1, 2,-1, 13), v); a5 = gtopoly(mkvecsmalln(6, 3L,-3L, 9L, 24L,-21L, 54L), v); a4 = gtopoly(mkvecsmalln(8, 3L,-9L, 27L,-22L, 6L, 84L,-121L, 75L), v); a3 = gtopoly(mkvecsmalln(10, 1L,-6L, 22L,-57L, 82L,-70L,-87L, 140L,-225L,-2L), v); a2 = gtopoly(mkvecsmalln(11, -1L, 5L,-25L, 61L,-126L, 117L,-58L,-155L, 168L,-80L,-44L), v); a1 = gtopoly(mkvecsmalln(11, -1L, 8L,-30L, 75L,-102L, 89L, 34L,-56L, 113L, 42L,-17L), v); a0 = gtopoly(mkvecsmalln(10, 1L,-7L, 23L,-42L, 28L, 19L,-60L,-2L, 16L,-1L), v); return mkpoln(8, gen_1,a6,a5,a4,a3,a2,a1,a0); case 2: a5 = gtopoly(mkvecsmall4(-147,-735,-441,-21), v); a4 = gtopoly(mkvecsmall5(-686,-3920,-4508,-1568,-70), v); a3 = gtopoly(mkvecsmalln(7, 7203L, 67914L, 183505L, 107996L, 8085L,-1862L,-105L), v); a2 = gtopoly(mkvecsmalln(8, 67228L, 547428L, 1373372L, 1227940L, 416500L, 38220L,-588L,-84L), v); a1 = gtopoly(mkvecsmalln(10, -117649L,-1563051L,-6809236L,-10708460L,-4050830L, 788214L, 402780L, 37828L, 343L,-35L), v); a0 = gtopoly(mkvecsmalln(11, -1647086L,-16893436L,-56197806L,-69977488L,-44893212L,-13304872L,-624652L, 103152L, 11466L, 196L,-6L), v); return mkpoln(8, gen_1,gen_0,a5,a4,a3,a2,a1,a0); case 3: a5 = gtopoly(mkvecsmalln(7, -21L,0L,-1176L,147L,-20580L,3969L,-107163L), v); a4 = gtopoly(mkvecsmalln(10, -21L,49L,-1715L,4214L,-51107L,129850L,-653905L,1648458L,-3000564L,6751269L), v); a3 = gtopoly(mkvecsmalln(13, 91L,98L,9849L,8673L,427133L,291354L,9385460L,4618152L,108334149L,35173278L,608864445L,114771573L,1275989841L), v); a2 = gtopoly(mkZVn(16, "112","-49","14651","-10682","800513","-821730","23571744","-30983190","401636536","-628991685","3929562693","-6832117530","20190045015","-35916751080","40831674912","-68903451414]"), v); a1 = gtopoly(mkZVn(19, "-84","-98","-14896","-16709","-1127098","-1228626","-47347279","-51034970","-1201635330","-1316073164","-18735012261","-21705143929","-173551408569","-224605199322","-861876002232","-1329675932088","-1728966234555","-3376269119286","0"), v); a0 = gtopoly(mkZVn(22, "-97","-14","-19803","-903","-1765232","84609","-89982172","11950757","-2882068329","588528171","-59885187418","15296374002","-801314604769","222442927665","-6560078164731","1705024373220","-28577589326937","5543939564730","-38647180304208","4961048501808","74415727527120","25115308040403"), v); return mkpoln(8, gen_1,gen_0,a5,a4,a3,a2,a1,a0); case 4: a4 = deg2pol_shallow(stoi(-7), gen_0, stoi(98), v); a3 = deg1pol_shallow(stoi(28), stoi(441), v); a2 = gtopoly(mkvecsmall4(-35,-112,-196, 343), v); a1 = deg2pol_shallow(stoi(7), stoi(196), stoi(1372), v); a0 = gtopoly(mkvecsmalln(6, -1L,-30L,-259L,-588L,-1372L, 0L), v); return mkpoln(8, gen_1,stoi(7),stoi(42),a4,a3,a2,a1,a0); case 5: a3 = deg1pol_shallow(stoi(12), stoi(7203), v); a2 = deg1pol_shallow(stoi(-30), gen_0, v); a1 = deg1pol_shallow(stoi(28), stoi(-117649), v); a0 = deg1pol_shallow(stoi(-9), gen_0, v); return mkpoln(8, gen_1,gen_0,stoi(-147),pol_mx(v),a3,a2,a1,a0); default: return NULL; }} static GEN nflistQTfile(long n, long t) { pariFILE *F; GEN z; char *f = stack_sprintf("%s/nflistdata/%ld/%ld/QT", pari_datadir, n, t); F = pari_fopengz(f); if (!F) return NULL; z = gp_read_stream(F->file); pari_fclose(F); return z; } static GEN nfmakeQT(long deg, long k, long v) { long i, l; GEN P; switch(deg) { case 4: P = QT4(k, v); break; case 5: P = QT5(k, v); break; case 6: P = QT6(k, v); break; case 7: P = QT7(k, v); break; default: P = nflistQTfile(deg, k); } if (!P) pari_err_IMPL(stack_sprintf("group %ldT%ld in nflist / Q(T)", deg,k)); if (deg <= 7) return P; l = lg(P); for (i = 1; i < l; i++) { GEN p = gel(P,i); if (typ(p) != t_INT) gel(P,i) = RgV_to_RgX(p, v); } return RgV_to_RgX(P, 0); } static GEN nfmakeAnQT(long n, long v) { GEN A, P = vec_ei(n + 1, 1); long s; if (odd(n)) { s = (n & 3L) == 1? 1: -1; A = sqru(n-2); setsigne(A, s); gel(P,2) = monomial(sqru(n), 1, v); gel(P,n) = s > 0? gen_1: gen_m1; gel(P,n+1) = monomial(A, 1, v); } else { s = (n & 3L)? -1 : 1; gel(P,2) = utoineg(n); gel(P,n+1) = deg2pol_shallow(stoi(s), gen_0, powuu(n-1,n-1), v); } return RgV_to_RgX_reverse(P, 0); } static GEN nfmakeSnQT(long n, long v) { GEN P = vec_ei(n + 1, 1); gel(P,n) = pol_x(v); gel(P,n+1) = gen_1; return RgV_to_RgX_reverse(P, 0); } GEN nflistQT(long n, long t, long v) { if (varncmp(0,v) >= 0) pari_err(e_MISC, "incorrect variable in nflist / Q(T)"); if (n == 1) return pol_x(0); if (n == 2) return deg2pol_shallow(gen_1, pol_mx(v), gen_1, 0); if (t == -1) return nfmakeSnQT(n, v); if (t == -2) return nfmakeAnQT(n, v); return nfmakeQT(n, t, v); } pari-2.17.2/src/basemath/crvwtors.c0000644000175000017500000050332314760123736015613 0ustar billbill/* Copyright (C) 2014 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" /* In the database, the curve X1(N) is given by the bivariate * polynomial X. The degree of X in its main variable is at least * the degree of its secondary variable, except for N = 6, 7, 8, 9, * 10, 12. Note that X1(N) is genus 0 for N <= 10 and N = 12, and * genus 1 for N = 11, 14, and 15. */ INLINE ulong Fl_mul4(ulong x, ulong p) { return Fl_double(Fl_double(x, p), p); } /* p odd */ INLINE ulong Fl_inv4(ulong p) { if ((p & 3UL) == 3) return (p + 1) >> 2; return p - (p >> 2); } /* p > 3 */ INLINE ulong Fl_inv3(ulong p) { if ((p % 3) == 1) return p - p / 3; return (p + 1) / 3; } INLINE ulong Fl_div4(ulong x, ulong p) { return Fl_halve(Fl_halve(x, p), p); } INLINE ulong Fl_div8(ulong x, ulong p) { return Fl_halve(Fl_div4(x, p), p); } /* which map to use to convert from (r,s) to (b,c) coeffs. */ typedef enum { RS_MAP, T_MAP, QT_MAP, TQ_MAP } map_type; typedef struct { GEN crv; GEN r_num, r_den; long rplus1; GEN s_num, s_den; long splus1; map_type map; } X1_info; #define FIRST_X1_LEVEL 13 #define LAST_X1_LEVEL 39 /* The table is defined at the end of the file. */ INLINE const X1_info *get_X1_info(ulong N); /* Compute the image of (x,y) -> (r_n(x,y)/r_d(x,y), s_n(x,y), s_d(x,y)) */ static void map_X1_points(GEN r, GEN s, const X1_info *X1, long ncurves, ulong p, ulong pi) { pari_sp ltop = avma, av; GEN X1_c, rn_pol, rd_pol, sn_pol, sd_pol, rn, sn, rd, sd; long xdeg, ydeg, i; X1_c = zxX_to_FlxX(X1->crv, p); xdeg = degpol(X1_c); ydeg = FlxY_degreex(X1_c); rn_pol = zxX_to_FlxX(X1->r_num, p); rd_pol = zxX_to_FlxX(X1->r_den, p); sn_pol = zxX_to_FlxX(X1->s_num, p); sd_pol = zxX_to_FlxX(X1->s_den, p); xdeg = maxss(xdeg, degpol(rn_pol)); xdeg = maxss(xdeg, degpol(rd_pol)); xdeg = maxss(xdeg, degpol(sn_pol)); xdeg = maxss(xdeg, degpol(sd_pol)); ydeg = maxss(ydeg, FlxY_degreex(rn_pol)); ydeg = maxss(ydeg, FlxY_degreex(rd_pol)); ydeg = maxss(ydeg, FlxY_degreex(sn_pol)); ydeg = maxss(ydeg, FlxY_degreex(sd_pol)); rn = cgetg(ncurves + 1, t_VECSMALL); rd = cgetg(ncurves + 1, t_VECSMALL); sn = cgetg(ncurves + 1, t_VECSMALL); sd = cgetg(ncurves + 1, t_VECSMALL); av = avma; for (i = 1; i <= ncurves; ) { GEN pol, ypowers, xpowers; ulong y, x; y = random_Fl(p); ypowers = Fl_powers_pre(y, ydeg, p, pi); pol = FlxY_evalx_powers_pre(X1_c, ypowers, p, pi); x = Flx_oneroot_pre(pol, p, pi); if (x != p) { xpowers = Fl_powers_pre(x, xdeg, p, pi); rd[i] = FlxY_eval_powers_pre(rd_pol, ypowers, xpowers, p, pi); sd[i] = FlxY_eval_powers_pre(sd_pol, ypowers, xpowers, p, pi); if (rd[i] != 0 && sd[i] != 0) { rn[i] = FlxY_eval_powers_pre(rn_pol, ypowers, xpowers, p, pi); sn[i] = FlxY_eval_powers_pre(sn_pol, ypowers, xpowers, p, pi); ++i; } } set_avma(av); } Flv_inv_pre_inplace(rd, p, pi); Flv_inv_pre_inplace(sd, p, pi); for (i = 1; i <= ncurves; ++i) { r[i] = Fl_addmul_pre(X1->rplus1, rn[i], rd[i], p, pi); s[i] = Fl_addmul_pre(X1->splus1, sn[i], sd[i], p, pi); } set_avma(ltop); } /* * A curve y^2 = x^3 + a2 x^2 + a4 x is isomorphic to the curve * * y^2 = x^3 + (a4 - 1/3*a2^2) x + (2/27*a2^3 - 1/3*a4*a2) * = x^3 + (a4 - a2 c) x + (2 c^3 - a4 c) * * (where c = a2/3) which is in short form. */ INLINE void a2a4_to_a4a6(ulong *a4, ulong *a6, ulong A2, ulong A4, ulong inv3, ulong p, ulong pi) { ulong c = Fl_mul_pre(A2, inv3, p, pi); *a4 = Fl_sub(A4, Fl_mul_pre(A2, c, p, pi), p); *a6 = Fl_sub(Fl_double(Fl_mul_pre(c, Fl_sqr_pre(c, p, pi), p, pi), p), Fl_mul_pre(A4, c, p, pi), p); } /* * A curve y^2 + a1 xy + a3 y = x^3 is isomorphic to the curve * * y^2 = x^3 + (1/2*a3*a1 -1/48*a1^4) x + (1/864*a1^6 - 1/24*a3*a1^3 + 1/4*a3^2 * = x^3 + c (a3 - 1/3 * c^3) x + 1/3 * c^3(1/9 c^2 a1 - a3) + 1/4 a3^2 * * (where c = a1/2) which is in short form. */ INLINE void a1a3_to_a4a6( ulong *a4, ulong *a6, ulong a1, ulong a3, ulong inv3, ulong inv4, ulong inv9, ulong p, ulong pi) { ulong c = Fl_halve(a1, p); ulong c2 = Fl_sqr_pre(c, p, pi); ulong c3_on_3 = Fl_mul_pre(Fl_mul_pre(c, c2, p, pi), inv3, p, pi); /* t1 = c^2 * a1 / 9 */ ulong t1 = Fl_mul_pre(c2, Fl_mul_pre(a1, inv9, p, pi), p, pi); /* t1 = c^3/3 (c^2 * a1 / 9 - a3) */ t1 = Fl_mul_pre(c3_on_3, Fl_sub(t1, a3, p), p, pi); *a4 = Fl_mul_pre(c, Fl_sub(a3, c3_on_3, p), p, pi); *a6 = Fl_addmul_pre(t1, inv4, Fl_sqr_pre(a3, p, pi), p, pi); } /* E: y^2 + (1 - c)xy - by = x^3 - bx^2; p > 3 * Singular iff b(c^4 - 3*c^3 + (-8*b+3)*c^2 + (-20*b-1)*c + (16*b^2+b)) = 0 * Sutherland has a version of this function in tecurve.c * around line 306. FIXME: Could precompute some of the constants. */ INLINE void bc_to_a4a6(ulong *a4, ulong *a6, ulong b, ulong c, ulong p, ulong pi) { ulong t0, t2, b2, b4, b6, c4, c6; b6 = Fl_sub(c, 1, p); t0 = Fl_sqr_pre(b6, p, pi); b4 = Fl_mul4(b, p); b2 = Fl_sub(t0, b4, p); b4 = Fl_mul_pre(b6, b, p, pi); b6 = Fl_sqr_pre(b, p, pi); t2 = Fl_sqr_pre(b2, p, pi); c4 = Fl_mul_pre(24 % p, b4, p, pi); c4 = Fl_sub(c4, t2, p); t0 = Fl_mul_pre(36 % p, b4, p, pi); t2 = Fl_sub(t2, t0, p); c6 = Fl_mul_pre(b2, t2, p, pi); t0 = Fl_mul_pre(216 % p, b6, p, pi); c6 = Fl_add(c6, t0, p); *a4 = Fl_mul_pre(27 % p, c4, p, pi); *a6 = Fl_mul_pre(54 % p, c6, p, pi); } INLINE void bc_to_a4a6_and_tors( ulong *a4, ulong *a6, ulong *tx, ulong *ty, ulong b, ulong c, ulong p, ulong pi) { bc_to_a4a6(a4, a6, b, c, p, pi); /* tx = 3((c - 1)^2 - 4b) */ *tx = Fl_triple(Fl_sub(Fl_sqr(Fl_sub(c, 1, p), p), Fl_mul4(b, p), p), p); /* ty = -108 b */ *ty = Fl_neg(Fl_mul_pre(108 % p, b, p, pi), p); } INLINE void tq_to_a4a6_and_tors( ulong *a4, ulong *a6, ulong *tx, ulong *ty, ulong q, ulong t, ulong p, ulong pi, ulong inv3) { ulong A2, A4; ulong t2 = Fl_sqr_pre(t, p, pi); ulong qtp1 = Fl_addmul_pre(1L, q, t, p, pi); /* a2 = t^2-2*(q*t+1), a4 = (1-t^2)*(q*t+1)^2 */ A2 = Fl_sub(t2, Fl_double(qtp1, p), p); A4 = Fl_mul_pre(Fl_sub(1L, t2, p), Fl_sqr_pre(qtp1, p, pi), p, pi); a2a4_to_a4a6(a4, a6, A2, A4, inv3, p, pi); /* [tx, ty] = [(t+1)*(q*t+1),t*(q*t+1)*(t+1)] */ *tx = Fl_mul_pre(Fl_add(t, 1L, p), qtp1, p, pi); *ty = Fl_mul_pre(t, *tx, p, pi); /* Map to isomorphic curve */ *tx = Fl_addmul_pre(*tx, A2, inv3, p, pi); } INLINE void qt_to_a4a6_and_tors( ulong *a4, ulong *a6, ulong *tx, ulong *ty, ulong q, ulong t, ulong p, ulong pi, ulong c_12, ulong c_108) { /* z = (q+1)*(t^2-1)/8 */ ulong z = Fl_div8(Fl_mul_pre(Fl_add(q, 1L, p), Fl_sub(Fl_sqr_pre(t, p, pi), 1L, p), p, pi), p); ulong bb = Fl_mul_pre(Fl_sub(q, 1L, p), z, p, pi); ulong b = Fl_halve(bb, p); /* E=[1,(q^2-1)*(t^2-1)/16,(q^2-1)*(t^2-1)/16,0,0]; * = [1, (q-1)*(q+1)*(t^2-1)/16, idem] * = [1, b, b, 0, 0] */ bc_to_a4a6(a4, a6, Fl_neg(b, p), 0L, p, pi); /* [tx,ty]= [(q+1)*(t^2-1)/8,(q+1)^2*(t^2-1)*(t-1)/32]; * = [z, (q+1)*(t-1)*z*1/4] */ *tx = z; *ty = Fl_mul_pre(Fl_add(q, 1L, p), Fl_mul_pre(Fl_div4(z, p), Fl_sub(t, 1L, p), p, pi), p, pi); /* Map to isomorphic curve: * (x, y) -> (3(12x + 4b + 1), 108(2y + x + b)) */ *ty = Fl_mul_pre(c_108, Fl_add(Fl_double(*ty, p), Fl_add(b, *tx, p), p), p, pi); *tx = Fl_triple(Fl_addmul_pre(Fl_add(Fl_double(bb,p), 1L, p), c_12, *tx,p,pi), p); } INLINE void t_to_a4a6_and_tors( ulong *a4, ulong *a6, ulong *tx, ulong *ty, ulong q, ulong t, ulong p, ulong pi, ulong inv3, ulong inv4, ulong inv9) { ulong a1, a3, qt = Fl_mul_pre(q, t, p, pi), t1; /* a1 = q*t+t+(2-q), a3 = (q*t)*(t-1)+t */ a1 = Fl_add(Fl_add(qt, t, p), Fl_sub(2L, q, p), p); a3 = Fl_addmul_pre(t, qt, Fl_sub(t, 1L, p), p, pi); a1a3_to_a4a6(a4, a6, a1, a3, inv3, inv4, inv9, p, pi); *tx = Fl_neg(t, p); *ty = Fl_sqr_pre(t, p, pi); /* Map to isomorphic curve: * (x, y) -> (x + 1/12*a1^2, 1/2*a1*x + (y + 1/2*a3)) */ t1 = Fl_halve(a1, p); *ty = Fl_addmul_pre(Fl_add(*ty, Fl_halve(a3, p), p), *tx, t1, p, pi); *tx = Fl_addmul_pre(*tx, inv3, Fl_sqr_pre(t1, p, pi), p, pi); } INLINE void rs_to_a4a6_and_tors( ulong *a4, ulong *a6, ulong *tx, ulong *ty, ulong r, ulong s, ulong p, ulong pi) { /* c = s (r - 1) */ ulong c = Fl_mul_pre(s, Fl_sub(r, 1, p), p, pi); /* b = rc */ ulong b = Fl_mul_pre(r, c, p, pi); bc_to_a4a6_and_tors(a4, a6, tx, ty, b, c, p, pi); } INLINE void E_general_X1( ulong *a4, ulong *a6, ulong *tx, ulong *ty, long ncurves, long m, ulong p, ulong pi) { pari_sp av = avma; const X1_info *X1 = get_X1_info(m); GEN r, r_, s, s_; r_ = cgetg(ncurves + 1, t_VECSMALL); r = r_ + 1; s_ = cgetg(ncurves + 1, t_VECSMALL); s = s_ + 1; map_X1_points(r_, s_, X1, ncurves, p, pi); switch (X1->map) { case RS_MAP: while (ncurves--) rs_to_a4a6_and_tors(a4++, a6++, tx++, ty++, *r++, *s++, p, pi); break; case T_MAP: { ulong inv3 = Fl_inv3(p), inv4 = Fl_inv4(p), inv9 = Fl_sqr_pre(inv3, p, pi); while (ncurves--) t_to_a4a6_and_tors(a4++,a6++, tx++,ty++, *r++,*s++, p, pi, inv3, inv4, inv9); break; } case TQ_MAP: { ulong inv3 = Fl_inv3(p); while (ncurves--) tq_to_a4a6_and_tors(a4++, a6++, tx++, ty++, *r++, *s++, p, pi, inv3); break; } case QT_MAP: { ulong c_12 = 12 % p, c_108 = 108 % p; while (ncurves--) qt_to_a4a6_and_tors(a4++,a6++, tx++,ty++, *r++,*s++, p, pi, c_12, c_108); break; } } set_avma(av); } INLINE void E_11_torsion( ulong *a4, ulong *a6, ulong *tx, ulong *ty, long ncurves, ulong p, ulong pi) { pari_sp av = avma; const ulong A4 = Fl_neg(432 % p, p), A6 = 8208 % p; const ulong c_6 = 6 % p, c_72 = 72 % p, c_108 = 108 % p; const ulong inv216 = Fl_inv(216 % p, p); while (ncurves) { GEN Q; ulong r, s, den; #if 0 /* FIXME: it's faster to generate random points on the curve than to * compute random multiples of a point. Disabled for now. */ /* Must guard against the possibility that [n]Q = 0 */ do { /* FIXME: should perhaps use p + 1 + 2\sqrt{p} instead of p - 1 */ n = random_Fl(m1) + 1; /* m1 = p - 1; */ Q = Fle_mulu(P, n, A4, p); } while (ell_is_inf(Q)); #endif /* FIXME: Thing is, if I'm going to do it this way *anyway*, I * might as well use the nonelliptic version of X1(11), since the * formulae are much nicer. */ Q = random_Fle_pre(A4, A6, p, pi); /* den = 6x + 72 */ den = Fl_addmul_pre(c_72, c_6, Q[1], p, pi); if (den == 0) continue; /* r = (y + 108)/216, s = 1 + (y - 108)/(6x + 72) */ r = Fl_mul_pre(Fl_add(Q[2], c_108, p), inv216, p, pi); if (r == 1) continue; s = Fl_add(1, Fl_div(Fl_sub(Q[2], c_108, p), den, p), p); if (s == 0) continue; rs_to_a4a6_and_tors(a4, a6, tx, ty, r, s, p, pi); if (!Fl_elldisc_pre(*a4, *a6, p, pi)) continue; a4++; a6++; tx++; ty++; ncurves--; } set_avma(av); } INLINE void E_2_torsion( ulong *a4, ulong *a6, ulong *tx, ulong *ty, long ncurves, ulong p, ulong pi) { const ulong m1 = p - 1, inv3 = Fl_inv3(p); while (ncurves) { ulong A2 = random_Fl(m1) + 1; /* nonzero */ ulong A4 = random_Fl(m1) + 1; /* nonzero */ if (!Fl_sub(Fl_sqr_pre(A2, p, pi), Fl_mul4(A4, p), p)) continue; a2a4_to_a4a6(a4++, a6++, A2, A4, inv3, p, pi); /* [0,0] is a 2-torsion point on y^2 = x(x^2 + a2x + a4) which * is mapped to [(1/3)a2, 0] on y^2 = x^3 + A4x + A6. */ *tx++ = Fl_mul_pre(inv3, A2, p, pi); *ty++ = 0L; ncurves--; }; } INLINE void E_3_torsion( ulong *a4, ulong *a6, ulong *tx, ulong *ty, long ncurves, ulong p, ulong pi) { const ulong m1 = p - 1, _27 = 27 % p; const ulong inv3 = Fl_inv3(p), inv4 = Fl_inv4(p); const ulong inv9 = Fl_sqr_pre(inv3, p, pi); while (ncurves) { ulong a1 = random_Fl(m1) + 1; /* nonzero */ ulong a3 = random_Fl(m1) + 1; /* nonzero */ /* a1^3 - 27 a3 != 0 */ if (Fl_mul_pre(a1, Fl_sqr_pre(a1, p, pi), p, pi) == Fl_mul_pre(_27, a3, p, pi)) continue; a1a3_to_a4a6(a4++, a6++, a1, a3, inv3, inv4, inv9, p, pi); /* [0,0] is a 3-torsion point on y^2 + a1xy + a3y = x^3 which * is mapped to [a1^2/12, a3/2] on y^2 = x^3 + a4x + a6. */ *tx++ = Fl_mul_pre(Fl_sqr_pre(Fl_halve(a1, p), p, pi), inv3, p, pi); *ty++ = Fl_halve(a3, p); ncurves--; } } INLINE void E_4_torsion( ulong *a4, ulong *a6, ulong *tx, ulong *ty, long ncurves, ulong p, ulong pi) { const ulong m1 = p - 1; while (ncurves) { ulong b = random_Fl(m1) + 1; /* nonzero */ if (Fl_mul4(Fl_mul4(b, p), p) == m1) continue; /* need b(16b+1) != 0 */ bc_to_a4a6_and_tors(a4++, a6++, tx++, ty++, b, 0L, p, pi); ncurves--; } } INLINE void E_5_torsion( ulong *a4, ulong *a6, ulong *tx, ulong *ty, long ncurves, ulong p, ulong pi) { const ulong m1 = p - 1, _11 = 11 % p; while (ncurves) { ulong b = random_Fl(m1) + 1; /* nonzero */ if (Fl_mul_pre(b, Fl_sub(b, _11, p), p, pi) == 1UL) continue; bc_to_a4a6_and_tors(a4++, a6++, tx++, ty++, b, b, p, pi); ncurves--; } } INLINE void E_6_torsion( ulong *a4, ulong *a6, ulong *tx, ulong *ty, long ncurves, ulong p, ulong pi) { const ulong m2 = p - 2, _9 = 9 % p; while (ncurves) { ulong b, c = random_Fl(m2) + 1; /* in [1, p - 2] */ if (!Fl_add(Fl_mul_pre(c, _9, p, pi), 1, p)) continue; b = Fl_add(c, Fl_sqr_pre(c, p, pi), p); /* b = c + c^2 */ bc_to_a4a6_and_tors(a4++, a6++, tx++, ty++, b, c, p, pi); ncurves--; } } INLINE void E_7_torsion( ulong *a4, ulong *a6, ulong *tx, ulong *ty, long ncurves, ulong p, ulong pi) { const ulong m2 = p - 2, _7 = 7 % p; while (ncurves) { ulong d = random_Fl(m2) + 2; /* in [2, p - 1] */ ulong c = Fl_sub(Fl_sqr_pre(d, p, pi), d, p); /* c = d^2 - d */ ulong b = Fl_mul_pre(c, d, p, pi); /* b = d^3 - d^2 */ if (Fl_mul_pre(Fl_sub(d, _7, p), c, p, pi) == Fl_double(d, p) - 1) continue; bc_to_a4a6_and_tors(a4++, a6++, tx++, ty++, b, c, p, pi); ncurves--; } } INLINE void E_8_torsion( ulong *a4, ulong *a6, ulong *tx, ulong *ty, long ncurves, ulong p, ulong pi) { const ulong m2 = p - 2; while (ncurves) { ulong b, c, d = random_Fl(m2) + 2; /* in [2, p - 1] */ b = Fl_sub(Fl_double(d, p), 1, p); /* 2d - 1 */ if (!b) continue; /* b = (2d - 1)(d - 1) */ b = Fl_mul_pre(b, Fl_sub(d, 1, p), p, pi); /* c = (2d - 1)(d - 1)/d */ c = Fl_div(b, d, p); if (Fl_mul4(Fl_add(b, d, p), p) == 3) continue; bc_to_a4a6_and_tors(a4++, a6++, tx++, ty++, b, c, p, pi); ncurves--; } } INLINE void E_9_torsion( ulong *a4, ulong *a6, ulong *tx, ulong *ty, long ncurves, ulong p, ulong pi) { const ulong m2 = p - 2; while (ncurves) { ulong b, c, d, f = random_Fl(m2) + 2; /* in [2, p - 1] */ /* d = f^2 - f + 1 */ d = Fl_sub(Fl_sqr_pre(f, p, pi), Fl_sub(f, 1, p), p); if (!d) continue; /* c = fd - f */ c = Fl_mul_pre(f, Fl_sub(d, 1, p), p, pi); /* b = cd */ b = Fl_mul_pre(c, d, p, pi); /* f^3 - 6*f^2 + 3*f + 1 != 0 */ if (!Fl_sub(Fl_sub(c, Fl_mul(5 % p, d, p), p), Fl_double(Fl_sub(f, 3, p), p ), p)) continue; bc_to_a4a6_and_tors(a4++, a6++, tx++, ty++, b, c, p, pi); ncurves--; } } INLINE void E_10_torsion( ulong *a4, ulong *a6, ulong *tx, ulong *ty, long ncurves, ulong p, ulong pi) { const ulong m2 = p - 2; while (ncurves) { ulong f, ff, f2, d, c, b, t; f = random_Fl(m2) + 2; /* in [2, p - 1] */ /* t = f - (f - 1)^2 = (3f - 1) - f^2 */ f2 = Fl_double(f, p); t = Fl_sub(f2, 1, p); if (!t || Fl_mul_pre(f2, t, p, pi) == 1) continue; ff = Fl_sqr_pre(f, p, pi); t = Fl_sub(Fl_add(t, f, p), ff, p); if (!t) continue; /* d = f^2 / (f - (f - 1)^2) */ d = Fl_div(ff, t, p); /* c = fd - f */ c = Fl_mul_pre(f, Fl_sub(d, 1, p), p, pi); /* b = cd */ b = Fl_mul_pre(c, d, p, pi); bc_to_a4a6_and_tors(a4++, a6++, tx++, ty++, b, c, p, pi); ncurves--; } } INLINE void E_12_torsion( ulong *a4, ulong *a6, ulong *tx, ulong *ty, long ncurves, ulong p, ulong pi) { const long m2 = p - 2; while (ncurves) { ulong tau, t1, t2, M, f, d, c, b; tau = random_Fl(m2) + 2; /* in [2, p - 1] */ /* t1 = tau - 1 */ t1 = Fl_sub(tau, 1, p); /* M = (3 tau - 3 tau^2 - 1)/(tau - 1) = -(3 tau + 1/(tau - 1)) */ t2 = Fl_inv(t1, p); M = Fl_neg(Fl_add(Fl_triple(tau, p), t2, p), p); /* (3 tau^2 - 3 tau + 1)(6 tau^2 - 6 tau + 1) = 0 */ if (!M || !Fl_add(Fl_double(M, p), t2, p)) continue; /* d = M + tau */ d = Fl_add(M, tau, p); if (!d || d == 1) continue; /* f = M/(1 - tau) = -M / (tau - 1) */ f = Fl_neg(Fl_mul_pre(M, t2, p, pi), p); /* c = fd - f */ c = Fl_mul_pre(f, Fl_sub(d, 1, p), p, pi); /* b = cd */ b = Fl_mul_pre(c, d, p, pi); bc_to_a4a6_and_tors(a4++, a6++, tx++, ty++, b, c, p, pi); ncurves--; } } static void E_any_torsion( ulong *a4, ulong *a6, ulong *px, ulong *py, long ncurves, ulong p, ulong pi) { pari_sp av = avma; ulong c_1728 = 1728 % p; long i; for (i = 0; i < ncurves; i++) { GEN P; ulong j; do j = random_Fl(p); while (j == 0 || j == c_1728); Fl_ellj_to_a4a6(j, p, &a4[i], &a6[i]); P = random_Fle_pre(a4[i], a6[i], p, pi); px[i] = P[1]; py[i] = P[2]; set_avma(av); } } /* Assume p < 2^62. Is there an n such that mn belongs to Hasse's interval? */ INLINE long torsion_compatible_with_characteristic(long m, ulong p) { ulong u = usqrt(4*p); return ceildivuu(p + 1 - u, m) <= (p + 1 + u) / m; } /* Input: pointers a4, a6, t{x,y} pointing to space for at least ncurves * elements; an integer 1 <= m <= LAST_X1_LEVEL; a prime p > 3. * * Output: Put the coefficients of ncurves elliptic curves with m-torsion into * a4 and a6. The actual number of unique curves is not guaranteed to be * ncurves, but will be close whenever p >> ncurves. (tx[i], ty[i]) * is an m-torsion point on [a4[i], a6[i]]. */ void random_curves_with_m_torsion( ulong *a4, ulong *a6, ulong *tx, ulong *ty, long ncurves, long m, ulong p, ulong pi) { if (ncurves == 0) return; if (m < 1 || m > LAST_X1_LEVEL || ! torsion_compatible_with_characteristic(m, p)) pari_err_BUG("E_m_torsion"); switch (m) { case 1: E_any_torsion(a4, a6, tx, ty, ncurves, p, pi); break; case 2: E_2_torsion(a4, a6, tx, ty, ncurves, p, pi); break; case 3: E_3_torsion(a4, a6, tx, ty, ncurves, p, pi); break; case 4: E_4_torsion(a4, a6, tx, ty, ncurves, p, pi); break; case 5: E_5_torsion(a4, a6, tx, ty, ncurves, p, pi); break; case 6: E_6_torsion(a4, a6, tx, ty, ncurves, p, pi); break; case 7: E_7_torsion(a4, a6, tx, ty, ncurves, p, pi); break; case 8: E_8_torsion(a4, a6, tx, ty, ncurves, p, pi); break; case 9: E_9_torsion(a4, a6, tx, ty, ncurves, p, pi); break; case 10: E_10_torsion(a4, a6, tx, ty, ncurves, p, pi); break; case 11: E_11_torsion(a4, a6, tx, ty, ncurves, p, pi); break; case 12: E_12_torsion(a4, a6, tx, ty, ncurves, p, pi); break; default: E_general_X1(a4, a6, tx, ty, ncurves, m, p, pi); while (ncurves--) { while (!Fl_elldisc_pre(*a4, *a6, p, pi)) /* rare */ E_general_X1(a4, a6, tx, ty, 1L, m, p, pi); a4++; a6++; tx++; ty++; } } } #define vZ evalvarn(1) /* variable number for secondary variable */ static const long FLX_0[3] = { evaltyp(t_VECSMALL) | _evallg(2), vZ }; static const long FLX_1[3] = { evaltyp(t_VECSMALL) | _evallg(3), vZ, 1 }; static const long FLX_m1[3] = { evaltyp(t_VECSMALL) | _evallg(3), vZ, -1 }; static const long FLX_Z[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 0, 1 }; static const long FLX_mZ[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 0, -1 }; /* * X1 Curves database follows! */ /* x^2 + (z^3 + z^2 + 1)*x + (-z^2 - z) */ static const long X1_13_crv_0[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, -1, -1 }; /* -z^2 - z */ static const long X1_13_crv_1[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 1, 0, 1, 1 }; /* z^3 + z^2 + 1 */ static const long *X1_13_crv[5] = { (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)), X1_13_crv_0, X1_13_crv_1, FLX_1 }; /* -z*x + 1 */ static const long *X1_13_r_n[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), FLX_1, FLX_mZ }; /* 1 */ static const long *X1_13_r_d[3] = { (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)), FLX_1 }; /* -z*x */ static const long *X1_13_s_n[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), FLX_0, FLX_mZ }; /* x + 1 */ static const long *X1_13_s_d[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), FLX_1, FLX_1 }; /* x^2 + (z^2 + z)*x + z */ static const long X1_14_crv_1[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 1, 1 }; /* z^2 + z */ static const long *X1_14_crv[5] = { (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)), FLX_Z, X1_14_crv_1, FLX_1 }; /* -x - z */ static const long *X1_14_r_n[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), FLX_mZ, FLX_m1 }; /* x^2 + (z + 2)*x + (z + 1) */ static const long X1_14_r_d_0[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */ static const long X1_14_r_d_1[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 2, 1 }; /* z + 2 */ static const long *X1_14_r_d[5] = { (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)), X1_14_r_d_0, X1_14_r_d_1, FLX_1 }; /* (-z + 1) */ static const long X1_14_s_n_0[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, -1 }; /* -z + 1 */ static const long *X1_14_s_n[3] = { (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)), X1_14_s_n_0 }; /* x + 1 */ static const long *X1_14_s_d[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), FLX_1, FLX_1 }; /* x^2 + (z^2 + z + 1)*x + z^2 */ static const long X1_15_crv_0[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, 1 }; /* z^2 */ static const long X1_15_crv_1[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 1, 1, 1 }; /* z^2 + z + 1 */ static const long *X1_15_crv[5] = { (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)), X1_15_crv_0, X1_15_crv_1, FLX_1 }; /* x^2 + z*x */ static const long *X1_15_r_n[5] = { (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)), FLX_0, FLX_Z, FLX_1 }; /* z^2*x + (z^3 + z^2) */ static const long X1_15_r_d_0[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, 1, 1 }; /* z^3 + z^2 */ static const long X1_15_r_d_1[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, 1 }; /* z^2 */ static const long *X1_15_r_d[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), X1_15_r_d_0, X1_15_r_d_1 }; /* x */ static const long *X1_15_s_n[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), FLX_0, FLX_1 }; /* (z^2 + z) */ static const long X1_15_s_d_0[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 1, 1 }; /* z^2 + z */ static const long *X1_15_s_d[3] = { (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)), X1_15_s_d_0 }; /* x^2 + (z^3 + z^2 - z + 1)*x + z^2 */ static const long X1_16_crv_0[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, 1 }; /* z^2 */ static const long X1_16_crv_1[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 1, -1, 1, 1 }; /* z^3 + z^2 - z + 1 */ static const long *X1_16_crv[5] = { (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)), X1_16_crv_0, X1_16_crv_1, FLX_1 }; /* x^2 + (-z + 1)*x + z^2 */ static const long X1_16_r_n_0[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, 1 }; /* z^2 */ static const long X1_16_r_n_1[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, -1 }; /* -z + 1 */ static const long *X1_16_r_n[5] = { (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)), X1_16_r_n_0, X1_16_r_n_1, FLX_1 }; /* -x + (z^2 + z - 1) */ static const long X1_16_r_d_0[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, -1, 1, 1 }; /* z^2 + z - 1 */ static const long *X1_16_r_d[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), X1_16_r_d_0, FLX_m1 }; /* -x + z */ static const long *X1_16_s_n[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), FLX_Z, FLX_m1 }; /* (z + 1) */ static const long X1_16_s_d_0[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */ static const long *X1_16_s_d[3] = { (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)), X1_16_s_d_0 }; /* x^4 + (z^3 + z^2 - z + 2)*x^3 + (z^3 - 3*z + 1)*x^2 + (-z^4 - 2*z)*x + (z^3 + z^2) */ static const long X1_17_crv_0[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, 1, 1 }; /* z^3 + z^2 */ static const long X1_17_crv_1[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, -2, 0, 0, -1 }; /* -z^4 - 2*z */ static const long X1_17_crv_2[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 1, -3, 0, 1 }; /* z^3 - 3*z + 1 */ static const long X1_17_crv_3[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 2, -1, 1, 1 }; /* z^3 + z^2 - z + 2 */ static const long *X1_17_crv[7] = { (long *)(evaltyp(t_POL) | _evallg(7)), (long *)(evalvarn(0) | evalsigne(1)), X1_17_crv_0, X1_17_crv_1, X1_17_crv_2, X1_17_crv_3, FLX_1 }; /* -x + (z^2 + z) */ static const long X1_17_r_n_0[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 1, 1 }; /* z^2 + z */ static const long *X1_17_r_n[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), X1_17_r_n_0, FLX_m1 }; /* -x^2 + (z - 1)*x + (z^2 + z) */ static const long X1_17_r_d_0[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 1, 1 }; /* z^2 + z */ static const long X1_17_r_d_1[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, -1, 1 }; /* z - 1 */ static const long *X1_17_r_d[5] = { (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)), X1_17_r_d_0, X1_17_r_d_1, FLX_m1 }; /* (z + 1) */ static const long X1_17_s_n_0[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */ static const long *X1_17_s_n[3] = { (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)), X1_17_s_n_0 }; /* x + (z + 1) */ static const long X1_17_s_d_0[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */ static const long *X1_17_s_d[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), X1_17_s_d_0, FLX_1 }; /* x^2 + (z^3 - 2*z^2 + 3*z + 1)*x + 2*z */ static const long X1_18_crv_0[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 0, 2 }; /* 2*z */ static const long X1_18_crv_1[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 1, 3, -2, 1 }; /* z^3 - 2*z^2 + 3*z + 1 */ static const long *X1_18_crv[5] = { (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)), X1_18_crv_0, X1_18_crv_1, FLX_1 }; /* -z*x + (z^2 - 3*z + 1) */ static const long X1_18_r_n_0[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 1, -3, 1 }; /* z^2 - 3*z + 1 */ static const long *X1_18_r_n[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), X1_18_r_n_0, FLX_mZ }; /* (z^3 - 2*z^2 + z)*x + (z^2 - 2*z + 1) */ static const long X1_18_r_d_0[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 1, -2, 1 }; /* z^2 - 2*z + 1 */ static const long X1_18_r_d_1[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 1, -2, 1 }; /* z^3 - 2*z^2 + z */ static const long *X1_18_r_d[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), X1_18_r_d_0, X1_18_r_d_1 }; /* -x + (z^2 - 2*z) */ static const long X1_18_s_n_0[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, -2, 1 }; /* z^2 - 2*z */ static const long *X1_18_s_n[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), X1_18_s_n_0, FLX_m1 }; /* -x^2 + (-z - 2)*x + (z^2 - 3*z) */ static const long X1_18_s_d_0[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, -3, 1 }; /* z^2 - 3*z */ static const long X1_18_s_d_1[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, -2, -1 }; /* -z - 2 */ static const long *X1_18_s_d[5] = { (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)), X1_18_s_d_0, X1_18_s_d_1, FLX_m1 }; /* x^5 + (-z^2 - 2)*x^4 + (-2*z^3 - 2*z^2 - 2*z + 1)*x^3 + (z^5 + 3*z^4 + 7*z^3 + 6*z^2 + 2*z)*x^2 + (-z^5 - 2*z^4 - 4*z^3 - 3*z^2)*x + (z^3 + z^2) */ static const long X1_19_crv_0[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, 1, 1 }; /* z^3 + z^2 */ static const long X1_19_crv_1[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, -3, -4, -2, -1 }; /* -z^5 - 2*z^4 - 4*z^3 - 3*z^2 */ static const long X1_19_crv_2[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 2, 6, 7, 3, 1 }; /* z^5 + 3*z^4 + 7*z^3 + 6*z^2 + 2*z */ static const long X1_19_crv_3[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 1, -2, -2, -2 }; /* -2*z^3 - 2*z^2 - 2*z + 1 */ static const long X1_19_crv_4[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, -2, 0, -1 }; /* -z^2 - 2 */ static const long *X1_19_crv[8] = { (long *)(evaltyp(t_POL) | _evallg(8)), (long *)(evalvarn(0) | evalsigne(1)), X1_19_crv_0, X1_19_crv_1, X1_19_crv_2, X1_19_crv_3, X1_19_crv_4, FLX_1 }; /* z*x^2 + (z^2 - z)*x - z^2 */ static const long X1_19_r_n_0[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, -1 }; /* -z^2 */ static const long X1_19_r_n_1[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, -1, 1 }; /* z^2 - z */ static const long *X1_19_r_n[5] = { (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)), X1_19_r_n_0, X1_19_r_n_1, FLX_Z }; /* (-z - 1)*x^2 + (-z^2 + 1)*x + (z^3 + 3*z^2 + 2*z) */ static const long X1_19_r_d_0[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 2, 3, 1 }; /* z^3 + 3*z^2 + 2*z */ static const long X1_19_r_d_1[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 1, 0, -1 }; /* -z^2 + 1 */ static const long X1_19_r_d_2[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, -1, -1 }; /* -z - 1 */ static const long *X1_19_r_d[5] = { (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)), X1_19_r_d_0, X1_19_r_d_1, X1_19_r_d_2 }; /* z*x - z */ static const long *X1_19_s_n[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), FLX_mZ, FLX_Z }; /* (-z - 1)*x + (z^2 + 2*z + 1) */ static const long X1_19_s_d_0[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 1, 2, 1 }; /* z^2 + 2*z + 1 */ static const long X1_19_s_d_1[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, -1, -1 }; /* -z - 1 */ static const long *X1_19_s_d[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), X1_19_s_d_0, X1_19_s_d_1 }; /* x^3 - z^3*x^2 - z^2*x + z */ static const long X1_20_crv_1[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, -1 }; /* -z^2 */ static const long X1_20_crv_2[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, 0, -1 }; /* -z^3 */ static const long *X1_20_crv[6] = { (long *)(evaltyp(t_POL) | _evallg(6)), (long *)(evalvarn(0) | evalsigne(1)), FLX_Z, X1_20_crv_1, X1_20_crv_2, FLX_1 }; /* -x + z */ static const long *X1_20_r_n[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), FLX_Z, FLX_m1 }; /* z*x - 1 */ static const long *X1_20_r_d[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), FLX_m1, FLX_Z }; /* 4*z^3*x^3 + (-4*z^4 - 8*z^2)*x^2 + (8*z^3 + 4*z)*x - 4*z^2 */ static const long X1_20_s_n_0[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, -4 }; /* -4*z^2 */ static const long X1_20_s_n_1[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 4, 0, 8 }; /* 8*z^3 + 4*z */ static const long X1_20_s_n_2[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 0, -8, 0, -4 }; /* -4*z^4 - 8*z^2 */ static const long X1_20_s_n_3[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, 0, 4 }; /* 4*z^3 */ static const long *X1_20_s_n[6] = { (long *)(evaltyp(t_POL) | _evallg(6)), (long *)(evalvarn(0) | evalsigne(1)), X1_20_s_n_0, X1_20_s_n_1, X1_20_s_n_2, X1_20_s_n_3 }; /* (z^4 + 4*z^2 - 1)*x^3 + (-10*z^3 - 2*z)*x^2 + (3*z^4 + 8*z^2 + 1)*x + (-2*z^3 - 2*z) */ static const long X1_20_s_d_0[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, -2, 0, -2 }; /* -2*z^3 - 2*z */ static const long X1_20_s_d_1[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 1, 0, 8, 0, 3 }; /* 3*z^4 + 8*z^2 + 1 */ static const long X1_20_s_d_2[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, -2, 0, -10 }; /* -10*z^3 - 2*z */ static const long X1_20_s_d_3[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, -1, 0, 4, 0, 1 }; /* z^4 + 4*z^2 - 1 */ static const long *X1_20_s_d[6] = { (long *)(evaltyp(t_POL) | _evallg(6)), (long *)(evalvarn(0) | evalsigne(1)), X1_20_s_d_0, X1_20_s_d_1, X1_20_s_d_2, X1_20_s_d_3 }; /* x^4 + (3*z^2 + 1)*x^3 + (z^5 + z^4 + 2*z^2 + 2*z)*x^2 + (2*z^4 + z^3 + z)*x + z^3 */ static const long X1_21_crv_0[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, 0, 1 }; /* z^3 */ static const long X1_21_crv_1[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 1, 0, 1, 2 }; /* 2*z^4 + z^3 + z */ static const long X1_21_crv_2[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 2, 2, 0, 1, 1 }; /* z^5 + z^4 + 2*z^2 + 2*z */ static const long X1_21_crv_3[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 1, 0, 3 }; /* 3*z^2 + 1 */ static const long *X1_21_crv[7] = { (long *)(evaltyp(t_POL) | _evallg(7)), (long *)(evalvarn(0) | evalsigne(1)), X1_21_crv_0, X1_21_crv_1, X1_21_crv_2, X1_21_crv_3, FLX_1 }; /* (z + 1)*x^3 + (z + 2)*x^2 + x */ static const long X1_21_r_n_2[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 2, 1 }; /* z + 2 */ static const long X1_21_r_n_3[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */ static const long *X1_21_r_n[6] = { (long *)(evaltyp(t_POL) | _evallg(6)), (long *)(evalvarn(0) | evalsigne(1)), FLX_0, FLX_1, X1_21_r_n_2, X1_21_r_n_3 }; /* -z*x^3 + (z^2 - 1)*x^2 + 2*z*x + 1 */ static const long X1_21_r_d_1[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 0, 2 }; /* 2*z */ static const long X1_21_r_d_2[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, -1, 0, 1 }; /* z^2 - 1 */ static const long *X1_21_r_d[6] = { (long *)(evaltyp(t_POL) | _evallg(6)), (long *)(evalvarn(0) | evalsigne(1)), FLX_1, X1_21_r_d_1, X1_21_r_d_2, FLX_mZ }; /* x^2 + x */ static const long *X1_21_s_n[5] = { (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)), FLX_0, FLX_1, FLX_1 }; /* z*x + 1 */ static const long *X1_21_s_d[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), FLX_1, FLX_Z }; /* x^4 + (z^3 + 2*z^2 + z + 2)*x^3 + (z^5 + z^4 + 2*z^3 + 2*z^2 + 1)*x^2 + (z^5 - z^4 - 2*z^3 - z^2 - z)*x + (-z^4 - z^3) */ static const long X1_22_crv_0[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 0, 0, -1, -1 }; /* -z^4 - z^3 */ static const long X1_22_crv_1[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, -1, -1, -2, -1, 1 }; /* z^5 - z^4 - 2*z^3 - z^2 - z */ static const long X1_22_crv_2[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 1, 0, 2, 2, 1, 1 }; /* z^5 + z^4 + 2*z^3 + 2*z^2 + 1 */ static const long X1_22_crv_3[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 2, 1, 2, 1 }; /* z^3 + 2*z^2 + z + 2 */ static const long *X1_22_crv[7] = { (long *)(evaltyp(t_POL) | _evallg(7)), (long *)(evalvarn(0) | evalsigne(1)), X1_22_crv_0, X1_22_crv_1, X1_22_crv_2, X1_22_crv_3, FLX_1 }; /* (z^2 + z + 1)*x + z^2 */ static const long X1_22_r_n_0[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, 1 }; /* z^2 */ static const long X1_22_r_n_1[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 1, 1, 1 }; /* z^2 + z + 1 */ static const long *X1_22_r_n[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), X1_22_r_n_0, X1_22_r_n_1 }; /* x + (z^3 + 2*z^2) */ static const long X1_22_r_d_0[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, 2, 1 }; /* z^3 + 2*z^2 */ static const long *X1_22_r_d[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), X1_22_r_d_0, FLX_1 }; /* (z + 1)*x */ static const long X1_22_s_n_1[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */ static const long *X1_22_s_n[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), FLX_0, X1_22_s_n_1 }; /* x + z^2 */ static const long X1_22_s_d_0[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, 1 }; /* z^2 */ static const long *X1_22_s_d[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), X1_22_s_d_0, FLX_1 }; /* x^7 + (z^5 - z^4 + z^3 + 4*z^2 + 3)*x^6 + (z^7 + 3*z^5 + z^4 + 5*z^3 + 7*z^2 - 4*z + 3)*x^5 + (2*z^7 + 3*z^5 - z^4 - 2*z^3 - z^2 - 8*z + 1)*x^4 + (z^7 - 4*z^6 - 5*z^5 - 6*z^4 - 6*z^3 - 2*z^2 - 3*z)*x^3 + (-3*z^6 + 5*z^4 + 3*z^3 + 3*z^2 + 2*z)*x^2 + (3*z^5 + 4*z^4 + z)*x + (-z^4 - 2*z^3 - z^2) */ static const long X1_23_crv_0[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 0, -1, -2, -1 }; /* -z^4 - 2*z^3 - z^2 */ static const long X1_23_crv_1[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 1, 0, 0, 4, 3 }; /* 3*z^5 + 4*z^4 + z */ static const long X1_23_crv_2[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 2, 3, 3, 5, 0, -3 }; /* -3*z^6 + 5*z^4 + 3*z^3 + 3*z^2 + 2*z */ static const long X1_23_crv_3[10] = { evaltyp(t_VECSMALL) | _evallg(10), vZ, 0, -3, -2, -6, -6, -5, -4, 1 }; /* z^7 - 4*z^6 - 5*z^5 - 6*z^4 - 6*z^3 - 2*z^2 - 3*z */ static const long X1_23_crv_4[10] = { evaltyp(t_VECSMALL) | _evallg(10), vZ, 1, -8, -1, -2, -1, 3, 0, 2 }; /* 2*z^7 + 3*z^5 - z^4 - 2*z^3 - z^2 - 8*z + 1 */ static const long X1_23_crv_5[10] = { evaltyp(t_VECSMALL) | _evallg(10), vZ, 3, -4, 7, 5, 1, 3, 0, 1 }; /* z^7 + 3*z^5 + z^4 + 5*z^3 + 7*z^2 - 4*z + 3 */ static const long X1_23_crv_6[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 3, 0, 4, 1, -1, 1 }; /* z^5 - z^4 + z^3 + 4*z^2 + 3 */ static const long *X1_23_crv[10] = { (long *)(evaltyp(t_POL) | _evallg(10)), (long *)(evalvarn(0) | evalsigne(1)), X1_23_crv_0, X1_23_crv_1, X1_23_crv_2, X1_23_crv_3, X1_23_crv_4, X1_23_crv_5, X1_23_crv_6, FLX_1 }; /* x + (z^2 + z + 1) */ static const long X1_23_r_n_0[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 1, 1, 1 }; /* z^2 + z + 1 */ static const long *X1_23_r_n[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), X1_23_r_n_0, FLX_1 }; /* -z*x + z^2 */ static const long X1_23_r_d_0[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, 1 }; /* z^2 */ static const long *X1_23_r_d[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), X1_23_r_d_0, FLX_mZ }; /* x + (z + 1) */ static const long X1_23_s_n_0[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */ static const long *X1_23_s_n[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), X1_23_s_n_0, FLX_1 }; /* z */ static const long *X1_23_s_d[3] = { (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)), FLX_Z }; /* (z^2 - 3)*x^4 + (z^5 + 2*z^4 + 2*z^3 + 2*z^2 - 3*z)*x^2 + (-z^4 - z^2) */ static const long X1_24_crv_0[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 0, -1, 0, -1 }; /* -z^4 - z^2 */ static const long X1_24_crv_2[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, -3, 2, 2, 2, 1 }; /* z^5 + 2*z^4 + 2*z^3 + 2*z^2 - 3*z */ static const long X1_24_crv_4[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, -3, 0, 1 }; /* z^2 - 3 */ static const long *X1_24_crv[7] = { (long *)(evaltyp(t_POL) | _evallg(7)), (long *)(evalvarn(0) | evalsigne(1)), X1_24_crv_0, FLX_0, X1_24_crv_2, FLX_0, X1_24_crv_4 }; /* x */ static const long *X1_24_r_n[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), FLX_0, FLX_1 }; /* 1 */ static const long *X1_24_r_d[3] = { (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)), FLX_1 }; /* 4*x^3 + 4*z*x */ static const long X1_24_s_n_1[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 0, 4 }; /* 4*z */ static const long X1_24_s_n_3[3] = { evaltyp(t_VECSMALL) | _evallg(3), vZ, 4 }; /* 4 */ static const long *X1_24_s_n[6] = { (long *)(evaltyp(t_POL) | _evallg(6)), (long *)(evalvarn(0) | evalsigne(1)), FLX_0, X1_24_s_n_1, FLX_0, X1_24_s_n_3 }; /* (z - 2)*x^4 + (-4*z - 2)*x^2 - z */ static const long X1_24_s_d_2[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, -2, -4 }; /* -4*z - 2 */ static const long X1_24_s_d_4[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, -2, 1 }; /* z - 2 */ static const long *X1_24_s_d[7] = { (long *)(evaltyp(t_POL) | _evallg(7)), (long *)(evalvarn(0) | evalsigne(1)), FLX_mZ, FLX_0, X1_24_s_d_2, FLX_0, X1_24_s_d_4 }; /* z*u^5 + (z^4 - 2*z^3 - z^2 + 2*z + 1)*u^4 + (-2*z^6 + 2*z^4 - 4*z^3 - 2*z^2 + 2)*u^3 + (z^8 + z^7 - 2*z^6 + z^5 - z^4 - z^3 - 2*z^2 - z + 1)*u^2 + (z^8 + z^7 + 2*z^6 + z^5 - 2*z^4 + z^3 - z^2)*u + z^6 */ static const long X1_25_crv_0[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, 0, 0, 0, 0, 1 }; /* z^6 */ static const long X1_25_crv_1[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 0, -1, 1, -2, 1, 2, 1, 1 }; /* z^8 + z^7 + 2*z^6 + z^5 - 2*z^4 + z^3 - z^2 */ static const long X1_25_crv_2[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, 1, -1, -2, -1, -1, 1, -2, 1, 1 }; /* z^8 + z^7 - 2*z^6 + z^5 - z^4 - z^3 - 2*z^2 - z + 1 */ static const long X1_25_crv_3[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 2, 0, -2, -4, 2, 0, -2 }; /* -2*z^6 + 2*z^4 - 4*z^3 - 2*z^2 + 2 */ static const long X1_25_crv_4[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 1, 2, -1, -2, 1 }; /* z^4 - 2*z^3 - z^2 + 2*z + 1 */ static const long *X1_25_crv[8] = { (long *)(evaltyp(t_POL) | _evallg(8)), (long *)(evalvarn(0) | evalsigne(1)), X1_25_crv_0, X1_25_crv_1, X1_25_crv_2, X1_25_crv_3, X1_25_crv_4, FLX_Z }; /* -z^2*u^6 + (2*z^4 - 2*z^2 - 2*z)*u^5 + (-z^6 + 2*z^5 + 5*z^4 + z^3 - 4*z - 1)*u^4 + (-2*z^7 - 3*z^6 + 4*z^5 + 4*z^4 + 5*z^3 - z - 2)*u^3 + (-z^8 - 4*z^7 - 2*z^6 - z^5 + 3*z^4 + 5*z^3 - z^2 + z - 1)*u^2 + (-z^8 - z^7 - 2*z^6 - 3*z^5 + 2*z^4 + z^3)*u - z^6 */ static const long X1_25_r_n_0[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, 0, 0, 0, 0, -1 }; /* -z^6 */ static const long X1_25_r_n_1[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 0, 0, 1, 2, -3, -2, -1, -1 }; /* -z^8 - z^7 - 2*z^6 - 3*z^5 + 2*z^4 + z^3 */ static const long X1_25_r_n_2[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, -1, 1, -1, 5, 3, -1, -2, -4, -1 }; /* -z^8 - 4*z^7 - 2*z^6 - z^5 + 3*z^4 + 5*z^3 - z^2 + z - 1 */ static const long X1_25_r_n_3[10] = { evaltyp(t_VECSMALL) | _evallg(10), vZ, -2, -1, 0, 5, 4, 4, -3, -2 }; /* -2*z^7 - 3*z^6 + 4*z^5 + 4*z^4 + 5*z^3 - z - 2 */ static const long X1_25_r_n_4[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, -1, -4, 0, 1, 5, 2, -1 }; /* -z^6 + 2*z^5 + 5*z^4 + z^3 - 4*z - 1 */ static const long X1_25_r_n_5[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, -2, -2, 0, 2 }; /* 2*z^4 - 2*z^2 - 2*z */ static const long X1_25_r_n_6[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, -1 }; /* -z^2 */ static const long *X1_25_r_n[9] = { (long *)(evaltyp(t_POL) | _evallg(9)), (long *)(evalvarn(0) | evalsigne(1)), X1_25_r_n_0, X1_25_r_n_1, X1_25_r_n_2, X1_25_r_n_3, X1_25_r_n_4, X1_25_r_n_5, X1_25_r_n_6 }; /* -z^2*u^6 + (2*z^4 + z^3 - 2*z^2 - 2*z)*u^5 + (-z^6 + 7*z^4 + 3*z^3 + z^2 - 4*z - 1)*u^4 + (-z^7 - 8*z^6 + z^5 + 7*z^4 + 7*z^3 + 2*z^2 - z - 2)*u^3 + (2*z^8 - 6*z^7 - 11*z^6 - 2*z^5 + 3*z^4 + 7*z^3 + z - 1)*u^2 + (3*z^9 + 3*z^8 - 6*z^7 - 6*z^6 - 3*z^5 + z^4 + 2*z^3)*u + (z^10 + 3*z^9 + z^8 - 2*z^7 - z^6) */ static const long X1_25_r_d_0[13] = { evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 0, 0, 0, 0, 0, -1, -2, 1, 3, 1 }; /* z^10 + 3*z^9 + z^8 - 2*z^7 - z^6 */ static const long X1_25_r_d_1[12] = { evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 0, 0, 2, 1, -3, -6, -6, 3, 3 }; /* 3*z^9 + 3*z^8 - 6*z^7 - 6*z^6 - 3*z^5 + z^4 + 2*z^3 */ static const long X1_25_r_d_2[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, -1, 1, 0, 7, 3, -2, -11, -6, 2 }; /* 2*z^8 - 6*z^7 - 11*z^6 - 2*z^5 + 3*z^4 + 7*z^3 + z - 1 */ static const long X1_25_r_d_3[10] = { evaltyp(t_VECSMALL) | _evallg(10), vZ, -2, -1, 2, 7, 7, 1, -8, -1 }; /* -z^7 - 8*z^6 + z^5 + 7*z^4 + 7*z^3 + 2*z^2 - z - 2 */ static const long X1_25_r_d_4[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, -1, -4, 1, 3, 7, 0, -1 }; /* -z^6 + 7*z^4 + 3*z^3 + z^2 - 4*z - 1 */ static const long X1_25_r_d_5[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, -2, -2, 1, 2 }; /* 2*z^4 + z^3 - 2*z^2 - 2*z */ static const long X1_25_r_d_6[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, -1 }; /* -z^2 */ static const long *X1_25_r_d[9] = { (long *)(evaltyp(t_POL) | _evallg(9)), (long *)(evalvarn(0) | evalsigne(1)), X1_25_r_d_0, X1_25_r_d_1, X1_25_r_d_2, X1_25_r_d_3, X1_25_r_d_4, X1_25_r_d_5, X1_25_r_d_6 }; /* -z*u^3 + (z^3 - z - 1)*u^2 + (z^4 + z^3 - z^2 + z - 1)*u + z^4 */ static const long X1_25_s_n_0[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 0, 0, 0, 1 }; /* z^4 */ static const long X1_25_s_n_1[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, -1, 1, -1, 1, 1 }; /* z^4 + z^3 - z^2 + z - 1 */ static const long X1_25_s_n_2[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, -1, -1, 0, 1 }; /* z^3 - z - 1 */ static const long *X1_25_s_n[6] = { (long *)(evaltyp(t_POL) | _evallg(6)), (long *)(evalvarn(0) | evalsigne(1)), X1_25_s_n_0, X1_25_s_n_1, X1_25_s_n_2, FLX_mZ }; /* -z*u^3 + (z^3 + z^2 - z - 1)*u^2 + (2*z^3 + z - 1)*u + (-z^5 + z^3) */ static const long X1_25_s_d_0[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, 0, 1, 0, -1 }; /* -z^5 + z^3 */ static const long X1_25_s_d_1[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, -1, 1, 0, 2 }; /* 2*z^3 + z - 1 */ static const long X1_25_s_d_2[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, -1, -1, 1, 1 }; /* z^3 + z^2 - z - 1 */ static const long *X1_25_s_d[6] = { (long *)(evaltyp(t_POL) | _evallg(6)), (long *)(evalvarn(0) | evalsigne(1)), X1_25_s_d_0, X1_25_s_d_1, X1_25_s_d_2, FLX_mZ }; /* x^6 + (3*z^2 + 4*z - 2)*x^5 + (3*z^4 + 10*z^3 - 9*z + 1)*x^4 + (z^6 + 7*z^5 + 8*z^4 - 14*z^3 - 11*z^2 + 6*z)*x^3 + (z^7 + 4*z^6 - z^5 - 13*z^4 + 2*z^3 + 10*z^2 - z)*x^2 + (-z^6 + 7*z^4 + 4*z^3 - 2*z^2)*x + (-z^4 - z^3) */ static const long X1_26_crv_0[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 0, 0, -1, -1 }; /* -z^4 - z^3 */ static const long X1_26_crv_1[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, -2, 4, 7, 0, -1 }; /* -z^6 + 7*z^4 + 4*z^3 - 2*z^2 */ static const long X1_26_crv_2[10] = { evaltyp(t_VECSMALL) | _evallg(10), vZ, 0, -1, 10, 2, -13, -1, 4, 1 }; /* z^7 + 4*z^6 - z^5 - 13*z^4 + 2*z^3 + 10*z^2 - z */ static const long X1_26_crv_3[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 6, -11, -14, 8, 7, 1 }; /* z^6 + 7*z^5 + 8*z^4 - 14*z^3 - 11*z^2 + 6*z */ static const long X1_26_crv_4[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 1, -9, 0, 10, 3 }; /* 3*z^4 + 10*z^3 - 9*z + 1 */ static const long X1_26_crv_5[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, -2, 4, 3 }; /* 3*z^2 + 4*z - 2 */ static const long *X1_26_crv[9] = { (long *)(evaltyp(t_POL) | _evallg(9)), (long *)(evalvarn(0) | evalsigne(1)), X1_26_crv_0, X1_26_crv_1, X1_26_crv_2, X1_26_crv_3, X1_26_crv_4, X1_26_crv_5, FLX_1 }; /* z*x^2 + (z^3 + 3*z^2)*x - z^2 */ static const long X1_26_r_n_0[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, -1 }; /* -z^2 */ static const long X1_26_r_n_1[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, 3, 1 }; /* z^3 + 3*z^2 */ static const long *X1_26_r_n[5] = { (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)), X1_26_r_n_0, X1_26_r_n_1, FLX_Z }; /* (z + 1)*x^2 + (z^3 + 4*z^2 + 3*z)*x + (z^3 + z^2) */ static const long X1_26_r_d_0[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, 1, 1 }; /* z^3 + z^2 */ static const long X1_26_r_d_1[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 3, 4, 1 }; /* z^3 + 4*z^2 + 3*z */ static const long X1_26_r_d_2[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */ static const long *X1_26_r_d[5] = { (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)), X1_26_r_d_0, X1_26_r_d_1, X1_26_r_d_2 }; /* z*x - z */ static const long *X1_26_s_n[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), FLX_mZ, FLX_Z }; /* (z + 1)*x */ static const long X1_26_s_d_1[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */ static const long *X1_26_s_d[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), FLX_0, X1_26_s_d_1 }; /* (z^2 - 2*z + 1)*u^6 + (z^5 - 2*z^4 + z^3 + 2*z^2 - 4*z + 2)*u^5 + (-z^7 + 5*z^5 - 5*z^4 + 2*z^3 - 2*z^2 + 1)*u^4 + (z^8 - 4*z^7 - z^6 + 5*z^5 + 2*z^3 - 5*z^2 + 2*z)*u^3 + (3*z^8 - 4*z^7 - 2*z^6 - 2*z^5 + 3*z^4 + 2*z^3 - z^2 + z)*u^2 + (3*z^8 - 3*z^5)*u + (z^8 + z^7 + z^6) */ static const long X1_27_crv_0[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 0, 0, 0, 0, 0, 1, 1, 1 }; /* z^8 + z^7 + z^6 */ static const long X1_27_crv_1[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 0, 0, 0, 0, -3, 0, 0, 3 }; /* 3*z^8 - 3*z^5 */ static const long X1_27_crv_2[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 1, -1, 2, 3, -2, -2, -4, 3 }; /* 3*z^8 - 4*z^7 - 2*z^6 - 2*z^5 + 3*z^4 + 2*z^3 - z^2 + z */ static const long X1_27_crv_3[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 2, -5, 2, 0, 5, -1, -4, 1 }; /* z^8 - 4*z^7 - z^6 + 5*z^5 + 2*z^3 - 5*z^2 + 2*z */ static const long X1_27_crv_4[10] = { evaltyp(t_VECSMALL) | _evallg(10), vZ, 1, 0, -2, 2, -5, 5, 0, -1 }; /* -z^7 + 5*z^5 - 5*z^4 + 2*z^3 - 2*z^2 + 1 */ static const long X1_27_crv_5[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 2, -4, 2, 1, -2, 1 }; /* z^5 - 2*z^4 + z^3 + 2*z^2 - 4*z + 2 */ static const long X1_27_crv_6[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 1, -2, 1 }; /* z^2 - 2*z + 1 */ static const long *X1_27_crv[9] = { (long *)(evaltyp(t_POL) | _evallg(9)), (long *)(evalvarn(0) | evalsigne(1)), X1_27_crv_0, X1_27_crv_1, X1_27_crv_2, X1_27_crv_3, X1_27_crv_4, X1_27_crv_5, X1_27_crv_6 }; /* (-z^4 + 2*z^2 - 2*z + 1)*u^4 + (z^5 - 4*z^4 - z^3 + 6*z^2 - 4*z + 2)*u^3 + (3*z^5 - 5*z^4 - 2*z^3 + 5*z^2 - z + 1)*u^2 + (3*z^5 - 2*z^4 - z^3 + z^2)*u + z^5 */ static const long X1_27_r_n_0[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, 0, 0, 0, 1 }; /* z^5 */ static const long X1_27_r_n_1[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, 1, -1, -2, 3 }; /* 3*z^5 - 2*z^4 - z^3 + z^2 */ static const long X1_27_r_n_2[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 1, -1, 5, -2, -5, 3 }; /* 3*z^5 - 5*z^4 - 2*z^3 + 5*z^2 - z + 1 */ static const long X1_27_r_n_3[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 2, -4, 6, -1, -4, 1 }; /* z^5 - 4*z^4 - z^3 + 6*z^2 - 4*z + 2 */ static const long X1_27_r_n_4[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 1, -2, 2, 0, -1 }; /* -z^4 + 2*z^2 - 2*z + 1 */ static const long *X1_27_r_n[7] = { (long *)(evaltyp(t_POL) | _evallg(7)), (long *)(evalvarn(0) | evalsigne(1)), X1_27_r_n_0, X1_27_r_n_1, X1_27_r_n_2, X1_27_r_n_3, X1_27_r_n_4 }; /* (-z^3 + z^2 - z + 1)*u^4 + (z^5 - z^4 - 2*z^3 + z^2 - z + 2)*u^3 + (3*z^5 - 2*z^4 - z^3 - 2*z^2 + 2*z + 1)*u^2 + (3*z^5 - z^4 - 3*z^2 + z)*u + (z^5 - z^2) */ static const long X1_27_r_d_0[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, -1, 0, 0, 1 }; /* z^5 - z^2 */ static const long X1_27_r_d_1[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 1, -3, 0, -1, 3 }; /* 3*z^5 - z^4 - 3*z^2 + z */ static const long X1_27_r_d_2[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 1, 2, -2, -1, -2, 3 }; /* 3*z^5 - 2*z^4 - z^3 - 2*z^2 + 2*z + 1 */ static const long X1_27_r_d_3[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 2, -1, 1, -2, -1, 1 }; /* z^5 - z^4 - 2*z^3 + z^2 - z + 2 */ static const long X1_27_r_d_4[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 1, -1, 1, -1 }; /* -z^3 + z^2 - z + 1 */ static const long *X1_27_r_d[7] = { (long *)(evaltyp(t_POL) | _evallg(7)), (long *)(evalvarn(0) | evalsigne(1)), X1_27_r_d_0, X1_27_r_d_1, X1_27_r_d_2, X1_27_r_d_3, X1_27_r_d_4 }; /* (z^3 - 2*z + 1)*u^3 + (-z^4 + 2*z^3 + z^2 - 4*z + 2)*u^2 + (-2*z^4 + z^3 + z^2 - z + 1)*u - z^4 */ static const long X1_27_s_n_0[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 0, 0, 0, -1 }; /* -z^4 */ static const long X1_27_s_n_1[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 1, -1, 1, 1, -2 }; /* -2*z^4 + z^3 + z^2 - z + 1 */ static const long X1_27_s_n_2[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 2, -4, 1, 2, -1 }; /* -z^4 + 2*z^3 + z^2 - 4*z + 2 */ static const long X1_27_s_n_3[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 1, -2, 0, 1 }; /* z^3 - 2*z + 1 */ static const long *X1_27_s_n[6] = { (long *)(evaltyp(t_POL) | _evallg(6)), (long *)(evalvarn(0) | evalsigne(1)), X1_27_s_n_0, X1_27_s_n_1, X1_27_s_n_2, X1_27_s_n_3 }; /* (-z + 1)*u^3 + (-z^4 - z + 2)*u^2 + (-2*z^4 + 2*z + 1)*u + (-z^4 + z) */ static const long X1_27_s_d_0[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 1, 0, 0, -1 }; /* -z^4 + z */ static const long X1_27_s_d_1[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 1, 2, 0, 0, -2 }; /* -2*z^4 + 2*z + 1 */ static const long X1_27_s_d_2[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 2, -1, 0, 0, -1 }; /* -z^4 - z + 2 */ static const long X1_27_s_d_3[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, -1 }; /* -z + 1 */ static const long *X1_27_s_d[6] = { (long *)(evaltyp(t_POL) | _evallg(6)), (long *)(evalvarn(0) | evalsigne(1)), X1_27_s_d_0, X1_27_s_d_1, X1_27_s_d_2, X1_27_s_d_3 }; /* (z^5 + 3*z^4 + 3*z^3 + z^2)*x^6 + (z^8 + 2*z^7 + z^6 + 11*z^4 + 22*z^3 + 11*z^2)*x^5 + (9*z^7 + 9*z^6 - 6*z^5 - 6*z^4 + 45*z^3 + 45*z^2)*x^4 + (-5*z^8 + 28*z^6 - 42*z^4 + 84*z^2 - 1)*x^3 + (-25*z^7 + 25*z^6 + 23*z^5 - 23*z^4 - 67*z^3 + 67*z^2 + 5*z - 5)*x^2 + (6*z^8 - 12*z^7 - 12*z^6 + 36*z^5 - 36*z^3 + 12*z^2 + 12*z - 6)*x + (-z^9 + 3*z^8 - 8*z^6 + 6*z^5 + 6*z^4 - 8*z^3 + 3*z - 1) */ static const long X1_28_crv_0[12] = { evaltyp(t_VECSMALL) | _evallg(12), vZ, -1, 3, 0, -8, 6, 6, -8, 0, 3, -1 }; /* -z^9 + 3*z^8 - 8*z^6 + 6*z^5 + 6*z^4 - 8*z^3 + 3*z - 1 */ static const long X1_28_crv_1[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, -6, 12, 12, -36, 0, 36, -12, -12, 6 }; /* 6*z^8 - 12*z^7 - 12*z^6 + 36*z^5 - 36*z^3 + 12*z^2 + 12*z - 6 */ static const long X1_28_crv_2[10] = { evaltyp(t_VECSMALL) | _evallg(10), vZ, -5, 5, 67, -67, -23, 23, 25, -25 }; /* -25*z^7 + 25*z^6 + 23*z^5 - 23*z^4 - 67*z^3 + 67*z^2 + 5*z - 5 */ static const long X1_28_crv_3[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, -1, 0, 84, 0, -42, 0, 28, 0, -5 }; /* -5*z^8 + 28*z^6 - 42*z^4 + 84*z^2 - 1 */ static const long X1_28_crv_4[10] = { evaltyp(t_VECSMALL) | _evallg(10), vZ, 0, 0, 45, 45, -6, -6, 9, 9 }; /* 9*z^7 + 9*z^6 - 6*z^5 - 6*z^4 + 45*z^3 + 45*z^2 */ static const long X1_28_crv_5[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 0, 11, 22, 11, 0, 1, 2, 1 }; /* z^8 + 2*z^7 + z^6 + 11*z^4 + 22*z^3 + 11*z^2 */ static const long X1_28_crv_6[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, 1, 3, 3, 1 }; /* z^5 + 3*z^4 + 3*z^3 + z^2 */ static const long *X1_28_crv[9] = { (long *)(evaltyp(t_POL) | _evallg(9)), (long *)(evalvarn(0) | evalsigne(1)), X1_28_crv_0, X1_28_crv_1, X1_28_crv_2, X1_28_crv_3, X1_28_crv_4, X1_28_crv_5, X1_28_crv_6 }; /* (z + 1)*x + 2 */ static const long X1_28_r_n_0[3] = { evaltyp(t_VECSMALL) | _evallg(3), vZ, 2 }; /* 2 */ static const long X1_28_r_n_1[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */ static const long *X1_28_r_n[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), X1_28_r_n_0, X1_28_r_n_1 }; /* 2*z */ static const long X1_28_r_d_0[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 0, 2 }; /* 2*z */ static const long *X1_28_r_d[3] = { (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)), X1_28_r_d_0 }; /* (-z - 1)*x - 2 */ static const long X1_28_s_n_0[3] = { evaltyp(t_VECSMALL) | _evallg(3), vZ, -2 }; /* -2 */ static const long X1_28_s_n_1[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, -1, -1 }; /* -z - 1 */ static const long *X1_28_s_n[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), X1_28_s_n_0, X1_28_s_n_1 }; /* 2 */ static const long X1_28_s_d_0[3] = { evaltyp(t_VECSMALL) | _evallg(3), vZ, 2 }; /* 2 */ static const long *X1_28_s_d[3] = { (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)), X1_28_s_d_0 }; /* x^11 + (2*z^3 + 5*z^2 + 5*z - 3)*x^10 + (z^6 + 8*z^5 + 18*z^4 + 11*z^3 - 5*z^2 - 12*z + 3)*x^9 + (3*z^8 + 15*z^7 + 29*z^6 + 6*z^5 - 39*z^4 - 19*z^3 + 5*z^2 + 5*z - 1)*x^8 + (3*z^10 + 14*z^9 + 18*z^8 - 26*z^7 - 99*z^6 - 45*z^5 + 95*z^4 + 25*z^3 - 37*z^2 + 7*z)*x^7 + (z^12 + 5*z^11 - 44*z^9 - 106*z^8 - 40*z^7 + 197*z^6 + 190*z^5 - 140*z^4 - 93*z^3 + 59*z^2 - 6*z)*x^6 + (-2*z^12 - 16*z^11 - 37*z^10 + 9*z^9 + 184*z^8 + 256*z^7 - 99*z^6 - 346*z^5 + 20*z^4 + 130*z^3 - 32*z^2 + z)*x^5 + (z^12 + 15*z^11 + 65*z^10 + 99*z^9 - 55*z^8 - 320*z^7 - 165*z^6 + 223*z^5 + 100*z^4 - 66*z^3 + 5*z^2)*x^4 + (-4*z^11 - 36*z^10 - 108*z^9 - 98*z^8 + 110*z^7 + 191*z^6 - 15*z^5 - 64*z^4 + 10*z^3)*x^3 + (6*z^10 + 38*z^9 + 76*z^8 + 25*z^7 - 55*z^6 - 26*z^5 + 10*z^4)*x^2 + (-4*z^9 - 17*z^8 - 18*z^7 + 5*z^5)*x + (z^8 + 2*z^7 + z^6) */ static const long X1_29_crv_0[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 0, 0, 0, 0, 0, 1, 2, 1 }; /* z^8 + 2*z^7 + z^6 */ static const long X1_29_crv_1[12] = { evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 0, 0, 0, 0, 5, 0, -18, -17, -4 }; /* -4*z^9 - 17*z^8 - 18*z^7 + 5*z^5 */ static const long X1_29_crv_2[13] = { evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 0, 0, 0, 10, -26, -55, 25, 76, 38, 6 }; /* 6*z^10 + 38*z^9 + 76*z^8 + 25*z^7 - 55*z^6 - 26*z^5 + 10*z^4 */ static const long X1_29_crv_3[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, 10, -64, -15, 191, 110, -98, -108, -36, -4 }; /* -4*z^11 - 36*z^10 - 108*z^9 - 98*z^8 + 110*z^7 + 191*z^6 - 15*z^5 - 64*z^4 + 10*z^3 */ static const long X1_29_crv_4[15] = { evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, 0, 5, -66, 100, 223, -165, -320, -55, 99, 65, 15, 1 }; /* z^12 + 15*z^11 + 65*z^10 + 99*z^9 - 55*z^8 - 320*z^7 - 165*z^6 + 223*z^5 + 100*z^4 - 66*z^3 + 5*z^2 */ static const long X1_29_crv_5[15] = { evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, 1, -32, 130, 20, -346, -99, 256, 184, 9, -37, -16, -2 }; /* -2*z^12 - 16*z^11 - 37*z^10 + 9*z^9 + 184*z^8 + 256*z^7 - 99*z^6 - 346*z^5 + 20*z^4 + 130*z^3 - 32*z^2 + z */ static const long X1_29_crv_6[15] = { evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, -6, 59, -93, -140, 190, 197, -40, -106, -44, 0, 5, 1 }; /* z^12 + 5*z^11 - 44*z^9 - 106*z^8 - 40*z^7 + 197*z^6 + 190*z^5 - 140*z^4 - 93*z^3 + 59*z^2 - 6*z */ static const long X1_29_crv_7[13] = { evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 7, -37, 25, 95, -45, -99, -26, 18, 14, 3 }; /* 3*z^10 + 14*z^9 + 18*z^8 - 26*z^7 - 99*z^6 - 45*z^5 + 95*z^4 + 25*z^3 - 37*z^2 + 7*z */ static const long X1_29_crv_8[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, -1, 5, 5, -19, -39, 6, 29, 15, 3 }; /* 3*z^8 + 15*z^7 + 29*z^6 + 6*z^5 - 39*z^4 - 19*z^3 + 5*z^2 + 5*z - 1 */ static const long X1_29_crv_9[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 3, -12, -5, 11, 18, 8, 1 }; /* z^6 + 8*z^5 + 18*z^4 + 11*z^3 - 5*z^2 - 12*z + 3 */ static const long X1_29_crv_10[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, -3, 5, 5, 2 }; /* 2*z^3 + 5*z^2 + 5*z - 3 */ static const long *X1_29_crv[14] = { (long *)(evaltyp(t_POL) | _evallg(14)), (long *)(evalvarn(0) | evalsigne(1)), X1_29_crv_0, X1_29_crv_1, X1_29_crv_2, X1_29_crv_3, X1_29_crv_4, X1_29_crv_5, X1_29_crv_6, X1_29_crv_7, X1_29_crv_8, X1_29_crv_9, X1_29_crv_10, FLX_1 }; /* -x + (-z^3 - z^2 - z) */ static const long X1_29_r_n_0[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, -1, -1, -1 }; /* -z^3 - z^2 - z */ static const long *X1_29_r_n[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), X1_29_r_n_0, FLX_m1 }; /* (z^2 + z - 1)*x - z */ static const long X1_29_r_d_1[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, -1, 1, 1 }; /* z^2 + z - 1 */ static const long *X1_29_r_d[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), FLX_mZ, X1_29_r_d_1 }; /* -z*x - z^2 */ static const long X1_29_s_n_0[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 0, 0, -1 }; /* -z^2 */ static const long *X1_29_s_n[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), X1_29_s_n_0, FLX_mZ }; /* (z - 1)*x - z */ static const long X1_29_s_d_1[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, -1, 1 }; /* z - 1 */ static const long *X1_29_s_d[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), FLX_mZ, X1_29_s_d_1 }; /* x^6 + (z^6 - 5*z^5 + 6*z^4 + 3*z^3 - 6*z^2 + 7*z + 3)*x^5 + (z^7 - 3*z^6 - 13*z^5 + 44*z^4 - 18*z^3 + z^2 + 18*z + 3)*x^4 + (z^8 - 3*z^7 - 13*z^6 + 27*z^5 + 46*z^4 - 32*z^3 + 21*z^2 + 15*z + 1)*x^3 + (2*z^8 - 16*z^7 + 18*z^6 + 40*z^5 + 12*z^4 - 12*z^3 + 18*z^2 + 4*z)*x^2 + (-8*z^7 + 28*z^6 + 12*z^5 + 4*z^2)*x + 8*z^6 */ static const long X1_30_crv_0[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, 0, 0, 0, 0, 8 }; /* 8*z^6 */ static const long X1_30_crv_1[10] = { evaltyp(t_VECSMALL) | _evallg(10), vZ, 0, 0, 4, 0, 0, 12, 28, -8 }; /* -8*z^7 + 28*z^6 + 12*z^5 + 4*z^2 */ static const long X1_30_crv_2[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 4, 18, -12, 12, 40, 18, -16, 2 }; /* 2*z^8 - 16*z^7 + 18*z^6 + 40*z^5 + 12*z^4 - 12*z^3 + 18*z^2 + 4*z */ static const long X1_30_crv_3[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, 1, 15, 21, -32, 46, 27, -13, -3, 1 }; /* z^8 - 3*z^7 - 13*z^6 + 27*z^5 + 46*z^4 - 32*z^3 + 21*z^2 + 15*z + 1 */ static const long X1_30_crv_4[10] = { evaltyp(t_VECSMALL) | _evallg(10), vZ, 3, 18, 1, -18, 44, -13, -3, 1 }; /* z^7 - 3*z^6 - 13*z^5 + 44*z^4 - 18*z^3 + z^2 + 18*z + 3 */ static const long X1_30_crv_5[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 3, 7, -6, 3, 6, -5, 1 }; /* z^6 - 5*z^5 + 6*z^4 + 3*z^3 - 6*z^2 + 7*z + 3 */ static const long *X1_30_crv[9] = { (long *)(evaltyp(t_POL) | _evallg(9)), (long *)(evalvarn(0) | evalsigne(1)), X1_30_crv_0, X1_30_crv_1, X1_30_crv_2, X1_30_crv_3, X1_30_crv_4, X1_30_crv_5, FLX_1 }; /* x + 1 */ static const long *X1_30_r_n[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), FLX_1, FLX_1 }; /* 1 */ static const long *X1_30_r_d[3] = { (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)), FLX_1 }; /* 4*x^2 + (4*z + 4)*x + 4*z */ static const long X1_30_s_n_0[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 0, 4 }; /* 4*z */ static const long X1_30_s_n_1[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 4, 4 }; /* 4*z + 4 */ static const long X1_30_s_n_2[3] = { evaltyp(t_VECSMALL) | _evallg(3), vZ, 4 }; /* 4 */ static const long *X1_30_s_n[5] = { (long *)(evaltyp(t_POL) | _evallg(5)), (long *)(evalvarn(0) | evalsigne(1)), X1_30_s_n_0, X1_30_s_n_1, X1_30_s_n_2 }; /* (z - 3)*x^3 - 6*x^2 + (-4*z - 4)*x - 4*z */ static const long X1_30_s_d_0[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 0, -4 }; /* -4*z */ static const long X1_30_s_d_1[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, -4, -4 }; /* -4*z - 4 */ static const long X1_30_s_d_2[3] = { evaltyp(t_VECSMALL) | _evallg(3), vZ, -6 }; /* -6 */ static const long X1_30_s_d_3[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, -3, 1 }; /* z - 3 */ static const long *X1_30_s_d[6] = { (long *)(evaltyp(t_POL) | _evallg(6)), (long *)(evalvarn(0) | evalsigne(1)), X1_30_s_d_0, X1_30_s_d_1, X1_30_s_d_2, X1_30_s_d_3 }; /* u^12 + (z^10 - z^9 - 8*z^8 + 6*z^7 + 23*z^6 - 12*z^5 - 26*z^4 + 8*z^3 + 10*z^2 + 7*z - 3)*u^11 + (z^11 - 8*z^10 - 11*z^9 + 61*z^8 + 45*z^7 - 152*z^6 - 70*z^5 + 129*z^4 + 37*z^3 - 24*z + 3)*u^10 + (-8*z^11 + 17*z^10 + 105*z^9 - 93*z^8 - 387*z^7 + 145*z^6 + 453*z^5 - 57*z^4 - 91*z^3 - 73*z^2 + 31*z - 1)*u^9 + (-z^12 + 25*z^11 + 27*z^10 - 273*z^9 - 260*z^8 + 745*z^7 + 569*z^6 - 572*z^5 - 266*z^4 - 36*z^3 + 131*z^2 - 19*z)*u^8 + (5*z^12 - 32*z^11 - 162*z^10 + 193*z^9 + 911*z^8 - 147*z^7 - 1254*z^6 - 78*z^5 + 301*z^4 + 222*z^3 - 99*z^2 + 6*z)*u^7 + (-10*z^12 + 240*z^10 + 268*z^9 - 864*z^8 - 967*z^7 + 713*z^6 + 598*z^5 + 28*z^4 - 216*z^3 + 37*z^2 - z)*u^6 + (10*z^12 + 44*z^11 - 115*z^10 - 537*z^9 + 19*z^8 + 1033*z^7 + 242*z^6 - 351*z^5 - 200*z^4 + 91*z^3 - 6*z^2)*u^5 + (-5*z^12 - 47*z^11 - 52*z^10 + 293*z^9 + 448*z^8 - 266*z^7 - 390*z^6 - 17*z^5 + 112*z^4 - 15*z^3)*u^4 + (z^12 + 20*z^11 + 76*z^10 - z^9 - 247*z^8 - 119*z^7 + 103*z^6 + 68*z^5 - 20*z^4)*u^3 + (-3*z^11 - 27*z^10 - 49*z^9 + 25*z^8 + 67*z^7 + 13*z^6 - 15*z^5)*u^2 + (3*z^10 + 14*z^9 + 11*z^8 - 5*z^7 - 6*z^6)*u + (-z^9 - 2*z^8 - z^7) */ static const long X1_31_crv_0[12] = { evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 0, 0, 0, 0, 0, 0, -1, -2, -1 }; /* -z^9 - 2*z^8 - z^7 */ static const long X1_31_crv_1[13] = { evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 0, 0, 0, 0, 0, -6, -5, 11, 14, 3 }; /* 3*z^10 + 14*z^9 + 11*z^8 - 5*z^7 - 6*z^6 */ static const long X1_31_crv_2[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, 0, 0, -15, 13, 67, 25, -49, -27, -3 }; /* -3*z^11 - 27*z^10 - 49*z^9 + 25*z^8 + 67*z^7 + 13*z^6 - 15*z^5 */ static const long X1_31_crv_3[15] = { evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, 0, 0, 0, -20, 68, 103, -119, -247, -1, 76, 20, 1 }; /* z^12 + 20*z^11 + 76*z^10 - z^9 - 247*z^8 - 119*z^7 + 103*z^6 + 68*z^5 - 20*z^4 */ static const long X1_31_crv_4[15] = { evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, 0, 0, -15, 112, -17, -390, -266, 448, 293, -52, -47, -5 }; /* -5*z^12 - 47*z^11 - 52*z^10 + 293*z^9 + 448*z^8 - 266*z^7 - 390*z^6 - 17*z^5 + 112*z^4 - 15*z^3 */ static const long X1_31_crv_5[15] = { evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, 0, -6, 91, -200, -351, 242, 1033, 19, -537, -115, 44, 10 }; /* 10*z^12 + 44*z^11 - 115*z^10 - 537*z^9 + 19*z^8 + 1033*z^7 + 242*z^6 - 351*z^5 - 200*z^4 + 91*z^3 - 6*z^2 */ static const long X1_31_crv_6[15] = { evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, -1, 37, -216, 28, 598, 713, -967, -864, 268, 240, 0, -10 }; /* -10*z^12 + 240*z^10 + 268*z^9 - 864*z^8 - 967*z^7 + 713*z^6 + 598*z^5 + 28*z^4 - 216*z^3 + 37*z^2 - z */ static const long X1_31_crv_7[15] = { evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, 6, -99, 222, 301, -78, -1254, -147, 911, 193, -162, -32, 5 }; /* 5*z^12 - 32*z^11 - 162*z^10 + 193*z^9 + 911*z^8 - 147*z^7 - 1254*z^6 - 78*z^5 + 301*z^4 + 222*z^3 - 99*z^2 + 6*z */ static const long X1_31_crv_8[15] = { evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, -19, 131, -36, -266, -572, 569, 745, -260, -273, 27, 25, -1 }; /* -z^12 + 25*z^11 + 27*z^10 - 273*z^9 - 260*z^8 + 745*z^7 + 569*z^6 - 572*z^5 - 266*z^4 - 36*z^3 + 131*z^2 - 19*z */ static const long X1_31_crv_9[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, -1, 31, -73, -91, -57, 453, 145, -387, -93, 105, 17, -8 }; /* -8*z^11 + 17*z^10 + 105*z^9 - 93*z^8 - 387*z^7 + 145*z^6 + 453*z^5 - 57*z^4 - 91*z^3 - 73*z^2 + 31*z - 1 */ static const long X1_31_crv_10[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 3, -24, 0, 37, 129, -70, -152, 45, 61, -11, -8, 1 }; /* z^11 - 8*z^10 - 11*z^9 + 61*z^8 + 45*z^7 - 152*z^6 - 70*z^5 + 129*z^4 + 37*z^3 - 24*z + 3 */ static const long X1_31_crv_11[13] = { evaltyp(t_VECSMALL) | _evallg(13), vZ, -3, 7, 10, 8, -26, -12, 23, 6, -8, -1, 1 }; /* z^10 - z^9 - 8*z^8 + 6*z^7 + 23*z^6 - 12*z^5 - 26*z^4 + 8*z^3 + 10*z^2 + 7*z - 3 */ static const long *X1_31_crv[15] = { (long *)(evaltyp(t_POL) | _evallg(15)), (long *)(evalvarn(0) | evalsigne(1)), X1_31_crv_0, X1_31_crv_1, X1_31_crv_2, X1_31_crv_3, X1_31_crv_4, X1_31_crv_5, X1_31_crv_6, X1_31_crv_7, X1_31_crv_8, X1_31_crv_9, X1_31_crv_10, X1_31_crv_11, FLX_1 }; /* (-z^4 + 3*z^3 - 2*z^2 - z + 1)*u^7 + (-z^5 + 7*z^4 - 11*z^3 + 2*z^2 + 3*z)*u^6 + (5*z^5 - 18*z^4 + 12*z^3 + 3*z^2 - 1)*u^5 + (z^6 - 11*z^5 + 22*z^4 + z^3 - 6*z^2 - 4*z + 1)*u^4 + (-2*z^6 + 15*z^5 - 9*z^4 - 15*z^3 - 3*z^2 + 4*z)*u^3 + (3*z^6 - 11*z^5 - 10*z^4 + 4*z^3 + 6*z^2)*u^2 + (-3*z^6 + 6*z^4 + 4*z^3)*u + (z^6 + 2*z^5 + z^4) */ static const long X1_31_r_n_0[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, 0, 0, 1, 2, 1 }; /* z^6 + 2*z^5 + z^4 */ static const long X1_31_r_n_1[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, 0, 4, 6, 0, -3 }; /* -3*z^6 + 6*z^4 + 4*z^3 */ static const long X1_31_r_n_2[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, 6, 4, -10, -11, 3 }; /* 3*z^6 - 11*z^5 - 10*z^4 + 4*z^3 + 6*z^2 */ static const long X1_31_r_n_3[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 4, -3, -15, -9, 15, -2 }; /* -2*z^6 + 15*z^5 - 9*z^4 - 15*z^3 - 3*z^2 + 4*z */ static const long X1_31_r_n_4[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 1, -4, -6, 1, 22, -11, 1 }; /* z^6 - 11*z^5 + 22*z^4 + z^3 - 6*z^2 - 4*z + 1 */ static const long X1_31_r_n_5[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, -1, 0, 3, 12, -18, 5 }; /* 5*z^5 - 18*z^4 + 12*z^3 + 3*z^2 - 1 */ static const long X1_31_r_n_6[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 3, 2, -11, 7, -1 }; /* -z^5 + 7*z^4 - 11*z^3 + 2*z^2 + 3*z */ static const long X1_31_r_n_7[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 1, -1, -2, 3, -1 }; /* -z^4 + 3*z^3 - 2*z^2 - z + 1 */ static const long *X1_31_r_n[10] = { (long *)(evaltyp(t_POL) | _evallg(10)), (long *)(evalvarn(0) | evalsigne(1)), X1_31_r_n_0, X1_31_r_n_1, X1_31_r_n_2, X1_31_r_n_3, X1_31_r_n_4, X1_31_r_n_5, X1_31_r_n_6, X1_31_r_n_7 }; /* (-z + 1)*u^6 + (-4*z^2 + 5*z - 1)*u^5 + (-z^6 - z^5 + 5*z^4 - z^3 + 6*z^2 - 7*z + 1)*u^4 + (3*z^6 + 10*z^5 - 6*z^4 - 8*z^3 - 10*z^2 + 5*z)*u^3 + (-z^6 - 14*z^5 - 10*z^4 + z^3 + 8*z^2)*u^2 + (-2*z^6 + 2*z^5 + 7*z^4 + 5*z^3)*u + (z^6 + 2*z^5 + z^4) */ static const long X1_31_r_d_0[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, 0, 0, 1, 2, 1 }; /* z^6 + 2*z^5 + z^4 */ static const long X1_31_r_d_1[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, 0, 5, 7, 2, -2 }; /* -2*z^6 + 2*z^5 + 7*z^4 + 5*z^3 */ static const long X1_31_r_d_2[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, 8, 1, -10, -14, -1 }; /* -z^6 - 14*z^5 - 10*z^4 + z^3 + 8*z^2 */ static const long X1_31_r_d_3[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 5, -10, -8, -6, 10, 3 }; /* 3*z^6 + 10*z^5 - 6*z^4 - 8*z^3 - 10*z^2 + 5*z */ static const long X1_31_r_d_4[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 1, -7, 6, -1, 5, -1, -1 }; /* -z^6 - z^5 + 5*z^4 - z^3 + 6*z^2 - 7*z + 1 */ static const long X1_31_r_d_5[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, -1, 5, -4 }; /* -4*z^2 + 5*z - 1 */ static const long X1_31_r_d_6[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, -1 }; /* -z + 1 */ static const long *X1_31_r_d[9] = { (long *)(evaltyp(t_POL) | _evallg(9)), (long *)(evalvarn(0) | evalsigne(1)), X1_31_r_d_0, X1_31_r_d_1, X1_31_r_d_2, X1_31_r_d_3, X1_31_r_d_4, X1_31_r_d_5, X1_31_r_d_6 }; /* (-z^3 + 3*z^2 - z - 2)*u^6 + (-z^4 + 7*z^3 - 8*z^2 - 3*z + 1)*u^5 + (5*z^4 - 15*z^3 + 2*z^2 + 5*z + 1)*u^4 + (z^5 - 11*z^4 + 9*z^3 + 9*z^2 - z - 1)*u^3 + (-3*z^5 + 8*z^4 + 6*z^3 - 4*z^2 - 2*z)*u^2 + (3*z^5 + z^4 - 4*z^3 - 2*z^2)*u + (-z^5 - 2*z^4 - z^3) */ static const long X1_31_s_n_0[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, 0, -1, -2, -1 }; /* -z^5 - 2*z^4 - z^3 */ static const long X1_31_s_n_1[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, -2, -4, 1, 3 }; /* 3*z^5 + z^4 - 4*z^3 - 2*z^2 */ static const long X1_31_s_n_2[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, -2, -4, 6, 8, -3 }; /* -3*z^5 + 8*z^4 + 6*z^3 - 4*z^2 - 2*z */ static const long X1_31_s_n_3[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, -1, -1, 9, 9, -11, 1 }; /* z^5 - 11*z^4 + 9*z^3 + 9*z^2 - z - 1 */ static const long X1_31_s_n_4[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 1, 5, 2, -15, 5 }; /* 5*z^4 - 15*z^3 + 2*z^2 + 5*z + 1 */ static const long X1_31_s_n_5[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 1, -3, -8, 7, -1 }; /* -z^4 + 7*z^3 - 8*z^2 - 3*z + 1 */ static const long X1_31_s_n_6[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, -2, -1, 3, -1 }; /* -z^3 + 3*z^2 - z - 2 */ static const long *X1_31_s_n[9] = { (long *)(evaltyp(t_POL) | _evallg(9)), (long *)(evalvarn(0) | evalsigne(1)), X1_31_s_n_0, X1_31_s_n_1, X1_31_s_n_2, X1_31_s_n_3, X1_31_s_n_4, X1_31_s_n_5, X1_31_s_n_6 }; /* (z^2 - z - 1)*u^6 + (2*z^3 - 4*z^2 - z)*u^5 + (z^4 - 6*z^3 + 3*z^2 + z + 1)*u^4 + (-z^5 - 7*z^4 + 5*z^3 + 4*z^2 + 2*z - 1)*u^3 + (10*z^4 + 7*z^3 - z^2 - 3*z)*u^2 + (2*z^5 - z^4 - 5*z^3 - 3*z^2)*u + (-z^5 - 2*z^4 - z^3) */ static const long X1_31_s_d_0[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, 0, -1, -2, -1 }; /* -z^5 - 2*z^4 - z^3 */ static const long X1_31_s_d_1[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, -3, -5, -1, 2 }; /* 2*z^5 - z^4 - 5*z^3 - 3*z^2 */ static const long X1_31_s_d_2[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, -3, -1, 7, 10 }; /* 10*z^4 + 7*z^3 - z^2 - 3*z */ static const long X1_31_s_d_3[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, -1, 2, 4, 5, -7, -1 }; /* -z^5 - 7*z^4 + 5*z^3 + 4*z^2 + 2*z - 1 */ static const long X1_31_s_d_4[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 1, 1, 3, -6, 1 }; /* z^4 - 6*z^3 + 3*z^2 + z + 1 */ static const long X1_31_s_d_5[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, -1, -4, 2 }; /* 2*z^3 - 4*z^2 - z */ static const long X1_31_s_d_6[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, -1, -1, 1 }; /* z^2 - z - 1 */ static const long *X1_31_s_d[9] = { (long *)(evaltyp(t_POL) | _evallg(9)), (long *)(evalvarn(0) | evalsigne(1)), X1_31_s_d_0, X1_31_s_d_1, X1_31_s_d_2, X1_31_s_d_3, X1_31_s_d_4, X1_31_s_d_5, X1_31_s_d_6 }; /* (z^8 - 4*z^7 + 6*z^6 - 4*z^5 + z^4)*x^8 + (16*z^8 - 48*z^7 + 48*z^6 - 16*z^5)*x^7 + (z^11 - 2*z^10 + z^9 + 104*z^8 - 208*z^7 + 96*z^6 + 16*z^5 - 8*z^4 - z^3 + 2*z^2 - z)*x^6 + (12*z^11 - 12*z^10 + 352*z^8 - 352*z^7 - 96*z^6 + 96*z^5 - 12*z^3 + 12*z^2)*x^5 + (54*z^11 - 6*z^9 + 664*z^8 - 432*z^6 + 24*z^4 - 54*z^3 + 6*z)*x^4 + (112*z^11 + 112*z^10 + 64*z^9 + 768*z^8 + 768*z^7 - 128*z^6 - 128*z^5 + 64*z^4 - 48*z^3 - 48*z^2)*x^3 + (106*z^11 + 212*z^10 + 198*z^9 + 600*z^8 + 1020*z^7 + 576*z^6 + 132*z^5 + 168*z^4 + 90*z^3 - 20*z^2 - 10*z)*x^2 + (40*z^11 + 120*z^10 + 144*z^9 + 240*z^8 + 480*z^7 + 480*z^6 + 240*z^5 + 144*z^4 + 120*z^3 + 40*z^2)*x + (-z^12 + 6*z^10 - 15*z^8 + 20*z^6 - 15*z^4 + 6*z^2 - 1) */ static const long X1_32_crv_0[15] = { evaltyp(t_VECSMALL) | _evallg(15), vZ, -1, 0, 6, 0, -15, 0, 20, 0, -15, 0, 6, 0, -1 }; /* -z^12 + 6*z^10 - 15*z^8 + 20*z^6 - 15*z^4 + 6*z^2 - 1 */ static const long X1_32_crv_1[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 40, 120, 144, 240, 480, 480, 240, 144, 120, 40 }; /* 40*z^11 + 120*z^10 + 144*z^9 + 240*z^8 + 480*z^7 + 480*z^6 + 240*z^5 + 144*z^4 + 120*z^3 + 40*z^2 */ static const long X1_32_crv_2[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, -10, -20, 90, 168, 132, 576, 1020, 600, 198, 212, 106 }; /* 106*z^11 + 212*z^10 + 198*z^9 + 600*z^8 + 1020*z^7 + 576*z^6 + 132*z^5 + 168*z^4 + 90*z^3 - 20*z^2 - 10*z */ static const long X1_32_crv_3[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, -48, -48, 64, -128, -128, 768, 768, 64, 112, 112 }; /* 112*z^11 + 112*z^10 + 64*z^9 + 768*z^8 + 768*z^7 - 128*z^6 - 128*z^5 + 64*z^4 - 48*z^3 - 48*z^2 */ static const long X1_32_crv_4[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 6, 0, -54, 24, 0, -432, 0, 664, -6, 0, 54 }; /* 54*z^11 - 6*z^9 + 664*z^8 - 432*z^6 + 24*z^4 - 54*z^3 + 6*z */ static const long X1_32_crv_5[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 12, -12, 0, 96, -96, -352, 352, 0, -12, 12 }; /* 12*z^11 - 12*z^10 + 352*z^8 - 352*z^7 - 96*z^6 + 96*z^5 - 12*z^3 + 12*z^2 */ static const long X1_32_crv_6[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, -1, 2, -1, -8, 16, 96, -208, 104, 1, -2, 1 }; /* z^11 - 2*z^10 + z^9 + 104*z^8 - 208*z^7 + 96*z^6 + 16*z^5 - 8*z^4 - z^3 + 2*z^2 - z */ static const long X1_32_crv_7[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 0, 0, 0, 0, -16, 48, -48, 16 }; /* 16*z^8 - 48*z^7 + 48*z^6 - 16*z^5 */ static const long X1_32_crv_8[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 0, 0, 0, 1, -4, 6, -4, 1 }; /* z^8 - 4*z^7 + 6*z^6 - 4*z^5 + z^4 */ static const long *X1_32_crv[11] = { (long *)(evaltyp(t_POL) | _evallg(11)), (long *)(evalvarn(0) | evalsigne(1)), X1_32_crv_0, X1_32_crv_1, X1_32_crv_2, X1_32_crv_3, X1_32_crv_4, X1_32_crv_5, X1_32_crv_6, X1_32_crv_7, X1_32_crv_8 }; /* (z - 1)*x + 2*z */ static const long X1_32_r_n_0[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 0, 2 }; /* 2*z */ static const long X1_32_r_n_1[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, -1, 1 }; /* z - 1 */ static const long *X1_32_r_n[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), X1_32_r_n_0, X1_32_r_n_1 }; /* 2 */ static const long X1_32_r_d_0[3] = { evaltyp(t_VECSMALL) | _evallg(3), vZ, 2 }; /* 2 */ static const long *X1_32_r_d[3] = { (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)), X1_32_r_d_0 }; /* (-z + 1)*x - 2*z */ static const long X1_32_s_n_0[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 0, -2 }; /* -2*z */ static const long X1_32_s_n_1[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, -1 }; /* -z + 1 */ static const long *X1_32_s_n[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), X1_32_s_n_0, X1_32_s_n_1 }; /* 2*z */ static const long X1_32_s_d_0[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 0, 2 }; /* 2*z */ static const long *X1_32_s_d[3] = { (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)), X1_32_s_d_0 }; /* z^8*x^10 + (-z^17 - 2*z^16 - 4*z^15 - 6*z^14 - 9*z^13 - 12*z^12 - 16*z^11 - 20*z^10 - 25*z^9 - 18*z^8)*x^9 + (-3*z^17 - 15*z^16 - 24*z^15 - 28*z^14 - 16*z^13 + 6*z^12 + 32*z^11 + 32*z^10 - 33*z^9 - 155*z^8 - 188*z^7 - 108*z^6 - 58*z^5 - 28*z^4 - 12*z^3 - 4*z^2 - z)*x^8 + (-6*z^17 - 48*z^16 - 144*z^15 - 226*z^14 - 225*z^13 - 39*z^12 + 402*z^11 + 1116*z^10 + 1854*z^9 + 2071*z^8 + 1536*z^7 + 852*z^6 + 476*z^5 + 249*z^4 + 114*z^3 + 40*z^2 + 9*z)*x^7 + (-10*z^17 - 110*z^16 - 520*z^15 - 1464*z^14 - 3006*z^13 - 5160*z^12 - 7660*z^11 - 9656*z^10 - 9778*z^9 - 7536*z^8 - 4500*z^7 - 2580*z^6 - 1696*z^5 - 1028*z^4 - 508*z^3 - 180*z^2 - 36*z)*x^6 + (z^20 + 10*z^19 + 60*z^18 + 255*z^17 + 795*z^16 + 1872*z^15 + 3576*z^14 + 6042*z^13 + 9198*z^12 + 11872*z^11 + 12028*z^10 + 8886*z^9 + 4847*z^8 + 3188*z^7 + 3762*z^6 + 3917*z^5 + 2801*z^4 + 1422*z^3 + 480*z^2 + 84*z)*x^5 + (10*z^17 + 60*z^16 + 120*z^15 - 64*z^14 - 690*z^13 - 1026*z^12 + 392*z^11 + 3456*z^10 + 4980*z^9 + 1576*z^8 - 5292*z^7 - 10032*z^6 - 9630*z^5 - 6174*z^4 - 2808*z^3 - 840*z^2 - 126*z)*x^4 + (6*z^17 + 54*z^16 + 192*z^15 + 254*z^14 - 419*z^13 - 2392*z^12 - 4432*z^11 - 3020*z^10 + 4499*z^9 + 15607*z^8 + 23336*z^7 + 22966*z^6 + 16391*z^5 + 8779*z^4 + 3458*z^3 + 896*z^2 + 112*z - 1)*x^3 + (3*z^17 + 36*z^16 + 192*z^15 + 572*z^14 + 884*z^13 - 150*z^12 - 4536*z^11 - 13080*z^10 - 23253*z^9 - 29900*z^8 - 29288*z^7 - 22380*z^6 - 13480*z^5 - 6328*z^4 - 2184*z^3 - 476*z^2 - 41*z + 3)*x^2 + (z^17 + 15*z^16 + 108*z^15 + 494*z^14 + 1605*z^13 + 3927*z^12 + 7490*z^11 + 11376*z^10 + 13938*z^9 + 13882*z^8 + 11292*z^7 + 7506*z^6 + 4025*z^5 + 1659*z^4 + 462*z^3 + 56*z^2 - 9*z - 3)*x + (z^8 + 8*z^7 + 28*z^6 + 56*z^5 + 70*z^4 + 56*z^3 + 28*z^2 + 8*z + 1) */ static const long X1_33_crv_0[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, 1, 8, 28, 56, 70, 56, 28, 8, 1 }; /* z^8 + 8*z^7 + 28*z^6 + 56*z^5 + 70*z^4 + 56*z^3 + 28*z^2 + 8*z + 1 */ static const long X1_33_crv_1[20] = { evaltyp(t_VECSMALL) | _evallg(20), vZ, -3, -9, 56, 462, 1659, 4025, 7506, 11292, 13882, 13938, 11376, 7490, 3927, 1605, 494, 108, 15, 1 }; /* z^17 + 15*z^16 + 108*z^15 + 494*z^14 + 1605*z^13 + 3927*z^12 + 7490*z^11 + 11376*z^10 + 13938*z^9 + 13882*z^8 + 11292*z^7 + 7506*z^6 + 4025*z^5 + 1659*z^4 + 462*z^3 + 56*z^2 - 9*z - 3 */ static const long X1_33_crv_2[20] = { evaltyp(t_VECSMALL) | _evallg(20), vZ, 3, -41, -476, -2184, -6328, -13480, -22380, -29288, -29900, -23253, -13080, -4536, -150, 884, 572, 192, 36, 3 }; /* 3*z^17 + 36*z^16 + 192*z^15 + 572*z^14 + 884*z^13 - 150*z^12 - 4536*z^11 - 13080*z^10 - 23253*z^9 - 29900*z^8 - 29288*z^7 - 22380*z^6 - 13480*z^5 - 6328*z^4 - 2184*z^3 - 476*z^2 - 41*z + 3 */ static const long X1_33_crv_3[20] = { evaltyp(t_VECSMALL) | _evallg(20), vZ, -1, 112, 896, 3458, 8779, 16391, 22966, 23336, 15607, 4499, -3020, -4432, -2392, -419, 254, 192, 54, 6 }; /* 6*z^17 + 54*z^16 + 192*z^15 + 254*z^14 - 419*z^13 - 2392*z^12 - 4432*z^11 - 3020*z^10 + 4499*z^9 + 15607*z^8 + 23336*z^7 + 22966*z^6 + 16391*z^5 + 8779*z^4 + 3458*z^3 + 896*z^2 + 112*z - 1 */ static const long X1_33_crv_4[20] = { evaltyp(t_VECSMALL) | _evallg(20), vZ, 0, -126, -840, -2808, -6174, -9630, -10032, -5292, 1576, 4980, 3456, 392, -1026, -690, -64, 120, 60, 10 }; /* 10*z^17 + 60*z^16 + 120*z^15 - 64*z^14 - 690*z^13 - 1026*z^12 + 392*z^11 + 3456*z^10 + 4980*z^9 + 1576*z^8 - 5292*z^7 - 10032*z^6 - 9630*z^5 - 6174*z^4 - 2808*z^3 - 840*z^2 - 126*z */ static const long X1_33_crv_5[23] = { evaltyp(t_VECSMALL) | _evallg(23), vZ, 0, 84, 480, 1422, 2801, 3917, 3762, 3188, 4847, 8886, 12028, 11872, 9198, 6042, 3576, 1872, 795, 255, 60, 10, 1 }; /* z^20 + 10*z^19 + 60*z^18 + 255*z^17 + 795*z^16 + 1872*z^15 + 3576*z^14 + 6042*z^13 + 9198*z^12 + 11872*z^11 + 12028*z^10 + 8886*z^9 + 4847*z^8 + 3188*z^7 + 3762*z^6 + 3917*z^5 + 2801*z^4 + 1422*z^3 + 480*z^2 + 84*z */ static const long X1_33_crv_6[20] = { evaltyp(t_VECSMALL) | _evallg(20), vZ, 0, -36, -180, -508, -1028, -1696, -2580, -4500, -7536, -9778, -9656, -7660, -5160, -3006, -1464, -520, -110, -10 }; /* -10*z^17 - 110*z^16 - 520*z^15 - 1464*z^14 - 3006*z^13 - 5160*z^12 - 7660*z^11 - 9656*z^10 - 9778*z^9 - 7536*z^8 - 4500*z^7 - 2580*z^6 - 1696*z^5 - 1028*z^4 - 508*z^3 - 180*z^2 - 36*z */ static const long X1_33_crv_7[20] = { evaltyp(t_VECSMALL) | _evallg(20), vZ, 0, 9, 40, 114, 249, 476, 852, 1536, 2071, 1854, 1116, 402, -39, -225, -226, -144, -48, -6 }; /* -6*z^17 - 48*z^16 - 144*z^15 - 226*z^14 - 225*z^13 - 39*z^12 + 402*z^11 + 1116*z^10 + 1854*z^9 + 2071*z^8 + 1536*z^7 + 852*z^6 + 476*z^5 + 249*z^4 + 114*z^3 + 40*z^2 + 9*z */ static const long X1_33_crv_8[20] = { evaltyp(t_VECSMALL) | _evallg(20), vZ, 0, -1, -4, -12, -28, -58, -108, -188, -155, -33, 32, 32, 6, -16, -28, -24, -15, -3 }; /* -3*z^17 - 15*z^16 - 24*z^15 - 28*z^14 - 16*z^13 + 6*z^12 + 32*z^11 + 32*z^10 - 33*z^9 - 155*z^8 - 188*z^7 - 108*z^6 - 58*z^5 - 28*z^4 - 12*z^3 - 4*z^2 - z */ static const long X1_33_crv_9[20] = { evaltyp(t_VECSMALL) | _evallg(20), vZ, 0, 0, 0, 0, 0, 0, 0, 0, -18, -25, -20, -16, -12, -9, -6, -4, -2, -1 }; /* -z^17 - 2*z^16 - 4*z^15 - 6*z^14 - 9*z^13 - 12*z^12 - 16*z^11 - 20*z^10 - 25*z^9 - 18*z^8 */ static const long X1_33_crv_10[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; /* z^8 */ static const long *X1_33_crv[13] = { (long *)(evaltyp(t_POL) | _evallg(13)), (long *)(evalvarn(0) | evalsigne(1)), X1_33_crv_0, X1_33_crv_1, X1_33_crv_2, X1_33_crv_3, X1_33_crv_4, X1_33_crv_5, X1_33_crv_6, X1_33_crv_7, X1_33_crv_8, X1_33_crv_9, X1_33_crv_10 }; /* (z + 1) */ static const long X1_33_r_n_0[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */ static const long *X1_33_r_n[3] = { (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)), X1_33_r_n_0 }; /* z */ static const long *X1_33_r_d[3] = { (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)), FLX_Z }; /* 1 */ static const long *X1_33_s_n[3] = { (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)), FLX_1 }; /* (-z - 1)*x + (z + 1) */ static const long X1_33_s_d_0[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */ static const long X1_33_s_d_1[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, -1, -1 }; /* -z - 1 */ static const long *X1_33_s_d[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), X1_33_s_d_0, X1_33_s_d_1 }; /* u^10 + (z^5 - z^2 - 4*z + 4)*u^9 + (8*z^5 - z^4 - 5*z^3 + z^2 - 12*z + 6)*u^8 + (5*z^7 - 2*z^6 + 16*z^5 - z^4 - 20*z^3 + 9*z^2 - 11*z + 4)*u^7 + (-z^8 + 24*z^7 + 2*z^6 + 7*z^5 - 36*z^3 + 8*z^2 + 1)*u^6 + (z^10 + z^9 - 7*z^8 + 40*z^7 + 26*z^6 + 2*z^5 + 8*z^4 - 29*z^3 - 3*z^2 + 5*z)*u^5 + (2*z^10 + 4*z^9 - 5*z^8 + 35*z^7 + 37*z^6 + 5*z^5 + 12*z^4 - 6*z^3 - 5*z^2 + 2*z)*u^4 + (z^10 + 4*z^9 + 7*z^8 + 28*z^7 + 29*z^6 + 7*z^5 + 5*z^4 + 3*z^3)*u^3 + (2*z^9 + 10*z^8 + 16*z^7 + 10*z^6 + 2*z^5 - z^4 + z^2)*u^2 + (z^9 + 5*z^8 + 5*z^7 - z^5 - z^4 - z^3)*u + (-z^7 - 2*z^6 - z^5) */ static const long X1_34_crv_0[10] = { evaltyp(t_VECSMALL) | _evallg(10), vZ, 0, 0, 0, 0, 0, -1, -2, -1 }; /* -z^7 - 2*z^6 - z^5 */ static const long X1_34_crv_1[12] = { evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 0, 0, -1, -1, -1, 0, 5, 5, 1 }; /* z^9 + 5*z^8 + 5*z^7 - z^5 - z^4 - z^3 */ static const long X1_34_crv_2[12] = { evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 0, 1, 0, -1, 2, 10, 16, 10, 2 }; /* 2*z^9 + 10*z^8 + 16*z^7 + 10*z^6 + 2*z^5 - z^4 + z^2 */ static const long X1_34_crv_3[13] = { evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 0, 0, 3, 5, 7, 29, 28, 7, 4, 1 }; /* z^10 + 4*z^9 + 7*z^8 + 28*z^7 + 29*z^6 + 7*z^5 + 5*z^4 + 3*z^3 */ static const long X1_34_crv_4[13] = { evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 2, -5, -6, 12, 5, 37, 35, -5, 4, 2 }; /* 2*z^10 + 4*z^9 - 5*z^8 + 35*z^7 + 37*z^6 + 5*z^5 + 12*z^4 - 6*z^3 - 5*z^2 + 2*z */ static const long X1_34_crv_5[13] = { evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 5, -3, -29, 8, 2, 26, 40, -7, 1, 1 }; /* z^10 + z^9 - 7*z^8 + 40*z^7 + 26*z^6 + 2*z^5 + 8*z^4 - 29*z^3 - 3*z^2 + 5*z */ static const long X1_34_crv_6[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, 1, 0, 8, -36, 0, 7, 2, 24, -1 }; /* -z^8 + 24*z^7 + 2*z^6 + 7*z^5 - 36*z^3 + 8*z^2 + 1 */ static const long X1_34_crv_7[10] = { evaltyp(t_VECSMALL) | _evallg(10), vZ, 4, -11, 9, -20, -1, 16, -2, 5 }; /* 5*z^7 - 2*z^6 + 16*z^5 - z^4 - 20*z^3 + 9*z^2 - 11*z + 4 */ static const long X1_34_crv_8[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 6, -12, 1, -5, -1, 8 }; /* 8*z^5 - z^4 - 5*z^3 + z^2 - 12*z + 6 */ static const long X1_34_crv_9[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 4, -4, -1, 0, 0, 1 }; /* z^5 - z^2 - 4*z + 4 */ static const long *X1_34_crv[13] = { (long *)(evaltyp(t_POL) | _evallg(13)), (long *)(evalvarn(0) | evalsigne(1)), X1_34_crv_0, X1_34_crv_1, X1_34_crv_2, X1_34_crv_3, X1_34_crv_4, X1_34_crv_5, X1_34_crv_6, X1_34_crv_7, X1_34_crv_8, X1_34_crv_9, FLX_1 }; /* u^8 + (-z^2 - 3*z + 3)*u^7 + (-z^3 + 3*z^2 - 5*z + 3)*u^6 + (-3*z^4 - 11*z^3 + 7*z^2 - 2*z + 1)*u^5 + (2*z^5 + 2*z^4 - 15*z^3 + z^2 - z)*u^4 + (-2*z^6 + 5*z^4 - 7*z^3 - 3*z^2 - 2*z)*u^3 + (z^7 + 2*z^4 - z)*u^2 + (z^5 + z^4 + z^3 + z^2)*u + (z^6 + 2*z^5 + z^4) */ static const long X1_34_r_n_0[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, 0, 0, 1, 2, 1 }; /* z^6 + 2*z^5 + z^4 */ static const long X1_34_r_n_1[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, 1, 1, 1, 1 }; /* z^5 + z^4 + z^3 + z^2 */ static const long X1_34_r_n_2[10] = { evaltyp(t_VECSMALL) | _evallg(10), vZ, 0, -1, 0, 0, 2, 0, 0, 1 }; /* z^7 + 2*z^4 - z */ static const long X1_34_r_n_3[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, -2, -3, -7, 5, 0, -2 }; /* -2*z^6 + 5*z^4 - 7*z^3 - 3*z^2 - 2*z */ static const long X1_34_r_n_4[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, -1, 1, -15, 2, 2 }; /* 2*z^5 + 2*z^4 - 15*z^3 + z^2 - z */ static const long X1_34_r_n_5[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 1, -2, 7, -11, -3 }; /* -3*z^4 - 11*z^3 + 7*z^2 - 2*z + 1 */ static const long X1_34_r_n_6[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 3, -5, 3, -1 }; /* -z^3 + 3*z^2 - 5*z + 3 */ static const long X1_34_r_n_7[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 3, -3, -1 }; /* -z^2 - 3*z + 3 */ static const long *X1_34_r_n[11] = { (long *)(evaltyp(t_POL) | _evallg(11)), (long *)(evalvarn(0) | evalsigne(1)), X1_34_r_n_0, X1_34_r_n_1, X1_34_r_n_2, X1_34_r_n_3, X1_34_r_n_4, X1_34_r_n_5, X1_34_r_n_6, X1_34_r_n_7, FLX_1 }; /* (-z^3 + 1)*u^6 + (-z^4 - 4*z^3 + 2*z^2 + 3)*u^5 + (-2*z^5 - 2*z^4 - 4*z^3 + 2*z^2 - 3*z + 3)*u^4 + (-z^6 - 2*z^5 - 2*z^4 - 5*z^3 - 3*z^2 - 6*z + 1)*u^3 + (z^7 - z^5 - 2*z^4 - 2*z^3 - z^2 - 3*z)*u^2 + (2*z^5 + 3*z^4 + 3*z^3 + 2*z^2)*u + (z^6 + 2*z^5 + z^4) */ static const long X1_34_r_d_0[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, 0, 0, 1, 2, 1 }; /* z^6 + 2*z^5 + z^4 */ static const long X1_34_r_d_1[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, 2, 3, 3, 2 }; /* 2*z^5 + 3*z^4 + 3*z^3 + 2*z^2 */ static const long X1_34_r_d_2[10] = { evaltyp(t_VECSMALL) | _evallg(10), vZ, 0, -3, -1, -2, -2, -1, 0, 1 }; /* z^7 - z^5 - 2*z^4 - 2*z^3 - z^2 - 3*z */ static const long X1_34_r_d_3[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 1, -6, -3, -5, -2, -2, -1 }; /* -z^6 - 2*z^5 - 2*z^4 - 5*z^3 - 3*z^2 - 6*z + 1 */ static const long X1_34_r_d_4[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 3, -3, 2, -4, -2, -2 }; /* -2*z^5 - 2*z^4 - 4*z^3 + 2*z^2 - 3*z + 3 */ static const long X1_34_r_d_5[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 3, 0, 2, -4, -1 }; /* -z^4 - 4*z^3 + 2*z^2 + 3 */ static const long X1_34_r_d_6[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 1, 0, 0, -1 }; /* -z^3 + 1 */ static const long *X1_34_r_d[9] = { (long *)(evaltyp(t_POL) | _evallg(9)), (long *)(evalvarn(0) | evalsigne(1)), X1_34_r_d_0, X1_34_r_d_1, X1_34_r_d_2, X1_34_r_d_3, X1_34_r_d_4, X1_34_r_d_5, X1_34_r_d_6 }; /* -u^7 + (z^2 + 3*z - 3)*u^6 + (z^3 - 2*z^2 + 5*z - 3)*u^5 + (3*z^4 + 10*z^3 - 4*z^2 + z - 1)*u^4 + (-2*z^5 + 2*z^4 + 14*z^3 - 2*z)*u^3 + (z^6 + z^4 + 6*z^3 + z^2 - z)*u^2 + (z^4 + z^3)*u + (z^5 + 2*z^4 + z^3) */ static const long X1_34_s_n_0[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, 0, 1, 2, 1 }; /* z^5 + 2*z^4 + z^3 */ static const long X1_34_s_n_1[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 0, 0, 1, 1 }; /* z^4 + z^3 */ static const long X1_34_s_n_2[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, -1, 1, 6, 1, 0, 1 }; /* z^6 + z^4 + 6*z^3 + z^2 - z */ static const long X1_34_s_n_3[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, -2, 0, 14, 2, -2 }; /* -2*z^5 + 2*z^4 + 14*z^3 - 2*z */ static const long X1_34_s_n_4[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, -1, 1, -4, 10, 3 }; /* 3*z^4 + 10*z^3 - 4*z^2 + z - 1 */ static const long X1_34_s_n_5[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, -3, 5, -2, 1 }; /* z^3 - 2*z^2 + 5*z - 3 */ static const long X1_34_s_n_6[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, -3, 3, 1 }; /* z^2 + 3*z - 3 */ static const long *X1_34_s_n[10] = { (long *)(evaltyp(t_POL) | _evallg(10)), (long *)(evalvarn(0) | evalsigne(1)), X1_34_s_n_0, X1_34_s_n_1, X1_34_s_n_2, X1_34_s_n_3, X1_34_s_n_4, X1_34_s_n_5, X1_34_s_n_6, FLX_m1 }; /* z*u^6 + (-z^2 + 3*z - 1)*u^5 + (4*z^3 - z^2 + z - 3)*u^4 + (-z^5 + 6*z^3 - z^2 - 2*z - 3)*u^3 + (z^6 + 3*z^3 + z^2 - 1)*u^2 + (2*z^4 + 3*z^3 + 2*z^2 + z)*u + (z^5 + 2*z^4 + z^3) */ static const long X1_34_s_d_0[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, 0, 1, 2, 1 }; /* z^5 + 2*z^4 + z^3 */ static const long X1_34_s_d_1[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 1, 2, 3, 2 }; /* 2*z^4 + 3*z^3 + 2*z^2 + z */ static const long X1_34_s_d_2[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, -1, 0, 1, 3, 0, 0, 1 }; /* z^6 + 3*z^3 + z^2 - 1 */ static const long X1_34_s_d_3[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, -3, -2, -1, 6, 0, -1 }; /* -z^5 + 6*z^3 - z^2 - 2*z - 3 */ static const long X1_34_s_d_4[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, -3, 1, -1, 4 }; /* 4*z^3 - z^2 + z - 3 */ static const long X1_34_s_d_5[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, -1, 3, -1 }; /* -z^2 + 3*z - 1 */ static const long *X1_34_s_d[9] = { (long *)(evaltyp(t_POL) | _evallg(9)), (long *)(evalvarn(0) | evalsigne(1)), X1_34_s_d_0, X1_34_s_d_1, X1_34_s_d_2, X1_34_s_d_3, X1_34_s_d_4, X1_34_s_d_5, FLX_Z }; /* z^3*u^12 + (-z^7 - 8*z^4 - 6*z^3 - z)*u^11 + (7*z^8 + 5*z^7 + 25*z^5 + 44*z^4 + 12*z^3 + 7*z^2 + 5*z)*u^10 + (-18*z^9 - 32*z^8 - 7*z^7 - 34*z^6 - 122*z^5 - 80*z^4 - 27*z^3 - 32*z^2 - 8*z + 1)*u^9 + (-z^11 + 19*z^10 + 72*z^9 + 41*z^8 + 3*z^7 + 141*z^6 + 193*z^5 + 71*z^4 + 75*z^3 + 47*z^2 - 2*z - 3)*u^8 + (4*z^12 + 4*z^11 - 59*z^10 - 79*z^9 + 44*z^8 + 5*z^7 - 178*z^6 - 100*z^5 - 72*z^4 - 99*z^3 - 9*z^2 + 17*z + 3)*u^7 + (-6*z^13 - 32*z^12 - 24*z^11 + 45*z^10 - 43*z^9 - 174*z^8 - 37*z^7 + 35*z^6 - z^5 + 90*z^4 + 34*z^3 - 35*z^2 - 15*z - 1)*u^6 + (4*z^14 + 33*z^13 + 80*z^12 + 42*z^11 + 9*z^10 + 145*z^9 + 183*z^8 + 73*z^7 + 60*z^6 - 27*z^5 - 52*z^4 + 32*z^3 + 27*z^2 + 3*z)*u^5 + (-z^15 - 14*z^14 - 57*z^13 - 72*z^12 - 6*z^10 - 100*z^9 - 84*z^8 - 47*z^7 - 3*z^6 + 50*z^5 - 6*z^4 - 27*z^3 + 2*z)*u^4 + (2*z^15 + 16*z^14 + 36*z^13 + 6*z^12 - 45*z^11 - 13*z^10 + 25*z^9 + 11*z^8 - 7*z^7 - 36*z^6 - 15*z^5 + 19*z^4 - 8*z^2 - z)*u^3 + (-z^15 - 6*z^14 - 3*z^13 + 21*z^12 + 26*z^11 + z^10 - 3*z^9 + 9*z^8 + 20*z^7 + 16*z^6 - 8*z^5 - 7*z^4 + 7*z^3 + 4*z^2)*u^2 + (-3*z^13 - 6*z^12 + z^11 + 7*z^10 + z^9 - 6*z^8 - 7*z^7 + z^6 + 7*z^5 + z^4 - 3*z^3 - z^2)*u + (-z^12 - 3*z^11 - 3*z^10 - z^9 - z^7 - 3*z^6 - 3*z^5 - z^4) */ static const long X1_35_crv_0[15] = { evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, 0, 0, 0, -1, -3, -3, -1, 0, -1, -3, -3, -1 }; /* -z^12 - 3*z^11 - 3*z^10 - z^9 - z^7 - 3*z^6 - 3*z^5 - z^4 */ static const long X1_35_crv_1[16] = { evaltyp(t_VECSMALL) | _evallg(16), vZ, 0, 0, -1, -3, 1, 7, 1, -7, -6, 1, 7, 1, -6, -3 }; /* -3*z^13 - 6*z^12 + z^11 + 7*z^10 + z^9 - 6*z^8 - 7*z^7 + z^6 + 7*z^5 + z^4 - 3*z^3 - z^2 */ static const long X1_35_crv_2[18] = { evaltyp(t_VECSMALL) | _evallg(18), vZ, 0, 0, 4, 7, -7, -8, 16, 20, 9, -3, 1, 26, 21, -3, -6, -1 }; /* -z^15 - 6*z^14 - 3*z^13 + 21*z^12 + 26*z^11 + z^10 - 3*z^9 + 9*z^8 + 20*z^7 + 16*z^6 - 8*z^5 - 7*z^4 + 7*z^3 + 4*z^2 */ static const long X1_35_crv_3[18] = { evaltyp(t_VECSMALL) | _evallg(18), vZ, 0, -1, -8, 0, 19, -15, -36, -7, 11, 25, -13, -45, 6, 36, 16, 2 }; /* 2*z^15 + 16*z^14 + 36*z^13 + 6*z^12 - 45*z^11 - 13*z^10 + 25*z^9 + 11*z^8 - 7*z^7 - 36*z^6 - 15*z^5 + 19*z^4 - 8*z^2 - z */ static const long X1_35_crv_4[18] = { evaltyp(t_VECSMALL) | _evallg(18), vZ, 0, 2, 0, -27, -6, 50, -3, -47, -84, -100, -6, 0, -72, -57, -14, -1 }; /* -z^15 - 14*z^14 - 57*z^13 - 72*z^12 - 6*z^10 - 100*z^9 - 84*z^8 - 47*z^7 - 3*z^6 + 50*z^5 - 6*z^4 - 27*z^3 + 2*z */ static const long X1_35_crv_5[17] = { evaltyp(t_VECSMALL) | _evallg(17), vZ, 0, 3, 27, 32, -52, -27, 60, 73, 183, 145, 9, 42, 80, 33, 4 }; /* 4*z^14 + 33*z^13 + 80*z^12 + 42*z^11 + 9*z^10 + 145*z^9 + 183*z^8 + 73*z^7 + 60*z^6 - 27*z^5 - 52*z^4 + 32*z^3 + 27*z^2 + 3*z */ static const long X1_35_crv_6[16] = { evaltyp(t_VECSMALL) | _evallg(16), vZ, -1, -15, -35, 34, 90, -1, 35, -37, -174, -43, 45, -24, -32, -6 }; /* -6*z^13 - 32*z^12 - 24*z^11 + 45*z^10 - 43*z^9 - 174*z^8 - 37*z^7 + 35*z^6 - z^5 + 90*z^4 + 34*z^3 - 35*z^2 - 15*z - 1 */ static const long X1_35_crv_7[15] = { evaltyp(t_VECSMALL) | _evallg(15), vZ, 3, 17, -9, -99, -72, -100, -178, 5, 44, -79, -59, 4, 4 }; /* 4*z^12 + 4*z^11 - 59*z^10 - 79*z^9 + 44*z^8 + 5*z^7 - 178*z^6 - 100*z^5 - 72*z^4 - 99*z^3 - 9*z^2 + 17*z + 3 */ static const long X1_35_crv_8[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, -3, -2, 47, 75, 71, 193, 141, 3, 41, 72, 19, -1 }; /* -z^11 + 19*z^10 + 72*z^9 + 41*z^8 + 3*z^7 + 141*z^6 + 193*z^5 + 71*z^4 + 75*z^3 + 47*z^2 - 2*z - 3 */ static const long X1_35_crv_9[12] = { evaltyp(t_VECSMALL) | _evallg(12), vZ, 1, -8, -32, -27, -80, -122, -34, -7, -32, -18 }; /* -18*z^9 - 32*z^8 - 7*z^7 - 34*z^6 - 122*z^5 - 80*z^4 - 27*z^3 - 32*z^2 - 8*z + 1 */ static const long X1_35_crv_10[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 5, 7, 12, 44, 25, 0, 5, 7 }; /* 7*z^8 + 5*z^7 + 25*z^5 + 44*z^4 + 12*z^3 + 7*z^2 + 5*z */ static const long X1_35_crv_11[10] = { evaltyp(t_VECSMALL) | _evallg(10), vZ, 0, -1, 0, -6, -8, 0, 0, -1 }; /* -z^7 - 8*z^4 - 6*z^3 - z */ static const long X1_35_crv_12[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, 0, 1 }; /* z^3 */ static const long *X1_35_crv[15] = { (long *)(evaltyp(t_POL) | _evallg(15)), (long *)(evalvarn(0) | evalsigne(1)), X1_35_crv_0, X1_35_crv_1, X1_35_crv_2, X1_35_crv_3, X1_35_crv_4, X1_35_crv_5, X1_35_crv_6, X1_35_crv_7, X1_35_crv_8, X1_35_crv_9, X1_35_crv_10, X1_35_crv_11, X1_35_crv_12 }; /* -z^8*u^19 + (11*z^9 + 8*z^8 + 2*z^6)*u^18 + (-51*z^10 - 83*z^9 - 24*z^8 - 20*z^7 - 13*z^6 - z^4)*u^17 + (125*z^11 + 359*z^10 + 234*z^9 + 118*z^8 + 124*z^7 + 30*z^6 + 7*z^5 + 4*z^4)*u^16 + (-156*z^12 - 804*z^11 - 940*z^10 - 498*z^9 - 527*z^8 - 273*z^7 - 46*z^6 - 25*z^5 - 4*z^4 + 2*z^3 + z^2)*u^15 + (35*z^13 + 861*z^12 + 1909*z^11 + 1379*z^10 + 1322*z^9 + 1091*z^8 + 261*z^7 + 70*z^6 + 19*z^5 - 16*z^4 - 15*z^3 - 2*z^2)*u^14 + (174*z^14 + 19*z^13 - 1703*z^12 - 2223*z^11 - 2147*z^10 - 2523*z^9 - 972*z^8 - 162*z^7 - 62*z^6 + 61*z^5 + 79*z^4 + 21*z^3 - 2*z^2 - z - 1)*u^13 + (-232*z^15 - 1155*z^14 - 552*z^13 + 1490*z^12 + 2193*z^11 + 3700*z^10 + 2378*z^9 + 472*z^8 + 272*z^7 - 65*z^6 - 225*z^5 - 88*z^4 + 21*z^3 + 11*z^2 + 11*z + 2)*u^12 + (72*z^16 + 1175*z^15 + 2713*z^14 + 1080*z^13 - 944*z^12 - 3365*z^11 - 3864*z^10 - 1239*z^9 - 855*z^8 - 294*z^7 + 373*z^6 + 253*z^5 - 90*z^4 - 57*z^3 - 46*z^2 - 21*z - 1)*u^11 + (85*z^17 - 152*z^16 - 2096*z^15 - 2809*z^14 - 902*z^13 + 1269*z^12 + 3806*z^11 + 2152*z^10 + 1495*z^9 + 1142*z^8 - 339*z^7 - 614*z^6 + 111*z^5 + 181*z^4 + 84*z^3 + 81*z^2 + 11*z)*u^10 + (-85*z^18 - 520*z^17 - 149*z^16 + 1678*z^15 + 1797*z^14 + 1203*z^13 - 1299*z^12 - 2155*z^11 - 1471*z^10 - 1685*z^9 + 163*z^8 + 1172*z^7 + 249*z^6 - 319*z^5 - 62*z^4 - 132*z^3 - 43*z^2)*u^9 + (19*z^19 + 357*z^18 + 1085*z^17 + 381*z^16 - 1194*z^15 - 2243*z^14 - 1704*z^13 + 870*z^12 + 1000*z^11 + 1263*z^10 - 131*z^9 - 1589*z^8 - 952*z^7 + 278*z^6 + 36*z^5 + 65*z^4 + 75*z^3 - z^2 + 2*z)*u^8 + (7*z^20 - 40*z^19 - 522*z^18 - 898*z^17 + 184*z^16 + 1590*z^15 + 2413*z^14 + 396*z^13 - 950*z^12 - 708*z^11 + 188*z^10 + 1491*z^9 + 1264*z^8 - 100*z^7 - 187*z^6 + 53*z^5 - 73*z^4 + 12*z^3 - 9*z^2 - 2*z)*u^7 + (-3*z^21 - 34*z^20 - 2*z^19 + 314*z^18 + 201*z^17 - 523*z^16 - 1148*z^15 - 515*z^14 + 1090*z^13 + 767*z^12 - 67*z^11 - 980*z^10 - 905*z^9 + 43*z^8 + 463*z^7 - 23*z^6 + 39*z^5 - 27*z^4 + 2*z^3 + 11*z^2)*u^6 + (9*z^21 + 56*z^20 + 40*z^19 - 101*z^18 - 10*z^17 + 100*z^16 + 74*z^15 - 730*z^14 - 802*z^13 - 104*z^12 + 449*z^11 + 429*z^10 - 71*z^9 - 525*z^8 - 125*z^7 + 20*z^6 + 34*z^5 + 32*z^4 - 13*z^3)*u^5 + (-9*z^21 - 37*z^20 + 79*z^18 + 103*z^17 + 86*z^16 + 178*z^15 + 385*z^14 + 109*z^13 - 137*z^12 - 168*z^11 + 29*z^10 + 289*z^9 + 172*z^8 - 57*z^7 - 42*z^6 - 50*z^5 + 4*z^4 - z^3)*u^4 + (3*z^21 + 7*z^20 - 26*z^19 - 43*z^18 - 24*z^17 + 43*z^16 - 13*z^15 - 29*z^14 + 28*z^13 + 49*z^12 + 24*z^11 - 54*z^10 - 82*z^9 + 35*z^8 + 40*z^7 + 31*z^6 - 2*z^5 - 4*z^4 + z^3 - z^2)*u^3 + (z^20 + 9*z^19 - 4*z^18 - 30*z^17 - 44*z^16 - 5*z^15 - 6*z^13 - 25*z^12 - 17*z^11 + 9*z^10 - 5*z^9 - 19*z^8 - 11*z^7 + z^6 + 8*z^5 - z^4)*u^2 + (5*z^18 + 7*z^17 - 8*z^15 - 4*z^14 + 4*z^13 + 6*z^12 - 5*z^11 - 10*z^10 - 4*z^9 - z^8 - z^7 - 5*z^6 - 2*z^5)*u + (z^17 + 2*z^16 + z^15 - z^14 - 2*z^13 + 2*z^11 + z^10 - z^9 - 2*z^8 - z^7) */ static const long X1_35_r_n_0[20] = { evaltyp(t_VECSMALL) | _evallg(20), vZ, 0, 0, 0, 0, 0, 0, 0, -1, -2, -1, 1, 2, 0, -2, -1, 1, 2, 1 }; /* z^17 + 2*z^16 + z^15 - z^14 - 2*z^13 + 2*z^11 + z^10 - z^9 - 2*z^8 - z^7 */ static const long X1_35_r_n_1[21] = { evaltyp(t_VECSMALL) | _evallg(21), vZ, 0, 0, 0, 0, 0, -2, -5, -1, -1, -4, -10, -5, 6, 4, -4, -8, 0, 7, 5 }; /* 5*z^18 + 7*z^17 - 8*z^15 - 4*z^14 + 4*z^13 + 6*z^12 - 5*z^11 - 10*z^10 - 4*z^9 - z^8 - z^7 - 5*z^6 - 2*z^5 */ static const long X1_35_r_n_2[23] = { evaltyp(t_VECSMALL) | _evallg(23), vZ, 0, 0, 0, 0, -1, 8, 1, -11, -19, -5, 9, -17, -25, -6, 0, -5, -44, -30, -4, 9, 1 }; /* z^20 + 9*z^19 - 4*z^18 - 30*z^17 - 44*z^16 - 5*z^15 - 6*z^13 - 25*z^12 - 17*z^11 + 9*z^10 - 5*z^9 - 19*z^8 - 11*z^7 + z^6 + 8*z^5 - z^4 */ static const long X1_35_r_n_3[24] = { evaltyp(t_VECSMALL) | _evallg(24), vZ, 0, 0, -1, 1, -4, -2, 31, 40, 35, -82, -54, 24, 49, 28, -29, -13, 43, -24, -43, -26, 7, 3 }; /* 3*z^21 + 7*z^20 - 26*z^19 - 43*z^18 - 24*z^17 + 43*z^16 - 13*z^15 - 29*z^14 + 28*z^13 + 49*z^12 + 24*z^11 - 54*z^10 - 82*z^9 + 35*z^8 + 40*z^7 + 31*z^6 - 2*z^5 - 4*z^4 + z^3 - z^2 */ static const long X1_35_r_n_4[24] = { evaltyp(t_VECSMALL) | _evallg(24), vZ, 0, 0, 0, -1, 4, -50, -42, -57, 172, 289, 29, -168, -137, 109, 385, 178, 86, 103, 79, 0, -37, -9 }; /* -9*z^21 - 37*z^20 + 79*z^18 + 103*z^17 + 86*z^16 + 178*z^15 + 385*z^14 + 109*z^13 - 137*z^12 - 168*z^11 + 29*z^10 + 289*z^9 + 172*z^8 - 57*z^7 - 42*z^6 - 50*z^5 + 4*z^4 - z^3 */ static const long X1_35_r_n_5[24] = { evaltyp(t_VECSMALL) | _evallg(24), vZ, 0, 0, 0, -13, 32, 34, 20, -125, -525, -71, 429, 449, -104, -802, -730, 74, 100, -10, -101, 40, 56, 9 }; /* 9*z^21 + 56*z^20 + 40*z^19 - 101*z^18 - 10*z^17 + 100*z^16 + 74*z^15 - 730*z^14 - 802*z^13 - 104*z^12 + 449*z^11 + 429*z^10 - 71*z^9 - 525*z^8 - 125*z^7 + 20*z^6 + 34*z^5 + 32*z^4 - 13*z^3 */ static const long X1_35_r_n_6[24] = { evaltyp(t_VECSMALL) | _evallg(24), vZ, 0, 0, 11, 2, -27, 39, -23, 463, 43, -905, -980, -67, 767, 1090, -515, -1148, -523, 201, 314, -2, -34, -3 }; /* -3*z^21 - 34*z^20 - 2*z^19 + 314*z^18 + 201*z^17 - 523*z^16 - 1148*z^15 - 515*z^14 + 1090*z^13 + 767*z^12 - 67*z^11 - 980*z^10 - 905*z^9 + 43*z^8 + 463*z^7 - 23*z^6 + 39*z^5 - 27*z^4 + 2*z^3 + 11*z^2 */ static const long X1_35_r_n_7[23] = { evaltyp(t_VECSMALL) | _evallg(23), vZ, 0, -2, -9, 12, -73, 53, -187, -100, 1264, 1491, 188, -708, -950, 396, 2413, 1590, 184, -898, -522, -40, 7 }; /* 7*z^20 - 40*z^19 - 522*z^18 - 898*z^17 + 184*z^16 + 1590*z^15 + 2413*z^14 + 396*z^13 - 950*z^12 - 708*z^11 + 188*z^10 + 1491*z^9 + 1264*z^8 - 100*z^7 - 187*z^6 + 53*z^5 - 73*z^4 + 12*z^3 - 9*z^2 - 2*z */ static const long X1_35_r_n_8[22] = { evaltyp(t_VECSMALL) | _evallg(22), vZ, 0, 2, -1, 75, 65, 36, 278, -952, -1589, -131, 1263, 1000, 870, -1704, -2243, -1194, 381, 1085, 357, 19 }; /* 19*z^19 + 357*z^18 + 1085*z^17 + 381*z^16 - 1194*z^15 - 2243*z^14 - 1704*z^13 + 870*z^12 + 1000*z^11 + 1263*z^10 - 131*z^9 - 1589*z^8 - 952*z^7 + 278*z^6 + 36*z^5 + 65*z^4 + 75*z^3 - z^2 + 2*z */ static const long X1_35_r_n_9[21] = { evaltyp(t_VECSMALL) | _evallg(21), vZ, 0, 0, -43, -132, -62, -319, 249, 1172, 163, -1685, -1471, -2155, -1299, 1203, 1797, 1678, -149, -520, -85 }; /* -85*z^18 - 520*z^17 - 149*z^16 + 1678*z^15 + 1797*z^14 + 1203*z^13 - 1299*z^12 - 2155*z^11 - 1471*z^10 - 1685*z^9 + 163*z^8 + 1172*z^7 + 249*z^6 - 319*z^5 - 62*z^4 - 132*z^3 - 43*z^2 */ static const long X1_35_r_n_10[20] = { evaltyp(t_VECSMALL) | _evallg(20), vZ, 0, 11, 81, 84, 181, 111, -614, -339, 1142, 1495, 2152, 3806, 1269, -902, -2809, -2096, -152, 85 }; /* 85*z^17 - 152*z^16 - 2096*z^15 - 2809*z^14 - 902*z^13 + 1269*z^12 + 3806*z^11 + 2152*z^10 + 1495*z^9 + 1142*z^8 - 339*z^7 - 614*z^6 + 111*z^5 + 181*z^4 + 84*z^3 + 81*z^2 + 11*z */ static const long X1_35_r_n_11[19] = { evaltyp(t_VECSMALL) | _evallg(19), vZ, -1, -21, -46, -57, -90, 253, 373, -294, -855, -1239, -3864, -3365, -944, 1080, 2713, 1175, 72 }; /* 72*z^16 + 1175*z^15 + 2713*z^14 + 1080*z^13 - 944*z^12 - 3365*z^11 - 3864*z^10 - 1239*z^9 - 855*z^8 - 294*z^7 + 373*z^6 + 253*z^5 - 90*z^4 - 57*z^3 - 46*z^2 - 21*z - 1 */ static const long X1_35_r_n_12[18] = { evaltyp(t_VECSMALL) | _evallg(18), vZ, 2, 11, 11, 21, -88, -225, -65, 272, 472, 2378, 3700, 2193, 1490, -552, -1155, -232 }; /* -232*z^15 - 1155*z^14 - 552*z^13 + 1490*z^12 + 2193*z^11 + 3700*z^10 + 2378*z^9 + 472*z^8 + 272*z^7 - 65*z^6 - 225*z^5 - 88*z^4 + 21*z^3 + 11*z^2 + 11*z + 2 */ static const long X1_35_r_n_13[17] = { evaltyp(t_VECSMALL) | _evallg(17), vZ, -1, -1, -2, 21, 79, 61, -62, -162, -972, -2523, -2147, -2223, -1703, 19, 174 }; /* 174*z^14 + 19*z^13 - 1703*z^12 - 2223*z^11 - 2147*z^10 - 2523*z^9 - 972*z^8 - 162*z^7 - 62*z^6 + 61*z^5 + 79*z^4 + 21*z^3 - 2*z^2 - z - 1 */ static const long X1_35_r_n_14[16] = { evaltyp(t_VECSMALL) | _evallg(16), vZ, 0, 0, -2, -15, -16, 19, 70, 261, 1091, 1322, 1379, 1909, 861, 35 }; /* 35*z^13 + 861*z^12 + 1909*z^11 + 1379*z^10 + 1322*z^9 + 1091*z^8 + 261*z^7 + 70*z^6 + 19*z^5 - 16*z^4 - 15*z^3 - 2*z^2 */ static const long X1_35_r_n_15[15] = { evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, 0, 1, 2, -4, -25, -46, -273, -527, -498, -940, -804, -156 }; /* -156*z^12 - 804*z^11 - 940*z^10 - 498*z^9 - 527*z^8 - 273*z^7 - 46*z^6 - 25*z^5 - 4*z^4 + 2*z^3 + z^2 */ static const long X1_35_r_n_16[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, 0, 4, 7, 30, 124, 118, 234, 359, 125 }; /* 125*z^11 + 359*z^10 + 234*z^9 + 118*z^8 + 124*z^7 + 30*z^6 + 7*z^5 + 4*z^4 */ static const long X1_35_r_n_17[13] = { evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 0, 0, 0, -1, 0, -13, -20, -24, -83, -51 }; /* -51*z^10 - 83*z^9 - 24*z^8 - 20*z^7 - 13*z^6 - z^4 */ static const long X1_35_r_n_18[12] = { evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 0, 0, 0, 0, 0, 2, 0, 8, 11 }; /* 11*z^9 + 8*z^8 + 2*z^6 */ static const long X1_35_r_n_19[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 0, 0, 0, 0, 0, 0, 0, -1 }; /* -z^8 */ static const long *X1_35_r_n[22] = { (long *)(evaltyp(t_POL) | _evallg(22)), (long *)(evalvarn(0) | evalsigne(1)), X1_35_r_n_0, X1_35_r_n_1, X1_35_r_n_2, X1_35_r_n_3, X1_35_r_n_4, X1_35_r_n_5, X1_35_r_n_6, X1_35_r_n_7, X1_35_r_n_8, X1_35_r_n_9, X1_35_r_n_10, X1_35_r_n_11, X1_35_r_n_12, X1_35_r_n_13, X1_35_r_n_14, X1_35_r_n_15, X1_35_r_n_16, X1_35_r_n_17, X1_35_r_n_18, X1_35_r_n_19 }; /* (-z^10 + z^7)*u^16 + (10*z^11 + 5*z^10 - 9*z^8 - 4*z^7 - 2*z^5 - z^4)*u^15 + (-40*z^12 - 47*z^11 - 8*z^10 + 32*z^9 + 35*z^8 + 4*z^7 + 19*z^6 + 17*z^5 + 4*z^4 + z^3 + 2*z^2)*u^14 + (-z^14 + 77*z^13 + 175*z^12 + 71*z^11 - 48*z^10 - 122*z^9 - 33*z^8 - 75*z^7 - 107*z^6 - 48*z^5 - 12*z^4 - 22*z^3 - 6*z^2 - 1)*u^13 + (7*z^15 - 50*z^14 - 307*z^13 - 248*z^12 - 21*z^11 + 193*z^10 + 109*z^9 + 149*z^8 + 348*z^7 + 235*z^6 + 71*z^5 + 95*z^4 + 63*z^3 + 3*z^2 + 9*z + 2)*u^12 + (-19*z^16 - 79*z^15 + 169*z^14 + 406*z^13 + 219*z^12 - 27*z^11 - 153*z^10 - 117*z^9 - 627*z^8 - 612*z^7 - 237*z^6 - 201*z^5 - 257*z^4 - 38*z^3 - 28*z^2 - 20*z - 1)*u^11 + (23*z^17 + 192*z^16 + 271*z^15 - 206*z^14 - 400*z^13 - 436*z^12 - 70*z^11 - 106*z^10 + 512*z^9 + 884*z^8 + 427*z^7 + 180*z^6 + 492*z^5 + 171*z^4 + 21*z^3 + 73*z^2 + 11*z)*u^10 + (-7*z^18 - 142*z^17 - 520*z^16 - 311*z^15 + 307*z^14 + 779*z^13 + 598*z^12 + 382*z^11 + 204*z^10 - 520*z^9 - 317*z^8 + 106*z^7 - 343*z^6 - 348*z^5 + 75*z^4 - 108*z^3 - 45*z^2)*u^9 + (-11*z^19 - 6*z^18 + 271*z^17 + 539*z^16 + 53*z^15 - 548*z^14 - 883*z^13 - 517*z^12 - 885*z^11 - 445*z^10 - 196*z^9 - 456*z^8 - 282*z^7 + 295*z^6 - 201*z^5 + 2*z^4 + 91*z^3 + 2*z)*u^8 + (11*z^20 + 75*z^19 + 84*z^18 - 240*z^17 - 307*z^16 - 33*z^15 + 466*z^14 + 459*z^13 + 840*z^12 + 1094*z^11 + 575*z^10 + 413*z^9 + 589*z^8 + 9*z^7 + 163*z^6 + 191*z^5 - 109*z^4 - z^3 - 10*z^2 - 2*z)*u^7 + (-3*z^21 - 45*z^20 - 158*z^19 - 94*z^18 + 231*z^17 + 363*z^16 + 171*z^15 - 237*z^14 - 385*z^13 - 810*z^12 - 341*z^11 + 132*z^10 - 60*z^9 - 109*z^8 + 43*z^7 - 218*z^6 + 86*z^5 + 11*z^4 + 11*z^3 + 12*z^2)*u^6 + (9*z^21 + 66*z^20 + 128*z^19 - 49*z^18 - 304*z^17 - 367*z^16 - 4*z^15 + 143*z^14 + 189*z^13 - 122*z^12 - 610*z^11 - 532*z^10 - 58*z^9 - 108*z^8 + 91*z^7 - 19*z^6 - 22*z^5 + 19*z^4 - 19*z^3)*u^5 + (-9*z^21 - 40*z^20 - 16*z^19 + 130*z^18 + 208*z^17 + 70*z^16 - 130*z^15 + 7*z^14 + 219*z^13 + 509*z^12 + 451*z^11 + 43*z^10 - 81*z^9 - 62*z^8 - 56*z^7 + 12*z^6 - 48*z^5 + 4*z^4)*u^4 + (3*z^21 + 7*z^20 - 27*z^19 - 58*z^18 - 16*z^17 + 104*z^16 + 68*z^15 - 67*z^14 - 162*z^13 - 115*z^12 + 88*z^11 + 186*z^10 + 80*z^9 + 36*z^8 - 18*z^7 + 18*z^6 + 6*z^5 - 3*z^4 - z^2)*u^3 + (z^20 + 9*z^19 - 4*z^18 - 36*z^17 - 51*z^16 + 2*z^15 + 26*z^14 + 8*z^13 - 60*z^12 - 85*z^11 - 24*z^10 + 28*z^9 + 38*z^8 + 19*z^7 + 4*z^5 - z^4 + z^3)*u^2 + (5*z^18 + 7*z^17 - z^16 - 10*z^15 - 4*z^14 + 9*z^13 + 14*z^12 - 3*z^11 - 19*z^10 - 17*z^9 - 7*z^8 + 3*z^7 + 2*z^6 + 2*z^5 + z^4)*u + (z^17 + 2*z^16 + z^15 - z^14 - 2*z^13 + 2*z^11 + z^10 - z^9 - 2*z^8 - z^7) */ static const long X1_35_r_d_0[20] = { evaltyp(t_VECSMALL) | _evallg(20), vZ, 0, 0, 0, 0, 0, 0, 0, -1, -2, -1, 1, 2, 0, -2, -1, 1, 2, 1 }; /* z^17 + 2*z^16 + z^15 - z^14 - 2*z^13 + 2*z^11 + z^10 - z^9 - 2*z^8 - z^7 */ static const long X1_35_r_d_1[21] = { evaltyp(t_VECSMALL) | _evallg(21), vZ, 0, 0, 0, 0, 1, 2, 2, 3, -7, -17, -19, -3, 14, 9, -4, -10, -1, 7, 5 }; /* 5*z^18 + 7*z^17 - z^16 - 10*z^15 - 4*z^14 + 9*z^13 + 14*z^12 - 3*z^11 - 19*z^10 - 17*z^9 - 7*z^8 + 3*z^7 + 2*z^6 + 2*z^5 + z^4 */ static const long X1_35_r_d_2[23] = { evaltyp(t_VECSMALL) | _evallg(23), vZ, 0, 0, 0, 1, -1, 4, 0, 19, 38, 28, -24, -85, -60, 8, 26, 2, -51, -36, -4, 9, 1 }; /* z^20 + 9*z^19 - 4*z^18 - 36*z^17 - 51*z^16 + 2*z^15 + 26*z^14 + 8*z^13 - 60*z^12 - 85*z^11 - 24*z^10 + 28*z^9 + 38*z^8 + 19*z^7 + 4*z^5 - z^4 + z^3 */ static const long X1_35_r_d_3[24] = { evaltyp(t_VECSMALL) | _evallg(24), vZ, 0, 0, -1, 0, -3, 6, 18, -18, 36, 80, 186, 88, -115, -162, -67, 68, 104, -16, -58, -27, 7, 3 }; /* 3*z^21 + 7*z^20 - 27*z^19 - 58*z^18 - 16*z^17 + 104*z^16 + 68*z^15 - 67*z^14 - 162*z^13 - 115*z^12 + 88*z^11 + 186*z^10 + 80*z^9 + 36*z^8 - 18*z^7 + 18*z^6 + 6*z^5 - 3*z^4 - z^2 */ static const long X1_35_r_d_4[24] = { evaltyp(t_VECSMALL) | _evallg(24), vZ, 0, 0, 0, 0, 4, -48, 12, -56, -62, -81, 43, 451, 509, 219, 7, -130, 70, 208, 130, -16, -40, -9 }; /* -9*z^21 - 40*z^20 - 16*z^19 + 130*z^18 + 208*z^17 + 70*z^16 - 130*z^15 + 7*z^14 + 219*z^13 + 509*z^12 + 451*z^11 + 43*z^10 - 81*z^9 - 62*z^8 - 56*z^7 + 12*z^6 - 48*z^5 + 4*z^4 */ static const long X1_35_r_d_5[24] = { evaltyp(t_VECSMALL) | _evallg(24), vZ, 0, 0, 0, -19, 19, -22, -19, 91, -108, -58, -532, -610, -122, 189, 143, -4, -367, -304, -49, 128, 66, 9 }; /* 9*z^21 + 66*z^20 + 128*z^19 - 49*z^18 - 304*z^17 - 367*z^16 - 4*z^15 + 143*z^14 + 189*z^13 - 122*z^12 - 610*z^11 - 532*z^10 - 58*z^9 - 108*z^8 + 91*z^7 - 19*z^6 - 22*z^5 + 19*z^4 - 19*z^3 */ static const long X1_35_r_d_6[24] = { evaltyp(t_VECSMALL) | _evallg(24), vZ, 0, 0, 12, 11, 11, 86, -218, 43, -109, -60, 132, -341, -810, -385, -237, 171, 363, 231, -94, -158, -45, -3 }; /* -3*z^21 - 45*z^20 - 158*z^19 - 94*z^18 + 231*z^17 + 363*z^16 + 171*z^15 - 237*z^14 - 385*z^13 - 810*z^12 - 341*z^11 + 132*z^10 - 60*z^9 - 109*z^8 + 43*z^7 - 218*z^6 + 86*z^5 + 11*z^4 + 11*z^3 + 12*z^2 */ static const long X1_35_r_d_7[23] = { evaltyp(t_VECSMALL) | _evallg(23), vZ, 0, -2, -10, -1, -109, 191, 163, 9, 589, 413, 575, 1094, 840, 459, 466, -33, -307, -240, 84, 75, 11 }; /* 11*z^20 + 75*z^19 + 84*z^18 - 240*z^17 - 307*z^16 - 33*z^15 + 466*z^14 + 459*z^13 + 840*z^12 + 1094*z^11 + 575*z^10 + 413*z^9 + 589*z^8 + 9*z^7 + 163*z^6 + 191*z^5 - 109*z^4 - z^3 - 10*z^2 - 2*z */ static const long X1_35_r_d_8[22] = { evaltyp(t_VECSMALL) | _evallg(22), vZ, 0, 2, 0, 91, 2, -201, 295, -282, -456, -196, -445, -885, -517, -883, -548, 53, 539, 271, -6, -11 }; /* -11*z^19 - 6*z^18 + 271*z^17 + 539*z^16 + 53*z^15 - 548*z^14 - 883*z^13 - 517*z^12 - 885*z^11 - 445*z^10 - 196*z^9 - 456*z^8 - 282*z^7 + 295*z^6 - 201*z^5 + 2*z^4 + 91*z^3 + 2*z */ static const long X1_35_r_d_9[21] = { evaltyp(t_VECSMALL) | _evallg(21), vZ, 0, 0, -45, -108, 75, -348, -343, 106, -317, -520, 204, 382, 598, 779, 307, -311, -520, -142, -7 }; /* -7*z^18 - 142*z^17 - 520*z^16 - 311*z^15 + 307*z^14 + 779*z^13 + 598*z^12 + 382*z^11 + 204*z^10 - 520*z^9 - 317*z^8 + 106*z^7 - 343*z^6 - 348*z^5 + 75*z^4 - 108*z^3 - 45*z^2 */ static const long X1_35_r_d_10[20] = { evaltyp(t_VECSMALL) | _evallg(20), vZ, 0, 11, 73, 21, 171, 492, 180, 427, 884, 512, -106, -70, -436, -400, -206, 271, 192, 23 }; /* 23*z^17 + 192*z^16 + 271*z^15 - 206*z^14 - 400*z^13 - 436*z^12 - 70*z^11 - 106*z^10 + 512*z^9 + 884*z^8 + 427*z^7 + 180*z^6 + 492*z^5 + 171*z^4 + 21*z^3 + 73*z^2 + 11*z */ static const long X1_35_r_d_11[19] = { evaltyp(t_VECSMALL) | _evallg(19), vZ, -1, -20, -28, -38, -257, -201, -237, -612, -627, -117, -153, -27, 219, 406, 169, -79, -19 }; /* -19*z^16 - 79*z^15 + 169*z^14 + 406*z^13 + 219*z^12 - 27*z^11 - 153*z^10 - 117*z^9 - 627*z^8 - 612*z^7 - 237*z^6 - 201*z^5 - 257*z^4 - 38*z^3 - 28*z^2 - 20*z - 1 */ static const long X1_35_r_d_12[18] = { evaltyp(t_VECSMALL) | _evallg(18), vZ, 2, 9, 3, 63, 95, 71, 235, 348, 149, 109, 193, -21, -248, -307, -50, 7 }; /* 7*z^15 - 50*z^14 - 307*z^13 - 248*z^12 - 21*z^11 + 193*z^10 + 109*z^9 + 149*z^8 + 348*z^7 + 235*z^6 + 71*z^5 + 95*z^4 + 63*z^3 + 3*z^2 + 9*z + 2 */ static const long X1_35_r_d_13[17] = { evaltyp(t_VECSMALL) | _evallg(17), vZ, -1, 0, -6, -22, -12, -48, -107, -75, -33, -122, -48, 71, 175, 77, -1 }; /* -z^14 + 77*z^13 + 175*z^12 + 71*z^11 - 48*z^10 - 122*z^9 - 33*z^8 - 75*z^7 - 107*z^6 - 48*z^5 - 12*z^4 - 22*z^3 - 6*z^2 - 1 */ static const long X1_35_r_d_14[15] = { evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, 0, 2, 1, 4, 17, 19, 4, 35, 32, -8, -47, -40 }; /* -40*z^12 - 47*z^11 - 8*z^10 + 32*z^9 + 35*z^8 + 4*z^7 + 19*z^6 + 17*z^5 + 4*z^4 + z^3 + 2*z^2 */ static const long X1_35_r_d_15[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, 0, -1, -2, 0, -4, -9, 0, 5, 10 }; /* 10*z^11 + 5*z^10 - 9*z^8 - 4*z^7 - 2*z^5 - z^4 */ static const long X1_35_r_d_16[13] = { evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -1 }; /* -z^10 + z^7 */ static const long *X1_35_r_d[19] = { (long *)(evaltyp(t_POL) | _evallg(19)), (long *)(evalvarn(0) | evalsigne(1)), X1_35_r_d_0, X1_35_r_d_1, X1_35_r_d_2, X1_35_r_d_3, X1_35_r_d_4, X1_35_r_d_5, X1_35_r_d_6, X1_35_r_d_7, X1_35_r_d_8, X1_35_r_d_9, X1_35_r_d_10, X1_35_r_d_11, X1_35_r_d_12, X1_35_r_d_13, X1_35_r_d_14, X1_35_r_d_15, X1_35_r_d_16 }; /* z^4*u^10 + (-5*z^5 - 4*z^4 - z^2)*u^9 + (7*z^6 + 18*z^5 + 4*z^4 + 4*z^3 + 2*z^2)*u^8 + (3*z^7 - 22*z^6 - 16*z^5 - 5*z^4 - 6*z^3 + z + 1)*u^7 + (-14*z^8 - 10*z^7 + 17*z^6 + z^5 + 5*z^4 - 3*z^3 - 3*z^2 - 6*z - 1)*u^6 + (7*z^9 + 36*z^8 + 8*z^7 + 2*z^6 - z^5 + 5*z^4 + 3*z^3 + 10*z^2 + 6*z)*u^5 + (4*z^10 - 15*z^9 - 23*z^8 + 2*z^6 + 3*z^5 + z^4 - 3*z^3 - 9*z^2)*u^4 + (-3*z^11 - 9*z^10 + 8*z^9 - 2*z^8 - 4*z^7 - 9*z^6 - 5*z^5 - 6*z^4 + 6*z^3 - z^2)*u^3 + (6*z^11 + 5*z^10 + 3*z^8 + 4*z^7 + 3*z^6 + 5*z^5 - 3*z^4 + z^2 - z)*u^2 + (-3*z^11 + z^10 - z^8 - z^7 - 2*z^6 + z^4 - 2*z^3)*u + (-z^10 - z^5) */ static const long X1_35_s_n_0[13] = { evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1 }; /* -z^10 - z^5 */ static const long X1_35_s_n_1[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, -2, 1, 0, -2, -1, -1, 0, 1, -3 }; /* -3*z^11 + z^10 - z^8 - z^7 - 2*z^6 + z^4 - 2*z^3 */ static const long X1_35_s_n_2[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, -1, 1, 0, -3, 5, 3, 4, 3, 0, 5, 6 }; /* 6*z^11 + 5*z^10 + 3*z^8 + 4*z^7 + 3*z^6 + 5*z^5 - 3*z^4 + z^2 - z */ static const long X1_35_s_n_3[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, -1, 6, -6, -5, -9, -4, -2, 8, -9, -3 }; /* -3*z^11 - 9*z^10 + 8*z^9 - 2*z^8 - 4*z^7 - 9*z^6 - 5*z^5 - 6*z^4 + 6*z^3 - z^2 */ static const long X1_35_s_n_4[13] = { evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 0, -9, -3, 1, 3, 2, 0, -23, -15, 4 }; /* 4*z^10 - 15*z^9 - 23*z^8 + 2*z^6 + 3*z^5 + z^4 - 3*z^3 - 9*z^2 */ static const long X1_35_s_n_5[12] = { evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 6, 10, 3, 5, -1, 2, 8, 36, 7 }; /* 7*z^9 + 36*z^8 + 8*z^7 + 2*z^6 - z^5 + 5*z^4 + 3*z^3 + 10*z^2 + 6*z */ static const long X1_35_s_n_6[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, -1, -6, -3, -3, 5, 1, 17, -10, -14 }; /* -14*z^8 - 10*z^7 + 17*z^6 + z^5 + 5*z^4 - 3*z^3 - 3*z^2 - 6*z - 1 */ static const long X1_35_s_n_7[10] = { evaltyp(t_VECSMALL) | _evallg(10), vZ, 1, 1, 0, -6, -5, -16, -22, 3 }; /* 3*z^7 - 22*z^6 - 16*z^5 - 5*z^4 - 6*z^3 + z + 1 */ static const long X1_35_s_n_8[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, 2, 4, 4, 18, 7 }; /* 7*z^6 + 18*z^5 + 4*z^4 + 4*z^3 + 2*z^2 */ static const long X1_35_s_n_9[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, -1, 0, -4, -5 }; /* -5*z^5 - 4*z^4 - z^2 */ static const long X1_35_s_n_10[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 0, 0, 0, 1 }; /* z^4 */ static const long *X1_35_s_n[13] = { (long *)(evaltyp(t_POL) | _evallg(13)), (long *)(evalvarn(0) | evalsigne(1)), X1_35_s_n_0, X1_35_s_n_1, X1_35_s_n_2, X1_35_s_n_3, X1_35_s_n_4, X1_35_s_n_5, X1_35_s_n_6, X1_35_s_n_7, X1_35_s_n_8, X1_35_s_n_9, X1_35_s_n_10 }; /* z^5*u^9 + (-6*z^6 - 3*z^5 - z^3 - z^2)*u^8 + (13*z^7 + 16*z^6 + 2*z^5 + 5*z^4 + 8*z^3 + 2*z^2 + 1)*u^7 + (-10*z^8 - 31*z^7 - 9*z^6 - 10*z^5 - 22*z^4 - 13*z^3 + z^2 - 5*z - 1)*u^6 + (-3*z^9 + 21*z^8 + 16*z^7 + 10*z^6 + 30*z^5 + 28*z^4 - 3*z^3 + 6*z^2 + 6*z)*u^5 + (8*z^10 + 7*z^9 - 11*z^8 - 5*z^7 - 22*z^6 - 25*z^5 + 5*z^4 + 6*z^3 - 10*z^2)*u^4 + (-3*z^11 - 16*z^10 - 3*z^9 + z^8 + 7*z^7 + 6*z^6 - 8*z^5 - 20*z^4 + 5*z^3)*u^3 + (6*z^11 + 8*z^10 - z^9 + 3*z^7 + 7*z^6 + 16*z^5 + z^4 - 2*z^3 - z)*u^2 + (-3*z^11 + z^10 + z^9 - z^8 - 2*z^7 - 4*z^6 - z^5 + 3*z^4 + z^2)*u + (-z^10 - z^5) */ static const long X1_35_s_d_0[13] = { evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1 }; /* -z^10 - z^5 */ static const long X1_35_s_d_1[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 1, 0, 3, -1, -4, -2, -1, 1, 1, -3 }; /* -3*z^11 + z^10 + z^9 - z^8 - 2*z^7 - 4*z^6 - z^5 + 3*z^4 + z^2 */ static const long X1_35_s_d_2[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, -1, 0, -2, 1, 16, 7, 3, 0, -1, 8, 6 }; /* 6*z^11 + 8*z^10 - z^9 + 3*z^7 + 7*z^6 + 16*z^5 + z^4 - 2*z^3 - z */ static const long X1_35_s_d_3[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, 5, -20, -8, 6, 7, 1, -3, -16, -3 }; /* -3*z^11 - 16*z^10 - 3*z^9 + z^8 + 7*z^7 + 6*z^6 - 8*z^5 - 20*z^4 + 5*z^3 */ static const long X1_35_s_d_4[13] = { evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 0, -10, 6, 5, -25, -22, -5, -11, 7, 8 }; /* 8*z^10 + 7*z^9 - 11*z^8 - 5*z^7 - 22*z^6 - 25*z^5 + 5*z^4 + 6*z^3 - 10*z^2 */ static const long X1_35_s_d_5[12] = { evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 6, 6, -3, 28, 30, 10, 16, 21, -3 }; /* -3*z^9 + 21*z^8 + 16*z^7 + 10*z^6 + 30*z^5 + 28*z^4 - 3*z^3 + 6*z^2 + 6*z */ static const long X1_35_s_d_6[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, -1, -5, 1, -13, -22, -10, -9, -31, -10 }; /* -10*z^8 - 31*z^7 - 9*z^6 - 10*z^5 - 22*z^4 - 13*z^3 + z^2 - 5*z - 1 */ static const long X1_35_s_d_7[10] = { evaltyp(t_VECSMALL) | _evallg(10), vZ, 1, 0, 2, 8, 5, 2, 16, 13 }; /* 13*z^7 + 16*z^6 + 2*z^5 + 5*z^4 + 8*z^3 + 2*z^2 + 1 */ static const long X1_35_s_d_8[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, -1, -1, 0, -3, -6 }; /* -6*z^6 - 3*z^5 - z^3 - z^2 */ static const long X1_35_s_d_9[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 0, 0, 0, 0, 1 }; /* z^5 */ static const long *X1_35_s_d[12] = { (long *)(evaltyp(t_POL) | _evallg(12)), (long *)(evalvarn(0) | evalsigne(1)), X1_35_s_d_0, X1_35_s_d_1, X1_35_s_d_2, X1_35_s_d_3, X1_35_s_d_4, X1_35_s_d_5, X1_35_s_d_6, X1_35_s_d_7, X1_35_s_d_8, X1_35_s_d_9 }; /* (z^7 - 2*z^6 + 2*z^5 - z^4)*u^8 + (4*z^8 - 4*z^7 + 4*z^5 - 4*z^4)*u^7 + (6*z^9 + 2*z^8 - 10*z^7 + 10*z^6 + z^5 - 13*z^4 + 4*z^3 - z^2)*u^6 + (4*z^10 + 10*z^9 - 10*z^8 + 24*z^6 - 36*z^5 + 2*z^4 + 2*z^3 - 2*z^2)*u^5 + (z^11 + 8*z^10 + z^9 - 9*z^8 + 27*z^7 - 9*z^6 - 55*z^5 + 34*z^4 - 13*z^3)*u^4 + (2*z^11 + 4*z^10 - 4*z^9 + 8*z^8 + 26*z^7 - 54*z^6 - 24*z^5 + 50*z^4 - 38*z^3 + 12*z^2 - 2*z)*u^3 + (z^11 + 15*z^8 - 3*z^7 - 43*z^6 + 9*z^5 + 29*z^4 - 39*z^3 + 22*z^2 - 7*z + 1)*u^2 + (2*z^9 + 6*z^8 - 10*z^7 - 14*z^6 + 18*z^5 - 10*z^4 + 2*z^3)*u + (z^9 - 3*z^7 + z^6) */ static const long X1_36_crv_0[12] = { evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 0, 0, 0, 0, 0, 1, -3, 0, 1 }; /* z^9 - 3*z^7 + z^6 */ static const long X1_36_crv_1[12] = { evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 0, 0, 2, -10, 18, -14, -10, 6, 2 }; /* 2*z^9 + 6*z^8 - 10*z^7 - 14*z^6 + 18*z^5 - 10*z^4 + 2*z^3 */ static const long X1_36_crv_2[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 1, -7, 22, -39, 29, 9, -43, -3, 15, 0, 0, 1 }; /* z^11 + 15*z^8 - 3*z^7 - 43*z^6 + 9*z^5 + 29*z^4 - 39*z^3 + 22*z^2 - 7*z + 1 */ static const long X1_36_crv_3[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, -2, 12, -38, 50, -24, -54, 26, 8, -4, 4, 2 }; /* 2*z^11 + 4*z^10 - 4*z^9 + 8*z^8 + 26*z^7 - 54*z^6 - 24*z^5 + 50*z^4 - 38*z^3 + 12*z^2 - 2*z */ static const long X1_36_crv_4[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, -13, 34, -55, -9, 27, -9, 1, 8, 1 }; /* z^11 + 8*z^10 + z^9 - 9*z^8 + 27*z^7 - 9*z^6 - 55*z^5 + 34*z^4 - 13*z^3 */ static const long X1_36_crv_5[13] = { evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 0, -2, 2, 2, -36, 24, 0, -10, 10, 4 }; /* 4*z^10 + 10*z^9 - 10*z^8 + 24*z^6 - 36*z^5 + 2*z^4 + 2*z^3 - 2*z^2 */ static const long X1_36_crv_6[12] = { evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 0, -1, 4, -13, 1, 10, -10, 2, 6 }; /* 6*z^9 + 2*z^8 - 10*z^7 + 10*z^6 + z^5 - 13*z^4 + 4*z^3 - z^2 */ static const long X1_36_crv_7[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, 0, 0, 0, 0, -4, 4, 0, -4, 4 }; /* 4*z^8 - 4*z^7 + 4*z^5 - 4*z^4 */ static const long X1_36_crv_8[10] = { evaltyp(t_VECSMALL) | _evallg(10), vZ, 0, 0, 0, 0, -1, 2, -2, 1 }; /* z^7 - 2*z^6 + 2*z^5 - z^4 */ static const long *X1_36_crv[11] = { (long *)(evaltyp(t_POL) | _evallg(11)), (long *)(evalvarn(0) | evalsigne(1)), X1_36_crv_0, X1_36_crv_1, X1_36_crv_2, X1_36_crv_3, X1_36_crv_4, X1_36_crv_5, X1_36_crv_6, X1_36_crv_7, X1_36_crv_8 }; /* (z^3 - z)*u^4 + (4*z^4 - 4*z^2)*u^3 + (5*z^5 + z^4 - 6*z^3 - z^2 - 1)*u^2 + (2*z^6 + 2*z^5 - 4*z^4 - 2*z^3 - 2*z)*u + (z^6 - z^5 - 2*z^4 + 3*z^3 - 5*z^2 + 3*z - 1) */ static const long X1_36_r_n_0[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, -1, 3, -5, 3, -2, -1, 1 }; /* z^6 - z^5 - 2*z^4 + 3*z^3 - 5*z^2 + 3*z - 1 */ static const long X1_36_r_n_1[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, -2, 0, -2, -4, 2, 2 }; /* 2*z^6 + 2*z^5 - 4*z^4 - 2*z^3 - 2*z */ static const long X1_36_r_n_2[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, -1, 0, -1, -6, 1, 5 }; /* 5*z^5 + z^4 - 6*z^3 - z^2 - 1 */ static const long X1_36_r_n_3[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 0, -4, 0, 4 }; /* 4*z^4 - 4*z^2 */ static const long X1_36_r_n_4[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, -1, 0, 1 }; /* z^3 - z */ static const long *X1_36_r_n[7] = { (long *)(evaltyp(t_POL) | _evallg(7)), (long *)(evalvarn(0) | evalsigne(1)), X1_36_r_n_0, X1_36_r_n_1, X1_36_r_n_2, X1_36_r_n_3, X1_36_r_n_4 }; /* (z^3 - z)*u^4 + (6*z^4 - 2*z^3 - 4*z^2 + z)*u^3 + (7*z^5 + 3*z^4 - 12*z^3 + 3*z^2 + z - 1)*u^2 + (2*z^6 + 5*z^5 - 5*z^4 - 8*z^3 + 9*z^2 - 5*z + 1)*u + (z^6 - 3*z^4 + z^3) */ static const long X1_36_r_d_0[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 0, 0, 1, -3, 0, 1 }; /* z^6 - 3*z^4 + z^3 */ static const long X1_36_r_d_1[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 1, -5, 9, -8, -5, 5, 2 }; /* 2*z^6 + 5*z^5 - 5*z^4 - 8*z^3 + 9*z^2 - 5*z + 1 */ static const long X1_36_r_d_2[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, -1, 1, 3, -12, 3, 7 }; /* 7*z^5 + 3*z^4 - 12*z^3 + 3*z^2 + z - 1 */ static const long X1_36_r_d_3[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 1, -4, -2, 6 }; /* 6*z^4 - 2*z^3 - 4*z^2 + z */ static const long X1_36_r_d_4[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, -1, 0, 1 }; /* z^3 - z */ static const long *X1_36_r_d[7] = { (long *)(evaltyp(t_POL) | _evallg(7)), (long *)(evalvarn(0) | evalsigne(1)), X1_36_r_d_0, X1_36_r_d_1, X1_36_r_d_2, X1_36_r_d_3, X1_36_r_d_4 }; /* (z^3 - z)*u^4 + (2*z^4 + 2*z^3 - 4*z^2 - z)*u^3 + (z^5 + 3*z^4 - 2*z^3 - 6*z^2 - 1)*u^2 + (z^5 + z^4 - 4*z^3 - 5*z^2 + z - 1)*u + (-2*z^3 - 2*z^2 + 2*z - 1) */ static const long X1_36_s_n_0[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, -1, 2, -2, -2 }; /* -2*z^3 - 2*z^2 + 2*z - 1 */ static const long X1_36_s_n_1[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, -1, 1, -5, -4, 1, 1 }; /* z^5 + z^4 - 4*z^3 - 5*z^2 + z - 1 */ static const long X1_36_s_n_2[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, -1, 0, -6, -2, 3, 1 }; /* z^5 + 3*z^4 - 2*z^3 - 6*z^2 - 1 */ static const long X1_36_s_n_3[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, -1, -4, 2, 2 }; /* 2*z^4 + 2*z^3 - 4*z^2 - z */ static const long X1_36_s_n_4[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, -1, 0, 1 }; /* z^3 - z */ static const long *X1_36_s_n[7] = { (long *)(evaltyp(t_POL) | _evallg(7)), (long *)(evalvarn(0) | evalsigne(1)), X1_36_s_n_0, X1_36_s_n_1, X1_36_s_n_2, X1_36_s_n_3, X1_36_s_n_4 }; /* (z^3 - z)*u^4 + (4*z^4 - 4*z^2)*u^3 + (3*z^5 + 5*z^4 - 8*z^3 - 2*z^2 + z - 1)*u^2 + (4*z^5 - 10*z^3 + 4*z^2 - 2*z)*u + (z^5 - z^4 - 4*z^3 + 3*z^2 - z) */ static const long X1_36_s_d_0[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, -1, 3, -4, -1, 1 }; /* z^5 - z^4 - 4*z^3 + 3*z^2 - z */ static const long X1_36_s_d_1[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, -2, 4, -10, 0, 4 }; /* 4*z^5 - 10*z^3 + 4*z^2 - 2*z */ static const long X1_36_s_d_2[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, -1, 1, -2, -8, 5, 3 }; /* 3*z^5 + 5*z^4 - 8*z^3 - 2*z^2 + z - 1 */ static const long X1_36_s_d_3[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 0, 0, -4, 0, 4 }; /* 4*z^4 - 4*z^2 */ static const long X1_36_s_d_4[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, -1, 0, 1 }; /* z^3 - z */ static const long *X1_36_s_d[7] = { (long *)(evaltyp(t_POL) | _evallg(7)), (long *)(evalvarn(0) | evalsigne(1)), X1_36_s_d_0, X1_36_s_d_1, X1_36_s_d_2, X1_36_s_d_3, X1_36_s_d_4 }; /* (z^4 + 4*z^3 + 6*z^2 + 4*z + 1)*x^18 + (4*z^6 + 27*z^5 + 61*z^4 + 53*z^3 + 3*z^2 - 20*z - 8)*x^17 + (6*z^8 + 64*z^7 + 227*z^6 + 318*z^5 + 86*z^4 - 186*z^3 - 123*z^2 + 28*z + 28)*x^16 + (4*z^10 + 70*z^9 + 390*z^8 + 899*z^7 + 697*z^6 - 460*z^5 - 878*z^4 - 71*z^3 + 299*z^2 + 18*z - 56)*x^15 + (z^12 + 36*z^11 + 334*z^10 + 1256*z^9 + 1944*z^8 + 227*z^7 - 2560*z^6 - 1975*z^5 + 530*z^4 + 635*z^3 - 205*z^2 - 65*z + 70)*x^14 + (7*z^13 + 137*z^12 + 885*z^11 + 2414*z^10 + 2085*z^9 - 2931*z^8 - 6951*z^7 - 2982*z^6 + 2372*z^5 + 2034*z^4 + 306*z^3 + 38*z^2 - 50*z - 56)*x^13 + (21*z^14 + 294*z^13 + 1420*z^12 + 2579*z^11 - 870*z^10 - 9749*z^9 - 11481*z^8 + 664*z^7 + 10483*z^6 + 6962*z^5 - 527*z^4 - 2730*z^3 - 733*z^2 + 322*z + 28)*x^12 + (35*z^15 + 363*z^14 + 1210*z^13 + 414*z^12 - 6515*z^11 - 14529*z^10 - 6010*z^9 + 16913*z^8 + 23552*z^7 + 4413*z^6 - 13117*z^5 - 8675*z^4 + 2488*z^3 + 2270*z^2 - 494*z - 8)*x^11 + (26*z^16 + 184*z^15 + 129*z^14 - 2320*z^13 - 8129*z^12 - 7355*z^11 + 12096*z^10 + 31592*z^9 + 16424*z^8 - 20987*z^7 - 29776*z^6 - 1252*z^5 + 14573*z^4 + 1991*z^3 - 3145*z^2 + 412*z + 1)*x^10 + (-z^18 - 5*z^17 - 52*z^16 - 501*z^15 - 2023*z^14 - 2681*z^13 + 4715*z^12 + 19581*z^11 + 18001*z^10 - 14660*z^9 - 40593*z^8 - 16842*z^7 + 25005*z^6 + 20440*z^5 - 8210*z^4 - 5975*z^3 + 2525*z^2 - 210*z)*x^9 + (-z^19 - 10*z^18 - 52*z^17 - 172*z^16 - 162*z^15 + 1311*z^14 + 5622*z^13 + 7317*z^12 - 5435*z^11 - 25859*z^10 - 20839*z^9 + 16281*z^8 + 34475*z^7 + 2999*z^6 - 20366*z^5 - 2065*z^4 + 5725*z^3 - 1264*z^2 + 66*z)*x^8 + (3*z^18 + 32*z^17 + 180*z^16 + 595*z^15 + 789*z^14 - 1585*z^13 - 7639*z^12 - 9008*z^11 + 5183*z^10 + 22272*z^9 + 12561*z^8 - 16256*z^7 - 16253*z^6 + 7183*z^5 + 5741*z^4 - 3053*z^3 + 395*z^2 - 12*z)*x^7 + (-3*z^17 - 39*z^16 - 243*z^15 - 807*z^14 - 1079*z^13 + 1278*z^12 + 6267*z^11 + 6155*z^10 - 4834*z^9 - 13100*z^8 - 1905*z^7 + 9941*z^6 + 1372*z^5 - 3726*z^4 + 978*z^3 - 72*z^2 + z)*x^6 + (z^16 + 22*z^15 + 166*z^14 + 564*z^13 + 678*z^12 - 891*z^11 - 3469*z^10 - 2293*z^9 + 3656*z^8 + 4495*z^7 - 2053*z^6 - 2249*z^5 + 1275*z^4 - 180*z^3 + 6*z^2)*x^5 + (-5*z^14 - 60*z^13 - 210*z^12 - 180*z^11 + 555*z^10 + 1350*z^9 + 185*z^8 - 1655*z^7 - 400*z^6 + 910*z^5 - 240*z^4 + 15*z^3)*x^4 + (10*z^12 + 35*z^11 - 15*z^10 - 265*z^9 - 325*z^8 + 201*z^7 + 321*z^6 - 180*z^5 + 20*z^4)*x^3 + (26*z^9 + 77*z^8 + 30*z^7 - 72*z^6 + 15*z^5)*x^2 + (-z^9 - 7*z^8 - 12*z^7 + 6*z^6)*x + z^7 */ static const long X1_37_crv_0[10] = { evaltyp(t_VECSMALL) | _evallg(10), vZ, 0, 0, 0, 0, 0, 0, 0, 1 }; /* z^7 */ static const long X1_37_crv_1[12] = { evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 0, 0, 0, 0, 0, 6, -12, -7, -1 }; /* -z^9 - 7*z^8 - 12*z^7 + 6*z^6 */ static const long X1_37_crv_2[12] = { evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 0, 0, 0, 0, 15, -72, 30, 77, 26 }; /* 26*z^9 + 77*z^8 + 30*z^7 - 72*z^6 + 15*z^5 */ static const long X1_37_crv_3[15] = { evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, 0, 0, 0, 20, -180, 321, 201, -325, -265, -15, 35, 10 }; /* 10*z^12 + 35*z^11 - 15*z^10 - 265*z^9 - 325*z^8 + 201*z^7 + 321*z^6 - 180*z^5 + 20*z^4 */ static const long X1_37_crv_4[17] = { evaltyp(t_VECSMALL) | _evallg(17), vZ, 0, 0, 0, 15, -240, 910, -400, -1655, 185, 1350, 555, -180, -210, -60, -5 }; /* -5*z^14 - 60*z^13 - 210*z^12 - 180*z^11 + 555*z^10 + 1350*z^9 + 185*z^8 - 1655*z^7 - 400*z^6 + 910*z^5 - 240*z^4 + 15*z^3 */ static const long X1_37_crv_5[19] = { evaltyp(t_VECSMALL) | _evallg(19), vZ, 0, 0, 6, -180, 1275, -2249, -2053, 4495, 3656, -2293, -3469, -891, 678, 564, 166, 22, 1 }; /* z^16 + 22*z^15 + 166*z^14 + 564*z^13 + 678*z^12 - 891*z^11 - 3469*z^10 - 2293*z^9 + 3656*z^8 + 4495*z^7 - 2053*z^6 - 2249*z^5 + 1275*z^4 - 180*z^3 + 6*z^2 */ static const long X1_37_crv_6[20] = { evaltyp(t_VECSMALL) | _evallg(20), vZ, 0, 1, -72, 978, -3726, 1372, 9941, -1905, -13100, -4834, 6155, 6267, 1278, -1079, -807, -243, -39, -3 }; /* -3*z^17 - 39*z^16 - 243*z^15 - 807*z^14 - 1079*z^13 + 1278*z^12 + 6267*z^11 + 6155*z^10 - 4834*z^9 - 13100*z^8 - 1905*z^7 + 9941*z^6 + 1372*z^5 - 3726*z^4 + 978*z^3 - 72*z^2 + z */ static const long X1_37_crv_7[21] = { evaltyp(t_VECSMALL) | _evallg(21), vZ, 0, -12, 395, -3053, 5741, 7183, -16253, -16256, 12561, 22272, 5183, -9008, -7639, -1585, 789, 595, 180, 32, 3 }; /* 3*z^18 + 32*z^17 + 180*z^16 + 595*z^15 + 789*z^14 - 1585*z^13 - 7639*z^12 - 9008*z^11 + 5183*z^10 + 22272*z^9 + 12561*z^8 - 16256*z^7 - 16253*z^6 + 7183*z^5 + 5741*z^4 - 3053*z^3 + 395*z^2 - 12*z */ static const long X1_37_crv_8[22] = { evaltyp(t_VECSMALL) | _evallg(22), vZ, 0, 66, -1264, 5725, -2065, -20366, 2999, 34475, 16281, -20839, -25859, -5435, 7317, 5622, 1311, -162, -172, -52, -10, -1 }; /* -z^19 - 10*z^18 - 52*z^17 - 172*z^16 - 162*z^15 + 1311*z^14 + 5622*z^13 + 7317*z^12 - 5435*z^11 - 25859*z^10 - 20839*z^9 + 16281*z^8 + 34475*z^7 + 2999*z^6 - 20366*z^5 - 2065*z^4 + 5725*z^3 - 1264*z^2 + 66*z */ static const long X1_37_crv_9[21] = { evaltyp(t_VECSMALL) | _evallg(21), vZ, 0, -210, 2525, -5975, -8210, 20440, 25005, -16842, -40593, -14660, 18001, 19581, 4715, -2681, -2023, -501, -52, -5, -1 }; /* -z^18 - 5*z^17 - 52*z^16 - 501*z^15 - 2023*z^14 - 2681*z^13 + 4715*z^12 + 19581*z^11 + 18001*z^10 - 14660*z^9 - 40593*z^8 - 16842*z^7 + 25005*z^6 + 20440*z^5 - 8210*z^4 - 5975*z^3 + 2525*z^2 - 210*z */ static const long X1_37_crv_10[19] = { evaltyp(t_VECSMALL) | _evallg(19), vZ, 1, 412, -3145, 1991, 14573, -1252, -29776, -20987, 16424, 31592, 12096, -7355, -8129, -2320, 129, 184, 26 }; /* 26*z^16 + 184*z^15 + 129*z^14 - 2320*z^13 - 8129*z^12 - 7355*z^11 + 12096*z^10 + 31592*z^9 + 16424*z^8 - 20987*z^7 - 29776*z^6 - 1252*z^5 + 14573*z^4 + 1991*z^3 - 3145*z^2 + 412*z + 1 */ static const long X1_37_crv_11[18] = { evaltyp(t_VECSMALL) | _evallg(18), vZ, -8, -494, 2270, 2488, -8675, -13117, 4413, 23552, 16913, -6010, -14529, -6515, 414, 1210, 363, 35 }; /* 35*z^15 + 363*z^14 + 1210*z^13 + 414*z^12 - 6515*z^11 - 14529*z^10 - 6010*z^9 + 16913*z^8 + 23552*z^7 + 4413*z^6 - 13117*z^5 - 8675*z^4 + 2488*z^3 + 2270*z^2 - 494*z - 8 */ static const long X1_37_crv_12[17] = { evaltyp(t_VECSMALL) | _evallg(17), vZ, 28, 322, -733, -2730, -527, 6962, 10483, 664, -11481, -9749, -870, 2579, 1420, 294, 21 }; /* 21*z^14 + 294*z^13 + 1420*z^12 + 2579*z^11 - 870*z^10 - 9749*z^9 - 11481*z^8 + 664*z^7 + 10483*z^6 + 6962*z^5 - 527*z^4 - 2730*z^3 - 733*z^2 + 322*z + 28 */ static const long X1_37_crv_13[16] = { evaltyp(t_VECSMALL) | _evallg(16), vZ, -56, -50, 38, 306, 2034, 2372, -2982, -6951, -2931, 2085, 2414, 885, 137, 7 }; /* 7*z^13 + 137*z^12 + 885*z^11 + 2414*z^10 + 2085*z^9 - 2931*z^8 - 6951*z^7 - 2982*z^6 + 2372*z^5 + 2034*z^4 + 306*z^3 + 38*z^2 - 50*z - 56 */ static const long X1_37_crv_14[15] = { evaltyp(t_VECSMALL) | _evallg(15), vZ, 70, -65, -205, 635, 530, -1975, -2560, 227, 1944, 1256, 334, 36, 1 }; /* z^12 + 36*z^11 + 334*z^10 + 1256*z^9 + 1944*z^8 + 227*z^7 - 2560*z^6 - 1975*z^5 + 530*z^4 + 635*z^3 - 205*z^2 - 65*z + 70 */ static const long X1_37_crv_15[13] = { evaltyp(t_VECSMALL) | _evallg(13), vZ, -56, 18, 299, -71, -878, -460, 697, 899, 390, 70, 4 }; /* 4*z^10 + 70*z^9 + 390*z^8 + 899*z^7 + 697*z^6 - 460*z^5 - 878*z^4 - 71*z^3 + 299*z^2 + 18*z - 56 */ static const long X1_37_crv_16[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, 28, 28, -123, -186, 86, 318, 227, 64, 6 }; /* 6*z^8 + 64*z^7 + 227*z^6 + 318*z^5 + 86*z^4 - 186*z^3 - 123*z^2 + 28*z + 28 */ static const long X1_37_crv_17[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, -8, -20, 3, 53, 61, 27, 4 }; /* 4*z^6 + 27*z^5 + 61*z^4 + 53*z^3 + 3*z^2 - 20*z - 8 */ static const long X1_37_crv_18[7] = { evaltyp(t_VECSMALL) | _evallg(7), vZ, 1, 4, 6, 4, 1 }; /* z^4 + 4*z^3 + 6*z^2 + 4*z + 1 */ static const long *X1_37_crv[21] = { (long *)(evaltyp(t_POL) | _evallg(21)), (long *)(evalvarn(0) | evalsigne(1)), X1_37_crv_0, X1_37_crv_1, X1_37_crv_2, X1_37_crv_3, X1_37_crv_4, X1_37_crv_5, X1_37_crv_6, X1_37_crv_7, X1_37_crv_8, X1_37_crv_9, X1_37_crv_10, X1_37_crv_11, X1_37_crv_12, X1_37_crv_13, X1_37_crv_14, X1_37_crv_15, X1_37_crv_16, X1_37_crv_17, X1_37_crv_18 }; /* (z^2 + z + 1)*x - 1 */ static const long X1_37_r_n_1[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, 1, 1, 1 }; /* z^2 + z + 1 */ static const long *X1_37_r_n[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), FLX_m1, X1_37_r_n_1 }; /* x + (z^2 + z - 1) */ static const long X1_37_r_d_0[5] = { evaltyp(t_VECSMALL) | _evallg(5), vZ, -1, 1, 1 }; /* z^2 + z - 1 */ static const long *X1_37_r_d[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), X1_37_r_d_0, FLX_1 }; /* (z + 1)*x - 1 */ static const long X1_37_s_n_1[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */ static const long *X1_37_s_n[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), FLX_m1, X1_37_s_n_1 }; /* x + (z - 1) */ static const long X1_37_s_d_0[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, -1, 1 }; /* z - 1 */ static const long *X1_37_s_d[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), X1_37_s_d_0, FLX_1 }; /* z^3*u^12 + (z^6 + 4*z^4 + 10*z^3 - z^2 + z)*u^11 + (4*z^7 + 10*z^6 + 2*z^5 + 39*z^4 + 41*z^3 - 5*z^2 + 7*z - 1)*u^10 + (z^9 + 4*z^8 + 38*z^7 + 32*z^6 + 26*z^5 + 167*z^4 + 88*z^3 - 10*z^2 + 17*z - 6)*u^9 + (4*z^10 + 3*z^9 + 39*z^8 + 141*z^7 + 28*z^6 + 144*z^5 + 396*z^4 + 94*z^3 - 18*z^2 + 12*z - 15)*u^8 + (6*z^11 + 14*z^10 + 173*z^8 + 234*z^7 - 44*z^6 + 421*z^5 + 545*z^4 - 4*z^3 - 50*z^2 - 17*z - 20)*u^7 + (4*z^12 + 25*z^11 - z^10 + 41*z^9 + 368*z^8 + 91*z^7 - 39*z^6 + 691*z^5 + 383*z^4 - 168*z^3 - 91*z^2 - 38*z - 15)*u^6 + (z^13 + 17*z^12 + 30*z^11 - 33*z^10 + 171*z^9 + 326*z^8 - 163*z^7 + 166*z^6 + 594*z^5 + 24*z^4 - 236*z^3 - 82*z^2 - 28*z - 6)*u^5 + (4*z^13 + 26*z^12 + 4*z^11 - 7*z^10 + 202*z^9 + 61*z^8 - 135*z^7 + 249*z^6 + 210*z^5 - 153*z^4 - 146*z^3 - 34*z^2 - 9*z - 1)*u^4 + (6*z^13 + 17*z^12 - 10*z^11 + 27*z^10 + 78*z^9 - 34*z^8 - 10*z^7 + 107*z^6 - 17*z^5 - 90*z^4 - 39*z^3 - 5*z^2 - z)*u^3 + (4*z^13 + 4*z^12 - 3*z^11 + 12*z^10 + 10*z^9 - 9*z^8 + 6*z^7 + 6*z^6 - 25*z^5 - 15*z^4 - 3*z^3)*u^2 + (z^13 + z^10 + z^9 - 3*z^7 - 3*z^6 - 3*z^5)*u - z^7 */ static const long X1_38_crv_0[10] = { evaltyp(t_VECSMALL) | _evallg(10), vZ, 0, 0, 0, 0, 0, 0, 0, -1 }; /* -z^7 */ static const long X1_38_crv_1[16] = { evaltyp(t_VECSMALL) | _evallg(16), vZ, 0, 0, 0, 0, 0, -3, -3, -3, 0, 1, 1, 0, 0, 1 }; /* z^13 + z^10 + z^9 - 3*z^7 - 3*z^6 - 3*z^5 */ static const long X1_38_crv_2[16] = { evaltyp(t_VECSMALL) | _evallg(16), vZ, 0, 0, 0, -3, -15, -25, 6, 6, -9, 10, 12, -3, 4, 4 }; /* 4*z^13 + 4*z^12 - 3*z^11 + 12*z^10 + 10*z^9 - 9*z^8 + 6*z^7 + 6*z^6 - 25*z^5 - 15*z^4 - 3*z^3 */ static const long X1_38_crv_3[16] = { evaltyp(t_VECSMALL) | _evallg(16), vZ, 0, -1, -5, -39, -90, -17, 107, -10, -34, 78, 27, -10, 17, 6 }; /* 6*z^13 + 17*z^12 - 10*z^11 + 27*z^10 + 78*z^9 - 34*z^8 - 10*z^7 + 107*z^6 - 17*z^5 - 90*z^4 - 39*z^3 - 5*z^2 - z */ static const long X1_38_crv_4[16] = { evaltyp(t_VECSMALL) | _evallg(16), vZ, -1, -9, -34, -146, -153, 210, 249, -135, 61, 202, -7, 4, 26, 4 }; /* 4*z^13 + 26*z^12 + 4*z^11 - 7*z^10 + 202*z^9 + 61*z^8 - 135*z^7 + 249*z^6 + 210*z^5 - 153*z^4 - 146*z^3 - 34*z^2 - 9*z - 1 */ static const long X1_38_crv_5[16] = { evaltyp(t_VECSMALL) | _evallg(16), vZ, -6, -28, -82, -236, 24, 594, 166, -163, 326, 171, -33, 30, 17, 1 }; /* z^13 + 17*z^12 + 30*z^11 - 33*z^10 + 171*z^9 + 326*z^8 - 163*z^7 + 166*z^6 + 594*z^5 + 24*z^4 - 236*z^3 - 82*z^2 - 28*z - 6 */ static const long X1_38_crv_6[15] = { evaltyp(t_VECSMALL) | _evallg(15), vZ, -15, -38, -91, -168, 383, 691, -39, 91, 368, 41, -1, 25, 4 }; /* 4*z^12 + 25*z^11 - z^10 + 41*z^9 + 368*z^8 + 91*z^7 - 39*z^6 + 691*z^5 + 383*z^4 - 168*z^3 - 91*z^2 - 38*z - 15 */ static const long X1_38_crv_7[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, -20, -17, -50, -4, 545, 421, -44, 234, 173, 0, 14, 6 }; /* 6*z^11 + 14*z^10 + 173*z^8 + 234*z^7 - 44*z^6 + 421*z^5 + 545*z^4 - 4*z^3 - 50*z^2 - 17*z - 20 */ static const long X1_38_crv_8[13] = { evaltyp(t_VECSMALL) | _evallg(13), vZ, -15, 12, -18, 94, 396, 144, 28, 141, 39, 3, 4 }; /* 4*z^10 + 3*z^9 + 39*z^8 + 141*z^7 + 28*z^6 + 144*z^5 + 396*z^4 + 94*z^3 - 18*z^2 + 12*z - 15 */ static const long X1_38_crv_9[12] = { evaltyp(t_VECSMALL) | _evallg(12), vZ, -6, 17, -10, 88, 167, 26, 32, 38, 4, 1 }; /* z^9 + 4*z^8 + 38*z^7 + 32*z^6 + 26*z^5 + 167*z^4 + 88*z^3 - 10*z^2 + 17*z - 6 */ static const long X1_38_crv_10[10] = { evaltyp(t_VECSMALL) | _evallg(10), vZ, -1, 7, -5, 41, 39, 2, 10, 4 }; /* 4*z^7 + 10*z^6 + 2*z^5 + 39*z^4 + 41*z^3 - 5*z^2 + 7*z - 1 */ static const long X1_38_crv_11[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, 0, 1, -1, 10, 4, 0, 1 }; /* z^6 + 4*z^4 + 10*z^3 - z^2 + z */ static const long X1_38_crv_12[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, 0, 1 }; /* z^3 */ static const long *X1_38_crv[15] = { (long *)(evaltyp(t_POL) | _evallg(15)), (long *)(evalvarn(0) | evalsigne(1)), X1_38_crv_0, X1_38_crv_1, X1_38_crv_2, X1_38_crv_3, X1_38_crv_4, X1_38_crv_5, X1_38_crv_6, X1_38_crv_7, X1_38_crv_8, X1_38_crv_9, X1_38_crv_10, X1_38_crv_11, X1_38_crv_12 }; /* (z^3 - z^2)*u^10 + (z^5 + 4*z^4 + 2*z^3 - 8*z^2 + 2*z)*u^9 + (6*z^6 + 10*z^5 + 14*z^4 - 13*z^3 - 17*z^2 + 9*z - 1)*u^8 + (15*z^7 + 25*z^6 + 22*z^5 + 10*z^4 - 45*z^3 - 11*z^2 + 13*z - 2)*u^7 + (21*z^8 + 46*z^7 + 21*z^6 + 33*z^5 - 20*z^4 - 63*z^3 + 5*z^2 + 12*z - 1)*u^6 + (17*z^9 + 58*z^8 + 14*z^7 + 25*z^6 + 39*z^5 - 67*z^4 - 42*z^3 + 21*z^2 + 10*z)*u^5 + (7*z^10 + 45*z^9 + 24*z^8 - 27*z^7 + 75*z^6 - 9*z^5 - 71*z^4 + 23*z^2 + 4*z)*u^4 + (z^11 + 17*z^10 + 30*z^9 - 32*z^8 + 9*z^7 + 68*z^6 - 49*z^5 - 32*z^4 + 17*z^3 + 8*z^2)*u^3 + (2*z^11 + 12*z^10 - 2*z^9 - 24*z^8 + 33*z^7 + 16*z^6 - 38*z^5 - z^4 + 6*z^3)*u^2 + (z^11 + 2*z^10 - 6*z^9 - z^8 + 13*z^7 - 6*z^6 - 9*z^5 + 2*z^4)*u + (-z^9 + z^8 + z^7 - 2*z^6) */ static const long X1_38_r_n_0[12] = { evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 0, 0, 0, 0, 0, -2, 1, 1, -1 }; /* -z^9 + z^8 + z^7 - 2*z^6 */ static const long X1_38_r_n_1[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, 0, 2, -9, -6, 13, -1, -6, 2, 1 }; /* z^11 + 2*z^10 - 6*z^9 - z^8 + 13*z^7 - 6*z^6 - 9*z^5 + 2*z^4 */ static const long X1_38_r_n_2[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, 6, -1, -38, 16, 33, -24, -2, 12, 2 }; /* 2*z^11 + 12*z^10 - 2*z^9 - 24*z^8 + 33*z^7 + 16*z^6 - 38*z^5 - z^4 + 6*z^3 */ static const long X1_38_r_n_3[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 8, 17, -32, -49, 68, 9, -32, 30, 17, 1 }; /* z^11 + 17*z^10 + 30*z^9 - 32*z^8 + 9*z^7 + 68*z^6 - 49*z^5 - 32*z^4 + 17*z^3 + 8*z^2 */ static const long X1_38_r_n_4[13] = { evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 4, 23, 0, -71, -9, 75, -27, 24, 45, 7 }; /* 7*z^10 + 45*z^9 + 24*z^8 - 27*z^7 + 75*z^6 - 9*z^5 - 71*z^4 + 23*z^2 + 4*z */ static const long X1_38_r_n_5[12] = { evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 10, 21, -42, -67, 39, 25, 14, 58, 17 }; /* 17*z^9 + 58*z^8 + 14*z^7 + 25*z^6 + 39*z^5 - 67*z^4 - 42*z^3 + 21*z^2 + 10*z */ static const long X1_38_r_n_6[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, -1, 12, 5, -63, -20, 33, 21, 46, 21 }; /* 21*z^8 + 46*z^7 + 21*z^6 + 33*z^5 - 20*z^4 - 63*z^3 + 5*z^2 + 12*z - 1 */ static const long X1_38_r_n_7[10] = { evaltyp(t_VECSMALL) | _evallg(10), vZ, -2, 13, -11, -45, 10, 22, 25, 15 }; /* 15*z^7 + 25*z^6 + 22*z^5 + 10*z^4 - 45*z^3 - 11*z^2 + 13*z - 2 */ static const long X1_38_r_n_8[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, -1, 9, -17, -13, 14, 10, 6 }; /* 6*z^6 + 10*z^5 + 14*z^4 - 13*z^3 - 17*z^2 + 9*z - 1 */ static const long X1_38_r_n_9[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 2, -8, 2, 4, 1 }; /* z^5 + 4*z^4 + 2*z^3 - 8*z^2 + 2*z */ static const long X1_38_r_n_10[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, -1, 1 }; /* z^3 - z^2 */ static const long *X1_38_r_n[13] = { (long *)(evaltyp(t_POL) | _evallg(13)), (long *)(evalvarn(0) | evalsigne(1)), X1_38_r_n_0, X1_38_r_n_1, X1_38_r_n_2, X1_38_r_n_3, X1_38_r_n_4, X1_38_r_n_5, X1_38_r_n_6, X1_38_r_n_7, X1_38_r_n_8, X1_38_r_n_9, X1_38_r_n_10 }; /* (z^3 - z^2)*u^10 + (z^5 + 5*z^4 + z^3 - 8*z^2 + 2*z)*u^9 + (7*z^6 + 12*z^5 + 17*z^4 - 20*z^3 - 15*z^2 + 9*z - 1)*u^8 + (19*z^7 + 28*z^6 + 30*z^5 + 10*z^4 - 61*z^3 - 3*z^2 + 13*z - 2)*u^7 + (26*z^8 + 58*z^7 + 19*z^6 + 54*z^5 - 32*z^4 - 82*z^3 + 20*z^2 + 12*z - 1)*u^6 + (19*z^9 + 74*z^8 + 21*z^7 + 16*z^6 + 75*z^5 - 93*z^4 - 53*z^3 + 36*z^2 + 10*z)*u^5 + (7*z^10 + 51*z^9 + 43*z^8 - 41*z^7 + 72*z^6 + 35*z^5 - 106*z^4 - 2*z^3 + 31*z^2 + 4*z)*u^4 + (z^11 + 17*z^10 + 37*z^9 - 26*z^8 - 14*z^7 + 90*z^6 - 33*z^5 - 59*z^4 + 19*z^3 + 10*z^2)*u^3 + (2*z^11 + 12*z^10 + z^9 - 29*z^8 + 31*z^7 + 27*z^6 - 41*z^5 - 10*z^4 + 8*z^3)*u^2 + (z^11 + 2*z^10 - 6*z^9 - 2*z^8 + 14*z^7 - 5*z^6 - 11*z^5 + 2*z^4)*u + (-z^9 + z^8 + z^7 - 2*z^6) */ static const long X1_38_r_d_0[12] = { evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 0, 0, 0, 0, 0, -2, 1, 1, -1 }; /* -z^9 + z^8 + z^7 - 2*z^6 */ static const long X1_38_r_d_1[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, 0, 2, -11, -5, 14, -2, -6, 2, 1 }; /* z^11 + 2*z^10 - 6*z^9 - 2*z^8 + 14*z^7 - 5*z^6 - 11*z^5 + 2*z^4 */ static const long X1_38_r_d_2[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, 8, -10, -41, 27, 31, -29, 1, 12, 2 }; /* 2*z^11 + 12*z^10 + z^9 - 29*z^8 + 31*z^7 + 27*z^6 - 41*z^5 - 10*z^4 + 8*z^3 */ static const long X1_38_r_d_3[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 10, 19, -59, -33, 90, -14, -26, 37, 17, 1 }; /* z^11 + 17*z^10 + 37*z^9 - 26*z^8 - 14*z^7 + 90*z^6 - 33*z^5 - 59*z^4 + 19*z^3 + 10*z^2 */ static const long X1_38_r_d_4[13] = { evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 4, 31, -2, -106, 35, 72, -41, 43, 51, 7 }; /* 7*z^10 + 51*z^9 + 43*z^8 - 41*z^7 + 72*z^6 + 35*z^5 - 106*z^4 - 2*z^3 + 31*z^2 + 4*z */ static const long X1_38_r_d_5[12] = { evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 10, 36, -53, -93, 75, 16, 21, 74, 19 }; /* 19*z^9 + 74*z^8 + 21*z^7 + 16*z^6 + 75*z^5 - 93*z^4 - 53*z^3 + 36*z^2 + 10*z */ static const long X1_38_r_d_6[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, -1, 12, 20, -82, -32, 54, 19, 58, 26 }; /* 26*z^8 + 58*z^7 + 19*z^6 + 54*z^5 - 32*z^4 - 82*z^3 + 20*z^2 + 12*z - 1 */ static const long X1_38_r_d_7[10] = { evaltyp(t_VECSMALL) | _evallg(10), vZ, -2, 13, -3, -61, 10, 30, 28, 19 }; /* 19*z^7 + 28*z^6 + 30*z^5 + 10*z^4 - 61*z^3 - 3*z^2 + 13*z - 2 */ static const long X1_38_r_d_8[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, -1, 9, -15, -20, 17, 12, 7 }; /* 7*z^6 + 12*z^5 + 17*z^4 - 20*z^3 - 15*z^2 + 9*z - 1 */ static const long X1_38_r_d_9[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 2, -8, 1, 5, 1 }; /* z^5 + 5*z^4 + z^3 - 8*z^2 + 2*z */ static const long X1_38_r_d_10[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, -1, 1 }; /* z^3 - z^2 */ static const long *X1_38_r_d[13] = { (long *)(evaltyp(t_POL) | _evallg(13)), (long *)(evalvarn(0) | evalsigne(1)), X1_38_r_d_0, X1_38_r_d_1, X1_38_r_d_2, X1_38_r_d_3, X1_38_r_d_4, X1_38_r_d_5, X1_38_r_d_6, X1_38_r_d_7, X1_38_r_d_8, X1_38_r_d_9, X1_38_r_d_10 }; /* (z^3 - z^2)*u^9 + (z^5 + 3*z^4 + 3*z^3 - 8*z^2 + 2*z)*u^8 + (5*z^6 + 7*z^5 + 12*z^4 - 6*z^3 - 19*z^2 + 9*z - 1)*u^7 + (10*z^7 + 20*z^6 + 11*z^5 + 17*z^4 - 31*z^3 - 19*z^2 + 13*z - 2)*u^6 + (12*z^8 + 31*z^7 + 15*z^6 + 12*z^5 + 8*z^4 - 52*z^3 - 10*z^2 + 12*z - 1)*u^5 + (10*z^9 + 30*z^8 + 9*z^7 + 13*z^6 + 15*z^5 - 22*z^4 - 46*z^3 + 6*z^2 + 10*z)*u^4 + (5*z^10 + 23*z^9 - 2*z^8 - 4*z^7 + 42*z^6 - 27*z^5 - 25*z^4 - 13*z^3 + 15*z^2 + 4*z)*u^3 + (z^11 + 11*z^10 + 4*z^9 - 24*z^8 + 35*z^7 + 2*z^6 - 30*z^5 - 3*z^4 + 7*z^3 + 6*z^2)*u^2 + (2*z^11 + 5*z^10 - 11*z^9 + 4*z^8 + 13*z^7 - 11*z^6 - 8*z^5 + 6*z^4 + 2*z^3)*u + (z^11 - z^10 - z^9 + 2*z^8 + z^7 - 4*z^6 + 2*z^5) */ static const long X1_38_s_n_0[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, 0, 0, 2, -4, 1, 2, -1, -1, 1 }; /* z^11 - z^10 - z^9 + 2*z^8 + z^7 - 4*z^6 + 2*z^5 */ static const long X1_38_s_n_1[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, 2, 6, -8, -11, 13, 4, -11, 5, 2 }; /* 2*z^11 + 5*z^10 - 11*z^9 + 4*z^8 + 13*z^7 - 11*z^6 - 8*z^5 + 6*z^4 + 2*z^3 */ static const long X1_38_s_n_2[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 6, 7, -3, -30, 2, 35, -24, 4, 11, 1 }; /* z^11 + 11*z^10 + 4*z^9 - 24*z^8 + 35*z^7 + 2*z^6 - 30*z^5 - 3*z^4 + 7*z^3 + 6*z^2 */ static const long X1_38_s_n_3[13] = { evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 4, 15, -13, -25, -27, 42, -4, -2, 23, 5 }; /* 5*z^10 + 23*z^9 - 2*z^8 - 4*z^7 + 42*z^6 - 27*z^5 - 25*z^4 - 13*z^3 + 15*z^2 + 4*z */ static const long X1_38_s_n_4[12] = { evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 10, 6, -46, -22, 15, 13, 9, 30, 10 }; /* 10*z^9 + 30*z^8 + 9*z^7 + 13*z^6 + 15*z^5 - 22*z^4 - 46*z^3 + 6*z^2 + 10*z */ static const long X1_38_s_n_5[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, -1, 12, -10, -52, 8, 12, 15, 31, 12 }; /* 12*z^8 + 31*z^7 + 15*z^6 + 12*z^5 + 8*z^4 - 52*z^3 - 10*z^2 + 12*z - 1 */ static const long X1_38_s_n_6[10] = { evaltyp(t_VECSMALL) | _evallg(10), vZ, -2, 13, -19, -31, 17, 11, 20, 10 }; /* 10*z^7 + 20*z^6 + 11*z^5 + 17*z^4 - 31*z^3 - 19*z^2 + 13*z - 2 */ static const long X1_38_s_n_7[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, -1, 9, -19, -6, 12, 7, 5 }; /* 5*z^6 + 7*z^5 + 12*z^4 - 6*z^3 - 19*z^2 + 9*z - 1 */ static const long X1_38_s_n_8[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 2, -8, 3, 3, 1 }; /* z^5 + 3*z^4 + 3*z^3 - 8*z^2 + 2*z */ static const long X1_38_s_n_9[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, -1, 1 }; /* z^3 - z^2 */ static const long *X1_38_s_n[12] = { (long *)(evaltyp(t_POL) | _evallg(12)), (long *)(evalvarn(0) | evalsigne(1)), X1_38_s_n_0, X1_38_s_n_1, X1_38_s_n_2, X1_38_s_n_3, X1_38_s_n_4, X1_38_s_n_5, X1_38_s_n_6, X1_38_s_n_7, X1_38_s_n_8, X1_38_s_n_9 }; /* (z^3 - z^2)*u^9 + (z^5 + 4*z^4 + 2*z^3 - 8*z^2 + 2*z)*u^8 + (6*z^6 + 9*z^5 + 15*z^4 - 13*z^3 - 17*z^2 + 9*z - 1)*u^7 + (14*z^7 + 23*z^6 + 19*z^5 + 17*z^4 - 47*z^3 - 11*z^2 + 13*z - 2)*u^6 + (17*z^8 + 43*z^7 + 13*z^6 + 33*z^5 - 4*z^4 - 71*z^3 + 5*z^2 + 12*z - 1)*u^5 + (12*z^9 + 46*z^8 + 16*z^7 + 4*z^6 + 51*z^5 - 48*z^4 - 57*z^3 + 21*z^2 + 10*z)*u^4 + (5*z^10 + 29*z^9 + 17*z^8 - 18*z^7 + 39*z^6 + 17*z^5 - 60*z^4 - 15*z^3 + 23*z^2 + 4*z)*u^3 + (z^11 + 11*z^10 + 11*z^9 - 18*z^8 + 12*z^7 + 24*z^6 - 14*z^5 - 30*z^4 + 9*z^3 + 8*z^2)*u^2 + (2*z^11 + 5*z^10 - 8*z^9 - z^8 + 11*z^7 - 11*z^5 - 3*z^4 + 4*z^3)*u + (z^11 - z^10 - z^9 + z^8 + 2*z^7 - 3*z^6) */ static const long X1_38_s_d_0[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, 0, 0, 0, -3, 2, 1, -1, -1, 1 }; /* z^11 - z^10 - z^9 + z^8 + 2*z^7 - 3*z^6 */ static const long X1_38_s_d_1[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 0, 4, -3, -11, 0, 11, -1, -8, 5, 2 }; /* 2*z^11 + 5*z^10 - 8*z^9 - z^8 + 11*z^7 - 11*z^5 - 3*z^4 + 4*z^3 */ static const long X1_38_s_d_2[14] = { evaltyp(t_VECSMALL) | _evallg(14), vZ, 0, 0, 8, 9, -30, -14, 24, 12, -18, 11, 11, 1 }; /* z^11 + 11*z^10 + 11*z^9 - 18*z^8 + 12*z^7 + 24*z^6 - 14*z^5 - 30*z^4 + 9*z^3 + 8*z^2 */ static const long X1_38_s_d_3[13] = { evaltyp(t_VECSMALL) | _evallg(13), vZ, 0, 4, 23, -15, -60, 17, 39, -18, 17, 29, 5 }; /* 5*z^10 + 29*z^9 + 17*z^8 - 18*z^7 + 39*z^6 + 17*z^5 - 60*z^4 - 15*z^3 + 23*z^2 + 4*z */ static const long X1_38_s_d_4[12] = { evaltyp(t_VECSMALL) | _evallg(12), vZ, 0, 10, 21, -57, -48, 51, 4, 16, 46, 12 }; /* 12*z^9 + 46*z^8 + 16*z^7 + 4*z^6 + 51*z^5 - 48*z^4 - 57*z^3 + 21*z^2 + 10*z */ static const long X1_38_s_d_5[11] = { evaltyp(t_VECSMALL) | _evallg(11), vZ, -1, 12, 5, -71, -4, 33, 13, 43, 17 }; /* 17*z^8 + 43*z^7 + 13*z^6 + 33*z^5 - 4*z^4 - 71*z^3 + 5*z^2 + 12*z - 1 */ static const long X1_38_s_d_6[10] = { evaltyp(t_VECSMALL) | _evallg(10), vZ, -2, 13, -11, -47, 17, 19, 23, 14 }; /* 14*z^7 + 23*z^6 + 19*z^5 + 17*z^4 - 47*z^3 - 11*z^2 + 13*z - 2 */ static const long X1_38_s_d_7[9] = { evaltyp(t_VECSMALL) | _evallg(9), vZ, -1, 9, -17, -13, 15, 9, 6 }; /* 6*z^6 + 9*z^5 + 15*z^4 - 13*z^3 - 17*z^2 + 9*z - 1 */ static const long X1_38_s_d_8[8] = { evaltyp(t_VECSMALL) | _evallg(8), vZ, 0, 2, -8, 2, 4, 1 }; /* z^5 + 4*z^4 + 2*z^3 - 8*z^2 + 2*z */ static const long X1_38_s_d_9[6] = { evaltyp(t_VECSMALL) | _evallg(6), vZ, 0, 0, -1, 1 }; /* z^3 - z^2 */ static const long *X1_38_s_d[12] = { (long *)(evaltyp(t_POL) | _evallg(12)), (long *)(evalvarn(0) | evalsigne(1)), X1_38_s_d_0, X1_38_s_d_1, X1_38_s_d_2, X1_38_s_d_3, X1_38_s_d_4, X1_38_s_d_5, X1_38_s_d_6, X1_38_s_d_7, X1_38_s_d_8, X1_38_s_d_9 }; /* z^12*x^14 + (-z^23 - 2*z^22 - 4*z^21 - 6*z^20 - 9*z^19 - 12*z^18 - 16*z^17 - 20*z^16 - 25*z^15 - 30*z^14 - 36*z^13 - 12*z^12)*x^13 + (-18*z^23 - 52*z^22 - 100*z^21 - 147*z^20 - 187*z^19 - 208*z^18 - 216*z^17 - 218*z^16 - 248*z^15 - 348*z^14 - 596*z^13 - 650*z^12 - 483*z^11 - 308*z^10 - 188*z^9 - 108*z^8 - 58*z^7 - 28*z^6 - 12*z^5 - 4*z^4 - z^3)*x^12 + (-153*z^23 - 594*z^22 - 1300*z^21 - 2055*z^20 - 2574*z^19 - 2556*z^18 - 1806*z^17 - 261*z^16 + 1845*z^15 + 3786*z^14 + 3780*z^13 + 2178*z^12 + 849*z^11 + 360*z^10 + 266*z^9 + 243*z^8 + 192*z^7 + 124*z^6 + 60*z^5 + 21*z^4 + 3*z^3)*x^11 + (-816*z^23 - 4080*z^22 - 10860*z^21 - 20535*z^20 - 31080*z^19 - 39972*z^18 - 44924*z^17 - 43894*z^16 - 34940*z^15 - 17560*z^14 + 268*z^13 + 8717*z^12 + 7806*z^11 + 3780*z^10 + 720*z^9 - 616*z^8 - 818*z^7 - 544*z^6 - 240*z^5 - 60*z^4 - 6*z^3)*x^10 + (z^28 + 10*z^27 + 60*z^26 + 270*z^25 + 1005*z^24 + 192*z^23 - 9736*z^22 - 38140*z^21 - 87840*z^20 - 151485*z^19 - 216012*z^18 - 269898*z^17 - 306131*z^16 - 316700*z^15 - 284760*z^14 - 207128*z^13 - 114251*z^12 - 43146*z^11 - 5820*z^10 + 6900*z^9 + 7806*z^8 + 5035*z^7 + 2314*z^6 + 720*z^5 + 130*z^4 + 10*z^3)*x^9 + (9*z^28 + 91*z^27 + 540*z^26 + 2400*z^25 + 8890*z^24 + 20526*z^23 + 21288*z^22 - 23112*z^21 - 140013*z^20 - 320022*z^19 - 516680*z^18 - 678672*z^17 - 787386*z^16 - 859748*z^15 - 893172*z^14 - 842244*z^13 - 686088*z^12 - 474318*z^11 - 280656*z^10 - 144524*z^9 - 65124*z^8 - 25122*z^7 - 7784*z^6 - 1740*z^5 - 240*z^4 - 15*z^3)*x^8 + (36*z^28 + 369*z^27 + 2164*z^26 + 9452*z^25 + 34678*z^24 + 96449*z^23 + 188602*z^22 + 245336*z^21 + 166136*z^20 - 94892*z^19 - 461620*z^18 - 768278*z^17 - 883369*z^16 - 829121*z^15 - 743626*z^14 - 706388*z^13 - 669214*z^12 - 565402*z^11 - 404852*z^10 - 245998*z^9 - 129905*z^8 - 61105*z^7 - 25634*z^6 - 9268*z^5 - 2744*z^4 - 637*z^3 - 112*z^2 - 14*z - 1)*x^7 + (84*z^28 + 876*z^27 + 5076*z^26 + 21640*z^25 + 77944*z^24 + 230394*z^23 + 528492*z^22 + 922068*z^21 + 1213200*z^20 + 1162575*z^19 + 693252*z^18 + 6228*z^17 - 521846*z^16 - 626120*z^15 - 375720*z^14 - 68172*z^13 + 79677*z^12 + 72513*z^11 + 20760*z^10 - 6456*z^9 - 7416*z^8 - 1916*z^7 + 496*z^6 + 480*z^5 + 135*z^4 + 15*z^3)*x^6 + (126*z^28 + 1344*z^27 + 7704*z^26 + 31770*z^25 + 110495*z^24 + 332211*z^23 + 826386*z^22 + 1650292*z^21 + 2628990*z^20 + 3341835*z^19 + 3353964*z^18 + 2539962*z^17 + 1236231*z^16 + 55910*z^15 - 540060*z^14 - 540912*z^13 - 271552*z^12 - 44343*z^11 + 39780*z^10 + 34350*z^9 + 11565*z^8 + 333*z^7 - 1366*z^6 - 600*z^5 - 120*z^4 - 10*z^3)*x^5 + (126*z^28 + 1386*z^27 + 7896*z^26 + 31200*z^25 + 101730*z^24 + 297098*z^23 + 765412*z^22 + 1667408*z^21 + 3004995*z^20 + 4469310*z^19 + 5505000*z^18 + 5608136*z^17 + 4657354*z^16 + 3031220*z^15 + 1391660*z^14 + 270580*z^13 - 204565*z^12 - 244602*z^11 - 134160*z^10 - 41460*z^9 - 2842*z^8 + 4030*z^7 + 2216*z^6 + 600*z^5 + 90*z^4 + 6*z^3)*x^4 + (84*z^28 + 966*z^27 + 5544*z^26 + 21000*z^25 + 61860*z^24 + 161856*z^23 + 398596*z^22 + 897424*z^21 + 1758603*z^20 + 2925262*z^19 + 4115740*z^18 + 4919796*z^17 + 5012510*z^16 + 4342211*z^15 + 3166854*z^14 + 1907052*z^13 + 913956*z^12 + 320100*z^11 + 58652*z^10 - 14782*z^9 - 17649*z^8 - 8090*z^7 - 2360*z^6 - 456*z^5 - 54*z^4 - 3*z^3)*x^3 + (36*z^28 + 443*z^27 + 2640*z^26 + 9912*z^25 + 26488*z^24 + 56208*z^23 + 108084*z^22 + 209364*z^21 + 405039*z^20 + 723204*z^19 + 1128252*z^18 + 1513356*z^17 + 1749258*z^16 + 1752384*z^15 + 1525872*z^14 + 1153404*z^13 + 753402*z^12 + 422268*z^11 + 201168*z^10 + 80432*z^9 + 26520*z^8 + 7032*z^7 + 1444*z^6 + 216*z^5 + 21*z^4 + z^3)*x^2 + (9*z^28 + 123*z^27 + 800*z^26 + 3220*z^25 + 8834*z^24 + 17206*z^23 + 23900*z^22 + 22600*z^21 + 11580*z^20 - 2916*z^19 - 12024*z^18 - 12470*z^17 - 7885*z^16 - 3335*z^15 - 930*z^14 - 156*z^13 - 12*z^12)*x + (z^28 + 16*z^27 + 120*z^26 + 560*z^25 + 1820*z^24 + 4368*z^23 + 8008*z^22 + 11440*z^21 + 12870*z^20 + 11440*z^19 + 8008*z^18 + 4368*z^17 + 1820*z^16 + 560*z^15 + 120*z^14 + 16*z^13 + z^12) */ static const long X1_39_crv_0[31] = { evaltyp(t_VECSMALL) | _evallg(31), vZ, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 16, 120, 560, 1820, 4368, 8008, 11440, 12870, 11440, 8008, 4368, 1820, 560, 120, 16, 1 }; /* z^28 + 16*z^27 + 120*z^26 + 560*z^25 + 1820*z^24 + 4368*z^23 + 8008*z^22 + 11440*z^21 + 12870*z^20 + 11440*z^19 + 8008*z^18 + 4368*z^17 + 1820*z^16 + 560*z^15 + 120*z^14 + 16*z^13 + z^12 */ static const long X1_39_crv_1[31] = { evaltyp(t_VECSMALL) | _evallg(31), vZ, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -12, -156, -930, -3335, -7885, -12470, -12024, -2916, 11580, 22600, 23900, 17206, 8834, 3220, 800, 123, 9 }; /* 9*z^28 + 123*z^27 + 800*z^26 + 3220*z^25 + 8834*z^24 + 17206*z^23 + 23900*z^22 + 22600*z^21 + 11580*z^20 - 2916*z^19 - 12024*z^18 - 12470*z^17 - 7885*z^16 - 3335*z^15 - 930*z^14 - 156*z^13 - 12*z^12 */ static const long X1_39_crv_2[31] = { evaltyp(t_VECSMALL) | _evallg(31), vZ, 0, 0, 0, 1, 21, 216, 1444, 7032, 26520, 80432, 201168, 422268, 753402, 1153404, 1525872, 1752384, 1749258, 1513356, 1128252, 723204, 405039, 209364, 108084, 56208, 26488, 9912, 2640, 443, 36 }; /* 36*z^28 + 443*z^27 + 2640*z^26 + 9912*z^25 + 26488*z^24 + 56208*z^23 + 108084*z^22 + 209364*z^21 + 405039*z^20 + 723204*z^19 + 1128252*z^18 + 1513356*z^17 + 1749258*z^16 + 1752384*z^15 + 1525872*z^14 + 1153404*z^13 + 753402*z^12 + 422268*z^11 + 201168*z^10 + 80432*z^9 + 26520*z^8 + 7032*z^7 + 1444*z^6 + 216*z^5 + 21*z^4 + z^3 */ static const long X1_39_crv_3[31] = { evaltyp(t_VECSMALL) | _evallg(31), vZ, 0, 0, 0, -3, -54, -456, -2360, -8090, -17649, -14782, 58652, 320100, 913956, 1907052, 3166854, 4342211, 5012510, 4919796, 4115740, 2925262, 1758603, 897424, 398596, 161856, 61860, 21000, 5544, 966, 84 }; /* 84*z^28 + 966*z^27 + 5544*z^26 + 21000*z^25 + 61860*z^24 + 161856*z^23 + 398596*z^22 + 897424*z^21 + 1758603*z^20 + 2925262*z^19 + 4115740*z^18 + 4919796*z^17 + 5012510*z^16 + 4342211*z^15 + 3166854*z^14 + 1907052*z^13 + 913956*z^12 + 320100*z^11 + 58652*z^10 - 14782*z^9 - 17649*z^8 - 8090*z^7 - 2360*z^6 - 456*z^5 - 54*z^4 - 3*z^3 */ static const long X1_39_crv_4[31] = { evaltyp(t_VECSMALL) | _evallg(31), vZ, 0, 0, 0, 6, 90, 600, 2216, 4030, -2842, -41460, -134160, -244602, -204565, 270580, 1391660, 3031220, 4657354, 5608136, 5505000, 4469310, 3004995, 1667408, 765412, 297098, 101730, 31200, 7896, 1386, 126 }; /* 126*z^28 + 1386*z^27 + 7896*z^26 + 31200*z^25 + 101730*z^24 + 297098*z^23 + 765412*z^22 + 1667408*z^21 + 3004995*z^20 + 4469310*z^19 + 5505000*z^18 + 5608136*z^17 + 4657354*z^16 + 3031220*z^15 + 1391660*z^14 + 270580*z^13 - 204565*z^12 - 244602*z^11 - 134160*z^10 - 41460*z^9 - 2842*z^8 + 4030*z^7 + 2216*z^6 + 600*z^5 + 90*z^4 + 6*z^3 */ static const long X1_39_crv_5[31] = { evaltyp(t_VECSMALL) | _evallg(31), vZ, 0, 0, 0, -10, -120, -600, -1366, 333, 11565, 34350, 39780, -44343, -271552, -540912, -540060, 55910, 1236231, 2539962, 3353964, 3341835, 2628990, 1650292, 826386, 332211, 110495, 31770, 7704, 1344, 126 }; /* 126*z^28 + 1344*z^27 + 7704*z^26 + 31770*z^25 + 110495*z^24 + 332211*z^23 + 826386*z^22 + 1650292*z^21 + 2628990*z^20 + 3341835*z^19 + 3353964*z^18 + 2539962*z^17 + 1236231*z^16 + 55910*z^15 - 540060*z^14 - 540912*z^13 - 271552*z^12 - 44343*z^11 + 39780*z^10 + 34350*z^9 + 11565*z^8 + 333*z^7 - 1366*z^6 - 600*z^5 - 120*z^4 - 10*z^3 */ static const long X1_39_crv_6[31] = { evaltyp(t_VECSMALL) | _evallg(31), vZ, 0, 0, 0, 15, 135, 480, 496, -1916, -7416, -6456, 20760, 72513, 79677, -68172, -375720, -626120, -521846, 6228, 693252, 1162575, 1213200, 922068, 528492, 230394, 77944, 21640, 5076, 876, 84 }; /* 84*z^28 + 876*z^27 + 5076*z^26 + 21640*z^25 + 77944*z^24 + 230394*z^23 + 528492*z^22 + 922068*z^21 + 1213200*z^20 + 1162575*z^19 + 693252*z^18 + 6228*z^17 - 521846*z^16 - 626120*z^15 - 375720*z^14 - 68172*z^13 + 79677*z^12 + 72513*z^11 + 20760*z^10 - 6456*z^9 - 7416*z^8 - 1916*z^7 + 496*z^6 + 480*z^5 + 135*z^4 + 15*z^3 */ static const long X1_39_crv_7[31] = { evaltyp(t_VECSMALL) | _evallg(31), vZ, -1, -14, -112, -637, -2744, -9268, -25634, -61105, -129905, -245998, -404852, -565402, -669214, -706388, -743626, -829121, -883369, -768278, -461620, -94892, 166136, 245336, 188602, 96449, 34678, 9452, 2164, 369, 36 }; /* 36*z^28 + 369*z^27 + 2164*z^26 + 9452*z^25 + 34678*z^24 + 96449*z^23 + 188602*z^22 + 245336*z^21 + 166136*z^20 - 94892*z^19 - 461620*z^18 - 768278*z^17 - 883369*z^16 - 829121*z^15 - 743626*z^14 - 706388*z^13 - 669214*z^12 - 565402*z^11 - 404852*z^10 - 245998*z^9 - 129905*z^8 - 61105*z^7 - 25634*z^6 - 9268*z^5 - 2744*z^4 - 637*z^3 - 112*z^2 - 14*z - 1 */ static const long X1_39_crv_8[31] = { evaltyp(t_VECSMALL) | _evallg(31), vZ, 0, 0, 0, -15, -240, -1740, -7784, -25122, -65124, -144524, -280656, -474318, -686088, -842244, -893172, -859748, -787386, -678672, -516680, -320022, -140013, -23112, 21288, 20526, 8890, 2400, 540, 91, 9 }; /* 9*z^28 + 91*z^27 + 540*z^26 + 2400*z^25 + 8890*z^24 + 20526*z^23 + 21288*z^22 - 23112*z^21 - 140013*z^20 - 320022*z^19 - 516680*z^18 - 678672*z^17 - 787386*z^16 - 859748*z^15 - 893172*z^14 - 842244*z^13 - 686088*z^12 - 474318*z^11 - 280656*z^10 - 144524*z^9 - 65124*z^8 - 25122*z^7 - 7784*z^6 - 1740*z^5 - 240*z^4 - 15*z^3 */ static const long X1_39_crv_9[31] = { evaltyp(t_VECSMALL) | _evallg(31), vZ, 0, 0, 0, 10, 130, 720, 2314, 5035, 7806, 6900, -5820, -43146, -114251, -207128, -284760, -316700, -306131, -269898, -216012, -151485, -87840, -38140, -9736, 192, 1005, 270, 60, 10, 1 }; /* z^28 + 10*z^27 + 60*z^26 + 270*z^25 + 1005*z^24 + 192*z^23 - 9736*z^22 - 38140*z^21 - 87840*z^20 - 151485*z^19 - 216012*z^18 - 269898*z^17 - 306131*z^16 - 316700*z^15 - 284760*z^14 - 207128*z^13 - 114251*z^12 - 43146*z^11 - 5820*z^10 + 6900*z^9 + 7806*z^8 + 5035*z^7 + 2314*z^6 + 720*z^5 + 130*z^4 + 10*z^3 */ static const long X1_39_crv_10[26] = { evaltyp(t_VECSMALL) | _evallg(26), vZ, 0, 0, 0, -6, -60, -240, -544, -818, -616, 720, 3780, 7806, 8717, 268, -17560, -34940, -43894, -44924, -39972, -31080, -20535, -10860, -4080, -816 }; /* -816*z^23 - 4080*z^22 - 10860*z^21 - 20535*z^20 - 31080*z^19 - 39972*z^18 - 44924*z^17 - 43894*z^16 - 34940*z^15 - 17560*z^14 + 268*z^13 + 8717*z^12 + 7806*z^11 + 3780*z^10 + 720*z^9 - 616*z^8 - 818*z^7 - 544*z^6 - 240*z^5 - 60*z^4 - 6*z^3 */ static const long X1_39_crv_11[26] = { evaltyp(t_VECSMALL) | _evallg(26), vZ, 0, 0, 0, 3, 21, 60, 124, 192, 243, 266, 360, 849, 2178, 3780, 3786, 1845, -261, -1806, -2556, -2574, -2055, -1300, -594, -153 }; /* -153*z^23 - 594*z^22 - 1300*z^21 - 2055*z^20 - 2574*z^19 - 2556*z^18 - 1806*z^17 - 261*z^16 + 1845*z^15 + 3786*z^14 + 3780*z^13 + 2178*z^12 + 849*z^11 + 360*z^10 + 266*z^9 + 243*z^8 + 192*z^7 + 124*z^6 + 60*z^5 + 21*z^4 + 3*z^3 */ static const long X1_39_crv_12[26] = { evaltyp(t_VECSMALL) | _evallg(26), vZ, 0, 0, 0, -1, -4, -12, -28, -58, -108, -188, -308, -483, -650, -596, -348, -248, -218, -216, -208, -187, -147, -100, -52, -18 }; /* -18*z^23 - 52*z^22 - 100*z^21 - 147*z^20 - 187*z^19 - 208*z^18 - 216*z^17 - 218*z^16 - 248*z^15 - 348*z^14 - 596*z^13 - 650*z^12 - 483*z^11 - 308*z^10 - 188*z^9 - 108*z^8 - 58*z^7 - 28*z^6 - 12*z^5 - 4*z^4 - z^3 */ static const long X1_39_crv_13[26] = { evaltyp(t_VECSMALL) | _evallg(26), vZ, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -12, -36, -30, -25, -20, -16, -12, -9, -6, -4, -2, -1 }; /* -z^23 - 2*z^22 - 4*z^21 - 6*z^20 - 9*z^19 - 12*z^18 - 16*z^17 - 20*z^16 - 25*z^15 - 30*z^14 - 36*z^13 - 12*z^12 */ static const long X1_39_crv_14[15] = { evaltyp(t_VECSMALL) | _evallg(15), vZ, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; /* z^12 */ static const long *X1_39_crv[17] = { (long *)(evaltyp(t_POL) | _evallg(17)), (long *)(evalvarn(0) | evalsigne(1)), X1_39_crv_0, X1_39_crv_1, X1_39_crv_2, X1_39_crv_3, X1_39_crv_4, X1_39_crv_5, X1_39_crv_6, X1_39_crv_7, X1_39_crv_8, X1_39_crv_9, X1_39_crv_10, X1_39_crv_11, X1_39_crv_12, X1_39_crv_13, X1_39_crv_14 }; /* -z */ static const long *X1_39_r_n[3] = { (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)), FLX_mZ }; /* 1 */ static const long *X1_39_r_d[3] = { (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)), FLX_1 }; /* (z + 1)*x + (z + 1) */ static const long X1_39_s_n_0[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */ static const long X1_39_s_n_1[4] = { evaltyp(t_VECSMALL) | _evallg(4), vZ, 1, 1 }; /* z + 1 */ static const long *X1_39_s_n[4] = { (long *)(evaltyp(t_POL) | _evallg(4)), (long *)(evalvarn(0) | evalsigne(1)), X1_39_s_n_0, X1_39_s_n_1 }; /* z */ static const long *X1_39_s_d[3] = { (long *)(evaltyp(t_POL) | _evallg(3)), (long *)(evalvarn(0) | evalsigne(1)), FLX_Z }; static const X1_info X1_table[LAST_X1_LEVEL - FIRST_X1_LEVEL + 1] = { { (GEN)X1_13_crv, (GEN)X1_13_r_n, (GEN)X1_13_r_d, 0, (GEN)X1_13_s_n, (GEN)X1_13_s_d, 1, RS_MAP }, { (GEN)X1_14_crv, (GEN)X1_14_r_n, (GEN)X1_14_r_d, 1, (GEN)X1_14_s_n, (GEN)X1_14_s_d, 0, RS_MAP }, { (GEN)X1_15_crv, (GEN)X1_15_r_n, (GEN)X1_15_r_d, 1, (GEN)X1_15_s_n, (GEN)X1_15_s_d, 1, RS_MAP }, { (GEN)X1_16_crv, (GEN)X1_16_r_n, (GEN)X1_16_r_d, 0, (GEN)X1_16_s_n, (GEN)X1_16_s_d, 0, RS_MAP }, { (GEN)X1_17_crv, (GEN)X1_17_r_n, (GEN)X1_17_r_d, 0, (GEN)X1_17_s_n, (GEN)X1_17_s_d, 0, RS_MAP }, { (GEN)X1_18_crv, (GEN)X1_18_r_n, (GEN)X1_18_r_d, 0, (GEN)X1_18_s_n, (GEN)X1_18_s_d, 0, RS_MAP }, { (GEN)X1_19_crv, (GEN)X1_19_r_n, (GEN)X1_19_r_d, 1, (GEN)X1_19_s_n, (GEN)X1_19_s_d, 1, RS_MAP }, { (GEN)X1_20_crv, (GEN)X1_20_r_n, (GEN)X1_20_r_d, 0, (GEN)X1_20_s_n, (GEN)X1_20_s_d, 0, TQ_MAP }, { (GEN)X1_21_crv, (GEN)X1_21_r_n, (GEN)X1_21_r_d, 1, (GEN)X1_21_s_n, (GEN)X1_21_s_d, 1, RS_MAP }, { (GEN)X1_22_crv, (GEN)X1_22_r_n, (GEN)X1_22_r_d, 0, (GEN)X1_22_s_n, (GEN)X1_22_s_d, 0, RS_MAP }, { (GEN)X1_23_crv, (GEN)X1_23_r_n, (GEN)X1_23_r_d, 0, (GEN)X1_23_s_n, (GEN)X1_23_s_d, 0, RS_MAP }, { (GEN)X1_24_crv, (GEN)X1_24_r_n, (GEN)X1_24_r_d, 0, (GEN)X1_24_s_n, (GEN)X1_24_s_d, 0, TQ_MAP }, { (GEN)X1_25_crv, (GEN)X1_25_r_n, (GEN)X1_25_r_d, 0, (GEN)X1_25_s_n, (GEN)X1_25_s_d, 0, RS_MAP }, { (GEN)X1_26_crv, (GEN)X1_26_r_n, (GEN)X1_26_r_d, 0, (GEN)X1_26_s_n, (GEN)X1_26_s_d, 0, RS_MAP }, { (GEN)X1_27_crv, (GEN)X1_27_r_n, (GEN)X1_27_r_d, 0, (GEN)X1_27_s_n, (GEN)X1_27_s_d, 0, RS_MAP }, { (GEN)X1_28_crv, (GEN)X1_28_r_n, (GEN)X1_28_r_d, 0, (GEN)X1_28_s_n, (GEN)X1_28_s_d, 0, QT_MAP }, { (GEN)X1_29_crv, (GEN)X1_29_r_n, (GEN)X1_29_r_d, 0, (GEN)X1_29_s_n, (GEN)X1_29_s_d, 1, RS_MAP }, { (GEN)X1_30_crv, (GEN)X1_30_r_n, (GEN)X1_30_r_d, 0, (GEN)X1_30_s_n, (GEN)X1_30_s_d, 0, TQ_MAP }, { (GEN)X1_31_crv, (GEN)X1_31_r_n, (GEN)X1_31_r_d, 0, (GEN)X1_31_s_n, (GEN)X1_31_s_d, 0, RS_MAP }, { (GEN)X1_32_crv, (GEN)X1_32_r_n, (GEN)X1_32_r_d, 0, (GEN)X1_32_s_n, (GEN)X1_32_s_d, 0, QT_MAP }, { (GEN)X1_33_crv, (GEN)X1_33_r_n, (GEN)X1_33_r_d, 0, (GEN)X1_33_s_n, (GEN)X1_33_s_d, 0, T_MAP}, { (GEN)X1_34_crv, (GEN)X1_34_r_n, (GEN)X1_34_r_d, 0, (GEN)X1_34_s_n, (GEN)X1_34_s_d, 0, RS_MAP }, { (GEN)X1_35_crv, (GEN)X1_35_r_n, (GEN)X1_35_r_d, 0, (GEN)X1_35_s_n, (GEN)X1_35_s_d, 0, RS_MAP }, { (GEN)X1_36_crv, (GEN)X1_36_r_n, (GEN)X1_36_r_d, 0, (GEN)X1_36_s_n, (GEN)X1_36_s_d, 0, RS_MAP }, { (GEN)X1_37_crv, (GEN)X1_37_r_n, (GEN)X1_37_r_d, 0, (GEN)X1_37_s_n, (GEN)X1_37_s_d, 0, RS_MAP }, { (GEN)X1_38_crv, (GEN)X1_38_r_n, (GEN)X1_38_r_d, 0, (GEN)X1_38_s_n, (GEN)X1_38_s_d, 0, RS_MAP }, { (GEN)X1_39_crv, (GEN)X1_39_r_n, (GEN)X1_39_r_d, 0, (GEN)X1_39_s_n, (GEN)X1_39_s_d, 0, T_MAP } }; INLINE const X1_info * get_X1_info(ulong N) { return &X1_table[N - FIRST_X1_LEVEL]; } pari-2.17.2/src/basemath/buch1.c0000644000175000017500000007623314760123736014731 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_quadclassunit /*******************************************************************/ /* */ /* 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 (absequalii(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 (absequalii(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 (absequalii(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; for (i=1; i<=n; i++) { x = qfr5_rho(x,S); if (gc_needed(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->q): 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 qfbcomp_i(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= 2 is necessary. */ ulong bnf_increase_LIMC(ulong LIMC, ulong D) { if (LIMC >= D) pari_err_BUG("Buchmann's algorithm"); if (LIMC <= D / 13.333) LIMC *= 2; /* tiny c <= 0.3 : double it */ else LIMC += maxuu(1, D / 20); /* large c, add 0.2 to it */ if (LIMC > D) LIMC = D; return LIMC; } /* Is |q| <= p ? */ static int isless_iu(GEN q, ulong p) { long l = lgefint(q); return l==2 || (l == 3 && uel(q,2) <= p); } static GEN Z_isquasismooth_prod(GEN N, GEN P) { P = gcdii(P,N); while (!is_pm1(P)) { N = diviiexact(N, P); P = gcdii(N, P); } return N; } static long factorquad(struct buch_quad *B, GEN f, long nFB, ulong limp) { ulong X; long i, lo = 0; GEN F, x = gel(f,1), FB = B->FB, P = B->primfact, E = B->exprimfact; if (B->badprim && !is_pm1(gcdii(x, B->badprim))) return 0; F = Z_isquasismooth_prod(x, B->prodFB); if (cmpiu(F, B->limhash) > 0) return 0; for (i=1; lgefint(x) > 3; i++) { ulong p = uel(FB,i), r; GEN q = absdiviu_rem(x, p, &r); if (!r) { long k = 0; do { k++; x = q; q = absdiviu_rem(x, p, &r); } while (!r); lo++; P[lo] = p; E[lo] = k; } if (isless_iu(q,p)) { if (lgefint(x) == 3) { X = uel(x,2); goto END; } return 0; } if (i == nFB) return 0; } X = uel(x,2); if (X == 1) { P[0] = 0; return 1; } for (;; i++) { /* single precision affair, split for efficiency */ ulong p = uel(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) { lo++; P[lo] = X; E[lo] = 1; X = 1; } P[0] = lo; return X; } /* Check for a "large prime relation" involving q; q may not be prime */ static long * largeprime(struct buch_quad *B, long q, GEN ex, long np, long nrho) { const long hashv = hash(q); long *pt, i, l = lg(B->subFB); for (pt = B->hashtab[hashv]; ; pt = (long*) pt[0]) { if (!pt) { pt = (long*) pari_malloc((l+3) * sizeof(long)); *pt++ = nrho; /* nrho = pt[-3] */ *pt++ = np; /* np = pt[-2] */ *pt++ = q; /* q = pt[-1] */ pt[0] = (long)B->hashtab[hashv]; for (i=1; ihashtab[hashv]=pt; return NULL; } if (pt[-1] == q) break; } for(i=1; iprimes + S->nprimes-1)->p; } /* ensure that S->primes can hold at least nb primes */ void GRH_ensure(GRHcheck_t *S, long nb) { if (S->maxprimes <= nb) { do S->maxprimes *= 2; while (S->maxprimes <= nb); pari_realloc_ip((void**)&S->primes, S->maxprimes*sizeof(*S->primes)); } } /* cache data for all primes up to the LIM */ static void cache_prime_quad(GRHcheck_t *S, ulong LIM, GEN D) { GRHprime_t *pr; long nb; if (S->limp >= LIM) return; nb = (long)primepi_upper_bound((double)LIM); /* #{p <= LIM} <= nb */ GRH_ensure(S, nb+1); /* room for one extra prime */ for (pr = S->primes + S->nprimes;;) { ulong p = u_forprime_next(&(S->P)); pr->p = p; pr->logp = log((double)p); pr->dec = (GEN)kroiu(D,p); S->nprimes++; pr++; /* store up to nextprime(LIM) included */ if (p >= LIM) { S->limp = p; break; } } } static GEN compute_invresquad(GRHcheck_t *S, long LIMC) { pari_sp av = avma; GEN invres = real_1(DEFAULTPREC); double limp = log((double)LIMC) / 2; GRHprime_t *pr; long i; for (pr = S->primes, i = S->nprimes; i > 0; pr++, i--) { long s = (long)pr->dec; if (s) { ulong p = pr->p; if (s > 0 || pr->logp <= limp) /* Both p and P contribute */ invres = mulur(p - s, divru(invres, p)); else if (s<0) /* Only p contributes */ invres = mulur(p, divru(invres, p - 1)); } } return gerepileuptoleaf(av, invres); } /* p | conductor of order of disc D ? */ static int is_bad(GEN D, ulong p) { pari_sp av = avma; if (p == 2) { long r = mod16(D) >> 1; if (r && signe(D) < 0) r = 8-r; return (r < 4); } return gc_bool(av, dvdii(D, sqru(p))); /* p^2 | D ? */ } /* returns the n-th suitable ideal for the factorbase */ static long nthidealquad(GEN D, long n) { pari_sp av = avma; forprime_t S; ulong p; (void)u_forprime_init(&S, 2, ULONG_MAX); while ((p = u_forprime_next(&S)) && n > 0) if (!is_bad(D, p) && kroiu(D, p) >= 0) n--; return gc_long(av, p); } static int quadGRHchk(GEN D, GRHcheck_t *S, ulong LIMC) { double logC = log((double)LIMC), SA = 0, SB = 0; long i; cache_prime_quad(S, LIMC, D); for (i = 0;; i++) { GRHprime_t *pr = S->primes+i; ulong p = pr->p; long M; double logNP, q, A, B; if (p > LIMC) break; if ((long)pr->dec < 0) { logNP = 2 * pr->logp; q = 1/(double)p; } else { logNP = pr->logp; q = 1/sqrt((double)p); } A = logNP * q; B = logNP * A; M = (long)(logC/logNP); if (M > 1) { double inv1_q = 1 / (1-q); A *= (1 - pow(q, (double) M)) * inv1_q; B *= (1 - pow(q, (double) M)*(M+1 - M*q)) * inv1_q * inv1_q; } if ((long)pr->dec>0) { SA += 2*A;SB += 2*B; } else { SA += A; SB += B; } if (p == LIMC) break; } return GRHok(S, logC, SA, SB); } /* C2 >= C1; create B->FB, B->numFB; set B->badprim. Return L(kro_D, 1) */ static void FBquad(struct buch_quad *B, ulong C2, ulong C1, GRHcheck_t *S) { GEN D = B->q->D; long i; pari_sp av; GRHprime_t *pr; cache_prime_quad(S, C2, D); pr = S->primes; B->numFB = cgetg(C2+1, t_VECSMALL); B->FB = cgetg(C2+1, t_VECSMALL); av = avma; B->KC = 0; i = 0; B->badprim = gen_1; for (;; pr++) /* p <= C2 */ { ulong p = pr->p; if (!B->KC && p > C1) B->KC = i; if (p > C2) break; switch ((long)pr->dec) { case -1: break; /* inert */ case 0: /* ramified */ if (is_bad(D, p)) { B->badprim = muliu(B->badprim, p); break; } /* fall through */ default: /* split */ i++; B->numFB[p] = i; B->FB[i] = p; break; } if (p == C2) { if (!B->KC) B->KC = i; break; } } B->KC2 = i; setlg(B->FB, B->KC2+1); if (B->badprim != gen_1) B->badprim = gerepileuptoint(av, B->badprim); else { B->badprim = NULL; set_avma(av); } B->prodFB = zv_prod_Z(B->FB); } /* create B->vperm, return B->subFB */ static GEN subFBquad(struct buch_quad *B, GEN D, double PROD, long minSFB) { long i, j, lgsub = 1, ino = 1, lv = B->KC+1; double prod = 1.; pari_sp av; GEN no; B->vperm = cgetg(lv, t_VECSMALL); av = avma; no = cgetg(lv, t_VECSMALL); for (j = 1; j < lv; j++) { ulong p = uel(B->FB,j); if (!umodiu(D, p)) no[ino++] = j; /* ramified */ else { B->vperm[lgsub++] = j; prod *= p; if (lgsub > minSFB && prod > PROD) break; } } /* lgsub >= 1 otherwise quadGRHchk is false */ i = lgsub; for (j = 1; j < ino;i++,j++) B->vperm[i] = no[j]; for ( ; i < lv; i++) B->vperm[i] = i; no = gclone(vecslice(B->vperm, 1, lgsub-1)); set_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->q->D; if (B->PRECREG) /* real */ { for (i=1; iq, 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->q); } } 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) = qfbcomp_i(gel(y,j-1), F); } } x = gclone(x); set_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) { GEN res, init, u1, D = ZM_snf_group(W,NULL,&u1); long i, j, l = lg(W), c = lg(D); res=cgetg(c,t_VEC); init = cgetg(l,t_VEC); for (i=1; iq->D, B->FB[B->vperm[i]]); for (j=1; jq->D) > 0) { for (i=1; iq); g = g? qfr3_comp(g, t, B->q): t; } g = qfr3_to_qfr(qfr3_canon_safe(qfr3_red(g, B->q), B->q), B->q->D); } else { for (i=1; iq->D; for (i = 1; i <= B->KC; i++) { /* ramified prime ==> trivial relation */ if (umodiu(D, B->FB[i])) continue; col = zero_zv(B->KC); col[i] = 2; j++; gel(mat,j) = col; gel(C,j) = gen_0; } return j; } static void dbg_all(pari_timer *T, const char *phase, long s, long n) { err_printf("\n"); timer_printf(T, "%s rel [#rel/#test = %ld/%ld]", phase,s,n); } /* Imaginary Quadratic fields */ static void imag_relations(struct buch_quad *B, long need, long *pc, ulong LIMC, GEN mat) { pari_timer T; long lgsub = lg(B->subFB), current = *pc, nbtest = 0, s = 0; long i, fpc; pari_sp av; GEN col, form, ex = cgetg(lgsub, t_VECSMALL); if (!current) current = 1; if (DEBUGLEVEL>2) timer_start(&T); av = avma; for(;;) { if (s >= need) break; set_avma(av); form = qfi_random(B,ex); form = qfbcomp_i(form, qfi_pf(B->q->D, B->FB[current])); nbtest++; fpc = factorquad(B,form,B->KC,LIMC); if (!fpc) { if (DEBUGLEVEL>3) 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>3) err_printf("."); continue; } form2 = qfbcomp_i(qfi_factorback(B,fpd), qfi_pf(B->q->D, B->FB[fpd[-2]])); p = fpc << 1; b1 = umodiu(gel(form2,2), p); b2 = umodiu(gel(form,2), p); if (b1 != b2 && b1+b2 != p) continue; col = gel(mat,++s); add_fact(B,col, form); (void)factorquad(B,form2,B->KC,LIMC); if (b1==b2) { for (i=1; isubFB[i]] += fpd[i]-ex[i]; sub_fact(B, col, form2); col[fpd[-2]]++; } else { for (i=1; isubFB[i]] += -fpd[i]-ex[i]; add_fact(B, col, form2); col[fpd[-2]]--; } if (DEBUGLEVEL>2) err_printf(" %ldP",s); } else { col = gel(mat,++s); for (i=1; isubFB[i]] = -ex[i]; add_fact(B, col, form); if (DEBUGLEVEL>2) err_printf(" %ld",s); } col[current]--; if (++current > B->KC) current = 1; } if (DEBUGLEVEL>2) 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>2) err_printf(" %ld",p); F = qfbcomp_i(qfi_pf(B->q->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; set_avma(av); } return 1; } static GEN dist(GEN e, GEN d, long prec) { GEN t = qfr5_dist(e, d, prec); return signe(d) < 0 ? mkcomplex(t, gen_1): t; } /* 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; GEN d, col, form, form0, form1, ex = cgetg(lgsub, t_VECSMALL); if (DEBUGLEVEL>2) timer_start(&T); if (!current) current = 1; if (lim > need) lim = need; av = avma; for(;;) { if (s >= need) break; if (first && s >= lim) { first = 0; if (DEBUGLEVEL>2) dbg_all(&T, "initial", s, nbtest); } set_avma(av); form = qfr3_random(B, ex); if (!first) form = QFR3_comp(form, qfr3_pf(B->q, B->FB[current]), B->q); av1 = avma; form0 = form; form1 = NULL; endcycle = rhoacc = 0; rho = -1; CYCLE: if (endcycle || rho > 5000) { if (++current > B->KC) current = 1; continue; } if (gc_needed(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->q); rho++; rhoacc++; if (first) endcycle = (absequalii(gel(form,1),gel(form0,1)) && equalii(gel(form,2),gel(form0,2))); else { if (absequalii(gel(form,1), gel(form,3))) /* a = -c */ { if (absequalii(gel(form,1),gel(form0,1)) && equalii(gel(form,2),gel(form0,2))) continue; form = qfr3_rho(form, B->q); 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>3) 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>3) err_printf("."); goto CYCLE; } if (!form1) { form1 = qfr5_factorback(B,ex); if (!first) form1 = QFR5_comp(form1, qfr5_pf(B->q, B->FB[current], prec), B->q); } form1 = qfr5_rho_pow(form1, rho, B->q); rho = 0; form2 = qfr5_factorback(B,fpd); if (fpd[-2]) form2 = QFR5_comp(form2, qfr5_pf(B->q, B->FB[fpd[-2]], prec), B->q); form2 = qfr5_rho_pow(form2, fpd[-3], B->q); if (!absequalii(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 = 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 = dist(addii(gel(form1,4),gel(form2,4)), mulrr(gel(form1,5),gel(form2,5)), prec); } if (DEBUGLEVEL>2) err_printf(" %ldP",s); } else { /* standard relation */ if (!form1) { form1 = qfr5_factorback(B, ex); if (!first) form1 = QFR5_comp(form1, qfr5_pf(B->q, B->FB[current], prec), B->q); } form1 = qfr5_rho_pow(form1, rho, B->q); rho = 0; col = gel(mat,++s); for (i=1; isubFB[i]] = -ex[i]; add_fact(B, col, form1); d = dist(gel(form1,4), gel(form1,5), prec); if (DEBUGLEVEL>2) err_printf(" %ld",s); } gaffect(d, gel(C,s)); if (first) { if (s >= lim) continue; goto CYCLE; } else { col[current]--; if (++current > B->KC) current = 1; } } if (DEBUGLEVEL>2) 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>2) err_printf(" %ld",p); F = QFR3_comp(qfr3_random(B, ex), qfr3_pf(B->q, p), B->q); 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->q), B->q); if (equalii(gel(F,1),gel(F0,1)) && equalii(gel(F,2),gel(F0,2))) break; } set_avma(av); } return 1; } static GEN crabs(GEN a) { return signe(real_i(a)) < 0 ? gneg(a): a; } static GEN gcdreal(GEN a,GEN b) { if (!signe(real_i(a))) return crabs(b); if (!signe(real_i(b))) return crabs(a); if (expo(real_i(a))<-5) return crabs(b); if (expo(real_i(b))<-5) return crabs(a); a = crabs(a); b = crabs(b); while (expo(real_i(b)) >= -5 && signe(real_i(b))) { long e; GEN r, q = gcvtoi(divrr(real_i(a),real_i(b)),&e); if (e > 0) return NULL; r = gsub(a, gmul(q,b)); a = b; b = r; } return crabs(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 = crabs(gel(C,1)); for (i=2; i<=sreg; i++) { R = gcdreal(gel(C,i), R); if (!R) return fupb_PRECI; } if (gexpo(real_i(R)) <= -3) { if (DEBUGLEVEL>2) err_printf("regulator is zero.\n"); return fupb_RELAT; } if (DEBUGLEVEL>2) err_printf("#### Tentative regulator: %Ps\n",R); } c = gtodouble(gmul(z, real_i(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>2) err_printf("be honest for primes from %ld to %ld\n", B->FB[B->KC+1],B->FB[B->KC2]); r = B->PRECREG? real_be_honest(B): imag_be_honest(B); if (DEBUGLEVEL>2) err_printf("\n"); return r; } static GEN Buchquad_i(GEN D, double cbach, double cbach2, long prec) { const long MAXRELSUP = 7, SFB_MAX = 3; pari_timer T; pari_sp av, av2; const long RELSUP = 5; long i, s, current, triv, sfb_trials, nrelsup, nreldep, need, nsubFB, minSFB; ulong low, high, LIMC0, LIMC, LIMC2, LIMCMAX, cp; GEN W, cyc, gen, dep, mat, C, extraC, B, R, invhr, h = NULL; /*-Wall*/ double drc, sdrc, lim, LOGD, LOGD2; GRHcheck_t GRHcheck; struct qfr_data q; struct buch_quad BQ; int FIRST = 1; check_quaddisc(D, &s, /*junk*/&i, "Buchquad"); R = NULL; /* -Wall */ BQ.q = &q; q.D = D; if (s < 0) { if (abscmpiu(q.D,4) <= 0) retmkvec4(gen_1, cgetg(1,t_VEC), cgetg(1,t_VEC), gen_1); prec = BQ.PRECREG = 0; } else { BQ.PRECREG = maxss(prec+EXTRAPREC64, nbits2prec(2*expi(q.D) + 128)); } if (DEBUGLEVEL>2) timer_start(&T); BQ.primfact = new_chunk(100); BQ.exprimfact = new_chunk(100); BQ.hashtab = (long**) new_chunk(HASHT); for (i=0; i 6.) { if (cbach2 < cbach) cbach2 = cbach; cbach = 6.; } if (cbach < 0.) pari_err_DOMAIN("Buchquad","Bach constant","<",gen_0,dbltor(cbach)); av = avma; BQ.powsubFB = BQ.subFB = NULL; minSFB = (expi(D) > 15)? 3: 2; init_GRHcheck(&GRHcheck, 2, BQ.PRECREG? 2: 0, LOGD); high = low = LIMC0 = maxss((long)(cbach2*LOGD2), 1); LIMCMAX = (long)(4.*LOGD2); /* 97/1223 below to ensure a good enough approximation of residue */ cache_prime_quad(&GRHcheck, expi(D) < 16 ? 97: 1223, D); while (!quadGRHchk(D, &GRHcheck, high)) { low = high; high *= 2; } while (high - low > 1) { long test = (low+high)/2; if (quadGRHchk(D, &GRHcheck, test)) high = test; else low = test; } if (high == LIMC0+1 && quadGRHchk(D, &GRHcheck, LIMC0)) LIMC2 = LIMC0; else LIMC2 = high; if (LIMC2 > LIMCMAX) LIMC2 = LIMCMAX; LIMC0 = (long)(cbach*LOGD2); LIMC = cbach ? LIMC0 : LIMC2; LIMC = maxss(LIMC, nthidealquad(D, 2)); /* LIMC = Max(cbach*(log D)^2, exp(sqrt(log D loglog D) / 8)) */ START: do { if (!FIRST) LIMC = bnf_increase_LIMC(LIMC,LIMCMAX); if (DEBUGLEVEL>2 && LIMC > LIMC0) err_printf("%s*** Bach constant: %f\n", FIRST?"":"\n", LIMC/LOGD2); FIRST = 0; set_avma(av); guncloneNULL(BQ.subFB); guncloneNULL(BQ.powsubFB); clearhash(BQ.hashtab); if (LIMC < cp) LIMC = cp; if (LIMC2 < LIMC) LIMC2 = LIMC; if (BQ.PRECREG) qfr_data_init(q.D, BQ.PRECREG, &q); FBquad(&BQ, LIMC2, LIMC, &GRHcheck); if (DEBUGLEVEL>2) timer_printf(&T, "factor base"); BQ.subFB = subFBquad(&BQ, q.D, lim + 0.5, minSFB); if (DEBUGLEVEL>2) timer_printf(&T, "subFBquad = %Ps", vecpermute(BQ.FB, BQ.subFB)); nsubFB = lg(BQ.subFB) - 1; } while (nsubFB < (expi(D) > 15 ? 3 : 2)); /* invhr = 2^r1 (2pi)^r2 / sqrt(D) w ~ L(chi,1) / hR */ invhr = gmul(dbltor((BQ.PRECREG?2.:M_PI)/sdrc), compute_invresquad(&GRHcheck, LIMC)); BQ.powsubFB = powsubFBquad(&BQ,CBUCH+1); if (DEBUGLEVEL>2) 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>2) err_printf("*** Changing sub factor base\n"); gunclone(BQ.subFB); gunclone(BQ.powsubFB); BQ.subFB = gclone(vecslice(BQ.vperm, 1, nsubFB)); BQ.powsubFB = powsubFBquad(&BQ,CBUCH+1); if (DEBUGLEVEL>2) 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>2) err_printf("KC = %ld, need %ld relations\n", BQ.KC, need); } else { triv = 0; if (DEBUGLEVEL>2) err_printf("...need %ld more relations\n", need); } if (BQ.PRECREG) { for (i = triv+1; i<=need; i++) { gel(mat,i) = zero_zv(BQ.KC); gel(extraC,i) = mkcomplex(cgetr(BQ.PRECREG), cgeti(3)); } real_relations(&BQ, need - triv, ¤t, s,LIMC,mat + triv,extraC + triv); } else { for (i = triv+1; i<=need; i++) { gel(mat,i) = zero_zv(BQ.KC); gel(extraC,i) = gen_0; } imag_relations(&BQ, need - triv, ¤t, LIMC,mat + triv); } if (!W) W = hnfspec_i(mat,BQ.vperm,&dep,&B,&C,nsubFB); else W = hnfadd_i(W,BQ.vperm,&dep,&B,&C, mat,extraC); gerepileall(av2, 4, &W,&C,&B,&dep); need = BQ.KC - (lg(W)-1) - (lg(B)-1); if (need) { if (++nreldep > 15 && cbach < 1) goto START; continue; } h = ZM_det_triangular(W); if (DEBUGLEVEL>2) err_printf("\n#### Tentative class number: %Ps\n", h); switch(get_R(&BQ, C, (lg(C)-1) - (lg(B)-1) - (lg(W)-1), mulir(h,invhr), &R)) { case fupb_PRECI: BQ.PRECREG = precdbl(BQ.PRECREG); FIRST = 1; goto START; case fupb_RELAT: if (++nrelsup > MAXRELSUP) { if (++sfb_trials > SFB_MAX && cbach <= 1) goto START; if (nsubFB < minss(10,BQ.KC)) nsubFB++; } need = minss(BQ.KC, nrelsup); } } while (need); /* DONE */ if (!quad_be_honest(&BQ)) goto START; if (DEBUGLEVEL>2) timer_printf(&T, "be honest"); clearhash(BQ.hashtab); free_GRHcheck(&GRHcheck); gen = get_clgp(&BQ,W,&cyc); gunclone(BQ.subFB); gunclone(BQ.powsubFB); if (BQ.PRECREG) return mkvec5(h, cyc, gen, real_i(R), mpodd(imag_i(R)) ? gen_m1:gen_1); else return mkvec4(h, cyc, gen, real_i(R)); } GEN Buchquad(GEN D, double c, double c2, long prec) { pari_sp av = avma; GEN z = Buchquad_i(D, c, c2, prec); return gerepilecopy(av, z); } GEN buchimag(GEN D, GEN c, GEN c2, GEN REL) { (void)REL; return Buchquad(D,gtodouble(c),gtodouble(c2),0); } GEN buchreal(GEN D, GEN flag, GEN c, GEN c2, GEN REL, long prec) { if (signe(flag)) pari_err_IMPL("narrow class group"); (void)REL; return Buchquad(D,gtodouble(c),gtodouble(c2),prec); } GEN quadclassunit0(GEN x, long flag, GEN data, long prec) { long lx; double c1 = 0.0, c2 = 0.0; if (!data) lx=1; else { lx = lg(data); if (typ(data)!=t_VEC) pari_err_TYPE("quadclassunit", data); if (lx > 7) pari_err_DIM("quadclassunit [tech vector]"); if (lx > 3) lx = 3; } switch(lx) { case 3: c2 = gtodouble(gel(data,2)); case 2: c1 = gtodouble(gel(data,1)); } if (flag) pari_err_IMPL("narrow class group"); return Buchquad(x,c1,c2,prec); } GEN quadclassno(GEN D) { pari_sp av = avma; GEN h = abgrp_get_no(Buchquad_i(D, 0, 0, 0)); return icopy_avma(h, av); } long quadclassnos(long D) { pari_sp av = avma; long h = itos(abgrp_get_no(Buchquad_i(stoi(D), 0, 0, 0))); return gc_long(av, h); } pari-2.17.2/src/basemath/F2x.c0000644000175000017500000022670514702761220014357 0ustar billbill/* Copyright (C) 2007 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_fflog /* 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_degreespec(GEN x, long l) { return (l==0)?-1:l*BITS_IN_LONG-bfffo(x[l-1])-1; } 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 monomial_F2x(long d, long vs) { long l=nbits2lg(d+1); GEN z = zero_zv(l-1); z[1] = vs; F2x_set(z,d); return z; } GEN F2x_to_ZX(GEN x) { long l = 3+F2x_degree(x), lx = lg(x); GEN z = cgetg(l,t_POL); long i, j ,k; for (i=2, k=2; i=3)|x[1]; return z; } GEN F2x_to_Flx(GEN x) { long l = 3+F2x_degree(x), lx = lg(x); GEN z = cgetg(l,t_VECSMALL); long i, j, k; z[1] = x[1]; for (i=2, k=2; i>j)&1UL; return z; } GEN F2x_to_F2xX(GEN z, long sv) { long i, d = F2x_degree(z); GEN x = cgetg(d+3,t_POL); for (i=0; i<=d; i++) gel(x,i+2) = F2x_coeff(z,i) ? pol1_F2x(sv): pol0_F2x(sv); x[1] = evalsigne(d+1!=0)| z[1]; return x; } GEN Z_to_F2x(GEN x, long sv) { return mpodd(x) ? pol1_F2x(sv): pol0_F2x(sv); } GEN ZX_to_F2x(GEN x) { long lx = lg(x), l = nbits2lg(lx-2); 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; i> 32; #endif c ^= c >> 16; c ^= c >> 8; c ^= c >> 4; c ^= c >> 2; c ^= c >> 1; return c & 1; } else return F2x_coeff(P,0); } GEN F2x_add(GEN x, GEN y) { long i,lz; GEN z; long lx=lg(x); long ly=lg(y); if (ly>lx) swapspec(x,y, lx,ly); lz = lx; z = cgetg(lz, t_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; i>dc; yi = uel(y,i+1); x[i+1] ^= (yi<>dc; yi = uel(y,i+2); x[i+2] ^= (yi<>dc; yi = uel(y,i+3); x[i+3] ^= (yi<>dc; } for( ; i>dc; } if (r) x[i] ^= r; } else { for(i=0; 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; } static GEN F2x_mulspec_basecase(GEN x, GEN y, long nx, long ny) { long l, i, j; GEN z; l = nx + ny; z = zero_Flv(l+1); for(i=0; i < ny-1; i++) { GEN zi = z+2+i; ulong yi = uel(y,i); if (yi) for(j=0; j < BITS_IN_LONG; j++) if (yi&(1UL<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 = F2x_addspec(x,yd,nx,a); lz = (a>nx)? ny+2: lg(x)+d; x += 2; while (xd > x) *--zd = *--xd; } while (yd > y) *--zd = *--yd; *--zd = vs; *--zd = evaltyp(t_VECSMALL) | evallg(lz); return zd; } /* shift polynomial + gerepile */ /* Do not set evalvarn. Cf Flx_shiftip */ static GEN F2x_shiftip(pari_sp av, GEN x, long v) { long i, lx = lg(x), ly; GEN y; if (!v || lx==2) return gerepileuptoleaf(av, x); ly = lx + v; (void)new_chunk(ly); /* check that result fits */ x += lx; y = (GEN)av; for (i = 2; i= BIL) { k++; if (k>=lz) break; zs = int_nextW(zs); *zs = 0; m -= BIL; } *zs |= ((a[i]>>j)&1UL)<= BIL) { if (++k==lx) break; xs = int_nextW(xs); m -= BIL; } if ((*xs>>m)&1UL) z[i]|=1UL<= F2x_MUL_MULII_LIMIT) return F2x_shiftip(av, F2x_mulspec_mulii(a, b, 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 = F2x_mulspec(a,b,n0a,n0b); c0 = F2x_mulspec(a0,b0,na,nb); c2 = F2x_addspec(a0,a,na,n0a); c1 = F2x_addspec(b0,b,nb,n0b); c1 = F2x_mul(c1,c2); c2 = F2x_add(c0,c); c2 = F2x_add(c1,c2); c0 = F2x_addshift(c0,c2,n0); } else { c = F2x_mulspec(a,b,n0a,nb); c0 = F2x_mulspec(a0,b,na,nb); } c0 = F2x_addshift(c0,c,n0); return F2x_shiftip(av,c0, v); } GEN F2x_mul(GEN x, GEN y) { GEN z = F2x_mulspec(x+2,y+2, lgpol(x),lgpol(y)); z[1] = x[1]; return z; } GEN F2x_sqr(GEN x) { const ulong sq[]={0,1,4,5,16,17,20,21,64,65,68,69,80,81,84,85}; long i,ii,j,jj; long lx=lg(x), lz=2+((lx-2)<<1); GEN z; z = cgetg(lz, t_VECSMALL); z[1]=x[1]; for (j=2,jj=2;j>BITS_IN_HALFULONG; ulong x2=(ulong)x[j]&LOWMASK; z[jj]=0; if (x2) for(i=0,ii=0;i>i)&15UL]<>i)&15UL]<>1); GEN z; z = cgetg(lz, t_VECSMALL); z[1]=x[1]; for (j=2,jj=2;jj>i)&15UL, rh = (x2>>(i+4))&15UL; z[jj]|=sq[rl|(rh<<1)]<>i)&15UL, rh = (x2>>(i+4))&15UL; z[jj]|=(sq[rl|(rh<<1)]<=2; i--) { x[i] = (((ulong)y[i+dl])>>db)|r; r = ((ulong)y[i+dl])<>dc; } x[i+dl] = r; } else for(i=2; i>pk); #define F2x_recipu(pk) F2x_recip2(pk,((~0UL)/((1UL<>BITS_IN_HALFULONG); #ifdef LONG_IS_64BIT F2x_recipu(16); #endif F2x_recipu(8); F2x_recipu(4); F2x_recipu(2); F2x_recipu(1); return u; } static GEN F2x_recip_raw(GEN x) { long i, l; GEN y = cgetg_copy(x,&l); y[1] = x[1]; for (i=0; i0); g = cgetg(l, t_VECSMALL); g[1] = f[1]; for (i=2; i>1; v = (u&1UL)|2UL; w = u&v; w ^= w >> 1; v = (w&1UL)|(v<<1); w = u&v; w ^= w >> 2; w ^= w >> 1; v = (w&1UL)|(v<<1); w = u&v; w ^= w >> 2; w ^= w >> 1; v = (w&1UL)|(v<<1); for (i=1;i<=4;i++) { w = u&v; w ^= w >> 4; w ^= w >> 2; w ^= w >> 1; v = (w&1UL)|(v<<1); } for (i=1;i<=8;i++) { w = u&v; w ^= w >> 8; w ^= w >> 4; w ^= w >> 2; w ^= w >> 1; v = (w&1UL)|(v<<1); } for (i=1;i<=16;i++) { w = u&v; w ^= w >> 16; w ^= w >> 8; w ^= w >> 4; w ^= w >> 2; w ^= w >> 1; v = (w&1UL)|(v<<1); } #ifdef LONG_IS_64BIT for (i=1; i<=32; i++) { w = u&v; w ^= w >> 32; w ^= w >> 16; w ^= w >> 8; w ^= w >> 4; w ^= w >> 2; w ^= w >> 1; v = (w&1UL)|(v<<1); } #endif return (F2x_recip1(v)<<1) | 1UL; } static GEN F2xn_inv1(GEN v, long e) { ulong mask = e==BITS_IN_LONG ? -1UL: ((1UL<1;) { GEN u, fr; long n2 = n; n<<=1; if (mask & 1) n--; mask >>= 1; fr = F2xn_red(f, n); if (mask>1 || !g) { u = F2x_shift(F2xn_mul(W, fr, n), -n2); W = F2x_add(W, F2x_shift(F2xn_mul(u, W, n-n2), n2)); } else { GEN y = F2xn_mul(g, W, n), yt = F2xn_red(y, n-n2); u = F2xn_mul(yt, F2x_shift(F2xn_mul(fr, W, n), -n2), n-n2); W = F2x_add(y, F2x_shift(u, n2)); } if (gc_needed(av2,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"F2xn_inv, e = %ld", n); W = gerepileupto(av2, W); } } return gerepileupto(av, F2xn_red(W,e)); } GEN F2xn_inv(GEN f, long e) { return F2xn_div(NULL, f, e); } GEN F2x_get_red(GEN T) { return T; } /* separate from F2x_divrem for maximal speed. */ GEN F2x_rem(GEN x, GEN y) { long dx,dy; long lx=lg(x); dy = F2x_degree(y); if (!dy) return pol0_F2x(x[1]); dx = F2x_degree_lg(x,lx); x = F2x_copy(x); while (dx>=dy) { F2x_addshiftip(x,y,dx-dy); while (lx>2 && x[lx-1]==0) lx--; dx = F2x_degree_lg(x,lx); } return F2x_renormalize(x, lx); } GEN F2x_divrem(GEN x, GEN y, GEN *pr) { long dx, dy, dz, lx = lg(x), vs = x[1]; GEN z; dy = F2x_degree(y); if (dy<0) pari_err_INV("F2x_divrem",y); if (pr == ONLY_REM) return F2x_rem(x, y); if (!dy) { z = F2x_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? F2x_copy(x): NULL; z = pol0_F2x(vs); if (pr) *pr = F2x_copy(x); return z; } z = zero_zv(lg(x)-lg(y)+2); z[1] = vs; x = F2x_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; } return gc_NULL((pari_sp)(z + lg(z))); } *pr = x; return z; } long F2x_valrem(GEN x, GEN *Z) { long v, v2, i, l=lg(x); GEN y; if (l==2) { *Z = F2x_copy(x); return LONG_MAX; } for (i=2; i> v2; else { const ulong sh = BITS_IN_LONG - v2; ulong r = uel(x,2+v); for (i=3; i> v2); r = uel(x,i+v); } uel(y,l-1) = r >> v2; (void)F2x_renormalize(y,l); } *Z = y; return (v << TWOPOTBITS_IN_LONG) + v2; } GEN F2x_deflate(GEN x, long d) { GEN y; long i,id, dy, dx = F2x_degree(x); if (d <= 1) return F2x_copy(x); if (dx < 0) return F2x_copy(x); dy = dx/d; /* dy+1 coefficients + 1 extra word for variable */ y = zero_zv(nbits2lg(dy+1)-1); y[1] = x[1]; for (i=id=0; i<=dy; i++,id+=d) if (F2x_coeff(x,id)) F2x_set(y, i); return y; } /* write p(X) = e(X^2) + Xo(X^2), shallow function */ void F2x_even_odd(GEN p, GEN *pe, GEN *po) { long n = F2x_degree(p), n0, n1, i; GEN p0, p1; if (n <= 0) { *pe = F2x_copy(p); *po = pol0_F2x(p[1]); return; } n0 = (n>>1)+1; n1 = n+1 - n0; /* n1 <= n0 <= n1+1 */ p0 = zero_zv(nbits2lg(n0+1)-1); p0[1] = p[1]; p1 = zero_zv(nbits2lg(n1+1)-1); p1[1] = p[1]; for (i=0; i>1)&mask; return F2x_renormalize(x,l); } GEN F2x_gcd(GEN a, GEN b) { pari_sp av = avma; if (lg(b) > lg(a)) swap(a, b); while (lgpol(b)) { GEN c = F2x_rem(a,b); a = b; b = c; if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"F2x_gcd (d = %ld)",F2x_degree(c)); gerepileall(av,2, &a,&b); } } if (gc_needed(av,2)) a = gerepileuptoleaf(av, a); return a; } GEN F2x_extgcd(GEN a, GEN b, GEN *ptu, GEN *ptv) { pari_sp av=avma; 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 (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"F2x_extgcd (d = %ld)",F2x_degree(d)); gerepileall(av,5, &d,&d1,&u,&v,&v1); } } if (ptu) *ptu = F2x_div(F2x_add(d, F2x_mul(b,v)), a); *ptv = v; if (gc_needed(av,2)) gerepileall(av,ptu?3:2,&d,ptv,ptu); return d; } static GEN F2x_halfgcd_i(GEN a, GEN b) { pari_sp av=avma; GEN u,u1,v,v1; long vx = a[1]; long n = (F2x_degree(a)+1)>>1; u1 = v = pol0_F2x(vx); u = v1 = pol1_F2x(vx); while (F2x_degree(b)>=n) { GEN r, q = F2x_divrem(a,b, &r); a = b; b = r; swap(u,u1); swap(v,v1); u1 = F2x_add(u1, F2x_mul(u, q)); v1 = F2x_add(v1, F2x_mul(v, q)); if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"F2x_halfgcd (d = %ld)",F2x_degree(b)); gerepileall(av,6, &a,&b,&u1,&v1,&u,&v); } } return gerepilecopy(av, mkmat22(u,v,u1,v1)); } GEN F2x_halfgcd(GEN x, GEN y) { pari_sp av; GEN M,q,r; if (F2x_degree(y)= get_F2x_degree(T); return gen_powers(x, l, use_sqr, (void*)T, &_F2xq_sqr, &_F2xq_mul, &_F2xq_one); } GEN F2xq_matrix_pow(GEN y, long n, long m, GEN P) { return F2xV_to_F2m(F2xq_powers(y,m-1,P),n); } GEN F2x_Frobenius(GEN T) { return F2xq_sqr(polx_F2x(get_F2x_var(T)), T); } GEN F2x_matFrobenius(GEN T) { long n = get_F2x_degree(T); return F2xq_matrix_pow(F2x_Frobenius(T), n, n, T); } static struct bb_algebra F2xq_algebra = { _F2xq_red, _F2xq_add, _F2xq_add, _F2xq_mul, _F2xq_sqr, _F2xq_one, _F2xq_zero}; GEN F2x_F2xqV_eval(GEN Q, GEN x, GEN T) { long d = F2x_degree(Q); return gen_bkeval_powers(Q,d,x,(void*)T,&F2xq_algebra,_F2xq_cmul); } GEN F2x_F2xq_eval(GEN Q, GEN x, GEN T) { long d = F2x_degree(Q); int use_sqr = 2*F2x_degree(x) >= get_F2x_degree(T); return gen_bkeval(Q, d, x, use_sqr, (void*)T, &F2xq_algebra, _F2xq_cmul); } static GEN F2xq_autpow_sqr(void * T, GEN x) { return F2x_F2xq_eval(x, x, (GEN) T); } static GEN F2xq_autpow_mul(void * T, GEN x, GEN y) { return F2x_F2xq_eval(x, y, (GEN) T); } GEN F2xq_autpow(GEN x, long n, GEN T) { if (n==0) return F2x_rem(polx_F2x(x[1]), T); if (n==1) return F2x_rem(x, T); return gen_powu(x,n,(void*)T,F2xq_autpow_sqr,F2xq_autpow_mul); } ulong F2xq_trace(GEN x, GEN T) { pari_sp av = avma; long n = get_F2x_degree(T)-1; GEN z = F2xq_mul(x, F2x_deriv(get_F2x_mod(T)), T); return gc_ulong(av, F2x_degree(z) < n ? 0 : 1); } GEN F2xq_conjvec(GEN x, GEN T) { long i, l = 1+get_F2x_degree(T); GEN z = cgetg(l,t_COL); gel(z,1) = F2x_copy(x); for (i=2; i>n, d = dT-(h<1) err_printf("Found %lu\n", g[2]); } return gerepileuptoint(av, l); } } return gc_NULL(av); } static GEN F2xq_log_find_rel(GEN b, long r, GEN T, GEN *g, ulong *e) { pari_sp av = avma; while (1) { GEN M; *g = F2xq_mul(*g, b, T); (*e)++; M = F2x_halfgcd(*g,T); if (F2x_is_smooth(gcoeff(M,1,1), r)) { GEN z = F2x_add(F2x_mul(gcoeff(M,1,1),*g), F2x_mul(gcoeff(M,1,2),T)); if (F2x_is_smooth(z, r)) { GEN F = F2x_factorel(z); GEN G = F2x_factorel(gcoeff(M,1,1)); GEN rel = mkmat2(vecsmall_concat(gel(F, 1),gel(G, 1)), vecsmall_concat(gel(F, 2),zv_neg(gel(G, 2)))); return gc_all(av, 2, &rel, g); } } if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"F2xq_log_find_rel"); *g = gerepileuptoleaf(av, *g); } } } static GEN F2xq_log_Coppersmith_rec(GEN W, long r2, GEN a, long r, long n, GEN T, GEN m) { long vT = get_F2x_var(T); GEN b = polx_F2x(vT); ulong AV = 0; GEN g = a, bad = pol0_F2x(vT); pari_timer ti; while(1) { long i, l; GEN V, F, E, Ao; timer_start(&ti); V = F2xq_log_find_rel(b, r2, T, &g, &AV); if (DEBUGLEVEL>1) timer_printf(&ti,"%ld-smooth element",r2); F = gel(V,1); E = gel(V,2); l = lg(F); Ao = gen_0; for(i=1; i>n, d = dT-(h< 1) { for (j=1; jnbrel) break; gel(M,rel++) = gel(L,j); if (DEBUGLEVEL && (rel&511UL)==0) err_printf("%ld%%[%ld] ",rel*100/nbrel,i); } } if (rel>nbrel) stop=1; i++; } mt_queue_end(&pt); if (DEBUGLEVEL) err_printf(": %ld tests\n", nbtest); return M; } static GEN smallirred_F2x(ulong n, long sv) { GEN a = zero_zv(nbits2lg(n+1)-1); a[1] = sv; F2x_set(a,n); a[2]++; while (!F2x_is_irred(a)) a[2]+=2; return a; } static GEN check_kernel(long N, GEN M, long nbi, GEN T, GEN m) { pari_sp av = avma; long dT = get_F2x_degree(T), vT = get_F2x_var(T); GEN K = FpMs_leftkernel_elt(M, N, m); long i, f=0, tbs; long l = lg(K), lm = lgefint(m); GEN idx = diviiexact(int2um1(dT), m); GEN g = F2xq_pow(polx_F2x(vT), idx, T); GEN tab; pari_timer ti; if (DEBUGLEVEL) timer_start(&ti); K = FpC_Fp_mul(K, Fp_inv(gel(K,2), m), m); tbs = maxss(1, expu(nbi/expi(m))); tab = F2xq_pow_init(g, int2n(dT), tbs, T); for(i=1; i100); GEN T = smallirred_F2x(n,T0[1]); long d = 2, r2 = 3*r/2, d2 = 2; long N = (1UL<<(r+1))-1UL; long nbi = itos(ffsumnbirred(gen_2, r)), nbrel=nbi*5/4; if (DEBUGLEVEL) { err_printf("F2xq_log: Parameters r=%ld r2=%ld\n", r,r2); err_printf("F2xq_log: Size FB=%ld rel. needed=%ld\n", nbi, nbrel); timer_start(&ti); } S = Flx_to_F2x(Flx_ffisom(F2x_to_Flx(T0),F2x_to_Flx(T),2)); a = F2x_F2xq_eval(a0, S, T); b = F2x_F2xq_eval(b0, S, T); if (DEBUGLEVEL) timer_printf(&ti,"model change"); M = F2xq_log_Coppersmith(nbrel,r,d,T); if(DEBUGLEVEL) timer_printf(&ti,"relations"); W = check_kernel(N, M, nbi, T, m); timer_start(&ti); Ao = F2xq_log_Coppersmith_rec(W, r2, a, r, d2, T, m); if (DEBUGLEVEL) timer_printf(&ti,"smooth element"); Bo = F2xq_log_Coppersmith_rec(W, r2, b, r, d2, T, m); if (DEBUGLEVEL) timer_printf(&ti,"smooth generator"); e = Fp_div(Ao, Bo, m); if (!F2x_equal(F2xq_pow(b0,e,T0),a0)) pari_err_BUG("F2xq_log"); return gerepileupto(av, e); } static GEN F2xq_easylog(void* E, GEN a, GEN g, GEN ord) { if (F2x_equal1(a)) return gen_0; if (F2x_equal(a,g)) return gen_1; if (typ(ord)!=t_INT) return NULL; if (expi(ord)<28) return NULL; return F2xq_log_index(a,g,ord,(GEN)E); } GEN F2xq_log(GEN a, GEN g, GEN ord, GEN T) { GEN z, v = get_arith_ZZM(ord); ord = mkvec2(gel(v,1),ZM_famat_limit(gel(v,2),int2n(28))); z = gen_PH_log(a,g,ord,(void*)T,&F2xq_star); return z? z: cgetg(1,t_VEC); } GEN F2xq_Artin_Schreier(GEN a, GEN T) { pari_sp ltop=avma; long j,N = get_F2x_degree(T), vT = get_F2x_var(T); GEN Q = F2x_matFrobenius(T); for (j=1; j<=N; j++) F2m_flip(Q,j,j); F2v_add_inplace(gel(Q,1),a); Q = F2m_ker_sp(Q,0); if (lg(Q)!=2) return NULL; Q = gel(Q,1); Q[1] = vT; return gerepileuptoleaf(ltop, F2x_renormalize(Q, lg(Q))); } GEN F2xq_sqrt_fast(GEN c, GEN sqx, GEN T) { GEN c0, c1; F2x_even_odd(c, &c0, &c1); return F2x_add(c0, F2xq_mul(c1, sqx, T)); } static int F2x_is_x(GEN a) { return lg(a)==3 && a[2]==2; } GEN F2xq_sqrt(GEN a, GEN T) { pari_sp av = avma; long n = get_F2x_degree(T), vT = get_F2x_var(T); GEN sqx; if (n==1) return F2x_copy(a); if (n==2) return F2xq_sqr(a,T); sqx = F2xq_autpow(mkF2(4, vT), n-1, T); return gerepileuptoleaf(av, F2x_is_x(a)? sqx: F2xq_sqrt_fast(a,sqx,T)); } GEN F2xq_sqrtn(GEN a, GEN n, GEN T, GEN *zeta) { long dT = get_F2x_degree(T), vT = get_F2x_var(T); if (!lgpol(a)) { if (signe(n) < 0) pari_err_INV("F2xq_sqrtn",a); if (zeta) *zeta=pol1_F2x(vT); return pol0_F2x(vT); } return gen_Shanks_sqrtn(a, n, int2um1(dT), zeta, (void*)T, &F2xq_star); } GEN gener_F2xq(GEN T, GEN *po) { long i, j, vT = get_F2x_var(T), f = get_F2x_degree(T); pari_sp av0 = avma, av; GEN g, L2, o, q; if (f == 1) { if (po) *po = mkvec2(gen_1, trivial_fact()); return pol1_F2x(vT); } q = int2um1(f); o = factor_pn_1(gen_2,f); L2 = leafcopy( gel(o, 1) ); for (i = j = 1; i < lg(L2); i++) { if (absequaliu(gel(L2,i),2)) continue; gel(L2,j++) = diviiexact(q, gel(L2,i)); } setlg(L2, j); for (av = avma;; set_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(int2um1(f), o); gerepileall(av0, 2, &g, po); } return g; } static GEN _F2xq_neg(void *E, GEN x) { (void) E; return F2x_copy(x); } static GEN _F2xq_rmul(void *E, GEN x, GEN y) { (void) E; return F2x_mul(x,y); } static GEN _F2xq_inv(void *E, GEN x) { return F2xq_inv(x, (GEN) E); } static int _F2xq_equal0(GEN x) { return lgpol(x)==0; } static GEN _F2xq_s(void *E, long x) { GEN T = (GEN) E; long v = get_F2x_var(T); return odd(x)? pol1_F2x(v): pol0_F2x(v); } static const struct bb_field F2xq_field={_F2xq_red,_F2xq_add,_F2xq_rmul,_F2xq_neg, _F2xq_inv,_F2xq_equal0,_F2xq_s}; const struct bb_field *get_F2xq_field(void **E, GEN T) { *E = (void *) T; return &F2xq_field; } /***********************************************************************/ /** **/ /** F2xV **/ /** **/ /***********************************************************************/ /* F2xV are t_VEC with F2x coefficients. */ GEN FlxC_to_F2xC(GEN x) { pari_APPLY_type(t_COL, Flx_to_F2x(gel(x,i))) } GEN F2xC_to_FlxC(GEN x) { pari_APPLY_type(t_COL, F2x_to_Flx(gel(x,i))) } GEN F2xC_to_ZXC(GEN x) { pari_APPLY_type(t_COL, F2x_to_ZX(gel(x,i))) } GEN F2xV_to_F2m(GEN x, long n) { pari_APPLY_type(t_MAT, F2x_to_F2v(gel(x,i), n)) } void F2xV_to_FlxV_inplace(GEN v) { long i, l = lg(v); for(i = 1; i < l;i++) gel(v,i) = F2x_to_Flx(gel(v,i)); } void F2xV_to_ZXV_inplace(GEN v) { long i, l = lg(v); for(i = 1; i < l; i++) gel(v,i)= F2x_to_ZX(gel(v,i)); } /***********************************************************************/ /** **/ /** F2xX **/ /** **/ /***********************************************************************/ GEN F2xX_renormalize(GEN /*in place*/ x, long lx) { return FlxX_renormalize(x, lx); } GEN pol1_F2xX(long v, long sv) { return pol1_FlxX(v, sv); } GEN polx_F2xX(long v, long sv) { return polx_FlxX(v, sv); } long F2xY_degreex(GEN b) { long deg = 0, i; if (!signe(b)) return -1; for (i = 2; i < lg(b); ++i) deg = maxss(deg, F2x_degree(gel(b, i))); return deg; } GEN FlxX_to_F2xX(GEN B) { long lb=lg(B); long i; GEN b=cgetg(lb,t_POL); b[1]=evalsigne(1)|(((ulong)B[1])&VARNBITS); for (i=2; ilx) swapspec(x,y, lx,ly); lz = lx+2; z = cgetg(lz, t_POL); for (i=0; ilx) swapspec(x,y, lx,ly); lz = lx; z = cgetg(lz, t_POL); z[1]=x[1]; for (i=2; i>ib; for(i=0; i>ib; } if (db) uel(t,2+i) = (uel(x,3+il+i)< N+1) l = N+1; /* truncate higher degree terms */ z = cgetg(N+1,t_COL); for (i=1; i 0) { GEN u = pol0_F2x(T[1]); long i,j; for (i=2,j=2; i=dy; i--) { av=avma; p1=gel(x,i); for (j=i-dy+1; j<=i && j<=dz; j++) p1 = F2x_add(p1, F2x_mul(gel(z,j),gel(y,i-j))); if (lead) p1 = F2x_mul(p1, lead); tetpil=avma; gel(z,i-dy) = gerepile(av,tetpil,F2x_rem(p1,T)); } if (!pr) { guncloneNULL(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 = F2x_add(p1, F2x_mul(gel(z,j),gel(y,i-j))); tetpil=avma; p1 = F2x_rem(p1, T); if (lgpol(p1)) { sx = 1; break; } if (!i) break; set_avma(av); } if (pr == ONLY_DIVIDES) { guncloneNULL(lead); if (sx) return gc_NULL(av0); return gc_const((pari_sp)rem, 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 = F2x_add(p1, F2x_mul(gel(z,j),gel(y,i-j))); tetpil=avma; gel(rem,i) = gerepile(av,tetpil, F2x_rem(p1, T)); } rem -= 2; guncloneNULL(lead); if (!sx) (void)F2xX_renormalize(rem, lr); if (pr == ONLY_REM) return gerepileupto(av0,rem); *pr = rem; return z-2; } static GEN F2xX_recipspec(GEN x, long l, long n, long vs) { long i; GEN z = cgetg(n+2,t_POL); z[1] = 0; z += 2; for(i=0; i=0; i--) if (lgpol(gel(x,i))) break; return i+1; } static GEN F2xqX_invBarrett_Newton(GEN S, GEN T) { pari_sp av = avma; long nold, lx, lz, lq, l = degpol(S), i, lQ; GEN q, y, z, x = cgetg(l+2, t_POL) + 2; long dT = get_F2x_degree(T); ulong mask = quadratic_prec_mask(l-2); /* assume l > 2 */ for (i=0;i1 && F2x_degree(gel(q,1)) >= dT) gel(q,1) = F2x_rem(gel(q,1), T); if (lQ>1 && lgpol(gel(q,1))) { GEN u = gel(q, 1); if (!F2x_equal1(gel(x,0))) u = F2xq_mul(u, F2xq_sqr(gel(x,0), T), T); else u = F2x_copy(u); gel(x,1) = u; 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 = F2xX_lgrenormalizespec(q, minss(lQ,lnew)); z = F2xqX_mulspec(x, q, T, lx, lq); /* FIXME: high product */ lz = lgpol(z); if (lz > lnew) lz = lnew; z += 2; /* subtract 1 [=>first nold words are 0]: renormalize so that z(0) != 0 */ for (i = nold; i < lz; i++) if (lgpol(gel(z,i))) break; nold = nnew; if (i >= lz) continue; /* z-1 = 0(t^(nnew + 1)) */ /* z + i represents (x*q - 1) / t^i */ lz = F2xX_lgrenormalizespec (z+i, lz-i); z = F2xqX_mulspec(x, z+i, T, lx, lz); /* FIXME: low product */ lz = lgpol(z); z += 2; if (lz > lnew-i) lz = F2xX_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) = gel(z,i); } x -= 2; setlg(x, lx + 2); x[1] = S[1]; return gerepilecopy(av, x); } GEN F2xqX_invBarrett(GEN T, GEN Q) { pari_sp ltop=avma; long l=lg(T), v = varn(T); GEN r; GEN c = gel(T,l-1); if (l<5) return pol_0(v); if (l<=F2xqX_INVBARRETT_LIMIT) { if (!F2x_equal1(c)) { GEN ci = F2xq_inv(c,Q); T = F2xqX_F2xq_mul(T, ci, Q); r = F2xqX_invBarrett_basecase(T,Q); r = F2xqX_F2xq_mul(r,ci,Q); } else r = F2xqX_invBarrett_basecase(T,Q); } else r = F2xqX_invBarrett_Newton(T,Q); return gerepileupto(ltop, r); } GEN F2xqX_get_red(GEN S, GEN T) { if (typ(S)==t_POL && lg(S)>F2xqX_BARRETT_LIMIT) retmkvec2(F2xqX_invBarrett(S, T), S); return S; } /* Compute x mod S where 2 <= degpol(S) <= l+1 <= 2*(degpol(S)-1) * * and mg is the Barrett inverse of S. */ static GEN F2xqX_divrem_Barrettspec(GEN x, long l, GEN mg, GEN S, GEN T, GEN *pr) { GEN q, r; long lt = degpol(S); /*We discard the leading term*/ long ld, lm, lT, lmg; ld = l-lt; lm = minss(ld, lgpol(mg)); lT = F2xX_lgrenormalizespec(S+2,lt); lmg = F2xX_lgrenormalizespec(mg+2,lm); q = F2xX_recipspec(x+lt,ld,ld,0); /* q = rec(x) lq<=ld*/ q = F2xqX_mulspec(q+2,mg+2,T,lgpol(q),lmg); /* q = rec(x) * mg lq<=ld+lm*/ q = F2xX_recipspec(q+2,minss(ld,lgpol(q)),ld,0);/* q = rec (rec(x) * mg) lq<=ld*/ if (!pr) return q; r = F2xqX_mulspec(q+2,S+2,T,lgpol(q),lT); /* r = q*pol lr<=ld+lt*/ r = F2xX_addspec(x,r+2,lt,minss(lt,lgpol(r)));/* r = x - r lr<=lt */ if (pr == ONLY_REM) return r; *pr = r; return q; } static GEN F2xqX_divrem_Barrett(GEN x, GEN mg, GEN S, GEN T, GEN *pr) { GEN q = NULL, r = F2xqX_red(x, T); long l = lgpol(r), lt = degpol(S), lm = 2*lt-1, v = varn(S); long i; if (l <= lt) { if (pr == ONLY_REM) return r; if (pr == ONLY_DIVIDES) return signe(r)? NULL: pol_0(v); if (pr) *pr = r; return pol_0(v); } if (lt <= 1) return F2xqX_divrem_basecase(x,S,T,pr); if (pr != ONLY_REM && l>lm) { long vT = get_F2x_var(T); q = cgetg(l-lt+2, t_POL); q[1] = S[1]; for (i=0;ilm) { GEN zr, zq = F2xqX_divrem_Barrettspec(r+2+l-lm,lm,mg,S,T,&zr); long lz = lgpol(zr); if (pr != ONLY_REM) { long lq = lgpol(zq); for(i=0; i lt) r = F2xqX_divrem_Barrettspec(r+2,l,mg,S,T,ONLY_REM); else r = F2xX_renormalize(r, lg(r)); setvarn(r, v); return F2xX_renormalize(r, lg(r)); } if (l > lt) { GEN zq = F2xqX_divrem_Barrettspec(r+2,l,mg,S,T,pr? &r: NULL); if (!q) q = zq; else { long lq = lgpol(zq); for(i=0; i= 0) { if (!F2x_equal1(res->lc)) { res->lc = F2xq_powu(res->lc, da - dr, T); res->res = F2xq_mul(res->res, res->lc, T); } } else { if (db == 0) { if (!F2x_equal1(res->lc)) { res->lc = F2xq_powu(res->lc, da, T); res->res = F2xq_mul(res->res, res->lc, T); } } else res->res = pol0_F2x(get_F2x_var(T)); } } static GEN F2xqX_halfres_basecase(GEN a, GEN b, GEN T, GEN *pa, GEN *pb, struct F2xqX_res *res) { pari_sp av=avma; GEN u,u1,v,v1, M; long vx = varn(a), vT = get_F2x_var(T), n = lgpol(a)>>1; u1 = v = pol_0(vx); u = v1 = pol1_F2xX(vx, vT); while (lgpol(b)>n) { GEN r, q; q = F2xqX_divrem(a,b, T, &r); if (res) { long da = degpol(a), db = degpol(b), dr = degpol(r); res->lc = gel(b,db+2); if (dr >= n) F2xqX_halfres_update(da, db, dr, T, res); else { res->deg0 = da; res->deg1 = db; } } a = b; b = r; swap(u,u1); swap(v,v1); u1 = F2xX_add(u1, F2xqX_mul(u, q, T)); v1 = F2xX_add(v1, F2xqX_mul(v, q, T)); if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"F2xqX_halfgcd (d = %ld)",degpol(b)); if (res) gerepileall(av, 8, &a,&b,&u1,&v1,&u,&v,&res->res,&res->lc); else gerepileall(av, 6, &a,&b,&u1,&v1,&u,&v); } } M = mkmat22(u,v,u1,v1); *pa = a; *pb = b; return res ? gc_all(av, 5, &M, pa, pb, &res->res, &res->lc) : gc_all(av, 3, &M, pa, pb); } static GEN F2xqX_halfres_i(GEN x, GEN y, GEN T, GEN *a, GEN *b, struct F2xqX_res *res); static GEN F2xqX_halfres_split(GEN x, GEN y, GEN T, GEN *a, GEN *b, struct F2xqX_res *res) { pari_sp av = avma; GEN Q, R, S, V1, V2; GEN x1, y1, r, q; long l = lgpol(x), n = l>>1, k, vT = get_F2x_var(T); if (lgpol(y) <= n) { *a = RgX_copy(x); *b = RgX_copy(y); return matid2_F2xXM(varn(x),vT); } if (res) { res->lc = leading_coeff(y); res->deg0 -= n; res->deg1 -= n; } R = F2xqX_halfres_i(F2xX_shift(x,-n, vT),F2xX_shift(y,-n, vT), T, a, b, res); if (res) { res->deg0 += n; res->deg1 += n; } V1 = F2xqXM_F2xqX_mul2(R, Flxn_red(x,n), Flxn_red(y,n), T); x1 = F2xX_add(F2xX_shift(*a,n,vT), gel(V1,1)); y1 = F2xX_add(F2xX_shift(*b,n,vT), gel(V1,2)); if (lgpol(y1) <= n) { *a = x1; *b = y1; return res ? gc_all(av, 5, &R, a, b, &res->res, &res->lc) : gc_all(av, 3, &R, a, b, &res->res, &res->lc); } k = 2*n-degpol(y1); q = F2xqX_divrem(x1, y1, T, &r); if (res) { long dx1 = degpol(x1), dy1 = degpol(y1), dr = degpol(r); if (dy1 < degpol(y)) F2xqX_halfres_update(res->deg0, res->deg1, dy1, T, res); res->lc = leading_coeff(y1); res->deg0 = dx1; res->deg1 = dy1; if (dr >= n) { F2xqX_halfres_update(dx1, dy1, dr, T, res); res->deg0 = dy1; res->deg1 = dr; } res->deg0 -= k; res->deg1 -= k; } S = F2xqX_halfres_i(F2xX_shift(y1,-k, vT), F2xX_shift(r,-k, vT), T, a, b, res); if (res) { res->deg0 += k; res->deg1 += k; } Q = F2xqXM_mul2(S,F2xqX_F2xqXM_qmul(q, R, T), T); V2 = F2xqXM_F2xqX_mul2(S, F2xXn_red(y1,k), F2xXn_red(r,k), T); *a = F2xX_add(F2xX_shift(*a,k,vT), gel(V2,1)); *b = F2xX_add(F2xX_shift(*b,k,vT), gel(V2,2)); return res ? gc_all(av, 5, &Q, a, b, &res->res, &res->lc) : gc_all(av, 3, &Q, a, b, &res->res, &res->lc); } static GEN F2xqX_halfres_i(GEN x, GEN y, GEN T, GEN *a, GEN *b, struct F2xqX_res *res) { if (lgpol(x) < F2xqX_HALFGCD_LIMIT) return F2xqX_halfres_basecase(x, y, T, a, b, res); return F2xqX_halfres_split(x, y, T, a, b, res); } static GEN F2xqX_halfgcd_all_i(GEN x, GEN y, GEN T, GEN *pa, GEN *pb) { GEN a, b; GEN R = F2xqX_halfres_i(x, y, T, &a, &b, NULL); if (pa) *pa = a; if (pb) *pb = b; return R; } /* Return M in GL_2(F_2[X]/(T)[Y]) such that: if [a',b']~=M*[a,b]~ then degpol(a')>= (lgpol(a)>>1) >degpol(b') */ GEN F2xqX_halfgcd_all(GEN x, GEN y, GEN T, GEN *a, GEN *b) { pari_sp av = avma; GEN R,q,r; if (!signe(x)) { if (a) *a = RgX_copy(y); if (b) *b = RgX_copy(x); return matJ2_F2xXM(varn(x), get_F2x_var(T)); } if (degpol(y)1) pari_warn(warnmem,"F2xqX_gcd (d = %ld)",degpol(b)); gerepileall(av0,2, &a,&b); } av = avma; c = F2xqX_rem(a, b, T); a=b; b=c; } return gc_const(av, a); } GEN F2xqX_gcd(GEN x, GEN y, GEN T) { pari_sp av = avma; x = F2xqX_red(x, T); y = F2xqX_red(y, T); if (!signe(x)) return gerepileupto(av, y); while (lgpol(y)>=F2xqX_GCD_LIMIT) { if (lgpol(y)<=(lgpol(x)>>1)) { GEN r = F2xqX_rem(x, y, T); x = y; y = r; } (void) F2xqX_halfgcd_all(x, y, T, &x, &y); if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"F2xqX_gcd (y = %ld)",degpol(y)); gerepileall(av,2,&x,&y); } } return gerepileupto(av, F2xqX_gcd_basecase(x, y, T)); } static GEN F2xqX_extgcd_basecase(GEN a, GEN b, GEN T, GEN *ptu, GEN *ptv) { pari_sp av=avma; GEN u,v,d,d1,v1; long vx = varn(a); d = a; d1 = b; v = pol_0(vx); v1 = pol1_F2xX(vx, get_F2x_var(T)); while (signe(d1)) { GEN r, q = F2xqX_divrem(d, d1, T, &r); v = F2xX_add(v,F2xqX_mul(q,v1,T)); u=v; v=v1; v1=u; u=r; d=d1; d1=u; if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"F2xqX_extgcd (d = %ld)",degpol(d)); gerepileall(av,5, &d,&d1,&u,&v,&v1); } } if (ptu) *ptu = F2xqX_div(F2xX_add(d,F2xqX_mul(b,v, T)), a, T); *ptv = v; return d; } static GEN F2xqX_extgcd_halfgcd(GEN x, GEN y, GEN T, GEN *ptu, GEN *ptv) { GEN u,v; GEN V = cgetg(expu(lgpol(y))+2,t_VEC); long i, n = 0, vs = varn(x), vT = get_F2x_var(T); while (lgpol(y)>=F2xqX_EXTGCD_LIMIT) { if (lgpol(y)<=(lgpol(x)>>1)) { GEN r, q = F2xqX_divrem(x, y, T, &r); x = y; y = r; gel(V,++n) = mkmat22(pol_0(vs),pol1_F2xX(vs,vT),pol1_F2xX(vs,vT),RgX_copy(q)); } else gel(V,++n) = F2xqX_halfgcd_all(x, y, T, &x, &y); } y = F2xqX_extgcd_basecase(x,y, T, &u,&v); for (i = n; i>1; i--) { GEN R = gel(V,i); GEN u1 = F2xqX_addmulmul(u, v, gcoeff(R,1,1), gcoeff(R,2,1), T); GEN v1 = F2xqX_addmulmul(u, v, gcoeff(R,1,2), gcoeff(R,2,2), T); u = u1; v = v1; } { GEN R = gel(V,1); if (ptu) *ptu = F2xqX_addmulmul(u, v, gcoeff(R,1,1), gcoeff(R,2,1), T); *ptv = F2xqX_addmulmul(u, v, gcoeff(R,1,2), gcoeff(R,2,2), T); } return y; } /* 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 F2xqX_extgcd(GEN x, GEN y, GEN T, GEN *ptu, GEN *ptv) { pari_sp av = avma; GEN d; x = F2xqX_red(x, T); y = F2xqX_red(y, T); if (lgpol(y)>=F2xqX_EXTGCD_LIMIT) d = F2xqX_extgcd_halfgcd(x, y, T, ptu, ptv); else d = F2xqX_extgcd_basecase(x, y, T, ptu, ptv); return gc_all(av, ptu?3:2, &d, ptv, ptu); } static GEN F2xqX_halfres(GEN x, GEN y, GEN T, GEN *a, GEN *b, GEN *r) { struct F2xqX_res res; GEN V; long dB; res.res = *r; res.lc = leading_coeff(y); res.deg0 = degpol(x); res.deg1 = degpol(y); V = F2xqX_halfres_i(x, y, T, a, b, &res); dB = degpol(*b); if (dB < degpol(y)) F2xqX_halfres_update(res.deg0, res.deg1, dB, T, &res); *r = res.res; return V; } /* Res(A,B) = Res(B,R) * lc(B)^(a-r) * (-1)^(ab), with R=A%B, a=deg(A) ...*/ static GEN F2xqX_resultant_basecase(GEN a, GEN b, GEN T) { pari_sp av = avma; long vT = get_F2x_var(T), da,db,dc; GEN c,lb, res = pol1_F2x(vT); if (!signe(a) || !signe(b)) return pol0_F2x(vT); da = degpol(a); db = degpol(b); if (db > da) swapspec(a,b, da,db); if (!da) return pol1_F2x(vT); /* = res * a[2] ^ db, since 0 <= db <= da = 0 */ while (db) { lb = gel(b,db+2); c = F2xqX_rem(a,b, T); a = b; b = c; dc = degpol(c); if (dc < 0) { set_avma(av); return pol0_F2x(vT); } if (!equali1(lb)) res = F2xq_mul(res, F2xq_powu(lb, da - dc, T), T); if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"F2xqX_resultant (da = %ld)",da); gerepileall(av,3, &a,&b,&res); } da = db; /* = degpol(a) */ db = dc; /* = degpol(b) */ } res = F2xq_mul(res, F2xq_powu(gel(b,2), da, T), T); return gerepileupto(av, res); } /* Res(A,B) = Res(B,R) * lc(B)^(a-r) * (-1)^(ab), with R=A%B, a=deg(A) ...*/ GEN F2xqX_resultant(GEN x, GEN y, GEN T) { pari_sp av = avma; long dx, dy, vT = get_F2x_var(T); GEN res = pol1_F2x(vT); if (!signe(x) || !signe(y)) return pol0_F2x(vT); dx = degpol(x); dy = degpol(y); if (dx < dy) swap(x,y); while (lgpol(y) >= F2xqX_GCD_LIMIT) { if (lgpol(y)<=(lgpol(x)>>1)) { GEN r = F2xqX_rem(x, y, T); long dx = degpol(x), dy = degpol(y), dr = degpol(r); GEN ly = gel(y,dy+2); if (!F2x_equal1(ly)) res = F2xq_mul(res, F2xq_powu(ly, dx - dr, T), T); x = y; y = r; } (void) F2xqX_halfres(x, y, T, &x, &y, &res); if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"F2xqX_resultant (y = %ld)",degpol(y)); gerepileall(av,3,&x,&y,&res); } } res = F2xq_mul(res, F2xqX_resultant_basecase(x, y, T), T); return gerepileupto(av, res); } /* disc P = (-1)^(n(n-1)/2) lc(P)^(n - deg P' - 2) Res(P,P'), n = deg P */ GEN F2xqX_disc(GEN P, GEN T) { pari_sp av = avma; GEN L, dP = F2xX_deriv(P), D = F2xqX_resultant(P, dP, T); long dd; if (!lgpol(D)) return pol_0(get_F2x_var(T)); dd = degpol(P) - 2 - degpol(dP); /* >= -1; > -1 iff p | deg(P) */ L = leading_coeff(P); if (dd && !F2x_equal1(L)) D = (dd == -1)? F2xq_div(D,L,T): F2xq_mul(D, F2xq_powu(L, dd, T), T); return gerepileupto(av, D); } /***********************************************************************/ /** **/ /** F2xqXQ **/ /** **/ /***********************************************************************/ GEN F2xqXQ_mul(GEN x, GEN y, GEN S, GEN T) { return F2xqX_rem(F2xqX_mul(x,y,T),S,T); } GEN F2xqXQ_sqr(GEN x, GEN S, GEN T) { return F2xqX_rem(F2xqX_sqr(x,T),S,T); } GEN F2xqXQ_invsafe(GEN x, GEN S, GEN T) { GEN V, z = F2xqX_extgcd(get_F2xqX_mod(S), x, T, NULL, &V); if (degpol(z)) return NULL; z = F2xq_invsafe(gel(z,2),T); if (!z) return NULL; return F2xqX_F2xq_mul(V, z, T); } GEN F2xqXQ_inv(GEN x, GEN S, GEN T) { pari_sp av = avma; GEN U = F2xqXQ_invsafe(x, S, T); if (!U) pari_err_INV("F2xqXQ_inv",x); return gerepileupto(av, U); } struct _F2xqXQ { GEN T, S; }; static GEN _F2xqXQ_add(void *data, GEN x, GEN y) { (void) data; return F2xX_add(x,y); } static GEN _F2xqXQ_cmul(void *data, GEN P, long a, GEN x) { (void) data; return F2xX_F2x_mul(x,gel(P,a+2)); } static GEN _F2xqXQ_red(void *data, GEN x) { struct _F2xqXQ *d = (struct _F2xqXQ*) data; return F2xqX_red(x, d->T); } static GEN _F2xqXQ_mul(void *data, GEN x, GEN y) { struct _F2xqXQ *d = (struct _F2xqXQ*) data; return F2xqXQ_mul(x,y, d->S,d->T); } static GEN _F2xqXQ_sqr(void *data, GEN x) { struct _F2xqXQ *d = (struct _F2xqXQ*) data; return F2xqXQ_sqr(x, d->S,d->T); } static GEN _F2xqXQ_zero(void *data) { struct _F2xqXQ *d = (struct _F2xqXQ*) data; return pol_0(get_F2xqX_var(d->S)); } static GEN _F2xqXQ_one(void *data) { struct _F2xqXQ *d = (struct _F2xqXQ*) data; return pol1_F2xX(get_F2xqX_var(d->S),get_F2x_var(d->T)); } static struct bb_algebra F2xqXQ_algebra = { _F2xqXQ_red, _F2xqXQ_add, _F2xqXQ_add, _F2xqXQ_mul,_F2xqXQ_sqr,_F2xqXQ_one,_F2xqXQ_zero }; GEN F2xqXQ_pow(GEN x, GEN n, GEN S, GEN T) { struct _F2xqXQ D; long s = signe(n); if (!s) return pol1_F2xX(get_F2xqX_var(S), get_F2x_var(T)); if (s < 0) x = F2xqXQ_inv(x,S,T); if (is_pm1(n)) return s < 0 ? x : gcopy(x); if (degpol(x) >= get_F2xqX_degree(S)) x = F2xqX_rem(x,S,T); D.T = F2x_get_red(T); D.S = F2xqX_get_red(S, T); return gen_pow(x, n, (void*)&D, &_F2xqXQ_sqr, &_F2xqXQ_mul); } GEN F2xqXQ_powers(GEN x, long l, GEN S, GEN T) { struct _F2xqXQ D; int use_sqr = 2*degpol(x) >= get_F2xqX_degree(S); D.T = F2x_get_red(T); D.S = F2xqX_get_red(S, T); return gen_powers(x, l, use_sqr, (void*)&D, &_F2xqXQ_sqr, &_F2xqXQ_mul,&_F2xqXQ_one); } GEN F2xqX_F2xqXQV_eval(GEN P, GEN V, GEN S, GEN T) { struct _F2xqXQ D; D.T = F2x_get_red(T); D.S = F2xqX_get_red(S, T); return gen_bkeval_powers(P, degpol(P), V, (void*)&D, &F2xqXQ_algebra, _F2xqXQ_cmul); } GEN F2xqX_F2xqXQ_eval(GEN Q, GEN x, GEN S, GEN T) { struct _F2xqXQ D; int use_sqr = 2*degpol(x) >= get_F2xqX_degree(S); D.T = F2x_get_red(T); D.S = F2xqX_get_red(S, T); return gen_bkeval(Q, degpol(Q), x, use_sqr, (void*)&D, &F2xqXQ_algebra, _F2xqXQ_cmul); } static GEN F2xqXQ_autpow_sqr(void * E, GEN x) { struct _F2xqXQ *D = (struct _F2xqXQ *)E; GEN T = D->T; GEN phi = gel(x,1), S = gel(x,2); long n = brent_kung_optpow(get_F2x_degree(T)-1,lgpol(S)+1,1); GEN V = F2xq_powers(phi, n, T); GEN phi2 = F2x_F2xqV_eval(phi, V, T); GEN Sphi = F2xY_F2xqV_evalx(S, V, T); GEN S2 = F2xqX_F2xqXQ_eval(Sphi, S, D->S, T); return mkvec2(phi2, S2); } static GEN F2xqXQ_autpow_mul(void * E, GEN x, GEN y) { struct _F2xqXQ *D = (struct _F2xqXQ *)E; GEN T = D->T; GEN phi1 = gel(x,1), S1 = gel(x,2); GEN phi2 = gel(y,1), S2 = gel(y,2); long n = brent_kung_optpow(get_F2x_degree(T)-1,lgpol(S1)+1,1); GEN V = F2xq_powers(phi2, n, T); GEN phi3 = F2x_F2xqV_eval(phi1,V,T); GEN Sphi = F2xY_F2xqV_evalx(S1,V,T); GEN S3 = F2xqX_F2xqXQ_eval(Sphi, S2, D->S, T); return mkvec2(phi3, S3); } GEN F2xqXQ_autpow(GEN aut, long n, GEN S, GEN T) { struct _F2xqXQ D; D.T = F2x_get_red(T); D.S = F2xqX_get_red(S, T); return gen_powu(aut,n,&D,F2xqXQ_autpow_sqr,F2xqXQ_autpow_mul); } static GEN F2xqXQ_auttrace_mul(void *E, GEN x, GEN y) { struct _F2xqXQ *D = (struct _F2xqXQ *) E; GEN T = D->T; GEN phi1 = gel(x,1), S1 = gel(x,2), a1 = gel(x,3); GEN phi2 = gel(y,1), S2 = gel(y,2), a2 = gel(y,3); long n2 = brent_kung_optpow(get_F2x_degree(T)-1, lgpol(S1)+lgpol(a1)+1, 1); GEN V2 = F2xq_powers(phi2, n2, T); GEN phi3 = F2x_F2xqV_eval(phi1, V2, T); GEN Sphi = F2xY_F2xqV_evalx(S1, V2, T); GEN aphi = F2xY_F2xqV_evalx(a1, V2, T); long n = brent_kung_optpow(maxss(degpol(Sphi),degpol(aphi)),2,1); GEN V = F2xqXQ_powers(S2, n, D->S, T); GEN S3 = F2xqX_F2xqXQV_eval(Sphi, V, D->S, T); GEN aS = F2xqX_F2xqXQV_eval(aphi, V, D->S, T); GEN a3 = F2xX_add(aS, a2); return mkvec3(phi3, S3, a3); } static GEN F2xqXQ_auttrace_sqr(void *E, GEN x) { return F2xqXQ_auttrace_mul(E, x, x); } GEN F2xqXQ_auttrace(GEN aut, long n, GEN S, GEN T) { struct _F2xqXQ D; D.T = F2x_get_red(T); D.S = F2xqX_get_red(S, T); return gen_powu(aut,n,&D,F2xqXQ_auttrace_sqr,F2xqXQ_auttrace_mul); } GEN F2xqXQV_red(GEN x, GEN S, GEN T) { pari_APPLY_type(t_VEC, F2xqX_rem(gel(x,i), S, T)) } pari-2.17.2/src/basemath/prime.c0000644000175000017500000011140114760123736015026 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_isprime /*********************************************************************/ /** **/ /** PSEUDO PRIMALITY (MILLER-RABIN) **/ /** **/ /*********************************************************************/ typedef struct { GEN n, sqrt1, sqrt2, t1, t; long r1; } MR_Jaeschke_t; static void init_MR_Jaeschke(MR_Jaeschke_t *S, GEN n) { S->n = n = absi_shallow(n); S->t = subiu(n,1); 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); } /* is n strong pseudo-prime for base a ? 'End matching' (check for square * roots of -1): if ends do mismatch, then we have factored n, and this * information should be made available to the factoring machinery. But so * exceedingly rare... besides we use BSPW now. */ static int ispsp(MR_Jaeschke_t *S, ulong a) { pari_sp av = avma; GEN c = Fp_pow(utoipos(a), S->t1, S->n); long r; if (is_pm1(c) || equalii(S->t, c)) return 1; /* go fishing for -1, not for 1 (saves one squaring) */ for (r = S->r1 - 1; r; r--) /* r1 - 1 squarings */ { GEN c2 = c; c = remii(sqri(c), S->n); if (equalii(S->t, c)) { if (!signe(S->sqrt1)) { affii(subii(S->n, c2), S->sqrt2); affii(c2, S->sqrt1); return 1; } /* saw one earlier: too many sqrt(-1)s mod n ? */ return equalii(c2, S->sqrt1) || equalii(c2, S->sqrt2); } if (gc_needed(av,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"ispsp, r = %ld", r); c = gerepileuptoint(av, c); } } return 0; } /* is n > 0 strong pseudo-prime for base 2 ? Only used when lgefint(n) > 3, * so don't test */ static int is2psp(GEN n) { GEN c, t = subiu(n, 1); pari_sp av = avma; long e = vali(t); c = Fp_pow(gen_2, shifti(t, -e), n); if (is_pm1(c) || equalii(t, c)) return 1; while (--e) { /* go fishing for -1, not for 1 (e - 1 squaring) */ c = remii(sqri(c), n); if (equalii(t, c)) return 1; /* can return 0 if (c == 1) but very infrequent */ if (gc_needed(av,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"is2psp, r = %ld", e); c = gerepileuptoint(av, c); } } return 0; } static int uispsp_pre(ulong a, ulong n, ulong ni) { ulong c, t = n - 1; long e = vals(t); c = Fl_powu_pre(a, t >> e, n, ni); if (c == 1 || c == t) return 1; while (--e) { /* go fishing for -1, not for 1 (saves one squaring) */ c = Fl_sqr_pre(c, n, ni); if (c == t) return 1; /* can return 0 if (c == 1) but very infrequent */ } return 0; } int uispsp(ulong a, ulong n) { ulong c, t; long e; if (n & HIGHMASK) return uispsp_pre(a, n, get_Fl_red(n)); t = n - 1; e = vals(t); c = Fl_powu(a, t >> e, n); if (c == 1 || c == t) return 1; while (--e) { /* go fishing for -1, not for 1 (e - 1 squaring) */ c = Fl_sqr(c, n); if (c == t) return 1; /* can return 0 if (c == 1) but very infrequent */ } return 0; } int uis2psp(ulong n) { return uispsp(2, n); } /* Miller-Rabin test for k random bases */ long millerrabin(GEN n, long k) { pari_sp av2, av = avma; ulong r; long i; MR_Jaeschke_t S; if (typ(n) != t_INT) pari_err_TYPE("millerrabin",n); if (signe(n) <= 0) return 0; /* If |n| <= 3, check if n = +- 1 */ if (lgefint(n) == 3 && uel(n,2) <= 3) return uel(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 (!ispsp(&S, r)) return gc_long(av,0); set_avma(av2); } return gc_long(av,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); } int MR_Jaeschke(GEN n) { MR_Jaeschke_t S; pari_sp av; if (lgefint(n) == 3) return uisprime(uel(n,2)); if (!mod2(n)) return 0; av = avma; init_MR_Jaeschke(&S, n); return gc_int(av, ispsp(&S, 31) && ispsp(&S, 73)); } /*********************************************************************/ /** **/ /** 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; GEN nd = int_MSW(n); ulong m = *nd; long i, j; GEN v = utoipos(P), v1 = utoipos(P*P - 2); if (m == 1) j = 0; else { j = 1+bfffo(m); /* < BIL */ 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&HIGHBIT) { /* set v = v_{2k+1}, v1 = v_{2k+2} */ v = subiu(mulii(v,v1), P); v1= subiu(sqri(v1), 2); } else {/* set v = v_{2k}, v1 = v_{2k+1} */ v1= subiu(mulii(v,v1), P); v = subiu(sqri(v), 2); } v = modii(v, N); v1= modii(v1,N); if (gc_needed(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_pre(ulong n, ulong P, ulong N, ulong NI) { ulong v, v1, m; long j; if (n == 1) return P; j = 1 + bfffo(n); /* < BIL */ v = P; v1 = P*P - 2; m = n<>= v; z = u_LucasMod_pre(m, b, n, ni); if (z == 2 || z == n-2) return 1; for (i=1; i 3. Caller should check that N is not a square first (taken care of here, * but inefficient) */ static int islucaspsp(GEN N) { pari_sp av = avma; GEN m, z; long i, v; ulong b; for (b=3;; b+=2) { ulong c = b*b - 4; /* = 1 mod 4 */ if (b == 129 && Z_issquare(N)) return 0; /* avoid oo loop if N = m^2 */ if (krouu(umodiu(N,c), c) < 0) break; } m = addiu(N,1); v = vali(m); m = shifti(m,-v); z = LucasMod(m, b, N); if (absequaliu(z, 2)) return 1; if (equalii(z, subiu(N,2))) return 1; for (i=1; i1) pari_warn(warnmem,"islucaspsp"); z = gerepileupto(av, z); } } return 0; } /* composite strong 2-pseudoprime < 1016801 whose prime divisors are > 101. * All have a prime divisor <= 661 */ static int is_2_prp_101(ulong n) { switch(n) { case 42799: case 49141: case 88357: case 90751: case 104653: case 130561: case 196093: case 220729: case 253241: case 256999: case 271951: case 280601: case 357761: case 390937: case 458989: case 486737: case 489997: case 514447: case 580337: case 741751: case 838861: case 873181: case 877099: case 916327: case 976873: case 983401: return 1; } return 0; } static int _uispsp(ulong a, long n) { a %= n; return !a || uispsp(a, n); } static int _uisprime(ulong n) { #ifdef LONG_IS_64BIT ulong ni; if (n < 341531) return _uispsp(9345883071009581737UL, n); if (n < 1050535501) return _uispsp(336781006125UL, n) && _uispsp(9639812373923155UL, n); if (n < 350269456337) return _uispsp(4230279247111683200UL, n) && _uispsp(14694767155120705706UL, n) && _uispsp(16641139526367750375UL, n); /* n & HIGHMASK */ ni = get_Fl_red(n); return (uispsp_pre(2, n, ni) && uislucaspsp_pre(n,ni)); #else if (n < 360018361) return _uispsp(1143370UL, n) && _uispsp(2350307676UL, n); return uispsp(15, n) && uispsp(176006322UL, n) && _uispsp(4221622697UL, n); #endif } int uisprime(ulong n) { if (!odd(n)) return n == 2; if (n <= maxprimelim()) return PRIMES_search(n) > 0; /* gcd-extraction is much slower */ return n % 3 && n % 5 && n % 7 && n % 11 && n % 13 && n % 17 && n % 19 && n % 23 && n % 29 && n % 31 && n % 37 && n % 41 && _uisprime(n); } /* assume n <= maxprimelim() or no prime divisor <= 101 */ int uisprime_101(ulong n) { if (n <= maxprimelim()) return PRIMES_search(n) > 0; if (n < 1016801) return n < 10609? 1: (uispsp(2, n) && !is_2_prp_101(n)); return _uisprime(n); } /* assume n <= maxprimelim() or no prime divisor <= 661 */ int uisprime_661(ulong n) { if (n <= maxprimelim()) return PRIMES_search(n) > 0; if (n < 1016801) return n < 452929? 1: uispsp(2, n); return _uisprime(n); } static int iu_coprime(GEN N, ulong u) { return ugcd(u, umodiu(N,u)) == 1; } long BPSW_psp(GEN N) { pari_sp av; if (typ(N) != t_INT) pari_err_TYPE("BPSW_psp",N); if (signe(N) <= 0) return 0; if (lgefint(N) == 3) return uisprime(uel(N,2)); if (!mod2(N)) return 0; #ifdef LONG_IS_64BIT /* 16294579238595022365 = 3*5*7*11*13*17*19*23*29*31*37*41*43*47*53 * 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; return gc_long(av, is2psp(N) && islucaspsp(N)); } /* can we write n = x^k ? Assume N has no prime divisor <= 2^cutoff, else may * miss some powers. Not memory clean */ long Z_isanypower_nosmalldiv(GEN N, ulong cutoff, GEN *px) { GEN x = N, y; ulong mask = 7; long ex, k = 1; forprime_t T; while (Z_issquareall(x, &y)) { k <<= 1; x = y; } while ( (ex = is_357_power(x, &y, &mask)) ) { k *= ex; x = y; } (void)u_forprime_init(&T, 11, ULONG_MAX); /* stop when x^(1/k) < 2^cutoff */ while ( (ex = is_pth_power(x, &y, &T, cutoff)) ) { k *= ex; x = y; } *px = x; return k; } /* assume N has no prime divisor < 661. When N > 2^512, assume further * that it has no prime divisor < 2^14. */ long BPSW_psp_nosmalldiv(GEN N) { pari_sp av; long l = lgefint(N); if (l == 3) return uisprime_661(uel(N,2)); av = avma; /* N large: test for pure power, rarely succeeds, but requires < 1% of * compositeness test times */ if (bit_accuracy(l) > 512 && Z_isanypower_nosmalldiv(N, 15, &N) != 1) return gc_long(av,0); N = absi_shallow(N); return gc_long(av, is2psp(N) && islucaspsp(N)); } /***********************************************************************/ /** **/ /** 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 } /* Assume N > 1, p^e || N-1, p prime. Find a witness a(p) such that * a^(N-1) = 1 (mod N) * a^(N-1)/p - 1 invertible mod N. * Proves that any divisor of N is 1 mod p^e. Return 0 if N is composite */ static ulong pl831(GEN N, GEN p) { GEN b, c, g, Nmunp = diviiexact(subiu(N,1), p); pari_sp av = avma; ulong a; for(a = 2;; a++, set_avma(av)) { b = Fp_pow(utoipos(a), Nmunp, N); if (!equali1(b)) break; } c = Fp_pow(b,p,N); g = gcdii(subiu(b,1), N); /* 0 < g < N */ return (equali1(c) && equali1(g))? a: 0; } /* Brillhart, Lehmer, Selfridge test (Crandall & Pomerance, Th 4.1.5) * N^(1/3) <= f fully factored, f | N-1. If pl831(p) is true for * any prime divisor p of f, then any divisor of N is 1 mod f. * In that case return 1 iff N is prime */ static int BLS_test(GEN N, GEN f) { GEN c1, c2, r, q; q = dvmdii(N, f, &r); if (!is_pm1(r)) return 0; c2 = dvmdii(q, f, &c1); /* N = 1 + f c1 + f^2 c2, 0 <= c_i < f; check whether it is of the form * (1 + fa)(1 + fb) */ return ! Z_issquare(subii(sqri(c1), shifti(c2,2))); } /* BPSW_psp(N) && !BPSW_isprime_small(N). Decide between Pocklington-Lehmer * and APRCL/ECPP. Return a vector of (small) primes such that PL-witnesses * guarantee the primality of N. Return NULL if PL is likely too expensive. * Return gen_0 if BLS test finds N to be composite */ static GEN BPSW_try_PL(GEN N) { ulong B = minuu(1UL<<19, maxprime()); GEN E, p, U, F, N_1 = subiu(N,1); GEN fa = absZ_factor_limit_strict(N_1, B, &U), P = gel(fa,1); if (!U) return P; /* N-1 fully factored */ p = gel(U,1); E = gel(fa,2); U = powii(p, gel(U,2)); /* unfactored part of N-1 */ F = (lg(P) == 2)? powii(gel(P,1), gel(E,1)): diviiexact(N_1, U); /* N-1 = F U, F factored, U composite, (U,F) = 1 */ if (cmpii(F, U) > 0) return P; /* 1/2-smooth */ if (cmpii(sqri(F), U) > 0) return BLS_test(N,F)? P: gen_0; /* 1/3-smooth */ return NULL; /* not smooth enough */ } static GEN isprimePL(GEN N); /* F is a vector whose entries are primes. For each of them, find a PL * witness. Return 0 if caller lied and F contains a composite */ static long PL_certify(GEN N, GEN F) { long i, l = lg(F); for(i = 1; i < l; i++) if (! pl831(N, gel(F,i))) return 0; return 1; } /* F is a vector whose entries are *believed* to be primes (BPSW_psp). * For each of them, recording a witness and recursive primality certificate */ static GEN PL_certificate(GEN N, GEN F) { long i, l = lg(F); GEN C; if (BPSW_isprime_small(N)) return N; C = cgetg(l, t_VEC); for (i = 1; i < l; i++) { GEN p = gel(F,i), C0; ulong w; if (BPSW_isprime_small(p)) { gel(C,i) = p; continue; } w = pl831(N,p); if (!w) return gen_0; C0 = isprimePL(p); if (isintzero(C0)) { /* composite in prime factorisation ! */ err_printf("Not a prime: %Ps", p); pari_err_BUG("PL_certificate [false prime number]"); } gel(C,i) = mkvec3(p,utoipos(w), C0); } return mkvec2(N, C); } /* M a t_MAT */ static int PL_isvalid(GEN v) { GEN C, F, F2, N, N1, U; long i, l; switch(typ(v)) { case t_INT: return BPSW_isprime_small(v) && BPSW_psp(v); case t_VEC: if (lg(v) == 3) break;/*fall through */ default: return 0; } N = gel(v,1); C = gel(v,2); if (typ(N) != t_INT || signe(N) <= 0 || typ(C) != t_VEC) return 0; U = N1 = subiu(N,1); l = lg(C); for (i = 1; i < l; i++) { GEN p = gel(C,i), a = NULL, C0 = NULL, ap; long vp; if (typ(p) != t_INT) { if (lg(p) != 4) return 0; a = gel(p,2); C0 = gel(p,3); p = gel(p,1); if (typ(p) != t_INT || typ(a) != t_INT || !PL_isvalid(C0)) return 0; } vp = Z_pvalrem(U, p, &U); if (!vp) return 0; if (!a) { if (!BPSW_isprime_small(p)) return 0; continue; } if (!equalii(gel(C0,1), p)) return 0; ap = Fp_pow(a, diviiexact(N1,p), N); if (!equali1(gcdii(subiu(ap,1), N)) || !equali1(Fp_pow(ap, p, N))) return 0; } F = diviiexact(N1, U); /* factored part of N-1 */ F2= sqri(F); if (cmpii(F2, N) > 0) return 1; if (cmpii(mulii(F2,F), N) <= 0) return 0; return BLS_test(N,F); } /* Assume N is a strong BPSW pseudoprime, Pocklington-Lehmer primality proof. * Return gen_0 (nonprime), N (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] check_prime(a[i]) */ static GEN isprimePL(GEN N) { GEN cbrtN, N_1, F, f; if (BPSW_isprime_small(N)) return N; cbrtN = sqrtnint(N,3); N_1 = subiu(N,1); F = Z_factor_until(N_1, sqri(cbrtN)); f = factorback(F); /* factored part of N-1, f^3 > N */ if (DEBUGLEVEL>3) { GEN r = divri(itor(f,LOWDEFAULTPREC), N); err_printf("Pocklington-Lehmer: proving primality of N = %Ps\n", N); err_printf("Pocklington-Lehmer: N-1 factored up to %Ps! (%.3Ps%%)\n", f, r); } /* if N-1 is only N^(1/3)-smooth, BLS test */ if (!equalii(f,N_1) && cmpii(sqri(f),N) <= 0 && !BLS_test(N,f)) return gen_0; /* Failed, N is composite */ F = gel(F,1); settyp(F, t_VEC); return PL_certificate(N, F); } /* assume N a BPSW pseudoprime, in particular, it is odd > 2. Prove N prime */ long BPSW_isprime(GEN N) { pari_sp av; long t; GEN P; if (BPSW_isprime_small(N)) return 1; av = avma; P = BPSW_try_PL(N); if (!P) /* not smooth enough */ t = expi(N) < 768? isprimeAPRCL(N): isprimeECPP(N); else t = (typ(P) == t_INT)? 0: PL_certify(N,P); return gc_long(av,t); } static long _isprimePL(GEN x) { pari_sp av = avma; if (!BPSW_psp(x)) return 0; return gc_long(av, !isintzero(isprimePL(x))); } GEN gisprime(GEN x, long flag) { switch (flag) { case 0: return map_proto_lG(isprime,x); case 1: return map_proto_lG(_isprimePL,x); case 2: return map_proto_lG(isprimeAPRCL,x); case 3: return map_proto_lG(isprimeECPP,x); } pari_err_FLAG("gisprime"); return NULL;/*LCOV_EXCL_LINE*/ } long isprime(GEN x) { return BPSW_psp(x) && BPSW_isprime(x); } GEN primecert0(GEN x, long flag, long stopat) { if ((flag || typ(x) == t_INT) && !BPSW_psp(x)) return gen_0; switch(flag) { case 0: return ecpp0(x, stopat); case 1: { pari_sp av = avma; return gerepilecopy(av, isprimePL(x)); } } pari_err_FLAG("primecert"); return NULL;/*LCOV_EXCL_LINE*/ } GEN primecert(GEN x, long flag) { return primecert0(x, flag, 0); } enum { c_VOID = 0, c_ECPP, c_N1 }; static long cert_type(GEN c) { switch(typ(c)) { case t_INT: return c_ECPP; case t_VEC: if (lg(c) == 3 && typ(gel(c,1)) == t_INT) return c_N1; return c_ECPP; } return c_VOID; } long primecertisvalid(GEN c) { switch(typ(c)) { case t_INT: return BPSW_isprime_small(c) && BPSW_psp(c); case t_VEC: return cert_type(c) == c_ECPP? ecppisvalid(c): PL_isvalid(c); } return 0; } static long check_ecppcertentry(GEN c) { GEN v; long i,l = lg(c); if (typ(c)!=t_VEC || l!=6) return 0; for(i=1; i<=4; i++) if (typ(gel(c,i))!=t_INT) return 0; v = gel(c,5); if(typ(v)!=t_VEC) return 0; for(i=1; i<=2; i++) if (typ(gel(v,i))!=t_INT) return 0; return 1; } long check_ecppcert(GEN c) { long i, l; switch(typ(c)) { case t_INT: return signe(c) >= 0; case t_VEC: break; default: return 0; } l = lg(c); if (l == 1) return 0; for (i = 1; i < l; i++) if (check_ecppcertentry(gel(c,i))==0) return 0; return 1; } GEN primecertexport(GEN c, long flag) { if (cert_type(c) != c_ECPP) pari_err_IMPL("N-1 certificate"); if (!check_ecppcert(c)) pari_err_TYPE("primecertexport - invalid certificate", c); return ecppexport(c, flag); } /***********************************************************************/ /** **/ /** PRIME NUMBERS **/ /** **/ /***********************************************************************/ static struct { ulong p; long n; } prime_table[] = { { 0, 0}, { 7919, 1000}, { 17389, 2000}, { 27449, 3000}, { 37813, 4000}, { 48611, 5000}, { 59359, 6000}, { 70657, 7000}, { 81799, 8000}, { 93179, 9000}, { 104729, 10000}, { 224737, 20000}, { 350377, 30000}, { 479909, 40000}, { 611953, 50000}, { 746773, 60000}, { 882377, 70000}, { 1020379, 80000}, { 1159523, 90000}, { 1299709, 100000}, { 2750159, 200000}, { 7368787, 500000}, { 15485863, 1000000}, { 32452843, 2000000}, { 86028121, 5000000}, { 179424673, 10000000}, { 373587883, 20000000}, { 982451653, 50000000}, { 2038074743, 100000000}, { 4000000483UL,189961831}, { 4222234741UL,200000000}, #if BITS_IN_LONG == 64 { 5336500537UL, 250000000L}, { 6461335109UL, 300000000L}, { 7594955549UL, 350000000L}, { 8736028057UL, 400000000L}, { 9883692017UL, 450000000L}, { 11037271757UL, 500000000L}, { 13359555403UL, 600000000L}, { 15699342107UL, 700000000L}, { 18054236957UL, 800000000L}, { 20422213579UL, 900000000L}, { 22801763489UL, 1000000000L}, { 47055833459UL, 2000000000L}, { 71856445751UL, 3000000000L}, { 97011687217UL, 4000000000L}, {122430513841UL, 5000000000L}, {148059109201UL, 6000000000L}, {173862636221UL, 7000000000L}, {200000000507UL, 8007105083L}, {225898512559UL, 9000000000L}, {252097800623UL,10000000000L}, {384489816343UL,15000000000L}, {518649879439UL,20000000000L}, {654124187867UL,25000000000L}, {790645490053UL,30000000000L}, {928037044463UL,35000000000L}, {1066173339601UL,40000000000L}, {1344326694119UL,50000000000L}, {1624571841097UL,60000000000L}, {1906555030411UL,70000000000L}, {2190026988349UL,80000000000L}, {2474799787573UL,90000000000L}, {2760727302517UL,100000000000L} #endif }; static const int prime_table_len = numberof(prime_table); /* find prime closest to n in prime_table. */ static long prime_table_closest_p(ulong n) { long i; for (i = 1; i < prime_table_len; i++) { ulong p = prime_table[i].p; if (p > n) { ulong u = n - prime_table[i-1].p; if (p - n > u) i--; break; } } if (i == prime_table_len) i = prime_table_len - 1; return i; } /* return the n-th successor of prime p > 2; n > 0 */ static GEN prime_successor(ulong p, ulong n) { GEN Q = utoipos(p), P = NULL; ulong i; RESET: for(;;) { forprime_t S; GEN L = dbltor(4*n * log(gtodouble(Q) + 1)), R = addii(Q, ceil_safe(L)); forprime_init(&S, addiu(Q, 1), R); Q = R; for (i = 1; i <= n; i++) { P = forprime_next(&S); if (!P) { n -= i-1; goto RESET; } } return P; } } /* find the N-th prime */ static GEN prime_table_find_n(ulong N) { ulong n, p, maxp; long i; if (N <= (ulong)pari_PRIMES[0]) return utoipos((ulong)pari_PRIMES[N]); /* not in table */ for (i = 1; i < prime_table_len; i++) { n = prime_table[i].n; if (n > N) { ulong u = N - prime_table[i-1].n; if (n - N > u) i--; break; } } if (i == prime_table_len) i = prime_table_len - 1; p = prime_table[i].p; n = prime_table[i].n; if (n > N) { i--; p = prime_table[i].p; n = prime_table[i].n; } /* n <= N */ if (n == N) return utoipos(p); maxp = maxprime(); if (p < maxp) { p = maxp; n = pari_PRIMES[0]; } return prime_successor(p, N - n); } ulong uprime(long N) { pari_sp av = avma; GEN p; if (N <= 0) pari_err_DOMAIN("prime", "n", "<=",gen_0, stoi(N)); p = prime_table_find_n(N); if (lgefint(p) != 3) pari_err_OVERFLOW("uprime"); return gc_ulong(av, p[2]); } GEN prime(long N) { pari_sp av = avma; GEN p; if (N <= 0) pari_err_DOMAIN("prime", "n", "<=",gen_0, stoi(N)); new_chunk(4); /*HACK*/ p = prime_table_find_n(N); set_avma(av); return icopy(p); } /* N encodes an interval in which to draw a random uniform prime; * decoded as [a, b], d = b-a+1 */ static void prime_interval(GEN N, GEN *pa, GEN *pb, GEN *pd) { GEN a, b, d; switch(typ(N)) { case t_INT: a = gen_2; b = subiu(N,1); /* between 2 and N-1 */ d = subiu(N,2); if (signe(d) <= 0) pari_err_DOMAIN("randomprime","N", "<=", gen_2, N); break; case t_VEC: if (lg(N) != 3) pari_err_TYPE("randomprime",N); a = gel(N,1); b = gel(N,2); if (gcmp(b, a) < 0) pari_err_DOMAIN("randomprime","b-a", "<", gen_0, mkvec2(a,b)); if (typ(a) != t_INT) { a = gceil(a); if (typ(a) != t_INT) pari_err_TYPE("randomprime",a); } if (typ(b) != t_INT) { b = gfloor(b); if (typ(b) != t_INT) pari_err_TYPE("randomprime",b); } if (cmpiu(a, 2) < 0) { a = gen_2; d = subiu(b,1); } else d = addiu(subii(b,a), 1); if (signe(d) <= 0) pari_err_DOMAIN("randomprime","floor(b) - max(ceil(a),2)", "<", gen_0, mkvec2(a,b)); break; default: pari_err_TYPE("randomprime", N); a = b = d = NULL; /*LCOV_EXCL_LINE*/ } *pa = a; *pb = b; *pd = d; } /* random prime */ GEN randomprime(GEN N) { pari_sp av = avma, av2; GEN a, b, d; if (!N) for(;;) { ulong p = random_bits(31); if (uisprime(p)) return utoipos(p); } prime_interval(N, &a, &b, &d); av2 = avma; for (;;) { GEN p = addii(a, randomi(d)); if (BPSW_psp(p)) return gerepileuptoint(av, p); set_avma(av2); } } GEN randomprime0(GEN N, GEN q) { pari_sp av = avma, av2; GEN C, D, a, b, d, r; if (!q) return randomprime(N); switch(typ(q)) { case t_INT: C = gen_1; D = q; break; case t_INTMOD: C = gel(q,2); D = gel(q,1); break; default: pari_err_TYPE("randomprime", q); return NULL;/*LCOV_EXCL_LINE*/ } if (!N) N = int2n(31); prime_interval(N, &a, &b, &d); r = modii(subii(C, a), D); if (signe(r)) { a = addii(a, r); if (cmpii(a,b) > 0) pari_err(e_MISC, "no prime satisfies congruence in interval"); d = subii(d, r); } if (!equali1(gcdii(C,D))) { if (isprime(a)) return gerepilecopy(av, a); pari_err_COPRIME("randomprime", C, D); } d = divii(d, D); if (!signe(d)) d = gen_1; av2 = avma; for (;;) { GEN p = addii(a, mulii(D, randomi(d))); if (BPSW_psp(p)) return gerepileuptoint(av, p); set_avma(av2); } return NULL; } /* cf gen_search; assume 0 <= x <= maxprimelim(). Return i > 0 such that * x = T[i] or -i < 0 such that T[i-1] < x < T[i]; return -1 for the special * case 0 <= x < 2 */ long PRIMES_search(ulong x) { pari_prime *T = pari_PRIMES; ulong i, u = minuu(T[0], (x + 2) >> ((x < 122UL)? 1: 2)), l = 1; do { i = (l+u) >> 1; if (x < T[i]) u = i-1; else if (x > T[i]) l = i+1; else return i; } while (u > l); if (u == l) { i = l; if (x == T[i]) return i; } return -(long)(T[i] > x? i: i+1); } ulong uprimepi(ulong a) { ulong maxp, p, n; forprime_t S; long i; if (a <= maxprimelim()) { i = PRIMES_search(a); return (ulong)(i > 0? i: -i-1); } /* a > maxprimelim >= maxprime */ i = prime_table_closest_p(a); p = prime_table[i].p; if (p > a) p = prime_table[--i].p; /* p = largest prime in prime_table <= a and a > maxprime */ maxp = maxprime(); /* replace p by maxprime if larger */ if (p > maxp) n = prime_table[i].n; else { p = maxp; n = maxprimeN(); } (void)u_forprime_init(&S, p+1, a); for (; p; n++) p = u_forprime_next(&S); return n-1; } GEN primepi(GEN x) { pari_sp av = avma; GEN pp, nn, N = typ(x) == t_INT? x: gfloor(x); forprime_t S; ulong n, p; long i; if (typ(N) != t_INT) pari_err_TYPE("primepi",N); if (signe(N) <= 0) return gen_0; if (lgefint(N) == 3) return gc_utoi(av, uprimepi(N[2])); i = prime_table_len-1; p = prime_table[i].p; n = prime_table[i].n; (void)forprime_init(&S, utoipos(p+1), N); nn = setloop(utoipos(n)); pp = gen_0; for (; pp; incloop(nn)) pp = forprime_next(&S); return gerepileuptoint(av, subiu(nn,1)); } /* pi(x) < x/log x * (1 + 1/log x + 2.51/log^2 x)), x>=355991 [ Dusart ] * pi(x) < x/(log x - 1.1), x >= 60184 [ Dusart ] * ? \p9 * ? M = 0; for(x = 4, 60184, M = max(M, log(x) - x/primepi(x))); M * %1 = 1.11196252 */ double primepi_upper_bound(double x) { if (x >= 355991) { double L = 1/log(x); return x * L * (1 + L + 2.51*L*L); } if (x >= 60184) return x / (log(x) - 1.1); if (x < 5) return 2; /* don't bother */ return x / (log(x) - 1.111963); } /* pi(x) > x/log x (1 + 1/log x), x >= 599 [ Dusart ] * pi(x) > x / (log x + 2), x >= 55 [ Rosser ] */ double primepi_lower_bound(double x) { if (x >= 599) { double L = 1/log(x); return x * L * (1 + L); } if (x < 55) return 0; /* don't bother */ return x / (log(x) + 2.); } GEN gprimepi_upper_bound(GEN x) { pari_sp av = avma; double L; if (typ(x) != t_INT) x = gfloor(x); if (expi(x) <= 1022) { set_avma(av); return dbltor(primepi_upper_bound(gtodouble(x))); } x = itor(x, LOWDEFAULTPREC); L = 1 / rtodbl(logr_abs(x)); x = mulrr(x, dbltor(L * (1 + L + 2.51*L*L))); return gerepileuptoleaf(av, x); } GEN gprimepi_lower_bound(GEN x) { pari_sp av = avma; double L; if (typ(x) != t_INT) x = gfloor(x); if (abscmpiu(x, 55) <= 0) return gen_0; if (expi(x) <= 1022) { set_avma(av); return dbltor(primepi_lower_bound(gtodouble(x))); } x = itor(x, LOWDEFAULTPREC); L = 1 / rtodbl(logr_abs(x)); x = mulrr(x, dbltor(L * (1 + L))); return gerepileuptoleaf(av, x); } GEN primes(long n) { forprime_t S; long i; GEN y; if (n <= 0) return cgetg(1, t_VEC); y = cgetg(n+1, t_VEC); (void)new_chunk(3*n); /*HACK*/ u_forprime_init(&S, 2, (ulong)n > maxprimeN()? ULONG_MAX: maxprime()); set_avma((pari_sp)y); for (i = 1; i <= n; i++) gel(y, i) = utoipos( u_forprime_next(&S) ); return y; } GEN primes_zv(long n) { forprime_t S; long i; GEN y; if (n <= 0) return cgetg(1, t_VECSMALL); y = cgetg(n+1,t_VECSMALL); /* don't initialize sieve if all fits in primetable */ u_forprime_init(&S, 2, (ulong)n > maxprimeN()? ULONG_MAX: maxprime()); for (i = 1; i <= n; i++) y[i] = u_forprime_next(&S); set_avma((pari_sp)y); return y; } GEN primes0(GEN N) { switch(typ(N)) { case t_INT: return primes(itos(N)); case t_VEC: if (lg(N) == 3) return primes_interval(gel(N,1),gel(N,2)); } pari_err_TYPE("primes", N); return NULL;/*LCOV_EXCL_LINE*/ } GEN primes_interval(GEN a, GEN b) { pari_sp av = avma; forprime_t S; long i, n; GEN y, d, p; if (typ(a) != t_INT) { a = gceil(a); if (typ(a) != t_INT) pari_err_TYPE("primes_interval",a); } if (typ(b) != t_INT) { b = gfloor(b); if (typ(b) != t_INT) pari_err_TYPE("primes_interval",b); } if (signe(a) < 0) a = gen_2; d = subii(b, a); if (signe(d) < 0 || signe(b) <= 0) { set_avma(av); return cgetg(1, t_VEC); } if (lgefint(b) == 3) { set_avma(av); y = primes_interval_zv(itou(a), itou(b)); n = lg(y); settyp(y, t_VEC); for (i = 1; i < n; i++) gel(y,i) = utoipos(y[i]); return y; } /* at most d+1 primes in [a,b]. If d large, try better bound to lower * memory use */ if (abscmpiu(d,100000) > 0) { GEN D = gsub(gprimepi_upper_bound(b), gprimepi_lower_bound(a)); D = ceil_safe(D); if (cmpii(D, d) < 0) d = D; } n = itos(d)+1; forprime_init(&S, a, b); y = cgetg(n+1, t_VEC); i = 1; while ((p = forprime_next(&S))) gel(y, i++) = icopy(p); setlg(y, i); return gerepileupto(av, y); } /* simpler case a <= b <= maxprimelim() */ static GEN PRIMES_interval(ulong a, ulong b) { long k, i = PRIMES_search(a), j = PRIMES_search(b); GEN y; if (i < 0) i = -i; if (j < 0) j = -j - 1; /* T[i] = smallest p >= a, T[j] = largest p <= b */ y = cgetg(j - i + 2, t_VECSMALL); if (i == 1) for (; i <= j; i++) y[i] = pari_PRIMES[i]; else for (k = 1; i <= j; i++) y[k++] = pari_PRIMES[i]; return y; } /* a <= b, at most d primes in [a,b]. Return them. * PRIMES_interval is more efficient if b <= maxprimelim() */ static GEN primes_interval_i(ulong a, ulong b, ulong d) { ulong p, i = 1, n = d+1; GEN y = cgetg(n+1, t_VECSMALL); pari_sp av = avma; forprime_t S; u_forprime_init(&S, a, b); while ((p = u_forprime_next(&S))) y[i++] = p; set_avma(av); setlg(y, i); stackdummy((pari_sp)(y + i), (pari_sp)(y + n+1)); return y; } GEN primes_interval_zv(ulong a, ulong b) { ulong d; if (a < 3) return primes_upto_zv(b); if (b < a) return cgetg(1, t_VECSMALL); if (b <= maxprimelim()) return PRIMES_interval(a, b); d = b - a; if (d > 100000UL) { ulong D = (ulong)ceil(primepi_upper_bound(b)-primepi_lower_bound(a)); if (D < d) d = D; } return primes_interval_i(a, b, d); } GEN primes_upto_zv(ulong b) { ulong d; if (b < 2) return cgetg(1, t_VECSMALL); if (b <= maxprimelim()) return PRIMES_interval(2, b); d = (b > 100000UL)? (ulong)primepi_upper_bound(b): b; return primes_interval_i(2, b, d); } /***********************************************************************/ /** **/ /** PRIVATE PRIME TABLE **/ /** **/ /***********************************************************************/ void pari_set_primetab(GEN global_primetab) { if (global_primetab) { long i, l = lg(global_primetab); primetab = cgetg_block(l, t_VEC); for (i = 1; i < l; i++) gel(primetab,i) = gclone(gel(global_primetab,i)); } else primetab = cgetg_block(1, t_VEC); } /* delete dummy NULL entries */ static void cleanprimetab(GEN T) { long i,j, l = lg(T); for (i = j = 1; i < l; i++) if (T[i]) T[j++] = T[i]; setlg(T,j); } /* remove p from T */ static void rmprime(GEN T, GEN p) { long i; if (typ(p) != t_INT) pari_err_TYPE("removeprimes",p); i = ZV_search(T, p); if (!i) pari_err_DOMAIN("removeprimes","prime","not in", strtoGENstr("primetable"), p); gunclone(gel(T,i)); gel(T,i) = NULL; cleanprimetab(T); } /*stolen from ZV_union_shallow() : clone entries from y */ static GEN addp_union(GEN x, GEN y) { long i, j, k, lx = lg(x), ly = lg(y); GEN z = cgetg(lx + ly - 1, t_VEC); i = j = k = 1; while (i 0) gel(z,k++) = gclone(gel(y,j++)); else { gel(z,k++) = gel(x,i++); j++; } } while (i1; k++,l-=2) { av = avma; a = diviuuexact(muluui(l, l-1, a), 4*k, n-k); togglesign(a); a = gerepileuptoint(av, a); gel(r--,0) = a; gel(r--,0) = gen_0; } q[1] = evalsigne(1) | evalvarn(v); return q; } static void polchebyshev1_eval_aux(long n, GEN x, GEN *pt1, GEN *pt2) { GEN t1, t2, b; if (n == 1) { *pt1 = gen_1; *pt2 = x; return; } if (n == 0) { *pt1 = x; *pt2 = gen_1; return; } polchebyshev1_eval_aux((n+1) >> 1, x, &t1, &t2); b = gsub(gmul(gmul2n(t1,1), t2), x); if (odd(n)) { *pt1 = gadd(gmul2n(gsqr(t1), 1), gen_m1); *pt2 = b; } else { *pt1 = b; *pt2 = gadd(gmul2n(gsqr(t2), 1), gen_m1); } } static GEN polchebyshev1_eval(long n, GEN x) { GEN t1, t2; long i, v; pari_sp av; if (n < 0) n = -n; if (n==0) return gen_1; if (n==1) return gcopy(x); av = avma; v = u_lvalrem(n, 2, (ulong*)&n); polchebyshev1_eval_aux((n+1)>>1, x, &t1, &t2); if (n != 1) t2 = gsub(gmul(gmul2n(t1,1), t2), x); for (i = 1; i <= v; i++) t2 = gadd(gmul2n(gsqr(t2), 1), gen_m1); return gerepileupto(av, t2); } /* Chebychev polynomial of the second kind U(n,x): the coefficient in front of * x^(n-2*m) is (-1)^m * 2^(n-2m)*(n-m)!/m!/(n-2m)! for m=0,1,...,n/2 */ GEN polchebyshev2(long n, long v) { pari_sp av; GEN q, a, r; long m; int neg = 0; if (v<0) v = 0; /* polchebyshev(-n,2) = -polchebyshev(n-2,2) */ if (n < 0) { if (n == -1) return zeropol(v); neg = 1; n = -n-2; } if (n==0) return neg ? scalar_ZX_shallow(gen_m1, v): pol_1(v); q = cgetg(n+3, t_POL); r = q + n+2; a = int2n(n); if (neg) togglesign(a); gel(r--,0) = a; gel(r--,0) = gen_0; for (m=1; 2*m<= n; m++) { av = avma; a = diviuuexact(muluui(n-2*m+2, n-2*m+1, a), 4*m, n-m+1); togglesign(a); a = gerepileuptoint(av, a); gel(r--,0) = a; gel(r--,0) = gen_0; } q[1] = evalsigne(1) | evalvarn(v); return q; } static void polchebyshev2_eval_aux(long n, GEN x, GEN *pu1, GEN *pu2) { GEN u1, u2, u, mu1; if (n == 1) { *pu1 = gen_1; *pu2 = gmul2n(x,1); return; } if (n == 0) { *pu1 = gen_0; *pu2 = gen_1; return; } polchebyshev2_eval_aux(n >> 1, x, &u1, &u2); mu1 = gneg(u1); u = gmul(gadd(u2,u1), gadd(u2,mu1)); if (odd(n)) { *pu1 = u; *pu2 = gmul(gmul2n(u2,1), gadd(gmul(x,u2), mu1)); } else { *pu2 = u; *pu1 = gmul(gmul2n(u1,1), gadd(u2, gmul(x,mu1))); } } static GEN polchebyshev2_eval(long n, GEN x) { GEN u1, u2, mu1; long neg = 0; pari_sp av; if (n < 0) { if (n == -1) return gen_0; neg = 1; n = -n-2; } if (n==0) return neg ? gen_m1: gen_1; av = avma; polchebyshev2_eval_aux(n>>1, x, &u1, &u2); mu1 = gneg(u1); if (odd(n)) u2 = gmul(gmul2n(u2,1), gadd(gmul(x,u2), mu1)); else u2 = gmul(gadd(u2,u1), gadd(u2,mu1)); if (neg) u2 = gneg(u2); return gerepileupto(av, u2); } GEN polchebyshev(long n, long kind, long v) { switch (kind) { case 1: return polchebyshev1(n, v); case 2: return polchebyshev2(n, v); default: pari_err_FLAG("polchebyshev"); } return NULL; /* LCOV_EXCL_LINE */ } GEN polchebyshev_eval(long n, long kind, GEN x) { if (!x) return polchebyshev(n, kind, 0); if (gequalX(x)) return polchebyshev(n, kind, varn(x)); switch (kind) { case 1: return polchebyshev1_eval(n, x); case 2: return polchebyshev2_eval(n, x); default: pari_err_FLAG("polchebyshev"); } return NULL; /* LCOV_EXCL_LINE */ } /* 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) return pol_1(v); q = cgetg(n+3, t_POL); r = q + n+2; a = int2n(n); gel(r--,0) = a; gel(r--,0) = gen_0; for (m=1; 2*m<= n; m++) { av = avma; a = diviuexact(muluui(n-2*m+2, n-2*m+1, a), 4*m); togglesign(a); gel(r--,0) = a = gerepileuptoint(av, a); gel(r--,0) = gen_0; } q[1] = evalsigne(1) | evalvarn(v); return q; } static void err_hermite(long n) { pari_err_DOMAIN("polhermite", "degree", "<", gen_0, stoi(n)); } GEN polhermite_eval0(long n, GEN x, long flag) { long i; pari_sp av, av2; GEN x2, u, v; if (n < 0) err_hermite(n); if (!x || gequalX(x)) { long v = x? varn(x): 0; if (flag) { if (!n) err_hermite(-1); retmkvec2(polhermite(n-1,v),polhermite(n,v)); } return polhermite(n, v); } if (n==0) { if (flag) err_hermite(-1); return gen_1; } if (n==1) { if (flag) retmkvec2(gen_1, gmul2n(x,1)); return gmul2n(x,1); } av = avma; x2 = gmul2n(x,1); v = gen_1; u = x2; av2= avma; for (i=1; i1; k++,l-=2) { /* l = n-2*k+2 */ av = avma; a = diviuuexact(muluui(l, l-1, a), 2*k, n+l-1); togglesign(a); a = gerepileuptoint(av, a); gel(r--,0) = a; gel(r--,0) = gen_0; } q[1] = evalsigne(1) | evalvarn(v); return gerepileupto(av, gmul2n(q,-n)); } /* q such that Ln * 2^n = q(x^2) [n even] or x q(x^2) [n odd] */ GEN pollegendre_reduced(long n, long v) { long k, l, N; 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<=1) return n? scalarpol_shallow(gen_2,v): pol_1(v); N = n >> 1; q = cgetg(N+3, t_POL); r = q + N+2; gel(r--,0) = a = binomialuu(n<<1,n); for (k=1,l=n; l>1; k++,l-=2) { /* l = n-2*k+2 */ av = avma; a = diviuuexact(muluui(l, l-1, a), 2*k, n+l-1); togglesign(a); gel(r--,0) = a = gerepileuptoint(av, a); } q[1] = evalsigne(1) | evalvarn(v); return q; } GEN pollegendre_eval0(long n, GEN x, long flag) { pari_sp av; GEN u, v; long i; if (n < 0) n = -n-1; /* L(-n) = L(n-1) */ /* n >= 0 */ if (flag && flag != 1) pari_err_FLAG("pollegendre"); if (!x || gequalX(x)) { long v = x? varn(x): 0; if (flag) retmkvec2(pollegendre(n-1,v), pollegendre(n,v)); return pollegendre(n, v); } if (n==0) { if (flag) retmkvec2(gen_1, gcopy(x)); return gen_1; } if (n==1) { if (flag) retmkvec2(gcopy(x), gen_1); return gcopy(x); } av = avma; v = gen_1; u = x; for (i=1; i= 0; i--) { gel(L, i+2) = gdiv(c1, c2); if (i) { c2 = divis(c2,-i); c1 = gdivgu(gmul(c1, gaddsg(i,a)), n+1-i); } } return gerepilecopy(av, L); } static void err_lag(long n) { pari_err_DOMAIN("pollaguerre", "degree", "<", gen_0, stoi(n)); } GEN pollaguerre_eval0(long n, GEN a, GEN x, long flag) { pari_sp av = avma; long i; GEN v, u; if (n < 0) err_lag(n); if (flag && flag != 1) pari_err_FLAG("pollaguerre"); if (!a) a = gen_0; if (!x || gequalX(x)) { long v = x? varn(x): 0; if (flag) { if (!n) err_lag(-1); retmkvec2(pollaguerre(n-1,a,v), pollaguerre(n,a,v)); } return pollaguerre(n,a,v); } if (n==0) { if (flag) err_lag(-1); return gen_1; } if (n==1) { if (flag) retmkvec2(gsub(gaddgs(a,1),x), gen_1); return gsub(gaddgs(a,1),x); } av = avma; v = gen_1; u = gsub(gaddgs(a,1),x); for (i=1; i 1) { qpow = new_chunk(I+1); gel(qpow,2)=q; } for (j=3; j<=I; j++) gel(qpow,j) = gmul(q, gel(qpow,j-1)); } for (i=1; i<=n; i++) { I = (i+1)/2; gcoeff(m,i,1)= gen_1; if (q) { for (j=2; j<=I; j++) gcoeff(m,i,j) = gadd(gmul(gel(qpow,j),gcoeff(m,i-1,j)), gcoeff(m,i-1,j-1)); } else { for (j=2; j<=I; j++) gcoeff(m,i,j) = addii(gcoeff(m,i-1,j), gcoeff(m,i-1,j-1)); } for ( ; j<=i; j++) gcoeff(m,i,j) = gcoeff(m,i,i+1-j); for ( ; j<=n; j++) gcoeff(m,i,j) = gen_0; } return gerepilecopy(av, m); } GEN eulerianpol(long N, long v) { pari_sp av = avma; long n, n2, k = 0; GEN A; if (v < 0) v = 0; if (N < 0) pari_err_DOMAIN("eulerianpol", "index", "<", gen_0, stoi(N)); if (N <= 1) return pol_1(v); if (N == 2) return deg1pol_shallow(gen_1, gen_1, v); A = cgetg(N+1, t_VEC); gel(A,1) = gen_1; gel(A,2) = gen_1; /* A_2 = x+1 */ for (n = 3; n <= N; n++) { /* A(n,k) = (n-k)A(n-1,k-1) + (k+1)A(n-1,k) */ n2 = n >> 1; if (odd(n)) gel(A,n2+1) = mului(n+1, gel(A,n2)); for (k = n2-1; k; k--) gel(A,k+1) = addii(mului(n-k, gel(A,k)), mului(k+1, gel(A,k+1))); if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"eulerianpol, %ld/%ld",n,N); for (k = odd(n)? n2+1: n2; k < N; k++) gel(A,k+1) = gen_0; A = gerepilecopy(av, A); } } k = N >> 1; if (odd(N)) k++; for (; k < N; k++) gel(A,k+1) = gel(A, N-k); return gerepilecopy(av, RgV_to_RgX(A, v)); } /******************************************************************/ /** **/ /** PRECISION CHANGES **/ /** **/ /******************************************************************/ GEN gprec(GEN x, long d) { pari_sp av = avma; if (d <= 0) pari_err_DOMAIN("gprec", "precision", "<=", gen_0, stoi(d)); return gerepilecopy(av, gprec_w(x, ndec2prec(d))); } /* not GC-safe */ GEN gprec_w(GEN x, long pr) { long lx, i; GEN y; switch(typ(x)) { case t_REAL: if (signe(x)) return realprec(x) != pr? rtor(x,pr): x; i = -prec2nbits(pr); return real_0_bit(minss(i,expo(x))); case t_COMPLEX: y = cgetg(3, t_COMPLEX); gel(y,1) = gprec_w(gel(x,1),pr); gel(y,2) = gprec_w(gel(x,2),pr); break; case t_POL: case t_SER: 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; i1) pari_warn(warnmem,"dirmul, %ld/%ld",j,nx); z = gerepilecopy(av2,z); } } return gerepilecopy(av,z); } GEN dirdiv(GEN x, GEN y) { pari_sp av = avma, av2; long nx,ny,nz, dx,dy, i,j,k; GEN p1; if (typ(x)!=t_VEC) pari_err_TYPE("dirdiv",x); if (typ(y)!=t_VEC) pari_err_TYPE("dirdiv",y); dx = dirval(x); nx = lg(x)-1; dy = dirval(y); ny = lg(y)-1; if (dy != 1 || !ny) pari_err_INV("dirdiv",y); nz = minss(nx,ny*dx); p1 = gel(y,1); if (gequal1(p1)) p1 = NULL; else y = gdiv(y,p1); y = RgV_kill0(y); av2 = avma; x = p1 ? gdiv(x,p1): leafcopy(x); for (j=1; j1) pari_warn(warnmem,"dirdiv, %ld/%ld",j,nz); x = gerepilecopy(av2,x); } } return gerepilecopy(av,x); } /*******************************************************************/ /** **/ /** COMBINATORICS **/ /** **/ /*******************************************************************/ /** BINOMIAL COEFFICIENTS **/ /*******************************************************************/ /* Lucas's formula for v_p(\binom{n}{k}), used in the tough case p <= sqrt(n) */ static long binomial_lval(ulong n, ulong k, ulong p) { ulong r = 0, e = 0; do { ulong a = n % p, b = k % p + r; n /= p; k /= p; if (a < b) { e++; r = 1; } else r = 0; } while (n); return e; } GEN binomialuu(ulong n, ulong k) { pari_sp av = avma; ulong p, nk, sn; long c, l; forprime_t T; GEN v, z; if (k > n) return gen_0; nk = n-k; if (k > nk) lswap(nk, k); if (!k) return gen_1; if (k == 1) return utoipos(n); if (k == 2) return muluu(odd(n)? n: n-1, n>>1); if (k < 1000 || ((double)k/ n) * log((double)n) < 0.5) { /* k "small" */ z = diviiexact(mulu_interval(n-k+1, n), mulu_interval(2UL, k)); return gerepileuptoint(av, z); } sn = usqrt(n); /* use Lucas's formula, k <= n/2 */ l = minuu(1UL << 20, n); v = cgetg(l+1, t_VECSMALL); c = 1; u_forprime_init(&T, nk+1, n); while ((p = u_forprime_next(&T))) /* all primes n-k < p <= n occur, v_p = 1 */ { if (c == l) { ulong L = l << 1; v = vecsmall_lengthen(v, L); l = L; } v[c++] = p; } u_forprime_init(&T, sn+1, n >> 1); while ((p = u_forprime_next(&T))) /* p^2 > n, v_p <= 1 */ if (n % p < k % p) { if (c == l) { ulong L = l << 1; v = vecsmall_lengthen(v, L); l = L; } v[c++] = p; } setlg(v, c); z = zv_prod_Z(v); u_forprime_init(&T, 3, sn); l = minuu(1UL << 20, sn); v = cgetg(l + 1, t_VEC); c = 1; while ((p = u_forprime_next(&T))) /* p <= sqrt(n) */ { ulong e = binomial_lval(n, k, p); if (e) { if (c == l) { ulong L = l << 1; v = vec_lengthen(v, L); l = L; } gel(v, c++) = powuu(p, e); } } setlg(v, c); z = mulii(z, ZV_prod(v)); { /* p = 2 */ ulong e = hammingl(k); e += (k == nk)? e: hammingl(nk); e -= hammingl(n); if (e) z = shifti(z, e); } return gerepileuptoint(av, z); } GEN binomial(GEN n, long k) { long i, prec, tn = typ(n); pari_sp av; GEN y; av = avma; if (tn == t_INT) { long sn; GEN z; if (k == 0) return gen_1; sn = signe(n); if (sn == 0) return gen_0; /* k != 0 */ if (sn > 0) { /* n > 0 */ if (k < 0) return gen_0; if (k == 1) return icopy(n); z = subiu(n, k); if (cmpiu(z, k) < 0) { switch(signe(z)) { case -1: return gc_const(av, gen_0); case 0: return gc_const(av, gen_1); } k = z[2]; if (k == 1) { set_avma(av); return icopy(n); } } set_avma(av); if (lgefint(n) == 3) return binomialuu(n[2],(ulong)k); } else { /* n < 0, k != 0; use Kronenburg's definition */ if (k > 0) z = binomial(subsi(k - 1, n), k); else { z = subis(n, k); if (signe(z) < 0) return gen_0; n = stoi(-k-1); k = itos(z); z = binomial(n, k); } if (odd(k)) togglesign_safe(&z); return gerepileuptoint(av, z); } /* n >= 0 and huge, k != 0 */ if (k < 0) return gen_0; if (k == 1) return icopy(n); /* k > 1 */ y = cgetg(k+1,t_VEC); gel(y,1) = n; for (i = 2; i <= k; i++) gel(y,i) = subiu(n,i-1); y = diviiexact(ZV_prod(y), mpfact(k)); return gerepileuptoint(av, y); } if (is_noncalc_t(tn)) pari_err_TYPE("binomial",n); if (k <= 1) { if (k < 0) return Rg_get_0(n); if (k == 0) return Rg_get_1(n); return gcopy(n); } prec = precision(n); if (prec && k > 200 + 0.8*prec2nbits(prec)) { GEN A = mpfactr(k, prec), B = ggamma(gsubgs(n,k-1), prec); return gerepileupto(av, gdiv(ggamma(gaddgs(n,1), prec), gmul(A,B))); } y = cgetg(k+1,t_VEC); for (i=1; i<=k; i++) gel(y,i) = gsubgs(n,i-1); return gerepileupto(av, gdiv(RgV_prod(y), mpfact(k))); } GEN binomial0(GEN x, GEN k) { if (!k) { if (typ(x) != t_INT || signe(x) < 0) pari_err_TYPE("binomial", x); return vecbinomial(itos(x)); } if (typ(k) != t_INT) pari_err_TYPE("binomial", k); return binomial(x, itos(k)); } /* Assume n >= 0, return bin, bin[k+1] = binomial(n, k) */ GEN vecbinomial(long n) { long d, k; GEN C; if (!n) return mkvec(gen_1); C = cgetg(n+2, t_VEC) + 1; /* C[k] = binomial(n, k) */ gel(C,0) = gen_1; gel(C,1) = utoipos(n); d = (n + 1) >> 1; for (k=2; k <= d; k++) { pari_sp av = avma; gel(C,k) = gerepileuptoint(av, diviuexact(mului(n-k+1, gel(C,k-1)), k)); } for ( ; k <= n; k++) gel(C,k) = gel(C,n-k); return C - 1; } /********************************************************************/ /** STIRLING NUMBERS **/ /********************************************************************/ /* Stirling number of the 2nd kind. The number of ways of partitioning a set of n elements into m nonempty subsets. */ GEN stirling2(ulong n, ulong m) { pari_sp av = avma; 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 (gc_needed(av,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"stirling2"); gerepileall(av, 2, &s, &bmk); } } /* k = m/2 */ if (!odd(m)) { GEN c; bmk = diviuexact(mului(k+1, bmk), k); c = mulii(bmk, powuu(k,n)); s = odd(k)? subii(s, c): addii(s, c); } return gerepileuptoint(av, diviiexact(s, mpfact(m))); } /* Stirling number of the first kind. Up to the sign, the number of permutations of n symbols which have exactly m cycles. */ GEN stirling1(ulong n, ulong m) { pari_sp ltop=avma; ulong k; GEN s, t; if (n < m) return gen_0; else if (n==m) return gen_1; /* t = binomial(n-1+k, m-1) * binomial(2n-m, n-m-k) */ /* k = n-m > 0 */ t = binomialuu(2*n-m-1, m-1); s = mulii(t, stirling2(2*(n-m), n-m)); if (odd(n-m)) togglesign(s); for (k = n-m-1; k > 0; --k) { GEN c; t = diviuuexact(muluui(n-m+k+1, n+k+1, t), n+k, n-m-k); c = mulii(t, stirling2(n-m+k, k)); s = odd(k)? subii(s, c): addii(s, c); if ((k & 0x1f) == 0) { t = gerepileuptoint(ltop, t); s = gerepileuptoint(avma, s); } } return gerepileuptoint(ltop, s); } GEN stirling(long n, long m, long flag) { if (n < 0) pari_err_DOMAIN("stirling", "n", "<", gen_0, stoi(n)); if (m < 0) pari_err_DOMAIN("stirling", "m", "<", gen_0, stoi(m)); switch (flag) { case 1: return stirling1((ulong)n,(ulong)m); case 2: return stirling2((ulong)n,(ulong)m); default: pari_err_FLAG("stirling"); } return NULL; /*LCOV_EXCL_LINE*/ } /*******************************************************************/ /** **/ /** RECIPROCAL POLYNOMIAL **/ /** **/ /*******************************************************************/ /* return coefficients s.t x = x_0 X^n + ... + x_n */ GEN polrecip(GEN x) { long tx = typ(x); if (is_scalar_t(tx)) return gcopy(x); if (tx != t_POL) pari_err_TYPE("polrecip",x); return RgX_recip(x); } /********************************************************************/ /** **/ /** POLYNOMIAL INTERPOLATION **/ /** **/ /********************************************************************/ /* given complex roots L[i], i <= n of some monic T in C[X], return * the T'(L[i]), computed stably via products of differences */ GEN vandermondeinverseinit(GEN L) { long i, j, l = lg(L); GEN V = cgetg(l, t_VEC); for (i = 1; i < l; i++) { pari_sp av = avma; GEN W = cgetg(l-1,t_VEC); long k = 1; for (j = 1; j < l; j++) if (i != j) gel(W, k++) = gsub(gel(L,i), gel(L,j)); gel(V,i) = gerepileupto(av, RgV_prod(W)); } 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 V) { pari_sp av = avma; long i, n = lg(L)-1; GEN M = cgetg(n+1, t_MAT); if (!V) V = vandermondeinverseinit(L); if (den && equali1(den)) den = NULL; for (i = 1; i <= n; i++) { GEN d = gel(V,i), P = RgX_Rg_mul(RgX_div_by_X_x(T, gel(L,i), NULL), den? gdiv(den,d): ginv(d)); gel(M,i) = RgX_to_RgC(P, n); } return gerepilecopy(av, M); } static GEN RgV_polint_fast(GEN X, GEN Y, long v) { GEN p, pol; long t, pa; if (X) t = RgV_type2(X,Y, &p, &pol, &pa); else t = Rg_type(Y, &p, &pol, &pa); if (t != t_INTMOD) return NULL; Y = RgC_to_FpC(Y, p); X = X? RgC_to_FpC(X, p): identity_ZV(lg(Y)-1); return FpX_to_mod(FpV_polint(X, Y, p, v), p); } /* allow X = NULL for [1,...,n] */ GEN RgV_polint(GEN X, GEN Y, long v) { pari_sp av0 = avma, av; GEN Q, L, P = NULL; long i, l = lg(Y); if ((Q = RgV_polint_fast(X,Y,v))) return Q; if (!X) X = identity_ZV(l-1); L = vandermondeinverseinit(X); Q = roots_to_pol(X, v); av = avma; for (i=1; i1) pari_warn(warnmem,"RgV_polint i = %ld/%ld", i, l-1); P = gerepileupto(av, P); } } if (!P) { set_avma(av); return zeropol(v); } return gerepileupto(av0, P); } static int inC(GEN x) { switch(typ(x)) { case t_INT: case t_REAL: case t_FRAC: case t_COMPLEX: case t_QUAD: return 1; default: return 0; } } static long check_dy(GEN X, GEN x, long n) { GEN D = NULL; long i, ns = 0; if (!inC(x)) return -1; for (i = 0; i < n; i++) { GEN t = gsub(x, gel(X,i)); if (!inC(t)) return -1; t = gabs(t, DEFAULTPREC); if (!D || gcmp(t,D) < 0) { ns = i; D = t; } } /* X[ns] is closest to x */ return ns; } /* X,Y are "spec" GEN vectors with n > 0 components ( at X[0], ... X[n-1] ) */ GEN polintspec(GEN X, GEN Y, GEN x, long n, long *pe) { long i, m, ns; pari_sp av = avma, av2; GEN y, c, d, dy = NULL; /* gcc -Wall */ if (pe) *pe = -HIGHEXPOBIT; if (n == 1) return gmul(gel(Y,0), Rg_get_1(x)); if (!X) X = identity_ZV(n) + 1; av2 = avma; ns = check_dy(X, x, n); if (ns < 0) { pe = NULL; ns = 0; } c = cgetg(n+1, t_VEC); d = cgetg(n+1, t_VEC); for (i=0; i 0 && (!t || gequalX(t))) return RgV_polint(X, Y, vt); av = avma; /* first interpolate in high priority variable, then substitute t */ v0 = fetch_var_higher(); P = RgV_polint(X, Y, v0); P = gsubst(P, v0, t? t: pol_x(0)); (void)delete_var(); return gerepileupto(av, P); } /* numerical interpolation */ if (lx == 1) return Rg_get_0(t); return polintspec(X? X+1: NULL,Y+1,t,lx-1, pe); } GEN polint(GEN X, GEN Y, GEN t, GEN *pe) { long e; GEN p = polint_i(X, Y, t, &e); if (pe) *pe = stoi(e); return p; } /********************************************************************/ /** **/ /** MODREVERSE **/ /** **/ /********************************************************************/ static void err_reverse(GEN x, GEN T) { pari_err_DOMAIN("modreverse","deg(minpoly(z))", "<", stoi(degpol(T)), mkpolmod(x,T)); } /* return y such that Mod(y, charpoly(Mod(a,T)) = Mod(a,T) */ GEN RgXQ_reverse(GEN a, GEN T) { pari_sp av = avma; long n = degpol(T); GEN y; if (n <= 1) { if (n <= 0) return gcopy(a); return gerepileupto(av, gneg(gdiv(gel(T,2), gel(T,3)))); } if (typ(a) != t_POL || !signe(a)) err_reverse(a,T); y = RgXV_to_RgM(RgXQ_powers(a,n-1,T), n); y = RgM_solve(y, col_ei(n, 2)); if (!y) err_reverse(a,T); return gerepilecopy(av, RgV_to_RgX(y, varn(T))); } GEN QXQ_reverse(GEN a, GEN T) { pari_sp av = avma; long n = degpol(T); GEN y; if (n <= 1) { if (n <= 0) return gcopy(a); return gerepileupto(av, gneg(gdiv(gel(T,2), gel(T,3)))); } if (typ(a) != t_POL || !signe(a)) err_reverse(a,T); if (gequalX(a)) return gcopy(a); y = RgXV_to_RgM(QXQ_powers(a,n-1,T), n); y = QM_gauss(y, col_ei(n, 2)); if (!y) err_reverse(a,T); return gerepilecopy(av, RgV_to_RgX(y, varn(T))); } GEN modreverse(GEN x) { long v, n; GEN T, a; if (typ(x)!=t_POLMOD) pari_err_TYPE("modreverse",x); T = gel(x,1); n = degpol(T); if (n <= 0) return gcopy(x); a = gel(x,2); v = varn(T); retmkpolmod(RgXQ_reverse(a, T), (n==1)? gsub(pol_x(v), a): RgXQ_charpoly(a, T, v)); } /********************************************************************/ /** **/ /** MERGESORT **/ /** **/ /********************************************************************/ static int cmp_small(GEN x, GEN y) { long a = (long)x, b = (long)y; return a>b? 1: (a= lx) pari_err_TYPE("lexicographic vecsort, index too large", stoi(c)); s = lexcmp(gel(x,c), gel(y,c)); if (s) return s; } return 0; } /* return permutation sorting v[1..n], removing duplicates. Assume n > 0 */ static GEN gen_sortspec_uniq(GEN v, long n, void *E, int (*cmp)(void*,GEN,GEN)) { pari_sp av; long NX, nx, ny, m, ix, iy, i; GEN x, y, w, W; int s; switch(n) { case 1: return mkvecsmall(1); case 2: s = cmp(E,gel(v,1),gel(v,2)); if (s < 0) return mkvecsmall2(1,2); else if (s > 0) return mkvecsmall2(2,1); return mkvecsmall(1); case 3: s = cmp(E,gel(v,1),gel(v,2)); if (s < 0) { s = cmp(E,gel(v,2),gel(v,3)); if (s < 0) return mkvecsmall3(1,2,3); else if (s == 0) return mkvecsmall2(1,2); s = cmp(E,gel(v,1),gel(v,3)); if (s < 0) return mkvecsmall3(1,3,2); else if (s > 0) return mkvecsmall3(3,1,2); return mkvecsmall2(1,2); } else if (s > 0) { s = cmp(E,gel(v,1),gel(v,3)); if (s < 0) return mkvecsmall3(2,1,3); else if (s == 0) return mkvecsmall2(2,1); s = cmp(E,gel(v,2),gel(v,3)); if (s < 0) return mkvecsmall3(2,3,1); else if (s > 0) return mkvecsmall3(3,2,1); return mkvecsmall2(2,1); } else { s = cmp(E,gel(v,1),gel(v,3)); if (s < 0) return mkvecsmall2(1,3); else if (s == 0) return mkvecsmall(1); return mkvecsmall2(3,1); } } NX = nx = n>>1; ny = n-nx; av = avma; x = gen_sortspec_uniq(v, nx,E,cmp); nx = lg(x)-1; y = gen_sortspec_uniq(v+NX,ny,E,cmp); ny = lg(y)-1; w = cgetg(n+1, t_VECSMALL); m = ix = iy = 1; while (ix<=nx && iy<=ny) { s = cmp(E, gel(v,x[ix]), gel(v,y[iy]+NX)); if (s < 0) w[m++] = x[ix++]; else if (s > 0) w[m++] = y[iy++]+NX; else { w[m++] = x[ix++]; iy++; } } while (ix<=nx) w[m++] = x[ix++]; while (iy<=ny) w[m++] = y[iy++]+NX; set_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; set_avma((pari_sp)w); return w; } static void init_sort(GEN *x, long *tx, long *lx) { *tx = typ(*x); if (*tx == t_LIST) { if (list_typ(*x)!=t_LIST_RAW) pari_err_TYPE("sort",*x); *x = list_data(*x); *lx = *x? lg(*x): 1; } else { if (!is_matvec_t(*tx) && *tx != t_VECSMALL) pari_err_TYPE("gen_sort",*x); *lx = lg(*x); } } /* (x o y)[1..lx-1], destroy y */ INLINE GEN sort_extract(GEN x, GEN y, long tx, long lx) { long i; switch(tx) { case t_VECSMALL: for (i=1; i (cmp_REV|cmp_LEX|cmp_IND|cmp_UNIQ)) pari_err_FLAG("vecsort"); if (!CMP) { /* wrt key: precompute all values, O(n) calls instead of O(n log n) */ pari_sp av = avma; GEN v, y; long i, tx, lx; init_sort(&x, &tx, &lx); if (lx == 1) return flag&cmp_IND? cgetg(1,t_VECSMALL): triv_sort(tx); v = cgetg(lx, t_VEC); for (i = 1; i < lx; i++) gel(v,i) = closure_callgen1(k, gel(x,i)); y = vecsort0(v, NULL, flag | cmp_IND); y = flag&cmp_IND? y: sort_extract(x, y, tx, lg(y)); return gerepileupto(av, y); } if (flag&cmp_UNIQ) x = flag&cmp_IND? gen_indexsort_uniq(x, E, CMP): gen_sort_uniq(x, E, CMP); else x = flag&cmp_IND? gen_indexsort(x, E, CMP): gen_sort(x, E, CMP); if (flag & cmp_REV) { /* reverse order */ GEN y = x; if (typ(x)==t_LIST) { y = list_data(x); if (!y) return x; } vecreverse_inplace(y); } return x; } GEN indexsort(GEN x) { return gen_indexsort(x, (void*)&gcmp, cmp_nodata); } GEN indexlexsort(GEN x) { return gen_indexsort(x, (void*)&lexcmp, cmp_nodata); } GEN indexvecsort(GEN x, GEN k) { if (typ(k) != t_VECSMALL) pari_err_TYPE("vecsort",k); return gen_indexsort(x, (void*)k, &veccmp); } GEN sort(GEN x) { return gen_sort(x, (void*)gcmp, cmp_nodata); } GEN lexsort(GEN x) { return gen_sort(x, (void*)lexcmp, cmp_nodata); } GEN vecsort(GEN x, GEN k) { if (typ(k) != t_VECSMALL) pari_err_TYPE("vecsort",k); return gen_sort(x, (void*)k, &veccmp); } /* adapted from gen_search; don't export: keys of T[i] should be precomputed */ static long key_search(GEN T, GEN x, GEN code) { long u = lg(T)-1, i, l, s; if (!u) return 0; l = 1; x = closure_callgen1(code, x); do { i = (l+u)>>1; s = lexcmp(x, closure_callgen1(code, gel(T,i))); if (!s) return i; if (s<0) u=i-1; else l=i+1; } while (u>=l); return 0; } long vecsearch(GEN v, GEN x, GEN k) { pari_sp av = avma; long r; void *E; int (*CMP)(void*,GEN,GEN) = sort_function(&E, v, k); switch(typ(v)) { case t_VECSMALL: x = (GEN)itos(x); break; case t_VEC: case t_COL: break; case t_LIST: if (list_typ(v)==t_LIST_RAW) { v = list_data(v); if (!v) v = cgetg(1, t_VEC); break; } /* fall through */ default: pari_err_TYPE("vecsearch", v); } r = CMP? gen_search(v, x, E, CMP): key_search(v, x, k); return gc_long(av, r < 0? 0: r); } GEN ZV_indexsort(GEN L) { return gen_indexsort(L, (void*)&cmpii, &cmp_nodata); } GEN ZV_sort(GEN L) { return gen_sort(L, (void*)&cmpii, &cmp_nodata); } GEN ZV_sort_uniq(GEN L) { return gen_sort_uniq(L, (void*)&cmpii, &cmp_nodata); } void ZV_sort_inplace(GEN L) { gen_sort_inplace(L, (void*)&cmpii, &cmp_nodata,NULL); } GEN ZV_sort_uniq_shallow(GEN L) { GEN v = gen_indexsort_uniq(L, (void*)&cmpii, &cmp_nodata); return vecpermute(L, v); } GEN ZV_sort_shallow(GEN L) { GEN v = gen_indexsort(L, (void*)&cmpii, &cmp_nodata); return vecpermute(L, v); } GEN vec_equiv(GEN F) { pari_sp av = avma; long j, k, L = lg(F); GEN w = cgetg(L, t_VEC); GEN perm = gen_indexsort(F, (void*)&cmp_universal, cmp_nodata); for (j = k = 1; j < L;) { GEN v = cgetg(L, t_VECSMALL); long l = 1, o = perm[j]; v[l++] = o; for (j++; j < L; v[l++] = perm[j++]) if (!gequal(gel(F,o), gel(F, perm[j]))) break; setlg(v, l); gel(w, k++) = v; } setlg(w, k); return gerepilecopy(av,w); } GEN vec_reduce(GEN v, GEN *pE) { GEN E, F, P = gen_indexsort(v, (void*)cmp_universal, cmp_nodata); long i, m, l; F = cgetg_copy(v, &l); *pE = E = cgetg(l, t_VECSMALL); for (i = m = 1; i < l;) { GEN u = gel(v, P[i]); long k; for(k = i + 1; k < l; k++) if (cmp_universal(gel(v, P[k]), u)) break; E[m] = k - i; gel(F, m) = u; i = k; m++; } setlg(F, m); setlg(E, m); return F; } /********************************************************************/ /** 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, void *data, int (*cmp)(void*,GEN,GEN)) { long u = lg(T)-1, i, l, s; if (!u) return -1; l = 1; do { i = (l+u) >> 1; s = cmp(data, x, gel(T,i)); if (!s) return i; if (s < 0) u = i-1; else l = i+1; } while (u >= l); return -((s < 0)? i: i+1); } long ZV_search(GEN x, GEN y) { return tablesearch(x, y, cmpii); } long zv_search(GEN T, long x) { long l = 1, u = lg(T)-1; while (u>=l) { long i = (l+u)>>1; if (x < T[i]) u = i-1; else if (x > T[i]) l = i+1; else return i; } return 0; } /********************************************************************/ /** COMPARISON FUNCTIONS **/ /********************************************************************/ int cmp_nodata(void *data, GEN x, GEN y) { int (*cmp)(GEN,GEN)=(int (*)(GEN,GEN)) data; return cmp(x,y); } /* assume x and y come from the same idealprimedec call (uniformizer unique) */ int cmp_prime_over_p(GEN x, GEN y) { long k = pr_get_f(x) - pr_get_f(y); /* diff. between residue degree */ return k? ((k > 0)? 1: -1) : ZV_cmp(pr_get_gen(x), pr_get_gen(y)); } int cmp_prime_ideal(GEN x, GEN y) { int k = cmpii(pr_get_p(x), pr_get_p(y)); return k? k: cmp_prime_over_p(x,y); } /* assume x and y are t_POL in the same variable whose coeffs can be * compared (used to sort polynomial factorizations) */ int gen_cmp_RgX(void *data, GEN x, GEN y) { int (*coeff_cmp)(GEN,GEN)=(int(*)(GEN,GEN))data; long i, lx = lg(x), ly = lg(y); int fl; if (lx > ly) return 1; if (lx < ly) return -1; for (i=lx-1; i>1; i--) if ((fl = coeff_cmp(gel(x,i), gel(y,i)))) return fl; return 0; } static int cmp_RgX_Rg(GEN x, GEN y) { long lx = lgpol(x), ly; if (lx > 1) return 1; ly = gequal0(y) ? 0:1; if (lx > ly) return 1; if (lx < ly) return -1; if (lx==0) return 0; 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); } int cmp_Flx(GEN x, GEN y) { long i, lx = lg(x), ly = lg(y); if (lx > ly) return 1; if (lx < ly) return -1; for (i=lx-1; i>1; i--) if (uel(x,i) != uel(y,i)) return uel(x,i) 0) gel(z,k++) = gel(y,j++); else { gel(z,k++) = gel(x,i++); j++; } } while (i 0) gel(z,k++) = gel(y,j++); else { gel(z,k++) = gel(x,i++); j++; } } while (i < lx) gel(z,k++) = gel(x,i++); while (j < ly) gel(z,k++) = gel(y,j++); setlg(z, k); return z; } GEN ZV_union_shallow(GEN x, GEN y) { return ZV_union_shallow_t(x, y, t_VEC); } GEN ZC_union_shallow(GEN x, GEN y) { return ZV_union_shallow_t(x, y, t_COL); } /* sort generic factorization, in place */ GEN sort_factor(GEN y, void *data, int (*cmp)(void *,GEN,GEN)) { GEN a, b, A, B, w; pari_sp av; long n, i; a = gel(y,1); n = lg(a); if (n == 1) return y; b = gel(y,2); av = avma; A = new_chunk(n); B = new_chunk(n); w = gen_sortspec(a, n-1, data, cmp); for (i=1; i 0) return flag? 0: i; return flag ? -i: 0; } GEN setunion_i(GEN x, GEN y) { return merge_sort_uniq(x,y, (void*)cmp_universal, cmp_nodata); } GEN setunion(GEN x, GEN y) { pari_sp av = avma; if (typ(x) != t_VEC) pari_err_TYPE("setunion",x); if (typ(y) != t_VEC) pari_err_TYPE("setunion",y); return gerepilecopy(av, setunion_i(x, y)); } GEN setdelta(GEN x, GEN y) { long ix = 1, iy = 1, iz = 1, lx = lg(x), ly = lg(y); pari_sp av = avma; GEN z = cgetg(lx + ly - 1,t_VEC); if (typ(x) != t_VEC) pari_err_TYPE("setdelta",x); if (typ(y) != t_VEC) pari_err_TYPE("setdelta",y); while (ix < lx && iy < ly) { int c = cmp_universal(gel(x,ix), gel(y,iy)); if (c < 0) gel(z, iz++) = gel(x,ix++); else if (c > 0) gel(z, iz++) = gel(y,iy++); else { ix++; iy++; } } while (ix 0) iy++; else { gel(z, iz++) = gel(x,ix); ix++; iy++; } } setlg(z,iz); return gerepilecopy(av,z); } GEN gen_setminus(GEN A, GEN B, int (*cmp)(GEN,GEN)) { pari_sp ltop = avma; long i = 1, j = 1, k = 1, lx = lg(A), ly = lg(B); GEN diff = cgetg(lx,t_VEC); while (i < lx && j < ly) switch ( cmp(gel(A,i),gel(B,j)) ) { case -1: gel(diff,k++) = gel(A,i++); break; case 1: j++; break; case 0: i++; break; } while (i < lx) gel(diff,k++) = gel(A,i++); setlg(diff,k); return gerepilecopy(ltop,diff); } GEN setminus(GEN x, GEN y) { if (typ(x) != t_VEC) pari_err_TYPE("setminus",x); if (typ(y) != t_VEC) pari_err_TYPE("setminus",y); return gen_setminus(x,y,cmp_universal); } GEN setbinop(GEN f, GEN x, GEN y) { pari_sp av = avma; long i, j, lx, ly, k = 1; GEN z; if (typ(f) != t_CLOSURE || closure_arity(f) != 2 || closure_is_variadic(f)) pari_err_TYPE("setbinop [function needs exactly 2 arguments]",f); lx = lg(x); if (typ(x) != t_VEC) pari_err_TYPE("setbinop", x); if (y == NULL) { /* assume x = y and f symmetric */ z = cgetg((((lx-1)*lx) >> 1) + 1, t_VEC); for (i = 1; i < lx; i++) for (j = i; j < lx; j++) gel(z, k++) = closure_callgen2(f, gel(x,i),gel(x,j)); } else { ly = lg(y); if (typ(y) != t_VEC) pari_err_TYPE("setbinop", y); z = cgetg((lx-1)*(ly-1) + 1, t_VEC); for (i = 1; i < lx; i++) for (j = 1; j < ly; j++) gel(z, k++) = closure_callgen2(f, gel(x,i),gel(y,j)); } return gerepileupto(av, gtoset(z)); } pari-2.17.2/src/basemath/F2xqE.c0000644000175000017500000005734714760123736014661 0ustar billbill/* Copyright (C) 2012 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_ellcard /* Not so fast arithmetic with points over elliptic curves over F_2^n */ /***********************************************************************/ /** **/ /** F2xqE **/ /** **/ /***********************************************************************/ /* Theses functions deal with point over elliptic curves over F_2^n defined * by an equation of the form: ** y^2+x*y=x^3+a_2*x^2+a_6 if the curve is ordinary. ** y^2+a_3*y=x^3+a_4*x+a_6 if the curve is supersingular. * Most of the time a6 is omitted since it can be recovered from any point * on the curve. * For supersingular curves, the parameter a2 is replaced by [a3,a4,a3^-1]. */ GEN RgE_to_F2xqE(GEN x, GEN T) { if (ell_is_inf(x)) return x; retmkvec2(Rg_to_F2xq(gel(x,1),T),Rg_to_F2xq(gel(x,2),T)); } GEN F2xqE_changepoint(GEN x, GEN ch, GEN T) { pari_sp av = avma; GEN p1,z,u,r,s,t,v,v2,v3; if (ell_is_inf(x)) return x; u = gel(ch,1); r = gel(ch,2); s = gel(ch,3); t = gel(ch,4); v = F2xq_inv(u, T); v2 = F2xq_sqr(v, T); v3 = F2xq_mul(v,v2, T); p1 = F2x_add(gel(x,1),r); z = cgetg(3,t_VEC); gel(z,1) = F2xq_mul(v2, p1, T); gel(z,2) = F2xq_mul(v3, F2x_add(gel(x,2), F2x_add(F2xq_mul(s, p1, T),t)), T); return gerepileupto(av, z); } GEN F2xqE_changepointinv(GEN x, GEN ch, GEN T) { GEN u, r, s, t, X, Y, u2, u3, u2X, z; if (ell_is_inf(x)) return x; X = gel(x,1); Y = gel(x,2); u = gel(ch,1); r = gel(ch,2); s = gel(ch,3); t = gel(ch,4); u2 = F2xq_sqr(u, T); u3 = F2xq_mul(u,u2, T); u2X = F2xq_mul(u2,X, T); z = cgetg(3, t_VEC); gel(z,1) = F2x_add(u2X,r); gel(z,2) = F2x_add(F2xq_mul(u3,Y, T), F2x_add(F2xq_mul(s,u2X, T), t)); return z; } static GEN nonzerotrace_F2xq(GEN T) { pari_sp av = avma; long n = F2x_degree(T), vs = T[1]; GEN a; if (odd(n)) return pol1_F2x(vs); do { set_avma(av); a = random_F2x(n, vs); } while (F2xq_trace(a, T)==0); return a; } void F2xq_elltwist(GEN a, GEN a6, GEN T, GEN *pt_a, GEN *pt_a6) { pari_sp av = avma; GEN n = nonzerotrace_F2xq(T); if (typ(a)==t_VECSMALL) { *pt_a = gerepileuptoleaf(av, F2x_add(n, a)); *pt_a6 = vecsmall_copy(a6); } else { GEN a6t = F2x_add(a6, F2xq_mul(n, F2xq_sqr(gel(a,1), T), T)); *pt_a6 = gerepileuptoleaf(av, a6t); *pt_a = vecsmall_copy(a); } } static GEN F2xqE_dbl_slope(GEN P, GEN a, GEN T, GEN *slope) { GEN x, y, Q; if (ell_is_inf(P)) return ellinf(); x = gel(P,1); y = gel(P,2); if (typ(a)==t_VECSMALL) { GEN a2 = a; if (!lgpol(gel(P,1))) { *slope = NULL; return ellinf(); } *slope = F2x_add(x, F2xq_div(y, x, T)); Q = cgetg(3,t_VEC); gel(Q, 1) = F2x_add(F2xq_sqr(*slope, T), F2x_add(*slope, a2)); gel(Q, 2) = F2x_add(F2xq_mul(*slope, F2x_add(x, gel(Q, 1)), T), F2x_add(y, gel(Q, 1))); } else { GEN a3 = gel(a,1), a4 = gel(a,2), a3i = gel(a,3); *slope = F2xq_mul(F2x_add(a4, F2xq_sqr(x, T)), a3i, T); Q = cgetg(3,t_VEC); gel(Q, 1) = F2xq_sqr(*slope, T); gel(Q, 2) = F2x_add(F2xq_mul(*slope, F2x_add(x, gel(Q, 1)), T), F2x_add(y, a3)); } return Q; } GEN F2xqE_dbl(GEN P, GEN a, GEN T) { pari_sp av = avma; GEN slope; return gerepileupto(av, F2xqE_dbl_slope(P, a, T,&slope)); } static GEN F2xqE_add_slope(GEN P, GEN Q, GEN a, GEN T, GEN *slope) { GEN Px, Py, Qx, Qy, R; if (ell_is_inf(P)) { *slope = NULL; return Q; } if (ell_is_inf(Q)) { *slope = NULL; return P; } Px = gel(P,1); Py = gel(P,2); Qx = gel(Q,1); Qy = gel(Q,2); if (F2x_equal(Px, Qx)) { if (F2x_equal(Py, Qy)) return F2xqE_dbl_slope(P, a, T, slope); else { *slope = NULL; return ellinf(); } } *slope = F2xq_div(F2x_add(Py, Qy), F2x_add(Px, Qx), T); R = cgetg(3,t_VEC); if (typ(a)==t_VECSMALL) { GEN a2 = a; gel(R, 1) = F2x_add(F2x_add(F2x_add(F2x_add(F2xq_sqr(*slope, T), *slope), Px), Qx), a2); gel(R, 2) = F2x_add(F2xq_mul(*slope, F2x_add(Px, gel(R, 1)), T), F2x_add(Py, gel(R, 1))); } else { GEN a3 = gel(a,1); gel(R, 1) = F2x_add(F2x_add(F2xq_sqr(*slope, T), Px), Qx); gel(R, 2) = F2x_add(F2xq_mul(*slope, F2x_add(Px, gel(R, 1)), T), F2x_add(Py, a3)); } return R; } GEN F2xqE_add(GEN P, GEN Q, GEN a, GEN T) { pari_sp av = avma; GEN slope; return gerepileupto(av, F2xqE_add_slope(P, Q, a, T, &slope)); } static GEN F2xqE_neg_i(GEN P, GEN a) { GEN LHS; if (ell_is_inf(P)) return P; LHS = typ(a)==t_VECSMALL ? gel(P,1): gel(a,1); return mkvec2(gel(P,1), F2x_add(LHS, gel(P,2))); } GEN F2xqE_neg(GEN P, GEN a, GEN T) { GEN LHS; (void) T; if (ell_is_inf(P)) return ellinf(); LHS = typ(a)==t_VECSMALL ? gel(P,1): gel(a,1); return mkvec2(gcopy(gel(P,1)), F2x_add(LHS, gel(P,2))); } GEN F2xqE_sub(GEN P, GEN Q, GEN a2, GEN T) { pari_sp av = avma; GEN slope; return gerepileupto(av, F2xqE_add_slope(P, F2xqE_neg_i(Q, a2), a2, T, &slope)); } struct _F2xqE { GEN a2, a6; GEN T; }; static GEN _F2xqE_dbl(void *E, GEN P) { struct _F2xqE *ell = (struct _F2xqE *) E; return F2xqE_dbl(P, ell->a2, ell->T); } static GEN _F2xqE_add(void *E, GEN P, GEN Q) { struct _F2xqE *ell=(struct _F2xqE *) E; return F2xqE_add(P, Q, ell->a2, ell->T); } static GEN _F2xqE_mul(void *E, GEN P, GEN n) { pari_sp av = avma; struct _F2xqE *e=(struct _F2xqE *) E; long s = signe(n); if (!s || ell_is_inf(P)) return ellinf(); if (s<0) P = F2xqE_neg(P, e->a2, e->T); if (is_pm1(n)) return s>0? gcopy(P): P; return gerepilecopy(av, gen_pow_i(P, n, e, &_F2xqE_dbl, &_F2xqE_add)); } GEN F2xqE_mul(GEN P, GEN n, GEN a2, GEN T) { struct _F2xqE E; E.a2 = a2; E.T = T; return _F2xqE_mul(&E, P, n); } /* Finds a random nonsingular point on E */ GEN random_F2xqE(GEN a, GEN a6, GEN T) { pari_sp ltop = avma; GEN x, y, rhs, u; do { set_avma(ltop); x = random_F2x(F2x_degree(T),T[1]); if (typ(a) == t_VECSMALL) { GEN a2 = a, x2; if (!lgpol(x)) { set_avma(ltop); retmkvec2(pol0_Flx(T[1]), F2xq_sqrt(a6,T)); } u = x; x2 = F2xq_sqr(x, T); rhs = F2x_add(F2xq_mul(x2,F2x_add(x,a2),T),a6); rhs = F2xq_div(rhs,x2,T); } else { GEN a3 = gel(a,1), a4 = gel(a,2), a3i = gel(a,3), u2i; u = a3; u2i = F2xq_sqr(a3i,T); rhs = F2x_add(F2xq_mul(x,F2x_add(F2xq_sqr(x,T),a4),T),a6); rhs = F2xq_mul(rhs,u2i,T); } } while (F2xq_trace(rhs,T)); y = F2xq_mul(F2xq_Artin_Schreier(rhs, T), u, T); return gerepilecopy(ltop, mkvec2(x, y)); } static GEN _F2xqE_rand(void *E) { struct _F2xqE *ell=(struct _F2xqE *) E; return random_F2xqE(ell->a2, ell->a6, ell->T); } static const struct bb_group F2xqE_group={_F2xqE_add,_F2xqE_mul,_F2xqE_rand,hash_GEN,zvV_equal,ell_is_inf, NULL}; const struct bb_group * get_F2xqE_group(void ** pt_E, GEN a2, GEN a6, GEN T) { struct _F2xqE *e = (struct _F2xqE *) stack_malloc(sizeof(struct _F2xqE)); e->a2 = a2; e->a6 = a6; e->T = T; *pt_E = (void *) e; return &F2xqE_group; } GEN F2xqE_order(GEN z, GEN o, GEN a2, GEN T) { pari_sp av = avma; struct _F2xqE e; e.a2=a2; e.T=T; return gerepileuptoint(av, gen_order(z, o, (void*)&e, &F2xqE_group)); } GEN F2xqE_log(GEN a, GEN b, GEN o, GEN a2, GEN T) { pari_sp av = avma; struct _F2xqE e; e.a2=a2; e.T=T; return gerepileuptoint(av, gen_PH_log(a, b, o, (void*)&e, &F2xqE_group)); } /***********************************************************************/ /** **/ /** Pairings **/ /** **/ /***********************************************************************/ /* Derived from APIP from and by Jerome Milan, 2012 */ static long is_2_torsion(GEN Q, GEN a) { return (typ(a)==t_VEC || lgpol(gel(Q, 1))) ? 0: 1; } static GEN F2xqE_vert(GEN P, GEN Q, GEN a, GEN T) { long vT = T[1]; if (ell_is_inf(P)) return pol1_F2x(T[1]); if (!F2x_equal(gel(Q, 1), gel(P, 1))) return F2x_add(gel(Q, 1), gel(P, 1)); if (is_2_torsion(Q, a)) return F2xq_inv(gel(Q,2), T); return pol1_F2x(vT); } static GEN F2xqE_Miller_line(GEN R, GEN Q, GEN slope, GEN a, GEN T) { long vT = T[1]; GEN x = gel(Q, 1), y = gel(Q, 2); GEN tmp1 = F2x_add(x, gel(R, 1)); GEN tmp2 = F2x_add(F2xq_mul(tmp1, slope, T), gel(R, 2)); GEN s1, s2, ix; if (!F2x_equal(y, tmp2)) return F2x_add(y, tmp2); if (is_2_torsion(Q, a)) return pol1_F2x(vT); if (typ(a)==t_VEC) { GEN a4 = gel(a,2), a3i = gel(a,3); s1 = F2xq_mul(F2x_add(a4, F2xq_sqr(x, T)), a3i, T); if (!F2x_equal(s1, slope)) return F2x_add(s1, slope); s2 = F2xq_mul(F2x_add(x, F2xq_sqr(s1, T)), a3i, T); if (lgpol(s2)) return s2; return zv_copy(a3i); } else { GEN a2 = a ; ix = F2xq_inv(x, T); s1 = F2x_add(x, F2xq_mul(y, ix, T)); if (!F2x_equal(s1, slope)) return F2x_add(s1, slope); s2 =F2x_add(a2, F2x_add(F2xq_sqr(s1,T), s1)); if (!F2x_equal(s2, x)) return F2x_add(pol1_F2x(vT), F2xq_mul(s2, ix, T)); return ix; } } /* Computes the equation of the line tangent to R and returns its evaluation at the point Q. Also doubles the point R. */ static GEN F2xqE_tangent_update(GEN R, GEN Q, GEN a2, GEN T, GEN *pt_R) { if (ell_is_inf(R)) { *pt_R = ellinf(); return pol1_F2x(T[1]); } else if (is_2_torsion(R, a2)) { *pt_R = ellinf(); return F2xqE_vert(R, Q, a2, T); } else { GEN slope; *pt_R = F2xqE_dbl_slope(R, a2, T, &slope); return F2xqE_Miller_line(R, Q, slope, a2, T); } } /* Computes the equation of the line through R and P, and returns its evaluation at the point Q. Also adds P to the point R. */ static GEN F2xqE_chord_update(GEN R, GEN P, GEN Q, GEN a2, GEN T, GEN *pt_R) { if (ell_is_inf(R)) { *pt_R = gcopy(P); return F2xqE_vert(P, Q, a2, T); } else if (ell_is_inf(P)) { *pt_R = gcopy(R); return F2xqE_vert(R, Q, a2, T); } else if (F2x_equal(gel(P, 1), gel(R, 1))) { if (F2x_equal(gel(P, 2), gel(R, 2))) return F2xqE_tangent_update(R, Q, a2, T, pt_R); else { *pt_R = ellinf(); return F2xqE_vert(R, Q, a2, T); } } else { GEN slope; *pt_R = F2xqE_add_slope(P, R, a2, T, &slope); return F2xqE_Miller_line(R, Q, slope, a2, T); } } struct _F2xqE_miller { GEN T, a2, P; }; static GEN F2xqE_Miller_dbl(void* E, GEN d) { struct _F2xqE_miller *m = (struct _F2xqE_miller *)E; GEN T = m->T, a2 = m->a2, P = m->P; GEN v, line, point = gel(d,3); GEN N = F2xq_sqr(gel(d,1), T); GEN D = F2xq_sqr(gel(d,2), T); line = F2xqE_tangent_update(point, P, a2, T, &point); N = F2xq_mul(N, line, T); v = F2xqE_vert(point, P, a2, T); D = F2xq_mul(D, v, T); return mkvec3(N, D, point); } static GEN F2xqE_Miller_add(void* E, GEN va, GEN vb) { struct _F2xqE_miller *m = (struct _F2xqE_miller *)E; GEN T = m->T, a2 = m->a2, P = m->P; GEN v, line, point; GEN na = gel(va,1), da = gel(va,2), pa = gel(va,3); GEN nb = gel(vb,1), db = gel(vb,2), pb = gel(vb,3); GEN N = F2xq_mul(na, nb, T); GEN D = F2xq_mul(da, db, T); line = F2xqE_chord_update(pa, pb, P, a2, T, &point); N = F2xq_mul(N, line, T); v = F2xqE_vert(point, P, a2, T); D = F2xq_mul(D, v, T); return mkvec3(N, D, point); } /* Returns the Miller function f_{m, Q} evaluated at the point P using * the standard Miller algorithm. */ static GEN F2xqE_Miller(GEN Q, GEN P, GEN m, GEN a2, GEN T) { pari_sp av = avma; struct _F2xqE_miller d; GEN v, N, D, g1; d.a2 = a2; d.T = T; d.P = P; g1 = pol1_F2x(T[1]); v = gen_pow_i(mkvec3(g1,g1,Q), m, (void*)&d, F2xqE_Miller_dbl, F2xqE_Miller_add); N = gel(v,1); D = gel(v,2); return gerepileupto(av, F2xq_div(N, D, T)); } GEN F2xqE_weilpairing(GEN P, GEN Q, GEN m, GEN a2, GEN T) { pari_sp av = avma; GEN N, D; if (ell_is_inf(P) || ell_is_inf(Q) || (F2x_equal(gel(P,1),gel(Q,1)) && F2x_equal(gel(P,2),gel(Q,2)))) return pol1_F2x(T[1]); N = F2xqE_Miller(P, Q, m, a2, T); D = F2xqE_Miller(Q, P, m, a2, T); return gerepileupto(av, F2xq_div(N, D, T)); } GEN F2xqE_tatepairing(GEN P, GEN Q, GEN m, GEN a2, GEN T) { if (ell_is_inf(P) || ell_is_inf(Q)) return pol1_F2x(T[1]); return F2xqE_Miller(P, Q, m, a2, T); } /***********************************************************************/ /** **/ /** Point counting **/ /** **/ /***********************************************************************/ static GEN Z2x_rshift(GEN y, long x) { GEN z; long i, l; if (!x) return pol0_Flx(y[1]); z = cgetg_copy(y, &l); z[1] = y[1]; for(i=2; i>x; return Flx_renormalize(z, l); } /* Solve the linear equation approximation in the Newton algorithm */ static GEN gen_Z2x_Dixon(GEN F, GEN V, long N, void *E, GEN lin(void *E, GEN F, GEN d, long N), GEN invl(void *E, GEN d)) { pari_sp av = avma; long N2, M; GEN VN2, V2, VM, bil; ulong q = 1UL<>1; M = N - N2; F = FlxT_red(F, q); VN2 = gen_Z2x_Dixon(F, V, N2, E, lin, invl); bil = lin(E, F, VN2, N); V2 = Z2x_rshift(Flx_sub(V, bil, q), N2); VM = gen_Z2x_Dixon(F, V2, M, E, lin, invl); return gerepileupto(av, Flx_add(VN2, Flx_Fl_mul(VM, 1UL<>1; m = N - n; F = ZXT_remi2n(F, N); Xn = gen_Z2X_Dixon(F, V, n, E, lin, lins, invls); FXn = lin(E, F, Xn, N); Vm = ZX_shifti(ZX_sub(V, FXn), -n); Xm = gen_Z2X_Dixon(F, Vm, m, E, lin, lins, invls); return gerepileupto(av, ZX_remi2n(ZX_add(Xn, ZX_shifti(Xm, n)), N)); } /* H -> H mod 2*/ static GEN _can_invls(void *E, GEN V) {(void) E; return V; } /* H -> H-(f0*H0-f1*H1) */ static GEN _can_lin(void *E, GEN F, GEN V, long N) { pari_sp av=avma; GEN d0, d1, z; (void) E; RgX_even_odd(V, &d0, &d1); z = ZX_sub(V, ZX_sub(ZX_mul(gel(F,1), d0), ZX_mul(gel(F,2), d1))); return gerepileupto(av, ZX_remi2n(z, N)); } static GEN _can_lins(void *E, GEN F, GEN V, long N) { GEN D=Flx_splitting(V, 2), z; ulong q = 1UL< P-(P0^2-X*P1^2) */ static GEN _can_iter(void *E, GEN f2, GEN q) { GEN f0, f1, z; (void) E; RgX_even_odd(f2, &f0, &f1); z = ZX_add(ZX_sub(f2, FpX_sqr(f0, q)), RgX_shift_shallow(FpX_sqr(f1, q), 1)); return mkvec3(z,f0,f1); } /* H -> H-(2*P0*H0-2*X*P1*H1) */ static GEN _can_invd(void *E, GEN V, GEN v, GEN q, long M) { GEN F; (void)E; (void)q; F = mkvec2(ZX_shifti(gel(v,2),1), ZX_shifti(RgX_shift_shallow(gel(v,3),1),1)); return gen_Z2X_Dixon(F, V, M, NULL, _can_lin, _can_lins, _can_invls); } /* Lift P to Q such that Q(x^2)=Q(x)*Q(-x) mod 2^n if Q = Q0(X^2)+X*Q1(X^2), solve Q(X^2) = Q0^2-X*Q1^2 */ GEN F2x_Teichmuller(GEN P, long n) { return gen_ZpX_Newton(F2x_to_ZX(P),gen_2, n, NULL, _can_iter, _can_invd); } static GEN Z2XQ_frob(GEN x, GEN T, GEN q) { return FpX_rem(RgX_inflate(x, 2), T, q); } static GEN Z2xq_frob(GEN x, GEN T, ulong q) { return Flx_rem(Flx_inflate(x, 2), T, q); } struct _frob_lift { GEN T, sqx; }; /* H -> S^-1(H) mod 2 */ static GEN _frob_invls(void *E, GEN V) { struct _frob_lift *F = (struct _frob_lift*) E; GEN sqx = F->sqx; return F2x_to_Flx(F2xq_sqrt_fast(Flx_to_F2x(V), gel(sqx,1), gel(sqx,2))); } /* H -> f1*S(H) + f2*H */ static GEN _frob_lin(void *E, GEN F, GEN x2, long N) { GEN T = gel(F,3); GEN q = int2n(N); GEN y2 = Z2XQ_frob(x2, T, q); GEN lin = ZX_add(ZX_mul(gel(F,1), y2), ZX_mul(gel(F,2), x2)); (void) E; return FpX_rem(ZX_remi2n(lin, N), T, q); } static GEN _frob_lins(void *E, GEN F, GEN x2, long N) { GEN T = gel(F,3); ulong q = 1UL< P(X,S(X)) */ static GEN _lift_iter(void *E, GEN x2, GEN q) { struct _frob_lift *F = (struct _frob_lift*) E; long N = expi(q); GEN TN = ZXT_remi2n(F->T, N); GEN y2 = Z2XQ_frob(x2, TN, q); GEN x2y2 = FpX_rem(ZX_remi2n(ZX_mul(x2, y2), N), TN, q); GEN s = ZX_add(ZX_add(x2, ZX_shifti(y2, 1)), ZX_shifti(x2y2, 3)); GEN V = ZX_add(ZX_add(ZX_sqr(s), y2), ZX_shifti(x2y2, 2)); return mkvec4(FpX_rem(ZX_remi2n(V, N), TN, q),x2,y2,s); } /* H -> Dx*H+Dy*S(H) */ static GEN _lift_invd(void *E, GEN V, GEN v, GEN qM, long M) { struct _frob_lift *F = (struct _frob_lift*) E; GEN TM = ZXT_remi2n(F->T, M); GEN x2 = gel(v,2), y2 = gel(v,3), s = gel(v,4), r; GEN Dx = ZX_add(ZX_mul(ZX_Z_add(ZX_shifti(y2, 4), gen_2), s), ZX_shifti(y2, 2)); GEN Dy = ZX_add(ZX_Z_add(ZX_mul(ZX_Z_add(ZX_shifti(x2, 4), utoi(4)), s), gen_1), ZX_shifti(x2, 2)); Dx = FpX_rem(ZX_remi2n(Dx, M), TM, qM); Dy = FpX_rem(ZX_remi2n(Dy, M), TM, qM); r = mkvec3(Dy, Dx, TM); return gen_Z2X_Dixon(r, V, M, E, _frob_lin, _frob_lins, _frob_invls); } /* Let P(X,Y)=(X+2*Y+8*X*Y)^2+Y+4*X*Y Solve P(x,S(x))=0 [mod 2^n,T] assuming x = x0 [mod 2,T] we set s = X+2*Y+8*X*Y, P = s^2+Y+4*X*Y Dx = dP/dx = (16*s+4)*x+(4*s+1) Dy = dP/dy = (16*y+2)*s+4*y */ static GEN solve_AGM_eqn(GEN x0, long n, GEN T, GEN sqx) { struct _frob_lift F; F.T=T; F.sqx=sqx; return gen_ZpX_Newton(x0, gen_2, n, &F, _lift_iter, _lift_invd); } static GEN Z2XQ_invnorm_pcyc(GEN a, GEN T, long e) { GEN q = int2n(e); GEN z = ZpXQ_norm_pcyc(a, T, q, gen_2); return Zp_inv(z, gen_2, e); } /* Assume a = 1 [4] */ static GEN Z2XQ_invnorm(GEN a, GEN T, long e) { pari_timer ti; GEN pe = int2n(e), s; if (degpol(a)==0) return Zp_inv(Fp_powu(gel(a,2), get_FpX_degree(T), pe), gen_2, e); if (DEBUGLEVEL>=3) timer_start(&ti); s = ZpXQ_log(a, T, gen_2, e); if (DEBUGLEVEL>=3) timer_printf(&ti,"Z2XQ_log"); s = Fp_neg(FpXQ_trace(s, T, pe), pe); if (DEBUGLEVEL>=3) timer_printf(&ti,"FpXQ_trace"); s = modii(gel(Qp_exp(cvtop(s, gen_2, e-2)),4),pe); if (DEBUGLEVEL>=3) timer_printf(&ti,"Qp_exp"); return s; } /* Assume a2==0, so 4|E(F_p): if t^4 = a6 then (t,t^2) is of order 4 8|E(F_p) <=> trace(a6)==0 */ static GEN F2xq_elltrace_Harley(GEN a6, GEN T2) { pari_sp ltop = avma; pari_timer ti; GEN T, sqx; GEN x, x2, t; long n = F2x_degree(T2), N = ((n + 1)>>1) + 2; long ispcyc; if (n==1) return gen_m1; if (n==2) return F2x_degree(a6) ? gen_1 : stoi(-3); if (n==3) return F2x_degree(a6) ? (F2xq_trace(a6,T2) ? stoi(-3): gen_1) : stoi(5); timer_start(&ti); sqx = mkvec2(F2xq_sqrt(polx_F2x(T2[1]),T2), T2); if (DEBUGLEVEL>1) timer_printf(&ti,"Sqrtx"); ispcyc = zx_is_pcyc(F2x_to_Flx(T2)); T = ispcyc? F2x_to_ZX(T2): F2x_Teichmuller(T2, N-2); if (DEBUGLEVEL>1) timer_printf(&ti,"Teich"); T = FpX_get_red(T, int2n(N)); if (DEBUGLEVEL>1) timer_printf(&ti,"Barrett"); x = solve_AGM_eqn(F2x_to_ZX(a6), N-2, T, sqx); if (DEBUGLEVEL>1) timer_printf(&ti,"Lift"); x2 = ZX_Z_add_shallow(ZX_shifti(x,2), gen_1); t = (ispcyc? Z2XQ_invnorm_pcyc: Z2XQ_invnorm)(x2, T, N); if (DEBUGLEVEL>1) timer_printf(&ti,"Norm"); if (cmpii(sqri(t), int2n(n + 2)) > 0) t = subii(t, int2n(N)); return gerepileuptoint(ltop, t); } static GEN get_v(GEN u, GEN a, GEN T) { GEN a4 = gel(a,2), a3i = gel(a,3); GEN ui2 = F2xq_mul(u, a3i, T), ui4 = F2xq_sqr(ui2, T); return F2xq_mul(a4, ui4, T); } static GEN get_r(GEN w, GEN u, GEN T) { return F2xq_sqr(F2xq_mul(F2xq_Artin_Schreier(w, T), u, T), T); } static GEN F2xq_elltracej(GEN a, GEN a6, GEN T, GEN q, long n) { GEN a3 = gel(a,1), a4 = gel(a,2), a3i = gel(a,3); GEN r, pi, rhs; long t, s, m = n >> 1; if (odd(n)) { GEN u, v, w; u = F2xq_pow(a3,diviuexact(subiu(shifti(q,1), 1), 3),T); v = get_v(u, a, T); if (F2xq_trace(v, T)==0) return gen_0; w = F2xq_Artin_Schreier(F2x_1_add(v), T); if (F2xq_trace(w, T)) w = F2x_1_add(w); r = get_r(w, u, T); pi = int2n(m+1); s = (((m+3)&3L) <= 1) ? -1: 1; } else { if (F2x_degree(F2xq_pow(a3,diviuexact(subiu(q, 1), 3),T))==0) { GEN u, v, w; u = F2xq_sqrtn(a3, utoi(3), T, NULL); v = get_v(u, a, T); if (F2xq_trace(v, T)==1) return gen_0; w = F2xq_Artin_Schreier(v, T); if (F2xq_trace(w, T)==1) return gen_0; r = get_r(w, u, T); pi = int2n(m+1); s = odd(m+1) ? -1: 1; } else { long sv = T[1]; GEN P = mkpoln(5, pol1_F2x(sv), pol0_F2x(sv), pol0_F2x(sv), a3, a4); r = F2xq_sqr(gel(F2xqX_roots(P,T), 1), T); pi = int2n(m); s = odd(m) ? -1: 1; } } rhs = F2x_add(F2xq_mul(F2x_add(F2xq_sqr(r, T), a4), r, T), a6); t = F2xq_trace(F2xq_mul(rhs, F2xq_sqr(a3i, T), T), T); return (t==0)^(s==1)? pi: negi(pi); } GEN F2xq_ellcard(GEN a, GEN a6, GEN T) { pari_sp av = avma; long n = F2x_degree(T); GEN c; if (typ(a)==t_VECSMALL) { GEN t = F2xq_elltrace_Harley(a6, T); c = addii(int2u(n), F2xq_trace(a,T) ? addui(1,t): subui(1,t)); } else if (n==1) { long a4i = lgpol(gel(a,2)), a6i = lgpol(a6); return utoi(a4i? (a6i? 1: 5): 3); } else { GEN q = int2u(n); c = subii(addiu(q,1), F2xq_elltracej(a, a6, T, q, n)); } return gerepileuptoint(av, c); } /***********************************************************************/ /** **/ /** Group structure **/ /** **/ /***********************************************************************/ static GEN _F2xqE_pairorder(void *E, GEN P, GEN Q, GEN m, GEN F) { struct _F2xqE *e = (struct _F2xqE *) E; return F2xq_order(F2xqE_weilpairing(P,Q,m,e->a2,e->T), F, e->T); } GEN F2xq_ellgroup(GEN a2, GEN a6, GEN N, GEN T, GEN *pt_m) { struct _F2xqE e; GEN q = int2u(F2x_degree(T)); e.a2=a2; e.a6=a6; e.T=T; return gen_ellgroup(N, subiu(q,1), pt_m, (void*)&e, &F2xqE_group, _F2xqE_pairorder); } GEN F2xq_ellgens(GEN a2, GEN a6, GEN ch, GEN D, GEN m, GEN T) { GEN P; pari_sp av = avma; struct _F2xqE e; e.a2=a2; e.a6=a6; e.T=T; switch(lg(D)-1) { case 0: return cgetg(1,t_VEC); case 1: P = gen_gener(gel(D,1), (void*)&e, &F2xqE_group); P = mkvec(F2xqE_changepoint(P, ch, T)); break; default: P = gen_ellgens(gel(D,1), gel(D,2), m, (void*)&e, &F2xqE_group, _F2xqE_pairorder); gel(P,1) = F2xqE_changepoint(gel(P,1), ch, T); gel(P,2) = F2xqE_changepoint(gel(P,2), ch, T); break; } return gerepilecopy(av, P); } pari-2.17.2/src/basemath/buch4.c0000644000175000017500000001602314760123736014723 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*******************************************************************/ /* RNFISNORM */ /* (Adapted from Denis Simon's original implementation) */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" static void p_append(GEN p, hashtable *H, hashtable *H2) { ulong h = H->hash(p); hashentry *e = hash_search2(H, (void*)p, h); if (!e) { hash_insert2(H, (void*)p, NULL, h); if (H2) hash_insert2(H2, (void*)p, NULL, h); } } /* N a t_INT */ static void Zfa_append(GEN N, hashtable *H, hashtable *H2) { if (!is_pm1(N)) { GEN v = gel(absZ_factor(N),1); long i, l = lg(v); for (i=1; i 2) pari_err_FLAG("rnfisnorminit"); T = get_bnfpol(T, &bnf, &nf); if (!bnf) bnf = Buchall(nf? nf: T, nf_FORCE, DEFAULTPREC); if (!nf) nf = bnf_get_nf(bnf); R = get_bnfpol(R, &bnfabs, &nfabs); if (!gequal1(leading_coeff(R))) pari_err_IMPL("non monic relative equation"); dR = degpol(R); if (dR <= 2) galois = 1; R = RgX_nffix("rnfisnorminit", T, R, 1); if (nf_get_degree(nf) == 1) /* over Q */ rnfeq = mkvec5(R,gen_0,gen_0,T,R); else if (galois == 2) /* needs eltup+abstorel */ rnfeq = nf_rnfeq(nf, R); else /* needs abstorel */ rnfeq = nf_rnfeqsimple(nf, R); polabs = gel(rnfeq,1); k = gel(rnfeq,3); if (!bnfabs || !gequal0(k)) bnfabs = Buchall(polabs, nf_FORCE, nf_get_prec(nf)); if (!nfabs) nfabs = bnf_get_nf(bnfabs); if (galois == 2) { GEN P = polabs==R? leafcopy(R): nfX_eltup(nf, rnfeq, R); setvarn(P, fetch_var_higher()); galois = !!nfroots_if_split(&nfabs, P); (void)delete_var(); } 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, R, rnfeq, nfpol; GEN nf, aux, H, U, Y, M, A, bnfS, sunitrel, futu, S, S1, S2, Sx; long L, i, itu; hashtable *H0, *H2; if (typ(T) != t_VEC || lg(T) != 9) pari_err_TYPE("rnfisnorm [please apply rnfisnorminit()]", T); bnf = gel(T,1); rel = gel(T,2); bnf = checkbnf(bnf); rel = checkbnf(rel); nf = bnf_get_nf(bnf); x = nf_to_scalar_or_alg(nf,x); if (gequal0(x)) { set_avma(av); return mkvec2(gen_0, gen_1); } if (gequal1(x)) { set_avma(av); return mkvec2(gen_1, gen_1); } R = gel(T,3); rnfeq = gel(T,4); if (gequalm1(x) && odd(degpol(R))) { set_avma(av); return mkvec2(gen_m1, gen_1); } /* build set T of ideals involved in the solutions */ nfpol = nf_get_pol(nf); S = gel(T,5); H0 = hash_create_INT(100UL); H2 = hash_create_INT(100UL); L = lg(S); for (i = 1; i < L; i++) p_append(gel(S,i),H0,NULL); S1 = gel(T,6); S2 = gel(T,7); if (flag > 0) { forprime_t T; ulong p; u_forprime_init(&T, 2, flag); while ((p = u_forprime_next(&T))) p_append(utoipos(p), H0,H2); } else if (flag < 0) Zfa_append(utoipos(-flag),H0,H2); /* overkill: prime ideals dividing x would be enough */ A = idealnumden(nf, x); fa_append(gel(A,1), H0,H2); fa_append(gel(A,2), H0,H2); Sx = hash_keys_GEN(H2); L = lg(Sx); if (L > 1) { /* new primes */ S1 = shallowconcat(S1, nf_pV_to_prV(nf, Sx)); S2 = shallowconcat(S2, nf_pV_to_prV(rel, Sx)); } /* computation on T-units */ futu = shallowconcat(bnf_get_fu(rel), bnf_get_tuU(rel)); bnfS = bnfsunit(bnf,S1,LOWDEFAULTPREC); sunitrel = shallowconcat(futu, gel(bnfsunit(rel,S2,LOWDEFAULTPREC), 1)); A = lift_shallow(bnfissunit(bnf,bnfS,x)); L = lg(sunitrel); itu = lg(nf_get_roots(nf))-1; /* index of torsion unit in bnfsunit(nf) output */ M = cgetg(L+1,t_MAT); for (i=1; i 1)) { j = next_j; break; } set_avma(btop); } path[1] = j; /* For nhbr_polynomial() at the top. */ max_len++; set_avma(av); } return gc_long(ltop, j); } static void random_distinct_neighbours_of(ulong *nhbr1, ulong *nhbr2, GEN phi, ulong j, ulong p, ulong pi, long L, long must_have_two_neighbours) { pari_sp av = avma; GEN modpol = Flm_Fl_polmodular_evalx(phi, L, j, p, pi); ulong rem; *nhbr1 = Flx_oneroot_pre(modpol, p, pi); if (*nhbr1 == p) pari_err_BUG("random_distinct_neighbours_of [no neighbour]"); modpol = Flx_div_by_X_x(modpol, *nhbr1, p, &rem); *nhbr2 = Flx_oneroot_pre(modpol, p, pi); if (must_have_two_neighbours && *nhbr2 == p) pari_err_BUG("random_distinct_neighbours_of [single neighbour]"); set_avma(av); } /* * This is Sutherland 2009 Algorithm Descend (p12). */ ulong descend_volcano(GEN phi, ulong j, ulong p, ulong pi, long level, long L, long depth, long steps) { pari_sp ltop = avma; GEN path_g; ulong *path; long max_len; if (steps <= 0 || level + steps > depth) pari_err_BUG("descend_volcano"); max_len = depth - level; path_g = cgetg(max_len + 1 + 1, t_VECSMALL); path = zv_to_ulongptr(path_g); path[0] = j; /* level = 0 means we're on the volcano surface... */ if (!level) { /* Look for any path to the floor. One of j's first three neighbours leads * to the floor, since at most two neighbours are on the surface. */ GEN nhbrs = Flx_roots_pre(Flm_Fl_polmodular_evalx(phi, L, j, p, pi), p, pi); long i; for (i = 1; i <= 3; i++) { long len; path[1] = nhbrs[i]; len = extend_path(path, phi, p, pi, L, max_len); /* If nhbrs[i] took us to the floor: */ if (len < max_len || node_degree(phi, L, path[len], p, pi) == 1) break; } if (i > 3) pari_err_BUG("descend_volcano [2]"); } else { ulong nhbr1, nhbr2; long len; random_distinct_neighbours_of(&nhbr1, &nhbr2, phi, j, p, pi, L, 1); path[1] = nhbr1; len = extend_path(path, phi, p, pi, L, max_len); /* If last j isn't on the floor */ if (len == max_len /* Ended up on the surface. */ && (is_j_exceptional(path[len], p) || node_degree(phi, L, path[len], p, pi) != 1)) { /* The other neighbour leads to the floor */ path[1] = nhbr2; (void) extend_path(path, phi, p, pi, L, steps); } } return gc_ulong(ltop, path[steps]); } long j_level_in_volcano( GEN phi, ulong j, ulong p, ulong pi, long L, long depth) { pari_sp av = avma; GEN chunk; ulong *path1, *path2; long lvl; /* Fouquet & Morain, Section 4.3, if j = 0 or 1728 then it is on the * surface. Also, if the volcano depth is zero then j has level 0 */ if (depth == 0 || is_j_exceptional(j, p)) return 0; chunk = new_chunk(2 * (depth + 1)); path1 = (ulong *) &chunk[0]; path2 = (ulong *) &chunk[depth + 1]; path1[0] = path2[0] = j; random_distinct_neighbours_of(&path1[1], &path2[1], phi, j, p, pi, L, 0); if (path2[1] == p) lvl = depth; /* Only one neighbour => j is on the floor => level = depth */ else { long path1_len = extend_path(path1, phi, p, pi, L, depth); long path2_len = extend_path(path2, phi, p, pi, L, path1_len); lvl = depth - path2_len; } return gc_long(av, lvl); } INLINE GEN Flx_remove_root(GEN f, ulong a, ulong p) { ulong r; GEN g = Flx_div_by_X_x(f, a, p, &r); if (r) pari_err_BUG("Flx_remove_root"); return g; } INLINE GEN get_nbrs(GEN phi, long L, ulong J, const ulong *xJ, ulong p, ulong pi) { pari_sp av = avma; GEN f = Flm_Fl_polmodular_evalx(phi, L, J, p, pi); if (xJ) f = Flx_remove_root(f, *xJ, p); return gerepileupto(av, Flx_roots_pre(f, p, pi)); } /* Return a path of length n along the surface of an L-volcano of height h * starting from surface node j0. Assumes (D|L) = 1 where D = disc End(j0). * * Actually, if j0's endomorphism ring is a suborder, we return the * corresponding shorter path. W must hold space for n + h nodes. * * TODO: have two versions of this function: one that assumes J has the correct * endomorphism ring (hence avoiding several branches in the inner loop) and a * second that does not and accordingly checks for repetitions */ static long surface_path( ulong W[], long n, GEN phi, long L, long h, ulong J, const ulong *nJ, ulong p, ulong pi) { pari_sp av = avma, bv; GEN T, v; long j, k, w, x; ulong W0; W[0] = W0 = J; if (n == 1) return 1; T = cgetg(h+2, t_VEC); bv = avma; v = get_nbrs(phi, L, J, nJ, p, pi); /* Insert known neighbour first */ if (nJ) v = gerepileupto(bv, vecsmall_prepend(v, *nJ)); gel(T,1) = v; k = lg(v)-1; switch (k) { case 0: pari_err_BUG("surface_path"); /* We must always have neighbours */ case 1: /* If volcano is not flat, then we must have more than one neighbour */ if (h) pari_err_BUG("surface_path"); W[1] = uel(v, 1); set_avma(av); /* Check for bad endo ring */ if (W[1] == W[0]) return 1; return 2; case 2: /* If L=2 the only way we can have 2 neighbours is if we have a double root * which can only happen for |D| <= 16 (Thm 2.2 of Fouquet-Morain) * and if it does we must have a 2-cycle. Happens for D=-15. */ if (L == 2) { /* The double root is the neighbour on the surface, with exactly one * neighbour other than J; the other neighbour of J has either 0 or 2 * neighbours that are not J */ GEN u = get_nbrs(phi, L, uel(v, 1), &J, p, pi); long n = lg(u)-1 - !!vecsmall_isin(u, J); W[1] = n == 1 ? uel(v,1) : uel(v,2); return gc_long(av, 2); } /* Volcano is not flat but found only 2 neighbours for the surface node J */ if (h) pari_err_BUG("surface_path"); W[1] = uel(v,1); /* TODO: Can we use the other root uel(v,2) somehow? */ for (w = 2; w < n; w++) { v = get_nbrs(phi, L, W[w-1], &W[w-2], p, pi); /* A flat volcano must have exactly one non-previous neighbour */ if (lg(v) != 2) pari_err_BUG("surface_path"); W[w] = uel(v, 1); /* Detect cycle in case J doesn't have the right endo ring. */ set_avma(av); if (W[w] == W0) return w; } return gc_long(av, n); } if (!h) pari_err_BUG("surface_path"); /* Can't have a flat volcano if k > 2 */ /* At this point, each surface node has L+1 distinct neighbours, 2 of which * are on the surface */ w = 1; for (x = 0;; x++) { /* Get next neighbour of last known surface node to attempt to * extend the path. */ W[w] = umael(T, ((w-1) % h) + 1, x + 1); /* Detect cycle in case the given J didn't have the right endo ring */ if (W[w] == W0) return gc_long(av,w); /* If we have to test the last neighbour, we know it's on the * surface, and if we're done there's no need to extend. */ if (x == k-1 && w == n-1) return gc_long(av,n); /* Walk forward until we hit the floor or finish. */ /* NB: We don't keep the stack clean here; usage is in the order of Lh, * i.e. L roots for each level of the volcano of height h. */ for (j = w;;) { long m; /* We must get 0 or L neighbours here. */ v = get_nbrs(phi, L, W[j], &W[j-1], p, pi); m = lg(v)-1; if (!m) { /* We hit the floor: save the neighbours of W[w-1] and dump the rest */ GEN nbrs = gel(T, ((w-1) % h) + 1); gel(T, ((w-1) % h) + 1) = gerepileupto(bv, nbrs); break; } if (m != L) pari_err_BUG("surface_path"); gel(T, (j % h) + 1) = v; W[++j] = uel(v, 1); /* If we have our path by h nodes, we know W[w] is on the surface */ if (j == w + h) { ++w; /* Detect cycle in case the given J didn't have the right endo ring */ if (W[w] == W0) return gc_long(av,w); x = 0; k = L; } if (w == n) return gc_long(av,w); } } } long next_surface_nbr( ulong *nJ, GEN phi, long L, long h, ulong J, const ulong *pJ, ulong p, ulong pi) { pari_sp av = avma, bv; GEN S; ulong *P; long i, k; S = get_nbrs(phi, L, J, pJ, p, pi); k = lg(S)-1; /* If there is a double root and pJ is set, then k will be zero. */ if (!k) return gc_long(av,0); if (k == 1 || ( ! pJ && k == 2)) { *nJ = uel(S, 1); return gc_long(av,1); } if (!h) pari_err_BUG("next_surface_nbr"); P = (ulong *) new_chunk(h + 1); bv = avma; P[0] = J; for (i = 0; i < k; i++) { long j; P[1] = uel(S, i + 1); for (j = 1; j <= h; j++) { GEN T = get_nbrs(phi, L, P[j], &P[j - 1], p, pi); if (lg(T) == 1) break; P[j + 1] = uel(T, 1); } if (j < h) pari_err_BUG("next_surface_nbr"); set_avma(bv); if (j > h) break; } /* TODO: We could save one get_nbrs call by iterating from i up to k-1 and * assume that the last (kth) nbr is the one we want. For now we're careful * and check that this last nbr really is on the surface */ if (i == k) pari_err_BUG("next_surf_nbr"); *nJ = uel(S, i+1); return gc_long(av,1); } /* Return the number of distinct neighbours (1 or 2) */ INLINE long common_nbr(ulong *nbr, ulong J1, GEN Phi1, long L1, ulong J2, GEN Phi2, long L2, ulong p, ulong pi) { pari_sp av = avma; GEN d, f, g, r; long rlen; g = Flm_Fl_polmodular_evalx(Phi1, L1, J1, p, pi); f = Flm_Fl_polmodular_evalx(Phi2, L2, J2, p, pi); d = Flx_gcd(f, g, p); if (degpol(d) == 1) { *nbr = Flx_deg1_root(d, p); return gc_long(av,1); } if (degpol(d) != 2) pari_err_BUG("common_neighbour"); r = Flx_roots_pre(d, p, pi); rlen = lg(r)-1; if (!rlen) pari_err_BUG("common_neighbour"); /* rlen is 1 or 2 depending on whether the root is unique or not. */ nbr[0] = uel(r, 1); nbr[1] = uel(r, rlen); return gc_long(av,rlen); } /* Return gcd(Phi1(X,J1)/(X - J0), Phi2(X,J2)). Not stack clean. */ INLINE GEN common_nbr_pred_poly( ulong J1, GEN Phi1, long L1, ulong J2, GEN Phi2, long L2, ulong J0, ulong p, ulong pi) { GEN f, g; g = Flm_Fl_polmodular_evalx(Phi1, L1, J1, p, pi); g = Flx_remove_root(g, J0, p); f = Flm_Fl_polmodular_evalx(Phi2, L2, J2, p, pi); return Flx_gcd(f, g, p); } /* Find common neighbour of J1 and J2, where J0 is an L1 predecessor of J1. * Return 1 if successful, 0 if not. */ INLINE int common_nbr_pred(ulong *nbr, ulong J1, GEN Phi1, long L1, ulong J2, GEN Phi2, long L2, ulong J0, ulong p, ulong pi) { pari_sp av = avma; GEN d = common_nbr_pred_poly(J1, Phi1, L1, J2, Phi2, L2, J0, p, pi); int res = (degpol(d) == 1); if (res) *nbr = Flx_deg1_root(d, p); return gc_bool(av,res); } INLINE long common_nbr_verify(ulong *nbr, ulong J1, GEN Phi1, long L1, ulong J2, GEN Phi2, long L2, ulong J0, ulong p, ulong pi) { pari_sp av = avma; GEN d = common_nbr_pred_poly(J1, Phi1, L1, J2, Phi2, L2, J0, p, pi); if (!degpol(d)) return gc_long(av,0); if (degpol(d) > 1) pari_err_BUG("common_neighbour_verify"); *nbr = Flx_deg1_root(d, p); return gc_long(av,1); } INLINE ulong Flm_Fl_polmodular_evalxy(GEN Phi, long L, ulong x, ulong y, ulong p, ulong pi) { pari_sp av = avma; GEN f = Flm_Fl_polmodular_evalx(Phi, L, x, p, pi); return gc_ulong(av, Flx_eval_pre(f, y, p, pi)); } /* Find a common L1-neighbor of J1 and L2-neighbor of J2, given J0 an * L2-neighbor of J1 and an L1-neighbor of J2. Return 1 if successful, 0 * otherwise. Will only fail if initial J-invariant had the wrong endo ring */ INLINE int common_nbr_corner(ulong *nbr, ulong J1, GEN Phi1, long L1, long h1, ulong J2, GEN Phi2, long L2, ulong J0, ulong p, ulong pi) { ulong nbrs[2]; if (common_nbr(nbrs, J1,Phi1,L1, J2,Phi2,L2, p, pi) == 2) { ulong nJ1, nJ2; if (!next_surface_nbr(&nJ2, Phi1, L1, h1, J2, &J0, p, pi) || !next_surface_nbr(&nJ1, Phi1, L1, h1, nbrs[0], &J1, p, pi)) return 0; if (Flm_Fl_polmodular_evalxy(Phi2, L2, nJ1, nJ2, p, pi)) nbrs[0] = nbrs[1]; else if (!next_surface_nbr(&nJ1, Phi1, L1, h1, nbrs[1], &J1, p, pi) || !Flm_Fl_polmodular_evalxy(Phi2, L2, nJ1, nJ2, p, pi)) return 0; } *nbr = nbrs[0]; return 1; } /* Enumerate a surface L1-cycle using gcds with Phi_L2, where c_L2=c_L1^e and * |c_L1|=n, where c_a is the class of the pos def reduced primeform . * Assumes n > e > 1 and roots[0],...,roots[e-1] are already present in W */ static long surface_gcd_cycle( ulong W[], ulong V[], long n, GEN Phi1, long L1, GEN Phi2, long L2, long e, ulong p, ulong pi) { pari_sp av = avma; long i1, i2, j1, j2; i1 = j2 = 0; i2 = j1 = e - 1; /* If W != V we assume V actually points to an L2-isogenous parallel L1-path. * e should be 2 in this case */ if (W != V) { i1 = j1+1; i2 = n-1; } do { ulong t0, t1, t2, h10, h11, h20, h21; long k; GEN f, g, h1, h2; f = Flm_Fl_polmodular_evalx(Phi2, L2, V[i1], p, pi); g = Flm_Fl_polmodular_evalx(Phi1, L1, W[j1], p, pi); g = Flx_remove_root(g, W[j1 - 1], p); h1 = Flx_gcd(f, g, p); if (degpol(h1) != 1) break; /* Error */ h11 = Flx_coeff(h1, 1); h10 = Flx_coeff(h1, 0); set_avma(av); f = Flm_Fl_polmodular_evalx(Phi2, L2, V[i2], p, pi); g = Flm_Fl_polmodular_evalx(Phi1, L1, W[j2], p, pi); k = j2 + 1; if (k == n) k = 0; g = Flx_remove_root(g, W[k], p); h2 = Flx_gcd(f, g, p); if (degpol(h2) != 1) break; /* Error */ h21 = Flx_coeff(h2, 1); h20 = Flx_coeff(h2, 0); set_avma(av); i1++; i2--; if (i2 < 0) i2 = n-1; j1++; j2--; if (j2 < 0) j2 = n-1; t0 = Fl_mul_pre(h11, h21, p, pi); t1 = Fl_inv(t0, p); t0 = Fl_mul_pre(t1, h21, p, pi); t2 = Fl_mul_pre(t0, h10, p, pi); W[j1] = Fl_neg(t2, p); t0 = Fl_mul_pre(t1, h11, p, pi); t2 = Fl_mul_pre(t0, h20, p, pi); W[j2] = Fl_neg(t2, p); } while (j2 > j1 + 1); /* Usually the loop exits when j2 = j1 + 1, in which case we return n. * If we break early because of an error, then (j2 - (j1+1)) > 0 is the * number of elements we haven't calculated yet, and we return n minus that * quantity */ return gc_long(av, n - j2 + j1 + 1); } static long surface_gcd_path( ulong W[], ulong V[], long n, GEN Phi1, long L1, GEN Phi2, long L2, long e, ulong p, ulong pi) { pari_sp av = avma; long i, j; i = 0; j = e; /* If W != V then assume V actually points to a L2-isogenous * parallel L1-path. e should be 2 in this case */ if (W != V) i = j; while (j < n) { GEN f, g, d; f = Flm_Fl_polmodular_evalx(Phi2, L2, V[i], p, pi); g = Flm_Fl_polmodular_evalx(Phi1, L1, W[j - 1], p, pi); g = Flx_remove_root(g, W[j - 2], p); d = Flx_gcd(f, g, p); if (degpol(d) != 1) break; /* Error */ W[j] = Flx_deg1_root(d, p); i++; j++; set_avma(av); } return gc_long(av, j); } /* Given a path V of length n on an L1-volcano, and W[0] L2-isogenous to V[0], * extends the path W to length n on an L1-volcano, with W[i] L2-isogenous * to V[i]. Uses gcds unless L2 is too large to make it helpful. Always uses * GCD to get W[1] to ensure consistent orientation. * * Returns the new length of W. This will almost always be n, but could be * lower if V was started with a J-invariant with bad endomorphism ring */ INLINE long surface_parallel_path( ulong W[], ulong V[], long n, GEN Phi1, long L1, GEN Phi2, long L2, ulong p, ulong pi, long cycle) { ulong W2, nbrs[2]; if (common_nbr(nbrs, W[0], Phi1, L1, V[1], Phi2, L2, p, pi) == 2) { if (n <= 2) return 1; /* Error: Two choices with n = 2; ambiguous */ if (!common_nbr_verify(&W2,nbrs[0], Phi1,L1,V[2], Phi2,L2,W[0], p,pi)) nbrs[0] = nbrs[1]; /* nbrs[1] must be the correct choice */ else if (common_nbr_verify(&W2,nbrs[1], Phi1,L1,V[2], Phi2,L2,W[0], p,pi)) return 1; /* Error: Both paths extend successfully */ } W[1] = nbrs[0]; if (n <= 2) return n; return cycle? surface_gcd_cycle(W, V, n, Phi1, L1, Phi2, L2, 2, p, pi) : surface_gcd_path (W, V, n, Phi1, L1, Phi2, L2, 2, p, pi); } GEN enum_roots(ulong J0, norm_eqn_t ne, GEN fdb, GEN G, GEN vshape) { /* MAX_HEIGHT >= max_{p,n} val_p(n) where p and n are ulongs */ enum { MAX_HEIGHT = BITS_IN_LONG }; pari_sp av, ltop = avma; long s = !!pcp_get_L0(G); long *n = pcp_get_n(G)+s, *L = pcp_get_L(G)+s, *o = pcp_get_o(G)+s, k = pcp_get_k(G)-s; long i, t, vlen, *e, *h, *off, *poff, *M, N = pcp_get_enum_cnt(G); ulong p = ne->p, pi = ne->pi, *roots; GEN Phi, vp, ve, roots_; if (!k) return mkvecsmall(J0); roots_ = cgetg(N + MAX_HEIGHT, t_VECSMALL); roots = zv_to_ulongptr(roots_); av = avma; if (!vshape) vshape = factoru(ne->v); vp = gel(vshape, 1); vlen = lg(vp)-1; ve = gel(vshape, 2); Phi = new_chunk(k); e = new_chunk(k); off = new_chunk(k); poff = new_chunk(k); /* TODO: Surely we can work these out ahead of time? */ /* h[i] is the valuation of p[i] in v */ h = new_chunk(k); for (i = 0; i < k; ++i) { h[i] = 0; for (t = 1; t <= vlen; ++t) if (vp[t] == L[i]) { h[i] = uel(ve, t); break; } e[i] = 0; off[i] = 0; gel(Phi, i) = polmodular_db_getp(fdb, L[i], p); } t = surface_path(roots, n[0], gel(Phi, 0), L[0], h[0], J0, NULL, p, pi); if (t < n[0]) return gc_NULL(ltop); /* J0 has bad endo ring */ if (k == 1) { setlg(roots_, t + 1); return gc_const(av,roots_); } M = new_chunk(k); for (M[0] = 1, i = 1; i < k; ++i) M[i] = M[i-1] * n[i-1]; i = 1; while (i < k) { long j, t0; for (j = i + 1; j < k && ! e[j]; ++j); if (j < k) { if (e[i]) { if (! common_nbr_pred( &roots[t], roots[off[i]], gel(Phi,i), L[i], roots[t - M[j]], gel(Phi, j), L[j], roots[poff[i]], p, pi)) { break; /* J0 has bad endo ring */ } } else if ( ! common_nbr_corner( &roots[t], roots[off[i]], gel(Phi,i), L[i], h[i], roots[t - M[j]], gel(Phi, j), L[j], roots[poff[j]], p, pi)) { break; /* J0 has bad endo ring */ } } else if ( ! next_surface_nbr( &roots[t], gel(Phi,i), L[i], h[i], roots[off[i]], e[i] ? &roots[poff[i]] : NULL, p, pi)) break; /* J0 has bad endo ring */ if (roots[t] == roots[0]) break; /* J0 has bad endo ring */ poff[i] = off[i]; off[i] = t; e[i]++; for (j = i-1; j; --j) { e[j] = 0; off[j] = off[j+1]; } t0 = surface_parallel_path(&roots[t], &roots[poff[i]], n[0], gel(Phi, 0), L[0], gel(Phi, i), L[i], p, pi, n[0] == o[0]); if (t0 < n[0]) break; /* J0 has bad endo ring */ /* TODO: Do I need to check if any of the new roots is a repeat in * the case where J0 has bad endo ring? */ t += n[0]; for (i = 1; i < k && e[i] == n[i]-1; i++); } if (t != N) return gc_NULL(ltop); /* J0 has wrong endo ring */ setlg(roots_, t + 1); return gc_const(av,roots_); } pari-2.17.2/src/basemath/mellininv.c0000644000175000017500000005053714676526175015735 0ustar billbill/* Copyright (C) 2015 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_gammamellininv /*******************************************************************/ /* Computation of inverse Mellin */ /* transforms of gamma products. */ /*******************************************************************/ /* Handle complex Vga whose sum is real */ static GEN sumVga(GEN Vga) { return real_i(vecsum(Vga)); } /* ac != 0 */ static double lemma526_i(double ac, double c, double t, double B) { double D = -B/ac; /* sgn(t) = sgn(a) = - sgn(D) */ if (D <= 0) { if (D > -100) { D = -exp(D) / t; if (D < - 1/M_E) return 0; D = dbllambertW_1(D); } else { /* avoid underflow, use asymptotic expansion */ double U = D - log(t); D = U - log(-U); } return pow(maxdd(t, -t * D), c); } else { if (D < 100) D = dbllambertW0(-exp(D) / t); else { /* avoid overflow, use asymptotic expansion */ double U = D - log(-t); D = U - log(U); } return pow(-t * D, c); } } /* b > 0, c > 0; solve x^a exp(-b x^(1/c)) < e^(-B) for x >= 0 */ double dbllemma526(double a, double b, double c, double B) { double ac; if (!a) return B <= 0? 0: pow(B/b, c); ac = a*c; if (B < 0) B = 1e-9; return lemma526_i(ac, c, ac/b, B); } /* Same, special case b/c = 2Pi, the only one needed: for c = d/2 */ double dblcoro526(double a, double c, double B) { if (!a) return B <= 0? 0: pow(B/(2*M_PI*c), c); if (B < 0) B = 1e-9; return lemma526_i(a*c, c, a/(2*M_PI), B); } static const double MELLININV_CUTOFF = 121.; /* C*C */ /* x real */ static GEN RMOD2(GEN x) { return gsub(x, gmul2n(gdiventgs(x,2), 1)); } /* x real or complex, return canonical representative for x mod 2Z */ static GEN MOD2(GEN x) { return typ(x) == t_COMPLEX? mkcomplex(RMOD2(gel(x,1)), gel(x,2)): RMOD2(x); } static GEN RgV_MOD2(GEN x) { pari_APPLY_same(MOD2(gel(x,i))); } /* classes of poles of the gamma factor mod 2Z, sorted by increasing * Re(s) mod 2 (in [0,2[).*/ static GEN gammapoles(GEN Vga, long *pdV, long bit) { long i, m, emax, l = lg(Vga); GEN P, B = RgV_MOD2(Vga), V = cgetg(l, t_VEC); P = gen_indexsort(B, (void*)lexcmp, cmp_nodata); for (i = m = 1; i < l;) { GEN u = gel(B, P[i]); long k; for(k = i+1; k < l; k++) { GEN v = gsub(u, gel(B, P[k])); if (!gequal0(v) && (!isinexactreal(v) || gexpo(v) > -bit)) break; } gel(V, m++) = vecslice(P,i,k-1); i = k; } setlg(V, m); emax = 0; for (i = 1; i < m; i++) { long j, e = 0, li = lg(gel(V,i))-1; GEN b = gel(B, gel(V,i)[1]); for (j = 1; j < m; j++) if (j != i) e -= gexpo(gsub(gel(B, gel(V,j)[1]), b)); emax = maxss(emax, e * li); } for (i = 1; i < m; i++) gel(V,i) = vecpermute(Vga, gel(V,i)); *pdV = emax; return V; } static GEN sercoeff(GEN x, long n, long prec) { long N = n - valser(x); return (N < 0)? gen_0: gprec_wtrunc(gel(x, N+2), prec); } /* prod_i Gamma(s/2 + (m+LA[i])/2), set t *= prod_i (s/2 + (m+LA[i])/2) */ static GEN get_gamma(GEN *pt, GEN LA, GEN m, int round, long precdl, long prec) { long i, l = lg(LA); GEN pr = NULL, t = *pt; for (i = 1; i < l; i++) { GEN u, g, a = gmul2n(gadd(m, gel(LA,i)), -1); if (round) a = ground(a); u = deg1pol_shallow(ghalf, a, 0); g = ggamma(RgX_to_ser(u, precdl), prec); pr = pr? gmul(pr, g): g; t = t? gmul(t, u): u; } *pt = t; return pr; } /* generalized power series expansion of inverse Mellin around x = 0; * m-th derivative */ static GEN Kderivsmallinit(GEN ldata, GEN Vga, long m, long bit) { const double C2 = MELLININV_CUTOFF; long prec2, N, j, l, dLA, limn, d = lg(Vga)-1; GEN piA, LA, L, M, mat; LA = gammapoles(Vga, &dLA, bit); N = lg(LA)-1; prec2 = nbits2prec(dLA + bit * (1 + M_PI*d/C2)); #if BITS_IN_LONG == 32 prec2 += odd(prec2lg(prec2)) ? EXTRAPRECWORD: 0; #endif if (ldata) Vga = ldata_get_gammavec(ldata_newprec(ldata, prec2)); L = cgetg(N+1, t_VECSMALL); M = cgetg(N+1, t_VEC); mat = cgetg(N+1, t_VEC); limn = ceil(2*M_LN2*bit / (d * dbllambertW0(C2/(M_PI*M_E*d)))); l = limn + 2; for (j = 1; j <= N; j++) { GEN S = gel(LA,j); GEN C, c, mj, G = NULL, t = NULL, tj = NULL; long i, k, n, jj, lj = L[j] = lg(S)-1, precdl = lj+3; gel(M,j) = mj = gsubsg(2, gel(S, vecindexmin(real_i(S)))); for (jj = 1; jj <= N; jj++) { GEN g; if (jj == j) /* poles come from this class only */ g = get_gamma(&tj, gel(LA,jj), mj, 1, precdl, prec2); else g = get_gamma(&t, gel(LA,jj), mj, 0, precdl, prec2); G = G? gmul(G, g): g; } c = cgetg(limn+2,t_COL); gel(c,1) = G; for (n=1; n <= limn; n++) { GEN A = utoineg(2*n), T = RgX_translate(tj, A); /* T = exact polynomial, may vanish at 0 (=> pole in c[n+1]) */ if (t) T = RgX_mul(T, RgX_translate(t, A)); /* no pole here */ gel(c,n+1) = gdiv(gel(c,n), T); } gel(mat, j) = C = cgetg(lj+1, t_COL); for (k = 1; k <= lj; k++) { GEN L = cgetg(l, t_POL); for (n = 2; n < l; n++) gel(L,n) = sercoeff(gel(c,n), -k, prec2); L[1] = evalsigne(1)|evalvarn(0); gel(C,k) = L; } /* C[k] = \sum_n c_{j,k} t^n =: C_k(t) in Dokchitser's Algo 3.3 * m-th derivative of t^(-M+2) sum_k (-ln t)^k/k! C_k(t^2) */ if (m) { mj = gsubgs(mj, 2); for (i = 1; i <= m; i++, mj = gaddgs(mj,1)) for (k = 1; k <= lj; k++) { GEN c = gel(C,k), d = RgX_shift_shallow(gmul2n(RgX_deriv(c),1), 1); c = RgX_Rg_mul(c, mj); if (k < lj) c = RgX_add(c, gel(C,k+1)); gel(C,k) = RgX_sub(d, c); } gel(M,j) = gaddgs(mj,2); } for (k = 1; k <= lj; k++) { GEN c = gel(C,k); if (k > 2) c = RgX_Rg_div(c, mpfact(k-1)); gel(C,k) = RgX_to_RgC(c, lgpol(c)); } } /* Algo 3.3: * \phi^(m)(t) = sum_j t^m_j sum_k (-ln t)^k mat[j,k](t^2) */ piA = gsubsg(m*d, sumVga(Vga)); if (!gequal0(piA)) piA = powPis(gmul2n(piA,-1), prec2); return mkvec5(L, RgV_neg(M), mat, mkvecsmall(prec2), piA); } /* Evaluate a vector considered as a polynomial using Horner. */ static GEN evalvec(GEN vec, long N, GEN u) { GEN S = gen_0; long n; N = minss(N, lg(vec)-1); for (n = N; n >= 1; n--) S = gmul(u, gadd(gel(vec,n), S)); return S; } /* gammamellininvinit accessors */ static double get_tmax(long bitprec) { return (M_LN2 / MELLININV_CUTOFF) * bitprec ; } static GEN GMi_get_Vga(GEN K) { return gel(K,2); } static long GMi_get_degree(GEN K) { return lg(gel(K,2))-1; } static long GMi_get_m(GEN K) { return itos( gel(K,3) ); } static GEN /* [lj,mj,mat,prec2], Kderivsmall only */ GMi_get_VS(GEN K) { return gel(K,4); } /* K[5] = [Ms,cd,A2], Kderivlarge only */ static long/*Kderivlarge*/ GMi_get_status(GEN K) { return itos(gmael3(K,5,1,2)); } static GEN/*Kderivlarge*/ GMi_get_M(GEN K) { return gmael3(K,5,1,1); } static GEN/*Kderivlarge*/ GMi_get_cd(GEN K) { return gmael(K,5,2); } static GEN/*Kderivlarge*/ GMi_get_A2(GEN K) { return gmael(K,5,3); } static double GMi_get_tmax(GEN K, long bitprec) { return (typ(GMi_get_VS(K)) == t_INT)? -1.0 : get_tmax(bitprec); } /* Compute m-th derivative of inverse Mellin at x by generalized power series * around x = 0; x2d = x^(2/d), x is possibly NULL (don't bother about * complex branches). Assume |x|^(2/d) <= tmax = M_LN2*bitprec/MELLININV_CUTOFF*/ static GEN Kderivsmall(GEN K, GEN x, GEN x2d, long bitprec) { GEN VS = GMi_get_VS(K), L = gel(VS,1), M = gel(VS,2), mat = gel(VS,3); GEN d2, Lx, x2, S, pi, piA = gel(VS,5); long j, k, prec = gel(VS,4)[1], d = GMi_get_degree(K), limn, N = lg(L)-1; double xd, Wd, Ed = M_LN2*bitprec / d; xd = maxdd(M_PI*dblmodulus(x2d), 1E-13); /* pi |x|^2/d unless x tiny */ if (xd > Ed) pari_err_BUG("Kderivsmall (x2d too large)"); /* Lemma 5.2.6 (2), a = 1 + log(Pi x^(2/d)) = log(e / xd), * B = log(2)*bitprec / d = Ed */ Wd = dbllambertW0( Ed / (M_E*xd) ); /* solution of w exp(w) = B exp(-a)*/ limn = (long) ceil(2*Ed/Wd); pi = mppi(prec); d2 = gdivsg(d,gen_2); if (x) x = gmul(gtofp(x,prec), gpow(pi,d2,prec)); else x = gpow(gmul(gtofp(x2d,prec),pi), d2, prec); /* at this stage, x has been replaced by pi^(d/2) x */ x2 = gsqr(x); Lx = gpowers(gneg(glog(x,prec)), vecsmall_max(L)); S = gen_0; for (j = 1; j <= N; ++j) { long lj = L[j]; GEN s = gen_0; for (k = 1; k <= lj; k++) s = gadd(s, gmul(gel(Lx,k), evalvec(gmael(mat,j,k), limn, x2))); S = gadd(S, gmul(gpow(x, gel(M,j), prec), s)); } if (!gequal0(piA)) S = gmul(S, piA); return S; } /* In Klarge, we conpute K(t) as (asymptotic) * F(z), where F ~ 1 is given by * a continued fraction and z = Pi t^(2/d). If we take 2n terms in F (n terms * in Euler form), F_n(z) - F(z) is experimentally in exp(- C sqrt(n*z)) * where C ~ 8 for d > 2 [HEURISTIC] and C = 4 (theorem) for d = 1 or d = 2 * and vga = [0,1]. For e^(-E) absolute error, we want * exp(-C sqrt(nz)) < e^-(E+a), where a ~ ln(asymptotic) * i.e. 2n > (E+a)^2 / t^(2/d) * 2/(C^2 Pi); C^2*Pi/2 ~ 100.5 ~ 101 * * In fact, this model becomes wrong for z large: we use instead * * exp(- sqrt(D * nz/log(z+1))) < e^-(E+a), * i.e. 2n > (E+a)^2 * log(1 + Pi t^(2/d))/ t^(2/d) * 2/(D Pi); */ static double get_D(long d) { return d <= 2 ? 157. : 180.; } /* if (abs), absolute error rather than relative */ static void Kderivlarge_optim(GEN K, int abs, GEN t2d, double cd, long *pbitprec, long *pnlim) { GEN A2 = GMi_get_A2(K); long bitprec = *pbitprec, d = GMi_get_degree(K); const double D = get_D(d), td = dblmodulus(t2d); double a, rtd, E = M_LN2*bitprec; /* t = 0 can happen with finite continued fraction or easyvga */ if (!td) { *pnlim = 0; return; } rtd = (typ(t2d) == t_COMPLEX)? gtodouble(gel(t2d,1)): td; /* A2/2 = A, log(td) = (2/d)*log t */ a = d*gtodouble(A2)*log2(td)/2 - (M_PI/M_LN2)*d*rtd + log2(cd);/*log2 K(t)~a*/ /* if bitprec <= 0, caller should return K(t) ~ 0 */ bitprec += 64; if (abs) { bitprec += ceil(a); if (a <= -65) E = M_LN2*bitprec; /* guarantees E <= initial E */ } *pbitprec = bitprec; *pnlim = ceil(E*E * log2(1+M_PI*td) / (D*td)); } /* Compute m-th derivative of inverse Mellin at t by continued fraction of * asymptotic expansion; t2d = t^(2/d). If t is NULL, "lfun" mode: don't * bother about complex branches + use absolute (rather than relative) * accuracy */ static GEN Kderivlarge(GEN K, GEN t, GEN t2d, long bitprec0) { GEN tdA, P, S, pi, z; const long d = GMi_get_degree(K); GEN M = GMi_get_M(K), cd = GMi_get_cd(K), A2 = GMi_get_A2(K); long prec, nlim, status = GMi_get_status(K), m = GMi_get_m(K), bitprec = bitprec0; Kderivlarge_optim(K, !t, t2d, gtodouble(cd), &bitprec, &nlim); if (bitprec <= 0) return gen_0; prec = nbits2prec(bitprec); t2d = gtofp(t2d, prec); if (t) tdA = gpow(t, gdivgu(A2,d), prec); else tdA = gpow(t2d, gdivgu(A2,2), prec); pi = mppi(prec); z = gmul(pi, t2d); P = gmul(gmul(cd, tdA), gexp(gmulsg(-d, z), prec)); if (m) P = gmul(P, gpowgs(mulsr(-2, pi), m)); if (status == 2) /* finite continued fraction */ S = (lg(M) == 2)? gel(M,1): poleval(M, ginv(z)); else { S = contfraceval_inv(M, z, nlim/2); if (DEBUGLEVEL>3) { GEN S0 = contfraceval_inv(M, z, minss(nlim/2 + 1, minss(lg(gel(M, 1)) - 1, lg(gel(M, 2))))); long e = gexpo(gmul(P, gsub(S,S0))); if (-e < bitprec0) err_printf("Kderivlarge: e = %ld, bit = %ld\n",e,bitprec0); } if (status == 1) S = gmul(S, gsubsg(1, ginv(gmul(z, pi)))); } return gmul(P, S); } /* Dokchitser's coefficients used for asymptotic expansion of inverse Mellin * 2 <= p <= min(n+1, d), c = 2n-p+1; sh = (sh(x)/x)^(d-p) */ static GEN vp(long p, long c, GEN SMd, GEN sh) { GEN s, ve = cgetg(p+2, t_VEC); long m, j, k; gel(ve,1) = gen_1; gel(ve,2) = utoipos(c); for (j = 2; j <= p; j++) gel(ve,j+1) = gdivgs(gmulgu(gel(ve,j), c), j); s = gel(SMd, 1); for (m = 1; m <= p; m++) { GEN t, c = gel(SMd, m+1); if (gequal0(c)) continue; t = gel(ve, m+1); for (k = 1; k <= m/2; k++) t = gadd(t, gmul(gel(ve, m-2*k+1), RgX_coeff(sh, k))); s = gadd(s, gmul(c, t)); } return s; } static GEN get_SM(GEN Vga) { long k, m, d = lg(Vga)-1; GEN pol, nS1, SM, C, t = vecsum(Vga); pol = roots_to_pol(gmulgs(Vga, -d), 0); /* deg(pol) = d */ SM = cgetg(d+2, t_VEC); gel(SM,1) = gen_1; if (gequal0(t)) { /* shortcut */ for (m = 1; m <= d; m++) gel(SM,m+1) = gel(pol,d+2-m); return SM; } nS1 = gpowers(gneg(t), d); C = matpascal(d); for (m = 1; m <= d; m++) { pari_sp av = avma; GEN s = gmul(gel(nS1, m+1), gcoeff(C, d+1, m+1)); for (k = 1; k <= m; k++) { GEN e = gmul(gel(nS1, m-k+1), gcoeff(C, d-k+1, m-k+1)); s = gadd(s, gmul(e, RgX_coeff(pol, d-k))); } gel(SM, m+1) = gerepileupto(av, s); } return SM; } static GEN get_SMd(GEN Vga) { GEN M, SM = get_SM(Vga); long p, m, d = lg(Vga)-1; M = cgetg(d, t_VEC); for (p = 2; p <= d; p++) { GEN a = gen_1, c; long D = d - p; gel(M, p-1) = c = cgetg(p+2, t_COL); gel(c, 1) = gel(SM, p+1); for (m = 1; m <= p; m++) { a = muliu(a, D + m); gel(c, m+1) = gmul(gel(SM, p-m+1), a); } } return M; } /* Asymptotic expansion of inverse Mellin, to length nlimmax. Set status = 0 * (regular), 1 (one Hankel determinant vanishes => contfracinit will fail) * or 2 (same as 1, but asymptotic expansion is finite!) * * If status = 2, the asymptotic expansion is finite so return only * the necessary number of terms nlim <= nlimmax + d. */ static GEN Klargeinit(GEN Vga, long nlimmax, long *status, long prec) { long d = lg(Vga) - 1, p, n, cnt; GEN M, SMd, se, vsinh, vd; if (Vgaeasytheta(Vga)) { *status = 2; return mkvec(gen_1); } /* d >= 2 */ *status = 0; if (prec) prec += nbits2extraprec((prec >> 1) + BITS_IN_LONG); SMd = get_SMd(Vga); se = gsinh(RgX_to_ser(pol_x(0), d+2), 0); setvalser(se,0); se = gdeflate(se, 0, 2); /* se(x^2) = sinh(x)/x */ vsinh = gpowers(se, d); vd = gpowers(utoipos(2*d), d); M = cgetg(nlimmax + d + 1, t_VEC); gel(M,1) = gen_1; for (n = 2, cnt = 0; n <= nlimmax || cnt; n++) { pari_sp av = avma; long ld = minss(d, n); GEN s = gen_0; for (p = 2; p <= ld; p++) { GEN z = vp(p, 2*n-1-p, gel(SMd, p-1), gel(vsinh, d-p+1)); s = gadd(s, gmul(gdiv(z, gel(vd, p+1)), gel(M, n+1-p))); } if (prec && !isinexact(s)) s = gtofp(s, prec); gel(M,n) = s = gerepileupto(av, gdivgs(s, 1-n)); if (gequal0(s)) { cnt++; *status = 1; if (cnt >= d-1) { *status = 2; n -= d-2; break; } } else { if (n >= nlimmax) { n++; break; } cnt = 0; } } setlg(M, n); return M; } /* remove trailing zeros from vector. */ static void stripzeros(GEN M) { long i; for(i = lg(M)-1; i >= 1; --i) if (!gequal0(gel(M, i))) break; setlg(M, i+1); } /* Asymptotic expansion of the m-th derivative of inverse Mellin, to length * nlimmax. If status = 2, the asymptotic expansion is finite so return only * the necessary number of terms nlim <= nlimmax + d. */ static GEN gammamellininvasymp_i(GEN Vga, long nlimmax, long m, long *status, long prec) { GEN M, A, Aadd; long d, i, nlim, n; M = Klargeinit(Vga, nlimmax, status, prec); if (!m) return M; d = lg(Vga)-1; /* half the exponent of t in asymptotic expansion. */ A = gdivgu(gaddsg(1-d, sumVga(Vga)), 2*d); if (*status == 2) M = shallowconcat(M, zerovec(m)); nlim = lg(M)-1; Aadd = sstoQ(2-d, 2*d); /* (1/d) - (1/2) */ for (i = 1; i <= m; i++, A = gadd(A,Aadd)) for (n = nlim-1; n >= 1; --n) gel(M, n+1) = gsub(gel(M, n+1), gmul(gel(M, n), gsub(A, uutoQ(n-1, d)))); stripzeros(M); return M; } INLINE int RgV_is_CV(GEN x) { long i; for (i = lg(x)-1; i > 0; i--) { long t = typ(gel(x,i)); if (!is_real_t(t) && t!= t_COMPLEX) return 0; } return 1; } static GEN get_Vga(GEN x, GEN *ldata) { if (typ(x)==t_VEC && RgV_is_CV(x)) { *ldata = NULL; return x; } *ldata = lfunmisc_to_ldata_shallow_i(x); if (*ldata) x = ldata_get_gammavec(*ldata); return x; } GEN gammamellininvasymp(GEN Vga, long nlim, long m) { pari_sp av = avma; long status; GEN ldata; Vga = get_Vga(Vga, &ldata); if (!is_vec_t(typ(Vga)) || lg(Vga) == 1) pari_err_TYPE("gammamellininvasymp",Vga); return gerepilecopy(av, gammamellininvasymp_i(Vga, nlim, m, &status, 0)); } /* Does the continued fraction of the asymptotic expansion M at oo of inverse * Mellin transform attached to Vga have zero Hankel determinants ? */ static long ishankelspec(GEN Vga) { long status, i, d = lg(Vga)-1; GEN M; if (d == 5 || d == 7) { /* known bad cases: a x 5 and a x 7 */ GEN v1 = gel(Vga, 1); for (i = 2; i <= d; ++i) if (!gequal(gel(Vga,i), v1)) break; if (i > d) return 1; } else if (d==10 || d==14) { /* [ a x 5 , (a+1) x 5 ] */ long d2 = d>>1; long s0 = 1, s1 = 0, sm1 = 0; GEN v1 = gel(Vga, 1); for (i = 2; i <= d; i++) { GEN s = gsub(gel(Vga,i),v1); if (gequal0(s)) s0++; else if(gequal1(s)) s1++; else if(gequalm1(s)) sm1++; } if (s0==d2 && (s1==d2 || sm1==d2)) return 1; } /* Heuristic: if 6 first terms in contfracinit don't fail, assume OK */ M = Klargeinit(Vga, 7, &status, 0); return !contfracinit_i(M, 6); } /* Initialize data for computing m-th derivative of inverse Mellin */ GEN gammamellininvinit(GEN Vga, long m, long bitprec) { const double C2 = MELLININV_CUTOFF; pari_sp ltop = avma; GEN A2, M, VS, VL, cd, ldata; long nlimmax, status, d, prec = nbits2prec((4*bitprec)/3); double E = M_LN2*bitprec, tmax = get_tmax(bitprec); /* = E/C2 */ if (m < 0) pari_err_DOMAIN("gammamellininvinit", "derivation order", "<", gen_0, stoi(m)); Vga = get_Vga(Vga, &ldata); d = lg(Vga)-1; if (!is_vec_t(typ(Vga)) || !d) pari_err_TYPE("gammamellininvinit",Vga); nlimmax = ceil(E * log2(1+M_PI*tmax) * C2 / get_D(d)); A2 = gaddsg(m*(2-d) + 1-d, sumVga(Vga)); cd = (d <= 2)? gen_2: gsqrt(gdivgu(int2n(d+1), d), nbits2prec(bitprec)); /* if in Klarge, we have |t| > tmax = E/C2, thus nlim < E*C2/D. */ M = gammamellininvasymp_i(Vga, nlimmax, m, &status, prec); if (status == 2) { tmax = -1.; /* only use Klarge */ VS = gen_0; } else { VS = Kderivsmallinit(ldata, Vga, m, bitprec); if (status == 0 && ishankelspec(Vga)) status = 1; if (status == 1) { /* a Hankel determinant vanishes => contfracinit is undefined. So compute K(t) / (1 - 1/(pi^2*t)) instead of K(t)*/ GEN t = ginv(mppi(prec)); long i; for (i = 2; i < lg(M); ++i) gel(M, i) = gadd(gel(M, i), gmul(gel(M, i-1), t)); } else M = RgC_gtofp(M, prec); /* convert from rationals to t_REAL: faster */ M = contfracinit(M, lg(M)-2); } VL = mkvec3(mkvec2(M, stoi(status)), cd, A2); return gerepilecopy(ltop, mkvec5(dbltor(tmax), Vga, stoi(m), VS, VL)); } /* Compute m-th derivative of inverse Mellin at s2d = s^(d/2) using * initialization data. Use Taylor expansion at 0 for |s2d| < tmax, and * asymptotic expansion at oo otherwise. WARNING: assume that accuracy * has been increased according to tmax by the CALLING program. */ static GEN gammamellininvrt_i(GEN K, GEN s, GEN s2d, long bit) { if (dblmodulus(s2d) < GMi_get_tmax(K, bit)) return Kderivsmall(K, s, s2d, bit); else return Kderivlarge(K, s, s2d, bit); } GEN gammamellininvrt(GEN K, GEN s2d, long bit) { return gammamellininvrt_i(K, NULL, s2d, bit); } /* Compute inverse Mellin at s. K from gammamellininv OR a Vga, in which * case the initialization data is computed. */ GEN gammamellininv(GEN K, GEN s, long m, long bitprec) { pari_sp av = avma; GEN s2d; long d; if (!is_vec_t(typ(K)) || lg(K) != 6 || !is_vec_t(typ(GMi_get_Vga(K)))) K = gammamellininvinit(K, m, bitprec); d = GMi_get_degree(K); s2d = gpow(s, gdivgu(gen_2, d), nbits2prec(bitprec)); return gerepileupto(av, gammamellininvrt_i(K, s, s2d, bitprec)); } pari-2.17.2/src/basemath/concat.c0000644000175000017500000003330514567450071015167 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*******************************************************************/ /* */ /* CONCATENATION */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" /* assume A or B is a t_LIST */ static GEN listconcat(GEN A, GEN B) { long i, l1, lx; GEN L, z, L1, L2; if (typ(A) != t_LIST) { if (list_typ(B)!=t_LIST_RAW) pari_err_TYPE("listconcat",B); L2 = list_data(B); if (!L2) return mklistcopy(A); lx = lg(L2) + 1; z = mklist(); list_data(z) = L = cgetg(lx, t_VEC); for (i = 2; i < lx; i++) gel(L,i) = gcopy(gel(L2,i-1)); gel(L,1) = gcopy(A); return z; } else if (typ(B) != t_LIST) { if (list_typ(A)!=t_LIST_RAW) pari_err_TYPE("listconcat",A); L1 = list_data(A); if (!L1) return mklistcopy(B); lx = lg(L1) + 1; z = mklist(); list_data(z) = L = cgetg(lx, t_VEC); for (i = 1; i < lx-1; i++) gel(L,i) = gcopy(gel(L1,i)); gel(L,i) = gcopy(B); return z; } /* A, B both t_LISTs */ if (list_typ(A)!=t_LIST_RAW) pari_err_TYPE("listconcat",A); if (list_typ(B)!=t_LIST_RAW) pari_err_TYPE("listconcat",B); L1 = list_data(A); if (!L1) return listcopy(B); L2 = list_data(B); if (!L2) return listcopy(A); l1 = lg(L1); lx = l1-1 + lg(L2); z = mklist(); list_data(z) = L = cgetg(lx, t_VEC); L2 -= l1-1; for (i=1; i=3) break; return (ly==1)? x: shallowconcat(x,gel(y,1)); case t_MAT: z=cgetg(ly,t_MAT); if (lx != ly) break; for (i=1; i=3) break; return (ly==1)? x: shallowconcat(x, gel(y,1)); case t_MAT: if (lx != lgcols(y)) break; z=cgetg(ly+1,t_MAT); gel(z,1) = x; for (i=2; i<=ly; i++) gel(z,i) = gel(y,i-1); return z; } break; case t_MAT: switch(ty) { case t_VEC: z=cgetg(lx, t_MAT); if (ly != lx) break; for (i=1; i= y1; y--) { GEN c = gel(y,0); long nc = lg(c)-1; if (nc == 0) continue; if (h != lgcols(c)) { if (h) err_cat(gel(y2,0), c); h = lgcols(c); } L += nc; z = new_chunk(nc) - 1; for (i=1; i<=nc; i++) gel(z,i) = gel(c,i); } z = new_chunk(1); *z = evaltyp(t_MAT) | evallg(L); return z; } static GEN catmanySTR(GEN y1, GEN y2) { long L = 1; /* final \0 */ GEN z, y; char *s; for (y = y1; y <= y2; y++) { char *c = GSTR( gel(y,0) ); L += strlen(c); } z = cgetg(nchar2nlong(L)+1, t_STR); s = GSTR(z); for (y = y1; y <= y2; y++) { char *c = GSTR( gel(y,0) ); long nc = strlen(c); if (nc) { (void)memcpy(s, c, nc); s += nc; } } *s = 0; return z; } /* all entries in y have the same type t = t_VEC, COL, MAT or VECSMALL * concatenate y[k1..k2], with yi = y + ki, k1 <= k2 */ static GEN catmany(GEN y1, GEN y2, long t) { long i, L; GEN z, y; if (y1 == y2) return gel(y1,0); if (t == t_MAT) return catmanyMAT(y1, y2); if (t == t_STR) return catmanySTR(y1, y2); L = 1; for (y = y2; y >= y1; y--) { GEN c = gel(y,0); long nc = lg(c)-1; if (nc == 0) continue; L += nc; z = new_chunk(nc) - 1; for (i=1; i<=nc; i++) gel(z,i) = gel(c,i); } z = new_chunk(1); *z = evaltyp(t) | evallg(L); return z; } GEN shallowconcat1(GEN x) { pari_sp av = avma; long lx, t, i; GEN z; switch(typ(x)) { case t_VEC: case t_COL: lx = lg(x); break; case t_LIST: if (list_typ(x)!=t_LIST_RAW) pari_err_TYPE("concat",x); if (!list_data(x)) pari_err_DOMAIN("concat","vector","=",x,x); x = list_data(x); lx = lg(x); break; default: pari_err_TYPE("concat",x); return NULL; /* LCOV_EXCL_LINE */ } if (lx==1) pari_err_DOMAIN("concat","vector","=",x,x); 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 gconcat1(GEN x) { pari_sp av = avma; return gerepilecopy(av, shallowconcat1(x)); } /* fill M[xoff+i, yoff+j] with the contents of c ( c * Id_n if scalar ) */ static void matfill(GEN M, GEN c, long xoff, long yoff, long n) { long i, j, h, l; l = lg(c); if (l == 1) return; switch(typ(c)) { case t_VEC: for (i = 1; i < l; i++) gcoeff(M,xoff+1,yoff+i) = gel(c,i); break; case t_COL: for (i = 1; i < l; i++) gcoeff(M,xoff+i,yoff+1) = gel(c,i); break; case t_MAT: h = lgcols(c); for (j = 1; j < l; j++) for (i = 1; i < h; i++) gcoeff(M,xoff+i,yoff+j) = gcoeff(c,i,j); break; default: for (i = 1; i <= n; i++) gcoeff(M, xoff+i, yoff+i) = c; break; } } static GEN _matsize(GEN x) { long t = typ(x), L = lg(x) - 1; switch(t) { /* matsize */ case t_VEC: return mkvecsmall2(1, L); case t_COL: return mkvecsmall2(L, 1); case t_MAT: return mkvecsmall2(L? nbrows(x): 0, L); default: if (is_noncalc_t(t)) pari_err_TYPE("_matsize", x); return mkvecsmall2(1, 1); } } GEN shallowmatconcat(GEN v) { long i, j, h, l = lg(v), L = 0, H = 0; GEN M, maxh, maxl; if (l == 1) return cgetg(1,t_MAT); switch(typ(v)) { case t_VEC: for (i = 1; i < l; i++) { GEN c = gel(v,i); GEN s = _matsize(c); H = maxss(H, s[1]); L += s[2]; } M = zeromatcopy(H, L); L = 0; for (i = 1; i < l; i++) { GEN c = gel(v,i); GEN s = _matsize(c); matfill(M, c, 0, L, 1); L += s[2]; } return M; case t_COL: for (i = 1; i < l; i++) { GEN c = gel(v,i); GEN s = _matsize(c); H += s[1]; L = maxss(L, s[2]); } M = zeromatcopy(H, L); H = 0; for (i = 1; i < l; i++) { GEN c = gel(v,i); GEN s = _matsize(c); matfill(M, c, H, 0, 1); H += s[1]; } return M; case t_MAT: h = lgcols(v); maxh = zero_zv(h-1); maxl = zero_zv(l-1); for (j = 1; j < l; j++) for (i = 1; i < h; i++) { GEN c = gcoeff(v,i,j); GEN s = _matsize(c); if (s[1] > maxh[i]) maxh[i] = s[1]; if (s[2] > maxl[j]) maxl[j] = s[2]; } for (i = 1, H = 0; i < h; i++) H += maxh[i]; for (j = 1, L = 0; j < l; j++) L += maxl[j]; M = zeromatcopy(H, L); for (j = 1, L = 0; j < l; j++) { for (i = 1, H = 0; i < h; i++) { GEN c = gcoeff(v,i,j); matfill(M, c, H, L, minss(maxh[i], maxl[j])); H += maxh[i]; } L += maxl[j]; } return M; default: pari_err_TYPE("shallowmatconcat", v); return NULL;/*LCOV_EXCL_LINE*/ } } GEN matconcat(GEN v) { pari_sp av = avma; return gerepilecopy(av, shallowmatconcat(v)); } GEN gconcat(GEN x, GEN y) { long tx, lx,ty,ly,i; GEN z,p1; if (!y) return gconcat1(x); tx = typ(x); ty = typ(y); if (tx==t_STR || ty==t_STR) { pari_sp av = avma; return gerepileuptoleaf(av, strconcat(x,y)); } if (tx==t_LIST || ty==t_LIST) return listconcat(x,y); lx=lg(x); ly=lg(y); if (tx==t_MAT && lx==1) { if (ty!=t_VEC) return gtomat(y); if (ly==1) return cgetg(1, t_MAT); err_cat(x,y); } if (ty==t_MAT && ly==1) { if (tx!=t_VEC) return gtomat(x); if (lx==1) return cgetg(1, t_MAT); err_cat(x,y); } if (tx == ty) { if (tx == t_MAT && lgcols(x) != lgcols(y)) err_cat(x,y); if (!is_matvec_t(tx)) { if (tx != t_VECSMALL) return mkvec2copy(x, y); z = cgetg(lx+ly-1,t_VECSMALL); for (i=1; i=3) break; return (ly==1)? gcopy(x): gconcat(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): gconcat(x,gel(y,1)); case t_MAT: if (lx != lgcols(y)) break; z=cgetg(ly+1,t_MAT); gel(z,1) = gcopy(x); for (i=2; i<=ly; i++) gel(z,i) = gcopy(gel(y,i-1)); return z; } break; case t_MAT: switch(ty) { case t_VEC: z=cgetg(lx,t_MAT); if (ly != lx) break; for (i=1; i0; i--) { GEN Si = FpX_add(C, gel(S,i+2), p); GEN R, Q = FpX_divrem(Si, T, p, &R); gel(A,i+2) = R; C = Q; } gel(A,2) = FpX_add(C, gel(S,2), p); A[1] = S[1]; return gerepilecopy(av, FpXX_renormalize(A,dS+3)); } static GEN FpXXQ_sqr(GEN x, GEN T, GEN p) { pari_sp av = avma; long n = degpol(T); GEN z = FpX_red(ZXX_sqr_Kronecker(x, n), p); z = Kronecker_to_ZXX(z, n, varn(T)); return gerepileupto(av, FpXXQ_red(z, T, p)); } static GEN FpXXQ_mul(GEN x, GEN y, GEN T, GEN p) { pari_sp av = avma; long n = degpol(T); GEN z = FpX_red(ZXX_mul_Kronecker(x, y, n), p); z = Kronecker_to_ZXX(z, n, varn(T)); return gerepileupto(av, FpXXQ_red(z, T, p)); } static GEN ZpXXQ_invsqrt(GEN S, GEN T, ulong p, long e) { pari_sp av = avma, av2; ulong mask; long v = varn(S), n=1; GEN a = pol_1(v); if (e <= 1) return gerepilecopy(av, a); mask = quadratic_prec_mask(e); av2 = avma; for (;mask>1;) { GEN q, q2, q22, f, fq, afq; long n2 = n; n<<=1; if (mask & 1) n--; mask >>= 1; q = powuu(p,n); q2 = powuu(p,n2); f = RgX_sub(FpXXQ_mul(FpXX_red(S, q), FpXXQ_sqr(a, T, q), T, q), pol_1(v)); fq = ZXX_Z_divexact(f, q2); q22 = shifti(addiu(q2,1),-1); afq = FpXX_Fp_mul(FpXXQ_mul(a, fq, T, q2), q22, q2); a = RgX_sub(a, ZXX_Z_mul(afq, q2)); if (gc_needed(av2,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"ZpXXQ_invsqrt, e = %ld", n); a = gerepileupto(av2, a); } } return gerepileupto(av, a); } static GEN to_ZX(GEN a, long v) { return typ(a)==t_INT? scalarpol(a,v): a; } static void is_sing(GEN H, ulong p) { pari_err_DOMAIN("hyperellpadicfrobenius","H","is singular at",utoi(p),H); } static void get_UV(GEN *U, GEN *V, GEN T, ulong p, long e) { GEN q = powuu(p,e), d; GEN dT = FpX_deriv(T, q); GEN R = polresultantext(T, dT); long v = varn(T); if (dvdiu(gel(R,3),p)) is_sing(T, p); d = Zp_inv(gel(R,3), utoi(p), e); *U = FpX_Fp_mul(FpX_red(to_ZX(gel(R,1),v),q),d,q); *V = FpX_Fp_mul(FpX_red(to_ZX(gel(R,2),v),q),d,q); } static GEN frac_to_Fp(GEN a, GEN b, GEN p) { GEN d = gcdii(a, b); return Fp_div(diviiexact(a, d), diviiexact(b, d), p); } static GEN ZpXXQ_frob(GEN S, GEN U, GEN V, long k, GEN T, ulong p, long e) { pari_sp av = avma, av2; long i, pr = degpol(S), dT = degpol(T), vT = varn(T); GEN q = powuu(p,e); GEN Tp = FpX_deriv(T, q), Tp1 = RgX_shift_shallow(Tp, 1); GEN M = to_ZX(gel(S,pr+2),vT) , R; av2 = avma; for(i = pr-1; i>=k; i--) { GEN A, B, H, Bc; ulong v, r; H = FpX_divrem(FpX_mul(V,M,q), T, q, &B); A = FpX_add(FpX_mul(U,M,q), FpX_mul(H, Tp, q),q); v = u_lvalrem(2*i+1,p,&r); Bc = ZX_deriv(B); Bc = FpX_Fp_mul(ZX_divuexact(Bc,upowuu(p,v)),Fp_divu(gen_2, r, q), q); M = FpX_add(to_ZX(gel(S,i+2),vT), FpX_add(A, Bc, q), q); if (gc_needed(av2,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"ZpXXQ_frob, step 1, i = %ld", i); M = gerepileupto(av2, M); } } if (degpol(M)=1; i--) { GEN B, c; R = RgX_shift_shallow(R, 1); gel(R,2) = gel(M, i+1); if (degpol(R) < dT) continue; B = FpX_add(FpX_mulu(T, 2*i, q), Tp1, q); c = frac_to_Fp(leading_coeff(R), leading_coeff(B), q); R = FpX_sub(R, FpX_Fp_mul(B, c, q), q); if (gc_needed(av2,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"ZpXXQ_frob, step 2, i = %ld", i); R = gerepileupto(av2, R); } } if (degpol(R)==dT-1) { GEN c = frac_to_Fp(leading_coeff(R), leading_coeff(Tp), q); R = FpX_sub(R, FpX_Fp_mul(Tp, c, q), q); return gerepileupto(av, R); } else return gerepilecopy(av, R); } static GEN revdigits(GEN v) { long i, n = lg(v)-1; GEN w = cgetg(n+2, t_POL); w[1] = evalsigne(1)|evalvarn(0); for (i=0; i1) timer_start(&ti); Q = revdigits(FpX_digits(A,T,p)); n = degpol(Q); if (DEBUGLEVEL>1) timer_printf(&ti,"reddigits"); sQ = FpXXQ_mul(s,Q,T,p); if (DEBUGLEVEL>1) timer_printf(&ti,"redmul"); qS = RgX_shift_shallow(sQ,m-n); v = ZX_val(sQ); if (n > m + v) { long i, l = n-m-v; GEN rS = cgetg(l+1,t_VEC); for (i = l-1; i >=0 ; i--) gel(rS,i+1) = to_ZX(gel(sQ, 1+v+l-i), vT); rS = FpXV_FpX_fromdigits(rS,T,p); gel(qS,2) = FpX_add(FpX_mul(rS, T, p), gel(qS, 2), p); if (DEBUGLEVEL>1) timer_printf(&ti,"redadd"); } return qS; } static GEN ZC_to_padic(GEN C, GEN q) { long i, l = lg(C); GEN V = cgetg(l,t_COL); for(i = 1; i < l; i++) gel(V, i) = gadd(gel(C, i), q); return V; } static GEN ZM_to_padic(GEN M, GEN q) { long i, l = lg(M); GEN V = cgetg(l,t_MAT); for(i = 1; i < l; i++) gel(V, i) = ZC_to_padic(gel(M, i), q); return V; } static GEN ZX_to_padic(GEN P, GEN q) { long i, l = lg(P); GEN Q = cgetg(l, t_POL); Q[1] = P[1]; for (i=2; i1) timer_start(&ti); s = revdigits(FpX_digits(RgX_inflate(Q, p), Q, pN1)); if (DEBUGLEVEL>1) timer_printf(&ti,"s1"); s = ZpXXQ_invsqrt(s, Q, p, N); if (k==3) s = FpXXQ_mul(s, FpXXQ_sqr(s, Q, pN1), Q, pN1); if (DEBUGLEVEL>1) timer_printf(&ti,"invsqrt"); get_UV(&U, &V, Q, p, N+1); F = cgetg(d, t_MAT); for (i = 1; i < d; i++) { pari_sp av2 = avma; GEN M, D; D = diff_red(s, monomial(utoipos(p),p*i-1,1),(k*p-1)>>1, Q, pN1); if (DEBUGLEVEL>1) timer_printf(&ti,"red"); M = ZpXXQ_frob(D, U, V, (k-1)>>1, Q, p, N + 1); if (DEBUGLEVEL>1) timer_printf(&ti,"frob"); gel(F, i) = gerepilecopy(av2, RgX_to_RgC(M, d-1)); } return gerepileupto(av, F); } GEN hyperellpadicfrobenius(GEN H, ulong p, long n) { pari_sp av = avma; GEN M = ZlX_hyperellpadicfrobenius(H, p, n); GEN q = zeropadic_shallow(utoipos(p),n); return gerepileupto(av, ZM_to_padic(M, q)); } INLINE GEN FpXXX_renormalize(GEN x, long lx) { return ZXX_renormalize(x,lx); } static GEN ZpXQXXQ_red(GEN F, GEN S, GEN T, GEN q, GEN p, long e) { pari_sp av = avma; long i, dF = degpol(F); GEN A, C; if (signe(F)==0) return pol_0(varn(S)); A = cgetg(dF+3, t_POL); C = pol_0(varn(S)); for(i=dF; i>0; i--) { GEN Fi = FpXX_add(C, gel(F,i+2), q); GEN R, Q = ZpXQX_divrem(Fi, S, T, q, p, e, &R); gel(A,i+2) = R; C = Q; } gel(A,2) = FpXX_add(C, gel(F,2), q); A[1] = F[1]; return gerepilecopy(av, FpXXX_renormalize(A,dF+3)); } static GEN ZpXQXXQ_sqr(GEN x, GEN S, GEN T, GEN q, GEN p, long e) { pari_sp av = avma; GEN z, kx; long n = degpol(S); kx = RgXX_to_Kronecker(x, n); z = Kronecker_to_ZXX(FpXQX_sqr(kx, T, q), n, varn(S)); return gerepileupto(av, ZpXQXXQ_red(z, S, T, q, p, e)); } static GEN ZpXQXXQ_mul(GEN x, GEN y, GEN S, GEN T, GEN q, GEN p, long e) { pari_sp av = avma; GEN z, kx, ky; long n = degpol(S); kx = RgXX_to_Kronecker(x, n); ky = RgXX_to_Kronecker(y, n); z = Kronecker_to_ZXX(FpXQX_mul(ky, kx, T, q), n, varn(S)); return gerepileupto(av, ZpXQXXQ_red(z, S, T, q, p, e)); } static GEN FpXXX_red(GEN z, GEN p) { GEN res; long i, l = lg(z); res = cgetg(l,t_POL); res[1] = z[1]; for (i=2; i1) timer_start(&ti); if (e <= 1) return gerepilecopy(av, a); mask = quadratic_prec_mask(e); av2 = avma; for (;mask>1;) { GEN q, q2, q22, f, fq, afq; long n2 = n; n<<=1; if (mask & 1) n--; mask >>= 1; q = powuu(p,n); q2 = powuu(p,n2); av3 = avma; f = RgX_sub(ZpXQXXQ_mul(F, ZpXQXXQ_sqr(a, S, T, q, pp, n), S, T, q, pp, n), pol_1(v)); fq = gerepileupto(av3, RgX_Rg_divexact(f, q2)); q22 = shifti(addiu(q2,1),-1); afq = FpXXX_Fp_mul(ZpXQXXQ_mul(a, fq, S, T, q2, pp, n2), q22, q2); a = RgX_sub(a, RgX_Rg_mul(afq, q2)); if (gc_needed(av2,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"ZpXQXXQ_invsqrt, e = %ld", n); a = gerepileupto(av2, a); } } return gerepileupto(av, a); } static GEN frac_to_Fq(GEN a, GEN b, GEN T, GEN q, GEN p, long e) { GEN d = gcdii(ZX_content(a), ZX_content(b)); return ZpXQ_div(ZX_Z_divexact(a, d), ZX_Z_divexact(b, d), T, q, p, e); } static GEN ZpXQXXQ_frob(GEN F, GEN U, GEN V, long k, GEN S, GEN T, ulong p, long e) { pari_sp av = avma, av2; long i, pr = degpol(F), dS = degpol(S), v = varn(T); GEN q = powuu(p,e), pp = utoipos(p); GEN Sp = RgX_deriv(S), Sp1 = RgX_shift_shallow(Sp, 1); GEN M = gel(F,pr+2), R; av2 = avma; for(i = pr-1; i>=k; i--) { GEN A, B, H, Bc; ulong v, r; H = ZpXQX_divrem(FpXQX_mul(V, M, T, q), S, T, q, utoipos(p), e, &B); A = FpXX_add(FpXQX_mul(U, M, T, q), FpXQX_mul(H, Sp, T, q),q); v = u_lvalrem(2*i+1,p,&r); Bc = RgX_deriv(B); Bc = FpXX_Fp_mul(ZXX_Z_divexact(Bc,powuu(p,v)), Fp_divu(gen_2, r, q), q); M = FpXX_add(gel(F,i+2), FpXX_add(A, Bc, q), q); if (gc_needed(av2,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"ZpXQXXQ_frob, step 1, i = %ld", i); M = gerepileupto(av2, M); } } if (degpol(M)=1; i--) { GEN B, c; R = RgX_shift_shallow(R, 1); gel(R,2) = gel(M, i+1); if (degpol(R) < dS) continue; B = FpXX_add(FpXX_mulu(S, 2*i, q), Sp1, q); c = frac_to_Fq(to_ZX(leading_coeff(R),v), to_ZX(leading_coeff(B),v), T, q, pp, e); R = FpXX_sub(R, FpXQX_FpXQ_mul(B, c, T, q), q); if (gc_needed(av2,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"ZpXXQ_frob, step 2, i = %ld", i); R = gerepileupto(av2, R); } } if (degpol(R)==dS-1) { GEN c = frac_to_Fq(to_ZX(leading_coeff(R),v), to_ZX(leading_coeff(Sp),v), T, q, pp, e); R = FpXX_sub(R, FpXQX_FpXQ_mul(Sp, c, T, q), q); return gerepileupto(av, R); } else return gerepilecopy(av, R); } static GEN Fq_diff_red(GEN s, GEN A, long m, GEN S, GEN T, GEN q, GEN p, long e) { long v, n; GEN Q, sQ, qS; pari_timer ti; if (DEBUGLEVEL>1) timer_start(&ti); Q = revdigits(ZpXQX_digits(A, S, T, q, p, e)); n = degpol(Q); if (DEBUGLEVEL>1) timer_printf(&ti,"reddigits"); sQ = ZpXQXXQ_mul(s, Q, S, T, q, p, e); if (DEBUGLEVEL>1) timer_printf(&ti,"redmul"); qS = RgX_shift_shallow(sQ,m-n); v = ZX_val(sQ); if (n > m + v) { long i, l = n-m-v; GEN rS = cgetg(l+1,t_VEC); for (i = l-1; i >=0 ; i--) gel(rS,i+1) = gel(sQ, 1+v+l-i); rS = FpXQXV_FpXQX_fromdigits(rS, S, T, q); gel(qS,2) = FpXX_add(FpXQX_mul(rS, S, T, q), gel(qS, 2), q); if (DEBUGLEVEL>1) timer_printf(&ti,"redadd"); } return qS; } static void Fq_get_UV(GEN *U, GEN *V, GEN S, GEN T, ulong p, long e) { GEN q = powuu(p, e), pp = utoipos(p), d; GEN dS = RgX_deriv(S), R = polresultantext(S, dS), C; long v = varn(S); if (signe(FpX_red(to_ZX(gel(R,3),v), pp))==0) is_sing(S, p); C = FpXQ_red(to_ZX(gel(R, 3),v), T, q); d = ZpXQ_inv(C, T, pp, e); *U = FpXQX_FpXQ_mul(FpXQX_red(to_ZX(gel(R,1),v),T,q),d,T,q); *V = FpXQX_FpXQ_mul(FpXQX_red(to_ZX(gel(R,2),v),T,q),d,T,q); } static GEN ZXX_to_FpXC(GEN x, long N, GEN p, long v) { long i, l; GEN z; l = lg(x)-1; x++; if (l > N+1) l = N+1; /* truncate higher degree terms */ z = cgetg(N+1,t_COL); for (i=1; i1) timer_start(&ti); xp = ZpX_Frobenius(T, pp, N1); s = RgX_inflate(FpXY_FpXQ_evalx(Q, xp, T, pN1), p); s = revdigits(ZpXQX_digits(s, Q, T, pN1, pp, N1)); if (DEBUGLEVEL>1) timer_printf(&ti,"s1"); s = ZpXQXXQ_invsqrt(s, Q, T, p, N); if (k==3) s = ZpXQXXQ_mul(s, ZpXQXXQ_sqr(s, Q, T, pN1, pp, N1), Q, T, pN1, pp, N1); if (DEBUGLEVEL>1) timer_printf(&ti,"invsqrt"); Fq_get_UV(&U, &V, Q, T, p, N+1); if (DEBUGLEVEL>1) timer_printf(&ti,"get_UV"); F = cgetg(d, t_MAT); for (i = 1; i < d; i++) { pari_sp av2 = avma; GEN M, D; D = Fq_diff_red(s, monomial(pp,p*i-1,1),(k*p-1)>>1, Q, T, pN1, pp, N1); if (DEBUGLEVEL>1) timer_printf(&ti,"red"); M = ZpXQXXQ_frob(D, U, V, (k - 1)>>1, Q, T, p, N1); if (DEBUGLEVEL>1) timer_printf(&ti,"frob"); gel(F, i) = gerepileupto(av2, ZXX_to_FpXC(M, d-1, q, varn(T))); } return gerepileupto(av, F); } GEN nfhyperellpadicfrobenius(GEN H, GEN T, ulong p, long n) { pari_sp av = avma; GEN pp = utoipos(p), q = zeropadic_shallow(pp, n); GEN M = ZlXQX_hyperellpadicfrobenius(lift_shallow(H),T,p,n); GEN MM = ZpXQM_prodFrobenius(M, T, pp, n); GEN m = gmul(ZXM_to_padic(MM, q), gmodulo(gen_1, T)); return gerepileupto(av, m); } GEN hyperellpadicfrobenius0(GEN H, GEN Tp, long n) { GEN T, p; if (!ff_parse_Tp(Tp, &T,&p,0)) pari_err_TYPE("hyperellpadicfrobenius", Tp); if (lgefint(p) > 3) pari_err_IMPL("large prime in hyperellpadicfrobenius"); return T? nfhyperellpadicfrobenius(H, T, itou(p), n) : hyperellpadicfrobenius(H, itou(p), n); } static GEN F2x_genus2charpoly_naive(GEN P, GEN Q) { long a, b = 1, c = 0; GEN T = mkvecsmall2(P[1], 7); GEN PT = F2x_rem(P, T), QT = F2x_rem(Q, T); long q0 = F2x_eval(Q, 0), q1 = F2x_eval(Q, 1); long dP = F2x_degree(P), dQ = F2x_degree(Q); a= dQ<3 ? 0: dP<=5 ? 1: -1; a += (q0? F2x_eval(P, 0)? -1: 1: 0) + (q1? F2x_eval(P, 1)? -1: 1: 0); b += q0 + q1; if (lgpol(QT)) c = (F2xq_trace(F2xq_div(PT, F2xq_sqr(QT, T), T), T)==0 ? 1: -1); return mkvecsmalln(6, 0UL, 4UL, 2*a, (b+2*c+a*a)>>1, a, 1UL); } static GEN Flx_difftable(GEN P, ulong p) { long i, n = degpol(P); GEN V = cgetg(n+2, t_VEC); gel(V, n+1) = P; for(i = n; i >= 1; i--) gel(V, i) = Flx_diff1(gel(V, i+1), p); return V; } static GEN FlxV_Fl2_eval_pre(GEN V, GEN x, ulong D, ulong p, ulong pi) { long i, n = lg(V)-1; GEN r = cgetg(n+1, t_VEC); for (i = 1; i <= n; i++) gel(r, i) = Flx_Fl2_eval_pre(gel(V, i), x, D, p, pi); return r; } static GEN Fl2V_next(GEN V, ulong p) { long i, n = lg(V)-1; GEN r = cgetg(n+1, t_VEC); gel(r, 1) = gel(V, 1); for (i = 2; i <= n; i++) gel(r, i) = Flv_add(gel(V, i), gel(V, i-1), p); return r; } static GEN Flx_genus2charpoly_naive(GEN H, ulong p) { pari_sp av = avma, av2; ulong pi = get_Fl_red(p); ulong i, j, p2 = p>>1, D = 2, e = ((p&2UL) == 0) ? -1 : 1; long a, b, c = 0, n = degpol(H); GEN t, k = const_vecsmall(p, -1); k[1] = 0; for (i=1, j=1; i < p; i += 2, j = Fl_add(j, i, p)) k[j+1] = 1; while (k[1+D] >= 0) D++; b = n == 5 ? 0 : 1; a = b ? k[1+Flx_lead(H)]: 0; t = Flx_difftable(H, p); av2 = avma; for (i=0; i < p; i++) { ulong v = Flx_eval(H, i, p); a += k[1+v]; b += !!v; } for (j=1; j <= p2; j++) { GEN V = FlxV_Fl2_eval_pre(t, mkvecsmall2(0, j), D, p, pi); for (i=0;; i++) { GEN r2 = gel(V, n+1); c += uel(r2,2) ? (uel(r2,1) ? uel(k,1+Fl2_norm_pre(r2, D, p, pi)): e) : !!uel(r2,1); if (i == p-1) break; V = Fl2V_next(V, p); } set_avma(av2); } set_avma(av); return mkvecsmalln(6, 0UL, p*p, a*p, (b+2*c+a*a)>>1, a, 1UL); } static GEN charpoly_funceq(GEN P, GEN q) { long i, l, g = degpol(P)>>1; GEN Q = cgetg_copy(P, &l); Q[1] = P[1]; for (i=0; i<=g; i++) gel(Q, i+2) = mulii(gel(P, 2*g-i+2), powiu(q, g-i)); for (; i<=2*g; i++) gel(Q, i+2) = icopy(gel(P, i+2)); return Q; } static long hyperell_Weil_bound(GEN q, ulong g, GEN p) { pari_sp av = avma; GEN w = mulii(binomialuu(2*g,g),sqrtint(shifti(powiu(q, g),2))); return gc_long(av, logint(w,p) + 1); } /* return 4P + Q^2 */ static GEN check_hyperell(GEN PQ) { GEN H; if (is_vec_t(typ(PQ)) && lg(PQ)==3) H = gadd(gsqr(gel(PQ, 2)), gmul2n(gel(PQ, 1), 2)); else H = gmul2n(PQ, 2); return typ(H) == t_POL? H: NULL; } GEN hyperellcharpoly(GEN PQ) { pari_sp av = avma; GEN M, R, T=NULL, pp=NULL, q; long d, n, eps = 0; ulong p; GEN H = check_hyperell(PQ); if (!H || !RgX_is_FpXQX(H, &T, &pp) || !pp) pari_err_TYPE("hyperellcharpoly", PQ); p = itou(pp); if (!T) { if (p==2 && is_vec_t(typ(PQ))) { long dP, dQ, v = varn(H); GEN P = gel(PQ,1), Q = gel(PQ,2); if (typ(P)!=t_POL) P = scalarpol(P, v); if (typ(Q)!=t_POL) Q = scalarpol(Q, v); dP = degpol(P); dQ = degpol(Q); if (dP<=6 && dQ <=3 && (dQ==3 || dP>=5)) { GEN P2 = RgX_to_F2x(P), Q2 = RgX_to_F2x(Q); GEN D = F2x_add(F2x_mul(P2, F2x_sqr(F2x_deriv(Q2))), F2x_sqr(F2x_deriv(P2))); if (F2x_degree(F2x_gcd(D, Q2))) is_sing(PQ, 2); if (dP==6 && dQ<3 && F2x_coeff(P2,5)==F2x_coeff(Q2,2)) is_sing(PQ, 2); /* The curve is singular at infinity */ R = zx_to_ZX(F2x_genus2charpoly_naive(P2, Q2)); return gerepileupto(av, R); } } H = RgX_to_FpX(H, pp); d = degpol(H); if (d <= 0) is_sing(H, p); if (p > 2 && ((d == 5 && p < 17500) || (d == 6 && p < 24500))) { GEN Hp = ZX_to_Flx(H, p); if (!Flx_is_squarefree(Hp, p)) is_sing(H, p); R = zx_to_ZX(Flx_genus2charpoly_naive(Hp, p)); return gerepileupto(av, R); } n = hyperell_Weil_bound(pp, (d-1)>>1, pp); eps = odd(d)? 0: Fp_issquare(leading_coeff(H), pp); M = hyperellpadicfrobenius(H, p, n); R = centerlift(carberkowitz(M, 0)); q = pp; } else { int fixvar; T = typ(T)==t_FFELT? FF_mod(T): RgX_to_FpX(T, pp); q = powuu(p, degpol(T)); fixvar = (varncmp(varn(T),varn(H)) <= 0); if (fixvar) setvarn(T, fetch_var()); H = RgX_to_FpXQX(H, T, pp); d = degpol(H); if (d <= 0) is_sing(H, p); eps = odd(d)? 0: Fq_issquare(leading_coeff(H), T, pp); n = hyperell_Weil_bound(q, (d-1)>>1, pp); M = nfhyperellpadicfrobenius(H, T, p, n); R = simplify_shallow(centerlift(liftpol_shallow(carberkowitz(M, 0)))); if (fixvar) (void)delete_var(); } if (!odd(d)) { GEN b = get_basis(p, d) == 3 ? gen_1 : q; GEN pn = powuu(p, n); R = FpX_div_by_X_x(R, eps? b: negi(b), pn, NULL); R = FpX_center_i(R, pn, shifti(pn,-1)); } R = charpoly_funceq(R, q); return gerepilecopy(av, R); } int hyperellisoncurve(GEN W, GEN P) { pari_sp av = avma; long res; GEN x, y; if (typ(P)!=t_VEC || lg(P)!=3) pari_err_TYPE("hyperellisoncurve",P); x = gel(P,1); y = gel(P,2); if (typ(W)==t_POL) res = gequal(gsqr(y), poleval(W,x)); else { if (typ(W)!=t_VEC || lg(W)!=3) pari_err_TYPE("hyperellisoncurve",W); res = gequal(gmul(y, gadd(y,poleval(gel(W,2), x))), poleval(gel(W,1), x)); } return gc_int(av, res); } GEN hyperellordinate(GEN W, GEN x) { pari_sp av = avma; if (typ(W)==t_POL) { GEN d = poleval(W,x), y; if (gequal0(d)) { return gerepilecopy(av, mkvec(d)); } if (!issquareall(d, &y)) { set_avma(av); return cgetg(1,t_VEC); } return gerepilecopy(av, mkvec2(y, gneg(y))); } else { GEN b, c, d, rd, y; if (typ(W)!=t_VEC || lg(W)!=3) pari_err_TYPE("hyperellisoncurve",W); b = poleval(gel(W,2), x); c = poleval(gel(W,1), x); d = gadd(gsqr(b), gmul2n(c, 2)); if (gequal0(d)) { return gerepilecopy(av, mkvec(gmul2n(gneg(b),-1))); } if (!issquareall(d, &rd)) { set_avma(av); return cgetg(1,t_VEC); } y = gmul2n(gsub(rd, b), -1); return gerepilecopy(av, mkvec2(y, gsub(y,rd))); } } GEN hyperelldisc(GEN PQ) { pari_sp av = avma; GEN D, H = check_hyperell(PQ); long d, g; if (!H || signe(H)==0) pari_err_TYPE("hyperelldisc",PQ); d = degpol(H); g = ((d+1)>>1)-1; D = gmul2n(RgX_disc(H),-4*(g+1)); if (odd(d)) D = gmul(D, gsqr(leading_coeff(H))); return gerepileupto(av, D); } static long get_ep(GEN W) { GEN P = gel(W,1), Q = gel(W,2); if (signe(Q)==0) return ZX_lval(P,2); return minss(ZX_lval(P,2), ZX_lval(Q,2)); } static GEN algo51(GEN W, GEN M) { GEN P = gel(W,1), Q = gel(W,2); for(;;) { long vP = ZX_lval(P,2); long vQ = signe(Q) ? ZX_lval(Q,2): vP+1; long r; /* 1 */ if (vQ==0) break; /* 2 */ if (vP==0) { GEN H, H1; /* a */ RgX_even_odd(FpX_red(P,gen_2),&H, &H1); if (signe(H1)) break; /* b */ P = ZX_add(P, ZX_mul(H, ZX_sub(Q, H))); Q = ZX_sub(Q, ZX_mulu(H, 2)); vP = ZX_lval(P,2); vQ = signe(Q) ? ZX_lval(Q,2): vP+1; } /* 2c */ if (vP==1) break; /* 2d */ r = minss(2*vQ, vP)>>1; if (M) gel(M,1) = shifti(gel(M,1), r); P = ZX_shifti(P, -2*r); Q = ZX_shifti(Q, -r); } return mkvec2(P,Q); } static GEN algo52(GEN W, GEN c, long *pt_lambda) { long lambda; GEN P = gel(W,1), Q = gel(W,2); for(;;) { GEN H, H1; /* 1 */ GEN Pc = ZX_affine(P,gen_2,c), Qc = ZX_affine(Q,gen_2,c); long mP = ZX_lval(Pc,2), mQ = signe(Qc) ? ZX_lval(Qc,2): mP+1; /* 2 */ if (2*mQ <= mP) { lambda = 2*mQ; break; } /* 3 */ if (odd(mP)) { lambda = mP; break; } /* 4 */ RgX_even_odd(FpX_red(ZX_shifti(Pc, -mP),gen_2),&H, &H1); if (signe(H1)) { lambda = mP; break; } /* 5 */ P = ZX_add(P, ZX_mul(H, ZX_sub(Q, H))); Q = ZX_sub(Q, ZX_mulu(H, 2)); } *pt_lambda = lambda; return mkvec2(P,Q); } static long test53(long lambda, long ep, long g) { return (lambda <= g+1) || (odd(g) && lambda= (g + 3)>>1; else return ZX_val(FpX_deriv(Pe, gen_2)) >= g+1; } else return ZX_val(Qe) >= (g+1)>>1 && ZX_val(Pe) >= g + 1; } static GEN hyperell_reverse(GEN W, long g) { return mkvec2(RgXn_recip_shallow(gel(W,1),2*g+3), RgXn_recip_shallow(gel(W,2),g+2)); } static GEN algo56(GEN W, long g) { long ep; GEN M = mkvec2(gen_1, matid(2)), Woo; W = algo51(W, M); Woo = hyperell_reverse(W, g); ep = get_ep(Woo); if (test55(Woo,ep,g)) { long lambda; Woo = algo52(Woo, gen_0, &lambda); if (!test53(lambda,ep,g)) { long r = lambda>>1; gel(M,1) = shifti(gel(M,1), r); gel(M,2) = ZM2_mul(gel(M,2), mkmat22(gen_0, gen_1, gen_2, gen_0)); W = mkvec2(ZX_shifti(ZX_unscale(gel(Woo,1), gen_2), -2*r), ZX_shifti(ZX_unscale(gel(Woo,2), gen_2), -r)); } } for(;;) { long j, ep = get_ep(W); for (j = 0; j < 2; j++) { long lambda; GEN c = utoi(j); GEN Pc = ZX_affine(gel(W,1), gen_2, c); GEN Qc = ZX_affine(gel(W,2), gen_2, c); if (test55(mkvec2(Pc, Qc), ep, g)) { GEN Wc = algo52(W, c, &lambda); if (!test53(lambda,ep,g)) { long r = lambda>>1; gel(M,1) = shifti(gel(M,1), r); gel(M,2) = ZM2_mul(gel(M,2), mkmat22(gen_2, c, gen_0, gen_1)); W = mkvec2(ZX_shifti(ZX_affine(gel(Wc,1), gen_2,c), -2*r), ZX_shifti(ZX_affine(gel(Wc,2), gen_2,c), -r)); break; } } } if (j==2) break; } return mkvec2(W, M); } static GEN algo56bis(GEN W, long g, long inf, long thr) { pari_sp av = avma; GEN vl = cgetg(3,t_VEC); long nl = 1; W = algo51(W, NULL); if (inf) { GEN Woo = hyperell_reverse(W, g); GEN Pc = ZX_unscale(gel(W,1), gen_2); GEN Qc = ZX_unscale(gel(W,2), gen_2); long ep = get_ep(Woo); if (test55(mkvec2(Pc, Qc), ep, g)) { long lambda; Woo = algo52(Woo, gen_0, &lambda); if (lambda == thr) { long r = lambda>>1; gel(vl,nl++) = mkvec2(ZX_shifti(ZX_unscale(gel(Woo,1), gen_2), -2*r), ZX_shifti(ZX_unscale(gel(Woo,2), gen_2), -r)); } } } { long j, ep = get_ep(W); for (j = 0; j < 2; j++) { long lambda; GEN c = utoi(j); GEN Pc = ZX_affine(gel(W,1), gen_2, c); GEN Qc = ZX_affine(gel(W,2), gen_2, c); if (test55(mkvec2(Pc, Qc), ep, g)) { GEN Wc = algo52(W, c, &lambda); if (lambda == thr) { long r = lambda>>1; gel(vl,nl++) = mkvec2(ZX_shifti(ZX_affine(gel(Wc,1), gen_2,c), -2*r), ZX_shifti(ZX_affine(gel(Wc,2), gen_2,c), -r)); } } } } setlg(vl, nl); return gerepilecopy(av,vl); } /* return the (degree 2) apolar invariant (the nth transvectant of P and P) */ static GEN ZX_apolar(GEN P, long n) { pari_sp av = avma; long d = degpol(P), i; GEN s = gen_0, g = cgetg(n+2,t_VEC); gel(g,1) = gen_1; for (i = 1; i <= n; i++) gel(g,i+1) = muliu(gel(g,i),i); /* g[i+1] = i! */ for (i = n-d; i <= d; i++) { GEN a = mulii(mulii(gel(g,i+1),gel(g,n-i+1)), mulii(gel(P,i+2),gel(P,n-i+2))); s = odd(i)? subii(s, a): addii(s, a); } return gerepileuptoint(av,s); } static GEN algo57(GEN F, long g, GEN pr) { long i, l; GEN D, C = content(F); GEN e = gel(core2(shifti(C,-vali(C))),2); GEN M = mkvec2(e, matid(2)); long minvd = (2*g+1)>>(odd(g) ? 4:2); F = ZX_Z_divexact(F, sqri(e)); D = absi(hyperelldisc(F)); if (!pr) { GEN A = gcdii(D, ZX_apolar(F, 2*g+2)); pr = gel(factor(shifti(A, -vali(A))),1); } l = lg(pr); for (i = 1; i < l; i++) { long ep; GEN p = gel(pr, i), ps2 = shifti(p,-1), Fe; if (equaliu(p,2) || Z_pval(D,p) < minvd) continue; ep = ZX_pvalrem(F,p, &Fe); Fe = FpX_red(Fe, p); if (degpol(Fe) < g+1+ep) { GEN Fi = ZX_unscale(RgXn_recip_shallow(F,2*g+3), p); long lambda = ZX_pval(Fi,p); if (!test53(lambda,ep,g)) { GEN ppr = powiu(p,lambda>>1); F = ZX_Z_divexact(Fi,sqri(ppr)); gel(M,1) = mulii(gel(M,1), ppr); gel(M,2) = ZM2_mul(gel(M,2), mkmat22(gen_0,gen_1,p,gen_0)); } } for(;;) { GEN Fe, R; long j, lR, ep = ZX_pvalrem(F,p, &Fe); R = FpX_roots_mult(FpX_red(Fe, p), g+2-ep, p); lR = lg(R); for (j = 1; j>1); F = ZX_Z_divexact(Fi, sqri(ppr)); gel(M,1) = mulii(gel(M,1), ppr); gel(M,2) = ZM2_mul(gel(M,2), mkmat22(p,c,gen_0,gen_1)); break; } } if (j==lR) break; } } return mkvec2(F, M); } /* if inf=0, ignore point at infinity */ static GEN algo57bis(GEN F, long g, GEN p, long inf, long thr) { pari_sp av = avma; GEN vl = cgetg(3,t_VEC), Fe; long nl = 1, ep = ZX_pvalrem(F,p, &Fe); Fe = FpX_red(Fe, p); { GEN R = FpX_roots_mult(Fe, thr-ep, p); long j, lR = lg(R); for (j = 1; j= thr-ep) { GEN Fj = ZX_unscale(RgXn_recip_shallow(F,2*g+3), p); long lambda = ZX_pvalrem(Fj, p, &Fj); if (lambda == thr) gel(vl,nl++) = odd(lambda)? ZX_Z_mul(Fj, p): Fj; } setlg(vl, nl); return gerepilecopy(av,vl); } static GEN next_model(GEN G, long g, GEN p, long inf, long thr) { return equaliu(p,2) ? algo56bis(G, g, inf, thr) : algo57bis(G, g, p, inf, thr); } static GEN get_extremal(GEN F, GEN G, long g, GEN p) { while (1) { GEN Wi; Wi = next_model(G, g, p, 0, g+2); if (lg(Wi)==1) return F; F = gel(Wi,1); Wi = next_model(F, g, p, 0, g+1); if (lg(Wi)==1) return F; G = gel(Wi,1); } } GEN hyperellextremalmodels(GEN F, long g, GEN p) { pari_sp av = avma; GEN R, W; long l; if (equaliu(p,2)) { if (get_ep(F)>0) return mkvec(F); } else if( ZX_pval(F,p) > 0) return mkvec(F); W = next_model(F, g, p, 1, g+1); l = lg(W); if (l==1) { set_avma(av); return mkvec(F); } R = cgetg(3, t_VEC); gel(R,1) = get_extremal(F, gel(W,1), g, p); gel(R,2) = l==3 ? get_extremal(F, gel(W,2), g, p) : F; if (gel(R,2) == gel(R,1)) setlg(R,2); return gerepilecopy(av, R); } static GEN RgX_RgM2_eval(GEN P, GEN A, GEN Bp, long d) { if (signe(P)==0) return P; else { long dP = degpol(P); GEN R = RgX_homogenous_evalpow(P, A, Bp); if (d > dP) R = gmul(R, gel(Bp,1+d-dP)); return R; } } static GEN minimalmodel_merge(GEN W2, GEN Modd, long g, long v) { GEN P = gel(W2,1), Q = gel(W2,2); GEN e = gel(Modd,1), M = gel(Modd,2); GEN A = deg1pol_shallow(gcoeff(M,1,1), gcoeff(M,1,2), v); GEN B = deg1pol_shallow(gcoeff(M,2,1), gcoeff(M,2,2), v); GEN Bp = gpowers(B, 2*g+2); long f = mod4(e)==1 ? 1: -1; GEN m = shifti(f > 0 ? subui(1,e): addui(1,e), -2); GEN m24 = subii(shifti(m,1), shifti(sqri(m),2)); P = RgX_RgM2_eval(P, A, Bp, 2*g+2); Q = RgX_RgM2_eval(Q, A, Bp, g+1); P = ZX_Z_divexact(ZX_add(P, ZX_Z_mul(ZX_sqr(Q), m24)),sqri(e)); if (f < 0) Q = ZX_neg(Q); return mkvec2(P,Q); } static GEN hyperell_redQ(GEN W) { GEN P = gel(W,1), Q = gel(W,2); GEN Pr, Qr = FpX_red(Q, gen_2); Pr = ZX_add(P, ZX_shifti(ZX_mul(ZX_sub(Q, Qr),ZX_add(Q, Qr)),-2)); return mkvec2(Pr, Qr); } static GEN minimalmodel_getH(GEN W, GEN Qn, GEN e, GEN M, long g, long v) { GEN Q = gel(W,2); GEN A = deg1pol_shallow(gcoeff(M,1,1), gcoeff(M,1,2), v); GEN B = deg1pol_shallow(gcoeff(M,2,1), gcoeff(M,2,2), v); GEN Bp = gpowers(B, g+1); return ZX_shifti(ZX_sub(ZX_Z_mul(Qn,e),RgX_RgM2_eval(Q, A, Bp, g+1)), -1); } static void check_hyperell_Q(const char *fun, GEN *pW, GEN *pF) { GEN W = *pW, F = check_hyperell(W); long v, d; if (!F || !signe(F) || !RgX_is_ZX(F)) pari_err_TYPE(fun, W); if (!signe(ZX_disc(F))) pari_err_DOMAIN(fun,"disc(W)","==",gen_0,W); v = varn(F); d = degpol(F); if (typ(W)==t_POL) W = mkvec2(W, pol_0(v)); else { GEN P = gel(W, 1), Q = gel(W, 2); long g = ((d+1) >> 1) - 1; if (typ(P)!=t_POL) P = scalarpol_shallow(P, v); if (typ(Q)!=t_POL) Q = scalarpol_shallow(Q, v); if (!RgX_is_ZX(P) || !RgX_is_ZX(Q)) pari_err_TYPE(fun,W); if (degpol(P) > 2*g+2) pari_err_DOMAIN(fun, "deg(P)", ">", utoi(2*g+2), P); if (degpol(Q) > g+1) pari_err_DOMAIN(fun, "deg(Q)", ">", utoi(g+1), Q); W = mkvec2(P, Q); } if (d < 3) pari_err_DOMAIN(fun, "genus", "=", gen_0, gen_0); *pW = W; *pF = F; } GEN hyperellminimalmodel(GEN W, GEN *pM, GEN pr) { pari_sp av = avma; GEN Wr, F, WM2, F2, W2, M2, Modd, Wf, ef, Mf, Hf; long d, g, v; check_hyperell_Q("hyperellminimalmodel",&W, &F); if (pr && (!is_vec_t(typ(pr)) || !RgV_is_ZV(pr))) pari_err_TYPE("hyperellminimalmodel",pr); d = degpol(F); g = ((d+1)>>1)-1; v = varn(F); Wr = hyperell_redQ(W); if (!pr || RgV_isin(pr, gen_2)) { WM2 = algo56(Wr,g); W2 = gel(WM2, 1); M2 = gel(WM2, 2); F2 = check_hyperell(W2); } else { W2 = Wr; F2 = F; M2 = mkvec2(gen_1, matid(2)); } Modd = gel(algo57(F2, g, pr), 2); Wf = hyperell_redQ(minimalmodel_merge(W2, Modd, g, v)); if (!pM) return gerepilecopy(av, Wf); ef = mulii(gel(M2,1), gel(Modd,1)); Mf = ZM2_mul(gel(M2,2), gel(Modd,2)); Hf = minimalmodel_getH(W, gel(Wf,2), ef, Mf, g, v); *pM = mkvec3(ef, Mf, Hf); return gc_all(av, 2, &Wf, pM); } GEN hyperellminimaldisc(GEN W, GEN pr) { pari_sp av = avma; GEN C = hyperellminimalmodel(W, NULL, pr); return gerepileuptoint(av, hyperelldisc(C)); } static GEN redqfbsplit(GEN a, GEN b, GEN c, GEN d) { GEN p = subii(d,b), q = shifti(a,1); GEN U, Q, u, v, w = bezout(p, q, &u, &v); if (!equali1(w)) { p = diviiexact(p, w); q = diviiexact(q, w); } U = mkmat22(p, negi(v), q, u); Q = qfb_ZM_apply(mkvec3(a,b,c), U); b = gel(Q, 2); c = gel(Q,3); if (signe(b) < 0) gel(U,2) = mkcol2(v, negi(u)); gel(U,2) = ZC_lincomb(gen_1, truedivii(negi(c), d), gel(U,2), gel(U,1)); return U; } static GEN polreduce(GEN P, GEN M) { long v = varn(P), dP = degpol(P), d = odd(dP) ? dP+1: dP; GEN A = deg1pol_shallow(gcoeff(M,1,1), gcoeff(M,1,2), v); GEN B = deg1pol_shallow(gcoeff(M,2,1), gcoeff(M,2,2), v); return RgX_RgM2_eval(P, A, gpowers(B, d), d); } /* assume deg(P) > 2 */ static GEN red_Cremona_Stoll(GEN P, GEN *pM) { GEN q1, q2, q3, M, R; long i, prec = nbits2prec(2*gexpo(P)) + EXTRAPRECWORD, d = degpol(P); GEN dP = ZX_deriv(P); for (;;) { GEN r = QX_complex_roots(P, prec); q1 = gen_0; q2 = gen_0; q3 = gen_0; for (i = 1; i <= d; i++) { GEN ri = gel(r,i); GEN s = ginv(gabs(RgX_cxeval(dP,ri,NULL), prec)); if (d!=4) s = gpow(s, gdivgs(gen_2,d-2), prec); q1 = gadd(q1, s); q2 = gsub(q2, gmul(real_i(ri), s)); q3 = gadd(q3, gmul(gnorm(ri), s)); } M = lllgram(mkmat22(q1,q2,q2,q3)); if (M && lg(M) == 3) break; prec = precdbl(prec); } R = polreduce(P, M); *pM = M; return R; } /* assume deg(P) > 2 */ GEN ZX_hyperellred(GEN P, GEN *pM) { pari_sp av = avma; long d = degpol(P); GEN q1, q2, q3, D, vD; GEN a = gel(P,d+2), b = gel(P,d+1), c = gel(P, d); GEN M, R, M2; q1 = muliu(sqri(a), d); q2 = shifti(mulii(a,b), 1); q3 = subii(sqri(b), shifti(mulii(a,c), 1)); D = gcdii(gcdii(q1, q2), q3); if (!equali1(D)) { q1 = diviiexact(q1, D); q2 = diviiexact(q2, D); q3 = diviiexact(q3, D); } D = qfb_disc3(q1, q2, q3); if (!signe(D)) M = mkmat22(gen_1, truedivii(negi(q2),shifti(q1,1)), gen_0, gen_1); else if (issquareall(D,&vD)) M = redqfbsplit(q1, q2, q3, vD); else M = gel(qfbredsl2(mkqfb(q1,q2,q3,D), NULL), 2); R = red_Cremona_Stoll(polreduce(P, M), &M2); if (pM) *pM = gmul(M, M2); return gc_all(av, pM ? 2: 1, &R, pM); } GEN hyperellred(GEN W, GEN *pM) { pari_sp av = avma; long g, d, v; GEN F, M, Wf, Hf; check_hyperell_Q("hyperellred", &W, &F); d = degpol(F); g = ((d+1)>>1)-1; v = varn(F); (void) ZX_hyperellred(F, &M); Wf = hyperell_redQ(minimalmodel_merge(W, mkvec2(gen_1, M), g, v)); Hf = minimalmodel_getH(W, gel(Wf,2), gen_1, M, g, v); if (pM) *pM = mkvec3(gen_1, M, Hf); return gc_all(av, pM ? 2: 1, &Wf, pM); } static void check_hyperell_Rg(const char *fun, GEN *pW, GEN *pF) { GEN W = *pW, F = check_hyperell(W); long v; if (!F) pari_err_TYPE(fun, W); if (degpol(F) <= 0) pari_err_CONSTPOL(fun); v = varn(F); if (typ(W)==t_POL) W = mkvec2(W, pol_0(v)); else { GEN P = gel(W, 1), Q = gel(W, 2); long g = ((degpol(F)+1)>>1)-1; if( typ(P)!=t_POL) P = scalarpol(P, v); if( typ(Q)!=t_POL) Q = scalarpol(Q, v); if (degpol(P) > 2*g+2) pari_err_DOMAIN(fun, "poldegree(P)", ">", utoi(2*g+2), P); if (degpol(Q) > g+1) pari_err_DOMAIN(fun, "poldegree(Q)", ">", utoi(g+1), Q); W = mkvec2(P, Q); } if (pF) *pF = F; *pW = W; } static void check_hyperell_vc(const char *fun, GEN C, long v, GEN *e, GEN *M, GEN *H) { if (typ(C) != t_VEC || lg(C) != 4) pari_err_TYPE(fun,C); *e = gel(C,1); *M = gel(C,2); *H = gel(C,3); if (typ(*M) != t_MAT || lg(*M) != 3 || lgcols(*M) != 3) pari_err_TYPE(fun,C); if (typ(*H)!=t_POL || varncmp(varn(*H),v) > 0) *H = scalarpol_shallow(*H,v); } GEN hyperellchangecurve(GEN W, GEN C) { pari_sp av = avma; GEN F, P, Q, A, B, Bp, e, M, H; long d, g, v; check_hyperell_Rg("hyperellchangecurve",&W,&F); P = gel(W,1); Q = gel(W,2); d = degpol(F); g = ((d+1)>>1)-1; v = varn(F); check_hyperell_vc("hyperellchangecurve", C, v, &e, &M, &H); if (varncmp(gvar(M),v) <= 0) pari_err_PRIORITY("hyperellchangecurve",M,"<=",v); A = deg1pol_shallow(gcoeff(M,1,1), gcoeff(M,1,2), v); B = deg1pol_shallow(gcoeff(M,2,1), gcoeff(M,2,2), v); Bp = gpowers(B, 2*g+2); P = RgX_RgM2_eval(P, A, Bp, 2*g+2); Q = RgX_RgM2_eval(Q, A, Bp, g+1); P = RgX_Rg_div(RgX_sub(P, RgX_mul(H,RgX_add(Q,H))), gsqr(e)); Q = RgX_Rg_div(RgX_add(Q, RgX_mul2n(H,1)), e); return gerepilecopy(av, mkvec2(P,Q)); } pari-2.17.2/src/basemath/Flxq_log.c0000644000175000017500000004772314760123736015504 0ustar billbill/* Copyright (C) 2013 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_fflog /* Let [ be the following order on Fp: 0 [ p-1 [ 1 [ p-2 [ 2 .. [ p\2 and [[ the lexicographic extension of [ to Fp[T]. Compute the isomorphism (Fp[X], [[) -> (N,<) on P */ static long Flx_cindex(GEN P, ulong p) { long d = degpol(P), i; ulong s = 0, p2 = (p-1)>>1; for (i = 0; i <= d; ++i) { ulong x = P[d-i+2]; if (x<=p2) x = 2*x; else x = 1+2*(p-1-x); s = p*s+x; } return s; } /* Compute the polynomial immediately after t for the [[ order */ static void Flx_cnext(GEN t, ulong p) { long i; long p2 = p>>1; for(i=2;;i++) if (t[i]==p2) t[i]=0; else { t[i] = t[i]>1) : x>>1; c/=p; } return Flx_renormalize(P, d+3); } static GEN factorel(GEN h, ulong p) { GEN F = Flx_factor(h, p); GEN F1 = gel(F, 1), F2 = gel(F, 2); long i, l1 = lg(F1)-1; GEN p2 = cgetg(l1+1, t_VECSMALL); GEN e2 = cgetg(l1+1, t_VECSMALL); for (i = 1; i <= l1; ++i) { p2[i] = Flx_cindex(gel(F1, i), p); e2[i] = F2[i]; } return mkmat2(p2, e2); } static long Flx_addifsmooth3(pari_sp *av, struct Flxq_log_rel *r, GEN h, long u, long v, long w, ulong p) { long off = r->off; r->nbtest++; if (Flx_is_smooth(h, r->r, p)) { GEN z = factorel(h, p); if (v<0) z = mkmat2(vecsmall_append(gel(z,1),off+u),vecsmall_append(gel(z,2),-1)); else z = famatsmall_reduce(mkmat2( vecsmall_concat(gel(z,1),mkvecsmall3(off+u,off+v,off+w)), vecsmall_concat(gel(z,2),mkvecsmall3(-1,-1,-1)))); gel(r->rel,++r->nbrel) = gerepilecopy(*av,z); if (DEBUGLEVEL && (r->nbrel&511UL)==0) err_printf("%ld%% ",r->nbrel*100/r->nbexp); *av = avma; } else set_avma(*av); return r->nbrel==r->nb || r->nbrel==r->nbmax; } static void Flx_renormalize_inplace(GEN x, long lx) { long i; for (i = lx-1; i>1; i--) if (x[i]) break; setlg(x, i+1); } /* Let T*X^e=C^3-R a+b+c = 0 (C+a)*(C+b)*(C+c) = C^3+ (a*b+a*c+b*c)*C+a*b*c = R + (a*b+a*c+b*c)*C+a*b*c = R + (a*b-c^2)*C+a*b*c */ static void Flxq_log_cubic(struct Flxq_log_rel *r, GEN C, GEN R, ulong p, ulong pi) { long l = lg(C); GEN a = zero_zv(l); /*We allocate one extra word to catch overflow*/ GEN b = zero_zv(l); pari_sp av = avma; long i,j,k; for(i=0; ; i++, Flx_cnext(a, p)) { Flx_renormalize_inplace(a, l+1); r->nb++; if (Flx_addifsmooth3(&av, r, Flx_add(a, C, p), i, -1, -1, p)) return; for(j=2; j<=l; j++) b[j] = 0; for(j=0; j<=i; j++, Flx_cnext(b, p)) { GEN h,c; GEN pab,pabc,pabc2; Flx_renormalize_inplace(b, l+1); c = Flx_neg(Flx_add(a,b,p),p); k = Flx_cindex(c, p); if (k > j) continue; pab = Flx_mul_pre(a, b, p, pi); pabc = Flx_mul_pre(pab,c,p,pi); pabc2= Flx_sub(pab,Flx_sqr_pre(c,p,pi),p); h = Flx_add(R,Flx_add(Flx_mul_pre(C,pabc2,p,pi),pabc,p), p); h = Flx_normalize(h, p); if (Flx_addifsmooth3(&av, r, h, i, j, k, p)) return; } } } static GEN Flxq_log_find_rel(GEN b, long r, GEN T, ulong p, ulong pi, GEN *g, long *e) { pari_sp av = avma; while (1) { GEN M, z; *g = Flxq_mul_pre(*g, b, T, p, pi); (*e)++; M = Flx_halfgcd_all_pre(*g,T,p,pi,&z,NULL); if (Flx_is_smooth_pre(gcoeff(M,1,1), r, p, pi) && Flx_is_smooth_pre(z, r, p, pi)) { GEN F = factorel(z, p); GEN G = factorel(gcoeff(M,1,1), p); GEN rel = mkmat2(vecsmall_concat(gel(F, 1),gel(G, 1)), vecsmall_concat(gel(F, 2),zv_neg(gel(G, 2)))); return gc_all(av,2,&rel,g); } if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"Flxq_log_find_rel"); *g = gerepilecopy(av, *g); } } } /* Generalised Odlyzko formulae ( EUROCRYPT '84, LNCS 209, pp. 224-314, 1985. ) */ /* Return the number of monic, k smooth, degree n polynomials for k=1..r */ static GEN smoothness_vec(ulong p, long r, long n) { long i,j,k; GEN R = cgetg(r+1, t_VEC), pp = utoipos(p); GEN V = cgetg(n+1, t_VEC); for (j = 1; j <= n; ++j) gel(V, j) = binomialuu(p+j-1,j); gel(R, 1) = gel(V, n); for (k = 2; k <= r; ++k) { GEN W = cgetg(n+1, t_VEC); GEN Ik = ffnbirred(pp, k); for (j = 1; j <= n; ++j) { long l = j/k; GEN s = gen_0; pari_sp av2 = avma; if (l*k == j) { s = binomial(addiu(Ik,l-1), l); l--; } for (i = 0; i <= l; ++i) s = addii(s, mulii(gel(V, j-k*i), binomial(addis(Ik,i-1), i))); gel(W, j) = gerepileuptoint(av2, s); } V = W; gel(R, k) = gel(V, n); } return R; } /* Solve N^2*pr/6 + N*prC = N+fb N^2*pr/6 + N*(prC-1) -fb = 0 */ static GEN smooth_cost(GEN fb, GEN pr, GEN prC) { GEN a = gdivgu(pr,6); GEN b = gsubgs(prC,1); GEN c = gneg(fb); GEN vD = gsqrt(gsub(gsqr(b),gmul2n(gmul(a,c),2)),BIGDEFAULTPREC); return ceil_safe(gdiv(gsub(vD,b),gmul2n(a,1))); } /* Return best choice of r. We loop over d until there is sufficiently many triples (a,b,c) (a+b+c=0) of degree <=d with respect to the probability of smoothness of (a*b-c^2)*C */ static GEN smooth_best(long p, long n, long *pt_r, long *pt_nb) { pari_sp av = avma, av2; GEN bestc = NULL, pp = utoipos(p); long bestr = 0, bestFB = 0; long r,d, dC = (n+2)/3; for (r = 1; r < dC; ++r) { GEN fb = ffsumnbirred(pp, r); GEN smoothC = smoothness_vec(p,r,dC); GEN prC = gdiv(gel(smoothC,r), powuu(p,dC)); ulong rels = 0; av2 = avma; for(d=0; d= 0) { rels = itou_or_0(addui(rels, gceil(gmul(gdivgu(sqri(Nmax),6),pr)))); if (!rels) rels = ULONG_MAX; set_avma(av2); continue; } c = gdivgu(addii(powuu(p,2*d),sqri(N)),6); FB = addii(FB,N); if ((!bestc || gcmp(gmul2n(c,r), gmul2n(bestc,bestr)) < 0)) { if (DEBUGLEVEL) err_printf("r=%ld d=%ld fb=%Ps early rels=%lu P=%.5Pe -> C=%.5Pe \n", r, dt, FB, rels, pr, c); bestc = c; bestr = r; bestFB = itos_or_0(FB); } break; } } *pt_r=bestr; *pt_nb=bestFB; return bestc ? gerepileupto(av, gceil(bestc)): NULL; } static GEN check_kernel(long r, GEN M, long nbi, long nbrow, GEN T, ulong p, ulong pi, GEN m) { pari_sp av = avma; long N = 3*upowuu(p, r); GEN K = FpMs_leftkernel_elt(M, nbrow, m); long i, f=0, tbs; long lm = lgefint(m), u=1; GEN tab, g; GEN q = powuu(p,degpol(T)); GEN idx = diviiexact(subiu(q,1),m); pari_timer ti; if (DEBUGLEVEL) timer_start(&ti); while (signe(gel(K,u))==0) u++; K = FpC_Fp_mul(K, Fp_inv(gel(K, u), m), m); g = Flxq_pow_pre(cindex_Flx(u, r, p, T[1]), idx, T, p, pi); tbs = maxss(1, expu(nbi/expi(m))); tab = Flxq_pow_init_pre(g, q, tbs, T, p, pi); setlg(K, N); for (i=1; i1) timer_printf(&ti,"%ld-smooth element",r); F = gel(V,1); E = gel(V,2); l = lg(F); Ao = gen_0; for(i=1; i=0) return gc_NULL(av); nbi = itos(ffsumnbirred(stoi(p), r)); if (DEBUGLEVEL) { err_printf("Size FB=%ld, looking for %ld relations, %Ps tests needed\n", nbi, nb,cost); timer_start(&ti); } T = smallirred_Flx(p,n,get_Flx_var(T0), pi); for(;;) { S = Flx_ffisom(T0,T,p); a = Flx_Flxq_eval_pre(a0, S, T, p, pi); b = Flx_Flxq_eval_pre(b0, S, T, p, pi); C = Flx_shift(pol1_Flx(get_Flx_var(T)), (n+2)/3); R = Flxq_powu_pre(C,3,T,p,pi); if (DEBUGLEVEL) timer_printf(&ti," model change: %Ps",Flx_to_ZX(T)); rel.nbmax=2*nb; M = cgetg(rel.nbmax+1, t_VEC); rel.rel = M; rel.nbrel = 0; rel.r = r; rel.off = 3*upowuu(p,r); rel.nb = nbi; rel.nbexp = nb; rel.nbtest=0; Flxq_log_cubic(&rel, C, R, p, pi); setlg(M,1+rel.nbrel); if (DEBUGLEVEL) { err_printf("\n"); timer_printf(&ti," %ld relations, %ld generators (%ld tests)",rel.nbrel,rel.nb,rel.nbtest); } W = check_kernel(r, M, nbi, rel.off + rel.nb - nbi, T, p, pi, m); if (W) break; if (DEBUGLEVEL) timer_start(&ti); smallirred_Flx_next(T,p, pi); } if (DEBUGLEVEL) timer_start(&ti); Ao = Flxq_log_rec(W, a, r, T, p, pi, m); if (DEBUGLEVEL) timer_printf(&ti,"smooth element"); Bo = Flxq_log_rec(W, b, r, T, p, pi, m); if (DEBUGLEVEL) timer_printf(&ti,"smooth generator"); e = Fp_div(Ao, Bo, m); if (!Flx_equal(Flxq_pow_pre(b0, e, T0, p, pi), a0)) pari_err_BUG("Flxq_log"); return gerepileupto(av, e); } INLINE GEN Flx_frob(GEN u, ulong p) { return Flx_inflate(u, p); } static GEN rel_Coppersmith(long r, GEN u, GEN v, long h, GEN R, long d, ulong p, ulong pi) { GEN a, b, F, G, M; if (degpol(Flx_gcd_pre(u,v,p,pi))) return NULL; a = Flx_add(Flx_shift(u, h), v, p); if (lgpol(a)==0 || !Flx_is_smooth_pre(a, r, p, pi)) return NULL; b = Flx_add(Flx_mul_pre(R, Flx_frob(u, p), p, pi), Flx_shift(Flx_frob(v, p),d), p); if (!Flx_is_smooth_pre(b, r, p, pi)) return NULL; F = factorel(a, p); G = factorel(b, p); M = mkmat2(vecsmall_concat(gel(F, 1), vecsmall_append(gel(G, 1), 2*p)), vecsmall_concat(zv_z_mul(gel(F, 2),p), vecsmall_append(zv_neg(gel(G, 2)),d))); return famatsmall_reduce(M); } GEN Flxq_log_Coppersmith_worker(GEN u, long i, GEN V, GEN R) { long r = V[1], h = V[2], d = V[3], p = V[4], pi = V[5], dT = V[6]; pari_sp ltop = avma; GEN v = zero_zv(dT+2); GEN L = cgetg(2*i+1, t_VEC); pari_sp av = avma; long j; long nbtest=0, rel = 1; ulong lu = Flx_lead(u), lv; for (j=1; j<=i; j++) { GEN z; Flx_cnext(v, p); Flx_renormalize_inplace(v, dT+2); lv = Flx_lead(v); set_avma(av); if (lu != 1 && lv != 1) continue; if (degpol(Flx_gcd_pre(u, v, p, pi))!=0) continue; if (lu==1) { z = rel_Coppersmith(r, u, v, h, R, d, p, pi); nbtest++; if (z) { gel(L, rel++) = z; av = avma; } } if (i==j) continue; if (lv==1) { z = rel_Coppersmith(r, v, u, h, R, d, p, pi); nbtest++; if (z) { gel(L, rel++) = z; av = avma; } } } setlg(L,rel); return gerepilecopy(ltop, mkvec2(stoi(nbtest), L)); } static GEN Flxq_log_Coppersmith(long nbrel, long r, GEN T, ulong p, ulong pi) { pari_sp av; long dT = degpol(T); long h = dT/p, d = dT-(h*p); GEN R = Flx_sub(Flx_shift(pol1_Flx(T[1]), dT), T, p); GEN u = zero_zv(dT+2); GEN done; long nbtest = 0, rel = 0; GEN M = cgetg(nbrel+1, t_VEC); long i = 1; GEN worker = snm_closure(is_entry("_Flxq_log_Coppersmith_worker"), mkvec2(mkvecsmalln(6, r,h,d,p,pi,dT), R)); struct pari_mt pt; long running, pending = 0, stop=0; if (DEBUGLEVEL) err_printf("Coppersmith (R = %ld): ",degpol(R)); mt_queue_start(&pt, worker); av = avma; while ((running = !stop) || pending) { GEN L; long l, j; Flx_cnext(u, p); Flx_renormalize_inplace(u, dT+2); mt_queue_submit(&pt, 0, running ? mkvec2(u, stoi(i)): NULL); done = mt_queue_get(&pt, NULL, &pending); if (!done) continue; L = gel(done, 2); nbtest += itos(gel(done,1)); l = lg(L); if (l > 1) { for (j=1; jnbrel) break; gel(M,++rel) = gel(L,j); if (DEBUGLEVEL && (rel&511UL)==0) err_printf("%ld%%[%ld] ",rel*100/nbrel,i); } av = avma; } else set_avma(av); if (rel>nbrel) stop = 1; i++; } mt_queue_end(&pt); if (DEBUGLEVEL) err_printf(": %ld tests\n", nbtest); return M; } static GEN Flxq_log_Coppersmith_d(GEN W, GEN g, long r, GEN T, ulong p, ulong pi, GEN mo); static GEN Flxq_log_from_rel(GEN W, GEN rel, long r, GEN T, ulong p, ulong pi, GEN m) { pari_sp av = avma; GEN F = gel(rel,1), E = gel(rel,2), o = gen_0; long i, l = lg(F); for(i=1; i1) err_printf("Found %lu\n", idx); } return gerepileuptoint(av, l); } } set_avma(av); return NULL; } static GEN Flxq_log_Coppersmith_rec(GEN W, long r2, GEN a, long r, GEN T, ulong p, ulong pi, GEN m) { GEN b = polx_Flx(T[1]); long AV = 0; GEN g = a, bad = pol0_Flx(T[1]); pari_timer ti; while(1) { long i, l; GEN V, F, E, Ao; timer_start(&ti); V = Flxq_log_find_rel(b, r2, T, p, pi, &g, &AV); if (DEBUGLEVEL>1) timer_printf(&ti,"%ld-smooth element",r2); F = gel(V,1); E = gel(V,2); l = lg(F); Ao = gen_0; for(i=1; i41)) return Flxq_log_index_Coppersmith(a, b, m, T, p); else return Flxq_log_index_cubic(a, b, m, T, p); } int Flxq_log_use_index(GEN m, GEN T, ulong p) { long d = get_Flx_degree(T); if (p==3 || (p==5 && d>41)) return 1; else if (d<=4 || d==6) return 0; else return Flxq_log_use_index_cubic(m, T, p); } pari-2.17.2/src/basemath/trans1.c0000644000175000017500000032235614760137411015132 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /********************************************************************/ /** **/ /** TRANSCENDENTAL FUNCTIONS **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_trans #ifdef LONG_IS_64BIT static const long SQRTVERYBIGINT = 3037000500L; /* ceil(sqrt(LONG_MAX)) */ #else static const long SQRTVERYBIGINT = 46341L; #endif static THREAD GEN gcatalan, geuler, glog2, gpi; void pari_init_floats(void) { gcatalan = geuler = gpi = zetazone = bernzone = glog2 = eulerzone = NULL; } void pari_close_floats(void) { guncloneNULL(gcatalan); guncloneNULL(geuler); guncloneNULL(gpi); guncloneNULL(glog2); guncloneNULL(zetazone); guncloneNULL_deep(bernzone); guncloneNULL_deep(eulerzone); } /********************************************************************/ /** GENERIC BINARY SPLITTING **/ /** (Haible, Papanikolaou) **/ /********************************************************************/ void abpq_init(struct abpq *A, long n) { A->a = (GEN*)new_chunk(n+1); A->b = (GEN*)new_chunk(n+1); A->p = (GEN*)new_chunk(n+1); A->q = (GEN*)new_chunk(n+1); } static GEN mulii3(GEN a, GEN b, GEN c) { return mulii(mulii(a,b),c); } /* T_{n1,n1+1} */ static GEN T2(struct abpq *A, long n1) { GEN u = mulii3(A->a[n1], A->b[n1+1], A->q[n1+1]); GEN v = mulii3(A->b[n1], A->a[n1+1], A->p[n1+1]); return mulii(A->p[n1], addii(u, v)); } /* assume n2 > n1. Compute sum_{n1 <= n < n2} a/b(n) p/q(n1)... p/q(n) */ void abpq_sum(struct abpq_res *r, long n1, long n2, struct abpq *A) { struct abpq_res L, R; GEN u1, u2; pari_sp av; long n; switch(n2 - n1) { GEN b, q; case 1: r->P = A->p[n1]; r->Q = A->q[n1]; r->B = A->b[n1]; r->T = mulii(A->a[n1], A->p[n1]); return; case 2: r->P = mulii(A->p[n1], A->p[n1+1]); r->Q = mulii(A->q[n1], A->q[n1+1]); r->B = mulii(A->b[n1], A->b[n1+1]); av = avma; r->T = gerepileuptoint(av, T2(A, n1)); return; case 3: q = mulii(A->q[n1+1], A->q[n1+2]); b = mulii(A->b[n1+1], A->b[n1+2]); r->P = mulii3(A->p[n1], A->p[n1+1], A->p[n1+2]); r->Q = mulii(A->q[n1], q); r->B = mulii(A->b[n1], b); av = avma; u1 = mulii3(b, q, A->a[n1]); u2 = mulii(A->b[n1], T2(A, n1+1)); r->T = gerepileuptoint(av, mulii(A->p[n1], addii(u1, u2))); return; } av = avma; n = (n1 + n2) >> 1; abpq_sum(&L, n1, n, A); abpq_sum(&R, n, n2, A); r->P = mulii(L.P, R.P); r->Q = mulii(L.Q, R.Q); r->B = mulii(L.B, R.B); u1 = mulii3(R.B, R.Q, L.T); u2 = mulii3(L.B, L.P, R.T); r->T = addii(u1,u2); set_avma(av); r->P = icopy(r->P); r->Q = icopy(r->Q); r->B = icopy(r->B); r->T = icopy(r->T); } /********************************************************************/ /** **/ /** PI **/ /** **/ /********************************************************************/ /* replace *old clone by c. Protect against SIGINT */ static void swap_clone(GEN *old, GEN c) { GEN tmp = *old; *old = c; guncloneNULL(tmp); } /* ---- * 53360 (640320)^(1/2) \ (6n)! (545140134 n + 13591409) * -------------------- = / ------------------------------ * Pi ---- (n!)^3 (3n)! (-640320)^(3n) * n>=0 * * Ramanujan's formula + binary splitting */ static GEN pi_ramanujan(long prec) { const ulong B = 545140134, A = 13591409, C = 640320; const double alpha2 = 47.11041314; /* 3log(C/12) / log(2) */ long n, nmax, prec2; struct abpq_res R; struct abpq S; GEN D, u; nmax = (long)(1 + prec2nbits(prec)/alpha2); #ifdef LONG_IS_64BIT D = utoipos(10939058860032000UL); /* C^3/24 */ #else D = uutoi(2546948UL,495419392UL); #endif abpq_init(&S, nmax); S.a[0] = utoipos(A); S.b[0] = S.p[0] = S.q[0] = gen_1; for (n = 1; n <= nmax; n++) { S.a[n] = addiu(muluu(B, n), A); S.b[n] = gen_1; S.p[n] = mulis(muluu(6*n-5, 2*n-1), 1-6*n); S.q[n] = mulii(sqru(n), muliu(D,n)); } abpq_sum(&R, 0, nmax, &S); prec2 = prec+EXTRAPREC64; u = itor(muliu(R.Q,C/12), prec2); return rtor(mulrr(divri(u, R.T), sqrtr_abs(utor(C,prec2))), prec); } #if 0 /* Much slower than binary splitting at least up to prec = 10^8 */ /* Gauss - Brent-Salamin AGM iteration */ static GEN pi_brent_salamin(long prec) { GEN A, B, C; pari_sp av2; long i, G; G = - prec2nbits(prec); incrprec(prec); A = real2n(-1, prec); B = sqrtr_abs(A); /* = 1/sqrt(2) */ setexpo(A, 0); C = real2n(-2, prec); av2 = avma; for (i = 0;; i++) { GEN y, a, b, B_A = subrr(B, A); pari_sp av3 = avma; if (expo(B_A) < G) break; a = addrr(A,B); shiftr_inplace(a, -1); b = mulrr(A,B); affrr(a, A); affrr(sqrtr_abs(b), B); set_avma(av3); y = sqrr(B_A); shiftr_inplace(y, i - 2); affrr(subrr(C, y), C); set_avma(av2); } shiftr_inplace(C, 2); return divrr(sqrr(addrr(A,B)), C); } #endif GEN constpi(long prec) { pari_sp av; GEN tmp; if (gpi && realprec(gpi) >= prec) return gpi; av = avma; tmp = gclone(pi_ramanujan(prec)); swap_clone(&gpi,tmp); return gc_const(av, gpi); } GEN mppi(long prec) { return rtor(constpi(prec), prec); } /* Pi * 2^n */ GEN Pi2n(long n, long prec) { GEN x = mppi(prec); shiftr_inplace(x, n); return x; } /* I * Pi * 2^n */ GEN PiI2n(long n, long prec) { retmkcomplex(gen_0, Pi2n(n, prec)); } /* 2I * Pi */ GEN PiI2(long prec) { return PiI2n(1, prec); } /********************************************************************/ /** **/ /** EULER CONSTANT **/ /** **/ /********************************************************************/ GEN consteuler(long prec) { GEN u,v,a,b,tmpeuler; long l, n1, n, k, x; pari_sp av1, av2; if (geuler && realprec(geuler) >= prec) return geuler; av1 = avma; tmpeuler = cgetr_block(prec); incrprec(prec); l = prec+EXTRAPREC64; x = (long) (1 + prec2nbits_mul(l, M_LN2/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= prec) return gcatalan; tmp = gclone(catalan(prec)); swap_clone(&gcatalan,tmp); return gc_const(av, gcatalan); } GEN mpcatalan(long prec) { return rtor(constcatalan(prec), prec); } /********************************************************************/ /** **/ /** TYPE CONVERSION FOR TRANSCENDENTAL FUNCTIONS **/ /** **/ /********************************************************************/ static GEN transvec(GEN (*f)(GEN,long), GEN x, long prec) { pari_APPLY_same(f(gel(x,i), prec)); } static GEN transvecgen(void *E, GEN (*f)(void *,GEN,long), GEN x, long prec) { pari_APPLY_same(f(E, gel(x,i), prec)); } GEN trans_eval(const char *fun, GEN (*f)(GEN,long), GEN x, long prec) { pari_sp av = avma; if (prec < LOWDEFAULTPREC) pari_err_BUG("trans_eval [prec < 3]"); switch(typ(x)) { case t_INT: x = f(itor(x,prec),prec); break; case t_FRAC: x = f(fractor(x, prec),prec); break; case t_QUAD: x = f(quadtofp(x,prec),prec); break; case t_POLMOD: x = transvec(f, polmod_to_embed(x,prec), prec); break; case t_VEC: case t_COL: case t_MAT: return transvec(f, x, prec); default: pari_err_TYPE(fun,x); return NULL;/*LCOV_EXCL_LINE*/ } return gerepileupto(av, x); } GEN trans_evalgen(const char *fun, void *E, GEN (*f)(void*,GEN,long), GEN x, long prec) { pari_sp av = avma; if (prec < LOWDEFAULTPREC) pari_err_BUG("trans_eval [prec < 3]"); switch(typ(x)) { case t_INT: x = f(E, itor(x,prec),prec); break; case t_FRAC: x = f(E, fractor(x, prec),prec); break; case t_QUAD: x = f(E, quadtofp(x,prec),prec); break; case t_POLMOD: x = transvecgen(E, f, polmod_to_embed(x,prec), prec); break; case t_VEC: case t_COL: case t_MAT: return transvecgen(E, f, x, prec); default: pari_err_TYPE(fun,x); return NULL;/*LCOV_EXCL_LINE*/ } return gerepileupto(av, x); } /*******************************************************************/ /* */ /* POWERING */ /* */ /*******************************************************************/ /* x a t_REAL 0, return exp(x) */ static GEN mpexp0(GEN x) { long e = expo(x); return e >= 0? real_0_bit(e): real_1_bit(-e); } static GEN powr0(GEN x) { return signe(x)? real_1(realprec(x)): mpexp0(x); } /* assume typ(x) = t_VEC */ static int is_ext_qfr(GEN x) { return lg(x) == 3 && typ(gel(x,1)) == t_QFB && !qfb_is_qfi(gel(x,1)) && typ(gel(x,2)) == t_REAL; } /* x t_POL or t_SER, return scalarpol(Rg_get_1(x)) */ static GEN scalarpol_get_1(GEN x) { GEN y = cgetg(3,t_POL); y[1] = evalvarn(varn(x)) | evalsigne(1); gel(y,2) = Rg_get_1(x); return y; } /* to be called by the generic function gpowgs(x,s) when s = 0 */ static GEN gpowg0(GEN x) { long lx, i; GEN y; switch(typ(x)) { case t_INT: case t_REAL: case t_FRAC: case t_PADIC: return gen_1; case t_QUAD: x++; /*fall through*/ case t_COMPLEX: { pari_sp av = avma; GEN a = gpowg0(gel(x,1)); GEN b = gpowg0(gel(x,2)); if (a == gen_1) return b; if (b == gen_1) return a; return gerepileupto(av, gmul(a,b)); } case t_INTMOD: y = cgetg(3,t_INTMOD); gel(y,1) = icopy(gel(x,1)); gel(y,2) = is_pm1(gel(x,1))? gen_0: gen_1; return y; case t_FFELT: return FF_1(x); case t_POLMOD: retmkpolmod(scalarpol_get_1(gel(x,1)), gcopy(gel(x,1))); case t_RFRAC: return scalarpol_get_1(gel(x,2)); case t_POL: case t_SER: return scalarpol_get_1(x); case t_MAT: lx=lg(x); if (lx==1) return cgetg(1,t_MAT); if (lx != lgcols(x)) pari_err_DIM("gpow"); y = matid(lx-1); for (i=1; i 0) * * Use left shift binary algorithm (RS is wasteful: multiplies big numbers, * with LS one of them is the base, hence small). Sign of result is set * to s (= 1,-1). Makes life easier for caller, which otherwise might do a * setsigne(gen_1 / gen_m1) */ static GEN powiu_sign(GEN a, ulong N, long s) { pari_sp av; GEN y; if (lgefint(a) == 3) { /* easy if |a| < 3 */ ulong q = a[2]; if (q == 1) return (s>0)? gen_1: gen_m1; if (q == 2) { a = int2u(N); setsigne(a,s); return a; } q = upowuu(q, N); if (q) return s>0? utoipos(q): utoineg(q); } if (N <= 2) { if (N == 2) return sqri(a); a = icopy(a); setsigne(a,s); return a; } av = avma; y = gen_powu_i(a, N, NULL, &_sqri, &_muli); setsigne(y,s); return gerepileuptoint(av, y); } /* a^n */ GEN powiu(GEN a, ulong n) { long s; if (!n) return gen_1; s = signe(a); if (!s) return gen_0; return powiu_sign(a, n, (s < 0 && odd(n))? -1: 1); } GEN powis(GEN a, long n) { long s; GEN t, y; if (n >= 0) return powiu(a, n); s = signe(a); if (!s) pari_err_INV("powis",gen_0); t = (s < 0 && odd(n))? gen_m1: gen_1; if (is_pm1(a)) return t; /* n < 0, |a| > 1 */ y = cgetg(3,t_FRAC); gel(y,1) = t; gel(y,2) = powiu_sign(a, -n, 1); /* force denominator > 0 */ return y; } GEN powuu(ulong p, ulong N) { pari_sp av; ulong pN; GEN y; if (!p) return gen_0; if (N <= 2) { if (N == 2) return sqru(p); if (N == 1) return utoipos(p); return gen_1; } pN = upowuu(p, N); if (pN) return utoipos(pN); if (p == 2) return int2u(N); av = avma; y = gen_powu_i(utoipos(p), N, NULL, &_sqri, &_muli); return gerepileuptoint(av, y); } /* return 0 if overflow */ static ulong usqru(ulong p) { return p & HIGHMASK? 0: p*p; } ulong upowuu(ulong p, ulong k) { #ifdef LONG_IS_64BIT const ulong CUTOFF3 = 2642245; const ulong CUTOFF4 = 65535; const ulong CUTOFF5 = 7131; const ulong CUTOFF6 = 1625; const ulong CUTOFF7 = 565; const ulong CUTOFF8 = 255; const ulong CUTOFF9 = 138; const ulong CUTOFF10 = 84; const ulong CUTOFF11 = 56; const ulong CUTOFF12 = 40; const ulong CUTOFF13 = 30; const ulong CUTOFF14 = 23; const ulong CUTOFF15 = 19; const ulong CUTOFF16 = 15; const ulong CUTOFF17 = 13; const ulong CUTOFF18 = 11; const ulong CUTOFF19 = 10; const ulong CUTOFF20 = 9; #else const ulong CUTOFF3 = 1625; const ulong CUTOFF4 = 255; const ulong CUTOFF5 = 84; const ulong CUTOFF6 = 40; const ulong CUTOFF7 = 23; const ulong CUTOFF8 = 15; const ulong CUTOFF9 = 11; const ulong CUTOFF10 = 9; const ulong CUTOFF11 = 7; const ulong CUTOFF12 = 6; const ulong CUTOFF13 = 5; const ulong CUTOFF14 = 4; const ulong CUTOFF15 = 4; const ulong CUTOFF16 = 3; const ulong CUTOFF17 = 3; const ulong CUTOFF18 = 3; const ulong CUTOFF19 = 3; const ulong CUTOFF20 = 3; #endif if (p <= 2) { if (p < 2) return p; return k < BITS_IN_LONG? 1UL< CUTOFF3) return 0; return p*p*p; case 4: if (p > CUTOFF4) return 0; p2=p*p; return p2*p2; case 5: if (p > CUTOFF5) return 0; p2=p*p; return p2*p2*p; case 6: if (p > CUTOFF6) return 0; p2=p*p; return p2*p2*p2; case 7: if (p > CUTOFF7) return 0; p2=p*p; return p2*p2*p2*p; case 8: if (p > CUTOFF8) return 0; p2=p*p; p4=p2*p2; return p4*p4; case 9: if (p > CUTOFF9) return 0; p2=p*p; p4=p2*p2; return p4*p4*p; case 10: if (p > CUTOFF10)return 0; p2=p*p; p4=p2*p2; return p4*p4*p2; case 11: if (p > CUTOFF11)return 0; p2=p*p; p4=p2*p2; return p4*p4*p2*p; case 12: if (p > CUTOFF12)return 0; p2=p*p; p4=p2*p2; return p4*p4*p4; case 13: if (p > CUTOFF13)return 0; p2=p*p; p4=p2*p2; return p4*p4*p4*p; case 14: if (p > CUTOFF14)return 0; p2=p*p; p4=p2*p2; return p4*p4*p4*p2; case 15: if (p > CUTOFF15)return 0; p2=p*p; p3=p2*p; p5=p3*p2; return p5*p5*p5; case 16: if (p > CUTOFF16)return 0; p2=p*p; p4=p2*p2; p8=p4*p4; return p8*p8; case 17: if (p > CUTOFF17)return 0; p2=p*p; p4=p2*p2; p8=p4*p4; return p*p8*p8; case 18: if (p > CUTOFF18)return 0; p2=p*p; p4=p2*p2; p8=p4*p4; return p2*p8*p8; case 19: if (p > CUTOFF19)return 0; p2=p*p; p4=p2*p2; p8=p4*p4; return p*p2*p8*p8; case 20: if (p > CUTOFF20)return 0; p2=p*p; p4=p2*p2; p8=p4*p4; return p4*p8*p8; } #ifdef LONG_IS_64BIT switch(p) { case 3: if (k > 40) return 0; break; case 4: if (k > 31) return 0; return 1UL<<(2*k); case 5: if (k > 27) return 0; break; case 6: if (k > 24) return 0; break; case 7: if (k > 22) return 0; break; default: return 0; } /* no overflow */ { ulong q = upowuu(p, k >> 1); q *= q ; return odd(k)? q*p: q; } #else return 0; #endif } GEN upowers(ulong x, long n) { long i; GEN p = cgetg(n + 2, t_VECSMALL); uel(p,1) = 1; if (n == 0) return p; uel(p,2) = x; for (i = 3; i <= n; i++) uel(p,i) = uel(p,i-1)*x; return p; } typedef struct { long prec, a; GEN (*sqr)(GEN); GEN (*mulug)(ulong,GEN); } sr_muldata; static GEN _rpowuu_sqr(void *data, GEN x) { sr_muldata *D = (sr_muldata *)data; if (typ(x) == t_INT && lg2prec(lgefint(x)) >= D->prec) { /* switch to t_REAL */ D->sqr = &sqrr; D->mulug = &mulur; x = itor(x, D->prec); } return D->sqr(x); } static GEN _rpowuu_msqr(void *data, GEN x) { GEN x2 = _rpowuu_sqr(data, x); sr_muldata *D = (sr_muldata *)data; return D->mulug(D->a, x2); } /* return a^n as a t_REAL of precision prec. Assume a > 0, n > 0 */ GEN rpowuu(ulong a, ulong n, long prec) { pari_sp av; GEN y, z; sr_muldata D; if (a == 1) return real_1(prec); if (a == 2) return real2n(n, prec); if (n == 1) return utor(a, prec); z = cgetr(prec); av = avma; D.sqr = &sqri; D.mulug = &mului; D.prec = prec; D.a = (long)a; y = gen_powu_fold_i(utoipos(a), n, (void*)&D, &_rpowuu_sqr, &_rpowuu_msqr); mpaff(y, z); return gc_const(av,z); } GEN powrs(GEN x, long n) { pari_sp av = avma; GEN y; if (!n) return powr0(x); y = gen_powu_i(x, (ulong)labs(n), NULL, &_sqrr, &_mulr); if (n < 0) y = invr(y); return gerepileuptoleaf(av,y); } GEN powru(GEN x, ulong n) { pari_sp av = avma; GEN y; if (!n) return powr0(x); y = gen_powu_i(x, n, NULL, &_sqrr, &_mulr); return gerepileuptoleaf(av,y); } GEN powersr(GEN x, long n) { long prec = realprec(x); return gen_powers(x, n, 1, &prec, &_sqrr, &_mulr, &_oner); } /* x^(s/2), assume x t_REAL */ GEN powrshalf(GEN x, long s) { if (s & 1) return sqrtr(powrs(x, s)); return powrs(x, s>>1); } /* x^(s/2), assume x t_REAL */ GEN powruhalf(GEN x, ulong s) { if (s & 1) return sqrtr(powru(x, s)); return powru(x, s>>1); } /* x^(n/d), assume x t_REAL, return t_REAL */ GEN powrfrac(GEN x, long n, long d) { long z; if (!n) return powr0(x); z = cgcd(n, d); if (z > 1) { n /= z; d /= z; } if (d == 1) return powrs(x, n); x = powrs(x, n); if (d == 2) return sqrtr(x); return sqrtnr(x, d); } /* assume x != 0 */ static GEN pow_monome(GEN x, long n) { long i, d, dx = degpol(x); GEN A, b, y; if (n < 0) { n = -n; y = cgetg(3, t_RFRAC); } else y = NULL; if (HIGHWORD(dx) || HIGHWORD(n)) { LOCAL_HIREMAINDER; d = (long)mulll((ulong)dx, (ulong)n); if (hiremainder || (d &~ LGBITS)) d = LGBITS; /* overflow */ d += 2; } else d = dx*n + 2; if ((d + 1) & ~LGBITS) pari_err(e_OVERFLOW,"pow_monome [degree]"); A = cgetg(d+1, t_POL); A[1] = x[1]; for (i=2; i < d; i++) gel(A,i) = gen_0; b = gpowgs(gel(x,dx+2), n); /* not memory clean if (n < 0) */ if (!y) y = A; else { GEN c = denom_i(b); gel(y,1) = c; if (c != gen_1) b = gmul(b,c); gel(y,2) = A; } gel(A,d) = b; return y; } /* x t_PADIC */ static GEN powps(GEN x, long n) { long e = n*valp(x), v; GEN t, y, mod, p = gel(x,2); pari_sp av; if (!signe(gel(x,4))) { if (n < 0) pari_err_INV("powps",x); return zeropadic(p, e); } v = z_pval(n, p); y = cgetg(5,t_PADIC); mod = gel(x,3); if (v == 0) mod = icopy(mod); else { if (precp(x) == 1 && absequaliu(p, 2)) v++; mod = mulii(mod, powiu(p,v)); mod = gerepileuptoint((pari_sp)y, mod); } y[1] = evalprecp(precp(x) + v) | evalvalp(e); gel(y,2) = icopy(p); gel(y,3) = mod; av = avma; t = gel(x,4); if (n < 0) { t = Fp_inv(t, mod); n = -n; } t = Fp_powu(t, n, mod); gel(y,4) = gerepileuptoint(av, t); return y; } /* x t_PADIC */ static GEN powp(GEN x, GEN n) { long v; GEN y, mod, p = gel(x,2); if (valp(x)) pari_err_OVERFLOW("valp()"); if (!signe(gel(x,4))) { if (signe(n) < 0) pari_err_INV("powp",x); return zeropadic(p, 0); } v = Z_pval(n, p); y = cgetg(5,t_PADIC); mod = gel(x,3); if (v == 0) mod = icopy(mod); else { mod = mulii(mod, powiu(p,v)); mod = gerepileuptoint((pari_sp)y, mod); } y[1] = evalprecp(precp(x) + v) | _evalvalp(0); gel(y,2) = icopy(p); gel(y,3) = mod; gel(y,4) = Fp_pow(gel(x,4), n, mod); return y; } static GEN pow_polmod(GEN x, GEN n) { GEN z = cgetg(3, t_POLMOD), a = gel(x,2), T = gel(x,1); gel(z,1) = gcopy(T); if (typ(a) != t_POL || varn(a) != varn(T) || lg(a) <= 3) a = powgi(a, n); else { pari_sp av = avma; GEN p = NULL; if (RgX_is_FpX(T, &p) && RgX_is_FpX(a, &p) && p) { T = RgX_to_FpX(T, p); a = RgX_to_FpX(a, p); if (lgefint(p) == 3) { ulong pp = p[2]; a = Flxq_pow(ZX_to_Flx(a, pp), n, ZX_to_Flx(T, pp), pp); a = Flx_to_ZX(a); } else a = FpXQ_pow(a, n, T, p); a = FpX_to_mod(a, p); a = gerepileupto(av, a); } else { set_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) { long t = typ(x); if (is_scalar_t(t)) return gcopy(x); switch(t) { case t_POL: case t_SER: case t_RFRAC: case t_MAT: case t_VECSMALL: return gcopy(x); case t_VEC: if (!is_ext_qfr(x)) break; /* fall through handle extended t_QFB */ case t_QFB: return qfbred(x); } pari_err_TYPE("gpow", x); } if (n ==-1) return ginv(x); switch(typ(x)) { case t_INT: return powis(x,n); case t_REAL: return powrs(x,n); case t_INTMOD: y = cgetg(3,t_INTMOD); gel(y,1) = icopy(gel(x,1)); gel(y,2) = Fp_pows(gel(x,2), n, gel(x,1)); return y; case t_FRAC: { GEN a = gel(x,1), b = gel(x,2); long s = (signe(a) < 0 && odd(n))? -1: 1; if (n < 0) { n = -n; if (is_pm1(a)) return powiu_sign(b, n, s); /* +-1/x[2] inverts to t_INT */ swap(a, b); } y = cgetg(3, t_FRAC); gel(y,1) = powiu_sign(a, n, s); gel(y,2) = powiu_sign(b, n, 1); return y; } case t_PADIC: return powps(x, n); case t_RFRAC: { av = avma; y = cgetg(3, t_RFRAC); m = labs(n); gel(y,1) = gpowgs(gel(x,1),m); gel(y,2) = gpowgs(gel(x,2),m); if (n < 0) y = ginv(y); return gerepileupto(av,y); } case t_POLMOD: { long N[] = {evaltyp(t_INT) | _evallg(3),0,0}; affsi(n,N); return pow_polmod(x, N); } case t_VEC: if (!is_ext_qfr(x)) pari_err_TYPE("gpow", x); /* fall through handle extended t_QFB */ case t_QFB: return qfbpows(x, n); case t_POL: if (RgX_is_monomial(x)) return pow_monome(x, n); default: { pari_sp av = avma; y = gen_powu_i(x, (ulong)labs(n), NULL, &_sqr, &_mul); if (n < 0) y = ginv(y); return gerepileupto(av,y); } } } /* n a t_INT */ GEN powgi(GEN x, GEN n) { GEN y; if (!is_bigint(n)) return gpowgs(x, itos(n)); /* probable overflow for nonmodular types (typical exception: (X^0)^N) */ switch(typ(x)) { case t_INTMOD: y = cgetg(3,t_INTMOD); gel(y,1) = icopy(gel(x,1)); gel(y,2) = Fp_pow(gel(x,2), n, gel(x,1)); return y; case t_FFELT: return FF_pow(x,n); case t_PADIC: return powp(x, n); case t_INT: if (is_pm1(x)) return (signe(x) < 0 && mpodd(n))? gen_m1: gen_1; if (signe(x)) pari_err_OVERFLOW("lg()"); if (signe(n) < 0) pari_err_INV("powgi",gen_0); return gen_0; case t_FRAC: pari_err_OVERFLOW("lg()"); case t_VEC: if (!is_ext_qfr(x)) pari_err_TYPE("gpow",x); /* fall through handle extended t_QFB */ case t_QFB: return qfbpow(x, n); case t_POLMOD: return pow_polmod(x, n); default: { pari_sp av = avma; y = gen_pow_i(x, n, NULL, &_sqr, &_mul); if (signe(n) < 0) return gerepileupto(av, ginv(y)); return gerepilecopy(av,y); } } } /* Assume x = 1 + O(t), n a scalar. Return x^n */ static GEN ser_pow_1(GEN x, GEN n) { long lx, mi, i, j, d; GEN y = cgetg_copy(x, &lx), X = x+2, Y = y + 2; y[1] = evalsigne(1) | _evalvalser(0) | evalvarn(varn(x)); d = mi = lx-3; while (mi>=1 && isrationalzero(gel(X,mi))) mi--; gel(Y,0) = gen_1; for (i=1; i<=d; i++) { pari_sp av = avma; GEN s = gen_0; for (j=1; j<=minss(i,mi); j++) { GEN t = gsubgs(gmulgu(n,j),i-j); s = gadd(s, gmul(gmul(t, gel(X,j)), gel(Y,i-j))); } gel(Y,i) = gerepileupto(av, gdivgu(s,i)); } return y; } /* we suppose n != 0, valser(x) = 0 and leading-term(x) != 0. Not stack clean */ static GEN ser_pow(GEN x, GEN n, long prec) { GEN y, c, lead; if (varncmp(gvar(n), varn(x)) <= 0) return gexp(gmul(n, glog(x,prec)), prec); lead = gel(x,2); if (gequal1(lead)) return ser_pow_1(x, n); x = ser_normalize(x); if (typ(n) == t_FRAC && !isinexact(lead) && ispower(lead, gel(n,2), &c)) c = powgi(c, gel(n,1)); else c = gpow(lead,n, prec); y = gmul(c, ser_pow_1(x, n)); /* gpow(t_POLMOD,n) can be a t_COL [conjvec] */ if (typ(y) != t_SER) pari_err_TYPE("gpow", y); return y; } static long val_from_i(GEN E) { if (is_bigint(E)) pari_err_OVERFLOW("sqrtn [valuation]"); return itos(E); } /* return x^q, assume typ(x) = t_SER, typ(q) = t_INT/t_FRAC and q != 0 */ static GEN ser_powfrac(GEN x, GEN q, long prec) { GEN y, E = gmulsg(valser(x), q); long e; if (!signe(x)) { if (gsigne(q) < 0) pari_err_INV("gpow", x); return zeroser(varn(x), val_from_i(gfloor(E))); } if (typ(E) != t_INT) pari_err_DOMAIN("sqrtn", "valuation", "!=", mkintmod(gen_0, gel(q,2)), x); e = val_from_i(E); y = leafcopy(x); setvalser(y, 0); y = ser_pow(y, q, prec); setvalser(y, e); return y; } static GEN gpow0(GEN x, GEN n, long prec) { pari_sp av = avma; long i, lx; GEN y; switch(typ(n)) { case t_INT: case t_REAL: case t_FRAC: case t_COMPLEX: case t_QUAD: break; case t_VEC: case t_COL: case t_MAT: y = cgetg_copy(n, &lx); for (i=1; i= BITS_IN_LONG-1) pari_err_OVERFLOW("expo()"); q = d < 0 ? - (long) qd: (long) qd; *sh = q; if (q) { long l = realprec(x) + EXTRAPRECWORD; x = subrr(rtor(x,l), mulsr(q, mplog2(l))); if (!signe(x)) return NULL; } return x; } /* x^n, n a t_FRAC */ static GEN powfrac(GEN x, GEN n, long prec) { GEN a = gel(n,1), d = gel(n,2); long D = itos_or_0(d); if (D == 2) { GEN y = gsqrt(x,prec); if (!equali1(a)) y = gmul(y, powgi(x, shifti(subiu(a,1), -1))); return y; } if (D && is_real_t(typ(x)) && gsigne(x) > 0) { /* x^n = x^q * x^(r/D) */ GEN z, r, q = truedvmdis(a, D, &r); if (typ(x) == t_REAL) { z = sqrtnr(x, D); if (!equali1(r)) z = powgi(z, r); if (signe(q)) z = gmul(z, powgi(x, q)); } else { GEN X = x; x = gtofp(x, prec + nbits2extraprec(expi(r))); z = sqrtnr(x, D); if (!equali1(r)) z = powgi(z, r); if (signe(q)) { long e = typ(X)==t_INT? expi(X): maxuu(expi(gel(X,1)), expi(gel(X,2))); z = gmul(z, powgi(cmpiu(muliu(q,e), realprec(x)) > 0? x: X, q)); } } return z; } return NULL; } /* n = a+ib, x > 0 real, ex ~ |log2(x)|; return precision at which * log(x) must be computed to evaluate x^n */ long powcx_prec(long ex, GEN n, long prec) { GEN a = gel(n,1), b = gel(n,2); long e = (ex < 2)? 0: expu(ex); e += gexpo_safe(is_rational_t(typ(a))? b: n); return e > 2? prec + nbits2extraprec(e): prec; } GEN powcx(GEN x, GEN logx, GEN n, long prec) { GEN sxb, cxb, xa, a = gel(n,1), xb = gmul(gel(n,2), logx); long sh, p = realprec(logx); switch(typ(a)) { case t_INT: xa = powgi(x, a); break; case t_FRAC: xa = powfrac(x, a, prec); if (xa) break; default: xa = modlog2(gmul(gel(n,1), logx), &sh); if (!xa) xa = real2n(sh, prec); else { if (signe(xa) && realprec(xa) > prec) setprec(xa, prec); xa = mpexp(xa); shiftr_inplace(xa, sh); } } if (typ(xb) != t_REAL) return xa; if (gexpo(xb) > 30) { GEN q, P = Pi2n(-2, p), z = addrr(xb,P); /* = x + Pi/4 */ shiftr_inplace(P, 1); q = floorr(divrr(z, P)); /* round ( x / (Pi/2) ) */ xb = subrr(xb, mulir(q, P)); /* x mod Pi/2 */ sh = Mod4(q); } else { long q = floor(rtodbl(xb) / (M_PI/2) + 0.5); if (q) xb = subrr(xb, mulsr(q, Pi2n(-1,p))); /* x mod Pi/2 */ sh = q & 3; } if (signe(xb) && realprec(xb) > prec) setprec(xb, prec); mpsincos(xb, &sxb, &cxb); return gmul(xa, mulcxpowIs(mkcomplex(cxb, sxb), sh)); } GEN gpow(GEN x, GEN n, long prec) { long prec0, 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 0) { long p = powcx_prec(fabs(dbllog2(x)), n, prec); return gerepileupto(av, powcx(x, glog(x, p), n, prec)); } if (tn == t_PADIC) x = gcvtop(x, gel(n,2), precp(n)); i = precision(n); if (i) prec = i; prec0 = prec; if (!gprecision(x)) { long e = gexpo_safe(n); /* avoided if n = 0 or gexpo not defined */ if (e > 2) prec += nbits2extraprec(e); } y = gmul(n, glog(x,prec)); y = gexp(y,prec); if (prec0 == prec) return gerepileupto(av, y); return gerepilecopy(av, gprec_wtrunc(y,prec0)); } GEN powPis(GEN s, long prec) { pari_sp av = avma; GEN x; if (typ(s) != t_COMPLEX) return gpow(mppi(prec), s, prec); x = mppi(powcx_prec(1, s, prec)); return gerepileupto(av, powcx(x, logr_abs(x), s, prec)); } GEN pow2Pis(GEN s, long prec) { pari_sp av = avma; GEN x; if (typ(s) != t_COMPLEX) return gpow(Pi2n(1,prec), s, prec); x = Pi2n(1, powcx_prec(2, s, prec)); return gerepileupto(av, powcx(x, logr_abs(x), s, prec)); } GEN gpowers0(GEN x, long n, GEN x0) { long i, l; GEN V; if (!x0) return gpowers(x,n); if (n < 0) return cgetg(1,t_VEC); l = n+2; V = cgetg(l, t_VEC); gel(V,1) = gcopy(x0); for (i = 2; i < l; i++) gel(V,i) = gmul(gel(V,i-1),x); return V; } GEN gpowers(GEN x, long n) { if (n < 0) return cgetg(1,t_VEC); return gen_powers(x, n, 0, (void*)x, &_sqr, &_mul, &_one); } /* return [q^1,q^4,...,q^{n^2}] */ GEN gsqrpowers(GEN q, long n) { pari_sp av = avma; GEN L = gpowers0(gsqr(q), n, q); /* L[i] = q^(2i - 1), i <= n+1 */ GEN v = cgetg(n+1, t_VEC); long i; gel(v, 1) = gcopy(q); for (i = 2; i <= n ; ++i) gel(v, i) = q = gmul(q, gel(L,i)); /* q^(i^2) */ return gerepileupto(av, v); } /* 4 | N. returns a vector RU which contains exp(2*i*k*Pi/N), k=0..N-1 */ static GEN grootsof1_4(long N, long prec) { GEN z, RU = cgetg(N+1,t_COL), *v = ((GEN*)RU) + 1; long i, N2 = (N>>1), N4 = (N>>2), N8 = (N>>3); /* z^N2 = -1, z^N4 = I; if z^k = a+I*b, then z^(N4-k) = I*conj(z) = b+a*I */ v[0] = gen_1; v[1] = z = rootsof1u_cx(N, prec); if (odd(N4)) N8++; for (i=1; i 0 */ GEN Qp_sqrt(GEN x) { long pp, e = valp(x); GEN z,y,mod, p = gel(x,2); if (gequal0(x)) return zeropadic(p, (e+1) >> 1); if (e & 1) return NULL; y = cgetg(5,t_PADIC); pp = precp(x); mod = gel(x,3); z = gel(x,4); /* lift to t_INT */ e >>= 1; z = Zp_sqrt(z, p, pp); if (!z) return NULL; if (absequaliu(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; GEN b = gen_0, m = gen_1; long j, np; if (typ(d) != t_INT) pari_err_TYPE("Zn_sqrt",d); if (typ(fn) == t_INT) fn = absZ_factor(fn); else if (!is_Z_factorpos(fn)) pari_err_TYPE("Zn_sqrt",fn); np = nbrows(fn); btop = avma; 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 = Zp_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 (gc_needed(btop, 1)) gerepileall(btop, 2, &b, &m); } return gerepileupto(ltop, b); } static GEN sqrt_ser(GEN b, long prec) { long e = valser(b), vx = varn(b), lx, lold, j; ulong mask; GEN a, x, lta, ltx; if (!signe(b)) return zeroser(vx, e>>1); a = leafcopy(b); x = cgetg_copy(b, &lx); if (e & 1) pari_err_DOMAIN("sqrtn", "valuation", "!=", mkintmod(gen_0, gen_2), b); a[1] = x[1] = evalsigne(1) | evalvarn(0) | _evalvalser(0); lta = gel(a,2); if (gequal1(lta)) ltx = lta; else if (!issquareall(lta,<x)) ltx = gsqrt(lta,prec); gel(x,2) = ltx; for (j = 3; j < lx; j++) gel(x,j) = gen_0; setlg(x,3); mask = quadratic_prec_mask(lx - 2); lold = 1; while (mask > 1) { GEN y, x2 = gmul2n(x,1); long l = lold << 1, lx; 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; setvalser(y, lold); y = normalizeser(y); y = gsub(x, gdiv(y, x2)); /* = gmul2n(gsub(x, gdiv(a,x)), -1); */ lx = minss(l+2, lg(y)); for (j = lold+2; j < lx; j++) gel(x,j) = gel(y,j); lold = l; } x[1] = evalsigne(1) | evalvarn(vx) | _evalvalser(e >> 1); return x; } GEN gsqrt(GEN x, long prec) { pari_sp av; GEN y; switch(typ(x)) { case t_INT: if (!signe(x)) return real_0(prec); /* no loss of accuracy */ x = itor(x,prec); /* fall through */ case t_REAL: return sqrtr(x); case t_INTMOD: { GEN p = gel(x,1), a; y = cgetg(3,t_INTMOD); gel(y,1) = icopy(p); a = Fp_sqrt(gel(x,2),p); if (!a) { if (!BPSW_psp(p)) pari_err_PRIME("sqrt [modulus]",p); pari_err_SQRTN("gsqrt",x); } gel(y,2) = a; return y; } case t_COMPLEX: { /* (u+iv)^2 = a+ib <=> u^2+v^2 = sqrt(a^2+b^2), u^2-v^2=a, 2uv=b */ GEN a = gel(x,1), b = gel(x,2), r, u, v; if (isrationalzero(b)) return gsqrt(a, prec); y = cgetg(3,t_COMPLEX); av = avma; r = cxnorm(x); if (typ(r) == t_INTMOD || typ(r) == t_PADIC) pari_err_IMPL("sqrt(complex of t_INTMODs)"); r = gsqrt(r, prec); /* t_REAL, |a+Ib| */ if (!signe(r)) u = v = gerepileuptoleaf(av, sqrtr(r)); else if (gsigne(a) < 0) { /* v > 0 since r > 0, a < 0, rounding errors can't make the sum of two * positive numbers = 0 */ v = sqrtr( gmul2n(gsub(r,a), -1) ); if (gsigne(b) < 0) togglesign(v); v = gerepileuptoleaf(av, v); av = avma; /* v = 0 is impossible */ u = gerepileuptoleaf(av, gdiv(b, shiftr(v,1))); } else { u = sqrtr( gmul2n(gadd(r,a), -1) ); u = gerepileuptoleaf(av, u); av = avma; if (!signe(u)) /* possible if a = 0.0, e.g. sqrt(0.e-10+1e-10*I) */ v = u; else v = gerepileuptoleaf(av, gdiv(b, shiftr(u,1))); } gel(y,1) = u; gel(y,2) = v; return y; } case t_PADIC: y = Qp_sqrt(x); if (!y) pari_err_SQRTN("Qp_sqrt",x); return y; case t_FFELT: return FF_sqrt(x); default: av = avma; if (!(y = toser_i(x))) break; return gerepilecopy(av, sqrt_ser(y, prec)); } return trans_eval("sqrt",gsqrt,x,prec); } /********************************************************************/ /** **/ /** N-th ROOT **/ /** **/ /********************************************************************/ static GEN Z_to_padic(GEN a, GEN p, long e) { if (signe(a)==0) return zeropadic(p, e); else { GEN z = cgetg(5, t_PADIC); long v = Z_pvalrem(a, p, &a), d = e - v; z[1] = evalprecp(d) | evalvalp(v); gel(z,2) = icopy(p); gel(z,3) = powiu(p, d); gel(z,4) = a; return z; } } GEN Qp_log(GEN x) { pari_sp av = avma; GEN y, p = gel(x,2), a = gel(x,4); long e = precp(x); if (!signe(a)) pari_err_DOMAIN("Qp_log", "argument", "=", gen_0, x); if (absequaliu(p,2) || equali1(modii(a, p))) y = Zp_log(a, p, e); else { /* compute log(x^(p-1)) / (p-1) */ GEN q = gel(x,3), t = subiu(p, 1); a = Fp_pow(a, t, q); y = Fp_mul(Zp_log(a, p, e), diviiexact(subsi(1, q), t), q); } return gerepileupto(av, Z_to_padic(y, p, e)); } 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 (absequaliu(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,subiu(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; } return gc_const(av,r); } GEN Qp_sqrtn(GEN x, GEN n, GEN *zetan) { pari_sp av, tetpil; GEN q, p; long e; if (absequaliu(n, 2)) { if (zetan) *zetan = gen_m1; if (signe(n) < 0) x = ginv(x); return Qp_sqrt(x); } av = avma; p = gel(x,2); if (!signe(gel(x,4))) { if (signe(n) < 0) pari_err_INV("Qp_sqrtn", x); q = divii(addis(n, valp(x)-1), n); if (zetan) *zetan = gen_1; set_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 && absequaliu(p, 2))? gen_m1 /*-1 in Q_2*/ : gen_1; return x; } tetpil = avma; /* use hensel lift for unramified case */ x = Qp_sqrtn_unram(x, q, zetan); if (!x) return NULL; if (zetan) { GEN *gptr[2]; if (e && absequaliu(p, 2))/*-1 in Q_2*/ { tetpil = avma; x = gcopy(x); *zetan = gneg(*zetan); } gptr[0] = &x; gptr[1] = zetan; gerepilemanysp(av,tetpil,gptr,2); return x; } return gerepile(av,tetpil,x); } GEN sqrtnint(GEN a, long n) { pari_sp av = avma; GEN x, b, q; long s, k, e; const ulong nm1 = n - 1; if (n == 2) return sqrtint(a); if (typ(a) != t_INT) { if (typ(a) == t_REAL) { long e; switch(signe(a)) { case 0: return gen_0; case -1: pari_err_DOMAIN("sqrtnint", "argument", "<", gen_0,a); } e = expo(a); if (e < 0) return gen_0; if (nbits2lg(e+1) > lg(a)) a = floorr(sqrtnr(a,n)); /* try to avoid precision loss in truncation */ else a = sqrtnint(truncr(a),n); } else { GEN b = gfloor(a); if (typ(b) != t_INT) pari_err_TYPE("sqrtint",a); if (signe(b) < 0) pari_err_DOMAIN("sqrtnint", "argument", "<", gen_0,b); a = sqrtnint(b, n); } return gerepileuptoint(av, a); } if (n <= 0) pari_err_DOMAIN("sqrtnint", "n", "<=", gen_0, stoi(n)); if (n == 1) return icopy(a); s = signe(a); if (s < 0) pari_err_DOMAIN("sqrtnint", "x", "<", gen_0, a); if (!s) return gen_0; if (lgefint(a) == 3) return utoi(usqrtn(itou(a), n)); e = expi(a); k = e/(2*n); if (k == 0) { long flag; if (n > e) return gc_const(av, gen_1); flag = cmpii(a, powuu(3, n)); set_avma(av); return (flag < 0) ? gen_2: stoi(3); } if (e < n*BITS_IN_LONG - 1) { ulong xs, qs; b = itor(a, (2*e < n*BITS_IN_LONG)? DEFAULTPREC: MEDDEFAULTPREC); x = mpexp(divru(logr_abs(b), n)); xs = itou(floorr(x)) + 1; /* >= a^(1/n) */ for(;;) { q = divii(a, powuu(xs, nm1)); if (lgefint(q) > 3) break; qs = itou(q); if (qs >= xs) break; xs -= (xs - qs + nm1)/n; } return utoi(xs); } b = addui(1, shifti(a, -n*k)); x = shifti(addui(1, sqrtnint(b, n)), k); q = divii(a, powiu(x, nm1)); while (cmpii(q, x) < 0) /* a priori one iteration, no GC necessary */ { x = subii(x, divis(addui(nm1, subii(x, q)), n)); q = divii(a, powiu(x, nm1)); } return gerepileuptoleaf(av, x); } ulong usqrtn(ulong a, ulong n) { ulong x, s, q; const ulong nm1 = n - 1; if (!n) pari_err_DOMAIN("sqrtnint", "n", "=", gen_0, utoi(n)); if (n == 1 || a == 0) return a; s = 1 + expu(a)/n; x = 1UL << s; q = (nm1*s >= BITS_IN_LONG)? 0: a >> (nm1*s); while (q < x) { ulong X; x -= (x - q + nm1)/n; X = upowuu(x, nm1); q = X? a/X: 0; } return x; } static ulong cubic_prec_mask(long n) { long a = n, i; ulong mask = 0; for(i = 1;; i++, mask *= 3) { long c = a%3; if (c) mask += 3 - c; a = (a+2)/3; if (a==1) return mask + upowuu(3, i); } } /* cubic Newton iteration, |a|^(1/n), assuming a != 0 */ GEN sqrtnr_abs(GEN a, long n) { pari_sp av; GEN x, b; long eextra, eold, n1, n2, prec, B, v; ulong mask; double K = n, X; if (n == 1) return mpabs(a); if (n == 2) return sqrtr_abs(a); prec = realprec(a); v = expo(a) / n; av = avma; if (v) a = shiftr(a, -n*v); b = rtor(a, DEFAULTPREC); x = mpexp(divru(logr_abs(b), n)); if (prec == DEFAULTPREC) { if (v) shiftr_inplace(x, v); return gerepileuptoleaf(av, x); } X = rtodbl(x); K = (K*K-1) / (12*X*X); /* |x_{n+1} - x| < K |x_n - x|^3 */ eextra = dblexpo(K); n1 = n+1; n2 = 2*n; B = prec2nbits(prec); mask = cubic_prec_mask(B + 63); eold = 1; for(;;) { /* reach 64 */ long enew = eold * 3; enew -= mask % 3; if (enew > 64) break; /* back up one step */ mask /= 3; eold = enew; } for(;;) { long pr, enew = eold * 3; GEN y, z; enew -= mask % 3; mask /= 3; pr = nbits2prec(enew + eextra); b = rtor(a, pr); setsigne(b,1); x = rtor(x, pr); y = subrr(powru(x, n), b); z = divrr(y, addrr(mulur(n1, y), mulur(n2, b))); shiftr_inplace(z,1); x = subrr(x, mulrr(x,z)); if (mask == 1) { if (v) shiftr_inplace(x, v); return gerepileuptoleaf(av, gprec_wtrunc(x,prec)); } eold = enew; } } static void shiftc_inplace(GEN z, long d) { shiftr_inplace(gel(z,1), d); shiftr_inplace(gel(z,2), d); } /* exp(2*Pi*I/n), same iteration as sqrtnr_abs, different initial point */ static GEN sqrtnof1(ulong n, long prec) { pari_sp av; GEN x; long eold, n1, n2, B; ulong mask; B = prec2nbits(prec); n1 = n+1; n2 = 2*n; av = avma; x = expIr(divru(Pi2n(1, LOWDEFAULTPREC), n)); if (prec == LOWDEFAULTPREC) return gerepileupto(av, x); mask = cubic_prec_mask(B + BITS_IN_LONG-1); eold = 1; for(;;) { /* reach BITS_IN_LONG */ long enew = eold * 3; enew -= mask % 3; if (enew > BITS_IN_LONG) break; /* back up one step */ mask /= 3; eold = enew; } for(;;) { long pr, enew = eold * 3; GEN y, z; enew -= mask % 3; mask /= 3; pr = nbits2prec(enew); x = cxtofp(x, pr); y = gsub(gpowgs(x, n), gen_1); z = gdiv(y, gaddgs(gmulsg(n1, y), n2)); shiftc_inplace(z,1); x = gmul(x, gsubsg(1, z)); if (mask == 1) return gerepilecopy(av, gprec_w(x,prec)); eold = enew; } } /* exp(2iPi/d) */ GEN rootsof1u_cx(ulong n, long prec) { switch(n) { case 1: return gen_1; case 2: return gen_m1; case 4: return gen_I(); case 3: case 6: case 12: { pari_sp av = avma; GEN a = (n == 3)? mkfrac(gen_m1,gen_2): ghalf; GEN sq3 = sqrtr_abs(utor(3, prec)); shiftr_inplace(sq3, -1); a = (n == 12)? mkcomplex(sq3, a): mkcomplex(a, sq3); return gerepilecopy(av, a); } case 8: { pari_sp av = avma; GEN sq2 = sqrtr_abs(utor(2, prec)); shiftr_inplace(sq2,-1); return gerepilecopy(av, mkcomplex(sq2, sq2)); } } return sqrtnof1(n, prec); } /* e(a/b) */ GEN rootsof1q_cx(long a, long b, long prec) { long g = cgcd(a,b); GEN z; if (g != 1) { a /= g; b /= g; } if (b < 0) { b = -b; a = -a; } z = rootsof1u_cx(b, prec); if (a < 0) { z = conj_i(z); a = -a; } return gpowgs(z, a); } /* initializes powers of e(a/b) */ GEN rootsof1powinit(long a, long b, long prec) { long g = cgcd(a,b); if (g != 1) { a /= g; b /= g; } if (b < 0) { b = -b; a = -a; } a %= b; if (a < 0) a += b; return mkvec2(grootsof1(b,prec), mkvecsmall2(a,b)); } /* T = rootsof1powinit(a,b); return e(a/b)^c */ GEN rootsof1pow(GEN T, long c) { GEN vz = gel(T,1), ab = gel(T,2); long a = ab[1], b = ab[2]; /* a >= 0, b > 0 */ c %= b; if (c < 0) c += b; a = Fl_mul(a, c, b); return gel(vz, a + 1); } /* exp(2iPi/d), assume d a t_INT */ GEN rootsof1_cx(GEN d, long prec) { if (lgefint(d) == 3) return rootsof1u_cx((ulong)d[2], prec); return expIr(divri(Pi2n(1,prec), d)); } GEN gsqrtn(GEN x, GEN n, GEN *zetan, long prec) { long i, lx, tx; pari_sp av; GEN y, z; if (typ(n)!=t_INT) pari_err_TYPE("sqrtn",n); if (!signe(n)) pari_err_DOMAIN("sqrtn", "n", "=", gen_0, n); if (is_pm1(n)) { if (zetan) *zetan = gen_1; return (signe(n) > 0)? gcopy(x): ginv(x); } if (zetan) *zetan = gen_0; tx = typ(x); if (is_matvec_t(tx)) { y = cgetg_copy(x, &lx); for (i=1; i 0 && tx == t_REAL && signe(x) > 0) y = sqrtnr(x, nn); else y = gexp(gdiv(glog(x,prec), n), prec); y = gerepileupto(av, y); } if (zetan) *zetan = rootsof1_cx(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_TYPE("sqrtn",x); return NULL;/* LCOV_EXCL_LINE */ } /********************************************************************/ /** **/ /** 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 = realprec(x), a = expo(x), b = prec2nbits(l), L, i, n, m, 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 */ /* Multiplication is quadratic in this range (l is small, otherwise we * use logAGM + Newton). Set Y = 2^(-e-a) x, compute truncated series * sum_{k <= n} Y^k/k!: this costs roughly * m b^2 + sum_{k <= n} (k e + BITS_IN_LONG)^2 * bit operations with n ~ b/e, |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 */ d = m-dbllog2(x)-1/M_LN2; /* ~ -log_2 Y - 1/log(2) */ while (d <= 0) { d++; m++; } /* d < 0 can occur from expm1 */ L = l + nbits2extraprec(m); b += m; n = (long)(b / d); /* > 0 */ if (n == 1) n = (long)(b / (d + log2((double)n+1))); /* log ~ const in small ranges */ while (n*(d+log2((double)n+1)) < b) n++; /* expect few corrections */ X = rtor(x,L); shiftr_inplace(X, -m); setsigne(X, 1); if (n == 1) p2 = X; else { long s = 0, l1 = nbits2prec((long)(d + n + 16)); GEN unr = real_1(L); pari_sp av2; p2 = cgetr(L); av2 = avma; for (i=n; i>=2; i--, set_avma(av2)) { /* compute X^(n-1)/n! + ... + X/2 + 1 */ GEN p1, p3; setprec(X,l1); p3 = divru(X,i); l1 += nbits2extraprec(dvmdsBIL(s - expo(p3), &s)<L) l1=L; setprec(unr,l1); p1 = addrr_sign(unr,1, i == n? p3: mulrr(p3,p2),1); setprec(p2,l1); affrr(p1,p2); /* p2 <- 1 + (X/i)*p2 */ } setprec(X,L); p2 = mulrr(X,p2); } B = prec2nbits(L); for (i = 1; i <= m; i++) { if (realprec(p2) > L) setprec(p2,L); if (expo(p2) < -B) shiftr_inplace(p2, 1); /* 2 + p2 ~ 2 and may blow up accuracy */ else p2 = mulrr(p2, addsr(2,p2)); } affrr_fixlg(p2,y); return gc_const(av,y); } GEN mpexpm1(GEN x) { const long s = 6; long B, l, sx = signe(x); GEN y, z; pari_sp av; if (!sx) return real_0_bit(expo(x)); l = realprec(x); if (l > maxss(EXPNEWTON_LIMIT, BITS_IN_LONG< 0) return exp1r_abs(x); B = prec2nbits(l); if (cmpsr(-B, x) > 0) return real_m1(l); /* compute exp(x) * (1 - exp(-x)) */ av = avma; y = exp1r_abs(x); /* > 0 */ if (expo(y) >= -B) { z = addsr(1, y); y = divrr(y, z); } setsigne(y, -1); return gerepileuptoleaf(av, y); } static GEN serexp(GEN x, long prec); GEN gexpm1(GEN x, long prec) { switch(typ(x)) { case t_REAL: return mpexpm1(x); case t_COMPLEX: return cxexpm1(x,prec); case t_PADIC: return gsubgs(Qp_exp(x), 1); default: { pari_sp av = avma; long ey; GEN y; if (!(y = toser_i(x))) break; ey = valser(y); if (ey < 0) pari_err_DOMAIN("expm1","valuation", "<", gen_0, x); if (gequal0(y)) return gcopy(y); if (ey) return gerepileupto(av, gsubgs(serexp(y,prec), 1)); else { GEN e1 = gexpm1(gel(y,2), prec), e = gaddgs(e1,1); y = gmul(e, serexp(serchop0(y),prec)); gel(y,2) = e1; return gerepilecopy(av, y); } } } return trans_eval("expm1",gexpm1,x,prec); } /********************************************************************/ /** **/ /** EXP(X) **/ /** **/ /********************************************************************/ static GEN mpexp_basecase(GEN x) { pari_sp av = avma; long sh, l = realprec(x); GEN y, z; y = modlog2(x, &sh); if (!y) { set_avma(av); return real2n(sh, l); } z = addsr(1, exp1r_abs(y)); if (signe(y) < 0) z = invr(z); if (sh) { shiftr_inplace(z, sh); if (realprec(z) > l) z = rtor(z, l); /* spurious precision increase */ } #ifdef DEBUG { GEN t = mplog(z), u = divrr(subrr(x, t),x); if (signe(u) && expo(u) > 5-prec2nbits(minss(l,realprec(t)))) pari_err_BUG("exp"); } #endif return gerepileuptoleaf(av, z); /* NOT affrr, precision often increases */ } GEN mpexp(GEN x) { const long s = 6; /*Initial steps using basecase*/ long i, p, l = realprec(x), sh; GEN a, t, z; ulong mask; if (l <= maxss(EXPNEWTON_LIMIT, (BITS_IN_LONG<>= 1; } a = mpexp_basecase(rtor(x, nbits2prec(p))); x = addrs(x,1); if (realprec(x) < l+EXTRAPREC64) x = rtor(x, l+EXTRAPREC64); a = rtor(a, l+EXTRAPREC64); /*append 0s */ t = NULL; for(;;) { p <<= 1; if (mask & 1) p--; mask >>= 1; setprec(x, nbits2prec(p)); setprec(a, nbits2prec(p)); t = mulrr(a, subrr(x, logr_abs(a))); /* a (x - log(a)) */ if (mask == 1) break; affrr(t, a); set_avma((pari_sp)a); } affrr(t,z); if (sh) shiftr_inplace(z, sh); return gc_const((pari_sp)z, z); } /* x != 0; k = ceil(tn / (te-1)), t = p-1 */ long Qp_exp_prec(GEN x) { long e = valp(x), n = precp(x); ulong a, b, q, r, p, t; if (e < 1) return -1; if (e > n) return 1; p = itos_or_0(gel(x,2)); if (!p) return n / e + 1; if (p == 2) return e < 2? -1: ceildivuu(n, e - 1); /* n >= e > 0, n = qe + r */ /* tn = q (te-1) + rt + q = (q+1)(te-1) - t(e-r) + q + 1 */ t = p - 1; if (e == 1) return n + ceildivuu(n, t - 1); q = n / e; r = n % e; /* k = q + 1 if rt + q < te */ a = umuluu_or_0(e - r, t); if (!a || a > q) return q + 1; b = umuluu_or_0(e, t); if (!b) return q + 2; return q + 1 + ceildivuu(q + 1 - a, b - 1); } static GEN Qp_exp_safe(GEN x) { pari_sp av = avma; GEN p = gel(x,2), a = gel(x,4), z; long d = precp(x), v = valp(x), e = d+v; if (gequal0(x)) return gaddgs(x,1); if (v < (equaliu(p,2)? 2:1)) return NULL; z = Zp_exp(mulii(a,powiu(p,v)), p, e); return gerepileupto(av, Z_to_padic(z, p, e)); } GEN Qp_exp(GEN x) { GEN y = Qp_exp_safe(x); if (!y) pari_err_DOMAIN("gexp(t_PADIC)","argument","",gen_0,x); return y; } static GEN cos_p(GEN x) { long k; pari_sp av; GEN x2, y; if (gequal0(x)) return gaddgs(x,1); k = Qp_exp_prec(x); if (k < 0) return NULL; av = avma; x2 = gsqr(x); if (k & 1) k--; for (y=gen_1; k; k-=2) { GEN t = gdiv(gmul(y,x2), muluu(k, k-1)); y = gsubsg(1, t); } return gerepileupto(av, y); } static GEN sin_p(GEN x) { long k; pari_sp av; GEN x2, y; if (gequal0(x)) return gcopy(x); k = Qp_exp_prec(x); if (k < 0) return NULL; av = avma; x2 = gsqr(x); if (k & 1) k--; for (y=gen_1; k; k-=2) { GEN t = gdiv(gmul(y,x2), muluu(k, k+1)); y = gsubsg(1, t); } return gerepileupto(av, gmul(y, x)); } static GEN cxexp(GEN x, long prec) { GEN r, p1, p2, y = cgetg(3,t_COMPLEX); pari_sp av = avma, tetpil; long l; l = precision(x); if (l > prec) prec = l; if (gequal0(gel(x,1))) { gsincos(gel(x,2),&gel(y,2),&gel(y,1),prec); return y; } r = gexp(gel(x,1),prec); gsincos(gel(x,2),&p2,&p1,prec); tetpil = avma; gel(y,1) = gmul(r,p1); gel(y,2) = gmul(r,p2); gerepilecoeffssp(av,tetpil,y+1,2); return y; } /* given a t_SER x^v s(x), with s(0) != 0, return x^v(s - s(0)), shallow */ GEN serchop0(GEN s) { long i, l = lg(s); GEN y; if (l == 2) return s; if (l == 3 && isexactzero(gel(s,2))) return s; y = cgetg(l, t_SER); y[1] = s[1]; gel(y,2) = gen_0; for (i=3; i =3 && isrationalzero(gel(x,mi))) mi--; mi += e-2; y[1] = evalsigne(1) | _evalvalser(0) | evalvarn(varn(x)); /* zd[i] = coefficient of X^i in z */ xd = x+2-e; yd = y+2; ly -= 2; X = gel(xd,e); if (e != 1) X = gmulgu(X, e); /* left on stack */ X = isint1(X)? NULL: X; gel(yd,0) = gen_1; for (i = 1; i < e; i++) gel(yd,i) = gen_0; for ( ; i < ly; i++) { GEN t = gel(yd,i-e); long J = minss(i, mi); av = avma; if (X) t = gmul(t, X); for (j = e + 1; j <= J; j++) t = gadd(t, gmulgu(gmul(gel(xd,j),gel(yd,i-j)), j)); gel(yd,i) = gerepileupto(av, gdivgu(t, i)); } return y; } av = avma; return gerepileupto(av, gmul(gexp(gel(x,2),prec), serexp(serchop0(x),prec))); } static GEN expQ(GEN x, long prec) { GEN p, q, z, z0 = NULL; pari_sp av; long n, nmax, s, e, b = prec2nbits(prec); double ex; struct abpq_res R; struct abpq S; if (typ(x) == t_INT) { if (!signe(x)) return real_1(prec); p = x; q = gen_1; e = expi(p); if (e > b) return mpexp(itor(x, prec)); } else { long ep, eq, B = usqrt(b) / 2; p = gel(x,1); ep = expi(p); q = gel(x,2); eq = expi(q); if (ep > B || eq > B) return mpexp(fractor(x, prec)); e = ep - eq; if (e < -3) prec += nbits2extraprec(-e); /* see addrr 'extend' rule */ } if (e > 2) { z0 = cgetr(prec); prec += EXTRAPREC64; b += BITS_IN_LONG; } z = cgetr(prec); av = avma; if (e > 0) { /* simplify x/2^e = p / (q * 2^e) */ long v = minss(e, vali(p)); if (v) p = shifti(p, -v); if (e - v) q = shifti(q, e - v); } s = signe(p); if (s < 0) p = negi(p); ex = exp2(dbllog2(x) - e) * 2.718281828; /* exp(1) * x / 2^e, x / 2^e < 2 */ nmax = (long)(1 + exp(dbllambertW0(M_LN2 * b / ex)) * ex); abpq_init(&S, nmax); S.a[0] = S.b[0] = S.p[0] = S.q[0] = gen_1; for (n = 1; n <= nmax; n++) { S.a[n] = gen_1; S.b[n] = gen_1; S.p[n] = p; S.q[n] = muliu(q, n); } abpq_sum(&R, 0, nmax, &S); if (s > 0) rdiviiz(R.T, R.Q, z); else rdiviiz(R.Q, R.T, z); if (e > 0) { q = z; while (e--) q = sqrr(q); if (z0) { affrr(q, z0); z = z0; } else affrr(q,z); } return gc_const(av,z); } GEN gexp(GEN x, long prec) { switch(typ(x)) { case t_INT: case t_FRAC: return expQ(x, prec); case t_REAL: return mpexp(x); case t_COMPLEX: return cxexp(x,prec); case t_PADIC: return Qp_exp(x); default: { pari_sp av = avma; GEN y; if (!(y = toser_i(x))) break; return gerepileupto(av, serexp(y,prec)); } } return trans_eval("exp",gexp,x,prec); } /********************************************************************/ /** **/ /** AGM(X, Y) **/ /** **/ /********************************************************************/ static int agmr_gap(GEN a, GEN b, long L) { GEN d = subrr(b, a); return (signe(d) && expo(d) - expo(b) >= L); } /* assume x > 0 */ static GEN agm1r_abs(GEN x) { long l = realprec(x), L = 5-prec2nbits(l); GEN a1, b1, y = cgetr(l); pari_sp av = avma; a1 = addrr(real_1(l), x); shiftr_inplace(a1, -1); b1 = sqrtr_abs(x); while (agmr_gap(a1,b1,L)) { GEN a = a1; a1 = addrr(a,b1); shiftr_inplace(a1, -1); b1 = sqrtr_abs(mulrr(a,b1)); } affrr_fixlg(a1,y); return gc_const(av,y); } struct agmcx_gap_t { long L, ex, cnt; }; static void agmcx_init(GEN x, long *prec, struct agmcx_gap_t *S) { long l = precision(x); if (l) *prec = l; S->L = 1-prec2nbits(*prec); S->cnt = 0; S->ex = LONG_MAX; } static long agmcx_a_b(GEN x, GEN *a1, GEN *b1, long prec) { long rotate = 0; if (gsigne(real_i(x))<0) { /* Rotate by +/-Pi/2, so that the choice of the principal square * root gives the optimal AGM. So a1 = +/-I*a1, b1=sqrt(-x). */ if (gsigne(imag_i(x))<0) { *a1=mulcxI(*a1); rotate=-1; } else { *a1=mulcxmI(*a1); rotate=1; } x = gneg(x); } *b1 = gsqrt(x, prec); return rotate; } /* return 0 if we must stop the AGM loop (a=b or a ~ b), 1 otherwise */ static int agmcx_gap(GEN a, GEN b, struct agmcx_gap_t *S) { GEN d = gsub(b, a); long ex = S->ex; S->ex = gexpo(d); if (gequal0(d) || S->ex - gexpo(b) < S->L) return 0; /* if (S->ex >= ex) we're no longer making progress; twice in a row */ if (S->ex < ex) S->cnt = 0; else if (S->cnt++) return 0; return 1; } static GEN agm1cx(GEN x, long prec) { struct agmcx_gap_t S; GEN a1, b1; pari_sp av = avma; long rotate; agmcx_init(x, &prec, &S); a1 = gtofp(gmul2n(gadd(real_1(prec), x), -1), prec); rotate = agmcx_a_b(x, &a1, &b1, prec); while (agmcx_gap(a1,b1,&S)) { GEN a = a1; a1 = gmul2n(gadd(a,b1),-1); b1 = gsqrt(gmul(a,b1), prec); } if (rotate) a1 = rotate>0 ? mulcxI(a1):mulcxmI(a1); return gerepilecopy(av,a1); } GEN zellagmcx(GEN a0, GEN b0, GEN r, GEN t, long prec) { struct agmcx_gap_t S; pari_sp av = avma; GEN x = gdiv(a0, b0), a1, b1; long rotate; agmcx_init(x, &prec, &S); a1 = gtofp(gmul2n(gadd(real_1(prec), x), -1), prec); r = gsqrt(gdiv(gmul(a1,gaddgs(r, 1)),gadd(r, x)), prec); t = gmul(r, t); rotate = agmcx_a_b(x, &a1, &b1, prec); while (agmcx_gap(a1,b1,&S)) { GEN a = a1, b = b1; a1 = gmul2n(gadd(a,b),-1); b1 = gsqrt(gmul(a,b), prec); r = gsqrt(gdiv(gmul(a1,gaddgs(r, 1)),gadd(gmul(b, r), a )), prec); t = gmul(r, t); } if (rotate) a1 = rotate>0 ? mulcxI(a1):mulcxmI(a1); a1 = gmul(a1, b0); t = gatan(gdiv(a1,t), prec); /* send t to the fundamental domain if necessary */ if (gsigne(real_i(t))<0) t = gadd(t, mppi(prec)); return gerepileupto(av,gdiv(t,a1)); } static long ser_cmp_expo(GEN A, GEN B) { long e = -(long)HIGHEXPOBIT, d = valser(B) - valser(A); long i, la = lg(A), v = varn(B); for (i = 2; i < la; i++) { GEN a = gel(A,i), b; long ei; if (isexactzero(a)) continue; b = polcoef_i(B, i-2 + d, v); ei = gexpo(a); if (!isexactzero(b)) ei -= gexpo(b); e = maxss(e, ei); } return e; } static GEN ser_agm1(GEN y, long prec) { GEN a1 = y, b1 = gen_1; long l = lg(y)-2, l2 = 6-prec2nbits(prec), eold = LONG_MAX; for(;;) { GEN a = a1, p1; a1 = gmul2n(gadd(a,b1),-1); b1 = gsqrt(gmul(a,b1), prec); p1 = gsub(b1,a1); if (isinexactreal(p1)) { long e = ser_cmp_expo(p1, b1); if (e < l2 || e >= eold) break; eold = e; } else if (valser(p1)-valser(b1) >= l || gequal0(p1)) break; } return a1; } /* agm(1,x) */ static GEN agm1(GEN x, long prec) { GEN y; pari_sp av; if (gequal0(x)) return gcopy(x); switch(typ(x)) { case t_INT: if (!is_pm1(x)) break; return (signe(x) > 0)? real_1(prec): real_0(prec); case t_REAL: return signe(x) > 0? agm1r_abs(x): agm1cx(x, prec); case t_COMPLEX: if (gequal0(gel(x,2))) return agm1(gel(x,1), prec); return agm1cx(x, prec); case t_PADIC: { GEN a1 = x, b1 = gen_1; long l = precp(x); av = avma; for(;;) { GEN a = a1, p1; long ep; a1 = gmul2n(gadd(a,b1),-1); a = gmul(a,b1); b1 = Qp_sqrt(a); if (!b1) pari_err_SQRTN("Qp_sqrt",a); p1 = gsub(b1,a1); ep = valp(p1)-valp(b1); if (ep<=0) { b1 = gneg_i(b1); p1 = gsub(b1,a1); ep=valp(p1)-valp(b1); } if (ep >= l || gequal0(p1)) return gerepilecopy(av,a1); } } default: av = avma; if (!(y = toser_i(x))) break; return gerepilecopy(av, ser_agm1(y, prec)); } return trans_eval("agm",agm1,x,prec); } GEN agm(GEN x, GEN y, long prec) { pari_sp av; if (is_matvec_t(typ(y))) { if (is_matvec_t(typ(x))) pari_err_TYPE2("agm",x,y); swap(x, y); } if (gequal0(y)) return gcopy(y); av = avma; return gerepileupto(av, gmul(y, agm1(gdiv(x,y), prec))); } /* b2 != 0 */ static GEN ellK_i(GEN b2, long prec) { return gdiv(Pi2n(-1, prec), agm1(gsqrt(b2, prec), prec)); } GEN ellK(GEN k, long prec) { pari_sp av = avma; GEN k2 = gsqr(k), b2 = gsubsg(1, k2); if (gequal0(b2)) pari_err_DOMAIN("ellK", "k^2", "=", gen_1, k2); return gerepileupto(av, ellK_i(b2, prec)); } static int magm_gap(GEN a, GEN b, long L) { GEN d = gsub(b, a); return !gequal0(d) && gexpo(d) - gexpo(b) >= L; } /* http://www.ams.org/notices/201208/rtx120801094p.pdf * An Eloquent Formula for the Perimeter of an Ellipse * Semjon Adlaj, Notices of the AMS */ static GEN magm(GEN a, GEN b, long prec) { long L = -prec2nbits(prec) + 16; GEN c = gen_0; while (magm_gap(a, b, L)) { GEN u = gsqrt(gmul(gsub(a, c), gsub(b, c)), prec); a = gmul2n(gadd(a, b), -1); b = gadd(c, u); c = gsub(c, u); } return gmul2n(gadd(a, b), -1); } GEN ellE(GEN k, long prec) { pari_sp av = avma; GEN b2 = gsubsg(1, gsqr(k)); if (gequal0(b2)) { set_avma(av); return real_1(prec); } return gerepileupto(av, gmul(ellK_i(b2, prec), magm(gen_1, b2, prec))); } /********************************************************************/ /** **/ /** LOG(X) **/ /** **/ /********************************************************************/ /* log(2) = 18*atanh(1/26)-2*atanh(1/4801)+8*atanh(1/8749) * faster than 10*atanh(1/17)+4*atanh(13/499) for all precisions, * and than Pi/2M(1,4/2^n) ~ n log(2) for bitprec at least up to 10^8 */ static GEN log2_split(long prec) { GEN u = atanhuu(1, 26, prec); GEN v = atanhuu(1, 4801, prec); GEN w = atanhuu(1, 8749, prec); shiftr_inplace(v, 1); setsigne(v, -1); shiftr_inplace(w, 3); return addrr(mulur(18, u), addrr(v, w)); } GEN constlog2(long prec) { pari_sp av; GEN tmp; if (glog2 && realprec(glog2) >= prec) return glog2; tmp = cgetr_block(prec); av = avma; affrr(log2_split(prec+EXTRAPREC64), tmp); swap_clone(&glog2,tmp); return gc_const(av,glog2); } GEN mplog2(long prec) { return rtor(constlog2(prec), prec); } /* dont check that q != 2^expo(q), done in logr_abs */ static GEN logagmr_abs(GEN q) { long prec = realprec(q), e = expo(q), lim; GEN z = cgetr(prec), y, Q, _4ovQ; pari_sp av = avma; incrprec(prec); lim = prec2nbits(prec) >> 1; Q = rtor(q,prec); shiftr_inplace(Q,lim-e); setsigne(Q,1); _4ovQ = invr(Q); shiftr_inplace(_4ovQ, 2); /* 4/Q */ /* Pi / 2agm(1, 4/Q) ~ log(Q), q = Q * 2^(e-lim) */ y = divrr(Pi2n(-1, prec), agm1r_abs(_4ovQ)); y = addrr(y, mulsr(e - lim, mplog2(prec))); affrr_fixlg(y, z); return gc_const(av,z); } /* sum_{k >= 0} y^(2k+1) / (2k+1), y close to 0 */ static GEN logr_aux(GEN y) { long k, L = realprec(y); /* should be ~ l+1 - (k-2) */ /* log(x) = log(1+y) - log(1-y) = 2 sum_{k odd} y^k / k * Truncate the sum at k = 2n+1, the remainder is * 2 sum_{k >= 2n+3} y^k / k < 2y^(2n+3) / (2n+3)(1-y) < y^(2n+3) * We want y^(2n+3) < y 2^(-prec2nbits(L)), hence * n+1 > -prec2nbits(L) /-log_2(y^2) */ double d = -2*dbllog2r(y); /* ~ -log_2(y^2) */ k = (long)(2*(prec2nbits(L) / d)); k |= 1; if (k >= 3) { GEN T, S = cgetr(L), y2 = sqrr(y), unr = real_1(L); pari_sp av = avma; long s = 0, incs = (long)d, l1 = nbits2prec((long)d); setprec(S, l1); setprec(unr,l1); affrr(divru(unr,k), S); for (k -= 2;; k -= 2) /* k = 2n+1, ..., 1 */ { /* S = y^(2n+1-k)/(2n+1) + ... + 1 / k */ setprec(y2, l1); T = mulrr(S,y2); if (k == 1) break; l1 += nbits2extraprec(dvmdsBIL(s + incs, &s)<L) l1=L; setprec(S, l1); setprec(unr,l1); affrr(addrr(divru(unr, k), T), S); set_avma(av); } /* k = 1 special-cased for eficiency */ y = mulrr(y, addsr(1,T)); /* = log(X)/2 */ } return y; } /*return log(|x|), assuming x != 0 */ GEN logr_abs(GEN X) { long EX, L, m, k, a, b, l = lg(X), p = realprec(X); GEN z, x, y; ulong u; double d; /* 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 = uel(X,2); k = 2; if (u > (~0UL / 3) * 2) { /* choose 1-x/2 */ EX++; u = ~u; while (!u && ++k < l) { u = uel(X,k); u = ~u; } } else { /* choose x - 1 */ u &= ~HIGHBIT; /* u - HIGHBIT, assuming HIGHBIT set */ while (!u && ++k < l) u = uel(X,k); } if (k == l) return EX? mulsr(EX, mplog2(p)): real_0(p); a = bit_accuracy(k) + bfffo(u); /* ~ -log2 |1-x| */ L = p+EXTRAPRECWORD; b = prec2nbits(L - (bit_accuracy(k))); /* take loss of accuracy into account */ if (b > 24*a*log2(prec2lg(L)) && p > LOGAGM_LIMIT) return logagmr_abs(X); z = cgetr(EX? p: p - bit_accuracy(k)); /* 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 * Instead of the above pessimistic estimate for the cost of the sum, use * optimistic estimate (BITS_IN_LONG -> 0) */ d = -a/2.; m = (long)(d + sqrt(d*d + b/6)); /* >= 0 */ if (m > b-a) m = b-a; if (m < 0.2*a) m = 0; else L += nbits2extraprec(m); x = rtor(X,L); setsigne(x,1); shiftr_inplace(x,-EX); /* 2/3 < x < 4/3 */ for (k=1; k<=m; k++) x = sqrtr_abs(x); y = divrr(subrs(x,1), addrs(x,1)); /* = (x-1) / (x+1), close to 0 */ y = logr_aux(y); /* log(1+y) - log(1-y) = log(x) */ shiftr_inplace(y, m + 1); if (EX) y = addrr(y, mulsr(EX, mplog2(p+EXTRAPRECWORD))); affrr_fixlg(y, z); return gc_const((pari_sp)z, z); } /* assume Im(q) != 0 and precision(q) >= prec. Compute log(q) with accuracy * prec [disregard input accuracy] */ GEN logagmcx(GEN q, long prec) { GEN z = cgetc(prec), y, Q, a, b; long lim, e, ea, eb; pari_sp av = avma; int neg = 0; incrprec(prec); if (gsigne(gel(q,1)) < 0) { q = gneg(q); neg = 1; } lim = prec2nbits(prec) >> 1; Q = gtofp(q, prec); a = gel(Q,1); b = gel(Q,2); if (gequal0(a)) { affrr_fixlg(logr_abs(b), gel(z,1)); y = Pi2n(-1, prec); if (signe(b) < 0) setsigne(y, -1); affrr_fixlg(y, gel(z,2)); return gc_const(av,z); } ea = expo(a); eb = expo(b); e = ea <= eb ? lim - eb : lim - ea; shiftr_inplace(a, e); shiftr_inplace(b, e); /* Pi / 2agm(1, 4/Q) ~ log(Q), q = Q * 2^e */ y = gdiv(Pi2n(-1, prec), agm1cx( gdivsg(4, Q), prec )); a = gel(y,1); b = gel(y,2); a = addrr(a, mulsr(-e, mplog2(prec))); if (realprec(a) <= LOWDEFAULTPREC) a = real_0_bit(expo(a)); if (neg) b = gsigne(b) <= 0? gadd(b, mppi(prec)) : gsub(b, mppi(prec)); affrr_fixlg(a, gel(z,1)); affrr_fixlg(b, gel(z,2)); return gc_const(av,z); } GEN mplog(GEN x) { if (signe(x)<=0) pari_err_DOMAIN("mplog", "argument", "<=", gen_0, x); return logr_abs(x); } /* pe = p^e, p prime, 0 < x < pe a t_INT coprime to p. Return the (p-1)-th * root of 1 in (Z/pe)^* congruent to x mod p, resp x mod 4 if p = 2. * Simplified form of Zp_sqrtnlift: 1/(p-1) is trivial to compute */ GEN Zp_teichmuller(GEN x, GEN p, long e, GEN pe) { GEN q, z, p1; pari_sp av; ulong mask; if (absequaliu(p,2)) return (mod4(x) & 2)? subiu(pe,1): gen_1; if (e == 1) return icopy(x); av = avma; p1 = subiu(p, 1); mask = quadratic_prec_mask(e); q = p; z = remii(x, p); while (mask > 1) { /* Newton iteration solving z^{1 - p} = 1, z = x (mod p) */ GEN w, t, qold = q; if (mask <= 3) /* last iteration */ q = pe; else { q = sqri(q); if (mask & 1) q = diviiexact(q, p); } mask >>= 1; /* q <= qold^2 */ if (lgefint(q) == 3) { ulong Z = uel(z,2), Q = uel(q,2), P1 = uel(p1,2); ulong W = (Q-1) / P1; /* -1/(p-1) + O(qold) */ ulong T = Fl_mul(W, Fl_powu(Z,P1,Q) - 1, Q); Z = Fl_mul(Z, 1 + T, Q); z = utoi(Z); } else { w = diviiexact(subiu(qold,1),p1); /* -1/(p-1) + O(qold) */ t = Fp_mul(w, subiu(Fp_pow(z,p1,q), 1), q); z = Fp_mul(z, addui(1,t), q); } } return gerepileuptoint(av, z); } GEN teichmullerinit(long p, long n) { GEN t, pn, g, v; ulong gp, tp; long a, m; if (p == 2) return mkvec(gen_1); if (!uisprime(p)) pari_err_PRIME("teichmullerinit",utoipos(p)); m = p >> 1; /* (p-1)/2 */ tp= gp= pgener_Fl(p); /* order (p-1), gp^m = -1 */ pn = powuu(p, n); v = cgetg(p, t_VEC); t = g = Zp_teichmuller(utoipos(gp), utoipos(p), n, pn); gel(v, 1) = gen_1; gel(v, p-1) = subiu(pn,1); for (a = 1; a < m; a++) { gel(v, tp) = t; gel(v, p - tp) = Fp_neg(t, pn); /* g^(m+a) = -g^a */ if (a < m-1) { t = Fp_mul(t, g, pn); /* g^(a+1) */ tp = Fl_mul(tp, gp, p); /* t mod p */ } } return v; } /* tab from teichmullerinit or NULL */ GEN teichmuller(GEN x, GEN tab) { GEN p, q, y, z; long n, tx = typ(x); if (!tab) { if (tx == t_VEC && lg(x) == 3) { p = gel(x,1); q = gel(x,2); if (typ(p) == t_INT && typ(q) == t_INT) return teichmullerinit(itos(p), itos(q)); } } else if (typ(tab) != t_VEC) pari_err_TYPE("teichmuller",tab); if (tx!=t_PADIC) pari_err_TYPE("teichmuller",x); z = gel(x,4); if (!signe(z)) return gcopy(x); p = gel(x,2); q = gel(x,3); n = precp(x); y = cgetg(5,t_PADIC); y[1] = evalprecp(n) | _evalvalp(0); gel(y,2) = icopy(p); gel(y,3) = icopy(q); if (tab) { ulong pp = itou_or_0(p); if (lg(tab) != (long)pp) pari_err_TYPE("teichmuller",tab); z = gel(tab, umodiu(z, pp)); if (typ(z) != t_INT) pari_err_TYPE("teichmuller",tab); z = remii(z, q); } else z = Zp_teichmuller(z, p, n, q); gel(y,4) = z; return y; } GEN teich(GEN x) { return teichmuller(x, NULL); } GEN glog(GEN x, long prec) { pari_sp av, tetpil; GEN y, p1; long l; switch(typ(x)) { case t_REAL: if (signe(x) >= 0) { if (!signe(x)) pari_err_DOMAIN("log", "argument", "=", gen_0, x); return logr_abs(x); } retmkcomplex(logr_abs(x), mppi(realprec(x))); case t_FRAC: { GEN a, b; long e1, e2; av = avma; a = gel(x,1); b = gel(x,2); e1 = expi(subii(a,b)); e2 = expi(b); if (e2 > e1) prec += nbits2extraprec(e2 - e1); x = fractor(x, prec); return gerepileupto(av, glog(x, prec)); } case t_COMPLEX: if (ismpzero(gel(x,2))) return glog(gel(x,1), prec); l = precision(x); if (l > prec) prec = l; if (ismpzero(gel(x,1))) { GEN a = gel(x,2), b; av = avma; b = Pi2n(-1,prec); if (gsigne(a) < 0) { setsigne(b, -1); a = gabs(a,prec); } a = isint1(a) ? gen_0: glog(a,prec); return gerepilecopy(av, mkcomplex(a, b)); } if (prec >= LOGAGMCX_LIMIT) return logagmcx(x, prec); y = cgetg(3,t_COMPLEX); gel(y,2) = garg(x,prec); av = avma; p1 = glog(cxnorm(x),prec); tetpil = avma; gel(y,1) = gerepile(av,tetpil,gmul2n(p1,-1)); return y; case t_PADIC: return Qp_log(x); default: av = avma; if (!(y = toser_i(x))) break; if (!signe(y)) pari_err_DOMAIN("log", "argument", "=", gen_0, x); if (valser(y)) pari_err_DOMAIN("log", "series valuation", "!=", gen_0, x); p1 = integser(gdiv(derivser(y), y)); /* log(y)' = y'/y */ if (!gequal1(gel(y,2))) p1 = gadd(p1, glog(gel(y,2),prec)); return gerepileupto(av, p1); } return trans_eval("log",glog,x,prec); } static GEN mplog1p(GEN x) { long ex, a, b, l, L; if (!signe(x)) return rcopy(x); ex = expo(x); if (ex >= -3) return glog(addrs(x,1), 0); a = -ex; b = realprec(x); L = b+1; if (b > a*log2(L) && b > LOGAGM_LIMIT) { x = addrs(x,1); l = b + nbits2extraprec(a); if (realprec(x) < l) x = rtor(x,l); return logagmr_abs(x); } x = rtor(x, L); x = logr_aux(divrr(x, addrs(x,2))); if (realprec(x) > b) fixlg(x, b); shiftr_inplace(x,1); return x; } static GEN log1p_i(GEN x, long prec); static GEN cxlog1p(GEN x, long prec) { pari_sp av; GEN z, a, b = gel(x,2); long l; if (ismpzero(b)) return log1p_i(gel(x,1), prec); l = precision(x); if (l > prec) prec = l; if (prec >= LOGAGMCX_LIMIT) return logagmcx(gaddgs(x,1), prec); a = gel(x,1); z = cgetg(3,t_COMPLEX); av = avma; a = gadd(gadd(gmul2n(a,1), gsqr(a)), gsqr(b)); a = log1p_i(a, prec); shiftr_inplace(a,-1); gel(z,1) = gerepileupto(av, a); gel(z,2) = garg(gaddgs(x,1),prec); return z; } static GEN log1p_i(GEN x, long prec) { switch(typ(x)) { case t_REAL: return mplog1p(x); case t_COMPLEX: return cxlog1p(x, prec); case t_PADIC: return Qp_log(gaddgs(x,1)); default: { long ey; GEN y; if (!(y = toser_i(x))) break; ey = valser(y); if (ey < 0) pari_err_DOMAIN("log1p","valuation", "<", gen_0, x); if (gequal0(y)) return gcopy(y); if (ey) return glog(gaddgs(y,1),prec); else { GEN a = gel(y,2), a1 = gaddgs(a,1); y = gdiv(y, a1); gel(y,2) = gen_1; return gadd(glog1p(a,prec), glog(y, prec)); } } } return trans_eval("log1p",glog1p,x,prec); } GEN glog1p(GEN x, long prec) { pari_sp av = avma; return gerepileupto(av, log1p_i(x, prec)); } /********************************************************************/ /** **/ /** SINE, COSINE **/ /** **/ /********************************************************************/ /* Reduce x0 mod Pi/2 to x in [-Pi/4, Pi/4]. Return cos(x)-1 */ static GEN mpcosm1(GEN x, long *ptmod8) { long a = expo(x), l = realprec(x), b, L, i, n, m, B; GEN y, u, x2; double d; n = 0; if (a >= 0) { long p; GEN q; if (a > 30) { GEN z, P = Pi2n(-2, nbits2prec(a + 32)); z = addrr(x,P); /* = x + Pi/4 */ if (expo(z) >= bit_prec(z) + 3) pari_err_PREC("mpcosm1"); shiftr_inplace(P, 1); q = floorr(divrr(z, P)); /* round ( x / (Pi/2) ) */ p = l+EXTRAPREC64; x = rtor(x,p); } else { q = stoi((long)floor(rtodbl(x) / (M_PI/2) + 0.5)); p = l; } if (signe(q)) { GEN y = subrr(x, mulir(q, Pi2n(-1,p))); /* x mod Pi/2 */ long b = expo(y); if (a - b < 7) x = y; else { p += nbits2extraprec(a-b); x = rtor(x, p); x = subrr(x, mulir(q, Pi2n(-1,p))); } a = b; if (!signe(x) && a >= 0) pari_err_PREC("mpcosm1"); n = Mod4(q); } } /* a < 0 */ b = signe(x); *ptmod8 = (b < 0)? 4 + n: n; if (!b) return real_0_bit(expo(x)*2 - 1); b = prec2nbits(l); if (b + 2*a <= 0) { y = sqrr(x); shiftr_inplace(y, -1); setsigne(y, -1); return y; } y = cgetr(l); B = b/6 + BITS_IN_LONG/2 + (BITS_IN_LONG*BITS_IN_LONG/2)/ b; d = a/2.; m = (long)(d + sqrt(d*d + B)); /* >= 0 ,*/ if (m < (-a) * 0.1) m = 0; /* not worth it */ L = l + nbits2extraprec(m); b += m; d = 2.0 * (m-dbllog2r(x)-1/M_LN2); /* ~ 2( - log_2 Y - 1/log(2) ) */ n = (long)(b / d); if (n > 1) n = (long)(b / (d + log2((double)n+1))); /* log~constant in small ranges */ while (n*(d+log2((double)n+1)) < b) n++; /* expect few corrections */ /* Multiplication is quadratic in this range (l is small, otherwise we * use logAGM + Newton). Set Y = 2^(-e-a) x, compute truncated series * sum Y^2k/(2k)!: this costs roughly * m b^2 + sum_{k <= n} (2k e + BITS_IN_LONG)^2 * ~ (b/2e) b^2 / 3 + m b^2 * bit operations with n ~ b/2e, |x| < 2^(1+a), |Y| < 2^(1-e) , m = e+a and * b bits of accuracy needed, so * B := (b / 6 + BITS_IN_LONG/2 + 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 ) * NB: e ~ (b/6)^(1/2) or b/2. * * Truncate the sum at k = n (>= 1), the remainder is * < sum_{k >= n+1} Y^2k / 2k! < Y^(2n+2) / (2n+2)!(1-Y^2) < Y^(2n+2)/(2n+1)! * We want ... <= Y^2 2^-b, hence -2n log_2 |Y| + log_2 (2n+1)! >= b * log n! ~ (n + 1/2) log(n+1) - (n+1) + log(2Pi)/2, * error bounded by 1/6(n+1) <= 1/12. Finally, we want * 2n (-1/log(2) - log_2 |Y| + log_2(2n+2)) >= b */ x = rtor(x, L); shiftr_inplace(x, -m); setsigne(x, 1); x2 = sqrr(x); if (n == 1) { u = x2; shiftr_inplace(u, -1); setsigne(u, -1); } /*-Y^2/2*/ else { GEN un = real_1(L); pari_sp av; long s = 0, l1 = nbits2prec((long)(d + n + 16)); u = cgetr(L); av = avma; for (i = n; i >= 2; i--) { GEN t; setprec(x2,l1); t = divrunextu(x2, 2*i-1); l1 += nbits2extraprec(dvmdsBIL(s - expo(t), &s)< L) l1 = L; if (i != n) t = mulrr(t,u); setprec(un,l1); t = addrr_sign(un,1, t,-signe(t)); setprec(u,l1); affrr(t,u); set_avma(av); } shiftr_inplace(u, -1); togglesign(u); /* u := -u/2 */ setprec(x2,L); u = mulrr(x2,u); } /* Now u = sum {1<= i <=n} (-1)^i x^(2i) / (2i)! ~ cos(x) - 1 */ for (i = 1; i <= m; i++) { /* u = cos(x)-1 <- cos(2x)-1 = 2cos(x)^2 - 2 = 4u + 2u^2*/ GEN q = sqrr(u); shiftr_inplace(u, 1); u = addrr(u, q); shiftr_inplace(u, 1); if ((i & 31) == 0) u = gerepileuptoleaf((pari_sp)y, u); } affrr_fixlg(u, y); return y; } /* sqrt (|1 - (1+x)^2|) = sqrt(|x*(x+2)|). Sends cos(x)-1 to |sin(x)| */ static GEN mpaut(GEN x) { GEN t = mulrr(x, addsr(2,x)); /* != 0 */ if (!signe(t)) return real_0_bit(expo(t) >> 1); return sqrtr_abs(t); } /********************************************************************/ /** COSINE **/ /********************************************************************/ GEN mpcos(GEN x) { long mod8; pari_sp av; GEN y, z; if (!signe(x)) { long l = nbits2prec(-expo(x)); if (l < LOWDEFAULTPREC) l = LOWDEFAULTPREC; return real_1(l); } av = avma; z = mpcosm1(x,&mod8); switch(mod8) { case 0: case 4: y = addsr(1,z); break; case 1: case 7: y = mpaut(z); togglesign(y); break; case 2: case 6: y = subsr(-1,z); break; default: y = mpaut(z); 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 a, b, u, v, y, u1, v1; long i; switch(typ(x)) { case t_REAL: return mpcos(x); case t_COMPLEX: a = gel(x,1); b = gel(x,2); if (isintzero(a)) return gcosh(b, prec); i = precision(x); if (i) prec = i; y = cgetc(prec); av = avma; if (typ(b) != t_REAL) b = gtofp(b, prec); mpsinhcosh(b, &u1, &v1); u1 = mpneg(u1); if (typ(a) != t_REAL) a = gtofp(a, prec); mpsincos(a, &u, &v); affrr_fixlg(gmul(v1,v), gel(y,1)); affrr_fixlg(gmul(u1,u), gel(y,2)); return gc_const(av,y); case t_INT: case t_FRAC: y = cgetr(prec); av = avma; affrr_fixlg(mpcos(tofp_safe(x,prec)), y); return gc_const(av,y); case t_PADIC: y = cos_p(x); if (!y) pari_err_DOMAIN("gcos(t_PADIC)","argument","",gen_0,x); return y; default: av = avma; if (!(y = toser_i(x))) break; if (gequal0(y)) return gerepileupto(av, gaddsg(1,y)); if (valser(y) < 0) pari_err_DOMAIN("cos","valuation", "<", gen_0, x); gsincos(y,&u,&v,prec); return gerepilecopy(av,v); } return trans_eval("cos",gcos,x,prec); } /********************************************************************/ /** SINE **/ /********************************************************************/ GEN mpsin(GEN x) { long mod8; pari_sp av; GEN y, z; if (!signe(x)) return real_0_bit(expo(x)); av = avma; z = mpcosm1(x,&mod8); switch(mod8) { case 0: case 6: y = mpaut(z); break; case 1: case 5: y = addsr(1,z); break; case 2: case 4: y = mpaut(z); togglesign(y); break; default: y = subsr(-1,z); break; /* case 3: case 7: */ } return gerepileuptoleaf(av, y); } GEN gsin(GEN x, long prec) { pari_sp av; GEN a, b, u, v, y, v1, u1; long i; switch(typ(x)) { case t_REAL: return mpsin(x); case t_COMPLEX: a = gel(x,1); b = gel(x,2); if (isintzero(a)) retmkcomplex(gen_0,gsinh(b,prec)); i = precision(x); if (i) prec = i; y = cgetc(prec); av = avma; if (typ(b) != t_REAL) b = gtofp(b, prec); mpsinhcosh(b, &u1, &v1); if (typ(a) != t_REAL) a = gtofp(a, prec); mpsincos(a, &u, &v); affrr_fixlg(gmul(v1,u), gel(y,1)); affrr_fixlg(gmul(u1,v), gel(y,2)); return gc_const(av,y); case t_INT: case t_FRAC: y = cgetr(prec); av = avma; affrr_fixlg(mpsin(tofp_safe(x,prec)), y); return gc_const(av,y); case t_PADIC: y = sin_p(x); if (!y) pari_err_DOMAIN("gsin(t_PADIC)","argument","",gen_0,x); return y; default: av = avma; if (!(y = toser_i(x))) break; if (gequal0(y)) return gerepilecopy(av, y); if (valser(y) < 0) pari_err_DOMAIN("sin","valuation", "<", gen_0, x); gsincos(y,&u,&v,prec); return gerepilecopy(av,u); } return trans_eval("sin",gsin,x,prec); } /********************************************************************/ /** SINE, COSINE together **/ /********************************************************************/ void mpsincos(GEN x, GEN *s, GEN *c) { long mod8; pari_sp av, tetpil; GEN z, *gptr[2]; if (!signe(x)) { long e = expo(x); *s = real_0_bit(e); *c = e >= 0? real_0_bit(e): real_1_bit(-e); return; } av = avma; z = mpcosm1(x, &mod8); tetpil = avma; switch(mod8) { case 0: *c = addsr( 1,z); *s = mpaut(z); break; case 1: *s = addsr( 1,z); *c = mpaut(z); togglesign(*c); break; case 2: *c = subsr(-1,z); *s = mpaut(z); togglesign(*s); break; case 3: *s = subsr(-1,z); *c = mpaut(z); break; case 4: *c = addsr( 1,z); *s = mpaut(z); togglesign(*s); break; case 5: *s = addsr( 1,z); *c = mpaut(z); break; case 6: *c = subsr(-1,z); *s = mpaut(z); break; case 7: *s = subsr(-1,z); *c = mpaut(z); togglesign(*c); break; } gptr[0] = s; gptr[1] = c; gerepilemanysp(av,tetpil,gptr,2); } /* SINE and COSINE - 1 */ void mpsincosm1(GEN x, GEN *s, GEN *c) { long mod8; pari_sp av, tetpil; GEN z, *gptr[2]; if (!signe(x)) { long e = expo(x); *s = real_0_bit(e); *c = real_0_bit(2*e-1); return; } av = avma; z = mpcosm1(x,&mod8); tetpil = avma; switch(mod8) { case 0: *c = rcopy(z); *s = mpaut(z); break; case 1: *s = addsr(1,z); *c = addrs(mpaut(z),1); togglesign(*c); break; case 2: *c = subsr(-2,z); *s = mpaut(z); togglesign(*s); break; case 3: *s = subsr(-1,z); *c = subrs(mpaut(z),1); break; case 4: *c = rcopy(z); *s = mpaut(z); togglesign(*s); break; case 5: *s = addsr( 1,z); *c = subrs(mpaut(z),1); break; case 6: *c = subsr(-2,z); *s = mpaut(z); break; case 7: *s = subsr(-1,z); *c = subsr(-1,mpaut(z)); break; } gptr[0] = s; gptr[1] = c; gerepilemanysp(av,tetpil,gptr,2); } /* return exp(ix), x a t_REAL */ GEN expIr(GEN x) { pari_sp av = avma; GEN v = cgetg(3,t_COMPLEX); mpsincos(x, (GEN*)(v+2), (GEN*)(v+1)); if (!signe(gel(v,2))) return gerepilecopy(av, gel(v,1)); return v; } /* return exp(ix)-1, x a t_REAL */ static GEN expm1_Ir(GEN x) { pari_sp av = avma; GEN v = cgetg(3,t_COMPLEX); mpsincosm1(x, (GEN*)(v+2), (GEN*)(v+1)); if (!signe(gel(v,2))) return gerepilecopy(av, gel(v,1)); return v; } /* return exp(z)-1, z complex */ GEN cxexpm1(GEN z, long prec) { pari_sp av = avma; GEN X, Y, x = real_i(z), y = imag_i(z); long l = precision(z); if (l) prec = l; if (typ(x) != t_REAL) x = gtofp(x, prec); if (typ(y) != t_REAL) y = gtofp(y, prec); if (gequal0(y)) return mpexpm1(x); if (gequal0(x)) return expm1_Ir(y); X = mpexpm1(x); /* t_REAL */ Y = expm1_Ir(y); /* exp(x+iy) - 1 = (exp(x)-1)(exp(iy)-1) + exp(x)-1 + exp(iy)-1 */ return gerepileupto(av, gadd(gadd(X,Y), gmul(X,Y))); } void gsincos(GEN x, GEN *s, GEN *c, long prec) { long i, j, ex, ex2, lx, ly, mi; pari_sp av, tetpil; GEN y, r, u, v, u1, v1, p1, p2, p3, p4, ps, pc; GEN *gptr[4]; switch(typ(x)) { case t_INT: case t_FRAC: *s = cgetr(prec); *c = cgetr(prec); av = avma; mpsincos(tofp_safe(x, prec), &ps, &pc); affrr_fixlg(ps,*s); affrr_fixlg(pc,*c); set_avma(av); return; case t_REAL: mpsincos(x,s,c); return; case t_COMPLEX: i = precision(x); if (i) prec = i; ps = cgetc(prec); *s = ps; pc = cgetc(prec); *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)); set_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 = valser(y); lx = lg(y); ex2 = 2*ex+2; if (ex < 0) pari_err_DOMAIN("gsincos","valuation", "<", gen_0, x); if (ex2 > lx) { *s = x == y? gcopy(y): gerepilecopy(av, y); av = avma; *c = gerepileupto(av, gsubsg(1, gdivgu(gsqr(y),2))); return; } if (!ex) { gsincos(serchop0(y),&u,&v,prec); gsincos(gel(y,2),&u1,&v1,prec); p1 = gmul(v1,v); p2 = gmul(u1,u); p3 = gmul(v1,u); p4 = gmul(u1,v); tetpil = avma; *c = gsub(p1,p2); *s = gadd(p3,p4); gptr[0]=s; gptr[1]=c; gerepilemanysp(av,tetpil,gptr,2); return; } ly = lx+2*ex; mi = lx-1; while (mi>=3 && isrationalzero(gel(y,mi))) mi--; mi += ex-2; pc = cgetg(ly,t_SER); *c = pc; ps = cgetg(lx,t_SER); *s = ps; pc[1] = evalsigne(1) | _evalvalser(0) | evalvarn(varn(y)); gel(pc,2) = gen_1; ps[1] = y[1]; for (i=2; i 2) gel(y,2) = gen_1; return y; } else { GEN z0, y0 = gel(y,2), y1 = serchop0(y), y10 = y1; if (!gequal1(y0)) y10 = gdiv(y10, y0); gsincos(y1,&u,&v,prec); z0 = gdiv(gcos(y0,prec), y0); y = gaddsg(1, y10); u = gadd(gmul(gsinc(y0, prec),v), gmul(z0, u)); return gerepileupto(av,gdiv(u,y)); } } } return trans_eval("sinc",gsinc,x,prec); } /********************************************************************/ /** **/ /** TANGENT and COTANGENT **/ /** **/ /********************************************************************/ static GEN mptan(GEN x) { pari_sp av = avma; GEN s, c; mpsincos(x,&s,&c); if (!signe(c)) pari_err_DOMAIN("tan", "argument", "=", strtoGENstr("Pi/2 + kPi"),x); return gerepileuptoleaf(av, divrr(s,c)); } /* If exp(-|im(x)|) << 1, avoid overflow in sincos(x) */ static int tan_huge_im(GEN ix, long prec) { long b, p = precision(ix); if (!p) p = prec; b = prec2nbits(p); return (gexpo(ix) > b || fabs(gtodouble(ix)) > (M_LN2 / 2) * b); } /* \pm I */ static GEN real_I(long s, long prec) { GEN z = cgetg(3, t_COMPLEX); gel(z,1) = real_0(prec); gel(z,2) = s > 0? real_1(prec): real_m1(prec); return z; } GEN gtan(GEN x, long prec) { pari_sp av; GEN y, s, c; switch(typ(x)) { case t_REAL: return mptan(x); case t_COMPLEX: { if (isintzero(gel(x,1))) retmkcomplex(gen_0,gtanh(gel(x,2),prec)); if (tan_huge_im(gel(x,2), prec)) return real_I(gsigne(gel(x,2)), prec); av = avma; y = mulcxmI(gtanh(mulcxI(x), prec)); /* tan x = -I th(I x) */ gel(y,1) = gcopy(gel(y,1)); return gerepileupto(av, y); } case t_INT: case t_FRAC: y = cgetr(prec); av = avma; affrr_fixlg(mptan(tofp_safe(x,prec)), y); return gc_const(av,y); case t_PADIC: av = avma; return gerepileupto(av, gdiv(gsin(x,prec), gcos(x,prec))); default: av = avma; if (!(y = toser_i(x))) break; if (gequal0(y)) return gerepilecopy(av, y); if (valser(y) < 0) pari_err_DOMAIN("tan","valuation", "<", gen_0, x); gsincos(y,&s,&c,prec); return gerepileupto(av, gdiv(s,c)); } return trans_eval("tan",gtan,x,prec); } static GEN mpcotan(GEN x) { pari_sp av=avma, tetpil; GEN s,c; mpsincos(x,&s,&c); tetpil=avma; return gerepile(av,tetpil,divrr(c,s)); } GEN gcotan(GEN x, long prec) { pari_sp av; GEN y, s, c; switch(typ(x)) { case t_REAL: return mpcotan(x); case t_COMPLEX: if (isintzero(gel(x,1))) { GEN z = cgetg(3, t_COMPLEX); gel(z,1) = gen_0; av = avma; gel(z,2) = gerepileupto(av, gneg(ginv(gtanh(gel(x,2),prec)))); return z; } if (tan_huge_im(gel(x,2), prec)) return real_I(-gsigne(gel(x,2)), prec); av = avma; gsincos(x,&s,&c,prec); return gerepileupto(av, gdiv(c,s)); case t_INT: case t_FRAC: y = cgetr(prec); av = avma; affrr_fixlg(mpcotan(tofp_safe(x,prec)), y); return gc_const(av,y); case t_PADIC: av = avma; return gerepileupto(av, gdiv(gcos(x,prec), gsin(x,prec))); default: av = avma; if (!(y = toser_i(x))) break; if (gequal0(y)) pari_err_DOMAIN("cotan", "argument", "=", gen_0, y); if (valser(y) < 0) pari_err_DOMAIN("cotan","valuation", "<", gen_0, x); gsincos(y,&s,&c,prec); return gerepileupto(av, gdiv(c,s)); } return trans_eval("cotan",gcotan,x,prec); } pari-2.17.2/src/basemath/Zp.c0000644000175000017500000012430714676526175014326 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_hensel /* 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); } } /***********************************************************************/ /** **/ /** Zp **/ /** **/ /***********************************************************************/ static GEN Zp_divlift(GEN b, GEN a, GEN x, GEN p, long n) { pari_sp ltop = avma, av; ulong mask; GEN q = p; if (n == 1) return gcopy(x); mask = quadratic_prec_mask(n); av = avma; while (mask > 1) { GEN v, q2 = q; q = sqri(q); if (mask & 1UL) q = diviiexact(q,p); mask >>= 1; if (mask > 1 || !b) { v = Fp_sub(Fp_mul(x, modii(a, q), q), gen_1, q); x = Fp_sub(x, Fp_mul(v, x, q), q); } else { GEN y = Fp_mul(x, b, q), yt = modii(y, q2); v = Fp_sub(Fp_mul(x, modii(a, q), q), gen_1, q); x = Fp_sub(y, Fp_mul(v, yt, q), q); } if (gc_needed(av, 1)) { if(DEBUGMEM>1) pari_warn(warnmem,"gen_Zp_Newton"); gerepileall(av, 2, &x, &q); } } return gerepileupto(ltop, x); } GEN Zp_invlift(GEN a, GEN x, GEN p, long e) { return Zp_divlift(NULL, a, x, p, e); } GEN Zp_inv(GEN a, GEN p, long e) { pari_sp av=avma; GEN ai; if (lgefint(p)==3) { ulong pp = p[2]; ai = utoi(Fl_inv(umodiu(a,pp), pp)); } else ai = Fp_inv(modii(a, p), p); return gerepileupto(av, Zp_invlift(a, ai, p, e)); } GEN Zp_div(GEN b, GEN a, GEN p, long e) { pari_sp av=avma; GEN ai; if (lgefint(p)==3) { ulong pp = p[2]; ai = utoi(Fl_inv(umodiu(a,pp), pp)); } else ai = Fp_inv(modii(a, p), p); return gerepileupto(av, Zp_divlift(b, a, ai, p, e)); } static GEN mul2n(void *E, GEN x, GEN y) { return remi2n(mulii(x, y), (long)E); } static GEN sqr2n(void *E, GEN x) { return remi2n(sqri(x), (long)E); } /* a^n mod 2^e using remi2n (result has the same sign as a) */ static GEN Fp_pow2n(GEN a, GEN n, long e) { return gen_pow(a, n, (void*)e, &sqr2n, &mul2n); } /* Same as ZpX_liftroot for the polynomial X^n-b*/ GEN Zp_sqrtnlift(GEN b, GEN n, GEN a, GEN p, long e) { pari_sp av = avma; int nis2, pis2; GEN q, w, n_1; ulong mask; if (e == 1) return icopy(a); nis2 = equaliu(n, 2); n_1 = nis2? NULL: subiu(n,1); pis2 = equaliu(p, 2); mask = quadratic_prec_mask(e); w = nis2 ? shifti(a,1): Fp_mul(n, Fp_pow(a,n_1,p), p); w = Fp_inv(w, p); q = p; /* q = p^e; use e instead of q iff p = 2 */ e = 1; for(;;) { if (pis2) { e <<= 1; if (mask & 1) e--; mask >>= 1; /* a -= w (a^n - b) */ a = remi2n(subii(a, mulii(w, subii(Fp_pow2n(a, n, e), b))), e); if (mask == 1) break; /* w += w - w^2 n a^(n-1)*/ w = subii(shifti(w,1), remi2n(mulii(remi2n(sqri(w), e), mulii(n, Fp_pow2n(a, n_1, e))), e)); continue; } q = sqri(q); if (mask & 1) q = diviiexact(q, p); mask >>= 1; if (lgefint(q) == 3 && lgefint(n) == 3) { ulong Q = uel(q,2), N = uel(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; if (nis2) W = Fl_double(Fl_sub(W, Fl_mul(Fl_sqr(W,Q), A, Q), Q), Q); else W = Fl_sub(Fl_double(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)*/ if (nis2) w = shifti(subii(w, Fp_mul(Fp_sqr(w,q), a, q)), 1); else w = subii(shifti(w,1), Fp_mul(Fp_sqr(w,q), mulii(n, Fp_pow(a,n_1,q)), q)); } } if (pis2 && signe(a) < 0) a = addii(a, int2n(e)); return gerepileuptoint(av, a); } /* ZpX_liftroot for the polynomial X^2-b */ GEN Zp_sqrtlift(GEN b, GEN a, GEN p, long e) { return Zp_sqrtnlift(b, gen_2, a, p, e); } GEN Zp_sqrt(GEN x, GEN p, long e) { pari_sp av; GEN z; if (absequaliu(p,2)) return Z2_sqrt(x,e); av = avma; z = Fp_sqrt(Fp_red(x, p), p); if (!z) return NULL; if (e > 1) z = Zp_sqrtlift(x, z, p, e); return gerepileuptoint(av, z); } /* p-adic logarithm of a = 1 mod p (adapted from a C program of Xavier Caruso) * Algorithm: * 1. raise a at the power p^(v-1) in order to make it closer to 1 * 2. write the new a as a product * 1 / a = (1 - a_0*p^v) (1 - a_1*p^(2*v) (1 - a_2*p^(4*v) ... * with 0 <= a_i < p^(v*2^i). * 3. compute each log(1 - a_i*p^(v*2^i)) using Taylor expansion * and binary splitting */ GEN Zp_log(GEN a, GEN p, ulong e) { pari_sp av = avma; ulong v, N, Np, trunc, pp = itou_or_0(p); GEN pe, pv, trunc_mod, num, den, ans = gen_0; if (equali1(a)) return ans; /* very frequent! */ /* First make the argument closer to 1 by raising it to the p^(v-1) */ v = pp? ulogint(e, pp): 0; /* v here is v-1 */ pe = powiu(p,e); pv = powiu(p,v); a = Fp_pow(a, pv, mulii(pe, pv)); e += v; /* Where do we truncate the Taylor expansion */ N = e + v; N /= ++v; /* note the ++v */ Np = N; while(1) { ulong e = Np; if (pp) e += ulogint(N, pp) / v; if (e == N) break; N = e; } num = cgetg(N+1, t_INT); den = cgetg(N+1, t_INT); trunc = v << 1; trunc_mod = powiu(p, trunc); while(1) { /* compute f = 1 - a_i*p^((v+1)*2^i); trunc_mod = p^((v+1)*2^(i+1)) */ GEN f = modii(a, trunc_mod); if (!equali1(f)) { ulong i, step = 1; GEN h, hpow; f = subui(2, f); a = mulii(a, f); /* compute the Taylor expansion of log(f), over Q for now */ for (i = 1; i <= N; i++) { gel(num,i) = gen_1; gel(den,i) = utoipos(i); } hpow = h = subui(1, f); /* h = a_i*p^(2^i) */ while(1) { for (i = 1; i <= N - step; i += step << 1) { GEN t = mulii(mulii(hpow, gel(num,i+step)), gel(den,i)); gel(num,i) = mulii(gel(num,i), gel(den,i+step)); gel(num,i) = addii(gel(num,i), t); gel(den,i) = mulii(gel(den,i), gel(den,i+step)); } step <<= 1; if (step >= N) break; hpow = sqri(hpow); } if (pp) { /* simplify the fraction */ GEN d = powuu(pp, factorial_lval(N, pp)); gel(num,1) = diviiexact(gel(num,1), d); gel(den,1) = diviiexact(gel(den,1), d); } h = diviiexact(h, pv); ans = addii(ans, mulii(mulii(gel(num,1), h), Zp_inv(gel(den,1), p, e))); } if (trunc > e) break; trunc_mod = sqri(trunc_mod); trunc <<= 1; N >>= 1; } return gerepileuptoint(av, modii(ans, pe)); } /* p-adic exponential of a = 0 (mod 2p) * 1. write a as a sum a = a_0*p + a_1*p^2 + a_2*p^4 + ... * with 0 <= a_i < p^(2^i). * 2. compute exp(a_i*p^(2^i)) using Taylor expansion and binary splitting */ GEN Zp_exp(GEN a, GEN p, ulong e) { pari_sp av = avma; ulong trunc, N = e, pp = itou_or_0(p); GEN num, den, trunc_mod = NULL, denominator = gen_1, ans = gen_1; GEN pe = powiu(p, e); int pis2 = pp == 2; /* Where do we truncate the Taylor expansion */ if (!pis2) N += sdivsi(e, subis(p,2)); num = cgetg(N+2, t_VEC); den = cgetg(N+2, t_VEC); if (pis2) trunc = 4; else { trunc = 2; trunc_mod = sqri(p); } while(1) { GEN h, hpow, f = pis2? remi2n(a, trunc): modii(a, trunc_mod); a = subii(a, f); if (signe(f)) { ulong step = 1, i; /* Taylor expansion of exp(f), over Q for now */ gel(num,1) = gen_1; gel(den,1) = gen_1; for (i = 2; i <= N+1; i++) { gel(num,i) = gen_1; gel(den,i) = utoipos(i-1); } hpow = h = f; while(1) { for (i = 1; i <= N+1 - step; i += step << 1) { gel(num,i) = mulii(gel(num,i), gel(den,i+step)); gel(num,i) = addii(gel(num,i), mulii(hpow, gel(num,i+step))); gel(den,i) = mulii(gel(den,i), gel(den,i+step)); } step <<= 1; if (step > N) break; hpow = sqri(hpow); } /* We simplify the fraction */ if (pp) { GEN d = powuu(pp, factorial_lval(N, pp)); gel(num,1) = diviiexact(gel(num,1), d); gel(den,1) = diviiexact(gel(den,1), d); } /* We add this contribution to exp(f) */ ans = Fp_mul(ans, gel(num,1), pe); denominator = Fp_mul(denominator, gel(den,1), pe); } if (trunc > e) break; if (!pis2) trunc_mod = sqri(trunc_mod); trunc <<= 1; N >>= 1; } return gerepileuptoint(av, Zp_div(ans, denominator, p, e)); } /***********************************************************************/ /** **/ /** QUADRATIC HENSEL LIFT (adapted from V. Shoup's NTL) **/ /** **/ /***********************************************************************/ /* Setup for divide/conquer quadratic Hensel lift * a = set of k t_POL in Z[X] = factors over Fp (T=NULL) or Fp[Y]/(T) * V = set of products of factors built as follows * 1) V[1..k] = initial a * 2) iterate: * append to V the two smallest factors (minimal degree) in a, remove them * from a and replace them by their product [net loss for a = 1 factor] * * W = bezout coeffs W[i]V[i] + W[i+1]V[i+1] = 1 * * link[i] = -j if V[i] = a[j] * j if V[i] = V[j] * V[j+1] * Arrays (link, V, W) pre-allocated for 2k - 2 elements */ static void BuildTree(GEN link, GEN V, GEN W, GEN a, GEN T, GEN p) { long k = lg(a)-1; long i, j, s, minp, mind; for (i=1; i<=k; i++) { gel(V,i) = gel(a,i); link[i] = -i; } for (j=1; j <= 2*k-5; j+=2,i++) { minp = j; mind = degpol(gel(V,j)); for (s=j+1; s 0) pari_err_COPRIME("BuildTree", gel(V,j), gel(V,j+1)); d = gel(d,2); if (!gequal1(d)) { if (typ(d)==t_POL) { d = FpXQ_inv(d, T, p); u = FqX_Fq_mul(u, d, T, p); v = FqX_Fq_mul(v, d, T, p); } else { d = Fp_inv(d, p); u = FqX_Fp_mul(u, d, T,p); v = FqX_Fp_mul(v, d, T,p); } } gel(W,j) = u; gel(W,j+1) = v; } } /* au + bv = 1 (p0), ab = f (p0). Lift mod p1 = p0 pd (<= p0^2). * If noinv is set, don't lift the inverses u and v */ static void ZpX_HenselLift(GEN V, GEN W, long j, GEN f, GEN pd, GEN p0, GEN p1, int noinv) { pari_sp av = avma; long space = lg(f) * lgefint(p1); GEN a2, b2, g, z, s, t; GEN a = gel(V,j), b = gel(V,j+1); GEN u = gel(W,j), v = gel(W,j+1); (void)new_chunk(space); /* HACK */ g = ZX_sub(f, ZX_mul(a,b)); g = ZX_Z_divexact(g, p0); g = FpX_red(g, pd); z = FpX_mul(v,g, pd); t = FpX_divrem(z,a, pd, &s); t = ZX_add(ZX_mul(u,g), ZX_mul(t,b)); t = FpX_red(t, pd); t = ZX_Z_mul(t,p0); s = ZX_Z_mul(s,p0); set_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); set_avma(av); gel(W,j) = ZX_add(u,t); gel(W,j+1) = ZX_add(v,s); } static void ZpXQ_HenselLift(GEN V, GEN W, long j, GEN f, GEN Td, GEN T1, GEN pd, GEN p0, GEN p1, int noinv) { pari_sp av = avma; const long n = degpol(T1), vT = varn(T1); long space = lg(f) * lgefint(p1) * lg(T1); GEN a2, b2, g, z, s, t; GEN a = gel(V,j), b = gel(V,j+1); GEN u = gel(W,j), v = gel(W,j+1); (void)new_chunk(space); /* HACK */ g = RgX_sub(f, Kronecker_to_ZXX(ZXX_mul_Kronecker(a,b,n), n, vT)); g = FpXQX_red(g, T1, p1); g = RgX_Rg_divexact(g, p0); z = FpXQX_mul(v,g, Td,pd); t = FpXQX_divrem(z,a, Td,pd, &s); t = ZX_add(ZXX_mul_Kronecker(u,g,n), ZXX_mul_Kronecker(t,b,n)); t = Kronecker_to_ZXX(t, n, vT); t = FpXQX_red(t, Td, pd); t = RgX_Rg_mul(t,p0); s = RgX_Rg_mul(s,p0); set_avma(av); a2 = RgX_add(a,s); b2 = RgX_add(b,t); /* already reduced mod p1 = pd p0 */ gel(V,j) = a2; gel(V,j+1) = b2; if (noinv) return; av = avma; (void)new_chunk(space); /* HACK */ g = ZX_add(ZXX_mul_Kronecker(u,a2,n), ZXX_mul_Kronecker(v,b2,n)); g = Kronecker_to_ZXX(g, n, vT); g = Rg_RgX_sub(gen_1, g); g = FpXQX_red(g, T1, p1); g = RgX_Rg_divexact(g, p0); z = FpXQX_mul(v,g, Td,pd); t = FpXQX_divrem(z,a, Td,pd, &s); t = ZX_add(ZXX_mul_Kronecker(u,g,n), ZXX_mul_Kronecker(t,b,n)); t = Kronecker_to_ZXX(t, n, vT); t = FpXQX_red(t, Td, pd); t = RgX_Rg_mul(t,p0); s = RgX_Rg_mul(s,p0); set_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); } /* Lift to precision p^e0. * a = modular factors of f mod (p,T) [possibly T=NULL] * OR a TreeLift structure [e, link, v, w]: go on lifting * flag = 0: standard. * flag = 1: return TreeLift structure */ static GEN MultiLift(GEN f, GEN a, GEN T, GEN p, long e0, long flag) { long i, eold, e, k = lg(a) - 1; GEN E, v, w, link, penew, Tnew; ulong mask; pari_timer Ti; if (k < 2) pari_err_DOMAIN("MultiLift", "#(modular factors)", "<", gen_2,a); if (e0 < 1) pari_err_DOMAIN("MultiLift", "precision", "<", gen_1,stoi(e0)); if (e0 == 1) return a; if (DEBUGLEVEL > 3) timer_start(&Ti); if (typ(gel(a,1)) == t_INT) { /* a = TreeLift structure */ e = itos(gel(a,1)); link = gel(a,2); v = gel(a,3); w = gel(a,4); } else { e = 1; v = cgetg(2*k-2 + 1, t_VEC); w = cgetg(2*k-2 + 1, t_VEC); link=cgetg(2*k-2 + 1, t_VECSMALL); BuildTree(link, v, w, a, T? FpX_red(T,p): NULL, p); if (DEBUGLEVEL > 3) timer_printf(&Ti, "building tree"); } mask = quadratic_prec_mask(e0); eold = 1; penew = NULL; Tnew = NULL; if (DEBUGLEVEL > 3) err_printf("lifting to prec %ld\n", e0); 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, lg(v)-2, (flag == 0 && mask == 1)); } else ZpX_RecTreeLift(link, v, w, pd, peold, penew, f, lg(v)-2, (flag == 0 && mask == 1)); if (DEBUGLEVEL > 3) timer_printf(&Ti, "reaching 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 pe, GEN p, long e) { pari_sp av = avma; pol = FpX_normalize(pol, pe); if (lg(Q) == 2) return mkvec(pol); return gerepilecopy(av, MultiLift(pol, Q, NULL, p, e, 0)); } GEN ZpXQX_liftfact(GEN pol, GEN Q, GEN T, GEN pe, GEN p, long e) { pari_sp av = avma; pol = FpXQX_normalize(pol, T, pe); if (lg(Q) == 2) return mkvec(pol); return gerepilecopy(av, MultiLift(pol, Q, T, p, e, 0)); } GEN ZqX_liftfact(GEN f, GEN a, GEN T, GEN pe, GEN p, long e) { return T ? ZpXQX_liftfact(f, a, T, pe, p, e): ZpX_liftfact(f, a, pe, p, e); } GEN ZqX_liftroot(GEN f, GEN a, GEN T, GEN p, long e) { return T ? ZpXQX_liftroot(f, a,T , p, e): ZpX_liftroot(f, a, p, e); } /* 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) retmkvec(pol_1(varn(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, lg(v)-2); 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 Tp, long N) { GEN T, p; long i, l; pari_sp av = avma; void (*chk)(GEN, const char*); if (typ(pol) != t_POL) pari_err_TYPE("polhensellift",pol); RgX_check_ZXX(pol, "polhensellift"); if (!is_vec_t(typ(L)) || lg(L) < 3) pari_err_TYPE("polhensellift",L); if (N < 1) pari_err_DOMAIN("polhensellift", "precision", "<", gen_1,stoi(N)); if (!ff_parse_Tp(Tp, &T, &p, 0)) pari_err_TYPE("polhensellift",Tp); chk = T? RgX_check_ZXX: RgX_check_ZX; l = lg(L); L = leafcopy(L); for (i = 1; i < l; i++) { GEN q = gel(L,i); if (typ(q) != t_POL) gel(L,i) = scalar_ZX_shallow(q, varn(pol)); else chk(q, "polhensellift"); } return gerepilecopy(av, ZqX_liftfact(pol, L, T, powiu(p,N), p, N)); } static GEN FqV_roots_from_deg1(GEN x, GEN T, GEN p) { long i,l = lg(x); GEN r = cgetg(l,t_COL); for (i=1; i 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 ZpX_liftroots(GEN f, GEN S, GEN p, long e) { long i, n = lg(S)-1, d = degpol(f); GEN r; if (n == d) return ZpX_liftroots_full(f, S, powiu(p, e), p, e); r = cgetg(n+1, typ(S)); for (i=1; i <= n; i++) gel(r,i) = ZpX_liftroot(f, gel(S,i), p, e); return r; } GEN ZpXQX_liftroot_vald(GEN f, GEN a, long v, GEN T, GEN p, long e) { pari_sp av = avma, av2; GEN pv = p, q, W, df, Tq, fr, dfr; ulong mask; a = Fq_red(a, T, p); if (e <= v+1) return a; df = RgX_deriv(f); if (v) { pv = powiu(p,v); df = ZXX_Z_divexact(df, pv); } mask = quadratic_prec_mask(e-v); Tq = FpXT_red(T, p); dfr = FpXQX_red(df, Tq, p); W = Fq_inv(FqX_eval(dfr, a, Tq, p), Tq, p); /* 1/f'(a) mod (T,p) */ q = p; av2 = avma; for (;;) { GEN u, fa, qv, q2v, q2, Tq2; q2 = q; q = sqri(q); if (mask & 1) q = diviiexact(q,p); mask >>= 1; if (v) { qv = mulii(q, pv); q2v = mulii(q2, pv); } else { qv = q; q2v = q2; } Tq2 = FpXT_red(T, q2v); Tq = FpXT_red(T, qv); fr = FpXQX_red(f, Tq, qv); fa = FqX_eval(fr, a, Tq, qv); fa = typ(fa)==t_INT? diviiexact(fa,q2v): ZX_Z_divexact(fa, q2v); a = Fq_sub(a, Fq_mul(Fq_mul(W,fa,Tq2,q2v),q2, Tq,qv), Tq, qv); if (mask == 1) return gerepileupto(av, a); dfr = FpXQX_red(df, Tq, q); u = Fq_sub(Fq_mul(W,FqX_eval(dfr,a,Tq,q),Tq,q),gen_1,Tq,q); u = typ(u)==t_INT? diviiexact(u,q2): ZX_Z_divexact(u,q2); W = Fq_sub(W, Fq_mul(Fq_mul(u,W,Tq2,q2),q2, Tq,q),Tq,q); if (gc_needed(av2,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"ZpXQX_liftroot, e = %ld", e); gerepileall(av2, 3, &a, &W, &q); } } } GEN ZpXQX_liftroot(GEN f, GEN a, GEN T, GEN p, long e) { return ZpXQX_liftroot_vald(f,a,0,T,p,e); } GEN ZpXQX_liftroots(GEN f, GEN S, GEN T, GEN p, long e) { long i, n = lg(S)-1, d = degpol(f); GEN r; if (n == d) return ZpXQX_liftroots_full(f, S, T, powiu(p, e), p, e); r = cgetg(n+1, typ(S)); for (i=1; i <= n; i++) gel(r,i) = ZpXQX_liftroot(f, gel(S,i), T, p, e); return r; } /* Compute (x-1)/(x+1)/p^k */ static GEN ZpXQ_log_to_ath(GEN x, long k, GEN T, GEN p, long e, GEN pe) { pari_sp av = avma; long vT = get_FpX_var(T); GEN bn, bdi; GEN bd = ZX_Z_add(x, gen_1); if (absequaliu(p,2)) /*For p=2, we need to simplify by 2*/ { bn = ZX_shifti(x,-(k+1)); bdi= ZpXQ_invlift(ZX_shifti(bd ,-1), pol_1(vT), T, p, e); } else { bn = ZX_Z_divexact(ZX_Z_sub(x, gen_1),powiu(p,k)); bdi= ZpXQ_invlift(bd, scalarpol(Fp_inv(gen_2,p),vT), T, p, e); } return gerepileupto(av, FpXQ_mul(bn, bdi, T, pe)); } /* Assume p odd, a = 1 [p], return log(a) */ GEN ZpXQ_log(GEN a, GEN T, GEN p, long N) { pari_sp av = avma; pari_timer ti; long is2 = absequaliu(p,2); ulong pp = is2 ? 0: itou_or_0(p); double lp = is2 ? 1: pp ? log2(pp): expi(p); long k = maxss(1 , (long) .5+pow((double)(N>>1)/(lp*lp), 1./3)); GEN ak, s, b, pol; long e = is2 ? N-1: N; long i, l = (e-2)/(2*(k+is2)); GEN pe = powiu(p,e); GEN TNk, pNk = powiu(p,N+k); if( DEBUGLEVEL>=3) timer_start(&ti); TNk = FpX_get_red(get_FpX_mod(T), pNk); ak = FpXQ_pow(a, powiu(p,k), TNk, pNk); if( DEBUGLEVEL>=3) timer_printf(&ti,"FpXQ_pow(%ld)",k); b = ZpXQ_log_to_ath(ak, k, T, p, e, pe); if( DEBUGLEVEL>=3) timer_printf(&ti,"ZpXQ_log_to_ath"); pol= cgetg(l+3,t_POL); pol[1] = evalsigne(1)|evalvarn(0); for(i=0; i<=l; i++) { GEN g; ulong z = 2*i+1; if (pp) { long w = u_lvalrem(z, pp, &z); g = powuu(pp,2*i*k-w); } else g = powiu(p,2*i*k); gel(pol,i+2) = Fp_divu(g, z,pe); } if( DEBUGLEVEL>=3) timer_printf(&ti,"pol(%ld)",l); s = FpX_FpXQ_eval(pol, FpXQ_sqr(b, T, pe), T, pe); if( DEBUGLEVEL>=3) timer_printf(&ti,"FpX_FpXQ_eval"); s = ZX_shifti(FpXQ_mul(b, s, T, pe), 1); return gerepileupto(av, is2? s: FpX_red(s, pe)); } /***********************************************************************/ /** **/ /** Generic quadratic hensel lift over Zp[X] **/ /** **/ /***********************************************************************/ /* q = p^N */ GEN gen_ZpM_Dixon(GEN F, GEN V, GEN q, GEN p, long N, void *E, GEN lin(void *E, GEN F, GEN d, GEN q), GEN invl(void *E, GEN d)) { pari_sp av = avma; long N2, M; GEN VN2, V2, VM, bil; GEN q2, qM; V = FpM_red(V, q); if (N == 1) return invl(E, V); N2 = (N + 1)>>1; M = N - N2; F = FpM_red(F, q); qM = powiu(p, M); q2 = M == N2? qM: mulii(qM, p); /* q2 = p^N2, qM = p^M, q = q2 * qM */ VN2 = gen_ZpM_Dixon(F, V, q2, p, N2, E, lin, invl); bil = lin(E, F, VN2, q); V2 = ZM_Z_divexact(ZM_sub(V, bil), q2); VM = gen_ZpM_Dixon(F, V2, qM, p, M, E, lin, invl); return gerepileupto(av, FpM_red(ZM_add(VN2, ZM_Z_mul(VM, q2)), q)); } GEN gen_ZpX_Dixon(GEN F, GEN V, GEN q, GEN p, long N, void *E, GEN lin(void *E, GEN F, GEN d, GEN q), GEN invl(void *E, GEN d)) { pari_sp av = avma; long N2, M; GEN VN2, V2, VM, bil; GEN q2, qM; V = FpX_red(V, q); if (N == 1) return invl(E, V); N2 = (N + 1)>>1; M = N - N2; F = FpXT_red(F, q); qM = powiu(p, M); q2 = M == N2? qM: mulii(qM, p); /* q2 = p^N2, qM = p^M, q = q2 * qM */ VN2 = gen_ZpX_Dixon(F, V, q2, p, N2, E, lin, invl); bil = lin(E, F, VN2, q); V2 = ZX_Z_divexact(ZX_sub(V, bil), q2); VM = gen_ZpX_Dixon(F, V2, qM, p, M, E, lin, invl); return gerepileupto(av, FpX_red(ZX_add(VN2, ZX_Z_mul(VM, q2)), q)); } GEN gen_ZpM_Newton(GEN x, GEN p, long n, void *E, GEN eval(void *E, GEN f, GEN q), GEN invd(void *E, GEN V, GEN v, GEN q, long M)) { pari_sp ltop = avma, av; long N = 1, N2, M; long mask; GEN q = p; if (n == 1) return gcopy(x); mask = quadratic_prec_mask(n); av = avma; while (mask > 1) { GEN qM, q2, v, V; N2 = N; N <<= 1; q2 = q; if (mask&1UL) { /* can never happen when q2 = p */ N--; M = N2-1; qM = diviiexact(q2,p); /* > 1 */ q = mulii(qM,q2); } else { M = N2; qM = q2; q = sqri(q2); } /* q2 = p^N2, qM = p^M, q = p^N = q2 * qM */ mask >>= 1; v = eval(E, x, q); V = ZM_Z_divexact(gel(v,1), q2); x = FpM_sub(x, ZM_Z_mul(invd(E, V, v, qM, M), q2), q); if (gc_needed(av, 1)) { if(DEBUGMEM>1) pari_warn(warnmem,"gen_ZpM_Newton"); gerepileall(av, 2, &x, &q); } } return gerepileupto(ltop, x); } static GEN _ZpM_invd(void *E, GEN V, GEN v, GEN q, long M/*unused*/) { (void)E; (void)M; return FpM_mul(V, gel(v,2), q); } static GEN _ZpM_eval(void *E, GEN x, GEN q) { GEN f = RgM_Rg_sub_shallow(FpM_mul(x, FpM_red((GEN) E, q), q), gen_1); return mkvec2(f, x); } GEN ZpM_invlift(GEN M, GEN C, GEN p, long n) { return gen_ZpM_Newton(C, p, n, (void *)M, _ZpM_eval, _ZpM_invd); } GEN gen_ZpX_Newton(GEN x, GEN p, long n, void *E, GEN eval(void *E, GEN f, GEN q), GEN invd(void *E, GEN V, GEN v, GEN q, long M)) { pari_sp ltop = avma, av; long N = 1, N2, M; long mask; GEN q = p; if (n == 1) return gcopy(x); mask = quadratic_prec_mask(n); av = avma; while (mask > 1) { GEN qM, q2, v, V; N2 = N; N <<= 1; q2 = q; if (mask&1UL) { /* can never happen when q2 = p */ N--; M = N2-1; qM = diviiexact(q2,p); /* > 1 */ q = mulii(qM,q2); } else { M = N2; qM = q2; q = sqri(q2); } /* q2 = p^N2, qM = p^M, q = p^N = q2 * qM */ mask >>= 1; v = eval(E, x, q); V = ZX_Z_divexact(gel(v,1), q2); x = FpX_sub(x, ZX_Z_mul(invd(E, V, v, qM, M), q2), q); if (gc_needed(av, 1)) { if(DEBUGMEM>1) pari_warn(warnmem,"gen_ZpX_Newton"); gerepileall(av, 2, &x, &q); } } return gerepileupto(ltop, x); } struct _ZpXQ_inv { GEN T, a, p ,n; }; static GEN _inv_invd(void *E, GEN V, GEN v, GEN q, long M/*unused*/) { struct _ZpXQ_inv *d = (struct _ZpXQ_inv *) E; GEN Tq = FpXT_red(d->T, q); (void)M; return FpXQ_mul(V, gel(v,2), Tq, q); } static GEN _inv_eval(void *E, GEN x, GEN q) { struct _ZpXQ_inv *d = (struct _ZpXQ_inv *) E; GEN Tq = FpXT_red(d->T, q); GEN f = FpX_Fp_sub(FpXQ_mul(x, FpX_red(d->a, q), Tq, q), gen_1, q); return mkvec2(f, x); } GEN ZpXQ_invlift(GEN a, GEN x, GEN T, GEN p, long e) { struct _ZpXQ_inv d; d.a = a; d.T = T; d.p = p; return gen_ZpX_Newton(x, p, e, &d, _inv_eval, _inv_invd); } GEN ZpXQ_inv(GEN a, GEN T, GEN p, long e) { pari_sp av=avma; GEN ai; if (lgefint(p)==3) { ulong pp = p[2]; ai = Flx_to_ZX(Flxq_inv(ZX_to_Flx(a,pp), ZXT_to_FlxT(T, pp), pp)); } else ai = FpXQ_inv(FpX_red(a,p), FpXT_red(T,p),p); return gerepileupto(av, ZpXQ_invlift(a, ai, T, p, e)); } GEN ZpXQ_div(GEN a, GEN b, GEN T, GEN q, GEN p, long e) { return FpXQ_mul(a, ZpXQ_inv(b, T, p, e), T, q); } GEN ZpXQX_divrem(GEN x, GEN Sp, GEN T, GEN q, GEN p, long e, GEN *pr) { pari_sp av = avma; GEN S = get_FpXQX_mod(Sp); GEN b = leading_coeff(S), bi; GEN S2, Q; if (typ(b)==t_INT) return FpXQX_divrem(x, Sp, T, q, pr); bi = ZpXQ_inv(b, T, p, e); S2 = FqX_Fq_mul_to_monic(S, bi, T, q); Q = FpXQX_divrem(x, S2, T, q, pr); if (pr==ONLY_DIVIDES && !Q) { set_avma(av); return NULL; } if (pr==ONLY_REM || pr==ONLY_DIVIDES) return gerepileupto(av, Q); Q = FpXQX_FpXQ_mul(Q, bi, T, q); return gc_all(av, 2, &Q, pr); } GEN ZpXQX_digits(GEN x, GEN B, GEN T, GEN q, GEN p, long e) { pari_sp av = avma; GEN b = leading_coeff(B), bi; GEN B2, P, V, W; long i, lV; if (typ(b)==t_INT) return FpXQX_digits(x, B, T, q); bi = ZpXQ_inv(b, T, p, e); B2 = FqX_Fq_mul_to_monic(B, bi, T, q); V = FpXQX_digits(x, B2, T, q); lV = lg(V)-1; P = FpXQ_powers(bi, lV-1, T, q); W = cgetg(lV+1, t_VEC); for(i=1; i<=lV; i++) gel(W, i) = FpXQX_FpXQ_mul(gel(V,i), gel(P, i), T, q); return gerepileupto(av, W); } struct _ZpXQ_sqrtn { GEN T, a, n, ai; }; static GEN _sqrtn_invd(void *E, GEN V, GEN v, GEN q, long M) { struct _ZpXQ_sqrtn *d = (struct _ZpXQ_sqrtn *) E; GEN Tq = FpX_red(d->T, q), aiq = FpX_red(d->ai, q); (void)M; return FpXQ_mul(FpXQ_mul(V, gel(v,2), Tq, q), aiq, Tq, q); } static GEN _sqrtn_eval(void *E, GEN x, GEN q) { struct _ZpXQ_sqrtn *d = (struct _ZpXQ_sqrtn *) E; GEN Tq = FpX_red(d->T, q); GEN f = FpX_sub(FpXQ_pow(x, d->n, Tq, q), d->a, q); return mkvec2(f, x); } GEN ZpXQ_sqrtnlift(GEN a, GEN n, GEN x, GEN T, GEN p, long e) { struct _ZpXQ_sqrtn d; d.a = a; d.T = T; d.n = n; d.ai = ZpXQ_inv(ZX_Z_mul(a, n),T,p,(e+1)>>1); return gen_ZpX_Newton(x, p, e, &d, _sqrtn_eval, _sqrtn_invd); } static GEN to_ZX(GEN a, long v) { return typ(a)==t_INT? scalarpol_shallow(a,v): a; } GEN Zq_sqrtnlift(GEN a, GEN n, GEN x, GEN T, GEN p, long e) { return T? ZpXQ_sqrtnlift(to_ZX(a,varn(T)), n, to_ZX(x,varn(T)), T, p, e) : Zp_sqrtnlift(a, n, x, p, e); } GEN ZpXQ_sqrt(GEN a, GEN T, GEN p, long e) { pari_sp av = avma; GEN z = FpXQ_sqrt(FpX_red(a, p), T, p); if (!z) return NULL; if (e <= 1) return gerepileupto(av, z); return gerepileupto(av, ZpXQ_sqrtnlift(a, gen_2, z, T, p, e)); } GEN ZpX_ZpXQ_liftroot_ea(GEN P, GEN S, GEN T, GEN p, long n, void *E, GEN early(void *E, GEN x, GEN q)) { pari_sp ltop = avma, av; long N, r; long mask; GEN q2, q, W, Q, Tq2, Tq, Pq; pari_timer ti; T = FpX_get_red(T, powiu(p, n)); if (n == 1) return gcopy(S); mask = quadratic_prec_mask(n); av = avma; q2 = p; q = sqri(p); mask >>= 1; N = 2; if (DEBUGLEVEL > 3) timer_start(&ti); Tq = FpXT_red(T,q); Tq2 = FpXT_red(Tq,q2); Pq = FpX_red(P,q); W = FpXQ_inv(FpX_FpXQ_eval(FpX_deriv(P,q2), S, Tq2, q2), Tq2, q2); Q = ZX_Z_divexact(FpX_FpXQ_eval(Pq, S, Tq, q), q2); r = brent_kung_optpow(degpol(P), 4, 3); if (DEBUGLEVEL > 3) err_printf("ZpX_ZpXQ_liftroot: lifting to prec %ld\n",n); for (;;) { GEN H, Sq, Wq, Spow, dP, qq, Pqq, Tqq; H = FpXQ_mul(W, Q, Tq2, q2); Sq = FpX_sub(S, ZX_Z_mul(H, q2), q); if (DEBUGLEVEL > 3) timer_printf(&ti,"ZpX_ZpXQ_liftroot: reaching prec %ld",N); if (mask==1) return gerepileupto(ltop, Sq); if (early) { GEN Se = early(E, Sq, q); if (Se) return gerepileupto(ltop, Se); } qq = sqri(q); N <<= 1; if (mask&1UL) { qq = diviiexact(qq, p); N--; } mask >>= 1; Pqq = FpX_red(P, qq); Tqq = FpXT_red(T, qq); Spow = FpXQ_powers(Sq, r, Tqq, qq); Q = ZX_Z_divexact(FpX_FpXQV_eval(Pqq, Spow, Tqq, qq), q); dP = FpX_FpXQV_eval(FpX_deriv(Pq, q), FpXV_red(Spow, q), Tq, q); Wq = ZX_Z_divexact(FpX_Fp_sub(FpXQ_mul(W, dP, Tq, q), gen_1, q), q2); Wq = ZX_Z_mul(FpXQ_mul(W, Wq, Tq2, q2), q2); Wq = FpX_sub(W, Wq, q); S = Sq; W = Wq; q2 = q; q = qq; Tq2 = Tq; Tq = Tqq; Pq = Pqq; if (gc_needed(av, 1)) { if(DEBUGMEM>1) pari_warn(warnmem,"ZpX_ZpXQ_liftroot"); gerepileall(av, 8, &S, &W, &Q, &Tq2, &Tq, &Pq, &q, &q2); } } } GEN ZpX_ZpXQ_liftroot(GEN P, GEN S, GEN T, GEN p, long n) { return ZpX_ZpXQ_liftroot_ea(P, S, T, p, n, NULL, NULL); } GEN ZpX_Frobenius(GEN T, GEN p, long e) { return ZpX_ZpXQ_liftroot(get_FpX_mod(T), FpX_Frobenius(T, p), T, p, e); } GEN ZpXQM_prodFrobenius(GEN M, GEN T, GEN p, long e) { pari_sp av = avma; GEN xp = ZpX_Frobenius(T, p, e); GEN z = FpXQM_autsum(mkvec2(xp, M), get_FpX_degree(T), T, powiu(p,e)); return gerepilecopy(av, gel(z,2)); } GEN ZpXQX_ZpXQXQ_liftroot(GEN P, GEN S, GEN U, GEN T, GEN p, long n) { pari_sp ltop = avma, av; long N, r; long mask; GEN qn, q2, q, W, Q, Tq2, Tq, Pq, Uq, Uq2; pari_timer ti; qn = powiu(p, n); T = FpX_get_red(T, qn); U = FpXQX_get_red(U, T, qn); if (n == 1) return gcopy(S); mask = quadratic_prec_mask(n); av = avma; q2 = p; q = sqri(p); mask >>= 1; N = 2; if (DEBUGLEVEL > 3) timer_start(&ti); Tq = FpXT_red(T,q); Uq = FpXQXT_red(U, Tq, q); Tq2 = FpXT_red(Tq, q2); Uq2 = FpXQXT_red(U, Tq2, q2); Pq = FpXQX_red(P, Tq, q); W = FpXQXQ_inv(FpXQX_FpXQXQ_eval(FpXX_deriv(P,q2), S, Uq2, Tq2, q2), Uq2, Tq2, q2); Q = ZXX_Z_divexact(FpXQX_FpXQXQ_eval(Pq, S, Uq, Tq, q), q2); r = brent_kung_optpow(degpol(P), 4, 3); if (DEBUGLEVEL > 3) err_printf("ZpXQX_ZpXQXQ_liftroot: lifting to prec %ld\n",n); for (;;) { GEN H, Sq, Wq, Spow, dP, qq, Pqq, Tqq, Uqq; H = FpXQXQ_mul(W, Q, Uq2, Tq2, q2); Sq = FpXX_sub(S, ZXX_Z_mul(H, q2), q); if (DEBUGLEVEL > 3) timer_printf(&ti,"ZpXQX_ZpXQXQ_liftroot: reaching prec %ld",N); if (mask==1) return gerepileupto(ltop, Sq); qq = sqri(q); N <<= 1; if (mask&1UL) { qq = diviiexact(qq, p); N--; } mask >>= 1; Tqq = FpXT_red(T, qq); Uqq = FpXQXT_red(U, Tqq, qq); Pqq = FpXQX_red(P, Tqq, qq); Spow = FpXQXQ_powers(Sq, r, Uqq, Tqq, qq); Q = ZXX_Z_divexact(FpXQX_FpXQXQV_eval(Pqq, Spow, Uqq, Tqq, qq), q); dP = FpXQX_FpXQXQV_eval(FpXX_deriv(Pq, q), FpXQXV_red(Spow, Tq, q), Uq, Tq, q); Wq = ZXX_Z_divexact(gsub(FpXQXQ_mul(W, dP, Uq, Tq, q), gen_1), q2); Wq = ZXX_Z_mul(FpXQXQ_mul(W, Wq, Uq2, Tq2, q2), q2); Wq = FpXX_sub(W, Wq, q); S = Sq; W = Wq; q2 = q; q = qq; Tq2 = Tq; Tq = Tqq; Uq2 = Uq; Uq = Uqq; Pq = Pqq; if (gc_needed(av, 1)) { if(DEBUGMEM>1) pari_warn(warnmem,"ZpXQX_ZpXQXQ_liftroot"); gerepileall(av, 10, &S, &W, &Q, &Uq2, &Uq, &Tq2, &Tq, &Pq, &q, &q2); } } } GEN ZqX_ZqXQ_liftroot(GEN f, GEN a, GEN P, GEN T, GEN p, long e) { return T ? ZpXQX_ZpXQXQ_liftroot(f, a, P, T , p, e): ZpX_ZpXQ_liftroot(f, a, P, p, e); } /* Canonical lift of polynomial */ static GEN _can_invl(void *E, GEN V) {(void) E; return V; } static GEN _can_lin(void *E, GEN F, GEN V, GEN q) { GEN v = RgX_splitting(V, 3); (void) E; return FpX_sub(V,ZXV_dotproduct(v, F), q); } static GEN _can_iter(void *E, GEN f, GEN q) { GEN h = RgX_splitting(f,3); GEN h1s = ZX_sqr(gel(h,1)), h2s = ZX_sqr(gel(h,2)), h3s = ZX_sqr(gel(h,3)); GEN h12 = ZX_mul(gel(h,1), gel(h,2)); GEN h13 = ZX_mul(gel(h,1), gel(h,3)); GEN h23 = ZX_mul(gel(h,2), gel(h,3)); GEN h1c = ZX_mul(gel(h,1), h1s); GEN h3c = ZX_mul(gel(h,3), h3s); GEN th = ZX_mul(ZX_sub(h2s,ZX_mulu(h13,3)),gel(h,2)); GEN y = FpX_sub(f,ZX_add(RgX_shift_shallow(h3c,2),ZX_add(RgX_shift_shallow(th,1),h1c)),q); (void) E; return mkvecn(7,y,h1s,h2s,h3s,h12,h13,h23); } static GEN _can_invd(void *E, GEN V, GEN v, GEN qM, long M) { GEN h1s=gel(v,2), h2s=gel(v,3), h3s=gel(v,4); GEN h12=gel(v,5), h13=gel(v,6), h23=gel(v,7); GEN F = mkvec3(ZX_sub(h1s,RgX_shift_shallow(h23,1)),RgX_shift_shallow(ZX_sub(h2s,h13),1), ZX_sub(RgX_shift_shallow(h3s,2),RgX_shift_shallow(h12,1))); (void)E; return gen_ZpX_Dixon(ZXV_Z_mul(F, utoi(3)), V, qM, utoi(3), M, NULL, _can_lin, _can_invl); } static GEN F3x_frobeniuslift(GEN P, long n) { return gen_ZpX_Newton(Flx_to_ZX(P),utoi(3), n, NULL, _can_iter, _can_invd); } static GEN _can5_invl(void *E, GEN V) {(void) E; return V; } static GEN _can5_lin(void *E, GEN F, GEN V, GEN q) { ulong p = *(ulong*)E; GEN v = RgX_splitting(V, p); return FpX_sub(V,ZXV_dotproduct(v, F), q); } /* P(X,t) -> P(X*t^n,t) mod (t^p-1) */ static GEN _shift(GEN P, long n, ulong p, long v) { long i, l=lg(P); GEN r = cgetg(l,t_POL); r[1] = P[1]; for(i=2;ip, get_FpX_var(d->T)); GEN c = FpXQX_mul(a, bn, d->T, d->q); return mkvec2(c, addii(gel(A,2), gel(B,2))); } static GEN _can5_sqr(void *E, GEN A) { return _can5_mul(E,A,A); } static GEN _can5_iter(void *E, GEN f, GEN q) { pari_sp av = avma; struct _can_mul D; ulong p = *(ulong*)E; long i, vT = fetch_var(); GEN N, P, d, V, fs; D.q = q; D.T = ZX_Z_sub(pol_xn(p,vT),gen_1); D.p = p; fs = mkvec2(_shift(f, 1, p, vT), gen_1); N = gel(gen_powu_i(fs,p-1,(void*)&D,_can5_sqr,_can5_mul),1); N = ZXX_evalx0(FpXQX_red(N,polcyclo(p,vT),q)); P = FpX_mul(N,f,q); P = RgX_deflate(P, p); d = RgX_splitting(N, p); V = cgetg(p+1,t_VEC); gel(V,1) = ZX_mulu(gel(d,1), p); for(i=2; i<= (long)p; i++) gel(V,i) = ZX_mulu(RgX_shift_shallow(gel(d,p+2-i), 1), p); (void)delete_var(); return gerepilecopy(av, mkvec2(ZX_sub(f,P),V)); } static GEN _can5_invd(void *E, GEN H, GEN v, GEN qM, long M) { ulong p = *(long*)E; return gen_ZpX_Dixon(gel(v,2), H, qM, utoipos(p), M, E, _can5_lin, _can5_invl); } GEN Flx_Teichmuller(GEN P, ulong p, long n) { return p==3 ? F3x_frobeniuslift(P,n): gen_ZpX_Newton(Flx_to_ZX(P),utoipos(p), n, &p, _can5_iter, _can5_invd); } GEN polteichmuller(GEN P, ulong p, long n) { pari_sp av = avma; GEN q = NULL; if (typ(P)!=t_POL || !RgX_is_FpX(P,&q)) pari_err_TYPE("polteichmuller",P); if (q && !equaliu(q,p)) pari_err_MODULUS("polteichmuller",q,utoi(p)); if (n <= 0) pari_err_DOMAIN("polteichmuller", "precision", "<=",gen_0,stoi(n)); return gerepileupto(av, p==2 ? F2x_Teichmuller(RgX_to_F2x(P), n) : Flx_Teichmuller(RgX_to_Flx(P, p), p, n)); } pari-2.17.2/src/basemath/RgV.c0000644000175000017500000005675514760123736014434 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" int RgM_is_ZM(GEN x) { long i, j, h, l = lg(x); if (l == 1) return 1; h = lgcols(x); if (h == 1) return 1; for (j = l-1; j > 0; j--) for (i = h-1; i > 0; i--) if (typ(gcoeff(x,i,j)) != t_INT) return 0; return 1; } int RgM_is_QM(GEN x) { long i, j, h, l = lg(x); if (l == 1) return 1; h = lgcols(x); if (h == 1) return 1; for (j = l-1; j > 0; j--) for (i = h-1; i > 0; i--) if (!is_rational_t(typ(gcoeff(x,i,j)))) return 0; return 1; } int RgV_is_ZMV(GEN V) { long i, l = lg(V); for (i=1; i 0). */ static GEN RgM_zc_mul_i(GEN x, GEN y, long c, long l) { GEN z = cgetg(l,t_COL); long i; for (i = 1; i < l; i++) gel(z,i) = RgMrow_zc_mul_i(x,y,c,i); return z; } GEN RgM_zc_mul(GEN x, GEN y) { return RgM_zc_mul_i(x,y, lg(x), lgcols(x)); } /* x t_MAT, y a compatible zm (dimension > 0). */ GEN RgM_zm_mul(GEN x, GEN y) { long j, c, l = lg(x), ly = lg(y); GEN z = cgetg(ly, t_MAT); if (l == 1) return z; c = lgcols(x); for (j = 1; j < ly; j++) gel(z,j) = RgM_zc_mul_i(x, gel(y,j), l,c); return z; } /* x[i,]*y, l = lg(y) > 1 */ static GEN RgMrow_ZC_mul_i(GEN x, GEN y, long i, long l) { pari_sp av = avma; GEN t = gmul(gcoeff(x,i,1), gel(y,1)); /* l > 1 ! */ long j; for (j=2; j 1, l = lgcols(x) */ static GEN RgM_ZC_mul_i(GEN x, GEN y, long lx, long l) { GEN z = cgetg(l,t_COL); long i; for (i=1; i1) pari_warn(warnmem,"RgV_dotsquare, i = %ld",i); z = gerepileupto(av, z); } } return gerepileupto(av,z); } /* scalar product x.y, lx = lg(x) = lg(y) */ static GEN RgV_dotproduct_i(GEN x, GEN y, long lx) { pari_sp av = avma; long i; GEN z; if (lx == 1) return gen_0; z = gmul(gel(x,1),gel(y,1)); for (i=2; i1) pari_warn(warnmem,"RgV_dotproduct, i = %ld",i); z = gerepileupto(av, z); } } return gerepileupto(av,z); } GEN RgV_dotproduct(GEN x,GEN y) { if (x == y) return RgV_dotsquare(x); return RgV_dotproduct_i(x, y, lg(x)); } /* v[1] + ... + v[lg(v)-1] */ GEN RgV_sum(GEN v) { GEN p; long i, l = lg(v); if (l == 1) return gen_0; p = gel(v,1); for (i=2; i n. */ GEN RgV_sumpart(GEN v, long n) { GEN p; long i; if (!n) return gen_0; p = gel(v,1); for (i=2; i<=n; i++) p = gadd(p, gel(v,i)); return p; } /* v[m] + ... + v[n]. Assume lg(v) > n, m > 0. */ GEN RgV_sumpart2(GEN v, long m, long n) { GEN p; long i; if (n < m) return gen_0; p = gel(v,m); for (i=m+1; i<=n; i++) p = gadd(p, gel(v,i)); return p; } GEN RgM_sumcol(GEN A) { long i,j,m,l = lg(A); GEN v; if (l == 1) return cgetg(1,t_MAT); if (l == 2) return gcopy(gel(A,1)); m = lgcols(A); v = cgetg(m, t_COL); for (i = 1; i < m; i++) { pari_sp av = avma; GEN s = gcoeff(A,i,1); for (j = 2; j < l; j++) s = gadd(s, gcoeff(A,i,j)); gel(v, i) = gerepileupto(av, s); } return v; } static GEN _gmul(void *data, GEN x, GEN y) { (void)data; return gmul(x,y); } GEN RgV_prod(GEN x) { return gen_product(x, NULL, _gmul); } /* ADDITION SCALAR + MATRIX */ /* x square matrix, y scalar; create the square matrix x + y*Id */ GEN RgM_Rg_add(GEN x, GEN y) { long l = lg(x), i, j; GEN z = cgetg(l,t_MAT); if (l==1) return z; if (l != lgcols(x)) pari_err_OP("+", x, y); for (i=1; i 1 */ static GEN RgMrow_RgC_mul_i(GEN x, GEN y, long i, long l) { pari_sp av = avma; GEN t = gmul(gcoeff(x,i,1), gel(y,1)); /* l > 1 ! */ long j; for (j=2; j 1, l = lgcols(x) */ static GEN RgM_RgC_mul_i(GEN x, GEN y, long lx, long l) { GEN z = cgetg(l,t_COL); long i; for (i=1; i 1 */ static GEN RgM_mul_i(GEN x, GEN y, long lx, long ly) { GEN z = cgetg(ly, t_MAT); long j, l = lgcols(x); for (j = 1; j < ly; j++) gel(z,j) = RgM_RgC_mul_i(x, gel(y,j), lx, l); return z; } GEN RgM_mul(GEN x, GEN y) { long lx, ly = lg(y); GEN z; if (ly == 1) return cgetg(1,t_MAT); lx = lg(x); if (lx != lgcols(y)) pari_err_OP("operation 'RgM_mul'", x,y); if (lx == 1) return zeromat(0,ly-1); z = RgM_mul_fast(x, y); if (z) return z; return RgM_mul_i(x, y, lx, ly); } GEN RgM_sqr(GEN x) { long j, lx = lg(x); GEN z; if (lx == 1) return cgetg(1, t_MAT); if (lx != lgcols(x)) pari_err_OP("operation 'RgM_mul'", x,x); z = RgM_sqr_fast(x); if (z) return z; z = cgetg(lx, t_MAT); for (j=1; j1 ? lg(gel(x,1))-1:0; return gen_bkeval_powers(Q,degpol(Q),x,(void*)&n,&RgM_algebra,&_RgM_cmul); } GEN RgX_RgM_eval(GEN Q, GEN x) { long n = lg(x)-1; return gen_bkeval(Q,degpol(Q),x,1,(void*)&n,&RgM_algebra,&_RgM_cmul); } GEN RgC_Rg_div(GEN x, GEN y) { pari_APPLY_type(t_COL, gdiv(gel(x,i),y)) } GEN RgC_Rg_mul(GEN x, GEN y) { pari_APPLY_type(t_COL, gmul(gel(x,i),y)) } GEN RgV_Rg_mul(GEN x, GEN y) { pari_APPLY_type(t_VEC, gmul(gel(x,i),y)) } GEN RgM_Rg_div(GEN X, GEN c) { long i, j, h, l = lg(X); GEN A = cgetg(l, t_MAT); if (l == 1) return A; h = lgcols(X); for (j=1; jpow2; i--) x[i-pow2] -= x[i]; for (; i>0; i--) if (x[i]) break; i += 2; z = cgetg(i, t_POL); z[1] = evalsigne(1); for (i--; i>=2; i--) gel(z,i) = stoi(x[i-1]); return z; } /* x t_POL, n > 0. Return x mod polcyclo(2^n) = (x^(2^(n-1)) + 1). IN PLACE */ static GEN red_cyclo2n_ip(GEN x, long n) { long i, pow2 = 1L<<(n-1); for (i = lg(x)-1; i>pow2+1; i--) if (signe(gel(x,i))) gel(x,i-pow2) = subii(gel(x,i-pow2), gel(x,i)); return normalizepol_lg(x, i+1); } static GEN red_cyclo2n(GEN x, long n) { return red_cyclo2n_ip(leafcopy(x), n); } /* special case R->C = 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(ZX_rem(x, R->C), R->N, R->N2); } static GEN modZ(GEN x, Red *R) { return centermodii(x, R->N, R->N2); } static GEN sqrmodZ(GEN x, Red *R) { return modZ(sqri(x), R); } static GEN sqrmod(GEN x, Red *R) { return R->red(ZX_sqr(x), R); } static GEN _mul(GEN x, GEN y, Red *R) { return typ(x) == t_INT? modZ(mulii(x,y), R) : R->red(ZX_mul(x,y), R); } static GEN sqrconst(GEN pol, Red *R) { GEN z = cgetg(3,t_POL); gel(z,2) = modZ(sqri(gel(pol,2)), R); 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 = modZ(mulii(a,addii(b,bma)), R); B = modZ(mulii(bma,addii(a,b)), R); 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 = modZ(mulii(a, shifti(b,1)), R); B = modZ(mulii(subii(b,a),addii(b,a)), R); 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 = modZ(sqri(d), R); B = modZ(mulii(c2, d), R); C = modZ(sqri(c), R); 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 = modZ(A, R); B = modZ(B, R); C = modZ(C, R); D = modZ(D, R); return mkpoln(4,A,B,C,D); } /* jac^floor(N/pk) mod (N, polcyclo(pk)), flexible window */ static GEN _powpolmod(GEN C, GEN jac, Red *R, GEN (*_sqr)(GEN, Red *)) { const GEN taba = cache_aall(C); const GEN tabt = cache_tall(C); const long efin = lg(taba)-1, lv = R->lv; GEN L, res = jac, pol2 = _sqr(res, R); long f; pari_sp av0 = avma, av; L = cgetg(lv+1, t_VEC); gel(L,1) = res; for (f=2; f<=lv; f++) gel(L,f) = _mul(gel(L,f-1), pol2, R); av = avma; 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 (gc_needed(av,1)) { res = gerepilecopy(av, res); if(DEBUGMEM>1) pari_warn(warnmem,"powpolmod: f = %ld",f); } } } return gerepilecopy(av0, res); } static GEN _powpolmodsimple(GEN C, Red *R, GEN jac) { pari_sp av = avma; GEN w = ZM_ZX_mul(cache_mat(C), jac); long j, ph = lg(w); R->red = &modZ; for (j=1; jN, R->N2); w = gerepileupto(av, w); return RgV_to_RgX(w, 0); } static GEN powpolmod(GEN C, Red *R, long p, long k, GEN jac) { GEN (*_sqr)(GEN, Red *); if (!isintzero(cache_mat(C))) return _powpolmodsimple(C, R, jac); if (p == 2) /* p = 2 */ { if (k == 2) _sqr = &sqrmod4; else _sqr = &sqrmod; R->n = k; R->red = &_red_cyclo2n; } else if (k == 1) { if (p == 3) _sqr = &sqrmod3; else if (p == 5) _sqr = &sqrmod5; else _sqr = &sqrmod; R->n = p; R->red = &_red_cyclop; } else { R->red = &_red; _sqr = &sqrmod; } return _powpolmod(C, jac, R, _sqr); } /* Return e(t) = \prod_{p-1 | t} p^{1+v_p(t)}} * faet contains the odd prime divisors of e(t) */ static GEN compute_e(ulong t, GEN *faet) { GEN L, P, D = divisorsu(t); long l = lg(D); ulong k; P = vecsmalltrunc_init(l); L = vecsmalltrunc_init(l); for (k=l-1; k>1; k--) /* k != 1: avoid d = 1 */ { ulong d = D[k]; if (uisprime(++d)) { /* we want q = 1 (mod p) prime, not too large */ #ifdef LONG_IS_64BIT if (d > 5000000000UL) return gen_0; #endif vecsmalltrunc_append(P, d); vecsmalltrunc_append(L, upowuu(d, 1 + u_lval(t,d))); } } if (faet) *faet = P; return shifti(zv_prod_Z(L), 2 + u_lval(t,2)); } /* Table obtained by the following script: install(compute_e, "LD&"); \\ remove 'static' first table(first = 6, step = 6, MAXT = 6983776800)= { emax = 0; forstep(t = first, MAXT, step, e = compute_e(t); if (e > 1.9*emax, emax = e; printf(" if (C < %7.2f) return %8d;\n", 2*log(e)/log(2) - 1e-2, t) ); ); } table(,, 147026880); table(147026880,5040, 6983776800); */ /* assume C < 20003.8 */ static ulong compute_t_small(double C) { if (C < 17.94) return 6; if (C < 31.99) return 12; if (C < 33.99) return 24; if (C < 54.07) return 36; if (C < 65.32) return 60; if (C < 68.45) return 72; if (C < 70.78) return 108; if (C < 78.04) return 120; if (C < 102.41) return 180; if (C < 127.50) return 360; if (C < 136.68) return 420; if (C < 153.44) return 540; if (C < 165.67) return 840; if (C < 169.18) return 1008; if (C < 178.53) return 1080; if (C < 192.69) return 1200; if (C < 206.35) return 1260; if (C < 211.96) return 1620; if (C < 222.10) return 1680; if (C < 225.12) return 2016; if (C < 244.20) return 2160; if (C < 270.31) return 2520; if (C < 279.52) return 3360; if (C < 293.64) return 3780; if (C < 346.70) return 5040; if (C < 348.73) return 6480; if (C < 383.37) return 7560; if (C < 396.71) return 8400; if (C < 426.08) return 10080; if (C < 458.38) return 12600; if (C < 527.20) return 15120; if (C < 595.43) return 25200; if (C < 636.34) return 30240; if (C < 672.58) return 42840; if (C < 684.96) return 45360; if (C < 708.84) return 55440; if (C < 771.37) return 60480; if (C < 775.93) return 75600; if (C < 859.69) return 85680; if (C < 893.24) return 100800; if (C < 912.35) return 110880; if (C < 966.22) return 128520; if (C < 1009.18) return 131040; if (C < 1042.04) return 166320; if (C < 1124.98) return 196560; if (C < 1251.09) return 257040; if (C < 1375.13) return 332640; if (C < 1431.11) return 393120; if (C < 1483.46) return 514080; if (C < 1546.46) return 655200; if (C < 1585.94) return 665280; if (C < 1661.44) return 786240; if (C < 1667.67) return 831600; if (C < 1677.07) return 917280; if (C < 1728.17) return 982800; if (C < 1747.57) return 1081080; if (C < 1773.76) return 1179360; if (C < 1810.81) return 1285200; if (C < 1924.66) return 1310400; if (C < 2001.27) return 1441440; if (C < 2096.51) return 1663200; if (C < 2166.02) return 1965600; if (C < 2321.86) return 2162160; if (C < 2368.45) return 2751840; if (C < 2377.39) return 2827440; if (C < 2514.97) return 3326400; if (C < 2588.72) return 3341520; if (C < 2636.84) return 3603600; if (C < 2667.46) return 3931200; if (C < 3028.92) return 4324320; if (C < 3045.76) return 5654880; if (C < 3080.78) return 6652800; if (C < 3121.88) return 6683040; if (C < 3283.38) return 7207200; if (C < 3514.94) return 8648640; if (C < 3725.71) return 10810800; if (C < 3817.49) return 12972960; if (C < 3976.57) return 14414400; if (C < 3980.72) return 18378360; if (C < 4761.70) return 21621600; if (C < 5067.62) return 36756720; if (C < 5657.30) return 43243200; if (C < 5959.24) return 64864800; if (C < 6423.60) return 73513440; if (C < 6497.01) return 86486400; if (C < 6529.89) return 113097600; if (C < 6899.19) return 122522400; if (C < 7094.26) return 129729600; if (C < 7494.60) return 147026880; if (C < 7606.21) return 172972800; if (C < 7785.10) return 183783600; if (C < 7803.68) return 216216000; if (C < 8024.18) return 220540320; if (C < 8278.12) return 245044800; if (C < 8316.48) return 273873600; if (C < 8544.02) return 294053760; if (C < 8634.14) return 302702400; if (C < 9977.69) return 367567200; if (C < 10053.06) return 514594080; if (C < 10184.29) return 551350800; if (C < 11798.33) return 735134400; if (C < 11812.60) return 821620800; if (C < 11935.31) return 1029188160; if (C < 12017.99) return 1074427200; if (C < 12723.99) return 1102701600; if (C < 13702.71) return 1470268800; if (C < 13748.76) return 1643241600; if (C < 13977.37) return 2058376320; if (C < 14096.03) return 2148854400UL; if (C < 15082.25) return 2205403200UL; if (C < 15344.18) return 2572970400UL; if (C < 15718.37) return 2940537600UL; if (C < 15868.65) return 3491888400UL; if (C < 15919.88) return 3675672000UL; if (C < 16217.23) return 4108104000UL; #ifdef LONG_IS_64BIT if (C < 17510.32) return 4410806400UL; if (C < 18312.87) return 5145940800UL; return 6983776800UL; #else pari_err_IMPL("APRCL for large numbers on 32bit arch"); return 0; #endif } /* return t such that e(t) > sqrt(N), set *faet = odd prime divisors of e(t) */ static ulong compute_t(GEN N, GEN *e, GEN *faet) { /* 2^e b <= N < 2^e (b+1), where b >= 2^52. Approximating log_2 N by * log2(gtodouble(N)) ~ e+log2(b), the error is less than log(1+1/b) < 1e-15*/ double C = dbllog2(N) + 1e-10; /* > log_2 N at least for N < 2^(2^21) */ ulong t; /* Return "smallest" t such that f(t) >= C, which implies e(t) > sqrt(N) */ /* For N < 2^20003.8 ~ 5.5 10^6021 */ if (C < 20003.8) { t = compute_t_small(C); *e = compute_e(t, faet); } else { #ifdef LONG_IS_64BIT GEN B = sqrti(N); for (t = 6983776800UL+5040UL;; t+=5040) { pari_sp av = avma; *e = compute_e(t, faet); if (cmpii(*e, B) > 0) break; set_avma(av); } #else *e = NULL; /* LCOV_EXCL_LINE */ t = 0; /* LCOV_EXCL_LINE */ #endif } 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; } /* x a nonzero VECSMALL with >= 0 entries */ static GEN zv_to_ZX(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; j>1; /* (q-1)/2 */ GEN vpk = zero_zv(pk); for (x=2; x<=qs2; x++) vpk[ tabg[x]%pk + 1 ] += 2; vpk[ tabg[x]%pk + 1 ]++; /* x = (q+1)/2 */ return ZX_rem(zv_to_ZX(vpk), cache_cyc(C)); } /* p = 2 */ static GEN get_jac2(GEN N, ulong q, long k, GEN *j2q, GEN *j3q) { GEN jpq, vpk, T = computetabdl(q); ulong x, pk, i, qs2; /* could store T[x+1] + T[x] + qs2 (cf compute_g). * Recompute instead, saving half the memory. */ pk = 1UL << k;; vpk = zero_zv(pk); qs2 = q>>1; /* (q-1)/2 */ for (x=2; x<=qs2; x++) vpk[ (T[x]+T[x-1]+qs2)%pk + 1 ] += 2; vpk[ (T[x]+T[x-1]+qs2)%pk + 1 ]++; jpq = u_red_cyclo2n_ip(vpk, k); if (k == 2) return jpq; if (mod8(N) >= 5) { GEN v8 = cgetg(9,t_VECSMALL); for (x=1; x<=8; x++) v8[x] = 0; for (x=2; x<=qs2; x++) v8[ ((3*T[x]+T[x-1]+qs2)&7) + 1 ]++; for ( ; x<=q-1; x++) v8[ ((3*T[q-x]+T[q-x+1]-3*qs2)&7) + 1 ]++; *j2q = RgX_inflate(ZX_sqr(u_red_cyclo2n_ip(v8,3)), pk>>3); *j2q = red_cyclo2n_ip(*j2q, k); } for (i=1; i<=pk; i++) vpk[i] = 0; for (x=2; x<=qs2; x++) vpk[ (2*T[x]+T[x-1]+qs2)%pk + 1 ]++; for ( ; x<=q-1; x++) vpk[ (2*T[q-x]+T[q-x+1]-2*qs2)%pk + 1 ]++; *j3q = ZX_mul(jpq, u_red_cyclo2n_ip(vpk,k)); *j3q = red_cyclo2n_ip(*j3q, k); return jpq; } /* N = 1 mod p^k, return an elt of order p^k in (Z/N)^* */ static GEN finda(GEN Cp, GEN N, long pk, long p) { GEN a, pv; if (Cp && !isintzero(cache_a(Cp))) { a = cache_a(Cp); pv = cache_pk(Cp); } else { GEN ph, b, q; ulong u = 2; long v = Z_lvalrem(subiu(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(subiu(b,1), N); if (!gequal1(b)) return NULL; if (Cp) { cache_a(Cp) = a; /* a has order p^v */ cache_pk(Cp) = pv; } } return Fp_pow(a, divis(pv, pk), N); } /* return 0: N not a prime, 1: no problem so far */ static long filltabs(GEN C, GEN Cp, Red *R, long p, long pk, long ltab) { pari_sp av; long i, j; long e; GEN tabt, taba, m; cache_cyc(C) = 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; iN); gel(eta,i) = FpX_center_i(z, R->N, R->N2); } cache_eta(C) = eta; } else if (pk >= 8) { long LE = (pk>>2) + 1; GEN E = cgetg(LE, t_VECSMALL); for (i=1,j=0; i 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 = modZ(sqri(a), R); jj = 1; for (i=2; iN); } 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); cache_aall(C) = taba; setlg(tabt, e); cache_tall(C) = tabt; return gc_long(av,1); } static GEN calcglobs(Red *R, ulong t, long *plpC, long *pltab, GEN *pP) { GEN fat, P, E, PE; long lv, i, k, b; GEN pC; b = expi(R->N)+1; k = 3; while (((k+1)*(k+2) << (k-1)) < b) k++; *pltab = (b/k)+2; R->k = k; R->lv = 1L << (k-1); R->mask = (1UL << k) - 1; fat = factoru_pow(t); P = gel(fat,1); E = gel(fat,2); PE= gel(fat,3); *plpC = lv = vecsmall_max(PE); /* max(p^e, p^e | t) */ pC = zerovec(lv); gel(pC,1) = zerovec(9); /* to be used as temp in step5() */ for (i = 2; i <= lv; i++) gel(pC,i) = gen_0; 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) { pari_sp av = avma; 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 gerepileupto(av,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(GEN C, Red *R, ulong q, long p, long k, GEN tabg) { const long pk = upowuu(p,k); long ind; GEN jpq, s1, s2, s3; if (!tabg) tabg = compute_g(q); jpq = get_jac(C, q, pk, tabg); s1 = autvec_TH(pk, jpq, cache_E(C), cache_cyc(C)); s2 = powpolmod(C,R, p,k, s1); s3 = autvec_AL(pk, jpq, cache_E(C), R); s3 = _red(gmul(s3,s2), R); ind = look_eta(cache_eta(C), 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(addiu(x,1), N); } /* p=2, k>=3 */ static long step4b(GEN 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, cache_E(C), cache_cyc(C)); s2 = powpolmod(C,R, 2,k, s1); s3 = autvec_AL(pk, j3q, cache_E(C), 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; s3 = Fp_pow(utoipos(q), R->N2, R->N); return is_m1(s3, R->N); } /* p=2, k=2 */ static long step4c(GEN 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; s3 = Fp_pow(utoipos(q), R->N2, R->N); return is_m1(s3, R->N); } /* p=2, k=1 */ static long step4d(Red *R, ulong q) { GEN s1 = Fp_pow(utoipos(q), R->N2, R->N); 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(GEN pC, Red *R, long p, GEN et, ulong ltab, long lpC) { pari_sp av; ulong q; long pk, k, fl = -1; GEN C, Cp; forprime_t T; (void)u_forprime_arith_init(&T, 3, ULONG_MAX, 1,p); while( (q = u_forprime_next(&T)) ) { /* q = 1 (mod p) */ if (umodiu(et,q) == 0) continue; if (umodiu(R->N,q) == 0) return 0; k = u_lval(q-1, p); pk = upowuu(p,k); if (pk <= lpC && !isintzero(gel(pC,pk))) { C = gel(pC,pk); Cp = gel(pC,p); } else { C = gel(pC,1); Cp = NULL; cache_mat(C) = gen_0; /* re-init */ } av = avma; if (!filltabs(C, Cp, R, p, pk, ltab)) return 0; R->C = cache_cyc(C); 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(R, q); if (fl == -1) return 0; if (fl == 1) return 1; /*OK*/ set_avma(av); } pari_err_BUG("aprcl test fails! This is highly improbable"); return 0;/*LCOV_EXCL_LINE*/ } GEN aprcl_step6_worker(GEN r, long t, GEN N, GEN N1, GEN et) { long i; pari_sp av = avma; for (i=1; i<=t; i++) { r = remii(mulii(r,N1), et); if (equali1(r)) break; if (dvdii(N,r) && !equalii(r,N)) return gen_0; /* not prime */ if ((i & 0x1f) == 0) r = gerepileuptoint(av, r); } return cgetg(1,t_VECSMALL); } /* return 1 if N prime, else 0 */ static long step6(GEN N, ulong t, GEN et) { GEN worker, r, rk, N1 = remii(N, et); ulong k = 10000; ulong i; long pending = 0, res = 1; struct pari_mt pt; pari_sp btop; worker = snm_closure(is_entry("_aprcl_step6_worker"), mkvec3(N, N1, et)); r = gen_1; rk = Fp_powu(N1, k, et); mt_queue_start_lim(&pt, worker, (t-1+k-1)/k); btop = avma; for (i=1; (i1) pari_warn(warnmem,"APRCL: i = %ld",i); r = gerepileupto(btop, r); } } mt_queue_end(&pt); return res; } GEN aprcl_step4_worker(ulong q, GEN pC, GEN N, GEN v) { pari_sp av1 = avma, av2 = avma; long j, k; Red R; GEN faq = factoru_pow(q-1), tabg = compute_g(q); GEN P = gel(faq,1), E = gel(faq,2), PE = gel(faq,3); long lfaq = lg(P); GEN flags = cgetg(lfaq, t_VECSMALL); R.N = N; R.N2= shifti(N, -1); R.k = v[1]; R.lv = v[2]; R.mask = uel(v,3); R.n = v[4]; av2 = avma; for (j=1, k=1; j= 3) fl = step4a(C,&R, q,p,e, tabg); else if (e >= 3) fl = step4b(C,&R, q,e); else if (e == 2) fl = step4c(C,&R, q); else fl = step4d(&R, q); if (fl == -1) return gen_0; /* not prime */ if (fl == 1) flags[k++] = p; } setlg(flags, k); return gerepileuptoleaf(av1, flags); /* OK so far */ } /* return 1 if prime, else 0 */ static long aprcl(GEN N) { GEN pC, worker, et, fat, flaglp, faet = NULL; /*-Wall*/ long i, j, l, ltab, lfat, lpC, workid, pending = 0, res = 1; ulong t; Red R; struct pari_mt pt; if (typ(N) != t_INT) pari_err_TYPE("aprcl",N); if (cmpis(N,12) <= 0) switch(itos(N)) { case 2: case 3: case 5: case 7: case 11: return 1; default: return 0; } if (Z_issquare(N)) return 0; t = compute_t(N, &et, &faet); if (DEBUGLEVEL) err_printf("Starting APRCL with t = %ld\n",t); if (cmpii(sqri(et),N) < 0) pari_err_BUG("aprcl: e(t) too small"); if (!equali1(gcdii(N,mului(t,et)))) return 0; R.N = N; R.N2= shifti(N, -1); pC = calcglobs(&R, t, &lpC, <ab, &fat); if (!pC) return 0; lfat = lg(fat); flaglp = cgetg(lfat, t_VECSMALL); flaglp[1] = 0; for (i=2; i2) err_printf("Step4: %ld q-values\n", l-1); mt_queue_start_lim(&pt, worker, l-1); for (i=l-1; (i>0 && res) || pending; i--) { GEN done; ulong q = i>0 ? faet[i]: 0; mt_queue_submit(&pt, q, q>0? mkvec(utoi(q)): NULL); done = mt_queue_get(&pt, &workid, &pending); if (res && done) { long lf = lg(done); if (typ(done) != t_VECSMALL) { res = 0; continue; } /* not prime */ for (j=1; j2) err_printf("testing Jacobi sums for q = %ld...OK\n", workid); } } mt_queue_end(&pt); if (!res) return 0; if (DEBUGLEVEL>2) err_printf("Step5: testing conditions lp\n"); for (i=2; i2) err_printf("Step6: testing potential divisors\n"); return step6(N, t, et); } long isprimeAPRCL(GEN N) { pari_sp av = avma; return gc_long(av, aprcl(N)); } /*******************************************************************/ /* DIVISORS IN RESIDUE CLASSES (LENSTRA) */ /*******************************************************************/ /* This would allow to replace e(t) > N^(1/2) by e(t) > N^(1/3), but step6 * becomes so expensive that, at least up to 6000 bits, this is useless * in this application. */ static void set_add(hashtable *H, void *d) { ulong h = H->hash(d); if (!hash_search2(H, d, h)) hash_insert2(H, d, NULL, h); } static void add(hashtable *H, GEN t1, GEN t2, GEN a, GEN b, GEN r, GEN s) { GEN ra, qa = dvmdii(t1, a, &ra); if (!signe(ra) && dvdii(t2, b) && equalii(modii(qa, s), r)) set_add(H, (void*)qa); } /* T^2 - B*T + C has integer roots ? */ static void check_t(hashtable *H, GEN B, GEN C4, GEN a, GEN b, GEN r, GEN s) { GEN d, t1, t2, D = subii(sqri(B), C4); if (!Z_issquareall(D, &d)) return; t1 = shifti(addii(B, d), -1); /* >= 0 */ t2 = subii(B, t1); add(H, t1,t2, a,b,r,s); if (signe(t2) >= 0) add(H, t2,t1, a,b,r,s); } /* N > s > r >= 0, (r,s) = 1 */ GEN divisorslenstra(GEN N, GEN r, GEN s) { pari_sp av = avma; GEN u, Ns2, rp, a0, a1, b0, b1, c0, c1, s2; hashtable *H = hash_create(11, (ulong(*)(void*))&hash_GEN, (int(*)(void*,void*))&equalii, 1); long j; if (typ(N) != t_INT) pari_err_TYPE("divisorslenstra", N); if (typ(r) != t_INT) pari_err_TYPE("divisorslenstra", r); if (typ(s) != t_INT) pari_err_TYPE("divisorslenstra", s); u = Fp_inv(r, s); rp = Fp_mul(u, N, s); /* r' */ s2 = sqri(s); a0 = s; b0 = gen_0; c0 = gen_0; if (dvdii(N, r)) set_add(H, (void*)r); /* case i = 0 */ a1 = Fp_mul(u, rp, s); if (!signe(a1)) a1 = s; /* 0 < a1 <= s */ b1 = gen_1; c1 = Fp_mul(u, diviiexact(subii(N,mulii(r,rp)), s), s); Ns2 = divii(N, s2); j = 1; for (;;) { GEN Cs, q, c, ab = mulii(a1,b1); long i, lC; if (j == 0) /* i even, a1 >= 0 */ { if (!signe(c1)) Cs = mkvec(gen_0); else { GEN cs = mulii(c1, s); Cs = mkvec2(subii(cs,s2), cs); } } else { /* i odd, a1 > 0 */ GEN X = shifti(ab,1); c = c1; /* smallest c >= 2ab, c = c1 (mod s) */ if (cmpii(c, X) < 0) { GEN rX, qX = dvmdii(subii(X,c), s, &rX); if (signe(rX)) qX = addiu(qX,1); /* ceil((X-c)/s) */ c = addii(c, mulii(s, qX)); } Cs = (cmpii(c, addii(Ns2,ab)) <= 0)? mkvec(mulii(c,s)): cgetg(1,t_VEC); } lC = lg(Cs); if (signe(a1)) { GEN abN4 = shifti(mulii(ab, N), 2); GEN B = addii(mulii(a1,r), mulii(b1,rp)); for (i = 1; i < lC; i++) check_t(H, addii(B, gel(Cs,i)), abN4, a1, b1, r, s); } else { /* a1 = 0, last batch */ for (i = 1; i < lC; i++) { GEN ry, ys = dvmdii(gel(Cs,i), b1, &ry); if (!signe(ry)) { GEN d = addii(ys, rp); if (signe(d) > 0) { d = dvmdii(N, d, &ry); if (!signe(ry)) set_add(H, (void*)d); } } } break; /* DONE */ } j = 1-j; q = dvmdii(a0, a1, &c); if (j == 1 && !signe(c)) { q = subiu(q,1); c = a1; } a0 = a1; a1 = c; if (equali1(q)) /* frequent */ { c = subii(b0, b1); b0 = b1; b1 = c; c = Fp_sub(c0, c1, s); c0 = c1; c1 = c; } else { c = subii(b0, mulii(q,b1)); b0 = b1; b1 = c; c = modii(subii(c0, mulii(q,c1)), s); c0 = c1; c1 = c; } } return gerepileupto(av, ZV_sort(hash_keys_GEN(H))); } pari-2.17.2/src/basemath/trans2.c0000644000175000017500000020364514760123736015137 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /********************************************************************/ /** **/ /** TRANSCENDENTAL FUNCTIONS **/ /** (part 2) **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_trans GEN trans_fix_arg(long *prec, GEN *s0, GEN *sig, GEN *tau, pari_sp *av, GEN *res) { GEN p1, s = *s0 = cxtoreal(*s0); long l; l = precision(s); if (!l) l = *prec; if (l < LOWDEFAULTPREC) l = LOWDEFAULTPREC; *res = cgetc(l); *av = avma; if (typ(s) == t_COMPLEX) { /* s = sig + i t */ s = cxtofp(s, l+EXTRAPREC64); *sig = gel(s,1); *tau = gel(s,2); } else /* real number */ { *sig = s = gtofp(s, l+EXTRAPREC64); *tau = gen_0; p1 = trunc2nr(s, 0); if (!signe(subri(s,p1))) *s0 = p1; } *prec = l; return s; } /********************************************************************/ /** **/ /** ARCTANGENT **/ /** **/ /********************************************************************/ /* atan(b/a), real a and b, suitable for gerepileupto */ static GEN atan2_agm(GEN a, GEN b, long prec) { return gel(logagmcx(mkcomplex(a, b), prec), 2); } static GEN mpatan(GEN x) { long l, l1, l2, n, m, i, lp, e, s, sx = signe(x); pari_sp av0, av; double alpha, beta, delta; GEN y, p1, p2, p3, p4, p5, unr; int inv; if (!sx) return real_0_bit(expo(x)); l = lp = realprec(x); if (absrnz_equal1(x)) { /* |x| = 1 */ y = Pi2n(-2, l+EXTRAPREC64); if (sx < 0) setsigne(y,-1); return y; } if (l > AGM_ATAN_LIMIT) { av = avma; return gerepileuptoleaf(av, atan2_agm(gen_1, x, l)); } e = expo(x); inv = (e >= 0); /* = (|x| > 1 ) */ if (e > 0) lp += nbits2extraprec(e); y = cgetr(lp); av0 = avma; p1 = rtor(x, l+EXTRAPREC64); 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(M_PI / atan(rtodbl(p1))); beta = (double)(prec2nbits(l)>>1); delta = 1 + beta - alpha/2; if (delta <= 0) { n = 1; m = 0; } else { double fi = alpha-2; if (delta >= fi*fi) { double t = 1 + sqrt(delta); n = (long)t; m = (long)(t - fi); } else { n = (long)(1+beta/fi); m = 0; } } l2 = l + nbits2extraprec(m); p2 = rtor(p1, l2); av = avma; for (i=1; i<=m; i++) { p5 = addsr(1, sqrr(p2)); setprec(p5,l2); p5 = addsr(1, sqrtr_abs(p5)); setprec(p5,l2); affrr(divrr(p2,p5), p2); set_avma(av); } p3 = sqrr(p2); l1 = minss(LOWDEFAULTPREC+EXTRAPREC64, l2); /* l1 increases to l2 */; unr = real_1(l2); setprec(unr,l1); p4 = cgetr(l2); setprec(p4,l1); affrr(divru(unr,2*n+1), p4); s = 0; e = expo(p3); av = avma; for (i = n; i > 1; i--) /* n >= 1. i = 1 done outside for efficiency */ { setprec(p3,l1); p5 = mulrr(p4,p3); l1 += nbits2extraprec(dvmdsBIL(s - e, &s)< l2) l1 = l2; setprec(unr,l1); p5 = subrr(divru(unr,2*i-1), p5); setprec(p4,l1); affrr(p5,p4); set_avma(av); } setprec(p3, l2); p5 = mulrr(p4,p3); /* i = 1 */ setprec(unr,l2); p4 = subrr(unr, p5); p4 = mulrr(p2,p4); shiftr_inplace(p4, m); if (inv) p4 = subrr(Pi2n(-1, lp), p4); if (sx < 0) togglesign(p4); affrr_fixlg(p4,y); set_avma(av0); return y; } GEN gatan(GEN x, long prec) { pari_sp av; GEN a, y; switch(typ(x)) { case t_REAL: return mpatan(x); case t_COMPLEX: /* atan(x) = -i atanh(ix) */ if (ismpzero(gel(x,2))) return gatan(gel(x,1), prec); av = avma; return gerepilecopy(av, mulcxmI(gatanh(mulcxI(x),prec))); default: av = avma; if (!(y = toser_i(x))) break; if (valser(y) < 0) pari_err_DOMAIN("atan","valuation", "<", gen_0, x); if (lg(y)==2) return gerepilecopy(av, y); /* lg(y) > 2 */ a = integser(gdiv(derivser(y), gaddsg(1,gsqr(y)))); if (!valser(y)) a = gadd(a, gatan(gel(y,2),prec)); return gerepileupto(av, a); } return trans_eval("atan",gatan,x,prec); } /********************************************************************/ /** **/ /** ARCSINE **/ /** **/ /********************************************************************/ /* |x| < 1, x != 0 */ static GEN mpasin(GEN x) { pari_sp av = avma; GEN z, a = sqrtr(subsr(1, sqrr(x))); if (realprec(x) > AGM_ATAN_LIMIT) z = atan2_agm(a, x, realprec(x)); else z = mpatan(divrr(x, a)); return gerepileuptoleaf(av, z); } static GEN mpacosh(GEN x); GEN gasin(GEN x, long prec) { long sx; pari_sp av; GEN a, y, p1; switch(typ(x)) { case t_REAL: sx = signe(x); if (!sx) return real_0_bit(expo(x)); if (absrnz_equal1(x)) { /* |x| = 1 */ if (sx > 0) return Pi2n(-1, realprec(x)); /* 1 */ y = Pi2n(-1, realprec(x)); setsigne(y, -1); return y; /* -1 */ } if (expo(x) < 0) return mpasin(x); y = cgetg(3,t_COMPLEX); gel(y,1) = Pi2n(-1, realprec(x)); gel(y,2) = mpacosh(x); if (sx < 0) togglesign(gel(y,1)); else togglesign(gel(y,2)); return y; case t_COMPLEX: /* asin(z) = -i asinh(iz) */ if (ismpzero(gel(x,2))) return gasin(gel(x,1), prec); av = avma; return gerepilecopy(av, mulcxmI(gasinh(mulcxI(x), prec))); default: av = avma; if (!(y = toser_i(x))) break; if (gequal0(y)) return gerepilecopy(av, y); /* lg(y) > 2*/ if (valser(y) < 0) pari_err_DOMAIN("asin","valuation", "<", gen_0, x); p1 = gsubsg(1,gsqr(y)); if (gequal0(p1)) { GEN t = Pi2n(-1,prec); if (gsigne(gel(y,2)) < 0) setsigne(t, -1); return gerepileupto(av, scalarser(t, varn(y), valser(p1)>>1)); } p1 = gdiv(derivser(y), gsqrt(p1,prec)); a = integser(p1); if (!valser(y)) a = gadd(a, gasin(gel(y,2),prec)); return gerepileupto(av, a); } return trans_eval("asin",gasin,x,prec); } /********************************************************************/ /** **/ /** ARCCOSINE **/ /** **/ /********************************************************************/ static GEN acos0(long e) { return Pi2n(-1, nbits2prec(e<0? -e: 1)); } /* |x| < 1, x != 0 */ static GEN mpacos(GEN x) { pari_sp av = avma; GEN z, a = sqrtr(subsr(1, sqrr(x))); if (realprec(x) > AGM_ATAN_LIMIT) z = atan2_agm(x, a, realprec(x)); else { z = mpatan(divrr(a, x)); if (signe(x) < 0) z = addrr(mppi(realprec(z)), z); } return gerepileuptoleaf(av, z); } GEN gacos(GEN x, long prec) { long sx; pari_sp av; GEN a, y, p1; switch(typ(x)) { case t_REAL: sx = signe(x); if (!sx) return acos0(expo(x)); if (absrnz_equal1(x)) /* |x| = 1 */ return sx > 0? real_0_bit( -(bit_prec(x)>>1) ) : mppi(realprec(x)); if (expo(x) < 0) return mpacos(x); y = cgetg(3,t_COMPLEX); p1 = mpacosh(x); if (sx < 0) { gel(y,1) = mppi(realprec(x)); togglesign(p1); } else gel(y,1) = gen_0; gel(y,2) = p1; return y; case t_COMPLEX: if (ismpzero(gel(x,2))) return gacos(gel(x,1), prec); av = avma; p1 = gadd(x, mulcxI(gsqrt(gsubsg(1,gsqr(x)), prec))); y = glog(p1,prec); /* log(x + I*sqrt(1-x^2)) */ return gerepilecopy(av, mulcxmI(y)); default: av = avma; if (!(y = toser_i(x))) break; if (valser(y) < 0) pari_err_DOMAIN("acos","valuation", "<", gen_0, x); if (lg(y) > 2) { p1 = gsubsg(1,gsqr(y)); if (gequal0(p1)) { set_avma(av); return zeroser(varn(y), valser(p1)>>1); } p1 = integser(gdiv(gneg(derivser(y)), gsqrt(p1,prec))); /*y(t) = 1+O(t)*/ if (gequal1(gel(y,2)) && !valser(y)) return gerepileupto(av, p1); } else p1 = y; a = (lg(y)==2 || valser(y))? Pi2n(-1, prec): gacos(gel(y,2),prec); return gerepileupto(av, gadd(a,p1)); } return trans_eval("acos",gacos,x,prec); } /********************************************************************/ /** **/ /** ARGUMENT **/ /** **/ /********************************************************************/ /* we know that x and y are not both 0 */ static GEN mparg(GEN x, GEN y) { long prec, sx = signe(x), sy = signe(y); GEN z; if (!sy) { if (sx > 0) return real_0_bit(expo(y) - expo(x)); return mppi(realprec(x)); } prec = realprec(y); if (prec < realprec(x)) prec = realprec(x); if (!sx) { z = Pi2n(-1, prec); if (sy < 0) setsigne(z,-1); return z; } if (expo(x)-expo(y) > -2) { z = mpatan(divrr(y,x)); if (sx > 0) return z; return addrr_sign(z, signe(z), mppi(prec), sy); } z = mpatan(divrr(x,y)); return addrr_sign(z, -signe(z), Pi2n(-1, prec), sy); } static GEN rfix(GEN x,long prec) { switch(typ(x)) { case t_INT: return itor(x, prec); case t_FRAC: return fractor(x, prec); case t_REAL: break; default: pari_err_TYPE("rfix (conversion to t_REAL)",x); } return x; } static GEN cxarg(GEN x, GEN y, long prec) { pari_sp av = avma; x = rfix(x,prec); y = rfix(y,prec); return gerepileuptoleaf(av, mparg(x,y)); } GEN garg(GEN x, long prec) { long l; if (gequal0(x)) pari_err_DOMAIN("arg", "argument", "=", gen_0, x); switch(typ(x)) { case t_REAL: prec = realprec(x); /* fall through */ case t_INT: case t_FRAC: return (gsigne(x)>0)? real_0(prec): mppi(prec); case t_COMPLEX: l = precision(x); if (l) prec = l; return cxarg(gel(x,1),gel(x,2),prec); } return trans_eval("arg",garg,x,prec); } /********************************************************************/ /** **/ /** HYPERBOLIC COSINE **/ /** **/ /********************************************************************/ /* 1 + x */ static GEN mpcosh0(long e) { return e >= 0? real_0_bit(e): real_1_bit(-e); } static GEN mpcosh(GEN x) { pari_sp av; GEN z; if (!signe(x)) return mpcosh0(expo(x)); av = avma; z = mpexp(x); z = addrr(z, invr(z)); shiftr_inplace(z, -1); return gerepileuptoleaf(av, z); } GEN gcosh(GEN x, long prec) { pari_sp av; GEN y, p1; long v; switch(typ(x)) { case t_REAL: return mpcosh(x); case t_COMPLEX: if (isintzero(gel(x,1))) return gcos(gel(x,2),prec); /* fall through */ case t_PADIC: av = avma; p1 = gexp(x,prec); p1 = gadd(p1, ginv(p1)); return gerepileupto(av, gmul2n(p1,-1)); default: av = avma; if (!(y = toser_i(x))) break; if (gequal0(y) && valser(y) == 0) return gerepilecopy(av, y); v = valser(y); if (v > 0) y = sertoser(y, lg(y) - 2 + v); p1 = gexp(y,prec); p1 = gadd(p1, ginv(p1)); return gerepileupto(av, gmul2n(p1,-1)); } return trans_eval("cosh",gcosh,x,prec); } /********************************************************************/ /** **/ /** HYPERBOLIC SINE **/ /** **/ /********************************************************************/ static GEN mpsinh0(long e) { return real_0_bit(e); } static GEN mpsinh(GEN x) { pari_sp av; long lx; GEN z, res; if (!signe(x)) return mpsinh0(expo(x)); lx = realprec(x); res = cgetr(lx); av = avma; if (expo(x) + BITS_IN_LONG < 1) { /* y = e^x-1; e^x - e^(-x) = y(1 + 1/(y+1)) */ GEN y = mpexpm1(x); lx += EXTRAPRECWORD; z = addrs(y, 1); if (realprec(z) > lx) z = rtor(z,lx); /* e^x */ z = mulrr(y, addsr(1, invr(z))); } else { z = mpexp(x); z = subrr(z, invr(z)); } shiftr_inplace(z, -1); affrr(z, res); set_avma(av); return res; } void mpsinhcosh(GEN x, GEN *s, GEN *c) { pari_sp av; long lx, ex; GEN z, zi, S, C; if (!signe(x)) { ex = expo(x); *c = mpcosh0(ex); *s = mpsinh0(ex); return; } lx = realprec(x); *c = cgetr(lx); *s = cgetr(lx); av = avma; if (expo(x) + BITS_IN_LONG < 1) { /* y = e^x-1; e^x - e^(-x) = y(1 + 1/(y+1)) */ GEN y = mpexpm1(x); lx += EXTRAPRECWORD; z = addrs(y,1); if (realprec(z) > lx) z = rtor(z, lx); /* e^x */ zi = invr(z); /* z = exp(x), zi = exp(-x) */ S = mulrr(y, addsr(1,zi)); } else { z = mpexp(x); zi = invr(z); S = subrr(z, zi); } C = addrr(z, zi); shiftr_inplace(S, -1); affrr(S, *s); shiftr_inplace(C, -1); affrr(C, *c); set_avma(av); } GEN gsinh(GEN x, long prec) { pari_sp av; GEN y, p1; switch(typ(x)) { case t_REAL: return mpsinh(x); case t_COMPLEX: if (isintzero(gel(x,1))) retmkcomplex(gen_0, gsin(gel(x,2),prec)); /* fall through */ case t_PADIC: av = avma; p1 = gexp(x,prec); p1 = gsub(p1, ginv(p1)); return gerepileupto(av, gmul2n(p1,-1)); default: av = avma; if (!(y = toser_i(x))) break; if (gequal0(y) && valser(y) == 0) return gerepilecopy(av, y); p1 = gexp(y, prec); p1 = gsub(p1, ginv(p1)); return gerepileupto(av, gmul2n(p1,-1)); } return trans_eval("sinh",gsinh,x,prec); } /********************************************************************/ /** **/ /** HYPERBOLIC TANGENT **/ /** **/ /********************************************************************/ static GEN mptanh(GEN x) { long lx, s = signe(x); GEN y; if (!s) return real_0_bit(expo(x)); lx = realprec(x); if (abscmprr(x, utor(prec2nbits(lx), LOWDEFAULTPREC)) >= 0) { y = real_1(lx); } else { pari_sp av = avma; long e = expo(x) + BITS_IN_LONG; GEN t; if (e < 0) x = rtor(x, lx + nbits2extraprec(-e)); t = exp1r_abs(gmul2n(x,1)); /* exp(|2x|) - 1 */ y = gerepileuptoleaf(av, divrr(t, addsr(2,t))); } if (s < 0) togglesign(y); /* tanh is odd */ return y; } GEN gtanh(GEN x, long prec) { pari_sp av; GEN y, t; switch(typ(x)) { case t_REAL: return mptanh(x); case t_COMPLEX: if (isintzero(gel(x,1))) retmkcomplex(gen_0, gtan(gel(x,2),prec)); /* fall through */ case t_PADIC: av = avma; t = gexp(gmul2n(x,1),prec); t = gdivsg(-2, gaddgs(t,1)); return gerepileupto(av, gaddsg(1,t)); default: av = avma; if (!(y = toser_i(x))) break; if (gequal0(y)) return gerepilecopy(av, y); t = gexp(gmul2n(y, 1),prec); t = gdivsg(-2, gaddgs(t,1)); return gerepileupto(av, gaddsg(1,t)); } return trans_eval("tanh",gtanh,x,prec); } static GEN mpcotanh(GEN x) { long lx, s = signe(x); GEN y; if (!s) pari_err_DOMAIN("cotan", "argument", "=", gen_0, x); lx = realprec(x); if (abscmprr(x, utor(prec2nbits(lx), LOWDEFAULTPREC)) >= 0) { y = real_1(lx); } else { pari_sp av = avma; long e = expo(x) + BITS_IN_LONG; GEN t; if (e < 0) x = rtor(x, lx + nbits2extraprec(-e)); t = exp1r_abs(gmul2n(x,1)); /* exp(|2x|) - 1 */ y = gerepileuptoleaf(av, divrr(addsr(2,t), t)); } if (s < 0) togglesign(y); /* cotanh is odd */ return y; } GEN gcotanh(GEN x, long prec) { pari_sp av; GEN y, t; switch(typ(x)) { case t_REAL: return mpcotanh(x); case t_COMPLEX: if (isintzero(gel(x,1))) retmkcomplex(gen_0, gcotan(gel(x,2),prec)); /* fall through */ case t_PADIC: av = avma; t = gexpm1(gmul2n(x,1),prec); return gerepileupto(av, gaddsg(1, gdivsg(2,t))); default: av = avma; if (!(y = toser_i(x))) break; if (gequal0(y)) return gerepilecopy(av, y); t = gexpm1(gmul2n(y,1),prec); return gerepileupto(av, gaddsg(1, gdivsg(2,t))); } return trans_eval("cotanh",gcotanh,x,prec); } /********************************************************************/ /** **/ /** AREA HYPERBOLIC SINE **/ /** **/ /********************************************************************/ /* x != 0 */ static GEN mpasinh(GEN x) { long lx = realprec(x), e = expo(x) + BITS_IN_LONG; GEN z, res = cgetr(lx); pari_sp av = avma; if (e < 0) x = rtor(x, lx + nbits2extraprec(-e)); z = logr_abs( addrr_sign(x,1, sqrtr_abs( addrs(sqrr(x), 1) ), 1) ); if (signe(x) < 0) togglesign(z); affrr(z, res); return gc_const(av, res); } GEN gasinh(GEN x, long prec) { pari_sp av; GEN a, y, p1; switch(typ(x)) { case t_REAL: if (!signe(x)) return rcopy(x); return mpasinh(x); case t_COMPLEX: { GEN a, b, d; if (ismpzero(gel(x,2))) return gasinh(gel(x,1), prec); av = avma; if (ismpzero(gel(x,1))) /* avoid cancellation */ return gerepilecopy(av, mulcxI(gasin(gel(x,2), prec))); d = gsqrt(gaddsg(1,gsqr(x)), prec); /* Re(d) >= 0 */ a = gadd(d, x); b = gsub(d, x); /* avoid cancellation as much as possible */ if (gprecision(a) < gprecision(b)) y = gneg(glog(b,prec)); else y = glog(a,prec); return gerepileupto(av, y); /* log (x + sqrt(1+x^2)) */ } default: av = avma; if (!(y = toser_i(x))) break; if (gequal0(y)) return gerepilecopy(av, y); if (valser(y) < 0) pari_err_DOMAIN("asinh","valuation", "<", gen_0, x); p1 = gaddsg(1,gsqr(y)); if (gequal0(p1)) { GEN t = PiI2n(-1,prec); if ( gsigne(imag_i(gel(y,2))) < 0 ) setsigne(gel(t,2), -1); return gerepileupto(av, scalarser(t, varn(y), valser(p1)>>1)); } p1 = gdiv(derivser(y), gsqrt(p1,prec)); a = integser(p1); if (!valser(y)) a = gadd(a, gasinh(gel(y,2),prec)); return gerepileupto(av, a); } return trans_eval("asinh",gasinh,x,prec); } /********************************************************************/ /** **/ /** AREA HYPERBOLIC COSINE **/ /** **/ /********************************************************************/ /* |x| >= 1, return ach(|x|) */ static GEN mpacosh(GEN x) { long lx = realprec(x), e; GEN z, res = cgetr(lx); pari_sp av = avma; e = expo(signe(x) > 0? subrs(x,1): addrs(x,1)); if (e == -(long)HIGHEXPOBIT) return gc_const((pari_sp)(res + lx), real_0_bit(- bit_prec(x) >> 1)); if (e < -5) x = rtor(x, realprec(x) + nbits2extraprec(-e)); z = logr_abs( addrr_sign(x, 1, sqrtr( subrs(sqrr(x), 1) ), 1) ); affrr(z, res); return gc_const(av, res); } GEN gacosh(GEN x, long prec) { pari_sp av; GEN y; switch(typ(x)) { case t_REAL: { long s = signe(x), e = expo(x); GEN a, b; if (s > 0 && e >= 0) return mpacosh(x); /* x < 1 */ y = cgetg(3,t_COMPLEX); a = gen_0; if (s == 0) b = acos0(e); else if (e < 0) b = mpacos(x); /* -1 < x < 1 */ else { if (!absrnz_equal1(x)) a = mpacosh(x); b = mppi(realprec(x)); } gel(y,1) = a; gel(y,2) = b; return y; } case t_COMPLEX: { GEN a, b, d; if (ismpzero(gel(x,2))) return gacosh(gel(x,1), prec); av = avma; d = gsqrt(gaddsg(-1,gsqr(x)), prec); /* Re(d) >= 0 */ a = gadd(x, d); b = gsub(x, d); /* avoid cancellation as much as possible */ if (gprecision(a) < gprecision(b)) y = glog(b,prec); else y = glog(a,prec); /* y = \pm log(x + sqrt(x^2-1)) */ if (gsigne(real_i(y)) < 0) y = gneg(y); return gerepileupto(av, y); } default: { GEN a, d; long v; av = avma; if (!(y = toser_i(x))) break; v = valser(y); if (v < 0) pari_err_DOMAIN("acosh","valuation", "<", gen_0, x); if (gequal0(y)) { if (!v) return gerepilecopy(av, y); return gerepileupto(av, gadd(y, PiI2n(-1, prec))); } d = gsubgs(gsqr(y),1); if (gequal0(d)) { set_avma(av); return zeroser(varn(y), valser(d)>>1); } d = gdiv(derivser(y), gsqrt(d,prec)); a = integser(d); if (v) d = PiI2n(-1, prec); /* I Pi/2 */ else { d = gel(y,2); if (gequal1(d)) return gerepileupto(av,a); d = gacosh(d, prec); } return gerepileupto(av, gadd(d,a)); } } return trans_eval("acosh",gacosh,x,prec); } /********************************************************************/ /** **/ /** AREA HYPERBOLIC TANGENT **/ /** **/ /********************************************************************/ /* |x| < 1, x != 0 */ static GEN mpatanh(GEN x) { pari_sp av = avma; long e, s = signe(x); GEN z; z = s > 0? subsr(1,x): addsr(1,x); e = expo(z); if (e < -5) { x = rtor(x, realprec(x) + nbits2extraprec(-e)-EXTRAPRECWORD); z = s > 0? subsr(1,x): addsr(1,x); e = expo(z); } z = invr(z); shiftr_inplace(z, 1); /* 2/(1-|x|) */ z = logr_abs( addrs(z,-1) ); if (s < 0) togglesign(z); shiftr_inplace(z, -1); return gerepileuptoleaf(av, z); } static long get_nmax(double u, double v, long prec) { double d = 2 * log2(((double)v) / u); /* can be 0 due to rounding */ long nmax = -1; if (d) { d = ceil(prec2nbits(prec) / d); if (dblexpo(d) < BITS_IN_LONG) nmax = (long)d; } return nmax; } /* atanh(u/v) using binary splitting, 0 < u < v */ GEN atanhuu(ulong u, ulong v, long prec) { GEN u2 = sqru(u), v2 = sqru(v); long i, nmax = get_nmax((double)u, (double)v, prec); struct abpq_res R; struct abpq A; if (nmax < 0) pari_err_OVERFLOW("atanhuu"); abpq_init(&A, nmax); /* nmax satisfies (2n+1) (v/u)^2n > 2^bitprec */ A.a[0] = A.b[0] = gen_1; A.p[0] = utoipos(u); A.q[0] = utoipos(v); for (i = 1; i <= nmax; i++) { A.a[i] = gen_1; A.b[i] = utoipos((i<<1)+1); A.p[i] = u2; A.q[i] = v2; } abpq_sum(&R, 0, nmax, &A); return rdivii(R.T, mulii(R.B,R.Q),prec); } /* atanh(u/v) using binary splitting, 0 < u < v */ GEN atanhui(ulong u, GEN v, long prec) { GEN u2 = sqru(u), v2 = sqri(v); long i, nmax = get_nmax((double)u, gtodouble(v), prec); struct abpq_res R; struct abpq A; if (nmax < 0) pari_err_OVERFLOW("atanhui"); abpq_init(&A, nmax); A.a[0] = A.b[0] = gen_1; A.p[0] = utoipos(u); A.q[0] = v; for (i = 1; i <= nmax; i++) { A.a[i] = gen_1; A.b[i] = utoipos((i<<1)+1); A.p[i] = u2; A.q[i] = v2; } abpq_sum(&R, 0, nmax, &A); return rdivii(R.T, mulii(R.B,R.Q),prec); } static void err_atanh(GEN x, GEN bad) { pari_err_DOMAIN("atanh", "x", "=", bad, x); } GEN gatanh(GEN x, long prec) { long sx; pari_sp av; GEN a, y, z; switch(typ(x)) { case t_INT: sx = signe(x); if (!sx) return real_0(prec); z = cgetg(3, t_COMPLEX); av = avma; if (lgefint(x) == 3) { if (x[2] == 1) err_atanh(x, sx == 1? gen_1: gen_m1); a = atanhuu(1, x[2], prec); } else a = atanhui(1, x, prec); gel(z,1) = gerepileuptoleaf(av, a); gel(z,2) = Pi2n(-1, prec); togglesign(sx > 0? gel(z,2): gel(z,1)); return z; case t_FRAC: { long ly, lz, e; y = gel(x,1); ly = lgefint(y); z = gel(x,2); lz = lgefint(z); if (ly > 3 && lz > 3) break; if (abscmpii(y, z) > 0) /* |y| > z; lz = 3 */ { ulong u = z[2]; av = avma; e = expi((signe(y) < 0)? addii(y, z): subii(y, z)); set_avma(av); if (e < - prec2nbits(prec)) break; z = cgetg(3, t_COMPLEX); av = avma; a = ly == 3? atanhuu(u, y[2], prec): atanhui(u, y, prec); gel(z,1) = gerepileuptoleaf(av, a); gel(z,2) = Pi2n(-1, prec); togglesign(signe(y) > 0? gel(z,2): gel(z,1)); } else { /* |y| < z; ly = 3 */ av = avma; e = expi((signe(y) < 0)? addii(y, z): subii(y, z)); set_avma(av); if (e < - prec2nbits(prec)) break; a = lz == 3? atanhuu(y[2], z[2], prec): atanhui(y[2], z, prec); z = gerepileuptoleaf(av, a); if (signe(y) < 0) togglesign(z); } return z; } case t_REAL: sx = signe(x); if (!sx) return real_0_bit(expo(x)); if (expo(x) < 0) return mpatanh(x); y = cgetg(3,t_COMPLEX); av = avma; z = subrs(x,1); if (!signe(z)) err_atanh(x, gen_1); z = invr(z); shiftr_inplace(z, 1); /* 2/(x-1)*/ z = addrs(z,1); if (!signe(z)) err_atanh(x, gen_m1); z = logr_abs(z); shiftr_inplace(z, -1); /* (1/2)log((1+x)/(x-1)) */ gel(y,1) = gerepileuptoleaf(av, z); gel(y,2) = Pi2n(-1, realprec(x)); if (sx > 0) togglesign(gel(y,2)); return y; case t_COMPLEX: /* 2/(1-z) - 1 = (1+z) / (1-z) */ if (ismpzero(gel(x,2))) return gatanh(gel(x,1), prec); av = avma; z = glog( gaddgs(gdivsg(2,gsubsg(1,x)),-1), prec ); return gerepileupto(av, gmul2n(z,-1)); default: av = avma; if (!(y = toser_i(x))) break; if (valser(y) < 0) pari_err_DOMAIN("atanh","valuation", "<", gen_0, x); z = gdiv(derivser(y), gsubsg(1,gsqr(y))); a = integser(z); if (!valser(y)) a = gadd(a, gatanh(gel(y,2),prec)); return gerepileupto(av, a); } return trans_eval("atanh",gatanh,x,prec); } /********************************************************************/ /** **/ /** EULER'S GAMMA **/ /** **/ /********************************************************************/ /* 0 < a < b */ static GEN mulu_interval_step_i(ulong a, ulong b, ulong step) { ulong k, l, N, n; long lx; GEN x; n = 1 + (b-a) / step; b -= (b-a) % step; /* step | b-a */ lx = 1; x = cgetg(2 + n/2, t_VEC); N = b + a; for (k = a;; k += step) { 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 x; } static GEN _mul(void *data, GEN x, GEN y) { long prec = (long)data; /* switch to t_REAL ? */ if (typ(x) == t_INT && lg2prec(lgefint(x)) > prec) x = itor(x, prec); if (typ(y) == t_INT && lg2prec(lgefint(y)) > prec) y = itor(y, prec); return mpmul(x, y); } static GEN mulu_interval_step_prec(long l, long m, long s, long prec) { GEN v = mulu_interval_step_i(l, m, s); return gen_product(v, (void*)prec, &_mul); } /* x * (i*(i+1)) */ static GEN muliunextu(GEN x, ulong i) { if (i & HIGHMASK) /* i(i+1) >= 2^BITS_IN_LONG*/ return mulii(x, muluu(i, i+1)); else return muliu(x, i*(i+1)); } /* arg(s+it) */ double darg(double s, double t) { double x; if (!t) return (s>0)? 0.: M_PI; if (!s) return (t>0)? M_PI/2: -M_PI/2; x = atan(t/s); return (s>0)? x : ((t>0)? x+M_PI : x-M_PI); } void dcxlog(double s, double t, double *a, double *b) { *a = log(s*s + t*t) / 2; /* log |s| = Re(log(s)) */ *b = darg(s,t); /* Im(log(s)) */ } double dabs(double s, double t) { return sqrt( s*s + t*t ); } double dnorm(double s, double t) { return s*s + t*t; } #if 0 /* x, z t_REAL. Compute unique x in ]-z,z] congruent to x mod 2z */ static GEN red_mod_2z(GEN x, GEN z) { GEN Z = gmul2n(z, 1), d = subrr(z, x); /* require little accuracy */ if (!signe(d)) return x; setprec(d, nbits2prec(expo(d) - expo(Z))); return addrr(mulir(floorr(divrr(d, Z)), Z), x); } #endif static GEN negeuler(long prec) { GEN g = mpeuler(prec); setsigne(g, -1); return g; } /* lngamma(1+z) = -Euler*z + sum_{i > 1} zeta(i)/i (-z)^i * at relative precision prec, |z| <= 1/2 is small */ static GEN lngamma1(GEN z, long prec) { /* sum_{i > l} |z|^(i-1) = |z|^l / (1-|z|) < 2^-B * for l > (B+1) / |log2(|z|)| */ long i, l = ceil((prec2nbits(prec) + 1) / - dbllog2(z)); GEN s, vz; if (l <= 1) return gmul(negeuler(prec), z); vz = constzeta(l, prec); for (i = l, s = gen_0; i > 0; i--) { GEN c = divru(gel(vz,i), i); if (odd(i)) setsigne(c, -1); s = gadd(gmul(s,z), c); } return gmul(z, s); } /* B_i / (i(i-1)), i even. Sometimes NOT reduced (but gadd/gmul won't care)!*/ static GEN bern_unextu(long i) { GEN B = bernfrac(i); return mkfrac(gel(B,1), muliunextu(gel(B,2), i-1)); } /* B_i / i, i even. Sometimes NOT reduced (but gadd/gmul won't care)!*/ static GEN bern_u(long i) { GEN B = bernfrac(i); return mkfrac(gel(B,1), muliu(gel(B,2), i)); } /* sum_{i > 0} B_{2i}/(2i(2i-1)) * a^(i-1) */ static GEN lngamma_sum(GEN a, long N) { pari_sp av = avma; GEN S = bern_unextu(2*N); long i; for (i = 2*N-2; i > 0; i -= 2) { S = gadd(bern_unextu(i), gmul(a,S)); if (gc_needed(av,3)) { if(DEBUGMEM>1) pari_warn(warnmem,"gamma: i = %ld", i); S = gerepileupto(av, S); } } return S; } /* sum_{i > 0} B_{2i}/(2i) * a^i */ static GEN psi_sum(GEN a, long N) { pari_sp av = avma; GEN S = bern_u(2*N); long i; for (i = 2*N-2; i > 0; i -= 2) { S = gadd(bern_u(i), gmul(a,S)); if (gc_needed(av,3)) { if(DEBUGMEM>1) pari_warn(warnmem,"psi: i = %ld", i); S = gerepileupto(av, S); } } return gmul(a,S); } static void gamma_optim(double ssig, double st, long prec, long *plim, long *pN) { double la, l,l2,u,v, rlogs, ilogs; long N = 1, lim; 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.*M_PI)/2; v = v - st; l2 = u*u + v*v; if (l2 < 0.000001) l2 = 0.000001; l = (prec2nbits_mul(prec, M_LN2) - log(l2)/2) / 2.; if (l < 0) l = 0.; if (st > 1 && l > 0) { double t = st * M_PI / l; la = t * log(t); if (la < 4.) la = 4.; if (la > 150) la = t; } else la = 4.; /* heuristic */ lim = (long)ceil(l / (1.+ log(la))); if (lim == 0) lim = 1; u = (lim-0.5) * la / M_PI; l2 = u*u - st*st; if (l2 > 0) { double t = ceil(sqrt(l2) - ssig); if (t > 1) N = (long)t; } *plim = lim; *pN = N; } /* do we use lngamma1 instead of Euler-Maclaurin ? */ static int gamma_use_1(double s, double t, long prec, long *plim, long *pN) { double a = s-1, d = fabs(a) + fabs(t); long k; if (d < 1e-16) return 1; gamma_optim(s, t, prec, plim, pN); if (d >= 0.5) return 0; k = prec2nbits(prec) / -log2(dnorm(a, t)); /* 2k = lngamma1 bound */ return (t ? k: 1.5*k) < *plim + *pN; } static GEN cxgamma(GEN s0, int dolog, long prec) { GEN s, a, y, res, sig, tau, B, nnx, pi, pi2; long i, esig, et, lim, N = 1; pari_sp av, av2; int funeq = 0; pari_timer T; if (DEBUGLEVEL>5) timer_start(&T); s = trans_fix_arg(&prec,&s0,&sig,&tau,&av,&res); esig = expo(sig); et = signe(tau)? expo(tau): 0; if ((signe(sig) <= 0 || esig < -1) && et <= 16) { /* s <--> 1-s */ funeq = 1; s = gsubsg(1, s); sig = real_i(s); } /* find "optimal" parameters [lim, N] */ if (esig > 300 || et > 300) { /* |s| is HUGE ! Play safe and avoid inf / NaN */ GEN S, iS, l2, la, u; double logla, l; S = gprec_w(s,LOWDEFAULTPREC); /* l2 ~ |lngamma(s))|^2 */ l2 = gnorm(gmul(S, glog(S, LOWDEFAULTPREC))); l = (prec2nbits_mul(prec, M_LN2) - rtodbl(glog(l2,LOWDEFAULTPREC))/2) / 2.; if (l < 0) l = 0.; iS = imag_i(S); if (et > 0 && l > 0) { GEN t = gmul(iS, dbltor(M_PI / l)), logt = glog(t,LOWDEFAULTPREC); la = gmul(t, logt); if (gcmpgs(la, 3) < 0) { logla = log(3.); la = stoi(3); } else if (gcmpgs(la, 150) > 0) { logla = rtodbl(logt); la = t; } 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)/M_PI)); l2 = gsub(gsqr(u), gsqr(iS)); if (signe(l2) > 0) { l2 = gsub(gsqrt(l2,3), sig); if (signe(l2) > 0) N = itos( gceil(l2) ); } } else { /* |s| is moderate. Use floats */ double ssig = rtodbl(sig); double st = typ(s) == t_REAL? 0.0: rtodbl(imag_i(s)); if (gamma_use_1(ssig, st, prec, &lim, &N)) { /* s ~ 1: loggamma(1+u) ~ - Euler * u, cancellation */ if (funeq) /* s0 ~ 0: use lngamma(s0)+log(s0) = lngamma(s0+1) */ y = dolog? gsub(lngamma1(s0,prec), glog(s0,prec)) : gdiv(gexp(lngamma1(s0,prec), prec), s0); else { if (isint1(s0)) { set_avma(av); return dolog? real_0(prec): real_1(prec); } y = lngamma1(gsubgs(s0,1),prec); if (!dolog) y = gexp(y,prec); } set_avma(av); return affc_fixlg(y, res); } } if (DEBUGLEVEL>5) err_printf("lim, N: [%ld, %ld]\n",lim,N); incrprec(prec); av2 = avma; y = s; if (typ(s0) == t_INT) { ulong ss = itou_or_0(s0); if (signe(s0) <= 0) pari_err_DOMAIN("gamma","argument", "=", strtoGENstr("nonpositive integer"), s0); if (!ss || ss + (ulong)N < ss) { for (i=1; i < N; i++) { y = mulri(y, addiu(s0, i)); if (gc_needed(av2,3)) { if(DEBUGMEM>1) pari_warn(warnmem,"gamma"); y = gerepileuptoleaf(av2, y); } } } else { for (i=1; i < N; i++) { y = mulru(y, ss + i); if (gc_needed(av2,3)) { if(DEBUGMEM>1) pari_warn(warnmem,"gamma"); y = gerepileuptoleaf(av2, y); } } } } else { /* Compute lngamma mod 2 I Pi */ GEN sq = gsqr(s); pari_sp av3 = avma; for (i = 1; i < N - 1; i += 2) { y = gmul(y, gaddsg(i*(i + 1), gadd(gmulsg(2*i + 1, s), sq))); if (gc_needed(av2,3)) { if(DEBUGMEM>1) pari_warn(warnmem,"gamma"); y = gerepileupto(av3, y); } } if (!odd(N)) y = gmul(y, gaddsg(N - 1, s)); } if (DEBUGLEVEL>5) timer_printf(&T,"product from 0 to N-1"); constbern(lim); nnx = gaddgs(s, N); a = ginv(nnx); B = gadd(gsub(gmul(gsub(nnx, ghalf), glog(nnx,prec)), nnx), gmul(a, lngamma_sum(gsqr(a), lim))); if (DEBUGLEVEL>5) timer_printf(&T,"Bernoulli sum"); pi = mppi(prec); pi2 = shiftr(pi, 1); if (dolog) { if (typ(s) == t_REAL) { if (!funeq) y = logr_abs(divrr(sqrtr(pi2), y)); else { GEN T = shiftr(sqrtr(pi2),-1); /* sqrt(Pi/2) */ /* s0 < 0, step (*) simplifies: imag(lngamma(s0)) = - Pi * floor(s0) */ y = logr_abs(divrr(mulrr(y, T), mpsin(gmul(pi,s0)))); y = mkcomplex(y, mulri(pi, gfloor(s0))); B = gneg(B); } } else { /* log(y), fixing imaginary part */ long prec2 = LOWDEFAULTPREC; GEN k, s2 = gprec_w(s, prec2), y2 = garg(s2, prec2); /* ~ Im log(s) */ for (i=1; i < N; i++) y2 = gadd(y2, garg(gaddgs(s2,i), prec2)); y = glog(y, prec); k = ground( gdiv(gsub(y2, imag_i(y)), Pi2n(1,prec2)) ); if (signe(k)) y = gadd(y, mulcxI(mulir(k, Pi2n(1, prec)))); if (!funeq) y = gsub(shiftr(logr_abs(pi2),-1), y); /* y -> sqrt(2Pi)/y */ else { /* recall that s = 1 - s0 */ GEN T = shiftr(sqrtr(pi2),-1); /* sqrt(Pi/2) */ /* (*) 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(Pi/2)) */ GEN z = glog(gdiv(gsin(gmul(pi,s0),prec), T), prec); GEN b = shiftr(subrs(shiftr(sig, 1), 1), -2); /* (2 Re(s)-1) / 4 */ y = gsub(y, z); if (gsigne(imag_i(s)) > 0) togglesign(b); z = roundr(gsub(gdiv(imag_i(z), pi2), b)); /* round( Im(z)/2Pi - b ) */ if (signe(z)) { /* y += I*z, z a t_REAL */ z = mulir(z, pi2); if (typ(y) == t_COMPLEX) gel(y,2) = gadd(gel(y,2), z); else y = mkcomplex(y, z); } B = gneg(B); } } y = gadd(B, y); } else { GEN sqrtpi2 = sqrtr(pi2); 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 */ B = gneg(B); } else /* y --> sqrt(2Pi) / y */ y = gdiv(sqrtpi2, y); y = gmul(gexp(B, prec), y); } set_avma(av); return affc_fixlg(y, res); } /* Theory says n > C * b^1.5 / log(b). Timings: * b = 64*[1, 2, 3, 4, 5, 6, 7, 10, 20, 30, 50, 100, 200, 500]; * n = [1450, 1930, 2750, 3400, 4070, 5000, 6000, 8800, 26000, 50000, 130000, * 380000, 1300000, 6000000]; */ static long gamma2_n(long prec) { long b = prec2nbits(prec); if (b <= 64) return 1450; if (b <= 128) return 1930; if (b <= 192) return 2750; if (b <= 256) return 3400; if (b <= 320) return 4070; if (b <= 384) return 5000; if (b <= 448) return 6000; return 10.0 * b * sqrt(b) / log(b); } /* m even, 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 > gamma2_n(prec)) { z = stor(m + 1, prec); shiftr_inplace(z, -1); affrr(cxgamma(z,0,prec), y); set_avma(av); return y; } z = sqrtr( mppi(prec) ); if (m) { GEN t = mulu_interval_step_prec(1, ma-1, 2, prec + EXTRAPREC64); if (m >= 0) z = mpmul(z,t); else { z = mpdiv(z,t); if ((m&3) == 2) setsigne(z,-1); } shiftr_inplace(z, -m/2); } affrr(z, y); set_avma(av); return y; } GEN ggammah(GEN x, long prec) { switch(typ(x)) { case t_INT: { long k = itos_or_0(x); if (!k && signe(x)) pari_err_OVERFLOW("gamma"); return gammahs(k * 2, prec); } case t_REAL: case t_COMPLEX: case t_PADIC: case t_SER: { pari_sp av = avma; return gerepileupto(av, ggamma(gadd(x,ghalf), prec)); } } return trans_eval("gammah",ggammah,x,prec); } /* find n such that n+v_p(n!)>=k p^2/(p-1)^2 */ static long nboft(long k, long p) { pari_sp av = avma; long s, n; if (k <= 0) return 0; k = itou( gceil(gdiv(mului(k, sqru(p)), sqru(p-1))) ); set_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 = cvtop(gen_1, gel(x,2), n); gel(u, 1) = s; gel(u, 2) = s; for (j = 2; j < p; ++j) gel(u, j+1) = gdivgu(gel(u, j), j); for (k = 1, kp = p; k < n; ++k, kp += p) /* kp = k*p */ { GEN c; gel(u, 1) = gdivgu(gadd(gel(u, 1), gel(u, p)), kp); for (j = 1; j < p; ++j) gel(u, j+1) = gdivgu(gadd(gel(u, j), gel(u, j+1)), kp + j); t = gmul(t, gaddgs(x, k-1)); c = leafcopy(gel(u,1)); setvalp(c, valp(c) + k); /* c = u[1] * p^k */ s = gadd(s, gmul(c, t)); if ((k&0xFL)==0) gerepileall(ltop, 3, &u,&s,&t); } return gneg(s); } /*Use Dwork expansion*/ /*This is a O(p*e*log(pe)) algorithm, should be used when p small * If p==2 this is a O(pe) algorithm. */ static GEN Qp_gamma_Dwork(GEN x, long p) { pari_sp ltop = avma; long k = padic_to_Fl(x, p); GEN p1; long j; long px = precp(x); if (p==2 && px) { x = shallowcopy(x); setprecp(x, px+1); gel(x,3) = shifti(gel(x,3),1); } if (k) { GEN x_k = gsubgs(x,k); x = gdivgu(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(gdivgu(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 av = avma; GEN p2 = cvtop((n&1)? gen_m1: gen_1, p, e); long i, pp = is_bigint(p)? 0: itos(p); for (i = 2; i < n; i++) if (!pp || i%pp) { p2 = gmulgu(p2, i); if ((i&0xFL) == 0xFL) p2 = gerepileupto(av, p2); } return gerepileupto(av, 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 = valp(x) + precp(x); if (absequaliu(p, 2) && e == 2) e = 1; if (valp(x) < 0) pari_err_DOMAIN("gamma","v_p(x)", "<", gen_0, x); n = gtrunc(x); m = gtrunc(gneg(x)); N = cmpii(n,m)<=0?n:m; s = itos_or_0(N); if (s && cmpsi(s, muliu(p,e)) < 0) /* s < p*e */ return (N == n) ? Qp_gamma_Morita(s,p,e): Qp_gamma_neg_Morita(s,p,e); return Qp_gamma_Dwork(x, itos(p)); } static GEN Qp_lngamma(GEN x) { GEN s, y, Y; long v = valp(x), e, k, K; if (v >= 0) return Qp_log(Qp_gamma(x)); e = precp(x) + v; K = (2 + (e + 4) / (-v)) >> 1; s = gen_0; Y = y = ginv(x); y = gsqr(y); constbern(K); for (k = 1; k <= K; k++) { s = gadd(s, gmul(gdivgunextu(bernfrac(2*k), 2*k-1), Y)); if (k < K) Y = gmul(Y, y); /* x^(1-2k) */ } return gadd(s, gsub(gmul(gsub(x, ghalf), Qp_log(x)), x)); } /* gamma(1+x) - 1, |x| < 1 is "small" */ GEN ggamma1m1(GEN x, long prec) { return gexpm1(lngamma1(x, prec), prec); } /* lngamma(y) with 0 constant term, using (lngamma y)' = y' psi(y) */ static GEN serlngamma0(GEN y, long prec) { GEN t; if (valser(y)) pari_err_DOMAIN("lngamma","valuation", "!=", gen_0, y); t = derivser(y); /* don't compute psi if y'=0 */ if (signe(t)) t = gmul(t, gpsi(y,prec)); return integser(t); } static GEN sergamma(GEN y, long prec) { GEN z, y0, Y; if (lg(y) == 2) pari_err_DOMAIN("gamma", "argument", "=", gen_0,y); /* exp(lngamma) */ if (valser(y) > 0) return gdiv(gexp(glngamma(gaddgs(y,1),prec),prec),y); y0 = simplify_shallow(gel(y,2)); z = NULL; Y = y; if (isint(y0, &y0)) { /* fun eq. avoids log singularity of lngamma at negative ints */ long s = signe(y0); /* possible if y[2] is an inexact 0 */ if (!s) return gdiv(gexp(glngamma(gaddgs(y,1),prec),prec),y); if (signe(y0) < 0) { Y = gsubsg(1, y); y0 = subsi(1, y0); } if (abscmpiu(y0, 50) < 0) z = mpfact(itos(y0)-1); /* more precise */ } if (!z) z = ggamma(y0,prec); z = gmul(z, gexp(serlngamma0(Y,prec),prec)); if (Y != y) { GEN pi = mppi(prec); z = gdiv(mpodd(y0)? pi: negr(pi), gmul(z, gsin(gmul(pi,serchop0(y)), prec))); } return z; } static GEN sqrtu(ulong a, long prec) { return sqrtr_abs(utor(a, prec)); } static GEN cbrtu(ulong a, long prec) { return sqrtnr_abs(utor(a, prec), 3); } /* N | 6 */ static GEN ellkprime(long N, GEN s2, GEN s3) { GEN z; switch(N) { case 1: return shiftr(s2, -1); case 2: return sqrtr_abs(shiftr(subrs(s2,1), 1)); case 3: return shiftr(mulrr(s2, addrs(s3, 1)), -2); default: /* 6 */ z = mulrr(subrr(s3,s2), subsr(2,s3)); return mulrr(addsr(2,s2), sqrtr_abs(z)); } } static GEN ellKk(long N, GEN s2, GEN s3, long prec) { return gdiv(Pi2n(-1,prec), agm(ellkprime(N,s2,s3), gen_1, prec)); } /* Gamma(1/3) */ static GEN G3(GEN s2, GEN s3, long prec) { GEN A = ellKk(3, s2,s3, prec), pi = mppi(prec); A = shiftr(divrs(powrs(mulrr(pi, A), 12), 27), 28); return sqrtnr_abs(A, 36); } /* Gamma(1/4) */ static GEN G4(GEN s2, long prec) { GEN A = ellKk(1, s2,NULL, prec), pi = mppi(prec); return shiftr(sqrtr_abs(mulrr(sqrtr_abs(pi), A)), 1); } /* Gamma(n / 24), n = 1,5,7,11 */ static GEN Gn24(long n, GEN s2, GEN s3, long prec) { GEN A, B, C, t, t1, t2, t3, t4, pi = mppi(prec); A = ellKk(1, s2,s3, prec); B = ellKk(3, s2,s3, prec); C = ellKk(6, s2,s3, prec); t1 = sqrtr_abs(mulur(3, addsr(2, s3))); t2 = sqrtr_abs(divrr(s3, pi)); t2 = mulrr(t2, shiftr(mulrr(addrr(s2,s3), A), 2)); t3 = mulrr(divur(3,pi), sqrr(B)); t3 = mulrr(addsr(2,s2), sqrtnr_abs(shiftr(powrs(t3, 3), 8), 9)); t4 = mulrr(mulrr(addsr(1, s2), subrr(s3, s2)), subsr(2, s3)); t4 = mulrr(mulrr(mulur(384, t4), pi), sqrr(C)); switch (n) { case 1: t = mulrr(mulrr(t1, t2), mulrr(t3, t4)); break; case 5: t = divrr(mulrr(t2, t4), mulrr(t1, t3)); break; case 7: t = divrr(mulrr(t3, t4), mulrr(t1, t2)); break; default:t = divrr(mulrr(t1, t4), mulrr(t2, t3)); break; } return sqrtnr_abs(t, 4); } /* sin(x/2) = sqrt((1-c) / 2) > 0 given c = cos(x) */ static GEN sinx2(GEN c) { c = subsr(1, c); shiftr_inplace(c,-1); return sqrtr_abs(c); } /* sin(Pi/12), given sqrt(3) */ static GEN sin12(GEN s3) { GEN t = subsr(2, s3); shiftr_inplace(t, -2); return sqrtr_abs(t); } /* cos(Pi/12) = sin(5Pi/12), given sqrt(3) */ static GEN cos12(GEN s3) { GEN t = addsr(2, s3); shiftr_inplace(t, -2); return sqrtr_abs(t); } /* 0 < n < d, (n, d) = 1, 2 < d | 24 */ static GEN gammafrac24_s(long n, long d, long prec) { GEN A, B, s2, s3, pi = mppi(prec); s2 = sqrtu(2, prec); s3 = d % 3? NULL: sqrtu(3, prec); switch(d) { case 3: A = G3(s2,s3,prec); if (n == 1) return A; return divrr(Pi2n(1, prec), mulrr(s3, A)); case 4: A = G4(s2,prec); if (n == 1) return A; return divrr(mulrr(pi, s2), A); case 6: A = sqrr(G3(s2,s3,prec)); A = mulrr(A, sqrtr_abs(divsr(3, pi))); A = divrr(A, cbrtu(2, prec)); if (n == 1) return A; return divrr(Pi2n(1, prec), A); case 8: A = ellKk(1, s2,s3, prec); B = ellKk(2, s2,s3, prec); A = shiftr(sqrtr_abs(divrr(mulrr(addsr(1, s2), A), sqrtr_abs(pi))), 1); B = shiftr(mulrr(sqrtr_abs(gmul(subrs(s2, 1), mulrr(s2, pi))), B), 3); switch (n) { GEN t; case 1: return sqrtr_abs(mulrr(A, B)); case 3: return sqrtr_abs(divrr(B, A)); case 5: A = sqrtr_abs(divrr(B, A)); t = sqrtr_abs(shiftr(addsr(1, shiftr(s2, -1)), -1)); /*sin(3Pi/8)*/ return divrr(pi, mulrr(t, A)); default: A = sqrtr_abs(mulrr(A, B)); t = sqrtr_abs(shiftr(subsr(1, shiftr(s2, -1)), -1)); /*sin(Pi/8)*/ return divrr(pi, mulrr(t, A)); } case 12: A = G3(s2,s3,prec); B = G4(s2,prec); switch (n) { GEN t2; case 1: case 11: t2 = shiftr(mulur(27, powrs(divrr(addsr(1,s3), pi), 4)), -2); t2 = mulrr(sqrtnr_abs(t2, 8), mulrr(A, B)); if (n == 1) return t2; return divrr(pi, mulrr(sin12(s3), t2)); case 5: case 7: t2 = shiftr(divrs(powrs(mulrr(subrs(s3,1), pi), 4), 3), 2); t2 = mulrr(sqrtnr_abs(t2, 8), divrr(B, A)); if (n == 5) return t2; return divrr(pi, mulrr(cos12(s3), t2)); } default: /* n = 24 */ if (n > 12) { GEN t; n = 24 - n; A = Gn24(n, s2,s3, prec); switch(n) { /* t = sin(n*Pi/24) */ case 1: t = cos12(s3); t = sinx2(t); break; case 5: t = sin12(s3); t = sinx2(t); break; case 7: t = sin12(s3); togglesign(t); t = sinx2(t); break; default:t = cos12(s3); togglesign(t); t = sinx2(t); break; /* n=11 */ } return divrr(pi, mulrr(A, t)); } return Gn24(n, s2,s3, prec); } } /* (a,b) = 1. If 0 < x < b, m >= 0 gamma(x/b + m) = gamma(x/b) * mulu_interval_step(x, x+(m-1)*b, b) / b^m gamma(x/b - m) = gamma(x/b) / mulu_interval_step(b-x, b*m-x, b) * (-b)^m */ static GEN gammafrac24(GEN a, GEN b, long prec) { pari_sp av; long A, B, m, x, bit; GEN z0, z, t; if (!(A = itos_or_0(a)) || !(B = itos_or_0(b)) || B > 24) return NULL; switch(B) { case 2: return gammahs(A-1, prec); case 3: case 4: case 6: case 8: case 12: case 24: m = A / B; x = A % B; /* = A - m*B */ if (x < 0) { x += B; m--; } /* now 0 < x < B, A/B = x/B + m */ bit = prec2nbits(prec); /* Depending on B and prec, we must experimentally replace the 0.5 * by 0.4 to 2.0 for optimal value. Play safe. */ if (labs(m) > 0.5 * bit * sqrt(bit) / log(bit)) return NULL; z0 = cgetr(prec); av = avma; prec += EXTRAPREC64; z = gammafrac24_s(x, B, prec); if (m) { if (m > 0) t = mpdiv(mulu_interval_step(x, (m-1)*B + x, B), rpowuu(B,m,prec)); else { m = -m; t = mpdiv(rpowuu(B,m,prec), mulu_interval_step(B-x, m*B - x, B)); if (odd(m)) togglesign(t); } z = mpmul(z,t); } affrr(z, z0); set_avma(av); return z0; } return NULL; } GEN ggamma(GEN x, long prec) { pari_sp av; GEN y; switch(typ(x)) { case t_INT: if (signe(x) <= 0) pari_err_DOMAIN("gamma","argument", "=", strtoGENstr("nonpositive integer"), x); return mpfactr(itos(x) - 1, prec); case t_REAL: case t_COMPLEX: return cxgamma(x, 0, prec); case t_FRAC: { GEN a = gel(x,1), b = gel(x,2), c = gammafrac24(a, b, prec); if (c) return c; av = avma; c = subii(a,b); if (signe(a) < 0) { /* gamma will use functional equation x -> z = 1-x = -c/b >= 1/2. * Gamma(x) = Pi / (sin(Pi z) * Gamma(z)) */ GEN z = mkfrac(negi(c), b), q = ground(z), r = gsub(z,q); GEN pi = mppi(prec); /* |r| <= 1/2 */ z = fractor(z, prec+EXTRAPREC64); y = divrr(pi, mulrr(mpsin(gmul(pi, r)), cxgamma(z, 0, prec))); if (mpodd(q)) togglesign(y); return gerepileupto(av, y); } if (cmpii(shifti(a,1), b) < 0) { /* 0 < x < 1/2 gamma would use funeq: adding 1 is cheaper. */ if (expi(a) - expi(b) < -3) /* close to 0 */ { if (lg2prec(lgefint(b)) >= prec) x = fractor(x,prec); y = mpexp(lngamma1(x, prec)); } else y = cxgamma(fractor(mkfrac(addii(a,b), b), prec), 0, prec); return gerepileupto(av, gdiv(y, x)); } if (expi(c) - expi(b) < -3) { /* x = 1 + c/b is close to 1 */ x = mkfrac(c,b); if (lg2prec(lgefint(b)) >= prec) x = fractor(x,prec); y = mpexp(lngamma1(x, prec)); } else y = cxgamma(fractor(x, prec), 0, prec); return gerepileupto(av, y); } case t_PADIC: return Qp_gamma(x); default: av = avma; if (!(y = toser_i(x))) break; return gerepileupto(av, sergamma(y, prec)); } return trans_eval("gamma",ggamma,x,prec); } static GEN mpfactr_basecase(long n, long prec) { GEN v = cgetg(expu(n) + 2, t_VEC); long k, prec2 = prec + EXTRAPREC64; GEN a; for (k = 1;; k++) { long m = n >> (k-1), l; if (m <= 2) break; l = (1 + (n >> k)) | 1; /* product of odd numbers in ]n / 2^k, 2 / 2^(k-1)] */ a = mulu_interval_step_prec(l, m, 2, prec2); gel(v,k) = k == 1? a: gpowgs(a, k); } a = gel(v,--k); while (--k) a = mpmul(a, gel(v,k)); if (typ(a) == t_INT) a = itor(a, prec); else a = gprec_wtrunc(a, prec); shiftr_inplace(a, factorial_lval(n, 2)); return a; } /* Theory says n > C * b^1.5 / log(b). Timings: * b = [64, 128, 192, 256, 512, 1024, 2048, 4096, 8192, 16384] * n = [1930, 2650, 3300, 4270, 9000, 23000, 75000, 210000, 750000, 2400000] */ static long mpfactr_n(long prec) { long b = prec2nbits(prec); if (b <= 64) return 1930; if (b <= 128) return 2650; if (b <= 192) return 3300; return b * sqrt(b); } static GEN mpfactr_small(long n, long prec) { GEN f = cgetr(prec); pari_sp av = avma; if (n < 410) affir(mpfact(n), f); else affrr(mpfactr_basecase(n, prec), f); set_avma(av); return f; } GEN mpfactr(long n, long prec) { GEN f = cgetr(prec); pari_sp av = avma; if (n < 410) affir(mpfact(n), f); else { long N = mpfactr_n(prec); GEN z = n <= N? mpfactr_basecase(n, prec) : cxgamma(utor(n+1, prec), 0, prec); affrr(z, f); } set_avma(av); return f; } /* First a little worse than mpfactr_n because of the extra logarithm. * Asymptotically same. */ static ulong lngamma_n(long prec) { long b = prec2nbits(prec); double N; if (b <= 64) return 1450UL; if (b <= 128) return 2010UL; if (b <= 192) return 2870UL; N = b * sqrt(b); if (b <= 256) return N/1.25; if (b <= 512) return N/1.2; if (b <= 2048) return N/1.1; return N; } GEN glngamma(GEN x, long prec) { pari_sp av = avma; GEN y, y0, t; switch(typ(x)) { case t_INT: { ulong n; if (signe(x) <= 0) pari_err_DOMAIN("lngamma","argument", "=", strtoGENstr("nonpositive integer"), x); n = itou_or_0(x); if (!n || n > lngamma_n(prec)) return cxgamma(x, 1, prec); return gerepileuptoleaf(av, logr_abs( mpfactr_small(n-1, prec) )); } case t_FRAC: { GEN a = gel(x,1), b = gel(x,2), c = gammafrac24(a, b, prec); long e; if (c) return glog(c, prec); c = subii(a,b); e = expi(b) - expi(c); if (signe(a) < 0) { /* gamma will use functional equation x -> z = 1-x = -c/b >= 1/2. * lngamma(x) = log |Pi / (sin(Pi z) * Gamma(z))| + I*Pi * floor(x) */ GEN z = mkfrac(negi(c), b), q = ground(z), r = gsub(z,q); GEN pi = mppi(prec); /* |r| <= 1/2 */ z = fractor(z, prec+EXTRAPREC64); y = subrr(logr_abs(divrr(pi, mpsin(gmul(pi,r)))), cxgamma(z, 1, prec)); y = gadd(y, mkcomplex(gen_0, mulri(pi, gfloor(x)))); return gerepileupto(av, y); } if (cmpii(shifti(a,1), b) < 0) { /* 0 < x < 1/2 gamma would use funeq: adding 1 is cheaper. */ if (expi(a) - expi(b) < -3) /* close to 0 */ { if (lg2prec(lgefint(b)) >= prec) x = fractor(x,prec); y = lngamma1(x, prec); } else y = cxgamma(fractor(mkfrac(addii(a,b), b), prec), 1, prec); return gerepileupto(av, gsub(y, glog(x, prec))); } if (e > 3) { x = mkfrac(c,b); if (lg2prec(lgefint(b)) >= prec) x = fractor(x, prec + nbits2extraprec(e)); y = lngamma1(x, prec); } else { x = fractor(x, e > 1? prec+EXTRAPREC64: prec); y = cxgamma(x, 1, prec); } return gerepileupto(av, y); } case t_REAL: case t_COMPLEX: return cxgamma(x, 1, prec); default: if (!(y = toser_i(x))) break; if (lg(y) == 2) pari_err_DOMAIN("lngamma", "argument", "=", gen_0,y); t = serlngamma0(y,prec); y0 = simplify_shallow(gel(y,2)); /* no constant term if y0 = 1 or 2 */ if (!isint(y0,&y0) || signe(y0) <= 0 || abscmpiu(y0,2) > 2) t = gadd(t, glngamma(y0,prec)); return gerepileupto(av, t); case t_PADIC: return gerepileupto(av, Qp_lngamma(x)); } return trans_eval("lngamma",glngamma,x,prec); } /********************************************************************/ /** **/ /** PSI(x) = GAMMA'(x)/GAMMA(x) **/ /** **/ /********************************************************************/ static void err_psi(GEN s) { pari_err_DOMAIN("psi","argument", "=", strtoGENstr("nonpositive integer"), s); } /* L ~ |log s|^2 */ static long psi_lim(double L, double la, long prec) { double d = (prec2nbits_mul(prec, 2*M_LN2) - log(L)) / (4*(1+log(la))); return (d < 2)? 2: 2 + (long)ceil(d); } /* max(|log (s + it - Euler)|, 1e-6) */ static double dlogE(double s, double t) { double rlog, ilog; dcxlog(s - 0.57721566, t, &rlog,&ilog); return maxdd(dnorm(rlog,ilog), 1e-6); } static GEN cxpsi(GEN s0, long der, long prec) { pari_sp av, av2; GEN sum, z, a, res, sig, tau, s, unr, s2, sq; long lim, nn, k; const long la = 3; int funeq = 0; pari_timer T; if (der) { av = avma; res = zetahurwitz(stoi(der + 1), s0, 0, prec2nbits(prec)); if(!odd(der)) res = gneg(res); return gerepileupto(av, gmul(mpfact(der), res)); } if (DEBUGLEVEL>2) timer_start(&T); s = trans_fix_arg(&prec,&s0,&sig,&tau,&av,&res); if (signe(sig) <= 0) { funeq = 1; s = gsub(gen_1, s); sig = real_i(s); } if (typ(s0) == t_INT && signe(s0) <= 0) err_psi(s0); if (expo(sig) > 300 || (typ(s) == t_COMPLEX && gexpo(gel(s,2)) > 300)) { /* |s| is HUGE. Play safe */ GEN L, S = gprec_w(s,LOWDEFAULTPREC), rS = real_i(S), iS = imag_i(S); double l; lim = psi_lim(rtodbl(gnorm(glog(S,LOWDEFAULTPREC))), la, prec); l = (2*lim-1)*la / (2.*M_PI); L = gsub(dbltor(l*l), gsqr(iS)); if (signe(L) < 0) L = gen_0; L = gsub(gsqrt(L, LOWDEFAULTPREC), rS); if (signe(L) > 0) nn = (long)ceil(rtodbl(L)); else nn = 1; } else { double l, rS = rtodbl(sig), iS = typ(s) == t_REAL? 0.0: rtodbl(imag_i(s)); lim = psi_lim(dlogE(rS, iS), la, prec); l = (2*lim-1)*la / (2.*M_PI); l = l*l - iS*iS; if (l < 0.) l = 0.; nn = (long)ceil( sqrt(l) - rS ); if (nn < 1) nn = 1; } if (DEBUGLEVEL>2) err_printf("lim, nn: [%ld, %ld]\n",lim,nn); incrprec(prec); unr = real_1(prec); /* one extra word of precision */ s2 = gmul2n(s, 1); sq = gsqr(s); a = gdiv(unr, gaddgs(s, nn)); /* 1 / (s+n) */ av2 = avma; sum = gmul2n(a, -1); for (k = 0; k < nn - 1; k += 2) { GEN tmp = gaddsg(k*(k + 1), gadd(gmulsg(2*k + 1, s), sq)); sum = gadd(sum, gdiv(gaddsg(2*k + 1, s2), tmp)); if ((k & 1023) == 0) sum = gerepileupto(av2, sum); } if (odd(nn)) sum = gadd(sum, gdiv(unr, gaddsg(nn - 1, s))); z = gsub(glog(gaddgs(s, nn), prec), sum); if (DEBUGLEVEL>2) timer_printf(&T,"sum from 0 to N - 1"); constbern(lim); z = gsub(z, psi_sum(gsqr(a), lim)); if (DEBUGLEVEL>2) timer_printf(&T,"Bernoulli sum"); if (funeq) { GEN pi = mppi(prec); z = gadd(z, gmul(pi, gcotan(gmul(pi,s), prec))); } set_avma(av); return affc_fixlg(z, res); } /* n >= 0; return psi(1+x) + O(x^n), x = pol_x(v) */ GEN psi1series(long n, long v, long prec) { long i, l = n+3; GEN s = cgetg(l, t_SER), z = constzeta(n + 1, prec); s[1] = evalsigne(1)|evalvalser(0)|evalvarn(v); for (i = 1; i <= n+1; i++) { GEN c = gel(z,i); /* zeta(i) */ gel(s,i+1) = odd(i)? negr(c): c; } return s; } /* T an RgX, return T(X + z0) + O(X^L) */ static GEN tr(GEN T, GEN z0, long L) { GEN s = RgX_to_ser(RgX_translate(T, z0), L+3); setvarn(s, 0); return s; } /* z0 a complex number with Re(z0) > 1/2; return psi(z0+x) + O(x^L) * using Luke's rational approximation for psi(x) */ static GEN serpsiz0(GEN z0, long L, long v, long prec) { pari_sp av; GEN A,A1,A2, B,B1,B2, Q; long n; n = gprecision(z0); if (n) prec = n; z0 = gtofp(z0, prec + EXTRAPREC64); /* Start from n = 3; in Luke's notation, A2 := A_{n-2}, A1 := A_{n-1}, * A := A_n. Same for B */ av = avma; A2= gdivgu(mkpoln(2, gen_1, utoipos(6)), 2); B2 = scalarpol_shallow(utoipos(4), 0); A1= gdivgu(mkpoln(3, gen_1, utoipos(82), utoipos(96)), 6); B1 = mkpoln(2, utoipos(8), utoipos(28)); A = gdivgu(mkpoln(4, gen_1, utoipos(387), utoipos(2906), utoipos(1920)), 12); B = mkpoln(3, utoipos(14), utoipos(204), utoipos(310)); A2= tr(A2,z0, L); B2= tr(B2,z0, L); A1= tr(A1,z0, L); B1= tr(B1,z0, L); A = tr(A, z0, L); B = tr(B, z0, L); Q = gdiv(A, B); /* work with z0+x as a variable */ for (n = 4;; n++) { GEN Q0 = Q, a, b, r, c3,c2,c1,c0 = muluu(2*n-3, n+1); GEN u = subiu(muluu(n, 7*n-9), 6); GEN t = addiu(muluu(n, 7*n-19), 4); /* c1=(2*n-1)*(3*(n-1)*z+7*n^2-9*n-6); * c2=(2*n-3)*(z-n-1)*(-3*(n-1)*z+7*n^2-19*n+4); * c3=(2*n-1)*(n-3)*(z-n)*(z-(n+1))*(z+(n-4)); */ c1 = deg1pol_shallow(muluu(3*(n-1),2*n-1), muliu(u,2*n-1), 0); c2 = ZX_mul(deg1pol_shallow(utoipos(2*n-3), negi(muluu(2*n-3,n+1)), 0), deg1pol_shallow(utoineg(3*(n-1)), t, 0)); r = mkvec3(utoipos(n), utoipos(n+1), stoi(4-n)); c3 = ZX_Z_mul(roots_to_pol(r,0), muluu(2*n-1,n-3)); c1 = tr(c1, z0, L+3); c2 = tr(c2, z0, L+3); c3 = tr(c3, z0, L+3); /* A_{n+1}, B_{n+1} */ a = gdiv(gadd(gadd(gmul(c1,A),gmul(c2,A1)),gmul(c3,A2)), c0); b = gdiv(gadd(gadd(gmul(c1,B),gmul(c2,B1)),gmul(c3,B2)), c0); Q = gdiv(a,b); if (gexpo(gsub(Q,Q0)) < -prec2nbits(prec)) break; A2 = A1; A1 = A; A = a; B2 = B1; B1 = B; B = b; if (gc_needed(av,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"serpsiz0, n = %ld", n); gerepileall(av, 7, &A,&A1,&A2, &B,&B1,&B2, &Q); } } Q = gmul(Q, gmul2n(gsubsg(1, ginv(tr(pol_x(v),z0, L))), 1)); setvarn(Q, v); return gadd(negeuler(prec), Q); } /* sum (-1)^k*H(m,k)x^k + O(x^L); L > 0; * H(m,k) = (-1)^{k * \delta_{m > 0}} sum_{1<=i 2) { ik = divru(ik, i); if (expo(ik) < bit) break; } gel(H,k) = gadd(gel(H,k), ik); } if (gc_needed(av,3)) { if(DEBUGMEM>1) pari_warn(warnmem,"Hseries, i = %ld/%ld", i,M); H = gerepilecopy(av, H); } } if (m > 0) for (k = 3; k < l; k+=2) togglesign_safe(&gel(H,k)); return H; } static GEN serpsi(GEN y, long prec) { GEN Q = NULL, z0, Y = y, Y2; long L = lg(y)-2, v = varn(y), vy = valser(y); if (!L) pari_err_DOMAIN("psi", "argument", "=", gen_0,y); if (vy < 0) pari_err_DOMAIN("psi", "series valuation", "<", gen_0,y); if (vy) z0 = gen_0; else { z0 = simplify_shallow(gel(y,2)); (void)isint(z0, &z0); } if (typ(z0) == t_INT && !is_bigint(z0)) { long m = itos(z0); if (abscmpiu(muluu(prec2nbits(prec),L), labs(m)) > 0) { /* psi(m+x) = psi(1+x) + sum_{1 <= i < m} 1/(i+x) for m > 0 psi(1+x) - sum_{0 <= i < -m} 1/(i+x) for m <= 0 */ GEN H = NULL; if (m <= 0) L--; /* lose series accuracy due to 1/x term */ if (L) { Q = psi1series(L, v, prec); if (m && m != 1) { H = Hseries(m, L, v, prec); Q = gadd(Q, H); } if (m <= 0) Q = gsub(Q, ginv(pol_x(v))); } else { Q = scalarser(gen_m1, v, 1); setvalser(Q,-1); } } } if (!Q) { /* use psi(1-y)=psi(y)+Pi*cotan(Pi*y) ? */ if (gcmp(real_i(z0),ghalf) < 0) { z0 = gsubsg(1,z0); Y = gsubsg(1,y); } Q = serpsiz0(z0, L, v, prec); } Y2 = serchop0(Y); if (signe(Y2)) Q = gsubst(Q, v, Y2); /* psi(z0 + Y2) = psi(Y) */ if (Y != y) { /* psi(y) = psi(Y) + Pi cotan(Pi Y) */ GEN pi = mppi(prec); if (typ(z0) == t_INT) Y = Y2; /* in this case cotan(Pi*Y2) = cotan(Pi*Y) */ Q = gadd(Q, gmul(pi, gcotan(gmul(pi,Y), prec))); } return Q; } static ulong psi_n(ulong b) { if (b <= 64) return 50; if (b <= 128) return 85; if (b <= 192) return 122; if (b <= 256) return 150; if (b <= 512) return 320; if (b <= 1024) return 715; return 0.010709 * pow((double)b, 1.631); /* 1.631 ~ log_3(6) */ } GEN Qp_psi(GEN x, long der) { pari_sp av = avma; GEN p = gel(x,2), p1 = subis(p,1), z; long e = valp(x) + precp(x); if (valp(x) < 0) pari_err_DOMAIN("psi","v_p(x)", "<", gen_0, x); if (der < 0) pari_err_DOMAIN("psi","der","<", gen_0, stoi(der)); x = cvtop(x, p, e + 1); z = gmul(mpfact(der), Qp_zetahurwitz(cvtop(stoi(der + 1), p, e + sdivsi(e,p1)), x, -der)); if (!odd(der)) z = gneg(z); if (!der) z = gadd(mkfrac(p1,p), z); return gerepileupto(av, z); } GEN gpsi(GEN x, long prec) { pari_sp av; ulong n; GEN y; switch(typ(x)) { case t_INT: if (signe(x) <= 0) err_psi(x); if (lgefint(x) > 3 || (n = itou(x)) > psi_n(prec2nbits(prec))) break; av = avma; y = mpeuler(prec); return gerepileuptoleaf(av, n == 1? negr(y): gsub(harmonic(n-1), y)); case t_REAL: case t_COMPLEX: return cxpsi(x,0,prec); case t_PADIC: return Qp_psi(x, 0); default: av = avma; if (!(y = toser_i(x))) break; return gerepileupto(av, serpsi(y,prec)); } return trans_eval("psi",gpsi,x,prec); } static GEN _gpsi_der(void *E, GEN x, long prec) { return gpsi_der(x, (long) E, prec); } GEN gpsi_der(GEN x, long der, long prec) { pari_sp av; ulong n; GEN y; if (der < 0) pari_err_DOMAIN("gpsi", "der", "<", gen_0, stoi(der)); switch(typ(x)) { case t_INT: if (signe(x) <= 0) err_psi(x); if (lgefint(x) > 3 || (n = itou(x)) > psi_n(prec2nbits(prec))) break; av = avma; y = der ? szeta(der + 1, prec): mpeuler(prec); if (n > 1) { y = gsub(y, harmonic0(n - 1, stoi(der + 1))); if (!odd(der)) y = gneg(y); y = gmul(mpfact(der), y); return gerepileuptoleaf(av, y); } case t_REAL: case t_COMPLEX: return cxpsi(x, der, prec); case t_PADIC: return Qp_psi(x, der); default: av = avma; if (!(y = toser_i(x))) break; if (!der) y = serpsi(y,prec); else { y = zetahurwitz(stoi(der + 1), x, 0, prec2nbits(prec)); if(!odd(der)) y = gneg(y); y = gmul(mpfact(der), y); } return gerepileupto(av, y); } return trans_evalgen("psi",(void*)der,_gpsi_der,x,prec); } pari-2.17.2/src/basemath/FpX.c0000644000175000017500000022746014760123736014424 0ustar billbill/* Copyright (C) 2007 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" /* Not so fast arithmetic with polynomials over Fp */ static GEN get_FpX_red(GEN T, GEN *B) { if (typ(T)!=t_VEC) { *B=NULL; return T; } *B = gel(T,1); return gel(T,2); } /***********************************************************************/ /** **/ /** FpX **/ /** **/ /***********************************************************************/ /* FpX are polynomials over Z/pZ represented as t_POL with * t_INT coefficients. * 1) Coefficients should belong to {0,...,p-1}, though nonreduced * coefficients should work but be slower. * * 2) p is not assumed to be prime, but it is assumed that impossible divisions * will not happen. * 3) Theses functions let some garbage on the stack, but are gerepileupto * compatible. */ static ulong to_Flx(GEN *P, GEN *Q, GEN p) { ulong pp = uel(p,2); *P = ZX_to_Flx(*P, pp); if(Q) *Q = ZX_to_Flx(*Q, pp); return pp; } static ulong to_Flxq(GEN *P, GEN *T, GEN p) { ulong pp = uel(p,2); if (P) *P = ZX_to_Flx(*P, pp); *T = ZXT_to_FlxT(*T, pp); return pp; } GEN Z_to_FpX(GEN a, GEN p, long v) { pari_sp av = avma; GEN z = cgetg(3, t_POL); GEN x = modii(a, p); if (!signe(x)) { set_avma(av); return pol_0(v); } z[1] = evalsigne(1) | evalvarn(v); gel(z,2) = x; return z; } /* z in Z[X], return lift(z * Mod(1,p)), normalized*/ GEN FpX_red(GEN z, GEN p) { long i, l = lg(z); GEN x = cgetg(l, t_POL); for (i=2; i= ny) { lz = nx+2; z = cgetg(lz,t_POL); z[1] = 0; z += 2; for (i=0; ip); } static GEN _FpX_sqr(void *E, GEN x) { struct _FpX *D = (struct _FpX *)E; return FpX_sqr(x, D->p); } GEN FpX_powu(GEN x, ulong n, GEN p) { struct _FpX D; if (n==0) return pol_1(varn(x)); D.p = p; return gen_powu(x, n, (void *)&D, _FpX_sqr, _FpX_mul); } GEN FpXV_prod(GEN V, GEN p) { struct _FpX D; D.p = p; return gen_product(V, (void *)&D, &_FpX_mul); } static GEN _FpX_pow(void* E, GEN x, GEN y) { struct _FpX *D = (struct _FpX *)E; return FpX_powu(x, itou(y), D->p); } static GEN _FpX_one(void *E) { struct _FpX *D = (struct _FpX *)E; return pol_1(D->v); } GEN FpXV_factorback(GEN f, GEN e, GEN p, long v) { struct _FpX D; D.p = p; D.v = v; return gen_factorback(f, e, (void *)&D, &_FpX_mul, &_FpX_pow, &_FpX_one); } GEN FpX_halve(GEN y, GEN p) { GEN z; long i, l; z = cgetg_copy(y, &l); z[1] = y[1]; for(i=2; i=0 && !signe(gel(y, dy1)); dy1--); p1 = gel(x,dx); av = avma; gel(z,dz) = lead? gerepileuptoint(av, Fp_mul(p1,lead, p)): icopy(p1); for (i=dx-1; i>=dy; i--) { av=avma; p1=gel(x,i); for (j=i-dy1; 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) { guncloneNULL(lead); return z-2; } rem = (GEN)avma; av = (pari_sp)new_chunk(dx+3); for (sx=0; ; i--) { p1 = gel(x,i); for (j=maxss(0,i-dy1); 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; set_avma(av); } if (pr == ONLY_DIVIDES) { guncloneNULL(lead); if (sx) return gc_NULL(av0); return gc_const((pari_sp)rem, 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=maxss(0,i-dy1); 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; guncloneNULL(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; if (l <= 3) { if (r) *r = l == 2? gen_0: icopy(gel(a,2)); return pol_0(varn(a)); } l--; z = cgetg(l, t_POL); z[1] = a[1]; gel(z, l-1) = gel(a,l); for (i = l-2; i > 1; i--) /* z[i] = a[i+1] + x*z[i+1] */ gel(z,i) = Fp_addmul(gel(a,i+1), x, gel(z,i+1), p); if (r) *r = Fp_addmul(gel(a,2), x, gel(z,2), p); return z; } static GEN _FpX_divrem(void * E, GEN x, GEN y, GEN *r) { struct _FpX *D = (struct _FpX*) E; return FpX_divrem(x, y, D->p, r); } static GEN _FpX_add(void * E, GEN x, GEN y) { struct _FpX *D = (struct _FpX*) E; return FpX_add(x, y, D->p); } static struct bb_ring FpX_ring = { _FpX_add,_FpX_mul,_FpX_sqr }; GEN FpX_digits(GEN x, GEN T, GEN p) { struct _FpX D; long d = degpol(T), n = (lgpol(x)+d-1)/d; D.p = p; return gen_digits(x,T,n,(void *)&D, &FpX_ring, _FpX_divrem); } GEN FpXV_FpX_fromdigits(GEN x, GEN T, GEN p) { struct _FpX D; D.p = p; return gen_fromdigits(x,T,(void *)&D, &FpX_ring); } 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_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; } static GEN FpXM_mul2(GEN A, GEN B, GEN p) { GEN A11=gcoeff(A,1,1),A12=gcoeff(A,1,2), B11=gcoeff(B,1,1),B12=gcoeff(B,1,2); GEN A21=gcoeff(A,2,1),A22=gcoeff(A,2,2), B21=gcoeff(B,2,1),B22=gcoeff(B,2,2); GEN M1 = FpX_mul(FpX_add(A11,A22, p), FpX_add(B11,B22, p), p); GEN M2 = FpX_mul(FpX_add(A21,A22, p), B11, p); GEN M3 = FpX_mul(A11, FpX_sub(B12,B22, p), p); GEN M4 = FpX_mul(A22, FpX_sub(B21,B11, p), p); GEN M5 = FpX_mul(FpX_add(A11,A12, p), B22, p); GEN M6 = FpX_mul(FpX_sub(A21,A11, p), FpX_add(B11,B12, p), p); GEN M7 = FpX_mul(FpX_sub(A12,A22, p), FpX_add(B21,B22, p), p); GEN T1 = FpX_add(M1,M4, p), T2 = FpX_sub(M7,M5, p); GEN T3 = FpX_sub(M1,M2, p), T4 = FpX_add(M3,M6, p); retmkmat22(FpX_add(T1,T2, p), FpX_add(M3,M5, p), FpX_add(M2,M4, p), FpX_add(T3,T4, p)); } /* Return [0,1;1,-q]*M */ static GEN FpX_FpXM_qmul(GEN q, GEN M, GEN p) { GEN u = FpX_mul(gcoeff(M,2,1), q, p); GEN v = FpX_mul(gcoeff(M,2,2), q, p); retmkmat22(gcoeff(M,2,1), gcoeff(M,2,2), FpX_sub(gcoeff(M,1,1), u, p), FpX_sub(gcoeff(M,1,2), v, p)); } static GEN matid2_FpXM(long v) { retmkmat22(pol_1(v), pol_0(v), pol_0(v), pol_1(v)); } static GEN matJ2_FpXM(long v) { retmkmat22(pol_0(v), pol_1(v), pol_1(v), pol_0(v)); } INLINE GEN FpX_shift(GEN a, long n) { return RgX_shift_shallow(a, n); } INLINE GEN FpXn_red(GEN a, long n) { return RgXn_red_shallow(a, n); } /* Fast resultant formula from William Hart in Flint */ struct FpX_res { GEN res, lc; long deg0, deg1, off; }; INLINE void FpX_halfres_update(long da, long db, long dr, GEN p, struct FpX_res *res) { if (dr >= 0) { if (!equali1(res->lc)) { res->lc = Fp_powu(res->lc, da - dr, p); res->res = Fp_mul(res->res, res->lc, p); } if (both_odd(da + res->off, db + res->off)) res->res = Fp_neg(res->res, p); } else { if (db == 0) { if (!equali1(res->lc)) { res->lc = Fp_powu(res->lc, da, p); res->res = Fp_mul(res->res, res->lc, p); } } else res->res = gen_0; } } static GEN FpX_halfres_basecase(GEN a, GEN b, GEN p, GEN *pa, GEN *pb, struct FpX_res *res) { pari_sp av=avma; GEN u,u1,v,v1, M; long vx = varn(a), n = lgpol(a)>>1; u1 = v = pol_0(vx); u = v1 = pol_1(vx); while (lgpol(b)>n) { GEN r, q; q = FpX_divrem(a,b,p, &r); if (res) { long da = degpol(a), db=degpol(b), dr = degpol(r); res->lc = leading_coeff(b); if (dr >= n) FpX_halfres_update(da,db,dr,p,res); else { res->deg0 = da; res->deg1 = db; } } 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 (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"FpX_halfgcd (d = %ld)",degpol(b)); if (res) gerepileall(av, 8, &a,&b,&u1,&v1,&u,&v,&res->res,&res->lc); else gerepileall(av, 6, &a,&b,&u1,&v1,&u,&v); } } M = mkmat22(u,v,u1,v1); *pa = a; *pb = b; return res ? gc_all(av, 5, &M, pa, pb, &res->res, &res->lc) : gc_all(av, 3, &M, pa, pb); } static GEN FpX_halfres_i(GEN x, GEN y, GEN p, GEN *a, GEN *b, struct FpX_res *res); static GEN FpX_halfres_split(GEN x, GEN y, GEN p, GEN *a, GEN *b, struct FpX_res *res) { pari_sp av = avma; GEN R, S, T, V1, V2; GEN x1, y1, r, q; long l = lgpol(x), n = l>>1, k; if (lgpol(y) <= n) { *a = RgX_copy(x); *b = RgX_copy(y); return matid2_FpXM(varn(x)); } if (res) { res->lc = leading_coeff(y); res->deg0 -= n; res->deg1 -= n; res->off += n; } R = FpX_halfres_i(FpX_shift(x,-n), FpX_shift(y,-n), p, a, b, res); if (res) { res->off -= n; res->deg0 += n; res->deg1 += n; } V1 = FpXM_FpX_mul2(R, FpXn_red(x,n), FpXn_red(y,n), p); x1 = FpX_add(FpX_shift(*a,n), gel(V1,1), p); y1 = FpX_add(FpX_shift(*b,n), gel(V1,2), p); if (lgpol(y1) <= n) { *a = x1; *b = y1; return res ? gc_all(av, 5, &R, a, b, &res->res, &res->lc) : gc_all(av, 3, &R, a, b); } k = 2*n-degpol(y1); q = FpX_divrem(x1, y1, p, &r); if (res) { long dx1 = degpol(x1), dy1 = degpol(y1), dr = degpol(r); if (dy1 < degpol(y)) FpX_halfres_update(res->deg0, res->deg1, dy1, p,res); res->lc = gel(y1, dy1+2); res->deg0 = dx1; res->deg1 = dy1; if (dr >= n) { FpX_halfres_update(dx1, dy1, dr, p,res); res->deg0 = dy1; res->deg1 = dr; } res->deg0 -= k; res->deg1 -= k; res->off += k; } S = FpX_halfres_i(FpX_shift(y1,-k), FpX_shift(r,-k), p, a, b, res); if (res) { res->deg0 += k; res->deg1 += k; res->off -= k; } T = FpXM_mul2(S, FpX_FpXM_qmul(q, R, p), p); V2 = FpXM_FpX_mul2(S, FpXn_red(y1,k), FpXn_red(r,k), p); *a = FpX_add(FpX_shift(*a,k), gel(V2,1), p); *b = FpX_add(FpX_shift(*b,k), gel(V2,2), p); return res ? gc_all(av, 5, &T, a, b, &res->res, &res->lc) : gc_all(av, 3, &T, a, b); } static GEN FpX_halfres_i(GEN x, GEN y, GEN p, GEN *a, GEN *b, struct FpX_res *res) { if (lgpol(x) < FpX_HALFGCD_LIMIT) return FpX_halfres_basecase(x, y, p, a, b, res); return FpX_halfres_split(x, y, p, a, b, res); } static GEN FpX_halfgcd_all_i(GEN x, GEN y, GEN p, GEN *pa, GEN *pb) { GEN a, b; GEN R = FpX_halfres_i(x, y, p, &a, &b, NULL); if (pa) *pa = a; if (pb) *pb = b; return R; } /* Return M in GL_2(Fp[X]) such that: if [a',b']~=M*[a,b]~ then degpol(a')>= (lgpol(a)>>1) >degpol(b') */ GEN FpX_halfgcd_all(GEN x, GEN y, GEN p, GEN *a, GEN *b) { pari_sp av = avma; GEN R, q, r; if (lgefint(p)==3) { ulong pp = to_Flx(&x, &y, p); R = Flx_halfgcd_all(x, y, pp, a, b); R = FlxM_to_ZXM(R); if (a) *a = Flx_to_ZX(*a); if (b) *b = Flx_to_ZX(*b); return !a && b ? gc_all(av, 2, &R, b): gc_all(av, 1+!!a+!!b, &R, a, b); } if (!signe(x)) { if (a) *a = RgX_copy(y); if (b) *b = RgX_copy(x); return matJ2_FpXM(varn(x)); } 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; } return gc_const(av, a); } GEN FpX_gcd(GEN x, GEN y, GEN p) { pari_sp av = avma; if (lgefint(p)==3) { ulong pp; (void)new_chunk((lg(x) + lg(y)) << 2); /* scratch space */ pp = to_Flx(&x, &y, p); x = Flx_gcd(x, y, pp); set_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 (lgpol(y) >= FpX_GCD_LIMIT) { if (lgpol(y)<=(lgpol(x)>>1)) { GEN r = FpX_rem(x, y, p); x = y; y = r; } (void) FpX_halfgcd_all(x, y, p, &x, &y); if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"FpX_gcd (y = %ld)",degpol(y)); gerepileall(av,2,&x,&y); } } return gerepileupto(av, FpX_gcd_basecase(x,y,p)); } /* Return NULL if gcd can be computed else return a factor of p */ GEN FpX_gcd_check(GEN x, GEN y, GEN p) { pari_sp av = avma; GEN a,b,c; a = FpX_red(x, p); b = FpX_red(y, p); while (signe(b)) { GEN g; if (!invmod(leading_coeff(b), p, &g)) return gerepileuptoint(av,g); b = FpX_Fp_mul_to_monic(b, g, p); c = FpX_rem(a, b, p); a = b; b = c; if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"FpX_gcd_check (d = %ld)",degpol(b)); gerepileall(av,2,&a,&b); } } return gc_NULL(av); } static GEN FpX_extgcd_basecase(GEN a, GEN b, GEN p, GEN *ptu, GEN *ptv) { pari_sp av=avma; GEN v,v1, A = a, B = b; long vx = varn(a); if (!lgpol(b)) { if (ptu) *ptu = pol_1(vx); *ptv = pol_0(vx); return RgX_copy(a); } v = pol_0(vx); v1 = pol_1(vx); while (1) { GEN r, q = FpX_divrem(a,b,p, &r); a = b; b = r; swap(v,v1); if (!lgpol(b)) break; v1 = FpX_sub(v1, FpX_mul(v, q, p), p); if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"FpX_extgcd (d = %ld)",degpol(a)); gerepileall(av,4,&a,&b,&v,&v1); } } if (ptu) *ptu = FpX_div(FpX_sub(a,FpX_mul(B,v,p),p),A,p); *ptv = v; return a; } static GEN FpX_extgcd_halfgcd(GEN x, GEN y, GEN p, GEN *ptu, GEN *ptv) { GEN u, v; GEN V = cgetg(expu(lgpol(y))+2,t_VEC); long i, n = 0, vs = varn(x); while (lgpol(y) >= FpX_EXTGCD_LIMIT) { if (lgpol(y)<=(lgpol(x)>>1)) { GEN r, q = FpX_divrem(x, y, p, &r); x = y; y = r; gel(V,++n) = mkmat22(pol_0(vs),pol_1(vs),pol_1(vs),FpX_neg(q,p)); } else gel(V,++n) = FpX_halfgcd_all(x, y, p, &x, &y); } y = FpX_extgcd_basecase(x, y, p, &u, &v); for (i = n; i>1; i--) { GEN R = gel(V,i); GEN u1 = FpX_addmulmul(u, v, gcoeff(R,1,1), gcoeff(R,2,1), p); GEN v1 = FpX_addmulmul(u, v, gcoeff(R,1,2), gcoeff(R,2,2), p); u = u1; v = v1; } { GEN R = gel(V,1); 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) { pari_sp av = avma; GEN d; if (lgefint(p)==3) { ulong pp = to_Flx(&x, &y, p); d = Flx_extgcd(x,y, pp, ptu,ptv); d = Flx_to_ZX(d); if (ptu) *ptu = Flx_to_ZX(*ptu); *ptv = Flx_to_ZX(*ptv); } else { x = FpX_red(x, p); y = FpX_red(y, p); if (lgpol(y) >= FpX_EXTGCD_LIMIT) d = FpX_extgcd_halfgcd(x, y, p, ptu, ptv); else d = FpX_extgcd_basecase(x, y, p, ptu, ptv); } return gc_all(av, ptu?3:2, &d, ptv, ptu); } static GEN FpX_halfres(GEN x, GEN y, GEN p, GEN *a, GEN *b, GEN *r) { struct FpX_res res; GEN V; long dB; res.res = *r; res.lc = leading_coeff(y); res.deg0 = degpol(x); res.deg1 = degpol(y); res.off = 0; V = FpX_halfres_i(x, y, p, a, b, &res); dB = degpol(*b); if (dB < degpol(y)) FpX_halfres_update(res.deg0, res.deg1, dB, p, &res); *r = res.res; return V; } static GEN FpX_resultant_basecase(GEN a, GEN b, GEN p) { pari_sp av = avma; long da,db,dc; GEN c, lb, res = gen_1; if (!signe(a) || !signe(b)) return pol_0(varn(a)); 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 gc_const(av, gen_1); /* = res * a[2] ^ db, since 0 <= db <= da = 0 */ while (db) { lb = gel(b,db+2); c = FpX_rem(a,b, p); a = b; b = c; dc = degpol(c); if (dc < 0) return gc_const(av, gen_0); if (both_odd(da,db)) res = subii(p, res); if (!equali1(lb)) res = Fp_mul(res, Fp_powu(lb, da - dc, p), p); if (gc_needed(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) */ } return gerepileuptoint(av, Fp_mul(res, Fp_powu(gel(b,2), da, p), p)); } GEN FpX_resultant(GEN x, GEN y, GEN p) { pari_sp av = avma; long dx, dy; GEN res = gen_1; if (!signe(x) || !signe(y)) return gen_0; if (lgefint(p) == 3) { pari_sp av = avma; ulong pp = to_Flx(&x, &y, p); ulong res = Flx_resultant(x, y, pp); return gc_utoi(av, res); } dx = degpol(x); dy = degpol(y); if (dx < dy) { swap(x,y); if (both_odd(dx, dy)) res = Fp_neg(res, p); } while (lgpol(y) >= FpX_GCD_LIMIT) { if (lgpol(y)<=(lgpol(x)>>1)) { GEN r = FpX_rem(x, y, p); long dx = degpol(x), dy = degpol(y), dr = degpol(r); GEN ly = gel(y,dy+2); if (!equali1(ly)) res = Fp_mul(res, Fp_powu(ly, dx - dr, p), p); if (both_odd(dx, dy)) res = Fp_neg(res, p); x = y; y = r; } (void) FpX_halfres(x, y, p, &x, &y, &res); if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"FpX_res (y = %ld)",degpol(y)); gerepileall(av,3,&x,&y,&res); } } return gerepileuptoint(av, Fp_mul(res, FpX_resultant_basecase(x, y, p), p)); } /* If resultant is 0, *ptU and *ptV are not set */ static GEN FpX_extresultant_basecase(GEN a, GEN b, GEN p, GEN *ptU, GEN *ptV) { pari_sp av = avma; GEN z,q,u,v, x = a, y = b; GEN lb, res = gen_1; long dx, dy, dz; long vs = varn(a); u = pol_0(vs); v = pol_1(vs); /* v = 1 */ dx = degpol(x); dy = degpol(y); while (dy) { /* b u = x (a), b v = y (a) */ lb = gel(y,dy+2); q = FpX_divrem(x,y, p, &z); x = y; y = z; /* (x,y) = (y, x - q y) */ dz = degpol(z); if (dz < 0) return gc_const(av,gen_0); z = FpX_sub(u, FpX_mul(q,v, p), p); u = v; v = z; /* (u,v) = (v, u - q v) */ if (both_odd(dx,dy)) res = Fp_neg(res, p); if (!equali1(lb)) res = Fp_mul(res, Fp_powu(lb, dx-dz, p), p); dx = dy; /* = degpol(x) */ dy = dz; /* = degpol(y) */ } res = Fp_mul(res, Fp_powu(gel(y,2), dx, p), p); lb = Fp_mul(res, Fp_inv(gel(y,2),p), p); v = FpX_Fp_mul(v, lb, p); u = Fp_FpX_sub(res, FpX_mul(b,v,p), p); u = FpX_div(u,a,p); /* = (res - b v) / a */ *ptU = u; *ptV = v; return res; } GEN FpX_extresultant(GEN x, GEN y, GEN p, GEN *ptU, GEN *ptV) { pari_sp av=avma; GEN u, v, R; GEN res = gen_1, res1; long dx = degpol(x), dy = degpol(y); if (lgefint(p) == 3) { pari_sp av = avma; ulong pp = to_Flx(&x, &y, p); ulong resp = Flx_extresultant(x, y, pp, &u, &v); if (!resp) return gc_const(av, gen_0); res = utoi(resp); *ptU = Flx_to_ZX(u); *ptV = Flx_to_ZX(v); return gc_all(av, 3, &res, ptU, ptV); } if (dy > dx) { swap(x,y); lswap(dx,dy); if (both_odd(dx,dy)) res = Fp_neg(res,p); R = matJ2_FpXM(x[1]); } else R = matid2_FpXM(x[1]); if (dy < 0) return gen_0; while (lgpol(y) >= FpX_EXTGCD_LIMIT) { GEN M; if (lgpol(y)<=(lgpol(x)>>1)) { GEN r, q = FpX_divrem(x, y, p, &r); long dx = degpol(x), dy = degpol(y), dr = degpol(r); GEN ly = gel(y,dy+2); if (!equali1(ly)) res = Fp_mul(res, Fp_powu(ly, dx - dr, p), p); if (both_odd(dx, dy)) res = Fp_neg(res, p); x = y; y = r; R = FpX_FpXM_qmul(q, R, p); } M = FpX_halfres(x, y, p, &x, &y, &res); if (!signe(res)) return gc_const(av, gen_0); R = FpXM_mul2(M, R, p); gerepileall(av,4,&x,&y,&R,&res); } res1 = FpX_extresultant_basecase(x,y,p,&u,&v); if (!signe(res1)) return gc_const(av, gen_0); *ptU = FpX_Fp_mul(FpX_addmulmul(u, v, gcoeff(R,1,1), gcoeff(R,2,1), p), res, p); *ptV = FpX_Fp_mul(FpX_addmulmul(u, v, gcoeff(R,1,2), gcoeff(R,2,2), p), res, p); res = Fp_mul(res1,res,p); return gc_all(av, 3, &res, ptU, ptV); } GEN FpX_rescale(GEN P, GEN h, GEN p) { long i, l = lg(P); GEN Q = cgetg(l,t_POL), hi = h; gel(Q,l-1) = gel(P,l-1); for (i=l-2; i>=2; i--) { 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); } /* Compute intformal(x^n*S)/x^(n+1) */ static GEN FpX_integXn(GEN x, long n, GEN p) { long i, lx = lg(x); GEN y; if (lx == 2) return ZX_copy(x); y = cgetg(lx, t_POL); y[1] = x[1]; for (i=2; i=2; i--) { gel(y,i+2) = Fp_mul(gel(x,i+2), t, p); t = Fp_mulu(t, i, p); } gel(y,3) = gel(x,3); gel(y,2) = gel(x,2); return gerepilecopy(av, y); } GEN FpX_Laplace(GEN x, GEN p) { pari_sp av = avma; long i, d = degpol(x); GEN t = gen_1; GEN y; if (d <= 1) return gcopy(x); y = cgetg(d+3, t_POL); y[1] = x[1]; gel(y,2) = gel(x,2); gel(y,3) = gel(x,3); for (i=2; i<=d; i++) { t = Fp_mulu(t, i, p); gel(y,i+2) = Fp_mul(gel(x,i+2), t, p); } return gerepilecopy(av, y); } int FpX_is_squarefree(GEN f, GEN p) { pari_sp av = avma; GEN z = FpX_gcd(f,FpX_deriv(f,p),p); set_avma(av); return degpol(z)==0; } GEN random_FpX(long d1, long v, GEN p) { long i, d = d1+2; GEN y = cgetg(d,t_POL); y[1] = evalsigne(1) | evalvarn(v); for (i=2; i=2; i=j-1) { for (j=i; !signe(gel(x,j)); j--) if (j==2) { if (i!=j) y = Fp_powu(y,i-j+1,p); p1=mulii(p1,y); goto fppoleval;/*sorry break(2) no implemented*/ } r = (i==j)? y: Fp_powu(y,i-j+1,p); p1 = Fp_addmul(gel(x,j), p1, r, p); if ((i & 7) == 0) { affii(p1, res); p1 = res; set_avma(av); } } fppoleval: modiiz(p1,p,res); return gc_const(av, 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); } /* disc P = (-1)^(n(n-1)/2) lc(P)^(n - deg P' - 2) Res(P,P'), n = deg P */ GEN FpX_disc(GEN P, GEN p) { pari_sp av = avma; GEN L, dP = FpX_deriv(P,p), D = FpX_resultant(P, dP, p); long dd; if (!signe(D)) return gen_0; dd = degpol(P) - 2 - degpol(dP); /* >= -1; > -1 iff p | deg(P) */ L = leading_coeff(P); if (dd && !equali1(L)) D = (dd == -1)? Fp_div(D,L,p): Fp_mul(D, Fp_powu(L, dd, p), p); if (degpol(P) & 2) D = Fp_neg(D ,p); return gerepileuptoint(av, D); } GEN FpV_roots_to_pol(GEN V, GEN p, long v) { pari_sp ltop=avma; long i; GEN g=cgetg(lg(V),t_VEC); for(i=1;i 1; i--) { gel(y,i) = Fp_mul(u, gel(y,i-1), p); u = Fp_mul(u, gel(x,i), p); /* u = 1 / (x[1] ... x[i-1]) */ } gel(y,1) = u; return y; } GEN FqV_inv(GEN x, GEN T, GEN p) { long i, lx = lg(x); GEN u, y = cgetg(lx, t_VEC); gel(y,1) = gel(x,1); for (i=2; i 1; i--) { gel(y,i) = Fq_mul(u, gel(y,i-1), T,p); u = Fq_mul(u, gel(x,i), T,p); /* u = 1 / (x[1] ... x[i-1]) */ } gel(y,1) = u; return y; } /***********************************************************************/ /** **/ /** Barrett reduction **/ /** **/ /***********************************************************************/ static GEN FpX_invBarrett_basecase(GEN T, GEN p) { long i, l=lg(T)-1, lr = l-1, k; GEN r=cgetg(lr, t_POL); r[1]=T[1]; gel(r,2) = gen_1; for (i=3; i=0; i--) if (signe(gel(x,i))) break; return i+1; } INLINE GEN FpX_recipspec(GEN x, long l, long n) { return RgX_recipspec_shallow(x, l, n); } static GEN FpX_invBarrett_Newton(GEN T, GEN p) { pari_sp av = avma; long nold, lx, lz, lq, l = degpol(T), i, lQ; GEN q, y, z, x = cgetg(l+2, t_POL) + 2; ulong mask = quadratic_prec_mask(l-2); /* assume l > 2 */ for (i=0;i1) gel(q,1) = Fp_red(gel(q,1), p); if (lQ>1 && signe(gel(q,1))) { GEN u = gel(q, 1); if (!equali1(gel(x,0))) u = Fp_mul(u, Fp_sqr(gel(x,0), p), p); gel(x,1) = Fp_neg(u, p); lx = 2; } else lx = 1; nold = 1; for (; mask > 1; ) { /* set x -= x(x*q - 1) + O(t^(nnew + 1)), knowing x*q = 1 + O(t^(nold+1)) */ long i, lnew, nnew = nold << 1; if (mask & 1) nnew--; mask >>= 1; lnew = nnew + 1; lq = ZX_lgrenormalizespec(q, minss(lQ,lnew)); z = FpX_mulspec(x, q, p, lx, lq); /* FIXME: high product */ lz = lgpol(z); if (lz > lnew) lz = lnew; z += 2; /* subtract 1 [=>first nold words are 0]: renormalize so that z(0) != 0 */ for (i = nold; i < lz; i++) if (signe(gel(z,i))) break; nold = nnew; if (i >= lz) continue; /* z-1 = 0(t^(nnew + 1)) */ /* z + i represents (x*q - 1) / t^i */ lz = ZX_lgrenormalizespec (z+i, lz-i); z = FpX_mulspec(x, z+i, p, lx, lz); /* FIXME: low product */ lz = lgpol(z); z += 2; if (lz > lnew-i) lz = ZX_lgrenormalizespec(z, lnew-i); lx = lz+ i; y = x + i; /* x -= z * t^i, in place */ for (i = 0; i < lz; i++) gel(y,i) = Fp_neg(gel(z,i), p); } x -= 2; setlg(x, lx + 2); x[1] = T[1]; return gerepilecopy(av, x); } /* 1/polrecip(T)+O(x^(deg(T)-1)) */ GEN FpX_invBarrett(GEN T, GEN p) { pari_sp ltop = avma; long l = lg(T); GEN r; if (l<5) return pol_0(varn(T)); if (l<=FpX_INVBARRETT_LIMIT) { GEN c = gel(T,l-1), ci=gen_1; if (!equali1(c)) { ci = Fp_inv(c, p); T = FpX_Fp_mul(T, ci, p); r = FpX_invBarrett_basecase(T, p); r = FpX_Fp_mul(r, ci, p); } else r = FpX_invBarrett_basecase(T, p); } else r = FpX_invBarrett_Newton(T, p); return gerepileupto(ltop, r); } GEN FpX_get_red(GEN T, GEN p) { if (typ(T)==t_POL && lg(T)>FpX_BARRETT_LIMIT) retmkvec2(FpX_invBarrett(T,p),T); return T; } /* Compute x mod T where 2 <= degpol(T) <= l+1 <= 2*(degpol(T)-1) * and mg is the Barrett inverse of T. */ static GEN FpX_divrem_Barrettspec(GEN x, long l, GEN mg, GEN T, GEN p, GEN *pr) { GEN q, r; long lt = degpol(T); /*We discard the leading term*/ long ld, lm, lT, lmg; ld = l-lt; lm = minss(ld, lgpol(mg)); lT = ZX_lgrenormalizespec(T+2,lt); lmg = ZX_lgrenormalizespec(mg+2,lm); q = FpX_recipspec(x+lt,ld,ld); /* q = rec(x) lq<=ld*/ q = FpX_mulspec(q+2,mg+2,p,lgpol(q),lmg); /* q = rec(x) * mg lq<=ld+lm*/ q = FpX_recipspec(q+2,minss(ld,lgpol(q)),ld);/* q = rec (rec(x) * mg) lq<=ld*/ if (!pr) return q; r = FpX_mulspec(q+2,T+2,p,lgpol(q),lT); /* r = q*pol lr<=ld+lt*/ r = FpX_subspec(x,r+2,p,lt,minss(lt,lgpol(r)));/* r = x - r lr<=lt */ if (pr == ONLY_REM) return r; *pr = r; return q; } static GEN FpX_divrem_Barrett(GEN x, GEN mg, GEN T, GEN p, GEN *pr) { GEN q = NULL, r = FpX_red(x, p); long l = lgpol(r), lt = degpol(T), lm = 2*lt-1, v = varn(T); long i; if (l <= lt) { if (pr == ONLY_REM) return r; if (pr == ONLY_DIVIDES) return signe(r)? NULL: pol_0(v); if (pr) *pr = r; return pol_0(v); } if (lt <= 1) return FpX_divrem_basecase(r,T,p,pr); if (pr != ONLY_REM && l>lm) { q = cgetg(l-lt+2, t_POL); q[1] = T[1]; for (i=0;ilm) { GEN zr, zq = FpX_divrem_Barrettspec(r+2+l-lm,lm,mg,T,p,&zr); long lz = lgpol(zr); if (pr != ONLY_REM) { long lq = lgpol(zq); for(i=0; i lt) r = FpX_divrem_Barrettspec(r+2, l, mg, T, p, ONLY_REM); else r = FpX_renormalize(r, l+2); setvarn(r, v); return r; } if (l > lt) { GEN zq = FpX_divrem_Barrettspec(r+2,l,mg,T,p, pr? &r: NULL); if (!q) q = zq; else { long lq = lgpol(zq); for(i=0; i>1)+1, t_VEC); for (j=1, k=1; k=1; i--) { GEN u = gel(T, i); GEN v = gel(Tp, i+1); long n = lg(u)-1; t = cgetg(n+1, t_VEC); for (j=1, k=1; kT, D->p); } static GEN _FpXQ_mul(void *data, GEN x, GEN y) { struct _FpXQ *D = (struct _FpXQ*)data; return FpXQ_mul(x,y, D->T, D->p); } static GEN _FpXQ_zero(void *data) { struct _FpXQ *D = (struct _FpXQ*)data; return pol_0(get_FpX_var(D->T)); } static GEN _FpXQ_one(void *data) { struct _FpXQ *D = (struct _FpXQ*)data; return pol_1(get_FpX_var(D->T)); } static GEN _FpXQ_red(void *data, GEN x) { struct _FpXQ *D = (struct _FpXQ*)data; return FpX_red(x,D->p); } static struct bb_algebra FpXQ_algebra = { _FpXQ_red, _FpXQ_add, _FpXQ_sub, _FpXQ_mul, _FpXQ_sqr, _FpXQ_one, _FpXQ_zero }; const struct bb_algebra * get_FpXQ_algebra(void **E, GEN T, GEN p) { GEN z = new_chunk(sizeof(struct _FpXQ)); struct _FpXQ *e = (struct _FpXQ *) z; e->T = FpX_get_red(T, p); e->p = p; *E = (void*)e; return &FpXQ_algebra; } static GEN _FpX_red(void *E, GEN x) { struct _FpX *D = (struct _FpX*)E; return FpX_red(x,D->p); } static GEN _FpX_zero(void *E) { struct _FpX *D = (struct _FpX *)E; return pol_0(D->v); } static struct bb_algebra FpX_algebra = { _FpX_red, _FpXQ_add, _FpXQ_sub, _FpX_mul, _FpX_sqr, _FpX_one, _FpX_zero }; const struct bb_algebra * get_FpX_algebra(void **E, GEN p, long v) { GEN z = new_chunk(sizeof(struct _FpX)); struct _FpX *e = (struct _FpX *) z; e->p = p; e->v = v; *E = (void*)e; return &FpX_algebra; } /* x,pol in Z[X], p in Z, n in Z, compute lift(x^n mod (p, pol)) */ GEN FpXQ_pow(GEN x, GEN n, GEN T, GEN p) { struct _FpXQ D; pari_sp av; long s = signe(n); GEN y; if (!s) return pol_1(varn(x)); if (is_pm1(n)) /* +/- 1 */ return (s < 0)? FpXQ_inv(x,T,p): FpXQ_red(x,T,p); av = avma; if (!is_bigint(p)) { ulong pp = to_Flxq(&x, &T, p); y = Flxq_pow(x, n, T, pp); return Flx_to_ZX_inplace(gerepileuptoleaf(av, y)); } if (s < 0) x = FpXQ_inv(x,T,p); D.p = p; D.T = FpX_get_red(T,p); y = gen_pow_i(x, n, (void*)&D, &_FpXQ_sqr, &_FpXQ_mul); return gerepilecopy(av, y); } GEN /*Assume n is very small*/ FpXQ_powu(GEN x, ulong n, GEN T, GEN p) { struct _FpXQ D; pari_sp av; GEN y; if (!n) return pol_1(varn(x)); if (n==1) return FpXQ_red(x,T,p); av = avma; if (!is_bigint(p)) { ulong pp = to_Flxq(&x, &T, p); y = Flxq_powu(x, n, T, pp); return Flx_to_ZX_inplace(gerepileuptoleaf(av, y)); } D.T = FpX_get_red(T, p); D.p = p; y = gen_powu_i(x, n, (void*)&D, &_FpXQ_sqr, &_FpXQ_mul); return gerepilecopy(av, y); } /* generates the list of powers of x of degree 0,1,2,...,l*/ GEN FpXQ_powers(GEN x, long l, GEN T, GEN p) { struct _FpXQ D; int use_sqr; if (l>2 && lgefint(p) == 3) { pari_sp av = avma; ulong pp = to_Flxq(&x, &T, p); GEN z = FlxV_to_ZXV(Flxq_powers(x, l, T, pp)); return gerepileupto(av, z); } use_sqr = 2*degpol(x)>=get_FpX_degree(T); D.T = FpX_get_red(T,p); D.p = p; return gen_powers(x, l, use_sqr, (void*)&D, &_FpXQ_sqr, &_FpXQ_mul,&_FpXQ_one); } GEN FpXQ_matrix_pow(GEN y, long n, long m, GEN P, GEN l) { return RgXV_to_RgM(FpXQ_powers(y,m-1,P,l),n); } GEN FpX_Frobenius(GEN T, GEN p) { return FpXQ_pow(pol_x(get_FpX_var(T)), p, T, p); } GEN FpX_matFrobenius(GEN T, GEN p) { long n = get_FpX_degree(T); return FpXQ_matrix_pow(FpX_Frobenius(T, p), n, n, T, p); } GEN FpX_FpXQV_eval(GEN Q, GEN x, GEN T, GEN p) { struct _FpXQ D; D.T = FpX_get_red(T,p); D.p = p; return gen_bkeval_powers(Q,degpol(Q),x,(void*)&D,&FpXQ_algebra,_FpXQ_cmul); } GEN FpX_FpXQ_eval(GEN Q, GEN x, GEN T, GEN p) { struct _FpXQ D; int use_sqr; if (lgefint(p) == 3) { pari_sp av = avma; ulong pp = to_Flxq(&x, &T, p); GEN z = Flx_Flxq_eval(ZX_to_Flx(Q, pp), x, T, pp); return Flx_to_ZX_inplace(gerepileuptoleaf(av, z)); } use_sqr = 2*degpol(x) >= get_FpX_degree(T); D.T = FpX_get_red(T,p); D.p = p; return gen_bkeval(Q,degpol(Q),x,use_sqr,(void*)&D,&FpXQ_algebra,_FpXQ_cmul); } GEN FpXC_FpXQV_eval(GEN x, GEN v, GEN T, GEN p) { pari_APPLY_type(t_COL, FpX_FpXQV_eval(gel(x,i), v, T, p)) } GEN FpXM_FpXQV_eval(GEN x, GEN v, GEN T, GEN p) { pari_APPLY_same(FpXC_FpXQV_eval(gel(x,i), v, T, p)) } GEN FpXC_FpXQ_eval(GEN x, GEN F, GEN T, GEN p) { long d = brent_kung_optpow(RgXV_maxdegree(x), lg(x)-1, 1); GEN Fp = FpXQ_powers(F, d, T, p); return FpXC_FpXQV_eval(x, Fp, T, p); } GEN FpXQ_autpowers(GEN aut, long f, GEN T, GEN p) { pari_sp av = avma; long n = get_FpX_degree(T); long i, nautpow = brent_kung_optpow(n-1,f-2,1); long v = get_FpX_var(T); GEN autpow, V; T = FpX_get_red(T, p); autpow = FpXQ_powers(aut, nautpow,T,p); V = cgetg(f + 2, t_VEC); gel(V,1) = pol_x(v); if (f==0) return gerepileupto(av, V); gel(V,2) = gcopy(aut); for (i = 3; i <= f+1; i++) gel(V,i) = FpX_FpXQV_eval(gel(V,i-1),autpow,T,p); return gerepileupto(av, V); } static GEN FpXQ_autpow_sqr(void *E, GEN x) { struct _FpXQ *D = (struct _FpXQ*)E; return FpX_FpXQ_eval(x, x, D->T, D->p); } static GEN FpXQ_autpow_msqr(void *E, GEN x) { struct _FpXQ *D = (struct _FpXQ*)E; return FpX_FpXQV_eval(FpXQ_autpow_sqr(E, x), D->aut, D->T, D->p); } GEN FpXQ_autpow(GEN x, ulong n, GEN T, GEN p) { pari_sp av = avma; struct _FpXQ D; long d; if (n==0) return FpX_rem(pol_x(varn(x)), T, p); if (n==1) return FpX_rem(x, T, p); D.T = FpX_get_red(T, p); D.p = p; d = brent_kung_optpow(degpol(T), hammingl(n)-1, 1); D.aut = FpXQ_powers(x, d, T, p); x = gen_powu_fold(x,n,(void*)&D,FpXQ_autpow_sqr,FpXQ_autpow_msqr); return gerepilecopy(av, x); } static GEN FpXQ_auttrace_mul(void *E, GEN x, GEN y) { struct _FpXQ *D = (struct _FpXQ*)E; GEN T = D->T, p = D->p; GEN phi1 = gel(x,1), a1 = gel(x,2); GEN phi2 = gel(y,1), a2 = gel(y,2); ulong d = brent_kung_optpow(maxss(degpol(phi2),degpol(a2)),2,1); GEN V1 = FpXQ_powers(phi1, d, T, p); GEN phi3 = FpX_FpXQV_eval(phi2, V1, T, p); GEN aphi = FpX_FpXQV_eval(a2, V1, T, p); GEN a3 = FpX_add(a1, aphi, p); return mkvec2(phi3, a3); } static GEN FpXQ_auttrace_sqr(void *E, GEN x) { return FpXQ_auttrace_mul(E, x, x); } GEN FpXQ_auttrace(GEN x, ulong n, GEN T, GEN p) { pari_sp av = avma; struct _FpXQ D; D.T = FpX_get_red(T, p); D.p = p; x = gen_powu_i(x,n,(void*)&D,FpXQ_auttrace_sqr,FpXQ_auttrace_mul); return gerepilecopy(av, x); } static GEN FpXQ_autsum_mul(void *E, GEN x, GEN y) { struct _FpXQ *D = (struct _FpXQ*)E; GEN T = D->T, p = D->p; GEN phi1 = gel(x,1), a1 = gel(x,2); GEN phi2 = gel(y,1), a2 = gel(y,2); ulong d = brent_kung_optpow(maxss(degpol(phi2),degpol(a2)),2,1); GEN V1 = FpXQ_powers(phi1, d, T, p); GEN phi3 = FpX_FpXQV_eval(phi2, V1, T, p); GEN aphi = FpX_FpXQV_eval(a2, V1, T, p); GEN a3 = FpXQ_mul(a1, aphi, T, p); return mkvec2(phi3, a3); } static GEN FpXQ_autsum_sqr(void *E, GEN x) { return FpXQ_autsum_mul(E, x, x); } GEN FpXQ_autsum(GEN x, ulong n, GEN T, GEN p) { pari_sp av = avma; struct _FpXQ D; D.T = FpX_get_red(T, p); D.p = p; x = gen_powu_i(x,n,(void*)&D,FpXQ_autsum_sqr,FpXQ_autsum_mul); return gerepilecopy(av, x); } static GEN FpXQM_autsum_mul(void *E, GEN x, GEN y) { struct _FpXQ *D = (struct _FpXQ*)E; GEN T = D->T, p = D->p; GEN phi1 = gel(x,1), a1 = gel(x,2); GEN phi2 = gel(y,1), a2 = gel(y,2); long g = lg(a2)-1, dT = get_FpX_degree(T); ulong d = brent_kung_optpow(dT-1, g*g+1, 1); GEN V1 = FpXQ_powers(phi1, d, T, p); GEN phi3 = FpX_FpXQV_eval(phi2, V1, T, p); GEN aphi = FpXM_FpXQV_eval(a2, V1, T, p); GEN a3 = FqM_mul(a1, aphi, T, p); return mkvec2(phi3, a3); } static GEN FpXQM_autsum_sqr(void *E, GEN x) { return FpXQM_autsum_mul(E, x, x); } GEN FpXQM_autsum(GEN x, ulong n, GEN T, GEN p) { pari_sp av = avma; struct _FpXQ D; D.T = FpX_get_red(T, p); D.p = p; x = gen_powu_i(x, n, (void*)&D, FpXQM_autsum_sqr, FpXQM_autsum_mul); return gerepilecopy(av, x); } static long bounded_order(GEN p, GEN b, long k) { long i; GEN a=modii(p,b); for(i=1;i 1) z = gel(FpXQ_autsum(mkvec2(autk, z), m, T, p), 2); if (!is_pm1(u)) z = FpXQ_pow(z, u, T, p); if (signe(v)) z = FpXQ_mul(z, FpXQ_pow(x, v, T, p), T, p); } return gerepileupto(av,signe(n)>0 ? z : FpXQ_inv(z,T,p)); } /* assume T irreducible mod p */ int FpXQ_issquare(GEN x, GEN T, GEN p) { pari_sp av; if (lg(x) == 2 || absequalui(2, p)) return 1; if (lg(x) == 3) return Fq_issquare(gel(x,2), T, p); av = avma; /* Ng = g^((q-1)/(p-1)) */ return gc_bool(av, kronecker(FpXQ_norm(x,T,p), p) != -1); } int Fp_issquare(GEN x, GEN p) { return absequalui(2, p) || kronecker(x, p) != -1; } /* assume T irreducible mod p */ int Fq_issquare(GEN x, GEN T, GEN p) { if (typ(x) != t_INT) return FpXQ_issquare(x, T, p); return (T && ! odd(get_FpX_degree(T))) || Fp_issquare(x, p); } long Fq_ispower(GEN x, GEN K, GEN T, GEN p) { pari_sp av = avma; long d; GEN Q; if (equaliu(K,2)) return Fq_issquare(x, T, p); if (!T) return Fp_ispower(x, K, p); d = get_FpX_degree(T); if (typ(x) == t_INT && !umodui(d, K)) return 1; Q = subiu(powiu(p,d), 1); Q = diviiexact(Q, gcdii(Q, K)); d = gequal1(Fq_pow(x, Q, T,p)); return gc_long(av, d); } /* discrete log in FpXQ for a in Fp^*, g in FpXQ^* of order ord */ GEN Fp_FpXQ_log(GEN a, GEN g, GEN o, GEN T, GEN p) { pari_sp av = avma; GEN q,n_q,ord,ordp, op; if (equali1(a)) return gen_0; /* p > 2 */ ordp = subiu(p, 1); /* even */ ord = get_arith_Z(o); if (!ord) ord = T? subiu(powiu(p, get_FpX_degree(T)), 1): ordp; if (equalii(a, ordp)) /* -1 */ return gerepileuptoint(av, shifti(ord,-1)); ordp = gcdii(ordp,ord); op = typ(o)==t_MAT ? famat_Z_gcd(o,ordp) : ordp; q = NULL; if (T) { /* we want < g > = Fp^* */ if (!equalii(ord,ordp)) { q = diviiexact(ord,ordp); g = FpXQ_pow(g,q,T,p); } g = constant_coeff(g); } n_q = Fp_log(a,g,op,p); if (lg(n_q)==1) return gerepileuptoleaf(av, n_q); if (q) n_q = mulii(q, n_q); return gerepileuptoint(av, n_q); } static GEN _FpXQ_pow(void *data, GEN x, GEN n) { struct _FpXQ *D = (struct _FpXQ*)data; return FpXQ_pow_Frobenius(x,n, D->aut, D->T, D->p); } static GEN _FpXQ_rand(void *data) { pari_sp av=avma; struct _FpXQ *D = (struct _FpXQ*)data; GEN z; do { set_avma(av); z=random_FpX(get_FpX_degree(D->T),get_FpX_var(D->T),D->p); } while (!signe(z)); return z; } static GEN _FpXQ_easylog(void *E, GEN a, GEN g, GEN ord) { struct _FpXQ *s=(struct _FpXQ*) E; if (degpol(a)) return NULL; return Fp_FpXQ_log(constant_coeff(a),g,ord,s->T,s->p); } static const struct bb_group FpXQ_star={_FpXQ_mul,_FpXQ_pow,_FpXQ_rand,hash_GEN,ZX_equal,ZX_equal1,_FpXQ_easylog}; const struct bb_group * get_FpXQ_star(void **E, GEN T, GEN p) { struct _FpXQ *e = (struct _FpXQ *) stack_malloc(sizeof(struct _FpXQ)); e->T = T; e->p = p; e->aut = FpX_Frobenius(T, p); *E = (void*)e; return &FpXQ_star; } GEN FpXQ_order(GEN a, GEN ord, GEN T, GEN p) { if (lgefint(p)==3) { pari_sp av=avma; ulong pp = to_Flxq(&a, &T, p); GEN z = Flxq_order(a, ord, T, pp); return gerepileuptoint(av,z); } else { void *E; const struct bb_group *S = get_FpXQ_star(&E,T,p); return gen_order(a,ord,E,S); } } GEN FpXQ_log(GEN a, GEN g, GEN ord, GEN T, GEN p) { pari_sp av=avma; if (lgefint(p)==3) { if (uel(p,2) == 2) { GEN z = F2xq_log(ZX_to_F2x(a), ZX_to_F2x(g), ord, ZX_to_F2x(get_FpX_mod(T))); return gerepileuptoleaf(av, z); } else { ulong pp = to_Flxq(&a, &T, p); GEN z = Flxq_log(a, ZX_to_Flx(g, pp), ord, T, pp); return gerepileuptoleaf(av, z); } } else { void *E; const struct bb_group *S = get_FpXQ_star(&E,T,p); GEN z = gen_PH_log(a,g,ord,E,S); return gerepileuptoleaf(av, z); } } GEN Fq_log(GEN a, GEN g, GEN ord, GEN T, GEN p) { if (!T) return Fp_log(a,g,ord,p); if (typ(g) == t_INT) { if (typ(a) == t_POL) { if (degpol(a)) return cgetg(1,t_VEC); a = gel(a,2); } return Fp_log(a,g,ord,p); } return typ(a) == t_INT? Fp_FpXQ_log(a,g,ord,T,p): FpXQ_log(a,g,ord,T,p); } GEN FpXQ_sqrtn(GEN a, GEN n, GEN T, GEN p, GEN *zeta) { pari_sp av = avma; GEN z; if (!signe(a)) { long v=varn(a); if (signe(n) < 0) pari_err_INV("FpXQ_sqrtn",a); if (zeta) *zeta=pol_1(v); return pol_0(v); } if (lgefint(p)==3) { if (uel(p,2) == 2) { z = F2xq_sqrtn(ZX_to_F2x(a), n, ZX_to_F2x(get_FpX_mod(T)), zeta); if (!z) return NULL; z = F2x_to_ZX(z); if (!zeta) return gerepileuptoleaf(av, z); *zeta=F2x_to_ZX(*zeta); } else { ulong pp = to_Flxq(&a, &T, p); z = Flxq_sqrtn(a, n, T, pp, zeta); if (!z) return NULL; if (!zeta) return Flx_to_ZX_inplace(gerepileuptoleaf(av, z)); z = Flx_to_ZX(z); *zeta=Flx_to_ZX(*zeta); } } else { void *E; const struct bb_group *S = get_FpXQ_star(&E,T,p); GEN o = subiu(powiu(p,get_FpX_degree(T)),1); z = gen_Shanks_sqrtn(a,n,o,zeta,E,S); if (!z) return NULL; if (!zeta) return gerepileupto(av, z); } return gc_all(av, 2, &z,zeta); } static GEN Fp2_norm(GEN x, GEN D, GEN p) { GEN a = gel(x,1), b = gel(x,2); if (signe(b)==0) return Fp_sqr(a,p); return Fp_sub(sqri(a), mulii(D, Fp_sqr(b, p)), p); } static GEN Fp2_sqrt(GEN z, GEN D, GEN p) { GEN a = gel(z,1), b = gel(z,2), as2, u, v, s; GEN y = Fp_2gener_i(D, p); if (signe(b)==0) return kronecker(a, p)==1 ? mkvec2(Fp_sqrt_i(a, y, p), gen_0) : mkvec2(gen_0,Fp_sqrt_i(Fp_div(a, D, p), y, p)); s = Fp_sqrt_i(Fp2_norm(z, D, p), y, p); if(!s) return NULL; as2 = Fp_halve(Fp_add(a, s, p), p); if (kronecker(as2, p)==-1) as2 = Fp_sub(as2,s,p); u = Fp_sqrt_i(as2, y, p); v = Fp_div(b, Fp_double(u, p), p); return mkvec2(u,v); } GEN FpXQ_sqrt(GEN z, GEN T, GEN p) { pari_sp av = avma; long d = get_FpX_degree(T); if (lgefint(p)==3) { if (uel(p,2) == 2) { GEN r = F2xq_sqrt(ZX_to_F2x(z), ZX_to_F2x(get_FpX_mod(T))); return gerepileupto(av, F2x_to_ZX(r)); } else { ulong pp = to_Flxq(&z, &T, p); z = Flxq_sqrt(z, T, pp); if (!z) return NULL; return gerepileupto(av, Flx_to_ZX(z)); } } if (d==2) { GEN P = get_FpX_mod(T); GEN c = gel(P,2), b = gel(P,3), a = gel(P,4), b2 = Fp_halve(b, p); GEN t = Fp_div(b2, a, p); GEN D = Fp_sub(Fp_sqr(b2, p), Fp_mul(a, c, p), p); GEN x = degpol(z)<1 ? constant_coeff(z): Fp_sub(gel(z,2), Fp_mul(gel(z,3), t, p), p); GEN y = degpol(z)<1 ? gen_0: gel(z,3); GEN r = Fp2_sqrt(mkvec2(x, y), D, p), s; if (!r) return gc_NULL(av); s = deg1pol_shallow(gel(r,2),Fp_add(gel(r,1), Fp_mul(gel(r,2),t,p), p), varn(P)); return gerepilecopy(av, s); } if (lgpol(z)<=1 && odd(d)) { pari_sp av = avma; GEN s = Fp_sqrt(constant_coeff(z), p); if (!s) return gc_NULL(av); return gerepilecopy(av, scalarpol_shallow(s, get_FpX_var(T))); } return FpXQ_sqrtn(z, gen_2, T, p, NULL); } GEN FpXQ_norm(GEN x, GEN TB, GEN p) { pari_sp av = avma; GEN T = get_FpX_mod(TB); GEN y = FpX_resultant(T, x, p); GEN L = leading_coeff(T); if (gequal1(L) || signe(x)==0) return y; return gerepileupto(av, Fp_div(y, Fp_pows(L, degpol(x), p), p)); } GEN FpXQ_trace(GEN x, GEN TB, GEN p) { pari_sp av = avma; GEN T = get_FpX_mod(TB); GEN dT = FpX_deriv(T,p); long n = degpol(dT); GEN z = FpXQ_mul(x, dT, TB, p); if (degpol(z)v(tau*z) that is, v*(M_tau) */ static GEN FpXQ_transmul_init(GEN tau, GEN T, GEN p) { GEN bht; GEN h, Tp = get_FpX_red(T, &h); long n = degpol(Tp), vT = varn(Tp); GEN ft = FpX_recipspec(Tp+2, n+1, n+1); GEN bt = FpX_recipspec(tau+2, lgpol(tau), n); setvarn(ft, vT); setvarn(bt, vT); if (h) bht = FpXn_mul(bt, h, n-1, p); else { GEN bh = FpX_div(FpX_shift(tau, n-1), T, p); bht = FpX_recipspec(bh+2, lgpol(bh), n-1); setvarn(bht, vT); } return mkvec3(bt, bht, ft); } static GEN FpXQ_transmul(GEN tau, GEN a, long n, GEN p) { pari_sp ltop = avma; GEN t1, t2, t3, vec; GEN bt = gel(tau, 1), bht = gel(tau, 2), ft = gel(tau, 3); if (signe(a)==0) return pol_0(varn(a)); t2 = FpX_shift(FpX_mul(bt, a, p),1-n); if (signe(bht)==0) return gerepilecopy(ltop, t2); t1 = FpX_shift(FpX_mul(ft, a, p),-n); t3 = FpXn_mul(t1, bht, n-1, p); vec = FpX_sub(t2, FpX_shift(t3, 1), p); return gerepileupto(ltop, vec); } GEN FpXQ_minpoly(GEN x, GEN T, GEN p) { pari_sp ltop = avma; long vT, n; GEN v_x, g, tau; if (lgefint(p)==3) { ulong pp = to_Flxq(&x, &T, p); GEN g = Flxq_minpoly(x, T, pp); return gerepileupto(ltop, Flx_to_ZX(g)); } vT = get_FpX_var(T); n = get_FpX_degree(T); g = pol_1(vT); tau = pol_1(vT); T = FpX_get_red(T, p); x = FpXQ_red(x, T, p); v_x = FpXQ_powers(x, usqrt(2*n), T, p); while(signe(tau) != 0) { long i, j, m, k1; GEN M, v, tr; GEN g_prime, c; if (degpol(g) == n) { tau = pol_1(vT); g = pol_1(vT); } v = random_FpX(n, vT, p); tr = FpXQ_transmul_init(tau, T, p); v = FpXQ_transmul(tr, v, n, p); m = 2*(n-degpol(g)); k1 = usqrt(m); tr = FpXQ_transmul_init(gel(v_x,k1+1), T, p); c = cgetg(m+2,t_POL); c[1] = evalsigne(1)|evalvarn(vT); for (i=0; i , i = 0..m-1 */ M = FpX_halfgcd(pol_xn(m, vT), c, p); g_prime = gmael(M, 2, 2); if (degpol(g_prime) < 1) continue; g = FpX_mul(g, g_prime, p); tau = FpXQ_mul(tau, FpX_FpXQV_eval(g_prime, v_x, T, p), T, p); } g = FpX_normalize(g,p); return gerepilecopy(ltop,g); } GEN FpXQ_conjvec(GEN x, GEN T, GEN p) { pari_sp av=avma; long i; long n = get_FpX_degree(T), v = varn(x); GEN M = FpX_matFrobenius(T, p); GEN z = cgetg(n+1,t_COL); gel(z,1) = RgX_to_RgC(x,n); for (i=2; i<=n; i++) gel(z,i) = FpM_FpC_mul(M,gel(z,i-1),p); gel(z,1) = x; for (i=2; i<=n; i++) gel(z,i) = RgV_to_RgX(gel(z,i),v); return gerepilecopy(av,z); } /* p prime, p_1 = p-1, q = p^deg T, Lp = cofactors of some prime divisors * l_p of p-1, Lq = cofactors of some prime divisors l_q of q-1, return a * g in Fq such that * - Ng generates all l_p-Sylows of Fp^* * - g generates all l_q-Sylows of Fq^* */ static GEN gener_FpXQ_i(GEN T, GEN p, GEN p_1, GEN Lp, GEN Lq) { pari_sp av; long vT = varn(T), f = degpol(T), l = lg(Lq); GEN F = FpX_Frobenius(T, p); int p_is_2 = is_pm1(p_1); for (av = avma;; set_avma(av)) { GEN t, g = random_FpX(f, vT, p); long i; if (degpol(g) < 1) continue; if (p_is_2) t = g; else { t = FpX_resultant(T, g, p); /* Ng = g^((q-1)/(p-1)), assuming T monic */ if (kronecker(t, p) == 1) continue; if (lg(Lp) > 1 && !is_gener_Fp(t, p, p_1, Lp)) continue; t = FpXQ_pow(g, shifti(p_1,-1), T, p); } for (i = 1; i < l; i++) { GEN a = FpXQ_pow_Frobenius(t, gel(Lq,i), F, T, p); if (!degpol(a) && equalii(gel(a,2), p_1)) break; } if (i == l) return g; } } GEN gener_FpXQ(GEN T, GEN p, GEN *po) { long i, j, f = get_FpX_degree(T); GEN g, Lp, Lq, p_1, q_1, N, o; pari_sp av = avma; p_1 = subiu(p,1); if (f == 1) { GEN Lp, fa; o = p_1; fa = Z_factor(o); Lp = gel(fa,1); Lp = vecslice(Lp, 2, lg(Lp)-1); /* remove 2 for efficiency */ g = cgetg(3, t_POL); g[1] = evalsigne(1) | evalvarn(get_FpX_var(T)); gel(g,2) = pgener_Fp_local(p, Lp); if (po) *po = mkvec2(o, fa); return g; } if (lgefint(p) == 3) { ulong pp = to_Flxq(NULL, &T, p); g = gener_Flxq(T, pp, po); if (!po) return Flx_to_ZX_inplace(gerepileuptoleaf(av, g)); g = Flx_to_ZX(g); return gc_all(av, 2, &g, po); } /* p now odd */ q_1 = subiu(powiu(p,f), 1); N = diviiexact(q_1, p_1); Lp = odd_prime_divisors(p_1); for (i=lg(Lp)-1; i; i--) gel(Lp,i) = diviiexact(p_1, gel(Lp,i)); o = factor_pn_1(p,f); Lq = leafcopy( gel(o, 1) ); for (i = j = 1; i < lg(Lq); i++) { if (dvdii(p_1, gel(Lq,i))) continue; gel(Lq,j++) = diviiexact(N, gel(Lq,i)); } setlg(Lq, j); g = gener_FpXQ_i(get_FpX_mod(T), p, p_1, Lp, Lq); if (!po) g = gerepilecopy(av, g); else { *po = mkvec2(q_1, o); gerepileall(av, 2, &g, po); } return g; } GEN gener_FpXQ_local(GEN T, GEN p, GEN L) { GEN Lp, Lq, p_1, q_1, N, Q; long f, i, ip, iq, l; T = get_FpX_mod(T); f = degpol(T); if (f == 1) return pgener_Fp_local(p, L); l = lg(L); p_1 = subiu(p,1); q_1 = subiu(powiu(p,f), 1); N = diviiexact(q_1, p_1); Q = is_pm1(p_1)? gen_1: shifti(p_1,-1); Lp = cgetg(l, t_VEC); ip = 1; Lq = cgetg(l, t_VEC); iq = 1; for (i=1; i < l; i++) { GEN a, b, ell = gel(L,i); if (absequaliu(ell,2)) continue; a = dvmdii(Q, ell, &b); if (b == gen_0) gel(Lp,ip++) = a; else gel(Lq,iq++) = diviiexact(N,ell); } setlg(Lp, ip); setlg(Lq, iq); return gener_FpXQ_i(T, p, p_1, Lp, Lq); } /***********************************************************************/ /** **/ /** FpXn **/ /** **/ /***********************************************************************/ GEN FpXn_mul(GEN a, GEN b, long n, GEN p) { return FpX_red(ZXn_mul(a, b, n), p); } GEN FpXn_sqr(GEN a, long n, GEN p) { return FpX_red(ZXn_sqr(a, n), p); } /* (f*g) \/ x^n */ static GEN FpX_mulhigh_i(GEN f, GEN g, long n, GEN p) { return FpX_shift(FpX_mul(f,g, p),-n); } static GEN FpXn_mulhigh(GEN f, GEN g, long n2, long n, GEN p) { GEN F = RgX_blocks(f, n2, 2), fl = gel(F,1), fh = gel(F,2); return FpX_add(FpX_mulhigh_i(fl, g, n2, p), FpXn_mul(fh, g, n - n2, p), p); } GEN FpXn_div(GEN g, GEN f, long e, GEN p) { pari_sp av = avma, av2; ulong mask; GEN W, a; long v = varn(f), n = 1; if (!signe(f)) pari_err_INV("FpXn_inv",f); a = Fp_inv(gel(f,2), p); if (e == 1 && !g) return scalarpol(a, v); else if (e == 2 && !g) { GEN b; if (degpol(f) <= 0) return scalarpol(a, v); b = Fp_neg(gel(f,3),p); if (signe(b)==0) return scalarpol(a, v); if (!is_pm1(a)) b = Fp_mul(b, Fp_sqr(a, p), p); W = deg1pol_shallow(b, a, v); return gerepilecopy(av, W); } W = scalarpol_shallow(Fp_inv(gel(f,2), p),v); mask = quadratic_prec_mask(e); av2 = avma; for (;mask>1;) { GEN u, fr; long n2 = n; n<<=1; if (mask & 1) n--; mask >>= 1; fr = FpXn_red(f, n); if (mask>1 || !g) { u = FpXn_mul(W, FpXn_mulhigh(fr, W, n2, n, p), n-n2, p); W = FpX_sub(W, FpX_shift(u, n2), p); } else { GEN y = FpXn_mul(g, W, n, p), yt = FpXn_red(y, n-n2); u = FpXn_mul(yt, FpXn_mulhigh(fr, W, n2, n, p), n-n2, p); W = FpX_sub(y, FpX_shift(u, n2), p); } if (gc_needed(av2,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"FpXn_inv, e = %ld", n); W = gerepileupto(av2, W); } } return gerepileupto(av, W); } GEN FpXn_inv(GEN f, long e, GEN p) { return FpXn_div(NULL, f, e, p); } GEN FpXn_expint(GEN h, long e, GEN p) { pari_sp av = avma, av2; long v = varn(h), n=1; GEN f = pol_1(v), g = pol_1(v); ulong mask = quadratic_prec_mask(e); av2 = avma; for (;mask>1;) { GEN u, w; long n2 = n; n<<=1; if (mask & 1) n--; mask >>= 1; u = FpXn_mul(g, FpX_mulhigh_i(f, FpXn_red(h, n2-1), n2-1, p), n-n2, p); u = FpX_add(u, FpX_shift(FpXn_red(h, n-1), 1-n2), p); w = FpXn_mul(f, FpX_integXn(u, n2-1, p), n-n2, p); f = FpX_add(f, FpX_shift(w, n2), p); if (mask<=1) break; u = FpXn_mul(g, FpXn_mulhigh(f, g, n2, n, p), n-n2, p); g = FpX_sub(g, FpX_shift(u, n2), p); if (gc_needed(av2,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"FpXn_exp, e = %ld", n); gerepileall(av2, 2, &f, &g); } } return gerepileupto(av, f); } GEN FpXn_exp(GEN h, long e, GEN p) { if (signe(h)==0 || degpol(h)<1 || !gequal0(gel(h,2))) pari_err_DOMAIN("FpXn_exp","valuation", "<", gen_1, h); return FpXn_expint(FpX_deriv(h, p), e, p); } pari-2.17.2/src/basemath/base2.c0000644000175000017500000032700714760137411014714 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*******************************************************************/ /* */ /* MAXIMAL ORDERS */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_nf /* allow p = -1 from factorizations, avoid oo loop on p = 1 */ static long safe_Z_pvalrem(GEN x, GEN p, GEN *z) { if (is_pm1(p)) { if (signe(p) > 0) return gvaluation(x,p); /*error*/ *z = absi(x); return 1; } return Z_pvalrem(x, p, z); } /* D an integer, P a ZV, return a factorization matrix for D over P, removing * entries with 0 exponent. */ static GEN fact_from_factors(GEN D, GEN P, long flag) { long i, l = lg(P), iq = 1; GEN Q = cgetg(l+1,t_COL); GEN E = cgetg(l+1,t_COL); for (i=1; iT0 == S->T) return ZX_disc(S->T); d = degpol(S->T0); L = S->unscale; if (typ(L) == t_FRAC && abscmpii(gel(L,1), gel(L,2)) < 0) dT = ZX_disc(S->T); /* more efficient */ else { GEN l0 = leading_coeff(S->T0); GEN a = gpowgs(gdiv(gpowgs(L, d), sqri(l0)), d-1); dT = gmul(a, ZX_disc(S->T0)); /* more efficient */ } return S->dT = dT; } /* dT != 0 */ static GEN poldiscfactors_i(GEN T, GEN dT, long flag) { GEN U, fa, Z, E, P, Tp; long i, l; fa = absZ_factor_limit_strict(dT, minuu(tridiv_bound(dT), maxprime()), &U); if (!U) return fa; Z = mkcol(gel(U,1)); P = gel(fa,1); Tp = NULL; while (lg(Z) != 1) { /* pop and handle last element of Z */ GEN p = veclast(Z), r; setlg(Z, lg(Z)-1); if (!Tp) /* first time: p is composite and not a power */ Tp = ZX_deriv(T); else { (void)Z_isanypower(p, &p); if ((flag || lgefint(p)==3) && BPSW_psp(p)) { P = vec_append(P, p); continue; } } r = FpX_gcd_check(T, Tp, p); if (r) Z = shallowconcat(Z, Z_cba(r, diviiexact(p,r))); else if (flag) P = shallowconcat(P, gel(Z_factor(p),1)); else P = vec_append(P, p); } ZV_sort_inplace(P); l = lg(P); E = cgetg(l, t_COL); for (i = 1; i < l; i++) gel(E,i) = utoipos(Z_pvalrem(dT, gel(P,i), &dT)); return mkmat2(P,E); } GEN poldiscfactors(GEN T, long flag) { pari_sp av = avma; GEN dT; if (typ(T) != t_POL || !RgX_is_ZX(T)) pari_err_TYPE("poldiscfactors",T); if (flag < 0 || flag > 1) pari_err_FLAG("poldiscfactors"); dT = ZX_disc(T); if (!signe(dT)) retmkvec2(gen_0, Z_factor(gen_0)); return gerepilecopy(av, mkvec2(dT, poldiscfactors_i(T, dT, flag))); } static void nfmaxord_check_args(nfmaxord_t *S, GEN T, long flag) { GEN dT, L, E, P, fa = NULL; pari_timer t; long l, ty = typ(T); if (DEBUGLEVEL) timer_start(&t); if (ty == t_VEC) { if (lg(T) != 3) pari_err_TYPE("nfmaxord",T); fa = gel(T,2); T = gel(T,1); ty = typ(T); } if (ty != t_POL) pari_err_TYPE("nfmaxord",T); T = Q_primpart(T); if (degpol(T) <= 0) pari_err_CONSTPOL("nfmaxord"); RgX_check_ZX(T, "nfmaxord"); S->T0 = T; S->T = T = ZX_Q_normalize(T, &L); S->unscale = L; S->dT = dT = set_disc(S); S->certify = 1; if (!signe(dT)) pari_err_IRREDPOL("nfmaxord",T); if (fa) { const long MIN = 100; /* include at least all p < 101 */ GEN P0 = NULL, U; S->certify = 0; if (!isint1(L)) fa = update_fact(dT, fa); switch(typ(fa)) { case t_MAT: if (!is_Z_factornon0(fa)) pari_err_TYPE("nfmaxord",fa); P0 = gel(fa,1); /* fall through */ case t_VEC: case t_COL: if (!P0) { if (!RgV_is_ZV(fa)) pari_err_TYPE("nfmaxord",fa); P0 = fa; } P = gel(absZ_factor_limit_strict(dT, MIN, &U), 1); if (lg(P) != 0) { settyp(P, typ(P0)); P0 = shallowconcat(P0,P); } P0 = ZV_sort_uniq_shallow(P0); fa = fact_from_factors(dT, P0, 0); break; case t_INT: fa = absZ_factor_limit(dT, (signe(fa) <= 0)? 1: maxuu(itou(fa), MIN)); break; default: pari_err_TYPE("nfmaxord",fa); } } else { S->certify = !(flag & nf_PARTIALFACT); fa = poldiscfactors_i(T, dT, 0); } P = gel(fa,1); l = lg(P); E = gel(fa,2); if (l > 1 && is_pm1(gel(P,1))) { l--; P = vecslice(P, 2, l); E = vecslice(E, 2, l); } S->dTP = P; S->dTE = vec_to_vecsmall(E); if (DEBUGLEVEL>2) timer_printf(&t, "disc. factorisation"); } static int fnz(GEN x,long j) { long i; for (i=1; i 1 is composite, not a pure power, and has no prime divisor < 2^14; * return a BPSW divisor of n and smallest k-th root of largest coprime cofactor */ static GEN Z_fac(GEN n) { GEN p = icopy(n), part = ifac_start(p, 0); long e; ifac_next(&part , &p, &e); n = diviiexact(n, powiu(p, e)); (void)Z_isanypower(n, &n); return mkvec2(p, n); } /* Warning: data computed for T = ZX_Q_normalize(T0). If S.unscale != * gen_1, caller must take steps to correct the components if it wishes * to stick to the original T0. Return a vector of p-maximal orders, for * those p s.t p^2 | disc(T) [ = S->dTP ]*/ static GEN get_maxord(nfmaxord_t *S, GEN T0, long flag) { GEN P, E; VOLATILE GEN O; VOLATILE long lP, i, k; nfmaxord_check_args(S, T0, flag); P = S->dTP; lP = lg(P); E = S->dTE; O = cgetg(1, t_VEC); for (i=1; icertify) { GEN p = gel(P,i); if (signe(p) > 0 && !BPSW_psp(p)) { fix_PE(&P, &E, i, Z_fac(p), S->dT); lP = lg(P); i--; continue; } } O = vec_append(O, gen_1); continue; } av = avma; pari_CATCH(CATCH_ALL) { GEN u, err = pari_err_last(); long l; switch(err_get_num(err)) { case e_INV: { GEN p, x = err_get_compo(err, 2); if (typ(x) == t_INTMOD) { /* caught false prime, update factorization */ p = gcdii(gel(x,1), gel(x,2)); u = diviiexact(gel(x,1),p); if (DEBUGLEVEL) pari_warn(warner,"impossible inverse: %Ps", x); gerepileall(av, 2, &p, &u); u = get_coprimes(p, u); l = lg(u); /* no small factors, but often a prime power */ for (k = 1; k < l; k++) (void)Z_isanypower(gel(u,k), &gel(u,k)); break; } /* fall through */ } case e_PRIME: case e_IRREDPOL: { /* we're here because we failed BPSW_isprime(), no point in * reporting a possible counter-example to the BPSW test */ GEN p = gel(P,i); set_avma(av); if (DEBUGLEVEL) pari_warn(warner,"large composite in nfmaxord:loop(), %Ps", p); if (expi(p) < 100) u = gel(Z_factor(p), 1); /* p < 2^100 should take ~20ms */ else if (S->certify) u = Z_fac(p); else { /* give up, probably not maximal */ GEN B, g, k = ZX_Dedekind(S->T, &g, p); k = FpX_normalize(k, p); B = dbasis(p, S->T, E[i], NULL, FpX_div(S->T,k,p)); O = vec_append(O, B); pari_CATCH_reset(); continue; } break; } default: pari_err(0, err); return NULL;/*LCOV_EXCL_LINE*/ } fix_PE(&P, &E, i, u, S->dT); lP = lg(P); av = avma; } pari_RETRY { GEN p = gel(P,i), O2; if (DEBUGLEVEL>2) err_printf("Treating p^k = %Ps^%ld\n",p,E[i]); O2 = maxord(p,S->T,E[i]); if (S->certify && (odd(E[i]) || E[i] != 2*diag_denomval(O2, p)) && !BPSW_psp(p)) { fix_PE(&P, &E, i, gel(Z_factor(p), 1), S->dT); lP = lg(P); i--; } else O = vec_append(O, O2); } pari_ENDCATCH; } S->dTP = P; S->dTE = E; return O; } /* M a QM, return denominator of diagonal. All denominators are powers of * a given integer */ static GEN diag_denom(GEN M) { GEN d = gen_1; long j, l = lg(M); for (j=1; j 0) d = t; } return d; } static void setPE(GEN D, GEN P, GEN *pP, GEN *pE) { long k, j, l = lg(P); GEN P2, E2; *pP = P2 = cgetg(l, t_VEC); *pE = E2 = cgetg(l, t_VECSMALL); for (k = j = 1; j < l; 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); setlg(E2, k); } void nfmaxord(nfmaxord_t *S, GEN T0, long flag) { GEN O = get_maxord(S, T0, flag); GEN f = S->T, P = S->dTP, a = NULL, da = NULL; long n = degpol(f), lP = lg(P), i, j, k; int centered = 0; pari_sp av = avma; /* r1 & basden not initialized here */ S->r1 = -1; S->basden = NULL; for (i=1; iindex = index; S->dK = diviiexact(S->dT, sqri(index)); } else { S->index = gen_1; S->dK = S->dT; a = matid(n); } setPE(S->dK, P, &S->dKP, &S->dKE); S->basis = RgM_to_RgXV(a, varn(f)); } GEN nfbasis(GEN x, GEN *pdK) { pari_sp av = avma; nfmaxord_t S; GEN B; nfmaxord(&S, x, 0); B = RgXV_unscale(S.basis, S.unscale); if (pdK) *pdK = S.dK; return gc_all(av, pdK? 2: 1, &B, pdK); } /* field discriminant: faster than nfmaxord, use local data only */ static GEN maxord_disc(nfmaxord_t *S, GEN x) { GEN O = get_maxord(S, x, 0), I = gen_1; long n = degpol(S->T), lP = lg(O), i, j; for (i = 1; i < lP; i++) { GEN b = gel(O,i); if (b == gen_1) continue; for (j = 1; j <= n; j++) { GEN c = gcoeff(b,j,j); if (typ(c) == t_FRAC) I = mulii(I, gel(c,2)) ; } } return diviiexact(S->dT, sqri(I)); } GEN nfdisc(GEN x) { pari_sp av = avma; nfmaxord_t S; return gerepileuptoint(av, maxord_disc(&S, x)); } GEN nfdiscfactors(GEN x) { pari_sp av = avma; GEN E, P, D, nf = checknf_i(x); if (nf) { D = nf_get_disc(nf); P = nf_get_ramified_primes(nf); } else { nfmaxord_t S; D = maxord_disc(&S, x); P = S.dTP; } setPE(D, P, &P, &E); settyp(P, t_COL); return gerepilecopy(av, mkvec2(D, mkmat2(P, zc_to_ZC(E)))); } static ulong Flx_checkdeflate(GEN x) { ulong d = 0, i, lx = (ulong)lg(x); for (i=3; i f(x) */ u = Flx_gcd(f, Flx_deriv(f, p), p); /* (f,f') */ du = degpol(u); if (du) { if (du == (ulong)degpol(f)) f = Flx_radical(Flx_deflate(f,p), p); else { u = Flx_normalize(u, p); f = Flx_div(f, u, p); if (p <= du) { GEN w = (degpol(f) >= degpol(u))? Flx_rem(f, u, p): f; w = Flxq_powu(w, du, u, p); w = Flx_div(u, Flx_gcd(w,u,p), p); /* u / gcd(u, v^(deg u-1)) */ f = Flx_mul(f, Flx_radical(Flx_deflate(w,p), p), p); } } } if (v0) f = Flx_shift(f, 1); return f; } /* Assume f reduced mod p, otherwise valuation at x may be wrong */ static GEN FpX_radical(GEN f, GEN p) { GEN u; long v0; if (lgefint(p) == 3) { ulong q = p[2]; return Flx_to_ZX( Flx_radical(ZX_to_Flx(f, q), q) ); } v0 = ZX_valrem(f, &f); u = FpX_gcd(f,FpX_deriv(f, p), p); if (degpol(u)) f = FpX_div(f, u, p); if (v0) f = RgX_shift(f, 1); return f; } /* f / a */ static GEN zx_z_div(GEN f, ulong a) { long i, l = lg(f); GEN g = cgetg(l, t_VECSMALL); g[1] = f[1]; for (i = 2; i < l; i++) g[i] = f[i] / a; return g; } /* Dedekind criterion; return k = gcd(g,h, (f-gh)/p), where * f = \prod f_i^e_i, g = \prod f_i, h = \prod f_i^{e_i-1} * k = 1 iff Z[X]/(f) is p-maximal */ static GEN ZX_Dedekind(GEN F, GEN *pg, GEN p) { GEN k, h, g, f, f2; ulong q = p[2]; if (lgefint(p) == 3 && q < (1UL << BITS_IN_HALFULONG)) { ulong q2 = q*q; f2 = ZX_to_Flx(F, q2); f = Flx_red(f2, q); g = Flx_radical(f, q); h = Flx_div(f, g, q); k = zx_z_div(Flx_sub(f2, Flx_mul(g,h,q2), q2), q); k = Flx_gcd(k, Flx_gcd(g,h,q), q); k = Flx_to_ZX(k); g = Flx_to_ZX(g); } else { f2 = FpX_red(F, sqri(p)); f = FpX_red(f2, p); g = FpX_radical(f, p); h = FpX_div(f, g, p); k = ZX_Z_divexact(ZX_sub(f2, ZX_mul(g,h)), p); k = FpX_gcd(FpX_red(k, p), FpX_gcd(g,h,p), p); } *pg = g; return k; } /* p-maximal order of Z[x]/f; mf = v_p(Disc(f)) or < 0 [unknown]. * Return gen_1 if p-maximal */ static GEN maxord(GEN p, GEN f, long mf) { const pari_sp av = avma; GEN res, g, k = ZX_Dedekind(f, &g, p); long dk = degpol(k); if (DEBUGLEVEL>2) err_printf(" ZX_Dedekind: gcd has degree %ld\n", dk); if (!dk) { set_avma(av); return gen_1; } if (mf < 0) mf = ZpX_disc_val(f, p); k = FpX_normalize(k, p); if (2*dk >= mf-1) res = dbasis(p, f, mf, NULL, FpX_div(f,k,p)); else { GEN w, F1, F2; decomp_t S; F1 = FpX_factor(k,p); F2 = FpX_factor(FpX_div(g,k,p),p); w = merge_sort_uniq(gel(F1,1),gel(F2,1),(void*)cmpii,&gen_cmp_RgX); res = maxord_i(&S, p, f, mf, w, 0); } return gerepilecopy(av,res); } /* T monic separable ZX, p prime */ GEN ZpX_primedec(GEN T, GEN p) { const pari_sp av = avma; GEN w, F1, F2, res, g, k = ZX_Dedekind(T, &g, p); decomp_t S; if (!degpol(k)) return zm_to_ZM(FpX_degfact(T, p)); k = FpX_normalize(k, p); F1 = FpX_factor(k,p); F2 = FpX_factor(FpX_div(g,k,p),p); w = merge_sort_uniq(gel(F1,1),gel(F2,1),(void*)cmpii,&gen_cmp_RgX); res = maxord_i(&S, p, T, ZpX_disc_val(T, p), w, -1); if (!res) { long f = degpol(S.nu), e = degpol(T) / f; set_avma(av); retmkmat2(mkcols(f), mkcols(e)); } return gerepilecopy(av,res); } static GEN Zlx_sylvester_echelon(GEN f1, GEN f2, long early_abort, ulong p, ulong pm) { long j, n = degpol(f1); GEN h, a = cgetg(n+1,t_MAT); f1 = Flx_get_red(f1, pm); h = Flx_rem(f2,f1,pm); for (j=1;; j++) { gel(a,j) = Flx_to_Flv(h, n); if (j == n) break; h = Flx_rem(Flx_shift(h, 1), f1, pm); } return zlm_echelon(a, early_abort, p, pm); } /* Sylvester's matrix, mod p^m (assumes f1 monic). If early_abort * is set, return NULL if one pivot is 0 mod p^m */ static GEN ZpX_sylvester_echelon(GEN f1, GEN f2, long early_abort, GEN p, GEN pm) { long j, n = degpol(f1); GEN h, a = cgetg(n+1,t_MAT); h = FpXQ_red(f2,f1,pm); for (j=1;; j++) { gel(a,j) = RgX_to_RgC(h, n); if (j == n) break; h = FpX_rem(RgX_shift_shallow(h, 1), f1, pm); } return ZpM_echelon(a, early_abort, p, pm); } /* polynomial gcd mod p^m (assumes f1 monic). Return a QpX ! */ static GEN Zlx_gcd(GEN f1, GEN f2, ulong p, ulong pm) { pari_sp av = avma; GEN a = Zlx_sylvester_echelon(f1,f2,0,p,pm); long c, l = lg(a), sv = f1[1]; for (c = 1; c < l; c++) { ulong t = ucoeff(a,c,c); if (t) { a = Flx_to_ZX(Flv_to_Flx(gel(a,c), sv)); if (t == 1) return gerepilecopy(av, a); return gerepileupto(av, RgX_Rg_div(a, utoipos(t))); } } set_avma(av); a = cgetg(2,t_POL); a[1] = sv; return a; } GEN ZpX_gcd(GEN f1, GEN f2, GEN p, GEN pm) { pari_sp av = avma; GEN a; long c, l, v; if (lgefint(pm) == 3) { ulong q = pm[2]; return Zlx_gcd(ZX_to_Flx(f1, q), ZX_to_Flx(f2,q), p[2], q); } a = ZpX_sylvester_echelon(f1,f2,0,p,pm); l = lg(a); v = varn(f1); for (c = 1; c < l; c++) { GEN t = gcoeff(a,c,c); if (signe(t)) { a = RgV_to_RgX(gel(a,c), v); if (equali1(t)) return gerepilecopy(av, a); return gerepileupto(av, RgX_Rg_div(a, t)); } } set_avma(av); return pol_0(v); } /* Return m > 0, such that p^m ~ 2^16 for initial value of m; assume p prime */ static long init_m(GEN p) { ulong pp; if (lgefint(p) > 3) return 1; pp = p[2]; /* m ~ 16 / log2(pp) */ if (pp < 41) switch(pp) { case 2: return 16; case 3: return 10; case 5: return 6; case 7: return 5; case 11: case 13: return 4; default: return 3; } return pp < 257? 2: 1; } /* reduced resultant mod p^m (assumes x monic) */ GEN ZpX_reduced_resultant(GEN x, GEN y, GEN p, GEN pm) { pari_sp av = avma; GEN z; if (lgefint(pm) == 3) { ulong q = pm[2]; z = Zlx_sylvester_echelon(ZX_to_Flx(x,q), ZX_to_Flx(y,q),0,p[2],q); if (lg(z) > 1) { ulong c = ucoeff(z,1,1); if (c) return gc_utoipos(av, c); } } else { z = ZpX_sylvester_echelon(x,y,0,p,pm); if (lg(z) > 1) { GEN c = gcoeff(z,1,1); if (signe(c)) return gerepileuptoint(av, c); } } set_avma(av); return gen_0; } /* Assume Res(f,g) divides p^M. Return Res(f, g), using dynamic p-adic * precision (until result is nonzero or p^M). */ GEN ZpX_reduced_resultant_fast(GEN f, GEN g, GEN p, long M) { GEN R, q = NULL; long m; m = init_m(p); if (m < 1) m = 1; for(;; m <<= 1) { if (M < 2*m) break; q = q? sqri(q): powiu(p, m); /* p^m */ R = ZpX_reduced_resultant(f,g, p, q); if (signe(R)) return R; } q = powiu(p, M); R = ZpX_reduced_resultant(f,g, p, q); return signe(R)? R: q; } /* v_p(Res(x,y) mod p^m), assumes (lc(x),p) = 1 */ static long ZpX_resultant_val_i(GEN x, GEN y, GEN p, GEN pm) { pari_sp av = avma; GEN z; long i, l, v; if (lgefint(pm) == 3) { ulong q = pm[2], pp = p[2]; z = Zlx_sylvester_echelon(ZX_to_Flx(x,q), ZX_to_Flx(y,q), 1, pp, q); if (!z) return gc_long(av,-1); /* failure */ v = 0; l = lg(z); for (i = 1; i < l; i++) v += u_lval(ucoeff(z,i,i), pp); } else { z = ZpX_sylvester_echelon(x, y, 1, p, pm); if (!z) return gc_long(av,-1); /* failure */ v = 0; l = lg(z); for (i = 1; i < l; i++) v += Z_pval(gcoeff(z,i,i), p); } return v; } /* assume (lc(f),p) = 1; no assumption on g */ long ZpX_resultant_val(GEN f, GEN g, GEN p, long M) { pari_sp av = avma; GEN q = NULL; long v, m; m = init_m(p); if (m < 2) m = 2; for(;; m <<= 1) { if (m > M) m = M; q = q? sqri(q): powiu(p, m); /* p^m */ v = ZpX_resultant_val_i(f,g, p, q); if (v >= 0) return gc_long(av,v); if (m == M) return gc_long(av,M); } } /* assume f separable and (lc(f),p) = 1 */ long ZpX_disc_val(GEN f, GEN p) { pari_sp av = avma; long v; if (degpol(f) == 1) return 0; v = ZpX_resultant_val(f, ZX_deriv(f), p, LONG_MAX); return gc_long(av,v); } /* *e a ZX, *d, *z in Z, *d = p^(*vd). Simplify e / d by cancelling a * common factor p^v; if z!=NULL, update it by cancelling the same power of p */ static void update_den(GEN p, GEN *e, GEN *d, long *vd, GEN *z) { GEN newe; long ve = ZX_pvalrem(*e, p, &newe); if (ve) { GEN newd; long v = minss(*vd, ve); if (v) { if (v == *vd) { /* rare, denominator cancelled */ if (ve != v) newe = ZX_Z_mul(newe, powiu(p, ve - v)); newd = gen_1; *vd = 0; if (z) *z =diviiexact(*z, powiu(p, v)); } else { /* v = ve < vd, generic case */ GEN q = powiu(p, v); newd = diviiexact(*d, q); *vd -= v; if (z) *z = diviiexact(*z, q); } *e = newe; *d = newd; } } } /* return denominator, a power of p */ static GEN QpX_denom(GEN x) { long i, l = lg(x); GEN maxd = gen_1; for (i=2; i 0) maxd = gel(d,2); } return maxd; } static GEN QpXV_denom(GEN x) { long l = lg(x), i; GEN maxd = gen_1; for (i = 1; i < l; i++) { GEN d = QpX_denom(gel(x,i)); if (cmpii(d, maxd) > 0) maxd = d; } return maxd; } static GEN QpX_remove_denom(GEN x, GEN p, GEN *pdx, long *pv) { *pdx = QpX_denom(x); if (*pdx == gen_1) { *pv = 0; *pdx = NULL; } else { x = Q_muli_to_int(x,*pdx); *pv = Z_pval(*pdx, p); } return x; } /* p^v * f o g mod (T,q). q = p^vq */ static GEN compmod(GEN p, GEN f, GEN g, GEN T, GEN q, long v) { GEN D = NULL, z, df, dg, qD; long vD = 0, vdf, vdg; f = QpX_remove_denom(f, p, &df, &vdf); if (typ(g) == t_VEC) /* [num,den,v_p(den)] */ { vdg = itos(gel(g,3)); dg = gel(g,2); g = gel(g,1); } else g = QpX_remove_denom(g, p, &dg, &vdg); if (df) { D = df; vD = vdf; } if (dg) { long degf = degpol(f); D = mul_content(D, powiu(dg, degf)); vD += degf * vdg; } qD = D ? mulii(q, D): q; if (dg) f = FpX_rescale(f, dg, qD); z = FpX_FpXQ_eval(f, g, T, qD); if (!D) { if (v) { if (v > 0) z = ZX_Z_mul(z, powiu(p, v)); else z = RgX_Rg_div(z, powiu(p, -v)); } return z; } update_den(p, &z, &D, &vD, NULL); qD = mulii(D,q); if (v) vD -= v; z = FpX_center_i(z, qD, shifti(qD,-1)); if (vD > 0) z = RgX_Rg_div(z, powiu(p, vD)); else if (vD < 0) z = ZX_Z_mul(z, powiu(p, -vD)); return z; } /* fast implementation of ZM_hnfmodid(M, D) / D, D = p^k */ static GEN ZpM_hnfmodid(GEN M, GEN p, GEN D) { long i, l = lg(M); M = RgM_Rg_div(ZpM_echelon(M,0,p,D), D); for (i = 1; i < l; i++) if (gequal0(gcoeff(M,i,i))) gcoeff(M,i,i) = gen_1; return M; } /* Return Z-basis for Z[a] + U(a)/p Z[a] in Z[t]/(f), mf = v_p(disc f), U * a ZX. Special cases: a = t is coded as NULL, U = 0 is coded as NULL */ static GEN dbasis(GEN p, GEN f, long mf, GEN a, GEN U) { long n = degpol(f), i, dU; GEN b, h; if (n == 1) return matid(1); if (a && gequalX(a)) a = NULL; if (DEBUGLEVEL>5) { err_printf(" entering Dedekind Basis with parameters p=%Ps\n",p); err_printf(" f = %Ps,\n a = %Ps\n",f, a? a: pol_x(varn(f))); } if (a) { GEN pd = powiu(p, mf >> 1); GEN da, pdp = mulii(pd,p), D = pdp; long vda; dU = U ? degpol(U): 0; b = cgetg(n+1, t_MAT); h = scalarpol(pd, varn(f)); a = QpX_remove_denom(a, p, &da, &vda); if (da) D = mulii(D, da); gel(b,1) = scalarcol_shallow(pd, n); for (i=2; i<=n; i++) { if (i == dU+1) h = compmod(p, U, mkvec3(a,da,stoi(vda)), f, pdp, (mf>>1) - 1); else { h = FpXQ_mul(h, a, f, D); if (da) h = ZX_Z_divexact(h, da); } gel(b,i) = RgX_to_RgC(h,n); } return ZpM_hnfmodid(b, p, pd); } else { if (!U) return matid(n); dU = degpol(U); if (dU == n) return matid(n); U = FpX_normalize(U, p); b = cgetg(n+1, t_MAT); for (i = 1; i <= dU; i++) gel(b,i) = vec_ei(n, i); h = RgX_Rg_div(U, p); for ( ; i <= n; i++) { gel(b, i) = RgX_to_RgC(h,n); if (i == n) break; h = RgX_shift_shallow(h,1); } return b; } } static GEN get_partial_order_as_pols(GEN p, GEN f) { GEN O = maxord(p, f, -1); long v = varn(f); return O == gen_1? pol_x_powers(degpol(f), v): RgM_to_RgXV(O, v); } static long p_is_prime(decomp_t *S) { if (S->pisprime < 0) S->pisprime = BPSW_psp(S->p); return S->pisprime; } static GEN ZpX_monic_factor_squarefree(GEN f, GEN p, long prec); /* 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, pr2, pr, pk, ph2, ph, b1, b2, a, e, de, f1, f2, dt, th, chip; GEN p = S->p; long vde, vdt, k, r = maxss(flag, 2*S->df + 1); if (DEBUGLEVEL>5) err_printf(" entering Decomp: %Ps^%ld\n f = %Ps\n", p, r, S->f); else if (DEBUGLEVEL>2) err_printf(" entering Decomp\n"); chip = FpX_red(S->chi, p); if (!FpX_valrem(chip, S->nu, p, &b1)) { if (!p_is_prime(S)) pari_err_PRIME("Decomp",p); pari_err_BUG("Decomp (not a factor)"); } b2 = FpX_div(chip, b1, p); a = FpX_mul(FpXQ_inv(b2, b1, p), b2, p); /* E = e / de, e in Z[X], de in Z, E = a(phi) mod (f, p) */ th = QpX_remove_denom(S->phi, p, &dt, &vdt); if (dt) { long dega = degpol(a); vde = dega * vdt; de = powiu(dt, dega); pr = mulii(p, de); a = FpX_rescale(a, dt, pr); } else { vde = 0; de = gen_1; pr = p; } e = FpX_FpXQ_eval(a, th, S->f, pr); update_den(p, &e, &de, &vde, NULL); pk = p; k = 1; /* E, (1 - E) tend to orthogonal idempotents in Zp[X]/(f) */ while (k < r + vde) { /* E <-- E^2(3-2E) mod p^2k, with E = e/de */ GEN D; pk = sqri(pk); k <<= 1; e = ZX_mul(ZX_sqr(e), Z_ZX_sub(mului(3,de), gmul2n(e,1))); de= mulii(de, sqri(de)); vde *= 3; D = mulii(pk, de); e = FpX_rem(e, centermod(S->f, D), D); /* e/de defined mod pk */ update_den(p, &e, &de, &vde, NULL); } /* required precision of the factors */ pr = powiu(p, r); pr2 = shifti(pr, -1); ph = mulii(de,pr);ph2 = shifti(ph, -1); e = FpX_center_i(FpX_red(e, ph), ph, ph2); fred = FpX_red(S->f, ph); f1 = ZpX_gcd(fred, Z_ZX_sub(de, e), p, ph); /* p-adic gcd(f, 1-e) */ if (!is_pm1(de)) { fred = FpX_red(fred, pr); f1 = FpX_red(f1, pr); } f2 = FpX_div(fred,f1, pr); f1 = FpX_center_i(f1, pr, pr2); f2 = FpX_center_i(f2, pr, pr2); if (DEBUGLEVEL>5) err_printf(" leaving Decomp: f1 = %Ps\nf2 = %Ps\ne = %Ps\nde= %Ps\n", f1,f2,e,de); if (flag < 0) { GEN m = vconcat(ZpX_primedec(f1, p), ZpX_primedec(f2, p)); return sort_factor(m, (void*)&cmpii, &cmp_nodata); } else if (flag) { gerepileall(av, 2, &f1, &f2); return shallowconcat(ZpX_monic_factor_squarefree(f1, p, flag), ZpX_monic_factor_squarefree(f2, p, flag)); } else { GEN D, d1, d2, B1, B2, M; long n, n1, n2, i; gerepileall(av, 4, &f1, &f2, &e, &de); D = de; B1 = get_partial_order_as_pols(p,f1); n1 = lg(B1)-1; B2 = get_partial_order_as_pols(p,f2); n2 = lg(B2)-1; n = n1+n2; d1 = QpXV_denom(B1); d2 = QpXV_denom(B2); if (cmpii(d1, d2) < 0) d1 = d2; if (d1 != gen_1) { B1 = Q_muli_to_int(B1, d1); B2 = Q_muli_to_int(B2, d1); D = mulii(d1, D); } fred = centermod_i(S->f, D, shifti(D,-1)); M = cgetg(n+1, t_MAT); for (i=1; i<=n1; i++) gel(M,i) = RgX_to_RgC(FpX_rem(FpX_mul(gel(B1,i),e,D), fred, D), n); e = Z_ZX_sub(de, e); B2 -= n1; for ( ; i<=n; i++) gel(M,i) = RgX_to_RgC(FpX_rem(FpX_mul(gel(B2,i),e,D), fred, D), n); return ZpM_hnfmodid(M, p, D); } } /* minimum extension valuation: L/E */ static void vstar(GEN p,GEN h, long *L, long *E) { long first, j, k, v, w, m = degpol(h); first = 1; k = 1; v = 0; for (j=1; j<=m; j++) { GEN c = gel(h, m-j+2); if (signe(c)) { w = Z_pval(c,p); if (first || w*k < v*j) { v = w; k = j; } first = 0; } } /* v/k = min_j ( v_p(h_{m-j}) / j ) */ w = (long)ugcd(v,k); *L = v/w; *E = k/w; } static GEN redelt_i(GEN a, GEN N, GEN p, GEN *pda, long *pvda) { GEN z; a = Q_remove_denom(a, pda); *pvda = 0; if (*pda) { long v = Z_pvalrem(*pda, p, &z); if (v) { *pda = powiu(p, v); *pvda = v; N = mulii(*pda, N); } else *pda = NULL; if (!is_pm1(z)) a = ZX_Z_mul(a, Fp_inv(z, N)); } return centermod(a, N); } /* reduce the element a modulo N [ a power of p ], taking first care of the * denominators */ static GEN redelt(GEN a, GEN N, GEN p) { GEN da; long vda; a = redelt_i(a, N, p, &da, &vda); if (da) a = RgX_Rg_div(a, da); return a; } /* compute the 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, lns = lg(ns); pari_sp av; a = centermod(a, pp); av = avma; 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 l; pa = j == 1? a: FpXQ_mul(pa, a, chi, pp); l = lg(pa); if (l == 2) break; if (lns < l) l = lns; 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,2)); /* k = 2 */ for (k = 3; k < l; k++) s = addii(s, mulii(gel(pa,k), gel(ns,k))); 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 (gc_needed(av, 1)) { if(DEBUGMEM>1) pari_warn(warnmem, "newtonsums"); gerepileall(av, dpa?4:3, &pa, &va, &pp, &dpa); } } for (; j <= c; j++) gel(va,j) = gen_0; 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), pp2 = shifti(pp,-1); 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, Fp_center_i(s, pp, pp2)); } for (k = odd(n)? 1: 2; k <= n+1; k += 2) gel(c,k) = negi(gel(c,k)); return gtopoly(c, 0); } static void manage_cache(decomp_t *S, GEN f, GEN pp) { GEN t = S->precns; if (!t) t = mulii(S->pmf, powiu(S->p, S->df)); if (cmpii(t, pp) < 0) t = pp; if (!S->precns || !RgX_equal(f, S->nsf) || cmpii(S->precns, t) < 0) { if (DEBUGLEVEL>4) err_printf(" Precision for cached Newton sums for %Ps: %Ps -> %Ps\n", f, S->precns? S->precns: gen_0, t); S->nsf = f; S->ns = FpX_Newton(f, degpol(f), t); S->precns = t; } } /* return NULL if a mod f is not an integer * The denominator of any integer in Zp[X]/(f) divides pdr */ static GEN mycaract(decomp_t *S, GEN f, GEN a, GEN pp, GEN pdr) { pari_sp av; GEN d, chi, prec1, prec2, prec3, ns; long vd, n = degpol(f); if (gequal0(a)) return pol_0(varn(f)); a = QpX_remove_denom(a, S->p, &d, &vd); prec1 = pp; if (lgefint(S->p) == 3) prec1 = mulii(prec1, powiu(S->p, factorial_lval(n, itou(S->p)))); if (d) { GEN p1 = powiu(d, n); prec2 = mulii(prec1, p1); prec3 = mulii(prec1, gmin_shallow(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) { /* split off powers of x first for efficiency */ long v = ZX_valrem(FpX_red(chi,p), &chi), n; GEN P; if (!degpol(chi)) { *ptl = 1; return pol_x(varn(chi)); } P = gel(FpX_factor(chi,p), 1); n = lg(P)-1; *ptl = v? n+1: n; return gel(P,n); } /* Factor characteristic polynomial chi of phi mod p. If it splits, update * S->{phi, chi, nu} and return 1. In any case, set *nu to an irreducible * factor mod p of chi */ static int split_char(decomp_t *S, GEN chi, GEN phi, GEN phi0, GEN *nu) { long l; *nu = get_nu(chi, S->p, &l); if (l == 1) return 0; /* single irreducible factor: doesn't split */ /* phi o phi0 mod (p, f) */ S->phi = compmod(S->p, phi, phi0, S->f, S->p, 0); S->chi = chi; S->nu = *nu; return 1; } /* Return the prime element in Zp[phi], a t_INT (iff *Ep = 1) or QX; * nup, chip are ZX. phi = NULL codes X * If *Ep < oE or Ep divides Ediv (!=0) return NULL (uninteresting) */ static GEN getprime(decomp_t *S, GEN phi, GEN chip, GEN nup, long *Lp, long *Ep, long oE, long Ediv) { GEN z, chin, q, qp; long r, s; if (phi && dvdii(constant_coeff(chip), S->psc)) { chip = mycaract(S, S->chi, phi, S->pmf, S->prc); if (dvdii(constant_coeff(chip), S->pmf)) chip = ZXQ_charpoly(phi, S->chi, varn(chip)); } if (degpol(nup) == 1) { GEN c = gel(nup,2); /* nup = X + c */ chin = signe(c)? RgX_translate(chip, negi(c)): chip; } else chin = ZXQ_charpoly(nup, chip, varn(chip)); vstar(S->p, chin, Lp, Ep); if (*Ep < oE || (Ediv && Ediv % *Ep == 0)) return NULL; if (*Ep == 1) return S->p; (void)cbezout(*Lp, -*Ep, &r, &s); /* = 1 */ if (r <= 0) { long t = 1 + ((-r) / *Ep); r += t * *Ep; s += t * *Lp; } /* r > 0 minimal such that r L/E - s = 1/E * pi = nu^r / p^s is an element of valuation 1/E, * so is pi + O(p) since 1/E < 1. May compute nu^r mod p^(s+1) */ q = powiu(S->p, s); qp = mulii(q, S->p); nup = FpXQ_powu(nup, r, S->chi, qp); if (!phi) return RgX_Rg_div(nup, q); /* phi = X : no composition */ z = compmod(S->p, nup, phi, S->chi, qp, -s); return signe(z)? z: NULL; } static int update_phi(decomp_t *S) { GEN PHI = NULL, prc, psc, X = pol_x(varn(S->f)); long k, vpsc; for (k = 1;; k++) { prc = ZpX_reduced_resultant_fast(S->chi, ZX_deriv(S->chi), S->p, S->vpsc); /* if prc == S->psc then either chi is not separable or the reduced discriminant of chi is too large */ if (!equalii(prc, S->psc)) break; /* increase precision */ S->vpsc = maxss(S->vpsf, S->vpsc + 1); S->psc = (S->vpsc == S->vpsf)? S->psf: mulii(S->psc, S->p); PHI = S->phi; if (S->phi0) PHI = compmod(S->p, PHI, S->phi0, S->f, S->psc, 0); /* change phi (in case not separable) */ PHI = gadd(PHI, ZX_Z_mul(X, mului(k, S->p))); S->chi = mycaract(S, S->f, PHI, S->psc, S->pdf); } psc = mulii(sqri(prc), S->p); vpsc = 2*Z_pval(prc, S->p) + 1; if (!PHI) /* break out of above loop immediately (k = 1) */ { PHI = S->phi; if (S->phi0) PHI = compmod(S->p, PHI, S->phi0, S->f, psc, 0); if (S->phi0 || cmpii(psc,S->psc) > 0) { for(;;) { S->chi = mycaract(S, S->f, PHI, psc, S->pdf); prc = ZpX_reduced_resultant_fast(S->chi, ZX_deriv(S->chi), S->p, vpsc); if (!equalii(prc, psc)) break; psc = mulii(psc, S->p); vpsc++; /* it can happen that S->chi is never squarefree: then change PHI */ if (vpsc > 2*S->mf) PHI = gadd(PHI, ZX_Z_mul(X, S->p)); } psc = mulii(sqri(prc), S->p); vpsc = 2*Z_pval(prc, S->p) + 1; } } S->phi = PHI; S->chi = FpX_red(S->chi, psc); /* may happen if p is unramified */ if (is_pm1(prc)) return 0; S->prc = prc; S->psc = psc; S->vpsc = vpsc; return 1; } /* return 1 if at least 2 factors mod p ==> chi splits * Replace S->phi such that F increases (to D) */ static int testb2(decomp_t *S, long D, GEN theta) { long v = varn(S->chi), dlim = degpol(S->chi)-1; GEN T0 = S->phi, chi, phi, nu; if (DEBUGLEVEL>4) err_printf(" Increasing Fa\n"); for (;;) { phi = gadd(theta, random_FpX(dlim, v, S->p)); chi = mycaract(S, S->chi, phi, S->psf, S->prc); /* phi nonprimary ? */ if (split_char(S, chi, phi, T0, &nu)) return 1; if (degpol(nu) == D) break; } /* F_phi=lcm(F_alpha, F_theta)=D and E_phi=E_alpha */ S->phi0 = T0; S->chi = chi; S->phi = phi; S->nu = nu; return 0; } /* return 1 if at least 2 factors mod p ==> chi can be split. * compute a new S->phi such that E = lcm(Ea, Et); * A a ZX, T a t_INT (iff Et = 1, probably impossible ?) or QX */ static int testc2(decomp_t *S, GEN A, long Ea, GEN T, long Et) { GEN c, chi, phi, nu, T0 = S->phi; if (DEBUGLEVEL>4) err_printf(" Increasing Ea\n"); if (Et == 1) /* same as other branch, split for efficiency */ c = A; /* Et = 1 => s = 1, r = 0, t = 0 */ else { long r, s, t; (void)cbezout(Ea, Et, &r, &s); t = 0; while (r < 0) { r = r + Et; t++; } while (s < 0) { s = s + Ea; t++; } /* A^s T^r / p^t */ c = RgXQ_mul(RgXQ_powu(A, s, S->chi), RgXQ_powu(T, r, S->chi), S->chi); c = RgX_Rg_div(c, powiu(S->p, t)); c = redelt(c, S->psc, S->p); } phi = RgX_add(c, pol_x(varn(S->chi))); chi = mycaract(S, S->chi, phi, S->psf, S->prc); if (split_char(S, chi, phi, T0, &nu)) return 1; /* E_phi = lcm(E_alpha,E_theta) */ S->phi0 = T0; S->chi = chi; S->phi = phi; S->nu = nu; return 0; } /* Return h^(-degpol(P)) P(x * h) if result is integral, NULL otherwise */ static GEN ZX_rescale_inv(GEN P, GEN h) { long i, l = lg(P); GEN Q = cgetg(l,t_POL), hi = h; gel(Q,l-1) = gel(P,l-1); for (i=l-2; i>=2; i--) { GEN r; gel(Q,i) = dvmdii(gel(P,i), hi, &r); if (signe(r)) return NULL; if (i == 2) break; hi = mulii(hi,h); } Q[1] = P[1]; return Q; } /* x p^-eq nu^-er mod p */ static GEN get_gamma(decomp_t *S, GEN x, long eq, long er) { GEN q, g = x, Dg = powiu(S->p, eq); long vDg = eq; if (er) { if (!S->invnu) { while (gdvd(S->chi, S->nu)) S->nu = RgX_Rg_add(S->nu, S->p); S->invnu = QXQ_inv(S->nu, S->chi); S->invnu = redelt_i(S->invnu, S->psc, S->p, &S->Dinvnu, &S->vDinvnu); } if (S->Dinvnu) { Dg = mulii(Dg, powiu(S->Dinvnu, er)); vDg += er * S->vDinvnu; } q = mulii(S->p, Dg); g = ZX_mul(g, FpXQ_powu(S->invnu, er, S->chi, q)); g = FpX_rem(g, S->chi, q); update_den(S->p, &g, &Dg, &vDg, NULL); g = centermod(g, mulii(S->p, Dg)); } if (!is_pm1(Dg)) g = RgX_Rg_div(g, Dg); return g; } static GEN get_g(decomp_t *S, long Ea, long L, long E, GEN beta, GEN *pchig, long *peq, long *per) { long eq, er; GEN g, chig, chib = NULL; for(;;) /* at most twice */ { if (L < 0) { chib = ZXQ_charpoly(beta, S->chi, varn(S->chi)); vstar(S->p, chib, &L, &E); } eq = L / E; er = L*Ea / E - eq*Ea; /* floor(L Ea/E) = eq Ea + er */ if (er || !chib) { /* g might not be an integer ==> chig = NULL */ g = get_gamma(S, beta, eq, er); chig = mycaract(S, S->chi, g, S->psc, S->prc); } else { /* g = beta/p^eq, special case of the above */ GEN h = powiu(S->p, eq); g = RgX_Rg_div(beta, h); chig = ZX_rescale_inv(chib, h); /* chib(x h) / h^N */ if (chig) chig = FpX_red(chig, S->pmf); } /* either success or second consecutive failure */ if (chig || chib) break; /* if g fails the v*-test, v(beta) was wrong. Retry once */ L = -1; } *pchig = chig; *peq = eq; *per = er; return g; } /* return 1 if at least 2 factors mod p ==> chi can be split */ static int loop(decomp_t *S, long Ea) { pari_sp av = avma; GEN beta = FpXQ_powu(S->nu, Ea, S->chi, S->p); long N = degpol(S->f), v = varn(S->f); S->invnu = NULL; for (;;) { /* beta tends to a factor of chi */ long L, i, Fg, eq, er; GEN chig = NULL, d, g, nug; if (DEBUGLEVEL>4) err_printf(" beta = %Ps\n", beta); L = ZpX_resultant_val(S->chi, beta, S->p, S->mf+1); if (L > S->mf) L = -1; /* from scratch */ g = get_g(S, Ea, L, N, beta, &chig, &eq, &er); if (DEBUGLEVEL>4) err_printf(" (eq,er) = (%ld,%ld)\n", eq,er); /* g = beta p^-eq nu^-er (a unit), chig = charpoly(g) */ if (split_char(S, chig, g,S->phi, &nug)) return 1; Fg = degpol(nug); if (Fg == 1) { /* frequent special case nug = x - d */ long Le, Ee; GEN chie, nue, e, pie; d = negi(gel(nug,2)); chie = RgX_translate(chig, d); nue = pol_x(v); e = RgX_Rg_sub(g, d); pie = getprime(S, e, chie, nue, &Le, &Ee, 0,Ea); if (pie) return testc2(S, S->nu, Ea, pie, Ee); } else { long Fa = degpol(S->nu), vdeng; GEN deng, numg, nume; if (Fa % Fg) return testb2(S, ulcm(Fa,Fg), g); /* nu & nug irreducible mod p, deg nug | deg nu. To improve beta, look * for a root d of nug in Fp[phi] such that v_p(g - d) > 0 */ if (ZX_equal(nug, S->nu)) d = pol_x(v); else { if (!p_is_prime(S)) pari_err_PRIME("FpX_ffisom",S->p); d = FpX_ffisom(nug, S->nu, S->p); } /* write g = numg / deng, e = nume / deng */ numg = QpX_remove_denom(g, S->p, &deng, &vdeng); for (i = 1; i <= Fg; i++) { GEN chie, nue, e; if (i != 1) d = FpXQ_pow(d, S->p, S->nu, S->p); /* next root */ nume = ZX_sub(numg, ZX_Z_mul(d, deng)); /* test e = nume / deng */ if (ZpX_resultant_val(S->chi, nume, S->p, vdeng*N+1) <= vdeng*N) continue; e = RgX_Rg_div(nume, deng); chie = mycaract(S, S->chi, e, S->psc, S->prc); if (split_char(S, chie, e,S->phi, &nue)) return 1; if (RgX_is_monomial(nue)) { /* v_p(e) = v_p(g - d) > 0 */ long Le, Ee; GEN pie; pie = getprime(S, e, chie, nue, &Le, &Ee, 0,Ea); if (pie) return testc2(S, S->nu, Ea, pie, Ee); break; } } if (i > Fg) { if (!p_is_prime(S)) pari_err_PRIME("nilord",S->p); pari_err_BUG("nilord (no root)"); } } if (eq) d = gmul(d, powiu(S->p, eq)); if (er) d = gmul(d, gpowgs(S->nu, er)); beta = gsub(beta, d); if (gc_needed(av,1)) { if (DEBUGMEM > 1) pari_warn(warnmem, "nilord"); gerepileall(av, S->invnu? 6: 4, &beta, &(S->precns), &(S->ns), &(S->nsf), &(S->invnu), &(S->Dinvnu)); } } } /* E and F cannot decrease; return 1 if O = Zp[phi], 2 if we can get a * decomposition and 0 otherwise */ static long progress(decomp_t *S, GEN *ppa, long *pE) { long E = *pE, F; GEN pa = *ppa; S->phi0 = NULL; /* no delayed composition */ for(;;) { long l, La, Ea; /* N.B If E = 0, getprime cannot return NULL */ GEN pia = getprime(S, NULL, S->chi, S->nu, &La, &Ea, E,0); if (pia) { /* success, we break out in THIS loop */ pa = (typ(pia) == t_POL)? RgX_RgXQ_eval(pia, S->phi, S->f): pia; E = Ea; if (La == 1) break; /* no need to change phi so that nu = pia */ } /* phi += prime elt */ S->phi = typ(pa) == t_INT? RgX_Rg_add_shallow(S->phi, pa) : RgX_add(S->phi, pa); /* recompute char. poly. chi from scratch */ S->chi = mycaract(S, S->f, S->phi, S->psf, S->pdf); S->nu = get_nu(S->chi, S->p, &l); if (l > 1) return 2; if (!update_phi(S)) return 1; /* unramified */ if (pia) break; } *pE = E; *ppa = pa; F = degpol(S->nu); if (DEBUGLEVEL>4) err_printf(" (E, F) = (%ld,%ld)\n", E, F); if (E * F == degpol(S->f)) return 1; if (loop(S, E)) return 2; if (!update_phi(S)) return 1; return 0; } /* flag != 0 iff we're looking for the p-adic factorization, in which case it is the p-adic precision we want */ static GEN maxord_i(decomp_t *S, GEN p, GEN f, long mf, GEN w, long flag) { long oE, n = lg(w)-1; /* factor of largest degree */ GEN opa, D = ZpX_reduced_resultant_fast(f, ZX_deriv(f), p, mf); S->pisprime = -1; S->p = p; S->mf = mf; S->nu = gel(w,n); S->df = Z_pval(D, p); S->pdf = powiu(p, S->df); S->phi = pol_x(varn(f)); S->chi = S->f = f; if (n > 1) return Decomp(S, flag); /* FIXME: use bezout_lift_fact */ if (DEBUGLEVEL>4) err_printf(" entering Nilord: %Ps^%ld\n f = %Ps, nu = %Ps\n", p, S->df, S->f, S->nu); else if (DEBUGLEVEL>2) err_printf(" entering Nilord\n"); S->psf = S->psc = mulii(sqri(D), p); S->vpsf = S->vpsc = 2*S->df + 1; S->prc = mulii(D, p); S->chi = FpX_red(S->f, S->psc); S->pmf = powiu(p, S->mf+1); S->precns = NULL; for(opa = NULL, oE = 0;;) { long n = progress(S, &opa, &oE); if (n == 1) return flag? NULL: dbasis(p, S->f, S->mf, S->phi, S->chi); if (n == 2) return Decomp(S, flag); } } static int expo_is_squarefree(GEN e) { long i, l = lg(e); for (i=1; i 0. Return list of * irreducible factors in Zp[X] (computed mod p^prec) */ static GEN ZpX_monic_factor_squarefree(GEN f, GEN p, long prec) { pari_sp av = avma; GEN L, fa, w, e; long i, l; if (degpol(f) == 1) return mkvec(f); fa = FpX_factor(f,p); w = gel(fa,1); e = gel(fa,2); /* no repeated factors: Hensel lift */ if (expo_is_squarefree(e)) return ZpX_liftfact(f, w, powiu(p,prec), p, prec); l = lg(w); if (l == 2) { L = ZpX_round4(f,p,w,prec); if (lg(L) == 2) { set_avma(av); return mkvec(f); } } else { /* >= 2 factors mod p: partial Hensel lift */ GEN D = ZpX_reduced_resultant_fast(f, ZX_deriv(f), p, ZpX_disc_val(f,p)); long r = maxss(2*Z_pval(D,p)+1, prec); GEN W = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(W,i) = e[i] == 1? gel(w,i): FpX_powu(gel(w,i), e[i], p); L = ZpX_liftfact(f, W, powiu(p,r), p, r); for (i = 1; i < l; i++) gel(L,i) = e[i] == 1? mkvec(gel(L,i)) : ZpX_round4(gel(L,i), p, mkvec(gel(w,i)), prec); L = shallowconcat1(L); } return gerepilecopy(av, L); } /* assume T a ZX with leading_coeff 1, degree > 0 */ GEN ZpX_monic_factor(GEN T, GEN p, long prec) { GEN Q, P, E, F; long L, l, i, v; if (degpol(T) == 1) return mkmat2(mkcol(T), mkcol(gen_1)); v = ZX_valrem(T, &T); Q = ZX_squff(T, &F); l = lg(Q); L = v? l + 1: l; P = cgetg(L, t_VEC); E = cgetg(L, t_VEC); for (i = 1; i < l; i++) { GEN w = ZpX_monic_factor_squarefree(gel(Q,i), p, prec); gel(P,i) = w; settyp(w, t_COL); gel(E,i) = const_col(lg(w)-1, utoipos(F[i])); } if (v) { gel(P,i) = pol_x(varn(T)); gel(E,i) = utoipos(v); } return mkmat2(shallowconcat1(P), shallowconcat1(E)); } /* 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, U, res = gen_1, dT = ZX_deriv(T); if (!DT) DT = ZX_disc(T); fa = absZ_factor_limit_strict(DT, 0, &U); 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 (e2 >= 2) q = ZpX_reduced_resultant_fast(T, dT, p, e2); res = mulii(res, q); } if (U) { long e = itou(gel(U,2)), e2 = e >> 1; GEN p = gel(U,1), q = powiu(p, odd(e)? e2+1: e2); res = mulii(res, q); } return gerepileuptoint(av,res); } /*******************************************************************/ /* */ /* 2-ELT REPRESENTATION FOR PRIME IDEALS (dividing index) */ /* */ /*******************************************************************/ /* to compute norm of elt in basis form */ typedef struct { long r1; GEN M; /* via embed_norm */ GEN D, w, T; /* via resultant if M = NULL */ } norm_S; static GEN get_norm(norm_S *S, GEN a) { if (S->M) { long e; GEN N = grndtoi( embed_norm(RgM_RgC_mul(S->M, a), S->r1), &e ); if (e > -5) pari_err_PREC( "get_norm"); return N; } if (S->w) a = RgV_RgC_mul(S->w, a); return ZX_resultant_all(S->T, a, S->D, 0); } static void init_norm(norm_S *S, GEN nf, GEN p) { GEN T = nf_get_pol(nf), M = nf_get_M(nf); long N = degpol(T), ex = gexpo(M) + gexpo(mului(8 * N, p)); S->r1 = nf_get_r1(nf); if (N * ex <= gprecision(M) - 20) { /* enough prec to use embed_norm */ S->M = M; S->D = NULL; S->w = NULL; S->T = NULL; } else { GEN w = leafcopy(nf_get_zkprimpart(nf)), D = nf_get_zkden(nf), Dp = sqri(p); long i; if (!equali1(D)) { 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->M = NULL; 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 !dvdii(get_norm(S,a), q); } /* 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_i(x, y, p); } /* Fp-basis of (ZK/pr): applied to the primes found in primedec_aux() * true nf */ 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 = pr_hnf(nf, pr); l = lg(x); y = cgetg(l, t_MAT); for (i=j=1; i=2; i--) gel(B,i-1) = mul_intersect(gel(B,i), gel(LW,i), p); for (i=1; i<=l; i++) gel(LV,i) = mul_intersect(gel(A,i), gel(B,i), p); return LV; } static void errprime(GEN p) { pari_err_PRIME("idealprimedec",p); } /* P = Fp-basis (over O_K/p) for pr. * V = Z-basis for I_p/pr. ramif != 0 iff some pr|p is ramified. * Return a p-uniformizer for pr. Assume pr not inert, i.e. m > 0 */ static GEN uniformizer(GEN nf, norm_S *S, GEN P, GEN V, GEN p, int ramif) { long i, l, f, m = lg(P)-1, N = nf_get_degree(nf); GEN u, Mv, x, q; f = N - m; /* we want v_p(Norm(x)) = p^f */ q = powiu(p,f+1); u = FpM_FpC_invimage(shallowconcat(P, V), col_ei(N,1), p); setlg(u, lg(P)); u = centermod(ZM_ZC_mul(P, u), p); if (is_uniformizer(u, q, S)) return u; if (signe(gel(u,1)) <= 0) /* make sure u[1] in ]-p,p] */ gel(u,1) = addii(gel(u,1), p); /* try u + p */ else gel(u,1) = subii(gel(u,1), p); /* try u - p */ if (!ramif || is_uniformizer(u, q, S)) return u; /* P/p ramified, u in P^2, not in Q for all other Q|p */ Mv = zk_multable(nf, Z_ZC_sub(gen_1,u)); l = lg(P); for (i=1; i1) */ GEN cw, w = Q_primitive_part(nf_to_scalar_or_alg(nf, u), &cw); long v = cw? f - Q_pval(cw, p) * N: f; if (ZpX_resultant_val(T, w, p, v + 1) > v) { GEN c = gel(u,1); gel(u,1) = signe(c) > 0? subii(c, p): addii(c, p); } } t = zk_multable(nf, t); } return mk_pr(p,u,e,f,t); } 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); } /* nf a true nf; compute lift(nf.zk[I]^p mod p) */ static GEN pow_ei_mod_p(GEN nf, long I, GEN p) { pari_sp av = avma; eltmod_muldata D; long N = nf_get_degree(nf); GEN y = col_ei(N,I); if (I == 1) return y; D.nf = nf; D.p = p; D.I = I; y = gen_pow_fold(y, p, (void*)&D, &sqr_mod, &ei_msqr_mod); return gerepileupto(av,y); } /* nf a true nf; 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); m = frob; q = p; while (abscmpiu(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) = subiu(gcoeff(frob,i,i), 1); *phi = frob; return rad; } /* return powers of a: a^0, ... , a^d, d = dim A */ static GEN get_powers(GEN mul, GEN p) { long i, d = lgcols(mul); GEN z, pow = cgetg(d+2,t_MAT), P = pow+1; gel(P,0) = scalarcol_shallow(gen_1, d-1); z = gel(mul,1); for (i=1; i<=d; i++) { gel(P,i) = z; /* a^i */ if (i!=d) z = FpM_FpC_mul(mul, z, p); } return pow; } /* minimal polynomial of a in A (dim A = d). * mul = multiplication table by a in A */ static GEN pol_min(GEN mul, GEN p) { pari_sp av = avma; GEN z = FpM_deplin(get_powers(mul, p), p); return gerepilecopy(av, RgV_to_RgX(z,0)); } static GEN get_pr(GEN nf, norm_S *S, GEN p, GEN P, GEN V, int ramif, long N, long flim) { GEN u, t; long e, f; if (typ(P) == t_VEC) { /* already done (Kummer) */ f = pr_get_f(P); if (flim > 0 && f > flim) return NULL; if (flim == -2) return (GEN)f; return P; } f = N - (lg(P)-1); if (flim > 0 && f > flim) return NULL; if (flim == -2) return (GEN)f; /* P = (p,u) prime. t is an anti-uniformizer: Z_K + t/p Z_K = P^(-1), * so that v_P(t) = e(P/p)-1 */ if (f == N) { u = scalarcol_shallow(p,N); t = gen_1; e = 1; } else { GEN mt; u = uniformizer(nf, S, P, V, p, ramif); t = FpM_deplin(zk_multable(nf,u), p); mt = zk_multable(nf, t); e = ramif? 1 + ZC_nfval(t,mk_pr(p,u,0,0,mt)): 1; t = mt; } return mk_pr(p,u,e,f,t); } /* true nf */ static GEN primedec_end(GEN nf, GEN L, GEN p, long flim) { long i, j, l = lg(L), N = nf_get_degree(nf); 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 = j = 1; i < l; i++) { GEN P = get_pr(nf, &S, p, gel(L,i), gel(LV,i), ramif, N, flim); if (!P) continue; gel(L,j++) = P; if (flim == -1) return P; } setlg(L, j); return L; } /* prime ideal decomposition of p; if flim>0, restrict to f(P,p) <= flim * if flim = -1 return only the first P * if flim = -2 return only the f(P/p) in a t_VECSMALL; true nf */ static GEN primedec_aux(GEN nf, GEN p, long flim) { const long TYP = (flim == -2)? t_VECSMALL: t_VEC; GEN E, F, L, Ip, phi, f, g, h, UN, T = nf_get_pol(nf); long i, k, c, iL, N; int kummer; 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, TYP); for (i=1; i 0 && f > flim) { setlg(L, i); break; } if (flim == -2) L[i] = f; else gel(L,i) = idealprimedec_kummer(nf, t, E[i],p); if (flim == -1) return gel(L,1); } return L; } kummer = 0; g = FpXV_prod(F, p); h = FpX_div(T,g,p); f = FpX_red(ZX_Z_divexact(ZX_sub(ZX_mul(g,h), T), p), p); N = degpol(T); L = cgetg(N+1,TYP); iL = 1; 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 (kummer) { /* split off Kummer factors */ GEN mb, b = NULL; for (i=1; i M2 * Mi2 projector A --> A2 */ GEN M, Mi, M2, Mi2, phi2, mat1, H = gel(h,c); /* maximal rank */ long dim, r = lg(H)-1; M = FpM_suppl(shallowconcat(H,UN), p); Mi = FpM_inv(M, p); M2 = vecslice(M, r+1,N); /* M = (H|M2) invertible */ Mi2 = rowslice(Mi,r+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, a not in Fp.1 + H */ GEN R, a, mula, mul2, v = gel(mat1,2); long n; a = FpM_FpC_mul(M2,v, p); /* not a scalar */ mula = FpM_red(zk_multable(nf,a), 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 I = RgM_Rg_sub_shallow(mula, gel(R,i)); gel(h,c++) = FpM_image(shallowconcat(H, I), p); } if (n == dim) for (i=1; i<=n; i++) gel(L,iL++) = gel(h,--c); } else /* A2 field ==> H maximal, f = N-r = dim(A2) */ gel(L,iL++) = H; } setlg(L, iL); return primedec_end(nf, L, p, flim); } GEN idealprimedec_limit_f(GEN nf, GEN p, long f) { pari_sp av = avma; GEN v; if (typ(p) != t_INT) pari_err_TYPE("idealprimedec",p); if (f < 0) pari_err_DOMAIN("idealprimedec", "f", "<", gen_0, stoi(f)); v = primedec_aux(checknf(nf), p, f); v = gen_sort(v, (void*)&cmp_prime_over_p, &cmp_nodata); return gerepileupto(av,v); } /* true nf */ GEN idealprimedec_galois(GEN nf, GEN p) { pari_sp av = avma; GEN v = primedec_aux(nf, p, -1); return gerepilecopy(av,v); } /* true nf */ GEN idealprimedec_degrees(GEN nf, GEN p) { pari_sp av = avma; GEN v = primedec_aux(nf, p, -2); vecsmall_sort(v); return gerepileuptoleaf(av, v); } GEN idealprimedec_limit_norm(GEN nf, GEN p, GEN B) { return idealprimedec_limit_f(nf, p, logint(B,p)); } GEN idealprimedec(GEN nf, GEN p) { return idealprimedec_limit_f(nf, p, 0); } GEN nf_pV_to_prV(GEN nf, GEN P) { long i, l; GEN Q = cgetg_copy(P,&l); if (l == 1) return Q; for (i = 1; i < l; i++) gel(Q,i) = idealprimedec(nf, gel(P,i)); return shallowconcat1(Q); } /* return [Fp[x]: Fp] */ static long ffdegree(GEN x, GEN frob, GEN p) { pari_sp av = avma; long d, f = lg(frob)-1; GEN y = x; for (d=1; d < f; d++) { y = FpM_FpC_mul(frob, y, p); if (ZV_equal(y, x)) break; } return gc_long(av,d); } static GEN lift_to_zk(GEN v, GEN c, long N) { GEN w = zerocol(N); long i, l = lg(c); for (i=1; i= e(Q/p) for other Q | p */ z = ZM_hnfmodid(FpM_red(b,p), p); /* ideal (p) / pr^e, coprime to pr */ z = idealaddtoone_raw(nf, pr, z); return Z_ZC_sub(gen_1, FpC_center(FpC_red(z,p), p, shifti(p,-1))); } #define mpr_TAU 1 #define mpr_FFP 2 #define mpr_NFP 5 #define SMALLMODPR 4 #define LARGEMODPR 6 static GEN modpr_TAU(GEN modpr) { GEN tau = gel(modpr,mpr_TAU); return isintzero(tau)? NULL: tau; } /* prh = HNF matrix, which is identity but for the first line. Return a * projector to ZK / prh ~ Z/prh[1,1] */ GEN dim1proj(GEN prh) { long i, N = lg(prh)-1; GEN ffproj = cgetg(N+1, t_VEC); GEN x, q = gcoeff(prh,1,1); gel(ffproj,1) = gen_1; for (i=2; i<=N; i++) { x = gcoeff(prh,1,i); if (signe(x)) x = subii(q,x); gel(ffproj,i) = x; } return ffproj; } /* p not necessarily prime, but coprime to denom(basis) */ GEN QXQV_to_FpM(GEN basis, GEN T, GEN p) { long i, l = lg(basis), f = degpol(T); GEN z = cgetg(l, t_MAT); for (i = 1; i < l; i++) { GEN w = gel(basis,i); if (typ(w) == t_INT) w = scalarcol_shallow(w, f); else { GEN dx; w = Q_remove_denom(w, &dx); w = FpXQ_red(w, T, p); if (dx) { dx = Fp_inv(dx, p); if (!equali1(dx)) w = FpX_Fp_mul(w, dx, p); } w = RgX_to_RgC(w, f); } gel(z,i) = w; /* w_i mod (T,p) */ } return z; } /* initialize reduction mod pr; if zk = 1, will only init data required to * reduce *integral* element. Realize (O_K/pr) as Fp[X] / (T), for a * *monic* T; use variable vT for varn(T) */ static GEN modprinit(GEN nf, GEN pr, int zk, long vT) { pari_sp av = avma; GEN res, tau, mul, x, p, T, pow, ffproj, nfproj, prh, c; long N, i, k, f; nf = checknf(nf); checkprid(pr); if (vT < 0) vT = nf_get_varn(nf); f = pr_get_f(pr); N = nf_get_degree(nf); prh = pr_hnf(nf, pr); tau = zk? gen_0: anti_uniformizer(nf, pr); p = pr_get_p(pr); if (f == 1) { res = cgetg(SMALLMODPR, t_COL); gel(res,mpr_TAU) = tau; gel(res,mpr_FFP) = dim1proj(prh); gel(res,3) = pr; return gerepilecopy(av, res); } c = cgetg(f+1, t_VECSMALL); ffproj = cgetg(N+1, t_MAT); for (k=i=1; i<=N; i++) { x = gcoeff(prh, i,i); if (!is_pm1(x)) { c[k] = i; gel(ffproj,i) = col_ei(N, i); k++; } else gel(ffproj,i) = ZC_neg(gel(prh,i)); } ffproj = rowpermute(ffproj, c); if (! dvdii(nf_get_index(nf), p)) { GEN basis = nf_get_zkprimpart(nf), D = nf_get_zkden(nf); if (N == f) { /* pr inert */ T = nf_get_pol(nf); T = FpX_red(T,p); ffproj = RgV_to_RgM(basis, lg(basis)-1); } else { T = RgV_RgC_mul(basis, pr_get_gen(pr)); T = FpX_normalize(FpX_red(T,p),p); basis = FqV_red(vecpermute(basis,c), T, p); basis = RgV_to_RgM(basis, lg(basis)-1); ffproj = ZM_mul(basis, ffproj); } setvarn(T, vT); ffproj = FpM_red(ffproj, p); if (!equali1(D)) { D = modii(D,p); if (!equali1(D)) ffproj = FpM_Fp_mul(ffproj, Fp_inv(D,p), p); } res = cgetg(SMALLMODPR+1, t_COL); gel(res,mpr_TAU) = tau; gel(res,mpr_FFP) = ffproj; gel(res,3) = pr; gel(res,4) = T; return gerepilecopy(av, res); } if (uisprime(f)) { mul = ei_multable(nf, c[2]); mul = vecpermute(mul, c); } else { GEN v, u, u2, frob; long deg,deg1,deg2; /* matrix of Frob: x->x^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); 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 = ulcm(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), vT); nfproj = cgetg(f+1, t_MAT); for (i=1; i<=f; i++) gel(nfproj,i) = lift_to_zk(gel(pow,i), c, N); 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,3) = pr; gel(res,4) = T; gel(res,mpr_NFP) = nfproj; return gerepilecopy(av, res); } GEN nfmodprinit(GEN nf, GEN pr) { return modprinit(nf, pr, 0, -1); } GEN zkmodprinit(GEN nf, GEN pr) { return modprinit(nf, pr, 1, -1); } GEN nfmodprinit0(GEN nf, GEN pr, long v) { return modprinit(nf, pr, 0, v); } /* x may be a modpr */ static int ok_modpr(GEN x) { return typ(x) == t_COL && lg(x) >= SMALLMODPR && lg(x) <= LARGEMODPR; } void checkmodpr(GEN x) { if (!ok_modpr(x)) pari_err_TYPE("checkmodpr [use nfmodprinit]", x); checkprid(modpr_get_pr(x)); } GEN get_modpr(GEN x) { return ok_modpr(x)? x: NULL; } int checkprid_i(GEN x) { return (typ(x) == t_VEC && lg(x) == 6 && typ(gel(x,2)) == t_COL && typ(gel(x,3)) == t_INT && typ(gel(x,5)) != t_COL); /* tau changed to t_MAT/t_INT in 2.6 */ } void checkprid(GEN x) { if (!checkprid_i(x)) pari_err_TYPE("checkprid",x); } GEN get_prid(GEN x) { long lx = lg(x); if (lx == 3 && typ(x) == t_VEC) x = gel(x,1); if (checkprid_i(x)) return x; if (ok_modpr(x)) { x = modpr_get_pr(x); if (checkprid_i(x)) return x; } return NULL; } static GEN to_ff_init(GEN nf, GEN *pr, GEN *T, GEN *p, int zk) { GEN modpr = ok_modpr(*pr)? *pr: modprinit(nf, *pr, zk, -1); *T = modpr_get_T(modpr); *pr = modpr_get_pr(modpr); *p = pr_get_p(*pr); return modpr; } /* Return an element of O_K which is set to x Mod T */ 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( modpr_get_T(modpr) ); 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_uniformizer(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 = modpr_get_pr(modpr), p = pr_get_p(pr); GEN ffproj = gel(modpr,mpr_FFP); GEN T = modpr_get_T(modpr); return T? FpM_FpC_mul_FpX(ffproj,x, p, varn(T)): FpV_dotproduct(ffproj,x, p); } /* REDUCTION Modulo a prime ideal */ /* nf a true nf */ static GEN Rg_to_ff(GEN nf, GEN x0, GEN modpr) { GEN x = x0, den, pr = modpr_get_pr(modpr), p = pr_get_p(pr); long tx = typ(x); if (tx == t_POLMOD) { x = gel(x,2); tx = typ(x); } switch(tx) { case t_INT: return modii(x, p); case t_FRAC: return Rg_to_Fp(x, p); case t_POL: switch(lg(x)) { case 2: return gen_0; case 3: return Rg_to_Fp(gel(x,2), p); } x = Q_remove_denom(x, &den); x = poltobasis(nf, x); /* content(x) and den may not be coprime */ break; case t_COL: x = Q_remove_denom(x, &den); /* content(x) and den are coprime */ if (lg(x)-1 == nf_get_degree(nf)) break; default: pari_err_TYPE("Rg_to_ff",x); return NULL;/*LCOV_EXCL_LINE*/ } if (den) { long v = Z_pvalrem(den, p, &den); if (v) { if (tx == t_POL) v -= ZV_pvalrem(x, p, &x); /* now v = valuation(true denominator of x) */ if (v > 0) { GEN tau = modpr_TAU(modpr); if (!tau) pari_err_TYPE("zk_to_ff", x0); x = nfmuli(nf,x, nfpow_u(nf, tau, v)); v -= ZV_pvalrem(x, p, &x); } if (v > 0) pari_err_INV("Rg_to_ff", mkintmod(gen_0,p)); if (v) return gen_0; if (is_pm1(den)) den = NULL; } x = FpC_red(x, p); } x = zk_to_Fq(x, modpr); if (den) { GEN c = Fp_inv(den, p); x = typ(x) == t_INT? Fp_mul(x,c,p): FpX_Fp_mul(x,c,p); } return x; } GEN nfreducemodpr(GEN nf, GEN x, GEN modpr) { pari_sp av = avma; nf = checknf(nf); checkmodpr(modpr); return gerepileupto(av, algtobasis(nf, Fq_to_nf(Rg_to_ff(nf,x,modpr),modpr))); } GEN nfmodpr(GEN nf, GEN x, GEN pr) { pari_sp av = avma; GEN T, p, modpr; nf = checknf(nf); modpr = nf_to_Fq_init(nf, &pr, &T, &p); if (typ(x) == t_MAT && lg(x) == 3) { GEN y, v = famat_nfvalrem(nf, x, pr, &y); long s = signe(v); if (s < 0) pari_err_INV("Rg_to_ff", mkintmod(gen_0,p)); if (s > 0) return gc_const(av, gen_0); x = FqV_factorback(nfV_to_FqV(gel(y,1), nf, modpr), gel(y,2), T, p); return gerepileupto(av, x); } x = Rg_to_ff(nf, x, modpr); x = Fq_to_FF(x, Tp_to_FF(T,p)); return gerepilecopy(av, x); } GEN nfmodprlift(GEN nf, GEN x, GEN pr) { pari_sp av = avma; GEN y, T, p, modpr; long i, l, d; nf = checknf(nf); switch(typ(x)) { case t_INT: return icopy(x); case t_FFELT: break; case t_VEC: case t_COL: case t_MAT: y = cgetg_copy(x,&l); for (i = 1; i < l; i++) gel(y,i) = nfmodprlift(nf,gel(x,i),pr); return y; default: pari_err_TYPE("nfmodprlit",x); } x = FF_to_FpXQ(x); setvarn(x, nf_get_varn(nf)); d = degpol(x); if (d <= 0) { set_avma(av); return d? gen_0: icopy(gel(x,2)); } modpr = nf_to_Fq_init(nf, &pr, &T, &p); return gerepilecopy(av, Fq_to_nf(x, modpr)); } /* lift A from residue field to nf */ GEN Fq_to_nf(GEN A, GEN modpr) { long dA; if (typ(A) == t_INT || lg(modpr) < LARGEMODPR) return A; dA = degpol(A); if (dA <= 0) return dA ? gen_0: gel(A,2); return ZM_ZX_mul(gel(modpr,mpr_NFP), A); } GEN FqV_to_nfV(GEN x, GEN modpr) { pari_APPLY_same(Fq_to_nf(gel(x,i), modpr)) } GEN FqM_to_nfM(GEN A, GEN modpr) { long i,j,h,l = lg(A); GEN B = cgetg(l, t_MAT); if (l == 1) return B; h = lgcols(A); for (j=1; j= db) { long i, k = da; GEN A = gel(a, k+2); for (i = db-1, k--; i >= 0; i--, k--) gel(a,k+2) = nfsub(nf, gel(a,k+2), nfmul(nf, A, gel(b,i+2))); a = normalizepol_lg(a, lg(a)-1); da = degpol(a); } return a; } static GEN nfXQ_mul(GEN nf, GEN a, GEN b, GEN T) { GEN c = nfX_mul(nf, a, b); if (typ(c) != t_POL) return c; return nfX_rem(nf, c, T); } static void fill(long l, GEN H, GEN Hx, GEN I, GEN Ix) { long i; if (typ(Ix) == t_VEC) /* standard */ for (i=1; imultab,x) : tablemul_ei_ej(D->multab,D->h,D->h); return FqV_red(z,D->T,D->p); } static GEN _msqr(void *data, GEN x) { GEN x2 = _sqr(data, x), z; rnfeltmod_muldata *D = (rnfeltmod_muldata *) data; z = tablemul_ei(D->multab, x2, D->h); return FqV_red(z,D->T,D->p); } /* Compute W[h]^n mod (T,p) in the extension, assume n >= 0. T a ZX */ static GEN rnfeltid_powmod(GEN multab, long h, GEN n, GEN T, GEN p) { pari_sp av = avma; GEN y; rnfeltmod_muldata D; if (!signe(n)) return gen_1; D.multab = multab; D.h = h; D.T = T; D.p = p; y = gen_pow_fold(NULL, n, (void*)&D, &_sqr, &_msqr); return gerepilecopy(av, y); } /* P != 0 has at most degpol(P) roots. Look for an element in Fq which is not * a root, cf repres() */ static GEN FqX_non_root(GEN P, GEN T, GEN p) { long dP = degpol(P), f, vT; long i, j, k, pi, pp; GEN v; if (dP == 0) return gen_1; pp = is_bigint(p) ? dP+1: itos(p); v = cgetg(dP + 2, t_VEC); gel(v,1) = gen_0; if (T) { f = degpol(T); vT = varn(T); } else { f = 1; vT = 0; } for (i=pi=1; i<=f; i++,pi*=pp) { GEN gi = i == 1? gen_1: pol_xn(i-1, vT), jgi = gi; for (j=1; j only_maximal = 1 */ { if (mpr < 0) return NULL; if (! RgX_valrem(Ppr, &Ppr)) { /* nonzero constant coefficient */ Ppr = RgX_shift_shallow(RgX_recip_i(Ppr), m - mpr); P = RgX_recip_i(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_i(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(" pass no %ld\n",cnt); for (j=1; j<=n; j++) { GEN tau, tauinv; if (ideal_is1(gel(I,j))) { gel(I,j) = gel(Tau,j) = gel(Tauinv,j) = gen_1; continue; } gel(Tau,j) = tau = minval(nf, gel(I,j), pr); gel(Tauinv,j) = tauinv = nfinv(nf, tau); gel(W,j) = nfC_nf_mul(nf, gel(W,j), tau); gel(I,j) = idealmul(nf, tauinv, gel(I,j)); /* v_pr(I[j]) = 0 */ } /* W = (Z_K/pr)-basis of O/pr. O = (W0,I0) ~ (W, I) */ /* compute MW: W_i*W_j = sum MW_k,(i,j) W_k */ Wa = RgM_to_RgXV(W,vpol); Winv = nfM_inv(nf, W); MW = cgetg(nn+1, t_MAT); /* W_1 = 1 */ for (j=1; j<=n; j++) gel(MW, j) = gel(MW, (j-1)*n+1) = gel(Id,j); for (i=2; i<=n; i++) for (j=i; j<=n; j++) { GEN z = nfXQ_mul(nf, gel(Wa,i), gel(Wa,j), pol); if (typ(z) != t_POL) z = nfC_nf_mul(nf, gel(Winv,1), z); else { z = RgX_to_RgC(z, lg(Winv)-1); z = nfM_nfC_mul(nf, Winv, z); } gel(MW, (i-1)*n+j) = gel(MW, (j-1)*n+i) = z; } /* compute Ip = pr-radical [ could use Ker(trace) if q large ] */ MWmod = nfM_to_FqM(MW,nf,modpr); F = cgetg(n+1, t_MAT); gel(F,1) = gel(Id,1); for (j=2; j<=n; j++) gel(F,j) = rnfeltid_powmod(MWmod, j, q1, T,p); Ip = FqM_ker(F,T,p); if (lg(Ip) == 1) { W = W0; I = I0; break; } /* Fill C: W_k A_j = sum_i C_(i,j),k A_i */ A = FqM_to_nfM(FqM_suppl(Ip,T,p), modpr); for (j = lg(Ip); j<=n; j++) gel(A,j) = nfC_multable_mul(gel(A,j), mpi); MW = nfM_mul(nf, nfM_inv(nf,A), MW); C = cgetg(n+1, t_MAT); for (k=1; k<=n; k++) { GEN mek = vecslice(MW, (k-1)*n+1, k*n), Ck; gel(C,k) = Ck = cgetg(nn+1, t_COL); for (j=1; j<=n; j++) { GEN z = nfM_nfC_mul(nf, mek, gel(A,j)); for (i=1; i<=n; i++) gel(Ck, (j-1)*n+i) = nf_to_Fq(nf,gel(z,i),modpr); } } G = FqM_to_nfM(FqM_ker(C,T,p), modpr); pseudo = rnfjoinmodules_i(nf, G,prhinv, Id,I); /* express W in terms of the power basis */ W = nfM_mul(nf, W, gel(pseudo,1)); I = gel(pseudo,2); /* restore the HNF property W[i,i] = 1. NB: W upper triangular, with * W[i,i] = Tau[i] */ for (j=1; j<=n; j++) if (gel(Tau,j) != gen_1) { gel(W,j) = nfC_nf_mul(nf, gel(W,j), gel(Tauinv,j)); gel(I,j) = idealmul(nf, gel(Tau,j), gel(I,j)); } if (DEBUGLEVEL>3) err_printf(" new order:\n%Ps\n%Ps\n", W, I); if (sep <= 3 || gequal(I,I0)) break; if (gc_needed(av1,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"rnfmaxord"); gerepileall(av1,2, &W,&I); } } return gerepilecopy(av, mkvec2(W, I)); } GEN Rg_nffix(const char *f, GEN T, GEN c, int lift) { switch(typ(c)) { case t_INT: case t_FRAC: return c; case t_POL: if (lg(c) >= lg(T)) c = RgX_rem(c,T); break; case t_POLMOD: if (!RgX_equal_var(gel(c,1), T)) pari_err_MODULUS(f, gel(c,1),T); c = gel(c,2); switch(typ(c)) { case t_POL: break; case t_INT: case t_FRAC: return c; default: pari_err_TYPE(f, c); } break; default: pari_err_TYPE(f,c); } /* typ(c) = t_POL */ if (varn(c) != varn(T)) pari_err_VAR(f, c,T); switch(lg(c)) { case 2: return gen_0; case 3: c = gel(c,2); if (is_rational_t(typ(c))) return c; pari_err_TYPE(f,c); } RgX_check_QX(c, f); return lift? c: mkpolmod(c, T); } /* check whether P is a polynomials with coeffs in number field Q[y]/(T) */ GEN RgX_nffix(const char *f, GEN T, GEN P, int lift) { long i, l, vT = varn(T); GEN Q = cgetg_copy(P, &l); if (typ(P) != t_POL) pari_err_TYPE(stack_strcat(f," [t_POL expected]"), P); if (varncmp(varn(P), vT) >= 0) pari_err_PRIORITY(f, P, ">=", vT); Q[1] = P[1]; for (i=2; i 0) { c = gcoeff(H,i,i); ic = i; } if (!ic) break; vj[j++] = ic; U = shallowconcat(H, gel(vU, ic)); } setlg(vj, j); B = vecpermute(B, vj); l = lg(B); A = cgetg(l,t_MAT); for (j = 1; j < l; j++) { GEN t = eltabstorel_lift(rnfeq, gel(B,j)); gel(A,j) = Rg_to_RgC(t, n); } A = RgM_to_nfM(nf, A); A = Q_remove_denom(A, &dA); if (!dA) { /* order is maximal */ z = triv_order(n); if (pf) *pf = gen_1; } else { GEN fi; /* the first n columns of A are probably in HNF already */ A = shallowconcat(vecslice(A,n+1,lg(A)-1), vecslice(A,1,n)); A = mkvec2(A, const_vec(l-1,gen_1)); if (DEBUGLEVEL > 2) err_printf("rnfallbase: nfhnf in dim %ld\n", l-1); z = nfhnfmod(nf, A, nfdetint(nf,A)); gel(z,2) = gdiv(gel(z,2), dA); fi = idealprod(nf,gel(z,2)); D = idealmul(nf, D, idealsqr(nf, fi)); if (pf) *pf = idealinv(nf, fi); } if (RgM_isscalar(D,NULL)) D = gcoeff(D,1,1); if (pDKP) *pDKP = S.dKP; *pD = mkvec2(D, get_d(nf, disc)); return z; } fa = idealfactor(nf, disc); P = gel(fa,1); l = lg(P); z = NULL; E = gel(fa,2); Pf = cgetg(l, t_COL); Ef = cgetg(l, t_COL); for (i = j = jf = 1; i < l; i++) { GEN pr = gel(P,i); long e = itos(gel(E,i)); if (e > 1) { GEN vD = rnfmaxord(nf, pol, pr, e); if (vD) { long ef = idealprodval(nf, gel(vD,2), pr); z = rnfjoinmodules(nf, z, vD); if (ef) { gel(Pf, jf) = pr; gel(Ef, jf++) = stoi(-ef); } e += 2 * ef; } } if (e) { gel(P, j) = pr; gel(E, j++) = stoi(e); } } setlg(P,j); setlg(E,j); if (pDKP) *pDKP = prV_primes(P); if (pf) { setlg(Pf, jf); setlg(Ef, jf); *pf = pr_factorback_scal(nf, mkmat2(Pf,Ef)); } *pD = mkvec2(pr_factorback_scal(nf,fa), get_d(nf, disc)); return z? z: triv_order(degpol(pol)); } static GEN RgX_to_algX(GEN nf, GEN x) { long i, l; GEN y = cgetg_copy(x, &l); y[1] = x[1]; for (i=2; i 1; i--) { a = mulii(a,lT); gel(g,i) = gmul(a, gel(T,i)); } } else { gel(g, l-3) = nfmul(nf, a, gel(T,l-3)); for (i = l-3; i > 1; i--) { a = nfmul(nf,a,lT); gel(g,i) = nfmul(nf, a, gel(T,i)); } } return RgX_to_algX(nf, g); } GEN rnfdisc_factored(GEN nf, GEN pol, GEN *pd) { long i, j, l; GEN fa, E, P, disc, lim; pol = rnfdisc_get_T(nf, pol, &lim); disc = nf_to_scalar_or_basis(nf, nfX_disc(nf, pol)); if (gequal0(disc)) pari_err_DOMAIN("rnfdisc","issquarefree(pol)","=",gen_0, pol); pol = nfX_to_monic(nf, pol, NULL); fa = idealfactor_partial(nf, disc, lim); P = gel(fa,1); l = lg(P); E = gel(fa,2); for (i = j = 1; i < l; i++) { long e = itos(gel(E,i)); GEN pr = gel(P,i); if (e > 1) { GEN vD = rnfmaxord(nf, pol, pr, e); if (vD) e += 2*idealprodval(nf, gel(vD,2), pr); } if (e) { gel(P, j) = pr; gel(E, j++) = stoi(e); } } if (pd) *pd = get_d(nf, disc); setlg(P, j); setlg(E, j); return fa; } GEN rnfdiscf(GEN nf, GEN pol) { pari_sp av = avma; GEN d, fa; nf = checknf(nf); fa = rnfdisc_factored(nf, pol, &d); return gerepilecopy(av, mkvec2(pr_factorback_scal(nf,fa), d)); } GEN gen_if_principal(GEN bnf, GEN x) { pari_sp av = avma; GEN z = bnfisprincipal0(bnf,x, nf_GEN_IF_PRINCIPAL | nf_FORCE); return isintzero(z)? gc_NULL(av): z; } /* given bnf and a HNF pseudo-basis of a proj. module, 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 integral and * primitive. */ GEN rnfsimplifybasis(GEN bnf, GEN M) { pari_sp av = avma; long i, l; GEN y, Az, Iz, nf, A, I; bnf = checkbnf(bnf); nf = bnf_get_nf(bnf); if (!check_ZKmodule_i(M)) pari_err_TYPE("rnfsimplifybasis",M); A = gel(M,1); I = gel(M,2); l = lg(I); Az = cgetg(l, t_MAT); Iz = cgetg(l, t_VEC); y = mkvec2(Az, 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_module(GEN nf, GEN O, const char *s) { if (typ(O) == t_POL) return rnfpseudobasis(nf, O); if (!check_ZKmodule_i(O)) pari_err_TYPE(s, O); return shallowcopy(O); } GEN rnfdet(GEN nf, GEN M) { pari_sp av = avma; GEN D; nf = checknf(nf); M = get_module(nf, M, "rnfdet"); D = idealmul(nf, nfM_det(nf, gel(M,1)), idealprod(nf, gel(M,2))); 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 = gmul(x,da); if (db) y = gdiv(y,db); *px = x; *py = y; *pz = db ? negi(db): gen_m1; *pt = nfdiv(nf, gel(uv,1), x); } /* given a pseudo-basis of a proj. module in HNF [A,I] (or [A,I,D,d]), gives * an n x n matrix (not HNF) of a pseudo-basis and an ideal vector * [1,...,1,I] such that M ~ Z_K^(n-1) x I. Uses the approximation theorem.*/ GEN rnfsteinitz(GEN nf, GEN M) { pari_sp av = avma; long i, n; GEN A, I; nf = checknf(nf); M = get_module(nf, M, "rnfsteinitz"); A = RgM_to_nfM(nf, gel(M,1)); I = leafcopy(gel(M,2)); n = lg(A)-1; for (i = 1; i < n; i++) { GEN c1, c2, b, a = gel(I,i); gel(I,i) = gen_1; if (ideal_is1(a)) continue; c1 = gel(A,i); c2 = gel(A,i+1); b = gel(I,i+1); if (ideal_is1(b)) { gel(A,i) = c2; gel(A,i+1) = gneg(c1); gel(I,i+1) = a; } else { pari_sp av2 = avma; GEN x, y, z, t, c; nfidealdet1(nf,a,b, &x,&y,&z,&t); x = RgC_add(nfC_nf_mul(nf, c1, x), nfC_nf_mul(nf, c2, y)); y = RgC_add(nfC_nf_mul(nf, c1, z), nfC_nf_mul(nf, c2, t)); gerepileall(av2, 2, &x,&y); gel(A,i) = x; gel(A,i+1) = y; gel(I,i+1) = Q_primitive_part(idealmul(nf,a,b), &c); if (c) gel(A,i+1) = nfC_nf_mul(nf, gel(A,i+1), c); } } gel(M,1) = A; gel(M,2) = I; return gerepilecopy(av, M); } /* Given bnf and a proj. module (or a t_POL -> rnfpseudobasis), and outputs a * basis if it is free, an n+1-generating set if it is not */ GEN rnfbasis(GEN bnf, GEN M) { pari_sp av = avma; long j, n; GEN nf, A, I, cl, col, a; bnf = checkbnf(bnf); nf = bnf_get_nf(bnf); M = get_module(nf, M, "rnfbasis"); I = gel(M,2); n = lg(I)-1; j = 1; while (j < n && ideal_is1(gel(I,j))) j++; if (j < n) { M = rnfsteinitz(nf,M); I = gel(M,2); } A = gel(M,1); col= gel(A,n); A = vecslice(A, 1, n-1); cl = gel(I,n); a = gen_if_principal(bnf, cl); if (!a) { GEN v = idealtwoelt(nf, cl); A = vec_append(A, gmul(gel(v,1), col)); a = gel(v,2); } A = vec_append(A, nfC_nf_mul(nf, col, a)); return gerepilecopy(av, A); } /* Given a Z_K-module M (or a polynomial => rnfpseudobasis) outputs a * Z_K-basis in HNF if it exists, zero if not */ GEN rnfhnfbasis(GEN bnf, GEN M) { pari_sp av = avma; long j, l; GEN nf, A, I, a; bnf = checkbnf(bnf); nf = bnf_get_nf(bnf); if (typ(M) == t_POL) M = rnfpseudobasis(nf, M); else { if (typ(M) != t_VEC) pari_err_TYPE("rnfhnfbasis", M); if (lg(M) == 5) M = mkvec2(gel(M,1), gel(M,2)); M = nfhnf(nf, M); /* in case M is not in HNF */ } A = shallowcopy(gel(M,1)); I = gel(M,2); l = lg(A); for (j = 1; j < l; j++) { if (ideal_is1(gel(I,j))) continue; a = gen_if_principal(bnf, gel(I,j)); if (!a) return gc_const(av, gen_0); gel(A,j) = nfC_nf_mul(nf, gel(A,j), a); } return gerepilecopy(av,A); } long rnfisfree(GEN bnf, GEN M) { pari_sp av = avma; GEN nf, P, I; long l, j; bnf = checkbnf(bnf); if (is_pm1( bnf_get_no(bnf) )) return 1; nf = bnf_get_nf(bnf); M = get_module(nf, M, "rnfisfree"); I = gel(M,2); l = lg(I); P = NULL; for (j = 1; j < l; j++) if (!ideal_is1(gel(I,j))) P = P? idealmul(nf, P, gel(I,j)): gel(I,j); return gc_long(av, P? gequal0( isprincipal(bnf,P) ): 1); } /**********************************************************************/ /** **/ /** COMPOSITUM OF TWO NUMBER FIELDS **/ /** **/ /**********************************************************************/ static GEN compositum_fix(GEN nf, GEN A) { int ok; if (nf) { A = RgXQX_red(A, nf_get_pol(nf)); A = Q_primpart(liftpol_shallow(A)); RgX_check_ZXX(A,"polcompositum"); ok = nfissquarefree(nf,A); } else { A = Q_primpart(A); RgX_check_ZX(A,"polcompositum"); ok = ZX_is_squarefree(A); } if (!ok) pari_err_DOMAIN("polcompositum","issquarefree(arg)","=",gen_0,A); return A; } #define next_lambda(a) (a>0 ? -a : 1-a) static long nfcompositum_lambda(GEN nf, GEN A, GEN B, long lambda) { pari_sp av = avma; forprime_t S; GEN T = nf_get_pol(nf); long vT = varn(T); ulong p; init_modular_big(&S); p = u_forprime_next(&S); while (1) { GEN Hp, Tp, a; if (DEBUGLEVEL>4) err_printf("Trying lambda = %ld\n", lambda); a = ZXX_to_FlxX(RgX_rescale(A, stoi(-lambda)), p, vT); Tp = ZX_to_Flx(T, p); Hp = FlxqX_composedsum(a, ZXX_to_FlxX(B, p, vT), Tp, p); if (!FlxqX_is_squarefree(Hp, Tp, p)) { lambda = next_lambda(lambda); continue; } if (DEBUGLEVEL>4) err_printf("Final lambda = %ld\n", lambda); return gc_long(av, lambda); } } /* modular version */ GEN nfcompositum(GEN nf, GEN A, GEN B, long flag) { pari_sp av = avma; int same; long v, k; GEN C, D, LPRS; if (typ(A)!=t_POL) pari_err_TYPE("polcompositum",A); if (typ(B)!=t_POL) pari_err_TYPE("polcompositum",B); if (degpol(A)<=0 || degpol(B)<=0) pari_err_CONSTPOL("polcompositum"); v = varn(A); if (varn(B) != v) pari_err_VAR("polcompositum", A,B); if (nf) { nf = checknf(nf); if (varncmp(v,nf_get_varn(nf))>=0) pari_err_PRIORITY("polcompositum", nf, ">=", v); } same = (A == B || RgX_equal(A,B)); A = compositum_fix(nf,A); B = same ? A: compositum_fix(nf,B); D = LPRS = NULL; /* -Wall */ k = same? -1: 1; if (nf) { long v0 = fetch_var(); GEN q, T = nf_get_pol(nf); A = liftpol_shallow(A); B = liftpol_shallow(B); k = nfcompositum_lambda(nf, A, B, k); if (flag&1) { GEN H0, H1; GEN chgvar = deg1pol_shallow(stoi(k),pol_x(v0),v); GEN B1 = poleval(QXQX_to_mod_shallow(B, T), chgvar); C = RgX_resultant_all(QXQX_to_mod_shallow(A, T), B1, &q); C = gsubst(C,v0,pol_x(v)); C = lift_if_rational(C); H0 = gsubst(gel(q,2),v0,pol_x(v)); H1 = gsubst(gel(q,3),v0,pol_x(v)); if (typ(H0) != t_POL) H0 = scalarpol_shallow(H0,v); if (typ(H1) != t_POL) H1 = scalarpol_shallow(H1,v); H0 = lift_if_rational(H0); H1 = lift_if_rational(H1); LPRS = mkvec2(H0,H1); } else { C = nf_direct_compositum(nf, RgX_rescale(A,stoi(-k)), B); setvarn(C, v); C = QXQX_to_mod_shallow(C, T); } C = RgX_normalize(C); } else { B = leafcopy(B); setvarn(B,fetch_var_higher()); C = (flag&1)? ZX_ZXY_resultant_all(A, B, &k, &LPRS) : ZX_compositum(A, B, &k); setvarn(C, v); } /* C = Res_Y (A(Y), B(X + kY)) guaranteed squarefree */ if (flag & 2) C = mkvec(C); else { if (same) { D = RgX_rescale(A, stoi(1 - k)); if (nf) D = RgX_normalize(QXQX_to_mod_shallow(D, nf_get_pol(nf))); C = RgX_div(C, D); if (degpol(C) <= 0) C = mkvec(D); else C = shallowconcat(nf? gel(nffactor(nf,C),1): ZX_DDF(C), D); } else C = nf? gel(nffactor(nf,C),1): ZX_DDF(C); } gen_sort_inplace(C, (void*)(nf?&cmp_RgX: &cmpii), &gen_cmp_RgX, NULL); if (flag&1) { /* a,b,c root of A,B,C = compositum, c = b - k a */ long i, l = lg(C); GEN a, b, mH0 = RgX_neg(gel(LPRS,1)), H1 = gel(LPRS,2); setvarn(mH0,v); setvarn(H1,v); for (i=1; i 0? x: ZG_neg(x); if (typ(x) == t_INT) return mulii(x,c); return mkmat2(gel(x,1), ZC_Z_mul(gel(x,2), c)); } GEN ZG_mul(GEN x, GEN y) { pari_sp av; GEN z, XG, XE; long i, l; if (typ(x) == t_INT) return ZG_Z_mul(y, x); if (typ(y) == t_INT) return ZG_Z_mul(x, y); av = avma; XG = gel(x,1); XE = gel(x,2); l = lg(XG); z = ZG_Z_mul(G_ZG_mul(gel(XG,1), y), gel(XE,1)); for (i = 2; i < l; i++) { z = ZG_add(z, ZG_Z_mul(G_ZG_mul(gel(XG,i), y), gel(XE,i))); if (gc_needed(av,3)) { if(DEBUGMEM>1) pari_warn(warnmem,"ZG_mul, i = %ld/%ld",i,l-1); z = gerepilecopy(av, z); } } return z; } GEN ZGCs_add(GEN x, GEN y) { GEN xi = gel(x,1), xv = gel(x,2); GEN yi = gel(y,1), yv = gel(y,2); long i = 1, j = 1, k = 1, lx = lg(xi), ly = lg(yi), l = lx+ly-1; GEN zi = cgetg(l, t_VECSMALL), zv = cgetg(l, t_VEC); while (i < lx && j < ly) { if (xi[i] < yi[j]) { zi[k] = xi[i]; gel(zv,k) = gel(xv,i); i++; } else if (xi[i] > yi[j]) { zi[k] = yi[j]; gel(zv,k) = gel(yv,j); j++; } else { zi[k] = xi[i]; gel(zv,k) = ZG_add(gel(xv,i),gel(yv,j)); i++; j++; } k++; } for(; i < lx; i++,k++) { zi[k] = xi[i]; gel(zv,k) = gel(xv,i); } for(; j < ly; j++,k++) { zi[k] = yi[j]; gel(zv,k) = gel(yv,j); } setlg(zi,k); setlg(zv,k); return mkvec2(zi, zv); } GEN ZG_G_mul(GEN x, GEN y) { long i, l; GEN z, X; if (typ(x) == t_INT) return signe(x)? to_famat_shallow(y, x): gen_0; X = gel(x,1); z = cgetg_copy(X, &l); for (i = 1; i < l; i++) gel(z,i) = gmul(gel(X,i), y); return ZG_normalize( mkmat2(z, gel(x,2)) ); } GEN G_ZG_mul(GEN x, GEN y) { long i, l; GEN z, Y; if (typ(y) == t_INT) return to_famat_shallow(x, y); Y = gel(y,1); z = cgetg_copy(Y, &l); for (i = 1; i < l; i++) gel(z,i) = gmul(x, gel(Y,i)); return ZG_normalize( mkmat2(z, gel(y,2)) ); } void ZGC_G_mul_inplace(GEN v, GEN x) { long i, l = lg(v); for (i = 1; i < l; i++) gel(v,i) = ZG_G_mul(gel(v,i), x); } GEN ZGC_G_mul(GEN v, GEN x) { pari_APPLY_same(ZG_G_mul(gel(v,i), x)); } GEN G_ZGC_mul(GEN x, GEN v) { pari_APPLY_same(G_ZG_mul(gel(v,i), x)); } GEN ZGC_Z_mul(GEN v, GEN x) { pari_APPLY_same(ZG_Z_mul(gel(v,i), x)); } pari-2.17.2/src/basemath/Qfb.c0000644000175000017500000015344014676526175014445 0ustar billbill/* Copyright (C) 2000-2005 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" /*******************************************************************/ /* */ /* QUADRATIC POLYNOMIAL ASSOCIATED TO A DISCRIMINANT */ /* */ /*******************************************************************/ void check_quaddisc(GEN x, long *s, long *pr, const char *f) { long r; if (typ(x) != t_INT) pari_err_TYPE(f,x); *s = signe(x); if (Z_issquare(x)) pari_err_DOMAIN(f,"issquare(disc)","=", gen_1,x); r = mod4(x); if (*s < 0 && r) r = 4 - r; if (r > 1) pari_err_DOMAIN(f,"disc % 4",">", gen_1,x); if (pr) *pr = r; } void check_quaddisc_real(GEN x, long *r, const char *f) { long sx; check_quaddisc(x, &sx, r, f); if (sx < 0) pari_err_DOMAIN(f, "disc","<",gen_0,x); } void check_quaddisc_imag(GEN x, long *r, const char *f) { long sx; check_quaddisc(x, &sx, r, f); if (sx > 0) pari_err_DOMAIN(f, "disc",">",gen_0,x); } /* X^2 + b X + c is the canonical quadratic t_POL of discriminant D. * Dodd is nonzero iff D is odd */ static void quadpoly_bc(GEN D, long Dodd, GEN *b, GEN *c) { if (Dodd) { pari_sp av = avma; *b = gen_m1; *c = gerepileuptoint(av, shifti(subui(1,D), -2)); } else { *b = gen_0; *c = shifti(D,-2); togglesign(*c); } } /* X^2 - X - (D-1)/4 or X^2 - D/4 */ static GEN quadpoly_ii(GEN D, long Dmod4) { GEN b, c, y = cgetg(5,t_POL); y[1] = evalsigne(1) | evalvarn(0); quadpoly_bc(D, Dmod4, &b,&c); gel(y,2) = c; gel(y,3) = b; gel(y,4) = gen_1; return y; } GEN quadpoly(GEN D) { long s, Dmod4; check_quaddisc(D, &s, &Dmod4, "quadpoly"); return quadpoly_ii(D, Dmod4); } GEN /* no checks */ quadpoly_i(GEN D) { return quadpoly_ii(D, Mod4(D)); } GEN quadpoly0(GEN x, long v) { GEN T = quadpoly(x); if (v > 0) setvarn(T, v); return T; } GEN quadgen(GEN x) { retmkquad(quadpoly(x), gen_0, gen_1); } GEN quadgen0(GEN x, long v) { if (v==-1) v = fetch_user_var("w"); retmkquad(quadpoly0(x, v), gen_0, gen_1); } /***********************************************************************/ /** **/ /** BINARY QUADRATIC FORMS **/ /** **/ /***********************************************************************/ static int is_qfi(GEN q) { return typ(q)==t_QFB && qfb_is_qfi(q); } static GEN check_qfbext(const char *fun, GEN x) { long t = typ(x); if (t == t_QFB) return x; if (t == t_VEC && lg(x)==3) { GEN q = gel(x,1); if (!is_qfi(q) && typ(gel(x,2))==t_REAL) return q; } pari_err_TYPE(fun, x); return NULL;/* LCOV_EXCL_LINE */ } static GEN qfb3(GEN x, GEN y, GEN z) { retmkqfb(icopy(x), icopy(y), icopy(z), qfb_disc3(x,y,z)); } static int qfb_equal(GEN x, GEN y) { return equalii(gel(x,1),gel(y,1)) && equalii(gel(x,2),gel(y,2)) && equalii(gel(x,3),gel(y,3)); } /* valid for t_QFB, qfr3, qfr5; shallow */ static GEN qfb_inv(GEN x) { GEN z = shallowcopy(x); gel(z,2) = negi(gel(z,2)); return z; } /* valid for t_QFB, gerepile-safe */ static GEN qfbinv(GEN x) { retmkqfb(icopy(gel(x,1)),negi(gel(x,2)),icopy(gel(x,3)), icopy(gel(x,4))); } GEN Qfb0(GEN a, GEN b, GEN c) { GEN q, D; if (!b) { if (c) pari_err_TYPE("Qfb",c); if (typ(a) == t_VEC && lg(a) == 4) { b = gel(a,2); c = gel(a,3); a = gel(a,1); } else if (typ(a) == t_POL && degpol(a) == 2) { b = gel(a,3); c = gel(a,2); a = gel(a,4); } else if (typ(a) == t_MAT && lg(a)==3 && lgcols(a)==3) { b = gadd(gcoeff(a,2,1), gcoeff(a,1,2)); c = gcoeff(a,2,2); a = gcoeff(a,1,1); } else pari_err_TYPE("Qfb",a); } else if (!c) pari_err_TYPE("Qfb",b); if (typ(a)!=t_INT) pari_err_TYPE("Qfb",a); if (typ(b)!=t_INT) pari_err_TYPE("Qfb",b); if (typ(c)!=t_INT) pari_err_TYPE("Qfb",c); q = qfb3(a, b, c); D = qfb_disc(q); if (signe(D) < 0) { if (signe(a) < 0) pari_err_IMPL("negative definite t_QFB"); } else if (Z_issquare(D)) pari_err_DOMAIN("Qfb","issquare(disc)","=", gen_1,q); return q; } /***********************************************************************/ /** **/ /** Reduction **/ /** **/ /***********************************************************************/ /* assume a > 0. Write b = q*2a + r, with -a < r <= a */ static GEN dvmdii_round(GEN b, GEN a, GEN *r) { GEN a2 = shifti(a, 1), q = dvmdii(b, a2, r); if (signe(b) >= 0) { if (abscmpii(*r, a) > 0) { q = addiu(q, 1); *r = subii(*r, a2); } } else { /* r <= 0 */ if (abscmpii(*r, a) >= 0){ q = subiu(q, 1); *r = addii(*r, a2); } } return q; } /* Assume 0 < a <= LONG_MAX. Ensure no overflow */ static long dvmdsu_round(long b, ulong a, long *r) { ulong a2 = a << 1, q, ub, ur; if (b >= 0) { ub = b; q = ub / a2; ur = ub % a2; if (ur > a) { ur -= a; q++; *r = (long)ur; *r -= (long)a; } else *r = (long)ur; return (long)q; } else { /* r <= 0 */ ub = (ulong)-b; /* |b| */ q = ub / a2; ur = ub % a2; if (ur >= a) { ur -= a; q++; *r = (long)ur; *r = (long)a - *r; } else *r = -(long)ur; return -(long)q; } } /* reduce b mod 2*a. Update b,c */ static void REDB(GEN a, GEN *b, GEN *c) { GEN r, q = dvmdii_round(*b, a, &r); if (!signe(q)) return; *c = subii(*c, mulii(q, shifti(addii(*b, r),-1))); *b = r; } /* Assume a > 0. Reduce b mod 2*a. Update b,c */ static void sREDB(ulong a, long *b, ulong *c) { long r, q; ulong uz; if (a > LONG_MAX) return; /* b already reduced */ q = dvmdsu_round(*b, a, &r); if (q == 0) return; /* Final (a,r,c2) satisfies |r| <= |b| hence c2 <= c, c2 = c - q*z, * where z = (b+r) / 2, representable as long, has the same sign as q. */ if (*b < 0) { /* uz = -z >= 0, q < 0 */ if (r >= 0) /* different signs=>no overflow, exact division */ uz = (ulong)-((*b + r)>>1); else { ulong ub = (ulong)-*b, ur = (ulong)-r; uz = (ub + ur) >> 1; } *c -= (-q) * uz; /* c -= qz */ } else { /* uz = z >= 0, q > 0 */ if (r <= 0) uz = (*b + r)>>1; else { ulong ub = (ulong)*b, ur = (ulong)r; uz = ((ub + ur) >> 1); } *c -= q * uz; /* c -= qz */ } *b = r; } static void REDBU(GEN a, GEN *b, GEN *c, GEN u1, GEN *u2) { /* REDB(a,b,c) */ GEN r, q = dvmdii_round(*b, a, &r); *c = subii(*c, mulii(q, shifti(addii(*b, r),-1))); *b = r; *u2 = subii(*u2, mulii(q, u1)); } /* q t_QFB, return reduced representative and set base change U in Sl2(Z) */ static GEN qfbredsl2_imag_basecase(GEN q, GEN *U) { pari_sp av = avma; GEN z, u1,u2,v1,v2,Q; GEN a = gel(q,1), b = gel(q,2), c = gel(q,3); long cmp; u1 = gen_1; u2 = gen_0; cmp = abscmpii(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 = abscmpii(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 (gc_needed(av, 1)) { if (DEBUGMEM>1) pari_warn(warnmem, "qfbredsl2"); gerepileall(av, 5, &a,&b,&c, &u1,&u2); } } if (cmp == 0 && signe(b) < 0) { b = negi(b); z = u1; u1 = u2; u2 = negi(z); } /* 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)); *U = mkmat2(mkcol2(u1,v1), mkcol2(u2,v2)); Q = mkqfb(a,b,c,gel(q,4)); return gc_all(av, 2, &Q, U); } static GEN setq_b0(ulong a, ulong c, GEN D) { retmkqfb(utoipos(a), gen_0, utoipos(c), icopy(D)); } /* assume |sb| = 1 */ static GEN setq(ulong a, ulong b, ulong c, long sb, GEN D) { retmkqfb(utoipos(a), sb==1? utoipos(b): utoineg(b), utoipos(c), icopy(D)); } /* 0 < a, c < 2^BIL, b = 0 */ static GEN qfbred_imag_1_b0(ulong a, ulong c, GEN D) { return (a <= c)? setq_b0(a, c, D): setq_b0(c, a, D); } /* 0 < a, c < 2^BIL: single word affair */ static GEN qfbred_imag_1(pari_sp av, GEN a, GEN b, GEN c, GEN D) { ulong ua, ub, uc; long sb; for(;;) { /* at most twice */ long lb = lgefint(b); /* <= 3 after first loop */ if (lb == 2) return qfbred_imag_1_b0(a[2],c[2], D); if (lb == 3 && uel(b,2) <= (ulong)LONG_MAX) break; REDB(a,&b,&c); if (uel(a,2) <= uel(c,2)) { /* lg(b) <= 3 but may be too large for itos */ long s = signe(b); set_avma(av); if (!s) return qfbred_imag_1_b0(a[2], c[2], D); if (a[2] == c[2]) s = 1; return setq(a[2], b[2], c[2], s, D); } swap(a,c); b = negi(b); } /* b != 0 */ set_avma(av); ua = a[2]; ub = sb = b[2]; if (signe(b) < 0) sb = -sb; uc = c[2]; if (ua < ub) sREDB(ua, &sb, &uc); else if (ua == ub && sb < 0) sb = (long)ub; while(ua > uc) { lswap(ua,uc); sb = -sb; sREDB(ua, &sb, &uc); } if (!sb) return setq_b0(ua, uc, D); else { long s = 1; if (sb < 0) { sb = -sb; if (ua != uc) s = -1; } return setq(ua, sb, uc, s, D); } } static GEN rhoimag(GEN x) { pari_sp av = avma; GEN a = gel(x,1), b = gel(x,2), c = gel(x,3); int fl = abscmpii(a, c); if (fl <= 0) { int fg = abscmpii(a, b); if (fg >= 0) { x = gcopy(x); if ((!fl || !fg) && signe(gel(x,2)) < 0) setsigne(gel(x,2), 1); return x; } } swap(a,c); b = negi(b); REDB(a, &b, &c); return gerepilecopy(av, mkqfb(a,b,c, qfb_disc(x))); } /* qfr3 / qfr5 */ /* t_QFB are unusable: D, sqrtD, isqrtD are recomputed all the time and the * logarithmic Shanks's distance is costly and hard to control. * qfr3 / qfr5 routines take a container of t_INTs (e.g a t_VEC) as argument, * at least 3 (resp. 5) components [it is a feature that they do not check the * precise type or length of the input]. They return a vector of length 3 * (resp. 5). A qfr3 [a,b,c] contains the form coeffs, in a qfr5 [a,b,c, e,d] * the t_INT e is a binary exponent, d a t_REAL, coding the distance in * multiplicative form: the true distance is obtained from qfr5_dist. * All other qfr routines are obsolete (inefficient) wrappers */ /* static functions are not stack-clean. Unless mentionned otherwise, public * functions are. */ #define EMAX 22 static void fix_expo(GEN x) { if (expo(gel(x,5)) >= (1L << EMAX)) { gel(x,4) = addiu(gel(x,4), 1); shiftr_inplace(gel(x,5), - (1L << EMAX)); } } /* (1/2) log (d * 2^{e * 2^EMAX}). Not stack clean if e != 0 */ GEN qfr5_dist(GEN e, GEN d, long prec) { GEN t = logr_abs(d); if (signe(e)) { GEN u = mulir(e, mplog2(prec)); shiftr_inplace(u, EMAX); t = addrr(t, u); } shiftr_inplace(t, -1); return t; } static void rho_get_BC(GEN *B, GEN *C, GEN a, GEN b, GEN c, struct qfr_data *S) { GEN t, u, q; t = (abscmpii(S->isqrtD,c) >= 0)? S->isqrtD: absi_shallow(c); q = truedvmdii(addii(t, b), shifti(c,1), &u); *B = subii(t, u); /* |t| - ((|t|+b) % 2c) */ *C = subii(a, mulii(q, subii(b, mulii(q,c)))); } /* Not stack-clean */ GEN qfr3_rho(GEN x, struct qfr_data *S) { GEN B, C, a = gel(x,1), b = gel(x,2), c = gel(x,3); rho_get_BC(&B, &C, a, b, c, S); return mkvec3(c, B, C); } /* Not stack-clean */ GEN qfr5_rho(GEN x, struct qfr_data *S) { GEN B, C, a = gel(x,1), b = gel(x,2), c = gel(x,3), y; long sb = signe(b); rho_get_BC(&B, &C, a, 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); } else gel(y,5) = negr(gel(y,5)); 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 D, GEN d0) { if (d0) { GEN n = gel(x,4), d = absr(gel(x,5)); if (signe(n)) { n = addis(shifti(n, EMAX), expo(d)); setexpo(d, 0); d = logr_abs(d); if (signe(n)) d = addrr(d, mulir(n, mplog2(lg(d0)))); shiftr_inplace(d, -1); d0 = addrr(d0, d); } else if (!gequal1(d)) /* avoid loss of precision */ { d = logr_abs(d); shiftr_inplace(d, -1); d0 = addrr(d0, d); } } x = qfr3_to_qfr(x, D); return d0 ? mkvec2(x,d0): x; } /* Not stack-clean */ GEN qfr3_to_qfr(GEN x, GEN d) { retmkqfb(gel(x,1), gel(x,2), gel(x,3), d); } static int ab_isreduced(GEN a, GEN b, GEN isqrtD) { GEN t; if (signe(b) <= 0 || abscmpii(b, isqrtD) > 0) return 0; t = addii_sign(isqrtD,1, shifti(a,1),-1); /* floor(sqrt(D)) - |2a| */ return signe(t) < 0 ? abscmpii(b, t) >= 0 : abscmpii(b, t) > 0; } /* Not stack-clean */ GEN qfr5_red(GEN x, struct qfr_data *S) { pari_sp av = avma; while (!ab_isreduced(gel(x,1), gel(x,2), S->isqrtD)) { x = qfr5_rho(x, S); if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"qfr5_red"); x = gerepilecopy(av, x); } } return x; } /* Not stack-clean */ GEN qfr3_red(GEN x, struct qfr_data *S) { pari_sp av = avma; GEN a = gel(x,1), b = gel(x,2), c = gel(x,3); while (!ab_isreduced(a, b, S->isqrtD)) { GEN B, C; rho_get_BC(&B, &C, a, b, c, S); a = c; b = B; c = C; if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"qfr3_red"); gerepileall(av, 3, &a, &b, &c); } } return mkvec3(a, b, c); } 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, GEN d, struct qfr_data *S) { long prec = realprec(d), l = -expo(d); if (l < BITS_IN_LONG) l = BITS_IN_LONG; prec = maxss(prec, nbits2prec(l)); S->D = qfb_disc(x); x = qfr_to_qfr5(x,prec); if (!S->sqrtD) S->sqrtD = sqrtr(itor(S->D,prec)); else if (typ(S->sqrtD) != t_REAL) pari_err_TYPE("qfr_init",S->sqrtD); if (!S->isqrtD) { pari_sp av=avma; long e; S->isqrtD = gcvtoi(S->sqrtD,&e); if (e>-2) { set_avma(av); S->isqrtD = sqrti(S->D); } } else if (typ(S->isqrtD) != t_INT) pari_err_TYPE("qfr_init",S->isqrtD); return x; } static GEN qfr3_init(GEN x, struct qfr_data *S) { S->D = qfb_disc(x); if (!S->isqrtD) S->isqrtD = sqrti(S->D); else if (typ(S->isqrtD) != t_INT) pari_err_TYPE("qfr_init",S->isqrtD); return x; } #define qf_NOD 2 #define qf_STEP 1 static GEN qfbred_real_basecase_i(GEN x, long flag, GEN isqrtD, GEN sqrtD) { struct qfr_data S; GEN d = NULL, y; if (typ(x)==t_VEC) { d = gel(x,2); x = gel(x,1); } else flag |= qf_NOD; S.sqrtD = sqrtD; S.isqrtD = isqrtD; y = (flag & qf_NOD)? qfr3_init(x, &S): qfr5_init(x, d, &S); switch(flag) { case 0: y = qfr5_red(y,&S); break; case qf_NOD: y = qfr3_red(y,&S); break; case qf_STEP: y = qfr5_rho(y,&S); break; case qf_STEP|qf_NOD: y = qfr3_rho(y,&S); break; default: pari_err_FLAG("qfbred"); } return qfr5_to_qfr(y, qfb_disc(x), d); } static void _rhorealsl2(GEN *pa, GEN *pb, GEN *pc, GEN *pu1, GEN *pu2, GEN *pv1, GEN *pv2, GEN rd) { GEN C = mpabs_shallow(*pc), t = addii(*pb, gmax_shallow(rd,C)); GEN r, q = truedvmdii(t, shifti(C,1), &r); GEN a = *pa, b= *pb, c = *pc; if (signe(c) < 0) togglesign(q); *pa = *pc; *pb = subii(t, addii(r, *pb)); *pc = subii(a,mulii(q,subii(b, mulii(q,c)))); r = *pu1; *pu1 = *pv1; *pv1 = subii(mulii(q, *pv1), r); r = *pu2; *pu2 = *pv2; *pv2 = subii(mulii(q, *pv2), r); } static GEN rhorealsl2(GEN A, GEN rd) { GEN V = gel(A,1), M = gel(A,2); GEN a = gel(V,1), b = gel(V,2), c = gel(V,3), d = qfb_disc(V); GEN u1 = gcoeff(M,1,1), v1 = gcoeff(M,1,2); GEN u2 = gcoeff(M,2,1), v2 = gcoeff(M,2,2); _rhorealsl2(&a,&b,&c, &u1,&u2,&v1,&v2, rd); return mkvec2(mkqfb(a,b,c,d), mkmat22(u1,v1,u2,v2)); } static GEN qfbredsl2_real_basecase(GEN V, GEN rd) { pari_sp av = avma; GEN u1 = gen_1, u2 = gen_0, v1 = gen_0, v2 = gen_1; GEN a = gel(V,1), b = gel(V,2), c = gel(V,3), d = qfb_disc(V); while (!ab_isreduced(a,b,rd)) { _rhorealsl2(&a,&b,&c, &u1,&u2,&v1,&v2, rd); if (gc_needed(av, 1)) { if (DEBUGMEM>1) pari_warn(warnmem,"qfbredsl2"); gerepileall(av, 7, &a,&b,&c,&u1,&u2,&v1,&v2); } } return gerepilecopy(av, mkvec2(mkqfb(a,b,c,d), mkmat22(u1,v1,u2,v2))); } /* fast reduction of qfb with positive coefficients, based on Arnold Schoenhage, Fast reduction and composition of binary quadratic forms, Proc. of Intern. Symp. on Symbolic and Algebraic Computation (Bonn) (S. M. Watt, ed.), ACM Press, 1991, pp. 128-133. With thanks to Keegan Ryan BA20230927 */ #define QFBRED_LIMIT 9000 /* pqfb: qf with positive coefficients */ static int lti2n(GEN a, long m) { return signe(a) < 0 || expi(a) < m ? 1 : 0; } static GEN pqfbred_1(GEN Q, long m, GEN U) { GEN a = gel(Q,1), b = gel(Q,2), c = gel(Q,3), d = gel(Q,4); if (abscmpii(a, c) < 0) { GEN t, at, r; GEN r2 = addii(shifti(a, m + 2), d); long e2 = expi(r2); r = int2n(signe(r2) < 0 || e2 < 2*m+2 ? m+1 : e2>>1); t = truedivii(subii(b, r), shifti(a,1)); if (signe(t)==0) pari_err_BUG("pqfbred_1"); at = mulii(a,t); c = addii(subii(c, mulii(b, t)), mulii(at, t)); b = subii(b, shifti(at,1)); gcoeff(U,1,2) = subii( gcoeff(U,1,2), mulii(gcoeff(U,1,1), t)); gcoeff(U,2,2) = subii( gcoeff(U,2,2), mulii(gcoeff(U,2,1), t)); } else { GEN t, ct, r; GEN r2 = addii(shifti(c, m + 2), d); long e2 = expi(r2); r = int2n(signe(r2) < 0 || e2 < 2*m+2 ? m+1 : e2>>1); t = truedivii(subii(b, r), shifti(c,1)); if (signe(t)==0) pari_err_BUG("pqfbred_1"); ct = mulii(c, t); a = addii(subii(a, mulii(b, t)), mulii(ct, t)); b = subii(b, shifti(ct, 1)); gcoeff(U,1,1) = subii(gcoeff(U,1,1), mulii(gcoeff(U,1,2), t)); gcoeff(U,2,1) = subii(gcoeff(U,2,1), mulii(gcoeff(U,2,2), t)); } return mkqfb(a,b,c,d); } static int is_minimal(GEN Q, long m) { pari_sp av = avma; GEN a = gel(Q,1), b = gel(Q,2), c = gel(Q,3); return gc_bool(av, lti2n(addii(subii(a,b), c), m) || (lti2n(subii(b, shifti(a,1)), m+1) && lti2n(subii(b, shifti(c,1)), m+1))); } static GEN pqfbred_iter_1(GEN Q, ulong m, GEN U) { pari_sp av = avma; while (!is_minimal(Q,m)) { Q = pqfbred_1(Q, m, U); if (gc_needed(av, 1)) { if (DEBUGMEM>1) pari_warn(warnmem,"pqfbred_iter_1, lc = %ld", expi(gel(Q,3))); gerepileall(av, 3, &Q, &gel(U,1), &gel(U,2)); } } return Q; } static GEN pqfbred_basecase(GEN Q, ulong m, GEN *pt_U) { pari_sp av = avma; GEN U = matid(2); Q = pqfbred_iter_1(Q, m, U); *pt_U = U; return gc_all(av, 2, &Q, pt_U); } static long qfb_maxexpi(GEN Q) { return 1+maxss(expi(gel(Q,1)), maxss(expi(gel(Q,2)), expi(gel(Q,3)))); } static long qfb_minexpi(GEN Q) { long m = minss(expi(gel(Q,1)), minss(expi(gel(Q,2)), expi(gel(Q,3)))); return m < 0 ? 0: m; } static GEN pqfbred_rec(GEN Q, long m, GEN *pt_U) { pari_sp av = avma; GEN Q0, Q1, QR; GEN d = qfb_disc(Q); long n = qfb_maxexpi(Q) - m; long h; int going_to_r8 = 0; GEN U; if (n < 170) return pqfbred_basecase(Q, m, pt_U); if (qfb_minexpi(Q) <= m + 2) { U = matid(2); QR = Q; } else { long p, mm; if (m <= n) { mm = m; p = 0; Q1 = Q; } else { mm = n; p = m + 1 - n; Q0 = mkvec3(remi2n(gel(Q,1), p), remi2n(gel(Q,2), p), remi2n(gel(Q,3), p)); Q1 = qfb3(shifti(gel(Q,1),-p), shifti(gel(Q,2),-p), shifti(gel(Q,3),-p)); } h = mm + (n>>1); if (qfb_minexpi(Q1) <= h) { U = matid(2); QR = Q1; } else QR = pqfbred_rec(Q1, h, &U); while (qfb_maxexpi(QR) > h) { if (is_minimal(QR, mm)) { going_to_r8 = 1; break; } QR = pqfbred_1(QR, mm, U); } if (!going_to_r8) { GEN V; QR = pqfbred_rec(QR, mm, &V); U = ZM2_mul(U,V); } if (p > 0) { GEN Q0U = qfb_ZM_apply(Q0,U); QR = mkqfb(addii(shifti(gel(QR,1), p), gel(Q0U,1)), addii(shifti(gel(QR,2), p), gel(Q0U,2)), addii(shifti(gel(QR,3), p), gel(Q0U,3)), d); } } QR = pqfbred_iter_1(QR, m, U); *pt_U = U; return gc_all(av, 2, &QR, pt_U); } static GEN qfbredsl2_real(GEN Q, GEN isqrtD) { pari_sp av = avma; if (2*qfb_maxexpi(Q)-expi(gel(Q,4)) <= QFBRED_LIMIT) return qfbredsl2_real_basecase(Q, isqrtD); else { GEN a = gel(Q,1), b = gel(Q,2), c = gel(Q,3), d = gel(Q,4); GEN Qf, Qr, W, U, t = NULL; long sa = signe(a), sb; if (sa < 0) { a = negi(a); b = negi(b); c = negi(c); } if (signe(c) < 0) { GEN at; t = addiu(truedivii(subii(isqrtD,b),shifti(a,1)),1); at = mulii(a,t); c = addii(subii(c, mulii(b, t)), mulii(at, t)); b = subii(b, shifti(at,1)); } sb = signe(b); Qr = pqfbred_rec(mkqfb(a, sb < 0 ? negi(b): b, c, d), 0, &U); if (sa < 0) Qr = mkqfb(negi(gel(Qr,1)), negi(gel(Qr,2)), negi(gel(Qr,3)), gel(Qr,4)); if (sb < 0) { gcoeff(U,2,1) = negi(gcoeff(U,2,1)); gcoeff(U,2,2) = negi(gcoeff(U,2,2)); } if (t) { gcoeff(U,1,1) = subii( gcoeff(U,1,1), mulii(gcoeff(U,2,1), t)); gcoeff(U,1,2) = subii( gcoeff(U,1,2), mulii(gcoeff(U,2,2), t)); } W = qfbredsl2_real_basecase(Qr, isqrtD); Qf = gel(W,1); U = ZM2_mul(U,gel(W,2)); return gerepilecopy(av, mkvec2(Qf,U)); } } static GEN qfbredsl2_imag(GEN Q) { pari_sp av = avma; GEN Qt, U; if (2*qfb_maxexpi(Q)-expi(gel(Q,4)) <= QFBRED_LIMIT) Qt = qfbredsl2_imag_basecase(Q, &U); else { long sb = signe(gel(Q,2)); GEN Qr, W; Qr = pqfbred_rec(sb < 0 ? mkqfb(gel(Q,1), negi(gel(Q,2)), gel(Q,3), gel(Q,4)): Q, 0, &U); Qt = qfbredsl2_imag_basecase(Qr,&W); U = ZM2_mul(U,W); if (sb < 0) { gcoeff(U,2,1) = negi(gcoeff(U,2,1)); gcoeff(U,2,2) = negi(gcoeff(U,2,2)); } } return gerepilecopy(av, mkvec2(Qt,U)); } GEN redimagsl2(GEN Q, GEN *U) { GEN q = qfbredsl2_imag(Q); *U = gel(q,2); return gel(q,1); } GEN qfbredsl2(GEN q, GEN isD) { pari_sp av; if (typ(q) != t_QFB) pari_err_TYPE("qfbredsl2",q); if (qfb_is_qfi(q)) { if (isD) pari_err_TYPE("qfbredsl2", isD); return qfbredsl2_imag(q); } av = avma; if (!isD) isD = sqrti(qfb_disc(q)); else if (typ(isD) != t_INT) pari_err_TYPE("qfbredsl2",isD); return gerepileupto(av, qfbredsl2_real(q, isD)); } static GEN qfbred_real_i(GEN Q, long flag, GEN isqrtD, GEN sqrtD) { if (typ(Q)!=t_QFB || 2*qfb_maxexpi(Q)-expi(gel(Q,4)) <= QFBRED_LIMIT) return qfbred_real_basecase_i(Q, flag, isqrtD, sqrtD); else { GEN a = gel(Q,1), b = gel(Q,2), c = gel(Q,3), d = gel(Q,4); GEN Qr, W, U, t = NULL; long sa = signe(a), sb; if (sa < 0) { a = negi(a); b = negi(b); c = negi(c); } if (signe(c) < 0) { GEN at; t = addiu(truedivii(subii(isqrtD,b),shifti(a,1)),1); at = mulii(a,t); c = addii(subii(c, mulii(b, t)), mulii(at, t)); b = subii(b, shifti(at,1)); } sb = signe(b); Qr = pqfbred_rec(mkqfb(a, sb < 0 ? negi(b): b, c, d), 0, &U); if (sa < 0) Qr = mkqfb(negi(gel(Qr,1)), negi(gel(Qr,2)), negi(gel(Qr,3)), gel(Qr,4)); W = qfbred_real_basecase_i(Qr, flag, isqrtD, sqrtD); return gel(W,1); } } static GEN qfbred_real(GEN x) { return qfbred_real_i(x,0,NULL,NULL); } static GEN qfbred_imag_basecase_av(pari_sp av, GEN q) { GEN a = gel(q,1), b = gel(q,2), c = gel(q,3), D = gel(q,4); long cmp, lc = lgefint(c); if (lgefint(a) == 3 && lc == 3) return qfbred_imag_1(av, a, b, c, D); cmp = abscmpii(a, b); if (cmp < 0) REDB(a,&b,&c); else if (cmp == 0 && signe(b) < 0) b = negi(b); for(;;) { cmp = abscmpii(a, c); if (cmp <= 0) break; lc = lgefint(a); /* lg(future c): we swap a & c next */ if (lc == 3) return qfbred_imag_1(av, a, b, c, D); swap(a,c); b = negi(b); /* apply rho */ REDB(a,&b,&c); if (gc_needed(av, 2)) { if (DEBUGMEM>1) pari_warn(warnmem,"qfbred_imag, lc = %ld", lc); gerepileall(av, 3, &a,&b,&c); } } if (cmp == 0 && signe(b) < 0) b = negi(b); return gerepilecopy(av, mkqfb(a, b, c, D)); } static GEN qfbred_imag_av(pari_sp av, GEN Q) { if (2*qfb_maxexpi(Q)-expi(gel(Q,4)) <= QFBRED_LIMIT) return qfbred_imag_basecase_av(av, Q); else { long sb = signe(gel(Q,2)); GEN U, Qr = pqfbred_rec(sb < 0 ? mkqfb(gel(Q,1), negi(gel(Q,2)), gel(Q,3), gel(Q,4)): Q, 0, &U); return qfbred_imag_basecase_av(av, Qr); } } static GEN qfbred_imag(GEN q) { return qfbred_imag_av(avma, q); } GEN qfbred0(GEN x, long flag, GEN isqrtD, GEN sqrtD) { pari_sp av; GEN q = check_qfbext("qfbred",x); if (qfb_is_qfi(q)) return (flag & qf_STEP)? rhoimag(x): qfbred_imag(x); if (typ(x)==t_QFB) flag |= qf_NOD; else flag &= ~qf_NOD; av = avma; return gerepilecopy(av, qfbred_real_i(x,flag,isqrtD,sqrtD)); } /* t_QFB */ GEN qfbred_i(GEN x) { return qfb_is_qfi(x)? qfbred_imag(x): qfbred_real(x); } GEN qfbred(GEN x) { return qfbred0(x, 0, NULL, NULL); } /***********************************************************************/ /** **/ /** Composition **/ /** **/ /***********************************************************************/ static void qfb_sqr(GEN z, GEN x) { GEN c, d1, x2, v1, v2, c3, m, p1, r; d1 = bezout(gel(x,2),gel(x,1),&x2, NULL); /* usually 1 */ c = gel(x,3); m = mulii(c,x2); if (equali1(d1)) v1 = v2 = gel(x,1); else { v1 = diviiexact(gel(x,1),d1); v2 = mulii(v1, gcdii(d1,c)); /* = v1 iff x primitive */ c = mulii(c, d1); } togglesign(m); r = modii(m,v2); p1 = mulii(r, v1); c3 = addii(c, mulii(r,addii(gel(x,2),p1))); gel(z,1) = mulii(v1,v2); gel(z,2) = addii(gel(x,2), shifti(p1,1)); gel(z,3) = diviiexact(c3,v2); } /* z <- x * y */ static void qfb_comp(GEN z, GEN x, GEN y) { GEN n, c, d, y1, v1, v2, c3, m, p1, r; if (x == y) { qfb_sqr(z,x); return; } n = shifti(subii(gel(y,2),gel(x,2)), -1); v1 = gel(x,1); v2 = gel(y,1); c = gel(y,3); d = bezout(v2,v1,&y1,NULL); if (equali1(d)) m = mulii(y1,n); else { GEN s = subii(gel(y,2), n); GEN x2, y2, d1 = bezout(s,d,&x2,&y2); /* x2 s + y2 (x1 v1 + y1 v2) = d1 */ if (!equali1(d1)) { v1 = diviiexact(v1,d1); v2 = diviiexact(v2,d1); /* gcd = 1 iff x or y primitive */ v1 = mulii(v1, gcdii(c,gcdii(gel(x,3),gcdii(d1,n)))); c = mulii(c, d1); } m = addii(mulii(mulii(y1,y2),n), mulii(gel(y,3),x2)); } togglesign(m); r = modii(m, v1); p1 = mulii(r, v2); c3 = addii(c, mulii(r,addii(gel(y,2),p1))); gel(z,1) = mulii(v1,v2); gel(z,2) = addii(gel(y,2), shifti(p1,1)); gel(z,3) = diviiexact(c3,v1); } /* not meant to be efficient */ static GEN qfb_comp_gen(GEN x, GEN y) { GEN d1 = qfb_disc(x), d2 = qfb_disc(y); GEN a1 = gel(x,1), b1 = gel(x,2), c1 = gel(x,3), n1; GEN a2 = gel(y,1), b2 = gel(y,2), c2 = gel(y,3), n2; GEN cx = content(x), cy = content(y), A, B, C, D, U, m, m2; if (!is_pm1(cx)) { a1 = diviiexact(a1, cx); b1 = diviiexact(b1, cx); c1 = diviiexact(c1, cx); d1 = diviiexact(d1, sqri(cx)); } if (!is_pm1(cy)) { a2 = diviiexact(a2, cy); c2 = diviiexact(c2, cy); b2 = diviiexact(b2, cy); d2 = diviiexact(d2, sqri(cy)); } D = gcdii(d1, d2); if (signe(d1) < 0) setsigne(D, -1); if (!Z_issquareall(diviiexact(d1, D), &n1) || !Z_issquareall(diviiexact(d2, D), &n2)) return NULL; A = mulii(a1, n2); B = mulii(a2, n1); C = shifti(addii(mulii(b1, n2), mulii(b2, n1)), -1); U = ZV_extgcd(mkvec3(A, B, C)); m = gel(U,1); U = gmael(U,2,3); A = mulii(diviiexact(mulii(a1,b2),m), gel(U,1)); B = mulii(diviiexact(mulii(a2,b1),m), gel(U,2)); C = addii(mulii(b1,b2), mulii(D, mulii(n1,n2))); C = mulii(diviiexact(shifti(C,-1), m), gel(U,3)); B = addii(A, addii(B, C)); m2 = sqri(m); A = diviiexact(mulii(a1, a2), m2); C = diviiexact(shifti(subii(sqri(B),D), -2), A); cx = mulii(cx, cy); if (!is_pm1(cx)) { A = mulii(A, cx); B = mulii(B, cx); C = mulii(C, cx); D = mulii(D, sqri(cx)); } return mkqfb(A, B, C, D); } static GEN qficomp0(GEN x, GEN y, int raw) { pari_sp av = avma; GEN z = cgetg(5,t_QFB); gel(z,4) = gel(x,4); qfb_comp(z, x,y); if (raw) return gerepilecopy(av,z); return qfbred_imag_av(av, z); } static GEN qfrcomp0(GEN x, GEN y, int raw) { pari_sp av = avma; GEN dx = NULL, dy = NULL; GEN z = cgetg(5,t_QFB); if (typ(x)==t_VEC) { dx = gel(x,2); x = gel(x,1); } if (typ(y)==t_VEC) { dy = gel(y,2); y = gel(y,1); } gel(z,4) = gel(x,4); qfb_comp(z, x,y); if (dx) z = mkvec2(z, dy? addrr(dx, dy): dx); else if (dy) z = mkvec2(z, dy); if (!raw) z = qfbred_real(z); return gerepilecopy(av, z); } /* same discriminant, no distance, no checks */ GEN qfbcomp_i(GEN x, GEN y) { return qfb_is_qfi(x)? qficomp0(x,y,0): qfrcomp0(x,y,0); } GEN qfbcomp(GEN x, GEN y) { GEN qx = check_qfbext("qfbcomp", x); GEN qy = check_qfbext("qfbcomp", y); if (!equalii(gel(qx,4),gel(qy,4))) { pari_sp av = avma; GEN z = qfb_comp_gen(qx, qy); if (typ(x) == t_VEC || typ(y) == t_VEC) pari_err_IMPL("Shanks's distance in general composition"); if (!z) pari_err_OP("*",x,y); return gerepileupto(av, qfbred(z)); } return qfb_is_qfi(qx)? qficomp0(x,y,0): qfrcomp0(x,y,0); } /* same discriminant, no distance, no checks */ GEN qfbcompraw_i(GEN x, GEN y) { return qfb_is_qfi(x)? qficomp0(x,y,1): qfrcomp0(x,y,1); } GEN qfbcompraw(GEN x, GEN y) { GEN qx = check_qfbext("qfbcompraw", x); GEN qy = check_qfbext("qfbcompraw", y); if (!equalii(gel(qx,4),gel(qy,4))) { pari_sp av = avma; GEN z = qfb_comp_gen(qx, qy); if (typ(x) == t_VEC || typ(y) == t_VEC) pari_err_IMPL("Shanks's distance in general composition"); if (!z) pari_err_OP("qfbcompraw",x,y); return gerepilecopy(av, z); } if (!equalii(gel(qx,4),gel(qy,4))) pari_err_OP("qfbcompraw",x,y); return qfb_is_qfi(qx)? qficomp0(x,y,1): qfrcomp0(x,y,1); } static GEN qfisqr0(GEN x, long raw) { pari_sp av = avma; GEN z = cgetg(5,t_QFB); gel(z,4) = gel(x,4); qfb_sqr(z,x); if (raw) return gerepilecopy(av,z); return qfbred_imag_av(av, z); } static GEN qfrsqr0(GEN x, long raw) { pari_sp av = avma; GEN dx = NULL, z = cgetg(5,t_QFB); if (typ(x) == t_VEC) { dx = gel(x,2); x = gel(x,1); } gel(z,4) = gel(x,4); qfb_sqr(z,x); if (dx) z = mkvec2(z, shiftr(dx,1)); if (!raw) z = qfbred_real(z); return gerepilecopy(av, z); } /* same discriminant, no distance, no checks */ GEN qfbsqr_i(GEN x) { return qfb_is_qfi(x)? qfisqr0(x,0): qfrsqr0(x,0); } GEN qfbsqr(GEN x) { GEN qx = check_qfbext("qfbsqr", x); return qfb_is_qfi(qx)? qfisqr0(x,0): qfrsqr0(x,0); } static GEN qfr_1_by_disc(GEN D) { GEN y, r, s; check_quaddisc_real(D, NULL, "qfr_1_by_disc"); y = cgetg(5,t_QFB); s = sqrtremi(D, &r); togglesign(r); /* s^2 - r = D */ if (mpodd(r)) { s = subiu(s,1); r = subii(r, addiu(shifti(s, 1), 1)); r = shifti(r, -2); set_avma((pari_sp)y); s = icopy(s); } else { r = shifti(r, -2); set_avma((pari_sp)s); } gel(y,1) = gen_1; gel(y,2) = s; gel(y,3) = icopy(r); gel(y,4) = icopy(D); return y; } static GEN qfr_disc(GEN x) { return qfb_disc(typ(x)==t_VEC ? gel(x,1): x); } static GEN qfr_1(GEN x) { return qfr_1_by_disc(qfr_disc(x)); } 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 = subiu(y,1); gel(y,2) = y2; av = avma; gel(y,3) = gerepileuptoint(av, shifti(subii(sqri(y2), S->D),-2)); } static GEN qfr5_1(struct qfr_data *S, long prec) { GEN y = cgetg(6, t_VEC); qfr_1_fill(y, S); gel(y,4) = gen_0; gel(y,5) = real_1(prec); return y; } static GEN qfr3_1(struct qfr_data *S) { GEN y = cgetg(4, t_VEC); qfr_1_fill(y, S); return y; } /* Assume D < 0 is the discriminant of a t_QFB */ static GEN qfi_1_by_disc(GEN D) { GEN b,c, y = cgetg(5,t_QFB); quadpoly_bc(D, mod2(D), &b,&c); if (b == gen_m1) b = gen_1; gel(y,1) = gen_1; gel(y,2) = b; gel(y,3) = c; gel(y,4) = icopy(D); return y; } static GEN qfi_1(GEN x) { if (typ(x) != t_QFB) pari_err_TYPE("qfi_1",x); return qfi_1_by_disc(qfb_disc(x)); } GEN qfb_1(GEN x) { return qfb_is_qfi(x) ? qfi_1(x): qfr_1(x); } static GEN _qfimul(void *E, GEN x, GEN y) { (void) E; return qficomp0(x,y,0); } static GEN _qfisqr(void *E, GEN x) { (void) E; return qficomp0(x,x,0); } static GEN _qfimulraw(void *E, GEN x, GEN y) { (void) E; return qficomp0(x,y,1); } static GEN _qfisqrraw(void *E, GEN x) { (void) E; return qficomp0(x,x,1); } static GEN qfipowraw(GEN x, long n) { pari_sp av = avma; GEN y; if (!n) return qfi_1(x); if (n== 1) return gcopy(x); if (n==-1) { x = gcopy(x); togglesign(gel(x,2)); return x; } if (n < 0) x = qfb_inv(x); y = gen_powu(x, labs(n), NULL, &_qfisqrraw, &_qfimulraw); return gerepilecopy(av,y); } static GEN qfipow(GEN x, GEN n) { pari_sp av = avma; GEN y; long s = signe(n); if (!s) return qfi_1(x); if (s < 0) x = qfb_inv(x); y = gen_pow(qfbred_i(x), n, NULL, &_qfisqr, &_qfimul); return gerepilecopy(av,y); } static long parteucl(GEN L, GEN *d, GEN *v3, GEN *v, GEN *v2) { long z; *v = gen_0; *v2 = gen_1; for (z=0; abscmpii(*v3,L) > 0; z++) { GEN t3, t2 = subii(*v, mulii(truedvmdii(*d,*v3,&t3),*v2)); *v = *v2; *d = *v3; *v2 = t2; *v3 = t3; } return z; } /* composition: Shanks' NUCOMP & NUDUPL */ /* L = floor((|d|/4)^(1/4)) */ GEN nucomp(GEN x, GEN y, GEN L) { pari_sp av = avma; long z; GEN a, a1, a2, b2, b, d, d1, g, n, p1, q1, q2, s, u, u1, v, v2, v3, Q; if (x==y) return nudupl(x,L); if (!is_qfi(x)) pari_err_TYPE("nucomp",x); if (!is_qfi(y)) pari_err_TYPE("nucomp",y); if (abscmpii(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 (equali1(d)) { a = negi(mulii(u,n)); d1 = d; } else if (dvdii(s,d)) /* d | s */ { a = negi(mulii(u,n)); d1 = d; a1 = diviiexact(a1, d1); a2 = diviiexact(a2, d1); s = diviiexact(s, d1); } else { GEN p2, l; d1 = bezout(s,d,&u1,NULL); if (!equali1(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 (abscmpii(a,p1) > 0) a = p1; d = a1; v3 = a; z = parteucl(L, &d,&v3, &v,&v2); Q = cgetg(5,t_QFB); 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 (!equali1(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)); gel(Q,4) = gel(x,4); return qfbred_imag_av(av, Q); } GEN nudupl(GEN x, GEN L) { pari_sp av = avma; long z; GEN u, v, d, d1, p1, a, b, c, a2, b2, c2, Q, v2, v3, g; if (!is_qfi(x)) pari_err_TYPE("nudupl",x); a = gel(x,1); b = gel(x,2); d1 = bezout(b,a, &u,NULL); if (!equali1(d1)) { a = diviiexact(a, d1); b = diviiexact(b, d1); } c = modii(negi(mulii(u,gel(x,3))), a); p1 = subii(c,a); if (abscmpii(c,p1) > 0) c = p1; d = a; v3 = c; z = parteucl(L, &d,&v3, &v,&v2); a2 = sqri(d); c2 = sqri(v3); Q = cgetg(5,t_QFB); 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 (!equali1(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)); gel(Q,4) = gel(x,4); return qfbred_imag_av(av, Q); } static GEN mul_nucomp(void *l, GEN x, GEN y) { return nucomp(x, y, (GEN)l); } static GEN mul_nudupl(void *l, GEN x) { return nudupl(x, (GEN)l); } GEN nupow(GEN x, GEN n, GEN L) { pari_sp av; GEN y, D; if (typ(n) != t_INT) pari_err_TYPE("nupow",n); if (!is_qfi(x)) pari_err_TYPE("nupow",x); if (gequal1(n)) return gcopy(x); av = avma; D = qfb_disc(x); y = qfi_1_by_disc(D); if (!signe(n)) return y; if (!L) L = sqrtnint(absi_shallow(D), 4); y = gen_pow_i(x, n, (void*)L, &mul_nudupl, &mul_nucomp); if (signe(n) < 0 && !absequalii(gel(y,1),gel(y,2)) && !absequalii(gel(y,1),gel(y,3))) togglesign(gel(y,2)); return gerepilecopy(av, y); } /* Not stack-clean */ GEN qfr5_compraw(GEN x, GEN y) { 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); return z; } GEN qfr5_comp(GEN x, GEN y, struct qfr_data *S) { return qfr5_red(qfr5_compraw(x, y), S); } /* Not stack-clean */ GEN qfr3_compraw(GEN x, GEN y) { GEN z = cgetg(4,t_VEC); qfb_comp(z,x,y); return z; } GEN qfr3_comp(GEN x, GEN y, struct qfr_data *S) { return qfr3_red(qfr3_compraw(x,y), S); } /* m > 0. Not stack-clean */ static GEN qfr5_powraw(GEN x, long m) { GEN y = NULL; for (; m; m >>= 1) { if (m&1) y = y? qfr5_compraw(y,x): x; if (m == 1) break; x = qfr5_compraw(x,x); } return y; } /* 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))); if (s < 0) x = qfb_inv(x); 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; } /* m > 0; return x^m. Not stack-clean */ static GEN qfr3_powraw(GEN x, long m) { GEN y = NULL; for (; m; m>>=1) { if (m&1) y = y? qfr3_compraw(y,x): x; if (m == 1) break; x = qfr3_compraw(x,x); } 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 = qfb_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; } static GEN qfrinvraw(GEN x) { if (typ(x) == t_VEC) retmkvec2(qfbinv(gel(x,1)), negr(gel(x,2))); return qfbinv(x); } static GEN qfrpowraw(GEN x, long n) { struct qfr_data S = { NULL, NULL, NULL }; pari_sp av = avma; if (n==1) return gcopy(x); if (n==-1) return qfrinvraw(x); if (typ(x)==t_QFB) { GEN D = qfb_disc(x); if (!n) return qfr_1(x); if (n < 0) { x = qfb_inv(x); n = -n; } x = qfr3_powraw(x, n); x = qfr3_to_qfr(x, D); } else { GEN d0 = gel(x,2); x = gel(x,1); if (!n) retmkvec2(qfr_1(x), real_0(precision(d0))); if (n < 0) { x = qfb_inv(x); n = -n; } x = qfr5_init(x, d0, &S); if (labs(n) != 1) x = qfr5_powraw(x, n); x = qfr5_to_qfr(x, S.D, mulrs(d0,n)); } return gerepilecopy(av, x); } static GEN qfrpow(GEN x, GEN n) { struct qfr_data S = { NULL, NULL, NULL }; long s = signe(n); pari_sp av = avma; if (typ(x)==t_QFB) { if (!s) return qfr_1(x); if (s < 0) x = qfb_inv(x); x = qfr3_init(x, &S); x = is_pm1(n)? qfr3_red(x, &S): qfr3_pow(x, n, &S); x = qfr3_to_qfr(x, S.D); } else { GEN d0 = gel(x,2); x = gel(x,1); if (!s) retmkvec2(qfr_1(x), real_0(precision(d0))); if (s < 0) x = qfb_inv(x); x = qfr5_init(x, d0, &S); x = is_pm1(n)? qfr5_red(x, &S): qfr5_pow(x, n, &S); x = qfr5_to_qfr(x, S.D, mulri(d0,n)); } return gerepilecopy(av, x); } GEN qfbpowraw(GEN x, long n) { GEN q = check_qfbext("qfbpowraw",x); return qfb_is_qfi(q)? qfipowraw(x,n): qfrpowraw(x,n); } /* same discriminant, no distance, no checks */ GEN qfbpow_i(GEN x, GEN n) { return qfb_is_qfi(x)? qfipow(x,n): qfrpow(x,n); } GEN qfbpow(GEN x, GEN n) { GEN q = check_qfbext("qfbpow",x); return qfb_is_qfi(q)? qfipow(x,n): qfrpow(x,n); } GEN qfbpows(GEN x, long n) { long N[] = { evaltyp(t_INT) | _evallg(3), 0, 0}; affsi(n, N); return qfbpow(x, N); } /* Prime forms attached to prime ideals of degree 1 */ /* assume x != 0 a t_INT, p > 0 * Return a t_QFB, 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(5, t_QFB); pari_sp av = avma; ulong b; long s; s = mod8(x); if (signe(x) < 0 && s) s = 8-s; /* 2 or 3 mod 4 */ if (s & 2) pari_err_DOMAIN("primeform", "disc % 4", ">",gen_1, x); if (p == 2) { switch(s) { case 0: b = 0; break; case 1: b = 1; break; case 4: b = 2; break; default: pari_err_SQRTN("primeform", mkintmod(x,utoi(p)) ); b = 0; /* -Wall */ } c = shifti(subsi(s,x), -3); } else { b = Fl_sqrt(umodiu(x,p), p); if (b == ~0UL) pari_err_SQRTN("primeform", mkintmod(x,utoi(p)) ); /* mod(b) != mod2(x) ? */ if ((b ^ s) & 1) b = p - b; c = diviuexact(shifti(subii(sqru(b), x), -2), p); } gel(y,3) = gerepileuptoint(av, c); gel(y,4) = icopy(x); 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) { const char *f = "primeform"; pari_sp av; long s, sx = signe(x), sp = signe(p); GEN y, b, absp; if (typ(x) != t_INT) pari_err_TYPE(f,x); if (typ(p) != t_INT) pari_err_TYPE(f,p); if (!sp) pari_err_DOMAIN(f,"p","=",gen_0,p); if (!sx) pari_err_DOMAIN(f,"D","=",gen_0,x); if (lgefint(p) == 3) { ulong pp = p[2]; if (pp == 1) { if (sx < 0) { long r; if (sp < 0) pari_err_IMPL("negative definite t_QFB"); r = mod4(x); if (r && r != 3) pari_err_DOMAIN(f,"disc % 4",">", gen_1,x); return qfi_1_by_disc(x); } y = qfr_1_by_disc(x); if (sp < 0) { gel(y,1) = gen_m1; togglesign(gel(y,3)); } return y; } y = primeform_u(x, pp); if (sx < 0) { if (sp < 0) pari_err_IMPL("negative definite t_QFB"); return y; } if (sp < 0) { togglesign(gel(y,1)); togglesign(gel(y,3)); } return gcopy( qfr3_to_qfr(y, x) ); } s = mod8(x); if (sx < 0) { if (sp < 0) pari_err_IMPL("negative definite t_QFB"); if (s) s = 8-s; } y = cgetg(5, t_QFB); /* 2 or 3 mod 4 */ if (s & 2) pari_err_DOMAIN(f, "disc % 4", ">",gen_1, x); absp = absi_shallow(p); av = avma; b = Fp_sqrt(x, absp); if (!b) pari_err_SQRTN(f, mkintmod(x,absp)); s &= 1; /* s = x mod 2 */ /* mod(b) != mod2(x) ? [Warning: we may have b == 0] */ if ((!signe(b) && s) || mod2(b) != s) b = gerepileuptoint(av, subii(absp,b)); av = avma; gel(y,3) = gerepileuptoint(av, diviiexact(shifti(subii(sqri(b), x), -2), p)); gel(y,4) = icopy(x); gel(y,2) = b; gel(y,1) = icopy(p); return y; } static GEN normforms(GEN D, GEN fa) { long i, j, k, lB, aN, sa; GEN a, L, V, B, N, N2; int D_odd = mpodd(D); a = typ(fa) == t_INT ? fa: typ(fa) == t_VEC? gel(fa,1): factorback(fa); sa = signe(a); if (sa==0 || (signe(D)<0 && sa<0)) return NULL; V = D_odd? Zn_quad_roots(fa, gen_1, shifti(subsi(1, D), -2)) : Zn_quad_roots(fa, gen_0, negi(shifti(D, -2))); if (!V) return NULL; N = gel(V,1); B = gel(V,2); lB = lg(B); N2 = shifti(N,1); aN = itou(diviiexact(a, N)); /* |a|/N */ L = cgetg((lB-1)*aN+1, t_VEC); for (k = 1, i = 1; i < lB; i++) { GEN b = shifti(gel(B,i), 1), c, C; if (D_odd) b = addiu(b , 1); c = diviiexact(shifti(subii(sqri(b), D), -2), a); for (j = 0;; b = addii(b, N2)) { gel(L, k++) = mkqfb(a, b, c, D); if (++j == aN) break; C = addii(b, N); if (aN > 1) C = diviuexact(C, aN); c = sa > 0? addii(c, C): subii(c, C); } } return L; } /* Let M and N in SL2(Z), return (N*M^-1)[,1] */ static GEN SL2_div_mul_e1(GEN N, GEN M) { GEN b = gcoeff(M,2,1), d = gcoeff(M,2,2); GEN A = mulii(gcoeff(N,1,1), d), B = mulii(gcoeff(N,1,2), b); GEN C = mulii(gcoeff(N,2,1), d), D = mulii(gcoeff(N,2,2), b); retmkvec2(subii(A,B), subii(C,D)); } static GEN qfisolve_normform(GEN Q, GEN P) { GEN a = gel(Q,1), N = gel(Q,2); GEN M, b = qfbredsl2_imag_basecase(P, &M); if (!qfb_equal(a,b)) return NULL; return SL2_div_mul_e1(N,M); } /* Test equality modulo GL2 of two reduced forms */ static int GL2_qfb_equal(GEN a, GEN b) { return equalii(gel(a,1),gel(b,1)) && absequalii(gel(a,2),gel(b,2)) && equalii(gel(a,3),gel(b,3)); } /* Q(u,v) = p; if s < 0 return that solution; else the set of all solutions */ static GEN allsols(GEN Q, long s, GEN u, GEN v) { GEN w = mkvec2(u, v), b; if (signe(v) < 0) { u = negi(u); v = negi(v); } /* normalize for v >= 0 */ w = mkvec2(u, v); if (s < 0) return w; if (!s) return mkvec(w); b = gel(Q,2); /* sum of the 2 solutions (if they exist) is -bv / a */ if (signe(b)) { /* something to check */ GEN r, t; t = dvmdii(mulii(b, v), gel(Q,1), &r); if (signe(r)) return mkvec(w); u = addii(u, t); } return mkvec2(w, mkvec2(negi(u), v)); } static GEN qfisolvep_all(GEN Q, GEN p, long all) { GEN R, U, V, M, N, x, q, D = qfb_disc(Q); long s = kronecker(D, p); if (s < 0) return NULL; if (!all) s = -1; /* to indicate we want a single solution */ /* Solutions iff a class of maximal ideal above p is the class of Q; * Two solutions iff (s > 0 and the class has order > 2), else one */ if (!signe(gel(Q,2))) { /* if principal form, use faster cornacchia */ GEN a = gel(Q,1), c = gel(Q,3); if (equali1(a)) { if (!cornacchia(c, p, &M,&N)) return NULL; return allsols(Q, s, M, N); } if (equali1(c)) { if (!cornacchia(a, p, &M,&N)) return NULL; return allsols(Q, s, N, M); } } R = qfbredsl2_imag_basecase(Q, &U); if (equali1(gel(R,1))) { /* principal form */ if (!signe(gel(R,2))) { if (!cornacchia(gel(R,3), p, &M,&N)) return NULL; x = mkvec2(M,N); } else { /* x^2 + xy + ((1-D)/4)y^2 = p <==> (2x + y)^2 - D y^2 = 4p */ if (!cornacchia2(negi(D), p, &M, &N)) return NULL; x = subii(M,N); if (mpodd(x)) return NULL; x = mkvec2(shifti(x,-1), N); } x = ZM_ZC_mul(U, x); x[0] = evaltyp(t_VEC) | _evallg(3); /* transpose */ return allsols(Q, s, gel(x,1), gel(x,2)); } q = qfbredsl2_imag_basecase(primeform(D, p), &V); if (!GL2_qfb_equal(R,q)) return NULL; if (signe(gel(R,2)) != signe(gel(q,2))) gcoeff(V,2,1) = negi(gcoeff(V,2,1)); x = SL2_div_mul_e1(U,V); return allsols(Q, s, gel(x,1), gel(x,2)); } GEN qfisolvep(GEN Q, GEN p) { pari_sp av = avma; GEN x = qfisolvep_all(Q, p, 0); return x? gerepilecopy(av, x): gc_const(av, gen_0); } static GEN qfrsolve_normform(GEN N, GEN Ps, GEN rd) { pari_sp av = avma, btop; GEN M = N, P = qfbredsl2_real_basecase(Ps, rd), Q = P; btop = avma; for(;;) { if (qfb_equal(gel(M,1), gel(P,1))) return gerepileupto(av, SL2_div_mul_e1(gel(M,2),gel(P,2))); if (qfb_equal(gel(N,1), gel(Q,1))) return gerepileupto(av, SL2_div_mul_e1(gel(N,2),gel(Q,2))); M = rhorealsl2(M, rd); if (qfb_equal(gel(M,1), gel(N,1))) return gc_NULL(av); Q = rhorealsl2(Q, rd); if (qfb_equal(gel(P,1), gel(Q,1))) return gc_NULL(av); if (gc_needed(btop, 1)) gerepileall(btop, 2, &M, &Q); } } GEN qfrsolvep(GEN Q, GEN p) { pari_sp av = avma; GEN N, x, rd, d = qfb_disc(Q); if (kronecker(d, p) < 0) return gc_const(av, gen_0); rd = sqrti(d); N = qfbredsl2_real(Q, rd); x = qfrsolve_normform(N, primeform(d, p), rd); return x? gerepileupto(av, x): gc_const(av, gen_0); } static GEN known_prime(GEN v) { GEN p, e, fa = check_arith_all(v, "qfbsolve"); if (!fa) return BPSW_psp(v)? v: NULL; if (lg(gel(fa,1)) != 2) return NULL; p = gcoeff(fa,1,1); e = gcoeff(fa,1,2); return (equali1(e) && !is_pm1(p) && signe(p) > 0)? p: NULL; } static GEN qfsolve_normform(GEN Q, GEN f, GEN rd) { return rd? qfrsolve_normform(Q, f, rd): qfisolve_normform(Q, f); } static GEN qfbsolve_primitive_i(GEN Q, GEN rd, GEN *Qr, GEN fa, long all) { GEN x, W, F, p; long i, j, l; if (!rd && (p = known_prime(fa))) return qfisolvep_all(Q, p, all); F = normforms(qfb_disc(Q), fa); if (!F) return NULL; if (!*Qr) *Qr = qfbredsl2(Q, rd); l = lg(F); W = all? cgetg(l, t_VEC): NULL; for (j = i = 1; i < l; i++) if ((x = qfsolve_normform(*Qr, gel(F,i), rd))) { if (!all) return x; gel(W,j++) = x; } if (j == 1) return NULL; setlg(W,j); return lexsort(W); } static GEN qfb_initrd(GEN Q) { GEN d = qfb_disc(Q); return signe(d) > 0? sqrti(d): NULL; } static GEN qfbsolve_primitive(GEN Q, GEN fa, long all) { GEN x, Qr = NULL, rdQ = qfb_initrd(Q); x = qfbsolve_primitive_i(Q, rdQ, &Qr, fa, all); if (!x) return cgetg(1, t_VEC); return x; } /* f / g^2 */ static GEN famat_divsqr(GEN f, GEN g) { return famat_reduce(famat_div_shallow(f, famat_pows_shallow(g,2))); } static GEN qfbsolve_all(GEN Q, GEN n, long all) { GEN W, Qr = NULL, fa = factorint(n, 0), rdQ = qfb_initrd(Q); GEN D = divisors_factored(mkmat2(gel(fa,1), gshift(gel(fa,2),-1))); long i, j, l = lg(D); W = all? cgetg(l, t_VEC): NULL; for (i = j = 1; i < l; i++) { GEN w, d = gel(D,i), FA = i == 1? fa: famat_divsqr(fa, gel(d,2)); if ((w = qfbsolve_primitive_i(Q, rdQ, &Qr, FA, all))) { if (i != 1) w = RgV_Rg_mul(w, gel(d,1)); if (!all) return w; gel(W,j++) = w; } } if (j == 1) return cgetg(1, t_VEC); setlg(W,j); return lexsort(shallowconcat1(W)); } GEN qfbsolve(GEN Q, GEN n, long fl) { pari_sp av = avma; if (typ(Q) != t_QFB) pari_err_TYPE("qfbsolve",Q); if (fl < 0 || fl > 3) pari_err_FLAG("qfbsolve"); return gerepilecopy(av, (fl & 2)? qfbsolve_all(Q, n, fl & 1) : qfbsolve_primitive(Q, n, fl & 1)); } /* 1 if there exists x,y such that x^2 + dy^2 = p, 0 otherwise; * Assume d > 0 and p is prime */ long cornacchia(GEN d, GEN p, GEN *px, GEN *py) { pari_sp av = avma; GEN b, c, r; *px = *py = gen_0; b = subii(p, d); if (signe(b) < 0) return gc_long(av,0); if (signe(b) == 0) { *py = gen_1; return gc_long(av,1); } b = Fp_sqrt(b, p); /* sqrt(-d) */ if (!b) return gc_long(av,0); b = gmael(halfgcdii(p, b), 2, 2); c = dvmdii(subii(p, sqri(b)), d, &r); if (r != gen_0 || !Z_issquareall(c, &c)) return gc_long(av,0); set_avma(av); *px = icopy(b); *py = icopy(c); return 1; } static GEN lastqi(GEN Q) { GEN s = gcoeff(Q,1,1), q = gcoeff(Q,1,2), p = absi_shallow(gcoeff(Q,2,2)); if (!signe(q)) return gen_0; if (!signe(s)) return p; if (is_pm1(q)) return subiu(p,1); return divii(p, absi_shallow(q)); } static long cornacchia2_i(long av, GEN d, GEN p, GEN b, GEN px4, GEN *px, GEN *py) { GEN M, Q, V, c, r, b2; if (!signe(b)) { /* d = p,2p,3p,4p */ set_avma(av); if (absequalii(d, px4)){ *py = gen_1; return 1; } if (absequalii(d, p)) { *py = gen_2; return 1; } return 0; } if (mod2(b) != mod2(d)) b = subii(p,b); M = halfgcdii(shifti(p,1), b); Q = gel(M,1); V = gel(M, 2); b = addii(mulii(gel(V,1), lastqi(Q)), gel(V,2)); b2 = sqri(b); if (cmpii(b2,px4) > 0) { b = gel(V,1); b2 = sqri(b); if (cmpii(b2,px4) > 0) { b = gel(V,2); b2 = sqri(b); } } c = dvmdii(subii(px4, b2), d, &r); if (r != gen_0 || !Z_issquareall(c, &c)) return gc_long(av,0); set_avma(av); *px = icopy(b); *py = icopy(c); return 1; } /* 1 if there exists x,y such that x^2 + dy^2 = 4p, 0 otherwise; * Assume d > 0 is congruent to 0 or 3 mod 4 and p is prime */ long cornacchia2(GEN d, GEN p, GEN *px, GEN *py) { pari_sp av = avma; GEN b, p4 = shifti(p,2); *px = *py = gen_0; if (abscmpii(p4, d) < 0) return gc_long(av,0); if (absequaliu(p, 2)) { set_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) return gc_long(av,0); return cornacchia2_i(av, d, p, b, p4, px, py); } /* 1 if there exists x,y such that x^2 + dy^2 = 4p [p prime], 0 otherwise */ long cornacchia2_sqrt(GEN d, GEN p, GEN b, GEN *px, GEN *py) { pari_sp av = avma; GEN p4 = shifti(p,2); *px = *py = gen_0; if (abscmpii(p4, d) < 0) return gc_long(av,0); return cornacchia2_i(av, d, p, b, p4, px, py); } GEN qfbcornacchia(GEN d, GEN p) { pari_sp av = avma; GEN x, y; if (typ(d) != t_INT || signe(d) <= 0) pari_err_TYPE("qfbcornacchia", d); if (typ(p) != t_INT || cmpiu(p, 2) < 0) pari_err_TYPE("qfbcornacchia", p); if (mod4(p)? cornacchia(d, p, &x, &y): cornacchia2(d, shifti(p, -2), &x, &y)) return gerepilecopy(av, mkvec2(x, y)); set_avma(av); return cgetg(1, t_VEC); } pari-2.17.2/src/basemath/msfarey.c0000644000175000017500000002103514676526175015375 0ustar billbill/* Copyright (C) 2000, 2012 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" static long conginlist(GEN L, GEN g, void *E, long (*in)(void *, GEN )) { pari_sp av = avma; long i, l = lg(L); GEN gi = ginv(g); for (i = 1; i < l; i++) if (in(E, gmul(gel(L,i), gi))) break; return gc_long(av, i); } static GEN normalise(GEN M) { long sd = signe(gcoeff(M,2,2)); if (sd < 0 || (!sd && signe(gcoeff(M,1,2)) < 0)) M = ZM_neg(M); return M; } static void filln(GEN V, long n, long a, long c) { long i, j; for (j = a + 1, i = 1; i < n; i++) { /* j != a (mod n) */ gel(V,i) = mkvecsmall2(c, j); if (++j > n) j = 1; } } /* set v[k+1..k+n-1] or (k == l) append to v; 0 <= a < n */ static GEN vec_insertn(GEN v, long n, long k, long a, long c) { long i, j, l = lg(v), L = l + n-1; GEN V = cgetg(L, t_VEC); if (k == l) { for (i = 1; i < l; i++) gel(V,i) = gel(v,i); filln(V + i-1, n, a, c); } else { for (i = 1; i <= k; i++) gel(V,i) = gel(v,i); filln(V + i-1, n, a, c); i += n - 1; for (j = k + 1; j < l; j++) gel(V,i++) = gel(v,j); } return V; } /* append the [c,L[i]], i=1..#L to v */ static GEN vec_appendL(GEN v, GEN L, long c) { long i, j, lv, l = lg(L); GEN w; if (l == 1) return v; lv = lg(v); w = cgetg(lv + l -1, typ(v)); for (i = 1; i < lv; i++) gel(w,i) = gel(v,i); for (j = 1; j < l; i++, j++) gel(w,i) = mkvecsmall2(c, L[j]); return w; } #define newcoset(g, k, a) \ { \ long _c = lg(C); \ C = vec_append(C, g); \ M = vec_append(M, zero_zv(n)); \ L3= vec_appendL(L3, list3, _c); \ L = vec_appendL(L, list, _c); \ B = vec_insertn(B, n, k, a % n, _c); \ } static long _isin2(GEN L, long m, long a) { pari_sp av = avma; long k = RgV_isin(L, mkvecsmall2(m,a)); return gc_long(av, k? k: lg(L)); } static void get2(GEN x, long *a, long *b) { *a = x[1]; *b = x[2]; } static GEN denval(GEN g) { GEN a = gcoeff(g,1,1), c = gcoeff(g,2,1); return signe(c)? denom_i(gdiv(a,c)): gen_0; } /* M * S, S = [0,1;-1,0] */ static GEN mulS(GEN g) { GEN a = gcoeff(g,1,1), b = gcoeff(g,1,2); GEN c = gcoeff(g,2,1), d = gcoeff(g,2,2); retmkmat22(negi(b), a, negi(d), c); } /* remove extra scales and reduce ast to involution */ static GEN rectify(GEN V, GEN ast, GEN gam) { long n = lg(V)-1, n1, i, def, m, dec; GEN V1, a1, g1, d, inj; pari_sp av; for(i = 1, def = 0; i <= n; i++) if (ast[ast[i]] != i) def++; def /= 3; if (!def) return mkvec3(V, ast, gam); n1 = n + def; g1 = cgetg(n1+1, t_VEC); V1 = cgetg(n1+1, t_VEC); a1 = cgetg(n1+1, t_VECSMALL); d = cgetg(def+1, t_VECSMALL); av = avma; for (i = m = 1; i <= n; i++) { long i2 = ast[i], i3 = ast[i2]; if (i2 > i && i3 > i) { GEN d1 = denval(ZM_mul(gel(gam,i), gel(V,ast[i]))); GEN d2 = denval(ZM_mul(gel(gam,i2), gel(V,ast[i2]))); GEN d3 = denval(ZM_mul(gel(gam,i3), gel(V,ast[i3]))); if (cmpii(d1,d2) <= 0) d[m++] = cmpii(d1,d3) <= 0? i: i3; else d[m++] = cmpii(d2,d3) <= 0? i2: i3; } } set_avma(av); inj = zero_zv(n); for (i = 1; i <= def; i++) inj[d[i]] = 1; for (i = 1, dec = 0; i <= n; i++) { dec += inj[i]; inj[i] = i + dec; } for (i = 1; i <= n; i++) if (ast[ast[i]] == i) { gel(g1, inj[i]) = gel(gam,i); gel(V1, inj[i]) = gel(V,i); a1[inj[i]] = inj[ast[i]]; } for (i = 1; i <= def; i++) { long a = d[i], b = ast[a], c = ast[b]; GEN igc; gel(V1, inj[b]) = gel(V, b); gel(g1, inj[b]) = normalise(SL2_inv_shallow(gel(gam,a))); a1[inj[b]] = inj[a]-1; gel(V1, inj[c]) = gel(V, c); gel(g1, inj[c]) = gel(gam, c); a1[inj[c]] = inj[a]; gel(V1, inj[a]-1) = normalise(ZM_mul(gel(gam,a), mulS(gel(V,b)))); gel(g1, inj[a]-1) = gel(gam, a); a1[inj[a]-1] = inj[b]; igc = SL2_inv_shallow(gel(gam,c)); gel(V1, inj[a]) = normalise(ZM_mul(igc, mulS(gel(V,c)))); gel(g1, inj[a]) = normalise(igc); a1[inj[a]] = inj[c]; } return mkvec3(V1, a1, g1); } static GEN vecpop(GEN v) { long l = lg(v); *v++ = evaltyp(t_VEC)|_evallg(1); /* stackdummy */ *v = evaltyp(t_VEC)|_evallg(l-1); return v; } GEN msfarey(GEN F, void *E, long (*in)(void *, GEN), GEN *pCM) { pari_sp av = avma, av2, av3; GEN V = gel(F,1), ast = gel(F,2), gam = gel(F,3), V2, ast2, gam2; GEN C, M, L3, L, B, g, list3, list, perm, v2; long n = lg(gam)-1, i, k, m, a, l, c, c3; list = cgetg(n+1, t_VECSMALL); list3 = cgetg(n+1, t_VECSMALL); for (i = c = c3 = 1; i <= n; i++) { long t; if (ast[i] == i) t = !isintzero(gtrace(gel(gam,i))); else t = ast[ast[i]] != i; if (t) list3[c3++] = i; else list[c++] = i; } setlg(list, c); setlg(list3, c3); if (typ(ast) == t_VEC) ast = ZV_to_zv(ast); av2 = avma; C = M = L = L3 = cgetg(1, t_VEC); B = mkvec(mkvecsmall2(1,1)); newcoset(matid(2),1,1); while(lg(L)-1 + lg(L3)-1) { while(lg(L3)-1) { get2(gel(L3,1), &m,&a); L3 = vecpop(L3); av3 = avma; g = ZM_mul(gel(C,m), gel(gam,a)); k = conginlist(C, g, E, in); gel(M,m)[a] = k; if (k < lg(C)) set_avma(av3); else { k = _isin2(B, m, a); newcoset(g, k, ast[a]); newcoset(ZM_mul(g,gel(gam,ast[a])), k+n-1, ast[ast[a]]); B = vecsplice(B, k); } } get2(gel(L,1), &m,&a); L = vecpop(L); if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"msfarey, #L = %ld", lg(L)-1); gerepileall(av2, 4, &C, &M, &L, &B); L3 = cgetg(1, t_VEC); } av3 = avma; g = ZM_mul(gel(C,m), gel(gam,a)); k = conginlist(C, g, E, in); gel(M,m)[a] = k; /* class of C[m]*gam[a] */ if (k < lg(C)) set_avma(av3); else { k = _isin2(B, m, a); newcoset(g,k,ast[a]); B = vecsplice(B,k); } } vecvecsmall_sort_inplace(B, &perm); l = lg(B); V2 = cgetg(l, t_VEC); gam2 = cgetg(l, t_VEC); ast2 = cgetg(l, t_VECSMALL); v2 = cgetg(3, t_VECSMALL); for (i = 1; i < l; i++) { long r, j = perm[i]; GEN ig; get2(gel(B,i), &m,&a); r = gel(M,m)[a]; ig = SL2_inv_shallow(gel(C,r)); gel(V2, j) = normalise(ZM_mul(gel(C,m), gel(V,a))); gel(gam2, j) = normalise(ZM_mul(ZM_mul(gel(C,m), gel(gam,a)), ig)); v2[1] = r; v2[2] = ast[a]; k = vecvecsmall_search(B,v2); if (k < 0) pari_err(e_MISC, "msfarey: H is not a subgroup of PSL_2(Z)"); ast2[j] = perm[k]; } F = rectify(V2, ast2, gam2); if (pCM) *pCM = mkvec2(C,M); return gc_all(av, pCM? 2: 1, &F, pCM); } GEN mscosets(GEN G, void *E, long (*in)(void *, GEN)) { pari_sp av = avma; GEN g, L, M; long n = lg(G)-1, i, m, k; g = gel(G,1); L = mkvec(typ(g) == t_VECSMALL? identity_perm(lg(g)-1): gdiv(g,g)); M = mkvec(zero_zv(n)); for (m = 1; m < lg(L); m++) for (i = 1; i <= n; i++) { g = gmul(gel(L,m), gel(G,i)); mael(M, m, i) = k = conginlist(L, g, E, in); if (k > lg(L)-1) { L = vec_append(L,g); M = vec_append(M, zero_zv(n)); } if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"mscosets, #L = %ld", lg(L)-1); gerepileall(av, 2, &M, &L); } } return gerepilecopy(av, mkvec2(L, M)); } int checkfarey_i(GEN F) { GEN V, ast, gam; if (typ(F) != t_VEC || lg(F) < 4) return 0; V = gel(F,1); ast = gel(F,2); gam = gel(F,3); if (typ(V) != t_VEC || (typ(ast) != t_VECSMALL && (typ(ast) != t_VEC || !RgV_is_ZV(ast))) || typ(gam) != t_VEC || lg(V) != lg(ast) || lg(ast) != lg(gam)) return 0; return 1; } static int check_inH(GEN inH) { return (typ(inH) == t_CLOSURE && closure_arity(inH) == 1 && !closure_is_variadic(inH)); } GEN msfarey0(GEN F, GEN code, GEN *pCM) { if (!checkfarey_i(F)) pari_err_TYPE("msfarey", F); if (!check_inH(code)) pari_err_TYPE("msfarey", code); return msfarey(F, (void*)code, gp_callbool, pCM); } GEN mscosets0(GEN V, GEN code) { if (typ(V) != t_VEC) pari_err_TYPE("mscosets", V); if (!check_inH(code)) pari_err_TYPE("mscosets", code); if (lg(V) == 1) pari_err_TYPE("mscosets [trivial group]", V); return mscosets(V, (void*)code, gp_callbool); } pari-2.17.2/src/basemath/arith1.c0000644000175000017500000030527214760123736015115 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*********************************************************************/ /** ARITHMETIC FUNCTIONS **/ /** (first part) **/ /*********************************************************************/ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_arith /******************************************************************/ /* GENERATOR of (Z/mZ)* */ /******************************************************************/ static GEN remove2(GEN q) { long v = vali(q); return v? shifti(q, -v): q; } static ulong u_remove2(ulong q) { return q >> vals(q); } GEN odd_prime_divisors(GEN q) { return gel(Z_factor(remove2(q)), 1); } static GEN u_odd_prime_divisors(ulong q) { return gel(factoru(u_remove2(q)), 1); } /* p odd prime, q=(p-1)/2; L0 list of (some) divisors of q = (p-1)/2 or NULL * (all prime divisors of q); return the q/l, l in L0 */ static GEN is_gener_expo(GEN p, GEN L0) { GEN L, q = shifti(p,-1); long i, l; if (L0) { l = lg(L0); L = cgetg(l, t_VEC); } else { L0 = L = odd_prime_divisors(q); l = lg(L); } for (i=1; i> 1; long i; GEN L; if (!L0) L0 = u_odd_prime_divisors(q); L = cgetg_copy(L0,&i); while (--i) L[i] = q / uel(L0,i); return L; } int is_gener_Fl(ulong x, ulong p, ulong p_1, GEN L) { long i; if (krouu(x, p) >= 0) return 0; for (i=lg(L)-1; i; i--) { ulong t = Fl_powu(x, uel(L,i), p); if (t == p_1 || t == 1) return 0; } return 1; } /* assume p prime */ ulong pgener_Fl_local(ulong p, GEN L0) { const pari_sp av = avma; const ulong p_1 = p-1; long x; GEN L; if (p <= 19) switch(p) { /* quick trivial cases */ case 2: return 1; case 7: case 17: return 3; default: return 2; } L = u_is_gener_expo(p,L0); for (x = 2;; x++) if (is_gener_Fl(x,p,p_1,L)) return gc_ulong(av, x); } ulong pgener_Fl(ulong p) { return pgener_Fl_local(p, NULL); } /* L[i] = set of (p-1)/2l, l ODD prime divisor of p-1 (l=2 can be included, * but wasteful) */ int is_gener_Fp(GEN x, GEN p, GEN p_1, GEN L) { long i, t = lgefint(x)==3? kroui(x[2], p): kronecker(x, p); if (t >= 0) return 0; for (i = lg(L)-1; i; i--) { GEN t = Fp_pow(x, gel(L,i), p); if (equalii(t, p_1) || equali1(t)) return 0; } return 1; } /* assume p prime, return a generator of all L[i]-Sylows in F_p^*. */ GEN pgener_Fp_local(GEN p, GEN L0) { pari_sp av0 = avma; GEN x, p_1, L; if (lgefint(p) == 3) { ulong z; if (p[2] == 2) return gen_1; if (L0) L0 = ZV_to_nv(L0); z = pgener_Fl_local(uel(p,2), L0); return gc_utoipos(av0, z); } p_1 = subiu(p,1); L = is_gener_expo(p, L0); x = utoipos(2); for (;; x[2]++) { if (is_gener_Fp(x, p, p_1, L)) break; } return gc_utoipos(av0, uel(x,2)); } GEN pgener_Fp(GEN p) { return pgener_Fp_local(p, NULL); } ulong pgener_Zl(ulong p) { if (p == 2) pari_err_DOMAIN("pgener_Zl","p","=",gen_2,gen_2); /* only p < 2^32 such that znprimroot(p) != znprimroot(p^2) */ if (p == 40487) return 10; #ifndef LONG_IS_64BIT return pgener_Fl(p); #else if (p < (1UL<<32)) return pgener_Fl(p); else { const pari_sp av = avma; const ulong p_1 = p-1; long x ; GEN p2 = sqru(p), L = u_is_gener_expo(p, NULL); for (x=2;;x++) if (is_gener_Fl(x,p,p_1,L) && !is_pm1(Fp_powu(utoipos(x),p_1,p2))) return gc_ulong(av, x); } #endif } /* p prime. Return a primitive root modulo p^e, e > 1 */ GEN pgener_Zp(GEN p) { if (lgefint(p) == 3) return utoipos(pgener_Zl(p[2])); else { const pari_sp av = avma; GEN p_1 = subiu(p,1), p2 = sqri(p), L = is_gener_expo(p,NULL); GEN x = utoipos(2); for (;; x[2]++) if (is_gener_Fp(x,p,p_1,L) && !equali1(Fp_pow(x,p_1,p2))) break; return gc_utoipos(av, uel(x,2)); } } static GEN gener_Zp(GEN q, GEN F) { GEN p = NULL; long e = 0; if (F) { GEN P = gel(F,1), E = gel(F,2); long i, l = lg(P); for (i = 1; i < l; i++) { p = gel(P,i); if (absequaliu(p, 2)) continue; if (i < l-1) pari_err_DOMAIN("znprimroot", "n","=",F,F); e = itos(gel(E,i)); } if (!p) pari_err_DOMAIN("znprimroot", "n","=",F,F); } else e = Z_isanypower(q, &p); if (!BPSW_psp(e? p: q)) pari_err_DOMAIN("znprimroot", "n","=", q,q); return e > 1? pgener_Zp(p): pgener_Fp(q); } GEN znprimroot(GEN N) { pari_sp av = avma; GEN x, n, F; if ((F = check_arith_non0(N,"znprimroot"))) { F = clean_Z_factor(F); N = typ(N) == t_VEC? gel(N,1): factorback(F); } N = absi_shallow(N); if (abscmpiu(N, 4) <= 0) { set_avma(av); return mkintmodu(N[2]-1,N[2]); } switch(mod4(N)) { case 0: /* N = 0 mod 4 */ pari_err_DOMAIN("znprimroot", "n","=",N,N); x = NULL; break; case 2: /* N = 2 mod 4 */ n = shifti(N,-1); /* becomes odd */ x = gener_Zp(n,F); if (!mod2(x)) x = addii(x,n); break; default: /* N odd */ x = gener_Zp(N,F); break; } return gerepilecopy(av, mkintmod(x, N)); } /* n | (p-1), returns a primitive n-th root of 1 in F_p^* */ GEN rootsof1_Fp(GEN n, GEN p) { pari_sp av = avma; GEN L = odd_prime_divisors(n); /* 2 implicit in pgener_Fp_local */ GEN z = pgener_Fp_local(p, L); z = Fp_pow(z, diviiexact(subiu(p,1), n), p); /* prim. n-th root of 1 */ return gerepileuptoint(av, z); } GEN rootsof1u_Fp(ulong n, GEN p) { pari_sp av = avma; GEN z, L = u_odd_prime_divisors(n); /* 2 implicit in pgener_Fp_local */ z = pgener_Fp_local(p, Flv_to_ZV(L)); z = Fp_pow(z, diviuexact(subiu(p,1), n), p); /* prim. n-th root of 1 */ return gerepileuptoint(av, z); } ulong rootsof1_Fl(ulong n, ulong p) { pari_sp av = avma; GEN L = u_odd_prime_divisors(n); /* 2 implicit in pgener_Fl_local */ ulong z = pgener_Fl_local(p, L); z = Fl_powu(z, (p-1) / n, p); /* prim. n-th root of 1 */ return gc_ulong(av,z); } /*********************************************************************/ /** INVERSE TOTIENT FUNCTION **/ /*********************************************************************/ /* N t_INT, L a ZV containing all prime divisors of N, and possibly other * primes. Return factor(N) */ GEN Z_factor_listP(GEN N, GEN L) { long i, k, l = lg(L); GEN P = cgetg(l, t_COL), E = cgetg(l, t_COL); for (i = k = 1; i < l; i++) { GEN p = gel(L,i); long v = Z_pvalrem(N, p, &N); if (v) { gel(P,k) = p; gel(E,k) = utoipos(v); k++; } } setlg(P, k); setlg(E, k); return mkmat2(P,E); } /* look for x such that phi(x) = n, p | x => p > m (if m = NULL: no condition). * L is a list of primes containing all prime divisors of n. */ static long istotient_i(GEN n, GEN m, GEN L, GEN *px) { pari_sp av = avma, av2; GEN k, D; long i, v; if (m && mod2(n)) { if (!equali1(n)) return 0; if (px) *px = gen_1; return 1; } D = divisors(Z_factor_listP(shifti(n, -1), L)); /* loop through primes p > m, d = p-1 | n */ av2 = avma; if (!m) { /* special case p = 2, d = 1 */ k = n; for (v = 1;; v++) { if (istotient_i(k, gen_2, L, px)) { if (px) *px = shifti(*px, v); return 1; } if (mod2(k)) break; k = shifti(k,-1); } set_avma(av2); } for (i = 1; i < lg(D); ++i) { GEN p, d = shifti(gel(D, i), 1); /* even divisors of n */ if (m && cmpii(d, m) < 0) continue; p = addiu(d, 1); if (!isprime(p)) continue; k = diviiexact(n, d); for (v = 1;; v++) { GEN r; if (istotient_i(k, p, L, px)) { if (px) *px = mulii(*px, powiu(p, v)); return 1; } k = dvmdii(k, p, &r); if (r != gen_0) break; } set_avma(av2); } return gc_long(av,0); } /* find x such that phi(x) = n */ long istotient(GEN n, GEN *px) { pari_sp av = avma; if (typ(n) != t_INT) pari_err_TYPE("istotient", n); if (signe(n) < 1) return 0; if (mod2(n)) { if (!equali1(n)) return 0; if (px) *px = gen_1; return 1; } if (istotient_i(n, NULL, gel(Z_factor(n), 1), px)) { if (!px) set_avma(av); else *px = gerepileuptoint(av, *px); return 1; } return gc_long(av,0); } /*********************************************************************/ /** KRONECKER SYMBOL **/ /*********************************************************************/ /* t = 3,5 mod 8 ? (= 2 not a square mod t) */ static int ome(long t) { switch(t & 7) { case 3: case 5: return 1; default: return 0; } } /* t a t_INT, is t = 3,5 mod 8 ? */ static int gome(GEN t) { return signe(t)? ome( mod2BIL(t) ): 0; } /* assume y odd, return kronecker(x,y) * s */ static long krouu_s(ulong x, ulong y, long s) { ulong x1 = x, y1 = y, z; while (x1) { long r = vals(x1); if (r) { if (odd(r) && ome(y1)) s = -s; x1 >>= r; } if (x1 & y1 & 2) s = -s; z = y1 % x1; y1 = x1; x1 = z; } return (y1 == 1)? s: 0; } long kronecker(GEN x, GEN y) { pari_sp av = avma; long s = 1, r; ulong xu; if (typ(x) != t_INT) pari_err_TYPE("kronecker",x); if (typ(y) != t_INT) pari_err_TYPE("kronecker",y); switch (signe(y)) { case -1: y = negi(y); if (signe(x) < 0) s = -1; break; case 0: return is_pm1(x); } r = vali(y); if (r) { if (!mpodd(x)) return gc_long(av,0); if (odd(r) && gome(x)) s = -s; y = shifti(y,-r); } 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 (gc_needed(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; return gc_long(av, krouu_s(umodiu(y,xu), xu, s)); } long krois(GEN x, long y) { ulong yu; long s = 1; if (y <= 0) { if (y == 0) return is_pm1(x); yu = (ulong)-y; if (signe(x) < 0) s = -1; } else yu = (ulong)y; if (!odd(yu)) { long r; if (!mpodd(x)) return 0; r = vals(yu); yu >>= r; if (odd(r) && gome(x)) s = -s; } return krouu_s(umodiu(x, yu), yu, s); } /* assume y != 0 */ long kroiu(GEN x, ulong y) { long r; if (odd(y)) return krouu_s(umodiu(x,y), y, 1); if (!mpodd(x)) return 0; r = vals(y); y >>= r; return krouu_s(umodiu(x,y), y, (odd(r) && gome(x))? -1: 1); } /* assume y > 0, odd, return s * kronecker(x,y) */ static long krouodd(ulong x, GEN y, long s) { long r; if (lgefint(y) == 3) return krouu_s(x, y[2], s); if (!x) return 0; /* y != 1 */ r = vals(x); if (r) { if (odd(r) && gome(y)) s = -s; x >>= r; } /* x=3 mod 4 && y=3 mod 4 ? (both are odd here) */ if (x & mod2BIL(y) & 2) s = -s; return krouu_s(umodiu(y,x), x, s); } long krosi(long x, GEN y) { const pari_sp av = avma; long s = 1, r; 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)) return gc_long(av,0); if (odd(r) && ome(x)) s = -s; y = shifti(y,-r); } if (x < 0) { x = -x; if (mod4(y) == 3) s = -s; } return gc_long(av, krouodd((ulong)x, y, s)); } long kroui(ulong x, GEN y) { const pari_sp av = avma; long s = 1, r; switch (signe(y)) { case -1: y = negi(y); break; case 0: return x==1UL; } r = vali(y); if (r) { if (!odd(x)) return gc_long(av,0); if (odd(r) && ome(x)) s = -s; y = shifti(y,-r); } return gc_long(av, krouodd(x, y, s)); } long kross(long x, long y) { ulong yu; long s = 1; if (y <= 0) { if (y == 0) return (labs(x)==1); yu = (ulong)-y; if (x < 0) s = -1; } else yu = (ulong)y; if (!odd(yu)) { long r; if (!odd(x)) return 0; r = vals(yu); yu >>= r; if (odd(r) && ome(x)) s = -s; } x %= (long)yu; if (x < 0) x += yu; return krouu_s((ulong)x, yu, s); } long krouu(ulong x, ulong y) { long r; if (odd(y)) return krouu_s(x, y, 1); if (!odd(x)) return 0; r = vals(y); y >>= r; return krouu_s(x, y, (odd(r) && ome(x))? -1: 1); } /*********************************************************************/ /** HILBERT SYMBOL **/ /*********************************************************************/ /* x,y are t_INT or t_REAL */ static long mphilbertoo(GEN x, GEN y) { long sx = signe(x), sy = signe(y); if (!sx || !sy) return 0; return (sx < 0 && sy < 0)? -1: 1; } long hilbertii(GEN x, GEN y, GEN p) { pari_sp av; long oddvx, oddvy, z; if (!p) return mphilbertoo(x,y); if (is_pm1(p) || signe(p) < 0) pari_err_PRIME("hilbertii",p); if (!signe(x) || !signe(y)) return 0; av = avma; oddvx = odd(Z_pvalrem(x,p,&x)); oddvy = odd(Z_pvalrem(y,p,&y)); /* x, y are p-units, compute hilbert(x * p^oddvx, y * p^oddvy, p) */ if (absequaliu(p, 2)) { z = (Mod4(x) == 3 && Mod4(y) == 3)? -1: 1; if (oddvx && gome(y)) z = -z; if (oddvy && gome(x)) z = -z; } else { z = (oddvx && oddvy && mod4(p) == 3)? -1: 1; if (oddvx && kronecker(y,p) < 0) z = -z; if (oddvy && kronecker(x,p) < 0) z = -z; } return gc_long(av, z); } static void err_prec(void) { pari_err_PREC("hilbert"); } static void err_p(GEN p, GEN q) { pari_err_MODULUS("hilbert", p,q); } static void err_oo(GEN p) { pari_err_MODULUS("hilbert", p, strtoGENstr("oo")); } /* x t_INTMOD, *pp = prime or NULL [ unset, set it to x.mod ]. * Return lift(x) provided it's p-adic accuracy is large enough to decide * hilbert()'s value [ problem at p = 2 ] */ static GEN lift_intmod(GEN x, GEN *pp) { GEN p = *pp, N = gel(x,1); x = gel(x,2); if (!p) { *pp = p = N; switch(itos_or_0(p)) { case 2: case 4: err_prec(); } return x; } if (!signe(p)) err_oo(N); if (absequaliu(p,2)) { if (vali(N) <= 2) err_prec(); } else { if (!dvdii(N,p)) err_p(N,p); } if (!signe(x)) err_prec(); return x; } /* x t_PADIC, *pp = prime or NULL [ unset, set it to x.p ]. * Return lift(x)*p^(v(x) mod 2) provided it's p-adic accuracy is large enough * to decide hilbert()'s value [ problem at p = 2 ]*/ static GEN lift_padic(GEN x, GEN *pp) { GEN p = *pp, q = gel(x,2), y = gel(x,4); if (!p) *pp = p = q; else if (!equalii(p,q)) err_p(p, q); if (absequaliu(p,2) && precp(x) <= 2) err_prec(); if (!signe(y)) err_prec(); return odd(valp(x))? mulii(p,y): y; } long hilbert(GEN x, GEN y, GEN p) { pari_sp av = avma; long tx = typ(x), ty = typ(y); if (p && typ(p) != t_INT) pari_err_TYPE("hilbert",p); if (tx == t_REAL) { if (p && signe(p)) err_oo(p); switch (ty) { case t_INT: case t_REAL: return mphilbertoo(x,y); case t_FRAC: return mphilbertoo(x,gel(y,1)); default: pari_err_TYPE2("hilbert",x,y); } } if (ty == t_REAL) { if (p && signe(p)) err_oo(p); switch (tx) { case t_INT: case t_REAL: return mphilbertoo(x,y); case t_FRAC: return mphilbertoo(gel(x,1),y); default: pari_err_TYPE2("hilbert",x,y); } } if (tx == t_INTMOD) { x = lift_intmod(x, &p); tx = t_INT; } if (ty == t_INTMOD) { y = lift_intmod(y, &p); ty = t_INT; } if (tx == t_PADIC) { x = lift_padic(x, &p); tx = t_INT; } if (ty == t_PADIC) { y = lift_padic(y, &p); ty = t_INT; } if (tx == t_FRAC) { tx = t_INT; x = p? mulii(gel(x,1),gel(x,2)): gel(x,1); } if (ty == t_FRAC) { ty = t_INT; y = p? mulii(gel(y,1),gel(y,2)): gel(y,1); } if (tx != t_INT || ty != t_INT) pari_err_TYPE2("hilbert",x,y); if (p && !signe(p)) p = NULL; return gc_long(av, hilbertii(x,y,p)); } /*******************************************************************/ /* SQUARE ROOT MODULO p */ /*******************************************************************/ static void checkp(ulong q, ulong p) { if (!q) pari_err_PRIME("Fl_nonsquare",utoipos(p)); } /* p = 1 (mod 4) prime, return the first quadratic nonresidue, a prime */ static ulong nonsquare1_Fl(ulong p) { forprime_t S; ulong q; if ((p & 7UL) != 1) return 2UL; q = p % 3; if (q == 2) return 3UL; checkp(q, p); q = p % 5; if (q == 2 || q == 3) return 5UL; checkp(q, p); q = p % 7; if (q != 4 && q >= 3) return 7UL; checkp(q, p); /* log^2(2^64) < 1968 is enough under GRH (and p^(1/4)log(p) without it)*/ u_forprime_init(&S, 11, 1967); while ((q = u_forprime_next(&S))) { if (krouu(q, p) < 0) return q; checkp(q, p); } checkp(0, p); return 0; /*LCOV_EXCL_LINE*/ } /* p > 2 a prime */ ulong nonsquare_Fl(ulong p) { return ((p & 3UL) == 3)? p-1: nonsquare1_Fl(p); } /* allow pi = 0 */ ulong Fl_2gener_pre(ulong p, ulong pi) { ulong p1 = p-1; long e = vals(p1); if (e == 1) return p1; return Fl_powu_pre(nonsquare1_Fl(p), p1 >> e, p, pi); } ulong Fl_2gener_pre_i(ulong ns, ulong p, ulong pi) { ulong p1 = p-1; long e = vals(p1); if (e == 1) return p1; return Fl_powu_pre(ns, p1 >> e, p, pi); } static ulong Fl_sqrt_i(ulong a, ulong y, ulong p) { long i, e, k; ulong p1, q, v, w; if (!a) return 0; p1 = p - 1; e = vals(p1); if (e == 0) /* p = 2 */ { if (p != 2) pari_err_PRIME("Fl_sqrt [modulus]",utoi(p)); return ((a & 1) == 0)? 0: 1; } if (e == 1) { v = Fl_powu(a, (p+1) >> 2, p); if (Fl_sqr(v, p) != a) return ~0UL; p1 = p - v; if (v > p1) v = p1; return v; } q = p1 >> e; /* q = (p-1)/2^oo is odd */ p1 = Fl_powu(a, q >> 1, p); /* a ^ [(q-1)/2] */ if (!p1) return 0; v = Fl_mul(a, p1, p); w = Fl_mul(v, p1, p); if (!y) y = Fl_powu(nonsquare1_Fl(p), q, 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; } /* Tonelli-Shanks. Assume p is prime and (a,p) != -1. Allow pi = 0 */ ulong Fl_sqrt_pre_i(ulong a, ulong y, ulong p, ulong pi) { long i, e, k; ulong p1, q, v, w; if (!pi) return Fl_sqrt_i(a, y, p); if (!a) return 0; p1 = p - 1; e = vals(p1); if (e == 0) /* p = 2 */ { if (p != 2) pari_err_PRIME("Fl_sqrt [modulus]",utoi(p)); return ((a & 1) == 0)? 0: 1; } if (e == 1) { v = Fl_powu_pre(a, (p+1) >> 2, p, pi); if (Fl_sqr_pre(v, p, pi) != a) return ~0UL; p1 = p - v; if (v > p1) v = p1; return v; } q = p1 >> e; /* q = (p-1)/2^oo is odd */ p1 = Fl_powu_pre(a, q >> 1, p, pi); /* a ^ [(q-1)/2] */ if (!p1) return 0; v = Fl_mul_pre(a, p1, p, pi); w = Fl_mul_pre(v, p1, p, pi); if (!y) y = Fl_powu_pre(nonsquare1_Fl(p), q, p, pi); while (w != 1) { /* a*w = v^2, y primitive 2^e-th root of 1 a square --> w even power of y, hence w^(2^(e-1)) = 1 */ p1 = Fl_sqr_pre(w,p,pi); for (k=1; p1 != 1 && k < e; k++) p1 = Fl_sqr_pre(p1,p,pi); if (k == e) return ~0UL; /* w ^ (2^k) = 1 --> w = y ^ (u * 2^(e-k)), u odd */ p1 = y; for (i=1; i < e-k; i++) p1 = Fl_sqr_pre(p1, p, pi); y = Fl_sqr_pre(p1, p, pi); e = k; w = Fl_mul_pre(y, w, p, pi); v = Fl_mul_pre(v, p1, p, pi); } p1 = p - v; if (v > p1) v = p1; return v; } ulong Fl_sqrt(ulong a, ulong p) { ulong pi = (p & HIGHMASK)? get_Fl_red(p): 0; return Fl_sqrt_pre_i(a, 0, p, pi); } ulong Fl_sqrt_pre(ulong a, ulong p, ulong pi) { return Fl_sqrt_pre_i(a, 0, p, pi); } /* allow pi = 0 */ static ulong Fl_lgener_pre_all(ulong l, long e, ulong r, ulong p, ulong pi, ulong *pt_m) { ulong x, y, m, le1 = upowuu(l, e-1); for (x = 2; ; x++) { y = Fl_powu_pre(x, r, p, pi); if (y==1) continue; m = Fl_powu_pre(y, le1, p, pi); if (m != 1) break; } *pt_m = m; return y; } /* solve x^l = a , l prime in G of order q. * * q = (l^e)*r, e >= 1, (r,l) = 1 * y generates the l-Sylow of G * m = y^(l^(e-1)) != 1 */ static ulong Fl_sqrtl_raw(ulong a, ulong l, ulong e, ulong r, ulong p, ulong pi, ulong y, ulong m) { ulong u2, p1, v, w, z, dl; if (a==0) return a; u2 = Fl_inv(l%r, r); v = Fl_powu_pre(a, u2, p, pi); w = Fl_powu_pre(v, l, p, pi); w = pi? Fl_mul_pre(w, Fl_inv(a, p), p, pi): Fl_div(w, a, p); if (w==1) return v; if (y==0) y = Fl_lgener_pre_all(l, e, r, p, pi, &m); while (w!=1) { ulong k = 0; p1 = w; do { z = p1; p1 = Fl_powu_pre(p1, l, p, pi); if (++k == e) return ULONG_MAX; } while (p1!=1); dl = Fl_log_pre(z, m, l, p, pi); dl = Fl_neg(dl, l); p1 = Fl_powu_pre(y,dl*upowuu(l,e-k-1),p,pi); m = Fl_powu_pre(m, dl, p, pi); e = k; v = pi? Fl_mul_pre(p1,v,p,pi): Fl_mul(p1,v,p); y = Fl_powu_pre(p1,l,p,pi); w = pi? Fl_mul_pre(y,w,p,pi): Fl_mul(y,w,p); } return v; } /* allow pi = 0 */ static ulong Fl_sqrtl_i(ulong a, ulong l, ulong p, ulong pi, ulong y, ulong m) { ulong r, e = u_lvalrem(p-1, l, &r); return Fl_sqrtl_raw(a, l, e, r, p, pi, y, m); } /* allow pi = 0 */ ulong Fl_sqrtl_pre(ulong a, ulong l, ulong p, ulong pi) { return Fl_sqrtl_i(a, l, p, pi, 0, 0); } ulong Fl_sqrtl(ulong a, ulong l, ulong p) { ulong pi = (p & HIGHMASK)? get_Fl_red(p): 0; return Fl_sqrtl_i(a, l, p, pi, 0, 0); } /* allow pi = 0 */ ulong Fl_sqrtn_pre(ulong a, long n, ulong p, ulong pi, ulong *zetan) { ulong m, q = p-1, z; ulong nn = n >= 0 ? (ulong)n: -(ulong)n; if (a==0) { if (n < 0) pari_err_INV("Fl_sqrtn", mkintmod(gen_0,utoi(p))); if (zetan) *zetan = 1UL; return 0; } if (n==1) { if (zetan) *zetan = 1; return n < 0? Fl_inv(a,p): a; } if (n==2) { if (zetan) *zetan = p-1; return Fl_sqrt_pre_i(a, 0, p, pi); } if (a == 1 && !zetan) return a; m = ugcd(nn, q); z = 1; if (m!=1) { GEN F = factoru(m); long i, j, e; ulong r, zeta, y, l; for (i = nbrows(F); i; i--) { l = ucoeff(F,i,1); j = ucoeff(F,i,2); e = u_lvalrem(q,l, &r); y = Fl_lgener_pre_all(l, e, r, p, pi, &zeta); if (zetan) { ulong Y = Fl_powu_pre(y, upowuu(l,e-j), p, pi); z = pi? Fl_mul_pre(z, Y, p, pi): Fl_mul(z, Y, p); } if (a!=1) do { a = Fl_sqrtl_raw(a, l, e, r, p, pi, y, zeta); if (a==ULONG_MAX) return ULONG_MAX; } while (--j); } } if (m != nn) { ulong qm = q/m, nm = (nn/m) % qm; a = Fl_powu_pre(a, Fl_inv(nm, qm), p, pi); } if (n < 0) a = Fl_inv(a, p); if (zetan) *zetan = z; return a; } ulong Fl_sqrtn(ulong a, long n, ulong p, ulong *zetan) { ulong pi = (p & HIGHMASK)? get_Fl_red(p): 0; return Fl_sqrtn_pre(a, n, p, pi, zetan); } /* Cipolla is better than Tonelli-Shanks when e = v_2(p-1) is "too big". * Otherwise, is a constant times worse; for p = 3 (mod 4), is about 3 times worse, * and in average is about 2 or 2.5 times worse. But try both algorithms for * S(n) = (2^n+3)^2-8 with n = 750, 771, 779, 790, 874, 1176, 1728, 2604, etc. * * If X^2 := t^2 - a is not a square in F_p (so X is in F_p^2), then * (t+X)^(p+1) = (t-X)(t+X) = a, hence sqrt(a) = (t+X)^((p+1)/2) in F_p^2. * If (a|p)=1, then sqrt(a) is in F_p. * cf: LNCS 2286, pp 430-434 (2002) [Gonzalo Tornaria] */ /* compute y^2, y = y[1] + y[2] X */ static GEN sqrt_Cipolla_sqr(void *data, GEN y) { GEN u = gel(y,1), v = gel(y,2), p = gel(data,2), n = gel(data,3); GEN u2 = sqri(u), v2 = sqri(v); v = subii(sqri(addii(v,u)), addii(u2,v2)); u = addii(u2, mulii(v2,n)); retmkvec2(modii(u,p), modii(v,p)); } /* compute (t+X) y^2 */ static GEN sqrt_Cipolla_msqr(void *data, GEN y) { GEN u = gel(y,1), v = gel(y,2), a = gel(data,1), p = gel(data,2); ulong t = gel(data,4)[2]; GEN d = addii(u, mului(t,v)), d2 = sqri(d); GEN b = remii(mulii(a,v), p); u = subii(mului(t,d2), mulii(b,addii(u,d))); v = subii(d2, mulii(b,v)); retmkvec2(modii(u,p), modii(v,p)); } /* assume a reduced mod p [ otherwise correct but inefficient ] */ static GEN sqrt_Cipolla(GEN a, GEN p) { pari_sp av; GEN u, n, y, pov2; ulong t; if (kronecker(a, p) < 0) return NULL; pov2 = shifti(p,-1); /* center to avoid multiplying by huge base*/ if (cmpii(a,pov2) > 0) a = subii(a,p); av = avma; for (t=1; ; t++, set_avma(av)) { n = subsi((long)(t*t), a); if (kronecker(n, p) < 0) break; } /* compute (t+X)^((p-1)/2) =: u+vX */ u = utoipos(t); y = gen_pow_fold(mkvec2(u, gen_1), pov2, mkvec4(a,p,n,u), sqrt_Cipolla_sqr, sqrt_Cipolla_msqr); /* Now u+vX = (t+X)^((p-1)/2); thus * (u+vX)(t+X) = sqrt(a) + 0 X * Whence, * sqrt(a) = (u+vt)t - v*a * 0 = (u+vt) * Thus a square root is v*a */ return Fp_mul(gel(y,2), a, p); } /* Return NULL if p is found to be composite. * p odd, q = (p-1)/2^oo is odd */ static GEN Fp_2gener_all(GEN q, GEN p) { long k; for (k = 2;; k++) { long i = kroui(k, p); if (i < 0) return Fp_pow(utoipos(k), q, p); if (i == 0) return NULL; } } /* Return NULL if p is found to be composite */ GEN Fp_2gener(GEN p) { GEN q = subiu(p, 1); long e = Z_lvalrem(q, 2, &q); if (e == 0 && !equaliu(p,2)) return NULL; return Fp_2gener_all(q, p); } GEN Fp_2gener_i(GEN ns, GEN p) { GEN q = subiu(p,1); long e = vali(q); if (e == 1) return q; return Fp_pow(ns, shifti(q,-e), p); } static GEN nonsquare_Fp(GEN p) { forprime_t T; ulong a; if (mod4(p)==3) return gen_m1; if (mod8(p)==5) return gen_2; u_forprime_init(&T, 3, ULONG_MAX); while((a = u_forprime_next(&T))) if (kroui(a,p) < 0) return utoi(a); pari_err_PRIME("Fp_sqrt [modulus]",p); return NULL; /* LCOV_EXCL_LINE */ } static GEN Fp_rootsof1(ulong l, GEN p) { GEN z, pl = diviuexact(subis(p,1),l); ulong a; forprime_t T; u_forprime_init(&T, 3, ULONG_MAX); while((a = u_forprime_next(&T))) { z = Fp_pow(utoi(a), pl, p); if (!equali1(z)) return z; } pari_err_PRIME("Fp_sqrt [modulus]",p); return NULL; /* LCOV_EXCL_LINE */ } static GEN Fp_gausssum(long D, GEN p) { long i, l = labs(D); GEN z = Fp_rootsof1(l, p); GEN s = z, x = z; for(i = 2; i < l; i++) { long k = kross(i,l); x = mulii(x, z); if (k==1) s = addii(s, x); else if (k==-1) s = subii(s, x); } return s; } static GEN Fp_sqrts(long a, GEN p) { long v = vals(a)>>1; GEN r = gen_0; a >>= v << 1; switch(a) { case 1: r = gen_1; break; case -1: if (mod4(p)==1) r = Fp_pow(nonsquare_Fp(p), shifti(p,-2),p); else r = NULL; break; case 2: if (mod8(p)==1) { GEN z = Fp_pow(nonsquare_Fp(p), shifti(p,-3),p); r = Fp_mul(z,Fp_sub(gen_1,Fp_sqr(z,p),p),p); } else if (mod8(p)==7) r = Fp_pow(gen_2, shifti(addiu(p,1),-2),p); else return NULL; break; case -2: if (mod8(p)==1) { GEN z = Fp_pow(nonsquare_Fp(p), shifti(p,-3),p); r = Fp_mul(z,Fp_add(gen_1,Fp_sqr(z,p),p),p); } else if (mod8(p)==3) r = Fp_pow(gen_m2, shifti(addiu(p,1),-2),p); else return NULL; break; case -3: if (umodiu(p,3)==1) { GEN z = Fp_rootsof1(3, p); r = Fp_sub(z,Fp_sqr(z,p),p); } else return NULL; break; case 5: case 13: case 17: case 21: case 29: case 33: case -7: case -11: case -15: case -19: case -23: if (umodiu(p,labs(a))==1) r = Fp_gausssum(a,p); else return gen_0; break; default: return gen_0; } return remii(shifti(r, v), p); } static GEN Fp_sqrt_ii(GEN a, GEN y, GEN p) { pari_sp av = avma; GEN q, v, w, p1 = subiu(p,1); long i, k, e = vali(p1), as; /* direct formulas more efficient */ if (e == 0) pari_err_PRIME("Fp_sqrt [modulus]",p); /* p != 2 */ if (e == 1) { q = addiu(shifti(p1,-2),1); /* (p+1) / 4 */ v = Fp_pow(a, q, p); /* must check equality in case (a/p) = -1 or p not prime */ av = avma; e = equalii(Fp_sqr(v,p), a); set_avma(av); return e? v: NULL; } as = itos_or_0(a); if (!as) as = itos_or_0(subii(a,p)); if (as) { GEN res = Fp_sqrts(as, p); if (!res) return gc_NULL(av); if (signe(res)) return gerepileupto(av, res); } if (e == 2) { /* Atkin's formula */ GEN I, a2 = shifti(a,1); if (cmpii(a2,p) >= 0) a2 = subii(a2,p); q = shifti(p1, -3); /* (p-5)/8 */ v = Fp_pow(a2, q, p); I = Fp_mul(a2, Fp_sqr(v,p), p); /* I^2 = -1 */ v = Fp_mul(a, Fp_mul(v, subiu(I,1), p), p); /* must check equality in case (a/p) = -1 or p not prime */ av = avma; e = equalii(Fp_sqr(v,p), a); set_avma(av); return e? v: NULL; } /* On average, Cipolla is better than Tonelli/Shanks if and only if * e(e-1) > 8*log2(n)+20, see LNCS 2286 pp 430 [GTL] */ if (e*(e-1) > 20 + 8 * expi(p)) return sqrt_Cipolla(a,p); /* Tonelli-Shanks */ av = avma; q = shifti(p1,-e); /* q = (p-1)/2^oo is odd */ if (!y) { y = Fp_2gener_all(q, p); if (!y) pari_err_PRIME("Fp_sqrt [modulus]",p); } p1 = Fp_pow(a, shifti(q,-1), p); /* a ^ (q-1)/2 */ v = Fp_mul(a, p1, p); w = Fp_mul(v, p1, p); while (!equali1(w)) { /* a*w = v^2, y primitive 2^e-th root of 1 a square --> w even power of y, hence w^(2^(e-1)) = 1 */ p1 = Fp_sqr(w,p); for (k=1; !equali1(p1) && k < e; k++) p1 = Fp_sqr(p1,p); if (k == e) 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 = Fp_sqr(p1,p); y = Fp_sqr(p1, p); e = k; w = Fp_mul(y, w, p); v = Fp_mul(v, p1, p); if (gc_needed(av,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"Fp_sqrt"); gerepileall(av,3, &y,&w,&v); } } return v; } /* Assume p is prime and return NULL if (a,p) = -1; y = NULL or generator * of Fp^* 2-Sylow */ GEN Fp_sqrt_i(GEN a, GEN y, GEN p) { pari_sp av = avma, av2; GEN q; if (lgefint(p) == 3) { ulong pp = uel(p,2), u = umodiu(a, pp); if (!u) return gen_0; u = Fl_sqrt(u, pp); return (u == ~0UL)? NULL: utoipos(u); } a = modii(a, p); if (!signe(a)) return gen_0; a = Fp_sqrt_ii(a, y, p); if (!a) return gc_NULL(av); /* smallest square root */ av2 = avma; q = subii(p, a); if (cmpii(a, q) > 0) a = q; else set_avma(av2); return gerepileuptoint(av, a); } GEN Fp_sqrt(GEN a, GEN p) { return Fp_sqrt_i(a, NULL, p); } /*********************************************************************/ /** 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 (absequalii(a,y)) { set_avma(av); return absi(x); } if (!equali1(a)) y = diviiexact(y,a); b = mulii(x,y); setabssign(b); return gerepileuptoint(av, b); } /* given x in assume 0 < x < N; return u in (Z/NZ)^* such that u x = gcd(x,N) (mod N); * set *pd = gcd(x,N) */ GEN Fp_invgen(GEN x, GEN N, GEN *pd) { GEN d, d0, e, v; if (lgefint(N) == 3) { ulong dd, NN = N[2], xx = umodiu(x,NN); if (!xx) { *pd = N; return gen_0; } xx = Fl_invgen(xx, NN, &dd); *pd = utoi(dd); return utoi(xx); } *pd = d = bezout(x, N, &v, NULL); if (equali1(d)) return v; /* vx = gcd(x,N) (mod N), v coprime to N/d but need not be coprime to N */ e = diviiexact(N,d); d0 = Z_ppo(d, e); /* d = d0 d1, d0 coprime to N/d, rad(d1) | N/d */ if (equali1(d0)) return v; if (!equalii(d,d0)) e = lcmii(e, diviiexact(d,d0)); return Z_chinese_coprime(v, gen_1, e, d0, mulii(e,d0)); } /*********************************************************************/ /** CHINESE REMAINDERS **/ /*********************************************************************/ /* 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: * * ? 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)]; * ? chinese(x, y) * %3 = [1, Mod(16, 187), Mod(X + mod(9, 21), X^2 + 1)] */ static GEN gen_chinese(GEN x, GEN(*f)(GEN,GEN)) { GEN z = gassoc_proto(f,x,NULL); if (z == gen_1) retmkintmod(gen_0,gen_1); return z; } /* x t_INTMOD, y t_POLMOD; promote x to t_POLMOD mod Pol(x.mod) then * call chinese: makes Mod(0,1) a better "neutral" element */ static GEN chinese_intpol(GEN x,GEN y) { pari_sp av = avma; GEN z = mkpolmod(gel(x,2), scalarpol_shallow(gel(x,1), varn(gel(y,1)))); return gerepileupto(av, chinese(z, y)); } GEN chinese1(GEN x) { return gen_chinese(x,chinese); } GEN chinese(GEN x, GEN y) { pari_sp av; long tx = typ(x), ty; GEN z,p1,p2,d,u,v; if (!y) return chinese1(x); if (gidentical(x,y)) return gcopy(x); ty = typ(y); if (tx == ty) switch(tx) { case t_POLMOD: { GEN A = gel(x,1), B = gel(y,1); GEN a = gel(x,2), b = gel(y,2); if (varn(A)!=varn(B)) pari_err_VAR("chinese",A,B); if (RgX_equal(A,B)) retmkpolmod(chinese(a,b), gcopy(A)); /*same modulus*/ av = avma; d = RgX_extgcd(A,B,&u,&v); p2 = gsub(b, a); if (!gequal0(gmod(p2, d))) break; p1 = gdiv(A,d); p2 = gadd(a, gmul(gmul(u,p1), p2)); z = cgetg(3, t_POLMOD); gel(z,1) = gmul(p1,B); gel(z,2) = gmod(p2,gel(z,1)); return gerepileupto(av, z); } case t_INTMOD: { GEN A = gel(x,1), B = gel(y,1); GEN a = gel(x,2), b = gel(y,2), c, d, C, U; z = cgetg(3,t_INTMOD); Z_chinese_pre(A, B, &C, &U, &d); c = Z_chinese_post(a, b, C, U, d); if (!c) pari_err_OP("chinese", x,y); set_avma((pari_sp)z); gel(z,1) = icopy(C); gel(z,2) = icopy(c); return z; } case t_POL: { long i, lx = lg(x), ly = lg(y); if (varn(x) != varn(y)) break; if (lx < ly) { swap(x,y); lswap(lx,ly); } z = cgetg(lx, t_POL); z[1] = x[1]; for (i=2; i>1)+1, t_VEC); if (typ(xa)==t_VECSMALL) { for (j=1, k=1; k>1)+1, t_VEC); for (j=1, k=1; k=1; i--) { GEN u = gel(T, i); GEN v = gel(Tp, i+1); long n = lg(u)-1; t = cgetg(n+1, t_VEC); for (j=1, k=1; k4) timer_start(&ti); if (DEBUGLEVEL>5) err_printf("Start parallel Chinese remainder: "); mt_queue_start_lim(&pt, worker, l-1); for (i=1; i5) err_printf("%ld%% ",(++cnt)*100/(l-1)); } } if (DEBUGLEVEL>5) err_printf("\n"); if (DEBUGLEVEL>4) timer_printf(&ti, "nmV_chinese_center"); mt_queue_end(&pt); return M; } GEN nxMV_polint_center_tree_worker(GEN vA, GEN T, GEN R, GEN P, GEN m2) { return nxCV_polint_center_tree(vA, P, T, R, m2); } static GEN nxMV_polint_center_tree_seq(GEN vA, GEN P, GEN T, GEN R, GEN m2) { long i, j, l = lg(gel(vA,1)), n = lg(P); GEN A = cgetg(n, t_VEC); GEN V = cgetg(l, t_MAT); for (i=1; i < l; i++) { for (j=1; j < n; j++) gel(A,j) = gmael(vA,j,i); gel(V,i) = nxCV_polint_center_tree(A, P, T, R, m2); } return V; } static GEN nxMV_polint_center_tree(GEN mA, GEN P, GEN T, GEN R, GEN m2) { GEN worker = snm_closure(is_entry("_nxMV_polint_worker"), mkvec4(T, R, P, m2)); return polint_chinese(worker, mA, P); } static GEN nmV_polint_center_tree_seq(GEN vA, GEN P, GEN T, GEN R, GEN m2) { long i, j, l = lg(gel(vA,1)), n = lg(P); GEN A = cgetg(n, t_VEC); GEN V = cgetg(l, t_MAT); for (i=1; i < l; i++) { for (j=1; j < n; j++) gel(A,j) = gmael(vA,j,i); gel(V,i) = ncV_polint_center_tree(A, P, T, R, m2); } return V; } GEN nmV_polint_center_tree_worker(GEN vA, GEN T, GEN R, GEN P, GEN m2) { return ncV_polint_center_tree(vA, P, T, R, m2); } static GEN nmV_polint_center_tree(GEN mA, GEN P, GEN T, GEN R, GEN m2) { GEN worker = snm_closure(is_entry("_polint_worker"), mkvec4(T, R, P, m2)); return polint_chinese(worker, mA, P); } /* return [A mod P[i], i=1..#P] */ GEN Z_ZV_mod(GEN A, GEN P) { pari_sp av = avma; return gerepilecopy(av, Z_ZV_mod_tree(A, P, ZV_producttree(P))); } /* P a t_VECSMALL */ GEN Z_nv_mod(GEN A, GEN P) { pari_sp av = avma; return gerepileuptoleaf(av, Z_ZV_mod_tree(A, P, ZV_producttree(P))); } /* B a ZX, T = ZV_producttree(P) */ GEN ZX_nv_mod_tree(GEN B, GEN A, GEN T) { pari_sp av; long i, j, l = lg(B), n = lg(A)-1; GEN V = cgetg(n+1, t_VEC); for (j=1; j <= n; j++) { gel(V, j) = cgetg(l, t_VECSMALL); mael(V, j, 1) = B[1]&VARNBITS; } av = avma; for (i=2; i < l; i++) { GEN v = Z_ZV_mod_tree(gel(B, i), A, T); for (j=1; j <= n; j++) mael(V, j, i) = v[j]; set_avma(av); } for (j=1; j <= n; j++) (void) Flx_renormalize(gel(V, j), l); return V; } static GEN to_ZX(GEN a, long v) { return typ(a)==t_INT? scalarpol(a,v): a; } GEN ZXX_nv_mod_tree(GEN P, GEN xa, GEN T, long w) { pari_sp av = avma; long i, j, l = lg(P), n = lg(xa)-1; GEN V = cgetg(n+1, t_VEC); for (j=1; j <= n; j++) { gel(V, j) = cgetg(l, t_POL); mael(V, j, 1) = P[1]&VARNBITS; } for (i=2; i < l; i++) { GEN v = ZX_nv_mod_tree(to_ZX(gel(P, i), w), xa, T); for (j=1; j <= n; j++) gmael(V, j, i) = gel(v,j); } for (j=1; j <= n; j++) (void) FlxX_renormalize(gel(V, j), l); return gerepilecopy(av, V); } GEN ZXC_nv_mod_tree(GEN C, GEN xa, GEN T, long w) { pari_sp av = avma; long i, j, l = lg(C), n = lg(xa)-1; GEN V = cgetg(n+1, t_VEC); for (j = 1; j <= n; j++) gel(V, j) = cgetg(l, t_COL); for (i = 1; i < l; i++) { GEN v = ZX_nv_mod_tree(to_ZX(gel(C, i), w), xa, T); for (j = 1; j <= n; j++) gmael(V, j, i) = gel(v,j); } return gerepilecopy(av, V); } GEN ZXM_nv_mod_tree(GEN M, GEN xa, GEN T, long w) { pari_sp av = avma; long i, j, l = lg(M), n = lg(xa)-1; GEN V = cgetg(n+1, t_VEC); for (j=1; j <= n; j++) gel(V, j) = cgetg(l, t_MAT); for (i=1; i < l; i++) { GEN v = ZXC_nv_mod_tree(gel(M, i), xa, T, w); for (j=1; j <= n; j++) gmael(V, j, i) = gel(v,j); } return gerepilecopy(av, V); } GEN ZV_nv_mod_tree(GEN B, GEN A, GEN T) { pari_sp av; long i, j, l = lg(B), n = lg(A)-1; GEN V = cgetg(n+1, t_VEC); for (j=1; j <= n; j++) gel(V, j) = cgetg(l, t_VECSMALL); av = avma; for (i=1; i < l; i++) { GEN v = Z_ZV_mod_tree(gel(B, i), A, T); for (j=1; j <= n; j++) mael(V, j, i) = v[j]; set_avma(av); } return V; } GEN ZM_nv_mod_tree(GEN M, GEN xa, GEN T) { pari_sp av = avma; long i, j, l = lg(M), n = lg(xa)-1; GEN V = cgetg(n+1, t_VEC); for (j=1; j <= n; j++) gel(V, j) = cgetg(l, t_MAT); for (i=1; i < l; i++) { GEN v = ZV_nv_mod_tree(gel(M, i), xa, T); for (j=1; j <= n; j++) gmael(V, j, i) = gel(v,j); } return gerepilecopy(av, V); } static GEN ZV_sqr(GEN z) { long i,l = lg(z); GEN x = cgetg(l, t_VEC); if (typ(z)==t_VECSMALL) for (i=1; i 1 */ static ulong Fl_2powu_pre(ulong n, ulong p, ulong pi) { ulong y = 2; int j = 1+bfffo(n); /* normalize, i.e set highest bit to 1 (we know n != 0) */ n<<=j; j = BITS_IN_LONG-j; /* first bit is now implicit */ for (; j; n<<=1,j--) { y = Fl_sqr_pre(y,p,pi); if (n & HIGHBIT) y = Fl_double(y, p); } return y; } /* 2^n mod p; assume n > 1 and !(p & HIGHMASK) */ static ulong Fl_2powu(ulong n, ulong p) { ulong y = 2; int j = 1+bfffo(n); /* normalize, i.e set highest bit to 1 (we know n != 0) */ n<<=j; j = BITS_IN_LONG-j; /* first bit is now implicit */ for (; j; n<<=1,j--) { y = (y*y) % p; if (n & HIGHBIT) y = Fl_double(y, p); } return y; } /* allow pi = 0 */ ulong Fl_powu_pre(ulong x, ulong n0, ulong p, ulong pi) { ulong y, z, n; if (!pi) return Fl_powu(x, n0, p); if (n0 <= 1) { /* frequent special cases */ if (n0 == 1) return x; if (n0 == 0) return 1; } if (x <= 2) { if (x == 2) return Fl_2powu_pre(n0, p, pi); return x; /* 0 or 1 */ } y = 1; z = x; n = n0; for(;;) { if (n&1) y = Fl_mul_pre(y,z,p,pi); n>>=1; if (!n) return y; z = Fl_sqr_pre(z,p,pi); } } ulong Fl_powu(ulong x, ulong n0, ulong p) { ulong y, z, n; if (n0 <= 2) { /* frequent special cases */ if (n0 == 2) return Fl_sqr(x,p); if (n0 == 1) return x; if (n0 == 0) return 1; } if (x <= 1) return x; /* 0 or 1 */ if (p & HIGHMASK) return Fl_powu_pre(x, n0, p, get_Fl_red(p)); if (x == 2) return Fl_2powu(n0, p); y = 1; z = x; n = n0; for(;;) { if (n&1) y = (y*z) % p; n>>=1; if (!n) return y; z = (z*z) % p; } } /* Reduce data dependency to maximize internal parallelism; allow pi = 0 */ GEN Fl_powers_pre(ulong x, long n, ulong p, ulong pi) { long i, k; GEN z = cgetg(n + 2, t_VECSMALL); z[1] = 1; if (n == 0) return z; z[2] = x; if (pi) { for (i = 3, k=2; i <= n; i+=2, k++) { z[i] = Fl_sqr_pre(z[k], p, pi); z[i+1] = Fl_mul_pre(z[k], z[k+1], p, pi); } if (i==n+1) z[i] = Fl_sqr_pre(z[k], p, pi); } else if (p & HIGHMASK) { for (i = 3, k=2; i <= n; i+=2, k++) { z[i] = Fl_sqr(z[k], p); z[i+1] = Fl_mul(z[k], z[k+1], p); } if (i==n+1) z[i] = Fl_sqr(z[k], p); } else for (i = 2; i <= n; i++) z[i+1] = (z[i] * x) % p; return z; } GEN Fl_powers(ulong x, long n, ulong p) { return Fl_powers_pre(x, n, p, (p & HIGHMASK)? get_Fl_red(p): 0); } /********************************************************************** ** Powering over (Z/NZ)^*, large N ** **********************************************************************/ typedef struct muldata { GEN (*sqr)(void * E, GEN x); GEN (*mul)(void * E, GEN x, GEN y); GEN (*mul2)(void * E, GEN x); } muldata; /* modified Barrett reduction with one fold */ /* See Fast Modular Reduction, W. Hasenplaugh, G. Gaubatz, V. Gopal, ARITH 18 */ static GEN Fp_invmBarrett(GEN p, long s) { GEN R, Q = dvmdii(int2n(3*s),p,&R); return mkvec2(Q,R); } /* a <= (N-1)^2, 2^(2s-2) <= N < 2^(2s). Return 0 <= r < N such that * a = r (mod N) */ static GEN Fp_rem_mBarrett(GEN a, GEN B, long s, GEN N) { pari_sp av = avma; GEN P = gel(B, 1), Q = gel(B, 2); /* 2^(3s) = P N + Q, 0 <= Q < N */ long t = expi(P)+1; /* 2^(t-1) <= P < 2^t */ GEN u = shifti(a, -3*s), v = remi2n(a, 3*s); /* a = 2^(3s)u + v */ GEN A = addii(v, mulii(Q,u)); /* 0 <= A < 2^(3s+1) */ GEN q = shifti(mulii(shifti(A, t-3*s), P), -t); /* A/N - 4 < q <= A/N */ GEN r = subii(A, mulii(q, N)); GEN sr= subii(r,N); /* 0 <= r < 4*N */ if (signe(sr)<0) return gerepileuptoint(av, r); r=sr; sr = subii(r,N); /* 0 <= r < 3*N */ if (signe(sr)<0) return gerepileuptoint(av, r); r=sr; sr = subii(r,N); /* 0 <= r < 2*N */ return gerepileuptoint(av, signe(sr)>=0 ? sr:r); } /* Montgomery reduction */ INLINE ulong init_montdata(GEN N) { return (ulong) -invmod2BIL(mod2BIL(N)); } struct montred { GEN N; ulong inv; }; /* Montgomery reduction */ static GEN _sqr_montred(void * E, GEN x) { struct montred * D = (struct montred *) E; return red_montgomery(sqri(x), D->N, D->inv); } /* Montgomery reduction */ static GEN _mul_montred(void * E, GEN x, GEN y) { struct montred * D = (struct montred *) E; return red_montgomery(mulii(x, y), D->N, D->inv); } static GEN _mul2_montred(void * E, GEN x) { struct montred * D = (struct montred *) E; GEN z = shifti(_sqr_montred(E, x), 1); long l = lgefint(D->N); while (lgefint(z) > l) z = subii(z, D->N); return z; } static GEN _sqr_remii(void* N, GEN x) { return remii(sqri(x), (GEN) N); } static GEN _mul_remii(void* N, GEN x, GEN y) { return remii(mulii(x, y), (GEN) N); } static GEN _mul2_remii(void* N, GEN x) { return Fp_double(_sqr_remii(N, x), (GEN)N); } struct redbarrett { GEN iM, N; long s; }; static GEN _sqr_remiibar(void *E, GEN x) { struct redbarrett * D = (struct redbarrett *) E; return Fp_rem_mBarrett(sqri(x), D->iM, D->s, D->N); } static GEN _mul_remiibar(void *E, GEN x, GEN y) { struct redbarrett * D = (struct redbarrett *) E; return Fp_rem_mBarrett(mulii(x, y), D->iM, D->s, D->N); } static GEN _mul2_remiibar(void *E, GEN x) { struct redbarrett * D = (struct redbarrett *) E; return Fp_double(_sqr_remiibar(E, x), D->N); } static long Fp_select_red(GEN *y, ulong k, GEN N, long lN, muldata *D, void **pt_E) { if (lN >= Fp_POW_BARRETT_LIMIT && (k==0 || ((double)k)*expi(*y) > 2 + expi(N))) { struct redbarrett * E = (struct redbarrett *) stack_malloc(sizeof(struct redbarrett)); D->sqr = &_sqr_remiibar; D->mul = &_mul_remiibar; D->mul2 = &_mul2_remiibar; E->N = N; E->s = 1+(expi(N)>>1); E->iM = Fp_invmBarrett(N, E->s); *pt_E = (void*) E; return 0; } else if (mod2(N) && lN < Fp_POW_REDC_LIMIT) { struct montred * E = (struct montred *) stack_malloc(sizeof(struct montred)); *y = remii(shifti(*y, bit_accuracy(lN)), N); D->sqr = &_sqr_montred; D->mul = &_mul_montred; D->mul2 = &_mul2_montred; E->N = N; E->inv = init_montdata(N); *pt_E = (void*) E; return 1; } else { D->sqr = &_sqr_remii; D->mul = &_mul_remii; D->mul2 = &_mul2_remii; *pt_E = (void*) N; return 0; } } GEN Fp_powu(GEN A, ulong k, GEN N) { long lN = lgefint(N); int base_is_2, use_montgomery; muldata D; void *E; pari_sp av; if (lN == 3) { ulong n = uel(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; } av = avma; A = modii(A,N); base_is_2 = 0; if (lgefint(A) == 3) switch(A[2]) { case 1: set_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(&A, k, N, lN, &D, &E); if (base_is_2) A = gen_powu_fold_i(A, k, E, D.sqr, D.mul2); else A = gen_powu_i(A, k, E, D.sqr, D.mul); if (use_montgomery) { A = red_montgomery(A, N, ((struct montred *) E)->inv); if (cmpii(A, N) >= 0) A = subii(A,N); } return gerepileuptoint(av, A); } GEN Fp_pows(GEN A, long k, GEN N) { if (lgefint(N) == 3) { ulong n = N[2]; ulong a = umodiu(A, n); if (k < 0) { a = Fl_inv(a, n); k = -k; } return utoi( Fl_powu(a, (ulong)k, n) ); } if (k < 0) { A = Fp_inv(A, N); k = -k; }; return Fp_powu(A, (ulong)k, N); } /* A^K mod N */ GEN Fp_pow(GEN A, GEN K, GEN N) { pari_sp av; long s, lN = lgefint(N), sA, sy; int base_is_2, use_montgomery; GEN y; muldata D; void *E; s = signe(K); if (!s) return dvdii(A,N)? gen_0: gen_1; if (lN == 3 && lgefint(K) == 3) { ulong n = N[2], a = umodiu(A, n); if (s < 0) a = Fl_inv(a, n); if (a <= 1) return utoi(a); /* 0 or 1 */ return utoi(Fl_powu(a, uel(K,2), n)); } av = avma; if (s < 0) y = Fp_inv(A,N); else { y = modii(A,N); if (!signe(y)) { set_avma(av); return gen_0; } } if (lgefint(K) == 3) return gerepileuptoint(av, Fp_powu(y, K[2], N)); base_is_2 = 0; sy = abscmpii(y, shifti(N,-1)) > 0; if (sy) y = subii(N,y); sA = sy && mod2(K); if (lgefint(y) == 3) switch(y[2]) { case 1: set_avma(av); return sA ? subis(N,1): 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, &E); if (base_is_2) y = gen_pow_fold_i(y, K, E, D.sqr, D.mul2); else y = gen_pow_i(y, K, E, D.sqr, D.mul); if (use_montgomery) { y = red_montgomery(y, N, ((struct montred *) E)->inv); if (cmpii(y,N) >= 0) y = subii(y,N); } if (sA) y = subii(N, y); return gerepileuptoint(av,y); } static GEN _Fp_mul(void *E, GEN x, GEN y) { return Fp_mul(x,y,(GEN)E); } static GEN _Fp_sqr(void *E, GEN x) { return Fp_sqr(x,(GEN)E); } static GEN _Fp_one(void *E) { (void) E; return gen_1; } GEN Fp_pow_init(GEN x, GEN n, long k, GEN p) { return gen_pow_init(x, n, k, (void*)p, &_Fp_sqr, &_Fp_mul); } GEN Fp_pow_table(GEN R, GEN n, GEN p) { return gen_pow_table(R, n, (void*)p, &_Fp_one, &_Fp_mul); } GEN Fp_powers(GEN x, long n, GEN p) { if (lgefint(p) == 3) return Flv_to_ZV(Fl_powers(umodiu(x, uel(p, 2)), n, uel(p, 2))); return gen_powers(x, n, 1, (void*)p, _Fp_sqr, _Fp_mul, _Fp_one); } GEN FpV_prod(GEN V, GEN p) { return gen_product(V, (void *)p, &_Fp_mul); } static GEN _Fp_pow(void *E, GEN x, GEN n) { return Fp_pow(x,n,(GEN)E); } static GEN _Fp_rand(void *E) { return addiu(randomi(subiu((GEN)E,1)),1); } static GEN Fp_easylog(void *E, GEN a, GEN g, GEN ord); static const struct bb_group Fp_star={_Fp_mul,_Fp_pow,_Fp_rand,hash_GEN, equalii,equali1,Fp_easylog}; static GEN _Fp_red(void *E, GEN x) { return Fp_red(x, (GEN)E); } static GEN _Fp_add(void *E, GEN x, GEN y) { (void) E; return addii(x,y); } static GEN _Fp_neg(void *E, GEN x) { (void) E; return negi(x); } static GEN _Fp_rmul(void *E, GEN x, GEN y) { (void) E; return mulii(x,y); } static GEN _Fp_inv(void *E, GEN x) { return Fp_inv(x,(GEN)E); } static int _Fp_equal0(GEN x) { return signe(x)==0; } static GEN _Fp_s(void *E, long x) { (void) E; return stoi(x); } static const struct bb_field Fp_field={_Fp_red,_Fp_add,_Fp_rmul,_Fp_neg, _Fp_inv,_Fp_equal0,_Fp_s}; const struct bb_field *get_Fp_field(void **E, GEN p) { *E = (void*)p; return &Fp_field; } /*********************************************************************/ /** ORDER of INTEGERMOD x in (Z/nZ)* **/ /*********************************************************************/ ulong Fl_order(ulong a, ulong o, ulong p) { pari_sp av = avma; GEN m, P, E; long i; if (a==1) return 1; 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) { o = t * upowuu(l, j); break; } } } return gc_ulong(av, o); } /*Find the exact order of a assuming a^o==1*/ GEN Fp_order(GEN a, GEN o, GEN p) { if (lgefint(p) == 3 && (!o || typ(o) == t_INT)) { ulong pp = p[2], oo = (o && lgefint(o)==3)? uel(o,2): pp-1; return utoi( Fl_order(umodiu(a, pp), oo, pp) ); } return gen_order(a, o, (void*)p, &Fp_star); } GEN Fp_factored_order(GEN a, GEN o, GEN p) { return gen_factored_order(a, o, (void*)p, &Fp_star); } /* return order of a mod p^e, e > 0, pe = p^e */ static GEN Zp_order(GEN a, GEN p, long e, GEN pe) { GEN ap, op; if (absequaliu(p, 2)) { if (e == 1) return gen_1; if (e == 2) return mod4(a) == 1? gen_1: gen_2; if (mod4(a) == 1) op = gen_1; else { op = gen_2; a = Fp_sqr(a, pe); } } else { ap = (e == 1)? a: remii(a,p); op = Fp_order(ap, subiu(p,1), p); if (e == 1) return op; a = Fp_pow(a, op, pe); /* 1 mod p */ } if (equali1(a)) return op; return mulii(op, powiu(p, e - Z_pval(subiu(a,1), p))); } GEN znorder(GEN x, GEN o) { pari_sp av = avma; GEN b, a; if (typ(x) != t_INTMOD) pari_err_TYPE("znorder [t_INTMOD expected]",x); b = gel(x,1); a = gel(x,2); if (!equali1(gcdii(a,b))) pari_err_COPRIME("znorder", a,b); if (!o) { GEN fa = Z_factor(b), P = gel(fa,1), E = gel(fa,2); long i, l = lg(P); o = gen_1; for (i = 1; i < l; i++) { GEN p = gel(P,i); long e = itos(gel(E,i)); if (l == 2) o = Zp_order(a, p, e, b); else { GEN pe = powiu(p,e); o = lcmii(o, Zp_order(remii(a,pe), p, e, pe)); } } return gerepileuptoint(av, o); } return Fp_order(a, o, b); } /*********************************************************************/ /** DISCRETE LOGARITHM in (Z/nZ)* **/ /*********************************************************************/ static GEN Fp_log_halfgcd(ulong bnd, GEN C, GEN g, GEN p) { pari_sp av = avma; GEN h1, h2, F, G; if (!Fp_ratlift(g,p,C,shifti(C,-1),&h1,&h2)) return gc_NULL(av); if ((F = Z_issmooth_fact(h1, bnd)) && (G = Z_issmooth_fact(h2, bnd))) { GEN M = cgetg(3, t_MAT); gel(M,1) = vecsmall_concat(gel(F, 1),gel(G, 1)); gel(M,2) = vecsmall_concat(gel(F, 2),zv_neg_inplace(gel(G, 2))); return gerepileupto(av, M); } return gc_NULL(av); } static GEN Fp_log_find_rel(GEN b, ulong bnd, GEN C, GEN p, GEN *g, long *e) { GEN rel; do { (*e)++; *g = Fp_mul(*g, b, p); rel = Fp_log_halfgcd(bnd, C, *g, p); } while (!rel); return rel; } struct Fp_log_rel { GEN rel; ulong prmax; long nbrel, nbmax, nbgen; }; static long tr(long i) { return odd(i) ? (i+1)>>1: -(i>>1); } static long rt(long i) { return i>0 ? 2*i-1: -2*i; } /* add u^e */ static void addifsmooth1(struct Fp_log_rel *r, GEN z, long u, long e) { pari_sp av = avma; long off = r->prmax+1; GEN F = cgetg(3, t_MAT); gel(F,1) = vecsmall_append(gel(z,1), off+rt(u)); gel(F,2) = vecsmall_append(gel(z,2), e); gel(r->rel,++r->nbrel) = gerepileupto(av, F); } /* add u^-1 v^-1 */ static void addifsmooth2(struct Fp_log_rel *r, GEN z, long u, long v) { pari_sp av = avma; long off = r->prmax+1; GEN P = mkvecsmall2(off+rt(u),off+rt(v)), E = mkvecsmall2(-1,-1); GEN F = cgetg(3, t_MAT); gel(F,1) = vecsmall_concat(gel(z,1), P); gel(F,2) = vecsmall_concat(gel(z,2), E); gel(r->rel,++r->nbrel) = gerepileupto(av, F); } /* Let p=C^2+c Solve h = (C+x)*(C+a)-p = 0 [mod l] h= -c+x*(C+a)+C*a = 0 [mod l] x = (c-C*a)/(C+a) [mod l] h = -c+C*(x+a)+a*x */ GEN Fp_log_sieve_worker(long a, long prmax, GEN C, GEN c, GEN Ci, GEN ci, GEN pi, GEN sz) { pari_sp ltop = avma; long i, j, th, n = lg(pi)-1, rel = 1, ab = labs(a), ae; GEN sieve = zero_zv(2*ab+2)+1+ab; GEN L = cgetg(1+2*ab+2, t_VEC); pari_sp av = avma; GEN z, h = addis(C,a); if ((z = Z_issmooth_fact(h, prmax))) { gel(L, rel++) = mkvec2(z, mkvecsmall3(1, a, -1)); av = avma; } for (i=1; i<=n; i++) { ulong li = pi[i], s = sz[i], al = smodss(a,li); ulong iv = Fl_invsafe(Fl_add(Ci[i],al,li),li); long u; if (!iv) continue; u = Fl_add(Fl_mul(Fl_sub(ci[i],Fl_mul(Ci[i],al,li),li), iv ,li),ab%li,li)-ab; for(j = u; j<=ab; j+=li) sieve[j] += s; } if (a) { long e = expi(mulis(C,a)); th = e - expu(e) - 1; } else th = -1; ae = a>=0 ? ab-1: ab; for (j = 1-ab; j <= ae; j++) if (sieve[j]>=th) { GEN h = absi(addis(subii(mulis(C,a+j),c), a*j)); if ((z = Z_issmooth_fact(h, prmax))) { gel(L, rel++) = mkvec2(z, mkvecsmall3(2, a, j)); av = avma; } else set_avma(av); } /* j = a */ if (sieve[a]>=th) { GEN h = absi(addiu(subii(mulis(C,2*a),c), a*a)); if ((z = Z_issmooth_fact(h, prmax))) gel(L, rel++) = mkvec2(z, mkvecsmall3(1, a, -2)); } setlg(L, rel); return gerepilecopy(ltop, L); } static long Fp_log_sieve(struct Fp_log_rel *r, GEN C, GEN c, GEN Ci, GEN ci, GEN pi, GEN sz) { struct pari_mt pt; long i, j, nb = 0; GEN worker = snm_closure(is_entry("_Fp_log_sieve_worker"), mkvecn(7, utoi(r->prmax), C, c, Ci, ci, pi, sz)); long running, pending = 0; GEN W = zerovec(r->nbgen); mt_queue_start_lim(&pt, worker, r->nbgen); for (i = 0; (running = (i < r->nbgen)) || pending; i++) { GEN done; long idx; mt_queue_submit(&pt, i, running ? mkvec(stoi(tr(i))): NULL); done = mt_queue_get(&pt, &idx, &pending); if (!done || lg(done)==1) continue; gel(W, idx+1) = done; nb += lg(done)-1; if (DEBUGLEVEL && (i&127)==0) err_printf("%ld%% ",100*nb/r->nbmax); } mt_queue_end(&pt); for(j = 1; j <= r->nbgen && r->nbrel < r->nbmax; j++) { long ll, m; GEN L = gel(W,j); if (isintzero(L)) continue; ll = lg(L); for (m=1; mnbrel < r->nbmax ; m++) { GEN Lm = gel(L,m), h = gel(Lm, 1), v = gel(Lm, 2); if (v[1] == 1) addifsmooth1(r, h, v[2], v[3]); else addifsmooth2(r, h, v[2], v[3]); } } return j; } static GEN ECP_psi(GEN x, GEN y) { long prec = realprec(x); GEN lx = glog(x, prec), ly = glog(y, prec); GEN u = gdiv(lx, ly); return gpow(u, gneg(u),prec); } struct computeG { GEN C; long bnd, nbi; }; static GEN _computeG(void *E, GEN gen) { struct computeG * d = (struct computeG *) E; GEN ps = ECP_psi(gmul(gen,d->C), stoi(d->bnd)); return gsub(gmul(gsqr(gen),ps),gmulgs(gaddgs(gen,d->nbi),3)); } static long compute_nbgen(GEN C, long bnd, long nbi) { struct computeG d; d.C = shifti(C, 1); d.bnd = bnd; d.nbi = nbi; return itos(ground(zbrent((void*)&d, _computeG, gen_2, stoi(bnd), DEFAULTPREC))); } static GEN _psi(void*E, GEN y) { GEN lx = (GEN) E; long prec = realprec(lx); GEN ly = glog(y, prec); GEN u = gdiv(lx, ly); return gsub(gdiv(y ,ly), gpow(u, u, prec)); } static GEN opt_param(GEN x, long prec) { return zbrent((void*)glog(x,prec), _psi, gen_2, x, prec); } static GEN check_kernel(long nbg, long N, long prmax, GEN C, GEN M, GEN p, GEN m) { pari_sp av = avma; long lM = lg(M)-1, nbcol = lM; long tbs = maxss(1, expu(nbg/expi(m))); for (;;) { GEN K = FpMs_leftkernel_elt_col(M, nbcol, N, m); GEN tab; long i, f=0; long l = lg(K), lm = lgefint(m); GEN idx = diviiexact(subiu(p,1),m), g; pari_timer ti; if (DEBUGLEVEL) timer_start(&ti); for(i=1; i (nbg>>1)) return gerepileupto(av, K); for(i=1; i<=nbcol; i++) { long a = 1+random_Fl(lM); swap(gel(M,a),gel(M,i)); } if (4*nbcol>5*nbg) nbcol = nbcol*9/10; } } static GEN Fp_log_find_ind(GEN a, GEN K, long prmax, GEN C, GEN p, GEN m) { pari_sp av=avma; GEN aa = gen_1; long AV = 0; for(;;) { GEN A = Fp_log_find_rel(a, prmax, C, p, &aa, &AV); GEN F = gel(A,1), E = gel(A,2); GEN Ao = gen_0; long i, l = lg(F); for(i=1; i=0) return NULL; p_1 = subiu(p,1); if (!is_pm1(gcdii(m,diviiexact(p_1,m)))) m = diviiexact(p_1, Z_ppo(p_1, m)); pr = primes_upto_zv(bnd); nbi = lg(pr)-1; C = sqrtremi(p, &c); av2 = avma; for (i = 1; i <= nbi; ++i) { ulong lp = pr[i]; while (lp <= bnd) { nbr++; lp *= pr[i]; } } pi = cgetg(nbr+1,t_VECSMALL); Ci = cgetg(nbr+1,t_VECSMALL); ci = cgetg(nbr+1,t_VECSMALL); sz = cgetg(nbr+1,t_VECSMALL); for (i = 1, j = 1; i <= nbi; ++i) { ulong lp = pr[i], sp = expu(2*lp-1); while (lp <= bnd) { pi[j] = lp; Ci[j] = umodiu(C, lp); ci[j] = umodiu(c, lp); sz[j] = sp; lp *= pr[i]; j++; } } r.nbrel = 0; r.nbgen = compute_nbgen(C, bnd, nbi); r.nbmax = 2*(nbi+r.nbgen); r.rel = cgetg(r.nbmax+1,t_VEC); r.prmax = pr[nbi]; if (DEBUGLEVEL) { err_printf("bnd=%lu Size FB=%ld extra gen=%ld \n", bnd, nbi, r.nbgen); timer_start(&ti); } nbg = Fp_log_sieve(&r, C, c, Ci, ci, pi, sz); nbrow = r.prmax + nbg; if (DEBUGLEVEL) { err_printf("\n"); timer_printf(&ti," %ld relations, %ld generators", r.nbrel, nbi+nbg); } setlg(r.rel,r.nbrel+1); r.rel = gerepilecopy(av2, r.rel); K = check_kernel(nbi+nbrow-r.prmax, nbrow, r.prmax, C, r.rel, p, m); if (DEBUGLEVEL) timer_start(&ti); Ao = Fp_log_find_ind(a, K, r.prmax, C, p, m); if (DEBUGLEVEL) timer_printf(&ti," log element"); Bo = Fp_log_find_ind(b, K, r.prmax, C, p, m); if (DEBUGLEVEL) timer_printf(&ti," log generator"); d = gcdii(Ao,Bo); l = Fp_div(diviiexact(Ao, d) ,diviiexact(Bo, d), m); if (!equalii(a,Fp_pow(b,l,p))) pari_err_BUG("Fp_log_index"); return gerepileuptoint(av, l); } static int Fp_log_use_index(long e, long p) { return (e >= 27 && 20*(p+6)<=e*e); } /* Trivial cases a = 1, -1. Return x s.t. g^x = a or [] if no such x exist */ static GEN Fp_easylog(void *E, GEN a, GEN g, GEN ord) { pari_sp av = avma; GEN p = (GEN)E; /* assume a reduced mod p, p not necessarily prime */ if (equali1(a)) return gen_0; /* p > 2 */ if (equalii(subiu(p,1), a)) /* -1 */ { pari_sp av2; GEN t; ord = get_arith_Z(ord); if (mpodd(ord)) { set_avma(av); return cgetg(1, t_VEC); } /* no solution */ t = shifti(ord,-1); /* only possible solution */ av2 = avma; if (!equalii(Fp_pow(g, t, p), a)) { set_avma(av); return cgetg(1, t_VEC); } set_avma(av2); return gerepileuptoint(av, t); } if (typ(ord)==t_INT && BPSW_psp(p) && Fp_log_use_index(expi(ord),expi(p))) return Fp_log_index(a, g, ord, p); return gc_NULL(av); /* not easy */ } GEN Fp_log(GEN a, GEN g, GEN ord, GEN p) { GEN v = get_arith_ZZM(ord); GEN F = gmael(v,2,1); long lF = lg(F)-1, lmax; if (lF == 0) return equali1(a)? gen_0: cgetg(1, t_VEC); lmax = expi(gel(F,lF)); if (BPSW_psp(p) && Fp_log_use_index(lmax,expi(p))) v = mkvec2(gel(v,1),ZM_famat_limit(gel(v,2),int2n(27))); return gen_PH_log(a,g,v,(void*)p,&Fp_star); } /* assume !(p & HIGHMASK) */ static ulong Fl_log_naive(ulong a, ulong g, ulong ord, ulong p) { ulong i, h=1; for (i = 0; i < ord; i++, h = (h * g) % p) if (a==h) return i; return ~0UL; } static ulong Fl_log_naive_pre(ulong a, ulong g, ulong ord, ulong p, ulong pi) { ulong i, h=1; for (i = 0; i < ord; i++, h = Fl_mul_pre(h, g, p, pi)) if (a==h) return i; return ~0UL; } static ulong Fl_log_Fp(ulong a, ulong g, ulong ord, ulong p) { pari_sp av = avma; GEN r = Fp_log(utoi(a),utoi(g),utoi(ord),utoi(p)); return gc_ulong(av, typ(r)==t_INT ? itou(r): ~0UL); } /* allow pi = 0 */ ulong Fl_log_pre(ulong a, ulong g, ulong ord, ulong p, ulong pi) { if (!pi) return Fl_log(a, g, ord, p); if (ord <= 200) return Fl_log_naive_pre(a, g, ord, p, pi); return Fl_log_Fp(a, g, ord, p); } ulong Fl_log(ulong a, ulong g, ulong ord, ulong p) { if (ord <= 200) return (p&HIGHMASK)? Fl_log_naive_pre(a, g, ord, p, get_Fl_red(p)) : Fl_log_naive(a, g, ord, p); return Fl_log_Fp(a, g, ord, p); } /* find x such that h = g^x mod N > 1, N = prod_{i <= l} P[i]^E[i], P[i] prime. * PHI[l] = eulerphi(N / P[l]^E[l]). Destroys P/E */ static GEN znlog_rec(GEN h, GEN g, GEN N, GEN P, GEN E, GEN PHI) { long l = lg(P) - 1, e = E[l]; GEN p = gel(P, l), phi = gel(PHI,l), pe = e == 1? p: powiu(p, e); GEN a,b, hp,gp, hpe,gpe, ogpe; /* = order(g mod p^e) | p^(e-1)(p-1) */ if (l == 1) { hpe = h; gpe = g; } else { hpe = modii(h, pe); gpe = modii(g, pe); } if (e == 1) { hp = hpe; gp = gpe; } else { hp = remii(hpe, p); gp = remii(gpe, p); } if (hp == gen_0 || gp == gen_0) return NULL; if (absequaliu(p, 2)) { GEN n = int2n(e); ogpe = Zp_order(gpe, gen_2, e, n); a = Fp_log(hpe, gpe, ogpe, n); if (typ(a) != t_INT) return NULL; } else { /* Avoid black box groups: (Z/p^2)^* / (Z/p)^* ~ (Z/pZ, +), where DL is trivial */ /* [order(gp), factor(order(gp))] */ GEN v = Fp_factored_order(gp, subiu(p,1), p); GEN ogp = gel(v,1); if (!equali1(Fp_pow(hp, ogp, p))) return NULL; a = Fp_log(hp, gp, v, p); if (typ(a) != t_INT) return NULL; if (e == 1) ogpe = ogp; else { /* find a s.t. g^a = h (mod p^e), p odd prime, e > 0, (h,p) = 1 */ /* use p-adic log: O(log p + e) mul*/ long vpogpe, vpohpe; hpe = Fp_mul(hpe, Fp_pow(gpe, negi(a), pe), pe); gpe = Fp_pow(gpe, ogp, pe); /* g,h = 1 mod p; compute b s.t. h = g^b */ /* v_p(order g mod pe) */ vpogpe = equali1(gpe)? 0: e - Z_pval(subiu(gpe,1), p); /* v_p(order h mod pe) */ vpohpe = equali1(hpe)? 0: e - Z_pval(subiu(hpe,1), p); if (vpohpe > vpogpe) return NULL; ogpe = mulii(ogp, powiu(p, vpogpe)); /* order g mod p^e */ if (is_pm1(gpe)) return is_pm1(hpe)? a: NULL; b = gdiv(Qp_log(cvtop(hpe, p, e)), Qp_log(cvtop(gpe, p, e))); a = addii(a, mulii(ogp, padic_to_Q(b))); } } /* gp^a = hp => x = a mod ogpe => generalized Pohlig-Hellman strategy */ if (l == 1) return a; N = diviiexact(N, pe); /* make N coprime to p */ h = Fp_mul(h, Fp_pow(g, modii(negi(a), phi), N), N); g = Fp_pow(g, modii(ogpe, phi), N); setlg(P, l); /* remove last element */ setlg(E, l); b = znlog_rec(h, g, N, P, E, PHI); if (!b) return NULL; return addmulii(a, b, ogpe); } static GEN get_PHI(GEN P, GEN E) { long i, l = lg(P); GEN PHI = cgetg(l, t_VEC); gel(PHI,1) = gen_1; for (i=1; i 1) t = mulii(t, gel(PHI,i)); gel(PHI,i+1) = t; } return PHI; } GEN znlog(GEN h, GEN g, GEN o) { pari_sp av = avma; GEN N, fa, P, E, x; switch (typ(g)) { case t_PADIC: { GEN p = gel(g,2); long v = valp(g); if (v < 0) pari_err_DIM("znlog"); if (v > 0) { long k = gvaluation(h, p); if (k % v) return cgetg(1,t_VEC); k /= v; if (!gequal(h, gpowgs(g,k))) { set_avma(av); return cgetg(1,t_VEC); } return gc_stoi(av, k); } N = gel(g,3); g = Rg_to_Fp(g, N); break; } case t_INTMOD: N = gel(g,1); g = gel(g,2); break; default: pari_err_TYPE("znlog", g); return NULL; /* LCOV_EXCL_LINE */ } if (equali1(N)) { set_avma(av); return gen_0; } h = Rg_to_Fp(h, N); if (o) return gerepileupto(av, Fp_log(h, g, o, N)); fa = Z_factor(N); P = gel(fa,1); E = vec_to_vecsmall(gel(fa,2)); x = znlog_rec(h, g, N, P, E, get_PHI(P,E)); if (!x) { set_avma(av); return cgetg(1,t_VEC); } return gerepileuptoint(av, x); } GEN Fp_sqrtn(GEN a, GEN n, GEN p, GEN *zeta) { if (lgefint(p)==3) { long nn = itos_or_0(n); if (nn) { ulong pp = p[2]; ulong uz; ulong r = Fl_sqrtn(umodiu(a,pp),nn,pp, zeta ? &uz:NULL); if (r==ULONG_MAX) return NULL; if (zeta) *zeta = utoi(uz); return utoi(r); } } a = modii(a,p); if (!signe(a)) { if (zeta) *zeta = gen_1; if (signe(n) < 0) pari_err_INV("Fp_sqrtn", mkintmod(gen_0,p)); return gen_0; } if (absequaliu(n,2)) { if (zeta) *zeta = subiu(p,1); return signe(n) > 0 ? Fp_sqrt(a,p): Fp_sqrt(Fp_inv(a, p),p); } return gen_Shanks_sqrtn(a,n,subiu(p,1),zeta,(void*)p,&Fp_star); } /*********************************************************************/ /** FACTORIAL **/ /*********************************************************************/ GEN mulu_interval_step(ulong a, ulong b, ulong step) { pari_sp av = avma; ulong k, l, N, n; long lx; GEN x; if (!a) return gen_0; if (step == 1) return mulu_interval(a, b); n = 1 + (b-a) / step; b -= (b-a) % step; if (n < 61) { if (n == 1) return utoipos(a); x = muluu(a,a+step); if (n == 2) return x; for (k=a+2*step; k<=b; k+=step) x = mului(k,x); return gerepileuptoint(av, x); } /* step | b-a */ lx = 1; x = cgetg(2 + n/2, t_VEC); N = b + a; for (k = a;; k += step) { 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, ZV_prod(x)); } /* 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; long lx; GEN x; if (!a) return gen_0; n = b - a + 1; if (n < 61) { if (n == 1) return utoipos(a); x = muluu(a,a+1); if (n == 2) return x; for (k=a+2; k= 0) return gen_0; if (n < 61) { x = stoi(a); for (k=a+1; k<=b; k++) x = mulsi(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++) = mulss(k,l); } if (l == k) gel(x,lx++) = stoi(k); setlg(x, lx); return gerepileuptoint(av, ZV_prod(x)); } GEN mpprimorial(long n) { pari_sp av = avma; if (n <= 12) switch(n) { case 0: case 1: return gen_1; case 2: return gen_2; case 3: case 4: return utoipos(6); case 5: case 6: return utoipos(30); case 7: case 8: case 9: case 10: return utoipos(210); case 11: case 12: return utoipos(2310); default: pari_err_DOMAIN("primorial", "argument","<",gen_0,stoi(n)); } return gerepileuptoint(av, zv_prod_Z(primes_upto_zv(n))); } GEN mpfact(long n) { pari_sp av = avma; GEN a, v; long k; if (n <= 12) switch(n) { case 0: case 1: return gen_1; case 2: return gen_2; case 3: return utoipos(6); case 4: return utoipos(24); case 5: return utoipos(120); case 6: return utoipos(720); case 7: return utoipos(5040); case 8: return utoipos(40320); case 9: return utoipos(362880); case 10:return utoipos(3628800); case 11:return utoipos(39916800); case 12:return utoipos(479001600); default: pari_err_DOMAIN("factorial", "argument","<",gen_0,stoi(n)); } v = cgetg(expu(n) + 2, t_VEC); for (k = 1;; k++) { long m = n >> (k-1), l; if (m <= 2) break; l = (1 + (n >> k)) | 1; /* product of odd numbers in ]n / 2^k, n / 2^(k-1)] */ a = mulu_interval_step(l, m, 2); gel(v,k) = k == 1? a: powiu(a, k); } a = gel(v,--k); while (--k) a = mulii(a, gel(v,k)); a = shifti(a, factorial_lval(n, 2)); return gerepileuptoint(av, a); } ulong factorial_Fl(long n, ulong p) { long k; ulong v; if (p <= (ulong)n) return 0; v = Fl_powu(2, factorial_lval(n, 2), p); for (k = 1;; k++) { long m = n >> (k-1), l, i; ulong a = 1; if (m <= 2) break; l = (1 + (n >> k)) | 1; /* product of odd numbers in ]n / 2^k, 2 / 2^(k-1)] */ for (i=l; i<=m; i+=2) a = Fl_mul(a, i, p); v = Fl_mul(v, k == 1? a: Fl_powu(a, k, p), p); } return v; } GEN factorial_Fp(long n, GEN p) { pari_sp av = avma; long k; GEN v = Fp_powu(gen_2, factorial_lval(n, 2), p); for (k = 1;; k++) { long m = n >> (k-1), l, i; GEN a = gen_1; if (m <= 2) break; l = (1 + (n >> k)) | 1; /* product of odd numbers in ]n / 2^k, 2 / 2^(k-1)] */ for (i=l; i<=m; i+=2) a = Fp_mulu(a, i, p); v = Fp_mul(v, k == 1? a: Fp_powu(a, k, p), p); v = gerepileuptoint(av, v); } return v; } /*******************************************************************/ /** 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 = subiu(sqri(z),2); *b = subiu(zt,1); break; case 1: *a = subiu(zt,1); *b = addiu(sqri(t),2); break; case 2: *a = addiu(sqri(z),2); *b = addiu(zt,1); break; case 3: *a = addiu(zt,1); *b = subiu(sqri(t),2); } } 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 1 / log2( (1+sqrt(5)) / 2 ) */ l = (ulong)(3 + bit_accuracy_mul(ly, 1.44042009041256)); if (k > 0 && k+1 > 0 && l > k+1) l = k+1; /* beware overflow */ if (l > LGBITS) l = LGBITS; z = cgetg(l,t_VEC); l--; if (y) { pari_sp av = avma; if (l >= (ulong)lg(y)) l = lg(y)-1; for (i = 1; i <= l; i++) { GEN q = gel(y,i); gel(z,i) = q; c = b; if (!gequal1(q)) c = mulii(q, b); c = subii(a, c); if (signe(c) < 0) { /* partial quotient too large */ c = addii(c, b); if (signe(c) >= 0) i++; /* by 1 */ break; } if (cmpii(c, b) >= 0) { /* partial quotient too small */ c = subii(c, b); if (cmpii(c, b) < 0) { /* by 1. If next quotient is 1 in y, add 1 */ if (i < l && equali1(gel(y,i+1))) gel(z,i) = addiu(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) = addui(1, gel(z,i)); /* unclean: leave old z[i] on stack */ } setlg(z,i+1); return z; } static GEN sersfcont(GEN a, GEN b, long k) { long i, l = typ(a) == t_POL? lg(a): 3; GEN y, c; if (lg(b) > l) l = lg(b); if (k > 0 && l > k+1) l = k+1; y = cgetg(l,t_VEC); for (i=1; i= lb) pari_err_DIM("contfrac [too few denominators]"); lb = k+1; } y = cgetg(lb,t_VEC); if (lb==1) return y; if (is_scalar_t(tx)) { if (!is_intreal_t(tx) && tx != t_FRAC) pari_err_TYPE("sfcont2",x); } else if (tx == t_SER) x = ser2rfrac_i(x); if (!gequal1(gel(b,1))) x = gmul(gel(b,1),x); for (i = 1;;) { if (tx == t_REAL) { long e = expo(x); if (e > 0 && nbits2prec(e+1) > realprec(x)) break; gel(y,i) = floorr(x); p1 = subri(x, gel(y,i)); } else { gel(y,i) = gfloor(x); p1 = gsub(x, gel(y,i)); } if (++i >= lb) break; if (gequal0(p1)) break; x = gdiv(gel(b,i),p1); } setlg(y,i); return gerepilecopy(av,y); } GEN gcf(GEN x) { return gboundcf(x,0); } GEN gcf2(GEN b, GEN x) { return contfrac0(x,b,0); } GEN contfrac0(GEN x, GEN b, long nmax) { long tb; if (!b) return gboundcf(x,nmax); tb = typ(b); if (tb == t_INT) return gboundcf(x,itos(b)); if (! is_vec_t(tb)) pari_err_TYPE("contfrac0",b); if (nmax < 0) pari_err_DOMAIN("contfrac","nmax","<",gen_0,stoi(nmax)); return sfcont2(b,x,nmax); } GEN contfracpnqn(GEN x, long n) { pari_sp av = avma; long i, lx = lg(x); GEN M,A,B, p0,p1, q0,q1; if (lx == 1) { if (! is_matvec_t(typ(x))) pari_err_TYPE("pnqn",x); if (n >= 0) return cgetg(1,t_MAT); return matid(2); } switch(typ(x)) { case t_VEC: case t_COL: A = x; B = NULL; break; case t_MAT: switch(lgcols(x)) { case 2: A = row(x,1); B = NULL; break; case 3: A = row(x,2); B = row(x,1); break; default: pari_err_DIM("pnqn [ nbrows != 1,2 ]"); return NULL; /*LCOV_EXCL_LINE*/ } break; default: pari_err_TYPE("pnqn",x); return NULL; /*LCOV_EXCL_LINE*/ } p1 = gel(A,1); q1 = B? gel(B,1): gen_1; /* p[0], q[0] */ if (n >= 0) { lx = minss(lx, n+2); if (lx == 2) return gerepilecopy(av, mkmat(mkcol2(p1,q1))); } else if (lx == 2) return gerepilecopy(av, mkmat2(mkcol2(p1,q1), mkcol2(gen_1,gen_0))); /* lx >= 3 */ p0 = gen_1; q0 = gen_0; /* p[-1], q[-1] */ M = cgetg(lx, t_MAT); gel(M,1) = mkcol2(p1,q1); for (i=2; i= 0; * return [[p0, ..., pn], [q0,...,qn]] */ GEN ZV_allpnqn(GEN x) { long i, lx = lg(x); GEN p0, p1, q0, q1, p2, q2, P,Q, v = cgetg(3,t_VEC); gel(v,1) = P = cgetg(lx, t_VEC); gel(v,2) = Q = cgetg(lx, t_VEC); p0 = gen_1; q0 = gen_0; gel(P, 1) = p1 = gel(x,1); gel(Q, 1) = q1 = gen_1; for (i=2; i= 0) A = d-1 - B; else { B = d >> 1; A = odd(d)? B : B-1; } if (varn(N) != varn(x)) x = scalarpol(x, varn(N)); if (!RgXQ_ratlift(x, N, A, B, &a,&b) || degpol(RgX_gcd(a,b)) > 0) return NULL; return gdiv(a,b); } /* k > 0 t_INT, x a t_FRAC, returns the convergent a/b * of the continued fraction of x with b <= k maximal */ static GEN bestappr_frac(GEN x, GEN k) { pari_sp av; GEN p0, p1, p, q0, q1, q, a, y; if (cmpii(gel(x,2),k) <= 0) return gcopy(x); av = avma; y = x; p1 = gen_1; p0 = truedvmdii(gel(x,1), gel(x,2), &a); /* = floor(x) */ q1 = gen_0; q0 = gen_1; x = mkfrac(a, gel(x,2)); /* = frac(x); now 0<= x < 1 */ for(;;) { x = ginv(x); /* > 1 */ a = typ(x)==t_INT? x: divii(gel(x,1), gel(x,2)); if (cmpii(a,k) > 0) { /* next partial quotient will overflow limits */ GEN n, d; a = divii(subii(k, q1), q0); p = addii(mulii(a,p0), p1); p1=p0; p0=p; q = addii(mulii(a,q0), q1); q1=q0; q0=q; /* compare |y-p0/q0|, |y-p1/q1| */ n = gel(y,1); d = gel(y,2); if (abscmpii(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)); } /* k > 0 t_INT, x != 0 a t_REAL, returns the convergent a/b * of the continued fraction of x with b <= k maximal */ static GEN bestappr_real(GEN x, GEN k) { pari_sp av = avma; GEN kr, p0, p1, p, q0, q1, q, a, y = x; p1 = gen_1; a = p0 = floorr(x); q1 = gen_0; q0 = gen_1; x = subri(x,a); /* 0 <= x < 1 */ if (!signe(x)) { cgiv(x); return a; } kr = itor(k, realprec(x)); for(;;) { long d; x = invr(x); /* > 1 */ if (cmprr(x,kr) > 0) { /* next partial quotient will overflow limits */ a = divii(subii(k, q1), q0); p = addii(mulii(a,p0), p1); p1=p0; p0=p; q = addii(mulii(a,q0), q1); q1=q0; q0=q; /* compare |y-p0/q0|, |y-p1/q1| */ if (abscmprr(mulir(q1, subri(mulir(q0,y), p0)), mulir(q0, subri(mulir(q1,y), p1))) < 0) { p1 = p0; q1 = q0; } break; } d = nbits2prec(expo(x) + 1); if (d > realprec(x)) { p1 = p0; q1 = q0; break; } /* original x was ~ 0 */ a = truncr(x); /* truncr(x) will NOT raise e_PREC */ p = addii(mulii(a,p0), p1); p1=p0; p0=p; q = addii(mulii(a,q0), q1); q1=q0; q0=q; if (cmpii(q0,k) > 0) break; x = subri(x,a); /* 0 <= x < 1 */ if (!signe(x)) { p1 = p0; q1 = q0; break; } } if (signe(q1) < 0) { togglesign_safe(&p1); togglesign_safe(&q1); } return gerepilecopy(av, equali1(q1)? p1: mkfrac(p1,q1)); } /* k t_INT or NULL */ static GEN bestappr_Q(GEN x, GEN k) { long lx, tx = typ(x), i; GEN a, y; switch(tx) { case t_INT: return icopy(x); case t_FRAC: return k? bestappr_frac(x, k): gcopy(x); case t_REAL: if (!signe(x)) return gen_0; /* i <= e iff nbits2lg(e+1) > lg(x) iff floorr(x) fails */ i = bit_prec(x); if (i <= expo(x)) return NULL; return bestappr_real(x, k? k: int2n(i)); case t_INTMOD: { pari_sp av = avma; a = mod_to_frac(gel(x,2), gel(x,1), k); if (!a) return NULL; return gerepilecopy(av, a); } case t_PADIC: { pari_sp av = avma; long v = valp(x); a = mod_to_frac(gel(x,4), gel(x,3), k); if (!a) return NULL; if (v) a = gmul(a, powis(gel(x,2), v)); return gerepilecopy(av, a); } case t_COMPLEX: { pari_sp av = avma; y = cgetg(3, t_COMPLEX); gel(y,2) = bestappr(gel(x,2), k); gel(y,1) = bestappr(gel(x,1), k); if (gequal0(gel(y,2))) return gerepileupto(av, gel(y,1)); return y; } case t_SER: if (ser_isexactzero(x)) return gcopy(x); /* fall through */ case t_POLMOD: case t_POL: case t_RFRAC: case t_VEC: case t_COL: case t_MAT: y = cgetg_copy(x, &lx); if (lontyp[tx] == 1) i = 1; else { y[1] = x[1]; i = 2; } for (; i 0) { x = RgX_shift_shallow(x, v); dN += v; } else if (v < 0) { if (B >= 0) B = maxss(B+v, 0); } t = mod_to_rfrac(x, pol_xn(dN, varn(x)), B); if (!t) return NULL; if (v < 0) { GEN a, b; long vx; if (typ(t) == t_POL) return RgX_mulXn(t, v); /* t_RFRAC */ vx = varn(x); a = gel(t,1); b = gel(t,2); v -= RgX_valrem(b, &b); if (typ(a) == t_POL && varn(a) == vx) v += RgX_valrem(a, &a); if (v < 0) b = RgX_shift_shallow(b, -v); else if (v > 0) { if (typ(a) != t_POL || varn(a) != vx) a = scalarpol_shallow(a, vx); a = RgX_shift_shallow(a, v); } t = mkrfraccopy(a, b); } return t; } static GEN gc_empty(pari_sp av) { set_avma(av); return cgetg(1, t_VEC); } static GEN _gc_upto(pari_sp av, GEN x) { return x? gerepileupto(av, x): NULL; } static GEN bestappr_RgX(GEN x, long B); /* B >= 0 or < 0 [omit condition on B]. * Look for coprime t_POL a,b, deg(b)<=B, such that a/b ~ x */ static GEN bestappr_RgX(GEN x, long B) { pari_sp av; switch(typ(x)) { case t_INT: case t_REAL: case t_INTMOD: case t_FRAC: case t_FFELT: case t_COMPLEX: case t_PADIC: case t_QUAD: case t_POL: return gcopy(x); case t_RFRAC: if (B < 0 || degpol(gel(x,2)) <= B) return gcopy(x); av = avma; return _gc_upto(av, bestappr_ser(rfrac_to_ser_i(x, 2*B+1), B)); case t_POLMOD: av = avma; return _gc_upto(av, mod_to_rfrac(gel(x,2), gel(x,1), B)); case t_SER: av = avma; return _gc_upto(av, bestappr_ser(x, B)); case t_VEC: case t_COL: case t_MAT: { long i, lx; GEN y = cgetg_copy(x, &lx); for (i = 1; i < lx; i++) { GEN t = bestappr_RgX(gel(x,i),B); if (!t) return NULL; gel(y,i) = t; } return y; } } pari_err_TYPE("bestappr_RgX",x); return NULL; /* LCOV_EXCL_LINE */ } /* allow k = NULL: maximal accuracy */ GEN bestappr(GEN x, GEN k) { pari_sp av = avma; if (k) { /* replace by floor(k) */ switch(typ(k)) { case t_INT: break; case t_REAL: case t_FRAC: k = floor_safe(k); /* left on stack for efficiency */ if (!signe(k)) k = gen_1; break; default: pari_err_TYPE("bestappr [bound type]", k); break; } } x = bestappr_Q(x, k); return x? x: gc_empty(av); } GEN bestapprPade(GEN x, long B) { pari_sp av = avma; GEN t = bestappr_RgX(x, B); return t? t: gc_empty(av); } static GEN serPade(GEN S, long p, long q) { pari_sp av = avma; long va, v, t = typ(S); if (t!=t_SER && t!=t_POL && t!=t_RFRAC) pari_err_TYPE("bestapprPade", S); va = gvar(S); v = gvaluation(S, pol_x(va)); if (p < 0) pari_err_DOMAIN("bestapprPade", "p", "<", gen_0, stoi(p)); if (q < 0) pari_err_DOMAIN("bestapprPade", "q", "<", gen_0, stoi(q)); if (v == LONG_MAX) return gc_empty(av); S = gadd(S, zeroser(va, p + q + 1 + v)); return gerepileupto(av, bestapprPade(S, q)); } GEN bestapprPade0(GEN x, long p, long q) { return (p >= 0 && q >= 0)? serPade(x, p, q) : bestapprPade(x, p >= 0? p: q); } pari-2.17.2/src/basemath/hnf_snf.c0000644000175000017500000023526014676526175015357 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_mathnf /**************************************************************/ /** **/ /** HERMITE NORMAL FORM REDUCTION **/ /** **/ /**************************************************************/ static GEN ZV_hnfgcdext(GEN A); static GEN hnfallgen(GEN x) { GEN z = cgetg(3, t_VEC); gel(z,1) = RgM_hnfall(x, (GEN*)(z+2), 1); return z; } GEN mathnf0(GEN x, long flag) { switch(typ(x)) { case t_VEC: if (RgV_is_ZV(x)) switch (flag) { case 0: if (lg(x) == 1) return cgetg(1, t_MAT); retmkmat(mkcol(ZV_content(x))); case 1: case 4: return ZV_hnfgcdext(x); } x = gtomat(x); break; case t_MAT: break; default: pari_err_TYPE("mathnf0",x); } switch(flag) { case 0: case 2: return RgM_is_ZM(x)? ZM_hnf(x): RgM_hnfall(x,NULL,1); case 1: case 3: return RgM_is_ZM(x)? hnfall(x): hnfallgen(x); case 4: RgM_check_ZM(x, "mathnf0"); return hnflll(x); case 5: RgM_check_ZM(x, "mathnf0"); return hnfperm(x); default: pari_err_FLAG("mathnf"); } return NULL; /* LCOV_EXCL_LINE */ } /*******************************************************************/ /* */ /* 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; 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 = nbrows(matgen); /* was called lnz-1 - nr in hnfspec */ nlze = nbrows(dep); 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; Cnew = cgetg(co, typ(C)); setlg(C, col+1); p1 = gmul(C,U); for (j=1; j<=col; j++) gel(Cnew,j) = gel(p1,j); 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]) gel(p1,++j1) = gel(p2,i); else gel(p2,++i1) = gel(p2,i); for (i=i1+1; i<=lnz; i++) gel(p2,i) = gel(p1,i); /* s = # extra redundant generators taken from H * zc col-s co zc = col - lnz * [ 0 |dep | ] i = nlze + lnz - s = lig - s * nlze [--------| B' ] * [ 0 | H' | ] H' = H minus the s rows with a 1 on diagonal * i [--------|-----] lig-s (= "1-rows") * [ 0 | Id ] * [ | ] li */ lig -= s; col -= s; lnz -= s; Hnew = cgetg(lnz+1,t_MAT); depnew = cgetg(lnz+1,t_MAT); /* only used if nlze > 0 */ Bnew = cgetg(co-col,t_MAT); C = shallowcopy(Cnew); for (j=1,i1=j1=0; j<=lnz+s; j++) { GEN z = gel(H,j); if (diagH1[j]) { /* hit exactly s times */ i1++; C[i1+col] = Cnew[j+zc]; p1 = cgetg(lig+1,t_COL); gel(Bnew,i1) = p1; for (i=1; i<=nlze; i++) gel(p1,i) = gcoeff(dep,i,j); p1 += nlze; } else { j1++; C[j1+zc] = Cnew[j+zc]; p1 = cgetg(lnz+1,t_COL); gel(Hnew,j1) = p1; depnew[j1] = dep[j]; } for (i=k=1; k<=lnz; i++) if (!diagH1[i]) p1[k++] = z[i]; } for (j=s+1; j 6) err_printf("matgen = %Ps\n", zm_to_ZM( rowpermute(mat, perm) )); set_avma(av); } static GEN col_dup(long l, GEN col) { GEN c = new_chunk(l); memcpy(c,col,l * sizeof(long)); return c; } /* permutation giving imagecompl(x') | image(x'), x' = transpose of x */ static GEN ZM_rowrankprofile(GEN x, long *nlze) { pari_sp av = avma; GEN d, y; long i, j, k, l, r; x = shallowtrans(x); l = lg(x); (void)new_chunk(l); /* HACK */ d = ZM_pivots(x,&r); set_avma(av); *nlze = r; if (!d) return identity_perm(l-1); y = cgetg(l,t_VECSMALL); for (i = j = 1, k = r+1; i 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; i = lig = li-1; col = co-1; lk0 = k0; T = (k0 || (lg(C) > 1 && lgcols(C) > 1))? matid(col): NULL; /* Look for lines with a single nonzero 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 nonzero */ 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 set_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 (gc_needed(av,3)) { 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 = %ld", i); 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 nonzero rows (!= 0...0 1 0 ... 0) */ if (T) matt = ZM_mul(matt,T); /* update top rows */ extramat = cgetg(col+1,t_MAT); /* = new C minus the 0 rows */ for (j=1; j<=col; j++) { GEN z = gel(matt,j); GEN t = (gel(matb,j)) + nlze - k0; p2=cgetg(lnz,t_COL); gel(extramat,j) = p2; for (i=1; i<=k0; i++) gel(p2,i) = gel(z,i); /* top k0 rows */ for ( ; i co) { /* treat the rest, N cols at a time (hnflll slow otherwise) */ const long N = 300; long a, L = CO - co, l = minss(L, N); /* L columns to add */ GEN CC = *ptC, m0 = mat0; setlg(CC, CO); /* restore */ CC += co-1; m0 += co-1; for (a = l;;) { GEN MAT, emb; gerepileall(av, 4, &H,&C,ptB,ptdep); MAT = cgetg(l + 1, t_MAT); emb = cgetg(l + 1, typ(C)); for (j = 1 ; j <= l; j++) { gel(MAT,j) = gel(m0,j); emb[j] = CC[j]; } H = hnfadd_i(H, perm, ptdep, ptB, &C, MAT, emb); if (a == L) break; CC += l; m0 += l; a += l; if (a > L) { l = L - (a - l); a = L; } } } *ptC = C; return H; } GEN hnfspec(GEN mat, GEN perm, GEN* ptdep, GEN* ptB, GEN* ptC, long k0) { pari_sp av = avma; GEN H = hnfspec_i(mat, perm, ptdep, ptB, ptC, k0); return gc_all(av, 4, &H, ptC, ptdep, ptB); } /* HNF reduce x, apply same transforms to C */ GEN mathnfspec(GEN x, GEN *pperm, GEN *pdep, GEN *pB, GEN *pC) { long i, j, k, l, n, ly, lx = lg(x); GEN z, v1, perm; if (lx == 1) return cgetg(1, t_MAT); ly = lgcols(x); *pperm = perm = identity_perm(ly-1); z = cgetg(lx,t_MAT); for (i=1; i 1 && lgcols(*pC) > 1) pari_err_IMPL("mathnfspec with large entries"); x = ZM_hnf(x); lx = lg(x); v1 = cgetg(ly, t_VECSMALL); n = lx - ly; for (i = k = l = 1; i < ly; i++) if (equali1(gcoeff(x,i,i + n))) v1[l++] = i; else perm[k++] = i; setlg(perm, k); setlg(v1, l); x = rowpermute(x, perm); /* upper part */ *pperm = vecsmall_concat(perm, v1); *pB = vecslice(x, k+n, lx-1); setlg(x, k); *pdep = rowslice(x, 1, n); return n? rowslice(x, n+1, k-1): x; /* H */ } /* add new relations to a matrix treated by hnfspec (extramat / extraC) */ GEN hnfadd_i(GEN H, GEN perm, GEN* ptdep, GEN* ptB, GEN* ptC, /* cf hnfspec */ GEN extramat,GEN extraC) { GEN matb, extratop, Cnew, permpro, B = *ptB, C = *ptC, dep = *ptdep; long i, lH, lB, li, lig, co, col, nlze; if (lg(extramat) == 1) return H; co = lg(C)-1; lH = lg(H)-1; lB = lg(B)-1; li = lg(perm)-1; lig = li - lB; col = co - lB; nlze = lig - lH; /* col co * [ 0 |dep | ] * nlze [--------| B ] * [ 0 | H | ] * [--------|-----] lig * [ 0 | Id ] * [ | ] li */ extratop = zm_to_ZM( rowslicepermute(extramat, perm, 1, lig) ); if (li != lig) { /* zero out bottom part, using the Id block */ GEN A = vecslice(C, col+1, co); GEN c = rowslicepermute(extramat, perm, lig+1, li); extraC = gsub(extraC, typ(A)==t_MAT? RgM_zm_mul(A, c): RgV_zm_mul(A,c)); extratop = ZM_sub(extratop, ZM_zm_mul(B, c)); } extramat = shallowconcat(extratop, vconcat(dep, H)); Cnew = shallowconcat(extraC, vecslice(C, col-lH+1, co)); if (DEBUGLEVEL>5) err_printf(" 1st phase done\n"); permpro = ZM_rowrankprofile(extramat, &nlze); extramat = rowpermute(extramat, permpro); *ptB = rowpermute(B, permpro); permpro = vecsmallpermute(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); return gc_all(av, 4, &H, ptC, ptdep, ptB); } /* zero aj = Aij (!= 0) using ak = Aik (maybe 0), via linear combination of * A[j] and A[k] of determinant 1. If U != NULL, likewise update its columns */ static void ZC_elem(GEN aj, GEN ak, GEN A, GEN U, long j, long k) { GEN p1,u,v,d; if (!signe(ak)) { swap(gel(A,j), gel(A,k)); if (U) swap(gel(U,j), gel(U,k)); return; } d = bezout(aj,ak,&u,&v); /* frequent special case (u,v) = (1,0) or (0,1) */ if (!signe(u)) { /* ak | aj */ p1 = diviiexact(aj,ak); togglesign(p1); ZC_lincomb1_inplace(gel(A,j), gel(A,k), p1); if (U) ZC_lincomb1_inplace(gel(U,j), gel(U,k), p1); return; } if (!signe(v)) { /* aj | ak */ p1 = diviiexact(ak,aj); togglesign(p1); ZC_lincomb1_inplace(gel(A,k), gel(A,j), p1); swap(gel(A,j), gel(A,k)); if (U) { ZC_lincomb1_inplace(gel(U,k), gel(U,j), p1); swap(gel(U,j), gel(U,k)); } return; } if (!is_pm1(d)) { aj = diviiexact(aj, d); ak = diviiexact(ak, d); } p1 = gel(A,k); aj = negi(aj); /* NOT togglesign */ gel(A,k) = ZC_lincomb(u,v, gel(A,j),p1); gel(A,j) = ZC_lincomb(aj,ak, p1,gel(A,j)); if (U) { p1 = gel(U,k); gel(U,k) = ZC_lincomb(u,v, gel(U,j),p1); gel(U,j) = ZC_lincomb(aj,ak, p1,gel(U,j)); } } INLINE int is_RgX(GEN a, long v) { return typ(a) == t_POL && varn(a)==v; } /* set u,v such that au + bv = gcd(a,b), divide a,b by the gcd */ static GEN gbezout_step(GEN *pa, GEN *pb, GEN *pu, GEN *pv, long vx) { GEN a = *pa, b = *pb, d, l; if (gequal0(a)) { *pa = gen_0; *pu = gen_0; *pb = gen_1; *pv = gen_1; return b; } a = is_RgX(a,vx)? RgX_renormalize(a): scalarpol(a, vx); b = is_RgX(b,vx)? RgX_renormalize(b): scalarpol(b, vx); d = RgX_extgcd(a,b, pu,pv); l = pollead(d,vx); d = RgX_Rg_div(d,l); *pu = RgX_Rg_div(*pu,l); *pv = RgX_Rg_div(*pv,l); if (degpol(d)) { a = RgX_div(a, d); b = RgX_div(b, d); } else if (typ(gel(d,2)) == t_REAL && lg(gel(d,2)) <= 3) #if 1 { /* possible accuracy problem */ GEN D = RgX_gcd_simple(a,b); if (degpol(D)) { D = RgX_normalize(D); a = RgX_div(a, D); b = RgX_div(b, D); d = RgX_extgcd(a,b, pu,pv); /* retry now */ d = RgX_mul(d, D); } } #else { /* less stable */ d = RgX_extgcd_simple(a,b, pu,pv); if (degpol(d)) { a = RgX_div(a, d); b = RgX_div(b, d); } } #endif *pa = a; *pb = b; return d; } static GEN col_mul(GEN x, GEN c) { if (typ(x) == t_INT) { long s = signe(x); if (!s) return NULL; if (is_pm1(x)) return (s > 0)? c: RgC_neg(c); } return RgC_Rg_mul(c, x); } static void do_zero(GEN x) { long i, lx = lg(x); for (i=1; i (long)BITS_IN_LONG)) { T = normalizepol_lg(T, lg(T)-1); if (!signe(T)) { *pd = gen_1; return T; } d = leading_coeff(T); } if (degpol(T)) T = RgX_Rg_div(T,d); else { d = gel(T,2); T = gen_1; } *pd = d; return T; } /* reduce A[i,j] mod A[i,j0] for j=j0+1... via column operations */ static void RgM_reduce(GEN A, GEN U, long i, long j0, long vx) { long j, lA = lg(A); GEN d, T = normalize_as_RgX(gcoeff(A,i,j0), vx, &d); if (U && !gequal1(d)) gel(U,j0) = RgC_Rg_div(gel(U,j0), d); gcoeff(A,i,j0) = T; for (j=j0+1; j 0. Return Au * in Z^n (v in Z^n not computed), such that Au + Bv = [1, 0, ..., 0] */ GEN hnfmerge_get_1(GEN A, GEN B) { pari_sp av = avma; long j, k, l = lg(A), lb; GEN b, U = cgetg(l + 1, t_MAT), C = cgetg(l + 1, t_VEC); b = gcoeff(B,1,1); lb = lgefint(b); for (j = 1; j < l; j++) { GEN t; long 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; b = lcmii(gcoeff(A,1,1),b); A = FpC_red(ZM_ZC_mul(A,gel(U,1)), b); return gerepileupto(av, FpC_center(A, b, shifti(b,-1))); } /* remove the first r columns */ static void remove_0cols(long r, GEN *pA, GEN *pB, long remove) { GEN A = *pA, B = *pB; long l = lg(A); A += r; A[0] = evaltyp(t_MAT) | _evallg(l-r); if (B && remove == 2) { B += r; B[0] = A[0]; } *pA = A; *pB = B; } /* Inefficient compared to hnfall. 'remove' = throw away lin.dep columns */ static GEN hnf_i(GEN A, int remove) { pari_sp av0 = avma, av; long s, n, m, j, k, li, def, ldef; RgM_dimensions(A, &m, &n); if (!n) return cgetg(1,t_MAT); av = avma; A = RgM_shallowcopy(A); def = n; ldef = (m>n)? m-n: 0; for (li=m; li>ldef; li--) { for (j=def-1; j; j--) { GEN a = gcoeff(A,li,j); if (!signe(a)) continue; /* zero a = Aij using b = Aik */ k = (j==1)? def: j-1; ZC_elem(a,gcoeff(A,li,k), A,NULL, j,k); if (gc_needed(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 (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"ZM_hnf[2]. li=%ld",li); A = gerepilecopy(av, A); } } /* rank A = n - def */ if (remove) { GEN B = NULL; remove_0cols(def, &A, &B, remove); } return gerepileupto(av0, ZM_copy(A)); } GEN ZM_hnf(GEN x) { return lg(x) > 8? ZM_hnfall(x, NULL, 1): hnf_i(x, 1); } /* u*z[1..k] mod p, in place */ static void FpV_Fp_mul_part_ip(GEN z, GEN u, GEN p, long k) { long i; if (is_pm1(u)) { if (signe(u) > 0) { for (i = 1; i <= k; i++) if (signe(gel(z,i))) gel(z,i) = modii(gel(z,i), p); } else { for (i = 1; i <= k; i++) if (signe(gel(z,i))) gel(z,i) = modii(negi(gel(z,i)), p); } } else { for (i = 1; i <= k; i++) if (signe(gel(z,i))) gel(z,i) = Fp_mul(u,gel(z,i), p); } } static void FpV_red_part_ipvec(GEN z, GEN p, long k) { long i; for (i = 1; i <= k; i++) gel(z,i) = modii(gel(z,i), gel(p,i)); } /* return x * U, in echelon form (mod p^m), where (det(U),p) = 1. * If early_abort is set, return NULL as soon as one pivot is 0 (mod p^m) */ GEN ZpM_echelon(GEN x, long early_abort, GEN p, GEN pm) { pari_sp av0 = avma, av; long m, li, co, i, j, k, def, ldef; co = lg(x); if (co == 1) return cgetg(1,t_MAT); li = lgcols(x); av = avma; x = RgM_shallowcopy(x); m = Z_pval(pm, p); ldef = (li > co)? li - co: 0; for (def = co-1,i = li-1; i > ldef; i--) { long vmin = LONG_MAX, kmin = 0; GEN umin = gen_0, pvmin, q; for (k = 1; k <= def; k++) { GEN u = gcoeff(x,i,k); long v; if (!signe(u)) continue; v = Z_pvalrem(u, p, &u); if (v >= m) gcoeff(x,i,k) = gen_0; else if (v < vmin) { vmin = v; kmin = k; umin = u; if (!vmin) break; } } if (!kmin) { if (early_abort) return NULL; gcoeff(x,i,def) = gen_0; ldef--; if (ldef < 0) ldef = 0; continue; } if (kmin != def) swap(gel(x,def), gel(x,kmin)); q = vmin? powiu(p, m-vmin): pm; /* pivot has valuation vmin */ umin = modii(umin, q); if (!equali1(umin)) FpV_Fp_mul_part_ip(gel(x,def), Fp_inv(umin,q), pm, i-1); gcoeff(x, i, def) = pvmin = powiu(p, vmin); for (j = def-1; j; j--) { /* zero x[i, 1..def-1] using x[i,def] = pvmin */ GEN t, a = gcoeff(x,i,j) = modii(gcoeff(x,i,j), pm); if (!signe(a)) continue; t = diviiexact(a, pvmin); togglesign(t); ZC_lincomb1_inplace(gel(x,j), gel(x,def), t); if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"ZpM_echelon. i=%ld",i); x = gerepilecopy(av, x); pvmin = gcoeff(x,i,def); } } def--; } if (co > li) { x += co - li; x[0] = evaltyp(t_MAT) | _evallg(li); } return gerepilecopy(av0, x); } GEN zlm_echelon(GEN x, long early_abort, ulong p, ulong pm) { pari_sp av0 = avma; long li, co, i, j, k, def, ldef; ulong m; co = lg(x); if (co == 1) return cgetg(1,t_MAT); li = lgcols(x); x = Flm_copy(x); m = u_lval(pm, p); ldef = (li > co)? li - co: 0; for (def = co-1,i = li-1; i > ldef; i--) { long vmin = LONG_MAX, kmin = 0; ulong umin = 0, pvmin, q; for (k = 1; k <= def; k++) { ulong u = ucoeff(x,i,k); long v; if (!u) continue; v = u_lvalrem(u, p, &u); if (v >= (long) m) ucoeff(x,i,k) = 0; else if (v < vmin) { vmin = v; kmin = k; umin = u; if (!vmin) break; } } if (!kmin) { if (early_abort) return NULL; ucoeff(x,i,def) = 0; ldef--; if (ldef < 0) ldef = 0; continue; } if (kmin != def) swap(gel(x,def), gel(x,kmin)); q = vmin? upowuu(p, m-vmin): pm; /* pivot has valuation vmin */ umin %= q; if (umin != 1) Flv_Fl_mul_part_inplace(gel(x,def), Fl_inv(umin,q), pm, i-1); ucoeff(x, i, def) = pvmin = upowuu(p, vmin); for (j = def-1; j; j--) { /* zero x[i, 1..def-1] using x[i,def] = pvmin */ ulong t, a = ucoeff(x,i,j); if (!a) continue; t = Fl_neg(a / pvmin, q); Flc_lincomb1_inplace(gel(x,j), gel(x,def), t, pm); } def--; } if (co > li) { x += co - li; x[0] = evaltyp(t_MAT) | _evallg(li); } return gerepilecopy(av0, x); } static int ZV_allequal(GEN v) { long i, l = lg(v); if (l > 1) { GEN x = gel(v,1); for (i = 2; i < l; i++) if (!equalii(x,gel(v,i))) return 0; } return 1; } /* compute optimal D for hnfmod: x upper triangular */ static GEN optimal_D(GEN x, GEN D) { long i, n = nbrows(x); GEN C = shallowcopy(D); gel(C,1) = gcoeff(x,1,1); for (i = 2; i < n; i++) { GEN c = mulii(gel(C,i-1), gcoeff(x,i,i)); if (signe(c) < 0) togglesign(c); if (cmpii(c, gel(D,i)) >= 0) break; gel(C,i) = c; } return C; } /* D = multiple of det x (usually detint(x)) or vector of positive moduli * (compute hnf(x | D)) * flag & hnf_MODID: reduce mod D * matid [ otherwise as above ]. * flag & hnf_PART: don't reduce once diagonal is known * flag & hnf_CENTER: centermod HNF (2|x[i,j]| <] x[i,i]) */ GEN ZM_hnfmodall_i(GEN x, GEN D, long flag) { pari_sp av; const long center = (flag & hnf_CENTER); long moddiag, modsame, nli, li, co, i, j, k, def, ldef; GEN u, LDM; co = lg(x); if (co == 1) { if (typ(D) == t_INT || lg(D) == 1) return cgetg(1,t_MAT); x = diagonal_shallow(D); /* handle flags properly */ co = lg(x); } li = lgcols(x); if (li == 1) { if (typ(D) != t_INT && lg(D) != li) pari_err_DIM("ZM_hnfmod"); return cgetg(1,t_MAT); } nli = li - 1; modsame = typ(D)==t_INT; if (!modsame) { if (lg(D) != li) pari_err_DIM("ZM_hnfmod"); if (ZV_allequal(D)) { modsame = 1; D = gel(D,1); } } moddiag = (flag & hnf_MODID) || !modsame; /* modsame: triangularize mod fixed d*Id; * moddiag: modulo diagonal matrix, else modulo multiple of determinant */ if (modsame) { LDM = const_vecsmall(nli, 2*lgefint(D)-2); D = const_vec(nli,D); } else { LDM = cgetg(li, t_VECSMALL); for (i=1; i co) { ldef = li - co; if (!moddiag) pari_err_DOMAIN("ZM_hnfmod","nb lines",">", strtoGENstr("nb columns"), x); } for (def = co-1,i = nli; i > ldef; i--,def--) { GEN d = gel(D,i); long add_N = modsame; for (j = 1; j < def; j++) { GEN p1, p2, b, a = gcoeff(x,i,j) = remii(gcoeff(x,i,j), d); if (!signe(a)) continue; k = j+1; b = gcoeff(x,i,k) = remii(gcoeff(x,i,k), d); if (!signe(b)) { swap(gel(x,j), gel(x,k)); continue; } if (add_N) { /* ensure the moving pivot on row i divides d from now on */ add_N = 0; if (!equali1(a)) { /* x[j] *= u; after this, a = x[i,j] | d */ GEN u = Fp_invgen(a, d, &a); long t; p1 = gel(x,j); for (t = 1; t < i; t++) gel(p1,t) = mulii(gel(p1,t), u); FpV_red_part_ipvec(p1, D, i-1); gel(p1,i) = a; if (2*lg(a) < lg(b)) { /* reduce x[i,k] mod x[i,j]: helps ZC_elem */ GEN r, q = dvmdii(b, a, &r); togglesign(q); ZC_lincomb1_inplace_i(gel(x,k), gel(x,j), q, i-1); FpV_red_part_ipvec(gel(x,k), D, i-1); gcoeff(x,i,k) = b = r; } } } ZC_elem(a,b, x, NULL, j,k); p1 = gel(x,j); p2 = gel(x,k); /* prevent coeffs explosion */ for (k = 1; k < i; k++) { if (lgefint(gel(p1,k)) > LDM[k]) gel(p1,k) = remii(gel(p1,k),gel(D,k)); if (lgefint(gel(p2,k)) > LDM[k]) gel(p2,k) = remii(gel(p2,k),gel(D,k)); } } if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"ZM_hnfmod[1]. i=%ld",i); x = gerepilecopy(av, x); } if (moddiag && !signe(gcoeff(x,i,def))) { /* missing pivot on line i, insert column */ GEN a = cgetg(co + 1, t_MAT); for (k = 1; k <= def; k++) gel(a,k) = gel(x,k); gel(a,k++) = Rg_col_ei(gel(D,i), nli, i); for ( ; k <= co; k++) gel(a,k) = gel(x,k-1); ldef--; if (ldef < 0) ldef = 0; co++; def++; x = a; } } if (co < li) { /* implies moddiag, add missing diag(D) components */ GEN a = cgetg(li+1, t_MAT); for (k = 1; k <= li-co; k++) gel(a,k) = Rg_col_ei(gel(D,k), nli, k); for (i = 1; i < co; i++) gel(a,k-1+i) = gel(x,i); gel(a,li) = zerocol(nli); x = a; } else { x += co - li; x[0] = evaltyp(t_MAT) | _evallg(li); /* kill 0 columns */ if (moddiag) x = shallowconcat(x, zerocol(nli)); } if (moddiag) { /* x[li]: extra column, an accumulator discarded at the end */ GEN D2; gcoeff(x,1,1) = gcdii(gcoeff(x,1,1), gel(D,1)); D2 = optimal_D(x,D); /* add up missing diag(D) components */ for (i = nli; i > 0; i--) { gcoeff(x, i, li) = gel(D,i); for (j = i; j > 0; j--) { GEN a = gcoeff(x, j, li); if (!signe(a)) continue; ZC_elem(a, gcoeff(x,j,j), x, NULL, li,j); FpV_red_part_ipvec(gel(x,li), D, j-1); FpV_red_part_ipvec(gel(x,j), D, j-1); } if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"ZM_hnfmod[2]. i=%ld", i); gerepileall(av, 2, &x, &D2); } } D = D2; } else { GEN b = gel(D,1); for (i = nli; 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); } D = optimal_D(x,D); } x[0] = evaltyp(t_MAT) | _evallg(li); /* kill 0 columns, discard accumulator */ if (flag & hnf_PART) return x; for (i = nli; i > 0; i--) { GEN diag = gcoeff(x,i,i); if (signe(diag) < 0) { gel(x,i) = ZC_neg(gel(x,i)); diag = gcoeff(x,i,i); } if (i != nli) for (j = 1; j < i; j++) gcoeff(x,j,i) = remii(gcoeff(x,j,i), gel(D,j)); for (j = i+1; j < li; j++) { GEN b = gcoeff(x,i,j) = remii(gcoeff(x,i,j), gel(D,i)); GEN r, q = truedvmdii(b, diag, &r); /* ensure -diag/2 <= r < diag/2 */ if (center && signe(r) && abscmpii(shifti(r,1),diag) >= 0) { r = subii(r,diag); q = addiu(q,1); } if (!signe(q)) continue; togglesign(q); ZC_lincomb1_inplace_i(gel(x,j), gel(x,i), q, i-1); gcoeff(x,i,j) = r; } if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"ZM_hnfmod[3]. i=%ld", i); gerepileall(av, 2, &x, &D); } } return x; } GEN ZM_hnfmodall(GEN x, GEN dm, long flag) { pari_sp av = avma; return gerepilecopy(av, ZM_hnfmodall_i(x, dm, flag)); } GEN ZM_hnfmod(GEN x, GEN d) { return ZM_hnfmodall(x,d,0); } GEN ZM_hnfmodid(GEN x, GEN d) { return ZM_hnfmodall(x,d,hnf_MODID); } /* return the column echelon form of x with 1's as pivots, * P contains the row indices containing the pivots in increasing order */ static GEN FpM_echelon(GEN x, GEN *pP, GEN p) { pari_sp av; long iP, li, co, i, j, k, def, ldef; GEN P; co = lg(x); if (co == 1) { *pP = cgetg(1,t_VECSMALL); return cgetg(1,t_MAT); } li = lgcols(x); iP = 1; *pP = P = cgetg(li, t_VECSMALL); av = avma; x = FpM_red(x, p); ldef = (li > co)? li - co: 0; for (def = co-1,i = li-1; i > ldef; i--) { GEN u = NULL; for (k = def; k; k--) { u = gcoeff(x,i,k); if (signe(u)) break; } if (!k) { if (--ldef < 0) ldef = 0; continue; } P[iP++] = i; if (k != def) swap(gel(x,def), gel(x,k)); if (!equali1(u)) FpV_Fp_mul_part_ip(gel(x,def), Fp_inv(u,p), p, i-1); gcoeff(x, i, def) = gen_1; for (j = def-1; j; j--) { /* zero x[i, 1..def-1] using x[i,def] = 1*/ GEN xj = gel(x,j), u = gel(xj,i); if (!signe(u)) continue; ZC_lincomb1_inplace(xj, gel(x,def), negi(u)); for (k = 1; k < i; k++) gel(xj,k) = modii(gel(xj,k), p); } if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"FpM_echelon. i=%ld",i); x = gerepilecopy(av, x); } def--; } /* rank = iP - 1 */ setlg(P, iP); vecsmall_sort(P); if (co > iP) x += co - iP; x[0] = evaltyp(t_MAT) | _evallg(iP); return x; } /* given x square of maximal rank with 1 or p on diagonal from hnfmodid * (=> a column containing p has its other entries at 0 ), return the HNF */ static GEN FpM_hnfend(pari_sp av, GEN x, GEN p) { long i, l = lgcols(x); for (i = l-1; i > 0; i--) { GEN diag = gcoeff(x,i,i); long j; if (is_pm1(diag)) for (j = i+1; j < l; j++) { GEN xj = gel(x,j), b = gel(xj,i); long k; if (!signe(b)) continue; ZC_lincomb1_inplace(xj, gel(x,i), negi(b)); for (k=1; k 3) gel(xj,k) = remii(gel(xj,k), p); } else for (j = i+1; j < l; j++) gcoeff(x,i,j) = modii(gcoeff(x,i,j), p); if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"FpM_hnfend. i=%ld",i); x = gerepilecopy(av, x); } } return x; } GEN ZM_hnfmodprime(GEN x, GEN p) { pari_sp av = avma; GEN P, y; long l, lP, i; if (lg(x) == 1) return cgetg(1, t_MAT); l = lgcols(x); x = FpM_echelon(x, &P, p); lP = lg(P); /* rank = lP-1 */ if (lP == l) { set_avma(av); return matid(l-1); } y = scalarmat_shallow(p, l-1); for (i = 1; i < lP; i++) gel(y,P[i]) = gel(x,i); return gerepilecopy(av, FpM_hnfend(av,y,p)); } static GEN allhnfmod(GEN x, GEN dm, int flag) { if (typ(x)!=t_MAT) pari_err_TYPE("allhnfmod",x); RgM_check_ZM(x, "allhnfmod"); if (isintzero(dm)) return ZM_hnf(x); return ZM_hnfmodall(x, dm, flag); } GEN hnfmod(GEN x, GEN d) { if (typ(d) != t_INT) pari_err_TYPE("mathnfmod",d); return allhnfmod(x, d, 0); } GEN hnfmodid(GEN x, GEN d) { switch(typ(d)) { case t_INT: break; case t_VEC: case t_COL: if (RgV_is_ZV(d)) break; default: pari_err_TYPE("mathnfmodid",d); } return allhnfmod(x, d, hnf_MODID); } /* M a ZM in HNF. Normalize with *centered* residues */ GEN ZM_hnfcenter(GEN M) { long i, j, k, N = lg(M)-1; pari_sp av = avma; 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 (gc_needed(av,1)) { if (DEBUGMEM>1) 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_lincomb1z(gel(A,k),gel(A,j),q); if (B) ZC_lincomb1z(gel(B,k),gel(B,j),q); addmulzii(&gel(Lk,j), 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; } /* decide whether to swap */ static int must_swap(long k, GEN lambda, GEN D) { pari_sp av = avma; GEN z = addii(mulii(gel(D,k-2),gel(D,k)), sqri(gcoeff(lambda,k-1,k))); return gc_bool(av, cmpii(z, sqri(gel(D,k-1))) < 0); } GEN ZM_hnflll(GEN A, GEN *ptB, int remove) { pari_sp av = avma; 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) do_swap = 0; else do_swap = must_swap(k,lambda,D); 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 (++k > kmax) kmax = k; } if (gc_needed(av,3)) { GEN b = D-1; if (DEBUGMEM>1) pari_warn(warnmem,"hnflll, kmax = %ld / %ld",kmax,n-1); gerepileall(av, B? 4: 3, &A, &lambda, &b, &B); if (gc_needed(av,1)) paristack_resize(0); /* avoid desperation GC */ D = b+1; } } /* handle trivial case: return negative diag coefficient otherwise */ if (n == 2) (void)findi_normalize(gel(A,1), B,1,lambda); A = reverse_rows(A); if (remove) { long i; for (i = 1; i < n; i++) if (!ZV_equal0(gel(A,i))) break; remove_0cols(i-1, &A, &B, remove); } gerepileall(av, B? 2: 1, &A, &B); if (B) *ptB = B; return A; } GEN hnflll(GEN x) { GEN z = cgetg(3, t_VEC); gel(z,1) = ZM_hnflll(x, &gel(z,2), 1); return z; } /* Variation on HNFLLL: Extended GCD */ static void reduce1(GEN A, GEN B, long k, long j, GEN lambda, GEN D) { GEN q; long i; if (signe(gel(A,j))) q = diviiround(gel(A,k),gel(A,j)); else if (abscmpii(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) = addmulii(gel(A,k), q, gel(A,j)); ZC_lincomb1_inplace(gel(B,k),gel(B,j),q); gel(Lk,j) = addmulii(gel(Lk,j), q, gel(D,j)); for (i=1; i 2) k--; } else { long i; for (i=k-2; i; i--) reduce1(A,B,k,i,lambda,D); k++; } } if (signe(gel(A,n-1)) < 0) { gel(A,n-1) = negi(gel(A,n-1)); ZV_togglesign(gel(B,n-1)); } return mkvec2(gel(A,n-1), B); } GEN ZV_extgcd(GEN A) { pari_sp av = avma; return gerepilecopy(av, ZV_gcdext_i(A)); } /* as ZV_extgcd, transforming the gcd into a t_MAT, for mathnf0 */ static GEN ZV_hnfgcdext(GEN A) { pari_sp av = avma; GEN z; if (lg(A) == 1) retmkvec2(cgetg(1,t_MAT),cgetg(1,t_MAT)); z = ZV_gcdext_i(A); gel(z,1) = mkmat(mkcol(gel(z,1))); return gerepilecopy(av, z); } /* HNF with permutation. */ GEN ZM_hnfperm(GEN A, GEN *ptU, GEN *ptperm) { GEN U, c, l, perm, d, p, q, b; pari_sp av = avma, av1; long r, t, i, j, j1, k, m, n; n = lg(A)-1; if (!n) { if (ptU) *ptU = cgetg(1,t_MAT); if (ptperm) *ptperm = cgetg(1,t_VEC); return cgetg(1, t_MAT); } m = nbrows(A); c = zero_zv(m); l = zero_zv(n); perm = cgetg(m+1, t_VECSMALL); av1 = avma; 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, k=%ld",k); 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 ZM_hnf_knapsack(GEN x) { GEN t, perm, H = ZM_hnfperm(x,NULL,&perm); long i,j, l = lg(H), h = lgcols(H); for (i=1; ili; 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 even if a = 0 */ } if (gc_needed(av,1) && (j & 0x7f) == 0) { if (DEBUGMEM>1) pari_warn(warnmem,"ZM_hnfall[1], li = %ld, j = %ld", li, j); gerepileall(av, 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 (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"ZM_hnfall[2], li = %ld", li); gerepileall(av, 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 (gc_needed(av,1) && (j & 0x7f) == 0) { if (DEBUGMEM>1) pari_warn(warnmem,"ZM_hnfall[3], j = %ld", j); gerepileall(av, B? 2: 1, &A, &B); } } if (DEBUGLEVEL>5) err_printf("\n"); if (remove) remove_0cols(r, &A, &B, remove); if (ptB) *ptB = B; return A; } GEN ZM_hnfall(GEN A, GEN *ptB, long remove) { pari_sp av = avma; A = ZM_hnfall_i(A, ptB, remove); return gc_all(av, ptB? 2: 1, &A, ptB); } 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)t where A and C are integral, A is upper triangular, t t_INT */ GEN hnf_invscale(GEN A, 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++) { /* cf hnf_divscale with B = id, thus b = e_k */ GEN u = cgetg(n+1, t_COL); pari_sp av = avma; gel(c,k) = u; gel(u,n) = k == n? gerepileuptoint(av, diviiexact(t, gcoeff(A,n,n))): gen_0; for (i=n-1; i>0; i--) { av = avma; m = i == k? t: gen_0; 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; } /* C = A^(-1)(tB) where A, B, C are integral, A is upper triangular, t t_INT */ GEN hnf_divscale(GEN A, GEN B, GEN t) { long n = lg(A)-1, i,j,k; GEN m, c = cgetg(n+1,t_MAT); if (!n) return c; for (k=1; k<=n; k++) { GEN u = cgetg(n+1, t_COL), b = gel(B,k); pari_sp av = avma; gel(c,k) = u; m = mulii(gel(b,n),t); gel(u,n) = gerepileuptoint(av, diviiexact(m, gcoeff(A,n,n))); for (i=n-1; i>0; i--) { av = avma; m = mulii(gel(b,i),t); for (j=i+1; j<=n; j++) m = subii(m, mulii(gcoeff(A,i,j),gel(u,j))); gel(u,i) = gerepileuptoint(av, diviiexact(m, gcoeff(A,i,i))); } } return c; } /* A, B integral upper HNF. A^(-1) B integral ? */ int hnfdivide(GEN A, GEN B) { pari_sp av = avma; long n = lg(A)-1, i,j,k; GEN u, b, m, r; if (!n) return 1; if (lg(B)-1 != n) pari_err_DIM("hnfdivide"); u = cgetg(n+1, t_COL); for (k=1; k<=n; k++) { b = gel(B,k); m = gel(b,k); gel(u,k) = dvmdii(m, gcoeff(A,k,k), &r); if (r != gen_0) return gc_long(av, 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) return gc_long(av, 0); gel(u,i) = m; } } return gc_long(av, 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 lg(b)==1? cgetg(1,t_COL):NULL; m = nbrows(A); /* m >= n */ u = cgetg(n+1, t_COL); for (i = n, k = m; k > 0; k--) { pari_sp av2 = avma; long j; GEN t = gel(b,k), Aki = gcoeff(A,k,i); if (typ(t) != t_INT) pari_err_TYPE("hnf_invimage",t); for (j=i+1; j<=n; j++) t = subii(t, mulii(gcoeff(A,k,j),gel(u,j))); if (!signe(Aki)) { if (signe(t)) return gc_NULL(av); set_avma(av2); gel(u,i) = gen_0; continue; } t = dvmdii(t, Aki, &r); if (r != gen_0) return gc_NULL(av); gel(u,i) = gerepileuptoint(av2, t); if (--i == 0) break; } /* If there is a solution, it must be u. Check remaining equations */ for (; k > 0; k--) { pari_sp av2 = avma; long j; GEN t = gel(b,k); if (typ(t) != t_INT) pari_err_TYPE("hnf_invimage",t); for (j=1; j<=n; j++) t = subii(t, mulii(gcoeff(A,k,j),gel(u,j))); if (signe(t)) return gc_NULL(av); set_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) return gc_NULL(av); gel(C,i) = c; } return C; } /***************************************************************/ /** **/ /** SMITH NORMAL FORM REDUCTION **/ /** **/ /***************************************************************/ static GEN trivsmith(long all) { GEN z; if (!all) return cgetg(1,t_VEC); z=cgetg(4,t_VEC); gel(z,1) = cgetg(1,t_MAT); gel(z,2) = cgetg(1,t_MAT); gel(z,3) = cgetg(1,t_MAT); return z; } static void snf_pile1(pari_sp av, GEN *x, GEN *U) { GEN *gptr[2]; int c = 1; gptr[0]=x; if (*U) gptr[c++] = U; gerepilemany(av,gptr,c); } static void snf_pile(pari_sp av, GEN *x, GEN *U, GEN *V) { GEN *gptr[3]; int c = 1; gptr[0]=x; if (*U) gptr[c++] = U; if (*V) gptr[c++] = V; gerepilemany(av,gptr,c); } static GEN bezout_step(GEN *pa, GEN *pb, GEN *pu, GEN *pv) { GEN a = *pa, b = *pb, d; if (absequalii(a,b)) { long sa = signe(a), sb = signe(b); *pv = gen_0; if (sb == sa) { *pa = *pb = gen_1; if (sa > 0) {*pu=gen_1; return a;} else {*pu=gen_m1; return absi(a);} } if (sa > 0) { *pa = *pu = gen_1; *pb = gen_m1; return a; } *pa = *pu = gen_m1; *pb = gen_1; return b; } d = bezout(a,b, pu,pv); *pa = diviiexact(a, d); *pb = diviiexact(b, d); return d; } static int negcmpii(void *E, GEN x, GEN y) { (void)E; return -cmpii(x,y); } /* x square of maximal rank; does b = x[i,i] divide all entries in * x[1..i-1, 1..i-1] ? If so, return 0; else 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 (is_pm1(b)) return 0; for (k = 1; k < i; k++) for (j = 1; j < i; j++) if (!dvdii(gcoeff(x,k,j),b)) return k; return 0; } static void ZM_redpart(GEN x, GEN p, long I) { long l = lgefint(p), i, j; for (i = 1; i <= I; i++) for (j = 1; j <= I; j++) { GEN c = gcoeff(x,i,j); if (lgefint(c) > l) gcoeff(x,i,j) = remii(c, p); } } static void ZMrow_divexact_inplace(GEN M, long i, GEN c) { long j, l = lg(M); for (j = 1; j < l; j++) gcoeff(M,i,j) = diviiexact(gcoeff(M,i,j), c); } /* Return the SNF D of matrix X. If ptU/ptV non-NULL set them to U/V * to that D = UXV */ GEN ZM_snfall_i(GEN x, GEN *ptU, GEN *ptV, long flag) { pari_sp av0 = avma, av; const long return_vec = flag & 1; long i, j, k, m0, m, n0, n; GEN u, v, U, V, V0, mdet, A = NULL, perm = NULL; n0 = n = lg(x)-1; if (!n) { if (ptU) *ptU = cgetg(1,t_MAT); if (ptV) *ptV = cgetg(1,t_MAT); return cgetg(1, return_vec? t_VEC: t_MAT); } m0 = m = nbrows(x); U = V = V0 = NULL; /* U = TRANSPOSE of row transform matrix [act on columns]*/ if (m == n && ZM_ishnf(x)) { mdet = ZM_det_triangular(x); /* != 0 */ if (ptV) *ptV = matid(n); } else { mdet = ZM_detmult(x); if (!signe(mdet)) x = ZM_hnfperm(x, ptV, ptU? &perm: NULL); else { /* m <= n */ if (!ptV) x = ZM_hnfmod(x,mdet); else if (m == n) { GEN H = ZM_hnfmod(x,mdet); *ptV = ZM_gauss(x,H); x = H; } else x = ZM_hnfperm(x, ptV, ptU? &perm: NULL); mdet = ZM_det_triangular(x); /* > 0 */ } n = lg(x)-1; /* n independent columns */ if (ptV) { V = *ptV; if (n != n0) { V0 = vecslice(V, 1, n0 - n); /* kernel */ V = vecslice(V, n0-n+1, n0); } } if (!signe(mdet)) { if (n) { x = ZM_snfall_i(shallowtrans(x), ptV, ptU, return_vec); /* swap V,U */ if (!return_vec && n != m) x = shallowtrans(x); if (ptV) V = ZM_mul(V, shallowtrans(*ptV)); if (ptU) U = *ptU; /* TRANSPOSE */ } else /* 0 matrix */ { x = cgetg(1,t_MAT); if (ptV) V = cgetg(1, t_MAT); if (ptU) U = matid(m); } goto THEEND; } } if (ptV || ptU) U = matid(n); /* we will compute V in terms of U */ if (DEBUGLEVEL>7) err_printf("starting SNF loop"); /* square, maximal rank n */ A = x; x = shallowcopy(x); av = avma; 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,NULL, j,i); if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"[1]: ZM_snfall i = %ld", i); snf_pile1(av, &x,&U); } } 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 (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"[2]: ZM_snfall, i = %ld", i); snf_pile1(av, &x,&U); } 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)); } ZM_redpart(x, mdet, i); if (U && (flag & 2)) ZM_redpart(U, mdet, n); if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"[3]: ZM_snfall"); snf_pile1(av, &x,&U); } } } if (DEBUGLEVEL>7) err_printf("\n"); for (k = n; k; k--) { GEN d = gcdii(gcoeff(x,k,k), mdet); gcoeff(x,k,k) = d; if (!is_pm1(d)) mdet = diviiexact(mdet,d); } THEEND: if (U) U = shallowtrans(U); if (ptV && A) { /* U A V = D => D^(-1) U A = V^(-1) */ long l = lg(x); GEN W = ZM_mul(U, A); for (i = 1; i < l; i++) { GEN c = gcoeff(x,i,i); if (is_pm1(c)) break; /* only 1 from now on */ ZMrow_divexact_inplace(W, i, c); } if (flag & 2) { W = FpM_red(W, gcoeff(x,1,1)); W = matinvmod(W, gcoeff(x,1,1)); } else W = ZM_inv(W, NULL); V = V? ZM_mul(V, W): W; } 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) { /* add kernel */ if (!return_vec) x = shallowconcat(zeromat(m,n0-n), x); if (ptV) V = shallowconcat(V0, V); } if (perm && U) 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) { return ZM_snfall_i(x, NULL,NULL, 1); } GEN smithall(GEN x) { GEN z = cgetg(4, t_VEC); gel(z,3) = ZM_snfall_i(x, (GEN*)(z+1),(GEN*)(z+2), 0); return z; } GEN ZV_snfclean(GEN d) { long c, l = lg(d); for (c = 1; c < l; c++) { GEN t = gel(d,c); if (is_pm1(t)) break; } return c == l? d: vec_shorten(d, c-1); } 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) - gprecision(r)) ) return k; } return 0; } /* Hermite Normal Form, with base change matrix if ptB != NULL. * If 'remove' = 1, remove 0 columns (do NOT update *ptB accordingly) * If 'remove' = 2, remove 0 columns and update *ptB accordingly */ GEN RgM_hnfall(GEN A, GEN *pB, long remove) { pari_sp av; long li, j, k, m, n, def, ldef; GEN B; long vx = gvar(A); n = lg(A)-1; if (vx==NO_VARIABLE || !n) { RgM_check_ZM(A, "mathnf0"); return ZM_hnfall(A, pB, remove); } m = nbrows(A); av = avma; A = RgM_shallowcopy(A); B = pB? matid(n): NULL; def = n; ldef = (m>n)? m-n: 0; for (li=m; li>ldef; li--) { GEN d, T; for (j=def-1; j; j--) { GEN a = gcoeff(A,li,j); if (gequal0(a)) continue; k = (j==1)? def: j-1; RgC_elem(a,gcoeff(A,li,k), A,B, j,k, li, vx); } T = normalize_as_RgX(gcoeff(A,li,def), vx, &d); if (gequal0(T)) { if (ldef) ldef--; } else { if (!gequal1(d)) { gel(A,def) = RgC_Rg_div(gel(A,def), d); if (B) gel(B, def) = RgC_Rg_div(gel(B, def), d); } RgM_reduce(A, B, li, def, vx); def--; } if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"ghnfall"); gerepileall(av, B? 2: 1, &A, &B); } } /* rank A = n - def */ if (remove) remove_0cols(def, &A, &B, remove); gerepileall(av, B? 2: 1, &A, &B); if (B) *pB = B; return A; } static GEN RgXM_snf(GEN x,long all) { pari_sp av; long i, j, k, n; GEN z, u, v, U, V; long vx = gvar(x); n = lg(x)-1; if (!n) return trivsmith(all); if (vx==NO_VARIABLE) pari_err_TYPE("RgXM_snf",x); if (lgcols(x) != n+1) pari_err_DIM("gsmithall"); av = avma; 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 (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"gsmithall"); gerepileall(av, all? 3: 1, &x, &U, &V); } } } for (k=1; k<=n; k++) { GEN d, T = normalize_as_RgX(gcoeff(x,k,k), vx, &d); if (gequal0(T)) continue; if (all && !gequal1(d)) gel(V,k) = RgC_Rg_div(gel(V,k), d); gcoeff(x,k,k) = T; } z = all? mkvec3(shallowtrans(U), V, x): RgM_diagonal_shallow(x); return gerepilecopy(av, z); } GEN matsnf0(GEN x,long flag) { pari_sp av = avma; if (flag > 7) pari_err_FLAG("matsnf"); if (typ(x) == t_VEC && flag & 4) return smithclean(x); if (typ(x)!=t_MAT) pari_err_TYPE("matsnf",x); if (RgM_is_ZM(x)) x = flag&1 ? smithall(x): smith(x); else x = RgXM_snf(x, flag&1); if (flag & 4) x = gerepileupto(av, smithclean(x)); return x; } GEN gsmith(GEN x) { return RgXM_snf(x,0); } GEN gsmithall(GEN x) { return RgXM_snf(x,1); } /* H is a relation matrix, either in HNF or a t_VEC (diagonal HNF) */ static GEN snf_group(GEN H, GEN D, GEN *newU, GEN *newUi) { 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 && l > 1) { /* UHV=D -> U^-1 = (HV)D^-1 -> U^-1 = H(VD^-1 mod 1) mod H */ /* Ui = ZM_inv(U, NULL); setlg(Ui, l); */ GEN V = *newUi, Ui; int Hvec = (typ(H) == t_VEC); for (i = 1; i < l; i++) gel(V,i) = FpC_red(gel(V,i), gel(D,i)); if (!Hvec) { if (ZM_isdiagonal(H)) { H = RgM_diagonal_shallow(H); Hvec = 1; } } Ui = Hvec? ZM_diag_mul(H, V): ZM_mul(H, V); for (i = 1; i < l; i++) gel(Ui,i) = ZC_Z_divexact(gel(Ui,i), gel(D,i)); *newUi = Hvec? ZM_ZV_mod(Ui, H): ZM_hnfrem(Ui, H); } return D; } /* 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 + 2); return snf_group(H, D, newU, newUi); } /* D a ZV: SNF for matdiagonal(D). Faster because we only ensure elementary * divisors condition: d[n] | ... | d[1] and need not convert D to matrix form*/ GEN ZV_snfall(GEN D, GEN *pU, GEN *pV) { pari_sp av = avma; long j, n = lg(D)-1; GEN U = pU? matid(n): NULL; GEN V = pV? matid(n): NULL; GEN p; D = leafcopy(D); for (j = n; j > 0; j--) { GEN b = gel(D,j); if (signe(b) < 0) { gel(D,j) = negi(b); if (V) ZV_togglesign(gel(V,j)); } } /* entries are nonnegative integers */ p = gen_indexsort(D, NULL, &negcmpii); D = vecpermute(D, p); if (U) U = vecpermute(U, p); if (V) V = vecpermute(V, p); /* entries are sorted by decreasing value */ for (j = n; j > 0; j--) { GEN b = gel(D,j); long i; for (i = j-1; i > 0; i--) { /* invariant: a >= b. If au+bv = d is a Bezout relation, A=a/d and B=b/d * we have [B,-A;u,v]*diag(a,b)*[1-u*A,1; -u*A,1]] = diag(Ab, d) */ GEN a = gel(D,i), u,v, d = bezout(a,b, &u,&v), A, Wi, Wj; if (equalii(d,b)) continue; A = diviiexact(a,d); if (V) { GEN t = mulii(u,A); Wi = ZC_lincomb(subui(1,t), negi(t), gel(V,i), gel(V,j)); Wj = ZC_add(gel(V,i), gel(V,j)); gel(V,i) = Wi; gel(V,j) = Wj; } if (U) { GEN B = diviiexact(b,d); Wi = ZC_lincomb(B, negi(A), gel(U,i), gel(U,j)); Wj = ZC_lincomb(u, v, gel(U,i), gel(U,j)); gel(U,i) = Wi; gel(U,j) = Wj; } gel(D,i) = mulii(A,b); /* lcm(a,b) */ gel(D,j) = d; /* gcd(a,b) */ b = gel(D,j); if (equali1(b)) break; } } snf_pile(av, &D,&U,&V); if (U) *pU = shallowtrans(U); if (V) *pV = V; return D; } GEN ZV_snf_group(GEN d, GEN *newU, GEN *newUi) { GEN D = ZV_snfall(d, newU, newUi); return snf_group(d, D, newU, newUi); } /* D a vector of elementary divisors. Truncate (setlg) to leave out trivial * entries (= 1) */ void ZV_snf_trunc(GEN D) { long i, l = lg(D); for (i = 1; i < l; i++) if (is_pm1(gel(D,i))) { setlg(D,i); break; } } long zv_snf_rank(GEN D, ulong p) { long i, l = lg(D); if (!p) return l - 1; for (i = 1; i < l; i++) if (D[i] % p) break; return i - 1; } long ZV_snf_rank_u(GEN D, ulong p) { long i, l = lg(D); while (l > 1 && D[l-1] == 1) l--; if (!p) return l - 1; if (p == 2) { for (i = 1; i < l; i++) if (mpodd(gel(D,i))) break; } else if (!(p & (p-1))) { /* power of 2 */ long n = vals(p); for (i = 1; i < l; i++) if (umodi2n(gel(D,i), n)) break; } else { for (i = 1; i < l; i++) if (umodiu(gel(D,i), p)) break; } return i - 1; } long ZV_snf_rank(GEN D, GEN p) { long i, l = lg(D); if (lgefint(p) == 3) return ZV_snf_rank_u(D, p[2]); while (l > 1 && equali1(gel(D, l-1))) l--; if (!signe(p)) return l - 1; for (i = 1; i < l; i++) if (!dvdii(gel(D,i), p)) break; return i - 1; } long snfrank(GEN D, GEN p) { long i, l; if (typ(D) != t_VEC) pari_err_TYPE("snfrank", D); if (!p) p = gen_0; l = lg(D); if (l == 4 && typ(gel(D,3)) == t_MAT) { /* from matsnf(,1) */ pari_sp av = avma; long z; GEN v; D = gel(D,3); l = lg(D); if (l == 1) return 0; z = lgcols(D) - l; /* missing columns of 0s */ if (z < 0) pari_err_TYPE("snfrank", D); v = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(v, i) = gcoeff(D, i + z, i); return gc_long(av, z + snfrank(v, p)); } switch(typ(p)) { case t_INT: if (RgV_is_ZV(D)) return ZV_snf_rank(D, p); if (!signe(p)) break; /* allow p = 0 */ pari_err_TYPE("snfrank", D); case t_POL: break; default: pari_err_TYPE("snfrank", p); } while (l > 1 && gequal1(gel(D, l-1))) l--; if (gequal0(p)) return l - 1; for (i = 1; i < l; i++) if (!gdvd(gel(D,i), p)) break; return i - 1; } pari-2.17.2/src/basemath/F2v.c0000644000175000017500000005772214760123736014366 0ustar billbill/* Copyright (C) 2012-2019 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_mat /***********************************************************************/ /** **/ /** F2v **/ /** **/ /***********************************************************************/ /* F2v objects are defined as follows: An F2v is a t_VECSMALL: v[0] = codeword v[1] = number of components 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. */ int F2v_equal0(GEN V) { long l = lg(V); while (--l > 1) if (V[l]) return 0; return 1; } GEN F2c_to_ZC(GEN x) { long l = x[1]+1, lx = lg(x); GEN z = cgetg(l, t_COL); long i, j, k; for (i=2, k=1; i>j)&1UL; return z; } GEN F2m_to_ZM(GEN x) { pari_APPLY_same(F2c_to_ZC(gel(x,i))) } GEN F2m_to_mod(GEN x) { pari_APPLY_same(F2c_to_mod(gel(x,i))) } GEN F2m_to_Flm(GEN x) { pari_APPLY_same(F2v_to_Flv(gel(x,i))) } GEN RgV_F2v_extract_shallow(GEN V, GEN x) { long n = F2v_hamming(x), m = 1; long l = x[1]+1, lx = lg(x); GEN W = cgetg(n+1, t_VEC); long i,j,k; for (i=2, k=1; i>j)&1UL) gel(W, m++) = gel(V,k); return W; } GEN ZV_to_F2v(GEN x) { long i, j, k, l = lg(x)-1; GEN z = cgetg(nbits2lg(l), t_VECSMALL); z[1] = l; for(i=1,k=1,j=BITS_IN_LONG; i<=l; i++,j++) { if (j==BITS_IN_LONG) { j=0; z[++k]=0; } if (mpodd(gel(x,i))) z[k] |= 1UL<> 32; #endif c ^= c >> 16; c ^= c >> 8; c ^= c >> 4; c ^= c >> 2; c ^= c >> 1; return c & 1; } ulong F2v_hamming(GEN H) { long i, n=0, l=lg(H); for (i=2; im) { if (deplin) { GEN v = zero_F2v(n); for (i=1; im) { r++; d[k] = 0; } else { F2v_clear(c,j); d[k] = j; for (i=k+1; i<=n; i++) { GEN xi = gel(x,i); if (F2v_coeff(xi,j)) F2v_add_inplace(xi, xk); } } } *rr = r; return gc_const((pari_sp)d, d); } long F2m_rank(GEN x) { pari_sp av = avma; long r; (void)F2m_gauss_pivot(F2m_copy(x),&r); return gc_long(av, lg(x)-1 - r); } static GEN F2m_inv_upper_1_ind(GEN A, long index) { pari_sp av = avma; long n = lg(A)-1, i = index, j; GEN u = const_vecsmall(n, 0); u[i] = 1; for (i--; i>0; i--) { ulong m = F2m_coeff(A,i,i+1) & uel(u,i+1); /* j = i+1 */ for (j=i+2; j<=n; j++) m ^= F2m_coeff(A,i,j) & uel(u,j); u[i] = m & 1; } return gerepileuptoleaf(av, Flv_to_F2v(u)); } static GEN F2m_inv_upper_1(GEN A) { long i, l; GEN B = cgetg_copy(A, &l); for (i = 1; i < l; i++) gel(B,i) = F2m_inv_upper_1_ind(A, i); return B; } static GEN F2_get_col(GEN b, GEN d, long li, long aco) { long i, l = nbits2lg(aco); GEN u = cgetg(l, t_VECSMALL); u[1] = aco; for (i = 1; i <= li; i++) if (d[i]) /* d[i] can still be 0 if li > aco */ { if (F2v_coeff(b, i)) F2v_set(u, d[i]); else F2v_clear(u, d[i]); } return u; } /* destroy a, b */ GEN F2m_gauss_sp(GEN a, GEN b) { long i, j, k, l, li, bco, aco = lg(a)-1; GEN u, d; if (!aco) return cgetg(1,t_MAT); li = gel(a,1)[1]; d = zero_Flv(li); bco = lg(b)-1; for (i=1; i<=aco; i++) { GEN ai = vecsmall_copy(gel(a,i)); if (!d[i] && F2v_coeff(ai, i)) k = i; else for (k = 1; k <= li; k++) if (!d[k] && F2v_coeff(ai,k)) break; /* found a pivot on row k */ if (k > li) return NULL; d[k] = i; /* Clear k-th row but column-wise instead of line-wise */ /* a_ij -= a_i1*a1j/a_11 line-wise grouping: L_j -= a_1j/a_11*L_1 column-wise: C_i -= a_i1/a_11*C_1 */ F2v_clear(ai,k); for (l=1; l<=aco; l++) { GEN al = gel(a,l); if (F2v_coeff(al,k)) F2v_add_inplace(al,ai); } for (l=1; l<=bco; l++) { GEN bl = gel(b,l); if (F2v_coeff(bl,k)) F2v_add_inplace(bl,ai); } } u = cgetg(bco+1,t_MAT); for (j = 1; j <= bco; j++) gel(u,j) = F2_get_col(gel(b,j), d, li, aco); return u; } GEN F2m_gauss(GEN a, GEN b) { pari_sp av = avma; if (lg(a) == 1) return cgetg(1,t_MAT); return gerepileupto(av, F2m_gauss_sp(F2m_copy(a), F2m_copy(b))); } GEN F2m_F2c_gauss(GEN a, GEN b) { pari_sp av = avma; GEN z = F2m_gauss(a, mkmat(b)); if (!z) return gc_NULL(av); if (lg(z) == 1) { set_avma(av); return cgetg(1,t_VECSMALL); } return gerepileuptoleaf(av, gel(z,1)); } GEN F2m_inv(GEN a) { pari_sp av = avma; if (lg(a) == 1) return cgetg(1,t_MAT); return gerepileupto(av, F2m_gauss_sp(F2m_copy(a), matid_F2m(gel(a,1)[1]))); } GEN F2m_invimage_i(GEN A, GEN B) { GEN d, x, X, Y; long i, j, nY, nA = lg(A)-1, nB = lg(B)-1; x = F2m_ker_sp(shallowconcat(A, B), 0); /* AX = BY, Y in strict upper echelon form with pivots = 1. * We must find T such that Y T = Id_nB then X T = Z. This exists iff * Y has at least nB columns and full rank */ nY = lg(x)-1; if (nY < nB) return NULL; /* implicitly: Y = rowslice(x, nA+1, nA+nB), nB rows */ d = cgetg(nB+1, t_VECSMALL); for (i = nB, j = nY; i >= 1; i--, j--) { for (; j>=1; j--) if (F2m_coeff(x,nA+i,j)) { d[i] = j; break; } /* Y[i,j] */ if (!j) return NULL; } x = vecpermute(x, d); X = F2m_rowslice(x, 1, nA); Y = F2m_rowslice(x, nA+1, nA+nB); return F2m_mul(X, F2m_inv_upper_1(Y)); } GEN F2m_invimage(GEN A, GEN B) { pari_sp av = avma; GEN X = F2m_invimage_i(A,B); if (!X) return gc_NULL(av); return gerepileupto(av, X); } GEN F2m_F2c_invimage(GEN A, GEN y) { pari_sp av = avma; long i, l = lg(A); GEN M, x; if (l==1) return NULL; if (lg(y) != lgcols(A)) pari_err_DIM("F2m_F2c_invimage"); M = cgetg(l+1,t_MAT); for (i=1; i Copyright Jason Papadopoulos 2006 Released under the GNU General Public License v2 or later version. */ /* F2Ms are vector of vecsmall which represents nonzero entries of columns * F2w are vecsmall whoses entries are columns of a n x BIL F2m * F2wB are F2w in the special case where dim = BIL. */ #define BIL BITS_IN_LONG static GEN F2w_transpose_F2m(GEN x) { long i, j, l = lg(x)-1; GEN z = cgetg(BIL+1, t_MAT); for (j = 1; j <= BIL; j++) gel(z,j) = zero_F2v(l); for (i = 1; i <= l; i++) { ulong xi = uel(x,i); for(j = 1; j <= BIL; j++) if (xi&(1UL<<(j-1))) F2v_set(gel(z, j), i); } return z; } static GEN F2wB_mul(GEN a, GEN b) { long i, j; GEN c = cgetg(BIL+1, t_VECSMALL); for (i = 1; i <= BIL; i++) { ulong s = 0, ai = a[i]; for (j = 1; ai; j++, ai>>=1) if (ai & 1) s ^= b[j]; c[i] = s; } return c; } static void precompute_F2w_F2wB(GEN x, GEN c) { ulong z, xk; ulong i, j, k, index; x++; c++; for (j = 0; j < (BIL>>3); j++) { for (i = 0; i < 256; i++) { k = 0; index = i; z = 0; while (index) { xk = x[k]; if (index & 1) z ^= xk; index >>= 1; k++; } c[i] = z; } x += 8; c += 256; } } static void F2w_F2wB_mul_add_inplace(GEN v, GEN x, GEN y) { long i, n = lg(y)-1; ulong word; GEN c = cgetg(1+(BIL<<5), t_VECSMALL); precompute_F2w_F2wB(x, c); c++; for (i = 1; i <= n; i++) { word = v[i]; y[i] ^= c[ 0*256 + ((word>> 0) & 0xff) ] ^ c[ 1*256 + ((word>> 8) & 0xff) ] ^ c[ 2*256 + ((word>>16) & 0xff) ] ^ c[ 3*256 + ((word>>24) & 0xff) ] #ifdef LONG_IS_64BIT ^ c[ 4*256 + ((word>>32) & 0xff) ] ^ c[ 5*256 + ((word>>40) & 0xff) ] ^ c[ 6*256 + ((word>>48) & 0xff) ] ^ c[ 7*256 + ((word>>56) ) ] #endif ; } } /* Return x*y~, which is a F2wB */ static GEN F2w_transmul(GEN x, GEN y) { long i, j, n = lg(x)-1; GEN z = zero_zv(BIL); pari_sp av = avma; GEN c = zero_zv(BIL<<5) + 1; GEN xy = z + 1; for (i = 1; i <= n; i++) { ulong xi = x[i]; ulong yi = y[i]; c[ 0*256 + ( xi & 0xff) ] ^= yi; c[ 1*256 + ((xi >> 8) & 0xff) ] ^= yi; c[ 2*256 + ((xi >> 16) & 0xff) ] ^= yi; c[ 3*256 + ((xi >> 24) & 0xff) ] ^= yi; #ifdef LONG_IS_64BIT c[ 4*256 + ((xi >> 32) & 0xff) ] ^= yi; c[ 5*256 + ((xi >> 40) & 0xff) ] ^= yi; c[ 6*256 + ((xi >> 48) & 0xff) ] ^= yi; c[ 7*256 + ((xi >> 56) ) ] ^= yi; #endif } for(i = 0; i < 8; i++) { ulong a0 = 0, a1 = 0, a2 = 0, a3 = 0; #ifdef LONG_IS_64BIT ulong a4 = 0, a5 = 0, a6 = 0, a7 = 0; #endif for (j = 0; j < 256; j++) { if ((j >> i) & 1) { a0 ^= c[0*256 + j]; a1 ^= c[1*256 + j]; a2 ^= c[2*256 + j]; a3 ^= c[3*256 + j]; #ifdef LONG_IS_64BIT a4 ^= c[4*256 + j]; a5 ^= c[5*256 + j]; a6 ^= c[6*256 + j]; a7 ^= c[7*256 + j]; #endif } } xy[ 0] = a0; xy[ 8] = a1; xy[16] = a2; xy[24] = a3; #ifdef LONG_IS_64BIT xy[32] = a4; xy[40] = a5; xy[48] = a6; xy[56] = a7; #endif xy++; } return gc_const(av, z); } static GEN identity_F2wB(void) { long i; GEN M = cgetg(BIL+1, t_VECSMALL); for (i = 1; i <= BIL; i++) uel(M,i) = 1UL<<(i-1); return M; } static GEN find_nonsingular_sub(GEN t, GEN last_s, GEN *pt_s) { long i, j, dim = 0; ulong mask, row_i, row_j; long last_dim = lg(last_s)-1; GEN s = cgetg(BIL+1, t_VECSMALL); GEN M1 = identity_F2wB(); pari_sp av = avma; GEN cols = cgetg(BIL+1, t_VECSMALL); GEN M0 = zv_copy(t); mask = 0; for (i = 1; i <= last_dim; i++) { cols[BIL + 1 - i] = last_s[i]; mask |= 1UL<<(last_s[i]-1); } for (i = j = 1; i <= BIL; i++) if (!(mask & (1UL<<(i-1)))) cols[j++] = i; /* compute the inverse of t[][] */ for (i = 1; i <= BIL; i++) { mask = 1UL<<(cols[i]-1); row_i = cols[i]; for (j = i; j <= BIL; j++) { row_j = cols[j]; if (uel(M0,row_j) & mask) { swap(gel(M0, row_j), gel(M0, row_i)); swap(gel(M1, row_j), gel(M1, row_i)); break; } } if (j <= BIL) { for (j = 1; j <= BIL; j++) { row_j = cols[j]; if (row_i != row_j && (M0[row_j] & mask)) { uel(M0,row_j) ^= uel(M0,row_i); uel(M1,row_j) ^= uel(M1,row_i); } } s[++dim] = cols[i]; continue; } for (j = i; j <= BIL; j++) { row_j = cols[j]; if (uel(M1,row_j) & mask) { swap(gel(M0, row_j), gel(M0, row_i)); swap(gel(M1, row_j), gel(M1, row_i)); break; } } if (j > BIL) return NULL; for (j = 1; j <= BIL; j++) { row_j = cols[j]; if (row_i != row_j && (M1[row_j] & mask)) { uel(M0,row_j) ^= uel(M0,row_i); uel(M1,row_j) ^= uel(M1,row_i); } } M0[row_i] = M1[row_i] = 0; } mask = 0; for (i = 1; i <= dim; i++) mask |= 1UL<<(s[i]-1); for (i = 1; i <= last_dim; i++) mask |= 1UL<<(last_s[i]-1); if (mask != (ulong)(-1)) return NULL; /* Failure */ setlg(s, dim+1); set_avma(av); *pt_s = s; return M1; } /* Compute x * A~ */ static GEN F2w_F2Ms_transmul(GEN x, GEN A, long nbrow) { long i, j, l = lg(A); GEN b = zero_zv(nbrow); for (i = 1; i < l; i++) { GEN c = gel(A,i); long lc = lg(c); ulong xi = x[i]; for (j = 1; j < lc; j++) b[c[j]] ^= xi; } return b; } /* Compute x * A */ static GEN F2w_F2Ms_mul(GEN x, GEN A) { long i, j, l = lg(A); GEN b = cgetg(l, t_VECSMALL); for (i = 1; i < l; i++) { GEN c = gel(A,i); long lc = lg(c); ulong s = 0; for (j = 1; j < lc; j++) s ^= x[c[j]]; b[i] = s; } return b; } static void F2wB_addid_inplace(GEN f) { long i; for (i = 1; i <= BIL; i++) uel(f,i) ^= 1UL<<(i-1); } static void F2w_mask_inplace(GEN f, ulong m) { long i, l = lg(f); for (i = 1; i < l; i++) uel(f,i) &= m; } static GEN block_lanczos(GEN B, ulong nbrow) { pari_sp av = avma, av2; GEN v0, v1, v2, vnext, x, w; GEN winv0, winv1, winv2; GEN vt_a_v0, vt_a_v1, vt_a2_v0, vt_a2_v1; GEN d, e, f, f2, s0; long i, iter; long n = lg(B)-1; long dim0; ulong mask0, mask1; v1 = zero_zv(n); v2 = zero_zv(n); vt_a_v1 = zero_zv(BIL); vt_a2_v1 = zero_zv(BIL); winv1 = zero_zv(BIL); winv2 = zero_zv(BIL); s0 = identity_zv(BIL); mask1 = (ulong)(-1); x = random_zv(n); w = F2w_F2Ms_mul(F2w_F2Ms_transmul(x, B, nbrow), B); v0 = w; av2 = avma; for (iter=1;;iter++) { vnext = F2w_F2Ms_mul(F2w_F2Ms_transmul(v0, B, nbrow), B); vt_a_v0 = F2w_transmul(v0, vnext); if (zv_equal0(vt_a_v0)) break; /* success */ vt_a2_v0 = F2w_transmul(vnext, vnext); winv0 = find_nonsingular_sub(vt_a_v0, s0, &s0); if (!winv0) return gc_NULL(av); /* failure */ dim0 = lg(s0)-1; mask0 = 0; for (i = 1; i <= dim0; i++) mask0 |= 1UL<<(s0[i]-1); d = cgetg(BIL+1, t_VECSMALL); for (i = 1; i <= BIL; i++) d[i] = (vt_a2_v0[i] & mask0) ^ vt_a_v0[i]; d = F2wB_mul(winv0, d); F2wB_addid_inplace(d); e = F2wB_mul(winv1, vt_a_v0); F2w_mask_inplace(e, mask0); f = F2wB_mul(vt_a_v1, winv1); F2wB_addid_inplace(f); f = F2wB_mul(winv2, f); f2 = cgetg(BIL+1, t_VECSMALL); for (i = 1; i <= BIL; i++) f2[i] = ((vt_a2_v1[i] & mask1) ^ vt_a_v1[i]) & mask0; f = F2wB_mul(f, f2); F2w_mask_inplace(vnext, mask0); F2w_F2wB_mul_add_inplace(v0, d, vnext); F2w_F2wB_mul_add_inplace(v1, e, vnext); F2w_F2wB_mul_add_inplace(v2, f, vnext); d = F2wB_mul(winv0, F2w_transmul(v0, w)); F2w_F2wB_mul_add_inplace(v0, d, x); v2 = v1; v1 = v0; v0 = vnext; winv2 = winv1; winv1 = winv0; vt_a_v1 = vt_a_v0; vt_a2_v1 = vt_a2_v0; mask1 = mask0; gerepileall(av2, 9, &x, &s0, &v0, &v1, &v2, &winv1, &winv2, &vt_a_v1, &vt_a2_v1); } if (DEBUGLEVEL >= 5) err_printf("Lanczos halted after %ld iterations\n", iter); v1 = F2w_F2Ms_transmul(x, B, nbrow); v2 = F2w_F2Ms_transmul(v0, B, nbrow); x = shallowconcat(F2w_transpose_F2m(x), F2w_transpose_F2m(v0)); v1 = shallowconcat(F2w_transpose_F2m(v1), F2w_transpose_F2m(v2)); s0 = gel(F2m_indexrank(x), 2); x = shallowextract(x, s0); v1 = shallowextract(v1, s0); return F2m_mul(x, F2m_ker(v1)); } static GEN F2v_inflate(GEN v, GEN p, long n) { long i, l = lg(p)-1; GEN w = zero_F2v(n); for (i=1; i<=l; i++) if (F2v_coeff(v,i)) F2v_set(w, p[i]); return w; } static GEN F2m_inflate(GEN x, GEN p, long n) { pari_APPLY_same(F2v_inflate(gel(x,i), p, n)) } GEN F2Ms_ker(GEN M, long nbrow) { pari_sp av = avma; long nbcol = lg(M)-1; GEN Mp, R, Rp, p; if (nbrow <= 640) return gerepileupto(av, F2m_ker(F2Ms_to_F2m(M, nbrow))); p = F2Ms_colelim(M, nbrow); Mp = vecpermute(M, p); do { R = block_lanczos(Mp, nbrow); } while(!R); Rp = F2m_inflate(R, p, nbcol); return gerepilecopy(av, Rp); } GEN F2m_to_F2Ms(GEN M) { long ncol = lg(M)-1; GEN B = cgetg(ncol+1, t_MAT); long i, j, k; for(i = 1; i <= ncol; i++) { GEN D, V = gel(M,i); long n = F2v_hamming(V), l = V[1]; D = cgetg(n+1, t_VECSMALL); for (j=1, k=1; j<=l; j++) if( F2v_coeff(V,j)) D[k++] = j; gel(B, i) = D; } return B; } GEN F2Ms_to_F2m(GEN M, long nrow) { long i, j, l = lg(M); GEN B = cgetg(l, t_MAT); for(i = 1; i < l; i++) { GEN Bi = zero_F2v(nrow), Mi = gel(M,i); long l = lg(Mi); for (j = 1; j < l; j++) F2v_set(Bi, Mi[j]); gel(B, i) = Bi; } return B; } pari-2.17.2/src/basemath/ellisog.c0000644000175000017500000014327514760123736015366 0ustar billbill/* Copyright (C) 2014 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_ellisogeny /* Return 1 if the point Q is a Weierstrass (2-torsion) point of the * curve E, return 0 otherwise */ static long ellisweierstrasspoint(GEN E, GEN Q) { return ell_is_inf(Q) || gequal0(ec_dmFdy_evalQ(E, Q)); } /* Given an elliptic curve E = [a1, a2, a3, a4, a6] and t,w in the ring of * definition of E, return the curve * E' = [a1, a2, a3, a4 - 5t, a6 - (E.b2 t + 7w)] */ static GEN make_velu_curve(GEN E, GEN t, GEN w) { GEN A4, A6, a1 = ell_get_a1(E), a2 = ell_get_a2(E), a3 = ell_get_a3(E); A4 = gsub(ell_get_a4(E), gmulsg(5L, t)); A6 = gsub(ell_get_a6(E), gadd(gmul(ell_get_b2(E), t), gmulsg(7L, w))); return mkvec5(a1,a2,a3,A4,A6); } /* If phi = (f(x)/h(x)^2, g(x,y)/h(x)^3) is an isogeny, return the * variables x and y in a vecsmall */ INLINE void get_isog_vars(GEN phi, long *vx, long *vy) { *vx = varn(gel(phi, 1)); *vy = varn(gel(phi, 2)); if (*vy == *vx) *vy = gvar2(gel(phi,2)); } /* x must be nonzero */ INLINE long _degree(GEN x) { return typ(x)==t_POL ? degpol(x): 0; } static GEN RgH_eval(GEN P, GEN A, GEN B) { if (typ(P)==t_POL) { if (signe(P)==0) return mkvec2(P, gen_1); return mkvec2(RgX_homogenous_evalpow(P, A, B), gel(B,degpol(P)+1)); } else return mkvec2(P, gen_1); } /* Given isogenies F:E' -> E and G:E'' -> E', return the composite * isogeny F o G:E'' -> E */ static GEN ellcompisog(GEN F, GEN G) { pari_sp av = avma; GEN Gh, Gh2, Gh3, f, g, h, h2, h3, den, num; GEN K, K2, K3, F0, F1, g0, g1, Gp; long vx, vy, d; checkellisog(F); checkellisog(G); get_isog_vars(F, &vx, &vy); Gh = gel(G,3); Gh2 = gsqr(Gh); Gh3 = gmul(Gh, Gh2); F0 = polcoef_i(gel(F,2), 0, vy); F1 = polcoef_i(gel(F,2), 1, vy); d = maxss(maxss(degpol(gel(F,1)),_degree(gel(F,3))), maxss(_degree(F0),_degree(F1))); Gp = gpowers(Gh2, d); f = RgH_eval(gel(F,1), gel(G,1), Gp); g0 = RgH_eval(F0, gel(G,1), Gp); g1 = RgH_eval(F1, gel(G,1), Gp); h = RgH_eval(gel(F,3), gel(G,1), Gp); K = gmul(gel(h,1), Gh); K = RgX_normalize(RgX_div(K, RgX_gcd(K,RgX_deriv(K)))); K2 = gsqr(K); K3 = gmul(K, K2); h2 = mkvec2(gsqr(gel(h,1)), gsqr(gel(h,2))); h3 = mkvec2(gmul(gel(h,1),gel(h2,1)), gmul(gel(h,2),gel(h2,2))); f = gdiv(gmul(gmul(K2, gel(f,1)),gel(h2,2)), gmul(gel(f,2), gel(h2,1))); den = gmul(Gh3, gel(g1,2)); num = gadd(gmul(gel(g0,1),den), gmul(gmul(gel(G,2),gel(g1,1)),gel(g0,2))); g = gdiv(gmul(gmul(K3,num),gel(h3,2)),gmul(gmul(gel(g0,2),den), gel(h3,1))); return gerepilecopy(av, mkvec3(f,g,K)); } static GEN to_RgX(GEN P, long vx) { return typ(P) == t_POL && varn(P)==vx? P: scalarpol_shallow(P, vx); } static GEN divy(GEN P0, GEN P1, GEN Q, GEN T, long vy) { GEN DP0, P0r = Q_remove_denom(P0, &DP0), P0D; GEN DP1, P1r = Q_remove_denom(P1, &DP1), P1D; GEN DQ, Qr = Q_remove_denom(Q, &DQ), P2; P0D = RgXQX_div(P0r, Qr, T); if (DP0) P0D = gdiv(P0D, DP0); P1D = RgXQX_div(P1r, Qr, T); if (DP1) P1D = gdiv(P1D, DP1); P2 = gadd(gmul(P1D, pol_x(vy)), P0D); if (DQ) P2 = gmul(P2, DQ); return P2; } static GEN QXQH_eval(GEN P, GEN A, GEN B, GEN T) { if (signe(P)==0) return mkvec2(P, pol_1(varn(P))); return mkvec2(QXQX_homogenous_evalpow(P, A, B, T), gel(B,degpol(P)+1)); } static GEN ellnfcompisog(GEN nf, GEN F, GEN G) { pari_sp av = avma; GEN Gh, Gh2, Gh3, f, g, gd, h, h21, h22, h31, h32, den; GEN K, K2, K3, F0, F1, G0, G1, g0, g1, Gp; GEN num0, num1, gn0, gn1; GEN g0d, g01, k3h32; GEN T; pari_timer ti; long vx, vy, d; if (!nf) return ellcompisog(F, G); T = nf_get_pol(nf); timer_start(&ti); checkellisog(F); F = liftpol_shallow(F); checkellisog(G); G = liftpol_shallow(G); get_isog_vars(F, &vx, &vy); Gh = to_RgX(gel(G,3),vx); Gh2 = QXQX_sqr(Gh, T); Gh3 = QXQX_mul(Gh, Gh2, T); F0 = to_RgX(polcoef_i(gel(F,2), 0, vy), vx); F1 = to_RgX(polcoef_i(gel(F,2), 1, vy), vx); G0 = to_RgX(polcoef_i(gel(G,2), 0, vy), vx); G1 = to_RgX(polcoef_i(gel(G,2), 1, vy), vx); d = maxss(maxss(degpol(gel(F,1)),degpol(gel(F,3))),maxss(degpol(F0),degpol(F1))); Gp = QXQX_powers(Gh2, d, T); f = QXQH_eval(to_RgX(gel(F,1),vx), gel(G,1), Gp, T); g0 = QXQH_eval(F0, to_RgX(gel(G,1),vx), Gp, T); g1 = QXQH_eval(F1, to_RgX(gel(G,1),vx), Gp, T); h = QXQH_eval(to_RgX(gel(F,3),vx), gel(G,1), Gp, T); K = Q_remove_denom(QXQX_mul(to_RgX(gel(h,1),vx), Gh, T), NULL); K = RgXQX_div(K, nfgcd(K, RgX_deriv(K), T, NULL), T); K = RgX_normalize(K); if (DEBUGLEVEL) timer_printf(&ti,"ellnfcompisog: nfgcd"); K2 = QXQX_sqr(K, T); K3 = QXQX_mul(K, K2, T); if (DEBUGLEVEL) timer_printf(&ti,"ellnfcompisog: evalpow"); h21 = QXQX_sqr(gel(h,1),T); h22 = QXQX_sqr(gel(h,2),T); h31 = QXQX_mul(gel(h,1), h21,T); h32 = QXQX_mul(gel(h,2), h22,T); if (DEBUGLEVEL) timer_printf(&ti,"h"); f = RgXQX_div(QXQX_mul(QXQX_mul(K2, gel(f,1), T), h22, T), QXQX_mul(gel(f,2), h21, T), T); if (DEBUGLEVEL) timer_printf(&ti,"f"); den = QXQX_mul(Gh3, gel(g1,2), T); if (DEBUGLEVEL) timer_printf(&ti,"ellnfcompisog: den"); g0d = QXQX_mul(gel(g0,1),den, T); g01 = QXQX_mul(gel(g1,1),gel(g0,2),T); num0 = RgX_add(g0d, QXQX_mul(G0,g01, T)); num1 = QXQX_mul(G1,g01, T); if (DEBUGLEVEL) timer_printf(&ti,"ellnfcompisog: num"); k3h32 = QXQX_mul(K3,h32,T); gn0 = QXQX_mul(num0, k3h32, T); gn1 = QXQX_mul(num1, k3h32, T); if (DEBUGLEVEL) timer_printf(&ti,"ellnfcompisog: gn"); gd = QXQX_mul(QXQX_mul(gel(g0,2), den, T), h31, T); if (DEBUGLEVEL) timer_printf(&ti,"ellnfcompisog: gd"); g = divy(gn0, gn1, gd, T, vy); if (DEBUGLEVEL) timer_printf(&ti,"ellnfcompisog: divy"); return gerepilecopy(av, gmul(mkvec3(f,g,K),gmodulo(gen_1,T))); } /* Given an isogeny phi from ellisogeny() and a point P in the domain of phi, * return phi(P) */ GEN ellisogenyapply(GEN phi, GEN P) { pari_sp ltop = avma; GEN f, g, h, img_f, img_g, img_h, img_h2, img_h3, img, tmp; long vx, vy; if (lg(P) == 4) return ellcompisog(phi,P); checkellisog(phi); checkellpt(P); if (ell_is_inf(P)) return ellinf(); f = gel(phi, 1); g = gel(phi, 2); h = gel(phi, 3); get_isog_vars(phi, &vx, &vy); img_h = poleval(h, gel(P, 1)); if (gequal0(img_h)) { set_avma(ltop); return ellinf(); } img_h2 = gsqr(img_h); img_h3 = gmul(img_h, img_h2); img_f = poleval(f, gel(P, 1)); /* FIXME: This calculation of g is perhaps not as efficient as it could be */ tmp = gsubst(g, vx, gel(P, 1)); img_g = gsubst(tmp, vy, gel(P, 2)); img = cgetg(3, t_VEC); gel(img, 1) = gdiv(img_f, img_h2); gel(img, 2) = gdiv(img_g, img_h3); return gerepileupto(ltop, img); } /* isog = [f, g, h] = [x, y, 1] = identity */ static GEN isog_identity(long vx, long vy) { return mkvec3(pol_x(vx), pol_x(vy), pol_1(vx)); } /* Returns an updated value for isog based (primarily) on tQ and uQ. Used to * iteratively compute the isogeny corresponding to a subgroup generated by a * given point. Ref: Equation 8 in Velu's paper. * isog = NULL codes the identity */ static GEN update_isogeny_polys(GEN isog, GEN E, GEN Q, GEN tQ, GEN uQ, long vx, long vy) { pari_sp ltop = avma, av; GEN xQ = gel(Q, 1), yQ = gel(Q, 2); GEN rt = deg1pol_shallow(gen_1, gneg(xQ), vx); GEN a1 = ell_get_a1(E), a3 = ell_get_a3(E); GEN gQx = ec_dFdx_evalQ(E, Q); GEN gQy = ec_dFdy_evalQ(E, Q); GEN tmp1, tmp2, tmp3, tmp4, f, g, h, rt_sqr, res; /* g -= uQ * (2 * y + E.a1 * x + E.a3) * + tQ * rt * (E.a1 * rt + y - yQ) * + rt * (E.a1 * uQ - gQx * gQy) */ av = avma; tmp1 = gmul(uQ, gadd(deg1pol_shallow(gen_2, gen_0, vy), deg1pol_shallow(a1, a3, vx))); tmp1 = gerepileupto(av, tmp1); av = avma; tmp2 = gmul(tQ, gadd(gmul(a1, rt), deg1pol_shallow(gen_1, gneg(yQ), vy))); tmp2 = gerepileupto(av, tmp2); av = avma; tmp3 = gsub(gmul(a1, uQ), gmul(gQx, gQy)); tmp3 = gerepileupto(av, tmp3); if (!isog) isog = isog_identity(vx,vy); f = gel(isog, 1); g = gel(isog, 2); h = gel(isog, 3); rt_sqr = gsqr(rt); res = cgetg(4, t_VEC); av = avma; tmp4 = gdiv(gadd(gmul(tQ, rt), uQ), rt_sqr); gel(res, 1) = gerepileupto(av, gadd(f, tmp4)); av = avma; tmp4 = gadd(tmp1, gmul(rt, gadd(tmp2, tmp3))); gel(res, 2) = gerepileupto(av, gsub(g, gdiv(tmp4, gmul(rt, rt_sqr)))); av = avma; gel(res, 3) = gerepileupto(av, gmul(h, rt)); return gerepileupto(ltop, res); } /* Given a point P on E, return the curve E/

and, if only_image is zero, * the isogeny pi: E -> E/

. The variables vx and vy are used to describe * the isogeny (ignored if only_image is zero) */ static GEN isogeny_from_kernel_point(GEN E, GEN P, int only_image, long vx, long vy) { pari_sp av = avma; GEN isog, EE, f, g, h, h2, h3; GEN Q = P, t = gen_0, w = gen_0; if (!oncurve(E,P)) pari_err_DOMAIN("isogeny_from_kernel_point", "point", "not on", E, P); if (ell_is_inf(P)) { if (only_image) return E; return mkvec2(E, isog_identity(vx,vy)); } isog = NULL; for (;;) { GEN tQ, xQ = gel(Q,1), uQ = ec_2divpol_evalx(E, xQ); int stop = 0; if (ellisweierstrasspoint(E,Q)) { /* ord(P)=2c; take Q=[c]P into consideration and stop */ tQ = ec_dFdx_evalQ(E, Q); stop = 1; } else tQ = ec_half_deriv_2divpol_evalx(E, xQ); t = gadd(t, tQ); w = gadd(w, gadd(uQ, gmul(tQ, xQ))); if (!only_image) isog = update_isogeny_polys(isog, E, Q,tQ,uQ, vx,vy); if (stop) break; Q = elladd(E, P, Q); /* IF x([c]P) = x([c-1]P) THEN [c]P = -[c-1]P and [2c-1]P = 0 */ if (gequal(gel(Q,1), xQ)) break; if (gc_needed(av,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"isogeny_from_kernel_point"); gerepileall(av, isog? 4: 3, &Q, &t, &w, &isog); } } EE = make_velu_curve(E, t, w); if (only_image) return EE; if (!isog) isog = isog_identity(vx,vy); f = gel(isog, 1); g = gel(isog, 2); if ( ! (typ(f) == t_RFRAC && typ(g) == t_RFRAC)) pari_err_BUG("isogeny_from_kernel_point (f or g has wrong type)"); /* Clean up the isogeny polynomials f, g and h so that the isogeny * is given by (x,y) -> (f(x)/h(x)^2, g(x,y)/h(x)^3) */ h = gel(isog, 3); h2 = gsqr(h); h3 = gmul(h, h2); f = gmul(f, h2); g = gmul(g, h3); if (typ(f) != t_POL || typ(g) != t_POL) pari_err_BUG("isogeny_from_kernel_point (wrong denominator)"); return mkvec2(EE, mkvec3(f,g, gel(isog,3))); } /* Given a t_POL x^n - s1 x^{n-1} + s2 x^{n-2} - s3 x^{n-3} + ... * return the first three power sums (Newton's identities): * p1 = s1 * p2 = s1^2 - 2 s2 * p3 = (s1^2 - 3 s2) s1 + 3 s3 */ static void first_three_power_sums(GEN pol, GEN *p1, GEN *p2, GEN *p3) { long d = degpol(pol); GEN s1, s2, ms3; *p1 = s1 = gneg(RgX_coeff(pol, d-1)); s2 = RgX_coeff(pol, d-2); *p2 = gsub(gsqr(s1), gmulsg(2L, s2)); ms3 = RgX_coeff(pol, d-3); *p3 = gadd(gmul(s1, gsub(*p2, s2)), gmulsg(-3L, ms3)); } /* Let E and a t_POL h of degree 1 or 3 whose roots are 2-torsion points on E. * - if only_image != 0, return [t, w] used to compute the equation of the * quotient by the given 2-torsion points * - else return [t,w, f,g,h], along with the contributions f, g and * h to the isogeny giving the quotient by h. Variables vx and vy are used * to create f, g and h, or ignored if only_image is zero */ /* deg h = 1; 2-torsion contribution from Weierstrass point */ static GEN contrib_weierstrass_pt(GEN E, GEN h, long only_image, long vx, long vy) { GEN p = ellbasechar(E); GEN a1 = ell_get_a1(E); GEN a3 = ell_get_a3(E); GEN x0 = gneg(constant_coeff(h)); /* h = x - x0 */ GEN b = gadd(gmul(a1,x0), a3); GEN y0, Q, t, w, t1, t2, f, g; if (!equalis(p, 2L)) /* char(k) != 2 ==> y0 = -b/2 */ y0 = gmul2n(gneg(b), -1); else { /* char(k) = 2 ==> y0 = sqrt(f(x0)) where E is y^2 + h(x) = f(x). */ if (!gequal0(b)) pari_err_BUG("two_torsion_contrib (a1*x0+a3 != 0)"); y0 = gsqrt(ec_f_evalx(E, x0), 0); } Q = mkvec2(x0, y0); t = ec_dFdx_evalQ(E, Q); w = gmul(x0, t); if (only_image) return mkvec2(t,w); /* Compute isogeny, f = (x - x0) * t */ f = deg1pol_shallow(t, gmul(t, gneg(x0)), vx); /* g = (x - x0) * t * (a1 * (x - x0) + (y - y0)) */ t1 = deg1pol_shallow(a1, gmul(a1, gneg(x0)), vx); t2 = deg1pol_shallow(gen_1, gneg(y0), vy); g = gmul(f, gadd(t1, t2)); return mkvec5(t, w, f, g, h); } /* deg h =3; full 2-torsion contribution. NB: assume h is monic; base field * characteristic is odd or zero (cannot happen in char 2).*/ static GEN contrib_full_tors(GEN E, GEN h, long only_image, long vx, long vy) { GEN p1, p2, p3, half_b2, half_b4, t, w, f, g; first_three_power_sums(h, &p1,&p2,&p3); half_b2 = gmul2n(ell_get_b2(E), -1); half_b4 = gmul2n(ell_get_b4(E), -1); /* t = 3*(p2 + b4/2) + p1 * b2/2 */ t = gadd(gmulsg(3L, gadd(p2, half_b4)), gmul(p1, half_b2)); /* w = 3 * p3 + p2 * b2/2 + p1 * b4/2 */ w = gadd(gmulsg(3L, p3), gadd(gmul(p2, half_b2), gmul(p1, half_b4))); if (only_image) return mkvec2(t,w); /* Compute isogeny */ { GEN a1 = ell_get_a1(E), a3 = ell_get_a3(E), t1, t2; GEN s1 = gneg(RgX_coeff(h, 2)); GEN dh = RgX_deriv(h); GEN psi2xy = gadd(deg1pol_shallow(a1, a3, vx), deg1pol_shallow(gen_2, gen_0, vy)); /* f = -3 (3 x + b2/2 + s1) h + (3 x^2 + (b2/2) x + (b4/2)) h'*/ t1 = RgX_mul(h, gmulsg(-3, deg1pol(stoi(3), gadd(half_b2, s1), vx))); t2 = mkpoln(3, stoi(3), half_b2, half_b4); setvarn(t2, vx); t2 = RgX_mul(dh, t2); f = RgX_add(t1, t2); /* 2g = psi2xy * (f'*h - f*h') - (a1*f + a3*h) * h; */ t1 = RgX_sub(RgX_mul(RgX_deriv(f), h), RgX_mul(f, dh)); t2 = RgX_mul(h, RgX_add(RgX_Rg_mul(f, a1), RgX_Rg_mul(h, a3))); g = RgX_divs(gsub(gmul(psi2xy, t1), t2), 2L); f = RgX_mul(f, h); g = RgX_mul(g, h); } return mkvec5(t, w, f, g, h); } /* Given E and a t_POL T whose roots define a subgroup G of E, return the factor * of T that corresponds to the 2-torsion points E[2] \cap G in G */ INLINE GEN two_torsion_part(GEN E, GEN T) { return RgX_gcd(T, elldivpol(E, 2, varn(T))); } /* Return the jth Hasse derivative of the polynomial f = \sum_{i=0}^n a_i x^i, * i.e. \sum_{i=j}^n a_i \binom{i}{j} x^{i-j}. It is a derivation even when the * coefficient ring has positive characteristic */ static GEN derivhasse(GEN f, ulong j) { ulong i, d = degpol(f); GEN df; if (gequal0(f) || d == 0) return pol_0(varn(f)); if (j == 0) return gcopy(f); df = cgetg(2 + (d-j+1), t_POL); df[1] = f[1]; for (i = j; i <= d; ++i) gel(df, i-j+2) = gmul(binomialuu(i,j), gel(f, i+2)); return normalizepol(df); } static GEN non_two_torsion_abscissa(GEN E, GEN h0, long vx) { GEN mp1, dh0, ddh0, t, u, t1, t2, t3; long m = degpol(h0); mp1 = gel(h0, m + 1); /* negative of first power sum */ dh0 = RgX_deriv(h0); ddh0 = RgX_deriv(dh0); t = ec_bmodel(E, vx); u = ec_half_deriv_2divpol(E, vx); t1 = RgX_sub(RgX_sqr(dh0), RgX_mul(ddh0, h0)); t2 = RgX_mul(u, RgX_mul(h0, dh0)); t3 = RgX_mul(RgX_sqr(h0), deg1pol_shallow(stoi(2*m), gmulsg(2L, mp1), vx)); /* t * (dh0^2 - ddh0*h0) - u*dh0*h0 + (2*m*x - 2*s1) * h0^2); */ return RgX_add(RgX_sub(RgX_mul(t, t1), t2), t3); } static GEN isog_abscissa(GEN E, GEN kerp, GEN h0, long vx, GEN two_tors) { GEN f0, f2, h2, t1, t2, t3; f0 = (degpol(h0) > 0)? non_two_torsion_abscissa(E, h0, vx): pol_0(vx); f2 = gel(two_tors, 3); h2 = gel(two_tors, 5); /* Combine f0 and f2 into the final abscissa of the isogeny. */ t1 = RgX_mul(pol_x(vx), RgX_sqr(kerp)); t2 = RgX_mul(f2, RgX_sqr(h0)); t3 = RgX_mul(f0, RgX_sqr(h2)); /* x * kerp^2 + f2 * h0^2 + f0 * h2^2 */ return RgX_add(t1, RgX_add(t2, t3)); } static GEN non_two_torsion_ordinate_char_not2(GEN E, GEN f, GEN h, GEN psi2) { GEN a1 = ell_get_a1(E), a3 = ell_get_a3(E); GEN df = RgX_deriv(f), dh = RgX_deriv(h); /* g = df * h * psi2/2 - f * dh * psi2 * - (E.a1 * f + E.a3 * h^2) * h/2 */ GEN t1 = RgX_mul(df, RgX_mul(h, RgX_divs(psi2, 2L))); GEN t2 = RgX_mul(f, RgX_mul(dh, psi2)); GEN t3 = RgX_mul(RgX_divs(h, 2L), RgX_add(RgX_Rg_mul(f, a1), RgX_Rg_mul(RgX_sqr(h), a3))); return RgX_sub(RgX_sub(t1, t2), t3); } /* h = kerq */ static GEN non_two_torsion_ordinate_char2(GEN E, GEN h, GEN x, GEN y) { GEN a1 = ell_get_a1(E), a3 = ell_get_a3(E), a4 = ell_get_a4(E); GEN b2 = ell_get_b2(E), b4 = ell_get_b4(E), b6 = ell_get_b6(E); GEN h2, dh, dh2, ddh, D2h, D2dh, H, psi2, u, t, alpha; GEN p1, t1, t2, t3, t4; long m, vx = varn(x); h2 = RgX_sqr(h); dh = RgX_deriv(h); dh2 = RgX_sqr(dh); ddh = RgX_deriv(dh); H = RgX_sub(dh2, RgX_mul(h, ddh)); D2h = derivhasse(h, 2); D2dh = derivhasse(dh, 2); psi2 = deg1pol_shallow(a1, a3, vx); u = mkpoln(3, b2, gen_0, b6); setvarn(u, vx); t = deg1pol_shallow(b2, b4, vx); alpha = mkpoln(4, a1, a3, gmul(a1, a4), gmul(a3, a4)); setvarn(alpha, vx); m = degpol(h); p1 = RgX_coeff(h, m-1); /* first power sum */ t1 = gmul(gadd(gmul(a1, p1), gmulgu(a3, m)), RgX_mul(h,h2)); t2 = gmul(a1, gadd(gmul(a1, gadd(y, psi2)), RgX_add(RgX_Rg_add(RgX_sqr(x), a4), t))); t2 = gmul(t2, gmul(dh, h2)); t3 = gadd(gmul(y, t), RgX_add(alpha, RgX_Rg_mul(u, a1))); t3 = gmul(t3, RgX_mul(h, H)); t4 = gmul(u, psi2); t4 = gmul(t4, RgX_sub(RgX_sub(RgX_mul(h2, D2dh), RgX_mul(dh, H)), RgX_mul(h, RgX_mul(dh, D2h)))); return gadd(t1, gadd(t2, gadd(t3, t4))); } static GEN isog_ordinate(GEN E, GEN kerp, GEN kerq, GEN x, GEN y, GEN two_tors, GEN f) { GEN g; if (! equalis(ellbasechar(E), 2L)) { /* FIXME: We don't use (hence don't need to calculate) * g2 = gel(two_tors, 4) when char(k) != 2. */ GEN psi2 = ec_dmFdy_evalQ(E, mkvec2(x, y)); g = non_two_torsion_ordinate_char_not2(E, f, kerp, psi2); } else { GEN h2 = gel(two_tors, 5); GEN g2 = gmul(gel(two_tors, 4), RgX_mul(kerq, RgX_sqr(kerq))); GEN g0 = non_two_torsion_ordinate_char2(E, kerq, x, y); g0 = gmul(g0, RgX_mul(h2, RgX_sqr(h2))); g = gsub(gmul(y, RgX_mul(kerp, RgX_sqr(kerp))), gadd(g2, g0)); } return g; } /* Given an elliptic curve E and a polynomial kerp whose roots give the * x-coordinates of a subgroup G of E, return the curve E/G and, * if only_image is zero, the isogeny pi:E -> E/G. Variables vx and vy are * used to describe the isogeny (and are ignored if only_image is zero). */ static GEN isogeny_from_kernel_poly(GEN E, GEN kerp, long only_image, long vx, long vy) { long m; GEN b2 = ell_get_b2(E), b4 = ell_get_b4(E), b6 = ell_get_b6(E); GEN p1, p2, p3, x, y, f, g, two_tors, EE, t, w; GEN kerh = two_torsion_part(E, kerp); GEN kerq = RgX_divrem(kerp, kerh, ONLY_DIVIDES); if (!kerq) pari_err_BUG("isogeny_from_kernel_poly"); /* isogeny degree: 2*degpol(kerp)+1-degpol(kerh) */ m = degpol(kerq); kerp = RgX_normalize(kerp); kerq = RgX_normalize(kerq); kerh = RgX_normalize(kerh); switch(degpol(kerh)) { case 0: two_tors = only_image? mkvec2(gen_0, gen_0): mkvec5(gen_0, gen_0, pol_0(vx), pol_0(vx), pol_1(vx)); break; case 1: two_tors = contrib_weierstrass_pt(E, kerh, only_image,vx,vy); break; case 3: two_tors = contrib_full_tors(E, kerh, only_image,vx,vy); break; default: two_tors = NULL; pari_err_DOMAIN("isogeny_from_kernel_poly", "kernel polynomial", "does not define a subgroup of", E, kerp); } first_three_power_sums(kerq,&p1,&p2,&p3); x = pol_x(vx); y = pol_x(vy); /* t = 6 * p2 + b2 * p1 + m * b4, */ t = gadd(gmulsg(6L, p2), gadd(gmul(b2, p1), gmulsg(m, b4))); /* w = 10 * p3 + 2 * b2 * p2 + 3 * b4 * p1 + m * b6, */ w = gadd(gmulsg(10L, p3), gadd(gmul(gmulsg(2L, b2), p2), gadd(gmul(gmulsg(3L, b4), p1), gmulsg(m, b6)))); EE = make_velu_curve(E, gadd(t, gel(two_tors, 1)), gadd(w, gel(two_tors, 2))); if (only_image) return EE; f = isog_abscissa(E, kerp, kerq, vx, two_tors); g = isog_ordinate(E, kerp, kerq, x, y, two_tors, f); return mkvec2(EE, mkvec3(f,g,kerp)); } /* Given an elliptic curve E and a subgroup G of E, return the curve * E/G and, if only_image is zero, the isogeny corresponding * to the canonical surjection pi:E -> E/G. The variables vx and * vy are used to describe the isogeny (and are ignored if * only_image is zero). The subgroup G may be given either as * a generating point P on E or as a polynomial kerp whose roots are * the x-coordinates of the points in G */ GEN ellisogeny(GEN E, GEN G, long only_image, long vx, long vy) { pari_sp av = avma; GEN j, z; checkell(E);j = ell_get_j(E); if (vx < 0) vx = 0; if (vy < 0) vy = 1; if (varncmp(vx, vy) >= 0) pari_err_PRIORITY("ellisogeny", pol_x(vx), "<=", vy); if (!only_image && varncmp(vy, gvar(j)) >= 0) pari_err_PRIORITY("ellisogeny", j, ">=", vy); switch(typ(G)) { case t_VEC: checkellpt(G); if (!ell_is_inf(G)) { GEN x = gel(G,1), y = gel(G,2); if (!only_image) { if (varncmp(vy, gvar(x)) >= 0) pari_err_PRIORITY("ellisogeny", x, ">=", vy); if (varncmp(vy, gvar(y)) >= 0) pari_err_PRIORITY("ellisogeny", y, ">=", vy); } } z = isogeny_from_kernel_point(E, G, only_image, vx, vy); break; case t_POL: if (!only_image && varncmp(vy, gvar(constant_coeff(G))) >= 0) pari_err_PRIORITY("ellisogeny", constant_coeff(G), ">=", vy); z = isogeny_from_kernel_poly(E, G, only_image, vx, vy); break; default: z = NULL; pari_err_TYPE("ellisogeny", G); } return gerepilecopy(av, z); } static GEN trivial_isogeny(void) { return mkvec3(pol_x(0), scalarpol(pol_x(1), 0), pol_1(0)); } static GEN isogeny_a4a6(GEN E) { GEN a1 = ell_get_a1(E), a3 = ell_get_a3(E), b2 = ell_get_b2(E); retmkvec3(deg1pol(gen_1, gdivgu(b2, 12), 0), deg1pol(gdivgu(a1,2), deg1pol(gen_1, gdivgu(a3,2), 1), 0), pol_1(0)); } static GEN invisogeny_a4a6(GEN E) { GEN a1 = ell_get_a1(E), a3 = ell_get_a3(E), b2 = ell_get_b2(E); retmkvec3(deg1pol(gen_1, gdivgs(b2, -12), 0), deg1pol(gdivgs(a1,-2), deg1pol(gen_1, gadd(gdivgs(a3,-2), gdivgu(gmul(b2,a1), 24)), 1), 0), pol_1(0)); } static GEN RgXY_eval(GEN P, GEN x, GEN y) { return poleval(poleval(P,x), y); } static GEN twistisogeny(GEN iso, GEN d) { GEN d2 = gsqr(d), d3 = gmul(d, d2); return mkvec3(gdiv(gel(iso,1), d2), gdiv(gel(iso,2), d3), gel(iso, 3)); } static GEN ellisog_by_Kohel(GEN a4, GEN a6, long n, GEN ker, GEN kert, long flag) { GEN E = ellinit(mkvec2(a4, a6), NULL, DEFAULTPREC); GEN F = isogeny_from_kernel_poly(E, ker, flag, 0, 1); GEN Et = ellinit(flag ? F: gel(F, 1), NULL, DEFAULTPREC); GEN c4t = ell_get_c4(Et), c6t = ell_get_c6(Et), jt = ell_get_j(Et); if (!flag) { GEN Ft = isogeny_from_kernel_poly(Et, kert, flag, 0, 1); GEN isot = twistisogeny(gel(Ft, 2), stoi(n)); return mkvec5(c4t, c6t, jt, gel(F, 2), isot); } else return mkvec3(c4t, c6t, jt); } static GEN ellisog_by_roots(GEN a4, GEN a6, long n, GEN z, long flag) { GEN k = deg1pol_shallow(gen_1, gneg(z), 0); GEN kt= deg1pol_shallow(gen_1, gmulsg(n,z), 0); return ellisog_by_Kohel(a4, a6, n, k, kt, flag); } /* n = 2 or 3 */ static GEN a4a6_divpol(GEN a4, GEN a6, long n) { if (n == 2) return mkpoln(4, gen_1, gen_0, a4, a6); return mkpoln(5, utoi(3), gen_0, gmulgu(a4,6) , gmulgu(a6,12), gneg(gsqr(a4))); } static GEN ellisograph_Kohel_iso(GEN nf, GEN e, long n, GEN z, GEN *pR, long flag) { long i, r; GEN R, V, c4 = gel(e,1), c6 = gel(e,2); GEN a4 = gdivgs(c4, -48), a6 = gdivgs(c6, -864); GEN P = a4a6_divpol(a4, a6, n); R = nfroots(nf, z ? RgX_div_by_X_x(P, z, NULL): P); if (pR) *pR = R; r = lg(R); V = cgetg(r, t_VEC); for (i=1; i < r; i++) gel(V,i) = ellisog_by_roots(a4, a6, n, gel(R,i), flag); return V; } static GEN ellisograph_Kohel_r(GEN nf, GEN e, long n, GEN z, long flag) { GEN R, iso = ellisograph_Kohel_iso(nf, e, n, z, &R, flag); long i, r = lg(iso); GEN V = cgetg(r, t_VEC); for (i=1; i < r; i++) gel(V,i) = ellisograph_Kohel_r(nf, gel(iso,i), n, gmulgs(gel(R,i), -n), flag); return mkvec2(e, V); } static GEN corr(GEN c4, GEN c6) { GEN c62 = gmul2n(c6, 1); return gadd(gdiv(gsqr(c4), c62), gdiv(c62, gmulgu(c4,3))); } static GEN elkies98(GEN a4, GEN a6, long l, GEN s, GEN a4t, GEN a6t) { GEN C, P, S; long i, n, d; d = l == 2 ? 1 : l>>1; C = cgetg(d+1, t_VEC); gel(C, 1) = gdivgu(gsub(a4, a4t), 5); if (d >= 2) gel(C, 2) = gdivgu(gsub(a6, a6t), 7); if (d >= 3) gel(C, 3) = gdivgu(gsub(gsqr(gel(C, 1)), gmul(a4, gel(C, 1))), 3); for (n = 3; n < d; ++n) { GEN s = gen_0; for (i = 1; i < n; i++) s = gadd(s, gmul(gel(C, i), gel(C, n-i))); gel(C, n+1) = gdivgu(gsub(gsub(gmulsg(3, s), gmul(gmulsg((2*n-1)*(n-1), a4), gel(C, n-1))), gmul(gmulsg((2*n-2)*(n-2), a6), gel(C, n-2))), (n-1)*(2*n+5)); } P = cgetg(d+2, t_VEC); gel(P, 1 + 0) = stoi(d); gel(P, 1 + 1) = s; if (d >= 2) gel(P, 1 + 2) = gdivgu(gsub(gel(C, 1), gmulgu(a4, 2*d)), 6); for (n = 2; n < d; ++n) gel(P, 1 + n+1) = gdivgu(gsub(gsub(gel(C, n), gmul(gmulsg(4*n-2, a4), gel(P, 1+n-1))), gmul(gmulsg(4*n-4, a6), gel(P, 1+n-2))), 4*n+2); S = cgetg(d+3, t_POL); S[1] = evalsigne(1) | evalvarn(0); gel(S, 2 + d - 0) = gen_1; gel(S, 2 + d - 1) = gneg(s); for (n = 2; n <= d; ++n) { GEN s = gen_0; for (i = 1; i <= n; ++i) { GEN p = gmul(gel(P, 1+i), gel(S, 2 + d - (n-i))); s = gadd(s, p); } gel(S, 2 + d - n) = gdivgs(s, -n); } return S; } static GEN ellisog_by_jt(GEN c4, GEN c6, GEN jt, GEN jtp, GEN s0, long n, long flag) { GEN jtp2 = gsqr(jtp), den = gmul(jt, gsubgs(jt, 1728)); GEN c4t = gdiv(jtp2, den); GEN c6t = gdiv(gmul(jtp, c4t), jt); if (flag) return mkvec3(c4t, c6t, jt); else { GEN co = corr(c4, c6); GEN cot = corr(c4t, c6t); GEN s = gmul2n(gmulgs(gadd(gadd(s0, co), gmulgs(cot,-n)), -n), -2); GEN a4 = gdivgs(c4, -48), a6 = gdivgs(c6, -864); GEN a4t = gmul(gdivgs(c4t, -48), powuu(n,4)), a6t = gmul(gdivgs(c6t, -864), powuu(n,6)); GEN ker = elkies98(a4, a6, n, s, a4t, a6t); GEN st = gmulgs(s, -n); GEN a4tt = gmul(a4,powuu(n,4)), a6tt = gmul(a6,powuu(n,6)); GEN kert = elkies98(a4t, a6t, n, st, a4tt, a6tt); return ellisog_by_Kohel(a4, a6, n, ker, kert, flag); } } /* RENE SCHOOF, Counting points on elliptic curves over finite fields, * Journal de Theorie des Nombres de Bordeaux, tome 7, no 1 (1995), p. 219-254. * http://www.numdam.org/item?id=JTNB_1995__7_1_219_0 */ static GEN ellisog_by_j(GEN e, GEN jt, long n, GEN P, long flag) { pari_sp av = avma; GEN c4 = gel(e,1), c6 = gel(e, 2), j = gel(e, 3); GEN Px = RgX_deriv(P), Py = RgXY_derivx(P); GEN Pxj = RgXY_eval(Px, j, jt), Pyj = RgXY_eval(Py, j, jt); GEN Pxx = RgX_deriv(Px), Pxy = RgX_deriv(Py), Pyy = RgXY_derivx(Py); GEN Pxxj = RgXY_eval(Pxx,j,jt); GEN Pxyj = RgXY_eval(Pxy,j,jt); GEN Pyyj = RgXY_eval(Pyy,j,jt); GEN c6c4 = gdiv(c6, c4); GEN jp = gmul(j, c6c4); GEN jtp = gdivgs(gmul(jp, gdiv(Pxj, Pyj)), -n); GEN jtpn = gmulgs(jtp, n); GEN s0 = gdiv(gadd(gadd(gmul(gsqr(jp),Pxxj),gmul(gmul(jp,jtpn),gmul2n(Pxyj,1))), gmul(gsqr(jtpn),Pyyj)),gmul(jp,Pxj)); GEN et = ellisog_by_jt(c4, c6, jt, jtp, s0, n, flag); return gerepilecopy(av, et); } static GEN ellisograph_iso(GEN nf, GEN e, ulong p, GEN P, GEN oj, long flag) { long i, r; GEN Pj, R, V; if (!P) return ellisograph_Kohel_iso(nf, e, p, oj, NULL, flag); Pj = poleval(P, gel(e,3)); R = nfroots(nf,oj ? RgX_div_by_X_x(Pj, oj, NULL):Pj); r = lg(R); V = cgetg(r, t_VEC); for (i=1; i < r; i++) gel(V, i) = ellisog_by_j(e, gel(R, i), p, P, flag); return V; } static GEN ellisograph_r(GEN nf, GEN e, ulong p, GEN P, GEN oj, long flag) { GEN j = gel(e,3), iso = ellisograph_iso(nf, e, p, P, oj, flag); long i, r = lg(iso); GEN V = cgetg(r, t_VEC); for (i=1; i < r; i++) gel(V,i) = ellisograph_r(nf, gel(iso,i), p, P, j, flag); return mkvec2(e, V); } static GEN ellisograph_a4a6(GEN E, long flag) { GEN c4 = ell_get_c4(E), c6 = ell_get_c6(E), j = ell_get_j(E); return flag ? mkvec3(c4, c6, j): mkvec5(c4, c6, j, isogeny_a4a6(E), invisogeny_a4a6(E)); } static GEN ellisograph_dummy(GEN E, long n, GEN jt, GEN jtt, GEN s0, long flag) { GEN c4 = ell_get_c4(E), c6 = ell_get_c6(E), c6c4 = gdiv(c6, c4); GEN jtp = gmul(c6c4, gdivgs(gmul(jt, jtt), -n)); GEN iso = ellisog_by_jt(c4, c6, jt, jtp, gmul(s0, c6c4), n, flag); GEN v = mkvec2(iso, cgetg(1, t_VEC)); return mkvec2(ellisograph_a4a6(E, flag), mkvec(v)); } static GEN isograph_p(GEN nf, GEN e, ulong p, GEN P, long flag) { pari_sp av = avma; GEN iso; if (P) iso = ellisograph_r(nf, e, p, P, NULL, flag); else iso = ellisograph_Kohel_r(nf, e, p, NULL, flag); return gerepilecopy(av, iso); } static GEN get_polmodular(ulong p, long vx, long vy) { return p > 3 ? polmodular_ZXX(p,0,vx,vy): NULL; } static GEN ellisograph_p(GEN nf, GEN E, ulong p, long flag) { GEN e = ellisograph_a4a6(E, flag); GEN P = get_polmodular(p, 0, 1); return isograph_p(nf, e, p, P, flag); } static long etree_nbnodes(GEN T) { GEN F = gel(T,2); long n = 1, i, l = lg(F); for (i = 1; i < l; i++) n += etree_nbnodes(gel(F, i)); return n; } static long etree_listr(GEN nf, GEN T, GEN V, long n, GEN u, GEN ut) { GEN E = gel(T, 1), F = gel(T,2); long i, l = lg(F); GEN iso, isot = NULL; if (lg(E) == 6) { iso = ellnfcompisog(nf,gel(E,4), u); isot = ellnfcompisog(nf,ut, gel(E,5)); gel(V, n) = mkvec5(gel(E,1), gel(E,2), gel(E,3), iso, isot); } else { gel(V, n) = mkvec3(gel(E,1), gel(E,2), gel(E,3)); iso = u; } for (i = 1; i < l; i++) n = etree_listr(nf, gel(F, i), V, n + 1, iso, isot); return n; } static GEN etree_list(GEN nf, GEN T) { long n = etree_nbnodes(T); GEN V = cgetg(n+1, t_VEC); (void) etree_listr(nf, T, V, 1, trivial_isogeny(), trivial_isogeny()); return V; } static long etree_distmatr(GEN T, GEN M, long n) { GEN F = gel(T,2); long i, j, lF = lg(F), m = n + 1; GEN V = cgetg(lF, t_VECSMALL); mael(M, n, n) = 0; for(i = 1; i < lF; i++) V[i] = m = etree_distmatr(gel(F,i), M, m); for(i = 1; i < lF; i++) { long mi = i==1 ? n+1: V[i-1]; for(j = mi; j < V[i]; j++) { mael(M,n,j) = 1 + mael(M, mi, j); mael(M,j,n) = 1 + mael(M, j, mi); } for(j = 1; j < lF; j++) if (i != j) { long i1, j1, mj = j==1 ? n+1: V[j-1]; for (i1 = mi; i1 < V[i]; i1++) for(j1 = mj; j1 < V[j]; j1++) mael(M,i1,j1) = 2 + mael(M,mj,j1) + mael(M,i1,mi); } } return m; } static GEN etree_distmat(GEN T) { long i, n = etree_nbnodes(T); GEN M = cgetg(n+1, t_MAT); for(i = 1; i <= n; i++) gel(M,i) = cgetg(n+1, t_VECSMALL); (void)etree_distmatr(T, M, 1); return M; } static GEN distmat_pow(GEN E, ulong p) { long i, j, l = lg(E); GEN M = cgetg(l, t_MAT); for(i = 1; i < l; i++) { gel(M,i) = cgetg(l, t_COL); for(j = 1; j < l; j++) gmael(M,i,j) = powuu(p,mael(E,i,j)); } return M; } /* Assume there is a single p-isogeny */ static GEN isomatdbl(GEN nf, GEN L, GEN M, ulong p, GEN T2, long flag) { long i, j, n = lg(L) -1; GEN P = get_polmodular(p, 0, 1); GEN V = cgetg(2*n+1, t_VEC), N = cgetg(2*n+1, t_MAT); for (i=1; i <= n; i++) { GEN F, E, e = gel(L,i); if (i == 1) F = gmael(T2, 2, 1); else { F = ellisograph_iso(nf, e, p, P, NULL, flag); if (lg(F) != 2) pari_err_BUG("isomatdbl"); } E = gel(F, 1); if (flag) E = mkvec3(gel(E,1), gel(E,2), gel(E,3)); else { GEN iso = ellnfcompisog(nf, gel(E,4), gel(e, 4)); GEN isot = ellnfcompisog(nf, gel(e,5), gel(E, 5)); E = mkvec5(gel(E,1), gel(E,2), gel(E,3), iso, isot); } gel(V, i) = e; gel(V, i+n) = E; } for (i=1; i <= 2*n; i++) gel(N, i) = cgetg(2*n+1, t_COL); for (i=1; i <= n; i++) for (j=1; j <= n; j++) { gcoeff(N,i,j) = gcoeff(N,i+n,j+n) = gcoeff(M,i,j); gcoeff(N,i,j+n) = gcoeff(N,i+n,j) = muliu(gcoeff(M,i,j), p); } return mkvec2(V, N); } static ulong ellQ_exceptional_iso(GEN j, GEN *jt, GEN *jtp, GEN *s0) { *jt = j; *jtp = gen_1; if (typ(j)==t_INT) { long js = itos_or_0(j); GEN j37; if (js==-32768) { *s0 = mkfracss(-1156,539); return 11; } if (js==-121) { *jt = stoi(-24729001) ; *jtp = mkfracss(4973,5633); *s0 = mkfracss(-1961682050,1204555087); return 11;} if (js==-24729001) { *jt = stoi(-121); *jtp = mkfracss(5633,4973); *s0 = mkfracss(-1961682050,1063421347); return 11;} if (js==-884736) { *s0 = mkfracss(-1100,513); return 19; } j37 = negi(uu32toi(37876312,1780746325)); if (js==-9317) { *jt = j37; *jtp = mkfracss(1984136099,496260169); *s0 = mkfrac(negi(uu32toi(457100760,4180820796UL)), uu32toi(89049913, 4077411069UL)); return 37; } if (equalii(j, j37)) { *jt = stoi(-9317); *jtp = mkfrac(utoi(496260169),utoi(1984136099UL)); *s0 = mkfrac(negi(uu32toi(41554614,2722784052UL)), uu32toi(32367030,2614994557UL)); return 37; } if (js==-884736000) { *s0 = mkfracss(-1073708,512001); return 43; } if (equalii(j, negi(powuu(5280,3)))) { *s0 = mkfracss(-176993228,85184001); return 67; } if (equalii(j, negi(powuu(640320,3)))) { *s0 = mkfrac(negi(uu32toi(72512,1969695276)), uu32toi(35374,1199927297)); return 163; } } else { GEN j1 = mkfracss(-297756989,2); GEN j2 = mkfracss(-882216989,131072); if (gequal(j, j1)) { *jt = j2; *jtp = mkfracss(1503991,2878441); *s0 = mkfrac(negi(uu32toi(121934,548114672)),uu32toi(77014,117338383)); return 17; } if (gequal(j, j2)) { *jt = j1; *jtp = mkfracss(2878441,1503991); *s0 = mkfrac(negi(uu32toi(121934,548114672)),uu32toi(40239,4202639633UL)); return 17; } } return 0; } static GEN nfmkisomat(GEN nf, ulong p, GEN T) { return mkvec2(etree_list(nf,T), distmat_pow(etree_distmat(T),p)); } static GEN mkisomat(ulong p, GEN T) { return nfmkisomat(NULL, p, T); } static GEN mkisomatdbl(ulong p, GEN T, ulong p2, GEN T2, long flag) { GEN v = mkisomat(p,T); return isomatdbl(NULL, gel(v,1), gel(v,2), p2, T2, flag); } /*See M.A Kenku, On the number of Q-isomorphism classes of elliptic curves in * each Q-isogeny class, Journal of Number Theory Volume 15, Issue 2, * October 1982, pp 199-202, * http://www.sciencedirect.com/science/article/pii/0022314X82900257 */ enum { _2 = 1, _3 = 2, _5 = 4, _7 = 8, _13 = 16 }; static ulong ellQ_goodl(GEN E) { forprime_t T; long i, CM = ellQ_get_CM(E); ulong mask = 31; GEN disc = ell_get_disc(E); pari_sp av = avma; u_forprime_init(&T, 17UL,ULONG_MAX); for(i=1; mask && i<=20; i++) { ulong p = u_forprime_next(&T); if (umodiu(disc,p)==0) i--; else { long t = ellap_CM_fast(E, p, CM), D = t*t - 4*p; if (t%2) mask &= ~_2; if ((mask & _3) && kross(D,3)==-1) mask &= ~_3; if ((mask & _5) && kross(D,5)==-1) mask &= ~_5; if ((mask & _7) && kross(D,7)==-1) mask &= ~_7; if ((mask &_13) && kross(D,13)==-1) mask &= ~_13; } } return gc_ulong(av, mask); } static long ellQ_goodl_l(GEN E, long l) { forprime_t T; long i; GEN disc = ell_get_disc(E); pari_sp av; u_forprime_init(&T, 17UL, ULONG_MAX); av = avma; for (i = 1; i <= 20; i++, set_avma(av)) { ulong p = u_forprime_next(&T); long t; if (umodiu(disc,p)==0) { i--; continue; } t = itos(ellap(E, utoipos(p))); if (l==2) { if (odd(t)) return 0; } else { long D = t*t - 4*p; if (kross(D,l) == -1) return 0; } } return 1; } static GEN ellnf_goodl_l(GEN E, GEN v) { forprime_t T; long i, lv = lg(v); GEN nf = ellnf_get_nf(E), disc = ell_get_disc(E), w = const_F2v(lv-1); pari_sp av; u_forprime_init(&T, 17UL,ULONG_MAX); av = avma; for (i = 1; i <= 20; i++, set_avma(av)) { ulong p = u_forprime_next(&T); GEN pr = idealprimedec(nf, utoipos(p)); long t, j, k, g = lg(pr)-1; for (j = 1; j <= g; j++) { GEN prj = gel(pr, j); if (nfval(nf, disc, prj)) {i--; continue;} t = itos(ellap(E, prj)); for(k = 1; k < lv; k++) { GEN l = gel(v,k); if (equaliu(l,2)) { if (odd(t)) F2v_clear(w, k); } else { GEN D = subii(sqrs(t), shifti(pr_norm(prj),2)); if (kronecker(D,l)==-1) F2v_clear(w, k); } } } } return w; } static GEN ellnf_charpoly(GEN E, GEN pr) { return deg2pol_shallow(gen_1, negi(ellap(E,pr)), pr_norm(pr), 0); } static GEN starlaw(GEN p, GEN q) { GEN Q = RgX_homogenize(RgX_recip(q), 1); return ZX_ZXY_resultant(p, Q); } static GEN startor(GEN p, long r) { GEN xr = pol_xn(r, 0), psir = gsub(xr, gen_1); return gsubstpol(starlaw(p, psir),xr,pol_x(0)); } static GEN stariter_easy(GEN E, GEN p) { GEN nf = ellnf_get_nf(E), dec = idealprimedec(nf, p); long d = nf_get_degree(nf), l = lg(dec), i, k; GEN R, starl = deg1pol_shallow(gen_1, gen_m1, 0); for (i=1; i < l; i++) { GEN pr = gel(dec,i), q = ellnf_charpoly(E, pr); starl = starlaw(starl, startor(q, 12*pr_get_e(pr))); } for (k = 0, R = p; 2*k <= d; k++) R = mulii(R, poleval(starl, powiu(p,12*k))); return R; } /* pr^h assumed principal */ static GEN idealgen_minpoly(GEN bnf, GEN pr, GEN h) { GEN e = isprincipalfact(bnf, NULL, mkvec(pr), mkvec(h), nf_GEN); return minpoly(basistoalg(bnf, gel(e,2)), 0); } static GEN stariter(GEN p, long r) { GEN starl = deg1pol_shallow(gen_1, gen_m1, 0); long i; for (i = 1; i <= r; i++) starl = starlaw(starl, p); return starl; } static GEN stariter_hard(GEN E, GEN bnf, GEN pr) { GEN nf = bnf_get_nf(bnf); long k, d = nf_get_degree(nf), d2 = d>>1; GEN h = cyc_get_expo(bnf_get_cyc(bnf)); /* could use order of pr in Cl_K */ GEN pol = idealgen_minpoly(bnf, pr, h); GEN S = startor(pol,12), P = gen_1, polchar; for (k = 0; k <= d2; k++) P = gmul(P, stariter(S,k)); polchar = ellnf_charpoly(E, pr); return ZX_resultant(startor(polchar,12*itou(h)), P); } /* Based on a GP script by Nicolas Billerey and Theorems 2.4 and 2.8 of * N. Billerey, Criteres d'irreductibilite pour les representations des * courbes elliptiques, Int. J. Number Theory 7 (2011), no. 4, 1001-1032. */ static GEN ellnf_prime_degree_hard(GEN E, GEN bad) { GEN nf = ellnf_get_nf(E), bnf = ellnf_get_bnf(E), R = gen_0; forprime_t T; long i; if (!bnf) bnf = bnfinit0(nf,1,NULL,DEFAULTPREC); u_forprime_init(&T, 5UL, ULONG_MAX); for (i = 1; i <= 20; i++) { long j, lpr; GEN pri; ulong p = u_forprime_next(&T); if (dvdiu(bad, p)) { i--; continue; } pri = idealprimedec(nf,utoi(p)); lpr = lg(pri); for(j = 1; j < lpr; j++) { GEN R0 = stariter_hard(E,bnf,gel(pri,j)), r; R = gcdii(R, mului(p, R0)); if (Z_issquareall(R, &r)) R = r; } } return R; } /* Based on a GP script by Nicolas Billerey and Theorems 2.4 and 2.8 of * N. Billerey, Criteres d'irreductibilite pour les representations des * courbes elliptiques, Int. J. Number Theory 7 (2011), no. 4, 1001-1032. */ static GEN ellnf_prime_degree_easy(GEN E, GEN bad) { forprime_t T; long i; GEN B = gen_0; u_forprime_init(&T, 5UL,ULONG_MAX); for (i = 1; i <= 20; i++) { ulong p = u_forprime_next(&T); GEN b; if (dvdiu(bad, p)) { i--; continue; } B = gcdii(B, stariter_easy(E, utoipos(p))); if (Z_issquareall(B, &b)) B = b; } return B; } static GEN ellnf_prime_degree(GEN E) { GEN nf = ellnf_get_nf(E), nf_bad = nf_get_ramified_primes(nf); GEN g = ellglobalred(E); GEN N = idealnorm(nf,gel(g,1)), Nfa = prV_primes(gmael(g,4,1)); GEN bad = mulii(N, nf_get_disc(nf)), P; GEN B = ellnf_prime_degree_easy(E, bad); if (!signe(B)) { B = ellnf_prime_degree_hard(E, bad); if (!signe(B)) { long D = elliscm(E); if (!D || isintzero(nfisincl(quadpoly(stoi(D)), ellnf_get_nf(E)))) pari_err_IMPL("ellisomat, very hard case"); return stoi(D); } } if (!signe(B)) return NULL; B = muliu(absi(B), 6); P = ZV_union_shallow(ZV_union_shallow(Nfa,nf_bad), gel(Z_factor(B),1)); return vec_to_vecsmall(RgV_F2v_extract_shallow(P, ellnf_goodl_l(E, P))); } static GEN ellQ_isomat(GEN E, long flag) { GEN K = NULL, T2 = NULL, T3 = NULL, T5, T7, T13; ulong good; long n2, n3, n5, n7, n13; GEN jt, jtp, s0, j = ell_get_j(E); long l = ellQ_exceptional_iso(j, &jt, &jtp, &s0); if (l) { #if 1 return mkisomat(l, ellisograph_dummy(E, l, jt, jtp, s0, flag)); #else return mkisomat(l, ellisograph_p(K, E, l), flag); #endif } good = ellQ_goodl(ellintegralmodel(E,NULL)); if (good & _2) { T2 = ellisograph_p(K, E, 2, flag); n2 = etree_nbnodes(T2); if (n2>4 || gequalgs(j, 1728) || gequalgs(j, 287496)) return mkisomat(2, T2); } else n2 = 1; if (good & _3) { T3 = ellisograph_p(K, E, 3, flag); n3 = etree_nbnodes(T3); if (n3>1 && n2==2) return mkisomatdbl(3,T3,2,T2, flag); if (n3==2 && n2>1) return mkisomatdbl(2,T2,3,T3, flag); if (n3>2 || gequal0(j)) return mkisomat(3, T3); } else n3 = 1; if (good & _5) { T5 = ellisograph_p(K, E, 5, flag); n5 = etree_nbnodes(T5); if (n5>1 && n2>1) return mkisomatdbl(2,T2,5,T5, flag); if (n5>1 && n3>1) return mkisomatdbl(3,T3,5,T5, flag); if (n5>1) return mkisomat(5, T5); } else n5 = 1; if (good & _7) { T7 = ellisograph_p(K, E, 7, flag); n7 = etree_nbnodes(T7); if (n7>1 && n2>1) return mkisomatdbl(2,T2,7,T7, flag); if (n7>1 && n3>1) return mkisomatdbl(3,T3,7,T7, flag); if (n7>1) return mkisomat(7,T7); } else n7 = 1; if (n2>1) return mkisomat(2,T2); if (n3>1) return mkisomat(3,T3); if (good & _13) { T13 = ellisograph_p(K, E, 13, flag); n13 = etree_nbnodes(T13); if (n13>1) return mkisomat(13,T13); } else n13 = 1; return mkvec2(mkvec(ellisograph_a4a6(E,flag)), matid(1)); } static long fill_LM(GEN LM, GEN L, GEN M, GEN z, long k) { GEN Li = gel(LM,1), Mi1 = gmael(LM,2,1); long j, m = lg(Li); for (j = 2; j < m; j++) { GEN d = gel(Mi1,j); gel(L, k) = gel(Li,j); gel(M, k) = z? mulii(d,z): d; k++; } return k; } static GEN ellnf_isocrv(GEN nf, GEN E, GEN v, GEN PE, long flag) { long i, l, lv, n, k; GEN L, M, LE = cgetg_copy(v,&lv), e = ellisograph_a4a6(E, flag); for (i = n = 1; i < lv; i++) { ulong p = uel(v,i); GEN T = isograph_p(nf, e, p, gel(PE,i), flag); GEN LM = nfmkisomat(nf, p, T); gel(LE,i) = LM; n *= lg(gel(LM,1)) - 1; } L = cgetg(n+1,t_VEC); gel(L,1) = e; M = cgetg(n+1,t_COL); gel(M,1) = gen_1; for (i = 1, k = 2; i < lv; i++) { ulong p = uel(v,i); GEN P = gel(PE,i); long kk = k; k = fill_LM(gel(LE,i), L, M, NULL, k); for (l = 2; l < kk; l++) { GEN T = isograph_p(nf, gel(L,l), p, P, flag); GEN LMe = nfmkisomat(nf, p, T); k = fill_LM(LMe, L, M, gel(M,l), k); } } return mkvec2(L, M); } static long nfispower_quo(GEN nf, long d, GEN a, GEN b) { if (gequal(a,b)) return 1; return nfispower(nf, nfdiv(nf, a, b), d, NULL); } static long isomat_eq(GEN nf, GEN e1, GEN e2) { if (gequal(e1,e2)) return 1; if (!gequal(gel(e1,3), gel(e2,3))) return 0; if (gequal0(gel(e1,3))) return nfispower_quo(nf,6,gel(e1,2),gel(e2,2)); if (gequalgs(gel(e1,3),1728)) return nfispower_quo(nf,4,gel(e1,1),gel(e2,1)); return nfispower_quo(nf,2,gmul(gel(e1,1),gel(e2,2)),gmul(gel(e1,2),gel(e2,1))); } static long isomat_find(GEN nf, GEN e, GEN L) { long i, l = lg(L); for (i=1; i 1) pari_err_FLAG("ellisomat"); if (p < 0) pari_err_PRIME("ellisomat", stoi(p)); if (p == 1) { flag = 1; p = 0; } /* for backward compatibility */ checkell(E); switch(ell_get_type(E)) { case t_ELL_Q: if (p) good = ellQ_goodl_l(E, p); break; case t_ELL_NF: if (p) good = F2v_coeff(ellnf_goodl_l(E, mkvecs(p)), 1); nf = ellnf_get_nf(E); if (nf_get_varn(nf) <= 1 - flag) pari_err_PRIORITY("ellisomat", nf_get_pol(nf), "<=", 1 - flag); break; default: pari_err_TYPE("ellisomat",E); } if (!good) r = mkvec2(mkvec(ellisograph_a4a6(E, flag)), matid(1)); else { if (p) r = nfmkisomat(nf, p, ellisograph_p(nf, E, p, flag)); else r = nf? ellnf_isomat(E, flag): ellQ_isomat(E, flag); if (typ(r) == t_VEC) gel(r,1) = list_to_crv(gel(r,1)); } return gerepilecopy(av, r); } static GEN get_isomat(GEN v) { GEN M, vE, wE; long i, l; if (typ(v) != t_VEC) return NULL; if (checkell_i(v)) { if (ell_get_type(v) != t_ELL_Q) return NULL; v = ellisomat(v,0,1); wE = gel(v,1); l = lg(wE); M = gel(v,2); } else { if (lg(v) != 3) return NULL; vE = gel(v,1); l = lg(vE); M = gel(v,2); if (typ(M) != t_MAT || !RgM_is_ZM(M)) return NULL; if (typ(vE) != t_VEC || l == 1) return NULL; if (lg(gel(vE,1)) == 3) wE = shallowcopy(vE); else { /* [[a4,a6],f,g] */ wE = cgetg_copy(vE,&l); for (i = 1; i < l; i++) gel(wE,i) = gel(gel(vE,i),1); } } /* wE a vector of [a4,a6] */ for (i = 1; i < l; i++) { GEN e = ellinit(gel(wE,i), gen_1, DEFAULTPREC); GEN E = ellminimalmodel(e, NULL); obj_free(e); gel(wE,i) = E; } return mkvec2(wE, M); } GEN ellweilcurve(GEN E, GEN *ms) { pari_sp av = avma; GEN vE = get_isomat(E), vL, Wx, W, XPM, Lf, Cf; long i, l; if (!vE) pari_err_TYPE("ellweilcurve",E); vE = gel(vE,1); l = lg(vE); Wx = msfromell(vE, 0); W = gel(Wx,1); XPM = gel(Wx,2); /* lattice attached to the Weil curve in the isogeny class */ Lf = mslattice(W, gmael(XPM,1,3)); Cf = ginv(Lf); /* left-inverse */ vL = cgetg(l, t_VEC); for (i=1; i < l; i++) { GEN c, Ce, Le = gmael(XPM,i,3); Ce = Q_primitive_part(RgM_mul(Cf, Le), &c); Ce = ZM_snf(Ce); if (c) { Ce = ZC_Q_mul(Ce,c); settyp(Ce,t_VEC); } gel(vL,i) = Ce; } for (i = 1; i < l; i++) obj_free(gel(vE,i)); vE = mkvec2(vE, vL); if (!ms) return gerepilecopy(av, vE); *ms = Wx; return gc_all(av, 2, &vE, ms); } GEN ellisotree(GEN E) { pari_sp av = avma; GEN L = get_isomat(E), vE, adj, M; long i, j, n; if (!L) pari_err_TYPE("ellisotree",E); vE = gel(L,1); adj = gel(L,2); n = lg(vE)-1; L = cgetg(n+1, t_VEC); for (i = 1; i <= n; i++) gel(L,i) = ellR_area(gel(vE,i), DEFAULTPREC); M = zeromatcopy(n,n); for (i = 1; i <= n; i++) for (j = i+1; j <= n; j++) { GEN p = gcoeff(adj,i,j); if (!isprime(p)) continue; /* L[i] / L[j] = p or 1/p; p iff E[i].lattice \subset E[j].lattice */ if (gcmp(gel(L,i), gel(L,j)) > 0) gcoeff(M,i,j) = p; else gcoeff(M,j,i) = p; } for (i = 1; i <= n; i++) obj_free(gel(vE,i)); return gerepilecopy(av, mkvec2(vE,M)); } /* Shortest path between x and y on the adjencc graph of A-A~ * Dijkstra algorithm. */ static GEN shortest_path(GEN A, long x, long y) { GEN C, v, w; long n = lg(A)-1, i, l, z, t, m; v = const_vecsmall(n, n); v[x] = 0; w = const_vecsmall(n, 0); for (l = 1; l < n; l++) for (z = 1; z <= n; z++) { if (v[z] != l-1) continue; for (t = 1; t <= n; t++) if (!gequal(gcoeff(A,z,t),gcoeff(A,t,z)) && v[t]>l) { v[t]=l; w[t]=z; } } m = v[y]+1; if (m > n) return NULL; C = cgetg(m+1, t_VECSMALL); for (i = 1; i <= m; i++) { C[m+1-i] = y; y = w[y]; } return C; } static GEN path_to_manin(GEN A, long i, long k) { GEN C = shortest_path(A, i, k); long j, lC = lg(C); GEN c = gen_1; for (j = 1; j < lC-1; j++) { GEN t = gsub(gcoeff(A,C[j], C[j+1]), gcoeff(A,C[j+1], C[j])); if (signe(t) < 0) c = gmul(c, gneg(t)); } return c; } GEN ellmaninconstant(GEN E) { pari_sp av = avma; GEN M, A, vS, L; long i, k, lvS, is_ell = checkell_i(E); L = is_ell ? ellisomat(E,0,1): E; A = gel(ellisotree(L), 2); vS = gel(ellweilcurve(L, NULL), 2); lvS = lg(vS); for (i = 1; i < lvS; i++) if (equali1(gmael(vS,i,1) ) && equali1(gmael(vS,i,2))) break; if (is_ell) return gerepileupto(av, path_to_manin(A, i, 1)); M = cgetg(lvS, t_VEC); for (k = 1; k < lvS; k++) gel(M,k) = path_to_manin(A, i, k); return gerepileupto(av, M); } pari-2.17.2/src/basemath/bibli1.c0000644000175000017500000017227614760123736015075 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /********************************************************************/ /** **/ /** LLL Algorithm and close friends **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_qf /********************************************************************/ /** QR Factorization via Householder matrices **/ /********************************************************************/ static int no_prec_pb(GEN x) { return (typ(x) != t_REAL || realprec(x) > DEFAULTPREC || expo(x) < DEFAULTPREC>>1); } /* Find a Householder transformation which, applied to x[k..#x], zeroes * x[k+1..#x]; fill L = (mu_{i,j}). Return 0 if precision problem [obtained * a 0 vector], 1 otherwise */ static int FindApplyQ(GEN x, GEN L, GEN B, long k, GEN Q, long prec) { long i, lx = lg(x)-1; GEN x2, x1, xd = x + (k-1); x1 = gel(xd,1); x2 = mpsqr(x1); if (k < lx) { long lv = lx - (k-1) + 1; GEN beta, Nx, v = cgetg(lv, t_VEC); for (i=2; i 1) r = ApplyAllQ(Q, r, j); if (!FindApplyQ(r, L, B, j, Q, prec)) return 0; } *pB = B; *pQ = Q; *pL = L; return 1; } /* x a square t_MAT with t_INT / t_REAL entries and maximal rank. Return * qfgaussred(x~*x) */ GEN gaussred_from_QR(GEN x, long prec) { long j, k = lg(x)-1; GEN B, Q, L; if (!QR_init(x, &B,&Q,&L, prec)) return NULL; for (j=1; j 0; j--) { GEN c = gdiv( RgV_dotproduct(b, gel(G,j)), gel(N,j) ); long e; c = grndtoi(c,&e); if (e >= 0) return NULL; if (signe(c)) b = RgC_sub(b, RgC_Rg_mul(gel(B,j), c)); gel(C,j) = c; } return C; } /********************************************************************/ /** **/ /** LLL ALGORITHM **/ /** **/ /********************************************************************/ /* Def: a matrix M is said to be -partially reduced- if | m1 +- m2 | >= |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; 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 (gc_needed(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)); } } } /* 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(double b, double x, double rho, long d, long dim, long delta, long t) { double cond = delta * (d * (delta+1) - 2*b*dim + rho * (delta-1 + 2*t)) + x*dim*(dim - 1); if (DEBUGLEVEL >= 4) err_printf("delta = %d, t = %d (%.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), dim; GEN P0 = leading_coeff(P); double logN = gtodouble(glog(N, DEFAULTPREC)), x, b, rho; x = gtodouble(glog(X, DEFAULTPREC)) / logN; b = B? gtodouble(glog(B, DEFAULTPREC)) / logN: 1.; if (x * d >= b * b) pari_err_OVERFLOW("zncoppersmith [bound too large]"); /* TODO : remove P0 completely */ rho = is_pm1(P0)? 0: gtodouble(glog(P0, DEFAULTPREC)) / logN; /* Enumerate (delta,t) by increasing lattice dimension */ for(dim = d + 1;; dim++) { long delta, t; /* dim = d*delta + t in the loop */ for (delta = 0, t = dim; t >= 0; delta++, t -= d) if (check(b,x,rho,d,dim,delta,t)) { *pdelta = delta; *pt = t; return; } } } static int sol_OK(GEN x, GEN N, GEN B) { return B? (cmpii(gcdii(x,N),B) >= 0): dvdii(x,N); } /* deg(P) > 0, x >= 0. Find all j such that gcd(P(j), N) >= B, |j| <= x */ static GEN do_exhaustive(GEN P, GEN N, long x, GEN B) { GEN Pe, Po, sol = vecsmalltrunc_init(2*x + 2); pari_sp av; long j; RgX_even_odd(P, &Pe,&Po); av = avma; if (sol_OK(gel(P,2), N,B)) vecsmalltrunc_append(sol, 0); for (j = 1; j <= x; j++, set_avma(av)) { GEN j2 = sqru(j), E = FpX_eval(Pe,j2,N), O = FpX_eval(Po,j2,N); if (sol_OK(addmuliu(E,O,j), N,B)) vecsmalltrunc_append(sol, j); if (sol_OK(submuliu(E,O,j), N,B)) vecsmalltrunc_append(sol,-j); } vecsmall_sort(sol); return zv_to_ZV(sol); } /* General Coppersmith, look for a root x0 <= p, p >= B, p | N, |x0| <= X. * B = N coded as NULL */ GEN zncoppersmith(GEN P, GEN N, GEN X, GEN B) { GEN Q, R, N0, M, sh, short_pol, *Xpowers, sol, nsp, cP, Z; long delta, i, j, row, d, l, t, dim, bnd = 10; const ulong X_SMALL = 1000; pari_sp av = avma; if (typ(P) != t_POL || !RgX_is_ZX(P)) pari_err_TYPE("zncoppersmith",P); if (typ(N) != t_INT) pari_err_TYPE("zncoppersmith",N); if (typ(X) != t_INT) { X = gfloor(X); if (typ(X) != t_INT) pari_err_TYPE("zncoppersmith",X); } if (signe(X) < 0) pari_err_DOMAIN("zncoppersmith", "X", "<", gen_0, X); P = FpX_red(P, N); d = degpol(P); if (d == 0) { set_avma(av); return cgetg(1, t_VEC); } if (d < 0) pari_err_ROOTS0("zncoppersmith"); if (B && typ(B) != t_INT) B = gceil(B); if (abscmpiu(X, X_SMALL) <= 0) return gerepileupto(av, do_exhaustive(P, N, itos(X), B)); if (B && equalii(B,N)) B = NULL; if (B) bnd = 1; /* bnd-hack is only for the case B = N */ cP = gel(P,d+2); if (!gequal1(cP)) { GEN r, z; gel(P,d+2) = cP = bezout(cP, N, &z, &r); for (j = 0; j < d; j++) gel(P,j+2) = Fp_mul(gel(P,j+2), z, N); if (!is_pm1(cP)) { P = Q_primitive_part(P, &cP); if (cP) { N = diviiexact(N,cP); B = gceil(gdiv(B, cP)); } } } if (DEBUGLEVEL >= 2) err_printf("Modified P: %Ps\n", P); choose_params(P, N, X, B, &delta, &t); if (DEBUGLEVEL >= 2) err_printf("Init: trying delta = %d, t = %d\n", delta, t); for(;;) { dim = d * delta + t; /* TODO: In case of failure do not recompute the full vector */ Xpowers = (GEN*)new_chunk(dim + 1); Xpowers[0] = gen_1; for (j = 1; j <= dim; j++) Xpowers[j] = mulii(Xpowers[j-1], X); /* TODO: in case of failure, use the part of the matrix already computed */ M = zeromatcopy(dim,dim); /* Rows of M correspond to the polynomials * N^delta, N^delta Xi, ... N^delta (Xi)^d-1, * N^(delta-1)P(Xi), N^(delta-1)XiP(Xi), ... N^(delta-1)P(Xi)(Xi)^d-1, * ... * P(Xi)^delta, XiP(Xi)^delta, ..., P(Xi)^delta(Xi)^t-1 */ for (j = 1; j <= d; j++) gcoeff(M, j, j) = gel(Xpowers,j-1); /* P-part */ if (delta) row = d + 1; else row = 0; Q = P; for (i = 1; i < delta; i++) { for (j = 0; j < d; j++,row++) for (l = j + 1; l <= row; l++) gcoeff(M, l, row) = mulii(Xpowers[l-1], gel(Q,l-j+1)); Q = ZX_mul(Q, P); } for (j = 0; j < t; row++, j++) for (l = j + 1; l <= row; l++) gcoeff(M, l, row) = mulii(Xpowers[l-1], gel(Q,l-j+1)); /* N-part */ row = dim - t; N0 = N; while (row >= 1) { for (j = 0; j < d; j++,row--) for (l = 1; l <= row; l++) gcoeff(M, l, row) = mulii(gmael(M, row, l), N0); if (row >= 1) N0 = mulii(N0, N); } /* Z is the upper bound for the L^1 norm of the polynomial, ie. N^delta if B = N, B^delta otherwise */ if (B) Z = powiu(B, delta); else Z = N0; if (DEBUGLEVEL >= 2) { if (DEBUGLEVEL >= 6) err_printf("Matrix to be reduced:\n%Ps\n", M); err_printf("Entering LLL\nbitsize bound: %ld\n", expi(Z)); err_printf("expected shvector bitsize: %ld\n", expi(ZM_det_triangular(M))/dim); } sh = ZM_lll(M, 0.75, LLL_INPLACE); /* Take the first vector if it is non constant */ short_pol = gel(sh,1); if (ZV_isscalar(short_pol)) short_pol = gel(sh, 2); nsp = gen_0; for (j = 1; j <= dim; j++) nsp = addii(nsp, absi_shallow(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 */ if (++t == d) { delta++; t = 1; } if (DEBUGLEVEL >= 2) err_printf("Increasing dim, delta = %d t = %d\n", delta, t); } bnd = itos(divii(nsp, Z)) + 1; while (!signe(gel(short_pol,dim))) dim--; R = cgetg(dim + 2, t_POL); R[1] = P[1]; for (j = 1; j <= dim; j++) gel(R,j+1) = diviiexact(gel(short_pol,j), Xpowers[j-1]); gel(R,2) = subii(gel(R,2), mului(bnd - 1, N0)); sol = cgetg(1, t_VEC); for (i = -bnd + 1; i < bnd; i++) { GEN r = nfrootsQ(R); if (DEBUGLEVEL >= 2) err_printf("Roots: %Ps\n", r); for (j = 1; j < lg(r); j++) { GEN z = gel(r,j); if (typ(z) == t_INT && sol_OK(FpX_eval(P,z,N), N,B)) sol = shallowconcat(sol, z); } if (i < bnd) gel(R,2) = addii(gel(R,2), Z); } return gerepileupto(av, ZV_sort_uniq(sol)); } /********************************************************************/ /** **/ /** LINEAR & ALGEBRAIC DEPENDENCE **/ /** **/ /********************************************************************/ static int real_indep(GEN re, GEN im, long bit) { GEN d = gsub(gmul(gel(re,1),gel(im,2)), gmul(gel(re,2),gel(im,1))); return (!gequal0(d) && gexpo(d) > - bit); } GEN lindepfull_bit(GEN x, long bit) { long lx = lg(x), ly, i, j; GEN re, im, M; if (! is_vec_t(typ(x))) pari_err_TYPE("lindep2",x); if (lx <= 2) { if (lx == 2 && gequal0(x)) return matid(1); return NULL; } re = real_i(x); im = imag_i(x); /* independent over R ? */ if (lx == 3 && real_indep(re,im,bit)) return NULL; if (gequal0(im)) im = NULL; ly = im? lx+2: lx+1; M = cgetg(lx,t_MAT); for (i=1; i 0) x = gdiv(x, pol_xn(v, vx)); else x = gmul(x, pol_xn(-v, vx)); /* all t_SER have valuation >= 0 */ for (i=1; i 1 */ long t = typ(gel(x,1)), h = lg(gel(x,1)); GEN m = cgetg(l, t_MAT); for (i = 1; i < l; i++) { GEN y = gel(x,i); if (lg(y) != h || typ(y) != t) pari_err_TYPE("lindep",x); if (t != t_COL) y = shallowtrans(y); /* Sigh */ gel(m,i) = y; } return gerepileupto(av, deplin(m)); } GEN lindep(GEN x) { return lindep2(x, 0); } GEN lindep0(GEN x,long bit) { long i, tx = typ(x); if (tx == t_MAT) return deplin(x); if (! is_vec_t(tx)) pari_err_TYPE("lindep",x); for (i = 1; i < lg(x); i++) switch(typ(gel(x,i))) { case t_PADIC: return lindep_padic(x); case t_POL: case t_RFRAC: case t_SER: return lindep_Xadic(x); case t_VEC: case t_COL: return vec_lindep(x); } return lindep2(x, bit); } GEN algdep0(GEN x, long n, long bit) { long tx = typ(x), i; pari_sp av; GEN y; if (! is_scalar_t(tx)) pari_err_TYPE("algdep0",x); if (tx == t_POLMOD) { av = avma; y = minpoly(x, 0); return (degpol(y) > n)? gc_const(av, gen_1): y; } if (gequal0(x)) return pol_x(0); if (n <= 0) { if (!n) return gen_1; pari_err_DOMAIN("algdep", "degree", "<", gen_0, stoi(n)); } av = avma; y = cgetg(n+2,t_COL); gel(y,1) = gen_1; gel(y,2) = x; /* n >= 1 */ for (i=3; i<=n+1; i++) gel(y,i) = gmul(gel(y,i-1),x); if (typ(x) == t_PADIC) y = lindep_padic(y); else y = lindep2(y, bit); if (lg(y) == 1) pari_err(e_DOMAIN,"algdep", "degree(x)",">", stoi(n), x); y = RgV_to_RgX(y, 0); if (signe(leading_coeff(y)) > 0) return gerepilecopy(av, y); return gerepileupto(av, ZX_neg(y)); } GEN algdep(GEN x, long n) { return algdep0(x,n,0); } static GEN sertomat(GEN S, long p, long r, long vy) { long n, m; GEN v = cgetg(r*p+1, t_VEC); /* v[r*n+m+1] = s^n * y^m */ /* n = 0 */ for (m = 0; m < r; m++) gel(v, m+1) = pol_xn(m, vy); for(n=1; n < p; n++) for (m = 0; m < r; m++) { GEN c = gel(S,n); if (m) { c = shallowcopy(c); setvalser(c, valser(c) + m); } gel(v, r*n + m + 1) = c; } return v; } GEN seralgdep(GEN s, long p, long r) { pari_sp av = avma; long vy, i, n, prec; GEN S, v, D; if (typ(s) != t_SER) pari_err_TYPE("seralgdep",s); if (p <= 0) pari_err_DOMAIN("seralgdep", "p", "<=", gen_0, stoi(p)); if (r < 0) pari_err_DOMAIN("seralgdep", "r", "<", gen_0, stoi(r)); if (is_bigint(addiu(muluu(p, r), 1))) pari_err_OVERFLOW("seralgdep"); vy = varn(s); if (!vy) pari_err_PRIORITY("seralgdep", s, ">", 0); r++; p++; prec = valser(s) + lg(s)-2; if (r > prec) r = prec; S = cgetg(p+1, t_VEC); gel(S, 1) = s; for (i = 2; i <= p; i++) gel(S,i) = gmul(gel(S,i-1), s); v = sertomat(S, p, r, vy); D = lindep_Xadic(v); if (lg(D) == 1) { set_avma(av); return gen_0; } v = cgetg(p+1, t_VEC); for (n = 0; n < p; n++) gel(v, n+1) = RgV_to_RgX(vecslice(D, r*n+1, r*n+r), vy); return gerepilecopy(av, RgV_to_RgX(v, 0)); } GEN serdiffdep(GEN s, long p, long r) { pari_sp av = avma; long vy, i, n, prec; GEN P, S, v, D; if (typ(s) != t_SER) pari_err_TYPE("serdiffdep",s); if (p <= 0) pari_err_DOMAIN("serdiffdep", "p", "<=", gen_0, stoi(p)); if (r < 0) pari_err_DOMAIN("serdiffdep", "r", "<", gen_0, stoi(r)); if (is_bigint(addiu(muluu(p, r), 1))) pari_err_OVERFLOW("serdiffdep"); vy = varn(s); if (!vy) pari_err_PRIORITY("serdiffdep", s, ">", 0); r++; p++; prec = valser(s) + lg(s)-2; if (r > prec) r = prec; S = cgetg(p+1, t_VEC); gel(S, 1) = s; for (i = 2; i <= p; i++) gel(S,i) = derivser(gel(S,i-1)); v = sertomat(S, p, r, vy); D = lindep_Xadic(v); if (lg(D) == 1) { set_avma(av); return gen_0; } P = RgV_to_RgX(vecslice(D, 1, r), vy); v = cgetg(p, t_VEC); for (n = 1; n < p; n++) gel(v, n) = RgV_to_RgX(vecslice(D, r*n+1, r*n+r), vy); return gerepilecopy(av, mkvec2(RgV_to_RgX(v, 0), gneg(P))); } /* FIXME: could precompute ZM_lll attached to V[2..] */ static GEN lindepcx(GEN V, long bit) { GEN Vr = real_i(V), Vi = imag_i(V); if (gexpo(Vr) < -bit) V = Vi; else if (gexpo(Vi) < -bit) V = Vr; return lindepfull_bit(V, bit); } /* c floating point t_REAL or t_COMPLEX, T ZX, recognize in Q[x]/(T). * V helper vector (containing complex roots of T), MODIFIED */ static GEN cx_bestapprnf(GEN c, GEN T, GEN V, long bit) { GEN M, a, v = NULL; long i, l; gel(V,1) = gneg(c); M = lindepcx(V, bit); if (!M) pari_err(e_MISC, "cannot rationalize coeff in bestapprnf"); l = lg(M); a = NULL; for (i = 1; i < l; i ++) { v = gel(M,i); a = gel(v,1); if (signe(a)) break; } v = RgC_Rg_div(vecslice(v, 2, lg(M)-1), a); if (!T) return gel(v,1); v = RgV_to_RgX(v, varn(T)); l = lg(v); if (l == 2) return gen_0; if (l == 3) return gel(v,2); return mkpolmod(v, T); } static GEN bestapprnf_i(GEN x, GEN T, GEN V, long bit) { long i, l, tx = typ(x); GEN z; switch (tx) { case t_INT: case t_FRAC: return x; case t_REAL: case t_COMPLEX: return cx_bestapprnf(x, T, V, bit); case t_POLMOD: if (RgX_equal(gel(x,1),T)) return x; break; case t_POL: case t_SER: case t_VEC: case t_COL: case t_MAT: l = lg(x); z = cgetg(l, tx); for (i = 1; i < lontyp[tx]; i++) z[i] = x[i]; for (; i < l; i++) gel(z,i) = bestapprnf_i(gel(x,i), T, V, bit); return z; } pari_err_TYPE("mfcxtoQ", x); return NULL;/*LCOV_EXCL_LINE*/ } GEN bestapprnf(GEN x, GEN T, GEN roT, long prec) { pari_sp av = avma; long tx = typ(x), dT = 1, bit; GEN V; if (T) { if (typ(T) != t_POL) T = nf_get_pol(checknf(T)); else if (!RgX_is_ZX(T)) pari_err_TYPE("bestapprnf", T); dT = degpol(T); } if (is_rational_t(tx)) return gcopy(x); if (tx == t_POLMOD) { if (!T || !RgX_equal(T, gel(x,1))) pari_err_TYPE("bestapprnf",x); return gcopy(x); } if (roT) { long l = gprecision(roT); switch(typ(roT)) { case t_INT: case t_FRAC: case t_REAL: case t_COMPLEX: break; default: pari_err_TYPE("bestapprnf", roT); } if (prec < l) prec = l; } else if (!T) roT = gen_1; else { long n = poliscyclo(T); /* cyclotomic is an important special case */ roT = n? rootsof1u_cx(n,prec): gel(QX_complex_roots(T,prec), 1); } V = vec_prepend(gpowers(roT, dT-1), NULL); bit = prec2nbits_mul(prec, 0.8); return gerepilecopy(av, bestapprnf_i(x, T, V, bit)); } /********************************************************************/ /** **/ /** 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); *y = (double*) stack_malloc_align(s, sizeof(double)); *z = (double*) stack_malloc_align(s, sizeof(double)); *v = (double*) stack_malloc_align(s, sizeof(double)); for (i=1; ia = RgM_gtofp(a, DEFAULTPREC); r = qfgaussred_positive(qv->a); if (!r) { r = qfgaussred_positive(a); /* exact computation */ if (!r) err_minim(a); r = RgM_gtofp(r, DEFAULTPREC); } qv->r = r; qv->u = u; } static void forqfvec_init(struct qfvec *qv, GEN a) { forqfvec_init_dolll(qv, &a, 1); } static void forqfvec_i(void *E, long (*fun)(void *, GEN, GEN, double), struct qfvec *qv, GEN BORNE) { GEN x, a = qv->a, r = qv->r, u = qv->u; long n = lg(a)-1, i, j, k; double p,BOUND,*v,*y,*z,**q; const double eps = 1e-10; if (!BORNE) BORNE = gen_0; else { BORNE = gfloor(BORNE); if (typ(BORNE) != t_INT) pari_err_TYPE("minim0",BORNE); if (signe(BORNE) <= 0) return; } if (n == 0) return; minim_alloc(n+1, &q, &x, &y, &z, &v); for (j=1; j<=n; j++) { v[j] = rtodbl(gcoeff(r,j,j)); for (i=1; i (double)ULONG_MAX || (ulong)BOUND != (ulong)p) pari_err_PREC("forqfvec"); k = n; y[n] = z[n] = 0; x[n] = (long)sqrt(BOUND/v[n]); for(;;x[1]--) { do { if (k>1) { long l = k-1; z[l] = 0; for (j=k; j<=n; j++) z[l] += q[l][j]*x[j]; p = (double)x[k] + z[k]; y[l] = y[k] + p*p*v[k]; x[l] = (long)floor(sqrt((BOUND-y[l])/v[l])-z[l]); k = l; } for(;;) { p = (double)x[k] + z[k]; if (y[k] + p*p*v[k] <= BOUND) break; k++; x[k]--; } } while (k > 1); if (! x[1] && y[1]<=eps) break; p = (double)x[1] + z[1]; p = y[1] + p*p*v[1]; /* norm(x) */ if (fun(E, u, x, p)) break; } } void forqfvec(void *E, long (*fun)(void *, GEN, GEN, double), GEN a, GEN BORNE) { pari_sp av = avma; struct qfvec qv; forqfvec_init(&qv, a); forqfvec_i(E, fun, &qv, BORNE); set_avma(av); } struct qfvecwrap { void *E; long (*fun)(void *, GEN); }; static long forqfvec_wrap(void *E, GEN u, GEN x, double d) { pari_sp av = avma; struct qfvecwrap *W = (struct qfvecwrap *) E; (void) d; return gc_long(av, W->fun(W->E, ZM_zc_mul_canon(u, x))); } void forqfvec1(void *E, long (*fun)(void *, GEN), GEN a, GEN BORNE) { pari_sp av = avma; struct qfvecwrap wr; struct qfvec qv; wr.E = E; wr.fun = fun; forqfvec_init(&qv, a); forqfvec_i((void*) &wr, forqfvec_wrap, &qv, BORNE); set_avma(av); } void forqfvec0(GEN a, GEN BORNE, GEN code) { EXPRVOID_WRAP(code, forqfvec1(EXPR_ARGVOID, a, BORNE)) } enum { min_ALL = 0, min_FIRST, min_VECSMALL, min_VECSMALL2 }; /* Minimal vectors for the integral definite quadratic form: a. * Result u: * u[1]= Number of vectors of square norm <= BORNE * u[2]= maximum norm found * u[3]= list of vectors found (at most STOCKMAX, unless NULL) * * If BORNE = NULL: Minimal nonzero vectors. * flag = min_ALL, as above * flag = min_FIRST, exits when first suitable vector is found. * flag = min_VECSMALL, return a t_VECSMALL of (half) the number of vectors * for each norm * flag = min_VECSMALL2, same but count only vectors with even norm, and shift * the answer */ static GEN minim0_dolll(GEN a, GEN BORNE, GEN STOCKMAX, long flag, long dolll) { GEN x, u, r, L, gnorme; long n = lg(a)-1, i, j, k, s, maxrank, sBORNE; pari_sp av = avma, av1; double p,maxnorm,BOUND,*v,*y,*z,**q; const double eps = 1e-10; int stockall = 0; struct qfvec qv; if (!BORNE) sBORNE = 0; else { BORNE = gfloor(BORNE); if (typ(BORNE) != t_INT) pari_err_TYPE("minim0",BORNE); if (is_bigint(BORNE)) pari_err_PREC( "qfminim"); sBORNE = itos(BORNE); set_avma(av); if (sBORNE < 0) sBORNE = 0; } if (!STOCKMAX) { stockall = 1; maxrank = 200; } else { STOCKMAX = gfloor(STOCKMAX); if (typ(STOCKMAX) != t_INT) pari_err_TYPE("minim0",STOCKMAX); maxrank = itos(STOCKMAX); if (maxrank < 0) pari_err_TYPE("minim0 [negative number of vectors]",STOCKMAX); } switch(flag) { case min_VECSMALL: case min_VECSMALL2: if (sBORNE <= 0) return cgetg(1, t_VECSMALL); L = zero_zv(sBORNE); if (flag == min_VECSMALL2) sBORNE <<= 1; if (n == 0) return L; break; case min_FIRST: if (n == 0 || (!sBORNE && BORNE)) return cgetg(1,t_VEC); L = NULL; /* gcc -Wall */ break; case min_ALL: if (n == 0 || (!sBORNE && BORNE)) retmkvec3(gen_0, gen_0, cgetg(1, t_MAT)); L = new_chunk(1+maxrank); break; default: return NULL; } minim_alloc(n+1, &q, &x, &y, &z, &v); forqfvec_init_dolll(&qv, &a, dolll); av1 = avma; r = qv.r; u = qv.u; for (j=1; j<=n; j++) { v[j] = rtodbl(gcoeff(r,j,j)); for (i=1; i1) { long l = k-1; z[l] = 0; for (j=k; j<=n; j++) z[l] += q[l][j]*x[j]; p = (double)x[k] + z[k]; y[l] = y[k] + p*p*v[k]; x[l] = (long)floor(sqrt((BOUND-y[l])/v[l])-z[l]); k = l; } for(;;) { p = (double)x[k] + z[k]; if (y[k] + p*p*v[k] <= BOUND) break; k++; x[k]--; } } while (k > 1); if (! x[1] && y[1]<=eps) break; p = (double)x[1] + z[1]; p = y[1] + p*p*v[1]; /* norm(x) */ if (maxnorm >= 0) { if (p > maxnorm) maxnorm = p; } else { /* maxnorm < 0 : only look for minimal vectors */ pari_sp av2 = avma; gnorme = roundr(dbltor(p)); if (cmpis(gnorme, sBORNE) >= 0) set_avma(av2); else { sBORNE = itos(gnorme); set_avma(av1); BOUND = sBORNE * (1+eps); L = new_chunk(maxrank+1); s = 0; } } s++; switch(flag) { case min_FIRST: if (dolll) x = ZM_zc_mul_canon(u,x); return gerepilecopy(av, mkvec2(roundr(dbltor(p)), x)); case min_ALL: if (s > maxrank && stockall) /* overflow */ { long maxranknew = maxrank << 1; GEN Lnew = new_chunk(1 + maxranknew); for (i=1; i<=maxrank; i++) Lnew[i] = L[i]; L = Lnew; maxrank = maxranknew; } if (s<=maxrank) gel(L,s) = leafcopy(x); break; case min_VECSMALL: { ulong norm = (ulong)(p + 0.5); L[norm]++; } break; case min_VECSMALL2: { ulong norm = (ulong)(p + 0.5); if (!odd(norm)) L[norm>>1]++; } break; } } switch(flag) { case min_FIRST: set_avma(av); return cgetg(1,t_VEC); case min_VECSMALL: case min_VECSMALL2: set_avma((pari_sp)L); return L; } r = (maxnorm >= 0) ? roundr(dbltor(maxnorm)): stoi(sBORNE); k = minss(s,maxrank); L[0] = evaltyp(t_MAT) | evallg(k + 1); if (dolll) for (j=1; j<=k; j++) gel(L,j) = dolll==1 ? ZM_zc_mul_canon(u, gel(L,j)) : ZM_zc_mul_canon_zm(u, gel(L,j)); return gerepilecopy(av, mkvec3(stoi(s<<1), r, L)); } /* Closest vectors for the integral definite quadratic form: a. * Code bases on minim0_dolll * Result u: * u[1]= Number of closest vectors of square distance <= BORNE * u[2]= maximum squared distance found * u[3]= list of vectors found (at most STOCKMAX, unless NULL) * * If BORNE = NULL or <= 0.: returns closest vectors. * flag = min_ALL, as above * flag = min_FIRST, exits when first suitable vector is found. */ static GEN cvp0_dolll(GEN a, GEN target, GEN BORNE, GEN STOCKMAX, long flag, long dolll) { GEN x, u, r, L; GEN uinv, tv; GEN pd; long n = lg(a)-1, nt = lg(target)-1, i, j, k, s, maxrank; pari_sp av = avma, av1; double p,maxnorm,BOUND,*v,*y,*z,*tt,**q, *tpre, sBORNE; const double eps = 1e-10; int stockall = 0; struct qfvec qv; int done = 0; if (typ(target) != t_VEC && typ(target) != t_COL ) pari_err_TYPE("cvp0",target); if (n != nt) pari_err_TYPE("cvp0 [different dimensions]",target); if (!BORNE) sBORNE = 0.; else { if (typ(BORNE) != t_REAL && typ(BORNE) != t_INT && typ(BORNE) != t_FRAC ) pari_err_TYPE("cvp0",BORNE); sBORNE = gtodouble(BORNE); set_avma(av); if (sBORNE < 0.) sBORNE = 0.; } if (!STOCKMAX) { stockall = 1; maxrank = 200; } else { STOCKMAX = gfloor(STOCKMAX); if (typ(STOCKMAX) != t_INT) pari_err_TYPE("cvp0",STOCKMAX); maxrank = itos(STOCKMAX); if (maxrank < 0) pari_err_TYPE("cvp0 [negative number of vectors]",STOCKMAX); } L = (flag==min_ALL) ? new_chunk(1+maxrank) : NULL; if (n == 0 ) { if (flag==min_ALL) { retmkvec3(gen_0, gen_0, cgetg(1, t_MAT)); } else { return cgetg(1,t_VEC); } } cvp_alloc(n+1, &q, &x, &y, &z, &v, &tt, &tpre); forqfvec_init_dolll(&qv, &a, dolll); av1 = avma; r = qv.r; u = qv.u; for (j=1; j<=n; j++) { v[j] = rtodbl(gcoeff(r,j,j)); for (i=1; i1) { long l = k-1; z[l] = tpre[l]; 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; if (k >= n) { done = 1; break; } k++; x[k]--; } } while (k > 1 && !done); if (done) break; p = (double)x[1] + z[1]; p = y[1] + p*p*v[1]; /* norm(x-target) */ if (maxnorm >= 0) { if (p > maxnorm) maxnorm = p; } else { /* maxnorm < 0 : only look for closest vectors */ if (p * (1+10*eps) < sBORNE) { sBORNE = p; set_avma(av1); BOUND = sBORNE * (1+eps); L = new_chunk(maxrank+1); s = 0; } } s++; switch(flag) { case min_FIRST: if (dolll) x = ZM_zc_mul(u,x); return gerepilecopy(av, mkvec2(dbltor(p), x)); case min_ALL: if (s > maxrank && stockall) /* overflow */ { long maxranknew = maxrank << 1; GEN Lnew = new_chunk(1 + maxranknew); for (i=1; i<=maxrank; i++) Lnew[i] = L[i]; L = Lnew; maxrank = maxranknew; } if (s<=maxrank) gel(L,s) = leafcopy(x); break; } } switch(flag) { case min_FIRST: set_avma(av); return cgetg(1,t_VEC); } r = (maxnorm >= 0) ? dbltor(maxnorm): dbltor(sBORNE); k = minss(s,maxrank); L[0] = evaltyp(t_MAT) | evallg(k + 1); for (j=1; j<=k; j++) gel(L,j) = (dolll==1) ? ZM_zc_mul(u, gel(L,j)) : zc_to_ZC(gel(L,j)); return gerepilecopy(av, mkvec3(stoi(s), r, L)); } static GEN minim0(GEN a, GEN BORNE, GEN STOCKMAX, long flag) { GEN v = minim0_dolll(a, BORNE, STOCKMAX, flag, 1); if (!v) pari_err_PREC("qfminim"); return v; } static GEN cvp0(GEN a, GEN target, GEN BORNE, GEN STOCKMAX, long flag) { GEN v = cvp0_dolll(a, target, BORNE, STOCKMAX, flag, 1); if (!v) pari_err_PREC("qfcvp"); return v; } static GEN minim0_zm(GEN a, GEN BORNE, GEN STOCKMAX, long flag) { GEN v = minim0_dolll(a, BORNE, STOCKMAX, flag, 2); if (!v) pari_err_PREC("qfminim"); return v; } GEN qfrep0(GEN a, GEN borne, long flag) { return minim0(a, borne, gen_0, (flag & 1)? min_VECSMALL2: min_VECSMALL); } GEN qfminim0(GEN a, GEN borne, GEN stockmax, long flag, long prec) { switch(flag) { case 0: return minim0(a,borne,stockmax,min_ALL); case 1: return minim0(a,borne,gen_0 ,min_FIRST); case 2: { long maxnum = -1; if (typ(a) != t_MAT) pari_err_TYPE("qfminim",a); if (stockmax) { if (typ(stockmax) != t_INT) pari_err_TYPE("qfminim",stockmax); maxnum = itos(stockmax); } a = fincke_pohst(a,borne,maxnum,prec,NULL); if (!a) pari_err_PREC("qfminim"); return a; } default: pari_err_FLAG("qfminim"); } return NULL; /* LCOV_EXCL_LINE */ } GEN qfcvp0(GEN a, GEN target, GEN borne, GEN stockmax, long flag) { switch(flag) { case 0: return cvp0(a,target,borne,stockmax,min_ALL); case 1: return cvp0(a,target,borne,gen_0 ,min_FIRST); /* case 2: TODO: more robust finke_pohst enumeration */ default: pari_err_FLAG("qfcvp"); } return NULL; /* LCOV_EXCL_LINE */ } GEN minim(GEN a, GEN borne, GEN stockmax) { return minim0(a,borne,stockmax,min_ALL); } GEN minim_zm(GEN a, GEN borne, GEN stockmax) { return minim0_zm(a,borne,stockmax,min_ALL); } GEN minim_raw(GEN a, GEN BORNE, GEN STOCKMAX) { return minim0_dolll(a, BORNE, STOCKMAX, min_ALL, 0); } GEN minim2(GEN a, GEN borne, GEN stockmax) { return minim0(a,borne,stockmax,min_FIRST); } /* If V depends linearly from the columns of the matrix, return 0. * Otherwise, update INVP and L and return 1. No GC. */ static int addcolumntomatrix(GEN V, GEN invp, GEN L) { long i,j,k, n = lg(invp); GEN a = cgetg(n, t_COL), ak = NULL, mak; for (k = 1; k < n; k++) if (!L[k]) { ak = RgMrow_zc_mul(invp, V, k); if (!gequal0(ak)) break; } if (k == n) return 0; L[k] = 1; mak = gneg_i(ak); for (i=k+1; i> 1; if (L) { GEN D, V, invp; L = gel(L, 3); l = lg(L); if (l == 2) { set_avma(av); return gen_1; } /* |L[i]|^2 fits into a long for all i */ D = zero_zv(r); V = cgetg(r+1, t_VECSMALL); invp = matid(r); s = 0; for (k = 1; k < l; k++) { pari_sp av2 = avma; GEN x = gel(L,k); long i, j, I; for (i = I = 1; i<=n; i++) for (j=i; j<=n; j++,I++) V[I] = x[i]*x[j]; if (!addcolumntomatrix(V,invp,D)) set_avma(av2); else if (++s == r) break; } } else { GEN M; L = fincke_pohst(a,NULL,-1, DEFAULTPREC, NULL); if (!L) pari_err_PREC("qfminim"); L = gel(L, 3); l = lg(L); if (l == 2) { set_avma(av); return gen_1; } M = cgetg(l, t_MAT); for (k = 1; k < l; k++) { GEN x = gel(L,k), c = cgetg(r+1, t_COL); long i, I, j; for (i = I = 1; i<=n; i++) for (j=i; j<=n; j++,I++) gel(c,I) = mulii(gel(x,i), gel(x,j)); gel(M,k) = c; } s = ZM_rank(M); } return gc_utoipos(av, s); } static GEN clonefill(GEN S, long s, long t) { /* initialize to dummy values */ GEN T = S, dummy = cgetg(1, t_STR); long i; for (i = s+1; i <= t; i++) gel(S,i) = dummy; S = gclone(S); if (isclone(T)) gunclone(T); return S; } /* increment ZV x, by incrementing cell of index k. Initial value x0[k] was * chosen to minimize qf(x) for given x0[1..k-1] and x0[k+1,..] = 0 * The last nonzero entry must be positive and goes through x0[k]+1,2,3,... * Others entries go through: x0[k]+1,-1,2,-2,...*/ INLINE void step(GEN x, GEN y, GEN inc, long k) { if (!signe(gel(y,k))) /* x[k+1..] = 0 */ gel(x,k) = addiu(gel(x,k), 1); /* leading coeff > 0 */ else { long i = inc[k]; gel(x,k) = addis(gel(x,k), i), inc[k] = (i > 0)? -1-i: 1-i; } } /* 1 if we are "sure" that x < y, up to few rounding errors, i.e. * x < y - epsilon. More precisely : * - sign(x - y) < 0 * - lgprec(x-y) > 3 || expo(x - y) - expo(x) > -24 */ static int mplessthan(GEN x, GEN y) { pari_sp av = avma; GEN z = mpsub(x, y); set_avma(av); if (typ(z) == t_INT) return (signe(z) < 0); if (signe(z) >= 0) return 0; if (realprec(z) > LOWDEFAULTPREC) return 1; return ( expo(z) - mpexpo(x) > -24 ); } /* 1 if we are "sure" that x > y, up to few rounding errors, i.e. * x > y + epsilon */ static int mpgreaterthan(GEN x, GEN y) { pari_sp av = avma; GEN z = mpsub(x, y); set_avma(av); if (typ(z) == t_INT) return (signe(z) > 0); if (signe(z) <= 0) return 0; if (realprec(z) > LOWDEFAULTPREC) return 1; return ( expo(z) - mpexpo(x) > -24 ); } /* x a t_INT, y t_INT or t_REAL */ INLINE GEN mulimp(GEN x, GEN y) { if (typ(y) == t_INT) return mulii(x,y); return signe(x) ? mulir(x,y): gen_0; } /* x + y*z, x,z two mp's, y a t_INT */ INLINE GEN addmulimp(GEN x, GEN y, GEN z) { if (!signe(y)) return x; if (typ(z) == t_INT) return mpadd(x, mulii(y, z)); return mpadd(x, mulir(y, z)); } /* yk + vk * (xk + zk)^2 */ static GEN norm_aux(GEN xk, GEN yk, GEN zk, GEN vk) { GEN t = mpadd(xk, zk); if (typ(t) == t_INT) { /* probably gen_0, avoid loss of accuracy */ yk = addmulimp(yk, sqri(t), vk); } else { yk = mpadd(yk, mpmul(sqrr(t), vk)); } return yk; } /* yk + vk * (xk + zk)^2 < B + epsilon */ static int check_bound(GEN B, GEN xk, GEN yk, GEN zk, GEN vk) { pari_sp av = avma; int f = mpgreaterthan(norm_aux(xk,yk,zk,vk), B); return gc_bool(av, !f); } /* q(k-th canonical basis vector), where q is given in Cholesky form * q(x) = sum_{i = 1}^n q[i,i] (x[i] + sum_{j > i} q[i,j] x[j])^2. * Namely q(e_k) = q[k,k] + sum_{i < k} q[i,i] q[i,k]^2 * Assume 1 <= k <= n. */ static GEN cholesky_norm_ek(GEN q, long k) { GEN t = gcoeff(q,k,k); long i; for (i = 1; i < k; i++) t = norm_aux(gen_0, t, gcoeff(q,i,k), gcoeff(q,i,i)); return t; } /* q is the Cholesky decomposition of a quadratic form * Enumerate vectors whose norm is less than BORNE (Algo 2.5.7), * minimal vectors if BORNE = NULL (implies check = NULL). * If (check != NULL) consider only vectors passing the check, and assumes * we only want the smallest possible vectors */ static GEN smallvectors(GEN q, GEN BORNE, long maxnum, FP_chk_fun *CHECK) { long N = lg(q), n = N-1, i, j, k, s, stockmax, checkcnt = 1; pari_sp av, av1; 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; stockmax = stockall? 2000: maxnum; norms = cgetg(check?(stockmax+1): 1,t_VEC); /* unused if (!check) */ S = cgetg(stockmax+1,t_VEC); x = cgetg(N,t_COL); y = cgetg(N,t_COL); z = cgetg(N,t_COL); for (i=1; i2) err_printf("smallvectors looking for norm < %P.4G\n",borne1); s = 0; k = n; for(;; step(x,y,inc,k)) /* main */ { /* x (supposedly) small vector, ZV. * For all t >= k, we have * z[t] = sum_{j > t} q[t,j] * x[j] * y[t] = sum_{i > t} q[i,i] * (x[i] + z[i])^2 * = 0 <=> x[i]=0 for all i>t */ do { int skip = 0; if (k > 1) { long l = k-1; av1 = avma; p1 = mulimp(gel(x,k), gcoeff(q,l,k)); for (j=k+1; j n) goto END; } if (gc_needed(av,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"smallvectors"); if (stockmax) S = clonefill(S, s, stockmax); if (check) { GEN dummy = cgetg(1, t_STR); for (i=s+1; i<=stockmax; i++) gel(norms,i) = dummy; } gerepileall(av,7,&x,&y,&z,&normax1,&borne1,&borne2,&norms); } } while (k > 1); if (!signe(gel(x,1)) && !signe(gel(y,1))) continue; /* exclude 0 */ av1 = avma; norme1 = norm_aux(gel(x,1),gel(y,1),gel(z,1),gel(v,1)); if (mpgreaterthan(norme1,borne1)) { set_avma(av1); continue; /* main */ } norme1 = gerepileuptoleaf(av1,norme1); if (check) { if (checkcnt < 5 && mpcmp(norme1, borne2) < 0) { if (!check(data,x)) { checkcnt++ ; continue; /* main */} if (DEBUGLEVEL>4) err_printf("New bound: %Ps", norme1); borne1 = norme1; borne2 = mulrr(borne1, alpha); s = 0; checkcnt = 0; } } else { if (!BORNE) /* find minimal vectors */ { if (mplessthan(norme1, borne1)) { /* strictly smaller vector than previously known */ borne1 = norme1; /* + epsilon */ s = 0; } } else if (mpcmp(norme1,normax1) > 0) normax1 = norme1; } if (++s > stockmax) continue; /* too many vectors: no longer remember */ if (check) gel(norms,s) = norme1; gel(S,s) = leafcopy(x); if (s != stockmax) continue; /* still room, get next vector */ if (check) { /* overflow, eliminate vectors failing "check" */ pari_sp av2 = avma; long imin, imax; GEN per = indexsort(norms), S2 = cgetg(stockmax+1, t_VEC); if (DEBUGLEVEL>2) err_printf("sorting... [%ld elts]\n",s); /* let N be the minimal norm so far for x satisfying 'check'. Keep * all elements of norm N */ for (i = 1; i <= s; i++) { long k = per[i]; if (check(data,gel(S,k))) { borne1 = gel(norms,k); break; } } imin = i; for (; i <= s; i++) if (mpgreaterthan(gel(norms,per[i]), borne1)) break; imax = i; for (i=imin, s=0; i < imax; i++) gel(S2,++s) = gel(S,per[i]); for (i = 1; i <= s; i++) gel(S,i) = gel(S2,i); set_avma(av2); if (s) { borne2 = mulrr(borne1, alpha); checkcnt = 0; } if (!stockall) continue; if (s > stockmax/2) stockmax <<= 1; norms = cgetg(stockmax+1, t_VEC); for (i = 1; i <= s; i++) gel(norms,i) = borne1; } else { if (!stockall && BORNE) goto END; if (!stockall) continue; stockmax <<= 1; } { GEN Snew = clonefill(vec_lengthen(S,stockmax), s, stockmax); if (isclone(S)) gunclone(S); S = Snew; } } END: if (s < stockmax) stockmax = s; if (check) { GEN per, alph, pols, p; if (DEBUGLEVEL>2) err_printf("final sort & check...\n"); setlg(norms,stockmax+1); per = indexsort(norms); alph = cgetg(stockmax+1,t_VEC); pols = cgetg(stockmax+1,t_VEC); for (j=0,i=1; i<=stockmax; i++) { long t = per[i]; GEN N = gel(norms,t); if (j && mpgreaterthan(N, borne1)) break; if ((p = check(data,gel(S,t)))) { if (!j) borne1 = N; j++; gel(pols,j) = p; gel(alph,j) = gel(S,t); } } setlg(pols,j+1); setlg(alph,j+1); if (stockmax && isclone(S)) { alph = gcopy(alph); gunclone(S); } return mkvec2(pols, alph); } if (stockmax) { setlg(S,stockmax+1); settyp(S,t_MAT); if (isclone(S)) { p1 = S; S = gcopy(S); gunclone(p1); } } else S = cgetg(1,t_MAT); return mkvec3(utoi(s<<1), borne1, S); } /* solve q(x) = x~.a.x <= bound, a > 0. * If check is non-NULL keep x only if check(x). * If a is a vector, assume a[1] is the LLL-reduced Cholesky form of q */ GEN fincke_pohst(GEN a, GEN B0, long stockmax, long PREC, FP_chk_fun *CHECK) { pari_sp av = avma; VOLATILE long i,j,l; VOLATILE GEN r,rinv,rinvtrans,u,v,res,z,vnorm,rperm,perm,uperm, bound = B0; if (typ(a) == t_VEC) { r = gel(a,1); u = NULL; } else { long prec = PREC; l = lg(a); if (l == 1) { if (CHECK) pari_err_TYPE("fincke_pohst [dimension 0]", a); retmkvec3(gen_0, gen_0, cgetg(1,t_MAT)); } u = lllfp(a, 0.75, LLL_GRAM | LLL_IM); if (!u || lg(u) != lg(a)) return gc_NULL(av); r = qf_RgM_apply(a,u); i = gprecision(r); if (i) prec = i; else { prec = DEFAULTPREC + nbits2extraprec(gexpo(r)); if (prec < PREC) prec = PREC; } if (DEBUGLEVEL>2) err_printf("first LLL: prec = %ld\n", prec); r = qfgaussred_positive(r); if (!r) return gc_NULL(av); for (i=1; i2) err_printf("Fincke-Pohst, final LLL: prec = %ld\n", gprecision(rinvtrans)); v = lll(rinvtrans); if (lg(v) != lg(rinvtrans)) return gc_NULL(av); rinvtrans = RgM_mul(rinvtrans, v); v = ZM_inv(shallowtrans(v),NULL); r = RgM_mul(r,v); u = u? ZM_mul(u,v): v; l = lg(r); vnorm = cgetg(l,t_VEC); for (j=1; jf_init) bound = CHECK->f_init(CHECK, r, u); q = gaussred_from_QR(r, gprecision(vnorm)); if (q) res = smallvectors(q, bound, stockmax, CHECK); } pari_ENDCATCH; if (!res) return gc_NULL(av); if (CHECK) { if (CHECK->f_post) res = CHECK->f_post(CHECK, res, u); return res; } 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.17.2/src/basemath/bern.c0000644000175000017500000004317714760137411014651 0ustar billbill/* Copyright (C) 2018 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_bern /********************************************************************/ /** **/ /** BERNOULLI NUMBERS B_2k **/ /** **/ /********************************************************************/ /* D = divisorsu(n). Return a/b = \sum_{p-1 | 2n: p prime} 1/p * B_2k + a/b in Z [Clausen-von Staudt] */ static GEN fracB2k(GEN D) { GEN a = utoipos(5), b = utoipos(6); /* 1/2 + 1/3 */ long i, l = lg(D); for (i = 2; i < l; i++) /* skip 1 */ { ulong p = 2*D[i] + 1; /* a/b += 1/p */ if (uisprime(p)) { a = addii(muliu(a,p), b); b = muliu(b,p); } } return mkfrac(a,b); } /* precision needed to compute B_k for all k <= N */ long bernbitprec(long N) { /* 1.612086 ~ log(8Pi) / 2 */ const double log2PI = 1.83787706641; double logN = log((double)N); double t = (N + 4) * logN - N*(1 + log2PI) + 1.612086; return (long)ceil(t / M_LN2) + 10; } static long bernprec(long N) { return nbits2prec(bernbitprec(N)); } /* \sum_{k > M} k^(-n) <= M^(1-n) / (n-1) < 2^-b */ static long zetamaxpow(long n) { long M = (long)ceil(n / (2 * M_PI * M_E)); return M | 1; /* make it odd */ } /* v * zeta(k) using r precomputed odd powers */ static GEN bern_zeta(GEN v, long k, GEN pow, long r, long p) { GEN z, s = gel(pow, r); long j; for (j = r - 2; j >= 3; j -= 2) s = addii(s, gel(pow,j)); z = s = itor(s, nbits2prec(p)); shiftr_inplace(s, -p); /* zeta(k)(1 - 2^(-k)) - 1*/ s = addrs(s, 1); shiftr_inplace(s, -k); /* divide by 1 - 2^(-k): s + s/2^k + s/2^(2k) + ... */ for (; k < p; k <<= 1) s = addrr(s, shiftr(s, -k)); return addrr(v, mulrr(v, addrr(z, s))); } /* z * j^2 */ static GEN muliu2(GEN z, ulong j) { return (j | HIGHMASK)? mulii(z, sqru(j)): muliu(z, j*j); } /* 1 <= m <= n, set y[1] = B_{2m}, ... y[n-m+1] = B_{2n} in Q */ static void bernset(GEN *y, long m, long n) { long i, j, k, p, prec, r, N = n << 1; /* up to B_N */ GEN u, b, v, t; p = bernbitprec(N); prec = nbits2prec(p); u = sqrr(Pi2n(1, prec)); /* (2Pi)^2 */ v = divrr(mpfactr(N, prec), powru(u, n)); shiftr_inplace(v,1); r = zetamaxpow(N); t = cgetg(r+1, t_VEC); b = int2n(p); /* fixed point */ for (j = 3; j <= r; j += 2) { GEN z = cgeti(nbits2lg(p)); pari_sp av2 = avma; affii(divii(b, powuu(j, N)), z); gel(t,j) = z; set_avma(av2); } y += n - m; for (i = n, k = N;; i--) { /* set B_n, k = 2i */ pari_sp av2 = avma; GEN z = fracB2k(divisorsu(i)), B = bern_zeta(v, k, t, r, p); long j; /* B = v * zeta(k), v = 2*k! / (2Pi)^k */ if (!odd(i)) setsigne(B, -1); /* B ~ B_n */ B = roundr(addrr(B, fractor(z,LOWDEFAULTPREC))); /* B - z = B_n */ *y-- = gclone(gsub(B, z)); if (i == m) break; affrr(divrunextu(mulrr(v,u), k-1), v); for (j = r; j >= 3; j -= 2) affii(muliu2(gel(t,j), j), gel(t,j)); set_avma(av2); k -= 2; if (((N - k) & 0x7f) == 0x7e) { /* reduce precision if possible */ long p2 = p, prec2 = prec; p = bernbitprec(k); prec = nbits2prec(p); if (prec2 == prec) continue; setprec(v, prec); r = zetamaxpow(k); for (j = 3; j <= r; j += 2) affii(shifti(gel(t,j), p - p2), gel(t,j)); set_avma(av2); } } } /* need B[2..2*nb] as t_INT or t_FRAC */ void constbern(long nb) { const pari_sp av = avma; long i, l; GEN B; pari_timer T; l = bernzone? lg(bernzone): 0; if (l > nb) return; nb = maxss(nb, l + 127); B = cgetg_block(nb+1, t_VEC); if (bernzone) { for (i = 1; i < l; i++) gel(B,i) = gel(bernzone,i); } else { gel(B,1) = gclone(mkfracss(1,6)); gel(B,2) = gclone(mkfracss(-1,30)); gel(B,3) = gclone(mkfracss(1,42)); gel(B,4) = gclone(mkfracss(-1,30)); gel(B,5) = gclone(mkfracss(5,66)); gel(B,6) = gclone(mkfracss(-691,2730)); gel(B,7) = gclone(mkfracss(7,6)); gel(B,8) = gclone(mkfracss(-3617,510)); gel(B,9) = gclone(mkfracss(43867,798)); gel(B,10)= gclone(mkfracss(-174611,330)); gel(B,11)= gclone(mkfracss(854513,138)); gel(B,12)= gclone(mkfracss(-236364091,2730)); gel(B,13)= gclone(mkfracss(8553103,6)); /* B_26 */ l = 14; } set_avma(av); if (DEBUGLEVEL) { err_printf("caching Bernoulli numbers 2*%ld to 2*%ld\n", l, nb); timer_start(&T); } bernset((GEN*)B + l, l, nb); if (DEBUGLEVEL) timer_printf(&T, "Bernoulli"); swap(B, bernzone); guncloneNULL(B); set_avma(av); #if 0 if (nb > 200000) #endif { const ulong p = 4294967291UL; long n = 2 * nb + 2; GEN t = const_vecsmall(n+1, 1); t[1] = evalvarn(0); t[2] = 0; t = Flx_shift(Flx_invLaplace(t, p), -1); /* t = (exp(x)-1)/x */ t = Flx_Laplace(Flxn_inv(t, n, p), p); for (i = 1; i <= nb; i++) if (Rg_to_Fl(bernfrac(2*i), p) != uel(t,2*i+2)) { gunclone(bernzone); bernzone = NULL; pari_err_BUG(stack_sprintf("B_{2*%ld}", i)); } set_avma(av); } } /* Obsolete, kept for backward compatibility */ void mpbern(long n, long prec) { (void)prec; constbern(n); } /* assume n even > 0, if iz != NULL, assume iz = 1/zeta(n) */ static GEN bernreal_using_zeta(long n, long prec) { GEN pi2 = Pi2n(1, prec+EXTRAPREC64); GEN iz = inv_szeta_euler(n, prec); GEN z = divrr(mpfactr(n, prec), mulrr(powru(pi2, n), iz)); shiftr_inplace(z, 1); /* 2 * n! * zeta(n) / (2Pi)^n */ if ((n & 3) == 0) setsigne(z, -1); return z; } /* assume n even > 0, B = NULL or good approximation to B_n */ static GEN bernfrac_i(long n, GEN B) { GEN z = fracB2k(divisorsu(n >> 1)); if (!B) B = bernreal_using_zeta(n, bernprec(n)); B = roundr( gadd(B, fractor(z,LOWDEFAULTPREC)) ); return gsub(B, z); } GEN bernfrac(long n) { pari_sp av; long k; if (n <= 1) { if (n < 0) pari_err_DOMAIN("bernfrac", "index", "<", gen_0, stoi(n)); return n? mkfrac(gen_m1,gen_2): gen_1; } if (odd(n)) return gen_0; k = n >> 1; if (!bernzone) constbern(0); if (bernzone && k < lg(bernzone)) return gel(bernzone, k); av = avma; return gerepileupto(av, bernfrac_i(n, NULL)); } GEN bernvec(long n) { long i, l; GEN y; if (n < 0) return cgetg(1, t_VEC); constbern(n); l = n+2; y = cgetg(l, t_VEC); gel(y,1) = gen_1; for (i = 2; i < l; i++) gel(y,i) = gel(bernzone,i-1); return y; } /* x := pol_x(v); B_k(x) = \sum_{i=0}^k binomial(k, i) B_i x^{k-i} */ static GEN bernpol_i(long k, long v) { GEN B, C; long i; if (v < 0) v = 0; constbern(k >> 1); /* cache B_2, ..., B_2[k/2] */ C = vecbinomial(k); B = cgetg(k + 3, t_POL); for (i = 0; i <= k; ++i) gel(B, k-i+2) = gmul(gel(C,i+1), bernfrac(i)); B[1] = evalsigne(1) | evalvarn(v); return B; } GEN bernpol(long k, long v) { pari_sp av = avma; if (k < 0) pari_err_DOMAIN("bernpol", "index", "<", gen_0, stoi(k)); return gerepileupto(av, bernpol_i(k, v)); } GEN bernpol_eval(long k, GEN x) { pari_sp av = avma; GEN B; if (!x) return bernpol(k, 0); if (gequalX(x)) return bernpol(k, varn(x)); if (k < 0) pari_err_DOMAIN("bernpol", "index", "<", gen_0, stoi(k)); B = poleval(bernpol_i(k, fetch_var_higher()), x); delete_var(); return gerepileupto(av, B); } /* x := pol_x(v); return 1^e + ... + x^e = x^e + (B_{e+1}(x) - B_{e+1})/(e+1) */ static GEN faulhaber(long e, long v) { GEN B; if (e == 0) return pol_x(v); B = RgX_integ(bernpol_i(e, v)); /* (B_{e+1}(x) - B_{e+1}) / (e+1) */ gel(B,e+2) = gaddgs(gel(B,e+2), 1); /* add x^e, in place */ return B; } /* sum_v T(v), T a polynomial expression in v */ GEN sumformal(GEN T, long v) { pari_sp av = avma, av2; long i, t, d; GEN R; T = simplify_shallow(T); t = typ(T); if (is_scalar_t(t)) return gerepileupto(av, monomialcopy(T, 1, v < 0? 0: v)); if (t != t_POL) pari_err_TYPE("sumformal [not a t_POL]", T); if (v < 0) v = varn(T); av2 = avma; R = gen_0; d = poldegree(T,v); for (i = d; i >= 0; i--) { GEN c = polcoef_i(T, i, v); if (gequal0(c)) continue; R = gadd(R, gmul(c, faulhaber(i, v))); if (gc_needed(av2,3)) { if(DEBUGMEM>1) pari_warn(warnmem,"sumformal, i = %ld/%ld", i,d); R = gerepileupto(av2, R); } } return gerepileupto(av, R); } /* 1/zeta(n) using Euler product. Assume n > 0. */ GEN inv_szeta_euler(long n, long prec) { long bit = prec2nbits(prec); GEN z, res; pari_sp av, av2; double A, D, lba; ulong p, lim; forprime_t S; if (n > bit) return real_1(prec); lba = prec2nbits_mul(prec, M_LN2); D = exp((lba - log((double)(n-1))) / (n-1)); lim = 1 + (ulong)ceil(D); if (lim < 3) return subir(gen_1,real2n(-n,prec)); res = cgetr(prec); av = avma; incrprec(prec); (void)u_forprime_init(&S, 3, lim); av2 = avma; A = n / M_LN2; z = subir(gen_1, real2n(-n, prec)); while ((p = u_forprime_next(&S))) { long l = bit - (long)floor(A * log((double)p)); GEN h; if (l < BITS_IN_LONG) l = BITS_IN_LONG; l = minss(prec, nbits2prec(l)); h = divrr(z, rpowuu(p, (ulong)n, l)); z = subrr(z, h); if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"inv_szeta_euler, p = %lu/%lu", p,lim); z = gerepileuptoleaf(av2, z); } } affrr(z, res); set_avma(av); return res; } /* Return B_n */ GEN bernreal(long n, long prec) { pari_sp av; GEN B; long p, k; if (n < 0) pari_err_DOMAIN("bernreal", "index", "<", gen_0, stoi(n)); if (n == 0) return real_1(prec); if (n == 1) return real_m2n(-1,prec); /*-1/2*/ if (odd(n)) return real_0(prec); k = n >> 1; if (!bernzone) constbern(0); if (k < lg(bernzone)) return fractor(gel(bernzone,k), prec); p = bernprec(n); av = avma; B = bernreal_using_zeta(n, minss(p, prec)); if (p < prec) B = fractor(bernfrac_i(n, B), prec); return gerepileuptoleaf(av, B); } GEN eulerpol(long k, long v) { pari_sp av = avma; GEN B, E; if (k < 0) pari_err_DOMAIN("eulerpol", "index", "<", gen_0, stoi(k)); k++; B = bernpol_i(k, v); E = RgX_Rg_mul(RgX_sub(B, RgX_rescale(B, gen_2)), uutoQ(2,k)); return gerepileupto(av, E); } /*******************************************************************/ /** HARMONIC NUMBERS **/ /*******************************************************************/ /* 1/a + ... + 1/(b-1); a < b <= 2^(BIL-1) */ static GEN hrec(ulong a, ulong b) { ulong m; switch(b - a) { case 1: retmkfrac(gen_1, utoipos(a)); case 2: if (a < 65536) retmkfrac(utoipos(2*a + 1), utoipos(a * a + a)); retmkfrac(utoipos(2*a + 1), muluu(a, a+1)); } m = (a + b) >> 1; return gadd(hrec(a, m), hrec(m, b)); } /* exact Harmonic number H_n, n < 2^(BIL-1). * Could use H_n = sum_k 2^(-k) H^odd_{n \ 2^k} */ GEN harmonic(ulong n) { pari_sp av = avma; return n? gerepileupto(av, hrec(1, n+1)): gen_0; } /* 1/a^k + ... + 1/(b-1)^k; a < b */ static GEN hreck(ulong a, ulong b, ulong k) { ulong m; switch(b - a) { GEN x, y; case 1: retmkfrac(gen_1, powuu(a, k)); case 2: x = powuu(a, k); y = powuu(a + 1, k); retmkfrac(addii(x, y), mulii(x, y)); } m = (a + b) >> 1; return gadd(hreck(a, m, k), hreck(m, b, k)); } GEN harmonic0(ulong n, GEN k) { pari_sp av = avma; ulong r; if (!n) return gen_0; if (n & HIGHBIT) pari_err_OVERFLOW("harmonic"); if (!k) return harmonic(n); if (typ(k) != t_INT) pari_err_TYPE("harmonic", k); if (signe(k) < 0) { GEN H = poleval(faulhaber(-itos(k), 0), utoipos(n)); return gerepileuptoint(av, H); } r = itou(k); if (!r) return utoipos(n); if (r == 1) return harmonic(n); return gerepileupto(av, hreck(1, n+1, r)); } /**************************************************************/ /* Euler numbers */ /**************************************************************/ /* precision needed to compute E_k for all k <= N */ static long eulerbitprec(long N) { /* 1.1605 ~ log(32/Pi) / 2 */ const double logPIS2 = 0.4515827; double t = (N + 1) * log((double)N) - N*(1 + logPIS2) + 1.1605; return (long)ceil(t / M_LN2) + 10; } static long eulerprec(long N) { return nbits2prec(eulerbitprec(N)); } /* sum_{k > M, k odd} (-1)^((k-1)/2)k^(-n) < M^(-n) < 2^-b */ static long lfun4maxpow(long n) { long M = (long)ceil(2 * n / (M_E * M_PI)); return M | 1; /* make it odd */ } /* lfun4(k) using r precomputed odd powers */ static GEN euler_lfun4(GEN v, GEN pow, long r, long p) { GEN s = ((r & 3L) == 1)? gel(pow, r): negi(gel(pow, r)); long j; for (j = r - 2; j >= 3; j -= 2) s = ((j & 3L) == 1)? addii(s, gel(pow,j)): subii(s, gel(pow,j)); s = mulri(v, s); shiftr_inplace(s, -p); return addrr(v, s); } /* 1 <= m <= n, set y[1] = E_{2m}, ... y[n-m+1] = E_{2n} in Z */ static void eulerset(GEN *y, long m, long n) { long i, j, k, p, prec, r, N = n << 1, N1 = N + 1; /* up to E_N */ GEN b, u, v, t; p = eulerbitprec(N); prec = nbits2prec(p); u = sqrr(Pi2n(-1, prec)); /* (Pi/2)^2 */ v = divrr(mpfactr(N, prec), mulrr(powru(u, n), Pi2n(-2,prec))); r = lfun4maxpow(N1); t = cgetg(r+1, t_VEC); b = int2n(p); /* fixed point */ for (j = 3; j <= r; j += 2) { GEN z = cgeti(nbits2lg(p)); pari_sp av2 = avma; affii(divii(b, powuu(j, N+1)), z); gel(t,j) = z; set_avma(av2); } y += n - m; for (i = n, k = N1;; i--) { /* set E_n, k = 2i + 1 */ pari_sp av2 = avma; GEN E = euler_lfun4(v, t, r, p); long j; /* E = v * lfun4(k), v = (4/Pi)*k! / (Pi/2)^k */ E = roundr(E); if (odd(i)) setsigne(E, -1); /* E ~ E_n */ *y-- = gclone(E); if (i == m) break; affrr(divrunextu(mulrr(v,u), k-2), v); for (j = r; j >= 3; j -= 2) affii(muliu2(gel(t,j), j), gel(t,j)); set_avma(av2); k -= 2; if (((N1 - k) & 0x7f) == 0x7e) { /* reduce precision if possible */ long p2 = p, prec2 = prec; p = eulerbitprec(k); prec = nbits2prec(p); if (prec2 == prec) continue; setprec(v, prec); r = lfun4maxpow(k); for (j = 3; j <= r; j += 2) affii(shifti(gel(t,j), p - p2), gel(t,j)); set_avma(av2); } } } /* need E[2..2*nb] as t_INT */ static void constreuler(long nb) { const pari_sp av = avma; long i, l; GEN E; pari_timer T; l = eulerzone? lg(eulerzone): 0; if (l > nb) return; nb = maxss(nb, l + 127); E = cgetg_block(nb+1, t_VEC); if (eulerzone) { for (i = 1; i < l; i++) gel(E,i) = gel(eulerzone,i); } else { gel(E,1) = gclone(stoi(-1)); gel(E,2) = gclone(stoi(5)); gel(E,3) = gclone(stoi(-61)); gel(E,4) = gclone(stoi(1385)); gel(E,5) = gclone(stoi(-50521)); gel(E,6) = gclone(stoi(2702765)); gel(E,7) = gclone(stoi(-199360981)); l = 8; } set_avma(av); if (DEBUGLEVEL) { err_printf("caching Euler numbers 2*%ld to 2*%ld\n", l, nb); timer_start(&T); } eulerset((GEN*)E + l, l, nb); if (DEBUGLEVEL) timer_printf(&T, "Euler"); swap(E, eulerzone); guncloneNULL(E); set_avma(av); } /* 1/lfun(-4,n) using Euler product. Assume n > 0. */ static GEN inv_lfun4(long n, long prec) { long bit = prec2nbits(prec); GEN z, res; pari_sp av, av2; double A; ulong p, lim; forprime_t S; if (n > bit) return real_1(prec); lim = 1 + (ulong)ceil(exp2((double)bit / n)); res = cgetr(prec); av = avma; incrprec(prec); (void)u_forprime_init(&S, 3, lim); av2 = avma; A = n / M_LN2; z = real_1(prec); while ((p = u_forprime_next(&S))) { long l = bit - (long)floor(A * log((double)p)); GEN h; if (l < BITS_IN_LONG) l = BITS_IN_LONG; l = minss(prec, nbits2prec(l)); h = rpowuu(p, (ulong)n, l); if ((p & 3UL) == 1) setsigne(h, -1); z = addrr(z, divrr(z, h)); /* z *= 1 - chi_{-4}(p) / p^n */ if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"inv_lfun4, p = %lu/%lu", p,lim); z = gerepileuptoleaf(av2, z); } } affrr(z, res); set_avma(av); return res; } /* assume n even > 0, E_n = (-1)^(n/2) (4/Pi) n! lfun4(n+1) / (Pi/2)^n */ static GEN eulerreal_using_lfun4(long n, long prec) { GEN pisur2 = Pi2n(-1, prec+EXTRAPREC64); GEN iz = inv_lfun4(n+1, prec); GEN z = divrr(mpfactr(n, prec), mulrr(powru(pisur2, n+1), iz)); if ((n & 3L) == 2) setsigne(z, -1); shiftr_inplace(z, 1); return z; } /* Euler numbers: 1, 0, -1, 0, 5, 0, -61,... */ GEN eulerfrac(long n) { pari_sp av; long k; GEN E; if (n <= 0) { if (n < 0) pari_err_DOMAIN("eulerfrac", "index", "<", gen_0, stoi(n)); return gen_1; } if (odd(n)) return gen_0; k = n >> 1; if (!eulerzone) constreuler(0); if (eulerzone && k < lg(eulerzone)) return gel(eulerzone, k); av = avma; E = eulerreal_using_lfun4(n, eulerprec(n)); return gerepileuptoleaf(av, roundr(E)); } GEN eulervec(long n) { long i, l; GEN y; if (n < 0) return cgetg(1, t_VEC); constreuler(n); l = n+2; y = cgetg(l, t_VEC); gel(y,1) = gen_1; for (i = 2; i < l; i++) gel(y,i) = gel(eulerzone,i-1); return y; } /* Return E_n */ GEN eulerreal(long n, long prec) { pari_sp av = avma; GEN B; long p, k; if (n < 0) pari_err_DOMAIN("eulerreal", "index", "<", gen_0, stoi(n)); if (n == 0) return real_1(prec); if (odd(n)) return real_0(prec); k = n >> 1; if (!eulerzone) constreuler(0); if (k < lg(eulerzone)) return itor(gel(eulerzone,k), prec); p = eulerprec(n); B = eulerreal_using_lfun4(n, minss(p, prec)); if (p < prec) B = itor(roundr(B), prec); return gerepileuptoleaf(av, B); } pari-2.17.2/src/basemath/lfun.c0000644000175000017500000024174714676526175014711 0ustar billbill/* Copyright (C) 2015 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /********************************************************************/ /** **/ /** L-functions **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_lfun /*******************************************************************/ /* Accessors */ /*******************************************************************/ static GEN mysercoeff(GEN x, long n) { long N = n - valser(x); return (N < 0)? gen_0: gel(x, N+2); } long ldata_get_type(GEN ldata) { return mael3(ldata, 1, 1, 1); } GEN ldata_get_an(GEN ldata) { return gel(ldata, 1); } GEN ldata_get_dual(GEN ldata) { return gel(ldata, 2); } long ldata_isreal(GEN ldata) { return isintzero(gel(ldata, 2)); } GEN ldata_get_gammavec(GEN ldata) { return gel(ldata, 3); } long ldata_get_degree(GEN ldata) { return lg(gel(ldata, 3))-1; } GEN ldata_get_k(GEN ldata) { GEN w = gel(ldata,4); if (typ(w) == t_VEC) w = gel(w,1); return w; } /* a_n = O(n^{k1 + epsilon}) */ GEN ldata_get_k1(GEN ldata) { GEN w = gel(ldata,4); if (typ(w) == t_VEC) return gel(w,2); /* by default, assume that k1 = k-1 and even (k-1)/2 for entire functions */ w = gaddgs(w,-1); return ldata_get_residue(ldata)? w: gmul2n(w, -1); } /* a_n = O(n^{k1 + epsilon}) */ static double ldata_get_k1_dbl(GEN ldata) { GEN w = gel(ldata,4); double k; if (typ(w) == t_VEC) return gtodouble(gel(w,2)); /* by default, assume that k1 = k-1 and even (k-1)/2 for entire functions */ k = gtodouble(w); return ldata_get_residue(ldata)? k-1: (k-1)/2.; } GEN ldata_get_conductor(GEN ldata) { return gel(ldata, 5); } GEN ldata_get_rootno(GEN ldata) { return gel(ldata, 6); } GEN ldata_get_residue(GEN ldata) { return lg(ldata) == 7 ? NULL: gel(ldata, 7); } long linit_get_type(GEN linit) { return mael(linit, 1, 1); } GEN linit_get_ldata(GEN linit) { return gel(linit, 2); } GEN linit_get_tech(GEN linit) { return gel(linit, 3); } long is_linit(GEN data) { return lg(data) == 4 && typ(data) == t_VEC && typ(gel(data, 1)) == t_VECSMALL; } GEN lfun_get_step(GEN tech) { return gmael(tech, 2, 1);} GEN lfun_get_pol(GEN tech) { return gmael(tech, 2, 2);} GEN lfun_get_Residue(GEN tech) { return gmael(tech, 2, 3);} GEN lfun_get_k2(GEN tech) { return gmael(tech, 3, 1);} GEN lfun_get_w2(GEN tech) { return gmael(tech, 3, 2);} GEN lfun_get_expot(GEN tech) { return gmael(tech, 3, 3);} GEN lfun_get_factgammavec(GEN tech) { return gmael(tech, 3, 4); } /* Handle complex Vga whose sum is real */ static GEN sumVga(GEN Vga) { return real_i(vecsum(Vga)); } /* sum_i max (Im v[i],0) */ static double sumVgaimpos(GEN v) { double d = 0.; long i, l = lg(v); for (i = 1; i < l; i++) { GEN c = imag_i(gel(v,i)); if (gsigne(c) > 0) d += gtodouble(c); } return d; } static long vgaell(GEN Vga) { if (lg(Vga) == 3) { GEN c = gsub(gel(Vga,1), gel(Vga,2)); return gequal1(c) || gequalm1(c); } return 0; } int Vgaeasytheta(GEN Vga) { return lg(Vga)-1 == 1 || vgaell(Vga); } /* return b(n) := a(n) * n^c, when Vgaeasytheta(Vga) is set */ static GEN antwist(GEN an, GEN Vga, long prec) { long l, i; GEN b, c = vecmin(Vga); if (gequal0(c)) return an; l = lg(an); b = cgetg(l, t_VEC); if (gequal1(c)) { if (typ(an) == t_VECSMALL) for (i = 1; i < l; i++) gel(b,i) = mulss(an[i], i); else for (i = 1; i < l; i++) gel(b,i) = gmulgu(gel(an,i), i); } else { GEN v = vecpowug(l-1, c, prec); if (typ(an) == t_VECSMALL) for (i = 1; i < l; i++) gel(b,i) = gmulsg(an[i], gel(v,i)); else for (i = 1; i < l; i++) gel(b,i) = gmul(gel(an,i), gel(v,i)); } return b; } static GEN theta_dual(GEN theta, GEN bn) { if (typ(bn)==t_INT) return NULL; else { GEN thetad = shallowcopy(theta), ldata = linit_get_ldata(theta); GEN Vga = ldata_get_gammavec(ldata); GEN tech = shallowcopy(linit_get_tech(theta)); GEN an = theta_get_an(tech); long prec = nbits2prec(theta_get_bitprec(tech)); GEN vb = ldata_vecan(bn, lg(an)-1, prec); if (!theta_get_m(tech) && Vgaeasytheta(Vga)) vb = antwist(vb, Vga, prec); gel(tech,1) = vb; gel(thetad,3) = tech; return thetad; } } static GEN domain_get_dom(GEN domain) { return gel(domain,1); } static long domain_get_der(GEN domain) { return mael2(domain, 2, 1); } static long domain_get_bitprec(GEN domain) { return mael2(domain, 2, 2); } GEN lfun_get_domain(GEN tech) { return gel(tech,1); } long lfun_get_bitprec(GEN tech){ return domain_get_bitprec(lfun_get_domain(tech)); } GEN lfun_get_dom(GEN tech) { return domain_get_dom(lfun_get_domain(tech)); } GEN lfunprod_get_fact(GEN tech) { return gel(tech, 2); } GEN theta_get_an(GEN tdata) { return gel(tdata, 1);} GEN theta_get_K(GEN tdata) { return gel(tdata, 2);} GEN theta_get_R(GEN tdata) { return gel(tdata, 3);} long theta_get_bitprec(GEN tdata) { return itos(gel(tdata, 4));} long theta_get_m(GEN tdata) { return itos(gel(tdata, 5));} GEN theta_get_tdom(GEN tdata) { return gel(tdata, 6);} GEN theta_get_isqrtN(GEN tdata) { return gel(tdata, 7);} /*******************************************************************/ /* Helper functions related to Gamma products */ /*******************************************************************/ /* x != 0 */ static int serisscalar(GEN x) { long i; if (valser(x)) return 0; for (i = lg(x)-1; i > 3; i--) if (!gequal0(gel(x,i))) return 0; return 1; } /* return -itos(s) >= 0 if scalar s is (approximately) equal to a nonpositive * integer, and -1 otherwise */ static long isnegint(GEN s) { GEN r = ground(real_i(s)); if (signe(r) <= 0 && gequal(s, r)) return -itos(r); return -1; } /* if s = a + O(x^n), a <= 0 integer, replace by a + b*x^n + O(x^(n+1)) */ static GEN serextendifnegint(GEN s, GEN b, long *ext) { if (!signe(s) || (serisscalar(s) && isnegint(gel(s,2)) >= 0)) { long l = lg(s); GEN t = cgetg(l+1, t_SER); gel(t, l) = b; while (--l > 1) gel(t,l) = gel(s,l); if (gequal0(gel(t,2))) gel(t,2) = gen_0; t[1] = s[1]; s = normalizeser(t); *ext = 1; } return s; } /* r/x + O(1), r != 0 */ static GEN serpole(GEN r) { GEN s = cgetg(3, t_SER); s[1] = evalsigne(1)|evalvalser(-1)|evalvarn(0); gel(s,2) = r; return s; } /* a0 + a1 x + O(x^e), e >= 0 */ static GEN deg1ser_shallow(GEN a1, GEN a0, long v, long e) { return RgX_to_ser(deg1pol_shallow(a1, a0, v), e+2); } /* pi^(-s/2) Gamma(s/2) */ static GEN gamma_R(GEN s, long *ext, long prec) { GEN s2 = gmul2n(s, -1); long ms; if (typ(s) == t_SER) s2 = serextendifnegint(s2, ghalf, ext); else if ((ms = isnegint(s2)) >= 0) { GEN r = gmul(powPis(stoi(ms),prec), gdivsg(odd(ms)? -2: 2, mpfact(ms))); return serpole(r); } return gdiv(ggamma(s2,prec), powPis(s2,prec)); } /* gamma_R(s)gamma_R(s+1) = 2 (2pi)^(-s) Gamma(s) */ static GEN gamma_C(GEN s, long *ext, long prec) { long ms; if (typ(s) == t_SER) s = serextendifnegint(s, gen_1, ext); else if ((ms = isnegint(s)) >= 0) { GEN r = gmul(pow2Pis(stoi(ms),prec), gdivsg(odd(ms)? -2: 2, mpfact(ms))); return serpole(r); } return gmul2n(gdiv(ggamma(s,prec), pow2Pis(s,prec)), 1); } static GEN gammafrac(GEN r, long d) { long i, l = labs(d) + 1, j = (d > 0)? 0: 2*d; GEN T, v = cgetg(l, t_COL); for (i = 1; i < l; i++, j += 2) gel(v,i) = deg1pol_shallow(gen_1, gaddgs(r, j), 0); T = RgV_prod(v); return d > 0? T: mkrfrac(gen_1, T); } /* GR(s)=Pi^-(s/2)*gamma(s/2); GC(s)=2*(2*Pi)^-s*gamma(s) gdirect(F,s)=prod(i=1,#F,GR(s+F[i])) gfact(F,s)= { my([R,A,B]=gammafactor(F), [a,e]=A, [b,f]=B, p=poldegree(R)); subst(R,x,s) * (2*Pi)^-p * prod(i=1,#a,GR(s+a[i])^e[i]) * prod(i=1,#b,GC(s+b[i])^f[i]); } */ static GEN gammafactor(GEN Vga) { long i, r, c, l = lg(Vga); GEN v, P, a, b, e, f, E, F = cgetg(l, t_VEC), R = gen_1; for (i = 1; i < l; ++i) { GEN a = gel(Vga,i), r = gmul2n(real_i(a), -1); long q = itos(gfloor(r)); /* [Re a/2] */ r = gmul2n(gsubgs(r, q), 1); gel(F,i) = gequal0(imag_i(a)) ? r : mkcomplex(r, imag_i(a)); /* 2{Re a/2} + I*(Im a) */ if (q) R = gmul(R, gammafrac(gel(F,i), q)); } F = vec_reduce(F, &E); l = lg(E); v = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(v,i) = mkvec2(gsub(gel(F,i),gfloor(real_i(gel(F,i)))), stoi(E[i])); gen_sort_inplace(v, (void*)cmp_universal, cmp_nodata, &P); a = cgetg(l, t_VEC); e = cgetg(l, t_VECSMALL); b = cgetg(l, t_VEC); f = cgetg(l, t_VECSMALL); for (i = r = c = 1; i < l;) if (i==l-1 || cmp_universal(gel(v,i), gel(v,i+1))) { gel(a, r) = gel(F, P[i]); e[r++] = E[P[i]]; i++; } else { gel(b, c) = gel(F, P[i]); f[c++] = E[P[i]]; i+=2; } setlg(a, r); setlg(e, r); setlg(b, c); setlg(f, c); return mkvec3(R, mkvec2(a,e), mkvec2(b,f)); } static GEN polgammaeval(GEN F, GEN s) { GEN r = poleval(F, s); if (typ(s) != t_SER && gequal0(r)) { /* here typ(F) = t_POL */ long e; for (e = 1;; e++) { F = RgX_deriv(F); r = poleval(F,s); if (!gequal0(r)) break; } if (e > 1) r = gdiv(r, mpfact(e)); r = serpole(r); setvalser(r, e); } return r; } static long rfrac_degree(GEN R) { GEN a = gel(R,1), b = gel(R,2); return ((typ(a) == t_POL)? degpol(a): 0) - degpol(b); } static GEN fracgammaeval(GEN F, GEN s, long prec) { GEN R = gel(F,1); long d; switch(typ(R)) { case t_POL: d = degpol(R); R = polgammaeval(R, s); break; case t_RFRAC: d = rfrac_degree(R); R = gdiv(polgammaeval(gel(R,1), s), polgammaeval(gel(R,2), s)); break; default: return R; } return gmul(R, powrs(Pi2n(1,prec), -d)); } static GEN gammafactproduct(GEN F, GEN s, long *ext, long prec) { pari_sp av = avma; GEN R = gel(F,2), Rw = gel(R,1), Re = gel(R,2); GEN C = gel(F,3), Cw = gel(C,1), Ce = gel(C,2), z = fracgammaeval(F,s,prec); long i, lR = lg(Rw), lC = lg(Cw); *ext = 0; for (i = 1; i < lR; i++) z = gmul(z, gpowgs(gamma_R(gadd(s,gel(Rw, i)), ext, prec), Re[i])); for (i = 1; i < lC; i++) z = gmul(z, gpowgs(gamma_C(gadd(s,gel(Cw, i)), ext, prec), Ce[i])); return gerepileupto(av, z); } static int gammaordinary(GEN Vga, GEN s) { long i, d = lg(Vga)-1; for (i = 1; i <= d; i++) { GEN z = gadd(s, gel(Vga,i)); long e; if (gexpo(imag_i(z)) < -10) { z = real_i(z); if (gsigne(z) <= 0) { (void)grndtoi(z, &e); if (e < -10) return 0; } } } return 1; } /* Exponent A of t in asymptotic expansion; K(t) ~ C t^A exp(-pi d t^(2/d)). * suma = vecsum(Vga)*/ static double gammavec_expo(long d, double suma) { return (1 - d + suma) / d; } /*******************************************************************/ /* First part: computations only involving Theta(t) */ /*******************************************************************/ static void get_cone(GEN t, double *r, double *a) { const long prec = LOWDEFAULTPREC; if (typ(t) == t_COMPLEX) { t = gprec_w(t, prec); *r = gtodouble(gabs(t, prec)); *a = fabs(gtodouble(garg(t, prec))); } else { *r = fabs(gtodouble(t)); *a = 0.; } if (!*r && !*a) pari_err_DOMAIN("lfunthetainit","t","=",gen_0,t); } /* slightly larger cone than necessary, to avoid round-off problems */ static void get_cone_fuzz(GEN t, double *r, double *a) { get_cone(t, r, a); *r -= 1e-10; if (*a) *a += 1e-10; } /* Initialization m-th Theta derivative. tdom is either * - [rho,alpha]: assume |t| >= rho and |arg(t)| <= alpha * - a positive real scalar: assume t real, t >= tdom; * - a complex number t: compute at t; * N is the conductor (either the true one from ldata or a guess from * lfunconductor) */ long lfunthetacost(GEN ldata, GEN tdom, long m, long bitprec) { pari_sp av = avma; GEN Vga = ldata_get_gammavec(ldata); long d = lg(Vga)-1; double k1 = maxdd(ldata_get_k1_dbl(ldata), 0.); double c = d/2., a, A, B, logC, al, rho, T; double N = gtodouble(ldata_get_conductor(ldata)); if (!N) pari_err_TYPE("lfunthetaneed [missing conductor]", ldata); if (typ(tdom) == t_VEC && lg(tdom) == 3) { rho= gtodouble(gel(tdom,1)); al = gtodouble(gel(tdom,2)); } else get_cone_fuzz(tdom, &rho, &al); A = gammavec_expo(d, gtodouble(sumVga(Vga))); set_avma(av); a = (A+k1+1) + (m-1)/c; if (fabs(a) < 1e-10) a = 0.; logC = c*M_LN2 - log(c)/2; /* +1: fudge factor */ B = M_LN2*bitprec+logC+m*log(2*M_PI) + 1 + (k1+1)*log(N)/2 - (k1+m+1)*log(rho); if (al) { /* t = rho e^(i*al), T^(1/c) = Re(t^(1/c)) > 0, T = rho cos^c(al/c) */ double z = cos(al/c); if (z <= 0) pari_err_DOMAIN("lfunthetaneed", "arg t", ">", dbltor(c*M_PI/2), tdom); T = (d == 2 && typ(tdom) != t_VEC)? gtodouble(real_i(tdom)): rho*pow(z,c); B -= log(z) * (c * (k1+A+1) + m); } else T = rho; if (B <= 0) return 0; A = floor(0.9 + dblcoro526(a,c,B) / T * sqrt(N)); if (dblexpo(A) >= BITS_IN_LONG-1) pari_err_OVERFLOW("lfunthetacost"); return (long)A; } long lfunthetacost0(GEN L, GEN tdom, long m, long bitprec) { long n; if (is_linit(L) && linit_get_type(L)==t_LDESC_THETA) { GEN tech = linit_get_tech(L); n = lg(theta_get_an(tech))-1; } else { pari_sp av = avma; GEN ldata = lfunmisc_to_ldata_shallow(L); n = lfunthetacost(ldata, tdom? tdom: gen_1, m, bitprec); set_avma(av); } return n; } static long fracgammadegree(GEN FVga) { GEN F = gel(FVga,1); return (typ(F)==t_RFRAC)? degpol(gel(F,2)): 0; } /* Poles of a L-function can be represented in the following ways: * 1) Nothing (ldata has only 6 components, ldata_get_residue = NULL). * 2) a complex number (single pole at s = k with given residue, unknown if 0). * 3) A vector (possibly empty) of 2-component vectors [a, ra], where a is the * pole, ra a t_SER: its Taylor expansion at a. A t_VEC encodes the polar * part of L, a t_COL, the polar part of Lambda */ /* 'a' a complex number (pole), 'r' the polar part of L at 'a'; * return 'R' the polar part of Lambda at 'a' */ static GEN rtoR(GEN a, GEN r, GEN FVga, GEN N, long prec) { long v = lg(r)-2, d = fracgammadegree(FVga), ext; GEN Na, as = deg1ser_shallow(gen_1, a, varn(r), v); Na = gpow(N, gdivgu(as, 2), prec); /* make up for a possible loss of accuracy */ if (d) as = deg1ser_shallow(gen_1, a, varn(r), v + d); return gmul(gmul(r, Na), gammafactproduct(FVga, as, &ext, prec)); } /* assume r in normalized form: t_VEC of pairs [be,re] */ GEN lfunrtopoles(GEN r) { long j, l = lg(r); GEN v = cgetg(l, t_VEC); for (j = 1; j < l; j++) { GEN rj = gel(r,j), a = gel(rj,1); gel(v,j) = a; } gen_sort_inplace(v, (void*)&cmp_universal, cmp_nodata, NULL); return v; } /* r / x + O(1) */ static GEN simple_pole(GEN r) { return isintzero(r)? gen_0: serpole(r); } static GEN normalize_simple_pole(GEN r, GEN k) { long tx = typ(r); if (is_vec_t(tx)) return r; if (!is_scalar_t(tx)) pari_err_TYPE("lfunrootres [poles]", r); return mkvec(mkvec2(k, simple_pole(r))); } /* normalize the description of a polar part */ static GEN normalizepoles(GEN r, GEN k) { long iv, j, l; GEN v; if (!is_vec_t(typ(r))) return normalize_simple_pole(r, k); v = cgetg_copy(r, &l); for (j = iv = 1; j < l; j++) { GEN rj = gel(r,j), a = gel(rj,1), ra = gel(rj,2); if (!is_scalar_t(typ(a)) || typ(ra) != t_SER) pari_err_TYPE("lfunrootres [poles]",r); if (valser(ra) >= 0) continue; gel(v,iv++) = rj; } setlg(v, iv); return v; } static int residues_known(GEN r) { long i, l = lg(r); if (isintzero(r)) return 0; if (!is_vec_t(typ(r))) return 1; for (i = 1; i < l; i++) { GEN ri = gel(r,i); if (!is_vec_t(typ(ri)) || lg(ri)!=3) pari_err_TYPE("lfunrootres [poles]",r); if (isintzero(gel(ri, 2))) return 0; } return 1; } /* Compute R's from r's (r = Taylor devts of L(s), R of Lambda(s)). * 'r/eno' passed to override the one from ldata */ static GEN lfunrtoR_i(GEN ldata, GEN r, GEN eno, long prec) { GEN Vga = ldata_get_gammavec(ldata), N = ldata_get_conductor(ldata); GEN R, vr, FVga; pari_sp av = avma; long lr, j, jR; GEN k = ldata_get_k(ldata); if (!r || isintzero(eno) || !residues_known(r)) return gen_0; r = normalizepoles(r, k); if (typ(r) == t_COL) return gerepilecopy(av, r); if (typ(ldata_get_dual(ldata)) != t_INT) pari_err(e_MISC,"please give the Taylor expansion of Lambda"); vr = lfunrtopoles(r); lr = lg(vr); FVga = gammafactor(Vga); R = cgetg(2*lr, t_COL); for (j = jR = 1; j < lr; j++) { GEN rj = gel(r,j), a = gel(rj,1), ra = gel(rj,2); GEN Ra = rtoR(a, ra, FVga, N, prec); GEN b = gsub(k, conj_i(a)); if (lg(Ra)-2 < -valser(Ra)) pari_err(e_MISC, "please give more terms in L function's Taylor expansion at %Ps", a); gel(R,jR++) = mkvec2(a, Ra); if (!tablesearch(vr, b, (int (*)(GEN,GEN))&cmp_universal)) { GEN mX = gneg(pol_x(varn(Ra))); GEN Rb = gmul(eno, gsubst(conj_i(Ra), varn(Ra), mX)); gel(R,jR++) = mkvec2(b, Rb); } } setlg(R, jR); return gerepilecopy(av, R); } static GEN lfunrtoR_eno(GEN ldata, GEN eno, long prec) { return lfunrtoR_i(ldata, ldata_get_residue(ldata), eno, prec); } static GEN lfunrtoR(GEN ldata, long prec) { return lfunrtoR_eno(ldata, ldata_get_rootno(ldata), prec); } static long prec_fix(long prec) { #ifndef LONG_IS_64BIT /* make sure that default accuracy is the same on 32/64bit */ if (odd(prec)) prec += EXTRAPREC64; #endif return prec; } /* thetainit using {an: n <= L}; if (m = 0 && easytheta), an2 is an * n^al */ static GEN lfunthetainit0(GEN ldata, GEN tdom, GEN an2, long m, long bitprec, long extrabit) { long prec = nbits2prec(bitprec); GEN tech, N = ldata_get_conductor(ldata); GEN K = gammamellininvinit(ldata, m, bitprec + extrabit); GEN R = lfunrtoR(ldata, prec); if (!tdom) tdom = gen_1; if (typ(tdom) != t_VEC) { double r, a; get_cone_fuzz(tdom, &r, &a); tdom = mkvec2(dbltor(r), a? dbltor(a): gen_0); } prec += maxss(EXTRAPREC64, nbits2extraprec(extrabit)); tech = mkvecn(7, an2,K,R, stoi(bitprec), stoi(m), tdom, gsqrt(ginv(N), prec_fix(prec))); return mkvec3(mkvecsmall(t_LDESC_THETA), ldata, tech); } /* tdom: 1) positive real number r, t real, t >= r; or * 2) [r,a], describing the cone |t| >= r, |arg(t)| <= a */ static GEN lfunthetainit_i(GEN data, GEN tdom, long m, long bit) { GEN ldata = lfunmisc_to_ldata_shallow(data); long b = 32, L = lfunthetacost(ldata, tdom, m, bit), prec = nbits2prec(bit); GEN ldatan = ldata_newprec(ldata, prec); GEN an = ldata_vecan(ldata_get_an(ldatan), L, prec); GEN Vga = ldata_get_gammavec(ldatan); if (m == 0 && Vgaeasytheta(Vga)) an = antwist(an, Vga, prec); if (typ(an) != t_VECSMALL) b = maxss(b, gexpo(an)); return lfunthetainit0(ldatan, tdom, an, m, bit, b); } GEN lfunthetainit(GEN ldata, GEN tdom, long m, long bitprec) { pari_sp av = avma; GEN S = lfunthetainit_i(ldata, tdom? tdom: gen_1, m, bitprec); return gerepilecopy(av, S); } GEN lfunan(GEN ldata, long L, long prec) { pari_sp av = avma; GEN an ; ldata = ldata_newprec(lfunmisc_to_ldata_shallow(ldata), prec); an = gerepilecopy(av, ldata_vecan(ldata_get_an(ldata), L, prec)); if (typ(an) != t_VEC) an = vecsmall_to_vec_inplace(an); return an; } static GEN mulrealvec(GEN x, GEN y) { if (is_vec_t(typ(x)) && is_vec_t(typ(y))) pari_APPLY_same(mulreal(gel(x,i),gel(y,i))) else return mulreal(x,y); } static GEN gmulvec(GEN x, GEN y) { if (is_vec_t(typ(x)) && is_vec_t(typ(y))) pari_APPLY_same(gmul(gel(x,i),gel(y,i))) else return gmul(x,y); } static GEN gdivvec(GEN x, GEN y) { if (is_vec_t(typ(x)) && is_vec_t(typ(y))) pari_APPLY_same(gdiv(gel(x,i),gel(y,i))) else return gdiv(x,y); } static GEN gsubvec(GEN x, GEN y) { if (is_vec_t(typ(x)) && !is_vec_t(typ(y))) pari_APPLY_same(gsub(gel(x,i),y)) else return gsub(x,y); } /* return [1^(2/d), 2^(2/d),...,lim^(2/d)] */ static GEN mkvroots(long d, long lim, long prec) { if (d <= 4) { GEN v = cgetg(lim+1,t_VEC); long n; switch(d) { case 1: for (n=1; n <= lim; n++) gel(v,n) = sqru(n); return v; case 2: for (n=1; n <= lim; n++) gel(v,n) = utoipos(n); return v; case 4: for (n=1; n <= lim; n++) gel(v,n) = sqrtr(utor(n, prec)); return v; } } return vecpowug(lim, gdivgu(gen_2,d), prec); } GEN lfunthetacheckinit(GEN data, GEN t, long m, long bitprec) { if (is_linit(data) && linit_get_type(data)==t_LDESC_THETA) { GEN tdom, thetainit = linit_get_tech(data); long bitprecnew = theta_get_bitprec(thetainit); long m0 = theta_get_m(thetainit); double r, al, rt, alt; if (m0 != m) pari_err_DOMAIN("lfuntheta","derivative order","!=", stoi(m),stoi(m0)); if (bitprec > bitprecnew) goto INIT; get_cone(t, &rt, &alt); tdom = theta_get_tdom(thetainit); r = gtodouble(gel(tdom,1)); al= gtodouble(gel(tdom,2)); if (rt >= r && alt <= al) return data; } INIT: return lfunthetainit_i(data, t, m, bitprec); } static GEN get_an(GEN an, long n) { if (typ(an) == t_VECSMALL) { long a = an[n]; if (a) return stoi(a); } else { GEN a = gel(an,n); if (a && !gequal0(a)) return a; } return NULL; } /* x * an[n] */ static GEN mul_an(GEN an, long n, GEN x) { if (typ(an) == t_VECSMALL) { long a = an[n]; if (a) return gmulsg(a,x); } else { GEN a = gel(an,n); if (a && !gequal0(a)) return gmul(a,x); } return NULL; } /* 2*t^a * x **/ static GEN mulT(GEN t, GEN a, GEN x, long prec) { if (gequal0(a)) return gmul2n(x,1); return gmul(x, gmul2n(gequal1(a)? t: gpow(t,a,prec), 1)); } static GEN vecan_cmul(void *E, GEN P, long a, GEN x) { (void)E; if (typ(P) == t_VECSMALL) return (a==0 || !P[a])? NULL: gmulsg(P[a], x); else return (a==0 || !gel(P,a))? NULL: gmul(gel(P,a), x); } /* d=2, 2 sum_{n <= N} a(n) (n t)^al q^n, q = exp(-2pi t), * an2[n] = a(n) * n^al */ static GEN theta2_i(GEN an2, long N, GEN t, GEN al, long prec) { GEN S, q, pi2 = Pi2n(1,prec); const struct bb_algebra *alg = get_Rg_algebra(); setsigne(pi2,-1); q = gexp(gmul(pi2, t), prec); /* Brent-Kung in case the a_n are small integers */ S = gen_bkeval(an2, N, q, 1, NULL, alg, vecan_cmul); return mulT(t, al, S, prec); } static GEN theta2(GEN an2, long N, GEN t, GEN al, long prec) { pari_sp av = avma; return gerepileupto(av, theta2_i(an2, N, t, al, prec)); } /* d=1, 2 sum_{n <= N} a_n (n t)^al q^(n^2), q = exp(-pi t^2), * an2[n] is a_n n^al */ static GEN theta1(GEN an2, long N, GEN t, GEN al, long prec) { GEN q = gexp(gmul(negr(mppi(prec)), gsqr(t)), prec); GEN vexp = gsqrpowers(q, N), S = gen_0; pari_sp av = avma; long n; for (n = 1; n <= N; n++) { GEN c = mul_an(an2, n, gel(vexp,n)); if (c) { S = gadd(S, c); if (gc_needed(av, 3)) S = gerepileupto(av, S); } } return mulT(t, al, S, prec); } /* If m > 0, compute m-th derivative of theta(t) = theta0(t/sqrt(N)) * with absolute error 2^-bitprec; theta(t)=\sum_{n\ge1}a(n)K(nt/N^(1/2)) */ GEN lfuntheta(GEN data, GEN t, long m, long bitprec) { pari_sp ltop = avma; long limt, d; GEN isqN, vecan, Vga, ldata, theta, thetainit, S; long n, prec; theta = lfunthetacheckinit(data, t, m, bitprec); ldata = linit_get_ldata(theta); thetainit = linit_get_tech(theta); vecan = theta_get_an(thetainit); isqN = theta_get_isqrtN(thetainit); prec = maxss(realprec(isqN), nbits2prec(bitprec)); t = gprec_w(t, prec); limt = lg(vecan)-1; if (theta == data) limt = minss(limt, lfunthetacost(ldata, t, m, bitprec)); if (!limt) { set_avma(ltop); S = real_0_bit(-bitprec); if (!is_real_t(typ(t)) || !ldata_isreal(ldata)) S = gerepilecopy(ltop, mkcomplex(S,S)); return S; } t = gmul(t, isqN); Vga = ldata_get_gammavec(ldata); d = lg(Vga)-1; if (m == 0 && Vgaeasytheta(Vga)) { if (theta_get_m(thetainit) > 0) vecan = antwist(vecan, Vga, prec); if (d == 1) S = theta1(vecan, limt, t, gel(Vga,1), prec); else S = theta2_i(vecan, limt, t, vecmin(Vga), prec); } else { GEN K = theta_get_K(thetainit); GEN vroots = mkvroots(d, limt, prec); pari_sp av; t = gpow(t, gdivgu(gen_2,d), prec); S = gen_0; av = avma; for (n = 1; n <= limt; ++n) { GEN nt, an = get_an(vecan, n); if (!an) continue; nt = gmul(gel(vroots,n), t); if (m) an = gmul(an, powuu(n, m)); S = gadd(S, gmul(an, gammamellininvrt(K, nt, bitprec))); if ((n & 0x1ff) == 0) S = gerepileupto(av, S); } if (m) S = gmul(S, gpowgs(isqN, m)); } return gerepileupto(ltop, S); } /*******************************************************************/ /* Second part: Computation of L-Functions. */ /*******************************************************************/ struct lfunp { long precmax, Dmax, D, M, m0, nmax, d, vgaell; double k1, dc, dw, dh, MAXs, sub; GEN L, an, bn; }; static void lfunp_set(GEN ldata, long der, long bitprec, struct lfunp *S) { const long derprec = (der > 1)? dbllog2(mpfact(der)): 0; /* log2(der!) */ GEN Vga, N, L, k; long k1, d, m, M, flag, nmax; double a, A, E, hd, Ep, d2, suma, maxs, mins, sub, B0,B1; double logN2, logC, Lestimate, Mestimate; Vga = ldata_get_gammavec(ldata); S->d = d = lg(Vga)-1; d2 = d/2.; suma = gtodouble(sumVga(Vga)); k = ldata_get_k(ldata); N = ldata_get_conductor(ldata); logN2 = log(gtodouble(N)) / 2; maxs = S->dc + S->dw; mins = S->dc - S->dw; S->MAXs = maxdd(maxs, gtodouble(k)-mins); /* we compute Lambda^(der)(s) / der!; need to compensate for L^(der)(s) * ln |gamma(s)| ~ -(pi/4) \sum_i |Im(s + a_i)|; max with 1: fudge factor */ a = (M_PI/(4*M_LN2))*(d*S->dh + sumVgaimpos(Vga)); S->D = (long)ceil(bitprec + derprec + maxdd(a, 1)); E = M_LN2*S->D; /* D:= required absolute bitprec */ Ep = E + maxdd(M_PI * S->dh * d2, (d*S->MAXs + suma - 1) * log(E)); hd = d2*M_PI*M_PI / Ep; S->m0 = (long)ceil(M_LN2/hd); hd = M_LN2/S->m0; logC = d2*M_LN2 - log(d2)/2; k1 = maxdd(ldata_get_k1_dbl(ldata), 0.); S->k1 = k1; /* assume |a_n| << n^k1 with small implied constant */ A = gammavec_expo(d, suma); sub = 0.; if (mins > 1) { GEN sig = dbltor(mins); sub += logN2*mins; if (gammaordinary(Vga, sig)) { long ext; GEN gas = gammafactproduct(gammafactor(Vga), sig, &ext, LOWDEFAULTPREC); if (typ(gas) != t_SER) { double dg = dbllog2(gas); if (dg > 0) sub += dg * M_LN2; } } } S->sub = sub; M = 1000; L = cgetg(M+2, t_VECSMALL); a = S->k1 + A; B0 = 5 + E - S->sub + logC + S->k1*logN2; /* 5 extra bits */ B1 = hd * (S->MAXs - S->k1); Lestimate = dblcoro526(a + S->MAXs - 2./d, d/2., E - S->sub + logC - log(2*M_PI*hd) + S->MAXs*logN2); Mestimate = ((Lestimate > 0? log(Lestimate): 0) + logN2) / hd; nmax = 0; flag = 0; for (m = 0;; m++) { double x, H = logN2 - m*hd, B = B0 + m*B1; long n; x = dblcoro526(a, d/2., B); n = floor(x*exp(H)); if (n > nmax) nmax = n; if (m > M) { M *= 2; L = vecsmall_lengthen(L,M+2); } L[m+1] = n; if (n == 0) { if (++flag > 2 && m > Mestimate) break; } else flag = 0; } m -= 2; while (m > 0 && !L[m]) m--; if (m == 0) { nmax = 1; L[1] = 1; m = 1; } /* can happen for tiny bitprec */ setlg(L, m+1); S->M = m-1; S->L = L; S->nmax = nmax; S->Dmax = S->D + (long)ceil((S->M * hd * S->MAXs - S->sub) / M_LN2); if (S->Dmax < S->D) S->Dmax = S->D; S->precmax = nbits2prec(S->Dmax); if (DEBUGLEVEL > 1) err_printf("Dmax=%ld, D=%ld, M = %ld, nmax = %ld, m0 = %ld\n", S->Dmax,S->D,S->M,S->nmax, S->m0); } static GEN lfuninit_pol(GEN v, GEN poqk, long prec) { long m, M = lg(v) - 2; GEN pol = cgetg(M+3, t_POL); pol[1] = evalsigne(1) | evalvarn(0); gel(pol, 2) = gprec_w(gmul2n(gel(v,1), -1), prec); if (poqk) for (m = 2; m <= M+1; m++) gel(pol, m+1) = gprec_w(gmul(gel(poqk,m), gel(v,m)), prec); else for (m = 2; m <= M+1; m++) gel(pol, m+1) = gprec_w(gel(v,m), prec); return RgX_renormalize_lg(pol, M+3); } static void worker_init(long q, GEN *an, GEN *bn, GEN *AB, GEN *A, GEN *B) { if (typ(*bn) == t_INT) *bn = NULL; if (*bn) { *AB = cgetg(3, t_VEC); gel(*AB,1) = *A = cgetg(q+1, t_VEC); gel(*AB,2) = *B = cgetg(q+1, t_VEC); if (typ(an) == t_VEC) *an = RgV_kill0(*an); if (typ(bn) == t_VEC) *bn = RgV_kill0(*bn); } else { *B = NULL; *AB = *A = cgetg(q+1, t_VEC); if (typ(*an) == t_VEC) *an = RgV_kill0(*an); } } GEN lfuninit_theta2_worker(long r, GEN L, GEN qk, GEN a, GEN di, GEN an, GEN bn) { long q, m, prec = di[1], M = di[2], m0 = di[3], L0 = lg(an)-1; GEN AB, A, B; worker_init((M - r) / m0 + 1, &an, &bn, &AB, &A, &B); for (q = 0, m = r; m <= M; m += m0, q++) { GEN t = gel(qk, m+1); long N = minss(L[m+1],L0); gel(A, q+1) = theta2(an, N, t, a, prec); /* theta(exp(mh)) */ if (bn) gel(B, q+1) = theta2(bn, N, t, a, prec); } return AB; } /* theta(exp(mh)) ~ sum_{n <= N} a(n) k[m,n] */ static GEN an_msum(GEN an, long N, GEN vKm) { pari_sp av = avma; GEN s = gen_0; long n; for (n = 1; n <= N; n++) if (gel(vKm,n)) { GEN c = mul_an(an, n, gel(vKm,n)); if (c) s = gadd(s, c); } return gerepileupto(av, s); } GEN lfuninit_worker(long r, GEN K, GEN L, GEN peh2d, GEN vroots, GEN dr, GEN di, GEN an, GEN bn) { pari_sp av0 = avma; long m, n, q, L0 = lg(an)-1; double sig0 = rtodbl(gel(dr,1)), sub2 = rtodbl(gel(dr,2)); double k1 = rtodbl(gel(dr,3)), MAXs = rtodbl(gel(dr,4)); long D = di[1], M = di[2], m0 = di[3]; double M0 = sig0? sub2 / sig0: 1./0.; GEN AB, A, B, vK = cgetg(M/m0 + 2, t_VEC); for (q = 0, m = r; m <= M; m += m0, q++) gel(vK, q+1) = const_vec(L[m+1], NULL); worker_init(q, &an, &bn, &AB, &A, &B); for (m -= m0, q--; m >= 0; m -= m0, q--) { double c1 = D + ((m > M0)? m * sig0 - sub2 : 0); GEN vKm = gel(vK,q+1); /* conceptually K(m,n) */ for (n = 1; n <= L[m+1]; n++) { GEN t2d, kmn; long nn, mm, qq, p = 0; double c, c2; pari_sp av; if (gel(vKm, n)) continue; /* done already */ c = c1 + k1 * log2(n); /* n *= 2; m -= m0 => c += c2, provided m >= M0. Else c += k1 */ c2 = k1 - MAXs; /* p = largest (absolute) accuracy to which we need K(m,n) */ for (mm=m,nn=n; mm >= M0;) { if (nn <= L[mm+1] && (gel(an, nn) || (bn && gel(bn, nn)))) if (c > 0) p = maxuu(p, (ulong)c); nn <<= 1; mm -= m0; if (mm >= M0) c += c2; else { c += k1; break; } } /* mm < M0 || nn > L[mm+1] */ for ( ; mm >= 0; nn<<=1,mm-=m0,c+=k1) if (nn <= L[mm+1] && (gel(an, nn) || (bn && gel(bn, nn)))) if (c > 0) p = maxuu(p, (ulong)c); if (!p) continue; /* a_{n 2^v} = 0 for all v in range */ av = avma; t2d = mpmul(gel(vroots,n), gel(peh2d,m+1));/*(n exp(mh)/sqrt(N))^(2/d)*/ kmn = gerepileupto(av, gammamellininvrt(K, t2d, p)); for (qq=q,mm=m,nn=n; mm >= 0; nn<<=1,mm-=m0,qq--) if (nn <= L[mm+1]) gmael(vK, qq+1, nn) = kmn; } } for (q = 0, m = r; m <= M; m += m0, q++) { long N = minss(L0, L[m+1]); gel(A, q+1) = an_msum(an, N, gel(vK,q+1)); if (bn) gel(B, q+1) = an_msum(bn, N, gel(vK,q+1)); } return gerepileupto(av0, AB); } /* return A = [\theta(exp(mh)), m=0..M], theta(t) = sum a(n) K(n/sqrt(N) t), * h = log(2)/m0. If bn != NULL, return the pair [A, B] */ static GEN lfuninit_ab(GEN theta, GEN h, struct lfunp *S) { const long M = S->M, prec = S->precmax; GEN tech = linit_get_tech(theta), isqN = theta_get_isqrtN(tech); GEN an = S->an, bn = S->bn, va, vb; struct pari_mt pt; GEN worker; long m0, r, pending; if (S->vgaell) { /* d=2 and Vga = [a,a+1] */ GEN a = vecmin(ldata_get_gammavec(linit_get_ldata(theta))); GEN qk = gpowers0(mpexp(h), M, isqN); m0 = minss(M+1, mt_nbthreads()); worker = snm_closure(is_entry("_lfuninit_theta2_worker"), mkvecn(6, S->L, qk, a, mkvecsmall3(prec, M, m0), an, bn? bn: gen_0)); } else { GEN vroots, peh2d, d2; double sig0 = S->MAXs / S->m0, sub2 = S->sub / M_LN2; /* For all 0<= m <= M, and all n <= L[m+1] such that a_n!=0, we compute * k[m,n] = K(n exp(mh)/sqrt(N)) * with ln(absolute error) <= E + max(mh sigma - sub, 0) + k1 * log(n). * N.B. we use the 'rt' variant and pass (n exp(mh)/sqrt(N))^(2/d). * Speedup: if n' = 2n and m' = m - m0 >= 0; then k[m,n] = k[m',n']. */ vroots = mkvroots(S->d, S->nmax, prec); /* vroots[n] = n^(2/d) */ d2 = gdivgu(gen_2, S->d); peh2d = gpowers0(gexp(gmul(d2,h), prec), M, gpow(isqN, d2, prec)); m0 = S->m0; /* peh2d[m+1] = (exp(mh)/sqrt(N))^(2/d) */ worker = snm_closure(is_entry("_lfuninit_worker"), mkvecn(8, theta_get_K(tech), S->L, peh2d, vroots, mkvec4(dbltor(sig0), dbltor(sub2), dbltor(S->k1), dbltor(S->MAXs)), mkvecsmall3(S->D, M, m0), an, bn? bn: gen_0)); /* For each 0 <= m <= M, we will sum for n<=L[m+1] a(n) K(m,n) * bit accuracy for K(m,n): D + k1*log2(n) + 1_{m > M0} (m*sig0 - sub2) * We restrict m to arithmetic progressions r mod m0 to save memory and * allow parallelization */ } va = cgetg(M+2, t_VEC); vb = bn? cgetg(M+2, t_VEC): NULL; mt_queue_start_lim(&pt, worker, m0); pending = 0; for (r = 0; r < m0 || pending; r++) { /* m = q m0 + r */ GEN done, A, B; long q, m, workid; mt_queue_submit(&pt, r, r < m0 ? mkvec(utoi(r)): NULL); done = mt_queue_get(&pt, &workid, &pending); if (!done) continue; if (bn) { A = gel(done,1); B = gel(done,2); } else { A = done; B = NULL; } for (q = 0, m = workid; m <= M; m += m0, q++) { gel(va, m+1) = gel(A, q+1); if (bn) gel(vb, m+1) = gel(B, q+1); } } mt_queue_end(&pt); return bn? mkvec2(va, vb): va; } static void parse_dom(double k, GEN dom, struct lfunp *S) { long l = lg(dom); if (typ(dom)!=t_VEC) pari_err_TYPE("lfuninit [domain]", dom); if (l == 1) { S->dc = 0; S->dw = -1; S->dh = -1; return; } if (l == 2) { S->dc = k/2.; S->dw = 0.; S->dh = gtodouble(gel(dom,1)); } else if (l == 3) { S->dc = k/2.; S->dw = gtodouble(gel(dom,1)); S->dh = gtodouble(gel(dom,2)); } else if (l == 4) { S->dc = gtodouble(gel(dom,1)); S->dw = gtodouble(gel(dom,2)); S->dh = gtodouble(gel(dom,3)); } else { pari_err_TYPE("lfuninit [domain]", dom); S->dc = S->dw = S->dh = 0; /*-Wall*/ } if (S->dw < 0 || S->dh < 0) pari_err_TYPE("lfuninit [domain]", dom); } /* do we have dom \subset dom0 ? dom = [center, width, height] */ int sdomain_isincl(double k, GEN dom, GEN dom0) { struct lfunp S0, S; parse_dom(k, dom, &S); if (S.dw < 0) return 1; parse_dom(k, dom0, &S0); if (S0.dw < 0) return 0; return S0.dc - S0.dw <= S.dc - S.dw && S0.dc + S0.dw >= S.dc + S.dw && S0.dh >= S.dh; } static int checklfuninit(GEN linit, GEN DOM, long der, long bitprec) { GEN ldata = linit_get_ldata(linit); GEN domain = lfun_get_domain(linit_get_tech(linit)); GEN dom = domain_get_dom(domain); if (lg(dom) == 1) return 1; return domain_get_der(domain) >= der && domain_get_bitprec(domain) >= bitprec && sdomain_isincl(gtodouble(ldata_get_k(ldata)), DOM, dom); } static GEN ginvsqrtvec(GEN x, long prec) { if (is_vec_t(typ(x))) pari_APPLY_same(ginv(gsqrt(gel(x,i), prec))) else return ginv(gsqrt(x, prec)); } GEN lfuninit_make(long t, GEN ldata, GEN tech, GEN domain) { GEN Vga = ldata_get_gammavec(ldata); long d = lg(Vga)-1; GEN w2 = gen_1, k2 = gmul2n(ldata_get_k(ldata), -1); GEN expot = gdivgu(gadd(gmulsg(d, gsubgs(k2, 1)), sumVga(Vga)), 4); if (typ(ldata_get_dual(ldata))==t_INT) { GEN eno = ldata_get_rootno(ldata); long prec = nbits2prec( domain_get_bitprec(domain) ); if (!isint1(eno)) w2 = ginvsqrtvec(eno, prec); } tech = mkvec3(domain, tech, mkvec4(k2, w2, expot, gammafactor(Vga))); return mkvec3(mkvecsmall(t), ldata, tech); } static GEN lfunnoinit(GEN ldata, long bitprec) { GEN tech, domain = mkvec2(cgetg(1,t_VEC), mkvecsmall2(0, bitprec)); GEN R = gen_0, r = ldata_get_residue(ldata), v = lfunrootres(ldata, bitprec); ldata = shallowcopy(ldata); gel(ldata,6) = gel(v,3); if (r) { if (isintzero(r)) setlg(ldata,7); else gel(ldata,7) = r; R = gel(v,2); } tech = mkvec3(domain, gen_0, R); return lfuninit_make(t_LDESC_INIT, ldata, tech, domain); } static void lfunparams2(struct lfunp *S) { GEN L = S->L, an = S->an, bn = S->bn; double pmax; long m, nan, nmax, neval, M = S->M; S->vgaell = 0; /* try to reduce parameters now we know the a_n (some may be 0) */ if (typ(an) == t_VEC) an = RgV_kill0(an); nan = S->nmax; /* lg(an)-1 may be large than this */ nmax = neval = 0; if (!bn) for (m = 0; m <= M; m++) { long n = minss(nan, L[m+1]); while (n > 0 && !gel(an,n)) n--; if (n > nmax) nmax = n; neval += n; L[m+1] = n; /* reduce S->L[m+1] */ } else { if (typ(bn) == t_VEC) bn = RgV_kill0(bn); for (m = 0; m <= M; m++) { long n = minss(nan, L[m+1]); while (n > 0 && !gel(an,n) && !gel(bn,n)) n--; if (n > nmax) nmax = n; neval += n; L[m+1] = n; /* reduce S->L[m+1] */ } } if (DEBUGLEVEL >= 1) err_printf("expected evaluations: %ld\n", neval); for (; M > 0; M--) if (L[M+1]) break; setlg(L, M+2); S->M = M; S->nmax = nmax; /* need K(n*exp(mh)/sqrt(N)) to absolute accuracy * D + k1*log(n) + max(m * sig0 - sub2, 0) */ pmax = S->D + S->k1 * log2(L[1]); if (S->MAXs) { double sig0 = S->MAXs/S->m0, sub2 = S->sub / M_LN2; for (m = ceil(sub2 / sig0); m <= S->M; m++) { double c = S->D + m*sig0 - sub2; if (S->k1 > 0) c += S->k1 * log2(L[m+1]); pmax = maxdd(pmax, c); } } S->Dmax = pmax; S->precmax = nbits2prec(pmax); } static GEN lfun_init_theta(GEN ldata, GEN eno, struct lfunp *S) { GEN an2, dual, tdom = NULL, Vga = ldata_get_gammavec(ldata); long L, prec = S->precmax; if (eno) L = S->nmax; else { tdom = dbltor(sqrt(0.5)); L = maxss(S->nmax, lfunthetacost(ldata, tdom, 0, S->D)); } dual = ldata_get_dual(ldata); S->an = ldata_vecan(ldata_get_an(ldata), L, prec); S->bn = typ(dual)==t_INT? NULL: ldata_vecan(dual, S->nmax, prec); if (!vgaell(Vga)) lfunparams2(S); else { S->an = antwist(S->an, Vga, prec); if (S->bn) S->bn = antwist(S->bn, Vga, prec); S->vgaell = 1; } an2 = lg(Vga)-1 == 1? antwist(S->an, Vga, prec): S->an; return lfunthetainit0(ldata, tdom, an2, 0, S->Dmax, 0); } GEN lfuncost(GEN L, GEN dom, long der, long bit) { pari_sp av = avma; GEN ldata = lfunmisc_to_ldata_shallow(L); GEN w, k = ldata_get_k(ldata); struct lfunp S; parse_dom(gtodouble(k), dom, &S); if (S.dw < 0) return mkvecsmall2(0, 0); lfunp_set(ldata, der, bit, &S); w = ldata_get_rootno(ldata); if (isintzero(w)) /* for lfunrootres */ S.nmax = maxss(S.nmax, lfunthetacost(ldata, dbltor(sqrt(0.5)), 0, bit+1)); set_avma(av); return mkvecsmall2(S.nmax, S.Dmax); } GEN lfuncost0(GEN L, GEN dom, long der, long bitprec) { pari_sp av = avma; GEN C; if (is_linit(L)) { GEN tech = linit_get_tech(L); GEN domain = lfun_get_domain(tech); dom = domain_get_dom(domain); der = domain_get_der(domain); bitprec = domain_get_bitprec(domain); if (linit_get_type(L) == t_LDESC_PRODUCT) { GEN v = lfunprod_get_fact(linit_get_tech(L)), F = gel(v,1); long i, l = lg(F); C = cgetg(l, t_VEC); for (i = 1; i < l; ++i) gel(C, i) = zv_to_ZV( lfuncost(gel(F,i), dom, der, bitprec) ); return gerepileupto(av, C); } } if (!dom) pari_err_TYPE("lfuncost [missing s domain]", L); C = lfuncost(L,dom,der,bitprec); return gerepileupto(av, zv_to_ZV(C)); } static int is_dirichlet(GEN ldata) { switch(ldata_get_type(ldata)) { case t_LFUN_ZETA: case t_LFUN_KRONECKER: case t_LFUN_CHIZ: return 1; case t_LFUN_CHIGEN: return ldata_get_degree(ldata)==1; default: return 0; } } static ulong lfuninit_cutoff(GEN ldata) { GEN gN = ldata_get_conductor(ldata); ulong L, N; if (ldata_get_type(ldata) == t_LFUN_NF) /* N ~ f^(d-1), exact for d prime */ gN = sqrtnint(gN, ldata_get_degree(ldata) - 1); N = itou_or_0(gN); if (N > 1000) L = 7000; else if (N > 100) L = 5000; else if (N > 15) L = 3000; else L = 2500; return L; } GEN lfuninit(GEN lmisc, GEN dom, long der, long bitprec) { pari_sp av = avma; GEN poqk, AB, R, h, theta, ldata, eno, r, domain, tech, k; struct lfunp S; if (is_linit(lmisc)) { long t = linit_get_type(lmisc); if (t == t_LDESC_INIT || t == t_LDESC_PRODUCT) { if (checklfuninit(lmisc, dom, der, bitprec)) return lmisc; pari_warn(warner,"lfuninit: insufficient initialization"); } } ldata = lfunmisc_to_ldata_shallow(lmisc); switch (ldata_get_type(ldata)) { case t_LFUN_NF: { GEN T = gel(ldata_get_an(ldata), 2); return gerepilecopy(av, lfunzetakinit(T, dom, der, bitprec)); } case t_LFUN_ABELREL: { GEN T = gel(ldata_get_an(ldata), 2); return gerepilecopy(av, lfunabelianrelinit(gel(T,1), gel(T,2), dom, der, bitprec)); } } k = ldata_get_k(ldata); parse_dom(gtodouble(k), dom, &S); /* Reduce domain for Dirichlet characters. NOT for Abelian t_LFUN_NF, * handled above. */ if (S.dw >= 0 && (!der && is_dirichlet(ldata))) S.dh = mindd(S.dh, lfuninit_cutoff(ldata)); if (S.dw < 0) { if (der) pari_err_IMPL("domain = [] for derivatives in lfuninit"); if (!is_dirichlet(ldata)) pari_err_IMPL("domain = [] for L functions of degree > 1"); return gerepilecopy(av, lfunnoinit(ldata, bitprec)); } lfunp_set(ldata, der, bitprec, &S); ldata = ldata_newprec(ldata, nbits2prec(S.Dmax)); r = ldata_get_residue(ldata); /* Note: all guesses should already have been performed (thetainit more * expensive than needed: should be either tdom = 1 or bitprec = S.D). * BUT if the root number / polar part do not have an algebraic * expression, there is no way to do this until we know the * precision, i.e. now. So we can't remove guessing code from here and * lfun_init_theta */ if (r && isintzero(r)) eno = NULL; else { eno = ldata_get_rootno(ldata); if (isintzero(eno)) eno = NULL; } theta = lfun_init_theta(ldata, eno, &S); if (eno && !r) R = gen_0; else { GEN v = lfunrootres(theta, S.D); ldata = shallowcopy(ldata); gel(ldata, 6) = gel(v,3); r = gel(v,1); R = gel(v,2); if (isintzero(r)) setlg(ldata,7); else gel(ldata, 7) = r; } h = divru(mplog2(S.precmax), S.m0); /* exp(kh/2 . [0..M]) */ poqk = gequal0(k) ? NULL : gpowers(gprec_w(mpexp(gmul2n(gmul(k,h), -1)), S.precmax), S.M); AB = lfuninit_ab(theta, h, &S); if (S.bn) { GEN A = gel(AB,1), B = gel(AB,2); A = lfuninit_pol(A, poqk, S.precmax); B = lfuninit_pol(B, poqk, S.precmax); AB = mkvec2(A, B); } else AB = lfuninit_pol(AB, poqk, S.precmax); tech = mkvec3(h, AB, R); domain = mkvec2(dom, mkvecsmall2(der, bitprec)); return gerepilecopy(av, lfuninit_make(t_LDESC_INIT, ldata, tech, domain)); } GEN lfuninit0(GEN lmisc, GEN dom, long der, long bitprec) { GEN z = lfuninit(lmisc, dom, der, bitprec); return z == lmisc? gcopy(z): z; } /* If s is a pole of Lambda, return polar part at s; else return NULL */ static GEN lfunpoleresidue(GEN R, GEN s) { long j; for (j = 1; j < lg(R); j++) { GEN Rj = gel(R, j), be = gel(Rj, 1); if (gequal(s, be)) return gel(Rj, 2); } return NULL; } /* Compute contribution of polar part at s when not a pole. */ static GEN veccothderivn(GEN a, long n) { long i; pari_sp av = avma; GEN c = pol_x(0), cp = mkpoln(3, gen_m1, gen_0, gen_1); GEN v = cgetg(n+2, t_VEC); gel(v, 1) = poleval(c, a); for(i = 2; i <= n+1; i++) { c = ZX_mul(ZX_deriv(c), cp); gel(v, i) = gdiv(poleval(c, a), mpfact(i-1)); } return gerepilecopy(av, v); } static GEN polepart(long n, GEN h, GEN C) { GEN h2n = gpowgs(gdiv(h, gen_2), n-1); GEN res = gmul(h2n, gel(C,n)); return odd(n)? res : gneg(res); } static GEN lfunsumcoth(GEN R, GEN s, GEN h, long prec) { long i,j; GEN S = gen_0; for (j = 1; j < lg(R); ++j) { GEN r = gel(R,j), be = gel(r,1), Rj = gel(r, 2); long e = valser(Rj); GEN z1 = gexpm1(gmul(h, gsub(s,be)), prec); /* exp(h(s-beta))-1 */ GEN c1 = gaddgs(gdivsg(2, z1), 1); /* coth((h/2)(s-beta)) */ GEN C1 = veccothderivn(c1, 1-e); for (i = e; i < 0; i++) { GEN Rbe = mysercoeff(Rj, i); GEN p1 = polepart(-i, h, C1); S = gadd(S, gmul(Rbe, p1)); } } return gmul2n(S, -1); } static GEN lfunlambda_OK(GEN linit, GEN s, GEN sdom, long bitprec); /* L is a t_LDESC_PRODUCT or t_LDESC_INIT Linit */ static GEN _product(GEN (*fun)(GEN,GEN,long), GEN L, GEN s, long bitprec) { GEN ldata = linit_get_ldata(L), v, r, F, E, C, cs; long i, l; int isreal; if (linit_get_type(L) == t_LDESC_INIT) return fun(ldata, s, bitprec); v = lfunprod_get_fact(linit_get_tech(L)); F = gel(v,1); E = gel(v,2); C = gel(v,3); l = lg(F); cs = conj_i(s); isreal = gequal(imag_i(s), imag_i(cs)); for (i = 1, r = gen_1; i < l; ++i) { GEN f = fun(gel(F, i), s, bitprec); if (typ(f)==t_VEC) f = RgV_prod(f); if (E[i]) r = gmul(r, gpowgs(f, E[i])); if (C[i]) { GEN fc = isreal? f: conj_i(fun(gel(F, i), cs, bitprec)); r = gmul(r, gpowgs(fc, C[i])); } } return (ldata_isreal(ldata) && gequal0(imag_i(s)))? real_i(r): r; } /* s a t_SER; # terms - 1 */ static long der_level(GEN s) { return signe(s)? lg(s)-3: valser(s)-1; } /* s a t_SER; return coeff(s, X^0) */ static GEN ser_coeff0(GEN s) { return simplify_shallow(polcoef_i(s, 0, -1)); } static GEN get_domain(GEN s, GEN *dom, long *der) { GEN sa = s; *der = 0; switch(typ(s)) { case t_POL: case t_RFRAC: s = toser_i(s); case t_SER: *der = der_level(s); sa = ser_coeff0(s); } *dom = mkvec3(real_i(sa), gen_0, gabs(imag_i(sa),DEFAULTPREC)); return s; } /* assume s went through get_domain and s/bitprec belong to domain */ static GEN lfunlambda_OK(GEN linit, GEN s, GEN sdom, long bitprec) { GEN dom, eno, ldata, tech, h, pol, k2, cost, S, S0 = NULL; long prec, prec0; struct lfunp D, D0; if (linit_get_type(linit) == t_LDESC_PRODUCT) return _product(&lfunlambda, linit, s, bitprec); ldata = linit_get_ldata(linit); eno = ldata_get_rootno(ldata); tech = linit_get_tech(linit); dom = lfun_get_dom(tech); if (lg(dom) == 1) return lfunlambda(linit, s, bitprec); /* FIXME:not OK! */ h = lfun_get_step(tech); prec = realprec(h); /* try to reduce accuracy */ parse_dom(0, sdom, &D0); parse_dom(0, dom, &D); if (0.8 * D.dh > D0.dh) { cost = lfuncost(linit, sdom, typ(s)==t_SER? der_level(s): 0, bitprec); prec0 = nbits2prec(cost[2]); if (prec0 < prec) { prec = prec0; h = gprec_w(h, prec); } } pol = lfun_get_pol(tech); s = gprec_w(s, prec); if (ldata_get_residue(ldata)) { GEN R = lfun_get_Residue(tech); GEN Ra = lfunpoleresidue(R, s); if (Ra) return gprec_w(Ra, nbits2prec(bitprec)); S0 = lfunsumcoth(R, s, h, prec); } k2 = lfun_get_k2(tech); if (typ(pol)==t_POL && typ(s) != t_SER && gequal(real_i(s), k2)) { /* on critical line: shortcut */ GEN polz, b = imag_i(s); polz = gequal0(b)? poleval(pol,gen_1): poleval(pol, expIr(gmul(h,b))); S = gadd(polz, gmulvec(eno, conj_i(polz))); } else { GEN z = gexp(gmul(h, gsub(s, k2)), prec); GEN zi = ginv(z), zc = conj_i(zi); if (typ(pol)==t_POL) S = gadd(poleval(pol, z), gmulvec(eno, conj_i(poleval(pol, zc)))); else S = gadd(poleval(gel(pol,1), z), gmulvec(eno, poleval(gel(pol,2), zi))); } if (S0) S = gadd(S,S0); return gprec_w(gmul(S,h), nbits2prec(bitprec)); } static long lfunspec_OK(GEN lmisc, GEN s, GEN *pldata) { long t, large = 0; GEN ldata; *pldata = ldata = lfunmisc_to_ldata_shallow(lmisc); if (!is_linit(lmisc)) lmisc = ldata; else switch(linit_get_type(lmisc)) { case t_LDESC_INIT: case t_LDESC_PRODUCT: if (lg(lfun_get_dom(linit_get_tech(lmisc))) == 1) large = 1; break; default: return 0; } switch(typ(s)) { case t_INT: case t_REAL: case t_FRAC: case t_COMPLEX: break; default: return 0; } t = ldata_get_type(ldata); switch(t) { case t_LFUN_KRONECKER: case t_LFUN_ZETA: if (typ(s) == t_INT && !is_bigint(s)) return 1; /* fall through */ case t_LFUN_NF: case t_LFUN_CHIZ: if (!large) large = (fabs(gtodouble(imag_i(s))) >= lfuninit_cutoff(ldata)); break; case t_LFUN_CHIGEN: if (ldata_get_degree(ldata) != 1) return 0; if (!large) large = (fabs(gtodouble(imag_i(s))) >= lfuninit_cutoff(ldata)); break; } if (large) { if (t == t_LFUN_NF) { GEN an = ldata_get_an(ldata), nf = gel(an,2), G = galoisinit(nf, NULL); if (isintzero(G) || !group_isabelian(galois_group(G))) return 0; } return 2; } return 0; } GEN lfunlambda(GEN lmisc, GEN s, long bitprec) { pari_sp av = avma; GEN linit = NULL, dom, z; long der; s = get_domain(s, &dom, &der); if (!der) { GEN ldata; long t = lfunspec_OK(lmisc, s, &ldata); if (t == 1) { /* special value ? */ GEN z = lfun(ldata, s, bitprec), gv = ldata_get_gammavec(ldata); long e = itou(gel(gv, 1)); if (!isintzero(z) && (e || gsigne(s) > 0)) /* TODO */ { GEN q = ldata_get_conductor(ldata); long prec = nbits2prec(bitprec); GEN se, r, Q = divir(q, mppi(prec)); se = gmul2n(gaddgs(s, e), -1); r = gmul(gpow(Q, se, prec), ggamma(se, prec)); if (e && !equali1(q)) r = gdiv(r, gsqrt(q, prec)); return gerepileupto(av, gmul(r, z)); } } if (is_linit(lmisc)) linit = lmisc; else lmisc = ldata; if (t == 2) return gerepilecopy(av, linit? _product(&lfunlambda, linit, s, bitprec) : lfunlambdalarge(ldata, s, bitprec)); } linit = lfuninit(lmisc, dom, der, bitprec); z = lfunlambda_OK(linit,s, dom, bitprec); return gerepilecopy(av, z); } static long is_ser(GEN x) { long t = typ(x); if (t == t_SER) return 1; if (!is_vec_t(t) || lg(x)==1) return 0; if (typ(gel(x,1))==t_SER) return 1; return 0; } static GEN lfunser(GEN L) { long v = valser(L); if (v > 0) return gen_0; if (v == 0) L = gel(L, 2); else setlg(L, minss(lg(L), 2-v)); return L; } static GEN lfunservec(GEN x) { if (typ(x)==t_SER) return lfunser(x); pari_APPLY_same(lfunser(gel(x,i))) } static GEN lfununext(GEN L) { setlg(L, maxss(lg(L)-1, valser(L)? 2: 3)); return normalizeser(L); } static GEN lfununextvec(GEN x) { if (typ(x)==t_SER) return lfununext(x); pari_APPLY_same(lfununext(gel(x,i))); } /* assume lmisc is an linit, s went through get_domain and s/bitprec belong * to domain */ static GEN lfun_OK(GEN linit, GEN s, GEN sdom, long bitprec) { GEN N, gas, S, FVga, res, ss = s; long prec = nbits2prec(bitprec), ext; FVga = lfun_get_factgammavec(linit_get_tech(linit)); S = lfunlambda_OK(linit, s, sdom, bitprec); if (is_ser(S)) { GEN r = typ(S)==t_SER ? S : gel(S,1); long d = lg(r) - 2 + fracgammadegree(FVga); if (typ(s) == t_SER) ss = sertoser(s, d); else ss = deg1ser_shallow(gen_1, s, varn(r), d); } gas = gammafactproduct(FVga, ss, &ext, prec); N = ldata_get_conductor(linit_get_ldata(linit)); res = gdiv(S, gmul(gpow(N, gdivgu(ss, 2), prec), gas)); if (typ(s) != t_SER && is_ser(res)) res = lfunservec(res); else if (ext) res = lfununextvec(res); return gprec_w(res, prec); } GEN lfun(GEN lmisc, GEN s, long bitprec) { pari_sp av = avma; GEN linit = NULL, ldata, dom, z; long der; s = get_domain(s, &dom, &der); if (der && typ(s) != t_SER) { if (lfunspec_OK(lmisc, s, &ldata)) { linit = lfuninit(lmisc, cgetg(1,t_VEC), 0, bitprec); return derivnumk((void*)linit, (GEN(*)(void*,GEN,long))&lfun, s, stoi(der), nbits2prec(bitprec)); } } else { long t = lfunspec_OK(lmisc, s, &ldata); if (t == 1) { /* special value ? */ long D = itos_or_0(gel(ldata_get_an(ldata), 2)), ss = itos(s); if (D) { if (ss <= 0) return lfunquadneg(D, ss); /* ss > 0 */ if ((!odd(ss) && D > 0) || (odd(ss) && D < 0)) { long prec = nbits2prec(bitprec), q = labs(D); ss = 1 - ss; /* <= 0 */ z = powrs(divrs(mppi(prec + EXTRAPREC64), q), 1-ss); z = mulrr(shiftr(z, -ss), sqrtr_abs(utor(q, prec))); z = gdiv(z, mpfactr(-ss, prec)); if (smodss(ss, 4) > 1) togglesign(z); return gmul(z, lfunquadneg(D, ss)); } } } if (is_linit(lmisc)) linit = lmisc; else lmisc = ldata; if (t == 2) return gerepilecopy(av, linit? _product(&lfun, linit, s, bitprec) : lfunlarge(ldata, s, bitprec)); } linit = lfuninit(lmisc, dom, der, bitprec); z = lfun_OK(linit, s, dom, bitprec); return gerepilecopy(av, z); } /* given a t_SER a+x*s(x), return x*s(x), shallow */ static GEN sersplit1(GEN s, GEN *head) { long i, l = lg(s); GEN y; *head = simplify_shallow(mysercoeff(s, 0)); if (valser(s) > 0) return s; y = cgetg(l-1, t_SER); y[1] = s[1]; setvalser(y, 1); for (i=3; i < l; i++) gel(y,i-1) = gel(s,i); return normalizeser(y); } /* order of pole of Lambda at s (0 if regular point) */ static long lfunlambdaord(GEN linit, GEN s) { GEN tech = linit_get_tech(linit); if (linit_get_type(linit)==t_LDESC_PRODUCT) { GEN v = lfunprod_get_fact(linit_get_tech(linit)); GEN F = gel(v, 1), E = gel(v, 2), C = gel(v, 3); long i, ex = 0, l = lg(F); for (i = 1; i < l; i++) ex += lfunlambdaord(gel(F,i), s) * (E[i]+C[i]); return ex; } if (ldata_get_residue(linit_get_ldata(linit))) { GEN r = lfunpoleresidue(lfun_get_Residue(tech), s); if (r) return lg(r)-2; } return 0; } static GEN derser(GEN res, long m) { long v = valser(res); if (v > m) return gen_0; if (v >= 0) return gmul(mysercoeff(res, m), mpfact(m)); else return derivn(res, m, -1); } static GEN derservec(GEN x, long m) { pari_APPLY_same(derser(gel(x,i),m)) } /* derivative of order m > 0 of L (flag = 0) or Lambda (flag = 1) */ static GEN lfunderiv(GEN lmisc, long m, GEN s, long flag, long bitprec) { pari_sp ltop = avma; GEN res, S = NULL, linit, ldata, dom; long der, prec = nbits2prec(bitprec); if (m <= 0) pari_err_DOMAIN("lfun", "D", "<=", gen_0, stoi(m)); s = get_domain(s, &dom, &der); if (typ(s) != t_SER && lfunspec_OK(lmisc, s, &ldata) == 2) { linit = lfuninit(lmisc, cgetg(1,t_VEC), 0, bitprec); return derivnumk((void*)linit, (GEN(*)(void*,GEN,long))&lfun, s, stoi(der + m), prec); } linit = lfuninit(lmisc, dom, der + m, bitprec); if (lg(lfun_get_dom(linit_get_tech(linit))) == 1) pari_err_IMPL("domain = [] for derivatives in lfuninit"); if (typ(s) == t_SER) { GEN a; if (valser(s) < 0) pari_err_DOMAIN("lfun","valuation", "<", gen_0, s); S = sersplit1(s, &a); s = deg1ser_shallow(gen_1, a, varn(S), m + ceildivuu(lg(s)-2, valser(S))); } else { long e = lfunlambdaord(linit, s) + m + 1; /* HACK: pretend lfuninit was done to right accuracy */ if (gequal0(s)) { s = gen_0; e--; } s = deg1ser_shallow(gen_1, s, 0, e); } res = flag ? lfunlambda_OK(linit, s, dom, bitprec): lfun_OK(linit, s, dom, bitprec); if (S) res = gsubst(derivn(res, m, -1), varn(S), S); else if (typ(res)==t_SER) { long v = valser(res); if (v > m) { set_avma(ltop); return gen_0; } if (v >= 0) res = gmul(mysercoeff(res, m), mpfact(m)); else res = derivn(res, m, -1); } else if (is_ser(res)) res = derservec(res, m); return gerepilecopy(ltop, gprec_w(res, prec)); } GEN lfunlambda0(GEN lmisc, GEN s, long der, long bitprec) { return der? lfunderiv(lmisc, der, s, 1, bitprec) : lfunlambda(lmisc, s, bitprec); } GEN lfun0(GEN lmisc, GEN s, long der, long bitprec) { return der? lfunderiv(lmisc, der, s, 0, bitprec) : lfun(lmisc, s, bitprec); } GEN lfunhardy(GEN lmisc, GEN t, long bitprec) { pari_sp ltop = avma; long prec = nbits2prec(bitprec), d, isbig = 0; GEN linit, h, ldata, tech, w2, k2, E, a, argz, z; switch(typ(t)) { case t_INT: case t_FRAC: case t_REAL: break; default: pari_err_TYPE("lfunhardy",t); } if (lfunspec_OK(lmisc, mkcomplex(gen_0, t), &ldata) == 2) { long B = bitprec + maxss(gexpo(t), 0); GEN L = NULL; isbig = 1; k2 = ghalf; z = mkcomplex(k2, t); if (is_linit(lmisc)) { linit = lmisc; if (linit_get_type(linit) == t_LDESC_PRODUCT) L = mkvec(linit);/*HACK*/ } else { linit = lfunnoinit(ldata, B); ldata = linit_get_ldata(linit); /* make sure eno is included */ } h = lfunloglambdalarge(L? L: ldata, gprec_w(z, nbits2prec(B)), B); tech = linit_get_tech(linit); } else { GEN k = ldata_get_k(ldata); GEN dom = mkvec3(gmul2n(k, -1), gen_0, gabs(t,LOWDEFAULTPREC)); if (!is_linit(lmisc)) lmisc = ldata; linit = lfuninit(lmisc, dom, 0, bitprec); tech = linit_get_tech(linit); k2 = lfun_get_k2(tech); z = mkcomplex(k2, t); h = lfunlambda_OK(linit, z, dom, bitprec); } w2 = lfun_get_w2(tech); E = lfun_get_expot(tech); /* 4E = d(k2 - 1) + real(vecsum(Vga)) */ d = ldata_get_degree(ldata); /* more accurate than garg: k/2 in Q */ argz = gequal0(k2)? Pi2n(-1, prec): gatan(gdiv(t, k2), prec); prec = precision(argz); /* prec may have increased: don't lose accuracy if |z|^2 is exact */ a = gsub(gmulsg(d, gmul(t, gmul2n(argz,-1))), gmul(E, glog(gnorm(z),prec))); if (!isint1(w2) && typ(ldata_get_dual(ldata))==t_INT) h = isbig ? gadd(h, glog(w2, prec)) : mulrealvec(h, w2); if (typ(h) == t_COMPLEX && gexpo(imag_i(h)) < -(bitprec >> 1)) h = real_i(h); if (isbig) h = greal(gexp(gadd(h, a), prec)); else h = gmul(h, gexp(a, prec)); return gerepileupto(ltop, h); } /* L = log(t); return \sum_{i = 0}^{v-1} R[-i-1] L^i/i! */ static GEN theta_pole_contrib(GEN R, long v, GEN L) { GEN s = mysercoeff(R,-v); long i; for (i = v-1; i >= 1; i--) s = gadd(mysercoeff(R,-i), gdivgu(gmul(s,L), i)); return s; } /* subtract successively rather than adding everything then subtracting. * The polar part is "large" and suffers from cancellation: a little stabler * this way */ static GEN theta_add_polar_part(GEN S, GEN R, GEN t, long prec) { GEN logt = NULL; long j, l = lg(R); for (j = 1; j < l; j++) { GEN Rj = gel(R,j), b = gel(Rj,1), Rb = gel(Rj,2); long v = -valser(Rb); if (v > 1 && !logt) logt = glog(t, prec); S = gsub(S, gmul(theta_pole_contrib(Rb,v,logt), gpow(t,b,prec))); } return S; } static long lfuncheckfeq_i(GEN theta, GEN thetad, GEN t0, GEN t0i, long bitprec) { GEN ldata = linit_get_ldata(theta); GEN S0, S0i, w, eno; long prec = nbits2prec(bitprec); if (thetad) S0 = lfuntheta(thetad, t0, 0, bitprec); else S0 = conj_i(lfuntheta(theta, conj_i(t0), 0, bitprec)); S0i = lfuntheta(theta, t0i, 0, bitprec); eno = ldata_get_rootno(ldata); if (ldata_get_residue(ldata)) { GEN R = theta_get_R(linit_get_tech(theta)); if (gequal0(R)) { GEN v, r; long t = ldata_get_type(ldata); if (t == t_LFUN_NF || t == t_LFUN_ABELREL) { /* inefficient since theta not needed; no need to optimize for this (artificial) query [e.g. lfuncheckfeq(t_POL)] */ GEN L = lfuninit(ldata,zerovec(3),0,bitprec); return lfuncheckfeq(L,t0,bitprec); } v = lfunrootres(theta, bitprec); r = gel(v,1); if (gequal0(eno)) eno = gel(v,3); R = lfunrtoR_i(ldata, r, eno, nbits2prec(bitprec)); } S0i = theta_add_polar_part(S0i, R, t0, prec); } if (gequal0(S0i) || gequal0(S0)) pari_err_PREC("lfuncheckfeq"); w = gdivvec(S0i, gmul(S0, gpow(t0, ldata_get_k(ldata), prec))); /* missing rootno: guess it */ if (gequal0(eno)) eno = lfunrootno(theta, bitprec); w = gsubvec(w, eno); if (thetad) w = gdivvec(w, eno); /* |eno| may be large in non-dual case */ return gexpo(w); } /* Check whether the coefficients, conductor, weight, polar part and root * number are compatible with the functional equation at t0 and 1/t0. * Different from lfunrootres. */ long lfuncheckfeq(GEN lmisc, GEN t0, long bitprec) { GEN ldata, theta, thetad, t0i; pari_sp av; if (is_linit(lmisc) && linit_get_type(lmisc)==t_LDESC_PRODUCT) { GEN v = lfunprod_get_fact(linit_get_tech(lmisc)), F = gel(v,1); long i, b = -bitprec, l = lg(F); for (i = 1; i < l; i++) b = maxss(b, lfuncheckfeq(gel(F,i), t0, bitprec)); return b; } av = avma; if (!t0) { /* ~Pi/3 + I/7, some random complex number */ t0 = mkcomplex(uutoQ(355,339), uutoQ(1,7)); t0i = ginv(t0); } else if (gcmpgs(gnorm(t0), 1) < 0) { t0i = t0; t0 = ginv(t0); } else t0i = ginv(t0); /* |t0| >= 1 */ theta = lfunthetacheckinit(lmisc, t0i, 0, bitprec); ldata = linit_get_ldata(theta); thetad = theta_dual(theta, ldata_get_dual(ldata)); return gc_long(av, lfuncheckfeq_i(theta, thetad, t0, t0i, bitprec)); } /*******************************************************************/ /* Compute root number and residues */ /*******************************************************************/ /* round root number to \pm 1 if close to integer. */ static GEN ropm1(GEN w, long prec) { long e; GEN r; if (typ(w) == t_INT) return w; r = grndtoi(w, &e); return (e < -prec/2)? r: w; } /* theta for t=1/sqrt(2) and t2==2t simultaneously, saving 25% of the work. * Assume correct initialization (no thetacheck) */ static void lfunthetaspec(GEN linit, long bitprec, GEN *pv, GEN *pv2) { pari_sp av = avma, av2; GEN t, Vga, an, K, ldata, thetainit, v, v2, vroots; long L, prec, n, d; ldata = linit_get_ldata(linit); thetainit = linit_get_tech(linit); prec = nbits2prec(bitprec); Vga = ldata_get_gammavec(ldata); d = lg(Vga)-1; if (Vgaeasytheta(Vga)) { GEN v2 = sqrtr(real2n(1, nbits2prec(bitprec))); GEN v = shiftr(v2,-1); *pv = lfuntheta(linit, v, 0, bitprec); *pv2= lfuntheta(linit, v2, 0, bitprec); return; } an = RgV_kill0( theta_get_an(thetainit) ); L = lg(an)-1; /* to compute theta(1/sqrt(2)) */ t = ginv(gsqrt(gmul2n(ldata_get_conductor(ldata), 1), prec)); /* t = 1/sqrt(2N) */ /* From then on, the code is generic and could be used to compute * theta(t) / theta(2t) without assuming t = 1/sqrt(2) */ K = theta_get_K(thetainit); vroots = mkvroots(d, L, prec); t = gpow(t, gdivgu(gen_2, d), prec); /* rt variant: t->t^(2/d) */ /* v = \sum_{n <= L, n odd} a_n K(nt) */ for (v = gen_0, n = 1; n <= L; n+=2) { GEN tn, Kn, a = gel(an, n); if (!a) continue; av2 = avma; tn = gmul(t, gel(vroots,n)); Kn = gammamellininvrt(K, tn, bitprec); v = gerepileupto(av2, gadd(v, gmul(a,Kn))); } /* v += \sum_{n <= L, n even} a_n K(nt), v2 = \sum_{n <= L/2} a_n K(2n t) */ for (v2 = gen_0, n = 1; n <= L/2; n++) { GEN t2n, K2n, a = gel(an, n), a2 = gel(an,2*n); if (!a && !a2) continue; av2 = avma; t2n = gmul(t, gel(vroots,2*n)); K2n = gerepileupto(av2, gammamellininvrt(K, t2n, bitprec)); if (a) v2 = gadd(v2, gmul(a, K2n)); if (a2) v = gadd(v, gmul(a2,K2n)); } *pv = v; *pv2 = v2; gerepileall(av, 2, pv,pv2); } static GEN Rtor(GEN a, GEN R, GEN ldata, long prec) { GEN FVga = gammafactor(ldata_get_gammavec(ldata)); GEN Na = gpow(ldata_get_conductor(ldata), gdivgu(a,2), prec); long ext; return gdiv(R, gmul(Na, gammafactproduct(FVga, a, &ext, prec))); } /* v = theta~(t), vi = theta(1/t) */ static GEN get_eno(GEN R, GEN k, GEN t, GEN v, GEN vi, long vx, long bitprec, long force) { long prec = nbits2prec(bitprec); GEN a0, a1, S = deg1pol(gmul(gpow(t,k,prec), gneg(v)), vi, vx); S = theta_add_polar_part(S, R, t, prec); if (typ(S) != t_POL || degpol(S) != 1) return NULL; a1 = gel(S,3); if (!force && gexpo(a1) < -bitprec/4) return NULL; a0 = gel(S,2); return gdivvec(a0, gneg(a1)); } /* Return w using theta(1/t) - w t^k \bar{theta}(t) = polar_part(t,w). * The full Taylor expansion of L must be known */ GEN lfunrootno(GEN linit, long bitprec) { GEN ldata, t, eno, v, vi, R, thetad; long c = 0, prec = nbits2prec(bitprec), vx = fetch_var(); GEN k; pari_sp av; /* initialize for t > 1/sqrt(2) */ linit = lfunthetacheckinit(linit, dbltor(sqrt(0.5)), 0, bitprec); ldata = linit_get_ldata(linit); k = ldata_get_k(ldata); R = ldata_get_residue(ldata)? lfunrtoR_eno(ldata, pol_x(vx), prec) : cgetg(1, t_VEC); t = gen_1; v = lfuntheta(linit, t, 0, bitprec); thetad = theta_dual(linit, ldata_get_dual(ldata)); vi = !thetad ? conj_i(v): lfuntheta(thetad, t, 0, bitprec); eno = get_eno(R,k,t,vi,v, vx, bitprec, 0); if (!eno && !thetad) { /* t = sqrt(2), vi = theta(1/t), v = theta(t) */ lfunthetaspec(linit, bitprec, &vi, &v); t = sqrtr(utor(2, prec)); eno = get_eno(R,k,t,conj_i(v),vi, vx, bitprec, 0); } av = avma; while (!eno) { t = addsr(1, shiftr(utor(pari_rand(), prec), -2-BITS_IN_LONG)); /* t in [1,1.25[ */ v = thetad? lfuntheta(thetad, t, 0, bitprec) : conj_i(lfuntheta(linit, t, 0, bitprec)); vi = lfuntheta(linit, ginv(t), 0, bitprec); eno = get_eno(R,k,t,v,vi, vx, bitprec, c++ == 5); set_avma(av); } delete_var(); return ropm1(eno,prec); } /* Find root number and/or residues when L-function coefficients and conductor are known. For the moment at most a single residue allowed. */ GEN lfunrootres(GEN data, long bitprec) { pari_sp ltop = avma; GEN k, w, r, R, a, b, e, v, v2, be, ldata, linit; long prec; ldata = lfunmisc_to_ldata_shallow(data); r = ldata_get_residue(ldata); k = ldata_get_k(ldata); w = ldata_get_rootno(ldata); if (r) r = normalize_simple_pole(r, k); if (!r || residues_known(r)) { if (isintzero(w)) w = lfunrootno(data, bitprec); if (!r) r = R = gen_0; else R = lfunrtoR_eno(ldata, w, nbits2prec(bitprec)); return gerepilecopy(ltop, mkvec3(r, R, w)); } linit = lfunthetacheckinit(data, dbltor(sqrt(0.5)), 0, bitprec); prec = nbits2prec(bitprec); if (lg(r) > 2) pari_err_IMPL("multiple poles in lfunrootres"); /* Now residue unknown, and r = [[be,0]]. */ be = gmael(r, 1, 1); if (ldata_isreal(ldata) && gequalm1(w)) R = lfuntheta(linit, gen_1, 0, bitprec); else { GEN p2k = gpow(gen_2,k,prec); lfunthetaspec(linit, bitprec, &v2, &v); if (gequal(gmulsg(2, be), k)) pari_err_IMPL("pole at k/2 in lfunrootres"); if (gequal(be, k)) { a = conj_i(gsub(gmul(p2k, v), v2)); b = subiu(p2k, 1); e = gmul(gsqrt(p2k, prec), gsub(v2, v)); } else { GEN tk2 = gsqrt(p2k, prec); GEN tbe = gpow(gen_2, be, prec); GEN tkbe = gpow(gen_2, gdivgu(gsub(k, be), 2), prec); a = conj_i(gsub(gmul(tbe, v), v2)); b = gsub(gdiv(tbe, tkbe), tkbe); e = gsub(gmul(gdiv(tbe, tk2), v2), gmul(tk2, v)); } if (isintzero(w)) { /* Now residue unknown, r = [[be,0]], and w unknown. */ GEN t0 = mkfrac(utoi(11),utoi(10)); GEN th1 = lfuntheta(linit, t0, 0, bitprec); GEN th2 = lfuntheta(linit, ginv(t0), 0, bitprec); GEN tbe = gpow(t0, gmulsg(2, be), prec); GEN tkbe = gpow(t0, gsub(k, be), prec); GEN tk2 = gpow(t0, k, prec); GEN c = conj_i(gsub(gmul(tbe, th1), th2)); GEN d = gsub(gdiv(tbe, tkbe), tkbe); GEN f = gsub(gmul(gdiv(tbe, tk2), th2), gmul(tk2, th1)); GEN D = gsub(gmul(a, d), gmul(b, c)); w = gdiv(gsub(gmul(d, e), gmul(b, f)), D); } w = ropm1(w, prec); R = gdiv(gsub(e, gmul(a, w)), b); } r = normalize_simple_pole(Rtor(be, R, ldata, prec), be); R = lfunrtoR_i(ldata, r, w, prec); return gerepilecopy(ltop, mkvec3(r, R, w)); } /*******************************************************************/ /* Zeros */ /*******************************************************************/ struct lhardyz_t { long bitprec, prec; GEN linit; }; static GEN lfunhardyzeros(void *E, GEN t) { struct lhardyz_t *S = (struct lhardyz_t*)E; GEN z = gprec_wensure(lfunhardy(S->linit, t, S->bitprec), S->prec); return typ(z) == t_VEC ? RgV_prod(z): z; } /* initialize for computation on critical line up to height h, zero * of order <= m */ static GEN lfuncenterinit(GEN lmisc, double h, long m, long bitprec) { GEN ldata = lfunmisc_to_ldata_shallow(lmisc); if (m < 0) { /* choose a sensible default */ m = 4; if (is_linit(lmisc) && linit_get_type(lmisc) == t_LDESC_INIT) { GEN domain = lfun_get_domain(linit_get_tech(lmisc)); m = domain_get_der(domain); } } if (is_dirichlet(ldata)) m = 0; return lfuninit(lmisc, mkvec(dbltor(h)), m, bitprec); } long lfunorderzero(GEN lmisc, long m, long bitprec) { pari_sp ltop = avma; GEN eno, ldata, linit, k2; long G, c0, c, st; if (is_linit(lmisc) && linit_get_type(lmisc) == t_LDESC_PRODUCT) { GEN M = gmael(linit_get_tech(lmisc), 2,1); long i, l = lg(M); for (c=0, i=1; i < l; i++) c += lfunorderzero(gel(M,i), m, bitprec); return c; } linit = lfuncenterinit(lmisc, 0, m, bitprec); ldata = linit_get_ldata(linit); eno = ldata_get_rootno(ldata); k2 = gmul2n(ldata_get_k(ldata), -1); G = -bitprec/2; c0 = 0; st = 1; if (typ(eno) == t_VEC) { long i, l = lg(eno), cnt = l-1, s = 0; GEN v = zero_zv(l-1); if (ldata_isreal(ldata)) st = 2; for (c = c0; cnt; c += st) { GEN L = lfun0(linit, k2, c, bitprec); for (i = 1; i < l; i++) { if (v[i]==0 && gexpo(gel(L,i)) > G) { v[i] = c; cnt--; s += c; } } } return gc_long(ltop,s); } else { if (ldata_isreal(ldata)) { st = 2; if (!gequal1(eno)) c0 = 1; } for (c = c0;; c += st) if (gexpo(lfun0(linit, k2, c, bitprec)) > G) return gc_long(ltop, c); } } /* assume T1 * T2 > 0, T1 <= T2 */ static void lfunzeros_i(struct lhardyz_t *S, GEN *pw, long *ct, GEN T1, GEN T2, long d, GEN cN, GEN pi2, GEN pi2div, long precinit, long prec) { GEN T = T1, w = *pw; long W = lg(w)-1, s = gsigne(lfunhardyzeros(S, T1)); for(;;) { pari_sp av = avma; GEN D, T0, z; D = gcmp(T, pi2) < 0? cN : gadd(cN, gmulsg(d, glog(gdiv(T, pi2), prec))); D = gdiv(pi2div, gmulsg(d, D)); for(;;) { long s0; T0 = T; T = gadd(T, D); if (gcmp(T, T2) >= 0) T = T2; s0 = gsigne(lfunhardyzeros(S, T)); if (s0 != s) { s = s0; break; } if (T == T2) { setlg(w, *ct); *pw = w; return; } } z = zbrent(S, lfunhardyzeros, T0, T, prec); /* T <= T2 */ gerepileall(av, 2, &T, &z); if (*ct > W) { W *= 2; w = vec_lengthen(w, W); } if (typ(z) == t_REAL) z = rtor(z, precinit); gel(w, (*ct)++) = z; } setlg(w, *ct); *pw = w; } GEN lfunzeros(GEN ldata, GEN lim, long divz, long bitprec) { pari_sp ltop = avma; GEN linit, pi2, pi2div, cN, w, T, h1, h2; long i, d, NEWD, c, ct, s1, s2, prec, prec0 = nbits2prec(bitprec); double maxt; struct lhardyz_t S; if (is_linit(ldata) && linit_get_type(ldata) == t_LDESC_PRODUCT) { GEN M = gmael(linit_get_tech(ldata), 2,1); long l = lg(M); w = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(w,i) = lfunzeros(gel(M,i), lim, divz, bitprec); return gerepileupto(ltop, vecsort0(shallowconcat1(w), NULL, 0)); } if (typ(lim) == t_VEC) { double H1, H2; if (lg(lim) != 3 || gcmp(gel(lim, 1), gel(lim, 2)) >= 0) pari_err_TYPE("lfunzeros",lim); h1 = gel(lim, 1); H1 = gtodouble(h1); h2 = gel(lim, 2); H2 = gtodouble(h2); maxt = maxdd(fabs(H1), fabs(H2)); if (H1 * H2 > 0) { GEN LDATA = lfunmisc_to_ldata_shallow(ldata); double m = mindd(fabs(H1), fabs(H2)); if (is_dirichlet(LDATA) && m > lfuninit_cutoff(LDATA)) maxt = 0; } } else { if (gcmp(lim, gen_0) <= 0) pari_err_TYPE("lfunzeros",lim); h1 = gen_0; h2 = lim; maxt = gtodouble(h2); } S.linit = linit = lfuncenterinit(ldata, maxt, -1, bitprec); S.bitprec = bitprec; S.prec = prec0; ldata = linit_get_ldata(linit); d = ldata_get_degree(ldata); NEWD = minss((long) ceil(bitprec + (M_PI/(4*M_LN2)) * d * maxt), lfun_get_bitprec(linit_get_tech(linit))); prec = nbits2prec(NEWD); cN = gdiv(ldata_get_conductor(ldata), gpowgs(Pi2n(-1, prec), d)); cN = gexpo(cN) >= 0? gaddsg(d, gmulsg(2, glog(cN, prec))): utoi(d); pi2 = Pi2n(1, prec); pi2div = gdivgu(pi2, labs(divz)); s1 = gsigne(h1); s2 = gsigne(h2); w = cgetg(100+1, t_VEC); c = 1; ct = 0; T = NULL; if (s1 <= 0 && s2 >= 0) { GEN r = ldata_get_residue(ldata); if (!r || gequal0(r)) { ct = lfunorderzero(linit, -1, bitprec); if (ct) T = real2n(-prec / (2*ct), prec); } } if (s1 <= 0) { if (s1 < 0) lfunzeros_i(&S, &w, &c, h1, T? negr(T): h2, d, cN, pi2, pi2div, prec0, prec); if (ct) { long n = lg(w)-1; if (c + ct >= n) w = vec_lengthen(w, n + ct); for (i = 1; i <= ct; i++) gel(w,c++) = gen_0; } } if (s2 > 0 && (T || s1 >= 0)) lfunzeros_i(&S, &w, &c, T? T: h1, h2, d, cN, pi2, pi2div, prec0, prec); return gerepilecopy(ltop, w); } /*******************************************************************/ /* Guess conductor */ /*******************************************************************/ struct huntcond_t { GEN k; GEN theta, thetad; GEN *pM, *psqrtM, *pMd, *psqrtMd; }; static void condset(struct huntcond_t *S, GEN M, long prec) { *(S->pM) = M; *(S->psqrtM) = gsqrt(ginv(M), prec); if (S->thetad != S->theta) { *(S->pMd) = *(S->pM); *(S->psqrtMd) = *(S->psqrtM); } } /* M should eventually converge to N, the conductor. L has no pole. */ static GEN wrap1(void *E, GEN M) { struct huntcond_t *S = (struct huntcond_t*)E; GEN thetainit, tk, p1, p1inv; GEN t = mkfrac(stoi(11), stoi(10)); long prec, bitprec; thetainit = linit_get_tech(S->theta); bitprec = theta_get_bitprec(thetainit); prec = nbits2prec(bitprec); condset(S, M, prec); tk = gpow(t, S->k, prec); p1 = lfuntheta(S->thetad, t, 0, bitprec); p1inv = lfuntheta(S->theta, ginv(t), 0, bitprec); return glog(gabs(gmul(tk, gdiv(p1, p1inv)), prec), prec); } /* M should eventually converge to N, the conductor. L has a pole. */ static GEN wrap2(void *E, GEN M) { struct huntcond_t *S = (struct huntcond_t*)E; GEN t1k, t2k, p1, p1inv, p2, p2inv, thetainit, R; GEN t1 = mkfrac(stoi(11), stoi(10)), t2 = mkfrac(stoi(13), stoi(11)); GEN t1be, t2be, t1bemk, t2bemk, t1kmbe, t2kmbe; GEN F11, F12, F21, F22, P1, P2, res; long prec, bitprec; GEN k = S->k; thetainit = linit_get_tech(S->theta); bitprec = theta_get_bitprec(thetainit); prec = nbits2prec(bitprec); condset(S, M, prec); p1 = lfuntheta(S->thetad, t1, 0, bitprec); p2 = lfuntheta(S->thetad, t2, 0, bitprec); p1inv = lfuntheta(S->theta, ginv(t1), 0, bitprec); p2inv = lfuntheta(S->theta, ginv(t2), 0, bitprec); t1k = gpow(t1, k, prec); t2k = gpow(t2, k, prec); R = theta_get_R(thetainit); if (typ(R) == t_VEC) { GEN be = gmael(R, 1, 1); t1be = gpow(t1, be, prec); t1bemk = gdiv(gsqr(t1be), t1k); t2be = gpow(t2, be, prec); t2bemk = gdiv(gsqr(t2be), t2k); t1kmbe = gdiv(t1k, t1be); t2kmbe = gdiv(t2k, t2be); } else { /* be = k */ t1be = t1k; t1bemk = t1k; t1kmbe = gen_1; t2be = t2k; t2bemk = t2k; t2kmbe = gen_1; } F11 = conj_i(gsub(gmul(gsqr(t1be), p1), p1inv)); F12 = conj_i(gsub(gmul(gsqr(t2be), p2), p2inv)); F21 = gsub(gmul(t1k, p1), gmul(t1bemk, p1inv)); F22 = gsub(gmul(t2k, p2), gmul(t2bemk, p2inv)); P1 = gsub(gmul(t1bemk, t1be), t1kmbe); P2 = gsub(gmul(t2bemk, t2be), t2kmbe); res = gdiv(gsub(gmul(P2,F21), gmul(P1,F22)), gsub(gmul(P2,F11), gmul(P1,F12))); return glog(gabs(res, prec), prec); } /* If flag = 0 (default) return all conductors found as integers. If flag = 1, return the approximations, not the integers. If flag = 2, return all, even nonintegers. */ static GEN checkconductor(GEN v, long bit, long flag) { GEN w; long e, j, k, l = lg(v); if (flag == 2) return v; w = cgetg(l, t_VEC); for (j = k = 1; j < l; j++) { GEN N = grndtoi(gel(v,j), &e); if (e < -bit) gel(w,k++) = flag ? gel(v,j): N; } if (k == 2) return gel(w,1); setlg(w,k); return w; } static GEN parse_maxcond(GEN maxN) { GEN M; if (!maxN) M = utoipos(10000); else if (typ(maxN) == t_VEC) { if (!RgV_is_ZV(maxN)) pari_err_TYPE("lfunconductor",maxN); return ZV_sort_shallow(maxN); } else M = maxN; return (typ(M) == t_INT)? addiu(M, 1): gceil(M); } GEN lfunconductor(GEN data, GEN maxcond, long flag, long bitprec) { struct huntcond_t S; pari_sp av = avma; GEN ldata = lfunmisc_to_ldata_shallow(data); GEN ld, r, v, theta, thetad, M, tdom, t0 = NULL, t0i = NULL; GEN (*eval)(void *, GEN); long prec; M = parse_maxcond(maxcond); r = ldata_get_residue(ldata); if (typ(M) == t_VEC) /* select in list */ { if (lg(M) == 1) { set_avma(av); return cgetg(1,t_VEC); } eval = NULL; tdom = dbltor(0.7); } else if (!r) { eval = wrap1; tdom = uutoQ(10,11); } else { if (typ(r) == t_VEC && lg(r) > 2) pari_err_IMPL("multiple poles in lfunconductor"); eval = wrap2; tdom = uutoQ(11,13); } if (eval) bitprec += bitprec/2; prec = nbits2prec(bitprec); ld = shallowcopy(ldata); gel(ld, 5) = eval? M: veclast(M); theta = lfunthetainit_i(ld, tdom, 0, bitprec); thetad = theta_dual(theta, ldata_get_dual(ldata)); gel(theta,3) = shallowcopy(linit_get_tech(theta)); S.k = ldata_get_k(ldata); S.theta = theta; S.thetad = thetad? thetad: theta; S.pM = &gel(linit_get_ldata(theta),5); S.psqrtM = &gel(linit_get_tech(theta),7); if (thetad) { S.pMd = &gel(linit_get_ldata(thetad),5); S.psqrtMd = &gel(linit_get_tech(thetad),7); } if (!eval) { long i, besti = 0, beste = -10, l = lg(M); t0 = uutoQ(11,10); t0i = uutoQ(10,11); for (i = 1; i < l; i++) { pari_sp av2 = avma; long e; condset(&S, gel(M,i), prec); e = lfuncheckfeq_i(theta, thetad, t0, t0i, bitprec); set_avma(av2); if (e < beste) { beste = e; besti = i; } else if (e == beste) beste = besti = 0; /* tie: forget */ } if (!besti) { set_avma(av); return cgetg(1,t_VEC); } return gerepilecopy(av, mkvec2(gel(M,besti), stoi(beste))); } v = solvestep((void*)&S, eval, ghalf, M, gen_2, 14, prec); return gerepilecopy(av, checkconductor(v, bitprec/2, flag)); } /* assume chi primitive */ static GEN znchargauss_i(GEN G, GEN chi, long bitprec) { GEN z, q, F = znstar_get_N(G); long prec; if (equali1(F)) return gen_1; prec = nbits2prec(bitprec); q = sqrtr_abs(itor(F, prec)); z = lfuntheta(mkvec2(G,chi), gen_1, 0, bitprec); if (gexpo(z) < 10 - bitprec) { if (equaliu(F,300)) { GEN z = rootsof1u_cx(25, prec); GEN n = znconreyexp(G, chi); if (equaliu(n, 131)) return gmul(q, gpowgs(z,14)); if (equaliu(n, 71)) return gmul(q, gpowgs(z,11)); } if (equaliu(F,600)) { GEN z = rootsof1u_cx(25, prec); GEN n = znconreyexp(G, chi); if (equaliu(n, 491)) return gmul(q, gpowgs(z,7)); if (equaliu(n, 11)) return gmul(q, gpowgs(z,18)); } pari_err_BUG("znchargauss [ Theta(chi,1) = 0 ]"); } z = gmul(gdiv(z, conj_i(z)), q); if (zncharisodd(G,chi)) z = mulcxI(z); return z; } static GEN Z_radical(GEN N, long *om) { GEN P = gel(Z_factor(N), 1); *om = lg(P)-1; return ZV_prod(P); } GEN znchargauss(GEN G, GEN chi, GEN a, long bitprec) { GEN v, T, N, F, b0, b1, b2, bF, a1, aF, A, r, GF, tau, B, faB, u, S; long omb0, prec = nbits2prec(bitprec); pari_sp av = avma; if (typ(chi) != t_COL) chi = znconreylog(G,chi); T = znchartoprimitive(G, chi); GF = gel(T,1); chi = gel(T,2); /* now primitive */ N = znstar_get_N(G); F = znstar_get_N(GF); if (equalii(N,F)) b1 = bF = gen_1; else { v = Z_ppio(diviiexact(N,F), F); bF = gel(v,2); /* (N/F, F^oo) */ b1 = gel(v,3); /* cofactor */ } if (!a) a = a1 = aF = gen_1; else { if (typ(a) != t_INT) pari_err_TYPE("znchargauss",a); a = modii(a, N); if (!signe(a)) { set_avma(av); return is_pm1(F)? eulerphi(N): gen_0; } v = Z_ppio(a, F); aF = gel(v,2); a1 = gel(v,3); } if (!equalii(aF, bF)) { set_avma(av); return gen_0; } b0 = Z_radical(b1, &omb0); b2 = diviiexact(b1, b0); A = dvmdii(a1, b2, &r); if (r != gen_0) { set_avma(av); return gen_0; } B = gcdii(A,b0); faB = Z_factor(B); /* squarefree */ S = eulerphi(mkvec2(B,faB)); if (odd(omb0 + lg(gel(faB,1))-1)) S = negi(S); /* moebius(b0/B) * phi(B) */ S = mulii(S, mulii(aF,b2)); tau = znchargauss_i(GF, chi, bitprec); u = Fp_div(b0, A, F); if (!equali1(u)) { GEN ord = zncharorder(GF, chi), z = rootsof1_cx(ord, prec); tau = gmul(tau, znchareval(GF, chi, u, mkvec2(z,ord))); } return gerepileupto(av, gmul(tau, S)); } pari-2.17.2/src/basemath/char.c0000644000175000017500000011422214676526175014645 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" /*********************************************************************/ /** **/ /** GENERIC ABELIAN CHARACTERS **/ /** **/ /*********************************************************************/ /* check whether G is a znstar */ int checkznstar_i(GEN G) { return (typ(G) == t_VEC && lg(G) == 6 && typ(znstar_get_N(G)) == t_INT && typ(znstar_get_faN(G)) == t_VEC && typ(gel(G,1)) == t_VEC && lg(gel(G,1)) == 3); } int char_check(GEN cyc, GEN chi) { return typ(chi) == t_VEC && lg(chi) == lg(cyc) && RgV_is_ZV(chi); } /* Shallow; return [ d[1], d[1]/d[2],...,d[1]/d[n] ] */ GEN cyc_normalize(GEN d) { long i, l = lg(d); GEN C, D; if (l == 1) return mkvec(gen_1); D = cgetg(l, t_VEC); gel(D,1) = C = gel(d,1); for (i = 2; i < l; i++) gel(D,i) = diviiexact(C, gel(d,i)); return D; } /* chi character [D,C] given by chi(g_i) = \zeta_D^C[i] for all i, return * [d,c] such that chi(g_i) = \zeta_d^c[i] for all i and d minimal */ GEN char_simplify(GEN D, GEN C) { GEN d = D; if (lg(C) == 1) d = gen_1; else { GEN t = gcdii(d, ZV_content(C)); if (!equali1(t)) { long tc = typ(C); C = ZC_Z_divexact(C, t); settyp(C, tc); d = diviiexact(d, t); } } return mkvec2(d,C); } /* Shallow; ncyc from cyc_normalize(): ncyc[1] = cyc[1], * ncyc[i] = cyc[i]/cyc[1] for i > 1; chi character on G ~ cyc. * Return [d,c] such that: chi( g_i ) = e(chi[i] / cyc[i]) = e(c[i]/ d) */ GEN char_normalize(GEN chi, GEN ncyc) { long i, l = lg(chi); GEN c = cgetg(l, t_VEC); if (l > 1) { gel(c,1) = gel(chi,1); for (i = 2; i < l; i++) gel(c,i) = mulii(gel(chi,i), gel(ncyc,i)); } return char_simplify(gel(ncyc,1), c); } /* Called by function 's'. x is a group object affording ".cyc" method, and * chi an abelian character. Return NULL if the group is (Z/nZ)^* [special * case more character types allowed] and x.cyc otherwise */ static GEN get_cyc(GEN x, GEN chi, const char *s) { switch(nftyp(x)) { case typ_BIDZ: if (!zncharcheck(x, chi)) pari_err_TYPE(s, chi); return NULL; case typ_GCHAR: x = gchar_get_cyc(x); if (!is_vec_t(typ(chi)) || lg(chi) != lg(x) || !RgV_is_ZV(chi)) pari_err_TYPE(s, chi); /* FIXME: handle norm component */ return x; default: if (typ(x) != t_VEC || !RgV_is_ZV(x)) x = member_cyc(x); if (!char_check(x, chi)) pari_err_TYPE(s, chi); return x; } } /* conjugate character [ZV/ZC] */ GEN charconj(GEN cyc, GEN chi) { long i, l; GEN z = cgetg_copy(chi, &l); for (i = 1; i < l; i++) { GEN c = gel(chi,i); gel(z,i) = signe(c)? subii(gel(cyc,i), c): gen_0; } return z; } GEN charconj0(GEN x, GEN chi) { GEN cyc = get_cyc(x, chi, "charconj"); return cyc? charconj(cyc, chi): zncharconj(x, chi); } GEN charorder(GEN cyc, GEN x) { pari_sp av = avma; long i, l = lg(cyc); GEN f = gen_1; for (i = 1; i < l; i++) if (signe(gel(x,i))) { GEN c, o = gel(cyc,i); if (!signe(o)) return gerepileupto(av,mkoo()); c = gcdii(o, gel(x,i)); if (!is_pm1(c)) o = diviiexact(o,c); f = lcmii(f, o); } return gerepileuptoint(av, f); } GEN charorder0(GEN x, GEN chi) { GEN cyc = get_cyc(x, chi, "charorder"); return cyc? charorder(cyc, chi): zncharorder(x, chi); } /* chi character of abelian G: chi[i] = chi(z_i), where G = \oplus Z/cyc[i] z_i. * Return Ker chi */ GEN charker(GEN cyc, GEN chi) { long i, l = lg(cyc); GEN nchi, ncyc, m, U; if (l == 1) return cgetg(1,t_MAT); /* trivial subgroup */ ncyc = cyc_normalize(cyc); nchi = char_normalize(chi, ncyc); m = shallowconcat(gel(nchi,2), gel(nchi,1)); U = gel(ZV_extgcd(m), 2); setlg(U,l); for (i = 1; i < l; i++) setlg(U[i], l); return hnfmodid(U, gel(ncyc,1)); } GEN charker0(GEN x, GEN chi) { GEN cyc = get_cyc(x, chi, "charker"); return cyc? charker(cyc, chi): zncharker(x, chi); } GEN charpow(GEN cyc, GEN a, GEN N) { long i, l; GEN v = cgetg_copy(a, &l); for (i = 1; i < l; i++) gel(v,i) = Fp_mul(gel(a,i), N, gel(cyc,i)); return v; } GEN charmul(GEN cyc, GEN a, GEN b) { long i, l; GEN v = cgetg_copy(a, &l); for (i = 1; i < l; i++) gel(v,i) = Fp_add(gel(a,i), gel(b,i), gel(cyc,i)); return v; } GEN chardiv(GEN cyc, GEN a, GEN b) { long i, l; GEN v = cgetg_copy(a, &l); for (i = 1; i < l; i++) gel(v,i) = Fp_sub(gel(a,i), gel(b,i), gel(cyc,i)); return v; } GEN charpow0(GEN x, GEN a, GEN N) { GEN cyc = get_cyc(x, a, "charpow"); return cyc? charpow(cyc, a, N): zncharpow(x, a, N); } GEN charmul0(GEN x, GEN a, GEN b) { const char *s = "charmul"; GEN cyc = get_cyc(x, a, s); if (!cyc) { if (!zncharcheck(x, b)) pari_err_TYPE(s, b); return zncharmul(x, a, b); } else { if (!char_check(cyc, b)) pari_err_TYPE(s, b); return charmul(cyc, a, b); } } GEN chardiv0(GEN x, GEN a, GEN b) { const char *s = "chardiv"; GEN cyc = get_cyc(x, a, s); if (!cyc) { if (!zncharcheck(x, b)) pari_err_TYPE(s, b); return znchardiv(x, a, b); } else { if (!char_check(cyc, b)) pari_err_TYPE(s, b); return chardiv(cyc, a, b); } } static GEN chareval_i(GEN nchi, GEN dlog, GEN z) { GEN o, q, r, b = gel(nchi,1); GEN a = FpV_dotproduct(gel(nchi,2), dlog, b); /* image is a/b in Q/Z */ if (!z) return gdiv(a,b); if (typ(z) == t_INT) { q = dvmdii(z, b, &r); if (signe(r)) pari_err_TYPE("chareval", z); return mulii(a, q); } /* return z^(a*o/b), assuming z^o = 1 and b | o */ if (typ(z) != t_VEC || lg(z) != 3) pari_err_TYPE("chareval", z); o = gel(z,2); if (typ(o) != t_INT) pari_err_TYPE("chareval", z); q = dvmdii(o, b, &r); if (signe(r)) pari_err_TYPE("chareval", z); q = mulii(a, q); /* in [0, o[ since a is reduced mod b */ z = gel(z,1); if (typ(z) == t_VEC) { if (itos_or_0(o) != lg(z)-1) pari_err_TYPE("chareval", z); return gcopy(gel(z, itos(q)+1)); } else return gpow(z, q, DEFAULTPREC); } static GEN not_coprime(GEN z) { return (!z || typ(z) == t_INT)? gen_m1: gen_0; } static GEN get_chi(GEN cyc, GEN chi) { if (!char_check(cyc,chi)) pari_err_TYPE("chareval", chi); return char_normalize(chi, cyc_normalize(cyc)); } /* G a bnr. FIXME: horribly inefficient to check that (x,N)=1, what to do ? */ static int bnr_coprime(GEN G, GEN x) { GEN t, N = gel(bnr_get_mod(G), 1); if (typ(x) == t_INT) /* shortcut */ { t = gcdii(gcoeff(N,1,1), x); if (equali1(t)) return 1; t = idealadd(G, N, x); return equali1(gcoeff(t,1,1)); } x = idealnumden(G, x); t = idealadd(G, N, gel(x,1)); if (!equali1(gcoeff(t,1,1))) return 0; t = idealadd(G, N, gel(x,2)); return equali1(gcoeff(t,1,1)); } GEN chareval(GEN G, GEN chi, GEN x, GEN z) { pari_sp av = avma; GEN nchi, L; switch(nftyp(G)) { case typ_BNR: if (!bnr_coprime(G, x)) return not_coprime(z); L = isprincipalray(G, x); nchi = get_chi(bnr_get_cyc(G), chi); break; case typ_BNF: L = isprincipal(G, x); nchi = get_chi(bnf_get_cyc(G), chi); break; case typ_BIDZ: if (checkznstar_i(G)) return gerepileupto(av, znchareval(G, chi, x, z)); /* don't implement chars on general bid: need an nf... */ case typ_GCHAR: pari_err_TYPE("chareval [use gchareval to evaluate a grossencharacter]", G); default: pari_err_TYPE("chareval", G); return NULL;/* LCOV_EXCL_LINE */ } return gerepileupto(av, chareval_i(nchi, L, z)); } /* nchi = [ord,D] a quasi-normalized character (ord may be a multiple of * the character order); return v such that v[n] = -1 if (n,N) > 1 else * chi(n) = e(v[n]/ord), 1 <= n <= N */ GEN ncharvecexpo(GEN G, GEN nchi) { long N = itou(znstar_get_N(G)), ord = itou(gel(nchi,1)), i, j, l; GEN cyc, gen, d, t, t1, t2, t3, e, u, u1, u2, u3; GEN D = gel(nchi,2), v = const_vecsmall(N,-1); pari_sp av = avma; if (typ(D) == t_COL) { cyc = znstar_get_conreycyc(G); gen = znstar_get_conreygen(G); } else { cyc = znstar_get_cyc(G); gen = znstar_get_gen(G); } l = lg(cyc); e = u = cgetg(N+1,t_VECSMALL); d = t = cgetg(N+1,t_VECSMALL); *++d = 1; *++e = 0; v[*d] = *e; for (i = 1; i < l; i++) { ulong g = itou(gel(gen,i)), c = itou(gel(cyc,i)), x = itou(gel(D,i)); for (t1=t,u1=u,j=c-1; j; j--,t1=t2,u1=u2) for (t2=d,u2=e, t3=t1,u3=u1; t3 0 */ GEN coprimes_zv(ulong N) { GEN v = const_vecsmall(N,1); pari_sp av = avma; GEN P = gel(factoru(N),1); long i, l = lg(P); for (i = 1; i < l; i++) { ulong p = P[i], j; for (j = p; j <= N; j += p) v[j] = 0; } set_avma(av); return v; } /* cf zv_cyc_minimal: return k such that g*k is minimal (wrt lex) */ long zv_cyc_minimize(GEN cyc, GEN g, GEN coprime) { pari_sp av = avma; long d, k, e, i, maxi, k0, bestk, l = lg(g), o = lg(coprime)-1; GEN best, gk, gd; ulong t; if (o == 1) return 1; for (i = 1; i < l; i++) if (g[i]) break; if (g[i] == 1) return 1; k0 = Fl_invgen(g[i], cyc[i], &t); d = cyc[i] / (long)t; if (k0 > 1) g = vecmoduu(Flv_Fl_mul(g, k0, cyc[i]), cyc); for (i++; i < l; i++) if (g[i]) break; if (i == l) return k0; cyc = vecslice(cyc,i,l-1); g = vecslice(g, i,l-1); e = cyc[1]; gd = Flv_Fl_mul(g, d, e); bestk = 1; best = g; maxi = e/ugcd(d,e); for (gk = g, k = d+1, i = 1; i < maxi; k += d, i++) { long ko = k % o; gk = Flv_add(gk, gd, e); if (!ko || !coprime[ko]) continue; gk = vecmoduu(gk, cyc); if (vecsmall_lexcmp(gk, best) < 0) { best = gk; bestk = k; } } return gc_long(av, bestk == 1? k0: (long) Fl_mul(k0, bestk, o)); } /* g of order o in abelian group G attached to cyc. Is g a minimal generator * [wrt lex order] of the cyclic subgroup it generates; * coprime = coprimes_zv(o) */ long zv_cyc_minimal(GEN cyc, GEN g, GEN coprime) { pari_sp av = avma; long i, maxi, d, k, e, l = lg(g), o = lg(coprime)-1; /* elt order */ GEN gd, gk; if (o == 1) return 1; for (k = 1; k < l; k++) if (g[k]) break; if (g[k] == 1) return 1; if (cyc[k] % g[k]) return 0; d = cyc[k] / g[k]; /* > 1 */ for (k++; k < l; k++) /* skip following 0s */ if (g[k]) break; if (k == l) return 1; cyc = vecslice(cyc,k,l-1); g = vecslice(g, k,l-1); e = cyc[1]; /* find k in (Z/e)^* such that g*k mod cyc is lexicographically minimal, * k = 1 mod d to fix the first nonzero entry */ gd = Flv_Fl_mul(g, d, e); maxi = e/ugcd(d,e); for (gk = g, k = d+1, i = 1; i < maxi; i++, k += d) { long ko = k % o; gk = Flv_add(gk, gd, e); if (!coprime[ko]) continue; gk = vecmoduu(gk, cyc); if (vecsmall_lexcmp(gk, g) < 0) return gc_long(av,0); } return gc_long(av,1); } static GEN coprime_tables(long N) { GEN D = divisorsu(N), v = const_vec(N, NULL); long i, l = lg(D); for (i = 1; i < l; i++) gel(v, D[i]) = coprimes_zv(D[i]); return v; } /* enumerate all group elements, modulo (Z/cyc[1])^* */ static GEN cyc2elts_normal(GEN cyc, long maxord, GEN ORD) { long i, n, o, N, j = 1; GEN z, vcoprime; if (typ(cyc) != t_VECSMALL) cyc = vec_to_vecsmall(cyc); n = lg(cyc)-1; N = zv_prod(cyc); z = cgetg(N+1, t_VEC); if (1 <= maxord && (!ORD|| zv_search(ORD,1))) gel(z,j++) = zero_zv(n); if (n == 0) { setlg(z, j); return z; } vcoprime = coprime_tables(cyc[1]); for (i = n; i > 0; i--) { GEN cyc0 = vecslice(cyc,i+1,n), pre = zero_zv(i); GEN D = divisorsu(cyc[i]), C = cyc2elts(cyc0); long s, t, lD = lg(D), nC = lg(C)-1; /* remove last element */ for (s = 1; s < lD-1; s++) { long o0 = D[lD-s]; /* cyc[i] / D[s] */ if (o0 > maxord) continue; pre[i] = D[s]; if (!ORD || zv_search(ORD,o0)) { GEN c = vecsmall_concat(pre, zero_zv(n-i)); gel(z,j++) = c; } for (t = 1; t < nC; t++) { GEN chi0 = gel(C,t); o = lcmuu(o0, zv_charorder(cyc0,chi0)); if (o <= maxord && (!ORD || zv_search(ORD,o))) { GEN c = vecsmall_concat(pre, chi0); if (zv_cyc_minimal(cyc, c, gel(vcoprime,o))) gel(z,j++) = c; } } } } setlg(z,j); return z; } GEN chargalois(GEN G, GEN ORD) { pari_sp av = avma; long maxord, i, l; GEN v, cyc = (typ(G) == t_VEC && RgV_is_ZVpos(G))? G: member_cyc(G); if (lg(cyc) == 1 && !ORD) retmkvec(cgetg(1,t_VEC)); maxord = itou(cyc_get_expo(cyc)); if (ORD) switch(typ(ORD)) { long l; case t_VEC: ORD = ZV_to_zv(ORD); case t_VECSMALL: l = lg(ORD); if (l > 2) { ORD = leafcopy(ORD); vecsmall_sort(ORD); } if (l == 1) { set_avma(av); return cgetg(1, t_VEC); } maxord = minss(maxord, ORD[l-1]); break; case t_INT: maxord = minss(maxord, itos(ORD)); ORD = NULL; break; default: pari_err_TYPE("chargalois", ORD); } v = cyc2elts_normal(cyc, maxord, ORD); l = lg(v); for(i = 1; i < l; i++) gel(v,i) = zv_to_ZV(gel(v,i)); return gerepileupto(av, v); } /*********************************************************************/ /** **/ /** (Z/NZ)^* AND DIRICHLET CHARACTERS **/ /** **/ /*********************************************************************/ GEN znstar0(GEN N, long flag) { GEN F = NULL, P, E, cyc, gen, mod, G; long i, i0, l, nbprimes; pari_sp av = avma; if (flag && flag != 1) pari_err_FLAG("znstar"); if ((F = check_arith_all(N,"znstar"))) { F = clean_Z_factor(F); N = typ(N) == t_VEC? gel(N,1): factorback(F); } if (!signe(N)) { if (flag) pari_err_IMPL("znstar(0,1)"); set_avma(av); retmkvec3(gen_2, mkvec(gen_2), mkvec(gen_m1)); } N = absi_shallow(N); if (abscmpiu(N,2) <= 0) { G = mkvec3(gen_1, cgetg(1,t_VEC), cgetg(1,t_VEC)); if (flag) { GEN v = const_vec(6,cgetg(1,t_VEC)); gel(v,3) = cgetg(1,t_MAT); F = equali1(N)? mkvec2(cgetg(1,t_COL),cgetg(1,t_VECSMALL)) : mkvec2(mkcol(gen_2), mkvecsmall(1)); G = mkvec5(mkvec2(N,mkvec(gen_0)), G, F, v, cgetg(1,t_MAT)); } return gerepilecopy(av,G); } if (!F) F = Z_factor(N); P = gel(F,1); nbprimes = lg(P)-1; E = ZV_to_nv( gel(F,2) ); switch(mod8(N)) { case 0: P = shallowconcat(gen_2,P); E = vecsmall_prepend(E, E[1]); /* add a copy of p=2 row */ i = 2; /* 2 generators at 2 */ break; case 4: i = 1; /* 1 generator at 2 */ break; case 2: case 6: P = vecsplice(P,1); E = vecsplice(E,1); /* remove 2 */ i = 0; /* no generator at 2 */ break; default: i = 0; /* no generator at 2 */ break; } l = lg(P); cyc = cgetg(l,t_VEC); gen = cgetg(l,t_VEC); mod = cgetg(l,t_VEC); /* treat p=2 first */ if (i == 2) { long v2 = E[1]; GEN q = int2n(v2); gel(cyc,1) = gen_2; gel(gen,1) = subiu(q,1); /* -1 */ gel(mod,1) = q; gel(cyc,2) = int2n(v2-2); gel(gen,2) = utoipos(5); /* Conrey normalization */ gel(mod,2) = q; i0 = 3; } else if (i == 1) { gel(cyc,1) = gen_2; gel(gen,1) = utoipos(3); gel(mod,1) = utoipos(4); i0 = 2; } else i0 = 1; /* odd primes, fill remaining entries */ for (i = i0; i < l; i++) { long e = E[i]; GEN p = gel(P,i), q = powiu(p, e-1), Q = mulii(p, q); gel(cyc,i) = subii(Q, q); /* phi(p^e) */ gel(gen,i) = pgener_Zp(p);/* Conrey normalization, for e = 1 also */ gel(mod,i) = Q; } /* gen[i] has order cyc[i] and generates (Z/mod[i]Z)^* */ if (nbprimes > 1) /* lift generators to (Z/NZ)^*, = 1 mod N/mod[i] */ for (i=1; i 1 and remain so in the loop, gen[i] = 1 mod (N/mod[i]) */ if (!flag) { /* update generators in place; about twice faster */ G = gen; for (i=l-1; i>=2; i--) { GEN ci = gel(cyc,i), gi = gel(G,i); long j; 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 (absequalii(ci, d)) continue; /* ci | cj */ if (absequalii(cj, d)) { /* cj | ci */ swap(gel(G,j),gel(G,i)); gi = gel(G,i); swap(gel(cyc,j),gel(cyc,i)); ci = gel(cyc,i); continue; } 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 = gel(G,j); /* (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 */ gel(G,i) = gi = Fp_mul(gi, Fp_pow(gj, mulii(qj, v), N), N); gel(G,j) = gj; ci = d; if (absequaliu(ci, 2)) break; } } G = mkvec3(ZV_prod(cyc), cyc, FpV_to_mod(G,N)); } else { /* keep matrices between generators, return an 'init' structure */ GEN D, U, Ui, fao = cgetg(l, t_VEC), lo = cgetg(l, t_VEC); F = mkvec2(P, E); D = ZV_snf_group(cyc,&U,&Ui); for (i = 1; i < l; i++) { GEN t = gen_0, p = gel(P,i), p_1 = subiu(p,1); long e = E[i]; gel(fao,i) = get_arith_ZZM(p_1); if (e >= 2 && !absequaliu(p,2)) { GEN q = gel(mod,i), g = Fp_pow(gel(gen,i),p_1,q); if (e == 2) t = Fp_inv(diviiexact(subiu(g,1), p), p); else t = ginv(Qp_log(cvtop(g,p,e))); } gel(lo,i) = t; } G = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(G,i) = FpV_factorback(gen, gel(Ui,i), N); G = mkvec3(ZV_prod(D), D, G); G = mkvec5(mkvec2(N,mkvec(gen_0)), G, F, mkvecn(6,mod,fao,Ui,gen,cyc,lo), U); } return gerepilecopy(av, G); } GEN znstar(GEN N) { return znstar0(N, 0); } /* g has order 2^(e-2), g,h = 1 (mod 4); return x s.t. g^x = h (mod 2^e) */ static GEN Zideallog_2k(GEN h, GEN g, long e, GEN pe) { GEN a = Fp_log(h, g, int2n(e-2), pe); if (typ(a) != t_INT) return NULL; return a; } /* ord = get_arith_ZZM(p-1), simplified form of znlog_rec: g is known * to be a primitive root mod p^e; lo = 1/log_p(g^(p-1)) */ static GEN Zideallog_pk(GEN h, GEN g, GEN p, long e, GEN pe, GEN ord, GEN lo) { GEN gp = (e == 1)? g: modii(g, p); GEN hp = (e == 1)? h: modii(h, p); GEN a = Fp_log(hp, gp, ord, p); if (typ(a) != t_INT) return NULL; if (e > 1) { /* find a s.t. g^a = h (mod p^e), p odd prime, e > 0, (h,p) = 1 */ /* use p-adic log: O(log p + e) mul*/ GEN b, p_1 = gel(ord,1); h = Fp_mul(h, Fp_pow(g, negi(a), pe), pe); /* g,h = 1 mod p; compute b s.t. h = g^b */ if (e == 2) /* simpler */ b = Fp_mul(diviiexact(subiu(h,1), p), lo, p); else b = padic_to_Q(gmul(Qp_log(cvtop(h, p, e)), lo)); a = addii(a, mulii(p_1, b)); } return a; } int znconrey_check(GEN cyc, GEN chi) { return typ(chi) == t_COL && lg(chi) == lg(cyc) && RgV_is_ZV(chi); } int zncharcheck(GEN G, GEN chi) { switch(typ(chi)) { case t_INT: return 1; case t_COL: return znconrey_check(znstar_get_conreycyc(G), chi); case t_VEC: return char_check(znstar_get_cyc(G), chi); } return 0; } GEN znconreyfromchar_normalized(GEN bid, GEN chi) { GEN nchi, U = znstar_get_U(bid); long l = lg(chi); if (l == 1) retmkvec2(gen_1,cgetg(1,t_VEC)); if (!RgV_is_ZV(chi) || lgcols(U) != l) pari_err_TYPE("lfunchiZ", chi); nchi = char_normalize(chi, cyc_normalize(znstar_get_cyc(bid))); gel(nchi,2) = ZV_ZM_mul(gel(nchi,2),U); return nchi; } GEN znconreyfromchar(GEN bid, GEN chi) { GEN nchi = znconreyfromchar_normalized(bid, chi); GEN v = char_denormalize(znstar_get_conreycyc(bid), gel(nchi,1), gel(nchi,2)); settyp(v, t_COL); return v; } /* discrete log on canonical "primitive root" generators * Allow log(x) instead of x [usual discrete log on bid's generators] */ GEN znconreylog(GEN bid, GEN x) { pari_sp av = avma; GEN N, L, F, P,E, y, pe, fao, gen, lo, cycg; long i, l; if (!checkznstar_i(bid)) pari_err_TYPE("znconreylog", bid); N = znstar_get_N(bid); if (abscmpiu(N, 2) <= 0) { switch(typ(x)) { case t_INT: break; case t_INTMOD: if (!equalii(N, gel(x,1))) pari_err_TYPE("znconreylog", x); x = gel(x,2); break; case t_COL: case t_VEC: if (lg(x) != 1) pari_err_TYPE("znconreylog", x); break; default: pari_err_TYPE("znconreylog", x); } return cgetg(1, t_COL); } cycg = znstar_get_conreycyc(bid); switch(typ(x)) { GEN Ui; case t_INTMOD: if (!equalii(N, gel(x,1))) pari_err_TYPE("znconreylog", x); x = gel(x,2); /* fall through */ case t_INT: if (!signe(x)) pari_err_COPRIME("znconreylog", x, N); break; case t_COL: /* log_bid(x) */ Ui = znstar_get_Ui(bid); if (!RgV_is_ZV(x) || lg(x) != lg(Ui)) pari_err_TYPE("znconreylog", x); return gerepileupto(av, ZV_ZV_mod(ZM_ZC_mul(Ui,x), cycg)); case t_VEC: return gerepilecopy(av, znconreyfromchar(bid, x)); default: pari_err_TYPE("znconreylog", x); } F = znstar_get_faN(bid); /* factor(N) */ P = gel(F, 1); /* prime divisors of N */ E = gel(F, 2); /* exponents */ L = gel(bid,4); pe = znstar_get_pe(bid); fao = gel(L,2); gen = znstar_get_conreygen(bid); /* local generators of (Z/p^k)^* */ lo = gel(L,6); /* 1/log_p((g_i)^(p_i-1)) */ l = lg(gen); i = 1; y = cgetg(l, t_COL); if (!mod2(N) && !mod2(x)) pari_err_COPRIME("znconreylog", x, N); if (absequaliu(gel(P,1), 2) && E[1] >= 2) { if (E[1] == 2) gel(y,i++) = mod4(x) == 1? gen_0: gen_1; else { GEN a, x2, q2 = gel(pe,1); x2 = modii(x, q2); if (mod4(x) == 1) /* 1 or 5 mod 8*/ gel(y,i++) = gen_0; else /* 3 or 7 */ { gel(y,i++) = gen_1; x2 = subii(q2, x2); } /* x2 = 5^x mod q */ a = Zideallog_2k(x2, gel(gen,i), E[1], q2); if (!a) pari_err_COPRIME("znconreylog", x, N); gel(y, i++) = a; } } while (i < l) { GEN p = gel(P,i), q = gel(pe,i), xpe = modii(x, q); GEN a = Zideallog_pk(xpe, gel(gen,i), p, E[i], q, gel(fao,i), gel(lo,i)); if (!a) pari_err_COPRIME("znconreylog", x, N); gel(y, i++) = a; } return gerepilecopy(av, y); } GEN Zideallog(GEN bid, GEN x) { pari_sp av = avma; GEN y = znconreylog(bid, x), U = znstar_get_U(bid); return gerepileupto(av, ZM_ZC_mul(U, y)); } GEN znlog0(GEN h, GEN g, GEN o) { if (typ(g) == t_VEC) { GEN N; if (o) pari_err_TYPE("znlog [with znstar]", o); if (!checkznstar_i(g)) pari_err_TYPE("znlog", g); N = znstar_get_N(g); h = Rg_to_Fp(h,N); return Zideallog(g, h); } return znlog(h, g, o); } GEN znconreyexp(GEN bid, GEN x) { pari_sp av = avma; long i, l; GEN N, pe, gen, cycg, v, vmod; int e2; if (!checkznstar_i(bid)) pari_err_TYPE("znconreyexp", bid); cycg = znstar_get_conreycyc(bid); switch(typ(x)) { case t_VEC: x = znconreylog(bid, x); break; case t_COL: if (RgV_is_ZV(x) && lg(x) == lg(cycg)) break; default: pari_err_TYPE("znconreyexp",x); } pe = znstar_get_pe(bid); gen = znstar_get_conreygen(bid); /* local generators of (Z/p^k)^* */ cycg = znstar_get_conreycyc(bid); l = lg(x); v = cgetg(l, t_VEC); N = znstar_get_N(bid); e2 = !mod8(N); /* 2 generators at p = 2 */ for (i = 1; i < l; i++) { GEN q, g, m; if (i == 1 && e2) { gel(v,1) = NULL; continue; } q = gel(pe,i); g = gel(gen,i); m = modii(gel(x,i), gel(cycg,i)); m = Fp_pow(g, m, q); if (i == 2 && e2 && signe(gel(x,1))) m = Fp_neg(m, q); gel(v,i) = mkintmod(m, q); } if (e2) v = vecsplice(v, 1); v = chinese1_coprime_Z(v); vmod = gel(v,1); v = gel(v,2); if (mpodd(v) || mpodd(N)) return gerepilecopy(av, v); /* handle N = 2 mod 4 */ return gerepileuptoint(av, addii(v, vmod)); } /* Return Dirichlet character \chi_q(m,.), where bid = znstar(q); * m is either a t_INT, or a t_COL [Conrey logarithm] */ GEN znconreychar(GEN bid, GEN m) { pari_sp av = avma; GEN c, d, nchi; if (!checkznstar_i(bid)) pari_err_TYPE("znconreychar", bid); switch(typ(m)) { case t_INTMOD: if (!equalii(gel(m,1), znstar_get_N(bid))) pari_err_TYPE("znconreychar",m); m = gel(m,2); /* fall through */ case t_INT: case t_COL: nchi = znconrey_normalized(bid,m); /* images of primroot gens */ break; default: pari_err_TYPE("znconreychar",m); return NULL;/*LCOV_EXCL_LINE*/ } d = gel(nchi,1); c = ZV_ZM_mul(gel(nchi,2), znstar_get_Ui(bid)); /* images of bid gens */ return gerepilecopy(av, char_denormalize(znstar_get_cyc(bid),d,c)); } /* chi a t_INT or Conrey log describing a character. Return conductor, as an * integer if primitive; as a t_VEC [N,factor(N)] if not. Set *pm=m to the * attached primitive character: chi(g_i) = m[i]/ord(g_i) * Caller should use znconreylog_normalize(BID, m), once BID(conductor) is * computed (wasteful to do it here since BID is shared by many characters) */ GEN znconreyconductor(GEN bid, GEN chi, GEN *pm) { pari_sp av = avma; GEN q, m, F, P, E; long i, j, l; int e2, primitive = 1; if (!checkznstar_i(bid)) pari_err_TYPE("znconreyconductor", bid); if (typ(chi) == t_COL) { if (!znconrey_check(znstar_get_conreycyc(bid), chi)) pari_err_TYPE("znconreyconductor",chi); } else chi = znconreylog(bid, chi); l = lg(chi); F = znstar_get_faN(bid); P = gel(F,1); E = gel(F,2); if (l == 1) { set_avma(av); if (pm) *pm = cgetg(1,t_COL); if (lg(P) == 1) return gen_1; retmkvec2(gen_1, trivial_fact()); } P = leafcopy(P); E = leafcopy(E); m = cgetg(l, t_COL); e2 = (E[1] >= 3 && absequaliu(gel(P,1),2)); i = j = 1; if (e2) { /* two generators at p=2 */ GEN a1 = gel(chi,1), a = gel(chi,2); i = 3; if (!signe(a)) { e2 = primitive = 0; if (signe(a1)) { /* lose one generator */ E[1] = 2; gel(m,1) = a1; j = 2; } /* else lose both */ } else { long v = Z_pvalrem(a, gen_2, &a); if (v) { E[1] -= v; E[2] = E[1]; primitive = 0; } gel(m,1) = a1; gel(m,2) = a; j = 3; } } l = lg(P); for (; i < l; i++) { GEN p = gel(P,i), a = gel(chi,i); /* image of g_i in Q/Z is a/cycg[i], cycg[i] = order(g_i) */ if (!signe(a)) primitive = 0; else { long v = Z_pvalrem(a, p, &a); E[j] = E[i]; if (v) { E[j] -= v; primitive = 0; } gel(P,j) = gel(P,i); gel(m,j) = a; j++; } } setlg(m,j); setlg(P,j); setlg(E,j); if (pm) *pm = m; /* attached primitive character */ if (primitive) { q = znstar_get_N(bid); if (mod4(q) == 2) primitive = 0; } if (!primitive) { if (e2) { /* remove duplicate p=2 row from factorization */ P = vecsplice(P,1); E = vecsplice(E,1); } E = zc_to_ZC(E); q = mkvec2(factorback2(P,E), mkmat2(P,E)); } return gc_all(av, pm? 2: 1, &q, pm); } GEN zncharinduce(GEN G, GEN chi, GEN N) { pari_sp av = avma; GEN q, faq, P, E, Pq, Eq, CHI; long i, j, l; int e2; if (!checkznstar_i(G)) pari_err_TYPE("zncharinduce", G); if (!zncharcheck(G, chi)) pari_err_TYPE("zncharinduce", chi); q = znstar_get_N(G); if (typ(chi) != t_COL) chi = znconreylog(G, chi); if (checkznstar_i(N)) { GEN faN = znstar_get_faN(N); P = gel(faN,1); l = lg(P); E = gel(faN,2); N = znstar_get_N(N); if (l > 2 && equalii(gel(P,1),gel(P,2))) { /* remove duplicate 2 */ l--; P = vecsplice(P,1); E = vecsplice(E,1); } } else { GEN faN = check_arith_pos(N, "zncharinduce"); if (!faN) faN = Z_factor(N); else N = (typ(N) == t_VEC)? gel(N,1): factorback(faN); P = gel(faN,1); E = gel(faN,2); } if (!dvdii(N,q)) pari_err_DOMAIN("zncharinduce", "N % q", "!=", gen_0, N); if (mod4(N) == 2) { /* remove 2 */ if (lg(P) > 1 && absequaliu(gel(P,1), 2)) { P = vecsplice(P,1); E = vecsplice(E,1); } N = shifti(N,-1); } l = lg(P); /* q = N or q = 2N, N odd */ if (cmpii(N,q) <= 0) return gerepilecopy(av, chi); /* N > 1 => l > 1*/ if (typ(E) != t_VECSMALL) E = ZV_to_zv(E); e2 = (E[1] >= 3 && absequaliu(gel(P,1),2)); /* 2 generators at 2 mod N */ if (ZV_equal0(chi)) { set_avma(av); return equali1(N)? cgetg(1, t_COL): zerocol(l+e2 - 1); } faq = znstar_get_faN(G); Pq = gel(faq,1); Eq = gel(faq,2); CHI = cgetg(l+e2, t_COL); i = j = 1; if (e2) { i = 2; j = 3; if (absequaliu(gel(Pq,1), 2)) { if (Eq[1] >= 3) { /* 2 generators at 2 mod q */ gel(CHI,1) = gel(chi,1); gel(CHI,2) = shifti(gel(chi,2), E[1]-Eq[1]); } else if (Eq[1] == 2) { /* 1 generator at 2 mod q */ gel(CHI,1) = gel(chi,1); gel(CHI,2) = gen_0; } else gel(CHI,1) = gel(CHI,2) = gen_0; } else gel(CHI,1) = gel(CHI,2) = gen_0; } for (; i < l; i++,j++) { GEN p = gel(P,i); long k = ZV_search(Pq, p); gel(CHI,j) = k? mulii(gel(chi,k), powiu(p, E[i]-Eq[k])): gen_0; } return gerepilecopy(av, CHI); } /* m a Conrey log [on the canonical primitive roots], cycg the primitive * roots orders */ GEN znconreylog_normalize(GEN G, GEN m) { GEN cycg = znstar_get_conreycyc(G); long i, l; GEN d, M = cgetg_copy(m, &l); if (typ(cycg) != t_VEC || lg(cycg) != l) pari_err_TYPE("znconreylog_normalize",mkvec2(m,cycg)); for (i = 1; i < l; i++) gel(M,i) = gdiv(gel(m,i), gel(cycg,i)); /* m[i]: image of primroot generators g_i in Q/Z */ M = Q_remove_denom(M, &d); return mkvec2(d? d: gen_1, M); } /* return normalized character on Conrey generators attached to chi: Conrey * label (t_INT), char on (SNF) G.gen* (t_VEC), or Conrey log (t_COL) */ GEN znconrey_normalized(GEN G, GEN chi) { switch(typ(chi)) { case t_INT: /* Conrey label */ return znconreylog_normalize(G, znconreylog(G, chi)); case t_COL: /* Conrey log */ if (!RgV_is_ZV(chi)) break; return znconreylog_normalize(G, chi); case t_VEC: /* char on G.gen */ if (!RgV_is_ZV(chi)) break; return znconreyfromchar_normalized(G, chi); } pari_err_TYPE("znchareval",chi); return NULL;/* LCOV_EXCL_LINE */ } /* return 1 iff chi(-1) = -1, and 0 otherwise */ long zncharisodd(GEN G, GEN chi) { long i, l, s; GEN N; if (!checkznstar_i(G)) pari_err_TYPE("zncharisodd", G); if (!zncharcheck(G, chi)) pari_err_TYPE("zncharisodd", chi); if (typ(chi) != t_COL) chi = znconreylog(G, chi); N = znstar_get_N(G); l = lg(chi); s = 0; if (!mod8(N)) { s = mpodd(gel(chi,1)); i = 3; } else i = 1; for (; i < l; i++) s += mpodd(gel(chi,i)); return odd(s); } GEN znchartokronecker(GEN G, GEN chi, long flag) { pari_sp av = avma; long s; GEN F, o; if (flag && flag != 1) pari_err_FLAG("znchartokronecker"); s = zncharisodd(G, chi)? -1: 1; if (typ(chi) != t_COL) chi = znconreylog(G, chi); o = zncharorder(G, chi); if (abscmpiu(o,2) > 0) { set_avma(av); return gen_0; } F = znconreyconductor(G, chi, NULL); if (typ(F) == t_INT) { if (s < 0) F = negi(F); return gerepileuptoint(av, F); } F = gel(F,1); F = (s < 0)? negi(F): icopy(F); if (!flag) { GEN MF = znstar_get_faN(G), P = gel(MF,1); long i, l = lg(P); for (i = 1; i < l; i++) { GEN p = gel(P,i); if (!dvdii(F,p)) F = mulii(F,sqri(p)); } } return gerepileuptoint(av, F); } /* (D/.) as a character mod N; assume |D| divides N and D = 0,1 mod 4*/ GEN znchar_quad(GEN G, GEN D) { GEN cyc = znstar_get_conreycyc(G); GEN gen = znstar_get_conreygen(G); long i, l = lg(cyc); GEN chi = cgetg(l, t_COL); for (i = 1; i < l; i++) { long k = kronecker(D, gel(gen,i)); gel(chi,i) = (k==1)? gen_0: shifti(gel(cyc,i), -1); } return chi; } GEN znchar(GEN D) { pari_sp av = avma; GEN G, chi; switch(typ(D)) { case t_INT: if (!signe(D) || Mod4(D) > 1) pari_err_TYPE("znchar", D); G = znstar0(D,1); chi = mkvec2(G, znchar_quad(G,D)); break; case t_INTMOD: G = znstar0(gel(D,1), 1); chi = mkvec2(G, znconreylog(G, gel(D,2))); break; case t_VEC: if (checkMF_i(D)) { chi = vecslice(MF_get_CHI(D),1,2); break; } else if (checkmf_i(D)) { chi = vecslice(mf_get_CHI(D),1,2); break; } if (lg(D) != 3) pari_err_TYPE("znchar", D); G = gel(D,1); if (!checkznstar_i(G)) pari_err_TYPE("znchar", D); chi = gel(D,2); if (typ(chi) == t_VEC && lg(chi) == 3 && is_vec_t(typ(gel(chi,2)))) { /* normalized character */ GEN n = gel(chi,1), chic = gel(chi,2); GEN cyc = typ(chic)==t_VEC? znstar_get_cyc(G): znstar_get_conreycyc(G); if (!char_check(cyc, chic)) pari_err_TYPE("znchar",D); chi = char_denormalize(cyc, n, chic); } if (!zncharcheck(G, chi)) pari_err_TYPE("znchar", D); chi = mkvec2(G,chi); break; default: pari_err_TYPE("znchar", D); return NULL; /*LCOV_EXCL_LINE*/ } return gerepilecopy(av, chi); } /* G a znstar, not stack clean */ GEN znchareval(GEN G, GEN chi, GEN n, GEN z) { GEN nchi, N = znstar_get_N(G); /* avoid division by 0 */ if (typ(n) == t_FRAC && !equali1(gcdii(gel(n,2), N))) return not_coprime(z); n = Rg_to_Fp(n, N); if (!equali1(gcdii(n, N))) return not_coprime(z); /* nchi: normalized character on Conrey generators */ nchi = znconrey_normalized(G, chi); return chareval_i(nchi, znconreylog(G,n), z); } /* G is a znstar, chi a Dirichlet character */ GEN zncharconj(GEN G, GEN chi) { switch(typ(chi)) { case t_INT: chi = znconreylog(G, chi); /* fall through */ case t_COL: return charconj(znstar_get_conreycyc(G), chi); case t_VEC: return charconj(znstar_get_cyc(G), chi); } pari_err_TYPE("zncharconj",chi); return NULL; /*LCOV_EXCL_LINE*/ } /* G is a znstar, chi a Dirichlet character */ GEN zncharorder(GEN G, GEN chi) { switch(typ(chi)) { case t_INT: chi = znconreylog(G, chi); /*fall through*/ case t_COL: return charorder(znstar_get_conreycyc(G), chi); case t_VEC: return charorder(znstar_get_cyc(G), chi); default: pari_err_TYPE("zncharorder",chi); return NULL; /* LCOV_EXCL_LINE */ } } /* G is a znstar, chi a Dirichlet character */ GEN zncharker(GEN G, GEN chi) { if (typ(chi) != t_VEC) chi = znconreychar(G, chi); return charker(znstar_get_cyc(G), chi); } /* G is a znstar, 'a' is a Dirichlet character */ GEN zncharpow(GEN G, GEN a, GEN n) { switch(typ(a)) { case t_INT: return Fp_pow(a, n, znstar_get_N(G)); case t_VEC: return charpow(znstar_get_cyc(G), a, n); case t_COL: return charpow(znstar_get_conreycyc(G), a, n); default: pari_err_TYPE("znchapow",a); return NULL; /* LCOV_EXCL_LINE */ } } /* G is a znstar, 'a' and 'b' are Dirichlet character */ GEN zncharmul(GEN G, GEN a, GEN b) { long ta = typ(a), tb = typ(b); if (ta == tb) switch(ta) { case t_INT: return Fp_mul(a, b, znstar_get_N(G)); case t_VEC: return charmul(znstar_get_cyc(G), a, b); case t_COL: return charmul(znstar_get_conreycyc(G), a, b); default: pari_err_TYPE("zncharmul",a); return NULL; /* LCOV_EXCL_LINE */ } if (ta != t_COL) a = znconreylog(G, a); if (tb != t_COL) b = znconreylog(G, b); return charmul(znstar_get_conreycyc(G), a, b); } /* G is a znstar, 'a' and 'b' are Dirichlet character */ GEN znchardiv(GEN G, GEN a, GEN b) { long ta = typ(a), tb = typ(b); if (ta == tb) switch(ta) { case t_INT: return Fp_div(a, b, znstar_get_N(G)); case t_VEC: return chardiv(znstar_get_cyc(G), a, b); case t_COL: return chardiv(znstar_get_conreycyc(G), a, b); default: pari_err_TYPE("znchardiv",a); return NULL; /* LCOV_EXCL_LINE */ } if (ta != t_COL) a = znconreylog(G, a); if (tb != t_COL) b = znconreylog(G, b); return chardiv(znstar_get_conreycyc(G), a, b); } /* CHI mod N = \prod_p p^e; let CHI = \prod CHI_p, CHI_p mod p^e * return \prod_{p | (Q,N)} CHI_p. E.g if Q = p, return chi_p */ GEN znchardecompose(GEN G, GEN chi, GEN Q) { GEN c, P, E, F; long l, lP, i; if (!checkznstar_i(G)) pari_err_TYPE("znchardecompose", G); if (typ(Q) != t_INT) pari_err_TYPE("znchardecompose", Q); if (typ(chi) == t_COL) { if (!zncharcheck(G, chi)) pari_err_TYPE("znchardecompose", chi); } else chi = znconreylog(G, chi); l = lg(chi); if (l == 1) return cgetg(1, t_VEC); F = znstar_get_faN(G); c = zerocol(l-1); P = gel(F,1); /* prime divisors of N */ lP = lg(P); E = gel(F,2); /* exponents */ for (i = 1; i < lP; i++) { GEN p = gel(P,i); if (i == 1 && equaliu(p,2) && E[1] >= 3) { if (!mpodd(Q)) { gel(c,1) = icopy(gel(chi,1)); gel(c,2) = icopy(gel(chi,2)); } i = 2; /* skip P[2] = P[1] = 2 */ } else if (dvdii(Q, p)) gel(c,i) = icopy(gel(chi,i)); } return c; } GEN zncharconductor(GEN G, GEN chi) { pari_sp av = avma; GEN F = znconreyconductor(G, chi, NULL); if (typ(F) == t_INT) return F; return gerepilecopy(av, gel(F,1)); } GEN znchartoprimitive(GEN G, GEN chi) { pari_sp av = avma; GEN chi0, F = znconreyconductor(G, chi, &chi0); if (typ(F) == t_INT) chi = mkvec2(G,chi); else chi = mkvec2(znstar0(F,1), chi0); return gerepilecopy(av, chi); } pari-2.17.2/src/basemath/FpX_factor.c0000644000175000017500000017520514676526175015773 0ustar billbill/* Copyright (C) 2012 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_factormod /***********************************************************************/ /** **/ /** Factorisation over finite field **/ /** **/ /***********************************************************************/ /*******************************************************************/ /* */ /* ROOTS MODULO a prime p (no multiplicities) */ /* */ /*******************************************************************/ /* Replace F by a monic normalized FpX having the same factors; * assume p prime and *F a ZX */ static int ZX_factmod_init(GEN *F, GEN p) { if (lgefint(p) == 3) { ulong pp = p[2]; if (pp == 2) { *F = ZX_to_F2x(*F); return 0; } *F = ZX_to_Flx(*F, pp); if (lg(*F) > 3) *F = Flx_normalize(*F, pp); return 1; } *F = FpX_red(*F, p); if (lg(*F) > 3) *F = FpX_normalize(*F, p); return 2; } static GEN ZX_rootmod_init(GEN F, GEN p) { return lgefint(p) == 3? ZX_to_Flx(F, p[2]): FpX_red(F, p); } /* return 1,...,p-1 [not_0 = 1] or 0,...,p [not_0 = 0] */ static GEN all_roots_mod_p(ulong p, int not_0) { GEN r; ulong i; if (not_0) { r = cgetg(p, t_VECSMALL); for (i = 1; i < p; i++) r[i] = i; } else { r = cgetg(p+1, t_VECSMALL); for (i = 0; i < p; i++) r[i+1] = i; } return r; } /* X^n - 1 */ static GEN Flx_Xnm1(long sv, long n, ulong p) { GEN t = cgetg(n+3, t_VECSMALL); long i; t[1] = sv; t[2] = p - 1; for (i = 3; i <= n+1; i++) t[i] = 0; t[i] = 1; return t; } /* X^n + 1 */ static GEN Flx_Xn1(long sv, long n, ulong p) { GEN t = cgetg(n+3, t_VECSMALL); long i; (void) p; t[1] = sv; t[2] = 1; for (i = 3; i <= n+1; i++) t[i] = 0; t[i] = 1; return t; } /* assume lg(f) > 3 */ static GEN Flx_root_mod_2(GEN f) { long i, n = lg(f)-1, c = f[2]; int z0 = !c; c ^= 1; /* c = f[2] + f[n] mod 2, we know f[n] is odd */ for (i=3; i < n; i++) c ^= f[i]; /* c = 0 iff f(1) = 0 (mod 2) */ if (z0) return c? mkvecsmall(0): mkvecsmall2(0, 1); return c? cgetg(1, t_VECSMALL): mkvecsmall(1); } /* assume lg(f) > 3 */ static ulong Flx_oneroot_mod_2(GEN f) { long i, n, c = f[2]; if (!c) return 0; n = lg(f)-1; c = 0; /* = f[2] + f[n] (mod 2); both are odd */ for (i=3; i < n; i++) c ^= f[i]; return c? 2: 1; } static GEN FpX_roots_i(GEN f, GEN p); static int cmpGuGu(GEN a, GEN b) { return (ulong)a < (ulong)b? -1: (a == b? 0: 1); } /* assume that f is a ZX and p a prime */ GEN FpX_roots(GEN f, GEN p) { pari_sp av = avma; GEN y; f = ZX_rootmod_init(f, p); switch(lg(f)) { case 2: pari_err_ROOTS0("FpX_roots"); case 3: return cgetg(1,t_COL); } if (typ(f) == t_VECSMALL) { ulong pp = p[2]; if (pp == 2) y = Flx_root_mod_2(f); else { if (!odd(pp)) pari_err_PRIME("FpX_roots", p); y = Flx_roots_pre(f, pp, SMALL_ULONG(pp)? 0: get_Fl_red(pp)); } y = Flc_to_ZC(y); } else y = FpX_roots_i(f, p); return gerepileupto(av, y); } /* assume x reduced mod p > 2, monic. */ static int FpX_quad_factortype(GEN x, GEN p) { GEN b = gel(x,3), c = gel(x,2); GEN D = subii(sqri(b), shifti(c,2)); return kronecker(D,p); } /* assume x reduced mod p, monic. Return one root, or NULL if irreducible */ static GEN FpX_quad_root(GEN x, GEN p, int unknown) { GEN s, D, b = gel(x,3), c = gel(x,2); if (absequaliu(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; return Fp_halve(Fp_sub(s,b, p), p); } static GEN FpX_otherroot(GEN x, GEN r, GEN p) { return Fp_neg(Fp_add(gel(x,3), r, p), p); } /* disc(x^2+bx+c) = b^2 - 4c */ static ulong Fl_disc_bc(ulong b, ulong c, ulong p) { return Fl_sub(Fl_sqr(b,p), Fl_double(Fl_double(c,p),p), p); } /* p > 2; allow pi = 0 */ static ulong Flx_quad_root(GEN x, ulong p, ulong pi, int unknown) { ulong s, b = x[3], c = x[2]; ulong D = Fl_disc_bc(b, c, p); if (unknown && krouu(D,p) == -1) return p; s = Fl_sqrt_pre(D, p, pi); if (s==~0UL) return p; return Fl_halve(Fl_sub(s,b, p), p); } static ulong Flx_otherroot(GEN x, ulong r, ulong p) { return Fl_neg(Fl_add(x[3], r, p), p); } /* 'todo' contains the list of factors to be split. * 'done' the list of finished factors, no longer touched */ struct split_t { GEN todo, done; }; static void split_init(struct split_t *S, long max) { S->todo = vectrunc_init(max); S->done = vectrunc_init(max); } #if 0 /* move todo[i] to done */ static void split_convert(struct split_t *S, long i) { long n = lg(S->todo)-1; vectrunc_append(S->done, gel(S->todo,i)); if (n) gel(S->todo,i) = gel(S->todo, n); setlg(S->todo, n); } #endif /* append t to todo */ static void split_add(struct split_t *S, GEN t) { vectrunc_append(S->todo, t); } /* delete todo[i], add t to done */ static void split_moveto_done(struct split_t *S, long i, GEN t) { long n = lg(S->todo)-1; vectrunc_append(S->done, t); if (n) gel(S->todo,i) = gel(S->todo, n); setlg(S->todo, n); } /* append t to done */ static void split_add_done(struct split_t *S, GEN t) { vectrunc_append(S->done, t); } /* split todo[i] into a and b */ static void split_todo(struct split_t *S, long i, GEN a, GEN b) { gel(S->todo, i) = a; split_add(S, b); } /* split todo[i] into a and b, moved to done */ static void split_done(struct split_t *S, long i, GEN a, GEN b) { split_moveto_done(S, i, a); split_add_done(S, b); } /* by splitting, assume p > 2 prime, deg(f) > 0 */ static GEN FpX_roots_i(GEN f, GEN p) { GEN pol, pol0, a, q; struct split_t S; f = FpX_normalize(f, p); split_init(&S, lg(f)-1); settyp(S.done, t_COL); if (ZX_valrem(f, &f)) split_add_done(&S, gen_0); switch(degpol(f)) { case 0: return ZC_copy(S.done); case 1: split_add_done(&S, subii(p, gel(f,2))); return ZC_copy(S.done); case 2: { GEN s, r = FpX_quad_root(f, p, 1); if (r) { split_add_done(&S, r); s = FpX_otherroot(f,r, p); /* f not known to be square free yet */ if (!equalii(r, s)) split_add_done(&S, s); } return sort(S.done); } } a = FpXQ_pow(pol_x(varn(f)), subiu(p,1), f,p); if (lg(a) < 3) pari_err_PRIME("rootmod",p); a = FpX_Fp_sub_shallow(a, gen_1, p); /* a = x^(p-1) - 1 mod f */ a = FpX_gcd(f,a, p); if (!degpol(a)) return ZC_copy(S.done); split_add(&S, FpX_normalize(a,p)); q = shifti(p,-1); pol0 = icopy(gen_1); /* constant term, will vary in place */ pol = deg1pol_shallow(gen_1, pol0, varn(f)); for (pol0[2] = 1;; pol0[2]++) { long j, l = lg(S.todo); if (l == 1) return sort(S.done); if (pol0[2] == 100 && !BPSW_psp(p)) pari_err_PRIME("polrootsmod",p); for (j = 1; j < l; j++) { GEN b, r, s, c = gel(S.todo,j); switch(degpol(c)) { /* convert linear and quadratics to roots, try to split the rest */ case 1: split_moveto_done(&S, j, subii(p, gel(c,2))); j--; l--; break; case 2: r = FpX_quad_root(c, p, 0); if (!r) pari_err_PRIME("polrootsmod",p); s = FpX_otherroot(c,r, p); split_done(&S, j, r, s); j--; l--; break; default: b = FpXQ_pow(pol,q, c,p); if (degpol(b) <= 0) continue; b = FpX_gcd(c,FpX_Fp_sub_shallow(b,gen_1,p), p); if (!degpol(b)) continue; b = FpX_normalize(b, p); c = FpX_div(c,b, p); split_todo(&S, j, b, c); } } } } /* Assume f is normalized; allow pi = 0 */ static ulong Flx_cubic_root(GEN ff, ulong p, ulong pi) { GEN f = Flx_normalize(ff,p); ulong a = f[4], b=f[3], c=f[2], p3 = p%3==1 ? (2*p+1)/3 :(p+1)/3; ulong t, t2, A, B2, B, A3, A33, S, P, D; if (pi) { t = Fl_mul_pre(a, p3, p, pi); t2 = Fl_sqr_pre(t, p, pi); A = Fl_sub(b, Fl_triple(t2, p), p); B = Fl_sub(c, Fl_mul_pre(t, Fl_add(A, t2, p), p, pi), p); A3 = Fl_mul_pre(A, p3, p, pi); B2 = Fl_sqr_pre(B, p, pi); } else { t = Fl_mul(a, p3, p); t2 = Fl_sqr(t, p); A = Fl_sub(b, Fl_triple(t2, p), p); B = Fl_sub(c, Fl_mul(t, Fl_add(A, t2, p), p), p); A3 = Fl_mul(A, p3, p); B2 = Fl_sqr(B, p); } A33 = Fl_powu_pre(A3, 3, p, pi); D = Fl_add(B2, Fl_double(Fl_double(A33, p), p), p); S = Fl_neg(B,p); P = Fl_neg(A3,p); if (krouu(D,p) >= 0) { ulong s = Fl_sqrt_pre(D, p, pi), vS1, vS2; ulong S1 = S==s ? S: Fl_halve(Fl_sub(S, s, p), p); if (p%3==2) /* 1 solutions */ vS1 = Fl_powu_pre(S1, p - p3, p, pi); else { vS1 = Fl_sqrtl_pre(S1, 3, p, pi); if (vS1==~0UL) return p; /*0 solutions*/ /*3 solutions*/ } if (!P) return Fl_sub(vS1, t, p); vS2 = pi? Fl_mul_pre(P, Fl_inv(vS1, p), p, pi): Fl_div(P, vS1, p); return Fl_sub(Fl_add(vS1,vS2, p), t, p); } else { pari_sp av = avma; GEN S1 = mkvecsmall2(Fl_halve(S, p), (p + 1UL) >> 1); GEN vS1 = Fl2_sqrtn_pre(S1, utoi(3), D, p, pi, NULL); ulong Sa; if (!vS1) return p; /*0 solutions, p%3==2*/ Sa = vS1[1]; if (p%3==1) /*1 solutions*/ { ulong Fa = Fl2_norm_pre(vS1, D, p, pi); if (Fa!=P) Sa = Fl_mul(Sa, Fl_div(Fa, P, p),p); } set_avma(av); return Fl_sub(Fl_double(Sa,p),t,p); } } /* Assume f is normalized */ static GEN FpX_cubic_root(GEN ff, GEN p) { GEN f = FpX_normalize(ff,p); GEN a = gel(f,4), b = gel(f,3), c = gel(f,2); ulong pm3 = umodiu(p,3); GEN p3 = pm3==1 ? diviuexact(addiu(shifti(p,1),1),3) : diviuexact(addiu(p,1),3); GEN t = Fp_mul(a, p3, p), t2 = Fp_sqr(t, p); GEN A = Fp_sub(b, Fp_mulu(t2, 3, p), p); GEN B = Fp_addmul(c, t, Fp_sub(shifti(t2, 1), b, p), p); GEN A3 = Fp_mul(A, p3, p), A33 = Fp_powu(A3, 3, p); GEN S = Fp_neg(B,p), P = Fp_neg(A3,p); GEN D = Fp_add(Fp_sqr(S, p), shifti(A33, 2), p); if (kronecker(D,p) >= 0) { GEN s = Fp_sqrt(D, p), vS1, vS2; GEN S1 = S==s ? S: Fp_halve(Fp_sub(S, s, p), p); if (pm3 == 2) /* 1 solutions */ vS1 = Fp_pow(S1, diviuexact(addiu(shifti(p, 1), 1), 3), p); else { vS1 = Fp_sqrtn(S1, utoi(3), p, NULL); if (!vS1) return p; /*0 solutions*/ /*3 solutions*/ } vS2 = P? Fp_mul(P, Fp_inv(vS1, p), p): 0; return Fp_sub(Fp_add(vS1,vS2, p), t, p); } else { pari_sp av = avma; GEN T = deg2pol_shallow(gen_1, gen_0, negi(D), 0); GEN S1 = deg1pol_shallow(Fp_halve(gen_1, p), Fp_halve(S, p), 0); GEN vS1 = FpXQ_sqrtn(S1, utoi(3), T, p, NULL); GEN Sa; if (!vS1) return p; /*0 solutions, p%3==2*/ Sa = gel(vS1,2); if (pm3 == 1) /*1 solutions*/ { GEN Fa = FpXQ_norm(vS1, T, p); if (!equalii(Fa,P)) Sa = Fp_mul(Sa, Fp_div(Fa, P, p),p); } set_avma(av); return Fp_sub(shifti(Sa,1),t,p); } } /* assume p > 2 prime; if fl is set, assume that f splits mod p */ static ulong Flx_oneroot_pre_i(GEN f, ulong p, ulong pi, long fl) { GEN pol, a; ulong q, PI; long da; if (Flx_val(f)) return 0; da = degpol(f); f = Flx_normalize(f, p); if (da == 1) return Fl_neg(f[2], p); PI = pi? pi: get_Fl_red(p); /* PI for Fp, pi for Fp[x] */ switch(da) { case 2: return Flx_quad_root(f, p, PI, 1); case 3: if (p>3) return Flx_cubic_root(f, p, PI); /*FALL THROUGH*/ } if (SMALL_ULONG(p)) pi = 0; /* bilinear ops faster without Fl_*_pre */ if (!fl) { a = Flxq_powu_pre(polx_Flx(f[1]), p - 1, f,p,pi); if (lg(a) < 3) pari_err_PRIME("rootmod",utoipos(p)); a = Flx_Fl_add(a, p-1, p); /* a = x^(p-1) - 1 mod f */ a = Flx_gcd_pre(f,a, p, pi); } else a = f; da = degpol(a); if (!da) return p; a = Flx_normalize(a,p); q = p >> 1; pol = polx_Flx(f[1]); for(pol[2] = 1;; pol[2]++) { if (pol[2] == 1000 && !uisprime(p)) pari_err_PRIME("Flx_oneroot",utoipos(p)); switch(da) { case 1: return Fl_neg(a[2], p); case 2: return Flx_quad_root(a, p, PI, 0); case 3: if (p>3) return Flx_cubic_root(a, p, PI); /*FALL THROUGH*/ default: { GEN b = Flxq_powu_pre(pol,q, a,p,pi); long db; if (degpol(b) <= 0) continue; b = Flx_gcd_pre(a,Flx_Fl_add(b,p-1,p), p, pi); db = degpol(b); if (!db) continue; b = Flx_normalize(b, p); if (db <= (da >> 1)) { a = b; da = db; } else { a = Flx_div_pre(a,b, p, pi); da -= db; } } } } } ulong Flx_oneroot_pre(GEN f, ulong p, ulong pi) { return Flx_oneroot_pre_i(f, p, pi, 0); } ulong Flx_oneroot_split_pre(GEN f, ulong p, ulong pi) { return Flx_oneroot_pre_i(f, p, pi, 1); } /* assume p > 3 prime */ static GEN FpX_oneroot_i(GEN f, GEN p) { GEN pol, pol0, a, q; long da; if (ZX_val(f)) return gen_0; f = FpX_normalize(f, p); switch(degpol(f)) { case 1: return subii(p, gel(f,2)); case 2: return FpX_quad_root(f, p, 1); case 3: return FpX_cubic_root(f, p); } a = FpXQ_pow(pol_x(varn(f)), subiu(p,1), f,p); if (lg(a) < 3) pari_err_PRIME("rootmod",p); a = FpX_Fp_sub_shallow(a, gen_1, p); /* a = x^(p-1) - 1 mod f */ a = FpX_gcd(f,a, p); da = degpol(a); if (!da) return NULL; a = FpX_normalize(a,p); q = shifti(p,-1); pol0 = icopy(gen_1); /* constant term, will vary in place */ pol = deg1pol_shallow(gen_1, pol0, varn(f)); for (pol0[2]=1; ; pol0[2]++) { if (pol0[2] == 1000 && !BPSW_psp(p)) pari_err_PRIME("FpX_oneroot",p); switch(da) { case 1: return subii(p, gel(a,2)); case 2: return FpX_quad_root(a, p, 0); default: { GEN b = FpXQ_pow(pol,q, a,p); long db; if (degpol(b) <= 0) continue; b = FpX_gcd(a,FpX_Fp_sub_shallow(b,gen_1,p), p); db = degpol(b); if (!db) continue; b = FpX_normalize(b, p); if (db <= (da >> 1)) { a = b; da = db; } else { a = FpX_div(a,b, p); da -= db; } } } } } ulong Flx_oneroot(GEN f, ulong p) { pari_sp av = avma; switch(lg(f)) { case 2: return 0; case 3: return p; } if (p == 2) return Flx_oneroot_mod_2(f); return gc_ulong(av, Flx_oneroot_pre(f, p, SMALL_ULONG(p)? 0: get_Fl_red(p))); } ulong Flx_oneroot_split(GEN f, ulong p) { pari_sp av = avma; switch(lg(f)) { case 2: return 0; case 3: return p; } if (p == 2) return Flx_oneroot_mod_2(f); return gc_ulong(av, Flx_oneroot_split_pre(f, p, 0)); } /* assume that p is prime */ GEN FpX_oneroot(GEN f, GEN p) { pari_sp av = avma; f = ZX_rootmod_init(f, p); switch(lg(f)) { case 2: set_avma(av); return gen_0; case 3: return gc_NULL(av); } if (typ(f) == t_VECSMALL) { ulong r, pp = p[2]; if (pp == 2) r = Flx_oneroot_mod_2(f); else r = Flx_oneroot_pre(f, pp, SMALL_ULONG(pp)? 0: get_Fl_red(pp)); set_avma(av); return (r == pp)? NULL: utoi(r); } f = FpX_oneroot_i(f, p); if (!f) return gc_NULL(av); return gerepileuptoint(av, f); } /* returns a root of unity in F_p that is suitable for finding a factor */ /* of degree deg_factor of a polynomial of degree deg; the order is */ /* returned in n */ /* A good choice seems to be n close to deg/deg_factor; we choose n */ /* twice as big and decrement until it divides p-1. */ static GEN good_root_of_unity(GEN p, long deg, long deg_factor, long *pt_n) { pari_sp ltop = avma; GEN pm, factn, power, base, zeta; long n; pm = subis (p, 1ul); for (n = deg / 2 / deg_factor + 1; !dvdiu (pm, n); n--); factn = Z_factor(stoi(n)); power = diviuexact (pm, n); base = gen_1; do { base = addis (base, 1l); zeta = Fp_pow (base, power, p); } while (!equaliu (Fp_order (zeta, factn, p), n)); *pt_n = n; return gerepileuptoint (ltop, zeta); } GEN FpX_oneroot_split(GEN fact, GEN p) { pari_sp av = avma; long n, deg_f, i, dmin; GEN prim, expo, minfactor, xplusa, zeta, xpow; fact = FpX_normalize(fact, p); deg_f = degpol(fact); if (deg_f <= 3) return FpX_oneroot(fact, p); minfactor = fact; /* factor of minimal degree found so far */ dmin = degpol(minfactor); xplusa = pol_x(varn(fact)); while (dmin > 3) { /* split minfactor by computing its gcd with (X+a)^exp-zeta, where */ /* zeta varies over the roots of unity in F_p */ fact = minfactor; deg_f = dmin; zeta = gen_1; prim = good_root_of_unity(p, deg_f, 1, &n); expo = diviuexact(subiu(p, 1), n); /* update X+a, avoid a=0 */ gel (xplusa, 2) = addis (gel (xplusa, 2), 1); xpow = FpXQ_pow (xplusa, expo, fact, p); for (i = 0; i < n; i++) { GEN tmp = FpX_gcd(FpX_Fp_sub(xpow, zeta, p), fact, p); long dtmp = degpol(tmp); if (dtmp > 0 && dtmp < deg_f) { fact = FpX_div(fact, tmp, p); deg_f = degpol(fact); if (dtmp < dmin) { minfactor = FpX_normalize (tmp, p); dmin = dtmp; if (dmin == 1 || dmin <= (2 * deg_f) / n - 1) /* stop early to avoid too many gcds */ break; } } zeta = Fp_mul (zeta, prim, p); } } return gerepileuptoint(av, FpX_oneroot(minfactor, p)); } /*******************************************************************/ /* */ /* FACTORISATION MODULO p */ /* */ /*******************************************************************/ /* F / E a vector of vectors of factors / exponents of virtual length l * (their real lg may be larger). Set their lg to j, concat and return [F,E] */ static GEN FE_concat(GEN F, GEN E, long l) { setlg(E,l); E = shallowconcat1(E); setlg(F,l); F = shallowconcat1(F); return mkvec2(F,E); } static GEN ddf_to_ddf2_i(GEN V, long fl) { GEN F, D; long i, j, l = lg(V); F = cgetg(l, t_VEC); D = cgetg(l, t_VECSMALL); for (i = j = 1; i < l; i++) { GEN Vi = gel(V,i); if ((fl==2 && F2x_degree(Vi) == 0) ||(fl==0 && degpol(Vi) == 0)) continue; gel(F,j) = Vi; uel(D,j) = i; j++; } setlg(F,j); setlg(D,j); return mkvec2(F,D); } GEN ddf_to_ddf2(GEN V) { return ddf_to_ddf2_i(V, 0); } static GEN F2x_ddf_to_ddf2(GEN V) { return ddf_to_ddf2_i(V, 2); } GEN vddf_to_simplefact(GEN V, long d) { GEN E, F; long i, j, c, l = lg(V); F = cgetg(d+1, t_VECSMALL); E = cgetg(d+1, t_VECSMALL); for (i = c = 1; i < l; i++) { GEN Vi = gel(V,i); long l = lg(Vi); for (j = 1; j < l; j++) { long k, n = degpol(gel(Vi,j)) / j; for (k = 1; k <= n; k++) { uel(F,c) = j; uel(E,c) = i; c++; } } } setlg(F,c); setlg(E,c); return sort_factor(mkvec2(F,E), (void*)&cmpGuGu, cmp_nodata); } /* product of terms of degree 1 in factorization of f */ 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 = FpX_sub(FpX_Frobenius(f, p), X, p); return FpX_gcd(z,f,p); } /* Compute the number of roots in Fp without counting multiplicity * return -1 for 0 polynomial. lc(f) must be prime to p. */ long FpX_nbroots(GEN f, GEN p) { pari_sp av = avma; GEN z = FpX_split_part(f, p); return gc_long(av, degpol(z)); } /* 1 < deg(f) <= p */ static int Flx_is_totally_split_i(GEN f, ulong p) { GEN F = Flx_Frobenius(f, p); return degpol(F)==1 && uel(F,2)==0UL && uel(F,3)==1UL; } int Flx_is_totally_split(GEN f, ulong p) { pari_sp av = avma; ulong n = degpol(f); if (n <= 1) return 1; if (n > p) return 0; /* includes n < 0 */ return gc_bool(av, Flx_is_totally_split_i(f,p)); } int FpX_is_totally_split(GEN f, GEN p) { pari_sp av = avma; ulong n = degpol(f); int u; if (n <= 1) return 1; if (abscmpui(n, p) > 0) return 0; /* includes n < 0 */ if (lgefint(p) != 3) u = gequalX(FpX_Frobenius(FpX_red(f,p), p)); else { ulong pp = (ulong)p[2]; u = Flx_is_totally_split_i(ZX_to_Flx(f,pp), pp); } return gc_bool(av, u); } long Flx_nbroots(GEN f, ulong p) { long n = degpol(f); ulong pi; pari_sp av = avma; GEN z; if (n <= 1) return n; if (n == 2) { ulong D; if (p==2) return (f[2]==0) + (f[2]!=f[3]); D = Fl_sub(Fl_sqr(f[3], p), Fl_mul(Fl_mul(f[4], f[2], p), 4%p, p), p); return 1 + krouu(D,p); } pi = SMALL_ULONG(p)? 0: get_Fl_red(p); z = Flx_sub(Flx_Frobenius_pre(f, p, pi), polx_Flx(f[1]), p); z = Flx_gcd_pre(z, f, p, pi); return gc_long(av, degpol(z)); } long FpX_ddf_degree(GEN T, GEN XP, GEN p) { pari_sp av = avma; GEN X, b, g, xq; long i, j, n, v, B, l, m; pari_timer ti; hashtable h; n = get_FpX_degree(T); v = get_FpX_var(T); X = pol_x(v); if (ZX_equal(X,XP)) return 1; B = n/2; l = usqrt(B); m = (B+l-1)/l; T = FpX_get_red(T, p); hash_init_GEN(&h, l+2, ZX_equal, 1); hash_insert_long(&h, X, 0); hash_insert_long(&h, XP, 1); if (DEBUGLEVEL>=7) timer_start(&ti); b = XP; xq = FpXQ_powers(b, brent_kung_optpow(n, l-1, 1), T, p); if (DEBUGLEVEL>=7) timer_printf(&ti,"FpX_ddf_degree: xq baby"); for (i = 3; i <= l+1; i++) { b = FpX_FpXQV_eval(b, xq, T, p); if (gequalX(b)) return gc_long(av,i-1); hash_insert_long(&h, b, i-1); } if (DEBUGLEVEL>=7) timer_printf(&ti,"FpX_ddf_degree: baby"); g = b; xq = FpXQ_powers(g, brent_kung_optpow(n, m, 1), T, p); if (DEBUGLEVEL>=7) timer_printf(&ti,"FpX_ddf_degree: xq giant"); for(i = 2; i <= m+1; i++) { g = FpX_FpXQV_eval(g, xq, T, p); if (hash_haskey_long(&h, g, &j)) return gc_long(av, l*i-j); } return gc_long(av,n); } /* See */ static GEN FpX_ddf_Shoup(GEN T, GEN XP, GEN p) { GEN b, g, h, F, f, Tr, xq; long i, j, n, v, B, l, m; pari_timer ti; n = get_FpX_degree(T); v = get_FpX_var(T); if (n == 0) return cgetg(1, t_VEC); if (n == 1) return mkvec(get_FpX_mod(T)); B = n/2; l = usqrt(B); m = (B+l-1)/l; T = FpX_get_red(T, p); b = cgetg(l+2, t_VEC); gel(b, 1) = pol_x(v); gel(b, 2) = XP; if (DEBUGLEVEL>=7) timer_start(&ti); xq = FpXQ_powers(gel(b, 2), brent_kung_optpow(n, l-1, 1), T, p); if (DEBUGLEVEL>=7) timer_printf(&ti,"FpX_ddf_Shoup: xq baby"); for (i = 3; i <= l+1; i++) gel(b, i) = FpX_FpXQV_eval(gel(b, i-1), xq, T, p); if (DEBUGLEVEL>=7) timer_printf(&ti,"FpX_ddf_Shoup: baby"); xq = FpXQ_powers(gel(b, l+1), brent_kung_optpow(n, m-1, 1), T, p); if (DEBUGLEVEL>=7) timer_printf(&ti,"FpX_ddf_Shoup: xq giant"); g = cgetg(m+1, t_VEC); gel(g, 1) = gel(xq, 2); for(i = 2; i <= m; i++) gel(g, i) = FpX_FpXQV_eval(gel(g, i-1), xq, T, p); if (DEBUGLEVEL>=7) timer_printf(&ti,"FpX_ddf_Shoup: giant"); h = cgetg(m+1, t_VEC); for (j = 1; j <= m; j++) { pari_sp av = avma; GEN gj = gel(g,j), e = FpX_sub(gj, gel(b,1), p); for (i = 2; i <= l; i++) e = FpXQ_mul(e, FpX_sub(gj, gel(b,i), p), T, p); gel(h,j) = gerepileupto(av, e); } if (DEBUGLEVEL>=7) timer_printf(&ti,"FpX_ddf_Shoup: diff"); Tr = get_FpX_mod(T); F = cgetg(m+1, t_VEC); for (j = 1; j <= m; j++) { GEN u = FpX_gcd(Tr, gel(h,j), p); if (degpol(u)) { u = FpX_normalize(u, p); Tr = FpX_div(Tr, u, p); } gel(F,j) = u; } if (DEBUGLEVEL>=7) timer_printf(&ti,"FpX_ddf_Shoup: F"); f = const_vec(n, pol_1(v)); for (j = 1; j <= m; j++) { GEN e = gel(F, j); for (i=l-1; i >= 0; i--) { GEN u = FpX_gcd(e, FpX_sub(gel(g, j), gel(b, i+1), p), p); if (degpol(u)) { u = FpX_normalize(u, p); gel(f, l*j-i) = u; e = FpX_div(e, u, p); } if (!degpol(e)) break; } } if (DEBUGLEVEL>=7) timer_printf(&ti,"FpX_ddf_Shoup: f"); if (degpol(Tr)) gel(f, degpol(Tr)) = Tr; return f; } static void FpX_edf_simple(GEN Tp, GEN XP, long d, GEN p, GEN V, long idx) { long n = degpol(Tp), r = n/d, ct = 0; GEN T, f, ff, p2; if (r==1) { gel(V, idx) = Tp; return; } p2 = shifti(p,-1); T = FpX_get_red(Tp, p); XP = FpX_rem(XP, T, p); while (1) { pari_sp btop = avma; long i; GEN g = random_FpX(n, varn(Tp), p); GEN t = gel(FpXQ_auttrace(mkvec2(XP, g), d, T, p), 2); if (signe(t) == 0) continue; for(i=1; i<=10; i++) { pari_sp btop2 = avma; GEN R = FpXQ_pow(FpX_Fp_add(t, randomi(p), p), p2, T, p); f = FpX_gcd(FpX_Fp_sub(R, gen_1, p), Tp, p); if (degpol(f) > 0 && degpol(f) < n) break; set_avma(btop2); } if (degpol(f) > 0 && degpol(f) < n) break; if (++ct == 10 && !BPSW_psp(p)) pari_err_PRIME("FpX_edf_simple",p); set_avma(btop); } f = FpX_normalize(f, p); ff = FpX_div(Tp, f ,p); FpX_edf_simple(f, XP, d, p, V, idx); FpX_edf_simple(ff, XP, d, p, V, idx+degpol(f)/d); } static void FpX_edf_rec(GEN T, GEN hp, GEN t, long d, GEN p2, GEN p, GEN V, long idx) { pari_sp av; GEN Tp = get_FpX_mod(T); long n = degpol(hp), vT = varn(Tp), ct = 0; GEN u1, u2, f1, f2, R, h; h = FpX_get_red(hp, p); t = FpX_rem(t, T, p); av = avma; do { set_avma(av); R = FpXQ_pow(deg1pol(gen_1, randomi(p), vT), p2, h, p); u1 = FpX_gcd(FpX_Fp_sub(R, gen_1, p), hp, p); if (++ct == 10 && !BPSW_psp(p)) pari_err_PRIME("FpX_edf_rec",p); } while (degpol(u1)==0 || degpol(u1)==n); f1 = FpX_gcd(FpX_FpXQ_eval(u1, t, T, p), Tp, p); f1 = FpX_normalize(f1, p); u2 = FpX_div(hp, u1, p); f2 = FpX_div(Tp, f1, p); if (degpol(u1)==1) gel(V, idx) = f1; else FpX_edf_rec(FpX_get_red(f1, p), u1, t, d, p2, p, V, idx); idx += degpol(f1)/d; if (degpol(u2)==1) gel(V, idx) = f2; else FpX_edf_rec(FpX_get_red(f2, p), u2, t, d, p2, p, V, idx); } /* assume Tp a squarefree product of r > 1 irred. factors of degree d */ static void FpX_edf(GEN Tp, GEN XP, long d, GEN p, GEN V, long idx) { long n = degpol(Tp), r = n/d, vT = varn(Tp), ct = 0; GEN T, h, t; pari_timer ti; T = FpX_get_red(Tp, p); XP = FpX_rem(XP, T, p); if (DEBUGLEVEL>=7) timer_start(&ti); do { GEN g = random_FpX(n, vT, p); t = gel(FpXQ_auttrace(mkvec2(XP, g), d, T, p), 2); if (DEBUGLEVEL>=7) timer_printf(&ti,"FpX_edf: FpXQ_auttrace"); h = FpXQ_minpoly(t, T, p); if (DEBUGLEVEL>=7) timer_printf(&ti,"FpX_edf: FpXQ_minpoly"); if (++ct == 10 && !BPSW_psp(p)) pari_err_PRIME("FpX_edf",p); } while (degpol(h) != r); FpX_edf_rec(T, h, t, d, shifti(p, -1), p, V, idx); } static GEN FpX_factor_Shoup(GEN T, GEN p) { long i, n, s = 0; GEN XP, D, V; long e = expi(p); pari_timer ti; n = get_FpX_degree(T); T = FpX_get_red(T, p); if (DEBUGLEVEL>=6) timer_start(&ti); XP = FpX_Frobenius(T, p); if (DEBUGLEVEL>=6) timer_printf(&ti,"FpX_Frobenius"); D = FpX_ddf_Shoup(T, XP, p); if (DEBUGLEVEL>=6) timer_printf(&ti,"FpX_ddf_Shoup"); s = ddf_to_nbfact(D); V = cgetg(s+1, t_COL); for (i = 1, s = 1; i <= n; i++) { GEN Di = gel(D,i); long ni = degpol(Di), ri = ni/i; if (ni == 0) continue; Di = FpX_normalize(Di, p); if (ni == i) { gel(V, s++) = Di; continue; } if (ri <= e*expu(e)) FpX_edf(Di, XP, i, p, V, s); else FpX_edf_simple(Di, XP, i, p, V, s); if (DEBUGLEVEL>=6) timer_printf(&ti,"FpX_edf(%ld)",i); s += ri; } return V; } long ddf_to_nbfact(GEN D) { long l = lg(D), i, s = 0; for(i = 1; i < l; i++) s += degpol(gel(D,i))/i; return s; } /* Yun algorithm: Assume p > degpol(T) */ static GEN FpX_factor_Yun(GEN T, GEN p) { long n = degpol(T), i = 1; GEN a, b, c, d = FpX_deriv(T, p); GEN V = cgetg(n+1,t_VEC); a = FpX_gcd(T, d, p); if (degpol(a) == 0) return mkvec(T); b = FpX_div(T, a, p); do { c = FpX_div(d, a, p); d = FpX_sub(c, FpX_deriv(b, p), p); a = FpX_normalize(FpX_gcd(b, d, p), p); gel(V, i++) = a; b = FpX_div(b, a, p); } while (degpol(b)); setlg(V, i); return V; } GEN FpX_factor_squarefree(GEN T, GEN p) { if (lgefint(p)==3) { ulong pp = (ulong)p[2]; GEN u = Flx_factor_squarefree(ZX_to_Flx(T,pp), pp); return FlxV_to_ZXV(u); } return FpX_factor_Yun(T, p); } GEN FpX_roots_mult(GEN T, long n, GEN p) { pari_sp av = avma; GEN V = FpX_factor_squarefree(T, p), W; long l = lg(V), i; if (l <= n) { set_avma(av); return cgetg(1,t_COL); } W = cgetg(l-n+1,t_VEC); for (i = n; i < l; i++) gel(W,i-n+1) = FpX_roots(gel(V,i), p); return gerepileupto(av, sort(shallowconcat1(W))); } long FpX_ispower(GEN f, ulong k, GEN p, GEN *pt_r) { pari_sp av = avma; GEN lc, F; long i, l, n = degpol(f), v = varn(f); if (n % k) return 0; if (lgefint(p)==3) { ulong pp = p[2]; GEN fp = ZX_to_Flx(f, pp); if (!Flx_ispower(fp, k, pp, pt_r)) return gc_long(av,0); if (pt_r) *pt_r = gerepileupto(av, Flx_to_ZX(*pt_r)); else set_avma(av); return 1; } lc = Fp_sqrtn(leading_coeff(f), stoi(k), p, NULL); if (!lc) { av = avma; return 0; } F = FpX_factor_Yun(f, p); l = lg(F)-1; for(i=1; i <= l; i++) if (i%k && degpol(gel(F,i))) return gc_long(av,0); if (pt_r) { GEN r = scalarpol(lc, v), s = pol_1(v); for (i=l; i>=1; i--) { if (i%k) continue; s = FpX_mul(s, gel(F,i), p); r = FpX_mul(r, s, p); } *pt_r = gerepileupto(av, r); } else av = avma; return 1; } static GEN FpX_factor_Cantor(GEN T, GEN p) { GEN E, F, V = FpX_factor_Yun(T, p); long i, j, l = lg(V); F = cgetg(l, t_VEC); E = cgetg(l, t_VEC); for (i=1, j=1; i < l; i++) if (degpol(gel(V,i))) { GEN Fj = FpX_factor_Shoup(gel(V,i), p); gel(F, j) = Fj; gel(E, j) = const_vecsmall(lg(Fj)-1, i); j++; } return sort_factor_pol(FE_concat(F,E,j), cmpii); } static GEN FpX_ddf_i(GEN T, GEN p) { GEN XP; T = FpX_get_red(T, p); XP = FpX_Frobenius(T, p); return ddf_to_ddf2(FpX_ddf_Shoup(T, XP, p)); } GEN FpX_ddf(GEN f, GEN p) { pari_sp av = avma; GEN F; switch(ZX_factmod_init(&f, p)) { case 0: F = F2x_ddf(f); F2xV_to_ZXV_inplace(gel(F,1)); break; case 1: F = Flx_ddf(f,p[2]); FlxV_to_ZXV_inplace(gel(F,1)); break; default: F = FpX_ddf_i(f,p); break; } return gerepilecopy(av, F); } static GEN Flx_simplefact_Cantor(GEN T, ulong p); static GEN FpX_simplefact_Cantor(GEN T, GEN p) { GEN V; long i, l; if (lgefint(p) == 3) { ulong pp = p[2]; return Flx_simplefact_Cantor(ZX_to_Flx(T,pp), pp); } T = FpX_get_red(T, p); V = FpX_factor_Yun(get_FpX_mod(T), p); l = lg(V); for (i=1; i < l; i++) gel(V,i) = FpX_ddf_Shoup(gel(V,i), FpX_Frobenius(gel(V,i), p), p); return vddf_to_simplefact(V, get_FpX_degree(T)); } static int FpX_isirred_Cantor(GEN Tp, GEN p) { pari_sp av = avma; pari_timer ti; long n; GEN T = get_FpX_mod(Tp); GEN dT = FpX_deriv(T, p); GEN XP, D; if (degpol(FpX_gcd(T, dT, p)) != 0) return gc_bool(av,0); n = get_FpX_degree(T); T = FpX_get_red(Tp, p); if (DEBUGLEVEL>=6) timer_start(&ti); XP = FpX_Frobenius(T, p); if (DEBUGLEVEL>=6) timer_printf(&ti,"FpX_Frobenius"); D = FpX_ddf_Shoup(T, XP, p); if (DEBUGLEVEL>=6) timer_printf(&ti,"FpX_ddf_Shoup"); return gc_bool(av, degpol(gel(D,n)) == n); } static GEN FpX_factor_deg2(GEN f, GEN p, long d, long flag); /*Assume that p is large and odd*/ static GEN FpX_factor_i(GEN f, GEN pp, long flag) { long d = degpol(f); if (d <= 2) return FpX_factor_deg2(f,pp,d,flag); switch(flag) { default: return FpX_factor_Cantor(f, pp); case 1: return FpX_simplefact_Cantor(f, pp); case 2: return FpX_isirred_Cantor(f, pp)? gen_1: NULL; } } long FpX_nbfact_Frobenius(GEN T, GEN XP, GEN p) { pari_sp av = avma; long s = ddf_to_nbfact(FpX_ddf_Shoup(T, XP, p)); return gc_long(av,s); } long FpX_nbfact(GEN T, GEN p) { pari_sp av = avma; GEN XP = FpX_Frobenius(T, p); long n = FpX_nbfact_Frobenius(T, XP, p); return gc_long(av,n); } /* p > 2 */ static GEN FpX_is_irred_2(GEN f, GEN p, long d) { switch(d) { case -1: case 0: return NULL; case 1: return gen_1; } return FpX_quad_factortype(f, p) == -1? gen_1: NULL; } /* p > 2 */ static GEN FpX_degfact_2(GEN f, GEN p, long d) { switch(d) { case -1:retmkvec2(mkvecsmall(-1),mkvecsmall(1)); case 0: return trivial_fact(); case 1: retmkvec2(mkvecsmall(1), mkvecsmall(1)); } switch(FpX_quad_factortype(f, p)) { case 1: retmkvec2(mkvecsmall2(1,1), mkvecsmall2(1,1)); case -1: retmkvec2(mkvecsmall(2), mkvecsmall(1)); default: retmkvec2(mkvecsmall(1), mkvecsmall(2)); } } GEN prime_fact(GEN x) { retmkmat2(mkcolcopy(x), mkcol(gen_1)); } GEN trivial_fact(void) { retmkmat2(cgetg(1,t_COL), cgetg(1,t_COL)); } /* not gerepile safe */ static GEN FpX_factor_2(GEN f, GEN p, long d) { GEN r, s, R, S; long v; int sgn; switch(d) { case -1: retmkvec2(mkcol(pol_0(varn(f))), mkvecsmall(1)); case 0: retmkvec2(cgetg(1,t_COL), cgetg(1,t_VECSMALL)); case 1: retmkvec2(mkcol(f), mkvecsmall(1)); } r = FpX_quad_root(f, p, 1); if (!r) return mkvec2(mkcol(f), mkvecsmall(1)); v = varn(f); s = FpX_otherroot(f, r, p); if (signe(r)) r = subii(p, r); if (signe(s)) s = subii(p, s); sgn = cmpii(s, r); if (sgn < 0) swap(s,r); R = deg1pol_shallow(gen_1, r, v); if (!sgn) return mkvec2(mkcol(R), mkvecsmall(2)); S = deg1pol_shallow(gen_1, s, v); return mkvec2(mkcol2(R,S), mkvecsmall2(1,1)); } static GEN FpX_factor_deg2(GEN f, GEN p, long d, long flag) { switch(flag) { case 2: return FpX_is_irred_2(f, p, d); case 1: return FpX_degfact_2(f, p, d); default: return FpX_factor_2(f, p, d); } } static int F2x_quad_factortype(GEN x) { return x[2] == 7 ? -1: x[2] == 6 ? 1 :0; } static GEN F2x_is_irred_2(GEN f, long d) { return d == 1 || (d==2 && F2x_quad_factortype(f) == -1)? gen_1: NULL; } static GEN F2x_degfact_2(GEN f, long d) { if (!d) return trivial_fact(); if (d == 1) return mkvec2(mkvecsmall(1), mkvecsmall(1)); switch(F2x_quad_factortype(f)) { case 1: return mkvec2(mkvecsmall2(1,1), mkvecsmall2(1,1)); case -1:return mkvec2(mkvecsmall(2), mkvecsmall(1)); default: return mkvec2(mkvecsmall(1), mkvecsmall(2)); } } static GEN F2x_factor_2(GEN f, long d) { long v = f[1]; if (!d) return mkvec2(cgetg(1,t_COL), cgetg(1,t_VECSMALL)); if (labs(d) == 1) return mkvec2(mkcol(f), mkvecsmall(1)); switch(F2x_quad_factortype(f)) { case -1: return mkvec2(mkcol(f), mkvecsmall(1)); case 0: return mkvec2(mkcol(mkvecsmall2(v,2+F2x_coeff(f,0))), mkvecsmall(2)); default: return mkvec2(mkcol2(mkvecsmall2(v,2),mkvecsmall2(v,3)), mkvecsmall2(1,1)); } } static GEN F2x_factor_deg2(GEN f, long d, long flag) { switch(flag) { case 2: return F2x_is_irred_2(f, d); case 1: return F2x_degfact_2(f, d); default: return F2x_factor_2(f, d); } } /* xt = NULL or x^(p-1)/2 mod g */ static void split_squares(struct split_t *S, GEN g, ulong p, ulong pi, GEN xt) { ulong q = p >> 1; GEN a = Flx_mod_Xnm1(g, q, p); /* mod x^(p-1)/2 - 1 */ long d = degpol(a); if (d < 0) { ulong i; split_add_done(S, (GEN)1); if (!pi) for (i = 2; i <= q; i++) split_add_done(S, (GEN)Fl_sqr(i,p)); else for (i = 2; i <= q; i++) split_add_done(S, (GEN)Fl_sqr_pre(i,p,pi)); } else { if (a != g) { (void)Flx_valrem(a, &a); d = degpol(a); } if (d) { if (xt) xt = Flx_Fl_add(xt, p-1, p); else xt = Flx_Xnm1(g[1], q, p); a = Flx_gcd_pre(a, xt, p, pi); if (degpol(a)) split_add(S, Flx_normalize(a, p)); } } } static void split_nonsquares(struct split_t *S, GEN g, ulong p, ulong pi, GEN xt) { ulong q = p >> 1; GEN a = Flx_mod_Xn1(g, q, p); /* mod x^(p-1)/2 + 1 */ long d = degpol(a); if (d < 0) { ulong i, z = nonsquare_Fl(p); split_add_done(S, (GEN)z); if (!pi) for (i = 2; i <= q; i++) split_add_done(S, (GEN)Fl_mul(z, Fl_sqr(i,p), p)); else for (i = 2; i <= q; i++) split_add_done(S, (GEN)Fl_mul_pre(z, Fl_sqr_pre(i,p,pi), p,pi)); } else { if (a != g) { (void)Flx_valrem(a, &a); d = degpol(a); } if (d) { if (xt) xt = Flx_Fl_add(xt, 1, p); else xt = Flx_Xn1(g[1], q, p); a = Flx_gcd_pre(a, xt, p, pi); if (degpol(a)) split_add(S, Flx_normalize(a, p)); } } } /* p > 2. f monic Flx, f(0) != 0. Add to split_t structs coprime factors * of g = \prod_{f(a) = 0} (X - a). Return 0 when f(x) = 0 for all x in Fp* */ static int split_Flx_cut_out_roots(struct split_t *S, GEN f, ulong p, ulong pi) { GEN a, g = Flx_mod_Xnm1(f, p-1, p); /* f mod x^(p-1) - 1 */ long d = degpol(g); if (d < 0) return 0; if (g != f) { (void)Flx_valrem(g, &g); d = degpol(g); } /*kill powers of x*/ if (!d) return 1; if ((p >> 4) <= (ulong)d) { /* small p; split directly using x^((p-1)/2) +/- 1 */ GEN xt = ((ulong)d < (p>>1))? Flx_rem_pre(monomial_Flx(1, p>>1, g[1]), g, p, pi) : NULL; split_squares(S, g, p, pi, xt); split_nonsquares(S, g, p, pi, xt); } else { /* large p; use x^(p-1) - 1 directly */ a = Flxq_powu_pre(polx_Flx(f[1]), p-1, g, p, pi); if (lg(a) < 3) pari_err_PRIME("rootmod",utoipos(p)); a = Flx_Fl_add(a, p-1, p); /* a = x^(p-1) - 1 mod g */ g = Flx_gcd_pre(g,a, p,pi); if (degpol(g)) split_add(S, Flx_normalize(g,p)); } return 1; } /* by splitting, assume p > 2 prime, deg(f) > 0, and f monic */ GEN Flx_roots_pre(GEN f, ulong p, ulong pi) { GEN pol; long v = Flx_valrem(f, &f), n = degpol(f); ulong q, PI; struct split_t S; f = Flx_normalize(f, p); /* optimization: test for small degree first */ if (n == 1) { q = p - f[2]; return v? mkvecsmall2(0, q): mkvecsmall(q); } PI = pi? pi: get_Fl_red(p); /* PI for Fp, pi for Fp[x] */ if (n == 2) { ulong r = Flx_quad_root(f, p, PI, 1), s; if (r == p) return v? mkvecsmall(0): cgetg(1,t_VECSMALL); s = Flx_otherroot(f,r, p); if (r < s) return v? mkvecsmall3(0, r, s): mkvecsmall2(r, s); else if (r > s) return v? mkvecsmall3(0, s, r): mkvecsmall2(s, r); else return v? mkvecsmall2(0, s): mkvecsmall(s); } if (SMALL_ULONG(p)) pi = 0; /* bilinear ops faster without Fl_*_pre */ q = p >> 1; split_init(&S, lg(f)-1); settyp(S.done, t_VECSMALL); if (v) split_add_done(&S, (GEN)0); if (! split_Flx_cut_out_roots(&S, f, p, pi)) return all_roots_mod_p(p, lg(S.done) == 1); pol = polx_Flx(f[1]); for (pol[2]=1; ; pol[2]++) { long j, l = lg(S.todo); if (l == 1) { vecsmall_sort(S.done); return S.done; } if (pol[2] == 100 && !uisprime(p)) pari_err_PRIME("polrootsmod",utoipos(p)); for (j = 1; j < l; j++) { GEN b, c = gel(S.todo,j); ulong r, s; switch(degpol(c)) { case 1: split_moveto_done(&S, j, (GEN)(p - c[2])); j--; l--; break; case 2: r = Flx_quad_root(c, p, PI, 0); if (r == p) pari_err_PRIME("polrootsmod",utoipos(p)); s = Flx_otherroot(c,r, p); split_done(&S, j, (GEN)r, (GEN)s); j--; l--; break; default: b = Flxq_powu_pre(pol,q, c,p,pi); /* pol^(p-1)/2 */ if (degpol(b) <= 0) continue; b = Flx_gcd_pre(c,Flx_Fl_add(b,p-1,p), p, pi); if (!degpol(b)) continue; b = Flx_normalize(b, p); c = Flx_div_pre(c,b, p,pi); split_todo(&S, j, b, c); } } } } GEN Flx_roots(GEN f, ulong p) { pari_sp av = avma; ulong pi; switch(lg(f)) { case 2: pari_err_ROOTS0("Flx_roots"); case 3: set_avma(av); return cgetg(1, t_VECSMALL); } if (p == 2) return Flx_root_mod_2(f); pi = SMALL_ULONG(p)? 0: get_Fl_red(p); return gerepileuptoleaf(av, Flx_roots_pre(f, p, pi)); } /* assume x reduced mod p, monic. */ static int Flx_quad_factortype(GEN x, ulong p) { ulong b = x[3], c = x[2]; return krouu(Fl_disc_bc(b, c, p), p); } static GEN Flx_is_irred_2(GEN f, ulong p, long d) { if (!d) return NULL; if (d == 1) return gen_1; return Flx_quad_factortype(f, p) == -1? gen_1: NULL; } static GEN Flx_degfact_2(GEN f, ulong p, long d) { if (!d) return trivial_fact(); if (d == 1) return mkvec2(mkvecsmall(1), mkvecsmall(1)); switch(Flx_quad_factortype(f, p)) { case 1: return mkvec2(mkvecsmall2(1,1), mkvecsmall2(1,1)); case -1:return mkvec2(mkvecsmall(2), mkvecsmall(1)); default: return mkvec2(mkvecsmall(1), mkvecsmall(2)); } } /* p > 2 */ static GEN Flx_factor_2(GEN f, ulong p, long d) { ulong r, s; GEN R,S; long v = f[1]; if (!d) return mkvec2(cgetg(1,t_COL), cgetg(1,t_VECSMALL)); if (labs(d) == 1) return mkvec2(mkcol(f), mkvecsmall(1)); r = Flx_quad_root(f, p, get_Fl_red(p), 1); if (r==p) return mkvec2(mkcol(f), mkvecsmall(1)); s = Flx_otherroot(f, r, p); r = Fl_neg(r, p); s = Fl_neg(s, p); if (s < r) lswap(s,r); R = mkvecsmall3(v,r,1); if (s == r) return mkvec2(mkcol(R), mkvecsmall(2)); S = mkvecsmall3(v,s,1); return mkvec2(mkcol2(R,S), mkvecsmall2(1,1)); } static GEN Flx_factor_deg2(GEN f, ulong p, long d, long flag) { switch(flag) { case 2: return Flx_is_irred_2(f, p, d); case 1: return Flx_degfact_2(f, p, d); default: return Flx_factor_2(f, p, d); } } static GEN F2x_Berlekamp_ker(GEN u) { pari_sp ltop=avma; long j,N = F2x_degree(u); GEN Q; pari_timer T; timer_start(&T); Q = F2x_matFrobenius(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); } #define set_irred(i) { if ((i)>ir) swap(t[i],t[ir]); ir++;} static long F2x_split_Berlekamp(GEN *t) { GEN u = *t, a, b, vker; long lb, d, i, ir, L, la, sv = u[1], du = F2x_degree(u); if (du == 1) return 1; if (du == 2) { if (F2x_quad_factortype(u) == 1) /* 0 is a root: shouldn't occur */ { t[0] = mkvecsmall2(sv, 2); t[1] = mkvecsmall2(sv, 3); return 2; } return 1; } vker = F2x_Berlekamp_ker(u); lb = lgcols(vker); d = lg(vker)-1; ir = 0; /* t[i] irreducible for i < ir, still to be treated for i < L */ for (L=1; L 2 */ static GEN F2x_Berlekamp_i(GEN f, long flag) { long lfact, val, d = F2x_degree(f), j, k, lV; GEN y, E, t, V; val = F2x_valrem(f, &f); if (flag == 2 && val) return NULL; V = F2x_factor_squarefree(f); lV = lg(V); if (flag == 2 && lV > 2) return NULL; /* to hold factors and exponents */ t = cgetg(d+1, flag? t_VECSMALL: t_VEC); E = cgetg(d+1,t_VECSMALL); lfact = 1; if (val) { if (flag == 1) t[1] = 1; else gel(t,1) = polx_F2x(f[1]); E[1] = val; lfact++; } for (k=1; k 0) { long j; for(j = 1;;j++) { v = F2x_gcd(r, t); tv = F2x_div(t, v); if (F2x_degree(tv) > 0) gel(u, j*q) = tv; if (F2x_degree(v) <= 0) break; r = F2x_div(r, v); t = v; } if (F2x_degree(r) == 0) break; } f = F2x_sqrt(r); } for (i = n; i; i--) if (F2x_degree(gel(u,i))) break; setlg(u,i+1); return u; } static GEN F2x_ddf_simple(GEN T, GEN XP) { pari_sp av = avma, av2; GEN f, z, Tr, X; long j, n = F2x_degree(T), v = T[1], B = n/2; if (n == 0) return cgetg(1, t_VEC); if (n == 1) return mkvec(T); z = XP; Tr = T; X = polx_F2x(v); f = const_vec(n, pol1_F2x(v)); av2 = avma; for (j = 1; j <= B; j++) { GEN u = F2x_gcd(Tr, F2x_add(z, X)); if (F2x_degree(u)) { gel(f, j) = u; Tr = F2x_div(Tr, u); av2 = avma; } else z = gerepileuptoleaf(av2, z); if (!F2x_degree(Tr)) break; z = F2xq_sqr(z, Tr); } if (F2x_degree(Tr)) gel(f, F2x_degree(Tr)) = Tr; return gerepilecopy(av, f); } GEN F2x_ddf(GEN T) { GEN XP; T = F2x_get_red(T); XP = F2x_Frobenius(T); return F2x_ddf_to_ddf2(F2x_ddf_simple(T, XP)); } static GEN F2xq_frobtrace(GEN a, long d, GEN T) { pari_sp av = avma; long i; GEN x = a; for(i=1; i 0 && df < n) break; set_avma(btop); } ff = F2x_div(Tp, f); F2x_edf_simple(f, XP, d, V, idx); F2x_edf_simple(ff, XP, d, V, idx+F2x_degree(f)/d); } static GEN F2x_factor_Shoup(GEN T) { long i, n, s = 0; GEN XP, D, V; pari_timer ti; n = F2x_degree(T); if (DEBUGLEVEL>=6) timer_start(&ti); XP = F2x_Frobenius(T); if (DEBUGLEVEL>=6) timer_printf(&ti,"F2x_Frobenius"); D = F2x_ddf_simple(T, XP); if (DEBUGLEVEL>=6) timer_printf(&ti,"F2x_ddf_simple"); for (i = 1; i <= n; i++) s += F2x_degree(gel(D,i))/i; V = cgetg(s+1, t_COL); for (i = 1, s = 1; i <= n; i++) { GEN Di = gel(D,i); long ni = F2x_degree(Di), ri = ni/i; if (ni == 0) continue; if (ni == i) { gel(V, s++) = Di; continue; } F2x_edf_simple(Di, XP, i, V, s); if (DEBUGLEVEL>=6) timer_printf(&ti,"F2x_edf(%ld)",i); s += ri; } return V; } static GEN F2x_factor_Cantor(GEN T) { GEN E, F, V = F2x_factor_squarefree(T); long i, j, l = lg(V); E = cgetg(l, t_VEC); F = cgetg(l, t_VEC); for (i=1, j=1; i < l; i++) if (F2x_degree(gel(V,i))) { GEN Fj = F2x_factor_Shoup(gel(V,i)); gel(F, j) = Fj; gel(E, j) = const_vecsmall(lg(Fj)-1, i); j++; } return sort_factor_pol(FE_concat(F,E,j), cmpGuGu); } #if 0 static GEN F2x_simplefact_Shoup(GEN T) { long i, n, s = 0, j = 1, k; GEN XP, D, V; pari_timer ti; n = F2x_degree(T); if (DEBUGLEVEL>=6) timer_start(&ti); XP = F2x_Frobenius(T); if (DEBUGLEVEL>=6) timer_printf(&ti,"F2x_Frobenius"); D = F2x_ddf_simple(T, XP); if (DEBUGLEVEL>=6) timer_printf(&ti,"F2x_ddf_simple"); for (i = 1; i <= n; i++) s += F2x_degree(gel(D,i))/i; V = cgetg(s+1, t_VECSMALL); for (i = 1; i <= n; i++) { long ni = F2x_degree(gel(D,i)), ri = ni/i; if (ni == 0) continue; for (k = 1; k <= ri; k++) V[j++] = i; } return V; } static GEN F2x_simplefact_Cantor(GEN T) { GEN E, F, V = F2x_factor_squarefree(T); long i, j, l = lg(V); F = cgetg(l, t_VEC); E = cgetg(l, t_VEC); for (i=1, j=1; i < l; i++) if (F2x_degree(gel(V,i))) { GEN Fj = F2x_simplefact_Shoup(gel(V,i)); gel(F, j) = Fj; gel(E, j) = const_vecsmall(lg(Fj)-1, i); j++; } return sort_factor(FE_concat(F,E,j), (void*)&cmpGuGu, cmp_nodata); } static int F2x_isirred_Cantor(GEN T) { pari_sp av = avma; pari_timer ti; long n; GEN dT = F2x_deriv(T); GEN XP, D; if (F2x_degree(F2x_gcd(T, dT)) != 0) return gc_bool(av,0); n = F2x_degree(T); if (DEBUGLEVEL>=6) timer_start(&ti); XP = F2x_Frobenius(T); if (DEBUGLEVEL>=6) timer_printf(&ti,"F2x_Frobenius"); D = F2x_ddf_simple(T, XP); if (DEBUGLEVEL>=6) timer_printf(&ti,"F2x_ddf_simple"); return gc_bool(av, F2x_degree(gel(D,n)) == n); } #endif /* driver for Cantor factorization, assume deg f > 2; not competitive for * flag != 0, or as deg f increases */ static GEN F2x_Cantor_i(GEN f, long flag) { switch(flag) { default: return F2x_factor_Cantor(f); #if 0 case 1: return F2x_simplefact_Cantor(f); case 2: return F2x_isirred_Cantor(f)? gen_1: NULL; #endif } } static GEN F2x_factor_i(GEN f, long flag) { long d = F2x_degree(f); if (d <= 2) return F2x_factor_deg2(f,d,flag); return (flag == 0 && d <= 20)? F2x_Cantor_i(f, flag) : F2x_Berlekamp_i(f, flag); } GEN F2x_degfact(GEN f) { pari_sp av = avma; GEN z = F2x_factor_i(f, 1); return gerepilecopy(av, z); } int F2x_is_irred(GEN f) { return !!F2x_factor_i(f, 2); } /* Adapted from Shoup NTL */ GEN Flx_factor_squarefree_pre(GEN f, ulong p, ulong pi) { long i, q, n = degpol(f); GEN u = const_vec(n+1, pol1_Flx(f[1])); for(q = 1;;q *= p) { GEN t, v, tv, r = Flx_gcd_pre(f, Flx_deriv(f, p), p, pi); if (degpol(r) == 0) { gel(u, q) = f; break; } t = Flx_div_pre(f, r, p, pi); if (degpol(t) > 0) { long j; for(j = 1;;j++) { v = Flx_gcd_pre(r, t, p, pi); tv = Flx_div_pre(t, v, p, pi); if (degpol(tv) > 0) gel(u, j*q) = Flx_normalize(tv, p); if (degpol(v) <= 0) break; r = Flx_div_pre(r, v, p, pi); t = v; } if (degpol(r) == 0) break; } f = Flx_normalize(Flx_deflate(r, p), p); } for (i = n; i; i--) if (degpol(gel(u,i))) break; setlg(u,i+1); return u; } GEN Flx_factor_squarefree(GEN f, ulong p) { return Flx_factor_squarefree_pre(f, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } long Flx_ispower(GEN f, ulong k, ulong p, GEN *pt_r) { pari_sp av = avma; ulong lc, pi; GEN F; long i, n = degpol(f), v = f[1], l; if (n % k) return 0; lc = Fl_sqrtn(Flx_lead(f), k, p, NULL); if (lc == ULONG_MAX) { av = avma; return 0; } pi = SMALL_ULONG(p)? 0: get_Fl_red(p); F = Flx_factor_squarefree_pre(f, p, pi); l = lg(F)-1; for (i = 1; i <= l; i++) if (i%k && degpol(gel(F,i))) return gc_long(av,0); if (pt_r) { GEN r = Fl_to_Flx(lc, v), s = pol1_Flx(v); for(i = l; i >= 1; i--) { if (i%k) continue; s = Flx_mul_pre(s, gel(F,i), p, pi); r = Flx_mul_pre(r, s, p, pi); } *pt_r = gerepileuptoleaf(av, r); } else set_avma(av); return 1; } /* See */ static GEN Flx_ddf_Shoup(GEN T, GEN XP, ulong p, ulong pi) { pari_sp av = avma; GEN b, g, h, F, f, Tr, xq; long i, j, n, v, bo, ro; long B, l, m; pari_timer ti; n = get_Flx_degree(T); v = get_Flx_var(T); if (n == 0) return cgetg(1, t_VEC); if (n == 1) return mkvec(get_Flx_mod(T)); B = n/2; l = usqrt(B); m = (B+l-1)/l; T = Flx_get_red(T, p); b = cgetg(l+2, t_VEC); gel(b, 1) = polx_Flx(v); gel(b, 2) = XP; bo = brent_kung_optpow(n, l-1, 1); ro = l<=1 ? 0:(bo-1)/(l-1) + ((n-1)/bo); if (DEBUGLEVEL>=7) timer_start(&ti); if (expu(p) <= ro) for (i = 3; i <= l+1; i++) gel(b, i) = Flxq_powu_pre(gel(b, i-1), p, T, p, pi); else { xq = Flxq_powers_pre(gel(b, 2), bo, T, p, pi); if (DEBUGLEVEL>=7) timer_printf(&ti,"Flx_ddf_Shoup: xq baby"); for (i = 3; i <= l+1; i++) gel(b, i) = Flx_FlxqV_eval_pre(gel(b, i-1), xq, T, p, pi); } if (DEBUGLEVEL>=7) timer_printf(&ti,"Flx_ddf_Shoup: baby"); xq = Flxq_powers_pre(gel(b, l+1), brent_kung_optpow(n, m-1, 1), T, p, pi); if (DEBUGLEVEL>=7) timer_printf(&ti,"Flx_ddf_Shoup: xq giant"); g = cgetg(m+1, t_VEC); gel(g, 1) = gel(xq, 2); for(i = 2; i <= m; i++) gel(g, i) = Flx_FlxqV_eval_pre(gel(g, i-1), xq, T, p, pi); if (DEBUGLEVEL>=7) timer_printf(&ti,"Flx_ddf_Shoup: giant"); h = cgetg(m+1, t_VEC); for (j = 1; j <= m; j++) { pari_sp av = avma; GEN gj = gel(g, j); GEN e = Flx_sub(gj, gel(b, 1), p); for (i = 2; i <= l; i++) e = Flxq_mul_pre(e, Flx_sub(gj, gel(b, i), p), T, p, pi); gel(h, j) = gerepileupto(av, e); } if (DEBUGLEVEL>=7) timer_printf(&ti,"Flx_ddf_Shoup: diff"); Tr = get_Flx_mod(T); F = cgetg(m+1, t_VEC); for (j = 1; j <= m; j++) { GEN u = Flx_gcd_pre(Tr, gel(h, j), p, pi); if (degpol(u)) { u = Flx_normalize(u, p); Tr = Flx_div_pre(Tr, u, p, pi); } gel(F, j) = u; } if (DEBUGLEVEL>=7) timer_printf(&ti,"Flx_ddf_Shoup: F"); f = const_vec(n, pol1_Flx(v)); for (j = 1; j <= m; j++) { GEN e = gel(F, j); for (i=l-1; i >= 0; i--) { GEN u = Flx_gcd_pre(e, Flx_sub(gel(g, j), gel(b, i+1), p), p, pi); if (degpol(u)) { gel(f, l*j-i) = u; e = Flx_div_pre(e, u, p, pi); } if (!degpol(e)) break; } } if (DEBUGLEVEL>=7) timer_printf(&ti,"Flx_ddf_Shoup: f"); if (degpol(Tr)) gel(f, degpol(Tr)) = Tr; return gerepilecopy(av, f); } static void Flx_edf_simple(GEN Tp, GEN XP, long d, ulong p, ulong pi, GEN V, long idx) { long n = degpol(Tp), r = n/d; GEN T, f, ff; ulong p2; if (r==1) { gel(V, idx) = Tp; return; } p2 = p>>1; T = Flx_get_red_pre(Tp, p, pi); XP = Flx_rem_pre(XP, T, p, pi); while (1) { pari_sp btop = avma; long i; GEN g = random_Flx(n, Tp[1], p); GEN t = gel(Flxq_auttrace_pre(mkvec2(XP, g), d, T, p, pi), 2); if (lgpol(t) == 0) continue; for(i=1; i<=10; i++) { pari_sp btop2 = avma; GEN R = Flxq_powu_pre(Flx_Fl_add(t, random_Fl(p), p), p2, T, p, pi); f = Flx_gcd_pre(Flx_Fl_add(R, p-1, p), Tp, p, pi); if (degpol(f) > 0 && degpol(f) < n) break; set_avma(btop2); } if (degpol(f) > 0 && degpol(f) < n) break; set_avma(btop); } f = Flx_normalize(f, p); ff = Flx_div_pre(Tp, f, p, pi); Flx_edf_simple(f, XP, d, p, pi, V, idx); Flx_edf_simple(ff, XP, d, p, pi, V, idx+degpol(f)/d); } static void Flx_edf(GEN Tp, GEN XP, long d, ulong p, ulong pi, GEN V, long idx); static void Flx_edf_rec(GEN T, GEN XP, GEN hp, GEN t, long d, ulong p, ulong pi, GEN V, long idx) { pari_sp av; GEN Tp = get_Flx_mod(T); long n = degpol(hp), vT = Tp[1]; GEN u1, u2, f1, f2; ulong p2 = p>>1; GEN R, h; h = Flx_get_red_pre(hp, p, pi); t = Flx_rem_pre(t, T, p, pi); av = avma; do { set_avma(av); R = Flxq_powu_pre(mkvecsmall3(vT, random_Fl(p), 1), p2, h, p, pi); u1 = Flx_gcd_pre(Flx_Fl_add(R, p-1, p), hp, p, pi); } while (degpol(u1)==0 || degpol(u1)==n); f1 = Flx_gcd_pre(Flx_Flxq_eval_pre(u1, t, T, p, pi), Tp, p, pi); f1 = Flx_normalize(f1, p); u2 = Flx_div_pre(hp, u1, p, pi); f2 = Flx_div_pre(Tp, f1, p, pi); if (degpol(u1)==1) { if (degpol(f1)==d) gel(V, idx) = f1; else Flx_edf(f1, XP, d, p, pi, V, idx); } else Flx_edf_rec(Flx_get_red(f1, p), XP, u1, t, d, p, pi, V, idx); idx += degpol(f1)/d; if (degpol(u2)==1) { if (degpol(f2)==d) gel(V, idx) = f2; else Flx_edf(f2, XP, d, p, pi, V, idx); } else Flx_edf_rec(Flx_get_red(f2, p), XP, u2, t, d, p, pi, V, idx); } static void Flx_edf(GEN Tp, GEN XP, long d, ulong p, ulong pi, GEN V, long idx) { long n = degpol(Tp), r = n/d, vT = Tp[1]; GEN T, h, t; pari_timer ti; if (r==1) { gel(V, idx) = Tp; return; } T = Flx_get_red_pre(Tp, p, pi); XP = Flx_rem_pre(XP, T, p, pi); if (DEBUGLEVEL>=7) timer_start(&ti); do { GEN g = random_Flx(n, vT, p); t = gel(Flxq_auttrace_pre(mkvec2(XP, g), d, T, p, pi), 2); if (DEBUGLEVEL>=7) timer_printf(&ti,"Flx_edf: Flxq_auttrace"); h = Flxq_minpoly_pre(t, T, p, pi); if (DEBUGLEVEL>=7) timer_printf(&ti,"Flx_edf: Flxq_minpoly"); } while (degpol(h) <= 1); Flx_edf_rec(T, XP, h, t, d, p, pi, V, idx); } static GEN Flx_factor_Shoup(GEN T, ulong p, ulong pi) { long i, n, s = 0, e = expu(p); GEN XP, D, V; pari_timer ti; n = get_Flx_degree(T); T = Flx_get_red_pre(T, p, pi); if (DEBUGLEVEL>=6) timer_start(&ti); XP = Flx_Frobenius_pre(T, p, pi); if (DEBUGLEVEL>=6) timer_printf(&ti,"Flx_Frobenius"); D = Flx_ddf_Shoup(T, XP, p, pi); if (DEBUGLEVEL>=6) timer_printf(&ti,"Flx_ddf_Shoup"); s = ddf_to_nbfact(D); V = cgetg(s+1, t_COL); for (i = 1, s = 1; i <= n; i++) { GEN Di = gel(D,i); long ni = degpol(Di), ri = ni/i; if (ni == 0) continue; Di = Flx_normalize(Di, p); if (ni == i) { gel(V, s++) = Di; continue; } if (ri <= e*expu(e)) Flx_edf(Di, XP, i, p, pi, V, s); else Flx_edf_simple(Di, XP, i, p, pi, V, s); if (DEBUGLEVEL>=6) timer_printf(&ti,"Flx_edf(%ld)",i); s += ri; } return V; } static GEN Flx_factor_Cantor(GEN T, ulong p) { ulong pi = SMALL_ULONG(p)? 0: get_Fl_red(p); GEN E, F, V = Flx_factor_squarefree_pre(get_Flx_mod(T), p, pi); long i, j, l = lg(V); F = cgetg(l, t_VEC); E = cgetg(l, t_VEC); for (i=1, j=1; i < l; i++) if (degpol(gel(V,i))) { GEN Fj = Flx_factor_Shoup(gel(V,i), p, pi); gel(F, j) = Fj; gel(E, j) = const_vecsmall(lg(Fj)-1, i); j++; } return sort_factor_pol(FE_concat(F,E,j), cmpGuGu); } GEN Flx_ddf_pre(GEN T, ulong p, ulong pi) { GEN XP; T = Flx_get_red_pre(T, p, pi); XP = Flx_Frobenius_pre(T, p, pi); return ddf_to_ddf2(Flx_ddf_Shoup(T, XP, p, pi)); } GEN Flx_ddf(GEN T, ulong p) { return Flx_ddf_pre(T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } static GEN Flx_simplefact_Cantor(GEN T, ulong p) { ulong pi = SMALL_ULONG(p)? 0: get_Fl_red(p); long i, l; GEN V; T = Flx_get_red_pre(T, p, pi); V = Flx_factor_squarefree_pre(get_Flx_mod(T), p, pi); l = lg(V); for (i=1; i < l; i++) gel(V,i) = Flx_ddf_Shoup(gel(V,i), Flx_Frobenius_pre(gel(V,i), p,pi), p,pi); return vddf_to_simplefact(V, get_Flx_degree(T)); } static int Flx_isirred_Cantor(GEN Tp, ulong p) { pari_sp av = avma; pari_timer ti; GEN T = get_Flx_mod(Tp), dT = Flx_deriv(T, p), XP, D; ulong pi = SMALL_ULONG(p)? 0: get_Fl_red(p); long n; if (degpol(Flx_gcd_pre(T, dT, p, pi)) != 0) return gc_bool(av,0); n = get_Flx_degree(T); T = Flx_get_red_pre(Tp, p, pi); if (DEBUGLEVEL>=6) timer_start(&ti); XP = Flx_Frobenius_pre(T, p, pi); if (DEBUGLEVEL>=6) timer_printf(&ti,"Flx_Frobenius"); D = Flx_ddf_Shoup(T, XP, p, pi); if (DEBUGLEVEL>=6) timer_printf(&ti,"Flx_ddf_Shoup"); return gc_bool(av, degpol(gel(D,n)) == n); } /* f monic */ static GEN Flx_factor_i(GEN f, ulong pp, long flag) { long d; if (pp==2) { /*We need to handle 2 specially */ GEN F = F2x_factor_i(Flx_to_F2x(f),flag); if (flag==0) F2xV_to_FlxV_inplace(gel(F,1)); return F; } d = degpol(f); if (d <= 2) return Flx_factor_deg2(f,pp,d,flag); switch(flag) { default: return Flx_factor_Cantor(f, pp); case 1: return Flx_simplefact_Cantor(f, pp); case 2: return Flx_isirred_Cantor(f, pp)? gen_1: NULL; } } GEN Flx_degfact(GEN f, ulong p) { pari_sp av = avma; GEN z = Flx_factor_i(Flx_normalize(f,p),p,1); return gerepilecopy(av, z); } /* T must be squarefree mod p*/ GEN Flx_nbfact_by_degree(GEN T, long *nb, ulong p) { GEN XP, D; pari_timer ti; ulong pi = SMALL_ULONG(p)? 0: get_Fl_red(p); long i, s, n = get_Flx_degree(T); GEN V = const_vecsmall(n, 0); pari_sp av = avma; T = Flx_get_red_pre(T, p, pi); if (DEBUGLEVEL>=6) timer_start(&ti); XP = Flx_Frobenius_pre(T, p, pi); if (DEBUGLEVEL>=6) timer_printf(&ti,"Flx_Frobenius"); D = Flx_ddf_Shoup(T, XP, p, pi); if (DEBUGLEVEL>=6) timer_printf(&ti,"Flx_ddf_Shoup"); for (i = 1, s = 0; i <= n; i++) { V[i] = degpol(gel(D,i))/i; s += V[i]; } *nb = s; set_avma(av); return V; } long Flx_nbfact_Frobenius_pre(GEN T, GEN XP, ulong p, ulong pi) { pari_sp av = avma; long s = ddf_to_nbfact(Flx_ddf_Shoup(T, XP, p, pi)); return gc_long(av,s); } long Flx_nbfact_Frobenius(GEN T, GEN XP, ulong p) { return Flx_nbfact_Frobenius_pre(T, XP, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } /* T must be squarefree mod p*/ long Flx_nbfact_pre(GEN T, ulong p, ulong pi) { pari_sp av = avma; GEN XP = Flx_Frobenius_pre(T, p, pi); long n = Flx_nbfact_Frobenius_pre(T, XP, p, pi); return gc_long(av,n); } long Flx_nbfact(GEN T, ulong p) { return Flx_nbfact_pre(T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } int Flx_is_irred(GEN f, ulong p) { pari_sp av = avma; f = Flx_normalize(f,p); return gc_bool(av, !!Flx_factor_i(f,p,2)); } /* Use this function when you think f is reducible, and that there are lots of * factors. If you believe f has few factors, use FpX_nbfact(f,p)==1 instead */ int FpX_is_irred(GEN f, GEN p) { pari_sp av = avma; int z; switch(ZX_factmod_init(&f,p)) { case 0: z = !!F2x_factor_i(f,2); break; case 1: z = !!Flx_factor_i(f,p[2],2); break; default: z = !!FpX_factor_i(f,p,2); break; } return gc_bool(av,z); } GEN FpX_degfact(GEN f, GEN p) { pari_sp av = avma; GEN F; switch(ZX_factmod_init(&f,p)) { case 0: F = F2x_factor_i(f,1); break; case 1: F = Flx_factor_i(f,p[2],1); break; default: F = FpX_factor_i(f,p,1); break; } return gerepilecopy(av, F); } #if 0 /* set x <-- x + c*y mod p */ /* x is not required to be normalized.*/ static void Flx_addmul_inplace(GEN gx, GEN gy, ulong c, ulong p) { long i, lx, ly; ulong *x=(ulong *)gx; ulong *y=(ulong *)gy; if (!c) return; lx = lg(gx); ly = lg(gy); if (lx 1, gcd(c,d)=1. * Furthermore, d != d0 (mod N/c) with c,d0 already in the list */ l = lg(divN) - 1; /* c = 1 first */ gel(ret, ++curn) = mkvecsmall2(1,0); for (d = 2; d < N; d++) if (ugcd(d,N) != 1UL) gel(ret, ++curn) = mkvecsmall2(1,d); /* omit c = 1 (first) and c = N (last) */ for (i=2; i < l; i++) { ulong Novc, d0; c = divN[i]; Novc = N / c; for (d0 = 2; d0 <= Novc; d0++) { ulong k, d = d0; if (ugcd(d, Novc) == 1UL) continue; for (k = 0; k < c; k++, d += Novc) if (ugcd(c,d) == 1UL) { gel(ret, ++curn) = mkvecsmall2(c,d); break; } } } if (curn != num) pari_err_BUG("generatemsymbols [wrong number of symbols]"); return ret; } static GEN inithashmsymbols(ulong N, GEN symbols) { GEN H = zerovec(N); long k, l = lg(symbols); /* skip the (c:1), 0 <= c < N and (1:0) */ for (k=N+2; k < l; k++) { GEN s = gel(symbols, k); ulong c = s[1], d = s[2], Novc = N/c; if (gel(H,c) == gen_0) gel(H,c) = const_vecsmall(Novc+1,0); if (c != 1) { d %= Novc; if (!d) d = Novc; } mael(H, c, d) = k; } return H; } /** Helper functions for Sl2(Z) / Gamma_0(N) **/ /* M a 2x2 ZM in SL2(Z) */ GEN SL2_inv_shallow(GEN M) { GEN a = gcoeff(M,1,1), b = gcoeff(M,1,2); GEN c = gcoeff(M,2,1), d = gcoeff(M,2,2); retmkmat22(d,negi(b), negi(c),a); } /* SL2_inv(M)[2] */ static GEN SL2_inv2(GEN M) { GEN a = gcoeff(M,1,1), b = gcoeff(M,1,2); return mkcol2(negi(b),a); } /* M a 2x2 mat2 in SL2(Z) */ static GEN sl2_inv(GEN M) { long a=coeff(M,1,1), b=coeff(M,1,2), c=coeff(M,2,1), d=coeff(M,2,2); return mkvec2(mkvecsmall2(d, -c), mkvecsmall2(-b, a)); } /* Return the mat2 [a,b; c,d], not a zm to avoid GP problems */ static GEN mat2(long a, long b, long c, long d) { return mkvec2(mkvecsmall2(a,c), mkvecsmall2(b,d)); } static GEN mat2_to_ZM(GEN M) { GEN A = gel(M,1), B = gel(M,2); retmkmat2(mkcol2s(A[1],A[2]), mkcol2s(B[1],B[2])); } /* Input: a = 2-vector = path = {r/s,x/y} * Output: either [r,x;s,y] or [-r,x;-s,y], whichever has determinant > 0 */ static GEN path_to_ZM(GEN a) { GEN v = gel(a,1), w = gel(a,2); long r = v[1], s = v[2], x = w[1], y = w[2]; if (cmpii(mulss(r,y), mulss(x,s)) < 0) { r = -r; s = -s; } return mkmat22s(r,x,s,y); } static GEN path_to_zm(GEN a) { GEN v = gel(a,1), w = gel(a,2); long r = v[1], s = v[2], x = w[1], y = w[2]; if (cmpii(mulss(r,y), mulss(x,s)) < 0) { r = -r; s = -s; } return mat2(r,x,s,y); } /* path from c1 to c2 */ static GEN mkpath(GEN c1, GEN c2) { return mat2(c1[1], c2[1], c1[2], c2[2]); } static long cc(GEN M) { GEN v = gel(M,1); return v[2]; } static long dd(GEN M) { GEN v = gel(M,2); return v[2]; } /*Input: a,b = 2 paths, N = integer *Output: 1 if the a,b are \Gamma_0(N)-equivalent; 0 otherwise */ static int gamma_equiv(GEN a, GEN b, ulong N) { pari_sp av = avma; GEN m = path_to_zm(a); GEN n = path_to_zm(b); GEN d = subii(mulss(cc(m),dd(n)), mulss(dd(m),cc(n))); return gc_bool(av, umodiu(d, N) == 0); } /* Input: a,b = 2 paths that are \Gamma_0(N)-equivalent, N = integer * Output: M in \Gamma_0(N) such that Mb=a */ static GEN gamma_equiv_matrix(GEN a, GEN b) { GEN m = path_to_ZM(a); GEN n = path_to_ZM(b); return ZM_mul(m, SL2_inv_shallow(n)); } /*************/ /* P^1(Z/NZ) */ /*************/ /* a != 0 in Z/NZ. Return v in (Z/NZ)^* such that av = gcd(a, N) (mod N)*/ static ulong Fl_inverse(ulong a, ulong N) { ulong g; return Fl_invgen(a,N,&g); } /* Input: N = integer * Output: creates P^1(Z/NZ) = [symbols, H, N] * symbols: list of vectors [x,y] that give a set of representatives * of P^1(Z/NZ) * H: an M by M grid whose value at the r,c-th place is the index of the * "standard representative" equivalent to [r,c] occurring in the first * list. If gcd(r,c,N) > 1 the grid has value 0. */ static GEN create_p1mod(ulong N) { GEN fa = factoru(N), div = divisorsu_fact(fa); ulong i, nsym = count_Manin_symbols(N, gel(fa,1)); GEN symbols = generatemsymbols(N, nsym, div); GEN H = inithashmsymbols(N,symbols); GEN invsafe = cgetg(N, t_VECSMALL), inverse = cgetg(N, t_VECSMALL); for (i = 1; i < N; i++) { invsafe[i] = Fl_invsafe(i,N); inverse[i] = Fl_inverse(i,N); } return mkvecn(7, symbols, H, utoipos(N), fa, div, invsafe, inverse); } /* Let (c : d) in P1(Z/NZ). * If c = 0 return (0:1). If d = 0 return (1:0). * Else replace by (cu : du), where u in (Z/NZ)^* such that C := cu = gcd(c,N). * In create_p1mod(), (c : d) is represented by (C:D) where D = du (mod N/c) * is smallest such that gcd(C,D) = 1. Return (C : du mod N/c), which need * not belong to P1(Z/NZ) ! A second component du mod N/c = 0 is replaced by * N/c in this case to avoid problems with array indices */ static void p1_std_form(long *pc, long *pd, GEN p1N) { ulong N = p1N_get_N(p1N); ulong u; *pc = umodsu(*pc, N); if (!*pc) { *pd = 1; return; } *pd = umodsu(*pd, N); if (!*pd) { *pc = 1; return; } u = p1N_get_invsafe(p1N)[*pd]; if (u) { *pc = Fl_mul(*pc,u,N); *pd = 1; return; } /* (d,N) = 1 */ u = p1N_get_inverse(p1N)[*pc]; if (u > 1) { *pc = Fl_mul(*pc,u,N); *pd = Fl_mul(*pd,u,N); } /* c | N */ if (*pc != 1) *pd %= (N / *pc); if (!*pd) *pd = N / *pc; } /* Input: v = [x,y] = elt of P^1(Z/NZ) = class in Gamma_0(N) \ PSL2(Z) * Output: returns the index of the standard rep equivalent to v */ static long p1_index(long x, long y, GEN p1N) { ulong N = p1N_get_N(p1N); GEN H = p1N_get_hash(p1N); p1_std_form(&x, &y, p1N); if (y == 1) return x+1; if (y == 0) return N+1; if (mael(H,x,y) == 0) pari_err_BUG("p1_index"); return mael(H,x,y); } /* Cusps for \Gamma_0(N) */ /* \sum_{d | N} \phi(gcd(d, N/d)), using multiplicativity. fa = factor(N) */ ulong mfnumcuspsu_fact(GEN fa) { GEN P = gel(fa,1), E = gel(fa,2); long i, l = lg(P); ulong T = 1; for (i = 1; i < l; i++) { long e = E[i], e2 = e >> 1; /* floor(E[i] / 2) */ ulong p = P[i]; if (odd(e)) T *= 2 * upowuu(p, e2); else T *= (p+1) * upowuu(p, e2-1); } return T; } ulong mfnumcuspsu(ulong n) { pari_sp av = avma; return gc_ulong(av, mfnumcuspsu_fact( factoru(n) )); } /* \sum_{d | N} \phi(gcd(d, N/d)), using multiplicativity. fa = factor(N) */ GEN mfnumcusps_fact(GEN fa) { GEN P = gel(fa,1), E = gel(fa,2), T = gen_1; long i, l = lg(P); for (i = 1; i < l; i++) { GEN p = gel(P,i), c; long e = itos(gel(E,i)), e2 = e >> 1; /* floor(E[i] / 2) */ if (odd(e)) c = shifti(powiu(p, e2), 1); else c = mulii(addiu(p,1), powiu(p, e2-1)); T = T? mulii(T, c): c; } return T? T: gen_1; } GEN mfnumcusps(GEN n) { pari_sp av = avma; GEN F = check_arith_pos(n,"mfnumcusps"); if (!F) { if (lgefint(n) == 3) return utoi( mfnumcuspsu(n[2]) ); F = absZ_factor(n); } return gerepileuptoint(av, mfnumcusps_fact(F)); } /* to each cusp in \Gamma_0(N) P1(Q), represented by p/q, we associate a * unique index. Canonical representative: (1:0) or (p:q) with q | N, q < N, * p defined modulo d := gcd(N/q,q), (p,d) = 1. * Return [[N, nbcusps], H, cusps]*/ static GEN inithashcusps(GEN p1N) { ulong N = p1N_get_N(p1N); GEN div = p1N_get_div(p1N), H = zerovec(N+1); long k, ind, l = lg(div), ncusp = mfnumcuspsu_fact(p1N_get_fa(p1N)); GEN cusps = cgetg(ncusp+1, t_VEC); gel(H,1) = mkvecsmall2(0/*empty*/, 1/* first cusp: (1:0) */); gel(cusps, 1) = mkvecsmall2(1,0); ind = 2; for (k=1; k < l-1; k++) /* l-1: remove q = N */ { ulong p, q = div[k], d = ugcd(q, N/q); GEN h = const_vecsmall(d+1,0); gel(H,q+1) = h ; for (p = 0; p < d; p++) if (ugcd(p,d) == 1) { h[p+1] = ind; gel(cusps, ind) = mkvecsmall2(p,q); ind++; } } return mkvec3(mkvecsmall2(N,ind-1), H, cusps); } /* c = [p,q], (p,q) = 1, return a canonical representative for * \Gamma_0(N)(p/q) */ static GEN cusp_std_form(GEN c, GEN S) { long p, N = gel(S,1)[1], q = umodsu(c[2], N); ulong u, d; if (q == 0) return mkvecsmall2(1, 0); p = umodsu(c[1], N); u = Fl_inverse(q, N); q = Fl_mul(q,u, N); d = ugcd(q, N/q); return mkvecsmall2(Fl_div(p % d,u % d, d), q); } /* c = [p,q], (p,q) = 1, return the index of the corresponding cusp. * S from inithashcusps */ static ulong cusp_index(GEN c, GEN S) { long p, q; GEN H = gel(S,2); c = cusp_std_form(c, S); p = c[1]; q = c[2]; if (!mael(H,q+1,p+1)) pari_err_BUG("cusp_index"); return mael(H,q+1,p+1); } /* M a square invertible ZM, return a ZM iM such that iM M = M iM = d.Id */ static GEN ZM_inv_denom(GEN M) { GEN diM, iM = ZM_inv(M, &diM); return mkvec2(iM, diM); } /* return M^(-1) v, dinv = ZM_inv_denom(M) OR Qevproj_init(M) */ static GEN ZC_apply_dinv(GEN dinv, GEN v) { GEN x, c, iM; if (lg(dinv) == 3) { iM = gel(dinv,1); c = gel(dinv,2); } else { /* Qevproj_init */ iM = gel(dinv,2); c = gel(dinv,3); v = typ(v) == t_MAT? rowpermute(v, gel(dinv,4)) : vecpermute(v, gel(dinv,4)); } x = RgM_RgC_mul(iM, v); if (!isint1(c)) x = RgC_Rg_div(x, c); return x; } /* M an n x d ZM of rank d (basis of a Q-subspace), n >= d. * Initialize a projector on M */ GEN Qevproj_init(GEN M) { GEN v, perm, MM, iM, diM; v = ZM_indexrank(M); perm = gel(v,1); MM = rowpermute(M, perm); /* square invertible */ iM = ZM_inv(MM, &diM); return mkvec4(M, iM, diM, perm); } /* same with typechecks */ static GEN Qevproj_init0(GEN M) { switch(typ(M)) { case t_VEC: if (lg(M) == 5) return M; break; case t_COL: M = mkmat(M);/*fall through*/ case t_MAT: M = Q_primpart(M); RgM_check_ZM(M,"Qevproj_init"); return Qevproj_init(M); } pari_err_TYPE("Qevproj_init",M); return NULL;/*LCOV_EXCL_LINE*/ } /* T an n x n QM, pro = Qevproj_init(M), pro2 = Qevproj_init(M2); TM \subset M2. * Express these column vectors on M2's basis */ static GEN Qevproj_apply2(GEN T, GEN pro, GEN pro2) { GEN M = gel(pro,1), iM = gel(pro2,2), ciM = gel(pro2,3), perm = gel(pro2,4); return RgM_Rg_div(RgM_mul(iM, RgM_mul(rowpermute(T,perm), M)), ciM); } /* T an n x n QM, stabilizing d-dimensional Q-vector space spanned by the * d columns of M, pro = Qevproj_init(M). Return dxd matrix of T acting on M */ GEN Qevproj_apply(GEN T, GEN pro) { return Qevproj_apply2(T, pro, pro); } /* Qevproj_apply(T,pro)[,k] */ GEN Qevproj_apply_vecei(GEN T, GEN pro, long k) { GEN M = gel(pro,1), iM = gel(pro,2), ciM = gel(pro,3), perm = gel(pro,4); GEN v = RgM_RgC_mul(iM, RgM_RgC_mul(rowpermute(T,perm), gel(M,k))); return RgC_Rg_div(v, ciM); } static int cmp_dim(void *E, GEN a, GEN b) { long k; (void)E; a = gel(a,1); b = gel(b,1); k = lg(a)-lg(b); return k? ((k > 0)? 1: -1): 0; } /* FIXME: could use ZX_roots for deglim = 1 */ static GEN ZX_factor_limit(GEN T, long deglim, long *pl) { GEN fa = ZX_factor(T), P, E; long i, l; P = gel(fa,1); *pl = l = lg(P); if (deglim <= 0) return fa; E = gel(fa,2); for (i = 1; i < l; i++) if (degpol(gel(P,i)) > deglim) break; setlg(P,i); setlg(E,i); return fa; } /* Decompose the subspace H (Qevproj format) in simple subspaces. * Eg for H = msnew */ static GEN mssplit_i(GEN W, GEN H, long deglim) { ulong p, N = ms_get_N(W); long first, dim; forprime_t S; GEN T1 = NULL, T2 = NULL, V; dim = lg(gel(H,1))-1; V = vectrunc_init(dim+1); if (!dim) return V; (void)u_forprime_init(&S, 2, ULONG_MAX); vectrunc_append(V, H); first = 1; /* V[1..first-1] contains simple subspaces */ while ((p = u_forprime_next(&S))) { GEN T; long j, lV; if (N % p == 0) continue; if (T1 && T2) { T = RgM_add(T1,T2); T2 = NULL; } else { T2 = T1; T1 = T = mshecke(W, p, NULL); } lV = lg(V); for (j = first; j < lV; j++) { pari_sp av = avma; long lP; GEN Vj = gel(V,j), P = gel(Vj,1); GEN TVj = Qevproj_apply(T, Vj); /* c T | V_j */ GEN ch = QM_charpoly_ZX(TVj), fa = ZX_factor_limit(ch,deglim, &lP); GEN F = gel(fa, 1), E = gel(fa, 2); long k, lF = lg(F); if (lF == 2 && lP == 2) { if (equali1(gel(E,1))) { /* simple subspace */ swap(gel(V,first), gel(V,j)); first++; } else set_avma(av); } else if (lF == 1) /* discard V[j] */ { swap(gel(V,j), gel(V,lg(V)-1)); setlg(V, lg(V)-1); } else { /* can split Vj */ GEN pows; long D = 1; for (k = 1; k < lF; k++) { long d = degpol(gel(F,k)); if (d > D) D = d; } /* remove V[j] */ gel(V,j) = gel(V,lg(V)-1); setlg(V, lg(V)-1); pows = RgM_powers(TVj, minss((long)2*sqrt((double)D), D)); for (k = 1; k < lF; k++) { GEN f = gel(F,k); GEN K = QM_ker( RgX_RgMV_eval(f, pows)) ; /* Ker f(TVj) */ GEN p = vec_Q_primpart( RgM_mul(P, K) ); vectrunc_append(V, Qevproj_init(p)); if (lg(K) == 2 || isint1(gel(E,k))) { /* simple subspace */ swap(gel(V,first), gel(V, lg(V)-1)); first++; } } if (j < first) j = first; } } if (first >= lg(V)) { gen_sort_inplace(V, NULL, cmp_dim, NULL); return V; } } pari_err_BUG("subspaces not found"); return NULL;/*LCOV_EXCL_LINE*/ } GEN mssplit(GEN W, GEN H, long deglim) { pari_sp av = avma; checkms(W); if (!msk_get_sign(W)) pari_err_DOMAIN("mssplit","abs(sign)","!=",gen_1,gen_0); if (!H) H = msnew(W); H = Qevproj_init0(H); return gerepilecopy(av, mssplit_i(W,H,deglim)); } /* proV = Qevproj_init of a Hecke simple subspace, return [ a_n, n <= B ] */ static GEN msqexpansion_i(GEN W, GEN proV, ulong B) { ulong p, N = ms_get_N(W), sqrtB; long i, d, k = msk_get_weight(W); forprime_t S; GEN T1=NULL, T2=NULL, TV=NULL, ch=NULL, v, dTiv, Tiv, diM, iM, L; switch(B) { case 0: return cgetg(1,t_VEC); case 1: return mkvec(gen_1); } (void)u_forprime_init(&S, 2, ULONG_MAX); while ((p = u_forprime_next(&S))) { GEN T; if (N % p == 0) continue; if (T1 && T2) { T = RgM_add(T1,T2); T2 = NULL; } else { T2 = T1; T1 = T = mshecke(W, p, NULL); } TV = Qevproj_apply(T, proV); /* T | V */ ch = QM_charpoly_ZX(TV); if (ZX_is_irred(ch)) break; ch = NULL; } if (!ch) pari_err_BUG("q-Expansion not found"); /* T generates the Hecke algebra (acting on V) */ d = degpol(ch); v = vec_ei(d, 1); /* take v = e_1 */ Tiv = cgetg(d+1, t_MAT); /* Tiv[i] = T^(i-1)v */ gel(Tiv, 1) = v; for (i = 2; i <= d; i++) gel(Tiv, i) = RgM_RgC_mul(TV, gel(Tiv,i-1)); Tiv = Q_remove_denom(Tiv, &dTiv); iM = ZM_inv(Tiv, &diM); if (dTiv) diM = gdiv(diM, dTiv); L = const_vec(B,NULL); sqrtB = usqrt(B); gel(L,1) = d > 1? mkpolmod(gen_1,ch): gen_1; for (p = 2; p <= B; p++) { pari_sp av = avma; GEN T, u, Tv, ap, P; ulong m; if (gel(L,p)) continue; /* p not prime */ T = mshecke(W, p, NULL); Tv = Qevproj_apply_vecei(T, proV, 1); /* Tp.v */ /* Write Tp.v = \sum u_i T^i v */ u = RgC_Rg_div(RgM_RgC_mul(iM, Tv), diM); ap = gerepilecopy(av, RgV_to_RgX(u, 0)); if (d > 1) ap = mkpolmod(ap,ch); else ap = simplify_shallow(ap); gel(L,p) = ap; if (!(N % p)) { /* p divides the level */ ulong C = B/p; for (m=1; m<=C; m++) if (gel(L,m)) gel(L,m*p) = gmul(gel(L,m), ap); continue; } P = powuu(p,k-1); if (p <= sqrtB) { ulong pj, oldpj = 1; for (pj = p; pj <= B; oldpj=pj, pj *= p) { GEN apj = (pj==p)? ap : gsub(gmul(ap,gel(L,oldpj)), gmul(P,gel(L,oldpj/p))); gel(L,pj) = apj; for (m = B/pj; m > 1; m--) if (gel(L,m) && m%p) gel(L,m*pj) = gmul(gel(L,m), apj); } } else { gel(L,p) = ap; for (m = B/p; m > 1; m--) if (gel(L,m)) gel(L,m*p) = gmul(gel(L,m), ap); } } return L; } GEN msqexpansion(GEN W, GEN proV, ulong B) { pari_sp av = avma; checkms(W); proV = Qevproj_init0(proV); return gerepilecopy(av, msqexpansion_i(W,proV,B)); } static GEN Qevproj_apply0(GEN T, GEN pro) { GEN iM = gel(pro,2), perm = gel(pro,4); return vec_Q_primpart(ZM_mul(iM, rowpermute(T,perm))); } /* T a ZC or ZM */ GEN Qevproj_down(GEN T, GEN pro) { GEN iM = gel(pro,2), ciM = gel(pro,3), perm = gel(pro,4); if (typ(T) == t_COL) return RgC_Rg_div(ZM_ZC_mul(iM, vecpermute(T,perm)), ciM); else return RgM_Rg_div(ZM_mul(iM, rowpermute(T,perm)), ciM); } static GEN Qevproj_star(GEN W, GEN H) { long s = msk_get_sign(W); if (s) { /* project on +/- component */ GEN A = RgM_mul(msk_get_star(W), H); A = (s > 0)? gadd(A, H): gsub(A, H); /* Im(star + sign) = Ker(star - sign) */ H = QM_image_shallow(A); H = Qevproj_apply0(H, msk_get_starproj(W)); } return H; } static GEN Tp_matrices(ulong p) { GEN v = cgetg(p+2, t_VEC); ulong i; for (i = 1; i <= p; i++) gel(v,i) = mat2(1, i-1, 0, p); gel(v,i) = mat2(p, 0, 0, 1); return v; } static GEN Up_matrices(ulong p) { GEN v = cgetg(p+1, t_VEC); ulong i; for (i = 1; i <= p; i++) gel(v,i) = mat2(1, i-1, 0, p); return v; } /* M = N/p. Classes of Gamma_0(M) / Gamma_O(N) when p | M */ static GEN NP_matrices(ulong M, ulong p) { GEN v = cgetg(p+1, t_VEC); ulong i; for (i = 1; i <= p; i++) gel(v,i) = mat2(1, 0, (i-1)*M, 1); return v; } /* M = N/p. Extra class of Gamma_0(M) / Gamma_O(N) when p \nmid M */ static GEN NP_matrix_extra(ulong M, ulong p) { long w,z, d = cbezout(p, -M, &w, &z); if (d != 1) return NULL; return mat2(w,z,M,p); } static GEN WQ_matrix(long N, long Q) { long w,z, d = cbezout(Q, N/Q, &w, &z); if (d != 1) return NULL; return mat2(Q,1,-N*z,Q*w); } GEN msnew(GEN W) { pari_sp av = avma; GEN S = mscuspidal(W, 0); ulong N = ms_get_N(W); long s = msk_get_sign(W), k = msk_get_weight(W); if (N > 1 && (!uisprime(N) || (k == 12 || k > 14))) { GEN p1N = ms_get_p1N(W), P = gel(p1N_get_fa(p1N), 1); long i, nP = lg(P)-1; GEN v = cgetg(2*nP + 1, t_COL); S = gel(S,1); /* Q basis */ for (i = 1; i <= nP; i++) { pari_sp av = avma, av2; long M = N/P[i]; GEN T1,Td, Wi = mskinit(M, k, s); GEN v1 = NP_matrices(M, P[i]); GEN vd = Up_matrices(P[i]); /* p^2 \nmid N */ if (M % P[i]) { v1 = vec_append(v1, NP_matrix_extra(M,P[i])); vd = vec_append(vd, WQ_matrix(N,P[i])); } T1 = getMorphism(W, Wi, v1); Td = getMorphism(W, Wi, vd); if (s) { T1 = Qevproj_apply2(T1, msk_get_starproj(W), msk_get_starproj(Wi)); Td = Qevproj_apply2(Td, msk_get_starproj(W), msk_get_starproj(Wi)); } av2 = avma; T1 = RgM_mul(T1,S); Td = RgM_mul(Td,S); /* multiply by S = restrict to mscusp */ gerepileallsp(av, av2, 2, &T1, &Td); gel(v,2*i-1) = T1; gel(v,2*i) = Td; } S = ZM_mul(S, QM_ker(matconcat(v))); /* Snew */ S = Qevproj_init(vec_Q_primpart(S)); } return gerepilecopy(av, S); } /* Solve the Manin relations for a congruence subgroup \Gamma by constructing * a well-formed fundamental domain for the action of \Gamma on upper half * space. See * Pollack and Stevens, Overconvergent modular symbols and p-adic L-functions * Annales scientifiques de l'ENS 44, fascicule 1 (2011), 1-42 * http://math.bu.edu/people/rpollack/Papers/Overconvergent_modular_symbols_and_padic_Lfunctions.pdf * * FIXME: Implemented for \Gamma = \Gamma_0(N) only. */ /* linked lists */ typedef struct list_t { GEN data; struct list_t *next; } list_t; static list_t * list_new(GEN x) { list_t *L = (list_t*)stack_malloc(sizeof(list_t)); L->data = x; L->next = NULL; return L; } static void list_insert(list_t *L, GEN x) { list_t *l = list_new(x); l->next = L->next; L->next = l; } /*Input: N > 1, p1N = P^1(Z/NZ) *Output: a connected fundamental domain for the action of \Gamma_0(N) on * upper half space. When \Gamma_0(N) is torsion free, the domain has the * property that all of its vertices are cusps. When \Gamma_0(N) has * three-torsion, 2 extra triangles need to be added. * * The domain is constructed by beginning with the triangle with vertices 0,1 * and oo. Each adjacent triangle is successively tested to see if it contains * points not \Gamma_0(N) equivalent to some point in our region. If a * triangle contains new points, it is added to the region. This process is * continued until the region can no longer be extended (and still be a * fundamental domain) by added an adjacent triangle. The list of cusps * between 0 and 1 are then returned * * Precisely, the function returns a list such that the elements of the list * with odd index are the cusps in increasing order. The even elements of the * list are either an "x" or a "t". A "t" represents that there is an element * of order three such that its fixed point is in the triangle directly * adjacent to the our region with vertices given by the cusp before and after * the "t". The "x" represents that this is not the case. */ enum { type_X, type_DO /* ? */, type_T }; static GEN form_list_of_cusps(ulong N, GEN p1N) { pari_sp av = avma; long i, position, nbC = 2; GEN v, L; list_t *C, *c; /* Let t be the index of a class in PSL2(Z) / \Gamma in our fixed enumeration * v[t] != 0 iff it is the class of z tau^r for z a previous alpha_i * or beta_i. * For \Gamma = \Gamma_0(N), the enumeration is given by p1_index. * We write cl(gamma) = the class of gamma mod \Gamma */ v = const_vecsmall(p1_size(p1N), 0); i = p1_index( 0, 1, p1N); v[i] = 1; i = p1_index( 1,-1, p1N); v[i] = 2; i = p1_index(-1, 0, p1N); v[i] = 3; /* the value is unused [debugging]: what matters is whether it is != 0 */ position = 4; /* at this point, Fund = R, v contains the classes of Id, tau, tau^2 */ C = list_new(mkvecsmall3(0,1, type_X)); list_insert(C, mkvecsmall3(1,1,type_DO)); /* C is a list of triples[a,b,t], where c = a/b is a cusp, and t is the type * of the path between c and the PREVIOUS cusp in the list, coded as * type_DO = "?", type_X = "x", type_T = "t" * Initially, C = [0/1,"?",1/1]; */ /* loop through the current set of cusps C and check to see if more cusps * should be added */ for (;;) { int done = 1; for (c = C; c; c = c->next) { GEN cusp1, cusp2, gam; long pos, b1, b2, b; if (!c->next) break; cusp1 = c->data; /* = a1/b1 */ cusp2 = (c->next)->data; /* = a2/b2 */ if (cusp2[3] != type_DO) continue; /* gam (oo -> 0) = (cusp2 -> cusp1), gam in PSL2(Z) */ gam = path_to_zm(mkpath(cusp2, cusp1)); /* = [a2,a1;b2,b1] */ /* we have normalized the cusp representation so that a1 b2 - a2 b1 = 1 */ b1 = coeff(gam,2,1); b2 = coeff(gam,2,2); /* gam.1 = (a1 + a2) / (b1 + b2) */ b = b1 + b2; /* Determine whether the adjacent triangle *below* (cusp1->cusp2) * should be added */ pos = p1_index(b1,b2, p1N); /* did we see cl(gam) before ? */ if (v[pos]) cusp2[3] = type_X; /* NO */ else { /* YES */ ulong B1, B2; v[pos] = position; i = p1_index(-(b1+b2), b1, p1N); v[i] = position+1; i = p1_index(b2, -(b1+b2), p1N); v[i] = position+2; /* add cl(gam), cl(gam*TAU), cl(gam*TAU^2) to v */ position += 3; /* gam tau gam^(-1) in \Gamma ? */ B1 = umodsu(b1, N); B2 = umodsu(b2, N); if ((Fl_sqr(B2,N) + Fl_sqr(B1,N) + Fl_mul(B1,B2,N)) % N == 0) cusp2[3] = type_T; else { long a1 = coeff(gam, 1,1), a2 = coeff(gam, 1,2); long a = a1 + a2; /* gcd(a,b) = 1 */ list_insert(c, mkvecsmall3(a,b,type_DO)); c = c->next; nbC++; done = 0; } } } if (done) break; } L = cgetg(nbC+1, t_VEC); i = 1; for (c = C; c; c = c->next) gel(L,i++) = c->data; return gerepilecopy(av, L); } /* W an msN. M in PSL2(Z). Return index of M in P1^(Z/NZ) = Gamma0(N) \ PSL2(Z), * and M0 in Gamma_0(N) such that M = M0 * M', where M' = chosen * section( PSL2(Z) -> P1^(Z/NZ) ). */ static GEN Gamma0N_decompose(GEN W, GEN M, long *index) { GEN p1N = msN_get_p1N(W), W3 = gel(W,3), section = msN_get_section(W); GEN A; ulong N = p1N_get_N(p1N); ulong c = umodiu(gcoeff(M,2,1), N); ulong d = umodiu(gcoeff(M,2,2), N); long s, ind = p1_index(c, d, p1N); /* as an elt of P1(Z/NZ) */ *index = W3[ind]; /* as an elt of F, E2, ... */ M = ZM_zm_mul(M, sl2_inv(gel(section,ind))); /* normalize mod +/-Id */ A = gcoeff(M,1,1); s = signe(A); if (s < 0) M = ZM_neg(M); else if (!s) { GEN C = gcoeff(M,2,1); if (signe(C) < 0) M = ZM_neg(M); } return M; } /* W an msN; as above for a path. Return [[ind], M] */ static GEN path_Gamma0N_decompose(GEN W, GEN path) { GEN p1N = msN_get_p1N(W); GEN p1index_to_ind = gel(W,3); GEN section = msN_get_section(W); GEN M = path_to_zm(path); long p1index = p1_index(cc(M), dd(M), p1N); long ind = p1index_to_ind[p1index]; GEN M0 = ZM_zm_mul(mat2_to_ZM(M), sl2_inv(gel(section,p1index))); return mkvec2(mkvecsmall(ind), M0); } /*Form generators of H_1(X_0(N),{cusps},Z) * *Input: N = integer > 1, p1N = P^1(Z/NZ) *Output: [cusp_list,E,F,T2,T3,E1] where * cusps_list = list of cusps describing fundamental domain of * \Gamma_0(N). * E = list of paths in the boundary of the fundamental domains and oriented * clockwise such that they do not contain a point * fixed by an element of order 2 and they are not an edge of a * triangle containing a fixed point of an element of order 3 * F = list of paths in the interior of the domain with each * orientation appearing separately * T2 = list of paths in the boundary of domain containing a point fixed * by an element of order 2 (oriented clockwise) * T3 = list of paths in the boundard of domain which are the edges of * some triangle containing a fixed point of a matrix of order 3 (both * orientations appear) * E1 = a sublist of E such that every path in E is \Gamma_0(N)-equivalent to * either an element of E1 or the flip (reversed orientation) of an element * of E1. * (Elements of T2 are \Gamma_0(N)-equivalent to their own flip.) * * sec = a list from 1..#p1N of matrices describing a section of the map * SL_2(Z) to P^1(Z/NZ) given by [a,b;c,d]-->[c,d]. * Given our fixed enumeration of P^1(Z/NZ), the j-th element of the list * represents the image of the j-th element of P^1(Z/NZ) under the section. */ /* insert path in set T */ static void set_insert(hashtable *T, GEN path) { hash_insert(T, path, (void*)(T->nb + 1)); } static GEN hash_to_vec(hashtable *h) { GEN v = cgetg(h->nb + 1, t_VEC); ulong i; for (i = 0; i < h->len; i++) { hashentry *e = h->table[i]; while (e) { GEN key = (GEN)e->key; long index = (long)e->val; gel(v, index) = key; e = e->next; } } return v; } static long path_to_p1_index(GEN path, GEN p1N) { GEN M = path_to_zm(path); return p1_index(cc(M), dd(M), p1N); } /* Pollack-Stevens sets */ typedef struct PS_sets_t { hashtable *F, *T2, *T31, *T32, *E1, *E2; GEN E2fromE1, stdE1; } PS_sets_t; static hashtable * set_init(long max) { return hash_create(max, (ulong(*)(void*))&hash_GEN, (int(*)(void*,void*))&gidentical, 1); } /* T = E2fromE1[i] = [c, gamma] */ static ulong E2fromE1_c(GEN T) { return itou(gel(T,1)); } static GEN E2fromE1_Zgamma(GEN T) { return gel(T,2); } static GEN E2fromE1_gamma(GEN T) { return gcoeff(gel(T,2),1,1); } static void insert_E(GEN path, PS_sets_t *S, GEN p1N) { GEN rev = vecreverse(path); long std = path_to_p1_index(rev, p1N); GEN v = gel(S->stdE1, std); if (v) { /* [s, p1], where E1[s] is the path p1 = vecreverse(path) mod \Gamma */ GEN gamma, p1 = gel(v,2); long r, s = itou(gel(v,1)); set_insert(S->E2, path); r = S->E2->nb; if (gel(S->E2fromE1, r) != gen_0) pari_err_BUG("insert_E"); gamma = gamma_equiv_matrix(rev, p1); /* reverse(E2[r]) = gamma * E1[s] */ gel(S->E2fromE1, r) = mkvec2(utoipos(s), to_famat_shallow(gamma,gen_m1)); } else { set_insert(S->E1, path); std = path_to_p1_index(path, p1N); gel(S->stdE1, std) = mkvec2(utoipos(S->E1->nb), path); } } static GEN cusp_infinity(void) { return mkvecsmall2(1,0); } static void form_E_F_T(ulong N, GEN p1N, GEN *pC, PS_sets_t *S) { GEN C, cusp_list = form_list_of_cusps(N, p1N); long nbgen = lg(cusp_list)-1, nbmanin = p1_size(p1N), r, s, i; hashtable *F, *T2, *T31, *T32, *E1, *E2; *pC = C = cgetg(nbgen+1, t_VEC); for (i = 1; i <= nbgen; i++) { GEN c = gel(cusp_list,i); gel(C,i) = mkvecsmall2(c[1], c[2]); } S->F = F = set_init(nbmanin); S->E1 = E1 = set_init(nbgen); S->E2 = E2 = set_init(nbgen); S->T2 = T2 = set_init(nbgen); S->T31 = T31 = set_init(nbgen); S->T32 = T32 = set_init(nbgen); /* T31 represents the three torsion paths going from left to right */ /* T32 represents the three torsion paths going from right to left */ for (r = 1; r < nbgen; r++) { GEN c2 = gel(cusp_list,r+1); if (c2[3] == type_T) { GEN c1 = gel(cusp_list,r), path = mkpath(c1,c2), path2 = vecreverse(path); set_insert(T31, path); set_insert(T32, path2); } } /* to record relations between E2 and E1 */ S->E2fromE1 = zerovec(nbgen); S->stdE1 = const_vec(nbmanin, NULL); /* Assumption later: path [oo,0] is E1[1], path [1,oo] is E2[1] */ { GEN oo = cusp_infinity(); GEN p1 = mkpath(oo, mkvecsmall2(0,1)); /* [oo, 0] */ GEN p2 = mkpath(mkvecsmall2(1,1), oo); /* [1, oo] */ insert_E(p1, S, p1N); insert_E(p2, S, p1N); } for (r = 1; r < nbgen; r++) { GEN c1 = gel(cusp_list,r); for (s = r+1; s <= nbgen; s++) { pari_sp av = avma; GEN c2 = gel(cusp_list,s), path; GEN d = subii(mulss(c1[1],c2[2]), mulss(c1[2],c2[1])); set_avma(av); if (!is_pm1(d)) continue; path = mkpath(c1,c2); if (r+1 == s) { GEN w = path; ulong hash = T31->hash(w); /* T31, T32 use the same hash function */ if (!hash_search2(T31, w, hash) && !hash_search2(T32, w, hash)) { if (gamma_equiv(path, vecreverse(path), N)) set_insert(T2, path); else insert_E(path, S, p1N); } } else { set_insert(F, mkvec2(path, mkvecsmall2(r,s))); set_insert(F, mkvec2(vecreverse(path), mkvecsmall2(s,r))); } } } setlg(S->E2fromE1, E2->nb+1); } /* v = \sum n_i g_i, g_i in Sl(2,Z), return \sum n_i g_i^(-1) */ static GEN ZSl2_star(GEN v) { long i, l; GEN w, G; if (typ(v) == t_INT) return v; G = gel(v,1); w = cgetg_copy(G, &l); for (i = 1; i < l; i++) { GEN g = gel(G,i); if (typ(g) == t_MAT) g = SL2_inv_shallow(g); gel(w,i) = g; } return ZG_normalize(mkmat2(w, gel(v,2))); } /* Input: h = set of unimodular paths, p1N = P^1(Z/NZ) = Gamma_0(N)\PSL2(Z) * Output: Each path is converted to a matrix and then an element of P^1(Z/NZ) * Append the matrix to W[12], append the index that represents * these elements of P^1 (the classes mod Gamma_0(N) via our fixed * enumeration to W[2]. */ static void paths_decompose(GEN W, hashtable *h, int flag) { GEN p1N = ms_get_p1N(W), section = ms_get_section(W); GEN v = hash_to_vec(h); long i, l = lg(v); for (i = 1; i < l; i++) { GEN e = gel(v,i); GEN M = path_to_zm(flag? gel(e,1): e); long index = p1_index(cc(M), dd(M), p1N); vecsmalltrunc_append(gel(W,2), index); gel(section, index) = M; } } static void fill_W2_W12(GEN W, PS_sets_t *S) { GEN p1N = msN_get_p1N(W); long n = p1_size(p1N); gel(W, 2) = vecsmalltrunc_init(n+1); gel(W,12) = cgetg(n+1, t_VEC); /* F contains [path, [index cusp1, index cusp2]]. Others contain paths only */ paths_decompose(W, S->F, 1); paths_decompose(W, S->E2, 0); paths_decompose(W, S->T32, 0); paths_decompose(W, S->E1, 0); paths_decompose(W, S->T2, 0); paths_decompose(W, S->T31, 0); } /* x t_VECSMALL, corresponds to a map x(i) = j, where 1 <= j <= max for all i * Return y s.t. y[j] = i or 0 (not in image) */ static GEN reverse_list(GEN x, long max) { GEN y = const_vecsmall(max, 0); long r, lx = lg(x); for (r = 1; r < lx; r++) y[ x[r] ] = r; return y; } /* go from C[a] to C[b]; return the indices of paths * E.g. if a < b * (C[a]->C[a+1], C[a+1]->C[a+2], ... C[b-1]->C[b]) * (else reverse direction) * = b - a paths */ static GEN F_indices(GEN W, long a, long b) { GEN v = cgetg(labs(b-a) + 1, t_VEC); long s, k = 1; if (a < b) { GEN index_forward = gel(W,13); for (s = a; s < b; s++) gel(v,k++) = gel(index_forward,s); } else { GEN index_backward = gel(W,14); for (s = a; s > b; s--) gel(v,k++) = gel(index_backward,s); } return v; } /* go from C[a] to C[b] via oo; return the indices of paths * E.g. if a < b * (C[a]->C[a-1], ... C[2]->C[1], * C[1]->oo, oo-> C[end], * C[end]->C[end-1], ... C[b+1]->C[b]) * a-1 + 2 + end-(b+1)+1 = end - b + a + 1 paths */ static GEN F_indices_oo(GEN W, long end, long a, long b) { GEN index_oo = gel(W,15); GEN v = cgetg(end-labs(b-a)+1 + 1, t_VEC); long s, k = 1; if (a < b) { GEN index_backward = gel(W,14); for (s = a; s > 1; s--) gel(v,k++) = gel(index_backward,s); gel(v,k++) = gel(index_backward,1); /* C[1] -> oo */ gel(v,k++) = gel(index_oo,2); /* oo -> C[end] */ for (s = end; s > b; s--) gel(v,k++) = gel(index_backward,s); } else { GEN index_forward = gel(W,13); for (s = a; s < end; s++) gel(v,k++) = gel(index_forward,s); gel(v,k++) = gel(index_forward,end); /* C[end] -> oo */ gel(v,k++) = gel(index_oo,1); /* oo -> C[1] */ for (s = 1; s < b; s++) gel(v,k++) = gel(index_forward,s); } return v; } /* index of oo -> C[1], oo -> C[end] */ static GEN indices_oo(GEN W, GEN C) { long end = lg(C)-1; GEN w, v = cgetg(2+1, t_VEC), oo = cusp_infinity(); w = mkpath(oo, gel(C,1)); /* oo -> C[1]=0 */ gel(v,1) = path_Gamma0N_decompose(W, w); w = mkpath(oo, gel(C,end)); /* oo -> C[end]=1 */ gel(v,2) = path_Gamma0N_decompose(W, w); return v; } /* index of C[1]->C[2], C[2]->C[3], ... C[end-1]->C[end], C[end]->oo * Recall that C[1] = 0, C[end] = 1 */ static GEN indices_forward(GEN W, GEN C) { long s, k = 1, end = lg(C)-1; GEN v = cgetg(end+1, t_VEC); for (s = 1; s <= end; s++) { GEN w = mkpath(gel(C,s), s == end? cusp_infinity(): gel(C,s+1)); gel(v,k++) = path_Gamma0N_decompose(W, w); } return v; } /* index of C[1]->oo, C[2]->C[1], ... C[end]->C[end-1] */ static GEN indices_backward(GEN W, GEN C) { long s, k = 1, end = lg(C)-1; GEN v = cgetg(end+1, t_VEC); for (s = 1; s <= end; s++) { GEN w = mkpath(gel(C,s), s == 1? cusp_infinity(): gel(C,s-1)); gel(v,k++) = path_Gamma0N_decompose(W, w); } return v; } /*[0,-1;1,-1]*/ static GEN mkTAU() { retmkmat22(gen_0,gen_m1, gen_1,gen_m1); } /* S */ static GEN mkS() { retmkmat22(gen_0,gen_1, gen_m1,gen_0); } /* N = integer > 1. Returns data describing Delta_0 = Z[P^1(Q)]_0 seen as * a Gamma_0(N) - module. */ static GEN msinit_N(ulong N) { GEN p1N, C, vecF, vecT2, vecT31, TAU, W, W2, singlerel, annT2, annT31; GEN F_index; ulong r, s, width; long nball, nbgen, nbp1N; hashtable *F, *T2, *T31, *T32, *E1, *E2; PS_sets_t S; W = zerovec(16); gel(W,1) = p1N = create_p1mod(N); gel(W,16)= inithashcusps(p1N); TAU = mkTAU(); if (N == 1) { gel(W,5) = mkvecsmall(1); /* cheat because sets are not disjoint if N=1 */ gel(W,11) = mkvecsmall5(0, 0, 1, 1, 2); gel(W,12) = mkvec(mat2(1,0,0,1)); gel(W,8) = mkvec( mkmat22(gen_1,gen_1, mkS(),gen_1) ); gel(W,9) = mkvec( mkmat2(mkcol3(gen_1,TAU,ZM2_sqr(TAU)), mkcol3(gen_1,gen_1,gen_1)) ); return W; } nbp1N = p1_size(p1N); form_E_F_T(N,p1N, &C, &S); E1 = S.E1; E2 = S.E2; T31 = S.T31; T32 = S.T32; F = S.F; T2 = S.T2; nbgen = lg(C)-1; /* Put our paths in the order: F,E2,T32,E1,T2,T31 * W2[j] associates to the j-th element of this list its index in P1. */ fill_W2_W12(W, &S); W2 = gel(W, 2); nball = lg(W2)-1; gel(W,3) = reverse_list(W2, nbp1N); gel(W,5) = vecslice(gel(W,2), F->nb + E2->nb + T32->nb + 1, nball); gel(W,4) = reverse_list(gel(W,5), nbp1N); gel(W,13) = indices_forward(W, C); gel(W,14) = indices_backward(W, C); gel(W,15) = indices_oo(W, C); gel(W,11) = mkvecsmall5(F->nb, F->nb + E2->nb, F->nb + E2->nb + T32->nb, F->nb + E2->nb + T32->nb + E1->nb, F->nb + E2->nb + T32->nb + E1->nb + T2->nb); /* relations between T32 and T31 [not stored!] * T32[i] = - T31[i] */ /* relations of F */ width = E1->nb + T2->nb + T31->nb; /* F_index[r] = [index_1, ..., index_k], where index_i is the p1_index() * of the elementary unimodular path between 2 consecutive cusps * [in E1,E2,T2,T31 or T32] */ F_index = cgetg(F->nb+1, t_VEC); vecF = hash_to_vec(F); for (r = 1; r <= F->nb; r++) { GEN w = gel(gel(vecF,r), 2); long a = w[1], b = w[2], d = labs(b - a); /* c1 = cusp_list[a], c2 = cusp_list[b], ci != oo */ gel(F_index,r) = (nbgen-d >= d-1)? F_indices(W, a,b) : F_indices_oo(W, lg(C)-1,a,b); } singlerel = cgetg(width+1, t_VEC); /* form the single boundary relation */ for (s = 1; s <= E2->nb; s++) { /* reverse(E2[s]) = gamma * E1[c] */ GEN T = gel(S.E2fromE1,s), gamma = E2fromE1_gamma(T); gel(singlerel, E2fromE1_c(T)) = mkmat22(gen_1,gen_1, gamma,gen_m1); } for (r = E1->nb + 1; r <= width; r++) gel(singlerel, r) = gen_1; /* form the 2-torsion relations */ annT2 = cgetg(T2->nb+1, t_VEC); vecT2 = hash_to_vec(T2); for (r = 1; r <= T2->nb; r++) { GEN w = gel(vecT2,r); GEN gamma = gamma_equiv_matrix(vecreverse(w), w); gel(annT2, r) = mkmat22(gen_1,gen_1, gamma,gen_1); } /* form the 3-torsion relations */ annT31 = cgetg(T31->nb+1, t_VEC); vecT31 = hash_to_vec(T31); for (r = 1; r <= T31->nb; r++) { GEN M = path_to_ZM( vecreverse(gel(vecT31,r)) ); GEN gamma = ZM_mul(ZM_mul(M, TAU), SL2_inv_shallow(M)); gel(annT31, r) = mkmat2(mkcol3(gen_1,gamma,ZM2_sqr(gamma)), mkcol3(gen_1,gen_1,gen_1)); } gel(W,6) = F_index; gel(W,7) = S.E2fromE1; gel(W,8) = annT2; gel(W,9) = annT31; gel(W,10)= singlerel; return W; } static GEN cusp_to_P1Q(GEN c) { return c[2]? sstoQ(c[1], c[2]): mkoo(); } static GEN mspathgens_i(GEN W) { GEN R, r, g, section, gen, annT2, annT31; long i, l; checkms(W); W = get_msN(W); section = msN_get_section(W); gen = ms_get_genindex(W); l = lg(gen); g = cgetg(l,t_VEC); for (i = 1; i < l; i++) { GEN p = gel(section,gen[i]); gel(g,i) = mkvec2(cusp_to_P1Q(gel(p,1)), cusp_to_P1Q(gel(p,2))); } annT2 = msN_get_annT2(W); annT31= msN_get_annT31(W); if (ms_get_N(W) == 1) { R = cgetg(3, t_VEC); gel(R,1) = mkvec( mkvec2(gel(annT2,1), gen_1) ); gel(R,2) = mkvec( mkvec2(gel(annT31,1), gen_1) ); } else { GEN singlerel = msN_get_singlerel(W); long j, nbT2 = lg(annT2)-1, nbT31 = lg(annT31)-1, nbE1 = ms_get_nbE1(W); R = cgetg(nbT2+nbT31+2, t_VEC); l = lg(singlerel); r = cgetg(l, t_VEC); for (i = 1; i <= nbE1; i++) gel(r,i) = mkvec2(gel(singlerel, i), utoi(i)); for (; i < l; i++) gel(r,i) = mkvec2(gen_1, utoi(i)); gel(R,1) = r; j = 2; for (i = 1; i <= nbT2; i++,j++) gel(R,j) = mkvec( mkvec2(gel(annT2,i), utoi(i + nbE1)) ); for (i = 1; i <= nbT31; i++,j++) gel(R,j) = mkvec( mkvec2(gel(annT31,i), utoi(i + nbE1 + nbT2)) ); } return mkvec2(g,R); } GEN mspathgens(GEN W) { pari_sp av = avma; return gerepilecopy(av, mspathgens_i(W)); } /* Modular symbols in weight k: Hom_Gamma(Delta, Q[x,y]_{k-2}) */ /* A symbol phi is represented by the {phi(g_i)}, {phi(g'_i)}, {phi(g''_i)} * where the {g_i, g'_i, g''_i} are the Z[\Gamma]-generators of Delta, * g_i corresponds to E1, g'_i to T2, g''_i to T31. */ /* FIXME: export. T^1, ..., T^n */ static GEN RgX_powers(GEN T, long n) { GEN v = cgetg(n+1, t_VEC); long i; gel(v, 1) = T; for (i = 1; i < n; i++) gel(v,i+1) = RgX_mul(gel(v,i), T); return v; } /* g = [a,b;c,d] a mat2. Return (X^{k-2} | g)(X,Y)[X = 1]. */ static GEN voo_act_Gl2Q(GEN g, long k) { GEN mc = stoi(-coeff(g,2,1)), d = stoi(coeff(g,2,2)); return RgX_to_RgC(gpowgs(deg1pol_shallow(mc, d, 0), k-2), k-1); } struct m_act { long dim, k, p; GEN q; GEN(*act)(struct m_act *,GEN); }; /* g = [a,b;c,d]. Return (P | g)(X,Y)[X = 1] = P(dX - cY, -b X + aY)[X = 1], * for P = X^{k-2}, X^{k-3}Y, ..., Y^{k-2} */ GEN RgX_act_Gl2Q(GEN g, long k) { GEN a,b,c,d, V1,V2,V; long i; if (k == 2) return matid(1); a = gcoeff(g,1,1); b = gcoeff(g,1,2); c = gcoeff(g,2,1); d = gcoeff(g,2,2); V1 = RgX_powers(deg1pol_shallow(gneg(c), d, 0), k-2); /* d - c Y */ V2 = RgX_powers(deg1pol_shallow(a, gneg(b), 0), k-2); /*-b + a Y */ V = cgetg(k, t_MAT); gel(V,1) = RgX_to_RgC(gel(V1, k-2), k-1); for (i = 1; i < k-2; i++) { GEN v1 = gel(V1, k-2-i); /* (d-cY)^(k-2-i) */ GEN v2 = gel(V2, i); /* (-b+aY)^i */ gel(V,i+1) = RgX_to_RgC(RgX_mul(v1,v2), k-1); } gel(V,k-1) = RgX_to_RgC(gel(V2, k-2), k-1); return V; /* V[i+1] = X^i | g */ } /* z in Z[Gl2(Q)], return the matrix of z acting on V */ static GEN act_ZGl2Q(GEN z, struct m_act *T, hashtable *H) { GEN S = NULL, G, E; pari_sp av; long l, j; /* paranoia: should not occur */ if (typ(z) == t_INT) return scalarmat_shallow(z, T->dim); G = gel(z,1); l = lg(G); E = gel(z,2); av = avma; for (j = 1; j < l; j++) { GEN M, g = gel(G,j), n = gel(E,j); if (typ(g) == t_INT) /* = 1 */ M = n; /* n*Id_dim */ else { /*search in H succeeds because of preload*/ M = H? (GEN)hash_search(H,g)->val: T->act(T,g); if (is_pm1(n)) { if (signe(n) < 0) M = RgM_neg(M); } else M = RgM_Rg_mul(M, n); } if (!S) { S = M; continue; } S = gadd(S, M); if (gc_needed(av,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"act_ZGl2Q, j = %ld",j); S = gerepileupto(av, S); } } return gerepilecopy(av, S); } static GEN _RgX_act_Gl2Q(struct m_act *S, GEN z) { return RgX_act_Gl2Q(z, S->k); } /* acting on (X^{k-2},...,Y^{k-2}) */ GEN RgX_act_ZGl2Q(GEN z, long k) { struct m_act T; T.k = k; T.dim = k-1; T.act=&_RgX_act_Gl2Q; return act_ZGl2Q(z, &T, NULL); } /* First pass, identify matrices in Sl_2 to convert to operators; * insert operators in hashtable. This allows GC in act_ZGl2Q */ static void hash_preload(GEN M, struct m_act *S, hashtable *H) { if (typ(M) != t_INT) { ulong h = H->hash(M); hashentry *e = hash_search2(H, M, h); if (!e) hash_insert2(H, M, S->act(S,M), h); } } /* z a sparse operator */ static void hash_vecpreload(GEN z, struct m_act *S, hashtable *H) { GEN G = gel(z,1); long i, l = lg(G); for (i = 1; i < l; i++) hash_preload(gel(G,i), S, H); } static void ZGl2QC_preload(struct m_act *S, GEN v, hashtable *H) { GEN val = gel(v,2); long i, l = lg(val); for (i = 1; i < l; i++) hash_vecpreload(gel(val,i), S, H); } /* Given a sparse vector of elements in Z[G], convert it to a (sparse) vector * of operators on V (given by t_MAT) */ static void ZGl2QC_to_act(struct m_act *S, GEN v, hashtable *H) { GEN val = gel(v,2); long i, l = lg(val); for (i = 1; i < l; i++) gel(val,i) = act_ZGl2Q(gel(val,i), S, H); } /* For all V[i] in Z[\Gamma], find the P such that P . V[i]^* = 0; * write P in basis X^{k-2}, ..., Y^{k-2} */ static GEN ZGV_tors(GEN V, long k) { long i, l = lg(V); GEN v = cgetg(l, t_VEC); for (i = 1; i < l; i++) { GEN a = ZSl2_star(gel(V,i)); gel(v,i) = ZM_ker(RgX_act_ZGl2Q(a,k)); } return v; } static long set_from_index(GEN W11, long i) { if (i <= W11[1]) return 1; if (i <= W11[2]) return 2; if (i <= W11[3]) return 3; if (i <= W11[4]) return 4; if (i <= W11[5]) return 5; return 6; } /* det M = 1 */ static void treat_index(GEN W, GEN M, long index, GEN v) { GEN W11 = gel(W,11); long shift = W11[3]; /* #F + #E2 + T32 */ switch(set_from_index(W11, index)) { case 1: /*F*/ { GEN F_index = gel(W,6), ind = gel(F_index, index); long j, l = lg(ind); for (j = 1; j < l; j++) { GEN IND = gel(ind,j), M0 = gel(IND,2); long index = mael(IND,1,1); treat_index(W, ZM_mul(M,M0), index, v); } break; } case 2: /*E2, E2[r] + gamma * E1[s] = 0 */ { long r = index - W11[1]; GEN z = gel(msN_get_E2fromE1(W), r); index = E2fromE1_c(z); M = G_ZG_mul(M, E2fromE1_Zgamma(z)); /* M * (-gamma) */ gel(v, index) = ZG_add(gel(v, index), M); break; } case 3: /*T32, T32[i] = -T31[i] */ { long T3shift = W11[5] - W11[2]; /* #T32 + #E1 + #T2 */ index += T3shift; index -= shift; gel(v, index) = ZG_add(gel(v, index), to_famat_shallow(M,gen_m1)); break; } default: /*E1,T2,T31*/ index -= shift; gel(v, index) = ZG_add(gel(v, index), to_famat_shallow(M,gen_1)); break; } } static void treat_index_trivial(GEN v, GEN W, long index) { GEN W11 = gel(W,11); long shift = W11[3]; /* #F + #E2 + T32 */ switch(set_from_index(W11, index)) { case 1: /*F*/ { GEN F_index = gel(W,6), ind = gel(F_index, index); long j, l = lg(ind); for (j = 1; j < l; j++) { GEN IND = gel(ind,j); treat_index_trivial(v, W, mael(IND,1,1)); } break; } case 2: /*E2, E2[r] + gamma * E1[s] = 0 */ { long r = index - W11[1]; long s = E2fromE1_c(gel(msN_get_E2fromE1(W), r)); v[s]--; break; } case 3: case 5: case 6: /*T32,T2,T31*/ break; case 4: /*E1*/ v[index-shift]++; break; } } static GEN M2_log(GEN W, GEN M) { GEN a = gcoeff(M,1,1), b = gcoeff(M,1,2); GEN c = gcoeff(M,2,1), d = gcoeff(M,2,2); GEN u, v, D, V; long index, s; W = get_msN(W); V = zerovec(ms_get_nbgen(W)); D = subii(mulii(a,d), mulii(b,c)); s = signe(D); if (!s) return V; if (is_pm1(D)) { /* shortcut, no need to apply Manin's trick */ if (s < 0) { b = negi(b); d = negi(d); } M = Gamma0N_decompose(W, mkmat22(a,b, c,d), &index); treat_index(W, M, index, V); } else { GEN U, B, P, Q, PQ, C1,C2; long i, l; (void)bezout(a,c,&u,&v); B = addii(mulii(b,u), mulii(d,v)); /* [u,v;-c,a] [a,b; c,d] = [1,B; 0,D], i.e. M = U [1,B;0,D] */ U = mkmat22(a,negi(v), c,u); /* {1/0 -> B/D} as \sum g_i, g_i unimodular paths */ PQ = ZV_allpnqn( gboundcf(gdiv(B,D), 0) ); P = gel(PQ,1); l = lg(P); Q = gel(PQ,2); C1 = gel(U,1); for (i = 1; i < l; i++, C1 = C2) { GEN M; C2 = ZM_ZC_mul(U, mkcol2(gel(P,i), gel(Q,i))); if (!odd(i)) C1 = ZC_neg(C1); M = Gamma0N_decompose(W, mkmat2(C1,C2), &index); treat_index(W, M, index, V); } } return V; } /* express +oo->q=a/b in terms of the Z[G]-generators, trivial action */ static void Q_log_trivial(GEN v, GEN W, GEN q) { GEN Q, W3 = gel(W,3), p1N = msN_get_p1N(W); ulong c,d, N = p1N_get_N(p1N); long i, lx; Q = Q_log_init(N, q); lx = lg(Q); c = 0; for (i = 1; i < lx; i++, c = d) { long index; d = Q[i]; if (c && !odd(i)) c = N - c; index = W3[ p1_index(c,d,p1N) ]; treat_index_trivial(v, W, index); } } static void M2_log_trivial(GEN V, GEN W, GEN M) { GEN p1N = gel(W,1), W3 = gel(W,3); ulong N = p1N_get_N(p1N); GEN a = gcoeff(M,1,1), b = gcoeff(M,1,2); GEN c = gcoeff(M,2,1), d = gcoeff(M,2,2); GEN u, v, D; long index, s; D = subii(mulii(a,d), mulii(b,c)); s = signe(D); if (!s) return; if (is_pm1(D)) { /* shortcut, not need to apply Manin's trick */ if (s < 0) d = negi(d); index = W3[ p1_index(umodiu(c,N),umodiu(d,N),p1N) ]; treat_index_trivial(V, W, index); } else { GEN U, B, P, Q, PQ; long i, l; if (!signe(c)) { Q_log_trivial(V,W,gdiv(b,d)); return; } (void)bezout(a,c,&u,&v); B = addii(mulii(b,u), mulii(d,v)); /* [u,v;-c,a] [a,b; c,d] = [1,B; 0,D], i.e. M = U [1,B;0,D] */ U = mkvec2(c, u); /* {1/0 -> B/D} as \sum g_i, g_i unimodular paths */ PQ = ZV_allpnqn( gboundcf(gdiv(B,D), 0) ); P = gel(PQ,1); l = lg(P); Q = gel(PQ,2); for (i = 1; i < l; i++, c = d) { d = addii(mulii(gel(U,1),gel(P,i)), mulii(gel(U,2),gel(Q,i))); if (!odd(i)) c = negi(c); index = W3[ p1_index(umodiu(c,N),umodiu(d,N),p1N) ]; treat_index_trivial(V, W, index); } } } static GEN cusp_to_ZC(GEN c) { switch(typ(c)) { case t_INFINITY: return mkcol2(gen_1,gen_0); case t_INT: return mkcol2(c,gen_1); case t_FRAC: return mkcol2(gel(c,1),gel(c,2)); case t_VECSMALL: return mkcol2(stoi(c[1]), stoi(c[2])); default: pari_err_TYPE("mspathlog",c); return NULL;/*LCOV_EXCL_LINE*/ } } static GEN path2_to_M2(GEN p) { return mkmat2(cusp_to_ZC(gel(p,1)), cusp_to_ZC(gel(p,2))); } static GEN path_to_M2(GEN p) { if (lg(p) != 3) pari_err_TYPE("mspathlog",p); switch(typ(p)) { case t_MAT: RgM_check_ZM(p,"mspathlog"); break; case t_VEC: p = path2_to_M2(p); break; default: pari_err_TYPE("mspathlog",p); } return p; } /* Expresses path p as \sum x_i g_i, where the g_i are our distinguished * generators and x_i \in Z[\Gamma]. Returns [x_1,...,x_n] */ GEN mspathlog(GEN W, GEN p) { pari_sp av = avma; checkms(W); return gerepilecopy(av, M2_log(W, path_to_M2(p))); } /** HECKE OPERATORS **/ /* [a,b;c,d] * cusp */ static GEN cusp_mul(long a, long b, long c, long d, GEN cusp) { long x = cusp[1], y = cusp[2]; long A = a*x+b*y, B = c*x+d*y, u = cgcd(A,B); if (u != 1) { A /= u; B /= u; } return mkcol2s(A, B); } /* f in Gl2(Q), act on path (zm), return path_to_M2(f.path) */ static GEN Gl2Q_act_path(GEN f, GEN path) { long a = coeff(f,1,1), b = coeff(f,1,2); long c = coeff(f,2,1), d = coeff(f,2,2); GEN c1 = cusp_mul(a,b,c,d, gel(path,1)); GEN c2 = cusp_mul(a,b,c,d, gel(path,2)); return mkmat2(c1,c2); } static GEN init_act_trivial(GEN W) { return const_vecsmall(ms_get_nbE1(W), 0); } static GEN mspathlog_trivial(GEN W, GEN p) { GEN v; W = get_msN(W); v = init_act_trivial(W); M2_log_trivial(v, W, path_to_M2(p)); return v; } /* map from W1=Hom(Delta_0(N1),Q) -> W2=Hom(Delta_0(N2),Q), weight 2, * trivial action. v a t_VEC of Gl2_Q (\sum v[i] in Z[Gl2(Q)]). * Return the matrix attached to the action of v. */ static GEN getMorphism_trivial(GEN WW1, GEN WW2, GEN v) { GEN T, section, gen, W1 = get_msN(WW1), W2 = get_msN(WW2); long j, lv, d2; if (ms_get_N(W1) == 1) return cgetg(1,t_MAT); if (ms_get_N(W2) == 1) return zeromat(0, ms_get_nbE1(W1)); section = msN_get_section(W2); gen = msN_get_genindex(W2); d2 = ms_get_nbE1(W2); T = cgetg(d2+1, t_MAT); lv = lg(v); for (j = 1; j <= d2; j++) { GEN w = gel(section, gen[j]); GEN t = init_act_trivial(W1); pari_sp av = avma; long l; for (l = 1; l < lv; l++) M2_log_trivial(t, W1, Gl2Q_act_path(gel(v,l), w)); gel(T,j) = t; set_avma(av); } return shallowtrans(zm_to_ZM(T)); } static GEN RgV_sparse(GEN v, GEN *pind) { long i, l, k; GEN w = cgetg_copy(v,&l), ind = cgetg(l, t_VECSMALL); for (i = k = 1; i < l; i++) { GEN c = gel(v,i); if (typ(c) == t_INT) continue; gel(w,k) = c; ind[k] = i; k++; } setlg(w,k); setlg(ind,k); *pind = ind; return w; } static int mat2_isidentity(GEN M) { GEN A = gel(M,1), B = gel(M,2); return A[1] == 1 && A[2] == 0 && B[1] == 0 && B[2] == 1; } /* path a mat22/mat22s, return log(f.path)^* . f in sparse form */ static GEN M2_logf(GEN Wp, GEN path, GEN f) { pari_sp av = avma; GEN ind, L; long i, l; if (f) path = Gl2Q_act_path(f, path); else if (typ(gel(path,1)) == t_VECSMALL) path = path2_to_M2(path); L = M2_log(Wp, path); L = RgV_sparse(L,&ind); l = lg(L); for (i = 1; i < l; i++) gel(L,i) = ZSl2_star(gel(L,i)); if (f) ZGC_G_mul_inplace(L, mat2_to_ZM(f)); return gerepilecopy(av, mkvec2(ind,L)); } static hashtable * Gl2act_cache(long dim) { return set_init(dim*10); } /* f zm/ZM in Gl_2(Q), acts from the left on Delta, which is generated by * (g_i) as Z[Gamma1]-module, and by (G_i) as Z[Gamma2]-module. * We have f.G_j = \sum_i \lambda_{i,j} g_i, \lambda_{i,j} in Z[Gamma1] * For phi in Hom_Gamma1(D,V), g in D, phi | f is in Hom_Gamma2(D,V) and * (phi | f)(G_j) = phi(f.G_j) | f * = phi( \sum_i \lambda_{i,j} g_i ) | f * = \sum_i phi(g_i) | (\lambda_{i,j}^* f) * = \sum_i phi(g_i) | \mu_{i,j}(f) * More generally * (\sum_k (phi |v_k))(G_j) = \sum_i phi(g_i) | \Mu_{i,j} * with \Mu_{i,j} = \sum_k \mu{i,j}(v_k) * Return the \Mu_{i,j} matrix as vector of sparse columns of operators on V */ static GEN init_dual_act(GEN v, GEN W1, GEN W2, struct m_act *S) { GEN section = ms_get_section(W2), gen = ms_get_genindex(W2); /* HACK: the actions we consider in dimension 1 are trivial and in * characteristic != 2, 3 => torsion generators are 0 * [satisfy e.g. (1+gamma).g = 0 => \phi(g) | 1+gamma = 0 => \phi(g) = 0 */ long j, lv = lg(v), dim = S->dim == 1? ms_get_nbE1(W2): lg(gen)-1; GEN T = cgetg(dim+1, t_VEC); hashtable *H = Gl2act_cache(dim); for (j = 1; j <= dim; j++) { pari_sp av = avma; GEN w = gel(section, gen[j]); /* path_to_zm( E1/T2/T3 element ) */ GEN t = NULL; long k; for (k = 1; k < lv; k++) { GEN tk, f = gel(v,k); if (typ(gel(f,1)) != t_VECSMALL) f = ZM_to_zm(f); if (mat2_isidentity(f)) f = NULL; tk = M2_logf(W1, w, f); /* mu_{.,j}(v[k]) as sparse vector */ t = t? ZGCs_add(t, tk): tk; } gel(T,j) = gerepilecopy(av, t); } for (j = 1; j <= dim; j++) { ZGl2QC_preload(S, gel(T,j), H); ZGl2QC_to_act(S, gel(T,j), H); } return T; } /* modular symbol given by phi[j] = \phi(G_j) * \sum L[i]*phi[i], L a sparse column of operators */ static GEN dense_act_col(GEN col, GEN phi) { GEN s = NULL, colind = gel(col,1), colval = gel(col,2); long i, l = lg(colind), lphi = lg(phi); for (i = 1; i < l; i++) { long a = colind[i]; GEN t; if (a >= lphi) break; /* happens if k=2: torsion generator t omitted */ t = gel(phi, a); /* phi(G_a) */ t = RgM_RgC_mul(gel(colval,i), t); s = s? RgC_add(s, t): t; } return s; } /* modular symbol given by \phi( G[ind[j]] ) = val[j] * \sum L[i]*phi[i], L a sparse column of operators */ static GEN sparse_act_col(GEN col, GEN phi) { GEN s = NULL, colind = gel(col,1), colval = gel(col,2); GEN ind = gel(phi,2), val = gel(phi,3); long a, l = lg(ind); if (lg(gel(phi,1)) == 1) return RgM_RgC_mul(gel(colval,1), gel(val,1)); for (a = 1; a < l; a++) { GEN t = gel(val, a); /* phi(G_i) */ long i = zv_search(colind, ind[a]); if (!i) continue; t = RgM_RgC_mul(gel(colval,i), t); s = s? RgC_add(s, t): t; } return s; } static int phi_sparse(GEN phi) { return typ(gel(phi,1)) == t_VECSMALL; } /* phi in Hom_Gamma1(Delta, V), return the matrix whose colums are the * \sum_i phi(g_i) | \mu_{i,j} = (phi|f)(G_j), * see init_dual_act. */ static GEN dual_act(long dimV, GEN act, GEN phi) { long l = lg(act), j; GEN v = cgetg(l, t_MAT); GEN (*ACT)(GEN,GEN) = phi_sparse(phi)? sparse_act_col: dense_act_col; for (j = 1; j < l; j++) { pari_sp av = avma; GEN s = ACT(gel(act,j), phi); gel(v,j) = s? gerepileupto(av,s): zerocol(dimV); } return v; } /* in level N > 1 */ static void msk_get_st(GEN W, long *s, long *t) { GEN st = gmael(W,3,3); *s = st[1]; *t = st[2]; } static GEN msk_get_link(GEN W) { return gmael(W,3,4); } static GEN msk_get_inv(GEN W) { return gmael(W,3,5); } /* \phi in Hom(Delta, V), \phi(G_k) = phi[k]. Write \phi as * \sum_{i,j} mu_{i,j} phi_{i,j}, mu_{i,j} in Q */ static GEN getMorphism_basis(GEN W, GEN phi) { GEN R, Q, Ls, T0, T1, Ts, link, basis, inv = msk_get_inv(W); long i, j, r, s, t, dim, lvecT; if (ms_get_N(W) == 1) return ZC_apply_dinv(inv, gel(phi,1)); lvecT = lg(phi); basis = msk_get_basis(W); dim = lg(basis)-1; R = zerocol(dim); msk_get_st(W, &s, &t); link = msk_get_link(W); for (r = 2; r < lvecT; r++) { GEN Tr, L; if (r == s) continue; Tr = gel(phi,r); /* Phi(G_r), r != 1,s */ L = gel(link, r); Q = ZC_apply_dinv(gel(inv,r), Tr); /* write Phi(G_r) as sum_{a,b} mu_{a,b} Phi_{a,b}(G_r) */ for (j = 1; j < lg(L); j++) gel(R, L[j]) = gel(Q,j); } Ls = gel(link, s); T1 = gel(phi,1); /* Phi(G_1) */ gel(R, Ls[t]) = gel(T1, 1); T0 = NULL; for (i = 2; i < lg(link); i++) { GEN L; if (i == s) continue; L = gel(link,i); for (j =1 ; j < lg(L); j++) { long n = L[j]; /* phi_{i,j} = basis[n] */ GEN mu_ij = gel(R, n); GEN phi_ij = gel(basis, n), pols = gel(phi_ij,3); GEN z = RgC_Rg_mul(gel(pols, 3), mu_ij); T0 = T0? RgC_add(T0, z): z; /* += mu_{i,j} Phi_{i,j} (G_s) */ } } Ts = gel(phi,s); /* Phi(G_s) */ if (T0) Ts = RgC_sub(Ts, T0); /* solve \sum_{j!=t} mu_{s,j} Phi_{s,j}(G_s) = Ts */ Q = ZC_apply_dinv(gel(inv,s), Ts); for (j = 1; j < t; j++) gel(R, Ls[j]) = gel(Q,j); /* avoid mu_{s,t} */ for (j = t; j < lg(Q); j++) gel(R, Ls[j+1]) = gel(Q,j); return R; } /* a = s(g_i) for some modular symbol s; b in Z[G] * return s(b.g_i) = b^* . s(g_i) */ static GEN ZGl2Q_act_s(GEN b, GEN a, long k) { if (typ(b) == t_INT) { if (!signe(b)) return gen_0; switch(typ(a)) { case t_POL: a = RgX_to_RgC(a, k-1); /*fall through*/ case t_COL: a = RgC_Rg_mul(a,b); break; default: a = scalarcol_shallow(b,k-1); } } else { b = RgX_act_ZGl2Q(ZSl2_star(b), k); switch(typ(a)) { case t_POL: a = RgX_to_RgC(a, k-1); /*fall through*/ case t_COL: a = RgM_RgC_mul(b,a); break; default: a = RgC_Rg_mul(gel(b,1),a); } } return a; } static int checksymbol(GEN W, GEN s) { GEN t, annT2, annT31, singlerel; long i, k, l, nbE1, nbT2, nbT31; k = msk_get_weight(W); W = get_msN(W); nbE1 = ms_get_nbE1(W); singlerel = gel(W,10); l = lg(singlerel); if (k == 2) { for (i = nbE1+1; i < l; i++) if (!gequal0(gel(s,i))) return 0; return 1; } annT2 = msN_get_annT2(W); nbT2 = lg(annT2)-1; annT31 = msN_get_annT31(W);nbT31 = lg(annT31)-1; t = NULL; for (i = 1; i < l; i++) { GEN a = gel(s,i); a = ZGl2Q_act_s(gel(singlerel,i), a, k); t = t? gadd(t, a): a; } if (!gequal0(t)) return 0; for (i = 1; i <= nbT2; i++) { GEN a = gel(s,i + nbE1); a = ZGl2Q_act_s(gel(annT2,i), a, k); if (!gequal0(a)) return 0; } for (i = 1; i <= nbT31; i++) { GEN a = gel(s,i + nbE1 + nbT2); a = ZGl2Q_act_s(gel(annT31,i), a, k); if (!gequal0(a)) return 0; } return 1; } GEN msissymbol(GEN W, GEN s) { long k, nbgen; checkms(W); k = msk_get_weight(W); nbgen = ms_get_nbgen(W); switch(typ(s)) { case t_VEC: /* values s(g_i) */ if (lg(s)-1 != nbgen) return gen_0; break; case t_COL: if (msk_get_sign(W)) { GEN star = gel(msk_get_starproj(W), 1); if (lg(star) == lg(s)) return gen_1; } if (k == 2) /* on the dual basis of (g_i) */ { if (lg(s)-1 != nbgen) return gen_0; } else { GEN basis = msk_get_basis(W); return (lg(s) == lg(basis))? gen_1: gen_0; } break; case t_MAT: { long i, l = lg(s); GEN v = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(v,i) = msissymbol(W,gel(s,i))? gen_1: gen_0; return v; } default: return gen_0; } return checksymbol(W,s)? gen_1: gen_0; } /* map op: W1 = Hom(Delta_0(N1),V) -> W2 = Hom(Delta_0(N2),V), given by * \sum v[i], v[i] in Gl2(Q) */ static GEN getMorphism(GEN W1, GEN W2, GEN v) { struct m_act S; GEN B1, M, act; long a, l, k = msk_get_weight(W1); if (k == 2) return getMorphism_trivial(W1,W2,v); S.k = k; S.dim = k-1; S.act = &_RgX_act_Gl2Q; act = init_dual_act(v,W1,W2,&S); B1 = msk_get_basis(W1); l = lg(B1); M = cgetg(l, t_MAT); for (a = 1; a < l; a++) { pari_sp av = avma; GEN phi = dual_act(S.dim, act, gel(B1,a)); GEN D = getMorphism_basis(W2, phi); gel(M,a) = gerepilecopy(av, D); } return M; } static GEN msendo(GEN W, GEN v) { return getMorphism(W, W, v); } static GEN endo_project(GEN W, GEN e, GEN H) { if (msk_get_sign(W)) e = Qevproj_apply(e, msk_get_starproj(W)); if (H) e = Qevproj_apply(e, Qevproj_init0(H)); return e; } static GEN mshecke_i(GEN W, ulong p) { GEN v = ms_get_N(W) % p? Tp_matrices(p): Up_matrices(p); return msendo(W,v); } GEN mshecke(GEN W, long p, GEN H) { pari_sp av = avma; GEN T; checkms(W); if (p <= 1) pari_err_PRIME("mshecke",stoi(p)); T = mshecke_i(W,p); T = endo_project(W,T,H); return gerepilecopy(av, T); } static GEN msatkinlehner_i(GEN W, long Q) { long N = ms_get_N(W); GEN v; if (Q == 1) return matid(msk_get_dim(W)); if (Q == N) return msendo(W, mkvec(mat2(0,1,-N,0))); if (N % Q) pari_err_DOMAIN("msatkinlehner","N % Q","!=",gen_0,stoi(Q)); v = WQ_matrix(N, Q); if (!v) pari_err_DOMAIN("msatkinlehner","gcd(Q,N/Q)","!=",gen_1,stoi(Q)); return msendo(W,mkvec(v)); } GEN msatkinlehner(GEN W, long Q, GEN H) { pari_sp av = avma; GEN w; long k; checkms(W); k = msk_get_weight(W); if (Q <= 0) pari_err_DOMAIN("msatkinlehner","Q","<=",gen_0,stoi(Q)); w = msatkinlehner_i(W,Q); w = endo_project(W,w,H); if (k > 2 && Q != 1) w = RgM_Rg_div(w, powuu(Q,(k-2)>>1)); return gerepilecopy(av, w); } static GEN msstar_i(GEN W) { return msendo(W, mkvec(mat2(-1,0,0,1))); } GEN msstar(GEN W, GEN H) { pari_sp av = avma; GEN s; checkms(W); s = msstar_i(W); s = endo_project(W,s,H); return gerepilecopy(av, s); } #if 0 /* is \Gamma_0(N) cusp1 = \Gamma_0(N) cusp2 ? */ static int iscuspeq(ulong N, GEN cusp1, GEN cusp2) { long p1, q1, p2, q2, s1, s2, d; p1 = cusp1[1]; p2 = cusp2[1]; q1 = cusp1[2]; q2 = cusp2[2]; d = Fl_mul(umodsu(q1,N),umodsu(q2,N), N); d = ugcd(d, N); s1 = q1 > 2? Fl_inv(umodsu(p1,q1), q1): 1; s2 = q2 > 2? Fl_inv(umodsu(p2,q2), q2): 1; return Fl_mul(s1,q2,d) == Fl_mul(s2,q1,d); } #endif /* return E_c(r) */ static GEN get_Ec_r(GEN c, long k) { long p = c[1], q = c[2], u, v; GEN gr; (void)cbezout(p, q, &u, &v); gr = mat2(p, -v, q, u); /* g . (1:0) = (p:q) */ return voo_act_Gl2Q(sl2_inv(gr), k); } /* N > 1; returns the modular symbol attached to the cusp c := p/q via the rule * E_c(path from a to b in Delta_0) := E_c(b) - E_c(a), where * E_c(r) := 0 if r != c mod Gamma * v_oo | gamma_r^(-1) * where v_oo is stable by T = [1,1;0,1] (i.e x^(k-2)) and * gamma_r . (1:0) = r, for some gamma_r in SL_2(Z) * */ static GEN msfromcusp_trivial(GEN W, GEN c) { GEN section = ms_get_section(W), gen = ms_get_genindex(W); GEN S = ms_get_hashcusps(W); long j, ic = cusp_index(c, S), l = ms_get_nbE1(W)+1; GEN phi = cgetg(l, t_COL); for (j = 1; j < l; j++) { GEN vj, g = gel(section, gen[j]); /* path_to_zm(generator) */ GEN c1 = gel(g,1), c2 = gel(g,2); long i1 = cusp_index(c1, S); long i2 = cusp_index(c2, S); if (i1 == ic) vj = (i2 == ic)? gen_0: gen_1; else vj = (i2 == ic)? gen_m1: gen_0; gel(phi, j) = vj; } return phi; } static GEN msfromcusp_i(GEN W, GEN c) { GEN section, gen, S, phi; long j, ic, l, k = msk_get_weight(W); if (k == 2) { long N = ms_get_N(W); return N == 1? cgetg(1,t_COL): msfromcusp_trivial(W, c); } k = msk_get_weight(W); section = ms_get_section(W); gen = ms_get_genindex(W); S = ms_get_hashcusps(W); ic = cusp_index(c, S); l = lg(gen); phi = cgetg(l, t_COL); for (j = 1; j < l; j++) { GEN vj = NULL, g = gel(section, gen[j]); /* path_to_zm(generator) */ GEN c1 = gel(g,1), c2 = gel(g,2); long i1 = cusp_index(c1, S); long i2 = cusp_index(c2, S); if (i1 == ic) vj = get_Ec_r(c1, k); if (i2 == ic) { GEN s = get_Ec_r(c2, k); vj = vj? gsub(vj, s): gneg(s); } if (!vj) vj = zerocol(k-1); gel(phi, j) = vj; } return getMorphism_basis(W, phi); } GEN msfromcusp(GEN W, GEN c) { pari_sp av = avma; long N; checkms(W); N = ms_get_N(W); switch(typ(c)) { case t_INFINITY: c = mkvecsmall2(1,0); break; case t_INT: c = mkvecsmall2(smodis(c,N), 1); break; case t_FRAC: c = mkvecsmall2(smodis(gel(c,1),N), smodis(gel(c,2),N)); break; default: pari_err_TYPE("msfromcusp",c); } return gerepilecopy(av, msfromcusp_i(W,c)); } static GEN mseisenstein_i(GEN W) { GEN M, S = ms_get_hashcusps(W), cusps = gel(S,3); long i, l = lg(cusps); if (msk_get_weight(W)==2) l--; M = cgetg(l, t_MAT); for (i = 1; i < l; i++) gel(M,i) = msfromcusp_i(W, gel(cusps,i)); return Qevproj_init(Qevproj_star(W, QM_image_shallow(M))); } GEN mseisenstein(GEN W) { pari_sp av = avma; checkms(W); return gerepilecopy(av, mseisenstein_i(W)); } /* upper bound for log_2 |charpoly(T_p|S)|, where S is a cuspidal subspace of * dimension d, k is the weight */ #if 0 static long TpS_char_bound(ulong p, long k, long d) { /* |eigenvalue| <= 2 p^(k-1)/2 */ return d * (2 + (log2((double)p)*(k-1))/2); } #endif static long TpE_char_bound(ulong p, long k, long d) { /* |eigenvalue| <= 2 p^(k-1) */ return d * (2 + log2((double)p)*(k-1)); } static GEN eisker(GEN M); static int use_Petersson(long N, long k, long s) { if (!s) { if (N == 1) return 1; if (N <= 3) return k >= 42; if (N == 4) return k >= 30; if (N == 5) return k >= 20; if (N <= 10) return k >= 14; if (N <= 16) return k >= 10; if (N <= 28) return k >= 8; if (N <= 136 || N == 180 || N == 200 || N == 225) return k >= 6; return k >= 4; } if (s < 0) { if (N <= 64 || N == 100 || N == 128 || N == 144 || N == 225 || N == 351 || N == 375) return k >= 8; return k >= 6; } if (N == 1) return 1; if (N == 2) return k >= 56; if (N == 3) return k >= 68; if (N == 4) return k >= 78; if (N == 5) return k >= 38; if (N == 6) return k >= 24; if (N == 7) return k >= 44; if (N <= 9) return k >= 28; if (N <= 13) return k >= 20; if (N <= 21 || N == 50) return k >= 14; if (N == 24 || N == 25) return k >= 16; if (N <= 58 || N == 63 || N == 72 || N == 84 || N == 208 || N == 224) return k >= 10; if (N <= 128 || N == 144 || N == 145 || N == 160 || N == 168 || N == 175 || N == 180 || N == 252 || N == 253 || N == 273 || N == 320 || N == 335 || N == 336 || N == 345 || N == 360) return k >= 8; return k >= 6; } /* eisspace^-(N) = 0 */ static int isminustriv(GEN F) { GEN P = gel(F,1), E = gel(F,2); long i = 1, l = lg(P); if (l == 1) return 1; if (P[1] == 2) { if (E[1] >= 4) return 0; i++; } for (; i < l; i++) if (E[i] > 1) return 0; return 1; } GEN mscuspidal(GEN W, long flag) { pari_sp av = avma; GEN M, E, S; ulong p, N; long k, s; checkms(W); N = ms_get_N(W); k = msk_get_weight(W); s = msk_get_sign(W); E = flag? mseisenstein_i(W): NULL; if (s < 0 && isminustriv(factoru(N))) M = matid(msdim(W)); else if (use_Petersson(N, k, s)) M = eisker(W); else { GEN dT, T, TE, chE; forprime_t F; long bit; pari_timer ti; if (!E) E = mseisenstein_i(W); (void)u_forprime_init(&F, 2, ULONG_MAX); while ((p = u_forprime_next(&F))) if (N % p) break; if (DEBUGLEVEL) timer_start(&ti); T = mshecke(W, p, NULL); if (DEBUGLEVEL) timer_printf(&ti,"Tp, p = %ld", p); TE = Qevproj_apply(T, E); /* T_p | E */ if (DEBUGLEVEL) timer_printf(&ti,"Qevproj_init(E)"); bit = TpE_char_bound(p, k, lg(TE)-1); chE = QM_charpoly_ZX_bound(TE, bit); chE = ZX_radical(chE); T = Q_remove_denom(T, &dT); if (dT) chE = ZX_rescale(chE, dT); M = RgX_RgM_eval(chE, T); M = QM_image_shallow(M); /* = Im chE(T / dT) */ } S = Qevproj_init(M); return gerepilecopy(av, flag? mkvec2(S,E): S); } /** INIT ELLSYM STRUCTURE **/ /* V a vector of ZM. If all of them have 0 last row, return NULL. * Otherwise return [m,i,j], where m = V[i][last,j] contains the value * of smallest absolute value */ static GEN RgMV_find_non_zero_last_row(long offset, GEN V) { long i, lasti = 0, lastj = 0, lV = lg(V); GEN m = NULL; for (i = 1; i < lV; i++) { GEN M = gel(V,i); long j, n, l = lg(M); if (l == 1) continue; n = nbrows(M); for (j = 1; j < l; j++) { GEN a = gcoeff(M, n, j); if (!gequal0(a) && (!m || abscmpii(a, m) < 0)) { m = a; lasti = i; lastj = j; if (is_pm1(m)) goto END; } } } END: if (!m) return NULL; return mkvec2(m, mkvecsmall2(lasti+offset, lastj)); } /* invert the d_oo := (\gamma_oo - 1) operator, acting on * [x^(k-2), ..., y^(k-2)] */ static GEN Delta_inv(GEN doo, long k) { GEN M = RgX_act_ZGl2Q(doo, k); M = RgM_minor(M, k-1, 1); /* 1st column and last row are 0 */ return ZM_inv_denom(M); } /* The ZX P = \sum a_i x^i y^{k-2-i} is given by the ZV [a_0, ..., a_k-2]~, * return Q and d such that P = doo Q + d y^k-2, where d in Z and Q */ static GEN doo_decompose(GEN dinv, GEN P, GEN *pd) { long l = lg(P); *pd = gel(P, l-1); P = vecslice(P, 1, l-2); return vec_prepend(ZC_apply_dinv(dinv, P), gen_0); } static GEN get_phi_ij(long i,long j,long n, long s,long t,GEN P_st,GEN Q_st,GEN d_st, GEN P_ij, GEN lP_ij, GEN dinv) { GEN ind, pols; if (i == s && j == t) { ind = mkvecsmall(1); pols = mkvec(scalarcol_shallow(gen_1, lg(P_st)-1)); /* x^{k-2} */ } else { GEN d_ij, Q_ij = doo_decompose(dinv, lP_ij, &d_ij); GEN a = ZC_Z_mul(P_ij, d_st); GEN b = ZC_Z_mul(P_st, negi(d_ij)); GEN c = RgC_sub(RgC_Rg_mul(Q_ij, d_st), RgC_Rg_mul(Q_st, d_ij)); if (i == s) { /* j != t */ ind = mkvecsmall2(1, s); pols = mkvec2(c, ZC_add(a, b)); } else { ind = mkvecsmall3(1, i, s); pols = mkvec3(c, a, b); /* image of g_1, g_i, g_s */ } pols = Q_primpart(pols); } return mkvec3(mkvecsmall3(i,j,n), ind, pols); } static GEN mskinit_trivial(GEN WN) { long dim = ms_get_nbE1(WN); return mkvec3(WN, gen_0, mkvec2(gen_0,mkvecsmall2(2, dim))); } /* sum of #cols of the matrices contained in V */ static long RgMV_dim(GEN V) { long l = lg(V), d = 0, i; for (i = 1; i < l; i++) d += lg(gel(V,i)) - 1; return d; } static GEN mskinit_nontrivial(GEN WN, long k) { GEN annT2 = gel(WN,8), annT31 = gel(WN,9), singlerel = gel(WN,10); GEN link, basis, monomials, Inv; long nbE1 = ms_get_nbE1(WN); GEN dinv = Delta_inv(ZG_neg( ZSl2_star(gel(singlerel,1)) ), k); GEN p1 = cgetg(nbE1+1, t_VEC), remove; GEN p2 = ZGV_tors(annT2, k); GEN p3 = ZGV_tors(annT31, k); GEN gentor = shallowconcat(p2, p3); GEN P_st, lP_st, Q_st, d_st; long n, i, dim, s, t, u; gel(p1, 1) = cgetg(1,t_MAT); /* dummy */ for (i = 2; i <= nbE1; i++) /* skip 1st element = (\gamma_oo-1)g_oo */ { GEN z = gel(singlerel, i); gel(p1, i) = RgX_act_ZGl2Q(ZSl2_star(z), k); } remove = RgMV_find_non_zero_last_row(nbE1, gentor); if (!remove) remove = RgMV_find_non_zero_last_row(0, p1); if (!remove) pari_err_BUG("msinit [no y^k-2]"); remove = gel(remove,2); /* [s,t] */ s = remove[1]; t = remove[2]; /* +1 because of = x^(k-2), but -1 because of Manin relation */ dim = (k-1)*(nbE1-1) + RgMV_dim(p2) + RgMV_dim(p3); /* Let (g_1,...,g_d) be the Gamma-generators of Delta, g_1 = g_oo. * We describe modular symbols by the collection phi(g_1), ..., phi(g_d) * \in V := Q[x,y]_{k-2}, with right Gamma action. * For each i = 1, .., d, let V_i \subset V be the Q-vector space of * allowed values for phi(g_i): with basis (P^{i,j}) given by the monomials * x^(j-1) y^{k-2-(j-1)}, j = 1 .. k-1 * (g_i in E_1) or the solution of the torsion equations (1 + gamma)P = 0 * (g_i in T2) or (1 + gamma + gamma^2)P = 0 (g_i in T31). All such P * are chosen in Z[x,y] with Q_content 1. * * The Manin relation (singlerel) is of the form \sum_i \lambda_i g_i = 0, * where \lambda_i = 1 if g_i in T2 or T31, and \lambda_i = (1 - \gamma_i) * for g_i in E1. * * If phi \in Hom_Gamma(Delta, V), it is defined by phi(g_i) := P_i in V * with \sum_i P_i . \lambda_i^* = 0, where (\sum n_i g_i)^* := * \sum n_i \gamma_i^(-1). * * We single out gamma_1 / g_1 (g_oo in Pollack-Stevens paper) and * write P_{i,j} \lambda_i^* = Q_{i,j} (\gamma_1 - 1)^* + d_{i,j} y^{k-2} * where d_{i,j} is a scalar and Q_{i,j} in V; we normalize Q_{i,j} to * that the coefficient of x^{k-2} is 0. * * There exist (s,t) such that d_{s,t} != 0. * A Q-basis of the (dual) space of modular symbols is given by the * functions phi_{i,j}, 2 <= i <= d, 1 <= j <= k-1, mapping * g_1 -> d_{s,t} Q_{i,j} - d_{i,j} Q_{s,t} + [(i,j)=(s,t)] x^{k-2} * If i != s * g_i -> d_{s,t} P_{i,j} * g_s -> - d_{i,j} P_{s,t} * If i = s, j != t * g_i -> d_{s,t} P_{i,j} - d_{i,j} P_{s,t} * And everything else to 0. Again we normalize the phi_{i,j} such that * their image has content 1. */ monomials = matid(k-1); /* represent the monomials x^{k-2}, ... , y^{k-2} */ if (s <= nbE1) /* in E1 */ { P_st = gel(monomials, t); lP_st = gmael(p1, s, t); /* P_{s,t} lambda_s^* */ } else /* in T2, T31 */ { P_st = gmael(gentor, s - nbE1, t); lP_st = P_st; } Q_st = doo_decompose(dinv, lP_st, &d_st); basis = cgetg(dim+1, t_VEC); link = cgetg(nbE1 + lg(gentor), t_VEC); gel(link,1) = cgetg(1,t_VECSMALL); /* dummy */ n = 1; for (i = 2; i <= nbE1; i++) { GEN L = cgetg(k, t_VECSMALL); long j; /* link[i][j] = n gives correspondance between phi_{i,j} and basis[n] */ gel(link,i) = L; for (j = 1; j < k; j++) { GEN lP_ij = gmael(p1, i, j); /* P_{i,j} lambda_i^* */ GEN P_ij = gel(monomials,j); L[j] = n; gel(basis, n) = get_phi_ij(i,j,n, s,t, P_st, Q_st, d_st, P_ij, lP_ij, dinv); n++; } } for (u = 1; u < lg(gentor); u++,i++) { GEN V = gel(gentor,u); long j, lV = lg(V); GEN L = cgetg(lV, t_VECSMALL); gel(link,i) = L; for (j = 1; j < lV; j++) { GEN lP_ij = gel(V, j); /* P_{i,j} lambda_i^* = P_{i,j} */ GEN P_ij = lP_ij; L[j] = n; gel(basis, n) = get_phi_ij(i,j,n, s,t, P_st, Q_st, d_st, P_ij, lP_ij, dinv); n++; } } Inv = cgetg(lg(link), t_VEC); gel(Inv,1) = cgetg(1, t_MAT); /* dummy */ for (i = 2; i < lg(link); i++) { GEN M, inv, B = gel(link,i); long j, lB = lg(B); if (i == s) { B = vecsplice(B, t); lB--; } /* remove phi_st */ M = cgetg(lB, t_MAT); for (j = 1; j < lB; j++) { GEN phi_ij = gel(basis, B[j]), pols = gel(phi_ij,3); gel(M, j) = gel(pols, 2); /* phi_ij(g_i) */ } if (i <= nbE1 && i != s) /* maximal rank k-1 */ inv = ZM_inv_denom(M); else /* i = s (rank k-2) or from torsion: rank k/3 or k/2 */ inv = Qevproj_init(M); gel(Inv,i) = inv; } return mkvec3(WN, gen_0, mkvec5(basis, mkvecsmall2(k, dim), mkvecsmall2(s,t), link, Inv)); } static GEN add_star(GEN W, long sign) { GEN s = msstar_i(W); GEN K = sign? QM_ker(gsubgs(s, sign)): cgetg(1,t_MAT); gel(W,2) = mkvec3(stoi(sign), s, Qevproj_init(K)); return W; } /* WN = msinit_N(N) */ static GEN mskinit(ulong N, long k, long sign) { GEN W, WN = msinit_N(N); if (N == 1) { GEN basis, M = RgXV_to_RgM(mfperiodpolbasis(k, 0), k-1); GEN T = cgetg(1, t_VECSMALL), ind = mkvecsmall(1); long i, l = lg(M); basis = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(basis,i) = mkvec3(T, ind, mkvec(gel(M,i))); W = mkvec3(WN, gen_0, mkvec5(basis, mkvecsmall2(k, l-1), mkvecsmall2(0,0), gen_0, Qevproj_init(M))); } else W = k == 2? mskinit_trivial(WN) : mskinit_nontrivial(WN, k); return add_star(W, sign); } GEN msinit(GEN N, GEN K, long s) { pari_sp av = avma; GEN W; long k; if (typ(N) != t_INT) pari_err_TYPE("msinit", N); if (typ(K) != t_INT) pari_err_TYPE("msinit", K); k = itos(K); if (k < 2) pari_err_DOMAIN("msinit","k", "<", gen_2,K); if (odd(k)) pari_err_IMPL("msinit [odd weight]"); if (signe(N) <= 0) pari_err_DOMAIN("msinit","N", "<=", gen_0,N); if (labs(s) > 1) pari_err_DOMAIN("msinit", "|sign|", ">", gen_1, stoi(s)); W = mskinit(itou(N), k, s); return gerepilecopy(av, W); } /* W = msinit, xpm integral modular symbol of weight 2, c t_FRAC * Return image of c> */ GEN mseval2_ooQ(GEN W, GEN xpm, GEN c) { pari_sp av = avma; GEN v; W = get_msN(W); v = init_act_trivial(W); Q_log_trivial(v, W, c); /* oo -> (a:b), c = a/b */ return gerepileuptoint(av, ZV_zc_mul(xpm, v)); } static GEN eval_single(GEN s, long k, GEN B, long v) { long i, l; GEN A = cgetg_copy(s,&l); for (i=1; i 0 && o) || (s < 0 && !o) || itos(zncharconductor(G, chi)) != f) continue; S = seval(G, chi, vx); if (!S) { set_avma(av2); continue; } L = lfuntwist(LE, mkvec2(G, zncharconj(G,chi)), bit); z = lfun(L, gen_1, bit); tau = znchargauss(G, chi, gen_1, bit); return gdiv(gmul(z, tau), S); /* C * w */ } set_avma(av); } } static GEN ell_get_scale(GEN LE, GEN W, long sign, GEN x) { if (sign) return ell_get_Cw(LE, W, gel(x,1), sign); else { GEN Cwp = ell_get_Cw(LE, W, gel(x,1), 1); GEN Cwm = ell_get_Cw(LE, W, gel(x,2),-1); return mkvec2(Cwp, Cwm); } } /* E minimal */ static GEN msfromell_scale(GEN x, GEN Cw, GEN E, long s) { GEN B = int2n(32); if (s) { GEN C = gdiv(Cw, ellQtwist_bsdperiod(E,s)); return ZC_Q_mul(gel(x,1), bestappr(C,B)); } else { GEN xp = gel(x,1), Cp = gdiv(gel(Cw,1), ellQtwist_bsdperiod(E, 1)), L; GEN xm = gel(x,2), Cm = gdiv(gel(Cw,2), ellQtwist_bsdperiod(E,-1)); xp = ZC_Q_mul(xp, bestappr(Cp,B)); xm = ZC_Q_mul(xm, bestappr(Cm,B)); if (signe(ell_get_disc(E)) > 0) L = mkmat2(xp, xm); /* E(R) has 2 connected components */ else L = mkmat2(gsub(xp,xm), gmul2n(xm,1)); return mkvec3(xp, xm, L); } } /* v != 0 */ static GEN Flc_normalize(GEN v, ulong p) { long i, l = lg(v); for (i = 1; i < l; i++) if (v[i]) { if (v[i] != 1) v = Flv_Fl_div(v, v[i], p); return v; } return NULL; } /* K \cap Ker M [F_l vector spaces]. K = NULL means full space */ static GEN msfromell_ker(GEN K, GEN M, ulong l) { GEN B, Ml = ZM_to_Flm(M, l); if (K) Ml = Flm_mul(Ml, K, l); B = Flm_ker(Ml, l); if (!K) K = B; else if (lg(B) < lg(K)) K = Flm_mul(K, B, l); return K; } /* K = \cap_p Ker(T_p - a_p), 2-dimensional. Set *xl to the 1-dimensional * Fl-basis such that star . xl = sign . xl if sign != 0 and * star * xl[1] = xl[1]; star * xl[2] = -xl[2] if sign = 0 */ static void msfromell_l(GEN *pxl, GEN K, GEN star, long sign, ulong l) { GEN s = ZM_to_Flm(star, l); GEN a = gel(K,1), Sa = Flm_Flc_mul(s,a,l); GEN b = gel(K,2); GEN t = Flv_add(a,Sa,l), xp, xm; if (zv_equal0(t)) { xm = a; xp = Flv_add(b,Flm_Flc_mul(s,b,l), l); } else { xp = t; t = Flv_sub(a, Sa, l); xm = zv_equal0(t)? Flv_sub(b, Flm_Flc_mul(s,b,l), l): t; } /* xp = 0 on Im(S - 1), xm = 0 on Im(S + 1) */ if (sign > 0) *pxl = mkmat(Flc_normalize(xp, l)); else if (sign < 0) *pxl = mkmat(Flc_normalize(xm, l)); else *pxl = mkmat2(Flc_normalize(xp, l), Flc_normalize(xm, l)); } /* return a primitive symbol */ static GEN msfromell_ratlift(GEN x, GEN q) { GEN B = sqrti(shifti(q,-1)); GEN r = FpM_ratlift(x, q, B, B, NULL); if (r) r = Q_primpart(r); return r; } static int msfromell_check(GEN x, GEN vT, GEN star, long sign) { long i, l; GEN sx; if (!x) return 0; l = lg(vT); for (i = 1; i < l; i++) { GEN T = gel(vT,i); if (!gequal0(ZM_mul(T, x))) return 0; /* fail */ } sx = ZM_mul(star,x); if (sign) return ZV_equal(gel(sx,1), sign > 0? gel(x,1): ZC_neg(gel(x,1))); else return ZV_equal(gel(sx,1),gel(x,1)) && ZV_equal(gel(sx,2),ZC_neg(gel(x,2))); } GEN msfromell(GEN E0, long sign) { pari_sp av = avma, av2; GEN T, Cw, E, NE, star, q, vT, xl, xr, W, x = NULL, K = NULL; long lE, single; ulong p, l, N; forprime_t S, Sl; if (typ(E0) != t_VEC) pari_err_TYPE("msfromell",E0); lE = lg(E0); if (lE == 1) return cgetg(1,t_VEC); single = (typ(gel(E0,1)) != t_VEC); E = single ? E0: gel(E0,1); NE = ellQ_get_N(E); /* must make it integral for ellap; we have minimal model at hand */ T = obj_check(E, Q_MINIMALMODEL); if (lg(T) != 2) E = gel(T,3); N = itou(NE); av2 = avma; W = gerepilecopy(av2, mskinit(N,2,0)); star = msk_get_star(W); (void)u_forprime_init(&Sl, 1UL<<29, ULONG_MAX); /* loop for p <= count_Manin_symbols(N) / 6 would be enough */ (void)u_forprime_init(&S, 2, ULONG_MAX); vT = cgetg(1, t_VEC); l = u_forprime_next(&Sl); while( (p = u_forprime_next(&S)) ) { GEN M; if (N % p == 0) continue; av2 = avma; M = RgM_Rg_sub_shallow(mshecke_i(W, p), ellap(E, utoipos(p))); M = gerepilecopy(av2, M); vT = vec_append(vT, M); /* for certification at the end */ K = msfromell_ker(K, M, l); if (lg(K) == 3) break; } if (!p) pari_err_BUG("msfromell: ran out of primes"); /* mod one l should be enough */ msfromell_l(&xl, K, star, sign, l); x = ZM_init_CRT(xl, l); q = utoipos(l); xr = msfromell_ratlift(x, q); /* paranoia */ while (!msfromell_check(xr, vT, star, sign) && (l = u_forprime_next(&Sl)) ) { GEN K = NULL; long i, lvT = lg(vT); for (i = 1; i < lvT; i++) { K = msfromell_ker(K, gel(vT,i), l); if (lg(K) == 3) break; } if (i >= lvT) { x = NULL; continue; } msfromell_l(&xl, K, star, sign, l); ZM_incremental_CRT(&x, xl, &q, l); xr = msfromell_ratlift(x, q); } /* linear form = 0 on all Im(Tp - ap) and Im(S - sign) if sign != 0 */ Cw = ell_get_scale(lfuncreate(E), W, sign, xr); if (single) x = msfromell_scale(xr, Cw, E, sign); else { /* assume all E0[i] isogenous, given by minimal models */ GEN v = cgetg(lE, t_VEC); long i; for (i=1; ik, D = S->dim; GEN a = gcoeff(f,1,1), b = gcoeff(f,1,2); GEN c = gcoeff(f,2,1), d = gcoeff(f,2,2); GEN u, z, q = S->q, mat = cgetg(D+1, t_MAT); a = modii(a,q); c = modii(c,q); z = FpX_powu(deg1pol(c,a,0), k-2, q); /* (a+cx)^(k-2) */ /* u := (b+dx) / (a+cx) mod (q,x^D) = (b/a +d/a*x) / (1 - (-c/a)*x) */ if (!equali1(a)) { GEN ai = Fp_inv(a,q); b = Fp_mul(b,ai,q); c = Fp_mul(c,ai,q); d = Fp_mul(d,ai,q); } u = deg1pol_shallow(d, b, 0); /* multiply by 1 / (1 - (-c/a)*x) */ if (signe(c)) { GEN C = Fp_neg(c,q), v = cgetg(D+2,t_POL); v[1] = evalsigne(1)|evalvarn(0); gel(v, 2) = gen_1; gel(v, 3) = C; for (j = 4; j < D+2; j++) { GEN t = Fp_mul(gel(v,j-1), C, q); if (!signe(t)) { setlg(v,j); break; } gel(v,j) = t; } u = FpXn_mul(u, v, D, q); } for (j = 1; j <= D; j++) { gel(mat,j) = RgX_to_RgC(z, D); /* (a+cx)^(k-2) * ((b+dx)/(a+cx))^(j-1) */ if (j != D) z = FpXn_mul(z, u, D, q); } return shallowtrans(mat); } static GEN moments_act(struct m_act *S, GEN f) { pari_sp av = avma; return gerepilecopy(av, moments_act_i(S,f)); } static GEN init_moments_act(GEN W, long p, long n, GEN q, GEN v) { struct m_act S; long k = msk_get_weight(W); S.p = p; S.k = k; S.q = q; S.dim = n+k-1; S.act = &moments_act; return init_dual_act(v,W,W,&S); } static void clean_tail(GEN phi, long c, GEN q) { long a, l = lg(phi); for (a = 1; a < l; a++) { GEN P = FpC_red(gel(phi,a), q); /* phi(G_a) = vector of moments */ long j, lP = lg(P); for (j = c; j < lP; j++) gel(P,j) = gen_0; /* reset garbage to 0 */ gel(phi,a) = P; } } /* concat z to all phi[i] */ static GEN concat2(GEN phi, GEN z) { long i, l; GEN v = cgetg_copy(phi,&l); for (i = 1; i < l; i++) gel(v,i) = shallowconcat(gel(phi,i), z); return v; } static GEN red_mod_FilM(GEN phi, ulong p, long k, long flag) { long a, l; GEN den = gen_1, v = cgetg_copy(phi, &l); if (flag) { phi = Q_remove_denom(phi, &den); if (!den) { den = gen_1; flag = 0; } } for (a = 1; a < l; a++) { GEN P = gel(phi,a), q = den; long j; for (j = lg(P)-1; j >= k+1; j--) { q = muliu(q,p); gel(P,j) = modii(gel(P,j),q); } q = muliu(q,p); for ( ; j >= 1; j--) gel(P,j) = modii(gel(P,j),q); gel(v,a) = P; } if (flag) v = gdiv(v, den); return v; } /* denom(C) | p^(2(k-1) - v_p(ap)) */ static GEN oms_dim2(GEN W, GEN phi, GEN C, GEN ap) { long t, i, k = mspadic_get_weight(W); long p = mspadic_get_p(W), n = mspadic_get_n(W); GEN phi1 = gel(phi,1), phi2 = gel(phi,2); GEN v, q = mspadic_get_q(W); GEN act = mspadic_get_actUp(W); t = signe(ap)? Z_lval(ap,p) : k-1; phi1 = concat2(phi1, zerovec(n)); phi2 = concat2(phi2, zerovec(n)); for (i = 1; i <= n; i++) { phi1 = dual_act(k-1, act, phi1); phi1 = dual_act(k-1, act, phi1); clean_tail(phi1, k + i*t, q); phi2 = dual_act(k-1, act, phi2); phi2 = dual_act(k-1, act, phi2); clean_tail(phi2, k + i*t, q); } C = gpowgs(C,n); v = RgM_RgC_mul(C, mkcol2(phi1,phi2)); phi1 = red_mod_FilM(gel(v,1), p, k, 1); phi2 = red_mod_FilM(gel(v,2), p, k, 1); return mkvec2(phi1,phi2); } /* flag = 0 iff alpha is a p-unit */ static GEN oms_dim1(GEN W, GEN phi, GEN alpha, long flag) { long i, k = mspadic_get_weight(W); long p = mspadic_get_p(W), n = mspadic_get_n(W); GEN q = mspadic_get_q(W); GEN act = mspadic_get_actUp(W); phi = concat2(phi, zerovec(n)); for (i = 1; i <= n; i++) { phi = dual_act(k-1, act, phi); clean_tail(phi, k + i, q); } phi = gmul(lift_shallow(gpowgs(alpha,n)), phi); phi = red_mod_FilM(phi, p, k, flag); return mkvec(phi); } /* lift polynomial P in RgX[X,Y]_{k-2} to a distribution \mu such that * \int (Y - X z)^(k-2) d\mu(z) = P(X,Y) * Return the t_VEC of k-1 first moments of \mu: \int z^i d\mu(z), 0<= i < k-1. * \sum_j (-1)^(k-2-j) binomial(k-2,j) Y^j \int z^(k-2-j) d\mu(z) = P(1,Y) * Input is P(1,Y), bin = vecbinomial(k-2): bin[j] = binomial(k-2,j-1) */ static GEN RgX_to_moments(GEN P, GEN bin) { long j, k = lg(bin); GEN Pd, Bd; if (typ(P) != t_POL) P = scalarpol(P,0); P = RgX_to_RgC(P, k-1); /* deg <= k-2 */ settyp(P, t_VEC); Pd = P+1; /* Pd[i] = coeff(P,i) */ Bd = bin+1;/* Bd[i] = binomial(k-2,i) */ for (j = 1; j < k-2; j++) { GEN c = gel(Pd,j); if (odd(j)) c = gneg(c); gel(Pd,j) = gdiv(c, gel(Bd,j)); } return vecreverse(P); } static GEN RgXC_to_moments(GEN v, GEN bin) { long i, l; GEN w = cgetg_copy(v,&l); for (i=1; iq): zerocol(S->dim); } return v; } GEN msomseval(GEN W, GEN phi, GEN path) { struct m_act S; pari_sp av = avma; GEN v, Wp; long n, vden; checkmspadic(W); if (typ(phi) != t_COL || lg(phi) != 4) pari_err_TYPE("msomseval",phi); vden = itos(gel(phi,2)); phi = gel(phi,1); n = mspadic_get_n(W); Wp= mspadic_get_Wp(W); S.k = mspadic_get_weight(W); S.p = mspadic_get_p(W); S.q = powuu(S.p, n+vden); S.dim = n + S.k - 1; S.act = &moments_act; path = path_to_M2(path); v = omseval_int(&S, phi, M2_logf(Wp,path,NULL), NULL); return gerepilecopy(av, v); } /* W = msinit(N,k,...); if flag < 0 or flag >= k-1, allow all symbols; * else commit to v_p(a_p) <= flag (ordinary if flag = 0)*/ GEN mspadicinit(GEN W, long p, long n, long flag) { pari_sp av = avma; long a, N, k; GEN P, C, M, bin, Wp, Tp, q, pn, actUp, teich, pas; checkms(W); N = ms_get_N(W); k = msk_get_weight(W); if (flag < 0) flag = 1; /* worst case */ else if (flag >= k) flag = k-1; bin = vecbinomial(k-2); Tp = mshecke(W, p, NULL); if (N % p == 0) { if ((N/p) % p == 0) pari_err_IMPL("mspadicinit when p^2 | N"); /* a_p != 0 */ Wp = W; M = gen_0; flag = (k-2) / 2; /* exact valuation */ /* will multiply by matrix with denominator p^(k-2)/2 in mspadicint. * Except if p = 2 (multiply by alpha^2) */ if (p == 2) n += k-2; else n += (k-2)/2; pn = powuu(p,n); /* For accuracy mod p^n, oms_dim1 require p^(k/2*n) */ q = powiu(pn, k/2); } else { /* p-stabilize */ long s = msk_get_sign(W); GEN M1, M2; Wp = mskinit(N*p, k, s); M1 = getMorphism(W, Wp, mkvec(mat2(1,0,0,1))); M2 = getMorphism(W, Wp, mkvec(mat2(p,0,0,1))); if (s) { GEN SW = msk_get_starproj(W), SWp = msk_get_starproj(Wp); M1 = Qevproj_apply2(M1, SW, SWp); M2 = Qevproj_apply2(M2, SW, SWp); } M = mkvec2(M1,M2); n += Z_lval(Q_denom(M), p); /*den. introduced by p-stabilization*/ /* in supersingular case: will multiply by matrix with denominator p^k * in mspadicint. Except if p = 2 (multiply by alpha^2) */ if (flag) { if (p == 2) n += 2*k-2; else n += k; } pn = powuu(p,n); /* For accuracy mod p^n, supersingular require p^((2k-1-v_p(a_p))*n) */ if (flag) /* k-1 also takes care of a_p = 0. Worst case v_p(a_p) = flag */ q = powiu(pn, 2*k-1 - flag); else q = pn; } actUp = init_moments_act(Wp, p, n, q, Up_matrices(p)); if (p == 2) C = gen_0; else { pas = matpascal(n); teich = teichmullerinit(p, n+1); P = gpowers(utoipos(p), n); C = cgetg(p, t_VEC); for (a = 1; a < p; a++) { /* powb[j+1] = ((a - w(a)) / p)^j mod p^n */ GEN powb = Fp_powers(diviuexact(subui(a, gel(teich,a)), p), n, pn); GEN Ca = cgetg(n+2, t_VEC); long j, r, ai = Fl_inv(a, p); /* a^(-1) */ gel(C,a) = Ca; for (j = 0; j <= n; j++) { GEN Caj = cgetg(j+2, t_VEC); GEN atij = gel(teich, Fl_powu(ai,j,p));/* w(a)^(-j) = w(a^(-j) mod p) */ gel(Ca,j+1) = Caj; for (r = 0; r <= j; r++) { GEN c = Fp_mul(gcoeff(pas,j+1,r+1), gel(powb, j-r+1), pn); c = Fp_mul(c,atij,pn); /* binomial(j,r)*b^(j-r)*w(a)^(-j) mod p^n */ gel(Caj,r+1) = mulii(c, gel(P,j+1)); /* p^j * c mod p^(n+j) */ } } } } return gerepilecopy(av, mkvecn(8, Wp,Tp, bin, actUp, q, mkvecsmall3(p,n,flag), M, C)); } #if 0 /* assume phi an ordinary OMS */ static GEN omsactgl2(GEN W, GEN phi, GEN M) { GEN q, Wp, act; long p, k, n; checkmspadic(W); Wp = mspadic_get_Wp(W); p = mspadic_get_p(W); k = mspadic_get_weight(W); n = mspadic_get_n(W); q = mspadic_get_q(W); act = init_moments_act(Wp, p, n, q, M); phi = gel(phi,1); return dual_act(k-1, act, gel(phi,1)); } #endif static GEN eigenvalue(GEN T, GEN x) { long i, l = lg(x); for (i = 1; i < l; i++) if (!isintzero(gel(x,i))) break; if (i == l) pari_err_DOMAIN("mstooms", "phi", "=", gen_0, x); return gdiv(RgMrow_RgC_mul(T,x,i), gel(x,i)); } /* p coprime to ap, return unit root of x^2 - ap*x + p^(k-1), accuracy p^n */ GEN mspadic_unit_eigenvalue(GEN ap, long k, GEN p, long n) { GEN sqrtD, D = subii(sqri(ap), shifti(powiu(p,k-1),2)); if (absequaliu(p,2)) { n++; sqrtD = Zp_sqrt(D, p, n); if (mod4(sqrtD) != mod4(ap)) sqrtD = negi(sqrtD); } else sqrtD = Zp_sqrtlift(D, ap, p, n); /* sqrtD = ap (mod p) */ return gmul2n(gadd(ap, cvtop(sqrtD,p,n)), -1); } /* W = msinit(N,k,...); phi = T_p/U_p - eigensymbol */ GEN mstooms(GEN W, GEN phi) { pari_sp av = avma; GEN Wp, bin, Tp, c, alpha, ap, phi0, M; long k, p, vden; checkmspadic(W); if (typ(phi) != t_COL) { if (!is_Qevproj(phi)) pari_err_TYPE("mstooms",phi); phi = gel(phi,1); if (lg(phi) != 2) pari_err_TYPE("mstooms [dim_Q (eigenspace) > 1]",phi); phi = gel(phi,1); } Wp = mspadic_get_Wp(W); Tp = mspadic_get_Tp(W); bin = mspadic_get_bin(W); k = msk_get_weight(Wp); p = mspadic_get_p(W); M = mspadic_get_M(W); phi = Q_remove_denom(phi, &c); ap = eigenvalue(Tp, phi); vden = c? Z_lvalrem(c, p, &c): 0; if (typ(M) == t_INT) { /* p | N */ GEN c1; alpha = ap; alpha = ginv(alpha); phi0 = mseval(Wp, phi, NULL); phi0 = RgXC_to_moments(phi0, bin); phi0 = Q_remove_denom(phi0, &c1); if (c1) { vden += Z_lvalrem(c1, p, &c1); c = mul_denom(c,c1); } if (umodiu(ap,p)) /* p \nmid a_p */ phi = oms_dim1(W, phi0, alpha, 0); else { phi = oms_dim1(W, phi0, alpha, 1); phi = Q_remove_denom(phi, &c1); if (c1) { vden += Z_lvalrem(c1, p, &c1); c = mul_denom(c,c1); } } } else { /* p-stabilize */ GEN M1, M2, phi1, phi2, c1; if (typ(M) != t_VEC || lg(M) != 3) pari_err_TYPE("mstooms",W); M1 = gel(M,1); M2 = gel(M,2); phi1 = RgM_RgC_mul(M1, phi); phi2 = RgM_RgC_mul(M2, phi); phi1 = mseval(Wp, phi1, NULL); phi2 = mseval(Wp, phi2, NULL); phi1 = RgXC_to_moments(phi1, bin); phi2 = RgXC_to_moments(phi2, bin); phi = Q_remove_denom(mkvec2(phi1,phi2), &c1); phi1 = gel(phi,1); phi2 = gel(phi,2); if (c1) { vden += Z_lvalrem(c1, p, &c1); c = mul_denom(c,c1); } /* all polynomials multiplied by c p^vden */ if (umodiu(ap, p)) { alpha = mspadic_unit_eigenvalue(ap, k, utoipos(p), mspadic_get_n(W)); alpha = ginv(alpha); phi0 = gsub(phi1, gmul(lift_shallow(alpha),phi2)); phi = oms_dim1(W, phi0, alpha, 0); } else { /* p | ap, alpha = [a_p, -1; p^(k-1), 0] */ long flag = mspadic_get_flag(W); if (!flag || (signe(ap) && Z_lval(ap,p) < flag)) pari_err_TYPE("mstooms [v_p(ap) > mspadicinit flag]", phi); alpha = mkmat22(ap,gen_m1, powuu(p, k-1),gen_0); alpha = ginv(alpha); phi = oms_dim2(W, mkvec2(phi1,phi2), gsqr(alpha), ap); phi = Q_remove_denom(phi, &c1); if (c1) { vden += Z_lvalrem(c1, p, &c1); c = mul_denom(c,c1); } } } if (vden) c = mul_denom(c, powuu(p,vden)); if (p == 2) alpha = gsqr(alpha); if (c) alpha = gdiv(alpha,c); if (typ(alpha) == t_MAT) { /* express in basis (omega,-p phi(omega)) */ gcoeff(alpha,2,1) = gdivgs(gcoeff(alpha,2,1), -p); gcoeff(alpha,2,2) = gdivgs(gcoeff(alpha,2,2), -p); /* at the end of mspadicint we shall multiply result by [1,0;0,-1/p]*alpha * vden + k is the denominator of this matrix */ } /* phi is integral-valued */ return gerepilecopy(av, mkcol3(phi, stoi(vden), alpha)); } /* HACK: the v[j] have different lengths */ static GEN FpVV_dotproduct(GEN v, GEN w, GEN p) { long j, l = lg(v); GEN T = cgetg(l, t_VEC); for (j = 1; j < l; j++) gel(T,j) = FpV_dotproduct(gel(v,j),w,p); return T; } /* \int (-4z)^j given \int z^j */ static GEN twistmoment_m4(GEN v) { long i, l; GEN w = cgetg_copy(v, &l); for (i = 1; i < l; i++) { GEN c = gel(v,i); if (i > 1) c = gmul2n(c, (i-1)<<1); gel(w,i) = odd(i)? c: gneg(c); } return w; } /* \int (4z)^j given \int z^j */ static GEN twistmoment_4(GEN v) { long i, l; GEN w = cgetg_copy(v, &l); for (i = 1; i < l; i++) { GEN c = gel(v,i); if (i > 1) c = gmul2n(c, (i-1)<<1); gel(w,i) = c; } return w; } /* W an mspadic, phi eigensymbol, p \nmid D. Return C(x) mod FilM */ GEN mspadicmoments(GEN W, GEN PHI, long D) { pari_sp av = avma; long na, ia, b, lphi, aD = labs(D), pp, p, k, n, vden; GEN Wp, Dact, vL, v, C, pn, phi; struct m_act S; hashtable *H; checkmspadic(W); Wp = mspadic_get_Wp(W); p = mspadic_get_p(W); k = mspadic_get_weight(W); n = mspadic_get_n(W); C = mspadic_get_C(W); if (typ(PHI) != t_COL || lg(PHI) != 4 || typ(gel(PHI,1)) != t_VEC) PHI = mstooms(W, PHI); vden = itos( gel(PHI,2) ); phi = gel(PHI,1); lphi = lg(phi); if (p == 2) { na = 2; pp = 4; } else { na = p-1; pp = p; } pn = powuu(p, n + vden); S.p = p; S.k = k; S.q = pn; S.dim = n+k-1; S.act = &moments_act; H = Gl2act_cache(ms_get_nbgen(Wp)); if (D == 1) Dact = NULL; else { GEN gaD = utoi(aD), Dk = Fp_pows(stoi(D), 2-k, pn); if (!sisfundamental(D)) pari_err_TYPE("mspadicmoments", stoi(D)); if (D % p == 0) pari_err_DOMAIN("mspadicmoments","p","|", stoi(D), utoi(p)); Dact = cgetg(aD, t_VEC); for (b = 1; b < aD; b++) { GEN z = NULL; long s = kross(D, b); if (s) { pari_sp av2 = avma; GEN d; z = moments_act_i(&S, mkmat22(gaD,utoipos(b), gen_0,gaD)); d = s > 0? Dk: Fp_neg(Dk, pn); z = equali1(d)? gerepilecopy(av2, z) : gerepileupto(av2, FpM_Fp_mul(z, d, pn)); } gel(Dact,b) = z; } } vL = cgetg(na+1,t_VEC); /* first pass to precompute log(paths), preload matrices and allow GC later */ for (ia = 1; ia <= na; ia++) { GEN path, La; long a = (p == 2 && ia == 2)? -1: ia; if (Dact) { /* twist by D */ La = cgetg(aD, t_VEC); for (b = 1; b < aD; b++) { GEN Actb = gel(Dact,b); if (!Actb) continue; /* oo -> a/pp + b/|D|*/ path = mkmat22(gen_1, addii(mulss(a, aD), muluu(pp, b)), gen_0, muluu(pp, aD)); gel(La,b) = M2_logf(Wp,path,NULL); ZGl2QC_preload(&S, gel(La,b), H); } } else { path = mkmat22(gen_1,stoi(a), gen_0, utoipos(pp)); La = M2_logf(Wp,path,NULL); ZGl2QC_preload(&S, La, H); } gel(vL,ia) = La; } v = cgetg(na+1,t_VEC); /* second pass, with GC */ for (ia = 1; ia <= na; ia++) { pari_sp av2 = avma; GEN vca, Ca = gel(C,ia), La = gel(vL,ia), va = cgetg(lphi, t_VEC); long i; if (!Dact) vca = omseval_int(&S, phi, La, H); else { /* twist by D */ vca = cgetg(lphi,t_VEC); for (b = 1; b < aD; b++) { GEN T, Actb = gel(Dact,b); if (!Actb) continue; T = omseval_int(&S, phi, gel(La,b), H); for (i = 1; i < lphi; i++) { GEN z = FpM_FpC_mul(Actb, gel(T,i), pn); gel(vca,i) = b==1? z: ZC_add(gel(vca,i), z); } } } if (p != 2) { for (i=1; i= n) break; /* S = log(1+x)^j */ gel(vlog,j+1) = mspadicint(oms,teichi,S); S = S? RgXn_mul(S, L, n+1): L; } m = j; u = utoipos(p == 2? 5: 1+p); logu = glog(cvtop(u, utoipos(p), 4*m), 0); X = gdiv(pol_x(0), logu); s = cgetg(m+1, t_VEC); s2 = oms_is_supersingular(oms)? cgetg(m+1, t_VEC): NULL; bin = pol_1(0); for (j = 0; j < m; j++) { /* bin = binomial(x/log(1+p+O(p^(4*n))), j) mod x^m */ GEN a, v = mspadicint_RgXlog(bin, vlog); int done = 1; gel(s,j+1) = a = gel(v,1); if (!gequal0(a) || valp(a) > 0) done = 0; else setlg(s,j+1); if (s2) { gel(s2,j+1) = a = gel(v,2); if (!gequal0(a) || valp(a) > 0) done = 0; else setlg(s2,j+1); } if (done || j == m-1) break; bin = RgXn_mul(bin, gdivgu(gsubgs(X, j), j+1), m); } s = RgV_to_ser(s,0,lg(s)+1); if (s2) { s2 = RgV_to_ser(s2,0,lg(s2)+1); s = mkvec2(s, s2); } if (kross(oms_get_D(oms), p) >= 0) return gerepilecopy(av, s); return gerepileupto(av, gneg(s)); } void mspadic_parse_chi(GEN s, GEN *s1, GEN *s2) { if (!s) *s1 = *s2 = gen_0; else switch(typ(s)) { case t_INT: *s1 = *s2 = s; break; case t_VEC: if (lg(s) == 3) { *s1 = gel(s,1); *s2 = gel(s,2); if (typ(*s1) == t_INT && typ(*s2) == t_INT) break; } default: pari_err_TYPE("mspadicL",s); *s1 = *s2 = NULL; } } /* oms from mspadicmoments * r-th derivative of L(f,chi^s,psi) in direction - s \in Z_p \times \Z/(p-1)\Z, s-> chi^s=<\chi>^s_1 omega^s_2) - Z -> Z_p \times \Z/(p-1)\Z par s-> (s, s mod p-1). */ GEN mspadicL(GEN oms, GEN s, long r) { pari_sp av = avma; GEN s1, s2, z, S; long p, n, teich; checkoms(oms); p = oms_get_p(oms); n = oms_get_n(oms); mspadic_parse_chi(s, &s1,&s2); teich = umodiu(subii(s2,s1), p==2? 2: p-1); S = xlog1x(n, itos(s1), r, &teich); z = mspadicint(oms, teich, S); if (lg(z) == 2) z = gel(z,1); if (kross(oms_get_D(oms), p) < 0) z = gneg(z); return gerepilecopy(av, z); } /****************************************************************************/ struct siegel { GEN V, Ast; long N; /* level */ long oo; /* index of the [oo,0] path */ long k1, k2; /* two distinguished indices */ long n; /* #W, W = initial segment [in siegelstepC] already normalized */ }; static void siegel_init(struct siegel *C, GEN M) { GEN CPI, CP, MM, V, W, Ast; GEN m = gel(M,11), M2 = gel(M,2), S = msN_get_section(M); GEN E2fromE1 = msN_get_E2fromE1(M); long m0 = lg(M2)-1; GEN E2 = vecslice(M2, m[1]+1, m[2]);/* E2 */ GEN E1T = vecslice(M2, m[3]+1, m0); /* E1,T2,T31 */ GEN L = shallowconcat(E1T, E2); long i, l = lg(L), n = lg(E1T)-1, lE = lg(E2); Ast = cgetg(l, t_VECSMALL); for (i = 1; i < lE; ++i) { long j = E2fromE1_c(gel(E2fromE1,i)); Ast[n+i] = j; Ast[j] = n+i; } for (; i<=n; ++i) Ast[i] = i; MM = cgetg (l,t_VEC); for (i = 1; i < l; i++) { GEN c = gel(S, L[i]); long c12, c22, c21 = ucoeff(c,2,1); if (!c21) { gel(MM,i) = gen_0; continue; } c22 = ucoeff(c,2,2); if (!c22) { gel(MM,i) = gen_m1; continue; } c12 = ucoeff(c,1,2); gel(MM,i) = sstoQ(c12, c22); /* right extremity > 0 */ } CP = indexsort(MM); CPI = cgetg(l, t_VECSMALL); V = cgetg(l, t_VEC); W = cgetg(l, t_VECSMALL); for (i = 1; i < l; ++i) { gel(V,i) = mat2_to_ZM(gel(S, L[CP[i]])); CPI[CP[i]] = i; } for (i = 1; i < l; ++i) W[CPI[i]] = CPI[Ast[i]]; C->V = V; C->Ast = W; C->n = 0; C->oo = 2; C->N = ms_get_N(M); } static double ZMV_size(GEN v) { long i, l = lg(v); GEN z = cgetg(l, t_VECSMALL); for (i = 1; i < l; i++) z[i] = gexpo(gel(v,i)); return ((double)zv_sum(z)) / (4*(l-1)); } /* apply permutation perm to struct S. Don't follow k1,k2 */ static void siegel_perm0(struct siegel *S, GEN perm) { pari_sp av = avma; long i, l = lg(S->V); GEN V2 = cgetg(l, t_VEC), Ast2 = cgetg(l, t_VECSMALL); GEN V = S->V, Ast = S->Ast; for (i = 1; i < l; i++) gel(V2,perm[i]) = gel(V,i); for (i = 1; i < l; i++) Ast2[perm[i]] = perm[Ast[i]]; for (i = 1; i < l; i++) { S->Ast[i] = Ast2[i]; gel(V,i) = gel(V2,i); } set_avma(av); S->oo = perm[S->oo]; } /* apply permutation perm to full struct S */ static void siegel_perm(struct siegel *S, GEN perm) { siegel_perm0(S, perm); S->k1 = perm[S->k1]; S->k2 = perm[S->k2]; } /* cyclic permutation of lg = l-1 moving a -> 1, a+1 -> 2, etc. */ static GEN rotate_perm(long l, long a) { GEN p = cgetg(l, t_VECSMALL); long i, j = 1; for (i = a; i < l; i++) p[i] = j++; for (i = 1; i < a; i++) p[i] = j++; return p; } /* a1 < c1 <= a2 < c2*/ static GEN basic_op_perm(long l, long a1, long a2, long c1, long c2) { GEN p = cgetg(l, t_VECSMALL); long i, j = 1; p[a1] = j++; for (i = c1; i < a2; i++) p[i] = j++; for (i = a1+1; i < c1; i++) p[i] = j++; p[a2] = j++; for (i = c2; i < l; i++) p[i] = j++; for (i = 1; i < a1; i++) p[i] = j++; for (i = a2+1; i < c2; i++) p[i] = j++; return p; } static GEN basic_op_perm_elliptic(long l, long a1) { GEN p = cgetg(l, t_VECSMALL); long i, j = 1; p[a1] = j++; for (i = 1; i < a1; i++) p[i] = j++; for (i = a1+1; i < l; i++) p[i] = j++; return p; } static GEN ZM2_rev(GEN T) { return mkmat2(gel(T,2), ZC_neg(gel(T,1))); } /* In place, V = vector of consecutive paths, between x <= y. * V[x..y-1] <- g*V[x..y-1] */ static void path_vec_mul(GEN V, long x, long y, GEN g) { long j; GEN M; if (x == y) return; M = gel(V,x); gel(V,x) = ZM_mul(g,M); for (j = x+1; j < y; j++) /* V[j] <- g*V[j], optimized */ { GEN Mnext = gel(V,j); /* Mnext[,1] = M[,2] */ GEN gM = gel(V,j-1), u = gel(gM,2); if (!ZV_equal(gel(M,2), gel(Mnext,1))) u = ZC_neg(u); gel(V,j) = mkmat2(u, ZM_ZC_mul(g,gel(Mnext,2))); M = Mnext; } } static long prev(GEN V, long i) { return (i == 1)? lg(V)-1: i-1; } static long next(GEN V, long i) { return (i == lg(V)-1)? 1: i+1; } static GEN ZM_det2(GEN u, GEN v) { GEN a = gel(u,1), c = gel(u,2); GEN b = gel(v,1), d = gel(v,2); return subii(mulii(a,d), mulii(b,c)); } static GEN ZM2_det(GEN T) { return ZM_det2(gel(T,1),gel(T,2)); } static long ZM_det2_sign(GEN u, GEN v) { pari_sp av = avma; long s = signe(ZM_det2(u, v)); return gc_long(av, s); } static void fill1(GEN V, long a) { long p = prev(V,a), n = next(V,a); GEN u = gmael(V,p,2), v = gmael(V,n,1); if (ZM_det2_sign(u,v) < 0) v = ZC_neg(v); gel(V,a) = mkmat2(u, v); } /* a1 < a2 */ static void fill2(GEN V, long a1, long a2) { if (a2 != a1+1) { fill1(V,a1); fill1(V,a2); } /* non adjacent, reconnect */ else { /* parabolic */ long p = prev(V,a1), n = next(V,a2); GEN u, v, C = gmael(V,a1,2), mC = NULL; /* = \pm V[a2][1] */ u = gmael(V,p,2); v = C; if (ZM_det2_sign(u,v) < 0) v = mC = ZC_neg(C); gel(V,a1) = mkmat2(u,v); v = gmael(V,n,1); u = C; if (ZM_det2_sign(u,v) < 0) u = mC? mC: ZC_neg(C); gel(V,a2) = mkmat2(u,v); } } /* DU = det(U), return g = T*U^(-1) or NULL if not in Gamma0(N); if N = 0, * only test whether g is integral */ static GEN ZM2_div(GEN T, GEN U, GEN DU, long N) { GEN a=gcoeff(U,1,1), b=gcoeff(U,1,2), c=gcoeff(U,2,1), d=gcoeff(U,2,2); GEN e=gcoeff(T,1,1), f=gcoeff(T,1,2), g=gcoeff(T,2,1), h=gcoeff(T,2,2); GEN A, B, C, D, r; C = dvmdii(subii(mulii(d,g), mulii(c,h)), DU, &r); if (r != gen_0 || (N && smodis(C,N))) return NULL; A = dvmdii(subii(mulii(d,e), mulii(c,f)), DU, &r); if (r != gen_0) return NULL; B = dvmdii(subii(mulii(a,f), mulii(b,e)), DU, &r); if (r != gen_0) return NULL; D = dvmdii(subii(mulii(a,h), mulii(g,b)), DU, &r); if (r != gen_0) return NULL; retmkmat22(A,B,C,D); } static GEN get_g(struct siegel *S, long a1) { pari_sp av = avma; long a2 = S->Ast[a1]; GEN a = gel(S->V,a1), ar = ZM2_rev(gel(S->V,a2)), Dar = ZM2_det(ar); GEN g = ZM2_div(a, ar, Dar, S->N); if (!g) { GEN tau = mkmat22(gen_0,gen_m1, gen_1,gen_m1); /*[0,-1;1,-1]*/ g = ZM2_div(ZM_mul(ar, tau), ar, Dar, 0); } return gerepilecopy(av, g); } /* input V = (X1 a X2 | X3 a^* X4) + Ast * a1 = index of a * a2 = index of a^*, inferred from a1. We must have a != a^* * c1 = first cut [ index of first path in X3 ] * c2 = second cut [ either in X4 or X1, index of first path ] * Assume a < a^* (cf Paranoia below): c1 or c2 must be in * ]a,a^*], and the other in the "complement" ]a^*,a] */ static void basic_op(struct siegel *S, long a1, long c1, long c2) { pari_sp av; long l = lg(S->V), a2 = S->Ast[a1]; GEN g; if (a1 == a2) { /* a = a^* */ g = get_g(S, a1); path_vec_mul(S->V, a1+1, l, g); av = avma; siegel_perm(S, basic_op_perm_elliptic(l, a1)); /* fill the hole left at a1, reconnect the path */ set_avma(av); fill1(S->V, a1); return; } /* Paranoia: (a,a^*) conjugate, call 'a' the first one */ if (a2 < a1) lswap(a1,a2); /* Now a1 < a2 */ if (c1 <= a1 || c1 > a2) lswap(c1,c2); /* ensure a1 < c1 <= a2 */ if (c2 < a1) { /* if cut c2 is in X1 = X11|X12, rotate to obtain (a X2 | X3 a^* X4 X11|X12): then a1 = 1 */ GEN p; av = avma; p = rotate_perm(l, a1); siegel_perm(S, p); a1 = 1; /* = p[a1] */ a2 = S->Ast[1]; /* > a1 */ c1 = p[c1]; c2 = p[c2]; set_avma(av); } /* Now a1 < c1 <= a2 < c2; a != a^* */ g = get_g(S, a1); if (S->oo >= c1 && S->oo < c2) /* W inside [c1..c2[ */ { /* c2 -> c1 excluding a1 */ GEN gi = SL2_inv_shallow(g); /* g a^* = a; gi a = a^* */ path_vec_mul(S->V, 1, a1, gi); path_vec_mul(S->V, a1+1, c1, gi); path_vec_mul(S->V, c2, l, gi); } else { /* c1 -> c2 excluding a2 */ path_vec_mul(S->V, c1, a2, g); path_vec_mul(S->V, a2+1, c2, g); } av = avma; siegel_perm(S, basic_op_perm(l, a1,a2, c1,c2)); set_avma(av); /* fill the holes left at a1,a2, reconnect the path */ fill2(S->V, a1, a2); } /* a = a^* (elliptic case) */ static void basic_op_elliptic(struct siegel *S, long a1) { pari_sp av; long l = lg(S->V); GEN g = get_g(S, a1); path_vec_mul(S->V, a1+1, l, g); av = avma; siegel_perm(S, basic_op_perm_elliptic(l, a1)); /* fill the hole left at a1 (now at 1), reconnect the path */ set_avma(av); fill1(S->V, 1); } /* input V = W X a b Y a^* Z b^* T, W already normalized * X = [n+1, k1-1], Y = [k2+1, Ast[k1]-1], * Z = [Ast[k1]+1, Ast[k2]-1], T = [Ast[k2]+1, oo]. * Assume that X doesn't start by c c^* or a b a^* b^*. */ static void siegelstep(struct siegel *S) { if (S->Ast[S->k1] == S->k1) { basic_op_elliptic(S, S->k1); S->n++; } else if (S->Ast[S->k1] == S->k1+1) { basic_op(S, S->k1, S->Ast[S->k1], 1); /* 1: W starts there */ S->n += 2; } else { basic_op(S, S->k2, S->Ast[S->k1], 1); /* 1: W starts there */ basic_op(S, S->k1, S->k2, S->Ast[S->k2]); basic_op(S, S->Ast[S->k2], S->k2, S->Ast[S->k1]); basic_op(S, S->k1, S->Ast[S->k1], S->Ast[S->k2]); S->n += 4; } } /* normalize hyperbolic polygon */ static void mssiegel(struct siegel *S) { pari_sp av = avma; long k, t, nv; #ifdef COUNT long countset[16]; for (k = 0; k < 16; k++) countset[k] = 0; #endif nv = lg(S->V)-1; if (DEBUGLEVEL>1) err_printf("nv = %ld, expo = %.2f\n", nv,ZMV_size(S->V)); t = 0; while (S->n < nv) { if (S->Ast[S->n+1] == S->n+1) { S->n++; continue; } if (S->Ast[S->n+1] == S->n+2) { S->n += 2; continue; } if (S->Ast[S->n+1] == S->n+3 && S->Ast[S->n+2] == S->n+4) { S->n += 4; continue; } k = nv; while (k > S->n) { if (S->Ast[k] == k) { k--; continue; } if (S->Ast[k] == k-1) { k -= 2; continue; } if (S->Ast[k] == k-2 && S->Ast[k-1] == k-3) { k -= 4; continue; } break; } if (k != nv) { pari_sp av2 = avma; siegel_perm0(S, rotate_perm(nv+1, k+1)); set_avma(av2); S->n += nv-k; } for (k = S->n+1; k <= nv; k++) if (S->Ast[k] <= k) { t = S->Ast[k]; break; } S->k1 = t; S->k2 = t+1; #ifdef COUNT countset[ ((S->k1-1 == S->n) | ((S->k2 == S->Ast[S->k1]-1) << 1) | ((S->Ast[S->k1] == S->Ast[S->k2]-1) << 2) | ((S->Ast[S->k2] == nv) << 3)) ]++; #endif siegelstep(S); if (gc_needed(av,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"mspolygon, n = %ld",S->n); gerepileall(av, 2, &S->V, &S->Ast); } } if (DEBUGLEVEL>1) err_printf("expo = %.2f\n", ZMV_size(S->V)); #ifdef COUNT for (k = 0; k < 16; k++) err_printf("%3ld: %6ld\n", k, countset[k]); #endif } /* return a vector of char* */ static GEN Ast2v(GEN Ast) { long j = 0, k, l = lg(Ast); GEN v = const_vec(l-1, NULL); for (k=1; k < l; k++) { char *sj; if (gel(v,k)) continue; j++; sj = stack_sprintf("$%ld$", j); gel(v,k) = (GEN)sj; if (Ast[k] != k) gel(v,Ast[k]) = (GEN)stack_sprintf("$%ld^*$", j); } return v; }; static void decorate(pari_str *s, GEN g, GEN arc, double high) { double a = gtodouble(gcoeff(g,1,1)), c = gtodouble(gcoeff(g,2,1)); double d = gtodouble(gcoeff(g,2,2)); if (a + d) { double t, u, C = 360/(2*M_PI), x = (a-d) / (2*c), y = 0.8660254/fabs(c); long D1 = itos(gcoeff(arc,2,1)); long D2 = itos(gcoeff(arc,2,2)); str_printf(s, "\\coordinate (ellpt) at (%.4f,%.4f);\n\\draw (ellpt) node {$\\bullet$}\n", x, y); if (D1) { t = gtodouble(gcoeff(arc,1,1)) / D1; u = (x*x + y*y - t*t)/(x-t)/2; str_printf(s, "arc (%.4f:180:%.4f)\n", C*atan2(y,x-u), fabs(t-u)); } else str_printf(s, "-- (%.4f,%.4f)\n", x, high); if (D2) { t = gtodouble(gcoeff(arc,1,2)) / D2; u = (x*x + y*y - t*t)/(x-t)/2; str_printf(s, "(ellpt) arc (%.4f:0:%.4f);\n", C*atan2(y,x-u), fabs(t-u)); } else str_printf(s, "(ellpt) -- (%.4f,%.4f);\n", x, high); } else str_printf(s, "\\draw (%.4f,%.4f) node {$\\circ$};\n",a/c,fabs(1/c)); } static GEN polygon2tex(GEN V, GEN Ast, GEN G) { pari_sp av = avma; pari_str s; long j, l = lg(V), flag = (l <= 16); double d, high = (l < 4)? 1.2: 0.5; GEN v = Ast2v(Ast), r1 = NULL, r2 = NULL; for (j = 1; j < l; j++) { GEN arc = gel(V,j); if (!signe(gcoeff(arc,2,1))) r1 = gdiv(gcoeff(arc,1,2), gcoeff(arc,2,2)); else if (!signe(gcoeff(arc,2,2))) r2 = gdiv(gcoeff(arc,1,1), gcoeff(arc,2,1)); } if (!r1 || !r2) pari_err_BUG("polgon2tex"); str_init(&s, 1); d = fabs(gtodouble(gsub(r1,r2))); str_printf(&s, "\n\\begin{tikzpicture}[scale=%.2f]\n", d? (10 / d): 10); for (j = 1; j < l; j++) { GEN arc = gel(V,j); if (itos(gcoeff(arc,2,1))) { GEN a = gdiv(gcoeff(arc,1,1), gcoeff(arc,2,1)); double aa = gtodouble(a); str_printf(&s, "\\draw (%.4f,0) ", aa); if (flag || j == 2 || j == l-1) { long n, d; Qtoss(a, &n, &d); if (d == 1) str_printf(&s, "node [below] {$%ld$}\n", n); else str_printf(&s, "node [below] {$\\frac{%ld}{%ld}$}\n", n, d); } if (itos(gcoeff(arc,2,2))) { GEN b = gdiv(gcoeff(arc,1,2),gcoeff(arc,2,2)); str_printf(&s, "arc (%s:%.4f) ", (gcmp(a,b)<0)?"180:0":"0:180", fabs((gtodouble(b)-aa)/2)); if (flag) str_printf(&s, "node [midway, above] {%s} ", (char*)gel(v,j)); } else { str_printf(&s, "-- (%.4f,%.4f) ", aa, high); if (flag) str_printf(&s, "node [very near end, right] {%s}",(char*)gel(v,j)); } } else { GEN b = gdiv(gcoeff(arc,1,2), gcoeff(arc,2,2)); double bb = gtodouble(b); str_printf(&s, "\\draw (%.4f,%.4f)--(%.4f,0)\n", bb, high, bb); if (flag) str_printf(&s,"node [very near start, left] {%s}\n", (char*)gel(v,j)); } str_printf(&s,";\n"); if (Ast[j] == j) decorate(&s, gel(G,j), arc, high); } str_printf(&s, "\n\\end{tikzpicture}"); return gerepileuptoleaf(av, strtoGENstr(s.string)); } static GEN circle2tex(GEN Ast, GEN G) { pari_sp av = avma; GEN v = Ast2v(Ast); pari_str s; long u, n = lg(Ast)-1; const double ang = 360./n; if (n > 30) { v = const_vec(n, (GEN)""); gel(v,1) = (GEN)"$(1,\\infty)$"; } str_init(&s, 1); str_puts(&s, "\n\\begingroup\n\ \\def\\geo#1#2{(#2:1) arc (90+#2:270+#1:{tan((#2-#1)/2)})}\n\ \\def\\sgeo#1#2{(#2:1) -- (#1:1)}\n\ \\def\\unarc#1#2#3{({#1 * #3}:1.2) node {#2}}\n\ \\def\\cell#1#2{({#1 * #2}:0.95) circle(0.05)}\n\ \\def\\link#1#2#3#4#5{\\unarc{#1}{#2}{#5}\\geo{#1*#5}{#3*#5}\\unarc{#3}{#4}{#5}}\n\ \\def\\slink#1#2#3#4#5{\\unarc{#1}{#2}{#5}\\sgeo{#1*#5}{#3*#5}\\unarc{#3}{#4}{#5}}"); str_puts(&s, "\n\\begin{tikzpicture}[scale=4]\n"); str_puts(&s, "\\draw (0, 0) circle(1);\n"); for (u=1; u <= n; u++) { if (Ast[u] == u) { str_printf(&s,"\\draw\\unarc{%ld}{%s}{%.4f}; \\draw\\cell{%ld}{%.4f};\n", u, v[u], ang, u, ang); if (ZM_isscalar(gpowgs(gel(G,u),3), NULL)) str_printf(&s,"\\fill \\cell{%ld}{%.4f};\n", u, ang); } else if(Ast[u] > u) str_printf(&s, "\\draw \\%slink {%ld}{%s}{%ld}{%s}{%.4f};\n", (Ast[u] - u)*ang > 179? "s": "", u, v[u], Ast[u], v[Ast[u]], ang); } str_printf(&s, "\\end{tikzpicture}\\endgroup"); return gerepileuptoleaf(av, strtoGENstr(s.string)); } GEN mspolygon(GEN M, long flag) { pari_sp av = avma; struct siegel T; GEN v, msN = NULL, G = NULL; if (typ(M) == t_INT) { long N = itos(M); if (N <= 0) pari_err_DOMAIN("msinit","N", "<=", gen_0,M); msN = msinit_N(N); } else if (checkfarey_i(M)) { T.V = gel(M,1); T.Ast = gel(M,2); G = gel(M,3); } else { checkms(M); msN = get_msN(M); } if (flag < 0 || flag > 3) pari_err_FLAG("mspolygon"); if (!G) { if (ms_get_N(msN) == 1) { GEN S = mkS(); T.V = mkvec2(matid(2), S); T.Ast = mkvecsmall2(1,2); G = mkvec2(S, mkTAU()); } else { long i, l; siegel_init(&T, msN); l = lg(T.V); if (flag & 1) { long oo2 = 0; pari_sp av; mssiegel(&T); for (i = 1; i < l; i++) { GEN c = gel(T.V, i); GEN c22 = gcoeff(c,2,2); if (!signe(c22)) { oo2 = i; break; } } if (!oo2) pari_err_BUG("mspolygon"); av = avma; siegel_perm0(&T, rotate_perm(l, oo2)); set_avma(av); } G = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(G,i) = get_g(&T, i); } } if (flag & 2) v = mkvec5(T.V, T.Ast, G, polygon2tex(T.V,T.Ast,G), circle2tex(T.Ast,G)); else v = mkvec3(T.V, T.Ast, G); return gerepilecopy(av, v); } #if 0 static int iselliptic(GEN Ast, long i) { return i == Ast[i]; } static int isparabolic(GEN Ast, long i) { long i2 = Ast[i]; return (i2 == i+1 || i2 == i-1); } #endif /* M from msinit, F QM maximal rank */ GEN mslattice(GEN M, GEN F) { pari_sp av = avma; long i, ivB, j, k, l, lF; GEN D, U, G, A, vB, m, d; checkms(M); if (!F) F = gel(mscuspidal(M, 0), 1); else { if (is_Qevproj(F)) F = gel(F,1); if (typ(F) != t_MAT) pari_err_TYPE("mslattice",F); } lF = lg(F); if (lF == 1) return cgetg(1, t_MAT); D = mspolygon(M,0); k = msk_get_weight(M); F = vec_Q_primpart(F); if (typ(F)!=t_MAT || !RgM_is_ZM(F)) pari_err_TYPE("mslattice",F); G = gel(D,3); l = lg(G); A = gel(D,2); vB = cgetg(l, t_COL); d = mkcol2(gen_0,gen_1); m = mkmat2(d, d); for (i = ivB = 1; i < l; i++) { GEN B, vb, g = gel(G,i); if (A[i] < i) continue; gel(m,2) = SL2_inv2(g); vb = mseval(M, F, m); if (k == 2) B = vb; else { long lB; B = RgXV_to_RgM(vb, k-1); /* add coboundaries */ B = shallowconcat(B, RgM_Rg_sub_shallow(RgX_act_Gl2Q(g, k), gen_1)); /* beware: the basis for RgX_act_Gl2Q is (X^(k-2),...,Y^(k-2)) */ lB = lg(B); for (j = 1; j < lB; j++) gel(B,j) = vecreverse(gel(B,j)); } gel(vB, ivB++) = B; } setlg(vB, ivB); vB = shallowmatconcat(vB); if (ZM_equal0(vB)) return gerepilecopy(av, F); (void)QM_ImQ_hnfall(vB, &U, 0); if (k > 2) U = rowslice(U, 1, lgcols(U)-k); /* remove coboundary part */ U = Q_remove_denom(U, &d); F = ZM_hnf(ZM_mul(F, U)); if (d) F = RgM_Rg_div(F, d); return gerepileupto(av, F); } /**** Petersson scalar product ****/ /* TODO: * Eisspace: represent functions by coordinates of nonzero entries in matrix */ /* oo -> g^(-1) oo */ static GEN cocycle(GEN g) { retmkmat22(gen_1, gcoeff(g,2,2), gen_0, negi(gcoeff(g,2,1))); } /* CD = binomial_init(k-2); return * D (integral) */ static GEN bil(GEN P, GEN Q, GEN CD) { GEN s, C = gel(CD,1); long i, n = lg(C)-2; /* k - 2 */ if (!n) return gmul(P,Q); if (typ(P) != t_POL) P = scalarpol_shallow(P,0); if (typ(Q) != t_POL) Q = scalarpol_shallow(Q,0); s = gen_0; for (i = n - degpol(Q); i <= degpol(P); i++) { GEN t = gmul(gmul(RgX_coeff(P,i), RgX_coeff(Q, n-i)), gel(C,i+1)); s = odd(i)? gsub(s, t): gadd(s, t); } return s; } /* Let D = lcm {binomial(n,k), k = 0..n} = lcm([1..n+1]) / (n+1) * Return [C, D] where C[i] = D / binomial(n,i+1), i = 0..n */ static GEN binomial_init(long n, GEN vC) { GEN C = vC? shallowcopy(vC): vecbinomial(n), c = C + 1; GEN D = diviuexact(ZV_lcm(identity_ZV(n+1)), n+1); long k, d = (n + 1) >> 1; gel(c,0) = D; for (k = 1; k <= d; k++) gel(c, k) = diviiexact(D, gel(c, k)); for ( ; k <= n; k++) gel(c, k) = gel(c, n-k); return mkvec2(C, D); } static void mspetersson_i(GEN W, GEN F, GEN G, GEN *pvf, GEN *pvg, GEN *pC) { GEN WN = get_msN(W), annT2, annT31, section, c, vf, vg; long i, n1, n2, n3; annT2 = msN_get_annT2(WN); annT31 = msN_get_annT31(WN); section = msN_get_section(WN); if (ms_get_N(WN) == 1) { vf = cgetg(3, t_VEC); vg = cgetg(3, t_VEC); gel(vf,1) = mseval(W, F, gel(section,1)); gel(vf,2) = gneg(gel(vf,1)); n1 = 0; } else { GEN singlerel = msN_get_singlerel(WN); GEN gen = msN_get_genindex(WN); long l = lg(gen); vf = cgetg(l, t_VEC); vg = cgetg(l, t_VEC); /* generators of Delta ordered as E1,T2,T31 */ for (i = 1; i < l; i++) gel(vf, i) = mseval(W, F, gel(section,gen[i])); n1 = ms_get_nbE1(WN); /* E1 */ for (i = 1; i <= n1; i++) { c = cocycle(gcoeff(gel(singlerel,i),2,1)); gel(vg, i) = mseval(W, G, c); } } n2 = lg(annT2)-1; /* T2 */ for (i = 1; i <= n2; i++) { c = cocycle(gcoeff(gel(annT2,i), 2,1)); gel(vg, i+n1) = gmul2n(mseval(W, G, c), -1); } n3 = lg(annT31)-1; /* T31 */ for (i = 1; i <= n3; i++) { GEN f; c = cocycle(gcoeff(gel(annT31,i), 2,1)); f = mseval(W, G, c); c = cocycle(gcoeff(gel(annT31,i), 3,1)); gel(vg, i+n1+n2) = gdivgu(gadd(f, mseval(W, G, c)), 3); } *pC = binomial_init(msk_get_weight(W) - 2, NULL); *pvf = vf; *pvg = vg; } /* Petersson product on Hom_G(Delta_0, V_k) */ GEN mspetersson(GEN W, GEN F, GEN G) { pari_sp av = avma; GEN vf, vg, CD, cf, cg, A; long k, l, tG, tF; checkms(W); if (!F) F = matid(msdim(W)); if (!G) G = F; tF = typ(F); tG = typ(G); if (tF == t_MAT && tG != t_MAT) pari_err_TYPE("mspetersson",G); if (tG == t_MAT && tF != t_MAT) pari_err_TYPE("mspetersson",F); mspetersson_i(W, F, G, &vf, &vg, &CD); vf = Q_primitive_part(vf, &cf); vg = Q_primitive_part(vg, &cg); A = div_content(mul_content(cf, cg), gel(CD,2)); l = lg(vf); if (tF != t_MAT) { /* , two symbols */ GEN s = gen_0; for (k = 1; k < l; k++) s = gadd(s, bil(gel(vf,k), gel(vg,k), CD)); return gerepileupto(av, gmul(s, A)); } else if (F != G) { /* <(f_1,...,f_m), (g_1,...,g_n)> */ long iF, iG, lF = lg(F), lG = lg(G); GEN M = cgetg(lG, t_MAT); for (iG = 1; iG < lG; iG++) { GEN c = cgetg(lF, t_COL); gel(M,iG) = c; for (iF = 1; iF < lF; iF++) { GEN s = gen_0; for (k = 1; k < l; k++) s = gadd(s, bil(gmael(vf,k,iF), gmael(vg,k,iG), CD)); gel(c,iF) = s; /* M[iF,iG] = */ } } return gerepileupto(av, RgM_Rg_mul(M, A)); } else { /* <(f_1,...,f_n), (f_1,...,f_n)> */ long iF, iG, n = lg(F)-1; GEN M = zeromatcopy(n,n); for (iG = 1; iG <= n; iG++) for (iF = iG+1; iF <= n; iF++) { GEN s = gen_0; for (k = 1; k < l; k++) s = gadd(s, bil(gmael(vf,k,iF), gmael(vg,k,iG), CD)); gcoeff(M,iF,iG) = s; /* */ gcoeff(M,iG,iF) = gneg(s); } return gerepileupto(av, RgM_Rg_mul(M, A)); } } /* action of g in SL_2(Z/NZ) on functions f: (Z/NZ)^2 -> Q given by sparse * matrix M. */ static GEN actf(long N, GEN M, GEN g) { long n, a, b, c, d, l; GEN m; c = umodiu(gcoeff(g,2,1), N); if (!c) return M; d = umodiu(gcoeff(g,2,2), N); a = umodiu(gcoeff(g,1,1), N); b = umodiu(gcoeff(g,1,2), N); m = cgetg_copy(M, &l); for (n = 1; n < l; n++) { GEN v = gel(M,n); long i = v[1], j = v[2]; long I = Fl_add(Fl_mul(a,i,N), Fl_mul(c,j,N), N); long J = Fl_add(Fl_mul(b,i,N), Fl_mul(d,j,N), N); if (!I) I = N; if (!J) J = N; gel(m,n) = mkvecsmall2(I,J); } return m; } /* q1 = N/a, q2 = q1/d, (u,a) = 1. Gamma_0(N)-orbit attached to [q1,q2,u] * in (Z/N)^2; set of [q1 v, q2 w], v in (Z/a)^*, w in Z/a*d, * w mod a = u / v [invertible]; w mod d in (Z/d)^*; c1+c2= q2, d2|c1, d1|c2 * The orbit has cardinal C = a phi(d) <= N */ static GEN eisf(long N, long C, long a, long d1, GEN Z2, long c1, long c2, long q1, long u) { GEN m = cgetg(C+1, t_VEC); long v, n = 1, l = lg(Z2); for (v = 1; v <= a; v++) if (ugcd(v,a)==1) { long w1 = Fl_div(u, v, a), vq1 = v * q1, i, j; for (i = 0; i < d1; i++, w1 += a) { /* w1 defined mod a*d1, lifts u/v (mod a) */ for (j = 1; j < l; j++) if (Z2[j]) { long wq2 = (c1 * w1 + c2 * j) % N; if (wq2 <= 0) wq2 += N; gel(m, n++) = mkvecsmall2(vq1, wq2); } } } return m; } /* basis for Gamma_0(N)-invariant functions attached to cusps */ static GEN eisspace(long N, long k, long s) { GEN v, D, F = factoru(N); long l, n, i, j; D = divisorsu_fact(F); l = lg(D); n = mfnumcuspsu_fact(F); v = cgetg((k==2)? n: n+1, t_VEC); for (i = (k==2)? 2: 1, j = 1; i < l; i++) /* remove d = 1 if k = 2 */ { long d = D[i], Nd = D[l-i], a = ugcd(d, Nd), q1, q2, d1, d2, C, c1, c2, u; GEN Z2; if (s < 0 && a <= 2) continue; q1 = N / a; q2 = q1 / d; d2 = u_ppo(d/a, a); d1 = d / d2; C = eulerphiu(d) * a; Z2 = coprimes_zv(d2); /* d = d1d2, (d2,a) = 1; d1 and a have same prime divisors */ (void)cbezout(d1, d2, &c2, &c1); c2 *= d1 * q2; c1 *= d2 * q2; if (a <= 2) { /* sigma.(C cusp attached to [q1,q2,u]) = C */ gel(v, j++) = eisf(N,C,a,d1,Z2,c1,c2, N/a, 1); continue; } for (u = 1; 2*u < a; u++) { if (ugcd(u,a) != 1) continue; gel(v, j++) = eisf(N,C,a,d1,Z2,c1,c2, q1, u); if (!s) gel(v, j++) = eisf(N,C,a,d1,Z2,c1,c2, q1, a-u); } } if (s) setlg(v, j); return v; } /* action of g on V_k */ static GEN act(GEN P, GEN g, long k) { GEN a = gcoeff(g,1,1), b = gcoeff(g,1,2), V1, V2, Q; GEN c = gcoeff(g,2,1), d = gcoeff(g,2,2); long i; if (k == 2) return P; V1 = RgX_powers(deg1pol_shallow(c, a, 0), k-2); /* V1[i] = (a + c Y)^i */ V2 = RgX_powers(deg1pol_shallow(d, b, 0), k-2); /* V2[j] = (b + d Y)^j */ Q = gmul(RgX_coeff(P,0), gel(V1, k-2)); for (i = 1; i < k-2; i++) { GEN v1 = gel(V1, k-2-i); GEN v2 = gel(V2, i); Q = gadd(Q, gmul(RgX_coeff(P,i), RgX_mul(v1,v2))); } return gadd(Q, gmul(RgX_coeff(P,k-2), gel(V2,k-2))); } static long co_get_N(GEN co) { return gel(co,1)[1]; } static long co_get_k(GEN co) { return gel(co,1)[2]; } static GEN co_get_B(GEN co) { return gel(co,2); } static GEN co_get_BD(GEN co) { return gel(co,3); } static GEN co_get_C(GEN co) { return gel(co,4); } /* N g^(-1) . eval on g([0,a]_oo)=g([pi_oo(0),pi_oo(a)]), fg = f|g */ static GEN evalcap(GEN co, GEN fg, GEN a) { long n, t, l = lg(fg), N = co_get_N(co), k = co_get_k(co); GEN P, B, z, T; pari_sp av; if (isintzero(a)) return gen_0; /* (a+y)^(k-1) - y^(k-1) */ P = gsub(gpowgs(deg1pol_shallow(gen_1, a, 0), k-1), pol_xn(k-1, 0)); B = co_get_B(co); z = gen_0; av = avma; T = zero_zv(N); for (n = 1; n < l; n++) { GEN v = gel(fg, n); t = v[1]; T[t]++; } for (t = 1; t <= N; t++) { long c = T[t]; if (c) { GEN u = gmael(B, k, t); if (c != 1) u = gmulsg(c, u); z = gadd(z, u); } } if (co_get_BD(co)) z = gmul(co_get_BD(co),z); z = gerepileupto(av, gdivgs(z, -k * (k-1))); return RgX_Rg_mul(P, z); }; /* eval N g^(-1) * Psi(f) on g{oo,0}, fg = f|g */ static GEN evalcup(GEN co, GEN fg) { long j, n, k = co_get_k(co), l = lg(fg); GEN B = co_get_B(co), C = co_get_C(co), P = cgetg(k+1, t_POL); P[1] = evalvarn(0); for (j = 2; j <= k; j++) gel(P,j) = gen_0; for (n = 1; n < l; n++) { GEN v = gel(fg,n); long t = v[1], s = v[2]; for (j = 1; j < k; j++) { long j1 = k-j; GEN u = gmael(B, j1, t); GEN v = gmael(B, j, s); gel(P, j1+1) = gadd(gel(P, j1+1), gmul(u,v)); } } for (j = 1; j < k; j++) gel(P, j+1) = gmul(gel(C,j), gel(P, j+1)); return normalizepol(P); } /* Manin-Stevens algorithm, prepare for [pi_0(oo),pi_r(oo)] */ static GEN evalmanin(GEN r) { GEN fr = gboundcf(r, 0), pq, V; long j, n = lg(fr)-1; /* > 0 */ V = cgetg(n+2, t_VEC); gel(V,1) = gel(fr,1); /* a_0; tau_{-1} = id */ if (n == 1) { /* r integer, can happen iff N = 1 */ gel(V,2) = mkvec2(gen_0, mkmat22(negi(r), gen_1, gen_m1, gen_0)); return V; } pq = contfracpnqn(fr,n-1); fr = vec_append(fr, gdiv(negi(gcoeff(pq,2,n-1)), gcoeff(pq,2,n))); for (j = 0; j < n; j++) { GEN v1 = gel(pq, j+1), v2 = (j == 0)? col_ei(2,1): gel(pq, j); GEN z = gel(fr,j+2); if (!odd(j)) { v1 = ZC_neg(v1); z = gneg(z); } gel(V,j+2) = mkvec2(z, mkmat2(v1,v2)); /* [a_{j+1}, tau_j] */ } return V; } /* evaluate N * Psi(f) on g[pi_oo(0),pi_r(oo)]=g[pi_oo(0),pi_0(oo)] + g[pi_0(oo),pi_r(oo)] */ static GEN evalhull(GEN co, GEN f, GEN r) { GEN V = evalmanin(r), res = evalcap(co,f,gel(V,1)); long j, l = lg(V), N = co_get_N(co); for (j = 2; j < l; j++) { GEN v = gel(V,j), t = gel(v,2); /* in SL_2(Z) */ GEN ft = actf(N, f, t), a = gel(v,1); /* in Q */ /* t([pi_0(oo),pi_oo(a)]) */ res = gsub(res, act(gsub(evalcup(co,ft), evalcap(co,ft,a)), t, co_get_k(co))); } return res; }; /* evaluate N * cocycle at g in Gamma_0(N), f Gamma_0(N)-invariant */ static GEN eiscocycle(GEN co, GEN f, GEN g) { pari_sp av = avma; GEN a = gcoeff(g,1,1), b = gcoeff(g,1,2); GEN c = gcoeff(g,2,1), d = gcoeff(g,2,2), P; long N = co_get_N(co); if (!signe(c)) P = evalcap(co,f, gdiv(negi(b),a)); else { GEN gi = SL2_inv_shallow(g); P = gsub(evalhull(co, f, gdiv(negi(d),c)), act(evalcap(co, actf(N,f,gi), gdiv(a,c)), gi, co_get_k(co))); } return gerepileupto(av, P); } static GEN eisCocycle(GEN co, GEN D, GEN f) { GEN V = gel(D,1), Ast = gel(D,2), G = gel(D,3); long i, j, n = lg(G)-1; GEN VG = cgetg(n+1, t_VEC); for (i = j = 1; i <= n; i++) { GEN c, g, d, s = gel(V,i); if (i > Ast[i]) continue; g = SL2_inv_shallow(gel(G,i)); c = eiscocycle(co,f,g); if (i < Ast[i]) /* non elliptic */ d = gen_1; else { /* i = Ast[i] */ GEN g2 = ZM2_sqr(g); if (ZM_isdiagonal(g2)) d = gen_2; /* \pm Id */ else { c = gadd(c, eiscocycle(co,f,g2)); d = utoipos(3); } } gel(VG, j++) = mkvec3(d, s, c); } setlg(VG, j); return VG; }; /* F=modular symbol, Eis = cocycle attached to f invariant function * by Gamma_0(N); CD = binomial_init(k-2) */ static GEN eispetersson(GEN M, GEN F, GEN Eis, GEN CD) { pari_sp av = avma; long i, l = lg(Eis); GEN res = gen_0; for (i = 1; i < l; i++) { GEN e = gel(Eis,i), Q = mseval(M, F, gel(e,2)), z = bil(gel(e,3), Q, CD); long d = itou(gel(e,1)); res = gadd(res, d == 1? z: gdivgu(z,d)); } return gerepileupto(av, gdiv(simplify_shallow(res), gel(CD,2))); }; /*vB[j][i] = {i/N} */ static GEN get_bern(long N, long k) { GEN vB = cgetg(k+1, t_VEC), gN = utoipos(N); long i, j; /* no need for j = 0 */ for (j = 1; j <= k; j++) { GEN c, B = RgX_rescale(bernpol(j, 0), gN); gel(vB, j) = c = cgetg(N+1, t_VEC); for (i = 1; i < N; i++) gel(c,i) = poleval(B, utoipos(i)); gel(c,N) = gel(B,2); /* B(0) */ } return vB; } GEN eisker_worker(GEN Ei, GEN M, GEN D, GEN co, GEN CD) { pari_sp av = avma; long j, n = msdim(M), s = msk_get_sign(M); GEN V, Eis = eisCocycle(co, D, Ei), v = cgetg(n+1, t_VEC); V = s? gel(msk_get_starproj(M), 1): matid(n); /* T is multiplied by N * BD^2: same Ker */ for (j = 1; j <= n; j++) gel(v,j) = eispetersson(M, gel(V,j), Eis, CD); return gerepileupto(av, v); } /* vC = vecbinomial(k-2); vC[j] = binom(k-2,j-1) = vC[k-j], j = 1..k-1, k even. * C[k-j+1] = (-1)^(j-1) binom(k-2, j-1) / (j(k-j)) = C[j+1] */ static GEN get_C(GEN vC, long k) { GEN C = cgetg(k, t_VEC); long j, k2 = k/2; for (j = 1; j <= k2; j++) { GEN c = gel(vC, j); if (!odd(j)) c = negi(c); gel(C,k-j) = gel(C, j) = gdivgu(c, j*(k-j)); } return C; } static GEN eisker(GEN M) { long N = ms_get_N(M), k = msk_get_weight(M), s = msk_get_sign(M); GEN worker, vC, co, CD, D, B, BD, T, E = eisspace(N, k, s); long i, j, m = lg(E)-1, n = msdim(M), pending = 0; struct pari_mt pt; if (m == 0) return matid(n); vC = vecbinomial(k-2); T = zeromatcopy(m, n); D = mspolygon(M, 0); B = Q_remove_denom(get_bern(N,k), &BD); co = mkvec4(mkvecsmall2(N,k), B, BD, get_C(vC, k)); CD = binomial_init(k-2, vC); worker = snm_closure(is_entry("_eisker_worker"), mkvec4(M, D, co, CD)); mt_queue_start_lim(&pt, worker, m); for (i = 1; i <= m || pending; i++) { long workid; GEN done; mt_queue_submit(&pt, i, i<=m? mkvec(gel(E,i)): NULL); done = mt_queue_get(&pt, &workid, &pending); if (done) for (j = 1; j <= n; j++) gcoeff(T,workid,j) = gel(done,j); } mt_queue_end(&pt); return QM_ker(T); } pari-2.17.2/src/basemath/elliptic.c0000644000175000017500000064003014760301046015514 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /********************************************************************/ /** **/ /** ELLIPTIC CURVES **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_ell #undef coordch /* Transforms a curve E into short Weierstrass form E' modulo p. Returns a vector, the first two entries of which are a4' and a6'. The third entry is a vector describing the isomorphism E' \to E. */ static ulong Fl_c4_to_a4(ulong c4, ulong p) { return Fl_neg(Fl_mul(c4, 27, p), p); } static ulong Fl_c6_to_a6(ulong c6, ulong p) { return Fl_neg(Fl_mul(c6, 54, p), p); } static void Fl_c4c6_to_a4a6(ulong c4, ulong c6, ulong p, ulong *a4, ulong *a6) { *a4 = Fl_c4_to_a4(c4, p); *a6 = Fl_c6_to_a6(c6, p); } static GEN c4_to_a4(GEN c4, GEN p) { return Fp_neg(Fp_mulu(c4, 27, p), p); } static void c4c6_to_a4a6(GEN c4, GEN c6, GEN p, GEN *a4, GEN *a6) { *a4 = c4_to_a4(c4, p); *a6 = Fp_neg(Fp_mulu(c6, 54, p), p); } static GEN Fq_c4_to_a4(GEN c4, GEN T, GEN p) { return Fq_neg(Fq_mulu(c4, 27, T,p), T,p); } static void Fq_c4c6_to_a4a6(GEN c4, GEN c6, GEN T, GEN p, GEN *a4, GEN *a6) { *a4 = Fq_c4_to_a4(c4, T,p); *a6 = Fq_neg(Fq_mulu(c6, 54, T,p), T,p); } static void ell_to_a4a6(GEN E, GEN p, GEN *a4, GEN *a6) { GEN c4 = Rg_to_Fp(ell_get_c4(E),p); GEN c6 = Rg_to_Fp(ell_get_c6(E),p); c4c6_to_a4a6(c4, c6, p, a4, a6); } static void Fl_ell_to_a4a6(GEN E, ulong p, ulong *a4, ulong *a6) { ulong c4 = Rg_to_Fl(ell_get_c4(E),p); ulong c6 = Rg_to_Fl(ell_get_c6(E),p); Fl_c4c6_to_a4a6(c4, c6, p, a4, a6); } /* [6,3b2,3a1,108a3] */ static GEN a4a6_ch(GEN E, GEN p) { GEN a1 = Rg_to_Fp(ell_get_a1(E),p); GEN a3 = Rg_to_Fp(ell_get_a3(E),p); GEN b2 = Rg_to_Fp(ell_get_b2(E),p); retmkvec4(modsi(6,p),Fp_mulu(b2,3,p),Fp_mulu(a1,3,p),Fp_mulu(a3,108,p)); } static GEN a4a6_ch_Fl(GEN E, ulong p) { ulong a1 = Rg_to_Fl(ell_get_a1(E),p); ulong a3 = Rg_to_Fl(ell_get_a3(E),p); ulong b2 = Rg_to_Fl(ell_get_b2(E),p); return mkvecsmall4(6 % p,Fl_mul(b2,3,p),Fl_mul(a1,3,p),Fl_mul(a3,108,p)); } static GEN ell_to_a4a6_bc(GEN E, GEN p) { GEN A4, A6; ell_to_a4a6(E, p, &A4, &A6); retmkvec3(A4, A6, a4a6_ch(E,p)); } GEN point_to_a4a6(GEN E, GEN P, GEN p, GEN *pa4) { GEN c4 = Rg_to_Fp(ell_get_c4(E),p); *pa4 = c4_to_a4(c4, p); return FpE_changepointinv(RgV_to_FpV(P,p), a4a6_ch(E,p), p); } GEN point_to_a4a6_Fl(GEN E, GEN P, ulong p, ulong *pa4) { ulong c4 = Rg_to_Fl(ell_get_c4(E),p); *pa4 = Fl_c4_to_a4(c4, p); return Fle_changepointinv(RgV_to_Flv(P,p), a4a6_ch_Fl(E,p), p); } /* shallow basistoalg */ static GEN nftoalg(GEN nf, GEN x) { switch(typ(x)) { case t_INT: case t_FRAC: case t_POLMOD: return x; default: return basistoalg(nf, x); } } static int checkellpt_i(GEN z) { long l; if (typ(z)!=t_VEC) return 0; l = lg(z); return l == 3 || (l == 2 && isintzero(gel(z,1))); } void checkellpt(GEN z) { if (!checkellpt_i(z)) pari_err_TYPE("checkellpt", z); } void checkell5(GEN E) { long l = lg(E); if (typ(E)!=t_VEC || (l != 17 && l != 6)) pari_err_TYPE("checkell5",E); } void checkell(GEN E) { if (!checkell_i(E)) pari_err_TYPE("checkell",E); } void checkellisog(GEN v) { if (typ(v)!=t_VEC || lg(v) != 4) pari_err_TYPE("checkellisog",v); } void checkell_Q(GEN E) { if (!checkell_i(E) || ell_get_type(E)!=t_ELL_Q) pari_err_TYPE("checkell over Q",E); } void checkell_Qp(GEN E) { if (!checkell_i(E) || ell_get_type(E)!=t_ELL_Qp) pari_err_TYPE("checkell over Qp",E); } static int ell_over_Fq(GEN E) { long t = ell_get_type(E); return t==t_ELL_Fp || t==t_ELL_Fq; } void checkell_Fq(GEN E) { if (!checkell_i(E) || !ell_over_Fq(E)) pari_err_TYPE("checkell over Fq", E); } GEN ellff_get_p(GEN E) { GEN fg = ellff_get_field(E); return typ(fg)==t_INT? fg: FF_p_i(fg); } int ell_is_integral(GEN E) { return 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; } static void checkcoordch(GEN z) { if (typ(z)!=t_VEC || lg(z) != 5) pari_err_TYPE("checkcoordch",z); } /* 4 X^3 + b2 X^2 + 2b4 X + b6 */ GEN ec_bmodel(GEN e, long v) { GEN b2 = ell_get_b2(e), b6 = ell_get_b6(e), b42 = gmul2n(ell_get_b4(e),1); GEN P = mkpoln(4, utoipos(4), b2, b42, b6); setvarn(P, v); return P; } /* X^4 - b4*X^2 - 2b6*X - b8 */ GEN ec_phi2(GEN e, long v) { GEN b4 = ell_get_b4(e), b6 = ell_get_b6(e), b8 = ell_get_b8(e); GEN P = mkpoln(5, gen_1, gen_0, gneg(b4), gmul2n(gneg(b6),1), gneg(b8)); setvarn(P, v); return P; } static int invcmp(void *E, GEN x, GEN y) { (void)E; return -gcmp(x,y); } /* prec = working precision, prec0 = target precision */ static GEN doellR_roots_i(GEN e, long prec, long prec0) { GEN d1, d2, d3, e1, e2, e3, R = cleanroots(ec_bmodel(e,0), prec); long s = ellR_get_sign(e); if (s > 0) { /* sort 3 real roots in decreasing order */ R = real_i(R); gen_sort_inplace(R, NULL, &invcmp, NULL); e1 = gel(R,1); e2 = gel(R,2); e3 = gel(R,3); d3 = subrr(e1,e2); d1 = subrr(e2,e3); d2 = subrr(e1,e3); if (realprec(d3) < prec0 || realprec(d1) < prec0) return NULL; } else { e1 = gel(R,1); e2 = gel(R,2); e3 = gel(R,3); if (s < 0) { /* make sure e1 is real, imag(e2) > 0 and imag(e3) < 0 */ e1 = real_i(e1); if (signe(gel(e2,2)) < 0) swap(e2, e3); d1 = mkcomplex(gen_0, gsub(gel(e2,2),gel(e3,2))); } else d1 = gsub(e2,e3); d3 = gsub(e1,e2); d2 = gsub(e1,e3); if (precision(d1) < prec0 || precision(d2) < prec0 || precision(d3) < prec0) return NULL; } return mkcol6(e1,e2,e3,d1,d2,d3); } static GEN doellR_roots(GEN e, long prec0) { long p; for (p = prec0;; p = precdbl(p)) { GEN v = doellR_roots_i(e, p, prec0); if (v) return v; if (DEBUGLEVEL) pari_warn(warnprec,"doellR_roots", p); } } static GEN ellR_root(GEN e, long prec) { return gel(ellR_roots(e,prec),1); } /* Given E and the x-coordinate of a point Q = [xQ, yQ], return * f(xQ) = xQ^3 + E.a2 * xQ^2 + E.a4 * xQ + E.a6 * where E is given by y^2 + h(x)y = f(x). */ GEN ec_f_evalx(GEN E, GEN x) { pari_sp av = avma; GEN z; z = gadd(ell_get_a2(E),x); z = gadd(ell_get_a4(E), gmul(x,z)); z = gadd(ell_get_a6(E), gmul(x,z)); return gerepileupto(av, z); /* ((x + E.a2) * x + E.a4) * x + E.a6 */ } /* a1 x + a3 */ GEN ec_h_evalx(GEN e, GEN x) { GEN a1 = ell_get_a1(e); GEN a3 = ell_get_a3(e); return gadd(a3, gmul(x,a1)); } static GEN Zec_h_evalx(GEN e, GEN x) { GEN a1 = ell_get_a1(e); GEN a3 = ell_get_a3(e); return signe(a1)? addii(a3, mulii(x, a1)): a3; } /* y^2 + a1 xy + a3 y = y^2 + h(x)y */ static GEN ec_LHS_evalQ(GEN e, GEN Q) { GEN x = gel(Q,1), y = gel(Q,2); return gmul(y, gadd(y, ec_h_evalx(e,x))); } /* Given E and a point Q = [xQ, yQ], return * 3 * xQ^2 + 2 * E.a2 * xQ + E.a4 - E.a1 * yQ. * which is the derivative of the curve equation * f(x) - (y^2 + h(x)y) = 0 * wrt x evaluated at Q */ GEN ec_dFdx_evalQ(GEN E, GEN Q) { pari_sp av = avma; GEN x = gel(Q,1), y = gel(Q,2); GEN a1 = ell_get_a1(E); GEN a2 = ell_get_a2(E); GEN a4 = ell_get_a4(E); GEN tmp = gmul(gadd(gmulsg(3L,x), gmul2n(a2,1)), x); return gerepileupto(av, gadd(tmp, gsub(a4, gmul(a1, y)))); } /* 2y + a1 x + a3 = -ec_dFdy_evalQ */ GEN ec_dmFdy_evalQ(GEN e, GEN Q) { GEN x = gel(Q,1), y = gel(Q,2); return gadd(ec_h_evalx(e,x), gmul2n(y,1)); } /* Given E and a point Q = [xQ, yQ], return * -(2 * yQ + E.a1 * xQ + E.a3) * which is the derivative of the curve equation * f(x) - (y^2 + h(x)y) = 0 * wrt y evaluated at Q */ GEN ec_dFdy_evalQ(GEN E, GEN Q) { pari_sp av = avma; return gerepileupto(av, gneg(ec_dmFdy_evalQ(E,Q))); } /* Given E and a point Q = [xQ, yQ], return * 4 xQ^3 + E.b2 xQ^2 + 2 E.b4 xQ + E.b6 * which is the 2-division polynomial of E evaluated at Q */ GEN ec_2divpol_evalx(GEN E, GEN x) { pari_sp av = avma; GEN b2 = ell_get_b2(E), x4 = gmul2n(x,2), t1, t2; GEN b42 = gmul2n(ell_get_b4(E), 1); GEN b6 = ell_get_b6(E); if (ell_get_type(E) == t_ELL_NF && typ(x)==t_COL) { GEN nf = ellnf_get_nf(E); t1 = nfmul(nf, nfadd(nf, x4, b2), x); t2 = nfadd(nf, t1, b42); t2 = nfadd(nf, nfmul(nf, t2, x), b6); t2 = nftoalg(nf, t2); } else { t1 = gmul(gadd(x4, b2), x); t2 = gadd(t1, b42); t2 = gadd(gmul(t2, x), b6); } return gerepileupto(av, t2); } /* Given E and a point Q = [xQ, yQ], return * 3 xQ^4 + E.b2 xQ^3 + 3 E.b4 xQ^2 + 3*E.b6 xQ + E.b8 * which is the 3-division polynomial of E evaluated at Q */ GEN ec_3divpol_evalx(GEN E, GEN x) { pari_sp av = avma; GEN b2 = ell_get_b2(E); GEN b4 = ell_get_b4(E); GEN b6 = ell_get_b6(E); GEN b8 = ell_get_b8(E); GEN x2 = gsqr(x); GEN t1 = gadd(gadd(gmulsg(3L, x2), gmul(b2, x)), gmulsg(3L, b4)); GEN t2 = gadd(gmul(gmulsg(3L, b6), x), b8); return gerepileupto(av, gadd(gmul(t1, x2), t2)); } /* Given E and a point Q = [xQ, yQ], return * 6 xQ^2 + E.b2 xQ + E.b4 * which, if f is the curve equation, is 2 dfdx - E.a1 dfdy evaluated at Q */ GEN ec_half_deriv_2divpol(GEN E, long v) { return deg2pol_shallow(utoi(6), ell_get_b2(E), ell_get_b4(E), v); } GEN ec_half_deriv_2divpol_evalx(GEN E, GEN x) { pari_sp av = avma; GEN b2 = ell_get_b2(E); GEN b4 = ell_get_b4(E); GEN res = gadd(gmul(gadd(gmulsg(6L, x), b2), x), b4); return gerepileupto(av, res); } /* Return the characteristic of the ring over which E is defined. */ GEN ellbasechar(GEN E) { pari_sp av = avma; GEN D = ell_get_disc(E); return gerepileuptoint(av, characteristic(D)); } /* Initialize basic elliptic struct y[1..12] for initsmall * (do not include j to allow for singular Weistrass model) * Also allocate room for n dynamic members. */ static GEN initsmall46(GEN a4, GEN a6, long n) { GEN y = obj_init(15, n); gel(y,1) = gen_0; gel(y,2) = gen_0; gel(y,3) = gen_0; gel(y,4) = a4; gel(y,5) = a6; gel(y,6) = gen_0; gel(y,7) = gmul2n(a4,1); gel(y,8) = gmul2n(a6,2); gel(y,9) = gneg(gsqr(a4)); gel(y,10)= gmulgs(a4,-48); gel(y,11)= gmulgs(a6,-864); gel(y,12)= gadd(gmul(gmulgs(a4,-64), gsqr(a4)), gmulsg(-432,gsqr(a6))); gel(y,16) = zerovec(n); return y; } /* [a1,a2,a3,a4,a6] */ static GEN initsmall5(GEN x, long n) { GEN a1 = gel(x,1), a2 = gel(x,2), a3 = gel(x,3); GEN a4 = gel(x,4), a6 = gel(x,5); GEN y, b2, b4, b6, b8, c4, c6, D, a11, a13, a33, b22; if (gequal0(a1) && gequal0(a2) && gequal0(a3)) return initsmall46(a4, a6, n); a11= gsqr(a1); b2 = gadd(a11, gmul2n(a2,2)); a13= gmul(a1, a3); b4 = gadd(a13, gmul2n(a4,1)); a33= gsqr(a3); b6 = gadd(a33, gmul2n(a6,2)); b8 = gsub(gadd(gmul(a11,a6), gmul(b6, a2)), gmul(a4, gadd(a4,a13))); b22= gsqr(b2); c4 = gadd(b22, gmulsg(-24,b4)); c6 = gadd(gmul(b2,gsub(gmulsg(36,b4),b22)), gmulsg(-216,b6)); D = gsub(gmul(b4, gadd(gmulsg(9,gmul(b2,b6)),gmulsg(-8,gsqr(b4)))), gadd(gmul(b22,b8),gmulsg(27,gsqr(b6)))); y = obj_init(15, n); gel(y,1) = a1; gel(y,2) = a2; gel(y,3) = a3; gel(y,4) = a4; gel(y,5) = a6; gel(y,6) = b2; /* a1^2 + 4a2 */ gel(y,7) = b4; /* a1 a3 + 2a4 */ gel(y,8) = b6; /* a3^2 + 4 a6 */ gel(y,9) = b8; /* a1^2 a6 + 4a6 a2 + a2 a3^2 - a4(a4 + a1 a3) */ gel(y,10)= c4; /* b2^2 - 24 b4 */ gel(y,11)= c6; /* 36 b2 b4 - b2^3 - 216 b6 */ gel(y,12)= D; gel(y,16) = zerovec(n); return y; } static GEN get_j(GEN c4, GEN D) { GEN g, d, c; if (typ(D) != t_POL || typ(c4) != t_POL || varn(D) != varn(c4)) return gdiv(gmul(gsqr(c4),c4), D); /* c4^3 / D, simplifying incrementally */ g = RgX_gcd(D, c4); if (degpol(g) == 0) return gred_rfrac_simple(gmul(gsqr(c4),c4), D); c = RgX_div(c4, g); D = RgX_div(D, g); g = RgX_gcd(D,c4); if (degpol(g) == 0) return gred_rfrac_simple(gmul(gsqr(c4),c), D); D = RgX_div(D, g); d = RgX_div(c4, g); g = RgX_gcd(D,c4); if (degpol(g)) { D = RgX_div(D, g); c4 = RgX_div(c4, g); } return gred_rfrac_simple(gmul(gmul(c4, d),c), D); } /* return basic elliptic struct y[1..13], y[14] (domain type) and y[15] * (domain-specific data) are left uninitialized, from x[1], ..., x[5]. * Also allocate room for n dynamic members (actually stored in the last * component y[16])*/ static GEN initsmall(GEN x, long n) { GEN y, D; switch(lg(x)) { case 2: y = initsmall5(ellfromj(gel(x,1)), n); break; case 3: y = initsmall46(gel(x,1), gel(x,2), n); break; case 6: case 17: y = initsmall5(x, n); break; default: pari_err_TYPE("ellxxx [not an elliptic curve (ell5)]",x); return NULL; /* LCOV_EXCL_LINE */ } D = ell_get_disc(y); if (gequal0(D)) return NULL; gel(y,13) = get_j(ell_get_c4(y), D); return y; } void ellprint(GEN e) { pari_sp av = avma; long vx, vy; GEN z; checkell5(e); vx = fetch_var(); name_var(vx, "X"); vy = fetch_var(); name_var(vy, "Y"); z = mkvec2(pol_x(vx), pol_x(vy)); err_printf("%Ps - (%Ps)\n", ec_LHS_evalQ(e, z), ec_f_evalx(e, pol_x(vx))); (void)delete_var(); (void)delete_var(); set_avma(av); } /* compute a,b such that E1: y^2 = x(x-a)(x-b) ~ E */ static GEN doellR_ab(GEN E, long prec) { GEN b2 = ell_get_b2(E), R = ellR_roots(E, prec); GEN e1 = gel(R,1), d2 = gel(R,5), d3 = gel(R,6), a, b, t; t = gmul2n(gadd(mulur(12,e1), b2), -4); /* = (12 e1 + b2) / 16 */ if (ellR_get_sign(E) > 0) b = mulrr(d3,d2); else b = cxnorm(d3); b = sqrtr(b); /* = sqrt( (e1 - e2)(e1 - e3) ) */ if (gsigne(t) > 0) togglesign(b); a = gsub(gmul2n(b,-1),t); return mkvec2(a, b); } GEN ellR_ab(GEN E, long prec) { return obj_checkbuild_realprec(E, R_AB, &doellR_ab, prec); } /* q a t_REAL*/ static long real_prec(GEN q) { return signe(q)? realprec(q): LONG_MAX; } /* q a t_PADIC */ static long padic_prec(GEN q) { return signe(gel(q,4))? precp(q)+valp(q): valp(q); } /* check whether moduli are consistent */ static void chk_p(GEN p, GEN p2) { if (!equalii(p, p2)) pari_err_MODULUS("ellinit", p,p2); } static int fix_nftype(GEN *pp) { switch(nftyp(*pp)) { case typ_NF: case typ_BNF: break; case typ_BNR:*pp = bnr_get_bnf(*pp); break; default: return 0; } return 1; } static long base_ring(GEN x, GEN *pp, long *prec) { long i, e = *prec, ep = LONG_MAX, imax = minss(lg(x), 6); GEN p = NULL, pol = NULL; long t = t_FRAC; if (*pp) switch(t = typ(*pp)) { case t_INT: if (cmpis(*pp,2) < 0) { t = t_FRAC; p = NULL; break; } p = *pp; t = t_INTMOD; break; case t_INTMOD: p = gel(*pp, 1); break; case t_REAL: e = real_prec(*pp); p = NULL; break; case t_PADIC: ep = padic_prec(*pp); p = gel(*pp, 2); break; case t_FFELT: p = *pp; break; case t_VEC: t = t_VEC; p = *pp; if (fix_nftype(&p)) break; default: pari_err_TYPE("elliptic curve base_ring", *pp); return 0; } if (t==t_VEC) pol = nf_get_pol(checknf(p)); /* Possible cases: * t = t_VEC (p an nf or bnf) * t = t_FFELT (p t_FFELT) * t = t_INTMOD (p a prime) * t = t_PADIC (p a prime, ep = padic prec) * t = t_REAL (p = NULL, e = real prec) * t = t_FRAC (p = NULL) */ for (i = 1; i < imax; i++) { GEN p2, q = gel(x,i); switch(typ(q)) { case t_PADIC: p2 = gel(q,2); switch(t) { case t_FRAC: t = t_PADIC; p = p2; break; case t_PADIC: chk_p(p,p2); break; default: pari_err_TYPE("elliptic curve base_ring", x); } ep = minss(ep, padic_prec(q)); break; case t_INTMOD: p2 = gel(q,1); switch(t) { case t_FRAC: t = t_INTMOD; p = p2; break; case t_FFELT: chk_p(FF_p_i(p),p2); break; case t_INTMOD:chk_p(p,p2); break; default: pari_err_TYPE("elliptic curve base_ring", x); } break; case t_FFELT: switch(t) { case t_INTMOD: chk_p(p, FF_p_i(q)); /* fall through */ case t_FRAC: t = t_FFELT; p = q; break; case t_FFELT: if (!FF_samefield(p,q) && FF_f(q)>1) pari_err_MODULUS("ellinit", p,q); break; default: pari_err_TYPE("elliptic curve base_ring", x); } break; case t_INT: case t_FRAC: break; case t_REAL: switch(t) { case t_REAL: e = minss(e, real_prec(q)); break; case t_FRAC: e = real_prec(q); t = t_REAL; break; default: pari_err_TYPE("elliptic curve base_ring", x); } break; case t_POLMOD: if (pol && !RgX_equal(pol, gel(q,1))) pari_err_MODULUS("ellinit",gel(q,1), pol); case t_COL: case t_POL: if (t == t_VEC) break; default: /* base ring too general */ return t_COMPLEX; } } *pp = p; *prec = (t == t_PADIC)? ep: e; return t; } /* s = 0 complex, else real; * if (s = 2) set s = sign(D), else accept s as is */ static GEN ellinit_Rg(GEN x, long s, long prec) { GEN y; if (lg(x) > 6) switch(ell_get_type(x)) { case t_ELL_Rg: case t_ELL_Q: break; default: pari_err_TYPE("elliptic curve base_ring", x); } if (!(y = initsmall(x, 4))) return NULL; if (s == 2) s = gsigne(ell_get_disc(y)); gel(y,14) = mkvecsmall(t_ELL_Rg); gel(y,15) = mkvec(mkvecsmall2(prec, s)); return y; } static GEN ellinit_Qp(GEN x, GEN p, long prec) { GEN y; if (lg(x) > 6) { switch(ell_get_type(x)) { /* sanity checks */ case t_ELL_Q: break; case t_ELL_Qp: chk_p(ellQp_get_p(x), p); break; default: pari_err_TYPE("elliptic curve base_ring", x); } x = vecslice(x,1,5); } x = QpV_to_QV(x); /* make entries rational */ if (!(y = initsmall(x, 2))) return NULL; gel(y,14) = mkvecsmall(t_ELL_Qp); gel(y,15) = mkvec(zeropadic_shallow(p, prec)); return y; } static GEN ellinit_Q(GEN x, long prec) { GEN y; long s; if (!(y = initsmall(x, 8))) return NULL; s = gsigne( ell_get_disc(y) ); gel(y,14) = mkvecsmall(t_ELL_Q); gel(y,15) = mkvec(mkvecsmall2(prec, s)); return y; } static GEN nfVtoalg(GEN nf, GEN x) { pari_APPLY_same(nftoalg(nf,gel(x,i))); } static GEN ellinit_nf(GEN x, GEN p) { GEN y, nf; if (lg(x) > 6) x = vecslice(x,1,5); nf = checknf(p); x = nfVtoalg(nf, x); if (!(y = initsmall(x, 5))) return NULL; gel(y,14) = mkvecsmall(t_ELL_NF); gel(y,15) = mkvec(p); return y; } /* FF_ellinit allows singular cubic, return NULL in that case */ static GEN FF_ellinit_ns(GEN x, GEN fg) { x = FF_ellinit(x,fg); return FF_equal0(ell_get_disc(x))? NULL: x; } static GEN to_mod(GEN x, GEN p) { return mkintmod(Rg_to_Fp(x,p), p); } static GEN ellinit_Fp(GEN x, GEN p) { long i; GEN y, disc; if (lg(x) > 6) switch(ell_get_type(x)) { case t_ELL_Q: break; case t_ELL_Fp: chk_p(ellff_get_p(x),p); break; case t_ELL_Qp: chk_p(ellQp_get_p(x),p); break; default: pari_err_TYPE("elliptic curve base_ring", x); } if (lg(x) == 2) x = ellfromj(to_mod(gel(x,1), p)); if (!(y = initsmall(x, 4))) return NULL; /* ell_to_a4a6_bc does not handle p<=3 */ if (abscmpiu(p, 3) <= 0) return FF_ellinit_ns(y,p_to_FF(p,0)); disc = Rg_to_Fp(ell_get_disc(y),p); if (!signe(disc)) return NULL; for(i = 1; i <= 13; i++) gel(y,i) = to_mod(gel(y,i),p); gel(y,14) = mkvecsmall(t_ELL_Fp); gel(y,15) = mkvec2(p, ell_to_a4a6_bc(y, p)); return y; } static GEN ellinit_Fq(GEN x, GEN fg) { GEN y; if (lg(x) == 2) { GEN j = gel(x,1); if (typ(j) != t_FFELT) j = Fq_to_FF(j, fg); x = ellfromj(j); } if (!(y = initsmall(x, 4))) return NULL; return FF_ellinit_ns(y,fg); } static GEN ellnf_to_Fq(GEN nf, GEN x, GEN P, GEN *pp, GEN *pT) { GEN e = vecslice(x,1,5); GEN p, modP; if (get_modpr(P)) { /* modpr accept */ modP = P; p = modpr_get_p(modP); } else { /* pr, initialize modpr */ GEN d = Q_denom(e); p = pr_get_p(P); modP = dvdii(d,p)? nfmodprinit(nf,P): zkmodprinit(nf,P); } *pp = p; *pT = modpr_get_T(modP); return nfV_to_FqV(e, nf, modP); } static GEN ellinit_nf_to_Fq(GEN nf, GEN E, GEN P) { GEN T,p; E = ellnf_to_Fq(nf, E, P, &p, &T); return T? ellinit_Fq(E,Tp_to_FF(T,p)): ellinit_Fp(E,p); } static GEN ellinit_i(GEN x, GEN D, long prec) { GEN y; switch(typ(x)) { case t_STR: x = gel(ellsearchcurve(x),2); break; case t_VEC: switch(lg(x)) { case 2: case 3: case 6: case 17: break; default: pari_err_TYPE("ellinit",x); } break; default: pari_err_TYPE("ellinit",x); } if (D && get_prid(D)) { if (lg(x) == 6 || ell_get_type(x) != t_ELL_NF) pari_err_TYPE("ellinit",x); return ellinit_nf_to_Fq(ellnf_get_nf(x), x, D); } switch (base_ring(x, &D, &prec)) { case t_PADIC: y = ellinit_Qp(x, D, prec); break; case t_INTMOD: y = ellinit_Fp(x, D); break; case t_FFELT: y = ellinit_Fq(x, D); break; case t_FRAC: y = ellinit_Q(x, prec); break; case t_REAL: y = ellinit_Rg(x, 2, prec); break; case t_VEC: y = ellinit_nf(x, D); break; default: y = ellinit_Rg(x, 0, prec); } return y; } GEN ellinit(GEN x, GEN D, long prec) { pari_sp av = avma; GEN y = ellinit_i(x, D, prec); if (!y) { set_avma(av); return cgetg(1,t_VEC); } return gerepilecopy(av,y); } /********************************************************************/ /** **/ /** COORDINATE CHANGE **/ /** Apply [u,r,s,t]. All coordch_* functions update E[1..14] only **/ /** and copy E[15] (type-specific data), E[16] (dynamic data) **/ /** verbatim **/ /** **/ /********************************************************************/ /* [1,0,0,0] */ static GEN init_ch(void) { return mkvec4(gen_1,gen_0,gen_0,gen_0); } static int is_trivial_change(GEN v) { GEN u, r, s, t; if (typ(v) == t_INT) return 1; u = gel(v,1); r = gel(v,2); s = gel(v,3); t = gel(v,4); return isint1(u) && isintzero(r) && isintzero(s) && isintzero(t); } /* Accumulate the effects of variable changes w o v, where * w = [u,r,s,t], *vtotal = v = [U,R,S,T]. No assumption on types */ static void gcomposev(GEN *vtotal, GEN w) { GEN v = *vtotal; GEN U2, U, R, S, T, u, r, s, t; if (!v || typ(v) == t_INT) { *vtotal = w; return; } U = gel(v,1); R = gel(v,2); S = gel(v,3); T = gel(v,4); u = gel(w,1); r = gel(w,2); s = gel(w,3); t = gel(w,4); U2 = NULL; if (!gequal0(r)) { GEN rU2; U2 = gsqr(U); rU2 = gmul(U2, r); R = gadd(R, rU2); T = gadd(T, gmul(S, rU2)); } if (!gequal0(s)) S = gadd(S, gmul(U, s)); if (!gequal0(t)) { if (!U2) U2 = gsqr(U); T = gadd(T, gmul(gmul(U,U2), t)); } gel(v,1) = gmul(U, u); gel(v,2) = R; gel(v,3) = S; gel(v,4) = T; } /* [u,r,s,t]^-1 = [ 1/u,-r/u^2,-s/u, (rs-t)/u^3 ] */ GEN ellchangeinvert(GEN w) { GEN u,r,s,t, u2,u3, U,R,S,T; if (typ(w) == t_INT) return w; u = gel(w,1); r = gel(w,2); s = gel(w,3); t = gel(w,4); u2 = gsqr(u); u3 = gmul(u2,u); U = ginv(u); R = gdiv(gneg(r), u2); S = gdiv(gneg(s), u); T = gdiv(gsub(gmul(r,s), t), u3); return mkvec4(U,R,S,T); } static GEN ell_to_nfell10(GEN e) { long i; GEN nf = ellnf_get_nf(e); GEN y = cgetg(11,t_VEC); for(i=1; i<=10; i++) gel(y, i) = nf_to_scalar_or_basis(nf, gel(e, i)); return y; } /* apply [u^(-1),0,0,0] */ static GEN nf_coordch_uinv(GEN nf, GEN e, GEN u) { GEN y, u2, u3, u4, u6, u8; long lx; if (gequal1(u)) return e; y = cgetg_copy(e, &lx); u2 = nfsqr(nf,u); u3 = nfmul(nf,u,u2); u4 = nfsqr(nf,u2); u6 = nfsqr(nf,u3); u8 = nfsqr(nf,u4); gel(y,1) = nfmul(nf,ell_get_a1(e), u); gel(y,2) = nfmul(nf,ell_get_a2(e), u2); gel(y,3) = nfmul(nf,ell_get_a3(e), u3); gel(y,4) = nfmul(nf,ell_get_a4(e), u4); gel(y,5) = nfmul(nf,ell_get_a6(e), u6); if (lx == 6) return y; gel(y,6) = nfmul(nf,ell_get_b2(e), u2); gel(y,7) = nfmul(nf,ell_get_b4(e), u4); gel(y,8) = nfmul(nf,ell_get_b6(e), u6); gel(y,9) = nfmul(nf,ell_get_b8(e), u8); return y; } /* apply [1,r,0,0] */ static GEN nf_coordch_r(GEN nf, GEN e, GEN r) { GEN a2, a4, b4, b6, y, p1, r2, b2r, rx3; long lx; if (gequal0(r)) return e; y = cgetg_copy(e, &lx); a2 = ell_get_a2(e); a4 = ell_get_a4(e); rx3 = gmulsg(3,r); gel(y,1) = ell_get_a1(e); /* A2 = a2 + 3r */ gel(y,2) = nfadd(nf,a2,rx3); /* A3 = a1 r + a3 */ gel(y,3) = nfadd(nf,ell_get_a3(e), nfmul(nf,ell_get_a1(e),r)); /* A4 = 3r^2 + 2a2 r + a4 */ gel(y,4) = nfadd(nf,a4, nfmul(nf,r,nfadd(nf,gmul2n(a2,1),rx3))); /* A6 = r^3 + a2 r^2 + a4 r + a6 */ gel(y,5) = nfadd(nf,ell_get_a6(e),nfmul(nf,r,nfadd(nf, a4, nfmul(nf,r,nfadd(nf,a2, r))))); if (lx == 6) return y; b4 = ell_get_b4(e); b6 = ell_get_b6(e); /* B2 = 12r + b2 */ gel(y,6) = nfadd(nf,ell_get_b2(e),gmul2n(rx3,2)); b2r = nfmul(nf,r, ell_get_b2(e)); r2 = nfsqr(nf,r); /* B4 = 6r^2 + b2 r + b4 */ gel(y,7) = nfadd(nf,b4,nfadd(nf,b2r, gmulsg(6,r2))); /* B6 = 4r^3 + 2b2 r^2 + 2b4 r + b6 */ gel(y,8) = nfadd(nf,b6,nfmul(nf,r,nfadd(nf,gmul2n(b4,1), nfadd(nf,b2r,gmul2n(r2,2))))); /* B8 = 3r^4 + b2 r^3 + 3b4 r^2 + 3b6 r + b8 */ p1 = nfadd(nf,gmulsg(3,b4),nfadd(nf,b2r, gmulsg(3,r2))); gel(y,9) = nfadd(nf,ell_get_b8(e), nfmul(nf,r,nfadd(nf,gmulsg(3,b6), nfmul(nf,r,p1)))); return y; } static GEN nf_coordch_s(GEN nf, GEN e, GEN s) { GEN a1, y; if (gequal0(s)) return e; a1 = ell_get_a1(e); y = leafcopy(e); /* A1 = a1 + 2s */ gel(y,1) = nfadd(nf,a1,gmul2n(s,1)); /* A2 = a2 - (a1 s + s^2) */ gel(y,2) = nfsub(nf,ell_get_a2(e),nfmul(nf,s,nfadd(nf,a1,s))); /* A4 = a4 - s a3 */ gel(y,4) = nfsub(nf,ell_get_a4(e),nfmul(nf,s,ell_get_a3(e))); return y; } /* apply [1,0,0,t] */ static GEN nf_coordch_t(GEN nf, GEN e, GEN t) { GEN a1, a3, y; if (gequal0(t)) return e; a1 = ell_get_a1(e); a3 = ell_get_a3(e); y = leafcopy(e); /* A3 = 2t + a3 */ gel(y,3) = nfadd(nf,a3, gmul2n(t,1)); /* A4 = a4 - a1 t */ gel(y,4) = nfsub(nf,ell_get_a4(e), nfmul(nf,t,a1)); /* A6 = a6 - t(t + a3) */ gel(y,5) = nfsub(nf,ell_get_a6(e), nfmul(nf,t,nfadd(nf,t, a3))); return y; } /* apply [1,0,s,t] */ static GEN nf_coordch_st(GEN nf, GEN e, GEN s, GEN t) { GEN y, a1, a3; if (gequal0(s)) return nf_coordch_t(nf, e, t); if (gequal0(t)) return nf_coordch_s(nf, e, s); a1 = ell_get_a1(e); a3 = ell_get_a3(e); y = leafcopy(e); /* A1 = a1 + 2s */ gel(y,1) = nfadd(nf,a1,gmul2n(s,1)); /* A2 = a2 - (a1 s + s^2) */ gel(y,2) = nfsub(nf,ell_get_a2(e),nfmul(nf,s,nfadd(nf,a1,s))); /* A3 = 2t + a3 */ gel(y,3) = nfadd(nf,a3,gmul2n(t,1)); /* A4 = a4 - (a1 t + s (2t + a3)) */ gel(y,4) = nfsub(nf,ell_get_a4(e),nfadd(nf,nfmul(nf,t,a1),nfmul(nf,s,gel(y,3)))); /* A6 = a6 - t(t + a3) */ gel(y,5) = nfsub(nf,ell_get_a6(e), nfmul(nf,t,nfadd(nf,t, a3))); return y; } static GEN nf_coordch_rt(GEN nf, GEN e, GEN r, GEN t) { e = nf_coordch_r(nf, e, r); return nf_coordch_t(nf, e, t); } /* apply [1,r,s,t] */ static GEN nf_coordch_rst(GEN nf, GEN e, GEN r, GEN s, GEN t) { e = nf_coordch_r(nf, e, r); return nf_coordch_st(nf, e, s, t); } /* apply w = [u,r,s,t] */ static GEN nf_coordch(GEN nf, GEN e, GEN w) { if (typ(w) == t_INT) return e; e = nf_coordch_rst(nf, e, gel(w,2), gel(w,3), gel(w,4)); return nf_coordch_uinv(nf, e, nfinv(nf, gel(w,1))); } /* apply [u^(-1),0,0,0] */ static GEN coordch_uinv(GEN e, GEN u) { GEN y, u2, u3, u4, u6, u12, D, c4, c6; long lx; if (gequal1(u)) return e; y = cgetg_copy(e, &lx); u2 = gsqr(u); u3 = gmul(u,u2); u4 = gsqr(u2); u6 = gsqr(u3); gel(y,1) = gmul(ell_get_a1(e), u); gel(y,2) = gmul(ell_get_a2(e), u2); gel(y,3) = gmul(ell_get_a3(e), u3); gel(y,4) = gmul(ell_get_a4(e), u4); gel(y,5) = gmul(ell_get_a6(e), u6); if (lx == 6) return y; gel(y,6) = gmul(ell_get_b2(e), u2); gel(y,7) = gmul(ell_get_b4(e), u4); gel(y,8) = gmul(ell_get_b6(e), u6); gel(y,9) = gmul(ell_get_b8(e), gsqr(u4)); u12 = gsqr(u6); D = ell_get_disc(e); c4 = ell_get_c4(e); c6 = ell_get_c6(e); c4 = gmul(c4, u4); c6 = gmul(c6, u6); D = gmul(D, u12); gel(y,10)= c4; gel(y,11)= c6; gel(y,12)= D; gel(y,13)= ell_get_j(e); gel(y,14)= gel(e,14); gel(y,15)= gel(e,15); gel(y,16)= gel(e,16); return y; } /* apply [1,r,0,0] */ static GEN coordch_r(GEN e, GEN r) { GEN a2, b4, b6, y, p1, r2, b2r, rx3; if (gequal0(r)) return e; y = leafcopy(e); a2 = ell_get_a2(e); rx3 = gmulsg(3,r); /* A2 = a2 + 3r */ gel(y,2) = gadd(a2,rx3); /* A3 = a1 r + a3 */ gel(y,3) = ec_h_evalx(e,r); /* A4 = 3r^2 + 2a2 r + a4 */ gel(y,4) = gadd(ell_get_a4(e), gmul(r,gadd(gmul2n(a2,1),rx3))); /* A6 = r^3 + a2 r^2 + a4 r + a6 */ gel(y,5) = ec_f_evalx(e,r); if (lg(y) == 6) return y; b4 = ell_get_b4(e); b6 = ell_get_b6(e); /* B2 = 12r + b2 */ gel(y,6) = gadd(ell_get_b2(e),gmul2n(rx3,2)); b2r = gmul(r, ell_get_b2(e)); r2 = gsqr(r); /* B4 = 6r^2 + b2 r + b4 */ gel(y,7) = gadd(b4,gadd(b2r, gmulsg(6,r2))); /* B6 = 4r^3 + 2b2 r^2 + 2b4 r + b6 */ gel(y,8) = gadd(b6,gmul(r,gadd(gmul2n(b4,1), gadd(b2r,gmul2n(r2,2))))); /* B8 = 3r^4 + b2 r^3 + 3b4 r^2 + 3b6 r + b8 */ p1 = gadd(gmulsg(3,b4),gadd(b2r, gmulsg(3,r2))); gel(y,9) = gadd(ell_get_b8(e), gmul(r,gadd(gmulsg(3,b6), gmul(r,p1)))); return y; } /* apply [1,0,s,0] */ static GEN coordch_s(GEN e, GEN s) { GEN a1, y; if (gequal0(s)) return e; a1 = ell_get_a1(e); y = leafcopy(e); /* A1 = a1 + 2s */ gel(y,1) = gadd(a1,gmul2n(s,1)); /* A2 = a2 - (a1 s + s^2) */ gel(y,2) = gsub(ell_get_a2(e),gmul(s,gadd(a1,s))); /* A4 = a4 - s a3 */ gel(y,4) = gsub(ell_get_a4(e),gmul(s,ell_get_a3(e))); return y; } /* apply [1,0,0,t] */ static GEN coordch_t(GEN e, GEN t) { GEN a1, a3, y; if (gequal0(t)) return e; a1 = ell_get_a1(e); a3 = ell_get_a3(e); y = leafcopy(e); /* A3 = 2t + a3 */ gel(y,3) = gadd(a3, gmul2n(t,1)); /* A4 = a4 - a1 t */ gel(y,4) = gsub(ell_get_a4(e), gmul(t,a1)); /* A6 = a6 - t(t + a3) */ gel(y,5) = gsub(ell_get_a6(e), gmul(t,gadd(t, a3))); return y; } /* apply [1,0,s,t] */ static GEN coordch_st(GEN e, GEN s, GEN t) { GEN y, a1, a3; if (gequal0(s)) return coordch_t(e, t); if (gequal0(t)) return coordch_s(e, s); a1 = ell_get_a1(e); a3 = ell_get_a3(e); y = leafcopy(e); /* A1 = a1 + 2s */ gel(y,1) = gadd(a1,gmul2n(s,1)); /* A2 = a2 - (a1 s + s^2) */ gel(y,2) = gsub(ell_get_a2(e),gmul(s,gadd(a1,s))); /* A3 = 2t + a3 */ gel(y,3) = gadd(a3,gmul2n(t,1)); /* A4 = a4 - (a1 t + s (2t + a3)) */ gel(y,4) = gsub(ell_get_a4(e),gadd(gmul(t,a1),gmul(s,gel(y,3)))); /* A6 = a6 - t(t + a3) */ gel(y,5) = gsub(ell_get_a6(e), gmul(t,gadd(t, a3))); return y; } /* apply [1,r,s,t] */ static GEN coordch_rst(GEN e, GEN r, GEN s, GEN t) { e = coordch_r(e, r); return coordch_st(e, s, t); } /* apply w = [u,r,s,t] */ static GEN coordch(GEN e, GEN w) { if (typ(w) == t_INT) return e; e = coordch_rst(e, gel(w,2), gel(w,3), gel(w,4)); return coordch_uinv(e, ginv(gel(w,1))); } /* the ch_* routines update E[14] (type), E[15] (type specific data), E[16] * (dynamic data) */ static GEN ch_Qp(GEN E, GEN e, GEN w) { GEN S, p = ellQp_get_zero(E), u2 = NULL, u = gel(w,1), r = gel(w,2); long prec = valp(p); if (base_ring(E, &p, &prec) != t_PADIC) return ellinit(E, p, prec); if ((S = obj_check(e, Qp_ROOT))) { if (!u2) u2 = gsqr(u); obj_insert_shallow(E, Qp_ROOT, gdiv(gsub(S, r), u2)); } if ((S = obj_check(e, Qp_TATE))) { GEN U2 = gel(S,1), U = gel(S,2), Q = gel(S,3), AB = gel(S,4), L = gel(S,5); if (!u2) u2 = gsqr(u); U2 = gmul(U2, u2); U = gmul(U, u); AB = gdiv(AB, u2); obj_insert_shallow(E, Qp_TATE, mkvec5(U2,U,Q,AB,L)); } return E; } /* common to Q and Rg */ static GEN ch_R(GEN E, GEN e, GEN w) { GEN S, u = gel(w,1), r = gel(w,2); if ((S = obj_check(e, R_PERIODS))) obj_insert_shallow(E, R_PERIODS, gmul(S, u)); if ((S = obj_check(e, R_ETA))) obj_insert_shallow(E, R_ETA, gmul(S, u)); if ((S = obj_check(e, R_ROOTS))) { GEN ro = cgetg(4, t_VEC), u2 = gsqr(u); long i; for (i = 1; i <= 3; i++) gel(ro,i) = gdiv(gsub(gel(S,i), r), u2); obj_insert_shallow(E, R_ROOTS, ro); } return E; } static GEN ch_Rg(GEN E, GEN e, GEN w) { GEN p = NULL; long prec = ellR_get_prec(E); if (base_ring(E, &p, &prec) != t_REAL) return ellinit(E, p, prec); ch_R(E, e, w); return E; } static GEN ch_NF(GEN E, GEN e, GEN w) { long prec = ellR_get_prec(E); GEN S, p = ellnf_get_nf(E); if (base_ring(E, &p, &prec) != t_VEC) return ellinit(E, p, prec); if ((S = obj_check(e, NF_MINIMALMODEL))) { if (lg(S) == 1) { /* model was minimal */ if (!is_trivial_change(w)) /* no longer minimal */ S = mkvec2(ellchangeinvert(w), e); } else if (lg(S)==3) { GEN v = gel(S,1); if (gequal(v, w) || (is_trivial_change(v) && is_trivial_change(w))) S = cgetg(1,t_VEC); /* now minimal */ else { w = ellchangeinvert(w); gcomposev(&w, v); S = mkvec2(w, gel(S,2)); } } (void)obj_insert_shallow(E, NF_MINIMALMODEL, S); } if ((S = obj_check(e, NF_GLOBALRED))) S = obj_insert_shallow(E, NF_GLOBALRED, S); if ((S = obj_check(e, NF_ROOTNO))) S = obj_insert_shallow(E, NF_ROOTNO, S); if ((S = obj_check(e, NF_NF))) S = obj_insert_shallow(E, NF_NF, S); return E; } static GEN ch_Q(GEN E, GEN e, GEN w) { long prec = ellR_get_prec(E); GEN S, p = NULL; if (base_ring(E, &p, &prec) != t_FRAC) return ellinit(E, p, prec); ch_R(E, e, w); if ((S = obj_check(e, Q_GROUPGEN))) S = obj_insert_shallow(E, Q_GROUPGEN, ellchangepoint(S, w)); if ((S = obj_check(e, Q_MINIMALMODEL))) { if (lg(S) == 2) { /* model was minimal */ if (!is_trivial_change(w)) /* no longer minimal */ S = mkvec3(gel(S,1), ellchangeinvert(w), e); } else { GEN v = gel(S,2); if (gequal(v, w) || (is_trivial_change(v) && is_trivial_change(w))) S = mkvec(gel(S,1)); /* now minimal */ else { w = ellchangeinvert(w); gcomposev(&w, v); S = leafcopy(S); /* don't modify S in place: would corrupt e */ gel(S,2) = w; } } (void)obj_insert_shallow(E, Q_MINIMALMODEL, S); } if ((S = obj_check(e, Q_GLOBALRED))) S = obj_insert_shallow(E, Q_GLOBALRED, S); if ((S = obj_check(e, Q_ROOTNO))) S = obj_insert_shallow(E, Q_ROOTNO, S); return E; } static void ch_FF(GEN E, GEN e, GEN w) { GEN S; if ((S = obj_check(e, FF_CARD))) S = obj_insert_shallow(E, FF_CARD, S); if ((S = obj_check(e, FF_GROUP))) S = obj_insert_shallow(E, FF_GROUP, S); if ((S = obj_check(e, FF_GROUPGEN))) S = obj_insert_shallow(E, FF_GROUPGEN, ellchangepoint(S, w)); if ((S = obj_check(e, FF_O))) S = obj_insert_shallow(E, FF_O, S); } /* FF_CARD, FF_GROUP, FF_O are invariant */ static GEN ch_Fp(GEN E, GEN e, GEN w) { long prec = 0; GEN p = ellff_get_field(E); if (base_ring(E, &p, &prec) != t_INTMOD) return ellinit(E, p, prec); gel(E,15) = mkvec2(p, ell_to_a4a6_bc(E, p)); ch_FF(E, e, w); return E; } static GEN ch_Fq(GEN E, GEN e, GEN w) { long prec = 0; GEN p = ellff_get_field(E); if (base_ring(E, &p, &prec) != t_FFELT) return ellinit(E, p, prec); gel(E,15) = FF_elldata(E, p); ch_FF(E, e, w); return E; } static void ell_reset(GEN E) { gel(E,16) = zerovec(lg(gel(E,16))-1); } GEN ellchangecurve(GEN e, GEN w) { pari_sp av = avma; GEN E; checkell5(e); if (isint1(w)) return gcopy(e); checkcoordch(w); E = coordch(leafcopy(e), w); if (lg(E) != 6) { ell_reset(E); switch(ell_get_type(E)) { case t_ELL_Qp: E = ch_Qp(E,e,w); break; case t_ELL_Fp: E = ch_Fp(E,e,w); break; case t_ELL_Fq: E = ch_Fq(E,e,w); break; case t_ELL_Q: E = ch_Q(E,e,w); break; case t_ELL_Rg: E = ch_Rg(E,e,w); break; case t_ELL_NF: E = ch_NF(E,e,w); break; } } return gerepilecopy(av, E); } static GEN ellQ_isisom(GEN E, GEN F) { pari_sp av = avma; GEN j, u, r, s, t, u2, u3; GEN Ea1, Ea2, Ea3, Ec4, Ec6, Fa1, Fa2, Fa3, Fc4, Fc6; j = ell_get_j(E); if (!gequal(j, ell_get_j(F))) return gen_0; Ec4 = ell_get_c4(E); Ec6 = ell_get_c6(E); Fc4 = ell_get_c4(F); Fc6 = ell_get_c6(F); if (gequal0(j)) { if (!ispower(gdiv(Ec6, Fc6), utoi(6), &u)) return gc_const(av, gen_0); } else if(gequalgs(j, 1728)) { if (!ispower(gdiv(Ec4, Fc4), utoi(4), &u)) return gc_const(av, gen_0); } else { if (!issquareall(gdiv(gmul(Fc4, Ec6),gmul(Fc6,Ec4)),&u)) return gc_const(av, gen_0); } Ea1 = ell_get_a1(E); Ea2 = ell_get_a2(E); Ea3 = ell_get_a3(E); Fa1 = ell_get_a1(F); Fa2 = ell_get_a2(F); Fa3 = ell_get_a3(F); u2 = gsqr(u); u3 = gmul(u,u2); s = gdivgs(gsub(gmul(u, Fa1), Ea1), 2); r = gdivgs(gadd(gsub(gadd(gmul(u2, Fa2), gmul(s, Ea1)), Ea2), gsqr(s)), 3); t = gdivgs(gsub(gsub(gmul(u3, Fa3), gmul(r, Ea1)), Ea3), 2); return gerepilecopy(av, mkvec4(u,r,s,t)); } static GEN ellnf_isisom(GEN nf, GEN E, GEN F) { pari_sp av = avma; GEN j, u, r, s, t, u2, u3; GEN Ea1, Ea2, Ea3, Ec4, Ec6, Fa1, Fa2, Fa3, Fc4, Fc6; j = basistoalg(nf, ell_get_j(E)); if (!gequal(j, basistoalg(nf, ell_get_j(F)))) return gc_const(av, gen_0); Ec4 = ell_get_c4(E); Ec6 = ell_get_c6(E); Fc4 = ell_get_c4(F); Fc6 = ell_get_c6(F); if (gequal0(j)) { if (!nfispower(nf, nfdiv(nf, Ec6, Fc6), 6, &u)) return gc_const(av, gen_0); } else if(gequalgs(j, 1728)) { if (!nfispower(nf, nfdiv(nf, Ec4, Fc4), 4, &u)) return gc_const(av, gen_0); } else { if (!nfissquare(nf, nfdiv(nf, nfmul(nf, Fc4, Ec6), nfmul(nf, Fc6,Ec4)), &u)) return gc_const(av, gen_0); } Ea1 = ell_get_a1(E); Ea2 = ell_get_a2(E); Ea3 = ell_get_a3(E); Fa1 = ell_get_a1(F); Fa2 = ell_get_a2(F); Fa3 = ell_get_a3(F); u2 = nfsqr(nf,u); u3 = nfmul(nf,u,u2); s = gdivgs(nfsub(nf, nfmul(nf, u, Fa1), Ea1),2); r = gdivgs(nfadd(nf, nfsub(nf, nfadd(nf, nfmul(nf, u2, Fa2), nfmul(nf, s, Ea1)), Ea2), nfsqr(nf, s)), 3); t = gdivgs(nfsub(nf, nfsub(nf, nfmul(nf, u3, Fa3), nfmul(nf, r, Ea1)), Ea3), 2); u = basistoalg(nf, u); r = basistoalg(nf, r); s = basistoalg(nf, s); t = basistoalg(nf, t); return gerepilecopy(av, mkvec4(u,r,s,t)); } GEN ellisisom(GEN E, GEN F) { checkell(E); checkell(F); if (ell_get_type(E)!=ell_get_type(F)) pari_err_TYPE("ellisisom", mkvec2(E,F)); switch(ell_get_type(E)) { case t_ELL_Q: return ellQ_isisom(E, F); case t_ELL_NF: if (gequal(ellnf_get_nf(E), ellnf_get_nf(F))) return ellnf_isisom(ellnf_get_nf(E), E, F); default: /*FALL THROUGH*/ pari_err_TYPE("ellisisom", mkvec2(E,F)); return NULL;/*LCOV_EXCL_LINE*/ } } /* v o= [1,r,0,0] */ static void nf_compose_r(GEN nf, GEN *vtotal, GEN *e, GEN r) { GEN v = *vtotal; GEN U2, R, S, T; if (gequal0(r)) return; *e = nf_coordch_r(nf, *e,r); U2 = nfsqr(nf,gel(v,1)); R = gel(v,2); S = gel(v, 3); T = gel(v, 4); gel(v,2) = nfadd(nf,R, nfmul(nf,U2, r)); gel(v,4) = nfadd(nf,T, nfmul(nf,U2, nfmul(nf,S, r))); } /* v o= [1,0,s,0]; never used for s = 0 */ static void nf_compose_s(GEN nf, GEN *vtotal, GEN *e, GEN s) { GEN v = *vtotal; GEN U, S; *e = nf_coordch_s(nf,*e,s); U = gel(v,1); S = gel(v,3); gel(v,3) = nfadd(nf, S, nfmul(nf, U, s)); } /* v o= [1,0,0,t] */ static void nf_compose_t(GEN nf ,GEN *vtotal, GEN *e, GEN t) { GEN v = *vtotal; GEN U3, U, T; if (gequal0(t)) return; *e = nf_coordch_t(nf,*e,t); U = gel(v,1); U3 = nfmul(nf,U, nfsqr(nf,U)); T = gel(v,4); gel(v,4) = nfadd(nf,T, nfmul(nf,U3, t)); } /* v o= [1,r,0,t] */ static void nf_compose_rt(GEN nf, GEN *vtotal, GEN *e, GEN r, GEN t) { GEN v = *vtotal; GEN U2, U, R, S, T; if (gequal0(t)) { nf_compose_r(nf, vtotal, e, r); return; } *e = nf_coordch_rt(nf,*e,r,t); U = gel(v,1); R = gel(v,2); S = gel(v,3); T = gel(v,4); U2 = nfsqr(nf,U); gel(v,2) = nfadd(nf,R, nfmul(nf,U2, r)); gel(v,4) = nfadd(nf,T, nfmul(nf,U2, nfadd(nf,nfmul(nf,U, t), nfmul(nf,S, r)))); } /* v o= [1,0,s,t] */ static void nf_compose_st(GEN nf, GEN *vtotal, GEN *e, GEN s, GEN t) { GEN v = *vtotal; GEN U3, U, S, T; if (gequal0(s)) { nf_compose_t(nf, vtotal, e, t); return; } if (gequal0(t)) { nf_compose_s(nf, vtotal, e, s); return; } *e = nf_coordch_st(nf, *e,s,t); U = gel(v,1); U3 = nfmul(nf,U,nfsqr(nf,U)); S = gel(v,3); T = gel(v,4); gel(v,3) = nfadd(nf, S, nfmul(nf,U, s)); gel(v,4) = nfadd(nf, T, nfmul(nf,U3, t)); } /* v o= [u,0,0,0] */ static void nf_compose_u(GEN nf, GEN *vtotal, GEN *e, GEN u, GEN uinv) { GEN v = *vtotal; *e = nf_coordch_uinv(nf, *e,uinv); gel(v,1) = nfmul(nf,gel(v,1), u); } /* X = (x-r)/u^2 * Y = (y - s(x-r) - t) / u^3 */ static GEN ellchangepoint_i(GEN P, GEN v2, GEN v3, GEN r, GEN s, GEN t) { GEN a, x, y; if (!checkellpt_i(P)) pari_err_TYPE("ellchangepoint",P); if (ell_is_inf(P)) return P; x = gel(P,1); y = gel(P,2); a = gsub(x,r); retmkvec2(gmul(v2, a), gmul(v3, gsub(y, gadd(gmul(s,a),t)))); } GEN ellchangepoint(GEN x, GEN ch) { GEN y, v, v2, v3, r, s, t, u; long tx, i, lx = lg(x); pari_sp av = avma; if (typ(x) != t_VEC) pari_err_TYPE("ellchangepoint",x); if (isint1(ch)) return gcopy(x); checkcoordch(ch); if (lx == 1) return cgetg(1, t_VEC); u = gel(ch,1); r = gel(ch,2); s = gel(ch,3); t = gel(ch,4); v = ginv(u); v2 = gsqr(v); v3 = gmul(v,v2); tx = typ(gel(x,1)); if (is_vec_t(tx)) { y = cgetg(lx,tx); for (i=1; i= 6. * If nontrivial, v(d2) = 2 or 3 and let t = [(vg+6v(d2))/12]. * Good case if reduction in ellQ_minimalu i.e. t = 2 (v4 < 6 or v6 < 9 or * vD < 18) or 3 and "d--" does not occur. Minimal model => t = 3 iff * v4 = 6, v6 = 9 and vD >= 18. Total net effect is * v4 += 2v(d2) - 4t, v6 += 3v(d2) - 6t, vD += 6 v(d2) - 12t * After rescaling in ellQ_minimalu (c4 >>= 4t, c6 >>= 6t) we need * c6 % 4 = 3 OR (v4 >= 4 AND (v6 >= 5 or c6 % 32 = 8)) */ static long twist2(GEN c4, GEN c6, GEN disc, long vg) { /* v4 >= 4, v6 >= 3 (and c6 = 0,8 mod 32). After twist + minimization, * either same condition OR v(C4) = 0, C6 = 0,3 mod 4 */ long v4, v6, vD; if (vg == 18) /* v4=6, v6=9, vD>=18; only case with t = 3 */ return (umodi2n(c6, 11)>>9) == 1 ? -8: 8; /* need C6 % 4 = 3 */ /* 100 = oo, any number >= 8 would do */ v4 = signe(c4)? vali(c4): 100; if (v4 == 5) return 1; /* 100 = oo, any number > 9 would do */ v6 = signe(c6)? vali(c6): 100; if (v6 == 7) return 1; /* handle case v(DISC) = 0 or v(C4) = 0 after twist, only case with d2 = -4 */ if (vg == 12 && ((v4==4 && v6==6) || (v4>=8 && v6==9))) return -4; /* Now, d2 = 1 OR v(d2) = 3, t = 2 => v4 -= 2, v6 -= 3, vD -= 6 */ if (v4 < 6 || v6 < 6) return 1; /* v(C4) >= 4, v(C6) >= 3 */ vD = vali(disc); if (v6==6 && vD==6 && (umodi2n(c6,8)>>6) == 1) return 8; /* C6 % 32 = 8 */ return -8; } /* Return D such that E_D has minimal discriminant. It also has minimal * conductor in Z[1/2] */ GEN ellminimaltwist(GEN e) { pari_sp av = avma; GEN c4, c6, disc, g, N, M, F, E, D = gen_1; long i, lF; checkell_Q(e); E = ellminimalmodel(e, NULL); c4 = ell_get_c4(E); c6 = ell_get_c6(E); disc = ell_get_disc(E); g = gcdii(disc, sqri(c6)); ellQ_get_Nfa(E, &N, &M); F = gel(M, 1); lF = lg(F); /* on twist by d, (c4,c6,D,g) -> (d^2 c4, d^3 c6, d^6 D, d^6 g), * then apply ellQ_minimalu(). Since model is minimal, v(g) < 12 unless p=3 * and v(g) < 14 or p = 2 and v(g) <= 18 */ for(i = 1; i < lF; i++) { GEN p = gel(F, i); long vg = Z_pval(g,p), d2; if (vg < 6) continue; /* twist by fund. discriminant d2; in ellQ_minimalu, * we have v(g) = vg + 6*v(d2) */ switch(itou_or_0(p)) { default: /* p > 3, 6 <= v(g) < 12 => v(D) -= 6 */ D = mulii(D, (mod4(p)==1)? p: negi(p)); break; case 3: /* bad case: v(final_c6) = 2 => no reduction; else v(D) -= 6 */ if (safe_Z_lval(c6,3) != 5) D = mulis(D, -3); break; case 2: d2 = twist2(c4,c6,disc,vg); if (d2 != 1) D = mulis(D,d2); break; } } obj_free(E); return gerepileuptoleaf(av, D); } /* Reference: William A. Stein and Mark Watkins A Database of Elliptic Curves-First Report ANTS 5 */ static GEN localred_23(GEN e, long p); GEN ellminimaltwistcond(GEN e) { pari_sp av = avma; GEN D = ellminimaltwist(e), eD = elltwist(e, D); GEN R = localred_23(ellintegralmodel_i(eD,NULL), 2); long f = itos(gel(R,1)), v = vali(D); if (f==4) D = negi(v==3 ? D: shifti(D, v==0? 2: -2)); else if (f==6) { long s, t; if (v < 3) s = v==0? 3: 1; else { t = (v==3 && mod32(D) == 8)? 1: -1; s = signe(D)==t ? -3: -1; } D = shifti(D, s); } return gerepileuptoleaf(av, D); } GEN ellminimaltwist0(GEN e, long flag) { switch(flag) { case 0: return ellminimaltwist(e); case 1: return ellminimaltwistcond(e); } pari_err_FLAG("ellminimaltwist"); return NULL; /* LCOV_EXCL_LINE */ } static long ellexpo(GEN E) { long i, f, e = -(long)HIGHEXPOBIT; for (i=1; i<=5; i++) { f = gexpo(gel(E,i)); if (f > e) e = f; } return e; } static int oncurve_exact(GEN e, GEN z) { pari_sp av = avma; GEN A = ec_LHS_evalQ(e,z), B = ec_f_evalx(e,gel(z,1)); return gc_bool(av, gequal(A, B)); } /* Exactness of lhs and rhs in the following depends in nonobvious 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; if (!checkellpt_i(z)) return 0; if (ell_is_inf(z)) return 1; /* oo */ if (ell_get_type(e) == t_ELL_NF) z = nfVtoalg(ellnf_get_nf(e), z); av = avma; LHS = ec_LHS_evalQ(e,z); RHS = ec_f_evalx(e,gel(z,1)); x = gsub(LHS,RHS); if (gequal0(x)) return gc_bool(av,1); pl = precision(LHS); pr = precision(RHS); if (!pl && !pr) return gc_bool(av,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 - pr + 15 || expx < ellexpo(e) - pr + 5); return gc_bool(av,pr); } GEN ellisoncurve(GEN e, GEN x) { long i, tx = typ(x), lx; checkell(e); if (!is_vec_t(tx)) pari_err_TYPE("ellisoncurve [point]", x); lx = lg(x); if (lx==1) return cgetg(1,tx); tx = typ(gel(x,1)); if (is_vec_t(tx)) { GEN z = cgetg(lx,tx); for (i=1; i= gexpo(y1)); else eq = gequal(y1,y2); if (!eq) return NULL; } dx = ec_dmFdy_evalQ(e,mkvec2(x,y1)); if (gequal0(dx)) return NULL; dy = gadd(gsub(ell_get_a4(e),gmul(ell_get_a1(e),y1)), gmul(x,gadd(gmul2n(ell_get_a2(e),1),gmulsg(3,x)))); return gdiv(dy,dx); } GEN elladd(GEN e, GEN z1, GEN z2) { GEN s, z, x, y, x1, x2, y1, y2; pari_sp av = avma; checkell(e); if (!checkellpt_i(z1)) pari_err_TYPE("elladd", z1); if (!checkellpt_i(z2)) pari_err_TYPE("elladd", z2); if (ell_is_inf(z1)) return gcopy(z2); if (ell_is_inf(z2)) return gcopy(z1); x1 = gel(z1,1); y1 = gel(z1,2); x2 = gel(z2,1); y2 = gel(z2,2); if (ell_get_type(e) == t_ELL_NF) { GEN nf = ellnf_get_nf(e); x1 = nftoalg(nf, x1); x2 = nftoalg(nf, x2); y1 = nftoalg(nf, y1); y2 = nftoalg(nf, y2); } if (cx_approx_equal(x1,x2)) { s = slope_samex(e, x1, y1, y2); if (!s) { set_avma(av); return ellinf(); } } else s = gdiv(gsub(y2,y1), gsub(x2,x1)); x = gsub(gmul(s,gadd(s,ell_get_a1(e))), gadd(gadd(x1,x2),ell_get_a2(e))); y = gadd(gadd(y1, ec_h_evalx(e,x)), gmul(s,gsub(x,x1))); z = cgetg(3,t_VEC); gel(z,1) = gcopy(x); gel(z,2) = gneg(y); return gerepileupto(av, z); } static GEN ellneg_i(GEN e, GEN z) { GEN x, y; if (ell_is_inf(z)) return z; x = gel(z,1); y = gel(z,2); if (ell_get_type(e) == t_ELL_NF) { GEN nf = ellnf_get_nf(e); x = nftoalg(nf,x); y = nftoalg(nf,y); } retmkvec2(x, gneg_i(gadd(y, ec_h_evalx(e,x)))); } GEN ellneg(GEN e, GEN z) { pari_sp av; GEN t, y; checkell(e); if (!checkellpt_i(z)) pari_err_TYPE("ellneg", z); if (ell_is_inf(z)) return z; t = cgetg(3,t_VEC); gel(t,1) = gcopy(gel(z,1)); av = avma; y = gneg(gadd(gel(z,2), ec_h_evalx(e,gel(z,1)))); gel(t,2) = gerepileupto(av, y); return t; } GEN ellsub(GEN e, GEN z1, GEN z2) { pari_sp av = avma; checkell(e); if (!checkellpt_i(z1)) pari_err_TYPE("ellsub", z1); if (!checkellpt_i(z2)) pari_err_TYPE("ellsub", z2); return gerepileupto(av, elladd(e, z1, ellneg_i(e,z2))); } /* E an ell, x a scalar */ static GEN ellordinate_i(GEN E, GEN x, long prec) { pari_sp av = avma; GEN a, b, D, d, y, p, nf = NULL; if (ell_get_type(E) == t_ELL_NF) { nf = ellnf_get_nf(E); x = nftoalg(nf,x); } a = ec_f_evalx(E,x); b = ec_h_evalx(E,x); D = gadd(gsqr(b), gmul2n(a,2)); /* solve y*(y+b) = a */ if (gequal0(D)) { if (ell_get_type(E) == t_ELL_Fq && absequaliu(ellff_get_p(E),2)) retmkvec( FF_sqrt(a) ); b = gneg_i(b); y = cgetg(2,t_VEC); gel(y,1) = gmul2n(b,-1); return gerepileupto(av,y); } /* D != 0 */ switch(ell_get_type(E)) { case t_ELL_Fp: /* imply p!=2 */ p = ellff_get_p(E); D = gel(D,2); if (kronecker(D, p) < 0) { set_avma(av); return cgetg(1,t_VEC); } d = Fp_sqrt(D, p); break; case t_ELL_Fq: if (absequaliu(ellff_get_p(E),2)) { GEN F = FFX_roots(mkpoln(3, gen_1, b, a), D); if (lg(F) == 1) { set_avma(av); return cgetg(1,t_VEC); } return gerepileupto(av, F); } if (!FF_issquareall(D,&d)) { set_avma(av); return cgetg(1,t_VEC); } break; case t_ELL_Q: if (typ(x) == t_COMPLEX) { d = gsqrt(D, prec); break; } if (!issquareall(D,&d)) { set_avma(av); return cgetg(1,t_VEC); } break; case t_ELL_NF: if (!nfissquare(nf, D, &d)) { set_avma(av); return cgetg(1,t_VEC); } d = nftoalg(nf, d); break; case t_ELL_Qp: p = ellQp_get_p(E); D = cvtop(D, p, ellQp_get_prec(E)); if (!issquare(D)) { set_avma(av); return cgetg(1,t_VEC); } d = Qp_sqrt(D); break; default: d = gsqrt(D,prec); } a = gsub(d,b); y = cgetg(3,t_VEC); gel(y,1) = gmul2n(a, -1); gel(y,2) = gsub(gel(y,1),d); return gerepileupto(av,y); } GEN ellordinate(GEN e, GEN x, long prec) { checkell(e); if (is_matvec_t(typ(x))) { long i, lx; GEN v = cgetg_copy(x, &lx); for (i=1; i>1)-4)>>2; z1 = ellwpseries(e, 0, ln); z2 = ser_unscale(z1, n); p0 = gen_0; p1 = gen_1; q0 = gen_1; q1 = gen_0; do { GEN p2,q2, ss = gen_0; do { long ep = (-valser(z2)) >> 1; ss = gadd(ss, gmul(gel(z2,2), pol_xnall(ep, 0))); z2 = gsub(z2, gmul(gel(z2,2), gpowgs(z1, ep))); } while (valser(z2) <= 0); p2 = gadd(p0, gmul(ss,p1)); p0 = p1; p1 = p2; q2 = gadd(q0, gmul(ss,q1)); q0 = q1; q1 = q2; if (!signe(z2)) break; z2 = ginv(z2); } while (degpol(p1) < vn); if (degpol(p1) > vn || signe(z2)) pari_err_TYPE("ellmul [not a complex multiplication]", n); q1p = RgX_deriv(q1); b2ov12 = gdivgu(ell_get_b2(e), 12); grdx = gadd(gel(P,1), b2ov12); /* x(P) + b2/12 */ 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(ec_dmFdy_evalQ(e,P), y), ec_h_evalx(e,x)); return mkvec2(x, gmul2n(y,-1)); } static GEN _sqr(void *e, GEN x) { return elladd((GEN)e, x, x); } static GEN _mul(void *e, GEN x, GEN y) { return elladd((GEN)e, x, y); } static GEN ellffmul(GEN E, GEN P, GEN n) { GEN fg = ellff_get_field(E); if (typ(fg)==t_FFELT) return FF_ellmul(E, P, n); else { pari_sp av = avma; GEN p = fg, e = ellff_get_a4a6(E), Q; GEN Pp = FpE_changepointinv(RgE_to_FpE(P, p), gel(e,3), p); GEN Qp = FpE_mul(Pp, n, gel(e,1), p); Q = FpE_to_mod(FpE_changepoint(Qp, gel(e,3), p), p); return gerepileupto(av, Q); } } /* [n] z, n integral */ static GEN ellmul_Z(GEN e, GEN z, GEN n) { long s; if (ell_is_inf(z)) return ellinf(); if (ell_over_Fq(e)) return ellffmul(e,z,n); s = signe(n); if (!s) return ellinf(); if (s < 0) z = ellneg_i(e,z); if (is_pm1(n)) return z; return gen_pow(z, n, (void*)e, &_sqr, &_mul); } /* x a t_REAL, try to round it to an integer */ enum { OK, LOW_PREC, NO }; static long myroundr(GEN *px) { GEN x = *px; long e; if (bit_prec(x) - expo(x) < 5) return LOW_PREC; *px = grndtoi(x, &e); if (e >= -5) return NO; return OK; } /* E has CM by Q, t_COMPLEX or t_QUAD. Return q such that E has CM by Q/q * or gen_1 (couldn't find q > 1) * or NULL (doesn't have CM by Q) */ static GEN CM_factor(GEN E, GEN Q) { GEN w, tau, D, v, x, y, F, dF, q, r, fk, fkb, fkc; long prec; if (ell_get_type(E) != t_ELL_Q) return gen_1; switch(typ(Q)) { case t_COMPLEX: D = utoineg(4); v = gel(Q,2); break; case t_QUAD: D = quad_disc(Q); v = gel(Q,3); break; default: return NULL; /*-Wall*/ } /* disc Q = v^2 D, D < 0 fundamental */ w = ellR_omega(E, DEFAULTPREC + nbits2extraprec(expi(D))); tau = gdiv(gel(w,2), gel(w,1)); prec = precision(tau); /* disc tau = -4 k^2 (Im tau)^2 for some integral k * Assuming that E has CM by Q, then disc Q / disc tau = f^2 is a square. * Compute f*k */ x = gel(tau,1); y = gel(tau,2); /* tau = x + Iy */ fk = gmul(gdiv(v, gmul2n(y, 1)), sqrtr_abs(itor(D, prec))); switch(myroundr(&fk)) { case NO: return NULL; case LOW_PREC: return gen_1; } fk = absi_shallow(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_disc3(gel(F,1), gel(F,2), gel(F,3)); /* = 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_shallow(v), q, &r); if (r != gen_0) return NULL; return is_pm1(v)? gen_1: v; /* E has CM by Q/q: [Q] = [q] o [Q/q] */ } /* [a + w] z, a integral, w pure imaginary */ static GEN ellmul_CM_aux(GEN e, GEN z, GEN a, GEN w) { GEN A, B, q; if (typ(a) != t_INT) pari_err_TYPE("ellmul_Z",a); q = CM_factor(e, w); if (!q) pari_err_TYPE("ellmul [not a complex multiplication]",w); if (q != gen_1) w = gdiv(w, q); /* compute [a + q w] z, z has CM by w */ if (typ(w) == t_QUAD && is_pm1(gel(gel(w,1), 3))) { /* replace w by w - u, u in Z, so that N(w-u) is minimal * N(w - u) = N w - Tr w u + u^2, minimal for u = Tr w / 2 */ GEN u = gtrace(w); if (typ(u) != t_INT) pari_err_TYPE("ellmul_CM",w); u = shifti(u, -1); if (signe(u)) { w = gsub(w, u); a = addii(a, mulii(q,u)); } /* [a + w]z = [(a + qu)] z + [q] [(w - u)] z */ } A = ellmul_Z(e,z,a); B = ellmul_CM(e,z,w); if (q != gen_1) B = ellmul_Z(e, B, q); return elladd(e, A, B); } GEN ellmul(GEN e, GEN z, GEN n) { pari_sp av = avma; checkell(e); if (!checkellpt_i(z)) pari_err_TYPE("ellmul", z); if (ell_is_inf(z)) return ellinf(); switch(typ(n)) { case t_INT: return gerepilecopy(av, ellmul_Z(e,z,n)); case t_QUAD: { GEN pol = gel(n,1), a = gel(n,2), b = gel(n,3); if (signe(gel(pol,2)) < 0) pari_err_TYPE("ellmul_CM",n); /* disc > 0 ? */ return gerepileupto(av, ellmul_CM_aux(e,z,a,mkquad(pol, gen_0,b))); } case t_COMPLEX: { GEN a = gel(n,1), b = gel(n,2); return gerepileupto(av, ellmul_CM_aux(e,z,a,mkcomplex(gen_0,b))); } } pari_err_TYPE("ellmul (non integral, non CM exponent)",n); return NULL; /* LCOV_EXCL_LINE */ } /********************************************************************/ /** **/ /** Periods **/ /** **/ /********************************************************************/ /* References: The complex AGM, periods of elliptic curves over C and complex elliptic logarithms John E. Cremona, Thotsaphon Thongjunthug, arXiv:1011.0914 */ static GEN ellomega_agm(GEN a, GEN b, GEN c, long prec) { GEN pi = mppi(prec), mIpi = mkcomplex(gen_0, negr(pi)); GEN Mac = agm(a,c,prec), Mbc = agm(b,c,prec); retmkvec2(gdiv(pi, Mac), gdiv(mIpi, Mbc)); } static GEN ellomega_cx(GEN E, long prec) { pari_sp av = avma; GEN roots = ellR_roots(E, prec + EXTRAPREC64); GEN d1=gel(roots,4), d2=gel(roots,5), d3=gel(roots,6); GEN a = gsqrt(d3,prec), b = gsqrt(d1,prec), c = gsqrt(d2,prec); return gerepileupto(av, ellomega_agm(a,b,c,prec)); } /* return [w1,w2] for E / R; w1 > 0 is real. * If e.disc > 0, w2 = -I r; else w2 = w1/2 - I r, for some real r > 0. * => tau = w1/w2 is in upper half plane */ static GEN doellR_omega(GEN E, long prec) { pari_sp av = avma; GEN roots, d2, z, a, b, c; if (ellR_get_sign(E) >= 0) return ellomega_cx(E,prec); roots = ellR_roots(E,prec + EXTRAPREC64); d2 = gel(roots,5); z = gsqrt(d2,prec); /* imag(e1-e3) > 0, so that b > 0*/ a = gel(z,1); /* >= 0 */ b = gel(z,2); c = gabs(z, prec); z = ellomega_agm(a,b,c,prec); return gerepilecopy(av, mkvec2(gel(z,1),gmul2n(gadd(gel(z,1),gel(z,2)),-1))); } static GEN doellR_eta(GEN E, long prec) { GEN w = ellR_omega(E, prec + EXTRAPREC64); return elleta(w, prec); } GEN ellR_omega(GEN E, long prec) { return obj_checkbuild_realprec(E, R_PERIODS, &doellR_omega, prec); } GEN ellR_eta(GEN E, long prec) { return obj_checkbuild_realprec(E, R_ETA, &doellR_eta, prec); } GEN ellR_roots(GEN E, long prec) { return obj_checkbuild_realprec(E, R_ROOTS, &doellR_roots, prec); } GEN ellR_area(GEN E, long prec) { pari_sp av = avma; GEN w, w1, w2, a,b,c,d; w = ellR_omega(E, prec); w1 = gel(w,1); a = real_i(w1); b = imag_i(w1); w2 = gel(w,2); c = real_i(w2); d = imag_i(w2); return gerepileupto(av, gabs(gsub(gmul(a,d),gmul(b,c)), prec)); } /********************************************************************/ /** **/ /** ELLIPTIC FUNCTIONS **/ /** **/ /********************************************************************/ /* P = [x,0] is 2-torsion on y^2 = g(x). Return w1/2, (w1+w2)/2, or w2/2 * depending on whether x is closest to e1,e2, or e3, the 3 complex root of g */ static GEN zell_closest_0(GEN om, GEN x, GEN ro) { GEN e1 = gel(ro,1), e2 = gel(ro,2), e3 = gel(ro,3); GEN d1 = gnorm(gsub(x,e1)); GEN d2 = gnorm(gsub(x,e2)); GEN d3 = gnorm(gsub(x,e3)); GEN z = gel(om,2); if (gcmp(d1, d2) <= 0) { if (gcmp(d1, d3) <= 0) z = gel(om,1); } else { if (gcmp(d2, d3)<=0) z = gadd(gel(om,1),gel(om,2)); } return gmul2n(z, -1); } static GEN zellcx(GEN E, GEN P, long prec) { GEN R = ellR_roots(E, prec+EXTRAPREC64); GEN x0 = gel(P,1), y0 = ec_dmFdy_evalQ(E,P); if (gequal0(y0)) return zell_closest_0(ellomega_cx(E,prec),x0,R); else { GEN e2 = gel(R,2), e3 = gel(R,3), d2 = gel(R,5), d3 = gel(R,6); GEN a = gsqrt(d2,prec), b = gsqrt(d3,prec); GEN r = gsqrt(gdiv(gsub(x0,e3), gsub(x0,e2)),prec); GEN t = gdiv(gneg(y0), gmul2n(gmul(r,gsub(x0,e2)),1)); GEN ar = real_i(a), br = real_i(b), ai = imag_i(a), bi = imag_i(b); /* |a+b| < |a-b| */ if (gcmp(gmul(ar,br), gneg(gmul(ai,bi))) < 0) b = gneg(b); return zellagmcx(a,b,r,t,prec); } } /* Assume E/R, disc E < 0, and P \in E(R) ==> z \in R */ static GEN zellrealneg(GEN E, GEN P, long prec) { GEN x0 = gel(P,1), y0 = ec_dmFdy_evalQ(E,P); if (gequal0(y0)) return gmul2n(gel(ellR_omega(E,prec),1),-1); else { GEN R = ellR_roots(E, prec+EXTRAPREC64); GEN d2 = gel(R,5), e3 = gel(R,3); GEN a = gsqrt(d2,prec); GEN z = gsqrt(gsub(x0,e3), prec); GEN ar = real_i(a), zr = real_i(z), ai = imag_i(a), zi = imag_i(z); GEN t = gdiv(gneg(y0), gmul2n(gnorm(z),1)); GEN r2 = ginv(gsqrt(gaddsg(1,gdiv(gmul(ai,zi),gmul(ar,zr))),prec)); return zellagmcx(ar,gabs(a,prec),r2,gmul(t,r2),prec); } } /* Assume E/R, disc E > 0, and P \in E(R) */ static GEN zellrealpos(GEN E, GEN P, long prec) { GEN R = ellR_roots(E, prec+EXTRAPREC64); GEN d2,d3,e1,e2,e3, a,b, x0 = gel(P,1), y0 = ec_dmFdy_evalQ(E,P); if (gequal0(y0)) return zell_closest_0(ellR_omega(E,prec), x0,R); e1 = gel(R,1); e2 = gel(R,2); e3 = gel(R,3); d2 = gel(R,5); d3 = gel(R,6); a = gsqrt(d2,prec); b = gsqrt(d3,prec); if (gcmp(x0,e1)>0) { GEN r = gsqrt(gdiv(gsub(x0,e3), gsub(x0,e2)),prec); GEN t = gdiv(gneg(y0), gmul2n(gmul(r,gsub(x0,e2)),1)); return zellagmcx(a,b,r,t,prec); } else { GEN om = ellR_omega(E,prec); GEN r = gdiv(a,gsqrt(gsub(e1,x0),prec)); GEN t = gdiv(gmul(r,y0),gmul2n(gsub(x0,e3),1)); return gsub(zellagmcx(a,b,r,t,prec),gmul2n(gel(om,2),-1)); } } static void ellQp_P2t_err(GEN E, GEN z) { if (typ(ellQp_u(E,1)) == t_POLMOD) pari_err_IMPL("ellpointtoz when u not in Qp"); pari_err_DOMAIN("ellpointtoz", "point", "not on", strtoGENstr("E"),z); } static GEN get_r0(GEN E, long prec) { GEN b2 = ell_get_b2(E), e1 = ellQp_root(E, prec); return gadd(e1,gmul2n(b2,-2)); } static GEN ellQp_P2t(GEN E, GEN P, long prec) { pari_sp av = avma; GEN a, b, ab, c0, r0, ar, r, x, delta, x1, y1, t, u, q; long vq, vt, Q, R; if (ell_is_inf(P)) return gen_1; ab = ellQp_ab(E, prec); a = gel(ab,1); b = gel(ab,2); u = ellQp_u(E, prec); q = ellQp_q(E, prec); x = gel(P,1); r0 = get_r0(E, prec); c0 = gadd(x, gmul2n(r0,-1)); if (typ(c0) != t_PADIC || !is_scalar_t(typ(gel(P,2)))) pari_err_TYPE("ellpointtoz",P); r = gsub(a,b); ar = gmul(a, r); if (gequal0(c0)) { x1 = Qp_sqrt(gneg(ar)); if (!x1) ellQp_P2t_err(E,P); } else { delta = gdiv(ar, gsqr(c0)); t = Qp_sqrt(gsubsg(1,gmul2n(delta,2))); if (!t) ellQp_P2t_err(E,P); x1 = gmul(gmul2n(c0,-1), gaddsg(1,t)); } y1 = gsubsg(1, gdiv(ar, gsqr(x1))); if (gequal0(y1)) { y1 = Qp_sqrt(gmul(x1, gmul(gadd(x1, a), gadd(x1, r)))); if (!y1) ellQp_P2t_err(E,P); } else y1 = gdiv(gmul2n(ec_dmFdy_evalQ(E,P), -1), y1); Qp_descending_Landen(ellQp_AGM(E,prec), &x1,&y1); t = gmul(u, gmul2n(y1,1)); /* 2u y_oo */ t = gdiv(gsub(t, x1), gadd(t, x1)); /* Reduce mod q^Z: we want 0 <= v(t) < v(q) */ if (typ(t) == t_PADIC) vt = valp(t); else vt = valp(gnorm(t)) / 2; /* v(t) = v(Nt) / (e*f) */ vq = valp(q); /* > 0 */ Q = vt / vq; R = vt % vq; if (R < 0) Q--; if (Q) t = gdiv(t, gpowgs(q,Q)); if (padicprec_relative(t) > prec) t = gprec(t, prec); return gerepileupto(av, t); } static GEN ellQp_t2P(GEN E, GEN t, long prec) { pari_sp av = avma; GEN AB, A, R, x0,x1, y0,y1, u, u2, r0, s0, ar; long v; if (gequal1(t)) return ellinf(); AB = ellQp_AGM(E,prec); A = gel(AB,1); R = gel(AB,3); v = itos(gel(AB,4)); u = ellQp_u(E,prec); u2= ellQp_u2(E,prec); x1 = gdiv(t, gmul(u2, gsqr(gsubsg(1,t)))); y1 = gdiv(gmul(x1,gaddsg(1,t)), gmul(gmul2n(u,1),gsubsg(1,t))); Qp_ascending_Landen(AB, &x1,&y1); r0 = get_r0(E, prec); ar = gmul(gel(A,1), gel(R,1)); setvalp(ar, valp(ar)+v); x0 = gsub(gadd(x1, gdiv(ar, x1)), gmul2n(r0,-1)); s0 = gmul2n(ec_h_evalx(E, x0), -1); y0 = gsub(gmul(y1, gsubsg(1, gdiv(ar,gsqr(x1)))), s0); return gerepilecopy(av, mkvec2(x0,y0)); } static GEN zell_i(GEN e, GEN z, long prec) { GEN t; long s; (void)ellR_omega(e, prec); /* type checking */ if (ell_is_inf(z)) return gen_0; s = ellR_get_sign(e); if (s && typ(gel(z,1))!=t_COMPLEX && typ(gel(z,2))!=t_COMPLEX) t = (s < 0)? zellrealneg(e,z,prec): zellrealpos(e,z,prec); else t = zellcx(e,z,prec); return t; } static GEN ellnfembed(GEN E, long prec); static GEN ellpointnfembed(GEN E, GEN P, long prec); static void ellnfembed_free(GEN L); GEN zell(GEN E, GEN P, long prec) { pari_sp av = avma; checkell(E); if (!checkellpt_i(P)) pari_err_TYPE("ellpointtoz", P); switch(ell_get_type(E)) { case t_ELL_Qp: prec = minss(ellQp_get_prec(E), padicprec_relative(P)); return ellQp_P2t(E, P, prec); case t_ELL_NF: { GEN Ee = ellnfembed(E, prec), Pe = ellpointnfembed(E, P, prec); long i, l = lg(Pe); for (i = 1; i < l; i++) gel(Pe,i) = zell_i(gel(Ee,i), gel(Pe,i), prec); ellnfembed_free(Ee); return gerepilecopy(av, Pe); } case t_ELL_Q: break; case t_ELL_Rg: break; default: pari_err_TYPE("ellpointtoz", E); } return gerepileupto(av, zell_i(E, P, prec)); } enum period_type { t_PER_W, t_PER_WETA, t_PER_ELL }; /* normalization / argument reduction for ellptic functions */ typedef struct { enum period_type type; GEN in; /* original input */ GEN w1,w2,tau; /* original basis for L = = w2 <1,tau> */ GEN W1,W2,Tau; /* new basis for L = = W2 <1,tau> */ GEN a,b,c,d; /* t_INT; tau in F = h/Sl2, tau = g.t, g=[a,b;c,d] in SL(2,Z) */ GEN z,Z; /* z/w2 defined mod <1,tau>, Z = z/w2 + x*tau+y reduced mod <1,tau>*/ GEN x,y; /* t_INT */ int swap; /* 1 if we swapped w1 and w2 */ int some_q_is_real; /* exp(2iPi g.tau) for some g \in SL(2,Z) */ int some_z_is_real; /* z + xw1 + yw2 is real for some x,y \in Z */ int some_z_is_pure_imag; /* z + xw1 + yw2 in i*R */ int q_is_real; /* exp(2iPi tau) \in R */ int abs_u_is_1; /* |exp(2iPi Z)| = 1 */ long prec; /* precision(Z) */ long prec0; /* required precision for result */ } ellred_t; /* compute g in SL_2(Z), g.t is in the usual fundamental domain. Internal function no check, no garbage. */ static void set_gamma(GEN *pt, GEN *pa, GEN *pb, GEN *pc, GEN *pd) { GEN a, b, c, d, t, t0 = *pt, run = dbltor(1. - 1e-8); long e = gexpo(gel(t0,2)); if (e < 0) t0 = gprec_wensure(t0, precision(t0)+nbits2extraprec(-e)); t = t0; a = d = gen_1; b = c = gen_0; for(;;) { GEN m, n = ground(gel(t,1)); 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(conj_i(t), m)); /* apply S */ togglesign_safe(&c); swap(a,c); togglesign_safe(&d); swap(b,d); } if (e < 0 && (signe(b) || signe(c))) *pt = t0; *pa = a; *pb = b; *pc = c; *pd = d; } /* Im z > 0. Return U.z in PSl2(Z)'s standard fundamental domain. * Set *pU to U. */ GEN cxredsl2_i(GEN z, GEN *pU, GEN *czd) { GEN a,b,c,d; set_gamma(&z, &a, &b, &c, &d); *pU = mkmat2(mkcol2(a,c), mkcol2(b,d)); *czd = gadd(gmul(c,z), d); return gdiv(gadd(gmul(a,z), b), *czd); } GEN cxredsl2(GEN t, GEN *pU) { pari_sp av = avma; GEN czd; t = cxredsl2_i(t, pU, &czd); return gc_all(av, 2, &t, pU); } /* swap w1, w2 so that Im(t := w1/w2) > 0. Set tau = representative of t in * the standard fundamental domain, and g in Sl_2, such that tau = g.t */ static void red_modSL2(ellred_t *T, long prec) { long s, p; T->tau = gdiv(T->w1,T->w2); if (isintzero(real_i(T->tau))) T->some_q_is_real = 1; s = gsigne(imag_i(T->tau)); if (!s) pari_err_DOMAIN("elliptic function", "det(w1,w2)", "=", gen_0, mkvec2(T->w1,T->w2)); T->swap = (s < 0); if (T->swap) { swap(T->w1, T->w2); T->tau = ginv(T->tau); } p = precision(T->tau); T->prec0 = p? p: prec; set_gamma(&T->tau, &T->a, &T->b, &T->c, &T->d); /* update lattice */ p = precision(T->tau); if (p) { T->w1 = gprec_wensure(T->w1, p); T->w2 = gprec_wensure(T->w2, p); } T->W1 = gadd(gmul(T->a,T->w1), gmul(T->b,T->w2)); T->W2 = gadd(gmul(T->c,T->w1), gmul(T->d,T->w2)); T->Tau = gdiv(T->W1, T->W2); if (isintzero(real_i(T->Tau))) T->some_q_is_real = T->q_is_real = 1; p = precision(T->Tau); T->prec = p? p: prec; } /* is z real or pure imaginary ? */ static void check_complex(GEN z, int *real, int *imag) { if (typ(z) != t_COMPLEX) { *real = 1; *imag = 0; } else if (isintzero(gel(z,1))) { *real = 0; *imag = 1; } else *real = *imag = 0; } static void reduce_z(GEN z, ellred_t *T) { GEN x, Z; long p, e; switch(typ(z)) { case t_INT: case t_REAL: case t_FRAC: case t_COMPLEX: break; case t_QUAD: z = isexactzero(gel(z,2))? gel(z,1): quadtofp(z, T->prec); break; default: pari_err_TYPE("reduction mod 2-dim lattice (reduce_z)", z); } Z = gdiv(z, T->W2); T->z = z; x = gdiv(imag_i(Z), imag_i(T->Tau)); T->x = grndtoi(x, &e); /* |Im(Z - x*Tau)| <= Im(Tau)/2 */ /* Avoid Im(Z) << 0; take 0 <= Im(Z - x*Tau) < Im(Tau) instead. * Leave round when Im(Z - x*Tau) ~ 0 to allow detecting Z in <1,Tau> * at the end */ if (e > -10) T->x = gfloor(x); if (signe(T->x)) Z = gsub(Z, gmul(T->x,T->Tau)); T->y = ground(real_i(Z));/* |Re(Z - y)| <= 1/2 */ if (signe(T->y)) Z = gsub(Z, T->y); T->abs_u_is_1 = (typ(Z) != t_COMPLEX); /* Z = - y - x tau + z/W2, x,y integers */ check_complex(z, &(T->some_z_is_real), &(T->some_z_is_pure_imag)); if (!T->some_z_is_real && !T->some_z_is_pure_imag) { int W2real, W2imag; check_complex(T->W2,&W2real,&W2imag); if (W2real) check_complex(Z, &(T->some_z_is_real), &(T->some_z_is_pure_imag)); else if (W2imag) check_complex(Z, &(T->some_z_is_pure_imag), &(T->some_z_is_real)); } p = precision(Z); if (gequal0(Z) || (p && gexpo(Z) < 5 - p)) Z = NULL; /*z in L*/ if (p && p < T->prec) T->prec = p; T->Z = Z; } /* return x.eta1 + y.eta2 */ static GEN eta_correction(ellred_t *T, GEN eta) { GEN y1 = NULL, y2 = NULL; if (signe(T->x)) y1 = gmul(T->x, gel(eta,1)); if (signe(T->y)) y2 = gmul(T->y, gel(eta,2)); if (!y1) return y2? y2: gen_0; return y2? gadd(y1, y2): y1; } /* e is either * - [w1,w2] * - [[w1,w2],[eta1,eta2]] * - an ellinit structure */ static void compute_periods(ellred_t *T, GEN z, long prec) { GEN w, e; T->q_is_real = 0; T->some_q_is_real = 0; switch(T->type) { case t_PER_ELL: { long pr, p = prec; if (z && (pr = precision(z))) p = pr; e = T->in; w = ellR_omega(e, p); T->some_q_is_real = T->q_is_real = 1; break; } case t_PER_W: w = T->in; break; default: /*t_PER_WETA*/ w = gel(T->in,1); break; } T->w1 = gel(w,1); T->w2 = gel(w,2); red_modSL2(T, prec); if (z) reduce_z(z, T); } static int check_periods(GEN e, ellred_t *T) { GEN w1; if (typ(e) != t_VEC) return 0; T->in = e; switch(lg(e)) { case 17: T->type = t_PER_ELL; break; case 3: w1 = gel(e,1); if (typ(w1) != t_VEC) T->type = t_PER_W; else { if (lg(w1) != 3) return 0; T->type = t_PER_WETA; } break; default: return 0; } return 1; } static int get_periods(GEN e, GEN z, ellred_t *T, long prec) { if (!check_periods(e, T)) return 0; compute_periods(T, z, prec); return 1; } /* 2iPi/x, more efficient when x pure imaginary */ static GEN PiI2div(GEN x, long prec) { return gdiv(Pi2n(1, prec), mulcxmI(x)); } /* (2iPi/W2)^k E_k(W1/W2) */ static GEN _elleisnum(ellred_t *T, long k) { GEN z = gmul(cxEk(T->Tau, k, T->prec), gpowgs(PiI2div(T->W2, T->prec), k)); return cxtoreal(z); } /* Return (2iPi)^k E_k(L) = (2iPi/w2)^k E_k(tau), with L = , k > 0 even * E_k(tau) = 1 + 2/zeta(1-k) * sum(n>=1, n^(k-1) q^n/(1-q^n)) * If flag is != 0 and k=4 or 6, compute g2 = E4/12 or g3 = -E6/216 resp. */ GEN elleisnum(GEN om, long k, long flag, long prec) { pari_sp av = avma; GEN y; ellred_t T; if (k<=0) pari_err_DOMAIN("elleisnum", "k", "<=", gen_0, stoi(k)); if (k&1) pari_err_DOMAIN("elleisnum", "k % 2", "!=", gen_0, stoi(k)); if (!get_periods(om, NULL, &T, prec)) pari_err_TYPE("elleisnum",om); y = _elleisnum(&T, k); if (k==2 && signe(T.c)) { GEN a = gmul(Pi2n(1,T.prec), mului(12, T.c)); y = gsub(y, mulcxI(gdiv(a, gmul(T.w2, T.W2)))); } else if (k==4 && flag) y = gdivgu(y, 12); else if (k==6 && flag) y = gdivgs(y,-216); return gerepilecopy(av, gprec_wtrunc(y, T.prec0)); } /* return quasi-periods attached to [T->W1,T->W2] */ static GEN _elleta(ellred_t *T) { GEN y1, y2, e2 = gdivgs(_elleisnum(T,2), -12); y2 = gmul(T->W2, e2); y1 = gsub(gmul(T->W1,e2), PiI2div(T->W2, T->prec)); retmkvec2(y1, y2); } /* compute eta1, eta2 */ GEN elleta(GEN om, long prec) { pari_sp av = avma; GEN y1, y2, E2, pi; ellred_t T; if (!check_periods(om, &T)) { pari_err_TYPE("elleta",om); return NULL;/*LCOV_EXCL_LINE*/ } if (T.type == t_PER_ELL) return ellR_eta(om, prec); compute_periods(&T, NULL, prec); prec = T.prec; pi = mppi(prec); E2 = cxEk(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)); switch(typ(T.w1)) { case t_INT: case t_FRAC: case t_REAL: y1 = real_i(y1); } return gerepilecopy(av, mkvec2(y1,y2)); } GEN ellperiods(GEN w, long flag, long prec) { pari_sp av = avma; ellred_t T; if (!get_periods(w, NULL, &T, prec)) pari_err_TYPE("ellperiods",w); switch(flag) { case 0: return gerepilecopy(av, mkvec2(T.W1, T.W2)); case 1: return gerepilecopy(av, mkvec2(mkvec2(T.W1, T.W2), _elleta(&T))); default: pari_err_FLAG("ellperiods"); return NULL;/*LCOV_EXCL_LINE*/ } } /* 2Pi Im(z)/log(2) */ static double get_toadd(GEN z) { return (2*M_PI/M_LN2)*gtodouble(imag_i(z)); } /* computes the numerical value of wp(z | L), L = om1 Z + om2 Z * return NULL if z in L. If flall=1, compute also wp' */ static GEN ellwpnum_all(GEN e, GEN z, long flall, long prec) { long toadd; pari_sp av = avma, av1; GEN q, u, y, yp, u1, u2, qn; ellred_t T; int simple_case; if (!get_periods(e, z, &T, prec)) pari_err_TYPE("ellwp",e); if (!T.Z) return NULL; prec = T.prec; /* Now L,Z normalized to <1,tau>. Z in fund. domain of <1, tau> */ q = expIPiC(gmul2n(T.Tau,1), prec); u = expIPiC(gmul2n(T.Z,1), prec); u1 = gsubsg(1,u); u2 = gsqr(u1); /* (1-u)^2 = -4u sin^2(Pi Z) */ if (gequal0(gnorm(u2))) return NULL; /* possible if loss of accuracy */ y = gdiv(u,u2); /* -1/4(sin^2(Pi Z)) */ if (T.abs_u_is_1) y = real_i(y); simple_case = T.abs_u_is_1 && T.q_is_real; y = gadd(mkfrac(gen_1, utoipos(12)), y); yp = flall? gen_0: NULL; toadd = (long)ceil(get_toadd(T.Z)); av1 = avma; qn = q; for(;;) { /* y += u q^n [ 1/(1-q^n u)^2 + 1/(q^n-u)^2 ] - 2q^n /(1-q^n)^2 */ /* analogous formula for yp */ GEN yadd, ypadd = NULL; GEN qnu = gmul(qn,u); /* q^n u */ GEN a = gsubsg(1,qnu);/* 1 - q^n u */ GEN a2 = gsqr(a); /* (1 - q^n u)^2 */ if (yp) ypadd = gdiv(gaddsg(1,qnu),gmul(a,a2)); if (simple_case) /* conj(u) = 1/u: formula simplifies */ yadd = gmul2n(real_i(gdiv(u,a2)), 1); else { GEN b = gsub(qn,u);/* q^n - u */ GEN b2 = gsqr(b); /* (q^n - u)^2 */ yadd = gmul(u, gadd(ginv(a2),ginv(b2))); if (yp) ypadd = gadd(ypadd, gdiv(gadd(qn,u),gmul(b,b2))); } yadd = gsub(yadd, gmul2n(ginv(gsqr(gsubsg(1,qn))), 1)); y = gadd(y, gmul(qn,yadd)); if (yp) yp = gadd(yp, gmul(qn,ypadd)); qn = gmul(q,qn); if (gexpo(qn) <= - prec - 5 - toadd) break; if (gc_needed(av1,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"ellwp"); gerepileall(av1, flall? 3: 2, &y, &qn, &yp); } } if (yp) { if (simple_case) yp = gsub(yp, conj_i(gmul(yp,gsqr(u)))); yp = gadd(yp, gdiv(gaddsg(1,u), gmul(u1,u2))); } u1 = PiI2div(T.W2, prec); u2 = gsqr(u1); y = gmul(u2,y); /* y *= (2i pi / w2)^2 */ if (T.some_q_is_real && (T.some_z_is_real || T.some_z_is_pure_imag)) y = real_i(y); if (yp) { yp = gmul(u, gmul(gmul(u1,u2),yp));/* yp *= u (2i pi / w2)^3 */ if (T.some_q_is_real) { if (T.some_z_is_real) yp = real_i(yp); else if (T.some_z_is_pure_imag) yp = mkcomplex(gen_0, imag_i(yp)); } y = mkvec2(y, yp); } return gerepilecopy(av, gprec_wtrunc(y, T.prec0)); } static GEN ellwpseries_aux(GEN c4, GEN c6, long v, long PRECDL) { long i, k, l; pari_sp av; GEN _1, t, res = cgetg(PRECDL+2,t_SER), *P = (GEN*)(res + 2); res[1] = evalsigne(1) | _evalvalser(-2) | evalvarn(v); if (!PRECDL) { setsigne(res,0); return res; } for (i=1; i 1) pari_err_FLAG("ellsigma"); if (!z) z = pol_x(0); y = toser_i(z); if (y) { long vy = varn(y), v = valser(y); GEN P, Q, c4,c6; if (!get_c4c6(w,&c4,&c6,prec0)) pari_err_TYPE("ellsigma",w); if (v <= 0) pari_err_IMPL("ellsigma(t_SER) away from 0"); if (flag) pari_err_TYPE("log(ellsigma)",y); if (gequal0(y)) { set_avma(av); return zeroser(vy, -v); } P = ellwpseries_aux(c4,c6, vy, lg(y)-2); P = integser(gneg(P)); /* \zeta' = - \wp*/ /* (log \sigma)' = \zeta; remove log-singularity first */ P = integser(serchop0(P)); P = gexp(P, prec0); setvalser(P, valser(P)+1); Q = gsubst(P, varn(P), y); return gerepileupto(av, Q); } if (!get_periods(w, z, &T, prec0)) pari_err_TYPE("ellsigma",w); if (!T.Z) { if (!flag) return gen_0; pari_err_DOMAIN("log(ellsigma)", "argument","=",gen_0,z); } prec = T.prec; pi2 = Pi2n(1,prec); pi = mppi(prec); urninv = uinv = NULL; if (typ(T.Z) == t_FRAC && equaliu(gel(T.Z,2), 2) && equalim1(gel(T.Z,1))) { toadd = 0; urn = mkcomplex(gen_0, gen_m1); /* Z = -1/2 => urn = -I */ u = gen_1; } else { toadd = (long)ceil(fabs( get_toadd(T.Z) )); urn = expIPiC(T.Z, prec); /* exp(i Pi Z) */ u = gneg_i(gsqr(urn)); if (!T.abs_u_is_1) { urninv = ginv(urn); uinv = gneg_i(gsqr(urninv)); } } q8 = expIPiC(gmul2n(T.Tau, -2), prec); q = gpowgs(q8,8); av1 = avma; y = gen_0; qn = q; qn2 = gen_1; for(n=0;;n++) { /* qn = q^(n+1), qn2 = q^(n(n+1)/2), urn = u^((n+1)/2) * if |u| = 1, will multiply by 2*I at the end ! */ y = gadd(y, gmul(qn2, uinv? gsub(urn,urninv): imag_i(urn))); qn2 = gmul(qn,qn2); if (gexpo(qn2) + n*toadd <= - prec - 5) break; qn = gmul(q,qn); urn = gmul(urn,u); if (uinv) urninv = gmul(urninv,uinv); if (gc_needed(av1,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"ellsigma"); gerepileall(av1,urninv? 5: 4, &y,&qn,&qn2,&urn,&urninv); } } y = gmul(y, gdiv(q8, gmul(pi2, gpowgs(trueeta(T.Tau,prec),3)))); y = gmul(y, T.abs_u_is_1? gmul2n(T.W2,1): mulcxmI(T.W2)); et = _elleta(&T); z0 = gmul(T.Z,T.W2); y1 = gadd(z0, gmul2n(gadd(gmul(T.x,T.W1), gmul(T.y,T.W2)),-1)); etnew = gmul(eta_correction(&T, et), y1); y1 = gadd(etnew, gmul2n(gmul(gmul(T.Z,z0),gel(et,2)),-1)); if (flag) { y = gadd(y1, glog(y,prec)); if (mpodd(T.x) || mpodd(T.y)) y = gadd(y, mulcxI(pi)); /* log(real number): im(y) = 0 or Pi */ if (T.some_q_is_real && isintzero(imag_i(z)) && gexpo(imag_i(y)) < 1) y = real_i(y); } else { y = gmul(y, gexp(y1,prec)); if (mpodd(T.x) || mpodd(T.y)) y = gneg_i(y); if (T.some_q_is_real) { int re, cx; check_complex(z,&re,&cx); if (re) y = real_i(y); else if (cx && typ(y) == t_COMPLEX) gel(y,1) = gen_0; } } return gerepilecopy(av, gprec_wtrunc(y, T.prec0)); } GEN pointell(GEN e, GEN z, long prec) { pari_sp av = avma; GEN v; checkell(e); if (ell_get_type(e) == t_ELL_Qp) { prec = minss(ellQp_get_prec(e), padicprec_relative(z)); return ellQp_t2P(e, z, prec); } v = ellwpnum_all(e,z,1,prec); if (!v) { set_avma(av); return ellinf(); } gel(v,1) = gsub(gel(v,1), gdivgu(ell_get_b2(e),12)); gel(v,2) = gmul2n(gsub(gel(v,2), ec_h_evalx(e,gel(v,1))),-1); return gerepilecopy(av, v); } /********************************************************************/ /** **/ /** Tate's algorithm e (cf Anvers IV) **/ /** Kodaira types, global minimal model **/ /** **/ /********************************************************************/ /* structure to hold incremental computation of standard minimal model/Q */ typedef struct { long a1; /*{0,1}*/ long a2; /*{-1,0,1}*/ long a3; /*{0,1}*/ long b2; /* centermod(-c6, 12), in [-5,6] */ GEN u, u2, u3, u4, u6; GEN a4, a6, b4, b6, b8, c4, c6, D; } ellmin_t; /* u from [u,r,s,t] */ static void min_set_u(ellmin_t *M, GEN u) { M->u = u; if (is_pm1(u)) M->u2 = M->u3 = M->u4 = M->u6 = gen_1; else { M->u2 = sqri(u); M->u3 = mulii(M->u2, u); M->u4 = sqri(M->u2); M->u6 = sqri(M->u3); } } /* E = original curve */ static void min_set_c(ellmin_t *M, GEN E) { GEN c4 = ell_get_c4(E), c6 = ell_get_c6(E); if (!is_pm1(M->u4)) { c4 = diviiexact(c4, M->u4); c6 = diviiexact(c6, M->u6); } M->c4 = c4; M->c6 = c6; } static void min_set_D(ellmin_t *M, GEN E) { GEN D = ell_get_disc(E); if (!is_pm1(M->u6)) D = diviiexact(D, sqri(M->u6)); M->D = D; } static void min_set_b(ellmin_t *M) { long b22, b2; M->b2 = b2 = Fl_center(12 - umodiu(M->c6,12), 12, 6); b22 = b2 * b2; /* in [0,36] */ M->b4 = diviuexact(subui(b22, M->c4), 24); M->b6 = diviuexact(subii(mulsi(b2, subiu(mului(36,M->b4),b22)), M->c6), 216); } static void min_set_a(ellmin_t *M) { long a1, a2, a3, a13, b2 = M->b2; GEN b4 = M->b4, b6 = M->b6; if (odd(b2)) { a1 = 1; a2 = (b2 - 1) >> 2; } else { a1 = 0; a2 = b2 >> 2; } M->a1 = a1; M->a2 = a2; M->a3 = a3 = Mod2(b6)? 1: 0; a13 = a1 & a3; /* a1 * a3 */ M->a4 = shifti(subiu(b4, a13), -1); M->a6 = shifti(subiu(b6, a3), -2); } static void min_set_all(ellmin_t *M, GEN E, GEN u) { min_set_u(M, u); min_set_c(M, E); min_set_D(M, E); min_set_b(M); min_set_a(M); } static GEN min_to_ell(ellmin_t *M, GEN E) { GEN b8, y = obj_init(15, 8); long a11, a13; gel(y,1) = M->a1? gen_1: gen_0; gel(y,2) = stoi(M->a2); gel(y,3) = M->a3? gen_1: gen_0; gel(y,4) = M->a4; gel(y,5) = M->a6; gel(y,6) = stoi(M->b2); gel(y,7) = M->b4; gel(y,8) = M->b6; a11 = M->a1; a13 = M->a1 & M->a3; b8 = subii(addii(mului(a11,M->a6), mulis(M->b6, M->a2)), mulii(M->a4, addiu(M->a4,a13))); gel(y,9) = b8; /* a1^2 a6 + 4a6 a2 + a2 a3^2 - a4(a4 + a1 a3) */ gel(y,10)= M->c4; gel(y,11)= M->c6; gel(y,12)= M->D; gel(y,13)= gel(E,13); gel(y,14)= gel(E,14); gel(y,15)= gel(E,15); return y; } static GEN min_get_v(ellmin_t *M, GEN E) { GEN r, s, t; r = diviuexact(subii(mulis(M->u2,M->b2), ell_get_b2(E)), 12); s = shifti(subii(M->a1? M->u: gen_0, ell_get_a1(E)), -1); t = shifti(subii(M->a3? M->u3: gen_0, Zec_h_evalx(E,r)), -1); return mkvec4(M->u,r,s,t); } /* return v_p(u), where [u,r,s,t] is the variable change to minimal model */ static long get_vp_u_small(GEN E, ulong p, long *pv6, long *pvD) { GEN c6 = ell_get_c6(E); long d, v6, vD = Z_lval(ell_get_disc(E), p); if (!signe(c6)) { d = vD / 12; if (d) { if (p == 2) { GEN c4 = ell_get_c4(E); long a = Mod16( shifti(c4, -4*d) ); if (a) d--; } if (d) vD -= 12*d; /* non minimal model */ } v6 = 12; /* +oo */ } else { v6 = Z_lval(c6,p); d = minss(2*v6, vD) / 12; if (d) { if (p == 2) { GEN c4 = ell_get_c4(E); long a = Mod16( shifti(c4, -4*d) ); long b = Mod32( shifti(c6, -6*d) ); if ((b & 3) != 3 && (a || (b && b!=8))) d--; } else if (p == 3) { if (v6 == 6*d+2) d--; } if (d) { v6 -= 6*d; vD -= 12*d; } /* non minimal model */ } } *pv6 = v6; *pvD = vD; return d; } static long get_vp_u(GEN E, GEN p, long *pv6, long *pvD) { GEN c6; long d, v6, vD; if (lgefint(p) == 3) return get_vp_u_small(E, p[2], pv6, pvD); c6 = ell_get_c6(E); vD = Z_pval(ell_get_disc(E), p); if (!signe(c6)) { d = vD / 12; if (d) vD -= 12*d; /* non minimal model */ v6 = 12; /* +oo */ } else { v6 = Z_pval(c6,p); d = minss(2*v6, vD) / 12; if (d) { v6 -= 6*d; vD -= 12*d; } /* non minimal model */ } *pv6 = v6; *pvD = vD; return d; } /* Given an integral elliptic curve in ellinit form, and a prime p, returns the type of the fiber at p of the Neron model, as well as the change of variables in the form [f, kod, v, c]. * The integer f is the conductor's exponent. * The integer kod is the Kodaira type using the following notation: II , III , IV --> 2, 3, 4 I0 --> 1 Inu --> 4+nu for nu > 0 A '*' negates the code (e.g I* --> -2) * v is a quadruple [u, r, s, t] yielding a minimal model * c is the Tamagawa number. Uses Tate's algorithm (Anvers IV). Given the remarks at the bottom of page 46, the "long" algorithm is used for p = 2,3 only. */ static GEN localred_result(long f, long kod, long c, GEN v) { GEN z = cgetg(5, t_VEC); gel(z,1) = stoi(f); gel(z,2) = stoi(kod); gel(z,3) = gcopy(v); gel(z,4) = stoi(c); return z; } static GEN localredbug(GEN p, const char *s) { if (BPSW_psp(p)) pari_err_BUG(s); pari_err_PRIME("localred",p); return NULL; /* LCOV_EXCL_LINE */ } /* v_p( denom(j(E)) ) >= 0 */ static long j_pval(GEN E, GEN p) { return Z_pval(Q_denom(ell_get_j(E)), p); } /* p > 3, e integral */ static GEN localred_p(GEN e, GEN p) { long k, f, kod, c, nuj, nuD, nu6; GEN p2, v, tri, c4, c6, D = ell_get_disc(e); c4 = ell_get_c4(e); c6 = ell_get_c6(e); nuj = j_pval(e, p); nuD = Z_pval(D, p); k = get_vp_u(e, p, &nu6, &nuD); if (!k) v = init_ch(); else { /* model not minimal */ ellmin_t M; min_set_all(&M, e, powiu(p,k)); v = min_get_v(&M, e); c4 = M.c4; c6 = M.c6; D = M.D; } if (nuj > 0) switch(nuD - nuj) { case 0: f = 1; kod = 4+nuj; /* Inu */ switch(kronecker(negi(c6),p)) { case 1: c = nuD; break; case -1: c = odd(nuD)? 1: 2; break; default: return localredbug(p,"localred (p | c6)"); } break; case 6: { GEN d = Fp_red(diviiexact(D, powiu(p, 6+nuj)), p); if (nuj & 1) d = Fp_mul(d, diviiexact(c6, powiu(p,3)), p); f = 2; kod = -4-nuj; c = 3 + kronecker(d, p); /* Inu* */ break; } default: return localredbug(p,"localred (nu_D - nu_j != 0,6)"); } else switch(nuD) { case 0: f = 0; kod = 1; c = 1; break; /* I0, regular */ case 2: f = 2; kod = 2; c = 1; break; /* II */ case 3: f = 2; kod = 3; c = 2; break; /* III */ case 4: f = 2; kod = 4; /* IV */ c = 2 + krosi(-6,p) * kronecker(diviiexact(c6,sqri(p)), p); break; case 6: f = 2; kod = -1; /* I0* */ p2 = sqri(p); /* x^3 - 3c4/p^2 x - 2c6/p^3 */ tri = mkpoln(4, gen_1, gen_0, negi(mului(3, diviiexact(c4, p2))), negi(shifti(diviiexact(c6, mulii(p2,p)), 1))); c = 1 + FpX_nbroots(tri, p); break; case 8: f = 2; kod = -4; /* IV* */ c = 2 + krosi(-6,p) * kronecker(diviiexact(c6, sqri(sqri(p))), p); break; case 9: f = 2; kod = -3; c = 2; break; /* III* */ case 10: f = 2; kod = -2; c = 1; break; /* II* */ default: return localredbug(p,"localred"); } return localred_result(f, kod, c, v); } /* return a_{ k,l } in Tate's notation, pl = p^l */ static ulong aux(GEN ak, ulong q, ulong pl) { return umodiu(ak, q) / pl; } static ulong aux2(GEN ak, ulong p, GEN pl) { pari_sp av = avma; return gc_ulong(av, umodiu(diviiexact(ak, pl), p)); } /* 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 (odd(c + a * b)) return 3; *mult = b; return odd(a + b)? 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 odd(b)? 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, nu6, nuD, r, s, t; long k, theroot, p2, p3, p4, p5, a21, a42, a63, a32, a64; GEN v; k = get_vp_u_small(e, p, &nu6, &nuD); if (!k) v = init_ch(); else { ellmin_t M; min_set_all(&M, e, powuu(p, k)); v = min_get_v(&M, e); e = min_to_ell(&M, e); } /* model is minimal */ nuD = Z_lval(ell_get_disc(e), (ulong)p); if (!nuD) return localred_result(0, 1, 1, v); /* I0 */ if (p == 2) { p2 = 4; p3 = 8; p4 = 16; p5 = 32; } else { p2 = 9; p3 = 27; p4 = 81; p5 =243; } 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 = odd(nuD)? 1: 2; return localred_result(1, 4 + nuD, c, v); /* Inu */ } if (p == 2) { r = umodiu(ell_get_a4(e), 2); s = umodiu(ell_get_a2(e), 2); t = umodiu(ell_get_a6(e), 2); if (r) { t = (s + t) & 1; s = (s + 1) & 1; } } else /* p == 3 */ { r = - umodiu(ell_get_b6(e), 3); s = umodiu(ell_get_a1(e), 3); t = umodiu(ell_get_a3(e), 3); if (s) { t = (t + r*s) % 3; if (t < 0) t += 3; } } /* p | (a1, a2, a3, a4, a6) */ if (r || s || t) e = coordch_rst(e, stoi(r), stoi(s), stoi(t)); if (umodiu(ell_get_a6(e), p2)) return localred_result(nuD, 2, 1, v); /* II */ if (umodiu(ell_get_b8(e), p3)) return localred_result(nuD - 1, 3, 2, v); /* III */ if (umodiu(ell_get_b6(e), p3)) { if (umodiu(ell_get_b6(e), (p==2)? 32: 27) == (ulong)p2) c = 3; else c = 1; return localred_result(nuD - 2, 4, c, v); /* IV */ } if (umodiu(ell_get_a6(e), p3)) e = coordch_t(e, p == 2? gen_2: modis(ell_get_a3(e), 9)); /* p | a1, a2; p^2 | a3, a4; p^3 | a6 */ a21 = aux(ell_get_a2(e), p2, p); a42 = aux(ell_get_a4(e), p3, p2); a63 = aux(ell_get_a6(e), p4, p3); switch (numroots3(a21, a42, a63, p, &theroot)) { case 3: c = a63 ? 1: 2; if (p == 2) c += ((a21 + a42 + a63) & 1); else { if (((1 + a21 + a42 + a63) % 3) == 0) c++; if (((1 - a21 + a42 - a63) % 3) == 0) c++; } return localred_result(nuD - 4, -1, c, v); /* I0* */ case 2: { /* compute nu */ GEN pk, pk1, p2k; long al, be, ga; if (theroot) e = coordch_r(e, stoi(theroot * p)); /* p | a1; p^2 | a2, a3; p^3 | a4; p^4 | a6 */ nu = 1; pk = utoipos(p2); p2k = utoipos(p4); for(;;) { be = aux2(ell_get_a3(e), p, pk); ga = -aux2(ell_get_a6(e), p, p2k); al = 1; if (numroots2(al, be, ga, p, &theroot) == 2) break; if (theroot) e = coordch_t(e, mulsi(theroot,pk)); pk1 = pk; pk = mului(p, pk); p2k = mului(p, p2k); nu++; al = a21; be = aux2(ell_get_a4(e), p, pk); ga = aux2(ell_get_a6(e), p, p2k); if (numroots2(al, be, ga, p, &theroot) == 2) break; if (theroot) e = coordch_r(e, mulsi(theroot, pk1)); p2k = mului(p, p2k); nu++; } if (p == 2) c = odd(ga)? 2: 4; else c = 3 + kross(be * be - al * ga, 3); return localred_result(nuD - 4 - nu, -4 - nu, c, v); /* Inu* */ } case 1: if (theroot) e = coordch_r(e, stoi(theroot*p)); /* p | a1; p^2 | a2, a3; p^3 | a4; p^4 | a6 */ a32 = aux(ell_get_a3(e), p3, p2); a64 = aux(ell_get_a6(e), p5, p4); if (numroots2(1, a32, -a64, p, &theroot) == 2) { if (p == 2) c = 3 - 2 * a64; else c = 2 + kross(a32 * a32 + a64, 3); return localred_result(nuD - 6, -4, c, v); /* IV* */ } if (theroot) e = coordch_t(e, stoi(theroot*p2)); /* p | a1; p^2 | a2; p^3 | a3, a4; p^5 | a6 */ if (umodiu(ell_get_a4(e), p4)) return localred_result(nuD - 7, -3, 2, v); /* III* */ /* p^6 \nmid a6, otherwise wouldn't be minimal */ return localred_result(nuD - 8, -2, 1, v); /* II* */ } return NULL; /* LCOV_EXCL_LINE */ } /* e is integral */ static GEN localred(GEN e, GEN p) { if (abscmpiu(p, 3) > 0) /* p != 2,3 */ return localred_p(e,p); else { long l = itos(p); if (l < 2) pari_err_PRIME("localred",p); return localred_23(e, l); } } /* Given J an ideal in HNF coprime to 2 and z algebraic integer, * return b algebraic integer such that z + 2b in J */ static GEN approx_mod2(GEN J, GEN z) { GEN b = z; long i; if (typ(b) == t_INT) { if (mpodd(b)) b = addii(b, gcoeff(J,1,1)); return shifti(negi(b),-1); } for (i = lg(J)-1; i >= 1; i--) { if (mpodd(gel(b,i))) b = ZC_add(b, gel(J,i)); } return gshift(ZC_neg(b), -1); } /* Given J an ideal in HNF coprime to 3 and z algebraic integer, * return b algebraic integer such that z + 3b in J */ static GEN approx_mod3(GEN J, GEN z) { GEN b = z; long i; if (typ(b) == t_INT) { long s = smodis(b,3); if (s) { GEN Jz = gcoeff(J,1,1); if (smodis(Jz, 3) == s) b = subii(b, Jz); else b = addii(b, Jz); } return diviiexact(b, stoi(-3)); } for (i = lg(J)-1; i >= 1; i--) { long s = smodis(gel(b,i), 3); if (!s) continue; if (smodis(gcoeff(J,i,i), 3) == s) b = ZC_sub(b, gel(J,i)); else b = ZC_add(b, gel(J,i)); } return ZC_Z_divexact(b, stoi(-3)); } /* return a such that v_P(a) = -1, integral elsewhere */ static GEN get_piinv(GEN P) { GEN z = pr_get_tau(P); if (typ(z) == t_MAT) z = gel(z,1); return gdiv(z, pr_get_p(P)); } /* pi = local uniformizer, pv = 1/pi */ static void get_uniformizers(GEN nf, GEN P, GEN *pi, GEN *pv) { if (pr_is_inert(P)) { *pi = pr_get_p(P); *pv = mkfrac(gen_1, *pi); } else { *pv = get_piinv(P); *pi = nfinv(nf, *pv); } } /* x^2+E.a1*x-E.a2 */ static GEN pola1a2(GEN e, GEN nf, GEN modP) { GEN a1 = nf_to_Fq(nf, ell_get_a1(e), modP); GEN a2 = nf_to_Fq(nf, ell_get_a2(e), modP); return mkpoln(3, gen_1, a1, gneg(a2)); } /* x^2+E.a3*pv3*x-E.a6*pv6 */ static GEN pola3a6(GEN e, GEN nf, GEN modP, GEN pv3, GEN pv6) { GEN a3 = nf_to_Fq(nf, nfmul(nf, ell_get_a3(e), pv3), modP); GEN a6 = nf_to_Fq(nf, nfmul(nf, ell_get_a6(e), pv6), modP); return mkpoln(3, gen_1, a3, gneg(a6)); } /* E.a2*pv2*x^2 + E.a4*pv4*x + E.a6*pv6 */ static GEN pola2a4a6(GEN e, GEN nf, GEN modP, GEN pv2, GEN pv4, GEN pv6) { GEN a2 = nf_to_Fq(nf, nfmul(nf, ell_get_a2(e), pv2), modP); GEN a4 = nf_to_Fq(nf, nfmul(nf, ell_get_a4(e), pv4), modP); GEN a6 = nf_to_Fq(nf, nfmul(nf, ell_get_a6(e), pv6), modP); return mkpoln(3, a2, a4, a6); } static GEN pol2sqrt_23(GEN modP, GEN Q) { GEN p = modpr_get_p(modP), T = modpr_get_T(modP); GEN r = absequaliu(p,2) ? gel(Q,2): gel(Q,3); if (!gequal1(gel(Q,4))) r = Fq_div(r, gel(Q,4), T, p); if (absequaliu(p,2)) r = Fq_sqrt(r,T,p); return Fq_to_nf(r, modP); } static GEN nflocalred_section7(GEN e, GEN nf, GEN modP, GEN pi, GEN pv, long vD, GEN ch) { GEN p = modpr_get_p(modP), T = modpr_get_T(modP); GEN pi3 = nfsqr(nf,pi); GEN pv3 = nfsqr(nf,pv), pv4 = nfmul(nf,pv,pv3), pv6 = nfsqr(nf,pv3); long n = 1; while(1) { GEN Q = pola3a6(e, nf, modP, pv3, pv6); GEN gama; if (FqX_is_squarefree(Q, T, p)) { long nr = FqX_nbroots(Q,T,p); return localred_result(vD-n-4,-4-n,nr+2,ch); } gama = pol2sqrt_23(modP, Q); nf_compose_t(nf, &ch, &e, nfmul(nf, gama,pi3)); pv6 = nfmul(nf,pv,pv6); n++; Q = pola2a4a6(e, nf, modP, pv, pv4, pv6); if (FqX_is_squarefree(Q, T, p)) { long nr = FqX_nbroots(Q,T,p); return localred_result(vD-n-4,-4-n,nr+2,ch); } gama = pol2sqrt_23(modP, Q); nf_compose_r(nf, &ch, &e, nfmul(nf, gama, pi3)); pi3 = nfmul(nf,pi, pi3); pv3 = pv4; pv4 = nfmul(nf,pv,pv4); pv6 = nfmul(nf,pv,pv6); n++; } } /* Tate algorithm, following J.H. Silverman GTM 151, chapt. IV, algo 9.4 */ /* Dedicated to John Tate for his kind words */ static GEN nflocalred_23(GEN nf, GEN e, GEN D, GEN P, long *ap) { GEN T, p, modP; long vD; GEN ch, pv, pv2, pv4, pi, pol; modP = nf_to_Fq_init(nf,&P,&T,&p); get_uniformizers(nf,P, &pi, &pv); ch = init_ch(); vD = nfval(nf,D,P); *ap = 0; while(1) { if (vD==0) return localred_result(0,1,1,ch); else { GEN a1 = nf_to_Fq(nf, ell_get_a1(e), modP); GEN a2 = nf_to_Fq(nf, ell_get_a2(e), modP); GEN a3 = nf_to_Fq(nf, ell_get_a3(e), modP); GEN a4 = nf_to_Fq(nf, ell_get_a4(e), modP); GEN a6 = nf_to_Fq(nf, ell_get_a6(e), modP); GEN x0, y0; if (absequaliu(p,2)) { GEN x02, y02; if (signe(a1)) { x0 = Fq_div(a3, a1, T, p); x02 = Fq_sqr(x0,T,p); y02 = Fq_add(Fq_mul(x02,Fq_add(x0,a2,T,p),T,p),Fq_add(Fq_mul(a4,x0,T,p),a6,T,p),T,p); } else { x0 = Fq_sqrt(a4, T, p); y02 = Fq_add(Fq_mul(a4,a2,T,p),a6,T,p); } y0 = Fq_sqrt(y02,T,p); } else { GEN a12 = Fq_add(Fq_sqr(a1,T,p),a2,T,p); if (signe(a12)) x0 = Fq_div(Fq_sub(a4,Fq_mul(a3,a1,T,p),T,p),a12,T,p); else x0 = Fq_sqrtn(Fq_neg(Fq_add(Fq_sqr(a3,T,p),a6,T,p),T,p),p,T,p,NULL); y0 = Fq_add(Fq_mul(a1, x0, T, p), a3, T, p); } x0 = Fq_to_nf(x0, modP); y0 = Fq_to_nf(y0, modP); nf_compose_rt(nf, &ch, &e, x0, y0); } /* 2 */ { GEN b2 = nf_to_Fq(nf, ell_get_b2(e), modP); if (signe(b2) != 0) { GEN Q = pola1a2(e, nf, modP); long nr = FqX_nbroots(Q, T, p); if (nr==2) { *ap = 1; return localred_result(1,vD+4,vD,ch); /* Inu */ } else { *ap = -1; return localred_result(1,vD+4,odd(vD)?1:2,ch); } } } /* 3 */ { long va6 = nfval(nf,ell_get_a6(e),P); if (va6 <= 1) return localred_result(vD,2,1,ch); /* II */ } /* 4 */ { long vb8 = nfval(nf,ell_get_b8(e),P); if (vb8 <= 2) return localred_result(vD-1,3,2,ch);/* III */ } /* 5 */ pv2 = nfsqr(nf,pv); { long vb6 = nfval(nf,ell_get_b6(e),P); if (vb6<=2) { GEN Q = pola3a6(e, nf, modP, pv, pv2); long nr = FqX_nbroots(Q,T,p); return localred_result(vD-2,4,1+nr,ch);/* IV */ } } /* 6 */ { GEN pv3 = nfmul(nf,pv, pv2); GEN alpha = pol2sqrt_23(modP, pola1a2(e, nf, modP)); GEN beta = pol2sqrt_23(modP, pola3a6(e, nf, modP, pv, pv2)); GEN po2, E, F, mr; long i, lE; nf_compose_st(nf, &ch, &e, alpha, nfmul(nf, beta, pi)); po2 = pola2a4a6(e, nf, modP, pv, pv2, pv3); if (signe(po2)) /* po2 = 0 is frequent when nonminimal */ { pol = RgX_add(pol_xn(3,0), po2); F = FqX_factor(pol, T, p); E = gel(F,2); lE = lg(E); if (E[1] == 1 && (lE == 2 || E[2] == 1)) { /* T squarefree, degree pattern is (3), (12) or (111) */ long c; /* 1 + number of roots */ switch(lE) { case 2: c = 1; break; case 3: c = 2; break; default: c = 4; break; } return localred_result(vD-4,-1,c,ch);/* I0* */ } /* 7 */ i = (lE == 2 || E[1] == 2)? 1: 2; /* index of multiple root */ mr = constant_coeff(gmael(F,1,i)); /* - multiple root */ if (!gequal0(mr)) { /* not so frequent */ GEN gama = Fq_to_nf(Fq_neg(mr, T, p), modP); nf_compose_r(nf, &ch, &e, nfmul(nf, gama,pi)); } if (lE == 3) return nflocalred_section7(e, nf, modP, pi, pv, vD, ch); /* Inu* */ } } pv4 = nfsqr(nf,pv2); pol = pola3a6(e, nf, modP, pv2, pv4); /* 8 */ if (FqX_is_squarefree(pol,T,p)) { long nr = FqX_nbroots(pol, T, p); return localred_result(vD-6,-4,1+nr,ch); /* IV* */ } /* 9 */ { GEN alpha = pol2sqrt_23(modP, pol); nf_compose_t(nf, &ch, &e, nfmul(nf, alpha, nfsqr(nf,pi))); if (nfval(nf, ell_get_a4(e), P) == 3) return localred_result(vD-7,-3,2,ch); /* III* */ } /* 10 */ if (nfval(nf, ell_get_a6(e), P) == 5) return localred_result(vD-8,-2,1,ch); /* II* */ /* 11 */ nf_compose_u(nf, &ch, &e, pi, pv); vD -= 12; } } /* Local reduction, residual characteristic >= 5. E/nf, P prid * Output: f, kod, [u,r,s,t], c */ static GEN nflocalred_p(GEN e, GEN P) { GEN nf = ellnf_get_nf(e), T,p, modP = nf_to_Fq_init(nf,&P,&T,&p); long c, f, vD, nuj, kod, m; GEN ch, c4, c6, D, z, pi, piinv; c4 = ell_get_c4(e); c6 = ell_get_c6(e); D = ell_get_disc(e); vD = nfval(nf,D,P); nuj = nfval(nf,ell_get_j(e),P); nuj = nuj >= 0? 0: -nuj; /* v_P(denom(j)) */ m = (vD - nuj)/12; get_uniformizers(nf,P, &pi, &piinv); if(m <= 0) ch = init_ch(); else { /* model not minimal */ GEN r,s,t, a1,a2,a3, u,ui,ui2,ui4,ui6,ui12; u = nfpow_u(nf,pi,m); ui = nfpow_u(nf,piinv,m); ui2 = nfsqr(nf,ui); ui4 = nfsqr(nf,ui2); ui6 = nfmul(nf,ui2,ui4); ui12 = nfsqr(nf,ui6); c4 = nfmul(nf,c4,ui4); c6 = nfmul(nf,c6,ui6); D = nfmul(nf,D,ui12); vD -= 12*m; a1 = nf_to_scalar_or_basis(nf, ell_get_a1(e)); a2 = nf_to_scalar_or_basis(nf, ell_get_a2(e)); a3 = nf_to_scalar_or_basis(nf, ell_get_a3(e)); s = approx_mod2(idealpow(nf,P,stoi(m)), a1); r = gsub(a2, nfmul(nf,s,gadd(a1,s))); r = approx_mod3(idealpow(nf,P,stoi(2*m)), r); t = gadd(a3, nfmul(nf,r,a1)); t = approx_mod2(idealpow(nf,P,stoi(3*m)), t); ch = mkvec4(u,r,s,t); } kod = 1; c = 1; /* minimal at P */ if (nuj > 0) { /* v(j) < 0 */ if (vD == nuj) { /* v(c4) = v(c6) = 0, multiplicative reduction */ f = 1; kod = 4+vD; z = Fq_neg(nf_to_Fq(nf,c6,modP), T,p); if (Fq_issquare(z,T,p)) c = vD;/* split */ else c = odd(vD)?1 : 2; /* nonsplit */ } else { /* v(c4) = 2, v(c6) = 3, potentially multiplicative */ GEN Du; f = 2; kod = 2-vD; (void)nfvalrem(nf, D, P, &Du); z = nf_to_Fq(nf, Du, modP); if(odd(vD)) { GEN c6u; (void)nfvalrem(nf, c6, P, &c6u); c6u = nf_to_Fq(nf, c6u, modP); z = Fq_mul(z, c6u, T,p); } c = Fq_issquare(z,T,p)? 4: 2; } } else { /* v(j) >= 0 */ f = vD? 2: 0; switch(vD) { GEN piinv2, piinv3, piinv4, w; case 0: kod = 1; c = 1; break; case 2: kod = 2; c = 1; break; case 3: kod = 3; c = 2; break; case 4: kod = 4; z = nfmul(nf,c6,nfsqr(nf,piinv)); z = nf_to_Fq(nf, z, modP); z = Fq_Fp_mul(z,stoi(-6),T,p); c = Fq_issquare(z,T,p)? 3: 1; break; case 6: kod = -1; piinv2 = nfsqr(nf,piinv); piinv3 = nfmul(nf,piinv,piinv2); z = nfmul(nf,c4,piinv2); z = nf_to_Fq(nf, z, modP); z = Fq_Fp_mul(z,stoi(-3), T,p); w = nfmul(nf,c6,piinv3); w = nf_to_Fq(nf, w, modP); w = Fq_Fp_mul(w,gen_m2, T,p); c = 1 + FqX_nbroots(mkpoln(4, gen_1,gen_0,z,w), T,p); break; case 8: kod = -4; piinv4 = nfpow_u(nf,piinv,4); z = nfmul(nf,c6,piinv4); z = nf_to_Fq(nf, z, modP); z = Fq_Fp_mul(z,stoi(-6),T,p); c = Fq_issquare(z,T,p)? 3: 1; break; case 9: kod = -3; c = 2; break; case 10: kod = -2; c = 1; break; } } return localred_result(f,kod,c,ch); } /* E is integral */ static GEN nflocalred(GEN E, GEN pr) { GEN p = pr_get_p(pr), q, v, nf = ellnf_get_nf(E); long i; if (abscmpiu(p, 3) <= 0) { long ap, vu; GEN e = ell_to_nfell10(E), D = ell_get_disc(E), u; q = nflocalred_23(nf,e,D,pr,&ap); v = gel(q,3); u = gel(v,1); /* do nothing if already minimal or equation was not pr-integral */ vu = nfval(nf, u, pr); if (vu > 0) { /* remove denominators in r,s,t on nf.zk */ GEN D, r = gel(v,2), s = gel(v,3), t = gel(v,4); D = Q_denom(mkvec3(r, s, t)); if (!equali1(D)) { /* Beware: D may not be coprime to pr */ GEN a; (void)nfvalrem(nf, D, pr, &D); /* a in D/p^oo, = 1 mod (u^6) locally */ a = idealaddtoone_i(nf, D, idealpows(nf, pr, 6*vu)); gel(v,2) = nfmul(nf, r, a); gel(v,3) = nfmul(nf, s, a); gel(v,4) = nfmul(nf, t, a); } } } else q = nflocalred_p(E,pr); v = gel(q,3); for(i=1; i <= 4; i++) gel(v,i) = nftoalg(nf, gel(v,i)); return q; } static GEN checkellp(GEN *pE, GEN p, GEN *pv, const char *s) { GEN q, E = *pE; long tE; checkell(E); tE = ell_get_type(E); if (pv) *pv = NULL; if (p) switch(typ(p)) { case t_INT: if (cmpis(p, 2) < 0) pari_err_DOMAIN(s,"p", "<", gen_2, p); break; case t_VEC: q = get_prid(p); if (q && tE == t_ELL_NF) { *pE = ellintegralmodel_i(E, pv); return q; } default: pari_err_TYPE(s,p); } switch(tE) { case t_ELL_Fp: case t_ELL_Fq: q = ellff_get_p(E); break; case t_ELL_Qp: q = ellQp_get_p(E); break; case t_ELL_Q: if (p) { q = p; p = NULL; break; } default: pari_err_TYPE(stack_strcat(s," [can't determine p]"), E); return NULL;/*LCOV_EXCL_LINE*/ } if (p && !equalii(p, q)) pari_err_MODULUS(s, p,q); if (tE == t_ELL_Q || tE == t_ELL_Qp || tE == t_ELL_NF) *pE = ellintegralmodel_i(E, pv); return q; } GEN elllocalred(GEN E, GEN p) { pari_sp av = avma; GEN v, q; checkell(E); p = checkellp(&E, p, &v, "elllocalred"); switch(ell_get_type(E)) { case t_ELL_Qp: case t_ELL_Q: q = localred(E, p); break; case t_ELL_NF: q = nflocalred(E, p); break; default: pari_err_TYPE("elllocalred", E); return NULL;/*LCOV_EXCL_LINE*/ } if (v) { /* compose local change of variables with v */ GEN u = gel(v,1), w = gel(q,3); if (is_trivial_change(w)) gel(q,3) = mkvec4(u,gen_0,gen_0,gen_0); else gel(w,1) = gmul(u, gel(w,1)); } return gerepilecopy(av, q); } /* typ(c) = t_INT or t_FRAC */ static GEN handle_Q(GEN c, GEN *pd) { *pd = (typ(c) == t_INT)? NULL: gel(c,2); return c; } static GEN handle_coeff(GEN nf, GEN c, GEN *pd) { *pd = NULL; switch(typ(c)) { case t_INT: *pd = NULL; return c; case t_FRAC: *pd = gel(c,2); return c; case t_POL: case t_POLMOD: case t_COL: if (nf) { c = nf_to_scalar_or_basis(nf,c); return handle_Q(Q_content(c), pd); } default: pari_err_TYPE("ellintegralmodel",c); return NULL;/*LCOV_EXCL_LINE*/ } } /* Return an integral model for e / nf, Q. Set v = NULL (already integral) * or the variable change [u,0,0,0], u = 1/t, t > 1 integer making e integral */ GEN ellintegralmodel_i(GEN e, GEN *pv) { GEN a, t, u, L, nf; long i, l, k; if (pv) *pv = NULL; /* t_ELL_Qp is also possible */ nf = (ell_get_type(e) == t_ELL_NF)?ellnf_get_nf(e): NULL; L = cgetg(1, t_VEC); a = cgetg(6, t_VEC); for (i = 1; i < 6; i++) { GEN d; gel(a,i) = handle_coeff(nf, gel(e,i), &d); if (d) /* partial factorization of denominator */ L = shallowconcat(L, gel(Z_factor_limit(d, 0),1)); } /* a = [a1, a2, a3, a4, a6] */ l = lg(L); if (l == 1) return e; L = ZV_sort_uniq_shallow(L); l = lg(L); t = gen_1; for (k = 1; k < l; k++) { GEN p = gel(L,k); long n = 0, m; for (i = 1; i < 6; i++) if (!gequal0(gel(a,i))) { long r = (i == 5)? 6: i; /* a5 is missing */ m = r * n + Q_pval(gel(a,i), p); while (m < 0) { n++; m += r; } } t = mulii(t, powiu(p, n)); } u = ginv(t); if (pv) *pv = mkvec4(u,gen_0,gen_0,gen_0); return coordch_uinv(e, t); } GEN ellintegralmodel(GEN e, GEN *pv) { pari_sp av = avma; checkell(e); switch(ell_get_type(e)) { case t_ELL_Q: case t_ELL_Qp: case t_ELL_NF: break; default: pari_err_TYPE("ellintegralmodel",e); } e = ellintegralmodel_i(e, pv); if (pv && *pv) return gc_all(av, 2, &e, pv); e = gerepilecopy(av, e); if (pv) *pv = init_ch(); return e; } /* return an integral model with a1 = a3 = 0 */ GEN ellintegralbmodel(GEN e, GEN *pv) { pari_sp av = avma; GEN f, a1, a3; checkell(e); f = ellintegralmodel_i(e, pv); a1 = ell_get_a1(f); a3 = ell_get_a3(f); if (!signe(a1) && !signe(a3)) { if (!*pv) *pv = init_ch(); } else { GEN v = mkvec4(mpodd(a1) || mpodd(a3) ? ghalf : gen_1, gen_0, gdivgs(a1,-2), gdivgs(a3,-2)); gcomposev(pv, v); f = coordch(f, v); } if (f != e) ell_reset(f); return gc_all(av, 2, &f, pv); } static long F2_card(ulong a1, ulong a2, ulong a3, ulong a4, ulong a6) { long N = 1; /* oo */ if (!a3) N ++; /* x = 0, y=0 or 1 */ else if (!a6) N += 2; /* x = 0, y arbitrary */ if ((a3 ^ a1) == 0) N++; /* x = 1, y = 0 or 1 */ else if (a2 ^ a4 ^ a6) N += 2; /* x = 1, y arbitrary */ return N; } static long F3_card(ulong b2, ulong b4, ulong b6) { ulong Po = 1+2*b4, Pe = b2+b6; /* kro(x,3)+1 = (x+1)%3, N = 4 + sum(kro) = 1+ sum(1+kro) */ return 1+(b6+1)%3+(Po+Pe+1)%3+(2*Po+Pe+1)%3; } static long cardmod2(GEN e) { /* solve y(1 + a1x + a3) = x (1 + a2 + a4) + a6 */ ulong a1 = Rg_to_F2(ell_get_a1(e)); ulong a2 = Rg_to_F2(ell_get_a2(e)); ulong a3 = Rg_to_F2(ell_get_a3(e)); ulong a4 = Rg_to_F2(ell_get_a4(e)); ulong a6 = Rg_to_F2(ell_get_a6(e)); return F2_card(a1,a2,a3,a4,a6); } static long cardmod3(GEN e) { ulong b2 = Rg_to_Fl(ell_get_b2(e), 3); ulong b4 = Rg_to_Fl(ell_get_b4(e), 3); ulong b6 = Rg_to_Fl(ell_get_b6(e), 3); return F3_card(b2,b4,b6); } static ulong ZtoF2(GEN x) { return (ulong)mpodd(x); } /* complete local reduction at 2, u = 2^d */ static void min_set_2(ellmin_t *M, GEN E, long d) { min_set_u(M, int2n(d)); min_set_c(M, E); min_set_b(M); min_set_a(M); } /* local reduction at 3, u = 3^d, don't compute the a_i */ static void min_set_3(ellmin_t *M, GEN E, long d) { min_set_u(M, powuu(3, d)); min_set_c(M, E); min_set_b(M); } static long ellQap_u(GEN E, ulong p, int *good_red) { long vc6, vD, d = get_vp_u_small(E, p, &vc6, &vD); if (vD) /* bad reduction */ { GEN c6; long s; *good_red = 0; if (vc6) return 0; c6 = ell_get_c6(E); if (d) c6 = diviiexact(c6, powuu(p, 6*d)); s = kroiu(c6,p); if ((p & 3) == 3) s = -s; return s; } *good_red = 1; if (p == 2) { ellmin_t M; if (!d) return 3 - cardmod2(E); min_set_2(&M, E, d); return 3 - F2_card(M.a1, M.a2 & 1, M.a3, ZtoF2(M.a4), ZtoF2(M.a6)); } else if (p == 3) { ellmin_t M; if (!d) return 4 - cardmod3(E); min_set_3(&M, E, d); return 4 - F3_card(M.b2, umodiu(M.b4,3), umodiu(M.b6,3)); } else { ellmin_t M; GEN a4, a6, pp = utoipos(p); min_set_u(&M, powuu(p,d)); min_set_c(&M, E); c4c6_to_a4a6(M.c4, M.c6, pp, &a4,&a6); return itos( subui(p+1, Fp_ellcard(a4, a6, pp)) ); } } static GEN ellQap(GEN E, GEN p, int *good_red) { GEN a4,a6, c4, c6, D; long vc6, vD, d; if (lgefint(p) == 3) return stoi( ellQap_u(E, p[2], good_red) ); c6 = ell_get_c6(E); D = ell_get_disc(E); vc6 = Z_pval(c6,p); vD = Z_pval(D,p); d = minss(2*vc6, vD) / 12; if (d) { vc6 -= 6*d; vD -= 12*d; } /* non minimal model */ if (vD) /* bad reduction */ { long s; *good_red = 0; if (vc6) return gen_0; if (d) c6 = diviiexact(c6, powiu(p, 6*d)); s = kronecker(c6,p); if (mod4(p) == 3) s = -s; return s < 0? gen_m1: gen_1; } *good_red = 1; c4 = ell_get_c4(E); if (d) { GEN u2 = powiu(p, 2*d), u4 = sqri(u2), u6 = mulii(u2,u4); c4 = diviiexact(c4, u4); c6 = diviiexact(c6, u6); } c4c6_to_a4a6(c4, c6, p, &a4,&a6); return subii(addiu(p,1), Fp_ellcard(a4, a6, p)); } static GEN doellcard(GEN E) { GEN fg = ellff_get_field(E); if (typ(fg)==t_FFELT) return FF_ellcard(E); else { GEN e = ellff_get_a4a6(E); return Fp_ellcard(gel(e,1),gel(e,2),fg); } } static GEN ellnfap(GEN E, GEN P, int *good_red) { GEN a4,a6, card, nf = ellnf_get_nf(E); GEN T,p, modP = nf_to_Fq_init(nf,&P,&T,&p); if (abscmpiu(p, 3) <= 0) { long ap; GEN nf = ellnf_get_nf(E), e = ell_to_nfell10(E), D = ell_get_disc(E); GEN L = nflocalred_23(nf, e,D,P,&ap), kod = gel(L,2); if (!equali1(kod)) { *good_red = 0; return stoi(ap); } *good_red = 1; E = nf_coordch(nf, vecslice(e,1,5), gel(L,3)); E = ellinit_nf_to_Fq(nf, E, modP); card = FF_ellcard(E); } else { GEN c6 = ell_get_c6(E), c4 = ell_get_c4(E); long vD = nfval(nf, ell_get_disc(E), P); if (vD) { GEN c6new; long d, vc6 = nfvalrem(nf,c6,P, &c6new); d = ((vc6 == LONG_MAX)? vD: minss(vD,2*vc6)) / 12; if (vD > 12*d) { /* bad reduction */ *good_red = 0; if (vc6 != 6*d) return gen_0; c6 = nf_to_Fq(nf, c6new, modP); return Fq_issquare(gneg(c6),T,p)? gen_1: gen_m1; } if (d) { /* model not minimal at P */ GEN piinv = get_piinv(P); GEN ui2 = nfpow(nf, piinv, stoi(2*d)); GEN ui4 = nfsqr(nf, ui2); GEN ui6 = nfmul(nf, ui2, ui4); c4 = nfmul(nf, c4, ui4); c6 = nfmul(nf, c6, ui6); } } *good_red = 1; c4 = nf_to_Fq(nf, c4, modP); c6 = nf_to_Fq(nf, c6, modP); Fq_c4c6_to_a4a6(c4, c6, T,p, &a4,&a6); card = T? FpXQ_ellcard(Fq_to_FpXQ(a4,T,p),Fq_to_FpXQ(a6,T,p),T,p) : Fp_ellcard(a4,a6,p); } return subii(addiu(pr_norm(P),1), card); } /* a, b not both 0; sorted list of primes dividing gcd(a,b), using coprime * basis */ static GEN Z_gcd_primes(GEN a, GEN b) { GEN P; if (!signe(a)) P = gel(absZ_factor(b), 1); else if (!signe(b)) P = gel(absZ_factor(a), 1); else { GEN A, B, v = Z_ppio(a,b), d = gel(v,1); /* = gcd(a,b) */ long k, l; if (is_pm1(d)) return cgetg(1, t_COL); A = gel(v,2); /* gcd(a, b^oo) */ B = diviiexact(b, Z_ppo(b, d)); /* gcd(b, a^oo) */ /* d = gcd(A,B) */ P = Z_cba(A, B); /* use coprime basis to help as much as possible */ l = lg(P); for (k = 1; k < l; k++) gel(P,k) = gel(Z_factor(gel(P,k)), 1); P = shallowconcat1(P); ZV_sort_inplace(P); } settyp(P, t_VEC); return P; } /* E/Q, integral model, Laska-Kraus-Connell algorithm. Set *pDP to a list * of known prime divisors of minimal discriminant */ static GEN ellQ_minimalu(GEN E, GEN *pDP) { pari_sp av; GEN D = ell_get_disc(E); GEN c4 = ell_get_c4(E); GEN c6 = ell_get_c6(E), g, u, P, DP; long l, k; P = Z_gcd_primes(c4, c6); l = lg(P); if (l == 1) { if(pDP) *pDP = P; return gen_1; } DP = coltrunc_init(l); av = avma; g = gcdii(sqri(c6), D); u = gen_1; for (k = 1; k < l; k++) { GEN p = gel(P, k); long vg = Z_pval(g, p), d = vg / 12, r = vg % 12; if (d) switch(itou_or_0(p)) { case 2: { long a, b; a = Mod16( shifti(c4, -4*d) ); b = Mod32( shifti(c6, -6*d) ); if ((b & 3) != 3 && (a || (b && b!=8))) { d--; r += 12; } break; } case 3: if (safe_Z_lval(c6,3) == 6*d+2) { d--; r += 12; } break; } if (r) vectrunc_append(DP, p); if (d) u = mulii(u, powiu(p, d)); } if (pDP) *pDP = DP; return gerepileuptoint(av, u); } /* Ensure a1 and a3 are 2-restricted and a2 is 3-restricted */ static GEN nfrestrict23(GEN nf, GEN E) { GEN a1 = nf_to_scalar_or_basis(nf, ell_get_a1(E)), A1, A2, A3, r, s, t; GEN a2 = nf_to_scalar_or_basis(nf, ell_get_a2(E)); GEN a3 = nf_to_scalar_or_basis(nf, ell_get_a3(E)); A1 = gmodgs(a1,2); s = gshift(gsub(A1,a1), -1); s = lift_if_rational(basistoalg(nf, s)); A2 = nfsub(nf, a2, nfmul(nf,s, nfadd(nf,a1,s))); r = gdivgu(gsub(gmodgs(A2,3), A2), 3); r = lift_if_rational(basistoalg(nf, r)); A3 = nfadd(nf, a3, nfmul(nf,r,A1)); t = nfadd(nf, nfmul(nf, r,s), gshift(gsub(gmodgs(A3,2), A3), -1)); t = lift_if_rational(basistoalg(nf, t)); return mkvec4(gen_1, r, s, t); } static GEN zk_capZ(GEN nf, GEN x) { GEN mx = zk_scalar_or_multable(nf, x); return (typ(mx) == t_INT)? mx: zkmultable_capZ(mx); } static GEN ellnf_c4c6_primes(GEN E) { GEN nf = ellnf_get_nf(E); GEN c4Z = zk_capZ(nf, ell_get_c4(E)); GEN c6Z = zk_capZ(nf, ell_get_c6(E)); return Z_gcd_primes(c4Z, c6Z); /* primes dividing (c4,c6) \cap Z */ } static GEN ellnf_D_primes(GEN E) { GEN nf = ellnf_get_nf(E); GEN P = ellnf_c4c6_primes(E); GEN DZ = zk_capZ(nf, ell_get_disc(E)); long k, l = lg(P); for (k = 1; k < l; k++) (void)Z_pvalrem(DZ, gel(P,k), &DZ); if (!is_pm1(DZ)) { GEN Q = gel(absZ_factor(DZ),1); settyp(Q, t_VEC); P = shallowconcat(P, Q); ZV_sort_inplace(P); } return P; } /* convert vector of localreds to NF_MINIMALPRIMES */ static GEN Q_to_minimalprimes(GEN nf, GEN P, GEN Q) { GEN L, Lr, Ls, Lt, U; long k, l = lg(P); Lr = vectrunc_init(l); Ls = vectrunc_init(l); Lt = vectrunc_init(l); L = vectrunc_init(l); settyp(L,t_COL); U = vectrunc_init(l); settyp(U,t_COL); for (k = 1; k < l; k++) { GEN pr = gel(P, k), q = gel(Q, k), v, u; long vu; v = gel(q,3); u = gel(v,1); vu = nfval(nf, u, pr); if (!vu) continue; vectrunc_append(Lr, gel(v,2)); vectrunc_append(Ls, gel(v,3)); vectrunc_append(Lt, gel(v,4)); vectrunc_append(L, pr); vectrunc_append(U, stoi(vu)); } return mkvec5(L, U, Lr, Ls, Lt); } /* E integral */ static GEN ellminimalprimes(GEN E) { GEN S, nf, c4, c6, P, Q; long j, k, l; if ((S = obj_check(E, NF_MINIMALPRIMES))) return S; nf = ellnf_get_nf(E); c4 = nf_to_scalar_or_basis(nf, ell_get_c4(E)); c6 = nf_to_scalar_or_basis(nf, ell_get_c6(E)); if (typ(c4) == t_INT) c4 = NULL; if (typ(c6) == t_INT) c6 = NULL; P = nf_pV_to_prV(nf, ellnf_c4c6_primes(E)); Q = cgetg_copy(P, &l); for (k = j = 1; k < l; k++) { GEN pr = gel(P, k); if (c4 && !ZC_prdvd(c4,pr)) continue; if (c6 && !ZC_prdvd(c6,pr)) continue; gel(Q,j) = nflocalred(E, pr); /* pr | (c4,c6) */ gel(P,j++) = pr; } setlg(P,j); setlg(Q,j); return obj_insert(E, NF_MINIMALPRIMES, Q_to_minimalprimes(nf,P,Q)); } static GEN ellnf_minimalnormu(GEN E0) { GEN E, S, L, U, P, v, Nu = NULL, nf = ellnf_get_nf(E0); long i, l; E = ellintegralmodel_i(E0, &v); S = ellminimalprimes(E); L = gel(S,1); U = gel(S,2); if (v) Nu = idealnorm(nf, gel(v,1)); P = cgetg_copy(L, &l); for (i = 1; i < l; i++) gel(P,i) = pr_norm(gel(L,i)); P = factorback2(P, U); if (Nu) P = gmul(Nu, P); return P; } /* E integral model; return change of variable to minimal model (t_VEC) * or (nontrivial) Weierstrass class (t_COL) */ static GEN bnf_get_v(GEN E) { GEN bnf = ellnf_get_bnf(E); GEN nf, L, Lr, Ls, Lt, F, C, U, R, S, T; if (!bnf) pari_err_TYPE("ellminimalmodel (need a bnf)", ellnf_get_nf(E)); S = ellminimalprimes(E); L = gel(S,1); U = gel(S,2); Lr = gel(S,3); Ls = gel(S,4); Lt = gel(S,5); F = isprincipalfact(bnf, NULL, L, U, nf_GEN); if (!gequal0(gel(F,1))) return gel(F,1); nf = bnf_get_nf(bnf); C = idealchinese(nf, mkmat2(L, ZC_z_mul(U,6)), NULL); U = basistoalg(nf, gel(F,2)); R = basistoalg(nf, idealchinese(nf, C, Lr)); S = basistoalg(nf, idealchinese(nf, C, Ls)); T = basistoalg(nf, idealchinese(nf, C, Lt)); return lift_if_rational(mkvec4(U,R,S,T)); } GEN ellminimaldisc(GEN E) { pari_sp av = avma; checkell(E); switch(ell_get_type(E)) { case t_ELL_Q: E = ellminimalmodel(E,NULL); return gerepileuptoint(av, absi_shallow(ell_get_disc(E))); case t_ELL_NF: { GEN nf = ellnf_get_nf(E), S, L, U, D; E = ellintegralmodel_i(E,NULL); S = ellminimalprimes(E); L = gel(S,1); U = ZC_z_mul(gel(S,2), 12); D = idealfactorback(nf, L, U, 0); return gerepileupto(av, idealdiv(nf, ell_get_disc(E), D)); } default: pari_err_TYPE("ellminimaldisc (E / number field)", E); return NULL; /*LCOV_EXCL_LINE*/ } } /* update Q_MINIMALMODEL entry in E, but don't update type-specific data on * ellminimalmodel(E) */ static GEN ellminimalmodel_i(GEN E, GEN *ptv, GEN *pS) { GEN S, y, e, v, v0, u, DP; ellmin_t M; if ((S = obj_check(E, Q_MINIMALMODEL))) { if (lg(S) != 2) { E = gel(S,3); v = gel(S,2); } else v = init_ch(); if (ptv) *ptv = v; if (pS) *pS = S; return gcopy(E); } e = ellintegralmodel_i(E, &v0); u = ellQ_minimalu(e, &DP); min_set_all(&M, e, u); v = min_get_v(&M, e); y = min_to_ell(&M, e); if (v0) { gcomposev(&v0, v); v = v0; } if (is_trivial_change(v)) { v = init_ch(); S = mkvec(DP); } else S = mkvec3(DP, v, y); obj_insert(E, Q_MINIMALMODEL, S); if (pS) *pS = S; if (ptv) *ptv = v; return y; } static GEN ellQminimalmodel(GEN E, GEN *ptv) { pari_sp av = avma; GEN S, DP, v, y = ellminimalmodel_i(E, &v, &S); if (!is_trivial_change(v)) ch_Q(y, E, v); DP = gel(S,1); obj_insert_shallow(y, Q_MINIMALMODEL, mkvec(DP)); if (!ptv) return gerepilecopy(av, y); *ptv = v; return gc_all(av, 2, &y, ptv); } static GEN ellnfminimalmodel_i(GEN E, GEN *ptv) { GEN S, y, v, v2; if ((S = obj_check(E, NF_MINIMALMODEL))) { switch(lg(S)) { case 1: v = init_ch(); break; case 2: v = NULL; E = gel(S,1); break; default: E = gel(S,2); v = gel(S,1); break; } *ptv = v; return gcopy(E); } *ptv = NULL; y = ellintegralmodel_i(E, &v); v2 = bnf_get_v(y); if (typ(v2) == t_COL) { obj_insert(E, NF_MINIMALMODEL, mkvec(v2)); return v2; /* nontrivial Weierstrass class */ } y = coordch(y, v2); gcomposev(&v, v2); v2 = nfrestrict23(ellnf_get_nf(E), y); y = coordch(y, v2); /* copy to avoid inserting twice in y = E */ y = obj_reinit(y); gcomposev(&v, v2); if (is_trivial_change(v)) { v = init_ch(); S = cgetg(1,t_VEC); } else { v = lift_if_rational(v); S = mkvec2(v, y); } obj_insert(E, NF_MINIMALMODEL, S); *ptv = v; return y; } static GEN ellnfminimalmodel(GEN E, GEN *ptv) { pari_sp av = avma; GEN v, y = ellnfminimalmodel_i(E, &v); if (v) obj_insert_shallow(y, NF_MINIMALMODEL, cgetg(1,t_VEC)); if (!v || !ptv) return gerepilecopy(av, y); *ptv = v; return gc_all(av, 2, &y, ptv); } GEN ellminimalmodel(GEN E, GEN *ptv) { checkell(E); switch(ell_get_type(E)) { case t_ELL_Q: return ellQminimalmodel(E, ptv); case t_ELL_NF: return ellnfminimalmodel(E, ptv); default: pari_err_TYPE("ellminimalmodel (E / number field)", E); return NULL; /*LCOV_EXCL_LINE*/ } } /* return a model minimal among b models */ GEN ellminimalbmodel(GEN e, GEN *pv) { pari_sp av = avma; GEN f, a1, a3; checkell(e); f = ellminimalmodel(e, pv); a1 = ell_get_a1(f); a3 = ell_get_a3(f); if (!signe(a1) && !signe(a3)) { if (!*pv) *pv = init_ch(); } else { GEN v = mkvec4(mpodd(a1) || mpodd(a3) ? ghalf : gen_1, gen_0, gdivgs(a1,-2), gdivgs(a3,-2)); gcomposev(pv, v); f = coordch(f, v); } if (f != e) ell_reset(f); return gc_all(av, 2, &f, pv); } /* Reduction of a rational curve E to its standard minimal model, don't * update type-dependant components. * Set v = [u, r, s, t] = change of variable E -> minimal model, with u > 0 * Set gr = [N, [u,r,s,t], c, fa, L], where * N = arithmetic conductor of E * c = product of the local Tamagawa numbers cp * fa = factorization of N * L = list of localred(E,p) for p | N. */ static GEN ellQ_globalred(GEN e) { long k, l, iN; GEN S, c, E, L, P, NP, NE, D; E = ellminimalmodel_i(e, NULL, &S); P = gel(S,1); l = lg(P); /* some known prime divisors of D */ D = ell_get_disc(E); for (k = 1; k < l; k++) (void)Z_pvalrem(D, gel(P,k), &D); if (!is_pm1(D)) { P = shallowconcat(P, gel(absZ_factor(D),1)); ZV_sort_inplace(P); } l = lg(P); c = gen_1; iN = 1; NP = cgetg(l, t_COL); NE = cgetg(l, t_COL); L = cgetg(l, t_VEC); for (k = 1; k < l; k++) { GEN p = gel(P,k), q = localred(E, p), ex = gel(q,1); if (!signe(ex)) continue; gel(NP, iN) = p; gel(NE, iN) = ex; gel(L, iN) = q; iN++; gel(q,3) = gen_0; /*delete variable change*/ c = mulii(c, gel(q,4)); } setlg(L, iN); setlg(NP, iN); setlg(NE, iN); return mkvec4(factorback2(NP,NE), c, mkmat2(NP,NE), L); } static GEN ellglobalred_i(GEN E) { return obj_checkbuild(E, Q_GLOBALRED, &ellQ_globalred); } static GEN Q_to_globalred(GEN nf, GEN P, GEN Q, GEN v) { GEN c, L, NP, NE; long j, k, l = lg(P); c = gen_1; NP = cgetg(l, t_COL); NE = cgetg(l, t_COL); L = cgetg(l, t_VEC); for (k = j = 1; k < l; k++) { GEN p = gel(P,k), q = gel(Q,k), ex; ex = gel(q,1); if (!signe(ex)) continue; gel(NP, j) = p; gel(NE, j) = ex; gel(L, j) = q; j++; c = mulii(c, gel(q,4)); } setlg(L, j); setlg(NP, j); setlg(NE, j); return mkvec5(idealfactorback(nf,NP,NE,0), v, c, mkmat2(NP,NE), L); } static GEN ellnfglobalred(GEN E0) { GEN E, P, Q, D, nf, v; long j, k, l; E = ellintegralmodel_i(E0, &v); if (!v) v = init_ch(); nf = ellnf_get_nf(E); P = nf_pV_to_prV(nf, ellnf_D_primes(E)); D = nf_to_scalar_or_basis(nf, ell_get_disc(E)); if (typ(D) == t_INT) D = NULL; Q = cgetg_copy(P, &l); for (k = j = 1; k < l; k++) { GEN p = gel(P,k); if (D && !ZC_prdvd(D, p)) continue; gel(Q,j) = nflocalred(E, p); gel(P,j++) = p; } setlg(P,j); setlg(Q,j); if (!obj_check(E0, NF_MINIMALPRIMES)) (void)obj_insert(E0, NF_MINIMALPRIMES, Q_to_minimalprimes(nf,P,Q)); return Q_to_globalred(nf,P,Q,v); } GEN ellglobalred(GEN E) { pari_sp av = avma; GEN S, gr, v; checkell(E); switch(ell_get_type(E)) { default: pari_err_TYPE("ellglobalred",E); case t_ELL_Q: gr = ellglobalred_i(E); S = obj_check(E, Q_MINIMALMODEL); v = (lg(S) == 2)? init_ch(): gel(S,2); v = mkvec5(gel(gr,1), v, gel(gr,2),gel(gr,3),gel(gr,4)); break; case t_ELL_NF: v = obj_checkbuild(E, NF_GLOBALRED, &ellnfglobalred); break; } return gerepilecopy(av, v); } static GEN doellrootno(GEN e); /* Return E = ellminimalmodel(e), but only update E[1..14]. * insert MINIMALMODEL, GLOBALRED, ROOTNO in both e (regular insertion) * and E (shallow insert) */ GEN ellanal_globalred(GEN e, GEN *ch) { GEN E, S, v = NULL; checkell_Q(e); if (!(S = obj_check(e, Q_MINIMALMODEL))) { E = ellminimalmodel_i(e, &v, &S); obj_insert_shallow(E, Q_MINIMALMODEL, mkvec(gel(S,1))); } else if (lg(S) == 2) /* trivial change */ E = e; else { v = gel(S,2); E = gcopy(gel(S,3)); obj_insert_shallow(E, Q_MINIMALMODEL, mkvec(gel(S,1))); } if (ch) *ch = v; S = ellglobalred_i(e); if (E != e) obj_insert_shallow(E, Q_GLOBALRED, S); S = obj_check(e, Q_ROOTNO); if (!S) { S = doellrootno(E); obj_insert(e, Q_ROOTNO, S); /* insert in e */ } if (E != e) obj_insert_shallow(E, Q_ROOTNO, S); /* ... and in E */ return E; } static long nb_real_components(GEN E) { return gsigne(ell_get_disc(E)) > 0? 2: 1; } /* E minimal, \Omega_E^s in "La constante de Manin et le degre modulaire * d'une courbe elliptique" */ GEN ellQtwist_bsdperiod(GEN E, long s) { GEN w = ellR_omega(E,DEFAULTPREC); if (s == 1) w = gel(w,1); else if (nb_real_components(E) == 2) w = gneg(gel(w,2)); else w = mkcomplex(gen_0, gneg(gmul2n(imag_i(gel(w,2)), 1))); return w; } static GEN ellQ_tamagawa(GEN e) { GEN red = ellglobalred(e), tam = gel(red,3); return muliu(tam, nb_real_components(e)); } static GEN ellnf_tamagawa(GEN e) { GEN red = ellglobalred(e), tam = gel(red,3); GEN nf = ellnf_get_nf(e), s = nfsign(nf, ell_get_disc(e)); long r1, r2; nf_get_sign(nf, &r1, &r2); return shifti(tam, r2 + r1 - hammingweight(s)); } GEN elltamagawa(GEN E) { pari_sp av = avma; GEN v; checkell(E); switch(ell_get_type(E)) { default: pari_err_TYPE("elltamagawa",E); case t_ELL_Q: v = ellQ_tamagawa(E); break; case t_ELL_NF: v = ellnf_tamagawa(E); break; } return gerepileuptoint(av, v); } static GEN ellnf_get_nf_prec(GEN E, long prec) { GEN S, nf = ellnf_get_nf(E); if (nf_get_prec(nf) >= prec) return nf; if ((S = obj_check(E, NF_NF)) && nf_get_prec(S) >= prec) return S; return obj_insert(E, NF_NF, nfnewprec_shallow(nf, prec)); } /* true nf, use nf prec */ static GEN nfembedall(GEN nf, GEN x) { long r1, r2; GEN cx; nf_get_sign(nf,&r1,&r2); x = nf_to_scalar_or_basis(nf,x); if (typ(x) != t_COL) return const_vec(r1+r2, x); x = Q_primitive_part(x, &cx); x = RgM_RgC_mul(nf_get_M(nf), x); if (cx) x = RgC_Rg_mul(x,cx); return x; } static long nfembed_extraprec(GEN x) { long e = gexpo(x); return (e < 8)? 0: nbits2extraprec(e); } static GEN ellnfembed(GEN E, long prec) { GEN E0, nf = ellnf_get_nf(E), Eb = cgetg(6,t_VEC), e = cgetg(6,t_VEC), L, sD; long prec0, r1, r2, n, i; nf_get_sign(nf, &r1, &r2); n = r1+r2; E0 = RgC_to_nfC(nf, vecslice(E,1,5)); prec0 = prec + EXTRAPREC64; /* need accuracy 3b for bmodel to ensure roots are correct to b bits */ prec += 3*prec0 + nfembed_extraprec(E0); L = cgetg(n+1, t_VEC); sD = nfeltsign(nf, ell_get_disc(E), identity_perm(r1)); for(;;) { nf = ellnf_get_nf_prec(E, prec); for (i=1; i<=5; i++) gel(Eb,i) = nfembedall(nf,gel(E0,i)); for (i=1; i<=n; i++) { GEN Ei, r; long j; for (j=1; j<=5; j++) gel(e,j) = gmael(Eb,j,i); gel(L,i) = Ei = ellinit_Rg(e, i<=r1? signe(gel(sD,i)): 0, prec); if (!Ei) break; r = doellR_roots_i(Ei, prec, prec0); if (!r) break; } if (i > n) return L; prec = precdbl(prec); if (DEBUGLEVEL>1) pari_warn(warnprec,"ellnfembed", prec); } } static GEN ellpointnfembed(GEN E, GEN P, long prec) { GEN nf = ellnf_get_nf(E), Px, Py, L; long i, l; P = RgC_to_nfC(nf, P); prec += nfembed_extraprec(P); nf = ellnf_get_nf_prec(E, prec); Px = nfembedall(nf, gel(P,1)); Py = nfembedall(nf, gel(P,2)); l = lg(Px); L = cgetg(l, t_VEC); for(i = 1; i < l; i++) gel(L,i) = mkvec2(gel(Px,i), gel(Py,i)); return L; } static void ellnfembed_free(GEN L) { long i, l = lg(L); for(i = 1; i < l; i++) obj_free(gel(L,i)); } static GEN ellnf_vec_wrap(GEN (*fun)(GEN, long), GEN E, long prec) { pari_sp av = avma; GEN V = ellnfembed(E, prec); long i, l = lg(V); GEN P = cgetg(l, t_VEC); for(i=1; i>2,hn) > 0) return gc_NULL(av); } } GEN ellQ_genreduce(GEN E, GEN G, GEN M, long prec) { pari_sp av = avma; long i, j, l = lg(G); GEN L, V = cgetg(l, t_VEC); if (!M) M = ellheightmatrix(E, G, prec); while(1) { L = lllgram(M); if (L) break; prec = precdbl(prec); M = ellheightmatrix(E, G, prec); } l = lg(L); /* can decrease */ for (i = j = 1; i < l; i++) { GEN Li = gel(L, i), h = qfeval(M, Li); if (expo(h) > -prec/2) gel(V,j++) = ellQ_factorback(E, G, Li, 1, h, prec); } setlg(V, j); return gerepilecopy(av, V); } static long ellQ_isdivisible_test(forprime_t *S, GEN E, long CM, GEN P, ulong l, long nb) { GEN D = ell_get_disc(E); pari_sp av = avma; long m; for (m = 1; m <= nb; set_avma(av)) { ulong o, a4, a6, p = u_forprime_next(S); if (dvdiu(D, p)) continue; Fl_ell_to_a4a6(E, p, &a4, &a6); o = p+1 - Fl_elltrace_CM(CM, a4, a6, p); if (o % l == 0) { ulong pi = get_Fl_red(p); GEN a4a6 = a4a6_ch_Fl(E,p); GEN Q = Flj_changepointinv_pre(ZV_to_Flv(P, p), a4a6, p, pi); GEN R = Flj_mulu_pre(Q, o/l, a4, p, pi); if (uel(R, 3) != 0) return 0; m++; } } return 1; } /* Assume l prime to 210 */ GEN ellQ_isdivisible(GEN E, GEN P, ulong l) { pari_sp av = avma; GEN worker, mod = gen_1, H = NULL, D = ell_get_disc(E), PJ = QE_to_ZJ(P); forprime_t S, U; long CM = ellQ_get_CM(E); ulong bound; u_forprime_init(&U, l+1, ULONG_MAX); if (!ellQ_isdivisible_test(&U, E, CM, PJ, l, 10)) return gc_NULL(av); worker = snm_closure(is_entry("_ellQ_factorback_worker"), mkvec4(E, mkvec(PJ), mkvecs(1), utoi(l))); init_modular_small(&S); for (bound = 1;; bound <<= 1) { GEN amax, r; gen_inccrt("ellQ_factorback", worker, D, bound, 0, &S, &H, &mod, ellQ_factorback_chinese, NULL); amax = sqrti(shifti(mod,-2)); if (!ell_is_inf(H) && (r = FpC_ratlift(H, mod, amax, amax, NULL)) && oncurve_exact(E,r)) { settyp(r,t_VEC); if (gequal(ellmul(E,r,utoi(l)), P)) return gerepileupto(av, r); if (!ellQ_isdivisible_test(&U, E, CM, PJ, l, 10)) return gc_NULL(av); } } } /********************************************************************/ /** **/ /** ROOT NUMBER (after Halberstadt at p = 2,3) **/ /** **/ /********************************************************************/ /* x a t_INT */ static long val_aux(GEN x, long p, long pk, long *u) { long v; GEN z; if (!signe(x)) { *u = 0; return 12; } v = Z_lvalrem(x,p,&z); *u = umodiu(z,pk); return v; } static void val_init(GEN e, long p, long pk, long *v4, long *u, long *v6, long *v, long *vD, long *d1) { GEN c4 = ell_get_c4(e), c6 = ell_get_c6(e), D = ell_get_disc(e); pari_sp av = avma; *v4 = val_aux(c4, p,pk, u); *v6 = val_aux(c6, p,pk, v); *vD = val_aux(D , p,pk, d1); set_avma(av); } static long kod_23(GEN e, long p) { GEN S, nv; if ((S = obj_check(e, Q_GLOBALRED))) { GEN NP = gmael(S,3,1), L = gel(S,4); nv = absequaliu(gel(NP,1), p)? gel(L,1): gel(L,2); /* localred(p) */ } else nv = localred_23(e, p); return itos(gel(nv,2)); } /* v(c4), v(c6), v(D) for minimal model, +oo is coded by 12 */ static long neron_2(long v4, long v6, long vD, long kod) { if (kod > 4) return 1; switch(kod) { case 1: return (v6>0) ? 2 : 1; case 2: if (vD==4) return 1; else { if (vD==7) return 3; else return v4==4 ? 2 : 4; } case 3: switch(vD) { case 6: return 3; case 8: return 4; case 9: return 5; default: return v4==5 ? 2 : 1; } case 4: return v4>4 ? 2 : 1; case -1: switch(vD) { case 9: return 2; case 10: return 4; default: return v4>4 ? 3 : 1; } case -2: switch(vD) { case 12: return 2; case 14: return 3; default: return 1; } case -3: switch(vD) { case 12: return 2; case 14: return 3; case 15: return 4; default: return 1; } case -4: return v6==7 ? 2 : 1; case -5: return (v6==7 || v4==6) ? 2 : 1; case -6: switch(vD) { case 12: return 2; case 13: return 3; default: return v4==6 ? 2 : 1; } case -7: return (vD==12 || v4==6) ? 2 : 1; default: return v4==6 ? 2 : 1; } } /* p = 3; v(c4), v(c6), v(D) for minimal model, +oo is coded by 12 */ static long neron_3(long v4, long v6, long vD, long kod) { if (labs(kod) > 4) return 1; switch(kod) { case -1: case 1: return odd(v4)? 2: 1; case -3: case 3: return (2*v6>vD+3)? 2: 1; case -4: case 2: switch (vD%6) { case 4: return 3; case 5: return 4; default: return v6%3==1 ? 2 : 1; } default: /* kod = -2 et 4 */ switch (vD%6) { case 0: return 2; case 1: return 3; default: return 1; } } } static long ellrootno_2(GEN e) { long n2, kod, u, v, x1, y1, D1, vD, v4, v6; long d = get_vp_u_small(e, 2, &v6, &vD); if (!vD) return 1; if (d) { /* not minimal */ ellmin_t M; min_set_2(&M, e, d); min_set_D(&M, e); e = min_to_ell(&M, e); } val_init(e, 2,64,&v4,&u, &v6,&v, &vD,&D1); kod = kod_23(e,2); n2 = neron_2(v4,v6,vD, kod); if (kod>=5) { long a2, a3; a2 = ZtoF2(ell_get_a2(e)); a3 = ZtoF2(ell_get_a3(e)); return odd(a2 + a3) ? 1 : -1; } if (kod<-9) return (n2==2) ? -kross(-1,v) : -1; x1 = u+v+v; switch(kod) { case 1: return 1; case 2: switch(n2) { case 1: switch(v4) { case 4: return kross(-1,u); case 5: return 1; default: return -1; } case 2: return (v6==7) ? 1 : -1; case 3: return (v%8==5 || (u*v)%8==5) ? 1 : -1; case 4: if (v4>5) return kross(-1,v); return (v4==5) ? -kross(-1,u) : -1; } case 3: switch(n2) { case 1: return -kross(2,u*v); case 2: return -kross(2,v); case 3: y1 = (u - (v << (v6-5))) & 15; return (y1==7 || y1==11) ? 1 : -1; case 4: return (v%8==3 || (2*u+v)%8==7) ? 1 : -1; case 5: return v6==8 ? kross(2,x1) : kross(-2,u); } case -1: switch(n2) { case 1: return -kross(2,x1); case 2: return (v%8==7) || (x1%32==11) ? 1 : -1; case 3: return v4==6 ? 1 : -1; case 4: if (v4>6) return kross(-1,v); return v4==6 ? -kross(-1,u*v) : -1; } case -2: return n2==1 ? kross(-2,v) : kross(-1,v); case -3: switch(n2) { case 1: y1=(u-2*v)%64; if (y1<0) y1+=64; return (y1==3) || (y1==19) ? 1 : -1; case 2: return kross(2*kross(-1,u),v); case 3: return -kross(-1,u)*kross(-2*kross(-1,u),u*v); case 4: return v6==11 ? kross(-2,x1) : -kross(-2,u); } case -5: if (n2==1) return x1%32==23 ? 1 : -1; else return -kross(2,2*u+v); case -6: switch(n2) { case 1: return 1; case 2: return v6==10 ? 1 : -1; case 3: return (u%16==11) || ((u+4*v)%16==3) ? 1 : -1; } case -7: if (n2==1) return 1; else { y1 = (u + (v << (v6-8))) & 15; if (v6==10) return (y1==9 || y1==13) ? 1 : -1; else return (y1==9 || y1==5) ? 1 : -1; } case -8: return n2==2 ? kross(-1,v*D1) : -1; case -9: return n2==2 ? -kross(-1,D1) : -1; default: return -1; } } static long ellrootno_3(GEN e) { long n2, kod, u, v, D1, r6, K4, K6, vD, v4, v6; long d = get_vp_u_small(e, 3, &v6, &vD); if (!vD) return 1; if (d) { /* not minimal */ ellmin_t M; min_set_3(&M, e, d); min_set_a(&M); min_set_D(&M, e); e = min_to_ell(&M, e); } val_init(e, 3,81, &v4,&u, &v6,&v, &vD,&D1); kod = kod_23(e,3); K6 = kross(v,3); if (kod>4) return K6; n2 = neron_3(v4,v6,vD,kod); r6 = v%9; K4 = kross(u,3); switch(kod) { case 1: case 3: case -3: return 1; case 2: switch(n2) { case 1: return (r6==4 || r6>6) ? 1 : -1; case 2: return -K4*K6; case 3: return 1; case 4: return -K6; } case 4: switch(n2) { case 1: return K6*kross(D1,3); case 2: return -K4; case 3: return -K6; } case -2: return n2==2 ? 1 : K6; case -4: switch(n2) { case 1: if (v4==4) return (r6==4 || r6==8) ? 1 : -1; else return (r6==1 || r6==2) ? 1 : -1; case 2: return -K6; case 3: return (r6==2 || r6==7) ? 1 : -1; case 4: return K6; } default: return -1; } } /* p > 3. Don't assume that e is minimal or even integral at p */ static long ellrootno_p(GEN e, GEN p) { long nuj, nuD, nu; GEN D = ell_get_disc(e); long ep, z; nuD = Q_pval(D, p); if (!nuD) return 1; nuj = j_pval(e, p); nu = (nuD - nuj) % 12; if (nu == 0) { GEN c6; long d, vg; if (!nuj) return 1; /* good reduction */ /* p || N */ c6 = ell_get_c6(e); /* != 0 */ vg = minss(2*Q_pval(c6, p), nuD); d = vg / 12; if (d) { GEN q = powiu(p,6*d); c6 = (typ(c6) == t_INT)? diviiexact(c6, q): gdiv(c6, q); } if (typ(c6) != t_INT) c6 = Rg_to_Fp(c6,p); /* c6 in minimal model */ return -kronecker(negi(c6), p); } if (nuj) return krosi(-1,p); ep = 12 / ugcd(12, nu); if (ep==4) z = 2; else z = odd(ep)? 3: 1; return krosi(-z, p); } static GEN doellrootno(GEN e) { GEN V, P, S = ellglobalred_i(e); long i, l, s = -1; V = obj_check(e, Q_MINIMALMODEL); if (lg(V) != 2) e = gel(V,3); P = gmael(S,3,1); l = lg(P); V = cgetg(l, t_VECSMALL); for (i = 1; i < l; i++) { GEN p = gel(P,i); long t; switch(itou_or_0(p)) { case 2: t = ellrootno_2(e); break; case 3: t = ellrootno_3(e); break; default:t = ellrootno_p(e, p); } V[i] = t; if (t < 0) s = -s; } return mkvec2(stoi(s), V); } /* local epsilon factor at p (over Q), including p=0 for the infinite place. * Global if p==1 or NULL. */ static long ellQ_rootno(GEN e, GEN p) { pari_sp av = avma; GEN S; long s; if (!p || isint1(p)) return ellrootno_global(e); if (!signe(p)) return -1; /* local factor at infinity */ if ( (S = obj_check(e, Q_ROOTNO)) ) { GEN T = obj_check(e, Q_GLOBALRED), NP = gmael(T,3,1); long i = ZV_search(NP, p); if (i) { GEN V = gel(S,2); return V[i]; } return 1; } switch(itou_or_0(p)) { case 2: e = ellintegralmodel_i(e, NULL); s = ellrootno_2(e); break; case 3: e = ellintegralmodel_i(e, NULL); s = ellrootno_3(e); break; default: s = ellrootno_p(e,p); break; } return gc_long(av, s); } /* global root number over number field * Root numbers and parity of ranks of elliptic curves, Tim and Vladimir Dokchitser * https://arxiv.org/abs/0906.1815 */ static GEN ellrnfup(GEN rnf, GEN E, long prec) { long i; GEN Eb = cgetg(6, t_VEC); for(i=1; i<=5; i++) gel(Eb, i) = rnfeltup(rnf,gel(E, i)); return ellinit_nf(Eb, rnf_build_nfabs(rnf, prec)); } static GEN ellnf2isog(GEN E, GEN z) { long v = fetch_var_higher(); GEN S = deg1pol(gen_1, gneg(z), v); GEN E2 = ellisogeny(E, S, 1, -1, -1); delete_var(); return ellinit_nf(E2, ellnf_get_nf(E)); } static GEN ellnf_reladelicvolume(GEN E, GEN P, GEN C, GEN z, long prec) { pari_sp av = avma; GEN nf = ellnf_get_nf(E); GEN rnf = rnfinit0(nf, mkvec2(P, C), 1); GEN Et = ellrnfup(rnf, E, prec); GEN E2 = ellnf2isog(Et, rnfeltreltoabs(rnf, z)); GEN c1 = ellnf_adelicvolume(Et, prec), c2 = ellnf_adelicvolume(E2, prec); obj_free(rnf); obj_free(Et); obj_free(E2); return gerepilecopy(av, mkvec2(c1,c2)); } static long rootnovalp(GEN z, ulong p, long prec) { return mpodd(ground(gdiv(glog(z, prec), glog(utoi(p),prec)))); } static long ellnf_rootno_global(GEN E) { pari_sp av = avma; GEN nf = ellnf_get_nf(E); long prec = nf_get_prec(nf); long v, var = fetch_var_higher(); GEN F; E = ellintegralmodel_i(E, NULL); F = nfroots(nf, ec_bmodel(E, var)); if (lg(F)>1) { GEN Et = ellnf2isog(E, gel(F,1)); GEN cK = ellnf_adelicvolume(E, prec), cKt = ellnf_adelicvolume(Et, prec); obj_free(Et); v = rootnovalp(divrr(cK,cKt), 2, prec); } else { GEN C = ellnf_D_primes(E); GEN D = deg2pol_shallow(gen_1, gen_0, gneg(ell_get_disc(E)), var); GEN P = RgX_divs(RgX_rescale(ec_bmodel(E, var), utoi(4)), 4); GEN c = ellnf_reladelicvolume(E, P, C, gmul2n(pol_x(var),-2), prec); GEN cL = gel(c,1), cLt = gel(c,2); GEN F = nfroots(nf, D); if (lg(F)>1) v = rootnovalp(divrr(cL,cLt), 2, prec); else { GEN cK = ellnf_adelicvolume(E, prec); GEN cp = nfcompositum(nf, P, D, 3); GEN cc = ellnf_reladelicvolume(E, gel(cp,1), C, gmul2n(gel(cp,2),-2), prec); GEN cF = gel(cc,1), cFt = gel(cc,2); GEN rnf = rnfinit0(nf,mkvec2(D,C),1); GEN Et = ellrnfup(rnf, E, prec); GEN cKv = ellnf_adelicvolume(Et, prec); long v2 = rootnovalp(divrr(gmul(cL,cF),gmul(cLt,cFt)), 2, prec); long v3 = rootnovalp(divrr(gmul(cF,gsqr(cK)),gmul(cKv,gsqr(cL))), 3, prec); obj_free(rnf); obj_free(Et); v = odd(v2+v3); } } delete_var(); return gc_long(av, v? -1: 1); } static GEN doellnfrootno(GEN e) { return stoi(ellnf_rootno_global(e)); } long ellrootno_global(GEN e) { pari_sp av = avma; GEN S; switch(ell_get_type(e)) { case t_ELL_Q: S = gel(obj_checkbuild(e, Q_ROOTNO, &doellrootno),1); break; case t_ELL_NF: S = obj_checkbuild(e, NF_ROOTNO, &doellnfrootno); break; default: pari_err_TYPE("ellrootno", e); return 0; /*LCOV_EXCL_LINE*/ } return gc_long(av, itos(S)); } long ellrootno(GEN e, GEN p) { checkell(e); if (p && typ(p) != t_INT) pari_err_TYPE("ellrootno", p); if (p && signe(p) < 0) pari_err_PRIME("ellrootno",p); switch(ell_get_type(e)) { case t_ELL_Q: return ellQ_rootno(e, p); default: pari_err_TYPE("ellrootno", e); case t_ELL_NF: if (p) pari_err_IMPL("local root number for number fields"); return ellrootno_global(e); } } /********************************************************************/ /** **/ /** TRACE OF FROBENIUS **/ /** **/ /********************************************************************/ /* assume p does not divide disc E */ long ellap_CM_fast(GEN E, ulong p, long CM) { ulong a4, a6; if (p == 2) return 3 - cardmod2(E); if (p == 3) return 4 - cardmod3(E); Fl_ell_to_a4a6(E, p, &a4, &a6); return Fl_elltrace_CM(CM, a4, a6, p); } static void checkell_int(GEN e) { checkell_Q(e); if (typ(ell_get_a1(e)) != t_INT || typ(ell_get_a2(e)) != t_INT || typ(ell_get_a3(e)) != t_INT || typ(ell_get_a4(e)) != t_INT || typ(ell_get_a6(e)) != t_INT) pari_err_TYPE("ellanQ [not an integral model]",e); } long ellQ_get_CM(GEN e) { GEN j = ell_get_j(e); if (typ(j) != t_INT) return 0; if (is_bigint(j)) { #ifndef LONG_IS_64BIT if (signe(j) < 0) { pari_sp av = avma; if (absequalii(j, uu32toi(0x22UL,0x45ae8000UL))) return gc_long(av,-67); if (absequalii(j, uu32toi(0x03a4b862,0xc4b40000UL))) return gc_long(av,-163); } #endif return 0; } switch(signe(j)) { default: return -3; /* j = 0 */ case 1: switch(j[2]) { case 1728: return -4; case 8000: return -8; case 54000: return -12; case 287496: return -16; case 16581375: return -28; default: return 0; } case -1: switch(j[2]) { case 3375: return -7; case 32768: return -11; case 884736: return -19; case 12288000: return -27; case 884736000: return -43; #ifdef LONG_IS_64BIT case 147197952000L: return -67; case 262537412640768000L: return -163; #endif default: return 0; } } } static long ellnf_get_CM(GEN E) { long av = avma; GEN j = ell_get_j(E), nf = ellnf_get_nf(E); GEN P = minpoly(basistoalg(nf, j), 0); return gc_long(av, polisclass(P)); } long elliscm(GEN E) { checkell(E); switch(ell_get_type(E)) { case t_ELL_Q: return ellQ_get_CM(E); case t_ELL_NF: return ellnf_get_CM(E); default: pari_err_TYPE("elliscm", E); return 0; /*LCOV_EXCL_LINE*/ } } /* E/Q or Qp, return cardinality including the (possible) ramified point */ static GEN ellcard_ram(GEN E, GEN p, int *good_red) { GEN a4, a6, D = Rg_to_Fp(ell_get_disc(E), p); if (!signe(D)) { pari_sp av = avma; GEN ap = ellQap(E, p, good_red); return gerepileuptoint(av, subii(addiu(p,1), ap)); } *good_red = 1; if (absequaliu(p,2)) return utoi(cardmod2(E)); if (absequaliu(p,3)) return utoi(cardmod3(E)); ell_to_a4a6(E,p,&a4,&a6); return Fp_ellcard(a4, a6, p); } /* bad reduction at p */ static void sievep_bad(ulong p, GEN an, ulong n) { ulong m, N; switch (an[p]) /* (-c6/p) */ { case -1: /* nonsplit */ N = n/p; for (m=2; m<=N; m++) if (an[m] != LONG_MAX) an[m*p] = -an[m]; break; case 0: /* additive */ for (m=2*p; m<=n; m+=p) an[m] = 0; break; case 1: /* split */ N = n/p; for (m=2; m<=N; m++) if (an[m] != LONG_MAX) an[m*p] = an[m]; break; } } /* good reduction at p */ static void sievep_good(ulong p, GEN an, ulong n, ulong SQRTn) { const long ap = an[p]; ulong m; if (p <= SQRTn) { ulong pk, oldpk = 1; for (pk=p; pk <= n; oldpk=pk, pk *= p) { if (pk != p) an[pk] = ap * an[oldpk] - p * an[oldpk/p]; for (m = n/pk; m > 1; m--) if (an[m] != LONG_MAX && m%p) an[m*pk] = an[m] * an[pk]; } } else { for (m = n/p; m > 1; m--) if (an[m] != LONG_MAX) an[m*p] = ap * an[m]; } } static void sievep(ulong p, GEN an, ulong n, ulong SQRTn, int good_red) { if (good_red) sievep_good(p, an, n, SQRTn); else sievep_bad(p, an, n); } static long ellan_get_ap(ulong p, int *good_red, int CM, GEN e) { if (!umodiu(ell_get_disc(e),p)) /* p|D, bad reduction or nonminimal model */ return ellQap_u(e, p, good_red); else /* good reduction */ { *good_red = 1; return ellap_CM_fast(e, p, CM); } } GEN ellanQ_zv(GEN e, long n0) { pari_sp av; ulong p, SQRTn, n = (ulong)n0; GEN an; int CM; if (n0 <= 0) return cgetg(1,t_VEC); if (n >= LGBITS) pari_err_IMPL( stack_sprintf("ellan for n >= %lu", LGBITS) ); e = ellintegralmodel_i(e,NULL); SQRTn = usqrt(n); CM = ellQ_get_CM(e); an = const_vecsmall(n, LONG_MAX); an[1] = 1; av = avma; for (p=2; p<=n; p++) { int good_red; if (an[p] != LONG_MAX) continue; /* p not prime */ an[p] = ellan_get_ap(p, &good_red, CM, e); sievep(p, an, n, SQRTn, good_red); } set_avma(av); return an; } static GEN ellQ_eulerf(GEN e, GEN p) { int good_red; GEN card = ellcard_ram(e, p, &good_red); GEN ap = subii(addiu(p, 1), card); if (good_red) return mkrfrac(gen_1,deg2pol_shallow(p, gneg(ap), gen_1, 0)); if (!signe(ap)) return pol_1(0); return mkrfrac(gen_1,deg1pol_shallow(negi(ap), gen_1,0)); } static GEN ellanQ(GEN e, long N) { return vecsmall_to_vec_inplace(ellanQ_zv(e,N)); } static GEN ellnflocal(GEN E, GEN p, long n) { pari_sp av = avma; GEN nf = ellnf_get_nf(E); GEN LP = idealprimedec_limit_f(nf, p, n ? n-1: nf_get_degree(nf)), T = NULL; long l = lg(LP), i; for (i = 1; i < l; i++) { int goodred; GEN P = gel(LP,i), T2; GEN ap = ellnfap(E, P, &goodred); long f = pr_get_f(P); if (goodred) T2 = mkpoln(3, pr_norm(P), negi(ap), gen_1); else { if (!signe(ap)) continue; T2 = deg1pol_shallow(negi(ap), gen_1, 0); } if (f > 1) T2 = RgX_inflate(T2, f); T = T? ZX_mul(T, T2): T2; } if (!T) { set_avma(av); return pol_1(0); } if (n==0) return gerepilecopy(av, mkrfrac(gen_1,T)); return gerepileupto(av, RgXn_inv_i(T, n)); } GEN direllnf_worker(GEN P, ulong X, GEN E) { pari_sp av = avma; long i, l = lg(P); GEN W = cgetg(l, t_VEC); for(i = 1; i < l; i++) { ulong p = uel(P,i); long d = ulogint(X, p) + 1; /* minimal d such that p^d > X */ gel(W,i) = ellnflocal(E, utoi(uel(P,i)), d); } return gerepilecopy(av, mkvec2(P,W)); } static GEN ellnfan(GEN E, long N) { GEN worker = snm_closure(is_entry("_direllnf_worker"), mkvec(E)); return pardireuler(worker, gen_2, stoi(N), NULL, NULL); } GEN elleulerf(GEN E, GEN p) { checkell(E); switch(ell_get_type(E)) { case t_ELL_Q: return ellQ_eulerf(E, p); case t_ELL_NF: return ellnflocal(E, p, 0); default: pari_err_TYPE("elleulerf",E); return NULL; /*LCOV_EXCL_LINE*/ } } GEN ellan(GEN E, long N) { checkell(E); switch(ell_get_type(E)) { case t_ELL_Q: return ellanQ(E, N); case t_ELL_NF: return ellnfan(E, N); default: pari_err_TYPE("ellan",E); return NULL; /*LCOV_EXCL_LINE*/ } } static GEN apk_good(GEN ap, GEN p, long e) { GEN u, v, w; long j; if (e == 1) return ap; u = ap; w = subii(sqri(ap), p); for (j=3; j<=e; j++) { v = u; u = w; w = subii(mulii(ap,u), mulii(p,v)); } return w; } GEN akell(GEN e, GEN n) { long i, j, s; pari_sp av = avma; GEN fa, P, E, D, u, y; checkell_int(e); if (typ(n) != t_INT) pari_err_TYPE("akell",n); if (signe(n)<= 0) return gen_0; if (gequal1(n)) return gen_1; D = ell_get_disc(e); u = Z_ppo(n, D); y = gen_1; s = 1; if (!equalii(u, n)) { /* bad reduction at primes dividing n/u */ fa = Z_factor(diviiexact(n, u)); P = gel(fa,1); E = gel(fa,2); for (i=1; i */ static GEN ellheightfaltings(GEN e, long prec) { GEN h; long d; pari_sp av = avma; checkell(e); switch(ell_get_type(e)) { case t_ELL_Q: d = 1; e = ellintegralmodel_i(e,NULL); h = gmul(gsqr(ellQ_minimalu(e,NULL)), ellR_area(e, prec)); break; case t_ELL_NF: d = nf_get_degree(ellnf_get_nf(e)); h = gmul(gsqr(ellnf_minimalnormu(e)), ellnf_volume(e, prec)); break; default: pari_err_TYPE("ellheight", e); return NULL; /*LCOV_EXCL_LINE*/ } return gerepileupto(av, gdivgs(logr_abs(h), -2*d)); } static GEN Q_numer(GEN x) { return typ(x) == t_INT? x: gel(x,1); } /* one root of X^2 - t X + c */ static GEN quad_root(GEN t, GEN c, long prec) { return gmul2n(gadd(t, gsqrt(gsub(gsqr(t), gmul2n(c,2)),prec)), -1); } /* 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, int flag, long prec) { GEN x_a, ab, a, b, e1, r, V = cgetg(1, t_VEC), x = gel(z,1); long n, ex = 5-prec, p = prec+EXTRAPREC64; if (typ(x) == t_REAL && realprec(x) < p) x = gprec_w(x, p); ab = ellR_ab(e, p); a = gel(ab, 1); b = gel(ab, 2); e1= gel(obj_check(e,R_ROOTS), 1); /* use maximal accuracy, don't truncate */ x = gsub(x, e1); x = quad_root(gadd(x,b), gmul(a,x), prec); 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_shallow(x_a))); } /* is P \in E(R)^0, the neutral component ? */ static int ellR_on_neutral(GEN E, GEN P, long prec) { GEN x = gel(P,1), e1 = ellR_root(E, prec); return gcmp(x, e1) >= 0; } /* hoo + 1/2 log(den(x)) */ static GEN hoo_aux(GEN E, GEN z, GEN d, long prec) { pari_sp av = avma; GEN h; if (!ellR_on_neutral(E, z, prec)) { GEN eh = exphellagm(E, elladd(E, z,z), 0, prec); /* h_oo(2P) = 4h_oo(P) - log |2y + a1x + a3| */ h = gmul(eh, gabs(ec_dmFdy_evalQ(E, z), prec)); } else h = exphellagm(E, z, 1, prec); if (!is_pm1(d)) h = gmul(h, sqri(d)); return gerepileuptoleaf(av, gmul2n(mplog(h), -2)); } GEN ellheightoo(GEN E, GEN z, long prec) { return hoo_aux(E, z, gen_1, prec); } /* Formula from Silverman GTM 151 Theorem 3.2 page 466 */ static GEN ellheight_C(GEN E, GEN P, long prec) { pari_sp av = avma; GEN z = zell(E, P, prec); GEN per = ellperiods(E, 1, prec); GEN w = gel(per,1), w1 = gel(w,1), w2 = gel(w, 2), w1c = conj_i(w1); GEN e = gel(per,2), e1 = gel(e,1), e2 = gel(e, 2); GEN D = gsub(gmul(w1, conj_i(w2)),gmul(w1c, w2)); GEN b = gdiv(gsub(gmul(w1, conj_i(z)),gmul(w1c, z)), D); GEN a = gdiv(gsub(z, gmul(b, w2)), w1); GEN eta = gadd(gmul(a, e1), gmul(b, e2)); GEN r = gmul2n(real_i(gmul(z, eta)), -1); GEN l = real_i(ellsigma(per, z, 1, prec)); return gerepileupto(av, gsub(r, l)); } static GEN _hell(GEN E, GEN p, long n, GEN P) { return p? ellpadicheight(E,p,n, P): ellheight(E,P,n); } static GEN ellheightpairing(GEN E, GEN p, long n, GEN P, GEN Q) { pari_sp av = avma; GEN a = _hell(E,p,n, elladd(E,P,Q)); GEN b = _hell(E,p,n, ellsub(E,P,Q)); return gerepileupto(av, gmul2n(gsub(a,b), -2)); } GEN ellheight0(GEN e, GEN a, GEN b, long n) { if (!a) { if (b) pari_err(e_MISC, "cannot omit P and set Q"); return ellheightfaltings(e,n); } return b? ellheightpairing(e,NULL,n, a,b): ellheight(e,a,n); } GEN ellpadicheight0(GEN e, GEN p, long n, GEN P, GEN Q) { return Q? ellheightpairing(e,p,n, P,Q): ellpadicheight(e,p,n, P); } /* Based on J.H. Silverman, Advanced Topics in the Arithmetic of Elliptic * Curves, GTM 151, chap VI, p 478, exercise 6.7 * Note that we use BSD normalization not Silverman's. */ /* P an affine point on e */ static GEN ellnf_localheight(GEN e, GEN P, GEN pr) { long v2, vD, vu, vP, vQ; GEN lr = nflocalred(e,pr), k = gel(lr, 2), urst = gel(lr, 3); GEN E = ellchangecurve(e, urst); GEN Q = ellchangepoint(P, urst), nf = ellnf_get_nf(e), v; vP = minss(0, nfval(nf, gel(P,1), pr)); /* v_p(den(x_P)) */ vQ = minss(0, nfval(nf, gel(Q,1), pr)); /* v_p(den(x_Q)) */ v2 = nfval(nf, ec_dmFdy_evalQ(E, Q), pr); vD = nfval(nf, ell_get_disc(E), pr); /* >= 0 */ vu = (vQ-vP) >> 1; if (v2 <= 0 || nfval(nf, ec_dFdx_evalQ(E, Q), pr) <= 0) v = gen_0; else if (cmpis(k,5) >= 0) { GEN a = uutoQ(minss(2*v2,vD), 2*vD); v = gmul(gsub(gsqr(a),a), uutoQ(vD,2)); } else { long v3 = nfval(nf, ec_3divpol_evalx(E, gel(Q,1)), pr); v = (v2 < LONG_MAX && v3 >= 3*v2)? sstoQ(-v2,3): sstoQ(-v3,8); } return gsubgs(v,vu); } /* L list of prime ideals, merge with prime ideals dividing integral ideal A * in HNF (use elements of L as hints, which may or may not divide A). * Return sorted list, without duplicates */ static GEN prV_merge_factors(GEN nf, GEN L, GEN A) { if (lg(L) > 1) { GEN LQ = prV_primes(L); /* rational primes */ GEN p, e, N = Z_smoothen(gcoeff(A,1,1), LQ, &p, &e); L = shallowconcat(L, gel(idealfactor_partial(nf, A, LQ), 1)); /* L = primes in original L or dividing (A, vecprod(LQ)) */ A = N? ZM_hnfmodid(A, N): NULL; } /* A made coprime to vecprod(LQ), add remaining primes if not trivial */ if (A) L = shallowconcat(L, gel(idealfactor(nf, A), 1)); return gen_sort_uniq(L, (void*)cmp_prime_ideal, &cmp_nodata); } static GEN ellnf_height(GEN E, GEN P, long prec) { pari_sp av = avma; GEN logp, oldp, x, nf, d, F, Ee, Pe, s, v, phi2, psi2; long i, l, r1; E = ellintegralmodel_i(E, &v); if (v) P = ellchangepoint(P, v); if (!oncurve(E,P)) pari_err_DOMAIN("ellheight", "point", "not on", strtoGENstr("E"), P); if (signe(ellorder(E, P, NULL))) return gc_const(av, gen_0); x = gel(P,1); if (gequal0(ec_2divpol_evalx(E, x))) return gc_const(av, gen_0); nf = ellnf_get_nf(E); phi2 = gel(idealnumden(nf, ec_dFdx_evalQ(E, P)), 1); psi2 = gel(idealnumden(nf, ec_dmFdy_evalQ(E, P)),1); d = idealnorm(nf, gel(idealnumden(nf, x), 2)); F = gel(ellminimalprimes(E), 1); /* prime ideals dividing (c4,c6) */ F = prV_merge_factors(nf, F, idealadd(nf, phi2, psi2)); Ee = ellnfembed(E, prec); Pe = ellpointnfembed(E, P, prec); l = lg(Ee); r1 = nf_get_r1(nf); s = gsub(gmul2n(glog(d, prec), -1), glog(ellnf_minimalnormu(E), prec)); for (i=1; i <= r1; i++) s = gadd(s, ellheightoo(gel(Ee, i), gel(Pe, i), prec)); for ( ; i < l; i++) s = gadd(s, gmul2n(ellheight_C(gel(Ee, i), gel(Pe, i), prec), 1)); l = lg(F); oldp = logp = NULL; for (i = 1; i < l; i++) { /* F = primes dividing (c4,c6) or (phi2,psi2) */ GEN pr = gel(F,i), p = pr_get_p(pr), lam = ellnf_localheight(E, P, pr); if (!oldp || !equalii(p, oldp)) { oldp = p; logp = glog(p, prec); } s = gadd(s, gmul(lam, mulru(logp, pr_get_f(pr)))); } return gerepileupto(av, gmul2n(s, 1)); } static GEN ellQ_height(GEN e, GEN a, long prec) { long i, lx, newell = 0; pari_sp av; GEN Lp, x, z, phi2, psi2, psi3; GEN v, S, c4, D; if (!RgV_is_QV(a)) pari_err_TYPE("ellheight [not a rational point]",a); if (!oncurve(e,a)) pari_err_DOMAIN("ellheight", "point", "not on", strtoGENstr("E"),a); if (ellorder_Q(e, a)) return gen_0; av = avma; if ((S = obj_check(e, Q_MINIMALMODEL))) { /* switch to minimal model if needed */ if (lg(S) != 2) { v = gel(S,2); e = gel(S,3); a = ellchangepoint(a, v); } } else { newell = 1; e = ellminimalmodel_i(e, &v, NULL); a = ellchangepoint(a, v); } psi2 = Q_numer(ec_dmFdy_evalQ(e,a)); if (!signe(psi2)) { set_avma(av); return gen_0; } x = gel(a,1); psi3 = Q_numer( ec_3divpol_evalx(e, x) ); if (!signe(psi3)) { set_avma(av); return gen_0; } phi2 = Q_numer(ec_dFdx_evalQ(e, a)); c4 = ell_get_c4(e); D = ell_get_disc(e); z = hoo_aux(e,a,Q_denom(x),prec); /* hoo(a) + log(den(x))/2 */ Lp = gel(Z_factor(gcdii(psi2,phi2)),1); lx = lg(Lp); for (i=1; i 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)); } if (newell) obj_free(e); return gerepileupto(av, gmul2n(z, 1)); } GEN ellheight(GEN e, GEN a, long prec) { checkell(e); if (!checkellpt_i(a)) pari_err_TYPE("ellheight", a); switch(ell_get_type(e)) { case t_ELL_Q: return ellQ_height(e, a, prec); default: pari_err_TYPE("ellheight", e); case t_ELL_NF: return ellnf_height(e, a, prec); } } GEN ellpadicheightmatrix(GEN e, GEN p, long n, GEN x) { GEN D, A, B; long lx = lg(x), i, j; pari_sp av = avma; if (!is_vec_t(typ(x))) pari_err_TYPE("ellheightmatrix",x); D = cgetg(lx,t_VEC); A = cgetg(lx,t_MAT); B = cgetg(lx,t_MAT); for (i=1; i minq, then the list of potential orders in ellsea will not contain * an ambiguity => oo-loop. E.g. ellsea(ellinit([1,519],523)) */ GEN ellsea(GEN E, long smallfact) { const ulong minq = 523; checkell_Fq(E); switch(ell_get_type(E)) { case t_ELL_Fp: { GEN p = ellff_get_field(E), e = ellff_get_a4a6(E); if (abscmpiu(p, minq) <= 0) return Fp_ellcard(gel(e,1), gel(e,2), p); return Fp_ellcard_SEA(gel(e,1), gel(e,2), p, smallfact); } case t_ELL_Fq: { GEN fg = ellff_get_field(E); if (abscmpiu(FF_p_i(fg), 7) <= 0 || abscmpiu(FF_q(fg), minq) <= 0) return FF_ellcard(E); return FF_ellcard_SEA(E, smallfact); } } return NULL; /*LCOV_EXCL_LINE*/ } GEN ellff_get_card(GEN E) { return obj_checkbuild(E, FF_CARD, &doellcard); } GEN ellcard(GEN E, GEN p) { p = checkellp(&E, p, NULL, "ellcard"); switch(ell_get_type(E)) { case t_ELL_Fp: case t_ELL_Fq: return icopy(ellff_get_card(E)); case t_ELL_Qp: case t_ELL_Q: { pari_sp av = avma; int goodred; GEN N = ellcard_ram(E, p, &goodred); if (!goodred) N = subiu(N, 1); /* remove singular point */ return gerepileuptoint(av, N); } case t_ELL_NF: { pari_sp av = avma; int goodred; GEN N = subii(pr_norm(p), ellnfap(E, p, &goodred)); if (goodred) N = addiu(N, 1); return gerepileuptoint(av, N); } default: pari_err_TYPE("ellcard",E); return NULL; /*LCOV_EXCL_LINE*/ } } /* assume model is p-minimal */ static GEN ellgroup_m(GEN E, GEN p, GEN *pm) { GEN a4, a6, N = ellcard(E, p); /* #E^ns(Fp) */ *pm = gen_1; if (equali1(N)) return cgetg(1,t_VEC); if (absequaliu(p, 2)) return mkvec(N); if (absequaliu(p, 3)) { /* The only possible noncyclic group is [2,2] which happens 9 times */ ulong b2, b4, b6; if (!absequaliu(N, 4)) return mkvec(N); /* 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) return mkvec(N); /* 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) return mkvec(N); return mkvec2s(2, 2); } /* Now assume p > 3 */ ell_to_a4a6(E, p, &a4,&a6); return Fp_ellgroup(a4,a6,N,p, pm); } static GEN doellGm(GEN E) { GEN fg = ellff_get_field(E); GEN m, G = (typ(fg) == t_FFELT)? FF_ellgroup(E, &m): ellgroup_m(E, fg, &m); return mkvec2(G, m); } static GEN ellff_Gm(GEN E) { return obj_checkbuild(E, FF_GROUP, &doellGm); } GEN ellff_get_group(GEN E) { return gel(ellff_Gm(E), 1); } GEN ellff_get_m(GEN E) { return gel(ellff_Gm(E), 2); } GEN ellff_get_D(GEN E) { GEN G = ellff_get_group(E), o = ellff_get_o(E); switch(lg(G)) { case 1: return G; case 2: return mkvec(o); default: return mkvec2(o, gel(G,2)); } } /* E / Fp */ static GEN doellgens(GEN E) { GEN fg = ellff_get_field(E); if (typ(fg)==t_FFELT) return FF_ellgens(E); else { GEN F, p = fg, e = ellff_get_a4a6(E); F = Fp_ellgens(gel(e,1),gel(e,2),gel(e,3), ellff_get_D(E),ellff_get_m(E),p); return FpVV_to_mod(F,p); } } GEN ellff_get_gens(GEN E) { return obj_checkbuild(E, FF_GROUPGEN, &doellgens); } GEN ellgroup(GEN E, GEN p) { pari_sp av = avma; GEN m, G; p = checkellp(&E,p, NULL, "ellgroup"); switch(ell_get_type(E)) { case t_ELL_Fp: case t_ELL_Fq: G = ellff_get_group(E); break; case t_ELL_Qp: case t_ELL_Q: if (Z_pval(Q_numer(ell_get_disc(E)), p)) { GEN Q = localred(E,p), kod = gel(Q,2); E = ellchangecurve(E, gel(Q,3)); if (!equali1(kod)) { G = mkvec(ellcard(E,p)); break; } } G = ellgroup_m(E,p,&m); break; case t_ELL_NF: if (nfval(ellnf_get_nf(E), ell_get_disc(E), p)) { GEN Q = nflocalred(E,p), kod = gel(Q,2); E = ellchangecurve(E, gel(Q,3)); if (!equali1(kod)) { G = mkvec(ellcard(E,p)); break; } } E = ellinit(E, p, 0); G = ellff_get_group(E); G = gcopy(G); obj_free(E); break; default: pari_err_TYPE("ellgroup", E); return NULL;/*LCOV_EXCL_LINE*/ } return gerepilecopy(av, G); } GEN ellgroup0(GEN E, GEN p, long flag) { pari_sp av = avma; long tE, freeE = 0; GEN G; if (flag==0) return ellgroup(E, p); if (flag!=1) pari_err_FLAG("ellgroup"); checkell(E); tE = ell_get_type(E); if (tE != t_ELL_Fp && tE != t_ELL_Fq) { GEN Q = elllocalred(E, p), v = gel(Q,3), u = gel(v,1), kod = gel(Q,2); long vu; switch(tE) { case t_ELL_Qp: p = ellQp_get_p(E);/*fall through*/ case t_ELL_Q: vu = Q_pval(u, p); break; case t_ELL_NF: vu = nfval(ellnf_get_nf(E), u, p); break; default: pari_err_TYPE("ellgroup", E); vu = 0; } if (vu) pari_err_TYPE("ellgroup [not a p-minimal curve]",E); if (!equali1(kod)) /* bad reduction */ { GEN Ep, T = NULL, q = p, ap = ellap(E,p); if (typ(p) == t_INT) { long i; Ep = obj_init(15, 4); for (i = 1; i <= 12; i++) gel(Ep,i) = gel(E,i); } else { q = pr_norm(p); Ep = initsmall5(ellnf_to_Fq(ellnf_get_nf(E), E, p, &p, &T), 4); } E = FF_ellinit(Ep, Tp_to_FF(T, p)); /* singular curve */ gel(E,14) = mkvecsmall(t_ELL_Fq); obj_insert(E, FF_CARD, subii(q, ap)); } else E = ellinit(E, p, 0); freeE = 1; } G = mkvec3(ellff_get_card(E), ellff_get_group(E), ellff_get_gens(E)); if (!freeE) return gerepilecopy(av, G); G = gcopy(G); obj_free(E); return gerepileupto(av, G); } GEN ellgenerators(GEN E) { checkell(E); switch(ell_get_type(E)) { case t_ELL_Q: return obj_checkbuild(E, Q_GROUPGEN, &elldatagenerators); case t_ELL_Fp: case t_ELL_Fq: return gcopy(ellff_get_gens(E)); default: pari_err_TYPE("ellgenerators",E); return NULL;/*LCOV_EXCL_LINE*/ } } /* char != 2,3, j != 0, 1728 */ static GEN ellfromj_simple(GEN j) { pari_sp av = avma; GEN k = gsubsg(1728,j), kj = gmul(k, j), k2j = gmul(kj, k); GEN E = zerovec(5); gel(E,4) = gmulsg(3,kj); gel(E,5) = gmulsg(2,k2j); return gerepileupto(av, E); } GEN ellfromj(GEN j) { GEN T = NULL, p = typ(j)==t_FFELT? FF_p_i(j): NULL; /* trick: use j^0 to get 1 in the proper base field */ if ((p || (Rg_is_FpXQ(j,&T,&p) && p)) && lgefint(p) == 3) switch(p[2]) { case 2: if (gequal0(j)) retmkvec5(gen_0,gen_0, gpowgs(j,0), gen_0,gen_0); else retmkvec5(gpowgs(j,0),gen_0,gen_0, gen_0,ginv(j)); case 3: if (gequal0(j)) retmkvec5(gen_0,gen_0,gen_0, gpowgs(j,0), gen_0); else { GEN E = zerovec(5); pari_sp av = avma; gel(E,5) = gerepileupto(av, gneg(gsqr(j))); gel(E,2) = gcopy(j); return E; } } if (gequal0(j)) retmkvec5(gen_0,gen_0,gen_0,gen_0, gpowgs(j,0)); if (gequalgs(j,1728)) retmkvec5(gen_0,gen_0,gen_0, gpowgs(j,0), gen_0); return ellfromj_simple(j); } /********************************************************************/ /** **/ /** IS SUPERSINGULAR **/ /** **/ /********************************************************************/ int elljissupersingular(GEN x) { pari_sp av = avma; int res; if (typ(x) == t_INTMOD) { GEN p = gel(x, 1); GEN j = gel(x, 2); res = Fp_elljissupersingular(j, p); } else if (typ(x) == t_FFELT) { GEN j = FF_to_FpXQ_i(x); GEN p = FF_p_i(x); GEN T = FF_mod(x); res = FpXQ_elljissupersingular(j, T, p); } else { pari_err_TYPE("elljissupersingular", x); return 0; /*LCOV_EXCL_LINE*/ } set_avma(av); return res; } int ellissupersingular(GEN E, GEN p) { pari_sp av; GEN j; if (typ(E)!=t_VEC && !p) return elljissupersingular(E); p = checkellp(&E, p, NULL, "ellissupersingular"); j = ell_get_j(E); switch(ell_get_type(E)) { case t_ELL_Fp: case t_ELL_Fq: return elljissupersingular(j); case t_ELL_Qp: case t_ELL_Q: if (typ(j)==t_FRAC && dvdii(gel(j,2), p)) return 0; av = avma; return gc_bool(av, Fp_elljissupersingular(Rg_to_Fp(j,p), p)); case t_ELL_NF: { GEN modP, T, nf = ellnf_get_nf(E), pr = p; int res; av = avma; j = nf_to_scalar_or_basis(nf, j); if (dvdii(Q_denom(j), pr_get_p(pr))) { if (typ(j) == t_FRAC || nfval(nf, j, pr) < 0) return 0; modP = nf_to_Fq_init(nf,&pr,&T,&p); } else modP = zk_to_Fq_init(nf,&pr,&T,&p); j = nf_to_Fq(nf, j, modP); if (typ(j) == t_INT) res = Fp_elljissupersingular(j, p); else res = FpXQ_elljissupersingular(j, T, p); return gc_bool(av, res); } default: pari_err_TYPE("ellissupersingular",E); } return 0; /*LCOV_EXCL_LINE*/ } GEN ellsupersingularj(GEN a) { pari_sp av = avma; GEN r, T, p; long d; switch(typ(a)) { case t_INT: p = a; if (Z_issquare(p)) pari_err_PRIME("ellsupersingularj", p); T = init_Fq(p, 2, fetch_user_var("w")); d = 2; break; case t_FFELT: p = FF_p_i(a); T = FF_mod(a); d = degpol(T); if (!odd(d)) { if (d != 2) T = init_Fq(p, 2, varn(T)); break; } default: /* FALL THROUGH */ pari_err_TYPE("ellsupersingular", a); return NULL; /* LCOV_EXCL_LINE */ } r = Fq_to_FF(ellsupersingularj_FpXQ(T, p), Tp_to_FF(T, p)); if (d != 2) r = ffmap(ffembed(r, a), r); return gerepilecopy(av, r); } /* n <= 4, N is the characteristic of the base ring or NULL (char 0) */ static GEN elldivpol4(GEN e, GEN N, long n, long v) { GEN b2,b4,b6,b8, res; if (n==0) return pol_0(v); if (n<=2) return N? scalarpol_shallow(mkintmod(gen_1,N),v): pol_1(v); b2 = ell_get_b2(e); b4 = ell_get_b4(e); b6 = ell_get_b6(e); b8 = ell_get_b8(e); if (n==3) res = mkpoln(5, N? modsi(3,N): utoi(3),b2,gmulsg(3,b4),gmulsg(3,b6),b8); else { GEN b10 = gsub(gmul(b2, b8), gmul(b4, b6)); GEN b12 = gsub(gmul(b8, b4), gsqr(b6)); res = mkpoln(7, N? modsi(2,N): gen_2,b2,gmulsg(5,b4),gmulsg(10,b6),gmulsg(10,b8),b10,b12); } setvarn(res, v); return res; } /* T = (2y + a1x + a3)^4 modulo the curve equation. Store elldivpol(e,n,v) * in t[n]. N is the caracteristic of the base ring or NULL (char 0) */ static GEN elldivpol0(GEN e, GEN t, GEN N, GEN T, long n, long v) { GEN ret; long m = n/2; if (gel(t,n)) return gel(t,n); if (n<=4) ret = elldivpol4(e, N, n, v); else if (odd(n)) { GEN t1 = RgX_mul(elldivpol0(e,t,N,T,m+2,v), gpowgs(elldivpol0(e,t,N,T,m,v),3)); GEN t2 = RgX_mul(elldivpol0(e,t,N,T,m-1,v), gpowgs(elldivpol0(e,t,N,T,m+1,v),3)); if (odd(m))/*f_{4l+3} = f_{2l+3}f_{2l+1}^3 - T f_{2l}f_{2l+2}^3, m=2l+1*/ ret = RgX_sub(t1, RgX_mul(T,t2)); else /*f_{4l+1} = T f_{2l+2}f_{2l}^3 - f_{2l-1}f_{2l+1}^3, m=2l*/ ret = RgX_sub(RgX_mul(T,t1), t2); } else { /* f_2m = f_m(f_{m+2}f_{m-1}^2 - f_{m-2}f_{m+1}^2) */ GEN t1 = RgX_mul(elldivpol0(e,t,N,T,m+2,v), RgX_sqr(elldivpol0(e,t,N,T,m-1,v))); GEN t2 = RgX_mul(elldivpol0(e,t,N,T,m-2,v), RgX_sqr(elldivpol0(e,t,N,T,m+1,v))); ret = RgX_mul(elldivpol0(e,t,N,T,m,v), RgX_sub(t1,t2)); } gel(t,n) = ret; return ret; } GEN elldivpol(GEN e, long n0, long v) { pari_sp av = avma; GEN f, D, N; long n = labs(n0); checkell(e); D = ell_get_disc(e); if (v < 0) v = 0; if (varncmp(gvar(D), v) <= 0) pari_err_PRIORITY("elldivpol", e, "<=", v); N = characteristic(D); if (!signe(N)) N = NULL; if (n==1 || n==3) f = elldivpol4(e, N, n, v); else { GEN d2 = ec_bmodel(e,v); /* (2y + a1x + a3)^2 mod E */ if (N && !mod2(N)) { gel(d2,5) = modsi(4,N); d2 = normalizepol(d2); } if (n <= 4) f = elldivpol4(e, N, n, v); else f = elldivpol0(e, const_vec(n,NULL), N,RgX_sqr(d2), n, v); if (n%2==0) f = RgX_mul(f, d2); } if (n0 < 0) return gerepileupto(av, RgX_neg(f)); return gerepilecopy(av, f); } /* return [phi_n, (psi_n)^2] such that x[nP] = phi_n / (psi_n)^2 */ GEN ellxn(GEN e, long n, long v) { pari_sp av = avma; GEN d2, D, N, A, B; checkell(e); D = ell_get_disc(e); if (v==-1) v = 0; if (varncmp(gvar(D), v) <= 0) pari_err_PRIORITY("elldivpol", e, "<=", v); N = characteristic(D); if (!signe(N)) N = NULL; if (n < 0) n = -n; d2 = ec_bmodel(e,v); /* (2y + a1x + 3)^2 mod E */ if (N && !mod2(N)) { gel(d2,5) = modsi(4,N); d2 = normalizepol(d2); } if (n == 0) { A = pol_0(v); B = pol_0(v); } else if (n == 1) { A = pol_1(v); B = pol_x(v); } else if (n == 2) { A = d2; B = ec_phi2(e, v); } else { GEN t = const_vec(n+1,NULL), T = RgX_sqr(d2); GEN f = elldivpol0(e, t, N, T, n, v); /* f_n / d2^(n odd)*/ GEN g = elldivpol0(e, t, N, T, n-1, v); /* f_{n-1} / d2^(n even) */ GEN h = elldivpol0(e, t, N, T, n+1, v); /* f_{n+1} / d2^(n even) */ GEN f2 = RgX_sqr(f), u = RgX_mul(g,h); if (!odd(n)) A = RgX_mul(f2, d2); else { A = f2; u = RgX_mul(u,d2); } /* A = psi_n^2, u = psi_{n-1} psi_{n+1} */ B = RgX_sub(RgX_shift(A,1), u); } return gerepilecopy(av, mkvec2(B,A)); } /* l and p primes; p = 1 mod l; return an element of order l in (Z/pZ)^* */ static ulong ltors_Fl(ulong l, ulong p) { ulong x, y, r = (p-1)/l; for (x = 2;; x++) { y = Fl_powu(x, r, p); if (y != 1) return y; } } /* Assume that l|o but p!=1 [l] so r_l E(F_p) = 1 */ static void FljV_vecsat_Siksek(GEN E, GEN P, ulong o, ulong l, ulong a4, ulong a6, ulong p, GEN S, long *m) { long i, n = lg(P)-1; GEN a4a6, g, F, v = zero_zv(n); pari_sp av = avma; ulong q = o / l; F = mkmat2(mkcols(l), mkcols(1)); a4a6 = a4a6_ch_Fl(E, p); g = gel(Fl_ellptors(l, o, a4, a6, p), 1); for (i=1; i <= n; i++) { GEN Q = Fle_changepointinv(Flj_to_Fle(gel(P,i), p), a4a6, p); if (!ell_is_inf(Q)) v[i] = itou(Fle_log(Fle_mulu(Q, q, a4, p), g, F, a4, p)); } gel(S,(*m)++) = v; set_avma(av); } /* Assume that l|o and p=1 [l] so r_l E(F_p) = 1 or 2 */ static void FljV_vecsat_Prickett(GEN E, GEN P, ulong o, ulong l, ulong a4, ulong a6, ulong p, GEN S, long *m) { long i, n = lg(P)-1; GEN a4a6, G, G1, G2, v = zero_zv(n), w = zero_zv(n); ulong g = ltors_Fl(l, p), q = (p-1)/l; pari_sp av = avma; a4a6 = a4a6_ch_Fl(E, p); G = Fl_ellptors(l, o, a4, a6, p); G1 = gel(G,1); G2 = lg(G)==3 ? gel(G, 2): NULL; for (i = 1; i <= n; i++) { GEN Q = Fle_changepointinv(Flj_to_Fle(gel(P,i), p), a4a6, p); if (!ell_is_inf(Q)) { ulong u = Fl_powu(Fle_tatepairing(G1, Q, l, a4, p), q, p); v[i] = Fl_log(u, g, l, p); if (G2) { ulong u = Fl_powu(Fle_tatepairing(G2, Q, l, a4, p), q, p); w[i] = Fl_log(u, g, l, p); } } } gel(S,(*m)++) = v; if (G2 && *m < lg(S)) gel(S,(*m)++) = w; set_avma(av); } static void FljV_vecsat(GEN E, GEN P, ulong o, ulong l, ulong a4, ulong a6, ulong p, GEN S, long *m) { P = ZM_to_Flm(P, p); if (p % l == 1) FljV_vecsat_Prickett(E, P, o, l, a4, a6, p, S, m); else FljV_vecsat_Siksek(E, P, o, l, a4, a6, p, S, m); } /* P a vector of points in E(Q), return a linear map M from the abelian group * they generate to Z/lZ; sum x[i] P[i] is l-divisible => x M = 0 */ static GEN ellsatp_mat(hashtable *h, GEN E, long CM, GEN P, ulong l, long nb) { long m = 1; GEN D = ell_get_disc(E), M = cgetg(nb+1, t_MAT); forprime_t S; P = QEV_to_ZJV(P); (void)u_forprime_init(&S, 5, ULONG_MAX); while (m <= nb) { ulong a4, a6, p = u_forprime_next(&S); long o; if (dvdiu(D, p)) continue; Fl_ell_to_a4a6(E, p, &a4, &a6); if (!hash_haskey_long(h, (void*)p, &o)) { o = p+1 - Fl_elltrace_CM(CM, a4, a6, p); hash_insert_long(h,(void*)p, o); } if (o % l == 0) FljV_vecsat(E, P, o, l, a4, a6, p, M, &m); } return M; } INLINE long Flv_firstnonzero(GEN v) { long i, l = lg(v); for (i = 1; i < l; i++) if (v[i]) break; return i; } /* update M in place */ static GEN ellsatp(hashtable *hh, GEN E, long CM, GEN T, GEN H, GEN M, ulong l, GEN *xl, long vxl, long nb, long prec) { GEN P = T ? shallowconcat(H, T): H; GEN S = ellsatp_mat(hh, E, CM, P, l, nb); /* fill hh */ pari_sp av = avma; GEN K = Flm_ker(Flm_transpose(S), l); long i, lK = lg(K), nH = lg(H)-1; if (lK==1) return gc_NULL(av); if (DEBUGLEVEL >= 3) err_printf("ellsat: potential factor %lu, dim Ker = %ld\n",l,lK-1); /* Mazur bound for torsion of isogenous curves */ if (!*xl && l <= 7) *xl = ellxn(E, l, vxl); for (i = 1; i < lK; i++) { GEN ki = gel(K,i), Ki, h, R; long f = Flv_firstnonzero(ki); /* for T != NULL: avoid solving for [p]Q = R when R is p-torsion */ if (f > nH) continue; if (ki[f] != 1) ki = Flv_Fl_div(ki, ki[f], l); Ki = zv_to_ZV(Flv_center(ki, l, l >> 1)); h = qfeval(M, T? vecslice(Ki, 1, nH): Ki); if (*xl) { GEN Q = ellQ_factorback(E, P, Ki, 1, h, prec); if (ellisdivisible(E, Q, *xl, &R)) h = gdiv(h, sqru(l)); else R = NULL; } else { h = gdiv(h, sqru(l)); R = ellQ_factorback(E, P, Ki, l, h, prec); } if (DEBUGLEVEL >= 2) err_printf("ellsat: %s divisible by %lu\n", R? "": "not", l); if (!R) { if (lK == 2) break; return l > 7? gc_const(av,H): H; /* fail: return and retry */ } gcoeff(M, f, f) = h; for (i = 1; i <= nH; i++) if (i != f) gcoeff(M, f, i) = gdivgu(RgV_dotproduct(gel(M,i), Ki), l); for (i = 1; i <= nH; i++) gcoeff(M, i, f) = gcoeff(M, f, i); gel(H,f) = R; return H; /* found l-divisible point: return new lattice */ } return gc_NULL(av); /* l-saturated */ } static GEN ellQ_saturation(GEN E, GEN P, long B, long prec) { forprime_t S; GEN M = ellheightmatrix(E, P, prec); long CM = ellQ_get_CM(E), w = fetch_var_higher(); hashtable h; ulong p; hash_init_ulong(&h, 16, 1); (void)u_forprime_init(&S, 2, B); P = leafcopy(P); /* modified in place by ellsatp */ while((p = u_forprime_next(&S))) { long nb = lg(P)-1 + 25 / log2(p) - 1; /* error ~ 2^{-25} */ GEN xp = NULL, T = gel(elltors_psylow(E, p), 3); if (lg(T)==1) T = NULL; while (1) { GEN Q = ellsatp(&h, E, CM, T, P, M, p, &xp, w, nb, prec); if (!Q) break; nb += lg(P)-1; P = Q; } } (void)delete_var(); return ellQ_genreduce(E, P, M, prec); } GEN ellsaturation(GEN E, GEN P, long B, long prec) { pari_sp av = avma; GEN urst; if (lg(P) == 1) return cgetg(1, t_VEC); E = ellminimalmodel(E, &urst); if (is_trivial_change(urst)) urst = NULL; if (urst) P = ellchangepoint(P, urst); P = ellQ_saturation(E, P, B, prec); if (urst) P = ellchangepoint(P, ellchangeinvert(urst)); obj_free(E); return gerepilecopy(av, P); } static GEN to_RgX(GEN P, long vx) { return typ(P)==t_POL && varn(P) == vx ? P: scalarpol_shallow(P, vx); } GEN elltrace(GEN E, GEN P) { pari_sp av = avma; GEN xP, yP, T = NULL, Q, LP, M, K, U,V,R, xQ,yQ; long v, n, i, j, d; checkell(E); if (!checkellpt_i(P)) pari_err_TYPE("elltrace", P); if (ell_is_inf(P)) return gcopy(P); /* P == oo */ if (!oncurve(E,P)) pari_err_DOMAIN("elltrace", "point", "not on", strtoGENstr("E"), P); /* More checks */ xP = gel(P,1); yP = gel(P,2); if (typ(xP)==t_POLMOD) { T = gel(xP,1); xP = gel(xP,2); } if (typ(yP)==t_POLMOD) { if (T) { if (!gequal(gel(yP,1),T)) pari_err_MODULUS("elltrace",xP,yP); } else T = gel(yP,1); yP = gel(yP,2); } if (!T) pari_err_TYPE("elltrace",yP); v = varn(T); n = degpol(T); /* Trivial cases */ if (n == 1) { return gerepilecopy(av, mkvec2(xP,yP)); } xP = to_RgX(xP, v); yP = to_RgX(yP, v); if (degpol(xP) <= 0) { if (degpol(yP) > 0) { set_avma(av); retmkvec(gen_0); } P = mkvec2(constant_coeff(xP), constant_coeff(yP)); return gerepileupto(av, ellmul(E, P, utoipos(n))); } /* Strategy: look for a function with divisor equal to * [P_1] + ... + [P_n] + [-Tr(P)] - (n+1)[0]. */ LP = cgetg(n+2,t_VEC); /* basis of the Riemann-Roch space evaluated at P */ gel(LP,1) = pol_1(v); gel(LP,2) = xP; gel(LP,3) = yP; for (i = 4; i <= n+1; i++) gel(LP,i) = RgXQ_mul(gel(LP,i-2), xP, T); M = cgetg(n+2,t_MAT); /* functions defined over K vanishing at P */ for (j = 1; j <= n+1; j++) for (i = 1; i <= n; i++) gel(M,j) = RgX_to_RgC(gel(LP,j), n); K = gel(ker(M),1); /* Coords on 1,x,y,x^2,xy,.. of function f of smallest degree vanishing at P * div f = [P_1] + ... + [P_d] + [-Tr(P)] - (d+1)[0] * with deg(K(P)) = d+1 if Tr(P) != 0; = d otherwise; f = U(x) + y*V(x) */ U = cgetg((n+1)/2+3,t_POL); V = cgetg((n-2)/2+3,t_POL); U[1] = V[1] = evalvarn(0); gel(U,2) = gel(K,1); /* Coef of 1 */ for(i = 1; 2*i <= n+1; i++) gel(U,i+2) = gel(K,2*i); /* Coef of x^i */ for(i = 0; 2*i+3 <= n+1; i++) gel(V,i+2) = gel(K,2*i+3); /* Coef of x^i*y */ U = normalizepol(U); V = normalizepol(V); /* f does not depend on y, so trace = oo */ if (signe(V)==0) { set_avma(av); retmkvec(gen_0); } /* Plug y = -U(x)/V(x) into Weierstrass equation: * 0 = ((x^3+a2x^2+a4x+a6)*V + (a1x+a3)*U)*V - U^2 */ R = mkpoln(4, gen_1, ell_get_a2(E), ell_get_a4(E), ell_get_a6(E)); R = gmul(R, V); R = gadd(R, gmul(U, mkpoln(2,ell_get_a1(E),ell_get_a3(E)))); R = gmul(R, V); R = gsub(R, gsqr(U)); /* Discard Galois orbit of P */ R = RgX_div(R, RgXQ_minpoly(xP,T, 0)); /* What is left is either constant -> return 0, or deg 1 -> nontrivial trace. */ if(degpol(R)<=0) { set_avma(av); retmkvec(gen_0); } /* Recover the trace */ xQ = gneg(gdiv(gel(R,2), gel(R,3))); yQ = gneg(gdiv(poleval(U, xQ), poleval(V, xQ))); Q = mkvec2(xQ, yQ); /* So far, we have computed -Tr(P) over the extension K(P)/K * we still need to compute [L:K(P)] */ d = 0; for (i = n+1; i > 0; i--) if (!gequal0(gel(K,i))) { d = i; break; } return gerepileupto(av, ellmul(E, Q, stoi(-n / (d-1)))); } pari-2.17.2/src/basemath/FlxqE.c0000644000175000017500000013621114760123736014737 0ustar billbill/* Copyright (C) 2012 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_ellcard /* Not so fast arithmetic with points over elliptic curves over Fq, small characteristic. */ /***********************************************************************/ /** **/ /** FlxqE **/ /** **/ /***********************************************************************/ /* These functions deal with point over elliptic curves over Fq defined * by an equation of the form y^2=x^3+a4*x+a6. Most of the time a6 is omitted * since it can be recovered from any point on the curve. */ GEN RgE_to_FlxqE(GEN x, GEN T, ulong p) { if (ell_is_inf(x)) return x; retmkvec2(Rg_to_Flxq(gel(x,1),T,p), Rg_to_Flxq(gel(x,2),T,p)); } GEN FlxqE_changepoint(GEN x, GEN ch, GEN T, ulong p) { pari_sp av = avma; GEN p1, p2, z, u, r, s, t, v, v2, v3; ulong pi; if (ell_is_inf(x)) return x; pi = SMALL_ULONG(p)? 0: get_Fl_red(p); u = gel(ch,1); r = gel(ch,2); s = gel(ch,3); t = gel(ch,4); v = Flxq_inv_pre(u, T, p, pi); v2 = Flxq_sqr_pre(v, T, p, pi); v3 = Flxq_mul_pre(v,v2, T, p, pi); p1 = Flx_sub(gel(x,1), r, p); p2 = Flx_sub(gel(x,2), Flx_add(Flxq_mul_pre(s, p1, T, p, pi),t, p), p); z = cgetg(3,t_VEC); gel(z,1) = Flxq_mul_pre(v2, p1, T, p, pi); gel(z,2) = Flxq_mul_pre(v3, p2, T, p, pi); return gerepileupto(av, z); } GEN FlxqE_changepointinv(GEN x, GEN ch, GEN T, ulong p) { pari_sp av = avma; GEN p1, p2, u, r, s, t, X, Y, u2, u3, u2X, z; ulong pi; if (ell_is_inf(x)) return x; pi = SMALL_ULONG(p)? 0: get_Fl_red(p); X = gel(x,1); Y = gel(x,2); u = gel(ch,1); r = gel(ch,2); s = gel(ch,3); t = gel(ch,4); u2 = Flxq_sqr_pre(u, T, p, pi); u3 = Flxq_mul_pre(u,u2, T, p, pi); u2X = Flxq_mul_pre(u2,X, T, p, pi); p1 = Flxq_mul_pre(u3,Y, T, p, pi); p2 = Flx_add(Flxq_mul_pre(s,u2X, T, p, pi), t, p); z = cgetg(3, t_VEC); gel(z,1) = Flx_add(u2X, r, p); gel(z,2) = Flx_add(p1, p2, p); return gerepileupto(av, z); } static GEN nonsquare_Flxq(GEN T, ulong p) { pari_sp av = avma; long n = degpol(T), vs = T[1]; GEN a; if (odd(n)) return mkvecsmall2(vs, nonsquare_Fl(p)); do { set_avma(av); a = random_Flx(n, vs, p); } while (Flxq_issquare(a, T, p)); return a; } void Flxq_elltwist(GEN a, GEN a6, GEN T, ulong p, GEN *pt_a, GEN *pt_a6) { ulong pi = SMALL_ULONG(p)? 0: get_Fl_red(p); GEN d = nonsquare_Flxq(T, p); GEN d2 = Flxq_sqr_pre(d, T, p, pi), d3 = Flxq_mul_pre(d2, d, T, p, pi); if (typ(a)==t_VECSMALL) { *pt_a = Flxq_mul_pre(a, d2, T, p, pi); *pt_a6 = Flxq_mul_pre(a6, d3, T, p, pi); } else { *pt_a = mkvec(Flxq_mul_pre(gel(a,1), d, T, p, pi)); *pt_a6 = Flxq_mul_pre(a6, d3, T, p, pi); } } static GEN FlxqE_dbl_slope(GEN P, GEN a4, GEN T, ulong p, ulong pi, GEN *ps) { GEN x, y, Q, s; if (ell_is_inf(P) || !lgpol(gel(P,2))) return ellinf(); x = gel(P,1); y = gel(P,2); if (p==3UL) s = typ(a4)==t_VEC? Flxq_div_pre(Flxq_mul_pre(x, gel(a4,1), T,p,pi), y, T,p,pi) : Flxq_div_pre(a4, Flx_neg(y, p), T,p,pi); else { GEN sx = Flx_add(Flx_triple(Flxq_sqr_pre(x, T, p, pi), p), a4, p); s = Flxq_div_pre(sx, Flx_double(y, p), T, p, pi); } Q = cgetg(3,t_VEC); gel(Q,1) = Flx_sub(Flxq_sqr_pre(s, T, p, pi), Flx_double(x, p), p); if (typ(a4)==t_VEC) gel(Q, 1) = Flx_sub(gel(Q,1), gel(a4,1), p); gel(Q,2) = Flx_sub(Flxq_mul_pre(s, Flx_sub(x, gel(Q,1), p), T, p, pi), y, p); if (ps) *ps = s; return Q; } GEN FlxqE_dbl(GEN P, GEN a4, GEN T, ulong p) { pari_sp av = avma; ulong pi = SMALL_ULONG(p)? 0: get_Fl_red(p); return gerepileupto(av, FlxqE_dbl_slope(P,a4, T, p, pi, NULL)); } static GEN FlxqE_add_slope(GEN P, GEN Q, GEN a4, GEN T, ulong p, ulong pi, GEN *ps) { GEN Px, Py, Qx, Qy, R, s; if (ell_is_inf(P)) return Q; if (ell_is_inf(Q)) return P; Px = gel(P,1); Py = gel(P,2); Qx = gel(Q,1); Qy = gel(Q,2); if (Flx_equal(Px, Qx)) { if (Flx_equal(Py, Qy)) return FlxqE_dbl_slope(P, a4, T, p, pi, ps); else return ellinf(); } s = Flxq_div_pre(Flx_sub(Py, Qy, p), Flx_sub(Px, Qx, p), T, p, pi); R = cgetg(3,t_VEC); gel(R,1) = Flx_sub(Flx_sub(Flxq_sqr_pre(s, T, p, pi), Px, p), Qx, p); if (typ(a4)==t_VEC) gel(R,1) = Flx_sub(gel(R,1), gel(a4,1), p); gel(R,2) = Flx_sub(Flxq_mul_pre(s, Flx_sub(Px, gel(R,1), p), T, p, pi), Py, p); if (ps) *ps = s; return R; } GEN FlxqE_add(GEN P, GEN Q, GEN a4, GEN T, ulong p) { pari_sp av = avma; ulong pi = SMALL_ULONG(p)? 0: get_Fl_red(p); return gerepileupto(av, FlxqE_add_slope(P,Q,a4, T,p,pi, NULL)); } static GEN FlxqE_neg_i(GEN P, ulong p) { if (ell_is_inf(P)) return P; return mkvec2(gel(P,1), Flx_neg(gel(P,2), p)); } GEN FlxqE_neg(GEN P, GEN T, ulong p) { (void) T; if (ell_is_inf(P)) return ellinf(); return mkvec2(gcopy(gel(P,1)), Flx_neg(gel(P,2), p)); } GEN FlxqE_sub(GEN P, GEN Q, GEN a4, GEN T, ulong p) { pari_sp av = avma; ulong pi = SMALL_ULONG(p)? 0: get_Fl_red(p); return gerepileupto(av, FlxqE_add_slope(P, FlxqE_neg_i(Q, p), a4, T,p,pi, NULL)); } struct _FlxqE { GEN a4, a6, T; ulong p, pi; }; static GEN _FlxqE_dbl(void *E, GEN P) { struct _FlxqE *e = (struct _FlxqE *) E; return FlxqE_dbl_slope(P, e->a4, e->T, e->p, e->pi, NULL); } static GEN _FlxqE_add(void *E, GEN P, GEN Q) { struct _FlxqE *e = (struct _FlxqE *) E; return FlxqE_add_slope(P, Q, e->a4, e->T, e->p, e->pi, NULL); } static GEN _FlxqE_sub(void *E, GEN P, GEN Q) { struct _FlxqE *e = (struct _FlxqE *) E; return FlxqE_add_slope(P, FlxqE_neg_i(Q,e->p), e->a4, e->T,e->p,e->pi, NULL); } static GEN _FlxqE_mul(void *E, GEN P, GEN n) { pari_sp av = avma; struct _FlxqE *e=(struct _FlxqE *) E; long s = signe(n); if (!s || ell_is_inf(P)) return ellinf(); if (s < 0) P = FlxqE_neg(P, e->T, e->p); if (is_pm1(n)) return s>0? gcopy(P): P; return gerepilecopy(av, gen_pow_i(P, n, e, &_FlxqE_dbl, &_FlxqE_add)); } GEN FlxqE_mul(GEN P, GEN n, GEN a4, GEN T, ulong p) { struct _FlxqE E; E.a4= a4; E.T = T; E.p = p; E.pi = SMALL_ULONG(p)? 0: get_Fl_red(p); return _FlxqE_mul(&E, P, n); } /* 3*x^2+2*a2*x = -a2*x, and a2!=0 */ /* Finds a random nonsingular point on E */ static GEN random_F3xqE(GEN a2, GEN a6, GEN T) { pari_sp ltop = avma; GEN x, y, rhs; const ulong p = 3; do { set_avma(ltop); x = random_Flx(get_Flx_degree(T),get_Flx_var(T),p); rhs = Flx_add(Flxq_mul(Flxq_sqr(x, T, p), Flx_add(x, a2, p), T, p), a6, p); } while ((!lgpol(rhs) && !lgpol(x)) || !Flxq_issquare(rhs, T, p)); y = Flxq_sqrt(rhs, T, p); if (!y) pari_err_PRIME("random_F3xqE", T); return gerepilecopy(ltop, mkvec2(x, y)); } /* Finds a random nonsingular point on E */ static GEN random_FlxqE_pre(GEN a4, GEN a6, GEN T, ulong p, ulong pi) { pari_sp ltop = avma; GEN x, x2, y, rhs; if (typ(a4)==t_VEC) return random_F3xqE(gel(a4,1), a6, T); do { set_avma(ltop); x = random_Flx(get_Flx_degree(T),get_Flx_var(T),p); x2 = Flxq_sqr_pre(x, T, p, pi); /* x^3+a4*x+a6 = x*(x^2+a4)+a6 */ rhs = Flx_add(Flxq_mul_pre(x, Flx_add(x2, a4, p), T, p, pi), a6, p); } while ((!lgpol(rhs) && !lgpol(Flx_add(Flx_triple(x2, p), a4, p))) || !Flxq_issquare(rhs, T, p)); y = Flxq_sqrt(rhs, T, p); if (!y) pari_err_PRIME("random_FlxqE", T); return gerepilecopy(ltop, mkvec2(x, y)); } GEN random_FlxqE(GEN a4, GEN a6, GEN T, ulong p) { return random_FlxqE_pre(a4, a6, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } static GEN _FlxqE_rand(void *E) { struct _FlxqE *e=(struct _FlxqE *) E; return random_FlxqE_pre(e->a4, e->a6, e->T, e->p, e->pi); } static const struct bb_group FlxqE_group={_FlxqE_add,_FlxqE_mul,_FlxqE_rand,hash_GEN,zvV_equal,ell_is_inf, NULL}; const struct bb_group * get_FlxqE_group(void ** pt_E, GEN a4, GEN a6, GEN T, ulong p) { struct _FlxqE *e = (struct _FlxqE *) stack_malloc(sizeof(struct _FlxqE)); e->a4 = a4; e->a6 = a6; e->pi = SMALL_ULONG(p)? 0: get_Fl_red(p); e->p = p; e->T = Flx_get_red_pre(T, p, e->pi); *pt_E = (void *)e; return &FlxqE_group; } GEN FlxqE_order(GEN z, GEN o, GEN a4, GEN T, ulong p) { pari_sp av = avma; struct _FlxqE e; e.a4 = a4; e.T = T; e.p = p; e.pi = SMALL_ULONG(p)? 0: get_Fl_red(p); return gerepileuptoint(av, gen_order(z, o, (void*)&e, &FlxqE_group)); } GEN FlxqE_log(GEN a, GEN b, GEN o, GEN a4, GEN T, ulong p) { pari_sp av = avma; struct _FlxqE e; e.a4 = a4; e.T = T; e.p = p; e.pi = SMALL_ULONG(p)? 0: get_Fl_red(p); return gerepileuptoint(av, gen_PH_log(a, b, o, (void*)&e, &FlxqE_group)); } /***********************************************************************/ /** Pairings **/ /***********************************************************************/ /* Derived from APIP by Jerome Milan, 2012 */ static GEN FlxqE_vert(GEN P, GEN Q, GEN a4, GEN T, ulong p, ulong pi) { long vT = get_Flx_var(T); GEN df; if (ell_is_inf(P)) return pol1_Flx(vT); if (!Flx_equal(gel(Q,1), gel(P,1))) return Flx_sub(gel(Q,1), gel(P,1), p); if (lgpol(gel(P,2))!=0) return pol1_Flx(vT); df = typ(a4)==t_VEC ? Flxq_mul_pre(gel(P,1), Flx_double(gel(a4,1), p), T,p,pi) : a4; return Flxq_inv_pre(Flx_add(Flx_triple(Flxq_sqr_pre(gel(P,1), T,p, pi), p), df, p), T, p, pi); } static GEN FlxqE_Miller_line(GEN R, GEN Q, GEN slope, GEN a4, GEN T, ulong p, ulong pi) { long vT = get_Flx_var(T); GEN x = gel(Q,1), y = gel(Q,2); GEN tmp1 = Flx_sub(x, gel(R,1), p); GEN tmp2 = Flx_add(Flxq_mul_pre(tmp1, slope, T, p, pi), gel(R,2), p); if (!Flx_equal(y, tmp2)) return Flx_sub(y, tmp2, p); if (lgpol(y) == 0) return pol1_Flx(vT); else { GEN s1, s2, a2 = typ(a4)==t_VEC ? gel(a4,1): NULL; GEN y2i = Flxq_inv_pre(Flx_mulu(y, 2, p), T, p, pi); GEN df = a2 ? Flxq_mul_pre(x, Flx_mulu(a2, 2, p), T, p, pi): a4; GEN x3, ddf; s1 = Flxq_mul_pre(Flx_add(Flx_triple(Flxq_sqr_pre(x, T, p, pi), p), df, p), y2i, T, p, pi); if (!Flx_equal(s1, slope)) return Flx_sub(s1, slope, p); x3 = Flx_triple(x, p); ddf = a2 ? Flx_add(x3, a2, p): x3; s2 = Flxq_mul_pre(Flx_sub(ddf, Flxq_sqr_pre(s1, T,p,pi), p), y2i, T,p,pi); return lgpol(s2)!=0 ? s2: y2i; } } /* Computes the equation of the line tangent to R and returns its * evaluation at the point Q. Also doubles the point R. */ static GEN FlxqE_tangent_update(GEN R, GEN Q, GEN a4, GEN T, ulong p, ulong pi, GEN *pt_R) { if (ell_is_inf(R)) { *pt_R = ellinf(); return pol1_Flx(get_Flx_var(T)); } else if (!lgpol(gel(R,2))) { *pt_R = ellinf(); return FlxqE_vert(R, Q, a4, T, p, pi); } else { GEN slope; *pt_R = FlxqE_dbl_slope(R, a4, T, p, pi, &slope); return FlxqE_Miller_line(R, Q, slope, a4, T, p, pi); } } /* Computes the equation of the line through R and P, and returns its * evaluation at the point Q. Also adds P to the point R. */ static GEN FlxqE_chord_update(GEN R, GEN P, GEN Q, GEN a4, GEN T, ulong p, ulong pi, GEN *pt_R) { if (ell_is_inf(R)) { *pt_R = gcopy(P); return FlxqE_vert(P, Q, a4, T, p, pi); } else if (ell_is_inf(P)) { *pt_R = gcopy(R); return FlxqE_vert(R, Q, a4, T, p, pi); } else if (Flx_equal(gel(P, 1), gel(R, 1))) { if (Flx_equal(gel(P, 2), gel(R, 2))) return FlxqE_tangent_update(R, Q, a4, T, p, pi, pt_R); else { *pt_R = ellinf(); return FlxqE_vert(R, Q, a4, T, p, pi); } } else { GEN slope; *pt_R = FlxqE_add_slope(P, R, a4, T, p, pi, &slope); return FlxqE_Miller_line(R, Q, slope, a4, T, p, pi); } } struct _FlxqE_miller { ulong p, pi; GEN T, a4, P; }; static GEN FlxqE_Miller_dbl(void* E, GEN d) { struct _FlxqE_miller *m = (struct _FlxqE_miller *)E; ulong p = m->p, pi = m->pi; GEN T = m->T, a4 = m->a4, P = m->P; GEN v, line, point = gel(d,3); GEN N = Flxq_sqr_pre(gel(d,1), T, p, pi); GEN D = Flxq_sqr_pre(gel(d,2), T, p, pi); line = FlxqE_tangent_update(point, P, a4, T, p, pi, &point); N = Flxq_mul_pre(N, line, T, p, pi); v = FlxqE_vert(point, P, a4, T, p, pi); D = Flxq_mul_pre(D, v, T, p, pi); return mkvec3(N, D, point); } static GEN FlxqE_Miller_add(void* E, GEN va, GEN vb) { struct _FlxqE_miller *m = (struct _FlxqE_miller *)E; ulong p = m->p, pi = m->pi; GEN T = m->T, a4 = m->a4, P = m->P; GEN v, line, point; GEN na = gel(va,1), da = gel(va,2), pa = gel(va,3); GEN nb = gel(vb,1), db = gel(vb,2), pb = gel(vb,3); GEN N = Flxq_mul_pre(na, nb, T, p, pi); GEN D = Flxq_mul_pre(da, db, T, p, pi); line = FlxqE_chord_update(pa, pb, P, a4, T, p, pi, &point); N = Flxq_mul_pre(N, line, T, p, pi); v = FlxqE_vert(point, P, a4, T, p, pi); D = Flxq_mul_pre(D, v, T, p, pi); return mkvec3(N, D, point); } /* Returns the Miller function f_{m, Q} evaluated at the point P using * the standard Miller algorithm. */ static GEN FlxqE_Miller(GEN Q, GEN P, GEN m, GEN a4, GEN T, ulong p, ulong pi) { pari_sp av = avma; struct _FlxqE_miller d; GEN v, N, D, g1; d.a4 = a4; d.T = T; d.p = p; d.P = P; d.pi = pi; g1 = pol1_Flx(get_Flx_var(T)); v = gen_pow_i(mkvec3(g1,g1,Q), m, (void*)&d, FlxqE_Miller_dbl, FlxqE_Miller_add); N = gel(v,1); D = gel(v,2); return gerepileupto(av, Flxq_div_pre(N, D, T, p, pi)); } GEN FlxqE_weilpairing_pre(GEN P, GEN Q, GEN m, GEN a4, GEN T, ulong p, ulong pi) { pari_sp av = avma; GEN N, D, w; if (ell_is_inf(P) || ell_is_inf(Q) || (Flx_equal(gel(P,1),gel(Q,1)) && Flx_equal(gel(P,2),gel(Q,2)))) return pol1_Flx(get_Flx_var(T)); N = FlxqE_Miller(P, Q, m, a4, T, p, pi); D = FlxqE_Miller(Q, P, m, a4, T, p, pi); w = Flxq_div_pre(N, D, T, p, pi); if (mpodd(m)) w = Flx_neg(w, p); return gerepileupto(av, w); } GEN FlxqE_weilpairing(GEN P, GEN Q, GEN m, GEN a4, GEN T, ulong p) { return FlxqE_weilpairing_pre(P,Q,m,a4,T,p, SMALL_ULONG(p)?0:get_Fl_red(p)); } GEN FlxqE_tatepairing(GEN P, GEN Q, GEN m, GEN a4, GEN T, ulong p) { if (ell_is_inf(P) || ell_is_inf(Q)) return pol1_Flx(get_Flx_var(T)); return FlxqE_Miller(P, Q, m, a4, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } static GEN _FlxqE_pairorder(void *E, GEN P, GEN Q, GEN m, GEN F) { struct _FlxqE *e = (struct _FlxqE *) E; return Flxq_order(FlxqE_weilpairing_pre(P,Q,m,e->a4,e->T,e->p,e->pi), F, e->T, e->p); } GEN Flxq_ellgroup(GEN a4, GEN a6, GEN N, GEN T, ulong p, GEN *pt_m) { struct _FlxqE e; GEN q = powuu(p, get_Flx_degree(T)); e.a4=a4; e.a6=a6; e.T=T; e.p=p; e.pi = SMALL_ULONG(p)? 0: get_Fl_red(p); return gen_ellgroup(N, subiu(q,1), pt_m, (void*)&e, &FlxqE_group, _FlxqE_pairorder); } GEN Flxq_ellgens(GEN a4, GEN a6, GEN ch, GEN D, GEN m, GEN T, ulong p) { GEN P; pari_sp av = avma; struct _FlxqE e; e.a4=a4; e.a6=a6; e.T=T; e.p=p; e.pi = SMALL_ULONG(p)? 0: get_Fl_red(p); switch(lg(D)-1) { case 0: return cgetg(1,t_VEC); case 1: P = gen_gener(gel(D,1), (void*)&e, &FlxqE_group); P = mkvec(FlxqE_changepoint(P, ch, T, p)); break; default: P = gen_ellgens(gel(D,1), gel(D,2), m, (void*)&e, &FlxqE_group, _FlxqE_pairorder); gel(P,1) = FlxqE_changepoint(gel(P,1), ch, T, p); gel(P,2) = FlxqE_changepoint(gel(P,2), ch, T, p); break; } return gerepilecopy(av, P); } /***********************************************************************/ /** Point counting **/ /***********************************************************************/ /* assume a and n are coprime */ static GEN RgX_circular_shallow(GEN P, long a, long n) { long i, l = lgpol(P); GEN Q = cgetg(2+n,t_POL); Q[1] = P[1]; for(i=0; iTp; ulong p = d->p, pi = d->pi; GEN xai = Flxq_mul_pre(ZX_to_Flx(x, p), d->ai, T, p, pi); return Flx_to_ZX(Flxq_lroot_fast_pre(xai, d->sqx, T, p, pi)); } static GEN _lift_lin(void *E, GEN F, GEN x2, GEN q) { struct _lift_lin *d = (struct _lift_lin *) E; pari_sp av = avma; GEN T = gel(F,3), Xm = gel(F,4); GEN y2 = ZpXQ_frob(x2, Xm, T, q, d->p); GEN lin = FpX_add(ZX_mul(gel(F,1), y2), ZX_mul(gel(F,2), x2), q); return gerepileupto(av, FpX_rem(lin, T, q)); } static GEN FpM_FpXV_bilinear(GEN P, GEN X, GEN Y, GEN p) { pari_sp av = avma; GEN s = ZX_mul(FpXV_FpC_mul(X,gel(P,1),p),gel(Y,1)); long i, l = lg(P); for(i=2; ip; long n = lg(d->phi)-2; GEN TN = FpXT_red(d->T, q), XN = FpXV_red(d->Xm, q); GEN y2 = ZpXQ_frob(x2, XN, TN, q, p); GEN xp = FpXQ_powers(x2, n, TN, q); GEN yp = FpXQ_powers(y2, n, TN, q); GEN V = FpM_FpXQV_bilinear(d->phi,xp,yp,TN,q); return mkvec3(V,xp,yp); } static GEN _lift_invd(void *E, GEN V, GEN v, GEN qM, long M) { struct _lift_iso *d = (struct _lift_iso *) E; struct _lift_lin e; ulong p = d->p, pi = d->pi; GEN TM = FpXT_red(d->T, qM), XM = FpXV_red(d->Xm, qM); GEN xp = FpXV_red(gel(v,2), qM); GEN yp = FpXV_red(gel(v,3), qM); GEN Dx = FpM_FpXQV_bilinear(d->phi, FpXC_powderiv(xp, qM), yp, TM, qM); GEN Dy = FpM_FpXQV_bilinear(d->phi, xp, FpXC_powderiv(yp, qM), TM, qM); GEN F = mkvec4(Dy, Dx, TM, XM); e.ai = Flxq_inv_pre(ZX_to_Flx(Dy,p),d->Tp, p, pi); e.sqx = d->sqx; e.Tp = d->Tp; e.p=p; e.pi=pi; e.Xm = XM; return gen_ZpX_Dixon(F,V,qM,utoipos(p),M,(void*) &e, _lift_lin, _lift_invl); } static GEN lift_isogeny(GEN phi, GEN x0, long n, GEN Xm, GEN T, GEN sqx, GEN Tp, ulong p, ulong pi) { struct _lift_iso d; d.phi = phi; d.Xm = Xm; d.T = T; d.sqx = sqx; d.Tp = Tp; d.p = p; d.pi = pi; return gen_ZpX_Newton(x0, utoipos(p), n,(void*)&d, _lift_iter, _lift_invd); } static GEN getc2(GEN act, GEN X, GEN T, GEN q, ulong p, long N) { GEN A1 = RgV_to_RgX(gel(act,1),0), A2 = RgV_to_RgX(gel(act,2),0); long n = brent_kung_optpow(maxss(degpol(A1),degpol(A2)),2,1); GEN xp = FpXQ_powers(X,n,T,q); GEN P = FpX_FpXQV_eval(A1, xp, T, q); GEN Q = FpX_FpXQV_eval(A2, xp, T, q); return ZpXQ_div(P, Q, T, q, utoipos(p), N); } struct _ZpXQ_norm { long n; GEN T, p; }; static GEN ZpXQ_norm_mul(void *E, GEN x, GEN y) { struct _ZpXQ_norm *D = (struct _ZpXQ_norm*)E; GEN P = gel(x,1), Q = gel(y,1); long a = mael(x,2,1), b = mael(y,2,1); retmkvec2(FpXQ_mul(P,ZpXQ_frob_cyc(Q, D->T, D->p, a), D->T, D->p), mkvecsmall((a*b)%D->n)); } static GEN ZpXQ_norm_sqr(void *E, GEN x) { return ZpXQ_norm_mul(E, x, x); } /* Assume T = Phi_(n) and n prime */ GEN ZpXQ_norm_pcyc(GEN x, GEN T, GEN q, GEN p) { GEN z; struct _ZpXQ_norm D; long d = get_FpX_degree(T); D.T = T; D.p = q; D.n = d+1; if (d==1) return ZX_copy(x); z = mkvec2(x,mkvecsmall(p[2])); z = gen_powu_i(z,d,(void*)&D,ZpXQ_norm_sqr,ZpXQ_norm_mul); return gmael(z,1,2); } /* Assume T = Phi_(n) and n prime */ static GEN ZpXQ_sqrtnorm_pcyc(GEN x, GEN T, GEN q, GEN p, long e) { GEN z = ZpXQ_norm_pcyc(x, T, q, p); return Zp_sqrtlift(z,Fp_sqrt(z,p),p,e); } /* Assume a = 1 [p], return the square root of the norm */ static GEN ZpXQ_sqrtnorm(GEN a, GEN T, GEN q, GEN p, long e) { GEN s = Fp_div(FpXQ_trace(ZpXQ_log(a, T, p, e), T, q), gen_2, q); return modii(gel(Qp_exp(cvtop(s, p, e-1)),4), q); } struct _teich_lin { ulong p, pi; GEN sqx, Tp; long m; }; static GEN _teich_invl(void *E, GEN x) { struct _teich_lin *d = (struct _teich_lin *) E; ulong p = d->p, pi = d->pi; return Flx_to_ZX(Flxq_lroot_fast_pre(ZX_to_Flx(x,p), d->sqx, d->Tp, p, pi)); } static GEN _teich_lin(void *E, GEN F, GEN x2, GEN q) { struct _teich_lin *d = (struct _teich_lin *) E; pari_sp av = avma; GEN T = gel(F,2), Xm = gel(F,3); GEN y2 = ZpXQ_frob(x2, Xm, T, q, d->p); GEN lin = FpX_sub(y2, ZX_mulu(ZX_mul(gel(F,1), x2), d->p), q); return gerepileupto(av, FpX_rem(lin, T, q)); } struct _teich_iso { GEN Xm, T, sqx, Tp; ulong p, pi; }; static GEN _teich_iter(void *E, GEN x2, GEN q) { struct _teich_iso *d = (struct _teich_iso *) E; ulong p = d->p; GEN TN = FpXT_red(d->T, q), XN = FpXV_red(d->Xm, q); GEN y2 = ZpXQ_frob(x2, XN, TN, q, d->p); GEN x1 = FpXQ_powu(x2, p-1, TN, q); GEN xp = FpXQ_mul(x2, x1, TN, q); GEN V = FpX_sub(y2,xp,q); return mkvec2(V,x1); } static GEN _teich_invd(void *E, GEN V, GEN v, GEN qM, long M) { struct _teich_iso *d = (struct _teich_iso *) E; struct _teich_lin e; ulong p = d->p; GEN TM = FpXT_red(d->T, qM), XM = FpXV_red(d->Xm, qM); GEN x1 = FpX_red(gel(v,2), qM); GEN F = mkvec3(x1, TM, XM); e.sqx = d->sqx; e.Tp = d->Tp; e.p = p; e.pi = d->pi; return gen_ZpX_Dixon(F,V,qM,utoipos(p),M,(void*) &e, _teich_lin, _teich_invl); } static GEN Teichmuller_lift(GEN x, GEN Xm, GEN T, GEN sqx, GEN Tp, ulong p, ulong pi, long N) { struct _teich_iso d; d.Xm = Xm; d.T = T; d.sqx = sqx; d.Tp = Tp; d.p = p; d.pi = pi; return gen_ZpX_Newton(x,utoipos(p), N,(void*)&d, _teich_iter, _teich_invd); } static GEN get_norm(GEN a4, GEN a6, GEN T, ulong p, ulong pi, long N) { long sv=T[1]; GEN a; if (p==3) a = gel(a4,1); else { GEN P = mkpoln(4, pol1_Flx(sv), pol0_Flx(sv), a4, a6); a = gel(FlxqX_powu_pre(P, p>>1, T,p,pi), 2+p-1); } return Zp_sqrtnlift(gen_1,subss(p,1),utoi(Flxq_norm(a,T,p)),utoipos(p), N); } static GEN fill_pols(long n, const long *v, long m, const long *vn, const long *vd, GEN *act) { long i, j; long d = upowuu(n,12/(n-1)); GEN N, D, M = zeromatcopy(n+1,n+1); gmael(M,1,n+1) = gen_1; for (i = 2; i <= n+1; i++) for (j = i-1; j <= n; j++) gmael(M,i,j) = mulis(powuu(d,i-2), v[j-i+1]); N = cgetg(m+1,t_COL); D = cgetg(m+1,t_COL); for(i = 1; i <= m; i++) { gel(N,i) = stoi(*vn++); gel(D,i) = stoi(*vd++); } *act = mkmat2(N,D); return M; } /* These polynomials were extracted from the ECHIDNA databases available at and computed by David R. Kohel. Return the matrix of the modular polynomial, set act to the parametrization, and set dj to the opposite of the supersingular j-invariant. */ static GEN get_Kohel_polynomials(ulong p, GEN *act, long *dj) { const long mat3[] = {-1,-36,-270}; const long num3[] = {1,-483,-21141,-59049}; const long den3[] = {1,261, 4347, -6561}; const long mat5[] = {-1,-30,-315,-1300,-1575}; const long num5[] = {-1,490,20620,158750,78125}; const long den5[] = {-1,-254,-4124,-12250,3125}; const long mat7[] = {-1,-28,-322,-1904,-5915,-8624,-4018}; const long num7[] = {1,-485,-24058,-343833,-2021642,-4353013,-823543}; const long den7[] = {1,259,5894,49119,168406,166355,-16807}; const long mat13[]= {-1,-26,-325,-2548,-13832,-54340,-157118,-333580,-509366, -534820,-354536,-124852,-15145}; const long num13[]= {1,-487,-24056,-391463,-3396483,-18047328,-61622301, -133245853,-168395656,-95422301,-4826809}; const long den13[]= {1,257,5896,60649,364629,1388256,3396483,5089019,4065464, 1069939,-28561}; switch(p) { case 3: *dj = 0; return fill_pols(3,mat3,4,num3,den3,act); case 5: *dj = 0; return fill_pols(5,mat5,5,num5,den5,act); case 7: *dj = 1; return fill_pols(7,mat7,7,num7,den7,act); case 13: *dj = 8; return fill_pols(13,mat13,11,num13,den13,act); } *dj=0; *act = NULL; return NULL; /* LCOV_EXCL_LINE */ } long zx_is_pcyc(GEN T) { long i, n = degpol(T); if (!uisprime(n+1)) return 0; for (i = 0; i <= n; i++) if (T[i+2] != 1UL) return 0; return 1; } static GEN Flxq_ellcard_Kohel(GEN a4, GEN a6, GEN T, ulong p) { pari_sp av = avma, av2; pari_timer ti; long n = get_Flx_degree(T), N = (n+4)/2, dj; GEN q = powuu(p, N); GEN T2, Xm, s1, c2, t, lr, S1, sqx, Nc2, Np; GEN act, phi = get_Kohel_polynomials(p, &act, &dj); long ispcyc = zx_is_pcyc(get_Flx_mod(T)); ulong pi = SMALL_ULONG(p)? 0: get_Fl_red(p); timer_start(&ti); if (!ispcyc) { T2 = Flx_Teichmuller(get_Flx_mod(T),p,N); if (DEBUGLEVEL) timer_printf(&ti,"Teich"); } else T2 = Flx_to_ZX(get_Flx_mod(T)); T2 = FpX_get_red(T2, q); T = ZXT_to_FlxT(T2, p); av2 = avma; if (DEBUGLEVEL) timer_printf(&ti,"Barrett"); if (!ispcyc) { Xm = FpXQ_powers(pol_xn(n,get_FpX_var(T2)),p-1,T2,q); if (DEBUGLEVEL) timer_printf(&ti,"Xm"); } else Xm = cgetg(1,t_VEC); s1 = Flxq_inv_pre(Flx_Fl_add(Flxq_ellj(a4,a6,T,p),dj, p),T,p,pi); lr = Flxq_lroot_pre(polx_Flx(get_Flx_var(T)), T,p,pi); sqx = Flxq_powers_pre(lr, p-1, T, p, pi); S1 = lift_isogeny(phi, Flx_to_ZX(s1), N, Xm, T2, sqx, T,p,pi); if (DEBUGLEVEL) timer_printf(&ti,"Lift isogeny"); c2 = getc2(act, S1, T2, q, p, N); if (DEBUGLEVEL) timer_printf(&ti,"c^2"); if (p>3 && !ispcyc) { GEN c2p = Flx_to_ZX(Flxq_inv_pre(ZX_to_Flx(c2,p),T,p,pi)); GEN tc2 = Teichmuller_lift(c2p,Xm, T2,sqx,T,p,pi,N); if (DEBUGLEVEL) timer_printf(&ti,"Teichmuller/Fq"); c2 = FpX_rem(FpX_mul(tc2,c2,q),T2,q); } c2 = gerepileupto(av2, c2); if (DEBUGLEVEL) timer_printf(&ti,"tc2"); Nc2 = (ispcyc? ZpXQ_sqrtnorm_pcyc: ZpXQ_sqrtnorm)(c2, T2, q, utoipos(p), N); if (DEBUGLEVEL) timer_printf(&ti,"Norm"); Np = get_norm(a4,a6,T,p,pi,N); if (p>3 && ispcyc) { GEN Ncpi = utoi(Fl_inv(umodiu(Nc2,p), p)); GEN tNc2 = Zp_sqrtnlift(gen_1, subss(p,1), Ncpi, utoipos(p),N); if (DEBUGLEVEL) timer_printf(&ti,"Teichmuller/Fp"); Nc2 = Fp_mul(Nc2,tNc2,q); } t = Fp_center_i(Fp_mul(Nc2,Np,q),q,shifti(q,-1)); return gerepileupto(av, subii(addiu(powuu(p,n),1),t)); } /* Use Damien Robert's method */ static GEN get_trace_Robert(GEN J, GEN phi, GEN Xm, GEN T, GEN q, ulong p, long e) { long n = lg(phi)-2; GEN K = ZpXQ_frob(J, Xm, T, q, p); GEN Jp = FpXQ_powers(J, n, T, q); GEN Kp = FpXQ_powers(K, n, T, q); GEN Jd = FpXC_powderiv(Jp, q); GEN Kd = FpXC_powderiv(Kp, q); GEN Dx = FpM_FpXQV_bilinear(phi, Kd, Jp, T, q); GEN Dy = FpM_FpXQV_bilinear(phi, Kp, Jd, T, q); GEN C = ZpXQ_inv(ZX_divuexact(Dy, p), T, utoi(p), e); return FpX_neg(FpXQ_mul(Dx, C, T, q), q); } /* in p^2, so p is tiny */ static GEN Flxq_ellcard_Harley(GEN a4, GEN a6, GEN T, ulong p) { pari_sp av = avma, av2; pari_timer ti; long n = get_Flx_degree(T), N = (n+5)/2; GEN pp = utoipos(p), q = powuu(p, N); GEN T2, j, t, phi, J1, sqx, Xm, c2, tc2, c2p, Nc2, Np; long ispcyc = zx_is_pcyc(get_Flx_mod(T)); ulong pi = SMALL_ULONG(p)? 0: get_Fl_red(p); /* = 0 here */ timer_start(&ti); if (!ispcyc) { T2 = Flx_Teichmuller(get_Flx_mod(T),p,N); if (DEBUGLEVEL) timer_printf(&ti,"Teich"); } else T2 = Flx_to_ZX(get_Flx_mod(T)); T2 = FpX_get_red(T2, q); T = ZXT_to_FlxT(T2, p); av2 = avma; if (DEBUGLEVEL) timer_printf(&ti,"Barrett"); if (!ispcyc) { Xm = FpXQ_powers(pol_xn(n,get_FpX_var(T2)),p-1,T2,q); if (DEBUGLEVEL) timer_printf(&ti,"Xm"); } else Xm = cgetg(1,t_VEC); j = Flxq_ellj(a4,a6,T,p); sqx = Flxq_powers_pre(Flxq_lroot_pre(polx_Flx(T[1]), T,p,pi), p-1, T,p,pi); phi = polmodular_ZM(p, 0); if (DEBUGLEVEL) timer_printf(&ti,"phi"); J1 = lift_isogeny(phi, Flx_to_ZX(j), N, Xm, T2,sqx,T,p,pi); if (DEBUGLEVEL) timer_printf(&ti,"Lift isogeny"); c2 = get_trace_Robert(J1, phi, Xm, T2, q, p, N); q = diviuexact(q,p); N--; if (DEBUGLEVEL) timer_printf(&ti,"c^2"); if (!ispcyc) { c2p = Flx_to_ZX(Flxq_inv_pre(ZX_to_Flx(c2,p),T,p,pi)); tc2 = Teichmuller_lift(c2p,Xm, T2,sqx,T,p,pi,N); if (DEBUGLEVEL) timer_printf(&ti,"teichmuller"); c2 = FpX_rem(FpX_mul(tc2,c2,q),T2,q); } c2 = gerepileupto(av2, c2); q = powuu(p, N); Nc2 = (ispcyc? ZpXQ_sqrtnorm_pcyc: ZpXQ_sqrtnorm)(c2, T2, q, pp, N); if (DEBUGLEVEL) timer_printf(&ti,"Norm"); Np = get_norm(a4,a6,T,p,pi,N); if (ispcyc) { GEN Ncpi = utoi(Fl_inv(umodiu(Nc2,p), p)); GEN tNc2 = Zp_sqrtnlift(gen_1, subss(p,1), Ncpi, pp, N); if (DEBUGLEVEL) timer_printf(&ti,"Teichmuller/Fp"); Nc2 = Fp_mul(Nc2,tNc2,q); } t = Fp_center_i(Fp_mul(Nc2,Np,q),q,shifti(q,-1)); return gerepileupto(av, subii(addiu(powuu(p,n),1),t)); } /***************************************************************************/ /* Shanks-Mestre */ /***************************************************************************/ /* Return the lift of a (mod b), which is closest to h */ static GEN closest_lift(GEN a, GEN b, GEN h) { return addii(a, mulii(b, diviiround(subii(h,a), b))); } /* find multiple of order of f using Baby Step/Giant Step, f^h close to 1, * order lies in an interval of size <= 'bound' and known mod B */ static GEN _FlxqE_order_multiple(void *E, GEN f, GEN h, GEN bound, GEN B) { pari_sp av = avma, av1; pari_timer Ti; long i, s = ceilsqrtdiv(bound, B) >> 1; GEN P, F, tx, ti, fg, fh; P = fh = _FlxqE_mul(E, f, h); if (DEBUGLEVEL >= 6) timer_start(&Ti); if (ell_is_inf(fh)) return h; F = _FlxqE_mul(E, f, B); if (s < 3) { /* we're nearly done: naive search */ GEN Q = P; for (i=1;; i++) { P = _FlxqE_add(E, P, F); /* h.f + i.F */ if (ell_is_inf(P)) return gerepileupto(av, addii(h, mului(i,B))); Q = _FlxqE_sub(E, Q, F); /* h.f - i.F */ if (ell_is_inf(Q)) return gerepileupto(av, subii(h, mului(i,B))); } } tx = cgetg(s+1,t_VECSMALL); av1 = avma; for (i=1; i<=s; i++) { /* baby steps */ tx[i] = hash_GEN(gel(P, 1)); P = _FlxqE_add(E, P, F); /* h.f + i.F */ if (ell_is_inf(P)) return gerepileupto(av, addii(h, mului(i,B))); if (gc_needed(av1,3)) { if(DEBUGMEM>1) pari_warn(warnmem,"[Flxq_ellcard] baby steps, i=%ld",i); P = gerepileupto(av1,P); } } if (DEBUGLEVEL >= 6) timer_printf(&Ti,"[Flxq_ellcard] baby steps, s = %ld",s); /* giant steps: fg = s.F */ fg = gerepileupto(av1, _FlxqE_sub(E, P, fh)); if (ell_is_inf(fg)) return gerepileupto(av, mului(s,B)); ti = vecsmall_indexsort(tx); /* = permutation sorting tx */ tx = perm_mul(tx,ti); if (DEBUGLEVEL >= 6) timer_printf(&Ti, "[Flxq_ellcard] sorting"); av1 = avma; for (P=fg, i=1; ; i++) { long k = hash_GEN(gel(P,1)), r = zv_search(tx, k); if (r) { while (r && tx[r] == k) r--; for (r++; r <= s && tx[r] == k; r++) { long j = ti[r]-1; GEN Q = _FlxqE_add(E, _FlxqE_mul(E, F, stoi(j)), fh); if (DEBUGLEVEL >= 6) timer_printf(&Ti, "[Flxq_ellcard] giant steps, i = %ld",i); if (Flx_equal(gel(P,1), gel(Q,1))) { if (Flx_equal(gel(P,2), gel(Q,2))) i = -i; return gerepileupto(av,addii(h, mulii(addis(mulss(s,i), j), B))); } } } P = _FlxqE_add(E, P, fg); if (gc_needed(av1,3)) { if(DEBUGMEM>1) pari_warn(warnmem,"[Flxq_ellcard] giants steps, i=%ld",i); P = gerepileupto(av1,P); } } } static GEN _FlxqE_order(void *E, GEN f, GEN h, GEN bound, GEN B) { GEN o = _FlxqE_order_multiple(E, f, h, bound, B); return gen_order(f, o, E, &FlxqE_group); } static void Flx_next(GEN t, ulong p) { long i; for(i=2;;i++) if (uel(t,i)==p-1) t[i]=0; else { t[i]++; break; } } static void Flx_renormalize_ip(GEN x, long lx) { long i; for (i = lx-1; i>=2; i--) if (x[i]) break; setlg(x, i+1); } static ulong F3xq_ellcard_naive(GEN a2, GEN a6, GEN T) { pari_sp av = avma; long i, d = get_Flx_degree(T), lx = d+2; long q = upowuu(3, d), a; GEN x = zero_zv(lx); x[1] = get_Flx_var(T); for(a=1, i=0; i= bound, it is determined */ switch(FlxqX_nbroots(mkpoln(4, pol1_Flx(v), pol0_Flx(v), a4, a6), T, p)) { /* how many 2-torsion points ? */ 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 */ } for(;;) { h = closest_lift(A, B, q1p); /* [ux, u^2] is on E_u: y^2 = x^3 + c4 u^2 x + c6 u^3 * E_u isomorphic to E (resp. E') iff KRO = 1 (resp. -1) * #E(F_p) = p+1 - a_p, #E'(F_p) = p+1 + a_p * * #E_u(Flxq) = A (mod B), h is close to #E_u(Flxq) */ KRO = -KRO; f = Flxq_ellpoint(KRO, a4,a6, T,p,pi); e.a4 = Flxq_mul_pre(a4, gel(f,2), T,p,pi); /* a4 for E_u */ h = _FlxqE_order((void*)&e, f, h, bound, B); /* h | #E_u(Flxq) = A (mod B) */ A = Z_chinese_all(A, gen_0, B, h, &B); if (cmpii(B, bound) >= 0) break; /* not done, update A mod B for the _next_ curve, isomorphic to * the quadratic twist of this one */ A = remii(subii(q2p,A), B); /* #E(Fq)+#E'(Fq) = 2q+2 */ } h = closest_lift(A, B, q1p); return gerepileuptoint(av, KRO == 1? h: subii(q2p,h)); } static GEN F3xq_ellcard(GEN a2, GEN a6, GEN T) { long n = get_Flx_degree(T); if (n <= 2) return utoi(F3xq_ellcard_naive(a2, a6, T)); else { GEN q1 = addiu(powuu(3, get_Flx_degree(T)), 1), t; GEN a = Flxq_div(a6,Flxq_powu(a2,3,T,3),T,3); if (Flx_equal1(Flxq_powu(a, 8, T, 3))) { GEN P = Flxq_minpoly(a,T,3); long dP = degpol(P); /* dP <= 2 */ ulong q = upowuu(3,dP); GEN A2 = pol1_Flx(P[1]), A6 = Flx_rem(polx_Flx(P[1]), P, 3); long tP = q + 1 - F3xq_ellcard_naive(A2, A6, P); t = elltrace_extension(stoi(tP), n/dP, utoi(q)); if (umodiu(t, 3)!=1) t = negi(t); return Flx_equal1(a2) || Flxq_issquare(a2,T,3) ? subii(q1,t): addii(q1,t); } else return Flxq_ellcard_Kohel(mkvec(a2), a6, T, 3); } } static GEN Flxq_ellcard_Satoh(GEN a4, GEN a6, GEN j, GEN T, ulong p) { long n = get_Flx_degree(T); if (n <= 2) return utoi(Flxq_ellcard_naive(a4, a6, T, p)); else { GEN jp = Flxq_powu(j, p, T, p); GEN s = Flx_add(j, jp, p); if (degpol(s) <= 0) { /* it is assumed j not in F_p */ GEN m = Flxq_mul(j, jp, T, p); if (degpol(m) <= 0) { GEN q = sqru(p); GEN q1 = addiu(powuu(p, get_Flx_degree(T)), 1); GEN sk = Flx_Fl_add(Flx_neg(j, p), 1728%p, p); GEN sA4 = Flx_triple(Flxq_mul(sk, j, T, p), p); GEN u = Flxq_div(a4, sA4, T, p); ulong ns = lgpol(s) ? Fl_neg(s[2], p): 0UL; GEN P = mkvecsmall4(T[1], m[2], ns, 1L); GEN A4, A6, t, tP; Flxq_ellj_to_a4a6(polx_Flx(T[1]), P, p, &A4, &A6); tP = addis(q, 1 - Flxq_ellcard_naive(A4, A6, P, p)); t = elltrace_extension(tP, n>>1, q); return Flxq_is2npower(u, 2, T, p) ? subii(q1,t): addii(q1,t); } } if (p<=7 || p==13) return Flxq_ellcard_Kohel(a4, a6, T, p); else return Flxq_ellcard_Harley(a4, a6, T, p); } } static GEN Flxq_ellcard_Kedlaya(GEN a4, GEN a6, GEN T, ulong p) { pari_sp av = avma; GEN H = mkpoln(4, gen_1, gen_0, Flx_to_ZX(a4), Flx_to_ZX(a6)); GEN Tp = Flx_to_ZX(get_Flx_mod(T)); long n = degpol(Tp), e = ((p < 16 ? n+1: n)>>1)+1; GEN M = ZlXQX_hyperellpadicfrobenius(H, Tp, p, e); GEN N = ZpXQM_prodFrobenius(M, Tp, utoipos(p), e); GEN q = powuu(p, e); GEN tp = Fq_add(gcoeff(N,1,1), gcoeff(N,2,2), Tp, q); GEN t = Fp_center_i(typ(tp)==t_INT ? tp: leading_coeff(tp), q, shifti(q,-1)); return gerepileupto(av, subii(addiu(powuu(p, n), 1), t)); } GEN Flxq_ellj(GEN a4, GEN a6, GEN T, ulong p) { pari_sp av=avma; if (p==3) { GEN J; if (typ(a4)!=t_VEC) return pol0_Flx(get_Flx_var(T)); J = Flxq_div(Flxq_powu(gel(a4,1),3, T, p),Flx_neg(a6,p), T, p); return gerepileuptoleaf(av, J); } else { pari_sp av=avma; GEN a43 = Flxq_mul(a4,Flxq_sqr(a4,T,p),T,p); GEN a62 = Flxq_sqr(a6,T,p); GEN num = Flx_mulu(a43,6912,p); GEN den = Flx_add(Flx_mulu(a43,4,p),Flx_mulu(a62,27,p),p); return gerepileuptoleaf(av, Flxq_div(num, den, T, p)); } } void Flxq_ellj_to_a4a6(GEN j, GEN T, ulong p, GEN *pt_a4, GEN *pt_a6) { ulong zagier = 1728 % p; if (lgpol(j)==0) { *pt_a4 = pol0_Flx(T[1]); *pt_a6 =pol1_Flx(T[1]); } else if (lgpol(j)==1 && uel(j,2) == zagier) { *pt_a4 = pol1_Flx(T[1]); *pt_a6 =pol0_Flx(T[1]); } else { GEN k = Flx_Fl_add(Flx_neg(j, p), zagier, p); GEN kj = Flxq_mul(k, j, T, p); GEN k2j = Flxq_mul(kj, k, T, p); *pt_a4 = Flx_triple(kj, p); *pt_a6 = Flx_double(k2j, p); } } static GEN F3xq_ellcardj(GEN a4, GEN a6, GEN T, GEN q, long n) { const ulong p = 3; ulong t; GEN q1 = addiu(q,1); GEN na4 = Flx_neg(a4,p), ra4; if (!Flxq_issquare(na4,T,p)) return q1; ra4 = Flxq_sqrt(na4,T,p); t = Flxq_trace(Flxq_div(a6,Flxq_mul(na4,ra4,T,p),T,p),T,p); if (n%2==1) { GEN q3; if (t==0) return q1; q3 = powuu(p,(n+1)>>1); return (t==1)^(n%4==1) ? subii(q1,q3): addii(q1,q3); } else { GEN q22, q2 = powuu(p,n>>1); GEN W = Flxq_pow(a4,shifti(q,-2),T,p); long s = (W[2]==1)^(n%4==2); if (t!=0) return s ? addii(q1,q2): subii(q1, q2); q22 = shifti(q2,1); return s ? subii(q1,q22): addii(q1, q22); } } static GEN Flxq_ellcardj(GEN a4, GEN a6, ulong j, GEN T, GEN q, ulong p, long n) { GEN q1 = addiu(q,1); if (j==0) { ulong w; GEN W, t, N; if (umodiu(q,6)!=1) return q1; N = Fp_ffellcard(gen_0,gen_1,q,n,utoipos(p)); t = subii(q1, N); W = Flxq_pow(a6,diviuexact(shifti(q,-1), 3),T,p); if (degpol(W)>0) /*p=5 mod 6*/ return Flx_equal1(Flxq_powu(W,3,T,p)) ? addii(q1,shifti(t,-1)): subii(q1,shifti(t,-1)); w = W[2]; if (w==1) return N; if (w==p-1) return addii(q1,t); else /*p=1 mod 6*/ { GEN u = shifti(t,-1), v = sqrtint(diviuexact(subii(q,sqri(u)),3)); GEN a = addii(u,v), b = shifti(v,1); if (Fl_powu(w,3,p)==1) { if (Fl_add(umodiu(a,p),Fl_mul(w,umodiu(b,p),p),p)==0) return subii(q1,subii(shifti(b,1),a)); else return addii(q1,addii(a,b)); } else { if (Fl_sub(umodiu(a,p),Fl_mul(w,umodiu(b,p),p),p)==0) return subii(q1,subii(a,shifti(b,1))); else return subii(q1,addii(a,b)); } } } else if (j==1728%p) { ulong w; GEN W, N, t; if (mod4(q)==3) return q1; W = Flxq_pow(a4,shifti(q,-2),T,p); if (degpol(W)>0) return q1; /*p=3 mod 4*/ w = W[2]; N = Fp_ffellcard(gen_1,gen_0,q,n,utoipos(p)); if(w==1) return N; t = subii(q1, N); if(w==p-1) return addii(q1, t); else /*p=1 mod 4*/ { GEN u = shifti(t,-1), v = sqrtint(subii(q,sqri(u))); if (Fl_add(umodiu(u,p),Fl_mul(w,umodiu(v,p),p),p)==0) return subii(q1,shifti(v,1)); else return addii(q1,shifti(v,1)); } } else { ulong g = Fl_div(j, Fl_sub(1728%p, j, p), p); GEN N = Fp_ffellcard(utoi(Fl_triple(g,p)),utoi(Fl_double(g,p)),q,n,utoipos(p)); GEN l = Flxq_mul(Flx_triple(a6,p),Flx_double(a4,p),T,p); if (Flxq_issquare(l,T,p)) return N; return subii(shifti(q1,1),N); } } static GEN Flxq_ffellcard(GEN a4, GEN a6, GEN M, GEN q, GEN T, ulong p, long n) { long m = degpol(M); GEN j = polx_Flx(M[1]); GEN g = Flxq_div(j, mkvecsmall3(M[1],1728%p,p-1), M, p); GEN N = Flxq_ellcard(Flx_triple(g, p), Flx_double(g, p), M, p); GEN qm = powuu(p, m), q1 = addiu(q, 1), qm1 = addiu(qm, 1); GEN l = Flxq_mul(Flx_triple(a6,p), Flx_double(a4,p), T, p); GEN te = elltrace_extension(subii(qm1, N), n/m, qm); return Flxq_issquare(l,T,p) ? subii(q1, te): addii(q1, te); } static GEN Flxq_ellcard_i(GEN a4, GEN a6, GEN T, ulong p) { long n = get_Flx_degree(T); GEN J, M, q = powuu(p, n); if (typ(a4)==t_VEC) return F3xq_ellcard(gel(a4,1), a6, T); if (p==3) return F3xq_ellcardj(a4, a6, T, q, n); if (degpol(a4)<=0 && degpol(a6)<=0) return Fp_ffellcard(utoi(Flx_eval(a4,0,p)),utoi(Flx_eval(a6,0,p)),q,n,utoipos(p)); J = Flxq_ellj(a4,a6,T,p); if (degpol(J)<=0) return Flxq_ellcardj(a4,a6,lgpol(J)?J[2]:0,T,q,p,n); M = Flxq_minpoly(J, T, p); if (degpol(M) < n) return Flxq_ffellcard(a4, a6, M, q, T, p, n); if (p <= 7) return Flxq_ellcard_Satoh(a4, a6, J, T, p); if (cmpis(q,100)<0) return utoi(Flxq_ellcard_naive(a4, a6, T, p)); if (p == 13 || (7*p <= (ulong)10*n && (BITS_IN_LONG==64 || p <= 103))) return Flxq_ellcard_Satoh(a4, a6, J, T, p); if (p <= (ulong)2*n) return Flxq_ellcard_Kedlaya(a4, a6, T, p); if (expi(q)<=62) return Flxq_ellcard_Shanks(a4, a6, q, T, p); else return Fq_ellcard_SEA(Flx_to_ZX(a4),Flx_to_ZX(a6),q,Flx_to_ZX(T),utoipos(p),0); } GEN Flxq_ellcard(GEN a4, GEN a6, GEN T, ulong p) { pari_sp av = avma; return gerepileuptoint(av, Flxq_ellcard_i(a4, a6, T, p)); } static long Fl_ellj_trace(ulong j, ulong p) { ulong a4, a6; Fl_ellj_to_a4a6(j, p, &a4, &a6); return Fl_elltrace(a4, a6, p); } /* Given ordinary E/Fq, a prime ell, and the height of the ell-volcano * containing j(E) (= v_ell(conductor of Z[pi_E]) returns the height of j(E) * on its ell-volcano (= v_ell(conductor of the order End(E)). */ static long Fl_ellheightabovefloor(ulong j, long ell, long e, ulong p) { pari_sp av = avma; GEN Xp, G, phi, phix, j0, j1; long h, i, nj1; if (e==0) return 0; if (j==0 || j==1728%p) return e; phi = ZXX_to_FlxX(polmodular_ZXX(ell, 0, 0, 1), p, 1); phix = FlxY_evalx(phi, j, p); Xp = Flx_Frobenius(phix, p); G = Flx_gcd(Flx_sub(Xp, polx_Flx(0), p), phix, p); nj1 = degpol(G); if (nj1 < ell) return 0; if (e==1 || nj1 != ell+1) return e; j1 = Flx_roots(G, p); nj1 = lg(j1)-1; if (nj1 < 3) return 0; j0 = mkvecsmall3(j,j,j); for (h = 1; ; h++) for(i = 1; i <= 3; i++) { GEN P = Flx_div_by_X_x(FlxY_evalx(phi, uel(j1,i), p), uel(j0,i), p, NULL); GEN r = Flx_roots(P, p); if (lg(r) == 1) return gc_long(av, h); j0[i] = j1[i]; j1[i] = r[1]; } } /* Given an ordinary elliptic curve E/Fp and an integer h, returns * D = disc(End(E)) assuming h(D) = h, using the approach sketched in * Remark 13. If the algorithm returns 0 it has proved that h(D) != h, but it * is under no obligation to do so and is allowed to return any value when the * assumption h(d) = h is false. */ static long Fl_end13(ulong j, ulong h, ulong p) { ulong D0, v, h0; long i, lL, lc, lD, nc; GEN D, DF, cs, L, vP, vE; ulong t = Fl_ellj_trace(j, p); D0 = coredisc2u_fact(factoru(4*p-t*t), -1, &vP, &vE); h0 = itou(classno(stoi(-D0))); if (h % h0 != 0) return 0; h /= h0; D = divisorsu_fact_factored(mkmat2(vP,vE)); DF = gel(D,2); D = gel(D,1); lD = lg(D); v = D[lD-1]; cs = cgetg(lD,t_VECSMALL); nc = 0; for (i = 1; i < lD; i++) { GEN F = gel(DF,i); ulong w = uquadclassnoF_fact(D0, -1, gel(F,1), gel(F,2)); if (w == h) uel(cs,++nc) = v / uel(D,i); } if (nc==0) return 0; if (nc==1) { v /= uel(cs,1); return -D0*v*v; } L = cgetg(nc+1, t_VEC); for (i = 1; i <= nc; i++) gel(L,i) = gel(factoru(uel(cs,i)), 1); L = vecsmall_uniq(shallowconcat1(L)); lL = lg(L); lc = nc+1; for (i = 1; i < lL; i++) { ulong ell = L[i]; long k, e = Fl_ellheightabovefloor(j, ell, z_lval(v,ell), p); for (k = 1; k < lc; k++) if(cs[k] && z_lval(cs[k], ell) != e) { cs[k] = 0; nc--; } if (nc==0) return 0; if (nc==1) { for (k = 1; k < lc; k++) if (cs[k]) { v /= uel(cs,k); return -D0*v*v; } } } return 0; } INLINE int RgX_is_monic_ZX(GEN pol) { return RgX_is_ZX(pol) && ZX_is_monic(pol); } long polisclass(GEN H) { pari_sp av = avma, btop; long h = degpol(H), hl, i, pmin, vH = varn(H), vh; double lmin; ulong p; GEN h2list; forprime_t T; if (typ(H)!= t_POL) pari_err_TYPE("polsisclass",H); if (h <= 0 || !RgX_is_monic_ZX(H)) return 0; vh = vals(h); h2list = cgetg(vh+2, t_VECSMALL); hl = 1; for (i = 0; i <= vh; i++) { ulong d = 1UL< r) { if (--s < T) T = s; } else s++; H = zero_zv(r + 1 - T); for (k = 1, s = 0; k <= 2*r; k++) /* (x^-T * Hodge) += x^s, s - T >= 0 */ if (w[k] > r) s--; else { H[s + 1 - T]++; s++; } *pTT = -T; return zv_to_zx(H, evalvarn(0)); } /* Conversion from [val] to cyclotomic factorization: t_VECSMALL E encodes * prod_i polcyclo(i)^E[i] */ static GEN al2cyE(GEN v) { GEN dv, E, F, w; long N, i, j, l = lg(v); if (l == 1) return cgetg(1, t_VECSMALL); w = Q_remove_denom(v, &dv); if (!dv) return mkvecsmall(l-1); N = itou(dv); w = ZV_to_Flv(w, N); vecsmall_sort(w); E = zero_zv(N); /* to record polcyclo(i)^E[i] */ F = cgetg(l, t_VECSMALL); /* to check input */ for (i = j = 1; i < l; i++) { long k, m = w[i]; if (!m) { E[1]++; F[j++] = 0; } else if (N % m == 0) { long d = N/m, km; E[d]++; for (k = 1, km = m; k <= d; k++, km += m) if (ugcd(k,d) == 1) F[j++] = km; } } setlg(F,j); vecsmall_sort(F); return gequal(w,F)? E: NULL; } static int cyE_intersect(GEN a, GEN b) { long i, l = minss(lg(a), lg(b)); for (i = 1; i < l; i++) if (a[i] && b[i]) return 1; return 0; } static GEN get_CYCLOE(GEN val, GEN vbe) { GEN Ea = al2cyE(val), Eb = al2cyE(vbe); if (!Ea || !Eb || cyE_intersect(Ea, Eb)) pari_err_TYPE("hgminit [not a Q motive]", mkvec2(val,vbe)); return mkvec2(Ea, Eb); } /* R[n/d] += mu(d) * r, for all d | n */ static void moebiusadd(GEN R, long n, long r) { if (r) { GEN D = divisorsu_moebius(gel(factoru(n), 1)); long j, l = lg(D); R[n] += r; /* d = 1 */ for (j = 2; j < l; j++) { long d = D[j]; R[n / labs(d)] += d < 0? -r: r; } } } /* Use Phi_n(x) = Prod_{d|n} (x^d-1)^mu(n/d); Ea/Eb in terms of (x^i-1) */ static GEN get_VPOLGA(GEN E) { GEN Ea = gel(E,1), Eb = gel(E,2), R; long i, la = lg(Ea), lb = lg(Eb), n = maxuu(la, lb) - 1; pari_sp av; R = zero_zv(n); av = avma; for (i = 1; i < la; i++) moebiusadd(R, i, Ea[i]); for (i = 1; i < lb; i++) moebiusadd(R, i, -Eb[i]); for (i = n; i; i--) if (R[i]) break; setlg(R,i+1); set_avma(av); return R; } /* disc(polcyclo(n)) modulo squares */ static GEN cyclodiscmodsq(ulong n) { long e, s; ulong p; if (n <= 2) return gen_1; if ((n & 3) == 2) n >>= 1; e = uisprimepower(n, &p); if (!e) return gen_1; if (p == 2) return e == 2? gen_m1: gen_1; s = odd(e)? p: 1; if ((p & 3) == 3) s = -s; return stoi(s); } /* E encodes prod polcyclo(i)^E(i) */ static GEN discprod(GEN E) { long i, j, l = lg(E); GEN P = cgetg(l, t_VEC); for (i = 3, j = 1; i < l; i++) /* can skip polcyclo(1 or 2) */ if (odd(E[i])) gel(P,j++) = cyclodiscmodsq(i); setlg(P,j); return ZV_prod(P); } static GEN QV_normalize(GEN a) { long l = lg(a), i; GEN v = cgetg(l, t_VEC); for (i = 1; i < l; i++) { GEN c = gel(a, i); if (!is_rational_t(typ(c))) pari_err_TYPE("hgminit [not rational params]",c); gel(v, i) = gfrac(c); } return sort(v); } static GEN mangoldtexp(long n) { GEN D = divisorsu_moebius(gel(factoru(n),1)), P = gen_1; long i, l = lg(D); for (i = 1; i < l; i++) { /* prod (n/d) ^ (n/d mu(d)) */ long mud = D[i], nd = n / mud; /* mud = mu(d) * d */ P = gmul(P, powis(utoi(labs(nd)), nd)); } return P; } static GEN E2exp(GEN E) { long n, r, l = lg(E); GEN P = gen_1; for (n = 1; n < l; n++) if ((r = E[n])) P = gmul(P, gpowgs(mangoldtexp(n), r)); return P; } static long get_b1(GEN CYCLOE) { return gel(CYCLOE,2)[1]; } static GEN get_u(GEN al, GEN be, GEN CYCLOE, GEN VPOLGA, long DEG, long WT); /* [a,b] = alpha, beta */ static GEN initab(GEN a, GEN b) { GEN VALNUM, VALDEN, VBENUM, VBEDEN, CYCLOE, SIGNPAR; GEN BAD, HODGE, VPOLGA, res; long j, WT, TT, OFFMPOL, l = lg(a), DEG = l-1, SWAP = 0; if (lg(b) != l) pari_err_TYPE("hgminit [#al != #be]", mkvec2(a,b)); if (l == 1) pari_err_TYPE("hgminit [#al = 0]", mkvec2(a,b)); a = QV_normalize(a); b = QV_normalize(b); if (isintzero(gel(a,1))) { if (isintzero(gel(b,1))) pari_err_TYPE("hgminit [nonempty intersection]", mkvec2(a,b)); swap(a, b); SWAP = 1; } VALNUM = cgetg(l, t_VECSMALL); VALDEN = cgetg(l, t_VECSMALL); VBENUM = cgetg(l, t_VECSMALL); VBEDEN = cgetg(l, t_VECSMALL); for (j = 1; j < l; j++) { Qtoss(gel(a,j), &VALNUM[j], &VALDEN[j]); Qtoss(gel(b,j), &VBENUM[j], &VBEDEN[j]); } BAD = negi(lcmii(ZV_lcm(zv_to_ZV(VALDEN)), ZV_lcm(zv_to_ZV(VBEDEN)))); HODGE = hodge(a, b, &TT); WT = degpol(HODGE); CYCLOE = get_CYCLOE(a, b); VPOLGA = get_VPOLGA(CYCLOE); SIGNPAR = odd(WT)? gen_1: discprod(gel(CYCLOE, odd(DEG)? 2: 1)); OFFMPOL = (get_b1(CYCLOE) - zv_sum(VPOLGA)) >> 1; res = cgetg(13, t_VEC); gel(res, 1) = a; gel(res, 2) = b; gel(res, 3) = CYCLOE; gel(res, 4) = VBENUM; gel(res, 5) = VBEDEN; gel(res, 6) = gdiv(E2exp(gel(CYCLOE,1)), E2exp(gel(CYCLOE,2))); /*MVALUE*/ gel(res, 7) = VPOLGA; gel(res, 8) = BAD; gel(res, 9) = HODGE; gel(res, 10) = get_u(a, b, CYCLOE, VPOLGA, DEG, WT); gel(res, 11) = SIGNPAR; gel(res, 12) = mkvecsmall3(OFFMPOL, TT, SWAP); return res; } static int checkhgm(GEN v) { return typ(v) == t_VEC && lg(v) == 13 && typ(gel(v,12)) == t_VECSMALL && lg(gel(v,12)) == 4; } /* accessors */ static GEN hgm_get_VAL(GEN v) { return gel(v, 1); } static GEN hgm_get_VBE(GEN v) { return gel(v, 2); } static GEN hgm_get_CYCLOE(GEN v) { return gel(v, 3); } static GEN hgm_get_VBENUM(GEN v) { return gel(v, 4); } static GEN hgm_get_VBEDEN(GEN v) { return gel(v, 5); } static GEN hgm_get_MVALUE(GEN v) { return gel(v, 6); } static GEN hgm_get_VPOLGA(GEN v) { return gel(v, 7); } static GEN hgm_get_BAD(GEN v) { return gel(v, 8); } static GEN hgm_get_HODGE(GEN v) { return gel(v, 9); } static GEN hgm_get_U(GEN v) { return gmael(v, 10,1); } static GEN hgm_get_U0(GEN v) { return gmael(v, 10,2); } static GEN hgm_get_SIGNPAR(GEN v) { return gel(v, 11); } static long hgm_get_DEG(GEN v) { return lg(hgm_get_VAL(v))-1; } static long hgm_get_OFFMPOL(GEN v) { return gel(v, 12)[1]; } static long hgm_get_TT(GEN v) { return gel(v, 12)[2]; } static long hgm_get_SWAP(GEN v) { return gel(v, 12)[3]; } static long hgm_get_WT(GEN v) { return degpol(hgm_get_HODGE(v)); } /***************************************************************/ /* PART II: p-adic functions */ /***************************************************************/ /* Compute p^k u_{pk+r} for 0 <= r < p and 0 <= k < ell */ static GEN compu(long ell, long p, long D) { GEN v = cgetg(p + 1, t_VEC), w = cgetg(ell + 2, t_VEC); long s, t, k, i, L = ell * p; gel(v,1) = gel(v,2) = cvtop(gen_1, stoi(p), D); for (i = 2; i < p; i++) gel(v, i+1) = gdivgu(gel(v, i), i); gel(w, 1) = shallowcopy(v); for (k = s = 1, t = p; k <= L; k++) { gel(v, s) = gdivgu(gadd(gel(v, t), gel(v, s)), k + p - 1); if (++s > p) { s = 1; gel(w, k/p + 1) = shallowcopy(v); } if (++t > p) t = 1; } return w; } /* [binom(x + k - 1, k) k! p^k, k = 1..N], x a t_PADIC */ static GEN binomfact(GEN x, long N) { GEN z, v = cgetg(N+1, t_VEC); long i; gel(v,1) = z = leafcopy(x); setvalp(z, valp(z)+1); for (i = 1; i < N; i++) { gel(v, i+1) = z = gmul(z, gaddgs(x, i)); setvalp(z, valp(z) + 1); } return v; } /* gamma(m /p^f-1) mod p^dfp, m = m0 (mod p), x = (m\p + m0*p^(f-1)) / p^f-1 */ static ulong sumbinom(GEN v, GEN x, long m0, long N, ulong pD) { pari_sp av = avma; GEN C = binomfact(x, N), S = gmael(v, 1, m0+1); /* k = 0 */ long k; for (k = 1; k <= N; k++) S = gadd(S, gmul(gel(C,k), gmael(v, k+1, m0+1))); return gc_ulong(av, Rg_to_Fl(S, pD)); } /* x * y mod p^D, y a p-unit */ static GEN umultop(ulong x, ulong y, GEN gp, GEN gpD, long D) { ulong pD = gpD[2]; long v; GEN z; if (!x) return zeropadic_shallow(gp, D); v = u_lvalrem(x, gp[2], &x); if (x >= pD) x %= pD; z = cgetg(5, t_PADIC); z[1] = evalprecp(D) | evalvalp(v); gel(z,2) = gp; gel(z,3) = gpD; gel(z,4) = utoi( Fl_mul(x, y, pD) ); return z; } /* Compute all gamma(m/(p^f-1)) mod p^D for 0 <= m < p^f-1 */ static GEN precomp(ulong p, long f, long D) { pari_sp av, av2; GEN vall, gp, gpD, vres, x, l2; ulong m, m0, m1, M, q, v, vpo, vva, vpowv, pf1; ulong N = ceildivuu(D * p, p-1), pf = upowuu(p,f), pD = upowuu(p, D), pM; ulong ga12, S, iQ, Q = pf - 1; if (!pD || !pf) pari_err_OVERFLOW("hgmprecomp"); iQ = D <= f? pD - 1: Fl_inv(Q, pD); vres = cgetg(pf, t_VECSMALL); vres[1] = 1; av = avma; gp = utoipos(p); gpD = utoipos(pD); vall = compu(N, p, D); if (p == 2) { if (f == 1) return gc_const(av, vres); av2 = avma; for (m = 1; m < Q; m++, set_avma(av2)) { m0 = m&1, m1 = m >> 1; x = umultop(m1 + (m0 << (f - 1)), iQ, gp, gpD, D); vres[m+1] = sumbinom(vall, x, m0, N, pD); } return gc_const(av, vres); } q = Q >> 1; pf1 = pf / p; vva = z_lval(Q, 2); vpowv = 1 << vva; av2 = avma; for (m = 1; m <= q; m += 2, set_avma(av2)) { if (f > 1) { m0 = m%p; m1 = m / p; M = m1 + m0 * pf1; } else M = m0 = m; x = umultop(M, iQ, gp, gpD, D); vres[m+1] = S = sumbinom(vall, x, m0, N, pD); if (!odd(m0)) S = pD - S; vres[pf - m] = Fl_inv(S, pD); } for (m = vpowv; m <= q; m += 2*vpowv, set_avma(av2)) { if (f > 1) { m0 = m%p; m1 = m / p; M = m1 + m0 * pf1; } else M = m0 = m; x = umultop(M, iQ, gp, gpD, D); vres[m+1] = S = sumbinom(vall, x, m0, N, pD); if (!odd(m0)) S = pD - S; vres[pf - m] = Fl_inv(S, pD); } l2 = gmulgu(Qp_log(cvtop(gen_2, gp, D)), p - 1); ga12 = Fl_inv(Rg_to_Fl(Qp_gamma(cvtop(ghalf, gp, D)), pD), pD); pM = maxuu(pD, pf); av2 = avma; for (v = 1, vpo = 2; vpo < Q; v++, vpo <<= 1) { if (v == vva) continue; for (m = vpo; m <= q; m += 2*vpo, set_avma(av2)) { ulong ms2 = (m >> 1) + 1; ulong t = Fl_mul(Fl_mul(vres[ms2], vres[ms2+q], pD), ga12, pD); GEN mp; /* - m = -m1 * p + m0, 1 <= m0 <= p */ m0 = p - m%p; m1 = m/p + 1; M = pM + m1 - m0 * pf1; mp = umultop(M, iQ, gp, gpD, D); S = Rg_to_Fl(gmul(Qp_exp(gmul(mp, l2)), shifti(utoi(t), m0-1)), pD); vres[m+1] = S; if (odd(m0)) S = pD - S; vres[pf - m] = Fl_inv(S, pD); } } return gc_const(av, vres); } static long get_pad(ulong p) { switch(p) { case 2: return 18; case 3: return 11; case 5: return 8; } if (p <= 37) return 6; if (p <= 251) return 4; if (p <= 65521) return 2; return 1; } static GEN Flv_red(GEN z, ulong p) { long i, l = lg(z); GEN x = cgetg(l, t_VECSMALL); for (i=1; i 0, p prime, need result mod p^dfp */ static GEN doprecomp(ulong p, long f, long dfp) { GEN t, T; long F; /* can compute cache mod p^F < 2^BIL */ ulong m, n, q; if (f > 3 || (F = get_pad(p)) < dfp) return precomp(p, f, dfp); if (f == 3) { T = HGMDATA3; if (!T) T = HGMDATA3 = block0(100); if (p >= (ulong)lg(T)) return precomp(p, f, dfp); t = gel(T,p); if (typ(t) == t_INT) t = gel(T,p) = gclone(precomp(p, f, F)); return (F == dfp)? t: Flv_red(t, upowuu(p, dfp)); } /* f <= 2, dfp <= F */ T = HGMDATA2; if (!T) T = HGMDATA2 = block0(1000); if (p >= (ulong)lg(T)) return precomp(p, f, dfp); t = gel(T,p); if (typ(t) == t_INT) { if (f == 1) return precomp(p, f, dfp); t = gel(T,p) = gclone(precomp(p, f, F)); } /* t = precomp(p, 2, F) = HGMDATA2[p] */ if (f == 2) return (F == dfp)? t: Flv_red(t, upowuu(p, dfp)); /* f = 1 */ T = cgetg(p, t_VECSMALL); q = upowuu(p, dfp); for (m = n = 1; m < p; m++, n += p+1) T[m] = uel(t, n) % q; return T; } /* W[N] = teich(N ^ (N * sign(VPOLGA[N]))) mod p^2 */ static GEN teichmodp2(GEN VPOLGA, ulong p, ulong p2) { ulong pN; long c, l, N; GEN W = cgetg_copy(VPOLGA,&l); /* W[N] = teich(N)^N */ for (N = 1, pN = p; N < l; N++, pN += p) if ((c = VPOLGA[N])) { long N0; (void)z_lvalrem(N, p, &N0); if (c < 0) N0 = Fl_inv(N0 % p, p); W[N] = Fl_powu(N0, pN, p2); } return W; } /* GF[i] = i! mod p^2 */ static GEN get_GF(ulong p, ulong p2) { GEN F = cgetg(p, t_VECSMALL); ulong i; F[1] = 1; F[2] = 2; for (i = 3; i < p; i++) F[i] = Fl_mul(F[i-1], i, p2); return F; } /* p odd, return v s.t. v[i] = 1/i mod p, i < p/2 */ static GEN Flv_inv_p2(ulong p) { long i, g = pgener_Fl(p), ph = (p >> 1); GEN v = cgetg(ph + 1, t_VECSMALL); pari_sp av = avma; GEN w = cgetg(ph, t_VECSMALL); w[1] = g; for (i = 2; i < ph; i++) w[i] = Fl_mul(w[i-1], g, p); /* w[i]=g^i */ for (i = 1; i < ph; i++) { long x = w[i], y = w[ph - i]; /* g^(-i) = - g^(ph - i) */ if (x > ph) v[p - x] = y; else v[x] = p - y; /* 1/(-x) = y, 1/x = -y */ } v[1] = 1; return gc_const(av, v); } /* H[i] = i * (H_i - ((p-1)! + 1) / p) mod p */ static GEN get_GH(GEN F, ulong p) { long i, g, ph = p >> 1; GEN H = cgetg(p, t_VECSMALL), v = Flv_inv_p2(p); H[p-1] = (F[p-1] + 1) / p; g = p - H[p-1]; for (i = 1; i <= ph; i++) { long c = g = Fl_add(g, v[i], p); H[i] = c = Fl_mul(c, i, p); H[p-1 - i] = Fl_neg(Fl_add(c, g, p), p); } return H; } /* p odd, GPB[m+1] = Gamma_p(m/(p-1)) mod p^2 */ static GEN doprecompmodp2(ulong p, ulong p2) { GEN F = get_GF(p, p2), H = get_GH(F, p), GPV = cgetg(p, t_VECSMALL); ulong r; for (r = 1; r < p; r++) { long t = Fl_mul(F[r], 1 + p * H[r], p2); GPV[p - r] = odd(r)? t: p2 - t; } return GPV; } /***************************************************************/ /* PART III: Motive initializations depending on p */ /***************************************************************/ static GEN get_L1(GEN hgm, long PFM1, long f) { GEN VBEDEN = hgm_get_VBEDEN(hgm); GEN VBENUM = hgm_get_VBENUM(hgm), v; long DEG = hgm_get_DEG(hgm), j; v = const_vecsmall(PFM1, f * hgm_get_TT(hgm)); for (j = 1; j <= DEG; j++) if (PFM1 % VBEDEN[j] == 0) { long t = ((-(PFM1 / VBEDEN[j]) * VBENUM[j]) % PFM1) + 1; if (t <= 0) t += PFM1; v[t] -= f; } return v; } /* Stickelberger valuation: L0(p, f, m), power of (-p) * = f * OFFMPOL - sum_{e < f, N < l} gamma_N [N p^e m / (p^f-1)]*/ /* 1) amortized (all m < p^f-1), good when p >> N log N. Assume f=1 */ static GEN get_L0(GEN hgm, ulong PM1) { GEN perm, vt, vc, VL0, VPOLGA = hgm_get_VPOLGA(hgm); long w, S, c, d, j, N, m, l = lg(VPOLGA), D = (l * (l-1)) >> 1; vt = cgetg(D+1, t_VECSMALL); vc = cgetg(D+1, t_VECSMALL); for (N = 2, c = 1; N < l; N++) if (VPOLGA[N]) { ulong Q; long q; for (q = 1, Q = 0; q <= N; q++, Q += PM1, c++) { vt[c] = ceildivuu(Q, N); vc[c] = VPOLGA[N]; } } setlg(vt,c); setlg(vc,c); perm = vecsmall_indexsort(vt); vt = vecsmallpermute(vt, perm); vc = vecsmallpermute(vc, perm); w = vt[1]; for (j = 2, d = 1; j < c; j++) if (vt[j] == w) vc[d] += vc[j]; else { d++; vt[d] = w = vt[j]; vc[d] = vc[j]; } d++; vt[d] = PM1; vc[d] = 0; /* sentinels */ VL0 = cgetg(PM1+1, t_VECSMALL); S = hgm_get_OFFMPOL(hgm); for (j = 1; j < d; j++) { for (m = vt[j]; m < vt[j+1]; m++) VL0[m+1] = S; S -= vc[j+1]; } return VL0; } /* 2) direct computation (single m), good when p << N log N */ static long L0(GEN hgm, ulong p, long f, long PFM1, long m) { GEN VPOLGA = hgm_get_VPOLGA(hgm); long e, S = hgm_get_OFFMPOL(hgm) * f, l = lg(VPOLGA); ulong pem; for (e = 0, pem = m; e < f; e++, pem *= p) { long N, s = 0; ulong Npem; for (N = 1, Npem = pem; N < l; N++, Npem += pem) if (VPOLGA[N]) s += VPOLGA[N] * (long)(Npem / PFM1); S -= s; } return S; } static GEN get_teich1(GEN VPOLGA, GEN ZP, ulong p) { long l = lg(VPOLGA), N; GEN v = zerovec(l - 1); for (N = 2; N < l; N++) if (VPOLGA[N]) { long N0; (void)z_lvalrem(N, p, &N0); gel(v, N) = teich(gaddsg(N0, ZP)); } return v; } static GEN get_teich(GEN VPOLGA, GEN ZP, ulong p, long f, long PFM1) { GEN v, Q; long l, N; if (f == 1) return get_teich1(VPOLGA, ZP, p); l = lg(VPOLGA); v = zerovec(l - 1); Q = utoipos(PFM1 / (p - 1)); for (N = 2; N < l; N++) if (VPOLGA[N]) { long N0; (void)z_lvalrem(N, p, &N0); gel(v,N) = Qp_sqrtn(gdivsg(N0, teich(gaddsg(N0,ZP))), Q, NULL); } return v; } /* compute N^{-[N*s-1-(N*s-1)\p]}, N*s=a/(p^f-1) with a=N*m*p^e */ static GEN gapnpow(GEN T, long p, long f, long PFM1, long N, ulong Nmpe) { GEN Vr; long Nm, i, S; if (f == 1) return gpowgs(T, Nmpe); Nm = Fl_neg(Nmpe, PFM1); Vr = cgetg(f + 1, t_VECSMALL); for (i = 1; i <= f; i++) { Vr[i] = Nm % p; Nm /= p; } S = Vr[1]; for (i = 1; i < f; i++) S = Vr[f + 1 - i] + p * S; return gdiv(gpowgs(T, S), powuu(N, Vr[1])); } /* prod_{j = 1}^DEG prod_{e = 0}^{f - 1} * gamma_p({p^e * (VAL[j] + m/(p^f-1))}) / * gamma_p({p^e * (VBE[j] + m/(p^f-1))}), a p-unit. 0 <= m < p^f-1 */ static GEN hgmC(GEN VPOLGA, GEN GPV, GEN TEICH, ulong p, long f, ulong PFM1, ulong m, long dfp) { GEN r = gen_1; long c, e, N, l = lg(VPOLGA); ulong Nmpe, mpe; for (e = 0, mpe = m; e < f; e++, mpe = Fl_mul(mpe, p, PFM1)) for (N = 1, Nmpe = mpe; N < l; N++, Nmpe = Fl_add(Nmpe, mpe, PFM1)) if ((c = VPOLGA[N])) { /* Gamma_p(frac(N*m*p^e/(p^f-1))) */ GEN z = utoi(GPV[Nmpe + 1]); if (N > 1) z = gmul(z, gapnpow(gel(TEICH, N), p, f, PFM1, N, Nmpe)); /* z = prod_{0 <= j < N} Gamma_p( frac(p^e * (m/(p^f-1) + j/N)) ) */ r = gmul(r, gpowgs(z, c)); } if (typ(r) != t_PADIC) r = cvtop(r, utoipos(p), dfp); return r; } /* Same modulo p^2, Wm[N] = teich(N^(sign(VPOLGA[N]) * m)) */ static ulong hgmCmodp2(GEN VPOLGA, GEN Wm, GEN GPV, ulong PFM1, ulong m, ulong p2) { long l = lg(VPOLGA), c, N; ulong res = 1, Nm; for (N = 1, Nm = m; N < l; N++, Nm = Fl_add(Nm, m, PFM1)) if ((c = VPOLGA[N])) { ulong z; if (c > 0) z = GPV[Nm + 1]; else { c = -c; if (!Nm) z = 1; else { z = GPV[PFM1 + 1 - Nm]; if (!odd(Nm)) z = p2 - z; /* GPV[Nm+1]^(-1) by reflection formula */ } } if (N > 1) z = Fl_mul(z, Wm[N], p2); z = Fl_powu(z, c, p2); /* z = (GPV[Nm+1] * teich(N^m))^VPOLGA[N] */ res = res == 1? z: Fl_mul(res, z, p2); } return res; } /***************************************************************/ /* PART IV: Motive functions depending on p, t */ /***************************************************************/ static long get_dfp(GEN hgm, long p, long f) { long DEG = hgm_get_DEG(hgm), WT = hgm_get_WT(hgm); long dfp = ceil(log((double)2*DEG) / log((double)p) + f * (WT * 0.5 ) + 1e-5); if (p == 2) dfp++; /* FIXME: why ? */ return dfp; } /* V being a vecsmall, compute all p^TT*hgmC(m)/hgmC(0) for indices in V */ static GEN hgmCall(GEN hgm, ulong p, long f, long dfp, GEN V) { GEN v, c, GPV, VL0, VL1, TEICH, ZP = zeropadic_shallow(utoipos(p), dfp); GEN VPOLGA = hgm_get_VPOLGA(hgm); ulong i, PFM1 = upowuu(p, f) - 1, lV = V? lg(V): PFM1+1; long l0, fTT = f * hgm_get_TT(hgm); GPV = doprecomp(p, f, dfp); VL0 = (V && f == 1)? get_L0(hgm, PFM1): NULL; VL1 = get_L1(hgm, PFM1, f); TEICH = get_teich(VPOLGA, ZP, p, f, PFM1); l0 = hgm_get_OFFMPOL(hgm) * f; if (V) { v = cgetg(lV, t_VEC); i = 1; } else { v = cgetg(lV+1, t_POL); v[1] = evalsigne(1)|evalvarn(0); gel(v,2) = c = powuu(p, fTT); /* m = 0 */ i = 2; } for (; i < lV; i++) { long m = V? V[i]: i-1; long L = VL0? VL0[m+1]: L0(hgm, p, f, PFM1, m); long e = L + VL1[m+1]; if (!V && e >= dfp) c = gen_0; else { /* FIXME: dfp is fishy in Jordantame, don't trust if V = NULL */ pari_sp av = avma; c = hgmC(VPOLGA, GPV, TEICH, p, f, PFM1, m, dfp); setvalp(c, e); if (odd(L ^ l0)) c = gneg(c); c = gerepileupto(av, padic_to_Q(c)); } gel(v, V? i: i+1) = c; } return v; } /* Same mod p^2, f = 1 */ static GEN hgmCallmodp2(GEN hgm, ulong p) { GEN C, GPV, VL0, VL1, W1, Wm, VPOLGA = hgm_get_VPOLGA(hgm); long l = lg(VPOLGA), TT = hgm_get_TT(hgm); ulong m, PFM1 = p - 1, p2 = p * p; if (p & HIGHMASK) pari_err_OVERFLOW("hgmCallmodp2"); VL0 = get_L0(hgm, PFM1); VL1 = get_L1(hgm, PFM1, 1); W1 = teichmodp2(VPOLGA, p, p2); Wm = shallowcopy(W1); GPV = doprecompmodp2(p, p2); C = cgetg(PFM1+2, t_VECSMALL); C[1] = evalvarn(0); C[2] = TT > 1? 0: (TT == 1? p : 1); /* m = 0 */ for (m = 1; m < PFM1; m++) { long e = VL0[m + 1] + VL1[m + 1], j; ulong c; if (e >= 2) c = 0; else { c = hgmCmodp2(VPOLGA, Wm, GPV, PFM1, m, p2); if (odd(VL0[m + 1] ^ VL0[1])) c = Fl_neg(c, p2); if (e == 1) c = (c % p) * p; } C[m + 2] = c; for (j = 2; j < l; j++) if (VPOLGA[j]) Wm[j] = Fl_mul(Wm[j], W1[j], p2); } return C; } /* 1 / (1-q) ~ 1 + q + ... + q^n; n >= 1 */ static ulong inv(ulong q, long n) { ulong z = q + 1; long i; for (i = 1; i < n; i++) z = z * q + 1; return z; } /* General H function: C(teich(f + O(p^dfp))) / (1 - p^f) */ static GEN hgmH(GEN C, long p, long f, long dfp, GEN t) { GEN q = powuu(p, dfp), z; long n; (void)Q_lvalrem(t, p, &t); z = Rg_to_Fp(t, q); z = Zp_teichmuller(z, utoipos(p), dfp, q); z = FpX_eval(C, z, q); n = dfp / f; if (!(dfp % f)) n--; z = Fp_mulu(z, inv(upowuu(p,f), n), q); return Fp_center(z, q, shifti(q,-1)); } static GEN hgmHmodp2(GEN C, ulong p, GEN t) { ulong p2 = p * p, wt = Fl_powu(Rg_to_Fl(t, p2), p, p2); return stoi( Fl_center(Fl_mul(Flx_eval(C, wt, p2), 1+p, p2), p2, p2 >> 1) ); } enum { C_OK = 0, C_FAKE, C_BAD, C_TAME0, C_TAME1}; static GEN hgmU(GEN hgm, long p, long f, GEN t, long dfp); static long hgmclass(GEN hgm, long p, GEN t); static GEN hgmtrace(GEN hgm, long p, long f, GEN t, long c) { long dfp = get_dfp(hgm, p, f); if (c == C_FAKE) return hgmU(hgm, p, f, t, dfp); if (f == 1 && dfp <= 2) return hgmHmodp2(hgmCallmodp2(hgm, p), p, t); return hgmH(hgmCall(hgm, p, f, dfp, NULL), p, f, dfp, t); } static GEN F2v_factorback(GEN E) { long i, l = lg(E); GEN c = gen_1; for (i = 1; i < l; i++) if (odd(E[i])) c = muliu(c, i); return c; } static long Q_krois(GEN T, long p) { return krouu(Rg_to_Fl(T, (p == 2)? 8: p), p); } static long hgmsign(GEN hgm, long p, GEN t) { GEN u; if (odd(hgm_get_WT(hgm))) return 1; t = ginv(t); u = gmul(gsubsg(1, t), hgm_get_SIGNPAR(hgm)); return odd(hgm_get_DEG(hgm))? -Q_krois(u, p): Q_krois(gmul(gneg(t), u), p); } /* conductor of the central character */ static GEN hgmcharcond(GEN hgm, GEN t) { GEN u; if (odd(hgm_get_WT(hgm))) return gen_1; t = ginv(t); u = gmul(gsubsg(1, t), hgm_get_SIGNPAR(hgm)); if (!odd(hgm_get_DEG(hgm))) u = gmul(gneg(t), u); if (typ(u) == t_FRAC) u = mulii(gel(u,1), gel(u,2)); return gequal0(u) ? gen_1 : coredisc(u); } /* valuations of central character conductor at BAD */ static GEN get_achi(GEN hgm, GEN t, GEN BAD) { long i, l = lg(BAD); GEN Nchi = hgmcharcond(hgm, t), v = cgetg(l, t_VECSMALL); for (i = 1; i < l; i++) v[i] = Z_lval(Nchi, BAD[i]); return v; } /* [a,a*r, ..., a*r^n] */ static GEN upowers_u(ulong r, long n, ulong a) { long i, l = n + 2, t = a; GEN v = cgetg(l, t_VECSMALL); for (i = 1; i < l; i++) { v[i] = t; t *= r; } return v; } static GEN powers_u(ulong r, long n, ulong a) { long i, l = n + 2; GEN v = cgetg(l, t_VEC), t = utoi(a); for (i = 1; i < l; i++) { gel(v,i) = t; t = muliu(t, r); } return v; } static GEN mkpowers(long p, long d, long WT) { ulong q, r; if (WT == 0) q = r = 1; else if (!odd(d)) q = r = upowuu(p, WT); else if (WT == 1) { q = 1; r = p; } else { q = upowuu(p, WT >> 1); r = q*q; if (odd(WT)) r *= p; } return powers_u(r, (d-1)>>1, q); } /* complete local factor E (of degree d) at p using functional equation * E(T) = SIGN p^(WT*d)/2 T^d E(1/(p^WT*T)) */ static GEN Efuneq(GEN E, long p, long d, long WT, long SIGN, long B) { long j = maxss(d - B, 0), k = d + 1 - j, nE = lg(E)-1, l = (d + 1) >> 1; GEN T = cgetg(k + 1, t_VEC), vp = mkpowers(p, d, WT); for (; j < l; j++, k--) { GEN q = gel(vp,l-j); if (SIGN < 0) q = negi(q); /* q = SIGN * p^(WT(d-2*j) / 2) */ gel(T, k) = gmul(q, RgX_coeff(E, j)); } for (; k >= nE; k--) gel(T, k) = gen_0; for (; k > 0; k--) gel(T, k) = gel(E, k+1); return RgV_to_RgX(T,0); } static long hgmclass(GEN hgm, long p, GEN t) { GEN BAD = hgm_get_BAD(hgm); long ap, bp; if (!umodiu(BAD, p)) { long v = Q_lval(t, p); if (v && v + Q_lval(hgm_get_MVALUE(hgm), p) == 0) { GEN N = hgmcharcond(hgm, t); if (umodiu(N, p)) return C_FAKE; /* a(chi) = 0 */ } return C_BAD; } if (typ(t) == t_INT) { ap = umodiu(t, p); if (!ap) return C_TAME0; bp = 1; } else { ap = umodiu(gel(t,1), p); if (!ap) return C_TAME0; bp = umodiu(gel(t,2), p); if (!bp) return C_TAME0; } return ap == bp? C_TAME1 : C_OK; } /* p good or Tame1; return local factor at p: 1/E + O(x^(B+1)); t a t_VEC, * C a t_VECSMALL giving their class. */ static GEN frobpoltrunc(GEN hgm, GEN t, long c, long p, long B, long *pF) { long DEG = hgm_get_DEG(hgm), WT = hgm_get_WT(hgm); long D = isint1(t)? (odd(WT) ? DEG - 2 : DEG - 1): DEG; long f, mi, m, q = upowuu(p, WT >> 1); GEN E, s; mi = minss(B, (c == C_FAKE)? D: D >> 1); m = (mi == D && c == C_TAME1 && !odd(DEG))? mi: mi+1; s = cgetg(m+1, t_POL); s[1] = evalsigne(1)|evalvarn(0); for (f = 1; f < m; f++) gel(s, f+1) = negi( hgmtrace(hgm, p, f, t, c) ); s = RgX_renormalize_lg(s, m+1); *pF = 0; s = RgXn_expint(s, m); if (mi == D) return s; if (c == C_TAME1) { long SIGN = kroiu(hgm_get_U(hgm), p); if (odd(DEG)) E = Efuneq(s, p, DEG-1, WT, SIGN, B); else { GEN T = deg1pol_shallow(stoi(- SIGN * q), gen_1, 0); E = RgXn_mul(s, RgXn_inv(T, m), m); E = Efuneq(E, p, DEG - 2, WT, 1, B); if (!gequal1(t) || !odd(WT)) E = gmul(E, T); } *pF = 1; if (!odd(WT)) { GEN T, u, t0; long v = Q_lvalrem(gsubgs(t, 1), p, &t0); if (!odd(v)) { if (typ(t0) == t_FRAC) t0 = mulii(gel(t0,1), gel(t0,2)); u = coredisc(mulii(t0, hgm_get_U0(hgm))); T = deg1pol_shallow(stoi(-kroiu(u, p) * q), gen_1, 0); E = gmul(E, T); *pF = 0; } } } else { long SIGN = hgmsign(hgm, p, t); E = Efuneq(s, p, DEG, WT, SIGN, B); } return E; } GEN hgmcoef(GEN hgm, GEN t, GEN n) { pari_sp av = avma; GEN T, P, E, F = check_arith_all(n, "hgmcoef"); long i, lP; if (!checkhgm(hgm)) pari_err_TYPE("hgmcoef", hgm); if (!is_rational_t(typ(t))) pari_err_TYPE("hgmcoef",t); if (hgm_get_SWAP(hgm)) t = ginv(t); if (!F) { F = Z_factor(n); P = gel(F,1); } else { P = gel(F,1); if (lg(P) == 1 || signe(gel(P,1)) <= 0) return gen_0; n = typ(n) == t_VEC? gel(n,1): factorback(F); } if (signe(n) <= 0) pari_err_DOMAIN("hgmcoef", "n", "<=", gen_0, n); E = gel(F,2); lP = lg(P); T = gen_1; T = gen_1; for (i = 1; i < lP; i++) { long e, p = itos(gel(P, i)), f = itos(gel(E, i)), c = hgmclass(hgm, p, t); GEN A; if (c == C_BAD) pari_err_IMPL("hgmcoef for bad primes"); A = frobpoltrunc(hgm, t, c, p, f, &e); T = gmul(T, RgX_coeff(RgXn_inv(A, f+1), f)); } return gerepilecopy(av, T); } static GEN count2list(GEN E) { long i, j, r, l = lg(E); GEN v = cgetg(zv_sum(E)+1, t_VECSMALL); for (i = j = 1; i < l; i++) if ((r = E[i])) while(r--) v[j++] = i; setlg(v,j); return v; } static GEN hgminit_i(GEN val, GEN vbe); #if 0 static long minval(GEN F, long p) { long i, d = degpol(F), m = LONG_MAX; for (i = 1; i <= d; i++) m = minss(m, Z_lval(gel(F,i+2), p) / i); return m; } static GEN cycloE_filter(GEN A, long p) { long i, j, l = lg(A); GEN B = shallowcopy(A); if (p < l) for (i = p; i < l; i += p) if (A[i]) { (void)z_lvalrem(i / p, p, &j); B[j] += A[i]; B[i] = 0; } return B; } /* doesn't work because A/B is not valid hypergeometric data */ static GEN eulfacbadnew(GEN hgm, GEN t, long p, long *pe) { GEN AB = hgm_get_CYCLOE(hgm), gp = utoipos(p); GEN A = cycloE_filter(gel(AB,1), p); GEN B = cycloE_filter(gel(AB,2), p); GEN hgmp = hgminit_i(count2list(A), count2list(B)); GEN cF, E, F = hgmeulerfactor(hgmp, t, p, &E); long s, v, d = degpol(F), w = hgm_get_WT(hgm); *pe = 0; if (!d) return pol_1(0); cF = leading_coeff(F); v = Z_lvalrem(cF, p, &cF); if (!is_pm1(cF)) return pol_1(0); s = minval(F, p); if (s) { F = RgX_unscale(F, powis(gp, -s)); v -= s * d; } if ((2 * v) % d || (!odd(w) && v % d)) return F; return RgX_unscale(F, powis(gp, w / 2 - v / d)); } #endif static GEN Jordantameexpo(GEN hgm, long v, GEN t0, long p, long *pe); static GEN hgmeulerfactorlimit(GEN hgm, GEN t, long p, long d, long flag, long *pe) { long c = hgmclass(hgm, p, t); if (c == C_TAME0) { long v = Q_lvalrem(t, p, &t); return Jordantameexpo(hgm, v, t, p, pe); } if (c != C_BAD) return frobpoltrunc(hgm, t, c, p, d, pe); if (flag) { *pe = -1; return gen_0; } else { *pe = 0; return pol_1(0); } } GEN hgmeulerfactor(GEN hgm, GEN t, long p, GEN* pE) { pari_sp av = avma; long e, B; GEN P; if (!checkhgm(hgm)) pari_err_TYPE("hgmeulerfactor", hgm); if (!is_rational_t(typ(t))) pari_err_TYPE("hgmeulerfactor",t); if (hgm_get_SWAP(hgm)) t = ginv(t); B = (long)(hgm_get_DEG(hgm) * log(p)) + 1; P = gerepilecopy(av, hgmeulerfactorlimit(hgm, t, p, B, 1, &e)); if (pE) *pE = stoi(e); return P; } /***********************************************************************/ /* Tame Euler factors */ /***********************************************************************/ /* FIXME: implement properly like RgXn_sqrt */ static GEN RgXn_sqrtnu(GEN h, long f, long e) { if (f == 1) return h; if (f == 2) return RgXn_sqrt(h, e); return ser2rfrac_i(gsqrtn(RgX_to_ser(h, e + 2), utoipos(f), NULL, 0)); } static GEN Jordantame(GEN hgm, GEN t0, long m, long p) { GEN P, T, C, ZP, V; long d, phim, f, j, c, q, qm, dfp; if (m == 1) { long e = hgm_get_WT(hgm) - get_b1(hgm_get_CYCLOE(hgm)); return deg1pol_shallow(negi(powuu(p, (e+1) >> 1)), gen_1, 0); } phim = eulerphiu(m); f = Fl_order(p % m, phim, m); d = phim + 1; /* DEG >= phim >= f */ q = upowuu(p, f); qm = (q - 1) / m; V = cgetg(phim + 1, t_VECSMALL); for (j = c = 1; j < m; j++) if (cgcd(j, m) == 1) V[c++] = j * qm; dfp = get_dfp(hgm, p, f); C = hgmCall(hgm, p, f, dfp, V); ZP = zeropadic_shallow(utoipos(p), dfp); T = teich(gadd(t0, ZP)); P = pol_1(0); for (j = 1; j < lg(V); j++) { GEN Q, c = gmul(gpowgs(T, V[j]), gel(C,j)); Q = RgXn_red_shallow(RgX_shift_shallow(RgX_Rg_mul(P, c), f), d); P = RgX_sub(P, Q); /* P * (1 - c x^f) mod X^d */ } return centerlift(RgXn_sqrtnu(P, f, d)); } static GEN eulfactameinit(GEN hgm, long v) { GEN C = hgm_get_CYCLOE(hgm); if (!v) pari_err_BUG("hgmeulerfactor [incorrect t in eulfactame]"); if (hgm_get_SWAP(hgm)) v = -v; return gel(C, (v < 0)? 2: 1); } static long tameexpo(GEN hgm, long v) { GEN W = eulfactameinit(hgm,v); long e, m, l = lg(W); for (m = 1, e = 0; m < l; m++) if (W[m] && v % m == 0) e += eulerphiu(m); return hgm_get_DEG(hgm) - e; } static GEN Jordantameexpo(GEN hgm, long v, GEN t0, long p, long *pe) { GEN P = pol_1(0), W = eulfactameinit(hgm, v); long e, m, l = lg(W); for (m = 1, e = 0; m < l; m++) if (W[m] && v % m == 0) { P = gmul(P, Jordantame(hgm, t0, m, p)); e += eulerphiu(m); } *pe = hgm_get_DEG(hgm) - e; return P; } /***************************************************************/ /* PART IV.5: Fake wild primes for t */ /***************************************************************/ /* Compute g_q(r)=pi^sq(r)*gauss(r) */ static GEN gkgauss(long p, long f, GEN vp, long r, GEN ZP, GEN *sp) { GEN S = gen_0, P = gen_m1; long i, qm1 = vp[f+1] - 1; for (i = 1; i <= f; i++) { GEN t = gfrac(sstoQ(r * vp[i], qm1)); S = gadd(S, t); P = gmul(P, Qp_gamma(gadd(t, ZP))); } *sp = gmulsg(p - 1, S); /* t_INT */ return P; } static GEN hgmG(GEN hgm, long p, long f, GEN vp, long r, GEN ZP) { GEN S = gen_0, P = gen_1, VPOLGA = hgm_get_VPOLGA(hgm); long n, c; for (n = 1; n < lg(VPOLGA); n++) if ((c = VPOLGA[n])) { GEN sq, g = gkgauss(p, f, vp, r*n, ZP, &sq); S = addii(S, mulsi(c, sq)); P = gmul(P, gpowgs(g, c)); } /* p - 1 | S */ return gmul(P, powis(utoineg(p), itos(S) / (p - 1))); } /* multiplicity of -r / (q-1) in beta */ static long hgmmulti(GEN B, long q, long r) { long d = (q-1) / ugcd(r, q-1); return d >= lg(B)? 0: B[d]; } /* We must have w(M)^r*hgmQ(q,r)=hgmC(q,r)/hgmC(q,0) */ static GEN hgmQ(GEN hgm, long p, long f, GEN vp, long r, GEN ZP) { pari_sp av = avma; GEN B = gel(hgm_get_CYCLOE(hgm), 2); long q = vp[f+1], m0 = hgmmulti(B, q, 0), m1 = hgmmulti(B, q, r); GEN c = powis(utoipos(q), hgm_get_TT(hgm) + m0 - m1); if (odd(m0)) c = negi(c); return gerepileupto(av, padic_to_Q(gmul(c, hgmG(hgm, p, f, vp, r, ZP)))); } static GEN hgmU(GEN hgm, long p, long f, GEN t, long dfp) { pari_sp av = avma; GEN ZP = zeropadic_shallow(utoipos(p), dfp), vp = upowers_u(p, f, 1); long q = vp[f+1], i; GEN Q = cgetg(q+1, t_POL); Q[1] = evalsigne(1)|evalvarn(0); for (i = 2; i <= q; i++) gel(Q, i) = hgmQ(hgm, p, f, vp, i-2, ZP); t = p == 2? gen_1: gmul(hgm_get_MVALUE(hgm), t); return gerepileupto(av, hgmH(Q, p, f, dfp, t)); } /***************************************************************/ /* PART V: Utility programs and main init */ /***************************************************************/ static GEN cycloE2cyclo(GEN A, GEN B) { return mkvec2(count2list(A), count2list(B)); } #if 0 GEN hgmalphatocyclo(GEN val, GEN vbe) { GEN C = get_CYCLOE(val,vbe); return cycloE2cyclo(gel(C,1), gel(C,2)); } #endif static GEN allprims(long n, GEN cache) { long l, i, c; GEN z, v; if (gel(cache,n)) return gel(cache,n); z = coprimes_zv(n); l = lg(z); v = cgetg(l, t_VEC); for (i = c = 1; i < l; i++) if (z[i]) gel(v, c++) = mkfracss(i, n); setlg(v, c); return gel(cache,n) = v; } static GEN zv_to_prims(GEN D, GEN cache) { long i, l = lg(D); GEN v = cgetg(l, t_VEC); for (i = 1; i < l; i++) { if (D[i] <= 0) pari_err_TYPE("hgmcyclotoalpha", D); gel(v, i) = allprims(D[i], cache); } return shallowconcat1(v); } static void hgmcyclotoalpha(GEN *pA, GEN *pB) { GEN v, D = *pA, E = *pB; if (typ(D) != t_VECSMALL) D = gtovecsmall(D); if (typ(E) != t_VECSMALL) E = gtovecsmall(E); v = const_vec(maxss(vecsmall_max(D), vecsmall_max(E)), NULL); gel(v,1) = mkvec(gen_0); *pA = zv_to_prims(D, v); *pB = zv_to_prims(E, v); if (lg(*pA) != lg(*pB)) pari_err_TYPE("hgminit [incorrect lengths]", mkvec2(D,E)); } static GEN hgmalphatogamma(GEN val, GEN vbe) { return get_VPOLGA(get_CYCLOE(val, vbe)); } static void hgmgammatocyclo(GEN VPOLGA, GEN *pD, GEN *pE) { long i, cn, cd, l = lg(VPOLGA); GEN d, n, v = zero_zv(l - 1); if (typ(VPOLGA) != t_VECSMALL) VPOLGA = gtovecsmall(VPOLGA); for (i = 1; i < l; i++) { long e = VPOLGA[i]; if (e) { GEN D = divisorsu(i); long j, lD = lg(D); for (j = 1; j < lD; j++) v[ D[j] ] += e; } } for (i = 1, cn = cd = 0; i < l; i++) { long e = v[i]; if (e > 0) cn += e; else cd -= e; } if (!cn || !cd) pari_err_TYPE("hgmgammatocyclo", VPOLGA); *pE = n = cgetg(cn+1, t_VECSMALL); *pD = d = cgetg(cd+1, t_VECSMALL); for (i = cn = cd = 1; i < l; i++) { long e = v[i], j; if (e < 0) for (j = 1; j <= -e; j++) d[cd++] = i; else if (e > 0) for (j = 1; j <= e; j++) n[cn++] = i; } } static void hgmgammatoalpha(GEN VPOLGA, GEN *pA, GEN *pB) { hgmgammatocyclo(VPOLGA, pA, pB); hgmcyclotoalpha(pA, pB); } /* A and B sorted */ static long zv_intersect(GEN A, GEN B) { long a = 1, b = 1, lA = lg(A), lB = lg(B); while (a < lA && b < lB) { if (A[a] < B[b]) a++; else if (A[a] > B[b]) b++; else return 1; } return 0; } static void remove_intersect(GEN *pA, GEN *pB) { GEN V, W, A = *pA, B = *pB; long a = 1, b = 1, v = 1, w = 1, lA, lB; *pA = V = cgetg_copy(A, &lA); *pB = W = cgetg_copy(B, &lB); while (a < lA && b < lB) { int s = gcmp(gel(A,a), gel(B,b)); if (s < 0) gel(V,v++) = gel(A,a++); else if (s > 0) gel(W,w++) = gel(B,b++); else { a++; b++; } } while (a < lA) gel(V,v++) = gel(A,a++); while (b < lB) gel(W,w++) = gel(B,b++); setlg(V,v); setlg(W,w); } /* al, be normalized, sorted, unknown intersection */ static GEN albe2u(GEN al, GEN be) { GEN ga; remove_intersect(&al, &be); ga = hgmalphatogamma(al, be); return F2v_factorback(ga); } static GEN get_u(GEN al, GEN be, GEN CYCLOE, GEN VPOLGA, long DEG, long WT) { GEN u, u0 = F2v_factorback(VPOLGA); long b1 = get_b1(CYCLOE); if (odd(DEG)) { be = QV_normalize(RgV_addhalf(be)); u = albe2u(al, be); if ((DEG & 3) == 3) u = negi(u); } else if (odd(WT)) { u = u0; if ((b1 & 3) == 2) u = negi(u); } else { al = QV_normalize(RgV_addhalf(al)); u = shifti(albe2u(al, be), 1); if (((DEG + b1) & 3) == 1) u = negi(u); } u0 = shifti(u0, 1); if ((b1 & 3) == 3) u0 = negi(u0); return mkvec2(coredisc(u), u0); } static long zv_sumeuler(GEN v) { long i, l = lg(v); GEN s = gen_0; for (i = 1; i < l; i++) { if (v[i] <= 0) pari_err_TYPE("hgminit", v); s = addiu(s, eulerphiu(v[i])); } return itou(s); } /* (a, b): format (1) if denominator, format (2) if no denominator, * format (3) if b not vector. */ static GEN hgminit_i(GEN a, GEN b) { long ta = typ(a), l = lg(a); if (ta != t_VEC && ta != t_VECSMALL) pari_err_TYPE("hgminit", a); if (!b) { if (l == 1) initab(a, a); /* error */ if (ta == t_VECSMALL || RgV_is_ZV(a)) { long i; if (ta != t_VECSMALL) a = vec_to_vecsmall(a); for (i = 1; i < l; i++) if (a[i] <= 0) break; if (i != l) hgmgammatoalpha(a, &a, &b); /* gamma */ else { /* cyclo */ b = const_vecsmall(zv_sumeuler(a), 1); hgmcyclotoalpha(&a, &b); } } else /* alpha */ b = zerovec(l - 1); } else { if (typ(b) != ta) pari_err_TYPE("hgminit", b); if (l > 1 && (ta == t_VECSMALL || (RgV_is_ZV(a) && RgV_is_ZV(b)))) hgmcyclotoalpha(&a, &b); /* cyclo */ } return initab(a, b); } GEN hgminit(GEN val, GEN vbe) { pari_sp av = avma; return gerepilecopy(av, hgminit_i(val, vbe)); } GEN hgmalpha(GEN hgm) { GEN al, be; if (!checkhgm(hgm)) pari_err_TYPE("hgmalpha", hgm); al = hgm_get_VAL(hgm); be = hgm_get_VBE(hgm); if (hgm_get_SWAP(hgm)) swap(al, be); retmkvec2(gcopy(al), gcopy(be)); } GEN hgmgamma(GEN hgm) { pari_sp av = avma; GEN g; if (!checkhgm(hgm)) pari_err_TYPE("hgmgamma", hgm); g = hgm_get_VPOLGA(hgm); if (hgm_get_SWAP(hgm)) g = zv_neg(g); return gerepilecopy(av, g); } GEN hgmcyclo(GEN hgm) { pari_sp av = avma; GEN A, B, C; if (!checkhgm(hgm)) pari_err_TYPE("hgmcyclo", hgm); C = hgm_get_CYCLOE(hgm); A = gel(C,1); B = gel(C,2); if (hgm_get_SWAP(hgm)) swap(A, B); return gerepilecopy(av, cycloE2cyclo(A, B)); } GEN hgmtwist(GEN hgm) { pari_sp av = avma; GEN val, vbe; if (!checkhgm(hgm)) pari_err_TYPE("hgmtwist", hgm); val = hgm_get_VAL(hgm); vbe = hgm_get_VBE(hgm); if (hgm_get_SWAP(hgm)) swap(val, vbe); val = sort(RgV_addhalf(val)); vbe = sort(RgV_addhalf(vbe)); return gerepilecopy(av, initab(val, vbe)); } GEN hgmparams(GEN hgm) { pari_sp av = avma; GEN H, M; long TT, DEG, WT; if (!checkhgm(hgm)) pari_err_TYPE("hgmparams", hgm); H = zx_to_ZX(hgm_get_HODGE(hgm)); TT = hgm_get_TT(hgm); DEG = hgm_get_DEG(hgm); WT = hgm_get_WT(hgm); M = hgm_get_MVALUE(hgm); return gerepilecopy(av, mkvec4(utoipos(DEG), utoi(WT), mkvec2(H,stoi(TT)), M)); } /* symmetry at 1? */ long hgmissymmetrical(GEN hgm) { GEN A, B, C; long a, i, j, lA, lB; if (!checkhgm(hgm)) pari_err_TYPE("hgmissymmetrical", hgm); C = hgm_get_CYCLOE(hgm); if (odd(hgm_get_DEG(hgm))) return 0; A = gel(C,1); lA = lg(A); B = gel(C,2); lB = lg(B); for (i = 1; i < lA; i++) if ((a = A[i])) { switch(i & 3) { /* polcyclo(i)[-X] = polcyclo(j) */ case 0: j = i; break; case 2: j = i >> 1; break; default: j = i << 1; break; } if (j >= lB || B[j] != a) return 0; } return 1; } /***************************************************************/ /* PART VI: Experimental euler factors */ /***************************************************************/ /* FIXME: one prime at a time */ static GEN hgmmodif(GEN an, GEN PPol) { pari_sp av = avma; long i, L = lg(an), lP = lg(PPol); for (i = 1; i < lP; i++) { GEN E = gel(PPol, i), pol = gel(E, 2); long d = degpol(pol); if (d) { GEN v = vec_ei(L, 1); long j, p = itos(gel(E, 1)), pj = p; for (j = 1; j <= d && pj <= L; j++, pj *= p) gel(v, pj) = RgX_coeff(pol, j); an = dirdiv(an, v); } } return gerepileupto(av, an); } /***************************************************************/ /* PART VII: Make tables of HGMs */ /***************************************************************/ static int ok_part(GEN v, GEN W) { long l = lg(v), j; for (j = 1; j < l; j++) if (!gel(W,v[j])) return 0; return 1; } static GEN mkphi() { GEN W = const_vec(20, NULL); gel(W,1) = mkvecsmall2(1,2); gel(W,2) = mkvecsmall3(3,4,6); gel(W,4) = mkvecsmall4(5,8,10,12); gel(W,6) = mkvecsmall4(7,9,14,18); gel(W,8) = mkvecsmall5(15,16,20,24,30); gel(W,10)= mkvecsmall2(11,22); gel(W,12)= mkvecsmalln(6, 13L,21L,26L,28L,36L,42L); gel(W,16)= mkvecsmalln(6, 17L,32L,34L,40L,48L,60L); gel(W,18)= mkvecsmall4(19,27,38,54); gel(W,20)= mkvecsmall5(25,33,44,50,66); return W; } static GEN mkal(GEN p, GEN W) { GEN res, V; long l = lg(p), lV, i, j; V = cgetg(l, t_VECSMALL); for (i = 1; i < l; i++) V[i] = lg(gel(W, p[i])) - 1; V = cyc2elts(V); lV = lg(V); res = cgetg(1, t_VEC); for (j = 1; j < lV; j++) { GEN t = cgetg(l, t_VECSMALL), v = gel(V,j); for (i = 1; i < l; i++) t[i] = umael2(W, p[i], v[i]+1); vecsmall_sort(t); if (!RgV_isin(res, t)) res = vec_append(res, t); } return res; } static GEN mkallal(long n) { GEN W = mkphi(), p = partitions(n, NULL, NULL); long i, c, l = lg(p); for (i = c = 1; i < l; i++) if (ok_part(gel(p,i), W)) gel(p, c++) = mkal(gel(p,i), W); setlg(p, c); return shallowconcat1(p); } static GEN mkalbe(long n) { GEN w, L = mkallal(n); long i, j, c, l = lg(L); w = cgetg(l * (l / 2) + 1, t_VEC); for (i = c = 1; i < l; i++) { GEN A = gel(L, i); long a = A[lg(A)-1]; for (j = i + 1; j < l; j++) { GEN B = gel(L, j); if (!zv_intersect(A, B)) gel(w,c++) = (A[1]==1 || (B[1]!=1 && a > B[lg(B)-1]))? mkvec2(B,A): mkvec2(A,B); } } setlg(w,c); return w; } static long cyclowt(GEN a, GEN b) { pari_sp av = avma; long TT; hgmcyclotoalpha(&a, &b); return gc_long(av, degpol(hodge(a, b, &TT))); } GEN hgmbydegree(long n) { pari_sp av = avma; GEN w = cgetg(n+1, t_VEC), c = const_vecsmall(n, 1), v = mkalbe(n); long i, l = lg(v); for (i = 1; i <= n; i++) gel(w,i) = cgetg(l,t_VEC); for (i = 1; i < l; i++) { GEN z = gel(v,i); long k = cyclowt(gel(z,1), gel(z,2)) + 1; gmael(w, k, c[k]++) = z; } for (i = 1; i <= n; i++) setlg(gel(w,i), c[i]); return gerepilecopy(av, w); } /***************************************************************/ /* PART VIII: L-function data */ /***************************************************************/ /* BAD sorted t_VECSMALL */ static GEN removebad(GEN v, GEN BAD) { long i, c, l = lg(v); GEN w = cgetg(l, t_VECSMALL); for (i = c = 1; i < lg(v); i++) if (!zv_search(BAD, v[i])) w[c++] = v[i]; setlg(w, c); return w; } static GEN primedivisors(GEN t) { GEN fa = absZ_factor(t); return ZV_to_zv(gel(fa,1)); } static GEN gacfac(long p, long m, long c) { long i, l = p + m + 1; GEN v = cgetg(l, t_VECSMALL); for (i = 1; i <= p; i++) v[i] = -c; for ( ; i < l; i++) v[i] = 1 - c; return v; } static GEN hgmfindvga(GEN hgm, GEN t) { GEN v, HODGE = hgm_get_HODGE(hgm); long WT = degpol(HODGE), WT2 = (WT - 1) >> 1, i, c, h, fl = gequal1(t); v = cgetg(WT + 2, t_VEC); for (i = 0, c = 1; i <= WT2; i++) { if ((h = HODGE[i+2])) { if (fl && 2*i == WT - 1) h--; if (h) gel(v, c++) = gacfac(h, h, i); } } if (!odd(WT)) { long h = HODGE[WT2+3], hp = h >> 1, hm; if (!fl) { hm = hp; if (odd(h)) { if (gsigne(t) >= 0 && gcmpgs(t, 1) <= 0) hm++; else hp++; } else { if (gcmpgs(t, 1) > 0) { hp++; hm--; } } if (odd(hgm_get_TT(hgm) + WT2 + 1)) lswap(hp, hm); } else { h--; hm = h - hp; if (odd(h) && odd(hgm_get_TT(hgm) + WT2 + 1)) lswap(hp, hm); } if (hp || hm) gel(v, c++) = gacfac(hp, hm, WT2 + 1); } if (c == 1) return cgetg(1, t_VECSMALL); setlg(v, c); v = shallowconcat1(v); vecsmall_sort(v); return v; } /* Return [VGA, k, BAD, COND] where VGA as in lfun, k non motivic * weight (s -> k - s), BAD is the list of wild primes and Euler factors, * COND is the tame part of the conductor */ static GEN hgmlfuninfty(GEN hgm, GEN t) { pari_sp av = avma; GEN VGA = hgmfindvga(hgm, t), T0, T1, v; GEN COND, t1 = gsubgs(t, 1), BAD = primedivisors(hgm_get_BAD(hgm)); long k = hgm_get_WT(hgm) + 1, i, j, l; if (isintzero(t1)) T1 = cgetg(1, t_VECSMALL); else { GEN fa = absZ_factor(numer_i(t1)), P = gel(fa,1), E = gel(fa,2); if (!odd(k)) T1 = removebad(ZV_to_zv(P), BAD); else { long j, lP = lg(P); T1 = cgetg(lP, t_VECSMALL); for (i = j = 1; i < lP; i++) { long p = itos(gel(P,i)); if (mpodd(gel(E,i)) && !zv_search(BAD, p)) T1[j++] = p; } setlg(T1,j); } } COND = zv_prod_Z(T1); T0 = removebad(gconcat(primedivisors(numer_i(t)), primedivisors(denom_i(t))), BAD); for (i = 1; i < lg(T0); i++) { long p = T0[i], e = tameexpo(hgm, Q_lval(t, p)); COND = mulii(powuu(p, e), COND); } l = lg(BAD); v = cgetg(l, t_VEC); for (i = j = 1; i < l; i++) /* FIXME: precompute wild Euler factors */ if (hgmclass(hgm, BAD[i], t) == C_BAD) gel(v,j++) = mkvec2(utoipos(BAD[i]), pol_1(0)); setlg(v, j); return gerepilecopy(av, mkvec4(VGA, utoi(k), v, COND)); } /***************************************************************/ /* PART IX: GUESS OF WILD PRIMES */ /***************************************************************/ static GEN vecmellin(GEN L, GEN K, GEN t, GEN td, GEN vroots, long bitprec) { long i, N = lfunthetacost(L, t, 0, bitprec); GEN v = cgetg(N+1, t_VEC); for (i = 1; i <= N; i++) gel(v,i) = gammamellininvrt(K, gmul(td, gel(vroots,i)), bitprec); return v; } /* List of Weil polynomials for prime p of degree d and weight w */ static GEN listweil_i(ulong d, ulong p, ulong w) { GEN V; if (d == 0) return mkvec(pol_1(0)); if (odd(d)) { GEN P; if (odd(w)) return cgetg(1, t_VEC); V = listweil_i(d - 1, p, w); P = monomial(powuu(p, w / 2), 1, 0); return shallowconcat(gmul(gsubsg(1, P), V), gmul(gaddsg(1, P), V)); } if (d == 2) { long q = upowuu(p, w), s = usqrt(4 * q), i; GEN Q = utoi(q); V = cgetg(2*s + 3, t_VEC); for (i = 1; i <= 2*s + 1; i++) gel(V,i) = mkpoln(3, Q, stoi(1+s-i), gen_1); gel(V, 2*s + 2) = mkpoln(3, negi(Q), gen_0, gen_1); return V; } if (d == 4) { long q = upowuu(p, w), s = usqrt(16 * q), a, c, is2 = usqrt(4 * q); double s2 = 2 * sqrt((double)q); GEN Q2 = sqru(q), W, A, mA, tmp, Q; V = cgetg(s + 3, t_VEC); for (a = 0; a <= s; a++) { long b, m = ceil(a * s2) - 2 * q, M = ((a * a) >> 2) + 2 * q; GEN AQ = stoi(a * q), mAQ = stoi(-a * q); A = stoi(a); mA = stoi(-a); W = cgetg(2*(M - m) + 3, t_VEC); for (b = m, c = 1; b <= M; b++) { if (a) gel(W, c++) = mkpoln(5, Q2, mAQ, stoi(b), mA, gen_1); gel(W, c++) = mkpoln(5, Q2, AQ, stoi(b), A, gen_1); } setlg(W, c); gel(V, a + 1) = W; } W = cgetg(2 * is2 + 2, t_VEC); tmp = mkpoln(3, stoi(-q), gen_0, gen_1); Q = utoipos(q); for (a = 0, c = 1; a <= is2; a++) { A = stoi(a); mA = stoi(-a); if (a) gel(W, c++) = gmul(tmp, mkpoln(3, Q, mA, gen_1)); gel(W, c++) = gmul(tmp, mkpoln(3, Q, A, gen_1)); } setlg(W, c); gel(V, s + 2) = W; return shallowconcat1(V); } pari_err_IMPL("d > 5 in listweil"); return NULL; /* LCOV_EXCL_LINE */ } /* Same, weight <= w, by decreasing weight */ static GEN listweilallw_i(ulong d, ulong p, ulong w) { long i = d? w: 0; GEN V = cgetg(i+2, t_VEC); for (; i >= 0; i--) gel(V,i+1) = listweil_i(d, p, i); return shallowconcat1(V); } static long sumdeg(GEN W, GEN M) { long i, l = lg(M), s = 0; for (i = 1; i < l; i++) s += degpol(gmael(W,i,M[i]+1)); return s; } static GEN mul(GEN a, GEN b, ulong lim) { long na = lg(a)-1, nb = lg(b)-1, i, j, n; GEN c = cgetg(na * nb + 1, t_VECSMALL); for (i = n = 1; i <= na; i++) for (j = 1; j <= nb; j++) { ulong m = umuluu_or_0(a[i], b[j]); if (m && m <= lim) c[n++] = m; } setlg(c, n); return c; } static GEN listcond(GEN BAD, GEN achi, ulong min, ulong max) { long i, j, l = lg(BAD); GEN P = cgetg(l, t_VEC), z; for (i = 1; i < l; i++) { long p = BAD[i], v = achi[i]; gel(P,i) = upowers_u(p, ulogint(max, p) - v, upowuu(p, v)); } z = gel(P,1); for (i = 2; i < l; i++) z = mul(z, gel(P,i), max); if (min > 1) { l = lg(z); for (i = j = 1; i < l; i++) if ((ulong)z[i] >= min) z[j++] = z[i]; setlg(z, j); } vecsmall_sort(z); return z; } /* Artificial lfundiv by zeta(s - (k - 1) / 2). */ static GEN lfundivraw(GEN L) { long k = itos(ldata_get_k(L)), i; GEN v = ldata_get_gammavec(L); i = RgV_isin(v, stoi(-(k - 1) >> 2)); if (!i) pari_err_BUG("lfundivraw"); L = shallowcopy(L); gel(L, 3) = vecsplice(v, i); setlg(L, 7); return L; } /* Compute forvec vectors from v, sorted by increasing total degree */ static GEN forvecsort(GEN vF, GEN v) { GEN w, E = cyc2elts(v); long i, l = lg(E); w = cgetg(l, t_VECSMALL); for (i = 1; i < l; i++) w[i] = sumdeg(vF, gel(E, i)); return vecpermute(E, vecsmall_indexsort(w)); /* by increasing total degree */ } static GEN lfunhgmwild(GEN L, GEN H, GEN t, GEN BAD, long pole, GEN hint, long bitprec) { GEN v, K, t0, t0r, t0ir, t0i, t0k, N0, vM, vD, val, PPOL, vF, achi; long d, lM, iN, iM, i, k, k2, prec = nbits2prec(bitprec), lB = lg(BAD); long BADprod, limdeg; ulong minN = 1, maxN = 2048; v = cgetg(lB, t_VECSMALL); PPOL = cgetg(lB, t_VEC); for (i = 1; i < lB; i++) { v[i] = itou( gmael(BAD,i,1) ); gel(PPOL,i) = shallowcopy(gel(BAD,i)); } BAD = v; BADprod = zv_prod(BAD); achi = get_achi(H, t, BAD); if (pole) L = lfundivraw(L); limdeg = d = ldata_get_degree(L); N0 = ldata_get_conductor(L); if (hint) switch(typ(hint)) { long l; case t_INT: limdeg = itos(hint); if (limdeg < 0 || limdeg > d) pari_err_TYPE("lfunhgm [bad hint]", hint); break; case t_VEC: l = lg(hint); if (l > 1 && l < 4) { GEN t = gel(hint,1), r; if (typ(t) != t_INT || signe(t) <= 0) pari_err_TYPE("lfunhgm [bad hint]", hint); t = dvmdii(t, N0, &r); if (r != gen_0) pari_err_TYPE("lfunhgm [bad hint]", hint); minN = maxN = itou(t); if (l == 3) { t = gel(hint,2); if (typ(t) != t_INT || signe(t) < 0 || cmpis(t, d) > 0) pari_err_TYPE("lfunhgm [bad hint]", hint); limdeg = itos(t); } } } k = itos(ldata_get_k(L)); k2 = (k-1) >> 1; K = gammamellininvinit(ldata_get_gammavec(L), 0, bitprec + 32); t0 = sstoQ(11, 10); t0i = ginv(t0); t0k = gpowgs(t0, k); t0r = gpow(t0, sstoQ(2,d), prec); t0ir = ginv(t0r); /* vF[i] list of Weil polynomials F for p = BAD[i], * F = prod_j Fj, |reciprocal root of Fj|^2 = p^(w + 1 - nj) * 2v_p(lc(F)) = deg F * (w + 1) - sum_j deg Fj * nj; */ vF = cgetg(lB, t_VEC); vD = cgetg(lB, t_VEC); /* vD[k][l] = sum_j deg Fj * nj for F = vF[k][l] */ v = cgetg(lB, t_VECSMALL); for (i = 1; i < lB; i++) { GEN W = cgetg(limdeg+2, t_VEC), D; long p = BAD[i], j, lW; for (j = 0; j <= limdeg; j++) gel(W,j+1) = listweilallw_i(j, p, k-1); gel(vF, i) = W = shallowconcat1(W); lW = lg(W); v[i] = lW-1; gel(vD,i) = D = cgetg(lW, t_VEC); for (j = 1; j < lW; j++) { GEN F = gel(W,j); D[j] = degpol(F) * k - 2 * Z_lval(leading_coeff(F), p); } } vM = forvecsort(vF, v); lM = lg(vM); if (DEBUGLEVEL) { err_printf(" lM = %ld ", lM); err_flush(); } L = shallowcopy(L); val = cgetg(lB, t_VECSMALL); for(;;) { GEN z, vroots, an0, vN; long lN, lim; z = listcond(BAD, achi, minN, maxN); if (maxN == minN) /* from hint */ { minN = 1; /* in case it fails */ maxN--; } else { minN = maxN+1; maxN <<= 2; } lN = lg(z); if (lN == 1) continue; vN = cgetg(lN, t_VEC); for (i = 1; i < lN; i++) gel(vN, i) = muliu(N0, z[i]); gel(L, 5) = gel(vN, lN - 1); if (DEBUGLEVEL) err_printf("\nmaxN = %ld\n", itos(gel(L,5))); lim = lfunthetacost(L, t0i, 0, bitprec); vroots = dirpowers(lim, sstoQ(2, d), prec + EXTRAPREC64); an0 = hgmcoefs(H, t, lim); if (pole) { GEN w = vecpowuu(lim, k2); for (i = 1; i <= lim; i++) if (cgcd(i, BADprod) > 1) gel(w, i) = gen_0; an0 = dirdiv(an0, w); } for (iN = 1; iN < lN; iN++) { pari_sp av0 = avma, av2; GEN vecK, vecKi, N = gel(vN,iN), isqN = gpow(N, sstoQ(-1,d), prec); if (DEBUGLEVEL) { err_printf(" %ld ", itos(N)); err_flush(); } gel(L,5) = N; vecK = vecmellin(L, K, t0, gmul(t0r, isqN), vroots, bitprec); vecKi= vecmellin(L, K, t0i,gmul(t0ir, isqN), vroots, bitprec); for (i = 1; i < lB; i++) val[i] = Z_lval(N, BAD[i]); setlg(an0, lg(vecKi)); av2 = avma; for (iM = 1; iM < lM; iM++, set_avma(av2)) { GEN M = gel(vM, iM), an, eno, den; for (i = 1; i < lB; i++) { GEN F = gmael(vF, i, M[i]+1); long D, dF = degpol(F), a = val[i]; if (a < d - dF) break; if (a) { if (d == dF) break; D = mael(vD, i, M[i]+1); /* sum_j deg Fj nj */ if (D == d && d - dF != a) break; /* a = a(chi) + d - deg F - 1 */ if (D == d-1 && a != d - dF + achi[i] - 1 && !gequal1(t)) break; } gmael(PPOL, i, 2) = F; } if (i < lB) continue; an = hgmmodif(an0, PPOL); den = gmul(t0k, RgV_dotproduct(vecK, an)); eno = gdiv(RgV_dotproduct(vecKi, an), den); if (gexpo(gsubgs(gabs(eno, prec), 1)) < -bitprec / 2) { if (pole) for (i = 1; i < lB; i++) { GEN t = deg1pol_shallow(negi(powuu(BAD[i], k2)), gen_1, 0); gmael(PPOL, i, 2) = gmul(gmael(PPOL, i, 2), t); } for (i = 1; i < lB; i++) gmael(PPOL, i, 2) = ginv(gmael(PPOL, i, 2)); eno = grndtoi(eno, NULL); if (typ(eno) != t_INT) pari_err_BUG("lfunhgmwild"); return mkvec3(N, mkvec2(t, PPOL), eno); } } set_avma(av0); } } } static GEN BAD2small(GEN BAD) { long i, l = lg(BAD); GEN v = cgetg(l, t_VECSMALL); for (i = 1; i < l; i++) v[i] = itou( gmael(BAD,i,1) ); return v; } /* moments of motive */ static GEN hgmmoments(GEN H, GEN t, GEN M, long nb) { pari_sp av = avma, av2; GEN P, v, S, L = hgmlfuninfty(H, t), BAD = BAD2small(gel(L, 3)); GEN k2 = gmul2n(gsubgs(gel(L,2), 1), -1); long ct = 0, i, j, lP, lm, tm = typ(M); if (!nb) nb = 1000; P = primes_zv(nb); lP = lg(P); v = hgmcoefs(H, t, P[lP - 1]); if (tm != t_VEC) M = gtovec(M); av2 = avma; lm = lg(M); S = const_vec(lm - 1, real_0(DEFAULTPREC)); for (i = 1; i < lP; i++) { long p = P[i]; if (!Q_lval(t, p) && !zv_search(BAD, p)) { GEN T = gdiv(gel(v, p), gpow(utoipos(p), k2, DEFAULTPREC)); ct++; for (j = 1; j < lm; j++) gel(S,j) = gadd(gel(S,j), gpow(T, gel(M,j), DEFAULTPREC)); } if ((i & 0xf) == 0) S = gerepilecopy(av2, S); } if (tm != t_VEC && tm != t_COL && tm != t_VECSMALL) S = gel(S, 1); return gerepileupto(av, gdivgu(S, ct)); } /* Heuristic guess: is there a pole ? */ static long lfunhgmispole(GEN H, GEN t, long nb) { pari_sp av = avma; GEN M; if (!nb) nb = 40; M = hgmmoments(H, t, gen_1, nb); return gc_bool(av, gexpo(M) > -2); } static GEN tag(GEN x, long t) { return mkvec2(mkvecsmall(t), x); } static GEN lfunhgm_i(GEN hgm, GEN t, GEN hint, long bitprec) { GEN L, vr, v = hgmlfuninfty(hgm, t), vga = zv_to_ZV(gel(v,1)), k = gel(v,2); GEN BAD = gel(v,3), COND = gel(v, 4); long pole = mpodd(k) && lfunhgmispole(hgm, t, 0), lB = lg(BAD); L = mkvecn(pole? 7: 6, tag(mkvec2(hgm,t), t_LFUN_HGM), gen_0, vga, k, COND, gen_0, mkvec(mkvec2(shifti(addiu(k,1),-1), gen_0))); if (pole && ldata_get_degree(L) == 1) { /* motive = zeta */ long i; gel(L,5) = gel(L,6) = gel(L,7) = gen_1; if (lB != 1) { GEN R = mkrfrac(gen_1, deg1pol_shallow(gen_m1,gen_1,0)); gmael3(L, 1, 2, 2) = mkvec2(t, BAD); for (i = 1; i < lB; i++) gmael(BAD, i, 2) = R; } return L; } if (lB == 1) { vr = lfunrootres(L, bitprec); gel(L, 6) = gel(vr, 3); if (pole) gel(L, 7) = gel(vr, 1); return L; } v = lfunhgmwild(L, hgm, t, BAD, pole, hint, bitprec); gel(L, 5) = gel(v, 1); /* N */ gmael3(L, 1, 2, 2) = gel(v, 2); /* [t, PPOL] */ gel(L, 6) = gel(v, 3); /* w */ if (pole) { vr = lfunrootres(L, bitprec); gel(L, 7) = gel(vr, 1); } return L; } GEN lfunhgm(GEN hgm, GEN t, GEN hint, long bit) { pari_sp av = avma; if (!checkhgm(hgm)) pari_err_TYPE("lfunhgm", hgm); return gerepilecopy(av, lfunhgm_i(hgm, t, hint, bit)); } GEN dirhgm_worker(GEN P, ulong X, GEN hgm, GEN t) { pari_sp av = avma; long i, l = lg(P); GEN W = cgetg(l, t_VEC); for(i = 1; i < l; i++) { ulong p = uel(P,i); long e, d = ulogint(X, p) + 1; /* minimal d such that p^d > X */ gel(W,i) = RgXn_inv(hgmeulerfactorlimit(hgm, t, p, d-1, 0, &e), d); } return gerepilecopy(av, mkvec2(P,W)); } GEN hgmcoefs(GEN hgm, GEN t, long n) { GEN worker, bad = NULL; if (!checkhgm(hgm)) pari_err_TYPE("hgmcoefs", hgm); if (typ(t) == t_VEC && lg(t) == 3) { bad = gel(t,2); t = gel(t,1); } if (!is_rational_t(typ(t))) pari_err_TYPE("hgmcoefs",t); worker = snm_closure(is_entry("_dirhgm_worker"), mkvec2(hgm, t)); return pardireuler(worker, gen_2, stoi(n), NULL, bad); } pari-2.17.2/src/basemath/gen1.c0000644000175000017500000027074514760123736014565 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /********************************************************************/ /** **/ /** GENERIC OPERATIONS **/ /** (first part) **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_mod /* assume z[1] was created last */ #define fix_frac_if_int(z) if (equali1(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 (equali1(gel(z,2)))\ z = gerepileupto((pari_sp)(z+3), gel(z,1));\ else\ gerepilecoeffssp((pari_sp)z, tetpil, z+1, 2); } static void warn_coercion(GEN x, GEN y, GEN z) { if (DEBUGLEVEL) pari_warn(warner,"coercing quotient rings; moduli %Ps and %Ps -> %Ps",x,y,z); } static long kro_quad(GEN x, GEN y) { pari_sp av=avma; return gc_long(av, kronecker(quad_disc(x), y)); } /* 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 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 += nbits2extraprec(i); return gerepileupto(av, gadd(y, quadtofp(x, prec))); } static GEN mulrfrac(GEN x, GEN y) { pari_sp av; GEN z, a = gel(y,1), b = gel(y,2); if (is_pm1(a)) /* frequent special case */ { z = divri(x, b); if (signe(a) < 0) togglesign(z); return z; } av = avma; return gerepileuptoleaf(av, divri(mulri(x,a), b)); } static GEN mulqf(GEN x, GEN y, long prec) { pari_sp av = avma; return gerepileupto(av, gmul(y, quadtofp(x, prec))); } static GEN divqf(GEN x, GEN y, long prec) { pari_sp av = avma; return gerepileupto(av, gdiv(quadtofp(x,prec), y)); } static GEN divfq(GEN x, GEN y, long prec) { pari_sp av = avma; return gerepileupto(av, gdiv(x, quadtofp(y,prec))); } /* y PADIC, x + y by converting x to padic */ static GEN addTp(GEN x, GEN y) { pari_sp av = avma; GEN z; if (!valp(y)) z = cvtop2(x,y); else { long l = signe(gel(y,4))? valp(y) + precp(y): valp(y); z = cvtop(x, gel(y,2), l); } return gerepileupto(av, addsub_pp(z, y, addii)); } /* y PADIC, x * y by converting x to padic */ static GEN mulTp(GEN x, GEN y) { pari_sp av = avma; return gerepileupto(av, mulpp(cvtop2(x,y), y)); } /* y PADIC, non zero x / y by converting x to padic */ static GEN divTp(GEN x, GEN y) { pari_sp av = avma; return gerepileupto(av, divpp(cvtop2(x,y), y)); } /* x PADIC, x / y by converting y to padic. Assume x != 0; otherwise y * converted to O(p^e) and division by 0 */ static GEN divpT(GEN x, GEN y) { pari_sp av = avma; return gerepileupto(av, divpp(x, cvtop2(y,x))); } /* z := Mod(x,X) + Mod(y,X) [ t_INTMOD preallocated ], x,y,X INT, 0 <= x,y < X * clean memory from z on */ static GEN add_intmod_same(GEN z, GEN X, GEN x, GEN y) { if (lgefint(X) == 3) { ulong u = Fl_add(itou(x),itou(y), X[2]); set_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]); set_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]); set_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 = uel(X,2), u = Fl_div(itou(x), itou(y), m); set_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_coeff(d), y); /* should fail */ pari_err_INV("gred_rfrac", y); /* better than nothing */ } return D; } static int Leading_is_neg(GEN x) { while (typ(x) == t_POL) x = leading_coeff(x); return is_real_t(typ(x))? gsigne(x) < 0: 0; } static int transtype(GEN x) { return x != gen_1 && typ(x) != t_PADIC; } /* 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 _1n, _1d, c, cn, cd, z; long dd = degpol(d); if (dd <= 0) { if (dd < 0) pari_err_INV("gred_rfrac_simple", d); n = gdiv(n, gel(d,2)); if (typ(n) != t_POL || varn(n) != varn(d)) n = scalarpol(n, varn(d)); return n; } if (Leading_is_neg(d)) { d = gneg(d); n = gneg(n); } _1n = Rg_get_1(n); _1d = Rg_get_1(d); if (transtype(_1n) && !gidentical(_1n, _1d)) d = gmul(d, _1n); if (transtype(_1d) && !gidentical(_1n, _1d)) n = gmul(n, _1d); cd = content(d); while (typ(n) == t_POL && !degpol(n)) n = gel(n,2); cn = (typ(n) == t_POL && varn(n) == varn(d))? content(n): n; if (!gequal1(cd)) { d = RgX_Rg_div(d,cd); if (!gequal1(cn)) { if (gequal0(cn)) { if (isexactzero(cn)) return scalarpol(cn, varn(d)); n = (cn != n)? RgX_Rg_div(n,cd): gdiv(n, cd); c = gen_1; } else { n = (cn != n)? RgX_Rg_div(n,cn): gen_1; c = gdiv(cn,cd); } } else c = ginv(cd); } else { if (!gequal1(cn)) { if (gequal0(cn)) { if (isexactzero(cn)) return scalarpol(cn, varn(d)); c = gen_1; } else { n = (cn != n)? RgX_Rg_div(n,cn): gen_1; c = cn; } } else { GEN y = cgetg(3,t_RFRAC); gel(y,1) = gcopy(n); gel(y,2) = RgX_copy(d); return y; } } if (typ(c) == t_POL) { z = c; do { z = content(z); } while (typ(z) == t_POL); cd = denom_i(z); cn = gmul(c, cd); } else { cn = numer_i(c); cd = denom_i(c); } z = cgetg(3,t_RFRAC); gel(z,1) = gmul(n, cn); gel(z,2) = d = rfrac_denom_mul_scal(d, cd); /* can happen: Pol(O(17^-1)) / Pol([Mod(9,23), O(23^-3)]) */ if (!signe(d)) pari_err_INV("gred_rfrac_simple", d); return z; } /* in rare cases x may be a t_POL, after 0/x for instance -> pol_0() */ static GEN fix_rfrac(GEN x, long d) { GEN z, N, D; if (!d || typ(x) == t_POL) return x; z = cgetg(3, t_RFRAC); N = gel(x,1); D = gel(x,2); if (d > 0) { gel(z, 1) = (typ(N)==t_POL && varn(N)==varn(D))? RgX_shift(N,d) : monomialcopy(N,d,varn(D)); gel(z, 2) = RgX_copy(D); } else { gel(z, 1) = gcopy(N); gel(z, 2) = RgX_shift(D, -d); } return z; } /* assume d != 0 */ static GEN gred_rfrac2(GEN n, GEN d) { GEN y, z, _1n, _1d; long v, vd, vn; n = simplify_shallow(n); if (isintzero(n)) return scalarpol(Rg_get_0(d), varn(d)); d = simplify_shallow(d); if (typ(d) != t_POL) return gdiv(n,d); vd = varn(d); if (typ(n) != t_POL) { if (varncmp(vd, gvar(n)) >= 0) return gdiv(n,d); if (varncmp(vd, gvar2(n)) < 0) return gred_rfrac_simple(n,d); pari_err_BUG("gred_rfrac2 [incompatible variables]"); } vn = varn(n); if (varncmp(vd, vn) < 0) return gred_rfrac_simple(n,d); if (varncmp(vd, vn) > 0) return RgX_Rg_div(n,d); _1n = Rg_get_1(n); _1d = Rg_get_1(d); if (transtype(_1n) && !gidentical(_1n, _1d)) d = gmul(d, _1n); if (transtype(_1d) && !gidentical(_1n, _1d)) n = gmul(n, _1d); /* 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); } /* x,y t_INT, return x/y in reduced form */ GEN Qdivii(GEN x, GEN y) { pari_sp av = avma; GEN r, q; if (lgefint(y) == 3) { q = Qdiviu(x, y[2]); if (signe(y) > 0) return q; if (typ(q) == t_INT) togglesign(q); else togglesign_safe(&gel(q,1)); return q; } if (is_pm1(y)) return (signe(y) < 0)? negi(x): icopy(x); if (equali1(x)) { if (!signe(y)) pari_err_INV("gdiv",y); retmkfrac(signe(y) < 0? gen_m1: gen_1, absi(y)); } q = dvmdii(x,y,&r); if (r == gen_0) return q; /* gen_0 intended */ r = gcdii(y, r); if (lgefint(r) == 3) { ulong t = r[2]; set_avma(av); if (t == 1) q = mkfraccopy(x,y); else { q = cgetg(3,t_FRAC); gel(q,1) = diviuexact(x,t); gel(q,2) = diviuexact(y,t); } } else { /* rare: r and q left on stack for efficiency */ q = cgetg(3,t_FRAC); gel(q,1) = diviiexact(x,r); gel(q,2) = diviiexact(y,r); } normalize_frac(q); return q; } /* x t_INT, return x/y in reduced form */ GEN Qdiviu(GEN x, ulong y) { pari_sp av = avma; ulong r, t; GEN q; if (y == 1) return icopy(x); if (!y) pari_err_INV("gdiv",gen_0); if (equali1(x)) retmkfrac(gen_1, utoipos(y)); q = absdiviu_rem(x,y,&r); if (!r) { if (signe(x) < 0) togglesign(q); return q; } t = ugcd(y, r); set_avma(av); if (t == 1) retmkfrac(icopy(x), utoipos(y)); retmkfrac(diviuexact(x,t), utoipos(y / t)); } /* x t_INT, return x/y in reduced form */ GEN Qdivis(GEN x, long y) { pari_sp av = avma; ulong r, t; long s; GEN q; if (y > 0) return Qdiviu(x, y); if (!y) pari_err_INV("gdiv",gen_0); s = signe(x); if (!s) return gen_0; if (y < 0) { y = -y; s = -s; } if (y == 1) { x = icopy(x); setsigne(x,s); return x; } if (equali1(x)) retmkfrac(s > 0? gen_1: gen_m1, utoipos(y)); q = absdiviu_rem(x,y,&r); if (!r) { if (s < 0) togglesign(q); return q; } t = ugcd(y, r); set_avma(av); q = cgetg(3, t_FRAC); if (t != 1) { x = diviuexact(x,t); y /= t; } else x = icopy(x); gel(q,1) = x; setsigne(x, s); gel(q,2) = utoipos(y); return q; } /*******************************************************************/ /* */ /* 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; if (typ(x) != t_POL) return gcopy(x); if (varn(x) != varn(y) || degpol(x) <= 0) return RgX_copy(x); a = gel(y,4); u = gel(x,3); /*Mod(ux + v, ax^2 + bx + c)*/ b = gel(y,3); v = gel(x,2); z = cgetg(4, t_POL); z[1] = x[1]; gel(z,2) = 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; 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); z = gmul(u, gsub(gmul(c,u), gmul(b,v))); if (!gequal1(a)) z = gdiv(z, a); return gadd(z, gsqr(v)); } GEN conj_i(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 x; case t_COMPLEX: return mkcomplex(gel(x,1), gneg(gel(x,2))); case t_QUAD: y = cgetg(4,t_QUAD); gel(y,1) = gel(x,1); gel(y,2) = gequal0(gmael(x,1,3))? gel(x,2) : gadd(gel(x,2), gel(x,3)); gel(y,3) = gneg(gel(x,3)); return y; case t_POL: case t_SER: y = cgetg_copy(x, &lx); y[1] = x[1]; for (i=2; i= r) { set_avma(av); return zeropadic(p, e+r); } if (c) { mod = diviiexact(mod, powiu(p,c)); r -= c; e += c; } } u = modii(u, mod); set_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; } /* Rg_to_Fp(t_FRAC) without GC */ static GEN Q_to_Fp(GEN x, GEN p) { return mulii(gel(x,1), Fp_inv(gel(x,2),p)); } /* return x + y, where y t_PADIC and x is a nonzero t_INT or t_FRAC */ static GEN addQp(GEN x, GEN y) { pari_sp av = avma; long d, r, e, vy = valp(y), py = precp(y); GEN z, q, mod, u, p = gel(y,2); e = Q_pvalrem(x, p, &x); d = vy - e; r = d + py; if (r <= 0) { set_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); if (typ(x) != t_INT) x = Q_to_Fp(x, mod); u = addii(x, mulii(u, q)); } else if (d < 0) { q = powiu(p,-d); if (typ(x) != t_INT) x = Q_to_Fp(x, mod); u = addii(u, mulii(x, q)); r = py; e = vy; } else { long c; if (typ(x) != t_INT) x = Q_to_Fp(x, mod); u = addii(u, x); if (!signe(u) || (c = Z_pvalrem(u,p,&u)) >= r) { set_avma(av); return zeropadic(p,e+r); } if (c) { mod = diviiexact(mod, powiu(p,c)); r -= c; e += c; } } u = modii(u, mod); set_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; warn_coercion(X,Y,gel(z,1)); gel(z,2) = gerepileupto(av, gmod(op(x, y), gel(z,1))); return z; } if (varncmp(vx, vy) < 0) { gel(z,1) = RgX_copy(X); gel(T,1) = Y; gel(T,2) = y; y = T; } else { gel(z,1) = RgX_copy(Y); gel(T,1) = X; gel(T,2) = x; x = T; } gel(z,2) = op(x, y); return z; } /* Mod(y, Y) +/- x, x scalar or polynomial in same var and reduced degree */ static GEN addsub_polmod_scal(GEN Y, GEN y, GEN x, GEN(*op)(GEN,GEN)) { retmkpolmod(degpol(Y)? op(y, x): gen_0, RgX_copy(Y)); } /* typ(y) == t_SER, x "scalar" [e.g object in lower variable] */ static GEN add_ser_scal(GEN y, GEN x) { long i, v, ly, vy; GEN z; if (isrationalzero(x)) return gcopy(y); ly = lg(y); v = valser(y); if (v < 3-ly) return gcopy(y); /* v + ly >= 3 */ if (v < 0) { z = cgetg(ly,t_SER); z[1] = y[1]; for (i = 2; i <= 1-v; 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 normalizeser(z); } vy = varn(y); if (v > 0) { if (ser_isexactzero(y)) return scalarser(ly == 2? x: gadd(x,gel(y,2)), vy, v); y -= v; ly += v; z = cgetg(ly,t_SER); x = gcopy(x); for (i=3; i<=v+1; i++) gel(z,i) = gen_0; } else if (ser_isexactzero(y)) return gcopy(y); else { /* v = 0, ly >= 3 */ z = cgetg(ly,t_SER); x = gadd(x, gel(y,2)); i = 3; } for (; i lx) return gcopy(x); z = cgetg(ly,t_SER); for (i=2; i<=n+1; i++) gel(z,i) = gcopy(gel(x,i)); for ( ; i < ly; i++) gel(z,i) = gadd(gel(x,i),gel(y,i-n)); } else { z = cgetg(ly,t_SER); for (i=2; i < ly; i++) gel(z,i) = gadd(gel(x,i),gel(y,i)); } z[1] = x[1]; return normalizeser(z); } /* typ(y) == RFRAC, x polynomial in same variable or "scalar" */ static GEN add_rfrac_scal(GEN y, GEN x) { pari_sp av; GEN n; if (isintzero(x)) return gcopy(y); /* frequent special case */ av = avma; n = gadd(gmul(x, gel(y,2)), gel(y,1)); return gerepileupto(av, gred_rfrac_simple(n, gel(y,2))); } /* x "scalar", ty != t_MAT and nonscalar */ static GEN add_scal(GEN y, GEN x, long ty) { switch(ty) { case t_POL: return RgX_Rg_add(y, x); case t_SER: return add_ser_scal(y, x); case t_RFRAC: return add_rfrac_scal(y, x); case t_COL: return RgC_Rg_add(y, x); case t_VEC: if (isintzero(x)) return gcopy(y); break; } pari_err_TYPE2("+",x,y); return NULL; /* LCOV_EXCL_LINE */ } /* assumes z = cget(3, t_FRAC) comes first in stack, then a, then b */ static GEN setfrac(GEN z, GEN a, GEN b) { gel(z,1) = icopy_avma(a, (pari_sp)z); gel(z,2) = icopy_avma(b, (pari_sp)gel(z,1)); set_avma((pari_sp)gel(z,2)); return z; } /* z <- a / (b*Q), (Q,a) = 1 */ static GEN addsub_frac_i(GEN z, GEN Q, GEN a, GEN b) { GEN q = Qdivii(a, b); /* != 0 */ if (typ(q) == t_INT) { gel(z,1) = gerepileuptoint((pari_sp)Q, q); gel(z,2) = Q; return z; } return setfrac(z, gel(q,1), mulii(gel(q,2), Q)); } static GEN addsub_frac(GEN x, GEN y, GEN (*op)(GEN,GEN)) { GEN x1 = gel(x,1), x2 = gel(x,2); GEN y1 = gel(y,1), y2 = gel(y,2), z, Q, q, r, n, delta; int s = cmpii(x2, y2); /* common denominator: (x1 op y1) / x2 */ if (!s) { pari_sp av = avma; return gerepileupto(av, Qdivii(op(x1, y1), x2)); } z = cgetg(3, t_FRAC); if (s < 0) { Q = dvmdii(y2, x2, &r); /* y2 = Q x2: 1/x2 . (Q x1 op y1)/Q, where latter is in coprime form */ if (r == gen_0) return addsub_frac_i(z, Q, op(mulii(Q,x1), y1), x2); delta = gcdii(x2,r); } else { Q = dvmdii(x2, y2, &r); /* x2 = Q y2: 1/y2 . (x1 op Q y1)/Q, where latter is in coprime form */ if (r == gen_0) return addsub_frac_i(z, Q, op(x1, mulii(Q,y1)), y2); delta = gcdii(y2,r); } /* delta = gcd(x2,y2) */ if (equali1(delta)) { /* numerator is nonzero */ gel(z,1) = gerepileuptoint((pari_sp)z, op(mulii(x1,y2), mulii(y1,x2))); gel(z,2) = mulii(x2,y2); return z; } x2 = diviiexact(x2,delta); y2 = diviiexact(y2,delta); n = op(mulii(x1,y2), mulii(y1,x2)); /* != 0 */ q = dvmdii(n, delta, &r); if (r == gen_0) return setfrac(z, q, mulii(x2, y2)); r = gcdii(delta, r); if (!equali1(r)) { n = diviiexact(n, r); delta = diviiexact(delta, r); } return setfrac(z, n, mulii(mulii(x2, y2), delta)); } /* assume x2, y2 are t_POLs in the same variable */ static GEN add_rfrac(GEN x, GEN y) { pari_sp av = avma; GEN x1 = gel(x,1), x2 = gel(x,2); GEN y1 = gel(y,1), y2 = gel(y,2), q, r, n, d, delta; delta = RgX_gcd(x2,y2); if (!degpol(delta)) { n = simplify_shallow( gadd(gmul(x1,y2), gmul(y1,x2)) ); d = RgX_mul(x2, y2); return gerepileupto(av, gred_rfrac_simple(n, d)); } x2 = RgX_div(x2,delta); y2 = RgX_div(y2,delta); n = gadd(gmul(x1,y2), gmul(y1,x2)); if (!signe(n)) { n = simplify_shallow(n); if (isexactzero(n)) { if (isrationalzero(n)) { set_avma(av); return zeropol(varn(x2)); } return gerepileupto(av, scalarpol(n, varn(x2))); } return gerepilecopy(av, mkrfrac(n, RgX_mul(gel(x,2),y2))); } if (degpol(n) == 0) return gerepileupto(av, gred_rfrac_simple(gel(n,2), RgX_mul(gel(x,2),y2))); q = RgX_divrem(n, delta, &r); /* we want gcd(n,delta) */ if (isexactzero(r)) { GEN z; d = RgX_mul(x2, y2); /* "constant" denominator ? */ z = lg(d) == 3? RgX_Rg_div(q, gel(d,2)): gred_rfrac_simple(q, d); return gerepileupto(av, z); } r = RgX_gcd(delta, r); if (degpol(r)) { n = RgX_div(n, r); d = RgX_mul(RgX_mul(x2,y2), RgX_div(delta, r)); } else d = RgX_mul(gel(x,2), y2); return gerepileupto(av, gred_rfrac_simple(n, d)); } GEN gadd(GEN x, GEN y) { long tx = typ(x), ty = typ(y), vx, vy, lx, i, l; pari_sp av, tetpil; GEN z, p1; if (tx == ty) switch(tx) /* shortcut to generic case */ { case t_INT: return addii(x,y); case t_REAL: return addrr(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 add_intmod_same(z, X, gel(x,2), gel(y,2)); gel(z,1) = gcdii(X,Y); warn_coercion(X,Y,gel(z,1)); av = avma; p1 = addii(gel(x,2),gel(y,2)); gel(z,2) = gerepileuptoint(av, remii(p1, gel(z,1))); return z; } case t_FRAC: return addsub_frac(x,y,addii); case t_COMPLEX: z = cgetg(3,t_COMPLEX); gel(z,2) = gadd(gel(x,2),gel(y,2)); if (isintzero(gel(z,2))) { set_avma((pari_sp)(z+3)); return gadd(gel(x,1),gel(y,1)); } gel(z,1) = gadd(gel(x,1),gel(y,1)); return z; case t_PADIC: if (!equalii(gel(x,2),gel(y,2))) pari_err_OP("+",x,y); return addsub_pp(x,y, addii); case t_QUAD: z = cgetg(4,t_QUAD); if (!ZX_equal(gel(x,1),gel(y,1))) pari_err_OP("+",x,y); gel(z,1) = ZX_copy(gel(x,1)); gel(z,2) = gadd(gel(x,2),gel(y,2)); gel(z,3) = gadd(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), &gadd); return addsub_polmod(gel(x,1), gel(y,1), gel(x,2), gel(y,2), &gadd); case t_FFELT: return FF_add(x,y); case t_POL: vx = varn(x); vy = varn(y); if (vx != vy) { if (varncmp(vx, vy) < 0) return RgX_Rg_add(x, y); else return RgX_Rg_add(y, x); } return RgX_add(x, y); case t_SER: vx = varn(x); vy = varn(y); if (vx != vy) { if (varncmp(vx, vy) < 0) return add_ser_scal(x, y); else return add_ser_scal(y, x); } return ser_add(x, y); case t_RFRAC: vx = varn(gel(x,2)); vy = varn(gel(y,2)); if (vx != vy) { if (varncmp(vx, vy) < 0) return add_rfrac_scal(x, y); else return add_rfrac_scal(y, x); } return add_rfrac(x,y); case t_VEC: if (lg(y) != lg(x)) pari_err_OP("+",x,y); return RgV_add(x,y); case t_COL: if (lg(y) != lg(x)) pari_err_OP("+",x,y); return RgC_add(x,y); case t_MAT: lx = lg(x); if (lg(y) != lx) pari_err_OP("+",x,y); if (lx == 1) return cgetg(1, t_MAT); if (lgcols(y) != lgcols(x)) pari_err_OP("+",x,y); return RgM_add(x,y); default: pari_err_TYPE2("+",x,y); } /* tx != ty */ if (tx > ty) { swap(x,y); lswap(tx,ty); } if (is_const_t(ty)) switch(tx) /* tx < ty, is_const_t(tx) && is_const_t(ty) */ { case t_INT: switch(ty) { case t_REAL: return addir(x,y); case t_INTMOD: z = cgetg(3, t_INTMOD); return add_intmod_same(z, gel(y,1), gel(y,2), modii(x, gel(y,1))); case t_FRAC: z = cgetg(3,t_FRAC); gel(z,1) = gerepileuptoint((pari_sp)z, addii(gel(y,1), mulii(gel(y,2),x))); gel(z,2) = icopy(gel(y,2)); return z; case t_COMPLEX: return addRc(x, y); case t_PADIC: if (!signe(x)) return gcopy(y); return addQp(x,y); case t_QUAD: return addRq(x, y); case t_FFELT: return FF_Z_add(y,x); } case t_REAL: switch(ty) { case t_FRAC: if (!signe(gel(y,1))) return rcopy(x); if (!signe(x)) { lx = expi(gel(y,1)) - expi(gel(y,2)) - expo(x); return lx <= 0? rcopy(x): fractor(y, nbits2prec(lx)); } av=avma; z=addir(gel(y,1),mulir(gel(y,2),x)); tetpil=avma; return gerepile(av,tetpil,divri(z,gel(y,2))); case t_COMPLEX: return addRc(x, y); case t_QUAD: return gequal0(y)? rcopy(x): addqf(y, x, realprec(x)); default: pari_err_TYPE2("+",x,y); } case t_INTMOD: switch(ty) { case t_FRAC: { GEN X = gel(x,1); z = cgetg(3, t_INTMOD); p1 = Fp_div(gel(y,1), gel(y,2), X); return add_intmod_same(z, X, p1, gel(x,2)); } case t_FFELT: if (!equalii(gel(x,1),FF_p_i(y))) pari_err_OP("+",x,y); return FF_Z_add(y,gel(x,2)); case t_COMPLEX: return addRc(x, y); case t_PADIC: { GEN X = gel(x,1); z = cgetg(3, t_INTMOD); return add_intmod_same(z, X, gel(x,2), padic_to_Fp(y, X)); } case t_QUAD: return addRq(x, y); } case t_FRAC: switch (ty) { case t_COMPLEX: return addRc(x, y); case t_PADIC: if (!signe(gel(x,1))) return gcopy(y); return addQp(x,y); case t_QUAD: return addRq(x, y); case t_FFELT: return FF_Q_add(y, x); } case t_FFELT: pari_err_TYPE2("+",x,y); case t_COMPLEX: switch(ty) { case t_PADIC: return Zp_nosquare_m1(gel(y,2))? addRc(y, x): addTp(x, y); case t_QUAD: lx = precision(x); if (!lx) pari_err_OP("+",x,y); return gequal0(y)? gcopy(x): addqf(y, x, lx); } case t_PADIC: /* ty == t_QUAD */ return (kro_quad(y,gel(x,2)) == -1)? addRq(x, y): addTp(y, x); } /* tx < ty, !is_const_t(y) */ switch(ty) { case t_MAT: if (is_matvec_t(tx)) pari_err_TYPE2("+",x,y); if (isrationalzero(x)) return gcopy(y); return RgM_Rg_add(y, x); case t_COL: if (tx == t_VEC) pari_err_TYPE2("+",x,y); return RgC_Rg_add(y, x); case t_POLMOD: /* is_const_t(tx) in this case */ return addsub_polmod_scal(gel(y,1), gel(y,2), x, &gadd); } if (is_scalar_t(tx)) { if (tx == t_POLMOD) { vx = varn(gel(x,1)); vy = gvar(y); if (vx == vy) y = gmod(y, gel(x,1)); /* error if ty == t_SER */ else if (varncmp(vx,vy) > 0) return add_scal(y, x, ty); return addsub_polmod_scal(gel(x,1), gel(x,2), y, &gadd); } return add_scal(y, x, ty); } /* x and y are not scalars, ty != t_MAT */ vx = gvar(x); vy = gvar(y); if (vx != vy) { /* x or y is treated as a scalar */ if (is_vec_t(tx) || is_vec_t(ty)) pari_err_TYPE2("+",x,y); return (varncmp(vx, vy) < 0)? add_scal(x, y, tx) : add_scal(y, x, ty); } /* vx = vy */ switch(tx) { case t_POL: switch (ty) { case t_SER: if (lg(x) == 2) return gcopy(y); i = RgX_val(x); if (i == LONG_MAX) i = 0; /* e.g. x = Mod(0,3)*x^0 */ i = lg(y) + valser(y) - i; if (i < 3) return gcopy(y); p1 = RgX_to_ser(x,i); y = ser_add(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) { long vn, vd; av = avma; vn = gval(gel(y,1), vy); vd = RgX_valrem_inexact(gel(y,2), NULL); if (vd == LONG_MAX) pari_err_INV("gadd", gel(y,2)); l = lg(x) + valser(x) - (vn - vd); if (l < 3) { set_avma(av); return gcopy(x); } return gerepileupto(av, gadd(x, rfrac_to_ser_i(y, l))); } break; } pari_err_TYPE2("+",x,y); return NULL; /* LCOV_EXCL_LINE */ } GEN gaddsg(long x, GEN y) { long ty = typ(y); GEN z; switch(ty) { case t_INT: return addsi(x,y); case t_REAL: return addsr(x,y); case t_INTMOD: z = cgetg(3, t_INTMOD); return add_intmod_same(z, gel(y,1), gel(y,2), modsi(x, gel(y,1))); case t_FRAC: z = cgetg(3,t_FRAC); gel(z,1) = gerepileuptoint((pari_sp)z, addii(gel(y,1), mulis(gel(y,2),x))); gel(z,2) = icopy(gel(y,2)); return z; case t_COMPLEX: z = cgetg(3, t_COMPLEX); gel(z,1) = gaddsg(x, gel(y,1)); gel(z,2) = gcopy(gel(y,2)); return z; default: return gadd(stoi(x), y); } } GEN gsubsg(long x, GEN y) { GEN z, a, b; pari_sp av; switch(typ(y)) { case t_INT: return subsi(x,y); case t_REAL: return subsr(x,y); case t_INTMOD: z = cgetg(3, t_INTMOD); a = gel(y,1); b = gel(y,2); return add_intmod_same(z, a, Fp_neg(b,a), modsi(x, a)); case t_FRAC: z = cgetg(3,t_FRAC); a = gel(y,1); b = gel(y,2); gel(z,1) = gerepileuptoint((pari_sp)z, subii(mulis(b,x), a)); gel(z,2) = icopy(gel(y,2)); return z; case t_COMPLEX: z = cgetg(3, t_COMPLEX); gel(z,1) = gsubsg(x, gel(y,1)); gel(z,2) = gneg(gel(y,2)); return z; } av = avma; return gerepileupto(av, gadd(stoi(x), gneg_i(y))); } /********************************************************************/ /** **/ /** SUBTRACTION **/ /** **/ /********************************************************************/ GEN gsub(GEN x, GEN y) { long tx = typ(x), ty = typ(y); pari_sp av; GEN z; if (tx == ty) switch(tx) /* shortcut to generic case */ { case t_INT: return subii(x,y); case t_REAL: return subrr(x,y); case t_INTMOD: { GEN p1, X = gel(x,1), Y = gel(y,1); z = cgetg(3,t_INTMOD); if (X==Y || equalii(X,Y)) return sub_intmod_same(z, X, gel(x,2), gel(y,2)); gel(z,1) = gcdii(X,Y); warn_coercion(X,Y,gel(z,1)); av = avma; p1 = subii(gel(x,2),gel(y,2)); gel(z,2) = gerepileuptoint(av, modii(p1, gel(z,1))); return z; } 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))) { set_avma((pari_sp)(z+3)); return gsub(gel(x,1),gel(y,1)); } gel(z,1) = gsub(gel(x,1),gel(y,1)); return z; case t_PADIC: if (!equalii(gel(x,2),gel(y,2))) pari_err_OP("+",x,y); return addsub_pp(x,y, subii); case t_QUAD: z = cgetg(4,t_QUAD); if (!ZX_equal(gel(x,1),gel(y,1))) pari_err_OP("+",x,y); gel(z,1) = ZX_copy(gel(x,1)); gel(z,2) = gsub(gel(x,2),gel(y,2)); gel(z,3) = gsub(gel(x,3),gel(y,3)); return z; case t_POLMOD: if (RgX_equal_var(gel(x,1), gel(y,1))) return addsub_polmod_same(gel(x,1), gel(x,2), gel(y,2), &gsub); return addsub_polmod(gel(x,1), gel(y,1), gel(x,2), gel(y,2), &gsub); case t_FFELT: return FF_sub(x,y); case t_POL: { long vx = varn(x); long vy = varn(y); if (vx != vy) { if (varncmp(vx, vy) < 0) return RgX_Rg_sub(x, y); else return Rg_RgX_sub(x, y); } return RgX_sub(x, y); } case t_VEC: if (lg(y) != lg(x)) pari_err_OP("+",x,y); return RgV_sub(x,y); case t_COL: if (lg(y) != lg(x)) pari_err_OP("+",x,y); return RgC_sub(x,y); case t_MAT: { long lx = lg(x); if (lg(y) != lx) pari_err_OP("+",x,y); if (lx == 1) return cgetg(1, t_MAT); if (lgcols(y) != lgcols(x)) pari_err_OP("+",x,y); return RgM_sub(x,y); } case t_RFRAC: case t_SER: break; default: pari_err_TYPE2("+",x,y); } av = avma; return gerepileupto(av, gadd(x,gneg_i(y))); } /********************************************************************/ /** **/ /** MULTIPLICATION **/ /** **/ /********************************************************************/ static GEN mul_ser_scal(GEN y, GEN x) { long l, i; GEN z; if (isexactzero(x)) return gmul(Rg_get_0(y), x); if (ser_isexactzero(y)) { z = scalarser(lg(y) == 2? Rg_get_0(x): gmul(gel(y,2), x), varn(y), 1); setvalser(z, valser(y)); return z; } z = cgetg_copy(y, &l); z[1] = y[1]; for (i = 2; i < l; i++) gel(z,i) = gmul(gel(y,i), x); return normalizeser(z); } /* (n/d) * x, x "scalar" or polynomial in the same variable as d * [n/d a valid RFRAC] */ static GEN mul_rfrac_scal(GEN n, GEN d, GEN x) { pari_sp av = avma; GEN z; switch(typ(x)) { case t_PADIC: n = gmul(n, x); d = gcvtop(d, gel(x,2), signe(gel(x,4))? precp(x): 1); return gerepileupto(av, gdiv(n,d)); case t_INTMOD: case t_POLMOD: n = gmul(n, x); d = gmul(d, gmodulo(gen_1, gel(x,1))); return gerepileupto(av, gdiv(n,d)); } z = gred_rfrac2(x, d); n = simplify_shallow(n); if (typ(z) == t_RFRAC) { n = gmul(gel(z,1), n); d = gel(z,2); if (typ(n) == t_POL && varncmp(varn(n), varn(d)) < 0) z = RgX_Rg_div(n, d); else z = gred_rfrac_simple(n, d); } else z = gmul(z, n); return gerepileupto(av, z); } static GEN mul_scal(GEN y, GEN x, long ty) { switch(ty) { case t_POL: if (lg(y) == 2) return scalarpol(gmul(gen_0,x), varn(y)); return RgX_Rg_mul(y, x); case t_SER: return mul_ser_scal(y, x); case t_RFRAC: return mul_rfrac_scal(gel(y,1),gel(y,2), x); case t_QFB: if (typ(x) == t_INT && gequal1(x)) return gcopy(y); /* fall through */ } pari_err_TYPE2("*",x,y); return NULL; /* LCOV_EXCL_LINE */ } 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(x1, y2); Y = gred_rfrac2(y1, x2); if (typ(X) == t_RFRAC) { if (typ(Y) == t_RFRAC) { x1 = gel(X,1); x2 = gel(X,2); y1 = gel(Y,1); y2 = gel(Y,2); z = gred_rfrac_simple(gmul(x1,y1), gmul(x2,y2)); } else z = mul_gen_rfrac(Y, X); } else if (typ(Y) == t_RFRAC) z = mul_gen_rfrac(X, Y); else z = gmul(X, Y); return gerepileupto(av, z); } /* (x1/x2) /y2, x2 and y2 are t_POL in the same variable */ static GEN div_rfrac_pol(GEN x1, GEN x2, GEN y2) { pari_sp av = avma; GEN X = gred_rfrac2(x1, y2); if (typ(X) == t_RFRAC && varn(gel(X,2)) == varn(x2)) { x2 = RgX_mul(gel(X,2), x2); x1 = gel(X,1); } else x1 = X; return gerepileupto(av, gred_rfrac_simple(x1, x2)); } /* Mod(y, Y) * x, assuming x scalar */ static GEN mul_polmod_scal(GEN Y, GEN y, GEN x) { retmkpolmod(gmul(x,y), RgX_copy(Y)); } /* cf mulqq */ static GEN quad_polmod_mul(GEN P, GEN x, GEN y) { GEN T = cgetg(4, t_POL), b = gel(P,3), c = gel(P,2), p1, p2, p3, p4; pari_sp tetpil, av = avma; T[1] = x[1]; p2 = gmul(gel(x,2), gel(y,2)); p3 = gmul(gel(x,3), gel(y,3)); p1 = gmul(gneg_i(c),p3); /* operands are usually small: gadd ~ gmul and Karatsuba is a waste */ if (typ(b) == t_INT) { if (signe(b)) { p4 = gadd(gmul(gel(x,2), gel(y,3)), gmul(gel(x,3), gel(y,2))); if (is_pm1(b)) { if (signe(b) > 0) p3 = gneg(p3); } else p3 = gmul(negi(b), p3); } else { p3 = gmul(gel(x,2),gel(y,3)); p4 = gmul(gel(x,3),gel(y,2)); } } else { p4 = gadd(gmul(gel(x,2), gel(y,3)), gmul(gel(x,3), gel(y,2))); p3 = gmul(gneg_i(b), p3); } tetpil = avma; gel(T,2) = gadd(p2, p1); gel(T,3) = gadd(p4, p3); gerepilecoeffssp(av,tetpil,T+2,2); return normalizepol_lg(T,4); } /* Mod(x,T) * Mod(y,T) */ static GEN mul_polmod_same(GEN T, GEN x, GEN y) { GEN z = cgetg(3,t_POLMOD), a; long v = varn(T), lx = lg(x), ly = lg(y); gel(z,1) = RgX_copy(T); /* x * y mod T optimised */ if (typ(x) != t_POL || varn(x) != v || lx <= 3 || typ(y) != t_POL || varn(y) != v || ly <= 3) a = gmul(x, y); else { if (lg(T) == 5 && isint1(gel(T,4))) /* quadratic fields */ a = quad_polmod_mul(T, x, y); else a = RgXQ_mul(x, y, gel(z,1)); } gel(z,2) = a; return z; } static GEN sqr_polmod(GEN T, GEN x) { GEN a, z = cgetg(3,t_POLMOD); gel(z,1) = RgX_copy(T); if (typ(x) != t_POL || varn(x) != varn(T) || lg(x) <= 3) a = gsqr(x); else { pari_sp av = avma; a = RgXQ_sqr(x, gel(z,1)); a = gerepileupto(av, a); } gel(z,2) = a; return z; } /* Mod(x,X) * Mod(y,Y) */ static GEN mul_polmod(GEN X, GEN Y, GEN x, GEN y) { long T[3] = { evaltyp(t_POLMOD) | _evallg(3),0,0 }; long vx = varn(X), vy = varn(Y); GEN z = cgetg(3,t_POLMOD); if (vx==vy) { pari_sp av; gel(z,1) = RgX_gcd(X,Y); av = avma; warn_coercion(X,Y,gel(z,1)); gel(z,2) = gerepileupto(av, gmod(gmul(x, y), gel(z,1))); return z; } if (varncmp(vx, vy) < 0) { gel(z,1) = RgX_copy(X); gel(T,1) = Y; gel(T,2) = y; y = T; } else { gel(z,1) = RgX_copy(Y); gel(T,1) = X; gel(T,2) = x; x = T; } gel(z,2) = gmul(x, y); return z; } #if 0 /* used by 3M only */ /* set z = x+y and return 1 if x,y have the same sign * set z = x-y and return 0 otherwise */ static int did_add(GEN x, GEN y, GEN *z) { long tx = typ(x), ty = typ(y); if (tx == ty) switch(tx) { case t_INT: *z = addii(x,y); return 1; case t_FRAC: *z = addsub_frac(x,y,addii); return 1; case t_REAL: if (signe(x) == -signe(y)) { *z = subrr(x,y); return 0; } else { *z = addrr(x,y); return 1; } } if (tx == t_REAL) switch(ty) { case t_INT: if (signe(x) == -signe(y)) { *z = subri(x,y); return 0; } else { *z = addri(x,y); return 1; } case t_FRAC: if (signe(x) == -signe(gel(y,1))) { *z = gsub(x,y); return 0; } else { *z = gadd(x,y); return 1; } } else if (ty == t_REAL) switch(tx) { case t_INT: if (signe(x) == -signe(y)) { *z = subir(x,y); return 0; } else { *z = addir(x,y); return 1; } case t_FRAC: if (signe(gel(x,1)) == -signe(y)) { *z = gsub(x,y); return 0; } else { *z = gadd(x,y); return 1; } } *z = gadd(x,y); return 1; } #endif /* x * I * y, x t_COMPLEX with non-intzero real part, y non-intzero "scalar" */ static GEN mulcIR(GEN x, GEN y) { GEN z = cgetg(3,t_COMPLEX); pari_sp av = avma; gel(z,1) = gerepileupto(av, gneg(gmul(y,gel(x,2)))); gel(z,2) = gmul(y, gel(x,1)); return z; } /* x,y COMPLEX */ static GEN mulcc(GEN x, GEN y) { GEN xr = gel(x,1), xi = gel(x,2); GEN yr = gel(y,1), yi = gel(y,2); GEN p1, p2, p3, p4, z; pari_sp tetpil, av; if (isintzero(xr)) { if (isintzero(yr)) { av = avma; return gerepileupto(av, gneg(gmul(xi,yi))); } return mulcIR(y, xi); } if (isintzero(yr)) return mulcIR(x, yi); z = cgetg(3,t_COMPLEX); av = avma; #if 0 /* 3M method avoiding catastrophic cancellation, BUT loses accuracy due to * e.g. xr + xi if exponents differ */ if (did_add(xr, xi, &p3)) { if (did_add(yr, yi, &p4)) { /* R = xr*yr - xi*yi * I = (xr+xi)(yr+yi) - xr*yr - xi*yi */ p1 = gmul(xr,yr); p2 = gmul(xi,yi); p2 = gneg(p2); p3 = gmul(p3, p4); p4 = gsub(p2, p1); } else { /* R = (xr + xi) * (yr - yi) + (xr * yi - xi * yr) * I = xr*yi + xi*yr */ p1 = gmul(p3,p4); p3 = gmul(xr,yi); p4 = gmul(xi,yr); p2 = gsub(p3, p4); } } else { if (did_add(yr, yi, &p4)) { /* R = (xr - xi) * (yr + yi) + (xi * yr - xr * yi) * I = xr*yi +xi*yr */ p1 = gmul(p3,p4); p3 = gmul(xr,yi); p4 = gmul(xi,yr); p2 = gsub(p4, p3); } else { /* R = xr*yr - xi*yi * I = -(xr-xi)(yr-yi) + xr*yr + xi*yi */ p3 = gneg( gmul(p3, p4) ); p1 = gmul(xr,yr); p2 = gmul(xi,yi); p4 = gadd(p1, p2); p2 = gneg(p2); } } tetpil = avma; gel(z,1) = gadd(p1,p2); gel(z,2) = gadd(p3,p4); #else if (typ(xr)==t_INT && typ(yr)==t_INT && typ(xi)==t_INT && typ(yi)==t_INT) { /* 3M formula */ p3 = addii(xr,xi); p4 = addii(yr,yi); p1 = mulii(xr,yr); p2 = mulii(xi,yi); p3 = mulii(p3,p4); p4 = addii(p2,p1); tetpil = avma; gel(z,1) = subii(p1,p2); gel(z,2) = subii(p3,p4); if (!signe(gel(z,2))) return gerepileuptoint((pari_sp)(z+3), gel(z,1)); } else { /* naive 4M formula: avoid all loss of accuracy */ p1 = gmul(xr,yr); p2 = gmul(xi,yi); p3 = gmul(xr,yi); p4 = gmul(xi,yr); tetpil = avma; gel(z,1) = gsub(p1,p2); gel(z,2) = gadd(p3,p4); if (isintzero(gel(z,2))) { cgiv(gel(z,2)); return gerepileupto((pari_sp)(z+3), gel(z,1)); } } #endif gerepilecoeffssp(av,tetpil, z+1,2); return z; } /* x,y PADIC */ static GEN mulpp(GEN x, GEN y) { long l = valp(x) + valp(y); pari_sp av; GEN z, t; if (!equalii(gel(x,2),gel(y,2))) pari_err_OP("*",x,y); if (!signe(gel(x,4))) return zeropadic(gel(x,2), l); if (!signe(gel(y,4))) return zeropadic(gel(x,2), l); t = (precp(x) > precp(y))? y: x; z = cgetp(t); setvalp(z,l); av = avma; affii(remii(mulii(gel(x,4),gel(y,4)), gel(t,3)), gel(z,4)); set_avma(av); return z; } /* x,y QUAD */ static GEN mulqq(GEN x, GEN y) { GEN z = cgetg(4,t_QUAD); GEN p1, p2, p3, p4, P = gel(x,1), b = gel(P,3), c = gel(P,2); pari_sp av, tetpil; if (!ZX_equal(P, gel(y,1))) pari_err_OP("*",x,y); gel(z,1) = ZX_copy(P); av = avma; p2 = gmul(gel(x,2),gel(y,2)); p3 = gmul(gel(x,3),gel(y,3)); p1 = gmul(gneg_i(c),p3); if (signe(b)) p4 = gadd(gmul(gel(x,2),gel(y,3)), gmul(gel(x,3),gel(y,2))); else { p3 = gmul(gel(x,2),gel(y,3)); p4 = gmul(gel(x,3),gel(y,2)); } tetpil = avma; gel(z,2) = gadd(p2,p1); gel(z,3) = gadd(p4,p3); gerepilecoeffssp(av,tetpil,z+2,2); return z; } GEN mulcxI(GEN x) { GEN z; switch(typ(x)) { case t_INT: case t_REAL: case t_FRAC: return mkcomplex(gen_0, x); case t_COMPLEX: if (isintzero(gel(x,1))) return gneg(gel(x,2)); z = cgetg(3,t_COMPLEX); gel(z,1) = gneg(gel(x,2)); gel(z,2) = gel(x,1); return z; default: return gmul(gen_I(), x); } } GEN mulcxmI(GEN x) { GEN z; switch(typ(x)) { case t_INT: case t_REAL: case t_FRAC: return mkcomplex(gen_0, gneg(x)); case t_COMPLEX: if (isintzero(gel(x,1))) return gel(x,2); z = cgetg(3,t_COMPLEX); gel(z,1) = gel(x,2); gel(z,2) = gneg(gel(x,1)); return z; default: return gmul(mkcomplex(gen_0, gen_m1), x); } } /* x * I^k */ GEN mulcxpowIs(GEN x, long k) { switch (k & 3) { case 1: return mulcxI(x); case 2: return gneg(x); case 3: return mulcxmI(x); } return x; } /* caller will assume l > 2 later */ static GEN init_ser(long l, long v, long e) { GEN z = cgetg(l, t_SER); z[1] = evalvalser(e) | evalvarn(v) | evalsigne(1); return z; } /* fill in coefficients of t_SER z from coeffs of t_POL y */ static GEN fill_ser(GEN z, GEN y) { long i, lx = lg(z), ly = lg(y); /* lx > 2 */ if (ly >= lx) { for (i = 2; i < lx; i++) gel(z,i) = gel(y,i); } else { for (i = 2; i < ly; i++) gel(z,i) = gel(y,i); for ( ; i < lx; i++) gel(z,i) = gen_0; } /* dangerous case (already normalized), don't use normalizeser */ if (ly == 3 && !signe(y)) { setsigne(z, 0); return z; } return normalizeser(z); } /* assume typ(x) = t_VEC */ static int is_ext_qfr(GEN x) { return lg(x) == 3 && typ(gel(x,1)) == t_QFB && !qfb_is_qfi(gel(x,1)) && typ(gel(x,2)) == t_REAL; } GEN gmul(GEN x, GEN y) { long tx, ty, lx, ly, vx, vy, i, l; pari_sp av, tetpil; GEN z, p1; 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); warn_coercion(X,Y,gel(z,1)); av = avma; p1 = mulii(gel(x,2),gel(y,2)); gel(z,2) = gerepileuptoint(av, remii(p1, gel(z,1))); return z; } case t_FRAC: { 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 (!equali1(p1)) { x1 = diviiexact(x1,p1); y2 = diviiexact(y2,p1); } p1 = gcdii(x2, y1); if (!equali1(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); } return RgX_mul(x, y); case t_SER: { vx = varn(x); vy = varn(y); if (vx != vy) { if (varncmp(vx, vy) < 0) return mul_ser_scal(x, y); return mul_ser_scal(y, x); } lx = minss(lg(x), lg(y)); if (lx == 2) return zeroser(vx, valser(x)+valser(y)); av = avma; z = init_ser(lx, vx, valser(x)+valser(y)); x = ser2pol_i(x, lx); y = ser2pol_i(y, lx); y = RgXn_mul(x, y, lx-2); return gerepilecopy(av, fill_ser(z,y)); } case t_VEC: if (!is_ext_qfr(x) || !is_ext_qfr(y)) pari_err_TYPE2("*",x,y); /* fall through, handle extended t_QFB */ case t_QFB: return qfbcomp(x,y); case t_RFRAC: return mul_rfrac(gel(x,1),gel(x,2), gel(y,1),gel(y,2)); case t_MAT: return RgM_mul(x, y); case t_VECSMALL: /* multiply as permutation. cf perm_mul */ z = cgetg_copy(x, &l); if (l != lg(y)) break; for (i=1; i= l) pari_err_TYPE2("*",x,y); z[i] = x[yi]; } return z; default: pari_err_TYPE2("*",x,y); } /* tx != ty */ if (is_const_t(ty) && is_const_t(tx)) { if (tx > ty) { swap(x,y); lswap(tx,ty); } switch(tx) { case t_INT: switch(ty) { case t_REAL: return signe(x)? mulir(x,y): gen_0; case t_INTMOD: z = cgetg(3, t_INTMOD); return mul_intmod_same(z, gel(y,1), gel(y,2), modii(x, gel(y,1))); case t_FRAC: if (!signe(x)) return gen_0; z=cgetg(3,t_FRAC); p1 = gcdii(x,gel(y,2)); if (equali1(p1)) { set_avma((pari_sp)z); gel(z,2) = icopy(gel(y,2)); gel(z,1) = mulii(gel(y,1), x); } else { x = diviiexact(x,p1); tetpil = avma; gel(z,2) = diviiexact(gel(y,2), p1); gel(z,1) = mulii(gel(y,1), x); fix_frac_if_int_GC(z,tetpil); } return z; case t_COMPLEX: return signe(x)? mulRc(x, y): gen_0; case t_PADIC: return signe(x)? mulTp(x, y): gen_0; case t_QUAD: return mulRq(x,y); case t_FFELT: return FF_Z_mul(y,x); } case t_REAL: switch(ty) { case t_FRAC: return mulrfrac(x, y); case t_COMPLEX: return mulRc(x, y); case t_QUAD: return mulqf(y, x, realprec(x)); default: pari_err_TYPE2("*",x,y); } case t_INTMOD: switch(ty) { case t_FRAC: { GEN X = gel(x,1); z = cgetg(3, t_INTMOD); p1 = Fp_mul(gel(y,1), gel(x,2), X); return div_intmod_same(z, X, p1, remii(gel(y,2), X)); } case t_COMPLEX: return mulRc_direct(x,y); case t_PADIC: { GEN X = gel(x,1); z = cgetg(3, t_INTMOD); return mul_intmod_same(z, X, gel(x,2), padic_to_Fp(y, X)); } case t_QUAD: return mulRq(x, y); case t_FFELT: if (!equalii(gel(x,1),FF_p_i(y))) pari_err_OP("*",x,y); return FF_Z_mul(y,gel(x,2)); } case t_FRAC: switch(ty) { case t_COMPLEX: return mulRc(x, y); case t_PADIC: return signe(gel(x,1))? mulTp(x, y): gen_0; case t_QUAD: return mulRq(x, y); case t_FFELT: return FF_Z_Z_muldiv(y, gel(x,1),gel(x,2)); } case t_FFELT: pari_err_TYPE2("*",x,y); case t_COMPLEX: switch(ty) { case t_PADIC: return Zp_nosquare_m1(gel(y,2))? mulRc(y, x): mulTp(x, y); case t_QUAD: lx = precision(x); if (!lx) pari_err_OP("*",x,y); return mulqf(y, x, lx); } case t_PADIC: /* ty == t_QUAD */ return (kro_quad(y,gel(x,2))== -1)? mulRq(x, y): mulTp(y, x); } } if (is_matvec_t(ty)) { if (!is_matvec_t(tx)) { if (is_noncalc_t(tx)) pari_err_TYPE2( "*",x,y); /* necessary if ly = 1 */ z = cgetg_copy(y, &ly); for (i=1; i ty) { swap(x,y); lswap(tx,ty); } /* tx < ty, !ismatvec(x and y) */ if (ty == t_POLMOD) /* is_const_t(tx) in this case */ return mul_polmod_scal(gel(y,1), gel(y,2), x); if (is_scalar_t(tx)) { if (tx == t_POLMOD) { vx = varn(gel(x,1)); vy = gvar(y); if (vx != vy) { if (varncmp(vx,vy) > 0) return mul_scal(y, x, ty); return mul_polmod_scal(gel(x,1), gel(x,2), y); } /* error if ty == t_SER */ av = avma; y = gmod(y, gel(x,1)); return gerepileupto(av, mul_polmod_same(gel(x,1), gel(x,2), y)); } return mul_scal(y, x, ty); } /* x and y are not scalars, nor matvec */ vx = gvar(x); vy = gvar(y); if (vx != vy) /* x or y is treated as a scalar */ return (varncmp(vx, vy) < 0)? mul_scal(x, y, tx) : mul_scal(y, x, ty); /* vx = vy */ switch(tx) { case t_POL: switch (ty) { case t_SER: { long v; av = avma; v = RgX_valrem(x, &x); if (v == LONG_MAX) return gerepileupto(av, Rg_get_0(x)); v += valser(y); ly = lg(y); if (ly == 2) { set_avma(av); return zeroser(vx, v); } if (degpol(x)) { z = init_ser(ly, vx, v); x = RgXn_mul(x, ser2pol_i(y, ly), ly-2); return gerepilecopy(av, fill_ser(z, x)); } /* take advantage of x = c*t^v */ set_avma(av); y = mul_ser_scal(y, gel(x,2)); setvalser(y, v); return y; } case t_RFRAC: return mul_rfrac_scal(gel(y,1),gel(y,2), x); } break; case t_SER: switch (ty) { case t_RFRAC: av = avma; return gerepileupto(av, gdiv(gmul(gel(y,1),x), gel(y,2))); } break; } pari_err_TYPE2("*",x,y); return NULL; /* LCOV_EXCL_LINE */ } /* return a nonnormalized result */ 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*valser(x)); p2 = cgetg(l2+2, t_VECSMALL)+1; /* left on stack on exit */ Z = cgetg(l2-l1+3, t_SER); Z[1] = evalvalser(2*valser(x)) | evalvarn(varn(x)); z = Z + 2-l1; x += 2; mi = 0; for (i=0; i>1) - 1; for (j=i-mi; j<=minss(l,mi); j++) if (p2[j] && p2[i-j]) p1 = gadd(p1, gmul(gel(x,j),gel(x,i-j))); p1 = gshift(p1,1); if ((i&1) == 0 && p2[i>>1]) p1 = gadd(p1, gsqr(gel(x,i>>1))); gel(z,i) = gerepileupto(av,p1); } return Z; } GEN gsqr(GEN x) { long i, lx; pari_sp av, tetpil; GEN z, p1, p2, p3, p4; switch(typ(x)) { case t_INT: return sqri(x); case t_REAL: return sqrr(x); case t_INTMOD: { GEN X = gel(x,1); z = cgetg(3,t_INTMOD); gel(z,2) = gerepileuptoint((pari_sp)z, remii(sqri(gel(x,2)), X)); gel(z,1) = icopy(X); return z; } case t_FRAC: return sqrfrac(x); case t_COMPLEX: if (isintzero(gel(x,1))) { av = avma; return gerepileupto(av, gneg(gsqr(gel(x,2)))); } z = cgetg(3,t_COMPLEX); av = avma; p1 = gadd(gel(x,1),gel(x,2)); p2 = gsub(gel(x,1), gel(x,2)); p3 = gmul(gel(x,1),gel(x,2)); tetpil = avma; gel(z,1) = gmul(p1,p2); gel(z,2) = gshift(p3,1); gerepilecoeffssp(av,tetpil,z+1,2); return z; case t_PADIC: z = cgetg(5,t_PADIC); i = (absequaliu(gel(x,2), 2) && signe(gel(x,4)))? 1: 0; if (i && precp(x) == 1) i = 2; /* (1 + O(2))^2 = 1 + O(2^3) */ z[1] = evalprecp(precp(x)+i) | evalvalp(valp(x)*2); gel(z,2) = icopy(gel(x,2)); gel(z,3) = shifti(gel(x,3), i); av = avma; gel(z,4) = gerepileuptoint(av, remii(sqri(gel(x,4)), gel(z,3))); return z; case t_QUAD: z = cgetg(4,t_QUAD); p1 = gel(x,1); gel(z,1) = ZX_copy(p1); av = avma; p2 = gsqr(gel(x,2)); p3 = gsqr(gel(x,3)); p4 = gmul(gneg_i(gel(p1,2)),p3); if (gequal0(gel(p1,3))) { tetpil = avma; gel(z,2) = gerepile(av,tetpil,gadd(p4,p2)); av = avma; p2 = gmul(gel(x,2),gel(x,3)); tetpil = avma; gel(z,3) = gerepile(av,tetpil,gmul2n(p2,1)); return z; } p1 = gmul2n(gmul(gel(x,2),gel(x,3)), 1); tetpil = avma; gel(z,2) = gadd(p2,p4); gel(z,3) = gadd(p1,p3); gerepilecoeffssp(av,tetpil,z+2,2); return z; case t_POLMOD: return sqr_polmod(gel(x,1), gel(x,2)); case t_FFELT: return FF_sqr(x); case t_POL: return RgX_sqr(x); case t_SER: lx = lg(x); if (ser_isexactzero(x)) { GEN z = gcopy(x); setvalser(z, 2*valser(x)); return z; } if (lx < 40) return normalizeser( sqr_ser_part(x, 0, lx-3) ); else { pari_sp av = avma; GEN z = init_ser(lx, varn(x), 2*valser(x)); x = ser2pol_i(x, lx); x = RgXn_sqr(x, lx-2); return gerepilecopy(av, fill_ser(z,x)); } 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_VEC: if (!is_ext_qfr(x)) pari_err_TYPE2("*",x,x); /* fall through handle extended t_QFB */ case t_QFB: return qfbsqr(x); case t_VECSMALL: z = cgetg_copy(x, &lx); for (i=1; i= lx) pari_err_TYPE2("*",x,x); z[i] = x[xi]; } return z; } pari_err_TYPE2("*",x,x); return NULL; /* LCOV_EXCL_LINE */ } /********************************************************************/ /** **/ /** 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); if (typ(y1) == t_POL && varn(y2) == varn(y1)) { if (degpol(y1)) { pari_sp av = avma; GEN _1 = Rg_get_1(x); if (transtype(_1)) y1 = gmul(y1, _1); return gerepileupto(av, gred_rfrac_simple(gmul(x, y2), y1)); } y1 = gel(y1,2); } return RgX_Rg_mul(y2, gdiv(x,y1)); } static GEN div_rfrac(GEN x, GEN y) { return mul_rfrac(gel(x,1),gel(x,2), gel(y,2),gel(y,1)); } /* x != 0 */ static GEN div_ser_scal(GEN y, GEN x) { long i, l; GEN z; if (ser_isexactzero(y)) { z = scalarser(lg(y) == 2? Rg_get_0(x): gdiv(gel(y,2), x), varn(y), 1); setvalser(z, valser(y)); return z; } z = cgetg_copy(y, &l); z[1] = y[1]; for (i = 2; i < l; i++) gel(z,i) = gdiv(gel(y,i), x); return normalizeser(z); } GEN ser_normalize(GEN x) { long i, lx = lg(x); GEN c, z; if (lx == 2) return x; c = gel(x,2); if (gequal1(c)) return x; z = cgetg(lx, t_SER); z[1] = x[1]; gel(z,2) = gen_1; for (i=3; i b) { M = gel(y,3); } else { M = gel(x,3); b = a; } z = cgetg(5, t_PADIC); z[1] = _evalprecp(b) | evalvalp(valp(x) - valp(y)); gel(z,2) = icopy(gel(x,2)); gel(z,3) = icopy(M); av = avma; gel(z,4) = gerepileuptoint(av, remii(mulii(gel(x,4), Fp_inv(gel(y,4), M)), M) ); return z; } static GEN div_polmod_same(GEN T, GEN x, GEN y) { long v = varn(T); GEN a, z = cgetg(3, t_POLMOD); gel(z,1) = RgX_copy(T); if (typ(y) != t_POL || varn(y) != v || lg(y) <= 3) a = gdiv(x, y); else if (typ(x) != t_POL || varn(x) != v || lg(x) <= 3) { pari_sp av = avma; a = gerepileupto(av, gmul(x, RgXQ_inv(y, T))); } else if (degpol(T) == 2 && isint1(gel(T,4))) /* quadratic fields */ { pari_sp av = avma; a = quad_polmod_mul(T, x, quad_polmod_conj(y, T)); a = RgX_Rg_div(a, quad_polmod_norm(y, T)); a = gerepileupto(av, a); } else { pari_sp av = avma; 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: return Qdivii(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); warn_coercion(X,Y,gel(z,1)); av = avma; p1 = mulii(gel(x,2), Fp_inv(gel(y,2), gel(z,1))); gel(z,2) = gerepileuptoint(av, remii(p1, gel(z,1))); return z; } case t_FRAC: { 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 (!equali1(p1)) { x1 = diviiexact(x1,p1); y1 = diviiexact(y1,p1); } p1 = gcdii(x2, y2); if (!equali1(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, conj_i(y)); tetpil = avma; return gerepile(av, tetpil, gdiv(p2,p1)); case t_PADIC: if (!equalii(gel(x,2),gel(y,2))) pari_err_OP("/",x,y); return divpp(x, y); case t_QUAD: if (!ZX_equal(gel(x,1),gel(y,1))) pari_err_OP("/",x,y); av = avma; p1 = quadnorm(y); p2 = mulqq(x, conj_i(y)); tetpil = avma; return gerepile(av, tetpil, gdiv(p2,p1)); case t_FFELT: return FF_div(x,y); case t_POLMOD: if (RgX_equal_var(gel(x,1), gel(y,1))) z = div_polmod_same(gel(x,1), gel(x,2), gel(y,2)); else { av = avma; z = gerepileupto(av, gmul(x, ginv(y))); } return z; case t_POL: vx = varn(x); vy = varn(y); if (vx != vy) { if (varncmp(vx, vy) < 0) return RgX_Rg_div(x, y); else return div_scal_pol(x, y); } if (!signe(y)) pari_err_INV("gdiv",y); if (lg(y) == 3) return RgX_Rg_div(x,gel(y,2)); av = avma; return gerepileupto(av, gred_rfrac2(x,y)); case t_SER: vx = varn(x); vy = varn(y); if (vx != vy) { if (varncmp(vx, vy) < 0) { if (!signe(y)) pari_err_INV("gdiv",y); return div_ser_scal(x, y); } 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_VEC: /* handle extended t_QFB */ case t_QFB: av = avma; return gerepileupto(av, qfbcomp(x, ginv(y))); case t_MAT: p1 = RgM_div(x,y); if (!p1) pari_err_INV("gdiv",y); return p1; default: pari_err_TYPE2("/",x,y); } if (tx==t_INT && is_const_t(ty)) /* optimized for speed */ { long s = signe(x); if (!s) { if (gequal0(y)) pari_err_INV("gdiv",y); switch (ty) { default: return gen_0; case t_INTMOD: z = cgetg(3,t_INTMOD); gel(z,1) = icopy(gel(y,1)); gel(z,2) = gen_0; return z; case t_FFELT: return FF_zero(y); } } if (is_pm1(x)) { if (s > 0) return ginv(y); av = avma; return gerepileupto(av, ginv(gneg(y))); } switch(ty) { case t_REAL: return divir(x,y); case t_INTMOD: z = cgetg(3, t_INTMOD); return div_intmod_same(z, gel(y,1), modii(x, gel(y,1)), gel(y,2)); case t_FRAC: z = cgetg(3,t_FRAC); p1 = gcdii(x,gel(y,1)); if (equali1(p1)) { set_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, conj_i(y)); tetpil = avma; return gerepile(av, tetpil, gdiv(p2,p1)); } } if (gequal0(y)) { if (is_matvec_t(tx) && lg(x) == 1) return gcopy(x); if (ty != t_MAT) pari_err_INV("gdiv",y); } if (is_const_t(tx) && is_const_t(ty)) switch(tx) { 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, realprec(x)); default: pari_err_TYPE2("/",x,y); } case t_INTMOD: switch(ty) { case t_INT: z = cgetg(3, t_INTMOD); return div_intmod_same(z, gel(x,1), gel(x,2), modii(y, gel(x,1))); case t_FRAC: { GEN X = gel(x,1); z = cgetg(3,t_INTMOD); p1 = remii(mulii(gel(y,2), gel(x,2)), X); return div_intmod_same(z, X, p1, modii(gel(y,1), X)); } case t_FFELT: if (!equalii(gel(x,1),FF_p_i(y))) pari_err_OP("/",x,y); return Z_FF_div(gel(x,2),y); case t_COMPLEX: av = avma; return gerepileupto(av, mulRc_direct(gdiv(x,cxnorm(y)), conj_i(y))); case t_QUAD: av = avma; p1 = quadnorm(y); p2 = gmul(x,conj_i(y)); tetpil = avma; return gerepile(av,tetpil, gdiv(p2,p1)); case t_PADIC: { GEN X = gel(x,1); z = cgetg(3, t_INTMOD); return div_intmod_same(z, X, gel(x,2), padic_to_Fp(y, X)); } case t_REAL: pari_err_TYPE2("/",x,y); } case t_FRAC: switch(ty) { case t_INT: z = cgetg(3, t_FRAC); p1 = gcdii(y,gel(x,1)); if (equali1(p1)) { set_avma((pari_sp)z); tetpil = 0; gel(z,1) = icopy(gel(x,1)); } else { y = diviiexact(y,p1); tetpil = avma; gel(z,1) = diviiexact(gel(x,1), p1); } gel(z,2) = mulii(gel(x,2),y); normalize_frac(z); if (tetpil) fix_frac_if_int_GC(z,tetpil); return z; case t_REAL: av=avma; p1=mulri(y,gel(x,2)); tetpil=avma; return gerepile(av, tetpil, divir(gel(x,1), p1)); case t_INTMOD: { GEN Y = gel(y,1); z = cgetg(3,t_INTMOD); p1 = remii(mulii(gel(y,2),gel(x,2)), Y); return div_intmod_same(z, Y, modii(gel(x,1), Y), p1); } case t_FFELT: av=avma; return gerepileupto(av,Z_FF_div(gel(x,1),FF_Z_mul(y,gel(x,2)))); case t_COMPLEX: return divRc(x, y); case t_PADIC: if (!signe(gel(x,1))) return gen_0; return divTp(x, y); case t_QUAD: av=avma; p1=quadnorm(y); p2=gmul(x,conj_i(y)); tetpil=avma; return gerepile(av,tetpil,gdiv(p2,p1)); } case t_FFELT: switch (ty) { case t_INT: return FF_Z_Z_muldiv(x,gen_1,y); case t_FRAC: return FF_Z_Z_muldiv(x,gel(y,2),gel(y,1)); case t_INTMOD: if (!equalii(gel(y,1),FF_p_i(x))) pari_err_OP("/",x,y); return FF_Z_Z_muldiv(x,gen_1,gel(y,2)); default: pari_err_TYPE2("/",x,y); } break; case t_COMPLEX: switch(ty) { case t_INT: case t_REAL: case t_FRAC: return divcR(x,y); case t_INTMOD: return mulRc_direct(ginv(y), x); case t_PADIC: return Zp_nosquare_m1(gel(y,2))? divcR(x,y): divTp(x, y); case t_QUAD: lx = precision(x); if (!lx) pari_err_OP("/",x,y); return divfq(x, y, lx); } case t_PADIC: switch(ty) { case t_INT: case t_FRAC: { GEN p = gel(x,2); return signe(gel(x,4))? divpT(x, y) : zeropadic(p, valp(x) - Q_pval(y,p)); } case t_INTMOD: { GEN Y = gel(y,1); z = cgetg(3, t_INTMOD); return div_intmod_same(z, Y, padic_to_Fp(x, Y), gel(y,2)); } case t_COMPLEX: case t_QUAD: av=avma; p1=gmul(x,conj_i(y)); p2=gnorm(y); tetpil=avma; return gerepile(av,tetpil,gdiv(p1,p2)); case t_REAL: pari_err_TYPE2("/",x,y); } case t_QUAD: switch (ty) { case t_INT: case t_INTMOD: case t_FRAC: z = cgetg(4,t_QUAD); gel(z,1) = ZX_copy(gel(x,1)); gel(z,2) = gdiv(gel(x,2), y); gel(z,3) = gdiv(gel(x,3), y); return z; case t_REAL: return divqf(x, y, realprec(y)); case t_PADIC: return divTp(x, y); case t_COMPLEX: ly = precision(y); if (!ly) pari_err_OP("/",x,y); return divqf(x, y, ly); } } switch(ty) { case t_REAL: case t_INTMOD: case t_PADIC: case t_POLMOD: return gmul(x, ginv(y)); /* missing gerepile, for speed */ case t_MAT: av = avma; p1 = RgM_inv(y); if (!p1) pari_err_INV("gdiv",y); return gerepileupto(av, gmul(x, p1)); case t_VEC: case t_COL: case t_LIST: case t_STR: case t_VECSMALL: case t_CLOSURE: pari_err_TYPE2("/",x,y); } switch(tx) { case t_VEC: case t_COL: case t_MAT: z = cgetg_copy(x, &lx); for (i=1; i 0) return div_scal_T(x, y, ty); retmkpolmod(gdiv(gel(x,2), y), RgX_copy(X)); } /* y is POL, SER or RFRAC */ av = avma; switch(ty) { case t_RFRAC: y = gmod(ginv(y), X); break; default: y = ginvmod(gmod(y,X), X); } return gerepileupto(av, mul_polmod_same(X, gel(x,2), y)); } /* x and y are not both is_scalar_t. If one of them is scalar, it's not a * POLMOD (done already), hence its variable is NO_VARIABLE. If the other has * variable NO_VARIABLE, then the operation is incorrect */ vx = gvar(x); if (vx != vy) { /* includes cases where one is scalar */ if (varncmp(vx, vy) < 0) return div_T_scal(x, y, tx); else return div_scal_T(x, y, ty); } switch(tx) { case t_POL: switch(ty) { case t_SER: { GEN y0 = y; long v; av = avma; v = RgX_valrem(x, &x); if (v == LONG_MAX) return gerepileupto(av, Rg_get_0(x)); v -= valser(y); ly = lg(y); /* > 2 */ y = ser2pol_i_normalize(y, ly, &i); if (i) { pari_warn(warner,"normalizing a series with 0 leading term"); ly -= i; v -= i; if (ly <= 2) pari_err_INV("gdiv", y0); } z = init_ser(ly, vx, v); return gerepilecopy(av, fill_ser(z, RgXn_div(x, y, ly-2))); } 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: { long v = valser(x); lx = lg(x); if (lx == 2) return zeroser(vx, v - RgX_val(y)); av = avma; x = ser2pol_i(x, lx); v -= RgX_valrem_inexact(y, &y); z = init_ser(lx, vx, v); if (!signe(x)) setsigne(z,0); return gerepilecopy(av, fill_ser(z, RgXn_div(x, y, lx - 2))); } 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; return gerepileupto(av, gdiv(gel(x,1), gmul(gel(x,2), y))); } break; } pari_err_TYPE2("/",x,y); return NULL; /* LCOV_EXCL_LINE */ } /********************************************************************/ /** **/ /** 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 s? mulsr(s,y): gen_0; /* gmul semantic */ 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 = labs(s); i = ugcd(i, umodiu(gel(y,2), i)); if (i == 1) { gel(z,2) = icopy(gel(y,2)); gel(z,1) = mulis(gel(y,1), s); } else { gel(z,2) = diviuexact(gel(y,2), (ulong)i); gel(z,1) = mulis(gel(y,1), s/i); fix_frac_if_int(z); } return z; case t_COMPLEX: if (!s) return gen_0; 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: retmkpolmod(gmulsg(s,gel(y,2)), RgX_copy(gel(y,1))); case t_POL: if (!signe(y)) return RgX_copy(y); if (!s) return scalarpol(Rg_get_0(y), varn(y)); z = cgetg_copy(y, &ly); z[1]=y[1]; for (i=2; i= 2^BITS_IN_LONG*/ return divri(x, muluu(i , i+1)); else return divru(x, i*(i+1)); } /* x / (i*(i+1)) */ GEN gdivgunextu(GEN x, ulong i) { if (i & HIGHMASK) /* i(i+1) >= 2^BITS_IN_LONG*/ return gdivgu(x, i*(i+1)); else return gdiv(x, muluu(i, i+1)); } /* True shift (exact multiplication by 2^n) */ GEN gmul2n(GEN x, long n) { long lx, i, k, l; GEN z, a, b; switch(typ(x)) { case t_INT: if (n>=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: retmkpolmod(gmul2n(gel(x,2),n), RgX_copy(gel(x,1))); case t_POL: z = cgetg_copy(x, &lx); z[1] = x[1]; for (i=2; i 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=quadnorm(x); p2=conj_i(x); tetpil=avma; return gerepile(av,tetpil,gdiv(p2,p1)); case t_PADIC: z = cgetg(5,t_PADIC); if (!signe(gel(x,4))) pari_err_INV("ginv",x); z[1] = _evalprecp(precp(x)) | evalvalp(-valp(x)); gel(z,2) = icopy(gel(x,2)); gel(z,3) = icopy(gel(x,3)); gel(z,4) = Zp_inv(gel(x,4),gel(z,2),precp(x)); 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 ser_inv(x); case t_RFRAC: { GEN n = gel(x,1), d = gel(x,2); pari_sp av = avma, ltop; if (gequal0(n)) pari_err_INV("ginv",x); n = simplify_shallow(n); if (typ(n) != t_POL || varn(n) != varn(d)) { if (gequal1(n)) { set_avma(av); return RgX_copy(d); } ltop = avma; z = RgX_Rg_div(d,n); } else { ltop = avma; z = cgetg(3,t_RFRAC); gel(z,1) = RgX_copy(d); gel(z,2) = RgX_copy(n); } stackdummy(av, ltop); return z; } case t_VEC: if (!is_ext_qfr(x)) break; case t_QFB: return qfbpow(x, gen_m1); case t_MAT: y = RgM_inv(x); if (!y) pari_err_INV("ginv",x); return y; case t_VECSMALL: { long i, lx = lg(x)-1; y = zero_zv(lx); for (i=1; i<=lx; i++) { long xi = x[i]; if (xi<1 || xi>lx || y[xi]) pari_err_TYPE("ginv [not a permutation]", x); y[xi] = i; } return y; } } pari_err_TYPE("inverse",x); return NULL; /* LCOV_EXCL_LINE */ } pari-2.17.2/src/basemath/perm.c0000644000175000017500000013133114760123736014661 0ustar billbill/* Copyright (C) 2000-2003 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #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 max) { max = v[i]; if (max >= l) return -1; } else if (v[i] < 0) return -1; return max; } /* assume 0 <= v[i] <= M. In place. */ void vecsmall_counting_sort(GEN v, long M) { pari_sp av; long i, j, k, l; GEN T; if (M == 0) return; av = avma; T = new_chunk(M + 1); l = lg(v); for (i = 0; i <= M; i++) T[i] = 0; for (i = 1; i < l; i++) T[v[i]]++; /* T[j] is # keys = j */ for (j = 0, k = 1; j <= M; j++) for (i = 1; i <= T[j]; i++) v[k++] = j; set_avma(av); } /* not GC-clean, suitable for gerepileupto */ GEN vecsmall_counting_uniq(GEN v, long M) { long i, k, l = lg(v); GEN T, U; if (l == 1) return cgetg(1, t_VECSMALL); if (M == 0) return mkvecsmall(0); if (l == 2) return leafcopy(v); U = new_chunk(M + 2); T = U+1; /* allows to rewrite result over T also if T[0] = 1 */ for (i = 0; i <= M; i++) T[i] = 0; for (i = 1; i < l; i++) T[v[i]] = 1; for (i = 0, k = 1; i <= M; i++) if (T[i]) U[k++] = i; U[0] = evaltyp(t_VECSMALL) | _evallg(k); return U; } GEN vecsmall_counting_indexsort(GEN v, long M) { pari_sp av; long i, l = lg(v); GEN T, p; if (M == 0 || l <= 2) return identity_zv(l - 1); p = cgetg(l, t_VECSMALL); av = avma; T = new_chunk(M + 1); for (i = 0; i <= M; i++) T[i] = 0; for (i = 1; i < l; i++) T[v[i]]++; /* T[j] is # keys = j */ for (i = 1; i <= M; i++) T[i] += T[i-1]; /* T[j] is # keys <= j */ for (i = l-1; i > 0; i--) { p[T[v[i]]] = i; T[v[i]]--; } return gc_const(av, p); } /* in place sort */ void vecsmall_sort(GEN v) { long n = lg(v) - 1, max; if (n <= 1) return; if ((max = vecsmall_sort_max(v)) >= 0) vecsmall_counting_sort(v, max); else vecsmall_sortspec(v+1, n, v+1); } /* cf gen_sortspec */ static GEN vecsmall_indexsortspec(GEN v, long n) { long nx, ny, m, ix, iy; GEN x, y, w; switch(n) { case 1: return mkvecsmall(1); case 2: return (v[1] <= v[2])? mkvecsmall2(1,2): mkvecsmall2(2,1); case 3: if (v[1] <= v[2]) { if (v[2] <= v[3]) return mkvecsmall3(1,2,3); return (v[1] <= v[3])? mkvecsmall3(1,3,2) : mkvecsmall3(3,1,2); } else { if (v[1] <= v[3]) return mkvecsmall3(2,1,3); return (v[2] <= v[3])? mkvecsmall3(2,3,1) : mkvecsmall3(3,2,1); } } nx = n>>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; set_avma((pari_sp)w); return w; } /*indirect sort.*/ GEN vecsmall_indexsort(GEN v) { long n = lg(v) - 1, max; if (n==0) return cgetg(1, t_VECSMALL); if ((max = vecsmall_sort_max(v)) >= 0) return vecsmall_counting_indexsort(v, max); else return vecsmall_indexsortspec(v,n); } /* assume V sorted */ GEN vecsmall_uniq_sorted(GEN v) { long i, j, l; GEN w = cgetg_copy(v, &l); if (l == 1) return w; w[1] = v[1]; for(i = j = 2; i < l; i++) if (v[i] != w[j-1]) w[j++] = v[i]; stackdummy((pari_sp)(w + l), (pari_sp)(w + j)); setlg(w, j); return w; } GEN vecsmall_uniq(GEN v) { pari_sp av = avma; long max; if ((max = vecsmall_sort_max(v)) >= 0) v = vecsmall_counting_uniq(v, max); else { v = zv_copy(v); vecsmall_sort(v); v = vecsmall_uniq_sorted(v); } return gerepileuptoleaf(av, v); } /* assume x sorted */ long vecsmall_duplicate_sorted(GEN x) { long i,k,l=lg(x); if (l==1) return 0; for (k=x[1],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) return 0; else if (v0 m) m = t; } return m; } /*************************************************************************/ /** **/ /** Routines for handling permutations **/ /** **/ /*************************************************************************/ /* Permutations may be given by * perm (VECSMALL): a bijection from 1...n to 1...n i-->perm[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]]; } GEN vecperm_extendschreier(GEN C, GEN v, long n) { pari_sp av = avma; long mj, lv = lg(v), m = 1, mtested = 1; GEN bit = const_vecsmall(n, 0); GEN cy = cgetg(n+1, t_VECSMALL); GEN sh = const_vec(n, gen_0); for(mj=1; mj<=n; mj++) { if (isintzero(gel(C,mj))) continue; gel(sh,mj) = gcopy(gel(C,mj)); if (bit[mj]) continue; cy[m++] = mj; bit[mj] = 1; for(;;) { long o, mold = m; for (o = 1; o < lv; o++) { GEN vo = gel(v,o); long p; for (p = mtested; p < mold; p++) /* m increases! */ { long j = vo[ cy[p] ]; if (!bit[j]) { gel(sh,j) = perm_mul(vo, gel(sh, cy[p])); cy[m++] = j; } bit[j] = 1; } } mtested = mold; if (m == mold) break; } } return gerepileupto(av, sh); } /* Orbits of the subgroup generated by v on {1,..,n} */ static GEN vecperm_orbits_i(GEN v, long n) { long mj = 1, lv = lg(v), k, l; GEN cycle = cgetg(n+1, t_VEC), bit = const_vecsmall(n, 0); for (k = 1, l = 1; k <= n;) { pari_sp ltop = avma; long m = 1; GEN cy = cgetg(n+1, t_VECSMALL); for ( ; bit[mj]; mj++) /*empty*/; k++; cy[m++] = mj; bit[mj++] = 1; for(;;) { long o, mold = m; for (o = 1; o < lv; o++) { GEN vo = gel(v,o); long p; for (p = 1; p < m; p++) /* m increases! */ { long j = vo[ cy[p] ]; if (!bit[j]) cy[m++] = j; bit[j] = 1; } } if (m == mold) break; k += m - mold; } setlg(cy, m); gel(cycle,l++) = gerepileuptoleaf(ltop, 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)); } static int isperm(GEN v) { pari_sp av = avma; long i, n = lg(v)-1; GEN w; if (typ(v) != t_VECSMALL) return 0; w = zero_zv(n); for (i=1; i<=n; i++) { long d = v[i]; if (d < 1 || d > n || w[d]) return gc_bool(av,0); w[d] = 1; } return gc_bool(av,1); } /* 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)); } GEN permcycles(GEN v) { if (!isperm(v)) pari_err_TYPE("permcycles",v); return perm_cycles(v); } /* Output the order of p */ ulong perm_orderu(GEN v) { pari_sp av = avma; GEN c = vecperm_orbits_i(mkvec(v), lg(v)-1); long i, d; for(i=1, d=1; i=1; r--) { ulong a; x = absdiviu_rem(x, n+1-r, &a); for (i=r+1; i<=(ulong)n; i++) if (uel(v,i) > a) uel(v,i)++; uel(v,r) = a+1; } set_avma(av); return v; } GEN numtoperm(long n, GEN x) { if (n < 0) pari_err_DOMAIN("numtoperm", "n", "<", gen_0, stoi(n)); if (typ(x) != t_INT) pari_err_TYPE("numtoperm",x); return Z_to_perm(n, x); } /* destroys v */ static GEN perm_to_Z_inplace(GEN v) { long l = lg(v), i, r; GEN x = gen_0; if (!isperm(v)) return NULL; for (i = 1; i < l; i++) { long vi = v[i]; if (vi <= 0) return NULL; x = i==1 ? utoi(vi-1): addiu(muliu(x,l-i), vi-1); for (r = i+1; r < l; r++) if (v[r] > vi) v[r]--; } return x; } GEN perm_to_Z(GEN v) { pari_sp av = avma; GEN x = perm_to_Z_inplace(leafcopy(v)); if (!x) pari_err_TYPE("permtonum",v); return gerepileuptoint(av, x); } GEN permtonum(GEN p) { pari_sp av = avma; GEN v, x; switch(typ(p)) { case t_VECSMALL: return perm_to_Z(p); case t_VEC: case t_COL: if (RgV_is_ZV(p)) { v = ZV_to_zv(p); break; } default: pari_err_TYPE("permtonum",p); return NULL;/*LCOV_EXCL_LINE*/ } x = perm_to_Z_inplace(v); if (!x) pari_err_TYPE("permtonum",p); return gerepileuptoint(av, x); } GEN cyc_pow(GEN cyc, long exp) { long i, j, k, l, r; GEN c; for (r = j = 1; j < lg(cyc); j++) { long n = lg(gel(cyc,j)) - 1; r += cgcd(n, exp); } c = cgetg(r, t_VEC); for (r = j = 1; j < lg(cyc); j++) { GEN v = gel(cyc,j); long n = lg(v) - 1, e = umodsu(exp,n), g = (long)ugcd(n, e), m = n / g; for (i = 0; i < g; i++) { GEN p = cgetg(m+1, t_VECSMALL); gel(c,r++) = p; for (k = 1, l = i; k <= m; k++) { p[k] = v[l+1]; l += e; if (l >= n) l -= n; } } } return c; } /* Compute the power of a permutation given by product of cycles * Ouput a perm, not a cyc */ GEN cyc_pow_perm(GEN cyc, long exp) { long e, j, k, l, n; GEN p; for (n = 0, j = 1; j < lg(cyc); j++) n += lg(gel(cyc,j))-1; p = cgetg(n + 1, t_VECSMALL); for (j = 1; j < lg(cyc); j++) { GEN v = gel(cyc,j); n = lg(v) - 1; e = umodsu(exp, n); for (k = 1, l = e; k <= n; k++) { p[v[k]] = v[l+1]; if (++l == n) l = 0; } } return p; } GEN perm_pow(GEN perm, GEN exp) { long i, r = lg(perm)-1; GEN p = zero_zv(r); pari_sp av = avma; GEN v = cgetg(r+1, t_VECSMALL); for (i=1; i<=r; i++) { long e, n, k, l; if (p[i]) continue; v[1] = i; for (n=1, k=perm[i]; k!=i; k=perm[k], n++) v[n+1] = k; e = umodiu(exp, n); for (k = 1, l = e; k <= n; k++) { p[v[k]] = v[l+1]; if (++l == n) l = 0; } } set_avma(av); return p; } GEN perm_powu(GEN perm, ulong exp) { ulong i, r = lg(perm)-1; GEN p = zero_zv(r); pari_sp av = avma; GEN v = cgetg(r+1, t_VECSMALL); for (i=1; i<=r; i++) { ulong e, n, k, l; if (p[i]) continue; v[1] = i; for (n=1, k=perm[i]; k!=i; k=perm[k], n++) v[n+1] = k; e = exp % n; for (k = 1, l = e; k <= n; k++) { p[v[k]] = v[l+1]; if (++l == n) l = 0; } } set_avma(av); return p; } GEN perm_to_GAP(GEN p) { pari_sp ltop=avma; GEN gap; GEN x; long i; long nb, c=0; char *s; long sz; long lp=lg(p)-1; if (typ(p) != t_VECSMALL) pari_err_TYPE("perm_to_GAP",p); x = perm_cycles(p); sz = (long) ((bfffo(lp)+1) * LOG10_2 + 1); /*Dry run*/ for (i = 1, nb = 1; i < lg(x); ++i) { GEN z = gel(x,i); long lz = lg(z)-1; nb += 1+lz*(sz+2); } nb++; /*Real run*/ gap = cgetg(nchar2nlong(nb) + 1, t_STR); s = GSTR(gap); for (i = 1; i < lg(x); ++i) { long j; GEN z = gel(x,i); if (lg(z) > 2) { s[c++] = '('; for (j = 1; j < lg(z); ++j) { if (j > 1) { s[c++] = ','; s[c++] = ' '; } sprintf(s+c,"%ld",z[j]); while(s[c++]) /* empty */; c--; } s[c++] = ')'; } } if (!c) { s[c++]='('; s[c++]=')'; } s[c] = '\0'; return gerepileupto(ltop,gap); } int perm_commute(GEN s, GEN t) { long i, l = lg(t); for (i = 1; i < l; i++) if (t[ s[i] ] != s[ t[i] ]) return 0; return 1; } /*************************************************************************/ /** **/ /** Routines for handling groups **/ /** **/ /*************************************************************************/ /* A Group is a t_VEC [gen,orders] * gen (vecvecsmall): list of generators given by permutations * orders (vecsmall): relatives orders of generators. */ INLINE GEN grp_get_gen(GEN G) { return gel(G,1); } INLINE GEN grp_get_ord(GEN G) { return gel(G,2); } /* A Quotient Group is a t_VEC [gen,coset] * gen (vecvecsmall): coset generators * coset (vecsmall): gen[coset[p[1]]] generate the p-coset. */ INLINE GEN quo_get_gen(GEN C) { return gel(C,1); } INLINE GEN quo_get_coset(GEN C) { return gel(C,2); } static GEN trivialsubgroups(void) { GEN L = cgetg(2, t_VEC); gel(L,1) = trivialgroup(); return L; } /* Compute the order of p modulo the group given by a set */ long perm_relorder(GEN p, GEN set) { pari_sp ltop = avma; long n = 1, q = p[1]; while (!F2v_coeff(set,q)) { q = p[q]; n++; } return gc_long(ltop,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 (cardinality) of a group */ long group_order(GEN G) { return zv_prod(grp_get_ord(G)); } /* G being a subgroup of S_n, output n */ long group_domain(GEN G) { GEN gen = grp_get_gen(G); if (lg(gen) < 2) pari_err_DOMAIN("group_domain", "#G", "=", gen_1,G); return lg(gel(gen,1)) - 1; } /*Left coset of g mod G: gG*/ GEN group_leftcoset(GEN G, GEN g) { GEN gen = grp_get_gen(G), ord = grp_get_ord(G); GEN res = cgetg(group_order(G)+1, t_VEC); long i, j, k; gel(res,1) = vecsmall_copy(g); k = 1; for (i = 1; i < lg(gen); i++) { long c = k * (ord[i] - 1); for (j = 1; j <= c; j++) gel(res,++k) = perm_mul(gel(res,j), gel(gen,i)); } return res; } /*Right coset of g mod G: Gg*/ GEN group_rightcoset(GEN G, GEN g) { GEN gen = grp_get_gen(G), ord = grp_get_ord(G); GEN res = cgetg(group_order(G)+1, t_VEC); long i, j, k; gel(res,1) = vecsmall_copy(g); k = 1; for (i = 1; i < lg(gen); i++) { long c = k * (ord[i] - 1); for (j = 1; j <= c; j++) gel(res,++k) = perm_mul(gel(gen,i), gel(res,j)); } return res; } /*Elements of a group from the generators, cf group_leftcoset*/ GEN group_elts(GEN G, long n) { if (lg(G)==3 && typ(gel(G,1))==t_VEC) { 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; } else return gcopy(G); } GEN groupelts_conj_set(GEN elts, GEN p) { long i, j, l = lg(elts), n = lg(p)-1; GEN res = zero_F2v(n); for(j = 1; j < n; j++) if (p[j]==1) break; for(i = 1; i < l; i++) F2v_set(res, p[mael(elts,i,j)]); 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 groupelts_quotient(GEN elt, GEN H) { pari_sp ltop = avma; GEN p2, p3; long i, j, a = 1; long n = lg(gel(elt,1))-1, o = group_order(H); GEN el; long le = lg(elt)-1; GEN used = zero_F2v(le+1); long l = le/o; p2 = cgetg(l+1, t_VEC); p3 = zero_zv(n); el = zero_zv(n); for (i = 1; i<=le; i++) el[mael(elt,i,1)]=i; for (i = 1; i <= l; ++i) { GEN V; while(F2v_coeff(used,a)) a++; V = group_leftcoset(H,gel(elt,a)); gel(p2,i) = gel(V,1); for(j=1;j G/H * * Lift a subgroup S of G/H to a subgroup of G containing H */ GEN quotient_subgroup_lift(GEN C, GEN H, GEN S) { GEN genH = grp_get_gen(H); GEN genS = grp_get_gen(S); GEN genC = quo_get_gen(C); long l1 = lg(genH)-1; long l2 = lg(genS)-1, j; GEN p1 = cgetg(3, t_VEC), L = cgetg(l1+l2+1, t_VEC); for (j = 1; j <= l1; ++j) gel(L,j) = gel(genH,j); for (j = 1; j <= l2; ++j) gel(L,l1+j) = gel(genC, mael(genS,j,1)); gel(p1,1) = L; gel(p1,2) = vecsmall_concat(grp_get_ord(H), grp_get_ord(S)); return p1; } /* Let G a group and C a quotient map G --> G/H * Assume H is normal, return the group G/H */ GEN quotient_group(GEN C, GEN G) { pari_sp ltop = avma; GEN Qgen, Qord, Qelt, Qset, Q; GEN Cgen = quo_get_gen(C); GEN Ggen = grp_get_gen(G); long i,j, n = lg(Cgen)-1, l = lg(Ggen); Qord = cgetg(l, t_VECSMALL); Qgen = cgetg(l, t_VEC); Qelt = mkvec(identity_perm(n)); Qset = groupelts_set(Qelt, n); for (i = 1, j = 1; i < l; ++i) { GEN g = quotient_perm(C, gel(Ggen,i)); long o = perm_relorder(g, Qset); gel(Qgen,j) = g; Qord[j] = o; if (o != 1) { Qelt = perm_generate(g, Qelt, o); Qset = groupelts_set(Qelt, n); j++; } } setlg(Qgen,j); setlg(Qord,j); Q = mkvec2(Qgen, Qord); return gerepilecopy(ltop,Q); } GEN quotient_groupelts(GEN C) { GEN G = quo_get_gen(C); long i, l = lg(G); GEN Q = cgetg(l, t_VEC); for (i = 1; i < l; ++i) gel(Q,i) = quotient_perm(C, gel(G,i)); return 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_shallow(group_leftcoset(N, g)), vecvecsmall_sort_shallow(group_rightcoset(N, g))); return gc_long(ltop, 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(vec_append(gen, 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, 3:F36, 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 (n==4 && ord[1]==3 && ord[2]==3 && ord[3]==4) { long i; GEN p = gel(elt,1), q = gel(elt,2), r = gel(elt,3); for(i=1; i<=36; i++) if (p[r[i]]!=r[q[i]]) return 0; return 3; } 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); long t; if (n == 1) return trivialsubgroups(); t = group_isA4S4(G); if (t == 3) { GEN H = mkvec2(mkvec3(gel(gen,1), gel(gen,2), perm_sqr(gel(gen,3))), mkvecsmall3(3, 3, 2)); GEN S = group_subgroups(H); GEN V = cgetg(11,t_VEC); gel(V,1) = cyclicgroup(gel(gen,3),4); for (i=2; i<10; i++) gel(V,i) = cyclicgroup(perm_mul(gmael3(V,i-1,1,1),gel(gen,i%3==1 ? 2:1)),4); gel(V,10) = G; return gerepilecopy(ltop,shallowconcat(S,V)); } else if (t) { 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_sqr(u); else { u2 = u; u = perm_sqr(u); } if (perm_orderu(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_sqr(w), s)) /*w=(1,4,2,3)*/ { w = perm_conj(u,w); if (!zv_equal(perm_sqr(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 { ulong osig = mael(factoru(ord[1]), 1, 1); GEN sig = perm_powu(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 = gconcat(sg1, shallowconcat1(sg2)); if (sg3) { p1 = gconcat(p1, sg3); if (n==5) /*ensure that the D4 subgroups of S4 are in supersolvable format*/ for(j = 3; j <= 5; j++) { GEN c = gmael(p1,j,1); if (!perm_commute(gel(c,1),gel(c,3))) { if (perm_commute(gel(c,2),gel(c,3))) { swap(gel(c,1), gel(c,2)); } else perm_mul_inplace2(gel(c,2), gel(c,1)); } } } return gerepileupto(ltop,p1); } /*return 1 if G is abelian, else 0*/ long group_isabelian(GEN G) { GEN g = grp_get_gen(G); long i, j, n = lg(g); for(i=2; i 1 && group_domain(G) != group_domain(H)) pari_err_DOMAIN("group_subgroup_isnormal","domain(H)","!=", strtoGENstr("domain(G)"), H); return groupelts_subgroup_isnormal(grp_get_gen(G), H); } static GEN group_subgroup_kernel_set(GEN G, GEN H) { pari_sp av; GEN g = grp_get_gen(G); long i, n = lg(g); GEN S, elts; long d = group_domain(G); if (lg(grp_get_gen(H)) > 1 && group_domain(G) != group_domain(H)) pari_err_DOMAIN("group_subgroup_isnormal","domain(H)","!=", strtoGENstr("domain(G)"), H); elts = group_elts(H,d); S = groupelts_set(elts, d); av = avma; for(i=1; i 1) gel(s,k++) = comma; gel(s,k++) = perm_to_GAP(gel(g,i)); } gel(s,k++) = strtoGENstr(")"); return gerepilecopy(av, shallowconcat1(s)); } GEN group_export_MAGMA(GEN G) { pari_sp av = avma; GEN s, comma, g = grp_get_gen(G); long i, k, l = lg(g); if (l == 1) return strtoGENstr("PermutationGroup<1|>"); s = cgetg(2*l, t_VEC); comma = strtoGENstr(", "); gel(s,1) = gsprintf("PermutationGroup<%ld|",group_domain(G)); for (i=1, k=2; i < l; ++i) { if (i > 1) gel(s,k++) = comma; gel(s,k++) = GENtoGENstr( vecsmall_to_vec(gel(g,i)) ); } gel(s,k++) = strtoGENstr(">"); return gerepilecopy(av, shallowconcat1(s)); } GEN group_export(GEN G, long format) { switch(format) { case 0: return group_export_GAP(G); case 1: return group_export_MAGMA(G); } pari_err_FLAG("galoisexport"); return NULL; /*-Wall*/ } static GEN groupelts_cyclic_subgroups(GEN G) { pari_sp av = avma; long i, j, n = lg(G)-1; GEN elts, f, gen, ord; if (n==1) return cgetg(1,t_VEC); elts = zero_F2v(lg(gel(G,1))-1); gen = cgetg(n+1, t_VECSMALL); ord = cgetg(n+1, t_VECSMALL); for (i=1, j=1; i<=n; i++) { long k = 1, o, c = 0; GEN p = gel(G, i); if (F2v_coeff(elts, p[1])) continue; o = perm_orderu(p); gen[j] = i; ord[j] = o; j++; do { if (cgcd(o, ++c)==1) F2v_set(elts, p[k]); k = p[k]; } while (k!=1); } setlg(gen, j); setlg(ord, j); f = vecsmall_indexsort(ord); return gerepilecopy(av, mkvec2(vecsmallpermute(gen, f), vecsmallpermute(ord, f))); } GEN groupelts_to_group(GEN G) { pari_sp av = avma; GEN L, cyc, ord; long i, l, n = lg(G)-1; if (n==1) return trivialgroup(); L = groupelts_cyclic_subgroups(G); cyc = gel(L,1); ord = gel(L,2); l = lg(cyc); for (i = l-1; i >= 2; i--) { GEN p = gel(G,cyc[i]); long o = ord[i]; GEN H = cyclicgroup(p, o); if (o == n) return gerepileupto(av, H); if (groupelts_subgroup_isnormal(G, H)) { GEN C = groupelts_quotient(G, H); GEN Q = quotient_groupelts(C); GEN R = groupelts_to_group(Q); if (!R) return gc_NULL(av); return gerepilecopy(av, quotient_subgroup_lift(C, H, R)); } } if (n==12 && l==9 && ord[2]==2 && ord[3]==2 && ord[5]==3) return gerepilecopy(av, mkvec2(mkvec3(gel(G,cyc[2]), gel(G,cyc[3]), gel(G,cyc[5])), mkvecsmall3(2,2,3))); if (n==24 && l==18 && ord[11]==3 && ord[15]==4 && ord[16]==4) { GEN t21 = perm_sqr(gel(G,cyc[15])); GEN t22 = perm_sqr(gel(G,cyc[16])); GEN s = perm_mul(t22, gel(G,cyc[15])); return gerepilecopy(av, mkvec2(mkvec4(t21,t22, gel(G,cyc[11]), s), mkvecsmall4(2,2,3,2))); } if (n==36 && l==24 && ord[11]==3 && ord[15]==4) { GEN t1 = gel(G,cyc[11]), t3 = gel(G,cyc[15]); return gerepilecopy(av, mkvec2(mkvec3(perm_conj(t3, t1), t1, t3), mkvecsmall3(3,3,4))); } return gc_NULL(av); } static GEN subg_get_gen(GEN subg) { return gel(subg, 1); } static GEN subg_get_set(GEN subg) { return gel(subg, 2); } static GEN groupelt_subg_normalize(GEN elt, GEN subg, GEN cyc) { GEN gen = subg_get_gen(subg), set = subg_get_set(subg); long i, j, u, n = lg(elt)-1, lgen = lg(gen); GEN b = F2v_copy(cyc), res = zero_F2v(n); for(i = 1; i <= n; i++) { GEN g; if (!F2v_coeff(b, i)) continue; g = gel(elt,i); for(u=1; u<=n; u++) if (g[u]==1) break; for(j=1; j 1 && o < oo); if (o==1) return NULL; return gerepilecopy(av,mkvec2(set_idx(set), set)); } static GEN all_cyclic_subg(GEN pr, GEN po, GEN elt) { long i, n = lg(pr)-1, m = 0, k = 1; GEN W; for (i=1; i <= n; i++) m += po[i]==1; W = cgetg(m+1, t_VEC); for (i=1; i <= n; i++) if (po[i]==1) gel(W, k++) = cyclic_subg(i, pr[i], elt); return W; } static GEN groupelts_subgroups_raw(GEN elts) { pari_sp av = avma; GEN elt = groupelts_to_regular(elts); GEN pr, po, cyc = groupelts_cyclic_primepow(elt, &pr, &po); long n = lg(elt)-1; long i, j, nS = 1; GEN S, L, R = NULL; S = cgetg(1+bigomegau(n)+1, t_VEC); gel(S, nS++) = mkvec(triv_subg(elt)); gel(S, nS++) = L = all_cyclic_subg(pr, po, elt); if (DEBUGLEVEL) err_printf("subgroups: level %ld: %ld\n",nS-1,lg(L)-1); while (lg(L) > 1) { pari_sp av2 = avma; long nW = 1, lL = lg(L); long ng = n; GEN W = cgetg(1+ng, t_VEC); for (i=1; i ng) { ng<<=1; W = vec_lengthen(W, ng); } gel(W, nW++) = U2; } } } setlg(W, nW); L = W; if (nW > 1) gel(S, nS++) = L = gerepilecopy(av2, W); if (DEBUGLEVEL) err_printf("subgroups: level %ld: %ld\n",nS-1,nW-1); if (lg(L)==1 && !R) { R = groupelts_residuum(elt); if (!R) break; gel(S, nS++) = L = mkvec(R); } } setlg(S, nS); return gerepilecopy(av, shallowconcat1(S)); } static GEN subg_to_elts(GEN S, GEN x) { pari_APPLY_type(t_VEC, set_groupelts(S, gmael(x,i,2))); } GEN groupelts_solvablesubgroups(GEN G) { pari_sp av = avma; GEN S = vecvecsmall_sort(checkgroupelts(G)); GEN L = groupelts_subgroups_raw(S); return gerepilecopy(av, subg_to_elts(S, L)); } pari-2.17.2/src/basemath/nffactor.c0000644000175000017500000021034714676526175015537 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; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*******************************************************************/ /* */ /* POLYNOMIAL FACTORIZATION IN A NUMBER FIELD */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_nffactor static GEN nfsqff(GEN nf,GEN pol,long fl,GEN den); static int nfsqff_use_Trager(long n, long dpol); enum { FACTORS = 0, ROOTS, ROOTS_SPLIT }; /* for nf_bestlift: reconstruction of algebraic integers known mod P^k, * P maximal ideal above p */ typedef struct { long k; /* input known mod P^k */ GEN p, pk; /* p^k = denom(prk^-1) [ assume pr unramified ]*/ GEN prk; /* |.|^2 LLL-reduced basis (b_i) of P^k (NOT T2-reduced) */ GEN iprk; /* den * prk^-1 */ GEN GSmin; /* min |b_i^*|^2 */ GEN Tp; /* Tpk mod p */ GEN Tpk; GEN ZqProj;/* projector to Zp / P^k = Z/p^k[X] / Tpk */ GEN tozk; GEN topow; GEN topowden; /* topow x / topowden = basistoalg(x) */ GEN dn; /* NULL (we trust nf.zk) or a t_INT > 1 (an alg. integer has denominator dividing dn, when expressed on nf.zk */ } nflift_t; typedef struct { nflift_t *L; GEN nf; GEN pol, polbase; /* leading coeff is a t_INT */ GEN fact; GEN Br, bound, ZC, BS_2; } nfcmbf_t; /*******************************************************************/ /* RATIONAL RECONSTRUCTION (use ratlift) */ /*******************************************************************/ /* NOT stack clean. a, b stay on the stack */ static GEN lift_to_frac(GEN t, GEN N, GEN amax, GEN bmax, GEN den, GEN tden) { GEN a, b; if (signe(t) < 0) t = addii(t, N); /* in case t is a centerlift */ if (tden) { pari_sp av = avma; a = Fp_center_i(Fp_mul(t, tden, N), N, shifti(N,-1)); if (abscmpii(a, amax) < 0) return gerepileupto(av, Qdivii(a, tden)); set_avma(av); } if (!Fp_ratlift(t, N, amax,bmax, &a,&b) || (den && !dvdii(den,b)) || !is_pm1(gcdii(a,b))) return NULL; if (is_pm1(b)) { cgiv(b); return a; } return mkfrac(a, b); } /* Compute rational lifting for all the components of P modulo N. Assume * Fp_ratlift preconditions are met; we allow centerlifts. If one component * fails, return NULL. If den != NULL, check that the deninators divide den; * assume (N, den) = 1. */ GEN FpC_ratlift(GEN P, GEN N, GEN amax, GEN bmax, GEN den) { pari_sp av = avma; long j, l; GEN tden = NULL, Q = cgetg_copy(P, &l); if (l==1) return Q; if (den && cmpii(bmax, den) > 0) bmax = den; for (j = 1; j < l; ++j) { GEN a = lift_to_frac(gel(P,j), N, amax, bmax, den, tden); if (!a) return gc_NULL(av); if (typ(a) == t_FRAC) { GEN d = gel(a,2); tden = tden? (cmpii(tden, d) < 0? d: tden): d; } gel(Q,j) = a; } return Q; } GEN FpX_ratlift(GEN P, GEN N, GEN amax, GEN bmax, GEN den) { pari_sp av = avma; long j, l; GEN tden = NULL, Q = cgetg_copy(P, &l); Q[1] = P[1]; if (den && cmpii(bmax, den) > 0) bmax = den; for (j = 2; j < l; ++j) { GEN a = lift_to_frac(gel(P,j), N, amax, bmax, den, tden); if (!a) return gc_NULL(av); if (typ(a) == t_FRAC) { GEN d = gel(a,2); tden = tden? (cmpii(tden, d) < 0? d: tden): d; } gel(Q,j) = a; } return Q; } GEN FpM_ratlift(GEN M, GEN mod, GEN amax, GEN bmax, GEN den) { pari_sp av = avma; long j, l = lg(M); GEN N = cgetg_copy(M, &l); if (l == 1) return N; for (j = 1; j < l; ++j) { GEN a = FpC_ratlift(gel(M, j), mod, amax, bmax, den); if (!a) return gc_NULL(av); gel(N,j) = a; } return N; } /*******************************************************************/ /* GCD in K[X], K NUMBER FIELD */ /*******************************************************************/ /* P a nonzero ZXQX */ static GEN lead_simplify(GEN P) { GEN x = leading_coeff(P); /* x a nonzero ZX or t_INT */ if (typ(x) == t_POL) { if (degpol(x)) return x; x = gel(x,2); } return is_pm1(x)? NULL: x; } /* 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 be 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, ltop = avma; GEN lP, lQ, M, dsol, R, bo, sol, mod = NULL, lden = NULL; long vP = varn(P), vT = varn(T), dT = degpol(T), dM = 0, dR; forprime_t S; if (!signe(P)) { if (Pnew) *Pnew = pol_0(vT); return gcopy(Q); } if (!signe(Q)) { if (Pnew) *Pnew = pol_1(vT); return gcopy(P); } /* Compute denominators */ if ((lP = lead_simplify(P)) && (lQ = lead_simplify(Q))) { if (typ(lP) == t_INT && typ(lQ) == t_INT) lden = powiu(gcdii(lP, lQ), dT); else if (typ(lP) == t_INT) lden = gcdii(powiu(lP, dT), ZX_resultant(lQ, T)); else if (typ(lQ) == t_INT) lden = gcdii(powiu(lQ, dT), ZX_resultant(lP, T)); else lden = gcdii(ZX_resultant(lP, T), ZX_resultant(lQ, T)); if (is_pm1(lden)) lden = NULL; if (den && lden) den = mulii(den, lden); } init_modular_small(&S); btop = avma; for(;;) { ulong p = u_forprime_next(&S); GEN Tp; if (!p) pari_err_OVERFLOW("nfgcd [ran out of primes]"); /*Discard primes dividing disc(T) or lc(PQ) */ if (lden && !umodiu(lden, p)) continue; Tp = ZX_to_Flx(T,p); if (!Flx_is_squarefree(Tp, p)) continue; /*Discard primes when modular gcd does not exist*/ if ((R = FlxqX_safegcd(ZXX_to_FlxX(P,p,vT), ZXX_to_FlxX(Q,p,vT), Tp, p)) == NULL) continue; dR = degpol(R); if (dR == 0) { set_avma(ltop); if (Pnew) *Pnew = P; return pol_1(vP); } if (mod && dR > dM) continue; /* p divides Res(P/gcd, Q/gcd). Discard. */ R = FlxX_to_Flm(R, dT); /* previous primes divided Res(P/gcd, Q/gcd)? Discard them. */ if (!mod || dR < dM) { M = ZM_init_CRT(R, p); mod = utoipos(p); dM = dR; continue; } (void)ZM_incremental_CRT(&M,R, &mod,p); if (gc_needed(btop, 1)) { if (DEBUGMEM>1) pari_warn(warnmem,"nfgcd"); gerepileall(btop, 2, &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; return gc_all(ltop, Pnew? 2: 1, &dsol, Pnew); /* both remainders are 0 */ } } GEN nfgcd(GEN P, GEN Q, GEN T, GEN den) { return nfgcd_all(P, Q, T, den, NULL); } GEN ZXQX_gcd(GEN P, GEN Q, GEN T) { return nfgcd_all(P, Q, T, NULL, NULL); } GEN QXQX_gcd(GEN P, GEN Q, GEN T) { pari_sp av = avma; GEN P1 = Q_remove_denom(P, NULL); GEN Q1 = Q_remove_denom(Q, NULL); return gerepileupto(av, ZXQX_gcd(P1, Q1, T)); } int nfissquarefree(GEN nf, GEN x) { pari_sp av = avma; GEN g, y = RgX_deriv(x); if (RgX_is_rational(x)) g = QX_gcd(x, y); else { GEN T = get_nfpol(nf,&nf); x = Q_primpart( liftpol_shallow(x) ); y = Q_primpart( liftpol_shallow(y) ); g = nfgcd(x, y, T, nf? nf_get_index(nf): NULL); } return gc_bool(av, degpol(g) == 0); } /*******************************************************************/ /* FACTOR OVER (Z_K/pr)[X] --> FqX_factor */ /*******************************************************************/ GEN nffactormod(GEN nf, GEN x, GEN pr) { long j, l, vx = varn(x), vn; pari_sp av = avma; GEN F, E, rep, xrd, modpr, T, p; nf = checknf(nf); vn = nf_get_varn(nf); if (typ(x)!=t_POL) pari_err_TYPE("nffactormod",x); if (varncmp(vx,vn) >= 0) pari_err_PRIORITY("nffactormod", x, ">=", vn); modpr = nf_to_Fq_init(nf, &pr, &T, &p); xrd = nfX_to_FqX(x, nf, modpr); rep = FqX_factor(xrd,T,p); settyp(rep, t_MAT); F = gel(rep,1); l = lg(F); E = gel(rep,2); settyp(E, t_COL); for (j = 1; j < l; j++) { gel(F,j) = FqX_to_nfX(gel(F,j), modpr); gel(E,j) = stoi(E[j]); } return gerepilecopy(av, rep); } /*******************************************************************/ /* MAIN ROUTINES nfroots / nffactor */ /*******************************************************************/ static GEN QXQX_normalize(GEN P, GEN T) { GEN P0 = leading_coeff(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_coeff(P); /* cater for t_POL */ if (typ(P0) == t_POL) { P0 = gel(P0,2); /* nonzero constant */ P = shallowcopy(P); gel(P,lg(P)-1) = P0; /* now leading term is a t_INT */ } if (typ(P0) != t_INT) pari_err_BUG("RgX_int_normalize"); if (is_pm1(P0)) return signe(P0) > 0? P: RgX_neg(P); return RgX_Rg_div(P, P0); } /* discard change of variable if nf is of the form [nf,c] as return by nfinit * for nonmonic polynomials */ static GEN proper_nf(GEN nf) { return (lg(nf) == 3)? gel(nf,1): nf; } /* if *pnf = NULL replace if by a "quick" K = nfinit(T), ensuring maximality * by small primes only. Return a multiplicative bound for the denominator of * algebraic integers in Z_K in terms of K.zk */ static GEN fix_nf(GEN *pnf, GEN *pT, GEN *pA) { GEN nf, NF, P, q, D, T = *pT; nfmaxord_t S; long i, l, lim; if (*pnf) return gen_1; lim = GP_DATA->factorlimit + 1; nfmaxord(&S, mkvec2(T, utoipos(lim)), nf_PARTIALFACT); NF = nfinit_complete(&S, 0, DEFAULTPREC); *pnf = nf = proper_nf(NF); if (nf != NF) { /* t_POL defining base field changed (not monic) */ GEN A = *pA, a = cgetg_copy(A, &l); GEN rev = gel(NF,2), pow, dpow; *pT = T = nf_get_pol(nf); /* need to update T */ pow = QXQ_powers(lift_shallow(rev), degpol(T)-1, T); pow = Q_remove_denom(pow, &dpow); a[1] = A[1]; for (i=2; i= 0 && !BPSW_psp(p)) q = mulii(q, p); } return q; } /* lt(A) is an integer; ensure it is not a constant t_POL. In place */ static void ensure_lt_INT(GEN A) { long n = lg(A)-1; GEN lt = gel(A,n); while (typ(lt) != t_INT) gel(A,n) = lt = gel(lt,2); } /* 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, D, B, A = *pA, T = *pT; long n = degpol(T); A = Q_primpart( QXQX_normalize(A, T) ); if (nfsqff_use_Trager(n, degpol(A))) { *pnf = T; bad = den = absi_shallow(ZX_disc(T)); if (is_pm1(leading_coeff(T))) den = indexpartial(T, den); } else { den = fix_nf(pnf, &T, &A); bad = nf_get_index(*pnf); if (den != gen_1) bad = mulii(bad, den); } D = nfgcd_all(A, RgX_deriv(A), T, bad, &B); if (degpol(D)) B = Q_primpart( QXQX_normalize(B, T) ); if (ptbad) *ptbad = bad; *pA = A; *pB = B; ensure_lt_INT(B); *pT = T; return den; } /* return the roots of pol in nf */ GEN nfroots(GEN nf,GEN pol) { pari_sp av = avma; GEN z, A, B, T, den; long d, dT; if (!nf) return nfrootsQ(pol); T = get_nfpol(nf, &nf); RgX_check_ZX(T,"nfroots"); A = RgX_nffix("nfroots", T,pol,1); d = degpol(A); if (d < 0) pari_err_ROOTS0("nfroots"); if (d == 0) return cgetg(1,t_COL); if (d == 1) { A = QXQX_normalize(A,T); A = mkpolmod(gneg_i(gel(A,2)), T); return gerepilecopy(av, mkcol(A)); } dT = degpol(T); if (dT == 1) return gerepileupto(av, nfrootsQ(simplify_shallow(A))); den = get_nfsqff_data(&nf, &T, &A, &B, NULL); if (RgX_is_ZX(B)) { GEN v = gel(ZX_factor(B), 1); long i, l = lg(v), p = mael(factoru(dT),1,1); /* smallest prime divisor */ z = cgetg(1, t_VEC); for (i = 1; i < l; i++) { GEN b = gel(v,i); /* irreducible / Q */ long db = degpol(b); if (db != 1 && degpol(b) < p) continue; z = shallowconcat(z, nfsqff(nf, b, ROOTS, den)); } } else z = nfsqff(nf,B, ROOTS, den); z = gerepileupto(av, QXQV_to_mod(z, T)); gen_sort_inplace(z, (void*)&cmp_RgX, &cmp_nodata, NULL); settyp(z, t_COL); return z; } static GEN _norml2(GEN x) { return RgC_fpnorml2(x, DEFAULTPREC); } /* return a minimal lift of elt modulo id, as a ZC */ static GEN nf_bestlift(GEN elt, GEN bound, nflift_t *L) { GEN u; long i,l = lg(L->prk), t = typ(elt); if (t != t_INT) { if (t == t_POL) elt = ZM_ZX_mul(L->tozk, elt); u = ZM_ZC_mul(L->iprk,elt); for (i=1; ipk); } else { u = ZC_Z_mul(gel(L->iprk,1), elt); for (i=1; ipk); elt = scalarcol(elt, l-1); } u = ZC_sub(elt, ZM_ZC_mul(L->prk, u)); if (bound && gcmp(_norml2(u), 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); set_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, nflift_t *L) { long i, l = lg(pol); GEN x = cgetg(l,t_POL); x[1] = pol[1]; for (i=l-1; i>1; i--) { GEN t = nf_bestlift_to_pol(gel(pol,i), bound, L); if (!t) return NULL; gel(x,i) = t; } return x; } static GEN zerofact(long v) { GEN z = cgetg(3, t_MAT); gel(z,1) = mkcol(pol_0(v)); gel(z,2) = mkcol(gen_1); return z; } /* Return the factorization of A in Q[X]/(T) in rep [pre-allocated with * cgetg(3,t_MAT)], reclaiming all memory between avma and rep. * y is the vector of irreducible factors of B = Q_primpart( A/gcd(A,A') ). * Bad primes divide 'bad' */ static void fact_from_sqff(GEN rep, GEN A, GEN B, GEN y, GEN T, GEN bad) { pari_sp av = (pari_sp)rep; long n = lg(y)-1; GEN ex; if (A != B) { /* not squarefree */ if (n == 1) { /* perfect power, simple ! */ long e = degpol(A) / degpol(gel(y,1)); y = gerepileupto(av, QXQXV_to_mod(y, T)); ex = mkcol(utoipos(e)); } else { /* compute valuations mod a prime of degree 1 (avoid coeff explosion) */ GEN quo, p, r, Bp, lb = leading_coeff(B), E = cgetalloc(n+1,t_VECSMALL); pari_sp av1 = avma; ulong pp; long j; forprime_t S; u_forprime_init(&S, degpol(T), ULONG_MAX); for (; ; set_avma(av1)) { pp = u_forprime_next(&S); if (! umodiu(bad,pp) || !umodiu(lb, pp)) continue; p = utoipos(pp); r = FpX_oneroot(T, p); if (!r) continue; Bp = FpXY_evalx(B, r, p); if (FpX_is_squarefree(Bp, p)) break; } quo = FpXY_evalx(Q_primpart(A), r, p); for (j=n; j>=2; j--) { GEN junk, fact = Q_remove_denom(gel(y,j), &junk); long e = 0; fact = FpXY_evalx(fact, r, p); for(;; e++) { GEN q = FpX_divrem(quo,fact,p,ONLY_DIVIDES); if (!q) break; quo = q; } E[j] = e; } E[1] = degpol(quo) / degpol(gel(y,1)); y = gerepileupto(av, QXQXV_to_mod(y, T)); ex = zc_to_ZC(E); pari_free((void*)E); } } else { y = gerepileupto(av, QXQXV_to_mod(y, T)); ex = const_col(n, gen_1); } gel(rep,1) = y; settyp(y, t_COL); gel(rep,2) = ex; } /* return the factorization of polynomial pol in nf */ static GEN nffactor_i(GEN nf,GEN T,GEN pol) { GEN bad, A, B, y, 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"); } A = RgX_nffix("nffactor",T,pol,1); dA = degpol(A); if (dA <= 0) { set_avma((pari_sp)(rep + 3)); return (dA == 0)? trivial_fact(): zerofact(varn(pol)); } if (dA == 1) { GEN c; A = Q_primpart( QXQX_normalize(A, T) ); 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 (RgX_is_ZX(B)) { GEN v = gel(ZX_factor(B), 1); long i, l = lg(v); y = cgetg(1, t_VEC); for (i = 1; i < l; i++) { GEN b = gel(v,i); /* irreducible / Q */ y = shallowconcat(y, nfsqff(nf, b, 0, den)); } } else y = nfsqff(nf,B, 0, den); 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 rep; } /* return the factorization of P in nf */ GEN nffactor(GEN nf, GEN P) { GEN y, T = get_nfpol(nf, &nf); if (!nf) RgX_check_ZX(T,"nffactor"); if (typ(P) == t_RFRAC) { pari_sp av = avma; GEN a = gel(P, 1), b = gel(P, 2); y = famat_inv_shallow(nffactor_i(nf, T, b)); if (typ(a) == t_POL && varn(a) == varn(b)) y = famat_mul_shallow(nffactor_i(nf, T, a), y); y = gerepilecopy(av, y); } else y = nffactor_i(nf, T, P); return sort_factor_pol(y, cmp_RgX); } /* assume x scalar or t_COL, G t_MAT */ static GEN arch_for_T2(GEN G, GEN x) { return (typ(x) == t_COL)? RgM_RgC_mul(G,x) : RgC_Rg_mul(gel(G,1),x); } /* polbase a zkX with t_INT leading coeff; 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 lS = leading_coeff(polbase); /* t_INT */ GEN p1, C, N2, binlS, bin; long prec = nf_get_prec(nf), n = nf_get_degree(nf), r1 = nf_get_r1(nf); long i, j, d = degpol(polbase); binlS = bin = vecbinomial(d-1); if (!isint1(lS)) binlS = ZC_Z_mul(bin,lS); N2 = cgetg(n+1, t_VEC); for (;;) { GEN G = nf_get_G(nf), matGS = cgetg(d+2, t_MAT); for (j=0; j<=d; j++) gel(matGS,j+1) = arch_for_T2(G, gel(polbase,j+2)); matGS = shallowtrans(matGS); for (j=1; j <= r1; j++) /* N2[j] = || sigma_j(S) ||_2 */ { GEN c = sqrtr( _norml2(gel(matGS,j)) ); gel(N2,j) = c; if (!signe(c)) goto PRECPB; } for ( ; j <= n; j+=2) { GEN q1 = _norml2(gel(matGS, j)); GEN q2 = _norml2(gel(matGS, j+1)); GEN c = sqrtr( gmul2n(addrr(q1, q2), -1) ); gel(N2,j) = gel(N2,j+1) = c; if (!signe(c)) goto PRECPB; } break; /* done */ PRECPB: prec = precdbl(prec); nf = nfnewprec_shallow(nf, prec); if (DEBUGLEVEL>1) pari_warn(warnprec, "nf_factor_bound", prec); } /* Take sup over 0 <= i <= d of * sum_j | binom(d-1, i-1) ||sigma_j(S)||_2 + binom(d-1,i) lc(S) |^2 */ /* i = 0: n lc(S)^2 */ C = mului(n, sqri(lS)); /* i = d: sum_sigma ||sigma(S)||_2^2 */ p1 = gnorml2(N2); if (gcmp(C, p1) < 0) C = p1; for (i = 1; i < d; i++) { GEN B = gel(bin,i), L = gel(binlS,i+1); GEN s = sqrr(addri(mulir(B, gel(N2,1)), L)); /* j=1 */ for (j = 2; j <= n; j++) s = addrr(s, sqrr(addri(mulir(B, gel(N2,j)), L))); if (mpcmp(C, s) < 0) C = s; } return C; } /* return a bound for T_2(P), P | polbase * max |b_i|^2 <= 3^{3/2 + d} / (4 \pi d) [P]_2, * where [P]_2 is Bombieri's 2-norm * Sum over conjugates */ static GEN nf_Beauzamy_bound(GEN nf, GEN polbase) { GEN lt, C, s, POL, bin; long d = degpol(polbase), n = nf_get_degree(nf), prec = nf_get_prec(nf); bin = vecbinomial(d); POL = polbase + 2; /* compute [POL]_2 */ for (;;) { GEN G = nf_get_G(nf); long i; s = real_0(prec); for (i=0; i<=d; i++) { GEN c = gel(POL,i); if (gequal0(c)) continue; c = _norml2(arch_for_T2(G,c)); if (!signe(c)) goto PRECPB; /* s += T2(POL[i]) / binomial(d,i) */ s = addrr(s, divri(c, gel(bin,i+1))); } break; PRECPB: prec = precdbl(prec); nf = nfnewprec_shallow(nf, prec); if (DEBUGLEVEL>1) pari_warn(warnprec, "nf_factor_bound", prec); } lt = leading_coeff(polbase); s = mulri(s, muliu(sqri(lt), n)); C = powruhalf(utor(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)); } /* True nf; return Bs: if r a root of sigma_i(P), |r| < Bs[i] */ static GEN nf_root_bounds(GEN nf, GEN P) { long lR, i, j, l, prec, r1; GEN Ps, R, V; if (RgX_is_rational(P)) return polrootsbound(P, NULL); r1 = nf_get_r1(nf); P = Q_primpart(P); prec = ZXX_max_lg(P) + 1; l = lg(P); if (nf_get_prec(nf) >= prec) R = nf_get_roots(nf); else R = QX_complex_roots(nf_get_pol(nf), 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 nonzero 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->pk, DEFAULTPREC)); T->dPinvS = ZM_mul(L->iprk, S); l = lg(S); h = lgcols(T->dPinvS); T->PinvSdbl = (double**)cgetg(l, t_MAT); for (j = 1; j < l; j++) { double *t = (double *) stack_malloc_align(h * sizeof(double), 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))); set_avma(av); } T->d = L->pk; T->P1 = gdivround(L->prk, q); T->S1 = S1; return T; } static void update_trace(trace_data *T, long k, long i) { if (!T) return; gel(T->S1,k) = gel(T->S1,i); gel(T->dPinvS,k) = gel(T->dPinvS,i); T->PinvSdbl[k] = T->PinvSdbl[i]; } /* reduce coeffs mod (T,pk), then center mod pk */ static GEN FqX_centermod(GEN z, GEN T, GEN pk, GEN pks2) { long i, l; GEN y; if (!T) return centermod_i(z, pk, pks2); y = FpXQX_red(z, T, pk); l = lg(y); for (i = 2; i < l; i++) { GEN c = gel(y,i); if (typ(c) == t_INT) c = Fp_center_i(c, pk, pks2); else c = FpX_center_i(c, pk, pks2); gel(y,i) = c; } return y; } typedef struct { GEN lt, C, Clt, C2lt, C2ltpol; } div_data; static void init_div_data(div_data *D, GEN pol, nflift_t *L) { GEN C2lt, Clt, C = mul_content(L->topowden, L->dn); GEN lc = leading_coeff(pol), lt = is_pm1(lc)? NULL: absi_shallow(lc); if (C) { GEN C2 = sqri(C); if (lt) { C2lt = mulii(C2, lt); Clt = mulii(C,lt); } else { C2lt = C2; Clt = C; } } else C2lt = Clt = lt; D->lt = lt; D->C = C; D->Clt = Clt; D->C2lt = C2lt; D->C2ltpol = C2lt? RgX_Rg_mul(pol, C2lt): pol; } static void update_target(div_data *D, GEN pol) { D->C2ltpol = D->Clt? RgX_Rg_mul(pol, D->Clt): pol; } /* nb = number of modular factors; return a "good" K such that naive * recombination of up to maxK modular factors is not too costly */ long cmbf_maxK(long nb) { if (nb > 10) return 3; return nb-1; } /* Naive recombination of modular factors: combine up to maxK modular * factors, degree <= klim * * target = polynomial we want to factor * famod = array of modular factors. Product should be congruent to * target/lc(target) modulo p^a * For true factors: S1,S2 <= p^b, with b <= a and p^(b-a) < 2^31 */ /* set *done = 1 if factorisation is known to be complete */ static GEN nfcmbf(nfcmbf_t *T, long klim, long *pmaxK, int *done) { GEN nf = T->nf, famod = T->fact, bound = T->bound; GEN ltdn, nfpol = nf_get_pol(nf); long K = 1, cnt = 1, i,j,k, curdeg, lfamod = lg(famod)-1, dnf = degpol(nfpol); pari_sp av0 = avma; GEN Tpk = T->L->Tpk, pk = T->L->pk, pks2 = shifti(pk,-1); GEN ind = cgetg(lfamod+1, t_VECSMALL); GEN deg = cgetg(lfamod+1, t_VECSMALL); GEN degsofar = cgetg(lfamod+1, t_VECSMALL); GEN fa = cgetg(lfamod+1, t_VEC); const double Bhigh = get_Bhigh(lfamod, dnf); trace_data _T1, _T2, *T1, *T2; div_data D; pari_timer ti; timer_start(&ti); *pmaxK = cmbf_maxK(lfamod); init_div_data(&D, T->pol, T->L); ltdn = mul_content(D.lt, T->L->dn); { GEN q = ceil_safe(sqrtr(T->BS_2)); GEN t1,t2, lt2dn = mul_content(ltdn, D.lt); GEN trace1 = cgetg(lfamod+1, t_MAT); GEN trace2 = cgetg(lfamod+1, t_MAT); for (i=1; i <= lfamod; i++) { pari_sp av = avma; GEN P = gel(famod,i); long d = degpol(P); deg[i] = d; P += 2; t1 = gel(P,d-1);/* = - S_1 */ t2 = Fq_sqr(t1, Tpk, pk); if (d > 1) t2 = Fq_sub(t2, gmul2n(gel(P,d-2), 1), Tpk, pk); /* t2 = S_2 Newton sum */ if (ltdn) { t1 = Fq_Fp_mul(t1, ltdn, Tpk, pk); t2 = Fq_Fp_mul(t2, lt2dn, Tpk, pk); } gel(trace1,i) = gclone( nf_bestlift(t1, NULL, T->L) ); gel(trace2,i) = gclone( nf_bestlift(t2, NULL, T->L) ); set_avma(av); } T1 = init_trace(&_T1, trace1, T->L, q); T2 = init_trace(&_T2, trace2, T->L, q); for (i=1; i <= lfamod; i++) { gunclone(gel(trace1,i)); gunclone(gel(trace2,i)); } } degsofar[0] = 0; /* sentinel */ /* ind runs through strictly increasing sequences of length K, * 1 <= ind[i] <= lfamod */ nextK: if (K > *pmaxK || 2*K > lfamod) goto END; if (DEBUGLEVEL > 3) err_printf("\n### K = %d, %Ps combinations\n", K,binomial(utoipos(lfamod), K)); setlg(ind, K+1); ind[1] = 1; i = 1; curdeg = deg[ind[1]]; for(;;) { /* try all combinations of K factors */ for (j = i; j < K; j++) { degsofar[j] = curdeg; ind[j+1] = ind[j]+1; curdeg += deg[ind[j+1]]; } if (curdeg <= klim) /* trial divide */ { GEN t, y, q; pari_sp av; av = avma; if (T1) { /* d-1 test */ t = get_trace(ind, T1); if (rtodbl(_norml2(t)) > Bhigh) { if (DEBUGLEVEL>6) err_printf("."); set_avma(av); goto NEXT; } } if (T2) { /* d-2 test */ t = get_trace(ind, T2); if (rtodbl(_norml2(t)) > Bhigh) { if (DEBUGLEVEL>3) err_printf("|"); set_avma(av); goto NEXT; } } set_avma(av); y = ltdn; /* full computation */ for (i=1; i<=K; i++) { GEN q = gel(famod, ind[i]); if (y) q = gmul(y, q); y = FqX_centermod(q, Tpk, pk, pks2); } y = nf_pol_lift(y, bound, T->L); if (!y) { if (DEBUGLEVEL>3) err_printf("@"); set_avma(av); goto NEXT; } /* y = topowden*dn*lt*\prod_{i in ind} famod[i] is apparently in O_K[X], * in fact in (Z[Y]/nf.pol)[X] due to multiplication by C = topowden*dn. * Try out this candidate factor */ q = RgXQX_divrem(D.C2ltpol, y, nfpol, ONLY_DIVIDES); if (!q) { if (DEBUGLEVEL>3) err_printf("*"); set_avma(av); goto NEXT; } /* Original T->pol in O_K[X] with leading coeff lt in Z, * y = C*lt \prod famod[i] is in O_K[X] with leading coeff in Z * q = C^2*lt*pol / y = C * (lt*pol) / (lt*\prod famod[i]) is a * K-rational factor, in fact in Z[Y]/nf.pol)[X] as above, with * leading term C*lt. */ update_target(&D, q); gel(fa,cnt++) = D.C2lt? RgX_int_normalize(y): y; /* make monic */ for (i=j=k=1; i <= lfamod; i++) { /* remove used factors */ if (j <= K && i == ind[j]) j++; else { gel(famod,k) = gel(famod,i); update_trace(T1, k, i); update_trace(T2, k, i); deg[k] = deg[i]; k++; } } lfamod -= K; *pmaxK = cmbf_maxK(lfamod); if (lfamod < 2*K) goto END; i = 1; curdeg = deg[ind[1]]; if (DEBUGLEVEL > 2) { err_printf("\n"); timer_printf(&ti, "to find factor %Ps",gel(fa,cnt-1)); err_printf("remaining modular factor(s): %ld\n", lfamod); } continue; } NEXT: for (i = K+1;;) { if (--i == 0) { K++; goto nextK; } if (++ind[i] <= lfamod - K + i) { curdeg = degsofar[i-1] + deg[ind[i]]; if (curdeg <= klim) break; } } } END: *done = 1; if (degpol(D.C2ltpol) > 0) { /* leftover factor */ GEN q = D.C2ltpol; if (D.C2lt) q = RgX_int_normalize(q); if (lfamod >= 2*K) { /* restore leading coefficient [#930] */ if (D.lt) q = RgX_Rg_mul(q, D.lt); *done = 0; /* ... may still be reducible */ } setlg(famod, lfamod+1); gel(fa,cnt++) = q; } if (DEBUGLEVEL>6) err_printf("\n"); 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 = ZM_hnf_knapsack(M_L); if (!piv) return NULL; if (DEBUGLEVEL>3) err_printf("ZM_hnf_knapsack output:\n%Ps\n",piv); r = lg(piv)-1; list = cgetg(r+1, t_VEC); init_div_data(&D, pol, T->L); for (i = 1;;) { pari_sp av = avma; if (DEBUGLEVEL) err_printf("nf_LLL_cmbf: checking factor %ld\n", i); y = chk_factors_get(D.lt, famod, gel(piv,i), Tpk, pk); if (! (y = nf_pol_lift(y, bound, T->L)) ) 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_i(FpX_rem(y, T, pk), pk, pks2); } /* Assume P in nfX form, lc(P) != 0 mod p. Reduce P to Zp[X]/(T) mod p^a */ static GEN ZqX(GEN P, GEN pk, GEN T, GEN proj) { long i, l = lg(P); GEN z, pks2 = shifti(pk,-1); z = cgetg(l,t_POL); z[1] = P[1]; for (i=2; ipk)): P; return ZqX(R, L->pk, L->Tpk, L->ZqProj); } /* k allowing to reconstruct x, T_2(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 p, long f) { const double g = 1 / (alpha - 0.25); /* = 2 if alpha = 3/4 */ GEN C4 = shiftr(gtofp(C,DEFAULTPREC), 2); double t, logp = log(gtodouble(p)); if (f == d) { /* p inert, no LLL fudge factor: p^(2k) / 4 > C */ t = 0.5 * rtodbl(mplog(C4)); return ceil(t / logp); } /* (1/2)log (4C/d) + (d-1)(log 3/2 sqrt(gamma)) */ t = 0.5 * rtodbl(mplog(divru(C4,d))) + (d-1) * log(1.5 * sqrt(g)); return ceil((t * d) / (logp * f)); } static GEN get_R(GEN M) { GEN R; long i, l, prec = nbits2prec( gexpo(M) + 64 ); for(;;) { R = gaussred_from_QR(M, prec); if (R) break; prec = precdbl(prec); } l = lg(R); for (i=1; iTp)>1) { 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), L->pk, L->p, L->k); L->Tpk = gel(z,1); proj = QXQV_to_FpM(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(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_j ( s_ij^2 / B_j) * For p inert, S = Id, T_i = 1 / p^{2k} and Rmax = p^k / 2 */ static GEN max_radius(GEN PRK, GEN B) { GEN S, smax = gen_0; pari_sp av = avma; long i, j, d = lg(PRK)-1; S = RgM_inv( get_R(PRK) ); if (!S) pari_err_PREC("max_radius"); for (i=1; i<=d; i++) { GEN s = gen_0; for (j=1; j<=d; j++) s = mpadd(s, mpdiv( mpsqr(gcoeff(S,i,j)), gel(B,j))); if (mpcmp(s, smax) > 0) smax = s; } return gerepileupto(av, ginv(gmul2n(smax, 2))); } static void bestlift_init(long a, GEN nf, GEN 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, iPRK, GSmin, T = L->Tp, p = L->p; long f = degpol(T); pari_timer ti; if (f == d) { /* inert p, much simpler */ long a0 = bestlift_bound(C, d, alpha, p, f); GEN q; if (a < a0) a = a0; /* guarantees GSmin >= C */ if (DEBUGLEVEL>2) err_printf("exponent %ld\n",a); q = powiu(p,a); PRK = prk = scalarmat_shallow(q, d); GSmin = shiftr(itor(q, DEFAULTPREC), -1); iPRK = matid(d); goto END; } timer_start(&ti); if (!a) a = (long)bestlift_bound(C, d, alpha, p, f); for (;; set_avma(av), a += (a==1)? 1: (a>>1)) /* roughly a *= 1.5 */ { GEN B, q = powiu(p,a), Tq = FpXQ_powu(T, a, FpX_red(nf_get_pol(nf), q), q); if (DEBUGLEVEL>2) err_printf("exponent %ld\n",a); prk = idealhnf_two(nf, mkvec2(q, Tq)); av2 = avma; 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); iPRK = ZM_inv(PRK, NULL); if (DEBUGLEVEL>2) err_printf("for this exponent, GSmin = %Ps\nTime reduction: %ld\n", GSmin, timer_delay(&ti)); END: L->k = a; L->pk = gcoeff(prk,1,1); L->prk = PRK; L->iprk = iPRK; L->GSmin= GSmin; init_proj(L, prk, 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; set_avma(av2); gel(V,i) = gerepileupto(av, v); /* small */ } return V; } static GEN nf_LLL_cmbf(nfcmbf_t *T, long rec) { const double BitPerFactor = 0.4; /* nb bits / modular factor */ nflift_t *L = T->L; GEN famod = T->fact, ZC = T->ZC, Br = T->Br, P = T->pol, dn = T->L->dn; long dnf = nf_get_degree(T->nf), dP = degpol(P); long i, C, tmax, n0; GEN lP, Bnorm, Tra, T2, TT, CM_L, m, list, ZERO, Btra; double Bhigh; pari_sp av, av2; long ti_LLL = 0, ti_CF = 0; pari_timer ti2, TI; lP = absi_shallow(leading_coeff(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, normTp(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; TT = const_vec(n0, NULL); Tra = cgetg(n0+1, t_MAT); 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, normTp(Br, 2*tnew, dnf))); bmin = logint(ceil_safe(sqrtr(Btra)), gen_2) + 1; 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, Btra, L); polred = ZqX_normalize(T->polbase, lP, L); famod = ZqX_liftfact(polred, famod, L->Tpk, L->pk, L->p, L->k); for (i=1; i<=n0; i++) gel(TT,i) = NULL; } 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; set_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; } if (gc_needed(av,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"nf_LLL_cmbf"); gerepileall(av, L->Tpk? 9: 8, &CM_L,&TT,&Tra,&famod,&L->GSmin,&L->pk,&L->prk,&L->iprk, &L->Tpk); } else CM_L = gerepilecopy(av2, CM_L); } 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 = ZqX_liftfact(polred, T->fact, L->Tpk, L->pk, L->p, L->k); 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) { GEN den; T->pol = gel(res,l); T->polbase = Q_remove_denom(RgX_to_nfX(T->nf, T->pol), &den); if (den) { T->Br = gmul(T->Br, den); T->pol = RgX_Rg_mul(T->pol, den); } } 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, long fl, nflift_t *L) { GEN z, Cltx_r, ltdn; long i, m, lz; div_data D; init_div_data(&D, pol, L); ltdn = mul_content(D.lt, L->dn); z = ZqX_roots(polred, L->Tpk, L->p, L->k); Cltx_r = deg1pol_shallow(D.Clt? D.Clt: gen_1, NULL, varn(pol)); lz = lg(z); if (DEBUGLEVEL > 3) err_printf("Checking %ld roots:",lz-1); for (m=1,i=1; i 3) err_printf(" %ld",i); /* lt*dn*topowden * r = Clt * r */ r = nf_bestlift_to_pol(ltdn? gmul(ltdn,r): r, NULL, L); av = avma; gel(Cltx_r,2) = gneg(r); /* check P(r) == 0 */ dvd = ZXQX_dvd(D.C2ltpol, Cltx_r, nfpol); /* integral */ set_avma(av); /* don't go on with q, usually much larger that C2ltpol */ if (dvd) { if (D.Clt) r = gdiv(r, D.Clt); gel(z,m++) = r; } else if (fl == ROOTS_SPLIT) return cgetg(1, t_VEC); } if (DEBUGLEVEL > 3) err_printf(" done\n"); z[0] = evaltyp(t_VEC) | _evallg(m); return z; } /* returns a few factors of T in Fp of degree <= maxf, NULL if none exist */ static GEN get_good_factor(GEN T, ulong p, long maxf) { pari_sp av = avma; GEN r, R = gel(Flx_factor(ZX_to_Flx(T,p),p), 1); if (maxf == 1) { /* degree 1 factors are best */ r = gel(R,1); if (degpol(r) == 1) return mkvec(r); } else { /* otherwise, pick factor of largish degree */ long i, j, dr, d = 0, l = lg(R); GEN v; if (l == 2) return mkvec(gel(R,1)); /* inert is fine */ v = cgetg(l, t_VEC); for (i = j = 1; i < l; i++) { r = gel(R,i); dr = degpol(r); if (dr > maxf) break; if (dr != d) { gel(v,j++) = r; d = dr; } } setlg(v,j); if (j > 1) return v; } return gc_NULL(av); /* failure */ } /* n = number of modular factors, f = residue degree; nold/fold current best * return 1 if new values are "better" than old ones */ static int record(long nold, long n, long fold, long f) { if (!nold) return 1; /* uninitialized */ if (fold == f) return n < nold; /* if f increases, allow increasing n a little */ if (fold < f) return n <= 20 || n < 1.1*nold; /* f decreases, only allow if decreasing n a lot */ return n < 0.7*nold; } /* 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 =32; else if (nfdeg >= 30) maxf =16; else if (nfdeg >= 15) maxf = 8; return maxf; } /* number of maximal ideals to test before settling on best prime and number * of factors; B = [K:Q]*deg(P) */ static long get_nbprimes(long B) { if (B <= 128) return 5; if (B <= 1024) return 20; if (B <= 2048) return 65; return 100; } /* Select a prime ideal pr over which to factor pol. * Return the number of factors (or roots, according to flag fl) mod pr. * 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(GEN nf, GEN pol, long fl, GEN *lt, GEN *Tp, ulong *pp) { GEN nfpol = nf_get_pol(nf), bad = mulii(nf_get_disc(nf), nf_get_index(nf)); long nfdeg = degpol(nfpol), dpol = degpol(pol), nold = 0, fold = 1; long maxf = get_maxf(nfdeg), ct = get_nbprimes(nfdeg * dpol); ulong p; forprime_t S; pari_timer ti_pr; if (DEBUGLEVEL>3) timer_start(&ti_pr); /* if field degree is large, try hard to find an inert prime */ if (nfdeg > 30) ct = maxss(ct, 2*nfdeg); *lt = leading_coeff(pol); /* t_INT */ if (gequal1(*lt)) *lt = NULL; *pp = 0; *Tp = NULL; (void)u_forprime_init(&S, 2, ULONG_MAX); /* select pr such that pol has the smallest number of factors, ct attempts */ while ((p = u_forprime_next(&S))) { GEN vT; long n, i, l, ok = 0; ulong ltp = 0; if (! umodiu(bad,p)) continue; if (*lt) { ltp = umodiu(*lt, p); if (!ltp) continue; } vT = get_good_factor(nfpol, p, maxf); if (!vT) continue; l = lg(vT); for (i = 1; i < l; i++) { pari_sp av2 = avma; GEN T = gel(vT,i), red = RgX_to_FlxqX(pol, T, p); long f = degpol(T); if (f == 1) { /* degree 1 */ red = FlxX_to_Flx(red); if (ltp) red = Flx_normalize(red, p); if (!Flx_is_squarefree(red, p)) { set_avma(av2); continue; } ok = 1; n = (fl == FACTORS)? Flx_nbfact(red,p): Flx_nbroots(red,p); } else { if (ltp) red = FlxqX_normalize(red, T, p); if (!FlxqX_is_squarefree(red, T, p)) { set_avma(av2); continue; } ok = 1; n = (fl == FACTORS)? FlxqX_nbfact(red,T,p): FlxqX_nbroots(red,T,p); } if (fl == ROOTS_SPLIT && n < dpol) return n; /* not split */ if (n <= 1) { if (fl == FACTORS) return n; /* irreducible */ if (!n) return 0; /* no root */ } if (DEBUGLEVEL>3) err_printf("%3ld %s at prime (%ld,x^%ld+...)\n Time: %ld\n", n, (fl == FACTORS)? "factors": "roots", p,f, timer_delay(&ti_pr)); if (fl == ROOTS && f==nfdeg) { *Tp = T; *pp = p; return n; } if (record(nold, n, fold, f)) { nold = n; fold = f; *Tp = T; *pp = p; } else set_avma(av2); } if (ok && --ct <= 0) break; } if (!nold) pari_err_OVERFLOW("nf_pick_prime [ran out of primes]"); return nold; } /* Assume lt(T) is a t_INT and T square free. Return t_VEC of irred. factors */ static GEN nfsqff_trager(GEN u, GEN T, GEN dent, long fl) { long k = 0, i, lx; GEN U, P, x0, mx0, fa, n = ZX_ZXY_rnfequation(T, u, &k); int tmonic; if (DEBUGLEVEL>4) err_printf("nfsqff_trager: choosing k = %ld\n",k); /* n guaranteed to be squarefree */ fa = ZX_DDF_max(Q_primpart(n),fl==ROOTS || fl==ROOTS_SPLIT ? degpol(T): 0); lx = lg(fa); if (lx == 2) return mkvec(u); tmonic = is_pm1(leading_coeff(T)); P = cgetg(lx,t_VEC); x0 = deg1pol_shallow(stoi(-k), gen_0, varn(T)); mx0 = deg1pol_shallow(stoi(k), gen_0, varn(T)); U = RgXQX_translate(u, mx0, T); if (!tmonic) U = Q_primpart(U); for (i=lx-1; i>0; i--) { GEN f = gel(fa,i), F = nfgcd(U, f, T, dent); F = RgXQX_translate(F, x0, T); /* F = gcd(f, u(t - x0)) [t + x0] = gcd(f(t + x0), u), more efficient */ if (typ(F) != t_POL || degpol(F) == 0) pari_err_IRREDPOL("factornf [modulus]",T); gel(P,i) = QXQX_normalize(F, T); } gen_sort_inplace(P, (void*)&cmp_RgX, &gen_cmp_RgX, NULL); return P; } /* Factor polynomial a on the number field defined by polynomial T, using * Trager's trick */ GEN polfnf(GEN a, GEN T) { GEN rep = cgetg(3, t_MAT), A, B, y, dent, bad; long dA; int tmonic; if (typ(a)!=t_POL) pari_err_TYPE("polfnf",a); if (typ(T)!=t_POL) pari_err_TYPE("polfnf",T); T = Q_primpart(T); tmonic = is_pm1(leading_coeff(T)); RgX_check_ZX(T,"polfnf"); A = Q_primpart( QXQX_normalize(RgX_nffix("polfnf",T,a,1), T) ); dA = degpol(A); if (dA <= 0) { set_avma((pari_sp)(rep + 3)); return (dA == 0)? trivial_fact(): zerofact(varn(A)); } bad = dent = absi_shallow(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, FACTORS); 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 C0, polbase; GEN N2, res, polred, lt, nfpol = typ(nf)==t_POL?nf:nf_get_pol(nf); ulong pp; nfcmbf_t T; nflift_t L; pari_timer ti, ti_tot; if (DEBUGLEVEL>2) { timer_start(&ti); timer_start(&ti_tot); } n = degpol(nfpol); /* deg = 1 => irreducible */ if (dpol == 1) { if (fl == FACTORS) return mkvec(QXQX_normalize(pol, nfpol)); return mkvec(gneg(gdiv(gel(pol,2),gel(pol,3)))); } if (typ(nf)==t_POL || nfsqff_use_Trager(n,dpol)) { GEN z; if (DEBUGLEVEL>2) err_printf("Using Trager's method\n"); if (typ(nf) != t_POL) den = mulii(den, nf_get_index(nf)); z = nfsqff_trager(Q_primpart(pol), nfpol, den, fl); 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(nf, pol, fl, <, &L.Tp, &pp); if (L.Tp) { L.Tp = Flx_to_ZX(L.Tp); L.p = utoi(pp); } 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: (%lu,x^%ld+...)\n", pp, degpol(L.Tp)); } L.tozk = nf_get_invzk(nf); L.topow= nf_get_zkprimpart(nf); L.topowden = nf_get_zkden(nf); if (is_pm1(den)) den = NULL; L.dn = den; T.ZC = nf_L2_bound(nf, den, NULL); T.Br = nf_root_bounds(nf, pol); if (lt) T.Br = gmul(T.Br, lt); /* C0 = bound for T_2(Q_i), Q | P */ if (fl != FACTORS) C0 = normTp(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, normTp(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); } bestlift_init(0, nf, 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, fl, &L); if (lg(z) == 1) return cgetg(1, t_VEC); return z; } T.fact = gel(FqX_factor(polred, L.Tp, L.p), 1); if (DEBUGLEVEL>2) timer_printf(&ti, "splitting mod %Ps^%ld", L.p, degpol(L.Tp)); 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_if_split(GEN *pnf, GEN pol) { GEN T = get_nfpol(*pnf,pnf), den = fix_nf(pnf, &T, &pol); pari_sp av = avma; GEN z = nfsqff(*pnf, pol, ROOTS_SPLIT, den); if (lg(z) == 1) return gc_NULL(av); return gerepilecopy(av, z); } /*******************************************************************/ /* */ /* 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 4]: factor the cyclotomic polynomial mod [pr], */ /* 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 T, GEN D, GEN index) { long c = 0, nfdegree = degpol(T), B = nfdegree + 20, l; ulong p = 2; GEN nbroots = NULL; forprime_t S; pari_sp av; (void)u_forprime_init(&S, 3, ULONG_MAX); av = avma; /* result must be stationary (counter c) for at least B loops */ for (l=1; (p = u_forprime_next(&S)); l++) { GEN old, F, pf_1, Tp; ulong i, gcdf = 0; long nb; if (!umodiu(D,p) || !umodiu(index,p)) continue; Tp = ZX_to_Flx(T,p); /* squarefree */ F = Flx_nbfact_by_degree(Tp, &nb, p); /* the gcd of the p^f - 1 is p^(gcd of the f's) - 1 */ for (i = 1; i <= (ulong) nfdegree; i++) if (F[i]) { gcdf = gcdf? ugcd(gcdf, i): i; if (gcdf == 1) break; } pf_1 = subiu(powuu(p, gcdf), 1); old = nbroots; nbroots = nbroots? gcdii(pf_1, nbroots): pf_1; if (DEBUGLEVEL>5) err_printf("p=%lu; gcf(f(P/p))=%ld; nbroots | %Ps",p, gcdf, nbroots); /* if same result go on else reset the stop counter [c] */ if (old && equalii(nbroots,old)) { if (!is_bigint(nbroots) && ++c > B) break; } else c = 0; } if (!nbroots) pari_err_OVERFLOW("guess_roots [ran out of primes]"); if (DEBUGLEVEL>5) err_printf("%ld loops\n",l); return gc_long(av, itos(nbroots)); } /* T(x) an irreducible ZX. Is it of the form Phi_n(c \pm x) ? * Return NULL if not, and a root of 1 of maximal order in Z[x]/(T) otherwise * * N.B. Set n_squarefree = 1 if n is squarefree, and 0 otherwise. * This last parameter is inconvenient, but it allows a cheap * stringent test. (n guessed from guess_roots())*/ static GEN ZXirred_is_cyclo_translate(GEN T, long n_squarefree) { long r, m, d = degpol(T); GEN T1, c = divis_rem(gel(T, d+1), d, &r); /* d-1 th coeff divisible by d ? */ /* The trace coefficient of polcyclo(n) is \pm1 if n is square free, and 0 * otherwise. */ if (!n_squarefree) { if (r) return NULL; } else { if (r < -1) { r += d; c = subiu(c, 1); } else if (r == d-1) { r = -1; c = addiu(c, 1); } if (r != 1 && r != -1) return NULL; } if (signe(c)) /* presumably Phi_guess(c \pm x) */ T = RgX_translate(T, negi(c)); if (!n_squarefree) T = RgX_deflate_max(T, &m); /* presumably Phi_core(guess)(\pm x), cyclotomic iff original T was */ T1 = ZX_graeffe(T); if (ZX_equal(T, T1)) /* T = Phi_n, n odd */ return deg1pol_shallow(gen_m1, negi(c), varn(T)); else if (ZX_equal(T1, ZX_z_unscale(T, -1))) /* T = Phi_{2n}, nodd */ return deg1pol_shallow(gen_1, c, varn(T)); return NULL; } static GEN trivroots(void) { return mkvec2(gen_2, gen_m1); } /* Number of roots of unity in number field [nf]. */ GEN nfrootsof1(GEN nf) { GEN T, fa, LP, LE, z, disc, index; pari_timer ti; long i, l, nbguessed, nbroots, nfdegree; pari_sp av; T = get_nfpol(nf, &nf); nfdegree = degpol(T); RgX_check_ZX(T, "nfrootsof1"); if (nfdegree <= 0) pari_err_CONSTPOL("nfrootsof1"); if (nf) { if (nf_get_r1(nf)) return trivroots(); disc = nf_get_disc(nf); index = nf_get_index(nf); } else { if (odd(nfdegree) || signe(leading_coeff(T)) != signe(constant_coeff(T))) return trivroots(); disc = ZX_disc(T); index = gen_1; } /* Step 1 : guess number of roots and discard trivial case 2 */ if (DEBUGLEVEL>2) timer_start(&ti); nbguessed = guess_roots(T, disc, index); if (DEBUGLEVEL>2) timer_printf(&ti, "guessing roots of 1 [guess = %ld]", nbguessed); if (nbguessed == 2) return trivroots(); fa = factoru(nbguessed); LP = gel(fa,1); l = lg(LP); LE = gel(fa,2); for (i = 1; i < l; i++) { long p = LP[i]; /* Degree and ramification test: find largest k such that Q(zeta_{p^k}) * may be a subfield of K. Q(zeta_p^k) has degree (p-1)p^(k-1) * and v_p(discriminant) = ((p-1)k-1)p^(k-1); so we must have * v_p(disc_K) >= ((p-1)k-1) * n / (p-1) = kn - q, where q = n/(p-1) */ if (p == 2) { /* the test simplifies a little in that case */ long v, vnf, k; if (LE[i] == 1) continue; vnf = vals(nfdegree); v = vali(disc); for (k = minss(LE[i], vnf+1); k >= 1; k--) if (v >= nfdegree*(k-1)) { nbguessed >>= LE[i]-k; LE[i] = k; break; } /* N.B the test above always works for k = 1: LE[i] >= 1 */ } else { long v, vnf, k; ulong r, q = udivuu_rem(nfdegree, p-1, &r); if (r) { nbguessed /= upowuu(p, LE[i]); LE[i] = 0; continue; } /* q = n/(p-1) */ vnf = u_lval(q, p); v = Z_lval(disc, p); for (k = minss(LE[i], vnf+1); k >= 0; k--) if (v >= nfdegree*k-(long)q) { nbguessed /= upowuu(p, LE[i]-k); LE[i] = k; break; } /* N.B the test above always works for k = 0: LE[i] >= 0 */ } } if (DEBUGLEVEL>2) timer_printf(&ti, "after ramification conditions [guess = %ld]", nbguessed); if (nbguessed == 2) return trivroots(); av = avma; /* Step 1.5 : test if nf.pol == subst(polcyclo(nbguessed), x, \pm x+c) */ if (eulerphiu_fact(fa) == (ulong)nfdegree) { z = ZXirred_is_cyclo_translate(T, uissquarefree_fact(fa)); if (DEBUGLEVEL>2) timer_printf(&ti, "checking for cyclotomic polynomial"); if (z) { if (nf) z = nf_to_scalar_or_basis(nf,z); return gerepilecopy(av, mkvec2(utoipos(nbguessed), z)); } set_avma(av); } /* Step 2 : actual computation of roots */ nbroots = 2; z = scalarpol(gen_m1, varn(T)); 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 */ pari_sp av = avma; long pk = upowuu(p,k); GEN r; if (pk==2) continue; /* no need to test second roots ! */ r = nfisincl0(polcyclo(pk, 0), T, 1); if (!isintzero(r)) { if (DEBUGLEVEL>2) err_printf(" %s root of unity found\n",uordinal(pk)); if (p==2) { nbroots = pk; z = r; } else { nbroots *= pk; z = nf ? nfmul(nf, z, r): QXQ_mul(z, r, T); } break; } set_avma(av); if (DEBUGLEVEL) pari_warn(warner,"nfrootsof1: wrong guess"); } } if (nf) z = nf_to_scalar_or_basis(nf,z); return gerepilecopy(av, mkvec2(utoi(nbroots), z)); } /*******************************************************************/ /* */ /* rnfgaloisconj */ /* */ /*******************************************************************/ static GEN rnffrobeniuslift(GEN nf, GEN P, GEN Tp, GEN p, GEN bound, GEN den, GEN iden, GEN T) { GEN q, Tq, Pp, Pq, s, S; long v = varn(P), e; nflift_t L; L.p = p; L.Tp = Tp; L.tozk = nf_get_invzk(nf); L.topow= nf_get_zkprimpart(nf); L.topowden = nf_get_zkden(nf); bestlift_init(0, nf, bound, &L); q = L.pk; Tq = L.Tpk; e = L.k; P = gmul(P,L.topowden); Pq = ZqX(RgX_to_nfX(nf, P), q, Tq, L.ZqProj); Pp = FqX_red(Pq, Tp, p); s = FpXQXQ_pow(pol_x(v), powiu(p, degpol(Tp)), Pp, Tp, p); S = ZqX_ZqXQ_liftroot(Pq, s, Pq, Tq, p, e); den = nf_to_Zq(den, Tq, q, shifti(q,-1), L.ZqProj); S = FqX_Fq_mul(S, den, Tq, q); P = nf_pol_lift(S, bound, &L); if (!P) return NULL; return gdiv(QXQX_QXQ_mul(P, iden, T), L.topowden); } static GEN RgX_galconj_bound(GEN T, long prec) { GEN L = QX_complex_roots(T, prec); GEN prep = vandermondeinverseinit(L); GEN M = vandermondeinverse(L, RgX_gtofp(T, prec), gen_1, prep); return gmul(matrixnorm(M, prec), gsupnorm(L, prec)); } static GEN rnfgaloisconj_bound(GEN P, GEN z, GEN den, long prec) { pari_sp av = avma; long i, l = lg(z); GEN s = gen_0; for (i = 1; i < l; i++) { GEN a = gabs(RgX_cxeval(den, gel(z,i), NULL),prec); GEN b = RgX_galconj_bound(RgXY_cxevalx(P, gel(z,i), NULL), prec); s = gerepileupto(av, gadd(s, gsqr(gmul(a,b)))); } return gerepileupto(av, ceil_safe(s)); } static GEN FlxqXQV_fixedalg(GEN aut, GEN S, GEN T, ulong p) { pari_sp av = avma; long d = get_FlxqX_degree(S), sv = get_Flx_var(T), v = get_FlxqX_var(S); long i, l = lg(aut); GEN A = RgX_to_FlxqX(gel(aut,1), T, p); GEN M = FlxXV_to_FlxM(FlxqXQ_powers(A, d-1, S, T, p), d, sv); GEN M2 = FlxM_Flx_add_shallow(M, Fl_to_Flx(p-1, sv), p); GEN C = FlxM_to_FlxXV(FlxqM_ker(M2, T, p), v); for (i = 2; i < l; i++) { GEN A = RgX_to_FlxqX(gel(aut,i), T, p); GEN M = FlxXC_sub(FlxqXC_FlxqXQ_eval(C, A, S, T, p), C, p); GEN K = FlxqM_ker(FlxXV_to_FlxM(M, d, sv), T, p); C = FlxM_to_FlxXV(FlxqM_mul(FlxXV_to_FlxM(C, d, sv), K, T, p), v); } return gerepilecopy(av, C); } static long fixedalg_order(GEN aut, GEN S, GEN T, ulong p) { pari_sp av = avma; long e, i, d = get_Flx_degree(T), l = lg(aut); for (e = 1;; e++, set_avma(av)) { for (i = 1; i < l; i++, set_avma(av)) if (!gequal(FlxqXQ_pow(gel(aut,i), powuu(p, d*e), S, T, p), gel(aut,i))) break; if (i == l) return e; } } static GEN rnfgaloisanalysis(GEN nf, GEN P, GEN aut, long m, GEN d, long *pt_o) { GEN T = nf_get_pol(nf), R = NULL, den = nf_get_zkden(nf); long n = degpol(P), omax = 0, ntry = 0; GEN daut = lg(aut) > 1 ? Q_denom(aut) : NULL; forprime_t S; u_forprime_init(&S, 2, ULONG_MAX); while (ntry <= n || omax < 2) { ulong p = u_forprime_next(&S); GEN F, Tp; long i, lF; if ((d && dvdiu(d,p)) || dvdiu(den, p) || (daut && dvdiu(daut,p))) continue; Tp = ZX_to_Flx(T, p); if (!Flx_is_squarefree(Tp,p)) continue; F = gel(Flx_factor(Tp, p), 1); lF = lg(F); for (i = 1; i < lF; i++) { pari_sp av = avma; long o, d; GEN D, Fi = gel(F,i), Pp = RgX_to_FlxqX(P, Fi, p); if (degpol(Pp) < n || !FlxqX_is_squarefree(Pp, Fi, p)) continue; D = FlxqX_nbfact_by_degree(Pp, &d, Fi, p); o = n / d; /* d factors, all should have degree o */ if (D[o] != d) { if(DEBUGLEVEL) err_printf("rnfisabelian: not Galois at %lu: %Ps\n",p,D); return NULL; } if (lg(aut) > 1) { GEN U = FlxqXQV_fixedalg(aut, Pp, Fi, p); o = fixedalg_order(U, Pp, Fi, p); d = m / o; } if (d == 1) { *pt_o = o; return mkvec2(Flx_to_ZX(Fi), utoi(p)); } if (o > omax) { omax = o; R = mkvec2(Flx_to_ZX(Fi), utoi(p)); } else set_avma(av); } ntry++; } *pt_o = omax; return R; } static GEN rnfabelianconjgen_i(GEN nf, GEN P) { long prec, m, i, l; GEN bnd, den, iden, T, Pr, gen, orders, d; nf = checknf(nf); T = nf_get_pol(nf); P = RgX_nffix("rnfgaloisconj", T, P, 1); P = Q_remove_denom(P, &d); Pr = RgX_to_nfX(nf, P); prec = DEFAULTPREC + nbits2extraprec(gexpo(Pr) * degpol(T)); nf = nfnewprec_shallow(nf, prec); den = nfX_disc(nf, P); bnd = rnfgaloisconj_bound(P, nf_get_roots(nf), den, prec); iden = QXQ_inv(den, T); den = nf_to_scalar_or_basis(nf, den); m = degpol(P); l = expu(m) + 1; gen = cgetg(l, t_VEC); orders = cgetg(l,t_VECSMALL); for (i = 1; m > 1; i++) { long o; GEN S, Tp; setlg(gen, i); Tp = rnfgaloisanalysis(nf, P, gen, m, d, &o); if (!Tp) return NULL; S = rnffrobeniuslift(nf, P, gel(Tp,1), gel(Tp,2), bnd, den, iden, T); if (!S) return NULL; gel(gen,i) = S; orders[i] = o; m /= o; } setlg(gen,i); setlg(orders,i); return mkvec2(gen, orders); } GEN rnfabelianconjgen(GEN nf, GEN P) { pari_sp av = avma; GEN G = rnfabelianconjgen_i(nf, P); return G? gerepilecopy(av, G): gc_const(av, gen_0); } long rnfisabelian(GEN nf, GEN pol) { pari_sp av = avma; GEN G = rnfabelianconjgen_i(nf, pol); return gc_long(av, G? 1: 0); } pari-2.17.2/src/basemath/FpXX.c0000644000175000017500000015562414716371161014554 0ustar billbill/* Copyright (C) 2012 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" /* Not so fast arithmetic with polynomials over FpX */ /*******************************************************************/ /* */ /* FpXX */ /* */ /*******************************************************************/ /*Polynomials whose coefficients are either polynomials or integers*/ static GEN to_ZX(GEN a, long v) { return typ(a)==t_INT? scalarpol_shallow(a,v): a; } static ulong to_FlxqX(GEN P, GEN Q, GEN T, GEN p, GEN *pt_P, GEN *pt_Q, GEN *pt_T) { ulong pp = uel(p,2); long v = get_FpX_var(T); *pt_P = ZXX_to_FlxX(P, pp, v); if (pt_Q) *pt_Q = ZXX_to_FlxX(Q, pp, v); *pt_T = ZXT_to_FlxT(T, pp); return pp; } static GEN ZXX_copy(GEN a) { return gcopy(a); } GEN FpXX_red(GEN z, GEN p) { GEN res; long i, l = lg(z); res = cgetg(l,t_POL); res[1] = z[1]; for (i=2; ilx) swapspec(x,y, lx,ly); lz = lx; z = cgetg(lz, t_POL); z[1]=x[1]; for (i=2; i=0 && !signe(gel(y, dy1)); dy1--); p1 = gel(x,dx); av = avma; gel(z,dz) = lead? gerepileupto(av, Fq_mul(p1,lead, T, p)): gcopy(p1); for (i=dx-1; i>=dy; i--) { av=avma; p1=gel(x,i); for (j=i-dy1; 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) { guncloneNULL(lead); return z-2; } rem = (GEN)avma; av = (pari_sp)new_chunk(dx+3); for (sx=0; ; i--) { p1 = gel(x,i); for (j=maxss(0,i-dy1); 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; set_avma(av); } if (pr == ONLY_DIVIDES) { guncloneNULL(lead); if (sx) return gc_NULL(av0); return gc_const((pari_sp)rem, 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=maxss(0,i-dy1); 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; guncloneNULL(lead); if (!sx) (void)FpXQX_renormalize(rem, lr); if (pr == ONLY_REM) return gerepileupto(av0,rem); *pr = rem; return z-2; } static GEN FpXQX_addmulmul(GEN u, GEN v, GEN x, GEN y, GEN T, GEN p) { return FpXX_add(FpXQX_mul(u, x, T, p),FpXQX_mul(v, y, T, p), p); } static GEN FpXQXM_FpXQX_mul2(GEN M, GEN x, GEN y, GEN T, GEN p) { GEN res = cgetg(3, t_COL); gel(res, 1) = FpXQX_addmulmul(gcoeff(M,1,1), gcoeff(M,1,2), x, y, T, p); gel(res, 2) = FpXQX_addmulmul(gcoeff(M,2,1), gcoeff(M,2,2), x, y, T, p); return res; } static GEN FpXQXM_mul2(GEN A, GEN B, GEN T, GEN p) { GEN A11=gcoeff(A,1,1),A12=gcoeff(A,1,2), B11=gcoeff(B,1,1),B12=gcoeff(B,1,2); GEN A21=gcoeff(A,2,1),A22=gcoeff(A,2,2), B21=gcoeff(B,2,1),B22=gcoeff(B,2,2); GEN M1 = FpXQX_mul(FpXX_add(A11,A22, p), FpXX_add(B11,B22, p), T, p); GEN M2 = FpXQX_mul(FpXX_add(A21,A22, p), B11, T, p); GEN M3 = FpXQX_mul(A11, FpXX_sub(B12,B22, p), T, p); GEN M4 = FpXQX_mul(A22, FpXX_sub(B21,B11, p), T, p); GEN M5 = FpXQX_mul(FpXX_add(A11,A12, p), B22, T, p); GEN M6 = FpXQX_mul(FpXX_sub(A21,A11, p), FpXX_add(B11,B12, p), T, p); GEN M7 = FpXQX_mul(FpXX_sub(A12,A22, p), FpXX_add(B21,B22, p), T, p); GEN T1 = FpXX_add(M1,M4, p), T2 = FpXX_sub(M7,M5, p); GEN T3 = FpXX_sub(M1,M2, p), T4 = FpXX_add(M3,M6, p); retmkmat22(FpXX_add(T1,T2, p), FpXX_add(M3,M5, p), FpXX_add(M2,M4, p), FpXX_add(T3,T4, p)); } /* Return [0,1;1,-q]*M */ static GEN FpXQX_FpXQXM_qmul(GEN q, GEN M, GEN T, GEN p) { GEN u = FpXQX_mul(gcoeff(M,2,1), q, T, p); GEN v = FpXQX_mul(gcoeff(M,2,2), q, T, p); retmkmat22(gcoeff(M,2,1), gcoeff(M,2,2), FpXX_sub(gcoeff(M,1,1), u, p), FpXX_sub(gcoeff(M,1,2), v, p)); } static GEN matid2_FpXQXM(long v) { retmkmat22(pol_1(v),pol_0(v),pol_0(v),pol_1(v)); } static GEN matJ2_FpXQXM(long v) { retmkmat22(pol_0(v),pol_1(v),pol_1(v),pol_0(v)); } static GEN FpXX_shift(GEN a, long n) { return RgX_shift_shallow(a, n); } INLINE GEN FpXXn_red(GEN a, long n) { return RgXn_red_shallow(a, n); } /* Fast resultant formula from William Hart in Flint */ struct FpXQX_res { GEN res, lc; long deg0, deg1, off; }; INLINE void FpXQX_halfres_update(long da, long db, long dr, GEN T, GEN p, struct FpXQX_res *res) { if (dr >= 0) { if (!ZX_equal1(res->lc)) { res->lc = FpXQ_powu(res->lc, da - dr, T, p); res->res = FpXQ_mul(res->res, res->lc, T, p); } if (both_odd(da + res->off, db + res->off)) res->res = FpX_neg(res->res, p); } else { if (db == 0) { if (!ZX_equal1(res->lc)) { res->lc = FpXQ_powu(res->lc, da, T, p); res->res = FpXQ_mul(res->res, res->lc, T, p); } } else res->res = pol_0(get_FpX_var(T)); } } static GEN FpXQX_halfres_basecase(GEN a, GEN b, GEN T, GEN p, GEN *pa, GEN *pb, struct FpXQX_res *res) { pari_sp av=avma; GEN u,u1,v,v1, M; long vx = varn(a), vT = get_FpX_var(T), n = lgpol(a)>>1; u1 = v = pol_0(vx); u = v1 = pol_1(vx); while (lgpol(b)>n) { GEN r, q; q = FpXQX_divrem(a,b, T, p, &r); if (res) { long da = degpol(a), db=degpol(b), dr = degpol(r); res->lc = to_ZX(gel(b,db+2),vT); if (dr >= n) FpXQX_halfres_update(da, db, dr, T, p, res); else { res->deg0 = da; res->deg1 = db; } } a = b; b = r; swap(u,u1); swap(v,v1); u1 = FpXX_sub(u1, FpXQX_mul(u, q, T, p), p); v1 = FpXX_sub(v1, FpXQX_mul(v, q, T, p), p); if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"FpXQX_halfgcd (d = %ld)",degpol(b)); if (res) gerepileall(av, 8, &a,&b,&u1,&v1,&u,&v,&res->res,&res->lc); else gerepileall(av, 6, &a,&b,&u1,&v1,&u,&v); } } M = mkmat22(u,v,u1,v1); *pa = a; *pb = b; return res ? gc_all(av, 5, &M, pa, pb, &res->res, &res->lc) : gc_all(av, 3, &M, pa, pb); } static GEN FpXQX_halfres_i(GEN x, GEN y, GEN T, GEN p, GEN *a, GEN *b, struct FpXQX_res *res); static GEN FpXQX_halfres_split(GEN x, GEN y, GEN T, GEN p, GEN *a, GEN *b, struct FpXQX_res *res) { pari_sp av = avma; GEN Q, R, S, V1, V2; GEN x1, y1, r, q; long l = lgpol(x), n = l>>1, k, vT = get_FpX_var(T); if (lgpol(y) <= n) { *a = RgX_copy(x); *b = RgX_copy(y); return matid2_FpXQXM(varn(x)); } if (res) { res->lc = to_ZX(leading_coeff(y), vT); res->deg0 -= n; res->deg1 -= n; res->off += n; } R = FpXQX_halfres_i(FpXX_shift(x,-n),FpXX_shift(y,-n), T, p, a, b, res); if (res) { res->off -= n; res->deg0 += n; res->deg1 += n; } V1 = FpXQXM_FpXQX_mul2(R, Flxn_red(x,n), Flxn_red(y,n), T, p); x1 = FpXX_add(FpXX_shift(*a,n), gel(V1,1), p); y1 = FpXX_add(FpXX_shift(*b,n), gel(V1,2), p); if (lgpol(y1) <= n) { *a = x1; *b = y1; return res ? gc_all(av, 5, &R, a, b, &res->res, &res->lc) : gc_all(av, 3, &R, a, b); } k = 2*n-degpol(y1); q = FpXQX_divrem(x1, y1, T, p, &r); if (res) { long dx1 = degpol(x1), dy1 = degpol(y1), dr = degpol(r); if (dy1 < degpol(y)) FpXQX_halfres_update(res->deg0, res->deg1, dy1, T, p, res); res->lc = to_ZX(leading_coeff(y1), vT); res->deg0 = dx1; res->deg1 = dy1; if (dr >= n) { FpXQX_halfres_update(dx1, dy1, dr, T, p, res); res->deg0 = dy1; res->deg1 = dr; } res->deg0 -= k; res->deg1 -= k; res->off += k; } S = FpXQX_halfres_i(FpXX_shift(y1,-k), FpXX_shift(r,-k), T, p, a, b, res); if (res) { res->deg0 += k; res->deg1 += k; res->off -= k; } Q = FpXQXM_mul2(S,FpXQX_FpXQXM_qmul(q, R, T, p), T, p); V2 = FpXQXM_FpXQX_mul2(S, FpXXn_red(y1,k), FpXXn_red(r,k), T, p); *a = FpXX_add(FpXX_shift(*a,k), gel(V2,1), p); *b = FpXX_add(FpXX_shift(*b,k), gel(V2,2), p); return res ? gc_all(av, 5, &Q, a, b, &res->res, &res->lc) : gc_all(av, 3, &Q, a, b); } static GEN FpXQX_halfres_i(GEN x, GEN y, GEN T, GEN p, GEN *a, GEN *b, struct FpXQX_res *res) { if (lgpol(x) < FpXQX_HALFGCD_LIMIT) return FpXQX_halfres_basecase(x, y, T, p, a, b, res); return FpXQX_halfres_split(x, y, T, p, a, b, res); } static GEN FpXQX_halfgcd_all_i(GEN x, GEN y, GEN T, GEN p, GEN *pa, GEN *pb) { GEN a, b; GEN R = FpXQX_halfres_i(x, y, T, p, &a, &b, NULL); if (pa) *pa = a; if (pb) *pb = b; return R; } /* Return M in GL_2(Fp[X]/(T)[Y]) such that: if [a',b']~=M*[a,b]~ then degpol(a')>= (lgpol(a)>>1) >degpol(b') */ GEN FpXQX_halfgcd_all(GEN x, GEN y, GEN T, GEN p, GEN *a, GEN *b) { pari_sp av = avma; GEN R,q,r; if (lgefint(p)==3) { ulong pp = to_FlxqX(x, y, T, p, &x, &y, &T); R = FlxXM_to_ZXXM(FlxqX_halfgcd(x, y, T, pp)); if (a) *a = Flx_to_ZX(*a); if (b) *b = Flx_to_ZX(*b); return !a && b ? gc_all(av, 2, &R, b): gc_all(av, 1+!!a+!!b, &R, a, b); } if (!signe(x)) { if (a) *a = RgX_copy(y); if (b) *b = RgX_copy(x); return matJ2_FpXQXM(varn(x)); } if (degpol(y)1) pari_warn(warnmem,"FpXQX_gcd (d = %ld)",degpol(b)); gerepileall(av0,2, &a,&b); } av = avma; c = FpXQX_rem(a, b, T, p); a=b; b=c; } return gc_const(av, a); } GEN FpXQX_gcd(GEN x, GEN y, GEN T, GEN p) { pari_sp av = avma; if (lgefint(p) == 3) { GEN Pl, Ql, Tl, U; ulong pp = to_FlxqX(x, y, T, p, &Pl, &Ql, &Tl); U = FlxqX_gcd(Pl, Ql, Tl, pp); return gerepileupto(av, FlxX_to_ZXX(U)); } x = FpXQX_red(x, T, p); y = FpXQX_red(y, T, p); if (!signe(x)) return gerepileupto(av, y); while (lgpol(y)>=FpXQX_GCD_LIMIT) { if (lgpol(y)<=(lgpol(x)>>1)) { GEN r = FpXQX_rem(x, y, T, p); x = y; y = r; } (void) FpXQX_halfgcd_all(x,y, T, p, &x, &y); if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"FpXQX_gcd (y = %ld)",degpol(y)); gerepileall(av,2,&x,&y); } } return gerepileupto(av, FpXQX_gcd_basecase(x, y, T, p)); } static GEN FpXQX_extgcd_basecase(GEN a, GEN b, GEN T, GEN p, GEN *ptu, GEN *ptv) { pari_sp av=avma; 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 = FpXQX_divrem(d, d1, T, p, &r); v = FpXX_sub(v,FpXQX_mul(q,v1,T, p),p); u=v; v=v1; v1=u; u=r; d=d1; d1=u; if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"FpXQX_extgcd (d = %ld)",degpol(d)); gerepileall(av,5, &d,&d1,&u,&v,&v1); } } if (ptu) *ptu = FpXQX_div(FpXX_sub(d,FpXQX_mul(b,v, T, p), p), a, T, p); *ptv = v; return d; } static GEN FpXQX_extgcd_halfgcd(GEN x, GEN y, GEN T, GEN p, GEN *ptu, GEN *ptv) { GEN u,v; GEN V = cgetg(expu(lgpol(y))+2,t_VEC); long i, n = 0, vs = varn(x); while (lgpol(y) >= FpXQX_EXTGCD_LIMIT) { if (lgpol(y)<=(lgpol(x)>>1)) { GEN r, q = FpXQX_divrem(x, y, T, p, &r); x = y; y = r; gel(V,++n) = mkmat22(pol_0(vs),pol_1(vs),pol_1(vs),FpXX_neg(q,p)); } else gel(V,++n) = FpXQX_halfgcd_all(x, y, T, p, &x, &y); } y = FpXQX_extgcd_basecase(x,y, T, p, &u,&v); for (i = n; i>1; i--) { GEN R = gel(V,i); GEN u1 = FpXQX_addmulmul(u, v, gcoeff(R,1,1), gcoeff(R,2,1), T, p); GEN v1 = FpXQX_addmulmul(u, v, gcoeff(R,1,2), gcoeff(R,2,2), T, p); u = u1; v = v1; } { GEN R = gel(V,1); if (ptu) *ptu = FpXQX_addmulmul(u, v, gcoeff(R,1,1), gcoeff(R,2,1), T, p); *ptv = FpXQX_addmulmul(u, v, gcoeff(R,1,2), gcoeff(R,2,2), T, p); } return y; } /* 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) { pari_sp av = avma; GEN d; if (lgefint(p) == 3) { GEN Pl, Ql, Tl, Dl; ulong pp = to_FlxqX(x, y, T, p, &Pl, &Ql, &Tl); Dl = FlxqX_extgcd(Pl, Ql, Tl, pp, ptu, ptv); if (ptu) *ptu = FlxX_to_ZXX(*ptu); *ptv = FlxX_to_ZXX(*ptv); d = FlxX_to_ZXX(Dl); } else { x = FpXQX_red(x, T, p); y = FpXQX_red(y, T, p); if (lgpol(y)>=FpXQX_EXTGCD_LIMIT) d = FpXQX_extgcd_halfgcd(x, y, T, p, ptu, ptv); else d = FpXQX_extgcd_basecase(x, y, T, p, ptu, ptv); } return gc_all(av, ptu?3:2, &d, ptv, ptu); } static GEN FpXQX_halfres(GEN x, GEN y, GEN T, GEN p, GEN *a, GEN *b, GEN *r) { struct FpXQX_res res; GEN V; long dB, vT = get_FpX_var(T); res.res = *r; res.lc = to_ZX(leading_coeff(y),vT); res.deg0 = degpol(x); res.deg1 = degpol(y); res.off = 0; V = FpXQX_halfres_i(x, y, T, p, a, b, &res); dB = degpol(*b); if (dB < degpol(y)) FpXQX_halfres_update(res.deg0, res.deg1, dB, T, p, &res); *r = res.res; return V; } /* Res(A,B) = Res(B,R) * lc(B)^(a-r) * (-1)^(ab), with R=A%B, a=deg(A) ...*/ static GEN FpXQX_resultant_basecase(GEN a, GEN b, GEN T, GEN p) { pari_sp av = avma; long vT = get_FpX_var(T), da,db,dc; GEN c,lb, res = pol_1(vT); if (!signe(a) || !signe(b)) return pol_0(vT); da = degpol(a); db = degpol(b); if (db > da) { swapspec(a,b, da,db); if (both_odd(da,db)) res = FpX_neg(res, p); } if (!da) return pol_1(vT); /* = res * a[2] ^ db, since 0 <= db <= da = 0 */ while (db) { lb = to_ZX(gel(b,db+2),vT); c = FpXQX_rem(a,b, T,p); a = b; b = c; dc = degpol(c); if (dc < 0) { set_avma(av); return pol_0(vT); } if (both_odd(da,db)) res = FpX_neg(res, p); if (!ZX_equal1(lb)) res = FpXQ_mul(res, FpXQ_powu(lb, da - dc, T, p), T, p); if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"FpXQX_resultant (da = %ld)",da); gerepileall(av,3, &a,&b,&res); } da = db; /* = degpol(a) */ db = dc; /* = degpol(b) */ } res = FpXQ_mul(res, FpXQ_powu(gel(b,2), da, T, p), T, p); return gerepileupto(av, res); } GEN FpXQX_resultant(GEN x, GEN y, GEN T, GEN p) { pari_sp av = avma; long dx, dy, vT = get_FpX_var(T); GEN res = pol_1(vT); if (!signe(x) || !signe(y)) return pol_0(vT); if (lgefint(p) == 3) { pari_sp av = avma; GEN Pl, Ql, Tl, R; ulong pp = to_FlxqX(x, y, T, p, &Pl, &Ql, &Tl); R = FlxqX_resultant(Pl, Ql, Tl, pp); return gerepileupto(av, Flx_to_ZX(R)); } dx = degpol(x); dy = degpol(y); if (dx < dy) { swap(x,y); if (both_odd(dx, dy)) res = Fp_neg(res, p); } while (lgpol(y) >= FpXQX_GCD_LIMIT) { if (lgpol(y)<=(lgpol(x)>>1)) { GEN r = FpXQX_rem(x, y, T, p); long dx = degpol(x), dy = degpol(y), dr = degpol(r); GEN ly = FpX_red(gel(y,dy+2),p); if (!ZX_equal1(ly)) res = FpXQ_mul(res, FpXQ_powu(ly, dx - dr, T, p), T, p); if (both_odd(dx, dy)) res = Fp_neg(res, p); x = y; y = r; } (void) FpXQX_halfres(x, y, T, p, &x, &y, &res); if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"FpXQX_resultant (y = %ld)",degpol(y)); gerepileall(av,3,&x,&y,&res); } } return gerepileupto(av, FpXQ_mul(res, FpXQX_resultant_basecase(x, y, T, p), T, p)); } /* disc P = (-1)^(n(n-1)/2) lc(P)^(n - deg P' - 2) Res(P,P'), n = deg P */ GEN FpXQX_disc(GEN P, GEN T, GEN p) { pari_sp av = avma; GEN L, dP = FpXX_deriv(P, p), D = FpXQX_resultant(P, dP, T, p); long dd; if (!signe(D)) return pol_0(get_FpX_var(T)); dd = degpol(P) - 2 - degpol(dP); /* >= -1; > -1 iff p | deg(P) */ L = leading_coeff(P); if (dd && !gequal1(L)) D = (dd == -1)? FpXQ_div(D,L,T,p): FpXQ_mul(D, FpXQ_powu(L, dd, T, p), T, p); if (degpol(P) & 2) D = FpX_neg(D, p); return gerepileupto(av, D); } GEN FpXQX_dotproduct(GEN x, GEN y, GEN T, GEN p) { long i, l = minss(lg(x), lg(y)); pari_sp av; GEN c; if (l == 2) return gen_0; av = avma; c = gmul(gel(x,2),gel(y,2)); for (i=3; i=0; i--) if (signe(gel(x,i))) break; return i+1; } static GEN FpXQX_invBarrett_basecase(GEN S, GEN T, GEN p) { long i, l=lg(S)-1, lr = l-1, k; GEN r=cgetg(lr, t_POL); r[1]=S[1]; gel(r,2) = gen_1; for (i=3; i 2 */ for (i=0;i1) gel(q,1) = Fq_red(gel(q,1), T, p); if (lQ>1 && signe(gel(q,1))) { GEN u = gel(q, 1); if (!gequal1(gel(x,0))) u = Fq_mul(u, Fq_sqr(gel(x,0), T, p), T, p); gel(x,1) = Fq_neg(u, T, p); lx = 2; } else lx = 1; nold = 1; for (; mask > 1; ) { /* set x -= x(x*q - 1) + O(t^(nnew + 1)), knowing x*q = 1 + O(t^(nold+1)) */ long i, lnew, nnew = nold << 1; if (mask & 1) nnew--; mask >>= 1; lnew = nnew + 1; lq = ZXX_lgrenormalizespec(q, minss(lQ,lnew)); z = FpXQX_mulspec(x, q, T, p, lx, lq); /* FIXME: high product */ lz = lgpol(z); if (lz > lnew) lz = lnew; z += 2; /* subtract 1 [=>first nold words are 0]: renormalize so that z(0) != 0 */ for (i = nold; i < lz; i++) if (signe(gel(z,i))) break; nold = nnew; if (i >= lz) continue; /* z-1 = 0(t^(nnew + 1)) */ /* z + i represents (x*q - 1) / t^i */ lz = ZXX_lgrenormalizespec (z+i, lz-i); z = FpXQX_mulspec(x, z+i, T, p, lx, lz); /* FIXME: low product */ lz = lgpol(z); z += 2; if (lz > lnew-i) lz = ZXX_lgrenormalizespec(z, lnew-i); lx = lz+ i; y = x + i; /* x -= z * t^i, in place */ for (i = 0; i < lz; i++) gel(y,i) = Fq_neg(gel(z,i), T, p); } x -= 2; setlg(x, lx + 2); x[1] = S[1]; return gerepilecopy(av, x); } GEN FpXQX_invBarrett(GEN S, GEN T, GEN p) { pari_sp ltop = avma; long l = lg(S); GEN r; if (l<5) return pol_0(varn(S)); if (l<=FpXQX_INVBARRETT_LIMIT) { GEN c = gel(S,l-1), ci=gen_1; if (!gequal1(c)) { ci = Fq_inv(c, T, p); S = FqX_Fq_mul(S, ci, T, p); r = FpXQX_invBarrett_basecase(S, T, p); r = FqX_Fq_mul(r, ci, T, p); } else r = FpXQX_invBarrett_basecase(S, T, p); } else r = FpXQX_invBarrett_Newton(S, T, p); return gerepileupto(ltop, r); } GEN FpXQX_get_red(GEN S, GEN T, GEN p) { if (typ(S)==t_POL && lg(S)>FpXQX_BARRETT_LIMIT) retmkvec2(FpXQX_invBarrett(S,T,p),S); return S; } /* Compute x mod S where 2 <= degpol(S) <= l+1 <= 2*(degpol(S)-1) * and mg is the Barrett inverse of S. */ static GEN FpXQX_divrem_Barrettspec(GEN x, long l, GEN mg, GEN S, GEN T, GEN p, GEN *pr) { GEN q, r; long lt = degpol(S); /*We discard the leading term*/ long ld, lm, lT, lmg; ld = l-lt; lm = minss(ld, lgpol(mg)); lT = ZXX_lgrenormalizespec(S+2,lt); lmg = ZXX_lgrenormalizespec(mg+2,lm); q = FpXX_recipspec(x+lt,ld,ld); /* q = rec(x) lq<=ld*/ q = FpXQX_mulspec(q+2,mg+2,T,p,lgpol(q),lmg); /* q = rec(x) * mg lq<=ld+lm*/ q = FpXX_recipspec(q+2,minss(ld,lgpol(q)),ld); /* q = rec (rec(x) * mg) lq<=ld*/ if (!pr) return q; r = FpXQX_mulspec(q+2,S+2,T,p,lgpol(q),lT); /* r = q*pol lr<=ld+lt*/ r = FpXX_subspec(x,r+2,p,lt,minss(lt,lgpol(r))); /* r = x - r lr<=lt */ if (pr == ONLY_REM) return r; *pr = r; return q; } static GEN FpXQX_divrem_Barrett(GEN x, GEN mg, GEN S, GEN T, GEN p, GEN *pr) { GEN q = NULL, r = FpXQX_red(x, T, p); long l = lgpol(r), lt = degpol(S), lm = 2*lt-1, v = varn(S); long i; if (l <= lt) { if (pr == ONLY_REM) return r; if (pr == ONLY_DIVIDES) return signe(r)? NULL: pol_0(v); if (pr) *pr = r; return pol_0(v); } if (lt <= 1) return FpXQX_divrem_basecase(r,S,T,p,pr); if (pr != ONLY_REM && l>lm) { q = cgetg(l-lt+2, t_POL); q[1] = S[1]; for (i=0;ilm) { GEN zr, zq = FpXQX_divrem_Barrettspec(r+2+l-lm,lm,mg,S,T,p,&zr); long lz = lgpol(zr); if (pr != ONLY_REM) { long lq = lgpol(zq); for(i=0; i lt) r = FpXQX_divrem_Barrettspec(r+2,l,mg,S,T,p,ONLY_REM); else r = FpXQX_renormalize(r, l+2); setvarn(r, v); return r; } if (l > lt) { GEN zq = FpXQX_divrem_Barrettspec(r+2,l,mg,S,T,p,pr ? &r: NULL); if (!q) q = zq; else { long lq = lgpol(zq); for(i=0; i1; i--) /* z[i] = a[i+1] + x*z[i+1] */ gel(z, i) = Fq_addmul(gel(a,i+1), x, gel(z,i+1), T, p); if (r) *r = Fq_addmul(gel(a,2), x, gel(z,2), T, p); return z; } struct _FpXQXQ { GEN T, S; GEN p; }; static GEN _FpXQX_mul(void *data, GEN a,GEN b) { struct _FpXQXQ *d=(struct _FpXQXQ*)data; return FpXQX_mul(a,b,d->T,d->p); } static GEN _FpXQX_sqr(void *data, GEN a) { struct _FpXQXQ *d=(struct _FpXQXQ*)data; return FpXQX_sqr(a, d->T, d->p); } GEN FpXQX_powu(GEN x, ulong n, GEN T, GEN p) { struct _FpXQXQ D; if (n==0) return pol_1(varn(x)); D.T = T; D.p = p; return gen_powu(x, n, (void *)&D, _FpXQX_sqr, _FpXQX_mul); } GEN FpXQXV_prod(GEN V, GEN T, GEN p) { if (lgefint(p) == 3) { pari_sp av = avma; ulong pp = p[2]; GEN Tl = ZXT_to_FlxT(T, pp); GEN Vl = ZXXV_to_FlxXV(V, pp, get_FpX_var(T)); Tl = FlxqXV_prod(Vl, Tl, pp); return gerepileupto(av, FlxX_to_ZXX(Tl)); } else { struct _FpXQXQ d; d.T=T; d.p=p; return gen_product(V, (void*)&d, &_FpXQX_mul); } } static GEN _FpXQX_divrem(void * E, GEN x, GEN y, GEN *r) { struct _FpXQXQ *d = (struct _FpXQXQ *) E; return FpXQX_divrem(x, y, d->T, d->p, r); } static GEN _FpXQX_add(void * E, GEN x, GEN y) { struct _FpXQXQ *d = (struct _FpXQXQ *) E; return FpXX_add(x, y, d->p); } static GEN _FpXQX_sub(void * E, GEN x, GEN y) { struct _FpXQXQ *d = (struct _FpXQXQ*) E; return FpXX_sub(x,y, d->p); } static struct bb_ring FpXQX_ring = { _FpXQX_add, _FpXQX_mul, _FpXQX_sqr }; GEN FpXQX_digits(GEN x, GEN B, GEN T, GEN p) { long d = degpol(B), n = (lgpol(x)+d-1)/d; struct _FpXQXQ D; D.T = T; D.p = p; return gen_digits(x, B, n, (void *)&D, &FpXQX_ring, _FpXQX_divrem); } GEN FpXQXV_FpXQX_fromdigits(GEN x, GEN B, GEN T, GEN p) { struct _FpXQXQ D; D.T = T; D.p = p; return gen_fromdigits(x,B,(void *)&D, &FpXQX_ring); } /* Q an FpXY (t_POL with FpX coeffs), evaluate at X = x */ GEN FpXY_evalx(GEN Q, GEN x, GEN p) { long i, lb = lg(Q); GEN z; z = cgetg(lb, t_POL); z[1] = Q[1]; for (i=2; i=2; i--) z = Fq_add(gel(Q,i), FpX_Fp_mul(z, y, p), NULL, p); return gerepileupto(av, z); } /* Q an FpXY, evaluate at (X,Y) = (x,y) */ GEN FpXY_eval(GEN Q, GEN y, GEN x, GEN p) { pari_sp av = avma; return gerepileuptoint(av, FpX_eval(FpXY_evalx(Q, x, p), y, p)); } GEN FpXY_FpXQV_evalx(GEN P, GEN x, GEN T, GEN p) { long i, lP = lg(P); GEN res = cgetg(lP,t_POL); res[1] = P[1]; for(i=2; iT, D->p),D->S,D->T,D->p); } static GEN FpXYQQ_mul(void *data, GEN x, GEN y) { FpXYQQ_muldata *D = (FpXYQQ_muldata*)data; return FpXYQQ_redswap(FpXQX_mul(x,y, D->T, D->p),D->S,D->T,D->p); } /* x in Z[X,Y], S in Z[X] over Fq = Z[Y]/(p,T); compute lift(x^n mod (S,T,p)) */ GEN FpXYQQ_pow(GEN x, GEN n, GEN S, GEN T, GEN p) { pari_sp av = avma; FpXYQQ_muldata D; GEN y; if (lgefint(p) == 3) { ulong pp = to_FlxqX(x, NULL, T, p, &x, NULL, &T); S = ZX_to_Flx(S, pp); y = FlxX_to_ZXX( FlxYqq_pow(x, n, S, T, pp) ); y = gerepileupto(av, y); } else { D.S = S; D.T = T; D.p = p; y = gen_pow(x, n, (void*)&D, &FpXYQQ_sqr, &FpXYQQ_mul); } return y; } GEN FpXQXQ_mul(GEN x, GEN y, GEN S, GEN T, GEN p) { return FpXQX_rem(FpXQX_mul(x, y, T, p), S, T, p); } GEN FpXQXQ_sqr(GEN x, GEN S, GEN T, GEN p) { return FpXQX_rem(FpXQX_sqr(x, T, p), S, T, p); } /* Inverse of x in Z/pZ[X]/(pol) or NULL if inverse doesn't exist * return lift(1 / (x mod (p,pol))) */ GEN FpXQXQ_invsafe(GEN x, GEN S, GEN T, GEN p) { GEN V, z = FpXQX_extgcd(get_FpXQX_mod(S), x, T, p, NULL, &V); if (degpol(z)) return NULL; z = gel(z,2); z = typ(z)==t_INT ? Fp_invsafe(z,p) : FpXQ_invsafe(z,T,p); if (!z) return NULL; return typ(z)==t_INT ? FpXX_Fp_mul(V, z, p): FpXQX_FpXQ_mul(V, z, T, p); } GEN FpXQXQ_inv(GEN x, GEN S, GEN T,GEN p) { pari_sp av = avma; GEN U = FpXQXQ_invsafe(x, S, T, p); if (!U) pari_err_INV("FpXQXQ_inv",x); return gerepileupto(av, U); } GEN FpXQXQ_div(GEN x,GEN y,GEN S, GEN T,GEN p) { pari_sp av = avma; return gerepileupto(av, FpXQXQ_mul(x, FpXQXQ_inv(y,S,T,p),S,T,p)); } static GEN _FpXQXQ_cmul(void *data, GEN P, long a, GEN x) { struct _FpXQXQ *d = (struct _FpXQXQ*) data; GEN y = gel(P,a+2); return typ(y)==t_INT ? FpXX_Fp_mul(x,y, d->p): FpXX_FpX_mul(x,y,d->p); } static GEN _FpXQXQ_red(void *data, GEN x) { struct _FpXQXQ *d = (struct _FpXQXQ*) data; return FpXQX_red(x, d->T, d->p); } static GEN _FpXQXQ_mul(void *data, GEN x, GEN y) { struct _FpXQXQ *d = (struct _FpXQXQ*) data; return FpXQXQ_mul(x,y, d->S,d->T, d->p); } static GEN _FpXQXQ_sqr(void *data, GEN x) { struct _FpXQXQ *d = (struct _FpXQXQ*) data; return FpXQXQ_sqr(x, d->S,d->T, d->p); } static GEN _FpXQXQ_one(void *data) { struct _FpXQXQ *d = (struct _FpXQXQ*) data; return pol_1(get_FpXQX_var(d->S)); } static GEN _FpXQXQ_zero(void *data) { struct _FpXQXQ *d = (struct _FpXQXQ*) data; return pol_0(get_FpXQX_var(d->S)); } static struct bb_algebra FpXQXQ_algebra = { _FpXQXQ_red, _FpXQX_add, _FpXQX_sub, _FpXQXQ_mul, _FpXQXQ_sqr, _FpXQXQ_one, _FpXQXQ_zero }; const struct bb_algebra * get_FpXQXQ_algebra(void **E, GEN S, GEN T, GEN p) { GEN z = new_chunk(sizeof(struct _FpXQXQ)); struct _FpXQXQ *e = (struct _FpXQXQ *) z; e->T = FpX_get_red(T, p); e->S = FpXQX_get_red(S, e->T, p); e->p = p; *E = (void*)e; return &FpXQXQ_algebra; } static struct bb_algebra FpXQX_algebra = { _FpXQXQ_red, _FpXQX_add, _FpXQX_sub, _FpXQX_mul, _FpXQX_sqr, _FpXQXQ_one, _FpXQXQ_zero }; const struct bb_algebra * get_FpXQX_algebra(void **E, GEN T, GEN p, long v) { GEN z = new_chunk(sizeof(struct _FpXQXQ)); struct _FpXQXQ *e = (struct _FpXQXQ *) z; e->T = FpX_get_red(T, p); e->S = pol_x(v); e->p = p; *E = (void*)e; return &FpXQX_algebra; } /* 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; struct _FpXQXQ D; long s = signe(n); if (!s) return pol_1(varn(x)); if (is_pm1(n)) /* +/- 1 */ return (s < 0)? FpXQXQ_inv(x,S,T,p): ZXX_copy(x); if (lgefint(p) == 3) { ulong pp = to_FlxqX(x, S, T, p, &x, &S, &T); GEN z = FlxqXQ_pow(x, n, S, T, pp); y = FlxX_to_ZXX(z); return gerepileupto(ltop, y); } else { T = FpX_get_red(T, p); S = FpXQX_get_red(S, T, p); D.S = S; D.T = T; D.p = p; if (s < 0) x = FpXQXQ_inv(x,S,T,p); y = gen_pow_i(x, n, (void*)&D,&_FpXQXQ_sqr,&_FpXQXQ_mul); return gerepilecopy(ltop, y); } } /* generates the list of powers of x of degree 0,1,2,...,l*/ GEN FpXQXQ_powers(GEN x, long l, GEN S, GEN T, GEN p) { struct _FpXQXQ D; int use_sqr = 2*degpol(x) >= get_FpXQX_degree(S); T = FpX_get_red(T, p); S = FpXQX_get_red(S, T, p); D.S = S; D.T = T; D.p = p; return gen_powers(x, l, use_sqr, (void*)&D, &_FpXQXQ_sqr, &_FpXQXQ_mul,&_FpXQXQ_one); } /* Let v a linear form, return the linear form z->v(tau*z) that is, v*(M_tau) */ INLINE GEN FpXQX_recipspec(GEN x, long l, long n) { return RgX_recipspec_shallow(x, l, n); } static GEN FpXQXQ_transmul_init(GEN tau, GEN S, GEN T, GEN p) { GEN bht; GEN h, Sp = get_FpXQX_red(S, &h); long n = degpol(Sp), vT = varn(Sp); GEN ft = FpXQX_recipspec(Sp+2, n+1, n+1); GEN bt = FpXQX_recipspec(tau+2, lgpol(tau), n); setvarn(ft, vT); setvarn(bt, vT); if (h) bht = FpXQXn_mul(bt, h, n-1, T, p); else { GEN bh = FpXQX_div(FpXX_shift(tau, n-1), S, T, p); bht = FpXQX_recipspec(bh+2, lgpol(bh), n-1); setvarn(bht, vT); } return mkvec3(bt, bht, ft); } static GEN FpXQXQ_transmul(GEN tau, GEN a, long n, GEN T, GEN p) { pari_sp ltop = avma; GEN t1, t2, t3, vec; GEN bt = gel(tau, 1), bht = gel(tau, 2), ft = gel(tau, 3); if (signe(a)==0) return pol_0(varn(a)); t2 = FpXX_shift(FpXQX_mul(bt, a, T, p),1-n); if (signe(bht)==0) return gerepilecopy(ltop, t2); t1 = FpXX_shift(FpXQX_mul(ft, a, T, p),-n); t3 = FpXQXn_mul(t1, bht, n-1, T, p); vec = FpXX_sub(t2, FpXX_shift(t3, 1), p); return gerepileupto(ltop, vec); } static GEN polxn_FpXX(long n, long v, long vT) { long i, a = n+2; GEN p = cgetg(a+1, t_POL); p[1] = evalsigne(1)|evalvarn(v); for (i = 2; i < a; i++) gel(p,i) = pol_0(vT); gel(p,a) = pol_1(vT); return p; } GEN FpXQXQ_minpoly(GEN x, GEN S, GEN T, GEN p) { pari_sp ltop = avma; long vS, vT, n; GEN v_x, g, tau; vS = get_FpXQX_var(S); vT = get_FpX_var(T); n = get_FpXQX_degree(S); g = pol_1(vS); tau = pol_1(vS); S = FpXQX_get_red(S, T, p); v_x = FpXQXQ_powers(x, usqrt(2*n), S, T, p); while(signe(tau) != 0) { long i, j, m, k1; GEN M, v, tr; GEN g_prime, c; if (degpol(g) == n) { tau = pol_1(vS); g = pol_1(vS); } v = random_FpXQX(n, vS, T, p); tr = FpXQXQ_transmul_init(tau, S, T, p); v = FpXQXQ_transmul(tr, v, n, T, p); m = 2*(n-degpol(g)); k1 = usqrt(m); tr = FpXQXQ_transmul_init(gel(v_x,k1+1), S, T, p); c = cgetg(m+2,t_POL); c[1] = evalsigne(1)|evalvarn(vS); for (i=0; i , i = 0..m-1 */ M = FpXQX_halfgcd(polxn_FpXX(m, vS, vT), c, T, p); g_prime = gmael(M, 2, 2); if (degpol(g_prime) < 1) continue; g = FpXQX_mul(g, g_prime, T, p); tau = FpXQXQ_mul(tau, FpXQX_FpXQXQV_eval(g_prime, v_x, S, T, p), S, T, p); } g = FpXQX_normalize(g,T, p); return gerepilecopy(ltop,g); } GEN FpXQXQ_matrix_pow(GEN y, long n, long m, GEN S, GEN T, GEN p) { return RgXV_to_RgM(FpXQXQ_powers(y,m-1,S,T,p),n); } GEN FpXQX_FpXQXQV_eval(GEN P, GEN V, GEN S, GEN T, GEN p) { struct _FpXQXQ D; T = FpX_get_red(T, p); S = FpXQX_get_red(S, T, p); D.S=S; D.T=T; D.p=p; return gen_bkeval_powers(P, degpol(P), V, (void*)&D, &FpXQXQ_algebra, _FpXQXQ_cmul); } GEN FpXQX_FpXQXQ_eval(GEN Q, GEN x, GEN S, GEN T, GEN p) { struct _FpXQXQ D; int use_sqr = 2*degpol(x) >= get_FpXQX_degree(S); T = FpX_get_red(T, p); S = FpXQX_get_red(S, T, p); D.S=S; D.T=T; D.p=p; return gen_bkeval(Q, degpol(Q), x, use_sqr, (void*)&D, &FpXQXQ_algebra, _FpXQXQ_cmul); } static GEN FpXQXQ_autpow_sqr(void * E, GEN x) { struct _FpXQXQ *D = (struct _FpXQXQ *)E; GEN S = D->S, T = D->T, p = D->p; GEN phi = gel(x,1), S1 = gel(x,2); long n = brent_kung_optpow(get_FpX_degree(T)-1,lgpol(S1)+1,1); GEN V = FpXQ_powers(phi, n, T, p); GEN phi2 = FpX_FpXQV_eval(phi, V, T, p); GEN Sphi = FpXY_FpXQV_evalx(S1, V, T, p); GEN S2 = FpXQX_FpXQXQ_eval(Sphi, S1, S, T, p); return mkvec2(phi2, S2); } static GEN FpXQXQ_autpow_mul(void * E, GEN x, GEN y) { struct _FpXQXQ *D = (struct _FpXQXQ *)E; GEN S = D->S, T = D->T, p = D->p; GEN phi1 = gel(x,1), S1 = gel(x,2); GEN phi2 = gel(y,1), S2 = gel(y,2); long n = brent_kung_optpow(get_FpX_degree(T)-1, lgpol(S1)+1, 1); GEN V = FpXQ_powers(phi2, n, T, p); GEN phi3 = FpX_FpXQV_eval(phi1, V, T, p); GEN Sphi = FpXY_FpXQV_evalx(S1, V, T, p); GEN S3 = FpXQX_FpXQXQ_eval(Sphi, S2, S, T, p); return mkvec2(phi3, S3); } GEN FpXQXQ_autpow(GEN aut, long n, GEN S, GEN T, GEN p) { pari_sp av = avma; struct _FpXQXQ D; T = FpX_get_red(T, p); S = FpXQX_get_red(S, T, p); D.S=S; D.T=T; D.p=p; aut = gen_powu_i(aut,n,&D,FpXQXQ_autpow_sqr,FpXQXQ_autpow_mul); return gerepilecopy(av, aut); } static GEN FpXQXQ_auttrace_mul(void *E, GEN x, GEN y) { struct _FpXQXQ *D = (struct _FpXQXQ *)E; GEN S = D->S, T = D->T; GEN p = D->p; GEN S1 = gel(x,1), a1 = gel(x,2); GEN S2 = gel(y,1), a2 = gel(y,2); long n = brent_kung_optpow(maxss(degpol(S1),degpol(a1)),2,1); GEN V = FpXQXQ_powers(S2, n, S, T, p); GEN S3 = FpXQX_FpXQXQV_eval(S1, V, S, T, p); GEN aS = FpXQX_FpXQXQV_eval(a1, V, S, T, p); GEN a3 = FpXX_add(aS, a2, p); return mkvec2(S3, a3); } static GEN FpXQXQ_auttrace_sqr(void *E, GEN x) { return FpXQXQ_auttrace_mul(E, x, x); } GEN FpXQXQ_auttrace(GEN aut, long n, GEN S, GEN T, GEN p) { pari_sp av = avma; struct _FpXQXQ D; T = FpX_get_red(T, p); S = FpXQX_get_red(S, T, p); D.S=S; D.T=T; D.p=p; aut = gen_powu_i(aut,n,&D,FpXQXQ_auttrace_sqr,FpXQXQ_auttrace_mul); return gerepilecopy(av, aut); } static GEN FpXQXQ_autsum_mul(void *E, GEN x, GEN y) { struct _FpXQXQ *D = (struct _FpXQXQ *) E; GEN S = D->S, T = D->T, p = D->p; GEN phi1 = gel(x,1), S1 = gel(x,2), a1 = gel(x,3); GEN phi2 = gel(y,1), S2 = gel(y,2), a2 = gel(y,3); long n2 = brent_kung_optpow(get_FpX_degree(T)-1, lgpol(S1)+lgpol(a1)+1, 1); GEN V2 = FpXQ_powers(phi2, n2, T, p); GEN phi3 = FpX_FpXQV_eval(phi1, V2, T, p); GEN Sphi = FpXY_FpXQV_evalx(S1, V2, T, p); GEN aphi = FpXY_FpXQV_evalx(a1, V2, T, p); long n = brent_kung_optpow(maxss(degpol(Sphi),degpol(aphi)),2,1); GEN V = FpXQXQ_powers(S2, n, S, T, p); GEN S3 = FpXQX_FpXQXQV_eval(Sphi, V, S, T, p); GEN aS = FpXQX_FpXQXQV_eval(aphi, V, S, T, p); GEN a3 = FpXQXQ_mul(aS, a2, S, T, p); return mkvec3(phi3, S3, a3); } static GEN FpXQXQ_autsum_sqr(void * T, GEN x) { return FpXQXQ_autsum_mul(T,x,x); } GEN FpXQXQ_autsum(GEN aut, long n, GEN S, GEN T, GEN p) { pari_sp av = avma; struct _FpXQXQ D; T = FpX_get_red(T, p); S = FpXQX_get_red(S, T, p); D.S=S; D.T=T; D.p=p; aut = gen_powu_i(aut,n,&D,FpXQXQ_autsum_sqr,FpXQXQ_autsum_mul); return gerepilecopy(av, aut); } GEN FpXQXn_mul(GEN x, GEN y, long n, GEN T, GEN p) { pari_sp av = avma; GEN z, kx, ky; long d; if (ZXX_is_ZX(y) && ZXX_is_ZX(x)) return FpXn_mul(x,y,n,p); d = get_FpX_degree(T); kx = RgXX_to_Kronecker(x, d); ky = RgXX_to_Kronecker(y, d); z = Kronecker_to_FpXQX(ZXn_mul(ky,kx,(2*d-1)*n), T, p); return gerepileupto(av, z); } GEN FpXQXn_sqr(GEN x, long n, GEN T, GEN p) { pari_sp av = avma; GEN z, kx; long d; if (ZXX_is_ZX(x)) return ZXn_sqr(x, n); d = get_FpX_degree(T); kx= RgXX_to_Kronecker(x, d); z = Kronecker_to_FpXQX(ZXn_sqr(kx, (2*d-1)*n), T, p); return gerepileupto(av, z); } /* (f*g) \/ x^n */ static GEN FpXQX_mulhigh_i(GEN f, GEN g, long n, GEN T, GEN p) { return FpXX_shift(FpXQX_mul(f,g,T, p),-n); } static GEN FpXQXn_mulhigh(GEN f, GEN g, long n2, long n, GEN T, GEN p) { GEN F = RgX_blocks(f, n2, 2), fl = gel(F,1), fh = gel(F,2); return FpXX_add(FpXQX_mulhigh_i(fl, g, n2, T, p), FpXQXn_mul(fh, g, n - n2, T, p), p); } /* Compute intformal(x^n*S)/x^(n+1) */ static GEN FpXX_integXn(GEN x, long n, GEN p) { long i, lx = lg(x); GEN y; if (lx == 2) return ZXX_copy(x); y = cgetg(lx, t_POL); y[1] = x[1]; for (i=2; i1;) { GEN u, w; long n2 = n; n<<=1; if (mask & 1) n--; mask >>= 1; u = FpXQXn_mul(g, FpXQX_mulhigh_i(f, FpXXn_red(h, n2-1), n2-1, T, p), n-n2, T, p); u = FpXX_add(u, FpXX_shift(FpXXn_red(h, n-1), 1-n2), p); w = FpXQXn_mul(f, ZlXX_integXn(u, n2-1, p, pp), n-n2, T, p); f = FpXX_add(f, FpXX_shift(w, n2), p); if (mask<=1) break; u = FpXQXn_mul(g, FpXQXn_mulhigh(f, g, n2, n, T, p), n-n2, T, p); g = FpXX_sub(g, FpXX_shift(u, n2), p); if (gc_needed(av2,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"FpXQXn_exp, e = %ld", n); gerepileall(av2, 2, &f, &g); } } return gerepileupto(av, f); } GEN FpXQXn_expint(GEN h, long e, GEN T, GEN p) { return ZlXQXn_expint(h, e, T, p, 0); } GEN FpXQXn_exp(GEN h, long e, GEN T, GEN p) { if (signe(h)==0 || degpol(h)<1 || !gequal0(gel(h,2))) pari_err_DOMAIN("FpXQXn_exp","valuation", "<", gen_1, h); return FpXQXn_expint(FpXX_deriv(h, p), e, T, p); } GEN FpXQXn_div(GEN g, GEN f, long e, GEN T, GEN p) { pari_sp av = avma, av2; ulong mask; GEN W, a; long v = varn(f), n = 1; if (!signe(f)) pari_err_INV("FpXXn_inv",f); a = Fq_inv(gel(f,2), T, p); if (e == 1 && !g) return scalarpol(a, v); else if (e == 2 && !g) { GEN b; if (degpol(f) <= 0) return scalarpol(a, v); b = Fq_neg(gel(f,3),T,p); if (signe(b)==0) return scalarpol(a, v); if (!is_pm1(a)) b = Fq_mul(b, Fq_sqr(a, T, p), T, p); W = deg1pol_shallow(b, a, v); return gerepilecopy(av, W); } W = scalarpol_shallow(Fq_inv(gel(f,2), T, p),v); mask = quadratic_prec_mask(e); av2 = avma; for (;mask>1;) { GEN u, fr; long n2 = n; n<<=1; if (mask & 1) n--; mask >>= 1; fr = FpXXn_red(f, n); if (mask>1 || !g) { u = FpXQXn_mul(W, FpXQXn_mulhigh(fr, W, n2, n, T, p), n-n2, T, p); W = FpXX_sub(W, FpXX_shift(u, n2), p); } else { GEN y = FpXQXn_mul(g, W, n, T, p), yt = FpXXn_red(y, n-n2); u = FpXQXn_mul(yt, FpXQXn_mulhigh(fr, W, n2, n, T, p), n-n2, T, p); W = FpXX_sub(y, FpXX_shift(u, n2), p); } if (gc_needed(av2,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"FpXQXn_inv, e = %ld", n); W = gerepileupto(av2, W); } } return gerepileupto(av, W); } GEN FpXQXn_inv(GEN f, long e, GEN T, GEN p) { return FpXQXn_div(NULL, f, e, T, p); } pari-2.17.2/src/basemath/gen3.c0000644000175000017500000034013314760123736014554 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /********************************************************************/ /** **/ /** GENERIC OPERATIONS **/ /** (third part) **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" /********************************************************************/ /** **/ /** PRINCIPAL VARIABLE NUMBER **/ /** **/ /********************************************************************/ static void recvar(hashtable *h, GEN x) { long i = 1, lx = lg(x); void *v; switch(typ(x)) { case t_POL: case t_SER: v = (void*)varn(x); if (!hash_search(h, v)) hash_insert(h, v, NULL); i = 2; break; case t_POLMOD: case t_RFRAC: case t_VEC: case t_COL: case t_MAT: break; case t_LIST: x = list_data(x); lx = x? lg(x): 1; break; default: return; } for (; i < lx; i++) recvar(h, gel(x,i)); } GEN variables_vecsmall(GEN x) { hashtable *h = hash_create_ulong(100, 1); recvar(h, x); return vars_sort_inplace(hash_keys(h)); } GEN variables_vec(GEN x) { return x? vars_to_RgXV(variables_vecsmall(x)): gpolvar(NULL); } long gvar(GEN x) { long i, v, w, lx; switch(typ(x)) { case t_POL: case t_SER: return varn(x); case t_POLMOD: return varn(gel(x,1)); case t_RFRAC: return varn(gel(x,2)); case t_VEC: case t_COL: case t_MAT: lx = lg(x); break; case t_LIST: x = list_data(x); lx = x? lg(x): 1; break; default: return NO_VARIABLE; } v = NO_VARIABLE; for (i=1; i < lx; i++) { w = gvar(gel(x,i)); if (varncmp(w,v) < 0) v = w; } return v; } /* T main polynomial in R[X], A auxiliary in R[X] (possibly degree 0). * Guess and return the main variable of R */ static long var2_aux(GEN T, GEN A) { long a = gvar2(T); long b = (typ(A) == t_POL && varn(A) == varn(T))? gvar2(A): gvar(A); if (varncmp(a, b) > 0) a = b; return a; } static long var2_rfrac(GEN x) { return var2_aux(gel(x,2), gel(x,1)); } static long var2_polmod(GEN x) { return var2_aux(gel(x,1), gel(x,2)); } /* main variable of x, with the convention that the "natural" main * variable of a POLMOD is mute, so we want the next one. */ static long gvar9(GEN x) { return (typ(x) == t_POLMOD)? var2_polmod(x): gvar(x); } /* main variable of the ring over wich x is defined */ long gvar2(GEN x) { long i, v, w; switch(typ(x)) { case t_POLMOD: return var2_polmod(x); case t_POL: case t_SER: v = NO_VARIABLE; for (i=2; i < lg(x); i++) { w = gvar9(gel(x,i)); if (varncmp(w,v) < 0) v=w; } return v; case t_RFRAC: return var2_rfrac(x); case t_VEC: case t_COL: case t_MAT: v = NO_VARIABLE; for (i=1; i < lg(x); i++) { w = gvar2(gel(x,i)); if (varncmp(w,v)<0) v=w; } return v; } return NO_VARIABLE; } /*******************************************************************/ /* */ /* PRECISION OF SCALAR OBJECTS */ /* */ /*******************************************************************/ static long prec0(long e) { return (e < 0)? nbits2prec(-e): LOWDEFAULTPREC; } static long precREAL(GEN x) { return signe(x) ? realprec(x): prec0(expo(x)); } /* x t_REAL, y an exact noncomplex type. Return precision(|x| + |y|) */ static long precrealexact(GEN x, GEN y) { long lx, ey = gexpo(y), ex, e; if (ey == -(long)HIGHEXPOBIT) return precREAL(x); ex = expo(x); e = ey - ex; if (!signe(x)) return prec0((e >= 0)? -e: ex); lx = realprec(x); return (e > 0)? lx + nbits2extraprec(e): lx; } static long precCOMPLEX(GEN z) { /* ~ precision(|x| + |y|) */ GEN x = gel(z,1), y = gel(z,2); long e, ex, ey, lz, lx, ly; if (typ(x) != t_REAL) { if (typ(y) != t_REAL) return 0; return precrealexact(y, x); } if (typ(y) != t_REAL) return precrealexact(x, y); /* x, y are t_REALs, cf addrr_sign */ ex = expo(x); ey = expo(y); e = ey - ex; if (!signe(x)) { if (!signe(y)) return prec0( minss(ex,ey) ); if (e <= 0) return prec0(ex); lz = nbits2prec(e); ly = realprec(y); if (lz > ly) lz = ly; return lz; } if (!signe(y)) { if (e >= 0) return prec0(ey); lz = nbits2prec(-e); lx = realprec(x); if (lz > lx) lz = lx; return lz; } if (e < 0) { swap(x, y); e = -e; } lx = realprec(x); ly = realprec(y); if (e) { long d = nbits2extraprec(e), l = ly-d; return (l > lx)? lx + d: ly; } return minss(lx, ly); } long precision(GEN z) { switch(typ(z)) { case t_REAL: return precREAL(z); case t_COMPLEX: return precCOMPLEX(z); } return 0; } long gprecision(GEN x) { long i, k, l; switch(typ(x)) { case t_REAL: return precREAL(x); case t_COMPLEX: return precCOMPLEX(x); case t_INT: case t_INTMOD: case t_FRAC: case t_FFELT: case t_PADIC: case t_QUAD: case t_POLMOD: return 0; case t_POL: case t_SER: k = LONG_MAX; for (i=lg(x)-1; i>1; i--) { l = gprecision(gel(x,i)); if (l && l0; i--) { l = gprecision(gel(x,i)); if (l && l=imin; i--) { t = padicprec_relative(gel(x,i)); if (t=imin; i--) { t = padicprec(gel(x,i),p); if (t=imin; i--) { t = serprec(gel(x,i),v); if (t= 0, * wrt to main variable if v < 0. */ long poldegree(GEN x, long v) { const long DEGREE0 = -LONG_MAX; long tx = typ(x), lx,w,i,d; if (is_scalar_t(tx)) return gequal0(x)? DEGREE0: 0; switch(tx) { case t_POL: if (!signe(x)) return DEGREE0; w = varn(x); if (v < 0 || v == w) return degpol(x); if (varncmp(v, w) < 0) return 0; lx = lg(x); d = DEGREE0; for (i=2; i d) d = e; } return d; case t_RFRAC: { GEN a = gel(x,1), b = gel(x,2); if (gequal0(a)) return DEGREE0; if (v < 0) { v = varn(b); d = -degpol(b); if (typ(a) == t_POL && varn(a) == v) d += degpol(a); return d; } return poldegree(a,v) - poldegree(b,v); } } pari_err_TYPE("degree",x); return 0; /* LCOV_EXCL_LINE */ } GEN gppoldegree(GEN x, long v) { long d = poldegree(x,v); return d == -LONG_MAX? mkmoo(): stoi(d); } /* assume v >= 0 and x is a POLYNOMIAL in v, return deg_v(x) */ long RgX_degree(GEN x, long v) { long tx = typ(x), lx, w, i, d; if (is_scalar_t(tx)) return gequal0(x)? -1: 0; switch(tx) { case t_POL: if (!signe(x)) return -1; w = varn(x); if (v == w) return degpol(x); if (varncmp(v, w) < 0) return 0; lx = lg(x); d = -1; for (i=2; i d) d = e; } return d; case t_RFRAC: w = varn(gel(x,2)); if (varncmp(v, w) < 0) return 0; if (RgX_degree(gel(x,2),v)) pari_err_TYPE("RgX_degree", x); return RgX_degree(gel(x,1),v); } pari_err_TYPE("RgX_degree",x); return 0; /* LCOV_EXCL_LINE */ } 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 tx = typ(x), w; pari_sp av; if (is_scalar_t(tx)) return gcopy(x); w = varn(x); switch(tx) { case t_POL: if (v < 0 || v == w) { long l = lg(x); return (l==2)? gen_0: gcopy(gel(x,l-1)); } break; case t_SER: if (v < 0 || v == w) return signe(x)? gcopy(gel(x,2)): gen_0; if (varncmp(v, w) > 0) x = polcoef_i(x, valser(x), v); break; default: pari_err_TYPE("pollead",x); return NULL; /* LCOV_EXCL_LINE */ } if (varncmp(v, w) < 0) return gcopy(x); av = avma; w = fetch_var_higher(); x = gsubst(x, v, pol_x(w)); x = pollead(x, w); delete_var(); return gerepileupto(av, x); } /* returns 1 if there's a real component in the structure, 0 otherwise */ int isinexactreal(GEN x) { long i; switch(typ(x)) { case t_REAL: return 1; case t_COMPLEX: return (typ(gel(x,1))==t_REAL || typ(gel(x,2))==t_REAL); case t_INT: case t_INTMOD: case t_FRAC: case t_FFELT: case t_PADIC: case t_QUAD: case t_QFB: return 0; case t_RFRAC: case t_POLMOD: return isinexactreal(gel(x,1)) || isinexactreal(gel(x,2)); case t_POL: case t_SER: for (i=lg(x)-1; i>1; i--) if (isinexactreal(gel(x,i))) return 1; return 0; case t_VEC: case t_COL: case t_MAT: for (i=lg(x)-1; i>0; i--) if (isinexactreal(gel(x,i))) return 1; return 0; default: return 0; } } /* Check if x is approximately real with precision e */ int isrealappr(GEN x, long e) { long i; switch(typ(x)) { case t_INT: case t_REAL: case t_FRAC: return 1; case t_COMPLEX: return (gexpo(gel(x,2)) < e); case t_POL: case t_SER: for (i=lg(x)-1; i>1; i--) if (! isrealappr(gel(x,i),e)) return 0; return 1; case t_RFRAC: case t_POLMOD: return isrealappr(gel(x,1),e) && isrealappr(gel(x,2),e); case t_VEC: case t_COL: case t_MAT: for (i=lg(x)-1; i>0; i--) if (! isrealappr(gel(x,i),e)) return 0; return 1; default: pari_err_TYPE("isrealappr",x); return 0; } } /* returns 1 if there's an inexact component in the structure, and * 0 otherwise. */ int isinexact(GEN x) { long lx, i; switch(typ(x)) { case t_REAL: case t_PADIC: case t_SER: return 1; case t_INT: case t_INTMOD: case t_FFELT: case t_FRAC: case t_QFB: return 0; case t_COMPLEX: case t_QUAD: case t_RFRAC: case t_POLMOD: return isinexact(gel(x,1)) || isinexact(gel(x,2)); case t_POL: for (i=lg(x)-1; i>1; i--) if (isinexact(gel(x,i))) return 1; return 0; case t_VEC: case t_COL: case t_MAT: for (i=lg(x)-1; i>0; i--) if (isinexact(gel(x,i))) return 1; return 0; case t_LIST: x = list_data(x); lx = x? lg(x): 1; for (i=1; i 0; } pari_err_TYPE("iscomplex",x); return 0; /* LCOV_EXCL_LINE */ } /*******************************************************************/ /* */ /* GENERIC REMAINDER */ /* */ /*******************************************************************/ static int is_realquad(GEN x) { GEN Q = gel(x,1); return signe(gel(Q,2)) < 0; } static int is_realext(GEN x) { long t = typ(x); return (t == t_QUAD)? is_realquad(x): is_real_t(t); } /* 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 = addiu(f, 1); return f; } /* y t_REAL, x \ y */ static GEN _quotsr(long x, GEN y) { GEN q, f; if (!x) return gen_0; q = divsr(x,y); f = floorr(q); if (signe(y) < 0 && signe(subir(f,q))) f = addiu(f, 1); return f; } /* x t_REAL, x \ y */ static GEN _quotrs(GEN x, long y) { GEN q = divrs(x,y), f = floorr(q); if (y < 0 && signe(subir(f,q))) f = addiu(f, 1); return f; } static GEN _quotri(GEN x, GEN y) { GEN q = divri(x,y), f = floorr(q); if (signe(y) < 0 && signe(subir(f,q))) f = addiu(f, 1); return f; } static GEN _quotsq(long x, GEN y) { GEN f = gfloor(gdivsg(x,y)); if (gsigne(y) < 0) f = gaddgs(f, 1); return f; } static GEN _quotqs(GEN x, long y) { GEN f = gfloor(gdivgs(x,y)); if (y < 0) f = addiu(f, 1); return f; } /* y t_FRAC, x \ y */ static GEN _quotsf(long x, GEN y) { return truedivii(mulis(gel(y,2),x), gel(y,1)); } /* x t_FRAC, x \ y */ static GEN _quotfs(GEN x, long y) { return truedivii(gel(x,1),mulis(gel(x,2),y)); } /* x t_FRAC, y t_INT, x \ y */ static GEN _quotfi(GEN x, GEN y) { return truedivii(gel(x,1),mulii(gel(x,2),y)); } static GEN quot(GEN x, GEN y) { pari_sp av = avma; return gerepileupto(av, _quot(x, y)); } static GEN quotrs(GEN x, long y) { pari_sp av = avma; return gerepileuptoleaf(av, _quotrs(x,y)); } static GEN quotfs(GEN x, long s) { pari_sp av = avma; return gerepileuptoleaf(av, _quotfs(x,s)); } static GEN quotsr(long x, GEN y) { pari_sp av = avma; return gerepileuptoleaf(av, _quotsr(x, y)); } static GEN quotsf(long x, GEN y) { pari_sp av = avma; return gerepileuptoleaf(av, _quotsf(x, y)); } static GEN quotsq(long x, GEN y) { pari_sp av = avma; return gerepileuptoleaf(av, _quotsq(x, y)); } static GEN quotqs(GEN x, long y) { pari_sp av = avma; return gerepileuptoleaf(av, _quotqs(x, y)); } static GEN quotfi(GEN x, GEN y) { pari_sp av = avma; return gerepileuptoleaf(av, _quotfi(x, y)); } static GEN quotri(GEN x, GEN y) { pari_sp av = avma; return gerepileuptoleaf(av, _quotri(x, y)); } static GEN modrs(GEN x, long y) { pari_sp av = avma; GEN q = _quotrs(x,y); if (!signe(q)) { set_avma(av); return rcopy(x); } return gerepileuptoleaf(av, subri(x, mulis(q,y))); } static GEN modsr(long x, GEN y) { pari_sp av = avma; GEN q = _quotsr(x,y); if (!signe(q)) return gc_stoi(av, x); return gerepileuptoleaf(av, subsr(x, mulir(q,y))); } static GEN modsf(long x, GEN y) { pari_sp av = avma; return gerepileupto(av, Qdivii(modii(mulis(gel(y,2),x), gel(y,1)), gel(y,2))); } /* assume y a t_REAL, x a t_INT, t_FRAC or t_REAL. * Return x mod y or NULL if accuracy error */ GEN modRr_safe(GEN x, GEN y) { GEN q, f; long e; if (isintzero(x)) return gen_0; q = gdiv(x,y); /* t_REAL */ e = expo(q); if (e >= 0 && nbits2prec(e+1) > realprec(q)) return NULL; f = floorr(q); if (signe(y) < 0 && signe(subri(q,f))) f = addiu(f, 1); return signe(f)? gsub(x, mulir(f,y)): x; } GEN modRr_i(GEN x, GEN y, GEN iy) { GEN q, f; long e; if (isintzero(x)) return gen_0; q = gmul(x, iy); /* t_REAL */ e = expo(q); if (e >= 0 && nbits2prec(e+1) > realprec(q)) return NULL; f = floorr(q); if (signe(y) < 0 && signe(subri(q,f))) f = addiu(f, 1); return signe(f)? gsub(x, mulir(f,y)): x; } GEN gmod(GEN x, GEN y) { pari_sp av; long ty, tx; GEN z; tx = typ(x); if (tx == t_INT && !is_bigint(x)) return gmodsg(itos(x),y); ty = typ(y); if (ty == t_INT && !is_bigint(y)) return gmodgs(x,itos(y)); if (is_matvec_t(tx)) pari_APPLY_same(gmod(gel(x,i), y)); if (tx == t_POL || ty == t_POL) return grem(x,y); if (!is_scalar_t(tx) || !is_scalar_t(ty)) pari_err_TYPE2("%",x,y); switch(ty) { case t_INT: switch(tx) { case t_INT: return modii(x,y); case t_INTMOD: z=cgetg(3, t_INTMOD); gel(z,1) = gcdii(gel(x,1),y); gel(z,2) = modii(gel(x,2),gel(z,1)); return z; case t_FRAC: return Fp_div(gel(x,1),gel(x,2),y); case t_PADIC: return padic_to_Fp(x, y); case t_QUAD: if (!is_realquad(x)) break; case t_REAL: av = avma; /* NB: conflicting semantic with lift(x * Mod(1,y)). */ return gerepileupto(av, gsub(x, gmul(_quot(x,y),y))); } break; case t_QUAD: if (!is_realquad(y)) break; case t_REAL: case t_FRAC: if (!is_realext(x)) break; av = avma; return gerepileupto(av, gsub(x, gmul(_quot(x,y),y))); } pari_err_TYPE2("%",x,y); return NULL; /* LCOV_EXCL_LINE */ } GEN gmodgs(GEN x, long y) { ulong u; long i, tx = typ(x); GEN z; if (is_matvec_t(tx)) pari_APPLY_same(gmodgs(gel(x,i), y)); if (!y) pari_err_INV("gmodgs",gen_0); switch(tx) { case t_INT: return modis(x,y); case t_REAL: return modrs(x,y); case t_INTMOD: z=cgetg(3, t_INTMOD); u = (ulong)labs(y); i = ugcdiu(gel(x,1), u); gel(z,1) = utoi(i); gel(z,2) = modis(gel(x,2), i); return z; case t_FRAC: u = (ulong)labs(y); return utoi( Fl_div(umodiu(gel(x,1), u), umodiu(gel(x,2), u), u) ); case t_QUAD: { pari_sp av = avma; if (!is_realquad(x)) break; return gerepileupto(av, gsub(x, gmulgs(_quotqs(x,y),y))); } case t_PADIC: return padic_to_Fp(x, stoi(y)); case t_POL: return scalarpol(Rg_get_0(x), varn(x)); case t_POLMOD: return gmul(gen_0,x); } pari_err_TYPE2("%",x,stoi(y)); return NULL; /* LCOV_EXCL_LINE */ } GEN gmodsg(long x, GEN y) { switch(typ(y)) { case t_INT: return modsi(x,y); case t_REAL: return modsr(x,y); case t_FRAC: return modsf(x,y); case t_QUAD: { pari_sp av = avma; if (!is_realquad(y)) break; return gerepileupto(av, gsubsg(x, gmul(_quotsq(x,y),y))); } case t_POL: if (!signe(y)) pari_err_INV("gmodsg",y); return degpol(y)? gmulsg(x, Rg_get_1(y)): Rg_get_0(y); } pari_err_TYPE2("%",stoi(x),y); return NULL; /* LCOV_EXCL_LINE */ } /* divisibility: return 1 if y | x, 0 otherwise */ int gdvd(GEN x, GEN y) { pari_sp av = avma; return gc_bool(av, gequal0( gmod(x,y) )); } GEN gmodulss(long x, long y) { if (!y) pari_err_INV("%",gen_0); y = labs(y); retmkintmod(utoi(umodsu(x, y)), utoipos(y)); } GEN gmodulsg(long x, GEN y) { switch(typ(y)) { case t_INT: if (!is_bigint(y)) return gmodulss(x,itos(y)); retmkintmod(modsi(x,y), absi(y)); case t_POL: if (!signe(y)) pari_err_INV("%", y); retmkpolmod(degpol(y)? stoi(x): gen_0,RgX_copy(y)); } pari_err_TYPE2("%",stoi(x),y); return NULL; /* LCOV_EXCL_LINE */ } GEN gmodulo(GEN x,GEN y) { long tx = typ(x), vx, vy; if (tx == t_INT && !is_bigint(x)) return gmodulsg(itos(x), y); if (is_matvec_t(tx)) pari_APPLY_same(gmodulo(gel(x,i), y)); switch(typ(y)) { case t_INT: if (!is_const_t(tx)) return gmul(x, gmodulsg(1,y)); if (tx == t_INTMOD) return gmod(x,y); retmkintmod(Rg_to_Fp(x,y), absi(y)); case t_POL: vx = gvar(x); vy = varn(y); if (varncmp(vy, vx) > 0) return gmul(x, gmodulsg(1,y)); if (vx == vy && tx == t_POLMOD) return grem(x,y); retmkpolmod(grem(x,y), RgX_copy(y)); } pari_err_TYPE2("%",x,y); return NULL; /* LCOV_EXCL_LINE */ } /*******************************************************************/ /* */ /* GENERIC EUCLIDEAN DIVISION */ /* */ /*******************************************************************/ GEN gdivent(GEN x, GEN y) { long tx, ty; tx = typ(x); if (tx == t_INT && !is_bigint(x)) return gdiventsg(itos(x),y); ty = typ(y); if (ty == t_INT && !is_bigint(y)) return gdiventgs(x,itos(y)); if (is_matvec_t(tx)) pari_APPLY_same(gdivent(gel(x,i), y)); if (tx == t_POL || ty == t_POL) return gdeuc(x,y); switch(ty) { case t_INT: switch(tx) { case t_INT: return truedivii(x,y); case t_REAL: return quotri(x,y); case t_FRAC: return quotfi(x,y); case t_QUAD: if (!is_realquad(x)) break; return quot(x,y); } break; case t_QUAD: if (!is_realext(x) || !is_realquad(y)) break; case t_REAL: case t_FRAC: return quot(x,y); } pari_err_TYPE2("\\",x,y); return NULL; /* LCOV_EXCL_LINE */ } GEN gdiventgs(GEN x, long y) { switch(typ(x)) { case t_INT: return truedivis(x,y); case t_REAL: return quotrs(x,y); case t_FRAC: return quotfs(x,y); case t_QUAD: if (!is_realquad(x)) break; return quotqs(x,y); case t_POL: return gdivgs(x,y); case t_VEC: case t_COL: case t_MAT: pari_APPLY_same(gdiventgs(gel(x,i),y)); } pari_err_TYPE2("\\",x,stoi(y)); return NULL; /* LCOV_EXCL_LINE */ } GEN gdiventsg(long x, GEN y) { switch(typ(y)) { case t_INT: return truedivsi(x,y); case t_REAL: return quotsr(x,y); case t_FRAC: return quotsf(x,y); case t_QUAD: if (!is_realquad(y)) break; return quotsq(x,y); case t_POL: if (!signe(y)) pari_err_INV("gdiventsg",y); return degpol(y)? Rg_get_0(y): gdivsg(x,gel(y,2)); } pari_err_TYPE2("\\",stoi(x),y); return NULL; /* LCOV_EXCL_LINE */ } /* with remainder */ static GEN quotrem(GEN x, GEN y, GEN *r) { GEN q = quot(x,y); pari_sp av = avma; *r = gerepileupto(av, gsub(x, gmul(q,y))); return q; } GEN gdiventres(GEN x, GEN y) { long tx = typ(x), ty = typ(y); GEN z; if (is_matvec_t(tx)) pari_APPLY_same(gdiventres(gel(x,i), y)); z = cgetg(3,t_COL); if (tx == t_POL || ty == t_POL) { gel(z,1) = poldivrem(x,y,(GEN*)(z+2)); return z; } switch(ty) { case t_INT: switch(tx) { /* equal to, but more efficient than next case */ case t_INT: gel(z,1) = truedvmdii(x,y,(GEN*)(z+2)); return z; case t_QUAD: if (!is_realquad(x)) break; case t_REAL: case t_FRAC: gel(z,1) = quotrem(x,y,&gel(z,2)); return z; } break; case t_QUAD: if (!is_realext(x) || !is_realquad(y)) break; case t_REAL: case t_FRAC: gel(z,1) = quotrem(x,y,&gel(z,2)); return z; } pari_err_TYPE2("\\",x,y); return NULL; /* LCOV_EXCL_LINE */ } GEN divrem(GEN x, GEN y, long v) { pari_sp av = avma; long vx, vy; GEN q, r; if (v < 0 || typ(y) != t_POL || typ(x) != t_POL) return gdiventres(x,y); vx = varn(x); if (vx != v) x = swap_vars(x,v); vy = varn(y); if (vy != v) y = swap_vars(y,v); q = RgX_divrem(x,y, &r); if (v && (vx != v || vy != v)) { GEN X = pol_x(v); q = gsubst(q, v, X); /* poleval broken for t_RFRAC, subst is safe */ r = gsubst(r, v, X); } return gerepilecopy(av, mkcol2(q, r)); } GEN diviiround(GEN x, GEN y) { pari_sp av1, av = avma; GEN q,r; int fl; q = dvmdii(x,y,&r); /* q = x/y rounded towards 0, sgn(r)=sgn(x) */ if (r==gen_0) return q; av1 = avma; fl = abscmpii(shifti(r,1),y); set_avma(av1); cgiv(r); if (fl >= 0) /* If 2*|r| >= |y| */ { long sz = signe(x)*signe(y); if (fl || sz > 0) q = gerepileuptoint(av, addis(q,sz)); } return q; } static GEN _abs(GEN x) { if (typ(x) == t_QUAD) return (gsigne(x) < 0)? gneg(x): x; return R_abs_shallow(x); } /* If x and y are not both scalars, same as gdivent. * Otherwise, compute the quotient x/y, rounded to the nearest integer * (towards +oo in case of tie). */ GEN gdivround(GEN x, GEN y) { pari_sp av; long tx = typ(x), ty = typ(y); GEN q, r; if (tx == t_INT && ty == t_INT) return diviiround(x,y); av = avma; if (is_realext(x) && is_realext(y)) { /* same as diviiround, less efficient */ pari_sp av1; int fl; q = quotrem(x,y,&r); av1 = avma; fl = gcmp(gmul2n(_abs(r),1), _abs(y)); set_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)) pari_APPLY_same(gdivround(gel(x,i),y)); return gdivent(x,y); } GEN gdivmod(GEN x, GEN y, GEN *pr) { switch(typ(x)) { case t_INT: switch(typ(y)) { case t_INT: return dvmdii(x,y,pr); case t_POL: *pr=icopy(x); return gen_0; } break; case t_POL: return poldivrem(x,y,pr); } pari_err_TYPE2("gdivmod",x,y); return NULL;/*LCOV_EXCL_LINE*/ } /*******************************************************************/ /* */ /* SHIFT */ /* */ /*******************************************************************/ /* Shift tronque si n<0 (multiplication tronquee par 2^n) */ GEN gshift(GEN x, long n) { switch(typ(x)) { case t_INT: return shifti(x,n); case t_REAL:return shiftr(x,n); case t_VEC: case t_COL: case t_MAT: pari_APPLY_same(gshift(gel(x,i),n)); } return gmul2n(x,n); } /*******************************************************************/ /* */ /* SUBSTITUTION DANS UN POLYNOME OU UNE SERIE */ /* */ /*******************************************************************/ /* Convert t_SER --> t_POL, ignoring valser. INTERNAL ! */ GEN ser2pol_i(GEN x, long lx) { long i = lx-1; GEN y; while (i > 1 && isrationalzero(gel(x,i))) i--; if (!signe(x)) { /* danger */ if (i == 1) return zeropol(varn(x)); y = cgetg(3,t_POL); y[1] = x[1] & ~VALSERBITS; gel(y,2) = gel(x,2); return y; } y = cgetg(i+1, t_POL); y[1] = x[1] & ~VALSERBITS; for ( ; i > 1; i--) gel(y,i) = gel(x,i); return y; } GEN ser2pol_i_normalize(GEN x, long l, long *v) { long i = 2, j = l-1, k; GEN y; while (i < l && gequal0(gel(x,i))) i++; *v = i - 2; if (i == l) return zeropol(varn(x)); while (j > i && gequal0(gel(x,j))) j--; l = j - *v + 1; y = cgetg(l, t_POL); y[1] = x[1] & ~VALSERBITS; k = l; while (k > 2) gel(y, --k) = gel(x,j--); return y; } GEN ser_inv(GEN b) { pari_sp av = avma; long e, l = lg(b); GEN x, y; y = ser2pol_i_normalize(b, l, &e); if (e) { pari_warn(warner,"normalizing a series with 0 leading term"); l -= e; if (l <= 2) pari_err_INV("inv_ser", b); } y = RgXn_inv_i(y, l-2); x = RgX_to_ser(y, l); setvalser(x, - valser(b) - e); return gerepilecopy(av, x); } /* T t_POL in var v, mod out by T components of x which are t_POL/t_RFRAC in v. * Recursively. Make sure that resulting polynomials of degree 0 in v are * simplified (map K[X]_0 to K) */ static GEN mod_r(GEN x, long v, GEN T) { long w, tx = typ(x); GEN y; if (is_const_t(tx)) return x; switch(tx) { case t_POLMOD: w = varn(gel(x,1)); if (w == v) pari_err_PRIORITY("subst", gel(x,1), "=", v); if (varncmp(v, w) < 0) return x; return gmodulo(mod_r(gel(x,2),v,T), mod_r(gel(x,1),v,T)); case t_SER: w = varn(x); if (w == v) break; /* fail */ if (varncmp(v, w) < 0 || ser_isexactzero(x)) return x; pari_APPLY_ser(mod_r(gel(x,i),v,T)); case t_POL: w = varn(x); if (w == v) { x = RgX_rem(x, T); if (!degpol(x)) x = gel(x,2); return x; } if (varncmp(v, w) < 0) return x; pari_APPLY_pol(mod_r(gel(x,i),v,T)); case t_RFRAC: x = gdiv(mod_r(gel(x,1),v,T), mod_r(gel(x,2),v,T)); if (typ(x) == t_POL && varn(x) == v && lg(x) == 3) x = gel(x,2); return x; case t_VEC: case t_COL: case t_MAT: pari_APPLY_same(mod_r(gel(x,i),v,T)); case t_LIST: y = mklist(); list_data(y) = list_data(x)? mod_r(list_data(x),v,T): NULL; return y; } pari_err_TYPE("substpol",x); return NULL;/*LCOV_EXCL_LINE*/ } GEN gsubstpol(GEN x, GEN T, GEN y) { pari_sp av = avma; long v; GEN z; if (typ(T) == t_POL && RgX_is_monomial(T) && gequal1(leading_coeff(T))) { /* T = t^d */ long d = degpol(T); v = varn(T); z = (d==1)? x: gdeflate(x, v, d); if (z) return gerepileupto(av, gsubst(z, v, y)); } v = fetch_var(); T = simplify_shallow(T); if (typ(T) == t_RFRAC) z = gsub(gel(T,1), gmul(pol_x(v), gel(T,2))); else z = gsub(T, pol_x(v)); z = mod_r(x, gvar(T), z); z = gsubst(z, v, y); (void)delete_var(); return gerepileupto(av, z); } long RgX_deflate_order(GEN x) { ulong d = 0, i, lx = (ulong)lg(x); for (i=3; i 0) return gcopy(x); av = avma; V = valser(x); lx = lg(x); if (lx == 2) return zeroser(v, V / d); y = ser2pol_i(x, lx); dy = degpol(y); if (V % d != 0 || (dy > 0 && RgX_deflate_order(y) % d != 0)) { const char *s = stack_sprintf("valuation(x) %% %ld", d); pari_err_DOMAIN("gdeflate", s, "!=", gen_0,x); } if (dy > 0) y = RgX_deflate(y, d); y = RgX_to_ser(y, 3 + (lx-3)/d); setvalser(y, V/d); return gerepilecopy(av, y); } static GEN poldeflate(GEN x, long v, long d) { long vx = varn(x); pari_sp av; if (varncmp(vx, v) < 0) return vdeflate(x,v,d); if (varncmp(vx, v) > 0 || degpol(x) <= 0) return gcopy(x); av = avma; /* x nonconstant */ if (RgX_deflate_order(x) % d != 0) return NULL; return gerepilecopy(av, RgX_deflate(x,d)); } static GEN listdeflate(GEN x, long v, long d) { GEN y = NULL, z = mklist(); if (list_data(x)) { y = vdeflate(list_data(x),v,d); if (!y) return NULL; } list_data(z) = y; return z; } /* return NULL if substitution fails */ GEN gdeflate(GEN x, long v, long d) { if (d <= 0) pari_err_DOMAIN("gdeflate", "degree", "<=", gen_0,stoi(d)); switch(typ(x)) { case t_INT: case t_REAL: case t_INTMOD: case t_FRAC: case t_FFELT: case t_COMPLEX: case t_PADIC: case t_QUAD: return gcopy(x); case t_POL: return poldeflate(x,v,d); case t_SER: return serdeflate(x,v,d); case t_POLMOD: if (varncmp(varn(gel(x,1)), v) >= 0) return gcopy(x); /* fall through */ case t_RFRAC: case t_VEC: case t_COL: case t_MAT: return vdeflate(x,v,d); case t_LIST: return listdeflate(x,v,d); } pari_err_TYPE("gdeflate",x); return NULL; /* LCOV_EXCL_LINE */ } /* set *m to the largest d such that x0 = A(X^d); return A */ GEN RgX_deflate_max(GEN x, long *m) { *m = RgX_deflate_order(x); return RgX_deflate(x, *m); } GEN ZX_deflate_max(GEN x, long *m) { *m = ZX_deflate_order(x); return RgX_deflate(x, *m); } static int serequalXk(GEN x) { long i, l = lg(x); if (l == 2 || !isint1(gel(x,2))) return 0; for (i = 3; i < l; i++) if (!isintzero(gel(x,i))) return 0; return 1; } static GEN gsubst_v(GEN e, long v, GEN x) { pari_APPLY_same(gsubst(e, v, gel(x,i))); } static GEN constmat(GEN z, long n) { GEN y = cgetg(n+1, t_MAT), c = const_col(n, gcopy(z)); long i; for (i = 1; i <= n; i++) gel(y, i) = c; return y; } static GEN scalarmat2(GEN o, GEN z, long n) { GEN y; long i; if (n == 0) return cgetg(1, t_MAT); if (n == 1) retmkmat(mkcol(gcopy(o))); y = cgetg(n+1, t_MAT); z = gcopy(z); o = gcopy(o); for (i = 1; i <= n; i++) { gel(y, i) = const_col(n, z); gcoeff(y,i,i) = o; } return y; } /* x * y^0, n = dim(y) if t_MAT, else -1 */ static GEN subst_higher(GEN x, GEN y, long n) { GEN o = Rg_get_1(y); if (o == gen_1) return n < 0? gcopy(x): scalarmat(x,n); x = gmul(x,o); return n < 0? x: scalarmat2(x, Rg_get_0(y), n); } /* x t_POLMOD, v strictly lower priority than var(x) */ static GEN subst_polmod(GEN x, long v, GEN y) { long l, i; GEN a = gsubst(gel(x,2),v,y), b = gsubst(gel(x,1),v,y), z; if (typ(b) != t_POL) pari_err_TYPE2("substitution",x,y); if (typ(a) != t_POL || varncmp(varn(a), varn(b)) >= 0) return gmodulo(a, b); l = lg(a); z = cgetg(l,t_POL); z[1] = a[1]; for (i = 2; i < l; i++) gel(z,i) = gmodulo(gel(a,i),b); return normalizepol_lg(z, l); } /* Trunc to n terms; x + O(t^(n + v(x))). FIXME: export ? */ static GEN sertrunc(GEN x, long n) { long i, l = n + 2; GEN y; if (l >= lg(x)) return x; if (n <= 0) return zeroser(varn(x), n + valser(x)); y = cgetg(l, t_SER); for (i = 2; i < l; i++) gel(y,i) = gel(x,i); y[1] = x[1]; return y; } /* FIXME: export ? */ static GEN sertrunc_copy(GEN x, long n) { long i, l = minss(n + 2, lg(x)); GEN y = cgetg(l, t_SER); for (i = 2; i < l; i++) gel(y,i) = gcopy(gel(x,i)); y[1] = x[1]; return y; } GEN gsubst(GEN x, long v, GEN y) { long tx = typ(x), ty = typ(y), lx = lg(x), ly = lg(y); long l, vx, vy, ex, ey, i, j, k, jb, matn; pari_sp av, av2; GEN X, t, z; switch(ty) { case t_VEC: case t_COL: return gsubst_v(x, v, y); case t_MAT: if (ly==1) return cgetg(1,t_MAT); if (ly == lgcols(y)) { matn = ly - 1; break; } /* fall through */ case t_QFB: pari_err_TYPE2("substitution",x,y); default: matn = -1; } if (is_scalar_t(tx)) { if (tx == t_POLMOD && varncmp(v, varn(gel(x,1))) > 0) { av = avma; return gerepileupto(av, subst_polmod(x, v, y)); } return subst_higher(x, y, matn); } switch(tx) { case t_POL: vx = varn(x); if (varncmp(vx, v) > 0) return subst_higher(x, y, matn); if (varncmp(vx, v) < 0) { av = avma; z = cgetg(lx, t_POL); z[1] = x[1]; if (lx == 2) return z; for (i = 2; i < lx; i++) gel(z,i) = gsubst(gel(x,i),v,y); z = normalizepol_lg(z, lx); lx = lg(z); if (lx == 2) { set_avma(av); return zeropol(vx); } if (lx == 3) return gerepileupto(av, gmul(pol_1(vx), gel(z,2))); return gerepileupto(av, poleval(z, pol_x(vx))); } /* v = vx */ if (lx == 2) { GEN z = Rg_get_0(y); return matn >= 0? constmat(z, matn): z; } if (lx == 3) { x = subst_higher(gel(x,2), y, matn); if (matn >= 0) return x; vy = gvar(y); return (vy == NO_VARIABLE)? x: gmul(x, pol_1(vy)); } return matn >= 0? RgX_RgM_eval(x, y): poleval(x,y); case t_SER: vx = varn(x); if (varncmp(vx, v) > 0) return subst_higher(x, y, matn); ex = valser(x); if (varncmp(vx, v) < 0) { if (lx == 2) return matn >= 0? scalarmat(x, matn): gcopy(x); av = avma; X = pol_x(vx); av2 = avma; z = gadd(gsubst(gel(x,lx-1),v,y), zeroser(vx,1)); for (i = lx-2; i>=2; i--) { z = gadd(gmul(z,X), gsubst(gel(x,i),v,y)); if (gc_needed(av2,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"gsubst (i = %ld)", i); z = gerepileupto(av2, z); } } if (ex) z = gmul(z, pol_xnall(ex,vx)); return gerepileupto(av, z); } switch(ty) /* here vx == v */ { case t_SER: vy = varn(y); ey = valser(y); if (ey < 1 || lx == 2) return zeroser(vy, ey*(ex+lx-2)); if (ey == 1 && serequalXk(y) && (varncmp(vx,vy) >= 0 || varncmp(gvar2(x), vy) >= 0)) { /* y = t + O(t^N) */ if (lx > ly) { /* correct number of significant terms */ l = ly; if (!ex) for (i = 3; i < lx; i++) if (++l >= lx || !gequal0(gel(x,i))) break; lx = l; } z = sertrunc_copy(x, lx - 2); if (vx != vy) setvarn(z,vy); return z; } if (vy != vx) { long nx = lx - 2, n = minss(ey * nx, ly - 2); av = avma; z = gel(x, nx+1); for (i = nx; i > 1; i--) { z = gadd(gmul(y,z), gel(x,i)); if (gc_needed(av,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"gsubst (i = %ld)", i); z = gerepileupto(av, z); } } if (ex) { if (ex < 0) { y = ginv(y); ex = -ex; } z = gmul(z, gpowgs(sertrunc(y, n), ex)); } if (lg(z)-2 > n) z = sertrunc_copy(z, n); return gerepileupto(av,z); } l = (lx-2)*ey + 2; if (ex) { if (l>ly) l = ly; } else if (lx != 3) { for (i = 3; i < lx; i++) if (!isexactzero(gel(x,i))) break; l = minss(l, (i-2)*ey + (gequal0(y)? 2 : ly)); } av = avma; t = leafcopy(y); if (l < ly) setlg(t, l); z = scalarser(gen_1, varn(y), l-2); gel(z,2) = gel(x,2); /* ensure lg(z) = l even if x[2] = 0 */ for (i = 3, jb = ey; jb <= l-2; i++,jb += ey) { if (i < lx) { for (j = jb+2; j < minss(l, jb+ly); j++) gel(z,j) = gadd(gel(z,j), gmul(gel(x,i),gel(t,j-jb))); } for (j = minss(ly-1, l-1-jb-ey); j > 1; j--) { GEN a = gmul(gel(t,2), gel(y,j)); for (k=2; k1) pari_warn(warnmem,"gsubst"); gerepileall(av,2, &z,&t); } } if (!ex) return gerepilecopy(av,z); if (ex < 0) { ex = -ex; y = ginv(y); } return gerepileupto(av, gmul(z, gpowgs(sertrunc(y, l-2), ex))); case t_POL: case t_RFRAC: { long N, n = lx-2; vy = gvar(y); ey = gval(y,vy); if (ey == LONG_MAX) { /* y = 0 */ if (ex < 0) pari_err_INV("gsubst",y); if (!n) return gcopy(x); if (ex > 0) return Rg_get_0(ty == t_RFRAC? gel(y,2): y); y = Rg_get_1(ty == t_RFRAC? gel(y,2): y); return gmul(y, gel(x,2)); } if (ey < 1 || n == 0) return zeroser(vy, ey*(ex+n)); av = avma; n *= ey; N = ex? n: maxss(n-ey,1); y = (ty == t_RFRAC)? rfrac_to_ser_i(y, N+2): RgX_to_ser(y, N+2); if (lg(y)-2 > n) setlg(y, n+2); x = ser2pol_i(x, lx); if (varncmp(vy,vx) > 0) z = gadd(poleval(x, y), zeroser(vy,n)); else { z = RgXn_eval(x, ser2rfrac_i(y), n); if (varn(z) == vy) z = RgX_to_ser(z, n+2); else z = scalarser(z, vy, n); } if (!ex) return gerepilecopy(av, z); return gerepileupto(av, gmul(z, gpowgs(y,ex))); } default: if (isexactzero(y)) { if (ex < 0) pari_err_INV("gsubst",y); if (ex > 0) return gcopy(y); if (lx > 2) return gadd(gel(x,2), y); /*add maps to correct ring*/ } pari_err_TYPE2("substitution",x,y); } break; case t_RFRAC: { GEN a = gel(x,1), b = gel(x,2); av = avma; a = gsubst(a, v, y); b = gsubst(b, v, y); return gerepileupto(av, gdiv(a, b)); } case t_VEC: case t_COL: case t_MAT: pari_APPLY_same(gsubst(gel(x,i),v,y)); case t_LIST: z = mklist(); list_data(z) = list_data(x)? gsubst(list_data(x),v,y): NULL; return z; } return gcopy(x); } /* Return P(x * h), not memory clean */ GEN ser_unscale(GEN P, GEN h) { long l = lg(P); GEN Q = cgetg(l,t_SER); Q[1] = P[1]; if (l != 2) { long i = 2; GEN hi = gpowgs(h, valser(P)); gel(Q,i) = gmul(gel(P,i), hi); for (i++; i 1? gerepilecopy(av, e): gerepileupto(av, e); } /*******************************************************************/ /* */ /* SERIE RECIPROQUE D'UNE SERIE */ /* */ /*******************************************************************/ GEN serreverse(GEN x) { long v=varn(x), lx = lg(x), i, mi; pari_sp av0 = avma, av; GEN a, y, u; if (typ(x)!=t_SER) pari_err_TYPE("serreverse",x); if (valser(x)!=1) pari_err_DOMAIN("serreverse", "valuation", "!=", gen_1,x); if (lx < 3) pari_err_DOMAIN("serreverse", "x", "=", gen_0,x); y = ser_normalize(x); if (y == x) a = NULL; else { a = gel(x,2); x = y; } av = avma; mi = lx-1; while (mi>=3 && gequal0(gel(x,mi))) mi--; u = cgetg(lx,t_SER); y = cgetg(lx,t_SER); u[1] = y[1] = evalsigne(1) | _evalvalser(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,"serreverse"); for(k=i+1; k 0 */ static GEN derivnser(GEN x, long n) { long i, vx = varn(x), e = valser(x), lx = lg(x); GEN y; if (ser_isexactzero(x)) { x = gcopy(x); if (e) setvalser(x,e-n); return x; } if (e < 0 || e >= n) { y = cgetg(lx,t_SER); y[1] = evalsigne(1)| evalvalser(e-n) | evalvarn(vx); for (i=0; i 0 */ static GEN RgX_derivn(GEN x, long n) { long i, vx = varn(x), lx = lg(x); GEN y; if (lx <= n+2) return pol_0(vx); lx -= n; y = cgetg(lx,t_POL); y[1] = evalsigne(1)| evalvarn(vx); for (i=0; i=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; if (ser_isexactzero(x)) y = x; else { y = cgetg_copy(x, &lx); y[1] = x[1]; for (i=2; i 0) y = gerepileuptoint(av, addui(1,y)); return y; case t_QUAD: if (!is_realquad(x)) break; if (gequal0(gel(x,3))) return gceil(gel(x,2)); av = avma; return gerepileupto(av, addiu(gfloor(x), 1)); case t_RFRAC: return gdeuc(gel(x,1),gel(x,2)); case t_VEC: case t_COL: case t_MAT: pari_APPLY_same(gceil(gel(x,i))); } pari_err_TYPE("gceil",x); return NULL; /* LCOV_EXCL_LINE */ } GEN round0(GEN x, GEN *pte) { if (pte) { long e; x = grndtoi(x,&e); *pte = stoi(e); } return ground(x); } /* x t_REAL, return q=floor(x+1/2), set e = expo(x-q) */ static GEN round_i(GEN x, long *pe) { long e; GEN B, q,r, m = mantissa_real(x, &e); /* x = m/2^e */ if (e <= 0) { if (e) m = shifti(m,-e); if (pe) *pe = -e; return m; } B = int2n(e-1); m = addii(m, B); q = shifti(m, -e); r = remi2n(m, e); /* 2^e (x+1/2) = m = 2^e q + r, sgn(r)=sgn(m), |r|<2^e */ if (!signe(r)) { if (pe) *pe = -1; } else { if (signe(m) < 0) { q = subiu(q,1); r = addii(r, B); } else r = subii(r, B); /* |x - q| = |r| / 2^e */ if (pe) *pe = signe(r)? expi(r) - e: -e; cgiv(r); } return q; } /* assume x a t_REAL */ GEN roundr(GEN x) { long ex, s = signe(x); pari_sp av; 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; x = round_i(x, &ex); if (ex >= 0) pari_err_PREC( "roundr (precision loss in truncation)"); return gerepileuptoint(av, x); } GEN roundr_safe(GEN x) { long ex, s = signe(x); pari_sp av; 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; x = round_i(x, NULL); return gerepileuptoint(av, x); } GEN ground(GEN x) { pari_sp av; GEN y; switch(typ(x)) { case t_INT: return icopy(x); case t_INTMOD: return gcopy(x); case t_REAL: return roundr(x); case t_FRAC: return diviiround(gel(x,1), gel(x,2)); case t_QUAD: { GEN Q = gel(x,1), u, v, b, d, z; av = avma; if (is_realquad(x)) return gerepileupto(av, gfloor(gadd(x, ghalf))); u = gel(x,2); v = gel(x,3); b = gel(Q,3); u = ground(gsub(u, gmul2n(gmul(v,b),-1))); v = Q_remove_denom(v, &d); if (!d) d = gen_1; /* Im x = v sqrt(|D|) / (2d), * Im(round(x)) = floor((d + v sqrt(|D|)) / (2d)) * = floor(floor(d + v sqrt(|D|)) / (2d)) */ z = sqrti(mulii(sqri(v), quad_disc(x))); if (signe(v) < 0) { z = addiu(z,1); togglesign(z); } /* z = floor(v * sqrt(|D|)) */ v = truedivii(addii(z, d), shifti(d,1)); return gerepilecopy(av, signe(v)? mkcomplex(u,v): u); } case t_POLMOD: retmkpolmod(ground(gel(x,2)), RgX_copy(gel(x,1))); case t_COMPLEX: av = avma; y = cgetg(3, t_COMPLEX); gel(y,2) = ground(gel(x,2)); if (!signe(gel(y,2))) { set_avma(av); return ground(gel(x,1)); } gel(y,1) = ground(gel(x,1)); return y; case t_POL: pari_APPLY_pol(ground(gel(x,i))); case t_SER: if (ser_isexactzero(x)) return gcopy(x); pari_APPLY_ser(ground(gel(x,i))); case t_RFRAC: av = avma; return gerepileupto(av, gdiv(ground(gel(x,1)), ground(gel(x,2)))); case t_VEC: case t_COL: case t_MAT: pari_APPLY_same(ground(gel(x,i))); } pari_err_TYPE("ground",x); return NULL; /* LCOV_EXCL_LINE */ } /* e = number of error bits on integral part */ GEN grndtoi(GEN x, long *e) { GEN y; long i, lx, e1; pari_sp av; if (e) *e = -(long)HIGHEXPOBIT; switch(typ(x)) { case t_INT: return icopy(x); case t_REAL: { long ex = expo(x); if (!signe(x) || ex < -1) { if (e) *e = ex; return gen_0; } av = avma; x = round_i(x, e); return gerepileuptoint(av, x); } case t_FRAC: y = diviiround(gel(x,1), gel(x,2)); if (!e) return y; av = avma; *e = gexpo(gsub(x, y)); set_avma(av); return y; case t_INTMOD: return gcopy(x); case t_QUAD: y = ground(x); av = avma; if (!e) return y; *e = gexpo(gsub(x,y)); set_avma(avma); return y; case t_COMPLEX: av = avma; y = cgetg(3, t_COMPLEX); gel(y,2) = grndtoi(gel(x,2), e); if (!signe(gel(y,2))) { set_avma(av); y = grndtoi(gel(x,1), e? &e1: NULL); } else gel(y,1) = grndtoi(gel(x,1), e? &e1: NULL); if (e && e1 > *e) *e = e1; return y; case t_POLMOD: retmkpolmod(grndtoi(gel(x,2), e), RgX_copy(gel(x,1))); 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: if (ser_isexactzero(x)) return gcopy(x); y = cgetg_copy(x, &lx); y[1] = x[1]; for (i=2; i *e) *e = e1; } return normalizeser(y); case t_RFRAC: y = cgetg(3,t_RFRAC); gel(y,1) = grndtoi(gel(x,1), e? &e1: NULL); if (e && e1 > *e) *e = e1; gel(y,2) = grndtoi(gel(x,2), e? &e1: NULL); if (e && e1 > *e) *e = e1; return y; case t_VEC: case t_COL: case t_MAT: y = cgetg_copy(x, &lx); for (i=1; i *e) *e = e1; } return y; } pari_err_TYPE("grndtoi",x); return NULL; /* LCOV_EXCL_LINE */ } /* 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))) { set_avma((pari_sp)(z + 3)); return gtrunc2n(gel(x,1), s); } gel(z,1) = gtrunc2n(gel(x,1), s); return z; default: pari_err_TYPE("gtrunc2n",x); return NULL; /* LCOV_EXCL_LINE */ } } /* e = number of error bits on integral part */ GEN gcvtoi(GEN x, long *e) { long tx = typ(x), lx, e1; GEN y; if (tx == t_REAL) { long ex = expo(x); if (ex < 0) { *e = ex; return gen_0; } e1 = ex - bit_prec(x) + 1; y = mantissa2nr(x, e1); if (e1 <= 0) { pari_sp av = avma; e1 = expo(subri(x,y)); set_avma(av); } *e = e1; return y; } *e = -(long)HIGHEXPOBIT; if (is_matvec_t(tx)) { long i; y = cgetg_copy(x, &lx); for (i=1; i *e) *e = e1; } return y; } return gtrunc(x); } int isint(GEN n, GEN *ptk) { switch(typ(n)) { case t_INT: *ptk = n; return 1; case t_REAL: { pari_sp av0 = avma; GEN z = floorr(n); pari_sp av = avma; long s = signe(subri(n, z)); if (s) return gc_bool(av0,0); *ptk = z; return gc_bool(av,1); } case t_FRAC: return 0; case t_COMPLEX: return gequal0(gel(n,2)) && isint(gel(n,1),ptk); case t_QUAD: return gequal0(gel(n,3)) && isint(gel(n,2),ptk); default: pari_err_TYPE("isint",n); return 0; /* LCOV_EXCL_LINE */ } } 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); set_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 = valser(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, pol_xn(-e, varn(a))); } return a; } static GEN ser2rfrac(GEN x) { pari_sp av = avma; return gerepilecopy(av, ser2rfrac_i(x)); } /* x t_PADIC, truncate to rational (t_INT/t_FRAC) */ GEN padic_to_Q(GEN x) { GEN u = gel(x,4), p; long v; if (!signe(u)) return gen_0; v = valp(x); if (!v) return icopy(u); p = gel(x,2); if (v>0) { pari_sp av = avma; return gerepileuptoint(av, mulii(u, powiu(p,v))); } retmkfrac(icopy(u), powiu(p,-v)); } GEN padic_to_Q_shallow(GEN x) { GEN u = gel(x,4), p, q, q2; long v; if (!signe(u)) return gen_0; q = gel(x,3); q2 = shifti(q,-1); v = valp(x); u = Fp_center_i(u, q, q2); if (!v) return u; p = gel(x,2); if (v>0) return mulii(powiu(p,v), u); return mkfrac(u, powiu(p,-v)); } GEN QpV_to_QV(GEN v) { long i, l; GEN w = cgetg_copy(v, &l); for (i = 1; i < l; i++) { GEN c = gel(v,i); switch(typ(c)) { case t_INT: case t_FRAC: break; case t_PADIC: c = padic_to_Q_shallow(c); break; default: pari_err_TYPE("padic_to_Q", v); } gel(w,i) = c; } return w; } GEN gtrunc(GEN x) { switch(typ(x)) { case t_INT: return icopy(x); case t_REAL: return truncr(x); case t_FRAC: return divii(gel(x,1),gel(x,2)); case t_PADIC: return padic_to_Q(x); case t_POL: return RgX_copy(x); case t_RFRAC: return gdeuc(gel(x,1),gel(x,2)); case t_SER: return ser2rfrac(x); case t_VEC: case t_COL: case t_MAT: pari_APPLY_same(gtrunc(gel(x,i))); } pari_err_TYPE("gtrunc",x); return NULL; /* LCOV_EXCL_LINE */ } GEN trunc0(GEN x, GEN *pte) { if (pte) { long e; x = gcvtoi(x,&e); *pte = stoi(e); } return gtrunc(x); } /*******************************************************************/ /* */ /* CONVERSIONS --> INT, POL & SER */ /* */ /*******************************************************************/ /* return a_(n-1) B^(n-1) + ... + a_0, where B = 2^32. * The a_i are 32bits integers */ GEN mkintn(long n, ...) { va_list ap; GEN x, y; long i; #ifdef LONG_IS_64BIT long e = (n&1); n = (n+1) >> 1; #endif va_start(ap,n); x = cgetipos(n+2); y = int_MSW(x); for (i=0; i = 0; i--) gel(y,i) = va_arg(ap, GEN); va_end(ap); return normalizepol_lg(x, l); } /* return [a_1, ..., a_n] */ GEN mkvecn(long n, ...) { va_list ap; GEN x; long i; va_start(ap,n); x = cgetg(n+1, t_VEC); for (i=1; i <= n; i++) gel(x,i) = va_arg(ap, GEN); va_end(ap); return x; } GEN mkcoln(long n, ...) { va_list ap; GEN x; long i; va_start(ap,n); x = cgetg(n+1, t_COL); for (i=1; i <= n; i++) gel(x,i) = va_arg(ap, GEN); va_end(ap); return x; } GEN mkvecsmalln(long n, ...) { va_list ap; GEN x; long i; va_start(ap,n); x = cgetg(n+1, t_VECSMALL); for (i=1; i <= n; i++) x[i] = va_arg(ap, long); va_end(ap); return x; } GEN scalarpol(GEN x, long v) { GEN y; if (isrationalzero(x)) return zeropol(v); y = cgetg(3,t_POL); y[1] = gequal0(x)? evalvarn(v) : evalvarn(v) | evalsigne(1); gel(y,2) = gcopy(x); return y; } GEN scalarpol_shallow(GEN x, long v) { GEN y; if (isrationalzero(x)) return zeropol(v); y = cgetg(3,t_POL); y[1] = gequal0(x)? evalvarn(v) : evalvarn(v) | evalsigne(1); gel(y,2) = x; return y; } /* x0 + x1*T, do not assume x1 != 0 */ GEN deg1pol(GEN x1, GEN x0,long v) { GEN x = cgetg(4,t_POL); x[1] = evalsigne(1) | evalvarn(v); gel(x,2) = x0 == gen_0? x0: gcopy(x0); /* gen_0 frequent */ gel(x,3) = gcopy(x1); return normalizepol_lg(x,4); } /* same, no copy */ GEN deg1pol_shallow(GEN x1, GEN x0,long v) { GEN x = cgetg(4,t_POL); x[1] = evalsigne(1) | evalvarn(v); gel(x,2) = x0; gel(x,3) = x1; return normalizepol_lg(x,4); } GEN deg2pol_shallow(GEN x2, GEN x1, GEN x0, long v) { GEN x = cgetg(5,t_POL); x[1] = evalsigne(1) | evalvarn(v); gel(x,2) = x0; gel(x,3) = x1; gel(x,4) = x2; return normalizepol_lg(x,5); } static GEN _gtopoly(GEN x, long v, int reverse) { long tx = typ(x); GEN y; if (v<0) v = 0; switch(tx) { case t_POL: if (varncmp(varn(x), v) < 0) pari_err_PRIORITY("gtopoly", x, "<", v); y = RgX_copy(x); break; case t_SER: if (varncmp(varn(x), v) < 0) pari_err_PRIORITY("gtopoly", x, "<", v); y = ser2rfrac(x); if (typ(y) != t_POL) pari_err_DOMAIN("gtopoly", "valuation", "<", gen_0, x); break; case t_RFRAC: { GEN a = gel(x,1), b = gel(x,2); long vb = varn(b); if (varncmp(vb, v) < 0) pari_err_PRIORITY("gtopoly", x, "<", v); if (typ(a) != t_POL || varn(a) != vb) return zeropol(v); y = RgX_div(a,b); break; } case t_VECSMALL: x = zv_to_ZV(x); /* fall through */ case t_QFB: case t_VEC: case t_COL: case t_MAT: { long j, k, lx = lg(x); GEN z; if (tx == t_QFB) lx--; if (varncmp(gvar(x), v) <= 0) pari_err_PRIORITY("gtopoly", x, "<=", v); y = cgetg(lx+1, t_POL); y[1] = evalvarn(v); if (reverse) { x--; for (j=2; j<=lx; j++) gel(y,j) = gel(x,j); } else { for (j=2, k=lx; k>=2; j++) gel(y,j) = gel(x,--k); } z = RgX_copy(normalizepol_lg(y,lx+1)); settyp(y, t_VECSMALL);/* left on stack */ return z; } default: if (is_scalar_t(tx)) return scalarpol(x,v); pari_err_TYPE("gtopoly",x); return NULL; /* LCOV_EXCL_LINE */ } setvarn(y,v); return y; } GEN gtopolyrev(GEN x, long v) { return _gtopoly(x,v,1); } GEN gtopoly(GEN x, long v) { return _gtopoly(x,v,0); } static GEN gtovecpost(GEN x, long n) { long i, imax, lx, tx = typ(x); GEN y = zerovec(n); if (is_scalar_t(tx) || tx == t_RFRAC) { gel(y,1) = gcopy(x); return y; } switch(tx) { case t_POL: lx = lg(x); imax = minss(lx-2, n); for (i=1; i<=imax; i++) gel(y,i) = gcopy(gel(x,lx-i)); return y; case t_SER: lx = lg(x); imax = minss(lx-2, n); x++; for (i=1; i<=imax; i++) gel(y,i) = gcopy(gel(x,i)); return y; case t_QFB: lx = lg(x)-1; /* remove discriminant */ imax = minss(lx-1, n); for (i=1; i<=imax; i++) gel(y,i) = gcopy(gel(x,i)); return y; case t_VEC: case t_COL: lx = lg(x); imax = minss(lx-1, n); for (i=1; i<=imax; i++) gel(y,i) = gcopy(gel(x,i)); return y; case t_LIST: if (list_typ(x) == t_LIST_MAP) pari_err_TYPE("gtovec",x); x = list_data(x); lx = x? lg(x): 1; imax = minss(lx-1, n); for (i=1; i<=imax; i++) gel(y,i) = gcopy(gel(x,i)); return y; case t_STR: { char *s = GSTR(x); imax = minss(strlen(s), n); s--; for (i=1; i<=imax; i++) gel(y,i) = chartoGENstr(s[i]); return y; } case t_VECSMALL: lx = lg(x); imax = minss(lx-1, n); for (i=1; i<=imax; i++) gel(y,i) = stoi(x[i]); return y; default: pari_err_TYPE("gtovec",x); return NULL; /*LCOV_EXCL_LINE*/ } } static GEN init_vectopre(long a, long n, GEN y, long *imax) { if (n <= a) { *imax = n; return y; } *imax = a; return y + n - a; } /* assume n > 0 */ static GEN gtovecpre(GEN x, long n) { long a, i, imax, lx, tx = typ(x); GEN y = zerovec(n), y0; if (is_scalar_t(tx) || tx == t_RFRAC) { gel(y,n) = gcopy(x); return y; } switch(tx) { case t_POL: lx = lg(x); a = lx-2; y0 = init_vectopre(a, n, y, &imax); if (imax == n) x -= a-imax; for (i=1; i<=imax; i++) gel(y0,i) = gcopy(gel(x,lx-i)); return y; case t_SER: a = lg(x)-2; x++; y0 = init_vectopre(a, n, y, &imax); if (imax == n) x += a-imax; for (i=1; i<=imax; i++) gel(y0,i) = gcopy(gel(x,i)); return y; case t_QFB: a = lg(x)-2; /* remove discriminant */ y0 = init_vectopre(a, n, y, &imax); if (imax == n) x += a-imax; for (i=1; i<=imax; i++) gel(y0,i) = gcopy(gel(x,i)); return y; case t_VEC: case t_COL: a = lg(x)-1; y0 = init_vectopre(a, n, y, &imax); if (imax == n) x += a-imax; for (i=1; i<=imax; i++) gel(y0,i) = gcopy(gel(x,i)); return y; case t_LIST: if (list_typ(x) == t_LIST_MAP) pari_err_TYPE("gtovec",x); x = list_data(x); a = x? lg(x)-1: 0; y0 = init_vectopre(a, n, y, &imax); if (imax == n) x += a-imax; for (i=1; i<=imax; i++) gel(y0,i) = gcopy(gel(x,i)); return y; case t_STR: { char *s = GSTR(x); a = strlen(s); y0 = init_vectopre(a, n, y, &imax); s--; if (imax == n) s += a-imax; for (i=1; i<=imax; i++) gel(y,i) = chartoGENstr(s[i]); return y; } case t_VECSMALL: a = lg(x)-1; y0 = init_vectopre(a, n, y, &imax); if (imax == n) x += a-imax; for (i=1; i<=imax; i++) gel(y0,i) = stoi(x[i]); return y; default: pari_err_TYPE("gtovec",x); return NULL; /*LCOV_EXCL_LINE*/ } } GEN gtovec0(GEN x, long n) { if (!n) return gtovec(x); if (n > 0) return gtovecpost(x, n); return gtovecpre(x, -n); } GEN gtovec(GEN x) { long i, lx, tx = typ(x); GEN y; if (is_scalar_t(tx)) return mkveccopy(x); switch(tx) { case t_POL: lx=lg(x); y=cgetg(lx-1,t_VEC); for (i=1; i<=lx-2; i++) gel(y,i) = gcopy(gel(x,lx-i)); return y; case t_SER: lx=lg(x); y=cgetg(lx-1,t_VEC); x++; for (i=1; i<=lx-2; i++) gel(y,i) = gcopy(gel(x,i)); return y; case t_RFRAC: return mkveccopy(x); case t_QFB: retmkvec3(icopy(gel(x,1)), icopy(gel(x,2)), icopy(gel(x,3))); case t_VEC: case t_COL: case t_MAT: lx=lg(x); y=cgetg(lx,t_VEC); for (i=1; i>1, i; for (i = 1; i <= lim; i++) swap(gel(y,i), gel(y,ly-i)); return y; } GEN gtocolrev(GEN x) { return gtocolrev0(x, 0); } static long Itos(GEN x) { if (typ(x) != t_INT) pari_err_TYPE("vectosmall",x); return itos(x); } static GEN gtovecsmallpost(GEN x, long n) { long i, imax, lx; GEN y = zero_Flv(n); switch(typ(x)) { case t_INT: y[1] = itos(x); return y; case t_POL: lx=lg(x); imax = minss(lx-2, n); for (i=1; i<=imax; i++) y[i] = Itos(gel(x,lx-i)); return y; case t_SER: lx=lg(x); imax = minss(lx-2, n); x++; for (i=1; i<=imax; i++) y[i] = Itos(gel(x,i)); return y; case t_VEC: case t_COL: lx=lg(x); imax = minss(lx-1, n); for (i=1; i<=imax; i++) y[i] = Itos(gel(x,i)); return y; case t_LIST: x = list_data(x); lx = x? lg(x): 1; imax = minss(lx-1, n); for (i=1; i<=imax; i++) y[i] = Itos(gel(x,i)); return y; case t_VECSMALL: lx=lg(x); imax = minss(lx-1, n); for (i=1; i<=imax; i++) y[i] = x[i]; return y; case t_STR: { unsigned char *s = (unsigned char*)GSTR(x); imax = minss(strlen((const char *)s), n); s--; for (i=1; i<=imax; i++) y[i] = (long)s[i]; return y; } default: pari_err_TYPE("gtovecsmall",x); return NULL; /*LCOV_EXCL_LINE*/ } } static GEN gtovecsmallpre(GEN x, long n) { GEN y = zero_Flv(n), y0; long a, i, imax, lx; switch(typ(x)) { case t_INT: y[n] = itos(x); return y; case t_POL: lx = lg(x); a = lx-2; y0 = init_vectopre(a, n, y, &imax); if (imax == n) x -= a-imax; for (i=1; i<=imax; i++) y0[i] = Itos(gel(x,lx-i)); return y; case t_SER: a = lg(x)-2; x++; y0 = init_vectopre(a, n, y, &imax); if (imax == n) x += a-imax; for (i=1; i<=imax; i++) y0[i] = Itos(gel(x,i)); return y; case t_VEC: case t_COL: a = lg(x)-1; y0 = init_vectopre(a, n, y, &imax); if (imax == n) x += a-imax; for (i=1; i<=imax; i++) y0[i] = Itos(gel(x,i)); return y; case t_LIST: x = list_data(x); a = x? lg(x)-1: 0; y0 = init_vectopre(a, n, y, &imax); if (imax == n) x += a-imax; for (i=1; i<=imax; i++) y0[i] = Itos(gel(x,i)); return y; case t_VECSMALL: a = lg(x)-1; y0 = init_vectopre(a, n, y, &imax); if (imax == n) x += a-imax; for (i=1; i<=imax; i++) y0[i] = x[i]; return y; case t_STR: { unsigned char *s = (unsigned char*)GSTR(x); a = strlen((const char *)s); y0 = init_vectopre(a, n, y, &imax); s--; if (imax == n) s += a-imax; for (i=1; i<=imax; i++) y0[i] = (long)s[i]; return y; } default: pari_err_TYPE("gtovecsmall",x); return NULL; /*LCOV_EXCL_LINE*/ } } GEN gtovecsmall0(GEN x, long n) { if (!n) return gtovecsmall(x); if (n > 0) return gtovecsmallpost(x, n); return gtovecsmallpre(x, -n); } GEN gtovecsmall(GEN x) { GEN V; long l, i; switch(typ(x)) { case t_INT: return mkvecsmall(itos(x)); case t_STR: { unsigned char *s = (unsigned char*)GSTR(x); l = strlen((const char *)s); V = cgetg(l+1, t_VECSMALL); s--; for (i=1; i<=l; i++) V[i] = (long)s[i]; return V; } case t_VECSMALL: return leafcopy(x); case t_LIST: x = list_data(x); if (!x) return cgetg(1, t_VECSMALL); /* fall through */ case t_VEC: case t_COL: l = lg(x); V = cgetg(l,t_VECSMALL); for(i=1; i= lx) pari_err_COMPONENT("", ">", utoi(lx-1), stoi(n)); return stoi(x[n]); } pari_err_TYPE("component [leaf]", x); } if (n < 1) pari_err_COMPONENT("", "<", gen_1, stoi(n)); if (tx == t_LIST) { x = list_data(x); tx = t_VEC; lx = (ulong)(x? lg(x): 1); } l = (ulong)lontyp[tx] + (ulong)n-1; /* beware overflow */ if (l >= lx) pari_err_COMPONENT("", ">", utoi(lx-lontyp[tx]), stoi(n)); return gcopy(gel(x,l)); } /* assume x a t_POL */ static GEN _polcoef(GEN x, long n, long v) { long i, w, lx = lg(x), dx = lx-3; GEN z; if (dx < 0) return gen_0; if (v < 0 || v == (w=varn(x))) return (n < 0 || n > dx)? gen_0: gel(x,n+2); if (varncmp(w,v) > 0) return n? gen_0: x; /* w < v */ z = cgetg(lx, t_POL); z[1] = x[1]; for (i = 2; i < lx; i++) gel(z,i) = polcoef_i(gel(x,i), n, v); z = normalizepol_lg(z, lx); switch(lg(z)) { case 2: z = gen_0; break; case 3: z = gel(z,2); break; } return z; } /* assume x a t_SER */ static GEN _sercoef(GEN x, long n, long v) { long i, w = varn(x), lx = lg(x), dx = lx-3, N; GEN z; if (v < 0) v = w; N = v == w? n - valser(x): n; if (dx < 0) { if (N >= 0) pari_err_DOMAIN("polcoef", "t_SER", "=", x, x); return gen_0; } if (v == w) { if (!dx && !signe(x) && !isinexact(gel(x,2))) dx = -1; if (N > dx) pari_err_DOMAIN("polcoef", "degree", ">", stoi(dx+valser(x)), stoi(n)); return (N < 0)? gen_0: gel(x,N+2); } if (varncmp(w,v) > 0) return N? gen_0: x; /* w < v */ z = cgetg(lx, t_SER); z[1] = x[1]; for (i = 2; i < lx; i++) gel(z,i) = polcoef_i(gel(x,i), n, v); return normalizeser(z); } /* assume x a t_RFRAC(n) */ static GEN _rfraccoef(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 = varncmp(vp, vq) < 0? vp: vq; P = (vp == v)? p: swap_vars(p, v); Q = (vq == v)? q: swap_vars(q, v); if (!RgX_is_monomial(Q)) pari_err_TYPE("polcoef", x); n += degpol(Q); return gdiv(_polcoef(P, n, v), leading_coeff(Q)); } GEN polcoef_i(GEN x, long n, long v) { long tx = typ(x); switch(tx) { case t_POL: return _polcoef(x,n,v); case t_SER: return _sercoef(x,n,v); case t_RFRAC: return _rfraccoef(x,n,v); } if (!is_scalar_t(tx)) pari_err_TYPE("polcoef", x); 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 polcoef(GEN x, long n, long v) { pari_sp av = avma; x = polcoef_i(x,n,v); if (x == gen_0) return x; return (avma == av)? gcopy(x): gerepilecopy(av, x); } static GEN vecdenom(GEN v, long imin, long imax) { long i = imin; GEN s; if (imin > imax) return gen_1; s = denom_i(gel(v,i)); for (i++; i<=imax; i++) { GEN t = denom_i(gel(v,i)); if (t != gen_1) s = glcm(s,t); } return s; } static GEN denompol(GEN x, long v); static GEN vecdenompol(GEN v, long imin, long imax, long vx) { long i = imin; GEN s; if (imin > imax) return gen_1; s = denompol(gel(v,i), vx); for (i++; i<=imax; i++) { GEN t = denompol(gel(v,i), vx); if (t != gen_1) s = glcm(s,t); } return s; } GEN denom_i(GEN x) { switch(typ(x)) { case t_INT: case t_REAL: case t_INTMOD: case t_FFELT: case t_PADIC: case t_SER: case t_VECSMALL: return gen_1; case t_FRAC: return gel(x,2); case t_COMPLEX: return vecdenom(x,1,2); case t_QUAD: return vecdenom(x,2,3); case t_POLMOD: return denom_i(gel(x,2)); case t_RFRAC: return gel(x,2); case t_POL: return pol_1(varn(x)); case t_VEC: case t_COL: case t_MAT: return vecdenom(x, 1, lg(x)-1); } pari_err_TYPE("denom",x); return NULL; /* LCOV_EXCL_LINE */ } /* v has lower (or equal) priority as x's main variable */ static GEN denompol(GEN x, long v) { long vx, tx = typ(x); if (is_scalar_t(tx)) return gen_1; switch(typ(x)) { case t_SER: if (varn(x) != v) return x; vx = valser(x); return vx < 0? pol_xn(-vx, v): pol_1(v); case t_RFRAC: x = gel(x,2); return varn(x) == v? x: pol_1(v); case t_POL: return pol_1(v); case t_VEC: case t_COL: case t_MAT: return vecdenompol(x, 1, lg(x)-1, v); } pari_err_TYPE("denom",x); return NULL; /* LCOV_EXCL_LINE */ } GEN denom(GEN x) { pari_sp av = avma; return gerepilecopy(av, denom_i(x)); } static GEN denominator_v(GEN x, long v) { long v0 = gvar(x); GEN d; if (v0 == NO_VARIABLE || varncmp(v0,v) > 0) return pol_1(v); if (v0 != v) { v0 = fetch_var_higher(); x = gsubst(x, v, pol_x(v0)); } d = denompol(x, v0); if (v0 != v) { d = gsubst(d, v0, pol_x(v)); (void)delete_var(); } return d; } GEN denominator(GEN x, GEN D) { pari_sp av = avma; GEN d; if (!D) return denom(x); if (isint1(D)) { d = Q_denom_safe(x); if (!d) { set_avma(av); return gen_1; } return gerepilecopy(av, d); } if (!gequalX(D)) pari_err_TYPE("denominator", D); return gerepileupto(av, denominator_v(x, varn(D))); } GEN numerator(GEN x, GEN D) { pari_sp av = avma; long v; if (!D) return numer(x); if (isint1(D)) return Q_remove_denom(x,NULL); if (!gequalX(D)) pari_err_TYPE("numerator", D); v = varn(D); /* optimization */ if (typ(x) == t_RFRAC && varn(gel(x,2)) == v) return gcopy(gel(x,1)); return gerepileupto(av, gmul(x, denominator_v(x,v))); } GEN content0(GEN x, GEN D) { pari_sp av = avma; long v, v0; GEN d; if (!D) return content(x); if (isint1(D)) { d = Q_content_safe(x); return d? d: gen_1; } if (!gequalX(D)) pari_err_TYPE("content", D); v = varn(D); v0 = gvar(x); if (v0 == NO_VARIABLE) return gen_1; if (varncmp(v0,v) > 0) { v0 = gvar2(x); return v0 == NO_VARIABLE? gen_1: pol_1(v0); } if (v0 != v) { v0 = fetch_var_higher(); x = gsubst(x, v, pol_x(v0)); } d = content(x); /* gsubst is needed because of content([x]) = x */ if (v0 != v) { d = gsubst(d, v0, pol_x(v)); (void)delete_var(); } return gerepileupto(av, d); } GEN numer_i(GEN x) { switch(typ(x)) { case t_INT: case t_REAL: case t_INTMOD: case t_FFELT: case t_PADIC: case t_SER: case t_VECSMALL: case t_POL: return x; case t_POLMOD: return mkpolmod(numer_i(gel(x,2)), gel(x,1)); case t_FRAC: case t_RFRAC: return gel(x,1); case t_COMPLEX: case t_QUAD: case t_VEC: case t_COL: case t_MAT: return gmul(denom_i(x),x); } pari_err_TYPE("numer",x); return NULL; /* LCOV_EXCL_LINE */ } GEN numer(GEN x) { pari_sp av = avma; return gerepilecopy(av, numer_i(x)); } /* 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) { GEN y; switch(typ(x)) { case t_INT: return icopy(x); case t_INTMOD: return v < 0? icopy(gel(x,2)): gcopy(x); case t_POLMOD: if (v < 0 || v == varn(gel(x,1))) return gcopy(gel(x,2)); y = cgetg(3, t_POLMOD); gel(y,1) = lift0(gel(x,1),v); gel(y,2) = lift0(gel(x,2),v); return y; case t_PADIC: return v < 0? padic_to_Q(x): gcopy(x); case t_POL: pari_APPLY_pol(lift0(gel(x,i), v)); case t_SER: if (ser_isexactzero(x)) { if (lg(x) == 2) return gcopy(x); y = scalarser(lift0(gel(x,2),v), varn(x), 1); setvalser(y, valser(x)); return y; } pari_APPLY_ser(lift0(gel(x,i), v)); case t_COMPLEX: case t_QUAD: case t_RFRAC: case t_VEC: case t_COL: case t_MAT: pari_APPLY_same(lift0(gel(x,i), v)); default: return gcopy(x); } } /* same as lift, shallow */ GEN lift_shallow(GEN x) { GEN y; switch(typ(x)) { case t_INTMOD: case t_POLMOD: return gel(x,2); case t_PADIC: return padic_to_Q(x); case t_SER: if (ser_isexactzero(x)) { if (lg(x) == 2) return x; y = scalarser(lift_shallow(gel(x,2)), varn(x), 1); setvalser(y, valser(x)); return y; } pari_APPLY_ser(lift_shallow(gel(x,i))); case t_POL: pari_APPLY_pol(lift_shallow(gel(x,i))); case t_COMPLEX: case t_QUAD: case t_RFRAC: case t_VEC: case t_COL: case t_MAT: pari_APPLY_same(lift_shallow(gel(x,i))); default: return x; } } GEN lift(GEN x) { return lift0(x,-1); } GEN liftall_shallow(GEN x) { GEN y; switch(typ(x)) { case t_INTMOD: return gel(x,2); case t_POLMOD: return liftall_shallow(gel(x,2)); case t_PADIC: return padic_to_Q(x); case t_POL: pari_APPLY_pol(liftall_shallow(gel(x,i))); case t_SER: if (ser_isexactzero(x)) { if (lg(x) == 2) return x; y = scalarser(liftall_shallow(gel(x,2)), varn(x), 1); setvalser(y, valser(x)); return y; } pari_APPLY_ser(liftall_shallow(gel(x,i))); case t_COMPLEX: case t_QUAD: case t_RFRAC: case t_VEC: case t_COL: case t_MAT: pari_APPLY_same(liftall_shallow(gel(x,i))); default: return x; } } GEN liftall(GEN x) { pari_sp av = avma; return gerepilecopy(av, liftall_shallow(x)); } GEN liftint_shallow(GEN x) { GEN y; switch(typ(x)) { case t_INTMOD: return gel(x,2); case t_PADIC: return padic_to_Q(x); case t_POL: pari_APPLY_pol(liftint_shallow(gel(x,i))); case t_SER: if (ser_isexactzero(x)) { if (lg(x) == 2) return x; y = scalarser(liftint_shallow(gel(x,2)), varn(x), 1); setvalser(y, valser(x)); return y; } pari_APPLY_ser(liftint_shallow(gel(x,i))); case t_POLMOD: case t_COMPLEX: case t_QUAD: case t_RFRAC: case t_VEC: case t_COL: case t_MAT: pari_APPLY_same(liftint_shallow(gel(x,i))); default: return x; } } GEN liftint(GEN x) { pari_sp av = avma; return gerepilecopy(av, liftint_shallow(x)); } GEN liftpol_shallow(GEN x) { GEN y; switch(typ(x)) { case t_POLMOD: return liftpol_shallow(gel(x,2)); case t_POL: pari_APPLY_pol(liftpol_shallow(gel(x,i))); case t_SER: if (ser_isexactzero(x)) { if (lg(x) == 2) return x; y = scalarser(liftpol(gel(x,2)), varn(x), 1); setvalser(y, valser(x)); return y; } pari_APPLY_ser(liftpol_shallow(gel(x,i))); case t_RFRAC: case t_VEC: case t_COL: case t_MAT: pari_APPLY_same(liftpol_shallow(gel(x,i))); default: return x; } } GEN liftpol(GEN x) { pari_sp av = avma; return gerepilecopy(av, liftpol_shallow(x)); } static GEN centerliftii(GEN x, GEN y) { pari_sp av = avma; long i = cmpii(shifti(x,1), y); set_avma(av); return (i > 0)? subii(x,y): icopy(x); } /* see lift0 */ GEN centerlift0(GEN x, long v) { return v < 0? centerlift(x): lift0(x,v); } GEN centerlift(GEN x) { long v; GEN y; switch(typ(x)) { case t_INT: return icopy(x); case t_INTMOD: return centerliftii(gel(x,2), gel(x,1)); case t_POLMOD: return gcopy(gel(x,2)); case t_POL: pari_APPLY_pol(centerlift(gel(x,i))); case t_SER: if (ser_isexactzero(x)) return lift(x); pari_APPLY_ser(centerlift(gel(x,i))); case t_COMPLEX: case t_QUAD: case t_RFRAC: case t_VEC: case t_COL: case t_MAT: pari_APPLY_same(centerlift(gel(x,i))); case t_PADIC: if (!signe(gel(x,4))) return gen_0; v = valp(x); if (v>=0) { /* here p^v is an integer */ GEN z = centerliftii(gel(x,4), gel(x,3)); pari_sp av; if (!v) return z; av = avma; y = powiu(gel(x,2),v); return gerepileuptoint(av, mulii(y,z)); } y = cgetg(3,t_FRAC); gel(y,1) = centerliftii(gel(x,4), gel(x,3)); gel(y,2) = powiu(gel(x,2),-v); return y; default: return gcopy(x); } } /*******************************************************************/ /* */ /* REAL & IMAGINARY PARTS */ /* */ /*******************************************************************/ static GEN op_ReIm(GEN f(GEN), GEN x) { switch(typ(x)) { case t_POL: pari_APPLY_pol(f(gel(x,i))); case t_SER: pari_APPLY_ser(f(gel(x,i))); case t_RFRAC: { pari_sp av = avma; GEN n, d, dxb = conj_i(gel(x,2)); n = gmul(gel(x,1), dxb); d = gmul(gel(x,2), dxb); return gerepileupto(av, gdiv(f(n), d)); } case t_VEC: case t_COL: case t_MAT: pari_APPLY_same(f(gel(x, i))); } pari_err_TYPE("greal/gimag",x); return NULL; /* LCOV_EXCL_LINE */ } GEN real_i(GEN x) { switch(typ(x)) { case t_INT: case t_REAL: case t_FRAC: return x; case t_COMPLEX: return gel(x,1); case t_QUAD: return gel(x,2); } return op_ReIm(real_i,x); } GEN imag_i(GEN x) { switch(typ(x)) { case t_INT: case t_REAL: case t_FRAC: return gen_0; case t_COMPLEX: return gel(x,2); case t_QUAD: return gel(x,3); } return op_ReIm(imag_i,x); } GEN greal(GEN x) { switch(typ(x)) { case t_INT: case t_REAL: return mpcopy(x); case t_FRAC: return gcopy(x); case t_COMPLEX: return gcopy(gel(x,1)); case t_QUAD: return gcopy(gel(x,2)); } return op_ReIm(greal,x); } GEN gimag(GEN x) { switch(typ(x)) { case t_INT: case t_REAL: case t_FRAC: return gen_0; case t_COMPLEX: return gcopy(gel(x,2)); case t_QUAD: return gcopy(gel(x,3)); } return op_ReIm(gimag,x); } /* return Re(x * y), x and y scalars */ GEN mulreal(GEN x, GEN y) { if (typ(x) == t_COMPLEX) { if (typ(y) == t_COMPLEX) { pari_sp av = avma; GEN a = gmul(gel(x,1), gel(y,1)); GEN b = gmul(gel(x,2), gel(y,2)); return gerepileupto(av, gsub(a, b)); } x = gel(x,1); } else if (typ(y) == t_COMPLEX) y = gel(y,1); return gmul(x,y); } /* Compute Re(x * y), x and y matrices of compatible dimensions * assume scalar entries */ GEN RgM_mulreal(GEN x, GEN y) { long i, j, k, l, lx = lg(x), ly = lg(y); GEN z = cgetg(ly,t_MAT); l = (lx == 1)? 1: lgcols(x); for (j=1; j=0? gen_1: gen_0; } GEN ggt(GEN x, GEN y) { return gcmp(x,y)>0? gen_1: gen_0; } GEN geq(GEN x, GEN y) { return _egal(x,y)? gen_1: gen_0; } GEN gne(GEN x, GEN y) { return _egal(x,y)? gen_0: gen_1; } GEN gnot(GEN x) { return gequal0(x)? gen_1: gen_0; } /*******************************************************************/ /* */ /* FORMAL SIMPLIFICATIONS */ /* */ /*******************************************************************/ GEN geval_gp(GEN x, GEN t) { long lx, i, tx = typ(x); pari_sp av; GEN y, z; if (is_const_t(tx) || tx==t_VECSMALL) return gcopy(x); switch(tx) { case t_STR: return localvars_read_str(GSTR(x),t); case t_POLMOD: av = avma; return gerepileupto(av, gmodulo(geval_gp(gel(x,2),t), geval_gp(gel(x,1),t))); case t_POL: lx=lg(x); if (lx==2) return gen_0; z = fetch_var_value(varn(x),t); if (!z) return RgX_copy(x); av = avma; y = geval_gp(gel(x,lx-1),t); for (i=lx-2; i>1; i--) y = gadd(geval_gp(gel(x,i),t), gmul(z,y)); return gerepileupto(av, y); case t_SER: pari_err_IMPL( "evaluation of a power series"); case t_RFRAC: av = avma; return gerepileupto(av, gdiv(geval_gp(gel(x,1),t), geval_gp(gel(x,2),t))); case t_QFB: case t_VEC: case t_COL: case t_MAT: pari_APPLY_same(geval_gp(gel(x,i),t)); case t_CLOSURE: if (closure_arity(x) || closure_is_variadic(x)) pari_err_IMPL("eval on functions with parameters"); return closure_evalres(x); } pari_err_TYPE("geval",x); return NULL; /* LCOV_EXCL_LINE */ } GEN geval(GEN x) { return geval_gp(x,NULL); } GEN simplify_shallow(GEN x) { long v, lx; GEN y, z; if (!x) pari_err_BUG("simplify, NULL input"); switch(typ(x)) { case t_INT: case t_REAL: case t_INTMOD: case t_FRAC: case t_FFELT: case t_PADIC: case t_QFB: case t_LIST: case t_STR: case t_VECSMALL: case t_CLOSURE: case t_ERROR: case t_INFINITY: return x; case t_COMPLEX: return isintzero(gel(x,2))? gel(x,1): x; case t_QUAD: return isintzero(gel(x,3))? gel(x,2): x; case t_POLMOD: y = cgetg(3,t_POLMOD); z = gel(x,1); v = varn(z); z = simplify_shallow(z); if (typ(z) != t_POL || varn(z) != v) z = scalarpol_shallow(z, v); gel(y,1) = z; gel(y,2) = simplify_shallow(gel(x,2)); return y; case t_POL: lx = lg(x); if (lx==2) return gen_0; if (lx==3) return simplify_shallow(gel(x,2)); pari_APPLY_pol(simplify_shallow(gel(x,i))); case t_SER: pari_APPLY_ser(simplify_shallow(gel(x,i))); case t_RFRAC: y = cgetg(3,t_RFRAC); gel(y,1) = simplify_shallow(gel(x,1)); z = simplify_shallow(gel(x,2)); if (typ(z) != t_POL) return gdiv(gel(y,1), z); gel(y,2) = z; return y; case t_VEC: case t_COL: case t_MAT: pari_APPLY_same(simplify_shallow(gel(x,i))); } pari_err_BUG("simplify_shallow, type unknown"); return NULL; /* LCOV_EXCL_LINE */ } GEN simplify(GEN x) { pari_sp av = avma; GEN y = simplify_shallow(x); return av == avma ? gcopy(y): gerepilecopy(av, y); } /*******************************************************************/ /* */ /* EVALUATION OF SOME SIMPLE OBJECTS */ /* */ /*******************************************************************/ /* q is a real symmetric matrix, x a RgV. Horner-type evaluation of q(x) * using (n^2+3n-2)/2 mul */ GEN qfeval(GEN q, GEN x) { pari_sp av = avma; long i, j, l = lg(q); GEN z; if (lg(x) != l) pari_err_DIM("qfeval"); if (l==1) return gen_0; if (lgcols(q) != l) pari_err_DIM("qfeval"); /* l = lg(x) = lg(q) > 1 */ z = gmul(gcoeff(q,1,1), gsqr(gel(x,1))); for (i=2; i 2 */ xc = conj_i(x); z = mulreal(gcoeff(q,2,1), gmul(gel(x,2),gel(xc,1))); for (i=3;i 20) M = ZM_mul(shallowtrans(M), ZM_mul(q, M)); else M = ZM_transmultosym(M, ZM_mul(q, M)); return gerepileupto(av, M); } GEN poleval(GEN x, GEN y) { long i, j, imin, tx = typ(x); pari_sp av0 = avma, av; GEN t, t2, r, s; if (is_scalar_t(tx)) return gcopy(x); switch(tx) { case t_POL: i = lg(x)-1; imin = 2; break; case t_RFRAC: return gerepileupto(av0, gdiv(poleval(gel(x,1),y), poleval(gel(x,2),y))); case t_VEC: case t_COL: i = lg(x)-1; imin = 1; break; default: pari_err_TYPE("poleval",x); return NULL; /* LCOV_EXCL_LINE */ } if (i<=imin) return (i==imin)? gmul(gel(x,imin),Rg_get_1(y)): Rg_get_0(y); if (isintzero(y)) return gcopy(gel(x,imin)); t = gel(x,i); i--; if (typ(y)!=t_COMPLEX) { #if 0 /* standard Horner's rule */ for ( ; i>=imin; i--) t = gadd(gmul(t,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(t,y)); } r = (i==j)? y: gpowgs(y, i-j+1); t = gadd(gmul(t,r), gel(x,j)); if (gc_needed(av0,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"poleval: i = %ld",i); t = gerepileupto(av0, t); } } return gerepileupto(av0, t); } t2 = gel(x,i); i--; r = gtrace(y); s = gneg_i(gnorm(y)); av = avma; for ( ; i>=imin; i--) { GEN p = gadd(t2, gmul(r, t)); t2 = gadd(gel(x,i), gmul(s, t)); t = p; if (gc_needed(av0,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"poleval: i = %ld",i); gerepileall(av, 2, &t, &t2); } } return gerepileupto(av0, gadd(t2, gmul(y, t))); } /* Evaluate a polynomial using Horner. Unstable! * If ui != NULL, ui = 1/u, evaluate P(1/u)*u^(deg P): useful for |u|>1 */ GEN RgX_cxeval(GEN T, GEN u, GEN ui) { pari_sp ltop = avma; GEN S; long n, lim = lg(T)-1; if (lim == 1) return gen_0; if (lim == 2) return gcopy(gel(T,2)); if (!ui) { n = lim; S = gel(T,n); for (n--; n >= 2; n--) S = gadd(gmul(u,S), gel(T,n)); } else { n = 2; S = gel(T,2); for (n++; n <= lim; n++) S = gadd(gmul(ui,S), gel(T,n)); S = gmul(gpowgs(u, lim-2), S); } return gerepileupto(ltop, S); } GEN RgXY_cxevalx(GEN x, GEN u, GEN ui) { pari_APPLY_pol(typ(gel(x,i))==t_POL? RgX_cxeval(gel(x,i), u, ui): gel(x,i)); } pari-2.17.2/src/basemath/nflist.c0000644000175000017500000050660114760123736015223 0ustar billbill/* Copyright (C) 2020 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_nflist /* Code s: if s >= 0 number of complex embeddings; s = -1: all signatures; * s = -2: all signatures separated. * Known groups: C1 = 1T1, C2 = 2T1, C3 = 3T1, S3 = 3T2, C4 = 4T1, V4 = 4T2, * D4 = 4T3, A4 = 4T4, S4 = 4T5, C5 = 5T1, D5 = 5T2, F5 = M20 = 5T3, A5 = 5T4, * C6 = 6T1, S36 = D66 = 6T2, D612 = 6T3, A46 = 6T4, S3C3 = 6T5, * A462 = 6T6, S46P = 6T7, S46M = 6T8, C32C4 = 6T10, S462 = 6T11, * A56 = PSL25 = 6T12, C32D4 = 6T13, * C7 = 7T1, D7 = 7T2, M21 = 7T3, M42 = 7T4, C9 = 9T1, C3C3 = 9T2, * CL and DL for L prime. A5cond is A5 ordered by twist-minimal conductor. * * For each group G: * - makeG(GEN N, GEN F, long s, long prec): * fields of given Galois group G, absolute discriminant N, signature s, and * auxiliary field (possibly NULL) F. * - makeGvec(GEN X, GEN Xinf, GEN F, long s, long prec): * fields of given Galois group G, absolute discriminant between Xinf and X, * signature s, and auxiliary field (possibly NULL) F. * - makeGresolvent(GEN pol, long flag) * - makeGsome(long s, long n, long prec): find n fields of given Galois group * G and signature s, not necessarily the smallest; n is assumed small. Useful * only when makeG/makeGvec take a long time. */ /* Relations between discriminants: * D = disc of quadratic subfield or resolvent; Dk = disc subfield of degree k. * f,g are integers, not necessarily conductors. * * C_ell: f^(ell-1), conductor f; ell odd prime * D_ell: (Df^2)^((ell-1)/2), (f) = cond. over quad. subfield; ell odd prime * C4: D^3f^2 (D sum of 2 squares); "conductor" Df * V4: D^2f^2 (D for any of the 3 max. subfields); conductor lcm(D1,D2) * D4: D^2f; "conductor" Df * A4: Df^2, D = g^2 * S4: Df^2 * F5 = M20: Df^4 or 25D f^4 iff 125|D (what f's ?) * C6: D^3D3^2/gcd(D,D3)^2; conductor lcm(D,D3) * D6 = D6(12): D^3 D3^2 / gcd(D,D3)^2 * (1 or 4) * S3(6) = D6(6): D^3 f^4 = D3^2 D * A4(6), S4(6)+: D3 * D4 * S4(6)-: D*D3*D4 / gcd(g,D)^2*(1,4,16); D4 = D3*g^2, D3 = Df^2, D4 = D3g^2 * D*D3*D4 = D^3f^4g^2 = D3^3(g/f)^2 = D3^2*D*g^2=D4^3/(g^4f^2) * Disc = D3^2 D * (g * (1,2,4) / gcd(g,D))^2 * 16 iff v(D2)=2 and v(g)=2 or 3. * 4 iff v(g)=1 or (v(D2)=2 and v(g)=4) * 1 or 4 if v(D2)=3 and v(g)=4. * C32C4: D D4 f^2 * S32: disc of 2 S3 subfields: D1F1^2, D2F2^2, D1, D2 fund. disc * disc = (D1D2)^3 / gcd(D1,D2)^4 * lcm(F1,F2)^2 * g^2 * M21: D^2f^6 (D = g^2) or 7^4 D^2 f^6 iff 49|D * M42: Df^6 or 7^2 Df^6 iff 7^4|D or 7^4 Df^6 iff 7^5|D * C9: D^4f^6 * C3xC3: lcm(D3, D3')^3 * D9: D^4 g^2 f^6 (disc subic subfield = Dg^2) * * Minimimal discriminants for each group, by s * C1: [1] * C2: [5, 3] * C3: [49, 0] * S3: [148, 23] * C4: [1125, 0, 125] * V4: [1600, 0, 144] * D4: [725, 275, 117] * A4: [26569, 0, 3136] * S4: [1957, 283, 229] * C5: [14641, 0, 0] * D5: [160801, 0, 2209] * F5: [2382032, 0, 35152] * A5: [3104644, 0, 18496] * C6: [300125, 0, 0, 16807] * S36: [810448, 0, 0, 12167] * D612: [2738000, 0, 66125, 14283] * A46: [25969216, 0, 153664, 0] * S3C3: [722000, 0, 0, 9747] * A462: [434581, 103243, 31213, 0] * S46+: [3356224, 0, 33856, 0] * S46-: [7495014493, 0, 3241792, 778688] * S32: [27848000, 0, 242000, 309123] * C32C4: [55130625, 0, 525625, 0] * S462: [1387029, 309123, 28037, 10051] * C7: [594823321, 0, 0] * D7: [192100033, 0, 0, 357911] * M21: [1817487424, 0, 0, 0] * M42: [12431698517, 0, 0, 38014691] * C9: [16983563041, 0, 0, 0, 0] * C3C3: [62523502209, 0, 0, 0, 0] * D9: [1624709678881, 0, 0, 0, 775511104] * C11: [41426511213649, 0, 0, 0, 0] * D11: [3670285774226257, 0, 0, 0, 0, 129891985607] */ /* FIXME: export */ static long RgVV_nb(GEN v) { long i, l = lg(v), n = 0; for (i = 1; i < l; i++) n += lg(gel(v,i)) - 1; return n; } /* FIXME: export */ static GEN gtoset_shallow(GEN x) { GEN p = gen_indexsort_uniq(x, (void*)&cmp_universal, cmp_nodata); return vecpermute(x, p); } static GEN nflist_parapply(const char *s, GEN v, GEN w) { GEN L; if (DEBUGLEVEL>=3) err_printf("%s: ",s); L = gen_parapply_percent(snm_closure(is_entry(s), v), w, DEBUGLEVEL>=3); if (DEBUGLEVEL>=3) err_printf("done\n"); return L; } /**************************************************************************/ /* Utility functions */ /**************************************************************************/ static long divissquareall(GEN x, GEN y, GEN *f) { GEN r, q = dvmdii(x, y, &r); return r == gen_0 && Z_issquareall(q,f); } static long divissquare(GEN x, GEN y) { return divissquareall(x, y, NULL); } static long divispowerall(GEN x, GEN y, ulong k, GEN *f) { GEN r, q = dvmdii(x, y, &r); return r == gen_0 && Z_ispowerall(q,k,f); } /* x / y if y | x, else NULL */ static GEN divide(GEN x, GEN y) { GEN r, q = dvmdii(x, y, &r); return r == gen_0? q: NULL; } /* ceil(X^(1/n)) */ static long ceilsqrtn(GEN X, long n) { pari_sp av = avma; ulong x = itou(sqrtnint(X, n)); if (cmpii(powuu(x, n), X) < 0) x++; return gc_long(av, x); } static long ceilsqrt(GEN X) { pari_sp av = avma; GEN r; ulong x = itou(sqrtremi(X, &r)); return gc_long(av, r==gen_0? x: x+1); } static GEN gceilsqrtn(GEN X, long n) { GEN x = sqrtnint(X, n); if (cmpii(powiu(x, n), X) < 0) x = addiu(x, 1); return x; } /* assume X >= 0 or n odd */ static long sceilsqrtn(long X, long n) { ulong x, Xa; if (!X) return 0; Xa = labs(X); x = usqrtn(Xa, n); if (X > 0 && upowuu(x, n) != Xa) x++; return X > 0? (long)x: -(long)x; } /* ceil((X/Y)^1/n)*/ static long ceilsqrtndiv(GEN X, GEN Y, long n) { pari_sp av = avma; ulong x = itou(sqrtnint(divii(X, Y), n)); if (cmpii(mulii(powuu(x, n), Y), X) < 0) x++; return gc_long(av, x); } long ceilsqrtdiv(GEN X, GEN Y) { pari_sp av = avma; GEN r, q = dvmdii(X, Y, &r); ulong x = itou((r == gen_0)? sqrtremi(q, &r): sqrti(q)); return gc_long(av, r==gen_0? x: x+1); } static GEN gceilsqrtdiv(GEN X, GEN Y) { GEN r, q = dvmdii(X, Y, &r); q = (r == gen_0)? sqrtremi(q, &r): sqrti(q); return r == gen_0? q: addiu(q, 1); } static GEN gfloorsqrtdiv(GEN X, GEN Y) { return sqrti(divii(X, Y)); } /* floor(X^(1/n)) */ static long floorsqrtn(GEN X, long n) { pari_sp av = avma; return gc_long(av, itou(sqrtnint(X, n))); } static long floorsqrt(GEN X) { pari_sp av = avma; return gc_long(av, itou(sqrti(X))); } /* floor((X/Y)^(1/n)) */ static long floorsqrtndiv(GEN X, GEN Y, long n) { pari_sp av = avma; return gc_long(av, itou(sqrtnint(divii(X,Y), n))); } static long floorsqrtdiv(GEN X, GEN Y) { pari_sp av = avma; return gc_long(av, itou(gfloorsqrtdiv(X, Y))); } static GEN ceildiv(GEN X, GEN Y) { GEN r, q = dvmdii(X, Y, & r); return (r == gen_0)? q: addiu(q, 1); } static GEN nfY(GEN T) { T = shallowcopy(T); setvarn(T,1); return nfinit(T, MEDDEFAULTPREC); } static GEN bnfY(GEN T) { T = shallowcopy(T); setvarn(T,1); return Buchall(T, nf_FORCE, MEDDEFAULTPREC); } static GEN bnf_get_disc(GEN b) { return nf_get_disc(bnf_get_nf(b)); } /* Compute n s.t. d | n <=> d^k | N. Return [n, factor(n)] */ static GEN cored(GEN N, long k) { GEN fa = Z_factor(N), P = gel(fa,1), E = gel(fa,2), n = gen_1; long i, c, l = lg(P); for (i = c = 1; i < l; i++) { long e = itou(gel(E,i)); if (e >= k) { e /= k; n = mulii(n, powiu(gel(P,i), e)); gel(P,c) = gel(P,i); gel(E,c) = utoipos(e); c++; } } setlg(P,c); setlg(E,c); return mkvec2(n, fa); } /* return D = nfdisc(T), set d = coredisc */ static GEN nfcoredisc(GEN T, GEN *pd) { GEN D = nfdiscfactors(T), d = core(D); /* d = core(|D|) */ D = gel(D,1); if (signe(D) < 0) togglesign_safe(&d); if (Mod4(d) != 1) d = shifti(d,2); /* = coredisc(D) */ *pd = d; return D; } static GEN nfcoredisc2(GEN T, GEN *pd, GEN *pf) { GEN D = nfcoredisc(T, pd); if (pf) *pf = sqrti(diviiexact(D, *pd)); return D; } /* \prod {pr | ell} pr */ static GEN getpell(GEN nf, long ell, long *pteell) { GEN P = idealprimedec(nf, utoipos(ell)); *pteell = pr_get_e(gel(P,1)); return idealfactorback(nf, P, NULL, 0); } static void checkfield_i(GEN F, long d) { if (F && degpol(F) != d) pari_err_TYPE("nflist", F); } static GEN checkfield(GEN F, long d) { checkfield_i(F, d); return nfdisc(F); } static long pol2s(GEN T) { return (degpol(T) - ZX_sturm_irred(T)) >> 1; } static GEN sturmseparate(GEN V, long s, long deg) { GEN w, C; long l, ls , i; if (s != -2) return V; l = lg(V); ls = (deg >> 1) + 2; w = cgetg(ls, t_VEC); C = cgetg(ls, t_VECSMALL); for (i = 1; i < ls; i++) { gel(w, i) = cgetg(l, t_VEC); C[i] = 1; } for (i = 1; i < l; i++) { long k = pol2s(gel(V, i)) + 1; gmael(w, k, C[k]++) = gel(V, i); } for (i = 1; i < ls; i++) setlg(gel(w, i), C[i]); return w; } /* fa = factorization of positive integer N. Are +N and/or -N fundamental ? */ static void fa_is_fundamental_pm(GEN N, GEN fa, long s, int *p, int *m) { GEN P = gel(fa,1), E = gel(fa,2); long l = lg(P), i; ulong r, r4; if (l == 1) { *m = 0; *p = (s <= 0); return; } r = Mod16(N); r4 = r & 3UL; if (!r || r4 == 2) { *p = *m = 0; return; } /* v_2 > 3 or N=2 mod 4 */ *p = (s <= 0); *m = s? 1: 0; if (odd(r)) { if (r4 == 1) { *m = 0; if (!*p) return; } else { *p = 0; if (!*m) return; } i = 1; } else { /* P[1] = 2 => 4 | N */ if (r == 4) { *p = 0; if (!*m) return; } else if (r == 12) { *m = 0; if (!*p) return; } i = 2; } for (; i < l; i++) if (itou(gel(E,i)) > 1) { *p = *m = 0; return; } } /* if flag is set assume the odd part of N is squarefree */ static void uis_fundamental_pm_i(ulong N, long s, int *p, int *m, long flag) { ulong r, r4; if (N == 1UL) { *m = 0; *p = (s <= 0); return; } r = N & 15UL; r4 = r & 3UL; if (!r || r4 == 2) { *p = *m = 0; return; } /* v_2 > 3 or N=2 mod 4 */ *p = (s <= 0); *m = s? 1: 0; if (odd(r)) { if (r4 == 1) { *m = 0; if (!*p) return; } else { *p = 0; if (!*m) return; } } else { /* P[1] = 2 => 4 | N */ if (r == 4) { *p = 0; if (!*m) return; } else if (r == 12) { *m = 0; if (!*p) return; } N >>= (r == 8? 3: 2); /* odd part */ } if (!flag && !uissquarefree(N)) { *p = *m = 0; } } static void uis_fundamental_pm(ulong N, long s, int *p, int *m) { uis_fundamental_pm_i(N, s, p, m, 0); } static void is_fundamental_pm(GEN N, long s, int *p, int *m) { ulong r, r4; if (lgefint(N) == 3) { uis_fundamental_pm(N[2], s, p, m); return; } r = Mod16(N); r4 = r & 3UL; if (!r || r4 == 2) { *p = *m = 0; return; } /* v_2 > 3 or N=2 mod 4 */ *p = (s <= 0); *m = s? 1: 0; if (odd(r)) { if (r4 == 1) { *m = 0; if (!*p) return; } else { *p = 0; if (!*m) return; } } else { /* P[1] = 2 => 4 | N */ if (r == 4) { *p = 0; if (!*m) return; } else if (r == 12) { *m = 0; if (!*p) return; } N = shifti(N, r == 8? -3: -2); /* odd part */ } if (!Z_issquarefree(N)) { *p = *m = 0; } } static GEN fund_pm(GEN N, int p, int m) { if (p && m) return mkvec2(N, negi(N)); if (p) return mkvec(N); if (m) return mkvec(negi(N)); return NULL; } static GEN ufund_pm(ulong N, int p, int m) { if (p && m) return mkvec2(utoipos(N), utoineg(N)); if (p) return mkvec(utoipos(N)); if (m) return mkvec(utoineg(N)); return NULL; } /* return of fundamental discriminant divisors of N filtering by signature s. * if abs is set, only return their absolute values */ static GEN divisorsdisc_i(GEN N, long s, long abs) { GEN D, V; long l, c = 1, i; if (typ(N) == t_VEC) { /* [n, factor(n)]; assume n > 0 */ GEN n = gel(N,1), fa = gel(N,2); if (Mod4(n) == 2) N = mkvec2(shifti(n,-1), rowsplice(fa, 1)); } else if (Mod4(N) == 2) N = shifti(N, -1); D = divisors_factored(N); l = lg(D); V = cgetg(2 * l - 1, t_VEC); for (i = 2; i < l; i++) { GEN d = gel(D, i), A = gel(d, 1); int p, m; fa_is_fundamental_pm(A, gel(d,2), s, &p, &m); if (abs) { if (p || m) gel(V, c++) = A; } else { if (p) gel(V, c++) = gel(d,1); if (m) gel(V, c++) = negi(gel(d,1)); } } setlg(V, c); return V; } static GEN divisorsdisc(GEN N, long s) { return divisorsdisc_i(N, s, 0); } static GEN divisorsabsdisc(GEN N, long s) { return divisorsdisc_i(N, s, 1); } static int usum2sq(ulong m) { pari_sp av = avma; GEN fa, P, E; long i, v2 = vals(m); if (v2) { if (v2 != 3) return 0; m >>= 3; } if ((m & 3L) != 1) return 0; fa = factoru(m); P = gel(fa, 1); E = gel(fa, 2); for (i = 1; i < lg(P); i++) if (E[i] >= 2 || (P[i] & 3L) == 3) { set_avma(av); return 0; } set_avma(av); return 1; } static int sum2sq(GEN m) { pari_sp av = avma; GEN fa, P, E; long i, v2; if (lgefint(m) == 3) return usum2sq(m[2]); v2 = vali(m); if (v2) { if (v2 != 3) return 0; m = shifti(m, -3); } if (Mod4(m) != 1) return 0; fa = Z_factor(m); P = gel(fa, 1); E = gel(fa, 2); for (i = 1; i < lg(P); i++) if (!equali1(gel(E,i)) || Mod4(gel(P,i)) == 3) { set_avma(av); return 0; } set_avma(av); return 1; } static int ok_int(GEN d, GEN X, GEN Xinf) { return (abscmpii(d, X) <= 0 && abscmpii(d, Xinf) >= 0); } static int ok_intu(GEN d, ulong X, ulong Xinf) { return (abscmpiu(d, X) <= 0 && abscmpiu(d, Xinf) >= 0); } static int ok_disc(GEN d, GEN X, GEN Xinf) { if (!Xinf) return absequalii(d, X); return ok_int(d, X, Xinf); } /* G cyclic galoisinit */ static GEN cyclicgalois(GEN bnr, GEN G, long *o) { GEN g = galoispermtopol(G, gel(gal_get_gen(G), 1)); *o = gal_get_orders(G)[1]; return bnrautmatrix(bnr, g); /* order o */ } /* Cl_f / H cyclic of prime order, return i s.t bnr.cyc[i] is generator */ static long cyclicprimegen(GEN H) { long i, l = lg(H); for (i = 1; i < l; i++) if (!is_pm1(gcoeff(H,i,i))) return i; return -1;/*LCOV_EXCL_LINE*/ } /* k/Q cyclic and M the bnrautmatrix for the generator s of its Galois group * (action on bnr = Cl_f(k)). vH a vector of congruence subgroups for bnr, * attached to abelian extensions K/k of prime degree, assumed to be Galois * over Q [sf = f and sH = H]. Filter out the H corresponding to K/Q abelian */ static void nonabelianfilter(GEN vH, GEN M) { long i, c, l = lg(vH); for (i = c = 1; i < l; i++) { GEN v, H = gel(vH,i); long k = cyclicprimegen(H); v = shallowcopy(gel(M,k)); gel(v,k) = subiu(gel(v,k), 1); if (!hnf_invimage(H, v)) gel(vH, c++) = H; } setlg(vH, c); } /* bnf attached to K. Cyclic extensions L/K of degree d and exact conductor * F; if F = [F,Finf]~, check that Finf | conductor | F; * check that |disc L/Q| in [Xinf,X] if not NULL. If G != NULL, * then K/Q = is cyclic, we assume s.F = F and * G = [galoisinit(bnf), flag], with flag > 0 (resp. 0) to insist L be * Galois / Q (resp. not Galois). If flag = 2, insist that L/Q is non abelian. * In the non-Galois case, keep only one among isomorphic extensions attached * to sigma.H; sigma in Gal(K/Q). For simplicity assume the base is cyclic; * will extend it later if needed. */ static GEN mybnrclassfield_X(GEN bnf, GEN F, long d, GEN X, GEN Xinf, GEN G) { GEN gd = utoipos(d), Finf = NULL, bnr, L; long i, j, c, l; if (typ(F) == t_COL) { Finf = gel(F,1); F = gel(F,2); } bnr = bnrinitmod(bnf, F, 0, gd); L = subgrouplist0(bnr, mkvec(gd), Finf? 1: 0); l = lg(L); if (Finf) { GEN Fi = idealinv(bnr, Finf); for (i = c = 1; i < l; i++) { /* for now assume that F and Finf are finite */ GEN f = gel(bnrconductor_raw(bnr, gel(L,i)), 1); if (equali1(Q_denom(idealmul(bnr, f, Fi)))) gel(L,c++) = gel(L,i); } setlg(L, c); l = c; } if (l == 1) return L; if (!uisprime(d)) { for (i = j = 1; i < l; i++) if (lg(smithclean(ZM_snf(gel(L,i)))) == 2) gel(L,j++) = gel(L,i); setlg(L, l = j); if (l == 1) return L; } if (G) { GEN M; long o, gal = itou(gel(G,2)); if (l == 2) { /* => L[1] is fixed: must be Galois */ if (!gal) { setlg(L,1); return L; } if (gal == 2) { M = cyclicgalois(bnr, gel(G,1), &o); nonabelianfilter(L, M); } } else { M = cyclicgalois(bnr, gel(G,1), &o); /* assume cyclic for now */ if (gal) { for (i = j = 1; i < l; i++) { GEN H = gel(L,i); if (ZM_equal(bnrgaloisapply(bnr, M, H), H)) gel(L,j++) = H; } setlg(L, l = j); if (gal == 2) nonabelianfilter(L, M); } else { for (i = 1; i < l; i++) { GEN H = gel(L,i), K = bnrgaloisapply(bnr, M, H); long k; /* \sigma H = H <=> Galois : delete */ if (ZM_equal(K, H)) { L = vecsplice(L,i--); l--; continue; } /* else delete the rest of Galois orbit */ for (j = 1; j < o; j++) { for (k = i+1; k < l; k++) if (ZM_equal(K, gel(L,k))) { L = vecsplice(L,k); l--; break; } if (j != o-1) K = bnrgaloisapply(bnr, M, K); } } } } if ((l = lg(L)) == 1) return L; } if (X) { for (i = j = 1; i < l; i++) { GEN D = gel(bnrdisc(bnr, gel(L,i), 0), 3); if (ok_disc(D, X, Xinf)) gel(L,j++) = gel(L,i); } setlg(L, j); if (j == 1) return L; } return shallowconcat1(bnrclassfield(bnr, L, 0, MEDDEFAULTPREC)); } static GEN mybnrclassfield_N(GEN bnf, GEN F, GEN N, long d) { return mybnrclassfield_X(bnf, F, d, N, NULL, NULL); } static GEN mybnrclassfield(GEN bnf, GEN F, long d) { return mybnrclassfield_X(bnf, F, d, NULL, NULL, NULL); } /* N > 1 */ static int checkcondell_i(GEN N, long ell, GEN D2, GEN *pP) { GEN fa, P, E; long l, i, e; if (typ(N) == t_VEC) { fa = gel(N,2); P = gel(fa, 1); E = gel(fa, 2); i = ZV_search(P, utoipos(ell)); if (!i) e = 0; else { e = itou(gel(E,i)); if (e != 2) return 0; P = vecsplice(P, i); E = vecsplice(E, i); } } else { e = Z_lvalrem(N, ell, &N); if (e != 0 && e != 2) return 0; fa = Z_factor(N); P = gel(fa, 1); E = gel(fa, 2); } l = lg(P); for (i = 1; i < l; i++) { GEN p = gel(P,i); long r; if (!equaliu(gel(E,i), 1)) return 0; r = umodiu(p, ell); if (!D2) { if (r != 1) return 0; } else { r -= kronecker(D2, p); if (r && r != ell) return 0; } } *pP = P; return 1; } /* ell odd prime, N potential conductor for C_ell field, *pP contains * the prime divisors of N different from ell */ static int checkcondCL(GEN N, long ell, GEN *pP) { GEN n = typ(N) == t_VEC? gel(N, 1): N; return odd(Mod4(n)) && !equali1(n) && checkcondell_i(N, ell, NULL, pP); } /* D2 fundamental discriminant, ell odd prime, N potential conductor for * D_ell field over Q(sqrt(D2)) */ static int checkcondDL(GEN D2, GEN N, long ell, GEN *pP) { ulong N4; if (!umodiu(D2, ell)) { long v = Z_lvalrem(N, ell, &N); if (v && v > 2) return 0; } if (equali1(N)) { *pP = cgetg(1,t_VEC); return 1; } N4 = Mod4(N); return N4 && (N4 != 2 || ell == 3) && checkcondell_i(N, ell, D2, pP); } static GEN myshallowconcat1(GEN V) { if (lg(V) == 1) return V; return shallowconcat1(V); } static GEN _nfsubfields(GEN pol, long d) { return nfsubfields0(pol, d, 1); } static GEN _nfsubfields1(GEN pol, long d) { return gel(_nfsubfields(pol, d), 1); } static GEN mynfsubfields(GEN pol, long d) { GEN V = _nfsubfields(pol, d), W; long l = lg(V), i; W = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(W,i) = polredabs(gel(V,i)); return W; } static GEN mynfsubfield(GEN pol, long d) { if (d == 2 && (degpol(pol) & 3) == 2) return quadpoly_i(quaddisc(ZX_disc(pol))); return polredabs(gel(_nfsubfields(pol, d), 1)); } /* global checks to be done: -- in nflist: if s > deg / 2, return empty. -- in nfresolvent: check polynomial of correct degree. */ /***************************************************************/ static GEN makeC1(GEN N, GEN field, long s) { checkfield_i(field, 1); if (!equali1(N)) return NULL; return mkvec(s != -2? pol_x(0): mkvec(pol_x(0))); } static GEN makeC1resolvent(long flag) { return odd(flag)? mkvec2(pol_x(0), gen_1): pol_x(0); } static GEN makeC1vec(GEN Xinf, GEN field, long s) { return makeC1(Xinf, field, s); } /**********************************************************************/ /* C2 */ /**********************************************************************/ static GEN makeC2(GEN N, GEN field, long s) { GEN V = NULL; long l, i; int p, m; checkfield_i(field, 1); if (equali1(N) || Mod4(N) == 2) return NULL; is_fundamental_pm(N, s, &p, &m); if (!(V = fund_pm(N, p, m))) return NULL; l = lg(V); for (i = 1; i < l; i++) gel(V, i) = quadpoly_i(gel(V, i)); return sturmseparate(V, s, 2); } static GEN makeC2resolvent(GEN pol, long flag) { return odd(flag)? mkvec2(pol_x(0), absi_shallow(nfdisc(pol))): pol_x(0); } static GEN makeC2vec(GEN X, GEN Xinf, GEN field, long s) { long M, cv, cw, l = itou(subii(X, Xinf)) + 1; GEN v, w; checkfield_i(field, 1); v = (s <= 0)? cgetg(l, t_VEC): NULL; w = s? cgetg(l, t_VEC): NULL; for (M = equali1(Xinf)? 2: 1, cv = cw = 1; M < l; M++) { GEN N = addiu(Xinf, M); int p, m; is_fundamental_pm(N, s, &p, &m); if (p) gel(v, cv++) = quadpoly_i(N); if (m) gel(w, cw++) = quadpoly_i(negi(N)); } if (cv == 1 && cw == 1) return NULL; switch (s) { case 0: setlg(v, cv); return v; case 1: setlg(w, cw); return w; case -1: setlg(v, cv); setlg(w, cw); return shallowconcat(v, w); default: setlg(v, cv); setlg(w, cw); return mkvec2(v, w); } } /**********************************************************************/ /* C3 */ /**********************************************************************/ /* \prod x[i]^e[i], e[i] in {0,1} */ static GEN eltlist2(GEN nf, GEN x) { long i, j, c, l = lg(x); GEN v; if (l == 1) return mkvec(gen_1); v = cgetg((1 << (l-1))+1, t_VEC); gel(v,1) = gen_1; gel(v,2) = gel(x,1); for (i = c = 2; i < l; i++, c <<= 1) for (j = 1; j <= c; j++) gel(v, c + j) = nfmul(nf, gel(v,j), gel(x,i)); return v; } /* { x[1][1] * \prod_i>=2 x[i][e_i], (e) in {1,2}^(#x-1)} */ static GEN mullist2(GEN x) { long i, j, c, l = lg(x); GEN v; if (l == 2) return mkvec(gmael(x,1,1)); v = cgetg((1 << (l-2))+1, t_VEC); gel(v,1) = gel(v,2) = gmael(x,1,1); for (i = 2, c = 1; i < l; i++, c <<= 1) for (j = 1; j <= c; j++) { gel(v, c + j) = gmul(gel(v, j), gmael(x,i,2)); gel(v, j) = gmul(gel(v, j), gmael(x,i,1)); } return v; } static GEN makepolC3(GEN n, GEN u, long fl3) { GEN T = cgetg(6, t_POL), n3, nu27; T[1] = evalsigne(1) | evalvarn(0); gel(T, 5) = gen_1; gel(T, 4) = fl3 ? gen_m1 : gen_0; if (!fl3) { n3 = divis(n, -3); nu27 = mulii(n, u); } else { n3 = divis(subiu(n, 1), -3); nu27 = addiu(mulii(n, subiu(u, 3)), 1); } gel(T, 3) = n3; gel(T, 2) = divis(nu27, -27); return T; } static GEN decp(GEN Q, GEN t, GEN p) { GEN u, v, z; if (equaliu(p, 3)) { u = utoineg(3); v = utoipos(3); } else { GEN uv = qfbsolve(Q, shifti(p, 2), 2); u = gel(uv,1); if (umodiu(u, 3) == 1) togglesign(u); v = muliu(gel(uv,2), 3); if (signe(v) < 0) togglesign(v); } z = gadd(gmul(v, t), shifti(subii(u, v), -1)); return mkvec2(z, conj_i(z)); } static int checkcondC3(GEN n, GEN *pP) { GEN fa = NULL, P, E; long l, i, n27; *pP = NULL; if (typ(n) == t_VEC) { fa = gel(n,2); n = gel(n,1); } if (cmpiu(n, 7) < 0 || !mpodd(n)) return 0; n27 = umodiu(n, 27); switch(n27 % 3) { case 2: return 0; case 1: i = 1; break; default: i = 2; if (n27 != 9 && n27 != 18) return 0; } if (!fa) fa = Z_factor(n); P = gel(fa, 1); E = gel(fa, 2); l = lg(P); for (; i < l; i++) if (umodiu(gel(P,i), 3) != 1 || !equali1(gel(E,i))) return 0; *pP = P; return 1; } static GEN makeC3_i(GEN sqN, GEN P) { GEN v, t, Q = mkqfb(gen_1, gen_0, utoipos(27), utoineg(108)); long i, j, l, n = lg(P)-1, fl3 = umodiu(gel(P,1), 3); t = quadgen0(utoineg(3), 1); v = cgetg(n+1, t_VEC); for (i = 1; i <= n; i++) gel(v,i) = decp(Q, t, gel(P,i)); v = mullist2(v); l = lg(v); for (j = 1; j < l; j++) gel(v,j) = makepolC3(sqN, gtrace(gel(v,j)), fl3); return v; } /* makeC3(f^2, 0) */ static GEN makeC3_f(GEN f) { GEN P; return checkcondC3(f, &P)? makeC3_i(f, P): cgetg(1, t_VEC); } static GEN vecs(long ns, GEN x) { GEN v = const_vec(ns, cgetg(1,t_VEC)); gel(v,1) = x; return v; } static GEN vecs14(GEN x, GEN y) { GEN v = cgetg(1,t_VEC); return mkvec4(x,v,v,y); } static GEN makeC3(GEN N, GEN field, long s) { GEN v, f, P; checkfield_i(field, 1); if (s > 0 || cmpiu(N, 49) < 0 || !Z_issquareall(N, &f) || !checkcondC3(f, &P)) return NULL; v = makeC3_i(f, P); return s == -2 ? vecs(2, v): v; } static GEN makeC3resolvent(GEN pol, long flag) { return odd(flag)? mkvec2(pol_x(0), sqrti(nfdisc(pol))): pol_x(0); } GEN nflist_C3_worker(GEN gv, GEN T) { long v = itos(gv), sX = T[1], sXinf = T[2], c, r, u; long v227 = 27 * v * v, limu = usqrt((sX << 2) - v227); GEN V = cgetg(limu + 2, t_VEC); if (odd(limu - v)) limu--; /* make sure u = v (mod 2) */ for (u = -limu, r = smodss(u, 9), c = 1; u <= limu; u += 2, r += 2) { if (r >= 9) r -= 9; /* r = u % 9 */ if (r == 2 || r == 5 || r == 6 || r == 8) /* u = 2 (mod 3) or 6 (mod 9) */ { long e; if (ugcd(labs(u), v) > 2) continue; e = (u * u + v227) >> 2; /* conductor, disc = e^2 */ if (e < sXinf) continue; if (r == 6) e /= 9; /* 9 | e */ if (!uissquarefree(e)) continue; gel(V, c++) = r==6? mkvecsmall4(1, 0, -3 * e, -e * u / 3) : mkvecsmall4(1, -1, (1-e) / 3, -(1 + e * (u-3)) / 27 ); } } setlg(V, c); return V; } static GEN zvV_to_ZXV(GEN v) { long i, l = lg(v); GEN w = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(w,i) = gtopoly(gel(v,i), 0); return w; } static GEN C3vec(GEN V, long s) { if (s != -2) return zvV_to_ZXV(V); retmkvec2(zvV_to_ZXV(V), cgetg(1,t_VEC)); } /* t a C3 t_VECSMALL generated by C3_worker. Return its conductor f */ static long uC3pol_f(GEN t) { return - t[2] - 3 * t[3]; } /* t a C3 t_POL = gtopoly(C3_worker t_VECSMALL) */ static GEN C3pol_f(GEN t) { return subii(mulsi(-3, gel(t,3)), gel(t,4)); } /* C3vec for discriminant f^2, f in [sX,sXinf] */ static GEN C3vec_F(long sX, long sXinf, GEN *pF) { GEN v, F, perm, T = mkvecsmall2(sX, sXinf); long i, l, lim = usqrt((sX << 2) / 27); v = nflist_parapply("_nflist_C3_worker", mkvec(T), identity_ZV(lim)); v = myshallowconcat1(v); l = lg(v); if (l == 1) return NULL; F = cgetg(l, t_VECSMALL); for (i = 1; i < l; i++) F[i] = uC3pol_f(gel(v,i)); perm = vecsmall_indexsort(F); if (pF) *pF = vecsmallpermute(F, perm); return vecpermute(v, perm); } static GEN makeC3vec(GEN X, GEN Xinf, GEN field, long s) { GEN v; checkfield_i(field, 1); if (s > 0 || !(v = C3vec_F(floorsqrt(X), ceilsqrt(Xinf), NULL))) return NULL; return C3vec(v, s); } /**********************************************************************/ /* S3 */ /**********************************************************************/ /* Quadratic resolvent field. */ static GEN makeDL(long ell, GEN N, GEN field, long s); static GEN makeDLvec(long ell, GEN X, GEN Xinf, GEN field, long s); /* Cubic programs from KB and HC */ #define min(a, b) ((a) >= (b) ? b : a) #define max(a, b) ((a) >= (b) ? a : b) static GEN checkU(long a, long b, long c, long d, long P, long Q, long R, long D) { long t, f = cgcd(cgcd(P, Q), R); GEN F; if (odd(f)) { long e = D & 15L; if (e == 0 || e == 12) return NULL; } else if ((D & 7L) == 0) return NULL; if (f % 3 == 0) { if ((a % 9 == 0) || (a % 3 && (d % 9 == 0))) return NULL; if ((a % 3) && (d % 3)) { long e = (a - d) % 3 ? - 1 : 1; if ((a + c - e * (b + d)) % 9 == 0) return NULL; } if (!uissquarefree(f / 9)) return NULL; } else if (D % 27 == 0 || !uissquarefree(f)) return NULL; t = labs(D) / (f * f); t >>= vals(t); while (t % 3 == 0) t /= 3; if (cgcd(t, f) > 1 || !uissquarefree(t)) return NULL; F = cgetg(6, t_POL); F[1] = evalsigne(1)|evalvarn(0); gel(F,2) = stoi(d * a * a); gel(F,3) = stoi(c * a); gel(F,4) = stoi(b); gel(F,5) = gen_1; return F; } /* ceil(m/d), assume d != 0 */ static long sceildiv(long m, long d) { long q; if (d == 1) return m; if (!m) return 0; if (d < 0) { d = -d; m = -m; } if (m < 0) return -((-m) / d); q = m / d; return m%d? q+1: q; } /* floor(m/d), assume d != 0 */ static long sfloordiv(long m, long d) { long q; if (d == 1) return m; if (!m) return 0; if (d < 0) { d = -d; m = -m; } if (m > 0) return m / d; q = -((-m) / d); return (-m)%d? q-1: q; } GEN nflist_S3R_worker(GEN ga, GEN S) { long a = itos(ga), a3 = 3 * a, a9 = 9 * a, b, c, d, ct = 1; long x = S[1], xinf = S[2], sqx = S[3], cplus = S[4], cminus = S[5]; long cmin = S[6], Dmin = S[7], Dsup = S[8], bsup = S[9], binf = S[10]; long csupa = usqrtn(cplus / a, 3), cinfa = sceilsqrtn(sceildiv(cminus, a), 3); long dsupa = Dsup / a, dinfa = sceildiv(Dmin, a); GEN RET = cgetg(x / 3, t_VEC); for (b = binf; b <= bsup; b++) { long cinf = cinfa, csup = csupa, dinfb = dinfa, dsupb = dsupa; long bb = b * b, b3 = 3 * b, gcdab = cgcd(a, b); if (b) { long bbb = bb * b, sqxb = sqx / labs(b), m, M; if (b < 0) { cinf = -sqxb; csup = -1; M = sfloordiv(cminus,bbb); m = sceildiv(cplus, bbb); } else { cinf = cmin; csup = minss(csup, sqxb); M = cplus / bbb; m = sceildiv(cminus, bbb); } dsupb = minss(dsupb, M); dinfb = maxss(dinfb, m); cinf = maxss(cinfa, cinf); } for (c = cinf; c <= csup; c++) { long dsup, dinf, gcdabc = cgcd(gcdab, c); long bc = b * c, cc = c * c, P = bb - a3 * c; dsup = minss(dsupb, sfloordiv(bc, a9)); /* Q >= 0 */ /* bc-9ad <= 4x / 3c^2 */ dinf = c? maxss(dinfb, sceildiv(bc - ((4 * x) / (cc * 3)), a9)): dinfb; for (d = dinf; d <= dsup; d++) { long Q, R, D, DF; GEN F; if (cgcd(gcdabc, d) > 1) continue; Q = bc - a9 * d; if (Q < 0 || Q > P) continue; if (Q == 0 && b <= 0) continue; R = cc - b3 * d; if (P > R) continue; D = 4 * P * R - Q * Q; DF = D / 3; if (DF > x || DF < xinf) continue; if (P == Q && (Q == R || labs(b) >= labs(3 * a - b))) continue; if (P == R && (a > labs(d) || (a == labs(d) && labs(b) >= labs(c)))) continue; if ((F = checkU(a, b, c, d, P, Q, R, D))) gel(RET, ct++) = F; } } } setlg(RET, ct); return RET; } /* x >= xinf >= 1 */ static GEN cubicreal(long x, long xinf) { double sqx, sqx4, sq13, sq3x; long A, bsup, binf, cmin, cplus, cminus, Dmin, Dsup; GEN V, S; if (x < 148) return NULL; sqx = sqrt((double)x); sq3x = sqrt((double)(3 * x)); sqx4 = sqrt(sqx); sq13 = sqrt(13.); cplus = ((-35 + 13 * sq13) * x) / 216; cminus = ceil((-(35 + 13 * sq13) * x) / 216); cmin = ceil(-sq3x / 4); Dmin = ceil(-4./27 * sqx); Dsup = sq3x / 36; A = floor(sqx4 * 2. / sqrt(27)); bsup = floor(sqx4 * 2. / sqrt(3)); binf = ceil(-sqx4); S = mkvecsmalln(10, x, xinf, (long)sqx, cplus, cminus, cmin, Dmin, Dsup, bsup, binf); V = nflist_parapply("_nflist_S3R_worker", mkvec(S), identity_ZV(A)); V = myshallowconcat1(V); return lg(V) == 1? NULL: V; } GEN nflist_S3I_worker(GEN ga, GEN S) { long a = itos(ga), a3 = a * 3, a9 = a * 9, b, c, d, ct = 1; long x = S[1], xinf = S[2], cplus = S[3], Dsup = S[4], limb = S[5]; long x4 = x * 4, csupa = usqrtn(cplus / a, 3), dsupa = Dsup / a; GEN RET = cgetg(x, t_VEC); for (b = 0; b <= limb; b++) { long b3 = b * 3, bb = b * b, gcdab = cgcd(a, b); long apb = a + b, amb = a - b; long dsupb = b? minuu(dsupa, cplus / (bb * b)): dsupa; long csup = b? min(csupa, 4 * Dsup / b): csupa; for (c = -csup; c <= csup; c++) { long dsup = dsupb, dinf = b? -dsupb: 1, gcdabc = cgcd(gcdab, c); long bc = b * c, cc = c * c, P = bb - a3 * c; if (c) { /* c^2|bc-9ad| <= 4x */ long t = x4 / cc; dsup = minss(dsup, sfloordiv(bc + t, a)); dinf = maxss(dinf, sceildiv(bc - t, a)); } dinf = maxss(dinf, sceildiv(-amb * (amb + c) + 1, a)); dsup = minss(dsup, (apb * (apb + c) - 1) / a); for (d = dinf; d <= dsup; d++) { GEN F; long Q, R, D, DF; if (!d || cgcd(gcdabc, d) > 1) continue; if (d * (d - b) + a * (c - a) <= 0) continue; Q = bc - a9 * d; R = cc - b3 * d; D = 4 * P * R - Q * Q; DF = D / 3; if (DF > -xinf || DF < -x) continue; if ((F = checkU(a, b, c, d, P, Q, R, D))) gel(RET, ct++) = F; } } } setlg(RET, ct); return RET; } static GEN cubicimag(long x, long xinf) { double sqx, sqx4; long lima, limb, Dsup, cplus; GEN V, S; if (x < 31) return NULL; sqx = sqrt((double)x / 27); sqx4 = sqrt(sqx); cplus = (11 + 5 * sqrt(5.)) / 8 * x; Dsup = 3 * sqx; lima = 2 * sqx4; limb = sqrt(3.) * 2 * sqx4; S = mkvecsmall5(x, xinf, cplus, Dsup, limb); V = nflist_parapply("_nflist_S3I_worker", mkvec(S), identity_ZV(lima)); V = myshallowconcat1(V); return lg(V) == 1? NULL: V; } static GEN makeS3resolvent(GEN T, long flag) { GEN P, d, f = NULL; (void)nfcoredisc2(T, &d, odd(flag)? &f: NULL); P = quadpoly_i(d); return f? mkvec2(P, f): P; } static GEN makeS3vec(GEN X, GEN Xinf, GEN field, long s) { GEN R, I; long x, xinf; if (field) return makeDLvec(3, X, Xinf, field, s); x = itos(X); xinf = itos(Xinf); R = (s <= 0)? cubicreal(x, xinf): NULL; I = s? cubicimag(x, xinf): NULL; switch (s) { case 0: return R; case 1: return I; case -1: return R? (I? shallowconcat(R, I): R): I; default: if (!R && !I) return NULL; /* -2 */ return mkvec2(R? R: cgetg(1,t_VEC), I? I: cgetg(1,t_VEC)); } } /**********************************************************************/ /* C4 */ /**********************************************************************/ static GEN makepolC4(GEN S, GEN T) { GEN V = cgetg(7, t_POL); V[1] = evalsigne(1)|evalvarn(0); gel(V, 6) = gen_1; gel(V, 5) = gen_0; gel(V, 4) = S; gel(V, 3) = gen_0; gel(V, 2) = T; return V; } static GEN C4qfbsolve(GEN Q, GEN D) { GEN v = qfbsolve(Q, D, 1), w; long i, c, n = lg(v) - 1; w = cgetg(2 * n + 1, t_VEC); for (i = c = 1; i <= n; i++) { GEN BC = gel(v, i), B = gel(BC,1), C = gel(BC,2); gel(w, c++) = absi_shallow(B); if (!absequalii(B, C)) gel(w, c++) = absi_shallow(C); } setlg(w, c); return gtoset_shallow(w); } /* D squarefree in [D,factor(D)] form, D = B^2 + C^2, * A*(odd part of D) = n2 = prod_{odd p | n} p, v2 = v2(n) */ static GEN polsubC4_D(GEN Q, GEN A, GEN Dfa, GEN n2, long v2, long s, long fli) { GEN v, S, mS, AD, A2D, D = gel(Dfa,1), vB = C4qfbsolve(Q, Dfa); long i, c, l = lg(vB), A4 = Mod4(A); /* 1 or 3 */ AD = mpodd(D)? n2: shifti(n2, 1); A2D = mulii(A, AD); S = mulsi(-2, AD); mS = negi(S); v = cgetg(2 * l - 1, t_VEC); for (i = c = 1; i < l; i++) { GEN B = gel(vB, i), T; long B4 = Mod4(B); int p = (s <= 0), m = !!s; if (v2 <= 2 && odd(B4)) continue; if (!v2) { if (((A4 + B4) & 3) == 1) m = 0; else p = 0; } else if (fli) { if (v2 == 3) { if (!odd(B4)) continue; } else if (v2 == 2) { if (((A4 + B4) & 3) == 1) p = 0; else m = 0; } } if (!p && !m) continue; T = mulii(A2D, subii(D, sqri(B))); if (p) gel(v, c++) = makepolC4(S, T); if (m) gel(v, c++) = makepolC4(mS, T); } setlg(v, c); return v; } /* vector of distinct primes -> squarefree famat */ static GEN P2fa(GEN P) { return mkmat2(P, const_col(lg(P)-1, gen_1)); } /* vector of distinct primes -> [factorback, P2fa] */ static GEN P2Nfa(GEN P) { return mkvec2(ZV_prod(P), P2fa(P)); } /* P = prime divisors of f different from ell; nf = Q or quadratic */ static GEN Pell2prfa(GEN nf, GEN P, long ell, GEN f) { long v = Z_lval(f, ell); if (v) P = ZV_sort_shallow(vec_append(P, utoipos(ell))); P = nf_pV_to_prV(nf, P); settyp(P, t_COL); P = P2fa(P); if (v) { /* add pr^{2e} for all pr | ell */ long i, l = lg(gel(P,1)); for (i = 1; i < l; i++) { GEN pr = gcoeff(P,i,1); if (equaliu(pr_get_p(pr), ell)) gcoeff(P,i,2) = utoipos(v * pr_get_e(pr)); } } return P; } static int ZV_is_1(GEN x, long i0) { long i, l = lg(x); for (i = i0; i < l; i++) if (!equali1(gel(x,i))) return 0; return 1; } static int zv_is_1(GEN x, long i0) { long i, l = lg(x); for (i = i0; i < l; i++) if (x[i] != 1) return 0; return 1; } /* n > 0, D sqfree, sum2sq(odd(D)? D: 4*D) is true */ static GEN polsubcycloC4_i(GEN n, long s, long fli, GEN D) { GEN fa = NULL, P, Q, v, n2; long v2; if (typ(n) == t_VEC) { fa = gel(n,2); n = gel(n,1); } if (s == 1 || equali1(n)) return NULL; /* s = -1, 0 or 2 */ v2 = vali(n); if (fli && (v2 == 1 || v2 > 4)) return NULL; if (!fa) fa = Z_factor(n); P = gel(fa,1); if (fli && !ZV_is_1(gel(fa,2), v2? 2: 1)) return NULL; n2 = ZV_prod(v2? vecsplice(P, 1): P); /* odd part of rad(n) */ Q = mkqfb(gen_1, gen_0, gen_1, utoineg(4)); if (D) { GEN A, PD, LD; if (fli && mpodd(D) == (v2 == 4)) return NULL; if (!(A = divide(n2, mpodd(D) ? D : gmul2n(D, -1)))) return NULL; (void)Z_smoothen(D, P, &PD, &LD); D = mkvec2(D, mkmat2(PD, LD)); v = polsubC4_D(Q, A, D, n2, v2, s, fli); } else { long c, i, lv, l = lg(P); GEN M2 = NULL; c = (v2 && v2 < 4)? 2: 1; /* leave 2 in P if 16 | n */ if (c == 2) M2 = mkmat2(mkcol(gen_2),mkcol(gen_1)); for (i = v2? 2: 1; i < l; i++) /* odd prime divisors of n */ if (Mod4(gel(P,i)) == 1) gel(P, c++) = gel(P,i); setlg(P, c); v = divisors_factored(P2Nfa(P)); lv = lg(v); for (i = c = 1; i < lv; i++) { GEN A, D = gel(v,i), d = gel(D,1); if (M2) /* replace (odd) D by 2*D */ { gel(D,1) = shifti(d,1); gel(D,2) = famat_mul(M2, gel(D,2)); } else if (i == 1) continue; /* ommit D = 1 */ A = diviiexact(n2, mpodd(d)? d: shifti(d,-1)); gel(v,c++) = polsubC4_D(Q, A, D, n2, v2, s, fli); } if (c == 1) return NULL; setlg(v, c); v = shallowconcat1(v); } return v; } static GEN polsubcycloC4(GEN n, long s) { long i, l, c; GEN D = divisors_factored(n); l = lg(D); for (i = 2, c = 1; i < l; i++) { GEN v = polsubcycloC4_i(gel(D,i), s, 1, NULL); if (v) gel(D,c++) = v; } setlg(D, c); return myshallowconcat1(D); } /* x^2 + a */ static GEN X2p(GEN a) { return deg2pol_shallow(gen_1, gen_0, a, 0); } /* x^2 - a */ static GEN X2m(GEN a) { return deg2pol_shallow(gen_1, gen_0, negi(a), 0); } /* y^2 - a */ static GEN Y2m(GEN a) { return deg2pol_shallow(gen_1, gen_0, negi(a), 1); } static GEN makeC4(GEN N, GEN field, long s) { GEN D; long i, c; if (s == 1) return NULL; if (field) { GEN d = checkfield(field, 2); if (signe(d) < 0 || !divissquare(N, powiu(d,3))) return NULL; D = mkvec(d); } else D = divisorsabsdisc(cored(N, 3), 0); for (i = c = 1; i < lg(D); i++) { GEN cond, v, d = gel(D, i); if (sum2sq(d) && Z_issquareall(divii(N, powiu(d, 3)), &cond) && (v = polsubcycloC4_i(mulii(d,cond),s,1, mpodd(d)? d: shifti(d,-2)))) gel(D, c++) = v; } if (c == 1) return NULL; setlg(D, c); return sturmseparate(myshallowconcat1(D), s, 4); } static GEN condrel_i(GEN P, GEN pol) { GEN bnf = bnfY(P), T = gcoeff(nffactor(bnf, pol), 1, 1); GEN f = gel(rnfconductor0(bnf, T, 2), 1); GEN id = gel(f, 1), arch = gel(f, 2), co = gcoeff(id, 1, 1); if (ZM_isscalar(id, co)) id = co; return mkvec2(P, gequal0(arch) ? id : mkvec2(id, arch)); } static GEN condrel(GEN P, GEN pol, long flag) { return odd(flag)? condrel_i(P, pol): P; } static GEN condrel_dummy(GEN P, long flag) { return odd(flag)? mkvec2(P, gen_1): P; } static GEN condrelresolvent(GEN pol, long d, long flag) { return condrel(mynfsubfield(pol, d), pol, flag); } static GEN makeC4resolvent(GEN pol, long flag) { GEN d; (void)nfcoredisc(pol, &d); return condrel(quadpoly_i(d), pol, flag); } static GEN C4vec(GEN X, GEN Xinf, GEN m, long s) { GEN v, M, inf, m3 = powiu(m, 3), limf = gfloorsqrtdiv(X, m3); long l, n, c; pari_sp av; inf = cmpiu(Xinf, 500) >= 0? gceilsqrtdiv(Xinf, m3): gen_1; l = itos(subii(limf, inf)) + 2; M = mpodd(m)? m: shifti(m, -2); av = avma; v = const_vec(l-1, cgetg(1,t_VEC)); for (n = c = 1; n < l; n++) { GEN w, cond = addui(n-1, inf); if ((w = polsubcycloC4_i(mulii(m, cond), s, 1, M))) gel(v, c++) = w; if ((n & 0xfff) == 0 && gc_needed(av, 3)) { /* let parisizemax handle some of it */ if (DEBUGMEM>1) pari_warn(warnmem,"C4vec, n = %ld/%ld", n, l-1); v = gerepilecopy(av, v); } } setlg(v, c); return myshallowconcat1(v); } GEN nflist_C4vec_worker(GEN m, GEN X, GEN Xinf, GEN gs) { pari_sp av = avma; return gerepilecopy(av, C4vec(X, Xinf, m, itos(gs))); } static GEN makeC4vec_i(GEN X, GEN Xinf, GEN field, long s) { GEN v; long limD = floorsqrtn(X,3), m, c, snew = s == -2 ? -1 : s; if (s == 1) return NULL; if (field) { GEN gm = checkfield(field, 2); return sum2sq(gm)? C4vec(X, Xinf, gm, snew): NULL; } v = cgetg(limD >> 1, t_VEC); for (m = 5, c = 1; m <= limD; m += odd(m) ? 3 : 1) if (usum2sq(m)) gel(v, c++) = utoipos(m); setlg(v, c); v = nflist_parapply("_nflist_C4vec_worker", mkvec3(X, Xinf, stoi(snew)), v); return myshallowconcat1(v); } static GEN makeC4vec(GEN X, GEN Xinf, GEN field, long s) { GEN v = makeC4vec_i(X, Xinf, field, s); return v? sturmseparate(v, s, 4): NULL; } /**********************************************************************/ /* V4 */ /**********************************************************************/ static GEN makeV4(GEN N, GEN field, long s) { GEN V, R; long lV, i1, i2, c = 1; if (s == 1) return NULL; if (field) { GEN D = checkfield(field, 2); if (signe(D) < 0) pari_err_TYPE("makeV4 [real quadratic subfield]", field); V = mkvec(D); } else V = divisorsdisc(N, -1); lV = lg(V); R = cgetg((lV - 1) * (lV - 2) >> 1, t_VEC); for (i1 = 1; i1 < lV; i1++) { GEN V2, D1 = gel(V, i1); if (s == 0 && signe(D1) < 0) continue; if (cmpii(sqri(D1), N) > 0) continue; V2 = divisorsdisc(diviiexact(N, absi_shallow(D1)), -1); for (i2 = 1; i2 < lg(V2); i2++) { GEN D2 = gel(V2, i2), D3, D12; if (s == 0 && signe(D2) < 0) continue; if (s > 0 && signe(D1) > 0 && signe(D2) > 0) continue; if ((!field && cmpii(D1, D2) >= 0) || equalii(D1, D2)) continue; D12 = mulii(D1, D2); D3 = coredisc(D12); if (cmpii(D2, D3) < 0 && !equalii(D1, D3) && absequalii(mulii(D12, D3), N)) gel(R, c++) = mkpoln(5, gen_1, gen_0, mulsi(-2, addii(D1, D2)), gen_0, sqri(subii(D1, D2))); } } if (c == 1) return NULL; setlg(R, c); return sturmseparate(R, s, 4); } static GEN makeV4resolvent(GEN pol, long flag) { GEN P, V = mynfsubfields(pol, 2); long i; if (lg(V) != 4) pari_err_BUG("makeV4resolvent"); if (flag >= 2) { if (flag == 2) return V; return mkvec3(condrel_i(gel(V, 1), pol), condrel_i(gel(V, 2), pol), condrel_i(gel(V, 3), pol)); } for (i = 1; i <= 3; i++) { P = gel(V, i); if (signe(ZX_disc(P)) > 0) break; } return condrel(P, pol, flag); } static GEN polV4(long d1, long d2) { return mkpoln(5, gen_1, gen_0, mulss(-2, d1+d2), gen_0, sqrs(d1-d2)); } GEN nflist_V4_worker(GEN D1, GEN X, GEN Xinf, GEN gs) { pari_sp av = avma, av2; GEN V, W; long d2a, e1 = signe(D1), d1 = itos(D1), d1a = labs(d1); long limg, limg2, s2 = -1, s = itos(gs); long limD2 = itos(sqrti(divis(X, d1a))); long limQ = floorsqrtdiv(X, sqru(d1a)); limg2 = limg = usqrt(d1a); if (!odd(d1a)) { /* limg2 = sqrt(d1a * 4), to be used when d2 is also even */ long r = d1a - limg*limg; limg2 *= 2; if (r >= limg) limg2++; } if (s == 2 && e1 > 0) s2 = 1; /* forbid d2 > 0 */ else if (!s) s2 = 0; /* forbid d2 < 0 */ W = vectrunc_init(2 * limD2); V = e1 < 0? W: vectrunc_init(2 * limD2); av2 = avma; for (d2a = d1a; d2a <= limD2; d2a++, set_avma(av2)) { long g, d2ag, LIMg; GEN D3, d1d2a, d3; int p, m; if (odd(d2a)) LIMg = limg; else { if ((d2a & 3) == 2 || !(d2a & 15)) continue; /* v2(d2) = 1 or >= 4 */ LIMg = limg2; } g = ugcd(d2a, d1a); if (g > LIMg) continue; d2ag = d2a / g; if (d2ag > limQ) continue; uis_fundamental_pm(d2a, s2, &p, &m); if (!p && !m) continue; d3 = muluu(d1a / g, d2ag); d1d2a = muluu(d1a, d2a); if (p) { /* D2 = d2a is fundamental */ setsigne(d3, e1); D3 = Mod4(d3) > 1? shifti(d3, 2): d3; /* now D3 = coredisc(D1*D2) */ if (abscmpiu(D3, d2a) > 0 && ok_int(mulii(d1d2a, D3), X, Xinf)) { vectrunc_append(V, polV4(d1, d2a)); av2 = avma; } } if (m) { /* D2 = - d2a is fundamental */ int fl; setsigne(d3, -e1); D3 = Mod4(d3) > 1? shifti(d3, 2): d3; /* now D3 = coredisc(D1*D2) */ fl = abscmpiu(D3, d2a); if (fl < 0 || (!fl && e1 > 0)) continue; if (ok_int(mulii(d1d2a, D3), X, Xinf)) { set_avma(av2); vectrunc_append(W, polV4(d1, -d2a)); av2 = avma; } } } return gerepilecopy(av, mkvec2(e1 < 0? cgetg(1, t_VEC): V, W)); } static GEN Sextract(GEN v, long ind) { long j, l; GEN w = cgetg_copy(v, &l); for (j = 1; j < l; j++) gel(w, j) = gmael(v, j, ind); return myshallowconcat1(w); } static GEN makeV4vec(GEN X, GEN Xinf, GEN field, long s) { long s2, d, dinf, dsup, l, c; GEN v; if (s == 1) return NULL; if (field) { GEN D = checkfield(field, 2), DSQ = sqri(D); if (signe(D) < 0) pari_err_TYPE("makeV4 [real quadratic subfield]", field); if (cmpii(DSQ, X) > 0) return NULL; dinf = itos(D); dsup = dinf; l = 2; s2 = 0; } else { dinf = 3; dsup = floorsqrtn(X,3); l = dsup << 1; s2 = s? -1: 0; } v = cgetg(l, t_VEC); c = 1; for (d = dinf; d <= dsup; d++) { int p, m; uis_fundamental_pm(d, s2, &p, &m); if (m) gel(v, c++) = utoineg(d); if (p) gel(v, c++) = utoipos(d); } setlg(v, c); v = nflist_parapply("_nflist_V4_worker", mkvec3(X, Xinf, stoi(s)), v); switch (s) { case 0: return Sextract(v,1); case 2: return Sextract(v,2); case -1: return shallowconcat(Sextract(v,1), Sextract(v,2)); default: return mkvec3(Sextract(v,1), cgetg(1, t_VEC), Sextract(v,2)); } } /**********************************************************************/ /* D4 */ /**********************************************************************/ static GEN archD40() { return mkvec(cgetg(1, t_VECSMALL)); } static GEN archD41() { return mkvec2(mkvecsmall(2), mkvecsmall(1)); } static GEN archD42() { return mkvec(mkvecsmall2(1, 2)); } static GEN getarchD4(long s) { switch (s) { case 0: return archD40(); case 1: return archD41(); case 2: return archD42(); default: return shallowconcat1(mkvec3(archD40(), archD41(), archD42())); } return gen_0; } /* x = [N, a;0, m] quadratic ideal in HNF, apply quadratic automorphism */ static GEN aut2(GEN x, long oddD) { GEN N = gcoeff(x,1,1), t = subii(N, gcoeff(x,1,2)), m = gcoeff(x,2,2); if (oddD) t = addii(t, m); return mkmat2(gel(x,1), mkcol2(modii(t, N), m)); } /* I a vector of quadratic ideals of same norm */ static GEN authI(GEN nf, GEN I, GEN *pstable, GEN D) { long l = lg(I), i, oddD; GEN v, w; if (l == 1) { *pstable = NULL; return I; } if (l == 2) { *pstable = mkvecsmall(1); return I; } if (l == 3) { *pstable = mkvecsmall2(0,0); gel(I,2) = NULL; return I; } v = w = shallowcopy(I); *pstable = zero_zv(l-1); oddD = mpodd(D); if (typ(gcoeff(gel(I,1), 1, 1)) != t_INT) /* vector of factorizations */ { w = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(w,i) = idealfactorback(nf,gel(v,i),NULL,0); } for (i = 1; i < l; i++) { GEN a = gel(w, i), b; long j; if (!a) continue; b = aut2(a, oddD); if (ZM_equal(b, a)) { (*pstable)[i] = 1; continue; } for (j = i + 1; j < l; j++) if (ZM_equal(b, gel(w,j))) { gel(v,j) = gel(w,j) = NULL; break;} if (j == l) pari_err_BUG("makeD4 [conjugate not found]"); } return v; } /* kronecker(D, cond) != -1, Arch a vector of arch in t_VECSMALL form */ static GEN polD4onecond(GEN bnf, GEN G, GEN D, GEN I, GEN Arch) { GEN stable, v0, v1, v2; long j, k, m, l, lA, ok = 0, r1 = signe(D) > 0? 2: 0; v0 = v1 = v2 = cgetg(1,t_VEC); I = authI(bnf, I, &stable, D); l = lg(I); lA = lg(Arch); for (j = 1; j < l; j++) { GEN id = gel(I, j); if (!id) continue; for (k = 1; k < lA; k++) { GEN arch = gel(Arch, k), R = NULL; long st = lg(arch)-1, lR; if (stable[j]) { if (st == 1 && arch[1] == 1) continue; if (st != 1) R = mybnrclassfield_X(bnf, mkvec2(id,arch), 2,NULL,NULL,G); } if (!R) R = mybnrclassfield(bnf, mkvec2(id, arch), 2); lR = lg(R); if (lR == 1) continue; ok = 1; for (m = 1; m < lR; m++) { GEN P = rnfequation(bnf, gel(R, m)); if (st == 0 && r1) v0 = vec_append(v0, P); else if (st == 1) v1 = vec_append(v1, P); else v2 = vec_append(v2, P); } } } return ok? mkvec3(v0, v1, v2): NULL; } static GEN makeD4(GEN N, GEN field, long s) { pari_sp av2; GEN vD, v, v0, v1, v2, archempty, listarch = getarchD4(s); long l, i; if (field) { GEN D = checkfield(field, 2); if ((signe(D) < 0 && (s == 0 || s == 1)) || !dvdii(N, sqri(D))) return NULL; vD = mkvec(D); } else vD = divisorsdisc(cored(N,2), (s == 0 || s == 1)? 0 : -1); archempty = mkvec(cgetg(1, t_VECSMALL)); l = lg(vD); av2 = avma; v0 = const_vec(l-1, cgetg(1,t_VEC)); v1 = const_vec(l-1, cgetg(1,t_VEC)); v2 = const_vec(l-1, cgetg(1,t_VEC)); for (i = 1; i < l; i++) { GEN bnf, G, I, Arch, RET, D = gel(vD, i); pari_sp av3 = avma; long cond = itou(divii(N, sqri(D))); set_avma(av3); if (kroiu(D, cond) == -1) continue; bnf = Buchall(Y2m(D), nf_FORCE, MEDDEFAULTPREC); I = ideals_by_norm(bnf_get_nf(bnf), utoipos(cond)); Arch = signe(D) > 0 ? listarch : archempty; /* restrict to fields which are not Galois over Q [eliminate V4/C4] */ G = s != 1? mkvec2(galoisinit(bnf, NULL), gen_0): NULL; if (!(RET = polD4onecond(bnf, G, D, I, Arch))) { set_avma(av3); continue; } gel(v0,i) = gel(RET,1); gel(v1,i) = gel(RET,2); gel(v2,i) = gel(RET,3); if (gc_needed(av2, 2)) { if (DEBUGMEM>1) pari_warn(warnmem,"makeD4"); gerepileall(av2, 3, &v0,&v1,&v2); } } if (s == 0) v = myshallowconcat1(v0); else if (s == 1) v = myshallowconcat1(v1); else if (s == 2) v = myshallowconcat1(v2); else { v0 = myshallowconcat1(v0); v1 = myshallowconcat1(v1); v2 = myshallowconcat1(v2); v = mkvec3(v0, v1, v2); if (s == -1) v = myshallowconcat1(v); } return v; } GEN nflist_D4_worker(GEN D, GEN X, GEN Xinf, GEN listarch) { pari_sp av = avma, av2; GEN bnf, G, vI, v0, v1, v2, Arch, D2 = sqri(D); long c0, c1, c2, cond, l = itos(divii(X, D2)) + 1; long lmin = itos(ceildiv(Xinf, D2)); bnf = Buchall(Y2m(D), nf_FORCE, MEDDEFAULTPREC); vI = ideallist(bnf, l-1); Arch = signe(D) > 0 ? listarch : mkvec(cgetg(1,t_VECSMALL)); G = lg(Arch) != 3? mkvec2(galoisinit(bnf, NULL), gen_0): NULL; av2 = avma; v0 = const_vec(l-1, cgetg(1,t_VEC)); v1 = const_vec(l-1, cgetg(1,t_VEC)); v2 = const_vec(l-1, cgetg(1,t_VEC)); c0 = c1 = c2 = 1; for (cond = lmin; cond < l; cond++) { pari_sp av3 = avma; GEN R, R1, R2, R3; if (kroiu(D, cond) == -1) continue; if (!(R = polD4onecond(bnf, G, D, gel(vI, cond), Arch))) { set_avma(av3); continue; } R1 = gel(R,1); if (lg(R1) > 1) gel(v0, c0++) = R1; R2 = gel(R,2); if (lg(R2) > 1) gel(v1, c1++) = R2; R3 = gel(R,3); if (lg(R3) > 1) gel(v2, c2++) = R3; if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"makeD4vec, cond = %ld/%ld",cond,l-1); gerepileall(av2, 3, &v0,&v1,&v2); } } setlg(v0,c0); v0 = myshallowconcat1(v0); setlg(v1,c1); v1 = myshallowconcat1(v1); setlg(v2,c2); v2 = myshallowconcat1(v2); return gerepilecopy(av, mkvec3(v0, v1, v2)); } static GEN makeD4vec(GEN X, GEN Xinf, GEN field, long s) { long s2, limdinf, limdsup, c, da; GEN v, D; if (field) { GEN D = checkfield(field, 2); if (cmpii(sqri(D), X) > 0) return NULL; limdsup = limdinf = labs(itos(D)); s2 = signe(D) < 0? 1: 0; } else { limdinf = 3; limdsup = itou(sqrti(X)); s2 = (s == 0 || s == 1) ? 0 : -1; } D = cgetg(2 * limdsup + 1, t_VEC); c = 1; for (da = limdinf; da <= limdsup; da++) { int p, m; uis_fundamental_pm(da, s2, &p, &m); if (p) gel(D, c++) = utoipos(da); if (m) gel(D, c++) = utoineg(da); } setlg(D, c); v = nflist_parapply("_nflist_D4_worker", mkvec3(X, Xinf, getarchD4(s)), D); if (s >= 0) v = Sextract(v,s+1); else { v = mkvec3(Sextract(v,1), Sextract(v,2), Sextract(v,3)); if (s == -1) v = shallowconcat1(v); } return v; } /**********************************************************************/ /* A4 and S4 */ /**********************************************************************/ /* FIXME: export */ static GEN to_principal_unit(GEN nf, GEN x, GEN pr, GEN sprk) { if (pr_get_f(pr) != 1) { GEN prk = gel(sprk,3); x = nfpowmodideal(nf, x, gmael(sprk,5,1), prk); } return x; } static long ZV_iseven(GEN zlog) { long i, l = lg(zlog); for (i = 1; i < l; i++) if (mpodd(gel(zlog,i))) return 0; return 1; } /* x^2 = t (mod bid) solvable ? */ static int issolvable(GEN nf, GEN t, GEN sprk) { GEN pr = sprk_get_pr(sprk); (void)nfvalrem(nf, t, pr, &t); t = to_principal_unit(nf, t, pr, sprk); return ZV_iseven(sprk_log_prk1(nf, t, sprk)); } /* true nf, cubic field */ static GEN makeGid(GEN nf) { GEN P = idealprimedec(nf, gen_2), Sprk; GEN bid4 = cgetg(1, t_VEC), bid6 = cgetg(1, t_VEC); long l = lg(P), i, parity = mpodd(nf_get_disc(nf)); if (l == 3) { if (parity) /* ensure f(P[1]/2) = 2 */ { swap(gel(P,1), gel(P,2)); } else /* make sure e(P[1]/2) = 2 */ { if (pr_get_e(gel(P,1)) == 1) swap(gel(P,1), gel(P,2)); } } Sprk = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(Sprk, i) = log_prk_init(nf, gel(P,i), 2, gen_2); if (!parity) { bid4 = log_prk_init(nf, gel(P,1), 4, gen_2); if (l == 2) bid6 = log_prk_init(nf, gel(P,1), 6, gen_2); } return mkvecn(3, Sprk, bid4, bid6); } static long r2(GEN v) { long i, l = lg(v); for (i = 1; i < l; i++) if (mpodd(gel(v,i))) break; return i - 1; } /* list of virtual units whose norm is a square */ static GEN makevunits(GEN bnf) { GEN cyc = bnf_get_cyc(bnf), G = bnf_get_gen(bnf), nf = bnf_get_nf(bnf), v; long rc = r2(cyc), l, i; v = cgetg(rc + 1, t_VEC); for (i = 1; i <= rc; i++) { GEN g = idealpows(nf, gel(G, i), itos(gel(cyc, i)) >> 1); g = idealsqr(nf, idealred(nf, g)); g = bnfisprincipal0(bnf, g, nf_GEN | nf_FORCE); gel(v, i) = gel(g, 2); } v = shallowconcat(v, bnf_get_fu(bnf)); l = lg(v); for (i = 1; i < l; i++) { GEN u = gel(v,i); if (signe(nfnorm(nf, u)) < 0) gel(v,i) = gneg(u); /*norm is a square now*/ } return eltlist2(nf, v); } static GEN A4clean3(GEN v, long c) { if (c) { GEN w = gtoset_shallow(vecslice(v, 1, c)); /* #w /= 3 */ if (c != lg(v)-1) w = shallowconcat(w, vecslice(v, c+1, lg(v)-1)); v = w; } return v; } /* nf cubic field, possible local factors for ideals of square norm p^2 */ static GEN cubictypedec(GEN nf, GEN p) { GEN P = idealprimedec(nf, p); switch (lg(P)) { case 2: return NULL; case 3: if (pr_get_f(gel(P,2)) == 2) return mkvec(idealhnf_shallow(nf, gel(P,2))); return mkvec(idealmul(nf, gel(P, 1), gel(P, 2))); default: return mkvec3(idealmul(nf, gel(P, 1), gel(P, 2)), idealmul(nf, gel(P, 2), gel(P, 3)), idealmul(nf, gel(P, 3), gel(P, 1))); } } /* x = gen_1 or in HNF */ static int oddnorm(GEN x) { return typ(x) == t_INT || mpodd(gcoeff(x,1,1)); } /* return k < 4, s.t 2^(2k) = discriminant of quadratic extension over cubic */ static long quadcubpow(GEN bnf, GEN Gid, GEN ideal, GEN a) { GEN nf = bnf_get_nf(bnf), Sprk = gel(Gid,1); long t; if (mpodd(nf_get_disc(nf))) switch (lg(Sprk)) { /* 2 = P3, P2*P1, P1*P1*P1 */ case 2: return issolvable(nf, a, gel(Sprk,1))? 0: 3; /* ideal is odd */ case 3: t = issolvable(nf, a, gel(Sprk,2))? 2: 3; if (oddnorm(ideal) && issolvable(nf, a, gel(Sprk,1))) t -= 2; return t; default: t = 3; if (oddnorm(ideal)) { if (issolvable(nf,a,gel(Sprk,1))) t--; if (issolvable(nf,a,gel(Sprk,2))) t--; if (issolvable(nf,a,gel(Sprk,3))) t--; } else { /* exactly 2 of the 3 primes divide ideal, test solvability by 3rd */ if (!idealval(nf,ideal,sprk_get_pr(gel(Sprk,1)))) { if (issolvable(nf,a,gel(Sprk,1))) t--; } else if (!idealval(nf,ideal,sprk_get_pr(gel(Sprk,2)))) { if (issolvable(nf,a,gel(Sprk,2))) t--; } else { if (issolvable(nf,a,gel(Sprk,3))) t--; } } return t; } if (lg(Sprk) == 3) { /* 2 = P1^2 P2 */ if (!oddnorm(ideal)) return 3; t = issolvable(nf, a, gel(Sprk,2))? 2: 3; if (issolvable(nf, a, gel(Gid,2))) t -= 2; /* solvable mod P1^4 */ else if (issolvable(nf, a, gel(Sprk,1))) t--; /* solvable mod P1^2 */ return t; } else { /* 2 = P1^3, ideal must be odd */ if (issolvable(nf, a, gel(Gid,3))) return 0; /* solvable mod pr^6 */ if (issolvable(nf, a, gel(Gid,2))) return 1; /* solvable mod pr^4 */ if (issolvable(nf, a, gel(Sprk,1))) return 2; /* solvable mod pr^2 */ return 3; } } /* idealfactorback for { I } x W[1] x ... assuming all W[i] have d entries */ static GEN idlist(GEN nf, GEN I, GEN W) { long i, j, d, l = lg(W); GEN v, w; if (l == 1) return mkvec(I? I: gen_1); w = gel(W,1); d = lg(w)-1; if (!I) v = w; else { v = cgetg(d + 1, t_VEC); for (j = 1; j <= d; j++) gel(v,j) = idealmul(nf, I, gel(w,j)); } for (i = 2; i < l; i++) { long nv = lg(v)-1, c, k; GEN V = cgetg(d*nv + 1, t_VEC); w = gel(W,i); for (j = c = 1; j <= nv; j++) for (k = 1; k <= d; k++) gel(V, c++) = idealmul(nf, gel(v,j), gel(w,k)); v = V; } return v; } static GEN issquareclass(GEN bnf, GEN x, long rc) { GEN v, d, cyc = bnf_get_cyc(bnf), nf = bnf_get_nf(bnf); GEN e = isprincipal(bnf, x); long l = lg(cyc), j; v = cgetg(l, t_VEC); for (j = 1; j <= rc; j++) { if (mpodd(gel(e,j))) return NULL; gel(v, j) = subii(gel(cyc,j), gel(e,j)); } for (; j < l; j++) { GEN t = subii(gel(cyc,j), gel(e,j)); if (mpodd(t)) t = addii(t, gel(cyc,j)); gel(v, j) = t; } /* all exponents are even */ x = isprincipalfact(bnf, x, bnf_get_gen(bnf), v, nf_GENMAT | nf_FORCE); /* reduce generator mod squares */ x = gel(x,2); x = nffactorback(nf, gel(x,1), ZV_to_Flv(gel(x,2), 2)); x = nfmul(nf, x, nfsqr(nf, idealredmodpower(nf, x, 2, 0))); x = Q_remove_denom(x, &d); return d? gmul(x, d): x; } /* v a vector of ideals of same norm */ static GEN S4makeidclass(GEN bnf, GEN v, long rc) { long j, c, l = lg(v); GEN w = cgetg(l, t_VEC); for (j = c = 1; j < l; j++) { GEN N, a, I = gel(v,j); if (typ(I) == t_INT) a = gen_1; else { if (!(a = issquareclass(bnf, I, rc))) continue; /* I^2 = (a)(mod K^*)^2 */ N = nfnorm(bnf,a); if (signe(N) < 0) a = gneg(a);/* Norm(a)=|N| is a square */ } gel(w, c++) = mkvec2(I, a); } setlg(w, c); return w; } /* L squarefree outside of 2, v2(L) <= 4, P = prime divisors of L. * Write L = N*2^v2, v2 <= 4, N odd sqfree. * List of squarefree ideals A of norm N^2 (and 4N^2 if v2 > 1) */ static GEN S4makeid(GEN bnf, long isA4, long v2, GEN P) { GEN V, V3, v, id, w, d2, nf = bnf_get_nf(bnf); long c, c3, i, k, l, n2, rc; l = lg(P); V = cgetg(l, t_VEC); V3 = cgetg(l, t_VEC); for (i = v2? 2: 1, c = c3 = 1; i < l; i++) { GEN p = gel(P, i), d = cubictypedec(nf, p); if (!d) return NULL; if (lg(d) == 4) gel(V3, c3++) = d; else gel(V,c++) = gel(d, 1); } d2 = (v2 > 1)? cubictypedec(nf, gen_2): NULL; if (isA4) { /* choose representative in C3 orbit */ if (c3 > 1) gel(V, c++) = gmael(V3, --c3, 1); else if (d2 && lg(d2) == 4) d2 = mkvec(gel(d2,1)); } setlg(V,c); setlg(V3,c3); id = c > 1? idealfactorback(nf, V, NULL, 0): NULL; v = idlist(nf, id, V3); rc = r2(bnf_get_cyc(bnf)); if (!d2) return mkvec(S4makeidclass(bnf, v, rc)); n2 = lg(d2)-1; l = lg(v); w = cgetg(n2 * (l-1) + 1, t_VEC); for (i = c = 1; i < l; i++) for (k = 1; k <= n2; k++) gel(w, c++) = idealmul(nf, gel(v,i), gel(d2,k)); return mkvec2(v2 == 4? cgetg(1,t_VEC): S4makeidclass(bnf, v, rc), S4makeidclass(bnf, w, rc)); } static int checkS4data(GEN x) { return lg(x) == 6 && typ(gel(x, 5)) == t_VECSMALL; } static GEN S4data(GEN pol, long s) { GEN bnf, nf, lvunit, Gid, sgnu; long isA4; if (checkS4data(pol)) return pol; bnf = Buchall(pol, nf_FORCE, MEDDEFAULTPREC); nf = bnf_get_nf(bnf); Gid = makeGid(nf); lvunit = makevunits(bnf); isA4 = Z_issquare(nf_get_disc(nf)); sgnu = (s != -1 && nf_get_r1(nf) == 3)? nfsign(nf, lvunit): gen_0; return mkvecn(5, bnf, lvunit, Gid, sgnu, mkvecsmall(isA4)); } static GEN S4_get_disc(GEN S) { return nf_get_disc(bnf_get_nf(gel(S,1))); } static int cmp2(void *E,GEN x,GEN y) { (void)E; return signe(gel(x,2))==0 ? 1: signe(gel(y,2))==0 ? -1: cmpii(gel(x,2), gel(y,2)); } /* Find quartic A4 or S4-extensions of Q with resolvent pol and square root of * norm of relative discriminant = L; disc(K/Q) = L^2 nfdisc(pol). * Here s = -1 or (0, 1, 2) */ static GEN makeA4S4(GEN pol, GEN L, long s) { GEN DATA = S4data(pol, s), bnf = gel(DATA, 1), nf = bnf_get_nf(bnf); GEN lvunit = gel(DATA, 2), Gid = gel(DATA, 3), sgnunit = gel(DATA, 4); GEN sgnal0 = NULL, vI, V, P, L2; long nu, l, c, c1, i, j, k, v2, r1 = nf_get_r1(nf), isA4 = gel(DATA, 5)[1]; if (s != -1 && ((r1 == 1 && s != 1) || (r1 == 3 && s == 1))) return NULL; if (typ(L) == t_VEC) { P = gel(L,1); L = gel(L,2); v2 = vali(L); } else { GEN fa; v2 = vali(L); if (v2 > 4) return NULL; fa = Z_factor(L); if (!ZV_is_1(gel(fa,2), v2? 2: 1)) return NULL; P = gel(fa,1); } L2 = v2? shifti(L, -v2): L; vI = S4makeid(bnf, isA4, v2, P); if (!vI) return NULL; l = lg(vI); nu = lg(lvunit) - 1; V = cgetg(RgVV_nb(vI) * nu + 1, t_VEC); c = 1; c1 = 0; for (k = 1; k < l; k++) /* l = 2 or 3 */ { GEN I = gel(vI, k); int norm1 = k == 1 && equali1(L2); for (j = 1; j < lg(I); j++) { GEN ideal = gmael(I, j, 1), al0 = gmael(I, j, 2); if (s != -1 && r1 == 3) sgnal0 = nfsign(nf, al0); for (i = norm1? 2 : 1; i <= nu; i++) { GEN T, a1, a2, a3, a; if (sgnal0 && !!s == zv_equal0(Flv_add(sgnal0, gel(sgnunit,i), 2))) continue; a = nfmul(nf, al0, gel(lvunit, i)); if (v2 != quadcubpow(bnf, Gid, ideal, a) + (k == 1? 0 : 1)) continue; if (isA4 && norm1) c1++; a = nf_to_scalar_or_alg(nf, a); T = QXQ_charpoly(a, nf_get_pol(nf), 0); a1 = gel(T,4); a2 = gel(T,3); a3 = negi(gel(T,2)); T = mkpoln(5, gen_1, gen_0, shifti(a1,1), mulsi(-8,sqrti(a3)), subii(sqri(a1), shifti(a2, 2))); gel(V, c++) = isA4? polredabs(T): T; } } } if (c == 1) return NULL; setlg(V, c); return isA4? A4clean3(V, c1): V; } /* A4 fields of square root discriminant = N and "signature" s */ static GEN makeA4_i(GEN N2, GEN field, long s) { GEN N, v; if (s == 1 || !Z_issquareall(N2, &N)) return NULL; if (field) { GEN D = checkfield(field, 3), d, cond; if (!Z_issquareall(D, &d) || !(cond = divide(N,d)) || !(v = makeA4S4(field, cond, s))) return NULL; } else { GEN D = divisors(N); long i, cv, l = lg(D); v = cgetg(l, t_VEC); for (i = cv = 1; i < l; i++) { GEN w, m = gel(D, i), n = gel(D, l-i), C = makeC3_f(m); long j, c, lC = lg(C); for (j = c = 1; j < lC; j++) if ((w = makeA4S4(gel(C,j), n, s))) gel(C,c++) = w; if (c == 1) continue; setlg(C,c); gel(v,cv++) = shallowconcat1(C); } setlg(v,cv); v = myshallowconcat1(v); } return v; } static GEN makeA4(GEN N, GEN field, long s) { GEN v = makeA4_i(N, field, maxss(s, -1)); return v? sturmseparate(v, s, 4): NULL; } static GEN makeS4_i(GEN N, GEN field, long s) { GEN v; if (field) { GEN q, f, D = checkfield(field, 3); if (!(q = divide(N, D))) return NULL; setsigne(q, s == 2? -signe(q): 1); if (!Z_issquareall(q, &f) || !(v = makeA4S4(field, f, s))) return NULL; } else { GEN f, M = divisors(N); long i, cv, l = lg(M); v = cgetg(l, t_VEC); if (!odd(s)) s = 0; for (i = cv = 1; i < l; i++) if (Z_issquareall(gel(M, l-i), &f)) { GEN w, D; long j, c, lD; if (!(D = makeDL(3, gel(M,i), NULL, s))) continue; lD = lg(D); for (j = c = 1; j < lD; j++) if ((w = makeA4S4(gel(D,j), f, s))) gel(D, c++) = w; if (c == 1) continue; setlg(D, c); gel(v, cv++) = shallowconcat1(D); } if (cv == 1) return NULL; setlg(v,cv); v = shallowconcat1(v); } return v; } static GEN makeS4(GEN N, GEN field, long s) { GEN v = makeS4_i(N, field, maxss(s, -1)); return v? sturmseparate(v, s, 4): NULL; } static long gal_get_order(GEN G) { return degpol(gal_get_pol(G)); } /* P is monic */ static GEN makeA4S4resolvent(GEN P, long flag) { GEN R, a0 = gel(P,2), a1 = gel(P,3), a2 = gel(P,4), a3 = gel(P,5); GEN b0 = subii(mulii(a0, subii(shifti(a2,2), sqri(a3))), sqri(a1)); GEN b1 = subii(mulii(a3, a1), shifti(a0,2)); R = mkpoln(4, gen_1, negi(a2), b1, b0); setvarn(R, varn(P)); R = polredabs(R); return flag? mkvec2(R, sqrti(divii(nfdisc(P), nfdisc(R)))): R; } static GEN A4S4_fa(GEN DATA, GEN fa, long cond, long s) { pari_sp av = avma; GEN w, P = gel(fa,1), E = gel(fa,2); if (odd(cond)) { if (!zv_is_1(E, 1)) return gc_NULL(av); } else if (E[1] > 4 || !zv_is_1(E, 2)) return gc_NULL(av); if (!(w = makeA4S4(DATA, mkvec2(Flv_to_ZV(P), utoipos(cond)), s))) return gc_NULL(av); return gerepilecopy(av, w); } static GEN nflist_A4S4_worker_i(GEN P3, GEN X, GEN Xinf, long s) { GEN v, w, F, DATA = S4data(P3, s), D3 = absi_shallow(S4_get_disc(DATA)); long i, c, f, linf, limf = floorsqrtdiv(X, D3); linf = cmpii(Xinf, shifti(D3, 2)) >= 0? ceilsqrtdiv(Xinf, D3): 1; v = cgetg(limf - linf + 2, t_VEC); F = vecfactoru_i(linf, limf); for (f = linf, i = c = 1; f <= limf; f++, i++) if ((w = A4S4_fa(DATA, gel(F,i), f, s))) gel(v, c++) = w; setlg(v, c); return myshallowconcat1(v); } GEN nflist_A4S4_worker(GEN P3, GEN X, GEN Xinf, GEN gs) { pari_sp av = avma; return gerepilecopy(av, nflist_A4S4_worker_i(P3, X, Xinf, gs[1])); } static GEN makeA4S4vec(long A4, GEN X, GEN Xinf, GEN field, long s) { long snew = s == -2? -1: s; GEN v; if (field) { GEN D = checkfield(field, 3); long sD = signe(D); if (A4 != Z_issquare(D) || abscmpii(D, X) > 0 || (sD > 0 && snew == 1) || (sD < 0 && !odd(snew))) return NULL; v = nflist_A4S4_worker_i(field, X, Xinf, snew); } else { v = A4? makeC3vec(X, gen_1, NULL, 0) : makeS3vec(X, gen_1, NULL, odd(snew)? snew: 0); if (!v) return NULL; v = nflist_parapply("_nflist_A4S4_worker", mkvec3(X,Xinf,mkvecsmall(snew)), v); v = myshallowconcat1(v); } return sturmseparate(v, s, 4); } /**********************************************************************/ /* C5 */ /**********************************************************************/ /* elements in B have the same norm */ static void C5cleanB(GEN nf, GEN aut, GEN B) { long l = lg(B), c, i, j, k; GEN W = const_vecsmall(l - 1, 1); for (i = c = 1; i < l; i++) { GEN bi, d; if (!W[i]) continue; gel(B, c++) = gel(B,i); bi = Q_remove_denom(nfinv(nf, gel(B,i)), &d); /*1/b = bi / d */ for (j = 1; j <= 3; j++) { bi = galoisapply(nf, aut, bi); for (k = i + 1; k < l; k++) { GEN a; if (!W[k]) continue; a = nfmuli(nf, bi, gel(B,k)); /* bi/d * B[k] has norm 1 or -1 */ if (absequalii(content(a), d)) { W[k] = 0; break; } } } } setlg(B, c); } static GEN makepolC5(GEN nf, GEN e, GEN b, GEN aut) { GEN b1 = galoisapply(nf, aut, b), t1 = nfmuli(nf, b, b1); GEN b2 = galoisapply(nf, aut, b1); GEN t2 = nfmuli(nf, t1, nfmuli(nf, b1, b2)); GEN v = cgetg(8, t_POL); v[1] = evalsigne(1) | evalvarn(0); gel(v, 7) = gen_1; gel(v, 6) = gen_0; gel(v, 5) = mulsi(-10, e); gel(v, 4) = mulsi(-5, mulii(e, nftrace(nf, t1))); gel(v, 3) = mului(5, mulii(e, subii(e, nftrace(nf,t2)))); gel(v, 2) = mulii(negi(e), nftrace(nf, nfmuli(nf, t1, t2))); if (umodiu(e, 5)) v = ZX_translate(v, gen_m1); return ZX_Z_divexact(ZX_z_unscale(v, 5), utoipos(3125)); } /* b a pr-unit; multiply by a unit so that z u = 1 (mod pr5^2) */ static GEN C5prim(GEN nf, GEN pr5, GEN z, GEN eps, GEN b) { GEN pol = nf_get_pol(nf); long k, j; if (typ(b) != t_POL) b = scalarpol_shallow(b, varn(pol)); for (j = 0; j <= 1; j++) { GEN g = j ? b : ZXQ_mul(b, eps, pol); for (k = 0; k <= 9; k++) { if (idealval(nf, gsubgs(g, 1), pr5) > 1) return g; if (k < 9) g = ZXQ_mul(g, z, pol); } } pari_err_BUG("C5prim"); return NULL; /* LCOV_EXCL_LINE */ } static GEN C5bnf() { GEN bnf = Buchall(polcyclo(5,1), nf_FORCE, MEDDEFAULTPREC), nf = bnf_get_nf(bnf); GEN aut = poltobasis(nf, pol_xn(2, 1)); GEN p5 = idealprimedec_galois(nf, utoipos(5)); return mkvec3(bnf, aut, p5); } static GEN polsubcycloC5_i(GEN N, GEN T) { GEN bnf, nf, pol, B, aut, z, eps, p5, N5, P; long fl5, i, l, v; if (!checkcondCL(N, 5, &P)) return NULL; if (typ(N) == t_VEC) N = gel(N,1); if (!T) T = C5bnf(); bnf = gel(T, 1); nf = bnf_get_nf(bnf); pol = nf_get_pol(nf); aut = gel(T, 2); p5 = gel(T, 3); v = varn(pol); z = monomial(gen_m1, 1, v); /* tu */ eps = deg1pol_shallow(gen_1, gen_1, v); /* fu */ N5 = divis_rem(N, 25, &fl5); if (fl5) N5 = N; /* fl5 is set if 5 \nmid N */ N5 = mkvec2(N5, P2fa(P)); B = bnfisintnorm(bnf, N5); l = lg(B); for (i = 1; i < l; i++) gel(B, i) = C5prim(nf, p5, z, eps, gel(B, i)); if (fl5) { B = matalgtobasis(nf, B); C5cleanB(nf, aut, B); } else { GEN b5 = mkpoln(4, gen_m1, gen_1, gen_1, gen_m1); /* norm 25 */ setvarn(b5, v); B = matalgtobasis(nf, RgXQV_RgXQ_mul(B, b5, pol)); } for (i = 1; i < l; i++) gel(B, i) = makepolC5(nf, N, gel(B, i), aut); return B; } static GEN makeC5(GEN N, GEN field, long s) { GEN sqN, v; checkfield_i(field, 1); if (s > 0 || !Z_ispowerall(N, 4, &sqN) || !(v = polsubcycloC5_i(sqN, NULL))) return NULL; return s == -2? vecs(3,v): v; } GEN nflist_C5_worker(GEN N, GEN T) { pari_sp av = avma; GEN v = polsubcycloC5_i(N, T); if (!v) { set_avma(av); return cgetg(1, t_VEC); } return gerepilecopy(av, v); } static GEN makeC5vec(GEN X, GEN Xinf, GEN field, long s) { GEN v, F, bnfC5; long x, xinf, i, l; checkfield_i(field, 1); if (s > 0) return NULL; xinf = ceilsqrtn(Xinf, 4); x = floorsqrtn(X, 4); bnfC5 = C5bnf(); if (!odd(xinf)) xinf++; if (!odd(x)) x--; F = vecfactoroddu_i(xinf, x); l = lg(F); for (i = 1; i < l; i++) gel(F,i) = mkvec2(utoipos(xinf + ((i - 1) << 1)), zm_to_ZM(gel(F,i))); v = nflist_parapply("_nflist_C5_worker", mkvec(bnfC5), F); v = myshallowconcat1(v); return s == -2? vecs(3, v): v; } /**********************************************************************/ /* CL (ell prime) */ /**********************************************************************/ /* polredabs iff |nfdisc(pol)| = N */ static GEN ZX_red_disc(GEN pol, GEN N) { GEN d, B = nfbasis(mkvec2(pol, utoipos(500000)), &d); return absequalii(d, N)? polredabs(mkvec2(pol,B)): NULL; } /* polredabs iff Xinf <= |nfdisc(pol)| <= X */ static GEN ZX_red_disc2(GEN pol, GEN Xinf, GEN X) { GEN d, B = nfbasis(mkvec2(pol, utoipos(500000)), &d); if (abscmpii(d, X) > 0 || abscmpii(d, Xinf) < 0) return NULL; return polredabs(mkvec2(pol,B)); } /* make CL(f^(ell-1), 0) */ static GEN makeCL_f(long ell, GEN F) { GEN bnf, P, f = typ(F) == t_VEC? gel(F,1): F; if (!checkcondCL(F, ell, &P)) return cgetg(1,t_VEC); bnf = bnfY(pol_x(1)); P = Pell2prfa(bnf_get_nf(bnf), P, ell, f); return mybnrclassfield(bnf, P, ell); } /* ell odd prime */ static GEN makeCL(long ell, GEN N, GEN field, long s) { GEN F, v; checkfield_i(field, 1); if (s > 0 || !Z_ispowerall(N, ell-1, &F)) return NULL; v = makeCL_f(ell, F); return s != -2? v: vecs((ell-1)/2, v); } static GEN makeCLresolvent(long ell, GEN pol, long flag) { if (!odd(flag)) return pol_x(0); return mkvec2(pol_x(0), sqrtnint(checkfield(pol, ell), ell-1)); } static GEN RgXV_polred(GEN x) { pari_APPLY_same(polredabs(gel(x,i))); } GEN nflist_CL_worker(GEN f, GEN bnf, GEN gell) { pari_sp av = avma; return gerepileupto(av, RgXV_polred(mybnrclassfield(bnf, f, gell[1]))); } static GEN makeCLvec(long ell, GEN X, GEN Xinf, GEN field, long s) { long em1 = ell - 1, x, xinf, f; GEN v, bnf, F; checkfield_i(field, 1); if (s > 0) return NULL; xinf = ceilsqrtn(Xinf, em1); x = floorsqrtn(X, em1); bnf = bnfY(pol_x(1)); F = cgetg(x - xinf + 2, t_VEC); for (f = xinf; f <= x; f++) gel(F, f - xinf + 1) = utoipos(f); v = nflist_parapply("_nflist_CL_worker", mkvec2(bnf, mkvecsmall(ell)), F); v = myshallowconcat1(v); return s == -2? vecs(em1>>1, v): v; } /**********************************************************************/ /* DL (ell prime) */ /**********************************************************************/ /* For metacyclic groups; assume G is Galois and non-abelian */ static GEN getpol(GEN nf, GEN T) { GEN G = galoisinit(rnfequation(nf, T), NULL); return galoisfixedfield(G, vecsplice(gal_get_gen(G), 1), 1, 0); } static GEN makeDL(long ell, GEN N, GEN field, long s) { GEN v, vD, F = N; long i, l, c, si = 0, pow = (ell - 1) >> 1; if (s > 0 && s != pow) return NULL; if (ell != 3 && !Z_ispowerall(N, pow, &F)) return NULL; if (field) { GEN q, D = checkfield(field, 2); si = signe(D); if ((s > 0 && si > 0) || (!s && si < 0)) return NULL; D = absi_shallow(D); if (!(q = divide(F, D))) return NULL; vD = mkvec2(q, D); } else vD = divisors(F); l = lg(vD); v = cgetg(2 * l, t_VEC); for (i = 2, c = 1; i < l; i++) /* omit 1 */ { GEN LD, f, M = gel(vD, i); int p, m; long j; if (!Z_issquareall(gel(vD, l-i), &f)) continue; is_fundamental_pm(M, s, &p, &m); if (si < 0) p = 0; if (si > 0) m = 0; if (!(LD = fund_pm(M, p, m))) continue; for (j = 1; j < lg(LD); j++) { GEN D = gel(LD, j), R, bnf, P, G, pol; long k, lR; if (!checkcondDL(D, f, ell, &P)) continue; pol = Y2m(gel(LD,j)); bnf = bnfY(pol); G = mkvec2(galoisinit(pol,NULL), gen_2); P = Pell2prfa(bnf_get_nf(bnf), P, ell, f); R = mybnrclassfield_X(bnf, P, ell, NULL, NULL, G); lR = lg(R); if (lR == 1) continue; /* L/Q degree ell subfield of R; d(L) = F^pow, F = D f^2 */ for (k = 1; k < lR; k++) gel(R,k) = polredabs(getpol(bnf, gel(R,k))); gel(v, c++) = R; } } if (c == 1) return NULL; setlg(v, c); return sturmseparate(myshallowconcat1(v), s, ell); } /* ell >= 5 prime */ static GEN makeDLresolvent(long ell, GEN pol, long flag) { GEN Dpow = checkfield(pol, ell), D, DF, F; long d4, pow = (ell - 1) >> 1, si = signe(Dpow); D = si > 0 ? sqrtnint(Dpow, pow) : negi(sqrtnint(negi(Dpow), pow)); d4 = Mod4(D); if (d4 == 3 || (d4 == 0 && si > 0 && pol2s(pol))) D = negi(D); else if (d4 == 2) D = shifti(D, 2); DF = coredisc2(D); D = quadpoly_i(gel(DF, 1)); F = gel(DF, 2); return flag? mkvec2(D, F): D; } GEN nflist_DL_worker(GEN P2, GEN X1pow, GEN X0pow, GEN X2, GEN Xinf2, GEN gell) { pari_sp av = avma; GEN X, Xinf, G, D, Da, V, bnf = bnfY(P2), nf = bnf_get_nf(bnf); long f, c, limf, linf, ell = gell[1]; G = mkvec2(galoisinit(nf_get_pol(nf),NULL), gen_2); D = bnf_get_disc(bnf); Da = absi_shallow(D); limf = floorsqrtdiv(X1pow, Da); linf = cmpii(X0pow, shifti(Da, 2)) >= 0? ceilsqrtdiv(X0pow, Da): 1; V = cgetg(limf + 1, t_VEC); /* K/Q degree l with D_l Galois closure L/Q and k/Q quadratic resolvent * Then d_k = D, d_K = D^(l-1)/2 f^(l-1), d_L = D^l f^(2l-2). * Want d_K in [Xinf,X], i.e. d_L in D [Xinf^2,X^2] */ Xinf = mulii(Da, Xinf2); X = mulii(Da, X2); for (f = linf, c = 1; f <= limf; f++) { pari_sp av2 = avma; GEN P, R, F = utoipos(f); long lR, k; if (!checkcondDL(D, F, ell, &P)) { set_avma(av2); continue; } P = Pell2prfa(nf, P, ell, F); R = mybnrclassfield_X(bnf, P, ell, X, Xinf, G); lR = lg(R); if (lR == 1) { set_avma(av2); continue; } for (k = 1; k < lR; k++) gel(R,k) = polredabs(getpol(bnf, gel(R,k))); gel(V, c++) = R; } setlg(V,c); return gerepilecopy(av, myshallowconcat1(V)); } static GEN makeDLvec(long ell, GEN X, GEN Xinf, GEN field, long s) { GEN v, X1pow, X0pow, V2; long pow = (ell - 1) >> 1; checkfield_i(field, 2); if (s > 0 && s != pow) return NULL; if (s == pow) s = 1; X1pow = sqrtnint(X, pow); X0pow = gceilsqrtn(Xinf, pow); V2 = field? mkvec(field): makeC2vec(X1pow, gen_1, NULL, s == -2? -1: s); if (!V2) return NULL; v = nflist_parapply("_nflist_DL_worker", mkvec5(X1pow, X0pow, sqri(X), sqri(Xinf), mkvecsmall(ell)), V2); return sturmseparate(myshallowconcat1(v), s, ell); } /**********************************************************************/ /* D9 */ /**********************************************************************/ /* disc = D^4 g^2 f^6 (quad. subfield: D, cubic subfield: D g^2) */ static GEN makeD9(GEN N, GEN field, long s) { GEN v, LD, D, D4; long i, j, si; if ((s > 0 && s != 4) || !Z_issquare(N)) return NULL; if (field) { D = checkfield(field, 2); D4 = powiu(D, 4); si = signe(D); if ((s > 0 && si > 0) || (s == 0 && si < 0) || !dvdii(N, D4)) return NULL; LD = mkvec(field); } else { GEN t = divisorsdisc(cored(N, 4), s); long l = lg(t); LD = cgetg(l, t_VEC); for (j = 1; j < l; j++) gel(LD, j) = quadpoly_i(gel(t, j)); } v = cgetg(1, t_VEC); for (i = 1; i < lg(LD); i++) { GEN bnf = bnfY(gel(LD, i)), Q, F, G; G = mkvec2(galoisinit(bnf, NULL), gen_2); D4 = powiu(bnf_get_disc(bnf), 4); Q = divii(N, D4); F = divisors(cored(Q, 6)); for (j = 1; j < lg(F); j++) { GEN R = mybnrclassfield_X(bnf, gel(F,j), 9, NULL, NULL, G); long k; for (k = 1; k < lg(R); k++) { GEN pol = getpol(bnf, gel(R, k)); if (pol && (pol = ZX_red_disc(pol, N))) v = shallowconcat(v, pol); } } } return sturmseparate(v, s, 9); } GEN nflist_D9_worker(GEN P2, GEN X, GEN Xinf) { pari_sp av = avma; GEN v, bnf = bnfY(P2), D2 = bnf_get_disc(bnf); GEN G = mkvec2(galoisinit(bnf, NULL), gen_2); long l, f, c; l = floorsqrtndiv(X, powiu(D2, 4), 6) + 1; v = cgetg(l, t_VEC); c = 1; for (f = 1; f < l; f++) { GEN R = mybnrclassfield_X(bnf, utoipos(f), 9, NULL, NULL, G); long k, ci, lR = lg(R); for (k = ci = 1; k < lR; k++) { GEN pol = getpol(bnf, gel(R, k)); if ((pol = ZX_red_disc2(pol, Xinf, X))) gel(R, ci++) = pol; } if (ci > 1) { setlg(R, ci); gel(v, c++) = R; } } setlg(v,c); return gerepilecopy(av, myshallowconcat1(v)); } static GEN makeD9resolvent(GEN G, long flag) { GEN R = polredabs(galoisfixedfield(G, vecsplice(gal_get_gen(G), 2), 1, 0)); return condrel(R, gal_get_pol(G), flag); } static GEN makeD9vec(GEN X, GEN Xinf, GEN field, long s) { GEN X1pow, V2, v; checkfield_i(field,2); if (s > 0 && s != 4) return NULL; if (s == 4) s = 1; X1pow = sqrtnint(X, 4); V2 = field? mkvec(field): makeC2vec(X1pow, gen_1, NULL, s == -2? -1: s); if (!V2) return NULL; v = nflist_parapply("_nflist_D9_worker", mkvec2(X, Xinf), V2); return sturmseparate(myshallowconcat1(v), s, 9); } /**********************************************************************/ /* Metacyclic C_a \rtimes C_ell groups with ell prime and a | ell - 1 */ /* includes F5 = M20, M21, and M42 */ /**********************************************************************/ /* C_a resolvent field. */ static GEN nfmakenum(long n, long t, GEN N, GEN field, long s); static GEN nfmakevecnum(long n, long t, GEN X, GEN Xinf, GEN field, long s); static GEN MgenF(long ell, GEN d, GEN Fn, long *vell) { GEN F; if (umodiu(d, ell)) *vell = 0; else { *vell = Z_lval(Fn, ell) % (ell - 1); if (*vell) Fn = diviiexact(Fn, powuu(ell, *vell)); } return Z_ispowerall(Fn, ell - 1, &F)? F: NULL; } static int okgal(GEN P, GEN g) { GEN G = polgalois(P, DEFAULTPREC); return equaliu(gel(G,1), g[1]) && equalis(gel(G,2), g[2]) && equaliu(gel(G,3), g[3]); } static int okgal1(GEN P, long d) { GEN G = polgalois(P, DEFAULTPREC); return equaliu(gel(G,1), d); } static int okgal2(GEN P, long d, long p) { GEN G = polgalois(P, DEFAULTPREC); return equaliu(gel(G,1), d) && equalis(gel(G,2), p); } static int ok_s(GEN P, long s) { return s < 0 || pol2s(P) == s; } /* a | ell - 1, (Z/aZ)^* cyclic, F^(ell-1)*D^((ell-1)/a) */ static GEN makeMgen(long ell, long a, GEN N, GEN field, long s) { GEN v, Fn, F; long i, lv, c, vell, deg = ell * a, drel = (ell - 1) / a; if (field) { GEN d = absi_shallow(checkfield(field, a)); Fn = gdiv(N, powiu(d, drel)); if (typ(Fn) != t_INT || !(F = MgenF(ell, d, Fn, &vell))) return NULL; v = mkvec(mkvec3(mkvec(field), F, utoi(vell))); } else { long s2 = maxss(s, -1); v = divisors(cored(N, drel)); lv = lg(v); for (i = c = 1; i < lv; i++) { GEN R, d = gel(v, i); Fn = diviiexact(N, powiu(d, drel)); if ((F = MgenF(ell, d, Fn, &vell)) && (R = nfmakenum(a, 1, d, NULL, s2))) /* C_a, disc d */ gel(v, c++) = mkvec3(R, F, utoi(vell)); } setlg(v, c); } lv = lg(v); for (i = 1; i < lv; i++) { GEN T = gel(v, i), R = gel(T, 1), F0 = gel(T, 2); long vell = itou(gel(T, 3)), lR = lg(R), j; for (j = c = 1; j < lR; j++) { GEN nf = nfY(gel(R,j)), F = F0, K, G; long k, ck, l; if (vell) { /* ell ramified in nf */ long eell, q; GEN pell = getpell(nf, ell, &eell); q = (ell - 1) / eell; if (vell % q) continue; F = idealmul(nf, F, idealpows(nf, pell, vell / q)); } G = mkvec2(galoisinit(nf, NULL), gen_2); K = mybnrclassfield_X(Buchall(nf, nf_FORCE, MEDDEFAULTPREC), F, ell, NULL, NULL, G); l = lg(K); for (k = ck = 1; k < l; k++) { GEN q = getpol(nf, gel(K, k)); if ((deg == 21 || okgal1(q, deg)) && /* automatic for M21;FIXME */ (q = ZX_red_disc(q, N))) gel(K, ck++) = q; } if (ck > 1) { setlg(K, ck); gel(R,c++) = K; } } setlg(R, c); gel(v, i) = myshallowconcat1(R); } return sturmseparate(gtoset_shallow(myshallowconcat1(v)), s, ell); } /* (ell,a) = (5,4), (7,3) or (7,6) */ static GEN makeMgenresolvent(long ell, long a, GEN pol, long flag) { GEN Dpow = checkfield(pol, ell), G, R, DR, F2, nf, pell, F; G = galoissplittinginit(pol, utoipos(a*ell)); if (gal_get_order(G) != a * ell) pari_err_BUG("nfresolvent [Galois group]"); R = polredabs(galoisfixedfield(G, vecsplice(gal_get_gen(G), 2), 1, 0)); if (!flag) return R; DR = nfdisc(R); if (ell == 5 && a == 4) { F2 = sqrti(divii(Dpow, DR)); if (!Z_issquareall(F2, &F)) { long e; F2 = divis(F2, 5); if (!Z_issquareall(F2, &F)) pari_err_BUG("nfresolvent [F5]"); nf = nfinit(R, MEDDEFAULTPREC); pell = getpell(nf, 5, &e); if (e == 4) pell = idealsqr(nf, pell); F = idealmul(nf, F, pell); } } else { /* ell == 7 && (a == 3 || a == 6) */ long v; if (a == 3) DR = sqri(DR); if (!Z_issquareall(divii(Dpow, DR), &F2)) pari_err_BUG("nfresolvent [M21/M42]"); /* F2 = F^3 or 7F^3 or 7^2F^3 */ v = Z_lval(F2, 7) % 3; if (v) F2 = divii(F2, powuu(7, v)); if (!Z_ispowerall(F2, 3, &F)) pari_err_BUG("nfresolvent [M21/M42]"); if (v) { long e; nf = nfinit(R, DEFAULTPREC); pell = getpell(nf, 7, &e); if (e == 6) v *= 2; F = idealmul(nf, F, idealpows(nf, pell, v)); } } return mkvec2(R, F); } GEN nflist_Mgen_worker(GEN field, GEN X, GEN Xinf, GEN T) { pari_sp av = avma; GEN v, Fn, pell, lpow, bnf = bnfY(field), D = bnf_get_disc(bnf); GEN G = mkvec2(galoisinit(bnf, NULL), gen_2); long ell = T[1], drel = T[2], deg = T[3], c, e; long vd = Z_lval(D, ell), limf, f; Fn = divii(X, drel == 1 ? absi_shallow(D) : sqri(D)); limf = floorsqrtn(Fn, ell - 1); pell = getpell(bnf, ell, &e); /* e | a */ lpow = powuu(ell, (ell - 1) / e); v = cgetg(limf + 1, t_VEC); for (f = c = 1; f <= limf; f++) { GEN F = utoipos(f), K; long k, ci, lK; if (vd) { GEN fn = powuu(f, ell - 1); long imax = minss(e - 1, logint(divii(Fn, fn), lpow)); F = mkcol2(F, gmulgu(idealpows(bnf, pell, imax), f)); } K = mybnrclassfield_X(bnf, F, ell, NULL, NULL, G); lK = lg(K); for (k = ci = 1; k < lK; k++) { GEN q = getpol(bnf, gel(K, k)); if (degpol(q) == ell && (deg == 21 || okgal1(q, deg)) && /* FIXME */ (q = ZX_red_disc2(q, Xinf, X))) gel(K, ci++) = q; } if (ci > 1) { setlg(K, ci); gel(v, c++) = K; } } setlg(v, c); v = gtoset_shallow(myshallowconcat1(v)); return gerepilecopy(av, v); } /* (a,ell) = (3,7), (4,5) or (6,7) */ static GEN makeMgenvec(long ell, long a, GEN X, GEN Xinf, GEN field, long s) { GEN L, v, T; long drel = (ell - 1) / a; if (field) { if (degpol(field) != a || !okgal2(field, a, a==3? 1: -1)) pari_err_TYPE("makeMgenvec [field]", field); L = mkvec(field); } else L = nfmakevecnum(a, 1, drel == 1? X: sqrti(X), gen_1, NULL, maxss(s,-1)); if (!L) return NULL; T = mkvecsmall3(ell, drel, ell * a); v = nflist_parapply("_nflist_Mgen_worker", mkvec3(X, Xinf, T), L); return sturmseparate(myshallowconcat1(v), s, ell); } /**********************************************************************/ /* A5 by table lookup */ /**********************************************************************/ /* V a vector of [T, n] sorted wrt t_INT n. Return elts with Xinf <= n <= X. * If flag = 0 return only the T's. */ static GEN vecslicebyX(GEN V, GEN Xinf, GEN X, long flag) { long l = lg(V), i = 1, c; GEN W; if (cmpii(Xinf,gmael(V,1,2)) > 0) /* frequent special case */ { i = gen_search(V, mkvec2(NULL,Xinf), NULL, &cmp2); if (i > 0) /* found in list, rewind to first occurence */ { while (i > 1 && equalii(gmael(V, i-1, 2), Xinf)) i--; } else /* not in list */ i = -i; } W = cgetg(l, t_VEC); for (c = 1; i < l; i++) { GEN C = gmael(V, i, 2), x; if (isintzero(C)) /* marker for incomplete slice */ { GEN B = gmael(V, i-1, 2); if (equalii(B, X)) break; pari_err_DOMAIN("nflist(A5)", "sqrt(N)", ">", B, X); } if (cmpii(C, X) > 0) break; x = RgV_to_RgX(gmael(V, i, 1), 0); gel(W, c++) = flag ? mkvec2(x, gmael(V, i, 2)): x; } setlg(W, c); return W; } /* assume 1 <= t < 1000, 1 <= 2s <= n < 100 */ static GEN nflistfile(const char *suf, long n, long t, long s, long u) { pariFILE *F; GEN z; char *f = stack_sprintf("%s/nflistdata/%ld/%ld/%ld%s/%ld", pari_datadir, n, t, s, suf, u); F = pari_fopengz(f); if (!F) pari_err_FILE("nflistdata file",f); z = gp_readvec_stream(F->file); pari_fclose(F); return z; } static GEN A5file(const char *suf, long s, long u) { return nflistfile(suf, 5, 4, s, u); } /* If flag = 0 return only the T's. */ static GEN vecsliceA5all(const char *suf, long s, ulong sl, GEN Xinf, GEN X, long flag) { long i, l; GEN V; ulong uinf = itou(divis(Xinf, sl)); ulong usup = itou(divis(X, sl)); l = usup-uinf+2; V = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(V, i) = vecslicebyX(A5file(suf, s, uinf+i-1), Xinf, X, flag); return shallowconcat1(V); } static GEN vecsliceA5(long s, GEN Xinf, GEN X, long flag) { return vecsliceA5all("", s, 100000, Xinf, X, flag); } static GEN vecsliceA5cond(long s, GEN Xinf, GEN X, long flag) { return vecsliceA5all("cond", s, 100000, Xinf, X, flag); } static GEN A5vec(GEN X, GEN Xinf, long s, long fl) { GEN L1, L5; const char *suf = fl? "cond": ""; L1 = L5 = NULL; if (s <= 0) L5 = vecsliceA5all(suf, 0, 100000, Xinf, X, fl); if (s) L1 = vecsliceA5all(suf, 2, 100000, Xinf, X, fl); switch (s) { case 2: return L1; case 0: return L5; case -1: return shallowconcat(L1, L5); default: return mkvec3(L5, cgetg(1, t_VEC), L1); } } static GEN makeA5_i(GEN N, long s, long fl) { return s == 1 ? NULL: A5vec(N, N, s, fl); } static GEN makeA5(GEN N, long s) { GEN rN; if (!Z_issquareall(N, &rN)) return NULL; return makeA5_i(rN, s, 0); } static GEN makeA5cond(GEN N, long s) { return makeA5_i(N, s, 1); } /* D a sorted t_VECSMALL of conductors; return all [T, d] with d = D[i] * for some i and Gal(T) = A5 with s complex places */ GEN veccond_to_A5(GEN D, long s) { pari_sp av = avma; long l, j, lD = lg(D), c = 1; GEN W, V = vecsliceA5cond(s, utoi(D[1]), utoi(D[lD-1]), 1); l = lg(V); W = cgetg(lD, t_VEC); for (j = 1; j < lD; j++) { GEN Xinf = utoi(D[j]); long i = gen_search(V, mkvec2(NULL, Xinf), NULL, &cmp2); if (i > 0) /* found in list, rewind to first occurence */ { long ii; while (i > 1 && equalii(gmael(V, i-1, 2), Xinf)) i--; for (ii = i; ii < l && equaliu(gmael(V,ii,2),D[j]); ii++); gel(W, c++) = vecslice(V, i, ii-1); } } setlg(W, c); return gerepilecopy(av, shallowconcat1(W)); } /* Sextic resolvent of A5 field */ static GEN makeA5resolvent(GEN pol, long flag) { GEN R = cgetg(9, t_POL), D = ZX_disc(pol), c, d, e, f, v; GEN c2, d2, e2, c4, df; pol = RgX_translate(pol, gdivgs(gel(pol, 6), -5)); c = gdivgu(gel(pol, 5), 10); d = gdivgu(gel(pol, 4), 10); e = gdivgu(gel(pol, 3), 5); f = gel(pol, 2); c2 = gsqr(c); c4 = gsqr(c2); d2 = gsqr(d); e2 = gsqr(e); df = gmul(d, f); R[1] = evalsigne(1)|evalvarn(0); gel(R, 8) = gen_1; gel(R, 7) = gen_0; gel(R, 6) = gmulsg(-25, gadd(e, gmulsg(3, c2))); gel(R, 5) = gen_0; v = cgetg(6, t_VEC); gel(v, 1) = gmulsg(15, c4); gel(v, 2) = gmulsg(8, gmul(c, d2)); gel(v, 3) = gmulsg(-2, gmul(c2, e)); gel(v, 4) = gmulsg(3, e2); gel(v, 5) = gmulsg(-2, df); gel(R, 4) = gmulsg(125, vecsum(v)); gel(R, 3) = sqrti(D); v = cgetg(11, t_VEC); gel(v, 1) = gmulsg(-25, gmul(c2, c4)); gel(v, 2) = gmulsg(-40, gmul(gmul(c, c2), d2)); gel(v, 3) = gmulsg(-16, gsqr(d2)); gel(v, 4) = gmulsg(35, gmul(c4, e)); gel(v, 5) = gmulsg(28, gmul(c, gmul(d2, e))); gel(v, 6) = gmulsg(-11, gsqr(gmul(c, e))); gel(v, 7) = gmul(e, e2); gel(v, 8) = gmulsg(-2, gmul(c2, df)); gel(v, 9) = gmulsg(-2, gmul(e, df)); gel(v, 10) = gmul(c, gsqr(f)); gel(R, 2) = gmulsg(625, vecsum(v)); R = polredabs(R); return odd(flag)? mkvec2(R, gen_1): R; } /* For now field ignored. */ static GEN makeA5vec_i(GEN X, GEN Xinf, GEN field, long s, long fl) { (void)field; if (s == 1) return NULL; return A5vec(X, Xinf, s, fl); } static GEN makeA5vec(GEN X, GEN Xinf, GEN field, long s) { GEN rX = sqrti(X), sXinf, rXinf = sqrtremi(Xinf, &sXinf); if (signe(sXinf)) rXinf = addiu(rXinf, 1); return makeA5vec_i(rX, rXinf, field, s, 0); } static GEN makeA5condvec(GEN X, GEN Xinf, GEN field, long s) { return makeA5vec_i(X, Xinf, field, s, 1); } static GEN makeA56vec_i(GEN V, GEN X, GEN Xinf) { long l = lg(V), i, c; GEN W = cgetg(l, t_VEC); for (i = c = 1; i < l; i++) { GEN pol = makeA5resolvent(gel(V, i), 0), D = nfdisc(pol); if (cmpii(D, X) <= 0 && cmpii(D, Xinf) >= 0) gel(W, c++) = pol; } setlg(W, c); return W; } static GEN makeA56vec(GEN X, GEN Xinf, long s) { GEN v; if (s == 1 || s == 3 || !(v = makeA5vec(X, Xinf, NULL, s))) return NULL; if (s != -2) return makeA56vec_i(v, X, Xinf); return mkvec3(makeA56vec_i(gel(v, 1), X, Xinf), cgetg(1, t_VEC), makeA56vec_i(gel(v, 3), X, Xinf)); } static GEN makeA56(GEN N, long s) { return makeA56vec(N, N, s); } /* Stupid for now */ static GEN makeA56resolvent(GEN pol, long flag) { GEN D6 = sqrti(nfdisc(pol)), LD = divisors(D6); long i, s; pol = polredabs(pol); s = pol2s(pol)? 2: 0; for (i = 1; i < lg(LD); i++) { GEN D5 = gel(LD,i); if (dvdii(sqri(D5), D6)) { GEN L = vecsliceA5(s, D5, D5, 0); long j; for (j = 1; j < lg(L); j++) { GEN P = gel(L, j); if (ZX_equal(makeA5resolvent(P, 0), pol)) return odd(flag)? mkvec2(P, gen_1): P; } } } pari_err_BUG("nfresolvent [A56 resolvent not found]"); return NULL; /* LCOV_EXCL_LINE */ } /**********************************************************************/ /* C6 */ /**********************************************************************/ static GEN makepol6(GEN P3, GEN P2) { return polcompositum0(P3, P2, 2); } static GEN makepol6abs(GEN P3, GEN P2) { return polredabs(makepol6(P3, P2)); } static GEN makeC6(GEN N, GEN field, long s) { GEN R, D, d3 = NULL; long i, j, lD, s2, c; if (s == 1 || s == 2) return NULL; if (!field) D = divisorsabsdisc(cored(N, 3), s); else if (degpol(field) == 2) { GEN D2 = nfdisc(field); long si = signe(D2); if ((s == 3 && si > 0) || (s == 0 && si < 0) || !divissquare(N, powiu(D2,3))) return NULL; D = mkvec(absi_shallow(D2)); } else { GEN q, D3 = checkfield(field, 3); if (!Z_issquareall(D3, &d3)) pari_err_TYPE("makeC6 [field]", field); if (!(q = divide(N, sqri(D3)))) return NULL; D = divisorsabsdisc(cored(gcdii(N, powiu(q,3)), 3), s); } s2 = maxss(s, -1); if (s2 == 3) s2 = 1; lD = lg(D); R = cgetg(lD, t_VEC); for (i = c = 1; i < lD; i++) { GEN F, L, V2, R0, D2a = gel(D, i), M = diviiexact(N, powiu(D2a, 3)); long l, l2; if (!Z_issquareall(M, &F)) continue; if (d3) { L = mkvec(mkvec(field)); l = 2; } else { long k; L = divisors(cored(mulii(F, D2a), 2)); l = lg(L); for (j = k = 1; j < l; j ++) { GEN C = makeC3_f(gel(L, j)); if (lg(C) > 1) gel(L, k++) = C; } setlg(L, k); l = k; if (l == 1) continue; } V2 = makeC2(D2a, NULL, s2); l2 = lg(V2); R0 = cgetg(l, t_VEC); for (j = 1; j < l; j++) { GEN R3, C3 = gel(L, j); long i2, c3, i3, l3 = lg(C3); R3 = cgetg(l2 * l3, t_VEC); for (i3 = c3 = 1; i3 < l3; i3++) { GEN P3 = gel(C3, i3); for (i2 = 1; i2 < l2; i2++) { GEN P6 = makepol6(P3, gel(V2, i2)); if (absequalii(nfdisc(P6), N)) gel(R3, c3++) = P6; } } setlg(R3, c3); gel(R0, j) = R3; } gel(R, c++) = shallowconcat1(R0); } setlg(R,c); return sturmseparate(myshallowconcat1(R), s, 6); } static GEN makeC6resolvent(GEN pol, long flag) { GEN V, R3, R = mynfsubfield(pol, 2); R3 = (flag >= 2)? mynfsubfield(pol, 3): NULL; switch (flag) { case 0: V = R; break; case 1: V = condrel_i(R, pol); break; case 2: V = mkvec2(R, R3); break; default:V = mkvec2(condrel_i(R, pol), condrel_i(R3, pol)); break; } return V; } /* assume the odd part of M is squarefree, disc is OK */ static void C6fill(long M, GEN P3, long s, GEN vp,GEN vm) { int p, m; uis_fundamental_pm_i(M, s, &p, &m, 1); if (p) vectrunc_append(vp, makepol6(P3, X2p(utoineg(M)))); if (m) vectrunc_append(vm, makepol6(P3, X2p(utoipos(M)))); } GEN nflist_C6_worker(GEN P3, GEN X, GEN Xinf, GEN M, GEN T) { pari_sp av = avma; GEN D3, f, D32, vp, vm, G, Ginf; long i, limD2, l = lg(M), s = T[1]; if (typ(P3)==t_VEC) { f = gel(P3,2); P3 = gel(P3,1); } else f = C3pol_f(P3); D3 = sqri(f); D32 = sqri(D3); G = divii(X, D32); Ginf = ceildiv(Xinf, D32); limD2 = cmpiu(G, T[2]) < 0 ? itou(G) : T[2]; /* D3 = f^2 is odd, gcd(M,D3) = gcd(M,f); disc = D3^2 / (D3,M)^2 * M^3 */ vp = vectrunc_init(limD2); vm = vectrunc_init(limD2); for (i = 1; i < l; i++) { long m = M[i]; GEN g; if (!odd(m)) continue; if (m > limD2) break; g = muliu(sqru(m / ugcdiu(f, m)), m); if (m != 1 && ok_int(g, G, Ginf)) C6fill(m, P3, s, vp, vm); if ((m << 2) <= limD2 && ok_int(shifti(g,6), G, Ginf)) C6fill(m << 2, P3, s, vp, vm); if ((m << 3) <= limD2 && ok_int(shifti(g,9), G, Ginf)) C6fill(m << 3, P3, s, vp, vm); } return gerepilecopy(av, mkvec2(vp, vm)); } static GEN makeC6vec(GEN X, GEN Xinf, GEN field, long s) { GEN T, v, M; if (s == 1 || s == 2) return NULL; if (field) { GEN D, f; if (degpol(field) == 2) { long si, m, i, c, l; GEN F; D = nfdisc(field); si = signe(D); if (cmpii(powiu(D, 3), X) > 0 || (s == 3 && si > 0) || (s == 0 && si < 0)) return NULL; m = itou(D); v = C3vec_F(floorsqrtdiv(X,D), 1, &F); l = lg(v); for (i = c = 1; i < l; i++) { long f = F[i]; /* conductor */ GEN g = muliu(sqru(m / ugcd(f, m)), m); if (ok_int(mulii(powuu(f, 4), g), X, Xinf)) gel(v, c++) = makepol6(gtopoly(gel(v,i), 0), field); } setlg(v, c); if (s == -2) v = si > 0? vecs14(v, cgetg(1,t_VEC)): vecs(4, v); return v; } D = checkfield(field, 3); if (!Z_issquareall(D, &f)) pari_err_TYPE("makeC6 [field]", field); if (cmpii(sqri(D), X) > 0) return NULL; v = mkvec(mkvec2(field, f)); } else if (!(v = makeC3vec(sqrti(divis(X, 3)), gen_1, NULL, 0))) return NULL; T = mkvecsmall2(s, floorsqrtn(X, 3)); M = vecsquarefreeu(1, T[2]); v = nflist_parapply("_nflist_C6_worker", mkvec4(X, Xinf, M, T), v); switch (s) { case -1: return shallowconcat(Sextract(v,1), Sextract(v,2)); case -2: return vecs14(Sextract(v,1), Sextract(v,2)); /* -2 */ default: return Sextract(v, s? 2: 1); } } /**********************************************************************/ /* S36 = D66 */ /**********************************************************************/ static GEN makeS36(GEN N, GEN field, long s) { GEN vD, P, vp, vm; long i, l, cp, cm; if (s == 1 || s == 2) return NULL; if (s == 3) s = 1; if (field) { long sf = s != -1? pol2s(field): 0/*dummy*/; if (s >= 0 && s != sf) return NULL; if (degpol(field) == 3) { GEN d, D = nfcoredisc(field, &d); if (!absequalii(mulii(sqri(D), d), N)) return NULL; P = mkvec(makepol6abs(field, X2m(d))); if (s == -2) { P = vecs(4, P); if (sf) swap(gel(P,1), gel(P,4)); } return P; } else { GEN D2 = checkfield(field, 2); if (!divispowerall(N, powiu(absi_shallow(D2),3), 4, NULL)) return NULL; vD = mkvec(D2); } } else vD = divisorsdisc(cored(N, 3), s); l = lg(vD); vp = cgetg(l, t_VEC); vm = cgetg(l, t_VEC); for (i = cp = cm = 1; i < l; i++) { GEN F, w, P2, D = gel(vD, i), Da = absi_shallow(D); long lw, j, s2 = signe(D) > 0? 0: 1; if (!Z_ispowerall(divii(N, powiu(Da, 3)), 4, &F)) continue; P2 = X2m(D); if (!(w = makeDL(3, mulii(Da, sqri(F)), P2, s2))) continue; lw = lg(w); for (j = 1; j < lw; j++) gel(w, j) = makepol6abs(gel(w, j), P2); if (signe(D) < 0) gel(vm, cm++) = w; else gel(vp, cp++) = w; } setlg(vp, cp); vp = myshallowconcat1(vp); setlg(vm, cm); vm = myshallowconcat1(vm); return s == -2? vecs14(vp, vm): shallowconcat(vp, vm); } static GEN makeS36resolvent(GEN pol, long flag) { GEN R2, V, S = mynfsubfields(pol, 3); if (flag < 2) return condrel(gel(S,1), pol, flag); R2 = mynfsubfield(pol, 2); if (flag == 2) V = vec_append(S, R2); else V = mkvec4(condrel_i(gel(S,1), pol), condrel_i(gel(S,2), pol), condrel_i(gel(S,3), pol), condrel_i(R2, pol)); return V; } GEN nflist_S36_worker(GEN pol, GEN X, GEN Xinf) { GEN d, D = nfcoredisc(pol, &d); if (ok_int(mulii(sqri(D), d), X, Xinf)) return makepol6(pol, X2m(d)); return gen_0; } static GEN parselectS36(GEN v, GEN X, GEN Xinf) { GEN w = nflist_parapply("_nflist_S36_worker", mkvec2(X, Xinf), v); long l = lg(w), i, c; for (i = c = 1; i < l; i++) { GEN t = gel(w, i); if (typ(t) == t_POL) gel(w, c++) = t; } setlg(w, c); return w; } static GEN makeS36vec(GEN X, GEN Xinf, GEN field, long s) { GEN v; if (s == 1 || s == 2) return NULL; if (s == 3) s = 1; if (field) { if (degpol(field) == 3) { GEN d, D = nfcoredisc(field,&d); long ss = signe(D) < 0? 1: 0; if (s >= 0 && s != ss) return NULL; if (abscmpii(mulii(sqri(D), d), X) > 0) return NULL; v = mkvec(field); } else { GEN D2a = absi_shallow(checkfield(field, 2)), D2a3 = powiu(D2a, 3), RES; long Fsup, Finf, F, c; if ((s >= 0 && s != pol2s(field)) || cmpii(D2a3, X) > 0) return NULL; Fsup = floorsqrtndiv(X, D2a3, 4); Finf = ceilsqrtndiv(Xinf, D2a3, 4); RES = cgetg(Fsup + 1, t_VEC); for (F = Finf, c = 1; F <= Fsup; F++) { pari_sp av = avma; GEN w, N = mulii(powuu(F, 4), D2a3); if (!(w = makeS36(N, field, s))) set_avma(av); else gel(RES, c++) = gerepilecopy(av, w); } setlg(RES,c); return myshallowconcat1(RES); } } else if (!(v = makeS3vec(sqrti(divis(X, 3)), gen_1, NULL, s))) return NULL; if (s != -2) return parselectS36(v, X, Xinf); return mkvec4(parselectS36(gel(v,1), X, Xinf), cgetg(1, t_VEC), cgetg(1, t_VEC), parselectS36(gel(v,2), X, Xinf)); } /**********************************************************************/ /* D612 */ /**********************************************************************/ static void gets2s3(long s, long *s2, long *s3) { switch (s) { case 0: *s2 = *s3 = 0; break; case 2: *s2 = 0; *s3 = 1; break; case 3: *s2 = 1; *s3 = -1; break; default: *s2 = *s3 = -1; break; } } static GEN makeD612vec(GEN X, GEN Xinf, GEN field, long s); static GEN makeD612(GEN N, GEN field, long s) { long i, j, l, c3, s2, s3; GEN v; if (s == 1) return NULL; gets2s3(s, &s2, &s3); if (field) { GEN D2; long si; if (degpol(field) == 3) return makeD612vec(N,N,field,s); D2 = checkfield(field, 2); si = signe(D2); if ((si == 1 && s2 > 0) || (si == -1 && !s2) || !divissquare(N, powiu(D2,3))) return NULL; v = mkvec(D2); } else v = divisorsdisc(cored(N, 3), s2); l = lg(v); for (i = c3 = 1; i < l; i++) { GEN D2 = gel(v, i), D2a = absi_shallow(D2), M = divii(N, powiu(D2a, 3)); GEN P2, F = gel(core2(M), 2), L = divisors(mulii(F, D2a)); long c2, lL = lg(L); if (lL == 1) continue; P2 = quadpoly_i(D2); for (j = c2 = 1; j < lL; j++) { GEN w, D3 = gel(L, j); long k, c, lw; if (Mod4(D3) == 2 || !dvdii(F, divii(D3, gcdii(D2a, D3))) || !(w = makeDL(3, D3, NULL, s3))) continue; lw = lg(w); for (k = c = 1; k < lw; k++) { GEN P3 = gel(w, k), P6, d; (void)nfcoredisc(P3, &d); if (equalii(d, D2)) continue; if ((P6 = ZX_red_disc(makepol6(P3, P2), N))) gel(w, c++) = P6; } if (c > 1) { setlg(w, c); gel(L, c2++) = w; } } if (c2 > 1) { setlg(L, c2); gel(v, c3++) = shallowconcat1(L); } } setlg(v, c3); return sturmseparate(myshallowconcat1(v), s, 6); } static GEN makeD612resolvent(GEN pol, long flag) { GEN R3, R = mynfsubfield(pol, 2); if (flag < 2) return condrel(R, pol, flag); R3 = mynfsubfield(pol, 3); if (flag == 3) { R = condrel_i(R, pol); R3 = condrel_i(R3, pol); } return mkvec2(R, R3); } GEN nflist_D612_worker(GEN P3, GEN X, GEN Xinf, GEN limd2s2) { pari_sp av = avma; GEN v, D2, D3 = nfcoredisc(P3, &D2), D32 = sqri(D3), Q = divii(X, D32); long limD2 = limd2s2[1], s2 = limd2s2[2]; long c, M, limD = cmpis(Q, limD2) < 0 ? itos(Q) : limD2; v = cgetg(2 * limD + 1, t_VEC); for (M = 3, c = 1; M <= limD; M++) { GEN N, LD = cgetg(1, t_VEC); long g, i; int p, m; uis_fundamental_pm(M, s2, &p, &m); if (absequaliu(D2, M)) { if (signe(D2) > 0) p = 0; else m = 0; } if (!(LD = ufund_pm(M, p, m))) continue; g = ugcdiu(D3, M); N = mulii(D32, muliu(sqru(M/g), M)); if (cmpii(N, X) <= 0 && cmpii(shifti(N, 2), Xinf) >= 0) { long l = lg(LD); for (i = 1; i < l; i++) { GEN P = makepol6(P3, X2m(gel(LD,i))); if (odd(g)) gel(v, c++) = polredabs(P); else if ((P = ZX_red_disc2(P, Xinf, X))) gel(v, c++) = P; } } } setlg(v, c); return gerepilecopy(av, v); } static GEN makeD612vec(GEN X, GEN Xinf, GEN field, long s) { GEN v, T; long s2, s3; if (s == 1) return NULL; v = NULL; gets2s3(s, &s2, &s3); if (field) { if (degpol(field) == 3) { GEN D3 = nfdisc(field); long si = signe(D3); if ((si > 0 && s2 > 0) || (si < 0 && !s2) || cmpii(sqri(D3), X) > 0) return NULL; v = mkvec(field); } else { GEN D2a = absi_shallow(checkfield(field, 2)); long l, j, c; if (!(v = makeS3vec(sqrti(divii(X, D2a)), gen_1, NULL, s3))) return NULL; l = lg(v); for (j = c = 1; j < l; j++) { GEN P = makepol6(gel(v, j), field); if ((P = ZX_red_disc2(P, Xinf, X))) gel(v, c++) = P; } setlg(v, c); return sturmseparate(v, s, 6); } } else if (!(v = makeS3vec(sqrti(X), gen_1, NULL, s3))) return NULL; T = mkvecsmall2(floorsqrtn(X, 3), s2); v = nflist_parapply("_nflist_D612_worker", mkvec3(X, Xinf, T), v); return sturmseparate(myshallowconcat1(v), s, 6); } /**********************************************************************/ /* A46 and S46P */ /**********************************************************************/ /* A46, S46P, in place */ static GEN makeS46Ppols(long card, GEN v) { long l = lg(v), i; GEN d = utoipos(card); for (i = 1; i < l; i++) { GEN G = galoissplittinginit(gel(v,i), d), g = gal_get_gen(G); GEN p = (card == 12)? gel(g, 1): mkvec2(gel(g, 1), gel(g, 4)); gel(v,i) = polredabs(galoisfixedfield(G, p, 1, 0)); } return v; } /* S46M, in place */ static GEN makeS46Mpols(GEN v, GEN X, GEN Xinf) { long l = lg(v), i, c; GEN d = utoipos(24); for (i = c = 1; i < l; i++) { GEN G = galoissplittinginit(gel(v,i), d), g = gal_get_gen(G); GEN p = perm_mul(gel(g, 4), gel(g, 2)); p = galoisfixedfield(G, p, 1, 0); p = Xinf? ZX_red_disc2(p, Xinf, X): ZX_red_disc(p, X); if (p) gel(v, c++) = p; } setlg(v, c); return v; } static GEN makeA46(GEN N, GEN field, long s) { GEN n, v, D; long i, l, c; if (s== 1 || s==3 || !Z_issquareall(N, &n)) return NULL; if (field) { GEN t, q, D = checkfield(field, 3); if (!Z_issquare(D) || !(q = divide(n, D)) || !(t = makeA4S4(field, q, s))) return NULL; return makeS46Ppols(12, t); } D = divisors(gel(core2(n), 2)); l = lg(D); v = cgetg(l, t_VEC); for (i = 2, c = 1; i < l; i++) { GEN t, q, g3 = gel(D,i), C = makeC3_f(g3); long j, l = lg(C); if (l == 1) continue; q = diviiexact(n, sqri(g3)); for (j = 1; j < l; j++) if ((t = makeA4S4(gel(C,j), q, s))) gel(v, c++) = makeS46Ppols(12,t); } setlg(v,c); return sturmseparate(myshallowconcat1(v), s, 6); } static GEN makeS46P(GEN N, GEN field, long s) { GEN n, v, D; long i, snew, l, c; if (s==1 || s==3 || !Z_issquareall(N, &n)) return NULL; /* s = -2, -1, 0, 2 */ if (field) { GEN D3 = checkfield(field, 3), f, t; if (Z_issquare(D3) || !dvdii(n, D3)) return NULL; snew = s == 2 && signe(D3) < 0 ? 1 : s; f = divii(n, absi_shallow(D3)); if (!(t = makeA4S4(field, f, snew))) return NULL; return makeS46Ppols(24, t); } D = divisors(n); l = lg(D); v = cgetg(l, t_VEC); for (i = 2, c = 1; i < l; i++) { GEN f, P, D3a = gel(D,i); long c3, j, lv3; if (!(P = makeDL(3, D3a, NULL, s? -1: 0))) continue; f = gel(D, l-i); lv3 = lg(P); for (j = c3 = 1; j < lv3; j++) { GEN T, P3 = gel(P,j); long snew = (s == 2 && signe(ZX_disc(P3)) == -1) ? 1 : s; if ((T = makeA4S4(P3, f, snew))) gel(P,c3++) = T; } if (c3 == 1) continue; setlg(P, c3); gel(v, c++) = makeS46Ppols(24, shallowconcat1(P)); } setlg(v,c); return sturmseparate(myshallowconcat1(v), s, 6); } GEN nflist_A46S46P_worker(GEN P3, GEN Xinf, GEN sqX, GEN cards) { pari_sp av = avma; long card = cards[1], s = cards[2]; GEN w, F, V, DATA = S4data(P3, s), D3 = S4_get_disc(DATA); GEN D3a = absi_shallow(D3); long limf = itos(divii(sqX, D3a)), linf = 1, snew, f, i, c; if (cmpii(Xinf, sqri(shifti(D3a, 2))) >= 0) linf = ceilsqrtdiv(Xinf, sqri(D3)); snew = s == 2 && signe(D3) < 0 ? 1 : s; V = cgetg(limf, t_VEC); F = vecfactoru_i(linf, limf); for (f = linf, i = c = 1; f <= limf; f++, i++) if ((w = A4S4_fa(DATA, gel(F,i), f, snew))) gel(V, c++) = makeS46Ppols(card, w); setlg(V,c); V = myshallowconcat1(V); return gerepilecopy(av, V); } static GEN makeA46S46Pvec(long card, GEN X, GEN Xinf, GEN field, long s) { GEN v, sqX, T; if (s == 1 || s == 3) return NULL; sqX = sqrti(X); if (field) { GEN D = checkfield(field, 3); long fl = Z_issquare(D); if ((card == 12 && !fl) || (card == 24 && fl)) return NULL; v = mkvec(field); } else v = card == 12? makeC3vec(sqX, gen_1, NULL, 0) : makeS3vec(sqX, gen_1, NULL, s? -1: 0); if (!v) return NULL; T = mkvec3(Xinf, sqX, mkvecsmall2(card, s == -2? -1: s)); v = nflist_parapply("_nflist_A46S46P_worker", T, v); return sturmseparate(myshallowconcat1(v), s, 6); } /**********************************************************************/ /* S46M */ /**********************************************************************/ static GEN glco46M(GEN F, GEN D2a) { GEN C, F0, D = divisors(D2a); long k, i, c, l = lg(D), klim = vali(D2a)? minss(2, vali(F)): 0; /* could restrict divisors to multiples of (D2,F)/2^klim */ F0 = klim? shifti(F, -klim): F; C = cgetg((klim+1) * (l-1) + 1, t_VEC); for (i = c = 1; i < l; i++) { GEN g = gcdii(F, gel(D,l-i)); long v = vali(g); if (v) g = shifti(g, -v); if (!is_pm1(g) || v > klim) continue; /* (F,D[l-i]) = 2^v; if v <= k <= klim, add F*D[i]>>k */ gel(C, c++) = g = mulii(F0, gel(D,i)); for (k = v; k < klim; k++) gel(C, c++) = g = shifti(g, 1); } setlg(C, c); return C; } static GEN doA4S4(GEN field, GEN C, long s) { long l = lg(C), i, c; GEN w, v = cgetg(l, t_VEC); for (i = c = 1; i < l; i++) if ((w = makeA4S4(field, gel(C,i), s))) gel(v, c++) = w; setlg(v,c); return myshallowconcat1(v); } static GEN makeS46M(GEN N, GEN field, long s) { GEN v, D, LC, F; long i, c, l, snew; if (s == 1) return NULL; snew = s == 3 ? 1 : maxss(s, -1); if (field) { GEN D3, D2, D2a, t, Dpow; checkfield_i(field, 3); D3 = nfcoredisc(field, &D2); D2a = absi_shallow(D2); Dpow = mulii(D2a, sqri(D3)); if ((signe(D3) < 0 && (s == 0 || s == 2)) || (signe(D3) > 0 && (s == 3 || Z_issquare(D3))) || !divissquareall(N, Dpow, &F)) return NULL; LC = glco46M(F, D2a); t = doA4S4(field, LC, snew); return makeS46Mpols(t, N, NULL); } D = divisorsabsdisc(cored(N, 3), snew); l = lg(D); v = cgetg(l*l, t_VEC); for (i = c = 1; i < l; i++) { GEN D2a = gel(D, i), NSD2 = divii(N, powiu(D2a, 3)), NSD4, F; long j; if (!Z_issquareall(NSD2, &NSD4)) continue; F = divisors(cored(NSD2, 4)); for (j = 1; j < lg(F); j++) { GEN f2 = sqri(gel(F, j)), P; long k, lP; if (!(P = makeDL(3, mulii(D2a, f2), NULL, minss(snew, 1)))) continue; lP = lg(P); LC = glco46M(divii(NSD4, f2), D2a); for (k = 1; k < lP; k++) gel(P,k) = doA4S4(gel(P,k), LC, snew); gel(v, c++) = makeS46Mpols(shallowconcat1(P), N, NULL); } } if (c == 1) return NULL; setlg(v,c); return sturmseparate(gtoset_shallow(shallowconcat1(v)), s, 6); } GEN nflist_S46M_worker(GEN P3, GEN X, GEN Xinf, GEN gs) { pari_sp av = avma; long s = gs[1], snew = s == 3 ? 1 : s; GEN V, DATA = S4data(P3, s), D3 = S4_get_disc(DATA); GEN D2a = absi_shallow(coredisc(D3)); long lim = floorsqrtdiv(X, mulii(sqri(D3), D2a)), f, c; V = cgetg(lim + 1, t_VEC);; for (f = 1, c = 1; f <= lim; f++) { GEN C = glco46M(utoipos(f), D2a), t = doA4S4(DATA, C, snew); gel(V, c++) = makeS46Mpols(t, X, Xinf); } setlg(V,c); V = myshallowconcat1(V); return gerepileupto(av, gtoset(V)); } static GEN makeS46Mvec(GEN X, GEN Xinf, GEN field, long s) { GEN v; if (s == 1) return NULL; if (field) { GEN D = checkfield(field, 3); if (Z_issquare(D)) return NULL; v = mkvec(field); } else { long s3 = s == 3? 1: (s < 0? -1: 0), l2, i, c; GEN v2 = makeC2vec(sqrtnint(X,3), gen_1, NULL, s3); if (!v2) return NULL; l2 = lg(v2); v = cgetg(l2, t_VEC); for (i = c = 1; i < l2; i++) { GEN w, T = gel(v2, i), D2a = absi_shallow(nfdisc(T)); if ((w = makeS3vec(sqrti(divii(X, D2a)), gen_1, T, s3))) gel(v, c++) = w; } setlg(v,c); v = myshallowconcat1(v); } v = nflist_parapply("_nflist_S46M_worker", mkvec3(X, Xinf, mkvecsmall(s == -2? -1: s)), v); return sturmseparate(myshallowconcat1(v), s, 6); } /************************************************************************/ /* A462 */ /************************************************************************/ static GEN arch0() { return mkvec(mkvec3(gen_0, gen_0, gen_0)); } static GEN arch1g() { return mkvec(mkvec3(gen_1, gen_0, gen_0)); } static GEN arch1() { return mkvec3(mkvec3(gen_1, gen_0, gen_0), mkvec3(gen_0, gen_1, gen_0), mkvec3(gen_0, gen_0, gen_1)); } static GEN arch2g() { return mkvec(mkvec3(gen_0, gen_1, gen_1)); } static GEN arch2() { return mkvec3(mkvec3(gen_0, gen_1, gen_1), mkvec3(gen_1, gen_0, gen_1), mkvec3(gen_1, gen_1, gen_0)); } static GEN arch3() { return mkvec(mkvec3(gen_1, gen_1, gen_1)); } static GEN archA462(long s) { switch (s) { case 0: return arch0(); case 1: return arch1g(); case 2: return arch2g(); default: return shallowconcat1(mkvec3(arch0(),arch1g(),arch2g())); } } static int stable_arch(GEN v) { long i, l = lg(v); GEN x = gel(v,1); for (i = 2; i < l; i++) if (!equalii(x, gel(v,i))) return 0; return 1; } /* nf cyclic of prime degree, return a generator of */ static GEN cycfindaut(GEN nf) { GEN A = galoisconj(nf, NULL); return nfgaloismatrix(nf, gel(A, gequalX(gel(A,1))? 2 : 1)); } static int isprM(GEN x) { return typ(x) == t_MAT && lg(x) == 3; } static GEN doA462(GEN bnf, GEN L, GEN Arch, GEN aut, GEN G, GEN GAL) { pari_sp av = avma; long c, k, i, m, lA = lg(Arch), l = lg(L); int stable0; GEN v; if (l == 1) return NULL; v = cgetg((lA-1) * (l-1) + 1, t_VEC); stable0 = !isprM(gel(L,l-1)); /* not implemented for prM */ for (i = c = 1; i < lA; i++) { GEN arch = gel(Arch, i); int stable = stable0 && stable_arch(arch); for (k = 1; k < l; k++) { GEN R, id = gel(L,k), F = mkvec2(id, arch); long cR, lR; if (stable && ZM_equal(nfgaloismatrixapply(bnf, aut, id), id)) R = mybnrclassfield_X(bnf, F, 2, NULL, NULL, G); else R = mybnrclassfield(bnf, F, 2); lR = lg(R); for (m = cR = 1; m < lR; m++) { GEN P = rnfequation(bnf, gel(R, m)); if (okgal(P, GAL)) gel(R, cR++) = polredabs(P); } if (cR > 1) { setlg(R, cR); gel(v, c++) = R; } } } if (c == 1) { set_avma(av); return NULL; } setlg(v, c); return gtoset_shallow(shallowconcat1(v)); } static GEN makeA462(GEN N, GEN field, long s) { GEN v, L, Arch, GAL; long i, c, l; if (s == 3) return NULL; Arch = archA462(s); GAL = mkvecsmall3(24, -1, 2); if (field) { GEN D3 = checkfield(field, 3); if (!Z_issquare(D3) || !dvdii(N, sqri(D3))) return NULL; L = mkvec(field); } else { GEN LD = divisors(cored(N, 4)); L = cgetg(1, t_VEC); for (i = 1; i < lg(LD); i++) { GEN t = makeC3_f(gel(LD,i)); if (lg(t) > 1) L = shallowconcat(L, t); } } l = lg(L); v = cgetg(l, t_VEC); for (i = c = 1; i < l; i++) { GEN bnf = bnfY(gel(L,i)), nf = bnf_get_nf(bnf), aut = cycfindaut(bnf); GEN T, I = ideals_by_norm(nf, divii(N, sqri(nf_get_disc(nf)))); GEN G = mkvec2(galoisinit(nf, NULL), gen_0); if ((T = doA462(bnf, I, Arch, aut, G, GAL))) gel(v, c++) = T; } if (c == 1) return NULL; setlg(v, c); return sturmseparate(shallowconcat1(v), s, 6); } GEN nflist_A462_worker(GEN P3, GEN X, GEN Xinf, GEN Arch, GEN GAL) { pari_sp av = avma; GEN bnf = bnfY(P3), aut = cycfindaut(bnf), v, t; GEN G = mkvec2(galoisinit(bnf, NULL), gen_0), D2 = sqri(bnf_get_disc(bnf)); long c, l, j, lim = itos(divii(X, D2)), liminf = itos(ceildiv(Xinf, D2)); v = ideallist(bnf, lim); l = lg(v); for (c = 1, j = liminf; j < l; j++) if ((t = doA462(bnf, gel(v,j), Arch, aut, G, GAL))) gel(v,c++) = t; setlg(v, c); return gerepilecopy(av, myshallowconcat1(v)); } static GEN makeA462vec(GEN X, GEN Xinf, GEN field, long s) { GEN v, GAL; if (s == 3) return NULL; if (field) { GEN D3 = checkfield(field, 3); if (!Z_issquare(D3) || cmpii(sqri(D3), X) > 0) return NULL; v = mkvec(field); } else if (!(v = makeC3vec(sqrti(X), gen_1, NULL, 0))) return NULL; GAL = mkvecsmall3(24, -1, 2); v = nflist_parapply("_nflist_A462_worker", mkvec4(X, Xinf, archA462(s), GAL), v); return sturmseparate(myshallowconcat1(v), s, 6); } /************************************************************************/ /* S3C3 */ /************************************************************************/ static int isok3(ulong N) { GEN fa, P, E; long v = u_lvalrem(N, 3, &N), i, l; if (v == 1 || v >= 4) return 0; fa = factoru(N); P = gel(fa, 1); E = gel(fa, 2); l = lg(P); for (i = 1; i < l; i++) if (P[i] % 3 == 1) { if (E[i] != 1) return 0; } else { if (E[i] != 2) return 0; } return 1; } static GEN makeS3C3(GEN N, GEN field, long s) { GEN v, LD, cond; long s2, i; if (s == 1 || s == 2) return NULL; s2 = s == 3 ? 1 : s; if (field) { GEN D = checkfield(field, 2); if (!divissquareall(N, powiu(absi_shallow(D), 3), &cond)) return NULL; LD = mkvec(D); } else LD = divisorsdisc(cored(N, 3), s2); v = cgetg(1, t_VEC); for (i = 1; i < lg(LD); i++) { GEN L, bnf, nf, D = gel(LD, i); long j, k; if (!divissquareall(N, powiu(absi_shallow(D), 3), &cond)) continue; bnf = bnfY(Y2m(D)); nf = bnf_get_nf(bnf); L = ideals_by_norm(nf, cond); for (j = 1; j < lg(L); j++) { GEN R = mybnrclassfield_N(bnf, gel(L,j), N, 3); for (k = 1; k < lg(R); k++) { GEN P = rnfequation(nf, gel(R, k)); if (okgal1(P, 18)) v = vec_append(v, polredabs(P)); } } } return sturmseparate(gtoset_shallow(v), s, 6); } GEN nflist_S3C3_worker(GEN D2, GEN X, GEN Xinf) { pari_sp av = avma; GEN bnf = bnfY(Y2m(D2)), nf = bnf_get_nf(bnf), aut = cycfindaut(nf); GEN G = mkvec2(galoisinit(bnf, NULL), gen_0); long f, c, limf = floorsqrtdiv(X, powuu(itou(D2), 3)); GEN v = ideallist0(nf, limf, 4 | 8); for (f = c = 1; f <= limf; f++) { pari_sp av2; long j, k, cL; GEN L; if (!isok3(f)) continue; av2 = avma; L = gel(v, f); for (j = cL = 1; j < lg(L); j++) { pari_sp av3 = avma; long stable = gequal(gel(L,j), nfgaloismatrixapply(nf, aut, gel(L,j))); GEN R = mybnrclassfield_X(bnf, gel(L,j), 3, X, Xinf, stable? G: NULL); long lR = lg(R), cR; for (k = cR = 1; k < lR; k++) { GEN P = rnfequation(nf, gel(R, k)); if (okgal1(P, 18)) gel(R, cR++) = polredabs(P); } if (cR == 1) { set_avma(av3); continue; } setlg(R, cR); gel(L, cL++) = R; } if (cL == 1) { set_avma(av2); continue; } setlg(L, cL); gel(v, c++) = shallowconcat1(L); } setlg(v, c); return gerepilecopy(av, gtoset_shallow(myshallowconcat1(v))); } static GEN makeS3C3vec(GEN X, GEN Xinf, GEN field, long s) { GEN v; if (s == 1 || s == 2) return NULL; if (field) { GEN D = checkfield(field, 2); v = mkvec(D); } else { long lim = floorsqrtn(X, 3), Da, c; v = cgetg(2 * lim + 1, t_VEC); for (Da = 3, c = 1; Da <= lim; Da++) { int p, m; uis_fundamental_pm(Da, s, &p, &m); if (p) gel(v, c++) = utoipos(Da); if (m) gel(v, c++) = utoineg(Da); } if (c == 1) return NULL; setlg(v, c); } v = nflist_parapply("_nflist_S3C3_worker", mkvec2(X, Xinf), v); return sturmseparate(myshallowconcat1(v), s, 6); } /************************************************************************/ /* S462 */ /************************************************************************/ static GEN archS4621(long s) { switch(s) { case 0: case 1: return cgetg(1, t_VEC); case 2: retmkvec(mkvec(gen_0)); case 3: retmkvec(mkvec(gen_1)); default:retmkvec2(mkvec(gen_0), mkvec(gen_1)); } } static GEN archS4623(long s) { switch (s) { case 0: return arch0(); case 1: return arch1(); case 2: return arch2(); case 3: return arch3(); default:return shallowconcat1(mkvec4(arch0(),arch1(),arch2(),arch3())); } } static GEN makeS462(GEN N, GEN field, long s) { GEN RES = cgetg(1, t_VEC), L, listarch1, listarch3, GAL; long i, j, l, m; listarch1 = archS4621(s); listarch3 = archS4623(s); GAL = mkvecsmall3(48, -1, 1); if (field) { GEN d = checkfield(field, 3); if (Z_issquare(d) || !dvdii(N, sqri(d))) return NULL; L = mkvec(field); } else { GEN T; long c; L = divisors(cored(N, 2)); for (i = c = 1; i < lg(L); i++) if ((T = makeDL(3, gel(L,i), NULL, (s == 0 || s == 1) ? 0 : -1))) gel(L, c++) = T; if (c == 1) return NULL; setlg(L, c); L = shallowconcat1(L); } for (i = 1; i < lg(L); i++) { GEN bnf = bnfY(gel(L,i)), nf = bnf_get_nf(bnf); GEN I = ideals_by_norm(nf, divii(N, sqri(nf_get_disc(nf)))); GEN Arch = nf_get_r1(nf) == 1 ? listarch1 : listarch3; for (j = 1; j < lg(I); j++) { GEN id = gel(I, j); for (l = 1; l < lg(Arch); l++) { GEN R = mybnrclassfield(bnf, mkvec2(id, gel(Arch, l)), 2); for (m = 1; m < lg(R); m++) { GEN P = rnfequation(bnf, gel(R, m)); if (okgal(P, GAL) && (P = ZX_red_disc(P, N))) RES = vec_append(RES, P); } } } } return sturmseparate(gtoset_shallow(RES), s, 6); } GEN nflist_S462_worker(GEN P3, GEN X, GEN Xinf, GEN vArch, GEN GAL) { pari_sp av = avma; GEN bnf = bnfY(P3), nf = bnf_get_nf(bnf), D2 = sqri(nf_get_disc(nf)); long limf = itos(divii(X, D2)), liminf = itos(ceildiv(Xinf, D2)); long r1 = nf_get_r1(nf), c, j, k, l, m; GEN v, vI = ideallist(bnf, limf), Arch = gel(vArch, r1 == 1? 1 : 2); v = cgetg(limf + 1, t_VEC); for (c = 1, j = liminf; j <= limf; j++) { GEN I = gel(vI, j), REU = cgetg(1, t_VEC); for (k = 1; k < lg(I); k++) { GEN id = gel(I, k); for (l = 1; l < lg(Arch); l++) { GEN R = mybnrclassfield(bnf, mkvec2(id, gel(Arch, l)), 2); for (m = 1; m < lg(R); m++) { GEN P = rnfequation(bnf, gel(R, m)); if (okgal(P, GAL)) REU = vec_append(REU, polredabs(P)); } } } if (lg(REU) > 1) gel(v, c++) = REU; } setlg(v,c); v = myshallowconcat1(v); return gerepilecopy(av, gtoset_shallow(v)); } static GEN makeS462vec(GEN X, GEN Xinf, GEN field, long s) { GEN v, T, GAL; if (field) { GEN D3 = checkfield(field, 3); long si = signe(D3); if (Z_issquare(D3) || (si < 0 && (s == 0 || s == 1))) return NULL; v = mkvec(field); } else if (!(v = makeS3vec(sqrti(X), gen_1, NULL, (s==0 || s==1)? 0: -1))) return NULL; GAL = mkvecsmall3(48, -1, 1); T = mkvec4(X, Xinf, mkvec2(archS4621(s), archS4623(s)), GAL); v = nflist_parapply("_nflist_S462_worker", T, v); return sturmseparate(myshallowconcat1(v), s, 6); } /************************************************************************/ /* C32C4 */ /************************************************************************/ static GEN doC32C4_i(GEN bnf, GEN L, GEN GAL) { long i, l = lg(L); GEN v; if (l == 1) return L; v = cgetg(l, t_VEC); for (i = 1; i < l; i++) { GEN w = cgetg(1, t_VEC), R = mybnrclassfield(bnf, gel(L,i), 3); long j, lR = lg(R); for (j = 1; j < lR; j++) { GEN P12 = rnfequation(bnf, gel(R, j)), S = _nfsubfields(P12, 6); long k, lS = lg(S); for (k = 1; k < lS; k++) { GEN P = gel(S,k); if (okgal(P, GAL)) w = vec_append(w, polredabs(P)); } } gel(v,i) = w; } return gtoset_shallow(myshallowconcat1(v)); } static GEN doC32C4(GEN N, GEN P4, GEN GAL) { GEN nf, bnf, F, F2, D4 = nfdisc(P4), D2 = nfdisc(_nfsubfields1(P4, 2)); if (!(F2 = divide(N, mulii(D2,D4))) || !Z_issquareall(F2, &F)) return NULL; bnf = bnfY(P4); nf = bnf_get_nf(bnf); return doC32C4_i(bnf, ideals_by_norm(nf, F2), GAL); } static GEN makeC32C4_i(GEN N, GEN field, long s) { GEN GAL = mkvecsmall3(36, 1, 1), v, w, C; long c, i, j, l; if (!Z_issquare(N) || s == 1 || s == 3) return NULL; if (field) { checkfield_i(field, 4); return (okgal2(field,4,-1) && ok_s(field, s))? doC32C4(N, field, GAL): NULL; } v = divisors(N); l = lg(v); for (i = c = 1; i < l; i++) { long cw, lC; if (!(C = makeC4(gel(v, i), NULL, maxss(s, -1)))) continue; lC = lg(C); for (j = cw = 1; j < lC; j++) if ((w = doC32C4(N, gel(C,j), GAL))) gel(C,cw++) = w; if (cw > 1) { setlg(C, cw); gel(v, c++) = shallowconcat1(C); } } setlg(v, c); return myshallowconcat1(v); } static GEN makeC32C4(GEN N, GEN field, long s) { GEN v = makeC32C4_i(N, field, s); return v? sturmseparate(v, s, 6): NULL; } static GEN makeC32C4resolvent(GEN pol, long flag) { GEN P12 = polredabs(gel(compositum(pol, pol), 2)); return condrel(mynfsubfield(P12,4), P12, flag); } /* ideals of square norm < lim^2 */ static GEN ideallistsquare(GEN bnf, long lim) { pari_sp av = avma; GEN nf = bnf_get_nf(bnf), V, Z, F; long d = nf_get_degree(nf), lim2 = lim * lim, p; forprime_t T; if (lim <= 0) return cgetg(1, t_VEC); V = const_vec(lim, cgetg(1, t_VEC)); gel(V, 1) = mkvec(trivial_fact()); u_forprime_init(&T, 2, lim); F = cgetg(d+1, t_VECSMALL); Z = cgetg(d+1, t_VECSMALL); while ((p = u_forprime_next(&T))) { long lv, i, llp = ulogint(lim2, p), tot, m; GEN P = idealprimedec_limit_f(nf, utoipos(p), llp); GEN W = shallowcopy(V); lv = lg(P); for (i = tot = 1; i < lv; i++) { F[i] = pr_get_f(gel(P,i)); Z[i] = llp / F[i] + 1; tot *= Z[i]; } for (m = 1; m < tot; m++) { GEN v = cgetg(lv, t_VECSMALL); long n = m, S = 0; for (i = 1; i < lv; i++) { v[i] = n % Z[i]; n /= Z[i]; S += v[i] * F[i]; } if (!odd(S) && S <= llp) { GEN id = famat_remove_trivial(mkvec2(P, zc_to_ZC(v))); long j, pS = upowuu(p, S >> 1); for (j = 1; j <= lim / pS; j++) { GEN vs = shallowcopy(gel(V, j)); long k, l = lg(vs); for (k = 1; k < l; k++) gel(vs, k) = famat_mul(gel(vs, k), id); gel(W, pS * j) = shallowconcat(gel(W, pS * j), vs); } } } V = W; } return gerepilecopy(av, V); } GEN nflist_C32C4_worker(GEN P4, GEN X, GEN Xinf, GEN GAL) { pari_sp av = avma; GEN bnf = bnfY(P4), D4 = bnf_get_disc(bnf), D2 = nfdisc(_nfsubfields1(P4, 2)); GEN vI, v, w, D4D2 = mulii(D4, D2); long f, c, limf = floorsqrtdiv(X, D4D2), liminf = ceilsqrtdiv(Xinf, D4D2); vI = ideallistsquare(bnf, limf); v = cgetg(limf + 1, t_VEC); for (c = 1, f = liminf; f <= limf; f++) if ((w = doC32C4_i(bnf, gel(vI, f), GAL))) gel(v, c++) = w; setlg(v,c); return gerepilecopy(av, gtoset_shallow(myshallowconcat1(v))); } static GEN makeC32C4vec(GEN X, GEN Xinf, GEN field, long s) { GEN v, L, GAL; if (s == 1 || s == 3) return NULL; GAL = mkvecsmall3(36, 1, 1); if (field) { checkfield_i(field, 4); if (!okgal2(field, 4, -1) || !ok_s(field, s)) return NULL; L = mkvec(field); } else L = makeC4vec(divis(X, 5), gen_1, NULL, s == -2? -1: s); v = nflist_parapply("_nflist_C32C4_worker", mkvec3(X, Xinf, GAL), L); return sturmseparate(myshallowconcat1(v), s, 6); } /************************************************************************/ /* C9 */ /************************************************************************/ static GEN bnrcfC9(GEN bnf, GEN P, GEN F) { GEN v, cond = F, vec9 = mkvec(utoipos(9)), nf = bnf_get_nf(bnf); long i, l, c, lP = lg(P); for (i = 1; i < lP; i++) { GEN p = gel(P, i), pr = idealprimedec_galois(nf, p); if (equaliu(p, 3)) pr = idealsqr(nf, pr); cond = idealmul(nf, cond, pr); } v = mybnrclassfield(bnf, cond, 3); l = lg(v); if (l == 1) return v; for (i = c = 1; i < l; i++) { GEN P = rnfequation(nf, gel(v,i)), G = galoisinit(P, NULL); if (typ(G) != t_INT && gequal(galoisisabelian(G, 2), vec9)) gel(v, c++) = polredabs(P); } setlg(v, c); return gtoset_shallow(v); } static GEN makeC9(GEN N, GEN field, long s) { GEN v, D, F; long i, lD; if (s > 0) return NULL; if (field) { GEN D = checkfield(field, 3), d, P; if (!Z_issquareall(D, &d) || !divispowerall(N, powiu(D,4), 6, &F)) return NULL; P = gel(Z_factor(d), 1); return bnrcfC9(bnfY(field), P, F); } v = cgetg(1, t_VEC); D = divisors(cored(N, 8)); lD = lg(D); for (i = 2; i < lD; i++) { GEN v3, P, d = gel(D,i); long j, l3; if (!Z_ispowerall(divii(N, powiu(d, 8)), 6, &F) || !checkcondC3(d, &P)) continue; v3 = makeC3_i(d, P); l3 = lg(v3); for (j = 1; j < l3; j++) v = shallowconcat(v, bnrcfC9(bnfY(gel(v3,j)), P, F)); } return s == -2? vecs(5, v): v; } GEN nflist_C9_worker(GEN T, GEN X, GEN Xinf) { pari_sp av = avma; GEN bnf = bnfY(T), D3 = bnf_get_disc(bnf), D34 = powiu(D3, 4); GEN sqD = sqrti(D3), P = gel(Z_factor(sqD), 1), v; long fl = umodiu(D3, 3) == 0; long limf = floorsqrtndiv(X, D34, 6), f, c; long limi = ceilsqrtndiv(Xinf, D34, 6); v = cgetg(limf + 1, t_VEC); c = 1; for (f = limi; f <= limf; f++) { GEN t; if (fl) { long r = f % 9; if (r != 3 && r != 6) continue; } t = bnrcfC9(bnf, P, utoipos(f)); if (lg(t) > 1) gel(v, c++) = t; } if (c == 1) { set_avma(av); return cgetg(1, t_VEC); } setlg(v,c); return gerepilecopy(av, myshallowconcat1(v)); } static GEN makeC9vec(GEN X, GEN Xinf, GEN field, long s) { GEN v; if (s > 0) return NULL; if (field) { GEN D = checkfield(field, 3); if (!Z_issquare(D) || cmpii(powiu(D,4), X) > 0) return NULL; v = mkvec(field); } else if (!(v = makeC3vec(sqrtnint(X, 4), gen_1, NULL, 0))) return NULL; v = nflist_parapply("_nflist_C9_worker", mkvec2(X, Xinf), v); v = myshallowconcat1(v); return (s == -2)? vecs(5, v): v; } /************************************************************************/ /* C3xC3 */ /************************************************************************/ static GEN makeC3C3(GEN N, GEN field, long s) { GEN D, v, f, L; long i, j, l, c; if (s > 0 || !Z_ispowerall(N, 6, &f)) return NULL; D = divisors(f); l = lg(D); if (field) { GEN d = checkfield(field, 3), g; if (!Z_issquareall(d, &g) || !dvdii(f, g)) return NULL; v = cgetg(l, t_VEC); for (i = 2, c = 1; i < l; i++) { GEN t, g3 = gel(D, i); long lt; if (equalii(g3, g) || !equalii(lcmii(g,g3), f)) continue; t = makeC3_f(g3); lt = lg(t); if (lt == 1) continue; for (j = 1; j < lt; j++) gel(t,j) = polredabs(polcompositum0(field, gel(t,j), 2)); gel(v, c++) = t; } setlg(v, c); return gtoset_shallow(myshallowconcat1(v)); } L = const_vec(l-1, NULL); v = cgetg(l * (l-1) / 2 + 1, t_VEC); for (i = c = 1; i < l; i++) { GEN g = gel(D,i); for (j = i; j < l; j++) if (equalii(lcmii(g, gel(D,j)), f)) { GEN Li, Lj, w; long li, lj, a, b, cw; if (!gel(L,i)) gel(L,i) = makeC3_f(g); if (!gel(L,j)) gel(L,j) = makeC3_f(gel(D,j)); Li = gel(L,i); li = lg(Li); Lj = gel(L,j); lj = lg(Lj); w = cgetg(li * lj, t_VEC); for (a = cw = 1; a < li; a++) for (b = i == j? a+1: 1; b < lj; b++) gel(w, cw++) = polredabs(polcompositum0(gel(Li,a), gel(Lj,b), 2)); setlg(w, cw); gel(v, c++) = w; } } setlg(v, c); v = gtoset_shallow(myshallowconcat1(v)); return s == -2? vecs(5, v): v; } static GEN makeC3C3resolvent(GEN pol, long flag) { GEN V = mynfsubfields(pol, 3); if (lg(V) != 5) pari_err_BUG("makeC3C3resolvent"); if (flag < 2) return condrel(gel(V,1), pol, flag); if (flag == 2) return V; return mkvec4(condrel_i(gel(V,1), pol), condrel_i(gel(V,2), pol), condrel_i(gel(V,3), pol), condrel_i(gel(V,4), pol)); } /* x, y > 0 */ static GEN lcmiu(GEN x, ulong y) { return muliu(x, y / ugcd(umodiu(x,y), y)); } static GEN lcmuu(ulong x, ulong y) { return muluu(x, y / ugcd(x, y)); } GEN nflist_C3C3_worker(GEN gi, GEN w, GEN F, GEN X) { pari_sp av = avma; long c, j, i = itos(gi), l = lg(w), f = F[i], x = X[1], xinf = X[2]; GEN P3 = gel(w, i), v = cgetg(l, t_VEC); for (j = i + 1, c = 1; j < l; j++) if (ok_intu(lcmuu(f, F[j]), x, xinf)) gel(v, c++) = polredabs(polcompositum0(P3, gel(w, j), 2)); setlg(v, c); return gerepilecopy(av, v); } static GEN makeC3C3vec(GEN X, GEN Xinf, GEN field, long s) { GEN F, v, v3; long j, l, x, xinf; if (s > 0) return NULL; x = floorsqrtn(X, 6); v3 = C3vec_F(x, 1, &F); if (!v3) return NULL; v3 = zvV_to_ZXV(v3); l = lg(v3); v = cgetg((l - 1) * l / 2 + 1, t_VEC); xinf = ceilsqrtn(Xinf, 6); if (field) { GEN F3, D3 = checkfield(field, 3); long c; if (!Z_issquareall(D3, &F3)) return NULL; for (j = c = 1; j < l; j++) if (ok_intu(lcmiu(F3, F[j]), x, xinf) && !ZX_equal(gel(v3,j), field)) gel(v, c++) = polredabs(polcompositum0(field, gel(v3,j), 2)); setlg(v, c); } else { GEN T = mkvec3(v3, F, mkvecsmall2(x,xinf)); v = nflist_parapply("_nflist_C3C3_worker", T, identity_ZV(l-1)); v = myshallowconcat1(v); } v = gtoset_shallow(v); return s == -2? vecs(5, v): v; } /************************************************************************/ /* S32 */ /************************************************************************/ static GEN makepolS32(GEN P1, GEN P2) { GEN G = galoissplittinginit(polcompositum0(P1, P2, 2), utoipos(36)); GEN vH = galoissubgroups(G), g = mkvec2(gal_get_gen(G), gal_get_orders(G)); long i, l = lg(vH); for (i = 1; i < l; i++) { GEN H = gel(vH, i); if (group_order(H) == 6 && !group_isabelian(H) /*S3*/ && group_subgroup_is_faithful(g, H)) return polredabs(galoisfixedfield(G, H, 1, 0)); } return NULL; /*LCOV_EXCL_LINE*/ } static GEN extractS3cond(GEN V3, GEN sqX, GEN field, long s) { GEN v, v2 = NULL; long l = lg(V3), c, c2, i; v = cgetg(l, t_VEC); if (s == 3) v2 = cgetg(l, t_VEC); for (i = c = c2 = 1; i < l; i++) { GEN pol = gel(V3, i), D, F, DF; (void)nfcoredisc2(pol, &D, &F); DF = mulii(D, F); if (abscmpii(DF, sqX) <= 0) { GEN ind = field || s == 3 ? gen_0 : utoipos(c); GEN V = mkvecn(5, pol, F, mulii(sqri(DF), D), D, ind); if (s != 3 || signe(D) > 0) gel(v, c++) = V; else gel(v2, c2++) = V; } } setlg(v, c); if (s != 3) return v; setlg(v2, c2); return mkvec2(v, v2); } static GEN makeS32common(GEN V3, GEN X, GEN Xinf, GEN field, long s); static GEN makeS32(GEN N, GEN field, long s) { long s3, i, c, l; GEN v, t; if (s == 1) return NULL; s3 = -1; if (s == 0) s3 = 0; if (s == 2) s3 = 1; v = divisors(N); l = lg(v); for (i = 2, c = 1; i < l; i++) if ((t = makeDL(3, gel(v, i), NULL, s3))) gel(v,c++) = t; setlg(v,c); return makeS32common(myshallowconcat1(v), N, N, field, s); } static GEN group_add_elt(GEN H, GEN g, long r) { return mkvec2(vec_append(gel(H,1),g), vecsmall_append(gel(H,2), r)); } static GEN makeS32resolvent(GEN pol, long flag) { GEN w, g1, g2, H1, H2, G = galoissplittinginit(pol, utoipos(36)); GEN v = galoissubgroups(G), g = galois_group(G); long i, c, l = lg(v); for (i = c = 1; i < l; i++) { GEN H = gel(v,i); if (group_order(H) == 6 && group_subgroup_isnormal(g,H)) gel(v, c++) = H; } H1 = gel(v,1); g1 = gel(H1,1); H2 = gel(v,2); g2 = gel(H2,1); /* G = H1 x H2, Hi ~ S3 */ H1 = group_add_elt(H1, gel(g2,2), 2); H2 = group_add_elt(H2, gel(g1,2), 2); w = condrel_dummy(galoisfixedfield(G,H1,1,0), flag); if (flag >= 2) w = mkvec2(w, condrel_dummy(galoisfixedfield(G,H2,1,0),flag)); return w; } /* s = 0: real, real; s = 1 imp; s = 2: imag, imag; s = 3: real, imag. */ GEN nflist_S32_worker(GEN S1, GEN X, GEN Xinf, GEN w, GEN gs) { pari_sp av = avma; GEN pol1 = gel(S1, 1), F1 = gel(S1, 2), A1 = gel(S1, 3), D1 = gel(S1, 4), v; long c, j, l = lg(w), i = itos(gel(S1, 5)), s = gs[1]; v = cgetg(l, t_VEC); for (j = s == 3 ? 1 : i + 1, c = 1; j < l; j++) { GEN S2 = gel(w,j), F2 = gel(S2,2), A2 = gel(S2,3), D2 = gel(S2,4), Q,P; if (equalii(D2, D1)) continue; P = mulii(sqri(gcdii(D1,D2)), gcdii(F1,F2)); /* usually 1 */ Q = diviiexact(mulii(A1, A2), sqri(P)); if (abscmpii(Q, X) > 0) continue; P = makepolS32(pol1, gel(S2,1)); if (ok_int(nfdisc(P), X, Xinf)) gel(v, c++) = P; } setlg(v, c); return gerepilecopy(av, v); } static GEN makeS32common(GEN v, GEN X, GEN Xinf, GEN field, long s) { GEN v1, v2; v = extractS3cond(v, sqrti(X), field, s); if (field) { GEN D, F; long si; checkfield_i(field, 3); nfcoredisc2(field, &D, &F); si = signe(D); if ((si > 0 && s == 2) || (si < 0 && s == 0) || equali1(D)) return NULL; v2 = mkvec(mkvecn(5, field, F, mulii(sqri(F), powiu(D, 3)), D, gen_0)); if (s != 3) v1 = v; else v1 = gel(v, si > 0 ? 2 : 1); } else if (s != 3) v1 = v2 = v; else { v1 = gel(v, 1); v2 = gel(v, 2); } v = nflist_parapply("_nflist_S32_worker", mkvec4(X, Xinf, v2, mkvecsmall(s)), v1); return sturmseparate(gtoset_shallow(myshallowconcat1(v)), s, 6); } static GEN makeS32vec(GEN X, GEN Xinf, GEN field, long s) { long s3 = -1; GEN v; if (s == 1) return NULL; if (s == 0) s3 = 0; else if (s == 2) s3 = 1; if (!(v = makeS3vec(divis(X, s? 3: 5), gen_1, NULL, s3))) return NULL; return makeS32common(v, X, Xinf, field, s); } /************************************************************************/ /* C32:D4 */ /************************************************************************/ static GEN makeC32D4resolvent(GEN pol, long flag) { return makeC32C4resolvent(pol, flag); } static int cyc_is_trivial(GEN c) { return lg(c) == 1 || equali1(gel(c,1)); } static GEN C32D4pol(GEN bnf, GEN id) { GEN v, g3 = utoipos(3), bnr = bnrinitmod(bnf, id, 0, g3); long l, i, c; if (cyc_is_trivial(bnr_get_cyc(bnr))) return NULL; v = bnrclassfield(bnr, g3, 0, MEDDEFAULTPREC); if (typ(v) == t_POL) v = mkvec(v); l = lg(v); for (i = c = 1; i < l; i++) { GEN Q = rnfequation0(bnf, gel(v, i), 0); Q = _nfsubfields(Q, 6); if (lg(Q) > 1) { Q = polredabs(gel(Q, 1)); if (okgal1(Q, 72)) gel(v, c++) = Q; } } if (c == 1) return NULL; setlg(v, c); return v; } static GEN bigdisc(GEN P) { return mulii(nfdisc(P), nfdisc(_nfsubfields1(P, 2))); } /* v,w = factorization matrices (for ideals of the same norm), do we have * aut(v) = w ? */ static int prMconj(GEN nf, GEN v, GEN w, GEN aut) { GEN P = gel(v,1), E = gel(v,2), Q = gel(w,1), F = gel(w,2); long i, j, l = lg(P); if (lg(Q) != l) return 0; if (!ZV_equal(ZV_sort_shallow(E), ZV_sort_shallow(F))) return 0; Q = shallowcopy(Q); for (i = 1; i < l; i++) { GEN pr = gel(P,i), p = pr_get_p(pr), e = gel(E,i), pi = pr_get_gen(pr); long ep = pr_get_e(pr), fp = pr_get_f(pr); pi = nfgaloismatrixapply(nf, aut, pi); for (j = 1; j < l; j++) { GEN qr = gel(Q,j); if (!qr) continue; if (pr_get_f(qr) == fp && pr_get_e(qr) == ep && equalii(gel(F,j), e) && equalii(pr_get_p(qr), p) && nfval(nf, pi, qr)) { gel(Q,j) = NULL; break; } } } return 1; } GEN nflist_C32D4_worker(GEN P, GEN X, GEN Xinf, GEN gs) { pari_sp av = avma; GEN bd = bigdisc(P), RES = cgetg(1, t_VEC), L, bnf, nf, aut; long s = itos(gs), lim, j; if (absi_cmp(bd, X) > 0) { set_avma(av); return cgetg(1, t_VEC); } bnf = bnfY(P); nf = bnf_get_nf(bnf); aut = cycfindaut(nf); lim = itos(divii(X, absi_shallow(bd))); L = ideallistsquare(bnf, lim); for (j = 1; j <= lim; j++) { GEN v = gel(L, j); long k, lv = lg(v); for (k = 1; k < lv; k++) { GEN R, vk = gel(v, k); long m, n, c, lR; if (!vk || !(R = C32D4pol(bnf, vk))) continue; lR = lg(R); for (m = c = 1; m < lR; m++) { GEN Z = gel(R, m); if (ok_s(Z, s) && ok_int(nfdisc(Z), X, Xinf)) gel(R, c++) = Z; } if (c > 1) { setlg(R, c); RES = shallowconcat(RES, R); } for (n = k + 1; n < lv; n++) if (gel(v,n) && prMconj(nf, vk, gel(v,n), aut)) {gel(v,n)=NULL; break;} } } return gerepilecopy(av, RES); } static GEN makeC32D4vec(GEN X, GEN Xinf, GEN field, long s) { long s4; GEN v; if (s == -2) s4 = -1; else if (s == 3) s4 = 2; else s4 = s; if (field) { checkfield_i(field, 4); if (!okgal1(field, 8) || !ok_s(field,s4)) return NULL; v = mkvec(field); } else v = makeD4vec(X, gen_1, NULL, s4); v = nflist_parapply("_nflist_C32D4_worker", mkvec3(X, Xinf, stoi(s)), v); return sturmseparate(gtoset_shallow(myshallowconcat1(v)), s, 6); } static GEN makeC32D4(GEN N, GEN field, long s) { long s4, i, lv; GEN v; if (s == -2) s4 = -1; else if (s == 3) s4 = 2; else s4 = s; if (field) { GEN D = checkfield(field, 4); if (!okgal1(field, 8) || !ok_s(field,s4) || !dvdii(N, D)) return NULL; v = mkvec(field); } else { long c; GEN C; v = divisors(absi(N)); lv = lg(v); for (i = c = 1; i < lv; i++) if ((C = makeD4(gel(v, i), NULL, s4))) { long j, cC, lC = lg(C); for (j = cC = 1; j < lC; j++) if (dvdii(N, bigdisc(gel(C,j)))) gel(C, cC++) = gel(C,j); if (cC > 1) { setlg(C, cC); gel(v, c++) = C; } } if (c == 1) return NULL; setlg(v, c); v = shallowconcat1(v); } lv = lg(v); for (i = 1; i < lv; i++) gel(v,i) = nflist_C32D4_worker(gel(v,i), N, N, stoi(s)); return sturmseparate(gtoset_shallow(myshallowconcat1(v)), s, 6); } /************************************************************************/ /* Global Programs */ /************************************************************************/ static long grouptranslate(const char *g, long *t, int QT) { long ell; char r; if (QT) { r = *g; ell = itos( strtoi(g + 1) ); if (ell < 0) return 0; if (r == 'A') { *t = -2; return ell; } if (r == 'S') { *t = -1; return ell; } if (!strcmp(g, "C3")) { *t = -2; return ell; } } if (!strcmp(g, "C1")) { *t = 1; return 1; } if (!strcmp(g, "C2") || !strcmp(g, "D2")) { *t = 1; return 2; } if (!strcmp(g, "C3")) { *t = 1; return 3; } if (!strcmp(g, "S3") || !strcmp(g,"D3")) { *t = 2; return 3; } if (!strcmp(g, "C4")) { *t = 1; return 4; } if (!strcmp(g, "V4")) { *t = 2; return 4; } if (!strcmp(g, "D4")) { *t = 3; return 4; } if (!strcmp(g, "A4")) { *t = 4; return 4; } if (!strcmp(g, "S4")) { *t = 5; return 4; } if (!strcmp(g, "C5")) { *t = 1; return 5; } if (!strcmp(g, "D5")) { *t = 2; return 5; } if (!strcmp(g, "F5") || !strcmp(g, "M20")) { *t = 3; return 5; } if (!strcmp(g, "A5")) { *t = 4; return 5; } if (!strcmp(g, "A5cond")) { *t = 9; return 5; } if (!strcmp(g, "C6")) { *t = 1; return 6; } if (!strcmp(g, "D6")) { *t = 2; return 6; } if (!strcmp(g, "C7")) { *t = 1; return 7; } if (!strcmp(g, "D7")) { *t = 2; return 7; } if (!strcmp(g, "M21")) { *t = 3; return 7; } if (!strcmp(g, "M42")) { *t = 4; return 7; } if (!strcmp(g, "C9")) { *t = 1; return 9; } if (!strcmp(g, "D9")) { *t = 3; return 9; } if (QT) { if (!strcmp(g, "C8")) { *t = 1; return 8; } if (!strcmp(g, "D8")) { *t = 2; return 8; } if (!strcmp(g, "C10")) { *t = 1; return 10; } if (!strcmp(g, "D10")) { *t = 3; return 10; } if (!strcmp(g, "C11")) { *t = 1; return 11; } if (!strcmp(g, "D11")) { *t = 2; return 11; } } r = *g; ell = itos( strtoi(g + 1) ); if (ell >= 8 && uisprime(ell)) { if (r == 'C') { *t = 1; return ell; } if (r == 'D') { *t = 2; return ell; } } *t = 0; return 0; } static long group_nTk(GEN g, long *t, int QT) { long L[] = { 0, /* https://oeis.org/A002106 */ 1,1,2,5,5,16,7,50,34,45,8,301,9,63,104,1954,10, 983,8,1117,164,59,7,25000,211,96,2392,1854,8,5712, 12,2801324,162,115,407,121279,11,76,306,315842,10, 9491,10,2113,10923,56,6 }; long N = numberof(L), n, k; if (lg(g) != 3 || !RgV_is_ZV(g)) { *t = 0; return 0; } n = itos(gel(g,1)); if (n <= 0) return 0; if (n >= N) pari_err_IMPL(stack_sprintf("group nTk with n > %ld", N-1)); *t = k = itos(gel(g,2)); if (k <= 0 || k > L[n]) { char *s; s = stack_sprintf("incorrect group %ldTk with k = %ld not in [1,%ld]", n, k, L[n]); pari_err(e_MISC, s); } if (!QT) { if (n <= 9) { long v[] = { 0, 1, 1, 2, 5, 4, 13, 4, 0, 3 }; return k <= v[n]? n: 0; } return (uisprime(n) && k <= 2)? n: 0; } if (n <= 2) *t = -2; /* An */ else if (k == L[n]) *t = -1; /* Sn */ else if (k == L[n]-1) *t = -2; /* An */ return n; } static int okfield(GEN F) { return typ(F) == t_POL && RgX_is_ZX(F) && ZX_is_irred(F); } static GEN nfmakenum(long n, long t, GEN N, GEN field, long s) { GEN v = NULL; switch(100 * n + t) { case 101: return makeC1(N, field, s); case 201: return makeC2(N, field, s); case 301: return makeC3(N, field, s); case 302: return makeDL(3, N, field, s); case 401: return makeC4(N, field, s); case 402: return makeV4(N, field, s); case 403: return makeD4(N, field, s); case 404: return makeA4(N, field, s); case 405: return makeS4(N, field, s); case 501: return makeC5(N, field, s); case 502: return makeDL(5, N, field, s); case 503: return makeMgen(5, 4, N, field, s); /*F5*/ case 504: return makeA5(N, s); case 509: return makeA5cond(N, s); case 601: return makeC6(N, field, s); case 602: return makeS36(N, field, s); case 603: return makeD612(N, field, s); case 604: return makeA46(N, field, s); case 605: return makeS3C3(N, field, s); case 606: return makeA462(N, field, s); case 607: return makeS46P(N, field, s); case 608: return makeS46M(N, field, s); case 609: return makeS32(N, field, s); case 610: return makeC32C4(N, field, s); case 611: return makeS462(N, field, s); case 612: return makeA56(N, s); case 613: return makeC32D4(N, field, s); case 701: return makeCL(7, N, field, s); case 702: return makeDL(7, N, field, s); case 703: return makeMgen(7, 3, N, field, s); /*M21*/ case 704: return makeMgen(7, 6, N, field, s); case 901: return makeC9(N, field, s); case 902: return makeC3C3(N, field, s); case 903: return makeD9(N, field, s); } if (!v && uisprime(n)) switch(t) { case 1: return makeCL(n, N, field, s); case 2: return makeDL(n, N, field, s); } return NULL;/*LCOV_EXCL_LINE*/ } /* deg(pol) < 8 */ static GEN nfresolvent_small(GEN pol, long flag) { long deg = degpol(pol), dP, s; GEN G; if (deg == 1) return makeC1resolvent(flag); if (deg == 2) return makeC2resolvent(pol, flag); G = polgalois(pol, DEFAULTPREC); dP = itos(gel(G,1)); if (deg == 3) return dP == 3? makeC3resolvent(pol, flag) : makeS3resolvent(pol, flag); s = itos(gel(G,2)); if (deg == 4) { if (dP == 4) return s == -1? makeC4resolvent(pol, flag) : makeV4resolvent(pol, flag); if (dP == 8) return condrelresolvent(pol, 2, flag); /*D4*/ return makeA4S4resolvent(pol, flag); } if (deg == 5) { if (dP == 5) return makeCLresolvent(5, pol, flag); if (dP == 10) return makeDLresolvent(5, pol, flag); if (dP == 20) return makeMgenresolvent(5, 4, pol, flag); /*F5*/ if (dP == 60) return makeA5resolvent(pol, flag); } if (deg == 6) { if (dP == 6 && s == -1) { /* works both with new_galois_format set or unset */ long k = itos(gel(G,3)); return k == 1? makeC6resolvent(pol, flag) : makeS36resolvent(pol, flag); } if (dP == 12) return s == -1? makeD612resolvent(pol, flag) : condrelresolvent(pol,3,flag); /*A46*/ if (dP == 18) return condrelresolvent(pol,2,flag); /*S3C3*/ if (dP == 24) return condrelresolvent(pol,3,flag); /*S46P,S46M,A462*/ if (dP == 36) return (s == 1)? makeC32C4resolvent(pol, flag) : makeS32resolvent(pol, flag); if (dP == 48) return condrelresolvent(pol,3,flag); /*S462*/ if (dP == 60) return makeA56resolvent(pol,flag); if (dP == 72) return makeC32D4resolvent(pol, flag); } if (deg == 7) { if (dP == 7) return makeCLresolvent(7, pol, flag); if (dP == 14) return makeDLresolvent(7, pol, flag); if (dP == 21) return makeMgenresolvent(7, 3, pol, flag); /*M21*/ if (dP == 42) return makeMgenresolvent(7, 6, pol, flag); /*M42*/ } return gen_0; } static GEN nfresolvent_i(GEN pol, long flag) { long d; GEN G; if (!okfield(pol)) pari_err_TYPE("nfresolvent", pol); if (flag < 0 || flag > 3) pari_err_FLAG("nfresolvent"); d = degpol(pol); if (d < 8) return nfresolvent_small(pol, flag); if (d != 9 && !uisprime(d)) return gen_0; G = galoisinit(pol, NULL); if (typ(G) != t_INT) { if (d == 9) { long n = lg(gal_get_gen(G))-1; return n == 1? condrelresolvent(pol,3,flag) /*C9*/ : makeC3C3resolvent(pol, flag); /*C3xC3*/ } return makeCLresolvent(d, pol, flag); } G = galoissplittinginit(pol, utoipos(2*d)); if (gal_get_order(G) != 2*d) return gen_0; return d == 9? makeD9resolvent(G, flag): makeDLresolvent(d, pol, flag); } GEN nfresolvent(GEN pol, long flag) { pari_sp av = avma; return gerepilecopy(av, nfresolvent_i(pol, flag)); } /* 1 <= Xinf <= X */ static GEN nfmakevecnum(long n, long t, GEN X, GEN Xinf, GEN field, long s) { switch(n * 100 + t) { case 101: return makeC1vec(Xinf, field, s); case 201: return makeC2vec(X, Xinf, field, s); case 301: return makeC3vec(X, Xinf, field, s); case 302: return makeS3vec(X, Xinf, field, s); case 401: return makeC4vec(X, Xinf, field, s); case 402: return makeV4vec(X, Xinf, field, s); case 403: return makeD4vec(X, Xinf, field, s); case 404: return makeA4S4vec(1, X, Xinf, field, s); case 405: return makeA4S4vec(0, X, Xinf, field, s); case 501: return makeC5vec(X, Xinf, field, s); case 502: return makeDLvec(5, X, Xinf, field, s); case 503: return makeMgenvec(5, 4, X, Xinf, field, s); /*F5*/ case 504: return makeA5vec(X, Xinf, field, s); case 509: return makeA5condvec(X, Xinf, field, s); case 601: return makeC6vec(X, Xinf, field, s); case 602: return makeS36vec(X, Xinf, field, s); case 603: return makeD612vec(X, Xinf, field, s); case 604: return makeA46S46Pvec(12, X, Xinf, field, s);/*A46S*/ case 605: return makeS3C3vec(X, Xinf, field, s); case 606: return makeA462vec(X, Xinf, field, s); case 607: return makeA46S46Pvec(24, X, Xinf, field, s); /*S46P*/ case 608: return makeS46Mvec(X, Xinf, field, s); case 609: return makeS32vec(X, Xinf, field, s); case 610: return makeC32C4vec(X, Xinf, field, s); case 611: return makeS462vec(X, Xinf, field, s); case 612: return makeA56vec(X, Xinf, s); case 613: return makeC32D4vec(X, Xinf, field, s); case 701: return makeCLvec(7, X, Xinf, field, s); case 702: return makeDLvec(7, X, Xinf, field, s); case 703: return makeMgenvec(7, 3, X, Xinf, field, s); /*M21*/ case 704: return makeMgenvec(7, 6, X, Xinf, field, s); /*M41*/ case 901: return makeC9vec(X, Xinf, field, s); case 902: return makeC3C3vec(X, Xinf, field, s); case 903: return makeD9vec(X, Xinf, field, s); } if (uisprime(n)) switch(t) { case 1: return makeCLvec(n, X, Xinf, field, s); case 2: return makeDLvec(n, X, Xinf, field, s); } return NULL;/*LCOV_EXCL_LINE*/ } /* s > -2 */ static GEN nfmakesomehard(long n, long t, long s) { pari_sp av = avma; long i; for (i = 1;; i++, set_avma(av)) { GEN v = nfmakevecnum(n, t, int2n(18 + 2*i), gen_1, NULL, s); if (v && lg(v) > 2) return v; } } static long minlim(GEN v) { long i, m = LONG_MAX; if (!v) return m; for (i = lg(v)-1; i; i--) if (v[i] && m > v[i]) m = v[i]; return m; } static GEN nfmakesome(long n, long t, long s) { GEN v = NULL; long lim, flag = 0; switch(n * 100 + t) { case 101: v = mkvecsmall(1); break; case 201: v = mkvecsmall2(33, 24); break; case 301: v = mkvecsmall2(3969, 0); break; case 302: v = mkvecsmall2(568, 108); break; case 401: v = mkvecsmall3(35152, 0, 44217); break; case 402: v = mkvecsmall3(14400, 0, 1225); break; case 403: v = mkvecsmall3(5125, 1375, 549); break; case 404: v = mkvecsmall3(270400, 0, 29241); break; case 405: v = mkvecsmall3(8468, 976, 1076); break; case 501: v = mkvecsmall3(1073283121, 0, 0); break; case 502: v = mkvecsmall3(4330561, 0, 51529); break; case 503: v = mkvecsmall3(LONG_MAX, 0, 253125); break; case 504: v = mkvecsmall3(11812969, 0, 149769); break; case 509: v = mkvecsmall3(5105, 0, 992); break; case 601: v = mkvecsmall4(4148928, 0, 0, 2250423); break; case 602: v = mkvecsmall4(32166277, 0, 0, 273375); break; case 603: v = mkvecsmall4(9045125, 0, 242000, 86528); break; case 604: v = mkvecsmall4(125238481, 0, 4439449, 0); break; case 605: v = mkvecsmall4(7442000, 0, 0, 143883); break; case 606: v = mkvecsmall4(2115281, 419904, 373977, 0); break; case 607: v = mkvecsmall4(12730624, 0, 118336, 0); break; case 608: v = mkvecsmall4(183250432, 0, 440711081, 13144256); break; case 609: v = mkvecsmall4(LONG_MAX, 0, 1382400, 1494108); break; case 610: v = mkvecsmall4(765905625, 0, 4950625, 0); break; case 611: v = mkvecsmall4(5695040, 941872, 57661, 37479); break; case 612: v = mkvecsmall4(185313769, 0, 1907161, 0); break; case 613: v = mkvecsmall4(LONG_MAX, 221875, 87625, 44496); break; case 701: v = mkvecsmall4(LONG_MAX, 0, 0, 0); break; case 702: v = mkvecsmall4(LONG_MAX, 0, 0, 80062991); break; case 703: v = mkvecsmall4(LONG_MAX, 0, 0, 0); break; case 704: v = mkvecsmall4(LONG_MAX, 0, 0, LONG_MAX); break; case 901: v = mkvecsmall5(LONG_MAX, 0, 0, 0, 0); break; case 902: v = mkvecsmall5(LONG_MAX, 0, 0, 0, 0); break; case 903: v = mkvecsmall5(LONG_MAX, 0, 0, 0, LONG_MAX); break; } if (!v) flag = uisprime(n) && t <= 2? t: 0; if (s == -2) { long i, l = (n >> 1) + 2; GEN W = cgetg(l, t_VEC); for (i = 1; i < l; i++) { GEN w = NULL; if (!v) { if (i == 1 || (i == l-1 && flag == 2)) w = nfmakesomehard(n, t, i-1); } else if (v[i] == LONG_MAX) w = nfmakesomehard(n, t, i-1); else if (v[i]) w = nfmakevecnum(n, t, utoipos(v[i]), gen_1, NULL, i-1); gel(W, i) = w? w: cgetg(1, t_VEC); } return W; } else if (s == -1) lim = minlim(v); else { lim = v[s + 1]; if (!lim) return cgetg(1, t_VEC); } if (lim == LONG_MAX) return nfmakesomehard(n, t, s); return nfmakevecnum(n, t, utoipos(lim), gen_1, NULL, s); } GEN nflist(GEN GP, GEN N, long s, GEN field) { pari_sp av = avma; GEN v, X, Xinf; long n = 0, t = 0, tp = typ(GP); long QT = N && typ(N) == t_POL; if (s < -2) pari_err_DOMAIN("nflist", "s", "<", gen_m2, stoi(s)); if (field && !okfield(field)) pari_err_TYPE("nflist", field); switch(tp) { case t_STR: n = grouptranslate(GSTR(GP), &t, QT); break; case t_VEC: n = group_nTk(GP, &t, QT); break; } if (!n) { const char *s = "unsupported group (%Ps). Use one of\n\ \"C1\"=[1,1];\n\ \"C2\"=[2,1];\n\ \"C3\"=[3,1], \"S3\"=[3,2];\n\ \"C4\"=[4,1], \"V4\"=[4,2], \"D4\"=[4,3], \"A4\"=[4,4], \"S4\"=[4,5];\n\ \"C5\"=[5,1], \"D5\"=[5,2], \"F5\"=\"M20\"=[5,3], \"A5\"=[5,4];\n\ \"C6\"=[6,1], \"D6\"=[6,2], [6,3], [6,4],..., [6,13];\n\ \"C7\"=[7,1], \"D7\"=[7,2], \"M21\"=[7,3], \"M42\"=[7,4];\n\ \"C9\"=[9,1], [9,2], \"D9\"=[9,3].\"\n\ Also supported are \"Cp\"=[p,1] and \"Dp\"=[p,2] for any odd prime p"; pari_err(e_MISC, s, GP); } if (QT) return gerepilecopy(av, nflistQT(n, t, varn(N))); if (s > (n >> 1)) return cgetg(1, t_VEC); if (!N) return gerepilecopy(av, nfmakesome(n, t, s)); switch(typ(N)) { case t_INT: X = Xinf = N; break; case t_VEC: case t_COL: if (lg(N) == 3) { Xinf = gel(N,1); X = gel(N,2); break; } default: pari_err_TYPE("nflist", N); Xinf = X = NULL;/*LCOV_EXCL_LINE*/ } if (typ(X) != t_INT) { X = gfloor(X); if (typ(X) != t_INT) pari_err_TYPE("nflist", N); } if (typ(Xinf) != t_INT) { Xinf = gceil(Xinf); if (typ(Xinf) != t_INT) pari_err_TYPE("nflist", N); } if (signe(Xinf) <= 0) { if (signe(Xinf) < 0) pari_err_DOMAIN("nflist", "Xinf", "<=", gen_0, Xinf); Xinf = gen_1; } if (signe(X) < 0) pari_err_DOMAIN("nflist", "X", "<=", gen_0, X); switch(cmpii(Xinf, X)) { case 1: v = NULL; break; case 0: v = nfmakenum(n, t, X, field, s); break; default: v = nfmakevecnum(n, t, X, Xinf, field, s); } if (!v) { set_avma(av); if (s != -2) return cgetg(1,t_VEC); retconst_vec((n>>1) + 1, cgetg(1,t_VEC)); } return gerepilecopy(av, v); } /*****************************************************************/ /* Polsubcyclo */ /*****************************************************************/ /* auxiliary functions assume that trivial impossibilities for s or n * are already handled in caller */ static GEN polsubcycloC2(GEN n, long s) { GEN V = divisorsdisc(n, s), W; long l = lg(V), i; W = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(W, i) = quadpoly_i(gel(V, i)); return W; } static GEN polsubcycloC2_i(GEN n, long s) { long l, i; GEN V; int p, m; if (typ(n) == t_VEC) { fa_is_fundamental_pm(gel(n,1), gel(n,2), s, &p, &m); n = gel(n,1); } else is_fundamental_pm(n, s, &p, &m); if (!(V = fund_pm(n, p, m))) return NULL; l = lg(V); for (i = 1; i < l; i++) gel(V, i) = quadpoly_i(gel(V, i)); return V; } static GEN polsubcycloC3_i(GEN n) { GEN P; return checkcondC3(n, &P)? makeC3_i(typ(n) == t_VEC? gel(n,1): n, P) : NULL; } /* Cyclic cubic subfields of Q(zeta_n). */ static GEN polsubcycloC3(GEN n) { long i, l, c; GEN D = divisors_factored(n); l = lg(D); for (i = 2, c = 1; i < l; i++) { GEN v = polsubcycloC3_i(gel(D,i)); if (v) gel(D,c++) = v; } setlg(D, c); return myshallowconcat1(D); } static GEN makeV4pairssimple(GEN D, GEN P, GEN f) { long l = lg(D), n = l-1, i, j, c; GEN R = cgetg((n-1) * n / 2 + 1, t_VEC); for (i = c = 1; i < n; i++) { GEN Di = gel(D,i); for (j = i + 1; j < l; j++) { if (f && !equalii(lcmii(Di, gel(D,j)), f)) continue; gel(R, c++) = polcompositum0(gel(P,i), gel(P,j), 2); } } setlg(R,c); return R; } static GEN makeV4pairs(GEN D, GEN P, GEN f) { long l = lg(D), n = l-1, i, j, c; GEN V = cgetg(l, t_VEC), R = cgetg((n-1) * n / 2 + 1, t_VEC); for (i = 1; i < l; i++) gel(V, i) = const_vecsmall(n, 1); for (i = c = 1; i < n; i++) { GEN C = gel(V,i); for (j = i + 1; j < l; j++) if (C[j]) { /* Di, Dj fundamental discs */ GEN d, Di = gel(D,i), Dj = gel(D,j), g = gcdii(Di, Dj); long k; if (!is_pm1(g)) { Di = diviiexact(Di, g); Dj = diviiexact(Dj, g); } d = mulii(Di, Dj); if (f && !equalii(f, mulii(d, g))) continue; if (Mod4(d) > 1) d = shifti(d, 2); k = vecsearch(D, d, NULL); /* d = coredisc(Di*Dj), j < k */ C[k] = gel(V, j)[k] = 0; gel(R, c++) = polcompositum0(gel(P,i), gel(P,j), 2); } } setlg(R, c); return R; } static GEN polsubcycloV4_i(GEN V, long s, GEN n) { long i, l = lg(V); GEN P = cgetg(l, t_VEC); if (s <= 0) ZV_sort_inplace(V); /* for vecsearch */ for (i = 1; i < l; i++) gel(P,i) = quadpoly_i(gel(V,i)); return (s <= 0)? makeV4pairs(V, P, n): makeV4pairssimple(V, P, n); } static GEN polsubcycloC5(GEN n) { GEN v, D = divisors_factored(n), T = C5bnf(); long i, c, l = lg(D); for (i = 2, c = 1; i < l; i++) if ((v = polsubcycloC5_i(gel(D,i), T))) gel(D,c++) = v; setlg(D, c); return myshallowconcat1(D); } /* ell odd prime */ static GEN makeCLall(long ell, GEN F) { GEN D = divisors(F); long i, l = lg(D); for (i = 1; i < l; i++) gel(D,i) = makeCL_f(ell, gel(D,i)); return shallowconcat1(D); } static GEN polsubcycloC6(GEN n, long s) { GEN v3 = polsubcycloC3(n), v2, R; long n3 = lg(v3) - 1, n2, i, j, c; if (!n3) return v3; v2 = polsubcycloC2(n, s); n2 = lg(v2) - 1; if (!n2) return NULL; R = cgetg(n2 * n3 + 1, t_VEC); for (i = c = 1; i <= n3; i++) { GEN p3 = gel(v3, i); for (j = 1; j <= n2; j++) gel(R, c++) = polcompositum0(p3, gel(v2,j), 2); } return R; } static GEN polsubcycloC6_i(GEN n, long s) { GEN D = divisors_factored(n), R; long l = lg(D), i, j, c, L = 2 * (l-1) * omega(n); if (typ(n) == t_VEC) n = gel(n,1); R = cgetg(L + 1, t_VEC); c = 1; for (i = 2; i < l; i++) { GEN d = gel(D, i), V2 = polsubcycloC2_i(d, s); long l2; if (!V2) continue; l2 = lg(V2); if (typ(d) == t_VEC) d = gel(d,1); for (j = 1; j < l; j++) { GEN V3, e = gel(D, j); long l3, i3; if (!equalii(lcmii(d, typ(e) == t_VEC? gel(e,1): e), n)) continue; V3 = polsubcycloC3_i(e); if (!V3) continue; l3 = lg(V3); for (i3 = 1; i3 < l3; i3++) { GEN p3 = gel(V3, i3); long i2; for (i2 = 1; i2 < l2; i2++) gel(R, c++) = polcompositum0(p3, gel(V2,i2), 2); } } } setlg(R, c); return R; } /* fli = 1 for conductor n, else all subfields of Q(zeta_n) */ static GEN polsubcyclofast_i(GEN n, long ell, long s, long fli) { GEN N, fa = check_arith_pos(n, "polsubcyclofast"); if (fa && typ(n) != t_VEC) n = mkvec2(factorback(fa), fa); /* n either t_INT or [N, factor(N)] */ if (ell <= 0 && ell != -4) pari_err_DOMAIN("polsubcyclofast", "d", "<=", gen_0, stoi(ell)); /* translate wrt r2 for compatibility with nflist functions */ if (!s) s = odd(ell)? 0: -1; else if (s == 1) s = 0; else if (s ==-1) { if (odd(ell)) return NULL; s = labs(ell) >> 1; } else pari_err_FLAG("polsubcyclo"); N = fa? gel(n, 1): n; if (Mod4(N) == 2) { if (fli) return NULL; N = shifti(N, -1); if (fa) { /* remove 2^1 */ GEN P = vecsplice(gel(fa,1), 1), E = vecsplice(gel(fa,2), 1); n = mkvec2(N, mkmat2(P, E)); } } if (ell == 1) { if (fli && !equali1(N)) return NULL; retmkvec(pol_x(0)); } if (equali1(N)) return NULL; if (ell == -4) return polsubcycloV4_i(divisorsdisc(n,s), s, fli? N: NULL); if (ell >= 7) return fli? makeCLall(ell,n): makeCL_f(ell,n); switch(ell) { case 2: return fli? polsubcycloC2_i(n, s): polsubcycloC2(n, s); case 3: return fli? polsubcycloC3_i(n): polsubcycloC3(n); case 4: return fli? polsubcycloC4_i(n, s, fli, NULL): polsubcycloC4(n, s); case 5: return fli? polsubcycloC5_i(n, NULL): polsubcycloC5(n); case 6: return fli? polsubcycloC6_i(n, s): polsubcycloC6(n, s); } return NULL; /* LCOV_EXCL_LINE */ } GEN polsubcyclofast(GEN n, long ell, long s, long fli) { pari_sp av = avma; GEN v = polsubcyclofast_i(n, ell, s, fli); if (!v) { set_avma(av); return cgetg(1, t_VEC); } return gerepilecopy(av, v); } pari-2.17.2/src/basemath/lambert.c0000644000175000017500000003356414760123736015355 0ustar billbill/* Copyright (C) 2021 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" /***********************************************************************/ /** LAMBERT's W_K FUNCTIONS **/ /***********************************************************************/ /* roughly follows Veberic, https://arxiv.org/abs/1003.1628 */ static double dblL1L2(double L1) { double L2 = log(-L1), LI = 1 / L1, N2, N3, N4, N5; N2 = (L2-2.)/2.; N3 = (6.+L2*(-9.+2.*L2))/6.; N4 = (-12.+L2*(36.+L2*(-22.+3*L2)))/12.; N5 = (60.+L2*(-300.+L2*(350.+L2*(-125.+12*L2))))/60.; return L1-L2+L2*LI*(1+LI*(N2+LI*(N3+LI*(N4+LI*N5)))); } /* rough approximation to W0(a > -1/e), < 1% relative error */ double dbllambertW0(double a) { if (a < -0.2583) { const double c2 = -1./3, c3 = 11./72, c4 = -43./540, c5 = 769./17280; double p = sqrt(2 * (M_E * a + 1)); if (a < -0.3243) return -1+p*(1+p*(c2+p*c3)); return -1+p*(1+p*(c2+p*(c3+p*(c4+p*c5)))); } else { double Wd = log(1.+a); Wd *= (1.-log(Wd/a))/(1.+Wd); if (a < 0.6482 && a > -0.1838) return Wd; return Wd*(1.-log(Wd/a))/(1.+Wd); } } /* uniform approximation to W0, at least 15 bits. */ static double dbllambertW0init(double a) { if (a < -0.323581) { const double c2 = 1./3., c3 = 11./72., c4 = 43./540., c5 = 769./17280.; const double c6 = 221./8505., c7 = 680863./43545600.; const double c8 = 1963./204120., c9 = 226287557./37623398400.; double p = M_E * a + 1; if (p <= 0) return -1; p = -sqrt(2 * p); return -(1.+p*(1.+p*(c2+p*(c3+p*(c4+p*(c5+p*(c6+p*(c7+p*(c8+p*c9))))))))); } if (a < 0.145469) { const double a1 = 5.931375, a2 = 11.392205, a3 = 7.338883, a4 = 0.653449; const double b1 = 6.931373, b2 = 16.823494, b3 = 16.430723, b4 = 5.115235; double n = 1.+a*(a1+a*(a2+a*(a3+a*a4))); double d = 1.+a*(b1+a*(b2+a*(b3+a*b4))); return a * n / d; } if (a < 8.706658) { const double a1 = 2.445053, a2 = 1.343664, a3 = 0.148440, a4 = 0.000804; const double b1 = 3.444708, b2 = 3.292489, b3 = 0.916460, b4 = 0.053068; double n = 1.+a*(a1+a*(a2+a*(a3+a*a4))); double d = 1.+a*(b1+a*(b2+a*(b3+a*b4))); return a * n / d; } else { double w = log(1.+a); w *= (1.-log(w/a)) / (1.+w); return w * (1.-log(w/a)) / (1.+w); } } /* rough approximation to W_{-1}(0 > a > -1/e), < 1% relative error */ double dbllambertW_1(double a) { if (a < -0.2464) { const double c2 = -1./3, c3 = 11./72, c4 = -43./540, c5 = 769./17280; double p = -sqrt(2 * (M_E * a + 1)); if (a < -0.3243) return -1+p*(1+p*(c2+p*c3)); return -1+p*(1+p*(c2+p*(c3+p*(c4+p*c5)))); } else { double Wd; a = -a; Wd = -log(a); Wd *= (1.-log(Wd/a))/(1.-Wd); if (a < 0.0056) return -Wd; return -Wd*(1.-log(Wd/a))/(1.-Wd); } } /* uniform approximation to W_{-1}, at least 15 bits. */ static double dbllambertW_1init(double a) { if (a < -0.302985) { const double c2 = 1./3., c3 = 11./72., c4 = 43./540., c5 = 769./17280.; const double c6 = 221./8505., c7 = 680863./43545600.; const double c8 = 1963./204120., c9 = 226287557./37623398400.; double p = M_E * a + 1; if (p <= 0) return -1; p = sqrt(2 * p); return -(1.+p*(1.+p*(c2+p*(c3+p*(c4+p*(c5+p*(c6+p*(c7+p*(c8+p*c9))))))))); } if (a <= -0.051012) { const double a0 = -7.814176, a1 = 253.888101, a2 = 657.949317; const double b1 = -60.439587, b2 = 99.985670, b3 = 682.607399; const double b4 = 962.178439, b5 = 1477.934128; double n = a0+a*(a1+a*a2); double d = 1+a*(b1+a*(b2+a*(b3+a*(b4+a*b5)))); return n / d; } return dblL1L2(log(-a)); } /* uniform approximation to more than 46 bits, 50 bits away from -1/e; * branch = -1 or 0 */ static double dbllambertWfritsch(GEN ga, int branch) { double a, z, w1, q, w; if (expo(ga) >= 0x3fe) { /* branch = 0 */ double w = dbllog2(ga) * M_LN2; /* ~ log(1+a) ~ log a */ return w * (1.+w-log(w)) / (1.+w); } a = rtodbl(ga); w = branch? dbllambertW_1init(a): dbllambertW0init(a); if (w == -1.|| w == 0.) return w; z = log(a / w) - w; w1 = 1. + w; q = 2. * w1 * (w1 + (2./3.) * z); return w * (1 + (z / w1) * (q - z) / (q - 2 * z)); } static double dbllambertWhalleyspec(double loga) { double w = dblL1L2(loga); for(;;) { double n = w + log(-w) - loga, d = 1 - w, r = n / (d + n / d); w *= 1 - r; if (r < 2.e-15) return w; } } /* k = 0 or -1. */ static GEN lambertW(GEN z, long k, long prec) { pari_sp av = avma; long bit = prec2nbits(prec), L = -(bit / 3 + 10), ct = 0, p; double wd; GEN w, vp; if (gequal0(z) && !k) return real_0(prec); z = gtofp(z, prec); if (k == -1) { long e = expo(z); if (signe(z) >= 0) pari_err_DOMAIN("lambertw", "z", ">", gen_0, z); wd = e < -512? dbllambertWhalleyspec(dbllog2(z) * M_LN2) : dbllambertWfritsch(z, -1); } else wd = dbllambertWfritsch(z, 0); if (fabs(wd + 1) < 1e-5) { long prec2 = prec + EXTRAPREC64; GEN Z = rtor(z, prec2); GEN t = addrs(mulrr(Z, gexp(gen_1, prec2)), 1); if (signe(t) <= 0) { set_avma(av); return real_m1(prec); } if (realprec(t) < prec) { prec2 += prec - realprec(t); Z = rtor(z, prec2); t = addrs(mulrr(Z, gexp(gen_1, prec2)), 1); } t = sqrtr(shiftr(t, 1)); w = gprec_w(k == -1? subsr(-1, t) : subrs(t, 1), prec); p = prec; vp = NULL; } else { /* away from -1/e: can reduce accuracy and self-correct */ long pb; w = wd == 0.? z: dbltor(wd); vp = cgetg(30, t_VECSMALL); pb = bit; while (pb > BITS_IN_LONG * 3/4) { vp[++ct] = nbits2prec(pb); pb = (pb + 2) / 3; } p = vp[ct]; w = gprec_w(w, p); } if ((k == -1 && (bit < 192 || bit > 640)) || (k == 0 && bit > 1024)) { for(;;) { GEN t, ew, n, d; ew = mplog(divrr(w, z)); n = addrr(w, ew); d = addrs(w, 1); t = divrr(n, shiftr(d, 1)); w = mulrr(w, subsr(1, divrr(n, addrr(d, t)))); if (p >= prec && expo(n) - expo(d) - expo(w) <= L) break; if (vp) { if (--ct) p = vp[ct]; w = gprec_w(w, ct? p: prec); } } } else { for(;;) { GEN t, ew, wew, n, d; ew = mpexp(w); wew = mulrr(w, ew); n = subrr(wew, z); d = addrr(ew, wew); t = divrr(mulrr(addrs(w, 2), n), shiftr(addrs(w, 1), 1)); w = subrr(w, divrr(n, subrr(d, t))); if (p >= prec && expo(n) - expo(d) - expo(w) <= L) break; if (vp) { if (--ct) p = vp[ct]; w = gprec_w(w, ct? p: prec); } } } return gerepileupto(av, w); } /*********************************************************************/ /* Complex branches */ /*********************************************************************/ /* x *= (1 - (x + log(x) - L) / (x + 1)); L = log(z) + 2IPi * k */ static GEN lamaux(GEN x, GEN L, long *pe, long prec) { GEN n = gsub(gadd(x, glog(x, prec)), L); if (pe) *pe = maxss(4, -gexpo(n)); if (gequal0(imag_i(n))) n = real_i(n); return gmul(x, gsubsg(1, gdiv(n, gaddsg(1, x)))); } /* Complex branches, experimental */ static GEN lambertWC(GEN z, long branch, long prec) { pari_sp av = avma; GEN w, pii2k, zl, lzl, L, Lz; long bit0, si, j, fl = 0, lim = 6, lp = DEFAULTPREC, bit = prec2nbits(prec); si = gsigne(imag_i(z)); if (!si) z = real_i(z); pii2k = gmulsg(branch, PiI2(lp)); zl = gtofp(z, lp); lzl = glog(zl, lp); /* From here */ if (branch == 0 || branch * si < 0 || (si == 0 && gsigne(z) < 0 && branch == -1)) { GEN lnzl1 = gaddsg(1, glog(gneg(zl), lp)); if (si == 0) si = gsigne(lnzl1); if ((branch == 0 || branch * si < 0) && gexpo(lnzl1) < -1) { /* close to -1/e */ w = gaddsg(1, gmul(z, gexp(gen_1, prec))); w = gprec_wtrunc(w, lp); w = gsqrt(gmul2n(w, 1), lp); w = branch * si < 0? gsubsg(-1, w): gaddsg(-1, w); lim = 10; fl = 1; } if (branch == 0 && !fl && gexpo(lzl) < 0) { w = zl; fl = 1; } } if (!fl) { if (branch) { GEN lr = glog(pii2k, lp); w = gadd(gsub(gadd(pii2k, lzl), lr), gdiv(gsub(lr, lzl), pii2k)); } else { GEN p = gaddsg(1, gmul(z, gexp(gen_1, lp))); w = gexpo(p) > 0? lzl: gaddgs(gsqrt(p, lp), -1); } } /* to here: heuristic */ L = gadd(lzl, pii2k); for (j = 1; j < lim; j++) w = lamaux(w, L, NULL, lp); Lz = NULL; if (branch == 0 || branch == -1) { Lz = glog(z, prec); if (branch == -1) { long flag = 1; if (!si && signe(z) <= 0 && signe(addrs(Lz, 1))) flag = 0; if (flag) Lz = gsub(Lz, PiI2(prec)); } } w = lamaux(w, L, &bit0, lp); while (bit0 < bit || (Lz && gexpo(gsub(gadd(w, glog(w, prec)), Lz)) > 16-bit)) { long p = nbits2prec(bit0 <<= 1); L = gadd(gmulsg(branch, PiI2(p)), glog(gprec_w(z, p), p)); w = lamaux(gprec_w(w, p), L, NULL, p); } return gerepilecopy(av, gprec_w(w, nbits2prec(bit))); } /* exp(t (1 + O(t^n))), n >= 0 */ static GEN serexp0(long v, long n) { GEN y = cgetg(n+3, t_SER), t; long i; y[1] = evalsigne(1) | evalvarn(v) | evalvalser(0); gel(y,2) = gen_1; if (!n) return y; gel(y,3) = gen_1; if (n == 1) return y; for (i=2, t = gen_2; i < n; i++, t = muliu(t,i)) gel(y,i+2) = mkfrac(gen_1,t); gel(y,i+2) = mkfrac(gen_1,t); return y; } /* series expansion of W at -1/e */ static GEN Wbra(long N) { GEN v = cgetg(N + 2, t_VEC); long n; gel(v, 1) = gen_m1; gel(v, 2) = gen_1; for (n = 2; n <= N; n++) { GEN t = gel(v,n), a = gen_0; long k, K = (n - 1) >> 1; for (k = 1; k <= K; k++) t = gadd(t, gmul2n(gel(v,n-2*k), -k)); for (k = 2; k < n; k++) a = gadd(a, gmul(gel(v,k+1), gel(v,n+2-k))); gel(v,n+1) = gsub(gdivgs(t, -n-1), gmul2n(a, -1)); } return RgV_to_RgX(v, 0); } static GEN reverse(GEN y) { GEN z = ser2rfrac_i(y); long l = lg(z); return RgX_to_ser(RgXn_reverse(z, l-2), l-1); } static GEN serlambertW(GEN y, long branch, long prec) { long n, vy, val, v; GEN t = NULL; if (!signe(y)) return gcopy(y); v = valser(y); if (v < 0) pari_err_DOMAIN("lambertw","valuation", "<", gen_0, y); if (v > 0 && branch) pari_err_DOMAIN("lambertw [k != 0]", "x", "~", gen_0, y); vy = varn(y); n = lg(y)-3; for (val = 1; val < n; val++) if (!gequal0(polcoef_i(y, val, vy))) break; if (v) { t = serexp0(vy, n / val); setvalser(t, 1); t = reverse(t); /* rev(x exp(x)) */ } else { GEN y0 = gel(y,2), x = glambertW(y0, branch, prec); if (val > n) return scalarser(x, vy, n+1); y = serchop0(y); if (gequalm1(x)) { /* y0 ~ -1/e, branch = 0 or -1 */ GEN p = gmul(shiftr(gexp(gen_1,prec), 1), y); if (odd(val)) pari_err(e_MISC, "odd valuation at branch point"); p = gsqrt(p, prec); if (odd(branch)) p = gneg(p); n -= val >> 1; t = RgXn_eval(Wbra(n), ser2rfrac_i(p), n); return gtoser(t, varn(t), lg(p)); } t = serexp0(vy, n / val); /* (x + t) exp(x + t) = (y0 + t y0/x) * exp(t) */ t = gmul(deg1pol_shallow(gdiv(y0,x), y0, vy), t); t = gadd(x, reverse(serchop0(t))); } return normalizeser(gsubst(t, vy, y)); } static GEN lambertp(GEN x) { pari_sp av = avma; long k, minv; GEN y; if (gequal0(x)) return gcopy(x); minv = equaliu(gel(x,2), 2)? 2: 1; if (valp(x) < minv) { x = leafcopy(x); setvalp(x, minv); } k = Qp_exp_prec(x); if (k < 0) return NULL; y = gpowgs(cvstop2(k, x), k - 1); for (k--; k; k--) y = gsub(gpowgs(cvstop2(k, x), k - 1), gdivgu(gmul(x, y), k + 1)); return gerepileupto(av, gmul(x, y)); } /* y a t_REAL */ static int useC(GEN y, long k) { if (signe(y) > 0 || (k && k != -1)) return k ? 1: 0; return gsigne(addsr(1, logr_abs(y))) > 0; } static GEN glambertW_i(void *E, GEN y, long prec) { pari_sp av; long k = (long)E, p; GEN z; if (gequal0(y)) { if (k) pari_err_DOMAIN("glambertW","argument","",gen_0,y); return gcopy(y); } switch(typ(y)) { case t_REAL: p = minss(prec, realprec(y)); return useC(y, k)? lambertWC(y, k, p): lambertW(y, k, p); case t_PADIC: z = lambertp(y); if (!z) pari_err_DOMAIN("glambertW(t_PADIC)","argument","",gen_0,y); return z; case t_COMPLEX: p = precision(y); return lambertWC(y, k, p? p: prec); default: av = avma; if (!(z = toser_i(y))) break; return gerepileupto(av, serlambertW(z, k, prec)); } return trans_evalgen("lambert", E, glambertW_i, y, prec); } GEN glambertW(GEN y, long k, long prec) { return glambertW_i((void*)k, y, prec); } GEN mplambertW(GEN y, long prec) { return lambertW(y, 0, prec); } /*********************************************************************/ /* Application */ /*********************************************************************/ /* Solve x - a * log(x) = b with a > 0 and b >= a * (1 - log(a)). */ GEN mplambertx_logx(GEN a, GEN b, long bit) { pari_sp av = avma; GEN e = gexp(gneg(gdiv(b, a)), nbits2prec(bit)); return gerepileupto(av, gmul(gneg(a), lambertW(gneg(gdiv(e, a)), -1, bit))); } /* Special case a = 1, b = log(y): solve e^x / x = y with y >= exp(1). */ GEN mplambertX(GEN y, long bit) { pari_sp av = avma; return gerepileupto(av, gneg(lambertW(gneg(ginv(y)), -1, bit))); } /* Solve x * log(x) - a * x = b; if b < 0, assume a >= 1 + log |b|. */ GEN mplambertxlogx_x(GEN a, GEN b, long bit) { pari_sp av = avma; long s = gsigne(b); GEN e; if (!s) return gen_0; e = gexp(gneg(a), nbits2prec(bit)); return gerepileupto(av, gdiv(b, lambertW(gmul(b, e), s > 0? 0: -1, bit))); } pari-2.17.2/src/basemath/rootpol.c0000644000175000017500000021636114760123736015423 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*******************************************************************/ /* */ /* ROOTS OF COMPLEX POLYNOMIALS */ /* (original code contributed by Xavier Gourdon, INRIA RR 1852) */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_polroots static const double pariINFINITY = 1./0.; static long isvalidcoeff(GEN x) { switch (typ(x)) { case t_INT: case t_REAL: case t_FRAC: return 1; case t_COMPLEX: return isvalidcoeff(gel(x,1)) && isvalidcoeff(gel(x,2)); } return 0; } static void checkvalidpol(GEN p, const char *f) { long i,n = lg(p); for (i=2; i 2^21, it is correct to 2 ulp */ static double mydbllog2i(GEN x) { #ifdef LONG_IS_64BIT const double W = 1/(4294967296. * 4294967296.); /* 2^-64 */ #else const double W = 1/4294967296.; /*2^-32*/ #endif GEN m; long lx = lgefint(x); double l; if (lx == 2) return -pariINFINITY; m = int_MSW(x); l = (double)(ulong)*m; if (lx == 3) return log2(l); l += ((double)(ulong)*int_precW(m)) * W; /* at least m = min(53,BIL) bits are correct in the mantissa, thus log2 * is correct with error < log(1 + 2^-m) ~ 2^-m. Adding the correct * exponent BIL(lx-3) causes 1ulp further round-off error */ return log2(l) + (double)(BITS_IN_LONG*(lx-3)); } /* return log(|x|) or -pariINFINITY */ static double mydbllogr(GEN x) { if (!signe(x)) return -pariINFINITY; return M_LN2*dbllog2r(x); } /* return log2(|x|) or -pariINFINITY */ static double mydbllog2r(GEN x) { if (!signe(x)) return -pariINFINITY; return dbllog2r(x); } double dbllog2(GEN z) { double x, y; switch(typ(z)) { case t_INT: return mydbllog2i(z); case t_FRAC: return mydbllog2i(gel(z,1))-mydbllog2i(gel(z,2)); case t_REAL: return mydbllog2r(z); default: /*t_COMPLEX*/ x = dbllog2(gel(z,1)); y = dbllog2(gel(z,2)); if (x == -pariINFINITY) return y; if (y == -pariINFINITY) return x; if (fabs(x-y) > 10) return maxdd(x,y); return x + 0.5*log2(1 + exp2(2*(y-x))); } } static GEN /* beware overflow */ dblexp(double x) { return fabs(x) < 100.? dbltor(exp(x)): mpexp(dbltor(x)); } /* find s such that A_h <= 2^s <= 2 A_i for one h and all i < n = deg(p), * with A_i := (binom(n,i) lc(p) / p_i) ^ 1/(n-i), and p = sum p_i X^i */ static long findpower(GEN p) { double x, L, mins = pariINFINITY; long n = degpol(p),i; L = dbllog2(gel(p,n+2)); /* log2(lc * binom(n,i)) */ for (i=n-1; i>=0; i--) { L += log2((double)(i+1) / (double)(n-i)); x = dbllog2(gel(p,i+2)); if (x != -pariINFINITY) { double s = (L - x) / (double)(n-i); if (s < mins) mins = s; } } i = (long)ceil(mins); if (i - mins > 1 - 1e-12) i--; return i; } /* returns the exponent for logmodulus(), from the Newton diagram */ static long newton_polygon(GEN p, long k) { pari_sp av = avma; long n = degpol(p), i, j, h, l, *vertex = (long*)new_chunk(n+1); double *L = (double*)stack_malloc_align((n+1)*sizeof(double), sizeof(double)); /* vertex[i] = 1 if i a vertex of convex hull, 0 otherwise */ for (i=0; i<=n; i++) { L[i] = dbllog2(gel(p,2+i)); vertex[i] = 0; } vertex[0] = 1; /* sentinel */ for (i=0; i < n; i=h) { double slope; h = i+1; while (L[i] == -pariINFINITY) { vertex[h] = 1; i = h; h = i+1; } slope = L[h] - L[i]; for (j = i+2; j<=n; j++) if (L[j] != -pariINFINITY) { double pij = (L[j] - L[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--; set_avma(av); return (long)floor((L[h]-L[l])/(double)(h-l) + 0.5); } /* change z into z*2^e, where z is real or complex of real */ static void myshiftrc(GEN z, long e) { if (typ(z)==t_COMPLEX) { if (signe(gel(z,1))) shiftr_inplace(gel(z,1), e); if (signe(gel(z,2))) shiftr_inplace(gel(z,2), e); } else if (signe(z)) shiftr_inplace(z, e); } /* return z*2^e, where z is integer or complex of integer (destroy z) */ static GEN myshiftic(GEN z, long e) { if (typ(z)==t_COMPLEX) { gel(z,1) = signe(gel(z,1))? mpshift(gel(z,1),e): gen_0; gel(z,2) = mpshift(gel(z,2),e); return z; } return signe(z)? mpshift(z,e): gen_0; } static GEN RgX_gtofp_bit(GEN q, long bit) { return RgX_gtofp(q, nbits2prec(bit)); } static GEN mygprecrc(GEN x, long prec, long e) { GEN y; switch(typ(x)) { case t_REAL: if (!signe(x)) return real_0_bit(e); return realprec(x) == prec? x: rtor(x, prec); 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 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; return gc_double(ltop, R); } /* return R such that exp(R - tau) <= rho_n(P) <= exp(R + tau) * P(0) != 0 and P non constant */ static double logmax_modulus(GEN p, double tau) { GEN r, q, aux, gunr; pari_sp av, ltop = avma; long i,k,n=degpol(p),nn,bit,M,e; double rho,eps, tau2 = (tau > 3.0)? 0.5: tau/6.; r = cgeti(BIGDEFAULTPREC); av = avma; eps = - 1/log(1.5*tau2); /* > 0 */ bit = (long) ((double) n*log2(1./tau2)+3*log2((double) n))+1; gunr = real_1_bit(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); 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)) return gc_double(ltop,0.); r = itor(r, DEFAULTPREC); shiftr_inplace(r, -M); return gc_double(ltop, -rtodbl(r) * M_LN2); /* -log(2) sum e_i 2^-i */ } static GEN RgX_normalize1(GEN x) { long i, n = lg(x)-1; GEN y; for (i = n; i > 1; i--) if (!gequal0( gel(x,i) )) break; if (i == n) return x; pari_warn(warner,"normalizing a polynomial with 0 leading term"); if (i == 1) pari_err_ROOTS0("roots"); y = cgetg(i+1, t_POL); y[1] = x[1]; for (; i > 1; i--) gel(y,i) = gel(x,i); return y; } static GEN polrootsbound_i(GEN P, double TAU) { pari_sp av = avma; double d; (void)RgX_valrem_inexact(P,&P); P = RgX_normalize1(P); switch(degpol(P)) { case -1: pari_err_ROOTS0("roots"); case 0: set_avma(av); return gen_0; } d = logmax_modulus(P, TAU) + TAU; /* not dblexp: result differs on ARM emulator */ return gerepileuptoleaf(av, mpexp(dbltor(d))); } GEN polrootsbound(GEN P, GEN tau) { if (typ(P) != t_POL) pari_err_TYPE("polrootsbound",P); checkvalidpol(P, "polrootsbound"); return polrootsbound_i(P, tau? gtodouble(tau): 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; if (gequal0(gel(p,2))) return -pariINFINITY; return gc_double(av, - logmax_modulus(RgX_recip_i(p),tau)); } /* 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))); } return gc_double(ltop, -r * M_LN2); } /* 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 / M_LN2 - 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>1; step2 = step<<1; fft2(W,p, f, step2,l1); fft2(W,p+step, f+l1,step2,l1); for (i = s1 = 0; i < l1; i++, s1 += step) { GEN f0 = gel(f,i); GEN f1 = gmul(gel(W,s1), gel(f,i+l1)); gel(f,i) = gadd(f0, f1); gel(f,i+l1) = gsub(f0, f1); } gerepilecoeffs(av, f, l); } static void fft(GEN W, GEN p, GEN f, long step, long l, long inv) { pari_sp av; long i, s1, l1, l2, l3, step4; GEN f1, f2, f3, f02; if (l == 2) { gel(f,0) = gadd(gel(p,0), gel(p,step)); gel(f,1) = gsub(gel(p,0), gel(p,step)); return; } av = avma; if (l == 4) { pari_sp av2; f1 = gadd(gel(p,0), gel(p,step<<1)); f2 = gsub(gel(p,0), gel(p,step<<1)); f3 = gadd(gel(p,step), gel(p,3*step)); f02 = gsub(gel(p,step), gel(p,3*step)); f02 = inv? mulcxI(f02): mulcxmI(f02); av2 = avma; gel(f,0) = gadd(f1, f3); gel(f,1) = gadd(f2, f02); gel(f,2) = gsub(f1, f3); gel(f,3) = gsub(f2, f02); gerepileallsp(av,av2,4,&gel(f,0),&gel(f,1),&gel(f,2),&gel(f,3)); return; } l1 = l>>2; l2 = 2*l1; l3 = l1+l2; step4 = step<<2; fft(W,p, f, step4,l1,inv); fft(W,p+step, f+l1,step4,l1,inv); fft(W,p+(step<<1),f+l2,step4,l1,inv); fft(W,p+3*step, f+l3,step4,l1,inv); for (i = s1 = 0; i < l1; i++, s1 += step) { long s2 = s1 << 1, s3 = s1 + s2; GEN g02, g13, f13; f1 = gmul(gel(W,s1), gel(f,i+l1)); f2 = gmul(gel(W,s2), gel(f,i+l2)); f3 = gmul(gel(W,s3), gel(f,i+l3)); f02 = gadd(gel(f,i),f2); g02 = gsub(gel(f,i),f2); f13 = gadd(f1,f3); g13 = gsub(f1,f3); g13 = inv? mulcxI(g13): mulcxmI(g13); gel(f,i) = gadd(f02, f13); gel(f,i+l1) = gadd(g02, g13); gel(f,i+l2) = gsub(f02, f13); gel(f,i+l3) = gsub(g02, g13); } gerepilecoeffs(av, f, l); } #define code(t1,t2) ((t1 << 6) | t2) static GEN FFT_i(GEN W, GEN x) { long i, l = lg(W), n = lg(x), tx = typ(x), tw, pa; GEN y, z, p, pol; if (l==1 || ((l-1) & (l-2))) pari_err_DIM("fft"); tw = RgV_type(W, &p, &pol, &pa); if (tx == t_POL) { x++; n--; } else if (!is_vec_t(tx)) pari_err_TYPE("fft",x); if (n > l) pari_err_DIM("fft"); if (n < l) { z = cgetg(l, t_VECSMALL); /* cf stackdummy */ for (i = 1; i < n; i++) gel(z,i) = gel(x,i); for ( ; i < l; i++) gel(z,i) = gen_0; } else z = x; if (l == 2) return mkveccopy(gel(z,1)); y = cgetg(l, t_VEC); if (tw==code(t_COMPLEX,t_INT) || tw==code(t_COMPLEX,t_REAL)) { long inv = (l >= 5 && signe(imag_i(gel(W,1+(l>>2))))==1) ? 1 : 0; fft(W+1, z+1, y+1, 1, l-1, inv); } else fft2(W+1, z+1, y+1, 1, l-1); return y; } #undef code GEN FFT(GEN W, GEN x) { if (!is_vec_t(typ(W))) pari_err_TYPE("fft",W); return FFT_i(W, x); } GEN FFTinv(GEN W, GEN x) { long l = lg(W), i; GEN w; if (!is_vec_t(typ(W))) pari_err_TYPE("fft",W); if (l==1 || ((l-1) & (l-2))) pari_err_DIM("fft"); w = cgetg(l, t_VECSMALL); /* cf stackdummy */ gel(w,1) = gel(W,1); /* w = gconj(W), faster */ for (i = 2; i < l; i++) gel(w, i) = gel(W, l-i+1); return FFT_i(w, x); } /* returns 1 if p has only real coefficients, 0 else */ static int isreal(GEN p) { long i; for (i = lg(p)-1; i > 1; i--) if (typ(gel(p,i)) == t_COMPLEX) return 0; return 1; } /* x non complex */ static GEN abs_update_r(GEN x, double *mu) { GEN y = gtofp(x, DEFAULTPREC); double ly = mydbllogr(y); if (ly < *mu) *mu = ly; setabssign(y); return y; } /* return |x|, low accuracy. Set *mu = min(log(y), *mu) */ static GEN abs_update(GEN x, double *mu) { GEN y, xr, yr; double ly; if (typ(x) != t_COMPLEX) return abs_update_r(x, mu); xr = gel(x,1); yr = gel(x,2); if (gequal0(xr)) return abs_update_r(yr,mu); if (gequal0(yr)) return abs_update_r(xr,mu); /* have to treat 0 specially: 0E-10 + 1e-20 = 0E-10 */ xr = gtofp(xr, DEFAULTPREC); yr = gtofp(yr, DEFAULTPREC); y = sqrtr(addrr(sqrr(xr), sqrr(yr))); ly = mydbllogr(y); if (ly < *mu) *mu = ly; return y; } static void initdft(GEN *Omega, GEN *prim, long N, long Lmax, long bit) { long prec = nbits2prec(bit); *Omega = grootsof1(Lmax, prec) + 1; *prim = rootsof1u_cx(N, prec); } 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, TWO; long n = degpol(p), bit, NN, K, i, j, Lmax; pari_sp av2, av = avma; 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; initdft(&Omega, &prim, NN, Lmax, bit); q = mygprec(p,bit) + 2; A = cgetg(Lmax+1,t_VEC); A++; pc= cgetg(Lmax+1,t_VEC); pc++; for (i=0; i <= n; i++) gel(pc,i)= gel(q,i); for ( ; i0 && i1) pari_warn(warnmem,"parameters"); gerepileall(av2,2, &g,&RU); } } *gamma = mydbllog2r(divru(g,NN)); *LMAX = Lmax; set_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; initdft(&Omega, &prim, NN, Lmax, bit); RU = cgetg(n+2,t_VEC) + 1; 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++; gel(pc,0) = gel(q,2); for (i=n+1; i0 && i-bit && i1) pari_warn(warnmem,"refine_H"); gerepileall(ltop,2, &D,&H); } bit1 = -error + Sbit; aux = RgX_mul(mygprec(H,bit1), mygprec(D,bit1)); aux = RgX_rem(mygprec(aux,bit1), mygprec(F,bit1)); bit1 = -error*2 + Sbit; if (bit1 > bit2) bit1 = bit2; H = RgX_add(mygprec(H,bit1), aux); D = Rg_RgX_sub(gen_1, RgX_rem(RgX_mul(H,G),F)); error = gexpo(D); if (error < -bit1) error = -bit1; } if (error > -bit/2) return NULL; /* FAIL */ return gerepilecopy(ltop,H); } /* return 0 if fails, 1 else */ static long refine_F(GEN p, GEN *F, GEN *G, GEN H, long bit, double gamma) { GEN f0, FF, GG, r, HH = H; long error, i, bit1 = 0, bit2, Sbit, Sbit2, enh, normF, normG, n = degpol(p); pari_sp av = avma; FF = *F; GG = RgX_divrem(p, FF, &r); error = gexpo(r); if (error <= -bit) error = 1-bit; normF = gexpo(FF); normG = gexpo(GG); enh = gexpo(H); if (enh < 0) enh = 0; Sbit = normF + 2*normG + enh + (long)(4.*log2((double)n)+gamma) + 1; Sbit2 = enh + 2*(normF+normG) + (long)(2.*gamma+5.*log2((double)n)) + 1; bit2 = bit + Sbit; for (i=0; error>-bit && i= 2) { Sbit += n; Sbit2 += n; bit2 += n; } if (gc_needed(av,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"refine_F"); gerepileall(av,4, &FF,&GG,&r,&HH); } bit1 = -error + Sbit2; HH = refine_H(mygprec(FF,bit1), mygprec(GG,bit1), mygprec(HH,bit1), 1-error, Sbit2); if (!HH) return 0; /* FAIL */ bit1 = -error + Sbit; r = RgX_mul(mygprec(HH,bit1), mygprec(r,bit1)); f0 = RgX_rem(mygprec(r,bit1), mygprec(FF,bit1)); bit1 = -2*error + Sbit; if (bit1 > bit2) bit1 = bit2; FF = gadd(mygprec(FF,bit1),f0); bit1 = -3*error + Sbit; if (bit1 > bit2) bit1 = bit2; GG = RgX_divrem(mygprec(p,bit1), mygprec(FF,bit1), &r); error = gexpo(r); if (error < -bit1) error = -bit1; } if (error>-bit) return 0; /* FAIL */ *F = FF; *G = GG; return 1; } /* returns F and G from the unit circle U such that |p-FG|<2^(-bit) |cd|, where cd is the leading coefficient of p */ static void split_fromU(GEN p, long k, double delta, long bit, GEN *F, GEN *G, double param, double param2) { GEN pp, FF, GG, H; long n = degpol(p), NN, bit2, Lmax; int polreal = isreal(p); pari_sp ltop; double mu, gamma; pp = gdiv(p, gel(p,2+n)); parameters(pp, &Lmax,&mu,&gamma, polreal,param,param2); H = cgetg(k+2,t_POL); H[1] = p[1]; FF = cgetg(k+3,t_POL); FF[1]= p[1]; gel(FF,k+2) = gen_1; NN = (long)(0.5/delta); NN |= 1; if (NN < 2) NN = 2; NN *= Lmax; ltop = avma; for(;;) { bit2 = (long)(((double)NN*delta-mu)/M_LN2) + gexpo(pp) + 8; dft(pp, k, NN, Lmax, bit2, FF, H, polreal); if (refine_F(pp,&FF,&GG,H,bit,gamma)) break; NN <<= 1; set_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_i(p),n-k,delta,bit,&FF,&GG,param,param2); *F = RgX_recip_i(GG); *G = RgX_recip_i(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; assume R is at the correct accuracy */ static GEN scalepol(GEN p, GEN R, long bit) { return RgX_rescale(mygprec(p, bit), R); } /* return (conj(a)X-1)^n * p[ (X-a) / (conj(a)X-1) ] */ static GEN conformal_basecase(GEN p, GEN a) { GEN z, r, ma, ca; long i, n = degpol(p); pari_sp av; if (n <= 0) return p; ma = gneg(a); ca = conj_i(a); av = avma; z = deg1pol_shallow(ca, gen_m1, 0); r = scalarpol_shallow(gel(p,2+n), 0); for (i=n-1; ; i--) { r = RgX_addmulXn_shallow(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 = RgX_addmulXn_shallow(gmul(z,ca), gneg(z), 1); /* z *= conj(a)X - 1 */ if (gc_needed(av,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"conformal_pol (%ld/%ld)",n-i, n); gerepileall(av,2, &r,&z); } } } static GEN conformal_pol(GEN p, GEN a) { pari_sp av = avma; long d, nR, n = degpol(p), v; GEN Q, R, S, T; if (n < 35) return conformal_basecase(p, a); d = (n+1) >> 1; v = varn(p); Q = RgX_shift_shallow(p, -d); R = RgXn_red_shallow(p, d); Q = conformal_pol(Q, a); R = conformal_pol(R, a); S = gpowgs(deg1pol_shallow(gen_1, gneg(a), v), d); T = RgX_recip_i(S); if (typ(a) == t_COMPLEX) T = gconj(T); if (odd(d)) T = RgX_neg(T); /* S = (X - a)^d, T = (conj(a) X - 1)^d */ nR = n - degpol(R) - d; /* >= 0 */ if (nR) T = RgX_mul(T, gpowgs(deg1pol_shallow(gconj(a), gen_m1, v), nR)); return gerepileupto(av, RgX_add(RgX_mul(Q, S), RgX_mul(R, T))); } 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( utor(3, precdbl(MEDDEFAULTPREC)) ); 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); for (i=1; i<=n; i++) if (radii[i] != UNDEF) /* update array radii */ { pari_sp av2 = avma; GEN t, r = dblexp(radii[i]), r2 = sqrr(r); /* 2(r^2 - 1) / (r^2 - 3(r-1)) */ t = divrr(shiftr((subrs(r2,1)),1), subrr(r2, mulur(3,subrs(r,1)))); radii[i] = mydbllogr(addsr(1,t)) / 2; set_avma(av2); } lrho = logradius(radii, q,k,aux/10., &delta); update_radius(n, radii, lrho, ¶m, ¶m2); bit2 += (long)(n * fabs(lrho)/M_LN2 + 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); GG = conformal_pol(GG,a); 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; radii = (double*) stack_malloc_align((n+1) * sizeof(double), 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)/M_LN2 + 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)/M_LN2 + 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 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); v = cgetg(5,t_VEC); gel(v,1) = gen_2; gel(v,2) = gen_m2; 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 > M_LN2) break; if (polreal && i==2 && lthick > LOG3 - M_LN2) break; } bit2 = bit + gexpo(newq) - ep + (long)(n*LOG3/M_LN2 + 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; long n = degpol(p), k, bit2, eq; double aux0 = dbllog2(gel(p,n+2)); /* != -oo */ double aux1 = dbllog2(gel(p,n+1)), aux; if (aux1 == -pariINFINITY) /* p1 = 0 */ aux = 0; else { aux = aux1 - aux0; /* log2(p1/p0) */ /* 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); if (aux1 == -pariINFINITY) b = NULL; else { 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; *F = pol_xn(k, 0); *G = RgX_shift_shallow(q, -k); } else { split_1(q,bit2,F,G); bit2 = bit + gexpo(*F) + gexpo(*G) - gexpo(p) + (long)aux+1; *F = mygprec(*F,bit2); } *G = mygprec(*G,bit2); if (b) { GEN mb = mygprec(gneg(b), bit2); *F = RgX_translate(*F, mb); *G = RgX_translate(*G, mb); } 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 = pol_xn(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_i(p); lr = logmax_modulus(q,0.05); if (lr < LOG1_9) { split_0_1(q, bit, F, G); *F = RgX_recip_i(*F); *G = RgX_recip_i(*G); } else split_2(p,bit,NULL, 1.2837,F,G); } } } /********************************************************************/ /** **/ /** ERROR ESTIMATE FOR THE ROOTS **/ /** **/ /********************************************************************/ static GEN root_error(long n, long k, GEN roots_pol, long err, GEN shatzle) { GEN rho, d, eps, epsbis, eps2, aux, rap = NULL; long i, j; d = cgetg(n+1,t_VEC); for (i=1; i<=n; i++) { if (i!=k) { aux = gsub(gel(roots_pol,i), gel(roots_pol,k)); gel(d,i) = gabs(mygprec(aux,31), DEFAULTPREC); } } rho = gabs(mygprec(gel(roots_pol,k),31), DEFAULTPREC); if (expo(rho) < 0) rho = real_1(DEFAULTPREC); eps = mulrr(rho, shatzle); aux = shiftr(powru(rho,n), err); for (j=1; j<=2 || (j<=5 && cmprr(rap, dbltor(1.2)) > 0); j++) { GEN prod = NULL; /* 1. */ long m = n; epsbis = mulrr(eps, dbltor(1.25)); for (i=1; i<=n; i++) { if (i != k && cmprr(gel(d,i),epsbis) > 0) { GEN dif = subrr(gel(d,i),eps); prod = prod? mulrr(prod, dif): dif; m--; } } eps2 = prod? divrr(aux, prod): aux; if (m > 1) eps2 = sqrtnr(shiftr(eps2, 2*m-2), m); rap = divrr(eps,eps2); eps = eps2; } return eps; } /* round a complex or real number x to an absolute value of 2^(-bit) */ static GEN mygprec_absolute(GEN x, long bit) { long e; GEN y; switch(typ(x)) { case t_REAL: e = expo(x) + bit; return (e <= 0 || !signe(x))? real_0_bit(-bit): rtor(x, nbits2prec(e)); case t_COMPLEX: if (gexpo(gel(x,2)) < -bit) return mygprec_absolute(gel(x,1),bit); y = cgetg(3,t_COMPLEX); gel(y,1) = mygprec_absolute(gel(x,1),bit); gel(y,2) = mygprec_absolute(gel(x,2),bit); return y; default: return x; } } static long a_posteriori_errors(GEN p, GEN roots_pol, long err) { long i, n = degpol(p), e_max = -(long)EXPOBITS; GEN sigma, shatzle; err += (long)log2((double)n) + 1; if (err > -2) return 0; sigma = real2n(-err, LOWDEFAULTPREC); /* 2 / ((s - 1)^(1/n) - 1) */ shatzle = divur(2, subrs(sqrtnr(subrs(sigma,1),n), 1)); for (i=1; i<=n; i++) { pari_sp av = avma; GEN x = root_error(n,i,roots_pol,err,shatzle); long e = gexpo(x); set_avma(av); if (e > e_max) e_max = e; gel(roots_pol,i) = mygprec_absolute(gel(roots_pol,i), -e); } return e_max; } /********************************************************************/ /** **/ /** MAIN **/ /** **/ /********************************************************************/ static GEN append_clone(GEN r, GEN a) { a = gclone(a); vectrunc_append(r, a); return a; } /* put roots in placeholder roots_pol so that |P - L_1...L_n| < 2^(-bit)|P| * returns prod (x-roots_pol[i]) */ static GEN split_complete(GEN p, long bit, GEN roots_pol) { long n = degpol(p); pari_sp ltop; GEN p1, F, G, a, b, m1, m2; if (n == 1) { a = gneg_i(gdiv(gel(p,2), gel(p,3))); (void)append_clone(roots_pol,a); return p; } ltop = avma; if (n == 2) { F = gsub(gsqr(gel(p,3)), gmul2n(gmul(gel(p,2),gel(p,4)), 2)); F = gsqrt(F, nbits2prec(bit)); p1 = ginv(gmul2n(gel(p,4),1)); a = gneg_i(gmul(gadd(F,gel(p,3)), p1)); b = gmul(gsub(F,gel(p,3)), p1); a = append_clone(roots_pol,a); b = append_clone(roots_pol,b); set_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 quicktofp(GEN x) { const long prec = DEFAULTPREC; switch(typ(x)) { case t_INT: return itor(x, prec); case t_REAL: return rtor(x, prec); case t_FRAC: return fractor(x, prec); case t_COMPLEX: { GEN a = gel(x,1), b = gel(x,2); /* avoid problem with 0, e.g. x = 0 + I*1e-100. We don't want |x| = 0. */ if (isintzero(a)) return cxcompotor(b, prec); if (isintzero(b)) return cxcompotor(a, prec); a = cxcompotor(a, prec); b = cxcompotor(b, prec); return sqrtr(addrr(sqrr(a), sqrr(b))); } default: pari_err_TYPE("quicktofp",x); return NULL;/*LCOV_EXCL_LINE*/ } } /* bound log_2 |largest root of p| (Fujiwara's bound) */ double fujiwara_bound(GEN p) { pari_sp av = avma; long i, n = degpol(p); GEN cc; double loglc, Lmax; if (n <= 0) pari_err_CONSTPOL("fujiwara_bound"); loglc = mydbllog2r( quicktofp(gel(p,n+2)) ); /* log_2 |lc(p)| */ cc = gel(p, 2); if (gequal0(cc)) Lmax = -pariINFINITY-1; else Lmax = (mydbllog2r(quicktofp(cc)) - loglc - 1) / n; for (i = 1; i < n; i++) { GEN y = gel(p,i+2); double L; if (gequal0(y)) continue; L = (mydbllog2r(quicktofp(y)) - loglc) / (n-i); if (L > Lmax) Lmax = L; } return gc_double(av, Lmax+1); } /* Fujiwara's bound, real roots. Based on the following remark: if * p = x^n + sum a_i x^i and q = x^n + sum min(a_i,0)x^i * then for all x >= 0, p(x) >= q(x). Thus any bound for the (positive) roots * of q is a bound for the positive roots of p. */ double fujiwara_bound_real(GEN p, long sign) { pari_sp av = avma; GEN x; long n = degpol(p), i, signodd, signeven; if (n <= 0) pari_err_CONSTPOL("fujiwara_bound"); x = shallowcopy(p); if (gsigne(gel(x, n+2)) > 0) { signeven = 1; signodd = sign; } else { signeven = -1; signodd = -sign; } for (i = 0; i < n; i++) { if ((n - i) % 2) { if (gsigne(gel(x, i+2)) == signodd ) gel(x, i+2) = gen_0; } else { if (gsigne(gel(x, i+2)) == signeven) gel(x, i+2) = gen_0; } } return gc_double(av, fujiwara_bound(x)); } static GEN mygprecrc_special(GEN x, long prec, long e) { GEN y; switch(typ(x)) { case t_REAL: if (!signe(x)) return real_0_bit(minss(e, expo(x))); return (prec > realprec(x))? rtor(x, prec): x; case t_COMPLEX: y = cgetg(3,t_COMPLEX); gel(y,1) = mygprecrc_special(gel(x,1),prec,e); gel(y,2) = mygprecrc_special(gel(x,2),prec,e); return y; default: return x; } } /* like mygprec but keep at least the same precision as before */ static GEN mygprec_special(GEN x, long bit) { long lx, i, e, prec; GEN y; if (bit < 0) bit = 0; /* should not happen */ e = gexpo(x) - bit; prec = nbits2prec(bit); switch(typ(x)) { case t_POL: y = cgetg_copy(x, &lx); y[1] = x[1]; for (i=2; i= e) return -1; /* |Im x| ~ |Im y| ~ 0 */ } else if (!syi) { if (sxi && expo(xi) >= e) return 1; /* |Im x| ~ |Im y| ~ 0 */ } else { z = addrr_sign(xi, 1, yi, -1); sz = signe(z); if (sz && expo(z) >= e) return (int)sz; } /* |Im x| ~ |Im y|, sort according to real parts */ z = subrr(xr, yr); sz = signe(z); if (sz && expo(z) >= e) return (int)sz; /* Re x ~ Re y. Place negative imaginary part before positive */ return (int) (sxi - syi); } static GEN clean_roots(GEN L, long l, long bit, long clean) { long i, n = lg(L), ex = 5 - bit; GEN res = cgetg(n,t_COL); for (i=1; i 3? all_roots(Q_primpart(p), bit): cgetg(1,t_COL); if (v) L = shallowconcat(const_vec(v, real_0_bit(-bit)), L); return gerepilecopy(av, clean_roots(L, l, bit, 1)); } /********************************************************************/ /** **/ /** REAL ROOTS OF INTEGER POLYNOMIAL **/ /** **/ /********************************************************************/ /* Count sign changes in the coefficients of (x+1)^deg(P)*P(1/(x+1)), P * has no rational root. The inversion is implicit (we take coefficients * backwards). */ static long X2XP1(GEN P, GEN *Premapped) { const pari_sp av = avma; GEN v = shallowcopy(P); long i, j, nb, s, dP = degpol(P), vlim = dP+2; for (j = 2; j < vlim; j++) gel(v, j+1) = addii(gel(v, j), gel(v, j+1)); s = -signe(gel(v, vlim)); vlim--; nb = 0; for (i = 1; i < dP; i++) { long s2 = -signe(gel(v, 2)); int flag = (s2 == s); for (j = 2; j < vlim; j++) { gel(v, j+1) = addii(gel(v, j), gel(v, j+1)); if (flag) flag = (s2 != signe(gel(v, j+1))); } if (s == signe(gel(v, vlim))) { if (++nb >= 2) return gc_long(av,2); s = -s; } /* if flag is set there will be no further sign changes */ if (flag && (!Premapped || !nb)) return gc_long(av, nb); vlim--; if (gc_needed(av, 3)) { if (DEBUGMEM>1) pari_warn(warnmem, "X2XP1, i = %ld/%ld", i, dP-1); if (!Premapped) setlg(v, vlim + 2); v = gerepilecopy(av, v); } } if (vlim >= 2 && s == signe(gel(v, vlim))) nb++; if (Premapped && nb == 1) *Premapped = v; else set_avma(av); return nb; } static long _intervalcmp(GEN x, GEN y) { if (typ(x) == t_VEC) x = gel(x, 1); if (typ(y) == t_VEC) y = gel(y, 1); return gcmp(x, y); } static GEN _gen_nored(void *E, GEN x) { (void)E; return x; } static GEN _mp_add(void *E, GEN x, GEN y) { (void)E; return mpadd(x, y); } static GEN _mp_sub(void *E, GEN x, GEN y) { (void)E; return mpsub(x, y); } static GEN _mp_mul(void *E, GEN x, GEN y) { (void)E; return mpmul(x, y); } static GEN _mp_sqr(void *E, GEN x) { (void)E; return mpsqr(x); } static GEN _gen_one(void *E) { (void)E; return gen_1; } static GEN _gen_zero(void *E) { (void)E; return gen_0; } static struct bb_algebra mp_algebra = { _gen_nored, _mp_add, _mp_sub, _mp_mul, _mp_sqr, _gen_one, _gen_zero }; static GEN _mp_cmul(void *E, GEN P, long a, GEN x) {(void)E; return mpmul(gel(P,a+2), x);} /* Split the polynom P in two parts, whose coeffs have constant sign: * P(X) = X^D*Pp + Pm. Also compute the two parts of the derivative of P, * Pprimem = Pm', Pprimep = X*Pp'+ D*Pp => P' = X^(D-1)*Pprimep + Pprimem; * Pprimep[i] = (i+D) Pp[i]. Return D */ static long split_pols(GEN P, GEN *pPp, GEN *pPm, GEN *pPprimep, GEN *pPprimem) { long i, D, dP = degpol(P), s0 = signe(gel(P,2)); GEN Pp, Pm, Pprimep, Pprimem; for(i=1; i <= dP; i++) if (signe(gel(P, i+2)) == -s0) break; D = i; Pm = cgetg(D + 2, t_POL); Pprimem = cgetg(D + 1, t_POL); Pp = cgetg(dP-D + 3, t_POL); Pprimep = cgetg(dP-D + 3, t_POL); Pm[1] = Pp[1] = Pprimem[1] = Pprimep[1] = P[1]; for(i=0; i < D; i++) { GEN c = gel(P, i+2); gel(Pm, i+2) = c; if (i) gel(Pprimem, i+1) = mului(i, c); } for(; i <= dP; i++) { GEN c = gel(P, i+2); gel(Pp, i+2-D) = c; gel(Pprimep, i+2-D) = mului(i, c); } *pPm = normalizepol_lg(Pm, D+2); *pPprimem = normalizepol_lg(Pprimem, D+1); *pPp = normalizepol_lg(Pp, dP-D+3); *pPprimep = normalizepol_lg(Pprimep, dP-D+3); return dP - degpol(*pPp); } static GEN bkeval_single_power(long d, GEN V) { long mp = lg(V) - 2; if (d > mp) return gmul(gpowgs(gel(V, mp+1), d/mp), gel(V, (d%mp)+1)); return gel(V, d+1); } static GEN splitpoleval(GEN Pp, GEN Pm, GEN pows, long D, long bitprec) { GEN vp = gen_bkeval_powers(Pp, degpol(Pp), pows, NULL, &mp_algebra, _mp_cmul); GEN vm = gen_bkeval_powers(Pm, degpol(Pm), pows, NULL, &mp_algebra, _mp_cmul); GEN xa = bkeval_single_power(D, pows); GEN r; if (!signe(vp)) return vm; vp = gmul(vp, xa); r = gadd(vp, vm); if (gexpo(vp) - (signe(r)? gexpo(r): 0) > prec2nbits(realprec(vp)) - bitprec) return NULL; return r; } /* optimized Cauchy bound for P = X^D*Pp + Pm, D > deg(Pm) */ static GEN splitcauchy(GEN Pp, GEN Pm, long prec) { GEN S = gel(Pp,2), A = gel(Pm,2); long i, lPm = lg(Pm), lPp = lg(Pp); for (i=3; i < lPm; i++) { GEN c = gel(Pm,i); if (abscmpii(A, c) < 0) A = c; } for (i=3; i < lPp; i++) S = addii(S, gel(Pp, i)); return subsr(1, rdivii(A, S, prec)); /* 1 + |Pm|_oo / |Pp|_1 */ } static GEN ZX_deg1root(GEN P, long prec) { GEN a = gel(P,3), b = gel(P,2); if (is_pm1(a)) { b = itor(b, prec); if (signe(a) > 0) togglesign(b); return b; } return rdivii(negi(b), a, prec); } /* Newton for polynom P, P(0)!=0, with unique sign change => one root in ]0,oo[ * P' has also at most one zero there */ static GEN polsolve(GEN P, long bitprec) { pari_sp av; GEN Pp, Pm, Pprimep, Pprimem, Pprime, Pprime2, ra, rb, rc, Pc; long dP = degpol(P), prec = nbits2prec(bitprec); long expoold, iter, D, rt, s0, bitaddprec, cprec, PREC; if (dP == 1) return ZX_deg1root(P, prec); Pprime = ZX_deriv(P); Pprime2 = ZX_deriv(Pprime); bitaddprec = 1 + 2*expu(dP); PREC = prec + nbits2prec(bitaddprec); D = split_pols(P, &Pp, &Pm, &Pprimep, &Pprimem); /* P = X^D*Pp + Pm */ s0 = signe(gel(P, 2)); rt = maxss(D, brent_kung_optpow(maxss(degpol(Pp), degpol(Pm)), 2, 1)); rb = splitcauchy(Pp, Pm, DEFAULTPREC); for (cprec = DEFAULTPREC, expoold = LONG_MAX;;) { GEN pows = gen_powers(rb, rt, 1, NULL, _mp_sqr, _mp_mul, _gen_one); Pc = splitpoleval(Pp, Pm, pows, D, bitaddprec); if (!Pc) { cprec += EXTRAPREC64; rb = rtor(rb, cprec); continue; } if (signe(Pc) != s0) break; shiftr_inplace(rb,1); } for (iter = 0, ra = NULL;;) { GEN wdth; iter++; if (ra) rc = shiftr(addrr(ra, rb), -1); else rc = shiftr(rb, -1); for(;;) { GEN pows = gen_powers(rc, rt, 1, NULL, _mp_sqr, _mp_mul, _gen_one); Pc = splitpoleval(Pp, Pm, pows, D, bitaddprec+2); if (Pc) break; cprec += EXTRAPREC64; rc = rtor(rc, cprec); } if (signe(Pc) == s0) ra = rc; else rb = rc; if (!ra) continue; wdth = subrr(rb, ra); if (!(iter % 8)) { GEN m1 = poleval(Pprime, ra), M2; if (signe(m1) == s0) continue; M2 = poleval(Pprime2, rb); if (abscmprr(gmul(M2, wdth), shiftr(m1, 1)) > 0) continue; break; } else if (gexpo(wdth) <= -bitprec) break; } rc = rb; av = avma; for(;; rc = gerepileuptoleaf(av, rc)) { long exponew; GEN Ppc, dist, rcold = rc; GEN pows = gen_powers(rc, rt, 1, NULL, _mp_sqr, _mp_mul, _gen_one); Ppc = splitpoleval(Pprimep, Pprimem, pows, D-1, bitaddprec+4); if (Ppc) Pc = splitpoleval(Pp, Pm, pows, D, bitaddprec+4); if (!Ppc || !Pc) { if (cprec >= PREC) cprec += EXTRAPREC64; else cprec = minss(2*cprec, PREC); rc = rtor(rc, cprec); continue; /* backtrack one step */ } dist = typ(Ppc) == t_REAL? divrr(Pc, Ppc): divri(Pc, Ppc); rc = subrr(rc, dist); if (cmprr(ra, rc) > 0 || cmprr(rb, rc) < 0) { if (cprec >= PREC) break; cprec = minss(2*cprec, PREC); rc = rtor(rcold, cprec); continue; /* backtrack one step */ } if (expoold == LONG_MAX) { expoold = expo(dist); continue; } exponew = expo(dist); if (exponew < -bitprec - 1) { if (cprec >= PREC) break; cprec = minss(2*cprec, PREC); rc = rtor(rc, cprec); continue; } if (exponew > expoold - 2) { if (cprec >= PREC) break; expoold = LONG_MAX; cprec = minss(2*cprec, PREC); rc = rtor(rc, cprec); continue; } expoold = exponew; } return rtor(rc, prec); } /* Return primpart(P(x / 2)) */ static GEN ZX_rescale2prim(GEN P) { long i, l = lg(P), v, n; GEN Q; if (l==2) return pol_0(varn(P)); Q = cgetg(l,t_POL); v = vali(gel(P,l-1)); for (i = l-2, n = 1; v > n && i >= 2; i--, n++) v = minss(v, vali(gel(P,i)) + n); gel(Q,l-1) = v? shifti(gel(P,l-1), -v): gel(P,l-1); for (i = l-2, n = 1-v; i >= 2; i--, n++) gel(Q,i) = shifti(gel(P,i), n); Q[1] = P[1]; return Q; } /* assume Q0 has no rational root */ static GEN usp(GEN Q0, long flag, long bitprec) { const pari_sp av = avma; GEN Qremapped, Q, c, Lc, Lk, sol; GEN *pQremapped = flag == 1? &Qremapped: NULL; const long prec = nbits2prec(bitprec), deg = degpol(Q0); long listsize = 64, nbr = 0, nb_todo, ind, indf, i, k, nb; sol = zerocol(deg); Lc = zerovec(listsize); Lk = cgetg(listsize+1, t_VECSMALL); k = Lk[1] = 0; ind = 1; indf = 2; Q = Q0; c = gen_0; nb_todo = 1; while (nb_todo) { GEN nc = gel(Lc, ind); pari_sp av2; if (Lk[ind] == k + 1) { Q = Q0 = ZX_rescale2prim(Q0); c = gen_0; } if (!equalii(nc, c)) Q = ZX_translate(Q, subii(nc, c)); av2 = avma; k = Lk[ind]; ind++; c = nc; nb_todo--; nb = X2XP1(Q, pQremapped); if (nb == 1) { /* exactly one root */ GEN s = gen_0; if (flag == 0) { s = mkvec2(gmul2n(c,-k), gmul2n(addiu(c,1),-k)); s = gerepilecopy(av2, s); } else if (flag == 1) /* Caveat: Qremapped is the reciprocal polynomial */ { s = polsolve(*pQremapped, bitprec+1); s = addir(c, divrr(s, addsr(1, s))); shiftr_inplace(s, -k); if (realprec(s) != prec) s = rtor(s, prec); s = gerepileupto(av2, s); } else set_avma(av2); gel(sol, ++nbr) = s; } else if (nb) { /* unknown, add two nodes to refine */ if (indf + 2 > listsize) { if (ind>1) { for (i = ind; i < indf; i++) { gel(Lc, i-ind+1) = gel(Lc, i); Lk[i-ind+1] = Lk[i]; } indf -= ind-1; ind = 1; } if (indf + 2 > listsize) { listsize *= 2; Lc = vec_lengthen(Lc, listsize); Lk = vecsmall_lengthen(Lk, listsize); } for (i = indf; i <= listsize; i++) gel(Lc, i) = gen_0; } gel(Lc, indf) = nc = shifti(c, 1); gel(Lc, indf + 1) = addiu(nc, 1); Lk[indf] = Lk[indf + 1] = k + 1; indf += 2; nb_todo += 2; } if (gc_needed(av, 2)) { gerepileall(av, 6, &Q0, &Q, &c, &Lc, &Lk, &sol); if (DEBUGMEM > 1) pari_warn(warnmem, "ZX_Uspensky", avma); } } setlg(sol, nbr+1); return gerepilecopy(av, sol); } static GEN ZX_Uspensky_equal_yes(GEN a, long flag, long bit) { if (flag == 2) return gen_1; if (flag == 1 && typ(a) != t_REAL) { if (typ(a) == t_INT && !signe(a)) a = real_0_bit(bit); else a = gtofp(a, nbits2prec(bit)); } return mkcol(a); } static GEN ZX_Uspensky_no(long flag) { return flag <= 1 ? cgetg(1, t_COL) : gen_0; } /* ZX_Uspensky(P, [a,a], flag) */ static GEN ZX_Uspensky_equal(GEN P, GEN a, long flag, long bit) { if (typ(a) != t_INFINITY && gequal0(poleval(P, a))) return ZX_Uspensky_equal_yes(a, flag, bit); else return ZX_Uspensky_no(flag); } static int sol_ok(GEN r, GEN a, GEN b) { return gcmp(a, r) <= 0 && gcmp(r, b) <= 0; } /* P a ZX without real double roots; better if primitive and squarefree but * caller should ensure that. If flag & 4 assume that P has no rational root * (modest speedup) */ GEN ZX_Uspensky(GEN P, GEN ab, long flag, long bitprec) { pari_sp av = avma; GEN a, b, res, sol; double fb; long l, nbz, deg; if (ab) { if (typ(ab) == t_VEC) { if (lg(ab) != 3) pari_err_DIM("ZX_Uspensky"); a = gel(ab, 1); b = gel(ab, 2); } else { a = ab; b = mkoo(); } } else { a = mkmoo(); b = mkoo(); } if (flag & 4) { if (gcmp(a, b) >= 0) { set_avma(av); return ZX_Uspensky_no(flag); } flag &= ~4; sol = cgetg(1, t_COL); } else { switch (gcmp(a, b)) { case 1: set_avma(av); return ZX_Uspensky_no(flag); case 0: return gerepilecopy(av, ZX_Uspensky_equal(P, a, flag, bitprec)); } sol = nfrootsQ(P); } nbz = 0; l = lg(sol); if (l > 1) { long i, j; P = RgX_div(P, roots_to_pol(sol, varn(P))); if (!RgV_is_ZV(sol)) P = Q_primpart(P); for (i = j = 1; i < l; i++) if (sol_ok(gel(sol,i), a, b)) gel(sol,j++) = gel(sol,i); setlg(sol, j); if (flag == 2) { nbz = j-1; sol = utoi(nbz); } else if (flag == 1) sol = RgC_gtofp(sol, nbits2prec(bitprec)); } else if (flag == 2) sol = gen_0; deg = degpol(P); if (deg == 0) return gerepilecopy(av, sol); if (typ(a) == t_INFINITY && typ(b) != t_INFINITY && gsigne(b)) { fb = fujiwara_bound_real(P, -1); if (fb <= -pariINFINITY) a = gen_0; else if (fb < 0) a = gen_m1; else a = negi(int2n((long)ceil(fb))); } if (typ(b) == t_INFINITY && typ(a) != t_INFINITY && gsigne(a)) { fb = fujiwara_bound_real(P, 1); if (fb <= -pariINFINITY) b = gen_0; else if (fb < 0) b = gen_1; else b = int2n((long)ceil(fb)); } if (typ(a) != t_INFINITY && typ(b) != t_INFINITY) { GEN d, ad, bd, diff; long i; /* can occur if one of a,b was initially a t_INFINITY */ if (gequal(a,b)) return gerepilecopy(av, sol); d = lcmii(Q_denom(a), Q_denom(b)); if (is_pm1(d)) { d = NULL; ad = a; bd = b; } else { P = ZX_rescale(P, d); ad = gmul(a, d); bd = gmul(b, d); } diff = subii(bd, ad); P = ZX_affine(P, diff, ad); res = usp(P, flag, bitprec); if (flag <= 1) { for (i = 1; i < lg(res); i++) { GEN z = gmul(diff, gel(res, i)); if (typ(z) == t_VEC) { gel(z, 1) = gadd(ad, gel(z, 1)); gel(z, 2) = gadd(ad, gel(z, 2)); } else z = gadd(ad, z); if (d) z = gdiv(z, d); gel(res, i) = z; } sol = shallowconcat(sol, res); } else nbz += lg(res) - 1; } if (typ(b) == t_INFINITY && (fb=fujiwara_bound_real(P, 1)) > -pariINFINITY) { long bp = maxss((long)ceil(fb), 0); res = usp(ZX_unscale2n(P, bp), flag, bitprec); if (flag <= 1) sol = shallowconcat(sol, gmul2n(res, bp)); else nbz += lg(res)-1; } if (typ(a) == t_INFINITY && (fb=fujiwara_bound_real(P,-1)) > -pariINFINITY) { long i, bm = maxss((long)ceil(fb), 0); res = usp(ZX_unscale2n(ZX_z_unscale(P, -1), bm), flag, bitprec); if (flag <= 1) { for (i = 1; i < lg(res); i++) { GEN z = gneg(gmul2n(gel(res, i), bm)); if (typ(z) == t_VEC) swap(gel(z, 1), gel(z, 2)); gel(res, i) = z; } sol = shallowconcat(res, sol); } else nbz += lg(res)-1; } if (flag >= 2) return utoi(nbz); if (flag) sol = sort(sol); else sol = gen_sort(sol, (void *)_intervalcmp, cmp_nodata); return gerepileupto(av, sol); } /* x a scalar */ static GEN rootsdeg0(GEN x) { if (!is_real_t(typ(x))) pari_err_TYPE("realroots",x); if (gequal0(x)) pari_err_ROOTS0("realroots"); return cgetg(1,t_COL); /* constant polynomial */ } static void checkbound(GEN a) { switch(typ(a)) { case t_INT: case t_FRAC: case t_INFINITY: break; default: pari_err_TYPE("polrealroots", a); } } static GEN check_ab(GEN ab) { GEN a, b; if (!ab) return NULL; if (typ(ab) != t_VEC || lg(ab) != 3) pari_err_TYPE("polrootsreal",ab); a = gel(ab,1); checkbound(a); b = gel(ab,2); checkbound(b); if (typ(a) == t_INFINITY && inf_get_sign(a) < 0 && typ(b) == t_INFINITY && inf_get_sign(b) > 0) ab = NULL; return ab; } /* e^(1/h) assuming the h-th root is real, beware that sqrtnr assumes e >= 0 */ static GEN _sqrtnr(GEN e, long h) { long s; GEN r; if (h == 2) return sqrtr(e); s = signe(e); setsigne(e, 1); /* e < 0 is possible, implies h is odd */ r = sqrtnr(e, h); if (s < 0) setsigne(r, -1); return r; } GEN realroots(GEN P, GEN ab, long prec) { pari_sp av = avma; GEN sol = NULL, fa, ex; long i, j, v, l; ab = check_ab(ab); if (typ(P) != t_POL) return rootsdeg0(P); if (!RgX_is_ZX(P)) P = RgX_rescale_to_int(P); switch(degpol(P)) { case -1: return rootsdeg0(gen_0); case 0: return rootsdeg0(gel(P,2)); } v = ZX_valrem(Q_primpart(P), &P); fa = ZX_squff(P, &ex); l = lg(fa); sol = cgetg(l + 1, t_VEC); for (i = 1; i < l; i++) { GEN Pi = gel(fa, i), soli, soli2; long n, h; if (ab) h = 1; else Pi = ZX_deflate_max(Pi, &h); soli = ZX_Uspensky(Pi, odd(h)? ab: gen_0, 1, prec2nbits(prec)); n = lg(soli); soli2 = odd(h)? NULL: cgetg(n, t_COL); for (j = 1; j < n; j++) { GEN r = gel(soli, j); /* != 0 */ if (typ(r) != t_REAL) gel(soli, j) = r = gtofp(r, prec); if (h > 1) { gel(soli, j) = r = _sqrtnr(r, h); if (soli2) gel(soli2, j) = negr(r); } } if (soli2) soli = shallowconcat(soli, soli2); if (ex[i] > 1) soli = shallowconcat1( const_vec(ex[i], soli) ); gel(sol, i) = soli; } if (v && (!ab || (gsigne(gel(ab,1)) <= 0 && gsigne(gel(ab,2)) >= 0))) gel(sol, i++) = const_col(v, real_0(prec)); setlg(sol, i); if (i == 1) { set_avma(av); return cgetg(1,t_COL); } return gerepileupto(av, sort(shallowconcat1(sol))); } GEN ZX_realroots_irred(GEN P, long prec) { long dP = degpol(P), j, n, h; GEN sol, sol2; pari_sp av; if (dP == 1) retmkvec(ZX_deg1root(P, prec)); av = avma; P = ZX_deflate_max(P, &h); if (h == dP) { GEN r = _sqrtnr(ZX_deg1root(P, prec), h); return gerepilecopy(av, odd(h)? mkvec(r): mkvec2(negr(r), r)); } sol = ZX_Uspensky(P, odd(h)? NULL: gen_0, 1 | 4, prec2nbits(prec)); n = lg(sol); sol2 = odd(h)? NULL: cgetg(n, t_COL); for (j = 1; j < n; j++) { GEN r = gel(sol, j); if (typ(r) != t_REAL) gel(sol, j) = r = gtofp(r, prec); if (h > 1) { gel(sol, j) = r = _sqrtnr(r, h); if (sol2) gel(sol2, j) = negr(r); } } if (sol2) sol = shallowconcat(sol, sol2); return gerepileupto(av, sort(sol)); } static long ZX_sturm_i(GEN P, long flag) { pari_sp av; long h, r, dP = degpol(P); if (dP == 1) return 1; av = avma; P = ZX_deflate_max(P, &h); if (h == dP) { /* now deg P = 1 */ if (odd(h)) r = 1; else r = (signe(gel(P,2)) != signe(gel(P,3)))? 2: 0; return gc_long(av, r); } if (odd(h)) r = itou(ZX_Uspensky(P, NULL, flag, 0)); else r = 2*itou(ZX_Uspensky(P, gen_0, flag, 0)); return gc_long(av,r); } /* P nonconstant, squarefree ZX */ long ZX_sturmpart(GEN P, GEN ab) { pari_sp av = avma; if (!check_ab(ab)) return ZX_sturm(P); return gc_long(av, itou(ZX_Uspensky(P, ab, 2, 0))); } /* P nonconstant, squarefree ZX */ long ZX_sturm(GEN P) { return ZX_sturm_i(P, 2); } /* P irreducible ZX */ long ZX_sturm_irred(GEN P) { return ZX_sturm_i(P, 2 + 4); } pari-2.17.2/src/basemath/grossenchar.c0000644000175000017500000016246314760123736016246 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_gchar static GEN gchari_eval(GEN gc, GEN chi, GEN x, long flag, GEN logchi, GEN s0, long prec); /*********************************************************************/ /** **/ /** HECKE GROSSENCHARACTERS **/ /** contributed by Pascal Molin and Aurel Page (2022) **/ /** **/ /*********************************************************************/ /* characters can be represented by: - t_COL of coordinates on the snf basis (mostly for gp use): prefix gchar_ - t_VEC of coordinates on the internal basis: prefix gchari_ - t_VEC of R/Z components (logs): prefix gcharlog_ see gchar_internal for SNF -> internal and gchari_duallog for internal -> R/Z components */ /* localstar: represent (Z_F/m)^* . {+-1}^r + generators of U_{i-1}(p)/U_i structure: - [ sprk for p^k | m ] , size np - [ Ufil_p for p | m ], size np - m_oo, t_VECSMALL of size nci <= r1 (indices of real places) where Ufil_p = [ Mat([gen[j], t_COL of size ncp]_j) ]_{1<=i<=k} */ #define GC_LENGTH 12 #define LOCS_LENGTH 4 static GEN compute_Lcyc(GEN Lsprk, GEN moo) { long i, l = lg(Lsprk), len = l+lg(moo)-1; GEN Lcyc = cgetg(len,t_VEC); for (i = 1; i < l; i++) gel(Lcyc,i) = sprk_get_cyc(gel(Lsprk,i)); for ( ; i < len; i++) gel(Lcyc,i) = mkvec(gen_2); return Lcyc; } static long sprk_get_ncp(GEN sprk) { return lg(sprk_get_cyc(sprk)) - 1; } /* true nf; modulus = [ factor(m_f), m_oo ] */ static GEN localstar(GEN nf, GEN famod, GEN moo) { GEN Lcyc, cyc, Lsprk, Lgenfil, P = gel(famod,1), E = gel(famod,2); long i, l = lg(P); Lsprk = cgetg(l, t_VEC); Lgenfil = cgetg(l, t_VEC); for (i = 1; i < l; i++) { long e, k = itos(gel(E,i)); GEN v, sprk = log_prk_init(nf, gel(P,i), k, NULL); gel(Lsprk,i) = sprk; gel(Lgenfil,i) = v = cgetg(k+1, t_VEC); /* log on sprk of generators of U_{e-1}/U_e(pr) */ gel(v, 1) = col_ei(sprk_get_ncp(sprk), 1); for (e = 2; e <= k; e++) gel(v, e) = sprk_log_gen_pr2(nf, sprk, e); } Lcyc = compute_Lcyc(Lsprk, moo); if (lg(Lcyc) > 1) cyc = shallowconcat1(Lcyc); else cyc = cgetg(1, t_VEC); return mkvec4(cyc, Lsprk, Lgenfil, mkvec2(famod,moo)); } /* (nv * log|x^sigma|/norm, arg(x^sigma))/2*Pi * substract norm so that we project to the hyperplane * H : sum n_s x_s = 0 */ static GEN nfembedlog(GEN *pnf, GEN x, long prec) { pari_sp av = avma; GEN logs, cxlogs, nf = *pnf; long k, r1, r2, n, extrabit, extranfbit = 0, nfprec, nfprec0, logprec; nfprec0 = nf_get_prec(nf); nf_get_sign(nf, &r1, &r2); n = r1 + 2*r2; logprec = prec; extrabit = expu(n) + gexpo(nf_get_M(nf)) + 10; if (typ(x) == t_MAT) { long l = lg(gel(x,2)); if (l > 1) { extrabit += expu(l) + gexpo(gel(x,2)); extranfbit = gexpo(gel(x,1)); } } else { x = nf_to_scalar_or_basis(nf,x); extranfbit = gexpo(x); } if (DEBUGLEVEL>3) err_printf(" nfembedlog: prec=%d extrabit=%d nfprec=%d extralogprec=%d\n", prec, nbits2extraprec(extrabit + extranfbit), nfprec0, nbits2extraprec(extrabit)); nfprec = prec + nbits2extraprec(extrabit + extranfbit); logprec = prec + nbits2extraprec(extrabit); if (nfprec0 < nfprec) { if (DEBUGLEVEL) err_printf(" nfembedlog: increasing prec %d -> %d\n", nfprec0, nfprec); *pnf = nf = nfnewprec_shallow(nf, nfprec); av = avma; } if (!(cxlogs = nf_cxlog(nf, x, logprec))) return gc_NULL(av); if (!(cxlogs = nf_cxlog_normalize(nf, cxlogs, logprec))) return gc_NULL(av); logs = cgetg(n+1,t_COL); for (k = 1; k <= r1+r2; k++) gel(logs,k) = real_i(gel(cxlogs,k)); for ( ; k <= n; k++) gel(logs,k) = gmul2n(imag_i(gel(cxlogs,k-r2)), -1); extrabit = gexpo(logs); if (extrabit < 0) extrabit = 0; prec += nbits2extraprec(extrabit); return gerepileupto(av, gdiv(logs, Pi2n(1,prec))); } static GEN gchar_Sval(GEN nf, GEN S, GEN x) { GEN res = cgetg(lg(S),t_COL); long i; if (typ(x)==t_MAT) for (i=1; i1) err_printf("[%Ps*%Ps=%Ps..e=%ld|prec=%ld]\n", gel(v,k), den? den: gen_1, t, e, prec); if (e > bit) pari_err_BUG("gcharinit, non rational entry"); /*LCOV_EXCL_LINE*/ gel(v, k) = den? gdiv(t, den): t; } } /* FIXME: export ? */ static GEN rowreverse(GEN m) { long i, l; GEN v; if (lg(m) == 1) return m; l = lgcols(m); v = cgetg(l, t_VECSMALL); for (i = 1; i < l; i++) v[i] = l - i; return rowpermute(m, v); } /* lower-left hnf on subblock m[r0+1..r0+nr, c0+1..c0+nc] * return base change matrix U */ static GEN hnf_block(GEN m, long r0, long nr, long c0, long nc) { GEN block, u, uu; long nm = lg(m)-1, k; pari_sp av = avma; block = matslice(m, r0+1, r0+nr, c0+1, c0+nc); block = Q_remove_denom(block, NULL); block = rowreverse(block); (void)ZM_hnfall(block, &u, 1); vecreverse_inplace(u); uu = matid(nm); /* embed in matid */ for (k = 1; k <= nc; k++) gel(uu,c0+k) = embedcol(gel(u,k),nm,c0); return gerepilecopy(av, uu); } /* (matrix, starting row, nb rows, starting column, nb columns) */ static GEN lll_block(GEN m, long r0, long nr, long c0, long nc) { GEN block, u, uu; long nm = lg(m)-1, k; pari_sp av = avma; block = matslice(m, r0+1, r0+nr, c0+1, c0+nc); u = lll(block); if (lg(u) <= nc) return NULL; vecreverse_inplace(u); uu = matid(nm); /* embed in matid */ for (k = 1; k <= nc; k++) gel(uu,c0+k) = embedcol(gel(u,k),nm,c0); return gerepilecopy(av, uu); } /* insert a column at index i, no copy */ static GEN shallowmatinsert(GEN m, GEN x, long i) { long k, n = lg(m); GEN mm = cgetg(n+1,t_MAT); for (k=1; k < i; k++) gel(mm, k) = gel(m, k); gel(mm, i) = x; for (k=i; k < n; k++) gel(mm, k+1) = gel(m, k); return mm; } static GEN vec_v0(long n, long n0, long r1, long r2) { long k; GEN C = zerocol(n); for (k = 1; k <= r1; k++) gel(C, n0++) = gen_1; for (k = 1; k <= r2; k++) gel(C, n0++) = gen_2; return C; } /* select cm embeddings; return a matrix */ /* TODO detect if precision was insufficient */ static GEN cm_select(GEN nf, GEN cm, long prec) { GEN emb, keys, v, m_sel, imag_emb; long nalg, d_cm, r_cm, c, i, j, r2 = nf_get_r2(nf); pari_sp av; d_cm = degpol(gel(cm, 1)); /* degree of the cm field; even */ nalg = d_cm / 2; /* nb of clusters */ r_cm = nf_get_degree(nf) / d_cm; /* nb by cluster; nalg * r_cm = r2 */ m_sel = zeromatcopy(nalg, r2); /* selection matrix */ av = avma; /* group complex embeddings */ emb = nfeltembed(nf, gel(cm, 2), NULL, prec); /* sort */ imag_emb = imag_i(emb); keys = gadd(gmul(mppi(prec), real_i(emb)), gabs(imag_emb, prec)); v = indexsort(keys); for (j = c = 1; c <= nalg; c++) { int ref = gsigne(gel(imag_emb, v[j])); gcoeff(m_sel, c, v[j]) = gen_1; j++; for (i = 2; i <= r_cm; i++) { int s = gsigne(gel(imag_emb, v[j])); gcoeff(m_sel, c, v[j]) = (s == ref) ? gen_1 : gen_m1; j++; } } return gc_const(av, m_sel); } static GEN gchar_hnfreduce_shallow(GEN gc, GEN cm); static void gchar_snfbasis_shallow(GEN gc, GEN rel); static void gcharmat_tinverse(GEN gc, GEN m, long prec); static GEN gcharmatnewprec_shallow(GEN gc, long mprec); /* return a set S of prime ideals such that Cl_S(K) = 1 */ static GEN bestS(GEN bnf) { GEN v, S, hw, hv = bnf_get_no(bnf), DL, dl; long i, lS; ulong l; forprime_t P; if (equali1(hv)) return mkvec2(cgetg(1,t_VEC), cgetg(1,t_VEC)); v = diagonal_shallow(bnf_get_cyc(bnf)); S = cgetg(expi(hv)+2, t_VEC); lS = 1; DL = cgetg(expi(hv)+2, t_VEC); u_forprime_init(&P,2,ULONG_MAX); while ((l = u_forprime_next(&P))) { pari_sp av = avma; GEN w, Sl = idealprimedec(bnf, utoi(l)); long nSl = lg(Sl)-1; for (i = 1; i < nSl; i++) /* remove one prime ideal */ { dl = isprincipal(bnf, gel(Sl,i)); w = ZM_hnf(shallowconcat(v, dl)); hw = ZM_det(w); if (cmpii(hw, hv) < 0) { gel(DL,lS) = dl; gel(S,lS++) = gel(Sl,i); hv = hw; v = w; av = avma; if (equali1(hv)) { setlg(S, lS); setlg(DL, lS); return mkvec2(S,DL); } } } set_avma(av); } return NULL;/*LCOV_EXCL_LINE*/ } static GEN gcharDLdata(GEN bnf, GEN S, GEN DL) { GEN M, h, Minv, Lalpha, t, dl, alpha, gen, cyc = bnf_get_cyc(bnf); long i; M = shallowmatconcat(DL); h = bnf_get_no(bnf); gen = bnf_get_gen(bnf); /* compute right inverse of M modulo cyc */ M = shallowtrans(M); M = shallowmatconcat(mkcol2(M,diagonal_shallow(cyc))); Minv = matinvmod(M,h); Minv = vecslice(Minv,1,lg(Minv)-lg(cyc)); Minv = shallowtrans(Minv); Lalpha = cgetg(lg(Minv),t_VEC); for (i=1; i= max(evalprec + exponent(chi), nfprec+exponent(x)) where exponent(x) is the exponent of the number field element alpha obtained after principalisation of x. If prec is not sufficient, we call gcharnewprec. To mitigate precision increase, we always initialize the structure with 64 extra bits. Final remark: a gchar struct may have inconsistent values for prec and nfprec, for example if it has been saved and loaded at default prec : one should call gcharnewprec then. */ if (!checkbnf_i(bnf)) { nfprec = prec; bnf = bnfinit0(bnf, 1, NULL, nfprec); nf = shallowcopy(bnf_get_nf(bnf)); } else { GEN fu = bnf_get_sunits(bnf); if (!fu) fu = bnf_get_fu(bnf); /* impose fundamental units */ nf = shallowcopy(bnf_get_nf(bnf)); nfprec = nf_get_prec(nf); } /* Dirichlet group + make sure mod contains archimedean places */ mod = check_mod_factored(nf,mod,NULL,&fa2,&archp,NULL); sort_factor(fa2, (void*)&cmp_prime_ideal, &cmp_nodata); zm = localstar(nf, fa2, archp); zmcyc = locs_get_cyc(zm); /* set of primes S and valuations of generators */ S = bestS(bnf); DLdata = gel(S,2); S = gel(S,1); DLdata = gcharDLdata(bnf, S, DLdata); nf_get_sign(nf, &r1, &r2); n = r1+2*r2; ns = lg(S) - 1; nu = r1+r2-1 + ns; nc = lg(zmcyc) - 1; nm = ns+nc+n; /* number of parameters = ns + nc + r1 + r2 + r2 */ /* units and S-units */ sfu = gel(bnfunits(bnf,S), 1); sfu = vec_shorten(sfu, nu); /* remove torsion */ /* root of unity */ order = bnf_get_tuN(bnf); z = bnf_get_tuU(bnf); /* maximal cm subfield */ cm = nfsubfieldscm(nf, 0); /* Now compute matrix of parameters, until we obtain the right precision FIXME: make sure generators, units, and discrete logs do not depend on precision. m0 is the matrix of units embeddings u is the HNF base change, m = m0*u subsequent steps may lead to precision increase, we put everything in gc struct and modify it in place. A) sets m0 B) sets U, cyc, rel, U and Ui C) sets m_inv */ /* A) make big matrix m0 of embeddings of units */ if (DEBUGLEVEL>2) err_printf("start matrix m\n"); m = cgetg(nm + 1, t_MAT); mprec = nbits2prec(nm+10) + EXTRAPREC64; embprec = mprec; for(;;) { for (k = 1; k <= nu; k++) { /* Lambda_S (S-units) then Lambda_f, fund. units */ logx = gchar_nflog(&nf, zm, S, gel(sfu,k), embprec); if (!logx) break; gel(m, k) = logx; } if (k > nu) break; if (DEBUGLEVEL) err_printf("gcharinit: increasing embprec %d -> %d\n", embprec, precdbl(embprec)); embprec = precdbl(embprec); } for (k = 1; k <= nc; k++) /* Gamma, structure of (Z/m)* */ { C = zerocol(nm); gel(C, ns+k) = gel(zmcyc, k); gel(m, nu+k) = C; } /* zeta, root of unity */ gel(m, nu+nc+1) = gchar_nflog(&nf, zm, S, z, mprec); shallow_clean_rat(gel(m, nu+nc+1), 1, nm, stoi(order), mprec); for (k = 1; k <= r2; k++) /* embed Z^r_2 */ { C = zerocol(nm); gel(C, ns+nc+r1+r2+k) = gen_1; gel(m, nu+nc+1+k) = C; } if (DEBUGLEVEL>1) err_printf("matrix m = %Ps\n", m); m0 = m; u0 = gen_0; rel = U = Ui = gen_0; cyc = gen_0; m_inv = gen_0; /* only m and m_inv depend on prec and are recomputed under gcharnewprec. */ gc = mkvecn(GC_LENGTH, m_inv, /* internal basis, characters as rows */ bnf, nf, zm, /* Zk/mod, nc components */ S, /* generators of clgp, ns components */ DLdata, sfu, mkvec2(mkvecsmall3(evalprec,prec,nfprec), mkvecsmall3(0,0,0)), /* ntors, nfree, nalg */ cyc, /* reduced components */ mkvec3(rel, U, Ui), /* internal / SNF base change */ m0, /* embeddings of units */ u0); /* m_inv = (m0 u0)~^-1 */ /* B) do HNF reductions + LLL (may increase precision) */ m = gchar_hnfreduce_shallow(gc, cm); /* C) compute snf basis of torsion subgroup */ rel = shallowtrans(matslice(m, 1, ns+nc, 1, ns+nc)); gchar_snfbasis_shallow(gc, rel); /* D) transpose inverse m_inv = (m0*u)~^-1 (may increase precision) */ gcharmat_tinverse(gc, m, prec); return gerepilecopy(av, gc); } /* b) do HNF reductions + LLL, keep base change u0 */ static GEN gchar_hnfreduce_shallow(GEN gc, GEN cm) { GEN bnf = gchar_get_bnf(gc), nf = gchar_get_nf(gc), u, u0, m; long order, r1, r2, ns, nc, n, nu, nm, nalg = 0, mprec; nf_get_sign(nf, &r1, &r2); n = r1 + 2*r2; nu = r1 + r2 - 1; ns = gchar_get_ns(gc); nc = gchar_get_nc(gc); nm = ns+nc+n; /* ns + nc + r1 + r2 + r2 */ order = 2*bnf_get_tuN(bnf); u0 = matid(nm); m = shallowcopy(gchar_get_m0(gc)); /* keep m0 unchanged */ mprec = gprecision(m); if (DEBUGLEVEL>1) err_printf("matrix m = %Ps\n", m); if (nc) { /* keep steps 1&2 to make sure we have zeta_m */ u = hnf_block(m, ns,nc, ns+nu,nc+1); u0 = ZM_mul(u0, u); m = RgM_ZM_mul(m, u); if (DEBUGLEVEL>2) err_printf("step 1 -> %Ps\n", m); u = hnf_block(m, ns,nc, ns,nu+nc); u0 = ZM_mul(u0, u); m = RgM_ZM_mul(m, u); if (DEBUGLEVEL>2) err_printf("step 2 -> %Ps\n", m); } if (r2) { u = hnf_block(m, nm-r2,r2, nm-r2-1,r2+1); u0 = ZM_mul(u0, u); m = RgM_ZM_mul(m, u); if (DEBUGLEVEL>2) err_printf("step 3 -> %Ps\n", m); } /* remove last column */ setlg(u0, nm); setlg(m, nm); if (DEBUGLEVEL>2) err_printf("remove last col -> %Ps\n", m); if (!gequal0(cm)) { GEN v, Nargs; long bit = - prec2nbits(mprec) + 16 + expu(order); /* reduce on Norm arguments */ v = cm_select(nf, cm, gchar_get_nfprec(gc)); if (DEBUGLEVEL>2) err_printf("cm_select -> %Ps\n", v); nalg = nbrows(v); gchar_set_u0(gc, u0); for(;;) { long e, emax, i; Nargs = gmul(v, rowslice(m, nm-r2+1, nm)); if (DEBUGLEVEL>2) err_printf("Nargs -> %Ps\n", Nargs); emax = bit-1; for (i = ns+nc+1; i < lg(Nargs); i++) { gel(Nargs,i) = grndtoi(gmulgs(gel(Nargs,i), order), &e); emax = maxss(emax,e); } if (emax < bit) break; if (DEBUGLEVEL>1) err_printf("cm select: doubling prec\n"); mprec = precdbl(mprec); m = gcharmatnewprec_shallow(gc, mprec); } if (DEBUGLEVEL>2) err_printf("rounded Nargs -> %Ps\n", Nargs); u = hnf_block(Nargs, 0, nalg, ns+nc, n-1); u0 = ZM_mul(u0, u); m = RgM_ZM_mul(m, u); if (DEBUGLEVEL>2) err_printf("after cm reduction -> %Ps\n", m); } /* apply LLL on Lambda_m, may need to increase prec */ gchar_set_nalg(gc, nalg); gchar_set_u0(gc, u0); /* TODO factor these two LLL reduction codes in a function? */ if (nalg > 0) { GEN u = NULL; while (1) { if ((u = lll_block(m, ns+nc, n, ns+nc, nalg))) break; mprec = precdbl(mprec); m = gcharmatnewprec_shallow(gc, mprec); } u0 = ZM_mul(u0, u); m = RgM_ZM_mul(m, u); if (DEBUGLEVEL>1) err_printf("after LLL reduction (CM block) -> %Ps\n", m); } gchar_set_u0(gc, u0); if (nu > 0) { GEN u = NULL; while (1) { if ((u = lll_block(m, ns+nc, n, ns+nc+nalg, n-1-nalg))) break; mprec = precdbl(mprec); m = gcharmatnewprec_shallow(gc, mprec); } u0 = ZM_mul(u0, u); m = RgM_ZM_mul(m, u); if (DEBUGLEVEL>1) err_printf("after LLL reduction (trans block) -> %Ps\n", m); } gchar_set_u0(gc, u0); return m; } /* convert to snf basis of torsion + Z^(r1+2*r2-1) */ static void gchar_snfbasis_shallow(GEN gc, GEN rel) { long n, r1, r2, lU, lUi; GEN nf, cyc, U, Ui; nf = gchar_get_nf(gc); nf_get_sign(nf, &r1, &r2); n = r1+2*r2; rel = ZM_hnf(rel); if (DEBUGLEVEL>1) err_printf("relations after hnf: %Ps\n", rel); cyc = ZM_snf_group(rel, &U, &Ui); if (lg(cyc)==1) { cyc = zerovec(n-1); U = shallowconcat(zeromat(n-1,lg(rel)-1),matid(n-1)); Ui = shallowtrans(U); } else if (n!=1) { cyc = shallowconcat(cyc, zerovec(n-1)); U = shallowmatconcat(mkmat22(U,gen_0,gen_0,matid(n-1))); Ui = shallowmatconcat(mkmat22(Ui,gen_0,gen_0,matid(n-1))); } rel = shallowtrans(rel); lU = lg(U); lUi = lg(Ui); U = shallowtrans(U); if (lg(U)==1 && lUi>1) U = zeromat(0,lUi-1); Ui = shallowtrans(Ui); if (lg(Ui)==1 && lU>1) Ui = zeromat(0,lU-1); gchar_set_nfree(gc, n-1); gchar_set_ntors(gc, (lg(cyc)-1) - (n-1)); gchar_set_cyc(gc, shallowconcat(cyc, real_0(gchar_get_prec(gc)))); gchar_set_HUUi(gc, rel, U, Ui); } static long mextraprec(GEN m_inv, GEN m, GEN gc) { return nbits2extraprec(2*maxss(gexpo(m_inv),1) + expu(lg(m)) + gexpo(gchar_get_u0(gc)) + 10); } /* c) transpose inverse + clean rationals. * prec = target prec for m^-1, * mprec = prec of m */ static void gcharmat_tinverse(GEN gc, GEN m, long prec) { GEN m_inv; long k, r1, r2, ns, nc, nalg, nm, mprec, bitprec = prec2nbits(prec); nf_get_sign(gchar_get_nf(gc), &r1, &r2); ns = gchar_get_ns(gc); nc = gchar_get_nc(gc); nalg = gchar_get_nalg(gc); nm = ns + nc + r1 + 2*r2; if (lg(m)==1) { gchar_set_basis(gc,zeromat(0,nm)); return; } mprec = gprecision(m); /* possibly 0, if m is exact */ while (1) { long targetmprec = 0; GEN v0, mm; /* insert at column ns+nc+r1+r2, or last column if cm */ v0 = vec_v0(nm, ns+nc+1, r1, r2); mm = shallowmatinsert(m, v0, nalg? nm: nm-r2); if (DEBUGLEVEL>1) err_printf("add v0 -> %Ps\n", mm); mm = shallowtrans(mm); m_inv = RgM_inv(mm); /* invert matrix, may need to increase prec */ if (m_inv) { if (DEBUGLEVEL>1) err_printf("inverse: %Ps\n",m_inv); m_inv = vecsplice(m_inv, nalg? nm: nm-r2); /* remove v0 */ if (DEBUGLEVEL>1) err_printf("v0 removed: %Ps\n", m_inv); m_inv = shallowtrans(m_inv); if (!mprec) break; /* enough precision? */ /* |B - A^(-1)| << |B|.|Id-B*A| */ if (gexpo(m_inv) + gexpo(gsub(RgM_mul(m_inv, m), gen_1)) + expu(lg(m)) <= -bitprec) { /* |A^(-1) - (A+H)^(-1)| << |H|.|A^(-1)|^2 */ targetmprec = prec + mextraprec(m_inv,m,gc); if (mprec >= targetmprec) break; } else targetmprec = 0; } mprec = maxss(precdbl(mprec), targetmprec); if (mprec < DEFAULTPREC) mprec = DEFAULTPREC; m = gcharmatnewprec_shallow(gc, mprec); /* m0 * u0 to higher prec */ } /* clean rationals */ if (nc) { /* reduce mod exponent of the group, TODO reduce on each component */ GEN zmcyc = locs_get_cyc(gchar_get_zm(gc)); GEN e = ZV_lcm(zmcyc); for (k = 1; k <= nc; k++) shallow_clean_rat(gel(m_inv, ns+k), 1, nm - 1, /*zmcyc[k]*/e, prec); } if (r2) { for (k = 1; k <= r2; k++) shallow_clean_rat(gel(m_inv,nm-k+1), 1, nm-1, NULL, prec); } if (nalg) { long i, j, e; for (i = 1; i<=r1+r2; i++) for (j = 1; j <= nalg; j++) { e = gexpo(gcoeff(m_inv, ns+nc+j, ns+nc+i)); if (e > -20) /* TODO is this bound too permissive? */ pari_err_BUG("gcharinit (nonzero entry)"); /*LCOV_EXCL_LINE*/ gcoeff(m_inv, ns+nc+j, ns+nc+i) = gen_0; } } if (DEBUGLEVEL>1) err_printf("cyc/cm cleaned: %Ps", shallowtrans(m_inv)); /* normalize characters, parameters mod Z */ for (k = 1; k <= ns+nc; k++) gel(m_inv, k) = gfrac(gel(m_inv, k)); /* increase relative prec of real values */ gchar_set_basis(gc, gprec_w(m_inv, prec)); } /* make sure same argument determination is chosen */ static void same_arg(GEN v1, GEN v2, long s1, long s2) { long i1, i2, l = lg(v1); for (i1 = s1, i2 = s2; i1 < l; i1++,i2++) { GEN d = grndtoi(gsub(gel(v2,i2),gel(v1,i1)), NULL); if (signe(d)) gel(v1,i1) = gadd(gel(v1,i1), d); } } static void vaffect_shallow(GEN x, long i0, GEN y) { long i; for (i = 1; i < lg(y); i++) gel(x, i+i0) = gel(y, i); } /* recompute matrix with precision increased */ /* u0 the base change, returns m0 * u0 */ /* mprec: requested precision for m0 */ static GEN gcharmatnewprec_shallow(GEN gc, long mprec) { GEN nf, m0, u0, sfu; long k, l, ns, nc, r1, r2, nfprec, embprec; ns = gchar_get_ns(gc); nc = gchar_get_nc(gc); nf = gchar_get_nf(gc); sfu = gchar_get_sfu(gc); nf_get_sign(nf, &r1, &r2); nfprec = nf_get_prec(gchar_get_nf(gc)); m0 = gchar_get_m0(gc); u0 = gchar_get_u0(gc); if (DEBUGLEVEL>3) err_printf("gcharmatnewprec_shallow mprec=%d nfprec=%d\n", mprec, nfprec); embprec = mprec; l = lg(sfu); while(1) { /* recompute the nfembedlogs of s-units and fundamental units */ for (k = 1; k < l; k++) /* ns s-units, then r1+r2-1 fundamental units */ { GEN emb = nfembedlog(&nf, gel(sfu,k), embprec); if (!emb) break; same_arg(emb, gel(m0,k), r1+r2, ns+nc+r1+r2); vaffect_shallow(gel(m0, k), ns+nc, emb); } if (k == l) break; if (DEBUGLEVEL) err_printf("gcharmatnewprec_shallow: increasing embprec %d -> %d\n", embprec, precdbl(embprec)); embprec = precdbl(embprec); } gchar_set_nf(gc, nf); gchar_set_nfprec(gc, nfprec); return RgM_ZM_mul(m0, u0); } static void _check_gchar_group(GEN gc, long flag); static void check_gchar_group(GEN gc) { _check_gchar_group(gc, 0); } /* increase prec if needed. newprec: requested precision for m_inv */ static GEN gcharnewprec_i(GEN gc, long newprec) { long prec, prec0, nfprec, nfprec0, mprec; GEN gc2 = shallowcopy(gc); _check_gchar_group(gc2, 1); /* ignore illegal prec */ prec = gchar_get_prec(gc2); nfprec = gchar_get_nfprec(gc2); if (newprec > prec) { /* increase precision */ if (DEBUGLEVEL) pari_warn(warnprec,"gcharnewprec",newprec); nfprec += newprec - prec; prec = newprec; gchar_copy_precs(gc, gc2); gchar_set_prec(gc2, prec); gchar_set_nfprec(gc2, nfprec); } nfprec0 = nf_get_prec(gchar_get_nf(gc2)); if (nfprec0 && nfprec > nfprec0) { if (DEBUGLEVEL) pari_warn(warnprec,"gcharnewprec (nf)", nfprec); gchar_set_nf(gc2, nfnewprec_shallow(gchar_get_nf(gc2), nfprec)); } prec0 = gprecision(gchar_get_basis(gc2)); if (prec0 && prec > prec0) { GEN cyc, m, m0 = gchar_get_m0(gc); if (DEBUGLEVEL) pari_warn(warnprec,"gcharnewprec (minv)", prec); gchar_set_m0(gc2, shallowcopy(m0)); mprec = prec + mextraprec(gchar_get_basis(gc), m0, gc); m = gcharmatnewprec_shallow(gc2, mprec); if (DEBUGLEVEL>2) err_printf("m0*u0 recomputed -> %Ps\n", m); gcharmat_tinverse(gc2, m, prec); cyc = shallowcopy(gchar_get_cyc(gc2)); gel(cyc, lg(cyc)-1) = real_0(prec); gchar_set_cyc(gc2, cyc); } return gc2; } /* newprec: requested evalprec */ GEN gcharnewprec(GEN gc, long newprec) { pari_sp av = avma; GEN gc2 = gcharnewprec_i(gc, newprec + EXTRAPREC64); gchar_set_evalprec(gc2, newprec); return gerepilecopy(av, gc2); } static void check_localstar(GEN x) { if (typ(x) != t_VEC || lg(x) != LOCS_LENGTH + 1) pari_err_TYPE("char group", x); /* FIXME: check components once settled */ } int is_gchar_group(GEN gc) { return (typ(gc) == t_VEC && lg(gc) == GC_LENGTH + 1 && typ(gel(gc, 8)) == t_VEC && lg(gel(gc, 8)) == 3 && typ(gmael(gc, 8, 1)) == t_VECSMALL && typ(gmael(gc, 8, 2)) == t_VECSMALL && (checkbnf_i(gchar_get_bnf(gc)) != NULL) && (checknf_i(gchar_get_nf(gc)) != NULL)); } /* validates the structure format. * Raise error if inconsistent precision, unless flag=1. */ static void _check_gchar_group(GEN gc, long flag) { GEN b, bnf, nf; if (typ(gc) != t_VEC || lg(gc) != GC_LENGTH + 1) pari_err_TYPE("char group", gc); check_localstar(gchar_get_zm(gc)); if (typ(gchar_get_loccyc(gc)) != t_VEC) pari_err_TYPE("gchar group (loccyc)", gc); b = gchar_get_basis(gc); if (typ(b) != t_MAT) pari_err_TYPE("gchar group (basis)", gc); bnf = gchar_get_bnf(gc); checkbnf(bnf); nf = gchar_get_nf(gc); checknf(nf); if (!gequal(nf_get_pol(nf),nf_get_pol(bnf_get_nf(bnf)))) pari_err_TYPE("gchar group (nf != bnf.nf)", gc); if (typ(gel(gc,8)) != t_VEC ||typ(gmael(gc,8,1)) != t_VECSMALL) pari_err_TYPE("gchar group (gc[8])", gc); if (!flag) { long prec0 = gprecision(b), nfprec0 = nf_get_prec(nf); if ((prec0 && gchar_get_prec(gc) > prec0) || (nfprec0 && gchar_get_nfprec(gc) > nfprec0)) pari_err_PREC("gchar group, please call gcharnewprec"); } } /* basis of algebraic characters + cyc vector */ static GEN gchar_algebraic_basis(GEN gc) { long ntors, nfree, nc, nm, r2, nalg, n0, k; GEN basis, args, m, w, normchar, alg_basis, tors_basis; /* in snf basis */ ntors = gchar_get_ntors(gc); /* number of torsion generators */ nfree = gchar_get_nfree(gc); nc = ntors + nfree; /* in internal basis */ n0 = gchar_get_ns(gc) + gchar_get_nc(gc); /* last index of torsion char */ r2 = gchar_get_r2(gc); nm = gchar_get_nm(gc); /* in both */ nalg = gchar_get_nalg(gc); /* number of generators of free algebraic chars */ /* finite order characters have weight 0 */ tors_basis = matid(ntors); /* the norm is an algebraic character */ normchar = gneg(col_ei(nc+1,nc+1)); /* add sublattice of algebraic */ if (!nalg) { if (DEBUGLEVEL>2) err_printf("nalg=0\n"); return shallowmatconcat(mkvec2(tors_basis,normchar)); } /* block of k_s parameters of free algebraic */ args = matslice(gchar_get_basis(gc),n0+1,n0+nalg,nm-r2+1,nm); if (r2 == 1) { /* no parity condition */ if (DEBUGLEVEL>2) err_printf("r2 = 1 -> args = %Ps\n", args); alg_basis = matid(nalg); w = gel(args,1); } else { /* parity condition: w + k_s = 0 mod 2 for all s, ie solve x.K constant mod 2, ie solve x.K' = 0 mod 2 where K' = [ C-C0 ] (substract first column) */ /* select block k_s in char parameters and */ if (DEBUGLEVEL>2) err_printf("block ks -> %Ps\n", args); m = cgetg(r2, t_MAT); for (k = 1; k < r2; k++) gel(m,k) = gsub(gel(args,k+1),gel(args,1)); if (DEBUGLEVEL>2) err_printf("block ks' -> %Ps", m); alg_basis = shallowtrans(gel(matsolvemod(shallowtrans(m),gen_2,gen_0,1),2)); if (DEBUGLEVEL>2) err_printf("alg_basis -> %Ps\n", alg_basis); w = gmul(alg_basis, gel(args,1)); if (DEBUGLEVEL>2) err_printf("w -> %Ps\n", w); } /* add weight to infinite order characters, at position nc+1 */ w = gneg(gdivgs(gmodgs(w, 2), 2)); alg_basis = shallowmatconcat(mkvec3(alg_basis, zerovec(nfree-nalg), w)); if (lg(tors_basis)>1) basis = shallowmatconcat(mkmat22(tors_basis, gen_0, gen_0, alg_basis)); else basis = alg_basis; return shallowmatconcat(mkvec2(shallowtrans(basis),normchar)); } static GEN gchar_algebraicnormtype(GEN gc, GEN type) { GEN w = NULL, w1, v; long i, r1, r2, n; r1 = gchar_get_r1(gc); r2 = gchar_get_r2(gc); for (i=1; i<=r1; i++) { w1 = addii(gmael(type,i,1),gmael(type,i,2)); if (!w) w = w1; else if (!equalii(w,w1)) return NULL; } for (i=r1+1; i<=r1+r2; i++) { w1 = gmael(type,i,1); if (!w) w = w1; else if (!equalii(w,w1)) return NULL; if (!equalii(w,gmael(type,i,2))) return NULL; } n = lg(gchar_get_cyc(gc))-1; v = zerocol(n); gel(v,n) = negi(w); return mkvec(v); } static GEN gchar_algebraicoftype(GEN gc, GEN type) { long i, r1, r2, nalg, n0, nm; GEN p, q, w, k, matk, chi; /* in internal basis */ n0 = gchar_get_ns(gc) + gchar_get_nc(gc); /* last index of torsion chars */ r1 = gchar_get_r1(gc); r2 = gchar_get_r2(gc); nm = gchar_get_nm(gc); /* in both */ nalg = gchar_get_nalg(gc); /* number of generators of free algebraic chars */ if (typ(type)!=t_VEC || lg(type) != r1+r2+1) pari_err_TYPE("gcharalgebraic (1)", type); for (i = 1; i<=r1+r2; i++) if (typ(gel(type,i)) != t_VEC ||lg(gel(type,i)) != 3 ||typ(gmael(type,i,1)) != t_INT ||typ(gmael(type,i,2)) != t_INT) pari_err_TYPE("gcharalgebraic (2)", type); chi = gchar_algebraicnormtype(gc, type); if (chi) return chi; if (!nalg) return NULL; k = cgetg(r2+1,t_VEC); p = gmael(type, 1, 1); q = gmael(type, 1, 2); w = addii(p, q); gel(k, 1) = subii(q, p); for (i = 2; i <= r2; i++) { p = gmael(type, i, 1); q = gmael(type, i, 2); if (!equalii(w, addii(p, q))) return NULL; gel(k, i) = subii(q, p); } /* block of k_s parameters of free algebraic */ matk = matslice(gchar_get_basis(gc),n0+1,n0+nalg,nm-r2+1,nm); chi = inverseimage(shallowtrans(matk),shallowtrans(k)); if (lg(chi) == 1) return NULL; for (i=1; i 0; i--) { GEN gens = gel(gens_fil, i); long j; for (j = 1; j < lg(gens); j++) { GEN v = gmul(chip, gel(gens, j)); if (denom_i(v) != gen_1) return stoi(i); } } return gen_0; } /* assume chi in log form */ static GEN gcharlog_conductor_f(GEN gc, GEN chi, GEN *faN) { GEN zm, P, E, Lsprk, ufil; long i, l, ic; if (gchar_get_nc(gc) == 0) { if (faN) *faN = trivial_fact(); return gen_1; } zm = gchar_get_zm(gc); Lsprk = locs_get_Lsprk(zm); ufil = locs_get_Lgenfil(zm); P = gel(locs_get_famod(zm), 1); l = lg(Lsprk); E = cgetg(l, t_COL); for (i = 1, ic = gchar_get_ns(gc); i < l ; i++) { GEN gens = gel(ufil, i), chip; long ncp = sprk_get_ncp(gel(Lsprk,i)); chip = vecslice(chi, ic + 1, ic + ncp); gel(E, i) = conductor_expo_pr(gens, chip); ic += ncp; } if (faN) *faN = famat_remove_trivial(mkmat2(P,E)); return idealfactorback(gchar_get_nf(gc), P, E, 0); /* red = 0 */ } /* ={sigma} s.t. k_sigma = 1 */ static GEN gcharlog_conductor_oo(GEN gc, GEN chi) { long noo, i, n0 = gchar_get_ns(gc) + gchar_get_nc(gc); GEN k_real, chi_oo, moo, den; moo = locs_get_m_infty(gchar_get_zm(gc)); noo = lg(moo)-1; k_real = vecslice(chi, n0-noo+1, n0); chi_oo = zerovec(gchar_get_r1(gc)); for (i=1; i<=noo; i++) { den = Q_denom(gel(k_real,i)); if (den && !equali1(den)) gel(chi_oo, moo[i]) = gen_1; } return chi_oo; } static GEN gchari_conductor(GEN gc, GEN chi) { chi = gchari_duallog(gc, chi); return mkvec2(gcharlog_conductor_f(gc, chi, NULL), gcharlog_conductor_oo(gc, chi)); } GEN gchar_conductor(GEN gc, GEN chi) { pari_sp av = avma; check_gchar_group(gc); return gerepilecopy(av, gchari_conductor(gc, gchar_internal(gc, chi, NULL))); } int gcharisalgebraic(GEN gc, GEN chi, GEN *pq) { long i, ntors, nfree, n0, nalg, r1, r2; GEN w, chii, v; pari_sp av = avma; check_gchar_group(gc); /* in snf basis */ ntors = gchar_get_ntors(gc); nfree = gchar_get_nfree(gc); /* in internal basis */ r1 = gchar_get_r1(gc); r2 = gchar_get_r2(gc); n0 = gchar_get_nm(gc) - r2; /* last index before k_s */ /* in both */ nalg = gchar_get_nalg(gc); /* number of generators of free algebraic chars */ chii = gchar_internal(gc, chi, &w); /* check component are on algebraic generators */ for (i = ntors+nalg+1; i <= ntors+nfree; i++) if (!gequal0(gel(chi,i))) return gc_bool(av, 0); chii = gchari_duallog(gc, chii); if (r1) /* not totally complex: finite order * integral power of norm */ { if (typ(w) != t_INT) return gc_bool(av, 0); w = negi(w); if (pq) { /* set the infinity type */ v = cgetg(r1+r2+1, t_VEC); for (i = 1; i <= r1; i++) gel(v, i) = mkvec2(w, gen_0); for ( ; i <= r1+r2; i++) gel(v, i) = mkvec2(w, w); } } else /* totally complex */ { int w2; w = gneg(gmul2n(w, 1)); if (typ(w) != t_INT) return gc_bool(av, 0); w2 = mpodd(w); for (i = 1; i <= r2; i++) /* need k_s + w = 0 mod 2 for all s */ if (mpodd(gel(chii, n0 + i)) != w2) return gc_bool(av, 0); if (pq) { /* set the infinity type */ v = cgetg(r2+1, t_VEC); for (i = 1; i <= r2; i++) { GEN p = gmul2n(subii(w, gel(chii, n0+i)), -1); gel(v, i) = mkvec2(p, subii(w, p)); } } } if (pq) { *pq = gerepilecopy(av, v); av = avma; } return gc_bool(av, 1); } GEN gcharlocal(GEN gc, GEN chi, GEN v, long prec, GEN* pbid) { pari_sp av = avma; GEN nf = gchar_get_nf(gc), s, chiv, logchi; check_gchar_group(gc); chi = gchar_internal(gc, chi, &s); logchi = gchari_duallog(gc, chi); if (typ(v) == t_INT) /* v infinite */ { long i, r1, r2, tau = itos(v), n0 = gchar_get_ns(gc) + gchar_get_nc(gc); GEN phi, k; nf_get_sign(nf, &r1, &r2); if (tau <= 0) pari_err_DOMAIN("gcharlocal [index of an infinite place]", "v", "<=", gen_0, v); if (tau > r1+r2) pari_err_DOMAIN("gcharlocal [index of an infinite place]", "v", ">", stoi(r1+r2), v); if (r1+r2 == 1) phi = gen_0; else phi = gel(logchi, n0 + tau); if (tau <= r1) /* v real */ { GEN moo = gel(gchar_get_mod(gc),2); i = zv_search(moo, tau); if (i==0) k = gen_0; else { k = gel(logchi, n0 - lg(moo) + 1 + i); /* 0 or 1/2 */ if (!gequal0(k)) k = gen_1; } } else /* v complex */ k = gel(logchi, n0 + r2 + tau); if (s) phi = gsub(phi, mulcxI(s)); chiv = mkvec2(k, phi); } else /* v finite */ { GEN P = gchar_get_modP(gc); long iv; checkprid(v); iv = gen_search(P, v, (void*)cmp_prime_ideal, cmp_nodata); chiv = gchari_eval(gc, NULL, v, 0, logchi, s, prec); if (iv <= 0) chiv = mkvec(chiv); else { GEN cyc, w, Lsprk, bid, chip = NULL; long i, ic, l = lg(P); Lsprk = locs_get_Lsprk(gchar_get_zm(gc)); for (i = 1, ic = gchar_get_ns(gc); i < l; i++) { long ncp = sprk_get_ncp(gel(Lsprk,i)); if (i == iv) { chip = vecslice(logchi, ic + 1, ic + ncp); break; } ic += ncp; } if (!chip) pari_err_BUG("gcharlocal (chip not found)"); /* TODO store bid instead of recomputing? */ bid = sprk_to_bid(nf, gel(Lsprk,i), nf_INIT); cyc = bid_get_cyc(bid); w = RgV_RgM_mul(chip, gel(bid_get_U(bid),1)); for (i = 1; i < lg(w); i++) gel(w,i) = modii(gmul(gel(w,i), gel(cyc,i)), gel(cyc,i)); chiv = vec_append(w, chiv); if (pbid) { *pbid = bid; gerepileall(av, 2, &chiv, pbid); return chiv; } } } return gerepilecopy(av, chiv); } /*******************************************************************/ /* */ /* EVALUATION OF CHARACTERS */ /* */ /*******************************************************************/ GEN gcharduallog(GEN gc, GEN chi) { pari_sp av = avma; GEN logchi, s; check_gchar_group(gc); logchi = gchari_duallog(gc, gchar_internal(gc, chi, &s)); return gerepilecopy(av, shallowconcat1(mkcol2(logchi,s))); } static GEN gcharisprincipal(GEN gc, GEN x, GEN *palpha) { GEN t, v, bnf = gchar_get_bnf(gc), DLdata = gchar_get_DLdata(gc); t = bnfisprincipal0(bnf, x, nf_GENMAT | nf_FORCE); v = gel(t, 1); *palpha = famat_reduce(famat_mul(nffactorback(bnf, gel(DLdata,2), v), gel(t, 2))); return ZM_ZC_mul(gel(DLdata,1), v); } /* complete log of ideal; if logchi != NULL make sure precision is * sufficient to evaluate gcharlog_eval_raw to attain 'prec' */ static GEN gchar_log(GEN gc, GEN x, GEN logchi, long prec) { GEN zm, v, alpha, arch_log = NULL, zm_log, nf; nf = gchar_get_nf(gc); zm = gchar_get_zm(gc); v = gcharisprincipal(gc, x, &alpha); /* alpha a GENMAT */ if (DEBUGLEVEL>2) err_printf("v %Ps\n", v); zm_log = gchar_logm(nf, zm, alpha); if (DEBUGLEVEL>2) err_printf("zm_log(alpha) %Ps\n", zm_log); if (logchi) { /* check if precision is sufficient, take care of gexpo = -infty */ long e, bit = expu(nf_get_degree(nf) + lg(zm_log)-1) + 3; e = gexpo(logchi); if (e > 0) bit += e; e = gexpo(gel(alpha,1)); if (e > 0) bit += e; prec += nbits2extraprec(bit); } for(;;) { arch_log = nfembedlog(&nf, alpha, prec); if (arch_log) break; prec = precdbl(prec); } if (DEBUGLEVEL>2) err_printf("arch log %Ps\n", arch_log); return shallowconcat1(mkvec3(v, gneg(zm_log), gneg(arch_log))); } /* gp version, with norm component */ GEN gcharlog(GEN gc, GEN x, long prec) { pari_sp av = avma; GEN norm; check_gchar_group(gc); norm = idealnorm(gchar_get_nf(gc), x); norm = mkcomplex(gen_0, gdiv(glog(norm,prec), Pi2n(1,prec))); return gerepilecopy(av, vec_append(gchar_log(gc, x, NULL, prec), norm)); } static GEN gcharlog_eval_raw(GEN logchi, GEN logx) { GEN v = RgV_dotproduct(logchi, logx); return gsub(v, ground(v)); } /* if flag = 1 -> value in C, flag = 0 -> value in R/Z * chi in chari format without norm component (given in s) * if logchi is provided, assume it has enough precision * TODO check that logchi argument is indeed used correctly by callers */ static GEN gchari_eval(GEN gc, GEN chi, GEN x, long flag, GEN logchi, GEN s, long prec) { GEN z, norm, logx; if (!logchi) { long e, precgc = prec, prec0 = gchar_get_prec(gc); logchi = gchari_duallog(gc, chi); e = gexpo(logchi); if (e > 0) precgc += nbits2extraprec(e); if (precgc > prec0) { gc = gcharnewprec(gc, precgc); logchi = gchari_duallog(gc, chi); } } logx = gchar_log(gc, x, logchi, prec); norm = gequal0(s)? NULL: idealnorm(gchar_get_nf(gc), x); z = gcharlog_eval_raw(logchi, logx); if (flag) { z = expIPiC(gmul2n(z, 1), prec); if (norm) z = gmul(z, gpow(norm, gneg(s), prec)); } else if (norm) z = gadd(z, mulcxI(gdiv(gmul(s, glog(norm,prec)), Pi2n(1,prec)))); if (DEBUGLEVEL>1) err_printf("char value %Ps\n", z); return z; } GEN gchareval(GEN gc, GEN chi, GEN x, long flag) { GEN s; long prec; pari_sp av = avma; check_gchar_group(gc); prec = gchar_get_evalprec(gc); chi = gchar_internal(gc, chi, &s); return gerepileupto(av, gchari_eval(gc, chi, x, flag, NULL, s, prec)); } /*******************************************************************/ /* */ /* IDENTIFICATION */ /* */ /*******************************************************************/ static GEN col_2ei(long n, long i) { GEN e = zerocol(n); gel(e,i) = gen_2; return e; } static GEN gchar_identify_init(GEN gc, GEN Lv, long prec) { GEN M, cyc, mult, Lpr, Lk1, Lphi1, Lk2, Llog, eps, U, P, nf, moo, vlogchi; long beps, r1, r2, d, nmiss, n, npr, nk1, nchi, s, i, j, l, dim, n0, ncol; check_gchar_group(gc); n0 = gchar_get_ns(gc) + gchar_get_nc(gc); /* last index of torsion char */ cyc = gchar_get_cyc(gc); P = gchar_get_modP(gc); moo = gel(gchar_get_mod(gc), 2); nf = gchar_get_nf(gc); nf_get_sign(nf, &r1, &r2); nchi = lg(cyc)-2; /* ignore norm */ d = r1 + 2*r2; mult = (nchi >= d)? gel(cyc,1): gen_1; s = (8*prec2nbits(prec))/10; mult = shifti(mult, s); beps = -(7*s) / 16; eps = real2n(beps, prec); l = lg(Lv); if (lg(gen_sort_uniq(Lv, (void*)cmp_universal, cmp_nodata)) != l) pari_err(e_MISC, "components of Lv must be distinct"); /* log of prime ideals */ Llog = cgetg(l, t_VEC); /* index in Lchiv corresponding to the places */ Lpr = cgetg(l, t_VECSMALL); Lk1 = cgetg(l, t_VECSMALL); Lphi1 = zero_zv(r1); Lk2 = zero_zv(r2); nmiss = d; for (i = 1, npr = nk1 = 0; i < l; i++) if (typ(gel(Lv,i)) == t_INT) { long v = itos(gel(Lv,i)); if (v <= 0) pari_err_DOMAIN("gcharidentify", "v", "<=", gen_0, stoi(v)); if (v > r1+r2) pari_err_DOMAIN("gcharidentify", "v", ">", stoi(r1+r2), stoi(v)); if (v <= r1) { /* don't put in k1 if not in conductor (but keep as phi) */ if (zv_search(moo, v)) { nk1++; Lk1[nk1] = i; } Lphi1[v] = i; nmiss--; } else { Lk2[v-r1] = i; nmiss -= 2; } } else { GEN pr = gel(Lv,i); long lP = lg(P); if (idealtyp(&pr, NULL) != id_PRIME) pari_err_TYPE("gcharidentify [ideal]", pr); for (j = 1; j < lP; j++) if (pr_equal(pr, gel(P,j))) pari_err_COPRIME("gcharidentify", pr, gel(gchar_get_mod(gc), 1)); npr++; Lpr[npr] = i; gel(Llog,npr) = gchar_log(gc, pr, NULL, prec); } setlg(Llog, npr+1); setlg(Lpr, npr+1); setlg(Lk1, nk1+1); /* build matrix M */ n = npr + nk1; dim = n + d; ncol = n + 1 + nchi; M = cgetg(ncol+1, t_MAT); for (j = 1; j <= npr; j++) gel(M,j) = col_ei(dim, j); for (; j <= n; j++) gel(M,j) = col_2ei(dim, j); gel(M,j) = zerocol(dim); for (i = n+1; i <= n+r1+r2; i++) gcoeff(M,i,j) = eps; vlogchi = RgM_mul(gchar_get_Ui(gc), gchar_get_basis(gc)); for (j=1; j<=nchi; j++) { GEN logchi = RgV_frac_inplace(row(vlogchi, j), n0); /* duallog(e_j) */ GEN chi_oo = gcharlog_conductor_oo(gc, logchi), C = cgetg(dim+1, t_COL); for (i=1; i<=npr; i++) gel(C,i) = gcharlog_eval_raw(logchi, gel(Llog,i)); for (i=1; i<=nk1; i++) gel(C,npr+i) = gel(chi_oo, itos(gel(Lv,Lk1[i]))); for (i=1; i<=d; i++) gel(C,n+i) = gel(logchi, n0 + i); gel(M,n+1+j) = C; } for (i = 1; i <= r1; i++) if (!Lphi1[i]) { long a = n + i; for (j = 1; j <= ncol; j++) gcoeff(M,a,j) = gmul2n(gcoeff(M,a,j), beps); } for (i = 1; i <= r2; i++) if (!Lk2[i]) { long a = n + r1 + i, b = a + r2; for (j = 1; j <= ncol; j++) { gcoeff(M,a,j) = gmul2n(gcoeff(M,a,j), beps); gcoeff(M,b,j) = gmul2n(gcoeff(M,b,j), beps); } } /* rescale and truncate M, then LLL-reduce M */ M = gtrunc(RgM_Rg_mul(M, mult)); U = ZM_lll(M, 0.99, LLL_IM); M = ZM_mul(M, U); U = rowslice(U, n + 2, n + 1 + nchi); return mkvecn(9, M, U, Lpr, Lk1, Lphi1, Lk2, mult, Lv, mkvecsmall3(prec, nmiss, beps)); } /* TODO return the distance between the character found and the conditions? */ static GEN gchar_identify_i(GEN gc, GEN idinit, GEN Lchiv) { GEN M, U, Lpr, Lk1, Lphi1, Lk2, mult, cyc, y, x, sumphi, Lv, Norm, nf; long i, l, r1, r2, beps, npr, nk1, n, nmiss, nnorm, prec; M = gel(idinit,1); U = gel(idinit,2); Lpr = gel(idinit,3); Lk1 = gel(idinit,4); Lphi1 = gel(idinit,5); Lk2 = gel(idinit,6); mult = gel(idinit,7); Lv = gel(idinit,8); prec = gel(idinit,9)[1]; nmiss = gel(idinit,9)[2]; beps = gel(idinit,9)[3]; npr = lg(Lpr)-1; nk1 = lg(Lk1)-1; n = npr + nk1; cyc = gchar_get_cyc(gc); nf = gchar_get_nf(gc); nf_get_sign(nf, &r1, &r2); nnorm = 0; Norm = gen_0; l = lg(Lchiv); Lchiv = shallowcopy(Lchiv); if (lg(Lv) != l) pari_err_DIM("gcharidentify [#Lv != #Lchiv]"); for (i = 1; i < l; i++) { GEN t = gel(Lchiv,i), u; if (typ(gel(Lv,i)) != t_INT) { if (typ(t) == t_VEC) /* value at last component */ gel(Lchiv,i) = t = gel(t, lg(t)-1); if (typ(t) == t_COMPLEX) { nnorm++; /* 2 Pi Im(theta) / log N(pr) */ Norm = gadd(Norm, gdiv(gmul(Pi2n(1,prec), gel(t,2)), glog(idealnorm(nf,gel(Lv,i)),prec))); gel(Lchiv,i) = t = gel(t,1); } if (!is_real_t(typ(t))) pari_err_TYPE("gcharidentify [character value: should be real or complex]", t); } else { if (typ(t) != t_VEC) pari_err_TYPE("gcharidentify [character at infinite place: should be a t_VEC]", t); if (lg(t) != 3) pari_err_DIM("gcharidentify [character at infinite place: should have two components]"); if (typ(gel(t,1)) != t_INT) pari_err_TYPE("gcharidentify [k parameter at infinite place: should be a t_INT]", gel(t,1)); u = gel(t,2); if (typ(u) == t_COMPLEX) { nnorm++; Norm = gsub(Norm, gel(u,2)); u = gel(u,1); gel(Lchiv, i) = mkvec2(gel(t,1), u); } if (!is_real_t(typ(u))) pari_err_TYPE("gcharidentify [phi parameter at infinite place: should be real or complex]", u); } } /* construct vector */ y = zerocol(n + r1 + 2*r2); sumphi = gen_0; for (i=1; i<=npr; i++) gel(y,i) = gel(Lchiv, Lpr[i]); for (i=1; i<=nk1; i++) gel(y,npr+i) = gmael(Lchiv,Lk1[i],1); for (i=1; i<=r1; i++) if (Lphi1[i]) { gel(y, n+i) = x = gmael(Lchiv,Lphi1[i],2); sumphi = gadd(sumphi, x); } for (i=1; i<=r2; i++) if (Lk2[i]) { long a = n + r1 + i; gel(y, a + r2) = gmael(Lchiv,Lk2[i],1); gel(y, a) = x = gmael(Lchiv,Lk2[i],2); sumphi = gadd(sumphi, gshift(x,1)); } if (nmiss) { sumphi = gmul2n(gdivgs(sumphi, -nmiss), beps); for (i = 1; i <= r1; i++) if (!Lphi1[i]) gel(y, n + i) = sumphi; for (i = 1; i <= r2; i++) if (!Lk2[i]) gel(y, n + r1+i) = sumphi; } y = gtrunc(RgC_Rg_mul(y, mult)); /* find approximation */ x = ZM_ZC_mul(U, RgM_Babai(M, y)); for (i = 1; i < lg(cyc)-1; i++) /* ignore norm */ if (signe(gel(cyc,i))) gel(x,i) = modii(gel(x,i), gel(cyc,i)); if (nnorm > 0) x = vec_append(x, gdivgu(Norm, lg(Lv)-1)); return x; } /* TODO export the init interface */ GEN gchar_identify(GEN gc, GEN Lv, GEN Lchiv, long prec) { pari_sp av = avma; GEN idinit = gchar_identify_init(gc, Lv, prec); return gerepilecopy(av, gchar_identify_i(gc,idinit,Lchiv)); } /*******************************************************************/ /* */ /* L FUNCTION */ /* */ /*******************************************************************/ /* TODO: could merge with vecan_chigen */ /* return x + yz; y != 0; z = 0,1 "often"; x = 0 "often" */ static GEN gaddmul(GEN x, GEN y, GEN z) { pari_sp av; if (typ(z) == t_INT) { if (!signe(z)) return x; if (equali1(z)) return gadd(x,y); } if (isintzero(x)) return gmul(y,z); av = avma; return gerepileupto(av, gadd(x, gmul(y,z))); } GEN vecan_gchar(GEN an, long n, long prec) { forprime_t iter; GEN gc = gel(an,1), chi = gel(an,2), P = gel(an,3), PZ = gel(an,4); GEN BOUND = stoi(n), v = vec_ei(n, 1); GEN gp = cgetipos(3), nf, chilog, s; ulong p; /* prec increase: 1/n*log(N(pmax)) < log(pmax) */ if (DEBUGLEVEL > 1) err_printf("vecan_gchar: need extra prec %ld\n", nbits2extraprec(expu(n))); gc = gcharnewprec(gc, prec + nbits2extraprec(expu(n))); chilog = gchari_duallog(gc, check_gchari(gc, chi, &s)); nf = gchar_get_nf(gc); /* FIXME: when many log of many primes are computed: - bnfisprincipal may not be improved - however we can precompute the logs of generators for principal part - when galois, should compute one ideal by orbit. - when real, clear imaginary part */ u_forprime_init(&iter, 2, n); while ((p = u_forprime_next(&iter))) { GEN L; long j; int check = !umodiu(PZ,p); gp[2] = p; L = idealprimedec_limit_norm(nf, gp, BOUND); for (j = 1; j < lg(L); j++) { GEN pr = gel(L, j), ch; pari_sp av; ulong k, q; if (check && gen_search(P, pr, (void*)cmp_prime_ideal, cmp_nodata) > 0) continue; /* TODO: extract code and use precom sprk? */ av = avma; ch = gchari_eval(gc, chi, pr, 1, chilog, gen_0, prec); ch = gerepileupto(av, ch); q = upr_norm(pr); gel(v, q) = gadd(gel(v, q), ch); for (k = 2*q; k <= (ulong)n; k += q) gel(v, k) = gaddmul(gel(v, k), ch, gel(v, k/q)); } } /* weight, could consider shifting s at eval instead */ if (!gequal0(s)) { GEN ns = dirpowers(n, gneg(s), prec); long j; for (j = 1; j <= n; j++) if (gel(v,j) != gen_0) gel(v, j) = gmul(gel(v,j),gel(ns,j)); } return v; } GEN eulerf_gchar(GEN an, GEN p, long prec) { GEN gc = gel(an,1), chi = gel(an,2), P = gel(an,3), PZ = gel(an,4); GEN f, L, nf, chilog, s; int check; long j, l; /* prec increase: 1/n*log(N(pmax)) < log(pmax) */ if (DEBUGLEVEL > 1) err_printf("vecan_gchar: need extra prec %ld\n", nbits2extraprec(expi(p))); gc = gcharnewprec(gc, prec + nbits2extraprec(expi(p))); chilog = gchari_duallog(gc, check_gchari(gc, chi, &s)); nf = gchar_get_nf(gc); f = pol_1(0); check = dvdii(PZ, p); L = idealprimedec(nf, p); l = lg(L); for (j = 1; j < l; j++) { GEN pr = gel(L, j), ch; if (check && gen_search(P, pr, (void*)cmp_prime_ideal, cmp_nodata) > 0) continue; ch = gchari_eval(gc, chi, pr, 1, chilog, s, prec); f = gmul(f, gsub(gen_1, monomial(ch, pr_get_f(pr), 0))); } return mkrfrac(gen_1,f); } static GEN cleanup_vga(GEN vga, long prec) { GEN ind; long bitprec, i, l; if (!prec) return vga; /* already exact */ bitprec = prec2nbits(prec); vga = shallowcopy(vga); l = lg(vga); for (i = 1; i < l; i++) { GEN z = gel(vga,i); if (typ(z) != t_COMPLEX) continue; if (gexpo(gel(z,2)) < -bitprec+20) gel(vga,i) = gel(z,1); } ind = indexsort(imag_i(vga)); for (i = 2; i < l; i++) { GEN z = gel(vga,ind[i]), t; if (typ(z) != t_COMPLEX) continue; t = imag_i(gel(vga, ind[i-1])); if (gexpo(gsub(gel(z,2), t)) < -bitprec+20) gel(vga, ind[i]) = mkcomplex(gel(z,1), t); } for (i = 1; i < l; i++) { GEN z = gel(vga,i); if (typ(z) != t_COMPLEX) continue; gel(vga, i) = mkcomplex(gel(z,1), bestappr(gel(z,2), int2n(bitprec/2))); } return vga; } /* TODO: move to lfunutils, use lfunzeta and lfunzetak */ GEN gchari_lfun(GEN gc, GEN chi, GEN s0) { GEN nf, chilog, s, cond_f, cond_oo, vga_r, vga_c, chiw; GEN v_phi, v_arg, sig, k, NN, faN, P; long ns, nc, nm, r1, r2; nf = gchar_get_nf(gc); ns = gchar_get_ns(gc); nc = gchar_get_nc(gc); nm = gchar_get_nm(gc); nf_get_sign(nf, &r1, &r2); chi = check_gchari(gc, chi, &s); chilog = gchari_duallog(gc, chi); s = gadd(s0,s); chiw = shallowconcat(chi, s); if (!gequal0(imag_i(s))) pari_err_IMPL("lfun for gchar with imaginary norm component"); cond_f = gcharlog_conductor_f(gc, chilog, &faN); P = gel(faN, 1); /* prime ideals dividing cond(chi) */ cond_oo = gcharlog_conductor_oo(gc, chilog); NN = mulii(idealnorm(nf, cond_f), absi_shallow(nf_get_disc(nf))); if (equali1(NN)) return lfunshift(lfuncreate(gen_1), gneg(s), 0, prec2nbits(gchar_get_evalprec(gc))); if (ZV_equal0(chi)) return lfunshift(lfuncreate(nf), gneg(s), 0, prec2nbits(gchar_get_evalprec(gc))); /* vga_r = vector(r1,k,I*c[ns+nc+k]-s + cond_oo[k]); * vga_c = vector(r2,k,I*c[ns+nc+r1+k]+abs(c[ns+nc+r1+r2+k])/2-s) */ v_phi = gmul(vecslice(chilog, ns+nc+1, ns+nc+r1+r2), gen_I()); v_arg = gdivgs(gabs(vecslice(chilog,ns+nc+r1+r2+1,nm),BITS_IN_LONG), 2); vga_r = gadd(vecslice(v_phi, 1, r1), cond_oo); vga_c = gadd(vecslice(v_phi, r1+1, r1+r2), v_arg); sig = shallowconcat1(mkvec3(vga_r,vga_c,gadd(vga_c,const_vec(r2,gen_1)))); /* TODO: remove cleanup when gammamellinv takes ldata*/ sig = cleanup_vga(sig, gchar_get_prec(gc)); k = gen_1; if (!gequal0(s)) { long j; for (j = 1; j < lg(sig); j++) gel(sig, j) = gadd(gel(sig, j), s); k = gsub(k, gmulgs(s,2)); } #define tag(x,t) mkvec2(mkvecsmall(t),x) return mkvecn(6, tag(mkvec4(gc, chiw, P, prV_lcm_capZ(P)), t_LFUN_HECKE), gen_1, sig, k, NN, gen_0); } GEN lfungchar(GEN gc, GEN chi) { pari_sp av = avma; GEN s; check_gchar_group(gc); chi = gchar_internal(gc, chi, &s); return gerepilecopy(av, gchari_lfun(gc, chi, s)); } pari-2.17.2/src/basemath/bb_group.c0000644000175000017500000007003014760123736015513 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; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /***********************************************************************/ /** **/ /** 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) */ #define DEBUGLEVEL DEBUGLEVEL_bb_group /***********************************************************************/ /** **/ /** POWERING **/ /** **/ /***********************************************************************/ /* return (n>>(i+1-l)) & ((1<=l) return (w>>(r-l))&((1UL<>= (BITS_IN_LONG-lr); return (w<= 0) { long w, v; GEN tw; if (e > l+1) e = l+1; w = (n>>(l+1-e)) & ((1UL<>(v+1))); if (!z) z = tw; else { for (i = 1; i <= e-v; i++) z = sqr(E, z); z = mul(E, z, tw); } for (i = 1; i <= v; i++) z = sqr(E, z); while (l >= 0) { if (n&(1UL<= 0) { long w, v; GEN tw; 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) z = tw; else { for (i = 1; i <= e-v; i++) z = sqr(E, z); z = mul(E, z, tw); } for (i = 1; i <= v; i++) z = sqr(E, z); while (l >= 0) { if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"sliding_window_pow (%ld)", l); z = gerepilecopy(av, z); } if (int_bit(n,l)) break; z = sqr(E, z); l--; } } return z; } /* assume n != 0, t_INT. Compute x^|n| using leftright binary powering */ static GEN leftright_binary_powu(GEN x, ulong n, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN)) { pari_sp av = avma; GEN y; int j; if (n == 1) return x; y = x; j = 1+bfffo(n); /* normalize, i.e set highest bit to 1 (we know n != 0) */ n<<=j; j = BITS_IN_LONG-j; /* first bit is now implicit */ for (; j; n<<=1,j--) { y = sqr(E,y); if (n & HIGHBIT) y = mul(E,y,x); /* first bit set: multiply by base */ if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"leftright_powu (%d)", j); y = gerepilecopy(av, y); } } return y; } GEN gen_powu_i(GEN x, ulong n, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN)) { if (n == 1) return x; if (n < 512) return leftright_binary_powu(x, n, E, sqr, mul); else return sliding_window_powu(x, n, n < (1UL<<25)? 2: 3, E, sqr, mul); } GEN gen_powu(GEN x, ulong n, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN)) { pari_sp av = avma; if (n == 1) return gcopy(x); return gerepilecopy(av, gen_powu_i(x,n,E,sqr,mul)); } GEN gen_pow_i(GEN x, GEN n, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN)) { long l, e; if (lgefint(n)==3) return gen_powu_i(x, uel(n,2), E, sqr, mul); l = expi(n); if (l<=64) e = 3; else if (l<=160) e = 4; else if (l<=384) e = 5; else if (l<=896) e = 6; else e = 7; return sliding_window_pow(x, n, e, E, sqr, mul); } GEN gen_pow(GEN x, GEN n, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN)) { pari_sp av = avma; return gerepilecopy(av, gen_pow_i(x,n,E,sqr,mul)); } /* assume n > 0. Compute x^n using left-right binary powering */ GEN gen_powu_fold_i(GEN x, ulong n, void *E, GEN (*sqr)(void*,GEN), GEN (*msqr)(void*,GEN)) { pari_sp av = avma; GEN y; int j; if (n == 1) return x; y = x; j = 1+bfffo(n); /* normalize, i.e set highest bit to 1 (we know n != 0) */ n<<=j; j = BITS_IN_LONG-j; /* first bit is now implicit */ for (; j; n<<=1,j--) { if (n & HIGHBIT) y = msqr(E,y); /* first bit set: multiply by base */ else y = sqr(E,y); if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"gen_powu_fold (%d)", j); y = gerepilecopy(av, y); } } return y; } GEN gen_powu_fold(GEN x, ulong n, void *E, GEN (*sqr)(void*,GEN), GEN (*msqr)(void*,GEN)) { pari_sp av = avma; if (n == 1) return gcopy(x); return gerepilecopy(av, gen_powu_fold_i(x,n,E,sqr,msqr)); } /* assume N != 0, t_INT. Compute x^|N| using left-right binary powering */ GEN gen_pow_fold_i(GEN x, GEN N, void *E, GEN (*sqr)(void*,GEN), GEN (*msqr)(void*,GEN)) { long ln = lgefint(N); if (ln == 3) return gen_powu_fold_i(x, N[2], E, sqr, msqr); else { GEN nd = int_MSW(N), y = x; ulong n = *nd; long i; int j; pari_sp av = avma; if (n == 1) j = 0; else { j = 1+bfffo(n); /* < BIL */ /* normalize, i.e set highest bit to 1 (we know n != 0) */ n <<= j; j = BITS_IN_LONG - j; } /* first bit is now implicit */ for (i=ln-2;;) { for (; j; n<<=1,j--) { if (n & HIGHBIT) y = msqr(E,y); /* first bit set: multiply by base */ else y = sqr(E,y); if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"gen_pow_fold (%ld,%d)", i,j); y = gerepilecopy(av, y); } } if (--i == 0) return y; nd = int_precW(nd); n = *nd; j = BITS_IN_LONG; } } } GEN gen_pow_fold(GEN x, GEN n, void *E, GEN (*sqr)(void*,GEN), GEN (*msqr)(void*,GEN)) { pari_sp av = avma; return gerepilecopy(av, gen_pow_fold_i(x,n,E,sqr,msqr)); } GEN gen_pow_init(GEN x, GEN n, long k, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN)) { long i, j, l = expi(n); long m = 1UL<<(k-1); GEN x2 = sqr(E, x), y = gcopy(x); GEN R = cgetg(m+1, t_VEC); for(i = 1; i <= m; i++) { GEN C = cgetg(l+1, t_VEC); gel(C,1) = y; for(j = 2; j <= l; j++) gel(C,j) = sqr(E, gel(C,j-1)); gel(R,i) = C; y = mul(E, y, x2); } return R; } GEN gen_pow_table(GEN R, GEN n, void *E, GEN (*one)(void*), GEN (*mul)(void*,GEN,GEN)) { long e = expu(lg(R)-1) + 1; long l = expi(n); long i, w; GEN z = one(E), tw; for(i=0; i<=l; ) { if (int_bit(n, i)==0) { i++; continue; } if (i+e-1>l) e = l+1-i; w = int_block(n,i+e-1,e); tw = gmael(R, 1+(w>>1), i+1); z = mul(E, z, tw); i += e; } return z; } GEN gen_powers(GEN x, long l, int use_sqr, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN), GEN (*one)(void*)) { long i; GEN V = cgetg(l+2,t_VEC); gel(V,1) = one(E); if (l==0) return V; gel(V,2) = gcopy(x); if (l==1) return V; gel(V,3) = sqr(E,x); if (use_sqr) for(i = 4; i < l+2; i++) gel(V,i) = (i&1)? sqr(E,gel(V, (i+1)>>1)) : mul(E,gel(V, i-1),x); else for(i = 4; i < l+2; i++) gel(V,i) = mul(E,gel(V,i-1),x); return V; } GEN producttree_scheme(long n) { GEN v, w; long i, j, k, u, l; if (n<=2) return mkvecsmall(n); u = expu(n-1); v = cgetg(n+1,t_VECSMALL); w = cgetg(n+1,t_VECSMALL); v[1] = n; l = 1; for (i=1; i<=u; i++) { for(j=1, k=1; j<=l; j++, k+=2) { long vj = v[j], v2 = vj>>1; w[k] = vj-v2; w[k+1] = v2; } swap(v,w); l<<=1; } fixlg(v, l+1); set_avma((pari_sp)v); return v; } GEN gen_product(GEN x, void *E, GEN (*mul)(void *,GEN,GEN)) { pari_sp av; long i, k, l = lg(x); pari_timer ti; GEN y, v; if (l <= 2) return l == 1? gen_1: gcopy(gel(x,1)); y = cgetg(l, t_VEC); av = avma; v = producttree_scheme(l-1); l = lg(v); if (DEBUGLEVEL>7) timer_start(&ti); for (k = i = 1; k < l; i += v[k++]) gel(y,k) = v[k]==1? gel(x,i): mul(E, gel(x,i), gel(x,i+1)); while (k > 2) { long n = k - 1; if (DEBUGLEVEL>7) timer_printf(&ti,"gen_product: remaining objects %ld",n); for (k = i = 1; i < n; i += 2) gel(y,k++) = mul(E, gel(y,i), gel(y,i+1)); if (gc_needed(av,1)) gerepilecoeffs(av, y+1, k-1); } return gel(y,1); } /***********************************************************************/ /** **/ /** 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), b = gel(A,2), c = gel(A,3); switch((h | grp->hash(a)) % 3UL) { case 0: return mkvec3(grp->pow(E,a,gen_2), Fp_mulu(b,2,q), Fp_mulu(c,2,q)); case 1: return mkvec3(grp->mul(E,a,x), addiu(b,1), c); case 2: return mkvec3(grp->mul(E,a,g), b, addiu(c,1)); } return NULL; /* LCOV_EXCL_LINE */ } /*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; GEN A, B, l, sqrt4q = sqrti(shifti(q,4)); ulong i, h = 0, imax = itou_or_0(sqrt4q); if (!imax) imax = ULONG_MAX; do { rho_restart: A = B = mkvec3(x,gen_1,gen_0); i=0; do { if (i>imax) { h++; if (DEBUGLEVEL) pari_warn(warner,"changing Pollard rho hash seed to %ld",h); goto rho_restart; } A = iter_rho(x, g, q, A, h, E, grp); B = iter_rho(x, g, q, B, h, E, grp); B = iter_rho(x, g, q, B, h, E, grp); if (gc_needed(av,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"gen_Pollard_log"); gerepileall(av, 2, &A, &B); } i++; } while (!grp->equal(gel(A,1), gel(B,1))); gel(A,2) = modii(gel(A,2), q); gel(B,2) = modii(gel(B,2), q); h++; } while (equalii(gel(A,2), gel(B,2))); l = Fp_div(Fp_sub(gel(B,3), gel(A,3),q),Fp_sub(gel(A,2), gel(B,2), q), q); return gerepileuptoint(av, l); } /* compute a hash of g^(i-1), 1<=i<=n. Return [sorted hash, perm, g^-n] */ GEN gen_Shanks_init(GEN g, long n, void *E, const struct bb_group *grp) { GEN p1 = g, G, perm, table = cgetg(n+1,t_VECSMALL); pari_sp av=avma; long i; table[1] = grp->hash(grp->pow(E,g,gen_0)); for (i=2; i<=n; i++) { table[i] = grp->hash(p1); p1 = grp->mul(E,p1,g); if (gc_needed(av,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"gen_Shanks_log, baby = %ld", i); p1 = gerepileupto(av, p1); } } G = gerepileupto(av, grp->pow(E,p1,gen_m1)); /* g^-n */ perm = vecsmall_indexsort(table); table = vecsmallpermute(table,perm); return mkvec4(table,perm,g,G); } /* T from gen_Shanks_init(g,n). Return v < n*N such that x = g^v or NULL */ GEN gen_Shanks(GEN T, GEN x, ulong N, void *E, const struct bb_group *grp) { pari_sp av=avma; GEN table = gel(T,1), perm = gel(T,2), g = gel(T,3), G = gel(T,4); GEN p1 = x; long n = lg(table)-1; ulong k; for (k=0; khash(p1), i = zv_search(table, h); if (i) { do i--; while (i && table[i] == h); for (i++; i <= n && table[i] == h; i++) { GEN v = addiu(muluu(n,k), perm[i]-1); if (grp->equal(grp->pow(E,g,v),x)) return gerepileuptoint(av,v); if (DEBUGLEVEL) err_printf("gen_Shanks_log: false positive %lu, %lu\n", k,h); } } p1 = grp->mul(E,p1,G); if (gc_needed(av,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"gen_Shanks_log, k = %lu", k); p1 = gerepileupto(av, p1); } } return NULL; } /* Generic Shanks baby-step/giant-step algorithm. Return log_g(x), ord g = q. * One-shot: use gen_Shanks_init/log if many logs are desired; early abort * if log < sqrt(q) */ static GEN gen_Shanks_log(GEN x, GEN g, GEN q, void *E, const struct bb_group *grp) { pari_sp av=avma, av1; long lbaby, i, k; GEN p1, table, giant, perm, ginv; p1 = sqrti(q); if (abscmpiu(p1,LGBITS) >= 0) pari_err_OVERFLOW("gen_Shanks_log [order too large]"); lbaby = itos(p1)+1; table = cgetg(lbaby+1,t_VECSMALL); ginv = grp->pow(E,g,gen_m1); av1 = avma; for (p1=x, i=1;;i++) { if (grp->equal1(p1)) return gc_stoi(av, i-1); table[i] = grp->hash(p1); if (i==lbaby) break; p1 = grp->mul(E,p1,ginv); if (gc_needed(av1,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"gen_Shanks_log, baby = %ld", i); p1 = gerepileupto(av1, p1); } } p1 = giant = gerepileupto(av1, grp->mul(E,x,grp->pow(E, p1, gen_m1))); perm = vecsmall_indexsort(table); table = vecsmallpermute(table,perm); av1 = avma; for (k=1; k<= lbaby; k++) { long h = grp->hash(p1), i = zv_search(table, h); if (i) { while (table[i] == h && i) i--; for (i++; i <= lbaby && table[i] == h; i++) { GEN v = addiu(mulss(lbaby-1,k),perm[i]-1); if (grp->equal(grp->pow(E,g,v),x)) return gerepileuptoint(av,v); if (DEBUGLEVEL) err_printf("gen_Shanks_log: false positive %ld, %lu\n", k,h); } } p1 = grp->mul(E,p1,giant); if (gc_needed(av1,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"gen_Shanks_log, k = %ld", k); p1 = gerepileupto(av1, p1); } } set_avma(av); return cgetg(1, t_VEC); /* no solution */ } /*Generic discrete logarithme in a group of prime order p*/ GEN gen_plog(GEN x, GEN g, GEN p, void *E, const struct bb_group *grp) { if (grp->easylog) { GEN e = grp->easylog(E, x, g, p); if (e) return e; } if (grp->equal1(x)) return gen_0; if (grp->equal(x,g)) return gen_1; if (expi(p)<32) return gen_Shanks_log(x,g,p,E,grp); return gen_Pollard_log(x, g, p, E, grp); } GEN get_arith_ZZM(GEN o) { if (!o) return NULL; switch(typ(o)) { case t_INT: if (signe(o) > 0) return mkvec2(o, Z_factor(o)); break; case t_MAT: if (is_Z_factorpos(o)) return mkvec2(factorback(o), o); break; case t_VEC: if (lg(o) == 3 && signe(gel(o,1)) > 0 && is_Z_factorpos(gel(o,2))) return o; break; } pari_err_TYPE("generic discrete logarithm (order factorization)",o); return NULL; /* LCOV_EXCL_LINE */ } GEN get_arith_Z(GEN o) { if (!o) return NULL; switch(typ(o)) { case t_INT: if (signe(o) > 0) return o; break; case t_MAT: o = factorback(o); if (typ(o) == t_INT && signe(o) > 0) return o; break; case t_VEC: if (lg(o) != 3) break; o = gel(o,1); if (typ(o) == t_INT && signe(o) > 0) return o; break; } pari_err_TYPE("generic discrete logarithm (order factorization)",o); return NULL; /* LCOV_EXCL_LINE */ } /* Generic Pohlig-Hellman discrete logarithm: smallest integer n >= 0 such that * g^n=a. Assume ord(g) | ord; grp->easylog() is an optional trapdoor * function that catches easy logarithms */ GEN gen_PH_log(GEN a, GEN g, GEN ord, void *E, const struct bb_group *grp) { pari_sp av = avma; GEN v, ginv, fa, ex; long i, j, l; if (grp->equal(g, a)) /* frequent special case */ return grp->equal1(g)? gen_0: gen_1; if (grp->easylog) { GEN e = grp->easylog(E, a, g, ord); if (e) return e; } v = get_arith_ZZM(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; i < l; i++) { GEN q = gel(fa,i), qj, gq, nq, ginv0, a0, t0; long e = itos(gel(ex,i)); if (DEBUGLEVEL>5) 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); /* ord(ginv0) | q^e */ if (grp->equal1(ginv0)) { gel(v,i) = mkintmod(gen_0, gen_1); continue; } do gq = grp->pow(E,g, mulii(t0, gel(qj,--e))); while (grp->equal1(gq)); /* ord(gq) = q */ nq = gen_0; for (j = 0;; j++) { /* nq = sum_{ipow(E,a0, gel(qj,e-j)); /* cheap early abort: wrong local order */ if (j == 0 && !grp->equal1(grp->pow(E,b,q))) { set_avma(av); return cgetg(1, t_VEC); } b = gen_plog(b, gq, q, E, grp); if (typ(b) != t_INT) { set_avma(av); return cgetg(1, t_VEC); } nq = addii(nq, mulii(b, gel(qj,j))); if (j == e) break; a0 = grp->mul(E,a0, grp->pow(E,ginv0, b)); ginv0 = grp->pow(E,ginv0, q); } gel(v,i) = mkintmod(nq, gel(qj,e+1)); } return gerepileuptoint(av, lift(chinese1_coprime_Z(v))); } /***********************************************************************/ /** **/ /** ORDER OF AN ELEMENT **/ /** **/ /***********************************************************************/ /*Find the exact order of a assuming a^o==1*/ GEN gen_order(GEN a, GEN o, void *E, const struct bb_group *grp) { pari_sp av = avma; long i, l; GEN m; m = get_arith_ZZM(o); if (!m) pari_err_TYPE("gen_order [missing order]",a); o = gel(m,1); m = gel(m,2); l = lgcols(m); for (i = l-1; i; i--) { GEN t, y, p = gcoeff(m,i,1); long j, e = itos(gcoeff(m,i,2)); if (l == 2) { t = gen_1; y = a; } else { t = diviiexact(o, powiu(p,e)); y = grp->pow(E, a, t); } if (grp->equal1(y)) o = t; else { for (j = 1; j < e; j++) { y = grp->pow(E, y, p); if (grp->equal1(y)) break; } if (j < e) { if (j > 1) p = powiu(p, j); o = mulii(t, p); } } } return gerepilecopy(av, o); } /*Find the exact order of a assuming a^o==1, return [order,factor(order)] */ GEN gen_factored_order(GEN a, GEN o, void *E, const struct bb_group *grp) { pari_sp av = avma; long i, l, ind; GEN m, F, P; m = get_arith_ZZM(o); if (!m) pari_err_TYPE("gen_factored_order [missing order]",a); o = gel(m,1); m = gel(m,2); l = lgcols(m); P = cgetg(l, t_COL); ind = 1; F = cgetg(l, t_COL); for (i = l-1; i; i--) { GEN t, y, p = gcoeff(m,i,1); long j, e = itos(gcoeff(m,i,2)); if (l == 2) { t = gen_1; y = a; } else { t = diviiexact(o, powiu(p,e)); y = grp->pow(E, a, t); } if (grp->equal1(y)) o = t; else { for (j = 1; j < e; j++) { y = grp->pow(E, y, p); if (grp->equal1(y)) break; } gel(P,ind) = p; gel(F,ind) = utoipos(j); if (j < e) { if (j > 1) p = powiu(p, j); o = mulii(t, p); } ind++; } } setlg(P, ind); P = vecreverse(P); setlg(F, ind); F = vecreverse(F); return gerepilecopy(av, mkvec2(o, mkmat2(P,F))); } /* E has order o[1], ..., or o[#o], draw random points until all solutions * but one are eliminated */ GEN gen_select_order(GEN o, void *E, const struct bb_group *grp) { pari_sp ltop = avma, btop; GEN lastgood, so, vo; long lo = lg(o), nbo=lo-1; if (nbo == 1) return icopy(gel(o,1)); so = ZV_indexsort(o); /* minimize max( o[i+1] - o[i] ) */ vo = zero_zv(lo); lastgood = gel(o, so[nbo]); btop = avma; for(;;) { GEN lasto = gen_0; GEN P = grp->rand(E), t = mkvec(gen_0); long i; for (i = 1; i < lo; i++) { GEN newo = gel(o, so[i]); if (vo[i]) continue; t = grp->mul(E,t, grp->pow(E, P, subii(newo,lasto)));/*P^o[i]*/ lasto = newo; if (!grp->equal1(t)) { if (--nbo == 1) { set_avma(ltop); return icopy(lastgood); } vo[i] = 1; } else lastgood = lasto; } set_avma(btop); } } /*******************************************************************/ /* */ /* n-th ROOT */ /* */ /*******************************************************************/ /* Assume l is prime. Return a generator of the l-th Sylow and set *zeta to an element * of order l. * * q = l^e*r, e>=1, (r,l)=1 * UNCLEAN */ static GEN gen_lgener(GEN l, long e, GEN r,GEN *zeta, void *E, const struct bb_group *grp) { const pari_sp av1 = avma; GEN m, m1; long i; for (;; set_avma(av1)) { m1 = m = grp->pow(E, grp->rand(E), r); if (grp->equal1(m)) continue; for (i=1; ipow(E,m,l); if (grp->equal1(m)) break; } if (i==e) break; } *zeta = m; return m1; } /* Let G be a cyclic group of order o>1. Returns a (random) generator */ GEN gen_gener(GEN o, void *E, const struct bb_group *grp) { pari_sp ltop = avma, av; long i, lpr; GEN F, N, pr, z=NULL; F = get_arith_ZZM(o); N = gel(F,1); pr = gel(F,2); lpr = lgcols(pr); av = avma; for (i = 1; i < lpr; i++) { GEN l = gcoeff(pr,i,1); long e = itos(gcoeff(pr,i,2)); GEN r = diviiexact(N,powis(l,e)); GEN zetan, zl = gen_lgener(l,e,r,&zetan,E,grp); z = i==1 ? zl: grp->mul(E,z,zl); if (gc_needed(av,2)) { /* n can have lots of prime factors*/ if(DEBUGMEM>1) pari_warn(warnmem,"gen_gener"); z = gerepileupto(av, z); } } return gerepileupto(ltop, z); } /* solve x^l = a , l prime in G of order q. * * q = (l^e)*r, e >= 1, (r,l) = 1 * y is not an l-th power, hence generates the l-Sylow of G * m = y^(q/l) != 1 */ static GEN gen_Shanks_sqrtl(GEN a, GEN l, long e, GEN r, GEN y, GEN m,void *E, const struct bb_group *grp) { pari_sp av = avma; long k; GEN p1, u1, u2, v, w, z, dl; (void)bezout(r,l,&u1,&u2); v = grp->pow(E,a,u2); w = grp->pow(E,v,l); w = grp->mul(E,w,grp->pow(E,a,gen_m1)); 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) return gc_NULL(av); dl = gen_plog(z,m,l,E,grp); if (typ(dl) != t_INT) return gc_NULL(av); dl = negi(dl); p1 = grp->pow(E, grp->pow(E,y, dl), powiu(l,e-k-1)); m = grp->pow(E,m,dl); e = k; v = grp->mul(E,p1,v); y = grp->pow(E,p1,l); w = grp->mul(E,y,w); if (gc_needed(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; GEN m, u1, u2, z; int is_1; if (is_pm1(n)) { if (zetan) *zetan = grp->pow(E,a,gen_0); return signe(n) < 0? grp->pow(E,a,gen_m1): gcopy(a); } is_1 = grp->equal1(a); if (is_1 && !zetan) return gcopy(a); m = bezout(n,q,&u1,&u2); z = grp->pow(E,a,gen_0); if (!is_pm1(m)) { GEN F = Z_factor(m); long i, j, e; GEN r, zeta, y, l; pari_sp av1 = avma; for (i = nbrows(F); i; i--) { l = gcoeff(F,i,1); j = itos(gcoeff(F,i,2)); e = Z_pvalrem(q,l,&r); y = gen_lgener(l,e,r,&zeta,E,grp); if (zetan) z = grp->mul(E,z, grp->pow(E,y,powiu(l,e-j))); if (!is_1) { do { a = gen_Shanks_sqrtl(a,l,e,r,y,zeta,E,grp); if (!a) return gc_NULL(ltop); } while (--j); } if (gc_needed(ltop,1)) { /* n can have lots of prime factors*/ if(DEBUGMEM>1) pari_warn(warnmem,"gen_Shanks_sqrtn"); gerepileall(av1, zetan? 2: 1, &a, &z); } } } if (!equalii(m, n)) a = grp->pow(E,a,modii(u1,q)); if (zetan) { *zetan = z; gerepileall(ltop,2,&a,zetan); } else /* is_1 is 0: a was modified above -> gerepileupto valid */ a = gerepileupto(ltop, a); return a; } /*******************************************************************/ /* */ /* structure of groups with pairing */ /* */ /*******************************************************************/ static GEN ellgroup_d2(GEN N, GEN d) { GEN r = gcdii(N, d); GEN F1 = gel(Z_factor(r), 1); long i, j, l1 = lg(F1); GEN F = cgetg(3, t_MAT); gel(F,1) = cgetg(l1, t_COL); gel(F,2) = cgetg(l1, t_COL); for (i = 1, j = 1; i < l1; ++i) { long v = Z_pval(N, gel(F1, i)); if (v<=1) continue; gcoeff(F, j , 1) = gel(F1, i); gcoeff(F, j++, 2) = stoi(v); } setlg(F[1],j); setlg(F[2],j); return j==1 ? NULL : mkvec2(factorback(F), F); } GEN gen_ellgroup(GEN N, GEN d, GEN *pt_m, void *E, const struct bb_group *grp, GEN pairorder(void *E, GEN P, GEN Q, GEN m, GEN F)) { pari_sp av = avma; GEN N0, N1, F; if (pt_m) *pt_m = gen_1; if (is_pm1(N)) return cgetg(1,t_VEC); F = ellgroup_d2(N, d); if (!F) {set_avma(av); return mkveccopy(N);} N0 = gel(F,1); N1 = diviiexact(N, N0); while(1) { pari_sp av2 = avma; GEN P, Q, d, s, t, m; P = grp->pow(E,grp->rand(E), N1); s = gen_order(P, F, E, grp); if (equalii(s, N0)) {set_avma(av); return mkveccopy(N);} Q = grp->pow(E,grp->rand(E), N1); t = gen_order(Q, F, E, grp); if (equalii(t, N0)) {set_avma(av); return mkveccopy(N);} m = lcmii(s, t); d = pairorder(E, P, Q, m, F); /* structure is [N/d, d] iff m d == N0. Note that N/d = N1 m */ if (is_pm1(d) && equalii(m, N0)) {set_avma(av); return mkveccopy(N);} if (equalii(mulii(m, d), N0)) { GEN g = mkvec2(mulii(N1,m), d); if (!pt_m) return gerepilecopy(av, g); *pt_m = m; return gc_all(av, 2, &g, pt_m); } set_avma(av2); } } GEN gen_ellgens(GEN D1, GEN d2, GEN m, void *E, const struct bb_group *grp, GEN pairorder(void *E, GEN P, GEN Q, GEN m, GEN F)) { pari_sp ltop = avma, av; GEN F, d1, dm; GEN P, Q, d, s; F = get_arith_ZZM(D1); d1 = gel(F, 1), dm = diviiexact(d1,m); av = avma; do { set_avma(av); P = grp->rand(E); s = gen_order(P, F, E, grp); } while (!equalii(s, d1)); av = avma; do { set_avma(av); Q = grp->rand(E); d = pairorder(E, grp->pow(E, P, dm), grp->pow(E, Q, dm), m, F); } while (!equalii(d, d2)); return gerepilecopy(ltop, mkvec2(P,Q)); } pari-2.17.2/src/basemath/FpXQX_factor.c0000644000175000017500000024717214760123736016235 0ustar billbill/* Copyright (C) 2016 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_factorff /*******************************************************************/ /** **/ /** Isomorphisms between finite fields **/ /** **/ /*******************************************************************/ static void err_Flxq(const char *s, GEN P, ulong l) { if (!uisprime(l)) pari_err_PRIME(s, utoi(l)); pari_err_IRREDPOL(s, Flx_to_ZX(get_Flx_mod(P))); } static void err_FpXQ(const char *s, GEN P, GEN l) { if (!BPSW_psp(l)) pari_err_PRIME(s, l); pari_err_IRREDPOL(s, get_FpX_mod(P)); } /* compute the reciprocical isomorphism of S mod T,p, i.e. V such that * V(S)=X mod T,p*/ static GEN Flxq_ffisom_inv_pre(GEN S, GEN T, ulong p, ulong pi) { pari_sp ltop = avma; long n = get_Flx_degree(T); GEN M = Flxq_matrix_pow_pre(S,n,n,T,p,pi); GEN V = Flm_Flc_invimage(M, vecsmall_ei(n, 2), p); if (!V) err_Flxq("Flxq_ffisom_inv", T, p); return gerepileupto(ltop, Flv_to_Flx(V, get_Flx_var(T))); } GEN Flxq_ffisom_inv(GEN S, GEN T, ulong p) { return Flxq_ffisom_inv_pre(S, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } GEN FpXQ_ffisom_inv(GEN S,GEN T, GEN p) { pari_sp ltop = avma; long n = get_FpX_degree(T); GEN M = FpXQ_matrix_pow(S,n,n,T,p); GEN V = FpM_FpC_invimage(M, col_ei(n, 2), p); if (!V) err_FpXQ("Flxq_ffisom_inv", T, p); return gerepilecopy(ltop, RgV_to_RgX(V, get_FpX_var(T))); } /* Let M the matrix of the Frobenius automorphism of Fp[X]/(T). Compute M^d * TODO: use left-right binary (tricky!) */ GEN Flm_Frobenius_pow(GEN M, long d, GEN T, ulong p) { pari_sp ltop=avma; long i,l = get_Flx_degree(T); GEN R, W = gel(M,2); for (i = 2; i <= d; ++i) W = Flm_Flc_mul(M,W,p); R=Flxq_matrix_pow(Flv_to_Flx(W,get_Flx_var(T)),l,l,T,p); return gerepileupto(ltop,R); } GEN FpM_Frobenius_pow(GEN M, long d, GEN T, GEN p) { pari_sp ltop=avma; long i,l = get_FpX_degree(T); GEN R, W = gel(M,2); for (i = 2; i <= d; ++i) W = FpM_FpC_mul(M,W,p); R=FpXQ_matrix_pow(RgV_to_RgX(W, get_FpX_var(T)),l,l,T,p); return gerepilecopy(ltop,R); } /* Essentially we want to compute FqM_ker(MA-pol_x(v),U,l) * To avoid use of matrix in Fq we compute FpM_ker(U(MA),l) then recover the * eigenvalue by Galois action */ static GEN Flx_Flm_Flc_eval(GEN U, GEN MA, GEN a, ulong p) { long i, l = lg(U); GEN b = Flv_Fl_mul(a, uel(U, l-1), p); for (i=l-2; i>=2; i--) b = Flv_add(Flm_Flc_mul(MA, b, p), Flv_Fl_mul(a, uel(U, i), p), p); return b; } static GEN Flx_intersect_ker(GEN P, GEN MA, GEN U, ulong p) { pari_sp ltop = avma; long i, vp = get_Flx_var(P), vu = get_Flx_var(U), r = get_Flx_degree(U); GEN V, A, R; ulong ib0; pari_timer T; if (DEBUGLEVEL>=4) timer_start(&T); V = Flx_div(Flx_Fl_add(monomial_Flx(1, get_Flx_degree(P), vu), p-1, p), U, p); do { A = Flx_Flm_Flc_eval(V, MA, random_Flv(lg(MA)-1, p), p); } while (zv_equal0(A)); if (DEBUGLEVEL>=4) timer_printf(&T,"matrix polcyclo"); /*The formula is * a_{r-1} = -\phi(a_0)/b_0 * a_{i-1} = \phi(a_i)+b_ia_{r-1} i=r-1 to 1 * Where a_0=A[1] and b_i=U[i+2] */ ib0 = Fl_inv(Fl_neg(U[2], p), p); R = cgetg(r+1,t_MAT); gel(R,1) = A; gel(R,r) = Flm_Flc_mul(MA, Flv_Fl_mul(A,ib0, p), p); for(i=r-1; i>1; i--) { gel(R,i) = Flm_Flc_mul(MA,gel(R,i+1),p); Flv_add_inplace(gel(R,i), Flv_Fl_mul(gel(R,r), U[i+2], p), p); } return gerepileupto(ltop, Flm_to_FlxX(Flm_transpose(R),vp,vu)); } static GEN FpX_FpM_FpC_eval(GEN U, GEN MA, GEN a, GEN p) { long i, l = lg(U); GEN b = FpC_Fp_mul(a, gel(U, l-1), p); for (i=l-2; i>=2; i--) b = FpC_add(FpM_FpC_mul(MA, b, p), FpC_Fp_mul(a, gel(U, i), p), p); return b; } static GEN FpX_intersect_ker(GEN P, GEN MA, GEN U, GEN l) { pari_sp ltop = avma; long i, vp = get_FpX_var(P), vu = get_FpX_var(U), r = get_FpX_degree(U); GEN V, A, R, ib0; pari_timer T; if (DEBUGLEVEL>=4) timer_start(&T); V = FpX_div(FpX_Fp_sub(pol_xn(get_FpX_degree(P), vu), gen_1, l), U, l); do { A = FpX_FpM_FpC_eval(V, MA, random_FpC(lg(MA)-1, l), l); } while (ZV_equal0(A)); if (DEBUGLEVEL>=4) timer_printf(&T,"matrix polcyclo"); /*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) = A; gel(R,r) = FpM_FpC_mul(MA, FpC_Fp_mul(A,ib0,l), l); for(i=r-1;i>1;i--) gel(R,i) = FpC_add(FpM_FpC_mul(MA,gel(R,i+1),l), FpC_Fp_mul(gel(R,r), gel(U,i+2), l),l); return gerepilecopy(ltop,RgM_to_RgXX(shallowtrans(R),vp,vu)); } /* n must divide both the degree of P and Q. Compute SP and SQ such * that the subfield of FF_l[X]/(P) generated by SP and the subfield of * FF_l[X]/(Q) generated by SQ are isomorphic of degree n. P and Q do * not need to be of the same variable; if MA, resp. MB, is not NULL, must be * the matrix of the Frobenius map in FF_l[X]/(P), resp. FF_l[X]/(Q). * Implementation choice: we assume the prime p is large so we handle * Frobenius as matrices. */ static void Flx_ffintersect_pre(GEN P, GEN Q, long n, ulong l, ulong li, GEN *SP, GEN *SQ, GEN MA, GEN MB) { pari_sp ltop = avma; long vp = get_Flx_var(P), vq = get_Flx_var(Q); long np = get_Flx_degree(P), nq = get_Flx_degree(Q), e; ulong pg; GEN A, B, Ap, Bp; if (np<=0) pari_err_IRREDPOL("FpX_ffintersect", P); if (nq<=0) pari_err_IRREDPOL("FpX_ffintersect", Q); if (n<=0 || np%n || nq%n) pari_err_TYPE("FpX_ffintersect [bad degrees]",stoi(n)); li = SMALL_ULONG(l)? 0: get_Fl_red(l); e = u_lvalrem(n, l, &pg); if(!MA) MA = Flx_matFrobenius_pre(P,l,li); if(!MB) MB = Flx_matFrobenius_pre(Q,l,li); A = Ap = pol0_Flx(vp); B = Bp = pol0_Flx(vq); if (pg > 1) { pari_timer T; GEN ipg = utoipos(pg); if (l%pg == 1) { /* more efficient special case */ ulong L, z, An, Bn; z = Fl_neg(rootsof1_Fl(pg, l), l); if (DEBUGLEVEL>=4) timer_start(&T); A = Flm_ker(Flm_Fl_add(MA, z, l),l); if (lg(A)!=2) err_Flxq("FpX_ffintersect",P,l); A = Flv_to_Flx(gel(A,1),vp); B = Flm_ker(Flm_Fl_add(MB, z, l),l); if (lg(B)!=2) err_Flxq("FpX_ffintersect",Q,l); B = Flv_to_Flx(gel(B,1),vq); if (DEBUGLEVEL>=4) timer_printf(&T, "FpM_ker"); An = Flxq_powu_pre(A,pg,P,l,li)[2]; Bn = Flxq_powu_pre(B,pg,Q,l,li)[2]; if (!Bn) pari_err_IRREDPOL("FpX_ffintersect", mkvec2(P,Q)); z = Fl_div(An,Bn,l); L = Fl_sqrtn(z, pg, l, NULL); if (L==ULONG_MAX) pari_err_IRREDPOL("FpX_ffintersect", mkvec2(P,Q)); if (DEBUGLEVEL>=4) timer_printf(&T, "Fp_sqrtn"); B = Flx_Fl_mul(B,L,l); } else { GEN L, An, Bn, z, U; U = gmael(Flx_factor(ZX_to_Flx(polcyclo(pg, fetch_var()),l),l),1,1); A = Flx_intersect_ker(P, MA, U, l); B = Flx_intersect_ker(Q, MB, U, l); if (DEBUGLEVEL>=4) timer_start(&T); An = gel(FlxYqq_pow(A,ipg,P,U,l),2); Bn = gel(FlxYqq_pow(B,ipg,Q,U,l),2); if (DEBUGLEVEL>=4) timer_printf(&T,"pows [P,Q]"); z = Flxq_div_pre(An,Bn,U,l,li); L = Flxq_sqrtn(z,ipg,U,l,NULL); if (!L) pari_err_IRREDPOL("FpX_ffintersect", mkvec2(P,Q)); if (DEBUGLEVEL>=4) timer_printf(&T,"FpXQ_sqrtn"); B = FlxqX_Flxq_mul_pre(B,L,U,l,li); A = FlxY_evalx_pre(A,0,l,li); B = FlxY_evalx_pre(B,0,l,li); (void)delete_var(); } } if (e) { GEN VP, VQ, Ay, By; ulong lmun = l-1; long j; MA = Flm_Fl_add(MA,lmun,l); MB = Flm_Fl_add(MB,lmun,l); Ay = pol1_Flx(vp); By = pol1_Flx(vq); VP = vecsmall_ei(np, 1); VQ = np == nq? VP: vecsmall_ei(nq, 1); /* save memory */ for(j=0;j 1) { GEN ipg = utoipos(pg); pari_timer T; if (umodiu(l,pg) == 1) /* No need to use relative extension, so don't. (Well, now we don't * in the other case either, but this special case is more efficient) */ { GEN L, An, Bn, z; z = negi( rootsof1u_Fp(pg, l) ); if (DEBUGLEVEL>=4) timer_start(&T); A = FpM_ker(RgM_Rg_add_shallow(MA, z),l); if (lg(A)!=2) err_FpXQ("FpX_ffintersect",P,l); A = RgV_to_RgX(gel(A,1),vp); B = FpM_ker(RgM_Rg_add_shallow(MB, z),l); if (lg(B)!=2) err_FpXQ("FpX_ffintersect",Q,l); B = RgV_to_RgX(gel(B,1),vq); if (DEBUGLEVEL>=4) timer_printf(&T, "FpM_ker"); An = gel(FpXQ_pow(A,ipg,P,l),2); Bn = gel(FpXQ_pow(B,ipg,Q,l),2); if (!signe(Bn)) pari_err_IRREDPOL("FpX_ffintersect", mkvec2(P,Q)); z = Fp_div(An,Bn,l); L = Fp_sqrtn(z,ipg,l,NULL); if (!L) pari_err_IRREDPOL("FpX_ffintersect", mkvec2(P,Q)); if (DEBUGLEVEL>=4) timer_printf(&T, "Fp_sqrtn"); B = FpX_Fp_mul(B,L,l); } else { GEN L, An, Bn, z, U; U = gmael(FpX_factor(polcyclo(pg,fetch_var()),l),1,1); A = FpX_intersect_ker(P, MA, U, l); B = FpX_intersect_ker(Q, MB, U, l); if (DEBUGLEVEL>=4) timer_start(&T); An = gel(FpXYQQ_pow(A,ipg,P,U,l),2); Bn = gel(FpXYQQ_pow(B,ipg,Q,U,l),2); if (DEBUGLEVEL>=4) timer_printf(&T,"pows [P,Q]"); if (!signe(Bn)) pari_err_IRREDPOL("FpX_ffintersect", mkvec2(P,Q)); z = Fq_div(An,Bn,U,l); L = Fq_sqrtn(z,ipg,U,l,NULL); if (!L) pari_err_IRREDPOL("FpX_ffintersect", mkvec2(P,Q)); if (DEBUGLEVEL>=4) timer_printf(&T,"FpXQ_sqrtn"); B = FqX_Fq_mul(B,L,U,l); A = FpXY_evalx(A,gen_0,l); B = FpXY_evalx(B,gen_0,l); (void)delete_var(); } } if (e) { GEN VP, VQ, Ay, By, lmun = subiu(l,1); long j; MA = RgM_Rg_add_shallow(MA,gen_m1); MB = RgM_Rg_add_shallow(MB,gen_m1); Ay = pol_1(vp); By = pol_1(vq); VP = col_ei(np, 1); VQ = np == nq? VP: col_ei(nq, 1); /* save memory */ for(j=0;j>1, S, T, p, pi); GEN V = FlxqXQ_autsum_pre(mkvec3(xp, Xp, ap2), get_Flx_degree(T), S, T, p,pi); return gel(V,3); } GEN FlxqXQ_halfFrobenius(GEN a, GEN S, GEN T, ulong p) { ulong pi = SMALL_ULONG(p)? 0: get_Fl_red(p); long vT = get_Flx_var(T); GEN xp, Xp; T = Flx_get_red_pre(T, p, pi); S = FlxqX_get_red_pre(S, T, p, pi); xp = Flx_Frobenius_pre(T, p, pi); Xp = FlxqXQ_powu_pre(polx_FlxX(get_FlxqX_var(S), vT), p, S, T, p, pi); return FlxqXQ_halfFrobenius_i(a, xp, Xp, S, T, p, pi); } static GEN FpXQXQ_halfFrobenius_i(GEN a, GEN xp, GEN Xp, GEN S, GEN T, GEN p) { GEN ap2 = FpXQXQ_pow(a, shifti(p,-1), S, T, p); GEN V = FpXQXQ_autsum(mkvec3(xp, Xp, ap2), get_FpX_degree(T), S, T, p); return gel(V, 3); } GEN FpXQXQ_halfFrobenius(GEN a, GEN S, GEN T, GEN p) { pari_sp av = avma; GEN z; if (lgefint(p)==3) { ulong pp = p[2]; long v = get_FpX_var(T); GEN Tp = ZXT_to_FlxT(T,pp), Sp = ZXXT_to_FlxXT(S, pp, v); z = FlxX_to_ZXX(FlxqXQ_halfFrobenius(ZXX_to_FlxX(a,pp,v),Sp,Tp,pp)); } else { GEN xp, Xp; T = FpX_get_red(T, p); S = FpXQX_get_red(S, T, p); xp = FpX_Frobenius(T, p); Xp = FpXQXQ_pow(pol_x(get_FpXQX_var(S)), p, S, T, p); z = FpXQXQ_halfFrobenius_i(a, xp, Xp, S, T, p); } return gerepilecopy(av, z); } static GEN FlxqXQ_Frobenius(GEN xp, GEN Xp, GEN f, GEN T, ulong p, ulong pi) { ulong dT = get_Flx_degree(T), df = get_FlxqX_degree(f); GEN q = powuu(p,dT); if (expi(q) >= expu(dT)*(long)usqrt(df)) return gel(FlxqXQ_autpow_pre(mkvec2(xp, Xp), dT, f, T, p, pi), 2); else return FlxqXQ_pow_pre(pol_x(get_FlxqX_var(f)), q, f, T, p, pi); } GEN FlxqX_Frobenius_pre(GEN S, GEN T, ulong p, ulong pi) { pari_sp av = avma; GEN X = polx_FlxX(get_FlxqX_var(S), get_Flx_var(T)); GEN xp = Flx_Frobenius_pre(T, p, pi); GEN Xp = FlxqXQ_powu_pre(X, p, S, T, p, pi); GEN Xq = FlxqXQ_Frobenius(xp, Xp, S, T, p, pi); return gerepilecopy(av, Xq); } GEN FlxqX_Frobenius(GEN S, GEN T, ulong p) { return FlxqX_Frobenius_pre(S, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } static GEN FpXQXQ_Frobenius(GEN xp, GEN Xp, GEN f, GEN T, GEN p) { ulong dT = get_FpX_degree(T), df = get_FpXQX_degree(f); GEN q = powiu(p, dT); if (expi(q) >= expu(dT)*(long)usqrt(df)) return gel(FpXQXQ_autpow(mkvec2(xp, Xp), dT, f, T, p), 2); else return FpXQXQ_pow(pol_x(get_FpXQX_var(f)), q, f, T, p); } GEN FpXQX_Frobenius(GEN S, GEN T, GEN p) { pari_sp av = avma; GEN X = pol_x(get_FpXQX_var(S)); GEN xp = FpX_Frobenius(T, p); GEN Xp = FpXQXQ_pow(X, p, S, T, p); GEN Xq = FpXQXQ_Frobenius(xp, Xp, S, T, p); return gerepilecopy(av, Xq); } static GEN F2xqXQ_Frobenius(GEN xp, GEN Xp, GEN f, GEN T) { ulong dT = get_F2x_degree(T), df = get_F2xqX_degree(f); if (dT >= expu(dT)*usqrt(df)) return gel(F2xqXQ_autpow(mkvec2(xp, Xp), dT, f, T), 2); else { long v = get_F2xqX_var(f), vT = get_F2x_var(T); return F2xqXQ_pow(polx_F2xX(v,vT), int2n(dT), f, T); } } static GEN FlxqX_split_part(GEN f, GEN T, ulong p) { long n = degpol(f); GEN z, Xq, X; ulong pi; if (n <= 1) return f; pi = SMALL_ULONG(p)? 0: get_Fl_red(p); X = polx_FlxX(varn(f),get_Flx_var(T)); f = FlxqX_red_pre(f, T, p, pi); Xq = FlxqX_Frobenius_pre(f, T, p, pi); z = FlxX_sub(Xq, X , p); return FlxqX_gcd_pre(z, f, T, p, pi); } GEN FpXQX_split_part(GEN f, GEN T, GEN p) { if(lgefint(p)==3) { ulong pp=p[2]; GEN Tp = ZXT_to_FlxT(T, pp); GEN z = FlxqX_split_part(ZXX_to_FlxX(f, pp, get_FpX_var(T)), Tp, pp); return FlxX_to_ZXX(z); } else { long n = degpol(f); GEN z, X = pol_x(varn(f)); if (n <= 1) return f; f = FpXQX_red(f, T, p); z = FpXQX_Frobenius(f, T, p); z = FpXX_sub(z, X , p); return FpXQX_gcd(z, f, T, p); } } long FpXQX_nbroots(GEN f, GEN T, GEN p) { pari_sp av = avma; GEN z = FpXQX_split_part(f, T, p); return gc_long(av, degpol(z)); } long FqX_nbroots(GEN f, GEN T, GEN p) { return T ? FpXQX_nbroots(f, T, p): FpX_nbroots(f, p); } long FlxqX_nbroots(GEN f, GEN T, ulong p) { pari_sp av = avma; GEN z = FlxqX_split_part(f, T, p); return gc_long(av, degpol(z)); } static GEN FlxqX_Berlekamp_ker_i(GEN Xq, GEN S, GEN T, ulong p) { long j, N = get_FlxqX_degree(S); GEN Q = FlxqXQ_matrix_pow(Xq,N,N,S,T,p); for (j=1; j<=N; j++) gcoeff(Q,j,j) = Flx_Fl_add(gcoeff(Q,j,j), p-1, p); return FlxqM_ker(Q,T,p); } static GEN FpXQX_Berlekamp_ker_i(GEN Xq, GEN S, GEN T, GEN p) { long j,N = get_FpXQX_degree(S); GEN Q = FpXQXQ_matrix_pow(Xq,N,N,S,T,p); for (j=1; j<=N; j++) gcoeff(Q,j,j) = Fq_sub(gcoeff(Q,j,j), gen_1, T, p); return FqM_ker(Q,T,p); } static long isabsolutepol(GEN f) { long i, l = lg(f); for(i=2; i 0) return 0; } return 1; } #define set_irred(i) { if ((i)>ir) swap(t[i],t[ir]); ir++;} static long FlxqX_split_Berlekamp(GEN *t, GEN xp, GEN T, ulong p, ulong pi) { GEN u = *t, a,b,vker,pol; long vu = varn(u), vT = get_Flx_var(T), dT = get_Flx_degree(T); long d, i, ir, L, la, lb; GEN S, X, Xp, Xq; if (degpol(u)==1) return 1; T = Flx_get_red_pre(T, p, pi); S = FlxqX_get_red_pre(u, T, p, pi); X = polx_FlxX(get_FlxqX_var(S),get_Flx_var(T)); Xp = FlxqXQ_powu_pre(X, p, S, T, p, pi); Xq = FlxqXQ_Frobenius(xp, Xp, S, T, p, pi); vker = FlxqX_Berlekamp_ker_i(Xq, S, T, p); vker = Flm_to_FlxV(vker,u[1]); d = lg(vker)-1; ir = 0; /* t[i] irreducible for i < ir, still to be treated for i < L */ for (L=1; L2 and x monic */ static GEN FlxqX_quad_roots(GEN x, GEN T, ulong p, ulong pi) { GEN s, D, nb, b = gel(x,3), c = gel(x,2); D = Flx_sub(Flxq_sqr_pre(b,T,p,pi), Flx_mulu(c,4,p), p); nb = Flx_neg(b,p); if (lgpol(D)==0) return mkcol(Flx_halve(nb, p)); s = Flxq_sqrt(D,T,p); if (!s) return cgetg(1, t_COL); s = Flx_halve(Flx_add(s,nb,p),p); return mkcol2(s, Flx_sub(nb,s,p)); } static GEN FpXQX_quad_roots(GEN x, GEN T, GEN p) { GEN s, D, nb, b = gel(x,3), c = gel(x,2); if (absequaliu(p, 2)) { GEN f2 = ZXX_to_F2xX(x, get_FpX_var(T)); s = F2xqX_quad_roots(f2, ZX_to_F2x(get_FpX_mod(T))); return F2xC_to_ZXC(s); } D = Fq_sub(Fq_sqr(b,T,p), Fq_Fp_mul(c,utoi(4),T,p), T,p); nb = Fq_neg(b,T,p); if (signe(D)==0) return mkcol(Fq_to_FpXQ(Fq_halve(nb,T, p),T,p)); s = Fq_sqrt(D,T,p); if (!s) return cgetg(1, t_COL); s = Fq_halve(Fq_add(s,nb,T,p),T, p); return mkcol2(Fq_to_FpXQ(s,T,p), Fq_to_FpXQ(Fq_sub(nb,s,T,p),T,p)); } static GEN F2xqX_Frobenius_deflate(GEN S, GEN T) { GEN F = RgX_deflate(S, 2); long i, l = lg(F); for (i=2; i 0) { long j; for(j = 1;;j++) { v = F2xqX_gcd(r, t, T); tv = F2xqX_div(t, v, T); if (degpol(tv) > 0) gel(u, j*q) = F2xqX_normalize(tv, T); if (degpol(v) <= 0) break; r = F2xqX_div(r, v, T); t = v; } if (degpol(r) == 0) break; } f = F2xqX_Frobenius_deflate(r, T); } for (i = n; i; i--) if (degpol(gel(u,i))) break; setlg(u,i+1); return gerepilecopy(av, u); } long F2xqX_ispower(GEN f, long k, GEN T, GEN *pt_r) { pari_sp av = avma; GEN lc, F; long i, l, n = degpol(f); if (n % k) return 0; lc = F2xq_sqrtn(leading_coeff(f), stoi(k), T, NULL); if (!lc) return gc_long(av,0); F = F2xqX_factor_squarefree(f, T); l = lg(F)-1; for(i=1; i<=l; i++) if (i%k && degpol(gel(F,i))) return gc_long(av,0); if (pt_r) { long v = varn(f); GEN r = scalarpol(lc, v), s = pol1_F2xX(v, T[1]); for(i=l; i>=1; i--) { if (i%k) continue; s = F2xqX_mul(s, gel(F,i), T); r = F2xqX_mul(r, s, T); } *pt_r = gerepileupto(av, r); } else set_avma(av); return 1; } static void F2xqX_roots_edf(GEN Sp, GEN xp, GEN Xp, GEN T, GEN V, long idx) { pari_sp btop; long n = degpol(Sp); GEN S, f, ff; long dT = get_F2x_degree(T); GEN R = F2xqX_easyroots(Sp, T); if (R) { long i, l = lg(R)-1; for (i=0; i 0 && degpol(f) < n) break; set_avma(btop); } f = gerepileupto(btop, F2xqX_normalize(f, T)); ff = F2xqX_div(Sp, f, T); F2xqX_roots_edf(f, xp, Xp, T, V, idx); F2xqX_roots_edf(ff,xp, Xp, T, V, idx+degpol(f)); } static GEN F2xqX_roots_ddf(GEN f, GEN xp, GEN T) { GEN X, Xp, Xq, g, V; long n; GEN R = F2xqX_easyroots(f, T); if (R) return R; X = pol_x(varn(f)); Xp = F2xqXQ_sqr(X, f, T); Xq = F2xqXQ_Frobenius(xp, Xp, f, T); g = F2xqX_gcd(F2xX_add(Xq, X), f, T); n = degpol(g); if (n==0) return cgetg(1, t_COL); g = F2xqX_normalize(g, T); V = cgetg(n+1,t_COL); F2xqX_roots_edf(g, xp, Xp, T, V, 1); return V; } static GEN F2xqX_roots_i(GEN S, GEN T) { GEN M; S = F2xqX_red(S, T); if (!signe(S)) pari_err_ROOTS0("F2xqX_roots"); if (degpol(S)==0) return cgetg(1, t_COL); S = F2xqX_normalize(S, T); M = F2xqX_easyroots(S, T); if (!M) { GEN xp = F2x_Frobenius(T); GEN F, V = F2xqX_factor_squarefree(S, T); long i, j, l = lg(V); F = cgetg(l, t_VEC); for (i=1, j=1; i < l; i++) if (degpol(gel(V,i))) gel(F, j++) = F2xqX_roots_ddf(gel(V,i), xp, T); setlg(F,j); M = shallowconcat1(F); } gen_sort_inplace(M, (void*) &cmp_Flx, &cmp_nodata, NULL); return M; } static GEN FlxqX_easyroots(GEN f, GEN T, ulong p, ulong pi) { if (FlxY_degreex(f) <= 0) return Flx_rootsff_i(FlxX_to_Flx(f), T, p); if (degpol(f)==1) return mkcol(Flx_neg(constant_coeff(f), p)); if (degpol(f)==2) return FlxqX_quad_roots(f,T,p,pi); return NULL; } static GEN FlxqX_invFrobenius(GEN xp, GEN T, ulong p, ulong pi) { return Flxq_autpow_pre(xp, get_Flx_degree(T)-1, T, p, pi); } static GEN FlxqX_Frobenius_deflate(GEN S, GEN ixp, GEN T, ulong p) { GEN F = RgX_deflate(S, p); long i, l = lg(F); if (typ(ixp)==t_INT) for (i=2; i 0) { long j; for(j = 1;;j++) { v = FlxqX_gcd_pre(r, t, T, p, pi); tv = FlxqX_div_pre(t, v, T, p, pi); if (degpol(tv) > 0) gel(u, j*q) = FlxqX_normalize_pre(tv, T, p, pi); if (degpol(v) <= 0) break; r = FlxqX_div_pre(r, v, T, p, pi); t = v; } if (degpol(r) == 0) break; } if (!xp) xp = Flx_Frobenius_pre(T, p, pi); if (!ixp) ixp = FlxqX_invFrobenius(xp, T, p, pi); f = FlxqX_Frobenius_deflate(r, ixp, T, p); } for (i = n; i; i--) if (degpol(gel(u,i))) break; setlg(u,i+1); return gerepilecopy(av, u); } GEN FlxqX_factor_squarefree_pre(GEN f, GEN T, ulong p, ulong pi) { return FlxqX_factor_squarefree_i(f, NULL, T, p, pi); } GEN FlxqX_factor_squarefree(GEN f, GEN T, ulong p) { return FlxqX_factor_squarefree_pre(f,T,p, SMALL_ULONG(p)? 0: get_Fl_red(p)); } long FlxqX_ispower(GEN f, ulong k, GEN T, ulong p, GEN *pt_r) { pari_sp av = avma; GEN lc, F; long i, l, n = degpol(f), v = varn(f); ulong pi; if (n % k) return 0; lc = Flxq_sqrtn(leading_coeff(f), stoi(k), T, p, NULL); if (!lc) return gc_long(av,0); pi = SMALL_ULONG(p)? 0: get_Fl_red(p); F = FlxqX_factor_squarefree_i(f, NULL, T, p, pi); l = lg(F)-1; for(i=1; i<=l; i++) if (i%k && degpol(gel(F,i))) return gc_long(av,0); if (pt_r) { GEN r = scalarpol(lc, v), s = pol1_FlxX(v, T[1]); for(i=l; i>=1; i--) { if (i%k) continue; s = FlxqX_mul_pre(s, gel(F,i), T, p, pi); r = FlxqX_mul_pre(r, s, T, p, pi); } *pt_r = gerepileupto(av, r); } else set_avma(av); return 1; } static GEN FlxqX_roots_split(GEN Sp, GEN xp, GEN Xp, GEN S, GEN T, ulong p, long pi) { pari_sp btop = avma; long n = degpol(Sp); GEN f; long vT = get_Flx_var(T), dT = get_Flx_degree(T); pari_timer ti; if (DEBUGLEVEL >= 7) timer_start(&ti); while (1) { GEN a = deg1pol(pol1_Flx(vT), random_Flx(dT, vT, p), varn(Sp)); GEN R = FlxqXQ_halfFrobenius_i(a, xp, Xp, S, T, p, pi); if (DEBUGLEVEL >= 7) timer_printf(&ti, "FlxqXQ_halfFrobenius"); f = FlxqX_gcd_pre(FlxX_Flx_sub(R, pol1_Flx(vT), p), Sp, T, p, pi); if (degpol(f) > 0 && degpol(f) < n) break; set_avma(btop); } return gerepileupto(btop, FlxqX_normalize_pre(f, T, p, pi)); } static void FlxqX_roots_edf(GEN Sp, GEN xp, GEN Xp, GEN T, ulong p, ulong pi, GEN V, long idx) { GEN S, f, ff; GEN R = FlxqX_easyroots(Sp, T, p, pi); if (R) { long i, l = lg(R)-1; for (i=0; i 0) gel(u, j) = FpXQX_normalize(tv, T, p); if (degpol(v) <= 0) break; r = FpXQX_div(r, v, T, p); t = v; } setlg(u, j+1); return gerepilecopy(av, u); } GEN FpXQX_factor_squarefree(GEN f, GEN T, GEN p) { if (lgefint(p)==3) { pari_sp av = avma; ulong pp = p[2]; GEN M; long vT = get_FpX_var(T); if (pp==2) { M = F2xqX_factor_squarefree(ZXX_to_F2xX(f, vT), ZX_to_F2x(get_FpX_mod(T))); return gerepileupto(av, F2xXC_to_ZXXC(M)); } M = FlxqX_factor_squarefree(ZXX_to_FlxX(f, pp, vT), ZXT_to_FlxT(T, pp), pp); return gerepileupto(av, FlxXC_to_ZXXC(M)); } return FpXQX_factor_Yun(f, T, p); } GEN FpXQX_roots_mult(GEN f, long n, GEN T, GEN p) { pari_sp av = avma; GEN V = FpXQX_factor_squarefree(f, T, p), W; long l = lg(V), i; if (l <= n) return cgetg(1,t_COL); W = cgetg(l-n+1,t_VEC); for (i = n; i < l; i++) gel(W,i-n+1) = FpXQX_roots(gel(V,i), T, p); W = shallowconcat1(W); gen_sort_inplace(W, (void*) &cmp_RgX, &cmp_nodata, NULL); return gerepilecopy(av, W); } long FpXQX_ispower(GEN f, ulong k, GEN T, GEN p, GEN *pt_r) { pari_sp av = avma; GEN lc, F; long i, l, n = degpol(f), v = varn(f); if (n % k) return 0; if (lgefint(p)==3) { ulong pp = p[2]; GEN fp = ZXX_to_FlxX(f, pp, varn(T)); if (!FlxqX_ispower(fp, k, ZX_to_Flx(T,pp), pp, pt_r)) return gc_long(av,0); if (pt_r) *pt_r = gerepileupto(av, FlxX_to_ZXX(*pt_r)); else set_avma(av); return 1; } lc = FpXQ_sqrtn(leading_coeff(f), stoi(k), T, p, NULL); if (!lc) return gc_long(av,0); F = FpXQX_factor_Yun(f, T, p); l = lg(F)-1; for(i=1; i <= l; i++) if (i%k && degpol(gel(F,i))) return gc_long(av,0); if (pt_r) { GEN r = scalarpol(lc, v), s = pol_1(v); for(i=l; i>=1; i--) { if (i%k) continue; s = FpXQX_mul(s, gel(F,i), T, p); r = FpXQX_mul(r, s, T, p); } *pt_r = gerepileupto(av, r); } else set_avma(av); return 1; } long FqX_ispower(GEN f, ulong k, GEN T, GEN p, GEN *pt_r) { return T ? FpXQX_ispower(f, k, T, p, pt_r): FpX_ispower(f, k, p, pt_r); } static GEN FpXQX_roots_split(GEN Sp, GEN xp, GEN Xp, GEN S, GEN T, GEN p) { pari_sp btop = avma; long n = degpol(Sp); GEN f; long vT = get_FpX_var(T), dT = get_FpX_degree(T); pari_timer ti; if (DEBUGLEVEL >= 7) timer_start(&ti); while (1) { GEN a = deg1pol(pol_1(vT), random_FpX(dT, vT, p), varn(Sp)); GEN R = FpXQXQ_halfFrobenius_i(a, xp, Xp, S, T, p); if (DEBUGLEVEL >= 7) timer_printf(&ti, "FpXQXQ_halfFrobenius"); f = FpXQX_gcd(FqX_Fq_sub(R, pol_1(vT), T, p), Sp, T, p); if (degpol(f) > 0 && degpol(f) < n) break; set_avma(btop); } return gerepileupto(btop, FpXQX_normalize(f, T, p)); } static void FpXQX_roots_edf(GEN Sp, GEN xp, GEN Xp, GEN T, GEN p, GEN V, long idx) { GEN S, f, ff; GEN R = FpXQX_easyroots(Sp, T, p); if (R) { long i, l = lg(R)-1; for (i=0; i=7) timer_start(&ti); if (dT <= ro) for (i = 3; i <= l+1; i++) gel(b, i) = F2xqXQ_pow(gel(b, i-1), int2n(dT), S, T); else { xq = F2xqXQ_powers(gel(b, 2), bo, S, T); if (DEBUGLEVEL>=7) timer_printf(&ti,"F2xqX_ddf_Shoup: xq baby"); for (i = 3; i <= l+1; i++) gel(b, i) = F2xqX_F2xqXQV_eval(gel(b, i-1), xq, S, T); } if (DEBUGLEVEL>=7) timer_printf(&ti,"F2xqX_ddf_Shoup: baby"); xq = F2xqXQ_powers(gel(b, l+1), brent_kung_optpow(n, m-1, 1), S, T); if (DEBUGLEVEL>=7) timer_printf(&ti,"F2xqX_ddf_Shoup: xq giant"); g = cgetg(m+1, t_VEC); gel(g, 1) = gel(xq, 2); for(i = 2; i <= m; i++) gel(g, i) = F2xqX_F2xqXQV_eval(gel(g, i-1), xq, S, T); if (DEBUGLEVEL>=7) timer_printf(&ti,"F2xqX_ddf_Shoup: giant"); h = cgetg(m+1, t_VEC); for (j = 1; j <= m; j++) { pari_sp av = avma; GEN gj = gel(g, j); GEN e = F2xX_add(gj, gel(b, 1)); for (i = 2; i <= l; i++) e = F2xqXQ_mul(e, F2xX_add(gj, gel(b, i)), S, T); gel(h, j) = gerepileupto(av, e); } if (DEBUGLEVEL>=7) timer_printf(&ti,"F2xqX_ddf_Shoup: diff"); Sr = get_F2xqX_mod(S); F = cgetg(m+1, t_VEC); for (j = 1; j <= m; j++) { GEN u = F2xqX_gcd(Sr, gel(h,j), T); if (degpol(u)) { u = F2xqX_normalize(u, T); Sr = F2xqX_div(Sr, u, T); } gel(F,j) = u; } if (DEBUGLEVEL>=7) timer_printf(&ti,"F2xqX_ddf_Shoup: F"); f = const_vec(n, pol1_F2xX(v, vT)); for (j = 1; j <= m; j++) { GEN e = gel(F, j); for (i=l-1; i >= 0; i--) { GEN u = F2xqX_gcd(e, F2xX_add(gel(g, j), gel(b, i+1)), T); if (degpol(u)) { gel(f, l*j-i) = u = F2xqX_normalize(u, T); e = F2xqX_div(e, u, T); } if (!degpol(e)) break; } } if (DEBUGLEVEL>=7) timer_printf(&ti,"F2xqX_ddf_Shoup: f"); if (degpol(Sr)) gel(f, degpol(Sr)) = Sr; return gerepilecopy(av, f); } static GEN F2xqX_ddf_i(GEN f, GEN T, GEN X, GEN xp) { GEN Xp, Xq; if (!get_F2xqX_degree(f)) return cgetg(1,t_VEC); f = F2xqX_get_red(f, T); Xp = F2xqXQ_sqr(X, f, T); Xq = F2xqXQ_Frobenius(xp, Xp, f, T); return F2xqX_ddf_Shoup(f, Xq, T); } static void F2xqX_ddf_init(GEN *S, GEN *T, GEN *xp, GEN *X) { *T = F2x_get_red(*T); *S = F2xqX_normalize(get_F2xqX_mod(*S), *T); *xp = F2x_Frobenius(*T); *X = polx_F2xX(get_F2xqX_var(*S), get_F2x_var(*T)); } GEN F2xqX_degfact(GEN S, GEN T) { GEN xp, X, V; long i, l; F2xqX_ddf_init(&S,&T,&xp,&X); V = F2xqX_factor_squarefree(S, T); l = lg(V); for (i=1; i < l; i++) gel(V,i) = F2xqX_ddf_i(gel(V,i), T, X, xp); return vddf_to_simplefact(V, degpol(S)); } GEN F2xqX_ddf(GEN S, GEN T) { GEN xp, X; F2xqX_ddf_init(&S,&T,&xp,&X); return ddf_to_ddf2( F2xqX_ddf_i(S, T, X, xp) ); } static void F2xqX_edf_simple(GEN Sp, GEN xp, GEN Xp, GEN Sq, long d, GEN T, GEN V, long idx) { long v = varn(Sp), n = degpol(Sp), r = n/d; GEN S, f, ff; long dT = get_F2x_degree(T); if (r==1) { gel(V, idx) = Sp; return; } S = F2xqX_get_red(Sp, T); Xp = F2xqX_rem(Xp, S, T); Sq = F2xqXQV_red(Sq, S, T); while (1) { pari_sp btop = avma; long l; GEN w0 = random_F2xqX(n, v, T), g = w0; for (l=1; l 0 && degpol(f) < n) break; set_avma(btop); } f = F2xqX_normalize(f, T); ff = F2xqX_div(Sp, f , T); F2xqX_edf_simple(f, xp, Xp, Sq, d, T, V, idx); F2xqX_edf_simple(ff, xp, Xp, Sq, d, T, V, idx+degpol(f)/d); } static GEN F2xqX_factor_Shoup(GEN S, GEN xp, GEN T) { long i, n, s = 0; GEN X, Xp, Xq, Sq, D, V; long vT = get_F2x_var(T); pari_timer ti; n = get_F2xqX_degree(S); S = F2xqX_get_red(S, T); if (DEBUGLEVEL>=6) timer_start(&ti); X = polx_F2xX(get_F2xqX_var(S), vT); Xp = F2xqXQ_sqr(X, S, T); Xq = F2xqXQ_Frobenius(xp, Xp, S, T); Sq = F2xqXQ_powers(Xq, n-1, S, T); if (DEBUGLEVEL>=6) timer_printf(&ti,"F2xqX_Frobenius"); D = F2xqX_ddf_Shoup(S, Xq, T); if (DEBUGLEVEL>=6) timer_printf(&ti,"F2xqX_ddf_Shoup"); s = ddf_to_nbfact(D); V = cgetg(s+1, t_COL); for (i = 1, s = 1; i <= n; i++) { GEN Di = gel(D,i); long ni = degpol(Di), ri = ni/i; if (ni == 0) continue; Di = F2xqX_normalize(Di, T); if (ni == i) { gel(V, s++) = Di; continue; } F2xqX_edf_simple(Di, xp, Xp, Sq, i, T, V, s); if (DEBUGLEVEL>=6) timer_printf(&ti,"F2xqX_edf(%ld)",i); s += ri; } return V; } static GEN F2xqX_factor_Cantor(GEN f, GEN T) { GEN xp, E, F, V; long i, j, l; T = F2x_get_red(T); f = F2xqX_normalize(f, T); switch(degpol(f)) { case -1: retmkmat2(mkcol(f), mkvecsmall(1)); case 0: return trivial_fact(); case 1: retmkmat2(mkcol(f), mkvecsmall(1)); case 2: return F2xqX_factor_2(f, T); } if (F2xY_degreex(f) <= 0) return F2x_factorff_i(F2xX_to_F2x(f), T); xp = F2x_Frobenius(T); V = F2xqX_factor_squarefree(f, T); l = lg(V); F = cgetg(l, t_VEC); E = cgetg(l, t_VEC); for (i=1, j=1; i < l; i++) if (degpol(gel(V,i))) { GEN Fj = F2xqX_factor_Shoup(gel(V,i), xp, T); gel(F, j) = Fj; gel(E, j) = const_vecsmall(lg(Fj)-1, i); j++; } return sort_factor_pol(FE_concat(F,E,j), cmp_Flx); } static GEN FlxqX_Berlekamp_i(GEN f, GEN T, ulong p) { long lfact, d = degpol(f), j, k, lV; GEN E, t, V, xp; ulong pi; switch(d) { case -1: retmkmat2(mkcolcopy(f), mkvecsmall(1)); case 0: return trivial_fact(); } pi = SMALL_ULONG(p)? 0: get_Fl_red(p); T = Flx_get_red_pre(T, p, pi); f = FlxqX_normalize_pre(f, T, p, pi); if (FlxY_degreex(f) <= 0) return Flx_factorff_i(FlxX_to_Flx(f), T, p); if (degpol(f)==2) return FlxqX_factor_2(f, T, p, pi); xp = Flx_Frobenius_pre(T, p, pi); V = FlxqX_factor_squarefree_i(f, xp, T, p, pi); lV = lg(V); /* to hold factors and exponents */ t = cgetg(d+1,t_VEC); E = cgetg(d+1, t_VECSMALL); lfact = 1; for (k=1; k=7) timer_start(&ti); b = XP; if (expi(q) > ro) { xq = FlxqXQ_powers_pre(b, brent_kung_optpow(n, l-1, 1), S, T, p, pi); if (DEBUGLEVEL>=7) timer_printf(&ti,"FlxqX_ddf_degree: xq baby"); } else xq = NULL; for (i = 3; i <= l+1; i++) { b = xq ? FlxqX_FlxqXQV_eval_pre(b, xq, S, T, p, pi) : FlxqXQ_pow_pre(b, q, S, T, p, pi); if (gequal(b,X)) return gc_long(av,i-1); hash_insert_long(&h, b, i-1); } if (DEBUGLEVEL>=7) timer_printf(&ti,"FlxqX_ddf_degree: baby"); g = b; xq = FlxqXQ_powers_pre(g, brent_kung_optpow(n, m, 1), S, T, p, pi); if (DEBUGLEVEL>=7) timer_printf(&ti,"FlxqX_ddf_degree: xq giant"); for(i = 2; i <= m+1; i++) { g = FlxqX_FlxqXQV_eval_pre(g, xq, S, T, p, pi); if (hash_haskey_long(&h, g, &j)) return gc_long(av, l*i-j); } return gc_long(av,n); } static GEN FlxqX_ddf_Shoup(GEN S, GEN Xq, GEN T, ulong p, ulong pi) { pari_sp av = avma; GEN b, g, h, F, f, Sr, xq, q; long i, j, n, v, vT, bo, ro; long B, l, m; pari_timer ti; n = get_FlxqX_degree(S); v = get_FlxqX_var(S); vT = get_Flx_var(T); if (n == 0) return cgetg(1, t_VEC); if (n == 1) return mkvec(get_FlxqX_mod(S)); B = n/2; l = usqrt(B); m = (B+l-1)/l; S = FlxqX_get_red_pre(S, T, p, pi); b = cgetg(l+2, t_VEC); gel(b, 1) = polx_FlxX(v, vT); gel(b, 2) = Xq; bo = brent_kung_optpow(n, l-1, 1); ro = l<=1 ? 0: (bo-1)/(l-1) + ((n-1)/bo); q = powuu(p, get_Flx_degree(T)); if (DEBUGLEVEL>=7) timer_start(&ti); if (expi(q) <= ro) for (i = 3; i <= l+1; i++) gel(b, i) = FlxqXQ_pow_pre(gel(b, i-1), q, S, T, p, pi); else { xq = FlxqXQ_powers_pre(gel(b, 2), bo, S, T, p, pi); if (DEBUGLEVEL>=7) timer_printf(&ti,"FlxqX_ddf_Shoup: xq baby"); for (i = 3; i <= l+1; i++) gel(b, i) = FlxqX_FlxqXQV_eval_pre(gel(b, i-1), xq, S, T, p, pi); } if (DEBUGLEVEL>=7) timer_printf(&ti,"FlxqX_ddf_Shoup: baby"); xq = FlxqXQ_powers_pre(gel(b, l+1), brent_kung_optpow(n, m-1, 1), S, T,p,pi); if (DEBUGLEVEL>=7) timer_printf(&ti,"FlxqX_ddf_Shoup: xq giant"); g = cgetg(m+1, t_VEC); gel(g, 1) = gel(xq, 2); for(i = 2; i <= m; i++) gel(g, i) = FlxqX_FlxqXQV_eval_pre(gel(g, i-1), xq, S, T, p, pi); if (DEBUGLEVEL>=7) timer_printf(&ti,"FlxqX_ddf_Shoup: giant"); h = cgetg(m+1, t_VEC); for (j = 1; j <= m; j++) { pari_sp av = avma; GEN gj = gel(g, j); GEN e = FlxX_sub(gj, gel(b, 1), p); for (i = 2; i <= l; i++) e = FlxqXQ_mul_pre(e, FlxX_sub(gj, gel(b, i), p), S, T, p, pi); gel(h, j) = gerepileupto(av, e); } if (DEBUGLEVEL>=7) timer_printf(&ti,"FlxqX_ddf_Shoup: diff"); Sr = get_FlxqX_mod(S); F = cgetg(m+1, t_VEC); for (j = 1; j <= m; j++) { GEN u = FlxqX_gcd_pre(Sr, gel(h, j), T, p, pi); if (degpol(u)) { u = FlxqX_normalize_pre(u, T, p, pi); Sr = FlxqX_div_pre(Sr, u, T, p, pi); } gel(F,j) = u; } if (DEBUGLEVEL>=7) timer_printf(&ti,"FlxqX_ddf_Shoup: F"); f = const_vec(n, pol1_FlxX(v, vT)); for (j = 1; j <= m; j++) { GEN e = gel(F, j); for (i=l-1; i >= 0; i--) { GEN u = FlxqX_gcd_pre(e, FlxX_sub(gel(g, j), gel(b, i+1), p), T, p, pi); if (degpol(u)) { gel(f, l*j-i) = u = FlxqX_normalize_pre(u, T, p, pi); e = FlxqX_div_pre(e, u, T, p, pi); } if (!degpol(e)) break; } } if (DEBUGLEVEL>=7) timer_printf(&ti,"FlxqX_ddf_Shoup: f"); if (degpol(Sr)) gel(f, degpol(Sr)) = Sr; return gerepilecopy(av, f); } static GEN FlxqX_ddf_i(GEN f, GEN T, ulong p, ulong pi) { GEN Xq; if (!get_FlxqX_degree(f)) return cgetg(1, t_VEC); f = FlxqX_get_red_pre(f, T, p, pi); Xq = FlxqX_Frobenius_pre(f, T, p, pi); return FlxqX_ddf_Shoup(f, Xq, T, p, pi); } GEN FlxqX_ddf(GEN S, GEN T, ulong p) { ulong pi = SMALL_ULONG(p)? 0: get_Fl_red(p); T = Flx_get_red_pre(T, p, pi); S = FlxqX_normalize_pre(get_FlxqX_mod(S), T, p, pi); return ddf_to_ddf2( FlxqX_ddf_i(S, T, p, pi) ); } GEN FlxqX_degfact(GEN S, GEN T, ulong p) { ulong pi = SMALL_ULONG(p)? 0: get_Fl_red(p); GEN V; long i, l; T = Flx_get_red_pre(T, p, pi); S = FlxqX_normalize_pre(get_FlxqX_mod(S), T, p, pi); V = FlxqX_factor_squarefree_pre(S, T, p, pi); l = lg(V); for (i=1; i < l; i++) gel(V,i) = FlxqX_ddf_i(gel(V,i), T, p, pi); return vddf_to_simplefact(V, degpol(S)); } static void FlxqX_edf_rec(GEN S, GEN xp, GEN Xp, GEN hp, GEN t, long d, GEN T, ulong p, ulong pi, GEN V, long idx) { GEN Sp = get_FlxqX_mod(S); GEN u1, u2, f1, f2; GEN h; h = FlxqX_get_red_pre(hp, T, p, pi); t = FlxqX_rem_pre(t, S, T, p, pi); Xp = FlxqX_rem_pre(Xp, h, T, p, pi); u1 = FlxqX_roots_split(hp, xp, Xp, h, T, p, pi); f1 = FlxqX_gcd_pre(FlxqX_FlxqXQ_eval_pre(u1, t, S, T, p, pi), Sp, T, p, pi); f1 = FlxqX_normalize_pre(f1, T, p, pi); u2 = FlxqX_div_pre(hp, u1, T, p, pi); f2 = FlxqX_div_pre(Sp, f1, T, p, pi); if (degpol(u1)==1) gel(V, idx) = f1; else FlxqX_edf_rec(FlxqX_get_red_pre(f1, T, p, pi), xp, Xp, u1, t, d, T, p, pi, V, idx); idx += degpol(f1)/d; if (degpol(u2)==1) gel(V, idx) = f2; else FlxqX_edf_rec(FlxqX_get_red_pre(f2, T, p, pi), xp, Xp, u2, t, d, T, p, pi, V, idx); } static void FlxqX_edf(GEN Sp, GEN xp, GEN Xp, GEN Xq, long d, GEN T, ulong p, ulong pi, GEN V, long idx) { long n = degpol(Sp), r = n/d, vS = varn(Sp), vT = get_Flx_var(T); GEN S, h, t; pari_timer ti; if (r==1) { gel(V, idx) = Sp; return; } S = FlxqX_get_red_pre(Sp, T, p, pi); Xp = FlxqX_rem_pre(Xp, S, T, p, pi); Xq = FlxqX_rem_pre(Xq, S, T, p, pi); if (DEBUGLEVEL>=7) timer_start(&ti); do { GEN g = random_FlxqX(n, vS, T, p); t = gel(FlxqXQ_auttrace_pre(mkvec2(Xq, g), d, S, T, p, pi), 2); if (DEBUGLEVEL>=7) timer_printf(&ti,"FlxqX_edf: FlxqXQ_auttrace"); h = FlxqXQ_minpoly_pre(t, S, T, p, pi); if (DEBUGLEVEL>=7) timer_printf(&ti,"FlxqX_edf: FlxqXQ_minpoly"); } while (degpol(h) != r); Xp = FlxqXQ_powu_pre(polx_FlxX(vS, vT), p, h, T, p, pi); FlxqX_edf_rec(S, xp, Xp, h, t, d, T, p, pi, V, idx); } static void FlxqX_edf_simple(GEN Sp, GEN xp, GEN Xp, GEN Xq, long d, GEN T, ulong p, ulong pi, GEN V, long idx) { long v = varn(Sp), n = degpol(Sp), r = n/d; GEN S, f, ff; long vT = get_Flx_var(T), dT = get_Flx_degree(T); if (r==1) { gel(V, idx) = Sp; return; } S = FlxqX_get_red_pre(Sp, T, p, pi); Xp = FlxqX_rem_pre(Xp, S, T, p, pi); Xq = FlxqX_rem_pre(Xq, S, T, p, pi); while (1) { pari_sp btop = avma; long i; GEN g = random_FlxqX(n, v, T, p); GEN t = gel(FlxqXQ_auttrace_pre(mkvec2(Xq, g), d, S, T, p, pi), 2); if (lgpol(t) == 0) continue; for(i=1; i<=10; i++) { pari_sp btop2 = avma; GEN r = random_Flx(dT, vT, p); GEN R = FlxqXQ_halfFrobenius_i(FlxX_Flx_add(t, r, p), xp, Xp, S, T, p, pi); f = FlxqX_gcd_pre(FlxX_Flx_sub(R, pol1_Flx(vT), p), Sp, T, p, pi); if (degpol(f) > 0 && degpol(f) < n) break; set_avma(btop2); } if (degpol(f) > 0 && degpol(f) < n) break; set_avma(btop); } f = FlxqX_normalize_pre(f, T, p, pi); ff = FlxqX_div_pre(Sp, f , T, p, pi); FlxqX_edf_simple(f, xp, Xp, Xq, d, T, p, pi, V, idx); FlxqX_edf_simple(ff, xp, Xp, Xq, d, T, p, pi, V, idx+degpol(f)/d); } static GEN FlxqX_factor_Shoup(GEN S, GEN xp, GEN T, ulong p, ulong pi) { long i, n, s = 0; GEN X, Xp, Xq, D, V; long dT = get_Flx_degree(T), vT = get_Flx_var(T); long e = expi(powuu(p, dT)); pari_timer ti; n = get_FlxqX_degree(S); S = FlxqX_get_red_pre(S, T, p, pi); if (DEBUGLEVEL>=6) timer_start(&ti); X = polx_FlxX(get_FlxqX_var(S), vT); Xp = FlxqXQ_powu_pre(X, p, S, T, p, pi); Xq = FlxqXQ_Frobenius(xp, Xp, S, T, p, pi); if (DEBUGLEVEL>=6) timer_printf(&ti,"FlxqX_Frobenius"); D = FlxqX_ddf_Shoup(S, Xq, T, p, pi); if (DEBUGLEVEL>=6) timer_printf(&ti,"FlxqX_ddf_Shoup"); s = ddf_to_nbfact(D); V = cgetg(s+1, t_COL); for (i = 1, s = 1; i <= n; i++) { GEN Di = gel(D,i); long ni = degpol(Di), ri = ni/i; if (ni == 0) continue; Di = FlxqX_normalize_pre(Di, T, p, pi); if (ni == i) { gel(V, s++) = Di; continue; } if (ri <= e*expu(e)) FlxqX_edf(Di, xp, Xp, Xq, i, T, p, pi, V, s); else FlxqX_edf_simple(Di, xp, Xp, Xq, i, T, p, pi, V, s); if (DEBUGLEVEL>=6) timer_printf(&ti,"FlxqX_edf(%ld)",i); s += ri; } return V; } static GEN FlxqX_factor_Cantor(GEN f, GEN T, ulong p) { ulong pi = SMALL_ULONG(p)? 0: get_Fl_red(p); GEN xp, E, F, V; long i, j, l; T = Flx_get_red_pre(T, p, pi); f = FlxqX_normalize_pre(f, T, p, pi); switch(degpol(f)) { case -1: retmkmat2(mkcol(f), mkvecsmall(1)); case 0: return trivial_fact(); case 1: retmkmat2(mkcol(f), mkvecsmall(1)); case 2: return FlxqX_factor_2(f, T, p, pi); } if (FlxY_degreex(f) <= 0) return Flx_factorff_i(FlxX_to_Flx(f), T, p); xp = Flx_Frobenius_pre(T, p, pi); V = FlxqX_factor_squarefree_i(f, xp, get_Flx_mod(T), p, pi); l = lg(V); F = cgetg(l, t_VEC); E = cgetg(l, t_VEC); for (i=1, j=1; i < l; i++) if (degpol(gel(V,i))) { GEN Fj = FlxqX_factor_Shoup(gel(V,i), xp, T, p, pi); gel(F, j) = Fj; gel(E, j) = const_vecsmall(lg(Fj)-1, i); j++; } return sort_factor_pol(FE_concat(F,E,j), cmp_Flx); } /* T must be squarefree mod p*/ GEN FlxqX_nbfact_by_degree(GEN f, long *nb, GEN T, ulong p) { GEN Xq, D; pari_timer ti; long i, s, n = get_FlxqX_degree(f); ulong pi = SMALL_ULONG(p)? 0: get_Fl_red(p); GEN V = const_vecsmall(n, 0); pari_sp av = avma; T = Flx_get_red_pre(T, p, pi); f = FlxqX_get_red_pre(f, T, p, pi); if (DEBUGLEVEL>=6) timer_start(&ti); Xq = FlxqX_Frobenius_pre(f, T, p, pi); if (DEBUGLEVEL>=6) timer_printf(&ti,"FlxqX_Frobenius"); D = FlxqX_ddf_Shoup(f, Xq, T, p, pi); if (DEBUGLEVEL>=6) timer_printf(&ti,"FlxqX_ddf_Shoup"); for (i = 1, s = 0; i <= n; i++) { V[i] = degpol(gel(D,i))/i; s += V[i]; } *nb = s; set_avma(av); return V; } long FlxqX_nbfact_Frobenius(GEN S, GEN Xq, GEN T, ulong p) { pari_sp av = avma; GEN u = get_FlxqX_mod(S); long s; if (FlxY_degreex(u) <= 0) s = Flx_nbfactff(FlxX_to_Flx(u), T, p); else s = ddf_to_nbfact(FlxqX_ddf_Shoup(S, Xq, T, p, SMALL_ULONG(p)? 0: get_Fl_red(p))); return gc_long(av,s); } long FlxqX_nbfact(GEN S, GEN T, ulong p) { pari_sp av = avma; GEN u = get_FlxqX_mod(S); long s; if (FlxY_degreex(u) <= 0) s = Flx_nbfactff(FlxX_to_Flx(u), T, p); else s = ddf_to_nbfact(FlxqX_ddf_Shoup(S, FlxqX_Frobenius(S, T, p), T, p, SMALL_ULONG(p)? 0: get_Fl_red(p))); return gc_long(av,s); } GEN FlxqX_factor(GEN x, GEN T, ulong p) { pari_sp av = avma; return gerepilecopy(av, FlxqX_factor_Cantor(x, T, p)); } GEN F2xqX_factor(GEN x, GEN T) { pari_sp av = avma; return gerepilecopy(av, F2xqX_factor_Cantor(x, T)); } long FpXQX_ddf_degree(GEN S, GEN XP, GEN T, GEN p) { pari_sp av = avma; GEN X, b, g, xq, q; long i, j, n, v, B, l, m, bo, ro; pari_timer ti; hashtable h; n = get_FpXQX_degree(S); v = get_FpXQX_var(S); X = pol_x(v); if (gequal(X,XP)) return 1; B = n/2; l = usqrt(B); m = (B+l-1)/l; T = FpX_get_red(T, p); S = FpXQX_get_red(S, T, p); hash_init_GEN(&h, l+2, gequal, 1); hash_insert_long(&h, X, 0); hash_insert_long(&h, simplify_shallow(XP), 1); bo = brent_kung_optpow(n, l-1, 1); ro = l<=1 ? 0: (bo-1)/(l-1) + ((n-1)/bo); q = powiu(p, get_FpX_degree(T)); if (DEBUGLEVEL>=7) timer_start(&ti); b = XP; if (expi(q) > ro) { xq = FpXQXQ_powers(b, brent_kung_optpow(n, l-1, 1), S, T, p); if (DEBUGLEVEL>=7) timer_printf(&ti,"FpXQX_ddf_degree: xq baby"); } else xq = NULL; for (i = 3; i <= l+1; i++) { b = xq ? FpXQX_FpXQXQV_eval(b, xq, S, T, p) : FpXQXQ_pow(b, q, S, T, p); if (gequal(b,X)) return gc_long(av,i-1); hash_insert_long(&h, simplify_shallow(b), i-1); } if (DEBUGLEVEL>=7) timer_printf(&ti,"FpXQX_ddf_degree: baby"); g = b; xq = FpXQXQ_powers(g, brent_kung_optpow(n, m, 1), S, T, p); if (DEBUGLEVEL>=7) timer_printf(&ti,"FpXQX_ddf_degree: xq giant"); for(i = 2; i <= m+1; i++) { g = FpXQX_FpXQXQV_eval(g, xq, S, T, p); if (hash_haskey_long(&h, simplify_shallow(g), &j)) return gc_long(av,l*i-j); } return gc_long(av,n); } static GEN FpXQX_ddf_Shoup(GEN S, GEN Xq, GEN T, GEN p) { pari_sp av = avma; GEN b, g, h, F, f, Sr, xq, q; long i, j, n, v, bo, ro; long B, l, m; pari_timer ti; n = get_FpXQX_degree(S); v = get_FpXQX_var(S); if (n == 0) return cgetg(1, t_VEC); if (n == 1) return mkvec(get_FpXQX_mod(S)); B = n/2; l = usqrt(B); m = (B+l-1)/l; S = FpXQX_get_red(S, T, p); b = cgetg(l+2, t_VEC); gel(b, 1) = pol_x(v); gel(b, 2) = Xq; bo = brent_kung_optpow(n, l-1, 1); ro = l<=1 ? 0: (bo-1)/(l-1) + ((n-1)/bo); q = powiu(p, get_FpX_degree(T)); if (DEBUGLEVEL>=7) timer_start(&ti); if (expi(q) <= ro) for (i = 3; i <= l+1; i++) gel(b, i) = FpXQXQ_pow(gel(b, i-1), q, S, T, p); else { xq = FpXQXQ_powers(gel(b, 2), bo, S, T, p); if (DEBUGLEVEL>=7) timer_printf(&ti,"FpXQX_ddf_Shoup: xq baby"); for (i = 3; i <= l+1; i++) gel(b, i) = FpXQX_FpXQXQV_eval(gel(b, i-1), xq, S, T, p); } if (DEBUGLEVEL>=7) timer_printf(&ti,"FpXQX_ddf_Shoup: baby"); xq = FpXQXQ_powers(gel(b, l+1), brent_kung_optpow(n, m-1, 1), S, T, p); if (DEBUGLEVEL>=7) timer_printf(&ti,"FpXQX_ddf_Shoup: xq giant"); g = cgetg(m+1, t_VEC); gel(g, 1) = gel(xq, 2); for(i = 2; i <= m; i++) gel(g, i) = FpXQX_FpXQXQV_eval(gel(g, i-1), xq, S, T, p); if (DEBUGLEVEL>=7) timer_printf(&ti,"FpXQX_ddf_Shoup: giant"); h = cgetg(m+1, t_VEC); for (j = 1; j <= m; j++) { pari_sp av = avma; GEN gj = gel(g, j); GEN e = FpXX_sub(gj, gel(b, 1), p); for (i = 2; i <= l; i++) e = FpXQXQ_mul(e, FpXX_sub(gj, gel(b, i), p), S, T, p); gel(h, j) = gerepileupto(av, e); } if (DEBUGLEVEL>=7) timer_printf(&ti,"FpXQX_ddf_Shoup: diff"); Sr = get_FpXQX_mod(S); F = cgetg(m+1, t_VEC); for (j = 1; j <= m; j++) { GEN u = FpXQX_gcd(Sr, gel(h,j), T, p); if (degpol(u)) { u = FpXQX_normalize(u, T, p); Sr = FpXQX_div(Sr, u, T, p); } gel(F,j) = u; } if (DEBUGLEVEL>=7) timer_printf(&ti,"FpXQX_ddf_Shoup: F"); f = const_vec(n, pol_1(v)); for (j = 1; j <= m; j++) { GEN e = gel(F, j); for (i=l-1; i >= 0; i--) { GEN u = FpXQX_gcd(e, FpXX_sub(gel(g, j), gel(b, i+1), p), T, p); if (degpol(u)) { gel(f, l*j-i) = u = FpXQX_normalize(u, T, p); e = FpXQX_div(e, u, T, p); } if (!degpol(e)) break; } } if (DEBUGLEVEL>=7) timer_printf(&ti,"FpXQX_ddf_Shoup: f"); if (degpol(Sr)) gel(f, degpol(Sr)) = Sr; return gerepilecopy(av, f); } static GEN FpXQX_ddf_i(GEN f, GEN T, GEN p) { GEN Xq; if (!get_FpXQX_degree(f)) return cgetg(1,t_VEC); f = FpXQX_get_red(f, T, p); Xq = FpXQX_Frobenius(f, T, p); return FpXQX_ddf_Shoup(f, Xq, T, p); } static GEN FpXQX_ddf_raw(GEN f, GEN T, GEN p) { if (lgefint(p)==3) { ulong pp = p[2]; GEN M; long vT = get_FpX_var(T); if (pp==2) { M = F2xqX_ddf(ZXX_to_F2xX(f, vT), ZX_to_F2x(get_FpX_mod(T))); return mkvec2(F2xXC_to_ZXXC(gel(M,1)), gel(M,2)); } M = FlxqX_ddf(ZXX_to_FlxX(f, pp, vT), ZXT_to_FlxT(T, pp), pp); return mkvec2(FlxXC_to_ZXXC(gel(M,1)), gel(M,2)); } T = FpX_get_red(T, p); f = FpXQX_normalize(get_FpXQX_mod(f), T, p); return ddf_to_ddf2( FpXQX_ddf_i(f, T, p) ); } GEN FpXQX_ddf(GEN x, GEN T, GEN p) { pari_sp av = avma; return gerepilecopy(av, FpXQX_ddf_raw(x,T,p)); } static GEN FpXQX_degfact_raw(GEN f, GEN T, GEN p) { GEN V; long i,l; if (lgefint(p)==3) { ulong pp = p[2]; long vT = get_FpX_var(T); if (pp==2) return F2xqX_degfact(ZXX_to_F2xX(f, vT), ZX_to_F2x(get_FpX_mod(T))); else return FlxqX_degfact(ZXX_to_FlxX(f, pp, vT), ZXT_to_FlxT(T, pp), pp); } T = FpX_get_red(T, p); f = FpXQX_normalize(get_FpXQX_mod(f), T, p); V = FpXQX_factor_Yun(f, T, p); l = lg(V); for (i=1; i < l; i++) gel(V,i) = FpXQX_ddf_i(gel(V,i), T, p); return vddf_to_simplefact(V, degpol(f)); } GEN FpXQX_degfact(GEN x, GEN T, GEN p) { pari_sp av = avma; return gerepilecopy(av, FpXQX_degfact_raw(x,T,p)); } static void FpXQX_edf_rec(GEN S, GEN xp, GEN Xp, GEN hp, GEN t, long d, GEN T, GEN p, GEN V, long idx) { GEN Sp = get_FpXQX_mod(S); GEN u1, u2, f1, f2; GEN h; h = FpXQX_get_red(hp, T, p); t = FpXQX_rem(t, S, T, p); Xp = FpXQX_rem(Xp, h, T, p); u1 = FpXQX_roots_split(hp, xp, Xp, h, T, p); f1 = FpXQX_gcd(FpXQX_FpXQXQ_eval(u1, t, S, T, p), Sp, T, p); f1 = FpXQX_normalize(f1, T, p); u2 = FpXQX_div(hp, u1, T, p); f2 = FpXQX_div(Sp, f1, T, p); if (degpol(u1)==1) gel(V, idx) = f1; else FpXQX_edf_rec(FpXQX_get_red(f1, T, p), xp, Xp, u1, t, d, T, p, V, idx); idx += degpol(f1)/d; if (degpol(u2)==1) gel(V, idx) = f2; else FpXQX_edf_rec(FpXQX_get_red(f2, T, p), xp, Xp, u2, t, d, T, p, V, idx); } static void FpXQX_edf(GEN Sp, GEN xp, GEN Xp, GEN Xq, long d, GEN T, GEN p, GEN V, long idx) { long n = degpol(Sp), r = n/d, vS = varn(Sp); GEN S, h, t; pari_timer ti; if (r==1) { gel(V, idx) = Sp; return; } S = FpXQX_get_red(Sp, T, p); Xp = FpXQX_rem(Xp, S, T, p); Xq = FpXQX_rem(Xq, S, T, p); if (DEBUGLEVEL>=7) timer_start(&ti); do { GEN g = random_FpXQX(n, vS, T, p); t = gel(FpXQXQ_auttrace(mkvec2(Xq, g), d, S, T, p), 2); if (DEBUGLEVEL>=7) timer_printf(&ti,"FpXQX_edf: FpXQXQ_auttrace"); h = FpXQXQ_minpoly(t, S, T, p); if (DEBUGLEVEL>=7) timer_printf(&ti,"FpXQX_edf: FpXQXQ_minpoly"); } while (degpol(h) != r); Xp = FpXQXQ_pow(pol_x(vS), p, h, T, p); FpXQX_edf_rec(S, xp, Xp, h, t, d, T, p, V, idx); } static void FpXQX_edf_simple(GEN Sp, GEN xp, GEN Xp, GEN Xq, long d, GEN T, GEN p, GEN V, long idx) { long v = varn(Sp), n = degpol(Sp), r = n/d; GEN S, f, ff; long vT = get_FpX_var(T), dT = get_FpX_degree(T); if (r==1) { gel(V, idx) = Sp; return; } S = FpXQX_get_red(Sp, T, p); Xp = FpXQX_rem(Xp, S, T, p); Xq = FpXQX_rem(Xq, S, T, p); while (1) { pari_sp btop = avma; long i; GEN g = random_FpXQX(n, v, T, p); GEN t = gel(FpXQXQ_auttrace(mkvec2(Xq, g), d, S, T, p), 2); if (lgpol(t) == 0) continue; for(i=1; i<=10; i++) { pari_sp btop2 = avma; GEN r = random_FpX(dT, vT, p); GEN R = FpXQXQ_halfFrobenius_i(FqX_Fq_add(t, r, T, p), xp, Xp, S, T, p); f = FpXQX_gcd(FqX_Fq_add(R, gen_m1, T, p), Sp, T, p); if (degpol(f) > 0 && degpol(f) < n) break; set_avma(btop2); } if (degpol(f) > 0 && degpol(f) < n) break; set_avma(btop); } f = FpXQX_normalize(f, T, p); ff = FpXQX_div(Sp, f , T, p); FpXQX_edf_simple(f, xp, Xp, Xq, d, T, p, V, idx); FpXQX_edf_simple(ff, xp, Xp, Xq, d, T, p, V, idx+degpol(f)/d); } static GEN FpXQX_factor_Shoup(GEN S, GEN xp, GEN T, GEN p) { long i, n, s = 0, dT = get_FpX_degree(T), e = expi(powiu(p, dT)); GEN X, Xp, Xq, D, V; pari_timer ti; n = get_FpXQX_degree(S); S = FpXQX_get_red(S, T, p); if (DEBUGLEVEL>=6) timer_start(&ti); X = pol_x(get_FpXQX_var(S)); Xp = FpXQXQ_pow(X, p, S, T, p); Xq = FpXQXQ_Frobenius(xp, Xp, S, T, p); if (DEBUGLEVEL>=6) timer_printf(&ti,"FpXQX_Frobenius"); D = FpXQX_ddf_Shoup(S, Xq, T, p); if (DEBUGLEVEL>=6) timer_printf(&ti,"FpXQX_ddf_Shoup"); s = ddf_to_nbfact(D); V = cgetg(s+1, t_COL); for (i = 1, s = 1; i <= n; i++) { GEN Di = gel(D,i); long ni = degpol(Di), ri = ni/i; if (ni == 0) continue; Di = FpXQX_normalize(Di, T, p); if (ni == i) { gel(V, s++) = Di; continue; } if (ri <= e*expu(e)) FpXQX_edf(Di, xp, Xp, Xq, i, T, p, V, s); else FpXQX_edf_simple(Di, xp, Xp, Xq, i, T, p, V, s); if (DEBUGLEVEL>=6) timer_printf(&ti,"FpXQX_edf(%ld)",i); s += ri; } return V; } static GEN FpXQX_factor_Cantor(GEN f, GEN T, GEN p) { GEN xp, E, F, V; long i, j, l; T = FpX_get_red(T, p); f = FpXQX_normalize(f, T, p); switch(degpol(f)) { case -1: retmkmat2(mkcol(f), mkvecsmall(1)); case 0: return trivial_fact(); case 1: retmkmat2(mkcol(f), mkvecsmall(1)); case 2: return FpXQX_factor_2(f, T, p); } if (isabsolutepol(f)) return FpX_factorff_i(simplify_shallow(f), T, p); xp = FpX_Frobenius(T, p); V = FpXQX_factor_Yun(f, T, p); l = lg(V); F = cgetg(l, t_VEC); E = cgetg(l, t_VEC); for (i=1, j=1; i < l; i++) if (degpol(gel(V,i))) { GEN Fj = FpXQX_factor_Shoup(gel(V,i), xp, T, p); gel(E,j) = const_vecsmall(lg(Fj)-1, i); gel(F,j) = Fj; j++; } return sort_factor_pol(FE_concat(F,E,j), cmp_RgX); } long FpXQX_nbfact_Frobenius(GEN S, GEN Xq, GEN T, GEN p) { pari_sp av = avma; GEN u = get_FpXQX_mod(S); long s; if (lgefint(p)==3) { ulong pp = p[2]; long vT = get_FpX_var(T); GEN Sp = ZXXT_to_FlxXT(S,pp,vT), Xqp = ZXX_to_FlxX(Xq,pp,vT); s = FlxqX_nbfact_Frobenius(Sp, Xqp, ZXT_to_FlxT(T,pp), pp); } else if (isabsolutepol(u)) s = FpX_nbfactff(simplify_shallow(u), T, p); else s = ddf_to_nbfact(FpXQX_ddf_Shoup(S, Xq, T, p)); return gc_long(av,s); } long FpXQX_nbfact(GEN S, GEN T, GEN p) { pari_sp av = avma; GEN u = get_FpXQX_mod(S); long s; if (lgefint(p)==3) { ulong pp = p[2]; long vT = get_FpX_var(T); s = FlxqX_nbfact(ZXXT_to_FlxXT(S,pp,vT), ZXT_to_FlxT(T,pp), pp); } else if (isabsolutepol(u)) s = FpX_nbfactff(simplify_shallow(u), T, p); else s = ddf_to_nbfact(FpXQX_ddf_Shoup(S, FpXQX_Frobenius(S, T, p), T, p)); return gc_long(av,s); } long FqX_nbfact(GEN u, GEN T, GEN p) { return T ? FpXQX_nbfact(u, T, p): FpX_nbfact(u, p); } static GEN FpXQX_factor_Berlekamp_i(GEN f, GEN T, GEN p) { if (lgefint(p)==3) { ulong pp = p[2]; GEN M; long vT = get_FpX_var(T); if (pp==2) { M = F2xqX_factor_Cantor(ZXX_to_F2xX(f, vT), ZX_to_F2x(get_FpX_mod(T))); return mkvec2(F2xXC_to_ZXXC(gel(M,1)), gel(M,2)); } M = FlxqX_Berlekamp_i(ZXX_to_FlxX(f, pp, vT), ZXT_to_FlxT(T, pp), pp); return mkvec2(FlxXC_to_ZXXC(gel(M,1)), gel(M,2)); } return FpXQX_Berlekamp_i(f, T, p); } GEN FpXQX_factor_Berlekamp(GEN x, GEN T, GEN p) { pari_sp av = avma; return gerepilecopy(av, FpXQX_factor_Berlekamp_i(x,T,p)); } static GEN FpXQX_factor_i(GEN f, GEN T, GEN p) { if (lgefint(p)==3) { ulong pp = p[2]; GEN M; long vT = get_FpX_var(T); if (pp==2) { M = F2xqX_factor_Cantor(ZXX_to_F2xX(f, vT), ZX_to_F2x(get_FpX_mod(T))); return mkvec2(F2xXC_to_ZXXC(gel(M,1)), gel(M,2)); } M = FlxqX_factor_Cantor(ZXX_to_FlxX(f, pp, vT), ZXT_to_FlxT(T, pp), pp); return mkvec2(FlxXC_to_ZXXC(gel(M,1)), gel(M,2)); } return FpXQX_factor_Cantor(f, T, p); } GEN FpXQX_factor(GEN x, GEN T, GEN p) { pari_sp av = avma; return gerepilecopy(av, FpXQX_factor_i(x,T,p)); } long FlxqX_is_squarefree(GEN P, GEN T, ulong p) { pari_sp av = avma; GEN z = FlxqX_gcd(P, FlxX_deriv(P, p), T, p); return gc_long(av, degpol(z)==0); } long FqX_is_squarefree(GEN P, GEN T, GEN p) { pari_sp av = avma; GEN z = FqX_gcd(P, FqX_deriv(P, T, p), T, p); return gc_long(av, degpol(z)==0); } /* as RgX_to_FpXQ(FqX_to_FFX), leaving alone t_FFELT */ static GEN RgX_to_FFX(GEN x, GEN ff) { long i, lx; GEN p = FF_p_i(ff), T = FF_mod(ff), y = cgetg_copy(x,&lx); y[1] = x[1]; if (degpol(T) == 1) T = NULL; for (i = 2; i < lx; i++) { GEN c = gel(x,i); gel(y,i) = typ(c) == t_FFELT? c: Fq_to_FF(Rg_to_Fq(c,T,p), ff); } return y; } #define code(t1,t2) ((t1 << 6) | t2) /* Check types and replace F by a monic normalized FpX having the same roots * Don't bother to make constant polynomials monic */ static GEN factmod_init(GEN f, GEN *pD, GEN *pT, GEN *pp) { const char *s = "factormod"; GEN T, p, D = *pD; if (typ(f) != t_POL) pari_err_TYPE(s,f); if (!D) { long pa, t = RgX_type(f, pp, pT, &pa); if (t == t_FFELT) return f; *pD = gen_0; if (t != t_INTMOD && t != code(t_POLMOD,t_INTMOD)) pari_err_TYPE(s,f); return RgX_to_FqX(f, *pT, *pp); } if (typ(D) == t_FFELT) { *pD = NULL; *pT = D; return RgX_to_FFX(f,D); } if (!ff_parse_Tp(D, &T, &p, 1)) pari_err_TYPE(s,D); if (T && varncmp(varn(T), varn(f)) <= 0) pari_err_PRIORITY(s, T, "<=", varn(f)); *pT = T; *pp = p; return RgX_to_FqX(f, T, p); } #undef code int ff_parse_Tp(GEN Tp, GEN *T, GEN *p, long red) { long t = typ(Tp); *T = *p = NULL; if (t == t_INT) { *p = Tp; return cmpiu(*p, 1) > 0; } if (t != t_VEC || lg(Tp) != 3) return 0; *T = gel(Tp,1); *p = gel(Tp,2); if (typ(*p) != t_INT) { if (typ(*T) != t_INT) return 0; swap(*T, *p); /* support both [T,p] and [p,T] */ } if (red) *T = RgX_to_FpX(*T, *p); return cmpiu(*p, 1) > 0 && typ(*T) == t_POL && RgX_is_ZX(*T); } static GEN to_Fq(GEN x, GEN T, GEN p) { long i, lx, tx = typ(x); GEN y; if (tx == t_INT) y = mkintmod(x,p); else { if (tx != t_POL) pari_err_TYPE("to_Fq",x); y = cgetg_copy(x,&lx); y[1] = x[1]; for (i=2; i= (lvl) + 3) err_printf /********************************************************************/ /** **/ /** BLACK BOX HERMITE RINGS AND HOWELL NORMAL FORM **/ /** contributed by Aurel Page (2017) **/ /** **/ /********************************************************************/ /* bb_hermite R: - add(a,b): a+b - neg(a): -a - mul(a,b): a*b - extgcd(a,b,&small): [d,U] with d in R and U in GL_2(R) such that [0;d] = [a;b]*U. set small==1 to assert that U is a 'small' operation (no red needed). - rann(a): b in R such that b*R = {x in R | a*x==0} - lquo(a,b,&r): q in R such that r=a-b*q is a canonical representative of the image of a in R/b*R. The canonical lift of 0 must be 0. - unit(a): u unit in R^* such that a*u is a canonical generator of the ideal a*R - equal0(a): a==0? - equal1(a): a==1? - s(n): image of the small integer n in R - red(a): unique representative of a as an element of R op encoding of elementary operations: - t_VECSMALL: the corresponding permutation (vecpermute) - [Vecsmall([i,j])]: the transposition Ci <-> Cj - [Vecsmall([i]),u], u in R^*: Ci <- Ci*u - [Vecsmall([i,j]),a], a in R: Ci <- Ci + Cj*a - [Vecsmall([i,j,0]),U], U in GL_2(R): (Ci|Cj) <- (Ci|Cj)*U */ struct bb_hermite { GEN (*add)(void*, GEN, GEN); GEN (*neg)(void*, GEN); GEN (*mul)(void*, GEN, GEN); GEN (*extgcd)(void*, GEN, GEN, int*); GEN (*rann)(void*, GEN); GEN (*lquo)(void*, GEN, GEN, GEN*); GEN (*unit)(void*, GEN); int (*equal0)(GEN); int (*equal1)(GEN); GEN (*s)(void*, long); GEN (*red)(void*, GEN); }; static GEN _Fp_add(void *data, GEN x, GEN y) { (void) data; return addii(x,y); } static GEN _Fp_neg(void *data, GEN x) { (void) data; return negi(x); } static GEN _Fp_mul(void *data, GEN x, GEN y) { (void) data; return mulii(x,y); } static GEN _Fp_rann(void *data, GEN x) { GEN d, N = (GEN)data; if (!signe(x)) return gen_1; d = gcdii(x,N); return modii(diviiexact(N,d),N); } static GEN _Fp_lquo(void *data, GEN x, GEN y, GEN* r) { (void) data; return truedvmdii(x,y,r); } /* D=MN, p|M => !p|a, p|N => p|a, return M */ static GEN Z_split(GEN D, GEN a) { long i, n; GEN N; n = expi(D); n = n<2 ? 1 : expu(n)+1; for (i=1;i<=n;i++) a = Fp_sqr(a,D); N = gcdii(a,D); return diviiexact(D,N); } /* c s.t. gcd(a+cb,N) = gcd(a,b,N) without factoring */ static GEN Z_stab(GEN a, GEN b, GEN N) { GEN g, a2, N2; g = gcdii(a,b); g = gcdii(g,N); N2 = diviiexact(N,g); a2 = diviiexact(a,g); return Z_split(N2,a2); } static GEN _Fp_unit(void *data, GEN x) { GEN g,s,v,d,N=(GEN)data,N2; long i; if (!signe(x)) return NULL; g = bezout(x,N,&s,&v); if (equali1(g) || equali1(gcdii(s,N))) return mkvec2(g,s); N2 = diviiexact(N,g); for (i=0; i<5; i++) { s = addii(s,N2); if (equali1(gcdii(s,N))) return mkvec2(g,s); } d = Z_stab(s,N2,N); d = mulii(d,N2); v = Fp_add(s,d,N); if (equali1(v)) return NULL; return mkvec2(g,v); } static GEN _Fp_extgcd(void *data, GEN x, GEN y, int* smallop) { GEN d,u,v,m; if (equali1(y)) { *smallop = 1; return mkvec2(y,mkmat2( mkcol2(gen_1,Fp_neg(x,(GEN)data)), mkcol2(gen_0,gen_1))); } *smallop = 0; d = bezout(x,y,&u,&v); if (!signe(d)) return mkvec2(d,matid(2)); m = cgetg(3,t_MAT); m = mkmat2( mkcol2(diviiexact(y,d),negi(diviiexact(x,d))), mkcol2(u,v)); return mkvec2(d,m); } static int _Fp_equal0(GEN x) { return !signe(x); } static int _Fp_equal1(GEN x) { return equali1(x); } static GEN _Fp_s(void *data, long x) { if (!x) return gen_0; if (x==1) return gen_1; return modsi(x,(GEN)data); } static GEN _Fp_red(void *data, GEN x) { return Fp_red(x, (GEN)data); } /* p not necessarily prime */ static const struct bb_hermite Fp_hermite= {_Fp_add,_Fp_neg,_Fp_mul,_Fp_extgcd,_Fp_rann,_Fp_lquo,_Fp_unit,_Fp_equal0,_Fp_equal1,_Fp_s,_Fp_red}; static const struct bb_hermite* get_Fp_hermite(void **data, GEN p) { *data = (void*)p; return &Fp_hermite; } static void gen_redcol(GEN C, long lim, void* data, const struct bb_hermite *R) { long i; for (i=1; i<=lim; i++) if (!R->equal0(gel(C,i))) gel(C,i) = R->red(data, gel(C,i)); } static GEN /* return NULL if a==0 */ /* assume C*a is zero after lim */ gen_rightmulcol(GEN C, GEN a, long lim, int fillzeros, void* data, const struct bb_hermite *R) { GEN Ca,zero; long i; if (R->equal1(a)) return C; if (R->equal0(a)) return NULL; Ca = cgetg(lg(C),t_COL); for (i=1; i<=lim; i++) gel(Ca,i) = R->mul(data, gel(C,i), a); if (fillzeros && lim+1 < lg(C)) { zero = R->s(data,0); for (i=lim+1; ilim */ gen_addcol(GEN C1, GEN C2, long lim, void* data, const struct bb_hermite *R) { long i; for (i=1; i<=lim; i++) gel(C1,i) = R->add(data, gel(C1,i), gel(C2,i)); } static void /* H[,i] <- H[,i] + C*a */ /* assume C is zero after lim */ gen_addrightmul(GEN H, GEN C, GEN a, long i, long lim, void* data, const struct bb_hermite *R) { GEN Ca; if (R->equal0(a)) return; Ca = gen_rightmulcol(C, a, lim, 0, data, R); gen_addcol(gel(H,i), Ca, lim, data, R); } static GEN gen_zerocol(long n, void* data, const struct bb_hermite *R) { GEN C = cgetg(n+1,t_COL), zero = R->s(data, 0); long i; for (i=1; i<=n; i++) gel(C,i) = zero; return C; } static GEN gen_zeromat(long m, long n, void* data, const struct bb_hermite *R) { GEN M = cgetg(n+1,t_MAT); long i; for (i=1; i<=n; i++) gel(M,i) = gen_zerocol(m, data, R); return M; } static GEN gen_colei(long n, long i, void* data, const struct bb_hermite *R) { GEN C = cgetg(n+1,t_COL), zero = R->s(data, 0); long j; for (j=1; j<=n; j++) if (i!=j) gel(C,j) = zero; else gel(C,j) = R->s(data,1); return C; } static GEN gen_matid_hermite(long n, void* data, const struct bb_hermite *R) { GEN M = cgetg(n+1,t_MAT); long i; for (i=1; i<=n; i++) gel(M,i) = gen_colei(n, i, data, R); return M; } static GEN gen_matmul_hermite(GEN A, GEN B, void* data, const struct bb_hermite *R) { GEN M,sum,prod,zero = R->s(data,0); long a,b,c,c2,i,j,k; RgM_dimensions(A,&a,&c); RgM_dimensions(B,&c2,&b); if (c!=c2) pari_err_DIM("gen_matmul_hermite"); M = cgetg(b+1,t_MAT); for (j=1; j<=b; j++) { gel(M,j) = cgetg(a+1,t_COL); for (i=1; i<=a; i++) { sum = zero; for (k=1; k<=c; k++) { prod = R->mul(data, gcoeff(A,i,k), gcoeff(B,k,j)); sum = R->add(data, sum, prod); } gcoeff(M,i,j) = sum; } gen_redcol(gel(M,j), a, data, R); } return M; } static void /* U = [u1,u2]~, C <- A*u1 + B*u2 */ /* assume both A, B and C are zero after lim */ gen_rightlincomb(GEN A, GEN B, GEN U, GEN *C, long lim, void* data, const struct bb_hermite *R) { GEN Au1, Bu2; Au1 = gen_rightmulcol(A, gel(U,1), lim, 1, data, R); Bu2 = gen_rightmulcol(B, gel(U,2), lim, 1, data, R); if (!Au1 && !Bu2) { *C = gen_zerocol(lg(A)-1, data, R); return; } if (!Au1) { *C = Bu2; return; } if (!Bu2) { *C = Au1; return; } gen_addcol(Au1, Bu2, lim, data, R); *C = Au1; } static void /* (H[,i] | H[,j]) <- (H[,i] | H[,j]) * U */ /* assume both columns are zero after lim */ gen_elem(GEN H, GEN U, long i, long j, long lim, void* data, const struct bb_hermite *R) { GEN Hi, Hj; Hi = shallowcopy(gel(H,i)); Hj = shallowcopy(gel(H,j)); gen_rightlincomb(Hi, Hj, gel(U,1), &gel(H,i), lim, data, R); gen_rightlincomb(Hi, Hj, gel(U,2), &gel(H,j), lim, data, R); } static int /* assume C is zero after lim */ gen_is_zerocol(GEN C, long lim, void* data, const struct bb_hermite *R) { long i; (void) data; for (i=1; i<=lim; i++) if (!R->equal0(gel(C,i))) return 0; return 1; } /* The mkop* functions return NULL if the corresponding operation is the identity */ static GEN /* Ci <- Ci + Cj*a */ mkoptransv(long i, long j, GEN a, void* data, const struct bb_hermite *R) { a = R->red(data,a); if (R->equal0(a)) return NULL; return mkvec2(mkvecsmall2(i,j),a); } static GEN /* (Ci|Cj) <- (Ci|Cj)*U */ mkopU(long i, long j, GEN U, void* data, const struct bb_hermite *R) { if (R->equal1(gcoeff(U,1,1)) && R->equal0(gcoeff(U,1,2)) && R->equal1(gcoeff(U,2,2))) return mkoptransv(i,j,gcoeff(U,2,1),data,R); return mkvec2(mkvecsmall3(i,j,0),U); } static GEN /* Ci <- Ci*u */ mkopmul(long i, GEN u, const struct bb_hermite *R) { if (R->equal1(u)) return NULL; return mkvec2(mkvecsmall(i),u); } static GEN /* Ci <-> Cj */ mkopswap(long i, long j) { return mkvec(mkvecsmall2(i,j)); } /* M: t_MAT. Apply the operation op to M by right multiplication. */ static void gen_rightapply(GEN M, GEN op, void* data, const struct bb_hermite *R) { GEN M2, ind, X; long i, j, m = lg(gel(M,1))-1; switch (typ(op)) { case t_VECSMALL: M2 = vecpermute(M,op); for (i=1; imul(data, X, gel(C,i)); gel(C,i) = R->red(data, gel(C,i)); return; case 3: j = ind[2]; if (R->equal0(gel(C,i))) return; gel(C,j) = R->add(data, gel(C,j), R->mul(data, X, gel(C,i))); return; case 4: j = ind[2]; C2 = gen_matmul_hermite(X, mkmat(mkcol2(gel(C,i),gel(C,j))), data, R); gel(C,i) = gcoeff(C2,1,1); gel(C,j) = gcoeff(C2,2,1); return; } } } } /* \prod_i det ops[i]. Only makes sense if R is commutative. */ static GEN gen_detops(GEN ops, void* data, const struct bb_hermite *R) { GEN d = R->s(data,1); long i, l = lg(ops); for (i = 1; i < l; i++) { GEN X, op = gel(ops,i); switch (typ(op)) { case t_VECSMALL: if (perm_sign(op) < 0) d = R->neg(data,d); break; case t_VEC: switch (lg(op)) { case 2: d = R->neg(data,d); break; case 3: X = gel(op,2); switch (lg(gel(op,1))) { case 2: d = R->mul(data, d, X); d = R->red(data, d); break; case 4: { GEN A = gcoeff(X,1,1), B = gcoeff(X,1,2); GEN C = gcoeff(X,2,1), D = gcoeff(X,2,2); GEN AD = R->mul(data,A,D); GEN BC = R->mul(data,B,C); d = R->mul(data, d, R->add(data, AD, R->neg(data,BC))); d = R->red(data, d); break; } } break; } break; } } return d; } static int gen_is_inv(GEN x, void* data, const struct bb_hermite *R) { GEN u = R->unit(data, x); if (!u) return R->equal1(x); return R->equal1(gel(u,1)); } static long gen_last_inv_diago(GEN A, void* data, const struct bb_hermite *R) { long i,m,n,j; RgM_dimensions(A,&m,&n); for (i=1,j=n-m+1; i<=m; i++,j++) if (!gen_is_inv(gcoeff(A,i,j),data,R)) return i-1; return m; } static GEN /* remove_zerocols: 0 none, 1 until square, 2 all */ /* early abort: if not right-invertible, abort, return NULL, and set ops to the * noninvertible pivot */ gen_howell_i(GEN A, long remove_zerocols, long permute_zerocols, long early_abort, long only_triangular, GEN* ops, void *data, const struct bb_hermite *R) { pari_sp av = avma, av1; GEN H,U,piv=gen_0,u,q,a,perm,iszero,C,zero=R->s(data,0),d,g,r,op,one=R->s(data,1); long m,n,i,j,s,si,i2,si2,nbz,lim,extra,maxop=0,nbop=0,lastinv=0; int smallop; av1 = avma; RgM_dimensions(A,&m,&n); if (early_abort && n0 && si>extra; i--,si--) /* si = s+i */ { if (R->red) gcoeff(H,i,si) = R->red(data, gcoeff(H,i,si)); /* bottom-right diagonal */ for (j = extra+1; j < si; j++) { if (R->red) gcoeff(H,i,j) = R->red(data, gcoeff(H,i,j)); if (R->equal0(gcoeff(H,i,j))) continue; U = R->extgcd(data, gcoeff(H,i,j), gcoeff(H,i,si), &smallop); d = gel(U,1); U = gel(U,2); if (n>10) { /* normalize diagonal coefficient -> faster reductions on this row */ u = R->unit(data, d); if (u) { g = gel(u,1); u = gel(u,2); gcoeff(U,1,2) = R->mul(data, gcoeff(U,1,2), u); gcoeff(U,2,2) = R->mul(data, gcoeff(U,2,2), u); d = g; } } gen_elem(H, U, j, si, i-1, data, R); if (ops) { op = mkopU(j,si,U,data,R); if (op) { nbop++; gel(*ops, nbop) = op; } } gcoeff(H,i,j) = zero; gcoeff(H,i,si) = d; if (R->red && !smallop) { gen_redcol(gel(H,si), i-1, data, R); gen_redcol(gel(H,j), i-1, data, R); } } if (early_abort) { d = gcoeff(H,i,si); u = R->unit(data, d); if (u) d = gel(u,1); if (!R->equal1(d)) { if (ops) *ops = d; return NULL; } } if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"gen_howell[1]. i=%ld",i); gerepileall(av1,ops?2:1,&H,ops); } } if (!ops) lastinv = gen_last_inv_diago(H, data, R); /* put in reduced Howell form */ if (!only_triangular) { for (i=m,si=s+m; i>0; i--,si--) /* si = s+i */ { /* normalize diagonal coefficient */ if (i<=lastinv) /* lastinv>0 => !ops */ gcoeff(H,i,si) = one; else { u = R->unit(data,gcoeff(H,i,si)); if (u) { g = gel(u,1); u = gel(u,2); gel(H,si) = gen_rightmulcol(gel(H,si), u, i-1, 1, data, R); gcoeff(H,i,si) = g; if (R->red) gen_redcol(gel(H,si), i-1, data, R); if (ops) { op = mkopmul(si,u,R); if (op) { nbop++; gel(*ops,nbop) = op; } } } else if (R->red) gcoeff(H,i,si) = R->red(data, gcoeff(H,i,si)); } piv = gcoeff(H,i,si); /* reduce above diagonal */ if (!R->equal0(piv)) { C = gel(H,si); for (j=si+1; j<=n; j++) { if (i<=lastinv) /* lastinv>0 => !ops */ gcoeff(H,i,j) = zero; else { gcoeff(H,i,j) = R->red(data, gcoeff(H,i,j)); if (R->equal1(piv)) { q = gcoeff(H,i,j); r = zero; } else q = R->lquo(data, gcoeff(H,i,j), piv, &r); q = R->neg(data,q); gen_addrightmul(H, C, q, j, i-1, data, R); if (ops) { op = mkoptransv(j,si,q,data,R); if (op) { nbop++; gel(*ops,nbop) = op; } } gcoeff(H,i,j) = r; } } } /* ensure Howell property */ if (i>1) { a = R->rann(data, piv); if (!R->equal0(a)) { gel(H,1) = gen_rightmulcol(gel(H,si), a, i-1, 1, data, R); if (gel(H,1) == gel(H,si)) gel(H,1) = shallowcopy(gel(H,1)); /* in case rightmulcol cheated */ if (ops) { op = mkoptransv(1,si,a,data,R); if (op) { nbop++; gel(*ops,nbop) = op; } } for (i2=i-1,si2=s+i2; i2>0; i2--,si2--) { if (R->red) gcoeff(H,i2,1) = R->red(data, gcoeff(H,i2,1)); if (R->equal0(gcoeff(H,i2,1))) continue; if (R->red) gcoeff(H,i2,si2) = R->red(data, gcoeff(H,i2,si2)); if (R->equal0(gcoeff(H,i2,si2))) { swap(gel(H,1), gel(H,si2)); if (ops) { nbop++; gel(*ops,nbop) = mkopswap(1,si2); } continue; } U = R->extgcd(data, gcoeff(H,i2,1), gcoeff(H,i2,si2), &smallop); d = gel(U,1); U = gel(U,2); gen_elem(H, U, 1, si2, i2-1, data, R); if (ops) { op = mkopU(1,si2,U,data,R); if (op) { nbop++; gel(*ops,nbop) = op; } } gcoeff(H,i2,1) = zero; gcoeff(H,i2,si2) = d; if (R->red && !smallop) { gen_redcol(gel(H,si2), i2, data, R); gen_redcol(gel(H,1), i2-1, data, R); } } } } if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"gen_howell[2]. i=%ld",i); gerepileall(av1,ops?3:2,&H,&piv,ops); } } } if (R->red) for (j=1; j<=n; j++) { lim = maxss(0,m-n+j); gen_redcol(gel(H,j), lim, data, R); for (i=lim+1; i<=m; i++) gcoeff(H,i,j) = zero; } /* put zero columns first */ iszero = cgetg(n+1,t_VECSMALL); nbz = 0; for (i=1; i<=n; i++) { iszero[i] = gen_is_zerocol(gel(H,i), maxss(0,m-n+i), data, R); if (iszero[i]) nbz++; } j = 1; if (permute_zerocols) { perm = cgetg(n+1, t_VECSMALL); for (i=1; i<=n; i++) if (iszero[i]) { perm[j] = i; j++; } } else perm = cgetg(n-nbz+1, t_VECSMALL); for (i=1; i<=n; i++) if (!iszero[i]) { perm[j] = i; j++; } if (permute_zerocols || remove_zerocols==2) H = vecpermute(H, perm); if (permute_zerocols && remove_zerocols==2) H = vecslice(H, nbz+1, n); if (remove_zerocols==1) H = vecslice(H, s+1, n); if (permute_zerocols && ops) { nbop++; gel(*ops,nbop) = perm; } if (ops) { setlg(*ops, nbop+1); } /* should have nbop <= maxop */ return H; } static GEN gen_howell(GEN A, long remove_zerocols, long permute_zerocols, long early_abort, long only_triangular, GEN* ops, void *data, const struct bb_hermite *R) { pari_sp av = avma; GEN H = gen_howell_i(A, remove_zerocols, permute_zerocols, early_abort, only_triangular, ops, data, R); return gc_all(av, ops?2:1, &H, ops); } static GEN gen_matimage(GEN A, GEN* U, void *data, const struct bb_hermite *R) { GEN ops, H; if (U) { pari_sp av = avma, av1; long m, n, i, r, n2, pergc; RgM_dimensions(A,&m,&n); H = gen_howell_i(A, 2, 1, 0, 0, &ops, data, R); av1 = avma; r = lg(H)-1; *U = shallowmatconcat(mkvec2(gen_zeromat(n, maxss(0,m-n+1), data, R), gen_matid_hermite(n, data, R))); n2 = lg(*U)-1; pergc = maxss(m,n); for (i=1; i1) pari_warn(warnmem,"gen_matimage. i=%ld",i); gerepileall(av1,1,U); } } if (r0; j--) { while (R->equal0(gcoeff(H,i,j))) i--; piv = gcoeff(H,i,j); if (R->equal0(piv)) continue; gcoeff(K,j,j) = R->rann(data, piv); if (jneg(data, R->lquo(data, gcoeff(FK,1,j2-j), piv, NULL)); /* remainder has to be zero */ } } return K; } static GEN /* (H,ops) Howell form of A, n = number of columns of A, return a kernel of A */ gen_kernel_from_howell(GEN H, GEN ops, long n, void *data, const struct bb_hermite *R) { pari_sp av; GEN K, KH, zC; long m, r, n2, nbz, i, o, extra, j; RgM_dimensions(H,&m,&r); if (!r) return gen_matid_hermite(n, data, R); /* zerology: what if 0==1 in R? */ n2 = maxss(n,m+1); extra = n2-n; nbz = n2-r; /* compute kernel of augmented matrix */ KH = gen_kernel_howell(H, data, R); zC = gen_zerocol(nbz, data, R); K = cgetg(nbz+r+1, t_MAT); for (i=1; i<=nbz; i++) gel(K,i) = gen_colei(nbz+r, i, data, R); for (i=1; i<=r; i++) gel(K,nbz+i) = shallowconcat(zC, gel(KH,i)); for (i=1; i0; o--) gen_leftapply(gel(K,i), gel(ops,o), data, R); gen_redcol(gel(K,i), nbz+r, data, R); gerepileall(av, 1, &gel(K,i)); } /* deduce kernel of original matrix */ K = rowpermute(K, cyclic_perm(n2,extra)); K = gen_howell_i(K, 2, 0, 0, 0, NULL, data, R); for (j=lg(K)-1, i=n2; j>0; j--) { while (R->equal0(gcoeff(K,i,j))) i--; if (i<=n) return matslice(K, 1, n, 1, j); } return cgetg(1,t_MAT); } /* not GC-clean */ static GEN gen_kernel(GEN A, GEN* im, void *data, const struct bb_hermite *R) { pari_sp av = avma; long n = lg(A)-1; GEN H, ops, K; H = gen_howell_i(A, 2, 1, 0, 0, &ops, data, R); gerepileall(av,2,&H,&ops); K = gen_kernel_from_howell(H, ops, n, data, R); if (im) *im = H; return K; } /* right inverse, not GC-clean */ static GEN gen_inv(GEN A, void* data, const struct bb_hermite *R) { pari_sp av; GEN ops, H, U, un=R->s(data,1); long m,n,j,o,n2; RgM_dimensions(A,&m,&n); av = avma; H = gen_howell_i(A, 0, 0, 1, 0, &ops, data, R); if (!H) pari_err_INV("gen_inv", ops); n2 = lg(H)-1; ops = gerepilecopy(av,ops); /* get rid of H */ U = gen_zeromat(n2, m, data, R); for (j=1; j<=m; j++) gcoeff(U,j+n2-m,j) = un; for (j=1; j<=m; j++) { av = avma; for (o=lg(ops)-1; o>0; o--) gen_leftapply(gel(U,j), gel(ops,o), data, R); gen_redcol(gel(U,j), n2, data, R); gerepileall(av, 1, &gel(U,j)); } if (n2>n) U = rowslice(U, n2-n+1, n2); return U; } /* H true Howell form (no zero columns). Compute Z = Y - HX canonical representative of R^m mod H(R^n) */ static GEN gen_reduce_mod_howell(GEN H, GEN Y, GEN *X, void* data, const struct bb_hermite *R) { pari_sp av = avma; long m,n,i,j; GEN Z, q, r, C; RgM_dimensions(H,&m,&n); if (X) *X = gen_zerocol(n,data,R); Z = shallowcopy(Y); i = m; for (j=n; j>0; j--) { while (R->equal0(gcoeff(H,i,j))) i--; q = R->lquo(data, gel(Z,i), gcoeff(H,i,j), &r); gel(Z,i) = r; C = gen_rightmulcol(gel(H,j), R->neg(data,q), i, 0, data, R); if (C) gen_addcol(Z, C, i-1, data, R); if (X) gel(*X,j) = q; } gen_redcol(Z, lg(Z)-1, data, R); return gc_all(av, X?2:1, &Z, X); } /* H: Howell form of A */ /* (m,n): dimensions of original matrix A */ /* return NULL if no solution */ static GEN gen_solve_from_howell(GEN H, GEN ops, long m, long n, GEN Y, void* data, const struct bb_hermite *R) { pari_sp av = avma; GEN Z, X; long n2, mH, nH, i; RgM_dimensions(H,&mH,&nH); n2 = maxss(n,m+1); Z = gen_reduce_mod_howell(H, Y, &X, data, R); if (!gen_is_zerocol(Z,m,data,R)) { set_avma(av); return NULL; } X = shallowconcat(zerocol(n2-nH),X); for (i=lg(ops)-1; i>0; i--) gen_leftapply(X, gel(ops,i), data, R); X = vecslice(X, n2-n+1, n2); gen_redcol(X, n, data, R); return gerepilecopy(av, X); } /* return NULL if no solution, not GC-clean */ static GEN gen_solve(GEN A, GEN Y, GEN* K, void* data, const struct bb_hermite *R) { GEN H, ops, X; long m,n; RgM_dimensions(A,&m,&n); if (!n) m = lg(Y)-1; H = gen_howell_i(A, 2, 1, 0, 0, &ops, data, R); X = gen_solve_from_howell(H, ops, m, n, Y, data, R); if (!X) return NULL; if (K) *K = gen_kernel_from_howell(H, ops, n, data, R); return X; } GEN matimagemod(GEN A, GEN d, GEN* U) { void *data; const struct bb_hermite* R; if (typ(A)!=t_MAT || !RgM_is_ZM(A)) pari_err_TYPE("matimagemod", A); if (typ(d)!=t_INT) pari_err_TYPE("matimagemod", d); if (signe(d)<=0) pari_err_DOMAIN("matimagemod", "d", "<=", gen_0, d); if (equali1(d)) return cgetg(1,t_MAT); R = get_Fp_hermite(&data, d); return gen_matimage(A, U, data, R); } /* for testing purpose */ /* GEN ZM_hnfmodid2(GEN A, GEN d) { pari_sp av = avma; void *data; long i; const struct bb_hermite* R = get_Fp_hermite(&data, d); GEN H; if (typ(A)!=t_MAT || !RgM_is_ZM(A)) pari_err_TYPE("ZM_hnfmodid2", A); if (typ(d)!=t_INT) pari_err_TYPE("ZM_hnfmodid2", d); H = gen_howell_i(A, 1, 0, 0, 0, NULL, data, R); for (i=1; i0, not GC-clean */ static GEN matsolvemod_finite(GEN M, GEN D, GEN Y, long flag) { void *data; const struct bb_hermite* R; GEN X, K, d; long m, n; RgM_dimensions(M,&m,&n); if (typ(D)==t_COL) { /* create extra variables for the D[i] */ GEN MD; long i, i2, extra = 0; d = gen_1; for (i=1; i 0) return caract_const(avma, A, v, degpol(T)); if (varncmp(vx, vp) < 0) pari_err_PRIORITY("charpoly", x, "<", vp); return RgXQ_charpoly(A, T, v); } case t_MAT: lx=lg(x); if (lx==1) return pol_1(v); if (lgcols(x) != lx) break; return NULL; } pari_err_TYPE("easychar",x); return NULL; /* LCOV_EXCL_LINE */ } /* compute charpoly by mapping to Fp first, return lift to Z */ static GEN RgM_Fp_charpoly(GEN x, GEN p, long v) { GEN T; if (lgefint(p) == 3) { ulong pp = itou(p); T = Flm_charpoly_i(RgM_to_Flm(x, pp), pp); T = Flx_to_ZX(T); } else T = FpM_charpoly(RgM_to_FpM(x, p), p); setvarn(T, v); return T; } GEN charpoly(GEN x, long v) { GEN T, p = NULL; long prec; if ((T = easychar(x,v))) return T; switch(RgM_type(x, &p,&T,&prec)) { case t_INT: T = ZM_charpoly(x); setvarn(T, v); break; case t_INTMOD: if (!BPSW_psp(p)) T = carberkowitz(x, v); else { pari_sp av = avma; T = RgM_Fp_charpoly(x,p,v); T = gerepileupto(av, FpX_to_mod(T,p)); } break; case t_REAL: case t_COMPLEX: case t_PADIC: T = carhess(x, v); break; default: T = carberkowitz(x, v); } return T; } /* We possibly worked with an "invalid" polynomial p, satisfying * varn(p) > gvar2(p). Fix this. */ static GEN fix_pol(pari_sp av, GEN p) { long w = gvar2(p), v = varn(p); if (w == v) pari_err_PRIORITY("charpoly", p, "=", w); if (varncmp(w,v) < 0) p = gerepileupto(av, poleval(p, pol_x(v))); return p; } GEN caract(GEN x, long v) { pari_sp av = avma; GEN T, C, x_k, Q; long k, n; if ((T = easychar(x,v))) return T; n = lg(x)-1; if (n == 1) return fix_pol(av, deg1pol(gen_1, gneg(gcoeff(x,1,1)), v)); x_k = pol_x(v); /* to be modified in place */ T = scalarpol(det(x), v); C = utoineg(n); Q = pol_x(v); for (k=1; k<=n; k++) { GEN mk = utoineg(k), d; gel(x_k,2) = mk; d = det(RgM_Rg_add_shallow(x, mk)); T = RgX_add(RgX_mul(T, x_k), RgX_Rg_mul(Q, gmul(C, d))); if (k == n) break; Q = RgX_mul(Q, x_k); C = diviuexact(mulsi(k-n,C), k+1); /* (-1)^k binomial(n,k) */ } return fix_pol(av, RgX_Rg_div(T, mpfact(n))); } /* C = charpoly(x, v) */ static GEN RgM_adj_from_char(GEN x, long v, GEN C) { if (varn(C) != v) /* problem with variable priorities */ { C = gdiv(gsub(C, gsubst(C, v, gen_0)), pol_x(v)); if (odd(lg(x))) C = RgX_neg(C); /* even dimension */ return gsubst(C, v, x); } else { C = RgX_shift_shallow(C, -1); if (odd(lg(x))) C = RgX_neg(C); /* even dimension */ return RgX_RgM_eval(C, x); } } /* assume x square matrice */ static GEN mattrace(GEN x) { long i, lx = lg(x); GEN t; if (lx < 3) return lx == 1? gen_0: gcopy(gcoeff(x,1,1)); t = gcoeff(x,1,1); for (i = 2; i < lx; i++) t = gadd(t, gcoeff(x,i,i)); return t; } static int bad_char(GEN q, long n) { forprime_t S; ulong p; if (!signe(q)) return 0; (void)u_forprime_init(&S, 2, n); while ((p = u_forprime_next(&S))) if (!umodiu(q, p)) return 1; return 0; } /* Using traces: return the characteristic polynomial of x (in variable v). * If py != NULL, the adjoint matrix is put there. */ GEN caradj(GEN x, long v, GEN *py) { pari_sp av, av0; long i, k, n; GEN T, y, t; if ((T = easychar(x, v))) { if (py) { if (typ(x) != t_MAT) pari_err_TYPE("matadjoint",x); *py = cgetg(1,t_MAT); } return T; } n = lg(x)-1; av0 = avma; T = cgetg(n+3,t_POL); T[1] = evalsigne(1) | evalvarn(v); gel(T,n+2) = gen_1; if (!n) { if (py) *py = cgetg(1,t_MAT); return T; } av = avma; t = gerepileupto(av, gneg(mattrace(x))); gel(T,n+1) = t; if (n == 1) { T = fix_pol(av0, T); if (py) *py = matid(1); return T; } if (n == 2) { GEN a = gcoeff(x,1,1), b = gcoeff(x,1,2); GEN c = gcoeff(x,2,1), d = gcoeff(x,2,2); av = avma; gel(T,2) = gerepileupto(av, gsub(gmul(a,d), gmul(b,c))); T = fix_pol(av0, T); if (py) { y = cgetg(3, t_MAT); gel(y,1) = mkcol2(gcopy(d), gneg(c)); gel(y,2) = mkcol2(gneg(b), gcopy(a)); *py = y; } return T; } /* l > 3 */ if (bad_char(residual_characteristic(x), n)) { /* n! not invertible in base ring */ T = charpoly(x, v); if (!py) return gerepileupto(av, T); *py = RgM_adj_from_char(x, v, T); return gc_all(av, 2, &T,py); } av = avma; y = RgM_shallowcopy(x); for (i = 1; i <= n; i++) gcoeff(y,i,i) = gadd(gcoeff(y,i,i), t); for (k = 2; k < n; k++) { GEN y0 = y; y = RgM_mul(y, x); t = gdivgs(mattrace(y), -k); for (i = 1; i <= n; i++) gcoeff(y,i,i) = gadd(gcoeff(y,i,i), t); y = gclone(y); gel(T,n-k+2) = gerepilecopy(av, t); av = avma; if (k > 2) gunclone(y0); } t = gmul(gcoeff(x,1,1),gcoeff(y,1,1)); for (i=2; i<=n; i++) t = gadd(t, gmul(gcoeff(x,1,i),gcoeff(y,i,1))); gel(T,2) = gerepileupto(av, gneg(t)); T = fix_pol(av0, T); if (py) *py = odd(n)? gcopy(y): RgM_neg(y); gunclone(y); return T; } GEN adj(GEN x) { GEN y; (void)caradj(x, fetch_var(), &y); (void)delete_var(); return y; } GEN adjsafe(GEN x) { const long v = fetch_var(); pari_sp av = avma; GEN C, A; if (typ(x) != t_MAT) pari_err_TYPE("matadjoint",x); if (lg(x) < 3) return gcopy(x); C = charpoly(x,v); A = RgM_adj_from_char(x, v, C); (void)delete_var(); return gerepileupto(av, A); } GEN matadjoint0(GEN x, long flag) { switch(flag) { case 0: return adj(x); case 1: return adjsafe(x); } pari_err_FLAG("matadjoint"); return NULL; /* LCOV_EXCL_LINE */ } /*******************************************************************/ /* */ /* Frobenius form */ /* */ /*******************************************************************/ /* The following section implement a mix of Ozello and Storjohann algorithms P. Ozello, doctoral thesis (in French): Calcul exact des formes de Jordan et de Frobenius d'une matrice, Chapitre 2 http://tel.archives-ouvertes.fr/tel-00323705 A. Storjohann, Diss. ETH No. 13922 Algorithms for Matrix Canonical Forms, Chapter 9 https://cs.uwaterloo.ca/~astorjoh/diss2up.pdf We use Storjohann Lemma 9.14 (step1, step2, step3) Ozello theorem 4, and Storjohann Lemma 9.18 */ /* Elementary transforms */ /* M <- U^(-1) M U, U = E_{i,j}(k) => U^(-1) = E{i,j}(-k) * P = U * P */ static void transL(GEN M, GEN P, GEN k, long i, long j) { long l, n = lg(M)-1; for(l=1; l<=n; l++) /* M[,j]-=k*M[,i] */ gcoeff(M,l,j) = gsub(gcoeff(M,l,j), gmul(gcoeff(M,l,i), k)); for(l=1; l<=n; l++) /* M[i,]+=k*M[j,] */ gcoeff(M,i,l) = gadd(gcoeff(M,i,l), gmul(gcoeff(M,j,l), k)); if (P) for(l=1; l<=n; l++) gcoeff(P,i,l) = gadd(gcoeff(P,i,l), gmul(gcoeff(P,j,l), k)); } /* j = a or b */ static void transD(GEN M, GEN P, long a, long b, long j) { long l, n; GEN k = gcoeff(M,a,b), ki; if (gequal1(k)) return; ki = ginv(k); n = lg(M)-1; for(l=1; l<=n; l++) if (l!=j) { gcoeff(M,l,j) = gmul(gcoeff(M,l,j), k); gcoeff(M,j,l) = (j==a && l==b)? gen_1: gmul(gcoeff(M,j,l), ki); } if (P) for(l=1; l<=n; l++) gcoeff(P,j,l) = gmul(gcoeff(P,j,l), ki); } static void transS(GEN M, GEN P, long i, long j) { long l, n = lg(M)-1; swap(gel(M,i), gel(M,j)); for (l=1; l<=n; l++) swap(gcoeff(M,i,l), gcoeff(M,j,l)); if (P) for (l=1; l<=n; l++) swap(gcoeff(P,i,l), gcoeff(P,j,l)); } /* Convert companion matrix to polynomial*/ static GEN minpoly_polslice(GEN M, long i, long j, long v) { long k, d = j+1-i; GEN P = cgetg(d+3,t_POL); P[1] = evalsigne(1)|evalvarn(v); for (k=0; k n) return j; transS(M, P, k, j+1); } transD(M, P, j+1, j, j+1); /* Now M[j+1,j] = 1 */ for (k = 1; k <= n; ++k) if (k != j+1 && !gequal0(gcoeff(M,k,j))) /* zero M[k,j] */ { transL(M, P, gneg(gcoeff(M,k,j)), k, j+1); gcoeff(M,k,j) = gen_0; /* avoid approximate 0 */ } if (gc_needed(av,1)) { if (DEBUGMEM > 1) pari_warn(warnmem,"RgM_minpoly stage 1: j0=%ld, j=%ld", j0, j); gerepilemat2_inplace(av, M, P); } } return n; } static void weakfrobenius_step2(GEN M, GEN P, long j) { pari_sp av = avma; long i, k, n = lg(M)-1; for(i=j; i>=2; i--) { for(k=j+1; k<=n; k++) if (!gequal0(gcoeff(M,i,k))) transL(M, P, gcoeff(M,i,k), i-1, k); if (gc_needed(av,1)) { if (DEBUGMEM > 1) pari_warn(warnmem,"RgM_minpoly stage 2: j=%ld, i=%ld", j, i); gerepilemat2_inplace(av, M, P); } } } static long weakfrobenius_step3(GEN M, GEN P, long j0, long j) { long i, k, n = lg(M)-1; if (j == n) return 0; if (gequal0(gcoeff(M, j0, j+1))) { for (k=j+2; k<=n; k++) if (!gequal0(gcoeff(M, j0, k))) break; if (k > n) return 0; transS(M, P, k, j+1); } transD(M, P, j0, j+1, j+1); for (i=j+2; i<=n; i++) if (!gequal0(gcoeff(M, j0, i))) transL(M, P, gcoeff(M, j0, i),j+1, i); return 1; } /* flag: 0 -> full Frobenius from , 1 -> weak Frobenius form */ static GEN RgM_Frobenius(GEN M, long flag, GEN *pt_P, GEN *pt_v) { pari_sp av = avma, av2, ltop; long n = lg(M)-1, eps, j0 = 1, nb = 0; GEN v, P; v = cgetg(n+1, t_VECSMALL); ltop = avma; P = pt_P ? matid(n): NULL; M = RgM_shallowcopy(M); av2 = avma; while (j0 <= n) { long j = weakfrobenius_step1(M, P, j0); weakfrobenius_step2(M, P, j); eps = weakfrobenius_step3(M, P, j0, j); if (eps == 0) { v[++nb] = j0; if (flag == 0 && nb > 1 && !minpoly_dvdslice(M, v[nb-1], j0, j)) { j = j0; j0 = v[nb-1]; nb -= 2; transL(M, P, gen_1, j, j0); /*lemma 9.18*/ } else j0 = j+1; } else transS(M, P, j0, j+1); /*theorem 4*/ if (gc_needed(av,1)) { if (DEBUGMEM > 1) pari_warn(warnmem,"weakfrobenius j0=%ld",j0); gerepilemat2_inplace(av2, M, P); } } fixlg(v, nb+1); if (pt_v) *pt_v = v; gerepileall(pt_v ? ltop: av, P? 2: 1, &M, &P); if (pt_P) *pt_P = P; return M; } static GEN RgM_minpoly(GEN M, long v) { pari_sp av = avma; GEN V, W; if (lg(M) == 1) return pol_1(v); M = RgM_Frobenius(M, 1, NULL, &V); W = minpoly_listpolslice(M, V, v); if (varncmp(v,gvar2(W)) >= 0) pari_err_PRIORITY("matfrobenius", M, "<=", v); return gerepileupto(av, RgX_normalize(glcm0(W, NULL))); } GEN Frobeniusform(GEN V, long n) { long i, j, k; GEN M = zeromatcopy(n,n); for (k=1,i=1;i n) pari_err_PREC("matfrobenius"); for (j=0; j 2) pari_err_FLAG("matfrobenius"); switch (flag) { case 0: return RgM_Frobenius(M, 0, NULL, NULL); case 1: { pari_sp av = avma; GEN V, W, F; F = RgM_Frobenius(M, 0, NULL, &V); W = minpoly_listpolslice(F, V, v); if (varncmp(v, gvar2(W)) >= 0) pari_err_PRIORITY("matfrobenius", M, "<=", v); return gerepileupto(av, W); } case 2: { GEN P, F, R = cgetg(3, t_VEC); F = RgM_Frobenius(M, 0, &P, NULL); gel(R,1) = F; gel(R,2) = P; return R; } default: pari_err_FLAG("matfrobenius"); } return NULL; /*LCOV_EXCL_LINE*/ } /*******************************************************************/ /* */ /* MINIMAL POLYNOMIAL */ /* */ /*******************************************************************/ static GEN RgXQ_minpoly_naive(GEN y, GEN P) { long n = lgpol(P); GEN M = ker(RgXQ_matrix_pow(y,n,n,P)); return content(RgM_to_RgXV(M,varn(P))); } static GEN RgXQ_minpoly_FpXQ(GEN x, GEN y, GEN p) { pari_sp av = avma; GEN r; if (lgefint(p) == 3) { ulong pp = uel(p, 2); r = Flx_to_ZX_inplace(Flxq_minpoly(RgX_to_Flx(x, pp), RgX_to_Flx(y, pp), pp)); } else r = FpXQ_minpoly(RgX_to_FpX(x, p), RgX_to_FpX(y, p), p); return gerepileupto(av, FpX_to_mod(r, p)); } static GEN RgXQ_minpoly_FpXQXQ(GEN x, GEN S, GEN pol, GEN p) { pari_sp av = avma; GEN r; GEN T = RgX_to_FpX(pol, p); if (signe(T)==0) pari_err_OP("minpoly",x,S); if (lgefint(p) == 3) { ulong pp = uel(p, 2); GEN Tp = ZX_to_Flx(T, pp); r = FlxX_to_ZXX(FlxqXQ_minpoly(RgX_to_FlxqX(x, Tp, pp), RgX_to_FlxqX(S, Tp, pp), Tp, pp)); } else r = FpXQXQ_minpoly(RgX_to_FpXQX(x, T, p), RgX_to_FpXQX(S, T, p), T, p); return gerepileupto(av, FpXQX_to_mod(r, T, p)); } #define code(t1,t2) ((t1 << 6) | t2) static GEN RgXQ_minpoly_fast(GEN x, GEN y) { GEN p, pol; long pa; long t = RgX_type2(x,y, &p,&pol,&pa); switch(t) { case t_INTMOD: return RgXQ_minpoly_FpXQ(x, y, p); case t_FFELT: return FFXQ_minpoly(x, y, pol); case code(t_POLMOD, t_INTMOD): return RgXQ_minpoly_FpXQXQ(x, y, pol, p); default: return NULL; } } #undef code /* return caract(Mod(x,T)) in variable v */ GEN RgXQ_minpoly(GEN x, GEN T, long v) { pari_sp av = avma; GEN R = RgXQ_minpoly_fast(x,T); if (R) { setvarn(R, v); return R; } if (!issquarefree(T)) { R = RgXQ_minpoly_naive(x, T); setvarn(R,v); return R; } R = RgXQ_charpoly(x, T, v); return gerepileupto(av, RgX_div(R,RgX_gcd(R, RgX_deriv(R)))); } static GEN easymin(GEN x, long v) { GEN G, R, dR; long tx = typ(x); if (tx == t_FFELT) { R = FpX_to_mod(FF_minpoly(x), FF_p_i(x)); setvarn(R,v); return R; } if (tx == t_POLMOD) { GEN a = gel(x,2), b = gel(x,1); if (degpol(b)==0) return pol_1(v); if (typ(a) != t_POL || varn(a) != varn(b)) { if (varncmp(gvar(a), v) <= 0) pari_err_PRIORITY("minpoly", x, "<", v); return deg1pol(gen_1, gneg_i(a), v); } return RgXQ_minpoly(a, b, v); } R = easychar(x, v); if (!R) return NULL; dR = RgX_deriv(R); if (!lgpol(dR)) return NULL; G = RgX_normalize(RgX_gcd(R,dR)); return RgX_div(R,G); } GEN minpoly(GEN x, long v) { pari_sp av = avma; GEN P; if (v < 0) v = 0; P = easymin(x,v); if (P) return gerepileupto(av,P); /* typ(x) = t_MAT */ set_avma(av); return RgM_minpoly(x,v); } /*******************************************************************/ /* */ /* HESSENBERG FORM */ /* */ /*******************************************************************/ static int relative0(GEN a, GEN a0, long bit) { if (gequal0(a)) return 1; if (gequal0(a0)) return gexpo(a) < bit; return (gexpo(a)-gexpo(a0) < bit); } /* x0 a nonempty square t_MAT that can be written to */ static GEN RgM_hess(GEN x0, long prec) { pari_sp av = avma; long lx = lg(x0), bit = prec? 8 - prec2nbits(prec): 0, m, i, j; GEN x = bit? RgM_shallowcopy(x0): x0; for (m=2; m E) { E = e; k = i; t = gcoeff(x,i,m-1); } } if (k != lx && relative0(t, gcoeff(x0,k,m-1), bit)) k = lx; i = k; } if (i == lx) continue; for (j=m-1; j1) pari_warn(warnmem,"hess, m = %ld", m); gerepileall(av,2, &x, &t); } } } return x; } GEN hess(GEN x) { pari_sp av = avma; GEN p = NULL, T = NULL; long prec, lx = lg(x); if (typ(x) != t_MAT) pari_err_TYPE("hess",x); if (lx == 1) return cgetg(1,t_MAT); if (lgcols(x) != lx) pari_err_DIM("hess"); switch(RgM_type(x, &p, &T, &prec)) { case t_REAL: case t_COMPLEX: break; default: prec = 0; } return gerepilecopy(av, RgM_hess(RgM_shallowcopy(x),prec)); } GEN Flm_hess(GEN x, ulong p) { long lx = lg(x), m, i, j; if (lx == 1) return cgetg(1,t_MAT); if (lgcols(x) != lx) pari_err_DIM("hess"); x = Flm_copy(x); for (m=2; m1) pari_warn(warnmem,"hess, m = %ld", m); gerepileall(av,2, &x, &t); } } } return gerepilecopy(av,x); } /* H in Hessenberg form */ static GEN RgM_hess_charpoly(GEN H, long v) { long n = lg(H), r, i; GEN y = cgetg(n+1, t_VEC); gel(y,1) = pol_1(v); for (r = 1; r < n; r++) { pari_sp av2 = avma; GEN z, a = gen_1, b = pol_0(v); for (i = r-1; i; i--) { a = gmul(a, gcoeff(H,i+1,i)); if (gequal0(a)) break; b = RgX_add(b, RgX_Rg_mul(gel(y,i), gmul(a,gcoeff(H,i,r)))); } z = RgX_sub(RgX_shift_shallow(gel(y,r), 1), RgX_Rg_mul(gel(y,r), gcoeff(H,r,r))); gel(y,r+1) = gerepileupto(av2, RgX_sub(z, b)); /* (X - H[r,r])y[r] - b */ } return gel(y,n); } GEN carhess(GEN x, long v) { pari_sp av; GEN y; if ((y = easychar(x,v))) return y; av = avma; y = RgM_hess_charpoly(hess(x), v); return fix_pol(av, y); } /* Bound for sup norm of charpoly(M/dM), M integral: let B = |M|oo / |dM|, * s = max_k binomial(n,k) (kB^2)^(k/2), * return ceil(log2(s)) */ static long charpoly_bound(GEN M, GEN dM, GEN N) { pari_sp av = avma; GEN B = itor(N, LOWDEFAULTPREC); GEN s = real_0(LOWDEFAULTPREC), bin, B2; long n = lg(M)-1, k; bin = gen_1; if (dM) B = divri(B, dM); B2 = sqrr(B); for (k = n; k >= (n+1)>>1; k--) { GEN t = mulri(powruhalf(mulur(k, B2), k), bin); if (abscmprr(t, s) > 0) s = t; bin = diviuexact(muliu(bin, k), n-k+1); } return gc_long(av, ceil(dbllog2(s))); } static GEN QM_charpoly_ZX_slice(GEN A, GEN dM, GEN P, GEN *mod) { pari_sp av = avma; long i, n = lg(P)-1; GEN H, T; if (n == 1) { ulong p = uel(P,1), dp = dM ? umodiu(dM, p): 1; GEN Hp, a = ZM_to_Flm(A, p); Hp = Flm_charpoly_i(a, p); if (dp != 1) Hp = Flx_rescale(Hp, Fl_inv(dp, p), p); Hp = gerepileupto(av, Flx_to_ZX(Hp)); *mod = utoipos(p); return Hp; } T = ZV_producttree(P); A = ZM_nv_mod_tree(A, P, T); H = cgetg(n+1, t_VEC); for(i=1; i <= n; i++) { ulong p = uel(P,i), dp = dM ? umodiu(dM, p): 1; gel(H,i) = Flm_charpoly(gel(A, i), p); if (dp != 1) gel(H,i) = Flx_rescale(gel(H,i), Fl_inv(dp, p), p); } H = nxV_chinese_center_tree(H, P, T, ZV_chinesetree(P,T)); *mod = gmael(T, lg(T)-1, 1); return gc_all(av, 2, &H, mod); } GEN QM_charpoly_ZX_worker(GEN P, GEN M, GEN dM) { GEN V = cgetg(3, t_VEC); gel(V,1) = QM_charpoly_ZX_slice(M, equali1(dM) ? NULL:dM, P, &gel(V,2)); return V; } /* Assume M a square ZM, dM integer. Return charpoly(M / dM) in Z[X] */ static GEN QM_charpoly_ZX_i(GEN M, GEN dM, long bound) { long n = lg(M)-1; forprime_t S; GEN worker = snm_closure(is_entry("_QM_charpoly_ZX_worker"), mkvec2(M, dM? dM: gen_1)); if (!n) return pol_1(0); if (bound < 0) { GEN N = ZM_supnorm(M); if (signe(N) == 0) return monomial(gen_1, n, 0); bound = charpoly_bound(M, dM, N) + 1; } if (DEBUGLEVEL>5) err_printf("ZM_charpoly: bound 2^%ld\n", bound); init_modular_big(&S); return gen_crt("QM_charpoly_ZX", worker, &S, dM, bound, 0, NULL, nxV_chinese_center, FpX_center); } GEN QM_charpoly_ZX_bound(GEN M, long bit) { pari_sp av = avma; GEN dM; M = Q_remove_denom(M, &dM); return gerepilecopy(av, QM_charpoly_ZX_i(M, dM, bit)); } GEN QM_charpoly_ZX(GEN M) { pari_sp av = avma; GEN dM; M = Q_remove_denom(M, &dM); return gerepilecopy(av, QM_charpoly_ZX_i(M, dM, -1)); } GEN ZM_charpoly(GEN M) { pari_sp av = avma; return gerepilecopy(av, QM_charpoly_ZX_i(M, NULL, -1)); } /*******************************************************************/ /* */ /* 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; if ((V = easychar(x,v))) return V; lx = lg(x); av0 = avma; V = cgetg(lx+1, t_VEC); S = cgetg(lx+1, t_VEC); C = cgetg(lx+1, t_VEC); Q = cgetg(lx+1, t_VEC); av = avma; gel(C,1) = gen_m1; gel(V,1) = gen_m1; for (i=2;i<=lx; i++) gel(C,i) = gel(Q,i) = gel(S,i) = gel(V,i) = gen_0; gel(V,2) = gcoeff(x,1,1); for (r = 2; r < lx; r++) { pari_sp av2; GEN t; for (i = 1; i < r; i++) gel(S,i) = gcoeff(x,i,r); gel(C,2) = gcoeff(x,r,r); for (i = 1; i < r-1; i++) { av2 = avma; t = gmul(gcoeff(x,r,1), gel(S,1)); for (j = 2; j < r; j++) t = gadd(t, gmul(gcoeff(x,r,j), gel(S,j))); gel(C,i+2) = gerepileupto(av2, t); for (j = 1; j < r; j++) { av2 = avma; t = gmul(gcoeff(x,j,1), gel(S,1)); for (k = 2; k < r; k++) t = gadd(t, gmul(gcoeff(x,j,k), gel(S,k))); gel(Q,j) = gerepileupto(av2, t); } for (j = 1; j < r; j++) gel(S,j) = gel(Q,j); } av2 = avma; t = gmul(gcoeff(x,r,1), gel(S,1)); for (j = 2; j < r; j++) t = gadd(t, gmul(gcoeff(x,r,j), gel(S,j))); gel(C,r+1) = gerepileupto(av2, t); if (gc_needed(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_reverse(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(conj_i(x),x))); case t_FFELT: y = cgetg(3, t_INTMOD); gel(y,1) = FF_p(x); gel(y,2) = FF_norm(x); return y; case t_POLMOD: { GEN T = gel(x,1), a = gel(x,2); if (typ(a) != t_POL || varn(a) != varn(T)) return gpowgs(a, degpol(T)); return RgXQ_norm(a, T); } case t_VEC: case t_COL: case t_MAT: y = cgetg_copy(x, &lx); for (i=1; i 0) return quadnorm(q); /* imaginary */ if (!prec) pari_err_TYPE("gnorml2", q); return sqrr(quadtofp(q, prec)); } static GEN gnorml2_i(GEN x, long prec) { pari_sp av; long i, lx; GEN s; switch(typ(x)) { case t_INT: return sqri(x); case t_REAL: return sqrr(x); case t_FRAC: return sqrfrac(x); case t_COMPLEX: av = avma; return gerepileupto(av, cxnorm(x)); case t_QUAD: av = avma; return gerepileupto(av, cxquadnorm(x,prec)); case t_POL: lx = lg(x)-1; x++; break; case t_VEC: case t_COL: case t_MAT: lx = lg(x); break; default: pari_err_TYPE("gnorml2",x); return NULL; /* LCOV_EXCL_LINE */ } if (lx == 1) return gen_0; av = avma; s = gnorml2(gel(x,1)); for (i=2; i1) pari_warn(warnmem,"gnorml2"); s = gerepileupto(av, s); } } return gerepileupto(av,s); } GEN gnorml2(GEN x) { return gnorml2_i(x, 0); } static GEN pnormlp(GEN,GEN,long); static GEN pnormlpvec(long i0, GEN x, GEN p, long prec) { pari_sp av = avma; long i, lx = lg(x); GEN s = gen_0; for (i=i0; i1) pari_warn(warnmem,"gnormlp, i = %ld", i); s = gerepileupto(av, s); } } return s; } /* (||x||_p)^p */ static GEN pnormlp(GEN x, GEN p, long prec) { switch(typ(x)) { case t_INT: case t_REAL: x = mpabs(x); break; case t_FRAC: x = absfrac(x); break; case t_COMPLEX: case t_QUAD: x = gabs(x,prec); break; case t_POL: return pnormlpvec(2, x, p, prec); case t_VEC: case t_COL: case t_MAT: return pnormlpvec(1, x, p, prec); default: pari_err_TYPE("gnormlp",x); } return gpow(x, p, prec); } GEN gnormlp(GEN x, GEN p, long prec) { pari_sp av = avma; if (!p || (typ(p) == t_INFINITY && inf_get_sign(p) > 0)) return gsupnorm(x, prec); if (gsigne(p) <= 0) pari_err_DOMAIN("normlp", "p", "<=", gen_0, p); if (is_scalar_t(typ(x))) return gabs(x, prec); if (typ(p) == t_INT) { ulong pp = itou_or_0(p); switch(pp) { case 1: return gnorml1(x, prec); case 2: x = gnorml2_i(x, prec); break; default: x = pnormlp(x, p, prec); break; } if (pp && typ(x) == t_INT && Z_ispowerall(x, pp, &x)) return gerepileuptoleaf(av, x); if (pp == 2) return gerepileupto(av, gsqrt(x, prec)); } else x = pnormlp(x, p, prec); x = gpow(x, ginv(p), prec); return gerepileupto(av, x); } GEN gnorml1(GEN x,long prec) { pari_sp av = avma; long lx,i; GEN s; switch(typ(x)) { case t_INT: case t_REAL: return mpabs(x); case t_FRAC: return absfrac(x); case t_COMPLEX: case t_QUAD: return gabs(x,prec); case t_POL: lx = lg(x); s = gen_0; for (i=2; i 0) *m = z; } /* compare |x| to *m or |x|^2 to *msq, whichever is easiest, and update * the pointed value if x is larger */ void gsupnorm_aux(GEN x, GEN *m, GEN *msq, long prec) { long i, lx; GEN z; switch(typ(x)) { case t_COMPLEX: z = cxnorm(x); store(z, msq); return; case t_QUAD: z = cxquadnorm(x,prec); store(z, msq); return; case t_INT: case t_REAL: z = mpabs(x); store(z,m); return; case t_FRAC: z = absfrac(x); store(z,m); return; case t_INFINITY: store(mkoo(), m); case t_POL: lx = lg(x)-1; x++; break; case t_VEC: case t_COL: case t_MAT: lx = lg(x); break; default: pari_err_TYPE("gsupnorm",x); return; /* LCOV_EXCL_LINE */ } for (i=1; i1) pari_warn(warnmem,"qfgaussred_positive"); b=gerepilecopy(av,b); } } return gerepilecopy(av,b); } GEN RgM_Cholesky(GEN M, long prec) { pari_sp av = avma; long i, j, lM = lg(M); GEN R, L = qfgaussred_positive(M); if (!L) return gc_NULL(av); R = cgetg(lM, t_MAT); for (j = 1; j < lM; j++) gel(R,j) = cgetg(lM, t_COL); for (i = 1; i < lM; i++) { GEN r = gsqrt(gcoeff(L,i,i), prec); for (j = 1; j < lM; j++) gcoeff(R, i, j) = (i == j) ? r: gmul(r, gcoeff(L, i, j)); } return gerepileupto(av, R); } /* Maximal pivot strategy: x is a suitable pivot if it is non zero and either * - an exact type, or * - it is maximal among remaining nonzero (t_REAL) pivots */ static int suitable(GEN x, long k, GEN *pp, long *pi) { long t = typ(x); switch(t) { case t_INT: return signe(x) != 0; case t_FRAC: return 1; case t_REAL: { GEN p = *pp; if (signe(x) && (!p || abscmprr(p, x) < 0)) { *pp = x; *pi = k; } return 0; } default: return !gequal0(x); } } /* Gauss reduction (arbitrary symmetric matrix, only the part above the * diagonal is considered). If signature is nonzero, return only the * signature, in which case gsigne() should be defined for elements of a. */ static GEN gaussred(GEN a, long signature) { GEN r, ak, al; pari_sp av = avma, av1; long n = lg(a), i, j, k, l, sp, sn, t; if (typ(a) != t_MAT) pari_err_TYPE("gaussred",a); if (n == 1) return signature? mkvec2(gen_0, gen_0): cgetg(1, t_MAT); if (lgcols(a) != n) pari_err_DIM("gaussred"); n--; r = const_vecsmall(n, 1); av1= avma; a = RgM_shallowcopy(a); t = n; sp = sn = 0; while (t) { long pind = 0; GEN invp, p = NULL; k=1; while (k<=n && (!r[k] || !suitable(gcoeff(a,k,k), k, &p, &pind))) k++; if (k > n && p) k = pind; if (k <= n) { p = gcoeff(a,k,k); invp = ginv(p); /* != 0 */ if (signature) { /* skip if (!signature): gsigne may fail ! */ if (gsigne(p) > 0) sp++; else sn++; } r[k] = 0; t--; ak = row(a, k); for (i=1; i<=n; i++) gcoeff(a,k,i) = r[i]? gmul(gcoeff(a,k,i), invp): gen_0; for (i=1; i<=n; i++) if (r[i]) { GEN c = gel(ak,i); /* - p * a[k,i] */ if (gequal0(c)) continue; for (j=1; j<=n; j++) if (r[j]) gcoeff(a,i,j) = gsub(gcoeff(a,i,j), gmul(c,gcoeff(a,k,j))); } gcoeff(a,k,k) = p; if (gc_needed(av1,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"gaussred (t = %ld)", t); a = gerepilecopy(av1, a); } } else { /* all remaining diagonal coeffs are currently 0 */ for (k=1; k<=n; k++) if (r[k]) { l=k+1; while (l<=n && (!r[l] || !suitable(gcoeff(a,k,l), l, &p, &pind))) l++; if (l > n && p) l = pind; if (l > n) continue; p = gcoeff(a,k,l); invp = ginv(p); sp++; sn++; r[k] = r[l] = 0; t -= 2; ak = row(a, k); al = row(a, l); for (i=1; i<=n; i++) if (r[i]) { gcoeff(a,k,i) = gmul(gcoeff(a,k,i), invp); gcoeff(a,l,i) = gmul(gcoeff(a,l,i), invp); } else { gcoeff(a,k,i) = gen_0; gcoeff(a,l,i) = gen_0; } for (i=1; i<=n; i++) if (r[i]) { /* c = a[k,i] * p, d = a[l,i] * p; */ GEN c = gel(ak,i), d = gel(al,i); for (j=1; j<=n; j++) if (r[j]) gcoeff(a,i,j) = gsub(gcoeff(a,i,j), gadd(gmul(gcoeff(a,l,j), c), gmul(gcoeff(a,k,j), d))); } for (i=1; i<=n; i++) if (r[i]) { GEN c = gcoeff(a,k,i), d = gcoeff(a,l,i); gcoeff(a,k,i) = gadd(c, d); gcoeff(a,l,i) = gsub(c, d); } gcoeff(a,k,l) = gen_1; gcoeff(a,l,k) = gen_m1; gcoeff(a,k,k) = gmul2n(p,-1); gcoeff(a,l,l) = gneg(gcoeff(a,k,k)); if (gc_needed(av1,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"gaussred"); a = gerepilecopy(av1, a); } break; } if (k > n) break; } } if (!signature) return gerepilecopy(av, a); set_avma(av); return mkvec2s(sp, sn); } GEN qfgaussred(GEN a) { return gaussred(a,0); } GEN qfgaussred2(GEN a) { pari_sp av = avma; GEN M = qfgaussred(a); long i, l = lg(M); GEN D = cgetg(l, t_VEC); for (i = 1; i < l; i++) { gel(D,i) = gcoeff(M,i,i); gcoeff(M,i,i) = gen_1; } return gerepilecopy(av, mkvec2(M,D)); } GEN qfgaussred0(GEN a, long flag) { switch (flag) { case 0: return qfgaussred(a); case 1: return qfgaussred2(a); default: pari_err_FLAG("qfgaussred"); } return NULL; /* LCOV_EXCL_LINE */ } GEN qfcholesky(GEN a, long prec) { GEN M; long n = lg(a); if (typ(a) != t_MAT) pari_err_TYPE("qfcholesky",a); if (n == 1) return cgetg(1, t_MAT); if (lgcols(a) != lg(a)) pari_err_DIM("qfcholesky"); M = RgM_Cholesky(a, prec); if (!M) return cgetg(1, t_VEC); return M; } 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 symmetric matrix. Return a vector [L, r]: * L = vector of eigenvalues * r = matrix of eigenvectors */ GEN jacobi(GEN a, long prec) { pari_sp av; long de, e, e1, e2, i, j, p, q, l = lg(a); GEN c, ja, L, r, L2, r2, unr; if (typ(a) != t_MAT) pari_err_TYPE("jacobi",a); ja = cgetg(3,t_VEC); L = cgetg(l,t_COL); gel(ja,1) = L; r = cgetg(l,t_MAT); gel(ja,2) = r; if (l == 1) return ja; if (lgcols(a) != l) pari_err_DIM("jacobi"); e1 = HIGHEXPOBIT-1; for (j=1; j e2) { e2 = e; p = i; q = j; } } } a = c; unr = real_1(prec); de = prec2nbits(prec); /* e1 = min expo(a[i,i]) * e2 = max expo(a[i,j]), i != j */ while (e1-e2 < de) { pari_sp av2 = avma; GEN x, y, t, c, s, u; /* compute attached 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; } } } set_avma(av2); } /* sort eigenvalues from smallest to largest */ c = indexsort(L); r2 = vecpermute(r, c); for (i=1; i Z-modules **/ /** **/ /*************************************************************************/ GEN matrixqz0(GEN x,GEN p) { if (typ(x) != t_MAT) pari_err_TYPE("matrixqz",x); if (!p) return QM_minors_coprime(x,NULL); if (typ(p) != t_INT) pari_err_TYPE("matrixqz",p); if (signe(p)>=0) return QM_minors_coprime(x,p); if (!RgM_is_QM(x)) pari_err_TYPE("matrixqz", x); if (absequaliu(p,1)) return QM_ImZ(x); /* p = -1 */ if (absequaliu(p,2)) return QM_ImQ(x); /* p = -2 */ pari_err_FLAG("QM_minors_coprime"); return NULL; /* LCOV_EXCL_LINE */ } GEN QM_minors_coprime(GEN x, GEN D) { pari_sp av = avma, av1; long i, j, m, n, lP; GEN P, y; n = lg(x)-1; if (!n) return gcopy(x); m = nbrows(x); if (n > m) pari_err_DOMAIN("QM_minors_coprime","n",">",strtoGENstr("m"),x); y = x; x = cgetg(n+1,t_MAT); for (j=1; j<=n; j++) { gel(x,j) = Q_primpart(gel(y,j)); RgV_check_ZV(gel(x,j), "QM_minors_coprime"); } /* x now a ZM */ if (n==m) { if (gequal0(ZM_det(x))) pari_err_DOMAIN("QM_minors_coprime", "rank(A)", "<",stoi(n),x); set_avma(av); return matid(n); } /* m > n */ if (!D || gequal0(D)) { pari_sp av2 = avma; D = ZM_detmult(shallowtrans(x)); if (is_pm1(D)) { set_avma(av2); return ZM_copy(x); } } P = gel(Z_factor(D), 1); lP = lg(P); av1 = avma; 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; FpM_center_inplace(M, p, pov2); N = ZM_Z_divexact(ZM_mul(x,M), p); for (j=1; j1) pari_warn(warnmem,"QM_minors_coprime, p = %Ps", p); x = gerepilecopy(av1, x); pov2 = shifti(p, -1); } } } return gerepilecopy(av, x); } static GEN QM_ImZ_all_i(GEN A, GEN *U, long remove, long hnf, long linindep) { GEN V = NULL, D; A = Q_remove_denom(A,&D); if (D) { long l, lA; V = matkermod(A,D,NULL); l = lg(V); lA = lg(A); if (l == 1) V = scalarmat_shallow(D, lA-1); else { if (l < lA) V = hnfmodid(V,D); A = ZM_Z_divexact(ZM_mul(A, V), D); } } if (!linindep && ZM_rank(A)==lg(A)-1) linindep = 1; if (hnf || !linindep) A = ZM_hnflll(A, U, remove); if (U && V) { if (hnf) *U = ZM_mul(V,*U); else *U = V; } return A; } GEN QM_ImZ_all(GEN x, GEN *U, long remove, long hnf) { pari_sp av = avma; x = QM_ImZ_all_i(x, U, remove, hnf, 0); return gc_all(av, U?2:1, &x, &U); } GEN QM_ImZ_hnfall(GEN x, GEN *U, long remove) { return QM_ImZ_all(x, U, remove, 1); } GEN QM_ImZ_hnf(GEN x) { return QM_ImZ_hnfall(x, NULL, 1); } GEN QM_ImZ(GEN x) { return QM_ImZ_all(x, NULL, 1, 0); } GEN QM_ImQ_all(GEN x, GEN *U, long remove, long hnf) { pari_sp av = avma; long i, n = lg(x), m; GEN ir, V, D, c, K = NULL; if (U) *U = matid(n-1); if (n==1) return gcopy(x); m = lg(gel(x,1)); x = RgM_shallowcopy(x); for (i=1; i * Fast Practical Lattice Reduction through Iterated Compression * * Keegan Ryan, University of California, San Diego * Nadia Heninger, University of California, San Diego. BA20230925 */ static long drop(GEN R) { long i, n = lg(R)-1; long s = 0, m = mpexpo(gcoeff(R, 1, 1)); for (i = 2; i <= n; ++i) { if (mpabscmp(gcoeff(R, i, i), gcoeff(R, i - 1, i - 1)) >= 0) { s += m - mpexpo(gcoeff(R, i - 1, i - 1)); m = mpexpo(gcoeff(R, i, i)); } } s += m - mpexpo(gcoeff(R, n, n)); return s; } static long potential(GEN R) { long i, n = lg(R)-1; long s = 0, mul = n-1;; for (i = 1; i <= n; i++, mul-=2) s += mul * mpexpo(gcoeff(R,i,i)); return s; } /* U upper-triangular invertible: * Bound on the exponent of the condition number of U. * Algo 8.13 in Higham, Accuracy and stability of numercal algorithms. */ static long condition_bound(GEN U, int lower) { long n = lg(U)-1, e, i, j; GEN y; pari_sp av = avma; y = cgetg(n+1, t_VECSMALL); e = y[n] = -gexpo(gcoeff(U,n,n)); for (i=n-1; i>0; i--) { long s = 0; for (j=i+1; j<=n; j++) s = maxss(s, (lower? gexpo(gcoeff(U,j,i)): gexpo(gcoeff(U,i,j))) + y[j]); y[i] = s - gexpo(gcoeff(U,i,i)); e = maxss(e, y[i]); } return gc_long(av, gexpo(U) + e); } static long gsisinv(GEN M) { long i, l = lg(M); for (i = 1; i < l; ++i) if (! signe(gmael(M, i, i))) return 0; return 1; } INLINE long nbits2prec64(long n) { return nbits2prec(((n+63)>>6)<<6); } static long spread(GEN R) { long i, n = lg(R)-1, m = mpexpo(gcoeff(R, 1, 1)), M = m; for (i = 2; i <= n; ++i) { long e = mpexpo(gcoeff(R, i, i)); if (e < m) m = e; if (e > M) M = e; } return M - m; } static long GS_extraprec(GEN L, int lower) { long C = condition_bound(L, lower), S = spread(L), n = lg(L)-1; return maxss(2*S+2*n, C-S-2*n); /* = 2*S + 2*n + maxss(0, C-3*S-4*n) */ } static GEN RgM_Cholesky_dynprec(GEN M) { pari_sp ltop = avma; GEN L; long minprec = lg(M) + 30, bitprec = minprec, prec; while (1) { long mbitprec; prec = nbits2prec64(bitprec); L = RgM_Cholesky(RgM_gtofp(M, prec), prec); /* upper-triangular */ if (!L) { bitprec *= 2; set_avma(ltop); continue; } mbitprec = minprec + GS_extraprec(L, 0); if (bitprec >= mbitprec) break; bitprec = maxss((4*bitprec)/3, mbitprec); set_avma(ltop); } return gerepilecopy(ltop, L); } static GEN gramschmidt_upper(GEN M) { long bitprec = lg(M)-1 + 31 + GS_extraprec(M, 0); return RgM_gtofp(M, nbits2prec64(bitprec)); } static GEN gramschmidt_dynprec(GEN M) { pari_sp ltop = avma; long minprec = lg(M) + 30, bitprec = minprec; if (ZM_is_upper(M)) return gramschmidt_upper(M); while (1) { GEN B, Q, L; long prec = nbits2prec64(bitprec), mbitprec; if (!QR_init(RgM_gtofp(M, prec), &B, &Q, &L, prec) || !gsisinv(L)) { bitprec *= 2; set_avma(ltop); continue; } mbitprec = minprec + GS_extraprec(L, 1); if (bitprec >= mbitprec) return gerepilecopy(ltop, shallowtrans(L)); bitprec = maxss((4*bitprec)/3, mbitprec); set_avma(ltop); } } /* return -T1 * round(T1^-1*(R1^-1*R2)*T3) */ static GEN sizered(GEN T1, GEN T3, GEN R1, GEN R2) { pari_sp ltop = avma; long e; return gerepileupto(ltop, ZM_mul(ZM_neg(T1), grndtoi(gmul(ZM_inv(T1,NULL), RgM_mul(RgM_mul(RgM_inv_upper(R1), R2), T3)), &e))); } static GEN flat(GEN M, long flag, GEN *pt_T, long *pt_s, long *pt_pot) { pari_sp ltop = avma; GEN R, R1, R2, R3, T1, T2, T3, T, S; long k = lg(M)-1, n = k>>1, n2 = k - n, m = n>>1; long keepfirst = flag & LLL_KEEP_FIRST, inplace = flag & LLL_INPLACE; /* for k = 3, we want n = 1; n2 = 2; m = 0 */ /* for k = 5, n = 2; n2 = 3; m = 1 */ R = gramschmidt_dynprec(M); R1 = matslice(R, 1, n, 1, n); R2 = matslice(R, 1, n, n + 1, k); R3 = matslice(R, n + 1, k, n + 1, k); T1 = lllfp(R1, 0.99, LLL_IM| LLL_UPPER| LLL_NOCERTIFY| (keepfirst ? LLL_KEEP_FIRST: 0)); T3 = lllfp(R3, 0.99, LLL_IM| LLL_UPPER| LLL_NOCERTIFY); T2 = sizered(T1, T3, R1, R2); T = shallowmatconcat(mkmat22(T1,T2,gen_0,T3)); M = ZM_mul(M, T); R = gramschmidt_dynprec(M); R3 = matslice(R, m + 1, m + n2, m + 1, m + n2); T3 = lllfp(R3, 0.99, LLL_IM| LLL_UPPER| LLL_NOCERTIFY); S = shallowmatconcat(diagonal( m == 0 ? mkvec2(T3, matid(k - m - n2)) : m+n2 == k ? mkvec2(matid(m), T3) : mkvec3(matid(m), T3, matid(k - m - n2)))); M = ZM_mul(M, S); if (!inplace) *pt_T = ZM_mul(T, S); *pt_s = drop(R); *pt_pot = potential(R); return gc_all(ltop, inplace ? 1: 2, &M, pt_T); } static GEN ZM_flatter(GEN M, long flag) { pari_sp ltop = avma, btop; long i, n = lg(M)-1; long s = -1, pot = LONG_MAX; GEN T; pari_timer ti; long lti = 1; long inplace = flag & LLL_INPLACE, cert = !(flag & LLL_NOCERTIFY); T = matid(n); if (DEBUGLEVEL>=3) { timer_start(&ti); if (cert) err_printf("flatter dim = %ld size = %ld\n", n, ZM_max_expi(M)); } btop = avma; for (i = 1;;i++) { long t, pot2; GEN U, M2 = flat(M, flag, &U, &t, &pot2); if (t==0) { s = t; break; } if (s >= 0) { if (s==t && pot>=pot2) break; if (s 20) { if (DEBUGLEVEL >= 3) err_printf("BACK:%ld:%ld:%g\n", n, i, s); break; } } if (DEBUGLEVEL>=3 && (cert || timer_get(&ti) > 1000)) { if (i==lti) timer_printf(&ti, "FLATTER, dim %ld, step %ld: \t slope=%0.10g \t pot=%0.10g", n, i, ((double)t)/n, ((double)pot2)/(n*(n+1))); else timer_printf(&ti, "FLATTER, dim %ld, steps %ld-%ld: \t slope=%0.10g \t pot=%0.10g", n, lti,i, ((double)t)/n, ((double)pot2)/(n*(n+1))); lti = i+1; } s = t; pot = pot2; M = M2; if (!inplace) T = ZM_mul(T, U); if (gc_needed(btop, 1)) gerepileall(btop, 2, &M, &T); } if (DEBUGLEVEL>=3 && (cert || timer_get(&ti) > 1000)) { if (i==lti) timer_printf(&ti, "FLATTER, dim %ld, final \t slope=%0.10g \t pot=%0.10g", n, ((double)s)/n, ((double)pot)/(n*(n+1))); else timer_printf(&ti, "FLATTER, dim %ld, steps %ld-final:\t slope=%0.10g \t pot=%0.10g", n, lti, ((double)s)/n, ((double)pot)/(n*(n+1))); } return gerepilecopy(ltop, inplace ? M: T); } static GEN ZM_flatter_rank(GEN M, long rank, long flag) { pari_timer ti; pari_sp ltop = avma; GEN T; long i, n = lg(M)-1, s, sm = LONG_MAX; long inplace = flag & LLL_INPLACE; if (rank == n) return ZM_flatter(M, flag); T = matid(n); if (DEBUGLEVEL>=3) timer_start(&ti); for (i = 1;; i++) { GEN S = ZM_flatter(vconcat(gshift(M,i),matid(n)), flag); s = expi(gnorml2(S)); if (DEBUGLEVEL>=3) timer_printf(&ti,"FLATTERRANK step %ld: %ld",i,s); if (ZM_isidentity(S) || s >= sm) break; sm = s; T = ZM_mul(T, S); M = ZM_mul(M, S); if (gc_needed(ltop, 1)) gerepileall(ltop, 2, &M, &T); } return gerepilecopy(ltop, inplace ? M: T); } static GEN flattergram_i(GEN M, long flag, long *pt_s) { pari_sp ltop = avma; GEN R, T; R = RgM_Cholesky_dynprec(M); *pt_s = drop(R); T = lllfp(R, 0.99, LLL_IM| LLL_UPPER| LLL_NOCERTIFY | (flag&LLL_KEEP_FIRST)); return gerepilecopy(ltop, T); } static GEN ZM_flattergram(GEN M, long flag) { pari_sp ltop = avma, btop; GEN T; long i, n = lg(M)-1; pari_timer ti; long s = -1; if (DEBUGLEVEL>=3) { timer_start(&ti); err_printf("FLATTERGRAM dim = %ld size = %ld\n", n, ZM_max_expi(M)); } btop = avma; T = matid(n); for (i = 1;; i++) { long t; GEN S = flattergram_i(M, flag, &t); t = expi(gnorml2(S)); if (t==0) { s = t; break; } if (s) { double st = s-t; if (st == 0) break; if (st < 0 && i > 20) { if (DEBUGLEVEL >= 3) err_printf("BACK:%ld:%ld:%0.10g\n", n, i, ((double)s)/n); break; } } T = ZM_mul(T, S); M = qf_ZM_apply(M, S); s = t; if (DEBUGLEVEL >= 3) timer_printf(&ti, "FLATTERGRAM, dim %ld step %ld, slope=%0.10g", n, i, ((double)s)/n); if (gc_needed(btop, 1)) gerepileall(btop, 2, &M, &T); } if (DEBUGLEVEL >= 3) timer_printf(&ti, "FLATTERGRAM, dim %ld, slope=%0.10g", n, ((double)s)/n); return gerepilecopy(ltop, T); } static GEN ZM_flattergram_rank(GEN M, long rank, long flag) { pari_timer ti; pari_sp ltop = avma; GEN T; long i, n = lg(M)-1; if (rank == n) return ZM_flattergram(M, flag); T = matid(n); if (DEBUGLEVEL>=3) timer_start(&ti); for (i = 1;; i++) { GEN S = ZM_flattergram(RgM_Rg_add(gshift(M, i), gen_1), flag); if (DEBUGLEVEL>=3) timer_printf(&ti,"FLATTERGRAMRANK step %ld: %ld",i,expi(gnorml2(S))); if (ZM_isidentity(S)) break; T = ZM_mul(T, S); M = qf_ZM_apply(M, S); if (gc_needed(ltop, 1)) gerepileall(ltop, 2, &M, &T); } return gerepilecopy(ltop, T); } static double pari_rint(double a) { #ifdef HAS_RINT return rint(a); #else const double two_to_52 = 4.5035996273704960e+15; double fa = fabs(a); double r = two_to_52 + fa; if (fa >= two_to_52) { r = a; } else { r = r - two_to_52; if (a < 0) r = -r; } return r; #endif } /* 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) { if (lg(x) == 1) { /* dim x = 0 */ if (! (flag & LLL_ALL)) return cgetg(1,t_MAT); retmkvec2(cgetg(1,t_MAT), cgetg(1,t_MAT)); } /* 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); retmkvec2(matid(1), cgetg(1,t_MAT)); } if (flag & LLL_INPLACE) return gcopy(x); if (flag & LLL_KER) return cgetg(1,t_MAT); if (flag & LLL_IM) return matid(1); retmkvec2(cgetg(1,t_MAT), (flag & LLL_GRAM)? gcopy(x): matid(1)); } /* vecslice(x,#x-k,#x) in place. Works for t_MAT, t_VEC/t_COL */ static GEN vectail_inplace(GEN x, long k) { if (!k) return x; x[k] = ((ulong)x[0] & ~LGBITS) | _evallg(lg(x) - k); return x + k; } /* k = dim Kernel */ static GEN lll_finish(GEN h, long k, long flag) { GEN g; if (!(flag & (LLL_IM|LLL_KER|LLL_ALL|LLL_INPLACE))) return h; if (flag & (LLL_IM|LLL_INPLACE)) return vectail_inplace(h, k); if (flag & LLL_KER) { setlg(h,k+1); return h; } g = vecslice(h,1,k); /* done first: vectail_inplace kills h */ return mkvec2(g, vectail_inplace(h, k)); } /* y * z * 2^e, e >= 0; y,z t_INT */ INLINE GEN mulshift(GEN y, GEN z, long e) { long ly = lgefint(y), lz; pari_sp av; GEN t; if (ly == 2) return gen_0; lz = lgefint(z); av = avma; (void)new_chunk(ly+lz+nbits2lg(e)); /* HACK */ t = mulii(z, y); set_avma(av); return shifti(t, e); } /* x - y * z * 2^e, e >= 0; x,y,z t_INT */ INLINE GEN submulshift(GEN x, GEN y, GEN z, long e) { long lx = lgefint(x), ly, lz; pari_sp av; GEN t; if (!e) return submulii(x, y, z); if (lx == 2) { t = mulshift(y, z, e); togglesign(t); return t; } ly = lgefint(y); if (ly == 2) return icopy(x); lz = lgefint(z); av = avma; (void)new_chunk(lx+ly+lz+nbits2lg(e)); /* HACK */ t = shifti(mulii(z, y), e); set_avma(av); return subii(x, t); } static void subzi(GEN *a, GEN b) { pari_sp av = avma; b = subii(*a, b); if (lgefint(b)<=lg(*a) && isonstack(*a)) { affii(b,*a); set_avma(av); } else *a = b; } static void addzi(GEN *a, GEN b) { pari_sp av = avma; b = addii(*a, b); if (lgefint(b)<=lg(*a) && isonstack(*a)) { affii(b,*a); set_avma(av); } else *a = b; } /* x - u*y * 2^e */ INLINE GEN submuliu2n(GEN x, GEN y, ulong u, long e) { pari_sp av; long ly = lgefint(y); if (ly == 2) return x; av = avma; (void)new_chunk(3+ly+lgefint(x)+nbits2lg(e)); /* HACK */ y = shifti(mului(u,y), e); set_avma(av); return subii(x, y); } /* *x -= u*y * 2^e */ INLINE void submulzu2n(GEN *x, GEN y, ulong u, long e) { pari_sp av; long ly = lgefint(y); if (ly == 2) return; av = avma; (void)new_chunk(3+ly+lgefint(*x)+nbits2lg(e)); /* HACK */ y = shifti(mului(u,y), e); set_avma(av); return subzi(x, y); } /* x + u*y * 2^e */ INLINE GEN addmuliu2n(GEN x, GEN y, ulong u, long e) { pari_sp av; long ly = lgefint(y); if (ly == 2) return x; av = avma; (void)new_chunk(3+ly+lgefint(x)+nbits2lg(e)); /* HACK */ y = shifti(mului(u,y), e); set_avma(av); return addii(x, y); } /* *x += u*y * 2^e */ INLINE void addmulzu2n(GEN *x, GEN y, ulong u, long e) { pari_sp av; long ly = lgefint(y); if (ly == 2) return; av = avma; (void)new_chunk(3+ly+lgefint(*x)+nbits2lg(e)); /* HACK */ y = shifti(mului(u,y), e); set_avma(av); return addzi(x, y); } /* n < 10; gerepileall supporting &NULL arguments. Maybe rename and export ? */ INLINE void gc_lll(pari_sp av, int n, ...) { int i, j; GEN *gptr[10]; size_t s; va_list a; va_start(a, n); for (i=j=0; i=0; j--) *gptr[j] = bin_copy((GENbin*)*gptr[j]); s = pari_mainstack->top - pari_mainstack->bot; /* size of saved objects ~ stacksize / 4 => overflow */ if (av - avma > (s >> 2)) { size_t t = avma - pari_mainstack->bot; av = avma; new_chunk((s + t) / sizeof(long)); set_avma(av); /* double */ } } /********************************************************************/ /** **/ /** FPLLL (adapted from D. Stehle's code) **/ /** **/ /********************************************************************/ /* Babai* and fplll* are a conversion to libpari API and data types of 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 t_REAL, |x| >= 1/2. Test whether |x| <= 3/2 */ static int absrsmall2(GEN x) { long e = expo(x), l, i; if (e < 0) return 1; if (e > 0 || (ulong)x[2] > (3UL << (BITS_IN_LONG-2))) return 0; /* line above assumes l > 2. OK since x != 0 */ l = lg(x); for (i = 3; i < l; i++) if (x[i]) return 0; return 1; } /* x t_REAL; test whether |x| <= 1/2 */ static int absrsmall(GEN x) { long e, l, i; if (!signe(x)) return 1; e = expo(x); if (e < -1) return 1; if (e > -1 || (ulong)x[2] > HIGHBIT) return 0; l = lg(x); for (i = 3; i < l; i++) if (x[i]) return 0; return 1; } static void rotate(GEN A, long k2, long k) { long i; GEN B = gel(A,k2); for (i = k2; i > k; i--) gel(A,i) = gel(A,i-1); gel(A,k) = B; } /************************* FAST version (double) ************************/ #define dmael(x,i,j) ((x)[i][j]) #define del(x,i) ((x)[i]) static double * cget_dblvec(long d) { return (double*) stack_malloc_align(d*sizeof(double), sizeof(double)); } static double ** cget_dblmat(long d) { return (double **) cgetg(d, t_VECSMALL); } static double itodbl_exp(GEN x, long *e) { pari_sp av = avma; GEN r = itor(x,DEFAULTPREC); *e = expo(r); setexpo(r,0); return gc_double(av, rtodbl(r)); } static double dbldotproduct(double *x, double *y, long n) { long i; double sum = del(x,1) * del(y,1); for (i=2; i<=n; i++) sum += del(x,i) * del(y,i); return sum; } static double dbldotsquare(double *x, long n) { long i; double sum = del(x,1) * del(x,1); for (i=2; i<=n; i++) sum += del(x,i) * del(x,i); return sum; } static long set_line(double *appv, GEN v, long n) { long i, maxexp = 0; pari_sp av = avma; GEN e = cgetg(n+1, t_VECSMALL); for (i = 1; i <= n; i++) { del(appv,i) = itodbl_exp(gel(v,i), e+i); if (e[i] > maxexp) maxexp = e[i]; } for (i = 1; i <= n; i++) del(appv,i) = ldexp(del(appv,i), e[i]-maxexp); set_avma(av); return maxexp; } static void dblrotate(double **A, long k2, long k) { long i; double *B = del(A,k2); for (i = k2; i > k; i--) del(A,i) = del(A,i-1); del(A,k) = B; } /* update G[kappa][i] from appB */ static void setG_fast(double **appB, long n, double **G, long kappa, long a, long b) { long i; for (i = a; i <= b; i++) dmael(G,kappa,i) = dbldotproduct(del(appB,kappa), del(appB,i), n); } /* update G[i][kappa] from appB */ static void setG2_fast(double **appB, long n, double **G, long kappa, long a, long b) { long i; for (i = a; i <= b; i++) dmael(G,i,kappa) = dbldotproduct(del(appB,kappa), del(appB,i), n); } const long EX0 = -2; /* uninitialized; any value less than expo(0.51) = -1 */ #ifdef LONG_IS_64BIT typedef long s64; #define addmuliu64_inplace addmuliu_inplace #define submuliu64_inplace submuliu_inplace #define submuliu642n submuliu2n #define addmuliu642n addmuliu2n #else typedef long long s64; typedef unsigned long long u64; INLINE GEN u64toi(u64 x) { GEN y; ulong h; if (!x) return gen_0; h = x>>32; if (!h) return utoipos(x); y = cgetipos(4); *int_LSW(y) = x&0xFFFFFFFF; *int_MSW(y) = x>>32; return y; } INLINE GEN u64toineg(u64 x) { GEN y; ulong h; if (!x) return gen_0; h = x>>32; if (!h) return utoineg(x); y = cgetineg(4); *int_LSW(y) = x&0xFFFFFFFF; *int_MSW(y) = x>>32; return y; } INLINE GEN addmuliu64_inplace(GEN x, GEN y, u64 u) { return addmulii(x, y, u64toi(u)); } INLINE GEN submuliu64_inplace(GEN x, GEN y, u64 u) { return submulii(x, y, u64toi(u)); } INLINE GEN addmuliu642n(GEN x, GEN y, u64 u, long e) { return submulshift(x, y, u64toineg(u), e); } INLINE GEN submuliu642n(GEN x, GEN y, u64 u, long e) { return submulshift(x, y, u64toi(u), e); } #endif /* Babai's Nearest Plane algorithm (iterative); see Babai() */ static int Babai_fast(pari_sp av, long kappa, GEN *pB, GEN *pU, double **mu, double **r, double *s, double **appB, GEN expoB, double **G, long a, long zeros, long maxG, double eta) { GEN B = *pB, U = *pU; const long n = nbrows(B), d = U ? lg(U)-1: 0; long k, aa = (a > zeros)? a : zeros+1; long emaxmu = EX0, emax2mu = EX0; s64 xx; int did_something = 0; /* N.B: we set d = 0 (resp. n = 0) to avoid updating U (resp. B) */ for (;;) { int go_on = 0; long i, j, emax3mu = emax2mu; if (gc_needed(av,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"Babai[1], a=%ld", aa); gc_lll(av,2,&B,&U); } /* Step2: compute the GSO for stage kappa */ emax2mu = emaxmu; emaxmu = EX0; for (j=aa; jzeros; j--) { double tmp = fabs(ldexp (dmael(mu,kappa,j), expoB[kappa]-expoB[j])); if (tmp>eta) { go_on = 1; break; } } /* Step3--5: compute the X_j's */ if (go_on) for (j=kappa-1; j>zeros; j--) { /* The code below seemingly handles U = NULL, but in this case d = 0 */ int e = expoB[j] - expoB[kappa]; double tmp = ldexp(dmael(mu,kappa,j), -e), atmp = fabs(tmp); /* tmp = Inf is allowed */ if (atmp <= .5) continue; /* size-reduced */ if (gc_needed(av,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"Babai[2], a=%ld, j=%ld", aa,j); gc_lll(av,2,&B,&U); } did_something = 1; /* we consider separately the case |X| = 1 */ if (atmp <= 1.5) { if (dmael(mu,kappa,j) > 0) { /* in this case, X = 1 */ for (k=zeros+1; k= 2 */ if (atmp < 9007199254740992.) { tmp = pari_rint(tmp); for (k=zeros+1; k 0) /* = xx */ { for (i=1; i<=n; i++) gmael(B,kappa,i) = submuliu64_inplace(gmael(B,kappa,i), gmael(B,j,i), xx); for (i=1; i<=d; i++) gmael(U,kappa,i) = submuliu64_inplace(gmael(U,kappa,i), gmael(U,j,i), xx); } else /* = -xx */ { for (i=1; i<=n; i++) gmael(B,kappa,i) = addmuliu64_inplace(gmael(B,kappa,i), gmael(B,j,i), -xx); for (i=1; i<=d; i++) gmael(U,kappa,i) = addmuliu64_inplace(gmael(U,kappa,i), gmael(U,j,i), -xx); } } else { int E; xx = (s64) ldexp(frexp(dmael(mu,kappa,j), &E), 53); E -= e + 53; if (E <= 0) { xx = xx << -E; for (k=zeros+1; k 0) /* = xx */ { for (i=1; i<=n; i++) gmael(B,kappa,i) = submuliu64_inplace(gmael(B,kappa,i), gmael(B,j,i), xx); for (i=1; i<=d; i++) gmael(U,kappa,i) = submuliu64_inplace(gmael(U,kappa,i), gmael(U,j,i), xx); } else /* = -xx */ { for (i=1; i<=n; i++) gmael(B,kappa,i) = addmuliu64_inplace(gmael(B,kappa,i), gmael(B,j,i), -xx); for (i=1; i<=d; i++) gmael(U,kappa,i) = addmuliu64_inplace(gmael(U,kappa,i), gmael(U,j,i), -xx); } } else { for (k=zeros+1; k 0) /* = xx */ { for (i=1; i<=n; i++) gmael(B,kappa,i) = submuliu642n(gmael(B,kappa,i), gmael(B,j,i), xx, E); for (i=1; i<=d; i++) gmael(U,kappa,i) = submuliu642n(gmael(U,kappa,i), gmael(U,j,i), xx, E); } else /* = -xx */ { for (i=1; i<=n; i++) gmael(B,kappa,i) = addmuliu642n(gmael(B,kappa,i), gmael(B,j,i), -xx, E); for (i=1; i<=d; i++) gmael(U,kappa,i) = addmuliu642n(gmael(U,kappa,i), gmael(U,j,i), -xx, E); } } } } if (!go_on) break; /* Anything happened? */ expoB[kappa] = set_line(del(appB,kappa), gel(B,kappa), n); setG_fast(appB, n, G, kappa, zeros+1, kappa-1); aa = zeros+1; } if (did_something) setG2_fast(appB, n, G, kappa, kappa, maxG); del(s,zeros+1) = dmael(G,kappa,kappa); /* the last s[kappa-1]=r[kappa][kappa] is computed only if kappa increases */ for (k=zeros+1; k<=kappa-2; k++) del(s,k+1) = del(s,k) - dmael(mu,kappa,k)*dmael(r,kappa,k); *pB = B; *pU = U; return 0; } static void update_alpha(GEN alpha, long kappa, long kappa2, long kappamax) { long i; for (i = kappa; i < kappa2; i++) if (kappa <= alpha[i]) alpha[i] = kappa; for (i = kappa2; i > kappa; i--) alpha[i] = alpha[i-1]; for (i = kappa2+1; i <= kappamax; i++) if (kappa < alpha[i]) alpha[i] = kappa; alpha[kappa] = kappa; } static void rotateG(GEN G, long kappa2, long kappa, long maxG, GEN Gtmp) { long i, j; for (i=1; i<=kappa2; i++) gel(Gtmp,i) = gmael(G,kappa2,i); for ( ; i<=maxG; i++) gel(Gtmp,i) = gmael(G,i,kappa2); for (i=kappa2; i>kappa; i--) { for (j=1; jkappa; i--) { for (j=1; j= 0) */ static long fplll_fast(GEN *pB, GEN *pU, double delta, double eta, long keepfirst) { pari_sp av; long kappa, kappa2, d, n, i, j, zeros, kappamax, maxG; double **mu, **r, *s, tmp, *Gtmp, **G, **appB; GEN alpha, expoB, B = *pB, U; long cnt = 0; d = lg(B)-1; n = nbrows(B); U = *pU; /* NULL if inplace */ G = cget_dblmat(d+1); appB = cget_dblmat(d+1); mu = cget_dblmat(d+1); r = cget_dblmat(d+1); s = cget_dblvec(d+1); for (j = 1; j <= d; j++) { del(mu,j) = cget_dblvec(d+1); del(r,j) = cget_dblvec(d+1); del(appB,j) = cget_dblvec(n+1); del(G,j) = cget_dblvec(d+1); for (i=1; i<=d; i++) dmael(G,j,i) = 0.; } expoB = cgetg(d+1, t_VECSMALL); for (i=1; i<=d; i++) expoB[i] = set_line(del(appB,i), gel(B,i), n); Gtmp = cget_dblvec(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 */ do { dmael(G,i,i) = dbldotsquare(del(appB,i),n); } while (dmael(G,i,i) <= 0 && (++i <=d)); zeros = i-1; /* all vectors B[i] with i <= zeros are zero vectors */ kappa = i; if (zeros < d) dmael(r,zeros+1,zeros+1) = dmael(G,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); maxG = kappamax = kappa; setG_fast(appB, n, G, kappa, zeros+1, kappa); } /* Step3: Call to the Babai algorithm, mu,r,s updated in place */ if (Babai_fast(av, kappa, &B,&U, mu,r,s, appB, expoB, G, alpha[kappa], zeros, maxG, eta)) { *pB=B; *pU=U; return -1; } tmp = ldexp(r[kappa-1][kappa-1] * delta, 2*(expoB[kappa-1]-expoB[kappa])); if ((keepfirst && kappa == 2) || tmp <= del(s,kappa-1)) { /* Step4: Success of Lovasz's condition */ alpha[kappa] = kappa; tmp = dmael(mu,kappa,kappa-1) * dmael(r,kappa,kappa-1); dmael(r,kappa,kappa) = del(s,kappa-1)- tmp; continue; } /* Step5: Find the right insertion index kappa, kappa2 = initial kappa */ if (DEBUGLEVEL>=4 && kappa==kappamax && del(s,kappa-1)!=0) if (++cnt > 20) { cnt = 0; err_printf("(%ld) ", 2*expoB[1] + dblexpo(del(s,1))); } kappa2 = kappa; do { kappa--; if (kappa= 0) return mantissa2nr(x, 0); *e = 0; return roundr_safe(x); } /* Babai's Nearest Plane algorithm (iterative); see Babai() */ static int Babai_heuristic(pari_sp av, long kappa, GEN *pB, GEN *pU, GEN mu, GEN r, GEN s, GEN appB, GEN G, long a, long zeros, long maxG, GEN eta, long prec) { GEN B = *pB, U = *pU; const long n = nbrows(B), d = U ? lg(U)-1: 0, bit = prec2nbits(prec); long k, aa = (a > zeros)? a : zeros+1; int did_something = 0; long emaxmu = EX0, emax2mu = EX0; /* N.B: we set d = 0 (resp. n = 0) to avoid updating U (resp. B) */ for (;;) { int go_on = 0; long i, j, emax3mu = emax2mu; if (gc_needed(av,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"Babai[1], a=%ld", aa); gc_lll(av,2,&B,&U); } /* Step2: compute the GSO for stage kappa */ emax2mu = emaxmu; emaxmu = EX0; for (j=aa; jzeros; j--) if (abscmprr(gmael(mu,kappa,j), eta) > 0) { go_on = 1; break; } /* Step3--5: compute the X_j's */ if (go_on) for (j=kappa-1; j>zeros; j--) { /* The code below seemingly handles U = NULL, but in this case d = 0 */ pari_sp btop; GEN tmp = gmael(mu,kappa,j); if (absrsmall(tmp)) continue; /* size-reduced */ if (gc_needed(av,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"Babai[2], a=%ld, j=%ld", aa,j); gc_lll(av,2,&B,&U); } btop = avma; did_something = 1; /* we consider separately the case |X| = 1 */ if (absrsmall2(tmp)) { if (signe(tmp) > 0) { /* in this case, X = 1 */ for (k=zeros+1; k= 2 */ if (expo(tmp) < BITS_IN_LONG) { ulong xx = roundr_safe(tmp)[2]; /* X fits in an ulong */ if (signe(tmp) > 0) /* = xx */ { for (k=zeros+1; k= 0) */ static long fplll_heuristic(GEN *pB, GEN *pU, double DELTA, double ETA, long keepfirst, long prec, long prec2) { pari_sp av, av2; long kappa, kappa2, d, i, j, zeros, kappamax, maxG; GEN mu, r, s, tmp, Gtmp, alpha, G, appB, B = *pB, U; GEN delta = dbltor(DELTA), eta = dbltor(ETA); long cnt = 0; d = lg(B)-1; U = *pU; /* NULL if inplace */ G = cgetg(d+1, t_MAT); mu = cgetg(d+1, t_MAT); r = cgetg(d+1, t_MAT); s = cgetg(d+1, t_VEC); appB = ZM_to_RM(B, prec2); for (j = 1; j <= d; j++) { GEN M = cgetg(d+1, t_COL), R = cgetg(d+1, t_COL), S = cgetg(d+1, t_COL); gel(mu,j)= M; gel(r,j) = R; gel(G,j) = S; gel(s,j) = cgetr(prec); for (i = 1; i <= d; i++) { gel(R,i) = cgetr(prec); gel(M,i) = cgetr(prec); gel(S,i) = cgetr(prec2); } } Gtmp = cgetg(d+1, t_VEC); alpha = cgetg(d+1, t_VECSMALL); av = avma; /* Step2: Initializing the main loop */ kappamax = 1; i = 1; maxG = d; /* later updated to kappamax */ do { affrr(RgV_dotsquare(gel(appB,i)), gmael(G,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) affrr(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); maxG = kappamax = kappa; setG_heuristic(appB, G, kappa, zeros+1, kappa); } /* Step3: Call to the Babai algorithm, mu,r,s updated in place */ if (Babai_heuristic(av, kappa, &B,&U, mu,r,s, appB, G, alpha[kappa], zeros, maxG, eta, prec)) { *pB = B; *pU = U; return -1; } 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)); set_avma(av2); continue; } /* Step5: Find the right insertion index kappa, kappa2 = initial kappa */ if (DEBUGLEVEL>=4 && kappa==kappamax && signe(gel(s,kappa-1))) if (++cnt > 20) { cnt = 0; err_printf("(%ld) ", expo(gel(s,1))); } kappa2 = kappa; do { kappa--; if (kappa < zeros+2 + (keepfirst ? 1: 0)) break; tmp = mulrr(gmael(r,kappa-1,kappa-1), delta); } while (cmprr(gel(s,kappa-1), tmp) <= 0 ); set_avma(av2); update_alpha(alpha, kappa, kappa2, kappamax); /* Step6: Update the mu's and r's */ rotate(mu,kappa2,kappa); rotate(r,kappa2,kappa); affrr(gel(s,kappa), gmael(r,kappa,kappa)); /* Step7: Update B, appB, U, G */ rotate(B,kappa2,kappa); rotate(appB,kappa2,kappa); if (U) rotate(U,kappa2,kappa); rotateG(G,kappa2,kappa, maxG, Gtmp); /* Step8: Prepare the next loop iteration */ if (kappa == zeros+1 && !signe(gmael(G,kappa,kappa))) { zeros++; kappa++; affrr(RgV_dotsquare(gel(appB,kappa)), gmael(G,kappa,kappa)); affrr(gmael(G,kappa,kappa), gmael(r,kappa,kappa)); } } *pB=B; *pU=U; return zeros; } /************************* PROVED version (t_INT) ***********************/ /* dpe inspired by dpe.h by Patrick Pelissier, Paul Zimmermann * https://gforge.inria.fr/projects/dpe/ */ typedef struct { double d; /* significand */ long e; /* exponent */ } dpe_t; #define Dmael(x,i,j) (&((x)[i][j])) #define Del(x,i) (&((x)[i])) static void dperotate(dpe_t **A, long k2, long k) { long i; dpe_t *B = A[k2]; for (i = k2; i > k; i--) A[i] = A[i-1]; A[k] = B; } static void dpe_normalize0(dpe_t *x) { int e; x->d = frexp(x->d, &e); x->e += e; } static void dpe_normalize(dpe_t *x) { if (x->d == 0.0) x->e = -LONG_MAX; else dpe_normalize0(x); } static GEN dpetor(dpe_t *x) { GEN r = dbltor(x->d); if (signe(r)==0) return r; setexpo(r, x->e-1); return r; } static void affdpe(dpe_t *y, dpe_t *x) { x->d = y->d; x->e = y->e; } static void affidpe(GEN y, dpe_t *x) { pari_sp av = avma; GEN r = itor(y, DEFAULTPREC); x->e = expo(r)+1; setexpo(r,-1); x->d = rtodbl(r); set_avma(av); } static void affdbldpe(double y, dpe_t *x) { x->d = (double)y; x->e = 0; dpe_normalize(x); } static void dpe_mulz(dpe_t *x, dpe_t *y, dpe_t *z) { z->d = x->d * y->d; if (z->d == 0.0) z->e = -LONG_MAX; else { z->e = x->e + y->e; dpe_normalize0(z); } } static void dpe_divz(dpe_t *x, dpe_t *y, dpe_t *z) { z->d = x->d / y->d; if (z->d == 0.0) z->e = -LONG_MAX; else { z->e = x->e - y->e; dpe_normalize0(z); } } static void dpe_negz(dpe_t *y, dpe_t *x) { x->d = - y->d; x->e = y->e; } static void dpe_addz(dpe_t *y, dpe_t *z, dpe_t *x) { if (y->e > z->e + 53) affdpe(y, x); else if (z->e > y->e + 53) affdpe(z, x); else { long d = y->e - z->e; if (d >= 0) { x->d = y->d + ldexp(z->d, -d); x->e = y->e; } else { x->d = z->d + ldexp(y->d, d); x->e = z->e; } dpe_normalize(x); } } static void dpe_subz(dpe_t *y, dpe_t *z, dpe_t *x) { if (y->e > z->e + 53) affdpe(y, x); else if (z->e > y->e + 53) dpe_negz(z, x); else { long d = y->e - z->e; if (d >= 0) { x->d = y->d - ldexp(z->d, -d); x->e = y->e; } else { x->d = ldexp(y->d, d) - z->d; x->e = z->e; } dpe_normalize(x); } } static void dpe_muluz(dpe_t *y, ulong t, dpe_t *x) { x->d = y->d * (double)t; x->e = y->e; dpe_normalize(x); } static void dpe_addmuluz(dpe_t *y, dpe_t *z, ulong t, dpe_t *x) { dpe_t tmp; dpe_muluz(z, t, &tmp); dpe_addz(y, &tmp, x); } static void dpe_submuluz(dpe_t *y, dpe_t *z, ulong t, dpe_t *x) { dpe_t tmp; dpe_muluz(z, t, &tmp); dpe_subz(y, &tmp, x); } static void dpe_submulz(dpe_t *y, dpe_t *z, dpe_t *t, dpe_t *x) { dpe_t tmp; dpe_mulz(z, t, &tmp); dpe_subz(y, &tmp, x); } static int dpe_cmp(dpe_t *x, dpe_t *y) { int sx = x->d < 0. ? -1: x->d > 0.; int sy = y->d < 0. ? -1: y->d > 0.; int d = sx - sy; if (d != 0) return d; else if (x->e > y->e) return (sx > 0) ? 1 : -1; else if (y->e > x->e) return (sx > 0) ? -1 : 1; else return (x->d < y->d) ? -1 : (x->d > y->d); } static int dpe_abscmp(dpe_t *x, dpe_t *y) { if (x->e > y->e) return 1; else if (y->e > x->e) return -1; else return (fabs(x->d) < fabs(y->d)) ? -1 : (fabs(x->d) > fabs(y->d)); } static int dpe_abssmall(dpe_t *x) { return (x->e <= 0) || (x->e == 1 && fabs(x->d) <= .75); } static int dpe_cmpmul(dpe_t *x, dpe_t *y, dpe_t *z) { dpe_t t; dpe_mulz(x,y,&t); return dpe_cmp(&t, z); } static dpe_t * cget_dpevec(long d) { return (dpe_t*) stack_malloc_align(d*sizeof(dpe_t), sizeof(dpe_t)); } static dpe_t ** cget_dpemat(long d) { return (dpe_t **) cgetg(d, t_VECSMALL); } static GEN dpeM_diagonal_shallow(dpe_t **m, long d) { long i; GEN y = cgetg(d+1,t_VEC); for (i=1; i<=d; i++) gel(y, i) = dpetor(Dmael(m,i,i)); return y; } static void affii_or_copy_gc(pari_sp av, GEN x, GEN *y) { long l = lg(*y); if (lgefint(x) <= l && isonstack(*y)) { affii(x,*y); set_avma(av); } else *y = gerepileuptoint(av, x); } /* *x -= u*y */ INLINE void submulziu(GEN *x, GEN y, ulong u) { pari_sp av; long ly = lgefint(y); if (ly == 2) return; av = avma; (void)new_chunk(3+ly+lgefint(*x)); /* HACK */ y = mului(u,y); set_avma(av); subzi(x, y); } /* *x += u*y */ INLINE void addmulziu(GEN *x, GEN y, ulong u) { pari_sp av; long ly = lgefint(y); if (ly == 2) return; av = avma; (void)new_chunk(3+ly+lgefint(*x)); /* HACK */ y = mului(u,y); set_avma(av); addzi(x, y); } /************************** PROVED version (dpe) *************************/ /* 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; long emaxmu = EX0, emax2mu = EX0; /* N.B: we set d = 0 (resp. n = 0) to avoid updating U (resp. B) */ d = U? lg(U)-1: 0; n = B? nbrows(B): 0; for (;;) { int go_on = 0; long i, j, emax3mu = emax2mu; if (gc_needed(av,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"Babai[1], a=%ld", aa); gc_lll(av,3,&G,&B,&U); } /* Step2: compute the GSO for stage kappa */ emax2mu = emaxmu; emaxmu = EX0; for (j=aa; je); } if (emax3mu != EX0 && emax3mu <= emax2mu + 5) /* precision too low */ { *pG = G; *pB = B; *pU = U; return 1; } for (j=kappa-1; j>zeros; j--) if (dpe_abscmp(Dmael(mu,kappa,j), eta) > 0) { go_on = 1; break; } /* Step3--5: compute the X_j's */ if (go_on) for (j=kappa-1; j>zeros; j--) { pari_sp btop; dpe_t *tmp = Dmael(mu,kappa,j); if (tmp->e < 0) continue; /* (essentially) size-reduced */ if (gc_needed(av,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"Babai[2], a=%ld, j=%ld", aa,j); gc_lll(av,3,&G,&B,&U); } /* we consider separately the case |X| = 1 */ if (dpe_abssmall(tmp)) { if (tmp->d > 0) { /* in this case, X = 1 */ for (k=zeros+1; k= 2 */ if (tmp->e < BITS_IN_LONG-1) { if (tmp->d > 0) { ulong xx = (ulong) pari_rint(ldexp(tmp->d, tmp->e)); /* X fits in an ulong */ for (k=zeros+1; kd, tmp->e)); /* X fits in an ulong */ for (k=zeros+1; ke - BITS_IN_LONG + 1; if (tmp->d > 0) { ulong xx = (ulong) pari_rint(ldexp(tmp->d, BITS_IN_LONG - 1)); for (k=zeros+1; kd, BITS_IN_LONG - 1)); for (k=zeros+1; k= 0) */ static long fplll_dpe(GEN *pG, GEN *pB, GEN *pU, GEN *pr, double DELTA, double ETA, long keepfirst) { pari_sp av; GEN Gtmp, alpha, G = *pG, B = *pB, U = *pU; long d, maxG, kappa, kappa2, i, j, zeros, kappamax, incgram = !G, cnt = 0; dpe_t delta, eta, **mu, **r, *s; affdbldpe(DELTA,&delta); affdbldpe(ETA,&eta); if (incgram) { /* incremental Gram matrix */ maxG = 2; d = lg(B)-1; G = zeromatcopy(d, d); } else maxG = d = lg(G)-1; mu = cget_dpemat(d+1); r = cget_dpemat(d+1); s = cget_dpevec(d+1); for (j = 1; j <= d; j++) { mu[j]= cget_dpevec(d+1); r[j] = cget_dpevec(d+1); } Gtmp = cgetg(d+1, t_VEC); alpha = cgetg(d+1, t_VECSMALL); av = avma; /* Step2: Initializing the main loop */ kappamax = 1; i = 1; do { if (incgram) gmael(G,i,i) = ZV_dotsquare(gel(B,i)); affidpe(gmael(G,i,i), Dmael(r,i,i)); } while (!signe(gmael(G,i,i)) && ++i <= d); zeros = i-1; /* all basis vectors b_i with i <= zeros are zero vectors */ kappa = i; 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 (incgram) { 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 */ if (Babai_dpe(av, kappa, &G,&B,&U, mu,r,s, alpha[kappa], zeros, maxG, &eta)) { *pG = incgram? NULL: G; *pB = B; *pU = U; return -1; } if ((keepfirst && kappa == 2) || dpe_cmpmul(Dmael(r,kappa-1,kappa-1), &delta, Del(s,kappa-1)) <= 0) { /* Step4: Success of Lovasz's condition */ alpha[kappa] = kappa; dpe_submulz(Del(s,kappa-1), Dmael(mu,kappa,kappa-1), Dmael(r,kappa,kappa-1), Dmael(r,kappa,kappa)); continue; } /* Step5: Find the right insertion index kappa, kappa2 = initial kappa */ if (DEBUGLEVEL>=4 && kappa==kappamax && Del(s,kappa-1)->d) if (++cnt > 20) { cnt = 0; err_printf("(%ld) ", Del(s,1)->e-1); } kappa2 = kappa; do { kappa--; if (kappa < zeros+2 + (keepfirst ? 1: 0)) break; } while (dpe_cmpmul(Dmael(r,kappa-1,kappa-1), &delta, Del(s,kappa-1)) >= 0); update_alpha(alpha, kappa, kappa2, kappamax); /* Step6: Update the mu's and r's */ dperotate(mu, kappa2, kappa); dperotate(r, kappa2, kappa); affdpe(Del(s,kappa), Dmael(r,kappa,kappa)); /* Step7: Update G, B, U */ if (U) rotate(U, kappa2, kappa); if (B) rotate(B, kappa2, kappa); rotateG(G,kappa2,kappa, maxG, Gtmp); /* Step8: Prepare the next loop iteration */ if (kappa == zeros+1 && !signe(gmael(G,kappa,kappa))) { zeros++; kappa++; affidpe(gmael(G,kappa,kappa), Dmael(r,kappa,kappa)); } } if (pr) *pr = dpeM_diagonal_shallow(r,d); *pG = G; *pB = B; *pU = U; return zeros; /* success */ } /************************** PROVED version (t_INT) *************************/ /* 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; const long n = B? nbrows(B): 0, d = U ? lg(U)-1: 0, bit = prec2nbits(prec); long emaxmu = EX0, emax2mu = EX0; /* N.B: we set d = 0 (resp. n = 0) to avoid updating U (resp. B) */ for (;;) { int go_on = 0; long i, j, emax3mu = emax2mu; if (gc_needed(av,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"Babai[1], a=%ld", aa); gc_lll(av,3,&G,&B,&U); } /* Step2: compute the GSO for stage kappa */ emax2mu = emaxmu; emaxmu = EX0; for (j=aa; jzeros; j--) if (abscmprr(gmael(mu,kappa,j), eta) > 0) { go_on = 1; break; } /* Step3--5: compute the X_j's */ if (go_on) for (j=kappa-1; j>zeros; j--) { pari_sp btop; GEN tmp = gmael(mu,kappa,j); if (absrsmall(tmp)) continue; /* size-reduced */ if (gc_needed(av,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"Babai[2], a=%ld, j=%ld", aa,j); gc_lll(av,3,&G,&B,&U); } btop = avma; /* we consider separately the case |X| = 1 */ if (absrsmall2(tmp)) { if (signe(tmp) > 0) { /* in this case, X = 1 */ for (k=zeros+1; k= 2 */ if (expo(tmp) < BITS_IN_LONG) { ulong xx = roundr_safe(tmp)[2]; /* X fits in an ulong */ if (signe(tmp) > 0) /* = xx */ { for (k=zeros+1; k= 0) */ static long fplll(GEN *pG, GEN *pB, GEN *pU, GEN *pr, double DELTA, double ETA, long keepfirst, long prec) { pari_sp av, av2; GEN mu, r, s, tmp, Gtmp, alpha, G = *pG, B = *pB, U = *pU; GEN delta = dbltor(DELTA), eta = dbltor(ETA); long d, maxG, kappa, kappa2, i, j, zeros, kappamax, incgram = !G, cnt = 0; if (incgram) { /* incremental Gram matrix */ maxG = 2; d = lg(B)-1; G = zeromatcopy(d, d); } else maxG = d = lg(G)-1; 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); } } Gtmp = cgetg(d+1, t_VEC); alpha = cgetg(d+1, t_VECSMALL); av = avma; /* Step2: Initializing the main loop */ kappamax = 1; i = 1; do { if (incgram) gmael(G,i,i) = ZV_dotsquare(gel(B,i)); affir(gmael(G,i,i), gmael(r,i,i)); } while (!signe(gmael(G,i,i)) && ++i <= d); zeros = i-1; /* all basis vectors b_i with i <= zeros are zero vectors */ kappa = i; 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 (incgram) { 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 */ if (Babai(av, kappa, &G,&B,&U, mu,r,s, alpha[kappa], zeros, maxG, eta, prec)) { *pG = incgram? NULL: G; *pB = B; *pU = U; return -1; } 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)); set_avma(av2); continue; } /* Step5: Find the right insertion index kappa, kappa2 = initial kappa */ if (DEBUGLEVEL>=4 && kappa==kappamax && signe(gel(s,kappa-1))) if (++cnt > 20) { cnt = 0; err_printf("(%ld) ", expo(gel(s,1))); } kappa2 = kappa; do { kappa--; if (kappa < zeros+2 + (keepfirst ? 1: 0)) break; tmp = mulrr(gmael(r,kappa-1,kappa-1), delta); } while (cmprr(gel(s,kappa-1), tmp) <= 0); set_avma(av2); update_alpha(alpha, kappa, kappa2, kappamax); /* Step6: Update the mu's and r's */ rotate(mu, kappa2, kappa); rotate(r, kappa2, kappa); affrr(gel(s,kappa), gmael(r,kappa,kappa)); /* Step7: Update G, B, U */ if (U) rotate(U, kappa2, kappa); if (B) rotate(B, kappa2, kappa); rotateG(G,kappa2,kappa, maxG, Gtmp); /* Step8: Prepare the next loop iteration */ if (kappa == zeros+1 && !signe(gmael(G,kappa,kappa))) { zeros++; kappa++; affir(gmael(G,kappa,kappa), gmael(r,kappa,kappa)); } } if (pr) *pr = RgM_diagonal_shallow(r); *pG = G; *pB = B; *pU = U; return zeros; /* success */ } /* do not support LLL_KER, LLL_ALL, LLL_KEEP_FIRST */ static GEN ZM2_lll_norms(GEN x, long flag, GEN *pN) { GEN a,b,c,d; GEN G, U; if (flag & LLL_GRAM) G = x; else G = gram_matrix(x); a = gcoeff(G,1,1); b = shifti(gcoeff(G,1,2),1); c = gcoeff(G,2,2); d = qfb_disc3(a,b,c); if (signe(d)>=0) return NULL; G = redimagsl2(mkqfb(a,b,c,d),&U); if (pN) (void) RgM_gram_schmidt(G, pN); if (flag & LLL_INPLACE) return ZM2_mul(x,U); return U; } static void fplll_flatter(GEN *pG, GEN *pB, GEN *pU, long rank, long flag) { if (!*pG) { GEN T = ZM_flatter_rank(*pB, rank, flag); if (*pU) { *pU = ZM_mul(*pU, T); *pB = ZM_mul(*pB, T); } else *pB = T; } else { GEN T, G = *pG; long i, j, l = lg(G); for (i = 1; i < l; i++) for(j = 1; j < i; j++) gmael(G,j,i) = gmael(G,i,j); T = ZM_flattergram_rank(G, rank, flag); if (*pU) *pU = ZM_mul(*pU, T); *pG = qf_ZM_apply(*pG, T); } } static GEN get_gramschmidt(GEN M, long rank) { GEN B, Q, L; long r = lg(M)-1, bitprec = 3*r + 30; long prec = nbits2prec64(bitprec); if (rank < r) M = vconcat(gshift(M,1), matid(r)); if (!QR_init(RgM_gtofp(M, prec), &B, &Q, &L, prec) || !gsisinv(L)) return NULL; return L; } static GEN get_gaussred(GEN M, long rank) { pari_sp ltop = avma; long r = lg(M)-1, bitprec = 3*r + 30, prec = nbits2prec64(bitprec); GEN R; if (rank < r) M = RgM_Rg_add(gshift(M, 1), gen_1); R = RgM_Cholesky(RgM_gtofp(M, prec), prec); if (!R) return NULL; return gerepilecopy(ltop, R); } /* Assume x a ZM, if pN != NULL, set it to Gram-Schmidt (squared) norms * The following modes are supported: * - flag & LLL_INPLACE: x a lattice basis, return x*U * - flag & LLL_GRAM: x a Gram matrix / else x a lattice basis; return * LLL base change matrix U [LLL_IM] * kernel basis [LLL_KER, nonreduced] * both [LLL_ALL] */ GEN ZM_lll_norms(GEN x, double DELTA, long flag, GEN *pN) { pari_sp av = avma; const double ETA = 0.51; const long keepfirst = flag & LLL_KEEP_FIRST; long p, zeros = -1, n = lg(x)-1, is_upper, is_lower, useflatter = 0, rank; GEN G, B, U, L = NULL; pari_timer T; long thre[]={31783,34393,20894,22525,13533,1928,672,671, 422,506,315,313,222,205,167,154,139,138, 110,120,98,94,81,75,74,64,74,74, 79,96,112,111,105,104,96,86,84,78,75,70,66,62,62,57,56,47,45,52,50,44,48,42,36,35,35,34,40,33,34,32,36,31, 38,38,40,38,38,37,35,31,34,36,34,32,34,32,28,27,25,31,25,27,28,26,25,21,21,25,25,22,21,24,24,22,21,23,22,22,22,22,21,24,21,22,19,20,19,20,19,19,19,18,19,18,18,20,19,20,18,19,18,21,18,20,18,18}; long thsn[]={23280,30486,50077,44136,78724,15690,1801,1611, 981,1359,978,1042,815,866,788,775,726,712, 626,613,548,564,474,481,504,447,453,508, 705,794,1008,946,767,898,886,763,842,757, 725,774,639,655,705,627,635,704,511,613, 583,595,568,640,541,640,567,540,577,584, 546,509,526,572,637,746,772,743,743,742,800,708,832,768,707,692,692,768,696,635,709,694,768,719,655,569,590,644,685,623,627,720,633,636,602,635,575,631,642,647,632,656,573,511,688,640,528,616,511,559,601,620,635,688,608,768,658,582,644,704,555,673,600,601,641,661,601,670}; if (n <= 1) return lll_trivial(x, flag); if (nbrows(x)==0) { if (flag & LLL_KER) return matid(n); if (flag & (LLL_INPLACE|LLL_IM)) return cgetg(1,t_MAT); retmkvec2(matid(n), cgetg(1,t_MAT)); } if (n==2 && nbrows(x)==2 && (flag&LLL_IM) && !keepfirst) { U = ZM2_lll_norms(x, flag, pN); if (U) return U; } if (flag & LLL_GRAM) { G = x; B = NULL; U = matid(n); is_upper = 0; is_lower = 0; } else { G = NULL; B = x; U = (flag & LLL_INPLACE)? NULL: matid(n); is_upper = (flag & LLL_UPPER) || ZM_is_upper(B); is_lower = !B || is_upper || keepfirst ? 0: ZM_is_lower(B); if (is_lower) L = RgM_flip(B); } rank = (flag&LLL_NOFLATTER) ? 0: ZM_rank(x); if (n > 2 && !(flag&LLL_NOFLATTER)) { GEN R = B ? (is_upper ? B : (is_lower ? L : get_gramschmidt(B, rank))) : get_gaussred(G, rank); if (R) { long spr = spread(R), sz = mpexpo(gsupnorm(R, DEFAULTPREC)), thr; if (DEBUGLEVEL>=5) err_printf("LLL: dim %ld, size %ld, spread %ld\n",n, sz, spr); if ((is_upper && ZM_is_knapsack(B)) || (is_lower && ZM_is_knapsack(L))) thr = thsn[minss(n-3,numberof(thsn)-1)]; else { thr = thre[minss(n-3,numberof(thre)-1)]; if (n>=10) sz = spr; } useflatter = sz >= thr; } else useflatter = 1; } else useflatter = 0; if(DEBUGLEVEL>=4) timer_start(&T); if (useflatter) { if (is_lower) { fplll_flatter(&G, &L, &U, rank, flag | LLL_UPPER); B = RgM_flop(L); if (U) U = RgM_flop(U); } else fplll_flatter(&G, &B, &U, rank, flag | (is_upper? LLL_UPPER:0)); if (DEBUGLEVEL>=4 && !(flag & LLL_NOCERTIFY)) timer_printf(&T, "FLATTER"); } if (!(flag & LLL_GRAM)) { long t; B = gcopy(B); if(DEBUGLEVEL>=4) err_printf("Entering L^2 (double): dim %ld, LLL-parameters (%.3f,%.3f)\n", n, DELTA,ETA); zeros = fplll_fast(&B, &U, DELTA, ETA, keepfirst); if (DEBUGLEVEL>=4) timer_printf(&T, zeros < 0? "LLL (failed)": "LLL"); for (p = DEFAULTPREC, t = 0; zeros < 0 && t < 1 ; p += EXTRAPREC64, t++) { if (DEBUGLEVEL>=4) err_printf("Entering L^2 (heuristic): LLL-parameters (%.3f,%.3f), prec = %d/%d\n", DELTA, ETA, p, p); zeros = fplll_heuristic(&B, &U, DELTA, ETA, keepfirst, p, p); gc_lll(av, 2, &B, &U); if (DEBUGLEVEL>=4) timer_printf(&T, zeros < 0? "LLL (failed)": "LLL"); } } else G = gcopy(G); if (zeros < 0 || !(flag & LLL_NOCERTIFY)) { if(DEBUGLEVEL>=4) err_printf("Entering L^2 (dpe): LLL-parameters (%.3f,%.3f)\n", DELTA,ETA); zeros = fplll_dpe(&G, &B, &U, pN, DELTA, ETA, keepfirst); if (DEBUGLEVEL>=4) timer_printf(&T, zeros < 0? "LLL (failed)": "LLL"); if (zeros < 0) for (p = DEFAULTPREC;; p += EXTRAPREC64) { if (DEBUGLEVEL>=4) err_printf("Entering L^2: LLL-parameters (%.3f,%.3f), prec = %d\n", DELTA,ETA, p); zeros = fplll(&G, &B, &U, pN, DELTA, ETA, keepfirst, p); if (DEBUGLEVEL>=4) timer_printf(&T, zeros < 0? "LLL (failed)": "LLL"); if (zeros >= 0) break; gc_lll(av, 3, &G, &B, &U); } } return lll_finish(U? U: B, zeros, flag); } /********************************************************************/ /** **/ /** 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 (gc_needed(av,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"lllgramallgen"); gerepileall(av,3,&B,&L,&h); } } k=1; while (k 0) return treeparent_r(t,x,tright(i),i); else return parent; } static void treekeys(GEN t, long i, GEN V, long *n) { if (i==0) return; treekeys(t, tleft(i), V, n); gel(V, ++*n) = gel(tvalue(i),1); treekeys(t, tright(i), V, n); } GEN mapdomain_shallow(GEN T) { GEN V, t = list_data(T); long n = 0; if (!t || lg(t)==1) return cgetg(1, t_VEC); V = cgetg(lg(t), t_VEC); treekeys(t, 1, V, &n); return V; } static void treeselect(void *E, long (*f)(void* E, GEN x), GEN t, long i, GEN V, long *n) { if (i==0) return; treeselect(E, f, t, tleft(i), V, n); if (f(E, gel(tvalue(i),2))) gel(V, ++*n) = gel(tvalue(i),1); treeselect(E, f, t, tright(i), V, n); } GEN mapselect_shallow(void *E, long (*f)(void* E, GEN x), GEN T) { GEN V, t = list_data(T); long n = 0; if (!t || lg(t)==1) return cgetg(1, t_VEC); clone_lock(T); V = cgetg(lg(t), t_COL); treeselect(E, f, t, 1, V, &n); clone_unlock_deep(T); fixlg(V, n+1); return V; } static void treemat(GEN t, long i, GEN V, long *n) { if (i==0) return; treemat(t, tleft(i), V, n); ++*n; gmael(V, 1, *n) = gel(tvalue(i), 1); gmael(V, 2, *n) = gel(tvalue(i), 2); treemat(t, tright(i), V, n); } GEN maptomat_shallow(GEN T) { GEN V, t = list_data(T); long n = 0; if (!t || lg(t)==1) return cgetg(1, t_MAT); V = cgetg(3, t_MAT); gel(V,1) = cgetg(lg(t), t_COL); gel(V,2) = cgetg(lg(t), t_COL); treemat(t, 1, V, &n); return V; } static void treemap_i_r(GEN t, long i, long a, long c, GEN p, GEN M) { long b = (a+c)>>1; GEN x = mkvec2(gcopy(gmael(M, 1, p[b])), gcopy(gmael(M, 2, p[b]))); if (a == c) gel(t, i) = mkvec2(x, mkvecsmall3(0, 0, 1)); else if (a+1 == c) { treemap_i_r(t, i+1, a+1, c, p, M); gel(t, i) = mkvec2(x, mkvecsmall3(0, i+1, theight(i+1) + 1)); } else { long l = i+1, r = l + b - a, h; treemap_i_r(t, l, a, b-1, p, M); treemap_i_r(t, r, b+1, c, p, M); h = maxss(theight(l), theight(r))+1; gel(t, i) = mkvec2(x, mkvecsmall3(l, r, h)); } } static void treemap_i(GEN t, GEN p, GEN M) { treemap_i_r(t, 1, 1, lg(p)-1, p, M); } #define value(i) gmael(list_data(T),(i),1) #define left(i) mael3(list_data(T),(i),2,1) #define right(i) mael3(list_data(T),(i),2,2) #define height(i) mael3(list_data(T),(i),2,3) static long treeheight(GEN T, long i) { return i? height(i): 0; } static void change_leaf(GEN T, GEN x, long p) { pari_sp av = avma; listput(T, mkvec2(x, gmael(list_data(T), p, 2)), p); set_avma(av); } static long new_leaf(GEN T, GEN x) { pari_sp av = avma; listput(T, mkvec2(x, mkvecsmall3(0,0,1)), 0); return gc_long(av, lg(list_data(T))-1); } static void fix_height(GEN T, long x) { height(x) = maxss(treeheight(T,left(x)), treeheight(T,right(x)))+1; } static long treebalance(GEN T, long i) { return i ? treeheight(T,left(i)) - treeheight(T,right(i)): 0; } static long rotright(GEN T, long y) { long x = left(y), t = right(x); right(x) = y; left(y) = t; fix_height(T, y); fix_height(T, x); return x; } static long rotleft(GEN T, long x) { long y = right(x), t = left(y); left(y) = x; right(x) = t; fix_height(T, x); fix_height(T, y); return y; } static long treeinsert_r(GEN T, GEN x, long i, long *d) { long b, c; if (i==0 || !list_data(T) || lg(list_data(T))==1) return new_leaf(T, x); c = cmp_universal(gel(x,1), gel(value(i),1)); if (c < 0) { long s = treeinsert_r(T, x, left(i), d); if (s < 0) return s; left(i) = s; } else if (c > 0) { long s = treeinsert_r(T, x, right(i), d); if (s < 0) return s; right(i) = s; } else return -i; fix_height(T, i); b = treebalance(T, i); if (b > 1) { if (*d > 0) left(i) = rotleft(T, left(i)); return rotright(T, i); } if (b < -1) { if (*d < 0) right(i) = rotright(T, right(i)); return rotleft(T, i); } *d = c; return i; } static long treeinsert(GEN T, GEN x) { long c = 0, r = treeinsert_r(T, x, 1, &c); GEN d; if (r < 0) return -r; if (r == 1) return 0; d = list_data(T); /* By convention we want the root to be 1 */ swap(gel(d,1), gel(d,r)); if (left(1) == 1) left(1) = r; else if (right(1) == 1) right(1) = r; else pari_err_BUG("treeadd"); return 0; } static long treedelete_r(GEN T, GEN x, long i, long *dead) { long b, c; if (i==0 || !list_data(T) || lg(list_data(T))==1) return -1; c = cmp_universal(x, gel(value(i),1)); if (c < 0) { long s = treedelete_r(T, x, left(i), dead); if (s < 0) return s; left(i) = s; } else if (c > 0) { long s = treedelete_r(T, x, right(i), dead); if (s < 0) return s; right(i) = s; } else { *dead = i; if (left(i)==0 && right(i)==0) return 0; else if (left(i)==0) return right(i); else if (right(i)==0) return left(i); else { GEN v, d = list_data(T); long j = right(i); while (left(j)) j = left(j); v = gel(value(j), 1); right(i) = treedelete_r(T, v, right(i), dead); swap(gel(d,i), gel(d,j)); lswap(left(i),left(j)); lswap(right(i),right(j)); lswap(height(i),height(j)); } } fix_height(T, i); b = treebalance(T, i); if (b > 1 && treebalance(T, left(i)) >= 0) return rotright(T, i); if (b > 1 && treebalance(T, left(i)) < 0) { left(i) = rotleft(T, left(i)); return rotright(T, i); } if (b < -1 && treebalance(T, right(i)) <= 0) return rotleft(T,i); if (b < -1 && treebalance(T, right(i)) > 0) { right(i) = rotright(T, right(i)); return rotleft(T, i); } return i; } static long treedelete(GEN T, GEN x) { long dead, l, r = treedelete_r(T, x, 1, &dead); GEN d; if (r < 0) return 0; d = list_data(T); /* != NULL and nonempty */ if (r > 1) { /* By convention we want the root to be 1 */ swap(gel(d,1), gel(d,r)); if (left(1) == 1) left(1) = r; else if (right(1) == 1) right(1) = r; else dead = r; } /* We want the dead to be last */ l = lg(d)-1; if (dead != l) { long p = treeparent_r(d, gel(value(l),1), 1, 0); if (left(p) == l) left(p) = dead; else if (right(p) == l) right(p) = dead; else pari_err_BUG("treedelete2"); swap(gel(d, dead),gel(d, l)); } listpop(T,0); return 1; } static int ismap(GEN T) { return typ(T) == t_LIST && list_typ(T) == t_LIST_MAP; } void mapput(GEN T, GEN a, GEN b) { pari_sp av = avma; GEN p = mkvec2(a, b); long i; if (!ismap(T)) pari_err_TYPE("mapput",T); i = treeinsert(T, p); if (i) change_leaf(T, p, i); set_avma(av); } void mapdelete(GEN T, GEN a) { pari_sp av = avma; long s; if (!ismap(T)) pari_err_TYPE("mapdelete",T); s = treedelete(T, a); set_avma(av); if (!s) pari_err_COMPONENT("mapdelete", "not in", strtoGENstr("map"), a); } GEN mapget(GEN T, GEN a) { GEN x; if (!ismap(T)) pari_err_TYPE("mapget",T); x = treesearch(T, a); if (!x) pari_err_COMPONENT("mapget", "not in", strtoGENstr("map"), a); return gcopy(gel(x, 2)); } GEN mapapply(GEN T, GEN a, GEN f, GEN u) { GEN x; if (!ismap(T)) pari_err_TYPE("mapapply",T); x = treesearch(T, a); if (!x) { if (!u) pari_err_COMPONENT("mapapply", "not in", strtoGENstr("map"), a); x = closure_callgen0(u); mapput(T, a, x); return x; } return closure_callgen1(f, gel(x,2)); } int mapisdefined(GEN T, GEN a, GEN *pt_z) { GEN x; if (!ismap(T)) pari_err_TYPE("mapisdefined",T); x = treesearch(T, a); if (!x) return 0; if (pt_z) *pt_z = gcopy(gel(x, 2)); return 1; } GEN mapdomain(GEN T) { long i, l; GEN V; if (!ismap(T)) pari_err_TYPE("mapdomain",T); V = mapdomain_shallow(T); l = lg(V); for (i = 1; i < l; i++) gel(V,i) = gcopy(gel(V,i)); return V; } GEN maptomat(GEN T) { long i, l; GEN V; if (!ismap(T)) pari_err_TYPE("maptomat",T); V = maptomat_shallow(T); if (lg(V) == 1) return V; l = lgcols(V); for (i = 1; i < l; i++) { gcoeff(V,i,1) = gcopy(gcoeff(V,i,1)); gcoeff(V,i,2) = gcopy(gcoeff(V,i,2)); } return V; } GEN gtomap(GEN x) { if (!x) return mkmap(); switch(typ(x)) { case t_MAT: { long l = lg(x); GEN M, p; if (l == 1 || lgcols(x)==1) return mkmap(); if (l != 3) pari_err_TYPE("Map",x); p = gen_indexsort_uniq(gel(x,1),(void*)&cmp_universal, cmp_nodata); l = lgcols(x); if (lg(p) != l) pari_err_DOMAIN("Map","x","is not",strtoGENstr("one-to-one"),x); M = cgetg(3, t_LIST); M[1] = evaltyp(t_LIST_MAP); /* do not set list_nmax! */ list_data(M) = cgetg(l, t_VEC); treemap_i(list_data(M), p, x); return M; } default: pari_err_TYPE("Map",x); } return NULL; /* LCOV_EXCL_LINE */ } pari-2.17.2/src/basemath/galconj.c0000644000175000017500000031725414676526175015357 0ustar billbill/* Copyright (C) 2000-2003 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_galois /*************************************************************************/ /** **/ /** GALOIS CONJUGATES **/ /** **/ /*************************************************************************/ static int is2sparse(GEN x) { long i, l = lg(x); if (odd(l-3)) return 0; for(i=3; i 1) { GEN T = real_1(prec); for (i = r1+1; i < n; i++) { GEN zi = gel(z,i), a = gel(zi,1), b = gel(zi,2); for (j = i+1; j <= n; j++) { GEN zj = gel(z,j), c = gel(zj,1), d = gel(zj,2); GEN f = gsqr(gsub(a,c)), g = gsqr(gsub(b,d)), h = gsqr(gadd(b,d)); T = gmul(T, gmul(gadd(f,g), gadd(f,h))); } } t = gmul(t, T); } t = gsqr(t); if (odd(r2)) t = gneg(t); return gerepileupto(av, t); } /* Compute bound for the coefficients of automorphisms. * T a ZX, den a t_INT denominator or NULL */ GEN initgaloisborne(GEN T, GEN den, long prec, GEN *pL, GEN *pprep, GEN *pD) { GEN L, prep, nf, r; pari_timer ti; if (DEBUGLEVEL>=4) timer_start(&ti); T = get_nfpol(T, &nf); r = nf ? nf_get_roots(nf) : NULL; if (nf && precision(gel(r, 1)) >= prec) L = embed_roots(r, nf_get_r1(nf)); else L = QX_complex_roots(T, prec); if (DEBUGLEVEL>=4) timer_printf(&ti,"roots"); prep = vandermondeinverseinit(L); if (!den || pD) { GEN res = RgV_prod(gabs(prep,prec)); GEN D = ZX_disc_all(T, 1 + gexpo(res)); /* +1 for safety */ if (pD) *pD = D; if (!den) den = indexpartial(T,D); } if (pprep) *pprep = prep; *pL = L; return den; } /* ||| M ||| with respect to || x ||_oo, M t_MAT */ GEN matrixnorm(GEN M, long prec) { long i,j,m, l = lg(M); GEN B = real_0(prec); if (l == 1) return B; m = lgcols(M); for (i = 1; i < m; i++) { GEN z = gabs(gcoeff(M,i,1), prec); for (j = 2; j < l; 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, av2; GEN borne, borneroots, bornetrace, borneabs; long prec; GEN L, M, prep, den; pari_timer ti; const long step=3; prec = nbits2prec(bit_accuracy(ZX_max_lg(T))); den = initgaloisborne(T,dn,prec, &L,&prep,&gb->dis); if (!dn) dn = den; ltop = avma; 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*/ bornetrace = mulur((2*step)*degpol(T)/d, powru(borneroots, minss(degpol(T), step))); borneroots = ceil_safe(gmul(borne, borneroots)); borneabs = ceil_safe(gmax_shallow(gmul(borne, bornetrace), powru(bornetrace, d))); av2 = avma; /*We use d-1 test, so we must overlift to 2^BITS_IN_LONG*/ gb->valsol = logint(shifti(borneroots,2+BITS_IN_LONG), gb->l) + 1; gb->valabs = logint(shifti(borneabs,2), gb->l) + 1; gb->valabs = maxss(gb->valsol, gb->valabs); if (DEBUGLEVEL >= 4) err_printf("GaloisConj: val1=%ld val2=%ld\n", gb->valsol, gb->valabs); set_avma(av2); gb->bornesol = gerepileuptoint(ltop, shifti(borneroots,1)); if (DEBUGLEVEL >= 9) err_printf("GaloisConj: Bound %Ps\n",borneroots); gb->ladicsol = powiu(gb->l, gb->valsol); gb->ladicabs = powiu(gb->l, gb->valabs); 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, ulong p, GEN L, GEN Lden, struct galois_borne *gb, struct galois_lift *gl) { pari_sp av; long e; gl->gb = gb; gl->T = T; gl->den = is_pm1(den)? gen_1: den; gl->p = utoipos(p); gl->L = L; gl->Lden = Lden; av = avma; e = logint(shifti(gb->bornesol, 2+BITS_IN_LONG), gl->p) + 1; set_avma(av); if (e < 2) e = 2; gl->e = e; gl->Q = powuu(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 (abscmpii(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++, set_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 galoisfrobeniustest(GEN aut, struct galois_lift *gl, GEN frob) { pari_sp av = avma; GEN tlift = aut; if (gl->den != gen_1) tlift = FpX_Fp_mul(tlift, gl->den, gl->Q); tlift = FpX_center_i(tlift, gl->Q, shifti(gl->Q,-1)); return gc_long(av, poltopermtest(tlift, gl, frob)); } static GEN monoratlift(void *E, GEN S, GEN q) { pari_sp ltop = avma; struct galois_lift *gl = (struct galois_lift *) E; GEN qm1 = sqrti(shifti(q,-2)), N = gl->Q; GEN tlift = FpX_ratlift(S, q, qm1, qm1, gl->den); if (tlift) { pari_sp ltop = avma; GEN frob = cgetg(lg(gl->L), t_VECSMALL); if(DEBUGLEVEL>=4) err_printf("MonomorphismLift: trying early solution %Ps\n",tlift); if (gl->den != gen_1) tlift = FpX_Fp_mul(FpX_red(Q_muli_to_int(tlift, gl->den), N), Fp_inv(gl->den, N), N); if (galoisfrobeniustest(tlift, gl, frob)) { if(DEBUGLEVEL>=4) err_printf("MonomorphismLift: true early solution.\n"); return gerepilecopy(ltop, tlift); } if(DEBUGLEVEL>=4) err_printf("MonomorphismLift: false early solution.\n"); } set_avma(ltop); return NULL; } static GEN monomorphismratlift(GEN P, GEN S, struct galois_lift *gl) { pari_timer ti; if (DEBUGLEVEL >= 1) timer_start(&ti); S = ZpX_ZpXQ_liftroot_ea(P,S,gl->T,gl->p, gl->e, (void*)gl, monoratlift); 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) { return monomorphismratlift(gl->T, S, gl); } static GEN galoisdolift(struct galois_lift *gl) { pari_sp av = avma; GEN Tp = FpX_red(gl->T, gl->p); GEN S = FpX_Frobenius(Tp, gl->p); return gerepileupto(av, automorphismlift(S, gl)); } static GEN galoisdoliftn(struct galois_lift *gl, long e) { pari_sp av = avma; GEN Tp = FpX_red(gl->T, gl->p); GEN S = FpXQ_autpow(FpX_Frobenius(Tp, gl->p), e, Tp, gl->p); return gerepileupto(av, automorphismlift(S, gl)); } static ulong findpsi(GEN D, ulong pstart, GEN P, GEN S, long o, GEN *Tmod, GEN *Tpsi) { forprime_t iter; ulong p; long n = degpol(P), i, j, g = n/o; GEN psi = cgetg(g+1, t_VECSMALL); u_forprime_init(&iter, pstart, ULONG_MAX); while ((p = u_forprime_next(&iter))) { GEN F, Sp; long gp = 0; if (smodis(D, p) == 0) continue; F = gel(Flx_factor(ZX_to_Flx(P, p), p), 1); if (lg(F)-1 != g) continue; Sp = RgX_to_Flx(S, p); for (j = 1; j <= g; j++) { GEN Fj = gel(F, j); GEN Sj = Flx_rem(Sp, Fj, p); GEN A = Flxq_autpowers(Flx_Frobenius(Fj, p), o, Fj, p); for (i = 1; i <= o; i++) if (gequal(Sj, gel(A,i+1))) { psi[j] = i; break; } if (i > o) break; if (gp==0 && i==1) gp=j; } if (gp && j > g) { /* Normalize result so that psi[l]=1 */ if (gp!=1) { swap(gel(F,1),gel(F,gp)); lswap(uel(psi,1),uel(psi,gp)); } *Tpsi = Flv_Fl_div(psi,psi[g],o); *Tmod = FlxV_to_ZXV(F); return p; } } return 0; } static void inittestlift(GEN plift, GEN Tmod, struct galois_lift *gl, struct galois_testlift *gt) { pari_timer ti; gt->n = lg(gl->L) - 1; gt->g = lg(Tmod) - 1; gt->f = gt->n / gt->g; gt->bezoutcoeff = bezout_lift_fact(gl->T, Tmod, gl->p, gl->e); if (DEBUGLEVEL >= 2) timer_start(&ti); gt->pauto = FpXQ_autpowers(plift, gt->f-1, gl->TQ, gl->Q); if (DEBUGLEVEL >= 2) timer_printf(&ti, "Frobenius power"); } /* Explanation of the intheadlong technique: * Let C be a bound, B = BITS_IN_LONG, M > C*2^B a modulus and 0 <= a_i < M for * i=1,...,n where n < 2^B. We want to test if there exist k,l, |k| < C < M/2^B, * such that sum a_i = k + l*M * We write a_i*2^B/M = b_i+c_i with b_i integer and 0<=c_i<1, so that * sum b_i - l*2^B = k*2^B/M - sum c_i * Since -1 < k*2^B/M < 1 and 0<=c_i<1, it follows that * -n-1 < sum b_i - l*2^B < 1 i.e. -n <= sum b_i -l*2^B <= 0 * So we compute z = - sum b_i [mod 2^B] and check if 0 <= z <= n. */ /* Assume 0 <= x < mod. */ static ulong intheadlong(GEN x, GEN mod) { pari_sp av = avma; long res = (long) itou(divii(shifti(x,BITS_IN_LONG),mod)); return gc_long(av,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, ord = gt->f, c_idx = gt->g-1; ulong headcache; 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 (abscmpiu(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); *psi = NULL; return gc_long(ltop,0); } N2=itos(NQ); if(!N2) N1=R1; if (DEBUGLEVEL>=4) timer_start(&ti); set_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); headcache = 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); set_avma(av3); } uel(cache,j) = uel(cache,j+1)+umael(Cd,h,j); } if (headlongisint(uel(cache,1),n)) { ulong head = headcache; for (j = 1; j < m; j++) head += polheadlong(gmael(C,SG[pf[j]],j),2,gl->Q); if (headlongisint(head,n)) { u = v; for (j = 1; j < m; j++) u = ZX_add(u, gmael(C,SG[pf[j]],j)); u = FpX_center_i(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)); } return gc_long(ltop2,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)); set_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; return gc_long(ltop,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)); set_avma(av); return m; } /* Initialize galois_test */ static void inittest(GEN L, GEN M, GEN borne, GEN ladic, struct galois_test *td) { long i, n = lg(L)-1; GEN p = cgetg(n+1, t_VECSMALL); if (DEBUGLEVEL >= 8) err_printf("GaloisConj: Init Test\n"); td->order = p; for (i = 1; i <= n-2; i++) p[i] = i+2; p[n-1] = 1; p[n] = 2; td->borne = borne; td->lborne = subii(ladic, borne); td->ladic = ladic; td->L = L; td->M = M; td->TM = shallowtrans(M); td->PV = zero_zv(n); gel(td->PV, 2) = Vmatrix(2, td); } /* Free clones stored inside galois_test */ static void freetest(struct galois_test *td) { long i; for (i = 1; i < lg(td->PV); i++) if (td->PV[i]) { gunclone(gel(td->PV,i)); td->PV[i] = 0; } } /* Check if the integer P seen as a p-adic number is close to an integer less * than td->borne in absolute value */ static long padicisint(GEN P, struct galois_test *td) { pari_sp ltop = avma; GEN U = modii(P, td->ladic); long r = cmpii(U, td->borne) <= 0 || cmpii(U, td->lborne) >= 0; return gc_long(ltop, r); } /* Check if the permutation pf is valid according to td. * If not, update td to make subsequent test faster (hopefully) */ static long galois_test_perm(struct galois_test *td, GEN pf) { pari_sp av = avma; long i, j, n = lg(td->L)-1; GEN V, P = NULL; for (i = 1; i < n; i++) { long ord = td->order[i]; GEN PW = gel(td->PV, ord); if (PW) { ulong head = umael(PW,1,pf[1]); for (j = 2; j <= n; j++) head += umael(PW,j,pf[j]); if (!headlongisint(head,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) return gc_long(av,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); } return gc_long(av,0); } /*Compute a*b/c when a*b will overflow*/ static long muldiv(long a,long b,long c) { return (long)((double)a*(double)b/c); } /* F = cycle decomposition of sigma, * B = cycle decomposition of cl(tau). * Check all permutations pf who can possibly correspond to tau, such that * tau*sigma*tau^-1 = sigma^s and tau^d = sigma^t, where d = ord cl(tau) * x: vector of choices, * G: vector allowing linear access to elts of F. * Choices multiple of e are not changed. */ static GEN testpermutation(GEN F, GEN B, GEN x, long s, long e, long cut, struct galois_test *td) { pari_sp av, avm = avma; long a, b, c, d, n, p1, p2, p3, p4, p5, p6, l1, l2, N1, N2, R1; long i, j, cx, hop = 0, start = 0; GEN pf, ar, G, W, NN, NQ; pari_timer ti; if (DEBUGLEVEL >= 1) timer_start(&ti); a = lg(F)-1; b = lg(gel(F,1))-1; c = lg(B)-1; d = lg(gel(B,1))-1; n = a*b; s = (b+s) % b; pf = cgetg(n+1, t_VECSMALL); av = avma; ar = cgetg(a+2, t_VECSMALL); ar[a+1]=0; G = cgetg(a+1, t_VECSMALL); W = gel(td->PV, td->order[n]); for (cx=1, i=1, j=1; cx <= a; cx++, i++) { gel(G,cx) = gel(F, coeff(B,i,j)); if (i == d) { i = 0; j++; } } NN = divis(powuu(b, c * (d - d/e)), cut); if (DEBUGLEVEL>=4) err_printf("GaloisConj: I will try %Ps permutations\n", NN); N1 = 1000000; NQ = divis_rem(NN,N1,&R1); if (abscmpiu(NQ,100000000)>0) { set_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 */ { GEN G1, G6; ulong V = 0; if (p5 == - 1) { p5 = d - 1; p6 = p1 + 1 - d; } else p6 = p1 + 1; G1 = gel(G,p1); G6 = gel(G,p6); p4 = p5 ? x[p1-1] : 0; for (p2 = 1+p4, p3 = 1 + x[p1]; p2 <= b; p2++) { V += umael(W,uel(G6,p3),uel(G1,p2)); p3 += s; if (p3 > b) p3 -= b; } p3 = 1 + x[p1] - s; if (p3 <= 0) p3 += b; for (p2 = p4; p2 >= 1; p2--) { V += umael(W,uel(G6,p3),uel(G1,p2)); p3 -= s; if (p3 <= 0) p3 += b; } uel(ar,p1) = uel(ar,p1+1) + V; } if (!headlongisint(uel(ar,1),n)) continue; /* intheadlong succeeds. Full computation */ for (p1=1, p5=d; p1 <= a; p1++, p5++) { if (p5 == d) { p5 = 0; p4 = 0; } else p4 = x[p1-1]; if (p5 == d-1) p6 = p1+1-d; else p6 = p1+1; for (p2 = 1+p4, p3 = 1 + x[p1]; p2 <= b; p2++) { pf[mael(G,p1,p2)] = mael(G,p6,p3); p3 += s; if (p3 > b) p3 -= b; } p3 = 1 + x[p1] - s; if (p3 <= 0) p3 += b; for (p2 = p4; p2 >= 1; p2--) { pf[mael(G,p1,p2)] = mael(G,p6,p3); p3 -= s; if (p3 <= 0) p3 += b; } } if (galois_test_perm(td, pf)) { if (DEBUGLEVEL >= 1) { GEN nb = addis(mulss(l2,N1),l1); timer_printf(&ti, "testpermutation(%Ps)", nb); if (DEBUGLEVEL >= 2 && hop) err_printf("GaloisConj: %d hop over %Ps iterations\n", hop, nb); } set_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); } return gc_NULL(avm); } /* List of subgroups of (Z/mZ)^* whose order divide o, and return the list * of their elements, sorted by increasing order */ static GEN listznstarelts(long m, long o) { pari_sp av = avma; GEN L, zn, zns; long i, phi, ind, l; if (m == 2) retmkvec(mkvecsmall(1)); 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) */ static GEN Flm_newtonsum(GEN M, ulong e, ulong p) { long f = lg(M), g = lg(gel(M,1)), i, j; GEN NS = cgetg(f, t_VECSMALL); 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 = Flv_sympol_eval(sym, NS, l); if (!vecsmall_is1to1(L)) { set_avma(av); continue; } return mkvec2(sym,W); } return NULL; } /*Check whether the line of NS are pair-wise distinct.*/ static long sympol_is1to1_lg(GEN NS, long n) { long i, j, k, l = lgcols(NS); for (i=1; i=n) return 0; } return 1; } /* Let O a set of orbits of roots (see fixedfieldorbits) modulo mod, * l | mod and p two prime numbers. Return a vector [sym,s,P] where: * sym is a sympol, s is the set of images of sym on O and * P is the polynomial with roots s. */ static GEN fixedfieldsympol(GEN O, ulong l) { pari_sp ltop=avma; const long n=(BITS_IN_LONG>>1)-1; GEN NS = cgetg(n+1,t_MAT), sym = NULL, W = cgetg(n+1,t_VECSMALL); long i, e=1; if (DEBUGLEVEL>=4) err_printf("FixedField: Size: %ldx%ld\n",lg(O)-1,lg(gel(O,1))-1); O = ZM_to_Flm(O,l); for (i=1; !sym && i<=n; i++) { GEN L = Flm_newtonsum(O, e++, l); if (lg(O)>2) while (vecsmall_isconst(L)) L = Flm_newtonsum(O, e++, l); W[i] = e-1; gel(NS,i) = L; if (sympol_is1to1_lg(NS,i+1)) sym = fixedfieldsurmer(l,NS,vecsmall_shorten(W,i)); } if (!sym) pari_err_BUG("fixedfieldsympol [p too small]"); if (DEBUGLEVEL>=2) err_printf("FixedField: Found: %Ps\n",gel(sym,1)); return gerepilecopy(ltop,sym); } /* Let O a set of orbits as indices and L the corresponding roots. * Return the set of orbits as roots. */ static GEN fixedfieldorbits(GEN O, GEN L) { GEN S = cgetg(lg(O), t_MAT); long i; for (i = 1; i < lg(O); i++) gel(S,i) = vecpermute(L, gel(O,i)); return S; } static GEN fixedfieldinclusion(GEN O, GEN PL) { long i, j, f = lg(O)-1, g = lg(gel(O,1))-1; GEN S = cgetg(f*g + 1, t_COL); for (i = 1; i <= f; i++) { GEN Oi = gel(O,i); for (j = 1; j <= g; j++) gel(S, Oi[j]) = gel(PL, i); } return S; } /* Polynomial attached 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= 2) err_printf("GaloisAnalysis:non Galois for p=%ld\n", p); ga->p = p; ga->deg = 0; } /*Gather information about the group*/ static long init_group(long n, long np, GEN Fp, GEN Fe, long *porder) { const long prim_nonwss_orders[] = { 48,56,60,72,75,80,196,200,216 }; long i, phi_order = 1, order = 1, group = 0; ulong p; /* non-WSS groups of this order? */ for (i=0; i < (long)numberof(prim_nonwss_orders); i++) if (n % prim_nonwss_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; } if (uisprimepower(n, &p) || n == 135) group |= ga_all_nilpotent; if (n <= 104) group |= ga_easy; /* no need to use polynomial algo */ *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, GEN bad) { pari_sp ltop = avma, av; long group, linf, n, p, i, karma = 0; GEN F, Fp, Fe, Fpe, O; long np, order, plift, nbmax, nbtest, deg; pari_timer ti; forprime_t S; if (DEBUGLEVEL >= 1) timer_start(&ti); n = degpol(T); O = zero_zv(n); F = factoru_pow(n); Fp = gel(F,1); np = lg(Fp)-1; Fe = gel(F,2); Fpe= gel(F,3); group = init_group(n, np, Fp, Fe, &order); /*Now we study the orders of the Frobenius elements*/ deg = Fp[np]; /* largest prime | n */ plift = 0; nbtest = 0; nbmax = 8+(n>>1); u_forprime_init(&S, n*maxss(expu(n)-3, 2), ULONG_MAX); av = avma; while (!plift || (nbtest < nbmax && (nbtest <=8 || order < (n>>1))) || ((n == 24 || n==36) && O[6] == 0 && O[4] == 0) || ((group&ga_non_wss) && order == Fp[np])) { long d, o, norm_o = 1; GEN D, Tp; if ((group&ga_non_wss) && nbtest >= 3*nbmax) break; /* in all cases */ nbtest++; set_avma(av); p = u_forprime_next(&S); if (!p) pari_err_OVERFLOW("galoisanalysis [ran out of primes]"); if (bad && dvdiu(bad, p)) continue; 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); return gc_bool(ltop,0); } if (!O[o]) O[o] = p; if (o % deg) goto ga_end; /* NB: deg > 1 */ if ((group&ga_all_normal) && o < order) goto ga_end; /*Frob_p has order o > 1, find a power which generates a normal subgroup*/ if (o * Fp[1] >= n) norm_o = o; /*subgroups of smallest index are normal*/ else { for (i = np; i > 0; i--) { if (o % Fpe[i]) break; norm_o *= Fpe[i]; } } /* Frob_p^(o/norm_o) generates a normal subgroup of order norm_o */ if (norm_o != 1) { if (!(group&ga_all_normal) || o > order) karma = ugcd(p-1,n); else if (!improves(norm_o, deg, plift,p,n, &karma)) goto ga_end; /* karma0=0, deg0<=norm_o -> the first improves() returns 1 */ deg = norm_o; group |= ga_all_normal; /* STORE */ } else if (group&ga_all_normal) goto ga_end; else if (!improves(o, order, plift,p,n, &karma)) goto ga_end; order = o; plift = p; /* STORE */ ga_end: if (DEBUGLEVEL >= 5) err_printf("GaloisAnalysis:Nbtest=%ld,p=%ld,o=%ld,n_o=%d,best p=%ld,ord=%ld,k=%ld\n", nbtest, p, o, norm_o, plift, order,karma); } /* To avoid looping on non-WSS group. * TODO: check for large groups. Would it be better to disable this check if * we are in a good case (ga_all_normal && !(ga_ext_2) (e.g. 60)) ?*/ ga->p = plift; if (!plift || ((group&ga_non_wss) && order == Fp[np])) { if (DEBUGLEVEL) pari_warn(warner,"Galois group probably not weakly super solvable"); return 0; } linf = 2*n*usqrt(n); if (calcul_l && O[1] <= linf) { pari_sp av2; forprime_t S2; ulong p; u_forprime_init(&S2, linf+1,ULONG_MAX); av2 = avma; while ((p = u_forprime_next(&S2))) { /*find a totally split prime l > linf*/ GEN Tp = ZX_to_Flx(T, p); long nb = Flx_nbroots(Tp, p); if (nb == n) { O[1] = p; break; } if (nb && Flx_is_squarefree(Tp,p)) { notgalois(p,ga); return gc_bool(ltop,0); } set_avma(av2); } if (!p) pari_err_OVERFLOW("galoisanalysis [ran out of primes]"); } ga->group = group; ga->deg = deg; ga->ord = order; ga->l = O[1]; ga->p4 = n >= 4 ? O[4] : 0; if (DEBUGLEVEL >= 4) err_printf("GaloisAnalysis:p=%ld l=%ld group=%ld deg=%ld ord=%ld\n", plift, O[1], group, deg, order); if (DEBUGLEVEL >= 1) timer_printf(&ti, "galoisanalysis()"); return gc_bool(ltop,1); } static GEN a4galoisgen(struct galois_test *td) { const long n = 12; pari_sp ltop = avma, av, av2; long i, j, k, N, hop = 0; GEN MT, O,O1,O2,O3, ar, mt, t, u, res, orb, pft, pfu, pfv; res = cgetg(3, t_VEC); pft = cgetg(n+1, t_VECSMALL); pfu = cgetg(n+1, t_VECSMALL); pfv = cgetg(n+1, t_VECSMALL); gel(res,1) = mkvec3(pft,pfu,pfv); gel(res,2) = mkvecsmall3(2,2,3); av = avma; ar = cgetg(5, t_VECSMALL); mt = gel(td->PV, td->order[n]); t = identity_perm(n) + 1; /* Sorry for this hack */ u = cgetg(n+1, t_VECSMALL) + 1; /* too lazy to correct */ MT = cgetg(n+1, t_MAT); for (j = 1; j <= n; j++) gel(MT,j) = cgetg(n+1, t_VECSMALL); for (j = 1; j <= n; j++) for (i = 1; i < j; i++) ucoeff(MT,i,j) = ucoeff(MT,j,i) = ucoeff(mt,i,j)+ucoeff(mt,j,i); /* MT(i,i) unused */ av2 = avma; /* N = itos(gdiv(mpfact(n), mpfact(n >> 1))) >> (n >> 1); */ /* n = 2k = 12; N = (2k)! / (k! * 2^k) = 10395 */ N = 10395; if (DEBUGLEVEL>=4) err_printf("A4GaloisConj: will test %ld permutations\n", N); uel(ar,4) = umael(MT,11,12); uel(ar,3) = uel(ar,4) + umael(MT,9,10); uel(ar,2) = uel(ar,3) + umael(MT,7,8); uel(ar,1) = uel(ar,2) + umael(MT,5,6); for (i = 0; i < N; i++) { long g; if (i) { long a, x = i, y = 1; do { y += 2; a = x%y; x = x/y; } while (!a); switch (y) { case 3: lswap(t[2], t[2-a]); break; case 5: x = t[0]; t[0] = t[2]; t[2] = t[1]; t[1] = x; lswap(t[4], t[4-a]); uel(ar,1) = uel(ar,2) + umael(MT,t[4],t[5]); break; case 7: x = t[0]; t[0] = t[4]; t[4] = t[3]; t[3] = t[1]; t[1] = t[2]; t[2] = x; lswap(t[6], t[6-a]); uel(ar,2) = uel(ar,3) + umael(MT,t[6],t[7]); uel(ar,1) = uel(ar,2) + umael(MT,t[4],t[5]); break; case 9: x = t[0]; t[0] = t[6]; t[6] = t[5]; t[5] = t[3]; t[3] = x; lswap(t[1], t[4]); lswap(t[8], t[8-a]); uel(ar,3) = uel(ar,4) + umael(MT,t[8],t[9]); uel(ar,2) = uel(ar,3) + umael(MT,t[6],t[7]); uel(ar,1) = uel(ar,2) + umael(MT,t[4],t[5]); break; case 11: x = t[0]; t[0] = t[8]; t[8] = t[7]; t[7] = t[5]; t[5] = t[1]; t[1] = t[6]; t[6] = t[3]; t[3] = t[2]; t[2] = t[4]; t[4] = x; lswap(t[10], t[10-a]); uel(ar,4) = umael(MT,t[10],t[11]); uel(ar,3) = uel(ar,4) + umael(MT,t[8],t[9]); uel(ar,2) = uel(ar,3) + umael(MT,t[6],t[7]); uel(ar,1) = uel(ar,2) + umael(MT,t[4],t[5]); } } g = uel(ar,1)+umael(MT,t[0],t[1])+umael(MT,t[2],t[3]); if (headlongisint(g,n)) { for (k = 0; k < n; k += 2) { pft[t[k]] = t[k+1]; pft[t[k+1]] = t[k]; } if (galois_test_perm(td, pft)) break; hop++; } set_avma(av2); } if (DEBUGLEVEL >= 1 && hop) err_printf("A4GaloisConj: %ld hop over %ld iterations\n", hop, N); if (i == N) return gc_NULL(ltop); /* N = itos(gdiv(mpfact(n >> 1), mpfact(n >> 2))) >> 1; */ N = 60; if (DEBUGLEVEL >= 4) err_printf("A4GaloisConj: sigma=%Ps \n", pft); for (k = 0; k < n; k += 4) { u[k+3] = t[k+3]; u[k+2] = t[k+1]; u[k+1] = t[k+2]; u[k] = t[k]; } for (i = 0; i < N; i++) { ulong g = 0; if (i) { long a, x = i, y = -2; do { y += 4; a = x%y; x = x/y; } while (!a); lswap(u[0],u[2]); switch (y) { case 2: break; case 6: lswap(u[4],u[6]); if (!(a & 1)) { a = 4 - (a>>1); lswap(u[6], u[a]); lswap(u[4], u[a-2]); } break; case 10: x = u[6]; u[6] = u[3]; u[3] = u[2]; u[2] = u[4]; u[4] = u[1]; u[1] = u[0]; u[0] = x; if (a >= 3) a += 2; a = 8 - a; lswap(u[10],u[a]); lswap(u[8], u[a-2]); break; } } for (k = 0; k < n; k += 2) g += mael(MT,u[k],u[k+1]); if (headlongisint(g,n)) { for (k = 0; k < n; k += 2) { pfu[u[k]] = u[k+1]; pfu[u[k+1]] = u[k]; } if (galois_test_perm(td, pfu)) break; hop++; } set_avma(av2); } if (i == N) return gc_NULL(ltop); 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); set_avma(av2); orb = mkvec2(pft,pfu); O = vecperm_orbits(orb, 12); if (DEBUGLEVEL >= 4) { err_printf("A4GaloisConj: orb=%Ps\n", orb); err_printf("A4GaloisConj: O=%Ps \n", O); } av2 = avma; O1 = gel(O,1); O2 = gel(O,2); O3 = gel(O,3); for (j = 0; j < 2; j++) { pfv[O1[1]] = O2[1]; pfv[O1[2]] = O2[3+j]; pfv[O1[3]] = O2[4 - (j << 1)]; pfv[O1[4]] = O2[2+j]; for (i = 0; i < 4; i++) { ulong g = 0; switch (i) { case 0: break; case 1: lswap(O3[1], O3[2]); lswap(O3[3], O3[4]); break; case 2: lswap(O3[1], O3[4]); lswap(O3[2], O3[3]); break; case 3: lswap(O3[1], O3[2]); lswap(O3[3], O3[4]); break; } pfv[O2[1]] = O3[1]; pfv[O2[3+j]] = O3[4-j]; pfv[O2[4 - (j<<1)]] = O3[2 + (j<<1)]; pfv[O2[2+j]] = O3[3-j]; pfv[O3[1]] = O1[1]; pfv[O3[4-j]] = O1[2]; pfv[O3[2 + (j<<1)]] = O1[3]; pfv[O3[3-j]] = O1[4]; for (k = 1; k <= n; k++) g += mael(mt,k,pfv[k]); if (headlongisint(g,n) && galois_test_perm(td, pfv)) { set_avma(av); if (DEBUGLEVEL >= 1) err_printf("A4GaloisConj: %ld hop over %d iterations max\n", hop, 10395 + 68); return res; } hop++; set_avma(av2); } } return gc_NULL(ltop); } /* S4 */ static GEN s4makelift(GEN u, struct galois_lift *gl) { return FpXQ_powers(u, degpol(gl->T)-1, 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 = 2; i <= d; i++) if (lg(gel(liftpow,i))>2) res = addii(res, mulii(gmael(liftpow,i,2), gel(u,i+1))); res = remii(res,Q); if (gl->den != gen_1) res = mulii(res, gl->den); res = centermodii(res, Q,Q2); if (abscmpii(res, gl->gb->bornesol) > 0) return gc_long(av,0); res = scalar_ZX_shallow(gel(u,2),varn(u)); for (i = 2; i <= d ; i++) if (lg(gel(liftpow,i))>2) res = ZX_add(res, ZX_Z_mul(gel(liftpow,i), gel(u,i+1))); res = FpX_red(res, Q); if (gl->den != gen_1) res = FpX_Fp_mul(res, gl->den, Q); res = FpX_center_i(res, Q, shifti(Q,-1)); bl = poltopermtest(res, gl, phi); if (DEBUGLEVEL >= 6) timer_printf(&ti, "s4test()"); return gc_long(av,bl); } static GEN s4releveauto(GEN M, GEN B, GEN T, GEN p,long a1,long a2,long a3,long a4,long a5,long a6) { GEN F = ZX_mul(gel(M,a1),gel(B,a2)); F = ZX_add(F, ZX_mul(gel(M,a2),gel(B,a1))); F = ZX_add(F, ZX_mul(gel(M,a3),gel(B,a4))); F = ZX_add(F, ZX_mul(gel(M,a4),gel(B,a3))); F = ZX_add(F, ZX_mul(gel(M,a5),gel(B,a6))); F = ZX_add(F, ZX_mul(gel(M,a6),gel(B,a5))); return FpXQ_red(F, T, p); } static GEN lincomb(GEN B, long a, long b, long j) { long k = (-j) & 3; return ZX_add(gmael(B,a,j+1), gmael(B,b,k+1)); } static GEN FpXV_ffisom(GEN V, GEN p) { pari_sp av = avma; long i, j, l = lg(V); GEN S = cgetg(l, t_VEC), Si = cgetg(l, t_VEC), M; for (i = 1; i < l; i++) { gel(S,i) = FpX_ffisom(gel(V,1), gel(V,i), p); gel(Si,i) = FpXQ_ffisom_inv(gel(S,i), gel(V,i), p); } M = cgetg(l, t_MAT); for (j = 1; j < l; j++) gel(M,j) = FpXC_FpXQ_eval(Si, gel(S,j), gel(V,j), p); return gerepileupto(av, M); } static GEN mkliftpow(GEN x, GEN T, GEN p, struct galois_lift *gl) { pari_APPLY_same(automorphismlift(FpXV_chinese(gel(x,i), T, p, NULL), gl)) } #define rot3(x,y,z) {long _t=x; x=y; y=z; z=_t;} #define rot4(x,y,z,t) {long _u=x; x=y; y=z; z=t; t=_u;} /* 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, misom, B, Bcoeff, liftpow, liftp, aut; res = cgetg(3, t_VEC); r1 = cgetg(n+1, t_VECSMALL); r2 = cgetg(n+1, t_VECSMALL); r3 = cgetg(n+1, t_VECSMALL); r4 = cgetg(n+1, t_VECSMALL); gel(res,1)= mkvec4(r1,r2,r3,r4); gel(res,2) = mkvecsmall4(2,2,3,2); ltop2 = avma; sg = identity_perm(6); pj = zero_zv(6); sigma = cgetg(n+1, t_VECSMALL); tau = cgetg(n+1, t_VECSMALL); phi = cgetg(n+1, t_VECSMALL); Tp = FpX_red(gl->T,p); Tmod = gel(FpX_factor(Tp,p), 1); misom = FpXV_ffisom(Tmod, p); aut = galoisdolift(gl); inittestlift(aut, Tmod, gl, >); B = FqC_FqV_mul(gt.pauto, gt.bezoutcoeff, gl->TQ, Q); Bcoeff = gt.bezoutcoeff; liftp = mkliftpow(shallowtrans(misom), Tmod, p, gl); av = avma; for (i = 0; i < 3; i++, set_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(liftp,Bcoeff,TQ,Q,sg[1],sg[2],sg[3],sg[4],sg[5],sg[6]); liftpow = s4makelift(u, gl); av1 = avma; for (j1 = 0; j1 < 4; j1++, set_avma(av1)) { u1 = lincomb(B,sg[5],sg[6],j1); av2 = avma; for (j2 = 0; j2 < 4; j2++, set_avma(av2)) { u2 = lincomb(B,sg[3],sg[4],j2); u2 = FpX_add(u1, u2, Q); av3 = avma; for (j3 = 0; j3 < 4; j3++, set_avma(av3)) { u3 = lincomb(B,sg[1],sg[2],j3); u3 = FpX_add(u2, u3, 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; } } } } } return gc_NULL(ltop); suites4: if (DEBUGLEVEL >= 4) err_printf("S4GaloisConj: sigma=%Ps\n", sigma); if (DEBUGLEVEL >= 4) err_printf("S4GaloisConj: pj=%Ps\n", pj); set_avma(av); for (j = 1; j <= 3; j++) { pari_sp av2, av3; GEN u; long w, l; rot3(sg[1], sg[3], sg[5]) rot3(sg[2], sg[4], sg[6]) rot3(pj[1], pj[2], pj[3]) for (l = 0; l < 2; l++, set_avma(av)) { u = s4releveauto(liftp,Bcoeff,TQ,Q,sg[1],sg[3],sg[2],sg[4],sg[5],sg[6]); liftpow = s4makelift(u, gl); av2 = avma; for (w = 0; w < 4; w += 2, set_avma(av2)) { GEN uu; pj[6] = (w + pj[3]) & 3; uu = lincomb(B, sg[5], sg[6], pj[6]); uu = FpX_red(uu, Q); av3 = avma; for (i = 0; i < 4; i++, set_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(B,sg[1],sg[3],pj[4]), lincomb(B,sg[2],sg[4],pj[5])); u = FpX_add(uu,u,Q); if (s4test(u, liftpow, gl, tau)) goto suites4_2; } } lswap(sg[3], sg[4]); pj[2] = (-pj[2]) & 3; } } return gc_NULL(ltop); suites4_2: set_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(liftp,Bcoeff,TQ,Q,sg[1],sg[4],sg[2],sg[5],sg[3],sg[6]); liftpow = s4makelift(u, gl); 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(B,sg[1],sg[4], g), lincomb(B,sg[2],sg[5], h)); u = FpX_add(u, lincomb(B,sg[3],sg[6], i),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; set_avma(av2); } } if (j == 8) return gc_NULL(ltop); 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]; } set_avma(ltop2); return res; } static GEN f36releveauto2(GEN Bl, GEN T, GEN p,GEN a) { GEN F = gmael(Bl,a[1],a[1]); F = ZX_add(F,gmael(Bl,a[2],a[3])); F = ZX_add(F,gmael(Bl,a[3],a[2])); F = ZX_add(F,gmael(Bl,a[4],a[5])); F = ZX_add(F,gmael(Bl,a[5],a[4])); F = ZX_add(F,gmael(Bl,a[6],a[7])); F = ZX_add(F,gmael(Bl,a[7],a[6])); F = ZX_add(F,gmael(Bl,a[8],a[9])); F = ZX_add(F,gmael(Bl,a[9],a[8])); return FpXQ_red(F, T, p); } static GEN f36releveauto4(GEN Bl, GEN T, GEN p,GEN a) { GEN F = gmael(Bl,a[1],a[1]); F = ZX_add(F,gmael(Bl,a[2],a[3])); F = ZX_add(F,gmael(Bl,a[3],a[4])); F = ZX_add(F,gmael(Bl,a[4],a[5])); F = ZX_add(F,gmael(Bl,a[5],a[2])); F = ZX_add(F,gmael(Bl,a[6],a[7])); F = ZX_add(F,gmael(Bl,a[7],a[8])); F = ZX_add(F,gmael(Bl,a[8],a[9])); F = ZX_add(F,gmael(Bl,a[9],a[6])); return FpXQ_red(F, T, p); } static GEN f36galoisgen(struct galois_lift *gl) { const long n = 36; struct galois_testlift gt; pari_sp av, ltop2, ltop = avma; long i; GEN sigma, tau, rho, res, r1,r2,r3, pj, pk, p = gl->p, Q = gl->Q, TQ = gl->TQ; GEN sg, s4, sp, Tp, Tmod, misom, Bcoeff, liftpow, aut, liftp, B, Bl, tam; res = cgetg(3, t_VEC); r1 = cgetg(n+1, t_VECSMALL); r2 = cgetg(n+1, t_VECSMALL); r3 = cgetg(n+1, t_VECSMALL); gel(res,1)= mkvec3(r1,r2,r3); gel(res,2) = mkvecsmall3(3,3,4); ltop2 = avma; sg = identity_perm(9); s4 = identity_perm(9); sp = identity_perm(9); pj = zero_zv(4); pk = zero_zv(2); sigma = cgetg(n+1, t_VECSMALL); tau = r3; rho = cgetg(n+1, t_VECSMALL); Tp = FpX_red(gl->T,p); Tmod = gel(FpX_factor(Tp,p), 1); misom = FpXV_ffisom(Tmod, p); aut = galoisdolift(gl); inittestlift(aut, Tmod, gl, >); Bcoeff = gt.bezoutcoeff; B = FqC_FqV_mul(gt.pauto, Bcoeff, gl->TQ, gl->Q); liftp = mkliftpow(shallowtrans(misom), Tmod, p, gl); Bl = FqC_FqV_mul(liftp,Bcoeff, gl->TQ, gl->Q); av = avma; for (i = 0; i < 105; i++, set_avma(av)) { pari_sp av0, av1, av2, av3; GEN u0, u1, u2, u3; long j0, j1, j2, j3, s; if (i) { rot3(sg[7],sg[8],sg[9]) if (i%3==0) { s=sg[5]; sg[5]=sg[6]; sg[6]=sg[7]; sg[7]=sg[8]; sg[8]=sg[9]; sg[9]=s; if (i%15==0) { s=sg[3]; sg[3]=sg[4]; sg[4]=sg[5]; sg[5]=sg[6]; sg[6]=sg[7]; sg[7]=sg[8]; sg[8]=sg[9]; sg[9]=s; } } } liftpow = s4makelift(f36releveauto2(Bl, TQ, Q, sg), gl); av0 = avma; for (j0 = 0; j0 < 4; j0++, set_avma(av0)) { u0 = lincomb(B,sg[8],sg[9],j0); u0 = FpX_add(u0, gmael(B,sg[1],3), Q); av1 = avma; for (j1 = 0; j1 < 4; j1++, set_avma(av1)) { u1 = lincomb(B,sg[6],sg[7],j1); u1 = FpX_add(u0, u1, Q); av2 = avma; for (j2 = 0; j2 < 4; j2++, set_avma(av2)) { u2 = lincomb(B,sg[4],sg[5],j2); u2 = FpX_add(u1, u2, Q); av3 = avma; for (j3 = 0; j3 < 4; j3++, set_avma(av3)) { u3 = lincomb(B,sg[2],sg[3],j3); u3 = FpX_add(u2, u3, Q); if (s4test(u3, liftpow, gl, sigma)) { pj[1] = j3; pj[2] = j2; pj[3] = j1; pj[4] = j0; goto suitef36; } } } } } } return gc_NULL(ltop); suitef36: s4[1]=sg[1]; s4[2]=sg[2]; s4[4]=sg[3]; s4[3]=sg[4]; s4[5]=sg[5]; s4[6]=sg[6]; s4[8]=sg[7]; s4[7]=sg[8]; s4[9]=sg[9]; for (i = 0; i < 12; i++, set_avma(av)) { pari_sp av0, av1; GEN u0, u1; long j0, j1; if (i) { lswap(s4[3],s4[5]); pj[2] = (-pj[2])&3; if (odd(i)) { lswap(s4[7],s4[9]); pj[4]=(-pj[4])&3; } if (i%4==0) { rot3(s4[3],s4[6],s4[7]); rot3(s4[5],s4[8],s4[9]); rot3(pj[2],pj[3],pj[4]); } } liftpow = s4makelift(f36releveauto4(Bl, TQ, Q, s4), gl); av0 = avma; for (j0 = 0; j0 < 4; j0++, set_avma(av0)) { u0 = FpX_add(gmael(B,s4[1],2), gmael(B,s4[2],1+j0),Q); u0 = FpX_add(u0, gmael(B,s4[3],1+smodss(pj[2]-j0,4)),Q); u0 = FpX_add(u0, gmael(B,s4[4],1+smodss(j0-pj[1]-pj[2],4)),Q); u0 = FpX_add(u0, gmael(B,s4[5],1+smodss(pj[1]-j0,4)),Q); av1 = avma; for (j1 = 0; j1 < 4; j1++, set_avma(av1)) { u1 = FpX_add(u0, gmael(B,s4[6],1+j1),Q); u1 = FpX_add(u1, gmael(B,s4[7],1+smodss(pj[4]-j1,4)),Q); u1 = FpX_add(u1, gmael(B,s4[8],1+smodss(j1-pj[3]-pj[4],4)),Q); u1 = FpX_add(u1, gmael(B,s4[9],1+smodss(pj[3]-j1,4)),Q); if (s4test(u1, liftpow, gl, tau)) { pk[1] = j0; pk[2] = j1; goto suitef36_2; } } } } return gc_NULL(ltop); suitef36_2: sp[1]=s4[9]; sp[2]=s4[1]; sp[3]=s4[2]; sp[4]=s4[7]; sp[5]=s4[3]; sp[6]=s4[8]; sp[8]=s4[4]; sp[7]=s4[5]; sp[9]=s4[6]; for (i = 0; i < 4; i++, set_avma(av)) { const int w[4][6]={{0,0,1,3,0,2},{1,0,2,1,1,2},{3,3,2,0,3,1},{0,1,3,0,0,3}}; pari_sp av0, av1, av2; GEN u0, u1, u2; long j0, j1,j2,j3,j4,j5; if (i) { rot4(sp[3],sp[5],sp[8],sp[7]) pk[1]=(-pk[1])&3; } liftpow = s4makelift(f36releveauto4(Bl,TQ,Q,sp), gl); av0 = avma; for (j0 = 0; j0 < 4; j0++, set_avma(av0)) { u0 = FpX_add(gmael(B,sp[1],2), gmael(B,sp[2],1+j0),Q); av1 = avma; for (j1 = 0; j1 < 4; j1++, set_avma(av1)) { u1 = FpX_add(u0, gmael(B,sp[3],1+j1),Q); j3 = (-pk[1]-pj[3]+j0+j1-w[i][0]*pj[1]-w[i][3]*pj[2])&3; u1 = FpX_add(u1, gmael(B,sp[6],1+j3),Q); j5 = (-pk[1]+2*j0+2*j1-w[i][2]*pj[1]-w[i][5]*pj[2])&3; u1 = FpX_add(u1, gmael(B,sp[8],1+j5),Q); av2 = avma; for (j2 = 0; j2 < 4; j2++, set_avma(av2)) { u2 = FpX_add(u1, gmael(B,sp[4],1+j2),Q); u2 = FpX_add(u2, gmael(B,sp[5],1+smodss(-j0-j1-j2,4)),Q); j4 = (-pk[1]-pk[2]+pj[3]+pj[4]-j2-w[i][1]*pj[1]-w[i][4]*pj[2])&3; u2 = FpX_add(u2, gmael(B,sp[7],1+j4),Q); u2 = FpX_add(u2, gmael(B,sp[9],1+smodss(-j3-j4-j5,4)),Q); if (s4test(u2, liftpow, gl, rho)) goto suitef36_3; } } } } return gc_NULL(ltop); suitef36_3: tam = perm_inv(tau); for (i = 1; i <= n; i++) { r1[tau[i]] = rho[i]; r2[i] = tam[rho[i]]; } set_avma(ltop2); return res; } /* return a vecvecsmall */ 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; iTmod)-1; GEN F,Fp,Fe, aut, frob, res = cgetg(lg(L), t_VECSMALL); gf->psi = const_vecsmall(g,1); av2 = avma; initlift(T, den, gf->p, L, Lden, gb, &gl); if (DEBUGLEVEL >= 4) err_printf("GaloisConj: p=%ld e=%ld deg=%ld fp=%ld\n", gf->p, gl.e, deg, gf->fp); aut = galoisdolift(&gl); if (galoisfrobeniustest(aut,&gl,res)) { set_avma(av2); gf->deg = gf->fp; return res; } 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 fres=NULL; long el = gf->fp, dg = 1, dgf = 1, e, pr; for(e=1; e<=Fe[k]; e++) { dg *= Fp[k]; el /= Fp[k]; if (DEBUGLEVEL>=4) err_printf("Trying degre %d.\n",dg); if (el==1) break; aut = galoisdoliftn(&gl, el); if (!galoisfrobeniustest(aut,&gl,frob)) break; dgf = dg; fres = gcopy(frob); } if (dgf == 1) { set_avma(btop); continue; } pr = deg*dgf; if (deg == 1) { for(i=1;i=4 && res) err_printf("Best lift: %d\n",deg); if (deg==1) return gc_NULL(ltop); else { set_avma(av2); gf->deg = deg; return res; } } 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, res = cgetg(lg(L), t_VECSMALL); gf->psi = const_vecsmall(g,1); av2 = avma; initlift(T, den, gf->p, L, Lden, gb, &gl); if (DEBUGLEVEL >= 4) err_printf("GaloisConj: p=%ld e=%ld deg=%ld fp=%ld\n", gf->p, gl.e, deg, gf->fp); aut = galoisdolift(&gl); if (galoisfrobeniustest(aut,&gl,res)) { set_avma(av2); gf->deg = gf->fp; return res; } inittestlift(aut,gf->Tmod, &gl, >); gt.C = cgetg(gf->fp+1,t_VEC); gt.Cd= cgetg(gf->fp+1,t_VEC); for (i = 1; i <= gf->fp; i++) { gel(gt.C,i) = zero_zv(gt.g); gel(gt.Cd,i) = zero_zv(gt.g); } F =factoru(gf->fp); Fp = gel(F,1); Fe = gel(F,2); frob = cgetg(lg(L), t_VECSMALL); for(k=lg(Fp)-1;k>=1;k--) { pari_sp btop=avma; GEN psi=NULL, fres=NULL, sg = identity_perm(1); long el=gf->fp, dg=1, dgf=1, e, pr; for(e=1; e<=Fe[k]; e++) { GEN lo, pf; long l; dg *= Fp[k]; el /= Fp[k]; if (DEBUGLEVEL>=4) err_printf("Trying degre %d.\n",dg); if (galoisfrobeniustest(gel(gt.pauto,el+1),&gl,frob)) { psi = const_vecsmall(g,1); dgf = dg; fres = leafcopy(frob); continue; } lo = listznstarelts(dg, n / gf->fp); if (e!=1) lo = galoisfindgroups(lo, sg, dgf); if (DEBUGLEVEL>=4) err_printf("Galoisconj:Subgroups list:%Ps\n", lo); for (l = 1; l < lg(lo); l++) if (lg(gel(lo,l))>2 && frobeniusliftall(gel(lo,l), el, &pf,&gl,>, frob)) { sg = leafcopy(gel(lo,l)); psi = galoismakepsi(g,sg,pf); dgf = dg; fres = leafcopy(frob); break; } if (l == lg(lo)) break; } if (dgf == 1) { set_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; set_avma(btop); } for (i = 1; i <= gf->fp; i++) for (j = 1; j <= gt.g; j++) guncloneNULL(gmael(gt.C,i,j)); if (DEBUGLEVEL>=4 && res) err_printf("Best lift: %d\n",deg); if (deg==1) return gc_NULL(ltop); else { /* Normalize result so that psi[g]=1 */ ulong im = Fl_inv(gf->psi[g], deg); GEN cp = perm_powu(res, im); for(i=1;ipsi);i++) gf->psi[i] = Fl_mul(im, gf->psi[i], deg); set_avma(av2); gf->deg = deg; return res; } } /* return NULL if not Galois */ static GEN galoisfindfrobenius(GEN T, GEN L, GEN den, GEN bad, struct galois_frobenius *gf, struct galois_borne *gb, const struct galois_analysis *ga) { pari_sp ltop = avma, av; long Try = 0, n = degpol(T), deg, gmask = (ga->group&ga_ext_2)? 3: 1; GEN frob, Lden = makeLden(L,den,gb); long is_nilpotent = ga->group&ga_all_nilpotent; forprime_t S; u_forprime_init(&S, ga->p, ULONG_MAX); av = avma; deg = gf->deg = ga->deg; while ((gf->p = u_forprime_next(&S))) { pari_sp lbot; GEN Ti, Tp; long nb, d; set_avma(av); Tp = ZX_to_Flx(T, gf->p); if (!Flx_is_squarefree(Tp, gf->p)) continue; if (bad && dvdiu(bad, gf->p)) continue; Ti = gel(Flx_factor(Tp, gf->p), 1); nb = lg(Ti)-1; d = degpol(gel(Ti,1)); if (nb > 1 && degpol(gel(Ti,nb)) != d) return gc_NULL(ltop); if (((gmask&1)==0 || d % deg) && ((gmask&2)==0 || odd(d))) continue; if (DEBUGLEVEL >= 1) err_printf("GaloisConj: Trying p=%ld\n", gf->p); FlxV_to_ZXV_inplace(Ti); gf->fp = d; gf->Tmod = Ti; lbot = avma; if (is_nilpotent) frob = galoisfrobeniuslift_nilp(T, den, L, Lden, gf, gb); else 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 (is_nilpotent) continue; 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) return gc_NULL(ltop); if ((ga->group&ga_non_wss) && ++Try > ((3*n)>>1)) { if (DEBUGLEVEL) pari_warn(warner,"Galois group probably not weakly super solvable"); return NULL; } } if (!gf->p) pari_err_OVERFLOW("galoisfindfrobenius [ran out of primes]"); return NULL; } /* compute g such that tau(Pmod[#])= tau(Pmod[g]) */ static long get_image(GEN tau, GEN P, GEN Pmod, GEN p) { pari_sp av = avma; long g, gp = lg(Pmod)-1; tau = RgX_to_FpX(tau, p); tau = FpX_FpXQ_eval(gel(Pmod, gp), tau, P, p); tau = FpX_normalize(FpX_gcd(P, tau, p), p); for (g = 1; g <= gp; g++) if (ZX_equal(tau, gel(Pmod,g))) return gc_long(av,g); return gc_long(av,0); } static GEN gg_get_std(GEN G) { return !G ? NULL: lg(G)==3 ? G: mkvec2(gel(G,1),gmael(G,5,1)); } static GEN galoisgen(GEN T, GEN L, GEN M, GEN den, GEN bad, struct galois_borne *gb, const struct galois_analysis *ga); static GEN galoisgenfixedfield(GEN Tp, GEN Pmod, GEN PL, GEN P, GEN ip, GEN bad, struct galois_borne *gb) { GEN Pden, PM; GEN tau, PG, Pg; long g, lP; long x = varn(Tp); GEN Pp = FpX_red(P, ip); if (DEBUGLEVEL>=6) err_printf("GaloisConj: Fixed field %Ps\n",P); if (degpol(P)==2 && !bad) { PG=cgetg(3,t_VEC); gel(PG,1) = mkvec( mkvecsmall2(2,1) ); gel(PG,2) = mkvecsmall(2); tau = deg1pol_shallow(gen_m1, negi(gel(P,3)), x); g = get_image(tau, Pp, Pmod, ip); if (!g) return NULL; Pg = mkvecsmall(g); } else { struct galois_analysis Pga; struct galois_borne Pgb; GEN mod, mod2; long j; if (!galoisanalysis(P, &Pga, 0, NULL)) return NULL; if (bad) Pga.group &= ~ga_easy; 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 = FpV_invVandermonde(PL, Pden, Pgb.ladicabs); PG = galoisgen(P, PL, PM, Pden, bad ? lcmii(Pgb.dis, bad): NULL, &Pgb, &Pga); if (!PG) return NULL; lP = lg(gel(PG,1)); mod = Pgb.ladicabs; mod2 = shifti(mod, -1); Pg = cgetg(lP, t_VECSMALL); for (j = 1; j < lP; j++) { pari_sp btop=avma; tau = permtopol(gmael(PG,1,j), PL, PM, Pden, mod, mod2, x); g = get_image(tau, Pp, Pmod, ip); if (!g) return NULL; Pg[j] = g; set_avma(btop); } } return mkvec2(PG,Pg); } static GEN galoisgenfixedfield0(GEN O, GEN L, GEN sigma, GEN T, GEN bad, GEN *pt_V, struct galois_frobenius *gf, struct galois_borne *gb) { pari_sp btop = avma; long vT = varn(T); GEN mod = gb->ladicabs, mod2 = shifti(gb->ladicabs,-1); GEN OL, sym, P, PL, p, Tp, Sp, Pmod, PG; OL = fixedfieldorbits(O,L); sym = fixedfieldsympol(OL, itou(gb->l)); PL = sympol_eval(sym, OL, mod); P = FpX_center_i(FpV_roots_to_pol(PL, mod, vT), mod, mod2); if (!FpX_is_squarefree(P,utoipos(gf->p))) { GEN badp = lcmii(bad? bad: gb->dis, ZX_disc(P)); gf->p = findpsi(badp, gf->p, T, sigma, gf->deg, &gf->Tmod, &gf->psi); } p = utoipos(gf->p); Tp = FpX_red(T,p); Sp = sympol_aut_evalmod(sym, gf->deg, sigma, Tp, p); Pmod = fixedfieldfactmod(Sp, p, gf->Tmod); PG = galoisgenfixedfield(Tp, Pmod, PL, P, p, bad, gb); if (PG == NULL) return NULL; if (DEBUGLEVEL >= 4) err_printf("GaloisConj: Back to Earth:%Ps\n", gg_get_std(gel(PG,1))); if (pt_V) *pt_V = mkvec3(sym, PL, P); return gc_all(btop, pt_V ? 4: 3, &PG, &gf->Tmod, &gf->psi, pt_V); } /* Let sigma^m=1, tau*sigma*tau^-1=sigma^s. Return n = sum_{0<=k=1; i--) { si = Fl_powu(si,e,m); w[i] = Fl_mul(s-1, stpow(si, w[i], m), m); } return w; } static GEN galoisgenliftauto(GEN O, GEN gj, long s, long n, struct galois_test *td) { pari_sp av = avma; long sr, k; long deg = lg(gel(O,1))-1; GEN X = cgetg(lg(O), t_VECSMALL); GEN oX = cgetg(lg(O), t_VECSMALL); GEN B = perm_cycles(gj); long oj = lg(gel(B,1)) - 1; GEN F = factoru(oj); GEN Fp = gel(F,1); GEN Fe = gel(F,2); GEN pf = identity_perm(n); if (DEBUGLEVEL >= 6) err_printf("GaloisConj: %Ps of relative order %d\n", gj, oj); for (k=lg(Fp)-1; k>=1; k--) { long f, dg = 1, el = oj, osel = 1, a = 0; long p = Fp[k], e = Fe[k], op = oj / upowuu(p,e); long i; GEN pf1 = NULL, w, wg, Be = cgetg(e+1,t_VEC); gel(Be,e) = cyc_pow(B, op); for(i=e-1; i>=1; i--) gel(Be,i) = cyc_pow(gel(Be,i+1), p); w = wpow(Fl_powu(s,op,deg),deg,p,e); wg = cgetg(e+2,t_VECSMALL); wg[e+1] = deg; for (i=e; i>=1; i--) wg[i] = ugcd(wg[i+1], w[i]); for (i=1; i= 6) err_printf("GaloisConj: B=%Ps\n", Bel); sr = ugcd(stpow(sel,p,deg),deg); if (DEBUGLEVEL >= 6) err_printf("GaloisConj: exp %d: s=%ld [%ld] a=%ld w=%ld wg=%ld sr=%ld\n", dg, sel, deg, a, w[f], wg[f+1], sr); for (t = 0; t < sr; t++) if ((a+t*w[f])%wg[f+1]==0) { long i, j, k, st; for (i = 1; i < lg(X); i++) X[i] = 0; for (i = 0; i < lg(X)-1; i+=dg) for (j = 1, k = p, st = t; k <= dg; j++, k += p) { X[k+i] = (oX[j+i] + st)%deg; st = (t + st*osel)%deg; } pf1 = testpermutation(O, Bel, X, sel, p, sr, td); if (pf1) break; } if (!pf1) return NULL; for (i=1; i=1; i--) { GEN pi = gel(p,i); long ei = uel(e,i); for(j = 1; j <= ei; j++) s = uel(pi, s); } return s; } static GEN pc_to_perm(GEN pc, GEN gen, long n) { long i, l = lg(pc); GEN s = identity_perm(n); for (i=1; ilg(W)-1) pari_err_BUG("W1"); if (W[s]) continue; W[s] = 1; if (no > l) pari_err_BUG("genorbit"); uel(orb,no) = s; gel(gen,no) = zv_copy(E); no++; } if(no g[i+1]) { GEN v = vecsmall_concat(vecslice(g,1,i-1), br_get(br,g[i],g[i+1])); GEN w = vecsmall_concat(mkvecsmall2(g[i+1],g[i]),vecslice(g,i+2,l)); v = vecsmall_concat(v, w); return pc_normalize(v, G); } else o = 1; } return g; } static GEN pc_inv(GEN g, GEN G) { long i, l = lg(g); GEN ord = pcgrp_get_ord(G), pw = pcgrp_get_pow(G); GEN v = cgetg(l, t_VEC); if (l==1) return v; for(i = 1; i < l; i++) { ulong gi = uel(g,i); gel(v,l-i) = vecsmall_concat(pc_inv(gel(pw, gi), G), const_vecsmall(uel(ord,gi)-1,gi)); } return pc_normalize(shallowconcat1(v), G); } static GEN pc_mul(GEN g, GEN h, GEN G) { return pc_normalize(vecsmall_concat(g,h), G); } static GEN pc_bracket(GEN g, GEN h, GEN G) { GEN gh = pc_mul(g, h, G); GEN hg = pc_mul(h, g, G); long i, l1 = lg(gh), l2 = lg(hg), lm = minss(l1,l2); for (i = 1; i < lm; i++) if (gh[l1-i] != hg[l2-i]) break; return pc_mul(vecsmall_shorten(gh,l1-i), pc_inv(vecsmall_shorten(hg,l2-i), G), G); } static GEN pc_exp(GEN v) { long i, l = lg(v); GEN w = cgetg(l, t_VEC); if (l==1) return w; for (i = 1; i < l; i++) gel(w,i) = const_vecsmall(v[i], i+1); return shallowconcat1(w); } static GEN vecsmall_increase(GEN x) { pari_APPLY_ulong(x[i]+1) } static GEN vecvecsmall_increase(GEN x) { pari_APPLY_same(vecsmall_increase(gel(x,i))) } static GEN pcgrp_lift(GEN G, long deg) { GEN ord = pcgrp_get_ord(G), pw = pcgrp_get_pow(G), br = pcgrp_get_br(G); long i, l = lg(br); GEN Ord = vecsmall_prepend(ord, deg); GEN Pw = vec_prepend(vecvecsmall_increase(pw), cgetg(1,t_VECSMALL)); GEN Br = cgetg(l+1, t_VEC); gel(Br,1) = const_vec(l-1, cgetg(1, t_VECSMALL)); for (i = 1; i < l; i++) gel(Br,i+1) = vecvecsmall_increase(gel(br, i)); return mkvec3(Ord, Pw, Br); } static GEN brl_add(GEN x, GEN a) { pari_APPLY_same(vecsmall_concat(const_vecsmall(uel(a,i),1),gel(x,i))) } static void pcgrp_insert(GEN G, long j, GEN a) { GEN pw = pcgrp_get_pow(G), br = pcgrp_get_br(G); gel(pw,j) = vecsmall_concat(gel(a,1),gel(pw, j)); gel(br,j) = brl_add(gel(br, j), gel(a,2)); } static long getfr(GEN f, GEN h) { long i, l = lg(f); for (i = 1; i < l; i++) if (zv_equal(gel(f,i), h)) return i; pari_err_BUG("galoisinit"); return 0; } static long get_pow(GEN pf, ulong o, GEN pw, GEN gen) { long i, n = lg(pf)-1; GEN p1 = perm_powu(pf, o); GEN p2 = pc_to_perm(pw, gen, n); for(i = 0; ; i++) { if (zv_equal(p1, p2)) break; p2 = perm_mul(gel(gen,1), p2); } return i; } struct galois_perm { GEN L; GEN M; GEN den; GEN mod, mod2; long x; GEN cache; }; static void galoisperm_init(struct galois_perm *gp, GEN L, GEN M, GEN den, GEN mod, GEN mod2, long x) { gp->L = L; gp->M = M; gp->den = den; gp->mod = mod; gp->mod2 = mod2; gp->x = x; gp->cache = zerovec(lg(L)-1); } static void galoisperm_free(struct galois_perm *gp) { long i, l = lg(gp->cache); for (i=1; icache,i))) gunclone(gel(gp->cache,i)); } static GEN permtoaut(GEN p, struct galois_perm *gp) { pari_sp av = avma; if (isintzero(gel(gp->cache,p[1]))) { GEN pol = permtopol(p, gp->L, gp->M, gp->den, gp->mod, gp->mod2, gp->x); gel(gp->cache,p[1]) = gclone(pol); } set_avma(av); return gel(gp->cache,p[1]); } static GEN pc_evalcache(GEN W, GEN u, GEN sp, GEN T, GEN p, struct galois_perm *gp) { GEN v; long ns = sp[1]; if (!isintzero(gel(W,ns))) return gel(W,ns); v = RgX_to_FpX(permtoaut(sp, gp), p); gel(W,ns) = FpX_FpXQV_eval(v, u, T, p); return gel(W,ns); } static ulong findp(GEN D, GEN P, GEN S, long o, GEN *Tmod) { forprime_t iter; ulong p; long n = degpol(P); u_forprime_init(&iter, n*maxss(expu(n)-3, 2), ULONG_MAX); while ((p = u_forprime_next(&iter))) { GEN F, F1, Sp; if (smodis(D, p) == 0) continue; F = gel(Flx_factor(ZX_to_Flx(P, p), p), 1); F1 = gel(F,1); if (degpol(F1) != o) continue; Sp = RgX_to_Flx(S, p); if (gequal(Flx_rem(Sp, F1, p), Flx_Frobenius(F1, p))) { *Tmod = FlxV_to_ZXV(F); return p; } } return 0; } static GEN nilp_froblift(GEN genG, GEN autH, long j, GEN pcgrp, GEN idp, GEN incl, GEN H, struct galois_lift *gl, struct galois_perm *gp) { pari_sp av = avma; GEN T = gl->T, p = gl->p, pe = gl->Q; ulong pp = itou(p); long e = gl->e; GEN pf = cgetg(lg(gl->L), t_VECSMALL); GEN Tp = ZX_to_Flx(T, pp); GEN Hp = ZX_to_Flx(H, pp); GEN ord = pcgrp_get_ord(pcgrp); GEN pcp = gel(pcgrp_get_pow(pcgrp),j+1); long o = uel(ord,1); GEN ordH = vecslice(ord,2,lg(ord)-1); long n = zv_prod(ordH), k = lg(ordH)-1, l = k-j, m = upowuu(o, l), v = varn(T); GEN factTp = gel(Flx_factor(Tp, pp), 1); long fp = degpol(gel(factTp, 1)); GEN frobp = Flxq_autpow(Flx_Frobenius(Tp, pp), fp-1, Tp, pp); GEN frob = ZpX_ZpXQ_liftroot(T, Flx_to_ZX(frobp), T, p, e); if (galoisfrobeniustest(frob, gl, pf)) { GEN pfi = perm_inv(pf); long d = get_pow(pfi, uel(ord,j+1), pcp, genG); return mkvec3(pfi, mkvec2(const_vecsmall(d,1),zero_zv(l+1)), gel(factTp, 1)); } else { GEN frobG = FpXQ_powers(frob, usqrt(degpol(T)), T, pe); GEN autHp = RgXV_to_FlxV(autH,pp); GEN inclp = RgX_to_Flx(incl,pp); GEN factHp = gel(Flx_factor(Hp, pp),1); long fr = getfr(factHp, idp); GEN minHp = FlxV_minpolymod(autHp, factHp, pp); GEN permfact_Hp = factperm(minHp); GEN permfact_Gp = FlxV_Flx_gcd(FlxC_Flxq_eval(factHp, inclp, Tp, pp), Tp, pp); GEN bezout_Gpe = bezout_lift_fact(T, FlxV_to_ZXV(permfact_Gp), p, e); GEN id = gmael(Flx_factor(gel(permfact_Gp, fr),pp),1,1); GEN orbgen = genorbit(ordH, permfact_Hp, fr, n, k, j); GEN orb = gel(orbgen,1), gen = gel(orbgen,2); long nborb = lg(orb)-1; GEN A = cgetg(l+1, t_VECSMALL); GEN W = zerovec(lg(gl->L)-1); GEN U = zeromatcopy(nborb,degpol(T)); GEN br = pcgrp_get_br(pcgrp), brj = gcopy(gel(br, j+1)); GEN Ui = cgetg(nborb+1, t_VEC); long a, b, i; for(a = 0; a < m; a++) { pari_timer ti; pari_sp av2; GEN B = pol_0(v); long aa = a; if (DEBUGLEVEL>=4) timer_start(&ti); for(i = 1; i <= l; i++) { uel(A,i) = aa % o; aa /= o; } gel(br,j+1) = brl_add(brj, A); for(b = 1; b <= nborb; b++) { GEN br = pc_bracket(pc_exp(gel(gen,b)), mkvecsmall(j+1), pcgrp); GEN sp = pc_to_perm(br, genG, degpol(T)); long u = sp[1]; long s = permprodeval(permfact_Hp, gel(gen,b), fr); if (isintzero(gmael(U,u,s))) { GEN Ub = pc_evalcache(W, frobG, sp, T, pe, gp); gmael(U,u,s) = FpXQ_mul(Ub, gel(bezout_Gpe,s), T, pe); } gel(Ui, b) = gmael(U,u,s); } av2 = avma; for(b = 1; b <= nborb; b++) B = FpX_add(B, gel(Ui,b), pe); if (DEBUGLEVEL >= 4) timer_printf(&ti,"Testing candidate %ld",a); if (galoisfrobeniustest(B, gl, pf)) { GEN pfi = perm_inv(pf); long d = get_pow(pfi, uel(ord,j+1), pcp, genG); gel(br,j+1) = brj; return gerepilecopy(av,mkvec3(pfi,mkvec2(const_vecsmall(d,1),A),id)); } set_avma(av2); } return gc_NULL(av); } } static GEN galoisgenlift_nilp(GEN PG, GEN O, GEN V, GEN T, GEN frob, GEN sigma, struct galois_borne *gb, struct galois_frobenius *gf, struct galois_perm *gp) { long j, n = degpol(T), deg = gf->deg; ulong p = gf->p; GEN L = gp->L, M = gp->M, den = gp->den; GEN S = fixedfieldinclusion(O, gel(V,2)); GEN incl = vectopol(S, M, den, gb->ladicabs, shifti(gb->ladicabs,-1), varn(T)); GEN H = gel(V,3); GEN PG1 = gmael(PG, 1, 1); GEN PG2 = gmael(PG, 1, 2); GEN PG3 = gmael(PG, 1, 3); GEN PG4 = gmael(PG, 1, 4); long lP = lg(PG1); GEN PG5 = pcgrp_lift(gmael(PG, 1, 5), deg); GEN res = cgetg(6, t_VEC), res1, res2, res3; gel(res,1) = res1 = cgetg(lP + 1, t_VEC); gel(res,2) = res2 = cgetg(lP + 1, t_VEC); gel(res,3) = res3 = cgetg(lP + 1, t_VEC); gel(res,4) = vecsmall_prepend(PG4, p); gel(res,5) = PG5; gel(res1, 1) = frob; gel(res2, 1) = ZX_to_Flx(gel(gf->Tmod,1), p); gel(res3, 1) = sigma; for (j = 1; j < lP; j++) { struct galois_lift gl; GEN Lden = makeLden(L,den,gb); GEN pf; initlift(T, den, uel(PG4,j), L, Lden, gb, &gl); pf = nilp_froblift(vecslice(res1,1,j), PG3, j, PG5, gel(PG2,j), incl, H, &gl, gp); if (!pf) return NULL; if (DEBUGLEVEL>=2) err_printf("found: %ld/%ld: %Ps: %Ps\n", n, j+1, gel(pf,2),gel(pf,1)); pcgrp_insert(PG5, j+1, gel(pf,2)); gel(res1, j+1) = gel(pf,1); gel(res2, j+1) = gel(pf,3); gel(res3, j+1) = gcopy(permtoaut(gel(pf,1), gp)); } if (DEBUGLEVEL >= 4) err_printf("GaloisConj: Fini!\n"); return res; } static GEN galoisgenlift(GEN PG, GEN Pg, GEN O, GEN L, GEN M, GEN frob, struct galois_borne *gb, struct galois_frobenius *gf) { struct galois_test td; GEN res, res1; GEN PG1 = gel(PG, 1), PG2 = gel(PG, 2); long lP = lg(PG1), j, n = lg(L)-1; inittest(L, M, gb->bornesol, gb->ladicsol, &td); res = cgetg(3, t_VEC); gel(res,1) = res1 = cgetg(lP + 1, t_VEC); gel(res,2) = vecsmall_prepend(PG2, gf->deg); gel(res1, 1) = vecsmall_copy(frob); for (j = 1; j < lP; j++) { GEN pf = galoisgenliftauto(O, gel(PG1, j), gf->psi[Pg[j]], n, &td); if (!pf) { freetest(&td); return NULL; } gel(res1, j+1) = pf; } if (DEBUGLEVEL >= 4) err_printf("GaloisConj: Fini!\n"); freetest(&td); return res; } static ulong psi_order(GEN psi, ulong d) { long i, l = lg(psi); ulong s = 1; for (i=1; ideg) return NULL; x = varn(T); if (DEBUGLEVEL >= 9) err_printf("GaloisConj: denominator:%Ps\n", den); if (n == 12 && ga->ord==3 && !ga->p4) { /* A4 is very probable: test it first */ pari_sp av = avma; if (DEBUGLEVEL >= 4) err_printf("GaloisConj: Testing A4 first\n"); inittest(L, M, gb->bornesol, gb->ladicsol, &td); PG = a4galoisgen(&td); freetest(&td); if (PG) return gerepileupto(ltop, PG); set_avma(av); } if (n == 24 && ga->ord==3 && ga->p4) { /* S4 is very probable: test it first */ pari_sp av = avma; struct galois_lift gl; if (DEBUGLEVEL >= 4) err_printf("GaloisConj: Testing S4 first\n"); initlift(T, den, ga->p4, L, makeLden(L,den,gb), gb, &gl); PG = s4galoisgen(&gl); if (PG) return gerepileupto(ltop, PG); set_avma(av); } if (n == 36 && ga->ord==3 && ga->p4) { /* F36 is very probable: test it first */ pari_sp av = avma; struct galois_lift gl; if (DEBUGLEVEL >= 4) err_printf("GaloisConj: Testing 3x3:4 first (p=%ld)\n",ga->p4); initlift(T, den, ga->p4, L, makeLden(L,den,gb), gb, &gl); PG = f36galoisgen(&gl); if (PG) return gerepileupto(ltop, PG); set_avma(av); } frob = galoisfindfrobenius(T, L, den, bad, &gf, gb, ga); if (!frob) return gc_NULL(ltop); po = psi_order(gf.psi, gf.deg); if (!(ga->group&ga_easy) && po < (ulong) gf.deg && gf.deg/radicalu(gf.deg)%po == 0) { is_central = 1; if (!bad) bad = gb->dis; if (po > 1) { ofrob = frob; ogf = gf; frob = perm_powu(frob, po); gf.deg /= po; } } else is_central = 0; sigma = permtopol(frob, L, M, den, gb->ladicabs, shifti(gb->ladicabs,-1), x); if (is_central && gf.fp != gf.deg) { gf.p = findp(bad, T, sigma, gf.deg, &gf.Tmod); gf.fp = gf.deg; gf.psi = const_vecsmall(lg(gf.Tmod)-1, 1); } if (gf.deg == n) /* cyclic */ { GEN Tp = ZX_to_Flx(gel(gf.Tmod,1), gf.p); res = mkvec5(mkvec(frob), mkvec(Tp), mkvec(sigma), mkvecsmall(gf.p), cyclic_pc(n)); return gerepilecopy(ltop, res); } O = perm_cycles(frob); if (DEBUGLEVEL >= 9) err_printf("GaloisConj: Frobenius:%Ps\n", sigma); PG = galoisgenfixedfield0(O, L, sigma, T, is_central ? bad: NULL, is_central ? &V: NULL, &gf, gb); if (PG == NULL) return gc_NULL(ltop); if (is_central && lg(gel(PG,1))!=3) { struct galois_perm gp; galoisperm_init(&gp, L, M, den, gb->ladicabs, shifti(gb->ladicabs,-1), varn(T)); res = galoisgenlift_nilp(PG, O, V, T, frob, sigma, gb, &gf, &gp); galoisperm_free(&gp); } else { if (is_central && po > 1) { /* backtrack powering of frob */ frob = ofrob; gf = ogf; O = perm_cycles(ofrob); sigma = permtopol(ofrob, L, M, den, gb->ladicabs, shifti(gb->ladicabs,-1), x); PG = galoisgenfixedfield0(O, L, sigma, T, NULL, NULL, &gf, gb); if (PG == NULL) return gc_NULL(ltop); } res = galoisgenlift(gg_get_std(gel(PG,1)), gel(PG,2), O, L, M, frob, gb, &gf); } if (!res) return gc_NULL(ltop); return gerepilecopy(ltop, res); } /* T = polcyclo(N) */ static GEN conjcyclo(GEN T, long N) { pari_sp av = avma; long i, k = 1, d = eulerphiu(N), v = varn(T); GEN L = cgetg(d+1,t_COL); for (i=1; i<=N; i++) if (ugcd(i, N)==1) { GEN s = pol_xn(i, v); if (i >= d) s = ZX_rem(s, T); gel(L,k++) = s; } return gerepileupto(av, gen_sort(L, (void*)&gcmp, &gen_cmp_RgX)); } static GEN aut_to_groupelts(GEN aut, GEN L, ulong p) { pari_sp av = avma; long i, d = lg(aut)-1; GEN P = ZV_to_Flv(L, p); GEN N = FlxV_Flv_multieval(aut, P, p); GEN q = perm_inv(vecsmall_indexsort(P)); GEN G = cgetg(d+1, t_VEC); for (i=1; i<=d; i++) gel(G,i) = perm_mul(vecsmall_indexsort(gel(N,i)), q); return gerepilecopy(av, vecvecsmall_sort_shallow(G)); } static ulong galois_find_totally_split(GEN P, GEN Q) { pari_sp av = avma; forprime_t iter; ulong p; long n = degpol(P); u_forprime_init(&iter, n*maxss(expu(n)-3, 2), ULONG_MAX); while ((p = u_forprime_next(&iter))) { if (Flx_is_totally_split(ZX_to_Flx(P, p), p) && (!Q || Flx_is_squarefree(ZX_to_Flx(Q, p), p))) return gc_ulong(av, p); set_avma(av); } return 0; } GEN galoisinitfromaut(GEN T, GEN aut, ulong l) { pari_sp ltop = avma; GEN nf, A, G, L, M, grp, den=NULL; 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 = nf_get_zkden(nf); } else { if (n <= 0) pari_err_IRREDPOL("galoisinit",T); RgX_check_ZX(T, "galoisinit"); if (!ZX_is_squarefree(T)) pari_err_DOMAIN("galoisinit","issquarefree(pol)","=",gen_0,T); if (!gequal1(gel(T,n+2))) pari_err_IMPL("galoisinit(nonmonic)"); } if (lg(aut)-1 != n) return gen_0; ga.l = l? l: galois_find_totally_split(T, NULL); if (!l) aut = RgXV_to_FlxV(aut, ga.l); 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 = ZpX_roots(T, gb.l, gb.valabs); if (DEBUGLEVEL >= 1) timer_printf(&ti, "ZpX_roots"); M = FpV_invVandermonde(L, den, gb.ladicabs); if (DEBUGLEVEL >= 1) timer_printf(&ti, "FpV_invVandermonde()"); A = aut_to_groupelts(aut, L, ga.l); G = groupelts_to_group(A); if (!G) G = trivialgroup(); else A = group_elts(G,n); grp = cgetg(9, t_VEC); gel(grp,1) = T; gel(grp,2) = mkvec3(utoipos(ga.l), utoipos(gb.valabs), gb.ladicabs); gel(grp,3) = L; gel(grp,4) = M; gel(grp,5) = den; gel(grp,6) = A; gel(grp,7) = gel(G,1); gel(grp,8) = gel(G,2); return gerepilecopy(ltop, grp); } GEN galoissplittinginit(GEN T, GEN D) { pari_sp av = avma; GEN R = nfsplitting0(T, D, 3), P = gel(R,1), aut = gel(R,2); ulong p = itou(gel(R,3)); return gerepileupto(av, galoisinitfromaut(P, aut, p)); } /* 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, grp; struct galois_analysis ga; struct galois_borne gb; long n; pari_timer ti; T = get_nfpol(T, &nf); n = poliscyclo(T); if (n) return flag? galoiscyclo(n, varn(T)): conjcyclo(T, n); n = degpol(T); if (nf) { if (!den) den = nf_get_zkden(nf); } else { if (n <= 0) pari_err_IRREDPOL("galoisinit",T); RgX_check_ZX(T, "galoisinit"); if (!ZX_is_squarefree(T)) pari_err_DOMAIN("galoisinit","issquarefree(pol)","=",gen_0,T); if (!gequal1(gel(T,n+2))) pari_err_IMPL("galoisinit(nonmonic)"); } 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, NULL)) return gc_NULL(ltop); if (den) { if (typ(den) != t_INT) pari_err_TYPE("galoisconj4 [2nd arg integer]", den); den = absi_shallow(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 = ZpX_roots(T, gb.l, gb.valabs); if (DEBUGLEVEL >= 1) timer_printf(&ti, "ZpX_roots"); M = FpV_invVandermonde(L, den, gb.ladicabs); if (DEBUGLEVEL >= 1) timer_printf(&ti, "FpV_invVandermonde()"); if (n == 1) { G = cgetg(3, t_VEC); gel(G,1) = cgetg(1, t_VEC); gel(G,2) = cgetg(1, t_VECSMALL); } else G = gg_get_std(galoisgen(T, L, M, den, NULL, &gb, &ga)); if (DEBUGLEVEL >= 6) err_printf("GaloisConj: %Ps\n", G); if (!G) return gc_NULL(ltop); if (DEBUGLEVEL >= 1) timer_start(&ti); grp = cgetg(9, t_VEC); gel(grp,1) = T; gel(grp,2) = mkvec3(utoipos(ga.l), utoipos(gb.valabs), gb.ladicabs); gel(grp,3) = L; gel(grp,4) = M; gel(grp,5) = den; gel(grp,6) = group_elts(G,n); gel(grp,7) = gel(G,1); gel(grp,8) = gel(G,2); if (flag) return gerepilecopy(ltop, grp); aut = galoisvecpermtopol(grp, gal_get_group(grp), gb.ladicabs, shifti(gb.ladicabs,-1)); settyp(aut, t_COL); if (DEBUGLEVEL >= 1) timer_printf(&ti, "Computation of polynomials"); return gerepileupto(ltop, gen_sort(aut, (void*)&gcmp, &gen_cmp_RgX)); } /* Heuristic computation of #Aut(T), pinit = first prime to be tested */ long numberofconjugates(GEN T, long pinit) { pari_sp av = avma; long c, nbtest, nbmax, n = degpol(T); ulong p; forprime_t S; if (n == 1) return 1; nbmax = (n < 10)? 20: (n<<1) + 1; nbtest = 0; #if 0 c = ZX_sturm(T); c = ugcd(c, n-c); /* too costly: finite primes are cheaper */ #else c = n; #endif u_forprime_init(&S, pinit, ULONG_MAX); while((p = u_forprime_next(&S))) { GEN L, Tp = ZX_to_Flx(T,p); long i, nb; if (!Flx_is_squarefree(Tp, p)) continue; /* unramified */ nbtest++; L = Flx_nbfact_by_degree(Tp, &nb, p); /* L[i] = #factors of degree i */ if (L[n/nb] == nb) { if (c == n && nbtest > 10) break; /* probably Galois */ } else { c = ugcd(c, L[1]); for (i = 2; i <= n; i++) if (L[i]) { c = ugcd(c, L[i]*i); if (c == 1) break; } if (c == 1) break; } if (nbtest == nbmax) break; if (DEBUGLEVEL >= 6) err_printf("NumberOfConjugates [%ld]:c=%ld,p=%ld\n", nbtest,c,p); set_avma(av); } if (DEBUGLEVEL >= 2) err_printf("NumberOfConjugates:c=%ld,p=%ld\n", c, p); return gc_long(av,c); } static GEN galoisconj4(GEN nf, GEN d) { pari_sp av = avma; GEN G, T; G = galoisconj4_main(nf, d, 0); if (G) return G; /* Success */ set_avma(av); T = get_nfpol(nf, &nf); G = cgetg(2, t_COL); gel(G,1) = pol_x(varn(T)); return G; /* Fail */ } /* d multiplicative bound for the automorphism's denominators */ static GEN galoisconj_monic(GEN nf, GEN d) { pari_sp av = avma; GEN G, NF, T = get_nfpol(nf,&NF); if (degpol(T) == 2) { /* fast shortcut */ GEN b = gel(T,3); long v = varn(T); G = cgetg(3, t_COL); gel(G,1) = deg1pol_shallow(gen_m1, negi(b), v); gel(G,2) = pol_x(v); return G; } G = galoisconj4_main(nf, d, 0); if (G) return G; /* Success */ set_avma(av); return galoisconj1(nf); } GEN galoisconj(GEN nf, GEN d) { pari_sp av; GEN NF, S, L, T = get_nfpol(nf,&NF); if (NF) return galoisconj_monic(NF, d); RgX_check_QX(T, "galoisconj"); av = avma; T = Q_primpart(T); if (ZX_is_monic(T)) return galoisconj_monic(T, d); S = galoisconj_monic(poltomonic(T,&L), NULL); return gerepileupto(av, gdiv(RgXV_unscale(S, L),L)); } /* FIXME: obsolete, use galoisconj(nf, d) directly */ GEN galoisconj0(GEN nf, long flag, GEN d, long prec) { (void)prec; switch(flag) { case 2: case 0: return galoisconj(nf, d); case 1: return galoisconj1(nf); case 4: return galoisconj4(nf, d); } pari_err_FLAG("nfgaloisconj"); return NULL; /*LCOV_EXCL_LINE*/ } /******************************************************************************/ /* Galois theory related algorithms */ /******************************************************************************/ GEN checkgal(GEN gal) { if (typ(gal) == t_POL) pari_err_TYPE("checkgal [apply galoisinit first]",gal); if (typ(gal) != t_VEC || lg(gal) != 9) pari_err_TYPE("checkgal",gal); return gal; } GEN galoisinit(GEN nf, GEN den) { GEN G; if (is_vec_t(typ(nf)) && lg(nf)==3 && is_vec_t(typ(gel(nf,2)))) return galoisinitfromaut(gel(nf,1), gel(nf,2), 0); G = galoisconj4_main(nf, den, 1); return G? G: gen_0; } static GEN galoispermtopol_i(GEN gal, GEN perm, GEN mod, GEN mod2) { switch (typ(perm)) { case t_VECSMALL: return permtopol(perm, gal_get_roots(gal), gal_get_invvdm(gal), gal_get_den(gal), mod, mod2, varn(gal_get_pol(gal))); case t_VEC: case t_COL: case t_MAT: return galoisvecpermtopol(gal, perm, mod, mod2); } pari_err_TYPE("galoispermtopol", perm); return NULL; /* LCOV_EXCL_LINE */ } GEN galoispermtopol(GEN gal, GEN perm) { pari_sp av = avma; GEN mod, mod2; gal = checkgal(gal); mod = gal_get_mod(gal); mod2 = shifti(mod,-1); return gerepilecopy(av, galoispermtopol_i(gal, perm, mod, mod2)); } GEN galoiscosets(GEN O, GEN perm) { long i, j, k, u, f, l = lg(O); GEN RC, C = cgetg(l,t_VECSMALL), o = gel(O,1); pari_sp av = avma; f = lg(o); u = o[1]; RC = zero_zv(lg(perm)-1); for(i=1,j=1; j=4) err_printf("GaloisFixedField:cosets=%Ps \n",cosets); if (DEBUGLEVEL>=6) err_printf("GaloisFixedField:den=%Ps mod=%Ps \n",den,mod); V = cgetg(l,t_COL); res = cgetg(l,t_VEC); for (i = 1; i < l; i++) { pari_sp av = avma; GEN G = cgetg(l,t_VEC), Lp = vecpermute(L, gel(perm, cosets[i])); for (k = 1; k < l; k++) gel(G,k) = FpV_roots_to_pol(vecpermute(Lp, gel(O,k)), mod, x); for (j = 1; j < lo; j++) { for(k = 1; k < l; k++) gel(V,k) = gmael(G,k,j+1); gel(F,j) = vectopol(V, M, den, mod, mod2, y); } gel(res,i) = gerepileupto(av,gtopolyrev(F,x)); } return gerepileupto(ltop,res); } static void chk_perm(GEN perm, long n) { if (typ(perm) != t_VECSMALL || lg(perm)!=n+1) pari_err_TYPE("galoisfixedfield", perm); } static int is_group(GEN g) { if (typ(g) == t_VEC && lg(g) == 3) { GEN a = gel(g,1), o = gel(g,2); return typ(a)==t_VEC && typ(o)==t_VECSMALL && lg(a) == lg(o); } return 0; } GEN galoisfixedfield(GEN gal, GEN perm, long flag, long y) { pari_sp ltop = avma; GEN T, L, P, S, PL, O, res, mod, mod2, OL, sym; long vT, n, i; if (flag<0 || flag>2) pari_err_FLAG("galoisfixedfield"); gal = checkgal(gal); T = gal_get_pol(gal); vT = varn(T); L = gal_get_roots(gal); n = lg(L)-1; mod = gal_get_mod(gal); if (typ(perm) == t_VEC) { if (is_group(perm)) perm = gel(perm, 1); for (i = 1; i < lg(perm); i++) chk_perm(gel(perm,i), n); O = vecperm_orbits(perm, n); } else { chk_perm(perm, n); O = perm_cycles(perm); } mod2 = shifti(mod,-1); OL = fixedfieldorbits(O, L); sym = fixedfieldsympol(OL, itou(gal_get_p(gal))); PL = sympol_eval(sym, OL, mod); P = FpX_center_i(FpV_roots_to_pol(PL, mod, vT), mod, mod2); if (flag==1) return gerepilecopy(ltop,P); S = fixedfieldinclusion(O, PL); S = vectopol(S, gal_get_invvdm(gal), gal_get_den(gal), mod, mod2, vT); if (flag==0) res = cgetg(3, t_VEC); else { GEN PM, Pden; struct galois_borne Pgb; long val = itos(gal_get_e(gal)); Pgb.l = gal_get_p(gal); Pden = galoisborne(P, NULL, &Pgb, degpol(T)/degpol(P)); if (Pgb.valabs > val) { if (DEBUGLEVEL>=4) err_printf("GaloisConj: increase p-adic prec by %ld.\n", Pgb.valabs-val); PL = ZpX_liftroots(P, PL, Pgb.l, Pgb.valabs); L = ZpX_liftroots(T, L, Pgb.l, Pgb.valabs); mod = Pgb.ladicabs; mod2 = shifti(mod,-1); } PM = FpV_invVandermonde(PL, Pden, mod); if (y < 0) y = 1; if (varncmp(y, vT) <= 0) pari_err_PRIORITY("galoisfixedfield", T, "<=", y); setvarn(P, y); res = cgetg(4, t_VEC); gel(res,3) = fixedfieldfactor(L,O,gal_get_group(gal), PM,Pden,mod,mod2,vT,y); } gel(res,1) = gcopy(P); gel(res,2) = gmodulo(S, T); return gerepileupto(ltop, res); } /* gal a galois group output the underlying wss group */ GEN galois_group(GEN gal) { return mkvec2(gal_get_gen(gal), gal_get_orders(gal)); } GEN checkgroup(GEN g, GEN *S) { if (is_group(g)) { *S = NULL; return g; } g = checkgal(g); *S = gal_get_group(g); return galois_group(g); } static GEN group_is_elt(GEN G) { long i, n = lg(G)-1; if (n==0) pari_err_DIM("checkgroupelts"); if (lg(G)==9 && typ(gel(G,1))==t_POL) if (lg(gal_get_gen(G))==1 && lg(gal_get_group(G))>2) return gal_get_group(G); if (typ(G)==t_VEC && typ(gel(G,1))==t_VECSMALL) { for (i = 1; i <= n; i++) { if (typ(gel(G,i)) != t_VECSMALL) pari_err_TYPE("checkgroupelts (element)", gel(G,i)); if (lg(gel(G,i)) != lg(gel(G,1))) pari_err_DIM("checkgroupelts [length of permutations]"); } return G; } return NULL; } GEN checkgroupelts(GEN G) { GEN S = group_is_elt(G); if (S) return S; if (is_group(G)) { /* subgroup of S_n */ if (lg(gel(G,1))==1) return mkvec(mkvecsmall(1)); return group_elts(G, group_domain(G)); } if (lg(G)==9 && typ(gel(G,1))==t_POL) return gal_get_group(G); /* galoisinit */ pari_err_TYPE("checkgroupelts",G); return NULL; /* LCOV_EXCL_LINE */ } GEN galoisisabelian(GEN gal, long flag) { pari_sp av = avma; GEN S, G = checkgroup(gal,&S); if (!group_isabelian(G)) { set_avma(av); return gen_0; } switch(flag) { case 0: return gerepileupto(av, group_abelianHNF(G,S)); case 1: set_avma(av); return gen_1; case 2: return gerepileupto(av, group_abelianSNF(G,S)); default: pari_err_FLAG("galoisisabelian"); } return NULL; /* LCOV_EXCL_LINE */ } 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); set_avma(av); return res; } static GEN conjclasses_count(GEN conj, long nb) { long i, l = lg(conj); GEN c = zero_zv(nb); for (i = 1; i < l; i++) c[conj[i]]++; return c; } GEN galoisconjclasses(GEN G) { pari_sp av = avma; GEN c, e, cc = group_to_cc(G); GEN elts = gel(cc,1), conj = gel(cc,2), repr = gel(cc,3); long i, l = lg(conj), lc = lg(repr); c = conjclasses_count(conj, lc-1); e = cgetg(lc, t_VEC); for (i = 1; i < lc; i++) gel(e,i) = cgetg(c[i]+1, t_VEC); for (i = 1; i < l; i++) { long ci = conj[i]; gmael(e, ci, c[ci]) = gel(elts, i); c[ci]--; } return gerepilecopy(av, e); } static GEN groupelts_to_group_or_elts(GEN elts) { GEN G = groupelts_to_group(elts); return G ? G: gcopy(elts); } static GEN vec_groupelts_to_group_or_elts(GEN x) { pari_APPLY_same(groupelts_to_group_or_elts(gel(x,i))) } GEN galoissubgroups(GEN gal) { pari_sp av = avma; GEN S = group_is_elt(gal), G; if (S) return gerepileupto(av, vec_groupelts_to_group_or_elts(groupelts_solvablesubgroups(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; long idx, card; GEN S = group_is_elt(gal), G; G = S ? S: checkgroup(gal,&S); idx = group_ident(G,S); card = S ? lg(S)-1: group_order(G); set_avma(av); return mkvec2s(card, idx); } /* index of conjugacy class containing g */ static long cc_id(GEN cc, GEN g) { GEN conj = gel(cc,2); long k = signe(gel(cc,4))? g[1]: vecvecsmall_search(gel(cc,1), g); return conj[k]; } static GEN Qevproj_RgX(GEN c, long d, GEN pro) { return RgV_to_RgX(Qevproj_down(RgX_to_RgC(c,d), pro), varn(c)); } /* c in Z[X] / (X^o-1), To = polcyclo(o), T = polcyclo(expo), e = expo/o * return c(X^e) mod T as an element of Z[X] / (To) */ static GEN chival(GEN c, GEN T, GEN To, long e, GEN pro, long phie) { c = ZX_rem(c, To); if (e != 1) c = ZX_rem(RgX_inflate(c,e), T); if (pro) c = Qevproj_RgX(c, phie, pro); return c; } /* chi(g^l) = sum_{k=0}^{o-1} a_k zeta_o^{l*k} for all l; * => a_k = 1/o sum_{l=0}^{o-1} chi(g^l) zeta_o^{-k*l}. Assume o > 1 */ static GEN chiFT(GEN cp, GEN jg, GEN vze, long e, long o, ulong p, ulong pov2) { const long var = 1; ulong oinv = Fl_inv(o,p); long k, l; GEN c = cgetg(o+2, t_POL); for (k = 0; k < o; k++) { ulong a = 0; for (l=0; l 1, exponent of G */ p = unextprime(2*n+1); while (p%expo != 1) p = unextprime(p+1); /* compute character table modulo p: idempotents of Z(KG) */ al = conjclasses_algcenter(cc, utoipos(p)); dec = algsimpledec_ss(al,1); ctp = cgetg(lcl,t_VEC); for(i=1; i>1; ct = cgetg(lcl, t_MAT); if (f == 1) { /* rational representation */ for (j=1; j 2? jg[2]: jg[1]; for(i=1; i 1; j--) { /* loop over conjugacy classes, decreasing order: skip 1_G */ long e, jperm = operm[j], o = vord[jperm]; GEN To, jg = gel(vjg,jperm); /* jg[l+1] = class of g^l */ if (gel(C, jperm)) continue; /* done already */ if (dim == 1) { gel(C, jperm) = gel(vzeZX, cp[jg[2]]); continue; } e = expo / o; cj = chiFT(cp, jg, vze, e, o, p, pov2); To = gel(vT, o); if (!To) To = gel(vT,o) = polcyclo(o, var); gel(C, jperm) = chival(cj, T, To, e, pro, phie); for (k = 2; k < o; k++) { GEN ck = RgX_inflate(cj, k); /* chi(g^k) */ gel(C, jg[k+1]) = chival(ck, T, To, e, pro, phie); } } } } ct = gen_sort_shallow(ct,(void*)cmp_universal,cmp_nodata); i = 1; while (!vec_isconst(gel(ct,i))) i++; if (i > 1) swap(gel(ct,1), gel(ct,i)); return mkvec2(ct, utoipos(f)); } GEN galoischartable(GEN gal) { pari_sp av = avma; GEN cc = group_to_cc(gal); return gerepilecopy(av, cc_chartable(cc)); } static void checkgaloischar(GEN ch, GEN repr) { if (gvar(ch) == 0) pari_err_PRIORITY("galoischarpoly",ch,"=",0); if (!is_vec_t(typ(ch))) pari_err_TYPE("galoischarpoly", ch); if (lg(repr) != lg(ch)) pari_err_DIM("galoischarpoly"); } static long galoischar_dim(GEN ch) { pari_sp av = avma; long d = gtos(simplify_shallow(lift_shallow(gel(ch,1)))); return gc_long(av,d); } static GEN galoischar_aut_charpoly(GEN cc, GEN ch, GEN p, long d) { GEN q = p, V = cgetg(d+2, t_POL); long i; V[1] = evalsigne(1)|evalvarn(0); for (i = 1; i <= d; i++) { gel(V,i+1) = gel(ch, cc_id(cc,q)); if (i < d) q = perm_mul(q, p); } return liftpol_shallow(RgXn_expint(RgX_neg(V),d+1)); } static GEN galoischar_charpoly(GEN cc, GEN ch, long o) { GEN chm, V, elts = gel(cc,1), repr = gel(cc,3); long i, d, l = lg(ch), v = gvar(ch); checkgaloischar(ch, repr); chm = v < 0 ? ch: gmodulo(ch, polcyclo(o, v)); V = cgetg(l, t_COL); d = galoischar_dim(ch); for (i = 1; i < l; i++) gel(V,i) = galoischar_aut_charpoly(cc, chm, gel(elts,repr[i]), d); return V; } GEN galoischarpoly(GEN gal, GEN ch, long o) { pari_sp av = avma; GEN cc = group_to_cc(gal); return gerepilecopy(av, galoischar_charpoly(cc, ch, o)); } static GEN cc_char_det(GEN cc, GEN ch, long o) { long i, l = lg(ch), d = galoischar_dim(ch); GEN V = galoischar_charpoly(cc, ch, o); for (i = 1; i < l; i++) gel(V,i) = leading_coeff(gel(V,i)); return odd(d)? gneg(V): V; } GEN galoischardet(GEN gal, GEN ch, long o) { pari_sp av = avma; GEN cc = group_to_cc(gal); return gerepilecopy(av, cc_char_det(cc, ch, o)); } pari-2.17.2/src/basemath/mftrace.c0000644000175000017500000133245314760123736015350 0ustar billbill/* Copyright (C) 2016 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*************************************************************************/ /* */ /* Modular forms package based on trace formulas */ /* */ /*************************************************************************/ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_mf enum { MF_SPLIT = 1, MF_EISENSPACE, MF_FRICKE, MF_MF2INIT, MF_SPLITN }; typedef struct { GEN vnew, vfull, DATA, VCHIP; long n, newHIT, newTOTAL, cuspHIT, cuspTOTAL; } cachenew_t; static void init_cachenew(cachenew_t *c, long n, long N, GEN f); static long mf1cuspdim_i(long N, GEN CHI, GEN TMP, GEN vSP, long *dih); static GEN mfinit_i(GEN NK, long space); static GEN mfinit_Nkchi(long N, long k, GEN CHI, long space, long flraw); static GEN mf2init_Nkchi(long N, long k, GEN CHI, long space, long flraw); static GEN mf2basis(long N, long r, GEN CHI, GEN *pCHI1, long space); static GEN mfeisensteinbasis(long N, long k, GEN CHI); static GEN mfeisensteindec(GEN mf, GEN F); static GEN initwt1newtrace(GEN mf); static GEN initwt1trace(GEN mf); static GEN myfactoru(long N); static GEN mydivisorsu(long N); static GEN Qab_Czeta(long k, long ord, GEN C, long vt); static GEN mfcoefs_i(GEN F, long n, long d); static GEN bhnmat_extend(GEN M, long m,long l, GEN S, cachenew_t *cache); static GEN initnewtrace(long N, GEN CHI); static void dbg_cachenew(cachenew_t *C); static GEN hecke_i(long m, long l, GEN V, GEN F, GEN DATA); static GEN c_Ek(long n, long d, GEN F); static GEN RgV_heckef2(long n, long d, GEN V, GEN F, GEN DATA); static GEN mfcusptrace_i(long N, long k, long n, GEN Dn, GEN TDATA); static GEN mfnewtracecache(long N, long k, long n, cachenew_t *cache); static GEN colnewtrace(long n0, long n, long d, long N, long k, cachenew_t *c); static GEN dihan(GEN bnr, GEN w, GEN k0j, long m, ulong n); static GEN sigchi(long k, GEN CHI, long n); static GEN sigchi2(long k, GEN CHI1, GEN CHI2, long n, long ord); static GEN mflineardivtomat(long N, GEN vF, long n); static GEN mfdihedralcusp(long N, GEN CHI, GEN vSP); static long mfdihedralcuspdim(long N, GEN CHI, GEN vSP); static GEN mfdihedralnew(long N, GEN CHI, GEN SP); static GEN mfdihedral(long N); static GEN mfdihedralall(long N); static long mf1cuspdim(long N, GEN CHI, GEN vSP); static long mf2dim_Nkchi(long N, long k, GEN CHI, ulong space); static long mfdim_Nkchi(long N, long k, GEN CHI, long space); static GEN charLFwtk(long N, long k, GEN CHI, long ord, long t); static GEN mfeisensteingacx(GEN E,long w,GEN ga,long n,long prec); static GEN mfgaexpansion(GEN mf, GEN F, GEN gamma, long n, long prec); static GEN mfEHmat(long n, long r); static GEN mfEHcoef(long r, long N); static GEN mftobasis_i(GEN mf, GEN F); static GEN mkgNK(GEN N, GEN k, GEN CHI, GEN P) { return mkvec4(N, k, CHI, P); } static GEN mkNK(long N, long k, GEN CHI) { return mkgNK(stoi(N), stoi(k), CHI, pol_x(1)); } GEN MF_get_CHI(GEN mf) { return gmael(mf,1,3); } GEN MF_get_gN(GEN mf) { return gmael(mf,1,1); } long MF_get_N(GEN mf) { return itou(MF_get_gN(mf)); } GEN MF_get_gk(GEN mf) { return gmael(mf,1,2); } long MF_get_k(GEN mf) { GEN gk = MF_get_gk(mf); if (typ(gk)!=t_INT) pari_err_IMPL("half-integral weight"); return itou(gk); } long MF_get_r(GEN mf) { GEN gk = MF_get_gk(mf); if (typ(gk) == t_INT) pari_err_IMPL("integral weight"); return itou(gel(gk, 1)) >> 1; } long MF_get_space(GEN mf) { return itos(gmael(mf,1,4)); } GEN MF_get_E(GEN mf) { return gel(mf,2); } GEN MF_get_S(GEN mf) { return gel(mf,3); } GEN MF_get_basis(GEN mf) { return shallowconcat(gel(mf,2), gel(mf,3)); } long MF_get_dim(GEN mf) { switch(MF_get_space(mf)) { case mf_FULL: return lg(MF_get_S(mf)) - 1 + lg(MF_get_E(mf))-1; case mf_EISEN: return lg(MF_get_E(mf))-1; default: /* mf_NEW, mf_CUSP, mf_OLD */ return lg(MF_get_S(mf)) - 1; } } GEN MFnew_get_vj(GEN mf) { return gel(mf,4); } GEN MFcusp_get_vMjd(GEN mf) { return gel(mf,4); } GEN MF_get_M(GEN mf) { return gmael(mf,5,3); } GEN MF_get_Minv(GEN mf) { return gmael(mf,5,2); } GEN MF_get_Mindex(GEN mf) { return gmael(mf,5,1); } /* ordinary gtocol forgets about initial 0s */ GEN sertocol(GEN S) { return gtocol0(S, -(lg(S) - 2 + valser(S))); } /*******************************************************************/ /* Linear algebra in cyclotomic fields (TODO: export this) */ /*******************************************************************/ /* return r and split prime p giving projection Q(zeta_n) -> Fp, zeta -> r */ static ulong QabM_init(long n, ulong *p) { ulong pinit = 1000000007; forprime_t T; if (n <= 1) { *p = pinit; return 0; } u_forprime_arith_init(&T, pinit, ULONG_MAX, 1, n); *p = u_forprime_next(&T); return Flx_oneroot(ZX_to_Flx(polcyclo(n, 0), *p), *p); } static ulong Qab_to_Fl(GEN P, ulong r, ulong p) { ulong t; GEN den; P = Q_remove_denom(liftpol_shallow(P), &den); if (typ(P) == t_POL) { GEN Pp = ZX_to_Flx(P, p); t = Flx_eval(Pp, r, p); } else t = umodiu(P, p); if (den) t = Fl_div(t, umodiu(den, p), p); return t; } static GEN QabC_to_Flc(GEN C, ulong r, ulong p) { long i, l = lg(C); GEN A = cgetg(l, t_VECSMALL); for (i = 1; i < l; i++) uel(A,i) = Qab_to_Fl(gel(C,i), r, p); return A; } static GEN QabM_to_Flm(GEN M, ulong r, ulong p) { long i, l; GEN A = cgetg_copy(M, &l); for (i = 1; i < l; i++) gel(A, i) = QabC_to_Flc(gel(M, i), r, p); return A; } /* A a t_POL */ static GEN QabX_to_Flx(GEN A, ulong r, ulong p) { long i, l = lg(A); GEN a = cgetg(l, t_VECSMALL); a[1] = ((ulong)A[1])&VARNBITS; for (i = 2; i < l; i++) uel(a,i) = Qab_to_Fl(gel(A,i), r, p); return Flx_renormalize(a, l); } /* FIXME: remove */ static GEN ZabM_pseudoinv_i(GEN M, GEN P, long n, GEN *pv, GEN *den, int ratlift) { GEN v = ZabM_indexrank(M, P, n); if (pv) *pv = v; M = shallowmatextract(M,gel(v,1),gel(v,2)); return ratlift? ZabM_inv_ratlift(M, P, n, den): ZabM_inv(M, P, n, den); } /* M matrix with coeff in Q(\chi)), where Q(\chi) = Q(X)/(P) for * P = cyclotomic Phi_n. Assume M rational if n <= 2 */ static GEN QabM_ker(GEN M, GEN P, long n) { if (n <= 2) return QM_ker(M); return ZabM_ker(row_Q_primpart(liftpol_shallow(M)), P, n); } /* pseudo-inverse of M. FIXME: should replace QabM_pseudoinv */ static GEN QabM_pseudoinv_i(GEN M, GEN P, long n, GEN *pv, GEN *pden) { GEN cM, Mi; if (n <= 2) { M = Q_primitive_part(M, &cM); Mi = ZM_pseudoinv(M, pv, pden); /* M^(-1) = Mi / (cM * den) */ } else { M = Q_primitive_part(liftpol_shallow(M), &cM); Mi = ZabM_pseudoinv(M, P, n, pv, pden); } *pden = mul_content(*pden, cM); return Mi; } /* FIXME: delete */ static GEN QabM_pseudoinv(GEN M, GEN P, long n, GEN *pv, GEN *pden) { GEN Mi = QabM_pseudoinv_i(M, P, n, pv, pden); return P? gmodulo(Mi, P): Mi; } static GEN QabM_indexrank(GEN M, GEN P, long n) { GEN z; if (n <= 2) { M = vec_Q_primpart(M); z = ZM_indexrank(M); /* M^(-1) = Mi / (cM * den) */ } else { M = vec_Q_primpart(liftpol_shallow(M)); z = ZabM_indexrank(M, P, n); } return z; } /*********************************************************************/ /* Simple arithmetic functions */ /*********************************************************************/ /* TODO: most of these should be exported and used in ifactor1.c */ /* phi(n) */ static ulong myeulerphiu(ulong n) { pari_sp av; if (n == 1) return 1; av = avma; return gc_ulong(av, eulerphiu_fact(myfactoru(n))); } static long mymoebiusu(ulong n) { pari_sp av; if (n == 1) return 1; av = avma; return gc_long(av, moebiusu_fact(myfactoru(n))); } static long mynumdivu(long N) { pari_sp av; if (N == 1) return 1; av = avma; return gc_long(av, numdivu_fact(myfactoru(N))); } /* N\prod_{p|N} (1+1/p) */ static long mypsiu(ulong N) { pari_sp av; GEN P; long j, l, a; if (N == 1) return 1; av = avma; P = gel(myfactoru(N), 1); l = lg(P); for (a = N, j = 1; j < l; j++) a += a / P[j]; return gc_long(av, a); } /* write n = mf^2. Return m, set f. */ static ulong mycore(ulong n, long *pf) { pari_sp av = avma; GEN fa = myfactoru(n), P = gel(fa,1), E = gel(fa,2); long i, l = lg(P), m = 1, f = 1; for (i = 1; i < l; i++) { long j, p = P[i], e = E[i]; if (e & 1) m *= p; for (j = 2; j <= e; j+=2) f *= p; } *pf = f; return gc_long(av,m); } /* fa = factorization of -D > 0, return -D0 > 0 (where D0 is fundamental) */ static long corediscs_fact(GEN fa) { GEN P = gel(fa,1), E = gel(fa,2); long i, l = lg(P), m = 1; for (i = 1; i < l; i++) { long p = P[i], e = E[i]; if (e & 1) m *= p; } if ((m&3L) != 3) m <<= 2; return m; } static long mubeta(long n) { pari_sp av = avma; GEN E = gel(myfactoru(n), 2); long i, s = 1, l = lg(E); for (i = 1; i < l; i++) { long e = E[i]; if (e >= 3) return gc_long(av,0); if (e == 1) s *= -2; } return gc_long(av,s); } /* n = n1*n2, n1 = ppo(n, m); return mubeta(n1)*moebiusu(n2). * N.B. If n from newt_params we, in fact, never return 0 */ static long mubeta2(long n, long m) { pari_sp av = avma; GEN fa = myfactoru(n), P = gel(fa,1), E = gel(fa,2); long i, s = 1, l = lg(P); for (i = 1; i < l; i++) { long p = P[i], e = E[i]; if (m % p) { /* p^e in n1 */ if (e >= 3) return gc_long(av,0); if (e == 1) s *= -2; } else { /* in n2 */ if (e >= 2) return gc_long(av,0); s = -s; } } return gc_long(av,s); } /* write N = prod p^{ep} and n = df^2, d squarefree. * set g = ppo(gcd(sqfpart(N), f), FC) * N2 = prod p^if(e==1 || p|n, ep-1, ep-2) */ static void newt_params(long N, long n, long FC, long *pg, long *pN2) { GEN fa = myfactoru(N), P = gel(fa,1), E = gel(fa,2); long i, g = 1, N2 = 1, l = lg(P); for (i = 1; i < l; i++) { long p = P[i], e = E[i]; if (e == 1) { if (FC % p && n % (p*p) == 0) g *= p; } else N2 *= upowuu(p,(n % p)? e-2: e-1); } *pg = g; *pN2 = N2; } /* simplified version of newt_params for n = 1 (newdim) */ static void newd_params(long N, long *pN2) { GEN fa = myfactoru(N), P = gel(fa,1), E = gel(fa,2); long i, N2 = 1, l = lg(P); for (i = 1; i < l; i++) { long p = P[i], e = E[i]; if (e > 2) N2 *= upowuu(p, e-2); } *pN2 = N2; } static long newd_params2(long N) { GEN fa = myfactoru(N), P = gel(fa,1), E = gel(fa,2); long i, N2 = 1, l = lg(P); for (i = 1; i < l; i++) { long p = P[i], e = E[i]; if (e >= 2) N2 *= upowuu(p, e); } return N2; } /*******************************************************************/ /* Relative trace between cyclotomic fields (TODO: export this) */ /*******************************************************************/ /* g>=1; return g * prod_{p | g, (p,q) = 1} (1-1/p) */ static long phipart(long g, long q) { if (g > 1) { GEN P = gel(myfactoru(g), 1); long i, l = lg(P); for (i = 1; i < l; i++) { long p = P[i]; if (q % p) g -= g / p; } } return g; } /* Set s,v s.t. Trace(zeta_N^k) from Q(zeta_N) to Q(\zeta_N) = s * zeta_M^v * With k > 0, N = M*d and N, M != 2 mod 4 */ static long tracerelz(long *pv, long d, long M, long k) { long s, g, q, muq; if (d == 1) { *pv = k; return 1; } *pv = 0; g = ugcd(k, d); q = d / g; muq = mymoebiusu(q); if (!muq) return 0; if (M != 1) { long v = Fl_invsafe(q % M, M); if (!v) return 0; *pv = (v * (k/g)) % M; } s = phipart(g, M*q); if (muq < 0) s = -s; return s; } /* Pi = polcyclo(i), i = m or n. Let Ki = Q(zeta_i), initialize Tr_{Kn/Km} */ GEN Qab_trace_init(long n, long m, GEN Pn, GEN Pm) { long a, i, j, N, M, vt, d, D; GEN T, G; if (m == n || n <= 2) return mkvec(Pm); vt = varn(Pn); d = degpol(Pn); /* if (N != n) zeta_N = zeta_n^2 and zeta_n = - zeta_N^{(N+1)/2} */ N = ((n & 3) == 2)? n >> 1: n; M = ((m & 3) == 2)? m >> 1: m; /* M | N | n */ a = N / M; T = const_vec(d, NULL); D = d / degpol(Pm); /* relative degree */ if (D == 1) G = NULL; else { /* zeta_M = zeta_n^A; s_j(zeta_M) = zeta_M <=> j = 1 (mod J) */ long lG, A = (N == n)? a: (a << 1), J = n / ugcd(n, A); G = coprimes_zv(n); for (j = lG = 1; j < n; j += J) if (G[j]) G[lG++] = j; setlg(G, lG); /* Gal(Q(zeta_n) / Q(zeta_m)) */ } T = const_vec(d, NULL); gel(T,1) = utoipos(D); /* Tr 1 */ for (i = 1; i < d; i++) { /* if n = 2N, zeta_n^i = (-1)^i zeta_N^k */ long s, v, k; GEN t; if (gel(T, i+1)) continue; k = (N == n)? i: ((odd(i)? i + N: i) >> 1); if ((s = tracerelz(&v, a, M, k))) { if (m != M) v *= 2;/* Tr = s * zeta_m^v */ if (n != N && odd(i)) s = -s; t = Qab_Czeta(v, m, stoi(s), vt); } else t = gen_0; /* t = Tr_{Kn/Km} zeta_n^i; fill using Galois action */ if (!G) gel(T, i + 1) = t; else for (j = 1; j <= D; j++) { long z = Fl_mul(i,G[j], n); if (z < d) gel(T, z + 1) = t; } } return mkvec3(Pm, Pn, T); } /* x a t_POL modulo Phi_n */ static GEN tracerel_i(GEN T, GEN x) { long k, l = lg(x); GEN S; if (l == 2) return gen_0; S = gmul(gel(T,1), gel(x,2)); for (k = 3; k < l; k++) S = gadd(S, gmul(gel(T,k-1), gel(x,k))); return S; } static GEN tracerel(GEN a, GEN v, GEN z) { a = liftpol_shallow(a); a = simplify_shallow(z? gmul(z,a): a); if (typ(a) == t_POL) { GEN T = gel(v,3); long degrel = itou(gel(T,1)); a = tracerel_i(T, RgX_rem(a, gel(v,2))); if (degrel != 1) a = gdivgu(a, degrel); if (typ(a) == t_POL) a = RgX_rem(a, gel(v,1)); } return a; } static GEN tracerel_z(GEN v, long t) { GEN Pn = gel(v,2); return t? pol_xn(t, varn(Pn)): NULL; } /* v = Qab_trace_init(n,m); x is a t_VEC of polmodulo Phi_n; Kn = Q(zeta_n) * [Kn:Km]^(-1) Tr_{Kn/Km} (zeta_n^t * x); 0 <= t < [Kn:Km] */ GEN Qab_tracerel(GEN v, long t, GEN a) { if (lg(v) != 4) return a; /* => t = 0 */ return tracerel(a, v, tracerel_z(v, t)); } GEN QabV_tracerel(GEN v, long t, GEN x) { GEN z; if (lg(v) != 4) return x; /* => t = 0 */ z = tracerel_z(v, t); pari_APPLY_same(tracerel(gel(x,i), v, z)); } GEN QabM_tracerel(GEN v, long t, GEN x) { if (lg(v) != 4) return x; pari_APPLY_same(QabV_tracerel(v, t, gel(x,i))); } /* C*zeta_o^k mod X^o - 1 */ static GEN Qab_Czeta(long k, long o, GEN C, long vt) { if (!k) return C; if (!odd(o)) { /* optimization: reduce max degree by a factor 2 for free */ o >>= 1; if (k >= o) { k -= o; C = gneg(C); if (!k) return C; } } return monomial(C, k, vt); } /* zeta_o^k */ static GEN Qab_zeta(long k, long o, long vt) { return Qab_Czeta(k, o, gen_1, vt); } /* Operations on Dirichlet characters */ /* A Dirichlet character can be given in GP in different formats, but in this * package, it will be a vector CHI=[G,chi,ord], where G is the (Z/MZ)^* to * which the character belongs, chi is the character in Conrey format, ord is * the order */ static GEN gmfcharorder(GEN CHI) { return gel(CHI, 3); } long mfcharorder(GEN CHI) { return itou(gmfcharorder(CHI)); } static long mfcharistrivial(GEN CHI) { return !CHI || mfcharorder(CHI) == 1; } static GEN gmfcharmodulus(GEN CHI) { return gmael3(CHI, 1, 1, 1); } long mfcharmodulus(GEN CHI) { return itou(gmfcharmodulus(CHI)); } GEN mfcharpol(GEN CHI) { return gel(CHI,4); } /* vz[i+1] = image of (zeta_o)^i in Fp */ static ulong Qab_Czeta_Fl(long k, GEN vz, ulong C, ulong p) { long o; if (!k) return C; o = lg(vz)-2; if ((k << 1) == o) return Fl_neg(C,p); return Fl_mul(C, vz[k+1], p); } static long znchareval_i(GEN CHI, long n, GEN ord) { return itos(znchareval(gel(CHI,1), gel(CHI,2), stoi(n), ord)); } /* n coprime with the modulus of CHI */ static GEN mfchareval(GEN CHI, long n) { GEN Pn, C, go = gmfcharorder(CHI); long k, o = go[2]; if (o == 1) return gen_1; k = znchareval_i(CHI, n, go); Pn = mfcharpol(CHI); C = Qab_zeta(k, o, varn(Pn)); if (typ(C) != t_POL) return C; return gmodulo(C, Pn); } /* d a multiple of ord(CHI); n coprime with char modulus; * return x s.t. CHI(n) = \zeta_d^x] */ static long mfcharevalord(GEN CHI, long n, long d) { if (mfcharorder(CHI) == 1) return 0; return znchareval_i(CHI, n, utoi(d)); } /* G a znstar, L a Conrey log: return a 'mfchar' */ static GEN mfcharGL(GEN G, GEN L) { GEN o = zncharorder(G,L); long ord = itou(o), vt = fetch_user_var("t"); return mkvec4(G, L, o, polcyclo(ord,vt)); } static GEN mfchartrivial() { return mfcharGL(znstar0(gen_1,1), cgetg(1,t_COL)); } /* convert a generic character into an 'mfchar' */ static GEN get_mfchar(GEN CHI) { GEN G, L; if (typ(CHI) != t_VEC) CHI = znchar(CHI); else { long l = lg(CHI); if ((l != 3 && l != 5) || !checkznstar_i(gel(CHI,1))) pari_err_TYPE("checkNF [chi]", CHI); if (l == 5) return CHI; } G = gel(CHI,1); L = gel(CHI,2); if (typ(L) != t_COL) L = znconreylog(G,L); return mfcharGL(G, L); } /* parse [N], [N,k], [N,k,CHI]. If 'joker' is set, allow wildcard for CHI */ static GEN checkCHI(GEN NK, long N, int joker) { GEN CHI; if (lg(NK) == 3) CHI = mfchartrivial(); else { long i, l; CHI = gel(NK,3); l = lg(CHI); if (isintzero(CHI) && joker) CHI = NULL; /* all character orbits */ else if (isintm1(CHI) && joker > 1) CHI = gen_m1; /* sum over all character orbits */ else if ((typ(CHI) == t_VEC && (l == 1 || l != 3 || !checkznstar_i(gel(CHI,1)))) && joker) { CHI = shallowtrans(CHI); /* list of characters */ for (i = 1; i < l; i++) gel(CHI,i) = get_mfchar(gel(CHI,i)); } else { CHI = get_mfchar(CHI); /* single char */ if (N % mfcharmodulus(CHI)) pari_err_TYPE("checkNF [chi]", NK); } } return CHI; } /* support half-integral weight */ static void checkNK2(GEN NK, long *N, long *nk, long *dk, GEN *CHI, int joker) { long l = lg(NK); GEN T; if (typ(NK) != t_VEC || l < 3 || l > 4) pari_err_TYPE("checkNK", NK); T = gel(NK,1); if (typ(T) != t_INT) pari_err_TYPE("checkNF [N]", NK); *N = itos(T); if (*N <= 0) pari_err_TYPE("checkNF [N <= 0]", NK); T = gel(NK,2); switch(typ(T)) { case t_INT: *nk = itos(T); *dk = 1; break; case t_FRAC: *nk = itos(gel(T,1)); *dk = itou(gel(T,2)); if (*dk == 2) break; default: pari_err_TYPE("checkNF [k]", NK); } *CHI = checkCHI(NK, *N, joker); } /* don't support half-integral weight */ static void checkNK(GEN NK, long *N, long *k, GEN *CHI, int joker) { long d; checkNK2(NK, N, k, &d, CHI, joker); if (d != 1) pari_err_TYPE("checkNF [k]", NK); } static GEN mfchargalois(long N, int odd, GEN flagorder) { GEN G = znstar0(utoi(N), 1), L = chargalois(G, flagorder); long l = lg(L), i, j; for (i = j = 1; i < l; i++) { GEN chi = znconreyfromchar(G, gel(L,i)); if (zncharisodd(G,chi) == odd) gel(L,j++) = mfcharGL(G,chi); } setlg(L, j); return L; } /* possible characters for nontrivial S_1(N, chi) */ static GEN mf1chars(long N, GEN vCHI) { if (vCHI) return vCHI; /*do not filter, user knows best*/ /* Tate's theorem */ return mfchargalois(N, 1, uisprime(N)? mkvecsmall2(2,4): NULL); } static GEN mfchars(long N, long k, long dk, GEN vCHI) { return vCHI? vCHI: mfchargalois(N, (dk == 2)? 0: (k & 1), NULL); } /* wrappers from mfchar to znchar */ static long mfcharparity(GEN CHI) { if (!CHI) return 1; return zncharisodd(gel(CHI,1), gel(CHI,2)) ? -1 : 1; } /* if CHI is primitive, return CHI itself, not a copy */ static GEN mfchartoprimitive(GEN CHI, long *pF) { pari_sp av; GEN chi, F; if (!CHI) { if (pF) *pF = 1; return mfchartrivial(); } av = avma; F = znconreyconductor(gel(CHI,1), gel(CHI,2), &chi); if (typ(F) == t_INT) set_avma(av); else { CHI = leafcopy(CHI); gel(CHI,1) = znstar0(F, 1); gel(CHI,2) = chi; } if (pF) *pF = mfcharmodulus(CHI); return CHI; } static long mfcharconductor(GEN CHI) { pari_sp av = avma; GEN res = znconreyconductor(gel(CHI,1), gel(CHI,2), NULL); if (typ(res) == t_VEC) res = gel(res, 1); return gc_long(av, itos(res)); } /* Operations on mf closures */ static GEN tagparams(long t, GEN NK) { return mkvec2(mkvecsmall(t), NK); } static GEN lfuntag(long t, GEN x) { return mkvec2(mkvecsmall(t), x); } static GEN tag0(long t, GEN NK) { retmkvec(tagparams(t,NK)); } static GEN tag(long t, GEN NK, GEN x) { retmkvec2(tagparams(t,NK), x); } static GEN tag2(long t, GEN NK, GEN x, GEN y) { retmkvec3(tagparams(t,NK), x,y); } static GEN tag3(long t, GEN NK, GEN x,GEN y,GEN z) { retmkvec4(tagparams(t,NK), x,y,z); } static GEN tag4(long t, GEN NK, GEN x,GEN y,GEN z,GEN a) { retmkvec5(tagparams(t,NK), x,y,z,a); } /* is F a "modular form" ? */ int checkmf_i(GEN F) { return typ(F) == t_VEC && lg(F) > 1 && typ(gel(F,1)) == t_VEC && lg(gel(F,1)) == 3 && typ(gmael(F,1,1)) == t_VECSMALL && typ(gmael(F,1,2)) == t_VEC; } long mf_get_type(GEN F) { return gmael(F,1,1)[1]; } GEN mf_get_gN(GEN F) { return gmael3(F,1,2,1); } GEN mf_get_gk(GEN F) { return gmael3(F,1,2,2); } /* k - 1/2, assume k in 1/2 + Z */ long mf_get_r(GEN F) { return itou(gel(mf_get_gk(F),1)) >> 1; } long mf_get_N(GEN F) { return itou(mf_get_gN(F)); } long mf_get_k(GEN F) { GEN gk = mf_get_gk(F); if (typ(gk)!=t_INT) pari_err_IMPL("half-integral weight"); return itou(gk); } GEN mf_get_CHI(GEN F) { return gmael3(F,1,2,3); } GEN mf_get_field(GEN F) { return gmael3(F,1,2,4); } GEN mf_get_NK(GEN F) { return gmael(F,1,2); } static void mf_setfield(GEN f, GEN P) { gel(f,1) = leafcopy(gel(f,1)); gmael(f,1,2) = leafcopy(gmael(f,1,2)); gmael3(f,1,2,4) = P; } /* UTILITY FUNCTIONS */ GEN mftocol(GEN F, long lim, long d) { GEN c = mfcoefs_i(F, lim, d); settyp(c,t_COL); return c; } GEN mfvectomat(GEN vF, long lim, long d) { long j, l = lg(vF); GEN M = cgetg(l, t_MAT); for (j = 1; j < l; j++) gel(M,j) = mftocol(gel(vF,j), lim, d); return M; } static GEN RgV_to_ser_full(GEN x) { return RgV_to_ser(x, 0, lg(x)+1); } /* TODO: delete */ static GEN mfcoefsser(GEN F, long n) { return RgV_to_ser_full(mfcoefs_i(F,n,1)); } static GEN sertovecslice(GEN S, long n) { GEN v = gtovec0(S, -(lg(S) - 2 + valser(S))); long l = lg(v), n2 = n + 2; if (l < n2) pari_err_BUG("sertovecslice [n too large]"); return (l == n2)? v: vecslice(v, 1, n2-1); } /* a, b two RgV of the same length, multiply as truncated power series */ static GEN RgV_mul_RgXn(GEN a, GEN b) { long n = lg(a)-1; GEN c; a = RgV_to_RgX(a,0); b = RgV_to_RgX(b,0); c = RgXn_mul(a, b, n); c = RgX_to_RgC(c,n); settyp(c,t_VEC); return c; } /* divide as truncated power series */ static GEN RgV_div_RgXn(GEN a, GEN b) { long n = lg(a)-1; GEN c; a = RgV_to_RgX(a,0); b = RgV_to_RgX(b,0); c = RgXn_div_i(a, b, n); c = RgX_to_RgC(c,n); settyp(c,t_VEC); return c; } /* a^b */ static GEN RgV_pows_RgXn(GEN a, long b) { long n = lg(a)-1; GEN c; a = RgV_to_RgX(a,0); if (b < 0) { a = RgXn_inv(a, n); b = -b; } c = RgXn_powu_i(a,b,n); c = RgX_to_RgC(c,n); settyp(c,t_VEC); return c; } /* assume lg(V) >= n*d + 2 */ static GEN c_deflate(long n, long d, GEN v) { long i, id, l = n+2; GEN w; if (d == 1) return lg(v) == l ? v: vecslice(v, 1, l-1); w = cgetg(l, typ(v)); for (i = id = 1; i < l; i++, id += d) gel(w, i) = gel(v, id); return w; } static void err_cyclo(void) { pari_err_IMPL("changing cyclotomic fields in mf"); } /* Q(zeta_a) = Q(zeta_b) ? */ static int same_cyc(long a, long b) { return (a == b) || (odd(a) && b == (a<<1)) || (odd(b) && a == (b<<1)); } /* need to combine elements in Q(CHI1) and Q(CHI2) with result in Q(CHI), * CHI = CHI1 * CHI2 or CHI / CHI2 times some character of order 2 */ static GEN chicompat(GEN CHI, GEN CHI1, GEN CHI2) { long o1 = mfcharorder(CHI1); long o2 = mfcharorder(CHI2), O, o; GEN T1, T2, P, Po; if (o1 <= 2 && o2 <= 2) return NULL; o = mfcharorder(CHI); Po = mfcharpol(CHI); P = mfcharpol(CHI1); if (o1 == o2) { if (o1 == o) return NULL; if (!same_cyc(o1,o)) err_cyclo(); return mkvec4(P, gen_1,gen_1, Qab_trace_init(o1, o, P, Po)); } O = ulcm(o1, o2); if (!same_cyc(O,o)) err_cyclo(); if (O != o1) P = (O == o2)? mfcharpol(CHI2): polcyclo(O, varn(P)); T1 = o1 <= 2? gen_1: utoipos(O / o1); T2 = o2 <= 2? gen_1: utoipos(O / o2); return mkvec4(P, T1, T2, O == o? gen_1: Qab_trace_init(O, o, P, Po)); } /* *F a vector of cyclotomic numbers */ static void compatlift(GEN *F, long o, GEN P) { long i, l; GEN f = *F, g = cgetg_copy(f,&l); for (i = 1; i < l; i++) { GEN fi = lift_shallow(gel(f,i)); gel(g,i) = gmodulo(typ(fi)==t_POL? RgX_inflate(fi,o): fi, P); } *F = g; } static void chicompatlift(GEN T, GEN *F, GEN *G) { long o1 = itou(gel(T,2)), o2 = itou(gel(T,3)); GEN P = gel(T,1); if (o1 != 1) compatlift(F, o1, P); if (o2 != 1 && G) compatlift(G, o2, P); } static GEN chicompatfix(GEN T, GEN F) { GEN V = gel(T,4); if (typ(V) == t_VEC) F = gmodulo(QabV_tracerel(V, 0, F), gel(V,1)); return F; } static GEN c_mul(long n, long d, GEN S) { pari_sp av = avma; long nd = n*d; GEN F = gel(S,2), G = gel(S,3); F = mfcoefs_i(F, nd, 1); G = mfcoefs_i(G, nd, 1); if (lg(S) == 5) chicompatlift(gel(S,4),&F,&G); F = c_deflate(n, d, RgV_mul_RgXn(F,G)); if (lg(S) == 5) F = chicompatfix(gel(S,4), F); return gerepilecopy(av, F); } static GEN c_pow(long n, long d, GEN S) { pari_sp av = avma; long nd = n*d; GEN F = gel(S,2), a = gel(S,3), f = mfcoefs_i(F,nd,1); if (lg(S) == 5) chicompatlift(gel(S,4),&F, NULL); f = RgV_pows_RgXn(f, itos(a)); f = c_deflate(n, d, f); if (lg(S) == 5) f = chicompatfix(gel(S,4), f); return gerepilecopy(av, f); } /* F * Theta */ static GEN mfmultheta(GEN F) { if (typ(mf_get_gk(F)) == t_FRAC && mf_get_type(F) == t_MF_DIV) { GEN T = gel(F,3); /* hopefully mfTheta() */ if (mf_get_type(T) == t_MF_THETA && mf_get_N(T) == 4) return gel(F,2); } return mfmul(F, mfTheta(NULL)); } static GEN c_bracket(long n, long d, GEN S) { pari_sp av = avma; long i, nd = n*d; GEN F = gel(S,2), G = gel(S,3), tF, tG, C, mpow, res, gk, gl; GEN VF = mfcoefs_i(F, nd, 1); GEN VG = mfcoefs_i(G, nd, 1); ulong j, m = itou(gel(S,4)); if (!n) { if (m > 0) { set_avma(av); return mkvec(gen_0); } return gerepilecopy(av, mkvec(gmul(gel(VF, 1), gel(VG, 1)))); } tF = cgetg(nd+2, t_VEC); tG = cgetg(nd+2, t_VEC); res = NULL; gk = mf_get_gk(F); gl = mf_get_gk(G); /* pow[i,j+1] = i^j */ if (lg(S) == 6) chicompatlift(gel(S,5),&VF,&VG); mpow = cgetg(m+2, t_MAT); gel(mpow,1) = const_col(nd, gen_1); for (j = 1; j <= m; j++) { GEN c = cgetg(nd+1, t_COL); gel(mpow,j+1) = c; for (i = 1; i <= nd; i++) gel(c,i) = muliu(gcoeff(mpow,i,j), i); } C = binomial(gaddgs(gk, m-1), m); if (odd(m)) C = gneg(C); for (j = 0; j <= m; j++) { /* C = (-1)^(m-j) binom(m+l-1, j) binom(m+k-1,m-j) */ GEN c; gel(tF,1) = j == 0? gel(VF,1): gen_0; gel(tG,1) = j == m? gel(VG,1): gen_0; gel(tF,2) = gel(VF,2); /* assume nd >= 1 */ gel(tG,2) = gel(VG,2); for (i = 2; i <= nd; i++) { gel(tF, i+1) = gmul(gcoeff(mpow,i,j+1), gel(VF, i+1)); gel(tG, i+1) = gmul(gcoeff(mpow,i,m-j+1), gel(VG, i+1)); } c = gmul(C, c_deflate(n, d, RgV_mul_RgXn(tF, tG))); res = res? gadd(res, c): c; if (j < m) C = gdiv(gmul(C, gmulsg(m-j, gaddgs(gl,m-j-1))), gmulsg(-(j+1), gaddgs(gk,j))); } if (lg(S) == 6) res = chicompatfix(gel(S,5), res); return gerepileupto(av, res); } /* linear combination \sum L[j] vecF[j] */ static GEN c_linear(long n, long d, GEN F, GEN L, GEN dL) { pari_sp av = avma; long j, l = lg(L); GEN S = NULL; for (j = 1; j < l; j++) { GEN c = gel(L,j); if (gequal0(c)) continue; c = gmul(c, mfcoefs_i(gel(F,j), n, d)); S = S? gadd(S,c): c; } if (!S) return zerovec(n+1); if (!is_pm1(dL)) S = gdiv(S, dL); return gerepileupto(av, S); } /* B_d(T_j Trace^new) as t_MF_BD(t_MF_HECKE(t_MF_NEWTRACE)) or * t_MF_HECKE(t_MF_NEWTRACE) * or t_MF_NEWTRACE in level N. Set d and j, return t_MF_NEWTRACE component*/ static GEN bhn_parse(GEN f, long *d, long *j) { long t = mf_get_type(f); *d = *j = 1; if (t == t_MF_BD) { *d = itos(gel(f,3)); f = gel(f,2); t = mf_get_type(f); } if (t == t_MF_HECKE) { *j = gel(f,2)[1]; f = gel(f,3); } return f; } /* f as above, return the t_MF_NEWTRACE component */ static GEN bhn_newtrace(GEN f) { long t = mf_get_type(f); if (t == t_MF_BD) { f = gel(f,2); t = mf_get_type(f); } if (t == t_MF_HECKE) f = gel(f,3); return f; } static int ok_bhn_linear(GEN vf) { long i, N0 = 0, l = lg(vf); GEN CHI, gk; if (l == 1) return 1; gk = mf_get_gk(gel(vf,1)); CHI = mf_get_CHI(gel(vf,1)); for (i = 1; i < l; i++) { GEN f = bhn_newtrace(gel(vf,i)); long N = mf_get_N(f); if (mf_get_type(f) != t_MF_NEWTRACE) return 0; if (N < N0) return 0; /* largest level must come last */ N0 = N; if (!gequal(gk,mf_get_gk(f))) return 0; /* same k */ if (!gequal(gel(mf_get_CHI(f),2), gel(CHI,2))) return 0; /* same CHI */ } return 1; } /* vF not empty, same hypotheses as bhnmat_extend */ static GEN bhnmat_extend_nocache(GEN M, long N, long n, long d, GEN vF) { cachenew_t cache; long l = lg(vF); GEN f; if (l == 1) return M? M: cgetg(1, t_MAT); f = bhn_newtrace(gel(vF,1)); /* N.B. mf_get_N(f) divides N */ init_cachenew(&cache, n*d, N, f); M = bhnmat_extend(M, n, d, vF, &cache); dbg_cachenew(&cache); return M; } /* c_linear of "bhn" mf closures, same hypotheses as bhnmat_extend */ static GEN c_linear_bhn(long n, long d, GEN F) { pari_sp av; GEN M, v, vF = gel(F,2), L = gel(F,3), dL = gel(F,4); if (lg(L) == 1) return zerovec(n+1); av = avma; M = bhnmat_extend_nocache(NULL, mf_get_N(F), n, d, vF); v = RgM_RgC_mul(M,L); settyp(v, t_VEC); if (!is_pm1(dL)) v = gdiv(v, dL); return gerepileupto(av, v); } /* c in K, K := Q[X]/(T) vz = vector of consecutive powers of root z of T * attached to an embedding s: K -> C. Return s(c) in C */ static GEN Rg_embed1(GEN c, GEN vz) { long t = typ(c); if (t == t_POLMOD) { c = gel(c,2); t = typ(c); } if (t == t_POL) c = RgX_RgV_eval(c, vz); return c; } /* return s(P) in C[X] */ static GEN RgX_embed1(GEN P, GEN vz) { long i, l; GEN Q = cgetg_copy(P, &l); Q[1] = P[1]; for (i = 2; i < l; i++) gel(Q,i) = Rg_embed1(gel(P,i), vz); return normalizepol_lg(Q,l); /* normally a no-op */ } /* return s(P) in C^n */ static GEN vecembed1(GEN P, GEN vz) { long i, l; GEN Q = cgetg_copy(P, &l); for (i = 1; i < l; i++) gel(Q,i) = Rg_embed1(gel(P,i), vz); return Q; } /* P in L = K[X]/(U), K = Q[t]/T; s an embedding of K -> C attached * to a root of T, extended to an embedding of L -> C attached to a root * of s(U); vT powers of the root of T, vU powers of the root of s(U). * Return s(P) in C^n */ static GEN Rg_embed2(GEN P, long vt, GEN vT, GEN vU) { long i, l; GEN Q; P = liftpol_shallow(P); if (typ(P) != t_POL) return P; if (varn(P) == vt) return Rg_embed1(P, vT); /* varn(P) == vx */ Q = cgetg_copy(P, &l); Q[1] = P[1]; for (i = 2; i < l; i++) gel(Q,i) = Rg_embed1(gel(P,i), vT); return Rg_embed1(Q, vU); } static GEN vecembed2(GEN P, long vt, GEN vT, GEN vU) { long i, l; GEN Q = cgetg_copy(P, &l); for (i = 1; i < l; i++) gel(Q,i) = Rg_embed2(gel(P,i), vt, vT, vU); return Q; } static GEN RgX_embed2(GEN P, long vt, GEN vT, GEN vU) { long i, l; GEN Q = cgetg_copy(P, &l); for (i = 2; i < l; i++) gel(Q,i) = Rg_embed2(gel(P,i), vt, vT, vU); Q[1] = P[1]; return normalizepol_lg(Q,l); } /* embed polynomial f in variable 0 [ may be a scalar ], E from getembed */ static GEN RgX_embed(GEN f, GEN E) { GEN vT; if (typ(f) != t_POL || varn(f) != 0) return mfembed(E, f); if (lg(E) == 1) return f; vT = gel(E,2); if (lg(E) == 3) f = RgX_embed1(f, vT); else f = RgX_embed2(f, varn(gel(E,1)), vT, gel(E,3)); return f; } /* embed vector, E from getembed */ GEN mfvecembed(GEN E, GEN v) { GEN vT; if (lg(E) == 1) return v; vT = gel(E,2); if (lg(E) == 3) v = vecembed1(v, vT); else v = vecembed2(v, varn(gel(E,1)), vT, gel(E,3)); return v; } GEN mfmatembed(GEN E, GEN f) { long i, l; GEN g; if (lg(E) == 1) return f; g = cgetg_copy(f, &l); for (i = 1; i < l; i++) gel(g,i) = mfvecembed(E, gel(f,i)); return g; } /* embed vector of polynomials in var 0 */ static GEN RgXV_embed(GEN f, GEN E) { long i, l; GEN v; if (lg(E) == 1) return f; v = cgetg_copy(f, &l); for (i = 1; i < l; i++) gel(v,i) = RgX_embed(gel(f,i), E); return v; } /* embed scalar */ GEN mfembed(GEN E, GEN f) { GEN vT; if (lg(E) == 1) return f; vT = gel(E,2); if (lg(E) == 3) f = Rg_embed1(f, vT); else f = Rg_embed2(f, varn(gel(E,1)), vT, gel(E,3)); return f; } /* vector of the sigma(f), sigma in vE */ static GEN RgX_embedall(GEN f, GEN vE) { long i, l = lg(vE); GEN v; if (l == 2) return RgX_embed(f, gel(vE,1)); v = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(v,i) = RgX_embed(f, gel(vE,i)); return v; } /* matrix whose colums are the sigma(v), sigma in vE */ static GEN RgC_embedall(GEN v, GEN vE) { long j, l = lg(vE); GEN M = cgetg(l, t_MAT); for (j = 1; j < l; j++) gel(M,j) = mfvecembed(gel(vE,j), v); return M; } /* vector of the sigma(v), sigma in vE */ static GEN Rg_embedall_i(GEN v, GEN vE) { long j, l = lg(vE); GEN M = cgetg(l, t_VEC); for (j = 1; j < l; j++) gel(M,j) = mfembed(gel(vE,j), v); return M; } /* vector of the sigma(v), sigma in vE; if #vE == 1, return v */ static GEN Rg_embedall(GEN v, GEN vE) { return (lg(vE) == 2)? mfembed(gel(vE,1), v): Rg_embedall_i(v, vE); } static GEN c_div_i(long n, GEN S) { GEN F = gel(S,2), G = gel(S,3); GEN a0, a0i, H; F = mfcoefs_i(F, n, 1); G = mfcoefs_i(G, n, 1); if (lg(S) == 5) chicompatlift(gel(S,4),&F,&G); F = RgV_to_ser_full(F); G = RgV_to_ser_full(G); a0 = polcoef_i(G, 0, -1); /* != 0 */ if (gequal1(a0)) a0 = a0i = NULL; else { a0i = ginv(a0); G = gmul(ser_unscale(G,a0), a0i); F = gmul(ser_unscale(F,a0), a0i); } H = gdiv(F, G); if (a0) H = ser_unscale(H,a0i); H = sertovecslice(H, n); if (lg(S) == 5) H = chicompatfix(gel(S,4), H); return H; } static GEN c_div(long n, long d, GEN S) { pari_sp av = avma; GEN D = (d==1)? c_div_i(n, S): c_deflate(n, d, c_div_i(n*d, S)); return gerepilecopy(av, D); } static GEN c_shift(long n, long d, GEN F, GEN gsh) { pari_sp av = avma; GEN vF; long sh = itos(gsh), n1 = n*d + sh; if (n1 < 0) return zerovec(n+1); vF = mfcoefs_i(F, n1, 1); if (sh < 0) vF = shallowconcat(zerovec(-sh), vF); else vF = vecslice(vF, sh+1, n1+1); return gerepilecopy(av, c_deflate(n, d, vF)); } static GEN c_deriv(long n, long d, GEN F, GEN gm) { pari_sp av = avma; GEN V = mfcoefs_i(F, n, d), res; long i, m = itos(gm); if (!m) return V; res = cgetg(n+2, t_VEC); gel(res,1) = gen_0; if (m < 0) { for (i=1; i <= n; i++) gel(res, i+1) = gdiv(gel(V, i+1), powuu(i,-m)); } else { for (i=1; i <= n; i++) gel(res, i+1) = gmul(gel(V,i+1), powuu(i,m)); } return gerepileupto(av, res); } static GEN c_derivE2(long n, long d, GEN F, GEN gm) { pari_sp av = avma; GEN VF, VE, res, tmp, gk; long i, m = itos(gm), nd; if (m == 0) return mfcoefs_i(F, n, d); nd = n*d; VF = mfcoefs_i(F, nd, 1); VE = mfcoefs_i(mfEk(2), nd, 1); gk = mf_get_gk(F); if (m == 1) { res = cgetg(n+2, t_VEC); for (i = 0; i <= n; i++) gel(res, i+1) = gmulsg(i, gel(VF, i*d+1)); tmp = c_deflate(n, d, RgV_mul_RgXn(VF, VE)); return gerepileupto(av, gsub(res, gmul(gdivgu(gk, 12), tmp))); } else { long j; for (j = 1; j <= m; j++) { tmp = RgV_mul_RgXn(VF, VE); for (i = 0; i <= nd; i++) gel(VF, i+1) = gmulsg(i, gel(VF, i+1)); VF = gsub(VF, gmul(gdivgu(gaddgs(gk, 2*(j-1)), 12), tmp)); } return gerepilecopy(av, c_deflate(n, d, VF)); } } /* Twist by the character (D/.) */ static GEN c_twist(long n, long d, GEN F, GEN D) { pari_sp av = avma; GEN v = mfcoefs_i(F, n, d), z = cgetg(n+2, t_VEC); long i; for (i = 0; i <= n; i++) { long s; GEN a = gel(v, i+1); if (d == 1) s = krois(D, i); else { pari_sp av2 = avma; s = kronecker(D, muluu(i, d)); set_avma(av2); } switch(s) { case 1: a = gcopy(a); break; case -1: a = gneg(a); break; default: a = gen_0; break; } gel(z, i+1) = a; } return gerepileupto(av, z); } /* form F given by closure, compute T(n)(F) as closure */ static GEN c_hecke(long m, long l, GEN DATA, GEN F) { pari_sp av = avma; return gerepilecopy(av, hecke_i(m, l, NULL, F, DATA)); } static GEN c_const(long n, long d, GEN C) { GEN V = zerovec(n+1); long i, j, l = lg(C); if (l > d*n+2) l = d*n+2; for (i = j = 1; i < l; i+=d, j++) gel(V, j) = gcopy(gel(C,i)); return V; } /* m > 0 */ static GEN eta3_ZXn(long m) { long l = m+2, n, k; GEN P = cgetg(l,t_POL); P[1] = evalsigne(1)|evalvarn(0); for (n = 2; n < l; n++) gel(P,n) = gen_0; for (n = k = 0;; n++) { if (k + n >= m) { setlg(P, k+3); return P; } k += n; /* now k = n(n+1) / 2 */ gel(P, k+2) = odd(n)? utoineg(2*n+1): utoipos(2*n+1); } } static GEN c_delta(long n, long d) { pari_sp ltop = avma; long N = n*d; GEN e; if (!N) return mkvec(gen_0); e = eta3_ZXn(N); e = ZXn_sqr(e,N); e = ZXn_sqr(e,N); e = ZXn_sqr(e,N); /* eta(x)^24 */ settyp(e, t_VEC); gel(e,1) = gen_0; /* Delta(x) = x*eta(x)^24 as a t_VEC */ return gerepilecopy(ltop, c_deflate(n, d, e)); } /* return s(d) such that s|f <=> d | f^2 */ static long mysqrtu(ulong d) { GEN fa = myfactoru(d), P = gel(fa,1), E = gel(fa,2); long l = lg(P), i, s = 1; for (i = 1; i < l; i++) s *= upowuu(P[i], (E[i]+1)>>1); return s; } static GEN c_theta(long n, long d, GEN psi) { long lim = usqrt(n*d), F = mfcharmodulus(psi), par = mfcharparity(psi); long f, d2 = d == 1? 1: mysqrtu(d); GEN V = zerovec(n + 1); for (f = d2; f <= lim; f += d2) if (ugcd(F, f) == 1) { pari_sp av = avma; GEN c = mfchareval(psi, f); gel(V, f*f/d + 1) = gerepileupto(av, par < 0? gmulgu(c,2*f): gmul2n(c,1)); } if (F == 1) gel(V, 1) = gen_1; return V; /* no gerepile needed */ } static GEN c_etaquo(long n, long d, GEN eta, GEN gs) { pari_sp av = avma; long s = itos(gs), nd = n*d, nds = nd - s + 1; GEN c; if (nds <= 0) return zerovec(n+1); c = RgX_to_RgC(eta_product_ZXn(eta, nds), nds); settyp(c, t_VEC); if (s > 0) c = shallowconcat(zerovec(s), c); return gerepilecopy(av, c_deflate(n, d, c)); } static GEN c_ell(long n, long d, GEN E) { pari_sp av = avma; GEN v; if (d == 1) return gconcat(gen_0, ellan(E, n)); v = vec_prepend(ellan(E, n*d), gen_0); return gerepilecopy(av, c_deflate(n, d, v)); } static GEN c_cusptrace(long n, long d, GEN F) { pari_sp av = avma; GEN D = gel(F,2), res = cgetg(n+2, t_VEC); long i, N = mf_get_N(F), k = mf_get_k(F); gel(res, 1) = gen_0; for (i = 1; i <= n; i++) gel(res, i+1) = mfcusptrace_i(N, k, i*d, mydivisorsu(i*d), D); return gerepilecopy(av, res); } static GEN c_newtrace(long n, long d, GEN F) { pari_sp av = avma; cachenew_t cache; long N = mf_get_N(F); GEN v; init_cachenew(&cache, n == 1? 1: n*d, N, F); v = colnewtrace(0, n, d, N, mf_get_k(F), &cache); settyp(v, t_VEC); return gerepilecopy(av, v); } static GEN c_Bd(long n, long d, GEN F, GEN A) { pari_sp av = avma; long a = itou(A), ad = ugcd(a,d), aad = a/ad, i, j; GEN w, v = mfcoefs_i(F, n/aad, d/ad); if (a == 1) return v; n++; w = zerovec(n); for (i = j = 1; j <= n; i++, j += aad) gel(w,j) = gcopy(gel(v,i)); return gerepileupto(av, w); } static GEN c_dihedral(long n, long d, GEN F) { pari_sp av = avma; GEN CHI = mf_get_CHI(F); GEN w = gel(F,3), V = dihan(gel(F,2), w, gel(F,4), mfcharorder(CHI), n*d); GEN Tinit = gel(w,3), Pm = gel(Tinit,1); GEN A = c_deflate(n, d, V); if (degpol(Pm) == 1 || RgV_is_ZV(A)) return gerepilecopy(av, A); return gerepileupto(av, gmodulo(A, Pm)); } static GEN c_mfEH(long n, long d, GEN F) { pari_sp av = avma; GEN v, M, A; long i, r = mf_get_r(F); if (n == 1) return gerepilecopy(av, mkvec2(mfEHcoef(r,0),mfEHcoef(r,d))); /* speedup mfcoef */ if (r == 1) { v = cgetg(n+2, t_VEC); gel(v,1) = sstoQ(-1,12); for (i = 1; i <= n; i++) { long id = i*d, a = id & 3; gel(v,i+1) = (a==1 || a==2)? gen_0: uutoQ(hclassno6u(id), 6); } return v; /* no gerepile needed */ } M = mfEHmat(n*d+1,r); if (d > 1) { long l = lg(M); for (i = 1; i < l; i++) gel(M,i) = c_deflate(n, d, gel(M,i)); } A = gel(F,2); /* [num(B), den(B)] */ v = RgC_Rg_div(RgM_RgC_mul(M, gel(A,1)), gel(A,2)); settyp(v,t_VEC); return gerepileupto(av, v); } static GEN c_mfeisen(long n, long d, GEN F) { pari_sp av = avma; GEN v, vchi, E0, P, T, CHI, gk = mf_get_gk(F); long i, k; if (typ(gk) != t_INT) return c_mfEH(n, d, F); k = itou(gk); vchi = gel(F,2); E0 = gel(vchi,1); T = gel(vchi,2); P = gel(T,1); CHI = gel(vchi,3); v = cgetg(n+2, t_VEC); gel(v, 1) = gcopy(E0); /* E(0) */ if (lg(vchi) == 5) { /* E_k(chi1,chi2) */ GEN CHI2 = gel(vchi,4), F3 = gel(F,3); long ord = F3[1], j = F3[2]; for (i = 1; i <= n; i++) gel(v, i+1) = sigchi2(k, CHI, CHI2, i*d, ord); v = QabV_tracerel(T, j, v); } else { /* E_k(chi) */ for (i = 1; i <= n; i++) gel(v, i+1) = sigchi(k, CHI, i*d); } if (degpol(P) != 1 && !RgV_is_QV(v)) return gerepileupto(av, gmodulo(v, P)); return gerepilecopy(av, v); } /* N^k * (D * B_k)(x/N), set D = denom(B_k) */ static GEN bern_init(long N, long k, GEN *pD) { return ZX_rescale(Q_remove_denom(bernpol(k, 0), pD), utoi(N)); } /* L(chi_D, 1-k) */ static GEN lfunquadneg_naive(long D, long k) { GEN B, dS, S; long r, N = labs(D); pari_sp av; if (k == 1 && N == 1) return gneg(ghalf); B = bern_init(N, k, &dS); dS = mul_denom(dS, stoi(-N*k)); av = avma; for (r = 0, S = gen_0; r < N; r++) { long c = kross(D, r); if (c) { GEN t = ZX_Z_eval(B, utoi(r)); S = c > 0 ? addii(S, t) : subii(S, t); S = gerepileuptoint(av, S); } } return gdiv(S, dS); } /* Returns vector of coeffs from F[0], F[d], ..., F[d*n] */ static GEN mfcoefs_i(GEN F, long n, long d) { if (n < 0) return gen_0; switch(mf_get_type(F)) { case t_MF_CONST: return c_const(n, d, gel(F,2)); case t_MF_EISEN: return c_mfeisen(n, d, F); case t_MF_Ek: return c_Ek(n, d, F); case t_MF_DELTA: return c_delta(n, d); case t_MF_THETA: return c_theta(n, d, gel(F,2)); case t_MF_ETAQUO: return c_etaquo(n, d, gel(F,2), gel(F,3)); case t_MF_ELL: return c_ell(n, d, gel(F,2)); case t_MF_MUL: return c_mul(n, d, F); case t_MF_POW: return c_pow(n, d, F); case t_MF_BRACKET: return c_bracket(n, d, F); case t_MF_LINEAR: return c_linear(n, d, gel(F,2), gel(F,3), gel(F,4)); case t_MF_LINEAR_BHN: return c_linear_bhn(n, d, F); case t_MF_DIV: return c_div(n, d, F); case t_MF_SHIFT: return c_shift(n, d, gel(F,2), gel(F,3)); case t_MF_DERIV: return c_deriv(n, d, gel(F,2), gel(F,3)); case t_MF_DERIVE2: return c_derivE2(n, d, gel(F,2), gel(F,3)); case t_MF_TWIST: return c_twist(n, d, gel(F,2), gel(F,3)); case t_MF_HECKE: return c_hecke(n, d, gel(F,2), gel(F,3)); case t_MF_BD: return c_Bd(n, d, gel(F,2), gel(F,3)); case t_MF_TRACE: return c_cusptrace(n, d, F); case t_MF_NEWTRACE: return c_newtrace(n, d, F); case t_MF_DIHEDRAL: return c_dihedral(n, d, F); default: pari_err_TYPE("mfcoefs",F); return NULL;/*LCOV_EXCL_LINE*/ } } static GEN matdeflate(long n, long d, GEN M) { long i, l; GEN A; /* if (d == 1) return M; */ A = cgetg_copy(M,&l); for (i = 1; i < l; i++) gel(A,i) = c_deflate(n,d,gel(M,i)); return A; } static int space_is_cusp(long space) { return space != mf_FULL && space != mf_EISEN; } /* safe with flraw mf */ static GEN mfcoefs_mf(GEN mf, long n, long d) { GEN MS, ME, E = MF_get_E(mf), S = MF_get_S(mf), M = MF_get_M(mf); long lE = lg(E), lS = lg(S), l = lE+lS-1; if (l == 1) return cgetg(1, t_MAT); if (typ(M) == t_MAT && lg(M) != 1 && (n+1)*d < nbrows(M)) return matdeflate(n, d, M); /*cached; lg = 1 is possible from mfinit */ ME = (lE == 1)? cgetg(1, t_MAT): mfvectomat(E, n, d); if (lS == 1) MS = cgetg(1, t_MAT); else if (mf_get_type(gel(S,1)) == t_MF_DIV) /*k 1/2-integer or k=1 (exotic)*/ MS = matdeflate(n,d, mflineardivtomat(MF_get_N(mf), S, n*d)); else if (MF_get_k(mf) == 1) /* k = 1 (dihedral) */ { GEN M = mfvectomat(gmael(S,1,2), n, d); long i; MS = cgetg(lS, t_MAT); for (i = 1; i < lS; i++) { GEN f = gel(S,i), dc = gel(f,4), c = RgM_RgC_mul(M, gel(f,3)); if (!equali1(dc)) c = RgC_Rg_div(c,dc); gel(MS,i) = c; } } else /* k >= 2 integer */ MS = bhnmat_extend_nocache(NULL, MF_get_N(mf), n, d, S); return shallowconcat(ME,MS); } GEN mfcoefs(GEN F, long n, long d) { if (!checkmf_i(F)) { pari_sp av = avma; GEN mf = checkMF_i(F); if (!mf) pari_err_TYPE("mfcoefs", F); return gerepilecopy(av, mfcoefs_mf(mf,n,d)); } if (d <= 0) pari_err_DOMAIN("mfcoefs", "d", "<=", gen_0, stoi(d)); if (n < 0) return cgetg(1, t_VEC); return mfcoefs_i(F, n, d); } /* assume k >= 0 */ static GEN mfak_i(GEN F, long k) { if (!k) return gel(mfcoefs_i(F,0,1), 1); return gel(mfcoefs_i(F,1,k), 2); } GEN mfcoef(GEN F, long n) { pari_sp av = avma; if (!checkmf_i(F)) pari_err_TYPE("mfcoef",F); return n < 0? gen_0: gerepilecopy(av, mfak_i(F, n)); } static GEN paramconst() { return tagparams(t_MF_CONST, mkNK(1,0,mfchartrivial())); } static GEN mftrivial(void) { retmkvec2(paramconst(), cgetg(1,t_VEC)); } static GEN mf1(void) { retmkvec2(paramconst(), mkvec(gen_1)); } /* induce mfchar CHI to G */ static GEN induce(GEN G, GEN CHI) { GEN o, chi; if (typ(CHI) == t_INT) /* Kronecker */ { chi = znchar_quad(G, CHI); o = ZV_equal0(chi)? gen_1: gen_2; CHI = mkvec4(G,chi,o,cgetg(1,t_VEC)); } else { if (mfcharmodulus(CHI) == itos(znstar_get_N(G))) return CHI; CHI = leafcopy(CHI); chi = zncharinduce(gel(CHI,1), gel(CHI,2), G); gel(CHI,1) = G; gel(CHI,2) = chi; } return CHI; } /* induce mfchar CHI to znstar(N) */ static GEN induceN(long N, GEN CHI) { if (mfcharmodulus(CHI) != N) CHI = induce(znstar0(utoipos(N),1), CHI); return CHI; } /* *pCHI1 and *pCHI2 are mfchar, induce to common modulus */ static void char2(GEN *pCHI1, GEN *pCHI2) { GEN CHI1 = *pCHI1, G1 = gel(CHI1,1), N1 = znstar_get_N(G1); GEN CHI2 = *pCHI2, G2 = gel(CHI2,1), N2 = znstar_get_N(G2); if (!equalii(N1,N2)) { GEN G, d = gcdii(N1,N2); if (equalii(N2,d)) *pCHI2 = induce(G1, CHI2); else if (equalii(N1,d)) *pCHI1 = induce(G2, CHI1); else { if (!equali1(d)) N2 = diviiexact(N2,d); G = znstar0(mulii(N1,N2), 1); *pCHI1 = induce(G, CHI1); *pCHI2 = induce(G, CHI2); } } } /* mfchar or charinit wrt same modulus; outputs a mfchar */ static GEN mfcharmul_i(GEN CHI1, GEN CHI2) { GEN G = gel(CHI1,1), chi3 = zncharmul(G, gel(CHI1,2), gel(CHI2,2)); return mfcharGL(G, chi3); } /* mfchar or charinit; outputs a mfchar */ static GEN mfcharmul(GEN CHI1, GEN CHI2) { char2(&CHI1, &CHI2); return mfcharmul_i(CHI1,CHI2); } /* mfchar or charinit; outputs a mfchar */ static GEN mfcharpow(GEN CHI, GEN n) { GEN G, chi; G = gel(CHI,1); chi = zncharpow(G, gel(CHI,2), n); return mfchartoprimitive(mfcharGL(G, chi), NULL); } /* mfchar or charinit wrt same modulus; outputs a mfchar */ static GEN mfchardiv_i(GEN CHI1, GEN CHI2) { GEN G = gel(CHI1,1), chi3 = znchardiv(G, gel(CHI1,2), gel(CHI2,2)); return mfcharGL(G, chi3); } /* mfchar or charinit; outputs a mfchar */ static GEN mfchardiv(GEN CHI1, GEN CHI2) { char2(&CHI1, &CHI2); return mfchardiv_i(CHI1,CHI2); } static GEN mfcharconj(GEN CHI) { CHI = leafcopy(CHI); gel(CHI,2) = zncharconj(gel(CHI,1), gel(CHI,2)); return CHI; } /* CHI mfchar, assume 4 | N. Multiply CHI by \chi_{-4} */ static GEN mfchilift(GEN CHI, long N) { CHI = induceN(N, CHI); return mfcharmul_i(CHI, induce(gel(CHI,1), stoi(-4))); } /* CHI defined mod N, N4 = N/4; * if CHI is defined mod N4 return CHI; * else if CHI' = CHI*(-4,.) is defined mod N4, return CHI' (primitive) * else error */ static GEN mfcharchiliftprim(GEN CHI, long N4) { long FC = mfcharconductor(CHI); GEN CHIP; if (N4 % FC == 0) return CHI; CHIP = mfchartoprimitive(mfchilift(CHI, N4 << 2), &FC); if (N4 % FC) pari_err_TYPE("mfkohnenbasis [incorrect CHI]", CHI); return CHIP; } /* ensure CHI(-1) = (-1)^k [k integer] or 1 [half-integer], by multiplying * by (-4/.) if needed */ static GEN mfchiadjust(GEN CHI, GEN gk, long N) { long par = mfcharparity(CHI); if (typ(gk) == t_INT && mpodd(gk)) par = -par; return par == 1 ? CHI : mfchilift(CHI, N); } static GEN mfsamefield(GEN T, GEN P, GEN Q) { if (degpol(P) == 1) return Q; if (degpol(Q) == 1) return P; if (!gequal(P,Q)) pari_err_TYPE("mfsamefield [different fields]",mkvec2(P,Q)); if (T) err_cyclo(); return P; } GEN mfmul(GEN f, GEN g) { pari_sp av = avma; GEN T, N, K, NK, CHI, CHIf, CHIg; if (!checkmf_i(f)) pari_err_TYPE("mfmul",f); if (!checkmf_i(g)) pari_err_TYPE("mfmul",g); N = lcmii(mf_get_gN(f), mf_get_gN(g)); K = gadd(mf_get_gk(f), mf_get_gk(g)); CHIf = mf_get_CHI(f); CHIg = mf_get_CHI(g); CHI = mfchiadjust(mfcharmul(CHIf,CHIg), K, itos(N)); T = chicompat(CHI, CHIf, CHIg); NK = mkgNK(N, K, CHI, mfsamefield(T, mf_get_field(f), mf_get_field(g))); return gerepilecopy(av, T? tag3(t_MF_MUL,NK,f,g,T): tag2(t_MF_MUL,NK,f,g)); } GEN mfpow(GEN f, long n) { pari_sp av = avma; GEN T, KK, NK, gn, CHI, CHIf; if (!checkmf_i(f)) pari_err_TYPE("mfpow",f); if (!n) return mf1(); if (n == 1) return gcopy(f); KK = gmulsg(n,mf_get_gk(f)); gn = stoi(n); CHIf = mf_get_CHI(f); CHI = mfchiadjust(mfcharpow(CHIf,gn), KK, mf_get_N(f)); T = chicompat(CHI, CHIf, CHIf); NK = mkgNK(mf_get_gN(f), KK, CHI, mf_get_field(f)); return gerepilecopy(av, T? tag3(t_MF_POW,NK,f,gn,T): tag2(t_MF_POW,NK,f,gn)); } GEN mfbracket(GEN f, GEN g, long m) { pari_sp av = avma; GEN T, N, K, NK, CHI, CHIf, CHIg; if (!checkmf_i(f)) pari_err_TYPE("mfbracket",f); if (!checkmf_i(g)) pari_err_TYPE("mfbracket",g); if (m < 0) pari_err_TYPE("mfbracket [m<0]",stoi(m)); K = gaddgs(gadd(mf_get_gk(f), mf_get_gk(g)), 2*m); if (gsigne(K) < 0) pari_err_IMPL("mfbracket for this form"); N = lcmii(mf_get_gN(f), mf_get_gN(g)); CHIf = mf_get_CHI(f); CHIg = mf_get_CHI(g); CHI = mfcharmul(CHIf, CHIg); CHI = mfchiadjust(CHI, K, itou(N)); T = chicompat(CHI, CHIf, CHIg); NK = mkgNK(N, K, CHI, mfsamefield(T, mf_get_field(f), mf_get_field(g))); return gerepilecopy(av, T? tag4(t_MF_BRACKET, NK, f, g, utoi(m), T) : tag3(t_MF_BRACKET, NK, f, g, utoi(m))); } /* remove 0 entries in L */ static int mflinear_strip(GEN *pF, GEN *pL) { pari_sp av = avma; GEN F = *pF, L = *pL; long i, j, l = lg(L); GEN F2 = cgetg(l, t_VEC), L2 = cgetg(l, t_VEC); for (i = j = 1; i < l; i++) { if (gequal0(gel(L,i))) continue; gel(F2,j) = gel(F,i); gel(L2,j) = gel(L,i); j++; } if (j == l) set_avma(av); else { setlg(F2,j); *pF = F2; setlg(L2,j); *pL = L2; } return (j > 1); } static GEN taglinear_i(long t, GEN NK, GEN F, GEN L) { GEN dL; L = Q_remove_denom(L, &dL); if (!dL) dL = gen_1; return tag3(t, NK, F, L, dL); } static GEN taglinear(GEN NK, GEN F, GEN L) { long t = ok_bhn_linear(F)? t_MF_LINEAR_BHN: t_MF_LINEAR; return taglinear_i(t, NK, F, L); } /* assume F has parameters NK = [N,K,CHI] */ static GEN mflinear_i(GEN NK, GEN F, GEN L) { if (!mflinear_strip(&F,&L)) return mftrivial(); return taglinear(NK, F,L); } static GEN mflinear_bhn(GEN mf, GEN L) { long i, l; GEN P, NK, F = MF_get_S(mf); if (!mflinear_strip(&F,&L)) return mftrivial(); l = lg(L); P = pol_x(1); for (i = 1; i < l; i++) { GEN c = gel(L,i); if (typ(c) == t_POLMOD && varn(gel(c,1)) == 1) P = mfsamefield(NULL, P, gel(c,1)); } NK = mkgNK(MF_get_gN(mf), MF_get_gk(mf), MF_get_CHI(mf), P); return taglinear_i(t_MF_LINEAR_BHN, NK, F,L); } /* F vector of forms with same weight and character but varying level, return * global [N,k,chi,P] */ static GEN vecmfNK(GEN F) { long i, l = lg(F); GEN N, f; if (l == 1) return mkNK(1, 0, mfchartrivial()); f = gel(F,1); N = mf_get_gN(f); for (i = 2; i < l; i++) N = lcmii(N, mf_get_gN(gel(F,i))); return mkgNK(N, mf_get_gk(f), mf_get_CHI(f), mf_get_field(f)); } /* do not use mflinear: mflineardivtomat rely on F being constant across the * basis where mflinear strips the ones matched by 0 coeffs. Assume k and CHI * constant, N is allowed to vary. */ static GEN vecmflinear(GEN F, GEN C) { long i, t, l = lg(C); GEN NK, v = cgetg(l, t_VEC); if (l == 1) return v; t = ok_bhn_linear(F)? t_MF_LINEAR_BHN: t_MF_LINEAR; NK = vecmfNK(F); for (i = 1; i < l; i++) gel(v,i) = taglinear_i(t, NK, F, gel(C,i)); return v; } /* vecmflinear(F,C), then divide everything by E, which has valuation 0 */ static GEN vecmflineardiv0(GEN F, GEN C, GEN E) { GEN v = vecmflinear(F, C); long i, l = lg(v); if (l == 1) return v; gel(v,1) = mfdiv_val(gel(v,1), E, 0); for (i = 2; i < l; i++) { /* v[i] /= E */ GEN f = shallowcopy(gel(v,1)); gel(f,2) = gel(v,i); gel(v,i) = f; } return v; } /* Non empty linear combination of linear combinations of same * F_j=\sum_i \mu_{i,j}G_i so R = \sum_i (\sum_j(\la_j\mu_{i,j})) G_i */ static GEN mflinear_linear(GEN F, GEN L, int strip) { long l = lg(F), j; GEN vF, M = cgetg(l, t_MAT); L = shallowcopy(L); for (j = 1; j < l; j++) { GEN f = gel(F,j), c = gel(f,3), d = gel(f,4); if (typ(c) == t_VEC) c = shallowtrans(c); if (!isint1(d)) gel(L,j) = gdiv(gel(L,j),d); gel(M,j) = c; } vF = gmael(F,1,2); L = RgM_RgC_mul(M,L); if (strip && !mflinear_strip(&vF,&L)) return mftrivial(); return taglinear(vecmfNK(vF), vF, L); } /* F nonempty vector of forms of the form mfdiv(mflinear(B,v), E) where E * does not vanish at oo, or mflinear(B,v). Apply mflinear(F, L) */ static GEN mflineardiv_linear(GEN F, GEN L, int strip) { long l = lg(F), j; GEN v, E, f; if (lg(L) != l) pari_err_DIM("mflineardiv_linear"); f = gel(F,1); /* l > 1 */ if (mf_get_type(f) != t_MF_DIV) return mflinear_linear(F,L,strip); E = gel(f,3); v = cgetg(l, t_VEC); for (j = 1; j < l; j++) { GEN f = gel(F,j); gel(v,j) = gel(f,2); } return mfdiv_val(mflinear_linear(v,L,strip), E, 0); } static GEN vecmflineardiv_linear(GEN F, GEN M) { long i, l = lg(M); GEN v = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(v,i) = mflineardiv_linear(F, gel(M,i), 0); return v; } static GEN tobasis(GEN mf, GEN F, GEN L) { if (checkmf_i(L) && mf) return mftobasis(mf, L, 0); if (typ(F) != t_VEC) pari_err_TYPE("mflinear",F); if (!is_vec_t(typ(L))) pari_err_TYPE("mflinear",L); if (lg(L) != lg(F)) pari_err_DIM("mflinear"); return L; } GEN mflinear(GEN F, GEN L) { pari_sp av = avma; GEN G, NK, P, mf = checkMF_i(F), N = NULL, K = NULL, CHI = NULL; long i, l; if (mf) { GEN gk = MF_get_gk(mf); F = MF_get_basis(F); if (typ(gk) != t_INT) return gerepilecopy(av, mflineardiv_linear(F, L, 1)); if (itou(gk) > 1 && space_is_cusp(MF_get_space(mf))) { L = tobasis(mf, F, L); return gerepilecopy(av, mflinear_bhn(mf, L)); } } L = tobasis(mf, F, L); if (!mflinear_strip(&F,&L)) return mftrivial(); l = lg(F); if (l == 2 && gequal1(gel(L,1))) return gerepilecopy(av, gel(F,1)); P = pol_x(1); for (i = 1; i < l; i++) { GEN f = gel(F,i), c = gel(L,i), Ni, Ki; if (!checkmf_i(f)) pari_err_TYPE("mflinear", f); Ni = mf_get_gN(f); N = N? lcmii(N, Ni): Ni; Ki = mf_get_gk(f); if (!K) K = Ki; else if (!gequal(K, Ki)) pari_err_TYPE("mflinear [different weights]", mkvec2(K,Ki)); P = mfsamefield(NULL, P, mf_get_field(f)); if (typ(c) == t_POLMOD && varn(gel(c,1)) == 1) P = mfsamefield(NULL, P, gel(c,1)); } G = znstar0(N,1); for (i = 1; i < l; i++) { GEN CHI2 = mf_get_CHI(gel(F,i)); CHI2 = induce(G, CHI2); if (!CHI) CHI = CHI2; else if (!gequal(CHI, CHI2)) pari_err_TYPE("mflinear [different characters]", mkvec2(CHI,CHI2)); } NK = mkgNK(N, K, CHI, P); return gerepilecopy(av, taglinear(NK,F,L)); } GEN mfshift(GEN F, long sh) { pari_sp av = avma; if (!checkmf_i(F)) pari_err_TYPE("mfshift",F); return gerepilecopy(av, tag2(t_MF_SHIFT, mf_get_NK(F), F, stoi(sh))); } static long mfval(GEN F) { pari_sp av = avma; long i = 0, n, sb; GEN gk, gN; if (!checkmf_i(F)) pari_err_TYPE("mfval", F); gN = mf_get_gN(F); gk = mf_get_gk(F); sb = mfsturmNgk(itou(gN), gk); for (n = 1; n <= sb;) { GEN v; if (n > 0.5*sb) n = sb+1; v = mfcoefs_i(F, n, 1); for (; i <= n; i++) if (!gequal0(gel(v, i+1))) return gc_long(av,i); n <<= 1; } return gc_long(av,-1); } GEN mfdiv_val(GEN f, GEN g, long vg) { GEN T, N, K, NK, CHI, CHIf, CHIg; if (vg) { f = mfshift(f,vg); g = mfshift(g,vg); } N = lcmii(mf_get_gN(f), mf_get_gN(g)); K = gsub(mf_get_gk(f), mf_get_gk(g)); CHIf = mf_get_CHI(f); CHIg = mf_get_CHI(g); CHI = mfchiadjust(mfchardiv(CHIf, CHIg), K, itos(N)); T = chicompat(CHI, CHIf, CHIg); NK = mkgNK(N, K, CHI, mfsamefield(T, mf_get_field(f), mf_get_field(g))); return T? tag3(t_MF_DIV, NK, f, g, T): tag2(t_MF_DIV, NK, f, g); } GEN mfdiv(GEN F, GEN G) { pari_sp av = avma; long v = mfval(G); if (!checkmf_i(F)) pari_err_TYPE("mfdiv", F); if (v < 0 || (v && !gequal0(mfcoefs(F, v-1, 1)))) pari_err_DOMAIN("mfdiv", "ord(G)", ">", strtoGENstr("ord(F)"), mkvec2(F, G)); return gerepilecopy(av, mfdiv_val(F, G, v)); } GEN mfderiv(GEN F, long m) { pari_sp av = avma; GEN NK, gk; if (!checkmf_i(F)) pari_err_TYPE("mfderiv",F); gk = gaddgs(mf_get_gk(F), 2*m); NK = mkgNK(mf_get_gN(F), gk, mf_get_CHI(F), mf_get_field(F)); return gerepilecopy(av, tag2(t_MF_DERIV, NK, F, stoi(m))); } GEN mfderivE2(GEN F, long m) { pari_sp av = avma; GEN NK, gk; if (!checkmf_i(F)) pari_err_TYPE("mfderivE2",F); if (m < 0) pari_err_DOMAIN("mfderivE2","m","<",gen_0,stoi(m)); gk = gaddgs(mf_get_gk(F), 2*m); NK = mkgNK(mf_get_gN(F), gk, mf_get_CHI(F), mf_get_field(F)); return gerepilecopy(av, tag2(t_MF_DERIVE2, NK, F, stoi(m))); } GEN mftwist(GEN F, GEN D) { pari_sp av = avma; GEN NK, CHI, NT, Da; long q; if (!checkmf_i(F)) pari_err_TYPE("mftwist", F); if (typ(D) != t_INT) pari_err_TYPE("mftwist", D); Da = mpabs_shallow(D); CHI = mf_get_CHI(F); q = mfcharconductor(CHI); NT = glcm(glcm(mf_get_gN(F), mulsi(q, Da)), sqri(Da)); NK = mkgNK(NT, mf_get_gk(F), CHI, mf_get_field(F)); return gerepilecopy(av, tag2(t_MF_TWIST, NK, F, D)); } /***************************************************************/ /* Generic cache handling */ /***************************************************************/ enum { cache_FACT, cache_DIV, cache_H, cache_D, cache_DIH }; typedef struct { const char *name; GEN cache; ulong minself, maxself; void (*init)(long); ulong miss, maxmiss; long compressed; } cache; static void constfact(long lim); static void constdiv(long lim); static void consttabh(long lim); static void consttabdihedral(long lim); static void constcoredisc(long lim); static THREAD cache caches[] = { { "Factors", NULL, 50000, 50000, &constfact, 0, 0, 0 }, { "Divisors", NULL, 50000, 50000, &constdiv, 0, 0, 0 }, { "H", NULL, 100000, 10000000, &consttabh, 0, 0, 1 }, { "CorediscF",NULL, 100000, 10000000, &constcoredisc, 0, 0, 0 }, { "Dihedral", NULL, 1000, 3000, &consttabdihedral, 0, 0, 0 }, }; static void cache_reset(long id) { caches[id].miss = caches[id].maxmiss = 0; } static void cache_delete(long id) { guncloneNULL(caches[id].cache); } static void cache_set(long id, GEN S) { GEN old = caches[id].cache; caches[id].cache = gclone(S); guncloneNULL(old); } /* handle a cache miss: store stats, possibly reset table; return value * if (now) cached; return NULL on failure. HACK: some caches contain an * ulong where the 0 value is impossible, and return it (typecast to GEN) */ static GEN cache_get(long id, ulong D) { cache *S = &caches[id]; const ulong d = S->compressed? D>>1: D; ulong max, l; if (!S->cache) { max = maxuu(minuu(D, S->maxself), S->minself); S->init(max); l = lg(S->cache); } else { l = lg(S->cache); if (l <= d) { if (D > S->maxmiss) S->maxmiss = D; if (DEBUGLEVEL >= 3) err_printf("miss in cache %s: %lu, max = %lu\n", S->name, D, S->maxmiss); if (S->miss++ >= 5 && D < S->maxself) { max = minuu(S->maxself, (long)(S->maxmiss * 1.2)); if (max <= S->maxself) { if (DEBUGLEVEL >= 3) err_printf("resetting cache %s to %lu\n", S->name, max); S->init(max); l = lg(S->cache); } } } } return (l <= d)? NULL: gel(S->cache, d); } static GEN cache_report(long id) { cache *S = &caches[id]; GEN v = zerocol(5); gel(v,1) = strtoGENstr(S->name); if (S->cache) { gel(v,2) = utoi(lg(S->cache)-1); gel(v,3) = utoi(S->miss); gel(v,4) = utoi(S->maxmiss); gel(v,5) = utoi(gsizebyte(S->cache)); } return v; } GEN getcache(void) { pari_sp av = avma; GEN M = cgetg(6, t_MAT); gel(M,1) = cache_report(cache_FACT); gel(M,2) = cache_report(cache_DIV); gel(M,3) = cache_report(cache_H); gel(M,4) = cache_report(cache_D); gel(M,5) = cache_report(cache_DIH); return gerepilecopy(av, shallowtrans(M)); } void pari_close_mf(void) { cache_delete(cache_FACT); cache_delete(cache_DIV); cache_delete(cache_H); cache_delete(cache_D); cache_delete(cache_DIH); } /*************************************************************************/ /* a odd, update local cache (recycle memory) */ static GEN update_factor_cache(long a, long lim, long *pb) { const long step = 16000; /* even; don't increase this: RAM cache thrashing */ if (a + 2*step > lim) *pb = lim; /* fuse last 2 chunks */ else *pb = a + step; return vecfactoroddu_i(a, *pb); } /* assume lim < MAX_LONG/8 */ static void constcoredisc(long lim) { pari_sp av2, av = avma; GEN D = caches[cache_D].cache, CACHE = NULL; long cachea, cacheb, N, LIM = !D ? 4 : lg(D)-1; if (lim <= 0) lim = 5; if (lim <= LIM) return; cache_reset(cache_D); D = zero_zv(lim); av2 = avma; cachea = cacheb = 0; for (N = 1; N <= lim; N+=2) { /* N odd */ long i, d, d2; GEN F; if (N > cacheb) { set_avma(av2); cachea = N; CACHE = update_factor_cache(N, lim, &cacheb); } F = gel(CACHE, ((N-cachea)>>1)+1); /* factoru(N) */ D[N] = d = corediscs_fact(F); /* = 3 mod 4 or 4 mod 16 */ d2 = odd(d)? d<<3: d<<1; for (i = 1;;) { if ((N << i) > lim) break; D[N< lim) break; D[N< 1, D = divisors(n); sets L = 2*lambda(n), S = sigma(n) */ static void lamsig(GEN D, long *pL, long *pS) { pari_sp av = avma; long i, l = lg(D), L = 1, S = D[l-1]+1; for (i = 2; i < l; i++) /* skip d = 1 */ { long d = D[i], nd = D[l-i]; /* nd = n/d */ if (d < nd) { L += d; S += d + nd; } else { L <<= 1; if (d == nd) { L += d; S += d; } break; } } set_avma(av); *pL = L; *pS = S; } /* table of 6 * Hurwitz class numbers D <= lim */ static void consttabh(long lim) { pari_sp av = avma, av2; GEN VHDH0, VDIV, CACHE = NULL; GEN VHDH = caches[cache_H].cache; long r, N, cachea, cacheb, lim0 = VHDH? lg(VHDH)-1: 2, LIM = lim0 << 1; if (lim <= 0) lim = 5; if (lim <= LIM) return; cache_reset(cache_H); r = lim&3L; if (r) lim += 4-r; cache_get(cache_DIV, lim); VDIV = caches[cache_DIV].cache; VHDH0 = cgetg(lim/2 + 1, t_VECSMALL); VHDH0[1] = 2; VHDH0[2] = 3; for (N = 3; N <= lim0; N++) VHDH0[N] = VHDH[N]; av2 = avma; cachea = cacheb = 0; for (N = LIM + 3; N <= lim; N += 4) { long s = 0, limt = usqrt(N>>2), flsq = 0, ind, t, L, S; GEN DN, DN2; if (N + 2 >= lg(VDIV)) { /* use local cache */ GEN F; if (N + 2 > cacheb) { set_avma(av2); cachea = N; CACHE = update_factor_cache(N, lim+2, &cacheb); } F = gel(CACHE, ((N-cachea)>>1)+1); /* factoru(N) */ DN = divisorsu_fact(F); F = gel(CACHE, ((N-cachea)>>1)+2); /* factoru(N+2) */ DN2 = divisorsu_fact(F); } else { /* use global cache */ DN = gel(VDIV,N); DN2 = gel(VDIV,N+2); } ind = N >> 1; for (t = 1; t <= limt; t++) { ind -= (t<<2)-2; /* N/2 - 2t^2 */ if (ind) s += VHDH0[ind]; else flsq = 1; } lamsig(DN, &L,&S); VHDH0[N >> 1] = 2*S - 3*L - 2*s + flsq; s = 0; flsq = 0; limt = (usqrt(N+2) - 1) >> 1; ind = (N+1) >> 1; for (t = 1; t <= limt; t++) { ind -= t<<2; /* (N+1)/2 - 2t(t+1) */ if (ind) s += VHDH0[ind]; else flsq = 1; } lamsig(DN2, &L,&S); VHDH0[(N+1) >> 1] = S - 3*(L >> 1) - s - flsq; } cache_set(cache_H, VHDH0); set_avma(av); } /*************************************************************************/ /* Core functions using factorizations, divisors of class numbers caches */ /* TODO: myfactoru and factorization cache should be exported */ static GEN myfactoru(long N) { GEN z = cache_get(cache_FACT, N); return z? gcopy(z): factoru(N); } static GEN mydivisorsu(long N) { GEN z = cache_get(cache_DIV, N); return z? leafcopy(z): divisorsu(N); } /* write -n = Df^2, D < 0 fundamental discriminant. Return D, set f. */ static long mycoredisc2neg(ulong n, long *pf) { ulong m, D = (ulong)cache_get(cache_D, n); if (D) { *pf = usqrt(n/D); return -(long)D; } m = mycore(n, pf); if ((m&3) != 3) { m <<= 2; *pf >>= 1; } return (long)-m; } /* write n = Df^2, D > 0 fundamental discriminant. Return D, set f. */ static long mycoredisc2pos(ulong n, long *pf) { ulong m = mycore(n, pf); if ((m&3) != 1) { m <<= 2; *pf >>= 1; } return (long)m; } /* D < 0 fundamental. Return 6*hclassno(-D); faster than quadclassunit up * to 5*10^5 or so */ static ulong hclassno6_count(long D) { ulong a, b, b2, h = 0, d = -D; int f = 0; if (d > 500000) return 6 * quadclassnos(D); /* this part would work with -d non fundamental */ b = d&1; b2 = (1+d)>>2; 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) return 6*h+2; if (f) return 6*h+3; return 6*h; } /* D0 < 0; 6 * hclassno(-D), using D = D0*F^2 */ static long hclassno6u_2(long D0, long F) { long h; if (F == 1) h = hclassno6_count(D0); else { /* second chance */ h = (ulong)cache_get(cache_H, -D0); if (!h) h = hclassno6_count(D0); h *= uhclassnoF_fact(myfactoru(F), D0); } return h; } /* D > 0; 6 * hclassno(D) (6*Hurwitz). Beware, cached value for D (=0,3 mod 4) * is stored at D>>1 */ ulong hclassno6u(ulong D) { ulong z = (ulong)cache_get(cache_H, D); long D0, F; if (z) return z; D0 = mycoredisc2neg(D, &F); return hclassno6u_2(D0,F); } /* same as hclassno6u without creating caches */ ulong hclassno6u_no_cache(ulong D) { cache *S = &caches[cache_H]; long D0, F; if (S->cache) { const ulong d = D>>1; /* compressed */ if ((ulong)lg(S->cache) > d) return S->cache[d]; } S = &caches[cache_D]; if (!S->cache || (ulong)lg(S->cache) <= D) return 0; D0 = mycoredisc2neg(D, &F); return hclassno6u_2(D0,F); } /* same, where the decomposition D = D0*F^2 is already known */ static ulong hclassno6u_i(ulong D, long D0, long F) { ulong z = (ulong)cache_get(cache_H, D); if (z) return z; return hclassno6u_2(D0,F); } /* D < -4 fundamental, h(D), ordinary class number */ static long myh(long D) { ulong z = (ulong)cache_get(cache_H, -D); return z? z / 6: quadclassnos(D); } /*************************************************************************/ /* TRACE FORMULAS */ /* CHIP primitive, initialize for t_POLMOD output */ static GEN mfcharinit(GEN CHIP) { long n, o, l, vt, N = mfcharmodulus(CHIP); GEN c, v, V, G, Pn; if (N == 1) return mkvec2(mkvec(gen_1), pol_x(0)); G = gel(CHIP,1); v = ncharvecexpo(G, znconrey_normalized(G, gel(CHIP,2))); l = lg(v); V = cgetg(l, t_VEC); o = mfcharorder(CHIP); Pn = mfcharpol(CHIP); vt = varn(Pn); if (o <= 2) { for (n = 1; n < l; n++) { if (v[n] < 0) c = gen_0; else c = v[n]? gen_m1: gen_1; gel(V,n) = c; } } else { for (n = 1; n < l; n++) { if (v[n] < 0) c = gen_0; else { c = Qab_zeta(v[n], o, vt); if (typ(c) == t_POL && lg(c) >= lg(Pn)) c = RgX_rem(c, Pn); } gel(V,n) = c; } } return mkvec2(V, Pn); } static GEN vchip_lift(GEN VCHI, long x, GEN C) { GEN V = gel(VCHI,1); long F = lg(V)-1; if (F == 1) return C; x %= F; if (!x) return C; if (x <= 0) x += F; return gmul(C, gel(V, x)); } static long vchip_FC(GEN VCHI) { return lg(gel(VCHI,1))-1; } static GEN vchip_mod(GEN VCHI, GEN S) { return (typ(S) == t_POL)? RgX_rem(S, gel(VCHI,2)): S; } static GEN vchip_polmod(GEN VCHI, GEN S) { return (typ(S) == t_POL)? mkpolmod(S, gel(VCHI,2)): S; } /* contribution of scalar matrices in dimension formula */ static GEN A1(long N, long k) { return uutoQ(mypsiu(N)*(k-1), 12); } static long ceilA1(long N, long k) { return ceildivuu(mypsiu(N) * (k-1), 12); } /* sturm bound, slightly larger than dimension */ long mfsturmNk(long N, long k) { return (mypsiu(N) * k) / 12; } long mfsturmNgk(long N, GEN k) { long n,d; Qtoss(k,&n,&d); return 1 + (mypsiu(N)*n)/(d == 1? 12: 24); } static long mfsturmmf(GEN F) { return mfsturmNgk(mf_get_N(F), mf_get_gk(F)); } /* List of all solutions of x^2 + x + 1 = 0 modulo N, x modulo N */ static GEN sqrtm3modN(long N) { pari_sp av; GEN fa, P, E, B, mB, A, Q, T, R, v, gen_m3; long l, i, n, ct, fl3 = 0, Ninit; if (!odd(N) || (N%9) == 0) return cgetg(1,t_VECSMALL); Ninit = N; if ((N%3) == 0) { N /= 3; fl3 = 1; } fa = myfactoru(N); P = gel(fa, 1); E = gel(fa, 2); l = lg(P); for (i = 1; i < l; i++) if ((P[i]%3) == 2) return cgetg(1,t_VECSMALL); A = cgetg(l, t_VECSMALL); B = cgetg(l, t_VECSMALL); mB= cgetg(l, t_VECSMALL); Q = cgetg(l, t_VECSMALL); gen_m3 = utoineg(3); for (i = 1; i < l; i++) { long p = P[i], e = E[i]; Q[i] = upowuu(p,e); B[i] = itou( Zp_sqrt(gen_m3, utoipos(p), e) ); mB[i]= Q[i] - B[i]; } ct = 1 << (l-1); T = ZV_producttree(Q); R = ZV_chinesetree(Q,T); v = cgetg(ct+1, t_VECSMALL); av = avma; for (n = 1; n <= ct; n++) { long m = n-1, r; for (i = 1; i < l; i++) { A[i] = (m&1L)? mB[i]: B[i]; m >>= 1; } r = itou( ZV_chinese_tree(A, Q, T, R) ); if (fl3) while (r%3) r += N; set_avma(av); v[n] = odd(r) ? (r-1) >> 1 : (r+Ninit-1) >> 1; } return v; } /* number of elliptic points of order 3 in X0(N) */ static long nu3(long N) { long i, l; GEN P; if (!odd(N) || (N%9) == 0) return 0; if ((N%3) == 0) N /= 3; P = gel(myfactoru(N), 1); l = lg(P); for (i = 1; i < l; i++) if ((P[i]%3) == 2) return 0; return 1L<<(l-1); } /* number of elliptic points of order 2 in X0(N) */ static long nu2(long N) { long i, l; GEN P; if ((N&3L) == 0) return 0; if (!odd(N)) N >>= 1; P = gel(myfactoru(N), 1); l = lg(P); for (i = 1; i < l; i++) if ((P[i]&3L) == 3) return 0; return 1L<<(l-1); } /* contribution of elliptic matrices of order 3 in dimension formula * Only depends on CHIP the primitive char attached to CHI */ static GEN A21(long N, long k, GEN CHI) { GEN res, G, chi, o; long a21, i, limx, S; if ((N&1L) == 0) return gen_0; a21 = k%3 - 1; if (!a21) return gen_0; if (N <= 3) return sstoQ(a21, 3); if (!CHI) return sstoQ(nu3(N) * a21, 3); res = sqrtm3modN(N); limx = (N - 1) >> 1; G = gel(CHI,1); chi = gel(CHI,2); o = gmfcharorder(CHI); for (S = 0, i = 1; i < lg(res); i++) { /* (x,N) = 1; S += chi(x) + chi(x^2) */ long x = res[i]; if (x <= limx) { /* CHI(x)=e(c/o), 3rd-root of 1 */ GEN c = znchareval(G, chi, utoi(x), o); if (!signe(c)) S += 2; else S--; } } return sstoQ(a21 * S, 3); } /* List of all square roots of -1 modulo N */ static GEN sqrtm1modN(long N) { pari_sp av; GEN fa, P, E, B, mB, A, Q, T, R, v; long l, i, n, ct, fleven = 0; if ((N&3L) == 0) return cgetg(1,t_VECSMALL); if ((N&1L) == 0) { N >>= 1; fleven = 1; } fa = myfactoru(N); P = gel(fa,1); E = gel(fa,2); l = lg(P); for (i = 1; i < l; i++) if ((P[i]&3L) == 3) return cgetg(1,t_VECSMALL); A = cgetg(l, t_VECSMALL); B = cgetg(l, t_VECSMALL); mB= cgetg(l, t_VECSMALL); Q = cgetg(l, t_VECSMALL); for (i = 1; i < l; i++) { long p = P[i], e = E[i]; Q[i] = upowuu(p,e); B[i] = itou( Zp_sqrt(gen_m1, utoipos(p), e) ); mB[i]= Q[i] - B[i]; } ct = 1 << (l-1); T = ZV_producttree(Q); R = ZV_chinesetree(Q,T); v = cgetg(ct+1, t_VECSMALL); av = avma; for (n = 1; n <= ct; n++) { long m = n-1, r; for (i = 1; i < l; i++) { A[i] = (m&1L)? mB[i]: B[i]; m >>= 1; } r = itou( ZV_chinese_tree(A, Q, T, R) ); if (fleven && !odd(r)) r += N; set_avma(av); v[n] = r; } return v; } /* contribution of elliptic matrices of order 4 in dimension formula. * Only depends on CHIP the primitive char attached to CHI */ static GEN A22(long N, long k, GEN CHI) { GEN G, chi, o, res; long S, a22, i, limx, o2; if ((N&3L) == 0) return gen_0; a22 = (k & 3L) - 1; /* (k % 4) - 1 */ if (!a22) return gen_0; if (N <= 2) return sstoQ(a22, 4); if (!CHI) return sstoQ(nu2(N)*a22, 4); if (mfcharparity(CHI) == -1) return gen_0; res = sqrtm1modN(N); limx = (N - 1) >> 1; G = gel(CHI,1); chi = gel(CHI,2); o = gmfcharorder(CHI); o2 = itou(o)>>1; for (S = 0, i = 1; i < lg(res); i++) { /* (x,N) = 1, S += real(chi(x)) */ long x = res[i]; if (x <= limx) { /* CHI(x)=e(c/o), 4th-root of 1 */ long c = itou( znchareval(G, chi, utoi(x), o) ); if (!c) S++; else if (c == o2) S--; } } return sstoQ(a22 * S, 2); } /* sumdiv(N,d,eulerphi(gcd(d,N/d))) */ static long nuinf(long N) { GEN fa = myfactoru(N), P = gel(fa,1), E = gel(fa,2); long i, t = 1, l = lg(P); for (i=1; i>1) << 1; else t *= upowuu(p,(e>>1)-1) * (p+1); } return t; } /* contribution of hyperbolic matrices in dimension formula */ static GEN A3(long N, long FC) { long i, S, NF, l; GEN D; if (FC == 1) return uutoQ(nuinf(N),2); D = mydivisorsu(N); l = lg(D); S = 0; NF = N/FC; for (i = 1; i < l; i++) { long g = ugcd(D[i], D[l-i]); if (NF%g == 0) S += myeulerphiu(g); } return uutoQ(S, 2); } /* special contribution in weight 2 in dimension formula */ static long A4(long k, long FC) { return (k==2 && FC==1)? 1: 0; } /* gcd(x,N) */ static long myugcd(GEN GCD, ulong x) { ulong N = lg(GCD)-1; if (x >= N) x %= N; return GCD[x+1]; } /* 1_{gcd(x,N) = 1} * chi(x), return NULL if 0 */ static GEN mychicgcd(GEN GCD, GEN VCHI, long x) { long N = lg(GCD)-1; if (N == 1) return gen_1; x = umodsu(x, N); if (GCD[x+1] != 1) return NULL; x %= vchip_FC(VCHI); if (!x) return gen_1; return gel(gel(VCHI,1), x); } /* contribution of scalar matrices to trace formula */ static GEN TA1(long N, long k, GEN VCHI, GEN GCD, long n) { GEN S; ulong m; if (!uissquareall(n, &m)) return gen_0; if (m == 1) return A1(N,k); /* common */ S = mychicgcd(GCD, VCHI, m); return S? gmul(gmul(powuu(m, k-2), A1(N,k)), S): gen_0; } /* All square roots modulo 4N, x modulo 2N, precomputed to accelerate TA2 */ static GEN mksqr(long N) { pari_sp av = avma; long x, N2 = N << 1, N4 = N << 2; GEN v = const_vec(N2, cgetg(1, t_VECSMALL)); gel(v, N2) = mkvecsmall(0); /* x = 0 */ for (x = 1; x <= N; x++) { long r = (((x*x - 1)%N4) >> 1) + 1; gel(v,r) = vecsmall_append(gel(v,r), x); } return gerepilecopy(av, v); } static GEN mkgcd(long N) { GEN GCD, d; long i, N2; if (N == 1) return mkvecsmall(N); GCD = cgetg(N + 1, t_VECSMALL); d = GCD+1; /* GCD[i+1] = d[i] = gcd(i,N) = gcd(N-i,N), i = 0..N-1 */ d[0] = N; d[1] = d[N-1] = 1; N2 = N>>1; for (i = 2; i <= N2; i++) d[i] = d[N-i] = ugcd(N, i); return GCD; } /* Table of \sum_{x^2-tx+n=0 mod Ng}chi(x) for all g dividing gcd(N,F), * F^2 largest such that (t^2-4n)/F^2=0 or 1 mod 4; t >= 0 */ static GEN mutglistall(long t, long N, long NF, GEN VCHI, long n, GEN MUP, GEN li, GEN GCD) { long i, lx = lg(li); GEN DNF = mydivisorsu(NF), v = zerovec(NF); long j, g, lDNF = lg(DNF); for (i = 1; i < lx; i++) { long x = (li[i] + t) >> 1, y, lD; GEN D, c = mychicgcd(GCD, VCHI, x); if (li[i] && li[i] != N) { GEN c2 = mychicgcd(GCD, VCHI, t - x); if (c2) c = c? gadd(c, c2): c2; } if (!c) continue; y = (x*(x - t) + n) / N; /* exact division */ D = mydivisorsu(ugcd(labs(y), NF)); lD = lg(D); for (j=1; j < lD; j++) { g = D[j]; gel(v,g) = gadd(gel(v,g), c); } } /* j = 1 corresponds to g = 1, and MUP[1] = 1 */ for (j=2; j < lDNF; j++) { g = DNF[j]; gel(v,g) = gmulsg(MUP[g], gel(v,g)); } return v; } /* special case (N,F) = 1: easier */ static GEN mutg1(long t, long N, GEN VCHI, GEN li, GEN GCD) { /* (N,F) = 1 */ GEN S = NULL; long i, lx = lg(li); for (i = 1; i < lx; i++) { long x = (li[i] + t) >> 1; GEN c = mychicgcd(GCD, VCHI, x); if (c) S = S? gadd(S, c): c; if (li[i] && li[i] != N) { c = mychicgcd(GCD, VCHI, t - x); if (c) S = S? gadd(S, c): c; } if (S && !signe(S)) S = NULL; /* strive hard to add gen_0 */ } return S; /* single value */ } /* Gegenbauer pol; n > 2, P = \sum_{0<=j<=n/2} (-1)^j (n-j)!/j!(n-2*j)! X^j */ GEN mfrhopol(long n) { #ifdef LONG_IS_64BIT const long M = 2642249; #else const long M = 1629; #endif long j, d = n >> 1; /* >= 1 */ GEN P = cgetg(d + 3, t_POL); if (n > M) pari_err_IMPL("mfrhopol for large weight"); /* avoid overflow */ P[1] = evalvarn(0)|evalsigne(1); gel(P,2) = gen_1; gel(P,3) = utoineg(n-1); /* j = 1 */ if (d > 1) gel(P,4) = utoipos(((n-3)*(n-2)) >> 1); /* j = 2 */ if (d > 2) gel(P,5) = utoineg(((n-5)*(n-4)*(n-3)) / 6); /* j = 3 */ for (j = 4; j <= d; j++) gel(P,j+2) = divis(mulis(gel(P,j+1), (n-2*j+1)*(n-2*j+2)), (n-j+1)*(-j)); return P; } /* polrecip(Q)(t2), assume Q(0) = 1 */ GEN mfrhopol_u_eval(GEN Q, ulong t2) { GEN T = addiu(gel(Q,3), t2); long l = lg(Q), j; for (j = 4; j < l; j++) T = addii(gel(Q,j), mului(t2, T)); return T; } GEN mfrhopol_eval(GEN Q, GEN t2) { long l, j; GEN T; if (lgefint(t2) == 3) return mfrhopol_u_eval(Q, t2[2]); l = lg(Q); T = addii(gel(Q,3), t2); for (j = 4; j < l; j++) T = addii(gel(Q,j), mulii(t2, T)); return T; } /* return sh * sqrt(n)^nu * G_nu(t/(2*sqrt(n))) for t != 0 * else (sh/2) * sqrt(n)^nu * G_nu(0) [ implies nu is even ] * G_nu(z) = \sum_{0<=j<=nu/2} (-1)^j (nu-j)!/j!(nu-2*j)! * (2z)^(nu-2*j)) */ static GEN mfrhopowsimp(GEN Q, GEN sh, long nu, long t, long t2, long n) { GEN T; switch (nu) { case 0: return t? sh: gmul2n(sh,-1); case 1: return gmulsg(t, sh); case 2: return t? gmulsg(t2 - n, sh): gmul(gmul2n(stoi(-n), -1), sh); case 3: return gmul(mulss(t, t2 - 2*n), sh); default: if (!t) return gmul(gmul2n(gel(Q, lg(Q) - 1), -1), sh); T = mfrhopol_u_eval(Q, t2); if (odd(nu)) T = mulsi(t, T); return gmul(T, sh); } } /* contribution of elliptic matrices to trace formula */ static GEN TA2(long N, long k, GEN VCHI, long n, GEN SQRTS, GEN MUP, GEN GCD) { const long n4 = n << 2, N4 = N << 2, nu = k - 2; const long st = (!odd(N) && odd(n)) ? 2 : 1; long limt, t; GEN S, Q; limt = usqrt(n4); if (limt*limt == n4) limt--; Q = nu > 3 ? ZX_z_unscale(mfrhopol(nu), n) : NULL; S = gen_0; for (t = odd(k)? st: 0; t <= limt; t += st) /* t^2 < 4n */ { pari_sp av = avma; long t2 = t*t, D = n4 - t2, F, D0, NF; GEN sh, li; li = gel(SQRTS, (umodsu(-D - 1, N4) >> 1) + 1); if (lg(li) == 1) continue; D0 = mycoredisc2neg(D, &F); NF = myugcd(GCD, F); if (NF == 1) { /* (N,F) = 1 => single value in mutglistall */ GEN mut = mutg1(t, N, VCHI, li, GCD); if (!mut) { set_avma(av); continue; } sh = gmul(uutoQ(hclassno6u_i(D,D0,F),6), mut); } else { GEN v = mutglistall(t, N, NF, VCHI, n, MUP, li, GCD); GEN DF = mydivisorsu(F); long i, lDF = lg(DF); sh = gen_0; for (i = 1; i < lDF; i++) { long Ff, f = DF[i], g = myugcd(GCD, f); GEN mut = gel(v, g); if (gequal0(mut)) continue; Ff = DF[lDF-i]; /* F/f */ if (Ff == 1) sh = gadd(sh, mut); else { GEN P = gel(myfactoru(Ff), 1); long j, lP = lg(P); for (j = 1; j < lP; j++) { long p = P[j]; Ff -= kross(D0, p)*Ff/p; } sh = gadd(sh, gmulsg(Ff, mut)); } } if (gequal0(sh)) { set_avma(av); continue; } if (D0 == -3) sh = gdivgu(sh, 3); else if (D0 == -4) sh = gdivgu(sh, 2); else sh = gmulgu(sh, myh(D0)); } S = gerepileupto(av, gadd(S, mfrhopowsimp(Q,sh,nu,t,t2,n))); } return S; } /* compute global auxiliary data for TA3 */ static GEN mkbez(long N, long FC) { long ct, i, NF = N/FC; GEN w, D = mydivisorsu(N); long l = lg(D); w = cgetg(l, t_VEC); for (i = ct = 1; i < l; i++) { long u, v, h, c = D[i], Nc = D[l-i]; if (c > Nc) break; h = cbezout(c, Nc, &u, &v); if (h == 1) /* shortcut */ gel(w, ct++) = mkvecsmall4(1,u*c,1,i); else if (!(NF%h)) gel(w, ct++) = mkvecsmall4(h,u*(c/h),myeulerphiu(h),i); } setlg(w,ct); stackdummy((pari_sp)(w+ct),(pari_sp)(w+l)); return w; } /* contribution of hyperbolic matrices to trace formula, d * nd = n, * DN = divisorsu(N) */ static GEN auxsum(GEN VCHI, GEN GCD, long d, long nd, GEN DN, GEN BEZ) { GEN S = gen_0; long ct, g = nd - d, lDN = lg(DN), lBEZ = lg(BEZ); for (ct = 1; ct < lBEZ; ct++) { GEN y, B = gel(BEZ, ct); long ic, c, Nc, uch, h = B[1]; if (g%h) continue; uch = B[2]; ic = B[4]; c = DN[ic]; Nc= DN[lDN - ic]; /* Nc = N/c */ if (ugcd(Nc, nd) == 1) y = mychicgcd(GCD, VCHI, d + uch*g); /* 0 if (c,d) > 1 */ else y = NULL; if (c != Nc && ugcd(Nc, d) == 1) { GEN y2 = mychicgcd(GCD, VCHI, nd - uch*g); /* 0 if (c,nd) > 1 */ if (y2) y = y? gadd(y, y2): y2; } if (y) S = gadd(S, gmulsg(B[3], y)); } return S; } static GEN TA3(long N, long k, GEN VCHI, GEN GCD, GEN Dn, GEN BEZ) { GEN S = gen_0, DN = mydivisorsu(N); long i, l = lg(Dn); for (i = 1; i < l; i++) { long d = Dn[i], nd = Dn[l-i]; /* = n/d */ GEN t, u; if (d > nd) break; t = auxsum(VCHI, GCD, d, nd, DN, BEZ); if (isintzero(t)) continue; u = powuu(d,k-1); if (d == nd) u = gmul2n(u,-1); S = gadd(S, gmul(u,t)); } return S; } /* special contribution in weight 2 in trace formula */ static long TA4(long k, GEN VCHIP, GEN Dn, GEN GCD) { long i, l, S; if (k != 2 || vchip_FC(VCHIP) != 1) return 0; l = lg(Dn); S = 0; for (i = 1; i < l; i++) { long d = Dn[i]; /* gcd(N,n/d) == 1? */ if (myugcd(GCD, Dn[l-i]) == 1) S += d; } return S; } /* precomputation of products occurring im mutg, again to accelerate TA2 */ static GEN mkmup(long N) { GEN fa = myfactoru(N), P = gel(fa,1), D = divisorsu_fact(fa); long i, lP = lg(P), lD = lg(D); GEN MUP = zero_zv(N); MUP[1] = 1; for (i = 2; i < lD; i++) { long j, g = D[i], Ng = D[lD-i]; /* N/g */ for (j = 1; j < lP; j++) { long p = P[j]; if (Ng%p) g += g/p; } MUP[D[i]] = g; } return MUP; } /* quadratic nonresidues mod p; p odd prime, p^2 fits in a long */ static GEN non_residues(long p) { long i, j, p2 = p >> 1; GEN v = cgetg(p2+1, t_VECSMALL), w = const_vecsmall(p-1, 1); for (i = 2; i <= p2; i++) w[(i*i) % p] = 0; /* no need to check 1 */ for (i = 2, j = 1; i < p; i++) if (w[i]) v[j++] = i; return v; } /* CHIP primitive. Return t_VECSMALL v of length q such that * Tr^new_{N,CHIP}(n) = 0 whenever v[(n%q) + 1] is nonzero */ static GEN mfnewzerodata(long N, GEN CHIP) { GEN V, M, L, faN = myfactoru(N), PN = gel(faN,1), EN = gel(faN,2); GEN G = gel(CHIP,1), chi = gel(CHIP,2); GEN fa = znstar_get_faN(G), P = ZV_to_zv(gel(fa,1)), E = gel(fa,2); long i, mod, j = 1, l = lg(PN); M = cgetg(l, t_VECSMALL); M[1] = 0; V = cgetg(l, t_VEC); /* Tr^new(n) = 0 if (n mod M[i]) in V[i] */ if ((N & 3) == 0) { long e = EN[1]; long c = (lg(P) > 1 && P[1] == 2)? E[1]: 0; /* c = v_2(FC) */ /* e >= 2 */ if (c == e-1) return NULL; /* Tr^new = 0 */ if (c == e) { if (e == 2) { /* sc: -4 */ gel(V,1) = mkvecsmall(3); M[1] = 4; } else if (e == 3) { /* sc: -8 (CHI_2(-1)=-1<=>chi[1]=1) and 8 (CHI_2(-1)=1 <=> chi[1]=0) */ long t = signe(gel(chi,1))? 7: 3; gel(V,1) = mkvecsmall2(5, t); M[1] = 8; } } else if (e == 5 && c == 3) { /* sc: -8 (CHI_2(-1)=-1<=>chi[1]=1) and 8 (CHI_2(-1)=1 <=> chi[1]=0) */ long t = signe(gel(chi,1))? 7: 3; gel(V,1) = mkvecsmalln(6, 2L,4L,5L,6L,8L,t); M[1] = 8; } else if ((e == 4 && c == 2) || (e == 5 && c <= 2) || (e == 6 && c <= 2) || (e >= 7 && c == e - 3)) { /* sc: 4 */ gel(V,1) = mkvecsmall3(0,2,3); M[1] = 4; } else if ((e <= 4 && c == 0) || (e >= 5 && c == e - 2)) { /* sc: 2 */ gel(V,1) = mkvecsmall(0); M[1] = 2; } else if ((e == 6 && c == 3) || (e >= 7 && c <= e - 4)) { /* sc: -2 */ gel(V,1) = mkvecsmalln(7, 0L,2L,3L,4L,5L,6L,7L); M[1] = 8; } } j = M[1]? 2: 1; for (i = odd(N)? 1: 2; i < l; i++) /* skip p=2, done above */ { long p = PN[i], e = EN[i]; long z = zv_search(P, p), c = z? E[z]: 0; /* c = v_p(FC) */ if ((e <= 2 && c == 1 && itos(gel(chi,z)) == (p>>1)) /* ord(CHI_p)=2 */ || (e >= 3 && c <= e - 2)) { /* sc: -p */ GEN v = non_residues(p); if (e != 1) v = vecsmall_prepend(v, 0); gel(V,j) = v; M[j] = p; j++; } else if (e >= 2 && c < e) { /* sc: p */ gel(V,j) = mkvecsmall(0); M[j] = p; j++; } } if (j == 1) return cgetg(1, t_VECSMALL); setlg(V,j); setlg(M,j); mod = zv_prod(M); L = zero_zv(mod); for (i = 1; i < j; i++) { GEN v = gel(V,i); long s, m = M[i], lv = lg(v); for (s = 1; s < lv; s++) { long a = v[s] + 1; do { L[a] = 1; a += m; } while (a <= mod); } } return L; } /* v=mfnewzerodata(N,CHI); returns TRUE if newtrace(n) must be zero, * (but newtrace(n) may still be zero if we return FALSE) */ static long mfnewchkzero(GEN v, long n) { long q = lg(v)-1; return q && v[(n%q) + 1]; } /* if (!VCHIP): from mftraceform_cusp; * else from initnewtrace and CHI is known to be primitive */ static GEN inittrace(long N, GEN CHI, GEN VCHIP) { long FC; if (VCHIP) FC = mfcharmodulus(CHI); else VCHIP = mfcharinit(mfchartoprimitive(CHI, &FC)); return mkvecn(5, mksqr(N), mkmup(N), mkgcd(N), VCHIP, mkbez(N, FC)); } /* p > 2 prime; return a sorted t_VECSMALL of primes s.t Tr^new(p) = 0 for all * weights > 2 */ static GEN inittrconj(long N, long FC) { GEN fa, P, E, v; long i, k, l; if (FC != 1) return cgetg(1,t_VECSMALL); fa = myfactoru(N >> vals(N)); P = gel(fa,1); l = lg(P); E = gel(fa,2); v = cgetg(l, t_VECSMALL); for (i = k = 1; i < l; i++) { long j, p = P[i]; /* > 2 */ for (j = 1; j < l; j++) if (j != i && E[j] == 1 && kross(-p, P[j]) == 1) v[k++] = p; } setlg(v,k); return v; } /* assume CHIP primitive, f(CHIP) | N; NZ = mfnewzerodata(N,CHIP) */ static GEN initnewtrace_i(long N, GEN CHIP, GEN NZ) { GEN T = const_vec(N, cgetg(1,t_VEC)), D, VCHIP; long FC = mfcharmodulus(CHIP), N1, N2, i, l; if (!NZ) NZ = mkvecsmall(1); /*Tr^new = 0; initialize data nevertheless*/ VCHIP = mfcharinit(CHIP); N1 = N/FC; newd_params(N1, &N2); D = mydivisorsu(N1/N2); l = lg(D); N2 *= FC; for (i = 1; i < l; i++) { long M = D[i]*N2; gel(T,M) = inittrace(M, CHIP, VCHIP); } gel(T,N) = shallowconcat(gel(T,N), mkvec2(NZ, inittrconj(N,FC))); return T; } /* don't initialize if Tr^new = 0, return NULL */ static GEN initnewtrace(long N, GEN CHI) { GEN CHIP = mfchartoprimitive(CHI, NULL), NZ = mfnewzerodata(N,CHIP); return NZ? initnewtrace_i(N, CHIP, NZ): NULL; } /* (-1)^k */ static long m1pk(long k) { return odd(k)? -1 : 1; } static long badchar(long N, long k, GEN CHI) { return mfcharparity(CHI) != m1pk(k) || (CHI && N % mfcharconductor(CHI)); } static long mfcuspdim_i(long N, long k, GEN CHI, GEN vSP) { pari_sp av = avma; long FC; GEN s; if (k <= 0) return 0; if (k == 1) return CHI? mf1cuspdim(N, CHI, vSP): 0; FC = CHI? mfcharconductor(CHI): 1; if (FC == 1) CHI = NULL; s = gsub(A1(N, k), gadd(A21(N, k, CHI), A22(N, k, CHI))); s = gadd(s, gsubsg(A4(k, FC), A3(N, FC))); return gc_long(av, itos(s)); } /* dimension of space of cusp forms S_k(\G_0(N),CHI) * Only depends on CHIP the primitive char attached to CHI */ long mfcuspdim(long N, long k, GEN CHI) { return mfcuspdim_i(N, k, CHI, NULL); } /* dimension of whole space M_k(\G_0(N),CHI) * Only depends on CHIP the primitive char attached to CHI; assumes !badchar */ long mffulldim(long N, long k, GEN CHI) { pari_sp av = avma; long FC = CHI? mfcharconductor(CHI): 1; GEN s; if (k <= 0) return (k == 0 && FC == 1)? 1: 0; if (k == 1) return gc_long(av, itos(A3(N, FC)) + mf1cuspdim(N, CHI, NULL)); if (FC == 1) CHI = NULL; s = gsub(A1(N, k), gadd(A21(N, k, CHI), A22(N, k, CHI))); s = gadd(s, A3(N, FC)); return gc_long(av, itos(s)); } /* Dimension of the space of Eisenstein series */ long mfeisensteindim(long N, long k, GEN CHI) { pari_sp av = avma; long s, FC = CHI? mfcharconductor(CHI): 1; if (k <= 0) return (k == 0 && FC == 1)? 1: 0; s = itos(gmul2n(A3(N, FC), 1)); if (k > 1) s -= A4(k, FC); else s >>= 1; return gc_long(av,s); } enum { _SQRTS = 1, _MUP, _GCD, _VCHIP, _BEZ, _NEWLZ, _TRCONJ }; /* Trace of T(n) on space of cuspforms; only depends on CHIP the primitive char * attached to CHI */ static GEN mfcusptrace_i(long N, long k, long n, GEN Dn, GEN S) { pari_sp av = avma; GEN a, b, VCHIP, GCD; long t; if (!n) return gen_0; VCHIP = gel(S,_VCHIP); GCD = gel(S,_GCD); t = TA4(k, VCHIP, Dn, GCD); a = TA1(N, k, VCHIP, GCD, n); if (t) a = gaddgs(a,t); b = TA2(N, k, VCHIP, n, gel(S,_SQRTS), gel(S,_MUP), GCD); b = gadd(b, TA3(N, k, VCHIP, GCD, Dn, gel(S,_BEZ))); b = gsub(a,b); if (typ(b) != t_POL) return gerepileupto(av, b); return gerepilecopy(av, vchip_polmod(VCHIP, b)); } static GEN mfcusptracecache(long N, long k, long n, GEN Dn, GEN S, cachenew_t *cache) { GEN C = NULL, T = gel(cache->vfull,N); long lcache = lg(T); if (n < lcache) C = gel(T, n); if (C) cache->cuspHIT++; else C = mfcusptrace_i(N, k, n, Dn, S); cache->cuspTOTAL++; if (n < lcache) gel(T,n) = C; return C; } /* return the divisors of n, known to be among the elements of D */ static GEN div_restrict(GEN D, ulong n) { long i, j, l; GEN v, VDIV = caches[cache_DIV].cache; if (lg(VDIV) > n) return gel(VDIV,n); l = lg(D); v = cgetg(l, t_VECSMALL); for (i = j = 1; i < l; i++) { ulong d = D[i]; if (n % d == 0) v[j++] = d; } setlg(v,j); return v; } /* for some prime divisors of N, Tr^new(p) = 0 */ static int trconj(GEN T, long N, long n) { return (lg(T) > 1 && N % n == 0 && zv_search(T, n)); } /* n > 0; trace formula on new space */ static GEN mfnewtrace_i(long N, long k, long n, cachenew_t *cache) { GEN VCHIP, s, Dn, DN1, SN, S = cache->DATA; long FC, N1, N2, N1N2, g, i, j, lDN1; if (!S) return gen_0; SN = gel(S,N); if (mfnewchkzero(gel(SN,_NEWLZ), n)) return gen_0; if (k > 2 && trconj(gel(SN,_TRCONJ), N, n)) return gen_0; VCHIP = gel(SN, _VCHIP); FC = vchip_FC(VCHIP); N1 = N/FC; newt_params(N1, n, FC, &g, &N2); N1N2 = N1/N2; DN1 = mydivisorsu(N1N2); lDN1 = lg(DN1); N2 *= FC; Dn = mydivisorsu(n); /* this one is probably out of cache */ s = gmulsg(mubeta2(N1N2,n), mfcusptracecache(N2, k, n, Dn, gel(S,N2), cache)); for (i = 2; i < lDN1; i++) { /* skip M1 = 1, done above */ long M1 = DN1[i], N1M1 = DN1[lDN1-i]; GEN Dg = mydivisorsu(ugcd(M1, g)); M1 *= N2; s = gadd(s, gmulsg(mubeta2(N1M1,n), mfcusptracecache(M1, k, n, Dn, gel(S,M1), cache))); for (j = 2; j < lg(Dg); j++) /* skip d = 1, done above */ { long d = Dg[j], ndd = n/(d*d), M = M1/d; GEN z = mulsi(mubeta2(N1M1,ndd), powuu(d,k-1)), C = vchip_lift(VCHIP,d,z); GEN Dndd = div_restrict(Dn, ndd); s = gadd(s, gmul(C, mfcusptracecache(M, k, ndd, Dndd, gel(S,M), cache))); } s = vchip_mod(VCHIP, s); } return vchip_polmod(VCHIP, s); } static GEN get_DIH(long N) { GEN x = cache_get(cache_DIH, N); return x? gcopy(x): mfdihedral(N); } static GEN get_vDIH(long N, GEN D) { GEN x = const_vec(N, NULL); long i, l; if (!D) D = mydivisorsu(N); l = lg(D); for (i = 1; i < l; i++) { long d = D[i]; gel(x, d) = get_DIH(d); } return x; } /* divisors of N which are multiple of F */ static GEN divisorsNF(long N, long F) { GEN D = mydivisorsu(N / F); long l = lg(D), i; for (i = 1; i < l; i++) D[i] = N / D[i]; return D; } /* mfcuspdim(N,k,CHI) - mfnewdim(N,k,CHI); CHIP primitive (for efficiency) */ static long mfolddim_i(long N, long k, GEN CHIP, GEN vSP) { long S, i, l, F = mfcharmodulus(CHIP), N1 = N / F, N2; GEN D; newd_params(N1, &N2); /* will ensure mubeta != 0 */ D = mydivisorsu(N1/N2); l = lg(D); S = 0; if (k == 1 && !vSP) vSP = get_vDIH(N, divisorsNF(N, F)); for (i = 2; i < l; i++) { long d = mfcuspdim_i(N / D[i], k, CHIP, vSP); if (d) S -= mubeta(D[i]) * d; } return S; } long mfolddim(long N, long k, GEN CHI) { pari_sp av = avma; GEN CHIP = mfchartoprimitive(CHI, NULL); return gc_long(av, mfolddim_i(N, k, CHIP, NULL)); } /* Only depends on CHIP the primitive char attached to CHI; assumes !badchar */ long mfnewdim(long N, long k, GEN CHI) { pari_sp av; long S, F; GEN vSP, CHIP = mfchartoprimitive(CHI, &F); vSP = (k == 1)? get_vDIH(N, divisorsNF(N, F)): NULL; S = mfcuspdim_i(N, k, CHIP, vSP); if (!S) return 0; av = avma; return gc_long(av, S - mfolddim_i(N, k, CHIP, vSP)); } /* trace form, given as closure */ static GEN mftraceform_new(long N, long k, GEN CHI) { GEN T; if (k == 1) return initwt1newtrace(mfinit_Nkchi(N, 1, CHI, mf_CUSP, 0)); T = initnewtrace(N,CHI); if (!T) return mftrivial(); return tag(t_MF_NEWTRACE, mkNK(N,k,CHI), T); } static GEN mftraceform_cusp(long N, long k, GEN CHI) { if (k == 1) return initwt1trace(mfinit_Nkchi(N, 1, CHI, mf_CUSP, 0)); return tag(t_MF_TRACE, mkNK(N,k,CHI), inittrace(N,CHI,NULL)); } static GEN mftraceform_i(GEN NK, long space) { GEN CHI; long N, k; checkNK(NK, &N, &k, &CHI, 0); if (!mfdim_Nkchi(N, k, CHI, space)) return mftrivial(); switch(space) { case mf_NEW: return mftraceform_new(N, k, CHI); case mf_CUSP:return mftraceform_cusp(N, k, CHI); } pari_err_DOMAIN("mftraceform", "space", "=", utoi(space), NK); return NULL;/*LCOV_EXCL_LINE*/ } GEN mftraceform(GEN NK, long space) { pari_sp av = avma; return gerepilecopy(av, mftraceform_i(NK,space)); } static GEN hecke_data(long N, long n) { return mkvecsmall3(n, u_ppo(n, N), N); } /* 1/2-integral weight */ static GEN heckef2_data(long N, long n) { ulong f, fN, fN2; if (!uissquareall(n, &f)) return NULL; fN = u_ppo(f, N); fN2 = fN*fN; return mkvec2(myfactoru(fN), mkvecsmall4(n, N, fN2, n/fN2)); } /* N = mf_get_N(F) or a multiple */ static GEN mfhecke_i(long n, long N, GEN F) { if (n == 1) return F; return tag2(t_MF_HECKE, mf_get_NK(F), hecke_data(N,n), F); } GEN mfhecke(GEN mf, GEN F, long n) { pari_sp av = avma; GEN NK, CHI, gk, DATA; long N, nk, dk; mf = checkMF(mf); if (!checkmf_i(F)) pari_err_TYPE("mfhecke",F); if (n <= 0) pari_err_TYPE("mfhecke [n <= 0]", stoi(n)); if (n == 1) return gcopy(F); gk = mf_get_gk(F); Qtoss(gk,&nk,&dk); CHI = mf_get_CHI(F); N = MF_get_N(mf); if (dk == 2) { DATA = heckef2_data(N,n); if (!DATA) return mftrivial(); } else DATA = hecke_data(N,n); NK = mkgNK(lcmii(stoi(N), mf_get_gN(F)), gk, CHI, mf_get_field(F)); return gerepilecopy(av, tag2(t_MF_HECKE, NK, DATA, F)); } /* form F given by closure, compute B(d)(F) as closure (q -> q^d) */ static GEN mfbd_i(GEN F, long d) { GEN D, NK, gk, CHI; if (d == 1) return F; if (d <= 0) pari_err_TYPE("mfbd [d <= 0]", stoi(d)); if (mf_get_type(F) != t_MF_BD) D = utoi(d); else { D = mului(d, gel(F,3)); F = gel(F,2); } gk = mf_get_gk(F); CHI = mf_get_CHI(F); if (typ(gk) != t_INT) CHI = mfcharmul(CHI, get_mfchar(utoi(d << 2))); NK = mkgNK(muliu(mf_get_gN(F), d), gk, CHI, mf_get_field(F)); return tag2(t_MF_BD, NK, F, D); } GEN mfbd(GEN F, long d) { pari_sp av = avma; if (!checkmf_i(F)) pari_err_TYPE("mfbd",F); return gerepilecopy(av, mfbd_i(F, d)); } /* A[i+1] = a(t*i^2) */ static GEN RgV_shimura(GEN A, long n, long t, long N, long r, GEN CHI) { GEN R, a0, Pn = mfcharpol(CHI); long m, st, ord = mfcharorder(CHI), vt = varn(Pn), Nt = t == 1? N: ulcm(N,t); R = cgetg(n + 2, t_VEC); st = odd(r)? -t: t; a0 = gel(A, 1); if (!gequal0(a0)) { long o = mfcharorder(CHI); if (st != 1 && odd(o)) o <<= 1; a0 = gmul(a0, charLFwtk(Nt, r, CHI, o, st)); } gel(R, 1) = a0; for (m = 1; m <= n; m++) { GEN Dm = mydivisorsu(u_ppo(m, Nt)), S = gel(A, m*m + 1); long i, l = lg(Dm); for (i = 2; i < l; i++) { /* (e,Nt) = 1; skip i = 1: e = 1, done above */ long e = Dm[i], me = m / e, a = mfcharevalord(CHI, e, ord); GEN c, C = powuu(e, r - 1); if (kross(st, e) == -1) C = negi(C); c = Qab_Czeta(a, ord, C, vt); S = gadd(S, gmul(c, gel(A, me*me + 1))); } gel(R, m+1) = S; } return degpol(Pn) > 1? gmodulo(R, Pn): R; } static long mfisinkohnen(GEN mf, GEN F) { GEN v, gk = MF_get_gk(mf), CHI = MF_get_CHI(mf); long i, eps, N4 = MF_get_N(mf) >> 2, sb = mfsturmNgk(N4 << 4, gk) + 1; eps = N4 % mfcharconductor(CHI)? -1 : 1; if (odd(MF_get_r(mf))) eps = -eps; v = mfcoefs(F, sb, 1); for (i = 2; i <= sb; i+=4) if (!gequal0(gel(v,i+1))) return 0; for (i = 2+eps; i <= sb; i+=4) if (!gequal0(gel(v,i+1))) return 0; return 1; } static long mfshimura_space_cusp(GEN mf) { long N4; if (MF_get_r(mf) == 1 && (N4 = MF_get_N(mf) >> 2) >= 4) { GEN E = gel(myfactoru(N4), 2); long ma = vecsmall_max(E); if (ma > 2 || (ma == 2 && !mfcharistrivial(MF_get_CHI(mf)))) return 0; } return 1; } /* D is either a discriminant (not necessarily fundamental) with sign(D)=(-1)^{k-1/2}*eps, or a positive squarefree integer t, which is then transformed into a fundamental discriminant of the correct sign. */ GEN mfshimura(GEN mf, GEN F, long t) { pari_sp av = avma; GEN G, res, mf2, CHI; long sb, M, r, N, space = mf_FULL; if (!checkmf_i(F)) pari_err_TYPE("mfshimura",F); mf = checkMF(mf); r = MF_get_r(mf); if (r <= 0) pari_err_DOMAIN("mfshimura", "weight", "<=", ghalf, mf_get_gk(F)); if (t <= 0 || !uissquarefree(t)) pari_err_TYPE("mfshimura [t]", stoi(t)); N = MF_get_N(mf); M = N >> 1; if (mfiscuspidal(mf,F)) { if (mfshimura_space_cusp(mf)) space = mf_CUSP; if (mfisinkohnen(mf,F)) M = N >> 2; } CHI = MF_get_CHI(mf); mf2 = mfinit_Nkchi(M, r << 1, mfcharpow(CHI, gen_2), space, 0); sb = mfsturm(mf2); G = RgV_shimura(mfcoefs_i(F, sb*sb, t), sb, t, N, r, CHI); res = mftobasis_i(mf2, G); /* not mflinear(mf2,): we want lowest possible level */ G = mflinear(MF_get_basis(mf2), res); return gerepilecopy(av, mkvec3(mf2, G, res)); } /* W ZabM (ZM if n = 1), a t_INT or NULL, b t_INT, ZXQ mod P or NULL. * Write a/b = A/d with d t_INT and A Zab return [W,d,A,P] */ static GEN mkMinv(GEN W, GEN a, GEN b, GEN P) { GEN A = (b && typ(b) == t_POL)? Q_remove_denom(QXQ_inv(b,P), &b): NULL; if (a && b) { a = Qdivii(a,b); if (typ(a) == t_INT) b = gen_1; else { b = gel(a,2); a = gel(a,1); } if (is_pm1(a)) a = NULL; } if (a) A = A? ZX_Z_mul(A,a): a; else if (!A) A = gen_1; if (!b) b = gen_1; if (!P) P = gen_0; return mkvec4(W,b,A,P); } /* M square invertible QabM, return [M',d], M*M' = d*Id */ static GEN QabM_Minv(GEN M, GEN P, long n) { GEN dW, W, dM; M = Q_remove_denom(M, &dM); W = P? ZabM_inv(liftpol_shallow(M), P, n, &dW): ZM_inv(M, &dW); return mkMinv(W, dM, dW, P); } /* Simplified form of mfclean, after a QabM_indexrank: M a ZabM with full * column rank and z = indexrank(M) is known */ static GEN mfclean2(GEN M, GEN z, GEN P, long n) { GEN d, Minv, y = gel(z,1), W = rowpermute(M, y); W = P? ZabM_inv(liftpol_shallow(W), P, n, &d): ZM_inv(W, &d); M = rowslice(M, 1, y[lg(y)-1]); Minv = mkMinv(W, NULL, d, P); return mkvec3(y, Minv, M); } /* M QabM, lg(M)>1 and [y,z] its rank profile. Let Minv be the inverse of the * invertible square matrix in mkMinv format. Return [y,Minv, M[..y[#y],]] * P cyclotomic polynomial of order n > 2 or NULL */ static GEN mfclean(GEN M, GEN P, long n, int ratlift) { GEN W, v, y, z, d, Minv, dM, MdM = Q_remove_denom(M, &dM); if (n <= 2) W = ZM_pseudoinv(MdM, &v, &d); else W = ZabM_pseudoinv_i(liftpol_shallow(MdM), P, n, &v, &d, ratlift); y = gel(v,1); z = gel(v,2); if (lg(z) != lg(MdM)) M = vecpermute(M,z); M = rowslice(M, 1, y[lg(y)-1]); Minv = mkMinv(W, dM, d, P); return mkvec3(y, Minv, M); } /* call mfclean using only CHI */ static GEN mfcleanCHI(GEN M, GEN CHI, int ratlift) { long n = mfcharorder(CHI); GEN P = (n <= 2)? NULL: mfcharpol(CHI); return mfclean(M, P, n, ratlift); } /* DATA component of a t_MF_NEWTRACE. Was it stripped to save memory ? */ static int newtrace_stripped(GEN DATA) { return DATA && (lg(DATA) == 5 && typ(gel(DATA,3)) == t_INT); } /* f a t_MF_NEWTRACE */ static GEN newtrace_DATA(long N, GEN f) { GEN DATA = gel(f,2); return newtrace_stripped(DATA)? initnewtrace(N, DATA): DATA; } /* reset cachenew for new level incorporating new DATA, tf a t_MF_NEWTRACE * (+ possibly initialize 'full' for new allowed levels) */ static void reset_cachenew(cachenew_t *cache, long N, GEN tf) { long i, n, l; GEN v, DATA = newtrace_DATA(N,tf); cache->DATA = DATA; if (!DATA) return; n = cache->n; v = cache->vfull; l = N+1; /* = lg(DATA) */ for (i = 1; i < l; i++) if (typ(gel(v,i)) == t_INT && lg(gel(DATA,i)) != 1) gel(v,i) = const_vec(n, NULL); cache->VCHIP = gel(gel(DATA,N),_VCHIP); } /* initialize a cache of newtrace / cusptrace up to index n and level | N; * DATA may be NULL (<=> Tr^new = 0). tf a t_MF_NEWTRACE */ static void init_cachenew(cachenew_t *cache, long n, long N, GEN tf) { long i, l = N+1; /* = lg(tf.DATA) when DATA != NULL */ GEN v; cache->n = n; cache->vnew = v = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(v,i) = (N % i)? gen_0: const_vec(n, NULL); cache->newHIT = cache->newTOTAL = cache->cuspHIT = cache->cuspTOTAL = 0; cache->vfull = v = zerovec(N); reset_cachenew(cache, N, tf); } static void dbg_cachenew(cachenew_t *C) { if (DEBUGLEVEL >= 2 && C) err_printf("newtrace cache hits: new = %ld/%ld, cusp = %ld/%ld\n", C->newHIT, C->newTOTAL, C->cuspHIT, C->cuspTOTAL); } /* newtrace_{N,k}(d*i), i = n0, ..., n */ static GEN colnewtrace(long n0, long n, long d, long N, long k, cachenew_t *cache) { GEN v = cgetg(n-n0+2, t_COL); long i; for (i = n0; i <= n; i++) gel(v, i-n0+1) = mfnewtracecache(N, k, i*d, cache); return v; } /* T_n(l*m0, l*(m0+1), ..., l*m) F, F = t_MF_NEWTRACE [N,k],DATA, cache * contains DATA != NULL as well as cached values of F */ static GEN heckenewtrace(long m0, long m, long l, long N, long NBIG, long k, long n, cachenew_t *cache) { long lD, a, k1, nl = n*l; GEN D, V, v = colnewtrace(m0, m, nl, N, k, cache); /* d=1 */ GEN VCHIP; if (n == 1) return v; VCHIP = cache->VCHIP; D = mydivisorsu(u_ppo(n, NBIG)); lD = lg(D); k1 = k - 1; for (a = 2; a < lD; a++) { /* d > 1, (d,NBIG) = 1 */ long i, j, d = D[a], c = ugcd(l, d), dl = d/c, m0d = ceildivuu(m0, dl); GEN C = vchip_lift(VCHIP, d, powuu(d, k1)); /* m0=0: i = 1 => skip F(0) = 0 */ if (!m0) { i = 1; j = dl; } else { i = 0; j = m0d*dl; } V = colnewtrace(m0d, m/dl, nl/(d*c), N, k, cache); /* C = chi(d) d^(k-1) */ for (; j <= m; i++, j += dl) gel(v,j-m0+1) = gadd(gel(v,j-m0+1), vchip_mod(VCHIP, gmul(C,gel(V,i+1)))); } return v; } /* Given v = an[i], return an[d*i], i=0..n */ static GEN anextract(GEN v, long n, long d) { long i, id, l = n + 2; GEN w = cgetg(l, t_VEC); if (d == 1) for (i = 1; i < l; i++) gel(w, i) = gel(v, i); else for (i = id = 1; i < l; i++, id += d) gel(w, i) = gel(v, id); return w; } /* T_n(F)(0, l, ..., l*m) */ static GEN hecke_i(long m, long l, GEN V, GEN F, GEN DATA) { long k, n, nNBIG, NBIG, lD, M, a, t, nl; GEN D, v, CHI; if (typ(DATA) == t_VEC) { /* 1/2-integral k */ if (!V) { GEN S = gel(DATA,2); V = mfcoefs_i(F, m*l*S[3], S[4]); } return RgV_heckef2(m, l, V, F, DATA); } k = mf_get_k(F); n = DATA[1]; nl = n*l; nNBIG = DATA[2]; NBIG = DATA[3]; if (nNBIG == 1) return V? V: mfcoefs_i(F,m,nl); if (!V && mf_get_type(F) == t_MF_NEWTRACE) { /* inline F to allow cache, T_n at level NBIG acting on Tr^new(N,k,CHI) */ cachenew_t cache; long N = mf_get_N(F); init_cachenew(&cache, m*nl, N, F); v = heckenewtrace(0, m, l, N, NBIG, k, n, &cache); dbg_cachenew(&cache); settyp(v, t_VEC); return v; } CHI = mf_get_CHI(F); D = mydivisorsu(nNBIG); lD = lg(D); M = m + 1; t = nNBIG * ugcd(nNBIG, l); if (!V) V = mfcoefs_i(F, m * t, nl / t); /* usually nl = t */ v = anextract(V, m, t); /* mfcoefs(F, m, nl); d = 1 */ for (a = 2; a < lD; a++) { /* d > 1, (d, NBIG) = 1 */ long d = D[a], c = ugcd(l, d), dl = d/c, i, idl; GEN C = gmul(mfchareval(CHI, d), powuu(d, k-1)); GEN w = anextract(V, m/dl, t/(d*c)); /* mfcoefs(F, m/dl, nl/(d*c)) */ for (i = idl = 1; idl <= M; i++, idl += dl) gel(v,idl) = gadd(gel(v,idl), gmul(C, gel(w,i))); } return v; } static GEN mkmf(GEN x1, GEN x2, GEN x3, GEN x4, GEN x5) { GEN MF = obj_init(5, MF_SPLITN); gel(MF,1) = x1; gel(MF,2) = x2; gel(MF,3) = x3; gel(MF,4) = x4; gel(MF,5) = x5; return MF; } /* return an integer b such that p | b => T_p^k Tr^new = 0, for all k > 0 */ static long get_badj(long N, long FC) { GEN fa = myfactoru(N), P = gel(fa,1), E = gel(fa,2); long i, b = 1, l = lg(P); for (i = 1; i < l; i++) if (E[i] > 1 && u_lval(FC, P[i]) < E[i]) b *= P[i]; return b; } /* in place, assume perm strictly increasing */ static void vecpermute_inplace(GEN v, GEN perm) { long i, l = lg(perm); for (i = 1; i < l; i++) gel(v,i) = gel(v,perm[i]); } /* Find basis of newspace using closures; assume k >= 2 and !badchar. * Return NULL if space is empty, else * [mf1, list of closures T(j)traceform, list of corresponding j, matrix] */ static GEN mfnewinit(long N, long k, GEN CHI, cachenew_t *cache, long init) { GEN S, vj, M, CHIP, mf1, listj, P, tf; long j, ct, ctlj, dim, jin, SB, sb, two, ord, FC, badj; dim = mfnewdim(N, k, CHI); if (!dim && !init) return NULL; sb = mfsturmNk(N, k); CHIP = mfchartoprimitive(CHI, &FC); /* remove newtrace data from S to save space in output: negligible slowdown */ tf = tag(t_MF_NEWTRACE, mkNK(N,k,CHIP), CHIP); badj = get_badj(N, FC); /* try sbsmall first: Sturm bound not sharp for new space */ SB = ceilA1(N, k); listj = cgetg(2*sb + 3, t_VECSMALL); for (j = ctlj = 1; ctlj < 2*sb + 3; j++) if (ugcd(j, badj) == 1) listj[ctlj++] = j; if (init) { init_cachenew(cache, (SB+1)*listj[dim+1], N, tf); if (init == -1 || !dim) return NULL; /* old space or dim = 0 */ } else reset_cachenew(cache, N, tf); /* cache.DATA is not NULL */ ord = mfcharorder(CHIP); P = ord <= 2? NULL: mfcharpol(CHIP); vj = cgetg(dim+1, t_VECSMALL); M = cgetg(dim+1, t_MAT); for (two = 1, ct = 0, jin = 1; two <= 2; two++) { long a, jlim = jin + sb; for (a = jin; a <= jlim; a++) { GEN z, vecz; ct++; vj[ct] = listj[a]; gel(M, ct) = heckenewtrace(0, SB, 1, N, N, k, vj[ct], cache); if (ct < dim) continue; z = QabM_indexrank(M, P, ord); vecz = gel(z, 2); ct = lg(vecz) - 1; if (ct == dim) { M = mkvec3(z, gen_0, M); break; } /*maximal rank, done*/ vecpermute_inplace(M, vecz); vecpermute_inplace(vj, vecz); } if (a <= jlim) break; /* sbsmall was not sufficient, use Sturm bound: must extend M */ for (j = 1; j <= ct; j++) { GEN t = heckenewtrace(SB + 1, sb, 1, N, N, k, vj[j], cache); gel(M,j) = shallowconcat(gel(M, j), t); } jin = jlim + 1; SB = sb; } S = cgetg(dim + 1, t_VEC); for (j = 1; j <= dim; j++) gel(S, j) = mfhecke_i(vj[j], N, tf); dbg_cachenew(cache); mf1 = mkvec4(utoipos(N), utoipos(k), CHI, utoi(mf_NEW)); return mkmf(mf1, cgetg(1,t_VEC), S, vj, M); } /* k > 1 integral, mf space is mf_CUSP or mf_FULL */ static GEN mfinittonew(GEN mf) { GEN CHI = MF_get_CHI(mf), S = MF_get_S(mf), vMjd = MFcusp_get_vMjd(mf); GEN M = MF_get_M(mf), vj, mf1; long i, j, l, l0 = lg(S), N0 = MF_get_N(mf); for (i = l0-1; i > 0; i--) { long N = gel(vMjd,i)[1]; if (N != N0) break; } if (i == l0-1) return NULL; S = vecslice(S, i+1, l0-1); /* forms of conductor N0 */ l = lg(S); vj = cgetg(l, t_VECSMALL); for (j = 1; j < l; j++) vj[j] = gel(vMjd,j+i)[2]; M = vecslice(M, lg(M)-lg(S)+1, lg(M)-1); /* their coefficients */ M = mfcleanCHI(M, CHI, 0); mf1 = mkvec4(utoipos(N0), MF_get_gk(mf), CHI, utoi(mf_NEW)); return mkmf(mf1, cgetg(1,t_VEC), S, vj, M); } /* Bd(f)[m0..m], v = f[ceil(m0/d)..floor(m/d)], m0d = ceil(m0/d) */ static GEN RgC_Bd_expand(long m0, long m, GEN v, long d, long m0d) { long i, j; GEN w; if (d == 1) return v; w = zerocol(m-m0+1); if (!m0) { i = 1; j = d; } else { i = 0; j = m0d*d; } for (; j <= m; i++, j += d) gel(w,j-m0+1) = gel(v,i+1); return w; } /* S a nonempty vector of t_MF_BD(t_MF_HECKE(t_MF_NEWTRACE)); M the matrix * of their coefficients r*0, r*1, ..., r*m0 (~ mfvectomat) or NULL (empty), * extend it to coeffs up to m > m0. The forms B_d(T_j(tf_N))in S should be * sorted by level N, then j, then increasing d. No reordering here. */ static GEN bhnmat_extend(GEN M, long m, long r, GEN S, cachenew_t *cache) { long i, mr, m0, m0r, Nold = 0, jold = 0, l = lg(S); GEN MAT = cgetg(l, t_MAT), v = NULL; if (M) { m0 = nbrows(M); m0r = m0 * r; } else m0 = m0r = 0; mr = m*r; for (i = 1; i < l; i++) { long d, j, md, N; GEN c, f = bhn_parse(gel(S,i), &d,&j); /* t_MF_NEWTRACE */ N = mf_get_N(f); md = ceildivuu(m0r,d); if (N != Nold) { reset_cachenew(cache, N, f); Nold = N; jold = 0; } if (!cache->DATA) { gel(MAT,i) = zerocol(m+1); continue; } if (j != jold || md) { v = heckenewtrace(md, mr/d, 1, N, N, mf_get_k(f), j,cache); jold=j; } c = RgC_Bd_expand(m0r, mr, v, d, md); if (r > 1) c = c_deflate(m-m0, r, c); if (M) c = shallowconcat(gel(M,i), c); gel(MAT,i) = c; } return MAT; } /* k > 1 */ static GEN mfinitcusp(long N, long k, GEN CHI, cachenew_t *cache, long space) { long L, l, lDN1, FC, N1, d1, i, init; GEN vS, vMjd, DN1, vmf, CHIP = mfchartoprimitive(CHI, &FC); d1 = (space == mf_OLD)? mfolddim_i(N, k, CHIP, NULL): mfcuspdim(N, k, CHIP); if (!d1) return NULL; N1 = N/FC; DN1 = mydivisorsu(N1); lDN1 = lg(DN1); init = (space == mf_OLD)? -1: 1; vmf = cgetg(lDN1, t_VEC); for (i = lDN1 - 1, l = 1; i; i--) { /* by decreasing level to allow cache */ GEN mf = mfnewinit(FC*DN1[i], k, CHIP, cache, init); if (mf) gel(vmf, l++) = mf; init = 0; } setlg(vmf,l); vmf = vecreverse(vmf); /* reorder by increasing level */ L = mfsturmNk(N, k)+1; vS = vectrunc_init(L); vMjd = vectrunc_init(L); for (i = 1; i < l; i++) { GEN DNM, mf = gel(vmf,i), S = MF_get_S(mf), vj = MFnew_get_vj(mf); long a, lDNM, lS = lg(S), M = MF_get_N(mf); DNM = mydivisorsu(N / M); lDNM = lg(DNM); for (a = 1; a < lS; a++) { GEN tf = gel(S,a); long b, j = vj[a]; for (b = 1; b < lDNM; b++) { long d = DNM[b]; vectrunc_append(vS, mfbd_i(tf, d)); vectrunc_append(vMjd, mkvecsmall3(M, j, d)); } } } return mkmf(NULL, cgetg(1, t_VEC), vS, vMjd, NULL); } long mfsturm_mf(GEN mf) { GEN Mindex = MF_get_Mindex(mf); long n = lg(Mindex)-1; return n? Mindex[n]-1: 0; } long mfsturm(GEN T) { long N, nk, dk; GEN CHI, mf = checkMF_i(T); if (mf) return mfsturm_mf(mf); checkNK2(T, &N, &nk, &dk, &CHI, 0); return dk == 1 ? mfsturmNk(N, nk) : mfsturmNk(N, (nk + 1) >> 1); } long mfisequal(GEN F, GEN G, long lim) { pari_sp av = avma; long b; if (!checkmf_i(F)) pari_err_TYPE("mfisequal",F); if (!checkmf_i(G)) pari_err_TYPE("mfisequal",G); b = lim? lim: maxss(mfsturmmf(F), mfsturmmf(G)); return gc_long(av, gequal(mfcoefs_i(F, b, 1), mfcoefs_i(G, b, 1))); } GEN mffields(GEN mf) { if (checkmf_i(mf)) return gcopy(mf_get_field(mf)); mf = checkMF(mf); return gcopy(MF_get_fields(mf)); } GEN mfeigenbasis(GEN mf) { pari_sp ltop = avma; GEN F, S, v, vP; long i, l, k, dS; mf = checkMF(mf); k = MF_get_k(mf); S = MF_get_S(mf); dS = lg(S)-1; if (!dS) return cgetg(1, t_VEC); F = MF_get_newforms(mf); vP = MF_get_fields(mf); if (k == 1) { if (MF_get_space(mf) == mf_FULL) { long dE = lg(MF_get_E(mf)) - 1; if (dE) F = rowslice(F, dE+1, dE+dS); } v = vecmflineardiv_linear(S, F); l = lg(v); } else { GEN (*L)(GEN, GEN) = (MF_get_space(mf) == mf_FULL)? mflinear: mflinear_bhn; l = lg(F); v = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(v,i) = L(mf, gel(F,i)); } for (i = 1; i < l; i++) mf_setfield(gel(v,i), gel(vP,i)); return gerepilecopy(ltop, v); } /* Minv = [M, d, A], v a t_COL; A a Zab, d a t_INT; return (A/d) * M*v */ static GEN Minv_RgC_mul(GEN Minv, GEN v) { GEN M = gel(Minv,1), d = gel(Minv,2), A = gel(Minv,3); v = RgM_RgC_mul(M, v); if (!equali1(A)) { if (typ(A) == t_POL && degpol(A) > 0) A = mkpolmod(A, gel(Minv,4)); v = RgC_Rg_mul(v, A); } if (!equali1(d)) v = RgC_Rg_div(v, d); return v; } static GEN Minv_RgM_mul(GEN Minv, GEN B) { long j, l = lg(B); GEN M = cgetg(l, t_MAT); for (j = 1; j < l; j++) gel(M,j) = Minv_RgC_mul(Minv, gel(B,j)); return M; } /* B * Minv; allow B = NULL for Id */ static GEN RgM_Minv_mul(GEN B, GEN Minv) { GEN M = gel(Minv,1), d = gel(Minv,2), A = gel(Minv,3); if (B) M = RgM_mul(B, M); if (!equali1(A)) { if (typ(A) == t_POL) A = mkpolmod(A, gel(Minv,4)); M = RgM_Rg_mul(M, A); } if (!equali1(d)) M = RgM_Rg_div(M,d); return M; } /* perm vector of strictly increasing indices, v a vector or arbitrary length; * the last r entries of perm fall beyond v. * Return v o perm[1..(-r)], discarding the last r entries of v */ static GEN vecpermute_partial(GEN v, GEN perm, long *r) { long i, n = lg(v)-1, l = lg(perm); GEN w; if (perm[l-1] <= n) { *r = 0; return vecpermute(v,perm); } for (i = 1; i < l; i++) if (perm[i] > n) break; *r = l - i; l = i; w = cgetg(l, typ(v)); for (i = 1; i < l; i++) gel(w,i) = gel(v,perm[i]); return w; } /* given form F, find coeffs of F on mfbasis(mf). If power series, not * guaranteed correct if precision less than Sturm bound */ static GEN mftobasis_i(GEN mf, GEN F) { GEN v, Mindex, Minv; if (!MF_get_dim(mf)) return cgetg(1, t_COL); Mindex = MF_get_Mindex(mf); Minv = MF_get_Minv(mf); if (checkmf_i(F)) { long n = Mindex[lg(Mindex)-1]; v = vecpermute(mfcoefs_i(F, n, 1), Mindex); return Minv_RgC_mul(Minv, v); } else { GEN A = gel(Minv,1), d = gel(Minv,2); long r; v = F; switch(typ(F)) { case t_SER: v = sertocol(v); case t_VEC: case t_COL: break; default: pari_err_TYPE("mftobasis", F); } if (lg(v) == 1) pari_err_TYPE("mftobasis",v); v = vecpermute_partial(v, Mindex, &r); if (!r) return Minv_RgC_mul(Minv, v); /* single solution */ /* affine space of dimension r */ v = RgM_RgC_mul(vecslice(A, 1, lg(v)-1), v); if (!equali1(d)) v = RgC_Rg_div(v,d); return mkvec2(v, vecslice(A, lg(A)-r, lg(A)-1)); } } static GEN const_mat(long n, GEN x) { long j, l = n+1; GEN A = cgetg(l,t_MAT); for (j = 1; j < l; j++) gel(A,j) = const_col(n, x); return A; } /* L is the mftobasis of a form on CUSP space. We allow mf_FULL or mf_CUSP */ static GEN mftonew_i(GEN mf, GEN L, long *plevel) { GEN S, listMjd, CHI, res, Aclos, Acoef, D, perm; long N1, LC, lD, i, l, t, level, N = MF_get_N(mf); if (MF_get_k(mf) == 1) pari_err_IMPL("mftonew in weight 1"); listMjd = MFcusp_get_vMjd(mf); CHI = MF_get_CHI(mf); LC = mfcharconductor(CHI); S = MF_get_S(mf); N1 = N/LC; D = mydivisorsu(N1); lD = lg(D); perm = cgetg(N1+1, t_VECSMALL); for (i = 1; i < lD; i++) perm[D[i]] = i; Aclos = const_mat(lD-1, cgetg(1,t_VEC)); Acoef = const_mat(lD-1, cgetg(1,t_VEC)); l = lg(listMjd); for (i = 1; i < l; i++) { long M, d; GEN v; if (gequal0(gel(L,i))) continue; v = gel(listMjd, i); M = perm[ v[1]/LC ]; d = perm[ v[3] ]; gcoeff(Aclos,M,d) = vec_append(gcoeff(Aclos,M,d), gel(S,i)); gcoeff(Acoef,M,d) = shallowconcat(gcoeff(Acoef,M,d), gel(L,i)); } res = cgetg(l, t_VEC); level = 1; for (i = t = 1; i < lD; i++) { long j, M = D[i]*LC; GEN gM = utoipos(M); for (j = 1; j < lD; j++) { GEN f = gcoeff(Aclos,i,j), C, NK; long d; if (lg(f) == 1) continue; d = D[j]; C = gcoeff(Acoef,i,j); NK = mf_get_NK(gel(f, 1)); if (d > 1) { if (lg(f) > 2) pari_err_BUG("should be only one form"); f = gel(f, 1); if (mf_get_type(f) == t_MF_BD) { if (!equaliu(gel(f,3), d)) pari_err_BUG("inconsistent multiplier"); f = gel(f, 2); } f = mkvec(f); } level = ulcm(level, M*d); gel(res,t++) = mkvec3(gM, utoipos(d), mflinear_i(NK,f,C)); } } if (plevel) *plevel = level; setlg(res, t); return res; } GEN mftonew(GEN mf, GEN F) { pari_sp av = avma; GEN ES; long s; mf = checkMF(mf); s = MF_get_space(mf); if (s != mf_FULL && s != mf_CUSP) pari_err_TYPE("mftonew [not a full or cuspidal space]", mf); ES = mftobasisES(mf,F); if (!gequal0(gel(ES,1))) pari_err_TYPE("mftonew [not a cuspidal form]", F); F = gel(ES,2); return gerepilecopy(av, mftonew_i(mf,F, NULL)); } static GEN mfeisenstein_i(long k, GEN CHI1, GEN CHI2); /* mfinit(F * Theta) */ static GEN mf2init(GEN mf) { GEN CHI = MF_get_CHI(mf), gk = gadd(MF_get_gk(mf), ghalf); long N = MF_get_N(mf); return mfinit_Nkchi(N, itou(gk), mfchiadjust(CHI, gk, N), mf_FULL, 0); } static long mfvec_first_cusp(GEN v) { long i, l = lg(v); for (i = 1; i < l; i++) { GEN F = gel(v,i); long t = mf_get_type(F); if (t == t_MF_BD) { F = gel(F,2); t = mf_get_type(F); } if (t == t_MF_HECKE) { F = gel(F,3); t = mf_get_type(F); } if (t == t_MF_NEWTRACE) break; } return i; } /* vF a vector of mf F of type DIV(LINEAR(BAS,L), f) in (lcm) level N, * F[2]=LINEAR(BAS,L), F[2][2]=BAS=fixed basis (Eisenstein or bhn type), * F[2][3]=L, F[3]=f; mfvectomat(vF, n) */ static GEN mflineardivtomat(long N, GEN vF, long n) { GEN F, M, f, fc, ME, dB, B, a0, V = NULL; long lM, lF = lg(vF), j; if (lF == 1) return cgetg(1,t_MAT); F = gel(vF,1); if (lg(F) == 5) { /* chicompat */ V = gmael(F,4,4); if (typ(V) == t_INT) V = NULL; } M = gmael(F,2,2); /* BAS */ lM = lg(M); j = mfvec_first_cusp(M); if (j == 1) ME = NULL; else { /* BAS starts by Eisenstein */ ME = mfvectomat(vecslice(M,1,j-1), n, 1); M = vecslice(M, j,lM-1); } M = bhnmat_extend_nocache(NULL, N, n, 1, M); if (ME) M = shallowconcat(ME,M); /* M = mfcoefs of BAS */ B = cgetg(lF, t_MAT); dB= cgetg(lF, t_VEC); for (j = 1; j < lF; j++) { GEN g = gel(vF, j); /* t_MF_DIV */ gel(B,j) = RgM_RgC_mul(M, gmael(g,2,3)); gel(dB,j)= gmael(g,2,4); } f = mfcoefsser(gel(F,3),n); a0 = polcoef_i(f, 0, -1); if (gequal0(a0) || gequal1(a0)) a0 = NULL; else f = gdiv(ser_unscale(f, a0), a0); fc = ginv(f); for (j = 1; j < lF; j++) { pari_sp av = avma; GEN LISer = RgV_to_ser_full(gel(B,j)), f; if (a0) LISer = gdiv(ser_unscale(LISer, a0), a0); f = gmul(LISer, fc); if (a0) f = ser_unscale(f, ginv(a0)); f = sertocol(f); setlg(f, n+2); if (!gequal1(gel(dB,j))) f = RgC_Rg_div(f, gel(dB,j)); gel(B,j) = gerepileupto(av,f); } if (V) B = gmodulo(QabM_tracerel(V, 0, B), gel(V,1)); return B; } static GEN mfheckemat_mfcoefs(GEN mf, GEN B, GEN DATA) { GEN Mindex = MF_get_Mindex(mf), Minv = MF_get_Minv(mf); long j, l = lg(B), sb = mfsturm_mf(mf); GEN b = MF_get_basis(mf), Q = cgetg(l, t_VEC); for (j = 1; j < l; j++) { GEN v = hecke_i(sb, 1, gel(B,j), gel(b,j), DATA); /* Tn b[j] */ settyp(v,t_COL); gel(Q,j) = vecpermute(v, Mindex); } return Minv_RgM_mul(Minv,Q); } /* T_p^2, p prime, 1/2-integral weight; B = mfcoefs(mf,sb*p^2,1) or (mf,sb,p^2) * if p|N */ static GEN mfheckemat_mfcoefs_p2(GEN mf, long p, GEN B) { pari_sp av = avma; GEN DATA = heckef2_data(MF_get_N(mf), p*p); return gerepileupto(av, mfheckemat_mfcoefs(mf, B, DATA)); } /* convert Mindex from row-index to mfcoef indexation: a(n) is stored in * mfcoefs()[n+1], so subtract 1 from all indices */ static GEN Mindex_as_coef(GEN mf) { GEN v, Mindex = MF_get_Mindex(mf); long i, l = lg(Mindex); v = cgetg(l, t_VECSMALL); for (i = 1; i < l; i++) v[i] = Mindex[i]-1; return v; } /* T_p, p prime; B = mfcoefs(mf,sb*p,1) or (mf,sb,p) if p|N; integral weight */ static GEN mfheckemat_mfcoefs_p(GEN mf, long p, GEN B) { pari_sp av = avma; GEN vm, Q, C, Minv = MF_get_Minv(mf); long lm, k, i, j, l = lg(B), N = MF_get_N(mf); if (N % p == 0) return Minv_RgM_mul(Minv, rowpermute(B, MF_get_Mindex(mf))); k = MF_get_k(mf); C = gmul(mfchareval(MF_get_CHI(mf), p), powuu(p, k-1)); vm = Mindex_as_coef(mf); lm = lg(vm); Q = cgetg(l, t_MAT); for (j = 1; j < l; j++) gel(Q,j) = cgetg(lm, t_COL); for (i = 1; i < lm; i++) { long m = vm[i], mp = m*p; GEN Cm = (m % p) == 0? C : NULL; for (j = 1; j < l; j++) { GEN S = gel(B,j), s = gel(S, mp + 1); if (Cm) s = gadd(s, gmul(C, gel(S, m/p + 1))); gcoeff(Q, i, j) = s; } } return gerepileupto(av, Minv_RgM_mul(Minv,Q)); } /* Matrix of T(p), p prime, dim(mf) > 0 and integral weight */ static GEN mfheckemat_p(GEN mf, long p) { pari_sp av = avma; long N = MF_get_N(mf), sb = mfsturm_mf(mf); GEN B = (N % p)? mfcoefs_mf(mf, sb * p, 1): mfcoefs_mf(mf, sb, p); return gerepileupto(av, mfheckemat_mfcoefs(mf, B, hecke_data(N,p))); } /* mf_NEW != (0), weight > 1, p prime. Use * T(p) T(j) = T(j*p) + p^{k-1} \chi(p) 1_{p | j, p \nmid N} T(j/p) */ static GEN mfnewmathecke_p(GEN mf, long p) { pari_sp av = avma; GEN tf, vj = MFnew_get_vj(mf), CHI = MF_get_CHI(mf); GEN Mindex = MF_get_Mindex(mf), Minv = MF_get_Minv(mf); long N = MF_get_N(mf), k = MF_get_k(mf); long i, j, lvj = lg(vj), lim = vj[lvj-1] * p; GEN M, perm, V, need = zero_zv(lim); GEN C = (N % p)? gmul(mfchareval(CHI,p), powuu(p,k-1)): NULL; tf = mftraceform_new(N, k, CHI); for (i = 1; i < lvj; i++) { j = vj[i]; need[j*p] = 1; if (N % p && j % p == 0) need[j/p] = 1; } perm = zero_zv(lim); V = cgetg(lim+1, t_VEC); for (i = j = 1; i <= lim; i++) if (need[i]) { gel(V,j) = mfhecke_i(i, N, tf); perm[i] = j; j++; } setlg(V, j); V = bhnmat_extend_nocache(NULL, N, mfsturm_mf(mf), 1, V); V = rowpermute(V, Mindex); /* V[perm[i]] = coeffs(T_i newtrace) */ M = cgetg(lvj, t_MAT); for (i = 1; i < lvj; i++) { GEN t; j = vj[i]; t = gel(V, perm[j*p]); if (C && j % p == 0) t = RgC_add(t, RgC_Rg_mul(gel(V, perm[j/p]),C)); gel(M,i) = t; } return gerepileupto(av, Minv_RgM_mul(Minv, M)); } GEN mfheckemat(GEN mf, GEN vn) { pari_sp av = avma; long lv, lvP, i, N, dim, nk, dk, p, sb, flint = (typ(vn)==t_INT); GEN CHI, res, vT, FA, B, vP; mf = checkMF(mf); if (typ(vn) != t_VECSMALL) vn = gtovecsmall(vn); N = MF_get_N(mf); CHI = MF_get_CHI(mf); Qtoss(MF_get_gk(mf), &nk, &dk); dim = MF_get_dim(mf); lv = lg(vn); res = cgetg(lv, t_VEC); FA = cgetg(lv, t_VEC); vP = cgetg(lv, t_VEC); vT = const_vec(vecsmall_max(vn), NULL); for (i = 1; i < lv; i++) { ulong n = (ulong)labs(vn[i]); GEN fa; if (!n) pari_err_TYPE("mfheckemat", vn); if (dk == 1 || uissquareall(n, &n)) fa = myfactoru(n); else { n = 0; fa = myfactoru(1); } /* dummy: T_{vn[i]} = 0 */ vn[i] = n; gel(FA,i) = fa; gel(vP,i) = gel(fa,1); } vP = shallowconcat1(vP); vecsmall_sort(vP); vP = vecsmall_uniq_sorted(vP); /* all primes occurring in vn */ lvP = lg(vP); if (lvP == 1) goto END; p = vP[lvP-1]; sb = mfsturm_mf(mf); if (dk == 1 && nk != 1 && MF_get_space(mf) == mf_NEW) B = NULL; /* special purpose mfnewmathecke_p is faster */ else if (lvP == 2 && N % p == 0) B = mfcoefs_mf(mf, sb, dk==2? p*p: p); /* single prime | N, can optimize */ else B = mfcoefs_mf(mf, sb * (dk==2? p*p: p), 1); /* general initialization */ for (i = 1; i < lvP; i++) { long j, l, q, e = 1; GEN C, Tp, u1, u0; p = vP[i]; for (j = 1; j < lv; j++) e = maxss(e, z_lval(vn[j], p)); if (!B) Tp = mfnewmathecke_p(mf, p); else if (dk == 2) Tp = mfheckemat_mfcoefs_p2(mf,p, (lvP==2||N%p)? B: matdeflate(sb,p*p,B)); else Tp = mfheckemat_mfcoefs_p(mf, p, (lvP==2||N%p)? B: matdeflate(sb,p,B)); gel(vT, p) = Tp; if (e == 1) continue; u0 = gen_1; if (dk == 2) { C = N % p? gmul(mfchareval(CHI,p*p), powuu(p, nk-2)): NULL; if (e == 2) u0 = uutoQ(p+1,p); /* special case T_{p^4} */ } else C = N % p? gmul(mfchareval(CHI,p), powuu(p, nk-1)): NULL; for (u1=Tp, q=p, l=2; l <= e; l++) { /* u0 = T_{p^{l-2}}, u1 = T_{p^{l-1}} for l > 2 */ GEN v = gmul(Tp, u1); if (C) v = gsub(v, gmul(C, u0)); /* q = p^l, vT[q] = T_q for k integer else T_{q^2} */ q *= p; u0 = u1; gel(vT, q) = u1 = v; } } END: /* vT[p^e] = T_{p^e} for all p^e occurring below */ for (i = 1; i < lv; i++) { long n = vn[i], j, lP; GEN fa, P, E, M; if (n == 0) { gel(res,i) = zeromat(dim,dim); continue; } if (n == 1) { gel(res,i) = matid(dim); continue; } fa = gel(FA,i); P = gel(fa,1); lP = lg(P); E = gel(fa,2); M = gel(vT, upowuu(P[1], E[1])); for (j = 2; j < lP; j++) M = RgM_mul(M, gel(vT, upowuu(P[j], E[j]))); gel(res,i) = M; } if (flint) res = gel(res,1); return gerepilecopy(av, res); } /* f = \sum_i v[i] T_listj[i] (Trace Form) attached to v; replace by f/a_1(f) */ static GEN mf_normalize(GEN mf, GEN v) { GEN c, dc = NULL, M = MF_get_M(mf), Mindex = MF_get_Mindex(mf); v = Q_primpart(v); c = RgMrow_RgC_mul(M, v, 2); /* a_1(f) */ if (gequal1(c)) return v; if (typ(c) == t_POL) c = gmodulo(c, mfcharpol(MF_get_CHI(mf))); if (typ(c) == t_POLMOD && varn(gel(c,1)) == 1 && degpol(gel(c,1)) >= 40 && Mindex[1] == 2 && mfcharorder(MF_get_CHI(mf)) <= 2) { /* normalize using expansion at infinity (small coefficients) */ GEN w, P = gel(c,1), a1 = gel(c,2); long i, l = lg(Mindex); w = cgetg(l, t_COL); gel(w,1) = gen_1; for (i = 2; i < l; i++) { c = liftpol_shallow(RgMrow_RgC_mul(M, v, Mindex[i])); gel(w,i) = QXQ_div(c, a1, P); } /* w = expansion at oo of normalized form */ v = Minv_RgC_mul(MF_get_Minv(mf), Q_remove_denom(w, &dc)); v = gmodulo(v, P); /* back to mfbasis coefficients */ } else { c = ginv(c); if (typ(c) == t_POLMOD) c = Q_remove_denom(c, &dc); v = RgC_Rg_mul(v, c); } if (dc) v = RgC_Rg_div(v, dc); return v; } static void pol_red(GEN NF, GEN *pP, GEN *pa, long flag) { GEN dP, a, P = *pP; long d = degpol(P); *pa = a = pol_x(varn(P)); if (d * (NF ? nf_get_degree(NF): 1) > 30) return; dP = RgX_disc(P); if (typ(dP) != t_INT) { dP = gnorm(dP); if (typ(dP) != t_INT) pari_err_BUG("mfnewsplit"); } if (d == 2 || expi(dP) < 62) { if (expi(dP) < 31) P = NF? rnfpolredabs(NF, P,flag): polredabs0(P,flag); else P = NF? rnfpolredbest(NF,P,flag): polredbest(P,flag); if (flag) { a = gel(P,2); if (typ(a) == t_POLMOD) a = gel(a,2); P = gel(P,1); } } *pP = P; *pa = a; } /* Diagonalize and normalize. See mfsplit for meaning of flag. */ static GEN mfspclean(GEN mf, GEN mf0, GEN NF, long ord, GEN simplesp, long flag) { const long vz = 1; long i, l = lg(simplesp), dim = MF_get_dim(mf); GEN res = cgetg(l, t_MAT), pols = cgetg(l, t_VEC); GEN zeros = (mf == mf0)? NULL: zerocol(dim - MF_get_dim(mf0)); for (i = 1; i < l; i++) { GEN ATP = gel(simplesp, i), A = gel(ATP,1), P = gel(ATP,3); long d = degpol(P); GEN a, v = (flag && d > flag)? NULL: gel(A,1); if (d == 1) P = pol_x(vz); else { pol_red(NF, &P, &a, !!v); if (v) { /* Mod(a,P) root of charpoly(T), K*gpowers(a) = eigenvector of T */ GEN K, den, M = cgetg(d+1, t_MAT), T = gel(ATP,2); long j; T = shallowtrans(T); gel(M,1) = vec_ei(d,1); /* basis of cyclic vectors */ for (j = 2; j <= d; j++) gel(M,j) = RgM_RgC_mul(T, gel(M,j-1)); M = Q_primpart(M); K = NF? ZabM_inv(liftpol_shallow(M), nf_get_pol(NF), ord, &den) : ZM_inv(M,&den); K = shallowtrans(K); v = gequalX(a)? pol_x_powers(d, vz): RgXQ_powers(a, d-1, P); v = gmodulo(RgM_RgC_mul(A, RgM_RgC_mul(K,v)), P); } } if (v) { v = mf_normalize(mf0, v); if (zeros) v = shallowconcat(zeros,v); gel(res,i) = v; if (flag) setlg(res,i+1); } else gel(res,i) = zerocol(dim); gel(pols,i) = P; } return mkvec2(res, pols); } /* return v = v_{X-r}(P), and set Z = P / (X-r)^v */ static long RgX_valrem_root(GEN P, GEN r, GEN *Z) { long v; for (v = 0; degpol(P); v++) { GEN t, Q = RgX_div_by_X_x(P, r, &t); if (!gequal0(t)) break; P = Q; } *Z = P; return v; } static GEN mynffactor(GEN NF, GEN P, long dimlim) { long i, l, v; GEN R, E; if (dimlim != 1) { R = NF? nffactor(NF, P): QX_factor(P); if (!dimlim) return R; E = gel(R,2); R = gel(R,1); l = lg(R); for (i = 1; i < l; i++) if (degpol(gel(R,i)) > dimlim) break; if (i == 1) return NULL; setlg(E,i); setlg(R,i); return mkmat2(R, E); } /* dimlim = 1 */ R = nfroots(NF, P); l = lg(R); if (l == 1) return NULL; v = varn(P); settyp(R, t_COL); if (degpol(P) == l-1) E = const_col(l-1, gen_1); else { E = cgetg(l, t_COL); for (i = 1; i < l; i++) gel(E,i) = utoi(RgX_valrem_root(P, gel(R,i), &P)); } R = deg1_from_roots(R, v); return mkmat2(R, E); } /* Let K be a number field attached to NF (Q if NF = NULL). A K-vector * space of dimension d > 0 is given by a t_MAT A (n x d, full column rank) * giving a K-basis, X a section (d x n: left pseudo-inverse of A). Return a * pair (T, fa), where T is an element of the Hecke algebra (a sum of Tp taken * from vector vTp) acting on A (a d x d t_MAT) and fa is the factorization of * its characteristic polynomial, limited to factors of degree <= dimlim if * dimlim != 0 (return NULL if there are no factors of degree <= dimlim) */ static GEN findbestsplit(GEN NF, GEN vTp, GEN A, GEN X, long dimlim, long vz) { GEN T = NULL, Tkeep = NULL, fakeep = NULL; long lmax = 0, i, lT = lg(vTp); for (i = 1; i < lT; i++) { GEN D, P, E, fa, TpA = gel(vTp,i); long l; if (typ(TpA) == t_INT) break; if (lg(TpA) > lg(A)) TpA = RgM_mul(X, RgM_mul(TpA, A)); /* Tp | A */ T = T ? RgM_add(T, TpA) : TpA; if (!NF) { P = QM_charpoly_ZX(T); setvarn(P, vz); } else { P = charpoly(Q_remove_denom(T, &D), vz); if (D) P = gdiv(RgX_unscale(P, D), powiu(D, degpol(P))); } fa = mynffactor(NF, P, dimlim); if (!fa) return NULL; E = gel(fa, 2); /* characteristic polynomial is separable ? */ if (isint1(vecmax(E))) { Tkeep = T; fakeep = fa; break; } l = lg(E); /* characteristic polynomial has more factors than before ? */ if (l > lmax) { lmax = l; Tkeep = T; fakeep = fa; } } return mkvec2(Tkeep, fakeep); } static GEN nfcontent(GEN nf, GEN v) { long i, l = lg(v); GEN c = gel(v,1); for (i = 2; i < l; i++) c = idealadd(nf, c, gel(v,i)); if (typ(c) == t_MAT && gequal1(gcoeff(c,1,1))) c = gen_1; return c; } static GEN nf_primpart(GEN nf, GEN B) { switch(typ(B)) { case t_COL: { GEN A = matalgtobasis(nf, B), c = nfcontent(nf, A); if (typ(c) == t_INT) return B; c = idealred_elt(nf,c); A = Q_primpart( nfC_nf_mul(nf, A, Q_primpart(nfinv(nf,c))) ); A = liftpol_shallow( matbasistoalg(nf, A) ); if (gexpo(A) > gexpo(B)) A = B; return A; } case t_MAT: { long i, l; GEN A = cgetg_copy(B, &l); for (i = 1; i < l; i++) gel(A,i) = nf_primpart(nf, gel(B,i)); return A; } default: pari_err_TYPE("nf_primpart", B); return NULL; /*LCOV_EXCL_LINE*/ } } /* rotate entries of v to accomodate new entry 'x' (push out oldest entry) */ static void vecpush(GEN v, GEN x) { long i; for (i = lg(v)-1; i > 1; i--) gel(v,i) = gel(v,i-1); gel(v,1) = x; } /* sort t_VEC of vector spaces by increasing dimension */ static GEN sort_by_dim(GEN v) { long i, l = lg(v); GEN D = cgetg(l, t_VECSMALL); for (i = 1; i < l; i++) D[i] = lg(gmael(v,i,2)); return vecpermute(v , vecsmall_indexsort(D)); } static GEN split_starting_space(GEN mf) { long d = MF_get_dim(mf), d2; GEN id = matid(d); switch(MF_get_space(mf)) { case mf_NEW: case mf_CUSP: return mkvec2(id, id); } d2 = lg(MF_get_S(mf))-1; return mkvec2(vecslice(id, d-d2+1,d), shallowconcat(zeromat(d2,d-d2),matid(d2))); } /* If dimlim > 0, keep only the dimension <= dimlim eigenspaces. * See mfsplit for the meaning of flag. */ static GEN split_ii(GEN mf, long dimlim, long flag, GEN vSP, long *pnewd) { forprime_t iter; GEN CHI = MF_get_CHI(mf), empty = cgetg(1, t_VEC), mf0 = mf; GEN NF, POLCYC, todosp, Tpbigvec, simplesp; long N = MF_get_N(mf), k = MF_get_k(mf); long ord, FC, NEWT, dimsimple = 0, newd = -1; const long NBH = 5, vz = 1; ulong p; switch(MF_get_space(mf)) { case mf_NEW: break; case mf_CUSP: case mf_FULL: { GEN CHIP; if (k > 1) { mf0 = mfinittonew(mf); break; } CHIP = mfchartoprimitive(CHI, NULL); newd = lg(MF_get_S(mf))-1 - mfolddim_i(N, k, CHIP, vSP); break; } default: pari_err_TYPE("mfsplit [space does not contain newspace]", mf); return NULL; /*LCOV_EXCL_LINE*/ } if (newd < 0) newd = mf0? MF_get_dim(mf0): 0; *pnewd = newd; if (!newd) return mkvec2(cgetg(1, t_MAT), empty); NEWT = (k > 1 && MF_get_space(mf0) == mf_NEW); todosp = mkvec( split_starting_space(mf0) ); simplesp = empty; FC = mfcharconductor(CHI); ord = mfcharorder(CHI); if (ord <= 2) NF = POLCYC = NULL; else { POLCYC = mfcharpol(CHI); NF = nfinit(POLCYC,DEFAULTPREC); } Tpbigvec = zerovec(NBH); u_forprime_init(&iter, 2, ULONG_MAX); while (dimsimple < newd && (p = u_forprime_next(&iter))) { GEN nextsp; long ind; if (N % (p*p) == 0 && N/p % FC == 0) continue; /* T_p = 0 in this case */ vecpush(Tpbigvec, NEWT? mfnewmathecke_p(mf0,p): mfheckemat_p(mf0,p)); nextsp = empty; for (ind = 1; ind < lg(todosp); ind++) { GEN tmp = gel(todosp, ind), fa, P, E, D, Tp, DTp; GEN A = gel(tmp, 1); GEN X = gel(tmp, 2); long lP, i; tmp = findbestsplit(NF, Tpbigvec, A, X, dimlim, vz); if (!tmp) continue; /* nothing there */ Tp = gel(tmp, 1); fa = gel(tmp, 2); P = gel(fa, 1); E = gel(fa, 2); lP = lg(P); /* lP > 1 */ if (DEBUGLEVEL) err_printf("Exponents = %Ps\n", E); if (lP == 2) { GEN P1 = gel(P,1); long e1 = itos(gel(E,1)), d1 = degpol(P1); if (e1 * d1 == lg(Tp)-1) { if (e1 > 1) nextsp = vec_append(nextsp, mkvec2(A,X)); else { /* simple module */ simplesp = vec_append(simplesp, mkvec3(A,Tp,P1)); if ((dimsimple += d1) == newd) goto END; } continue; } } /* Found splitting */ DTp = Q_remove_denom(Tp, &D); for (i = 1; i < lP; i++) { GEN Ai, Xi, dXi, AAi, v, y, Pi = gel(P,i); Ai = RgX_RgM_eval(D? RgX_rescale(Pi,D): Pi, DTp); Ai = QabM_ker(Ai, POLCYC, ord); if (NF) Ai = nf_primpart(NF, Ai); AAi = RgM_mul(A, Ai); /* gives section, works on nonsquare matrices */ Xi = QabM_pseudoinv(Ai, POLCYC, ord, &v, &dXi); Xi = RgM_Rg_div(Xi, dXi); y = gel(v,1); if (isint1(gel(E,i))) { GEN Tpi = RgM_mul(Xi, RgM_mul(rowpermute(Tp,y), Ai)); simplesp = vec_append(simplesp, mkvec3(AAi, Tpi, Pi)); if ((dimsimple += degpol(Pi)) == newd) goto END; } else { Xi = RgM_mul(Xi, rowpermute(X,y)); nextsp = vec_append(nextsp, mkvec2(AAi, Xi)); } } } todosp = nextsp; if (lg(todosp) == 1) break; } END: if (DEBUGLEVEL) err_printf("end split, need to clean\n"); return mfspclean(mf, mf0, NF, ord, sort_by_dim(simplesp), flag); } static GEN dim_filter(GEN v, long dim) { GEN P = gel(v,2); long j, l = lg(P); for (j = 1; j < l; j++) if (degpol(gel(P,j)) > dim) { v = mkvec2(vecslice(gel(v,1),1,j-1), vecslice(P,1,j-1)); break; } return v; } static long dim_sum(GEN v) { GEN P = gel(v,2); long j, l = lg(P), d = 0; for (j = 1; j < l; j++) d += degpol(gel(P,j)); return d; } static GEN split_i(GEN mf, long dimlim, long flag) { long junk; return split_ii(mf, dimlim, flag, NULL, &junk); } /* mf is either already split or output by mfinit. Splitting is done only for * newspace except in weight 1. If flag = 0 (default) split completely. * If flag = d > 0, only give the Galois polynomials in degree > d * Flag is ignored if dimlim = 1. */ GEN mfsplit(GEN mf0, long dimlim, long flag) { pari_sp av = avma; GEN v, mf = checkMF_i(mf0); if (!mf) pari_err_TYPE("mfsplit", mf0); if ((v = obj_check(mf, MF_SPLIT))) { if (dimlim) v = dim_filter(v, dimlim); } else if (dimlim && (v = obj_check(mf, MF_SPLITN))) { v = (itos(gel(v,1)) >= dimlim)? dim_filter(gel(v,2), dimlim): NULL; } if (!v) { long newd; v = split_ii(mf, dimlim, flag, NULL, &newd); if (lg(v) == 1) obj_insert(mf, MF_SPLITN, mkvec2(utoi(dimlim), v)); else if (!flag) { if (dim_sum(v) == newd) obj_insert(mf, MF_SPLIT,v); else obj_insert(mf, MF_SPLITN, mkvec2(utoi(dimlim), v)); } } return gerepilecopy(av, v); } static GEN split(GEN mf) { return split_i(mf,0,0); } GEN MF_get_newforms(GEN mf) { return gel(obj_checkbuild(mf,MF_SPLIT,&split),1); } GEN MF_get_fields(GEN mf) { return gel(obj_checkbuild(mf,MF_SPLIT,&split),2); } /*************************************************************************/ /* Modular forms of Weight 1 */ /*************************************************************************/ /* S_1(G_0(N)), small N. Return 1 if definitely empty; return 0 if maybe * nonempty */ static int wt1empty(long N) { if (N <= 100) switch (N) { /* nonempty [32/100] */ case 23: case 31: case 39: case 44: case 46: case 47: case 52: case 55: case 56: case 57: case 59: case 62: case 63: case 68: case 69: case 71: case 72: case 76: case 77: case 78: case 79: case 80: case 83: case 84: case 87: case 88: case 92: case 93: case 94: case 95: case 99: case 100: return 0; default: return 1; } if (N <= 600) switch(N) { /* empty [111/500] */ case 101: case 102: case 105: case 106: case 109: case 113: case 121: case 122: case 123: case 125: case 130: case 134: case 137: case 146: case 149: case 150: case 153: case 157: case 162: case 163: case 169: case 170: case 173: case 178: case 181: case 182: case 185: case 187: case 193: case 194: case 197: case 202: case 205: case 210: case 218: case 221: case 226: case 233: case 241: case 242: case 245: case 246: case 250: case 257: case 265: case 267: case 269: case 274: case 277: case 281: case 289: case 293: case 298: case 305: case 306: case 313: case 314: case 317: case 326: case 337: case 338: case 346: case 349: case 353: case 361: case 362: case 365: case 369: case 370: case 373: case 374: case 377: case 386: case 389: case 394: case 397: case 401: case 409: case 410: case 421: case 425: case 427: case 433: case 442: case 449: case 457: case 461: case 466: case 481: case 482: case 485: case 490: case 493: case 509: case 514: case 521: case 530: case 533: case 534: case 538: case 541: case 545: case 554: case 557: case 562: case 565: case 569: case 577: case 578: case 586: case 593: return 1; default: return 0; } return 0; } static GEN initwt1trace(GEN mf) { GEN S = MF_get_S(mf), v, H; long l, i; if (lg(S) == 1) return mftrivial(); H = mfheckemat(mf, Mindex_as_coef(mf)); l = lg(H); v = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(v,i) = gtrace(gel(H,i)); v = Minv_RgC_mul(MF_get_Minv(mf), v); return mflineardiv_linear(S, v, 1); } static GEN initwt1newtrace(GEN mf) { GEN v, D, S, Mindex, CHI = MF_get_CHI(mf); long FC, lD, i, sb, N1, N2, lM, N = MF_get_N(mf); CHI = mfchartoprimitive(CHI, &FC); if (N % FC || mfcharparity(CHI) == 1) return mftrivial(); D = mydivisorsu(N/FC); lD = lg(D); S = MF_get_S(mf); if (lg(S) == 1) return mftrivial(); N2 = newd_params2(N); N1 = N / N2; Mindex = MF_get_Mindex(mf); lM = lg(Mindex); sb = Mindex[lM-1]; v = zerovec(sb+1); for (i = 1; i < lD; i++) { long M = FC*D[i], j; GEN tf = initwt1trace(M == N? mf: mfinit_Nkchi(M, 1, CHI, mf_CUSP, 0)); GEN listd, w; if (mf_get_type(tf) == t_MF_CONST) continue; w = mfcoefs_i(tf, sb, 1); if (M == N) { v = gadd(v, w); continue; } listd = mydivisorsu(u_ppo(ugcd(N/M, N1), FC)); for (j = 1; j < lg(listd); j++) { long d = listd[j], d2 = d*d; /* coprime to FC */ GEN dk = mfchareval(CHI, d); long NMd = N/(M*d), m; for (m = 1; m <= sb/d2; m++) { long be = mubeta2(NMd, m); if (be) { GEN c = gmul(dk, gmulsg(be, gel(w, m+1))); long n = m*d2; gel(v, n+1) = gadd(gel(v, n+1), c); } } } } if (gequal0(gel(v,2))) return mftrivial(); v = vecpermute(v,Mindex); v = Minv_RgC_mul(MF_get_Minv(mf), v); return mflineardiv_linear(S, v, 1); } /* i*p + 1, i*p < lim corresponding to a_p(f_j), a_{2p}(f_j)... */ static GEN pindices(long p, long lim) { GEN v = cgetg(lim, t_VECSMALL); long i, ip; for (i = 1, ip = p + 1; ip < lim; i++, ip += p) v[i] = ip; setlg(v, i); return v; } /* assume !wt1empty(N), in particular N>25 */ /* Returns [[lim,p], mf (weight 2), p*lim x dim matrix] */ static GEN mf1_pre(long N) { pari_timer tt; GEN mf, v, L, I, M, Minv, den; long B, lim, LIM, p; if (DEBUGLEVEL) timer_start(&tt); mf = mfinit_Nkchi(N, 2, mfchartrivial(), mf_CUSP, 0); if (DEBUGLEVEL) timer_printf(&tt, "mf1basis [pre]: S_2(%ld), dim = %ld", N, MF_get_dim(mf)); M = MF_get_M(mf); Minv = MF_get_Minv(mf); den = gel(Minv,2); B = mfsturm_mf(mf); if (uisprime(N)) { lim = 2 * MF_get_dim(mf); /* ensure mfstabiter's first kernel ~ square */ p = 2; } else { forprime_t S; u_forprime_init(&S, 2, N); while ((p = u_forprime_next(&S))) if (N % p) break; lim = B + 1; } LIM = (N & (N - 1))? 2 * lim: 3 * lim; /* N power of 2 ? */ L = mkvecsmall4(lim, LIM, mfsturmNk(N,1), p); M = bhnmat_extend_nocache(M, N, LIM-1, 1, MF_get_S(mf)); if (DEBUGLEVEL) timer_printf(&tt, "mf1basis [pre]: bnfmat_extend"); v = pindices(p, LIM); if (!LIM) return mkvec4(L, mf, M, v); I = RgM_Rg_div(ZM_mul(rowslice(M, B+2, LIM), gel(Minv,1)), den); I = Q_remove_denom(I, &den); if (DEBUGLEVEL) timer_printf(&tt, "mf1basis [prec]: Iden"); return mkvec5(L, mf, M, v, mkvec2(I, den)); } /* lg(A) > 1, E a t_POL */ static GEN mfmatsermul(GEN A, GEN E) { long j, l = lg(A), r = nbrows(A); GEN M = cgetg(l, t_MAT); E = RgXn_red_shallow(E, r+1); for (j = 1; j < l; j++) { GEN c = RgV_to_RgX(gel(A,j), 0); gel(M, j) = RgX_to_RgC(RgXn_mul(c, E, r+1), r); } return M; } /* lg(Ap) > 1, Ep an Flxn */ static GEN mfmatsermul_Fl(GEN Ap, GEN Ep, ulong p) { long j, l = lg(Ap), r = nbrows(Ap); GEN M = cgetg(l, t_MAT); for (j = 1; j < l; j++) { GEN c = Flv_to_Flx(gel(Ap,j), 0); gel(M,j) = Flx_to_Flv(Flxn_mul(c, Ep, r+1, p), r); } return M; } /* CHI mod F | N, return mfchar of modulus N. * FIXME: wasteful, G should be precomputed */ static GEN mfcharinduce(GEN CHI, long N) { GEN G, chi; if (mfcharmodulus(CHI) == N) return CHI; G = znstar0(utoipos(N), 1); chi = zncharinduce(gel(CHI,1), gel(CHI,2), G); CHI = leafcopy(CHI); gel(CHI,1) = G; gel(CHI,2) = chi; return CHI; } static GEN gmfcharno(GEN CHI) { GEN G = gel(CHI,1), chi = gel(CHI,2); return mkintmod(znconreyexp(G, chi), znstar_get_N(G)); } static long mfcharno(GEN CHI) { GEN n = znconreyexp(gel(CHI,1), gel(CHI,2)); return itou(n); } /* return k such that minimal mfcharacter in Galois orbit of CHI is CHI^k */ static long mfconreyminimize(GEN CHI) { GEN G = gel(CHI,1), cyc, chi; cyc = ZV_to_zv(znstar_get_cyc(G)); chi = ZV_to_zv(znconreychar(G, gel(CHI,2))); return zv_cyc_minimize(cyc, chi, coprimes_zv(mfcharorder(CHI))); } /* find scalar c such that first nonzero entry of c*v is 1; return c*v */ static GEN RgV_normalize(GEN v, GEN *pc) { long i, l = lg(v); for (i = 1; i < l; i++) { GEN c = gel(v,i); if (!gequal0(c)) { if (gequal1(c)) break; *pc = ginv(c); return RgV_Rg_mul(v, *pc); } } *pc = gen_1; return v; } /* pS != NULL; dim > 0 */ static GEN mftreatdihedral(long N, GEN DIH, GEN POLCYC, long ordchi, GEN *pS) { long l = lg(DIH), lim = mfsturmNk(N, 1), i; GEN Minv, C = cgetg(l, t_VEC), M = cgetg(l, t_MAT); for (i = 1; i < l; i++) { GEN c, v = mfcoefs_i(gel(DIH,i), lim, 1); gel(M,i) = RgV_normalize(v, &c); gel(C,i) = Rg_col_ei(c, l-1, i); } Minv = gel(mfclean(M,POLCYC,ordchi,0),2); M = RgM_Minv_mul(M, Minv); C = RgM_Minv_mul(C, Minv); *pS = vecmflinear(DIH, C); return M; } /* same mode a maximal ideal above q */ static GEN Tpmod(GEN Ap, GEN A, ulong chip, long p, ulong q) { GEN B = leafcopy(Ap); long i, ip, l = lg(B); for (i = 1, ip = p; ip < l; i++, ip += p) B[ip] = Fl_add(B[ip], Fl_mul(A[i], chip, q), q); return B; } /* Tp(f_1), ..., Tp(f_d) mod q */ static GEN matTpmod(GEN Ap, GEN A, ulong chip, long p, ulong q) { long i, l; GEN B = cgetg_copy(A, &l); for (i = 1; i < l; i++) gel(B,i) = Tpmod(gel(Ap,i), gel(A,i), chip, p, q); return B; } /* Ap[i] = a_{p*i}(F), A[i] = a_i(F), i = 1..lim * Tp(f)[n] = a_{p*n}(f) + chi(p) a_{n/p}(f) * 1_{p | n} */ static GEN Tp(GEN Ap, GEN A, GEN chip, long p) { GEN B = leafcopy(Ap); long i, ip, l = lg(B); for (i = 1, ip = p; ip < l; i++, ip += p) gel(B,ip) = gadd(gel(B,ip), gmul(gel(A,i), chip)); return B; } /* Tp(f_1), ..., Tp(f_d) mod q */ static GEN matTp(GEN Ap, GEN A, GEN chip, long p) { long i, l; GEN B = cgetg_copy(A, &l); for (i = 1; i < l; i++) gel(B,i) = Tp(gel(Ap,i), gel(A,i), chip, p); return B; } static GEN _RgXQM_mul(GEN x, GEN y, GEN T) { return T? RgXQM_mul(x, y, T): RgM_mul(x, y); } /* largest T-stable Q(CHI)-subspace of Q(CHI)-vector space spanned by columns * of A */ static GEN mfstabiter(GEN *pC, GEN A0, GEN chip, GEN TMP, GEN P, long ordchi) { GEN A, Ap, vp = gel(TMP,4), C = NULL; long i, lA, lim1 = gel(TMP,1)[3], p = gel(TMP,1)[4]; pari_timer tt; Ap = rowpermute(A0, vp); A = rowslice(A0, 2, nbrows(Ap)+1); /* remove a0 */ for(;;) { GEN R = shallowconcat(matTp(Ap, A, chip, p), A); GEN B = QabM_ker(R, P, ordchi); long lB = lg(B); if (DEBUGLEVEL) timer_printf(&tt, "mf1basis: Hecke intersection (dim %ld)", lB-1); if (lB == 1) return NULL; lA = lg(A); if (lB == lA) break; B = rowslice(B, 1, lA-1); Ap = _RgXQM_mul(Ap, B, P); A = _RgXQM_mul(A, B, P); C = C? _RgXQM_mul(C, B, P): B; } if (nbrows(A) < lim1) { A0 = rowslice(A0, 2, lim1); A = C? _RgXQM_mul(A0, C, P): A0; } else /* all needed coefs computed */ A = rowslice(A, 1, lim1-1); if (*pC) C = C? _RgXQM_mul(*pC, C, P): *pC; /* put back a0 */ for (i = 1; i < lA; i++) gel(A,i) = vec_prepend(gel(A,i), gen_0); *pC = C; return A; } static long mfstabitermod(GEN A, GEN vp, ulong chip, long p, ulong q) { GEN Ap, C = NULL; Ap = rowpermute(A, vp); A = rowslice(A, 2, nbrows(Ap)+1); while (1) { GEN Rp = shallowconcat(matTpmod(Ap, A, chip, p, q), A); GEN B = Flm_ker(Rp, q); long lA = lg(A), lB = lg(B); if (lB == 1) return 0; if (lB == lA) return lA-1; B = rowslice(B, 1, lA-1); Ap = Flm_mul(Ap, B, q); A = Flm_mul(A, B, q); C = C? Flm_mul(C, B, q): B; } } static GEN mfcharinv_i(GEN CHI) { GEN G = gel(CHI,1); CHI = leafcopy(CHI); gel(CHI,2) = zncharconj(G, gel(CHI,2)); return CHI; } /* upper bound dim S_1(Gamma_0(N),chi) performing the linear algebra mod p */ static long mf1dimmod(GEN E1, GEN E, GEN chip, long ordchi, long dih, GEN TMP) { GEN E1i, A, vp, mf, C = NULL; ulong q, r = QabM_init(ordchi, &q); long lim, LIM, p; LIM = gel(TMP,1)[2]; lim = gel(TMP,1)[1]; mf= gel(TMP,2); A = gel(TMP,3); A = QabM_to_Flm(A, r, q); E1 = QabX_to_Flx(E1, r, q); E1i = Flxn_inv(E1, nbrows(A), q); if (E) { GEN Iden = gel(TMP,5), I = gel(Iden,1), den = gel(Iden,2); GEN Mindex = MF_get_Mindex(mf), F = rowslice(A, 1, LIM); GEN E1ip = Flxn_red(E1i, LIM); ulong d = den? umodiu(den, q): 1; long i, nE = lg(E) - 1; pari_sp av; I = ZM_to_Flm(I, q); if (d != 1) I = Flm_Fl_mul(I, Fl_inv(d, q), q); av = avma; for (i = 1; i <= nE; i++) { GEN e = Flxn_mul(E1ip, QabX_to_Flx(gel(E,i), r, q), LIM, q); GEN B = mfmatsermul_Fl(F, e, q), z; GEN B2 = Flm_mul(I, rowpermute(B, Mindex), q); B = rowslice(B, lim+1,LIM); z = Flm_ker(Flm_sub(B2, B, q), q); if (lg(z)-1 == dih) return dih; C = C? Flm_mul(C, z, q): z; F = Flm_mul(F, z, q); gerepileall(av, 2, &F,&C); } A = F; } /* use Schaeffer */ p = gel(TMP,1)[4]; vp = gel(TMP,4); A = mfmatsermul_Fl(A, E1i, q); return mfstabitermod(A, vp, Qab_to_Fl(chip, r, q), p, q); } static GEN mf1intermat(GEN A, GEN Mindex, GEN e, GEN Iden, long lim, GEN POLCYC) { long j, l = lg(A), LIM = nbrows(A); GEN I = gel(Iden,1), den = gel(Iden,2), B = cgetg(l, t_MAT); for (j = 1; j < l; j++) { pari_sp av = avma; GEN c = RgV_to_RgX(gel(A,j), 0), c1, c2; c = RgX_to_RgC(RgXn_mul(c, e, LIM), LIM); if (POLCYC) c = liftpol_shallow(c); c1 = vecslice(c, lim+1, LIM); if (den) c1 = RgC_Rg_mul(c1, den); c2 = RgM_RgC_mul(I, vecpermute(c, Mindex)); gel(B, j) = gerepileupto(av, RgC_sub(c2, c1)); } return B; } /* Compute the full S_1(\G_0(N),\chi); return NULL if space is empty; else * if pS is NULL, return stoi(dim), where dim is the dimension; else *pS is * set to a vector of forms making up a basis, and return the matrix of their * Fourier expansions. pdih gives the dimension of the subspace generated by * dihedral forms; TMP is from mf1_pre or NULL. */ static GEN mf1basis(long N, GEN CHI, GEN TMP, GEN vSP, GEN *pS, long *pdih) { GEN E = NULL, EB, E1, E1i, dE1i, mf, A, C, POLCYC, DIH, Minv, chip; long nE = 0, p, LIM, lim, lim1, i, lA, dimp, ordchi, dih; pari_timer tt; pari_sp av; if (pdih) *pdih = 0; if (pS) *pS = NULL; if (wt1empty(N) || mfcharparity(CHI) != -1) return NULL; ordchi = mfcharorder(CHI); if (uisprime(N) && ordchi > 4) return NULL; if (pS) { DIH = mfdihedralcusp(N, CHI, vSP); dih = lg(DIH) - 1; } else { DIH = NULL; dih = mfdihedralcuspdim(N, CHI, vSP); } POLCYC = (ordchi <= 2)? NULL: mfcharpol(CHI); if (pdih) *pdih = dih; if (N <= 600) switch(N) { long m; case 219: case 273: case 283: case 331: case 333: case 344: case 416: case 438: case 468: case 491: case 504: case 546: case 553: case 563: case 566: case 581: case 592: break; /* one chi with both exotic and dihedral forms */ default: /* only dihedral forms */ if (!dih) return NULL; /* fall through */ case 124: case 133: case 148: case 171: case 201: case 209: case 224: case 229: case 248: case 261: case 266: case 288: case 296: case 301: case 309: case 325: case 342: case 371: case 372: case 380: case 399: case 402: case 403: case 404: case 408: case 418: case 432: case 444: case 448: case 451: case 453: case 458: case 496: case 497: case 513: case 522: case 527: case 532: case 576: case 579: /* no chi with both exotic and dihedral; one chi with exotic forms */ if (dih) { if (!pS) return utoipos(dih); return mftreatdihedral(N, DIH, POLCYC, ordchi, pS) ; } m = mfcharno(mfcharinduce(CHI,N)); if (N == 124 && (m != 67 && m != 87)) return NULL; if (N == 133 && (m != 83 && m !=125)) return NULL; if (N == 148 && (m !=105 && m !=117)) return NULL; if (N == 171 && (m != 94 && m !=151)) return NULL; if (N == 201 && (m != 29 && m !=104)) return NULL; if (N == 209 && (m != 87 && m !=197)) return NULL; if (N == 224 && (m != 95 && m !=191)) return NULL; if (N == 229 && (m !=107 && m !=122)) return NULL; if (N == 248 && (m != 87 && m !=191)) return NULL; if (N == 261 && (m != 46 && m !=244)) return NULL; if (N == 266 && (m != 83 && m !=125)) return NULL; if (N == 288 && (m != 31 && m !=223)) return NULL; if (N == 296 && (m !=105 && m !=265)) return NULL; } if (DEBUGLEVEL) err_printf("mf1basis: start character %Ps, conductor = %ld, order = %ld\n", gmfcharno(CHI), mfcharconductor(CHI), ordchi); if (!TMP) TMP = mf1_pre(N); lim = gel(TMP,1)[1]; LIM = gel(TMP,1)[2]; lim1 = gel(TMP,1)[3]; p = gel(TMP,1)[4]; mf = gel(TMP,2); A = gel(TMP,3); EB = mfeisensteinbasis(N, 1, mfcharinv_i(CHI)); nE = lg(EB) - 1; E1 = RgV_to_RgX(mftocol(gel(EB,1), LIM-1, 1), 0); /* + O(x^LIM) */ if (--nE) E = RgM_to_RgXV(mfvectomat(vecslice(EB, 2, nE+1), LIM-1, 1), 0); chip = mfchareval(CHI, p); /* != 0 */ if (DEBUGLEVEL) timer_start(&tt); av = avma; dimp = mf1dimmod(E1, E, chip, ordchi, dih, TMP); set_avma(av); if (DEBUGLEVEL) timer_printf(&tt, "mf1basis: dim mod p is %ld", dimp); if (!dimp) return NULL; if (!pS) return utoi(dimp); if (dimp == dih) return mftreatdihedral(N, DIH, POLCYC, ordchi, pS); E1i = RgXn_inv(E1, LIM); /* E[1] does not vanish at oo */ if (POLCYC) E1i = liftpol_shallow(E1i); E1i = Q_remove_denom(E1i, &dE1i); if (DEBUGLEVEL) { GEN a0 = gel(E1,2); if (typ(a0) == t_POLMOD) a0 = gnorm(a0); a0 = Q_abs_shallow(a0); timer_printf(&tt, "mf1basis: invert E; norm(a0(E)) = %Ps", a0); } C = NULL; if (nE) { /* mf attached to S2(N), fi = mfbasis(mf) * M = coefs(f1,...,fd) up to LIM * F = coefs(F1,...,FD) = M * C, for some matrix C over Q(chi), * initially 1, eventually giving \cap_E S2 / E; D <= d. * B = coefs(E/E1 F1, .., E/E1 FD); we want X in Q(CHI)^d and * Y in Q(CHI)^D such that * B * X = M * Y, i.e. Minv * rowpermute(B, Mindex * X) = Y *(B - I * rowpermute(B, Mindex)) * X = 0. * where I = M * Minv. Rows of (B - I * ...) are 0 up to lim so * are not included */ GEN Mindex = MF_get_Mindex(mf), Iden = gel(TMP,5); pari_timer TT; pari_sp av = avma; if (DEBUGLEVEL) timer_start(&TT); for (i = 1; i <= nE; i++) { pari_sp av2 = avma; GEN e, z, B; e = Q_primpart(RgXn_mul(E1i, gel(E,i), LIM)); if (DEBUGLEVEL) timer_printf(&TT, "mf1basis: E[%ld] / E[1]", i+1); /* the first time A is over Z and it is more efficient to lift than * to let RgXn_mul use Kronecker's trick */ if (POLCYC && i == 1) e = liftpol_shallow(e); B = mf1intermat(A, Mindex, e, Iden, lim, i == 1? NULL: POLCYC); if (DEBUGLEVEL) timer_printf(&TT, "mf1basis: ... intermat"); z = gerepileupto(av2, QabM_ker(B, POLCYC, ordchi)); if (DEBUGLEVEL) timer_printf(&TT, "mf1basis: ... kernel (dim %ld)",lg(z)-1); if (lg(z) == 1) return NULL; if (lg(z) == lg(A)) { set_avma(av2); continue; } /* no progress */ C = C? _RgXQM_mul(C, z, POLCYC): z; A = _RgXQM_mul(A, z, POLCYC); if (DEBUGLEVEL) timer_printf(&TT, "mf1basis: ... updates"); if (lg(z)-1 == dimp) break; if (gc_needed(av, 1)) { if (DEBUGMEM > 1) pari_warn(warnmem,"mf1basis i = %ld", i); gerepileall(av, 2, &A, &C); } } if (DEBUGLEVEL) timer_printf(&tt, "mf1basis: intersection [total]"); } lA = lg(A); if (lA-1 == dimp) { A = mfmatsermul(rowslice(A, 1, lim1), E1i); if (POLCYC) A = RgXQM_red(A, POLCYC); if (DEBUGLEVEL) timer_printf(&tt, "mf1basis: matsermul [1]"); } else { A = mfmatsermul(A, E1i); if (POLCYC) A = RgXQM_red(A, POLCYC); if (DEBUGLEVEL) timer_printf(&tt, "mf1basis: matsermul [2]"); A = mfstabiter(&C, A, chip, TMP, POLCYC, ordchi); if (DEBUGLEVEL) timer_printf(&tt, "mf1basis: Hecke stability"); if (!A) return NULL; } if (dE1i) C = RgM_Rg_mul(C, dE1i); if (POLCYC) { A = QXQM_to_mod_shallow(A, POLCYC); C = QXQM_to_mod_shallow(C, POLCYC); } lA = lg(A); for (i = 1; i < lA; i++) { GEN c, v = gel(A,i); gel(A,i) = RgV_normalize(v, &c); gel(C,i) = RgC_Rg_mul(gel(C,i), c); } Minv = gel(mfclean(A, POLCYC, ordchi, 0), 2); A = RgM_Minv_mul(A, Minv); C = RgM_Minv_mul(C, Minv); *pS = vecmflineardiv0(MF_get_S(mf), C, gel(EB,1)); return A; } static void MF_set_space(GEN mf, long x) { gmael(mf,1,4) = utoi(x); } static GEN mf1_cusptonew(GEN mf, GEN vSP) { const long vy = 1; long i, lP, dSnew, ct; GEN vP, F, S, Snew, vF, v = split_ii(mf, 0, 0, vSP, &i); F = gel(v,1); vP= gel(v,2); lP = lg(vP); if (lP == 1) { obj_insert(mf, MF_SPLIT, v); return NULL; } MF_set_space(mf, mf_NEW); S = MF_get_S(mf); dSnew = dim_sum(v); Snew = cgetg(dSnew + 1, t_VEC); ct = 0; vF = cgetg(lP, t_MAT); for (i = 1; i < lP; i++) { GEN V, P = gel(vP,i), f = liftpol_shallow(gel(F,i)); long j, d = degpol(P); gel(vF,i) = V = zerocol(dSnew); if (d == 1) { gel(Snew, ct+1) = mflineardiv_linear(S, f, 0); gel(V, ct+1) = gen_1; } else { f = RgXV_to_RgM(f,d); for (j = 1; j <= d; j++) { gel(Snew, ct+j) = mflineardiv_linear(S, row(f,j), 0); gel(V, ct+j) = mkpolmod(pol_xn(j-1,vy), P); } } ct += d; } obj_insert(mf, MF_SPLIT, mkvec2(vF, vP)); gel(mf,3) = Snew; return mf; } static GEN mf1init(long N, GEN CHI, GEN TMP, GEN vSP, long space, long flraw) { GEN mf, mf1, S, M = mf1basis(N, CHI, TMP, vSP, &S, NULL); if (!M) return NULL; mf1 = mkvec4(stoi(N), gen_1, CHI, utoi(mf_CUSP)); mf = mkmf(mf1, cgetg(1,t_VEC), S, gen_0, NULL); if (space == mf_NEW) { gel(mf,5) = mfcleanCHI(M,CHI, 0); mf = mf1_cusptonew(mf, vSP); if (!mf) return NULL; if (!flraw) M = mfcoefs_mf(mf, mfsturmNk(N,1)+1, 1); } gel(mf,5) = flraw? zerovec(3): mfcleanCHI(M, CHI, 0); return mf; } static GEN mfEMPTY(GEN mf1) { GEN Minv = mkMinv(cgetg(1,t_MAT), NULL,NULL,NULL); GEN M = mkvec3(cgetg(1,t_VECSMALL), Minv, cgetg(1,t_MAT)); return mkmf(mf1, cgetg(1,t_VEC), cgetg(1,t_VEC), cgetg(1,t_VEC), M); } static GEN mfEMPTYall(long N, GEN gk, GEN vCHI, long space) { long i, l; GEN v, gN, gs; if (!vCHI) return cgetg(1, t_VEC); gN = utoipos(N); gs = utoi(space); l = lg(vCHI); v = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(v,i) = mfEMPTY(mkvec4(gN,gk,gel(vCHI,i),gs)); return v; } static GEN fmt_dim(GEN CHI, long d, long dih) { return mkvec4(gmfcharorder(CHI), gmfcharno(CHI), utoi(d), stoi(dih)); } /* merge two vector of fmt_dim's for the same vector of characters. If CHI * is not NULL, remove dim-0 spaces and add character from CHI */ static GEN merge_dims(GEN V, GEN W, GEN CHI) { long i, j, id, l = lg(V); GEN A = cgetg(l, t_VEC); if (l == 1) return A; id = CHI? 1: 3; for (i = j = 1; i < l; i++) { GEN v = gel(V,i), w = gel(W,i); long dv = itou(gel(v,id)), dvh = itou(gel(v,id+1)), d; long dw = itou(gel(w,id)), dwh = itou(gel(w,id+1)); d = dv + dw; if (d || CHI) gel(A,j++) = CHI? fmt_dim(gel(CHI,i),d, dvh+dwh) : mkvec2s(d,dvh+dwh); } setlg(A, j); return A; } static GEN mfdim0all(GEN w) { if (w) retconst_vec(lg(w)-1, zerovec(2)); return cgetg(1,t_VEC); } static long mf1cuspdim_i(long N, GEN CHI, GEN TMP, GEN vSP, long *dih) { pari_sp av = avma; GEN b = mf1basis(N, CHI, TMP, vSP, NULL, dih); return gc_long(av, b? itou(b): 0); } static long mf1cuspdim(long N, GEN CHI, GEN vSP) { if (!vSP) vSP = get_vDIH(N, divisorsNF(N, mfcharconductor(CHI))); return mf1cuspdim_i(N, CHI, NULL, vSP, NULL); } static GEN mf1cuspdimall(long N, GEN vCHI) { GEN z, TMP, w, vSP; long i, j, l; if (wt1empty(N)) return mfdim0all(vCHI); w = mf1chars(N,vCHI); l = lg(w); if (l == 1) return cgetg(1,t_VEC); z = cgetg(l, t_VEC); TMP = mf1_pre(N); vSP = get_vDIH(N, NULL); for (i = j = 1; i < l; i++) { GEN CHI = gel(w,i); long dih, d = mf1cuspdim_i(N, CHI, TMP, vSP, &dih); if (vCHI) gel(z,j++) = mkvec2s(d, dih); else if (d) gel(z,j++) = fmt_dim(CHI, d, dih); } setlg(z,j); return z; } /* dimension of S_1(Gamma_1(N)) */ static long mf1cuspdimsum(long N) { pari_sp av = avma; GEN v = mf1cuspdimall(N, NULL); long i, ct = 0, l = lg(v); for (i = 1; i < l; i++) { GEN w = gel(v,i); /* [ord(CHI),*,dim,*] */ ct += itou(gel(w,3))*myeulerphiu(itou(gel(w,1))); } return gc_long(av,ct); } static GEN mf1newdimall(long N, GEN vCHI) { GEN z, w, vTMP, vSP, fa, P, E; long i, c, l, lw, P1; if (wt1empty(N)) return mfdim0all(vCHI); w = mf1chars(N,vCHI); lw = lg(w); if (lw == 1) return cgetg(1,t_VEC); vTMP = const_vec(N, NULL); vSP = get_vDIH(N, NULL); gel(vTMP,N) = mf1_pre(N); /* if p || N and p \nmid F(CHI), S_1^new(G0(N),chi) = 0 */ fa = znstar_get_faN(gmael(w,1,1)); P = gel(fa,1); l = lg(P); E = gel(fa,2); for (i = P1 = 1; i < l; i++) if (E[i] == 1) P1 *= itou(gel(P,i)); /* P1 = \prod_{v_p(N) = 1} p */ z = cgetg(lw, t_VEC); for (i = c = 1; i < lw; i++) { long S, j, l, F, dihnew; GEN D, CHI = gel(w,i), CHIP = mfchartoprimitive(CHI,&F); S = F % P1? 0: mf1cuspdim_i(N, CHI, gel(vTMP,N), vSP, &dihnew); if (!S) { if (vCHI) gel(z, c++) = zerovec(2); continue; } D = mydivisorsu(N/F); l = lg(D); for (j = l-2; j > 0; j--) /* skip last M = N */ { long M = D[j]*F, m, s, dih; GEN TMP = gel(vTMP,M); if (wt1empty(M) || !(m = mubeta(D[l-j]))) continue; /*m = mubeta(N/M)*/ if (!TMP) gel(vTMP,M) = TMP = mf1_pre(M); s = mf1cuspdim_i(M, CHIP, TMP, vSP, &dih); if (s) { S += m * s; dihnew += m * dih; } } if (vCHI) gel(z,c++) = mkvec2s(S, dihnew); else if (S) gel(z, c++) = fmt_dim(CHI, S, dihnew); } setlg(z,c); return z; } static GEN mf1olddimall(long N, GEN vCHI) { long i, j, l; GEN z, w; if (wt1empty(N)) return mfdim0all(vCHI); w = mf1chars(N,vCHI); l = lg(w); z = cgetg(l, t_VEC); for (i = j = 1; i < l; i++) { GEN CHI = gel(w,i); long d = mfolddim(N, 1, CHI); if (vCHI) gel(z,j++) = mkvec2s(d,d?-1:0); else if (d) gel(z, j++) = fmt_dim(CHI, d, -1); } setlg(z,j); return z; } static long mf1olddimsum(long N) { GEN D; long N2, i, l, S = 0; newd_params(N, &N2); /* will ensure mubeta != 0 */ D = mydivisorsu(N/N2); l = lg(D); for (i = 2; i < l; i++) { long M = D[l-i]*N2, d = mf1cuspdimsum(M); if (d) S -= mubeta(D[i]) * d; } return S; } static long mf1newdimsum(long N) { long S = mf1cuspdimsum(N); return S? S - mf1olddimsum(N): 0; } /* return the automorphism of a degree-2 nf */ static GEN nf2_get_conj(GEN nf) { GEN pol = nf_get_pol(nf); return deg1pol_shallow(gen_m1, negi(gel(pol,3)), varn(pol)); } static int foo_stable(GEN foo) { return lg(foo) != 3 || equalii(gel(foo,1), gel(foo,2)); } static long mfisdihedral(GEN vF, GEN DIH) { GEN vG = gel(DIH,1), M = gel(DIH,2), v, G, bnr, w, gen, D, f, nf, tau; GEN bnr0 = NULL, f0, f0b, xin, foo; long i, l, e, j, L, n; if (lg(M) == 1) return 0; v = RgM_RgC_invimage(M, vF); if (!v) return 0; l = lg(v); for (i = 1; i < l; i++) if (!gequal0(gel(v,i))) break; if (i == l) return 0; G = gel(vG,i); bnr = gel(G,2); D = cyc_get_expo(bnr_get_cyc(bnr)); w = gel(G,3); f = bnr_get_mod(bnr); nf = bnr_get_nf(bnr); tau = nf2_get_conj(nf); f0 = gel(f,1); foo = gel(f,2); f0b = galoisapply(nf, tau, f0); xin = zv_to_ZV(gel(w,2)); /* xi(bnr.gen[i]) = e(xin[i] / D) */ if (!foo_stable(foo)) { foo = mkvec2(gen_1, gen_1); bnr0 = bnr; } if (!gequal(f0, f0b)) { f0 = idealmul(nf, f0, idealdivexact(nf, f0b, idealadd(nf, f0, f0b))); bnr0 = bnr; } if (bnr0) { /* conductor not ambiguous */ GEN S; bnr = Buchray(bnr_get_bnf(bnr), mkvec2(f0, foo), nf_INIT | nf_GEN); S = bnrsurjection(bnr, bnr0); xin = FpV_red(RgV_RgM_mul(xin, gel(S,1)), D); /* still xi(gen[i]) = e(xin[i] / D), for the new generators; D stays * the same, not exponent(bnr.cyc) ! */ } gen = bnr_get_gen(bnr); L = lg(gen); for (j = 1, e = itou(D); j < L; j++) { GEN Ng = idealnorm(nf, gel(gen,j)); GEN a = shifti(gel(xin,j), 1); /* xi(g_j^2) = e(a/D) */ GEN b = FpV_dotproduct(xin, isprincipalray(bnr,Ng), D); GEN m = Fp_sub(a, b, D); /* xi(g_j/g_j^\tau) = e(m/D) */ e = ugcd(e, itou(m)); if (e == 1) break; } n = itou(D) / e; return n == 1? 4: 2*n; } static ulong myradicalu(ulong n) { return zv_prod(gel(myfactoru(n),1)); } /* list of fundamental discriminants unramified outside N, with sign s * [s = 0 => no sign condition] */ static GEN mfunram(long N, long s) { long cN = myradicalu(N >> vals(N)), p = 1, m = 1, l, c, i; GEN D = mydivisorsu(cN), res; l = lg(D); if (s == 1) m = 0; else if (s == -1) p = 0; res = cgetg(6*l - 5, t_VECSMALL); c = 1; if (!odd(N)) { /* d = 1 */ if (p) res[c++] = 8; if (m) { res[c++] =-8; res[c++] =-4; } } for (i = 2; i < l; i++) { /* skip d = 1, done above */ long d = D[i], d4 = d & 3L; /* d odd, squarefree, d4 = 1 or 3 */ if (d4 == 1) { if (p) res[c++] = d; } else { if (m) res[c++] =-d; } if (!odd(N)) { if (p) { res[c++] = 8*d; if (d4 == 3) res[c++] = 4*d; } if (m) { res[c++] =-8*d; if (d4 == 1) res[c++] =-4*d; } } } setlg(res, c); return res; } /* Return 1 if F is definitely not S4 type; return 0 on failure. */ static long mfisnotS4(long N, GEN w) { GEN D = mfunram(N, 0); long i, lD = lg(D), lw = lg(w); for (i = 1; i < lD; i++) { long p, d = D[i], ok = 0; for (p = 2; p < lw; p++) if (w[p] && kross(d,p) == -1) { ok = 1; break; } if (!ok) return 0; } return 1; } /* Return 1 if Q(sqrt(5)) \not\subset Q(F), i.e. F is definitely not A5 type; * return 0 on failure. */ static long mfisnotA5(GEN F) { GEN CHI = mf_get_CHI(F), P = mfcharpol(CHI), T, Q; if (mfcharorder(CHI) % 5 == 0) return 0; T = mf_get_field(F); if (degpol(T) == 1) return 1; if (degpol(P) > 1) T = rnfequation(P,T); Q = gsubgs(pol_xn(2,varn(T)), 5); return (typ(nfisincl(Q, T)) == t_INT); } /* v[p+1]^2 / chi(p) - 2 = z + 1/z with z primitive root of unity of order n, * return n */ static long mffindrootof1(GEN v, long p, GEN CHI) { GEN ap = gel(v,p+1), u0, u1, u1k, u2; long c = 1; if (gequal0(ap)) return 2; u0 = gen_2; u1k = u1 = gsubgs(gdiv(gsqr(ap), mfchareval(CHI, p)), 2); while (!gequalsg(2, liftpol_shallow(u1))) /* u1 = z^c + z^-c */ { u2 = gsub(gmul(u1k, u1), u0); u0 = u1; u1 = u2; c++; } return c; } /* we known that F is not dihedral */ static long mfgaloistype_i(long N, GEN CHI, GEN F, GEN v) { forprime_t iter; long lim = lg(v)-2; GEN w = zero_zv(lim); pari_sp av; ulong p; u_forprime_init(&iter, 2, lim); av = avma; while((p = u_forprime_next(&iter))) if (N%p) switch(mffindrootof1(v, p, CHI)) { case 1: case 2: continue; case 3: w[p] = 1; break; case 4: return -24; /* S4 */ case 5: return -60; /* A5 */ default: pari_err_DOMAIN("mfgaloistype", "form", "not a", strtoGENstr("cuspidal eigenform"), F); set_avma(av); } if (mfisnotS4(N,w) && mfisnotA5(F)) return -12; /* A4 */ return 0; /* FAILURE */ } static GEN mfgaloistype0(long N, GEN CHI, GEN F, GEN DIH, long lim) { pari_sp av = avma; GEN vF = mftocol(F, lim, 1); long t = mfisdihedral(vF, DIH), bound; if (t) return gc_stoi(av,t); bound = maxss(200, 5*expu(N)*expu(N)); for(;;) { t = mfgaloistype_i(N, CHI, F, vF); set_avma(av); if (t) return stoi(t); if (lim > bound) return gen_0; lim += lim >> 1; vF = mfcoefs_i(F,lim,1); } } /* If f is NULL, give all the galoistypes, otherwise just for f */ /* Return 0 to indicate failure; in this case the type is either -12 or -60, * most likely -12. FIXME using the Galois representation. */ GEN mfgaloistype(GEN NK, GEN f) { pari_sp av = avma; GEN CHI, T, F, DIH, SP, mf = checkMF_i(NK); long N, k, lL, i, lim, SB; if (f && !checkmf_i(f)) pari_err_TYPE("mfgaloistype", f); if (mf) { N = MF_get_N(mf); k = MF_get_k(mf); CHI = MF_get_CHI(mf); } else { checkNK(NK, &N, &k, &CHI, 0); mf = f? NULL: mfinit_i(NK, mf_NEW); } if (k != 1) pari_err_DOMAIN("mfgaloistype", "k", "!=", gen_1, stoi(k)); SB = mf? mfsturm_mf(mf): mfsturmNk(N,1); SP = get_DIH(N); DIH = mfdihedralnew(N, CHI, SP); lim = lg(DIH) == 1? 200: SB; DIH = mkvec2(DIH, mfvectomat(DIH,SB,1)); if (f) return gerepileuptoint(av, mfgaloistype0(N,CHI, f, DIH, lim)); F = mfeigenbasis(mf); lL = lg(F); T = cgetg(lL, t_VEC); for (i=1; i < lL; i++) gel(T,i) = mfgaloistype0(N, CHI, gel(F,i), DIH, lim); return gerepileupto(av, T); } /******************************************************************/ /* Find all dihedral forms. */ /******************************************************************/ /* lim >= 2 */ static void consttabdihedral(long lim) { cache_set(cache_DIH, mfdihedralall(lim)); } /* a ideal coprime to bnr modulus */ static long mfdiheval(GEN bnr, GEN w, GEN a) { GEN L, cycn = gel(w,1), chin = gel(w,2); long ordmax = cycn[1]; L = ZV_to_Flv(isprincipalray(bnr,a), ordmax); return Flv_dotproduct(chin, L, ordmax); } /* A(x^k) mod T = polcyclo(m), 0 <= k < m */ static GEN Galois(GEN A, long k, GEN T, long m) { GEN B; long i, ik, d; if (typ(A) != t_POL) return A; if (varn(A) != varn(T)) { B = cgetg_copy(A, &d); B[1] = A[1]; for (i = 2; i < d; i++) gel(B, i) = Galois(gel(A, i), k, T, m); return B; } if ((d = degpol(A)) <= 0) return A; B = cgetg(m + 2, t_POL); B[1] = A[1]; gel(B,2) = gel(A,2); for (i = 1; i < m; i++) gel(B, i+2) = gen_0; for (i = 1, ik = k; i <= d; i++, ik = Fl_add(ik, k, m)) gel(B, ik + 2) = gel(A, i+2); return QX_ZX_rem(normalizepol(B), T); } static GEN vecGalois(GEN v, long k, GEN T, long m) { long i, l; GEN w = cgetg_copy(v,&l); for (i = 1; i < l; i++) gel(w,i) = Galois(gel(v,i), k, T, m); return w; } static GEN fix_pol(GEN S, GEN Pn, int *trace) { if (typ(S) != t_POL) return S; S = RgX_rem(S, Pn); if (typ(S) == t_POL) { switch(lg(S)) { case 2: return gen_0; case 3: return gel(S,2); } *trace = 1; } return S; } static GEN dihan(GEN bnr, GEN w, GEN k0j, long m, ulong lim) { GEN nf = bnr_get_nf(bnr), f = bid_get_ideal(bnr_get_bid(bnr)); GEN v = zerovec(lim+1), cycn = gel(w,1), Tinit = gel(w,3); GEN Pn = gel(Tinit,lg(Tinit)==4? 2: 1); long j, ordmax = cycn[1]; long D = itos(nf_get_disc(nf)), vt = varn(Pn); int trace = 0; ulong p, n; forprime_t T; if (!lim) return v; gel(v,2) = gen_1; u_forprime_init(&T, 2, lim); /* fill in prime powers first */ while ((p = u_forprime_next(&T))) { GEN vP, vchiP, S; long k, lP; ulong q, qk; if (kross(D,p) >= 0) q = p; else if (!(q = umuluu_le(p,p,lim))) continue; /* q = Norm P */ vP = idealprimedec(nf, utoipos(p)); lP = lg(vP); vchiP = cgetg(lP, t_VECSMALL); for (j = k = 1; j < lP; j++) { GEN P = gel(vP,j); if (!idealval(nf, f, P)) vchiP[k++] = mfdiheval(bnr,w,P); } if (k == 1) continue; setlg(vchiP, k); lP = k; if (lP == 2) { /* one prime above p not dividing f */ long s, s0 = vchiP[1]; for (qk=q, s = s0;; s = Fl_add(s,s0,ordmax)) { S = Qab_zeta(s, ordmax, vt); gel(v, qk+1) = fix_pol(S, Pn, &trace); if (!(qk = umuluu_le(qk,q,lim))) break; } } else /* two primes above p not dividing f */ { long s, s0 = vchiP[1], s1 = vchiP[2]; for (qk=q, k = 1;; k++) { /* sum over a,b s.t. Norm( P1^a P2^b ) = q^k, i.e. a+b = k */ long a; GEN S = gen_0; for (a = 0; a <= k; a++) { s = Fl_add(Fl_mul(a, s0, ordmax), Fl_mul(k-a, s1, ordmax), ordmax); S = gadd(S, Qab_zeta(s, ordmax, vt)); } gel(v, qk+1) = fix_pol(S, Pn, &trace); if (!(qk = umuluu_le(qk,q,lim))) break; } } } /* complete with nonprime powers */ for (n = 2; n <= lim; n++) { GEN S, fa = myfactoru(n), P = gel(fa, 1), E = gel(fa, 2); long q; if (lg(P) == 2) continue; /* not a prime power */ q = upowuu(P[1],E[1]); S = gmul(gel(v, q + 1), gel(v, n/q + 1)); gel(v, n+1) = fix_pol(S, Pn, &trace); } if (trace) { long k0 = k0j[1], jdeg = k0j[2]; v = QabV_tracerel(Tinit, jdeg, v); /* Apply Galois Mod(k0, ordw) */ if (k0 > 1) v = vecGalois(v, k0, gel(Tinit,1), m); } return v; } /* as cyc_normalize for t_VECSMALL cyc */ static GEN cyc_normalize_zv(GEN cyc) { long i, o = cyc[1], l = lg(cyc); /* > 1 */ GEN D = cgetg(l, t_VECSMALL); D[1] = o; for (i = 2; i < l; i++) D[i] = o / cyc[i]; return D; } /* as char_normalize for t_VECSMALLs */ static GEN char_normalize_zv(GEN chi, GEN ncyc) { long i, l = lg(chi); GEN c = cgetg(l, t_VECSMALL); if (l > 1) { c[1] = chi[1]; for (i = 2; i < l; i++) c[i] = chi[i] * ncyc[i]; } return c; } static GEN dihan_bnf(long D) { GEN c = getrand(), bnf; setrand(gen_1); bnf = Buchall(quadpoly_i(stoi(D)), nf_FORCE, LOWDEFAULTPREC); setrand(c); return bnf; } static GEN dihan_bnr(GEN bnf, GEN A) { GEN c = getrand(), bnr; setrand(gen_1); bnr = Buchray(bnf, A, nf_INIT|nf_GEN); setrand(c); return bnr; } /* Hecke xi * (D/.) = Dirichlet chi, return v in Q^r st chi(g_i) = e(v[i]). * cycn = cyc_normalize_zv(bnr.cyc), chin = char_normalize_zv(chi,cyc) */ static GEN bnrchartwist2conrey(GEN chin, GEN cycn, GEN bnrconreyN, GEN kroconreyN) { long l = lg(bnrconreyN), c1 = cycn[1], i; GEN v = cgetg(l, t_COL); for (i = 1; i < l; i++) { GEN d = sstoQ(zv_dotproduct(chin, gel(bnrconreyN,i)), c1); if (kroconreyN[i] < 0) d = gadd(d, ghalf); gel(v,i) = d; } return v; } /* chi(g_i) = e(v[i]) denormalize wrt Conrey generators orders */ static GEN conreydenormalize(GEN znN, GEN v) { GEN gcyc = znstar_get_conreycyc(znN), w; long l = lg(v), i; w = cgetg(l, t_COL); for (i = 1; i < l; i++) gel(w,i) = modii(gmul(gel(v,i), gel(gcyc,i)), gel(gcyc,i)); return w; } static long Miyake(GEN vchi, GEN gb, GEN cycn) { long i, e = cycn[1], lb = lg(gb); GEN v = char_normalize_zv(vchi, cycn); for (i = 1; i < lb; i++) if ((zv_dotproduct(v, gel(gb,i)) - v[i]) % e) return 1; return 0; } /* list of Hecke characters not induced by a Dirichlet character up to Galois * conjugation, whose conductor is bnr.cond; cycn = cyc_normalize(bnr.cyc)*/ static GEN mklvchi(GEN bnr, GEN cycn, GEN gb) { GEN cyc = bnr_get_cyc(bnr), cycsmall = ZV_to_zv(cyc); GEN vchi = cyc2elts(cycsmall); long ordmax = cycsmall[1], c, i, l; l = lg(vchi); for (i = c = 1; i < l; i++) { GEN chi = gel(vchi,i); if (!gb || Miyake(chi, gb, cycn)) gel(vchi, c++) = Flv_to_ZV(chi); } setlg(vchi, c); l = c; for (i = 1; i < l; i++) { GEN chi = gel(vchi,i); long n; if (!chi) continue; for (n = 2; n < ordmax; n++) if (ugcd(n, ordmax) == 1) { GEN tmp = ZV_ZV_mod(gmulsg(n, chi), cyc); long j; for (j = i+1; j < l; j++) if (gel(vchi,j) && gequal(gel(vchi,j), tmp)) gel(vchi,j) = NULL; } } for (i = c = 1; i < l; i++) { GEN chi = gel(vchi,i); if (chi && bnrisconductor(bnr, chi)) gel(vchi, c++) = chi; } setlg(vchi, c); return vchi; } static GEN get_gb(GEN bnr, GEN con) { GEN gb, g = bnr_get_gen(bnr), nf = bnr_get_nf(bnr); long i, l = lg(g); gb = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(gb,i) = ZV_to_zv(isprincipalray(bnr, galoisapply(nf, con, gel(g,i)))); return gb; } static GEN get_bnrconreyN(GEN bnr, GEN znN) { GEN z, g = znstar_get_conreygen(znN); long i, l = lg(g); z = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(z,i) = ZV_to_zv(isprincipalray(bnr,gel(g,i))); return z; } /* con = NULL if D > 0 or if D < 0 and id != idcon. */ static GEN mfdihedralcommon(GEN bnf, GEN id, GEN znN, GEN kroconreyN, long vt, long N, long D, GEN con) { GEN bnr = dihan_bnr(bnf, id), cyc = ZV_to_zv( bnr_get_cyc(bnr) ); GEN bnrconreyN, cycn, cycN, Lvchi, res, P, vT; long j, ordmax, l, lc, deghecke; lc = lg(cyc); if (lc == 1) return NULL; cycn = cyc_normalize_zv(cyc); Lvchi = mklvchi(bnr, cycn, con? get_gb(bnr, con): NULL); l = lg(Lvchi); if (l == 1) return NULL; bnrconreyN = get_bnrconreyN(bnr, znN); cycN = ZV_to_zv(znstar_get_cyc(znN)); ordmax = cyc[1]; vT = const_vec(odd(ordmax)? ordmax << 1: ordmax, NULL); P = polcyclo(ordmax, vt); gel(vT,ordmax) = Qab_trace_init(ordmax, ordmax, P, P); deghecke = myeulerphiu(ordmax); res = cgetg(l, t_VEC); for (j = 1; j < l; j++) { GEN T, v, vchi = ZV_to_zv(gel(Lvchi,j)); GEN chi, chin = char_normalize_zv(vchi, cycn); long o, vnum, k0, degrel; v = bnrchartwist2conrey(chin, cycn, bnrconreyN, kroconreyN); o = itou(Q_denom(v)); T = gel(vT, o); if (!T) gel(vT,o) = T = Qab_trace_init(ordmax, o, P, polcyclo(o,vt)); chi = conreydenormalize(znN, v); vnum = itou(znconreyexp(znN, chi)); chi = ZV_to_zv(znconreychar(znN,chi)); degrel = deghecke / degpol(gel(T,1)); k0 = zv_cyc_minimize(cycN, chi, coprimes_zv(o)); vnum = Fl_powu(vnum, k0, N); /* encodes degrel forms: jdeg = 0..degrel-1 */ gel(res,j) = mkvec3(mkvecsmalln(5, N, k0 % o, vnum, D, degrel), id, mkvec3(cycn,chin,T)); } return res; } static long is_cond(long D, long n) { if (D > 0) return n != 4 || (D&7L) == 1; return n != 2 && n != 3 && (n != 4 || (D&7L)!=1); } /* Append to v all dihedral weight 1 forms coming from D, if fundamental. * level in [l1, l2] */ static void append_dihedral(GEN v, long D, long l1, long l2, long vt) { long Da = labs(D), no, i, numi, ct, min, max; GEN bnf, con, vI, resall, arch1, arch2; pari_sp av; /* min <= Nf <= max */ max = l2 / Da; if (l1 == l2) { /* assume Da | l2 */ min = max; if (D > 0 && min < 3) return; } else /* assume l1 < l2 */ min = (l1 + Da-1)/Da; if (!sisfundamental(D)) return; av = avma; bnf = dihan_bnf(D); con = nf2_get_conj(bnf_get_nf(bnf)); vI = ideallist(bnf, max); numi = 0; for (i = min; i <= max; i++) numi += lg(gel(vI, i)) - 1; if (D > 0) { numi <<= 1; arch1 = mkvec2(gen_1,gen_0); arch2 = mkvec2(gen_0,gen_1); } else arch1 = arch2 = NULL; resall = cgetg(numi+1, t_VEC); ct = 1; for (no = min; no <= max; no++) if (is_cond(D, no)) { long N = Da*no, lc, lI; GEN I = gel(vI, no), znN = znstar0(utoipos(N), 1), conreyN, kroconreyN; conreyN = znstar_get_conreygen(znN); lc = lg(conreyN); kroconreyN = cgetg(lc, t_VECSMALL); for (i = 1; i < lc; i++) kroconreyN[i] = krosi(D, gel(conreyN, i)); lI = lg(I); for (i = 1; i < lI; i++) { GEN id = gel(I, i), idcon, z; long j; if (typ(id) == t_INT) continue; idcon = galoisapply(bnf, con, id); for (j = i; j < lI; j++) if (gequal(idcon, gel(I, j))) { gel(I, j) = gen_0; break; } if (D < 0) { GEN conk = i == j ? con : NULL; z = mfdihedralcommon(bnf, id, znN, kroconreyN, vt, N, D, conk); if (z) gel(resall, ct++) = z; } else { GEN ide; ide = mkvec2(id, arch1); z = mfdihedralcommon(bnf, ide, znN, kroconreyN, vt, N, D, NULL); if (z) gel(resall, ct++) = z; if (gequal(idcon,id)) continue; ide = mkvec2(id, arch2); z = mfdihedralcommon(bnf, ide, znN, kroconreyN, vt, N, D, NULL); if (z) gel(resall, ct++) = z; } } } if (ct == 1) set_avma(av); else { setlg(resall, ct); vectrunc_append(v, gerepilecopy(av, shallowconcat1(resall))); } } static long di_N(GEN a) { return gel(a,1)[1]; } static GEN mfdihedral(long N) { GEN D = mydivisorsu(N), res = vectrunc_init(2*N); long j, l = lg(D), vt = fetch_user_var("t"); for (j = 2; j < l; j++) { /* skip d = 1 */ long d = D[j]; if (d == 2) continue; append_dihedral(res, -d, N,N, vt); if (d >= 5 && D[l-j] >= 3) append_dihedral(res, d, N,N, vt);/* Nf >= 3 */ } if (lg(res) > 1) res = shallowconcat1(res); return res; } /* All primitive dihedral weight 1 forms of leven in [1, N], N > 1 */ static GEN mfdihedralall(long N) { GEN res = vectrunc_init(2*N), z; long D, ct, i, vt = fetch_user_var("t"); for (D = -3; D >= -N; D--) append_dihedral(res, D, 1,N, vt); /* Nf >= 3 (GTM 193, prop 3.3.18) */ for (D = N / 3; D >= 5; D--) append_dihedral(res, D, 1,N, vt); ct = lg(res); if (ct > 1) { /* sort wrt N */ res = shallowconcat1(res); res = vecpermute(res, indexvecsort(res, mkvecsmall(1))); ct = lg(res); } z = const_vec(N, cgetg(1,t_VEC)); for (i = 1; i < ct;) { /* regroup result sharing the same N */ long n = di_N(gel(res,i)), j = i+1, k; GEN v; while (j < ct && di_N(gel(res,j)) == n) j++; gel(z, n) = v = cgetg(j-i+1, t_VEC); for (k = 1; i < j; k++,i++) gel(v,k) = gel(res,i); } return z; } /* return [vF, index], where vecpermute(vF,index) generates dihedral forms * for character CHI */ static GEN mfdihedralnew_i(long N, GEN CHI, GEN SP) { GEN bnf, Tinit, Pm, vf, M, V, NK; long Dold, d, ordw, i, SB, c, l, k0, k1, chino, chinoorig, lv; lv = lg(SP); if (lv == 1) return NULL; CHI = mfcharinduce(CHI,N); ordw = mfcharorder(CHI); chinoorig = mfcharno(CHI); k0 = mfconreyminimize(CHI); chino = Fl_powu(chinoorig, k0, N); k1 = Fl_inv(k0 % ordw, ordw); V = cgetg(lv, t_VEC); d = 0; for (i = l = 1; i < lv; i++) { GEN sp = gel(SP,i), T = gel(sp,1); if (T[3] != chino) continue; d += T[5]; if (k1 != 1) { GEN t = leafcopy(T); t[3] = chinoorig; t[2] = (t[2]*k1) % ordw; sp = mkvec4(t, gel(sp,2), gel(sp,3), gel(sp,4)); } gel(V, l++) = sp; } setlg(V, l); /* dihedral forms of level N and character CHI */ if (l == 1) return NULL; SB = mfsturmNk(N,1) + 1; M = cgetg(d+1, t_MAT); vf = cgetg(d+1, t_VEC); NK = mkNK(N, 1, CHI); bnf = NULL; Dold = 0; for (i = c = 1; i < l; i++) { /* T = [N, k0, conreyno, D, degrel] */ GEN bnr, Vi = gel(V,i), T = gel(Vi,1), id = gel(Vi,2), w = gel(Vi,3); long jdeg, k0i = T[2], D = T[4], degrel = T[5]; if (D != Dold) { Dold = D; bnf = dihan_bnf(D); } bnr = dihan_bnr(bnf, id); for (jdeg = 0; jdeg < degrel; jdeg++,c++) { GEN k0j = mkvecsmall2(k0i, jdeg), an = dihan(bnr, w, k0j, ordw, SB); settyp(an, t_COL); gel(M,c) = an; gel(vf,c) = tag3(t_MF_DIHEDRAL, NK, bnr, w, k0j); } } Tinit = gmael3(V,1,3,3); Pm = gel(Tinit,1); V = QabM_indexrank(M, degpol(Pm)==1? NULL: Pm, ordw); return mkvec2(vf,gel(V,2)); } static long mfdihedralnewdim(long N, GEN CHI, GEN SP) { pari_sp av = avma; GEN S = mfdihedralnew_i(N, CHI, SP); return gc_long(av, S? lg(gel(S,2))-1: 0); } static GEN mfdihedralnew(long N, GEN CHI, GEN SP) { pari_sp av = avma; GEN S = mfdihedralnew_i(N, CHI, SP); if (!S) { set_avma(av); return cgetg(1, t_VEC); } return vecpermute(gel(S,1), gel(S,2)); } static long mfdihedralcuspdim(long N, GEN CHI, GEN vSP) { pari_sp av = avma; GEN D, CHIP; long F, i, lD, dim; CHIP = mfchartoprimitive(CHI, &F); D = mydivisorsu(N/F); lD = lg(D); dim = mfdihedralnewdim(N, CHI, gel(vSP,N)); /* d = 1 */ for (i = 2; i < lD; i++) { long d = D[i], a = mfdihedralnewdim(N/d, CHIP, gel(vSP, N/d)); if (a) dim += a * mynumdivu(d); } return gc_long(av,dim); } static GEN mfbdall(GEN E, long N) { GEN v, D = mydivisorsu(N); long i, j, nD = lg(D) - 1, nE = lg(E) - 1; v = cgetg(nD*nE + 1, t_VEC); for (j = 1; j <= nE; j++) { GEN Ej = gel(E, j); for (i = 0; i < nD; i++) gel(v, i*nE + j) = mfbd_i(Ej, D[i+1]); } return v; } static GEN mfdihedralcusp(long N, GEN CHI, GEN vSP) { pari_sp av = avma; GEN D, CHIP, z; long F, i, lD; CHIP = mfchartoprimitive(CHI, &F); D = mydivisorsu(N/F); lD = lg(D); z = cgetg(lD, t_VEC); gel(z,1) = mfdihedralnew(N, CHI, gel(vSP,N)); for (i = 2; i < lD; i++) /* skip 1 */ { GEN LF = mfdihedralnew(N / D[i], CHIP, gel(vSP, N / D[i])); gel(z,i) = mfbdall(LF, D[i]); } return gerepilecopy(av, shallowconcat1(z)); } /* used to decide between ratlift and comatrix for ZM_inv; ratlift is better * when N has many divisors */ static int abundant(ulong N) { return mynumdivu(N) >= 8; } /* CHI an mfchar */ static int cmp_ord(void *E, GEN a, GEN b) { GEN chia = MF_get_CHI(a), chib = MF_get_CHI(b); (void)E; return cmpii(gmfcharorder(chia), gmfcharorder(chib)); } /* mfinit structure. -- mf[1] contains [N,k,CHI,space], -- mf[2] contains vector of closures of Eisenstein series, empty if not full space. -- mf[3] contains vector of closures, so #mf[3] = dimension of cusp/new space. -- mf[4] contains the corresponding indices: either j for T(j)tf if newspace, or [M,j,d] for B(d)T(j)tf_M if cuspspace or oldspace. -- mf[5] contains the matrix M of first coefficients of basis, never cleaned. * NK is either [N,k] or [N,k,CHI]. * mfinit does not do the splitting, only the basis generation. */ /* Set flraw to 1 if do not need mf[5]: no mftobasis etc..., only the expansions of the basis elements are needed. */ static GEN mfinit_Nkchi(long N, long k, GEN CHI, long space, long flraw) { GEN M = NULL, mf = NULL, mf1 = mkvec4(utoi(N), stoi(k), CHI, utoi(space)); long sb = mfsturmNk(N, k); if (k < 0 || badchar(N, k, CHI)) return mfEMPTY(mf1); if (k == 0 || space == mf_EISEN) /*nothing*/; else if (k == 1) { switch (space) { case mf_NEW: case mf_FULL: case mf_CUSP: mf = mf1init(N, CHI, NULL, get_vDIH(N,NULL), space, flraw); break; case mf_OLD: pari_err_IMPL("mfinit in weight 1 for old space"); default: pari_err_FLAG("mfinit"); } } else /* k >= 2 */ { long ord = mfcharorder(CHI); GEN z = NULL, P = (ord <= 2)? NULL: mfcharpol(CHI); cachenew_t cache; switch(space) { case mf_NEW: mf = mfnewinit(N, k, CHI, &cache, 1); if (mf && !flraw) { M = MF_get_M(mf); z = MF_get_Mindex(mf); } break; case mf_OLD: case mf_CUSP: case mf_FULL: if (!(mf = mfinitcusp(N, k, CHI, &cache, space))) break; if (!flraw) { M = bhnmat_extend(M, sb+1, 1, MF_get_S(mf), &cache); if (space != mf_FULL) gel(mf,5) = mfcleanCHI(M, CHI, abundant(N)); } dbg_cachenew(&cache); break; default: pari_err_FLAG("mfinit"); } if (z) gel(mf,5) = mfclean2(M, z, P, ord); } if (!mf) mf = mfEMPTY(mf1); else { gel(mf,1) = mf1; if (flraw) gel(mf,5) = zerovec(3); } if (!space_is_cusp(space)) { GEN E = mfeisensteinbasis(N, k, CHI); gel(mf,2) = E; if (!flraw) { if (M) M = shallowconcat(mfvectomat(E, sb+1, 1), M); else M = mfcoefs_mf(mf, sb+1, 1); gel(mf,5) = mfcleanCHI(M, CHI, abundant(N)); } } return mf; } /* mfinit for k = nk/dk */ static GEN mfinit_Nndkchi(long N, long nk, long dk, GEN CHI, long space, long flraw) { return (dk == 2)? mf2init_Nkchi(N, nk >> 1, CHI, space, flraw) : mfinit_Nkchi(N, nk, CHI, space, flraw); } static GEN mfinit_i(GEN NK, long space) { GEN CHI, mf; long N, k, dk, joker; if (checkmf_i(NK)) { N = mf_get_N(NK); Qtoss(mf_get_gk(NK), &k, &dk); CHI = mf_get_CHI(NK); } else if ((mf = checkMF_i(NK))) { long s = MF_get_space(mf); if (s == space) return mf; Qtoss(MF_get_gk(mf), &k, &dk); if (dk == 1 && k > 1 && space == mf_NEW && (s == mf_CUSP || s == mf_FULL)) return mfinittonew(mf); N = MF_get_N(mf); CHI = MF_get_CHI(mf); } else checkNK2(NK, &N, &k, &dk, &CHI, 1); joker = !CHI || typ(CHI) == t_COL; if (joker) { GEN mf, vCHI = CHI; long i, j, l; if (CHI && lg(CHI) == 1) return cgetg(1,t_VEC); if (k < 0) return mfEMPTYall(N, uutoQ(k,dk), CHI, space); if (k == 1 && dk == 1 && space != mf_EISEN) { GEN TMP, vSP, gN, gs; pari_timer tt; if (space != mf_CUSP && space != mf_NEW) pari_err_IMPL("mfinit([N,1,wildcard], space != cusp or new space)"); if (wt1empty(N)) return mfEMPTYall(N, gen_1, CHI, space); vCHI = mf1chars(N,vCHI); l = lg(vCHI); mf = cgetg(l, t_VEC); if (l == 1) return mf; TMP = mf1_pre(N); vSP = get_vDIH(N, NULL); gN = utoipos(N); gs = utoi(space); if (DEBUGLEVEL) timer_start(&tt); for (i = j = 1; i < l; i++) { pari_sp av = avma; GEN c = gel(vCHI,i), z = mf1init(N, c, TMP, vSP, space, 0); if (z) z = gerepilecopy(av, z); else { set_avma(av); if (CHI) z = mfEMPTY(mkvec4(gN,gen_1,c,gs)); } if (z) gel(mf, j++) = z; if (DEBUGLEVEL) timer_printf(&tt, "mf1basis: character %ld / %ld (order = %ld)", i, l-1, mfcharorder(c)); } } else { vCHI = mfchars(N,k,dk,vCHI); l = lg(vCHI); mf = cgetg(l, t_VEC); for (i = j = 1; i < l; i++) { pari_sp av = avma; GEN v = mfinit_Nndkchi(N, k, dk, gel(vCHI,i), space, 0); if (MF_get_dim(v) || CHI) gel(mf, j++) = v; else set_avma(av); } } setlg(mf,j); if (!CHI) gen_sort_inplace(mf, NULL, &cmp_ord, NULL); return mf; } return mfinit_Nndkchi(N, k, dk, CHI, space, 0); } GEN mfinit(GEN NK, long space) { pari_sp av = avma; return gerepilecopy(av, mfinit_i(NK, space)); } /* UTILITY FUNCTIONS */ static void cusp_canon(GEN cusp, long N, long *pA, long *pC) { pari_sp av = avma; long A, C, tc, cg; if (N <= 0) pari_err_DOMAIN("mfcuspwidth","N","<=",gen_0,stoi(N)); if (!cusp || (tc = typ(cusp)) == t_INFINITY) { *pA = 1; *pC = N; return; } if (tc != t_INT && tc != t_FRAC) pari_err_TYPE("checkcusp", cusp); Qtoss(cusp, &A,&C); if (N % C) { ulong uC; long u = Fl_invgen((C-1)%N + 1, N, &uC); A = Fl_mul(A, u, N); C = (long)uC; } cg = ugcd(C, N/C); while (ugcd(A, N) > 1) A += cg; *pA = A % N; *pC = C; set_avma(av); } static long mfcuspcanon_width(long N, long C) { return (!C || C == N)? 1 : N / ugcd(N, Fl_sqr(umodsu(C,N),N)); } /* v = [a,c] a ZC, width of cusp (a:c) */ static long mfZC_width(long N, GEN v) { ulong C = umodiu(gel(v,2), N); return (C == 0)? 1: N / ugcd(N, Fl_sqr(C,N)); } long mfcuspwidth(GEN gN, GEN cusp) { long N = 0, A, C; GEN mf; if (typ(gN) == t_INT) N = itos(gN); else if ((mf = checkMF_i(gN))) N = MF_get_N(mf); else pari_err_TYPE("mfcuspwidth", gN); cusp_canon(cusp, N, &A, &C); return mfcuspcanon_width(N, C); } /* Q a t_INT */ static GEN findq(GEN al, GEN Q) { long n; if (typ(al) == t_FRAC && cmpii(gel(al,2), Q) <= 0) return mkvec(mkvec2(gel(al,1), gel(al,2))); n = 1 + (long)ceil(2.0781*gtodouble(glog(Q, LOWDEFAULTPREC))); return contfracpnqn(gboundcf(al,n), n); } static GEN findqga(long N, GEN z) { GEN Q, LDC, CK = NULL, DK = NULL, ma, x, y = imag_i(z); long j, l; if (gcmpgs(gmulsg(2*N, y), 1) >= 0) return NULL; x = real_i(z); Q = ground(ginv(gsqrt(gmulsg(N, y), LOWDEFAULTPREC))); LDC = findq(gmulsg(-N,x), Q); ma = gen_1; l = lg(LDC); for (j = 1; j < l; j++) { GEN D, DC = gel(LDC,j), C1 = gel(DC,2); if (cmpii(C1,Q) > 0) break; D = gel(DC,1); if (ugcdiu(D,N) == 1) { GEN C = mului(N, C1), den; den = gadd(gsqr(gmul(C,y)), gsqr(gadd(D, gmul(C,x)))); if (gcmp(den, ma) < 0) { ma = den; CK = C; DK = D; } } } return DK? mkvec2(CK, DK): NULL; } static long valNC2(GEN P, GEN E, long e) { long i, d = 1, l = lg(P); for (i = 1; i < l; i++) { long v = u_lval(e, P[i]) << 1; if (v == E[i] + 1) v--; d *= upowuu(P[i], v); } return d; } static GEN findqganew(long N, GEN z) { GEN MI, DI, x = real_i(z), y = imag_i(z), Ck = gen_0, Dk = gen_1, fa, P, E; long i; MI = uutoQ(1,N); DI = mydivisorsu(mysqrtu(N)); fa = myfactoru(N); P = gel(fa,1); E = gel(fa,2); for (i = 1; i < lg(DI); i++) { long e = DI[i], g; GEN U, C, D, m; (void)cxredsl2(gmulsg(e, z), &U); C = gcoeff(U,2,1); if (!signe(C)) continue; D = gcoeff(U,2,2); g = ugcdiu(D,e); if (g > 1) { C = muliu(C,e/g); D = diviuexact(D,g); } else C = muliu(C,e); m = gadd(gsqr(gadd(gmul(C, x), D)), gsqr(gmul(C, y))); m = gdivgu(m, valNC2(P, E, e)); if (gcmp(m, MI) < 0) { MI = m; Ck = C; Dk = D; } } return signe(Ck)? mkvec2(Ck, Dk): NULL; } /* Return z' and U = [a,b;c,d] \in SL_2(Z), z' = U*z, * Im(z')/width(U.oo) > sqrt(3)/(2N). Set *pczd = c*z+d */ static GEN cxredga0N(long N, GEN z, GEN *pU, GEN *pczd, long flag) { GEN v = NULL, A, B, C, D; long e; if (N == 1) return cxredsl2_i(z, pU, pczd); e = gexpo(gel(z,2)); if (e < 0) z = gprec_wensure(z, precision(z) + nbits2extraprec(-e)); v = flag? findqganew(N,z): findqga(N,z); if (!v) { *pU = matid(2); *pczd = gen_1; return z; } C = gel(v,1); D = gel(v,2); if (!is_pm1(bezout(C,D, &B,&A))) pari_err_BUG("cxredga0N [gcd > 1]"); B = negi(B); *pU = mkmat2(mkcol2(A,C), mkcol2(B,D)); *pczd = gadd(gmul(C,z), D); return gdiv(gadd(gmul(A,z), B), *pczd); } static GEN lfunthetaall(GEN b, GEN vL, GEN t, long bitprec) { long i, l = lg(vL); GEN v = cgetg(l, t_VEC); for (i = 1; i < l; i++) { GEN T, L = gel(vL,i), a0 = gel(L,1), ldata = gel(L,2); GEN van = gel(ldata_get_an(ldata),2); if (lg(van) == 1) { T = gmul(b, a0); if (isexactzero(T)) { GEN z = real_0_bit(-bitprec); T = mkcomplex(z,z); } } else { T = gmul2n(lfuntheta(ldata, t, 0, bitprec), -1); T = gmul(b, gadd(a0, T)); } gel(v,i) = T; } return l == 2? gel(v,1): v; } /* P in ZX, irreducible */ static GEN ZX_roots(GEN P, long prec) { long d = degpol(P); if (d == 1) return mkvec(gen_0); if (d == 2 && isint1(gel(P,2)) && isintzero(gel(P,3)) && isint1(gel(P,4))) return mkvec2(powIs(3), gen_I()); /* order as polroots */ return (ZX_sturm_irred(P) == d)? ZX_realroots_irred(P, prec) : QX_complex_roots(P, prec); } /* initializations for RgX_RgV_eval / RgC_embed */ static GEN rootspowers(GEN v) { long i, l = lg(v); GEN w = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(w,i) = gpowers(gel(v,i), l-2); return w; } /* mf embeddings attached to Q(chi)/(T), chi attached to cyclotomic P */ static GEN getembed(GEN P, GEN T, GEN zcyclo, long prec) { long i, l; GEN v; if (degpol(P) == 1) P = NULL; /* mfcharpol for quadratic char */ if (degpol(T) == 1) T = NULL; /* dim 1 orbit */ if (T && P) { /* K(y) / (T(y)), K = Q(t)/(P) cyclotomic */ GEN vr = RgX_is_ZX(T)? ZX_roots(T,prec): roots(RgX_embed1(T,zcyclo), prec); v = rootspowers(vr); l = lg(v); for (i = 1; i < l; i++) gel(v,i) = mkcol3(P,zcyclo,gel(v,i)); } else if (T) { /* Q(y) / (T(y)), T noncyclotomic */ GEN vr = ZX_roots(T, prec); v = rootspowers(vr); l = lg(v); for (i = 1; i < l; i++) gel(v,i) = mkcol2(T, gel(v,i)); } else /* cyclotomic or rational */ v = mkvec(P? mkvec2(P, zcyclo): cgetg(1,t_VEC)); return v; } static GEN grootsof1_CHI(GEN CHI, long prec) { return grootsof1(mfcharorder(CHI), prec); } /* return the [Q(F):Q(chi)] embeddings of F */ static GEN mfgetembed(GEN F, long prec) { GEN T = mf_get_field(F), CHI = mf_get_CHI(F), P = mfcharpol(CHI); return getembed(P, T, grootsof1_CHI(CHI, prec), prec); } static GEN mfchiembed(GEN mf, long prec) { GEN CHI = MF_get_CHI(mf), P = mfcharpol(CHI); return getembed(P, pol_x(0), grootsof1_CHI(CHI, prec), prec); } /* mfgetembed for the successive eigenforms in MF_get_newforms */ static GEN mfeigenembed(GEN mf, long prec) { GEN vP = MF_get_fields(mf), vF = MF_get_newforms(mf); GEN zcyclo, vE, CHI = MF_get_CHI(mf), P = mfcharpol(CHI); long i, l = lg(vP); vF = Q_remove_denom(liftpol_shallow(vF), NULL); prec += nbits2extraprec(gexpo(vF)); zcyclo = grootsof1_CHI(CHI, prec); vE = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(vE,i) = getembed(P, gel(vP,i), zcyclo, prec); return vE; } static int checkPv(GEN P, GEN v) { return typ(P) == t_POL && is_vec_t(typ(v)) && lg(v)-1 >= degpol(P); } static int checkemb_i(GEN E) { long t = typ(E), l = lg(E); if (t == t_VEC) return l == 1 || (l == 3 && checkPv(gel(E,1), gel(E,2))); if (t != t_COL) return 0; if (l == 3) return checkPv(gel(E,1), gel(E,2)); return l == 4 && is_vec_t(typ(gel(E,2))) && checkPv(gel(E,1), gel(E,3)); } static GEN anyembed(GEN v, GEN E) { switch(typ(v)) { case t_VEC: case t_COL: return mfvecembed(E, v); case t_MAT: return mfmatembed(E, v); } return mfembed(E, v); } GEN mfembed0(GEN E, GEN v, long prec) { pari_sp av = avma; GEN mf, vE = NULL; if (checkmf_i(E)) vE = mfgetembed(E, prec); else if ((mf = checkMF_i(E))) vE = mfchiembed(mf, prec); if (vE) { long i, l = lg(vE); GEN w; if (!v) return gerepilecopy(av, l == 2? gel(vE,1): vE); w = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(w,i) = anyembed(v, gel(vE,i)); return gerepilecopy(av, l == 2? gel(w,1): w); } if (!checkemb_i(E) || !v) pari_err_TYPE("mfembed", E); return gerepilecopy(av, anyembed(v,E)); } /* dummy lfun create for theta evaluation */ static GEN mfthetaancreate(GEN van, GEN N, GEN k) { GEN L = zerovec(6); gel(L,1) = lfuntag(t_LFUN_GENERIC, van); gel(L,3) = mkvec2(gen_0, gen_1); gel(L,4) = k; gel(L,5) = N; return L; } /* destroy van and prepare to evaluate theta(sigma(van)), for all sigma in * embeddings vector vE */ static GEN van_embedall(GEN van, GEN vE, GEN gN, GEN gk) { GEN a0 = gel(van,1), vL; long i, lE = lg(vE), l = lg(van); van++; van[0] = evaltyp(t_VEC) | _evallg(l-1); /* remove a0 */ vL = cgetg(lE, t_VEC); for (i = 1; i < lE; i++) { GEN E = gel(vE,i), v = mfvecembed(E, van); gel(vL,i) = mkvec2(mfembed(E,a0), mfthetaancreate(v, gN, gk)); } return vL; } static int cusp_AC(GEN cusp, long *A, long *C) { switch(typ(cusp)) { case t_INFINITY: *A = 1; *C = 0; break; case t_INT: *A = itos(cusp); *C = 1; break; case t_FRAC: *A = itos(gel(cusp, 1)); *C = itos(gel(cusp, 2)); break; case t_REAL: case t_COMPLEX: *A = 0; *C = 0; if (gsigne(imag_i(cusp)) <= 0) pari_err_DOMAIN("mfeval","imag(tau)","<=",gen_0,cusp); return 0; default: pari_err_TYPE("cusp_AC", cusp); } return 1; } static GEN cusp2mat(long A, long C) { long B, D; cbezout(A, C, &D, &B); return mkmat22s(A, -B, C, D); } static GEN mkS(void) { return mkmat22s(0,-1,1,0); } /* if t is a cusp, return F(t), else NULL */ static GEN evalcusp(GEN mf, GEN F, GEN t, long prec) { long A, C; GEN R; if (!cusp_AC(t, &A,&C)) return NULL; if (C % mf_get_N(F) == 0) return gel(mfcoefs_i(F, 0, 1), 1); R = mfgaexpansion(mf, F, cusp2mat(A,C), 0, prec); return gequal0(gel(R,1))? gmael(R,3,1): gen_0; } /* Evaluate an mf closure numerically, i.e., in the usual sense, either for a * single tau or a vector of tau; for each, return a vector of results * corresponding to all complex embeddings of F. If flag is nonzero, allow * replacing F by F | gamma to increase imag(gamma^(-1).tau) [ expensive if * MF_EISENSPACE not present ] */ static GEN mfeval_i(GEN mf, GEN F, GEN vtau, long flag, long bitprec) { GEN L0, vL, vb, sqN, vczd, vTAU, vs, van, vE; long N = MF_get_N(mf), N0, ta, lv, i, prec = nbits2prec(bitprec); GEN gN = utoipos(N), gk = mf_get_gk(F), gk1 = gsubgs(gk,1), vgk; long flscal = 0; /* gen_0 is ignored, second component assumes Ramanujan-Petersson in * 1/2-integer weight */ vgk = mkvec2(gen_0, mfiscuspidal(mf,F)? gmul2n(gk1,-1): gk1); ta = typ(vtau); if (!is_vec_t(ta)) { flscal = 1; vtau = mkvec(vtau); ta = t_VEC; } lv = lg(vtau); sqN = sqrtr_abs(utor(N, prec)); vs = const_vec(lv-1, NULL); vb = const_vec(lv-1, NULL); vL = cgetg(lv, t_VEC); vTAU = cgetg(lv, t_VEC); vczd = cgetg(lv, t_VEC); L0 = mfthetaancreate(NULL, gN, vgk); /* only for thetacost */ vE = mfgetembed(F, prec); N0 = 0; for (i = 1; i < lv; i++) { GEN z = gel(vtau,i), tau, U; long w, n; gel(vs,i) = evalcusp(mf, F, z, prec); if (gel(vs,i)) continue; tau = cxredga0N(N, z, &U, &gel(vczd,i), flag); if (!flag) w = 0; else { w = mfZC_width(N, gel(U,1)); tau = gdivgu(tau,w); } gel(vTAU,i) = mulcxmI(gmul(tau, sqN)); n = lfunthetacost(L0, real_i(gel(vTAU,i)), 0, bitprec); if (N0 < n) N0 = n; if (flag) { GEN A, al, v = mfslashexpansion(mf, F, ZM_inv(U,NULL), n, 0, &A, prec); gel(vL,i) = van_embedall(v, vE, gN, vgk); al = gel(A,1); if (!gequal0(al)) gel(vb,i) = gexp(gmul(gmul(gmulsg(w,al),PiI2(prec)), tau), prec); } } if (!flag) { van = mfcoefs_i(F, N0, 1); vL = const_vec(lv-1, van_embedall(van, vE, gN, vgk)); } for (i = 1; i < lv; i++) { GEN T; if (gel(vs,i)) continue; T = gpow(gel(vczd,i), gneg(gk), prec); if (flag && gel(vb,i)) T = gmul(T, gel(vb,i)); gel(vs,i) = lfunthetaall(T, gel(vL,i), gel(vTAU,i), bitprec); } return flscal? gel(vs,1): vs; } static long mfistrivial(GEN F) { switch(mf_get_type(F)) { case t_MF_CONST: return lg(gel(F,2)) == 1; case t_MF_LINEAR: case t_MF_LINEAR_BHN: return gequal0(gel(F,3)); default: return 0; } } static long mf_same_k(GEN mf, GEN f) { return gequal(MF_get_gk(mf), mf_get_gk(f)); } static long mf_same_CHI(GEN mf, GEN f) { GEN F1, F2, chi1, chi2, CHI1 = MF_get_CHI(mf), CHI2 = mf_get_CHI(f); /* are the primitive chars attached to CHI1 and CHI2 equal ? */ F1 = znconreyconductor(gel(CHI1,1), gel(CHI1,2), &chi1); if (typ(F1) == t_VEC) F1 = gel(F1,1); F2 = znconreyconductor(gel(CHI2,1), gel(CHI2,2), &chi2); if (typ(F2) == t_VEC) F2 = gel(F2,1); return equalii(F1,F2) && ZV_equal(chi1,chi2); } /* check k and CHI rigorously, but not coefficients nor N */ static long mfisinspace_i(GEN mf, GEN F) { return mfistrivial(F) || (mf_same_k(mf,F) && mf_same_CHI(mf,F)); } static void err_space(GEN F) { pari_err_DOMAIN("mftobasis", "form", "does not belong to", strtoGENstr("space"), F); } static long mfcheapeisen(GEN mf) { long k, L, N = MF_get_N(mf); GEN P; if (N <= 70) return 1; k = itos(gceil(MF_get_gk(mf))); if (odd(k)) k--; switch (k) { case 2: L = 190; break; case 4: L = 162; break; case 6: case 8: L = 88; break; case 10: L = 78; break; default: L = 66; break; } P = gel(myfactoru(N), 1); return P[lg(P)-1] <= L; } static GEN myimag_i(GEN tau) { long tc = typ(tau); if (tc == t_INFINITY || tc == t_INT || tc == t_FRAC) return gen_1; if (tc == t_VEC) { long ltau, i; GEN z = cgetg_copy(tau, <au); for (i=1; i 0) prec += nbits2prec(e); B = gsubst(B, v[i], rootsof1u_cx(ord, prec)); if (d) B = gdiv(B, d); break; } return B; } GEN mfeval(GEN mf0, GEN F, GEN vtau, long bitprec) { pari_sp av = avma; long flnew = 1; GEN mf = checkMF_i(mf0); if (!mf) pari_err_TYPE("mfeval", mf0); if (!checkmf_i(F)) pari_err_TYPE("mfeval", F); if (!mfisinspace_i(mf, F)) err_space(F); if (!obj_check(mf, MF_EISENSPACE)) flnew = mfcheapeisen(mf); if (flnew && gcmpgs(gmulsg(2*MF_get_N(mf), mintau(vtau)), 1) >= 0) flnew = 0; return gerepilecopy(av, mfeval_i(mf, F, vtau, flnew, bitprec)); } static long val(GEN v, long bit) { long c, l = lg(v); for (c = 1; c < l; c++) if (gexpo(gel(v,c)) > -bit) return c-1; return -1; } GEN mfcuspval(GEN mf, GEN F, GEN cusp, long bitprec) { pari_sp av = avma; long lvE, w, N, sb, n, A, C, prec = nbits2prec(bitprec); GEN ga, gk, vE; mf = checkMF(mf); if (!checkmf_i(F)) pari_err_TYPE("mfcuspval",F); N = MF_get_N(mf); cusp_canon(cusp, N, &A, &C); gk = mf_get_gk(F); if (typ(gk) != t_INT) { GEN FT = mfmultheta(F), mf2 = obj_checkbuild(mf, MF_MF2INIT, &mf2init); GEN r = mfcuspval(mf2, FT, cusp, bitprec); if ((C & 3L) == 2) { GEN z = uutoQ(1,4); r = gsub(r, typ(r) == t_VEC? const_vec(lg(r)-1, z): z); } return gerepileupto(av, r); } vE = mfgetembed(F, prec); lvE = lg(vE); w = mfcuspcanon_width(N, C); sb = w * mfsturmNk(N, itos(gk)); ga = cusp2mat(A,C); for (n = 8;; n = minss(sb, n << 1)) { GEN R = mfgaexpansion(mf, F, ga, n, prec), res = liftpol_shallow(gel(R,3)); GEN v = cgetg(lvE-1, t_VECSMALL); long j, ok = 1; res = RgC_embedall(res, vE); for (j = 1; j < lvE; j++) { v[j] = val(gel(res,j), bitprec/2); if (v[j] < 0) ok = 0; } if (ok) { res = cgetg(lvE, t_VEC); for (j = 1; j < lvE; j++) gel(res,j) = gadd(gel(R,1), uutoQ(v[j], w)); return gerepilecopy(av, lvE==2? gel(res,1): res); } if (n == sb) return lvE==2? mkoo(): const_vec(lvE-1, mkoo()); /* 0 */ } } long mfiscuspidal(GEN mf, GEN F) { pari_sp av = avma; GEN mf2; if (space_is_cusp(MF_get_space(mf))) return 1; if (typ(mf_get_gk(F)) == t_INT) { GEN v = mftobasis(mf,F,0), vE = vecslice(v, 1, lg(MF_get_E(mf))-1); return gc_long(av, gequal0(vE)); } if (!gequal0(mfak_i(F, 0))) return 0; mf2 = obj_checkbuild(mf, MF_MF2INIT, &mf2init); return mfiscuspidal(mf2, mfmultheta(F)); } /* F = vector of newforms in mftobasis format */ static GEN mffrickeeigen_i(GEN mf, GEN F, GEN vE, long prec) { GEN M, Z, L0, gN = MF_get_gN(mf), gk = MF_get_gk(mf); long N0, i, lM, bit = prec2nbits(prec), k = itou(gk); long LIM = 5; /* Sturm bound is enough */ L0 = mfthetaancreate(NULL, gN, gk); /* only for thetacost */ START: N0 = lfunthetacost(L0, gen_1, LIM, bit); M = mfcoefs_mf(mf, N0, 1); lM = lg(F); Z = cgetg(lM, t_VEC); for (i = 1; i < lM; i++) { /* expansion of D * F[i] */ GEN D, z, van = RgM_RgC_mul(M, Q_remove_denom(gel(F,i), &D)); GEN L = van_embedall(van, gel(vE,i), gN, gk); long l = lg(L), j, bit_add = D? expi(D): 0; gel(Z,i) = z = cgetg(l, t_VEC); for (j = 1; j < l; j++) { GEN v, C, C0; long m, e; for (m = 0; m <= LIM; m++) { v = lfuntheta(gmael(L,j,2), gen_1, m, bit); if (gexpo(v) > bit_add - bit/2) break; } if (m > LIM) { LIM <<= 1; goto START; } C = mulcxpowIs(gdiv(v,conj_i(v)), 2*m - k); C0 = grndtoi(C, &e); if (e < 5-prec2nbits(precision(C))) C = C0; gel(z,j) = C; } } return Z; } static GEN mffrickeeigen(GEN mf, GEN vE, long prec) { GEN D = obj_check(mf, MF_FRICKE); if (D) { long p = gprecision(D); if (!p || p >= prec) return D; } D = mffrickeeigen_i(mf, MF_get_newforms(mf), vE, prec); return obj_insert(mf, MF_FRICKE, D); } /* integral weight, new space for primitive quadratic character CHIP; * MF = vector of embedded eigenforms coefs on mfbasis, by orbit. * Assume N > Q > 1 and (Q,f(CHIP)) = 1 */ static GEN mfatkineigenquad(GEN mf, GEN CHIP, long Q, GEN MF, long bitprec) { GEN L0, la2, S, F, vP, tau, wtau, Z, va, vb, den, coe, sqrtQ, sqrtN; GEN M, gN, gk = MF_get_gk(mf); long N0, x, yq, i, j, lF, dim, muQ, prec = nbits2prec(bitprec); long N = MF_get_N(mf), k = itos(gk), NQ = N / Q; /* Q coprime to FC */ F = MF_get_newforms(mf); vP = MF_get_fields(mf); lF = lg(F); Z = cgetg(lF, t_VEC); S = MF_get_S(mf); dim = lg(S) - 1; muQ = mymoebiusu(Q); if (muQ) { GEN SQ = cgetg(dim+1,t_VEC), Qk = gpow(stoi(Q), sstoQ(k-2, 2), prec); long i, bit2 = bitprec >> 1; for (j = 1; j <= dim; j++) gel(SQ,j) = mfak_i(gel(S,j), Q); for (i = 1; i < lF; i++) { GEN S = RgV_dotproduct(gel(F,i), SQ), T = gel(vP,i); long e; if (degpol(T) > 1 && typ(S) != t_POLMOD) S = gmodulo(S, T); S = grndtoi(gdiv(conjvec(S, prec), Qk), &e); if (e > -bit2) pari_err_PREC("mfatkineigenquad"); if (muQ == -1) S = gneg(S); gel(Z,i) = S; } return Z; } la2 = mfchareval(CHIP, Q); /* 1 or -1 */ (void)cbezout(Q, NQ, &x, &yq); sqrtQ = sqrtr_abs(utor(Q,prec)); tau = mkcomplex(gadd(sstoQ(-1, NQ), uutoQ(1, 1000)), divru(sqrtQ, N)); den = gaddgs(gmulsg(NQ, tau), 1); wtau = gdiv(gsub(gmulsg(x, tau), sstoQ(yq, Q)), den); coe = gpowgs(gmul(sqrtQ, den), k); sqrtN = sqrtr_abs(utor(N,prec)); tau = mulcxmI(gmul(tau, sqrtN)); wtau = mulcxmI(gmul(wtau, sqrtN)); gN = utoipos(N); L0 = mfthetaancreate(NULL, gN, gk); /* only for thetacost */ N0 = maxss(lfunthetacost(L0,real_i(tau), 0,bitprec), lfunthetacost(L0,real_i(wtau),0,bitprec)); M = mfcoefs_mf(mf, N0, 1); va = cgetg(dim+1, t_VEC); vb = cgetg(dim+1, t_VEC); for (j = 1; j <= dim; j++) { GEN L, v = vecslice(gel(M,j), 2, N0+1); /* remove a0 */ settyp(v, t_VEC); L = mfthetaancreate(v, gN, gk); gel(va,j) = lfuntheta(L, tau,0,bitprec); gel(vb,j) = lfuntheta(L,wtau,0,bitprec); } for (i = 1; i < lF; i++) { GEN z, FE = gel(MF,i); long l = lg(FE); z = cgetg(l, t_VEC); for (j = 1; j < l; j++) { GEN f = gel(FE,j), a = RgV_dotproduct(va,f), b = RgV_dotproduct(vb,f); GEN la = ground( gdiv(b, gmul(a,coe)) ); if (!gequal(gsqr(la), la2)) pari_err_PREC("mfatkineigenquad"); if (typ(la) == t_INT) { if (j != 1) pari_err_BUG("mfatkineigenquad"); z = const_vec(l-1, la); break; } gel(z,j) = la; } gel(Z,i) = z; } return Z; } static GEN myusqrt(ulong a, long prec) { if (a == 1UL) return gen_1; if (uissquareall(a, &a)) return utoipos(a); return sqrtr_abs(utor(a, prec)); } /* Assume mf is a nontrivial new space, rational primitive character CHIP * and (Q,FC) = 1 */ static GEN mfatkinmatnewquad(GEN mf, GEN CHIP, long Q, long flag, long PREC) { GEN cM, M, D, MF, den, vE, F = MF_get_newforms(mf); long i, c, e, prec, bitprec, lF = lg(F), N = MF_get_N(mf), k = MF_get_k(mf); if (Q == 1) return mkvec4(gen_0, matid(MF_get_dim(mf)), gen_1, mf); den = gel(MF_get_Minv(mf), 2); bitprec = expi(den) + 64; if (!flag) bitprec = maxss(bitprec, prec2nbits(PREC)); START: prec = nbits2prec(bitprec); vE = mfeigenembed(mf, prec); M = cgetg(lF, t_VEC); for (i = 1; i < lF; i++) gel(M,i) = RgC_embedall(gel(F,i), gel(vE,i)); if (Q != N) { D = mfatkineigenquad(mf, CHIP, Q, M, bitprec); c = odd(k)? Q: 1; } else { D = mffrickeeigen(mf, vE, prec); c = mfcharmodulus(CHIP); if (odd(k)) c = -Q/c; } D = shallowconcat1(D); if (vec_isconst(D)) { MF = diagonal_shallow(D); flag = 0; } else { M = shallowconcat1(M); MF = RgM_mul(matmuldiagonal(M,D), ginv(M)); } if (!flag) return mkvec4(gen_0, MF, gen_1, mf); if (c > 0) cM = myusqrt(c, PREC); else { MF = imag_i(MF); c = -c; cM = mkcomplex(gen_0, myusqrt(c,PREC)); } if (c != 1) MF = RgM_Rg_mul(MF, myusqrt(c,prec)); MF = grndtoi(RgM_Rg_mul(MF,den), &e); if (e > -32) { bitprec <<= 1; goto START; } MF = RgM_Rg_div(MF, den); if (is_rational_t(typ(cM)) && !isint1(cM)) { MF = RgM_Rg_div(MF, cM); cM = gen_1; } return mkvec4(gen_0, MF, cM, mf); } /* let CHI mod N, Q || N, return \bar{CHI_Q} * CHI_{N/Q} */ static GEN mfcharAL(GEN CHI, long Q) { GEN G = gel(CHI,1), c = gel(CHI,2), cycc, d, P, E, F; long l = lg(c), N = mfcharmodulus(CHI), i; if (N == Q) return mfcharconj(CHI); if (N == 1) return CHI; CHI = leafcopy(CHI); gel(CHI,2) = d = leafcopy(c); F = znstar_get_faN(G); P = gel(F,1); E = gel(F,2); cycc = znstar_get_conreycyc(G); if (!odd(Q) && equaliu(gel(P,1), 2) && E[1] >= 3) gel(d,2) = Fp_neg(gel(d,2), gel(cycc,2)); else for (i = 1; i < l; i++) if (!umodui(Q, gel(P,i))) gel(d,i) = Fp_neg(gel(d,i), gel(cycc,i)); return CHI; } static long atkin_get_NQ(long N, long Q, const char *f) { long NQ = N / Q; if (N % Q) pari_err_DOMAIN(f,"N % Q","!=",gen_0,utoi(Q)); if (ugcd(NQ, Q) > 1) pari_err_DOMAIN(f,"gcd(Q,N/Q)","!=",gen_1,utoi(Q)); return NQ; } /* transform mf to new_NEW if possible */ static GEN MF_set_new(GEN mf) { GEN vMjd, vj, gk = MF_get_gk(mf); long l, j; if (MF_get_space(mf) != mf_CUSP || typ(gk) != t_INT || itou(gk) == 1) return mf; vMjd = MFcusp_get_vMjd(mf); l = lg(vMjd); if (l > 1 && gel(vMjd,1)[1] != MF_get_N(mf)) return mf; /* oldspace != 0 */ mf = shallowcopy(mf); gel(mf,1) = shallowcopy(gel(mf,1)); MF_set_space(mf, mf_NEW); vj = cgetg(l, t_VECSMALL); for (j = 1; j < l; j++) vj[j] = gel(vMjd, j)[2]; gel(mf,4) = vj; return mf; } /* if flag = 1, rationalize, else don't */ static GEN mfatkininit_i(GEN mf, long Q, long flag, long prec) { GEN M, B, C, CHI, CHIAL, G, chi, P, z, g, mfB, s, Mindex, Minv; long j, l, lim, ord, FC, NQ, cQ, nk, dk, N = MF_get_N(mf); B = MF_get_basis(mf); l = lg(B); M = cgetg(l, t_MAT); if (l == 1) return mkvec4(gen_0,M,gen_1,mf); Qtoss(MF_get_gk(mf), &nk,&dk); Q = labs(Q); NQ = atkin_get_NQ(N, Q, "mfatkininit"); CHI = MF_get_CHI(mf); CHI = mfchartoprimitive(CHI, &FC); ord = mfcharorder(CHI); mf = MF_set_new(mf); if (MF_get_space(mf) == mf_NEW && ord <= 2 && NQ % FC == 0 && dk == 1) return mfatkinmatnewquad(mf, CHI, Q, flag, prec); /* now flag != 0 */ G = gel(CHI,1); chi = gel(CHI,2); if (Q == N) { g = mkmat22s(0, -1, N, 0); cQ = NQ; } /* Fricke */ else { GEN F, gQP = utoi(ugcd(Q, FC)); long t, v; chi = znchardecompose(G, chi, gQP); F = znconreyconductor(G, chi, &chi); G = znstar0(F,1); (void)cbezout(Q, NQ, &t, &v); g = mkmat22s(Q*t, 1, -N*v, Q); cQ = -NQ*v; } C = s = gen_1; /* N.B. G,chi are G_Q,chi_Q [primitive] at this point */ if (lg(chi) != 1) C = ginv( znchargauss(G, chi, gen_1, prec2nbits(prec)) ); if (dk == 1) { if (odd(nk)) s = myusqrt(Q,prec); } else { long r = nk >> 1; /* k-1/2 */ s = gpow(utoipos(Q), mkfracss(odd(r)? 1: 3, 4), prec); if (odd(cQ)) { long t = r + ((cQ-1) >> 1); s = mkcomplex(s, odd(t)? gneg(s): s); } } if (!isint1(s)) C = gmul(C, s); CHIAL = mfcharAL(CHI, Q); if (dk == 2) { ulong q = odd(Q)? Q << 2: Q, Nq = ulcm(q, mfcharmodulus(CHIAL)); CHIAL = induceN(Nq, CHIAL); CHIAL = mfcharmul(CHIAL, induce(gel(CHIAL,1), utoipos(q))); } CHIAL = mfchartoprimitive(CHIAL,NULL); mfB = gequal(CHIAL,CHI)? mf: mfinit_Nndkchi(N,nk,dk,CHIAL,MF_get_space(mf),0); Mindex = MF_get_Mindex(mfB); Minv = MF_get_Minv(mfB); P = z = NULL; if (ord > 2) { P = mfcharpol(CHI); z = rootsof1u_cx(ord, prec); } lim = maxss(mfsturm(mfB), mfsturm(mf)) + 1; for (j = 1; j < l; j++) { GEN v = mfslashexpansion(mf, gel(B,j), g, lim, 0, NULL, prec+EXTRAPREC64); long junk; if (!isint1(C)) v = RgV_Rg_mul(v, C); v = bestapprnf(v, P, z, prec); v = vecpermute_partial(v, Mindex, &junk); v = Minv_RgC_mul(Minv, v); /* cf mftobasis_i */ gel(M, j) = v; } if (is_rational_t(typ(C)) && !gequal1(C)) { M = gdiv(M, C); C = gen_1; } if (mfB == mf) mfB = gen_0; return mkvec4(mfB, M, C, mf); } GEN mfatkininit(GEN mf, long Q, long prec) { pari_sp av = avma; mf = checkMF(mf); return gerepilecopy(av, mfatkininit_i(mf, Q, 1, prec)); } static void checkmfa(GEN z) { if (typ(z) != t_VEC || lg(z) != 5 || typ(gel(z,2)) != t_MAT || !checkMF_i(gel(z,4)) || (!isintzero(gel(z,1)) && !checkMF_i(gel(z,1)))) pari_err_TYPE("mfatkin [please apply mfatkininit()]",z); } /* Apply atkin Q to closure F */ GEN mfatkin(GEN mfa, GEN F) { pari_sp av = avma; GEN z, mfB, MQ, mf; checkmfa(mfa); mfB= gel(mfa,1); MQ = gel(mfa,2); mf = gel(mfa,4); if (typ(mfB) == t_INT) mfB = mf; z = RgM_RgC_mul(MQ, mftobasis_i(mf,F)); return gerepileupto(av, mflinear(mfB, z)); } GEN mfatkineigenvalues(GEN mf, long Q, long prec) { pari_sp av = avma; GEN vF, L, CHI, M, mfatk, C, MQ, vE, mfB; long N, NQ, l, i; mf = checkMF(mf); N = MF_get_N(mf); vF = MF_get_newforms(mf); l = lg(vF); /* N.B. k is integral */ if (l == 1) { set_avma(av); return cgetg(1, t_VEC); } L = cgetg(l, t_VEC); if (Q == 1) { GEN vP = MF_get_fields(mf); for (i = 1; i < l; i++) gel(L,i) = const_vec(degpol(gel(vP,i)), gen_1); return L; } vE = mfeigenembed(mf,prec); if (Q == N) return gerepileupto(av, mffrickeeigen(mf, vE, prec)); Q = labs(Q); NQ = atkin_get_NQ(N, Q, "mfatkineigenvalues"); /* != 1 */ mfatk = mfatkininit(mf, Q, prec); mfB= gel(mfatk,1); if (typ(mfB) != t_VEC) mfB = mf; MQ = gel(mfatk,2); C = gel(mfatk,3); M = row(mfcoefs_mf(mfB,1,1), 2); /* vec of a_1(b_i) for mfbasis functions */ for (i = 1; i < l; i++) { GEN c = RgV_dotproduct(RgM_RgC_mul(MQ,gel(vF,i)), M); /* C * eigen_i */ gel(L,i) = Rg_embedall_i(c, gel(vE,i)); } if (!gequal1(C)) L = gdiv(L, C); CHI = MF_get_CHI(mf); if (mfcharorder(CHI) <= 2 && NQ % mfcharconductor(CHI) == 0) L = ground(L); return gerepilecopy(av, L); } /* expand B_d V, keeping same length */ static GEN bdexpand(GEN V, long d) { GEN W; long N, n; if (d == 1) return V; N = lg(V)-1; W = zerovec(N); for (n = 0; n <= (N-1)/d; n++) gel(W, n*d+1) = gel(V, n+1); return W; } /* expand B_d V, increasing length up to lim */ static GEN bdexpandall(GEN V, long d, long lim) { GEN W; long N, n; if (d == 1) return V; N = lg(V)-1; W = zerovec(lim); for (n = 0; n <= N-1 && n*d <= lim; n++) gel(W, n*d+1) = gel(V, n+1); return W; } static void parse_vecj(GEN T, GEN *E1, GEN *E2) { if (lg(T)==3) { *E1 = gel(T,1); *E2 = gel(T,2); } else { *E1 = T; *E2 = NULL; } } /* g in M_2(Z) ? */ static int check_M2Z(GEN g) { return typ(g) == t_MAT && lg(g) == 3 && lgcols(g) == 3 && RgM_is_ZM(g); } /* g in SL_2(Z) ? */ static int check_SL2Z(GEN g) { return check_M2Z(g) && equali1(ZM_det(g)); } static GEN mfcharcxeval(GEN CHI, long n, long prec) { ulong ord, N = mfcharmodulus(CHI); GEN ordg; if (N == 1) return gen_1; if (ugcd(N, labs(n)) > 1) return gen_0; ordg = gmfcharorder(CHI); ord = itou(ordg); return rootsof1q_cx(znchareval_i(CHI,n,ordg), ord, prec); } static GEN RgV_shift(GEN V, GEN gn) { long i, n, l; GEN W; if (typ(gn) != t_INT) pari_err_BUG("RgV_shift [n not integral]"); n = itos(gn); if (n < 0) pari_err_BUG("RgV_shift [n negative]"); if (!n) return V; W = cgetg_copy(V, &l); if (n > l-1) n = l-1; for (i=1; i <= n; i++) gel(W,i) = gen_0; for ( ; i < l; i++) gel(W,i) = gel(V, i-n); return W; } static GEN hash_eisengacx(hashtable *H, void *E, long w, GEN ga, long n, long prec) { ulong h = H->hash(E); hashentry *e = hash_search2(H, E, h); GEN v; if (e) v = (GEN)e->val; else { v = mfeisensteingacx((GEN)E, w, ga, n, prec); hash_insert2(H, E, (void*)v, h); } return v; } static GEN vecj_expand(GEN B, hashtable *H, long w, GEN ga, long n, long prec) { GEN E1, E2, v; parse_vecj(B, &E1, &E2); v = hash_eisengacx(H, (void*)E1, w, ga, n, prec); if (E2) { GEN u = hash_eisengacx(H, (void*)E2, w, ga, n, prec); GEN a = gadd(gel(v,1), gel(u,1)); GEN b = RgV_mul_RgXn(gel(v,2), gel(u,2)); v = mkvec2(a,b); } return v; } static GEN shift_M(GEN M, GEN Valpha, long w) { long i, l = lg(Valpha); GEN almin = vecmin(Valpha); for (i = 1; i < l; i++) { GEN alpha = gel(Valpha, i), gsh = gmulsg(w, gsub(alpha,almin)); gel(M,i) = RgV_shift(gel(M,i), gsh); } return almin; } static GEN mfeisensteinspaceinit(GEN NK); #if 0 /* ga in M_2^+(Z)), n >= 0 */ static GEN mfgaexpansion_init(GEN mf, GEN ga, long n, long prec) { GEN M, Mvecj, vecj, almin, Valpha; long i, w, l, N = MF_get_N(mf), c = itos(gcoeff(ga,2,1)); hashtable *H; if (c % N == 0) { /* ga in G_0(N), trivial case; w = 1 */ GEN chid = mfcharcxeval(MF_get_CHI(mf), itos(gcoeff(ga,2,2)), prec); return mkvec2(chid, utoi(n)); } Mvecj = obj_checkbuild(mf, MF_EISENSPACE, &mfeisensteinspaceinit); if (lg(Mvecj) < 5) pari_err_IMPL("mfgaexpansion_init in this case"); w = mfcuspcanon_width(N, c); vecj = gel(Mvecj, 3); l = lg(vecj); M = cgetg(l, t_VEC); Valpha = cgetg(l, t_VEC); H = hash_create(l, (ulong(*)(void*))&hash_GEN, (int(*)(void*,void*))&gidentical, 1); for (i = 1; i < l; i++) { GEN v = vecj_expand(gel(vecj,i), H, w, ga, n, prec); gel(Valpha,i) = gel(v,1); gel(M,i) = gel(v,2); } almin = shift_M(M, Valpha, w); return mkvec3(almin, utoi(w), M); } /* half-integer weight not supported; vF = [F,eisendec(F)]. * Minit = mfgaexpansion_init(mf, ga, n, prec) */ static GEN mfgaexpansion_with_init(GEN Minit, GEN vF) { GEN v; if (lg(Minit) == 3) { /* ga in G_0(N) */ GEN chid = gel(Minit,1), gn = gel(Minit,2); v = mfcoefs_i(gel(vF,1), itou(gn), 1); v = mkvec3(gen_0, gen_1, RgV_Rg_mul(v,chid)); } else { GEN V = RgM_RgC_mul(gel(Minit,3), gel(vF,2)); v = mkvec3(gel(Minit,1), gel(Minit,2), V); } return v; } #endif /* B = mfeisensteindec(F) already embedded, ga in M_2^+(Z)), n >= 0 */ static GEN mfgaexpansion_i(GEN mf, GEN B0, GEN ga, long n, long prec) { GEN M, Mvecj, vecj, almin, Valpha, B, E = NULL; long i, j, w, nw, l, N = MF_get_N(mf), bit = prec2nbits(prec) / 2; hashtable *H; Mvecj = obj_check(mf, MF_EISENSPACE); if (lg(Mvecj) < 5) { E = gel(Mvecj, 2); Mvecj = gel(Mvecj, 1); } vecj = gel(Mvecj, 3); l = lg(vecj); B = cgetg(l, t_COL); M = cgetg(l, t_VEC); Valpha = cgetg(l, t_VEC); w = mfZC_width(N, gel(ga,1)); nw = E ? n + w : n; H = hash_create(l, (ulong(*)(void*))&hash_GEN, (int(*)(void*,void*))&gidentical, 1); for (i = j = 1; i < l; i++) { GEN v; if (gequal0(gel(B0,i))) continue; v = vecj_expand(gel(vecj,i), H, w, ga, nw, prec); gel(B,j) = gel(B0,i); gel(Valpha,j) = gel(v,1); gel(M,j) = gel(v,2); j++; } setlg(Valpha, j); setlg(B, j); setlg(M, j); l = j; if (l == 1) return mkvec3(gen_0, utoi(w), zerovec(n+1)); almin = shift_M(M, Valpha, w); B = RgM_RgC_mul(M, B); l = lg(B); for (i = 1; i < l; i++) if (gexpo(gel(B,i)) < -bit) gel(B,i) = gen_0; settyp(B, t_VEC); if (E) { GEN v, e; long ell = 0, vB, ve; for (i = 1; i < l; i++) if (!gequal0(gel(B,i))) break; vB = i-1; v = hash_eisengacx(H, (void*)E, w, ga, n + vB, prec); e = gel(v,2); l = lg(e); for (i = 1; i < l; i++) if (!gequal0(gel(e,i))) break; ve = i-1; almin = gsub(almin, gel(v,1)); if (gsigne(almin) < 0) { GEN gell = gceil(gmulsg(-w, almin)); ell = itos(gell); almin = gadd(almin, gdivgu(gell, w)); if (nw < ell) pari_err_IMPL("alpha < 0 in mfgaexpansion"); } if (ve) { ell += ve; e = vecslice(e, ve+1, l-1); } B = vecslice(B, ell + 1, minss(n + ell + 1, lg(B)-1)); B = RgV_div_RgXn(B, e); } return mkvec3(almin, utoi(w), B); } /* Theta multiplier: assume 4 | C, (C,D)=1 */ static GEN mfthetamultiplier(GEN C, GEN D) { long s = kronecker(C, D); if (Mod4(D) == 1) return s > 0 ? gen_1: gen_m1; return s > 0? powIs(3): gen_I(); } /* theta | [*,*;C,D] defined over Q(i) [else over Q] */ static int mfthetaI(long C, long D) { return odd(C) || (D & 3) == 3; } /* (theta | M) [0..n], assume (C,D) = 1 */ static GEN mfthetaexpansion(GEN M, long n) { GEN w, s, al, sla, E, V = zerovec(n+1), C = gcoeff(M,2,1), D = gcoeff(M,2,2); long lim, la, f, C4 = Mod4(C); switch (C4) { case 0: al = gen_0; w = gen_1; s = mfthetamultiplier(C,D); lim = usqrt(n); gel(V, 1) = s; s = gmul2n(s, 1); for (f = 1; f <= lim; f++) gel(V, f*f + 1) = s; break; case 2: al = uutoQ(1,4); w = gen_1; E = subii(C, shifti(D,1)); /* (E, D) = 1 */ s = gmul2n(mfthetamultiplier(E, D), 1); if ((!signe(E) && equalim1(D)) || (signe(E) > 0 && signe(C) < 0)) s = gneg(s); lim = (usqrt(n << 2) - 1) >> 1; for (f = 0; f <= lim; f++) gel(V, f*(f+1) + 1) = s; break; default: al = gen_0; w = utoipos(4); la = (-Mod4(D)*C4) & 3L; E = negi(addii(D, mului(la, C))); s = mfthetamultiplier(E, C); /* (E,C) = 1 */ if (signe(C) < 0 && signe(E) >= 0) s = gneg(s); s = gsub(s, mulcxI(s)); sla = gmul(s, powIs(-la)); lim = usqrt(n); gel(V, 1) = gmul2n(s, -1); for (f = 1; f <= lim; f++) gel(V, f*f + 1) = odd(f) ? sla : s; break; } return mkvec3(al, w, V); } /* F 1/2 integral weight */ static GEN mf2gaexpansion(GEN mf2, GEN F, GEN ga, long n, long prec) { GEN FT = mfmultheta(F), mf = obj_checkbuild(mf2, MF_MF2INIT, &mf2init); GEN res, V1, Tres, V2, al, V, gsh, C = gcoeff(ga,2,1); long w2, N = MF_get_N(mf), w = mfcuspcanon_width(N, umodiu(C,N)); long ext = (Mod4(C) != 2)? 0: (w+3) >> 2; long prec2 = prec + nbits2extraprec((long)M_PI/(2*M_LN2)*sqrt(n + ext)); res = mfgaexpansion(mf, FT, ga, n + ext, prec2); Tres = mfthetaexpansion(ga, n + ext); V1 = gel(res,3); V2 = gel(Tres,3); al = gsub(gel(res,1), gel(Tres,1)); w2 = itos(gel(Tres,2)); if (w != itos(gel(res,2)) || w % w2) pari_err_BUG("mf2gaexpansion [incorrect w2 or w]"); if (w2 != w) V2 = bdexpand(V2, w/w2); V = RgV_div_RgXn(V1, V2); gsh = gfloor(gmulsg(w, al)); if (!gequal0(gsh)) { al = gsub(al, gdivgu(gsh, w)); if (gsigne(gsh) > 0) { V = RgV_shift(V, gsh); V = vecslice(V, 1, n + 1); } else { long sh = -itos(gsh), i; if (sh > ext) pari_err_BUG("mf2gaexpansion [incorrect sh]"); for (i = 1; i <= sh; i++) if (!gequal0(gel(V,i))) pari_err_BUG("mf2gaexpansion [sh too large]"); V = vecslice(V, sh+1, n + sh+1); } } obj_free(mf); return mkvec3(al, stoi(w), gprec_wtrunc(V, prec)); } static GEN mfgaexpansionatkin(GEN mf, GEN F, GEN C, GEN D, long Q, long n, long prec) { GEN mfa = mfatkininit_i(mf, Q, 0, prec), MQ = gel(mfa,2); long i, FC, k = MF_get_k(mf); GEN x, v, V, z, s, CHI = mfchartoprimitive(MF_get_CHI(mf), &FC); /* V = mfcoefs(F | w_Q, n), can't use mfatkin because MQ nonrational */ V = RgM_RgC_mul(mfcoefs_mf(mf,n,1), RgM_RgC_mul(MQ, mftobasis_i(mf,F))); (void)bezout(utoipos(Q), C, &x, &v); s = mfchareval(CHI, (umodiu(x, FC) * umodiu(D, FC)) % FC); s = gdiv(s, gpow(utoipos(Q), uutoQ(k,2), prec)); V = RgV_Rg_mul(V, s); z = rootsof1powinit(umodiu(D,Q)*umodiu(v,Q) % Q, Q, prec); for (i = 1; i <= n+1; i++) gel(V,i) = gmul(gel(V,i), rootsof1pow(z, i-1)); return mkvec3(gen_0, utoipos(Q), V); } static long inveis_extraprec(long N, GEN ga, GEN Mvecj, long n) { long e, w = mfZC_width(N, gel(ga,1)); GEN f, E = gel(Mvecj,2), v = mfeisensteingacx(E, w, ga, n, DEFAULTPREC); v = gel(v,2); f = RgV_to_RgX(v,0); n -= RgX_valrem(f, &f); e = gexpo(RgXn_inv(f, n+1)); return (e > 0)? nbits2extraprec(e): 0; } /* allow F of the form [F, mf_eisendec(F)]~ */ static GEN mfgaexpansion(GEN mf, GEN F, GEN ga, long n, long prec) { GEN v, EF = NULL, res, Mvecj, c, d; long precnew, N; if (n < 0) pari_err_DOMAIN("mfgaexpansion", "n", "<", gen_0, stoi(n)); if (typ(F) == t_COL && lg(F) == 3) { EF = gel(F,2); F = gel(F,1); } if (!checkmf_i(F)) pari_err_TYPE("mfgaexpansion", F); if (!check_SL2Z(ga)) pari_err_TYPE("mfgaexpansion",ga); if (typ(mf_get_gk(F)) != t_INT) return mf2gaexpansion(mf, F, ga, n, prec); c = gcoeff(ga,2,1); d = gcoeff(ga,2,2); N = MF_get_N(mf); if (!umodiu(c, mf_get_N(F))) { /* trivial case: ga in Gamma_0(N) */ long w = mfcuspcanon_width(N, umodiu(c,N)); GEN CHI = mf_get_CHI(F); GEN chid = mfcharcxeval(CHI, umodiu(d,mfcharmodulus(CHI)), prec); v = mfcoefs_i(F, n/w, 1); if (!isint1(chid)) v = RgV_Rg_mul(v,chid); return mkvec3(gen_0, stoi(w), bdexpandall(v,w,n+1)); } mf = MF_set_new(mf); if (MF_get_space(mf) == mf_NEW) { long cN = umodiu(c,N), g = ugcd(cN,N), Q = N/g; GEN CHI = MF_get_CHI(mf); if (ugcd(cN, Q)==1 && mfcharorder(CHI) <= 2 && g % mfcharconductor(CHI) == 0 && degpol(mf_get_field(F)) == 1) return mfgaexpansionatkin(mf, F, c, d, Q, n, prec); } Mvecj = obj_checkbuild(mf, MF_EISENSPACE, &mfeisensteinspaceinit); precnew = prec; if (lg(Mvecj) < 5) precnew += inveis_extraprec(N, ga, Mvecj, n); if (!EF) EF = mf_eisendec(mf, F, precnew); res = mfgaexpansion_i(mf, EF, ga, n, precnew); return precnew == prec ? res : gprec_wtrunc(res, prec); } /* parity = -1 or +1 */ static GEN findd(long N, long parity) { GEN L, D = mydivisorsu(N); long i, j, l = lg(D); L = cgetg(l, t_VEC); for (i = j = 1; i < l; i++) { long d = D[i]; if (parity == -1) d = -d; if (sisfundamental(d)) gel(L,j++) = stoi(d); } setlg(L,j); return L; } /* does ND contain a divisor of N ? */ static int seenD(long N, GEN ND) { long j, l = lg(ND); for (j = 1; j < l; j++) if (N % ND[j] == 0) return 1; return 0; } static GEN search_levels(GEN vN, const char *f) { switch(typ(vN)) { case t_INT: vN = mkvecsmall(itos(vN)); break; case t_VEC: case t_COL: vN = ZV_to_zv(vN); break; case t_VECSMALL: vN = leafcopy(vN); break; default: pari_err_TYPE(f, vN); } vecsmall_sort(vN); return vN; } GEN mfsearch(GEN NK, GEN V, long space) { pari_sp av = avma; GEN F, gk, NbyD, vN; long n, nk, dk, parity, nV, i, lvN; if (typ(NK) != t_VEC || lg(NK) != 3) pari_err_TYPE("mfsearch", NK); gk = gel(NK,2); if (typ(gmul2n(gk, 1)) != t_INT) pari_err_TYPE("mfsearch [k]", gk); switch(typ(V)) { case t_VEC: V = shallowtrans(V); case t_COL: break; default: pari_err_TYPE("mfsearch [V]", V); } vN = search_levels(gel(NK,1), "mfsearch [N]"); if (gequal0(V)) { set_avma(av); retmkvec(mftrivial()); } lvN = lg(vN); Qtoss(gk, &nk,&dk); parity = (dk == 1 && odd(nk)) ? -1 : 1; nV = lg(V)-2; F = cgetg(1, t_VEC); NbyD = const_vec(vN[lvN-1], cgetg(1,t_VECSMALL)); for (n = 1; n < lvN; n++) { long N = vN[n]; GEN L; if (N <= 0 || (dk == 2 && (N & 3))) continue; L = findd(N, parity); for (i = 1; i < lg(L); i++) { GEN mf, M, CO, gD = gel(L,i); GEN *ND = (GEN*)NbyD + itou(gD); /* points to NbyD[|D|] */ if (seenD(N, *ND)) continue; mf = mfinit_Nndkchi(N, nk, dk, get_mfchar(gD), space, 1); M = mfcoefs_mf(mf, nV, 1); CO = inverseimage(M, V); if (lg(CO) == 1) continue; F = vec_append(F, mflinear(mf,CO)); *ND = vecsmall_append(*ND, N); /* add to NbyD[|D|] */ } } return gerepilecopy(av, F); } static GEN search_from_split(GEN mf, GEN vap, GEN vlp) { pari_sp av = avma; long lvlp = lg(vlp), j, jv, l1; GEN v, NK, S1, S, M = NULL; S1 = gel(split_i(mf, 1, 0), 1); /* rational newforms */ l1 = lg(S1); if (l1 == 1) return gc_NULL(av); v = cgetg(l1, t_VEC); S = MF_get_S(mf); NK = mf_get_NK(gel(S,1)); if (lvlp > 1) M = rowpermute(mfcoefs_mf(mf, vlp[lvlp-1], 1), vlp); for (j = jv = 1; j < l1; j++) { GEN vF = gel(S1,j); long t; for (t = lvlp-1; t > 0; t--) { /* lhs = vlp[j]-th coefficient of eigenform */ GEN rhs = gel(vap,t), lhs = RgMrow_RgC_mul(M, vF, t); if (!gequal(lhs, rhs)) break; } if (!t) gel(v,jv++) = mflinear_i(NK,S,vF); } if (jv == 1) return gc_NULL(av); setlg(v,jv); return v; } GEN mfeigensearch(GEN NK, GEN AP) { pari_sp av = avma; GEN k, vN, vap, vlp, vres = cgetg(1, t_VEC), D; long n, lvN, i, l, even; if (!AP) l = 1; else { l = lg(AP); if (typ(AP) != t_VEC) pari_err_TYPE("mfeigensearch",AP); } vap = cgetg(l, t_VEC); vlp = cgetg(l, t_VECSMALL); if (l > 1) { GEN perm = indexvecsort(AP, mkvecsmall(1)); for (i = 1; i < l; i++) { GEN v = gel(AP,perm[i]), gp, ap; if (typ(v) != t_VEC || lg(v) != 3) pari_err_TYPE("mfeigensearch", AP); gp = gel(v,1); ap = gel(v,2); if (typ(gp) != t_INT || (typ(ap) != t_INT && typ(ap) != t_INTMOD)) pari_err_TYPE("mfeigensearch", AP); gel(vap,i) = ap; vlp[i] = itos(gp)+1; if (vlp[i] < 0) pari_err_TYPE("mfeigensearch", AP); } } l = lg(NK); if (typ(NK) != t_VEC || l != 3) pari_err_TYPE("mfeigensearch",NK); k = gel(NK,2); vN = search_levels(gel(NK,1), "mfeigensearch [N]"); lvN = lg(vN); vecsmall_sort(vlp); even = !mpodd(k); for (n = 1; n < lvN; n++) { pari_sp av2 = avma; GEN mf, L; long N = vN[n]; if (even) D = gen_1; else { long r = (N&3L); if (r == 1 || r == 2) continue; D = stoi( corediscs(-N, NULL) ); /* < 0 */ } mf = mfinit_i(mkvec3(utoipos(N), k, D), mf_NEW); L = search_from_split(mf, vap, vlp); if (L) vres = shallowconcat(vres, L); else set_avma(av2); } return gerepilecopy(av, vres); } /* tf_{N,k}(n) */ static GEN mfnewtracecache(long N, long k, long n, cachenew_t *cache) { GEN C = NULL, S; long lcache; if (!n) return gen_0; S = gel(cache->vnew,N); lcache = lg(S); if (n < lcache) C = gel(S, n); if (C) cache->newHIT++; else C = mfnewtrace_i(N,k,n,cache); cache->newTOTAL++; if (n < lcache) gel(S,n) = C; return C; } static long mfdim_Nkchi(long N, long k, GEN CHI, long space) { if (k < 0 || badchar(N,k,CHI)) return 0; if (k == 0) return mfcharistrivial(CHI) && !space_is_cusp(space)? 1: 0; switch(space) { case mf_NEW: return mfnewdim(N,k,CHI); case mf_CUSP:return mfcuspdim(N,k,CHI); case mf_OLD: return mfolddim(N,k,CHI); case mf_FULL:return mffulldim(N,k,CHI); case mf_EISEN: return mfeisensteindim(N,k,CHI); default: pari_err_FLAG("mfdim"); } return 0;/*LCOV_EXCL_LINE*/ } static long mf1dimsum(long N, long space) { switch(space) { case mf_NEW: return mf1newdimsum(N); case mf_CUSP: return mf1cuspdimsum(N); case mf_OLD: return mf1olddimsum(N); } pari_err_FLAG("mfdim"); return 0; /*LCOV_EXCL_LINE*/ } /* mfdim for k = nk/dk */ static long mfdim_Nndkchi(long N, long nk, long dk, GEN CHI, long space) { return (dk == 2)? mf2dim_Nkchi(N, nk >> 1, CHI, space) : mfdim_Nkchi(N, nk, CHI, space); } /* FIXME: use direct dim Gamma1(N) formula, don't compute individual spaces */ static long mfkdimsum(long N, long k, long dk, long space) { GEN w = mfchars(N, k, dk, NULL); long i, j, D = 0, l = lg(w); for (i = j = 1; i < l; i++) { GEN CHI = gel(w,i); long d = mfdim_Nndkchi(N,k,dk,CHI,space); if (d) D += d * myeulerphiu(mfcharorder(CHI)); } return D; } static GEN mf1dims(long N, GEN vCHI, long space) { GEN D = NULL; switch(space) { case mf_NEW: D = mf1newdimall(N, vCHI); break; case mf_CUSP:D = mf1cuspdimall(N, vCHI); break; case mf_OLD: D = mf1olddimall(N, vCHI); break; default: pari_err_FLAG("mfdim"); } return D; } static GEN mfkdims(long N, long k, long dk, GEN vCHI, long space) { GEN D, w = mfchars(N, k, dk, vCHI); long i, j, l = lg(w); D = cgetg(l, t_VEC); for (i = j = 1; i < l; i++) { GEN CHI = gel(w,i); long d = mfdim_Nndkchi(N,k,dk,CHI,space); if (vCHI) gel(D, j++) = mkvec2s(d, 0); else if (d) gel(D, j++) = fmt_dim(CHI, d, 0); } setlg(D,j); return D; } GEN mfdim(GEN NK, long space) { pari_sp av = avma; long N, k, dk, joker; GEN CHI, mf; if ((mf = checkMF_i(NK))) return utoi(MF_get_dim(mf)); checkNK2(NK, &N, &k, &dk, &CHI, 2); if (!CHI) joker = 1; else switch(typ(CHI)) { case t_INT: joker = 2; break; case t_COL: joker = 3; break; default: joker = 0; break; } if (joker) { long d; GEN D; if (k < 0) switch(joker) { case 1: return cgetg(1,t_VEC); case 2: return gen_0; case 3: return mfdim0all(CHI); } if (k == 0) { if (space_is_cusp(space)) switch(joker) { case 1: return cgetg(1,t_VEC); case 2: return gen_0; case 3: return mfdim0all(CHI); } switch(joker) { long i, l; case 1: retmkvec(fmt_dim(mfchartrivial(),0,0)); case 2: return gen_1; case 3: l = lg(CHI); D = cgetg(l,t_VEC); for (i = 1; i < l; i++) { long t = mfcharistrivial(gel(CHI,i)); gel(D,i) = mkvec2(t? gen_1: gen_0, gen_0); } return D; } } if (dk == 1 && k == 1 && space != mf_EISEN) { long fix = 0, space0 = space; if (space == mf_FULL) space = mf_CUSP; /* remove Eisenstein part */ if (joker == 2) { d = mf1dimsum(N, space); if (space0 == mf_FULL) d += mfkdimsum(N,k,dk,mf_EISEN);/*add it back*/ return gc_utoi(av, d); } /* must initialize explicitly: trivial spaces for E_k/S_k differ */ if (space0 == mf_FULL) { if (!CHI) fix = 1; /* must remove 0 spaces */ CHI = mfchars(N, k, dk, CHI); } D = mf1dims(N, CHI, space); if (space0 == mf_FULL) { GEN D2 = mfkdims(N, k, dk, CHI, mf_EISEN); D = merge_dims(D, D2, fix? CHI: NULL); } } else { if (joker==2) { d = mfkdimsum(N,k,dk,space); return gc_utoi(av,d); } D = mfkdims(N, k, dk, CHI, space); } if (!CHI) return gerepileupto(av, vecsort(D, mkvecsmall(1))); return gerepilecopy(av, D); } return utoi( mfdim_Nndkchi(N, k, dk, CHI, space) ); } GEN mfbasis(GEN NK, long space) { pari_sp av = avma; long N, k, dk; GEN mf, CHI; if ((mf = checkMF_i(NK))) return gconcat(gel(mf,2), gel(mf,3)); checkNK2(NK, &N, &k, &dk, &CHI, 0); if (dk == 2) return gerepilecopy(av, mf2basis(N, k>>1, CHI, NULL, space)); mf = mfinit_Nkchi(N, k, CHI, space, 1); return gerepilecopy(av, MF_get_basis(mf)); } static GEN deg1ser_shallow(GEN a1, GEN a0, long v, long e) { return RgX_to_ser(deg1pol_shallow(a1, a0, v), e+2); } /* r / x + O(1) */ static GEN simple_pole(GEN r) { GEN S = deg1ser_shallow(gen_0, r, 0, 1); setvalser(S, -1); return S; } /* F form, E embedding; mfa = mfatkininit or root number (eigenform case) */ static GEN mflfuncreate(GEN mfa, GEN F, GEN E, GEN N, GEN gk) { GEN LF = cgetg(8,t_VEC), polar = cgetg(1,t_COL), eps; long k = itou(gk); gel(LF,1) = lfuntag(t_LFUN_MFCLOS, mkvec3(F,E,gen_1)); if (typ(mfa) != t_VEC) eps = mfa; /* cuspidal eigenform: root number; no poles */ else { /* mfatkininit */ GEN a0, b0, vF, vG, G = NULL; GEN M = gel(mfa,2), C = gel(mfa,3), mf = gel(mfa,4); M = gdiv(mfmatembed(E, M), C); vF = mfvecembed(E, mftobasis_i(mf, F)); vG = RgM_RgC_mul(M, vF); if (gequal(vF,vG)) eps = gen_1; else if (gequal(vF,gneg(vG))) eps = gen_m1; else { /* not self-dual */ eps = NULL; G = mfatkin(mfa, F); gel(LF,2) = lfuntag(t_LFUN_MFCLOS, mkvec3(G,E,ginv(C))); gel(LF,6) = powIs(k); } /* polar part */ a0 = mfembed(E, mfcoef(F,0)); b0 = eps? gmul(eps,a0): gdiv(mfembed(E, mfcoef(G,0)), C); if (!gequal0(b0)) { b0 = mulcxpowIs(gmul2n(b0,1), k); polar = vec_append(polar, mkvec2(gk, simple_pole(b0))); } if (!gequal0(a0)) { a0 = gneg(gmul2n(a0,1)); polar = vec_append(polar, mkvec2(gen_0, simple_pole(a0))); } } if (eps) /* self-dual */ { gel(LF,2) = mfcharorder(mf_get_CHI(F)) <= 2? gen_0: gen_1; gel(LF,6) = mulcxpowIs(eps,k); } gel(LF,3) = mkvec2(gen_0, gen_1); gel(LF,4) = gk; gel(LF,5) = N; if (lg(polar) == 1) setlg(LF,7); else gel(LF,7) = polar; return LF; } static GEN mflfuncreateall(long sd, GEN mfa, GEN F, GEN vE, GEN gN, GEN gk) { long i, l = lg(vE); GEN L = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(L,i) = mflfuncreate(sd? gel(mfa,i): mfa, F, gel(vE,i), gN, gk); return L; } GEN lfunmf(GEN mf, GEN F, long bitprec) { pari_sp av = avma; long i, l, prec = nbits2prec(bitprec); GEN L, gk, gN; mf = checkMF(mf); gk = MF_get_gk(mf); gN = MF_get_gN(mf); if (typ(gk)!=t_INT) pari_err_IMPL("half-integral weight"); if (F) { GEN v; long s = MF_get_space(mf); if (!checkmf_i(F)) pari_err_TYPE("lfunmf", F); if (!mfisinspace_i(mf, F)) err_space(F); L = NULL; if ((s == mf_NEW || s == mf_CUSP || s == mf_FULL) && gequal(mfcoefs_i(F,1,1), mkvec2(gen_0,gen_1))) { /* check if eigenform */ GEN vP, vF, b = mftobasis_i(mf, F); long lF, d = degpol(mf_get_field(F)); v = mfsplit(mf, d, 0); vF = gel(v,1); vP = gel(v,2); lF = lg(vF); for (i = 1; i < lF; i++) if (degpol(gel(vP,i)) == d && gequal(gel(vF,i), b)) { GEN vE = mfgetembed(F, prec); GEN Z = mffrickeeigen_i(mf, mkvec(b), mkvec(vE), prec); L = mflfuncreateall(1, gel(Z,1), F, vE, gN, gk); break; } } if (!L) { /* not an eigenform: costly general case */ GEN mfa = mfatkininit_i(mf, itou(gN), 1, prec); L = mflfuncreateall(0,mfa, F, mfgetembed(F,prec), gN, gk); } if (lg(L) == 2) L = gel(L,1); } else { GEN M = mfeigenbasis(mf), vE = mfeigenembed(mf, prec); GEN v = mffrickeeigen(mf, vE, prec); l = lg(vE); L = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(L,i) = mflfuncreateall(1,gel(v,i), gel(M,i), gel(vE,i), gN, gk); } return gerepilecopy(av, L); } GEN mffromell(GEN E) { pari_sp av = avma; GEN mf, F, z, v, S; long N, i, l; checkell(E); if (ell_get_type(E) != t_ELL_Q) pari_err_TYPE("mfffromell [E not over Q]", E); N = itos(ellQ_get_N(E)); mf = mfinit_i(mkvec2(utoi(N), gen_2), mf_NEW); v = split_i(mf, 1, 0); S = gel(v,1); l = lg(S); /* rational newforms */ F = tag(t_MF_ELL, mkNK(N,2,mfchartrivial()), E); z = mftobasis_i(mf, F); for(i = 1; i < l; i++) if (gequal(z, gel(S,i))) break; if (i == l) pari_err_BUG("mffromell [E is not modular]"); return gerepilecopy(av, mkvec3(mf, F, z)); } /* returns -1 if not, degree otherwise */ long polishomogeneous(GEN P) { long i, D, l; if (typ(P) != t_POL) return 0; D = -1; l = lg(P); for (i = 2; i < l; i++) { GEN c = gel(P,i); long d; if (gequal0(c)) continue; d = polishomogeneous(c); if (d < 0) return -1; if (D < 0) D = d + i-2; else if (D != d + i-2) return -1; } return D; } /* M a pp((Gram q)^(-1)) ZM; P a homogeneous t_POL, is P spherical ? */ static int RgX_isspherical(GEN M, GEN P) { pari_sp av = avma; GEN S, v = variables_vecsmall(P); long i, j, l = lg(v); if (l > lg(M)) pari_err(e_MISC, "too many variables in mffromqf"); S = gen_0; for (j = 1; j < l; j++) { GEN Mj = gel(M, j), Pj = deriv(P, v[j]); for (i = 1; i <= j; i++) { GEN c = gel(Mj, i); if (!signe(c)) continue; if (i != j) c = shifti(c, 1); S = gadd(S, gmul(c, deriv(Pj, v[i]))); } } return gc_bool(av, gequal0(S)); } static GEN c_QFsimple_i(long n, GEN Q, GEN P) { GEN V, v = qfrep0(Q, utoi(n), 1); long i, l = lg(v); V = cgetg(l+1, t_VEC); if (!P || equali1(P)) { gel(V,1) = gen_1; for (i = 2; i <= l; i++) gel(V,i) = utoi(v[i-1] << 1); } else { gel(V,1) = gcopy(P); for (i = 2; i <= l; i++) gel(V,i) = gmulgu(P, v[i-1] << 1); } return V; } /* v a t_VECSMALL of variable numbers, lg(r) >= lg(v), r is a vector of * scalars [not involving any variable in v] */ static GEN gsubstvec_i(GEN e, GEN v, GEN r) { long i, l = lg(v); for(i = 1; i < l; i++) e = gsubst(e, v[i], gel(r,i)); return e; } static GEN c_QF_i(long n, GEN Q, GEN P) { pari_sp av = avma; GEN V, v, va; long i, l; if (!P || typ(P) != t_POL) return gerepileupto(av, c_QFsimple_i(n, Q, P)); v = gel(minim(Q, utoi(2*n), NULL), 3); va = variables_vecsmall(P); V = zerovec(n + 1); l = lg(v); for (i = 1; i < l; i++) { pari_sp av = avma; GEN X = gel(v,i); long c = (itos(qfeval(Q, X)) >> 1) + 1; gel(V, c) = gerepileupto(av, gadd(gel(V, c), gsubstvec_i(P, va, X))); } return gmul2n(V, 1); } GEN mffromqf(GEN Q, GEN P) { pari_sp av = avma; GEN G, Qi, F, D, N, mf, v, gk, chi; long m, d, space; if (typ(Q) != t_MAT) pari_err_TYPE("mffromqf", Q); if (!RgM_is_ZM(Q) || !qfiseven(Q)) pari_err_TYPE("mffromqf [not integral or even]", Q); m = lg(Q)-1; Qi = ZM_inv(Q, &N); if (!qfiseven(Qi)) N = shifti(N, 1); d = 0; if (!P || gequal1(P)) P = NULL; else { P = simplify_shallow(P); if (typ(P) == t_POL) { d = polishomogeneous(P); if (d < 0) pari_err_TYPE("mffromqf [not homogeneous t_POL]", P); if (!RgX_isspherical(Qi, P)) pari_err_TYPE("mffromqf [not a spherical t_POL]", P); } } gk = uutoQ(m + 2*d, 2); D = ZM_det(Q); if (!odd(m)) { if ((m & 3) == 2) D = negi(D); } else D = shifti(D, 1); space = d > 0 ? mf_CUSP : mf_FULL; G = znstar0(N,1); chi = mkvec2(G, znchar_quad(G,D)); mf = mfinit(mkvec3(N, gk, chi), space); if (odd(d)) { F = mftrivial(); v = zerocol(MF_get_dim(mf)); } else { F = c_QF_i(mfsturm(mf), Q, P); v = mftobasis_i(mf, F); F = mflinear(mf, v); } return gerepilecopy(av, mkvec3(mf, F, v)); } /***********************************************************************/ /* Eisenstein Series */ /***********************************************************************/ /* \sigma_{k-1}(\chi,n) */ static GEN sigchi(long k, GEN CHI, long n) { pari_sp av = avma; GEN S = gen_1, D = mydivisorsu(u_ppo(n,mfcharmodulus(CHI))); long i, l = lg(D), ord = mfcharorder(CHI), vt = varn(mfcharpol(CHI)); for (i = 2; i < l; i++) /* skip D[1] = 1 */ { long d = D[i], a = mfcharevalord(CHI, d, ord); S = gadd(S, Qab_Czeta(a, ord, powuu(d, k-1), vt)); } return gerepileupto(av,S); } /* write n = n0*n1*n2, (n0,N1*N2) = 1, n1 | N1^oo, n2 | N2^oo; * return NULL if (n,N1,N2) > 1, else return factoru(n0) */ static GEN sigchi2_dec(long n, long N1, long N2, long *pn1, long *pn2) { GEN P0, E0, P, E, fa = myfactoru(n); long i, j, l; *pn1 = 1; *pn2 = 1; if (N1 == 1 && N2 == 1) return fa; P = gel(fa,1); l = lg(P); E = gel(fa,2); P0 = cgetg(l, t_VECSMALL); E0 = cgetg(l, t_VECSMALL); for (i = j = 1; i < l; i++) { long p = P[i], e = E[i]; if (N1 % p == 0) { if (N2 % p == 0) return NULL; *pn1 *= upowuu(p,e); } else if (N2 % p == 0) *pn2 *= upowuu(p,e); else { P0[j] = p; E0[j] = e; j++; } } setlg(P0, j); setlg(E0, j); return mkvec2(P0,E0); } /* sigma_{k-1}(\chi_1,\chi_2,n), ord multiple of lcm(ord(CHI1),ord(CHI2)) */ static GEN sigchi2(long k, GEN CHI1, GEN CHI2, long n, long ord) { pari_sp av = avma; GEN S, D; long i, l, n1, n2, vt, N1 = mfcharmodulus(CHI1), N2 = mfcharmodulus(CHI2); D = sigchi2_dec(n, N1, N2, &n1, &n2); if (!D) return gc_const(av, gen_0); D = divisorsu_fact(D); l = lg(D); vt = varn(mfcharpol(CHI1)); for (i = 1, S = gen_0; i < l; i++) { /* S += d^(k-1)*chi1(d)*chi2(n/d) */ long a, d = n2*D[i], nd = n1*D[l-i]; /* (d,N1)=1; (n/d,N2) = 1 */ a = mfcharevalord(CHI1, d, ord) + mfcharevalord(CHI2, nd, ord); if (a >= ord) a -= ord; S = gadd(S, Qab_Czeta(a, ord, powuu(d, k-1), vt)); } return gerepileupto(av, S); } /**************************************************************************/ /** Dirichlet characters with precomputed values **/ /**************************************************************************/ /* CHI mfchar */ static GEN mfcharcxinit(GEN CHI, long prec) { GEN G = gel(CHI,1), chi = gel(CHI,2), z, V; GEN v = ncharvecexpo(G, znconrey_normalized(G,chi)); long n, l = lg(v), o = mfcharorder(CHI); V = cgetg(l, t_VEC); z = grootsof1(o, prec); /* Mod(t, Phi_o(t)) -> e(1/o) */ for (n = 1; n < l; n++) gel(V,n) = v[n] < 0? gen_0: gel(z, v[n]+1); return mkvecn(6, G, chi, gmfcharorder(CHI), v, V, mfcharpol(CHI)); } /* v a "CHIvec" */ static long CHIvec_N(GEN v) { return itou(znstar_get_N(gel(v,1))); } static GEN CHIvec_CHI(GEN v) { return mkvec4(gel(v,1), gel(v,2), gel(v,3), gel(v,6)); } /* character order */ static long CHIvec_ord(GEN v) { return itou(gel(v,3)); } /* character exponents, i.e. t such that chi(n) = e(t) */ static GEN CHIvec_expo(GEN v) { return gel(v,4); } /* character values chi(n) */ static GEN CHIvec_val(GEN v) { return gel(v,5); } /* CHI(n) */ static GEN mychareval(GEN v, long n) { long N = CHIvec_N(v), ind = n%N; if (ind <= 0) ind += N; return gel(CHIvec_val(v), ind); } /* return c such that CHI(n) = e(c / ordz) or -1 if (n,N) > 1 */ static long mycharexpo(GEN v, long n) { long N = CHIvec_N(v), ind = n%N; if (ind <= 0) ind += N; return CHIvec_expo(v)[ind]; } /* faster than mfcharparity */ static long CHIvec_parity(GEN v) { return mycharexpo(v,-1) ? -1: 1; } /**************************************************************************/ static ulong sigchi2_Fl(long k, GEN CHI1vec, GEN CHI2vec, long n, GEN vz, ulong p) { pari_sp av = avma; long ordz = lg(vz)-2, i, l, n1, n2; ulong S = 0; GEN D = sigchi2_dec(n, CHIvec_N(CHI1vec), CHIvec_N(CHI2vec), &n1, &n2); if (!D) return gc_ulong(av,S); D = divisorsu_fact(D); l = lg(D); for (i = 1; i < l; i++) { /* S += d^(k-1)*chi1(d)*chi2(n/d) */ long a, d = n2*D[i], nd = n1*D[l-i]; /* (d,N1)=1, (n/d,N2)=1 */ a = mycharexpo(CHI2vec, nd) + mycharexpo(CHI1vec, d); if (a >= ordz) a -= ordz; S = Fl_add(S, Qab_Czeta_Fl(a, vz, Fl_powu(d,k-1,p), p), p); } return gc_ulong(av,S); } /**********************************************************************/ /* Fourier expansions of Eisenstein series */ /**********************************************************************/ /* L(CHI_t,0) / 2, CHI_t(n) = CHI(n)(t/n) as a character modulo N*t, * order(CHI) | ord != 0 */ static GEN charLFwt1(long N, GEN CHI, long ord, long t) { GEN S; long r, vt; if (N == 1 && t == 1) return mkfrac(gen_m1,stoi(4)); S = gen_0; vt = varn(mfcharpol(CHI)); for (r = 1; r < N; r++) { /* S += r*chi(r) */ long a, c; if (ugcd(N,r) != 1) continue; a = mfcharevalord(CHI,r,ord); c = (t != 1 && kross(t, r) < 0)? -r: r; S = gadd(S, Qab_Czeta(a, ord, stoi(c), vt)); } return gdivgs(S, -2*N); } /* L(CHI,0) / 2, mod p */ static ulong charLFwt1_Fl(GEN CHIvec, GEN vz, ulong p) { long r, m = CHIvec_N(CHIvec); ulong S; if (m == 1) return Rg_to_Fl(mkfrac(gen_m1,stoi(4)), p); S = 0; for (r = 1; r < m; r++) { /* S += r*chi(r) */ long a = mycharexpo(CHIvec,r); if (a < 0) continue; S = Fl_add(S, Qab_Czeta_Fl(a, vz, r, p), p); } return Fl_div(Fl_neg(S,p), 2*m, p); } /* L(CHI_t,1-k) / 2, CHI_t(n) = CHI(n) * (t/n), order(CHI) | ord != 0; * assume conductor of CHI_t divides N */ static GEN charLFwtk(long N, long k, GEN CHI, long ord, long t) { GEN S, P, dS; long r, vt; if (k == 1) return charLFwt1(N, CHI, ord, t); if (N == 1 && t == 1) return gdivgs(bernfrac(k),-2*k); vt = varn(mfcharpol(CHI)); P = bern_init(N, k, &dS); dS = mul_denom(dS, stoi(-2*N*k)); for (r = 1, S = gen_0; r < N; r++) { /* S += P(r)*chi(r) */ long a; GEN C; if (ugcd(r,N) != 1) continue; a = mfcharevalord(CHI,r,ord); C = ZX_Z_eval(P, utoi(r)); if (t != 1 && kross(t, r) < 0) C = gneg(C); S = gadd(S, Qab_Czeta(a, ord, C, vt)); } return gdiv(S, dS); } /* L(CHI,1-k) / 2, mod p */ static ulong charLFwtk_Fl(long k, GEN CHIvec, GEN vz, ulong p) { GEN P, dS; long r, m; ulong S, d; if (k == 1) return charLFwt1_Fl(CHIvec, vz, p); m = CHIvec_N(CHIvec); if (m == 1) return Rg_to_Fl(gdivgs(bernfrac(k),-2*k), p); P = ZX_to_Flx(bern_init(m, k, &dS), p); for (r = 1, S = 0; r < m; r++) { /* S += P(r)*chi(r) */ long a = mycharexpo(CHIvec,r); if (a < 0) continue; S = Fl_add(S, Qab_Czeta_Fl(a, vz, Flx_eval(P,r,p), p), p); } d = (2 * k * m) % p; if (dS) d = Fl_mul(d, umodiu(dS, p), p); return Fl_div(Fl_neg(S,p), d, p); } static GEN mfeisenstein2_0(long k, GEN CHI1, GEN CHI2, long ord) { long N1 = mfcharmodulus(CHI1), N2 = mfcharmodulus(CHI2); if (k == 1 && N1 == 1) return charLFwtk(N2, 1, CHI2, ord, 1); if (N2 == 1) return charLFwtk(N1, k, CHI1, ord, 1); return gen_0; } static ulong mfeisenstein2_0_Fl(long k, GEN CHI1vec, GEN CHI2vec, GEN vz, ulong p) { if (k == 1 && CHIvec_N(CHI1vec) == 1) return charLFwtk_Fl(k, CHI2vec, vz, p); else if (CHIvec_N(CHI2vec) == 1) return charLFwtk_Fl(k, CHI1vec, vz, p); else return 0; } static GEN NK_eisen2(long k, GEN CHI1, GEN CHI2, long ord) { long o, N = mfcharmodulus(CHI1)*mfcharmodulus(CHI2); GEN CHI = mfcharmul(CHI1, CHI2); o = mfcharorder(CHI); if ((ord & 3) == 2) ord >>= 1; if ((o & 3) == 2) o >>= 1; if (ord != o) pari_err_IMPL("mfeisenstein for these characters"); return mkNK(N, k, CHI); } static GEN mfeisenstein_i(long k, GEN CHI1, GEN CHI2) { long s = 1, ord, vt; GEN E0, NK, vchi, T; if (CHI2) { CHI2 = get_mfchar(CHI2); if (mfcharparity(CHI2) < 0) s = -s; } if (CHI1) { CHI1 = get_mfchar(CHI1); if (mfcharparity(CHI1) < 0) s = -s; } if (s != m1pk(k)) return mftrivial(); if (!CHI1) CHI1 = mfchartrivial(); if (!CHI2) { /* E_k(chi1) */ vt = varn(mfcharpol(CHI1)); ord = mfcharorder(CHI1); NK = mkNK(mfcharmodulus(CHI1), k, CHI1); E0 = charLFwtk(mfcharmodulus(CHI1), k, CHI1, ord, 1); vchi = mkvec3(E0, mkvec(mfcharpol(CHI1)), CHI1); return tag(t_MF_EISEN, NK, vchi); } /* E_k(chi1,chi2) */ vt = varn(mfcharpol(CHI1)); ord = ulcm(mfcharorder(CHI1), mfcharorder(CHI2)); NK = NK_eisen2(k, CHI1, CHI2, ord); E0 = mfeisenstein2_0(k, CHI1, CHI2, ord); T = mkvec(polcyclo(ord, vt)); vchi = mkvec4(E0, T, CHI1, CHI2); return tag2(t_MF_EISEN, NK, vchi, mkvecsmall2(ord,0)); } GEN mfeisenstein(long k, GEN CHI1, GEN CHI2) { pari_sp av = avma; if (k < 1) pari_err_DOMAIN("mfeisenstein", "k", "<", gen_1, stoi(k)); return gerepilecopy(av, mfeisenstein_i(k, CHI1, CHI2)); } static GEN mfeisenstein2all(long N0, GEN NK, long k, GEN CHI1, GEN CHI2, GEN T, long o) { GEN E, E0 = mfeisenstein2_0(k, CHI1,CHI2, o), vchi = mkvec4(E0, T, CHI1,CHI2); long j, d = (lg(T)==4)? itou(gmael(T,3,1)): 1; E = cgetg(d+1, t_VEC); for (j=1; j<=d; j++) gel(E,j) = tag2(t_MF_EISEN, NK,vchi,mkvecsmall2(o,j-1)); return mfbdall(E, N0 / mf_get_N(gel(E,1))); } /* list of characters on G = (Z/NZ)^*, v[i] = NULL if (i,N) > 1, else * the conductor of Conrey label i, [conductor, primitive char]. * Trivial chi (label 1) comes first */ static GEN zncharsG(GEN G) { long i, l, N = itou(znstar_get_N(G)); GEN vCHI, V; if (N == 1) return mkvec2(gen_1,cgetg(1,t_COL)); vCHI = const_vec(N,NULL); V = cyc2elts(znstar_get_conreycyc(G)); l = lg(V); for (i = 1; i < l; i++) { GEN chi0, chi = zc_to_ZC(gel(V,i)), n, F; F = znconreyconductor(G, chi, &chi0); if (typ(F) != t_INT) F = gel(F,1); n = znconreyexp(G, chi); gel(vCHI, itos(n)) = mkvec2(chi0, F); } return vCHI; } /* CHI primitive, f(CHI) | N. Return pairs (CHI1,CHI2) both primitive * such that f(CHI1)*f(CHI2) | N and CHI1 * CHI2 = CHI; * if k = 1, CHI1 is even; if k = 2, omit (1,1) if CHI = 1 */ static GEN mfeisensteinbasis_i(long N0, long k, GEN CHI) { GEN G = gel(CHI,1), chi = gel(CHI,2), vT = const_vec(myeulerphiu(N0), NULL); GEN CHI0, GN, chiN, Lchi, LG, V, RES, NK, T, C = mfcharpol(CHI); long i, j, l, n, n1, N, ord = mfcharorder(CHI); long F = mfcharmodulus(CHI), vt = varn(mfcharpol(CHI)); CHI0 = (F == 1)? CHI: mfchartrivial(); j = 1; RES = cgetg(N0+1, t_VEC); T = gel(vT,ord) = Qab_trace_init(ord, ord, C, C); if (F != 1 || k != 2) { /* N1 = 1 */ NK = mkNK(F, k, CHI); gel(RES, j++) = mfeisenstein2all(N0, NK, k, CHI0, CHI, T, ord); if (F != 1 && k != 1) gel(RES, j++) = mfeisenstein2all(N0, NK, k, CHI, CHI0, T, ord); } if (N0 == 1) { setlg(RES,j); return RES; } GN = G; chiN = chi; if (F == N0) N = N0; else { GEN faN = myfactoru(N0), P = gel(faN,1), E = gel(faN,2); long lP = lg(P); for (i = N = 1; i < lP; i++) { long p = P[i]; N *= upowuu(p, maxuu(E[i]/2, z_lval(F,p))); } if ((N & 3) == 2) N >>= 1; if (N == 1) { setlg(RES,j); return RES; } if (F != N) { GN = znstar0(utoipos(N),1); chiN = zncharinduce(G, chi, GN); } } LG = const_vec(N, NULL); /* LG[d] = znstar(d,1) or NULL */ gel(LG,1) = gel(CHI0,1); gel(LG,F) = G; gel(LG,N) = GN; Lchi = coprimes_zv(N); n = itou(znconreyexp(GN,chiN)); V = zncharsG(GN); l = lg(V); for (n1 = 2; n1 < l; n1++) /* skip 1 (trivial char) */ { GEN v = gel(V,n1), w, chi1, chi2, G1, G2, CHI1, CHI2; long N12, N1, N2, no, o12, t, m; if (!Lchi[n1] || n1 == n) continue; /* skip trivial chi2 */ chi1 = gel(v,1); N1 = itou(gel(v,2)); /* conductor of chi1 */ w = gel(V, Fl_div(n,n1,N)); chi2 = gel(w,1); N2 = itou(gel(w,2)); /* conductor of chi2 */ N12 = N1 * N2; if (N0 % N12) continue; G1 = gel(LG,N1); if (!G1) gel(LG,N1) = G1 = znstar0(utoipos(N1), 1); if (k == 1 && zncharisodd(G1,chi1)) continue; G2 = gel(LG,N2); if (!G2) gel(LG,N2) = G2 = znstar0(utoipos(N2), 1); CHI1 = mfcharGL(G1, chi1); CHI2 = mfcharGL(G2, chi2); o12 = ulcm(mfcharorder(CHI1), mfcharorder(CHI2)); /* remove Galois orbit: same trace */ no = Fl_powu(n1, ord, N); for (t = 1+ord, m = n1; t <= o12; t += ord) { /* m <-> CHI1^t, if t in Gal(Q(chi1,chi2)/Q), omit (CHI1^t,CHI2^t) */ m = Fl_mul(m, no, N); if (!m) break; if (ugcd(t, o12) == 1) Lchi[m] = 0; } T = gel(vT,o12); if (!T) T = gel(vT,o12) = Qab_trace_init(o12, ord, polcyclo(o12,vt), C); NK = mkNK(N12, k, CHI); gel(RES, j++) = mfeisenstein2all(N0, NK, k, CHI1, CHI2, T, o12); } setlg(RES,j); return RES; } static GEN mfbd_E2(GEN E2, long d, GEN CHI) { GEN E2d = mfbd_i(E2, d); GEN F = mkvec2(E2, E2d), L = mkvec2(gen_1, utoineg(d)); /* cannot use mflinear_i: E2 and E2d do not have the same level */ return tag3(t_MF_LINEAR, mkNK(d,2,CHI), F, L, gen_1); } /* C-basis of E_k(Gamma_0(N),chi). If k = 1, the first basis element must not * vanish at oo [used in mf1basis]. Here E_1(CHI), whose q^0 coefficient * does not vanish (since L(CHI,0) does not) *if* CHI is not trivial; which * must be the case in weight 1. * * (k>=3): In weight k >= 3, basis is B(d) E(CHI1,(CHI/CHI1)_prim), where * CHI1 is primitive modulo N1, and if N2 is the conductor of CHI/CHI1 * then d*N1*N2 | N. * (k=2): In weight k=2, same if CHI is nontrivial. If CHI is trivial, must * not take CHI1 trivial, and must add E_2(tau)-dE_2(d tau)), where * d|N, d > 1. * (k=1): In weight k=1, same as k >= 3 except that we restrict to CHI1 even */ static GEN mfeisensteinbasis(long N, long k, GEN CHI) { long i, F; GEN L; if (badchar(N, k, CHI)) return cgetg(1, t_VEC); if (k == 0) return mfcharistrivial(CHI)? mkvec(mf1()): cgetg(1, t_VEC); CHI = mfchartoprimitive(CHI, &F); L = mfeisensteinbasis_i(N, k, CHI); if (F == 1 && k == 2) { GEN v, E2 = mfeisenstein(2, NULL, NULL), D = mydivisorsu(N); long nD = lg(D)-1; v = cgetg(nD, t_VEC); L = vec_append(L,v); for (i = 1; i < nD; i++) gel(v,i) = mfbd_E2(E2, D[i+1], CHI); } return lg(L) == 1? L: shallowconcat1(L); } static GEN not_in_space(GEN F, long flag) { if (!flag) err_space(F); return cgetg(1, t_COL); } /* when flag set, no error */ GEN mftobasis(GEN mf, GEN F, long flag) { pari_sp av2, av = avma; GEN G, v, y, gk; long N, B, ismf = checkmf_i(F); mf = checkMF(mf); if (ismf) { if (mfistrivial(F)) return zerocol(MF_get_dim(mf)); if (!mf_same_k(mf, F) || !mf_same_CHI(mf, F)) return not_in_space(F, flag); } N = MF_get_N(mf); gk = MF_get_gk(mf); if (ismf) { long NF = mf_get_N(F); B = maxuu(mfsturmNgk(NF,gk), mfsturmNgk(N,gk)) + 1; v = mfcoefs_i(F,B,1); } else { B = mfsturmNgk(N, gk) + 1; switch(typ(F)) { /* F(0),...,F(lg(v)-2) */ case t_SER: v = sertocol(F); settyp(v,t_VEC); break; case t_VEC: v = F; break; case t_COL: v = shallowtrans(F); break; default: pari_err_TYPE("mftobasis",F); v = NULL;/*LCOV_EXCL_LINE*/ } if (flag) B = minss(B, lg(v)-2); } y = mftobasis_i(mf, v); if (typ(y) == t_VEC) { if (flag) return gerepilecopy(av, y); pari_err(e_MISC, "not enough coefficients in mftobasis"); } av2 = avma; if (MF_get_space(mf) == mf_FULL || mfsturm(mf)+1 == B) return y; G = mflinear(mf, y); if (!gequal(v, mfcoefs_i(G, lg(v)-2,1))) y = NULL; if (!y) { set_avma(av); return not_in_space(F, flag); } set_avma(av2); return gerepileupto(av, y); } /* assume N > 0; first cusp is always 0 */ static GEN mfcusps_i(long N) { long i, c, l; GEN D, v; if (N == 1) return mkvec(gen_0); D = mydivisorsu(N); l = lg(D); /* left on stack */ c = mfnumcuspsu_fact(myfactoru(N)); v = cgetg(c + 1, t_VEC); for (i = c = 1; i < l; i++) { long C = D[i], NC = D[l-i], lima = ugcd(C, NC), A0, A; for (A0 = 0; A0 < lima; A0++) if (ugcd(A0, lima) == 1) { A = A0; while (ugcd(A,C) > 1) A += lima; gel(v, c++) = uutoQ(A, C); } } return v; } /* List of cusps of Gamma_0(N) */ GEN mfcusps(GEN gN) { long N; GEN mf; if (typ(gN) == t_INT) N = itos(gN); else if ((mf = checkMF_i(gN))) N = MF_get_N(mf); else { pari_err_TYPE("mfcusps", gN); N = 0; } if (N <= 0) pari_err_DOMAIN("mfcusps", "N", "<=", gen_0, stoi(N)); return mfcusps_i(N); } long mfcuspisregular(GEN NK, GEN cusp) { long v, N, dk, nk, t, o; GEN mf, CHI, go, A, C, g, c, d; if ((mf = checkMF_i(NK))) { GEN gk = MF_get_gk(mf); N = MF_get_N(mf); CHI = MF_get_CHI(mf); Qtoss(gk, &nk, &dk); } else checkNK2(NK, &N, &nk, &dk, &CHI, 0); if (typ(cusp) == t_INFINITY) return 1; if (typ(cusp) == t_FRAC) { A = gel(cusp,1); C = gel(cusp,2); } else { A = cusp; C = gen_1; } g = diviuexact(mului(N,C), ugcd(N, Fl_sqr(umodiu(C,N), N))); c = mulii(negi(C),g); d = addiu(mulii(A,g), 1); if (!CHI) return 1; go = gmfcharorder(CHI); v = vali(go); if (v < 2) go = shifti(go, 2-v); t = itou( znchareval(gel(CHI,1), gel(CHI,2), d, go) ); if (dk == 1) return t == 0; o = itou(go); if (kronecker(c,d) < 0) t = Fl_add(t, o/2, o); if (Mod4(d) == 1) return t == 0; t = Fl_sub(t, Fl_mul(o/4, nk, o), o); return t == 0; } /* Some useful closures */ /* sum_{d|n} d^k */ static GEN mysumdivku(ulong n, ulong k) { GEN fa = myfactoru(n); return k == 1? usumdiv_fact(fa): usumdivk_fact(fa,k); } static GEN c_Ek(long n, long d, GEN F) { GEN E = cgetg(n + 2, t_VEC), C = gel(F,2); long i, k = mf_get_k(F); gel (E, 1) = gen_1; for (i = 1; i <= n; i++) { pari_sp av = avma; gel(E, i+1) = gerepileupto(av, gmul(C, mysumdivku(i*d, k-1))); } return E; } GEN mfEk(long k) { pari_sp av = avma; GEN E0, NK; if (k < 0 || odd(k)) pari_err_TYPE("mfEk [incorrect k]", stoi(k)); if (!k) return mf1(); E0 = gdivsg(-2*k, bernfrac(k)); NK = mkNK(1,k,mfchartrivial()); return gerepilecopy(av, tag(t_MF_Ek, NK, E0)); } GEN mfDelta(void) { pari_sp av = avma; return gerepilecopy(av, tag0(t_MF_DELTA, mkNK(1,12,mfchartrivial()))); } GEN mfTheta(GEN psi) { pari_sp av = avma; GEN N, gk, psi2; long par; if (!psi) { psi = mfchartrivial(); N = utoipos(4); par = 1; } else { long FC; psi = get_mfchar(psi); FC = mfcharconductor(psi); if (mfcharmodulus(psi) != FC) pari_err_TYPE("mfTheta [nonprimitive character]", psi); par = mfcharparity(psi); N = shifti(sqru(FC),2); } if (par > 0) { gk = ghalf; psi2 = psi; } else { gk = gsubsg(2, ghalf); psi2 = mfcharmul(psi, get_mfchar(stoi(-4))); } return gerepilecopy(av, tag(t_MF_THETA, mkgNK(N, gk, psi2, pol_x(1)), psi)); } /* Output 0 if not desired eta product: if flag=0 (default) require * holomorphic at cusps. If flag set, accept meromorphic, but sill in some * modular function space */ GEN mffrometaquo(GEN eta, long flag) { pari_sp av = avma; GEN NK, N, k, BR, P; long v, cusp = 0; if (!etaquotype(&eta, &N,&k,&P, &v, NULL, flag? NULL: &cusp) || cusp < 0) return gc_const(av, gen_0); if (lg(gel(eta,1)) == 1) { set_avma(av); return mf1(); } BR = mkvec2(ZV_to_zv(gel(eta,1)), ZV_to_zv(gel(eta,2))); if (v < 0) v = 0; NK = mkgNK(N, k, get_mfchar(P), pol_x(1)); return gerepilecopy(av, tag2(t_MF_ETAQUO, NK, BR, utoi(v))); } /* Q^(-r) */ static GEN RgXn_negpow(GEN Q, long r, long L) { if (r < 0) r = -r; else Q = RgXn_inv_i(Q, L); if (r != 1) Q = RgXn_powu_i(Q, r, L); return Q; } /* flag same as in mffrometaquo: if set, accept meromorphic. */ static GEN mfisetaquo_i(GEN F, long flag) { GEN gk, P, E, M, S, G, CHI, v, w; long b, l, L, N, vS, m, j; const long bextra = 10; if (!checkmf_i(F)) pari_err_TYPE("mfisetaquo",F); CHI = mf_get_CHI(F); if (mfcharorder(CHI) > 2) return NULL; N = mf_get_N(F); gk = mf_get_gk(F); b = mfsturmNgk(N, gk); L = maxss(N, b) + bextra; S = mfcoefs_i(F, L, 1); if (!RgV_is_ZV(S)) return NULL; for (vS = 1; vS <= L+1; vS++) if (signe(gel(S,vS))) break; vS--; if (vS >= bextra - 1) { L += vS; S = mfcoefs_i(F, L, 1); } if (vS) { S = vecslice(S, vS+1, L+1); L -= vS; } S = RgV_to_RgX(S, 0); l = lg(S)-2; P = cgetg(l, t_COL); E = cgetg(l, t_COL); w = v = gen_0; /* w = weight, v = valuation */ for (m = j = 1; m+2 < lg(S); m++) { GEN c = gel(S,m+2); long r; if (is_bigint(c)) return NULL; r = -itos(c); if (r) { S = ZXn_mul(S, RgXn_negpow(eta_ZXn(m, L), r, L), L); gel(P,j) = utoipos(m); gel(E,j) = stoi(r); v = addmuliu(v, gel(E,j), m); w = addis(w, r); j++; } } if (!equalii(w, gmul2n(gk, 1)) || (!flag && !equalii(v, muluu(24,vS)))) return NULL; setlg(P, j); setlg(E, j); M = mkmat2(P, E); G = mffrometaquo(M, flag); return (typ(G) != t_INT && (mfsturmmf(G) <= b + bextra || mfisequal(F, G, b)))? M: NULL; } GEN mfisetaquo(GEN F, long flag) { pari_sp av = avma; GEN M = mfisetaquo_i(F, flag); return M? gerepilecopy(av, M): gc_const(av, gen_0); } #if 0 /* number of primitive characters modulo N */ static ulong numprimchars(ulong N) { GEN fa, P, E; long i, l; ulong n; if ((N & 3) == 2) return 0; fa = myfactoru(N); P = gel(fa,1); l = lg(P); E = gel(fa,2); for (i = n = 1; i < l; i++) { ulong p = P[i], e = E[i]; if (e == 2) n *= p-2; else n *= (p-1)*(p-1)*upowuu(p,e-2); } return n; } #endif /* Space generated by products of two Eisenstein series */ static int cmp_small_priority(void *E, GEN a, GEN b) { GEN prio = (GEN)E; return cmpss(prio[(long)a], prio[(long)b]); } static long znstar_get_expo(GEN G) { return itou(cyc_get_expo(znstar_get_cyc(G))); } /* Return [vchi, bymod, vG]: * vG[f] = znstar(f,1) for f a conductor of (at least) a char mod N; else NULL * bymod[f] = vecsmall of conrey indexes of chars modulo f | N; else NULL * vchi[n] = a list of CHIvec [G0,chi0,o,ncharvecexpo(G0,nchi0),...]: * chi0 = primitive char attached to Conrey Mod(n,N) * (resp. NULL if (n,N) > 1) */ static GEN charsmodN(long N) { GEN D, G, prio, phio, dummy = cgetg(1,t_VEC); GEN vP, vG = const_vec(N,NULL), vCHI = const_vec(N,NULL); GEN bymod = const_vec(N,NULL); long pn, i, l, vt = fetch_user_var("t"); D = mydivisorsu(N); l = lg(D); for (i = 1; i < l; i++) gel(bymod, D[i]) = vecsmalltrunc_init(myeulerphiu(D[i])+1); gel(vG,N) = G = znstar0(utoipos(N),1); pn = znstar_get_expo(G); /* exponent(Z/NZ)^* */ vP = const_vec(pn,NULL); for (i = 1; i <= N; i++) { GEN P, gF, G0, chi0, nchi0, chi, v, go; long j, F, o; if (ugcd(i,N) != 1) continue; chi = znconreylog(G, utoipos(i)); gF = znconreyconductor(G, chi, &chi0); F = (typ(gF) == t_INT)? itou(gF): itou(gel(gF,1)); G0 = gel(vG, F); if (!G0) G0 = gel(vG,F) = znstar0(gF, 1); nchi0 = znconreylog_normalize(G0,chi0); go = gel(nchi0,1); o = itou(go); /* order(chi0) */ v = ncharvecexpo(G0, nchi0); if (!equaliu(go, pn)) v = zv_z_mul(v, pn / o); P = gel(vP, o); if (!P) P = gel(vP,o) = polcyclo(o,vt); /* mfcharcxinit with dummy complex powers */ gel(vCHI,i) = mkvecn(6, G0, chi0, go, v, dummy, P); D = mydivisorsu(N / F); l = lg(D); for (j = 1; j < l; j++) vecsmalltrunc_append(gel(bymod, F*D[j]), i); } phio = zero_zv(pn); l = lg(vCHI); prio = cgetg(l, t_VEC); for (i = 1; i < l; i++) { GEN CHI = gel(vCHI,i); long o; if (!CHI) continue; o = CHIvec_ord(CHI); if (!phio[o]) phio[o] = myeulerphiu(o); prio[i] = phio[o]; } l = lg(bymod); /* sort characters by increasing value of phi(order) */ for (i = 1; i < l; i++) { GEN z = gel(bymod,i); if (z) gen_sort_inplace(z, (void*)prio, &cmp_small_priority, NULL); } return mkvec3(vCHI, bymod, vG); } static GEN mfeisenstein2pure(long k, GEN CHI1, GEN CHI2, long ord, GEN P, long lim) { GEN c, V = cgetg(lim+2, t_COL); long n; c = mfeisenstein2_0(k, CHI1, CHI2, ord); if (P) c = grem(c, P); gel(V,1) = c; for (n=1; n <= lim; n++) { c = sigchi2(k, CHI1, CHI2, n, ord); if (P) c = grem(c, P); gel(V,n+1) = c; } return V; } static GEN mfeisenstein2pure_Fl(long k, GEN CHI1vec, GEN CHI2vec, GEN vz, ulong p, long lim) { GEN V = cgetg(lim+2, t_VECSMALL); long n; V[1] = mfeisenstein2_0_Fl(k, CHI1vec, CHI2vec, vz, p); for (n=1; n <= lim; n++) V[n+1] = sigchi2_Fl(k, CHI1vec, CHI2vec, n, vz, p); return V; } static GEN getcolswt2(GEN M, GEN D, ulong p) { GEN R, v = gel(M,1); long i, l = lg(M) - 1; R = cgetg(l, t_MAT); /* skip D[1] = 1 */ for (i = 1; i < l; i++) { GEN w = Flv_Fl_mul(gel(M,i+1), D[i+1], p); gel(R,i) = Flv_sub(v, w, p); } return R; } static GEN expandbd(GEN V, long d) { long L, n, nd; GEN W; if (d == 1) return V; L = lg(V)-1; W = zerocol(L); /* nd = n/d */ for (n = nd = 0; n < L; n += d, nd++) gel(W, n+1) = gel(V, nd+1); return W; } static GEN expandbd_Fl(GEN V, long d) { long L, n, nd; GEN W; if (d == 1) return V; L = lg(V)-1; W = zero_Flv(L); /* nd = n/d */ for (n = nd = 0; n < L; n += d, nd++) W[n+1] = V[nd+1]; return W; } static void getcols_i(GEN *pM, GEN *pvj, GEN gk, GEN CHI1vec, GEN CHI2vec, long NN1, GEN vz, ulong p, long lim) { GEN CHI1 = CHIvec_CHI(CHI1vec), CHI2 = CHIvec_CHI(CHI2vec); long N2 = CHIvec_N(CHI2vec); GEN vj, M, D = mydivisorsu(NN1/N2); long i, l = lg(D), k = gk[2]; GEN V = mfeisenstein2pure_Fl(k, CHI1vec, CHI2vec, vz, p, lim); M = cgetg(l, t_MAT); for (i = 1; i < l; i++) gel(M,i) = expandbd_Fl(V, D[i]); if (k == 2 && N2 == 1 && CHIvec_N(CHI1vec) == 1) { M = getcolswt2(M, D, p); l--; D = vecslice(D, 2, l); } *pM = M; *pvj = vj = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(vj,i) = mkvec4(gk, CHI1, CHI2, utoipos(D[i])); } /* find all CHI1, CHI2 mod N such that CHI1*CHI2 = CHI, f(CHI1)*f(CHI2) | N. * set M = mfcoefs(B_e E(CHI1,CHI2), lim), vj = [e,i1,i2] */ static void getcols(GEN *pM, GEN *pv, long k, long nCHI, GEN allN, GEN vz, ulong p, long lim) { GEN vCHI = gel(allN,1), gk = utoi(k); GEN M = cgetg(1,t_MAT), v = cgetg(1,t_VEC); long i1, N = lg(vCHI)-1; for (i1 = 1; i1 <= N; i1++) { GEN CHI1vec = gel(vCHI, i1), CHI2vec, M1, v1; long NN1, i2; if (!CHI1vec) continue; if (k == 1 && CHIvec_parity(CHI1vec) == -1) continue; NN1 = N/CHIvec_N(CHI1vec); /* N/f(chi1) */; i2 = Fl_div(nCHI,i1, N); if (!i2) i2 = 1; CHI2vec = gel(vCHI,i2); if (NN1 % CHIvec_N(CHI2vec)) continue; /* f(chi1)f(chi2) | N ? */ getcols_i(&M1, &v1, gk, CHI1vec, CHI2vec, NN1, vz, p, lim); M = shallowconcat(M, M1); v = shallowconcat(v, v1); } *pM = M; *pv = v; } static void update_Mj(GEN *M, GEN *vecj, GEN *pz, ulong p) { GEN perm; *pz = Flm_indexrank(*M, p); perm = gel(*pz,2); *M = vecpermute(*M, perm); *vecj = vecpermute(*vecj, perm); } static int getcolsgen(long dim, GEN *pM, GEN *pvj, GEN *pz, long k, long ell, long nCHI, GEN allN, GEN vz, ulong p, long lim) { GEN vCHI = gel(allN,1), bymod = gel(allN,2), gell = utoi(ell); long i1, N = lg(vCHI)-1; long L = lim+1; if (lg(*pvj)-1 >= dim) update_Mj(pM, pvj, pz, p); if (lg(*pvj)-1 == dim) return 1; for (i1 = 1; i1 <= N; i1++) { GEN CHI1vec = gel(vCHI, i1), T; long par1, j, l, N1, NN1; if (!CHI1vec) continue; par1 = CHIvec_parity(CHI1vec); if (ell == 1 && par1 == -1) continue; if (odd(ell)) par1 = -par1; N1 = CHIvec_N(CHI1vec); NN1 = N/N1; T = gel(bymod, NN1); l = lg(T); for (j = 1; j < l; j++) { long i2 = T[j], l1, l2, j1, s, nC; GEN M, M1, M2, vj, vj1, vj2, CHI2vec = gel(vCHI, i2); if (CHIvec_parity(CHI2vec) != par1) continue; nC = Fl_div(nCHI, Fl_mul(i1,i2,N), N); getcols(&M2, &vj2, k-ell, nC, allN, vz, p, lim); l2 = lg(M2); if (l2 == 1) continue; getcols_i(&M1, &vj1, gell, CHI1vec, CHI2vec, NN1, vz, p, lim); l1 = lg(M1); M1 = Flm_to_FlxV(M1, 0); M2 = Flm_to_FlxV(M2, 0); M = cgetg((l1-1)*(l2-1) + 1, t_MAT); vj = cgetg((l1-1)*(l2-1) + 1, t_VEC); for (j1 = s = 1; j1 < l1; j1++) { GEN E = gel(M1,j1), v = gel(vj1,j1); long j2; for (j2 = 1; j2 < l2; j2++, s++) { GEN c = Flx_to_Flv(Flxn_mul(E, gel(M2,j2), L, p), L); gel(M,s) = c; gel(vj,s) = mkvec2(v, gel(vj2,j2)); } } *pM = shallowconcat(*pM, M); *pvj = shallowconcat(*pvj, vj); if (lg(*pvj)-1 >= dim) update_Mj(pM, pvj, pz, p); if (lg(*pvj)-1 == dim) return 1; } } if (ell == 1) { update_Mj(pM, pvj, pz, p); return (lg(*pvj)-1 == dim); } return 0; } static GEN mkF2bd(long d, long lim) { GEN V = zerovec(lim + 1); long n; gel(V, 1) = sstoQ(-1, 24); for (n = 1; n <= lim/d; n++) gel(V, n*d + 1) = mysumdivku(n, 1); return V; } static GEN mkeisen(GEN E, long ord, GEN P, long lim) { long k = itou(gel(E,1)), e = itou(gel(E,4)); GEN CHI1 = gel(E,2), CHI2 = gel(E,3); if (k == 2 && mfcharistrivial(CHI1) && mfcharistrivial(CHI2)) return gsub(mkF2bd(1,lim), gmulgu(mkF2bd(e,lim), e)); else { GEN V = mfeisenstein2pure(k, CHI1, CHI2, ord, P, lim); return expandbd(V, e); } } static GEN mkM(GEN vj, long pn, GEN P, long lim) { long j, l = lg(vj), L = lim+1; GEN M = cgetg(l, t_MAT); for (j = 1; j < l; j++) { GEN E1, E2; parse_vecj(gel(vj,j), &E1,&E2); E1 = RgV_to_RgX(mkeisen(E1, pn, P, lim), 0); if (E2) { E2 = RgV_to_RgX(mkeisen(E2, pn, P, lim), 0); E1 = RgXn_mul(E1, E2, L); } E1 = RgX_to_RgC(E1, L); if (P && E2) E1 = RgXQV_red(E1, P); gel(M,j) = E1; } return M; } /* assume N > 2 */ static GEN mffindeisen1(long N) { GEN G = znstar0(utoipos(N), 1), L = chargalois(G, NULL), chi0 = NULL; long j, m = N, l = lg(L); for (j = 1; j < l; j++) { GEN chi = gel(L,j); long r = myeulerphiu(itou(zncharorder(G,chi))); if (r >= m) continue; chi = znconreyfromchar(G, chi); if (zncharisodd(G,chi)) { m = r; chi0 = chi; if (r == 1) break; } } if (!chi0) pari_err_BUG("mffindeisen1 [no Eisenstein series found]"); chi0 = znchartoprimitive(G,chi0); return mfcharGL(gel(chi0,1), gel(chi0,2)); } static GEN mfeisensteinspaceinit_i(long N, long k, GEN CHI) { GEN M, Minv, vj, vG, GN, allN, P, vz, z = NULL; long nCHI, lim, ell, ord, dim = mffulldim(N, k, CHI); ulong r, p; if (!dim) retmkvec3(cgetg(1,t_VECSMALL), mkvec2(cgetg(1,t_MAT),gen_1),cgetg(1,t_VEC)); lim = mfsturmNk(N, k) + 1; allN = charsmodN(N); vG = gel(allN,3); GN = gel(vG,N); ord = znstar_get_expo(GN); P = ord <= 2? NULL: polcyclo(ord, varn(mfcharpol(CHI))); CHI = induce(GN, CHI); /* lift CHI mod N before mfcharno*/ nCHI = mfcharno(CHI); r = QabM_init(ord, &p); vz = Fl_powers(r, ord, p); getcols(&M, &vj, k, nCHI, allN, vz, p, lim); for (ell = k>>1; ell >= 1; ell--) if (getcolsgen(dim, &M, &vj, &z, k, ell, nCHI, allN, vz, p, lim)) break; if (!z) update_Mj(&M, &vj, &z, p); if (lg(vj) - 1 < dim) return NULL; M = mkM(vj, ord, P, lim); Minv = QabM_Minv(rowpermute(M, gel(z,1)), P, ord); return mkvec4(gel(z,1), Minv, vj, utoi(ord)); } /* true mf */ static GEN mfeisensteinspaceinit(GEN mf) { pari_sp av = avma; GEN z, CHI = MF_get_CHI(mf); long N = MF_get_N(mf), k = MF_get_k(mf); if (!CHI) CHI = mfchartrivial(); z = mfeisensteinspaceinit_i(N, k, CHI); if (!z) { GEN E, CHIN = mffindeisen1(N), CHI0 = mfchartrivial(); z = mfeisensteinspaceinit_i(N, k+1, mfcharmul(CHI, CHIN)); if (z) E = mkvec4(gen_1, CHI0, CHIN, gen_1); else { z = mfeisensteinspaceinit_i(N, k+2, CHI); E = mkvec4(gen_2, CHI0, CHI0, utoipos(N)); } z = mkvec2(z, E); } return gerepilecopy(av, z); } /* decomposition of modular form on eisenspace */ static GEN mfeisensteindec(GEN mf, GEN F) { pari_sp av = avma; GEN M, Mindex, Mvecj, V, B, CHI; long o, ord; Mvecj = obj_checkbuild(mf, MF_EISENSPACE, &mfeisensteinspaceinit); if (lg(Mvecj) < 5) { GEN E, e = gel(Mvecj,2), gkE = gel(e,1); long dE = itou(gel(e,4)); Mvecj = gel(Mvecj,1); E = mfeisenstein(itou(gkE), NULL, gel(e,3)); if (dE != 1) E = mfbd_E2(E, dE, gel(e,2)); /* here k = 2 */ F = mfmul(F, E); } M = gel(Mvecj, 2); if (lg(M) == 1) return cgetg(1, t_VEC); Mindex = gel(Mvecj, 1); ord = itou(gel(Mvecj,4)); V = mfcoefs(F, Mindex[lg(Mindex)-1]-1, 1); settyp(V, t_COL); CHI = mf_get_CHI(F); o = mfcharorder(CHI); if (o > 2 && o != ord) { /* convert Mod(.,polcyclo(o)) to Mod(., polcyclo(N)) for o | N, * o and N both != 2 (mod 4) */ GEN z, P = gel(M,4); /* polcyclo(ord) */ long vt = varn(P); z = gmodulo(pol_xn(ord/o, vt), P); if (ord % o) pari_err_TYPE("mfeisensteindec", V); V = gsubst(liftpol_shallow(V), vt, z); } B = Minv_RgC_mul(M, vecpermute(V, Mindex)); return gerepileupto(av, B); } /*********************************************************************/ /* END EISENSPACE */ /*********************************************************************/ static GEN sertocol2(GEN S, long l) { GEN C = cgetg(l + 2, t_COL); long i; for (i = 0; i <= l; i++) gel(C, i+1) = polcoef_i(S, i, -1); return C; } /* Compute polynomial P0 such that F=E4^(k/4)P0(E6/E4^(3/2)). */ static GEN mfcanfindp0(GEN F, long k) { pari_sp ltop = avma; GEN E4, E6, V, V1, Q, W, res, M, B; long l, j; l = k/6 + 2; V = mfcoefsser(F,l); E4 = mfcoefsser(mfEk(4),l); E6 = mfcoefsser(mfEk(6),l); V1 = gdiv(V, gpow(E4, uutoQ(k,4), 0)); Q = gdiv(E6, gpow(E4, uutoQ(3,2), 0)); W = gpowers(Q, l - 1); M = cgetg(l + 1, t_MAT); for (j = 1; j <= l; j++) gel(M,j) = sertocol2(gel(W,j), l); B = sertocol2(V1, l); res = inverseimage(M, B); if (lg(res) == 1) err_space(F); return gerepilecopy(ltop, gtopolyrev(res, 0)); } /* Compute the first n+1 Taylor coeffs at tau=I of a modular form * on SL_2(Z). */ GEN mftaylor(GEN F, long n, long flreal, long prec) { pari_sp ltop = avma; GEN P0, Pm1 = gen_0, v; GEN X2 = mkpoln(3, ghalf,gen_0,gneg(ghalf)); /* (x^2-1) / 2 */ long k, m; if (!checkmf_i(F)) pari_err_TYPE("mftaylor",F); k = mf_get_k(F); if (mf_get_N(F) != 1 || k < 0) pari_err_IMPL("mftaylor for this form"); P0 = mfcanfindp0(F, k); v = cgetg(n+2, t_VEC); gel(v, 1) = RgX_coeff(P0,0); for (m = 0; m < n; m++) { GEN P1 = gdivgu(gmulsg(-(k + 2*m), RgX_shift(P0,1)), 12); P1 = gadd(P1, gmul(X2, RgX_deriv(P0))); if (m) P1 = gsub(P1, gdivgu(gmulsg(m*(m+k-1), Pm1), 144)); Pm1 = P0; P0 = P1; gel(v, m+2) = RgX_coeff(P0, 0); } if (flreal) { GEN pi2 = Pi2n(1, prec), pim4 = gmulsg(-2, pi2), VPC; GEN C = gmulsg(3, gdiv(gpowgs(ggamma(uutoQ(1,4), prec), 8), gpowgs(pi2, 6))); /* E_4(i): */ GEN facn = gen_1; VPC = gpowers(gmul(pim4, gsqrt(C, prec)), n); C = gpow(C, uutoQ(k,4), prec); for (m = 0; m <= n; m++) { gel(v, m+1) = gdiv(gmul(C, gmul(gel(v, m+1), gel(VPC, m+1))), facn); facn = gmulgu(facn, m+1); } } return gerepilecopy(ltop, v); } #if 0 /* To be used in mfeigensearch() */ GEN mfreadratfile() { GEN eqn; pariFILE *F = pari_fopengz("rateigen300.gp"); eqn = gp_readvec_stream(F->file); pari_fclose(F); return eqn; } #endif /*****************************************************************/ /* EISENSTEIN CUSPS: COMPLEX DIRECTLY: one F_k */ /*****************************************************************/ /* CHIvec = charinit(CHI); data = [N1g/g1,N2g/g2,g1/g,g2/g,C/g1,C/g2, * (N1g/g1)^{-1},(N2g/g2)^{-1}] */ /* nm = n/m; * z1 = powers of \z_{C/g}^{(Ae/g)^{-1}}, * z2 = powers of \z_N^{A^{-1}(g1g2/C)}] * N.B. : we compute value and conjugate at the end, so it is (Ae/g)^{-1} * and not -(Ae/g)^{-1} */ static GEN eiscnm(long nm, long m, GEN CHI1vec, GEN CHI2vec, GEN data, GEN z1) { long Cg1 = data[5], s10 = (nm*data[7]) % Cg1, r10 = (nm - data[1]*s10) / Cg1; long Cg2 = data[6], s20 = (m *data[8]) % Cg2, r20 = (m - data[2]*s20) / Cg2; long j1, r1, s1; GEN T = gen_0; for (j1 = 0, r1 = r10, s1 = s10; j1 < data[3]; j1++, r1 -= data[1], s1 += Cg1) { GEN c1 = mychareval(CHI1vec, r1); if (!gequal0(c1)) { long j2, r2, s2; GEN S = gen_0; for (j2 = 0, r2 = r20, s2 = s20; j2 < data[4]; j2++, r2 -= data[2], s2 += Cg2) { GEN c2 = mychareval(CHI2vec, r2); if (!gequal0(c2)) S = gadd(S, gmul(c2, rootsof1pow(z1, s1*s2))); } T = gadd(T, gmul(c1, S)); } } return conj_i(T); } static GEN fg1g2n(long n, long k, GEN CHI1vec, GEN CHI2vec, GEN data, GEN z1, GEN z2) { pari_sp av = avma; GEN S = gen_0, D = mydivisorsu(n); long i, l = lg(D); for (i = 1; i < l; i++) { long m = D[i], nm = D[l-i]; /* n/m */ GEN u = eiscnm( nm, m, CHI1vec, CHI2vec, data, z1); GEN v = eiscnm(-nm, -m, CHI1vec, CHI2vec, data, z1); GEN w = odd(k) ? gsub(u, v) : gadd(u, v); S = gadd(S, gmul(powuu(m, k-1), w)); } return gerepileupto(av, gmul(S, rootsof1pow(z2, n))); } static GEN gausssumcx(GEN CHIvec, long prec) { GEN z, S, V; long m, N = CHIvec_N(CHIvec); if (N == 1) return gen_1; V = CHIvec_val(CHIvec); z = rootsof1u_cx(N, prec); S = gmul(z, gel(V, N)); for (m = N-1; m >= 1; m--) S = gmul(z, gadd(gel(V, m), S)); return S; } /* Computation of Q_k(\z_N^s) as a polynomial in \z_N^s. FIXME: explicit * formula ? */ static GEN mfqk(long k, long N) { GEN X, P, ZI, Q, Xm1, invden; long i; ZI = gdivgu(RgX_shift_shallow(RgV_to_RgX(identity_ZV(N-1), 0), 1), N); if (k == 1) return ZI; P = gsubgs(pol_xn(N,0), 1); invden = RgXQ_powu(ZI, k, P); X = pol_x(0); Q = gneg(X); Xm1 = gsubgs(X, 1); for (i = 2; i < k; i++) Q = RgX_shift_shallow(ZX_add(gmul(Xm1, ZX_deriv(Q)), gmulsg(-i, Q)), 1); return RgXQ_mul(Q, invden, P); } /* CHI mfchar; M is a multiple of the conductor of CHI, but is NOT * necessarily its modulus */ static GEN mfskcx(long k, GEN CHI, long M, long prec) { GEN S, CHIvec, P; long F, m, i, l; CHI = mfchartoprimitive(CHI, &F); CHIvec = mfcharcxinit(CHI, prec); if (F == 1) S = gdivgu(bernfrac(k), k); else { GEN Q = mfqk(k, F), V = CHIvec_val(CHIvec); S = gmul(gel(V, F), RgX_coeff(Q, 0)); for (m = 1; m < F; m++) S = gadd(S, gmul(gel(V, m), RgX_coeff(Q, m))); S = conj_i(S); } /* prime divisors of M not dividing f(chi) */ P = gel(myfactoru(u_ppo(M/F,F)), 1); l = lg(P); for (i = 1; i < l; i++) { long p = P[i]; S = gmul(S, gsubsg(1, gdiv(mychareval(CHIvec, p), powuu(p, k)))); } return gmul(gmul(gausssumcx(CHIvec, prec), S), powuu(M/F, k)); } static GEN f00_i(long k, GEN CHI1vec, GEN CHI2vec, GEN G2, GEN S, long prec) { GEN c, a; long N1 = CHIvec_N(CHI1vec), N2 = CHIvec_N(CHI2vec); if (S[2] != N1) return gen_0; c = mychareval(CHI1vec, S[3]); if (isintzero(c)) return gen_0; a = mfskcx(k, mfchardiv(CHIvec_CHI(CHI2vec), CHIvec_CHI(CHI1vec)), N1*N2, prec); a = gmul(a, conj_i(gmul(c,G2))); return gdiv(a, mulsi(-N2, powuu(S[1], k-1))); } static GEN f00(long k, GEN CHI1vec,GEN CHI2vec, GEN G1,GEN G2, GEN data, long prec) { GEN T1, T2; T2 = f00_i(k, CHI1vec, CHI2vec, G2, data, prec); if (k > 1) return T2; T1 = f00_i(k, CHI2vec, CHI1vec, G1, data, prec); return gadd(T1, T2); } /* ga in SL_2(Z), find beta [a,b;c,d] in Gamma_0(N) and mu in Z such that * beta * ga * T^u = [A',B';C',D'] with C' | N and N | B', C' > 0 */ static void mfgatogap(GEN ga, long N, long *pA, long *pC, long *pD, long *pd, long *pmu) { GEN A = gcoeff(ga,1,1), B = gcoeff(ga,1,2); GEN C = gcoeff(ga,2,1), D = gcoeff(ga,2,2), a, b, c, d; long t, Ap, Cp, B1, D1, mu; Cp = itou(bezout(muliu(A,N), C, &c, &d)); /* divides N */ t = 0; if (Cp > 1) { /* (d, N/Cp) = 1, find t such that (d - t*(A*N/Cp), N) = 1 */ long dN = umodiu(d,Cp), Q = (N/Cp * umodiu(A,Cp)) % Cp; while (ugcd(dN, Cp) > 1) { t++; dN = Fl_sub(dN, Q, Cp); } } if (t) { c = addii(c, mului(t, diviuexact(C,Cp))); d = subii(d, mului(t, muliu(A, N/Cp))); /* (d,N) = 1 */ } D1 = umodiu(mulii(d,D), N); (void)bezout(d, mulis(c,-N), &a, &b); /* = 1 */ t = 0; Ap = umodiu(addii(mulii(a,A), mulii(b,C)), N); /* (Ap,Cp) = 1 */ while (ugcd(Ap, N) > 1) { t++; Ap = Fl_add(Ap, Cp, N); } B1 = umodiu(a,N)*umodiu(B,N) + umodiu(b,N)*umodiu(D,N) + t*D1; B1 %= N; *pmu = mu = Fl_neg(Fl_div(B1, Ap, N), N); /* A', D' and d only needed modulo N */ *pd = umodiu(d, N); *pA = Ap; *pC = Cp; *pD = (D1 + Cp*mu) % N; } #if 0 /* CHI is a mfchar, return alpha(CHI) */ static long mfalchi(GEN CHI, long AN, long cg) { GEN G = gel(CHI,1), chi = gel(CHI,2), go = gmfcharorder(CHI); long o = itou(go), a = itos( znchareval(G, chi, stoi(1 + AN/cg), go) ); if (a < 0 || (cg * a) % o) pari_err_BUG("mfalchi"); return (cg * a) / o; } #endif /* return A such that CHI1(t) * CHI2(t) = e(A) or NULL if (t,N1*N2) > 1 */ static GEN mfcharmuleval(GEN CHI1vec, GEN CHI2vec, long t) { long a1 = mycharexpo(CHI1vec, t), o1 = CHIvec_ord(CHI1vec); long a2 = mycharexpo(CHI2vec, t), o2 = CHIvec_ord(CHI2vec);; if (a1 < 0 || a2 < 0) return NULL; return sstoQ(a1*o2 + a2*o1, o1*o2); } static GEN mfcharmulcxeval(GEN CHI1vec, GEN CHI2vec, long t, long prec) { GEN A = mfcharmuleval(CHI1vec, CHI2vec, t); long n, d; if (!A) return gen_0; Qtoss(A, &n,&d); return rootsof1q_cx(n, d, prec); } /* alpha(CHI1 * CHI2) */ static long mfalchi2(GEN CHI1vec, GEN CHI2vec, long AN, long cg) { GEN A = mfcharmuleval(CHI1vec, CHI2vec, 1 + AN/cg); long a; if (!A) pari_err_BUG("mfalchi2"); A = gmulsg(cg, A); if (typ(A) != t_INT) pari_err_BUG("mfalchi2"); a = itos(A) % cg; if (a < 0) a += cg; return a; } /* return g = (a,b), set u >= 0 s.t. g = a * u (mod b) */ static long mybezout(long a, long b, long *pu) { long junk, g = cbezout(a, b, pu, &junk); if (*pu < 0) *pu += b/g; return g; } /* E = [k, CHI1,CHI2, e], CHI1 and CHI2 primitive mfchars such that, * CHI1(-1)*CHI2(-1) = (-1)^k; expansion of (B_e (E_k(CHI1,CHI2))) | ga. * w is the width for the space of the calling function. */ static GEN mfeisensteingacx(GEN E, long w, GEN ga, long lim, long prec) { GEN CHI1vec, CHI2vec, CHI1 = gel(E,2), CHI2 = gel(E,3), v, S, ALPHA; GEN G1, G2, z1, z2, data; long k = itou(gel(E,1)), e = itou(gel(E,4)); long N1 = mfcharmodulus(CHI1); long N2 = mfcharmodulus(CHI2), N = e * N1 * N2; long NsurC, cg, wN, A, C, Ai, d, mu, alchi, na, da; long eg, g, gH, U, u0, u1, u2, Aig, H, m, n, t, Cg, NC1, NC2; mfgatogap(ga, N, &A, &C, &Ai, &d, &mu); CHI1vec = mfcharcxinit(CHI1, prec); CHI2vec = mfcharcxinit(CHI2, prec); NsurC = N/C; cg = ugcd(C, NsurC); wN = NsurC / cg; if (w%wN) pari_err_BUG("mfeisensteingacx [wN does not divide w]"); alchi = mfalchi2(CHI1vec, CHI2vec, A*N, cg); ALPHA = sstoQ(alchi, NsurC); g = mybezout(A*e, C, &u0); Cg = C/g; eg = e/g; NC1 = mybezout(N1, Cg, &u1); NC2 = mybezout(N2, Cg, &u2); H = (NC1*NC2*g)/Cg; Aig = (Ai*H)%N; if (Aig < 0) Aig += N; z1 = rootsof1powinit(u0, Cg, prec); z2 = rootsof1powinit(Aig, N, prec); data = mkvecsmalln(8, N1/NC1, N2/NC2, NC1, NC2, Cg/NC1, Cg/NC2, u1, u2); v = zerovec(lim + 1); /* need n*H = alchi (mod cg) */ gH = mybezout(H, cg, &U); if (gH > 1) { if (alchi % gH) return mkvec2(gen_0, v); alchi /= gH; cg /= gH; H /= gH; } G1 = gausssumcx(CHI1vec, prec); G2 = gausssumcx(CHI2vec, prec); if (!alchi) gel(v,1) = f00(k, CHI1vec,CHI2vec,G1,G2, mkvecsmall3(NC2,Cg,A*eg), prec); n = Fl_mul(alchi,U,cg); if (!n) n = cg; m = (n*H - alchi) / cg; /* positive, exact division */ for (; m <= lim; n+=cg, m+=H) gel(v, m+1) = fg1g2n(n, k, CHI1vec, CHI2vec, data, z1,z2); t = (2*e)/g; if (odd(k)) t = -t; v = gdiv(v, gmul(conj_i(gmul(G1,G2)), mulsi(t, powuu(eg*N2/NC2, k-1)))); if (k == 2 && N1 == 1 && N2 == 1) v = gsub(mkF2bd(wN,lim), gmulsg(e,v)); Qtoss(ALPHA, &na,&da); S = conj_i( mfcharmulcxeval(CHI1vec,CHI2vec,d,prec) ); /* CHI(1/d) */ if (wN > 1) { GEN z = rootsof1powinit(-mu, wN, prec); long i, l = lg(v); for (i = 1; i < l; i++) gel(v,i) = gmul(gel(v,i), rootsof1pow(z,i-1)); } v = RgV_Rg_mul(v, gmul(S, rootsof1q_cx(-mu*na, da, prec))); return mkvec2(ALPHA, bdexpand(v, w/wN)); } /*****************************************************************/ /* END EISENSTEIN CUSPS */ /*****************************************************************/ static GEN mfchisimpl(GEN CHI) { GEN G, chi; if (typ(CHI) == t_INT) return CHI; G = gel(CHI, 1); chi = gel(CHI, 2); switch(mfcharorder(CHI)) { case 1: chi = gen_1; break; case 2: chi = znchartokronecker(G,chi,1); break; default:chi = mkintmod(znconreyexp(G,chi), znstar_get_N(G)); break; } return chi; } GEN mfparams(GEN F) { pari_sp av = avma; GEN z, mf, CHI; if ((mf = checkMF_i(F))) { long N = MF_get_N(mf); GEN gk = MF_get_gk(mf); CHI = MF_get_CHI(mf); z = mkvec5(utoi(N), gk, CHI, utoi(MF_get_space(mf)), mfcharpol(CHI)); } else { if (!checkmf_i(F)) pari_err_TYPE("mfparams", F); z = vec_append(mf_get_NK(F), mfcharpol(mf_get_CHI(F))); } gel(z,3) = mfchisimpl(gel(z,3)); return gerepilecopy(av, z); } GEN mfisCM(GEN F) { pari_sp av = avma; forprime_t S; GEN D, v; long N, k, lD, sb, p, i; if (!checkmf_i(F)) pari_err_TYPE("mfisCM", F); N = mf_get_N(F); k = mf_get_k(F); if (N < 0 || k < 0) pari_err_IMPL("mfisCM for this F"); D = mfunram(N, -1); lD = lg(D); sb = maxss(mfsturmNk(N, k), 4*N); v = mfcoefs_i(F, sb, 1); u_forprime_init(&S, 2, sb); while ((p = u_forprime_next(&S))) { GEN ap = gel(v, p+1); if (!gequal0(ap)) for (i = 1; i < lD; i++) if (kross(D[i], p) == -1) { D = vecsplice(D, i); lD--; } } if (lD == 1) return gc_const(av, gen_0); if (lD == 2) return gc_stoi(av, D[1]); if (k > 1) pari_err_BUG("mfisCM"); return gerepileupto(av, zv_to_ZV(D)); } static long mfspace_i(GEN mf, GEN F) { GEN v, vF, gk; long n, nE, i, l, s, N; mf = checkMF(mf); s = MF_get_space(mf); if (!F) return s; if (!checkmf_i(F)) pari_err_TYPE("mfspace",F); v = mftobasis(mf, F, 1); n = lg(v)-1; if (!n) return -1; nE = lg(MF_get_E(mf))-1; switch(s) { case mf_NEW: case mf_OLD: case mf_EISEN: return s; case mf_FULL: if (mf_get_type(F) == t_MF_THETA) return mf_EISEN; if (!gequal0(vecslice(v,1,nE))) return gequal0(vecslice(v,nE+1,n))? mf_EISEN: mf_FULL; } /* mf is mf_CUSP or mf_FULL, F a cusp form */ gk = mf_get_gk(F); if (typ(gk) == t_FRAC || equali1(gk)) return mf_CUSP; vF = mftonew_i(mf, vecslice(v, nE+1, n), &N); if (N != MF_get_N(mf)) return mf_OLD; l = lg(vF); for (i = 1; i < l; i++) if (itos(gmael(vF,i,1)) != N) return mf_CUSP; return mf_NEW; } long mfspace(GEN mf, GEN F) { pari_sp av = avma; return gc_long(av, mfspace_i(mf,F)); } static GEN lfunfindchi(GEN ldata, GEN van, long prec) { GEN gN = ldata_get_conductor(ldata), gk = ldata_get_k(ldata); GEN G = znstar0(gN,1), cyc = znstar_get_conreycyc(G), L, go, vz; long N = itou(gN), odd = typ(gk) == t_INT && mpodd(gk); long i, j, o, l, B0 = 2, B = lg(van)-1, bit = 10 - prec2nbits(prec); /* if van is integral, chi must be trivial */ if (typ(van) == t_VECSMALL) return mfcharGL(G, zerocol(lg(cyc)-1)); L = cyc2elts(cyc); l = lg(L); for (i = j = 1; i < l; i++) { GEN chi = zc_to_ZC(gel(L,i)); if (zncharisodd(G,chi) == odd) gel(L,j++) = mfcharGL(G,chi); } setlg(L,j); l = j; if (l <= 2) return gel(L,1); o = znstar_get_expo(G); go = utoi(o); vz = grootsof1(o, prec); for (;;) { long n; for (n = B0; n <= B; n++) { GEN an, r; long j; if (ugcd(n, N) != 1) continue; an = gel(van,n); if (gexpo(an) < bit) continue; r = gdiv(an, conj_i(an)); for (i = 1; i < l; i++) { GEN CHI = gel(L,i); if (gexpo(gsub(r, gel(vz, znchareval_i(CHI,n,go)+1))) > bit) gel(L,i) = NULL; } for (i = j = 1; i < l; i++) if (gel(L,i)) gel(L,j++) = gel(L,i); l = j; setlg(L,l); if (l == 2) return gel(L,1); } B0 = B+1; B <<= 1; van = ldata_vecan(ldata_get_an(ldata), B, prec); } } GEN mffromlfun(GEN L, long prec) { pari_sp av = avma; GEN ldata = lfunmisc_to_ldata_shallow(L), Vga = ldata_get_gammavec(ldata); GEN van, a0, CHI, NK, gk = ldata_get_k(ldata); long N, space; if (!gequal(Vga, mkvec2(gen_0, gen_1))) pari_err_TYPE("mffromlfun", L); N = itou(ldata_get_conductor(ldata)); van = ldata_vecan(ldata_get_an(ldata), mfsturmNgk(N,gk) + 2, prec); CHI = lfunfindchi(ldata, van, prec); if (typ(van) != t_VEC) van = vecsmall_to_vec_inplace(van); space = (lg(ldata) == 7)? mf_CUSP: mf_FULL; a0 = (space == mf_CUSP)? gen_0: gneg(lfun(L, gen_0, prec2nbits(prec))); NK = mkvec3(utoi(N), gk, mfchisimpl(CHI)); return gerepilecopy(av, mkvec3(NK, utoi(space), shallowconcat(a0, van))); } /*******************************************************************/ /* */ /* HALF-INTEGRAL WEIGHT */ /* */ /*******************************************************************/ /* We use the prefix mf2; k represents the weight -1/2, so e.g. k = 2 is weight 5/2. N is the level, so 4\mid N, and CHI is the character, always even. */ static long lamCO(long r, long s, long p) { if ((s << 1) <= r) { long rp = r >> 1; if (odd(r)) return upowuu(p, rp) << 1; else return (p + 1)*upowuu(p, rp - 1); } else return upowuu(p, r - s) << 1; } static int condC(GEN faN, GEN valF) { GEN P = gel(faN, 1), E = gel(faN, 2); long l = lg(P), i; for (i = 1; i < l; i++) if ((P[i] & 3L) == 3) { long r = E[i]; if (odd(r) || r < (valF[i] << 1)) return 1; } return 0; } /* returns 2*zetaCO; weight is k + 1/2 */ static long zeta2CO(GEN faN, GEN valF, long r2, long s2, long k) { if (r2 >= 4) return lamCO(r2, s2, 2) << 1; if (r2 == 3) return 6; if (condC(faN, valF)) return 4; if (odd(k)) return s2 ? 3 : 5; else return s2 ? 5: 3; } /* returns 4 times last term in formula */ static long dim22(long N, long F, long k) { pari_sp av = avma; GEN vF, faN = myfactoru(N), P = gel(faN, 1), E = gel(faN, 2); long i, D, l = lg(P); vF = cgetg(l, t_VECSMALL); for (i = 1; i < l; i++) vF[i] = u_lval(F, P[i]); D = zeta2CO(faN, vF, E[1], vF[1], k); for (i = 2; i < l; i++) D *= lamCO(E[i], vF[i], P[i]); return gc_long(av,D); } /* PSI not necessarily primitive, of conductor F */ static int charistotallyeven(GEN PSI, long F) { pari_sp av = avma; GEN P = gel(myfactoru(F), 1); GEN G = gel(PSI,1), psi = gel(PSI,2); long i; for (i = 1; i < lg(P); i++) { GEN psip = znchardecompose(G, psi, utoipos(P[i])); if (zncharisodd(G, psip)) return gc_bool(av,0); } return gc_bool(av,1); } static GEN get_PSI(GEN CHI, long t) { long r = t & 3L, t2 = (r == 2 || r == 3) ? t << 2 : t; return mfcharmul_i(CHI, induce(gel(CHI,1), utoipos(t2))); } /* space = mf_CUSP, mf_EISEN or mf_FULL, weight k + 1/2 */ static long mf2dimwt12(long N, GEN CHI, long space) { pari_sp av = avma; GEN D = mydivisorsu(N >> 2); long i, l = lg(D), dim3 = 0, dim4 = 0; CHI = induceN(N, CHI); for (i = 1; i < l; i++) { long rp, t = D[i], Mt = D[l-i]; GEN PSI = get_PSI(CHI,t); rp = mfcharconductor(PSI); if (Mt % (rp*rp) == 0) { dim4++; if (charistotallyeven(PSI,rp)) dim3++; } } set_avma(av); switch (space) { case mf_CUSP: return dim4 - dim3; case mf_EISEN:return dim3; case mf_FULL: return dim4; } return 0; /*LCOV_EXCL_LINE*/ } static long mf2dimwt32(long N, GEN CHI, long F, long space) { long D; switch(space) { case mf_CUSP: D = mypsiu(N) - 6*dim22(N, F, 1); if (D%24) pari_err_BUG("mfdim"); return D/24 + mf2dimwt12(N, CHI, 4); case mf_FULL: D = mypsiu(N) + 6*dim22(N, F, 0); if (D%24) pari_err_BUG("mfdim"); return D/24 + mf2dimwt12(N, CHI, 1); case mf_EISEN: D = dim22(N, F, 0) + dim22(N, F, 1); if (D & 3L) pari_err_BUG("mfdim"); return (D >> 2) - mf2dimwt12(N, CHI, 3); } return 0; /*LCOV_EXCL_LINE*/ } /* F = conductor(CHI), weight k = r+1/2 */ static long checkmf2(long N, long r, GEN CHI, long F, long space) { switch(space) { case mf_FULL: case mf_CUSP: case mf_EISEN: break; case mf_NEW: case mf_OLD: pari_err_TYPE("half-integral weight [new/old spaces]", utoi(space)); default: pari_err_TYPE("half-integral weight [incorrect space]",utoi(space)); } if (N & 3L) pari_err_DOMAIN("half-integral weight", "N % 4", "!=", gen_0, stoi(N)); return r >= 0 && mfcharparity(CHI) == 1 && N % F == 0; } /* weight k = r + 1/2 */ static long mf2dim_Nkchi(long N, long r, GEN CHI, ulong space) { long D, D2, F = mfcharconductor(CHI); if (!checkmf2(N, r, CHI, F, space)) return 0; if (r == 0) return mf2dimwt12(N, CHI, space); if (r == 1) return mf2dimwt32(N, CHI, F, space); if (space == mf_EISEN) { D = dim22(N, F, r) + dim22(N, F, 1-r); if (D & 3L) pari_err_BUG("mfdim"); return D >> 2; } D2 = space == mf_FULL? dim22(N, F, 1-r): -dim22(N, F, r); D = (2*r-1)*mypsiu(N) + 6*D2; if (D%24) pari_err_BUG("mfdim"); return D/24; } /* weight k=r+1/2 */ static GEN mf2init_Nkchi(long N, long r, GEN CHI, long space, long flraw) { GEN CHI1, Minv, Minvmat, B, M, gk = gaddsg(r,ghalf); GEN mf1 = mkvec4(utoi(N),gk,CHI,utoi(space)); long L; if (!checkmf2(N, r, CHI, mfcharconductor(CHI), space)) return mfEMPTY(mf1); if (space==mf_EISEN) pari_err_IMPL("half-integral weight Eisenstein space"); L = mfsturmNgk(N, gk) + 1; B = mf2basis(N, r, CHI, &CHI1, space); M = mflineardivtomat(N,B,L); /* defined modulo T = charpol(CHI) */ if (flraw) M = mkvec3(gen_0,gen_0,M); else { long o1 = mfcharorder(CHI1), o = mfcharorder(CHI); M = mfcleanCHI(M, CHI, 0); Minv = gel(M,2); Minvmat = RgM_Minv_mul(NULL, Minv); /* mod T */ if (o1 != o) { GEN tr = Qab_trace_init(o, o1, mfcharpol(CHI), mfcharpol(CHI1)); Minvmat = QabM_tracerel(tr, 0, Minvmat); } /* Minvmat mod T1 = charpol(CHI1) */ B = vecmflineardiv_linear(B, Minvmat); gel(M,3) = RgM_Minv_mul(gel(M,3), Minv); gel(M,2) = mkMinv(matid(lg(B)-1), NULL,NULL,NULL); } return mkmf(mf1, cgetg(1,t_VEC), B, gen_0, M); } /**************************************************************************/ /* Kohnen + space */ /**************************************************************************/ static GEN mfkohnenbasis_i(GEN mf, GEN CHI, long eps, long sb) { GEN M = mfcoefs_mf(mf, sb, 1), p, P; long c, i, n = mfcharorder(CHI), l = sb + 2; p = cgetg(l, t_VECSMALL); /* keep the a_n, n = (2 or 2+eps) mod 4 */ for (i = 3, c = 1; i < l; i+=4) p[c++] = i; for (i = 3+eps; i < l; i+=4) p[c++] = i; P = n <= 2? NULL: mfcharpol(CHI); setlg(p, c); return QabM_ker(rowpermute(M, p), P, n); } GEN mfkohnenbasis(GEN mf) { pari_sp av = avma; GEN gk, CHI, CHIP, K; long N4, r, eps, sb; mf = checkMF(mf); if (MF_get_space(mf) != mf_CUSP) pari_err_TYPE("mfkohnenbasis [not a cuspidal space", mf); if (!MF_get_dim(mf)) return cgetg(1, t_MAT); N4 = MF_get_N(mf) >> 2; gk = MF_get_gk(mf); CHI = MF_get_CHI(mf); if (typ(gk) == t_INT) pari_err_TYPE("mfkohnenbasis", gk); r = MF_get_r(mf); CHIP = mfcharchiliftprim(CHI, N4); eps = CHIP==CHI? 1: -1; if (odd(r)) eps = -eps; if (uissquarefree(N4)) { long d = mfdim_Nkchi(N4, 2*r, mfcharpow(CHI, gen_2), mf_CUSP); sb = mfsturmNgk(N4 << 2, gk) + 1; K = mfkohnenbasis_i(mf, CHIP, eps, sb); if (lg(K) - 1 == d) return gerepilecopy(av, K); } sb = mfsturmNgk(N4 << 4, gk) + 1; K = mfkohnenbasis_i(mf, CHIP, eps, sb); return gerepilecopy(av, K); } static GEN get_Shimura(GEN mf, GEN CHI, GEN vB, long t) { long N = MF_get_N(mf), r = MF_get_k(mf) >> 1; long i, d = MF_get_dim(mf), sb = mfsturm_mf(mf); GEN a = cgetg(d+1, t_MAT); for (i = 1; i <= d; i++) { pari_sp av = avma; GEN f = c_deflate(sb*sb, t, gel(vB,i)); f = mftobasis_i(mf, RgV_shimura(f, sb, t, N, r, CHI)); gel(a,i) = gerepileupto(av, f); } return a; } static long QabM_rank(GEN M, GEN P, long n) { GEN z = QabM_indexrank(M, P, n); return lg(gel(z,2))-1; } /* discard T[*i] */ static void discard_Ti(GEN T, long *i, long *lt) { long j, l = *lt-1; for (j = *i; j < l; j++) T[j] = T[j+1]; (*i)--; *lt = l; } /* return [mf3, bijection, mfkohnenbasis, codeshi] */ static GEN mfkohnenbijection_i(GEN mf) { GEN CHI = MF_get_CHI(mf), K = mfkohnenbasis(mf); GEN mres, dMi, Mi, M, C, vB, mf3, SHI, T, P; long N4 = MF_get_N(mf)>>2, r = MF_get_r(mf), dK = lg(K) - 1; long i, c, n, oldr, lt, ltold, sb3, t, limt; const long MAXlt = 100; mf3 = mfinit_Nkchi(N4, r<<1, mfcharpow(CHI,gen_2), mf_CUSP, 0); if (MF_get_dim(mf3) != dK) pari_err_BUG("mfkohnenbijection [different dimensions]"); if (!dK) return mkvec4(mf3, cgetg(1, t_MAT), K, cgetg(1, t_VEC)); CHI = mfcharchiliftprim(CHI, N4); n = mfcharorder(CHI); P = n<=2? NULL: mfcharpol(CHI); SHI = cgetg(MAXlt, t_COL); T = cgetg(MAXlt, t_VECSMALL); sb3 = mfsturm_mf(mf3); limt = 6; oldr = 0; vB = C = M = NULL; for (t = lt = ltold = 1; lt < MAXlt; t++) { pari_sp av; if (!uissquarefree(t)) continue; T[lt++] = t; if (t <= limt) continue; av = avma; if (vB) gunclone(vB); /* could improve the rest but 99% of running time is spent here */ vB = gclone( RgM_mul(mfcoefs_mf(mf, t*sb3*sb3, 1), K) ); set_avma(av); for (i = ltold; i < lt; i++) { pari_sp av; long r; M = get_Shimura(mf3, CHI, vB, T[i]); r = QabM_rank(M, P, n); if (!r) { discard_Ti(T, &i, <); continue; } gel(SHI, i) = M; setlg(SHI, i+1); if (r >= dK) { C = vecsmall_ei(dK, i); goto DONE; } if (i == 1) { oldr = r; continue; } av = avma; M = shallowmatconcat(SHI); r = QabM_rank(M, P, n); /* >= rank(sum C[j] SHI[j]), probably sharp */ if (r >= dK) { M = RgV_sum(SHI); if (QabM_rank(M, P, n) >= dK) { C = const_vecsmall(dK, 1); goto DONE; } C = random_Flv(dK, 16); M = RgV_zc_mul(SHI, C); if (QabM_rank(M, P, n) >= dK) goto DONE; } else if (r == oldr) discard_Ti(T, &i, <); oldr = r; set_avma(av); } limt *= 2; ltold = lt; } pari_err_BUG("mfkohnenbijection"); DONE: gunclone(vB); lt = lg(SHI); Mi = QabM_pseudoinv(M,P,n, NULL,&dMi); Mi = RgM_Rg_div(Mi,dMi); mres = cgetg(lt, t_VEC); for (i = c = 1; i < lt; i++) if (C[i]) gel(mres,c++) = mkvec2s(T[i], C[i]); setlg(mres,c); return mkvec4(mf3, Mi, K, mres); } GEN mfkohnenbijection(GEN mf) { pari_sp av = avma; long N; mf = checkMF(mf); N = MF_get_N(mf); if (!uissquarefree(N >> 2)) pari_err_TYPE("mfkohnenbijection [N/4 not squarefree]", utoi(N)); if (MF_get_space(mf) != mf_CUSP || MF_get_r(mf) == 0 || !mfshimura_space_cusp(mf)) pari_err_TYPE("mfkohnenbijection [incorrect mf for Kohnen]", mf); return gerepilecopy(av, mfkohnenbijection_i(mf)); } static int checkbij_i(GEN b) { return typ(b) == t_VEC && lg(b) == 5 && checkMF_i(gel(b,1)) && typ(gel(b,2)) == t_MAT && typ(gel(b,3)) == t_MAT && typ(gel(b,4)) == t_VEC; } /* bij is the output of mfkohnenbijection */ GEN mfkohneneigenbasis(GEN mf, GEN bij) { pari_sp av = avma; GEN mf3, mf30, B, KM, M, k; long r, i, l, N4; mf = checkMF(mf); if (!checkbij_i(bij)) pari_err_TYPE("mfkohneneigenbasis [bijection]", bij); if (MF_get_space(mf) != mf_CUSP) pari_err_TYPE("mfkohneneigenbasis [not a cuspidal space]", mf); if (!MF_get_dim(mf)) retmkvec3(cgetg(1, t_VEC), cgetg(1, t_VEC), cgetg(1, t_VEC)); N4 = MF_get_N(mf) >> 2; k = MF_get_gk(mf); if (typ(k) == t_INT) pari_err_TYPE("mfkohneneigenbasis", k); if (!uissquarefree(N4)) pari_err_TYPE("mfkohneneigenbasis [N not squarefree]", utoipos(N4)); r = MF_get_r(mf); KM = RgM_mul(gel(bij,3), gel(bij,2)); mf3 = gel(bij,1); mf30 = mfinit_Nkchi(N4, 2*r, MF_get_CHI(mf3), mf_NEW, 0); B = mfcoefs_mf(mf30, mfsturm_mf(mf3), 1); l = lg(B); M = cgetg(l, t_MAT); for (i=1; i 0, N >= 0 */ static GEN mfEHcoef(long r, long N) { long D0, f, i, l, s; GEN S, Df; if (r == 1) return hclassno(utoi(N)); if (N == 0) return gdivgs(bernfrac(2*r), -2*r); s = N & 3L; if (odd(r)) { if (s == 2 || s == 1) return gen_0; D0 = mycoredisc2neg(N,&f); } else { if (s == 2 || s == 3) return gen_0; D0 = mycoredisc2pos(N,&f); } Df = mydivisorsu(u_pporad(f, D0)); l = lg(Df); S = gen_0; for (i = 1; i < l; i++) { long d = Df[i], s = mymoebiusu(d)*kross(D0, d); /* != 0 */ GEN c = gmul(powuu(d, r-1), mysumdivku(f/d, 2*r-1)); S = s > 0? addii(S, c): subii(S, c); } return gmul(lfunquadneg_naive(D0, r), S); } static GEN mfEHmat(long lim, long r) { long j, l, d = r/2; GEN f2, th4, th3, v, vth4, vf2; c_F2TH4(lim, &f2, &th4); f2 = RgV_to_ser(f2, 0, lim+3); th4 = RgV_to_ser(th4, 0, lim+3); th3 = RgV_to_ser(c_theta(lim, 1, mfchartrivial()), 0, lim+3); if (odd(r)) th3 = gpowgs(th3, 3); vth4 = gpowers(th4, d); vf2 = gpowers0(f2, d, th3); /* th3 f2^j */ l = d+2; v = cgetg(l, t_VEC); for (j = 1; j < l; j++) gel(v, j) = ser2rfrac_i(gmul(gel(vth4, l-j), gel(vf2, j))); return RgXV_to_RgM(v, lim); } static GEN Hfind(long r, GEN *pden) { long lim = (r/2)+3, i; GEN res, M, B; if (r <= 0) pari_err_DOMAIN("mfEH", "r", "<=", gen_0, stoi(r)); M = mfEHmat(lim, r); B = cgetg(lim+1, t_COL); for (i = 1; i <= lim; i++) gel(B, i) = mfEHcoef(r, i-1); res = QM_gauss(M, B); if (lg(res) == 1) pari_err_BUG("mfEH"); return Q_remove_denom(res,pden); } GEN mfEH(GEN gk) { pari_sp av = avma; GEN v, d, NK, gr = gsub(gk, ghalf); long r; if (typ(gr) != t_INT) pari_err_TYPE("mfEH", gk); r = itos(gr); switch (r) { case 1: v=cgetg(1,t_VEC); d=gen_1; break; case 2: v=mkvec2s(1,-20); d=utoipos(120); break; case 3: v=mkvec2s(-1,14); d=utoipos(252); break; case 4: v=mkvec3s(1,-16,16); d=utoipos(240); break; case 5: v=mkvec3s(-1,22,-88); d=utoipos(132); break; case 6: v=mkvec4s(691,-18096,110136,-4160); d=utoipos(32760); break; case 7: v=mkvec4s(-1,30,-240,224); d=utoipos(12); break; default: v = Hfind(r, &d); break; } NK = mkgNK(utoipos(4), gaddgs(ghalf,r), mfchartrivial(), pol_x(1)); return gerepilecopy(av, tag(t_MF_EISEN, NK, mkvec2(v,d))); } /**********************************************************/ /* T(f^2) for half-integral weight */ /**********************************************************/ /* T_p^2 V, p2 = p^2, c1 = chi(p) (-1/p)^r p^(r-1), c2 = chi(p^2)*p^(2r-1) */ static GEN tp2apply(GEN V, long p, long p2, GEN c1, GEN c2) { long lw = (lg(V) - 2)/p2 + 1, m, n; GEN a0 = gel(V,1), W = cgetg(lw + 1, t_VEC); gel(W,1) = gequal0(a0)? gen_0: gmul(a0, gaddsg(1, c2)); for (n = 1; n < lw; n++) { GEN c = gel(V, p2*n + 1); if (n%p) c = gadd(c, gmulsg(kross(n,p), gmul(gel(V,n+1), c1))); gel(W, n+1) = c; /* a(p^2*n) + c1 * (n/p) a(n) */ } for (m = 1, n = p2; n < lw; m++, n += p2) gel(W, n+1) = gadd(gel(W,n+1), gmul(gel(V,m+1), c2)); return W; } /* T_{p^{2e}} V; can derecursify [Purkait, Hecke operators in half-integral * weight, Prop 4.3], not worth it */ static GEN tp2eapply(GEN V, long p, long p2, long e, GEN q, GEN c1, GEN c2) { GEN V4 = NULL; if (e > 1) { V4 = vecslice(V, 1, (lg(V) - 2)/(p2*p2) + 1); V = tp2eapply(V, p, p2, e-1, q, c1, c2); } V = tp2apply(V, p, p2, c1, c2); if (e > 1) V = gsub(V, (e == 2)? gmul(q, V4) : gmul(c2, tp2eapply(V4, p, p2, e-2, q, c1, c2))); return V; } /* weight k = r+1/2 */ static GEN RgV_heckef2(long n, long d, GEN V, GEN F, GEN DATA) { GEN CHI = mf_get_CHI(F), fa = gel(DATA,1), P = gel(fa,1), E = gel(fa,2); long i, l = lg(P), r = mf_get_r(F), s4 = odd(r)? -4: 4, k2m2 = (r<<1)-1; if (typ(V) == t_COL) V = shallowtrans(V); for (i = 1; i < l; i++) { /* p does not divide N */ long p = P[i], e = E[i], p2 = p*p; GEN c1, c2, a, b, q = NULL, C = mfchareval(CHI,p), C2 = gsqr(C); a = r? powuu(p,r-1): mkfrac(gen_1,utoipos(p)); /* p^(r-1) = p^(k-3/2) */ b = r? mulii(powuu(p,r), a): a; /* p^(2r-1) = p^(2k-2) */ c1 = gmul(C, gmulsg(kross(s4,p),a)); c2 = gmul(C2, b); if (e > 1) { q = r? powuu(p,k2m2): a; if (e == 2) q = gmul(q, uutoQ(p+1,p)); /* special case T_{p^4} */ q = gmul(C2, q); /* chi(p^2) [ p^(2k-2) or (p+1)p^(2k-3) ] */ } V = tp2eapply(V, p, p2, e, q, c1, c2); } return c_deflate(n, d, V); } static GEN GL2toSL2(GEN g, GEN *abd) { GEN A, B, C, D, u, v, a, b, d, q; g = Q_primpart(g); if (!check_M2Z(g)) pari_err_TYPE("GL2toSL2", g); A = gcoeff(g,1,1); B = gcoeff(g,1,2); C = gcoeff(g,2,1); D = gcoeff(g,2,2); a = bezout(A, C, &u, &v); if (!equali1(a)) { A = diviiexact(A,a); C = diviiexact(C,a); } d = subii(mulii(A,D), mulii(B,C)); if (signe(d) <= 0) pari_err_TYPE("GL2toSL2",g); q = dvmdii(addii(mulii(u,B), mulii(v,D)), d, &b); *abd = (equali1(a) && equali1(d))? NULL: mkvec3(a, b, d); return mkmat22(A, subii(mulii(q,A), v), C, addii(mulii(q,C), u)); } static GEN Rg_approx(GEN t, long bit) { GEN a = real_i(t), b = imag_i(t); long e1 = gexpo(a), e2 = gexpo(b); if (e2 < -bit) { t = e1 < -bit? gen_0: a; } else if (e1 < -bit) t = gmul(b, gen_I()); return t; } static GEN RgV_approx(GEN v, long bit) { long i, l = lg(v); GEN w = cgetg_copy(v, &l); for (i = 1; i < lg(v); i++) gel(w,i) = Rg_approx(gel(v,i), bit); return w; } /* m != 2 (mod 4), D t_INT; V has "denominator" D, recognize in Q(zeta_m) */ static GEN bestapprnf2(GEN V, long m, GEN D, long prec) { long i, j, f, vt = fetch_user_var("t"), bit = prec2nbits_mul(prec, 0.8); GEN Tinit, Vl, H, Pf, P = polcyclo(m, vt); V = liftpol_shallow(V); V = gmul(RgV_approx(V, bit), D); V = bestapprnf(V, P, NULL, prec); Vl = liftpol_shallow(V); H = coprimes_zv(m); for (i = 2; i < m; i++) { if (H[i] != 1) continue; if (!gequal(Vl, vecGalois(Vl, i, P, m))) H[i] = 0; else for (j = i; j < m; j *= i) H[i] = 3; } f = znstar_conductor_bits(Flv_to_F2v(H)); if (f == 1) return gdiv(V, D); if (f == m) return gmodulo(gdiv(V, D), P); Pf = polcyclo(f, vt); Tinit = Qab_trace_init(m, f, P, Pf); return gmodulo(gdiv(QabV_tracerel(Tinit, 0, Vl), D), Pf); } /* f | ga expansion; [f, mf_eisendec(f)]~ allowed */ GEN mfslashexpansion(GEN mf, GEN f, GEN ga, long n, long flrat, GEN *params, long prec) { pari_sp av = avma; GEN a, b, d, res, al, V, M, ad, abd, gk, A, awd = NULL; long i, w; mf = checkMF(mf); gk = MF_get_gk(mf); M = GL2toSL2(ga, &abd); if (abd) { a = gel(abd,1); b = gel(abd,2); d = gel(abd,3); } else { a = d = gen_1; b = gen_0; } ad = gdiv(a,d); res = mfgaexpansion(mf, f, M, n, prec); al = gel(res,1); w = itou(gel(res,2)); V = gel(res,3); if (flrat) { GEN CHI = MF_get_CHI(mf); long N = MF_get_N(mf), F = mfcharconductor(CHI); long ord = mfcharorder(CHI), k, deg; long B = umodiu(gcoeff(M,1,2), N); long C = umodiu(gcoeff(M,2,1), N); long D = umodiu(gcoeff(M,2,2), N); long CD = (C * D) % N, BC = (B * C) % F; GEN CV, t; /* weight of f * Theta in 1/2-integral weight */ k = typ(gk) == t_INT? (long) itou(gk): MF_get_r(mf)+1; CV = odd(k) ? powuu(N, k - 1) : powuu(N, k >> 1); deg = ulcm(ulcm(ord, N/ugcd(N,CD)), F/ugcd(F,BC)); if ((deg & 3) == 2) deg >>= 1; if (typ(gk) != t_INT && odd(deg) && mfthetaI(C,D)) deg <<= 2; V = bestapprnf2(V, deg, CV, prec); if (abd && !signe(b)) { /* can [a,0; 0,d] be simplified to id ? */ long nk, dk; Qtoss(gk, &nk, &dk); if (ispower(ad, utoipos(2*dk), &t)) /* t^(2*dk) = a/d or t = NULL */ { V = RgV_Rg_mul(V, powiu(t,nk)); awd = gdiv(a, muliu(d,w)); } } } else if (abd) { /* ga = M * [a,b;0,d] * rational, F := f | M = q^al * \sum V[j] q^(j/w) */ GEN u, t = NULL, wd = muliu(d,w); /* a > 0, 0 <= b < d; f | ga = (a/d)^(k/2) * F(tau + b/d) */ if (signe(b)) { long ns, ds; GEN z; Qtoss(gdiv(b, wd), &ns, &ds); z = rootsof1powinit(ns, ds, prec); for (i = 1; i <= n+1; i++) gel(V,i) = gmul(gel(V,i), rootsof1pow(z, i-1)); if (!gequal0(al)) t = gexp(gmul(PiI2(prec), gmul(al, gdiv(b,d))), prec); } awd = gdiv(a, wd); u = gpow(ad, gmul2n(gk,-1), prec); t = t? gmul(t, u): u; V = RgV_Rg_mul(V, t); } if (!awd) A = mkmat22(a, b, gen_0, d); else { /* rescale and update w from [a,0; 0,d] */ long ns; Qtoss(awd, &ns, &w); /* update w */ V = bdexpand(V, ns); if (!gequal0(al)) { GEN adal = gmul(ad, al), sh = gfloor(adal); al = gsub(adal, sh); V = RgV_shift(V, sh); } A = matid(2); } if (params) *params = mkvec3(al, utoipos(w), A); return gc_all(av,params?2:1,&V,params); } /**************************************************************/ /* Alternative method for 1/2-integral weight */ /**************************************************************/ static GEN mf2basis(long N, long r, GEN CHI, GEN *pCHI1, long space) { GEN CHI1, CHI2, mf1, mf2, B1, B2, BT, M1, M2, M, M2i, T, Th, v, den; long sb, N2, o1, o2, k1 = r + 1; if (odd(k1)) { CHI1 = mfcharmul(CHI, get_mfchar(stoi(-4))); CHI2 = mfcharmul(CHI, get_mfchar(stoi(-8))); } else { CHI1 = CHI; CHI2 = mfcharmul(CHI, get_mfchar(utoi(8))); } mf1 = mfinit_Nkchi(N, k1, CHI1, space, 1); if (pCHI1) *pCHI1 = CHI1; B1 = MF_get_basis(mf1); if (lg(B1) == 1) return cgetg(1,t_VEC); N2 = ulcm(8, N); mf2 = mfinit_Nkchi(N2, k1, CHI2, space, 1); B2 = MF_get_basis(mf2); if (lg(B2) == 1) return cgetg(1,t_VEC); sb = mfsturmNgk(N2, gaddsg(k1, ghalf)); M1 = mfcoefs_mf(mf1, sb, 1); M2 = mfcoefs_mf(mf2, sb, 1); Th = mfTheta(NULL); BT = mfcoefs_i(Th, sb, 1); M1 = mfmatsermul(M1, RgV_to_RgX(expandbd(BT,2),0)); M2 = mfmatsermul(M2, RgV_to_RgX(BT,0)); o1= mfcharorder(CHI1); T = (o1 <= 2)? NULL: mfcharpol(CHI1); if (o1 > 2) M1 = liftpol_shallow(M1); o2= mfcharorder(CHI2); if (T) { if (o2 == o1) M2 = liftpol_shallow(M2); else { GEN tr = Qab_trace_init(o2, o1, mfcharpol(CHI2), mfcharpol(CHI1)); M2 = QabM_tracerel(tr, 0, M2); } } /* now everything is defined mod T = mfcharpol(CHI1) */ M2i = QabM_pseudoinv_i(M2, T, o1, &v, &den); M = RgM_mul(M2i, rowpermute(M1, gel(v,1))); M = RgM_mul(M2, M); M1 = RgM_Rg_mul(M1, den); M = RgM_sub(M1, M); if (T) M = RgXQM_red(M, T); return vecmflineardiv0(B1, QabM_ker(M, T, o1), Th); } /*******************************************************************/ /* Integration */ /*******************************************************************/ static GEN vanembed(GEN F, GEN v, long prec) { GEN CHI = mf_get_CHI(F); long o = mfcharorder(CHI); if (o > 2 || degpol(mf_get_field(F)) > 1) v = liftpol_shallow(v); if (o > 2) v = gsubst(v, varn(mfcharpol(CHI)), rootsof1u_cx(o, prec)); return v; } static long mfperiod_prelim_double(double t0, long k, long bitprec) { double nlim, c = 2*M_PI*t0; nlim = ceil(bitprec * M_LN2 / c); c -= (k - 1)/(2*nlim); if (c < 1) c = 1.; nlim += ceil((0.7 + (k-1)/2*log(nlim))/c); return (long)nlim; } static long mfperiod_prelim(GEN t0, long k, long bitprec) { return mfperiod_prelim_double(gtodouble(t0), k, bitprec); } /* (-X)^(k-2) * P(-1/X) = (-1)^{k-2} P|_{k-2} S */ static GEN RgX_act_S(GEN P, long k) { P = RgX_unscale(RgX_recipspec_shallow(P+2, lgpol(P), k-1), gen_m1); setvarn(P,0); return P; } static int RgX_act_typ(GEN P, long k) { switch(typ(P)) { case t_RFRAC: return t_RFRAC; case t_POL: if (varn(P) == 0) { long d = degpol(P); if (d > k-2) return t_RFRAC; if (d) return t_POL; } } return 0; } static GEN act_S(GEN P, long k) { GEN X; switch(RgX_act_typ(P, k)) { case t_RFRAC: X = gneg(pol_x(0)); return gmul(gsubst(P, 0, ginv(X)), gpowgs(X, k - 2)); case t_POL: return RgX_act_S(P, k); } return P; } static GEN AX_B(GEN M) { GEN A = gcoeff(M,1,1), B = gcoeff(M,1,2); return deg1pol_shallow(A,B,0); } static GEN CX_D(GEN M) { GEN C = gcoeff(M,2,1), D = gcoeff(M,2,2); return deg1pol_shallow(C,D,0); } /* P|_{2-k}M = (CX+D)^{k-2}P((AX+B)/(CX+D)) */ static GEN RgX_act_gen(GEN P, GEN M, long k) { GEN S = gen_0, PCD, PAB; long i; PCD = gpowers(CX_D(M), k-2); PAB = gpowers(AX_B(M), k-2); for (i = 0; i <= k-2; i++) { GEN t = RgX_coeff(P, i); if (!gequal0(t)) S = gadd(S, gmul(t, gmul(gel(PCD, k-i-1), gel(PAB, i+1)))); } return S; } static GEN act_GL2(GEN P, GEN M, long k) { switch(RgX_act_typ(P, k)) { case t_RFRAC: { GEN AB = AX_B(M), CD = CX_D(M); return gmul(gsubst(P, 0, gdiv(AB, CD)), gpowgs(CD, k - 2)); } case t_POL: return RgX_act_gen(P, M, k); } return P; } static GEN vecact_GL2(GEN x, GEN M, long k) { pari_APPLY_same(act_GL2(gel(x,i), M, k)); } static GEN normalizeapprox(GEN R, long bit) { GEN X = gen_1, Q; long i, l; if (is_vec_t(typ(R))) { Q = cgetg_copy(R, &l); for (i = 1; i < l; i++) { pari_sp av = avma; gel(Q,i) = gerepileupto(av, normalizeapprox(gel(R,i), bit)); } return Q; } if (typ(R) == t_RFRAC && varn(gel(R,2)) == 0) { X = gel(R,2); R = gel(R,1); } if (typ(R) != t_POL || varn(R) != 0) return gdiv(R, X); Q = cgetg_copy(R, &l); Q[1] = R[1]; for (i = 2; i < l; ++i) gel(Q,i) = Rg_approx(gel(R,i),bit); Q = normalizepol_lg(Q,l); return gdiv(Q, X); } /* make sure T is a t_POL in variable 0 */ static GEN toRgX0(GEN T) { return typ(T) == t_POL && varn(T) == 0? T: scalarpol_shallow(T,0); } /* integrate by summing nlim+1 terms of van [may be < lg(van)] * van can be an expansion with vector coefficients * \int_A^oo \sum_n van[n] * q^(n/w + al) * P(z-A) dz, q = e(z) */ static GEN intAoo(GEN van, long nlim, GEN al, long w, GEN P, GEN A, long k, long prec) { GEN alw, P1, piI2A, q, S, van0; long n, vz = varn(gel(P,2)); if (nlim < 1) nlim = 1; alw = gmulsg(w, al); P1 = RgX_translate(P, gneg(A)); piI2A = gmul(PiI2n(1, prec), A); q = gexp(gdivgu(piI2A, w), prec); S = gen_0; for (n = nlim; n >= 1; n--) { GEN t = gsubst(P1, vz, gdivsg(w, gaddsg(n, alw))); S = gadd(gmul(gel(van, n+1), t), gmul(q, S)); } S = gmul(q, S); van0 = gel(van, 1); if (!gequal0(al)) { S = gadd(S, gmul(gsubst(P1, vz, ginv(al)), van0)); S = gmul(S, gexp(gmul(piI2A, al), prec)); } else if (!gequal0(van0)) S = gsub(S, gdivgu(gmul(van0, gpowgs(gsub(pol_x(0), A), k-1)), k-1)); if (is_vec_t(typ(S))) { long j, l = lg(S); for (j = 1; j < l; j++) gel(S,j) = toRgX0(gel(S,j)); } else S = toRgX0(S); return gneg(S); } /* \sum_{j <= k} X^j * (Y / (2I\pi))^{k+1-j} k! / j! */ static GEN get_P(long k, long v, long prec) { GEN a, S = cgetg(k + 1, t_POL), u = invr(Pi2n(1, prec+EXTRAPREC64)); long j, K = k-2; S[1] = evalsigne(1)|evalvarn(0); a = u; gel(S,K+2) = monomial(mulcxpowIs(a,3), 1, v); /* j = K */ for(j = K-1; j >= 0; j--) { a = mulrr(mulru(a,j+1), u); gel(S,j+2) = monomial(mulcxpowIs(a,3*(K+1-j)), K+1-j, v); } return S; } static GEN getw1w2(long N, GEN ga) { return mkvecsmall2(mfZC_width(N, gel(ga,1)), mfZC_width(N, gel(ga,2))); } static GEN intAoowithvanall(GEN mf, GEN vanall, GEN P, GEN cosets, long bitprec) { GEN vvan = gel(vanall,1), vaw = gel(vanall,2), W1W2, resall; long prec = nbits2prec(bitprec), N, k, lco, j; N = MF_get_N(mf); k = MF_get_k(mf); lco = lg(cosets); W1W2 = cgetg(lco, t_VEC); resall = cgetg(lco, t_VEC); for (j = 1; j < lco; j++) gel(W1W2,j) = getw1w2(N, gel(cosets, j)); for (j = 1; j < lco; j++) { GEN w1w2j = gel(W1W2,j), alj, M, VAN, RES, AR, Q; long jq, c, w1, w2, w; if (!w1w2j) continue; alj = gel(vaw,j); w1 = w1w2j[1]; Q = cgetg(lco, t_VECSMALL); w2 = w1w2j[2]; M = cgetg(lco, t_COL); for (c = 1, jq = j; jq < lco; jq++) { GEN W = gel(W1W2, jq); if (jq == j || (W && gequal(W, w1w2j) && gequal(gel(vaw, jq), alj))) { Q[c] = jq; gel(W1W2, jq) = NULL; gel(M, c) = gel(vvan, jq); c++; } } setlg(M,c); VAN = shallowmatconcat(M); AR = mkcomplex(gen_0, sqrtr_abs(divru(utor(w1, prec+EXTRAPREC64), w2))); w = itos(gel(alj,2)); RES = intAoo(VAN, lg(VAN)-2, gel(alj,1),w, P, AR, k, prec); for (jq = 1; jq < c; jq++) gel(resall, Q[jq]) = gel(RES, jq); } return resall; } GEN mftobasisES(GEN mf, GEN F) { GEN v = mftobasis(mf, F, 0); long nE = lg(MF_get_E(mf))-1; return mkvec2(vecslice(v,1,nE), vecslice(v,nE+1,lg(v)-1)); } static long wt1mulcond(GEN F, long D, long space) { GEN E = mfeisenstein_i(1, mfchartrivial(), get_mfchar(stoi(D))), mf; F = mfmul(F, E); mf = mfinit_Nkchi(mf_get_N(F), mf_get_k(F), mf_get_CHI(F), space, 0); return mfconductor(mf, F); } static int wt1newlevel(long N) { GEN P = gel(myfactoru(N),1); long l = lg(P), i; for (i = 1; i < l; i++) if (!wt1empty(N/P[i])) return 0; return 1; } long mfconductor(GEN mf, GEN F) { pari_sp av = avma; GEN gk; long space, N, M; mf = checkMF(mf); if (!checkmf_i(F)) pari_err_TYPE("mfconductor",F); if (mfistrivial(F)) return 1; space = MF_get_space(mf); if (space == mf_NEW) return mf_get_N(F); gk = MF_get_gk(mf); if (isint1(gk)) { N = mf_get_N(F); if (!wt1newlevel(N)) { long s = space_is_cusp(space)? mf_CUSP: mf_FULL; N = ugcd(N, wt1mulcond(F,-3,s)); if (!wt1newlevel(N)) N = ugcd(N, wt1mulcond(F,-4,s)); } return gc_long(av,N); } if (typ(gk) != t_INT) { F = mfmultheta(F); mf = obj_checkbuild(mf, MF_MF2INIT, &mf2init); /* mf_FULL */ } N = 1; if (space_is_cusp(space)) { F = mftobasis_i(mf, F); if (typ(gk) != t_INT) F = vecslice(F, lg(MF_get_E(mf)), lg(F) - 1); } else { GEN EF = mftobasisES(mf, F), vE = gel(EF,1), B = MF_get_E(mf); long i, l = lg(B); for (i = 1; i < l; i++) if (!gequal0(gel(vE,i))) N = ulcm(N, mf_get_N(gel(B, i))); F = gel(EF,2); } (void)mftonew_i(mf, F, &M); /* M = conductor of cuspidal part */ return gc_long(av, ulcm(M, N)); } static GEN fs_get_MF(GEN fs) { return gel(fs,1); } static GEN fs_get_vES(GEN fs) { return gel(fs,2); } static GEN fs_get_pols(GEN fs) { return gel(fs,3); } static GEN fs_get_cosets(GEN fs) { return gel(fs,4); } static long fs_get_bitprec(GEN fs) { return itou(gel(fs,5)); } static GEN fs_get_vE(GEN fs) { return gel(fs,6); } static GEN fs_get_EF(GEN fs) { return gel(fs,7); } static GEN fs_get_expan(GEN fs) { return gel(fs,8); } static GEN fs_set_expan(GEN fs, GEN vanall) { GEN f = shallowcopy(fs); gel(f,8) = vanall; return f; } static int mfs_checkmf(GEN fs, GEN mf) { GEN mfF = fs_get_MF(fs); return gequal(gel(mfF,1), gel(mf,1)); } static long checkfs_i(GEN v) { return typ(v) == t_VEC && lg(v) == 9 && checkMF_i(fs_get_MF(v)) && typ(fs_get_vES(v)) == t_VEC && typ(fs_get_pols(v)) == t_VEC && typ(fs_get_cosets(v)) == t_VEC && typ(fs_get_vE(v)) == t_VEC && lg(fs_get_pols(v)) == lg(fs_get_cosets(v)) && typ(fs_get_expan(v)) == t_VEC && lg(fs_get_expan(v)) == 3 && lg(gel(fs_get_expan(v), 1)) == lg(fs_get_cosets(v)) && typ(gel(v,5)) == t_INT; } GEN checkMF_i(GEN mf) { long l = lg(mf); GEN v; if (typ(mf) != t_VEC) return NULL; if (l == 9) return checkMF_i(fs_get_MF(mf)); if (l != 7) return NULL; v = gel(mf,1); if (typ(v) != t_VEC || lg(v) != 5) return NULL; return (typ(gel(v,1)) == t_INT && typ(gmul2n(gel(v,2), 1)) == t_INT && typ(gel(v,3)) == t_VEC && typ(gel(v,4)) == t_INT)? mf: NULL; } GEN checkMF(GEN T) { GEN mf = checkMF_i(T); if (!mf) pari_err_TYPE("checkMF [please use mfinit]", T); return mf; } /* c,d >= 0; c * Nc = N, find coset whose image in P1(Z/NZ) ~ (c, d + k(N/c)) */ static GEN coset_complete(long c, long d, long Nc) { long a, b; while (ugcd(c, d) > 1) d += Nc; (void)cbezout(c, d, &b, &a); return mkmat22s(a, -b, c, d); } /* right cosets of $\G_0(N)$: $\G=\bigsqcup_j \G_0(N)\ga_j$. */ /* We choose them with c\mid N and d mod N/c, not the reverse */ GEN mfcosets(GEN gN) { pari_sp av = avma; GEN V, D, mf; long l, i, ct, N = 0; if (typ(gN) == t_INT) N = itos(gN); else if ((mf = checkMF_i(gN))) N = MF_get_N(mf); else pari_err_TYPE("mfcosets", gN); if (N <= 0) pari_err_DOMAIN("mfcosets", "N", "<=", gen_0, stoi(N)); V = cgetg(mypsiu(N) + 1, t_VEC); D = mydivisorsu(N); l = lg(D); for (i = ct = 1; i < l; i++) { long d, c = D[i], Nc = D[l-i], e = ugcd(Nc, c); for (d = 0; d < Nc; d++) if (ugcd(d,e) == 1) gel(V, ct++) = coset_complete(c, d, Nc); } return gerepilecopy(av, V); } static int cmp_coset(void *E, GEN A, GEN B) { ulong N = (ulong)E, Nc, c = itou(gcoeff(A,2,1)); int r = cmpuu(c, itou(gcoeff(B,2,1))); if (r) return r; Nc = N / c; return cmpuu(umodiu(gcoeff(A,2,2), Nc), umodiu(gcoeff(B,2,2), Nc)); } /* M in SL_2(Z) */ static long mftocoset_i(ulong N, GEN M, GEN cosets) { pari_sp av = avma; long A = itos(gcoeff(M,1,1)), c, u, v, Nc, i; long C = itos(gcoeff(M,2,1)), D = itos(gcoeff(M,2,2)); GEN ga; c = cbezout(N*A, C, &u, &v); Nc = N/c; ga = coset_complete(c, umodsu(v*D, Nc), Nc); i = gen_search(cosets, ga, (void*)N, &cmp_coset); if (i < 0) pari_err_BUG("mftocoset [no coset found]"); return gc_long(av,i); } /* (U * V^(-1))[2,2] mod N, assuming V in SL2(Z) */ static long SL2_div_D(ulong N, GEN U, GEN V) { long c = umodiu(gcoeff(U,2,1), N), d = umodiu(gcoeff(U,2,2), N); long a2 = umodiu(gcoeff(V,1,1), N), b2 = umodiu(gcoeff(V,1,2), N); return (a2*d - b2*c) % (long)N; } static long mftocoset_iD(ulong N, GEN M, GEN cosets, long *D) { long i = mftocoset_i(N, M, cosets); *D = SL2_div_D(N, M, gel(cosets,i)); return i; } GEN mftocoset(ulong N, GEN M, GEN cosets) { long i; if (!check_SL2Z(M)) pari_err_TYPE("mftocoset",M); i = mftocoset_i(N, M, cosets); retmkvec2(gdiv(M,gel(cosets,i)), utoipos(i)); } static long getnlim2(long N, long w1, long w2, long nlim, long k, long bitprec) { if (w2 == N) return nlim; return mfperiod_prelim_double(1./sqrt((double)w1*w2), k, bitprec + 32); } /* g * S, g 2x2 */ static GEN ZM_mulS(GEN g) { return mkmat2(gel(g,2), ZC_neg(gel(g,1))); } /* g * T, g 2x2 */ static GEN ZM_mulT(GEN g) { return mkmat2(gel(g,1), ZC_add(gel(g,2), gel(g,1))); } /* g * T^(-1), g 2x2 */ static GEN ZM_mulTi(GEN g) { return mkmat2(gel(g,1), ZC_sub(gel(g,2), gel(g,1))); } /* Compute all slashexpansions for all cosets */ static GEN mfgaexpansionall(GEN mf, GEN FE, GEN cosets, double height, long prec) { GEN CHI = MF_get_CHI(mf), vres, vresaw; long lco, j, k = MF_get_k(mf), N = MF_get_N(mf), bitprec = prec2nbits(prec); lco = lg(cosets); vres = const_vec(lco-1, NULL); vresaw = cgetg(lco, t_VEC); for (j = 1; j < lco; j++) if (!gel(vres,j)) { GEN ga = gel(cosets, j), van, aw, al, z, gai; long w1 = mfZC_width(N, gel(ga,1)); long w2 = mfZC_width(N, gel(ga,2)); long nlim, nlim2, daw, da, na, i; double sqNinvdbl = height ? height/w1 : 1./sqrt((double)w1*N); nlim = mfperiod_prelim_double(sqNinvdbl, k, bitprec + 32); van = mfslashexpansion(mf, FE, ga, nlim, 0, &aw, prec + EXTRAPREC64); van = vanembed(gel(FE, 1), van, prec + EXTRAPREC64); al = gel(aw, 1); nlim2 = height? nlim: getnlim2(N, w1, w2, nlim, k, bitprec); gel(vres, j) = vecslice(van, 1, nlim2 + 1); gel(vresaw, j) = aw; Qtoss(al, &na, &da); daw = da*w1; z = rootsof1powinit(1, daw, prec + EXTRAPREC64); gai = ga; for (i = 1; i < w1; i++) { GEN V, coe; long Di, n, ind, w2, s = ((i*na) % da) * w1, t = i*da; gai = ZM_mulT(gai); ind = mftocoset_iD(N, gai, cosets, &Di); w2 = mfZC_width(N, gel(gel(cosets,ind), 2)); nlim2 = height? nlim: getnlim2(N, w1, w2, nlim, k, bitprec); gel(vresaw, ind) = aw; V = cgetg(nlim2 + 2, t_VEC); for (n = 0; n <= nlim2; n++, s = Fl_add(s, t, daw)) gel(V, n+1) = gmul(gel(van, n+1), rootsof1pow(z, s)); coe = mfcharcxeval(CHI, Di, prec + EXTRAPREC64); if (!gequal1(coe)) V = RgV_Rg_mul(V, conj_i(coe)); gel(vres, ind) = V; } } return mkvec2(vres, vresaw); } /* Compute all period pols of F|_k\ga_j, vF = mftobasis(F_S) */ static GEN mfperiodpols_i(GEN mf, GEN FE, GEN cosets, GEN *pvan, long bit) { long N, i, prec = nbits2prec(bit), k = MF_get_k(mf); GEN vP, P, CHI, intall = gen_0; *pvan = gen_0; if (k == 0 && gequal0(gel(FE,2))) return cosets? const_vec(lg(cosets)-1, pol_0(0)): pol_0(0); N = MF_get_N(mf); CHI = MF_get_CHI(mf); P = get_P(k, fetch_var(), prec); if (!cosets) { /* ga = id */ long nlim, PREC = prec + EXTRAPREC64; GEN F = gel(FE,1), sqNinv = invr(sqrtr_abs(utor(N, PREC))); /* A/w */ GEN AR, v, van, T1, T2; nlim = mfperiod_prelim(sqNinv, k, bit + 32); /* F|id: al = 0, w = 1 */ v = mfcoefs_i(F, nlim, 1); van = vanembed(F, v, PREC); AR = mkcomplex(gen_0, sqNinv); T1 = intAoo(van, nlim, gen_0,1, P, AR, k, prec); if (N == 1) T2 = T1; else { /* F|S: al = 0, w = N */ v = mfgaexpansion(mf, FE, mkS(), nlim, PREC); van = vanembed(F, gel(v,3), PREC); AR = mkcomplex(gen_0, mulur(N,sqNinv)); T2 = intAoo(van, nlim, gen_0,N, P, AR, k, prec); } T1 = gsub(T1, act_S(T2, k)); T1 = normalizeapprox(T1, bit-20); vP = gprec_wtrunc(T1, prec); } else { long lco = lg(cosets); GEN vanall = mfgaexpansionall(mf, FE, cosets, 0, prec); *pvan = vanall; intall = intAoowithvanall(mf, vanall, P, cosets, bit); vP = const_vec(lco-1, NULL); for (i = 1; i < lco; i++) { GEN P, P1, P2, c, ga = gel(cosets, i); long iS, DS; if (gel(vP,i)) continue; P1 = gel(intall, i); iS = mftocoset_iD(N, ZM_mulS(ga), cosets, &DS); c = mfcharcxeval(CHI, DS, prec + EXTRAPREC64); P2 = gel(intall, iS); P = act_S(isint1(c)? P2: gmul(c, P2), k); P = normalizeapprox(gsub(P1, P), bit-20); gel(vP,i) = gprec_wtrunc(P, prec); if (iS == i) continue; P = act_S(isint1(c)? P1: gmul(conj_i(c), P1), k); if (!odd(k)) P = gneg(P); P = normalizeapprox(gadd(P, P2), bit-20); gel(vP,iS) = gprec_wtrunc(P, prec); } } delete_var(); return vP; } /* when cosets = NULL, return a "fake" symbol containing only fs(oo->0) */ static GEN mfsymbol_i(GEN mf, GEN F, GEN cosets, long bit) { GEN FE, van, vP, vE, Mvecj, vES = mftobasisES(mf,F); long precnew, prec = nbits2prec(bit), k = MF_get_k(mf); vE = mfgetembed(F, prec); Mvecj = obj_checkbuild(mf, MF_EISENSPACE, &mfeisensteinspaceinit); if (lg(Mvecj) >= 5) precnew = prec; else { long N = MF_get_N(mf), n = mfperiod_prelim_double(1/(double)N, k, bit + 32); precnew = prec + inveis_extraprec(N, mkS(), Mvecj, n); } FE = mkcol2(F, mf_eisendec(mf,F,precnew)); vP = mfperiodpols_i(mf, FE, cosets, &van, bit); return mkvecn(8, mf, vES, vP, cosets, utoi(bit), vE, FE, van); } static GEN fs2_get_cusps(GEN f) { return gel(f,3); } static GEN fs2_get_MF(GEN f) { return gel(f,1); } static GEN fs2_get_W(GEN f) { return gel(f,2); } static GEN fs2_get_F(GEN f) { return gel(f,4); } static long fs2_get_bitprec(GEN f) { return itou(gel(f,5)); } static GEN fs2_get_al0(GEN f) { return gel(f,6); } static GEN fs2_get_den(GEN f) { return gel(f,7); } static int checkfs2_i(GEN f) { GEN W, C, F, al0; long l; if (typ(f) != t_VEC || lg(f) != 8 || typ(gel(f,5)) != t_INT) return 0; C = fs2_get_cusps(f); l = lg(C); W = fs2_get_W(f); F = fs2_get_F(f); al0 = fs2_get_al0(f); return checkMF_i(fs2_get_MF(f)) && typ(W) == t_VEC && typ(F) == t_VEC && typ(al0) == t_VECSMALL && lg(W) == l && lg(F) == l && lg(al0) == l; } static GEN fs2_init(GEN mf, GEN F, long bit); GEN mfsymbol(GEN mf, GEN F, long bit) { pari_sp av = avma; GEN cosets = NULL; if (!F) { F = mf; if (!checkmf_i(F)) pari_err_TYPE("mfsymbol", F); mf = mfinit_i(F, mf_FULL); } else if (!checkmf_i(F)) pari_err_TYPE("mfsymbol", F); if (checkfs2_i(mf)) return fs2_init(mf, F, bit); if (checkfs_i(mf)) { cosets = fs_get_cosets(mf); mf = fs_get_MF(mf); } else if (checkMF_i(mf)) { GEN gk = MF_get_gk(mf); if (typ(gk) != t_INT || equali1(gk)) return fs2_init(mf, F, bit); if (signe(gk) <= 0) pari_err_TYPE("mfsymbol [k <= 0]", mf); cosets = mfcosets(MF_get_gN(mf)); } else pari_err_TYPE("mfsymbol",mf); return gerepilecopy(av, mfsymbol_i(mf, F, cosets, bit)); } static GEN RgX_by_parity(GEN P, long odd) { long i, l = lg(P); GEN Q; if (l < 4) return odd ? pol_x(0): P; Q = cgetg(l, t_POL); Q[1] = P[1]; for (i = odd? 2: 3; i < l; i += 2) gel(Q,i) = gen_0; for (i = odd? 3: 2; i < l; i += 2) gel(Q,i) = gel(P,i); return normalizepol_lg(Q, l); } /* flag 0: period polynomial of F, >0 or <0 with corresponding parity */ GEN mfperiodpol(GEN mf0, GEN F, long flag, long bit) { pari_sp av = avma; GEN pol, mf = checkMF_i(mf0); if (!mf) pari_err_TYPE("mfperiodpol",mf0); if (checkfs_i(F)) { GEN mfpols = fs_get_pols(F); if (!mfs_checkmf(F, mf)) pari_err_TYPE("mfperiodpol [different mf]",F); pol = veclast(mfpols); /* trivial coset is last */ } else { GEN gk = MF_get_gk(mf); if (typ(gk) != t_INT) pari_err_TYPE("mfperiodpol [half-integral k]", mf); if (equali1(gk)) pari_err_TYPE("mfperiodpol [k = 1]", mf); F = mfsymbol_i(mf, F, NULL, bit); pol = fs_get_pols(F); } if (flag) pol = RgX_by_parity(pol, flag < 0); return gerepilecopy(av, RgX_embedall(pol, fs_get_vE(F))); } static int mfs_iscusp(GEN mfs) { return gequal0(gmael(mfs,2,1)); } /* given cusps s1 and s2 (rationals or oo) * compute $\int_{s1}^{s2}(X-\tau)^{k-2}F|_k\ga_j(\tau)\,d\tau$ */ /* If flag = 1, do not give an error message if divergent, but give the rational function as result. */ static GEN col2cusp(GEN v) { GEN A, C; if (lg(v) != 3 || !RgV_is_ZV(v)) pari_err_TYPE("col2cusp",v); A = gel(v,1); C = gel(v,2); if (gequal0(C)) { if (gequal0(A)) pari_err_TYPE("mfsymboleval", mkvec2(A, C)); return mkoo(); } return gdiv(A, C); } /* g.oo */ static GEN mat2cusp(GEN g) { return col2cusp(gel(g,1)); } static GEN pathmattovec(GEN path) { return mkvec2(col2cusp(gel(path,1)), col2cusp(gel(path,2))); } static void get_mf_F(GEN fs, GEN *mf, GEN *F) { if (lg(fs) == 3) { *mf = gel(fs,1); *F = gel(fs,2); } else { *mf = fs_get_MF(fs); *F = NULL; } } static GEN mfgetvan(GEN fs, GEN ga, GEN *pal, long nlim, long prec) { GEN van, mf, F, W; long PREC; get_mf_F(fs, &mf, &F); if (!F) { GEN vanall = fs_get_expan(fs), cosets = fs_get_cosets(fs); long D, jga = mftocoset_iD(MF_get_N(mf), ga, cosets, &D); van = gmael(vanall, 1, jga); W = gmael(vanall, 2, jga); if (lg(van) >= nlim + 2) { GEN z = mfcharcxeval(MF_get_CHI(mf), D, prec); if (!gequal1(z)) van = RgV_Rg_mul(van, z); *pal = gel(W,1); return van; } F = gel(fs_get_EF(fs), 1); } PREC = prec + EXTRAPREC64; van = mfslashexpansion(mf, F, ga, nlim, 0, &W, PREC); van = vanembed(F, van, PREC); *pal = gel(W,1); return van; } /* Computation of int_A^oo (f | ga)(t)(X-t)^{k-2} dt, assuming convergence; * fs is either a symbol or a triple [mf,F,bitprec]. A != oo and im(A) > 0 */ static GEN intAoo0(GEN fs, GEN A, GEN ga, GEN P, long bit) { long nlim, N, k, w, prec = nbits2prec(bit); GEN van, mf, F, al; get_mf_F(fs, &mf,&F); N = MF_get_N(mf); k = MF_get_k(mf); w = mfZC_width(N, gel(ga,1)); nlim = mfperiod_prelim(gdivgu(imag_i(A), w), k, bit + 32); van = mfgetvan(fs, ga, &al, nlim, prec); return intAoo(van, nlim, al,w, P, A, k, prec); } /* fs symbol, naive summation, A != oo, im(A) > 0 and B = oo or im(B) > 0 */ static GEN mfsymboleval_direct(GEN fs, GEN path, GEN ga, GEN P) { GEN A, B, van, S, al, mf = fs_get_MF(fs); long w, nlimA, nlimB = 0, N = MF_get_N(mf), k = MF_get_k(mf); long bit = fs_get_bitprec(fs), prec = nbits2prec(bit); A = gel(path, 1); B = gel(path, 2); if (typ(B) == t_INFINITY) B = NULL; w = mfZC_width(N, gel(ga,1)); nlimA = mfperiod_prelim(gdivgu(imag_i(A),w), k, bit + 32); if (B) nlimB = mfperiod_prelim(gdivgu(imag_i(B),w), k, bit + 32); van = mfgetvan(fs, ga, &al, maxss(nlimA,nlimB), prec); S = intAoo(van, nlimA, al,w, P, A, k, prec); if (B) S = gsub(S, intAoo(van, nlimB, al,w, P, B, k, prec)); return RgX_embedall(S, fs_get_vE(fs)); } /* Computation of int_A^oo (f | ga)(t)(X-t)^{k-2} dt, assuming convergence; * fs is either a symbol or a pair [mf,F]. */ static GEN mfsymbolevalpartial(GEN fs, GEN A, GEN ga, long bit) { GEN Y, F, S, P, mf; long N, k, w, prec = nbits2prec(bit); get_mf_F(fs, &mf, &F); N = MF_get_N(mf); w = mfZC_width(N, gel(ga,1)); k = MF_get_k(mf); Y = gdivgu(imag_i(A), w); P = get_P(k, fetch_var(), prec); if (lg(fs) != 3 && gtodouble(Y)*(2*N) < 1) { /* true symbol + low imaginary part: use GL_2 action to improve */ GEN U, ga2, czd, A2 = cxredga0N(N, A, &U, &czd, 1); GEN vE = fs_get_vE(fs); ga2 = ZM_mul(ga, ZM_inv(U, NULL)); S = RgX_embedall(intAoo0(fs, A2, ga2, P, bit), vE); S = gsub(S, mfsymboleval(fs, mkvec2(mat2cusp(U), mkoo()), ga2, bit)); S = typ(S) == t_VEC? vecact_GL2(S, U, k): act_GL2(S, U, k); } else { S = intAoo0(fs, A, ga, P, bit); S = RgX_embedall(S, F? mfgetembed(F,prec): fs_get_vE(fs)); } delete_var(); return normalizeapprox(S, bit-20); } static GEN actal(GEN x, GEN vabd) { if (typ(x) == t_INFINITY) return x; return gdiv(gadd(gmul(gel(vabd,1), x), gel(vabd,2)), gel(vabd,3)); } static GEN unact(GEN z, GEN vabd, long k, long prec) { GEN res = gsubst(z, 0, actal(pol_x(0), vabd)); GEN CO = gpow(gdiv(gel(vabd,3), gel(vabd,1)), sstoQ(k-2, 2), prec); return gmul(CO, res); } GEN mfsymboleval(GEN fs, GEN path, GEN ga, long bitprec) { pari_sp av = avma; GEN tau, V, LM, S, CHI, mfpols, cosets, al, be, mf, F, vabd = NULL; long D, B, m, u, v, a, b, c, d, j, k, N, prec, tsc1, tsc2; if (checkfs_i(fs)) { get_mf_F(fs, &mf, &F); bitprec = minss(bitprec, fs_get_bitprec(fs)); } else { if (checkfs2_i(fs)) pari_err_TYPE("mfsymboleval [need integral k > 1]",fs); if (typ(fs) != t_VEC || lg(fs) != 3) pari_err_TYPE("mfsymboleval",fs); get_mf_F(fs, &mf, &F); mf = checkMF_i(mf); if (!mf ||!checkmf_i(F)) pari_err_TYPE("mfsymboleval",fs); } if (lg(path) != 3) pari_err_TYPE("mfsymboleval",path); if (typ(path) == t_MAT) path = pathmattovec(path); if (typ(path) != t_VEC) pari_err_TYPE("mfsymboleval",path); al = gel(path,1); be = gel(path,2); ga = ga? GL2toSL2(ga, &vabd): matid(2); if (vabd) { al = actal(al, vabd); be = actal(be, vabd); path = mkvec2(al, be); } tsc1 = cusp_AC(al, &a, &c); tsc2 = cusp_AC(be, &b, &d); prec = nbits2prec(bitprec); k = MF_get_k(mf); if (!tsc1) { GEN z2, z = mfsymbolevalpartial(fs, al, ga, bitprec); if (tsc2) z2 = d? mfsymboleval(fs, mkvec2(be, mkoo()), ga, bitprec): gen_0; else z2 = mfsymbolevalpartial(fs, be, ga, bitprec); z = gsub(z, z2); if (vabd) z = unact(z, vabd, k, prec); return gerepileupto(av, normalizeapprox(z, bitprec-20)); } else if (!tsc2) { GEN z = mfsymbolevalpartial(fs, be, ga, bitprec); if (c) z = gsub(mfsymboleval(fs, mkvec2(al, mkoo()), ga, bitprec), z); else z = gneg(z); if (vabd) z = unact(z, vabd, k, prec); return gerepileupto(av, normalizeapprox(z, bitprec-20)); } if (F) pari_err_TYPE("mfsymboleval", fs); D = a*d-b*c; if (!D) { set_avma(av); return RgX_embedall(gen_0, fs_get_vE(fs)); } mfpols = fs_get_pols(fs); cosets = fs_get_cosets(fs); CHI = MF_get_CHI(mf); N = MF_get_N(mf); cbezout(a, c, &u, &v); B = u*b + v*d; tau = mkmat22s(a, -v, c, u); V = gcf(sstoQ(B, D)); LM = shallowconcat(mkcol2(gen_1, gen_0), contfracpnqn(V, lg(V))); S = gen_0; m = lg(LM) - 2; for (j = 0; j < m; j++) { GEN M, P; long D, iN; M = mkmat2(gel(LM, j+2), gel(LM, j+1)); if (!odd(j)) gel(M,1) = ZC_neg(gel(M,1)); M = ZM_mul(tau, M); iN = mftocoset_iD(N, ZM_mul(ga, M), cosets, &D); P = gmul(gel(mfpols,iN), mfcharcxeval(CHI,D,prec)); S = gadd(S, act_GL2(P, ZM_inv(M, NULL), k)); } if (typ(S) == t_RFRAC) { GEN R, S1, co; gel(S,2) = primitive_part(gel(S,2), &co); if (co) gel(S,1) = gdiv(gel(S,1), gtofp(co,prec)); S1 = poldivrem(gel(S,1), gel(S,2), &R); if (gexpo(R) < -bitprec + 20) S = S1; } if (vabd) S = unact(S, vabd, k, prec); S = RgX_embedall(S, fs_get_vE(fs)); return gerepileupto(av, normalizeapprox(S, bitprec-20)); } /* v a scalar or t_POL; set *pw = a if expo(a) > E for some coefficient; * take the 'a' with largest exponent */ static void improve(GEN v, GEN *pw, long *E) { if (typ(v) != t_POL) { long e = gexpo(v); if (e > *E) { *E = e; *pw = v; } } else { long j, l = lg(v); for (j = 2; j < l; j++) improve(gel(v,j), pw, E); } } static GEN polabstorel(GEN rnfeq, GEN T) { long i, l; GEN U; if (typ(T) != t_POL) return T; U = cgetg_copy(T, &l); U[1] = T[1]; for (i = 2; i < l; i++) gel(U,i) = eltabstorel(rnfeq, gel(T,i)); return U; } static GEN bestapprnfrel(GEN x, GEN polabs, GEN roabs, GEN rnfeq, long prec) { x = bestapprnf(x, polabs, roabs, prec); if (rnfeq) x = polabstorel(rnfeq, liftpol_shallow(x)); return x; } /* v vector of polynomials polynomial in C[X] (possibly scalar). * Set *w = coeff with largest exponent and return T / *w, rationalized */ static GEN normal(GEN v, GEN polabs, GEN roabs, GEN rnfeq, GEN *w, long prec) { long i, l = lg(v), E = -(long)HIGHEXPOBIT; GEN dv; for (i = 1; i < l; i++) improve(gel(v,i), w, &E); v = RgV_Rg_mul(v, ginv(*w)); for (i = 1; i < l; i++) gel(v,i) = bestapprnfrel(gel(v,i), polabs,roabs,rnfeq,prec); v = Q_primitive_part(v,&dv); if (dv) *w = gmul(*w,dv); return v; } static GEN mfpetersson_i(GEN FS, GEN GS); GEN mfmanin(GEN FS, long bitprec) { pari_sp av = avma; GEN mf, M, vp, vm, cosets, CHI, vpp, vmm, f, T, P, vE, polabs, roabs, rnfeq; GEN pet; long N, k, lco, i, prec, lvE; if (!checkfs_i(FS)) { if (checkfs2_i(FS)) pari_err_TYPE("mfmanin [need integral k > 1]",FS); pari_err_TYPE("mfmanin",FS); } if (!mfs_iscusp(FS)) pari_err_TYPE("mfmanin [noncuspidal]",FS); mf = fs_get_MF(FS); vp = fs_get_pols(FS); cosets = fs_get_cosets(FS); bitprec = fs_get_bitprec(FS); N = MF_get_N(mf); k = MF_get_k(mf); CHI = MF_get_CHI(mf); lco = lg(cosets); vm = cgetg(lco, t_VEC); prec = nbits2prec(bitprec); for (i = 1; i < lco; i++) { GEN g = gel(cosets, i), c; long A = itos(gcoeff(g,1,1)), B = itos(gcoeff(g,1,2)); long C = itos(gcoeff(g,2,1)), D = itos(gcoeff(g,2,2)); long Dbar, ibar = mftocoset_iD(N, mkmat22s(-B,-A,D,C), cosets, &Dbar); c = mfcharcxeval(CHI, Dbar, prec); if (odd(k)) c = gneg(c); T = RgX_Rg_mul(gel(vp,ibar), c); if (typ(T) == t_POL && varn(T) == 0) T = RgX_recip(T); gel(vm,i) = T; } vpp = gadd(vp,vm); vmm = gsub(vp,vm); vE = fs_get_vE(FS); lvE = lg(vE); f = gel(fs_get_EF(FS), 1); P = mf_get_field(f); if (degpol(P) == 1) P = NULL; T = mfcharpol(CHI); if (degpol(T) == 1) T = NULL; if (T && P) { rnfeq = nf_rnfeqsimple(T, P); polabs = gel(rnfeq,1); roabs = gel(QX_complex_roots(polabs,prec), 1); } else { rnfeq = roabs = NULL; polabs = P? P: T; } pet = mfpetersson_i(FS, NULL); M = cgetg(lvE, t_VEC); for (i = 1; i < lvE; i++) { GEN p, m, wp, wm, petdiag, r, E = gel(vE,i); p = normal(RgXV_embed(vpp, E), polabs, roabs, rnfeq, &wp, prec); m = normal(RgXV_embed(vmm, E), polabs, roabs, rnfeq, &wm, prec); petdiag = typ(pet)==t_MAT? gcoeff(pet,i,i): pet; r = gdiv(imag_i(gmul(wp, conj_i(wm))), petdiag); r = bestapprnfrel(r, polabs, roabs, rnfeq, prec); gel(M,i) = mkvec2(mkvec2(p,m), mkvec3(wp,wm,r)); } return gerepilecopy(av, lvE == 2? gel(M,1): M); } /* flag = 0: full, flag = +1 or -1, odd/even */ /* Basis of period polynomials in level 1. */ GEN mfperiodpolbasis(long k, long flag) { pari_sp av = avma; long i, j, n = k - 2; GEN M, C, v; if (k <= 4) return cgetg(1,t_VEC); M = cgetg(k, t_MAT); C = matpascal(n); if (!flag) for (j = 0; j <= n; j++) { gel(M, j+1) = v = cgetg(k, t_COL); for (i = 0; i <= j; i++) gel(v, i+1) = gcoeff(C, j+1, i+1); for (; i <= n; i++) gel(v, i+1) = gcoeff(C, n-j+1, i-j+1); } else for (j = 0; j <= n; j++) { gel(M, j+1) = v = cgetg(k, t_COL); for (i = 0; i <= n; i++) { GEN a = i < j ? gcoeff(C, j+1, i+1) : gen_0; if (i + j >= n) { GEN b = gcoeff(C, j+1, i+j-n+1); a = flag < 0 ? addii(a,b) : subii(a,b); } gel(v, i+1) = a; } } return gerepilecopy(av, RgM_to_RgXV(ZM_ker(M), 0)); } static int zero_at_cusp(GEN mf, GEN F, GEN c) { GEN v = evalcusp(mf, F, c, LOWDEFAULTPREC); return (gequal0(v) || gexpo(v) <= -62); } /* Compute list E of j such that F|_k g_j vanishes at oo: return [E, s(E)] */ static void mffvanish(GEN mf, GEN F, GEN G, GEN cosets, GEN *pres, GEN *press) { long j, lc = lg(cosets), N = MF_get_N(mf); GEN v, vs; *pres = v = zero_zv(lc-1); *press= vs = zero_zv(lc-1); for (j = 1; j < lc; j++) { GEN ga = gel(cosets,j), c = mat2cusp(ga); if (zero_at_cusp(mf, F, c)) v[j] = vs[ mftocoset_i(N, ZM_mulS(ga), cosets) ] = 1; else if (!zero_at_cusp(mf, G, c)) pari_err_IMPL("divergent Petersson product"); } } static GEN Haberland(GEN PF, GEN PG, GEN vEF, GEN vEG, long k) { GEN S = gen_0, vC = vecbinomial(k-2); /* vC[n+1] = (-1)^n binom(k-2,n) */ long n, j, l = lg(PG); for (n = 2; n < k; n+=2) gel(vC,n) = negi(gel(vC,n)); for (j = 1; j < l; j++) { GEN PFj = gel(PF,j), PGj = gel(PG,j); for (n = 0; n <= k-2; n++) { GEN a = RgX_coeff(PGj, k-2-n), b = RgX_coeff(PFj, n); a = Rg_embedall(a, vEG); b = Rg_embedall(b, vEF); a = conj_i(a); if (typ(a) == t_VEC) settyp(a, t_COL); /* a*b = scalar or t_VEC or t_COL or t_MAT */ S = gadd(S, gdiv(gmul(a,b), gel(vC,n+1))); } } S = mulcxpowIs(gmul2n(S, 1-k), 1+k); return vEF==vEG? real_i(S): S; } /* F1S, F2S both symbols, same mf */ static GEN mfpeterssonnoncusp(GEN F1S, GEN F2S) { pari_sp av = avma; GEN mf, F1, F2, GF1, GF2, P2, cosets, vE1, vE2, FE1, FE2, P; GEN I, IP1, RHO, RHOP1, INF, res, ress; const double height = sqrt(3.)/2; long k, r, j, bitprec, prec; mf = fs_get_MF(F1S); FE1 = fs_get_EF(F1S); F1 = gel(FE1, 1); FE2 = fs_get_EF(F2S); F2 = gel(FE2, 1); cosets = fs_get_cosets(F1S); bitprec = minuu(fs_get_bitprec(F1S), fs_get_bitprec(F2S)); prec = nbits2prec(bitprec); F1S = fs_set_expan(F1S, mfgaexpansionall(mf, FE1, cosets, height, prec)); if (F2S != F1S) F2S = fs_set_expan(F2S, mfgaexpansionall(mf, FE2, cosets, height, prec)); k = MF_get_k(mf); r = lg(cosets) - 1; vE1 = fs_get_vE(F1S); vE2 = fs_get_vE(F2S); I = gen_I(); IP1 = mkcomplex(gen_1,gen_1); RHO = rootsof1u_cx(3, prec+EXTRAPREC64); RHOP1 = gaddsg(1, RHO); INF = mkoo(); mffvanish(mf, F1, F2, cosets, &res, &ress); P2 = fs_get_pols(F2S); GF1 = cgetg(r+1, t_VEC); GF2 = cgetg(r+1, t_VEC); P = get_P(k, fetch_var(), prec); for (j = 1; j <= r; j++) { GEN g = gel(cosets,j); if (res[j]) { gel(GF1,j) = mfsymboleval_direct(F1S, mkvec2(RHOP1,INF), g, P); gel(GF2,j) = mfsymboleval_direct(F2S, mkvec2(I,IP1), g, P); } else if (ress[j]) { gel(GF1,j) = mfsymboleval_direct(F1S, mkvec2(RHOP1,RHO), g, P); gel(GF2,j) = mfsymboleval_direct(F2S, mkvec2(I,INF), g, P); } else { gel(GF1,j) = mfsymboleval_direct(F1S, mkvec2(RHO,I), g, P); gel(GF2,j) = gneg(gel(P2,j)); /* - symboleval(F2S, [0,oo] */ } } delete_var(); return gerepileupto(av, gdivgu(Haberland(GF1,GF2, vE1,vE2, k), r)); } /* Petersson product of F and G, given by mfsymbol's [k > 1 integral] */ static GEN mfpetersson_i(GEN FS, GEN GS) { pari_sp av = avma; GEN mf, ESF, ESG, PF, PG, PH, CHI, cosets, vEF, vEG; long k, r, j, N, bitprec, prec; if (!checkfs_i(FS)) pari_err_TYPE("mfpetersson",FS); mf = fs_get_MF(FS); ESF = fs_get_vES(FS); if (!GS) GS = FS; else { if (!checkfs_i(GS)) pari_err_TYPE("mfpetersson",GS); if (!mfs_checkmf(GS, mf)) pari_err_TYPE("mfpetersson [different mf]", mkvec2(FS,GS)); } ESG = fs_get_vES(GS); if (!gequal0(gel(ESF,1)) && !gequal0(gel(ESG,1))) return mfpeterssonnoncusp(FS, GS); if (gequal0(gel(ESF,2)) || gequal0(gel(ESG,2))) return gc_const(av, gen_0); N = MF_get_N(mf); k = MF_get_k(mf); CHI = MF_get_CHI(mf); PF = fs_get_pols(FS); vEF = fs_get_vE(FS); PG = fs_get_pols(GS); vEG = fs_get_vE(GS); cosets = fs_get_cosets(FS); bitprec = minuu(fs_get_bitprec(FS), fs_get_bitprec(GS)); prec = nbits2prec(bitprec); r = lg(PG)-1; PH = cgetg(r+1, t_VEC); for (j = 1; j <= r; j++) { GEN ga = gel(cosets,j), PGj1, PGjm1; long iT, D; iT = mftocoset_iD(N, ZM_mulTi(ga), cosets, &D); PGj1 = RgX_translate(gel(PG, iT), gen_1); PGj1 = RgX_Rg_mul(PGj1, mfcharcxeval(CHI, D, prec)); iT = mftocoset_iD(N, ZM_mulT(ga), cosets, &D); PGjm1 = RgX_translate(gel(PG,iT), gen_m1); PGjm1 = RgX_Rg_mul(PGjm1, mfcharcxeval(CHI, D, prec)); gel(PH,j) = gsub(PGj1, PGjm1); } return gerepileupto(av, gdivgu(Haberland(PF, PH, vEF, vEG, k), 6*r)); } /****************************************************************/ /* Petersson products using Nelson-Collins */ /****************************************************************/ /* Compute W(k,z) = sum_{m >= 1} (mz)^{k-1}(mzK_{k-2}(mz)-K_{k-1}(mz)) * for z>0 and absolute accuracy < 2^{-B}. * K_k(x) ~ (Pi/(2x))^{1/2} e^{-x} */ static void Wparams(GEN *ph, long *pN, long k, double x, long prec) { double B = prec2nbits(prec) + 10; double C = B + k*log(x)/M_LN2 + 1, D = C*M_LN2 + 2.065; double F = 2 * ((C - 1) * M_LN2 + log(gtodouble(mpfact(k)))) / x; double T = log(F) * (1 + 2*k/x/F), PI2 = M_PI*M_PI; *pN = (long)ceil((T/PI2) * (D + log(D/PI2))); *ph = gprec_w(dbltor(T / *pN), prec); } static void Wcoshall(GEN *pCH, GEN *pCHK, GEN *pCHK1, GEN h, long N, long k, long prec) { GEN CH, CHK, CHK1, z = gexp(h, prec); GEN PO = gpowers(z, N), POK1 = gpowers(gpowgs(z, k-1), N); GEN E = ginv(gel(PO, N + 1)); /* exp(-hN) */ GEN E1 = ginv(gel(POK1, N + 1)); /* exp(-(k-1)h) */ long j; *pCH = CH = cgetg(N+1, t_VEC); *pCHK = CHK = cgetg(N+1, t_VEC); *pCHK1 = CHK1 = cgetg(N+1, t_VEC); for (j = 1; j <= N; j++) { GEN eh = gel(PO, j+1), emh = gmul(gel(PO, N-j+1), E); /* e^{jh}, e^{-jh} */ GEN ek1h = gel(POK1, j+1), ek1mh = gmul(gel(POK1, N-j+1), E1); gel(CH, j) = gmul2n(gadd(eh, emh), -1); /* cosh(jh) */ gel(CHK1,j) = gmul2n(gadd(ek1h, ek1mh), -1); /* cosh((k-1)jh) */ gel(CHK, j) = gmul2n(gadd(gmul(eh, ek1h), gmul(emh, ek1mh)), -1); } } /* computing W(k,x) via integral */ static GEN Wint(long k, GEN vP, GEN x, long prec) { GEN P, P1, S1, S, h, CH, CHK, CHK1; long N, j; Wparams(&h, &N, k, gtodouble(x), prec); Wcoshall(&CH, &CHK, &CHK1, h, N, k, prec); P = gel(vP, k+1); P1 = gel(vP, k); S = S1 = NULL; for (j = 0; j <= N; j++) { GEN eh = gexp(j? gmul(x, gel(CH, j)): x, prec); GEN eh1 = gsubgs(eh, 1), eh1k = gpowgs(eh1, k), t1, t; t = gdiv(poleval(P, eh), gmul(eh1, eh1k)); t1 = gdiv(poleval(P1, eh), eh1k); if (j) { S = gadd(S, gmul(t, gel(CHK, j))); S1 = gadd(S1, gmul(t1, gel(CHK1, j))); } else { S = gmul2n(t, -1); S1 = gmul2n(t1, -1); } } return gmul(gmul(h, gpowgs(x, k-1)), gsub(gmul(x, S), gmulsg(2*k-1, S1))); } static GEN get_vP(long k) { GEN P, v = cgetg(k+2, t_VEC), Q = deg1pol_shallow(gen_1,gen_m1,0); long j; gel(v,1) = gen_1; gel(v,2) = P = pol_x(0); for (j = 2; j <= k; j++) gel(v,j+1) = P = RgX_shift_shallow(gsub(gmulsg(j, P), gmul(Q, ZX_deriv(P))), 1); return v; } /* vector of (-1)^j(1/(exp(x)-1))^(j) [x = z] * z^j for 0<=j<=r */ static GEN VS(long r, GEN z, GEN V, long prec) { GEN e = gexp(z, prec), c = ginv(gsubgs(e,1)); GEN T = gpowers0(gmul(c, z), r, c); long j; V = gsubst(V, 0, e); for (j = 1; j <= r + 1; j++) gel(V,j) = gmul(gel(V,j), gel(T,j)); return V; } /* U(r,x)=sum_{m >= 1} (mx)^k K_k(mx), k = r+1/2 */ static GEN Unelson(long r, GEN V) { GEN S = gel(V,r+1), C = gen_1; /* (r+j)! / j! / (r-j)! */ long j; if (!r) return S; for (j = 1; j <= r; j++) { C = gdivgu(gmulgu(C, (r+j)*(r-j+1)), j); S = gadd(S, gmul2n(gmul(C, gel(V, r-j+1)), -j)); } return S; } /* W(r+1/2,z) / sqrt(Pi/2) */ static GEN Wint2(long r, GEN vP, GEN z, long prec) { GEN R, V = VS(r, z, vP, prec); R = Unelson(r, V); if (r) R = gsub(R, gmulsg(2*r, Unelson(r-1, V))); return R; } typedef GEN(*Wfun_t)(long, GEN, GEN, long); static GEN WfromZ(GEN Z, GEN vP, GEN gkm1, Wfun_t W, long k, GEN pi4, long prec) { pari_sp av = avma; GEN Zk = gpow(Z, gkm1, prec), z = gmul(pi4, gsqrt(Z,prec)); return gerepileupto(av, gdiv(W(k, vP, z, prec), Zk)); } /* mf a true mf or an fs2 */ static GEN fs2_init(GEN mf, GEN F, long bit) { pari_sp av = avma; long i, l, lim, N, k, k2, prec = nbits2prec(bit); GEN DEN, cusps, tab, gk, gkm1, W0, vW, vVW, vVF, vP, al0; GEN vE = mfgetembed(F, prec), pi4 = Pi2n(2, prec); Wfun_t Wf; if (lg(mf) == 7) { vW = cusps = NULL; /* true mf */ DEN = tab = NULL; /* -Wall */ } else { /* mf already an fs2, reset if its precision is too low */ vW = (fs2_get_bitprec(mf) < bit)? NULL: fs2_get_W(mf); cusps = fs2_get_cusps(mf); DEN = fs2_get_den(mf); mf = fs2_get_MF(mf); } N = MF_get_N(mf); gk = MF_get_gk(mf); gkm1 = gsubgs(gk, 1); k2 = itos(gmul2n(gk,1)); Wf = odd(k2)? Wint2: Wint; k = k2 >> 1; vP = get_vP(k); if (vW) lim = (lg(gel(vW,1)) - 2) / N; /* vW[1] attached to cusp 0, width N */ else { /* true mf */ double B = (bit + 10)*M_LN2; double L = (B + k2*log(B)/2 + k2*k2*log(B)/(4*B)) / (4*M_PI); long n, Lw; lim = ((long)ceil(L*L)); Lw = N*lim; tab = cgetg(Lw+1,t_VEC); for (n = 1; n <= Lw; n++) gel(tab,n) = WfromZ(uutoQ(n,N), vP, gkm1, Wf, k, pi4, prec); if (!cusps) cusps = mfcusps_i(N); DEN = gmul2n(gmulgu(gpow(Pi2n(3, prec), gkm1, prec), mypsiu(N)), -2); if (odd(k2)) DEN = gdiv(DEN, sqrtr_abs(Pi2n(-1,prec))); } l = lg(cusps); vVF = cgetg(l, t_VEC); vVW = cgetg(l, t_VEC); al0 = cgetg(l, t_VECSMALL); W0 = k2==1? ginv(pi4): gen_0; for (i = 1; i < l; i++) { long A, C, w, wi, Lw, n; GEN VF, W, paramsF, al; (void)cusp_AC(gel(cusps,i), &A,&C); wi = ugcd(N, C*C); w = N / wi; Lw = w * lim; VF = mfslashexpansion(mf, F, cusp2mat(A,C), Lw, 0, ¶msF, prec); /* paramsF[2] = w */ al = gel(paramsF, 1); if (gequal0(al)) al = NULL; for (n = 0; n <= Lw; n++) { GEN a = gel(VF,n+1); gel(VF,n+1) = gequal0(a)? gen_0: Rg_embedall(a, vE); } if (vW) W = gel(vW, i); else { W = cgetg(Lw+2, t_VEC); for (n = 0; n <= Lw; n++) gel(W, n+1) = al? WfromZ(gadd(al,uutoQ(n,w)),vP,gkm1,Wf,k,pi4, prec) : (n? gel(tab, n * wi): W0); } al0[i] = !al; gel(vVF, i) = VF; gel(vVW, i) = W; } if (k2 <= 1) al0 = zero_zv(l-1); /* no need to test for convergence */ return gerepilecopy(av, mkvecn(7, mf,vVW,cusps,vVF,utoipos(bit),al0,DEN)); } static GEN mfpetersson2(GEN Fs, GEN Gs) { pari_sp av = avma; GEN VC, RES, vF, vG, vW = fs2_get_W(Fs), al0 = fs2_get_al0(Fs); long N = MF_get_N(fs2_get_MF(Fs)), j, lC; VC = fs2_get_cusps(Fs); lC = lg(VC); vF = fs2_get_F(Fs); vG = Gs? fs2_get_F(Gs): vF; RES = gen_0; for (j = 1; j < lC; j++) { GEN W = gel(vW,j), VF = gel(vF,j), VG = gel(vG,j), T = gen_0; long A, C, w, n, L = lg(W); pari_sp av = avma; (void)cusp_AC(gel(VC,j), &A,&C); w = N/ugcd(N, C*C); if (al0[j] && !isintzero(gel(VF,1)) && !isintzero(gel(VG,1))) pari_err_IMPL("divergent Petersson product"); for (n = 1; n < L; n++) { GEN b = gel(VF,n), a = gel(VG,n); if (!isintzero(a) && !isintzero(b)) { T = gadd(T, gmul(gel(W,n), gmul(conj_i(a),b))); if (gc_needed(av,2)) T = gerepileupto(av,T); } } if (w != 1) T = gmulgu(T,w); RES = gerepileupto(av, gadd(RES, T)); } if (!Gs) RES = real_i(RES); return gerepileupto(av, gdiv(RES, fs2_get_den(Fs))); } static long symbol_type(GEN F) { if (checkfs_i(F)) return 1; if (checkfs2_i(F)) return 2; return 0; } static int symbol_same_mf(GEN F, GEN G) { return gequal(gmael(F,1,1), gmael(G,1,1)); } GEN mfpetersson(GEN F, GEN G) { long tF = symbol_type(F); if (!tF) pari_err_TYPE("mfpetersson",F); if (G) { long tG = symbol_type(G); if (!tG) pari_err_TYPE("mfpetersson",F); if (tF != tG || !symbol_same_mf(F,G)) pari_err_TYPE("mfpetersson [incompatible symbols]", mkvec2(F,G)); } return (tF == 1)? mfpetersson_i(F, G): mfpetersson2(F, G); } /****************************************************************/ /* projective Galois representation, weight 1 */ /****************************************************************/ static void moreorders(long N, GEN CHI, GEN F, GEN *pP, GEN *pO, ulong *bound) { pari_sp av = avma; forprime_t iter; ulong a = *bound+1, b = 2*(*bound), p; long i = 1; GEN P, O, V = mfcoefs_i(F, b, 1); *bound = b; P = cgetg(b-a+2, t_VECSMALL); O = cgetg(b-a+2, t_VECSMALL); u_forprime_init(&iter, a, b); while((p = u_forprime_next(&iter))) if (N % p) { O[i] = mffindrootof1(V, p, CHI); P[i++] = p; } setlg(P, i); *pP = shallowconcat(*pP, P); setlg(O, i); *pO = shallowconcat(*pO, O); gerepileall(av, 2, pP, pO); } static GEN search_abelian(GEN nf, long n, long k, GEN N, GEN CHI, GEN F, GEN *pP, GEN *pO, ulong *bound, long prec) { pari_sp av = avma; GEN bnr, cond, H, cyc, gn, T, Bquo, P, E; long sN = itos(N), r1 = nf_get_r1(nf), i, j, d; cond = idealfactor(nf, N); P = gel(cond,1); E = gel(cond,2); for (i = j = 1; i < lg(P); i++) { GEN pr = gel(P,i), Ej = gen_1; long p = itos(pr_get_p(pr)); if (p == n) { long e = pr_get_e(pr); /* 1 + [e*p/(p-1)] */ Ej = utoipos(1 + (e*p) / (p-1)); } else { long f = pr_get_f(pr); if (Fl_powu(p % n, f, n) != 1) continue; } gel(P,j) = pr; gel(E,j) = Ej; j++; } setlg(P,j); setlg(E,j); cond = mkvec2(cond, const_vec(r1, gen_1)); bnr = Buchraymod(Buchall(nf, nf_FORCE, prec), cond, nf_INIT, utoipos(n)); cyc = bnr_get_cyc(bnr); d = lg(cyc)-1; H = zv_diagonal(ZV_to_Flv(cyc, n)); gn = utoi(n); for (i = 1;;) { for(j = 2; i < lg(*pO); i++) { long o, q = (*pP)[i]; GEN pr = idealprimedec_galois(nf, stoi(q)); o = ((*pO)[i] / pr_get_f(pr)) % n; if (o) { GEN v = ZV_to_Flv(isprincipalray(bnr, pr), n); H = vec_append(H, Flv_Fl_mul(v, o, n)); } } H = Flm_image(H, n); if (lg(cyc)-lg(H) <= k) break; moreorders(sN, CHI, F, pP, pO, bound); } H = hnfmodid(shallowconcat(zm_to_ZM(H), diagonal_shallow(cyc)), gn); Bquo = cgetg(k+1, t_MAT); for (i = j = 1; i <= d; i++) if (!equali1(gcoeff(H,i,i))) gel(Bquo,j++) = col_ei(d,i); for (i = 1, T = NULL; i<=k; i++) { GEN Hi = hnfmodid(shallowconcat(H, vecsplice(Bquo,i)), gn); GEN pol = rnfkummer(bnr, Hi, prec); T = T? nfcompositum(nf, T, pol, 2): pol; } T = rnfequation(nf, T); return gc_all(av, 3, &T, pP, pO); } static GEN search_solvable(GEN LG, GEN mf, GEN F, long prec) { GEN N = MF_get_gN(mf), CHI = MF_get_CHI(mf), pol, O, P, nf, Nfa; long i, l = lg(LG), v = fetch_var(); ulong bound = 1; O = cgetg(1, t_VECSMALL); /* projective order of rho(Frob_p) */ P = cgetg(1, t_VECSMALL); Nfa = Z_factor(N); pol = pol_x(v); for (i = 1; i < l; i++) { /* n prime, find a (Z/nZ)^k - extension */ GEN G = gel(LG,i); long n = G[1], k = G[2]; nf = nfinitred(mkvec2(pol,Nfa), prec); pol = search_abelian(nf, n, k, N, CHI, F, &P, &O, &bound, prec); setvarn(pol,v); } delete_var(); setvarn(pol,0); return pol; } static GEN search_A5(GEN mf, GEN F) { GEN CHI = MF_get_CHI(mf), O, P, L; long N = MF_get_N(mf), i, j, lL, nd, r; ulong bound = 1; r = radicalu(N); L = veccond_to_A5(zv_z_mul(divisorsu(N/r),r), 2); lL = lg(L); nd = lL-1; if (nd == 1) return gmael(L,1,1); O = cgetg(1, t_VECSMALL); /* projective order of rho(Frob_p) */ P = cgetg(1, t_VECSMALL); for(i = 1; nd > 1; ) { long l; moreorders(N, CHI, F, &P, &O, &bound); l = lg(P); for ( ; i < l; i++) { ulong p = P[i], f = O[i]; for (j = 1; j < lL; j++) if (gel(L,j)) { GEN FE = ZpX_primedec(gmael(L,j,1), utoi(p)), F = gel(FE,1); long nF = lg(F)-1; if (!equaliu(gel(F, nF), f)) { gel(L,j) = NULL; nd--; } } if (nd <= 1) break; } } for (j = 1; j < lL; j++) if (gel(L,j)) return gmael(L,j,1); return NULL; } GEN mfgaloisprojrep(GEN mf, GEN F, long prec) { pari_sp av = avma; GEN LG = NULL; if (!checkMF_i(mf) && !checkmf_i(F)) pari_err_TYPE("mfgaloisrep", F); switch( itos(mfgaloistype(mf,F)) ) { case 0: case -12: LG = mkvec2(mkvecsmall2(3,1), mkvecsmall2(2,2)); break; case -24: LG = mkvec3(mkvecsmall2(2,1), mkvecsmall2(3,1), mkvecsmall2(2,2)); break; case -60: return gerepilecopy(av, search_A5(mf, F)); default: pari_err_IMPL("mfgaloisprojrep for types D_n"); } return gerepilecopy(av, search_solvable(LG, mf, F, prec)); } pari-2.17.2/src/basemath/RgX.c0000644000175000017500000023514314760123736014424 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_pol /*******************************************************************/ /* */ /* GENERIC */ /* */ /*******************************************************************/ /* Return optimal parameter l for the evaluation of n/m polynomials of degree d Fractional values can be used if the evaluations are done with different accuracies, and thus have different weights. */ long brent_kung_optpow(long d, long n, long m) { long p, r; long pold=1, rold=n*(d-1); for(p=2; p<=d; p++) { r = m*(p-1) + n*((d-1)/p); if (rone(E)); if (!z) z = gen_0; for (i=1; i<=n; i++) { GEN t = cmul(E,P,a+i,gel(V,i+1)); if (t) { z = ff->add(E, z, t); if (gc_needed(av,2)) z = gerepileupto(av, z); } } return ff->red(E,z); } /* Brent & Kung * (Fast algorithms for manipulating formal power series, JACM 25:581-595, 1978) * * V as output by FpXQ_powers(x,l,T,p). For optimal performance, l is as given * by brent_kung_optpow */ GEN gen_bkeval_powers(GEN P, long d, GEN V, void *E, const struct bb_algebra *ff, GEN cmul(void *E, GEN P, long a, GEN x)) { pari_sp av = avma; long l = lg(V)-1; GEN z, u; if (d < 0) return ff->zero(E); if (d < l) return gerepileupto(av, gen_RgXQ_eval_powers(P,V,0,d,E,ff,cmul)); if (l<2) pari_err_DOMAIN("gen_RgX_bkeval_powers", "#powers", "<",gen_2,V); if (DEBUGLEVEL>=8) { long cnt = 1 + (d - l) / (l-1); err_printf("RgX_RgXQV_eval(%ld/%ld): %ld RgXQ_mul\n", d, l-1, cnt); } d -= l; z = gen_RgXQ_eval_powers(P,V,d+1,l-1,E,ff,cmul); while (d >= l-1) { d -= l-1; u = gen_RgXQ_eval_powers(P,V,d+1,l-2,E,ff,cmul); z = ff->add(E,u, ff->mul(E,z,gel(V,l))); if (gc_needed(av,2)) z = gerepileupto(av, z); } u = gen_RgXQ_eval_powers(P,V,0,d,E,ff,cmul); z = ff->add(E,u, ff->mul(E,z,gel(V,d+2))); return gerepileupto(av, ff->red(E,z)); } GEN gen_bkeval(GEN Q, long d, GEN x, int use_sqr, void *E, const struct bb_algebra *ff, GEN cmul(void *E, GEN P, long a, GEN x)) { pari_sp av = avma; GEN z, V; long rtd; if (d < 0) return ff->zero(E); rtd = (long) sqrt((double)d); V = gen_powers(x,rtd,use_sqr,E,ff->sqr,ff->mul,ff->one); z = gen_bkeval_powers(Q, d, V, E, ff, cmul); return gerepileupto(av, z); } static GEN _gen_nored(void *E, GEN x) { (void)E; return x; } static GEN _gen_add(void *E, GEN x, GEN y) { (void)E; return gadd(x, y); } static GEN _gen_sub(void *E, GEN x, GEN y) { (void)E; return gsub(x, y); } static GEN _gen_mul(void *E, GEN x, GEN y) { (void)E; return gmul(x, y); } static GEN _gen_sqr(void *E, GEN x) { (void)E; return gsqr(x); } static GEN _gen_one(void *E) { (void)E; return gen_1; } static GEN _gen_zero(void *E) { (void)E; return gen_0; } static struct bb_algebra Rg_algebra = { _gen_nored, _gen_add, _gen_sub, _gen_mul, _gen_sqr,_gen_one,_gen_zero }; static GEN _gen_cmul(void *E, GEN P, long a, GEN x) {(void)E; return gmul(gel(P,a+2), x);} GEN RgX_RgV_eval(GEN Q, GEN x) { return gen_bkeval_powers(Q, degpol(Q), x, NULL, &Rg_algebra, _gen_cmul); } GEN RgX_Rg_eval_bk(GEN Q, GEN x) { return gen_bkeval(Q, degpol(Q), x, 1, NULL, &Rg_algebra, _gen_cmul); } GEN RgXV_RgV_eval(GEN Q, GEN x) { long i, l = lg(Q), vQ = gvar(Q); GEN v = cgetg(l, t_VEC); for (i = 1; i < l; i++) { GEN Qi = gel(Q, i); gel(v, i) = typ(Qi)==t_POL && varn(Qi)==vQ? RgX_RgV_eval(Qi, x): gcopy(Qi); } return v; } GEN RgX_homogenous_evalpow(GEN P, GEN A, GEN B) { pari_sp av = avma, btop; long i, d = degpol(P), o; GEN s; if (signe(P)==0) return pol_0(varn(P)); s = gel(P, d+2); if (d == 0) return gcopy(s); o = RgX_deflate_order(P); if (o > 1) A = gpowgs(A, o); btop = avma; for (i = d-o; i >= 0; i-=o) { s = gadd(gmul(s, A), gmul(gel(B,d+1-i), gel(P,i+2))); if (gc_needed(btop,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"RgX_homogenous_eval(%ld)",i); s = gerepileupto(btop, s); } } return gerepileupto(av, s); } GEN QXQX_homogenous_evalpow(GEN P, GEN A, GEN B, GEN T) { pari_sp av = avma; long i, d = degpol(P), v = varn(A); GEN s; if (signe(P)==0) return pol_0(v); if (d == 0) return scalarpol(gel(P, d+2), v); s = scalarpol_shallow(gel(P, d+2), v); for (i = d-1; i >= 0; i--) { GEN c = gel(P,i+2), b = gel(B,d+1-i); s = RgX_add(QXQX_mul(s, A, T), typ(c)==t_POL ? QXQX_QXQ_mul(b, c, T): gmul(b, c)); if (gc_needed(av,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"QXQX_homogenous_eval(%ld)",i); s = gerepileupto(av, s); } } return gerepileupto(av, s); } const struct bb_algebra * get_Rg_algebra(void) { return &Rg_algebra; } static struct bb_ring Rg_ring = { _gen_add, _gen_mul, _gen_sqr }; static GEN _RgX_divrem(void *E, GEN x, GEN y, GEN *r) { (void) E; return RgX_divrem(x, y, r); } GEN RgX_digits(GEN x, GEN T) { long d = degpol(T), n = (lgpol(x)+d-1)/d; return gen_digits(x,T,n,NULL, &Rg_ring, _RgX_divrem); } /*******************************************************************/ /* */ /* RgX */ /* */ /*******************************************************************/ long RgX_equal(GEN x, GEN y) { long i = lg(x); if (i != lg(y)) return 0; for (i--; i > 1; i--) if (!gequal(gel(x,i),gel(y,i))) return 0; return 1; } /* Returns 1 in the base ring over which x is defined */ /* HACK: this also works for t_SER */ GEN Rg_get_1(GEN x) { GEN p, T; long i, lx, tx = Rg_type(x, &p, &T, &lx); if (RgX_type_is_composite(tx)) RgX_type_decode(tx, &i /*junk*/, &tx); switch(tx) { case t_INTMOD: retmkintmod(is_pm1(p)? gen_0: gen_1, icopy(p)); case t_PADIC: return cvtop(gen_1, p, lx); case t_FFELT: return FF_1(T); default: return gen_1; } } /* Returns 0 in the base ring over which x is defined */ /* HACK: this also works for t_SER */ GEN Rg_get_0(GEN x) { GEN p, T; long i, lx, tx = Rg_type(x, &p, &T, &lx); if (RgX_type_is_composite(tx)) RgX_type_decode(tx, &i /*junk*/, &tx); switch(tx) { case t_INTMOD: retmkintmod(gen_0, icopy(p)); case t_PADIC: return zeropadic(p, lx); case t_FFELT: return FF_zero(T); default: return gen_0; } } GEN QX_ZXQV_eval(GEN P, GEN V, GEN dV) { long i, n = degpol(P); GEN z, dz, dP; if (n < 0) return gen_0; P = Q_remove_denom(P, &dP); z = gel(P,2); if (n == 0) return icopy(z); if (dV) z = mulii(dV, z); /* V[1] = dV */ z = ZX_Z_add_shallow(ZX_Z_mul(gel(V,2),gel(P,3)), z); for (i=2; i<=n; i++) z = ZX_add(ZX_Z_mul(gel(V,i+1),gel(P,2+i)), z); dz = mul_denom(dP, dV); return dz? RgX_Rg_div(z, dz): z; } /* Return P(h * x), not memory clean */ GEN RgX_unscale(GEN P, GEN h) { long i, l = lg(P); GEN hi = gen_1, Q = cgetg(l, t_POL); Q[1] = P[1]; if (l == 2) return Q; gel(Q,2) = gcopy(gel(P,2)); for (i=3; i 1 && i < l; i++) gel(Q, i) = diviiexact(gel(P, i), gel(H, j--)); if (i == l) return Q; gel(Q, i) = gel(P, i); i++; for (j = 2; i < l; i++) gel(Q, i) = mulii(gel(P, i), gel(H, j++)); return Q; } GEN RgXV_unscale(GEN x, GEN h) { if (isint1(h)) return gcopy(x); pari_APPLY_same(RgX_unscale(gel(x,i), h)); } /* Return h^degpol(P) P(x / h), not memory clean */ GEN RgX_rescale(GEN P, GEN h) { long i, l = lg(P); GEN Q = cgetg(l,t_POL), hi = h; gel(Q,l-1) = gel(P,l-1); for (i=l-2; i>=2; i--) { gel(Q,i) = gmul(gel(P,i), hi); if (i == 2) break; hi = gmul(hi,h); } Q[1] = P[1]; return Q; } GEN RgXV_rescale(GEN x, GEN h) { if (isint1(h)) return RgX_copy(x); pari_APPLY_same(RgX_rescale(gel(x,i), h)); } /* A(X^d) --> A(X) */ GEN RgX_deflate(GEN x0, long d) { GEN z, y, x; long i,id, dy, dx = degpol(x0); if (d == 1 || dx <= 0) return leafcopy(x0); dy = dx/d; y = cgetg(dy+3, t_POL); y[1] = x0[1]; z = y + 2; x = x0+ 2; for (i=id=0; i<=dy; i++,id+=d) gel(z,i) = gel(x,id); return y; } GEN RgX_homogenize(GEN P, long v) { long i, l, d; GEN Q = cgetg_copy(P, &l); Q[1] = P[1]; d = l-3; for (i = 2; i < l; i++) gel(Q,i) = monomial(gel(P,i), d--, v); return Q; } /* F a t_RFRAC */ long rfrac_deflate_order(GEN F) { GEN N = gel(F,1), D = gel(F,2); long m = (degpol(D) <= 0)? 0: RgX_deflate_order(D); if (m == 1) return 1; if (typ(N) == t_POL && varn(N) == varn(D)) m = cgcd(m, RgX_deflate_order(N)); return m; } /* F a t_RFRAC */ GEN rfrac_deflate_max(GEN F, long *m) { *m = rfrac_deflate_order(F); return rfrac_deflate(F, *m); } /* F a t_RFRAC */ GEN rfrac_deflate(GEN F, long m) { GEN N = gel(F,1), D = gel(F,2); if (m == 1) return F; if (typ(N) == t_POL && varn(N) == varn(D)) N = RgX_deflate(N, m); D = RgX_deflate(D, m); return mkrfrac(N, D); } /* return x0(X^d) */ GEN RgX_inflate(GEN x0, long d) { long i, id, dy, dx = degpol(x0); GEN x = x0 + 2, z, y; if (dx <= 0) return leafcopy(x0); dy = dx*d; y = cgetg(dy+3, t_POL); y[1] = x0[1]; z = y + 2; for (i=0; i<=dy; i++) gel(z,i) = gen_0; for (i=id=0; i<=dx; i++,id+=d) gel(z,id) = gel(x,i); return y; } /* return P(X + c) using destructive Horner, optimize for c = 1,-1 */ static GEN RgX_translate_basecase(GEN P, GEN c) { pari_sp av = avma; GEN Q, R; long i, k, n; if (!signe(P) || gequal0(c)) return RgX_copy(P); Q = leafcopy(P); R = Q+2; n = degpol(P); if (isint1(c)) { for (i=1; i<=n; i++) { for (k=n-i; k1) pari_warn(warnmem,"RgX_translate(1), i = %ld/%ld", i,n); Q = gerepilecopy(av, Q); R = Q+2; } } } else if (isintm1(c)) { for (i=1; i<=n; i++) { for (k=n-i; k1) pari_warn(warnmem,"RgX_translate(-1), i = %ld/%ld", i,n); Q = gerepilecopy(av, Q); R = Q+2; } } } else { for (i=1; i<=n; i++) { for (k=n-i; k1) pari_warn(warnmem,"RgX_translate, i = %ld/%ld", i,n); Q = gerepilecopy(av, Q); R = Q+2; } } } return gerepilecopy(av, Q); } GEN RgX_translate(GEN P, GEN c) { pari_sp av = avma; long n = degpol(P); if (n < 40) return RgX_translate_basecase(P, c); else { long d = n >> 1; GEN Q = RgX_translate(RgX_shift_shallow(P, -d), c); GEN R = RgX_translate(RgXn_red_shallow(P, d), c); GEN S = gpowgs(deg1pol_shallow(gen_1, c, varn(P)), d); return gerepileupto(av, RgX_add(RgX_mul(Q, S), R)); } } /* P(ax + b) */ GEN RgX_affine(GEN P, GEN a, GEN b) { if (signe(b)) P = RgX_translate(P, b); return RgX_unscale(P, a); } /* 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; GEN Q, R; long i, k, n; if (!signe(P) || gequal0(c)) return RgX_copy(P); Q = leafcopy(P); R = Q+2; n = degpol(P); 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 = Q+2; } } return gerepilecopy(av, Q); } /********************************************************************/ /** **/ /** CONVERSIONS **/ /** (not memory clean) **/ /** **/ /********************************************************************/ /* to INT / FRAC / (POLMOD mod T), not memory clean because T not copied, * but everything else is */ static GEN QXQ_to_mod(GEN x, GEN T) { long d; switch(typ(x)) { case t_INT: return icopy(x); case t_FRAC: return gcopy(x); case t_POL: d = degpol(x); if (d < 0) return gen_0; if (d == 0) return gcopy(gel(x,2)); return mkpolmod(RgX_copy(x), T); default: pari_err_TYPE("QXQ_to_mod",x); return NULL;/* LCOV_EXCL_LINE */ } } /* pure shallow version */ GEN QXQ_to_mod_shallow(GEN x, GEN T) { long d; switch(typ(x)) { case t_INT: case t_FRAC: return x; case t_POL: d = degpol(x); if (d < 0) return gen_0; if (d == 0) return gel(x,2); return mkpolmod(x, T); default: pari_err_TYPE("QXQ_to_mod",x); return NULL;/* LCOV_EXCL_LINE */ } } /* T a ZX, z lifted from (Q[Y]/(T(Y)))[X], apply QXQ_to_mod to all coeffs. * Not memory clean because T not copied, but everything else is */ static GEN QXQX_to_mod(GEN z, GEN T) { long i,l = lg(z); GEN x = cgetg(l,t_POL); for (i=2; i1; i--) if (! gequal0(gel(x,i))) break; /* _not_ isexactzero */ stackdummy((pari_sp)(x + lg(x)), (pari_sp)(x + i+1)); setlg(x, i+1); setsigne(x, i != 1); return x; } GEN RgV_to_RgX(GEN x, long v) { long i, k = lg(x); GEN p; while (--k && gequal0(gel(x,k))); if (!k) return pol_0(v); i = k+2; p = cgetg(i,t_POL); p[1] = evalsigne(1) | evalvarn(v); x--; for (k=2; k N+1) l = N+1; /* truncate higher degree terms */ z = cgetg(N+1,t_COL); for (i=1; i P(Y,X), n is an upper bound for deg_Y(P) */ GEN RgXY_swapspec(GEN x, long n, long w, long nx) { long j, ly = n+3; GEN y = cgetg(ly, t_POL); y[1] = evalsigne(1); for (j=2; j P(Y,X), n is an upper bound for deg_Y(P) */ GEN RgXY_swap(GEN x, long n, long w) { GEN z = RgXY_swapspec(x+2, n, w, lgpol(x)); setvarn(z, varn(x)); return z; } long RgXY_degreex(GEN b) { long deg = 0, i; if (!signe(b)) return -1; for (i = 2; i < lg(b); ++i) { GEN bi = gel(b, i); if (typ(bi) == t_POL) deg = maxss(deg, degpol(bi)); } return deg; } GEN RgXY_derivx(GEN x) { pari_APPLY_pol(RgX_deriv(gel(x,i))); } /* return (x % X^n). Shallow */ GEN RgXn_red_shallow(GEN a, long n) { long i, L = n+2, l = lg(a); GEN b; if (L >= l) return a; /* deg(x) < n */ b = cgetg(L, t_POL); b[1] = a[1]; for (i=2; i= 0) return RgX_shift(x, d); d = -d; v = RgX_val(x); if (v >= d) return RgX_shift(x, -d); av = avma; z = gred_rfrac_simple(RgX_shift_shallow(x, -v), pol_xn(d - v, varn(x))); return gerepileupto(av, z); } long RgXV_maxdegree(GEN x) { long d = -1, i, l = lg(x); for (i = 1; i < l; i++) d = maxss(d, degpol(gel(x,i))); return d; } 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) return LONG_MAX;/* possible with nonrational 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; /* possible with nonrational zeros */ if (i == lx) { *Z = scalarpol_shallow(Rg_get_0(x), varn(x)); return LONG_MAX; } 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 x, GEN T) { pari_APPLY_type(t_COL, grem(gel(x,i), T)) } GEN RgXQV_red(GEN x, GEN T) { pari_APPLY_type(t_VEC, grem(gel(x,i), T)) } GEN RgXQM_red(GEN x, GEN T) { pari_APPLY_same(RgXQC_red(gel(x,i), T)) } GEN RgXQM_mul(GEN P, GEN Q, GEN T) { return RgXQM_red(RgM_mul(P, Q), T); } GEN RgXQX_red(GEN P, GEN T) { long i, l = lg(P); GEN Q = cgetg(l, t_POL); Q[1] = P[1]; for (i=2; i= ny > 0, return x * y * t^v */ static GEN RgX_mulspec_basecase(GEN x, GEN y, long nx, long ny, long v) { long i, lz, nz; GEN z; x = RgXspec_kill0(x,nx); y = RgXspec_kill0(y,ny); lz = nx + ny + 1; nz = lz-2; lz += v; z = cgetg(lz, t_POL) + 2; /* x:y:z [i] = term of degree i */ for (i=0; i 0 */ GEN RgX_addmulXn_shallow(GEN x0, GEN y0, long d) { GEN x, y, xd, yd, zd; long a, lz, nx, ny; if (!signe(x0)) return y0; ny = lgpol(y0); nx = lgpol(x0); zd = (GEN)avma; x = x0 + 2; y = y0 + 2; a = ny-d; if (a <= 0) { lz = nx+d+2; (void)new_chunk(lz); xd = x+nx; yd = y+ny; while (xd > x) gel(--zd,0) = gel(--xd,0); x = zd + a; while (zd > x) gel(--zd,0) = gen_0; } else { xd = new_chunk(d); yd = y+d; x = RgX_addspec_shallow(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 = x0[1]; *--zd = evaltyp(t_POL) | evallg(lz); return zd; } GEN RgX_addmulXn(GEN x0, GEN y0, long d) { GEN x, y, xd, yd, zd; long a, lz, nx, ny; if (!signe(x0)) return RgX_copy(y0); nx = lgpol(x0); ny = lgpol(y0); zd = (GEN)avma; x = x0 + 2; y = y0 + 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 = RgX_addspec(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 = x0[1]; *--zd = evaltyp(t_POL) | evallg(lz); return zd; } /* return x * y mod t^n */ static GEN RgXn_mul_basecase(GEN x, GEN y, long n) { long i, lz = n+2, lx = lgpol(x), ly = lgpol(y); GEN z; if (lx < 0) return pol_0(varn(x)); if (ly < 0) return pol_0(varn(x)); z = cgetg(lz, t_POL) + 2; x+=2; if (lx > n) lx = n; y+=2; if (ly > n) ly = n; z[-1] = x[-1]; if (ly > lx) { swap(x,y); lswap(lx,ly); } x = RgXspec_kill0(x, lx); y = RgXspec_kill0(y, ly); /* x:y:z [i] = term of degree i */ for (i=0;i>1; n1 = n-n0; RgX_even_odd(f, &fe, &fo); RgX_even_odd(g, &ge, &go); l = RgXn_mul2(fe,ge,n1); h = RgXn_mul2(fo,go,n0); m = RgX_sub(RgXn_mul2(RgX_add(fe,fo),RgX_add(ge,go),n0), RgX_add(l,h)); /* n1-1 <= n0 <= n1, deg l,m <= n1-1, deg h <= n0-1 * result is t^2 h(t^2) + t m(t^2) + l(t^2) */ l = RgX_inflate(l,2); /* deg l <= 2n1 - 2 <= n-1 */ /* deg(t m(t^2)) <= 2n1 - 1 <= n, truncate to < n */ if (2*degpol(m)+1 == n) m = normalizepol_lg(m, lg(m)-1); m = RgX_inflate(m,2); /* deg(t^2 h(t^2)) <= 2n0 <= n, truncate to < n */ if (2*degpol(h)+2 == n) h = normalizepol_lg(h, lg(h)-1); h = RgX_inflate(h,2); h = RgX_addmulXn(RgX_addmulXn_shallow(h,m,1), l,1); return gerepileupto(av, h); } /* (f*g) \/ x^n */ static GEN RgX_mulhigh_i2(GEN f, GEN g, long n) { long d = degpol(f)+degpol(g) + 1 - n; GEN h; if (d <= 2) return RgX_shift_shallow(RgX_mul(f,g), -n); h = RgX_recip_i(RgXn_mul2(RgX_recip_i(f), RgX_recip_i(g), d)); return RgX_shift_shallow(h, d-1-degpol(h)); /* possibly (fg)(0) = 0 */ } /* (f*g) \/ x^n */ static GEN RgX_sqrhigh_i2(GEN f, long n) { long d = 2*degpol(f)+ 1 - n; GEN h; if (d <= 2) return RgX_shift_shallow(RgX_sqr(f), -n); h = RgX_recip_i(RgXn_sqr(RgX_recip_i(f), d)); return RgX_shift_shallow(h, d-1-degpol(h)); /* possibly (fg)(0) = 0 */ } /* 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 = RgX_addspec_shallow(a0,a, na,n0a); c1 = RgX_addspec_shallow(b0,b, nb,n0b); c1 = RgX_mulspec(c1+2,c2+2, lgpol(c1),lgpol(c2)); c2 = RgX_sub(c1, RgX_add(c0,c)); c0 = RgX_addmulXn_shallow(c0, c2, n0); } else { c = RgX_mulspec(a,b,n0a,nb); c0 = RgX_mulspec(a0,b,na,nb); } c0 = RgX_addmulXn(c0,c,n0); return RgX_shift_inplace(gerepileupto(av,c0), v); } INLINE GEN RgX_sqrspec_basecase_limb(GEN x, long a, long i) { pari_sp av = avma; GEN s = NULL; long j, l = (i+1)>>1; for (j=a; j>1); if (t) { t = gsqr(t); s = s? gadd(s, t): t; } } return s? gerepileupto(av,s): gen_0; } static GEN RgX_sqrspec_basecase(GEN x, long nx, long v) { long i, lz, nz; GEN z; if (!nx) return pol_0(0); x = RgXspec_kill0(x,nx); lz = (nx << 1) + 1, nz = lz-2; lz += v; z = cgetg(lz,t_POL) + 2; for (i=0; i n) lx = n; x = RgXspec_kill0(x,lx); z+=2;/* x:z [i] = term of degree i */ for (i=0;i>1; n1 = n-n0; RgX_even_odd(f, &fe, &fo); l = RgXn_sqr(fe,n1); h = RgXn_sqr(fo,n0); m = RgX_sub(RgXn_sqr(RgX_add(fe,fo),n0), RgX_add(l,h)); /* n1-1 <= n0 <= n1, deg l,m <= n1-1, deg h <= n0-1 * result is t^2 h(t^2) + t m(t^2) + l(t^2) */ l = RgX_inflate(l,2); /* deg l <= 2n1 - 2 <= n-1 */ /* deg(t m(t^2)) <= 2n1 - 1 <= n, truncate to < n */ if (2*degpol(m)+1 == n) m = normalizepol_lg(m, lg(m)-1); m = RgX_inflate(m,2); /* deg(t^2 h(t^2)) <= 2n0 <= n, truncate to < n */ if (2*degpol(h)+2 == n) h = normalizepol_lg(h, lg(h)-1); h = RgX_inflate(h,2); h = RgX_addmulXn(RgX_addmulXn_shallow(h,m,1), l,1); return gerepileupto(av, h); } GEN RgX_sqrspec(GEN a, long na) { GEN a0, c, c0, c1; long n0, n0a, i, v = 0; pari_sp av; while (na && isrationalzero(gel(a,0))) { a++; na--; v += 2; } if (na>1); n0 = na-i; na = i; av = avma; a0 = a+n0; n0a = n0; while (n0a && isrationalzero(gel(a,n0a-1))) n0a--; c = RgX_sqrspec(a,n0a); c0 = RgX_sqrspec(a0,na); c1 = gmul2n(RgX_mulspec(a0,a, na,n0a), 1); c0 = RgX_addmulXn_shallow(c0,c1, n0); c0 = RgX_addmulXn(c0,c,n0); return RgX_shift_inplace(gerepileupto(av,c0), v); } /* (X^a + A)(X^b + B) - X^(a+b), where deg A < a, deg B < b */ GEN RgX_mul_normalized(GEN A, long a, GEN B, long b) { GEN z = RgX_mul(A, B); if (a < b) z = RgX_addmulXn_shallow(RgX_addmulXn_shallow(A, B, b-a), z, a); else if (a > b) z = RgX_addmulXn_shallow(RgX_addmulXn_shallow(B, A, a-b), z, b); else z = RgX_addmulXn_shallow(RgX_add(A, B), z, a); return z; } GEN RgX_mul_i(GEN x, GEN y) { GEN z = RgX_mulspec(x+2, y+2, lgpol(x), lgpol(y)); setvarn(z, varn(x)); return z; } GEN RgX_sqr_i(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 = lg(x); GEN z; if (lx == 2) return gcopy(x); switch(typ(y)) { case t_INT: if (is_pm1(y)) return signe(y) < 0 ? RgX_neg(x): RgX_copy(x); break; case t_INTMOD: case t_POLMOD: return RgX_Rg_mul(x, ginv(y)); } z = cgetg(lx, t_POL); z[1] = x[1]; for (i=2; i 1; i--) { d = gel(x,i); if (!gequal0(d)) break; } if (i == 1) return pol_0(varn(x)); if (i == n && isint1(d)) return x; n = i; z = cgetg(n+1, t_POL); 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 pr = ONLY_REM return remainder, otherwise return quotient * if pr = ONLY_DIVIDES return quotient if division is exact, else NULL * if pr != NULL set *pr to remainder, as the last object on stack */ /* assume, typ(x) = typ(y) = t_POL, same variable */ static GEN RgX_divrem_i(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,p; GEN (*f)(GEN,GEN); if (!signe(y)) pari_err_INV("RgX_divrem",y); dy = degpol(y); y_lead = gel(y,dy+2); if (gequal0(y_lead)) /* normalize denominator if leading term is 0 */ { pari_warn(warner,"normalizing a polynomial with 0 leading term"); for (dy--; dy>=0; dy--) { y_lead = gel(y,dy+2); if (!gequal0(y_lead)) break; } } if (!dy) /* y is constant */ { if (pr == ONLY_REM) return pol_0(varn(x)); z = RgX_Rg_div(x, y_lead); if (pr == ONLY_DIVIDES) return z; if (pr) *pr = pol_0(varn(x)); return z; } dx = degpol(x); if (dx < dy) { if (pr == ONLY_REM) return RgX_copy(x); if (pr == ONLY_DIVIDES) return signe(x)? NULL: pol_0(varn(x)); z = pol_0(varn(x)); if (pr) *pr = RgX_copy(x); return z; } /* x,y in R[X], y non constant */ av = avma; p = NULL; if (RgX_is_FpX(x, &p) && RgX_is_FpX(y, &p) && p) { z = FpX_divrem(RgX_to_FpX(x, p), RgX_to_FpX(y, p), p, pr); if (!z) return gc_NULL(av); z = FpX_to_mod(z, p); if (!pr || pr == ONLY_REM || pr == ONLY_DIVIDES) return gerepileupto(av, z); *pr = FpX_to_mod(*pr, p); return gc_all(av, 2, &z, pr); } switch(typ(y_lead)) { case t_REAL: y_lead = ginv(y_lead); f = gmul; mod = NULL; break; case t_INTMOD: case t_POLMOD: y_lead = ginv(y_lead); f = gmul; mod = gmodulo(gen_1, gel(y_lead,1)); break; default: if (gequal1(y_lead)) y_lead = NULL; f = gdiv; mod = NULL; } if (y_lead == NULL) p2 = gel(x,dx+2); else { for(;;) { p2 = f(gel(x,dx+2),y_lead); p2 = simplify_shallow(p2); if (!isexactzero(p2) || (--dx < 0)) break; } if (dx < dy) /* leading coeff of x was in fact zero */ { if (pr == ONLY_DIVIDES) { set_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; set_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); set_avma(av); z = pol_0(varn(x)); x = scalarpol(p2, varn(x)); gunclone(p2); } else { GEN t; set_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 { set_avma(av); z = pol_0(varn(x)); } return z; } } /* dx >= dy */ avy = avma; dz = dx-dy; z = cgetg(dz+3,t_POL); z[1] = x[1]; x += 2; z += 2; y += 2; gel(z,dz) = gcopy(p2); for (i=dx-1; i>=dy; i--) { av1=avma; p1=gel(x,i); for (j=i-dy+1; j<=i && j<=dz; j++) p1 = gsub(p1, gmul(gel(z,j),gel(y,i-j))); if (y_lead) p1 = simplify(f(p1,y_lead)); if (isrationalzero(p1)) { set_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 nonzero */ if (!isexactzero(p1)) break; if (!i) break; set_avma(av1); } if (pr == ONLY_DIVIDES) { if (sx) return gc_NULL(av); set_avma((pari_sp)rem); return gerepileupto(av,z-2); } lr=i+3; rem -= lr; if (avma==av1) { set_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; } } GEN RgX_divrem(GEN x, GEN y, GEN *pr) { if (pr == ONLY_REM) return RgX_rem(x, y); return RgX_divrem_i(x, y, pr); } /* x and y in (R[Y]/T)[X] (lifted), T in R[Y]. y preferably monic */ GEN RgXQX_divrem(GEN x, GEN y, GEN T, GEN *pr) { long vx, dx, dy, dz, i, j, sx, lr; pari_sp av0, av, tetpil; GEN z,p1,rem,lead; if (!signe(y)) pari_err_INV("RgXQX_divrem",y); vx = varn(x); dx = degpol(x); dy = degpol(y); if (dx < dy) { if (pr) { av0 = avma; x = RgXQX_red(x, T); if (pr == ONLY_DIVIDES) { set_avma(av0); return signe(x)? NULL: gen_0; } if (pr == ONLY_REM) return x; *pr = x; } return pol_0(vx); } lead = leading_coeff(y); if (!dy) /* y is constant */ { if (pr && pr != ONLY_DIVIDES) { if (pr == ONLY_REM) return pol_0(vx); *pr = pol_0(vx); } if (gequal1(lead)) return RgX_copy(x); av0 = avma; x = gmul(x, ginvmod(lead,T)); tetpil = avma; return gerepile(av0,tetpil,RgXQX_red(x,T)); } av0 = avma; dz = dx-dy; lead = gequal1(lead)? NULL: gclone(ginvmod(lead,T)); set_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) { guncloneNULL(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; set_avma(av); } if (pr == ONLY_DIVIDES) { guncloneNULL(lead); if (sx) return gc_NULL(av0); return gc_const((pari_sp)rem, 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; guncloneNULL(lead); if (!sx) (void)normalizepol_lg(rem, lr); if (pr == ONLY_REM) return gerepileupto(av0,rem); *pr = rem; return z-2; } /*******************************************************************/ /* */ /* PSEUDO-DIVISION */ /* */ /*******************************************************************/ INLINE GEN rem(GEN c, GEN T) { if (T && typ(c) == t_POL && varn(c) == varn(T)) c = RgX_rem(c, T); return c; } /* x, y, are ZYX, lc(y) is an integer, T is a ZY */ int ZXQX_dvd(GEN x, GEN y, GEN T) { long dx, dy, i, T_ismonic; pari_sp av = avma, av2; GEN y_lead; if (!signe(y)) pari_err_INV("ZXQX_dvd",y); dy = degpol(y); y_lead = gel(y,dy+2); if (typ(y_lead) == t_POL) y_lead = gel(y_lead, 2); /* t_INT */ /* if monic, no point in using pseudo-division */ if (gequal1(y_lead)) return signe(RgXQX_rem(x, y, T)) == 0; T_ismonic = gequal1(leading_coeff(T)); dx = degpol(x); if (dx < dy) return !signe(x); (void)new_chunk(2); x = RgX_recip_i(x)+2; y = RgX_recip_i(y)+2; /* pay attention to sparse divisors */ for (i = 1; i <= dy; i++) if (!signe(gel(y,i))) gel(y,i) = NULL; av2 = avma; for (;;) { GEN m, x0 = gel(x,0), y0 = y_lead, cx = content(x0); x0 = gneg(x0); m = gcdii(cx, y0); if (!equali1(m)) { x0 = gdiv(x0, m); y0 = diviiexact(y0, m); if (equali1(y0)) y0 = NULL; } for (i=1; i<=dy; i++) { GEN c = gel(x,i); if (y0) c = gmul(y0, c); if (gel(y,i)) c = gadd(c, gmul(x0,gel(y,i))); if (typ(c) == t_POL) c = T_ismonic ? ZX_rem(c, T): RgX_rem(c, T); gel(x,i) = c; } for ( ; i<=dx; i++) { GEN c = gel(x,i); if (y0) c = gmul(y0, c); if (typ(c) == t_POL) c = T_ismonic ? ZX_rem(c, T): RgX_rem(c, T); gel(x,i) = c; } do { x++; dx--; } while (dx >= 0 && !signe(gel(x,0))); if (dx < dy) break; if (gc_needed(av2,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"ZXQX_dvd dx = %ld >= %ld",dx,dy); gerepilecoeffs(av2,x,dx+1); } } return gc_bool(av, dx < 0); } /* T either NULL or a t_POL. */ GEN RgXQX_pseudorem(GEN x, GEN y, GEN T) { long vx = varn(x), dx, dy, dz, i, lx, p; pari_sp av = avma, av2; GEN y_lead; if (!signe(y)) pari_err_INV("RgXQX_pseudorem",y); dy = degpol(y); y_lead = gel(y,dy+2); /* if monic, no point in using pseudo-division */ if (gequal1(y_lead)) return T? RgXQX_rem(x, y, T): RgX_rem(x, y); dx = degpol(x); if (dx < dy) return RgX_copy(x); (void)new_chunk(2); x = RgX_recip_i(x)+2; y = RgX_recip_i(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; 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 (gc_needed(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_i(x); if (p) { /* multiply by y[0]^p [beware dummy vars from FpX_FpXY_resultant] */ GEN t = y_lead; if (T && typ(t) == t_POL && varn(t) == varn(T)) t = RgXQ_powu(t, p, T); else t = gpowgs(t, p); for (i=2; i= dy && gequal0(gel(x,0))) { x++; dx--; iz++; } if (dx < dy) break; if (gc_needed(av2,1)) { GEN X = x-2; if(DEBUGMEM>1) pari_warn(warnmem,"RgX_pseudodivrem dx=%ld >= %ld",dx,dy); X[0] = evaltyp(t_POL)|_evallg(dx+3); X[1] = z[1]; /* hack */ gerepileall(av2,2, &X, &z); x = X+2; } } while (dx >= 0 && gequal0(gel(x,0))) { x++; dx--; } if (dx < 0) x = pol_0(vx); else { lx = dx+3; x -= 2; x[0] = evaltyp(t_POL) | _evallg(lx); x[1] = evalsigne(1) | evalvarn(vx); x = RgX_recip_i(x); } z = RgX_recip_i(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); } *ptr = r; return gc_all(av, 2, &z, ptr); } 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 x, GEN y) { pari_APPLY_pol(gmul(y, gel(x,i))); } GEN RgX_mul2n(GEN x, long n) { pari_APPLY_pol(gmul2n(gel(x,i), n)); } GEN RgX_muls(GEN x, long y) { pari_APPLY_pol(gmulsg(y, gel(x,i))); } GEN RgXQX_RgXQ_mul(GEN x, GEN y, GEN T) { return RgXQX_red(RgX_Rg_mul(x,y), T); } GEN RgXQV_RgXQ_mul(GEN v, GEN x, GEN T) { return RgXQV_red(RgV_Rg_mul(v,x), T); } GEN RgXQX_sqr(GEN x, GEN T) { return RgXQX_red(RgX_sqr(x), T); } GEN RgXQX_powers(GEN P, long n, GEN T) { GEN v = cgetg(n+2, t_VEC); long i; gel(v, 1) = pol_1(varn(T)); if (n==0) return v; gel(v, 2) = gcopy(P); for (i = 2; i <= n; i++) gel(v,i+1) = RgXQX_mul(P, gel(v,i), T); return v; } static GEN _add(void *data, GEN x, GEN y) { (void)data; return RgX_add(x, y); } static GEN _sub(void *data, GEN x, GEN y) { (void)data; return RgX_sub(x, y); } static GEN _sqr(void *data, GEN x) { return RgXQ_sqr(x, (GEN)data); } static GEN _pow(void *data, GEN x, GEN n) { return RgXQ_pow(x, n, (GEN)data); } static GEN _mul(void *data, GEN x, GEN y) { return RgXQ_mul(x,y, (GEN)data); } static GEN _cmul(void *data, GEN P, long a, GEN x) { (void)data; return RgX_Rg_mul(x,gel(P,a+2)); } static GEN _one(void *data) { return pol_1(varn((GEN)data)); } static GEN _zero(void *data) { return pol_0(varn((GEN)data)); } static GEN _red(void *data, GEN x) { (void)data; return gcopy(x); } static struct bb_algebra RgXQ_algebra = { _red, _add, _sub, _mul, _sqr, _one, _zero }; GEN RgX_RgXQV_eval(GEN Q, GEN x, GEN T) { return gen_bkeval_powers(Q,degpol(Q),x,(void*)T,&RgXQ_algebra,_cmul); } GEN RgX_RgXQ_eval(GEN Q, GEN x, GEN T) { int use_sqr = 2*degpol(x) >= degpol(T); return gen_bkeval(Q,degpol(Q),x,use_sqr,(void*)T,&RgXQ_algebra,_cmul); } /* mod X^n */ struct modXn { long v; /* varn(X) */ long n; } ; static GEN _sqrXn(void *data, GEN x) { struct modXn *S = (struct modXn*)data; return RgXn_sqr(x, S->n); } static GEN _mulXn(void *data, GEN x, GEN y) { struct modXn *S = (struct modXn*)data; return RgXn_mul(x,y, S->n); } static GEN _oneXn(void *data) { struct modXn *S = (struct modXn*)data; return pol_1(S->v); } static GEN _zeroXn(void *data) { struct modXn *S = (struct modXn*)data; return pol_0(S->v); } static struct bb_algebra RgXn_algebra = { _red, _add, _sub, _mulXn, _sqrXn, _oneXn, _zeroXn }; GEN RgXn_powers(GEN x, long m, long n) { long d = degpol(x); int use_sqr = (d<<1) >= n; struct modXn S; S.v = varn(x); S.n = n; return gen_powers(x,m,use_sqr,(void*)&S,_sqrXn,_mulXn,_oneXn); } GEN RgXn_powu_i(GEN x, ulong m, long n) { struct modXn S; long v; if (n == 0) return x; v = RgX_valrem(x, &x); if (v) { n -= m * v; if (n <= 0) return pol_0(varn(x)); } S.v = varn(x); S.n = n; x = gen_powu_i(x, m, (void*)&S,_sqrXn,_mulXn); if (v) x = RgX_shift_shallow(x, m * v); return x; } GEN RgXn_powu(GEN x, ulong m, long n) { pari_sp av; if (n == 0) return gcopy(x); av = avma; return gerepilecopy(av, RgXn_powu_i(x, m, n)); } GEN RgX_RgXnV_eval(GEN Q, GEN x, long n) { struct modXn S; S.v = varn(gel(x,2)); S.n = n; return gen_bkeval_powers(Q,degpol(Q),x,(void*)&S,&RgXn_algebra,_cmul); } GEN RgX_RgXn_eval(GEN Q, GEN x, long n) { int use_sqr = 2*degpol(x) >= n; struct modXn S; S.v = varn(x); S.n = n; return gen_bkeval(Q,degpol(Q),x,use_sqr,(void*)&S,&RgXn_algebra,_cmul); } /* Q(x) mod t^n, x in R[t], n >= 1 */ GEN RgXn_eval(GEN Q, GEN x, long n) { long d = degpol(x); int use_sqr; struct modXn S; if (d == 1 && isrationalzero(gel(x,2))) { GEN y = RgX_unscale(Q, gel(x,3)); setvarn(y, varn(x)); return y; } S.v = varn(x); S.n = n; use_sqr = (d<<1) >= n; return gen_bkeval(Q,degpol(Q),x,use_sqr,(void*)&S,&RgXn_algebra,_cmul); } /* (f*g mod t^n) \ t^n2, assuming 2*n2 >= n */ static GEN RgXn_mulhigh(GEN f, GEN g, long n2, long n) { GEN F = RgX_blocks(f, n2, 2), fl = gel(F,1), fh = gel(F,2); return RgX_add(RgX_mulhigh_i(fl, g, n2), RgXn_mul(fh, g, n - n2)); } /* (f^2 mod t^n) \ t^n2, assuming 2*n2 >= n */ static GEN RgXn_sqrhigh(GEN f, long n2, long n) { GEN F = RgX_blocks(f, n2, 2), fl = gel(F,1), fh = gel(F,2); return RgX_add(RgX_mulhigh_i(fl, f, n2), RgXn_mul(fh, f, n - n2)); } static GEN RgXn_div_gen(GEN g, GEN f, long e) { pari_sp av; ulong mask; GEN W, a; long v = varn(f), n = 1; if (!signe(f)) pari_err_INV("RgXn_inv",f); a = ginv(gel(f,2)); if (e == 1 && !g) return scalarpol(a, v); else if (e == 2 && !g) { GEN b; if (degpol(f) <= 0 || gequal0(b = gel(f,3))) return scalarpol(a, v); b = gneg(b); if (!gequal1(a)) b = gmul(b, gsqr(a)); return deg1pol(b, a, v); } av = avma; W = scalarpol_shallow(a,v); mask = quadratic_prec_mask(e); while (mask > 1) { GEN u, fr; long n2 = n; n<<=1; if (mask & 1) n--; mask >>= 1; fr = RgXn_red_shallow(f, n); if (mask>1 || !g) { u = RgXn_mul(W, RgXn_mulhigh(fr, W, n2, n), n-n2); W = RgX_sub(W, RgX_shift_shallow(u, n2)); } else { GEN y = RgXn_mul(g, W, n), yt = RgXn_red_shallow(y, n-n2); u = RgXn_mul(yt, RgXn_mulhigh(fr, W, n2, n), n-n2); W = RgX_sub(y, RgX_shift_shallow(u, n2)); } if (gc_needed(av,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"RgXn_inv, e = %ld", n); W = gerepileupto(av, W); } } return W; } static GEN RgXn_div_FpX(GEN x, GEN y, long e, GEN p) { GEN r; if (lgefint(p) == 3) { ulong pp = uel(p, 2); if (pp == 2) r = F2x_to_ZX(F2xn_div(RgX_to_F2x(x), RgX_to_F2x(y), e)); else r = Flx_to_ZX_inplace(Flxn_div(RgX_to_Flx(x, pp), RgX_to_Flx(y, pp), e, pp)); } else r = FpXn_div(RgX_to_FpX(x, p), RgX_to_FpX(y, p), e, p); return FpX_to_mod(r, p); } static GEN RgXn_div_FpXQX(GEN x, GEN y, long n, GEN pol, GEN p) { GEN r, T = RgX_to_FpX(pol, p); if (signe(T) == 0) pari_err_OP("/", x, y); r = FpXQXn_div(RgX_to_FpXQX(x, T, p), RgX_to_FpXQX(y, T, p), n, T, p); return FpXQX_to_mod(r, T, p); } static GEN RgXn_inv_FpX(GEN x, long e, GEN p) { GEN r; if (lgefint(p) == 3) { ulong pp = uel(p, 2); if (pp == 2) r = F2x_to_ZX(F2xn_inv(RgX_to_F2x(x), e)); else r = Flx_to_ZX_inplace(Flxn_inv(RgX_to_Flx(x, pp), e, pp)); } else r = FpXn_inv(RgX_to_FpX(x, p), e, p); return FpX_to_mod(r, p); } static GEN RgXn_inv_FpXQX(GEN x, long n, GEN pol, GEN p) { GEN r, T = RgX_to_FpX(pol, p); if (signe(T) == 0) pari_err_OP("/", gen_1, x); r = FpXQXn_inv(RgX_to_FpXQX(x, T, p), n, T, p); return FpXQX_to_mod(r, T, p); } #define code(t1,t2) ((t1 << 6) | t2) static GEN RgXn_inv_fast(GEN x, long e) { GEN p, pol; long pa; long t = RgX_type(x,&p,&pol,&pa); switch(t) { case t_INTMOD: return RgXn_inv_FpX(x, e, p); case code(t_POLMOD, t_INTMOD): return RgXn_inv_FpXQX(x, e, pol, p); default: return NULL; } } static GEN RgXn_div_fast(GEN x, GEN y, long e) { GEN p, pol; long pa; long t = RgX_type2(x,y,&p,&pol,&pa); switch(t) { case t_INTMOD: return RgXn_div_FpX(x, y, e, p); case code(t_POLMOD, t_INTMOD): return RgXn_div_FpXQX(x, y, e, pol, p); default: return NULL; } } #undef code GEN RgXn_div_i(GEN g, GEN f, long e) { GEN h = RgXn_div_fast(g, f, e); if (h) return h; return RgXn_div_gen(g, f, e); } GEN RgXn_div(GEN g, GEN f, long e) { pari_sp av = avma; return gerepileupto(av, RgXn_div_i(g, f, e)); } GEN RgXn_inv_i(GEN f, long e) { GEN h = RgXn_inv_fast(f, e); if (h) return h; return RgXn_div_gen(NULL, f, e); } GEN RgXn_inv(GEN f, long e) { pari_sp av = avma; return gerepileupto(av, RgXn_inv_i(f, e)); } /* Compute intformal(x^n*S)/x^(n+1) */ static GEN RgX_integXn(GEN x, long n) { long i, lx = lg(x); GEN y; if (lx == 2) return RgX_copy(x); y = cgetg(lx, t_POL); y[1] = x[1]; for (i=2; i1;) { GEN u, w; long n2 = n; n<<=1; if (mask & 1) n--; mask >>= 1; u = RgXn_mul(g, RgX_mulhigh_i(f, RgXn_red_shallow(h, n2-1), n2-1), n-n2); u = RgX_add(u, RgX_shift_shallow(RgXn_red_shallow(h, n-1), 1-n2)); w = RgXn_mul(f, RgX_integXn(u, n2-1), n-n2); f = RgX_add(f, RgX_shift_shallow(w, n2)); if (mask<=1) break; u = RgXn_mul(g, RgXn_mulhigh(f, g, n2, n), n-n2); g = RgX_sub(g, RgX_shift_shallow(u, n2)); if (gc_needed(av2,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"RgXn_expint, e = %ld", n); gerepileall(av2, 2, &f, &g); } } return gerepileupto(av, f); } GEN RgXn_exp(GEN h, long e) { long d = degpol(h); if (d < 0) return pol_1(varn(h)); if (!d || !gequal0(gel(h,2))) pari_err_DOMAIN("RgXn_exp","valuation", "<", gen_1, h); return RgXn_expint(RgX_deriv(h), e); } GEN RgXn_reverse(GEN f, long e) { pari_sp av = avma, av2; ulong mask; GEN fi, a, df, W, an; long v = varn(f), n=1; if (degpol(f)<1 || !gequal0(gel(f,2))) pari_err_INV("serreverse",f); fi = ginv(gel(f,3)); a = deg1pol_shallow(fi,gen_0,v); if (e <= 2) return gerepilecopy(av, a); W = scalarpol(fi,v); df = RgX_deriv(f); mask = quadratic_prec_mask(e); av2 = avma; for (;mask>1;) { GEN u, fa, fr; long n2 = n, rt; n<<=1; if (mask & 1) n--; mask >>= 1; fr = RgXn_red_shallow(f, n); rt = brent_kung_optpow(degpol(fr), 4, 3); an = RgXn_powers(a, rt, n); if (n>1) { long n4 = (n2+1)>>1; GEN dfr = RgXn_red_shallow(df, n2); dfr = RgX_RgXnV_eval(dfr, RgXnV_red_shallow(an, n2), n2); u = RgX_shift(RgX_Rg_sub(RgXn_mul(W, dfr, n2), gen_1), -n4); W = RgX_sub(W, RgX_shift(RgXn_mul(u, W, n2-n4), n4)); } fa = RgX_sub(RgX_RgXnV_eval(fr, an, n), pol_x(v)); fa = RgX_shift(fa, -n2); a = RgX_sub(a, RgX_shift(RgXn_mul(W, fa, n-n2), n2)); if (gc_needed(av2,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"RgXn_reverse, e = %ld", n); gerepileall(av2, 2, &a, &W); } } return gerepileupto(av, a); } GEN RgXn_sqrt(GEN h, long e) { pari_sp av = avma, av2; long v = varn(h), n = 1; GEN f = scalarpol(gen_1, v), df = f; ulong mask = quadratic_prec_mask(e); if (degpol(h)<0 || !gequal1(gel(h,2))) pari_err_SQRTN("RgXn_sqrt",h); av2 = avma; while(1) { long n2 = n, m; GEN g; n<<=1; if (mask & 1) n--; mask >>= 1; m = n-n2; g = RgX_sub(RgXn_sqrhigh(f, n2, n), RgX_shift_shallow(RgXn_red_shallow(h, n),-n2)); f = RgX_sub(f, RgX_shift_shallow(RgXn_mul(gmul2n(df, -1), g, m), n2)); if (mask==1) return gerepileupto(av, f); g = RgXn_mul(df, RgXn_mulhigh(df, f, n2, n), m); df = RgX_sub(df, RgX_shift_shallow(g, n2)); if (gc_needed(av2,2)) { if(DEBUGMEM>1) pari_warn(warnmem,"RgXn_sqrt, e = %ld", n); gerepileall(av2, 2, &f, &df); } } } /* 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 = avma; if (!n) return pol_1(varn(x)); if (n == 1) return RgX_copy(x); x = gen_powu_i(x, n, (void*)T, &_sqr, &_mul); return gerepilecopy(av, x); } /* 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); if (!s) return pol_1(varn(x)); if (is_pm1(n) == 1) return (s < 0)? RgXQ_inv(x, T): RgX_copy(x); av = avma; if (s < 0) x = RgXQ_inv(x, T); x = gen_pow_i(x, n, (void*)T, &_sqr, &_mul); return gerepilecopy(av, x); } static GEN _ZXQsqr(void *data, GEN x) { return ZXQ_sqr(x, (GEN)data); } static GEN _ZXQmul(void *data, GEN x, GEN y) { return ZXQ_mul(x,y, (GEN)data); } /* generates the list of powers of x of degree 0,1,2,...,l*/ GEN ZXQ_powers(GEN x, long l, GEN T) { int use_sqr = 2*degpol(x) >= degpol(T); return gen_powers(x, l, use_sqr, (void *)T,_ZXQsqr,_ZXQmul,_one); } /* x,T in Z[X], n in N, compute lift(x^n mod T)) */ GEN ZXQ_powu(GEN x, ulong n, GEN T) { pari_sp av = avma; if (!n) return pol_1(varn(x)); if (n == 1) return ZX_copy(x); x = gen_powu_i(x, n, (void*)T, &_ZXQsqr, &_ZXQmul); return gerepilecopy(av, x); } /* generates the list of powers of x of degree 0,1,2,...,l*/ GEN RgXQ_powers(GEN x, long l, GEN T) { int use_sqr = 2*degpol(x) >= degpol(T); return gen_powers(x, l, use_sqr, (void *)T,_sqr,_mul,_one); } GEN RgXQV_factorback(GEN L, GEN e, GEN T) { return gen_factorback(L, e, (void*)T, &_mul, &_pow, &_one); } /* a in K = Q[X]/(T), returns [a^0, ..., a^n] */ GEN QXQ_powers(GEN a, long n, GEN T) { GEN den, v; if (!isint1(leading_coeff(T))) return RgXQ_powers(a, n, T); v = ZXQ_powers(Q_remove_denom(a, &den), n, T); /* den*a integral; v[i+1] = (den*a)^i in K */ if (den) { /* restore denominators */ GEN d = den; long i; gel(v,2) = a; for (i=3; i<=n+1; i++) { d = mulii(d,den); gel(v,i) = RgX_Rg_div(gel(v,i), d); } } return v; } static GEN do_QXQ_eval(GEN v, long imin, GEN a, GEN T) { long l, i, m = 0; GEN dz, z; GEN V = cgetg_copy(v, &l); for (i = imin; i < l; i++) { GEN c = gel(v, i); if (typ(c) == t_POL) m = maxss(m, degpol(c)); } z = Q_remove_denom(QXQ_powers(a, m, T), &dz); for (i = 1; i < imin; i++) V[i] = v[i]; for (i = imin; i < l; i++) { GEN c = gel(v,i); if (typ(c) == t_POL) c = QX_ZXQV_eval(c, z, dz); gel(V,i) = c; } return V; } /* [ s(a mod T) | s <- lift(v) ], a,T are QX, v a QXV */ GEN QXV_QXQ_eval(GEN v, GEN a, GEN T) { return do_QXQ_eval(v, 1, a, T); } GEN QXY_QXQ_evalx(GEN v, GEN a, GEN T) { return normalizepol(do_QXQ_eval(v, 2, a, T)); } GEN RgXQ_matrix_pow(GEN y, long n, long m, GEN P) { return RgXV_to_RgM(RgXQ_powers(y,m-1,P),n); } GEN RgXQ_norm(GEN x, GEN T) { pari_sp av; long dx = degpol(x); GEN L, y; if (degpol(T)==0) return gpowgs(x,0); av = avma; y = resultant(T, x); L = leading_coeff(T); if (gequal1(L) || !signe(x)) return y; return gerepileupto(av, gdiv(y, gpowgs(L, dx))); } GEN RgXQ_trace(GEN x, GEN T) { pari_sp av = avma; GEN dT, z; long n; if (degpol(T)==0) return gmulgs(x,0); dT = RgX_deriv(T); n = degpol(dT); z = RgXQ_mul(x, dT, T); if (degpol(z)>1)+1; n1 = n+1 - n0; /* n1 <= n0 <= n1+1 */ p0 = cgetg(n0+2, t_POL); p0[1] = evalvarn(v)|evalsigne(1); p1 = cgetg(n1+2, t_POL); p1[1] = evalvarn(v)|evalsigne(1); for (i=0; i 1) { if (B) { gel(B,1) = vec_append(gel(B,1), p); gel(B,2) = vec_append(gel(B,2), utoipos(e-1)); } else B = to_mat(p, e-1); } } set_avma(av); if (!B) return v? to_mat(gen_2, v): trivial_fact(); A = cgetg(3, t_MAT); P = gel(B,1); E = gel(B,2); l = lg(P); AP = cgetg(l+1, t_COL); gel(A,1) = AP; AP++; AE = cgetg(l+1, t_COL); gel(A,2) = AE; AE++; /* prepend "2^v" */ gel(AP,0) = gen_2; gel(AE,0) = utoipos(v); for (i = 1; i < l; i++) { gel(AP,i) = icopy(gel(P,i)); gel(AE,i) = icopy(gel(E,i)); } return A; } #endif /***********************************************************************/ /** CHECK FACTORIZATION FOR ARITHMETIC FUNCTIONS **/ /***********************************************************************/ int RgV_is_ZVpos(GEN v) { long i, l = lg(v); for (i = 1; i < l; i++) { GEN c = gel(v,i); if (typ(c) != t_INT || signe(c) <= 0) return 0; } return 1; } /* check whether v is a ZV with nonzero entries */ int RgV_is_ZVnon0(GEN v) { long i, l = lg(v); for (i = 1; i < l; i++) { GEN c = gel(v,i); if (typ(c) != t_INT || !signe(c)) return 0; } return 1; } /* check whether v is a ZV with nonzero entries OR exactly [0] */ static int RgV_is_ZV0(GEN v) { long i, l = lg(v); for (i = 1; i < l; i++) { GEN c = gel(v,i); long s; if (typ(c) != t_INT) return 0; s = signe(c); if (!s) return (l == 2); } return 1; } int RgV_is_prV(GEN v) { long l = lg(v), i; for (i = 1; i < l; i++) if (!checkprid_i(gel(v,i))) return 0; return 1; } int is_nf_factor(GEN F) { return typ(F) == t_MAT && lg(F) == 3 && RgV_is_prV(gel(F,1)) && RgV_is_ZVpos(gel(F,2)); } int is_nf_extfactor(GEN F) { return typ(F) == t_MAT && lg(F) == 3 && RgV_is_prV(gel(F,1)) && RgV_is_ZV(gel(F,2)); } static int is_Z_factor_i(GEN f) { return typ(f) == t_MAT && lg(f) == 3 && RgV_is_ZVpos(gel(f,2)); } int is_Z_factorpos(GEN f) { return is_Z_factor_i(f) && RgV_is_ZVpos(gel(f,1)); } int is_Z_factor(GEN f) { return is_Z_factor_i(f) && RgV_is_ZV0(gel(f,1)); } /* as is_Z_factorpos, also allow factor(0) */ int is_Z_factornon0(GEN f) { return is_Z_factor_i(f) && RgV_is_ZVnon0(gel(f,1)); } GEN clean_Z_factor(GEN f) { GEN P = gel(f,1); long n = lg(P)-1; if (n && equalim1(gel(P,1))) return mkmat2(vecslice(P,2,n), vecslice(gel(f,2),2,n)); return f; } GEN fuse_Z_factor(GEN f, GEN B) { GEN P = gel(f,1), E = gel(f,2), P2,E2; long i, l = lg(P); if (l == 1) return f; for (i = 1; i < l; i++) if (abscmpii(gel(P,i), B) > 0) break; if (i == l) return f; /* tail / initial segment */ P2 = vecslice(P, i, l-1); P = vecslice(P, 1, i-1); E2 = vecslice(E, i, l-1); E = vecslice(E, 1, i-1); P = vec_append(P, factorback2(P2,E2)); E = vec_append(E, gen_1); return mkmat2(P, E); } /* n attached to a factorization of a positive integer: either N (t_INT) * a factorization matrix faN, or a t_VEC: [N, faN] */ GEN check_arith_pos(GEN n, const char *f) { switch(typ(n)) { case t_INT: if (signe(n) <= 0) pari_err_DOMAIN(f, "argument", "<=", gen_0, gen_0); return NULL; case t_VEC: if (lg(n) != 3 || typ(gel(n,1)) != t_INT || signe(gel(n,1)) <= 0) break; n = gel(n,2); /* fall through */ case t_MAT: if (!is_Z_factorpos(n)) break; return n; } pari_err_TYPE(f,n); return NULL;/*LCOV_EXCL_LINE*/ } /* n attached to a factorization of a nonzero integer */ GEN check_arith_non0(GEN n, const char *f) { switch(typ(n)) { case t_INT: if (!signe(n)) pari_err_DOMAIN(f, "argument", "=", gen_0, gen_0); return NULL; case t_VEC: if (lg(n) != 3 || typ(gel(n,1)) != t_INT || !signe(gel(n,1))) break; n = gel(n,2); /* fall through */ case t_MAT: if (!is_Z_factornon0(n)) break; return n; } pari_err_TYPE(f,n); return NULL;/*LCOV_EXCL_LINE*/ } /* n attached to a factorization of an integer */ GEN check_arith_all(GEN n, const char *f) { switch(typ(n)) { case t_INT: return NULL; case t_VEC: if (lg(n) != 3 || typ(gel(n,1)) != t_INT) break; n = gel(n,2); /* fall through */ case t_MAT: if (!is_Z_factor(n)) break; return n; } pari_err_TYPE(f,n); return NULL;/*LCOV_EXCL_LINE*/ } /***********************************************************************/ /** MISCELLANEOUS ARITHMETIC FUNCTIONS **/ /** (ultimately depend on Z_factor()) **/ /***********************************************************************/ /* set P,E from F. Check whether F is an integer and kill "factor" -1 */ static void set_fact_check(GEN F, GEN *pP, GEN *pE, int *isint) { GEN E, P; if (lg(F) != 3) pari_err_TYPE("divisors",F); P = gel(F,1); E = gel(F,2); RgV_check_ZV(E, "divisors"); *isint = RgV_is_ZV(P); if (*isint) { long i, l = lg(P); /* skip -1 */ if (l>1 && signe(gel(P,1)) < 0) { E++; P = vecslice(P,2,--l); } /* test for 0 */ for (i = 1; i < l; i++) if (!signe(gel(P,i)) && signe(gel(E,i))) pari_err_DOMAIN("divisors", "argument", "=", gen_0, F); } *pP = P; *pE = E; } static void set_fact(GEN F, GEN *pP, GEN *pE) { *pP = gel(F,1); *pE = gel(F,2); } int divisors_init(GEN n, GEN *pP, GEN *pE) { long i,l; GEN E, P, e; int isint; switch(typ(n)) { case t_INT: if (!signe(n)) pari_err_DOMAIN("divisors", "argument", "=", gen_0, gen_0); set_fact(absZ_factor(n), &P,&E); isint = 1; break; case t_VEC: if (lg(n) != 3 || typ(gel(n,2)) !=t_MAT) pari_err_TYPE("divisors",n); set_fact_check(gel(n,2), &P,&E, &isint); break; case t_MAT: set_fact_check(n, &P,&E, &isint); break; default: set_fact(factor(n), &P,&E); isint = 0; break; } l = lg(P); e = cgetg(l, t_VECSMALL); for (i=1; ib? 1: (a> 1)); } return mkvec2(c,f); } GEN corepartial(GEN n, long all) { pari_sp av = avma; if (typ(n) != t_INT) pari_err_TYPE("corepartial",n); return gerepileuptoint(av, corefa(Z_factor_limit(n,all))); } GEN core2partial(GEN n, long all) { pari_sp av = avma; if (typ(n) != t_INT) pari_err_TYPE("core2partial",n); return gerepilecopy(av, core2fa(Z_factor_limit(n,all))); } /* given an arithmetic function argument, return the underlying integer */ static GEN arith_n(GEN A) { switch(typ(A)) { case t_INT: return A; case t_VEC: return gel(A,1); default: return factorback(A); } } static GEN core2_i(GEN n) { GEN f = core(n); if (!signe(f)) return mkvec2(gen_0, gen_1); return mkvec2(f, sqrtint(diviiexact(arith_n(n), f))); } GEN core2(GEN n) { pari_sp av = avma; return gerepilecopy(av, core2_i(n)); } GEN core0(GEN n,long flag) { return flag? core2(n): core(n); } static long _mod4(GEN c) { long r, s = signe(c); if (!s) return 0; r = mod4(c); if (s < 0) r = 4-r; return r; } long corediscs(long D, ulong *f) { /* D = f^2 d */ long d = D >= 0? (long)coreu(D) : -(long)coreu(-(ulong)D); if ((((ulong)d)&3UL) != 1) d *= 4; if (f) *f = usqrt((ulong)(D/d)); return d; } GEN coredisc(GEN n) { pari_sp av = avma; GEN c = core(n); if (_mod4(c)<=1) return c; /* c = 0 or 1 mod 4 */ return gerepileuptoint(av, shifti(c,2)); } GEN coredisc2(GEN n) { pari_sp av = avma; GEN y = core2_i(n); GEN c = gel(y,1), f = gel(y,2); if (_mod4(c)<=1) return gerepilecopy(av, y); y = cgetg(3,t_VEC); gel(y,1) = shifti(c,2); gel(y,2) = gmul2n(f,-1); return gerepileupto(av, y); } GEN coredisc0(GEN n,long flag) { return flag? coredisc2(n): coredisc(n); } /* Write x = Df^2, where D = fundamental discriminant, * P^E = factorisation of conductor f */ GEN coredisc2_fact(GEN fa, long s, GEN *pP, GEN *pE) { GEN P, E, P0 = gel(fa,1), E0 = gel(fa,2), D = s > 0? gen_1: gen_m1; long l = lg(P0), i, j; E = cgetg(l, t_VECSMALL); P = cgetg(l, t_VEC); for (i = j = 1; i < l; i++) { long e = itos(gel(E0,i)); GEN p = gel(P0,i); if (odd(e)) D = mulii(D, p); e >>= 1; if (e) { gel(P, j) = p; E[j] = e; j++; } } if (Mod4(D) != 1) { D = shifti(D, 2); if (!--E[1]) { P[1] = P[0]; P++; E[1] = E[0]; E++; j--; } } setlg(P,j); *pP = P; setlg(E,j); *pE = E; return D; } ulong coredisc2u_fact(GEN fa, long s, GEN *pP, GEN *pE) { GEN P, E, P0 = gel(fa,1), E0 = gel(fa,2); ulong D = 1; long i, j, l = lg(P0); E = cgetg(l, t_VECSMALL); P = cgetg(l, t_VECSMALL); for (i = j = 1; i < l; i++) { long e = E0[i], p = P0[i]; if (odd(e)) D *= p; e >>= 1; if (e) { P[j] = p; E[j] = e; j++; } } if ((D & 3) != (s > 0? 1: 3)) { D *= 4; if (!--E[1]) { P[1] = P[0]; P++; E[1] = E[0]; E++; j--; } } setlg(P,j); *pP = P; setlg(E,j); *pE = E; return D; } long omegau(ulong n) { pari_sp av; if (n == 1UL) return 0; av = avma; return gc_long(av, nbrows(factoru(n))); } long omega(GEN n) { pari_sp av; GEN F, P; if ((F = check_arith_non0(n,"omega"))) { long n; P = gel(F,1); n = lg(P)-1; if (n && equalim1(gel(P,1))) n--; return n; } if (lgefint(n) == 3) return omegau(n[2]); av = avma; F = absZ_factor(n); return gc_long(av, nbrows(F)); } long bigomegau(ulong n) { pari_sp av; if (n == 1) return 0; av = avma; return gc_long(av, zv_sum(gel(factoru(n),2))); } long bigomega(GEN n) { pari_sp av = avma; GEN F, E; if ((F = check_arith_non0(n,"bigomega"))) { GEN P = gel(F,1); long n = lg(P)-1; E = gel(F,2); if (n && equalim1(gel(P,1))) E = vecslice(E,2,n); } else if (lgefint(n) == 3) return bigomegau(n[2]); else E = gel(absZ_factor(n), 2); E = ZV_to_zv(E); return gc_long(av, zv_sum(E)); } /* assume f = factoru(n), possibly with 0 exponents. Return phi(n) */ ulong eulerphiu_fact(GEN f) { GEN P = gel(f,1), E = gel(f,2); long i, m = 1, l = lg(P); for (i = 1; i < l; i++) { ulong p = P[i], e = E[i]; if (!e) continue; if (p == 2) { if (e > 1) m <<= e-1; } else { m *= (p-1); if (e > 1) m *= upowuu(p, e-1); } } return m; } ulong eulerphiu(ulong n) { pari_sp av; if (!n) return 2; av = avma; return gc_long(av, eulerphiu_fact(factoru(n))); } GEN eulerphi(GEN n) { pari_sp av = avma; GEN Q, F, P, E; long i, l; if ((F = check_arith_all(n,"eulerphi"))) { F = clean_Z_factor(F); n = arith_n(n); if (lgefint(n) == 3) { ulong e; F = mkmat2(ZV_to_nv(gel(F,1)), ZV_to_nv(gel(F,2))); e = eulerphiu_fact(F); return gc_utoipos(av, e); } } else if (lgefint(n) == 3) return utoipos(eulerphiu(uel(n,2))); else F = absZ_factor(n); if (!signe(n)) return gen_2; P = gel(F,1); E = gel(F,2); l = lg(P); Q = cgetg(l, t_VEC); for (i = 1; i < l; i++) { GEN p = gel(P,i), q; ulong v = itou(gel(E,i)); q = subiu(p,1); if (v != 1) q = mulii(q, v == 2? p: powiu(p, v-1)); gel(Q,i) = q; } return gerepileuptoint(av, ZV_prod(Q)); } long numdivu_fact(GEN fa) { GEN E = gel(fa,2); long n = 1, i, l = lg(E); for (i = 1; i < l; i++) n *= E[i]+1; return n; } long numdivu(long N) { pari_sp av; if (N == 1) return 1; av = avma; return gc_long(av, numdivu_fact(factoru(N))); } static GEN numdiv_aux(GEN F) { GEN x, E = gel(F,2); long i, l = lg(E); x = cgetg(l, t_VECSMALL); for (i=1; i 1; v--) u = addui(1, mului(p, u)); return u; } /* 1 + q + ... + q^v */ static GEN euler_sumdiv(GEN q, long v) { GEN u = addui(1, q); for (; v > 1; v--) u = addui(1, mulii(q, u)); return u; } static GEN sumdiv_aux(GEN F) { GEN x, P = gel(F,1), E = gel(F,2); long i, l = lg(P); x = cgetg(l, t_VEC); for (i=1; i 0) return gerepileuptoint(av, v); } if (F) n = arith_n(n); if (k != 1) n = powiu(n,k); return gerepileupto(av, gdiv(v, n)); } GEN usumdiv_fact(GEN f) { GEN P = gel(f,1), E = gel(f,2); long i, l = lg(P); GEN v = cgetg(l, t_VEC); for (i=1; i 1) return 0; return 1; } long uissquarefree(ulong n) { if (!n) return 0; return moebiusu(n)? 1: 0; } long Z_issquarefree(GEN n) { switch(lgefint(n)) { case 2: return 0; case 3: return uissquarefree(n[2]); } return moebius(n)? 1: 0; } long Z_issquarefree_fact(GEN F) { GEN E = gel(F,2); long i, l = lg(E); if (l == 2) return signe(gcoeff(F,1,1))? equali1(gel(E,1)): 0; for(i = 1; i < l; i++) if (!equali1(gel(E,i))) return 0; return 1; } 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)); return gc_long(av, lg(d)==3); case t_VEC: case t_MAT: return Z_issquarefree_fact(check_arith_all(x,"issquarefree")); default: pari_err_TYPE("issquarefree",x); return 0; /* LCOV_EXCL_LINE */ } } pari-2.17.2/src/basemath/hypergeom.c0000644000175000017500000010612114760123736015714 0ustar billbill/* Copyright (C) 2017 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /********************************************************************/ /** **/ /** HYPERGEOMETRIC FUNCTIONS **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" static GEN F10(GEN a, GEN z, long prec) { return gpow(gsubsg(1,z), gneg(a), prec); } static int isnegint2(GEN a, long *pa) { GEN b; if (!is_scalar_t(typ(a)) || !gequal0(imag_i(a))) return 0; a = real_i(a); if (gsigne(a) > 0) return 0; b = ground(a); if (!gequal(a, b)) return 0; if (pa) *pa = -itos(b); return 1; } static int isnegint(GEN a) { return isnegint2(a, NULL); } static int isnegint_approx(GEN a, long bit) { GEN b; if (gexpo(imag_i(a)) > -bit) return 0; a = real_i(a); if (gsigne(a) > 0) return 0; b = ground(a); return gexpo(gsub(a, b)) < -bit; } static int is0(GEN a, long bit) { return gequal0(a) || gexpo(a) < -bit; } static int islong(GEN a, long *m, long prec) { *m = itos(ground(real_i(a))); if (is0(gsubgs(a, *m), prec2nbits(prec) - 5)) return 1; return 0; } static GEN F01(GEN a, GEN z, long prec) { GEN A, B, al, sz; if (is0(z, prec2nbits(prec)-5)) return real_1(prec); sz = gsqrt(z, prec); al = gsubgs(a, 1); A = gmul(ggamma(a, prec), gpow(sz, gneg(al), prec)); B = ibessel(al, gmul2n(sz,1), prec); return isexactzero(imag_i(z))? mulreal(A,B): gmul(A,B); } /* Airy functions [Ai,Bi] */ static GEN airy_i(GEN x, long prec) { long bit = prec2nbits(prec), tx = typ(x), prec2; GEN a, b, A, B, z, z2; if (!is_scalar_t(tx)) pari_err_TYPE("airy",x); if (is0(x, bit)) { GEN s = sqrtnr_abs(utor(3,prec), 6), s3 = powrs(s,3), s4 = mulrr(s,s3); A = invr(mulrr(s4, ggamma(uutoQ(2,3), prec))); B = mulrr(A, s3); return mkvec2(A, B); } prec2 = prec + EXTRAPREC64; x = gprec_wensure(x, prec2); z = gsqrt(gpowgs(x,3), prec2); z2 = gdivgu(gmul2n(z,1),3); if (is_real_t(tx) && gsigne(x) > 0) a = b = gsqrt(x, prec2); /* expression simplifies */ else { a = gsqrtn(z, utoipos(3), NULL, prec2); b = gdiv(x, a); } a = gmul(a, ibessel(sstoQ(-1,3),z2, prec)); b = gmul(b, ibessel(uutoQ(1,3), z2, prec)); if (isexactzero(imag_i(x))) { a = real_i(a); b = real_i(b); } A = gdivgu(gsub(a,b), 3); B = gdiv(gadd(a,b), sqrtr_abs(utor(3, prec))); bit -= gexpo(a) + 16; if (!is0(A, bit) && !is0(B, bit)) return mkvec2(A, B); prec = precdbl(prec); x = gprec_wensure(x, prec); return airy_i(x, prec); } GEN airy(GEN z, long prec) { pari_sp av = avma; return gerepilecopy(av, airy_i(z, prec)); } /* Gamma(a)*Gamma(b); allow a = NULL [omit] */ static GEN mulgamma2(GEN a, GEN b, long prec) { GEN gb = ggamma(b, prec); return a? gmul(ggamma(a, prec), gb): gb; } /* Gamma(a)/Gamma(b) */ static GEN divgamma2(GEN a, GEN b, long prec) { return gdiv(ggamma(a, prec), ggamma(b, prec)); } /* Gamma(v[1])*Gamma(v[2]) */ static GEN mulgammav2(GEN v, long prec) { return mulgamma2(gel(v,1), gel(v,2), prec); } /***********************************************************************/ /** CONFLUENT HYPERGEOMETRIC U(a,b,z) **/ /***********************************************************************/ static GEN Ftaylor(GEN N, GEN D, GEN z, long prec); /* b not integral; use 1F1; prec0 is precision we really want */ static GEN hyperu_F11(GEN a, GEN b, GEN z, long prec0, long prec) { GEN S1, S2, b1 = gsubsg(1, b), ab1 = gadd(a, b1); if (isnegint(ab1)) S1 = gen_0; else { GEN tmp = Ftaylor(mkvec(a), mkvec(b), z, prec); S1 = gmul(divgamma2(b1, ab1, prec), tmp); } if (isnegint(a)) S2 = gen_0; else { GEN tmp = Ftaylor(mkvec(ab1), mkvec(gaddsg(1, b1)), z, prec); S2 = gmul(divgamma2(gneg(b1), a, prec), tmp); S2 = gmul(S2, gpow(z, b1, prec)); } S1 = gadd(S1, S2); if (gexpo(S1)-gexpo(S2) >= prec2nbits(prec0) - prec2nbits(prec)) return S1; prec = precdbl(prec); a = gprec_wensure(a, prec); b = gprec_wensure(b, prec); z = gprec_wensure(z, prec); return hyperu_F11(a, b, z, prec0, prec); } /* one branch of this must assume x > 0 (a,b complex); see Temme, The * numerical computation of the confluent hypergeometric function U(a,b,z), * Numer. Math. 41 (1983), no. 1, 63-82. */ static GEN hyperu_i(GEN a, GEN b, GEN x, long prec) { GEN u, S, P, T, zf, a1; long k, n, bit, l, bigx; if (gequal0(imag_i(x))) x = real_i(x); l = precision(x); if (!l) l = prec; prec = l; a1 = gaddsg(1, gsub(a,b)); P = gmul(a1, a); S = gadd(a1, a); n = (long)(prec2nbits_mul(l, M_LN2) + M_PI*sqrt(dblmodulus(P))); bigx = dbllog2(x) >= log2((double)n); if (!bigx && (!isint(b,&b) || typ(x) == t_COMPLEX || gsigne(x) <= 0)) { if (typ(b) == t_INT) { bit = prec2nbits(l); l = precdbl(l); b = gadd(b, real2n(-bit, l)); a = gprec_wensure(a, l); x = gprec_wensure(x, l); } return hyperu_F11(a, b, x, l, l); } bit = prec2nbits(l)-1; l += EXTRAPREC64; T = gadd(gadd(P, gmulsg(n-1, S)), sqru(n-1)); x = gtofp(x, l); if (!bigx) { /* this part only works if x is real and positive; only used with b t_INT */ pari_sp av2 = avma; GEN q, v, c, s = real_1(l), t = real_0(l); for (k = n-1; k >= 0; k--) { /* T = (a+k)*(a1+k) = a*a1 + k(a+a1) + k^2 = previous(T) - S - 2k + 1 */ GEN p1 = gdiv(T, mulss(-n, k+1)); s = gprec_wtrunc(gaddgs(gmul(p1,s), 1), l); t = gprec_wtrunc(gadd(gmul(p1,t), gaddgs(a,k)), l); if (!k) break; T = gsubgs(gsub(T, S), 2*k-1); if (gc_needed(av2,3)) gerepileall(av2, 3, &s,&t,&T); } q = utor(n, l); zf = gpow(utoi(n), gneg_i(a), l); u = gprec_wensure(gmul(zf, s), l); v = gprec_wensure(gmul(zf, gdivgs(t,-n)), l); for(;;) { GEN p1, e, f, d = real_1(l), qmb = gsub(q,b); pari_sp av3; c = divur(5,q); if (expo(c) >= -1) c = real2n(-1, l); p1 = subsr(1, divrr(x,q)); if (cmprr(c,p1) > 0) c = p1; togglesign(c); av3 = avma; e = u; f = v; for(k = 1;; k++) { GEN w = gadd(gmul(gaddgs(a,k-1),u), gmul(gaddgs(qmb,1-k),v)); u = gmul(divru(q,k),v); v = gdivgu(w, k); d = mulrr(d, c); e = gadd(e, gmul(d,u)); f = gadd(f, p1 = gmul(d,v)); if (gequal0(p1) || gexpo(p1) - gexpo(f) <= 1-prec2nbits(precision(p1))) break; if (gc_needed(av3,3)) gerepileall(av3,5,&u,&v,&d,&e,&f); } u = e; v = f; q = mulrr(q, addrs(c,1)); if (expo(x) - expo(subrr(q,x)) >= bit) break; gerepileall(av2, 3, &u,&v,&q); } } else { /* this part works for large complex x */ GEN zz = gneg_i(ginv(x)), s = gen_1; zf = gpow(x, gneg_i(a), l); for (k = n-1; k >= 0; k--) { s = gaddsg(1, gmul(gmul(T, gdivgu(zz,k+1)), s)); if (!k) break; T = gsubgs(gsub(T, S), 2*k-1); } u = gmul(s, zf); } return gprec_wtrunc(u, prec); } GEN hyperu(GEN a, GEN b, GEN x, long prec) { pari_sp av = avma; return gerepilecopy(av, hyperu_i(a,b,x,prec)); } static GEN mkendpt(GEN z, GEN a) { a = real_i(a); if (gcmpgs(a,-1) <= 0) pari_err_IMPL("hypergeom for these parameters"); return (gcmpgs(a,1) >= 0 || gequal0(a))? z: mkvec2(z, a); } /*z != 0 */ static GEN F20(GEN a, GEN b, GEN z, long prec) { GEN U; z = gneg_i(z); U = hyperu_i(a, gadd(a, gsubsg(1, b)), ginv(z), prec); return gmul(U, gpow(z, gneg(a), prec)); } static GEN F21(GEN a, GEN b, GEN c, GEN z, long prec); static GEN fF31(void *E, GEN t) { pari_sp av = avma; GEN a1 = gel(E,1), b = gel(E,2), c = gel(E,3), d = gel(E,4), z = gel(E,5); long prec = precision(t); return gerepileupto(av, gmul(gmul(gexp(gneg(t), prec), gpow(t, a1, prec)), F21(b, c, d, gmul(t, z), prec))); } /* F31(a,b,c;d,z) = \int_0^oo\exp(-t)t^{a-1}F_{21}(b,c;d,tz) / gamma(a) */ static GEN F31(GEN a, GEN b, GEN c, GEN d, GEN z, long prec) { GEN p1, p2, a1; if (gcmp(real_i(a), real_i(b)) < 0) swap(a,b); if (gcmp(real_i(a), real_i(c)) < 0) swap(a,c); if (gsigne(real_i(a)) <= 0) pari_err_IMPL("F31 with a, b, and c <= 0"); a1 = gsubgs(a,1); p1 = mkendpt(gen_0, a1); p2 = mkvec2(mkoo(), gen_1); return gdiv(intnum(mkvecn(5, a1, b, c, d, z), fF31, p1, p2, NULL, prec), ggamma(a, prec)); } /* F32(a,b,c;d,e;z)=\int_0^1,x^{c-1}(1-x)^{e-c-1}F21(a,b,d,x*z)*gamma(e)/(gamma(c)*gamma(e-c)) */ static GEN fF32(void *E, GEN x) { pari_sp av = avma; GEN c1 = gel(E,1), ec = gel(E,2), a = gel(E,3), b = gel(E,4); GEN d = gel(E,5), z = gel(E,6), T; long prec = precision(x); T = F21(a, b, d, gmul(x, z), prec); if (!gequal0(c1)) T = gmul(T, gpow(x,c1,prec)); if (!gequal0(ec)) T = gmul(T, gpow(gsubsg(1,x),ec,prec)); return gerepileupto(av,T); } static GEN myint32(GEN a, GEN b, GEN c, GEN d, GEN e, GEN z, long prec) { GEN c1 = gsubgs(c,1), c2 = gsub(e, gaddgs(c,1)); GEN p0 = mkendpt(gen_0, c1); GEN p1 = mkendpt(gen_1, c2); return intnum(mkvecn(6, c1, c2, a,b,d, z), fF32, p0, p1, NULL, prec); } static void check_hyp1(GEN x) { if (gsigne(real_i(x)) <= 0) pari_err_DOMAIN("hypergeom","real(vecsum(D)-vecsum(N))", "<=", gen_0, x); } /* 0 < re(z) < e ? */ static int ok_F32(GEN z, GEN e) { GEN x = real_i(z); return gsigne(x) > 0 && gcmp(e, x) > 0; } /* |z| very close to 1 but z != 1 */ static GEN F32(GEN N, GEN D, GEN z, long prec) { GEN tmp, a,b,c, d,e, re; a = gel(N,1); d = gel(D,1); b = gel(N,2); e = gel(D,2); c = gel(N,3); if (gcmp(real_i(e), real_i(d)) < 0) swap(e,d); re = real_i(e); if (!ok_F32(c, re)) { if (ok_F32(b, re)) {swap(b,c);} else if (ok_F32(a, re)) {swap(a,c);} else pari_err_IMPL("3F2 for these arguments"); } tmp = gdiv(ggamma(e, prec), mulgamma2(c, gsub(e,c), prec)); return gmul(tmp, myint32(a, b, c, d, e, z, prec)); } static GEN poch(GEN a, long n, long prec) { GEN S = real_1(prec); long j; for (j = 0; j < n; j++) S = gmul(S, gaddsg(j, a)); return S; } static GEN vpoch(GEN a, long n) { GEN v = cgetg(n+1, t_VEC); long j; gel(v,1) = a; for (j = 1; j < n; j++) gel(v,j+1) = gmul(gel(v,j), gaddsg(j, a)); return v; } static GEN Npoch(GEN a, long n) { return gnorm(poch(a, n, LOWDEFAULTPREC)); } static GEN Npochden(GEN a, long n) { GEN L = Npoch(a, n), r = ground(real_i(a)); if (signe(r) <= 0) { GEN t = gnorm(gsub(a, r)); if (gcmpgs(t,1) > 0) L = gmul(L, t); } return L; } /* |x + z|^2 */ static GEN normpol2(GEN z) { GEN a = real_i(z), b = imag_i(z); return deg2pol_shallow(gen_1, gmul2n(a,1), gadd(gsqr(a),gsqr(b)), 0); } /* \prod |x + v[i]|^2 */ static GEN vnormpol2(GEN v) { long i, l = lg(v); GEN P; if (l == 1) return pol_1(0); P = normpol2(gel(v,1)); for (i = 2; i < l; i++) P = RgX_mul(P, normpol2(gel(v,i))); return P; } /* return an 'extraprec' */ static long precFtaylor(GEN N, GEN D, GEN z, long *pmi) { GEN v, ma, P = vnormpol2(D), Q = vnormpol2(N), Nz = gnorm(z); double wma, logNz = (gexpo(Nz) < -27)? -27: dbllog2(Nz) / 2; long pr = LOWDEFAULTPREC, prec = precision(z); long lN = lg(N), lD = lg(D), j, i, lv; P = RgX_shift_shallow(P, 2); /* avoid almost cancellation of leading coeff if |z| ~ 1 */ if (!prec || fabs(logNz) > 1e-38) Q = RgX_Rg_mul(Q,Nz); for (j = 1, ma = NULL; j < lN; j++) { GEN Nj = gel(N,j); if (isint(Nj,&Nj) && signe(Nj) <= 0 && (!ma || abscmpii(ma, Nj) < 0)) ma = Nj; } /* use less sharp fujiwara_bound_real(,1) ? */ v = realroots(gsub(P,Q), mkvec2(gen_0,mkoo()), pr); v = ZV_to_zv(ground(v)); lv = lg(v); if (ma) { long sma = is_bigint(ma)? LONG_MAX: maxss(labs(itos(ma))-1, 1); for (i = 1; i < lv; i++) v[i] = maxss(minss(sma, v[i]), 1); } for (i = 1, wma = 0.; i < lv; i++) { GEN t1 = gen_1, t2 = gen_1; long u = v[i]; double t; for (j = 1; j < lN; j++) t1 = gmul(t1, Npoch(gel(N,j), u)); for (j = 1; j < lD; j++) t2 = gmul(t2, Npochden(gel(D,j), u)); t = dbllog2(gdiv(t1,t2)) / 2 + u * logNz - dbllog2(mpfactr(u,pr)); wma = maxdd(wma, t); /* t ~ log2 | N(u)/D(u) z^u/u! | */ } /* make up for exponential decrease in exp() */ if (gsigne(real_i(z)) < 0) wma -= gtodouble(real_i(z)) / M_LN2; *pmi = maxss(v[lv-1],1); return nbits2extraprec(wma+BITS_IN_LONG); } static GEN Ftaylor(GEN N, GEN D, GEN z, long prec) { pari_sp av; GEN C, S; long i, j, ct, lN = lg(N), lD = lg(D), pradd, mi, bitmin, tol; pradd = precFtaylor(N, D, z, &mi); if (pradd > 0) { prec += pradd; N = gprec_wensure(N, prec); D = gprec_wensure(D, prec); z = gprec_wensure(z, prec); } bitmin = -(prec2nbits(prec) + 10); S = C = real_1(prec); ct = 0; j = 0; tol = 0; av = avma; for(;;) { GEN a = gen_1, b = gen_1; for (i = 1; i < lN; i++) a = gmul(a, gaddsg(j, gel(N,i))); for (i = 1; i < lD; i++) b = gmul(b, gaddsg(j, gel(D,i))); C = gmul(C, gmul(gdiv(a, gmulsg(j+1, b)), z)); if (gequal0(C)) break; if (j > mi) tol = gequal0(S)? 0: gexpo(C) - gexpo(S); S = gadd(S, C); j++; if (j > mi) { if (tol > bitmin) ct = 0; else if (++ct >= lN+lD-2) break; } if (gc_needed(av, 1)) gerepileall(av, 2, &S, &C); } return S; } static GEN bind(GEN a, GEN b, GEN c, long ind) { switch(ind) { case 1: case 2: return gsub(c, b); case 5: case 6: return gsub(gaddsg(1, a), c); default: return b; /* 3,4 */ } } static GEN cind(GEN a, GEN b, GEN c, long ind) { switch(ind) { case 1: case 6: return gaddsg(1, gsub(a,b)); case 4: case 5: return gsub(gaddsg(1, gadd(a,b)), c); default: return c; /* 2,3 */ } } static GEN zind(GEN z, long ind) { switch(ind) { case 1: return ginv(gsubsg(1, z)); case 2: return gdiv(z, gsubgs(z, 1)); case 4: return gsubsg(1, z); case 5: return gsubsg(1, ginv(z)); case 6: return ginv(z); default: return z; /* 3, LCOV_EXCL_LINE*/ } } /* z not 0 or 1, c not a nonpositive integer. Among the generic 6 * Kummer transforms 1/(1-z),z/(z-1),z,1-z,1-1/z,1/z, check in this order * which ones are allowed and return the index for the one with smallest * resulting |z|. If that modulus is "far enough" from 1 [we can sum the Taylor * series], return it negated. Otherwise, we'll use integral representations. */ static long F21ind(GEN a, GEN b, GEN c, GEN z, long bit) { GEN v = const_vec(6, mkoo()); long ind = 0, B = bit - 5; const long LD = LOWDEFAULTPREC; if (!isnegint_approx(cind(a,b,c, 1),B)) { /* 1 and 6 are allowed */ gel(v,1) = gabs(zind(z,1), LD); gel(v,6) = gabs(zind(z,6), LD); } gel(v,2) = gabs(zind(z,2), LD); gel(v,3) = gabs(z, LD); if (!isnegint_approx(cind(a,b,c, 4),B)) { /* 4 and 5 are allowed */ gel(v,4) = gabs(zind(z,4), LD); gel(v,5) = gabs(zind(z,5), LD); } ind = vecindexmin(v); /* |znew| <= 1; close to 1 ? */ return (gexpo(gsubgs(gel(v,ind),1)) > -maxss(bit / 4, 32))? -ind: ind; } static GEN mul3(GEN a, GEN b, GEN c) { return gmul(a,gmul(b, c)); } /* return the polynomial of degree N >= 1 * \sum_{i=0} binomial(N,i) (c-a)_i (a)_{N-i} X^i */ static GEN F21lam(long N, GEN a, GEN c) { GEN C = vecbinomial(N), S = cgetg(N+2, t_VEC); GEN vb = vpoch(gsub(c,a), N), va = vpoch(a, N); long i; gel(S,1) = gel(va,N); for (i = 1; i < N; i++) gel(S,i+1) = mul3(gel(C,i+1), gel(vb,i), gel(va,N-i)); gel(S,i+1) = gel(vb,N); return RgV_to_RgX(S,0); } /* F(-m,b; c; z), m >= 0; c != 0, -1, -2, ... */ static GEN F21finitetaylor(long m, GEN b, GEN c, GEN z, long prec) { pari_sp av; GEN C, P, S; long j, ct, pradd, mi, bitmin; if (isnegint2(b, &j) && j < m) { b = stoi(-m); m = j; } pradd = precFtaylor(mkvec2(stoi(-m), b), mkvec(c), z, &mi); if (pradd > 0) { prec += pradd; b = gprec_wensure(b, prec); c = gprec_wensure(c, prec); z = gprec_wensure(z, prec); } bitmin = -(prec2nbits(prec) + 10); C = vecbinomial(m); P = real_1(prec); S = P; ct = 0; av = avma; for(j = 0; j < m; j++) /* 15.2.4 */ { GEN p; P = gmul(P, gmul(z, gdiv(gaddsg(j,b), gaddsg(j,c)))); /*(b)_j z^j / (c)_j*/ p = gmul(P, gel(C, j+1)); /* times binomial(m,j) */ if (j > mi && !gequal0(S)) { if (gexpo(p) - gexpo(S) > bitmin) ct = 0; else if (++ct == 3) break; } S = odd(j)? gsub(S, p): gadd(S, p); if (gc_needed(av, 1)) gerepileall(av, 2, &S, &P); } return S; } static GEN F21finite_i(GEN F, GEN B, GEN C, long m, long prec) { return gdiv(gmul(F, poch(B, m, prec)), poch(C, m, prec)); } /* F(-m,b; c; z), m >= 0; c not a nonpositive integer */ static GEN F21finite(long m, GEN b, GEN c, GEN z, long prec) { GEN a = stoi(-m), b1, c1, z1, F; long ind = F21ind(a, b, c, z, prec2nbits(prec)); if (ind > 0 || ind == -3) return F21finitetaylor(m, b, c, z, prec); ind = labs(ind); z1 = zind(z, ind); b1 = bind(a, b, c, ind); c1 = cind(a, b, c, ind); /* not a nonpositive integer */ F = F21finitetaylor(m, b1, c1, z1, prec); switch (ind) { case 1: return F21finite_i(gmul(F, gpowgs(gsubsg(1,z), m)), b, c, m, prec); case 2: return gmul(F, gpowgs(gsubsg(1,z), m)); case 4: return F21finite_i(F, gsub(c,b), c, m, prec); case 5: return F21finite_i(gmul(F, gpowgs(z,m)), gsub(c,b), c, m, prec); case 6: return F21finite_i(gmul(F, gpowgs(gneg(z),m)), b, c, m, prec); } return NULL; /*LCOV_EXCL_LINE*/ } /**********************************************************/ /* allow a = NULL [omit] */ static GEN multgam(GEN a, GEN b, GEN c, GEN d, long prec) { if (isnegint(c) || isnegint(d)) return gen_0; return gdiv(mulgamma2(a, b, prec), mulgamma2(c, d, prec)); } static GEN intnumsplit(void *E, GEN (*f)(void*, GEN), GEN a, GEN b, GEN z, long prec) { if (!z) return intnum(E, f, a, b, NULL, prec); return gadd(intnum(E, f, a, z, NULL, prec), intnum(E, f, z, b, NULL, prec)); } /* (1 - zt)^a T(1-zt) t^b (1-t)^c */ static GEN fF21(void *E, GEN t) { GEN z = gel(E,1), a = gel(E,2), b = gel(E,3), c = gel(E,4), T = gel(E,5); GEN u = gsubsg(1, gmul(z, t)); long prec = precision(t); GEN x = mul3(gpow(u, a, prec), gpow(t, b, prec), gpow(gsubsg(1,t), c, prec)); return T? gmul(x, poleval(T, u)): x; } /* z != 1 */ static GEN int21(GEN a, GEN b, GEN c, GEN z, GEN T, long prec) { GEN A = gneg(a), B = gsubgs(b,1), C = gsubgs(gsub(c,b), 1), rA = real_i(A); GEN pz = NULL, p0 = mkendpt(gen_0, B), p1 = mkendpt(gen_1, C); GEN E = mkvec5(z, A, B, C, T); if (gcmpgs(rA, 1) <= 0 && is0(imag_i(z), 10)) { GEN r; pz = ginv(z); r = real_i(pz); if (gsigne(r) <= 0 || gcmp(r, gen_1) >= 0) pz = NULL; } if (pz) pz = mkendpt(pz,rA); else if (gcmpgs(rA,-1) <= 0) prec += ((gexpo(rA)+1)>>1) * EXTRAPREC64; return intnumsplit((void*)E, fF21, p0, p1, pz, prec); } static GEN F21taylorind(GEN a, GEN b, GEN c, GEN z, long ind, long prec); /* c not a nonpositive integer */ static GEN F21_i(GEN a, GEN b, GEN c, GEN z, long prec) { GEN res, p = NULL, T = NULL; long m, ind, prec2, bitprec = prec2nbits(prec); if (is0(imag_i(z), bitprec)) z = real_i(z); if (is0(z, bitprec)) return real_1(prec); if (gequal1(z)) { GEN x = gsub(c, gadd(a, b)); check_hyp1(x); return multgam(c, x, gsub(c,a), gsub(c,b), prec); } /* z != 0,1 */ if (isnegint2(b, &m)) return F21finite(m, a, c, z, prec); if (isnegint2(a, &m)) return F21finite(m, b, c, z, prec); if (isnegint(gsub(c, b))) swap(a, b); if (isnegint2(gsub(c, a), &m)) { GEN x = gpow(gsubsg(1, z), gneg(gaddsg(m, b)), prec); return gmul(x, F21finite(m, gsub(c, b), c, z, prec)); } /* None of a, b, c, c-a, c-b is a nonpositive integer. * Try Kummer transforms */ ind = F21ind(a, b, c, z, bitprec); prec2 = prec + EXTRAPREC64; a = gprec_wensure(a,prec2); b = gprec_wensure(b,prec2); c = gprec_wensure(c,prec2); z = gprec_wensure(z,prec2); /* can ensure |z| << 1: sum the Taylor series */ if (ind < 0) return gprec_wtrunc(F21taylorind(a,b,c, z, ind, prec), prec); /* can ensure |z| <= 1, but too close to 1: use integral 15.6.1 for * F21 / Gamma(c) */ if (gsigne(real_i(b)) <= 0) { if (gsigne(real_i(a)) <= 0) { /* 15.5.16 (a and b swapped) divided by c */ GEN p1,p2; if (gcmp(real_i(b), real_i(a)) < 0) swap(a,b); /* FIXME: solve recursion as below with F21lam */ p1 = gmul(gsubsg(1, z), F21_i(a, gaddsg(1,b), c, z, prec)); p2 = gmul(gmul(gsubsg(1, gdiv(a,c)), z), F21_i(a, gaddsg(1,b), gaddsg(1,c), z, prec)); return gadd(p1, p2); } swap(a,b); } /* Here real(b) > 0 */ if (gcmp(real_i(a), real_i(b)) < 0 && gsigne(real_i(a)) > 0) swap(a,b); /* further, either real(a) <= 0 or real(a) >= real(b) */ if (gcmp(real_i(c), real_i(b)) <= 0) { /* T(x) = sum_i binomial(N,i) (c-a)_i (a)_{N-i} x^i * (c)_N F(a,b,c;z) = sum_{i = 0}^N Ti F(a+N-i,b,c+N;z) for N >= 0, * where F = 2F1 / Gamma(c) */ long N = 1 + itos(gfloor(gsub(real_i(b),real_i(c)))); /* >= 1 */ T = F21lam(N, a, c); p = poch(c, N, prec); c = gaddsg(N,c); /* now real(b) < real(c) */ a = gaddsg(N,a); } /* real(b) < real(c) */ res = int21(a, b, c, z, T, prec2); if (p) res = gdiv(res, p); /* res = 2F1(a0,b0,c0; z)*Gamma(b)Gamma(c-b)/Gamma(c) by 15.6.1 */ return gdiv(gmul(ggamma(c,prec),res), mulgamma2(b, gsub(c,b), prec)); } /* c not a non-positive integer */ static GEN F21(GEN a, GEN b, GEN c, GEN z, long prec) { GEN res = F21_i(a, b, c, z, prec); long ex = labs(gexpo(res)), bitprec = prec2nbits(prec); if (ex > bitprec) { prec = nbits2prec(ex + bitprec); res = F21_i(gprec_wensure(a,prec), gprec_wensure(b,prec), gprec_wensure(c,prec), gprec_wensure(z,prec), prec); } return res; } static GEN F21taylor(GEN a, GEN b, GEN c, GEN z, long prec) { pari_sp av = avma; GEN r = gdiv(Ftaylor(mkvec2(a,b), mkvec(c), z, prec), ggamma(c, prec)); return gerepileupto(av, r); } static GEN F21taylorlim(GEN N, long m, GEN z, GEN Z, long ind, long prec) { pari_sp av; GEN C, P, S, a, b; long j, ct, pradd, mi, fl, bitmin, tol, si = (ind == 5 || ind == 6)? -1: 1; pradd = precFtaylor(N, mkvec(stoi(m + 1)), z, &mi); if (pradd) { prec += pradd; N = gprec_wensure(N, prec); z = gprec_wensure(z, prec); Z = gprec_wensure(Z, prec); } av = avma; a = gel(N,1); b = gel(N,2); bitmin = -(prec2nbits(prec) + 10); P = glog(Z, prec); if (ind == 4 || ind == 5) P = gneg(P); P = gadd(P, gsub(gpsi(stoi(m+1), prec), mpeuler(prec))); P = gsub(P, gadd(gpsi(a, prec), gpsi(si == -1? gsubsg(1, b): b, prec))); C = real_1(prec); ct = 0; tol = 0; S = P; for(j = 0, fl = 1;;) { GEN v1 = gaddgs(a, j), v2 = gaddgs(b, j); long J = (j+1) * (j+1+m); C = gmul(C, gdivgs(gmul(z, v1), J)); if (gequal0(v2)) fl = 0; else C = gmul(C, v2); if (j > mi) tol = gequal0(S) ? 0 : gexpo(C) - gexpo(S); if (fl) { P = gadd(P, gsub(uutoQ(2*j+2+m, J), gadd(ginv(v1), ginv(v2)))); S = gadd(S, gmul(C, P)); } else S = (si == 1)? gadd(S, C): gsub(S, C); if (++j > mi) { if (tol > bitmin) ct = 0; else if (++ct == 3) break; } if (gc_needed(av, 1)) gerepileall(av, 3, &S, &C, &P); } return gdiv(S, mpfact(m)); } /* N = [a,b]; (m-1)! sum_{0 <= k < m} (-z)^k (a)_k (b)_k / k!(m-k)...(m-1) */ static GEN F21finitelim(GEN N, long m, GEN z, long prec) { GEN C, S, a, b; long k; if (!m) return gen_0; a = gel(N,1); b = gel(N,2); S = C = real_1(prec + EXTRAPREC64); for (k = 1; k < m; k++) { GEN v1 = gaddsg(k-1, a), v2 = gaddsg(k-1, b); C = gdivgs(gmul(C, gmul(gmul(v1, v2), z)), k*(k-m)); S = gadd(S, C); } return gmul(S, mpfact(m-1)); } static GEN OK_gadd(GEN x, GEN y, long prec0, long *pprec, GEN *d1,GEN *d2,GEN *d3,GEN *d4,GEN *d5,GEN *d6,GEN *d7,GEN *d8) { long prec = *pprec; GEN z = gadd(x,y); if (!gequal0(z) && gexpo(z)-gexpo(x) >= prec2nbits(prec0) - prec2nbits(prec)) return z; *pprec = prec = precdbl(prec); *d1 = gprec_wensure(*d1, prec); *d2 = gprec_wensure(*d2, prec); *d3 = gprec_wensure(*d3, prec); *d4 = gprec_wensure(*d4, prec); *d5 = gprec_wensure(*d5, prec); *d6 = gprec_wensure(*d6, prec); *d7 = gprec_wensure(*d7, prec); *d8 = gprec_wensure(*d8, prec); return NULL; } static GEN FBaux1(GEN v1, GEN g1, GEN c1, GEN v2, GEN g2, GEN c2, GEN z, GEN bma, long prec0, long prec) { GEN pi = mppi(prec); for (;;) { GEN t1 = gdiv(c1, mulgammav2(g1, prec)), r1; GEN t2 = gdiv(c2, mulgammav2(g2, prec)), r2, F; r1 = gmul(t1, F21taylor(gel(v1,1), gel(v1,2), gel(v1,3), z, prec)); r2 = gmul(t2, F21taylor(gel(v2,1), gel(v2,2), gel(v2,3), z, prec)); F = OK_gadd(r1, r2, prec0, &prec, &c1,&c2, &g1,&g2, &v1,&v2, &z,&bma); if (F) return gmul(F, gdiv(pi, gsin(gmul(pi, bma), prec))); } } static GEN FBaux2(GEN v1, GEN g1, GEN c1, long m, GEN z1, GEN c2, GEN g2, GEN v2, GEN z2, GEN Z2, long ind, long prec) { GEN t1 = gdiv(c1, mulgammav2(g1, prec)), r1; GEN t2 = gdiv(c2, mulgammav2(g2, prec)), r2; r1 = gmul(t1, F21finitelim(v1, m, z1, prec)); r2 = gmul(t2, F21taylorlim(v2, m, z2, Z2, ind, prec)); return gadd(r1, r2); } /* 1 / (1-z) */ static GEN F21taylor1(GEN a, GEN b, GEN c, GEN z, long prec) { GEN bma = gsub(b, a), coe1, coe2, z1, g1, g2, v1, v2, Z; long m; if (!islong(bma,&m, prec)) { GEN b1, c1, e1, c2; b1 = gsub(c, b); c1 = gsubsg(1, bma); e1 = gsub(c, a); coe1 = gpow(gsubsg(1, z), gneg(a), prec); c2 = gaddgs(bma, 1); coe2 = gneg(gpow(gsubsg(1, z), gneg(b), prec)); z1 = ginv(gsubsg(1, z)); return FBaux1(mkvec3(a,b1,c1), mkvec2(b,e1), coe1, mkvec3(b,e1,c2), mkvec2(a,b1), coe2, z1, bma, prec, prec); } if (m < 0) { swap(a,b); m = -m; } Z = gsubsg(1, z); coe1 = gpow(Z, gneg(a), prec); v2 = g1 = mkvec2(gaddgs(a, m), gsub(c, a)); v1 = mkvec2(a, gsub(c, gaddgs(a, m))); z1 = ginv(Z); coe2 = gmul(coe1, gpowgs(z1, m)); if (m & 1L) coe2 = gneg(coe2); g2 = mkvec2(a, gsub(c, gaddgs(a, m))); /* 15.8.9 */ return FBaux2(v1, g1, coe1, m, z1, coe2, g2, v2, z1, Z, 1, prec); } /* 1 - z */ static GEN F21taylor4(GEN a, GEN b, GEN c, GEN z, long prec) { GEN bma = gsub(c, gadd(a, b)), coe2, z1, z2, g1, g2, v1, v2, F = NULL; long m; z1 = gsubsg(1, z); if (!islong(bma,&m, prec)) { GEN c1, a2, b2, c2; c1 = gsubsg(1, bma); a2 = gsub(c, a); b2 = gsub(c, b); c2 = gaddsg(1, bma); coe2 = gneg(gpow(z1, bma, prec)); return FBaux1(mkvec3(a,b,c1), mkvec2(a2,b2), gen_1, mkvec3(a2,b2,c2), mkvec2(a,b), coe2, z1, bma, prec, prec); } /* c - (a+b) ~ m; if m < 0: 15.8.12 */ if (m < 0) { m = -m; a = gsubgs(a, m); b = gsubgs(b, m); F = gpowgs(z1, -m); } v2 = g1 = mkvec2(gaddgs(a,m), gaddgs(b,m)); v1 = g2 = mkvec2(a, b); z2 = gneg(z1); coe2 = gpowgs(z2, m); /* 15.8.10 */ z1 = FBaux2(v1, g1, gen_1, m, z1, coe2, g2, v2, z1, z1, 4, prec); if (F) z1 = gmul(z1, F); return z1; } /* 1 - 1/z */ static GEN F21taylor5(GEN a, GEN b, GEN c, GEN z, long prec) { GEN bma = gsub(c, gadd(a,b)), coe1, coe2, z1, g1, g2, v1, v2, z2, F = NULL; long m; if (!islong(bma,&m, prec)) { GEN b1, c1, d1, e1, b2, c2; d1 = gsub(c, a); b1 = gsubsg(1, d1); c1 = gsubsg(1, bma); e1 = gsub(c, b); b2 = gsubsg(1, a); c2 = gaddsg(1, bma); coe1 = gpow(z, gneg(a), prec); coe2 = gneg(gmul(gpow(gsubsg(1, z), bma, prec), gpow(z, gneg(d1), prec))); z1 = gsubsg(1, ginv(z)); return FBaux1(mkvec3(a,b1,c1), mkvec2(d1,e1), coe1, mkvec3(d1,b2,c2), mkvec2(a, b), coe2, z1, bma, prec, prec); } /* c - (a+b) ~ m; if m < 0: 15.8.12 */ if (m < 0) { m = -m; a = gsubgs(a,m); b = gsubgs(b,m); F = gpowgs(gsubsg(1, z), -m); } g1 = mkvec2(gaddgs(a,m), gaddgs(b,m)); v1 = mkvec2(a, gsubsg(1-m, b)); v2 = mkvec2(gaddgs(a,m), gsubsg(1,b)); z1 = gsubgs(ginv(z), 1); z2 = gneg(z1); g2 = mkvec2(a, b); coe1 = gpow(z, gneg(a), prec); coe2 = gmul(coe1, gpowgs(z2, m)); /* 15.8.11 */ z1 = FBaux2(v1, g1, coe1, m, z1, coe2, g2, v2, z2, z1, 5, prec); if (F) z1 = gmul(z1, F); return z1; } /* 1 / z */ static GEN F21taylor6(GEN a, GEN b, GEN c, GEN z, long prec) { GEN bma = gsub(b, a), cma, am, coe1, coe2, z1, g1, g2, v1, v2, z2, Z; long m; if (!islong(bma,&m, prec)) { GEN e1, e2, b1, b2, c1, c2; b1 = gaddgs(gsub(a,c), 1); c1 = gsubsg(1, bma); e1 = gsub(c,a); b2 = gaddgs(gsub(b,c), 1); c2 = gaddgs(bma, 1); e2 = gsub(c, b); coe1 = gpow(gneg(z), gneg(a), prec); coe2 = gneg(gpow(gneg(z), gneg(b), prec)); z1 = ginv(z); return FBaux1(mkvec3(a,b1,c1), mkvec2(b,e1), coe1, mkvec3(b,b2,c2), mkvec2(a,e2), coe2, z1, bma, prec, prec); } /* b - a ~ m */ if (m < 0) { swap(a,b); m = -m; } cma = gsub(c, a); am = gaddgs(a,m); Z = gneg(z); coe1 = gpow(Z, gneg(a), prec); coe2 = gdiv(coe1, gpowgs(z, m)); g1 = mkvec2(am, cma); v1 = mkvec2(a, gsubsg(1, cma)); g2 = mkvec2(a, gsubgs(cma, m)); v2 = mkvec2(am, gsubsg(m+1, cma)); z2 = ginv(z); z1 = gneg(z2); /* 15.8.8 */ return FBaux2(v1, g1, coe1, m, z1, coe2, g2, v2, z2, Z, 6, prec); } /* (new b, new c, new z): given by bind, cind, zind * case 1: (c-b,1+a-b,1/(1-z)) 15.8.3 15.8.6 * case 2: (c-b,c,z/(z-1)) 15.8.1 * case 3: (b,c,z) * case 4: (b,b-c+a+1,1-z) 15.8.4 15.8.7 15.8.10 * case 5: (1+a-c,b-c+a+1,1-1/z) 15.8.5 15.8.7 15.8.11 * case 6: (1+a-c,1+a-b,1/z) 15.8.2 15.8.6 */ static GEN F21taylorind(GEN a, GEN b, GEN c, GEN z, long ind, long prec) { GEN res; switch (labs(ind)) { case 1: res = F21taylor1(a, b, c, z, prec); break; case 2: return gmul(Ftaylor(mkvec2(a, gsub(c, b)), mkvec(c), gdiv(z, gsubgs(z,1)), prec), gpow(gsubsg(1,z), gneg(a), prec)); case 3: return Ftaylor(mkvec2(a,b), mkvec(c), z, prec); case 4: res = F21taylor4(a, b, c, z, prec); break; case 5: res = F21taylor5(a, b, c, z, prec); break; default:res = F21taylor6(a, b, c, z, prec); break; } return gmul(ggamma(c, prec), res); } static long hypersimplify(GEN *pn, GEN *pd) { GEN n = *pn, d = *pd; long j, ld = lg(d), ln = lg(n); for (j = 1; j < ld; j++) { GEN t = gel(d, j); long k; for (k = 1; k < ln; k++) if (gequal(t, gel(n, k))) { *pd = vecsplice(d, j); *pn = vecsplice(n, k); return hypersimplify(pd, pn) + 1; } } return 0; } static GEN f_pochall(void *E, GEN n) { GEN S, a, tmp, N = gel(E,1), D = gel(E,2); long j, prec = itou(gel(E,3)); S = gen_0; for (j = 1; j < lg(N); j++) { a = gel(N, j); tmp = gsub(glngamma(gadd(n, a), prec), glngamma(a, prec)); S = gadd(S, tmp); } for (j = 1; j < lg(D); j++) { a = gel(D, j); tmp = gsub(glngamma(gadd(n, a), prec), glngamma(a, prec)); S = gsub(S, tmp); } return gexp(gsub(S, glngamma(gaddsg(1, n), prec)), prec); } static GEN f_pochall_alt(void *E, GEN n) { GEN z = f_pochall(E,n); return mpodd(n)? gneg(z): z; } /* z = \pm1 */ static GEN sumz(GEN N, GEN D, long z, long prec) { void *E = (void*)mkvec3(N, D, utoi(prec)); GEN tab, be; if (z == -1) return sumalt(E, f_pochall_alt, gen_0, prec); be = gsub(vecsum(D), vecsum(N)); check_hyp1(be); tab = sumnummonieninit(be, NULL, gen_0, prec); return sumnummonien(E, f_pochall, gen_0, tab, prec); } static GEN hypergeom_arg(GEN x) { if (!x) return cgetg(1,t_VEC); return (typ(x) == t_VEC)? x: mkvec(x); } /* [x[i]+k, i=1..#v] */ static GEN RgV_z_add(GEN x, long k) { if (!k) return x; pari_APPLY_same(gaddgs(gel(x,i), k)); } static GEN vp(GEN a, GEN p, GEN dft) { long v = gvaluation(a, p); return v < 0? stoi(v): dft; } static GEN Qp_hypergeom(GEN N, GEN D, GEN z) { pari_sp av = avma; GEN r, S = gen_1, R = gen_1, p = gel(z, 2), dft = ginv(subis(p, 1)); long l, i, prec = precp(z) + valp(z) + 1; r = gsub(stoi(valp(z)), dft); l = lg(N); for (i = 1; i < l; i++) r = gadd(r, vp(gel(N,i), p, dft)); l = lg(D); for (i = 1; i < l; i++) r = gsub(r, vp(gel(D,i), p, dft)); if (gsigne(r) <= 0) pari_err(e_MISC, "divergent p-adic hypergeometric sum"); l = itou(gceil(gdivsg(prec, r))); for (i = 1; i <= l; i++) { GEN u = vecprod(RgV_z_add(N, i-1)), v = vecprod(RgV_z_add(D, i-1)); R = gmul(R, gmul(z, gdiv(u, gmulsg(i, v)))); S = gadd(S, R); if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"hypergeom, i = %ld / %ld", i,l); gerepileall(av, 2, &R, &S); } } return S; } /* assume is_scalar_t(typ(z)) */ static GEN hypergeom_i(GEN N, GEN D, GEN z, long prec) { long nN, nD; if (typ(z) == t_PADIC) return Qp_hypergeom(N, D, z); if (gequal0(z)) return gen_1; nN = lg(N) - 1; nD = lg(D) - 1; if (nD >= (nN? nN: 2)) return Ftaylor(N, D, z, prec); if (nD == nN - 1 && nN >= 3) { GEN d = gsubsg(1, gabs(z,LOWDEFAULTPREC)); long ed = gexpo(d); /* z in unit disc but "away" from unit circle */ if (gsigne(d) > 0 && ed > -prec2nbits(prec)/4 && (nN != 3 || ed > -15)) /* For 3F2 we can use integral */ return Ftaylor(N, D, z, prec); if (gequal1(z)) return sumz(N, D, 1, prec); if (gequalm1(z)) return sumz(N, D,-1, prec); } switch (nN) { case 0: if (nD == 0) return gexp(z, prec); if (nD == 1) return F01(gel(D,1), z, prec); case 1: return F10(gel(N, 1), z, prec); case 2: if (nD == 0) return F20(gel(N,1), gel(N,2), z, prec); if (nD == 1) return F21(gel(N,1), gel(N,2), gel(D,1), z, prec); case 3: if (nD == 0) break; if (nD == 1) return F31(gel(N,1), gel(N,2), gel(N,3), gel(D,1), z, prec); if (nD == 2) return F32(N, D, z, prec); } pari_err_IMPL("this hypergeometric function"); return NULL; /*LCOV_EXCL_LINE*/ } static GEN serhypergeom(GEN N, GEN D, GEN y, long prec) { GEN Di, Ni, S = gen_1, R = gen_1, y0 = NULL; long v, l, i; pari_sp av; if (!signe(y)) return gadd(gen_1, y); v = valser(y); l = lg(y); if (v < 0) pari_err_DOMAIN("hypergeom","valuation", "<", gen_0, y); if (!v) { y0 = gel(y, 2); if (!is_scalar_t(typ(y0))) pari_err_TYPE("hypergeom",y); y = serchop0(y); l = 3 + (l - 3) / valser(y); S = hypergeom(N, D, y0, prec); } av = avma; Ni = N; Di = D; for (i = 1; i < l; i++) { R = gmul(R, gmul(y, gdiv(vecprod(Ni), gmulsg(i, vecprod(Di))))); /* have to offset by 1 when y0 != NULL; keep Ni,Di to avoid recomputing * in next loop */ Ni = RgV_z_add(N, i); Di = RgV_z_add(D, i); S = gadd(S, y0? gmul(R, hypergeom_i(Ni, Di, y0, prec)): R); if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"hypergeom, i = %ld / %ld", i,l-1); gerepileall(av, 4, &S, &R, &Ni, &Di); } } return S; } GEN hypergeom(GEN N, GEN D, GEN y, long prec) { pari_sp av = avma; GEN z; long j, n; N = hypergeom_arg(N); D = hypergeom_arg(D); n = hypersimplify(&N, &D); for (j = 1; j < lg(D); j++) if (isnegint(gel(D,j))) pari_err_DOMAIN("hypergeom", stack_sprintf("b[%ld]", j + n), "<=", gen_0, gel(D,j)); if (is_scalar_t(typ(y))) return gerepilecopy(av, hypergeom_i(N, D, y, prec)); if (!(z = toser_i(y))) pari_err_TYPE("hypergeom", y); return gerepileupto(av, serhypergeom(N, D, z, prec)); } pari-2.17.2/src/basemath/F3v.c0000644000175000017500000001534714567450071014364 0ustar billbill/* Copyright (C) 2021 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_mat GEN zero_F3v(long m) { long l = nbits2nlong(2*m); GEN v = const_vecsmall(l+1, 0); v[1] = m; return v; } GEN zero_F3m_copy(long m, long n) { long i; GEN M = cgetg(n+1, t_MAT); for (i = 1; i <= n; i++) gel(M,i)= zero_F3v(m); return M; } #define TRITS_IN_LONG (BITS_IN_LONG>>1) #define TRITS_MASK (ULONG_MAX/3UL) #define TWOPOTTRITS_IN_LONG (TWOPOTBITS_IN_LONG-1) ulong F3v_coeff(GEN x,long v) { long pos = (v-1)>>TWOPOTTRITS_IN_LONG; long r = (v-1)&(TRITS_IN_LONG-1); ulong u=(ulong)x[2+pos]; return (u>>(2*r))&3UL; } void F3v_clear(GEN x, long v) { long pos = (v-1)>>TWOPOTTRITS_IN_LONG; long r = (v-1)&(TRITS_IN_LONG-1); ulong *u=(ulong*)&x[2+pos]; *u&=~(3UL<<(2*r)); } void F3v_set(GEN x, long v, ulong n) { long pos = (v-1)>>TWOPOTTRITS_IN_LONG; long r = (v-1)&(TRITS_IN_LONG-1); ulong *u=(ulong*)&x[2+pos]; *u&=~(3UL<<(2*r)); *u|=(n<<(2*r)); } INLINE void F3v_setneg(GEN x, long v) { long pos = (v-1)>>TWOPOTTRITS_IN_LONG; long r = (v-1)&(TRITS_IN_LONG-1); ulong *u=(ulong*)&x[2+pos]; if ((*u>>(2*r))&3UL) *u^=(3UL<<(2*r)); } INLINE void F3m_setneg(GEN x, long a, long b) { F3v_setneg(gel(x,b), a); } static ulong bitswap(ulong a) { const ulong m = TRITS_MASK; return ((a&m)<<1)|((a>>1)&m); } static ulong F3_add(ulong a, ulong b) { ulong c = a^b^bitswap(a&b); return c&~bitswap(c); } static ulong F3_sub(ulong a, ulong b) { ulong bi = bitswap(b); ulong c = a^bi^bitswap(a&bi); return c&~bitswap(c); } /* Allow lg(y)>j)&3UL; return z; } GEN F3c_to_ZC(GEN x) { long l = x[1]+1, i, j, k; GEN z = cgetg(l, t_COL); for (i=2,k=1; i>j)&3UL) { case 0: gel(z,k) = gen_0; break; case 1: gel(z,k) = gen_1; break; default:gel(z,k) = gen_2; break; } return z; } GEN F3c_to_mod(GEN x) { long l = x[1]+1, i, j, k; GEN z = cgetg(l, t_COL), N = utoipos(3); GEN _0 = mkintmod(gen_0, N); GEN _1 = mkintmod(gen_1, N); GEN _2 = mkintmod(gen_2, N); for (i=2,k=1; i>j)&3UL) { case 0: gel(z,k) = _0; break; case 1: gel(z,k) = _1; break; default: gel(z,k)= _2; break; } return z; } GEN F3m_to_ZM(GEN x) { pari_APPLY_same(F3c_to_ZC(gel(x,i))) } GEN F3m_to_mod(GEN x) { pari_APPLY_same(F3c_to_mod(gel(x,i))) } GEN F3m_to_Flm(GEN x) { pari_APPLY_same(F3v_to_Flv(gel(x,i))) } /* in place, destroy x */ GEN F3m_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; d = cgetg(n+1, t_VECSMALL); c = const_F2v(m); for (k=1; k<=n; k++) { GEN xk = gel(x,k); for (j=1; j<=m; j++) if (F2v_coeff(c,j) && F3m_coeff(x,j,k)) break; if (j>m) { if (deplin) { GEN v = zero_F3v(n); for (i=1; i 0? leafcopy(v): RgC_neg(v); } l = lg(v); y = cgetg(l, t_COL); for (i=1; i < l; i++) { GEN c = gel(v,i); if (typ(c) != t_COL) c = gmul(c, x); else c = RgC_Rg_mul(c, x); gel(y,i) = c; } return y; } else { GEN dx; x = zk_multable(nf, Q_remove_denom(x,&dx)); y = nfC_multable_mul(v, x); return dx? RgC_Rg_div(y, dx): y; } } static GEN mulbytab(GEN M, GEN c) { return typ(c) == t_COL? RgM_RgC_mul(M,c): RgC_Rg_mul(gel(M,1), c); } GEN tablemulvec(GEN M, GEN x, GEN v) { long l, i; GEN y; if (typ(x) == t_COL && RgV_isscalar(x)) { x = gel(x,1); return typ(v) == t_POL? RgX_Rg_mul(v,x): RgV_Rg_mul(v,x); } x = multable(M, x); /* multiplication table by x */ y = cgetg_copy(v, &l); if (typ(v) == t_POL) { y[1] = v[1]; for (i=2; i < l; i++) gel(y,i) = mulbytab(x, gel(v,i)); y = normalizepol(y); } else { for (i=1; i < l; i++) gel(y,i) = mulbytab(x, gel(v,i)); } return y; } GEN zkmultable_capZ(GEN mx) { return Q_denom(zkmultable_inv(mx)); } GEN zkmultable_inv(GEN mx) { return ZM_gauss(mx, col_ei(lg(mx)-1,1)); } /* nf a true nf, x a ZC */ GEN zk_inv(GEN nf, GEN x) { return zkmultable_inv(zk_multable(nf,x)); } /* inverse of x in nf */ GEN nfinv(GEN nf, GEN x) { pari_sp av = avma; GEN z; nf = checknf(nf); if (is_famat(x)) return famat_inv(x); x = nf_to_scalar_or_basis(nf, x); if (typ(x) == t_COL) { GEN d; x = Q_remove_denom(x, &d); z = zk_inv(nf, x); if (d) z = RgC_Rg_mul(z, d); } else z = 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 z; nf = checknf(nf); if (is_famat(x) || is_famat(y)) return famat_div(x,y); y = nf_to_scalar_or_basis(nf, y); if (typ(y) != t_COL) { x = nf_to_scalar_or_basis(nf, x); z = (typ(x) == t_COL)? RgC_Rg_div(x, y): gdiv(x,y); } else { GEN d; y = Q_remove_denom(y, &d); z = nfmul(nf, x, zk_inv(nf,y)); if (d) z = typ(z) == t_COL? RgC_Rg_mul(z, d): gmul(z, d); } return gerepileupto(av, z); } /* product of INTEGERS (t_INT or ZC) x and y in (true) nf */ GEN nfmuli(GEN nf, GEN x, GEN y) { if (typ(x) == t_INT) return (typ(y) == t_COL)? ZC_Z_mul(y, x): mulii(x,y); if (typ(y) == t_INT) return ZC_Z_mul(x, y); return nfmuli_ZC(nf, x, y); } GEN nfsqri(GEN nf, GEN x) { return (typ(x) == t_INT)? sqri(x): nfsqri_ZC(nf, x); } /* 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; GEN x, cx; if (typ(n)!=t_INT) pari_err_TYPE("nfpow",n); nf = checknf(nf); s = signe(n); if (!s) return gen_1; if (is_famat(z)) return famat_pow(z, n); x = nf_to_scalar_or_basis(nf, z); if (typ(x) != t_COL) return powgi(x,n); if (s < 0) { /* simplified nfinv */ GEN d; x = Q_remove_denom(x, &d); x = zk_inv(nf, x); x = primitive_part(x, &cx); cx = mul_content(cx, d); n = negi(n); } else x = primitive_part(x, &cx); x = gen_pow_i(x, n, (void*)nf, _sqr, _mul); if (cx) x = gerepileupto(av, gmul(x, powgi(cx, n))); else x = gerepilecopy(av, x); return x; } /* Compute z^n in nf, left-shift binary powering */ GEN nfpow_u(GEN nf, GEN z, ulong n) { pari_sp av = avma; GEN x, cx; if (!n) return gen_1; x = nf_to_scalar_or_basis(nf, z); if (typ(x) != t_COL) return gpowgs(x,n); x = primitive_part(x, &cx); x = gen_powu_i(x, n, (void*)nf, _sqr, _mul); if (cx) { x = gmul(x, powgi(cx, utoipos(n))); return gerepileupto(av,x); } return gerepilecopy(av, x); } long nfissquare(GEN nf, GEN z, GEN *px) { pari_sp av = avma; long v = fetch_var_higher(); GEN R; nf = checknf(nf); if (nf_get_degree(nf) == 1) { z = algtobasis(nf, z); if (!issquareall(gel(z,1), px)) return gc_long(av, 0); if (px) *px = gerepileupto(av, *px); else set_avma(av); return 1; } z = nf_to_scalar_or_alg(nf, z); R = nfroots(nf, deg2pol_shallow(gen_m1, gen_0, z, v)); delete_var(); if (lg(R) == 1) return gc_long(av, 0); if (px) *px = gerepilecopy(av, nf_to_scalar_or_basis(nf, gel(R,1))); else set_avma(av); return 1; } long nfispower(GEN nf, GEN z, long n, GEN *px) { pari_sp av = avma; long v = fetch_var_higher(); GEN R; nf = checknf(nf); if (nf_get_degree(nf) == 1) { z = algtobasis(nf, z); if (!ispower(gel(z,1), stoi(n), px)) return gc_long(av, 0); if (px) *px = gerepileupto(av, *px); else set_avma(av); return 1; } if (n <= 0) pari_err_DOMAIN("nfeltispower","exponent","<=",gen_0,stoi(n)); z = nf_to_scalar_or_alg(nf, z); if (n==1) { if (px) *px = gerepilecopy(av, z); return 1; } R = nfroots(nf, gsub(pol_xn(n, v), z)); delete_var(); if (lg(R) == 1) return gc_long(av, 0); if (px) *px = gerepilecopy(av, nf_to_scalar_or_basis(nf, gel(R,1))); else set_avma(av); return 1; } static GEN idmulred(void *nf, GEN x, GEN y) { return idealmulred((GEN) nf, x, y); } static GEN idpowred(void *nf, GEN x, GEN n) { return idealpowred((GEN) nf, x, n); } static GEN idmul(void *nf, GEN x, GEN y) { return idealmul((GEN) nf, x, y); } static GEN idpow(void *nf, GEN x, GEN n) { return idealpow((GEN) nf, x, n); } GEN idealfactorback(GEN nf, GEN L, GEN e, int red) { nf = checknf(nf); if (red) return gen_factorback(L, e, (void*)nf, &idmulred, &idpowred, NULL); if (!e && typ(L) == t_MAT && lg(L) == 3) { e = gel(L,2); L = gel(L,1); } if (is_vec_t(typ(L)) && RgV_is_prV(L)) { /* don't use gen_factorback since *= pr^v can be done more efficiently */ pari_sp av = avma; long i, l = lg(L); GEN a; if (!e) e = const_vec(l-1, gen_1); else switch(typ(e)) { case t_VECSMALL: e = zv_to_ZV(e); break; case t_VEC: case t_COL: if (!RgV_is_ZV(e)) pari_err_TYPE("factorback [not an exponent vector]", e); break; default: pari_err_TYPE("idealfactorback", e); } if (l != lg(e)) pari_err_TYPE("factorback [not an exponent vector]", e); if (l == 1 || ZV_equal0(e)) return gc_const(av, gen_1); a = idealpow(nf, gel(L,1), gel(e,1)); for (i = 2; i < l; i++) if (signe(gel(e,i))) a = idealmulpowprime(nf, a, gel(L,i), gel(e,i)); return gerepileupto(av, a); } return gen_factorback(L, e, (void*)nf, &idmul, &idpow, NULL); } static GEN eltmul(void *nf, GEN x, GEN y) { return nfmul((GEN) nf, x, y); } static GEN eltpow(void *nf, GEN x, GEN n) { return nfpow((GEN) nf, x, n); } GEN nffactorback(GEN nf, GEN L, GEN e) { return gen_factorback(L, e, (void*)checknf(nf), &eltmul, &eltpow, NULL); } static GEN _nf_red(void *E, GEN x) { (void)E; return gcopy(x); } static GEN _nf_add(void *E, GEN x, GEN y) { return nfadd((GEN)E,x,y); } static GEN _nf_neg(void *E, GEN x) { (void)E; return gneg(x); } static GEN _nf_mul(void *E, GEN x, GEN y) { return nfmul((GEN)E,x,y); } static GEN _nf_inv(void *E, GEN x) { return nfinv((GEN)E,x); } static GEN _nf_s(void *E, long x) { (void)E; return stoi(x); } static const struct bb_field nf_field={_nf_red,_nf_add,_nf_mul,_nf_neg, _nf_inv,&gequal0,_nf_s }; const struct bb_field *get_nf_field(void **E, GEN nf) { *E = (void*)nf; return &nf_field; } GEN nfM_det(GEN nf, GEN M) { void *E; const struct bb_field *S = get_nf_field(&E, nf); return gen_det(M, E, S); } GEN nfM_inv(GEN nf, GEN M) { void *E; const struct bb_field *S = get_nf_field(&E, nf); return gen_Gauss(M, matid(lg(M)-1), E, S); } GEN nfM_ker(GEN nf, GEN M) { void *E; const struct bb_field *S = get_nf_field(&E, nf); return gen_ker(M, 0, E, S); } GEN nfM_mul(GEN nf, GEN A, GEN B) { void *E; const struct bb_field *S = get_nf_field(&E, nf); return gen_matmul(A, B, E, S); } GEN nfM_nfC_mul(GEN nf, GEN A, GEN B) { void *E; const struct bb_field *S = get_nf_field(&E, nf); return gen_matcolmul(A, B, E, S); } /* valuation of integral x (ZV), with resp. to prime ideal pr */ long ZC_nfvalrem(GEN x, GEN pr, GEN *newx) { pari_sp av = avma; long i, v, l; GEN r, y, p = pr_get_p(pr), mul = pr_get_tau(pr); /* p inert */ if (typ(mul) == t_INT) return newx? ZV_pvalrem(x, p, newx):ZV_pval(x, p); y = cgetg_copy(x, &l); /* will hold the new x */ x = leafcopy(x); for(v=0;; v++) { for (i=1; i1) pari_warn(warnmem,"ZC_nfvalrem, v >= %ld", v); gerepileall(av, 2, &x, &y); } } } long ZC_nfval(GEN x, GEN P) { return ZC_nfvalrem(x, P, NULL); } /* v_P(x) != 0, x a ZV. Simpler version of ZC_nfvalrem */ int ZC_prdvd(GEN x, GEN P) { pari_sp av = avma; long i, l; GEN p = pr_get_p(P), mul = pr_get_tau(P); if (typ(mul) == t_INT) return ZV_Z_dvd(x, p); l = lg(x); for (i=1; i n) return 1; /* room for only one such pr */ return ZV_equal(pr_get_gen(P), gQ) || ZC_prdvd(gQ, P); } GEN famat_nfvalrem(GEN nf, GEN x, GEN pr, GEN *py) { pari_sp av = avma; GEN P = gel(x,1), E = gel(x,2), V = gen_0, y = NULL; long l = lg(P), simplify = 0, i; if (py) { *py = gen_1; y = cgetg(l, t_COL); } for (i = 1; i < l; i++) { GEN e = gel(E,i); long v; if (!signe(e)) { if (py) gel(y,i) = gen_1; simplify = 1; continue; } v = nfvalrem(nf, gel(P,i), pr, py? &gel(y,i): NULL); if (v == LONG_MAX) { set_avma(av); if (py) *py = gen_0; return mkoo(); } V = addmulii(V, stoi(v), e); } if (!py) V = gerepileuptoint(av, V); else { y = mkmat2(y, gel(x,2)); if (simplify) y = famat_remove_trivial(y); gerepileall(av, 2, &V, &y); *py = y; } return V; } long nfval(GEN nf, GEN x, GEN pr) { pari_sp av = avma; long w, e; GEN cx, p; if (gequal0(x)) return LONG_MAX; nf = checknf(nf); checkprid(pr); p = pr_get_p(pr); e = pr_get_e(pr); x = nf_to_scalar_or_basis(nf, x); if (typ(x) != t_COL) return e*Q_pval(x,p); x = Q_primitive_part(x, &cx); w = ZC_nfval(x,pr); if (cx) w += e*Q_pval(cx,p); return gc_long(av,w); } /* want to write p^v = uniformizer^(e*v) * z^v, z coprime to pr */ /* z := tau^e / p^(e-1), algebraic integer coprime to pr; return z^v */ static GEN powp(GEN nf, GEN pr, long v) { GEN b, z; long e; if (!v) return gen_1; b = pr_get_tau(pr); if (typ(b) == t_INT) return gen_1; e = pr_get_e(pr); z = gel(b,1); if (e != 1) z = gdiv(nfpow_u(nf, z, e), powiu(pr_get_p(pr),e-1)); if (v < 0) { v = -v; z = nfinv(nf, z); } if (v != 1) z = nfpow_u(nf, z, v); return z; } long nfvalrem(GEN nf, GEN x, GEN pr, GEN *py) { pari_sp av = avma; long w, e; GEN cx, p, t; if (!py) return nfval(nf,x,pr); if (gequal0(x)) { *py = gen_0; return LONG_MAX; } nf = checknf(nf); checkprid(pr); p = pr_get_p(pr); e = pr_get_e(pr); x = nf_to_scalar_or_basis(nf, x); if (typ(x) != t_COL) { w = Q_pvalrem(x,p, py); if (!w) { *py = gerepilecopy(av, x); return 0; } *py = gerepileupto(av, gmul(powp(nf, pr, w), *py)); return e*w; } x = Q_primitive_part(x, &cx); w = ZC_nfvalrem(x,pr, py); if (cx) { long v = Q_pvalrem(cx,p, &t); *py = nfmul(nf, *py, gmul(powp(nf,pr,v), t)); *py = gerepileupto(av, *py); w += e*v; } else *py = gerepilecopy(av, *py); return w; } GEN gpnfvalrem(GEN nf, GEN x, GEN pr, GEN *py) { long v; if (is_famat(x)) return famat_nfvalrem(nf, x, pr, py); v = nfvalrem(nf,x,pr,py); return v == LONG_MAX? mkoo(): stoi(v); } /* true nf */ GEN coltoalg(GEN nf, GEN x) { return mkpolmod( nf_to_scalar_or_alg(nf, x), nf_get_pol(nf) ); } GEN basistoalg(GEN nf, GEN x) { GEN T; nf = checknf(nf); switch(typ(x)) { case t_COL: { pari_sp av = avma; return gerepilecopy(av, coltoalg(nf, x)); } case t_POLMOD: T = nf_get_pol(nf); if (!RgX_equal_var(T,gel(x,1))) pari_err_MODULUS("basistoalg", T,gel(x,1)); return gcopy(x); case t_POL: T = nf_get_pol(nf); if (varn(T) != varn(x)) pari_err_VAR("basistoalg",x,T); retmkpolmod(RgX_rem(x, T), ZX_copy(T)); case t_INT: case t_FRAC: T = nf_get_pol(nf); retmkpolmod(gcopy(x), ZX_copy(T)); default: pari_err_TYPE("basistoalg",x); return NULL; /* LCOV_EXCL_LINE */ } } /* true nf, x a t_POL */ static GEN pol_to_scalar_or_basis(GEN nf, GEN x) { GEN T = nf_get_pol(nf); long l = lg(x); if (varn(x) != varn(T)) pari_err_VAR("nf_to_scalar_or_basis", x,T); if (l >= lg(T)) { x = RgX_rem(x, T); l = lg(x); } if (l == 2) return gen_0; if (l == 3) { x = gel(x,2); if (!is_rational_t(typ(x))) pari_err_TYPE("nf_to_scalar_or_basis",x); return x; } return poltobasis(nf,x); } /* 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"); switch(typ(x)) { case t_INT: case t_FRAC: return x; case t_POL: return pol_to_scalar_or_basis(nf,x); } break; case t_POL: return pol_to_scalar_or_basis(nf,x); case t_COL: if (lg(x)-1 != nf_get_degree(nf)) break; return QV_isscalar(x)? gel(x,1): x; } pari_err_TYPE("nf_to_scalar_or_basis",x); return NULL; /* LCOV_EXCL_LINE */ } /* 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: { GEN dx; if (lg(x)-1 != nf_get_degree(nf)) break; if (QV_isscalar(x)) return gel(x,1); x = Q_remove_denom(x, &dx); x = RgV_RgC_mul(nf_get_zkprimpart(nf), x); dx = mul_denom(dx, nf_get_zkden(nf)); return gdiv(x,dx); } } pari_err_TYPE("nf_to_scalar_or_alg",x); return NULL; /* LCOV_EXCL_LINE */ } /* gmul(A, RgX_to_RgC(x)), A t_MAT of compatible dimensions */ GEN RgM_RgX_mul(GEN A, GEN x) { long i, l = lg(x)-1; GEN z; if (l == 1) return zerocol(nbrows(A)); z = gmul(gel(x,2), gel(A,1)); for (i = 2; i < l; i++) if (!gequal0(gel(x,i+1))) z = gadd(z, gmul(gel(x,i+1), gel(A,i))); return z; } GEN ZM_ZX_mul(GEN A, GEN x) { long i, l = lg(x)-1; GEN z; if (l == 1) return zerocol(nbrows(A)); z = ZC_Z_mul(gel(A,1), gel(x,2)); for (i = 2; i < l ; i++) if (signe(gel(x,i+1))) z = ZC_add(z, ZC_Z_mul(gel(A,i), gel(x,i+1))); return z; } /* x a t_POL, nf a genuine nf. No garbage collecting. No check. */ GEN poltobasis(GEN nf, GEN x) { GEN d, T = nf_get_pol(nf); if (varn(x) != varn(T)) pari_err_VAR( "poltobasis", x,T); if (degpol(x) >= degpol(T)) x = RgX_rem(x,T); x = Q_remove_denom(x, &d); if (!RgX_is_ZX(x)) pari_err_TYPE("poltobasis",x); x = ZM_ZX_mul(nf_get_invzk(nf), x); if (d) x = RgC_Rg_div(x, d); return x; } GEN algtobasis(GEN nf, GEN x) { pari_sp av; nf = checknf(nf); switch(typ(x)) { case t_POLMOD: if (!RgX_equal_var(nf_get_pol(nf),gel(x,1))) pari_err_MODULUS("algtobasis", nf_get_pol(nf),gel(x,1)); x = gel(x,2); switch(typ(x)) { case t_INT: case t_FRAC: return scalarcol(x, nf_get_degree(nf)); case t_POL: av = avma; return gerepileupto(av,poltobasis(nf,x)); } break; case t_POL: av = avma; return gerepileupto(av,poltobasis(nf,x)); case t_COL: if (!RgV_is_QV(x)) pari_err_TYPE("nfalgtobasis",x); if (lg(x)-1 != nf_get_degree(nf)) pari_err_DIM("nfalgtobasis"); return gcopy(x); case t_INT: case t_FRAC: return scalarcol(x, nf_get_degree(nf)); } pari_err_TYPE("algtobasis",x); return NULL; /* LCOV_EXCL_LINE */ } GEN rnfbasistoalg(GEN rnf,GEN x) { const char *f = "rnfbasistoalg"; long lx, i; pari_sp av = avma; GEN z, nf, R, T; checkrnf(rnf); nf = rnf_get_nf(rnf); T = nf_get_pol(nf); R = QXQX_to_mod_shallow(rnf_get_pol(rnf), T); switch(typ(x)) { case t_COL: z = cgetg_copy(x, &lx); for (i=1; i= degpol(T)) x = RgX_rem(x,T); x = mkpolmod(x,T); break; } x = RgX_nffix(f, T, x, 0); if (degpol(x) >= degpol(R)) x = RgX_rem(x, R); return gerepileupto(av, RgM_RgX_mul(rnf_get_invzk(rnf), x)); } return gerepileupto(av, scalarcol(x, rnf_get_degree(rnf))); } /* Given a and b in nf, gives an algebraic integer y in nf such that a-b.y * is "small" */ GEN nfdiveuc(GEN nf, GEN a, GEN b) { pari_sp av = avma; a = nfdiv(nf,a,b); return gerepileupto(av, ground(a)); } /* Given a and b in nf, gives a "small" algebraic integer r in nf * of the form a-b.y */ GEN nfmod(GEN nf, GEN a, GEN b) { pari_sp av = avma; GEN p1 = gneg_i(nfmul(nf,b,ground(nfdiv(nf,a,b)))); return gerepileupto(av, nfadd(nf,a,p1)); } /* Given a and b in nf, gives a two-component vector [y,r] in nf such * that r=a-b.y is "small". */ GEN nfdivrem(GEN nf, GEN a, GEN b) { pari_sp av = avma; GEN p1,z, y = ground(nfdiv(nf,a,b)); p1 = gneg_i(nfmul(nf,b,y)); z = cgetg(3,t_VEC); gel(z,1) = gcopy(y); gel(z,2) = nfadd(nf,a,p1); return gerepileupto(av, z); } /*************************************************************************/ /** **/ /** LOGARITHMIC EMBEDDINGS **/ /** **/ /*************************************************************************/ static int low_prec(GEN x) { switch(typ(x)) { case t_INT: return !signe(x); case t_REAL: return !signe(x) || realprec(x) <= DEFAULTPREC; default: return 0; } } static GEN cxlog_1(GEN nf) { return zerocol(lg(nf_get_roots(nf))-1); } static GEN cxlog_m1(GEN nf, long prec) { long i, l = lg(nf_get_roots(nf)), r1 = nf_get_r1(nf); GEN v = cgetg(l, t_COL), p, P; p = mppi(prec); P = mkcomplex(gen_0, p); for (i = 1; i <= r1; i++) gel(v,i) = P; /* IPi*/ if (i < l) P = gmul2n(P,1); for ( ; i < l; i++) gel(v,i) = P; /* 2IPi */ return v; } static GEN ZC_cxlog(GEN nf, GEN x, long prec) { long i, l, r1; GEN v; x = RgM_RgC_mul(nf_get_M(nf), Q_primpart(x)); l = lg(x); r1 = nf_get_r1(nf); for (i = 1; i <= r1; i++) if (low_prec(gel(x,i))) return NULL; for ( ; i < l; i++) if (low_prec(gnorm(gel(x,i)))) return NULL; v = cgetg(l,t_COL); 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_cxlog(GEN nf, GEN fa, long prec) { GEN G, E, y = NULL; long i, l; if (typ(fa) != t_MAT) pari_err_TYPE("famat_cxlog",fa); if (lg(fa) == 1) return cxlog_1(nf); G = gel(fa,1); E = gel(fa,2); l = lg(E); for (i = 1; i < l; i++) { GEN t, e = gel(E,i), x = nf_to_scalar_or_basis(nf, gel(G,i)); /* multiplicative arch would be better (save logs), but exponents overflow * [ could keep track of expo separately, but not worth it ] */ switch(typ(x)) { /* ignore positive rationals */ case t_FRAC: x = gel(x,1); /* fall through */ case t_INT: if (signe(x) > 0) continue; if (!mpodd(e)) continue; t = cxlog_m1(nf, prec); /* we probably should not reach this line */ break; default: /* t_COL */ t = ZC_cxlog(nf,x,prec); if (!t) return NULL; t = RgC_Rg_mul(t, e); } y = y? RgV_add(y,t): t; } return y ? y: cxlog_1(nf); } /* Archimedean components: [e_i Log( sigma_i(X) )], where X = primpart(x), * and e_i = 1 (resp 2.) for i <= R1 (resp. > R1) */ GEN nf_cxlog(GEN nf, GEN x, long prec) { if (typ(x) == t_MAT) return famat_cxlog(nf,x,prec); x = nf_to_scalar_or_basis(nf,x); switch(typ(x)) { case t_FRAC: x = gel(x,1); /* fall through */ case t_INT: return signe(x) > 0? cxlog_1(nf): cxlog_m1(nf, prec); default: return ZC_cxlog(nf, x, prec); } } GEN nfV_cxlog(GEN nf, GEN x, long prec) { long i, l; GEN v = cgetg_copy(x, &l); for (i = 1; i < l; i++) if (!(gel(v,i) = nf_cxlog(nf, gel(x,i), prec))) return NULL; return v; } static GEN scalar_logembed(GEN nf, GEN u, GEN *emb) { GEN v, logu; long i, s = signe(u), RU = lg(nf_get_roots(nf))-1, R1 = nf_get_r1(nf); if (!s) pari_err_DOMAIN("nflogembed","argument","=",gen_0,u); v = cgetg(RU+1, t_COL); logu = logr_abs(u); for (i = 1; i <= R1; i++) gel(v,i) = logu; if (i <= RU) { GEN logu2 = shiftr(logu,1); for ( ; i <= RU; i++) gel(v,i) = logu2; } if (emb) *emb = const_col(RU, u); return v; } static GEN famat_logembed(GEN nf,GEN x,GEN *emb,long prec) { GEN A, M, T, a, t, g = gel(x,1), e = gel(x,2); long i, l = lg(e); if (l == 1) return scalar_logembed(nf, real_1(prec), emb); A = NULL; T = emb? cgetg(l, t_COL): NULL; if (emb) *emb = M = mkmat2(T, e); for (i = 1; i < l; i++) { a = nflogembed(nf, gel(g,i), &t, prec); if (!a) return NULL; a = RgC_Rg_mul(a, gel(e,i)); A = A? RgC_add(A, a): a; if (emb) gel(T,i) = t; } return A; } /* Get archimedean components: [e_i log( | sigma_i(x) | )], with e_i = 1 * (resp 2.) for i <= R1 (resp. > R1) and set emb to the embeddings of x. * Return NULL if precision problem */ GEN nflogembed(GEN nf, GEN x, GEN *emb, long prec) { long i, l, r1; GEN v, t; if (typ(x) == t_MAT) return famat_logembed(nf,x,emb,prec); x = nf_to_scalar_or_basis(nf,x); if (typ(x) != t_COL) return scalar_logembed(nf, gtofp(x,prec), emb); x = RgM_RgC_mul(nf_get_M(nf), x); l = lg(x); r1 = nf_get_r1(nf); v = cgetg(l,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 < l; i++) { t = gnorm(gel(x,i)); if (low_prec(t)) return NULL; gel(v,i) = glog(t,prec); } if (emb) *emb = x; return v; } /*************************************************************************/ /** **/ /** REAL EMBEDDINGS **/ /** **/ /*************************************************************************/ static GEN sarch_get_cyc(GEN sarch) { return gel(sarch,1); } static GEN sarch_get_archp(GEN sarch) { return gel(sarch,2); } static GEN sarch_get_MI(GEN sarch) { return gel(sarch,3); } static GEN sarch_get_lambda(GEN sarch) { return gel(sarch,4); } static GEN sarch_get_F(GEN sarch) { return gel(sarch,5); } /* true nf, x non-zero algebraic integer; return number of positive real roots * of char_x */ static long num_positive(GEN nf, GEN x) { GEN T = nf_get_pol(nf), B, charx; long dnf, vnf, N, r1 = nf_get_r1(nf); x = nf_to_scalar_or_alg(nf, x); if (typ(x) != t_POL) return (signe(x) < 0)? 0: degpol(T); /* x not a scalar */ if (r1 == 1) { long s = signe(ZX_resultant(T, Q_primpart(x))); return s > 0? 1: 0; } charx = ZXQ_charpoly(x, T, 0); charx = ZX_radical(charx); N = degpol(T) / degpol(charx); /* real places are unramified ? */ if (N == 1 || ZX_sturm(charx) * N == r1) return ZX_sturmpart(charx, mkvec2(gen_0,mkoo())) * N; /* painful case, multiply by random square until primitive */ dnf = nf_get_degree(nf); vnf = varn(T); B = int2n(10); for(;;) { GEN y = RgXQ_sqr(random_FpX(dnf, vnf, B), T); y = RgXQ_mul(x, y, T); charx = ZXQ_charpoly(y, T, 0); if (ZX_is_squarefree(charx)) return ZX_sturmpart(charx, mkvec2(gen_0,mkoo())); } } /* x a QC: return sigma_k(x) where 1 <= k <= r1+r2; correct but inefficient * if x in Q. M = nf_get_M(nf) */ static GEN nfembed_i(GEN M, GEN x, long k) { long i, l = lg(M); GEN z = gel(x,1); for (i = 2; i < l; i++) z = gadd(z, gmul(gcoeff(M,k,i), gel(x,i))); return z; } GEN nfembed(GEN nf, GEN x, long k) { pari_sp av = avma; nf = checknf(nf); x = nf_to_scalar_or_basis(nf,x); if (typ(x) != t_COL) return gerepilecopy(av, x); return gerepileupto(av, nfembed_i(nf_get_M(nf),x,k)); } /* x a ZC */ static GEN zk_embed(GEN M, GEN x, long k) { long i, l = lg(x); GEN z = gel(x,1); /* times M[k,1], which is 1 */ for (i = 2; i < l; i++) z = mpadd(z, mpmul(gcoeff(M,k,i), gel(x,i))); return z; } /* check that signs[i..#signs] == s; signs = NULL encodes "totally positive" */ static int oksigns(long l, GEN signs, long i, long s) { if (!signs) return s == 0; for (; i < l; i++) if (signs[i] != s) return 0; return 1; } /* true nf, x a ZC (primitive for efficiency) which is not a scalar */ static int nfchecksigns_i(GEN nf, GEN x, GEN signs, GEN archp) { long i, np, npc, l = lg(archp), r1 = nf_get_r1(nf); GEN sarch; if (r1 == 0) return 1; np = num_positive(nf, x); if (np == 0) return oksigns(l, signs, 1, 1); if (np == r1) return oksigns(l, signs, 1, 0); sarch = nfarchstar(nf, NULL, identity_perm(r1)); for (i = 1, npc = 0; i < l; i++) { GEN xi = set_sign_mod_divisor(nf, vecsmall_ei(r1, archp[i]), gen_1, sarch); long ni, s; xi = Q_primpart(xi); ni = num_positive(nf, nfmuli(nf,x,xi)); s = ni < np? 0: 1; if (s != (signs? signs[i]: 0)) return 0; if (!s) npc++; /* found a positive root */ if (npc == np) { /* found all positive roots */ if (!signs) return i == l-1; for (i++; i < l; i++) if (signs[i] != 1) return 0; return 1; } if (i - npc == r1 - np) { /* found all negative roots */ if (!signs) return 1; for (i++; i < l; i++) if (signs[i]) return 0; return 1; } } return 1; } static void pl_convert(GEN pl, GEN *psigns, GEN *parchp) { long i, j, l = lg(pl); GEN signs = cgetg(l, t_VECSMALL); GEN archp = cgetg(l, t_VECSMALL); for (i = j = 1; i < l; i++) { if (!pl[i]) continue; archp[j] = i; signs[j] = (pl[i] < 0)? 1: 0; j++; } setlg(archp, j); *parchp = archp; setlg(signs, j); *psigns = signs; } /* pl : requested signs for real embeddings, 0 = no sign constraint */ int nfchecksigns(GEN nf, GEN x, GEN pl) { pari_sp av = avma; GEN signs, archp; nf = checknf(nf); x = nf_to_scalar_or_basis(nf,x); if (typ(x) != t_COL) { long i, l = lg(pl), s = gsigne(x); for (i = 1; i < l; i++) if (pl[i] && pl[i] != s) return gc_bool(av,0); return gc_bool(av,1); } pl_convert(pl, &signs, &archp); return gc_bool(av, nfchecksigns_i(nf, x, signs, archp)); } /* signs = NULL: totally positive, else sign[i] = 0 (+) or 1 (-) */ static GEN get_C(GEN lambda, long l, GEN signs) { long i; GEN C, mlambda; if (!signs) return const_vec(l-1, lambda); C = cgetg(l, t_COL); mlambda = gneg(lambda); for (i = 1; i < l; i++) gel(C,i) = signs[i]? mlambda: lambda; return C; } /* signs = NULL: totally positive at archp. * Assume that a t_COL x is not a scalar */ static GEN nfsetsigns(GEN nf, GEN signs, GEN x, GEN sarch) { long i, l = lg(sarch_get_archp(sarch)); GEN ex = NULL; /* Is signature already correct ? */ if (typ(x) != t_COL) { long s = gsigne(x); if (!s) i = 1; else if (!signs) i = (s < 0)? 1: l; else { s = s < 0? 1: 0; for (i = 1; i < l; i++) if (signs[i] != s) break; } if (i < l) ex = const_col(l-1, x); } else { /* inefficient if x scalar, wrong if x = 0 */ pari_sp av = avma; GEN cex, M = nf_get_M(nf), archp = sarch_get_archp(sarch); GEN xp = Q_primitive_part(x,&cex); if (nfchecksigns_i(nf, xp, signs, archp)) set_avma(av); else { ex = cgetg(l,t_COL); for (i = 1; i < l; i++) gel(ex,i) = zk_embed(M,xp,archp[i]); if (cex) ex = RgC_Rg_mul(ex, cex); /* put back content */ } } if (ex) { /* If no, fix it */ GEN MI = sarch_get_MI(sarch), F = sarch_get_F(sarch); GEN lambda = sarch_get_lambda(sarch); GEN t = RgC_sub(get_C(lambda, l, signs), ex); t = grndtoi(RgM_RgC_mul(MI,t), NULL); if (lg(F) != 1) t = ZM_ZC_mul(F, t); x = typ(x) == t_COL? RgC_add(t, x): RgC_Rg_add(t, x); } return x; } /* - true nf * - sarch = nfarchstar(nf, F); * - x encodes a vector of signs at arch.archp: either a t_VECSMALL * (vector of signs as {0,1}-vector), NULL (totally positive at archp), * or a nonzero number field element (replaced by its signature at archp); * - y is a nonzero number field element * Return z = y (mod F) with signs(y, archp) = signs(x) (a {0,1}-vector). * Not stack-clean */ GEN set_sign_mod_divisor(GEN nf, GEN x, GEN y, GEN sarch) { GEN archp = sarch_get_archp(sarch); if (lg(archp) == 1) return y; if (x && typ(x) != t_VECSMALL) x = nfsign_arch(nf, x, archp); return nfsetsigns(nf, x, nf_to_scalar_or_basis(nf,y), sarch); } static GEN setsigns_init(GEN nf, GEN archp, GEN F, GEN DATA) { GEN lambda, Mr = rowpermute(nf_get_M(nf), archp), MI = F? RgM_mul(Mr,F): Mr; lambda = gmul2n(matrixnorm(MI,DEFAULTPREC), -1); if (typ(lambda) != t_REAL) lambda = gmul(lambda, uutoQ(1001,1000)); if (lg(archp) < lg(MI)) { GEN perm = gel(indexrank(MI), 2); if (!F) F = matid(nf_get_degree(nf)); MI = vecpermute(MI, perm); F = vecpermute(F, perm); } if (!F) F = cgetg(1,t_MAT); MI = RgM_inv(MI); return mkvec5(DATA, archp, MI, lambda, F); } /* F nonzero integral ideal in HNF (or NULL: Z_K), compute elements in 1+F * whose sign matrix at archp is identity; archp in 'indices' format */ GEN nfarchstar(GEN nf, GEN F, GEN archp) { long nba = lg(archp) - 1; if (!nba) return mkvec2(cgetg(1,t_VEC), archp); if (F && equali1(gcoeff(F,1,1))) F = NULL; if (F) F = idealpseudored(F, nf_get_roundG(nf)); return setsigns_init(nf, archp, F, const_vec(nba, gen_2)); } /*************************************************************************/ /** **/ /** IDEALCHINESE **/ /** **/ /*************************************************************************/ static int isprfact(GEN x) { long i, l; GEN L, E; if (typ(x) != t_MAT || lg(x) != 3) return 0; L = gel(x,1); l = lg(L); E = gel(x,2); for(i=1; i= 0) gel(E,i) = addiu(gel(E,i), v); else if (v + e <= 0) F = idealmulpowprime(nf, F, pr, stoi(-v)); /* coprime to pr */ else { F = idealmulpowprime(nf, F, pr, stoi(e)); gel(E,i) = stoi(v + e); } } } U = cgetg(r, t_VEC); for (i = 1; i < r; i++) { GEN u; if (w && gequal0(gel(w,i))) u = gen_0; /* unused */ else { GEN pr = gel(L,i), e = gel(E,i), t; t = idealdivpowprime(nf,F, pr, e); u = hnfmerge_get_1(t, idealpow(nf, pr, e)); if (!u) pari_err_COPRIME("idealchinese", t,pr); } gel(U,i) = u; } FZ = gcoeff(F, 1, 1); F = idealpseudored(F, nf_get_roundG(nf)); return mkvec2(mkvec2(F, FZ), U); } static GEN pl_normalize(GEN nf, GEN pl) { const char *fun = "idealchinese"; if (lg(pl)-1 != nf_get_r1(nf)) pari_err_TYPE(fun,pl); switch(typ(pl)) { case t_VEC: RgV_check_ZV(pl,fun); pl = ZV_to_zv(pl); /* fall through */ case t_VECSMALL: break; default: pari_err_TYPE(fun,pl); } return pl; } static int is_chineseinit(GEN x) { GEN fa, pl; long l; if (typ(x) != t_VEC || lg(x)!=3) return 0; fa = gel(x,1); pl = gel(x,2); if (typ(fa) != t_VEC || typ(pl) != t_VEC) return 0; l = lg(fa); if (l != 1) { GEN z; if (l != 3) return 0; z = gel(fa, 1); if (typ(z) != t_VEC || lg(z) != 3 || typ(gel(z,1)) != t_MAT || typ(gel(z,2)) != t_INT || typ(gel(fa,2)) != t_VEC) return 0; } l = lg(pl); if (l != 1) { if (l != 6 || typ(gel(pl,3)) != t_MAT || typ(gel(pl,1)) != t_VECSMALL || typ(gel(pl,2)) != t_VECSMALL) return 0; } return 1; } /* nf a true 'nf' */ static GEN chineseinit_i(GEN nf, GEN fa, GEN w, GEN dw) { const char *fun = "idealchineseinit"; GEN archp = NULL, pl = NULL; switch(typ(fa)) { case t_VEC: if (is_chineseinit(fa)) { if (dw) pari_err_DOMAIN(fun, "denom(y)", "!=", gen_1, w); return fa; } if (lg(fa) != 3) pari_err_TYPE(fun, fa); /* of the form [x,s] */ pl = pl_normalize(nf, gel(fa,2)); fa = gel(fa,1); archp = vecsmall01_to_indices(pl); /* keep pr_init, reset pl */ if (is_chineseinit(fa)) { fa = gel(fa,1); break; } /* fall through */ case t_MAT: /* factorization? */ if (isprfact(fa)) { fa = pr_init(nf, fa, w, dw); break; } default: pari_err_TYPE(fun,fa); } if (!pl) pl = cgetg(1,t_VEC); else { long r = lg(archp); if (r == 1) pl = cgetg(1, t_VEC); else { GEN F = (lg(fa) == 1)? NULL: gmael(fa,1,1), signs = cgetg(r, t_VECSMALL); long i; for (i = 1; i < r; i++) signs[i] = (pl[archp[i]] < 0)? 1: 0; pl = setsigns_init(nf, archp, F, signs); } } return mkvec2(fa, pl); } /* Given a prime ideal factorization x, possibly with 0 or negative exponents, * and a vector w of elements of nf, gives b such that * v_p(b-w_p)>=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. */ GEN idealchinese(GEN nf, GEN x0, GEN w) { const char *fun = "idealchinese"; pari_sp av = avma; GEN x = x0, x1, x2, s, dw, F; nf = checknf(nf); if (!w) return gerepilecopy(av, chineseinit_i(nf,x,NULL,NULL)); if (typ(w) != t_VEC) pari_err_TYPE(fun,w); w = Q_remove_denom(matalgtobasis(nf,w), &dw); if (!is_chineseinit(x)) x = chineseinit_i(nf,x,w,dw); /* x is a 'chineseinit' */ x1 = gel(x,1); s = NULL; x2 = gel(x,2); if (lg(x1) == 1) { F = NULL; dw = NULL; } else { GEN U = gel(x1,2), FZ; long i, r = lg(w); F = gmael(x1,1,1); FZ = gmael(x1,1,2); for (i=1; i", utoi(r1), utoi(i)); } static GEN parse_embed(GEN ind, long r, const char *f) { long l, i; if (!ind) return identity_perm(r); switch(typ(ind)) { case t_INT: ind = mkvecsmall(itos(ind)); break; case t_VEC: case t_COL: ind = vec_to_vecsmall(ind); break; case t_VECSMALL: break; default: pari_err_TYPE(f, ind); } l = lg(ind); for (i = 1; i < l; i++) chk_ind(f, ind[i], r); return ind; } GEN nfeltsign(GEN nf, GEN x, GEN ind0) { pari_sp av = avma; long i, l; GEN v, ind; nf = checknf(nf); ind = parse_embed(ind0, nf_get_r1(nf), "nfeltsign"); l = lg(ind); if (is_rational_t(typ(x))) { /* nfsign_arch would test this, but avoid converting t_VECSMALL -> t_VEC */ GEN s; switch(gsigne(x)) { case -1:s = gen_m1; break; case 1: s = gen_1; break; default: s = gen_0; break; } set_avma(av); return (ind0 && typ(ind0) == t_INT)? s: const_vec(l-1, s); } v = nfsign_arch(nf, x, ind); if (ind0 && typ(ind0) == t_INT) { set_avma(av); return v[1]? gen_m1: gen_1; } settyp(v, t_VEC); for (i = 1; i < l; i++) gel(v,i) = v[i]? gen_m1: gen_1; return gerepileupto(av, v); } /* true nf */ GEN nfeltembed_i(GEN *pnf, GEN x, GEN ind0, long prec0) { long i, e, l, r1, r2, prec, prec1; GEN v, ind, cx, nf = *pnf; nf_get_sign(nf,&r1,&r2); x = nf_to_scalar_or_basis(nf, x); ind = parse_embed(ind0, r1+r2, "nfeltembed"); l = lg(ind); if (typ(x) != t_COL) { if (!(ind0 && typ(ind0) == t_INT)) x = const_vec(l-1, x); return x; } x = Q_primitive_part(x, &cx); prec1 = prec0; e = gexpo(x); if (e > 8) prec1 += nbits2extraprec(e); prec = prec1; if (nf_get_prec(nf) < prec) nf = nfnewprec_shallow(nf, prec); v = cgetg(l, t_VEC); for(;;) { GEN M = nf_get_M(nf); for (i = 1; i < l; i++) { GEN t = nfembed_i(M, x, ind[i]); long e = gexpo(t); if (gequal0(t) || precision(t) < prec0 || (e < 0 && prec < prec1 + nbits2extraprec(-e)) ) break; if (cx) t = gmul(t, cx); gel(v,i) = t; } if (i == l) break; prec = precdbl(prec); if (DEBUGLEVEL>1) pari_warn(warnprec,"eltnfembed", prec); *pnf = nf = nfnewprec_shallow(nf, prec); } if (ind0 && typ(ind0) == t_INT) v = gel(v,1); return v; } GEN nfeltembed(GEN nf, GEN x, GEN ind0, long prec0) { pari_sp av = avma; nf = checknf(nf); return gerepilecopy(av, nfeltembed_i(&nf, x, ind0, prec0)); } /* number of distinct roots of sigma(f) */ GEN nfpolsturm(GEN nf, GEN f, GEN ind0) { pari_sp av = avma; long d, l, r1, single; GEN ind, u, v, vr1, T, s, t; nf = checknf(nf); T = nf_get_pol(nf); r1 = nf_get_r1(nf); ind = parse_embed(ind0, r1, "nfpolsturm"); single = ind0 && typ(ind0) == t_INT; l = lg(ind); if (gequal0(f)) pari_err_ROOTS0("nfpolsturm"); if (typ(f) == t_POL && varn(f) != varn(T)) { f = RgX_nffix("nfpolsturm", T, f,1); if (lg(f) == 3) f = NULL; } else { (void)Rg_nffix("nfpolsturm", T, f, 0); f = NULL; } if (!f) { set_avma(av); return single? gen_0: zerovec(l-1); } d = degpol(f); if (d == 1) { set_avma(av); return single? gen_1: const_vec(l-1,gen_1); } vr1 = const_vecsmall(l-1, 1); u = Q_primpart(f); s = ZV_to_zv(nfeltsign(nf, gel(u,d+2), ind)); v = RgX_deriv(u); t = odd(d)? leafcopy(s): zv_neg(s); for(;;) { GEN r = RgX_neg( Q_primpart(RgX_pseudorem(u, v)) ), sr; long i, dr = degpol(r); if (dr < 0) break; sr = ZV_to_zv(nfeltsign(nf, gel(r,dr+2), ind)); for (i = 1; i < l; i++) if (sr[i] != s[i]) { s[i] = sr[i], vr1[i]--; } if (odd(dr)) sr = zv_neg(sr); for (i = 1; i < l; i++) if (sr[i] != t[i]) { t[i] = sr[i], vr1[i]++; } if (!dr) break; u = v; v = r; } if (single) return gc_stoi(av,vr1[1]); return gerepileupto(av, zv_to_ZV(vr1)); } /* True nf; return the vector of signs of x; the matrix of such if x is a vector * of nf elements */ GEN nfsign(GEN nf, GEN x) { long i, l; GEN archp, S; archp = identity_perm( nf_get_r1(nf) ); if (typ(x) != t_VEC) return nfsign_arch(nf, x, archp); l = lg(x); S = cgetg(l, t_MAT); for (i=1; i 0? zk_modHNF(x, A): x); for(y = NULL;;) { if (mpodd(k)) y = nfmulmodideal(nf,y,x,A); k = shifti(k,-1); if (!signe(k)) break; x = nfsqrmodideal(nf,x,A); } return gerepileupto(av, y); } /* a * g^n mod id */ static GEN nfmulpowmodideal(GEN nf, GEN a, GEN g, GEN n, GEN id) { return nfmulmodideal(nf, a, nfpowmodideal(nf,g,n,id), id); } /* assume (num(g[i]), id) = 1 for all i. Return prod g[i]^e[i] mod id. * EX = multiple of exponent of (O_K/id)^* */ GEN famat_to_nf_modideal_coprime(GEN nf, GEN g, GEN e, GEN id, GEN EX) { GEN EXo2, plus = NULL, minus = NULL, idZ = gcoeff(id,1,1); long i, lx = lg(g); if (equali1(idZ)) return gen_1; /* id = Z_K */ EXo2 = (expi(EX) > 10)? shifti(EX,-1): NULL; for (i = 1; i < lx; i++) { GEN h, n = centermodii(gel(e,i), EX, EXo2); long sn = signe(n); if (!sn) continue; h = nf_to_scalar_or_basis(nf, gel(g,i)); switch(typ(h)) { case t_INT: break; case t_FRAC: h = Fp_div(gel(h,1), gel(h,2), idZ); break; default: { GEN dh; h = Q_remove_denom(h, &dh); if (dh) h = FpC_Fp_mul(h, Fp_inv(dh,idZ), idZ); } } if (sn > 0) plus = nfmulpowmodideal(nf, plus, h, n, id); else /* sn < 0 */ minus = nfmulpowmodideal(nf, minus, h, negi(n), id); } if (minus) plus = nfmulmodideal(nf, plus, nfinvmodideal(nf,minus,id), id); return plus? plus: gen_1; } /* given 2 integral ideals x, y in HNF s.t x | y | x^2, compute (1+x)/(1+y) in * the form [[cyc],[gen], U], where U := ux^-1 as a pair [ZM, denom(U)] */ static GEN zidealij(GEN x, GEN y) { GEN U, G, cyc, xp = gcoeff(x,1,1), xi = hnf_invscale(x, xp); long j, N; /* x^(-1) y = relations between the 1 + x_i (HNF) */ cyc = ZM_snf_group(ZM_Z_divexact(ZM_mul(xi, y), xp), &U, &G); N = lg(cyc); G = ZM_mul(x,G); settyp(G, t_VEC); /* new generators */ for (j=1; j 1, x + 1; shallow */ static GEN ZC_add1(GEN x) { long i, l = lg(x); GEN y = cgetg(l, t_COL); for (i = 2; i < l; i++) gel(y,i) = gel(x,i); gel(y,1) = addiu(gel(x,1), 1); return y; } /* lg(x) > 1, x - 1; shallow */ static GEN ZC_sub1(GEN x) { long i, l = lg(x); GEN y = cgetg(l, t_COL); for (i = 2; i < l; i++) gel(y,i) = gel(x,i); gel(y,1) = subiu(gel(x,1), 1); return y; } /* x,y are t_INT or ZC */ static GEN zkadd(GEN x, GEN y) { long tx = typ(x); if (tx == typ(y)) return tx == t_INT? addii(x,y): ZC_add(x,y); else return tx == t_INT? ZC_Z_add(y,x): ZC_Z_add(x,y); } /* x a t_INT or ZC, x+1; shallow */ static GEN zkadd1(GEN x) { long tx = typ(x); return tx == t_INT? addiu(x,1): ZC_add1(x); } /* x a t_INT or ZC, x-1; shallow */ static GEN zksub1(GEN x) { long tx = typ(x); return tx == t_INT? subiu(x,1): ZC_sub1(x); } /* x,y are t_INT or ZC; x - y */ static GEN zksub(GEN x, GEN y) { long tx = typ(x), ty = typ(y); if (tx == ty) return tx == t_INT? subii(x,y): ZC_sub(x,y); else return tx == t_INT? Z_ZC_sub(x,y): ZC_Z_sub(x,y); } /* x is t_INT or ZM (mult. map), y is t_INT or ZC; x * y */ static GEN zkmul(GEN x, GEN y) { long tx = typ(x), ty = typ(y); if (ty == t_INT) return tx == t_INT? mulii(x,y): ZC_Z_mul(gel(x,1),y); else return tx == t_INT? ZC_Z_mul(y,x): ZM_ZC_mul(x,y); } /* (U,V) = 1 coprime ideals. Want z = x mod U, = y mod V; namely * z =vx + uy = v(x-y) + y, where u + v = 1, u in U, v in V. * zkc = [v, UV], v a t_INT or ZM (mult. by v map), UV a ZM (ideal in HNF); * shallow */ GEN zkchinese(GEN zkc, GEN x, GEN y) { GEN v = gel(zkc,1), UV = gel(zkc,2), z = zkadd(zkmul(v, zksub(x,y)), y); return zk_modHNF(z, UV); } /* special case z = x mod U, = 1 mod V; shallow */ GEN zkchinese1(GEN zkc, GEN x) { GEN v = gel(zkc,1), UV = gel(zkc,2), z = zkadd1(zkmul(v, zksub1(x))); return (typ(z) == t_INT)? z: ZC_hnfrem(z, UV); } static GEN zkVchinese1(GEN zkc, GEN v) { long i, ly; GEN y = cgetg_copy(v, &ly); for (i=1; i 5) { GEN b = (typ(v) == t_COL)? v: scalarcol_shallow(v, nf_get_degree(nf)); b= ZC_reducemodlll(b, AB); if (gexpo(b) < e) v = b; } return mkvec2(zk_scalar_or_multable(nf,v), AB); } /* prepare to solve z = x (mod A), z = 1 mod (B) * and then z = 1 (mod A), z = y mod (B) [zkchinese1 twice] */ static GEN zkchinese1init2(GEN nf, GEN A, GEN B, GEN AB) { GEN zkc = zkchineseinit(nf, A, B, AB); GEN mv = gel(zkc,1), mu; if (typ(mv) == t_INT) return mkvec2(zkc, mkvec2(subui(1,mv),AB)); mu = RgM_Rg_add_shallow(ZM_neg(mv), gen_1); return mkvec2(mkvec2(mv,AB), mkvec2(mu,AB)); } static GEN apply_U(GEN L, GEN a) { GEN e, U = gel(L,3), dU = gel(L,4); if (typ(a) == t_INT) e = ZC_Z_mul(gel(U,1), subiu(a, 1)); else { /* t_COL */ GEN t = shallowcopy(a); gel(t,1) = subiu(gel(t,1), 1); /* t = a - 1 */ e = ZM_ZC_mul(U, t); } return gdiv(e, dU); } /* true nf; vectors of [[cyc],[g],U.X^-1]. Assume k > 1. */ static GEN principal_units(GEN nf, GEN pr, long k, GEN prk) { GEN list, prb; ulong mask = quadratic_prec_mask(k); long a = 1; prb = pr_hnf(nf,pr); list = vectrunc_init(k); while (mask > 1) { GEN pra = prb; long b = a << 1; if (mask & 1) b--; mask >>= 1; /* compute 1 + pr^a / 1 + pr^b, 2a <= b */ prb = (b >= k)? prk: idealpows(nf,pr,b); vectrunc_append(list, zidealij(pra, prb)); a = b; } return list; } /* a = 1 mod (pr) return log(a) on local-gens of 1+pr/1+pr^k */ static GEN log_prk1(GEN nf, GEN a, long nh, GEN L2, GEN prk) { GEN y = cgetg(nh+1, t_COL); long j, iy, c = lg(L2)-1; for (j = iy = 1; j <= c; j++) { GEN L = gel(L2,j), cyc = gel(L,1), gen = gel(L,2), E = apply_U(L,a); long i, nc = lg(cyc)-1; int last = (j == c); for (i = 1; i <= nc; i++, iy++) { GEN t, e = gel(E,i); if (typ(e) != t_INT) pari_err_COPRIME("zlog_prk1", a, prk); t = Fp_neg(e, gel(cyc,i)); gel(y,iy) = negi(t); if (!last && signe(t)) a = nfmulpowmodideal(nf, a, gel(gen,i), t, prk); } } return y; } /* true nf */ static GEN principal_units_relations(GEN nf, GEN L2, GEN prk, long nh) { GEN h = cgetg(nh+1,t_MAT); long ih, j, c = lg(L2)-1; for (j = ih = 1; j <= c; j++) { GEN L = gel(L2,j), F = gel(L,1), G = gel(L,2); long k, lG = lg(G); for (k = 1; k < lG; k++,ih++) { /* log(g^f) mod pr^e */ GEN a = nfpowmodideal(nf,gel(G,k),gel(F,k),prk); gel(h,ih) = ZC_neg(log_prk1(nf, a, nh, L2, prk)); gcoeff(h,ih,ih) = gel(F,k); } } return h; } /* true nf; k > 1; multiplicative group (1 + pr) / (1 + pr^k) */ static GEN idealprincipalunits_i(GEN nf, GEN pr, long k, GEN *pU) { GEN cyc, gen, L2, prk = idealpows(nf, pr, k); L2 = principal_units(nf, pr, k, prk); if (k == 2) { GEN L = gel(L2,1); cyc = gel(L,1); gen = gel(L,2); if (pU) *pU = matid(lg(gen)-1); } else { long c = lg(L2), j; GEN EX, h, Ui, vg = cgetg(c, t_VEC); for (j = 1; j < c; j++) gel(vg, j) = gmael(L2,j,2); vg = shallowconcat1(vg); h = principal_units_relations(nf, L2, prk, lg(vg)-1); h = ZM_hnfall_i(h, NULL, 0); cyc = ZM_snf_group(h, pU, &Ui); c = lg(Ui); gen = cgetg(c, t_VEC); EX = cyc_get_expo(cyc); for (j = 1; j < c; j++) gel(gen,j) = famat_to_nf_modideal_coprime(nf, vg, gel(Ui,j), prk, EX); } return mkvec4(cyc, gen, prk, L2); } GEN idealprincipalunits(GEN nf, GEN pr, long k) { pari_sp av; GEN v; nf = checknf(nf); if (k == 1) { checkprid(pr); retmkvec3(gen_1,cgetg(1,t_VEC),cgetg(1,t_VEC)); } av = avma; v = idealprincipalunits_i(nf, pr, k, NULL); return gerepilecopy(av, mkvec3(powiu(pr_norm(pr), k-1), gel(v,1), gel(v,2))); } /* true nf; given an ideal pr^k dividing an integral ideal x (in HNF form) * compute an 'sprk', the structure of G = (Z_K/pr^k)^* [ x = NULL for x=pr^k ] * Return a vector with at least 4 components [cyc],[gen],[HNF pr^k,pr,k],ff, * where * cyc : type of G as abelian group (SNF) * gen : generators of G, coprime to x * pr^k: in HNF * ff : data for log_g in (Z_K/pr)^* * Two extra components are present iff k > 1: L2, U * L2 : list of data structures to compute local DL in (Z_K/pr)^*, * and 1 + pr^a/ 1 + pr^b for various a < b <= min(2a, k) * U : base change matrices to convert a vector of local DL to DL wrt gen * If MOD is not NULL, initialize G / G^MOD instead */ static GEN sprkinit(GEN nf, GEN pr, long k, GEN x, GEN MOD) { GEN T, p, Ld, modpr, cyc, gen, g, g0, A, prk, U, L2, ord0 = NULL; long f = pr_get_f(pr); if(DEBUGLEVEL>3) err_printf("treating pr^%ld, pr = %Ps\n",k,pr); modpr = nf_to_Fq_init(nf, &pr,&T,&p); if (MOD) { GEN o = subiu(powiu(p,f), 1), d = gcdii(o, MOD), fa = Z_factor(d); ord0 = mkvec2(o, fa); /* true order, factorization of order in G/G^MOD */ Ld = gel(fa,1); if (lg(Ld) > 1 && equaliu(gel(Ld,1),2)) Ld = vecslice(Ld,2,lg(Ld)-1); } /* (Z_K / pr)^* */ if (f == 1) { g0 = g = MOD? pgener_Fp_local(p, Ld): pgener_Fp(p); if (!ord0) ord0 = get_arith_ZZM(subiu(p,1)); } else { g0 = g = MOD? gener_FpXQ_local(T, p, Ld): gener_FpXQ(T,p, &ord0); g = Fq_to_nf(g, modpr); if (typ(g) == t_POL) g = poltobasis(nf, g); } A = gel(ord0, 1); /* Norm(pr)-1 */ /* If MOD != NULL, d = gcd(A, MOD): g^(A/d) has order d */ if (k == 1) { cyc = mkvec(A); gen = mkvec(g); prk = pr_hnf(nf,pr); L2 = U = NULL; } else { /* local-gens of (1 + pr)/(1 + pr^k) = SNF-gens * U */ GEN AB, B, u, v, w; long j, l; w = idealprincipalunits_i(nf, pr, k, &U); /* incorporate (Z_K/pr)^*, order A coprime to B = expo(1+pr/1+pr^k)*/ cyc = leafcopy(gel(w,1)); B = cyc_get_expo(cyc); AB = mulii(A,B); gen = leafcopy(gel(w,2)); prk = gel(w,3); g = nfpowmodideal(nf, g, B, prk); g0 = Fq_pow(g0, modii(B,A), T, p); /* update primitive root */ L2 = mkvec3(A, g, gel(w,4)); gel(cyc,1) = AB; gel(gen,1) = nfmulmodideal(nf, gel(gen,1), g, prk); u = mulii(Fp_inv(A,B), A); v = subui(1, u); l = lg(U); for (j = 1; j < l; j++) gcoeff(U,1,j) = Fp_mul(u, gcoeff(U,1,j), AB); U = mkvec2(Rg_col_ei(v, lg(gen)-1, 1), U); } /* local-gens of (Z_K/pr^k)^* = SNF-gens * U */ if (x) { GEN uv = zkchineseinit(nf, idealmulpowprime(nf,x,pr,utoineg(k)), prk, x); gen = zkVchinese1(uv, gen); } return mkvecn(U? 6: 4, cyc, gen, prk, mkvec3(modpr,g0,ord0), L2, U); } GEN sprk_get_cyc(GEN s) { return gel(s,1); } GEN sprk_get_expo(GEN s) { return cyc_get_expo(sprk_get_cyc(s)); } GEN sprk_get_gen(GEN s) { return gel(s,2); } GEN sprk_get_prk(GEN s) { return gel(s,3); } GEN sprk_get_ff(GEN s) { return gel(s,4); } GEN sprk_get_pr(GEN s) { GEN ff = gel(s,4); return modpr_get_pr(gel(ff,1)); } /* L2 to 1 + pr / 1 + pr^k */ static GEN sprk_get_L2(GEN s) { return gmael(s,5,3); } /* lift to nf of primitive root of k(pr) */ static GEN sprk_get_gnf(GEN s) { return gmael(s,5,2); } /* A = Npr-1, = (Z_K/pr)^*, L2 to 1 + pr / 1 + pr^k */ void sprk_get_AgL2(GEN s, GEN *A, GEN *g, GEN *L2) { GEN v = gel(s,5); *A = gel(v,1); *g = gel(v,2); *L2 = gel(v,3); } void sprk_get_U2(GEN s, GEN *U1, GEN *U2) { GEN v = gel(s,6); *U1 = gel(v,1); *U2 = gel(v,2); } static int sprk_is_prime(GEN s) { return lg(s) == 5; } GEN famat_zlog_pr(GEN nf, GEN g, GEN e, GEN sprk, GEN mod) { GEN x, expo = sprk_get_expo(sprk); if (mod) expo = gcdii(expo,mod); x = famat_makecoprime(nf, g, e, sprk_get_pr(sprk), sprk_get_prk(sprk), expo); return log_prk(nf, x, sprk, mod); } /* famat_zlog_pr assuming (g,sprk.pr) = 1 */ static GEN famat_zlog_pr_coprime(GEN nf, GEN g, GEN e, GEN sprk, GEN MOD) { GEN x = famat_to_nf_modideal_coprime(nf, g, e, sprk_get_prk(sprk), sprk_get_expo(sprk)); return log_prk(nf, x, sprk, MOD); } /* o t_INT, O = [ord,fa] format for multiple of o (for Fq_log); * return o in [ord,fa] format */ static GEN order_update(GEN o, GEN O) { GEN p = gmael(O,2,1), z = o, P, E; long i, j, l = lg(p); P = cgetg(l, t_COL); E = cgetg(l, t_COL); for (i = j = 1; i < l; i++) { long v = Z_pvalrem(z, gel(p,i), &z); if (v) { gel(P,j) = gel(p,i); gel(E,j) = utoipos(v); j++; if (is_pm1(z)) break; } } setlg(P, j); setlg(E, j); return mkvec2(o, mkmat2(P,E)); } /* a in Z_K (t_COL or t_INT), pr prime ideal, sprk = sprkinit(nf,pr,k,x), * mod positive t_INT or NULL (meaning mod=0). * return log(a) modulo mod on SNF-generators of (Z_K/pr^k)^* */ GEN log_prk(GEN nf, GEN a, GEN sprk, GEN mod) { GEN e, prk, g, U1, U2, y, ff, O, o, oN, gN, N, T, p, modpr, pr, cyc; if (typ(a) == t_MAT) return famat_zlog_pr(nf, gel(a,1), gel(a,2), sprk, mod); N = NULL; ff = sprk_get_ff(sprk); pr = gel(ff,1); /* modpr */ g = gN = gel(ff,2); O = gel(ff,3); /* order of g = |Fq^*|, in [ord, fa] format */ o = oN = gel(O,1); /* order as a t_INT */ prk = sprk_get_prk(sprk); modpr = nf_to_Fq_init(nf, &pr, &T, &p); if (mod) { GEN d = gcdii(o,mod); if (!equalii(o, d)) { N = diviiexact(o,d); /* > 1, coprime to p */ a = nfpowmodideal(nf, a, N, prk); oN = d; /* order of g^N mod pr */ } } if (equali1(oN)) e = gen_0; else { if (N) { O = order_update(oN, O); gN = Fq_pow(g, N, T, p); } e = Fq_log(nf_to_Fq(nf,a,modpr), gN, O, T, p); } /* 0 <= e < oN is correct modulo oN */ if (sprk_is_prime(sprk)) return mkcol(e); /* k = 1 */ sprk_get_U2(sprk, &U1,&U2); cyc = sprk_get_cyc(sprk); if (mod) { cyc = ZV_snf_gcd(cyc, mod); if (signe(remii(mod,p))) return ZV_ZV_mod(ZC_Z_mul(U1,e), cyc); } if (signe(e)) { GEN E = N? mulii(e, N): e; a = nfmulpowmodideal(nf, a, sprk_get_gnf(sprk), Fp_neg(E, o), prk); } /* a = 1 mod pr */ y = log_prk1(nf, a, lg(U2)-1, sprk_get_L2(sprk), prk); if (N) { /* from DL(a^N) to DL(a) */ GEN E = gel(sprk_get_cyc(sprk), 1), q = powiu(p, Z_pval(E, p)); y = ZC_Z_mul(y, Fp_inv(N, q)); } y = ZC_lincomb(gen_1, e, ZM_ZC_mul(U2,y), U1); return ZV_ZV_mod(y, cyc); } /* true nf */ GEN log_prk_init(GEN nf, GEN pr, long k, GEN MOD) { return sprkinit(nf,pr,k,NULL,MOD);} GEN veclog_prk(GEN nf, GEN v, GEN sprk) { long l = lg(v), i; GEN w = cgetg(l, t_MAT); for (i = 1; i < l; i++) gel(w,i) = log_prk(nf, gel(v,i), sprk, NULL); return w; } static GEN famat_zlog(GEN nf, GEN fa, GEN sgn, zlog_S *S) { long i, l0, l = lg(S->U); GEN g = gel(fa,1), e = gel(fa,2), y = cgetg(l, t_COL); l0 = lg(S->sprk); /* = l (trivial arch. part), or l-1 */ for (i=1; i < l0; i++) gel(y,i) = famat_zlog_pr(nf, g, e, gel(S->sprk,i), S->mod); if (l0 != l) { if (!sgn) sgn = nfsign_arch(nf, fa, S->archp); gel(y,l0) = Flc_to_ZC(sgn); } return y; } /* assume that cyclic factors are normalized, in particular != [1] */ static GEN split_U(GEN U, GEN Sprk) { long t = 0, k, n, l = lg(Sprk); GEN vU = cgetg(l+1, t_VEC); for (k = 1; k < l; k++) { n = lg(sprk_get_cyc(gel(Sprk,k))) - 1; /* > 0 */ gel(vU,k) = vecslice(U, t+1, t+n); t += n; } /* t+1 .. lg(U)-1 */ n = lg(U) - t - 1; /* can be 0 */ if (!n) setlg(vU,l); else gel(vU,l) = vecslice(U, t+1, t+n); return vU; } static void init_zlog_mod(zlog_S *S, GEN bid, GEN mod) { GEN fa2 = bid_get_fact2(bid), MOD = bid_get_MOD(bid); S->U = bid_get_U(bid); S->hU = lg(bid_get_cyc(bid))-1; S->archp = bid_get_archp(bid); S->sprk = bid_get_sprk(bid); S->bid = bid; if (MOD) mod = mod? gcdii(mod, MOD): MOD; S->mod = mod; S->P = gel(fa2,1); S->k = gel(fa2,2); S->no2 = lg(S->P) == lg(gel(bid_get_fact(bid),1)); } void init_zlog(zlog_S *S, GEN bid) { return init_zlog_mod(S, bid, NULL); } /* a a t_FRAC/t_INT, reduce mod bid */ static GEN Q_mod_bid(GEN bid, GEN a) { GEN xZ = gcoeff(bid_get_ideal(bid),1,1); GEN b = Rg_to_Fp(a, xZ); if (gsigne(a) < 0) b = subii(b, xZ); return signe(b)? b: xZ; } /* Return decomposition of a on the CRT generators blocks attached to the * S->sprk and sarch; sgn = sign(a, S->arch), NULL if unknown */ static GEN zlog(GEN nf, GEN a, GEN sgn, zlog_S *S) { long k, l; GEN y; a = nf_to_scalar_or_basis(nf, a); switch(typ(a)) { case t_INT: break; case t_FRAC: a = Q_mod_bid(S->bid, a); break; default: /* case t_COL: */ { GEN den; check_nfelt(a, &den); if (den) { a = Q_muli_to_int(a, den); a = mkmat2(mkcol2(a, den), mkcol2(gen_1, gen_m1)); return famat_zlog(nf, a, sgn, S); } } } if (sgn) sgn = (lg(sgn) == 1)? NULL: leafcopy(sgn); else sgn = (lg(S->archp) == 1)? NULL: nfsign_arch(nf, a, S->archp); l = lg(S->sprk); y = cgetg(sgn? l+1: l, t_COL); for (k = 1; k < l; k++) { GEN sprk = gel(S->sprk,k); gel(y,k) = log_prk(nf, a, sprk, S->mod); } if (sgn) gel(y,l) = Flc_to_ZC(sgn); return y; } /* true nf */ GEN pr_basis_perm(GEN nf, GEN pr) { long f = pr_get_f(pr); GEN perm; if (f == nf_get_degree(nf)) return identity_perm(f); perm = cgetg(f+1, t_VECSMALL); perm[1] = 1; if (f > 1) { GEN H = pr_hnf(nf,pr); long i, k; for (i = k = 2; k <= f; i++) if (!equali1(gcoeff(H,i,i))) perm[k++] = i; } return perm; } /* \sum U[i]*y[i], U[i] ZM, y[i] ZC. We allow lg(y) > lg(U). */ static GEN ZMV_ZCV_mul(GEN U, GEN y) { long i, l = lg(U); GEN z = NULL; if (l == 1) return cgetg(1,t_COL); for (i = 1; i < l; i++) { GEN u = ZM_ZC_mul(gel(U,i), gel(y,i)); z = z? ZC_add(z, u): u; } return z; } /* A * (U[1], ..., U[d] */ static GEN ZM_ZMV_mul(GEN A, GEN U) { long i, l; GEN V = cgetg_copy(U,&l); for (i = 1; i < l; i++) gel(V,i) = ZM_mul(A,gel(U,i)); return V; } /* a = 1 mod pr, sprk mod pr^e, e >= 1 */ static GEN sprk_log_prk1_2(GEN nf, GEN a, GEN sprk) { GEN U1, U2, y, L2 = sprk_get_L2(sprk); sprk_get_U2(sprk, &U1,&U2); y = ZM_ZC_mul(U2, log_prk1(nf, a, lg(U2)-1, L2, sprk_get_prk(sprk))); return ZV_ZV_mod(y, sprk_get_cyc(sprk)); } /* true nf; assume e >= 2 */ GEN sprk_log_gen_pr2(GEN nf, GEN sprk, long e) { GEN M, G, pr = sprk_get_pr(sprk); long i, l; if (e == 2) { GEN L2 = sprk_get_L2(sprk), L = gel(L2,1); G = gel(L,2); l = lg(G); } else { GEN perm = pr_basis_perm(nf,pr), PI = nfpow_u(nf, pr_get_gen(pr), e-1); l = lg(perm); G = cgetg(l, t_VEC); if (typ(PI) == t_INT) { /* zk_ei_mul doesn't allow t_INT */ long N = nf_get_degree(nf); gel(G,1) = addiu(PI,1); for (i = 2; i < l; i++) { GEN z = col_ei(N, 1); gel(G,i) = z; gel(z, perm[i]) = PI; } } else { gel(G,1) = nfadd(nf, gen_1, PI); for (i = 2; i < l; i++) gel(G,i) = nfadd(nf, gen_1, zk_ei_mul(nf, PI, perm[i])); } } M = cgetg(l, t_MAT); for (i = 1; i < l; i++) gel(M,i) = sprk_log_prk1_2(nf, gel(G,i), sprk); return M; } /* 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. 'ind' is the index of pr in modulus * factorization; true nf */ GEN log_gen_pr(zlog_S *S, long ind, GEN nf, long e) { GEN Uind = gel(S->U, ind); if (e == 1) retmkmat( gel(Uind,1) ); return ZM_mul(Uind, sprk_log_gen_pr2(nf, gel(S->sprk,ind), e)); } /* true nf */ GEN sprk_log_gen_pr(GEN nf, GEN sprk, long e) { if (e == 1) { long n = lg(sprk_get_cyc(sprk))-1; retmkmat(col_ei(n, 1)); } return sprk_log_gen_pr2(nf, sprk, e); } /* a = 1 mod pr */ GEN sprk_log_prk1(GEN nf, GEN a, GEN sprk) { if (lg(sprk) == 5) return mkcol(gen_0); /* mod pr */ return sprk_log_prk1_2(nf, a, sprk); } /* 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) { return gel(veclast(S->U), index); } /* compute bid.clgp: [h,cyc] or [h,cyc,gen] */ static GEN bid_grp(GEN nf, GEN U, GEN cyc, GEN g, GEN F, GEN sarch) { GEN G, h = ZV_prod(cyc); long c; if (!U) return mkvec2(h,cyc); c = lg(U); G = cgetg(c,t_VEC); if (c > 1) { GEN U0, Uoo, EX = cyc_get_expo(cyc); /* exponent of bid */ long i, hU = nbrows(U), nba = lg(sarch_get_cyc(sarch))-1; /* #f_oo */ if (!nba) { U0 = U; Uoo = NULL; } else if (nba == hU) { U0 = NULL; Uoo = U; } else { U0 = rowslice(U, 1, hU-nba); Uoo = rowslice(U, hU-nba+1, hU); } for (i = 1; i < c; i++) { GEN t = gen_1; if (U0) t = famat_to_nf_modideal_coprime(nf, g, gel(U0,i), F, EX); if (Uoo) t = set_sign_mod_divisor(nf, ZV_to_Flv(gel(Uoo,i),2), t, sarch); gel(G,i) = t; } } return mkvec3(h, cyc, G); } /* remove prime ideals of norm 2 with exponent 1 from factorization */ static GEN famat_strip2(GEN fa) { GEN P = gel(fa,1), E = gel(fa,2), Q, F; long l = lg(P), i, j; Q = cgetg(l, t_COL); F = cgetg(l, t_COL); for (i = j = 1; i < l; i++) { GEN pr = gel(P,i), e = gel(E,i); if (!absequaliu(pr_get_p(pr), 2) || itou(e) != 1 || pr_get_f(pr) != 1) { gel(Q,j) = pr; gel(F,j) = e; j++; } } setlg(Q,j); setlg(F,j); return mkmat2(Q,F); } static int checkarchp(GEN v, long r1) { long i, l = lg(v); pari_sp av = avma; GEN p; if (l == 1) return 1; if (l == 2) return v[1] > 0 && v[1] <= r1; p = zero_zv(r1); for (i = 1; i < l; i++) { long j = v[i]; if (j <= 0 || j > r1 || p[j]) return gc_long(av, 0); p[j] = 1; } return gc_long(av, 1); } /* True nf. Put ideal to form [[ideal,arch]] and set fa and fa2 to its * factorization, archp to the indices of arch places */ GEN check_mod_factored(GEN nf, GEN ideal, GEN *fa_, GEN *fa2_, GEN *archp_, GEN MOD) { GEN arch, x, fa, fa2, archp; long R1; R1 = nf_get_r1(nf); if (typ(ideal) == t_VEC && lg(ideal) == 3) { arch = gel(ideal,2); ideal= gel(ideal,1); switch(typ(arch)) { case t_VEC: if (lg(arch) != R1+1) pari_err_TYPE("Idealstar [incorrect archimedean component]",arch); archp = vec01_to_indices(arch); break; case t_VECSMALL: if (!checkarchp(arch, R1)) pari_err_TYPE("Idealstar [incorrect archimedean component]",arch); archp = arch; arch = indices_to_vec01(archp, R1); break; default: pari_err_TYPE("Idealstar [incorrect archimedean component]",arch); return NULL;/*LCOV_EXCL_LINE*/ } } else { arch = zerovec(R1); archp = cgetg(1, t_VECSMALL); } if (MOD) { if (typ(MOD) != t_INT) pari_err_TYPE("bnrinit [incorrect cycmod]", MOD); if (mpodd(MOD) && lg(archp) != 1) MOD = shifti(MOD, 1); /* ensure elements of G^MOD are >> 0 */ } if (is_nf_factor(ideal)) { fa = ideal; x = factorbackprime(nf, gel(fa,1), gel(fa,2)); } else { fa = idealfactor(nf, ideal); x = ideal; } if (typ(x) != t_MAT) x = idealhnf_shallow(nf, x); if (lg(x) == 1) pari_err_DOMAIN("Idealstar", "ideal","=",gen_0,x); if (typ(gcoeff(x,1,1)) != t_INT) pari_err_DOMAIN("Idealstar","denominator(ideal)", "!=",gen_1,x); fa2 = famat_strip2(fa); if (fa_ != NULL) *fa_ = fa; if (fa2_ != NULL) *fa2_ = fa2; if (fa2_ != NULL) *archp_ = archp; return mkvec2(x, arch); } /* True nf. Compute [[ideal,arch], [h,[cyc],[gen]], idealfact, [liste], U] flag may include nf_GEN | nf_INIT */ static GEN Idealstarmod_i(GEN nf, GEN ideal, long flag, GEN MOD) { long i, nbp; GEN y, cyc, U, u1 = NULL, fa, fa2, sprk, x_arch, x, arch, archp, E, P, sarch, gen; x_arch = check_mod_factored(nf, ideal, &fa, &fa2, &archp, MOD); x = gel(x_arch, 1); arch = gel(x_arch, 2); sarch = nfarchstar(nf, x, archp); P = gel(fa2,1); E = gel(fa2,2); nbp = lg(P)-1; sprk = cgetg(nbp+1,t_VEC); if (nbp) { GEN t = (lg(gel(fa,1))==2)? NULL: x; /* beware fa != fa2 */ cyc = cgetg(nbp+2,t_VEC); gen = cgetg(nbp+1,t_VEC); for (i = 1; i <= nbp; i++) { GEN L = sprkinit(nf, gel(P,i), itou(gel(E,i)), t, MOD); gel(sprk,i) = L; gel(cyc,i) = sprk_get_cyc(L); /* true gens are congruent to those mod x AND positive at archp */ gel(gen,i) = sprk_get_gen(L); } gel(cyc,i) = sarch_get_cyc(sarch); cyc = shallowconcat1(cyc); gen = shallowconcat1(gen); cyc = ZV_snf_group(cyc, &U, (flag & nf_GEN)? &u1: NULL); } else { cyc = sarch_get_cyc(sarch); gen = cgetg(1,t_VEC); U = matid(lg(cyc)-1); if (flag & nf_GEN) u1 = U; } if (MOD) cyc = ZV_snf_gcd(cyc, MOD); y = bid_grp(nf, u1, cyc, gen, x, sarch); if (!(flag & nf_INIT)) return y; U = split_U(U, sprk); return mkvec5(mkvec2(x, arch), y, mkvec2(fa,fa2), MOD? mkvec3(sprk, sarch, MOD): mkvec2(sprk, sarch), U); } static long idealHNF_norm_pval(GEN x, GEN p) { long i, v = 0, l = lg(x); for (i = 1; i < l; i++) v += Z_pval(gcoeff(x,i,i), p); return v; } static long sprk_get_k(GEN sprk) { GEN pr, prk; if (sprk_is_prime(sprk)) return 1; pr = sprk_get_pr(sprk); prk = sprk_get_prk(sprk); return idealHNF_norm_pval(prk, pr_get_p(pr)) / pr_get_f(pr); } /* true nf, L a sprk */ GEN sprk_to_bid(GEN nf, GEN L, long flag) { GEN y, cyc, U, u1 = NULL, fa, fa2, arch, sarch, gen, sprk; arch = zerovec(nf_get_r1(nf)); fa = to_famat_shallow(sprk_get_pr(L), utoipos(sprk_get_k(L))); sarch = nfarchstar(nf, NULL, cgetg(1, t_VECSMALL)); fa2 = famat_strip2(fa); sprk = mkvec(L); cyc = shallowconcat(sprk_get_cyc(L), sarch_get_cyc(sarch)); gen = sprk_get_gen(L); cyc = ZV_snf_group(cyc, &U, (flag & nf_GEN)? &u1: NULL); y = bid_grp(nf, u1, cyc, gen, NULL, sarch); if (!(flag & nf_INIT)) return y; return mkvec5(mkvec2(sprk_get_prk(L), arch), y, mkvec2(fa,fa2), mkvec2(sprk, sarch), split_U(U, sprk)); } GEN Idealstarmod(GEN nf, GEN ideal, long flag, GEN MOD) { pari_sp av = avma; nf = nf? checknf(nf): nfinit(pol_x(0), DEFAULTPREC); return gerepilecopy(av, Idealstarmod_i(nf, ideal, flag, MOD)); } GEN Idealstar(GEN nf, GEN ideal, long flag) { return Idealstarmod(nf, ideal, flag, NULL); } GEN Idealstarprk(GEN nf, GEN pr, long k, long flag) { pari_sp av = avma; GEN z = Idealstarmod_i(nf, mkmat2(mkcol(pr),mkcols(k)), flag, NULL); return gerepilecopy(av, z); } /* FIXME: obsolete */ GEN zidealstarinitgen(GEN nf, GEN ideal) { return Idealstar(nf,ideal, nf_INIT|nf_GEN); } GEN zidealstarinit(GEN nf, GEN ideal) { return Idealstar(nf,ideal, nf_INIT); } GEN zidealstar(GEN nf, GEN ideal) { return Idealstar(nf,ideal, nf_GEN); } GEN idealstarmod(GEN nf, GEN ideal, long flag, GEN MOD) { switch(flag) { case 0: return Idealstarmod(nf,ideal, nf_GEN, MOD); case 1: return Idealstarmod(nf,ideal, nf_INIT, MOD); case 2: return Idealstarmod(nf,ideal, nf_INIT|nf_GEN, MOD); default: pari_err_FLAG("idealstar"); } return NULL; /* LCOV_EXCL_LINE */ } GEN idealstar0(GEN nf, GEN ideal,long flag) { return idealstarmod(nf, ideal, flag, NULL); } void check_nfelt(GEN x, GEN *den) { long l = lg(x), i; GEN t, d = NULL; if (typ(x) != t_COL) pari_err_TYPE("check_nfelt", x); for (i=1; ihU) return cgetg(1, t_COL); if (typ(x) == t_MAT) y = famat_zlog(nf, x, NULL, S); else y = zlog(nf, x, NULL, S); y = ZMV_ZCV_mul(S->U, y); return gerepileupto(av, ZV_ZV_mod(y, bid_get_cyc(S->bid))); } GEN ideallogmod(GEN nf, GEN x, GEN bid, GEN mod) { zlog_S S; if (!nf) { if (mod) pari_err_IMPL("Zideallogmod"); return Zideallog(bid, x); } checkbid(bid); init_zlog_mod(&S, bid, mod); return ideallog_i(checknf(nf), x, &S); } GEN ideallog(GEN nf, GEN x, GEN bid) { return ideallogmod(nf, x, bid, NULL); } /*************************************************************************/ /** **/ /** JOIN BID STRUCTURES, IDEAL LISTS **/ /** **/ /*************************************************************************/ /* bid1, bid2: for coprime modules m1 and m2 (without arch. part). * Output: bid for m1 m2 */ static GEN join_bid(GEN nf, GEN bid1, GEN bid2) { pari_sp av = avma; long nbgen, l1,l2; GEN I1,I2, G1,G2, sprk1,sprk2, cyc1,cyc2, sarch; GEN sprk, fa,fa2, U, cyc, y, u1 = NULL, x, gen; I1 = bid_get_ideal(bid1); I2 = bid_get_ideal(bid2); if (gequal1(gcoeff(I1,1,1))) return bid2; /* frequent trivial case */ G1 = bid_get_grp(bid1); G2 = bid_get_grp(bid2); x = idealmul(nf, I1,I2); fa = famat_mul_shallow(bid_get_fact(bid1), bid_get_fact(bid2)); fa2= famat_mul_shallow(bid_get_fact2(bid1), bid_get_fact2(bid2)); sprk1 = bid_get_sprk(bid1); sprk2 = bid_get_sprk(bid2); sprk = shallowconcat(sprk1, sprk2); cyc1 = abgrp_get_cyc(G1); l1 = lg(cyc1); cyc2 = abgrp_get_cyc(G2); l2 = lg(cyc2); gen = (lg(G1)>3 && lg(G2)>3)? gen_1: NULL; nbgen = l1+l2-2; cyc = ZV_snf_group(shallowconcat(cyc1,cyc2), &U, gen? &u1: NULL); if (nbgen) { GEN U1 = bid_get_U(bid1), U2 = bid_get_U(bid2); U1 = l1==1? const_vec(lg(sprk1), cgetg(1,t_MAT)) : ZM_ZMV_mul(vecslice(U, 1, l1-1), U1); U2 = l2==1? const_vec(lg(sprk2), cgetg(1,t_MAT)) : ZM_ZMV_mul(vecslice(U, l1, nbgen), U2); U = shallowconcat(U1, U2); } else U = const_vec(lg(sprk), cgetg(1,t_MAT)); if (gen) { GEN uv = zkchinese1init2(nf, I2, I1, x); gen = shallowconcat(zkVchinese1(gel(uv,1), abgrp_get_gen(G1)), zkVchinese1(gel(uv,2), abgrp_get_gen(G2))); } sarch = bid_get_sarch(bid1); /* trivial */ y = bid_grp(nf, u1, cyc, gen, x, sarch); x = mkvec2(x, bid_get_arch(bid1)); y = mkvec5(x, y, mkvec2(fa, fa2), mkvec2(sprk, sarch), U); return gerepilecopy(av,y); } typedef struct _ideal_data { GEN nf, emb, L, pr, prL, sgnU, archp; } 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) { GEN bid = join_idealinit(D, gel(x,1)), u = gel(x,2), v = mkvec(D->emb); if (lg(u) != 1) v = shallowconcat(u, v); return mkvec2(bid, v); } GEN log_prk_units_init(GEN bnf) { GEN U = bnf_has_fu(bnf); if (U) U = matalgtobasis(bnf_get_nf(bnf), U); else if (!(U = bnf_compactfu_mat(bnf))) (void)bnf_build_units(bnf); return mkvec2(bnf_get_tuU(bnf), U); } /* flag & nf_GEN : generators, otherwise no * flag &2 : units, otherwise no * flag &4 : ideals in HNF, otherwise bid * flag &8 : omit ideals which cannot be conductors (pr^1 with Npr=2) */ static GEN Ideallist(GEN bnf, ulong bound, long flag) { const long do_units = flag & 2, big_id = !(flag & 4), cond = flag & 8; const long istar_flag = (flag & nf_GEN) | nf_INIT; pari_sp av; long i, j; GEN nf, z, p, fa, id, BOUND, U, empty = cgetg(1,t_VEC); forprime_t S; ideal_data ID; GEN (*join_z)(ideal_data*, GEN); if (do_units) { bnf = checkbnf(bnf); nf = bnf_get_nf(bnf); join_z = &join_unit; } else { nf = checknf(bnf); join_z = big_id? &join_idealinit: &join_ideal; } 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 */ BOUND = utoipos(bound); z = const_vec(bound, empty); U = do_units? log_prk_units_init(bnf): NULL; gel(z,1) = mkvec(U? mkvec2(id, empty): id); ID.nf = nf; p = cgetipos(3); u_forprime_init(&S, 2, bound); av = avma; while ((p[2] = u_forprime_next(&S))) { if (DEBUGLEVEL>1) err_printf("%ld ",p[2]); fa = idealprimedec_limit_norm(nf, p, BOUND); for (j = 1; j < lg(fa); j++) { GEN pr = gel(fa,j), z2 = leafcopy(z); ulong Q, q = upr_norm(pr); long l; ID.pr = ID.prL = pr; if (cond && q == 2) { l = 2; Q = 4; } else { l = 1; Q = q; } for (; Q <= bound; l++, Q *= q) /* add pr^l */ { ulong iQ; ID.L = utoipos(l); if (big_id) { ID.prL = Idealstarprk(nf, pr, l, istar_flag); if (U) ID.emb = Q == 2? empty : log_prk_units(nf, U, gel(bid_get_sprk(ID.prL),1)); } for (iQ = Q,i = 1; iQ <= bound; iQ += Q,i++) concat_join(&gel(z,iQ), gel(z2,i), join_z, &ID); } } if (gc_needed(av,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"Ideallist"); z = gerepilecopy(av, z); } } return z; } GEN gideallist(GEN bnf, GEN B, long flag) { pari_sp av = avma; if (typ(B) != t_INT) { B = gfloor(B); if (typ(B) != t_INT) pari_err_TYPE("ideallist", B); if (signe(B) < 0) B = gen_0; } if (signe(B) < 0) { if (flag != 4) pari_err_IMPL("ideallist with bid for single norm"); return gerepilecopy(av, ideals_by_norm(checknf(bnf), absi(B))); } if (flag < 0 || flag > 15) pari_err_FLAG("ideallist"); return gerepilecopy(av, Ideallist(bnf, itou(B), flag)); } GEN ideallist0(GEN bnf, long bound, long flag) { pari_sp av = avma; if (flag < 0 || flag > 15) pari_err_FLAG("ideallist"); return gerepilecopy(av, Ideallist(bnf, bound, flag)); } GEN ideallist(GEN bnf,long bound) { return ideallist0(bnf,bound,4); } /* bid = for module m (without arch. part), arch = archimedean part. * Output: bid for [m,arch] */ static GEN join_bid_arch(GEN nf, GEN bid, GEN archp) { pari_sp av = avma; GEN G, U; GEN sprk, cyc, y, u1 = NULL, x, sarch, gen; checkbid(bid); G = bid_get_grp(bid); x = bid_get_ideal(bid); sarch = nfarchstar(nf, bid_get_ideal(bid), archp); sprk = bid_get_sprk(bid); gen = (lg(G)>3)? gel(G,3): NULL; cyc = diagonal_shallow(shallowconcat(gel(G,2), sarch_get_cyc(sarch))); cyc = ZM_snf_group(cyc, &U, gen? &u1: NULL); y = bid_grp(nf, u1, cyc, gen, x, sarch); U = split_U(U, sprk); y = mkvec5(mkvec2(x, archp), y, gel(bid,3), mkvec2(sprk, sarch), U); return gerepilecopy(av,y); } static GEN join_arch(ideal_data *D, GEN x) { return join_bid_arch(D->nf, x, D->archp); } static GEN join_archunit(ideal_data *D, GEN x) { GEN bid = join_arch(D, gel(x,1)), u = gel(x,2), v = mkvec(D->emb); if (lg(u) != 1) v = shallowconcat(u, v); return mkvec2(bid, v); } /* 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, nf; ideal_data ID; GEN (*join_z)(ideal_data*, GEN); if (typ(L) != t_VEC) pari_err_TYPE("ideallistarch",L); if (l == 1) return cgetg(1,t_VEC); z = gel(L,1); if (typ(z) != t_VEC) pari_err_TYPE("ideallistarch",z); z = gel(z,1); /* either a bid or [bid,U] */ ID.archp = vec01_to_indices(arch); if (lg(z) == 3) { /* [bid,U]: do units */ bnf = checkbnf(bnf); nf = bnf_get_nf(bnf); if (typ(z) != t_VEC) pari_err_TYPE("ideallistarch",z); ID.emb = zm_to_ZM( rowpermute(nfsign_units(bnf,NULL,1), ID.archp) ); join_z = &join_archunit; } else { join_z = &join_arch; nf = checknf(bnf); } ID.nf = nf; 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= 2) #define dbg_mode1() if (DEBUGLEVEL >= 3) #define ANSI_RED "\x1b[31m" #define ANSI_GREEN "\x1b[32m" #define ANSI_YELLOW "\x1b[33m" #define ANSI_BLUE "\x1b[34m" #define ANSI_MAGENTA "\x1b[35m" #define ANSI_CYAN "\x1b[36m" #define ANSI_WHITE "\x1b[37m" #define ANSI_BRIGHT_RED "\x1b[31;1m" #define ANSI_BRIGHT_GREEN "\x1b[32;1m" #define ANSI_BRIGHT_YELLOW "\x1b[33;1m" #define ANSI_BRIGHT_BLUE "\x1b[34;1m" #define ANSI_BRIGHT_MAGENTA "\x1b[35;1m" #define ANSI_BRIGHT_CYAN "\x1b[36;1m" #define ANSI_BRIGHT_WHITE "\x1b[37;1m" #define ANSI_RESET "\x1b[0m" /* THINGS THAT DON'T BELONG */ /* Assume that x is a vector such that f(x) = 1 for x <= k f(x) = 0 otherwise. Return k. */ static long zv_binsearch0(void *E, long (*f)(void* E, GEN x), GEN x) { long lo = 1; long hi = lg(x)-1; while (lo < hi) { long mi = lo + (hi - lo)/2 + 1; if (f(E,gel(x,mi))) lo = mi; else hi = mi - 1; } if (f(E,gel(x,lo))) return lo; return 0; } INLINE long time_record(GEN* X0, const char* Xx, long t) { long i = Xx[0]-'A'+1, j = Xx[1]-'1'+1; umael3(*X0, 1, i, j) += t; umael3(*X0, 2, i, j) ++; return t; } INLINE long timer_record(GEN* X0, const char* Xx, pari_timer* ti) { return time_record(X0, Xx, timer_delay(ti)); } INLINE long FpJ_is_inf(GEN P) { return signe(gel(P, 3)) == 0; } /*****************************************************************/ /* D < 0 fundamental: return the number of units in Q(sqrt(D)) */ INLINE long D_get_wD(long D) { if (D == -4) return 4; if (D == -3) return 6; return 2; } /* Dinfo contains information related to the discirminant * D: the discriminant (D < 0) * h: the class number associated to D * bi: the "best invariant" for computing polclass(D, bi) * pd: the degree of polclass; equal to h except when bi is a double * eta-quotient w_p,q with p|D and q|D, where pd = h/2. * Dfac: the prime factorization of D; we have D = q0 q1* q2* ... qn* * where q0 = 1, -4, 8, -8, qi* = 1 mod 4 and |qi| is a prime. * The factorization is a vecsmall listing the indices of the qi* as * they appear in the primelist (q0 = 1 is omitted) */ INLINE long Dinfo_get_D(GEN Dinfo) { return gel(Dinfo, 1)[1]; } INLINE long Dinfo_get_h(GEN Dinfo) { return gel(Dinfo, 1)[2]; } INLINE long Dinfo_get_bi(GEN Dinfo) { return gel(Dinfo, 1)[3]; } INLINE ulong Dinfo_get_pd(GEN Dinfo) { return umael(Dinfo, 1, 4); } INLINE GEN Dinfo_get_Dfac(GEN Dinfo) { return gel(Dinfo, 2); } /* primelist and indexlist * * primelist begins with 8, -4, -8; subsequent elements are the p^* for * successive odd primes <= maxsqrt, by increasing absolute value * * i | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | * ---------+----+----+----+----+----+----+----+----+----+-----+-----+ * i | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | * Plist[i] | 8 | -4 | -8 | -3 | 5 | -7 |-11 | 13 | 17 | -19 | -23 | * p | 3 | 5 | 7 | 9 | 11 | 13 | 15 | 17 | 19 | 21 | 23 | * ---------+----+----+----+----+----+----+----+----+----+-----+-----+*/ /* primelist containing primes whose absolute value is at most maxsqrt */ static GEN ecpp_primelist_init(long maxsqrt) { GEN P = cgetg(maxsqrt, t_VECSMALL); forprime_t T; long p, j = 4; u_forprime_init(&T, 3, maxsqrt); P[1] = 8; P[2] = -4; P[3] = -8; while((p = u_forprime_next(&T))) P[j++] = ((p & 3UL) == 1)? p: -p; setlg(P,j); return P; } static GEN Dfac_to_p(GEN x, GEN P) { pari_APPLY_long(uel(P,x[i])); } static GEN Dfac_to_roots(GEN x, GEN P) { pari_APPLY_type(t_VEC, gel(P,x[i])); } #if 0 INLINE ulong ecpp_param_get_maxsqrt(GEN param) { return umael3(param, 1, 1, 1); } INLINE ulong ecpp_param_get_maxdisc(GEN param) { return umael3(param, 1, 1, 2); } #endif INLINE ulong ecpp_param_get_maxpcdg(GEN param) { return umael3(param, 1, 1, 3); } INLINE GEN ecpp_param_get_uprimelist(GEN param) { return gmael(param, 1, 2); } INLINE GEN ecpp_param_get_primelist(GEN param) { return gmael(param, 1, 3); } INLINE GEN ecpp_param_get_disclist(GEN param) { return gmael(param, 1, 4); } INLINE GEN ecpp_param_get_primeord(GEN param) { return gmael(param, 1, 5); } INLINE GEN ecpp_param_get_primorial_vec(GEN param) { return gel(param, 2); } INLINE GEN ecpp_param_get_tune(GEN param) { return gel(param, 3); } /* Input: x, 20 <= x <= 35 * Output: a vector whose ith entry is the product of all primes below 2^x */ static GEN primorial_vec(ulong x) { pari_sp av = avma; long i, y = x-19; GEN v = primes_upto_zv(1UL << x), w = cgetg(y+1, t_VEC); /* ind[i]th prime number is the largest prime <= 2^(20+i) */ long ind[] = { 0, 82025L, 155611L, 295947L, 564163L, 1077871L, 2063689L, 3957809L, 7603553L, 14630843L, 28192750L, 54400028L, 105097565L, 203280221L, 393615806L, 762939111L, 1480206279L}; gel(w,1) = zv_prod_Z(vecslice(v,1,ind[1])); for (i = 2; i <= y; i++) { pari_sp av2 = avma; GEN q = mulii(gel(w,i-1), zv_prod_Z(vecslice(v,ind[i-1]+1,ind[i]))); gel(w,i) = gerepileuptoint(av2, q); } return gerepileupto(av, w); } /* NDmqg contains N, as in the theorem in ??ecpp Dinfo, as discussed in the comment about Dinfo m, as in the theorem in ??ecpp q, as in the theorem in ??ecpp g, a quadratic nonresidue modulo N sqrt, a list of squareroots */ INLINE GEN NDmqg_get_N(GEN x) { return gel(x,1); } INLINE GEN NDmqg_get_Dinfo(GEN x) { return gel(x,2); } INLINE GEN NDmqg_get_m(GEN x) { return gel(x,3); } INLINE GEN NDmqg_get_q(GEN x) { return gel(x,4); } INLINE GEN NDmqg_get_g(GEN x) { return gel(x,5); } INLINE GEN NDmqg_get_sqrt(GEN x) { return gel(x,6); } /* COMPARATOR FUNCTIONS */ static int sort_disclist(void *data, GEN x, GEN y) { long d1, h1, g1, o1, pd1, hf1, wD1, d2, h2, g2, o2, pd2, hf2, wD2; (void)data; d1 = Dinfo_get_D(x); wD1 = D_get_wD(d1); d2 = Dinfo_get_D(y); wD2 = D_get_wD(d2); /* higher number of units means more elliptic curves to try */ if (wD1 != wD2) return wD2 > wD1 ? 1 : -1; /* lower polclass degree is better: faster computation of roots modulo N */ pd1 = Dinfo_get_pd(x); /* degree of polclass */ pd2 = Dinfo_get_pd(y); if (pd1 != pd2) return pd1 > pd2 ? 1 : -1; g1 = lg(Dinfo_get_Dfac(x))-1; /* genus number */ h1 = Dinfo_get_h(x); /* class number */ o1 = h1 >> (g1-1); /* odd class number */ g2 = lg(Dinfo_get_Dfac(y))-1; h2 = Dinfo_get_h(y); o2 = h2 >> (g2-1); if (o1 != o2) return g1 > g2 ? 1 : -1; /* lower class number is better: higher probability of succesful cornacchia */ if (h1 != h2) return h1 > h2 ? 1 : -1; /* higher height factor is better: polclass would have lower coefficients */ hf1 = modinv_height_factor(Dinfo_get_bi(x)); /* height factor for best inv. */ hf2 = modinv_height_factor(Dinfo_get_bi(y)); if (hf1 != hf2) return hf2 > hf1 ? 1 : -1; /* "higher" discriminant is better since its absolute value is lower */ if (d1 != d2) return d2 > d1 ? 1 : -1; return 0; } INLINE long NDmqg_get_D(GEN x) { return Dinfo_get_D(NDmqg_get_Dinfo(x)); } static int sort_NDmq_by_D(void *data, GEN x, GEN y) { long d1 = NDmqg_get_D(x); long d2 = NDmqg_get_D(y); (void)data; return d2 > d1 ? 1 : -1; } static int sort_Dmq_by_q(void *data, GEN x, GEN y) { (void)data; return cmpii(gel(x,3), gel(y,3)); } INLINE long Dmq_get_D(GEN Dmq) { return Dinfo_get_D(gel(Dmq,1)); } INLINE long Dmq_get_h(GEN Dmq) { return Dinfo_get_h(gel(Dmq,1)); } static int sort_Dmq_by_cnum(void *data, GEN x, GEN y) { ulong h1 = Dmq_get_h(x); ulong h2 = Dmq_get_h(y); if (h1 != h2) return h1 > h2 ? 1 : -1; return sort_Dmq_by_q(data, x, y); } static void allh_r(GEN H, ulong minD, ulong maxD) { ulong a, A = usqrt(maxD/3), minD2 = (minD-1) >> 1, maxD2 = maxD >> 1; for (a = 1; a <= A; a++) { ulong a2 = a << 1, aa = a*a, aa4 = aa << 2, b, B; { /* b = 0 */ ulong D = aa << 1; if (D <= minD2) D += a2 * ((minD2 - D + a2) / a2); for (; D <= maxD2; D += a2) H[D]++; } B = aa4 - 1; /* 4a^2 - b^2 */ for (b = 1; b < a; b++) { ulong D = B >> 1; /* (4a^2 - b^2) / 2 */ B -= (b << 1) + 1; if (D > maxD2) continue; if (D > minD2) { H[D]++; D += a2; /* c = a */ } else D += a2 * ((minD2 - D + a2) / a2); for (; D <= maxD2; D += a2) H[D] += 2; } { /* b = a */ ulong D = (aa4 - aa) >> 1; if (D <= minD2) D += a2 * ((minD2 - D + a2) / a2); for (; D <= maxD2; D += a2) H[D] ++; } } } /* return H s.t if -maxD <= D < 0 is fundamental then H[(-D)>>1] is the * ordinary class number of Q(sqrt(D)); junk at other entries. */ static GEN allh(ulong maxD) { ulong maxD2 = maxD>>1, s = 1UL<<16; GEN H = zero_zv(maxD2); ulong a; for (a = 0; a < maxD; a += s) allh_r(H, a+1, minss(a+s,maxD)); return H; } static GEN mkDinfo(GEN c, long D, long h) { long bi, pd, p1, p2; bi = disc_best_modinv(D); pd = (modinv_degree(&p1,&p2,bi) && (-D)%p1==0 && (-D)%p2==0)? h/2: h; return mkvec2(mkvecsmall4(D, h, bi, pd), c); } static GEN ecpp_disclist_init(ulong maxdisc, GEN primelist) { pari_sp av = avma; long t, ip, u, lp, lmerge; GEN merge, ev, od, Harr = allh(maxdisc); /* table of class numbers*/ long lenv = maxdisc/4; /* max length of od/ev */ long N = maxomegau(maxdisc) + 1; /* od[t] attached to discriminant 1-4*t, ev[t] attached to -4*t */ od = cgetg(lenv + 1, t_VEC); /* contains 'long' at first: save memory */ ev = cgetg(lenv + 1, t_VEC); /* first pass: squarefree sieve and restrict to maxsqrt-smooth disc */ for (t = 1; t <= lenv; t++) { od[t] = 1; switch(t&7) { case 0: case 4: ev[t] = 0; break; case 2: ev[t] =-8; break; case 6: ev[t] = 8; break; default:ev[t] =-4; break; } } lp = lg(primelist); for (ip = 4; ip < lp; ip++) /* skip 8,-4,-8 */ { /* sieve by squares of primes */ long s, q = primelist[ip], p = labs(q); s = (q == p)? 3: 1; for (t = (s*p+1)>>2; t <= lenv; t += p, s += 4) { long c = od[t]; if (c) { if (s%p == 0) od[t] = 0; else od[t] = c*q; } } s = 1; for (t = p; t <= lenv; t += p, s++) { long c = ev[t]; if (c) { if (s%p == 0) ev[t] = 0; else ev[t] = c*q; } } } for (u = 0, t = 1; t <= lenv; t++) { /* restrict to maxsqrt-smooth disc */ if (od[t] != -4*t+1) od[t] = 0; else u++; if (ev[t] != -4*t) ev[t] = 0; else u++; } /* second pass: sieve by primes and record factorization */ for (t = 1; t <= lenv; t++) { if (od[t]) gel(od,t) = vecsmalltrunc_init(N); if (ev[t]) { GEN F = vecsmalltrunc_init(N); long id; switch(t&7) { case 2: id = 3; break; case 6: id = 1; break; default:id = 2; break; } vecsmalltrunc_append(F, id); gel(ev,t) = F; } } lp = lg(primelist); for (ip = 4; ip < lp; ip++) /* skip 8,-4,-8 */ { long s, q = primelist[ip], p = labs(q); s = (q == p)? 3: 1; for (t = (s*p+1)>>2; t <= lenv; t += p, s += 4) { GEN c = gel(od,t); if (c) vecsmalltrunc_append(c, ip); } s = 1; for (t = p; t <= lenv; t += p, s++) { GEN c = gel(ev,t); if (c) vecsmalltrunc_append(c, ip); } } /* merging the two arrays */ merge = cgetg(u+1, t_VEC); lmerge = 0; for (t = 1; t <= lenv; t++) { GEN c; c = gel(od,t); if (c) gel(merge, ++lmerge) = mkDinfo(c,1-4*t, Harr[2*t-1]); c = gel(ev,t); if (c) gel(merge, ++lmerge) = mkDinfo(c, -4*t, Harr[2*t]); } setlg(merge, lmerge); gen_sort_inplace(merge, NULL, &sort_disclist, NULL); return gerepilecopy(av, merge); } static GEN ecpp_primeord_init(GEN primelist, GEN disclist) { long i, k=1, lgdisclist = lg(disclist), lprimelist = lg(primelist); GEN primeord = zero_Flv(lprimelist-1); for (i=1;i < lgdisclist; i++) { GEN Dinfo = gel(disclist, i), Dfac = Dinfo_get_Dfac(Dinfo); long j, l = lg(Dfac); for (j = 1; j < l; j++) { long ip = Dfac[j]; if (primeord[ip]==0) primeord[ip]=k++; } } return perm_inv(primeord); } /* Input: a vector tune whose components are [maxsqrt,maxpcdg,tdivexp,expiN] * Output: vector param of precomputations * let x = be a component of tune then * param[1][1] = [maxsqrt, maxdisc, maxpcdg] * param[1][2] = primelist = Vecsmall of primes * param[1][3] = disclist = vector of Dinfos, sorted by quality * param[2] = primorial_vec * param[3] = tune */ static GEN ecpp_param_set(GEN tune, GEN x) { pari_timer ti; pari_sp av = avma; ulong maxsqrt = uel(x,1), maxpcdg = uel(x,2), tdivexp = uel(x,3); ulong maxdisc = maxsqrt * maxsqrt; GEN Plist, U, Utree, Dlist, Olist, primorial, T; T = mkvecsmall3(maxsqrt, maxdisc, maxpcdg); dbg_mode() { err_printf(ANSI_BRIGHT_WHITE "\nECPP: parameters %Ps:\n" "init time: " ANSI_RESET, x); timer_start(&ti); } Plist = ecpp_primelist_init(maxsqrt); U = zv_abs(Plist); Utree = mkvec2(U, ZV_producttree(U)); dbg_mode() err_printf("%ld",timer_delay(&ti)); Dlist = ecpp_disclist_init(maxdisc, Plist); dbg_mode() err_printf(", %ld",timer_delay(&ti)); Olist = ecpp_primeord_init(Plist, Dlist); dbg_mode() err_printf(", %ld",timer_delay(&ti)); primorial = primorial_vec(tdivexp); dbg_mode() err_printf(", %ld\n",timer_delay(&ti)); return gerepilecopy(av, mkvec3(mkvec5(T,Utree,Plist,Dlist,Olist), primorial, tune)); } /* cert contains [N, t, s, a4, [x, y]] as documented in ??ecpp; the following * information can be obtained: * D = squarefreepart(t^2-4N) * m = (N+1-t), q = m/s, a6 = y^3 - x^2 - a4*x, J */ INLINE GEN cert_get_N(GEN x) { return gel(x,1); } INLINE GEN cert_get_t(GEN x) { return gel(x,2); } INLINE GEN cert_get_D(GEN x) { GEN N = cert_get_N(x), t = cert_get_t(x); return coredisc(subii(sqri(t), shifti(N, 2))); } INLINE GEN cert_get_m(GEN x) { GEN N = cert_get_N(x), t = cert_get_t(x); return subii(addiu(N, 1), t); } INLINE GEN cert_get_s(GEN x) { return gel(x,3); } INLINE GEN cert_get_q(GEN x) { return diviiexact(cert_get_m(x), cert_get_s(x)); } INLINE GEN cert_get_qlast(GEN x) { return cert_get_q(veclast(x)); } INLINE GEN cert_get_a4(GEN x) { return gel(x,4); } INLINE GEN cert_get_P(GEN x) { return gel(x,5); } INLINE GEN cert_get_x(GEN x) { return gel(cert_get_P(x), 1); } INLINE GEN cert_get_a6(GEN z) { GEN N = cert_get_N(z), a = cert_get_a4(z), P = cert_get_P(z); GEN x = gel(P,1), xx = Fp_sqr(x, N); GEN y = gel(P,2), yy = Fp_sqr(y, N); return Fp_sub(yy, Fp_mul(x, Fp_add(xx,a,N), N), N); } INLINE GEN cert_get_E(GEN x) { return mkvec2(cert_get_a4(x), cert_get_a6(x)); } INLINE GEN cert_get_J(GEN x) { GEN a = cert_get_a4(x), b = cert_get_a6(x), N = cert_get_N(x); return Fp_ellj(a, b, N); } /* "Twist factor". Does not cover J = 0, 1728 */ static GEN cert_get_lambda(GEN z) { GEN N, J, a, b, A, B; J = cert_get_J(z); N = cert_get_N(z); a = cert_get_a4(z); b = cert_get_a6(z); Fp_ellj_to_a4a6(J, N, &A, &B); return Fp_div(Fp_mul(a,B,N), Fp_mul(b,A,N), N); } /* Solves for T such that if [A, B] = [3*J*(1728-J), 2*J*(1728-J)^2] and you let L = T^3 + A*T + B, A = A*L^2, B = B*L^3 then x == TL and y == L^2 */ static GEN cert_get_T(GEN z) { GEN N = cert_get_N(z), x = cert_get_x(z); GEN l = cert_get_lambda(z); /* l = 1/L */ return Fp_mul(x, l, N); } /* database for all invariants, stolen from Hamish's code */ static GEN polmodular_db_init_allinv(void) { const long DEFAULT_MODPOL_DB_LEN = 32; GEN a, b = cgetg(39+1, t_VEC); long i; for (i = 1; i < 40; i++) gel(b,i) = zerovec_block(DEFAULT_MODPOL_DB_LEN); a = zerovec_block(DEFAULT_MODPOL_DB_LEN); return mkvec2(a, b); } /* Given D and a database of modular polynomials, return polclass(D, inv) */ static GEN D_polclass(long D, long inv, GEN *db) { GEN HD, t = mkvec2(gel(*db, 1), inv == 0? gen_0: gmael(*db, 2, inv)); HD = polclass0(D, inv, 0, &t); gel(*db, 1) = gel(t,1); if (inv != 0) gmael(*db, 2, inv) = gel(t,2); return HD; } static GEN NqE_check(GEN N, GEN q, GEN a, GEN b, GEN s) { GEN mP, sP, P = random_FpE(a, b, N); GEN PJ = mkvec3(gel(P,1), gel(P,2), gen_1); sP = FpJ_mul(PJ, s, a, N); if (FpJ_is_inf(sP)) return NULL; mP = FpJ_mul(sP, q, a, N); return FpJ_is_inf(mP)? mkvec2(a, P): NULL; } /* Find an elliptic curve E modulo N and a point P on E which corresponds to * the ith element of the certificate; uses N, D, m, q, J from previous steps. * All computations are modulo N unless stated otherwise */ /* g is a quadratic and cubic nonresidue modulo N */ static GEN j0_find_g(GEN N) { GEN n = diviuexact(subiu(N, 1), 3); for(;;) { GEN g = randomi(N); if (kronecker(g, N) == -1 && !equali1(Fp_pow(g, n, N))) return g; } } static GEN find_EP(GEN N, long D, GEN q, GEN g, GEN J, GEN s) { GEN A0, B0; Fp_ellj_to_a4a6(J, N, &A0, &B0); for(;;) { /* expect one iteration: not worth saving the A's and B's */ GEN gg, v, A = A0, B = B0; long i; if ((v = NqE_check(N, q, A, B, s))) return v; switch (D_get_wD(D)) { case 2: gg = Fp_sqr(g, N); A = Fp_mul(A, gg, N); B = Fp_mul(Fp_mul(B, gg, N), g, N); if ((v = NqE_check(N, q, A, B, s))) return v; break; case 4: for (i = 1; i < 4; i++) { A = Fp_mul(A, g, N); if ((v = NqE_check(N, q, A, B, s))) return v; } break; default: /* 6 */ B = Fp_mul(B, g, N); if ((v = NqE_check(N, q, A, B, s))) return v; g = j0_find_g(N); for (i = 1; i < 6; i++) { B = Fp_mul(B, g, N); if (i == 3) continue; if ((v = NqE_check(N, q, A, B, s))) return v; } break; } } } /* Return the genus field. If real is set only the real part */ static GEN genusfield(GEN Dfac, GEN sq, GEN p, long real) { long i, j, l = lg(Dfac), dn, n = 0; GEN sn, s = gen_0, R = cgetg(l-1+!real, t_VECSMALL); for (i = 1; i < l; i++) if (Dfac[i] < 0) { n = i; break; } if (n == 0) pari_err_BUG("realgenusfield"); dn = Dfac[n]; sn = gel(sq, n); for (j = i = 1; i < l; i++) if (i != n) { long d = Dfac[i]; GEN si = gel(sq,i); R[j++] = d > 0 ? d : d * dn; s = Fp_add(s, d > 0? si: Fp_mul(si, sn, p), p); } if (!real) { R[j++] = dn; s = Fp_add(s,sn, p); } return mkvec2(R, s); } static GEN realpart(GEN P, GEN R) { GEN G = galoisinit(rnfequation(P,R), NULL); GEN T = galoisfixedfield(G, gel(gal_get_gen(G),2), 1, -1); setvarn(T,1); return polredbest(T,0); } static GEN dihedralpol(long D, long l) { GEN P = quadpoly0(utoineg(-D), 1); GEN bnf = Buchall(P, 1, BIGDEFAULTPREC); GEN x = bnrclassfield(bnf, utoipos(l), 0, BIGDEFAULTPREC); pari_APPLY_same(realpart(P, gel(x,i))) } static GEN FpX_classtower_oneroot(GEN P, GEN Dinfo, GEN Dfac, GEN sq, GEN p) { long D = Dinfo_get_D(Dinfo), h = Dinfo_get_h(Dinfo); if (degpol(P) > 1) { long real = !modinv_is_double_eta(Dinfo_get_bi(Dinfo)); GEN V = genusfield(Dfac, sq, p, real), v = gel(V,1), R = gel(V,2); GEN N = NULL; long i, l = lg(v); for (i = 1; i < l; i++) { GEN Q = deg2pol_shallow(gen_1, gen_0, stoi(-v[i]), 1); if (!N) N = Q; else { GEN cm = polcompositum0(N,Q,3); N = gel(cm,1); P = QXY_QXQ_evalx(P,gmael(cm,2,2),N); } P = liftpol_shallow(gmael(nffactor(N,P),1,1)); } if (h%3 == 0 && (!N || degpol(N)*3=degpol(P)) break; } } if (N) P = FpXY_evalx(Q_primpart(P), R, p); } return P; } GEN ecpp_step2_worker(GEN S, GEN HD, GEN primelist, long dbg) { pari_sp av = avma; pari_timer ti; GEN J, t, s, EP, rt, res; GEN N = NDmqg_get_N(S), Dinfo = NDmqg_get_Dinfo(S); GEN m = NDmqg_get_m(S), q = NDmqg_get_q(S); GEN g = NDmqg_get_g(S), sq = NDmqg_get_sqrt(S); long D = Dinfo_get_D(Dinfo), inv = Dinfo_get_bi(Dinfo); GEN Dfacp = Dfac_to_p(Dinfo_get_Dfac(Dinfo), primelist); long C2 = 0, C3 = 0, C4 = 0, D1 = 0; GEN P, c = getrand(); setrand(gen_1); /* for reproducibility */ /* C2: Find a root modulo N of polclass(D,inv) */ if (dbg >= 2) timer_start(&ti); P = FpX_classtower_oneroot(HD, Dinfo, Dfacp, sq, N); if (dbg >= 2) C2 = timer_delay(&ti); rt = FpX_oneroot_split(P, N); if (dbg >= 2) C3 = timer_delay(&ti); /* C3: Convert root from previous step into the appropriate j-invariant */ J = Fp_modinv_to_j(rt, inv, N); /* root of polclass(D) */ if (dbg >= 2) C4 = timer_delay(&ti); /* D1: Find an elliptic curve E with a point P satisfying the theorem */ s = diviiexact(m, q); EP = find_EP(N, D, q, g, J, s); if (dbg >= 2) D1 = timer_delay(&ti); /* D2: Compute for t and s */ t = subii(addiu(N, 1), m); /* t = N+1-m */ res = mkvec2(mkvec5(N, t, s, gel(EP,1), gel(EP,2)),mkvecsmall4(C2,C3,C4,D1)); setrand(c); return gerepilecopy(av, res); } /* This uses [N, D, m, q] from step 1 to find the appropriate j-invariants * to be used in step 3. Step 2 is divided into substeps 2a, 2b, 2c */ static GEN ecpp_step2(GEN step1, GEN *X0, GEN primelist) { long j, Dprev = 0; pari_timer ti; GEN perm = gen_indexsort(step1, NULL, &sort_NDmq_by_D); GEN step2 = cgetg(lg(step1), t_VEC); GEN HD = NULL, db = polmodular_db_init_allinv(); long ls = lg(step2), pending = 0; GEN worker; struct pari_mt pt; GEN Hi = cgetg(ls, t_VEC); for (j = 1; j < ls; j++) { long i = uel(perm, j); GEN S = gel(step1, i); GEN Dinfo = NDmqg_get_Dinfo(S); long D = Dinfo_get_D(Dinfo), inv = Dinfo_get_bi(Dinfo); /* C1: Find the appropriate class polynomial modulo N */ dbg_mode() timer_start(&ti); if (D != Dprev) HD = D_polclass(D, inv, &db); dbg_mode() { GEN N = NDmqg_get_N(S); long tt = timer_record(X0, "C1", &ti); err_printf(ANSI_BRIGHT_GREEN "\n[ %3d | %4ld bits]" ANSI_RESET, i, expi(N)); err_printf(ANSI_GREEN " D = %8ld poldeg = %4ld" ANSI_RESET, D, degpol(HD)); if (D == Dprev) err_printf(" %6ld", tt); else err_printf(ANSI_BRIGHT_WHITE " %6ld" ANSI_RESET, tt); } gel(Hi, i) = HD; } gunclone_deep(db); worker = snm_closure(is_entry("_ecpp_step2_worker"), mkvec2(primelist,stoi(DEBUGLEVEL))); mt_queue_start_lim(&pt, worker, ls-1); for (j = 1; j < ls || pending; j++) { long jj; GEN S = gel(step1, j), HD = gel(Hi, j), done; mt_queue_submit(&pt, j, j < ls ? mkvec2(S, HD) : NULL); done = mt_queue_get(&pt, &jj, &pending); if (!done) continue; dbg_mode() { GEN T = gel(done,2); GEN N = NDmqg_get_N(gel(step1, jj)); err_printf(ANSI_BRIGHT_GREEN "\n[ %3d | %4ld bits]" ANSI_RESET, jj, expi(N)); err_printf(" %6ld", time_record(X0, "C2", T[1])); err_printf(" %6ld", time_record(X0, "C3", T[2])); err_printf(" %6ld", time_record(X0, "C4", T[3])); err_printf(" %6ld", time_record(X0, "D1", T[4])); } gel(step2, jj) = gel(done,1); } mt_queue_end(&pt); return step2; } /* end of functions for step 2 */ GEN ecpp_sqrt_worker(GEN p, GEN g, GEN N) { GEN r = Fp_sqrt_i(p, g, N); return r ? r: gen_0; } static void ecpp_parsqrt(GEN N, GEN param, GEN kroP, GEN sqrtlist, GEN g, long nb, long *nbsqrt) { GEN primelist = ecpp_param_get_primelist(param); GEN ordinv = ecpp_param_get_primeord(param); long i, k, l = lg(ordinv), n = *nbsqrt+1; GEN worker = snm_closure(is_entry("_ecpp_sqrt_worker"), mkvec2(g, N)); GEN W = cgetg(nb+1,t_VEC), V; for (i=n, k=1; k<=nb && i 0) gel(W,k++) = stoi(primelist[pi]); } *nbsqrt=i-1; setlg(W,k); V = gen_parapply(worker, W); for (i=n, k=1; k<=nb && i 0) { dbg_mode() err_printf(ANSI_MAGENTA "S" ANSI_RESET); if (!signe(gel(V,k))) pari_err_BUG("D_find_discsqrt"); /* possible if N composite */ gel(sqrtlist,pi) = gel(V,k++); } } } /* start of functions for step 1 */ /* This finds the square root of D modulo N [given by Dfac]: find the square * root modulo N of each prime p dividing D and multiply them out */ static GEN D_find_discsqrt(GEN N, GEN param, GEN Dfac, GEN kroP, GEN sqrtlist, GEN g, long *nbsqrt) { GEN s = NULL, sj; long i, l = lg(Dfac); for (i = 1; i < l; i++) { long j = Dfac[i]; while(!signe(gel(sqrtlist,j))) ecpp_parsqrt(N, param, kroP, sqrtlist, g, mt_nbthreads(), nbsqrt); sj = gel(sqrtlist,j); s = s? Fp_mul(s, sj, N): sj; } return s;/* != NULL */ } /* Given a solution U, V to U^2 + |D|V^2 = 4N, this find all the possible cardinalities of the elliptic curves over the finite field F_N whose endomorphism ring is isomorphic to the maximal order in the imaginary quadratic number field K = Q(sqrt(D)). ??? */ static GEN NUV_find_m(GEN Dinfo, GEN N, GEN U, GEN V, long wD) { GEN m, Nplus1 = addiu(N, 1), u = U, mvec = cgetg(wD+1, t_VEC); long i; for (i = 0; i < wD; i++) { if (odd(i)) m = subii(Nplus1, u); else { if (wD == 4 && i==2) u = shifti(V, 1); else if (wD == 6 && i==2) u = shifti(submuliu(U, V, 3), -1); else if (wD == 6 && i==4) u = shifti(addmuliu(U, V, 3), -1); m = addii(Nplus1, u); } gel(mvec, i+1) = mkvec2(Dinfo, m); } return mvec; } /* Populates Dmbatch with Dmvec's -- whose components are of the form [D,m], where m is a cardinalities of an elliptic curve with endomorphism ring isomorphic to the maximal order of imaginary quadratic K = Q(sqrt(D)). It returns 0 if: * Any of the p* dividing D is not a quadratic residue mod N * Cornacchia cannot find a solution U^2 + |D|V^2 = 4N. Otherwise, it returns the number of cardinalities added to Dmbatch. Finally, sqrtlist and g help compute the square root modulo N of D. */ static long D_collectcards(GEN N, GEN param, GEN* X0, GEN Dinfo, GEN sqrtlist, GEN g, GEN Dmbatch, GEN kroP, long *nbsqrt) { long i, l, corn_succ, wD, D = Dinfo_get_D(Dinfo); GEN U, V, sqrtofDmodN, Dfac = Dinfo_get_Dfac(Dinfo); pari_timer ti; /* A1: Check (p*|N) = 1 for all primes dividing D */ l = lg(Dfac); for (i = 1; i < l; i++) { long j = Dfac[i]; if (kroP[j] < 0) return 0; } /* A3: Get square root of D mod N */ dbg_mode() timer_start(&ti); sqrtofDmodN = D_find_discsqrt(N, param, Dfac, kroP, sqrtlist, g, nbsqrt); dbg_mode() timer_record(X0, "A3", &ti); /* A5: Use square root with Cornacchia to solve U^2 + |D|V^2 = 4N */ dbg_mode() timer_start(&ti); corn_succ = cornacchia2_sqrt( utoi(labs(D)), N, sqrtofDmodN, &U, &V); dbg_mode() timer_record(X0, "A5", &ti); if (!corn_succ) { dbg_mode1() err_printf(ANSI_YELLOW "c" ANSI_RESET); return 0; } /* A6: Collect the w(D) cardinalities of E/(F_N) with CM by D */ dbg_mode() err_printf(ANSI_BRIGHT_YELLOW "D" ANSI_RESET); wD = D_get_wD(D); vectrunc_append_batch(Dmbatch, NUV_find_m(Dinfo,N,U,V,wD)); return wD; } /* Compute (S(16N, 2) + S(4096N, 4) + 4)\4 + 1, where S is the nth root * rounded down. This is at most one more than (N^1/4 + 1)^2. */ static GEN ecpp_qlo(GEN N) { GEN a = sqrtnint(shifti(N, 4), 2); GEN b = sqrtnint(shifti(N, 12), 4); return addiu(shifti(addii(a, b), -2), 2); } static long lessthan_qlo(void* E, GEN Dmq) { return (cmpii(gel(Dmq,3), (GEN)E) < 0); } static long gained_bits(void* E, GEN Dmq) { return (expi(gel(Dmq,3)) <= (long)E); } /* Input: Dmqvec * Output: Dmqvec such that q satisfies (N^1/4 + 1)^2 < q < N/2 */ static GEN Dmqvec_slice(GEN N, GEN Dmqvec) { long lo, hi; gen_sort_inplace(Dmqvec, NULL, &sort_Dmq_by_q, NULL); /* sort wrt q */ lo = zv_binsearch0((void*)ecpp_qlo(N), &lessthan_qlo, Dmqvec); lo++; if (lo >= lg(Dmqvec)) return NULL; hi = zv_binsearch0((void*)(expi(N)-1), &gained_bits, Dmqvec); if (hi == 0) return NULL; return vecslice(Dmqvec, lo, hi); } /* Given a Dmvec of [D,m]'s, simultaneously remove all prime factors of each * m less then BOUND_PRIMORIAL. This implements Franke 2004: Proving the * Primality of Very Large Numbers with fastECPP */ static GEN Dmvec_batchfactor(GEN Dmvec, GEN primorial) { long i, l = lg(Dmvec); GEN leaf, v = cgetg(l, t_VEC); for (i = 1; i < l; i++) { /* cheaply remove powers of 2 */ GEN m = gmael(Dmvec, i, 2); long v2 = vali(m); gel(v,i) = v2? shifti(m,-v2): m; } leaf = Z_ZV_mod_tree(primorial, v, ZV_producttree(v)); /* Go through each leaf and remove small factors. */ for (i = 1; i < l; i++) { GEN q = gel(v,i), Dm = gel(Dmvec,i), L = gel(leaf,i); while (!equali1(L)) { L = gcdii(q, L); q = diviiexact(q, L); } gel(v,i) = mkvec3(gel(Dm,1), gel(Dm,2), q); } return v; } /* return good parameters [maxsqrt, maxpcdg, tdivexp] for ecpp(N) */ static GEN tunevec(long expiN, GEN param) { GEN T = ecpp_param_get_tune(param); long i, n = lg(T)-1; for (i = 1; i < n; i++) { GEN x = gel(T,i); if (expiN <= x[4]) return x; } return gel(T,n); } static long tunevec_tdivbd(long expiN, GEN param) { return uel(tunevec(expiN, param), 3); } static long tunevec_batchsize(long expiN, GEN param) { long t, b = 28 - tunevec_tdivbd(expiN, param); if (b < 0) return expiN; t = expiN >> b; return t < 1? 1: t; } static GEN Dmbatch_factor_Dmqvec(GEN N, long expiN, GEN* X0, GEN Dmbatch, GEN param) { pari_sp av = avma; pari_timer ti; GEN Dmqvec, primorial_vec = ecpp_param_get_primorial_vec(param); GEN primorial = gel(primorial_vec, tunevec_tdivbd(expiN, param)-19); /* B1: Factor by batch */ dbg_mode() timer_start(&ti); Dmqvec = Dmvec_batchfactor(Dmbatch, primorial); dbg_mode() timer_record(X0, "B1", &ti); /* B2: For each batch, remove cardinalities lower than (N^(1/4)+1)^2 * and cardinalities in which we didn't win enough bits */ Dmqvec = Dmqvec_slice(N, Dmqvec); if (!Dmqvec) return gc_NULL(av); /* nothing is left */ return gerepilecopy(av, Dmqvec); } GEN ecpp_ispsp_worker(GEN N) { return mkvecsmall(BPSW_psp_nosmalldiv(N)); } static GEN mkNDmqg(GEN z, GEN N, GEN Dmq, GEN g, GEN sqrtlist) { GEN Dinfo = gel(Dmq,1), sq = Dfac_to_roots(Dinfo_get_Dfac(Dinfo),sqrtlist); GEN NDmqg = mkcol6(N, Dinfo, gel(Dmq,2), gel(Dmq,3), g, sq); return mkvec2(NDmqg, z); } /* expi(N) > 64. Return [ NDmqg, N_downrun(q) ]; NDmqg is a vector of the form * [N,D,m,q,g,sqrt]. For successive D, find a square root of D mod N (g is a * quadratic nonresidue), solve U^2 + |D|V^2 = 4N, then find candidates for m. * When enough m's, batch-factor them to produce the q's. If one of the q's is * pseudoprime, recursive call with N = q. May return gen_0 at toplevel * => N has a small prime divisor */ static GEN N_downrun(GEN N, GEN param, GEN worker, GEN *X0, long *depth, long persevere, long stopat) { pari_timer T, ti; long lgdisclist, lprimelist, nbsqrt = 0, t, i, j, expiN = expi(N); long persevere_next = 0, FAIL = 0; ulong maxpcdg; GEN primelist, uprimelist, disclist, sqrtlist, g, Dmbatch, kroP, Np; dbg_mode() timer_start(&T); (*depth)++; /* we're going down the tree. */ maxpcdg = ecpp_param_get_maxpcdg(param); primelist = ecpp_param_get_primelist(param); uprimelist = ecpp_param_get_uprimelist(param); disclist = ecpp_param_get_disclist(param); lgdisclist = lg(disclist); t = tunevec_batchsize(expiN, param); /* Precomputation for taking square roots, g needed for Fp_sqrt_i */ g = Fp_2gener(N); if (!g) return gen_0; /* Composite if this happens. */ /* Initialize sqrtlist for this N. */ lprimelist = lg(primelist); sqrtlist = zerovec(lprimelist-1); /* A2: Check (p*|N) = 1 for all p */ dbg_mode() timer_start(&ti); /* kroP[i] will contain (primelist[i] | N) */ kroP = cgetg(lprimelist,t_VECSMALL); switch(mod8(N)) { /* primelist[1,2,3] = [8,-4,-8]; N is odd */ case 1: kroP[1] = kroP[2] = kroP[3] = 1; break; case 3: kroP[1] = -1; kroP[2] =-1; kroP[3] = 1; break; case 5: kroP[1] = -1; kroP[2] = 1; kroP[3] =-1; break; case 7: kroP[1] = 1; kroP[2] =-1; kroP[3] =-1; break; } Np = Z_ZV_mod_tree(N, gel(uprimelist,1), gel(uprimelist,2)); for(i=4; i': ']'; err_printf(ANSI_BRIGHT_CYAN "\n%c %3d | %4ld bits%c " ANSI_RESET, o, *depth, expiN, c); } /* Initialize Dmbatch, populated with candidate cardinalities in Phase I * (until #Dmbatch >= t); its elements will be factored on Phase II */ Dmbatch = vectrunc_init(t+7); /* Number of cardinalities so far; should always be equal to lg(Dmbatch)-1. */ /* i determines which discriminant we are considering. */ i = 1; while (!FAIL) { pari_timer F; long lgDmqlist, last_i = i, numcard = 0; /* #Dmbatch */ GEN Dmqlist; /* Dmbatch begins "empty", but keep the allocated memory. */ setlg(Dmbatch, 1); /* PHASE I: Go through the D's and search for candidate m's. * Fill up Dmbatch until there are at least t elements. */ while (i < lgdisclist ) { GEN Dinfo = gel(disclist, i); long n; if (!persevere && Dinfo_get_pd(Dinfo) > maxpcdg) { FAIL = 1; break; } n = D_collectcards(N,param, X0, Dinfo, sqrtlist, g, Dmbatch, kroP, &nbsqrt); if (n < 0) return gen_0; last_i = i++; numcard += n; if (numcard >= t) break; } /* We have exhausted disclist and there are no card. to be factored */ if (numcard <= 0 && (FAIL || i >= lgdisclist)) break; /* PHASE II: Find the corresponding q's for the m's found. Use Dmbatch */ /* Find coresponding q of the candidate m's. */ dbg_mode() timer_start(&F); Dmqlist = Dmbatch_factor_Dmqvec(N, expiN, X0, Dmbatch, param); if (Dmqlist == NULL) continue; /* none left => next discriminant. */ /* If we are cheating by adding class numbers, sort by class number */ if (Dinfo_get_pd(gel(disclist, last_i)) > maxpcdg) gen_sort_inplace(Dmqlist, NULL, &sort_Dmq_by_cnum, NULL); /* Check pseudoprimality before going down. */ lgDmqlist = lg(Dmqlist); for (j = 1; j < lgDmqlist; j++) { GEN z, Dmq, q; struct pari_mt pt; pari_timer ti2; long running, stop = 0, pending = 0; mt_queue_start_lim(&pt, worker, lgDmqlist-j); dbg_mode() timer_start(&ti2); while ((running = (!stop && j < lgDmqlist)) || pending) { long jj; GEN done; mt_queue_submit(&pt, j, running ? mkvec(gmael(Dmqlist,j,3)) : NULL); done = mt_queue_get(&pt, &jj, &pending); if (done) { if (done[1] == 0) { dbg_mode() err_printf(ANSI_WHITE "." ANSI_RESET); } else if (!stop || jj < stop) stop = jj; } j++; } mt_queue_end(&pt); dbg_mode() timer_record(X0, "B3", &ti2); if (!stop && j >= lgDmqlist) break; j = stop; Dmq = gel(Dmqlist,j); q = gel(Dmq,3); dbg_mode() { err_printf(ANSI_BRIGHT_RED "\n %5ld bits " ANSI_RESET, expi(q)-expiN); err_printf(" D = %ld", Dmq_get_D(Dmq)); err_printf(ANSI_BRIGHT_BLUE " h = %ld" ANSI_RESET, Dmq_get_h(Dmq)); } /* q is pseudoprime */ if (expi(q) < stopat) z = gen_1; /* q is prime; sentinel */ else { z = N_downrun(q, param, worker, X0, depth, persevere_next, stopat); if (!z) { dbg_mode() { char o = persevere? '<': '[', c = persevere? '>': ']'; err_printf(ANSI_CYAN "\n%c %3d | %4ld bits%c " ANSI_RESET, o, *depth, expiN, c); } continue; /* downrun failed */ } if (isintzero(z)) return z; } return mkNDmqg(z, N, Dmq, g, sqrtlist); /* SUCCESS */ } if (i >= lgdisclist) break; /* discriminants exhausted: FAIL */ if (Dinfo_get_pd(gel(disclist, last_i)) > maxpcdg) { dbg_mode() err_printf(ANSI_BRIGHT_RED " !" ANSI_RESET); persevere_next = 1; } } /* FAILED: Out of discriminants. */ umael(*X0, 3, 1)++; /* FAILS++ */ dbg_mode() err_printf(ANSI_BRIGHT_RED " X" ANSI_RESET); (*depth)--; return NULL; } /* x: the output of the (recursive) downrun function; return a vector * whose components are [N, D, m, q, g] */ static GEN ecpp_flattencert(GEN x, long depth) { long i, l = depth+1; GEN ret = cgetg(l, t_VEC); for (i = 1; i < l; i++) { gel(ret, i) = gel(x,1); x = gel(x,2); } return ret; } /* Call the first downrun then unravel the skeleton of the certificate. * Assume expi(N) < 64. This returns one of the following: * - a vector of the form [N, D, m, q, y] * - gen_0 (if N is composite) * - NULL (if FAIL) */ static GEN ecpp_step1(GEN N, GEN param, GEN* X0, long stopat) { pari_sp av = avma; long depth = 0; GEN worker = strtofunction("_ecpp_ispsp_worker"); GEN downrun = N_downrun(N, param, worker, X0, &depth, 1, stopat); if (downrun == NULL) return gc_NULL(av); if (typ(downrun) != t_VEC) return gen_0; return gerepilecopy(av, ecpp_flattencert(downrun, depth)); } /* The input is an integer N. It uses the precomputation step0 done in ecpp_step0. */ static GEN ecpp_param(GEN N, GEN param, long stopat) { GEN step1, answer, Tv, Cv, X0; pari_sp av = avma; long i, j; /* Check if N is pseudoprime to begin with. */ if (!BPSW_psp(N)) return gen_0; /* Check if we should even prove it. */ if (expi(N) < stopat) return N; /* Timers and Counters */ Tv = mkvec4(zero_zv(5), zero_zv(3), zero_zv(4), zero_zv(1)); Cv = mkvec4(zero_zv(5), zero_zv(3), zero_zv(4), zero_zv(1)); X0 = mkvec3(Tv, Cv, zero_zv(1)); step1 = ecpp_step1(N, param, &X0, stopat); if (step1 == NULL) return gc_NULL(av); if (typ(step1) != t_VEC) { set_avma(av); return gen_0; } answer = ecpp_step2(step1, &X0, ecpp_param_get_primelist(param)); dbg_mode() { for (i = 1; i < lg(Tv); i++) { GEN v = gel(Tv, i); long l = lg(v); for (j = 1; j < l; j++) { long t = umael3(X0,1, i,j), n = umael3(X0,2, i,j); if (!t) continue; err_printf("\n %c%ld: %16ld %16ld %16.3f", 'A'+i-1,j, t,n, (double)t/n); } } err_printf("\n" ANSI_BRIGHT_RED "\nFAILS: %16ld" ANSI_RESET "\n", umael(X0, 3, 1)); } return gerepilecopy(av, answer); } static const long ecpp_tune[][4]= { { 100, 2, 20, 500 }, { 350, 14, 21, 1000 }, { 450, 18, 21, 1500 }, { 750, 22, 22, 2000 }, { 900, 26, 23, 2500 }, { 1000, 32, 23, 3000 }, { 1200, 38, 24, 3500 }, { 1400, 44, 24, 4000 }, { 1600, 50, 24, 4500 }, { 1800, 56, 25, 5000 }, { 2000, 62, 25, 5500 }, { 2200, 68, 26, 6000 }, { 2400, 74, 26, 6500 }, { 2600, 80, 26, 7000 }, { 2800, 86, 26, 7500 }, { 3000, 92, 27, 8000 }, { 3200, 98, 27, 8500 }, { 3400, 104, 28, 9000 }, { 3600, 110, 28, 9500 }, { 3800, 116, 29, 10000 }, { 4000, 122, 29, 0 } }; /* assume N BPSW-pseudoprime */ GEN ecpp0(GEN C, long stopat) { pari_sp av = avma; long expiN, i, tunelen; GEN N = C, tune; /* Is it a partial certificate? */ if (typ(C) == t_VEC && check_ecppcert(C)) N = cert_get_qlast(C); if (typ(N) != t_INT) pari_err_TYPE("ecpp",C); /* Check if we should even prove it. */ expiN = expi(N); if (stopat < 64) stopat = 64; if (expiN < stopat) return C; tunelen = (expiN+499)/500; tune = cgetg(tunelen+1, t_VEC); for (i = 1; i <= tunelen && ecpp_tune[i-1][3]; i++) gel(tune,i) = mkvecsmall4(ecpp_tune[i-1][0], ecpp_tune[i-1][1], ecpp_tune[i-1][2], ecpp_tune[i-1][3]); for (; i <= tunelen; i++) gel(tune,i) = mkvecsmall4(100*(i+20),4*i+42,30,500*i); for(;;) { GEN C2, param, x = gel(tune, tunelen); param = ecpp_param_set(tune, x); C2 = ecpp_param(N, param, stopat); if (C2) return typ(C)==t_INT? C2: gerepilecopy(av, shallowconcat(C,C2)); x[1] *= 2; x[2] *= 2; x[3] = minss(x[3]+1, 30); } } GEN ecpp(GEN N) { return ecpp0(N, 0); } long isprimeECPP(GEN N) { pari_sp av = avma; if (!BPSW_psp(N)) return 0; return gc_long(av, !isintzero(ecpp(N))); } /* PARI ECPP Certificate -> Human-readable format */ static GEN cert_out(GEN x) { long i, l = lg(x); pari_str str; str_init(&str, 1); if (typ(x) == t_INT) { str_printf(&str, "%Ps is prime.\nIndeed, ispseudoprime(%Ps) = 1 and %Ps < 2^64.\n", x, x, x); return strtoGENstr(str.string); } for (i = 1; i < l; i++) { GEN xi = gel(x, i); str_printf(&str, "[%ld]\n", i); str_printf(&str, " N = %Ps\n", cert_get_N(xi)); str_printf(&str, " t = %Ps\n", cert_get_t(xi)); str_printf(&str, " s = %Ps\n", cert_get_s(xi)); str_printf(&str, "a = %Ps\n", cert_get_a4(xi)); str_printf(&str, "D = %Ps\n", cert_get_D(xi)); str_printf(&str, "m = %Ps\n", cert_get_m(xi)); str_printf(&str, "q = %Ps\n", cert_get_q(xi)); str_printf(&str, "E = %Ps\n", cert_get_E(xi)); str_printf(&str, "P = %Ps\n", cert_get_P(xi)); } return strtoGENstr(str.string); } /* PARI ECPP Certificate -> Magma Certificate * [* [* * N, |D|, -1, m, * [* a, b *], * [* x, y, 1 *], * [* [* q, 1 *] *] * *], ... *] */ static GEN magma_out(GEN x) { long i, n = lg(x)-1; pari_str ret; str_init(&ret, 1); if (typ(x) == t_INT) { str_printf(&ret, "Operation not supported."); return strtoGENstr(ret.string); } str_printf(&ret, "[* "); for (i = 1; i<=n; i++) { GEN xi = gel(x,i), E = cert_get_E(xi), P = cert_get_P(xi); str_printf(&ret, "[* %Ps, %Ps, -1, %Ps, ", cert_get_N(xi), negi(cert_get_D(xi)), cert_get_m(xi)); str_printf(&ret, "[* %Ps, %Ps *], ", gel(E,1), gel(E,2)); str_printf(&ret, "[* %Ps, %Ps, 1 *], ", gel(P,1), gel(P,2)); str_printf(&ret, "[* [* %Ps, 1 *] *] *]", cert_get_q(xi)); if (i != n) str_printf(&ret, ", "); } str_printf(&ret, " *]"); return strtoGENstr(ret.string); } /* Prints: label=(sign)hexvalue\n * where sign is + or - * hexvalue is value in hex, of the form: 0xABC123 */ static void primo_printval(pari_str *ret, const char* label, GEN value) { str_printf(ret, label); if (signe(value) >= 0) str_printf(ret, "=0x%P0X\n", value); else str_printf(ret, "=-0x%P0X\n", negi(value)); } /* Input: PARI ECPP Certificate / Output: PRIMO Certificate * * Let Y^2 = X^3 + aX + b be the elliptic curve over N with the point (x,y) * as described in the PARI certificate. * * If J != 0, 1728, PRIMO asks for [J,T], where T = a/A * B/b * x, * A = 3J(1728-J) and B = 2J(1728-J)^2. * * If J=0 or J=1728, PRIMO asks for [A,B,T]; we let A=a and B=b => T = x */ static GEN primo_out(GEN x) { long i, l = (typ(x) == t_INT) ? 1 : lg(x); pari_str ret; str_init(&ret, 1); str_printf(&ret, "[PRIMO - Primality Certificate]\nFormat=4\n"); str_printf(&ret, "TestCount=%ld\n\n[Comments]\n", l-1); str_printf(&ret, "Generated by %s\n",paricfg_version); str_printf(&ret, "https://pari.math.u-bordeaux.fr/\n\n[Candidate]\n"); if (typ(x) == t_INT) { str_printf(&ret, "N=0x%P0X\n", x); return strtoGENstr(ret.string); } str_printf(&ret, "N=0x%P0X\n\n", cert_get_N(gel(x,1))); for (i = 1; i < l; i++) { GEN a4, a6, N, Nover2, xi = gel(x,i); long Ais0, Bis0; str_printf(&ret, "[%ld]\n", i); N = cert_get_N(xi); Nover2 = shifti(N, -1); primo_printval(&ret, "S", cert_get_s(xi)); primo_printval(&ret, "W", cert_get_t(xi)); a4 = cert_get_a4(xi); Ais0 = isintzero(a4); a6 = cert_get_a6(xi); Bis0 = isintzero(a6); if (!Ais0 && !Bis0) { /* J != 0, 1728 */ primo_printval(&ret, "J", Fp_center_i(cert_get_J(xi), N, Nover2)); primo_printval(&ret, "T", cert_get_T(xi)); } else { if (!Ais0) a4 = Fp_center_i(a4, N, Nover2); if (!Bis0) a6 = Fp_center_i(a6, N, Nover2); primo_printval(&ret, "A", a4); primo_printval(&ret, "B", a6); primo_printval(&ret, "T", cert_get_x(xi)); } str_printf(&ret, "\n"); } return strtoGENstr(ret.string); } /* return 1 if q > (N^1/4 + 1)^2, 0 otherwise */ static long Nq_isvalid(GEN N, GEN q) { GEN c = subii(sqri(subiu(q,1)), N); if (signe(c) <= 0) return 0; /* (q-1)^2 > N; check that (N - (q-1)^2)^2 > 16Nq */ return (cmpii(sqri(c), shifti(mulii(N,q), 4)) > 0); } GEN primecertisvalid_ecpp_worker(GEN certi) { GEN N, W, mP, sP, r, m, s, a, P, q; if (lg(certi)-1 != 5) return gen_0; N = cert_get_N(certi); if (typ(N) != t_INT || signe(N) <= 0) return gen_0; switch(umodiu(N,6)) { case 1: case 5: break; /* Check if N is not divisible by 2 or 3 */ default: return gen_0; } W = cert_get_t(certi); if (typ(W) != t_INT) return gen_0; /* Check if W^2 < 4N (Hasse interval) */ if (!(cmpii(sqri(W), shifti(N,2)) < 0)) return gen_0; s = cert_get_s(certi); if (typ(s) != t_INT || signe(s) < 0) return gen_0; m = cert_get_m(certi); q = dvmdii(m, s, &r); /* Check m%s == 0 */ if (!isintzero(r)) return gen_0; /* Check q > (N^(1/4) + 1)^2 */ if (!Nq_isvalid(N, q)) return gen_0; a = cert_get_a4(certi); if (typ(a) != t_INT) return gen_0; P = cert_get_P(certi); if (typ(P) != t_VEC || lg(P) != 3) return gen_0; P = FpE_to_FpJ(P); /* Check sP != 0 and third component is coprime to N */ sP = FpJ_mul(P, s, a, N); if (!isint1(gcdii(gel(sP, 3), N))) return gen_0; /* Check mP == 0 */ mP = FpJ_mul(sP, q, a, N); if (!FpJ_is_inf(mP)) return gen_0; return q; } /* return 1 if 'cert' is a valid PARI ECPP certificate */ static long ecppisvalid_i(GEN cert) { const long trustbits = 64;/* a pseudoprime < 2^trustbits is prime */ long i, lgcert = lg(cert); GEN ql, q = gen_0, worker, check; if (typ(cert) == t_INT) { if (expi(cert) >= trustbits) return 0; /* >= 2^trustbits */ return BPSW_psp(cert); } if (typ(cert) != t_VEC || lgcert <= 1) return 0; ql = veclast(cert); if (lg(ql)-1 != 5) return 0; ql = cert_get_q(ql); if (expi(ql) >= trustbits || !BPSW_psp(ql)) return 0; worker = strtofunction("_primecertisvalid_ecpp_worker"); check = gen_parapply(worker, cert); for (i = 1; i < lgcert; i++) { GEN certi = gel(cert, i); GEN qq = gel(check,i), N = cert_get_N(certi); if (isintzero(qq)) return 0; if (i > 1 && !equalii(N, q)) return 0; /* N of this entry doesn't match q of previous */ q = qq; } return 1; } long ecppisvalid(GEN cert) { pari_sp av = avma; return gc_long(av, ecppisvalid_i(cert)); } GEN ecppexport(GEN cert, long flag) { switch(flag) { case 0: return cert_out(cert); case 1: return primo_out(cert); case 2: return magma_out(cert); } pari_err_FLAG("primecertexport"); return NULL;/*LCOV_EXCL_LINE*/ } pari-2.17.2/src/basemath/subcyclo.c0000644000175000017500000010054214676526175015553 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_subcyclo /*************************************************************************/ /** **/ /** 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; i 0; i--) { long p = P[i], e = E[i], cnd = cnd0; for ( ; e >= 2; e--) { long q = cnd / p; if (!F2v_coeff(bits, 1 + q)) break; cnd = q; } if (e == 1) { if (p == 2) e = 0; else { long h, g = pgener_Fl(p), q = cnd / p; h = Fl_mul(g-1, Fl_inv(q % p, p), p); /* 1+h*q = g (mod p) */ if (F2v_coeff(bits, 1 + h*q)) e = 0; } } if (e) f *= upowuu(p, e); } return gc_long(av,f); } long znstar_conductor(GEN H) { return znstar_conductor_bits(gel(H,3)); } /* 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, c = 0, card = znstar_order(H), 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); } set_avma(ltop); return cosets; } static GEN znstar_quotient(long n, long phi_n, GEN H, GEN R, ulong l) { long i, j, k, c = 0, card = znstar_order(H), index = phi_n/card; GEN cosets = cgetg(index+1,t_VECSMALL), mult = cgetg(index+1, t_VEC); GEN bits = zero_F2v(n), vbits= zero_F2m_copy(n,index); 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, gel(vbits,k), c); F2v_add_inplace(bits, gel(vbits,k)); } for (k = 1; k <= index; k++) { GEN v = cgetg(index+1, t_VECSMALL); for (j = 1; j <= index; j++) { long s = Fl_mul(cosets[k],cosets[j],n); for (i = 1; i <= index; i++) if (F2v_coeff(gel(vbits,i),s)) break; v[j] = R[i]; } gel(mult,k) = v; } return Flv_Flm_polint(R, mult, l, 0); } /* return n s.t. x^n in H */ static ulong order_H_x(GEN H, ulong x, GEN D, ulong *xn) { ulong i, l = lg(D), f = H[1], y = x; /* = x^D[1] */ *xn = x; if (F2v_coeff(H, y)) return D[1]; for (i = 2; i < l; i++) { /* TODO: could cache the x^delta[i] incrementally */ y = Fl_mul(y, Fl_powu(x, D[i]-D[i-1], f), f); if (F2v_coeff(H, y)) { if (xn) *xn = y; return D[i]; } } pari_err_BUG("znsubgroupgenerators [order_H_x]"); return 0;/*LCOV_EXCL_LINE*/ } /* If H2 = (0), return 0. Else find an x in H2 of maximal order o in H2/H1; * if flag is set, make sure that x has also order o in (Z/fZ)^* */ static ulong max_order_ele(GEN H1, GEN H2, GEN D, ulong *po, long flag) { ulong x, h, n = F2v_hamming(H2), f = H1[1], O = 0, X = 0, XO = 0; if (!n) return 0; for (x = 2; x < f; x++) if (F2v_coeff(H2, x)) { ulong xo, o = order_H_x(H1, x, D, &xo); if (o > O) { O = o; X = x; XO = xo; if (o == n) break; } } /* X of maximal order O in H2/H1 */ *po = O; if (!flag || XO == 1) return X; /* find h in H1 s.t. (Xh)^o=1 */ x = Fl_inv(XO, f); for (h = 1;; h++) /* stops for h < f */ if (F2v_coeff(H1, h) && x == Fl_powu(h, O, f)) break; return Fl_mul(X, h, f); } /* x not in H. Replace H in place by the subgroup generated by H and x, * which has order o > 1 in G/H */ static void enlarge_H(GEN H, ulong x, ulong o) { pari_sp av = avma; ulong i, j, l = lg(H), f = H[1]; GEN H1 = vecsmall_copy(H), y = Fl_powers(x, o-1, f); for (i = 1; i < f; i++) if (F2v_coeff(H, i)) for (j = 2; j <= o; j++) F2v_set(H1, Fl_mul(i, y[j], f)); for (i = 2; i < l; i++) H[i] = H1[i]; set_avma(av); } /* H F2v subgroup of (Z/fZ)^*: a in H <=> H[a] = 1 * Return generators. If flag is set, they generate the cyclic components */ GEN znsubgroupgenerators(GEN H, long flag) { pari_sp av = avma; ulong f, g, o; GEN H1, H2, z = const_vecsmall(0,0), D; switch(typ(H)) { case t_VECSMALL: H = Flv_to_F2v(H); break; case t_VEC: if (RgV_is_ZV(H)) { H = ZV_to_F2v(H); break; } default: pari_err_TYPE("znsubgroupgenerators", H); } f = H[1]; z = cgetg(1, t_VECSMALL); D = divisorsu(F2v_hamming(H)); H1 = zero_F2v(f); F2v_set(H1, 1); H2 = H; while ((g = max_order_ele(H1, H2, D, &o, flag))) { z = vecsmall_append(z, g); enlarge_H(H1, g, o); F2v_negimply_inplace(H2, H1); /* H2 <- H2 - H1 */ } return gerepileupto(av, zv_to_ZV(z)); } /*************************************************************************/ /** **/ /** znstar/HNF interface **/ /** **/ /*************************************************************************/ static long mod_to_small(GEN x) { return itos(typ(x) == t_INTMOD ? gel(x,2): x); } static GEN vecmod_to_vecsmall(GEN x) { pari_APPLY_long(mod_to_small(gel(x,i))) } /* Convert a true znstar output by znstar to a `small znstar' */ GEN znstar_small(GEN zn) { GEN Z = cgetg(4,t_VEC); gel(Z,1) = icopy(gmael3(zn,3,1,1)); gel(Z,2) = vec_to_vecsmall(gel(zn,2)); gel(Z,3) = vecmod_to_vecsmall(gel(zn,3)); return Z; } /* Compute generators for the subgroup of (Z/nZ)* given in HNF. */ GEN znstar_hnf_generators(GEN Z, GEN M) { long j, h, l = lg(M); GEN gen = cgetg(l, t_VECSMALL); pari_sp ltop = avma; GEN zgen = gel(Z,3); ulong n = itou(gel(Z,1)); for (j = 1; j < l; j++) { GEN Mj = gel(M,j); gen[j] = 1; for (h = 1; h < l; h++) { ulong u = itou(gel(Mj,h)); if (!u) continue; gen[j] = Fl_mul(uel(gen,j), Fl_powu(uel(zgen,h), u, n), n); } } set_avma(ltop); return gen; } GEN znstar_hnf(GEN Z, GEN M) { return znstar_generate(itos(gel(Z,1)),znstar_hnf_generators(Z,M)); } GEN znstar_hnf_elts(GEN Z, GEN H) { pari_sp ltop = avma; GEN G = znstar_hnf(Z,H); long n = itos(gel(Z,1)); return gerepileupto(ltop, znstar_elts(n,G)); } /*************************************************************************/ /** **/ /** polsubcyclo **/ /** **/ /*************************************************************************/ static GEN gscycloconductor(GEN g, long n, long flag) { if (flag==2) retmkvec2(gcopy(g), stoi(n)); return g; } static long lift_check_modulus(GEN H, long n) { long h; switch(typ(H)) { case t_INTMOD: if (!equalsi(n, gel(H,1))) pari_err_MODULUS("galoissubcyclo", stoi(n), gel(H,1)); H = gel(H,2); /* fall through */ case t_INT: h = smodis(H,n); if (ugcd(h,n) != 1) pari_err_COPRIME("galoissubcyclo", H,stoi(n)); return h ? h: 1; } pari_err_TYPE("galoissubcyclo [subgroup]", H); return 0;/*LCOV_EXCL_LINE*/ } /* Compute z^ex using the baby-step/giant-step table powz * with only one multiply. * In the modular case, the result is not reduced. */ static GEN polsubcyclo_powz(GEN powz, long ex) { long m = lg(gel(powz,1))-1, q = ex/m, r = ex%m; /*ex=m*q+r*/ GEN g = gmael(powz,1,r+1), G = gmael(powz,2,q+1); return (lg(powz)==4)? mulreal(g,G): gmul(g,G); } static GEN polsubcyclo_complex_bound(pari_sp av, GEN V, long prec) { GEN pol = real_i(roots_to_pol(V,0)); return gerepileuptoint(av, ceil_safe(gsupnorm(pol,prec))); } /* Newton sums mod le. if le==NULL, works with complex instead */ static GEN polsubcyclo_cyclic(long n, long d, long m ,long z, long g, GEN powz, GEN le) { GEN V = cgetg(d+1,t_VEC); ulong base = 1; long i,k; pari_timer ti; if (DEBUGLEVEL >= 6) timer_start(&ti); for (i=1; i<=d; i++, base = Fl_mul(base,z,n)) { pari_sp av = avma; long ex = base; GEN s = gen_0; for (k=0; k= 6) timer_printf(&ti, "polsubcyclo_cyclic"); return V; } struct _subcyclo_orbits_u { GEN bab, gig; ulong l; ulong s; long m; }; static void _Fl_subcyclo_orbits(void *E, long k) { struct _subcyclo_orbits_u *D = (struct _subcyclo_orbits_u *) E; ulong l = D->l; long q = k/D->m, r = k%D->m; /*k=m*q+r*/ ulong g = uel(D->bab,r+1), G = uel(D->gig,q+1); D->s = Fl_add(D->s, Fl_mul(g, G, l), l); } /* Newton sums mod le. if le==NULL, works with complex instead */ static GEN Fl_polsubcyclo_orbits(long n, GEN H, GEN O, ulong z, ulong l) { long i, d = lg(O); GEN V = cgetg(d,t_VECSMALL); struct _subcyclo_orbits_u D; long m = 1+usqrt(n); D.l = l; D.m = m; D.bab = Fl_powers(z, m, l); D.gig = Fl_powers(uel(D.bab,m+1), m-1, l); for(i=1; ipowz; GEN *s = data->s; if (!data->count) data->ltop = avma; *s = gadd(*s, polsubcyclo_powz(powz,k)); data->count++; if ((data->count & 0xffUL) == 0) *s = gerepileupto(data->ltop, *s); } /* Newton sums mod le. if le==NULL, works with complex instead */ static GEN polsubcyclo_orbits(long n, GEN H, GEN O, GEN powz, GEN le) { long i, d = lg(O); GEN V = cgetg(d,t_VEC); struct _subcyclo_orbits_s data; long lle = le?lg(le)*2+1: 2*lg(gmael(powz,1,2))+3;/*dvmdii uses lx+ly space*/ data.powz = powz; for(i=1; i= 4) err_printf("Subcyclo: prime l=%ld\n",l); gl = utoipos(l); av = avma; if (!borne) { /* Use vecmax(Vec((x+o)^d)) = max{binomial(d,i)*o^i ;1<=i<=d} */ i = d-(1+d)/(1+o); borne = mulii(binomial(utoipos(d),i),powuu(o,i)); } if (DEBUGLEVEL >= 4) err_printf("Subcyclo: bound=2^%ld\n",expi(borne)); val = logint(shifti(borne,2), gl) + 1; set_avma(av); if (DEBUGLEVEL >= 4) err_printf("Subcyclo: val=%ld\n",val); le = powiu(gl,val); z = utoipos( Fl_powu(pgener_Fl(l), e, l) ); z = Zp_sqrtnlift(gen_1,utoipos(n),z,gl,val); *ptr_val = val; *ptr_l = l; return gmodulo(z,le); } /*Fill in the powz table: * powz[1]: baby-step * powz[2]: giant-step * powz[3] exists only if the field is real (value is ignored). */ static GEN polsubcyclo_complex_roots(long n, long real, long prec) { long i, m = (long)(1+sqrt((double) n)); GEN bab, gig, powz = cgetg(real?4:3, t_VEC); bab = cgetg(m+1,t_VEC); gel(bab,1) = gen_1; gel(bab,2) = rootsof1u_cx(n, prec); /* = 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); set_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_shallow(gel(zn,3))); GEN ord = vec_to_vecsmall(gel(zn,2)); GEN T = polcyclo(n,v); long d = degpol(T); GEN borneabs = powuu(2,d); z = polsubcyclo_start(n,card/2,2,2*usqrt(d),borneabs,&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) = T; gel(grp,2) = mkvec3(stoi(l), stoi(val), icopy(le)); gel(grp,3) = L; gel(grp,4) = FpV_invVandermonde(L, NULL, le); gel(grp,5) = gen_1; gel(grp,6) = elts; gel(grp,7) = gel(G,1); gel(grp,8) = gel(G,2); return gerepilecopy(av, grp); } /* Convert a bnrinit(Q,n) to an abelian group similar to znstar(n), with * t_INTMOD generators; set cx = 0 if the class field is real and to 1 * otherwise */ static GEN bnr_to_abgrp(GEN bnr, long *cx) { GEN gen, F, v, bid, G, Ui = NULL; long l, i; checkbnr(bnr); bid = bnr_get_bid(bnr); G = bnr_get_clgp(bnr); if (lg(G) == 4) gen = abgrp_get_gen(G); else { Ui = gmael(bnr,4,3); if (ZM_isidentity(Ui)) Ui = NULL; gen = bid_get_gen(bid); } F = bid_get_ideal(bid); if (lg(F) != 2) pari_err_DOMAIN("bnr_to_abgrp", "bnr", "!=", strtoGENstr("Q"), bnr); /* F is the finite part of the conductor, cx is the infinite part*/ F = gcoeff(F, 1, 1); *cx = signe(gel(bid_get_arch(bid), 1)); l = lg(gen); v = cgetg(l, t_VEC); for (i = 1; i < l; ++i) { GEN x = gel(gen,i); if (typ(x) == t_COL) x = gel(x,1); gel(v,i) = gmodulo(absi_shallow(x), F); } if (Ui) { /* from bid.gen to bnr.gen (maybe one less) */ GEN w = v; l = lg(Ui); v = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(v,i) = factorback2(w, gel(Ui, i)); } return mkvec3(bnr_get_no(bnr), bnr_get_cyc(bnr), v); } static long _itos(const char *fun, GEN n) { if (is_bigint(n)) pari_err_IMPL(stack_sprintf("conductor f > %ld in %s", LONG_MAX, fun)); return itos(n); } long subcyclo_nH(const char *fun, GEN N, GEN *psg) { GEN V, Z = NULL, H = *psg; long i, l, n = 0, complex = 1; switch(typ(N)) { case t_INT: n = _itos(fun, N); if (n < 1) pari_err_DOMAIN(fun, "degree", "<=", gen_0, N); break; case t_VEC: if (lg(N)==7) N = bnr_to_abgrp(N,&complex); else if (checkznstar_i(N)) N = mkvec3(znstar_get_no(N), znstar_get_cyc(N), gmodulo(znstar_get_gen(N), znstar_get_N(N))); if (lg(N)==4) { /* abgrp */ GEN gen = abgrp_get_gen(N), z; if (typ(gen)!=t_VEC) pari_err_TYPE(fun,gen); Z = N; if (lg(gen) == 1) { n = 1; break; } z = gel(gen,1); if (typ(z) == t_INTMOD) { n = _itos(fun, gel(z,1)); break; } } default: /*fall through*/ pari_err_TYPE(fun,N); return 0;/*LCOV_EXCL_LINE*/ } if (!H) H = gen_1; switch(typ(H)) { case t_INTMOD: case t_INT: V = mkvecsmall( lift_check_modulus(H,n) ); break; case t_VECSMALL: l = lg(H); V = leafcopy(H); for (i = 1; i < l; i++) { V[i] %= n; if (V[i] < 0) V[i] += n; } break; case t_VEC: case t_COL: l = lg(H); V = cgetg(l,t_VECSMALL); for(i=1; i < l; i++) V[i] = lift_check_modulus(gel(H,i),n); break; case t_MAT: l = lg(H); if (l == 1 || l != lgcols(H)) pari_err_TYPE(stack_strcat(fun," [H not in HNF]"),H); if (!Z) pari_err_TYPE(stack_strcat(fun," [N not a bnrinit or znstar]"),H); if (lg(gel(Z,2)) != l) pari_err_DIM(fun); V = znstar_hnf_generators(znstar_small(Z),H); break; default: pari_err_TYPE(fun,H); return 0;/*LCOV_EXCL_LINE*/ } if (!complex) V = vecsmall_append(V, n-1); /*add complex conjugation*/ *psg = V; return n; } GEN galoissubcyclo(GEN N, GEN sg, long flag, long v) { pari_sp ltop = avma, av; GEN H, B, zl, L, T, le, powz, O; long i, card, phi_n, val,l, n, cnd, complex; pari_timer ti; if (flag<0 || flag>3) pari_err_FLAG("galoissubcyclo"); if (v < 0) v = 0; n = subcyclo_nH("galoissubcyclo", N, &sg); if (n==1) { set_avma(ltop); if (flag == 1) return gen_1; return gscycloconductor(deg1pol_shallow(gen_1, gen_m1, v), 1, flag); } H = znstar_generate(n, sg); if (DEBUGLEVEL >= 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(H); if (DEBUGLEVEL >= 1) timer_printf(&ti, "znstar_conductor"); if (flag == 1) return gc_stoi(ltop, cnd); if (cnd == 1) { set_avma(ltop); if (flag == 1) return gen_1; return gscycloconductor(deg1pol_shallow(gen_1,gen_m1,v),1,flag); } if (n != cnd) { H = znstar_reduce_modulus(H, cnd); n = cnd; } card = znstar_order(H); phi_n = eulerphiu(n); if (card == phi_n) { set_avma(ltop); return gscycloconductor(polcyclo(n,v),n,flag); } O = znstar_cosets(n, phi_n, H); if (DEBUGLEVEL >= 1) timer_printf(&ti, "znstar_cosets"); if (DEBUGLEVEL >= 6) err_printf("Subcyclo: orbits=%Ps\n",O); if (DEBUGLEVEL >= 4) err_printf("Subcyclo: %ld orbits with %ld elements each\n",phi_n/card,card); av = avma; powz = polsubcyclo_complex_roots(n,!complex,LOWDEFAULTPREC); L = polsubcyclo_orbits(n,H,O,powz,NULL); B = polsubcyclo_complex_bound(av,L,LOWDEFAULTPREC); zl = polsubcyclo_start(n,phi_n/card,card,1,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)); if (flag==3) { GEN L2, aut; if (Flx_is_squarefree(ZX_to_Flx(T, l),l)) L2 = ZV_to_Flv(L,l); else { ulong z; do l+=n; while (!uisprime(l) || !Flx_is_squarefree(ZX_to_Flx(T, l), l)); z = rootsof1_Fl(n,l); L2 = Fl_polsubcyclo_orbits(n,H,O,z,l); if (DEBUGLEVEL >= 4) err_printf("galoissubcyclo: switching to unramified prime %lu\n",l); } aut = znstar_quotient(n, phi_n, H, L2, l); return gerepileupto(ltop, galoisinitfromaut(T, aut, l)); } return gerepileupto(ltop, gscycloconductor(T,n,flag)); } /* Z = znstar(n) cyclic. n = 1,2,4,p^a or 2p^a, * and d | phi(n) = 1,1,2,(p-1)p^(a-1) */ static GEN polsubcyclo_g(long n, long d, GEN Z, long v) { pari_sp ltop = avma; long o, p, r, g, gd, l , val; GEN zl, L, T, le, B, powz; pari_timer ti; if (d==1) return deg1pol_shallow(gen_1,gen_m1,v); /* get rid of n=1,2 */ if ((n & 3) == 2) n >>= 1; /* n = 4 or p^a, p odd */ o = itos(gel(Z,1)); g = itos(gmael3(Z,3,1,2)); p = n / ugcd(n,o); /* p^a / gcd(p^a,phi(p^a)) = p*/ r = ugcd(d,n); /* = p^(v_p(d)) < n */ n = r*p; /* n is now the conductor */ o = n-r; /* = phi(n) */ if (o == d) return polcyclo(n,v); o /= d; gd = Fl_powu(g%n, d, n); /*FIXME: If degree is small, the computation of B is a waste of time*/ powz = polsubcyclo_complex_roots(n,(o&1)==0,LOWDEFAULTPREC); L = polsubcyclo_cyclic(n,d,o,g,gd,powz,NULL); B = polsubcyclo_complex_bound(ltop,L,LOWDEFAULTPREC); zl = polsubcyclo_start(n,d,o,1,B,&val,&l); le = gel(zl,1); powz = polsubcyclo_roots(n,zl); L = polsubcyclo_cyclic(n,d,o,g,gd,powz,le); if (DEBUGLEVEL >= 6) timer_start(&ti); T = FpV_roots_to_pol(L,le,v); if (DEBUGLEVEL >= 6) timer_printf(&ti, "roots_to_pol"); return gerepileupto(ltop, FpX_center(T,le,shifti(le,-1))); } GEN polsubcyclo(long n, long d, long v) { pari_sp ltop = avma; GEN L, Z; if (v<0) v = 0; if (d<=0) pari_err_DOMAIN("polsubcyclo","d","<=",gen_0,stoi(d)); if (n<=0) pari_err_DOMAIN("polsubcyclo","n","<=",gen_0,stoi(n)); Z = znstar(stoi(n)); if (!dvdis(gel(Z,1), d)) { set_avma(ltop); return cgetg(1, t_VEC); } if (lg(gel(Z,2)) == 2) { /* faster but Z must be cyclic */ set_avma(ltop); return polsubcyclo_g(n, d, Z, v); } L = subgrouplist(gel(Z,2), mkvec(stoi(d))); if (lg(L) == 2) return gerepileupto(ltop, galoissubcyclo(Z, gel(L,1), 0, v)); else { GEN V = cgetg(lg(L),t_VEC); long i; for (i=1; i< lg(V); i++) gel(V,i) = galoissubcyclo(Z, gel(L,i), 0, v); return gerepileupto(ltop, V); } } struct aurifeuille_t { GEN z, le; ulong l; long e; }; /* Let z a primitive n-th root of 1, n > 1, A an integer such that * Aurifeuillian factorization of Phi_n(A) exists ( z.A is a square in Q(z) ). * Let G(p) the Gauss sum mod p prime: * sum_x (x|p) z^(xn/p) for p odd, i - 1 for p = 2 [ i := z^(n/4) ] * We have N(-1) = Nz = 1 (n != 1,2), and * G^2 = (-1|p) p for p odd, G^2 = -2i for p = 2 * In particular, for odd A, (-1|A) A = g^2 is a square. If A = prod p^{e_p}, * sigma_j(g) = \prod_p (sigma_j G(p)))^e_p = \prod_p (j|p)^e_p g = (j|A) g * n odd : z^2 is a primitive root, A = g^2 * Phi_n(A) = N(A - z^2) = N(g - z) N(g + z) * * n = 2 (4) : -z^2 is a primitive root, -A = g^2 * Phi_n(A) = N(A - (-z^2)) = N(g^2 - z^2) [ N(-1) = 1 ] * = N(g - z) N(g + z) * * n = 4 (8) : i z^2 primitive root, -Ai = g^2 * Phi_n(A) = N(A - i z^2) = N(-Ai - z^2) = N(g - z) N(g + z) * sigma_j(g) / g = (j|A) if j = 1 (4) * (-j|A)i if j = 3 (4) * */ /* factor Phi_n(A), Astar: A* = squarefree kernel of A, P = odd prime divisors * of n */ static GEN factor_Aurifeuille_aux(GEN A, long Astar, long n, GEN P, struct aurifeuille_t *S) { pari_sp av; GEN f, a, b, s, powers, z = S->z, le = S->le; long j, k, maxjump, lastj, e = S->e; ulong l = S->l; char *invertible; if ((n & 7) == 4) { /* A^* even */ GEN i = Fp_powu(z, n>>2, le), z2 = Fp_sqr(z, le); invertible = stack_malloc(n); /* even indices unused */ for (j = 1; j < n; j+=2) invertible[j] = 1; for (k = 1; k < lg(P); k++) { long p = P[k]; for (j = p; j < n; j += 2*p) invertible[j] = 0; } lastj = 1; maxjump = 2; for (j= 3; j < n; j+=2) if (invertible[j]) { long jump = j - lastj; if (jump > maxjump) maxjump = jump; lastj = j; } powers = cgetg(maxjump+1, t_VEC); /* powers[k] = z^k, odd indices unused */ gel(powers,2) = z2; for (k = 4; k <= maxjump; k+=2) gel(powers,k) = odd(k>>1)? Fp_mul(gel(powers, k-2), z2, le) : Fp_sqr(gel(powers, k>>1), le); if (Astar == 2) { /* important special case (includes A=2), split for efficiency */ if (!equalis(A, 2)) { GEN f = sqrti(shifti(A,-1)), mf = Fp_neg(f,le), fi = Fp_mul(f,i,le); a = Fp_add(mf, fi, le); b = Fp_sub(mf, fi, le); } else { a = subiu(i,1); b = subsi(-1,i); } av = avma; s = z; f = subii(a, s); lastj = 1; for (j = 3, k = 0; j < n; j+=2) if (invertible[j]) { s = Fp_mul(gel(powers, j-lastj), s, le); /* z^j */ lastj = j; f = Fp_mul(f, subii((j & 3) == 1? a: b, s), le); if (++k == 0x1ff) { gerepileall(av, 2, &s, &f); k = 0; } } } else { GEN ma, mb, B = Fp_mul(A, i, le), gl = utoipos(l); long t; Astar >>= 1; t = Astar & 3; if (Astar < 0) t = 4-t; /* t = 1 or 3 */ if (t == 1) B = Fp_neg(B, le); a = Zp_sqrtlift(B, Fp_sqrt(B, gl), gl, e); b = Fp_mul(a, i, le); ma = Fp_neg(a, le); mb = Fp_neg(b, le); av = avma; s = z; f = subii(a, s); lastj = 1; for (j = 3, k = 0; j>= 1; } /* A^* = 1 (mod 4) */ g = Fl_sqrt(umodiu(A,l), l); a = Zp_sqrtlift(A, utoipos(g), utoipos(l), e); b = negi(a); invertible = stack_malloc(n); for (j = 1; j < n; j++) invertible[j] = 1; for (k = 1; k < lg(P); k++) { long p = P[k]; for (j = p; j < n; j += p) invertible[j] = 0; } lastj = 2; maxjump = 1; for (j= 3; j < n; j++) if (invertible[j]) { long jump = j - lastj; if (jump > maxjump) maxjump = jump; lastj = j; } powers = cgetg(maxjump+1, t_VEC); /* powers[k] = z^k */ gel(powers,1) = z; for (k = 2; k <= maxjump; k++) gel(powers,k) = odd(k)? Fp_mul(gel(powers, k-1), z, le) : Fp_sqr(gel(powers, k>>1), le); av = avma; s = z; f = subii(a, s); lastj = 1; for(j = 2, k = 0; j < n; j++) if (invertible[j]) { s = Fp_mul(gel(powers, j-lastj), s, le); lastj = j; f = Fp_mul(f, subii(kross(j,Astar)==1? a: b, s), le); if (++k == 0x1ff) { gerepileall(av, 2, &s, &f); k = 0; } } } return f; } /* d != 2 mod 4; fd = factoru(odd(d)? d: d / 4) */ static void Aurifeuille_init(GEN a, long d, GEN fd, struct aurifeuille_t *S) { GEN bound, zl, sqrta = sqrtr_abs(itor(a, LOWDEFAULTPREC)); ulong phi = eulerphiu_fact(fd); if (!odd(d)) phi <<= 1; /* eulerphi(d) */ bound = ceil_safe(powru(addrs(sqrta,1), phi)); zl = polsubcyclo_start(d, 0, 0, 1, bound, &(S->e), (long*)&(S->l)); S->le = gel(zl,1); S->z = gel(zl,2); } GEN factor_Aurifeuille_prime(GEN p, long d) { pari_sp av = avma; struct aurifeuille_t S; GEN fd; long pp; if ((d & 3) == 2) { d >>= 1; p = negi(p); } fd = factoru(odd(d)? d: d>>2); pp = itos(p); Aurifeuille_init(p, d, fd, &S); return gerepileuptoint(av, factor_Aurifeuille_aux(p, pp, d, gel(fd,1), &S)); } /* an algebraic factor of Phi_d(a), a != 0 */ GEN factor_Aurifeuille(GEN a, long d) { pari_sp av = avma; GEN fd, P, A; long i, lP, va = vali(a), sa, astar, D; struct aurifeuille_t S; if (d <= 0) pari_err_DOMAIN("factor_Aurifeuille", "degre", "<=",gen_0,stoi(d)); if ((d & 3) == 2) { d >>= 1; a = negi(a); } if ((va & 1) == (d & 1)) { set_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, addiu(A,1)); } A = va? shifti(a, -va): a; a4 = mod4(A); if (sa < 0) a4 = 4 - a4; if (a4 != 1) { set_avma(av); return gen_1; } } else if ((d & 7) == 4) A = shifti(a, -va); else { set_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)) { set_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.17.2/src/basemath/ispower.c0000644000175000017500000007720114760123736015413 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" /*********************************************************************/ /** PERFECT POWERS **/ /*********************************************************************/ #define DEBUGLEVEL DEBUGLEVEL_arith /*********************************************************************/ /** INTEGRAL LOGARITHM **/ /*********************************************************************/ /* y > 1 and B > 0 integers. Return e such that y^e <= B < y^(e+1), i.e * e = floor(log_y B). Set *ptq = y^e if non-NULL */ long ulogintall(ulong B, ulong y, ulong *ptq) { ulong r, r2; long e; if (y == 2) { long eB = expu(B); /* 2^eB <= B < 2^(eB + 1) */ if (ptq) *ptq = 1UL << eB; return eB; } r = y, r2 = 1UL; for (e=1;; e++) { /* here, r = y^e, r2 = y^(e-1) */ if (r >= B) { if (r != B) { e--; r = r2; } if (ptq) *ptq = r; return e; } r2 = r; r = umuluu_or_0(y, r); if (!r) { if (ptq) *ptq = r2; return e; } } } /* y > 1 and B > 0 integers. Return e such that y^e <= B < y^(e+1), i.e * e = floor(log_y B). Set *ptq = y^e if non-NULL */ long logintall(GEN B, GEN y, GEN *ptq) { pari_sp av; long ey, e, emax, i, eB = expi(B); /* 2^eB <= B < 2^(eB + 1) */ GEN q, pow2; if (lgefint(B) == 3) { ulong q; if (lgefint(y) > 3) { if (ptq) *ptq = gen_1; return 0; } if (!ptq) return ulogintall(B[2], y[2], NULL); e = ulogintall(B[2], y[2], &q); *ptq = utoi(q); return e; } if (equaliu(y,2)) { if (ptq) *ptq = int2n(eB); return eB; } av = avma; ey = expi(y); /* eB/(ey+1) - 1 < e <= eB/ey */ emax = eB/ey; if (emax <= 13) /* e small, be naive */ { GEN r = y, r2 = gen_1; for (e=1;; e++) { /* here, r = y^e, r2 = y^(e-1) */ long fl = cmpii(r, B); if (fl >= 0) { if (fl) { e--; cgiv(r); r = r2; } if (ptq) *ptq = gerepileuptoint(av, r); else set_avma(av); return e; } r2 = r; r = mulii(r,y); } } /* e >= 13 ey / (ey+1) >= 6.5 */ /* binary splitting: compute bits of e one by one */ /* compute pow2[i] = y^(2^i) [i < crude upper bound for log_2 log_y(B)] */ pow2 = new_chunk((long)log2(eB)+2); gel(pow2,0) = y; for (i=0, q=y;; ) { GEN r = gel(pow2,i); /* r = y^2^i */ long fl = cmpii(r,B); if (!fl) { e = 1L< 0) { i--; break; } q = r; if (1L<<(i+1) > emax) break; gel(pow2,++i) = sqri(q); } for (e = 1L< 0) set_avma(av2); else { e += (1L< p) { /* try to avoid precision loss in truncation */ if (p > DEFAULTPREC) { p = DEFAULTPREC; B = rtor(B, p); } a = itos(floorr(divrr(logr_abs(B), logr_abs(itor(y, p))))); set_avma(av); if (ptq) *ptq = powiu(y, a); return a; } a = logintall(truncr(B), y, ptq); } else { GEN b = gfloor(B); if (typ(b) != t_INT) pari_err_TYPE(f,B); if (signe(b) <= 0) pari_err_DOMAIN(f, "x", "<", gen_1, B); a = logintall(b, y, ptq); } if (!ptq) return gc_long(av, a); *ptq = gerepileuptoint(av, *ptq); return a; } if (signe(B) <= 0) pari_err_DOMAIN(f, "x" ,"<=", gen_0, B); return logintall(B,y,ptq); } /*********************************************************************/ /** INTEGRAL SQUARE ROOT **/ /*********************************************************************/ GEN sqrtint(GEN a) { if (typ(a) != t_INT) { pari_sp av = avma; if (typ(a) == t_REAL) { long e; switch(signe(a)) { case 0: return gen_0; case -1: pari_err_DOMAIN("sqrtint", "argument", "<", gen_0,a); } e = expo(a); if (e < 0) return gen_0; if (nbits2lg(e+1) > lg(a)) a = floorr(sqrtr(a)); /* try to avoid precision loss in truncation */ else a = sqrti(truncr(a)); } else { GEN b = gfloor(a); if (typ(b) != t_INT) pari_err_TYPE("sqrtint",a); if (signe(b) < 0) pari_err_DOMAIN("sqrtint", "argument", "<", gen_0,a); a = sqrti(b); } return gerepileuptoleaf(av, a); } switch (signe(a)) { case 1: return sqrti(a); case 0: return gen_0; default: pari_err_DOMAIN("sqrtint", "argument", "<", gen_0,a); } return NULL; /* LCOV_EXCL_LINE */ } GEN sqrtint0(GEN a, GEN *r) { if (!r) return sqrtint(a); if (typ(a) != t_INT) { GEN b = sqrtint(a); pari_sp av = avma; *r = gerepileupto(av, gsub(a, sqri(b))); return b; } switch (signe(a)) { case 1: return sqrtremi(a, r); case 0: *r = gen_0; return gen_0; default: pari_err_DOMAIN("sqrtint", "argument", "<", gen_0,a); } return NULL; /* LCOV_EXCL_LINE */ } /*********************************************************************/ /** PERFECT SQUARE **/ /*********************************************************************/ static int squaremod(ulong A) { const int squaremod64[]={ 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 squaremod63[]={ 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 squaremod65[]={ 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 squaremod11[]={1,1,0,1,1,1,0,0,0,1, 0}; return (squaremod64[A & 0x3fUL] && squaremod63[A % 63UL] && squaremod65[A % 65UL] && squaremod11[A % 11UL]); } /* emulate Z_issquareall on single-word integers */ long uissquareall(ulong A, ulong *sqrtA) { if (!A) { *sqrtA = 0; return 1; } if (squaremod(A)) { ulong a = usqrt(A); if (a * a == A) { *sqrtA = a; return 1; } } return 0; } long uissquare(ulong A) { if (!A) return 1; if (squaremod(A)) { ulong a = usqrt(A); if (a * a == 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 u = uel(x,2), a; if (!pt) return uissquare(u); if (!uissquareall(u, &a)) return 0; *pt = utoipos(a); return 1; } if (!squaremod(umodiu(x, 64*63*65*11))) return 0; av = avma; y = sqrtremi(x, &r); if (r != gen_0) return gc_long(av,0); if (pt) { *pt = y; set_avma((pari_sp)y); } else set_avma(av); return 1; } /* a t_INT, p prime */ long Zp_issquare(GEN a, GEN p) { long v; GEN ap; if (!signe(a) || equali1(a)) return 1; v = Z_pvalrem(a, p, &ap); if (v&1) return 0; return absequaliu(p, 2)? Mod8(ap) == 1 : kronecker(ap,p) == 1; } static long polissquareall(GEN x, GEN *pt) { pari_sp av; long v; GEN y, a, b, p; if (!signe(x)) { if (pt) *pt = gcopy(x); return 1; } if (odd(degpol(x))) return 0; /* odd degree */ av = avma; v = RgX_valrem(x, &x); if (v & 1) return gc_long(av,0); a = gel(x,2); /* test constant coeff */ if (!pt) { if (!issquare(a)) return gc_long(av,0); } else { if (!issquareall(a,&b)) return gc_long(av,0); } if (!degpol(x)) { /* constant polynomial */ if (!pt) return gc_long(av,1); y = scalarpol(b, varn(x)); goto END; } p = characteristic(x); if (signe(p) && !mod2(p)) { long i, lx; if (!absequaliu(p,2)) pari_err_IMPL("issquare for even characteristic != 2"); x = gmul(x, mkintmod(gen_1, gen_2)); lx = lg(x); if ((lx-3) & 1) return gc_long(av,0); for (i = 3; i < lx; i+=2) if (!gequal0(gel(x,i))) return gc_long(av,0); if (pt) { y = cgetg((lx+3) / 2, t_POL); for (i = 2; i < lx; i+=2) if (!issquareall(gel(x,i), &gel(y, (i+2)>>1))) return gc_long(av,0); y[1] = evalsigne(1) | evalvarn(varn(x)); goto END; } else { for (i = 2; i < lx; i+=2) if (!issquare(gel(x,i))) return gc_long(av,0); return gc_long(av,1); } } else { long m = 1; x = RgX_Rg_div(x,a); /* a(x^m) = B^2 => B = b(x^m) provided a(0) != 0 */ if (!signe(p)) x = RgX_deflate_max(x,&m); y = ser2rfrac_i(gsqrt(RgX_to_ser(x,lg(x)-1),0)); if (!RgX_equal(RgX_sqr(y), x)) return gc_long(av,0); if (!pt) return gc_long(av,1); if (!gequal1(a)) y = gmul(b, y); if (m != 1) y = RgX_inflate(y,m); } END: if (v) y = RgX_shift_shallow(y, v>>1); *pt = gerepilecopy(av, y); return 1; } /* b unit mod p */ static int Up_ispower(GEN b, GEN K, GEN p, long d, GEN *pt) { if (d == 1) { /* mod p: faster */ if (!Fp_ispower(b, K, p)) return 0; if (pt) *pt = Fp_sqrtn(b, K, p, NULL); } else { /* mod p^{2 +} */ if (!ispower(cvtop(b, p, d), K, pt)) return 0; if (pt) *pt = gtrunc(*pt); } return 1; } /* We're studying whether a mod (q*p^e) is a K-th power, (q,p) = 1. * Decide mod p^e, then reduce a mod q unless q = NULL. */ static int handle_pe(GEN *pa, GEN q, GEN L, GEN K, GEN p, long e) { GEN t, A; long v = Z_pvalrem(*pa, p, &A), d = e - v; if (d <= 0) t = gen_0; else { ulong r; v = uabsdivui_rem(v, K, &r); if (r || !Up_ispower(A, K, p, d, L? &t: NULL)) return 0; if (L && v) t = mulii(t, powiu(p, v)); } if (q) *pa = modii(*pa, q); if (L) vectrunc_append(L, mkintmod(t, powiu(p, e))); return 1; } long Zn_ispower(GEN a, GEN q, GEN K, GEN *pt) { GEN L, N; pari_sp av; long e, i, l; ulong pp; forprime_t S; if (!signe(a)) { if (pt) { GEN t = cgetg(3, t_INTMOD); gel(t,1) = icopy(q); gel(t,2) = gen_0; *pt = t; } return 1; } /* a != 0 */ av = avma; if (typ(q) != t_INT) /* integer factorization */ { GEN P = gel(q,1), E = gel(q,2); l = lg(P); L = pt? vectrunc_init(l): NULL; for (i = 1; i < l; i++) { GEN p = gel(P,i); long e = itos(gel(E,i)); if (!handle_pe(&a, NULL, L, K, p, e)) return gc_long(av,0); } goto END; } if (!mod2(K) && kronecker(a, shifti(q,-vali(q))) == -1) return gc_long(av,0); L = pt? vectrunc_init(expi(q)+1): NULL; u_forprime_init(&S, 2, tridiv_bound(q)); while ((pp = u_forprime_next(&S))) { int stop; e = Z_lvalrem_stop(&q, pp, &stop); if (!e) continue; if (!handle_pe(&a, q, L, K, utoipos(pp), e)) return gc_long(av,0); if (stop) { if (!is_pm1(q) && !handle_pe(&a, q, L, K, q, 1)) return gc_long(av,0); goto END; } } l = lg(primetab); for (i = 1; i < l; i++) { GEN p = gel(primetab,i); e = Z_pvalrem(q, p, &q); if (!e) continue; if (!handle_pe(&a, q, L, K, p, e)) return gc_long(av,0); if (is_pm1(q)) goto END; } N = gcdii(a,q); if (!is_pm1(N)) { if (ifac_isprime(N)) { e = Z_pvalrem(q, N, &q); if (!handle_pe(&a, q, L, K, N, e)) return gc_long(av,0); } else { GEN part = ifac_start(N, 0); for(;;) { long e; GEN p; if (!ifac_next(&part, &p, &e)) break; e = Z_pvalrem(q, p, &q); if (!handle_pe(&a, q, L, K, p, e)) return gc_long(av,0); } } } if (!is_pm1(q)) { if (ifac_isprime(q)) { if (!handle_pe(&a, q, L, K, q, 1)) return gc_long(av,0); } else { /* icopy needed: ifac_next would destroy q */ GEN part = ifac_start(icopy(q), 0); for(;;) { long e; GEN p; if (!ifac_next(&part, &p, &e)) break; if (!handle_pe(&a, q, L, K, p, e)) return gc_long(av,0); } } } END: if (pt) *pt = gerepileupto(av, chinese1_coprime_Z(L)); return 1; } static long polmodispower(GEN x, GEN K, GEN *pt) { pari_sp av = avma; GEN p = NULL, T = NULL; if (Rg_is_FpXQ(x, &T,&p) && p) { x = liftall_shallow(x); if (T) T = liftall_shallow(T); if (!Fq_ispower(x, K, T, p)) return gc_long(av,0); if (!pt) return gc_long(av,1); x = Fq_sqrtn(x, K, T,p, NULL); if (typ(x) == t_INT) x = Fp_to_mod(x,p); else x = mkpolmod(FpX_to_mod(x,p), FpX_to_mod(T,p)); *pt = gerepilecopy(av, x); return 1; } pari_err_IMPL("ispower for general t_POLMOD"); return 0; } static long rfracispower(GEN x, GEN K, GEN *pt) { pari_sp av = avma; GEN n = gel(x,1), d = gel(x,2); long v = -RgX_valrem(d, &d), vx = varn(d); if (typ(n) == t_POL && varn(n) == vx) v += RgX_valrem(n, &n); if (!dvdsi(v, K)) return gc_long(av, 0); if (lg(d) >= 3) { GEN a = gel(d,2); /* constant term */ if (!gequal1(a)) { d = RgX_Rg_div(d, a); n = gdiv(n, a); } } if (!ispower(d, K, pt? &d: NULL) || !ispower(n, K, pt? &n: NULL)) return gc_long(av, 0); if (!pt) return gc_long(av, 1); x = gdiv(n, d); if (v) x = gmul(x, monomial(gen_1, v / itos(K), vx)); *pt = gerepileupto(av, x); return 1; } long issquareall(GEN x, GEN *pt) { long tx = typ(x); GEN F; pari_sp av; if (!pt) return issquare(x); switch(tx) { case t_INT: return Z_issquareall(x, pt); case t_FRAC: av = avma; F = cgetg(3, t_FRAC); if ( !Z_issquareall(gel(x,1), &gel(F,1)) || !Z_issquareall(gel(x,2), &gel(F,2))) return gc_long(av,0); *pt = F; return 1; case t_POLMOD: return polmodispower(x, gen_2, pt); case t_POL: return polissquareall(x,pt); case t_RFRAC: return rfracispower(x, gen_2, pt); case t_REAL: case t_COMPLEX: case t_PADIC: case t_SER: if (!issquare(x)) return 0; *pt = gsqrt(x, DEFAULTPREC); return 1; case t_INTMOD: return Zn_ispower(gel(x,2), gel(x,1), gen_2, pt); case t_FFELT: return FF_issquareall(x, pt); } pari_err_TYPE("issquareall",x); return 0; /* LCOV_EXCL_LINE */ } long issquare(GEN x) { GEN a, p; long v; switch(typ(x)) { case t_INT: return Z_issquare(x); case t_REAL: return (signe(x)>=0); case t_INTMOD: return Zn_ispower(gel(x,2), gel(x,1), gen_2, NULL); case t_FRAC: return Z_issquare(gel(x,1)) && Z_issquare(gel(x,2)); case t_FFELT: return FF_issquareall(x, NULL); case t_COMPLEX: return 1; case t_PADIC: a = gel(x,4); if (!signe(a)) return 1; if (valp(x)&1) return 0; p = gel(x,2); if (!absequaliu(p, 2)) return (kronecker(a,p) != -1); v = precp(x); /* here p=2, a is odd */ if ((v>=3 && mod8(a) != 1 ) || (v==2 && mod4(a) != 1)) return 0; return 1; case t_POLMOD: return polmodispower(x, gen_2, NULL); case t_POL: return polissquareall(x,NULL); case t_SER: if (!signe(x)) return 1; if (valser(x)&1) return 0; return issquare(gel(x,2)); case t_RFRAC: return rfracispower(x, gen_2, NULL); } pari_err_TYPE("issquare",x); return 0; /* LCOV_EXCL_LINE */ } GEN gissquare(GEN x) { return issquare(x)? gen_1: gen_0; } GEN gissquareall(GEN x, GEN *pt) { return issquareall(x,pt)? gen_1: gen_0; } long ispolygonal(GEN x, GEN S, GEN *N) { pari_sp av = avma; GEN D, d, n; if (typ(x) != t_INT) pari_err_TYPE("ispolygonal", x); if (typ(S) != t_INT) pari_err_TYPE("ispolygonal", S); if (abscmpiu(S,3) < 0) pari_err_DOMAIN("ispolygonal","s","<", utoipos(3),S); if (signe(x) < 0) return 0; if (signe(x) == 0) { if (N) *N = gen_0; return 1; } if (is_pm1(x)) { if (N) *N = gen_1; return 1; } /* n = (sqrt( (8s - 16) x + (s-4)^2 ) + s - 4) / 2(s - 2) */ if (abscmpiu(S, 1<<16) < 0) /* common case ! */ { ulong s = S[2], r; if (s == 4) return Z_issquareall(x, N); if (s == 3) D = addiu(shifti(x, 3), 1); else D = addiu(mului(8*s - 16, x), (s-4)*(s-4)); if (!Z_issquareall(D, &d)) return gc_long(av,0); if (s == 3) d = subiu(d, 1); else d = addiu(d, s - 4); n = absdiviu_rem(d, 2*s - 4, &r); if (r) return gc_long(av,0); } else { GEN r, S_2 = subiu(S,2), S_4 = subiu(S,4); D = addii(mulii(shifti(S_2,3), x), sqri(S_4)); if (!Z_issquareall(D, &d)) return gc_long(av,0); d = addii(d, S_4); n = dvmdii(shifti(d,-1), S_2, &r); if (r != gen_0) return gc_long(av,0); } if (N) *N = gerepileuptoint(av, n); else set_avma(av); return 1; } /*********************************************************************/ /** PERFECT POWER **/ /*********************************************************************/ static long polispower(GEN x, GEN K, GEN *pt) { pari_sp av; long v, d, k = itos(K); GEN y, a, b; GEN T = NULL, p = NULL; if (!signe(x)) { if (pt) *pt = gcopy(x); return 1; } d = degpol(x); if (d % k) return 0; /* degree not multiple of k */ av = avma; if (RgX_is_FpXQX(x, &T, &p) && p) { /* over Fq */ if (T && typ(T) == t_FFELT) { if (!FFX_ispower(x, k, T, pt)) return gc_long(av,0); return 1; } x = RgX_to_FqX(x,T,p); if (!FqX_ispower(x, k, T,p, pt)) return gc_long(av,0); if (pt) *pt = gerepileupto(av, FqX_to_mod(*pt, T, p)); return 1; } v = RgX_valrem(x, &x); if (v % k) return 0; v /= k; a = gel(x,2); b = NULL; if (!ispower(a, K, &b)) return gc_long(av,0); if (d) { GEN p = characteristic(x); a = leading_coeff(x); if (!ispower(a, K, &b)) return gc_long(av,0); x = RgX_normalize(x); if (signe(p) && cmpii(p,K) <= 0) pari_err_IMPL("ispower(general t_POL) in small characteristic"); y = gtrunc(gsqrtn(RgX_to_ser(x,lg(x)), K, NULL, 0)); if (!RgX_equal(powgi(y, K), x)) return gc_long(av,0); } else y = pol_1(varn(x)); if (pt) { if (!gequal1(a)) { if (!b) b = gsqrtn(a, K, NULL, DEFAULTPREC); y = gmul(b,y); } if (v) y = RgX_shift_shallow(y, v); *pt = gerepilecopy(av, y); } else set_avma(av); return 1; } long Z_ispowerall(GEN x, ulong k, GEN *pt) { long s = signe(x); ulong mask; if (!s) { if (pt) *pt = gen_0; return 1; } if (s > 0) { if (k == 2) return Z_issquareall(x, pt); if (k == 3) { mask = 1; return !!is_357_power(x, pt, &mask); } if (k == 5) { mask = 2; return !!is_357_power(x, pt, &mask); } if (k == 7) { mask = 4; return !!is_357_power(x, pt, &mask); } return is_kth_power(x, k, pt); } if (!odd(k)) return 0; if (Z_ispowerall(absi_shallow(x), k, pt)) { if (pt) *pt = negi(*pt); return 1; }; return 0; } /* is x a K-th power mod p ? Assume p prime. */ int Fp_ispower(GEN x, GEN K, GEN p) { pari_sp av = avma; GEN p_1; x = modii(x, p); if (!signe(x) || equali1(x)) return gc_bool(av,1); /* implies p > 2 */ p_1 = subiu(p,1); K = gcdii(K, p_1); if (absequaliu(K, 2)) return gc_bool(av, kronecker(x,p) > 0); x = Fp_pow(x, diviiexact(p_1,K), p); return gc_bool(av, equali1(x)); } /* x unit defined modulo 2^e, e > 0, p prime */ static int U2_issquare(GEN x, long e) { long r = signe(x)>=0?mod8(x):8-mod8(x); if (e==1) return 1; if (e==2) return (r&3L) == 1; return r == 1; } /* x unit defined modulo p^e, e > 0, p prime */ static int Up_issquare(GEN x, GEN p, long e) { return (absequaliu(p,2))? U2_issquare(x, e): kronecker(x,p)==1; } long Zn_issquare(GEN d, GEN fn) { long j, np; if (typ(d) != t_INT) pari_err_TYPE("Zn_issquare",d); if (typ(fn) == t_INT) return Zn_ispower(d, fn, gen_2, NULL); /* integer factorization */ np = nbrows(fn); for (j = 1; j <= np; ++j) { GEN r, p = gcoeff(fn, j, 1); long e = itos(gcoeff(fn, j, 2)); long v = Z_pvalrem(d,p,&r); if (v < e && (odd(v) || !Up_issquare(r, p, e-v))) return 0; } return 1; } static long Qp_ispower(GEN x, GEN K, GEN *pt) { pari_sp av = avma; GEN z = Qp_sqrtn(x, K, NULL); if (!z) return gc_long(av,0); if (pt) *pt = z; return 1; } long ispower(GEN x, GEN K, GEN *pt) { GEN z; if (!K) return gisanypower(x, pt); if (typ(K) != t_INT) pari_err_TYPE("ispower",K); if (signe(K) <= 0) pari_err_DOMAIN("ispower","exponent","<=",gen_0,K); if (equali1(K)) { if (pt) *pt = gcopy(x); return 1; } switch(typ(x)) { case t_INT: if (lgefint(K) != 3) return 0; return Z_ispowerall(x, itou(K), pt); case t_FRAC: { GEN a = gel(x,1), b = gel(x,2); ulong k; if (lgefint(K) != 3) return 0; 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; } set_avma((pari_sp)(z + 3)); return 0; } return Z_ispower(a, k) && Z_ispower(b, k); } case t_INTMOD: return Zn_ispower(gel(x,2), gel(x,1), K, pt); case t_FFELT: return FF_ispower(x, K, pt); case t_PADIC: return Qp_ispower(x, K, pt); case t_POLMOD: return polmodispower(x, K, pt); case t_POL: return polispower(x, K, pt); case t_RFRAC: return rfracispower(x, K, pt); 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(valser(x), K) || !ispower(gel(x,2), K, NULL))) return 0; if (pt) *pt = gsqrtn(x, K, NULL, DEFAULTPREC); return 1; } pari_err_TYPE("ispower",x); return 0; /* LCOV_EXCL_LINE */ } 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 = (abscmpii(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)) return gc_long(av,0); if (signe(a) < 0) b = negi(b); k = Z_isanypower(b, pty? &b: NULL); if (!k || !pty) return gc_long(av,k); *pty = gerepileupto(av, ginv(b)); return k; } fa = factoru(k); P = gel(fa,1); E = gel(fa,2); h = k; for (i = lg(P) - 1; i > 0; i--) { p = P[i]; e = E[i]; for (j = 0; j < e; j++) if (!is_kth_power(b, p, &b)) break; if (j < e) k /= upowuu(p, e - j); } if (k == 1) return gc_long(av,0); if (!pty) return gc_long(av,k); if (k != h) a = powiu(a, h/k); *pty = gerepilecopy(av, mkfrac(a, b)); return k; } pari_err_TYPE("gisanypower", x); return 0; /* LCOV_EXCL_LINE */ } /* v_p(x) = e != 0 for some p; return ispower(x,,&x), updating x. * No need to optimize for 2,3,5,7 powers (done before) */ static long split_exponent(ulong e, GEN *x) { GEN fa, P, E; long i, j, l, k = 1; if (e == 1) return 1; fa = factoru(e); P = gel(fa,1); E = gel(fa,2); l = lg(P); for (i = 1; i < l; i++) { ulong p = P[i]; for (j = 0; j < E[i]; j++) { GEN y; if (!is_kth_power(*x, p, &y)) break; k *= p; *x = y; } } return k; } /* any prime divisor of x is > 102 */ static long Z_isanypower_101(GEN *px) { const double LOG2_103 = 6.6865; /* lower bound for log_2(103) */ const double LOG103 = 4.6347; /* lower bound for log(103) */ forprime_t T; ulong mask = 7, e2; long k, ex; GEN y, x = *px; k = 1; while (Z_issquareall(x, &y)) { k <<= 1; x = y; } while ( (ex = is_357_power(x, &y, &mask)) ) { k *= ex; x = y; } e2 = (ulong)((expi(x) + 1) / LOG2_103); /* >= log_103 (x) */ if (u_forprime_init(&T, 11, e2)) { GEN logx = NULL; const ulong Q = 30011; /* prime */ ulong p, xmodQ; double dlogx = 0; /* cut off at x^(1/p) ~ 2^30 bits which seems to be about optimum; * for large p the modular checks are no longer competitively fast */ while ( (ex = is_pth_power(x, &y, &T, 30)) ) { k *= ex; x = y; e2 = (ulong)((expi(x) + 1) / LOG2_103); u_forprime_restrict(&T, e2); } if (DEBUGLEVEL>4) err_printf("Z_isanypower: now k=%ld, x=%ld-bit\n", k, expi(x)+1); xmodQ = umodiu(x, Q); /* test Q | x, just in case */ if (!xmodQ) { *px = x; return k * split_exponent(Z_lval(x,Q), px); } /* x^(1/p) < 2^31 */ p = T.p; if (p <= e2) { logx = logr_abs( itor(x, DEFAULTPREC) ); dlogx = rtodbl(logx); e2 = (ulong)(dlogx / LOG103); /* >= log_103(x) */ } while (p && p <= e2) { /* is x a p-th power ? By computing y = round(x^(1/p)). * Check whether y^p = x, first mod Q, then exactly. */ pari_sp av = avma; long e; GEN logy = divru(logx, p), y = grndtoi(mpexp(logy), &e); ulong ymodQ = umodiu(y,Q); if (e >= -10 || Fl_powu(ymodQ, p % (Q-1), Q) != xmodQ || !equalii(powiu(y, p), x)) set_avma(av); else { k *= p; x = y; xmodQ = ymodQ; logx = logy; dlogx /= p; e2 = (ulong)(dlogx / LOG103); /* >= log_103(x) */ u_forprime_restrict(&T, e2); continue; /* if success, retry same p */ } p = u_forprime_next(&T); } } *px = x; return k; } static ulong tinyprimes[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199 }; /* disregard the sign of x, caller will take care of x < 0 */ static long Z_isanypower_aux(GEN x, GEN *pty) { long ex, v, i, l, k; GEN y, P, E; ulong mask, e = 0; if (abscmpii(x, gen_2) < 0) return 0; /* -1,0,1 */ x = absi_shallow(x); k = l = 1; P = cgetg(26 + 1, t_VECSMALL); E = cgetg(26 + 1, t_VECSMALL); /* trial division */ for(i = 0; i < 26; i++) { ulong p = tinyprimes[i]; int stop; v = Z_lvalrem_stop(&x, p, &stop); if (v) { P[l] = p; E[l] = v; l++; e = ugcd(e, v); if (e == 1) goto END; } if (stop) { if (is_pm1(x)) k = e; goto END; } } if (e) { /* Bingo. Result divides e */ long v3, v5, v7; ulong e2 = e; v = u_lvalrem(e2, 2, &e2); if (v) { for (i = 0; i < v; i++) { if (!Z_issquareall(x, &y)) break; k <<= 1; x = y; } } mask = 0; v3 = u_lvalrem(e2, 3, &e2); if (v3) mask = 1; v5 = u_lvalrem(e2, 5, &e2); if (v5) mask |= 2; v7 = u_lvalrem(e2, 7, &e2); if (v7) mask |= 4; while ( (ex = is_357_power(x, &y, &mask)) ) { x = y; switch(ex) { case 3: k *= 3; if (--v3 == 0) mask &= ~1; break; case 5: k *= 5; if (--v5 == 0) mask &= ~2; break; case 7: k *= 7; if (--v7 == 0) mask &= ~4; break; } } k *= split_exponent(e2, &x); } else k = Z_isanypower_101(&x); END: if (pty && k != 1) { if (e) { /* add missing small factors */ y = powuu(P[1], E[1] / k); for (i = 2; i < l; i++) y = mulii(y, powuu(P[i], E[i] / k)); x = equali1(x)? y: mulii(x,y); } *pty = x; } return k == 1? 0: k; } long Z_isanypower(GEN x, GEN *pty) { pari_sp av = avma; long k = Z_isanypower_aux(x, pty); if (!k) return gc_long(av,0); if (signe(x) < 0) { long v = vals(k); if (v) { k >>= v; if (k == 1) return gc_long(av,0); if (!pty) return gc_long(av,k); *pty = gerepileuptoint(av, powiu(*pty, 1< p >= 103 */ v = Z_isanypower_101(&n); /* expensive */ if (!(flag? isprime(n): BPSW_psp(n))) return gc_long(av,0); if (pt) *pt = gerepilecopy(av, n); else set_avma(av); return v; } long isprimepower(GEN n, GEN *pt) { return isprimepower_i(n,pt,1); } long ispseudoprimepower(GEN n, GEN *pt) { return isprimepower_i(n,pt,0); } long uisprimepower(ulong n, ulong *pp) { /* We must have CUTOFF^11 >= ULONG_MAX and CUTOFF^3 < ULONG_MAX. * Tests suggest that 200-300 is the best range for 64-bit platforms. */ const ulong CUTOFF = 200UL; const long TINYCUTOFF = 46; /* tinyprimes[45] = 199 */ const ulong CUTOFF3 = CUTOFF*CUTOFF*CUTOFF; #ifdef LONG_IS_64BIT /* primes preceeding the appropriate root of ULONG_MAX. */ const ulong ROOT9 = 137; const ulong ROOT8 = 251; const ulong ROOT7 = 563; const ulong ROOT5 = 7129; const ulong ROOT4 = 65521; #else const ulong ROOT9 = 11; const ulong ROOT8 = 13; const ulong ROOT7 = 23; const ulong ROOT5 = 83; const ulong ROOT4 = 251; #endif ulong mask; long v, i; int e; if (n < 2) return 0; if (!odd(n)) { if (n & (n-1)) return 0; *pp = 2; return vals(n); } if (n < 8) { *pp = n; return 1; } /* 3,5,7 */ for (i = 1/*skip p=2*/; i < TINYCUTOFF; i++) { ulong p = tinyprimes[i]; if (n % p == 0) { v = u_lvalrem(n, p, &n); if (n == 1) { *pp = p; return v; } return 0; } } /* p | n => p >= CUTOFF */ if (n < CUTOFF3) { if (n < CUTOFF*CUTOFF || uisprime_101(n)) { *pp = n; return 1; } if (uissquareall(n, &n)) { *pp = n; return 2; } return 0; } /* Check for squares, fourth powers, and eighth powers as appropriate. */ v = 1; if (uissquareall(n, &n)) { v <<= 1; if (CUTOFF <= ROOT4 && uissquareall(n, &n)) { v <<= 1; if (CUTOFF <= ROOT8 && uissquareall(n, &n)) v <<= 1; } } if (CUTOFF > ROOT5) mask = 1; else { const ulong CUTOFF5 = CUTOFF3*CUTOFF*CUTOFF; if (n < CUTOFF5) mask = 1; else mask = 3; if (CUTOFF <= ROOT7) { const ulong CUTOFF7 = CUTOFF5*CUTOFF*CUTOFF; if (n >= CUTOFF7) mask = 7; } } if (CUTOFF <= ROOT9 && (e = uis_357_power(n, &n, &mask))) { v *= e; mask=1; } if ((e = uis_357_power(n, &n, &mask))) v *= e; if (uisprime_101(n)) { *pp = n; return v; } return 0; } pari-2.17.2/src/basemath/Fle.c0000644000175000017500000005606214567450071014433 0ustar billbill/* Copyright (C) 2014 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" /* Not so fast arithmetic with points over elliptic curves over Fl */ /***********************************************************************/ /** Flj **/ /***********************************************************************/ /* Jacobian coordinates: we represent a projective point (x:y:z) on E by * [z*x, z^2*y, z]. Not the fastest representation available for the problem, * but easy to implement and up to 60% faster than the school-book method. */ /* Cost: 1M + 8S + 1*a + 10add + 1*8 + 2*2 + 1*3. * http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-2007-bl */ INLINE void Flj_dbl_indir_pre(GEN P, GEN Q, ulong a4, ulong p, ulong pi) { ulong X1, Y1, Z1; ulong XX, YY, YYYY, ZZ, S, M, T; X1 = P[1]; Y1 = P[2]; Z1 = P[3]; if (Z1 == 0) { Q[1] = X1; Q[2] = Y1; Q[3] = Z1; return; } XX = Fl_sqr_pre(X1, p, pi); YY = Fl_sqr_pre(Y1, p, pi); YYYY = Fl_sqr_pre(YY, p, pi); ZZ = Fl_sqr_pre(Z1, p, pi); S = Fl_double(Fl_sub(Fl_sqr_pre(Fl_add(X1, YY, p), p, pi), Fl_add(XX, YYYY, p), p), p); M = Fl_addmul_pre(Fl_triple(XX, p), a4, Fl_sqr_pre(ZZ, p, pi), p, pi); T = Fl_sub(Fl_sqr_pre(M, p, pi), Fl_double(S, p), p); Q[1] = T; Q[2] = Fl_sub(Fl_mul_pre(M, Fl_sub(S, T, p), p, pi), Fl_double(Fl_double(Fl_double(YYYY, p), p), p), p); Q[3] = Fl_sub(Fl_sqr_pre(Fl_add(Y1, Z1, p), p, pi), Fl_add(YY, ZZ, p), p); } INLINE void Flj_dbl_pre_inplace(GEN P, ulong a4, ulong p, ulong pi) { Flj_dbl_indir_pre(P, P, a4, p, pi); } GEN Flj_dbl_pre(GEN P, ulong a4, ulong p, ulong pi) { GEN Q = cgetg(4, t_VECSMALL); Flj_dbl_indir_pre(P, Q, a4, p, pi); return Q; } /* Cost: 11M + 5S + 9add + 4*2. * http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#addition-add-2007-bl */ INLINE void Flj_add_indir_pre(GEN P, GEN Q, GEN R, ulong a4, ulong p, ulong pi) { ulong X1, Y1, Z1, X2, Y2, Z2; ulong Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V, W; X1 = P[1]; Y1 = P[2]; Z1 = P[3]; X2 = Q[1]; Y2 = Q[2]; Z2 = Q[3]; if (Z2 == 0) { R[1] = X1; R[2] = Y1; R[3] = Z1; return; } if (Z1 == 0) { R[1] = X2; R[2] = Y2; R[3] = Z2; return; } Z1Z1 = Fl_sqr_pre(Z1, p, pi); Z2Z2 = Fl_sqr_pre(Z2, p, pi); U1 = Fl_mul_pre(X1, Z2Z2, p, pi); U2 = Fl_mul_pre(X2, Z1Z1, p, pi); S1 = Fl_mul_pre(Y1, Fl_mul_pre(Z2, Z2Z2, p, pi), p, pi); S2 = Fl_mul_pre(Y2, Fl_mul_pre(Z1, Z1Z1, p, pi), p, pi); H = Fl_sub(U2, U1, p); r = Fl_double(Fl_sub(S2, S1, p), p); if (H == 0) { if (r == 0) Flj_dbl_indir_pre(P, R, a4, p, pi); /* P = Q */ else { R[1] = R[2] = 1; R[3] = 0; } /* P = -Q */ return; } I = Fl_sqr_pre(Fl_double(H, p), p, pi); J = Fl_mul_pre(H, I, p, pi); V = Fl_mul_pre(U1, I, p, pi); W = Fl_sub(Fl_sqr_pre(r, p, pi), Fl_add(J, Fl_double(V, p), p), p); R[1] = W; R[2] = Fl_sub(Fl_mul_pre(r, Fl_sub(V, W, p), p, pi), Fl_double(Fl_mul_pre(S1, J, p, pi), p), p); R[3] = Fl_mul_pre(Fl_sub(Fl_sqr_pre(Fl_add(Z1, Z2, p), p, pi), Fl_add(Z1Z1, Z2Z2, p), p), H, p, pi); } INLINE void Flj_add_pre_inplace(GEN P, GEN Q, ulong a4, ulong p, ulong pi) { Flj_add_indir_pre(P, Q, P, a4, p, pi); } GEN Flj_add_pre(GEN P, GEN Q, ulong a4, ulong p, ulong pi) { GEN R = cgetg(4, t_VECSMALL); Flj_add_indir_pre(P, Q, R, a4, p, pi); return R; } GEN Flj_neg(GEN Q, ulong p) { return mkvecsmall3(Q[1], Fl_neg(Q[2], p), Q[3]); } typedef struct { ulong pbits, nbits; /* Positive bits and negative bits */ ulong lnzb; /* Leading nonzero bit */ } naf_t; /* Return the signed binary representation (i.e. the Non-Adjacent Form * in base 2) of a; a = x.pbits - x.nbits (+ 2^BILif < 0; this * exceptional case can happen if a > 2^(BIL-1)) */ static void naf_repr(naf_t *x, ulong a) { ulong pbits = 0, nbits = 0, c0 = 0, c1, a0; long t, i; for (i = 0; a; a >>= 1, ++i) { a0 = a & 1; c1 = (c0 + a0 + ((a & 2) >> 1)) >> 1; t = c0 + a0 - (c1 << 1); if (t < 0) nbits |= (1UL << i); else if (t > 0) pbits |= (1UL << i); c0 = c1; } c1 = c0 >> 1; t = c0 - (c1 << 1); /* since a >= 0, we have t >= 0; if i = BIL, pbits (virtually) overflows; * that leading overflowed bit is implied and not recorded in pbits */ if (t > 0 && i != BITS_IN_LONG) pbits |= (1UL << i); x->pbits = pbits; x->nbits = nbits; x->lnzb = t? i-2: i-3; } /* Standard left-to-right signed double-and-add to compute [n]P. */ static GEN Flj_mulu_pre_naf(GEN P, ulong n, ulong a4, ulong p, ulong pi, const naf_t *x) { GEN R, Pi; ulong pbits, nbits; ulong m; if (n == 0) return mkvecsmall3(1, 1, 0); if (n == 1) return Flv_copy(P); R = Flj_dbl_pre(P, a4, p, pi); if (n == 2) return R; pbits = x->pbits; nbits = x->nbits; Pi = nbits? Flj_neg(P, p): NULL; m = (1UL << x->lnzb); for ( ; m; m >>= 1) { Flj_dbl_pre_inplace(R, a4, p, pi); if (m & pbits) Flj_add_pre_inplace(R, P, a4, p, pi); else if (m & nbits) Flj_add_pre_inplace(R, Pi, a4, p, pi); } return gc_const((pari_sp)R, R); } GEN Flj_mulu_pre(GEN P, ulong n, ulong a4, ulong p, ulong pi) { naf_t x; naf_repr(&x, n); return Flj_mulu_pre_naf(P, n, a4, p, pi, &x); } struct _Flj { ulong a4, p, pi; }; static GEN _Flj_add(void *E, GEN P, GEN Q) { struct _Flj *ell=(struct _Flj *) E; return Flj_add_pre(P, Q, ell->a4, ell->p, ell->pi); } static GEN _Flj_mul(void *E, GEN P, GEN n) { struct _Flj *ell = (struct _Flj *) E; long s = signe(n); GEN Q; if (s==0) return mkvecsmall3(1, 1, 0); Q = Flj_mulu_pre(P, itou(n), ell->a4, ell->p, ell->pi); return s>0 ? Q : Flj_neg(Q, ell->p); } static GEN _Flj_one(void *E) { (void) E; return mkvecsmall3(1, 1, 0); } GEN FljV_factorback_pre(GEN P, GEN L, ulong a4, ulong p, ulong pi) { struct _Flj E; E.a4 = a4; E.p = p; E.pi = pi; return gen_factorback(P, L, (void*)&E, &_Flj_add, &_Flj_mul, &_Flj_one); } ulong Flj_order_ufact(GEN P, ulong n, GEN fa, ulong a4, ulong p, ulong pi) { pari_sp av = avma; GEN T = gel(fa,1), E = gel(fa,2); long i, l = lg(T); ulong res = 1; for (i = 1; i < l; i++, set_avma(av)) { ulong j, t = T[i], e = E[i]; GEN b = P; naf_t x; naf_repr(&x, t); if (l != 2) b = Flj_mulu_pre(b, n / upowuu(t,e), a4, p, pi); for (j = 0; j < e && b[3]; j++) b = Flj_mulu_pre_naf(b, t, a4, p, pi, &x); if (b[3]) return 0; res *= upowuu(t, j); } return res; } GEN Fle_to_Flj(GEN P) { return ell_is_inf(P) ? mkvecsmall3(1UL, 1UL, 0UL): mkvecsmall3(P[1], P[2], 1UL); } GEN Flj_to_Fle(GEN P, ulong p) { if (P[3] == 0) return ellinf(); else { ulong Z = Fl_inv(P[3], p); ulong Z2 = Fl_sqr(Z, p); ulong X3 = Fl_mul(P[1], Z2, p); ulong Y3 = Fl_mul(P[2], Fl_mul(Z, Z2, p), p); return mkvecsmall2(X3, Y3); } } GEN Flj_to_Fle_pre(GEN P, ulong p, ulong pi) { if (P[3] == 0) return ellinf(); else { ulong Z = Fl_inv(P[3], p); ulong Z2 = Fl_sqr_pre(Z, p, pi); ulong X3 = Fl_mul_pre(P[1], Z2, p, pi); ulong Y3 = Fl_mul_pre(P[2], Fl_mul_pre(Z, Z2, p, pi), p, pi); return mkvecsmall2(X3, Y3); } } INLINE void random_Fle_pre_indir(ulong a4, ulong a6, ulong p, ulong pi, ulong *pt_x, ulong *pt_y) { ulong x, x2, y, rhs; do { x = random_Fl(p); /* x^3+a4*x+a6 = x*(x^2+a4)+a6 */ x2 = Fl_sqr_pre(x, p, pi); rhs = Fl_addmul_pre(a6, x, Fl_add(x2, a4, p), p, pi); } while ((!rhs && !Fl_add(Fl_triple(x2,p),a4,p)) || krouu(rhs, p) < 0); y = Fl_sqrt_pre(rhs, p, pi); *pt_x = x; *pt_y = y; } GEN random_Flj_pre(ulong a4, ulong a6, ulong p, ulong pi) { ulong x, y; random_Fle_pre_indir(a4, a6, p, pi, &x, &y); return mkvecsmall3(x, y, 1); } GEN Flj_changepointinv_pre(GEN P, GEN ch, ulong p, ulong pi) { ulong c, u, r, s, t, u2, u3, z2; ulong x = uel(P,1), y = uel(P,2), z = uel(P,3); GEN w; if (z == 0) return Flv_copy(P); u = ch[1]; r = ch[2]; s = ch[3]; t = ch[4]; u2 = Fl_sqr_pre(u, p, pi); u3 = Fl_mul_pre(u, u2, p, pi); c = Fl_mul_pre(u2, x, p, pi); z2 = Fl_sqr_pre(z, p, pi); w = cgetg(4, t_VECSMALL); uel(w,1) = Fl_add(c, Fl_mul_pre(r, z2, p, pi), p); uel(w,2) = Fl_add(Fl_mul_pre(u3 ,y, p, pi), Fl_mul_pre(z, Fl_add(Fl_mul_pre(s,c,p,pi), Fl_mul_pre(z2,t,p,pi), p), p, pi), p); uel(w,3) = z; return w; } /***********************************************************************/ /** Fle **/ /***********************************************************************/ GEN Fle_changepoint(GEN P, GEN ch, ulong p) { ulong c, u, r, s, t, v, v2, v3; GEN z; if (ell_is_inf(P)) return ellinf(); u = ch[1]; r = ch[2]; s = ch[3]; t = ch[4]; v = Fl_inv(u, p); v2 = Fl_sqr(v,p); v3 = Fl_mul(v,v2,p); c = Fl_sub(uel(P,1),r,p); z = cgetg(3,t_VECSMALL); z[1] = Fl_mul(v2, c, p); z[2] = Fl_mul(v3, Fl_sub(uel(P,2), Fl_add(Fl_mul(s,c, p),t, p),p),p); return z; } GEN Fle_changepointinv(GEN P, GEN ch, ulong p) { ulong c, u, r, s, t, u2, u3; GEN z; if (ell_is_inf(P)) return ellinf(); u = ch[1]; r = ch[2]; s = ch[3]; t = ch[4]; u2 = Fl_sqr(u, p); u3 = Fl_mul(u,u2,p); c = Fl_mul(u2,uel(P,1), p); z = cgetg(3, t_VECSMALL); z[1] = Fl_add(c,r,p); z[2] = Fl_add(Fl_mul(u3,uel(P,2),p), Fl_add(Fl_mul(s,c,p), t, p), p); return z; } static GEN Fle_dbl_slope(GEN P, ulong a4, ulong p, ulong *slope) { ulong x, y, Qx, Qy; if (ell_is_inf(P) || !P[2]) return ellinf(); x = P[1]; y = P[2]; *slope = Fl_div(Fl_add(Fl_triple(Fl_sqr(x,p), p), a4, p), Fl_double(y, p), p); Qx = Fl_sub(Fl_sqr(*slope, p), Fl_double(x, p), p); Qy = Fl_sub(Fl_mul(*slope, Fl_sub(x, Qx, p), p), y, p); return mkvecsmall2(Qx, Qy); } GEN Fle_dbl(GEN P, ulong a4, ulong p) { ulong slope; return Fle_dbl_slope(P,a4,p,&slope); } static GEN Fle_add_slope(GEN P, GEN Q, ulong a4, ulong p, ulong *slope) { ulong Px, Py, Qx, Qy, Rx, Ry; if (ell_is_inf(P)) return Q; if (ell_is_inf(Q)) return P; Px = P[1]; Py = P[2]; Qx = Q[1]; Qy = Q[2]; if (Px==Qx) return Py==Qy ? Fle_dbl_slope(P, a4, p, slope): ellinf(); *slope = Fl_div(Fl_sub(Py, Qy, p), Fl_sub(Px, Qx, p), p); Rx = Fl_sub(Fl_sub(Fl_sqr(*slope, p), Px, p), Qx, p); Ry = Fl_sub(Fl_mul(*slope, Fl_sub(Px, Rx, p), p), Py, p); return mkvecsmall2(Rx, Ry); } GEN Fle_add(GEN P, GEN Q, ulong a4, ulong p) { ulong slope; return Fle_add_slope(P,Q,a4,p,&slope); } static GEN Fle_neg(GEN P, ulong p) { if (ell_is_inf(P)) return P; return mkvecsmall2(P[1], Fl_neg(P[2], p)); } GEN Fle_sub(GEN P, GEN Q, ulong a4, ulong p) { pari_sp av = avma; ulong slope; return gerepileupto(av, Fle_add_slope(P, Fle_neg(Q, p), a4, p, &slope)); } struct _Fle { ulong a4, a6, p; }; static GEN _Fle_dbl(void *E, GEN P) { struct _Fle *ell = (struct _Fle *) E; return Fle_dbl(P, ell->a4, ell->p); } static GEN _Fle_add(void *E, GEN P, GEN Q) { struct _Fle *ell=(struct _Fle *) E; return Fle_add(P, Q, ell->a4, ell->p); } GEN Fle_mulu(GEN P, ulong n, ulong a4, ulong p) { ulong pi; if (!n || ell_is_inf(P)) return ellinf(); if (n==1) return zv_copy(P); if (n==2) return Fle_dbl(P, a4, p); pi = get_Fl_red(p); return Flj_to_Fle_pre(Flj_mulu_pre(Fle_to_Flj(P), n, a4, p, pi), p, pi); } static GEN _Fle_mul(void *E, GEN P, GEN n) { pari_sp av = avma; struct _Fle *e=(struct _Fle *) E; long s = signe(n); GEN Q; if (!s || ell_is_inf(P)) return ellinf(); if (s < 0) P = Fle_neg(P, e->p); if (is_pm1(n)) return s > 0? zv_copy(P): P; Q = (lgefint(n)==3) ? Fle_mulu(P, uel(n,2), e->a4, e->p): gen_pow(P, n, (void*)e, &_Fle_dbl, &_Fle_add); return s > 0? Q: gerepileuptoleaf(av, Q); } GEN Fle_mul(GEN P, GEN n, ulong a4, ulong p) { struct _Fle E; E.a4 = a4; E.p = p; return _Fle_mul(&E, P, n); } /* Finds a random nonsingular point on E */ GEN random_Fle_pre(ulong a4, ulong a6, ulong p, ulong pi) { ulong x, y; random_Fle_pre_indir(a4, a6, p, pi, &x, &y); return mkvecsmall2(x, y); } GEN random_Fle(ulong a4, ulong a6, ulong p) { return random_Fle_pre(a4, a6, p, get_Fl_red(p)); } static GEN _Fle_rand(void *E) { struct _Fle *e=(struct _Fle *) E; return random_Fle(e->a4, e->a6, e->p); } static const struct bb_group Fle_group={_Fle_add,_Fle_mul,_Fle_rand,hash_GEN,zv_equal,ell_is_inf,NULL}; GEN Fle_order(GEN z, GEN o, ulong a4, ulong p) { pari_sp av = avma; struct _Fle e; e.a4=a4; e.p=p; return gerepileuptoint(av, gen_order(z, o, (void*)&e, &Fle_group)); } GEN Fle_log(GEN a, GEN b, GEN o, ulong a4, ulong p) { pari_sp av = avma; struct _Fle e; e.a4=a4; e.p=p; return gerepileuptoint(av, gen_PH_log(a, b, o, (void*)&e, &Fle_group)); } ulong Fl_ellj(ulong a4, ulong a6, ulong p) { if (SMALL_ULONG(p)) { /* a43 = 4 a4^3 */ ulong a43 = Fl_double(Fl_double(Fl_mul(a4, Fl_sqr(a4, p), p), p), p); /* a62 = 27 a6^2 */ ulong a62 = Fl_mul(Fl_sqr(a6, p), 27 % p, p); ulong z1 = Fl_mul(a43, 1728 % p, p); ulong z2 = Fl_add(a43, a62, p); return Fl_div(z1, z2, p); } return Fl_ellj_pre(a4, a6, p, get_Fl_red(p)); } void Fl_ellj_to_a4a6(ulong j, ulong p, ulong *pt_a4, ulong *pt_a6) { ulong zagier = 1728 % p; if (j == 0) { *pt_a4 = 0; *pt_a6 =1; } else if (j == zagier) { *pt_a4 = 1; *pt_a6 =0; } else { ulong k = Fl_sub(zagier, j, p); ulong kj = Fl_mul(k, j, p); ulong k2j = Fl_mul(kj, k, p); *pt_a4 = Fl_triple(kj, p); *pt_a6 = Fl_double(k2j, p); } } ulong Fl_elldisc_pre(ulong a4, ulong a6, ulong p, ulong pi) { /* D = -(4A^3 + 27B^2) */ ulong t1, t2; t1 = Fl_mul_pre(a4, Fl_sqr_pre(a4, p, pi), p, pi); t1 = Fl_double(Fl_double(t1, p), p); t2 = Fl_mul_pre(27 % p, Fl_sqr_pre(a6, p, pi), p, pi); return Fl_neg(Fl_add(t1, t2, p), p); } ulong Fl_elldisc(ulong a4, ulong a6, ulong p) { if (SMALL_ULONG(p)) { /* D = -(4A^3 + 27B^2) */ ulong t1, t2; t1 = Fl_mul(a4, Fl_sqr(a4, p), p); t1 = Fl_double(Fl_double(t1, p), p); t2 = Fl_mul(27 % p, Fl_sqr(a6, p), p); return Fl_neg(Fl_add(t1, t2, p), p); } return Fl_elldisc_pre(a4, a6, p, get_Fl_red(p)); } void Fl_elltwist_disc(ulong a4, ulong a6, ulong D, ulong p, ulong *pa4, ulong *pa6) { ulong D2 = Fl_sqr(D, p); *pa4 = Fl_mul(a4, D2, p); *pa6 = Fl_mul(a6, Fl_mul(D, D2, p), p); } void Fl_elltwist(ulong a4, ulong a6, ulong p, ulong *pt_a4, ulong *pt_a6) { Fl_elltwist_disc(a4, a6, nonsquare_Fl(p), p, pt_a4, pt_a6); } static void Fle_dbl_sinv_pre_inplace(GEN P, ulong a4, ulong sinv, ulong p, ulong pi) { ulong x, y, slope; if (uel(P,1)==p) return; if (!P[2]) { P[1] = p; return; } x = P[1]; y = P[2]; slope = Fl_mul_pre(Fl_add(Fl_triple(Fl_sqr_pre(x, p, pi), p), a4, p), sinv, p, pi); P[1] = Fl_sub(Fl_sqr_pre(slope, p, pi), Fl_double(x, p), p); P[2] = Fl_sub(Fl_mul_pre(slope, Fl_sub(x, P[1], p), p, pi), y, p); } static void Fle_add_sinv_pre_inplace(GEN P, GEN Q, ulong a4, ulong sinv, ulong p, ulong pi) { ulong Px, Py, Qx, Qy, slope; if (uel(P,1)==p) { P[1] = Q[1]; P[2] = Q[2]; } if (ell_is_inf(Q)) return; Px = P[1]; Py = P[2]; Qx = Q[1]; Qy = Q[2]; if (Px==Qx) { if (Py==Qy) Fle_dbl_sinv_pre_inplace(P, a4, sinv, p, pi); else P[1] = p; return; } slope = Fl_mul_pre(Fl_sub(Py, Qy, p), sinv, p, pi); P[1] = Fl_sub(Fl_sub(Fl_sqr_pre(slope, p, pi), Px, p), Qx, p); P[2] = Fl_sub(Fl_mul_pre(slope, Fl_sub(Px, P[1], p), p, pi), Py, p); } static void Fle_sub_sinv_pre_inplace(GEN P, GEN Q, ulong a4, ulong sinv, ulong p, ulong pi) { ulong Px, Py, Qx, Qy, slope; if (uel(P,1)==p) { P[1] = Q[1]; P[2] = Fl_neg(Q[2], p); } if (ell_is_inf(Q)) return; Px = P[1]; Py = P[2]; Qx = Q[1]; Qy = Q[2]; if (Px==Qx) { if (Py==Qy) P[1] = p; else Fle_dbl_sinv_pre_inplace(P, a4, sinv, p, pi); return; } slope = Fl_mul_pre(Fl_add(Py, Qy, p), sinv, p, pi); P[1] = Fl_sub(Fl_sub(Fl_sqr_pre(slope, p, pi), Px, p), Qx, p); P[2] = Fl_sub(Fl_mul_pre(slope, Fl_sub(Px, P[1], p), p, pi), Py, p); } static long skipzero(long n) { return n ? n:1; } void FleV_add_pre_inplace(GEN P, GEN Q, GEN a4, ulong p, ulong pi) { long i, l=lg(a4); GEN sinv = cgetg(l, t_VECSMALL); for(i=1; ipbits; nbits = x->nbits; m = (1UL << x->lnzb); for ( ; m; m >>= 1) { FleV_dbl_pre_inplace(R, a4, p, pi); if (m & pbits) FleV_add_pre_inplace(R, P, a4, p, pi); else if (m & nbits) FleV_sub_pre_inplace(R, P, a4, p, pi); } set_avma(av); } void FleV_mulu_pre_inplace(GEN P, ulong n, GEN a4, ulong p, ulong pi) { naf_t x; naf_repr(&x, n); FleV_mulu_pre_naf_inplace(P, n, a4, p, pi, &x); } /***********************************************************************/ /** Pairings **/ /** Derived from APIP by Jerome Milan, 2012 **/ /***********************************************************************/ static ulong Fle_vert(GEN P, GEN Q, ulong a4, ulong p) { if (ell_is_inf(P)) return 1; if (uel(Q, 1) != uel(P, 1)) return Fl_sub(uel(Q, 1), uel(P, 1), p); if (uel(P,2) != 0 ) return 1; return Fl_inv(Fl_add(Fl_triple(Fl_sqr(uel(P,1),p), p), a4, p), p); } static ulong Fle_Miller_line(GEN R, GEN Q, ulong slope, ulong a4, ulong p) { ulong x = uel(Q, 1), y = uel(Q, 2); ulong tmp1 = Fl_sub(x, uel(R, 1), p); ulong tmp2 = Fl_add(Fl_mul(tmp1, slope, p), uel(R,2), p); if (y != tmp2) return Fl_sub(y, tmp2, p); if (y == 0) return 1; else { ulong s1, s2; ulong y2i = Fl_inv(Fl_double(y, p), p); s1 = Fl_mul(Fl_add(Fl_triple(Fl_sqr(x, p), p), a4, p), y2i, p); if (s1 != slope) return Fl_sub(s1, slope, p); s2 = Fl_mul(Fl_sub(Fl_triple(x, p), Fl_sqr(s1, p), p), y2i, p); return s2 ? s2: y2i; } } /* Computes the equation of the line tangent to R and returns its * evaluation at the point Q. Also doubles the point R. */ static ulong Fle_tangent_update(GEN R, GEN Q, ulong a4, ulong p, GEN *pt_R) { if (ell_is_inf(R)) { *pt_R = ellinf(); return 1; } else if (uel(R,2) == 0) { *pt_R = ellinf(); return Fle_vert(R, Q, a4, p); } else { ulong slope; *pt_R = Fle_dbl_slope(R, a4, p, &slope); return Fle_Miller_line(R, Q, slope, a4, p); } } /* Computes the equation of the line through R and P, and returns its * evaluation at the point Q. Also adds P to the point R. */ static ulong Fle_chord_update(GEN R, GEN P, GEN Q, ulong a4, ulong p, GEN *pt_R) { if (ell_is_inf(R)) { *pt_R = P; return Fle_vert(P, Q, a4, p); } else if (ell_is_inf(P)) { *pt_R = R; return Fle_vert(R, Q, a4, p); } else if (uel(P, 1) == uel(R, 1)) { if (uel(P, 2) == uel(R, 2)) return Fle_tangent_update(R, Q, a4, p, pt_R); else { *pt_R = ellinf(); return Fle_vert(R, Q, a4, p); } } else { ulong slope; *pt_R = Fle_add_slope(P, R, a4, p, &slope); return Fle_Miller_line(R, Q, slope, a4, p); } } struct _Fle_miller { ulong p, a4; GEN P; }; static GEN Fle_Miller_dbl(void* E, GEN d) { struct _Fle_miller *m = (struct _Fle_miller *)E; ulong p = m->p, a4 = m->a4; GEN P = m->P; ulong v, line; ulong N = Fl_sqr(umael(d,1,1), p); ulong D = Fl_sqr(umael(d,1,2), p); GEN point = gel(d,2); line = Fle_tangent_update(point, P, a4, p, &point); N = Fl_mul(N, line, p); v = Fle_vert(point, P, a4, p); D = Fl_mul(D, v, p); return mkvec2(mkvecsmall2(N, D), point); } static GEN Fle_Miller_add(void* E, GEN va, GEN vb) { struct _Fle_miller *m = (struct _Fle_miller *)E; ulong p = m->p, a4= m->a4; GEN P = m->P, point; ulong v, line; ulong na = umael(va,1,1), da = umael(va,1,2); ulong nb = umael(vb,1,1), db = umael(vb,1,2); GEN pa = gel(va,2), pb = gel(vb,2); ulong N = Fl_mul(na, nb, p); ulong D = Fl_mul(da, db, p); line = Fle_chord_update(pa, pb, P, a4, p, &point); N = Fl_mul(N, line, p); v = Fle_vert(point, P, a4, p); D = Fl_mul(D, v, p); return mkvec2(mkvecsmall2(N, D), point); } /* Returns the Miller function f_{m, Q} evaluated at the point P using * the standard Miller algorithm. */ static ulong Fle_Miller(GEN Q, GEN P, ulong m, ulong a4, ulong p) { pari_sp av = avma; struct _Fle_miller d; GEN v; ulong N, D; d.a4 = a4; d.p = p; d.P = P; v = gen_powu_i(mkvec2(mkvecsmall2(1,1), Q), m, (void*)&d, Fle_Miller_dbl, Fle_Miller_add); N = umael(v,1,1); D = umael(v,1,2); return gc_ulong(av, Fl_div(N, D, p)); } ulong Fle_weilpairing(GEN P, GEN Q, ulong m, ulong a4, ulong p) { pari_sp ltop = avma; ulong N, D, w; if (ell_is_inf(P) || ell_is_inf(Q) || zv_equal(P,Q)) return 1; N = Fle_Miller(P, Q, m, a4, p); D = Fle_Miller(Q, P, m, a4, p); w = Fl_div(N, D, p); if (odd(m)) w = Fl_neg(w, p); return gc_ulong(ltop, w); } ulong Fle_tatepairing(GEN P, GEN Q, ulong m, ulong a4, ulong p) { if (ell_is_inf(P) || ell_is_inf(Q)) return 1; return Fle_Miller(P, Q, m, a4, p); } GEN Fl_ellptors(ulong l, ulong N, ulong a4, ulong a6, ulong p) { long v = z_lval(N, l); ulong N0, N1; GEN F; if (v==0) return cgetg(1,t_VEC); N0 = upowuu(l, v); N1 = N/N0; F = mkmat2(mkcols(l), mkcols(v)); while(1) { pari_sp av2 = avma; GEN P, Q; ulong d, s, t; P = Fle_mulu(random_Fle(a4, a6, p), N1, a4, p); Q = Fle_mulu(random_Fle(a4, a6, p), N1, a4, p); s = itou(Fle_order(P, F, a4, p)); t = itou(Fle_order(Q, F, a4, p)); if (s < t) { swap(P,Q); lswap(s,t); } if (s == N0) retmkvec(Fle_mulu(P, s/l, a4, p)); d = Fl_order(Fle_weilpairing(P, Q, s, a4, p), s, p); if (s*d == N0) retmkvec2(Fle_mulu(P, s/l, a4, p), Fle_mulu(Q, t/l, a4, p)); set_avma(av2); } } pari-2.17.2/src/basemath/ellpadiclambdamu.c0000644000175000017500000001411014567450071017171 0ustar billbill/* Copyright (C) 2011 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pari.h" #include "paripriv.h" /** Batch p-adic logarithms **/ /* a/b mod q */ static ulong divmodulo(ulong a, ulong b, ulong p, ulong q) { long v = u_lvalrem(b, p, &b); if (v) a /= upowuu(p,v); /* a/b is now a p-integer */ return Fl_div(a, b, q); } /* to compute log_p(a) mod q = p^n, p < 2^31 */ static GEN initQplog(long p, ulong q, long n) { long i, nn, nt; ulong a, P; GEN C; for(nn = n, nt = n + 1; nn >= p; nn /= p) nt++; if (p == 2) { P = q - 8; while (3 * (nt - 1) > u_lval(nt-1, p) + n) nt--; } else { P = q - p; while (nt > u_lval(nt-1, p) + n) nt--; } C = cgetg(nt, t_VECSMALL); /* [ P^(k-1) / k, k = 1..nt ] / (p - 1) */ for(i = 1, a = 1; i < nt; i++, a = Fl_mul(a, P, q)) C[i] = divmodulo(a, i * (p-1), p, q); return C; } /* compute log_p(a) / p (resp. log_2(a) / 4) mod p^n, 'a' a p-unit, * C = initQplog(p,q,n), q = p^n */ static ulong logp(GEN C, ulong a, ulong p, ulong q, ulong pn) { long i, b, z, n = lg(C)-1; a %= q; /* Euclidean quotient (a^2 = 1 mod 8, a^(p-1) = 1 mod p) */ if (p == 2) b = Fl_sqr(a, q << 1) >> 3; else b = Fl_powu(a, p-1, q) / p; z = Fl_mul(b, C[n], pn); for (i = n-1; i > 0; i--) z = Fl_mul(z + C[i], b, pn); return z; } /* p-adic integration against d mu_E, mod p^n, m > 0. D fundamental, * W a msinit for k = 2, xpm an eigensymbol. * Assume |D p^n| < MAX_LONG. Much cheaper than oms at low precision. * Return 1/2 * correct value [half loop over a]. Assume xpm belongs to * (-1)^i (D/-1) - part */ static GEN polPn(GEN W, GEN xpm, long p, long D, long R, long n) { pari_sp av = avma, av2; long N = (p == 2)? n + 2: n + 1; ulong aD = labs(D), pn = upowuu(p, n), q = upowuu(p, N), ic = 0; GEN v, Dq = muluu(aD, q), nc = icopy(gen_1), c = mkfrac(nc, Dq); GEN C = n? initQplog(p, q, N): NULL; GEN tab = R? ZV_to_Flv(teichmullerinit(p, N), q): NULL; long a, A = itou(shifti(Dq,-1)); if (n) ic = Fl_inv(logp(C, 1 + (p == 2? 4: p), p, q, pn), pn); v = zero_zv(pn); av2 = avma; for (a = 1; a <= A; a++, set_avma(av2)) { GEN X; long s, ap = a % p; ulong x, j; if (!ap || !(s = kross(D,a))) continue; nc[2] = (long)a; X = mseval2_ooQ(W, xpm, c); /* xpm(a / Dq) */ x = umodiu(X, q); if (!x) continue; /* log(a) / log(c) */ j = n? Fl_mul(logp(C, a, p, q, pn), ic, pn): 0; if (R) x = Fl_mul(x, tab[Fl_powu(ap, R, p)], q); if (s < 0) x = Fl_neg(x, q); v[j + 1] = Fl_add(v[j + 1], x, q); } v = Flv_to_Flx(v, evalvarn(0)); v = zlx_translate1(v, p, N); return gerepileupto(av, Flx_to_ZX(v)); } /* return lambda, assuming mu = 0 [else infinite loop] */ static long lambda_ss(GEN W, GEN xpm, long v, long p, long D, long R, long n) { for (;; n += 2) { GEN P = polPn(W, xpm, p, D, R, n); long mu; if (!signe(P)) continue; mu = ZX_lvalrem(P, p, &P) + v; if (!mu) { long M = upowuu(p,n); if (odd(n)) M -= p; else M--; M /= p + 1; return Flx_val(ZX_to_Flx(P, p)) - M; } } } /* return lambda, assuming mu = 0 [else infinite loop] */ static long lambda_ord(GEN W, GEN xpm, long v, long p, long D, long R, GEN ap) { GEN P1, P0 = polPn(W, xpm, p, D, R, 0); long n; for (n = 1;; n++, P0 = P1) { long mu, pn = upowuu(p,n); GEN P, xi, alpha, Q = utoipos(pn); P1 = polPn(W, xpm, p, D, R, n); alpha = mspadic_unit_eigenvalue(ap, 2, utoipos(p), n+1); alpha = padic_to_Q(ginv(alpha)); xi = FpX_translate(polcyclo(pn, 0), gen_1, Q); P = ZX_sub(P1, ZX_Z_mul(FpX_mul(P0, xi, Q), alpha)); /* mod p^n */ if (!signe(P) || n + v <= 0) continue; mu = ZX_lvalrem(P, p, &P) + v; if (!mu) return Flx_val(ZX_to_Flx(P, p)); } } GEN ellpadiclambdamu(GEN E, long p, long D, long R) { pari_sp av = avma; long vC, s, muadd = 0; GEN W, xpm, C, ap; if (!sisfundamental(D)) pari_err_DOMAIN("ellpadiclambdamu", "isfundamental(D)","=", gen_0, stoi(D)); s = D < 0? -1: 1; if (odd(R)) s = -s; ap = ellap(E, utoi(p)); if (ell_get_type(E) != t_ELL_Q) pari_err_TYPE("ellpadiclambdamu", E); if (!umodiu(ap, p)) { if (Z_lval(ellQ_get_N(E), p) >= 2) pari_err_IMPL("additive reduction in ellpadiclambdamu"); ap = NULL; /* supersingular */ } if (ap) { /* ordinary */ GEN v = ellisomat(E, p, 1), vE = gel(v,1), M = gel(v,2); if (lg(M) != 2) /* some p-isogeny */ { long i, imax = 0, l = lg(vE); GEN wmax = NULL, vw = cgetg(l, t_VEC); for (i = 1; i < l; i++) { GEN w, e = ellinit(gel(vE,i), gen_1, 0), em = ellminimalmodel(e, NULL); gel(vE,i) = em; obj_free(e); w = ellQtwist_bsdperiod(gel(vE,i), s); if (s < 0) w = gel(w,2); gel(vw,i) = w; /* w is a positive real number, either Omega^+ or Omega^- / I */ if (!imax || gcmp(w, wmax) > 0) { imax = i; wmax = w; } } if (imax != 1) muadd = Z_lval(ground(gdiv(gel(vw,imax), gel(vw,1))), p); for (i = 1; i < l; i++) obj_free(gel(vE,i)); E = gel(vE, imax); } } W = msfromell(E, s); xpm = gel(W,2); W = gel(W,1); xpm = Q_primitive_part(xpm, &C); vC = C? Q_pval(C, utoipos(p)): 0; if (p == 2) vC++; /* due to half-loop in polPn */ if (vC > 0) pari_err_BUG("ellpadiclambdamu [mu > 0]"); if (ap) { /* ordinary */ long L = lambda_ord(W, xpm, vC, p, D, R, ap); set_avma(av); return mkvec2s(L, muadd); } else { long Lp = lambda_ss(W, xpm, vC, p, D, R, 0); long Lm = lambda_ss(W, xpm, vC, p, D, R, 1); set_avma(av); retmkvec2(mkvec2s(Lp, Lm), zerovec(2)); } } pari-2.17.2/src/basemath/FF.c0000644000175000017500000014553614760123736014225 0ustar billbill/* Copyright (C) 2000-2003 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" /*************************************************************************/ /** **/ /** Routines for handling FFELT **/ /** **/ /*************************************************************************/ /*************************************************************************/ /** **/ /** Low-level constructors **/ /** **/ /*************************************************************************/ INLINE void _getFF(GEN x, GEN *T, GEN *p, ulong *pp) { *T=gel(x,3); *p=gel(x,4); *pp=(*p)[2]; } INLINE GEN _initFF(GEN x, GEN *T, GEN *p, ulong *pp) { _getFF(x,T,p,pp); return cgetg(5,t_FFELT); } INLINE void _checkFF(GEN x, GEN y, const char *s) { if (!FF_samefield(x,y)) pari_err_OP(s,x,y); } INLINE GEN _mkFF(GEN x, GEN z, GEN r) { z[1]=x[1]; gel(z,2)=r; gel(z,3)=gcopy(gel(x,3)); gel(z,4)=icopy(gel(x,4)); return z; } INLINE GEN _mkFF_i(GEN x, GEN z, GEN r) { z[1]=x[1]; gel(z,2)=r; gel(z,3)=gel(x,3); gel(z,4)=gel(x,4); return z; } INLINE GEN mkFF_i(GEN x, GEN r) { GEN z = cgetg(5,t_FFELT); return _mkFF_i(x,z,r); } /*************************************************************************/ /** **/ /** medium-level constructors **/ /** **/ /*************************************************************************/ static GEN Z_to_raw(GEN x, GEN ff) { ulong pp; GEN T, p; _getFF(ff,&T,&p,&pp); switch(ff[1]) { case t_FF_FpXQ: return scalarpol(x, varn(T)); case t_FF_F2xq: return Z_to_F2x(x, T[1]); default: return Z_to_Flx(x, pp, T[1]); } } static GEN Rg_to_raw(GEN x, GEN ff) { long tx = typ(x); switch(tx) { case t_INT: case t_FRAC: case t_PADIC: case t_INTMOD: return Z_to_raw(Rg_to_Fp(x, FF_p_i(ff)), ff); case t_FFELT: if (!FF_samefield(x,ff)) pari_err_MODULUS("Rg_to_raw",x,ff); return gel(x,2); } pari_err_TYPE("Rg_to_raw",x); return NULL;/* LCOV_EXCL_LINE */ } static GEN FFX_to_raw(GEN x, GEN ff) { long i, lx; GEN y = cgetg_copy(x,&lx); y[1] = x[1]; for(i=2; i>VARNSHIFT; } } long FF_f(GEN x) { switch(x[1]) { case t_FF_F2xq: return F2x_degree(gel(x,3)); default: return degpol(gel(x,3)); } } GEN FF_to_F2xq(GEN x) { switch(x[1]) { case t_FF_FpXQ: return ZX_to_F2x(gel(x,2)); case t_FF_F2xq: return zv_copy(gel(x,2)); default: return Flx_to_F2x(gel(x,2)); } } GEN FF_to_F2xq_i(GEN x) { switch(x[1]) { case t_FF_FpXQ: return ZX_to_F2x(gel(x,2)); case t_FF_F2xq: return gel(x,2); default: return Flx_to_F2x(gel(x,2)); } } GEN FF_to_Flxq(GEN x) { switch(x[1]) { case t_FF_FpXQ: return ZX_to_Flx(gel(x,2),itou(gel(x,4))); case t_FF_F2xq: return F2x_to_Flx(gel(x,2)); default: return zv_copy(gel(x,2)); } } GEN FF_to_Flxq_i(GEN x) { switch(x[1]) { case t_FF_FpXQ: return ZX_to_Flx(gel(x,2),itou(gel(x,4))); case t_FF_F2xq: return F2x_to_Flx(gel(x,2)); default: return gel(x,2); } } GEN FF_to_FpXQ(GEN x) { switch(x[1]) { case t_FF_FpXQ: return ZX_copy(gel(x,2)); case t_FF_F2xq: return F2x_to_ZX(gel(x,2)); default: return Flx_to_ZX(gel(x,2)); } } GEN FF_to_FpXQ_i(GEN x) { switch(x[1]) { case t_FF_FpXQ: return gel(x,2); case t_FF_F2xq: return F2x_to_ZX(gel(x,2)); default: return Flx_to_ZX(gel(x,2)); } } GEN FF_add(GEN x, GEN y) { ulong pp; GEN r, T, p, z=_initFF(x,&T,&p,&pp); _checkFF(x,y,"+"); switch(x[1]) { case t_FF_FpXQ: r=FpX_add(gel(x,2),gel(y,2),p); break; case t_FF_F2xq: r=F2x_add(gel(x,2),gel(y,2)); break; default: r=Flx_add(gel(x,2),gel(y,2),pp); } return _mkFF(x,z,r); } GEN FF_sub(GEN x, GEN y) { ulong pp; GEN r, T, p, z=_initFF(x,&T,&p,&pp); _checkFF(x,y,"+"); switch(x[1]) { case t_FF_FpXQ: r=FpX_sub(gel(x,2),gel(y,2),p); break; case t_FF_F2xq: r=F2x_add(gel(x,2),gel(y,2)); break; default: r=Flx_sub(gel(x,2),gel(y,2),pp); } return _mkFF(x,z,r); } GEN FF_Z_add(GEN x, GEN y) { ulong pp; GEN r, T, p, z=_initFF(x,&T,&p,&pp); switch(x[1]) { case t_FF_FpXQ: { pari_sp av=avma; r=gerepileupto(av,FpX_Fp_add(gel(x,2),modii(y,p),p)); break; } case t_FF_F2xq: r=mpodd(y)?F2x_1_add(gel(x,2)):vecsmall_copy(gel(x,2)); break; default: r=Flx_Fl_add(gel(x,2),umodiu(y,pp),pp); } return _mkFF(x,z,r); } GEN FF_Q_add(GEN x, GEN y) { ulong pp; GEN r, T, p, z=_initFF(x,&T,&p,&pp); switch(x[1]) { case t_FF_FpXQ: { pari_sp av=avma; r=gerepileupto(av,FpX_Fp_add(gel(x,2),Rg_to_Fp(y,p),p)); break; } case t_FF_F2xq: r=Rg_to_Fl(y,pp)?F2x_1_add(gel(x,2)):vecsmall_copy(gel(x,2)); break; default: r=Flx_Fl_add(gel(x,2),Rg_to_Fl(y,pp),pp); } return _mkFF(x,z,r); } GEN FF_neg(GEN x) { ulong pp; GEN r, T, p, z=_initFF(x,&T,&p,&pp); switch(x[1]) { case t_FF_FpXQ: r=FpX_neg(gel(x,2),p); break; case t_FF_F2xq: r=vecsmall_copy(gel(x,2)); break; default: r=Flx_neg(gel(x,2),pp); } return _mkFF(x,z,r); } GEN FF_neg_i(GEN x) { ulong pp; GEN r, T, p, z=_initFF(x,&T,&p,&pp); switch(x[1]) { case t_FF_FpXQ: r=FpX_neg(gel(x,2),p); break; case t_FF_F2xq: r=gel(x,2); break; default: r=Flx_neg(gel(x,2),pp); } return _mkFF_i(x,z,r); } GEN FF_map(GEN m, GEN x) { ulong pp; GEN r, T, p, z=_initFF(m,&T,&p,&pp); switch(m[1]) { case t_FF_FpXQ: r=FpX_FpXQ_eval(gel(x,2),gel(m,2),T,p); break; case t_FF_F2xq: r=F2x_F2xq_eval(gel(x,2),gel(m,2),T); break; default: r=Flx_Flxq_eval(gel(x,2),gel(m,2),T,pp); } return _mkFF(m,z,r); } GEN FF_Frobenius(GEN x, long e) { ulong pp; GEN r, T, p, z=_initFF(x,&T,&p,&pp); ulong n = umodsu(e, FF_f(x)); pari_sp av = avma; if (n==0) return gcopy(x); switch(x[1]) { case t_FF_FpXQ: r=FpX_Frobenius(T,p); if (n>1) r=FpXQ_autpow(r,n,T,p); break; case t_FF_F2xq: r=F2x_Frobenius(T); if (n>1) r=F2xq_autpow(r,n,T); break; default: r=Flx_Frobenius(T,pp); if (n>1) r=Flxq_autpow(r,n,T,pp); } r = gerepileupto(av, r); return _mkFF(x,z,r); } static GEN FFX_preimage_i(GEN x, GEN y, GEN F, GEN T, GEN p, long pp) { GEN r; F = FFX_to_raw(F, y); switch(y[1]) { case t_FF_FpXQ: r = FpXQX_rem(gel(x,2), F, T, p); break; case t_FF_F2xq: r = F2xqX_rem(F2x_to_F2xX(gel(x,2),T[1]), F, T); break; default: r = FlxqX_rem(Flx_to_FlxX(gel(x,2),T[1]), F, T, pp); } return r; } GEN FFX_preimage(GEN x, GEN F, GEN y) { GEN r, T, p, z; ulong pp; if (FF_equal0(x)) return FF_zero(y); z = _initFF(y,&T,&p,&pp); r = FFX_preimage_i(x, y, F, T, p, pp); if (degpol(r) > 0) return NULL; r = (y[1] == t_FF_FpXQ)? Fq_to_FpXQ(gel(r,2),T, p): gel(r,2); return _mkFF(y,z,r); } GEN FFX_preimagerel(GEN x, GEN F, GEN y) { pari_sp av = avma; GEN r, T, p; ulong pp; if (FF_equal0(x)) return FF_zero(y); _getFF(y,&T,&p,&pp); r = FFX_preimage_i(x, y, F, T, p, pp); return gerepilecopy(av, raw_to_FFX(r, y)); } GEN FF_mul(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=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,gerepileupto(av, r)); } GEN FF_Z_mul(GEN x, GEN y) { ulong pp; GEN r, T, p, A = gel(x,2), z=_initFF(x,&T,&p,&pp); switch(x[1]) { case t_FF_FpXQ: /* modii(y,p) left on stack for efficiency */ r = FpX_Fp_mul(A, modii(y,p),p); break; case t_FF_F2xq: r = mpodd(y)? vecsmall_copy(A): zero_Flx(A[1]); break; default: r = Flx_Fl_mul(A, umodiu(y,pp), pp); } return _mkFF(x,z,r); } GEN FF_Z_Z_muldiv(GEN x, GEN a, GEN b) { ulong pp; GEN r, T, p, A = gel(x,2), z=_initFF(x,&T,&p,&pp); switch(x[1]) { case t_FF_FpXQ: /* Fp_div(a,b,p) left on stack for efficiency */ r = FpX_Fp_mul(A, Fp_div(a,b,p), p); break; case t_FF_F2xq: if (!mpodd(b)) pari_err_INV("FF_Z_Z_muldiv", b); r = mpodd(a)? vecsmall_copy(A): zero_Flx(A[1]); break; default: r = Flx_Fl_mul(A, Fl_div(umodiu(a,pp),umodiu(b,pp),pp),pp); } return _mkFF(x,z,r); } GEN FF_sqr(GEN x) { ulong pp; GEN r, T, p, z=_initFF(x,&T,&p,&pp); switch(x[1]) { case t_FF_FpXQ: { pari_sp av=avma; r=gerepileupto(av,FpXQ_sqr(gel(x,2),T,p)); break; } case t_FF_F2xq: r=F2xq_sqr(gel(x,2),T); break; default: r=Flxq_sqr(gel(x,2),T,pp); } return _mkFF(x,z,r); } GEN FF_mul2n(GEN x, long n) { ulong pp; GEN r, T, p, A = gel(x,2), z=_initFF(x,&T,&p,&pp); switch(x[1]) { case t_FF_FpXQ: { GEN p1; /* left on stack for efficiency */ if (n>0) p1=remii(int2n(n),p); else p1=Fp_inv(remii(int2n(-n),p),p); r = FpX_Fp_mul(A, p1, p); } break; case t_FF_F2xq: if (n<0) pari_err_INV("FF_mul2n", gen_2); r = n==0? vecsmall_copy(A): zero_Flx(A[1]); break; default: { ulong l1; if (n>0) l1 = umodiu(int2n(n),pp); else l1 = Fl_inv(umodiu(int2n(-n),pp),pp); r = Flx_Fl_mul(A,l1,pp); } } return _mkFF(x,z,r); } GEN FF_inv(GEN x) { ulong pp; GEN r, T, p, z=_initFF(x,&T,&p,&pp); pari_sp av=avma; switch(x[1]) { case t_FF_FpXQ: r=gerepileupto(av,FpXQ_inv(gel(x,2),T,p)); break; case t_FF_F2xq: r=F2xq_inv(gel(x,2),T); break; default: r=Flxq_inv(gel(x,2),T,pp); } return _mkFF(x,z,r); } GEN FF_div(GEN x, GEN y) { ulong pp; GEN r, T, p, z=_initFF(x,&T,&p,&pp); pari_sp av=avma; _checkFF(x,y,"/"); switch(x[1]) { case t_FF_FpXQ: r=gerepileupto(av,FpXQ_div(gel(x,2),gel(y,2),T,p)); break; case t_FF_F2xq: r=gerepileupto(av,F2xq_div(gel(x,2),gel(y,2),T)); break; default: r=gerepileupto(av,Flxq_div(gel(x,2),gel(y,2),T,pp)); } return _mkFF(x,z,r); } GEN Z_FF_div(GEN n, GEN x) { ulong pp; GEN r, T, p, A = gel(x,2), z=_initFF(x,&T,&p,&pp); pari_sp av=avma; switch(x[1]) { case t_FF_FpXQ: r = gerepileupto(av,FpX_Fp_mul(FpXQ_inv(A,T,p),modii(n,p),p)); break; case t_FF_F2xq: r = F2xq_inv(A,T); /*Check for division by 0*/ if(!mpodd(n)) { set_avma(av); r = zero_Flx(A[1]); } break; default: r = gerepileupto(av, Flx_Fl_mul(Flxq_inv(A,T,pp),umodiu(n,pp),pp)); } return _mkFF(x,z,r); } GEN FF_sqrtn(GEN x, GEN n, GEN *zetan) { ulong pp; GEN r, T, p, y=_initFF(x,&T,&p,&pp); switch (x[1]) { case t_FF_FpXQ: r=FpXQ_sqrtn(gel(x,2),n,T,p,zetan); break; case t_FF_F2xq: r=F2xq_sqrtn(gel(x,2),n,T,zetan); break; default: r=Flxq_sqrtn(gel(x,2),n,T,pp,zetan); } if (!r) pari_err_SQRTN("FF_sqrtn",x); (void)_mkFF(x, y, r); if (zetan) { GEN z = cgetg(lg(y),t_FFELT); *zetan=_mkFF(x, z, *zetan); } return y; } GEN FF_sqrt(GEN x) { ulong pp; GEN r, T, p, y=_initFF(x,&T,&p,&pp); switch (x[1]) { case t_FF_FpXQ: r = FpXQ_sqrt(gel(x,2),T,p); break; case t_FF_F2xq: r = F2xq_sqrt(gel(x,2),T); break; default: r = Flxq_sqrt(gel(x,2),T,pp); } if (!r) pari_err_SQRTN("FF_sqrt",x); return _mkFF(x, y, r); } long FF_issquare(GEN x) { GEN T, p; ulong pp; _getFF(x, &T, &p, &pp); switch(x[1]) { case t_FF_FpXQ: return FpXQ_issquare(gel(x,2), T, p); case t_FF_F2xq: return 1; default: /* case t_FF_Flxq: */ return Flxq_issquare(gel(x,2), T, pp); } } long FF_issquareall(GEN x, GEN *pt) { if (!pt) return FF_issquare(x); return FF_ispower(x, gen_2, pt); } long FF_ispower(GEN x, GEN K, GEN *pt) { ulong pp; GEN z, r, T, p; pari_sp av = avma; if (FF_equal0(x)) { if (pt) *pt = gcopy(x); return 1; } _getFF(x, &T, &p, &pp); z = pt? cgetg(5,t_FFELT): NULL; switch(x[1]) { case t_FF_FpXQ: r = FpXQ_sqrtn(gel(x,2),K,T,p,NULL); break; case t_FF_F2xq: r = F2xq_sqrtn(gel(x,2),K,T,NULL); break; default: /* case t_FF_Flxq: */ r = Flxq_sqrtn(gel(x,2),K,T,pp,NULL); break; } if (!r) return gc_long(av,0); if (pt) { *pt = z; (void)_mkFF(x,z,r); } return 1; } GEN FF_pow(GEN x, GEN n) { ulong pp; GEN r, T, p, z=_initFF(x,&T,&p,&pp); switch(x[1]) { case t_FF_FpXQ: r = FpXQ_pow(gel(x,2), n, T, p); break; case t_FF_F2xq: r = F2xq_pow(gel(x,2), n, T); break; default: r = Flxq_pow(gel(x,2), n, T, pp); } return _mkFF(x,z,r); } GEN FF_norm(GEN x) { ulong pp; GEN T,p; _getFF(x,&T,&p,&pp); switch (x[1]) { case t_FF_FpXQ: return FpXQ_norm(gel(x,2),T,p); case t_FF_F2xq: return lgpol(gel(x,2))?gen_1:gen_0; default: return utoi(Flxq_norm(gel(x,2),T,pp)); } } GEN FF_trace(GEN x) { ulong pp; GEN T,p; _getFF(x,&T,&p,&pp); switch(x[1]) { case t_FF_FpXQ: return FpXQ_trace(gel(x,2),T,p); case t_FF_F2xq: return F2xq_trace(gel(x,2),T)?gen_1:gen_0; default: return utoi(Flxq_trace(gel(x,2),T,pp)); } } GEN FF_conjvec(GEN x) { ulong pp; GEN r,T,p,v; long i,l; pari_sp av; _getFF(x,&T,&p,&pp); av = avma; switch(x[1]) { case t_FF_FpXQ: v = FpXQ_conjvec(gel(x,2), T, p); break; case t_FF_F2xq: v = F2xq_conjvec(gel(x,2), T); break; default: v = Flxq_conjvec(gel(x,2), T, pp); } l = lg(v); r = cgetg(l, t_COL); for(i=1; i0; i--) if (!Rg_is_FF(gel(x,i), ff)) return 0; return (*ff != NULL); } int RgM_is_FFM(GEN x, GEN *ff) { long j, lx = lg(x); for (j=lx-1; j>0; j--) if (!RgC_is_FFC(gel(x,j), ff)) return 0; return (*ff != NULL); } static GEN FqC_to_FpXQC(GEN x, GEN T, GEN p) { long i, lx; GEN y = cgetg_copy(x,&lx); for(i=1; i t_MAT */ static GEN FFM_wrap(GEN M, GEN ff, GEN (*Fq)(GEN,GEN,GEN), GEN (*Flxq)(GEN,GEN,ulong), GEN (*F2xq)(GEN,GEN)) { pari_sp av = avma; ulong pp; GEN T, p; _getFF(ff,&T,&p,&pp); M = FFM_to_raw(M, ff); switch(ff[1]) { case t_FF_FpXQ: M = Fq(M,T,p); if (M) M = FqM_to_FpXQM(M,T,p); break; case t_FF_F2xq: M = F2xq(M,T); break; default: M = Flxq(M,T,pp); break; } if (!M) return gc_NULL(av); return gerepilecopy(av, raw_to_FFM(M, ff)); } /* for functions (t_MAT, t_MAT) -> t_MAT */ static GEN FFM_FFM_wrap(GEN M, GEN N, GEN ff, GEN (*Fq)(GEN, GEN, GEN, GEN), GEN (*Flxq)(GEN, GEN, GEN, ulong), GEN (*F2xq)(GEN, GEN, GEN)) { pari_sp av = avma; ulong pp; GEN T, p; int is_sqr = M==N; _getFF(ff, &T, &p, &pp); M = FFM_to_raw(M, ff); N = is_sqr? M: FFM_to_raw(N, ff); switch(ff[1]) { case t_FF_FpXQ: M = Fq(M, N, T, p); if (M) M = FqM_to_FpXQM(M, T, p); break; case t_FF_F2xq: M = F2xq(M, N, T); break; default: M = Flxq(M, N, T, pp); break; } if (!M) return gc_NULL(av); return gerepilecopy(av, raw_to_FFM(M, ff)); } /* for functions (t_MAT, t_COL) -> t_COL */ static GEN FFM_FFC_wrap(GEN M, GEN C, GEN ff, GEN (*Fq)(GEN, GEN, GEN, GEN), GEN (*Flxq)(GEN, GEN, GEN, ulong), GEN (*F2xq)(GEN, GEN, GEN)) { pari_sp av = avma; ulong pp; GEN T, p; _getFF(ff, &T, &p, &pp); M = FFM_to_raw(M, ff); C = FFC_to_raw(C, ff); switch(ff[1]) { case t_FF_FpXQ: C = Fq(M, C, T, p); if (C) C = FqC_to_FpXQC(C, T, p); break; case t_FF_F2xq: C = F2xq(M, C, T); break; default: C = Flxq(M, C, T, pp); break; } if (!C) return gc_NULL(av); return gerepilecopy(av, raw_to_FFC(C, ff)); } GEN FFM_ker(GEN M, GEN ff) { return FFM_wrap(M,ff, &FqM_ker,&FlxqM_ker,&F2xqM_ker); } GEN FFM_image(GEN M, GEN ff) { return FFM_wrap(M,ff, &FqM_image,&FlxqM_image,&F2xqM_image); } GEN FFM_inv(GEN M, GEN ff) { return FFM_wrap(M,ff, &FqM_inv,&FlxqM_inv,&F2xqM_inv); } GEN FFM_suppl(GEN M, GEN ff) { return FFM_wrap(M,ff, &FqM_suppl,&FlxqM_suppl,&F2xqM_suppl); } GEN FFM_deplin(GEN M, GEN ff) { pari_sp av = avma; ulong pp; GEN C, T, p; _getFF(ff, &T, &p, &pp); M = FFM_to_raw(M, ff); switch(ff[1]) { case t_FF_FpXQ: C = FqM_deplin(M, T, p); if (C) C = FqC_to_FpXQC(C, T, p); break; case t_FF_F2xq: C = F2xqM_deplin(M, T); break; default: C = FlxqM_deplin(M, T, pp); break; } if (!C) return gc_NULL(av); return gerepilecopy(av, raw_to_FFC(C, ff)); } GEN FFM_indexrank(GEN M, GEN ff) { pari_sp av = avma; ulong pp; GEN R, T, p; _getFF(ff,&T,&p,&pp); M = FFM_to_raw(M, ff); switch(ff[1]) { case t_FF_FpXQ: R = FqM_indexrank(M,T,p); break; case t_FF_F2xq: R = F2xqM_indexrank(M,T); break; default: R = FlxqM_indexrank(M,T,pp); break; } return gerepileupto(av, R); } long FFM_rank(GEN M, GEN ff) { pari_sp av = avma; long r; ulong pp; GEN T, p; _getFF(ff,&T,&p,&pp); M = FFM_to_raw(M, ff); switch(ff[1]) { case t_FF_FpXQ: r = FqM_rank(M,T,p); break; case t_FF_F2xq: r = F2xqM_rank(M,T); break; default: r = FlxqM_rank(M,T,pp); break; } return gc_long(av,r); } GEN FFM_det(GEN M, GEN ff) { pari_sp av = avma; ulong pp; GEN d, T, p; _getFF(ff,&T,&p,&pp); M = FFM_to_raw(M, ff); switch(ff[1]) { case t_FF_FpXQ: d = FqM_det(M,T,p); break; case t_FF_F2xq: d = F2xqM_det(M,T); break; default: d = FlxqM_det(M,T,pp); break; } return gerepilecopy(av, mkFF_i(ff, d)); } GEN FFM_FFC_gauss(GEN M, GEN C, GEN ff) { return FFM_FFC_wrap(M, C, ff, FqM_FqC_gauss, FlxqM_FlxqC_gauss, F2xqM_F2xqC_gauss); } GEN FFM_gauss(GEN M, GEN N, GEN ff) { return FFM_FFM_wrap(M, N, ff, FqM_gauss, FlxqM_gauss, F2xqM_gauss); } GEN FFM_FFC_invimage(GEN M, GEN C, GEN ff) { return FFM_FFC_wrap(M, C, ff, FqM_FqC_invimage, FlxqM_FlxqC_invimage, F2xqM_F2xqC_invimage); } GEN FFM_invimage(GEN M, GEN N, GEN ff) { return FFM_FFM_wrap(M, N, ff, FqM_invimage, FlxqM_invimage, F2xqM_invimage); } GEN FFM_FFC_mul(GEN M, GEN C, GEN ff) { return FFM_FFC_wrap(M, C, ff, FqM_FqC_mul, FlxqM_FlxqC_mul, F2xqM_F2xqC_mul); } GEN FFM_mul(GEN M, GEN N, GEN ff) { return FFM_FFM_wrap(M, N, ff, FqM_mul, FlxqM_mul, F2xqM_mul); } GEN FFV_roots_to_pol(GEN V, GEN ff, long v) { pari_sp av = avma; ulong pp; GEN P, T, p; long w = fetch_var_higher(); _getFF(ff,&T,&p,&pp); V = FFC_to_raw(V, ff); switch(ff[1]) { case t_FF_FpXQ: P = FqV_roots_to_pol(V, T, p, w); break; case t_FF_F2xq: P = F2xqV_roots_to_pol(V, T, w); break; default: P = FlxqV_roots_to_pol(V, T, pp, w); break; } if (!P) return gc_NULL(av); P = raw_to_FFX(P, ff); setvarn(P, v); delete_var(); return gerepilecopy(av, P); } pari-2.17.2/src/basemath/subfield.c0000644000175000017500000013015514760123736015516 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; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*******************************************************************/ /* */ /* SUBFIELDS OF A NUMBER FIELD */ /* J. Klueners and M. Pohst, J. Symb. Comp. (1996), vol. 11 */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_nfsubfields 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 attached 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 */ long fl; } 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 attached 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); set_avma(av); } } gel(Yp,lY) = Zp; K = divisorsu(n[1]); lK = lg(K); for (i=1; isize*k, lpn = 0; for (j=2; j= BIL) pari_err_OVERFLOW("calc_block"); pn[lpn] = n[j]; pnon[lpn] = j; ngcd = ugcd(ngcd, n[j]); } if (dk % ngcd) continue; T = 1L< print_block_system */ if (!T) continue; } if (dk == n[1]) { /* empty subset, t = 0. Split out for clarity */ Zp[1] = Z[1]; setlg(Zp, 2); for (u=1,j=2; j>=1) { if (tp&1) { nn += pn[u]; e[u] = 1; } else e[u] = 0; } if (dk != nn) continue; for (j=1; jN; long *k, *n, **e, *t; GEN D, De, Z, cyperm, perm, VOID = cgetg(1, t_VECSMALL); if (DEBUGLEVEL>5) err_printf("Y = %Ps\n",Y); n = new_chunk(N+1); D = vectrunc_init(N+1); t = new_chunk(r+1); k = new_chunk(r+1); Z = cgetg(r+1, t_VEC); for (ns=0,i=1; isize; De = cgetg(ki+1,t_VEC); for (j=1; j<=ki; j++) gel(De,j) = VOID; for (j=1; j<=si; j++) { GEN cy = gel(Yi,j); for (l=1,lp=0; l<=n[j]; l++) { lp++; if (lp > ki) lp = 1; gel(De,lp) = vecsmall_append(gel(De,lp), cy[l]); } } append(D, De); if (si>1 && ki>1) { GEN p1 = cgetg(si,t_VEC); for (j=2; j<=si; j++) p1[j-1] = Yi[j]; ns++; t[ns] = si-1; k[ns] = ki-1; gel(Z,ns) = p1; } } if (DEBUGLEVEL>2) err_printf("\nns = %ld\n",ns); if (!ns) return test_block(B, SB, D); setlg(Z, ns+1); e = (long**)new_chunk(ns+1); for (i=1; i<=ns; i++) { e[i] = new_chunk(t[i]+1); for (j=1; j<=t[i]; j++) e[i][j] = 0; } cyperm= cgetg(N+1,t_VECSMALL); perm = cgetg(N+1,t_VECSMALL); i = ns; do { pari_sp av = avma; for (u=1; u<=N; u++) perm[u] = u; for (u=1; u<=ns; u++) for (v=1; v<=t[u]; v++) perm_mul_i(perm, cycle_power_to_perm(cyperm, gmael(Z,u,v), e[u][v])); SB = test_block(B, SB, im_block_by_perm(D,perm)); set_avma(av); /* i = 1..ns, j = 1..t[i], e[i][j] loop through 0..k[i]. * TODO: flatten to 1-dimensional loop */ if (++e[ns][t[ns]] > k[ns]) { j = t[ns]-1; while (j>=1 && e[ns][j] == k[ns]) j--; if (j >= 1) { e[ns][j]++; for (l=j+1; l<=t[ns]; l++) e[ns][l] = 0; } else { i = ns-1; while (i>=1) { j = t[i]; while (j>=1 && e[i][j] == k[i]) j--; if (j<1) i--; else { e[i][j]++; for (l=j+1; l<=t[i]; l++) e[i][l] = 0; for (ll=i+1; ll<=ns; ll++) for (l=1; l<=t[ll]; l++) e[ll][l] = 0; break; } } } } } while (i > 0); return SB; } /* ALGEBRAIC PART: test potential block systems */ static GEN polsimplify(GEN x) { long i,lx = lg(x); for (i=2; i M[i] for some i; 1 otherwise */ static long ok_coeffs(GEN g,GEN M) { long i, lg = lg(g)-1; /* g is monic, and cst term is ok */ for (i=3; i 0) return 0; return 1; } /* assume x in Fq, return Tr_{Fq/Fp}(x) as a t_INT */ static GEN trace(GEN x, GEN Trq, GEN p) { long i, l; GEN s; if (typ(x) == t_INT) return Fp_mul(x, gel(Trq,1), p); l = lg(x)-1; if (l == 1) return gen_0; x++; s = mulii(gel(x,1), gel(Trq,1)); for (i=2; ip, pol = FpX_red(gel(DATA,1), p); long i, l; interp = gel(DATA,9); bezoutC= gel(DATA,6); h = NULL; l = lg(interp); for (i=1; iT, p); t = poltrace(t, gel(S->Trk,i), p); t = FpX_mul(t, gel(bezoutC,i), p); h = h? FpX_add(h,t,p): t; } return FpX_rem(h, pol, p); } /* g in Z[X] potentially defines a subfield of Q[X]/f. It is a subfield iff A * (cf subfield) was a block system; then there * exists h in Q[X] such that f | g o h. listdelta determines h s.t f | g o h * in Fp[X] (cf chinese_retrieve_pol). Try to lift it; den is a * multiplicative bound for denominator of lift. */ static GEN embedding(GEN g, GEN DATA, primedata *S, GEN den, GEN listdelta) { GEN TR, w0_Q, w0, w1_Q, w1, wpow, h0, gp, T, q2, q, maxp, a, p = S->p; long rt; pari_sp av; T = gel(DATA,1); rt = brent_kung_optpow(degpol(T), 4, 3); maxp= gel(DATA,7); gp = RgX_deriv(g); av = avma; w0 = chinese_retrieve_pol(DATA, S, listdelta); w0_Q = centermod(gmul(w0,den), p); h0 = FpXQ_inv(FpX_FpXQ_eval(gp,w0, T,p), T,p); /* = 1/g'(w0) mod (T,p) */ wpow = NULL; q = sqri(p); for(;;) {/* Given g,w0,h0 in Z[x], s.t. h0.g'(w0) = 1 and g(w0) = 0 mod (T,p), find * [w1,h1] satisfying the same conditions mod p^2, [w1,h1] = [w0,h0] (mod p) * (cf. Dixon: J. Austral. Math. Soc., Series A, vol.49, 1990, p.445) */ if (DEBUGLEVEL>1) err_printf("lifting embedding mod p^k = %Ps^%ld\n",S->p, Z_pval(q,S->p)); /* w1 := w0 - h0 g(w0) mod (T,q) */ if (wpow) a = FpX_FpXQV_eval(g,wpow, T,q); else a = FpX_FpXQ_eval(g,w0, T,q); /* first time */ /* now, a = 0 (p) */ a = FpXQ_mul(ZX_neg(h0), ZX_Z_divexact(a, p), T,p); w1 = ZX_add(w0, ZX_Z_mul(a, p)); w1_Q = centermod(ZX_Z_mul(w1, remii(den,q)), q); if (ZX_equal(w1_Q, w0_Q)) { GEN G = is_pm1(den)? g: RgX_rescale(g,den); if (gequal0(RgX_RgXQ_eval(G, w1_Q, T))) break; } else if (cmpii(q,maxp) > 0) { GEN G = is_pm1(den)? g: RgX_rescale(g,den); if (gequal0(RgX_RgXQ_eval(G, w1_Q, T))) break; if (DEBUGLEVEL) err_printf("coeff too big for embedding\n"); return NULL; } gerepileall(av, 5, &w1,&h0,&w1_Q,&q,&p); q2 = sqri(q); wpow = FpXQ_powers(w1, rt, T, q2); /* h0 := h0 * (2 - h0 g'(w1)) mod (T,q) * = h0 + h0 * (1 - h0 g'(w1)) */ a = FpXQ_mul(ZX_neg(h0), FpX_FpXQV_eval(gp, FpXV_red(wpow,q),T,q), T,q); a = ZX_Z_add_shallow(a, gen_1); /* 1 - h0 g'(w1) = 0 (p) */ a = FpXQ_mul(h0, ZX_Z_divexact(a, p), T,p); h0 = ZX_add(h0, ZX_Z_mul(a, p)); w0 = w1; w0_Q = w1_Q; p = q; q = q2; } TR = gel(DATA,5); if (!gequal0(TR)) w1_Q = RgX_translate(w1_Q, TR); return gdiv(w1_Q,den); } /* return U list of polynomials s.t U[i] = 1 mod fk[i] and 0 mod fk[j] for all * other j */ static GEN get_bezout(GEN pol, GEN fk, GEN p) { long i, l = lg(fk); GEN A, B, d, u, v, U = cgetg(l, t_VEC); for (i=1; i 0) pari_err_COPRIME("get_bezout",A,B); d = constant_coeff(d); if (!gequal1(d)) v = FpX_Fp_div(v, d, 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 = FpX_matFrobenius(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); S->T = T; S->firstroot = cgetg(lff, t_VECSMALL); S->interp = cgetg(lff, t_VEC); S->fk = cgetg(N+1, t_VEC); for (l=1,j=1; jff, j), deg1 = FpX_factorff_irred(F, T,p); GEN H = gel(deg1,1), a = Fq_neg(constant_coeff(H), T,p); GEN Q = FqX_div(F, H, T,p); GEN q = Fq_inv(FqX_eval(Q, a, T,p), T,p); gel(S->interp,j) = FqX_Fq_mul(Q, q, T,p); /* = 1 at a, 0 at other roots */ S->firstroot[j] = l; for (i=1; ifk, l) = gel(deg1, i); } S->Trk = init_traces(S->ff, T,p); S->bezoutC = get_bezout(S->pol, S->ff, p); } static int choose_prime(primedata *S, GEN pol) { long i, j, k, r, lcm, oldr, K, N = degpol(pol); ulong p, pp; GEN Z, ff, n, oldn; pari_sp av; forprime_t T; u_forprime_init(&T, (N*N) >> 2, ULONG_MAX); oldr = S->lcm = LONG_MAX; S->ff = oldn = NULL; pp = 0; /* gcc -Wall */ av = avma; K = N + 10; for(k = 1; k < K || !S->ff; k++,set_avma(av)) { GEN Tp; if (k > 5 * N) return 0; do { p = u_forprime_next(&T); Tp = ZX_to_Flx(pol, p); } while (!Flx_is_squarefree(Tp, p)); ff = gel(Flx_factor(Tp, 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 = ulcm(lcm, n[j]); } if (r > oldr || (r == oldr && (lcm <= S->lcm || S->lcm > 2*N))) continue; if (DEBUGLEVEL) err_printf("p = %lu,\tlcm = %ld,\torbits: %Ps\n",p,lcm,n); pp = p; oldr = r; oldn = n; S->ff = ff; S->lcm = lcm; if (r == 1) break; av = avma; } if (oldr > 6) return 0; if (DEBUGLEVEL) err_printf("Chosen prime: p = %ld\n", pp); FlxV_to_ZXV_inplace(S->ff); S->p = utoipos(pp); S->pol = FpX_red(pol, S->p); init_primedata(S); n = oldn; r = lg(n); S->Z = Z = cgetg(r,t_VEC); for (k=0,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 attached 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 = addiu(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 = logintall(shifti(vecmax(MM),20), p, &pe); /* overlift 2^20 [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, pe, p, e); 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_coeff(p1); d_1_term = addii(d_1_term, p1); } d_1_term = centermod(d_1_term, pe); /* Tr(g) */ if (abscmpii(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 B->fl==1? mkvec(g):_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 ); guncloneNULL(old); } return gc_const(av,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); return gc_const(av,L); } static void setvarn2(GEN t, long v) { setvarn(gel(t,1),v); setvarn(gel(t,2),v); } static GEN fix_var(GEN x, long v, long fl) { long i, l = lg(x); if (!v) return x; if (fl) for (i = 1; i < l; i++) setvarn(gel(x,i), v); else for (i = 1; i < l; i++) setvarn2(gel(x,i), v); return x; } static void subfields_poldata(GEN nf, GEN T, poldata *PD) { GEN L, dis; PD->pol = T; if (nf) { PD->den = nf_get_zkden(nf); PD->roo = nf_get_roots(nf); PD->dis = mulii(absi_shallow(nf_get_disc(nf)), sqri(nf_get_index(nf))); } else { PD->den = initgaloisborne(T,NULL,nbits2prec(bit_accuracy(ZX_max_lg(T))), &L,NULL,&dis); PD->roo = L; PD->dis = absi_shallow(dis); } } static GEN nfsubfields_fa(GEN nf, long d, long fl); static GEN subfieldsall(GEN nf0, long fl) { pari_sp av = avma; long N, ld, i, v; GEN nf, G, T, dg, LSB, NLSB; poldata PD; primedata S; blockdata B; /* much easier if nf is Galois (WSS) */ G = galoisinit(nf0, NULL); T = get_nfpol(nf0, &nf); if (G != gen_0) { GEN L, S; long l; L = lift_shallow( galoissubfields(G, fl, varn(T)) ); l = lg(L); S = cgetg(l, t_VECSMALL); for (i=1; i1; i--) { B.size = dg[i]; B.d = N / B.size; NLSB = subfields_of_given_degree(&B); if (NLSB) { LSB = gconcat(LSB, NLSB); gunclone(NLSB); } } (void)delete_var(); /* from init_primedata() */ LSB = shallowconcat(LSB, fl==1? mkvec(T):_subfield(T, pol_x(0))); if (DEBUGLEVEL) err_printf("\n***** Leaving subfields\n\n"); return fix_var(gerepilecopy(av, LSB), v, fl); } GEN nfsubfields0(GEN nf0, long d, long fl) { pari_sp av = avma; long N, v0; GEN nf, LSB, T, G; poldata PD; primedata S; blockdata B; if (fl<0 || fl>1) pari_err_FLAG("nfsubfields"); if (typ(nf0)==t_VEC && lg(nf0)==3) return nfsubfields_fa(nf0, d, fl); if (!d) return subfieldsall(nf0, fl); /* treat trivial cases */ T = get_nfpol(nf0, &nf); v0 = varn(T); N = degpol(T); RgX_check_ZX(T,"nfsubfields"); if (d == N) return gerepilecopy(av, fl==1 ? mkvec(T) : _subfield(T, pol_x(v0))); if (d == 1) return gerepilecopy(av, fl==1 ? mkvec(pol_x(v0)) : _subfield(pol_x(v0), zeropol(v0))); if (d < 1 || d > N || N % d) return cgetg(1,t_VEC); /* much easier if nf is Galois (WSS) */ G = galoisinit(nf0, NULL); if (G != gen_0) { /* Bingo */ GEN L = galoissubgroups(G), F; long k,i, l = lg(L), o = N/d; F = cgetg(l, t_VEC); k = 1; for (i=1; i B) B = bi; } ed = expu(d); B += ed+1; bound = 0; for (i=0; 2*i<=d; i++) { if (!i) bi = d*B; else bi = (d-i)*B + i*(3+ed-expu(i)); if (bi > bound) bound = bi; } Q = ZXQ_minpoly(a,pol,d,bound); return fl==1? Q: mkvec2(Q, a); } /* subfield sub of nf of degree d assuming: - V is contained in sub - V is not contained in a proper subfield of sub ero: maximum exponent+1 of roots of pol output as nfsubfields: - pair [g,h] where g absolute equation for the subfield and h expresses - one of the roots of g in terms of the generator of nf */ static GEN subfield_generator(GEN pol, GEN V, long d, long ero, long fl) { long p, i, e, vp = varn(pol); GEN a = NULL, v = cgetg(lg(V),t_COL), B; if (d==1) return fl ? pol_x(vp): mkvec2(pol_x(vp), pol_0(vp)); e = degpol(pol)/d; p = 1009; for (i=1; i dy) pari_err_BUG("RgXY_to_RgC [incorrect degree]"); res = cgetg((dx+1)*(dy+1)+1, t_COL); k = 1; for (i=0; i<=d; i++) { c = gel(P,i+2); if (typ(c)==t_POL) { long dc = degpol(c); if (dc > dx) pari_err_BUG("RgXY_to_RgC [incorrect degree]"); for (j=0; j<=dc; j++) gel(res,k++) = gel(c,j+2); } else { gel(res,k++) = c; j=1; } for ( ; j<=dx; j++) gel(res,k++) = gen_0; } for( ; i<=dy; i++) for (j=0; j<=dx; j++) gel(res,k++) = gen_0; return res; } /* lambda: t_VEC of t_INT; 0 means ignore this factor */ static GEN twoembequation(GEN pol, GEN fa, GEN lambda) { GEN m, vpolx, poly; long i,j, lfa = lg(fa), dx = degpol(pol); long vx = varn(pol), vy = varn(gel(fa,1)); /* vx < vy ! */ if (varncmp(vx,vy) <= 0) pari_err_BUG("twoembequation [incorrect variable priorities]"); lambda = shallowcopy(lambda); fa = shallowcopy(fa); j = 1; for (i=1; i= 0) pari_err_PRIORITY("nfsubfields_fa", o, "<=", v); } } static GEN rootsuptoconj(GEN pol, long prec) { GEN ro; long n, i; ro = roots(pol,prec); n = lg(ro)-1; for (i=1; i<=n/2; i++) gel(ro,i) = gel(ro,2*i-1); setlg(ro,n/2+1); return ro; } static GEN cmsubfield_get_roots(GEN pol, GEN nf, long n, long* r2, long *prec) { GEN ro; if (nf) { if (nf_get_r1(nf)) return NULL; *r2 = nf_get_r2(nf); *prec = nf_get_prec(nf); ro = nf_get_roots(nf); } else { if (n%2 || sturm(pol)) return NULL; *r2 = n/2; *prec = MEDDEFAULTPREC; ro = rootsuptoconj(pol, *prec); } return ro; } static GEN subfields_get_fa(GEN pol, GEN nf, GEN fa) { if (!fa) { GEN poly = shallowcopy(pol); setvarn(poly, fetch_var_higher()); fa = nffactor(nf? nf: pol, poly); } return liftpol_shallow(gel(fa,1)); } static long subfields_get_ero(GEN pol, GEN nf) { return 1 + gexpo(nf? nf_get_roots(nf): QX_complex_roots(pol, LOWDEFAULTPREC)); } static GEN try_imag(GEN x, GEN c, GEN pol, long v, ulong p, GEN emb, GEN galpol, long fl) { GEN a = Q_primpart(RgX_sub(RgX_RgXQ_eval(x,c,pol),x)); if (Flx_is_squarefree(Flxq_charpoly(ZX_to_Flx(a,p),ZX_to_Flx(pol,p),p),p)) { pol = ZXQ_charpoly(a, pol, v); return fl ? pol : mkvec2(pol, RgX_RgXQ_eval(a, emb, galpol)); } return NULL; } static GEN galoissubfieldcm(GEN G, long fl) { pari_sp av = avma; GEN c, H, elts, g, Hset, c2, gene, sub, pol, emb, a, galpol, B, b; long n, i, j, nH, ind, v, d; ulong p = 1009; galpol = gal_get_pol(G); n = degpol(galpol); v = varn(galpol); c = galois_get_conj(G); /* compute the list of c*g*c*g^(-1) : product of all pairs of conjugations * maximal CM subfield is the field fixed by those elements, if c does not * belong to the group they generate */ checkgroup(G, &elts); elts = gen_sort_shallow(elts,(void*)vecsmall_lexcmp,cmp_nodata); H = vecsmall_ei(n,1); /* indices of elements of H */ Hset = zero_F2v(n); F2v_set(Hset,1); nH = 1; for (i=2; i<=n; i++) { g = gel(elts,i); c2 = perm_mul(c,perm_conj(g,c)); if (!F2v_coeff(Hset,c2[1])) { nH++; H[nH] = c2[1]; F2v_set(Hset,c2[1]); } } /* group generated */ gene = gcopy(H); setlg(gene,nH+1); i = 1; /* last element that has been multiplied by the generators */ while (i < nH) { for (j=1; jn) return gc_const(av, gen_0); H[nH] = ind; F2v_set(Hset,ind); } } i++; } H = cgetg(lg(gene), t_VEC); for (i=1; i ero) ero = e; } ero++; fa = subfields_get_fa(pol, nf, fa); emax = 1; emin = -1; for (i=1; i emax) emax = e; if (e < emin) emin = e; } precbound = n*(emax-emin) + gexpo(fa) + n*n + 5; precbound = 3 + precbound/BITS_IN_LONG; if (prec < precbound) { prec = precbound; ro = rootsuptoconj(pol, prec); } lambda = zerovec(lg(fa)-1); for (i=1; i<=r2; i++) { a = gel(ro,i); aa = conj_i(a); for (j=1; j0) { minj = j; minev = ev; } } gel(lambda,minj) = gen_m1; } V = twoembequation(pol, fa, lambda); if (lg(V)==1) { delete_var(); return gc_const(av, gen_0); } res = subfield_generator(pol, V, 2*(lg(V)-1), ero, fl); delete_var(); return gerepilecopy(av, res); } static int field_is_contained(GEN V, GEN W, int strict) { GEN VW; ulong p = 1073741827; /* distinct overfield must have different dimension */ if (strict && lg(V) == lg(W)) return 0; /* dimension of overfield must be multiple */ if ((lg(W)-1) % (lg(V)-1)) return 0; VW = shallowconcat(V,W); if (Flm_rank(ZM_to_Flm(VW,p),p) > lg(W)-1) return 0; return ZM_rank(VW) == lg(W)-1; } /***********************************************/ /* */ /* Maximal, generating, all subfields */ /* Aurel Page (2019) */ /* after van Hoeij, Klueners, Novocin */ /* Journal of Symbolic Computation 52 (2013) */ /* */ /***********************************************/ const long subf_MAXIMAL = 1; /* return the maximal subfields */ const long subf_GENERATING = 2; /* return the generating subfields */ static GEN maxgen_subfields(GEN pol, GEN fa, long flag) { pari_sp av = avma; GEN principal, ismax, isgene, Lmax = NULL, Lgene, res, V, W, W1; long i, i2, j, flmax, flgene, nbmax = 0, nbgene = 0; if (!flag) return cgetg(1,t_VEC); flmax = (flag & subf_MAXIMAL)!=0; flgene = (flag & subf_GENERATING)!=0; /* compute principal subfields */ principal = cgetg(lg(fa),t_VEC); for (i=1; i 0 && lg(gel(principal,j)) == lg(V)) { if (field_is_contained(gel(principal,j),V,0)) { dup=1; break; } j--; } if (!dup) gel(principal,i2++) = V; } setlg(principal, i2); /* a subfield is generating iff all overfields contain the first overfield */ ismax = cgetg(lg(principal),t_VECSMALL); isgene = cgetg(lg(principal),t_VECSMALL); for (i=1; i 0) { swap(gel(*H,i), gel(*H,j)); return heap_climb(H,j); } } static void heap_push(GEN* H, long *len, GEN x) { if (*len+1 == lg(*H)) { GEN H2 = zerovec(2*(*len)); long i; for(i=1; i len) return; if (cmp_universal(gel(*H,j),gel(*H,i)) > 0) maxi = j; j++; if (j<=len && cmp_universal(gel(*H,j),gel(*H,maxi))>0) maxi = j; if (maxi == i) return; swap(gel(*H,i), gel(*H,maxi)); return heap_descend(H,len,maxi); } static void heap_pop(GEN *H, long *len, GEN* top) { *top = gel(*H,1); gel(*H,1) = gel(*H,*len); (*len)--; return heap_descend(H,*len,1); }; static GEN nfsubfields_fa(GEN nf, long d, long fl) { pari_sp av = avma; GEN pol, fa, gene, res, res2, H, V, v, W, w, data; long n, r, i, j, nres, len, s, newfield, ero, vp; subfields_cleanup(&nf, &pol, &n, &fa); vp = varn(pol); if (d && (d<1 || d>n || n%d)) return gerepilecopy(av, cgetg(1,t_VEC)); if (!d && uisprime(n)) return gerepilecopy(av, fl==1 ? mkvec2( pol_x(varn(pol)), pol) : mkvec2( mkvec2(pol_x(vp),pol_0(vp)), mkvec2(pol,pol_x(vp)))); if (n==1 || d==1) return gerepilecopy(av, fl==1 ? mkvec(pol_x(varn(pol))): _subfield(pol_x(vp),pol_0(vp))); if (d==n) return gerepilecopy(av, fl==1 ? mkvec(pol): _subfield(pol,pol_x(vp))); ero = subfields_get_ero(pol, nf); fa = subfields_get_fa(pol, nf, fa); gene = maxgen_subfields(pol, fa, subf_GENERATING); if (d) { /* keep only generating subfields of degree a multiple of d */ j=1; for (i=1; i0) { heap_pop(&H, &len, &data); V = gel(data,1); v = gel(data,2); s = gel(data,3)[1]; for (i=s+1; i<=r; i++) if (!F2v_coeff(v,i)) { W = vec_Q_primpart(intersect(V, gel(gene,i))); w = F2v_copy(v); F2v_set(w, i); newfield = 1; for (j=1; j<=r; j++) if (!F2v_coeff(w,j) && field_is_contained(W,gel(gene,j),1)) { if (j 0; return v_p(Nx) */ static long idealHNF_norm_pval(GEN x, GEN p, long Zval) { long i, v = Zval, l = lg(x); for (i = 2; i < l; i++) v += Z_pval(gcoeff(x,i,i), p); return v; } /* x integral in HNF, f0 = partial factorization of a multiple of * x[1,1] = x\cap Z */ GEN idealHNF_Z_factor_i(GEN x, GEN f0, GEN *pvN, GEN *pvZ) { GEN P, E, vN, vZ, xZ = gcoeff(x,1,1), f = f0? f0: Z_factor(xZ); long i, l; P = gel(f,1); l = lg(P); E = gel(f,2); *pvN = vN = cgetg(l, t_VECSMALL); *pvZ = vZ = cgetg(l, t_VECSMALL); for (i = 1; i < l; i++) { GEN p = gel(P,i); vZ[i] = f0? Z_pval(xZ, p): (long) itou(gel(E,i)); vN[i] = idealHNF_norm_pval(x,p, vZ[i]); } return P; } /* return P, primes dividing Nx and xZ = x\cap Z, set v_p(Nx), v_p(xZ); * x integral in HNF */ GEN idealHNF_Z_factor(GEN x, GEN *pvN, GEN *pvZ) { return idealHNF_Z_factor_i(x, NULL, pvN, pvZ); } /* v_P(A)*f(P) <= Nval [e.g. Nval = v_p(Norm A)], Zval = v_p(A \cap Z). * Return v_P(A) */ static long idealHNF_val(GEN A, GEN P, long Nval, long Zval) { long f = pr_get_f(P), vmax, v, e, i, j, k, l; GEN mul, B, a, y, r, p, pk, cx, vals; pari_sp av; if (Nval < f) return 0; p = pr_get_p(P); e = pr_get_e(P); /* v_P(A) <= max [ e * v_p(A \cap Z), floor[v_p(Nix) / f ] */ vmax = minss(Zval * e, Nval / f); mul = pr_get_tau(P); l = lg(mul); B = cgetg(l,t_MAT); /* B[1] not needed: v_pr(A[1]) = v_pr(A \cap Z) is known already */ gel(B,1) = gen_0; /* dummy */ for (j = 2; j < l; j++) { GEN x = gel(A,j); gel(B,j) = y = cgetg(l, t_COL); for (i = 1; i < l; i++) { /* compute a = (x.t0)_i, A in HNF ==> x[j+1..l-1] = 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)) return 0; } } vals = cgetg(l, t_VECSMALL); /* vals[1] not needed */ for (j = 2; j < l; j++) { gel(B,j) = Q_primitive_part(gel(B,j), &cx); vals[j] = cx? 1 + e * Q_pval(cx, p): 1; } pk = powiu(p, ceildivuu(vmax, e)); av = avma; y = cgetg(l,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 < l; j++) { GEN x = gel(B,j); if (v < vals[j]) continue; for (i = 1; i < l; i++) { pari_sp av2 = avma; a = mulii(gel(x,1), gcoeff(mul,i,1)); for (k = 2; k < l; 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)) return v; if (lgefint(a) > lgefint(pk)) a = remii(a, pk); gel(y,i) = gerepileuptoint(av2, a); } gel(B,j) = y; y = x; if (gc_needed(av,3)) { if(DEBUGMEM>1) pari_warn(warnmem,"idealval"); gerepileall(av,3, &y,&B,&pk); } } } return v; } /* true nf, x != 0 integral ideal in HNF, cx t_INT or NULL, * FA integer factorization matrix or NULL. Return partial factorization of * cx * x above primes in FA (complete factorization if !FA)*/ static GEN idealHNF_factor_i(GEN nf, GEN x, GEN cx, GEN FA) { const long N = lg(x)-1; long i, j, k, l, v; GEN vN, vZ, vP, vE, vp = idealHNF_Z_factor_i(x, FA, &vN,&vZ); l = lg(vp); i = cx? expi(cx)+1: 1; vP = cgetg((l+i-2)*N+1, t_COL); vE = cgetg((l+i-2)*N+1, t_COL); for (i = k = 1; i < l; i++) { GEN L, p = gel(vp,i); long Nval = vN[i], Zval = vZ[i], vc = cx? Z_pvalrem(cx,p,&cx): 0; if (vc) { L = idealprimedec(nf,p); if (is_pm1(cx)) cx = NULL; } else L = idealprimedec_limit_f(nf,p,Nval); for (j = 1; Nval && j < lg(L); j++) /* !Nval => only cx contributes */ { GEN P = gel(L,j); pari_sp av = avma; v = idealHNF_val(x, P, Nval, Zval); set_avma(av); Nval -= v*pr_get_f(P); v += vc * pr_get_e(P); if (!v) continue; gel(vP,k) = P; gel(vE,k) = utoipos(v); k++; } if (vc) for (; j lim */ for (i = lg(P)-1; i; i--) if (cmpiu(gel(P,i), lim) <= 0) break; setlg(P, i+1); setlg(E, i+1); } x = Q_primitive_part(x, &cx); return idealHNF_factor_i(nf, x, cx, F); } /* c * vector(#L,i,L[i].e), assume results fit in ulong */ static GEN prV_e_muls(GEN L, long c) { long j, l = lg(L); GEN z = cgetg(l, t_COL); for (j = 1; j < l; j++) gel(z,j) = stoi(c * pr_get_e(gel(L,j))); return z; } /* true nf, y in Q */ static GEN Q_nffactor(GEN nf, GEN y, ulong lim) { GEN f, P, E; long l, i; if (typ(y) == t_INT) { if (!signe(y)) pari_err_DOMAIN("idealfactor", "ideal", "=",gen_0,y); if (is_pm1(y)) return trivial_fact(); } y = Q_abs_shallow(y); if (!lim) f = Q_factor(y); else { f = Q_factor_limit(y, lim); P = gel(f,1); E = gel(f,2); for (i = lg(P)-1; i > 0; i--) if (abscmpiu(gel(P,i), lim) < 0) break; setlg(P,i+1); setlg(E,i+1); } P = gel(f,1); l = lg(P); if (l == 1) return f; E = gel(f,2); for (i = 1; i < l; i++) { gel(P,i) = idealprimedec(nf, gel(P,i)); gel(E,i) = prV_e_muls(gel(P,i), itos(gel(E,i))); } P = shallowconcat1(P); gel(f,1) = P; settyp(P, t_COL); E = shallowconcat1(E); gel(f,2) = E; return f; } GEN idealfactor_partial(GEN nf, GEN x, GEN L) { pari_sp av = avma; long i, j, l; GEN P, E; if (!L) return idealfactor(nf, x); if (typ(L) == t_INT) return idealfactor_limit(nf, x, itou(L)); l = lg(L); if (l == 1) return trivial_fact(); P = cgetg(l, t_VEC); for (i = 1; i < l; i++) { GEN p = gel(L,i); gel(P,i) = typ(p) == t_INT? idealprimedec(nf, p): mkvec(p); } P = shallowconcat1(P); settyp(P, t_COL); P = gen_sort_uniq(P, (void*)&cmp_prime_ideal, &cmp_nodata); E = cgetg_copy(P, &l); for (i = j = 1; i < l; i++) { long v = idealval(nf, x, gel(P,i)); if (v) { gel(P,j) = gel(P,i); gel(E,j) = stoi(v); j++; } } setlg(P,j); setlg(E,j); return gerepilecopy(av, mkmat2(P, E)); } GEN idealfactor_limit(GEN nf, GEN x, ulong lim) { pari_sp av = avma; GEN fa, y; long tx = idealtyp(&x, NULL); if (tx == id_PRIME) { if (lim && abscmpiu(pr_get_p(x), lim) >= 0) return trivial_fact(); retmkmat2(mkcolcopy(x), mkcol(gen_1)); } nf = checknf(nf); if (tx == id_PRINCIPAL) { y = nf_to_scalar_or_basis(nf, x); if (typ(y) != t_COL) return gerepilecopy(av, Q_nffactor(nf, y, lim)); } y = idealnumden(nf, x); fa = idealHNF_factor(nf, gel(y,1), lim); if (!isint1(gel(y,2))) fa = famat_div_shallow(fa, idealHNF_factor(nf, gel(y,2), lim)); fa = gerepilecopy(av, fa); return sort_factor(fa, (void*)&cmp_prime_ideal, &cmp_nodata); } GEN idealfactor(GEN nf, GEN x) { return idealfactor_limit(nf, x, 0); } GEN gpidealfactor(GEN nf, GEN x, GEN lim) { ulong L = 0; if (lim) { if (typ(lim) != t_INT || signe(lim) < 0) pari_err_FLAG("idealfactor"); L = itou(lim); } return idealfactor_limit(nf, x, L); } static GEN ramified_root(GEN nf, GEN R, GEN A, long n) { GEN v, P = gel(idealfactor(nf, R), 1); long i, l = lg(P); v = cgetg(l, t_VECSMALL); for (i = 1; i < l; i++) { long w = idealval(nf, A, gel(P,i)); if (w % n) return NULL; v[i] = w / n; } return idealfactorback(nf, P, v, 0); } static int ramified_root_simple(GEN nf, long n, GEN P, GEN v) { long i, l = lg(v); for (i = 1; i < l; i++) { long w = v[i] % n; if (w) { GEN vpr = idealprimedec(nf, gel(P,i)); long lpr = lg(vpr), j; for (j = 1; j < lpr; j++) { long e = pr_get_e(gel(vpr,j)); if ((e * w) % n) return 0; } } } return 1; } /* true nf, n > 1, A a non-zero integral ideal; check whether A is the n-th * power of an ideal and set *pB to its n-th root if so */ static long idealsqrtn_int(GEN nf, GEN A, long n, GEN *pB) { GEN C, root; long i, l; if (typ(A) == t_MAT && ZM_isscalar(A, NULL)) A = gcoeff(A,1,1); if (typ(A) == t_INT) /* > 0 */ { GEN P = nf_get_ramified_primes(nf), v, q; l = lg(P); v = cgetg(l, t_VECSMALL); for (i = 1; i < l; i++) v[i] = Z_pvalrem(A, gel(P,i), &A); C = gen_1; if (!isint1(A) && !Z_ispowerall(A, n, pB? &C: NULL)) return 0; if (!pB) return ramified_root_simple(nf, n, P, v); q = factorback2(P, v); root = ramified_root(nf, q, q, n); if (!root) return 0; if (!equali1(C)) root = isint1(root)? C: ZM_Z_mul(root, C); *pB = root; return 1; } /* compute valuations at ramified primes */ root = ramified_root(nf, idealadd(nf, nf_get_diff(nf), A), A, n); if (!root) return 0; /* remove ramified primes */ if (isint1(root)) root = matid(nf_get_degree(nf)); else A = idealdivexact(nf, A, idealpows(nf,root,n)); A = Q_primitive_part(A, &C); if (C) { if (!Z_ispowerall(C,n,&C)) return 0; if (pB) root = ZM_Z_mul(root, C); } /* compute final n-th root, at most degree(nf)-1 iterations */ for (i = 0;; i++) { GEN J, b, a = gcoeff(A,1,1); /* A \cap Z */ if (is_pm1(a)) break; if (!Z_ispowerall(a,n,&b)) return 0; J = idealadd(nf, b, A); A = idealdivexact(nf, idealpows(nf,J,n), A); /* div and not divexact here */ if (pB) root = odd(i)? idealdiv(nf, root, J): idealmul(nf, root, J); } if (pB) *pB = root; return 1; } /* A is assumed to be the n-th power of an ideal in nf returns its n-th root. */ long idealispower(GEN nf, GEN A, long n, GEN *pB) { pari_sp av = avma; GEN v, N, D; nf = checknf(nf); if (n <= 0) pari_err_DOMAIN("idealispower", "n", "<=", gen_0, stoi(n)); if (n == 1) { if (pB) *pB = idealhnf(nf,A); return 1; } v = idealnumden(nf,A); if (gequal0(gel(v,1))) { set_avma(av); if (pB) *pB = cgetg(1,t_MAT); return 1; } if (!idealsqrtn_int(nf, gel(v,1), n, pB? &N: NULL)) return 0; if (!idealsqrtn_int(nf, gel(v,2), n, pB? &D: NULL)) return 0; if (pB) *pB = gerepileupto(av, idealdiv(nf,N,D)); else set_avma(av); return 1; } /* x t_INT or integral nonzero ideal in HNF */ static GEN idealredmodpower_i(GEN nf, GEN x, ulong k, ulong B) { GEN cx, y, U, N, F, Q; if (typ(x) == t_INT) { if (!signe(x) || is_pm1(x)) return gen_1; F = Z_factor_limit(x, B); gel(F,2) = gdiventgs(gel(F,2), k); return ginv(factorback(F)); } N = gcoeff(x,1,1); if (is_pm1(N)) return gen_1; F = absZ_factor_limit_strict(N, B, &U); if (U) { GEN M = powii(gel(U,1), gel(U,2)); y = hnfmodid(x, M); /* coprime part to B! */ if (!idealispower(nf, y, k, &U)) U = NULL; x = hnfmodid(x, diviiexact(N, M)); } /* x = B-smooth part of initial x */ x = Q_primitive_part(x, &cx); F = idealHNF_factor_i(nf, x, cx, F); gel(F,2) = gdiventgs(gel(F,2), k); Q = idealfactorback(nf, gel(F,1), gel(F,2), 0); if (U) Q = idealmul(nf,Q,U); if (typ(Q) == t_INT) return Q; y = idealred_elt(nf, idealHNF_inv_Z(nf, Q)); return gdiv(y, gcoeff(Q,1,1)); } GEN idealredmodpower(GEN nf, GEN x, ulong n, ulong B) { pari_sp av = avma; GEN a, b; nf = checknf(nf); if (!n) pari_err_DOMAIN("idealredmodpower","n", "=", gen_0, gen_0); x = idealnumden(nf, x); a = gel(x,1); if (isintzero(a)) { set_avma(av); return gen_1; } a = idealredmodpower_i(nf, gel(x,1), n, B); b = idealredmodpower_i(nf, gel(x,2), n, B); if (!isint1(b)) a = nf_to_scalar_or_basis(nf, nfdiv(nf, a, b)); return gerepilecopy(av, a); } /* P prime ideal in idealprimedec format. Return valuation(A) at P */ long idealval(GEN nf, GEN A, GEN P) { pari_sp av = avma; GEN p, cA; long vcA, v, Zval, tx = idealtyp(&A, NULL); if (tx == id_PRINCIPAL) return nfval(nf,A,P); checkprid(P); if (tx == id_PRIME) return pr_equal(P, A)? 1: 0; /* id_MAT */ nf = checknf(nf); A = Q_primitive_part(A, &cA); p = pr_get_p(P); vcA = cA? Q_pval(cA,p): 0; if (pr_is_inert(P)) return gc_long(av,vcA); Zval = Z_pval(gcoeff(A,1,1), p); if (!Zval) v = 0; else { long Nval = idealHNF_norm_pval(A, p, Zval); v = idealHNF_val(A, P, Nval, Zval); } return gc_long(av, vcA? v + vcA*pr_get_e(P): v); } GEN gpidealval(GEN nf, GEN ix, GEN P) { long v = idealval(nf,ix,P); return v == LONG_MAX? mkoo(): stoi(v); } /* gcd and generalized Bezout */ GEN idealadd(GEN nf, GEN x, GEN y) { pari_sp av = avma; long tx, ty; GEN z, a, dx, dy, dz; tx = idealtyp(&x, NULL); ty = idealtyp(&y, NULL); 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) { set_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) { return (lg(x) == 1 || !is_pm1(gcoeff(x,1,1)))? NULL: gen_1; } /* true nf */ static GEN _idealaddtoone(GEN nf, GEN x, GEN y, long red) { GEN a; long tx = idealtyp(&x, NULL); long ty = idealtyp(&y, NULL); long ea; 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) pari_err_COPRIME("idealaddtoone",x,y); if (red && (ea = gexpo(a)) > 10) { GEN b = (typ(a) == t_COL)? a: scalarcol_shallow(a, nf_get_degree(nf)); b = ZC_reducemodlll(b, idealHNF_mul(nf,x,y)); if (gexpo(b) < ea) a = b; } return a; } /* true nf */ GEN idealaddtoone_i(GEN nf, GEN x, GEN y) { return _idealaddtoone(nf, x, y, 1); } /* true nf */ GEN idealaddtoone_raw(GEN nf, GEN x, GEN y) { return _idealaddtoone(nf, x, y, 0); } GEN idealaddtoone(GEN nf, GEN x, GEN y) { GEN z = cgetg(3,t_VEC), a; pari_sp av = avma; nf = checknf(nf); a = gerepileupto(av, idealaddtoone_i(nf,x,y)); gel(z,1) = a; gel(z,2) = typ(a) == t_COL? Z_ZC_sub(gen_1,a): subui(1,a); return z; } /* assume elements of list are integral ideals */ GEN idealaddmultoone(GEN nf, GEN list) { pari_sp av = avma; long N, i, l, nz, tx = typ(list); GEN H, U, perm, L; nf = checknf(nf); N = nf_get_degree(nf); if (!is_vec_t(tx)) pari_err_TYPE("idealaddmultoone",list); l = lg(list); L = cgetg(l, t_VEC); if (l == 1) pari_err_DOMAIN("idealaddmultoone", "sum(ideals)", "!=", gen_1, L); nz = 0; /* number of nonzero ideals in L */ for (i=1; i 1 && G[k] == G[k-1]) { E[k-1] += E[k]; k--; } } /* kill 0 exponents */ l = k; for (k=i=1; i 1) swap(gel(x,1), gel(x,i)); /* help HNF */ gel(x,1) = scalarcol_shallow(gel(x,1), lx-1); break; } x = ZM_hnfmodid(x, D); dx = mul_denom(dx,dA); return dx? gdiv(x,dx): x; } /* nf a true nf, 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 = pr_get_p(y), pi = pr_get_gen(y), 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(pr_hnf(nf,y), absi_shallow(x)); case t_FRAC: return RgM_Rg_mul(pr_hnf(nf,y), Q_abs_shallow(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_hnfmodid(z, mulii(p, zkmultable_capZ(x))); return cx? ZM_Q_mul(z, cx): z; } default: /* id_MAT */ return idealmulelt(nf, x,y); } case id_PRIME: if (ty==id_PRIME) { y = pr_hnf(nf,y); cy = NULL; } else y = Q_primitive_part(y, &cy); y = idealHNF_mul_two(nf,y,x); return cy? ZM_Q_mul(y,cy): y; default: /* id_MAT */ { long N = nf_get_degree(nf); if (lg(x)-1 != N || lg(y)-1 != N) pari_err_DIM("idealmul"); x = Q_primitive_part(x, &cx); y = Q_primitive_part(y, &cy); cx = mul_content(cx,cy); y = idealHNF_mul(nf,x,y); return cx? ZM_Q_mul(y,cx): y; } } } /* output the ideal product x.y */ 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; } /* Return x, integral in 2-elt form, such that pr^2 = c * x. cf idealpowprime * nf = true nf */ static GEN idealsqrprime(GEN nf, GEN pr, GEN *pc) { GEN p = pr_get_p(pr), q, gen; long e = pr_get_e(pr), f = pr_get_f(pr); q = (e == 1)? sqri(p): p; if (e <= 2 && e * f == nf_get_degree(nf)) { /* pr^e = (p) */ *pc = q; return mkvec2(gen_1,gen_0); } gen = nfsqr(nf, pr_get_gen(pr)); gen = FpC_red(gen, q); *pc = NULL; return mkvec2(q, gen); } /* cf idealpow_aux */ static GEN idealsqr_aux(GEN nf, GEN x, long tx) { GEN T = nf_get_pol(nf), m, cx, a, alpha; long N = degpol(T); switch(tx) { case id_PRINCIPAL: return idealhnf_principal(nf, nfsqr(nf,x)); case id_PRIME: if (pr_is_inert(x)) return scalarmat(sqri(gel(x,1)), N); x = idealsqrprime(nf, x, &cx); x = idealhnf_two(nf,x); return cx? ZM_Z_mul(x, cx): x; default: x = Q_primitive_part(x, &cx); a = mat_ideal_two_elt(nf,x); alpha = gel(a,2); a = gel(a,1); alpha = nfsqr(nf,alpha); m = zk_scalar_or_multable(nf, alpha); if (typ(m) == t_INT) { x = gcdii(sqri(a), m); if (cx) x = gmul(x, gsqr(cx)); x = scalarmat(x, N); } else { /* could use gcdii(sqri(a), zkmultable_capZ(m)), but costly */ x = ZM_hnfmodid(m, sqri(a)); if (cx) cx = gsqr(cx); if (cx) x = ZM_Q_mul(x, cx); } return x; } } 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, idealsqr_aux(checknf(nf), x, 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; long tx; switch(idealtyp(&x, NULL)) { case id_PRIME: return pr_norm(x); case id_MAT: return RgM_det_triangular(x); } /* id_PRINCIPAL */ nf = checknf(nf); av = avma; x = nfnorm(nf, x); tx = typ(x); if (tx == t_INT) return gerepileuptoint(av, absi(x)); if (tx != t_FRAC) pari_err_TYPE("idealnorm",x); return gerepileupto(av, Q_abs(x)); } /* x \cap Z */ GEN idealdown(GEN nf, GEN x) { pari_sp av = avma; GEN y, c; switch(idealtyp(&x, NULL)) { case id_PRIME: return icopy(pr_get_p(x)); case id_MAT: return gcopy(gcoeff(x,1,1)); } /* id_PRINCIPAL */ nf = checknf(nf); av = avma; x = nf_to_scalar_or_basis(nf, x); if (is_rational_t(typ(x))) return Q_abs(x); x = Q_primitive_part(x, &c); y = zkmultable_capZ(zk_multable(nf, x)); return gerepilecopy(av, mul_content(c, y)); } /* true nf */ static GEN idealismaximal_int(GEN nf, GEN p) { GEN L; if (!BPSW_psp(p)) return NULL; if (!dvdii(nf_get_index(nf), p) && !FpX_is_irred(FpX_red(nf_get_pol(nf),p), p)) return NULL; L = idealprimedec(nf, p); return (lg(L) == 2 && pr_get_e(gel(L,1)) == 1)? gel(L,1): NULL; } /* true nf */ static GEN idealismaximal_mat(GEN nf, GEN x) { GEN p, c, L; long i, l, f; x = Q_primitive_part(x, &c); p = gcoeff(x,1,1); if (c) { if (typ(c) == t_FRAC || !equali1(p)) return NULL; return idealismaximal_int(nf, c); } if (!BPSW_psp(p)) return NULL; l = lg(x); f = 1; for (i = 2; i < l; i++) { c = gcoeff(x,i,i); if (equalii(c, p)) f++; else if (!equali1(c)) return NULL; } L = idealprimedec_limit_f(nf, p, f); for (i = lg(L)-1; i; i--) { GEN pr = gel(L,i); if (pr_get_f(pr) != f) break; if (idealval(nf, x, pr) == 1) return pr; } return NULL; } /* true nf */ static GEN idealismaximal_i(GEN nf, GEN x) { GEN L, p, pr, c; long i, l; switch(idealtyp(&x, NULL)) { case id_PRIME: return x; case id_MAT: return idealismaximal_mat(nf, x); } /* id_PRINCIPAL */ x = nf_to_scalar_or_basis(nf, x); switch(typ(x)) { case t_INT: return idealismaximal_int(nf, absi_shallow(x)); case t_FRAC: return NULL; } x = Q_primitive_part(x, &c); if (c) return NULL; p = zkmultable_capZ(zk_multable(nf, x)); if (!BPSW_psp(p)) return NULL; L = idealprimedec(nf, p); l = lg(L); pr = NULL; for (i = 1; i < l; i++) { long v = ZC_nfval(x, gel(L,i)); if (v > 1 || (v && pr)) return NULL; pr = gel(L,i); } return pr; } GEN idealismaximal(GEN nf, GEN x) { pari_sp av = avma; x = idealismaximal_i(checknf(nf), x); if (!x) { set_avma(av); return gen_0; } return gerepilecopy(av, x); } /* 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) */ GEN idealHNF_inv_Z(GEN nf, GEN I) { GEN J, dual, IZ = gcoeff(I,1,1); /* I \cap Z */ if (isint1(IZ)) return matid(lg(I)-1); J = idealHNF_mul(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). */ GEN idealHNF_inv(GEN nf, GEN I) { GEN J, IQ = gcoeff(I,1,1); /* I \cap Q; d IQ = dI \cap Z */ J = idealHNF_inv_Z(nf, Q_remove_denom(I, NULL)); /* = (dI)^(-1) * (d IQ) */ return equali1(IQ)? J: RgM_Rg_div(J, IQ); } /* return p * P^(-1) [integral] */ GEN pr_inv_p(GEN pr) { if (pr_is_inert(pr)) return matid(pr_get_f(pr)); return ZM_hnfmodid(pr_get_tau(pr), pr_get_p(pr)); } GEN pr_inv(GEN pr) { GEN p = pr_get_p(pr); if (pr_is_inert(pr)) return scalarmat(ginv(p), pr_get_f(pr)); return RgM_Rg_div(ZM_hnfmodid(pr_get_tau(pr),p), p); } GEN idealinv(GEN nf, GEN x) { GEN res, ax; pari_sp av; long tx = idealtyp(&x,&ax), N; res = ax? cgetg(3,t_VEC): NULL; nf = checknf(nf); av = avma; N = nf_get_degree(nf); switch (tx) { case id_MAT: if (lg(x)-1 != N) pari_err_DIM("idealinv"); x = idealHNF_inv(nf,x); break; case id_PRINCIPAL: x = nf_to_scalar_or_basis(nf, x); if (typ(x) != t_COL) x = idealhnf_principal(nf,ginv(x)); else { /* nfinv + idealhnf where we already know (x) \cap Z */ GEN c, d; x = Q_remove_denom(x, &c); x = zk_inv(nf, x); x = Q_remove_denom(x, &d); /* true inverse is c/d * x */ if (!d) /* x and x^(-1) integral => x a unit */ x = c? scalarmat(c, N): matid(N); else { c = c? gdiv(c,d): ginv(d); x = zk_multable(nf, x); x = ZM_Q_mul(ZM_hnfmodid(x,d), c); } } break; case id_PRIME: x = pr_inv(x); break; } x = gerepileupto(av,x); if (!ax) return x; gel(res,1) = x; gel(res,2) = ext_inv(nf, ax); return res; } /* write x = A/B, A,B coprime integral ideals */ GEN idealnumden(GEN nf, GEN x) { pari_sp av = avma; GEN x0, c, d, A, B, J; long tx = idealtyp(&x, NULL); nf = checknf(nf); switch (tx) { case id_PRIME: retmkvec2(idealhnf(nf, x), gen_1); case id_PRINCIPAL: { GEN xZ, mx; x = nf_to_scalar_or_basis(nf, x); switch(typ(x)) { case t_INT: return gerepilecopy(av, mkvec2(absi_shallow(x),gen_1)); case t_FRAC:return gerepilecopy(av, mkvec2(absi_shallow(gel(x,1)), gel(x,2))); } /* t_COL */ x = Q_remove_denom(x, &d); if (!d) return gerepilecopy(av, mkvec2(idealhnf_shallow(nf, x), gen_1)); mx = zk_multable(nf, x); xZ = zkmultable_capZ(mx); x = ZM_hnfmodid(mx, xZ); /* principal ideal (x) */ x0 = mkvec2(xZ, mx); /* same, for fast multiplication */ break; } default: /* id_MAT */ { long n = lg(x)-1; if (n == 0) return mkvec2(gen_0, gen_1); if (n != nf_get_degree(nf)) pari_err_DIM("idealnumden"); x0 = x = Q_remove_denom(x, &d); if (!d) return gerepilecopy(av, mkvec2(x, gen_1)); break; } } J = hnfmodid(x, d); /* = d/B */ c = gcoeff(J,1,1); /* (d/B) \cap Z, divides d */ B = idealHNF_inv_Z(nf, J); /* (d/B \cap Z) B/d */ if (!equalii(c,d)) B = ZM_Z_mul(B, diviiexact(d,c)); /* = B ! */ A = idealHNF_mul(nf, B, x0); /* d * (original x) * B = d A */ A = ZM_Z_divexact(A, d); /* = A ! */ return gerepilecopy(av, mkvec2(A, B)); } /* Return x, integral in 2-elt form, such that pr^n = c * x. Assume n != 0. * nf = true nf */ static GEN idealpowprime(GEN nf, GEN pr, GEN n, GEN *pc) { GEN p = pr_get_p(pr), q, gen; *pc = NULL; if (is_pm1(n)) /* n = 1 special cased for efficiency */ { q = p; if (typ(pr_get_tau(pr)) == t_INT) /* inert */ { *pc = (signe(n) >= 0)? p: ginv(p); return mkvec2(gen_1,gen_0); } if (signe(n) >= 0) gen = pr_get_gen(pr); else { gen = pr_get_tau(pr); /* possibly t_MAT */ *pc = ginv(p); } } else if (equalis(n,2)) return idealsqrprime(nf, pr, pc); else { long e = pr_get_e(pr), f = pr_get_f(pr); GEN r, m = truedvmdis(n, e, &r); if (e * f == nf_get_degree(nf)) { /* pr^e = (p) */ if (signe(m)) *pc = powii(p,m); if (!signe(r)) return mkvec2(gen_1,gen_0); q = p; gen = nfpow(nf, pr_get_gen(pr), r); } else { m = absi_shallow(m); if (signe(r)) m = addiu(m,1); q = powii(p,m); /* m = ceil(|n|/e) */ if (signe(n) >= 0) gen = nfpow(nf, pr_get_gen(pr), n); else { gen = pr_get_tau(pr); if (typ(gen) == t_MAT) gen = gel(gen,1); n = negi(n); gen = ZC_Z_divexact(nfpow(nf, gen, n), powii(p, subii(n,m))); *pc = ginv(q); } } gen = FpC_red(gen, q); } return mkvec2(q, gen); } /* True nf. x * pr^n. Assume x in HNF or scalar (possibly nonintegral) */ GEN idealmulpowprime(GEN nf, GEN x, GEN pr, GEN n) { GEN c, cx, y; long N = nf_get_degree(nf); if (!signe(n)) return typ(x) == t_MAT? x: scalarmat_shallow(x, N); /* inert, special cased for efficiency */ if (pr_is_inert(pr)) { GEN q = powii(pr_get_p(pr), n); return typ(x) == t_MAT? RgM_Rg_mul(x,q) : scalarmat_shallow(gmul(Q_abs(x),q), N); } y = idealpowprime(nf, pr, n, &c); if (typ(x) == t_MAT) { x = Q_primitive_part(x, &cx); if (is_pm1(gcoeff(x,1,1))) x = NULL; } else { cx = x; x = NULL; } cx = mul_content(c,cx); if (x) x = idealHNF_mul_two(nf,x,y); else x = idealhnf_two(nf,y); if (cx) x = ZM_Q_mul(x,cx); return x; } GEN idealdivpowprime(GEN nf, GEN x, GEN pr, GEN n) { return idealmulpowprime(nf,x,pr, negi(n)); } /* nf = true nf */ 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: return idealhnf_principal(nf, nfpow(nf,x,n)); case id_PRIME: if (pr_is_inert(x)) return scalarmat(powii(gel(x,1), n), N); x = idealpowprime(nf, x, n, &cx); x = idealhnf_two(nf,x); return cx? ZM_Q_mul(x, cx): 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(powii(a,n1), m); if (s<0) x = ginv(x); if (cx) x = gmul(x, powgi(cx,n)); x = scalarmat(x, N); } else { /* could use gcdii(powii(a,n1), zkmultable_capZ(m)), but costly */ 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 = idealHNF_inv_Z(nf,x); } if (cx) x = ZM_Q_mul(x, cx); } return x; } } /* raise the ideal x to the power n (in Z) */ GEN idealpow(GEN nf, GEN x, GEN n) { pari_sp av; long tx; GEN res, ax; if (typ(n) != t_INT) pari_err_TYPE("idealpow",n); tx = idealtyp(&x,&ax); res = ax? cgetg(3,t_VEC): NULL; av = avma; x = gerepileupto(av, idealpow_aux(checknf(nf), x, tx, n)); if (!ax) return x; gel(res,1) = x; gel(res,2) = ext_pow(nf, ax, n); 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, av2; long s; GEN y; if (typ(n) != t_INT) pari_err_TYPE("idealpowred",n); s = signe(n); if (s == 0) return idealpow(nf,x,n); y = gen_pow_i(x, n, (void*)nf, &_sqr, &_mul); av2 = avma; if (s < 0) y = idealinv(nf,y); if (s < 0 || is_pm1(n)) y = idealred(nf,y); return avma == av2? gerepilecopy(av,y): 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, xZ; nf = checknf(nf); T = nf_get_pol(nf); lx = lg(x); if (tx==t_VEC && lx==3) { x = gel(x,1); tx = typ(x); lx = lg(x); } switch(tx) { case t_INT: case t_FRAC: return 1; case t_POL: return varn(x) == varn(T); case t_POLMOD: return RgX_equal_var(T, gel(x,1)); case t_VEC: return get_prid(x)? 1 : 0; case t_MAT: break; default: return 0; } N = degpol(T); if (lx-1 != N) return (lx == 1); if (nbrows(x) != N) return 0; av = avma; x = Q_primpart(x); if (!ZM_ishnf(x)) return 0; xZ = gcoeff(x,1,1); for (j=2; j<=N; j++) if (!dvdii(xZ, gcoeff(x,j,j))) return gc_long(av,0); for (i=2; i<=N; i++) for (j=2; j<=N; j++) if (! hnf_invimage(x, zk_ei_mul(nf,gel(x,i),j))) return gc_long(av,0); return gc_long(av,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. */ static void err_divexact(GEN x, GEN y) { pari_err_DOMAIN("idealdivexact","denominator(x/y)", "!=", gen_1,mkvec2(x,y)); } GEN idealdivexact(GEN nf, GEN x0, GEN y0) { pari_sp av = avma; GEN x, y, xZ, yZ, Nx, Ny, Nz, cy, q, r; nf = checknf(nf); x = idealhnf_shallow(nf, x0); y = idealhnf_shallow(nf, y0); if (lg(y) == 1) pari_err_INV("idealdivexact", y0); if (lg(x) == 1) { set_avma(av); return cgetg(1, t_MAT); } /* numerator is zero */ y = Q_primitive_part(y, &cy); if (cy) x = RgM_Rg_div(x,cy); xZ = gcoeff(x,1,1); if (typ(xZ) != t_INT) err_divexact(x,y); yZ = gcoeff(y,1,1); if (isint1(yZ)) return gerepilecopy(av, x); Nx = idealnorm(nf,x); Ny = idealnorm(nf,y); if (typ(Nx) != t_INT) err_divexact(x,y); q = dvmdii(Nx,Ny, &r); if (signe(r)) err_divexact(x,y); if (is_pm1(q)) { set_avma(av); return matid(nf_get_degree(nf)); } /* Find a norm Nz | Ny such that gcd(Nx/Nz, Nz) = 1 */ for (Nz = Ny;;) /* q = Nx/Nz */ { GEN p1 = gcdii(Nz, q); if (is_pm1(p1)) break; Nz = diviiexact(Nz,p1); q = mulii(q,p1); } xZ = gcoeff(x,1,1); q = gcdii(q, xZ); if (!equalii(xZ,q)) { /* Replace x/y by x+(Nx/Nz) / y+(Ny/Nz) */ x = ZM_hnfmodid(x, q); /* y reduced to unit ideal ? */ if (Nz == Ny) return gerepileupto(av, x); yZ = gcoeff(y,1,1); q = gcdii(diviiexact(Ny,Nz), yZ); y = ZM_hnfmodid(y, q); } yZ = gcoeff(y,1,1); y = idealHNF_mul(nf,x, idealHNF_inv_Z(nf,y)); return gerepileupto(av, ZM_Z_divexact(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) { set_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= gexpo(y)) aI = famat_div(aI, y); /* yi "larger" than y, keep the latter */ else { /* use yi */ aI = famat_mul(aI, nyi); c1 = div_content(c1, dyi); } if (c1) { aI = famat_mul(aI, Q_to_famat(c1)); c1 = NULL; } } else c1 = c1? RgC_Rg_mul(yi, c1): yi; END: if (c1) aI = ext_mul(nf, aI,c1); return gerepilecopy(av, mkvec2(I, aI)); } /* I integral ZM (not HNF), G ZM, rounded Cholesky form of a weighted * T2 matrix. Reduce I wrt G */ GEN idealpseudored(GEN I, GEN G) { return ZM_mul(I, ZM_lll(ZM_mul(G, I), 0.99, LLL_IM)); } /* Same I, G; m in I with T2(m) small */ 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)); } /* Same I,G; irrational m in I with T2(m) small */ 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; } /* Same I,G; t_VEC of irrational m in I with T2(m) small */ GEN idealpseudominvec(GEN I, GEN G) { long i, j, k, n = lg(I)-1; GEN x, L, b = idealpseudored(I, G); L = cgetg(1 + (n*(n+1))/2, t_VEC); for (i = k = 1; i <= n; i++) { x = gel(b,i); if (!ZV_isscalar(x)) gel(L,k++) = x; } for (i = 2; i <= n; i++) { long J = minss(i, 4); for (j = 1; j < J; j++) { x = ZC_add(gel(b,i),gel(b,j)); if (!ZV_isscalar(x)) gel(L,k++) = x; } } setlg(L,k); return L; } GEN idealred_elt(GEN nf, GEN I) { pari_sp av = avma; GEN u = idealpseudomin(I, nf_get_roundG(nf)); return gerepileupto(av, u); } GEN idealmin(GEN nf, GEN x, GEN vdir) { pari_sp av = avma; GEN y, dx; nf = checknf(nf); switch( idealtyp(&x, NULL) ) { case id_PRINCIPAL: return gcopy(x); case id_PRIME: x = pr_hnf(nf,x); break; case id_MAT: if (lg(x) == 1) return gen_0; } x = Q_remove_denom(x, &dx); y = idealpseudomin(x, nf_get_Gtwist(nf,vdir)); if (dx) y = RgC_Rg_div(y, dx); return gerepileupto(av, y); } /*******************************************************************/ /* */ /* APPROXIMATION THEOREM */ /* */ /*******************************************************************/ /* a = ppi(a,b) ppo(a,b), where ppi regroups primes common to a and b * and ppo(a,b) = Z_ppo(a,b) */ /* return gcd(a,b),ppi(a,b),ppo(a,b) */ GEN Z_ppio(GEN a, GEN b) { GEN x, y, d = gcdii(a,b); if (is_pm1(d)) return mkvec3(gen_1, gen_1, a); x = d; y = diviiexact(a,d); for(;;) { GEN g = gcdii(x,y); if (is_pm1(g)) return mkvec3(d, x, y); x = mulii(x,g); y = diviiexact(y,g); } } /* a = ppg(a,b)pple(a,b), where ppg regroups primes such that v(a) > v(b) * and pple all others */ /* return gcd(a,b),ppg(a,b),pple(a,b) */ GEN Z_ppgle(GEN a, GEN b) { GEN x, y, g, d = gcdii(a,b); if (equalii(a, d)) return mkvec3(a, gen_1, a); x = diviiexact(a,d); y = d; for(;;) { g = gcdii(x,y); if (is_pm1(g)) return mkvec3(d, x, y); x = mulii(x,g); y = diviiexact(y,g); } } static void Z_dcba_rec(GEN L, GEN a, GEN b) { GEN x, r, v, g, h, c, c0; long n; if (is_pm1(b)) { if (!is_pm1(a)) vectrunc_append(L, a); return; } v = Z_ppio(a,b); a = gel(v,2); r = gel(v,3); if (!is_pm1(r)) vectrunc_append(L, r); v = Z_ppgle(a,b); g = gel(v,1); h = gel(v,2); x = c0 = gel(v,3); for (n = 1; !is_pm1(h); n++) { GEN d, y; long i; v = Z_ppgle(h,sqri(g)); g = gel(v,1); h = gel(v,2); c = gel(v,3); if (is_pm1(c)) continue; d = gcdii(c,b); x = mulii(x,d); y = d; for (i=1; i < n; i++) y = sqri(y); Z_dcba_rec(L, diviiexact(c,y), d); } Z_dcba_rec(L,diviiexact(b,x), c0); } static GEN Z_cba_rec(GEN L, GEN a, GEN b) { GEN g; /* a few naive steps before switching to dcba */ if (lg(L) > 10) { Z_dcba_rec(L, a, b); return veclast(L); } if (is_pm1(a)) return b; g = gcdii(a,b); if (is_pm1(g)) { vectrunc_append(L, a); return b; } a = diviiexact(a,g); b = diviiexact(b,g); return Z_cba_rec(L, Z_cba_rec(L, a, g), b); } GEN Z_cba(GEN a, GEN b) { GEN L = vectrunc_init(expi(a) + expi(b) + 2); GEN t = Z_cba_rec(L, a, b); if (!is_pm1(t)) vectrunc_append(L, t); return L; } /* P = coprime base, extend it by b; TODO: quadratic for now */ GEN ZV_cba_extend(GEN P, GEN b) { long i, l = lg(P); GEN w = cgetg(l+1, t_VEC); for (i = 1; i < l; i++) { GEN v = Z_cba(gel(P,i), b); long nv = lg(v)-1; gel(w,i) = vecslice(v, 1, nv-1); /* those divide P[i] but not b */ b = gel(v,nv); } gel(w,l) = b; return shallowconcat1(w); } GEN ZV_cba(GEN v) { long i, l = lg(v); GEN P; if (l <= 2) return v; P = Z_cba(gel(v,1), gel(v,2)); for (i = 3; i < l; i++) P = ZV_cba_extend(P, gel(v,i)); return P; } /* write x = x1 x2, x2 maximal s.t. (x2,f) = 1, return x2 */ GEN Z_ppo(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 u_ppo(ulong x, ulong f) { for (;;) { f = ugcd(x, f); if (f == 1) break; x /= f; } return x; } /* result known to be representable as an ulong */ static ulong lcmuu(ulong a, ulong b) { ulong d = ugcd(a,b); return (a/d) * b; } /* assume 0 < x < N; return u in (Z/NZ)^* such that u x = gcd(x,N) (mod N); * set *pd = gcd(x,N) */ ulong Fl_invgen(ulong x, ulong N, ulong *pd) { ulong d, d0, e, v, v1; long s; *pd = d = xgcduu(N, x, 0, &v, &v1, &s); if (s > 0) v = N - v; if (d == 1) return v; /* vx = gcd(x,N) (mod N), v coprime to N/d but need not be coprime to N */ e = N / d; d0 = u_ppo(d, e); /* d = d0 d1, d0 coprime to N/d, rad(d1) | N/d */ if (d0 == 1) return v; e = lcmuu(e, d / d0); return u_chinese_coprime(v, 1, e, d0, e*d0); } /* 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 = Z_ppo(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 = pr_hnf(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. */ static GEN idealapprfact_i(GEN nf, GEN x, int nored) { GEN d = NULL, z, L, e, e2, F; long i, r; int hasden = 0; nf = checknf(nf); L = gel(x,1); e = gel(x,2); F = prV_lcm_capZ(L); z = NULL; r = lg(e); for (i = 1; i < r; i++) { long s = signe(gel(e,i)); GEN pi, q; if (!s) continue; if (s < 0) hasden = 1; pi = pr_uniformizer(gel(L,i), F); q = nfpow(nf, pi, gel(e,i)); z = z? nfmul(nf, z, q): q; } if (!z) return gen_1; if (hasden) /* denominator */ { z = Q_remove_denom(z, &d); d = diviiexact(d, Z_ppo(d, F)); } if (nored || typ(z) != t_COL) return d? gdiv(z, d): z; e2 = cgetg(r, t_VEC); for (i = 1; i < r; i++) gel(e2,i) = addiu(gel(e,i), 1); x = factorbackprime(nf, L, e2); if (d) x = RgM_Rg_mul(x, d); z = ZC_reducemodlll(z, x); return d? RgC_Rg_div(z,d): z; } GEN idealapprfact(GEN nf, GEN x) { pari_sp av = avma; return gerepileupto(av, idealapprfact_i(nf, x, 0)); } GEN idealappr(GEN nf, GEN x) { pari_sp av = avma; if (!is_nf_extfactor(x)) x = idealfactor(nf, x); return gerepileupto(av, idealapprfact_i(nf, x, 0)); } /* OBSOLETE */ GEN idealappr0(GEN nf, GEN x, long fl) { (void)fl; return idealappr(nf, x); } static GEN mat_ideal_two_elt2(GEN nf, GEN x, GEN a) { GEN F = idealfactor(nf,a), P = gel(F,1), E = gel(F,2); long i, r = lg(E); for (i=1; i= (lvl) + 3) err_printf /** * START Code from AVSs "class_inv.h" */ /* actually just returns the square-free part of the level, which is * all we care about */ long modinv_level(long inv) { switch (inv) { case INV_J: return 1; case INV_G2: case INV_W3W3E2:return 3; case INV_F: case INV_F2: case INV_F4: case INV_F8: return 6; case INV_F3: return 2; case INV_W3W3: return 6; case INV_W2W7E2: case INV_W2W7: return 14; case INV_W3W5: return 15; case INV_W2W3E2: case INV_W2W3: return 6; case INV_W2W5E2: case INV_W2W5: return 30; case INV_W2W13: return 26; case INV_W3W7: return 42; case INV_W5W7: return 35; case INV_W3W13: return 39; } pari_err_BUG("modinv_level"); return 0;/*LCOV_EXCL_LINE*/ } /* Where applicable, returns N=p1*p2 (possibly p2=1) s.t. two j's * related to the same f are N-isogenous, and 0 otherwise. This is * often (but not necessarily) equal to the level. */ long modinv_degree(long *p1, long *p2, long inv) { switch (inv) { case INV_W3W5: return (*p1 = 3) * (*p2 = 5); case INV_W2W3E2: case INV_W2W3: return (*p1 = 2) * (*p2 = 3); case INV_W2W5E2: case INV_W2W5: return (*p1 = 2) * (*p2 = 5); case INV_W2W7E2: case INV_W2W7: return (*p1 = 2) * (*p2 = 7); case INV_W2W13: return (*p1 = 2) * (*p2 = 13); case INV_W3W7: return (*p1 = 3) * (*p2 = 7); case INV_W3W3E2: case INV_W3W3: return (*p1 = 3) * (*p2 = 3); case INV_W5W7: return (*p1 = 5) * (*p2 = 7); case INV_W3W13: return (*p1 = 3) * (*p2 = 13); } *p1 = *p2 = 1; return 0; } /* Certain invariants require that D not have 2 in it's conductor, but * this doesn't apply to every invariant with even level so we handle * it separately */ INLINE int modinv_odd_conductor(long inv) { switch (inv) { case INV_F: case INV_W3W3: case INV_W3W7: return 1; } return 0; } long modinv_height_factor(long inv) { switch (inv) { case INV_J: return 1; case INV_G2: return 3; case INV_F: return 72; case INV_F2: return 36; case INV_F3: return 24; case INV_F4: return 18; case INV_F8: return 9; case INV_W2W3: return 72; case INV_W3W3: return 36; case INV_W2W5: return 54; case INV_W2W7: return 48; case INV_W3W5: return 36; case INV_W2W13: return 42; case INV_W3W7: return 32; case INV_W2W3E2:return 36; case INV_W2W5E2:return 27; case INV_W2W7E2:return 24; case INV_W3W3E2:return 18; case INV_W5W7: return 24; case INV_W3W13: return 28; default: pari_err_BUG("modinv_height_factor"); return 0;/*LCOV_EXCL_LINE*/ } } long disc_best_modinv(long D) { long ret; ret = INV_F; if (modinv_good_disc(ret, D)) return ret; ret = INV_W2W3; if (modinv_good_disc(ret, D)) return ret; ret = INV_W2W5; if (modinv_good_disc(ret, D)) return ret; ret = INV_W2W7; if (modinv_good_disc(ret, D)) return ret; ret = INV_W2W13; if (modinv_good_disc(ret, D)) return ret; ret = INV_W3W3; if (modinv_good_disc(ret, D)) return ret; ret = INV_W2W3E2;if (modinv_good_disc(ret, D)) return ret; ret = INV_W3W5; if (modinv_good_disc(ret, D)) return ret; ret = INV_W3W7; if (modinv_good_disc(ret, D)) return ret; ret = INV_W3W13; if (modinv_good_disc(ret, D)) return ret; ret = INV_W2W5E2;if (modinv_good_disc(ret, D)) return ret; ret = INV_F3; if (modinv_good_disc(ret, D)) return ret; ret = INV_W2W7E2;if (modinv_good_disc(ret, D)) return ret; ret = INV_W5W7; if (modinv_good_disc(ret, D)) return ret; ret = INV_W3W3E2;if (modinv_good_disc(ret, D)) return ret; ret = INV_G2; if (modinv_good_disc(ret, D)) return ret; return INV_J; } INLINE long modinv_sparse_factor(long inv) { switch (inv) { case INV_G2: case INV_F8: case INV_W3W5: case INV_W2W5E2: case INV_W3W3E2: return 3; case INV_F: return 24; case INV_F2: case INV_W2W3: return 12; case INV_F3: return 8; case INV_F4: case INV_W2W3E2: case INV_W2W5: case INV_W3W3: return 6; case INV_W2W7: return 4; case INV_W2W7E2: case INV_W2W13: case INV_W3W7: return 2; } return 1; } #define IQ_FILTER_1MOD3 1 #define IQ_FILTER_2MOD3 2 #define IQ_FILTER_1MOD4 4 #define IQ_FILTER_3MOD4 8 INLINE long modinv_pfilter(long inv) { switch (inv) { case INV_G2: case INV_W3W3: case INV_W3W3E2: case INV_W3W5: case INV_W2W5: case INV_W2W3E2: case INV_W2W5E2: case INV_W5W7: case INV_W3W13: return IQ_FILTER_1MOD3; /* ensure unique cube roots */ case INV_W2W7: case INV_F3: return IQ_FILTER_1MOD4; /* ensure at most two 4th/8th roots */ case INV_F: case INV_F2: case INV_F4: case INV_F8: case INV_W2W3: /* Ensure unique cube roots and at most two 4th/8th roots */ return IQ_FILTER_1MOD3 | IQ_FILTER_1MOD4; } return 0; } int modinv_good_prime(long inv, long p) { switch (inv) { case INV_G2: case INV_W2W3E2: case INV_W3W3: case INV_W3W3E2: case INV_W3W5: case INV_W2W5E2: case INV_W2W5: return (p % 3) == 2; case INV_W2W7: case INV_F3: return (p & 3) != 1; case INV_F2: case INV_F4: case INV_F8: case INV_F: case INV_W2W3: return ((p % 3) == 2) && (p & 3) != 1; } return 1; } /* Returns true if the prime p does not divide the conductor of D */ INLINE int prime_to_conductor(long D, long p) { long b; if (p > 2) return (D % (p * p)); b = D & 0xF; return (b && b != 4); /* 2 divides the conductor of D <=> D=0,4 mod 16 */ } INLINE GEN red_primeform(long D, long p) { pari_sp av = avma; GEN P; if (!prime_to_conductor(D, p)) return NULL; P = primeform_u(stoi(D), p); /* primitive since p \nmid conductor */ return gerepileupto(av, qfbred_i(P)); } /* Computes product of primeforms over primes appearing in the prime * factorization of n (including multiplicity) */ GEN qfb_nform(long D, long n) { pari_sp av = avma; GEN N = NULL, fa = factoru(n), P = gel(fa,1), E = gel(fa,2); long i, l = lg(P); for (i = 1; i < l; ++i) { long j, e; GEN Q = red_primeform(D, P[i]); if (!Q) return gc_NULL(av); e = E[i]; if (i == 1) { N = Q; j = 1; } else j = 0; for (; j < e; ++j) N = qfbcomp_i(Q, N); } return gerepileupto(av, N); } INLINE int qfb_is_two_torsion(GEN x) { return equali1(gel(x,1)) || !signe(gel(x,2)) || equalii(gel(x,1), gel(x,2)) || equalii(gel(x,1), gel(x,3)); } /* Returns true iff the products p1*p2, p1*p2^-1, p1^-1*p2, and * p1^-1*p2^-1 are all distinct in cl(D) */ INLINE int qfb_distinct_prods(long D, long p1, long p2) { GEN P1, P2; P1 = red_primeform(D, p1); if (!P1) return 0; P1 = qfbsqr_i(P1); P2 = red_primeform(D, p2); if (!P2) return 0; P2 = qfbsqr_i(P2); return !(equalii(gel(P1,1), gel(P2,1)) && absequalii(gel(P1,2), gel(P2,2))); } /* By Corollary 3.1 of Enge-Schertz Constructing elliptic curves over finite * fields using double eta-quotients, we need p1 != p2 to both be noninert * and prime to the conductor, and if p1=p2=p we want p split and prime to the * conductor. We exclude the case that p1=p2 divides the conductor, even * though this does yield class invariants */ INLINE int modinv_double_eta_good_disc(long D, long inv) { pari_sp av = avma; GEN P; long i1, i2, p1, p2, N; N = modinv_degree(&p1, &p2, inv); if (! N) return 0; i1 = kross(D, p1); if (i1 < 0) return 0; /* Exclude ramified case for w_{p,p} */ if (p1 == p2 && !i1) return 0; i2 = kross(D, p2); if (i2 < 0) return 0; /* this also verifies that p1 is prime to the conductor */ P = red_primeform(D, p1); if (!P || gequal1(gel(P,1)) /* don't allow p1 to be principal */ /* if p1 is unramified, require it to have order > 2 */ || (i1 && qfb_is_two_torsion(P))) return gc_bool(av,0); if (p1 == p2) /* if p1=p2 we need p1*p1 to be distinct from its inverse */ return gc_bool(av, !qfb_is_two_torsion(qfbsqr_i(P))); /* this also verifies that p2 is prime to the conductor */ P = red_primeform(D, p2); if (!P || gequal1(gel(P,1)) /* don't allow p2 to be principal */ /* if p2 is unramified, require it to have order > 2 */ || (i2 && qfb_is_two_torsion(P))) return gc_bool(av,0); set_avma(av); /* if p1 and p2 are split, we also require p1*p2, p1*p2^-1, p1^-1*p2, * and p1^-1*p2^-1 to be distinct */ if (i1>0 && i2>0 && !qfb_distinct_prods(D, p1, p2)) return gc_bool(av,0); if (!i1 && !i2) { /* if both p1 and p2 are ramified, make sure their product is not * principal */ P = qfb_nform(D, N); if (equali1(gel(P,1))) return gc_bool(av,0); set_avma(av); } return 1; } /* Assumes D is a good discriminant for inv, which implies that the * level is prime to the conductor */ long modinv_ramified(long D, long inv, long *pN) { long p1, p2; *pN = modinv_degree(&p1, &p2, inv); if (*pN <= 1) return 0; return !(D % p1) && !(D % p2); } int modinv_good_disc(long inv, long D) { switch (inv) { case INV_J: return 1; case INV_G2: return !!(D % 3); case INV_F3: return (-D & 7) == 7; case INV_F: case INV_F2: case INV_F4: case INV_F8: return ((-D & 7) == 7) && (D % 3); case INV_W3W5: return (D % 3) && modinv_double_eta_good_disc(D, inv); case INV_W3W3E2: return (D % 3) && modinv_double_eta_good_disc(D, inv); case INV_W3W3: return (D & 1) && (D % 3) && modinv_double_eta_good_disc(D, inv); case INV_W2W3E2: return (D % 3) && modinv_double_eta_good_disc(D, inv); case INV_W2W3: return ((-D & 7) == 7) && (D % 3) && modinv_double_eta_good_disc(D, inv); case INV_W2W5: return ((-D % 80) != 20) && (D % 3) && modinv_double_eta_good_disc(D, inv); case INV_W2W5E2: return (D % 3) && modinv_double_eta_good_disc(D, inv); case INV_W2W7E2: return ((-D % 112) != 84) && modinv_double_eta_good_disc(D, inv); case INV_W2W7: return ((-D & 7) == 7) && modinv_double_eta_good_disc(D, inv); case INV_W2W13: return ((-D % 208) != 52) && modinv_double_eta_good_disc(D, inv); case INV_W3W7: return (D & 1) && (-D % 21) && modinv_double_eta_good_disc(D, inv); case INV_W5W7: /* NB: This is a guess; avs doesn't have an entry */ return (D % 3) && modinv_double_eta_good_disc(D, inv); case INV_W3W13: /* NB: This is a guess; avs doesn't have an entry */ return (D & 1) && (D % 3) && modinv_double_eta_good_disc(D, inv); } pari_err_BUG("modinv_good_discriminant"); return 0;/*LCOV_EXCL_LINE*/ } int modinv_is_Weber(long inv) { return inv == INV_F || inv == INV_F2 || inv == INV_F3 || inv == INV_F4 || inv == INV_F8; } int modinv_is_double_eta(long inv) { switch (inv) { case INV_W2W3: case INV_W2W3E2: case INV_W2W5: case INV_W2W5E2: case INV_W2W7: case INV_W2W7E2: case INV_W2W13: case INV_W3W3: case INV_W3W3E2: case INV_W3W5: case INV_W3W7: case INV_W5W7: case INV_W3W13: return 1; } return 0; } /* END Code from "class_inv.h" */ INLINE int safe_abs_sqrt(ulong *r, ulong x, ulong p, ulong pi, ulong s2) { if (krouu(x, p) == -1) { if (p%4 == 1) return 0; x = Fl_neg(x, p); } *r = Fl_sqrt_pre_i(x, s2, p, pi); return 1; } INLINE int eighth_root(ulong *r, ulong x, ulong p, ulong pi, ulong s2) { ulong s; if (krouu(x, p) == -1) return 0; s = Fl_sqrt_pre_i(x, s2, p, pi); return safe_abs_sqrt(&s, s, p, pi, s2) && safe_abs_sqrt(r, s, p, pi, s2); } INLINE ulong modinv_f_from_j(ulong j, ulong p, ulong pi, ulong s2, long only_residue) { pari_sp av = avma; GEN pol, r; long i; ulong g2, f = ULONG_MAX; /* f^8 must be a root of X^3 - \gamma_2 X - 16 */ g2 = Fl_sqrtl_pre(j, 3, p, pi); pol = mkvecsmall5(0UL, Fl_neg(16 % p, p), Fl_neg(g2, p), 0UL, 1UL); r = Flx_roots_pre(pol, p, pi); for (i = 1; i < lg(r); ++i) if (only_residue) { if (krouu(r[i], p) != -1) return gc_ulong(av,r[i]); } else if (eighth_root(&f, r[i], p, pi, s2)) return gc_ulong(av,f); pari_err_BUG("modinv_f_from_j"); return 0;/*LCOV_EXCL_LINE*/ } INLINE ulong modinv_f3_from_j(ulong j, ulong p, ulong pi, ulong s2) { pari_sp av = avma; GEN pol, r; long i; ulong f = ULONG_MAX; pol = mkvecsmall5(0UL, Fl_neg(4096 % p, p), Fl_sub(768 % p, j, p), Fl_neg(48 % p, p), 1UL); r = Flx_roots_pre(pol, p, pi); for (i = 1; i < lg(r); ++i) if (eighth_root(&f, r[i], p, pi, s2)) return gc_ulong(av,f); pari_err_BUG("modinv_f3_from_j"); return 0;/*LCOV_EXCL_LINE*/ } /* Return the exponent e for the double-eta "invariant" w such that * w^e is a class invariant. For example w2w3^12 is a class * invariant, so double_eta_exponent(INV_W2W3) is 12 and * double_eta_exponent(INV_W2W3E2) is 6. */ INLINE ulong double_eta_exponent(long inv) { switch (inv) { case INV_W2W3: return 12; case INV_W2W3E2: case INV_W2W5: case INV_W3W3: return 6; case INV_W2W7: return 4; case INV_W3W5: case INV_W2W5E2: case INV_W3W3E2: return 3; case INV_W2W7E2: case INV_W2W13: case INV_W3W7: return 2; default: return 1; } } INLINE ulong weber_exponent(long inv) { switch (inv) { case INV_F: return 24; case INV_F2: return 12; case INV_F3: return 8; case INV_F4: return 6; case INV_F8: return 3; default: return 1; } } INLINE ulong double_eta_power(long inv, ulong w, ulong p, ulong pi) { return Fl_powu_pre(w, double_eta_exponent(inv), p, pi); } static GEN double_eta_raw_to_Fp(GEN f, GEN p) { GEN u = FpX_red(RgV_to_RgX(gel(f,1), 0), p); GEN v = FpX_red(RgV_to_RgX(gel(f,2), 0), p); return mkvec3(u, v, gel(f,3)); } /* Given a root x of polclass(D, inv) modulo N, returns a root of polclass(D,0) * modulo N by plugging x to a modular polynomial. For double-eta quotients, * this is done by plugging x into the modular polynomial Phi(INV_WpWq, j) * Enge, Morain 2013: Generalised Weber Functions. */ GEN Fp_modinv_to_j(GEN x, long inv, GEN p) { switch(inv) { case INV_J: return Fp_red(x, p); case INV_G2: return Fp_powu(x, 3, p); case INV_F: case INV_F2: case INV_F3: case INV_F4: case INV_F8: { GEN xe = Fp_powu(x, weber_exponent(inv), p); return Fp_div(Fp_powu(subiu(xe, 16), 3, p), xe, p); } default: if (modinv_is_double_eta(inv)) { GEN xe = Fp_powu(x, double_eta_exponent(inv), p); GEN uvk = double_eta_raw_to_Fp(double_eta_raw(inv), p); GEN J0 = FpX_eval(gel(uvk,1), xe, p); GEN J1 = FpX_eval(gel(uvk,2), xe, p); GEN J2 = Fp_pow(xe, gel(uvk,3), p); GEN phi = mkvec3(J0, J1, J2); return FpX_oneroot(RgX_to_FpX(RgV_to_RgX(phi,1), p),p); } pari_err_BUG("Fp_modinv_to_j"); return NULL;/* LCOV_EXCL_LINE */ } } /* Assuming p = 2 (mod 3) and p = 3 (mod 4): if the two 12th roots of * x (mod p) exist, set *r to one of them and return 1, otherwise * return 0 (without touching *r). */ INLINE int twelth_root(ulong *r, ulong x, ulong p, ulong pi, ulong s2) { ulong t = Fl_sqrtl_pre(x, 3, p, pi); if (krouu(t, p) == -1) return 0; t = Fl_sqrt_pre_i(t, s2, p, pi); return safe_abs_sqrt(r, t, p, pi, s2); } INLINE int sixth_root(ulong *r, ulong x, ulong p, ulong pi, ulong s2) { ulong t = Fl_sqrtl_pre(x, 3, p, pi); if (krouu(t, p) == -1) return 0; *r = Fl_sqrt_pre_i(t, s2, p, pi); return 1; } INLINE int fourth_root(ulong *r, ulong x, ulong p, ulong pi, ulong s2) { ulong s; if (krouu(x, p) == -1) return 0; s = Fl_sqrt_pre_i(x, s2, p, pi); return safe_abs_sqrt(r, s, p, pi, s2); } INLINE int double_eta_root(long inv, ulong *r, ulong w, ulong p, ulong pi, ulong s2) { switch (double_eta_exponent(inv)) { case 12: return twelth_root(r, w, p, pi, s2); case 6: return sixth_root(r, w, p, pi, s2); case 4: return fourth_root(r, w, p, pi, s2); case 3: *r = Fl_sqrtl_pre(w, 3, p, pi); return 1; case 2: return krouu(w, p) != -1 && !!(*r = Fl_sqrt_pre_i(w, s2, p, pi)); default: *r = w; return 1; /* case 1 */ } } /* F = double_eta_Fl(inv, p) */ static GEN Flx_double_eta_xpoly(GEN F, ulong j, ulong p, ulong pi) { GEN u = gel(F,1), v = gel(F,2), w; long i, k = itos(gel(F,3)), lu = lg(u), lv = lg(v), lw = lu + 1; w = cgetg(lw, t_VECSMALL); /* lu >= max(lv,k) */ w[1] = 0; /* variable number */ for (i = 1; i < lv; i++) uel(w, i+1) = Fl_add(uel(u,i), Fl_mul_pre(j, uel(v,i), p, pi), p); for ( ; i < lu; i++) uel(w, i+1) = uel(u,i); uel(w, k+2) = Fl_add(uel(w, k+2), Fl_sqr_pre(j, p, pi), p); return Flx_renormalize(w, lw); } /* F = double_eta_Fl(inv, p) */ static GEN Flx_double_eta_jpoly(GEN F, ulong x, ulong p, ulong pi) { pari_sp av = avma; GEN u = gel(F,1), v = gel(F,2), xs; long k = itos(gel(F,3)); ulong a, b, c; /* u is always longest and the length is bigger than k */ xs = Fl_powers_pre(x, lg(u) - 1, p, pi); c = Flv_dotproduct_pre(u, xs, p, pi); b = Flv_dotproduct_pre(v, xs, p, pi); a = uel(xs, k + 1); set_avma(av); return mkvecsmall4(0, c, b, a); } /* reduce F = double_eta_raw(inv) mod p */ static GEN double_eta_raw_to_Fl(GEN f, ulong p) { GEN u = ZV_to_Flv(gel(f,1), p); GEN v = ZV_to_Flv(gel(f,2), p); return mkvec3(u, v, gel(f,3)); } /* double_eta_raw(inv) mod p */ static GEN double_eta_Fl(long inv, ulong p) { return double_eta_raw_to_Fl(double_eta_raw(inv), p); } /* Go through roots of Psi(X,j) until one has an double_eta_exponent(inv)-th * root, and return that root. F = double_eta_Fl(inv,p) */ INLINE ulong modinv_double_eta_from_j(GEN F, long inv, ulong j, ulong p, ulong pi, ulong s2) { pari_sp av = avma; long i; ulong f = ULONG_MAX; GEN a = Flx_double_eta_xpoly(F, j, p, pi); a = Flx_roots_pre(a, p, pi); for (i = 1; i < lg(a); ++i) if (double_eta_root(inv, &f, uel(a, i), p, pi, s2)) break; if (i == lg(a)) pari_err_BUG("modinv_double_eta_from_j"); return gc_ulong(av,f); } /* assume j1 != j2 */ static long modinv_double_eta_from_2j( ulong *r, long inv, ulong j1, ulong j2, ulong p, ulong pi, ulong s2) { GEN f, g, d, F = double_eta_Fl(inv, p); f = Flx_double_eta_xpoly(F, j1, p, pi); g = Flx_double_eta_xpoly(F, j2, p, pi); d = Flx_gcd(f, g, p); /* we should have deg(d) = 1, but because j1 or j2 may not have the correct * endomorphism ring, we use the less strict conditional underneath */ return (degpol(d) > 2 || (*r = Flx_oneroot_pre(d, p, pi)) == p || ! double_eta_root(inv, r, *r, p, pi, s2)); } long modfn_unambiguous_root(ulong *r, long inv, ulong j0, norm_eqn_t ne, GEN jdb) { pari_sp av = avma; long p1, p2, v = ne->v, p1_depth; ulong j1, p = ne->p, pi = ne->pi, s2 = ne->s2; GEN phi; (void) modinv_degree(&p1, &p2, inv); p1_depth = u_lval(v, p1); phi = polmodular_db_getp(jdb, p1, p); if (!next_surface_nbr(&j1, phi, p1, p1_depth, j0, NULL, p, pi)) pari_err_BUG("modfn_unambiguous_root"); if (p2 == p1) { if (!next_surface_nbr(&j1, phi, p1, p1_depth, j1, &j0, p, pi)) pari_err_BUG("modfn_unambiguous_root"); } else { long p2_depth = u_lval(v, p2); phi = polmodular_db_getp(jdb, p2, p); if (!next_surface_nbr(&j1, phi, p2, p2_depth, j1, NULL, p, pi)) pari_err_BUG("modfn_unambiguous_root"); } return gc_long(av, j1 != j0 && !modinv_double_eta_from_2j(r, inv, j0, j1, p, pi, s2)); } ulong modfn_root(ulong j, norm_eqn_t ne, long inv) { ulong f, p = ne->p, pi = ne->pi, s2 = ne->s2; switch (inv) { case INV_J: return j; case INV_G2: return Fl_sqrtl_pre(j, 3, p, pi); case INV_F: return modinv_f_from_j(j, p, pi, s2, 0); case INV_F2: f = modinv_f_from_j(j, p, pi, s2, 0); return Fl_sqr_pre(f, p, pi); case INV_F3: return modinv_f3_from_j(j, p, pi, s2); case INV_F4: f = modinv_f_from_j(j, p, pi, s2, 0); return Fl_sqr_pre(Fl_sqr_pre(f, p, pi), p, pi); case INV_F8: return modinv_f_from_j(j, p, pi, s2, 1); } if (modinv_is_double_eta(inv)) { pari_sp av = avma; ulong f = modinv_double_eta_from_j(double_eta_Fl(inv,p), inv, j, p, pi, s2); return gc_ulong(av,f); } pari_err_BUG("modfn_root"); return ULONG_MAX;/*LCOV_EXCL_LINE*/ } /* F = double_eta_raw(inv) */ long modinv_j_from_2double_eta( GEN F, long inv, ulong x0, ulong x1, ulong p, ulong pi) { GEN f, g, d; x0 = double_eta_power(inv, x0, p, pi); x1 = double_eta_power(inv, x1, p, pi); F = double_eta_raw_to_Fl(F, p); f = Flx_double_eta_jpoly(F, x0, p, pi); g = Flx_double_eta_jpoly(F, x1, p, pi); d = Flx_gcd(f, g, p); /* >= 1 */ return degpol(d) == 1; } /* x root of (X^24 - 16)^3 - X^24 * j = 0 => j = (x^24 - 16)^3 / x^24 */ INLINE ulong modinv_j_from_f(ulong x, ulong n, ulong p, ulong pi) { ulong x24 = Fl_powu_pre(x, 24 / n, p, pi); return Fl_div(Fl_powu_pre(Fl_sub(x24, 16 % p, p), 3, p, pi), x24, p); } /* should never be called if modinv_double_eta(inv) is true */ INLINE ulong modfn_preimage(ulong x, ulong p, ulong pi, long inv) { switch (inv) { case INV_J: return x; case INV_G2: return Fl_powu_pre(x, 3, p, pi); /* NB: could replace these with a single call modinv_j_from_f(x,inv,p,pi) * but avoid the dependence on the actual value of inv */ case INV_F: return modinv_j_from_f(x, 1, p, pi); case INV_F2: return modinv_j_from_f(x, 2, p, pi); case INV_F3: return modinv_j_from_f(x, 3, p, pi); case INV_F4: return modinv_j_from_f(x, 4, p, pi); case INV_F8: return modinv_j_from_f(x, 8, p, pi); } pari_err_BUG("modfn_preimage"); return ULONG_MAX;/*LCOV_EXCL_LINE*/ } /* SECTION: class group bb_group. */ INLINE GEN mkqfis(GEN a, ulong b, ulong c, GEN D) { retmkqfb(a, utoi(b), utoi(c), D); } /* SECTION: dot-product-like functions on Fl's with precomputed inverse. */ /* Computes x0y1 + y0x1 (mod p); assumes p < 2^63. */ INLINE ulong Fl_addmul2( ulong x0, ulong x1, ulong y0, ulong y1, ulong p, ulong pi) { return Fl_addmulmul_pre(x0,y1,y0,x1,p,pi); } /* Computes x0y2 + x1y1 + x2y0 (mod p); assumes p < 2^62. */ INLINE ulong Fl_addmul3( ulong x0, ulong x1, ulong x2, ulong y0, ulong y1, ulong y2, ulong p, ulong pi) { ulong l0, l1, h0, h1; LOCAL_OVERFLOW; LOCAL_HIREMAINDER; l0 = mulll(x0, y2); h0 = hiremainder; l1 = mulll(x1, y1); h1 = hiremainder; l1 = addll(l0, l1); h1 = addllx(h0, h1); l0 = mulll(x2, y0); h0 = hiremainder; l1 = addll(l0, l1); h1 = addllx(h0, h1); return remll_pre(h1, l1, p, pi); } /* Computes x0y3 + x1y2 + x2y1 + x3y0 (mod p); assumes p < 2^62. */ INLINE ulong Fl_addmul4( ulong x0, ulong x1, ulong x2, ulong x3, ulong y0, ulong y1, ulong y2, ulong y3, ulong p, ulong pi) { ulong l0, l1, h0, h1; LOCAL_OVERFLOW; LOCAL_HIREMAINDER; l0 = mulll(x0, y3); h0 = hiremainder; l1 = mulll(x1, y2); h1 = hiremainder; l1 = addll(l0, l1); h1 = addllx(h0, h1); l0 = mulll(x2, y1); h0 = hiremainder; l1 = addll(l0, l1); h1 = addllx(h0, h1); l0 = mulll(x3, y0); h0 = hiremainder; l1 = addll(l0, l1); h1 = addllx(h0, h1); return remll_pre(h1, l1, p, pi); } /* Computes x0y4 + x1y3 + x2y2 + x3y1 + x4y0 (mod p); assumes p < 2^62. */ INLINE ulong Fl_addmul5( ulong x0, ulong x1, ulong x2, ulong x3, ulong x4, ulong y0, ulong y1, ulong y2, ulong y3, ulong y4, ulong p, ulong pi) { ulong l0, l1, h0, h1; LOCAL_OVERFLOW; LOCAL_HIREMAINDER; l0 = mulll(x0, y4); h0 = hiremainder; l1 = mulll(x1, y3); h1 = hiremainder; l1 = addll(l0, l1); h1 = addllx(h0, h1); l0 = mulll(x2, y2); h0 = hiremainder; l1 = addll(l0, l1); h1 = addllx(h0, h1); l0 = mulll(x3, y1); h0 = hiremainder; l1 = addll(l0, l1); h1 = addllx(h0, h1); l0 = mulll(x4, y0); h0 = hiremainder; l1 = addll(l0, l1); h1 = addllx(h0, h1); return remll_pre(h1, l1, p, pi); } /* A polmodular database for a given class invariant consists of a t_VEC whose * L-th entry is 0 or a GEN pointing to Phi_L. This function produces a pair * of databases corresponding to the j-invariant and inv */ GEN polmodular_db_init(long inv) { const long LEN = 32; GEN res = cgetg_block(3, t_VEC); gel(res, 1) = zerovec_block(LEN); gel(res, 2) = (inv == INV_J)? gen_0: zerovec_block(LEN); return res; } void polmodular_db_add_level(GEN *DB, long L, long inv) { GEN db = gel(*DB, (inv == INV_J)? 1: 2); long max_L = lg(db) - 1; if (L > max_L) { GEN newdb; long i, newlen = 2 * L; newdb = cgetg_block(newlen + 1, t_VEC); for (i = 1; i <= max_L; ++i) gel(newdb, i) = gel(db, i); for ( ; i <= newlen; ++i) gel(newdb, i) = gen_0; killblock(db); gel(*DB, (inv == INV_J)? 1: 2) = db = newdb; } if (typ(gel(db, L)) == t_INT) { pari_sp av = avma; GEN x = polmodular0_ZM(L, inv, NULL, NULL, 0, DB); /* may set db[L] */ GEN y = gel(db, L); gel(db, L) = gclone(x); if (typ(y) != t_INT) gunclone(y); set_avma(av); } } void polmodular_db_add_levels(GEN *db, long *levels, long k, long inv) { long i; for (i = 0; i < k; ++i) polmodular_db_add_level(db, levels[i], inv); } GEN polmodular_db_for_inv(GEN db, long inv) { return gel(db, (inv==INV_J)? 1: 2); } /* TODO: Also cache modpoly mod p for most recent p (avoid repeated * reductions in, for example, polclass.c:oneroot_of_classpoly(). */ GEN polmodular_db_getp(GEN db, long L, ulong p) { GEN f = gel(db, L); if (isintzero(f)) pari_err_BUG("polmodular_db_getp"); return ZM_to_Flm(f, p); } /* SECTION: Table of discriminants to use. */ typedef struct { long GENcode0; /* used when serializing the struct to a t_VECSMALL */ long inv; /* invariant */ long L; /* modpoly level */ long D0; /* fundamental discriminant */ long D1; /* chosen discriminant */ long L0; /* first generator norm */ long L1; /* second generator norm */ long n1; /* order of L0 in cl(D1) */ long n2; /* order of L0 in cl(D2) where D2 = L^2 D1 */ long dl1; /* m such that L0^m = L in cl(D1) */ long dl2_0; /* These two are (m, n) such that L0^m L1^n = form of norm L^2 in D2 */ long dl2_1; /* This n is always 1 or 0. */ /* this part is not serialized */ long nprimes; /* number of primes needed for D1 */ long cost; /* cost to enumerate subgroup of cl(L^2D): subgroup size is n2 if L1=0, 2*n2 o.w. */ long bits; ulong *primes; ulong *traces; } disc_info; #define MODPOLY_MAX_DCNT 64 /* Flag for last parameter of discriminant_with_classno_at_least. * Warning: ignoring the sparse factor makes everything slower by * something like (sparse factor)^3. */ #define USE_SPARSE_FACTOR 0 #define IGNORE_SPARSE_FACTOR 1 static long discriminant_with_classno_at_least(disc_info Ds[MODPOLY_MAX_DCNT], long L, long inv, GEN Q, long ignore_sparse); /* SECTION: evaluation functions for modular polynomials of small level. */ /* Based on phi2_eval_ff() in Sutherland's classpoly programme. * Calculates Phi_2(X, j) (mod p) with 6M+7A (4 reductions, not * counting those for Phi_2) */ INLINE GEN Flm_Fl_phi2_evalx(GEN phi2, ulong j, ulong p, ulong pi) { GEN res = cgetg(6, t_VECSMALL); ulong j2, t1; res[1] = 0; /* variable name */ j2 = Fl_sqr_pre(j, p, pi); t1 = Fl_add(j, coeff(phi2, 3, 1), p); t1 = Fl_addmul2(j, j2, t1, coeff(phi2, 2, 1), p, pi); res[2] = Fl_add(t1, coeff(phi2, 1, 1), p); t1 = Fl_addmul2(j, j2, coeff(phi2, 3, 2), coeff(phi2, 2, 2), p, pi); res[3] = Fl_add(t1, coeff(phi2, 2, 1), p); t1 = Fl_mul_pre(j, coeff(phi2, 3, 2), p, pi); t1 = Fl_add(t1, coeff(phi2, 3, 1), p); res[4] = Fl_sub(t1, j2, p); res[5] = 1; return res; } /* Based on phi3_eval_ff() in Sutherland's classpoly programme. * Calculates Phi_3(X, j) (mod p) with 13M+13A (6 reductions, not * counting those for Phi_3) */ INLINE GEN Flm_Fl_phi3_evalx(GEN phi3, ulong j, ulong p, ulong pi) { GEN res = cgetg(7, t_VECSMALL); ulong j2, j3, t1; res[1] = 0; /* variable name */ j2 = Fl_sqr_pre(j, p, pi); j3 = Fl_mul_pre(j, j2, p, pi); t1 = Fl_add(j, coeff(phi3, 4, 1), p); res[2] = Fl_addmul3(j, j2, j3, t1, coeff(phi3, 3, 1), coeff(phi3, 2, 1), p, pi); t1 = Fl_addmul3(j, j2, j3, coeff(phi3, 4, 2), coeff(phi3, 3, 2), coeff(phi3, 2, 2), p, pi); res[3] = Fl_add(t1, coeff(phi3, 2, 1), p); t1 = Fl_addmul3(j, j2, j3, coeff(phi3, 4, 3), coeff(phi3, 3, 3), coeff(phi3, 3, 2), p, pi); res[4] = Fl_add(t1, coeff(phi3, 3, 1), p); t1 = Fl_addmul2(j, j2, coeff(phi3, 4, 3), coeff(phi3, 4, 2), p, pi); t1 = Fl_add(t1, coeff(phi3, 4, 1), p); res[5] = Fl_sub(t1, j3, p); res[6] = 1; return res; } /* Based on phi5_eval_ff() in Sutherland's classpoly programme. * Calculates Phi_5(X, j) (mod p) with 33M+31A (10 reductions, not * counting those for Phi_5) */ INLINE GEN Flm_Fl_phi5_evalx(GEN phi5, ulong j, ulong p, ulong pi) { GEN res = cgetg(9, t_VECSMALL); ulong j2, j3, j4, j5, t1; res[1] = 0; /* variable name */ j2 = Fl_sqr_pre(j, p, pi); j3 = Fl_mul_pre(j, j2, p, pi); j4 = Fl_sqr_pre(j2, p, pi); j5 = Fl_mul_pre(j, j4, p, pi); t1 = Fl_add(j, coeff(phi5, 6, 1), p); t1 = Fl_addmul5(j, j2, j3, j4, j5, t1, coeff(phi5, 5, 1), coeff(phi5, 4, 1), coeff(phi5, 3, 1), coeff(phi5, 2, 1), p, pi); res[2] = Fl_add(t1, coeff(phi5, 1, 1), p); t1 = Fl_addmul5(j, j2, j3, j4, j5, coeff(phi5, 6, 2), coeff(phi5, 5, 2), coeff(phi5, 4, 2), coeff(phi5, 3, 2), coeff(phi5, 2, 2), p, pi); res[3] = Fl_add(t1, coeff(phi5, 2, 1), p); t1 = Fl_addmul5(j, j2, j3, j4, j5, coeff(phi5, 6, 3), coeff(phi5, 5, 3), coeff(phi5, 4, 3), coeff(phi5, 3, 3), coeff(phi5, 3, 2), p, pi); res[4] = Fl_add(t1, coeff(phi5, 3, 1), p); t1 = Fl_addmul5(j, j2, j3, j4, j5, coeff(phi5, 6, 4), coeff(phi5, 5, 4), coeff(phi5, 4, 4), coeff(phi5, 4, 3), coeff(phi5, 4, 2), p, pi); res[5] = Fl_add(t1, coeff(phi5, 4, 1), p); t1 = Fl_addmul5(j, j2, j3, j4, j5, coeff(phi5, 6, 5), coeff(phi5, 5, 5), coeff(phi5, 5, 4), coeff(phi5, 5, 3), coeff(phi5, 5, 2), p, pi); res[6] = Fl_add(t1, coeff(phi5, 5, 1), p); t1 = Fl_addmul4(j, j2, j3, j4, coeff(phi5, 6, 5), coeff(phi5, 6, 4), coeff(phi5, 6, 3), coeff(phi5, 6, 2), p, pi); t1 = Fl_add(t1, coeff(phi5, 6, 1), p); res[7] = Fl_sub(t1, j5, p); res[8] = 1; return res; } GEN Flm_Fl_polmodular_evalx(GEN phi, long L, ulong j, ulong p, ulong pi) { switch (L) { case 2: return Flm_Fl_phi2_evalx(phi, j, p, pi); case 3: return Flm_Fl_phi3_evalx(phi, j, p, pi); case 5: return Flm_Fl_phi5_evalx(phi, j, p, pi); default: { /* not GC clean, but gerepileupto-safe */ GEN j_powers = Fl_powers_pre(j, L + 1, p, pi); return Flm_Flc_mul_pre_Flx(phi, j_powers, p, pi, 0); } } } /* SECTION: Velu's formula for the codmain curve (Fl case). */ INLINE ulong Fl_mul4(ulong x, ulong p) { return Fl_double(Fl_double(x, p), p); } INLINE ulong Fl_mul5(ulong x, ulong p) { return Fl_add(x, Fl_mul4(x, p), p); } INLINE ulong Fl_mul8(ulong x, ulong p) { return Fl_double(Fl_mul4(x, p), p); } INLINE ulong Fl_mul6(ulong x, ulong p) { return Fl_sub(Fl_mul8(x, p), Fl_double(x, p), p); } INLINE ulong Fl_mul7(ulong x, ulong p) { return Fl_sub(Fl_mul8(x, p), x, p); } /* Given an elliptic curve E = [a4, a6] over F_p and a nonzero point * pt on E, return the quotient E' = E/

= [a4_img, a6_img] */ static void Fle_quotient_from_kernel_generator( ulong *a4_img, ulong *a6_img, ulong a4, ulong a6, GEN pt, ulong p, ulong pi) { pari_sp av = avma; ulong t = 0, w = 0; GEN Q; ulong xQ, yQ, tQ, uQ; Q = gcopy(pt); /* Note that, as L is odd, say L = 2n + 1, we necessarily have * [(L - 1)/2]P = [n]P = [n - L]P = -[n + 1]P = -[(L + 1)/2]P. This is * what the condition Q[1] != xQ tests, so the loop will execute n times. */ do { xQ = uel(Q, 1); yQ = uel(Q, 2); /* tQ = 6 xQ^2 + b2 xQ + b4 * = 6 xQ^2 + 2 a4 (since b2 = 0 and b4 = 2 a4) */ tQ = Fl_add(Fl_mul6(Fl_sqr_pre(xQ, p, pi), p), Fl_double(a4, p), p); uQ = Fl_add(Fl_mul4(Fl_sqr_pre(yQ, p, pi), p), Fl_mul_pre(tQ, xQ, p, pi), p); t = Fl_add(t, tQ, p); w = Fl_add(w, uQ, p); Q = gerepileupto(av, Fle_add(pt, Q, a4, p)); } while (uel(Q, 1) != xQ); set_avma(av); /* a4_img = a4 - 5 * t */ *a4_img = Fl_sub(a4, Fl_mul5(t, p), p); /* a6_img = a6 - b2 * t - 7 * w = a6 - 7 * w (since a1 = a2 = 0 ==> b2 = 0) */ *a6_img = Fl_sub(a6, Fl_mul7(w, p), p); } /* SECTION: Calculation of modular polynomials. */ /* Given an elliptic curve [a4, a6] over FF_p, try to find a * nontrivial L-torsion point on the curve by considering n times a * random point; val controls the maximum L-valuation expected of n * times a random point */ static GEN find_L_tors_point( ulong *ival, ulong a4, ulong a6, ulong p, ulong pi, ulong n, ulong L, ulong val) { pari_sp av = avma; ulong i; GEN P, Q; do { Q = random_Flj_pre(a4, a6, p, pi); P = Flj_mulu_pre(Q, n, a4, p, pi); } while (P[3] == 0); for (i = 0; i < val; ++i) { Q = Flj_mulu_pre(P, L, a4, p, pi); if (Q[3] == 0) break; P = Q; } if (ival) *ival = i; return gerepilecopy(av, P); } static GEN select_curve_with_L_tors_point( ulong *a4, ulong *a6, ulong L, ulong j, ulong n, ulong card, ulong val, norm_eqn_t ne) { pari_sp av = avma; ulong A4, A4t, A6, A6t; ulong p = ne->p, pi = ne->pi; GEN P; if (card % L != 0) { pari_err_BUG("select_curve_with_L_tors_point: " "Cardinality not divisible by L"); } Fl_ellj_to_a4a6(j, p, &A4, &A6); Fl_elltwist_disc(A4, A6, ne->T, p, &A4t, &A6t); /* Either E = [a4, a6] or its twist has cardinality divisible by L * because of the choice of p and t earlier on. We find out which * by attempting to find a point of order L on each. See bot p16 of * Sutherland 2012. */ while (1) { ulong i; P = find_L_tors_point(&i, A4, A6, p, pi, n, L, val); if (i < val) break; set_avma(av); lswap(A4, A4t); lswap(A6, A6t); } *a4 = A4; *a6 = A6; return gerepilecopy(av, P); } /* Return 1 if the L-Sylow subgroup of the curve [a4, a6] (mod p) is * cyclic, return 0 if it is not cyclic with "high" probability (I * guess around 1/L^3 chance it is still cyclic when we return 0). * * Based on Sutherland's velu.c:velu_verify_Sylow_cyclic() in classpoly-1.0.1 */ INLINE long verify_L_sylow_is_cyclic(long e, ulong a4, ulong a6, ulong p, ulong pi) { /* Number of times to try to find a point with maximal order in the * L-Sylow subgroup. */ enum { N_RETRIES = 3 }; pari_sp av = avma; long i, res = 0; GEN P; for (i = 0; i < N_RETRIES; ++i) { P = random_Flj_pre(a4, a6, p, pi); P = Flj_mulu_pre(P, e, a4, p, pi); if (P[3] != 0) { res = 1; break; } } return gc_long(av,res); } static ulong find_noniso_L_isogenous_curve( ulong L, ulong n, norm_eqn_t ne, long e, ulong val, ulong a4, ulong a6, GEN init_pt, long verify) { pari_sp ltop, av; ulong p = ne->p, pi = ne->pi, j_res = 0; GEN pt = init_pt; ltop = av = avma; while (1) { /* c. Use Velu to calculate L-isogenous curve E' = E/

*/ ulong a4_img, a6_img; ulong z2 = Fl_sqr_pre(pt[3], p, pi); pt = mkvecsmall2(Fl_div(pt[1], z2, p), Fl_div(pt[2], Fl_mul_pre(z2, pt[3], p, pi), p)); Fle_quotient_from_kernel_generator(&a4_img, &a6_img, a4, a6, pt, p, pi); /* d. If j(E') = j_res has a different endo ring to j(E), then * return j(E'). Otherwise, go to b. */ if (!verify || verify_L_sylow_is_cyclic(e, a4_img, a6_img, p, pi)) { j_res = Fl_ellj_pre(a4_img, a6_img, p, pi); break; } /* b. Generate random point P on E of order L */ set_avma(av); pt = find_L_tors_point(NULL, a4, a6, p, pi, n, L, val); } return gc_ulong(ltop, j_res); } /* Given a prime L and a j-invariant j (mod p), return the j-invariant * of a curve which has a different endomorphism ring to j and is * L-isogenous to j */ INLINE ulong compute_L_isogenous_curve( ulong L, ulong n, norm_eqn_t ne, ulong j, ulong card, ulong val, long verify) { ulong a4, a6; long e; GEN pt; if (ne->p < 5 || j == 0 || j == 1728 % ne->p) pari_err_BUG("compute_L_isogenous_curve"); pt = select_curve_with_L_tors_point(&a4, &a6, L, j, n, card, val, ne); e = card / L; if (e * L != card) pari_err_BUG("compute_L_isogenous_curve"); return find_noniso_L_isogenous_curve(L, n, ne, e, val, a4, a6, pt, verify); } INLINE GEN get_Lsqr_cycle(const disc_info *dinfo) { long i, n1 = dinfo->n1, L = dinfo->L; GEN cyc = cgetg(L, t_VECSMALL); cyc[1] = 0; for (i = 2; i <= L / 2; ++i) cyc[i] = cyc[i - 1] + n1; if ( ! dinfo->L1) { for ( ; i < L; ++i) cyc[i] = cyc[i - 1] + n1; } else { cyc[L - 1] = 2 * dinfo->n2 - n1 / 2; for (i = L - 2; i > L / 2; --i) cyc[i] = cyc[i + 1] - n1; } return cyc; } INLINE void update_Lsqr_cycle(GEN cyc, const disc_info *dinfo) { long i, L = dinfo->L; for (i = 1; i < L; ++i) ++cyc[i]; if (dinfo->L1 && cyc[L - 1] == 2 * dinfo->n2) { long n1 = dinfo->n1; for (i = L / 2 + 1; i < L; ++i) cyc[i] -= n1; } } static ulong oneroot_of_classpoly(GEN hilb, GEN factu, norm_eqn_t ne, GEN jdb) { pari_sp av = avma; ulong j0, p = ne->p, pi = ne->pi; long i, nfactors = lg(gel(factu, 1)) - 1; GEN hilbp = ZX_to_Flx(hilb, p); /* TODO: Work out how to use hilb with better invariant */ j0 = Flx_oneroot_split_pre(hilbp, p, pi); if (j0 == p) { pari_err_BUG("oneroot_of_classpoly: " "Didn't find a root of the class polynomial"); } for (i = 1; i <= nfactors; ++i) { long L = gel(factu, 1)[i]; long val = gel(factu, 2)[i]; GEN phi = polmodular_db_getp(jdb, L, p); val += z_lval(ne->v, L); j0 = descend_volcano(phi, j0, p, pi, 0, L, val, val); set_avma(av); } return gc_ulong(av, j0); } /* TODO: Precompute the GEN structs and link them to dinfo */ INLINE GEN make_pcp_surface(const disc_info *dinfo) { GEN L = mkvecsmall(dinfo->L0); GEN n = mkvecsmall(dinfo->n1); GEN o = mkvecsmall(dinfo->n1); return mkvec2(mkvec3(L, n, o), mkvecsmall3(0, 1, dinfo->n1)); } INLINE GEN make_pcp_floor(const disc_info *dinfo) { long k = dinfo->L1 ? 2 : 1; GEN L, n, o; if (k==1) { L = mkvecsmall(dinfo->L0); n = mkvecsmall(dinfo->n2); o = mkvecsmall(dinfo->n2); } else { L = mkvecsmall2(dinfo->L0, dinfo->L1); n = mkvecsmall2(dinfo->n2, 2); o = mkvecsmall2(dinfo->n2, 2); } return mkvec2(mkvec3(L, n, o), mkvecsmall3(0, k, dinfo->n2*k)); } INLINE GEN enum_volcano_surface(norm_eqn_t ne, ulong j0, GEN fdb, GEN G) { pari_sp av = avma; return gerepileupto(av, enum_roots(j0, ne, fdb, G, NULL)); } INLINE GEN enum_volcano_floor(long L, norm_eqn_t ne, ulong j0_pr, GEN fdb, GEN G) { pari_sp av = avma; /* L^2 D is the discriminant for the order R = Z + L OO. */ long DR = L * L * ne->D; long R_cond = L * ne->u; /* conductor(DR); */ long w = R_cond * ne->v; /* TODO: Calculate these once and for all in polmodular0_ZM(). */ norm_eqn_t eqn; memcpy(eqn, ne, sizeof *ne); eqn->D = DR; eqn->u = R_cond; eqn->v = w; return gerepileupto(av, enum_roots(j0_pr, eqn, fdb, G, NULL)); } INLINE void carray_reverse_inplace(long *arr, long n) { long lim = n>>1, i; --n; for (i = 0; i < lim; i++) lswap(arr[i], arr[n - i]); } INLINE void append_neighbours(GEN rts, GEN surface_js, long njs, long L, long m, long i) { long r_idx = (((i - 1) + m) % njs) + 1; /* (i + m) % njs */ long l_idx = umodsu((i - 1) - m, njs) + 1; /* (i - m) % njs */ rts[L] = surface_js[l_idx]; rts[L + 1] = surface_js[r_idx]; } INLINE GEN roots_to_coeffs(GEN rts, ulong p, long L) { long i, k, lrts= lg(rts); GEN M = cgetg(L+2+1, t_MAT); for (i = 1; i <= L+2; ++i) gel(M, i) = cgetg(lrts, t_VECSMALL); for (i = 1; i < lrts; ++i) { pari_sp av = avma; GEN modpol = Flv_roots_to_pol(gel(rts, i), p, 0); for (k = 1; k <= L + 2; ++k) mael(M, k, i) = modpol[k + 1]; set_avma(av); } return M; } /* NB: Assumes indices are offset at 0, not at 1 like in GENs; * i.e. indices[i] will pick out v[indices[i] + 1] from v. */ INLINE void vecsmall_pick(GEN res, GEN v, GEN indices) { long i; for (i = 1; i < lg(indices); ++i) res[i] = v[indices[i] + 1]; } /* First element of surface_js must lie above the first element of floor_js. * Reverse surface_js if it is not oriented in the same direction as floor_js */ INLINE GEN root_matrix(long L, const disc_info *dinfo, long njinvs, GEN surface_js, GEN floor_js, ulong n, ulong card, ulong val, norm_eqn_t ne) { pari_sp av; long i, m = dinfo->dl1, njs = lg(surface_js) - 1, inv = dinfo->inv, rev; GEN rt_mat = zero_Flm_copy(L + 1, njinvs), rts, cyc; ulong p = ne->p, pi = ne->pi, j; av = avma; i = 1; cyc = get_Lsqr_cycle(dinfo); rts = gel(rt_mat, i); vecsmall_pick(rts, floor_js, cyc); append_neighbours(rts, surface_js, njs, L, m, i); i = 2; update_Lsqr_cycle(cyc, dinfo); rts = gel(rt_mat, i); vecsmall_pick(rts, floor_js, cyc); /* Fix orientation if necessary */ if (modinv_is_double_eta(inv)) { /* TODO: There is potential for refactoring between this, * double_eta_initial_js and modfn_preimage. */ pari_sp av0 = avma; GEN F = double_eta_Fl(inv, p); pari_sp av = avma; ulong r1 = double_eta_power(inv, uel(rts, 1), p, pi); GEN r, f = Flx_double_eta_jpoly(F, r1, p, pi); if ((j = Flx_oneroot_pre(f, p, pi)) == p) pari_err_BUG("root_matrix"); j = compute_L_isogenous_curve(L, n, ne, j, card, val, 0); set_avma(av); r1 = double_eta_power(inv, uel(surface_js, i), p, pi); f = Flx_double_eta_jpoly(F, r1, p, pi); r = Flx_roots_pre(f, p, pi); if (lg(r) != 3) pari_err_BUG("root_matrix"); rev = (j != uel(r, 1)) && (j != uel(r, 2)); set_avma(av0); } else { ulong j1pr, j1; j1pr = modfn_preimage(uel(rts, 1), p, pi, dinfo->inv); j1 = compute_L_isogenous_curve(L, n, ne, j1pr, card, val, 0); rev = j1 != modfn_preimage(uel(surface_js, i), p, pi, dinfo->inv); } if (rev) carray_reverse_inplace(surface_js + 2, njs - 1); append_neighbours(rts, surface_js, njs, L, m, i); for (i = 3; i <= njinvs; ++i) { update_Lsqr_cycle(cyc, dinfo); rts = gel(rt_mat, i); vecsmall_pick(rts, floor_js, cyc); append_neighbours(rts, surface_js, njs, L, m, i); } set_avma(av); return rt_mat; } INLINE void interpolate_coeffs(GEN phi_modp, ulong p, GEN j_invs, GEN coeff_mat) { pari_sp av = avma; long i; GEN pols = Flv_Flm_polint(j_invs, coeff_mat, p, 0); for (i = 1; i < lg(pols); ++i) { GEN pol = gel(pols, i); long k, maxk = lg(pol); for (k = 2; k < maxk; ++k) coeff(phi_modp, k - 1, i) = pol[k]; } set_avma(av); } INLINE long Flv_lastnonzero(GEN v) { long i; for (i = lg(v) - 1; i > 0; --i) if (v[i]) break; return i; } /* Assuming the matrix of coefficients in phi corresponds to polynomials * phi_k^* satisfying Y^c phi_k^*(Y^s) for c in {0, 1, ..., s} satisfying * c + Lk = L + 1 (mod s), change phi so that the coefficients are for the * polynomials Y^c phi_k^*(Y^s) (s is the sparsity factor) */ INLINE void inflate_polys(GEN phi, long L, long s) { long k, deg = L + 1; long maxr; maxr = nbrows(phi); for (k = 0; k <= deg; ) { long i, c = umodsu(L * (1 - k) + 1, s); /* TODO: We actually know that the last nonzero element of gel(phi, k) * can't be later than index n+1, where n is about (L + 1)/s. */ ++k; for (i = Flv_lastnonzero(gel(phi, k)); i > 0; --i) { long r = c + (i - 1) * s + 1; if (r > maxr) { coeff(phi, i, k) = 0; continue; } if (r != i) { coeff(phi, r, k) = coeff(phi, i, k); coeff(phi, i, k) = 0; } } } } INLINE void Flv_powu_inplace_pre(GEN v, ulong n, ulong p, ulong pi) { long i; for (i = 1; i < lg(v); ++i) v[i] = Fl_powu_pre(v[i], n, p, pi); } INLINE void normalise_coeffs(GEN coeffs, GEN js, long L, long s, ulong p, ulong pi) { pari_sp av = avma; long k; GEN pows, modinv_js; /* NB: In fact it would be correct to return the coefficients "as is" when * s = 1, but we make that an error anyway since this function should never * be called with s = 1. */ if (s <= 1) pari_err_BUG("normalise_coeffs"); /* pows[i + 1] contains 1 / js[i + 1]^i for i = 0, ..., s - 1. */ pows = cgetg(s + 1, t_VEC); gel(pows, 1) = const_vecsmall(lg(js) - 1, 1); modinv_js = Flv_inv_pre(js, p, pi); gel(pows, 2) = modinv_js; for (k = 3; k <= s; ++k) { gel(pows, k) = gcopy(modinv_js); Flv_powu_inplace_pre(gel(pows, k), k - 1, p, pi); } /* For each column of coefficients coeffs[k] = [a0 .. an], * replace ai by ai / js[i]^c. * Said in another way, normalise each row i of coeffs by * dividing through by js[i - 1]^c (where c depends on i). */ for (k = 1; k < lg(coeffs); ++k) { long i, c = umodsu(L * (1 - (k - 1)) + 1, s); GEN col = gel(coeffs, k), C = gel(pows, c + 1); for (i = 1; i < lg(col); ++i) col[i] = Fl_mul_pre(col[i], C[i], p, pi); } set_avma(av); } INLINE void double_eta_initial_js( ulong *x0, ulong *x0pr, ulong j0, ulong j0pr, norm_eqn_t ne, long inv, ulong L, ulong n, ulong card, ulong val) { pari_sp av0 = avma; ulong p = ne->p, pi = ne->pi, s2 = ne->s2; GEN F = double_eta_Fl(inv, p); pari_sp av = avma; ulong j1pr, j1, r, t; GEN f, g; *x0pr = modinv_double_eta_from_j(F, inv, j0pr, p, pi, s2); t = double_eta_power(inv, *x0pr, p, pi); f = Flx_div_by_X_x(Flx_double_eta_jpoly(F, t, p, pi), j0pr, p, &r); if (r) pari_err_BUG("double_eta_initial_js"); j1pr = Flx_deg1_root(f, p); set_avma(av); j1 = compute_L_isogenous_curve(L, n, ne, j1pr, card, val, 0); f = Flx_double_eta_xpoly(F, j0, p, pi); g = Flx_double_eta_xpoly(F, j1, p, pi); /* x0 is the unique common root of f and g */ *x0 = Flx_deg1_root(Flx_gcd(f, g, p), p); set_avma(av0); if ( ! double_eta_root(inv, x0, *x0, p, pi, s2)) pari_err_BUG("double_eta_initial_js"); } /* This is Sutherland 2012, Algorithm 2.1, p16. */ static GEN polmodular_split_p_Flm(ulong L, GEN hilb, GEN factu, norm_eqn_t ne, GEN db, GEN G_surface, GEN G_floor, const disc_info *dinfo) { ulong j0, j0_rt, j0pr, j0pr_rt; ulong n, card, val, p = ne->p, pi = ne->pi; long inv = dinfo->inv, s = modinv_sparse_factor(inv); long nj_selected = ceil((L + 1)/(double)s) + 1; GEN surface_js, floor_js, rts, phi_modp, jdb, fdb; long switched_signs = 0; jdb = polmodular_db_for_inv(db, INV_J); fdb = polmodular_db_for_inv(db, inv); /* Precomputation */ card = p + 1 - ne->t; val = u_lvalrem(card, L, &n); /* n = card / L^{v_L(card)} */ j0 = oneroot_of_classpoly(hilb, factu, ne, jdb); j0pr = compute_L_isogenous_curve(L, n, ne, j0, card, val, 1); if (modinv_is_double_eta(inv)) { double_eta_initial_js(&j0_rt, &j0pr_rt, j0, j0pr, ne, inv, L, n, card, val); } else { j0_rt = modfn_root(j0, ne, inv); j0pr_rt = modfn_root(j0pr, ne, inv); } surface_js = enum_volcano_surface(ne, j0_rt, fdb, G_surface); floor_js = enum_volcano_floor(L, ne, j0pr_rt, fdb, G_floor); rts = root_matrix(L, dinfo, nj_selected, surface_js, floor_js, n, card, val, ne); do { pari_sp btop = avma; long i; GEN coeffs, surf; coeffs = roots_to_coeffs(rts, p, L); surf = vecsmall_shorten(surface_js, nj_selected); if (s > 1) { normalise_coeffs(coeffs, surf, L, s, p, pi); Flv_powu_inplace_pre(surf, s, p, pi); } phi_modp = zero_Flm_copy(L + 2, L + 2); interpolate_coeffs(phi_modp, p, surf, coeffs); if (s > 1) inflate_polys(phi_modp, L, s); /* TODO: Calculate just this coefficient of X^L Y^L, so we can do this * test, then calculate the other coefficients; at the moment we are * sometimes doing all the roots-to-coeffs, normalisation and interpolation * work twice. */ if (ucoeff(phi_modp, L + 1, L + 1) == p - 1) break; if (switched_signs) pari_err_BUG("polmodular_split_p_Flm"); set_avma(btop); for (i = 1; i < lg(rts); ++i) { surface_js[i] = Fl_neg(surface_js[i], p); coeff(rts, L, i) = Fl_neg(coeff(rts, L, i), p); coeff(rts, L + 1, i) = Fl_neg(coeff(rts, L + 1, i), p); } switched_signs = 1; } while (1); dbg_printf(4)(" Phi_%lu(X, Y) (mod %lu) = %Ps\n", L, p, phi_modp); return phi_modp; } INLINE void Flv_deriv_pre_inplace(GEN v, long deg, ulong p, ulong pi) { long i, ln = lg(v), d = deg % p; for (i = ln - 1; i > 1; --i, --d) v[i] = Fl_mul_pre(v[i - 1], d, p, pi); v[1] = 0; } INLINE GEN eval_modpoly_modp(GEN Tp, GEN j_powers, ulong p, ulong pi, int compute_derivs) { long L = lg(j_powers) - 3; GEN j_pows_p = ZV_to_Flv(j_powers, p); GEN tmp = cgetg(2 + 2 * compute_derivs, t_VEC); /* We wrap the result in this t_VEC Tp to trick the * ZM_*_CRT() functions into thinking it's a matrix. */ gel(tmp, 1) = Flm_Flc_mul_pre(Tp, j_pows_p, p, pi); if (compute_derivs) { Flv_deriv_pre_inplace(j_pows_p, L + 1, p, pi); gel(tmp, 2) = Flm_Flc_mul_pre(Tp, j_pows_p, p, pi); Flv_deriv_pre_inplace(j_pows_p, L + 1, p, pi); gel(tmp, 3) = Flm_Flc_mul_pre(Tp, j_pows_p, p, pi); } return tmp; } /* Parallel interface */ GEN polmodular_worker(GEN tp, ulong L, GEN hilb, GEN factu, GEN vne, GEN vinfo, long derivs, GEN j_powers, GEN G_surface, GEN G_floor, GEN fdb) { pari_sp av = avma; norm_eqn_t ne; long D = vne[1], u = vne[2]; ulong vL, t = tp[1], p = tp[2]; GEN Tp; if (! uissquareall((4 * p - t * t) / -D, &vL)) pari_err_BUG("polmodular_worker"); norm_eqn_set(ne, D, t, u, vL, NULL, p); /* L | vL */ Tp = polmodular_split_p_Flm(L, hilb, factu, ne, fdb, G_surface, G_floor, (const disc_info*)vinfo); if (!isintzero(j_powers)) Tp = eval_modpoly_modp(Tp, j_powers, ne->p, ne->pi, derivs); return gerepileupto(av, Tp); } static GEN sympol_to_ZM(GEN phi, long L) { pari_sp av = avma; GEN res = zeromatcopy(L + 2, L + 2); long i, j, c = 1; for (i = 1; i <= L + 1; ++i) for (j = 1; j <= i; ++j, ++c) gcoeff(res, i, j) = gcoeff(res, j, i) = gel(phi, c); gcoeff(res, L + 2, 1) = gcoeff(res, 1, L + 2) = gen_1; return gerepilecopy(av, res); } static GEN polmodular_small_ZM(long L, long inv, GEN *db); INLINE long modinv_max_internal_level(long inv) { switch (inv) { case INV_J: return 5; case INV_G2: return 2; case INV_F: case INV_F2: case INV_F4: case INV_F8: return 5; case INV_W2W5: case INV_W2W5E2: return 7; case INV_W2W3: case INV_W2W3E2: case INV_W3W3: case INV_W3W7: return 5; case INV_W3W3E2:return 2; case INV_F3: case INV_W2W7: case INV_W2W7E2: case INV_W2W13: return 3; case INV_W3W5: case INV_W5W7: case INV_W3W13: return 2; } pari_err_BUG("modinv_max_internal_level"); return LONG_MAX;/*LCOV_EXCL_LINE*/ } static void db_add_levels(GEN *db, GEN P, long inv) { polmodular_db_add_levels(db, zv_to_longptr(P), lg(P)-1, inv); } GEN polmodular0_ZM(long L, long inv, GEN J, GEN Q, int compute_derivs, GEN *db) { pari_sp ltop = avma; long k, d, Dcnt, nprimes = 0; GEN modpoly, plist, tp, j_powers; disc_info Ds[MODPOLY_MAX_DCNT]; long lvl = modinv_level(inv); if (ugcd(L, lvl) != 1) pari_err_DOMAIN("polmodular0_ZM", "invariant", "incompatible with", stoi(L), stoi(lvl)); dbg_printf(1)("Calculating modular polynomial of level %lu for invariant %d\n", L, inv); if (L <= modinv_max_internal_level(inv)) return polmodular_small_ZM(L,inv,db); Dcnt = discriminant_with_classno_at_least(Ds, L, inv, Q, USE_SPARSE_FACTOR); for (d = 0; d < Dcnt; d++) nprimes += Ds[d].nprimes; modpoly = cgetg(nprimes+1, t_VEC); plist = cgetg(nprimes+1, t_VECSMALL); tp = mkvec(mkvecsmall2(0,0)); j_powers = gen_0; if (J) { compute_derivs = !!compute_derivs; j_powers = Fp_powers(J, L+1, Q); } for (d = 0, k = 1; d < Dcnt; d++) { disc_info *dinfo = &Ds[d]; struct pari_mt pt; const long D = dinfo->D1, DK = dinfo->D0; const ulong cond = usqrt(D / DK); long i, pending = 0; GEN worker, hilb, factu = factoru(cond); polmodular_db_add_level(db, dinfo->L0, inv); if (dinfo->L1) polmodular_db_add_level(db, dinfo->L1, inv); dbg_printf(1)("Selected discriminant D = %ld = %ld^2 * %ld.\n", D,cond,DK); hilb = polclass0(DK, INV_J, 0, db); if (cond > 1) db_add_levels(db, gel(factu,1), INV_J); dbg_printf(1)("D = %ld, L0 = %lu, L1 = %lu, ", dinfo->D1, dinfo->L0, dinfo->L1); dbg_printf(1)("n1 = %lu, n2 = %lu, dl1 = %lu, dl2_0 = %lu, dl2_1 = %lu\n", dinfo->n1, dinfo->n2, dinfo->dl1, dinfo->dl2_0, dinfo->dl2_1); dbg_printf(0)("Calculating modular polynomial of level %lu:", L); worker = snm_closure(is_entry("_polmodular_worker"), mkvecn(10, utoi(L), hilb, factu, mkvecsmall2(D, cond), (GEN)dinfo, stoi(compute_derivs), j_powers, make_pcp_surface(dinfo), make_pcp_floor(dinfo), *db)); mt_queue_start_lim(&pt, worker, dinfo->nprimes); for (i = 0; i < dinfo->nprimes || pending; i++) { long workid; GEN done; if (i < dinfo->nprimes) { mael(tp, 1, 1) = dinfo->traces[i]; mael(tp, 1, 2) = dinfo->primes[i]; } mt_queue_submit(&pt, i, i < dinfo->nprimes? tp: NULL); done = mt_queue_get(&pt, &workid, &pending); if (done) { plist[k] = dinfo->primes[workid]; gel(modpoly, k) = done; k++; dbg_printf(0)(" %ld%%", k*100/nprimes); } } dbg_printf(0)(" done\n"); mt_queue_end(&pt); killblock((GEN)dinfo->primes); } modpoly = nmV_chinese_center(modpoly, plist, NULL); if (J) modpoly = FpM_red(modpoly, Q); return gerepileupto(ltop, modpoly); } GEN polmodular_ZM(long L, long inv) { GEN db, Phi; if (L < 2) pari_err_DOMAIN("polmodular_ZM", "L", "<", gen_2, stoi(L)); /* TODO: Handle nonprime L. Algorithm 1.1 and Corollary 3.4 in Sutherland, * "Class polynomials for nonholomorphic modular functions" */ if (! uisprime(L)) pari_err_IMPL("composite level"); db = polmodular_db_init(inv); Phi = polmodular0_ZM(L, inv, NULL, NULL, 0, &db); gunclone_deep(db); return Phi; } GEN polmodular_ZXX(long L, long inv, long vx, long vy) { pari_sp av = avma; GEN phi = polmodular_ZM(L, inv); if (vx < 0) vx = 0; if (vy < 0) vy = 1; if (varncmp(vx, vy) >= 0) pari_err_PRIORITY("polmodular_ZXX", pol_x(vx), "<=", vy); return gerepilecopy(av, RgM_to_RgXX(phi, vx, vy)); } INLINE GEN FpV_deriv(GEN v, long deg, GEN P) { long i, ln = lg(v); GEN dv = cgetg(ln, t_VEC); for (i = ln-1; i > 1; i--, deg--) gel(dv, i) = Fp_mulu(gel(v, i-1), deg, P); gel(dv, 1) = gen_0; return dv; } GEN Fp_polmodular_evalx(long L, long inv, GEN J, GEN P, long v, int compute_derivs) { pari_sp av = avma; GEN db, phi; if (L <= modinv_max_internal_level(inv)) { GEN tmp; GEN phi = RgM_to_FpM(polmodular_ZM(L, inv), P); GEN j_powers = Fp_powers(J, L + 1, P); GEN modpol = RgV_to_RgX(FpM_FpC_mul(phi, j_powers, P), v); if (compute_derivs) { tmp = cgetg(4, t_VEC); gel(tmp, 1) = modpol; j_powers = FpV_deriv(j_powers, L + 1, P); gel(tmp, 2) = RgV_to_RgX(FpM_FpC_mul(phi, j_powers, P), v); j_powers = FpV_deriv(j_powers, L + 1, P); gel(tmp, 3) = RgV_to_RgX(FpM_FpC_mul(phi, j_powers, P), v); } else tmp = modpol; return gerepilecopy(av, tmp); } db = polmodular_db_init(inv); phi = polmodular0_ZM(L, inv, J, P, compute_derivs, &db); phi = RgM_to_RgXV(phi, v); gunclone_deep(db); return gerepilecopy(av, compute_derivs? phi: gel(phi, 1)); } GEN polmodular(long L, long inv, GEN x, long v, long compute_derivs) { pari_sp av = avma; long tx; GEN J = NULL, P = NULL, res = NULL, one = NULL; check_modinv(inv); if (!x || gequalX(x)) { long xv = 0; if (x) xv = varn(x); if (compute_derivs) pari_err_FLAG("polmodular"); return polmodular_ZXX(L, inv, xv, v); } tx = typ(x); if (tx == t_INTMOD) { J = gel(x, 2); P = gel(x, 1); one = mkintmod(gen_1, P); } else if (tx == t_FFELT) { J = FF_to_FpXQ_i(x); if (degpol(J) > 0) pari_err_DOMAIN("polmodular", "x", "not in prime subfield ", gen_0, x); J = constant_coeff(J); P = FF_p_i(x); one = FF_1(x); } else pari_err_TYPE("polmodular", x); if (v < 0) v = 1; res = Fp_polmodular_evalx(L, inv, J, P, v, compute_derivs); return gerepileupto(av, gmul(res, one)); } /* SECTION: Modular polynomials of level <= MAX_INTERNAL_MODPOLY_LEVEL. */ /* These functions return a vector of coefficients of classical modular * polynomials Phi_L(X,Y) of small level L. The number of such coefficients is * (L+1)(L+2)/2 since Phi is symmetric. We omit the common coefficient of * X^{L+1} and Y^{L+1} since it is always 1. Use sympol_to_ZM() to get the * corresponding desymmetrised matrix of coefficients */ /* Phi2, the modular polynomial of level 2: * * X^3 + X^2 * (-Y^2 + 1488*Y - 162000) * + X * (1488*Y^2 + 40773375*Y + 8748000000) * + Y^3 - 162000*Y^2 + 8748000000*Y - 157464000000000 * * [[3, 0, 1], * [2, 2, -1], * [2, 1, 1488], * [2, 0, -162000], * [1, 1, 40773375], * [1, 0, 8748000000], * [0, 0, -157464000000000]], */ static GEN phi2_ZV(void) { GEN phi2 = cgetg(7, t_VEC); gel(phi2, 1) = uu32toi(36662, 1908994048); setsigne(gel(phi2, 1), -1); gel(phi2, 2) = uu32toi(2, 158065408); gel(phi2, 3) = stoi(40773375); gel(phi2, 4) = stoi(-162000); gel(phi2, 5) = stoi(1488); gel(phi2, 6) = gen_m1; return phi2; } /* L = 3 * * [4, 0, 1], * [3, 3, -1], * [3, 2, 2232], * [3, 1, -1069956], * [3, 0, 36864000], * [2, 2, 2587918086], * [2, 1, 8900222976000], * [2, 0, 452984832000000], * [1, 1, -770845966336000000], * [1, 0, 1855425871872000000000] * [0, 0, 0] * * 1855425871872000000000 = 2^32 * (100 * 2^32 + 2503270400) */ static GEN phi3_ZV(void) { GEN phi3 = cgetg(11, t_VEC); pari_sp av = avma; gel(phi3, 1) = gen_0; gel(phi3, 2) = gerepileupto(av, shifti(uu32toi(100, 2503270400UL), 32)); gel(phi3, 3) = uu32toi(179476562, 2147483648UL); setsigne(gel(phi3, 3), -1); gel(phi3, 4) = uu32toi(105468, 3221225472UL); gel(phi3, 5) = uu32toi(2072, 1050738688); gel(phi3, 6) = utoi(2587918086UL); gel(phi3, 7) = stoi(36864000); gel(phi3, 8) = stoi(-1069956); gel(phi3, 9) = stoi(2232); gel(phi3, 10) = gen_m1; return phi3; } static GEN phi5_ZV(void) { GEN phi5 = cgetg(22, t_VEC); gel(phi5, 1) = mkintn(5, 0x18c2cc9cUL, 0x484382b2UL, 0xdc000000UL, 0x0UL, 0x0UL); gel(phi5, 2) = mkintn(5, 0x2638fUL, 0x2ff02690UL, 0x68026000UL, 0x0UL, 0x0UL); gel(phi5, 3) = mkintn(5, 0x308UL, 0xac9d9a4UL, 0xe0fdab12UL, 0xc0000000UL, 0x0UL); setsigne(gel(phi5, 3), -1); gel(phi5, 4) = mkintn(5, 0x13UL, 0xaae09f9dUL, 0x1b5ef872UL, 0x30000000UL, 0x0UL); gel(phi5, 5) = mkintn(4, 0x1b802fa9UL, 0x77ba0653UL, 0xd2f78000UL, 0x0UL); gel(phi5, 6) = mkintn(4, 0xfbfdUL, 0x278e4756UL, 0xdf08a7c4UL, 0x40000000UL); gel(phi5, 7) = mkintn(4, 0x35f922UL, 0x62ccea6fUL, 0x153d0000UL, 0x0UL); gel(phi5, 8) = mkintn(4, 0x97dUL, 0x29203fafUL, 0xc3036909UL, 0x80000000UL); setsigne(gel(phi5, 8), -1); gel(phi5, 9) = mkintn(3, 0x56e9e892UL, 0xd7781867UL, 0xf2ea0000UL); gel(phi5, 10) = mkintn(3, 0x5d6dUL, 0xe0a58f4eUL, 0x9ee68c14UL); setsigne(gel(phi5, 10), -1); gel(phi5, 11) = mkintn(3, 0x1100dUL, 0x85cea769UL, 0x40000000UL); gel(phi5, 12) = mkintn(3, 0x1b38UL, 0x43cf461fUL, 0x3a900000UL); gel(phi5, 13) = mkintn(3, 0x14UL, 0xc45a616eUL, 0x4801680fUL); gel(phi5, 14) = uu32toi(0x17f4350UL, 0x493ca3e0UL); gel(phi5, 15) = uu32toi(0x183UL, 0xe54ce1f8UL); gel(phi5, 16) = uu32toi(0x1c9UL, 0x18860000UL); gel(phi5, 17) = uu32toi(0x39UL, 0x6f7a2206UL); setsigne(gel(phi5, 17), -1); gel(phi5, 18) = stoi(2028551200); gel(phi5, 19) = stoi(-4550940); gel(phi5, 20) = stoi(3720); gel(phi5, 21) = gen_m1; return phi5; } static GEN phi5_f_ZV(void) { GEN phi = zerovec(21); gel(phi, 3) = stoi(4); gel(phi, 21) = gen_m1; return phi; } static GEN phi3_f3_ZV(void) { GEN phi = zerovec(10); gel(phi, 3) = stoi(8); gel(phi, 10) = gen_m1; return phi; } static GEN phi2_g2_ZV(void) { GEN phi = zerovec(6); gel(phi, 1) = stoi(-54000); gel(phi, 3) = stoi(495); gel(phi, 6) = gen_m1; return phi; } static GEN phi5_w2w3_ZV(void) { GEN phi = zerovec(21); gel(phi, 3) = gen_m1; gel(phi, 10) = stoi(5); gel(phi, 21) = gen_m1; return phi; } static GEN phi7_w2w5_ZV(void) { GEN phi = zerovec(36); gel(phi, 3) = gen_m1; gel(phi, 15) = stoi(56); gel(phi, 19) = stoi(42); gel(phi, 24) = stoi(21); gel(phi, 30) = stoi(7); gel(phi, 36) = gen_m1; return phi; } static GEN phi5_w3w3_ZV(void) { GEN phi = zerovec(21); gel(phi, 3) = stoi(9); gel(phi, 6) = stoi(-15); gel(phi, 15) = stoi(5); gel(phi, 21) = gen_m1; return phi; } static GEN phi3_w2w7_ZV(void) { GEN phi = zerovec(10); gel(phi, 3) = gen_m1; gel(phi, 6) = stoi(3); gel(phi, 10) = gen_m1; return phi; } static GEN phi2_w3w5_ZV(void) { GEN phi = zerovec(6); gel(phi, 3) = gen_1; gel(phi, 6) = gen_m1; return phi; } static GEN phi5_w3w7_ZV(void) { GEN phi = zerovec(21); gel(phi, 3) = gen_m1; gel(phi, 6) = stoi(10); gel(phi, 8) = stoi(5); gel(phi, 10) = stoi(35); gel(phi, 13) = stoi(20); gel(phi, 15) = stoi(10); gel(phi, 17) = stoi(5); gel(phi, 19) = stoi(5); gel(phi, 21) = gen_m1; return phi; } static GEN phi3_w2w13_ZV(void) { GEN phi = zerovec(10); gel(phi, 3) = gen_m1; gel(phi, 6) = stoi(3); gel(phi, 8) = stoi(3); gel(phi, 10) = gen_m1; return phi; } static GEN phi2_w3w3e2_ZV(void) { GEN phi = zerovec(6); gel(phi, 3) = stoi(3); gel(phi, 6) = gen_m1; return phi; } static GEN phi2_w5w7_ZV(void) { GEN phi = zerovec(6); gel(phi, 3) = gen_1; gel(phi, 5) = gen_2; gel(phi, 6) = gen_m1; return phi; } static GEN phi2_w3w13_ZV(void) { GEN phi = zerovec(6); gel(phi, 3) = gen_m1; gel(phi, 5) = gen_2; gel(phi, 6) = gen_m1; return phi; } INLINE long modinv_parent(long inv) { switch (inv) { case INV_F2: case INV_F4: case INV_F8: return INV_F; case INV_W2W3E2: return INV_W2W3; case INV_W2W5E2: return INV_W2W5; case INV_W2W7E2: return INV_W2W7; case INV_W3W3E2: return INV_W3W3; default: pari_err_BUG("modinv_parent"); return -1;/*LCOV_EXCL_LINE*/ } } /* TODO: Think of a better name than "parent power"; sheesh. */ INLINE long modinv_parent_power(long inv) { switch (inv) { case INV_F4: return 4; case INV_F8: return 8; case INV_F2: case INV_W2W3E2: case INV_W2W5E2: case INV_W2W7E2: case INV_W3W3E2: return 2; default: pari_err_BUG("modinv_parent_power"); return -1;/*LCOV_EXCL_LINE*/ } } static GEN polmodular0_powerup_ZM(long L, long inv, GEN *db) { pari_sp ltop = avma, av; long s, D, nprimes, N; GEN mp, pol, P, H; long parent = modinv_parent(inv); long e = modinv_parent_power(inv); disc_info Ds[MODPOLY_MAX_DCNT]; /* FIXME: We throw away the table of fundamental discriminants here. */ long nDs = discriminant_with_classno_at_least(Ds, L, inv, NULL, IGNORE_SPARSE_FACTOR); if (nDs != 1) pari_err_BUG("polmodular0_powerup_ZM"); D = Ds[0].D1; nprimes = Ds[0].nprimes + 1; mp = polmodular0_ZM(L, parent, NULL, NULL, 0, db); H = polclass0(D, parent, 0, db); N = L + 2; if (degpol(H) < N) pari_err_BUG("polmodular0_powerup_ZM"); av = avma; pol = ZM_init_CRT(zero_Flm_copy(N, L + 2), 1); P = gen_1; for (s = 1; s < nprimes; ++s) { pari_sp av1, av2; ulong p = Ds[0].primes[s-1], pi = get_Fl_red(p); long i; GEN Hrts, js, Hp, Phip, coeff_mat, phi_modp; phi_modp = zero_Flm_copy(N, L + 2); av1 = avma; Hp = ZX_to_Flx(H, p); Hrts = Flx_roots_pre(Hp, p, pi); if (lg(Hrts)-1 < N) pari_err_BUG("polmodular0_powerup_ZM"); js = cgetg(N + 1, t_VECSMALL); for (i = 1; i <= N; ++i) uel(js, i) = Fl_powu_pre(uel(Hrts, i), e, p, pi); Phip = ZM_to_Flm(mp, p); coeff_mat = zero_Flm_copy(N, L + 2); av2 = avma; for (i = 1; i <= N; ++i) { long k; GEN phi_at_ji, mprts; phi_at_ji = Flm_Fl_polmodular_evalx(Phip, L, uel(Hrts, i), p, pi); mprts = Flx_roots_pre(phi_at_ji, p, pi); if (lg(mprts) != L + 2) pari_err_BUG("polmodular0_powerup_ZM"); Flv_powu_inplace_pre(mprts, e, p, pi); phi_at_ji = Flv_roots_to_pol(mprts, p, 0); for (k = 1; k <= L + 2; ++k) ucoeff(coeff_mat, i, k) = uel(phi_at_ji, k + 1); set_avma(av2); } interpolate_coeffs(phi_modp, p, js, coeff_mat); set_avma(av1); (void) ZM_incremental_CRT(&pol, phi_modp, &P, p); if (gc_needed(av, 2)) gerepileall(av, 2, &pol, &P); } killblock((GEN)Ds[0].primes); return gerepileupto(ltop, pol); } /* Returns the modular polynomial with the smallest level for the given * invariant, except if inv is INV_J, in which case return the modular * polynomial of level L in {2,3,5}. NULL is returned if the modular * polynomial can be calculated using polmodular0_powerup_ZM. */ INLINE GEN internal_db(long L, long inv) { switch (inv) { case INV_J: switch (L) { case 2: return phi2_ZV(); case 3: return phi3_ZV(); case 5: return phi5_ZV(); default: break; } case INV_F: return phi5_f_ZV(); case INV_F2: return NULL; case INV_F3: return phi3_f3_ZV(); case INV_F4: return NULL; case INV_G2: return phi2_g2_ZV(); case INV_W2W3: return phi5_w2w3_ZV(); case INV_F8: return NULL; case INV_W3W3: return phi5_w3w3_ZV(); case INV_W2W5: return phi7_w2w5_ZV(); case INV_W2W7: return phi3_w2w7_ZV(); case INV_W3W5: return phi2_w3w5_ZV(); case INV_W3W7: return phi5_w3w7_ZV(); case INV_W2W3E2: return NULL; case INV_W2W5E2: return NULL; case INV_W2W13: return phi3_w2w13_ZV(); case INV_W2W7E2: return NULL; case INV_W3W3E2: return phi2_w3w3e2_ZV(); case INV_W5W7: return phi2_w5w7_ZV(); case INV_W3W13: return phi2_w3w13_ZV(); } pari_err_BUG("internal_db"); return NULL;/*LCOV_EXCL_LINE*/ } /* NB: Should only be called if L <= modinv_max_internal_level(inv) */ static GEN polmodular_small_ZM(long L, long inv, GEN *db) { GEN f = internal_db(L, inv); if (!f) return polmodular0_powerup_ZM(L, inv, db); return sympol_to_ZM(f, L); } /* Each function phi_w?w?_j() returns a vector V containing two * vectors u and v, and a scalar k, which together represent the * bivariate polnomial * * phi(X, Y) = \sum_i u[i] X^i + Y \sum_i v[i] X^i + Y^2 X^k */ static GEN phi_w2w3_j(void) { GEN phi, phi0, phi1; phi = cgetg(4, t_VEC); phi0 = cgetg(14, t_VEC); gel(phi0, 1) = gen_1; gel(phi0, 2) = utoineg(0x3cUL); gel(phi0, 3) = utoi(0x702UL); gel(phi0, 4) = utoineg(0x797cUL); gel(phi0, 5) = utoi(0x5046fUL); gel(phi0, 6) = utoineg(0x1be0b8UL); gel(phi0, 7) = utoi(0x28ef9cUL); gel(phi0, 8) = utoi(0x15e2968UL); gel(phi0, 9) = utoi(0x1b8136fUL); gel(phi0, 10) = utoi(0xa67674UL); gel(phi0, 11) = utoi(0x23982UL); gel(phi0, 12) = utoi(0x294UL); gel(phi0, 13) = gen_1; phi1 = cgetg(13, t_VEC); gel(phi1, 1) = gen_0; gel(phi1, 2) = gen_0; gel(phi1, 3) = gen_m1; gel(phi1, 4) = utoi(0x23UL); gel(phi1, 5) = utoineg(0xaeUL); gel(phi1, 6) = utoineg(0x5b8UL); gel(phi1, 7) = utoi(0x12d7UL); gel(phi1, 8) = utoineg(0x7c86UL); gel(phi1, 9) = utoi(0x37c8UL); gel(phi1, 10) = utoineg(0x69cUL); gel(phi1, 11) = utoi(0x48UL); gel(phi1, 12) = gen_m1; gel(phi, 1) = phi0; gel(phi, 2) = phi1; gel(phi, 3) = utoi(5); return phi; } static GEN phi_w3w3_j(void) { GEN phi, phi0, phi1; phi = cgetg(4, t_VEC); phi0 = cgetg(14, t_VEC); gel(phi0, 1) = utoi(0x2d9UL); gel(phi0, 2) = utoi(0x4fbcUL); gel(phi0, 3) = utoi(0x5828aUL); gel(phi0, 4) = utoi(0x3a7a3cUL); gel(phi0, 5) = utoi(0x1bd8edfUL); gel(phi0, 6) = utoi(0x8348838UL); gel(phi0, 7) = utoi(0x1983f8acUL); gel(phi0, 8) = utoi(0x14e4e098UL); gel(phi0, 9) = utoi(0x69ed1a7UL); gel(phi0, 10) = utoi(0xc3828cUL); gel(phi0, 11) = utoi(0x2696aUL); gel(phi0, 12) = utoi(0x2acUL); gel(phi0, 13) = gen_1; phi1 = cgetg(13, t_VEC); gel(phi1, 1) = gen_0; gel(phi1, 2) = utoineg(0x1bUL); gel(phi1, 3) = utoineg(0x5d6UL); gel(phi1, 4) = utoineg(0x1c7bUL); gel(phi1, 5) = utoi(0x7980UL); gel(phi1, 6) = utoi(0x12168UL); gel(phi1, 7) = utoineg(0x3528UL); gel(phi1, 8) = utoineg(0x6174UL); gel(phi1, 9) = utoi(0x2208UL); gel(phi1, 10) = utoineg(0x41dUL); gel(phi1, 11) = utoi(0x36UL); gel(phi1, 12) = gen_m1; gel(phi, 1) = phi0; gel(phi, 2) = phi1; gel(phi, 3) = gen_2; return phi; } static GEN phi_w2w5_j(void) { GEN phi, phi0, phi1; phi = cgetg(4, t_VEC); phi0 = cgetg(20, t_VEC); gel(phi0, 1) = gen_1; gel(phi0, 2) = utoineg(0x2aUL); gel(phi0, 3) = utoi(0x549UL); gel(phi0, 4) = utoineg(0x6530UL); gel(phi0, 5) = utoi(0x60504UL); gel(phi0, 6) = utoineg(0x3cbbc8UL); gel(phi0, 7) = utoi(0x1d1ee74UL); gel(phi0, 8) = utoineg(0x7ef9ab0UL); gel(phi0, 9) = utoi(0x12b888beUL); gel(phi0, 10) = utoineg(0x15fa174cUL); gel(phi0, 11) = utoi(0x615d9feUL); gel(phi0, 12) = utoi(0xbeca070UL); gel(phi0, 13) = utoineg(0x88de74cUL); gel(phi0, 14) = utoineg(0x2b3a268UL); gel(phi0, 15) = utoi(0x24b3244UL); gel(phi0, 16) = utoi(0xb56270UL); gel(phi0, 17) = utoi(0x25989UL); gel(phi0, 18) = utoi(0x2a6UL); gel(phi0, 19) = gen_1; phi1 = cgetg(19, t_VEC); gel(phi1, 1) = gen_0; gel(phi1, 2) = gen_0; gel(phi1, 3) = gen_m1; gel(phi1, 4) = utoi(0x1eUL); gel(phi1, 5) = utoineg(0xffUL); gel(phi1, 6) = utoi(0x243UL); gel(phi1, 7) = utoineg(0xf3UL); gel(phi1, 8) = utoineg(0x5c4UL); gel(phi1, 9) = utoi(0x107bUL); gel(phi1, 10) = utoineg(0x11b2fUL); gel(phi1, 11) = utoi(0x48fa8UL); gel(phi1, 12) = utoineg(0x6ff7cUL); gel(phi1, 13) = utoi(0x4bf48UL); gel(phi1, 14) = utoineg(0x187efUL); gel(phi1, 15) = utoi(0x404cUL); gel(phi1, 16) = utoineg(0x582UL); gel(phi1, 17) = utoi(0x3cUL); gel(phi1, 18) = gen_m1; gel(phi, 1) = phi0; gel(phi, 2) = phi1; gel(phi, 3) = utoi(7); return phi; } static GEN phi_w2w7_j(void) { GEN phi, phi0, phi1; phi = cgetg(4, t_VEC); phi0 = cgetg(26, t_VEC); gel(phi0, 1) = gen_1; gel(phi0, 2) = utoineg(0x24UL); gel(phi0, 3) = utoi(0x4ceUL); gel(phi0, 4) = utoineg(0x5d60UL); gel(phi0, 5) = utoi(0x62b05UL); gel(phi0, 6) = utoineg(0x47be78UL); gel(phi0, 7) = utoi(0x2a3880aUL); gel(phi0, 8) = utoineg(0x114bccf4UL); gel(phi0, 9) = utoi(0x4b95e79aUL); gel(phi0, 10) = utoineg(0xe2cfee1cUL); gel(phi0, 11) = uu32toi(0x1UL, 0xe43d1126UL); gel(phi0, 12) = uu32toineg(0x2UL, 0xf04dc6f8UL); gel(phi0, 13) = uu32toi(0x3UL, 0x5384987dUL); gel(phi0, 14) = uu32toineg(0x2UL, 0xa5ccbe18UL); gel(phi0, 15) = uu32toi(0x1UL, 0x4c52c8a6UL); gel(phi0, 16) = utoineg(0x2643fdecUL); gel(phi0, 17) = utoineg(0x49f5ab66UL); gel(phi0, 18) = utoi(0x33074d3cUL); gel(phi0, 19) = utoineg(0x6a3e376UL); gel(phi0, 20) = utoineg(0x675aa58UL); gel(phi0, 21) = utoi(0x2674005UL); gel(phi0, 22) = utoi(0xba5be0UL); gel(phi0, 23) = utoi(0x2644eUL); gel(phi0, 24) = utoi(0x2acUL); gel(phi0, 25) = gen_1; phi1 = cgetg(25, t_VEC); gel(phi1, 1) = gen_0; gel(phi1, 2) = gen_0; gel(phi1, 3) = gen_m1; gel(phi1, 4) = utoi(0x1cUL); gel(phi1, 5) = utoineg(0x10aUL); gel(phi1, 6) = utoi(0x3f0UL); gel(phi1, 7) = utoineg(0x5d3UL); gel(phi1, 8) = utoi(0x3efUL); gel(phi1, 9) = utoineg(0x102UL); gel(phi1, 10) = utoineg(0x5c8UL); gel(phi1, 11) = utoi(0x102fUL); gel(phi1, 12) = utoineg(0x13f8aUL); gel(phi1, 13) = utoi(0x86538UL); gel(phi1, 14) = utoineg(0x1bbd10UL); gel(phi1, 15) = utoi(0x3614e8UL); gel(phi1, 16) = utoineg(0x42f793UL); gel(phi1, 17) = utoi(0x364698UL); gel(phi1, 18) = utoineg(0x1c7a10UL); gel(phi1, 19) = utoi(0x97cc8UL); gel(phi1, 20) = utoineg(0x1fc8aUL); gel(phi1, 21) = utoi(0x4210UL); gel(phi1, 22) = utoineg(0x524UL); gel(phi1, 23) = utoi(0x38UL); gel(phi1, 24) = gen_m1; gel(phi, 1) = phi0; gel(phi, 2) = phi1; gel(phi, 3) = utoi(9); return phi; } static GEN phi_w2w13_j(void) { GEN phi, phi0, phi1; phi = cgetg(4, t_VEC); phi0 = cgetg(44, t_VEC); gel(phi0, 1) = gen_1; gel(phi0, 2) = utoineg(0x1eUL); gel(phi0, 3) = utoi(0x45fUL); gel(phi0, 4) = utoineg(0x5590UL); gel(phi0, 5) = utoi(0x64407UL); gel(phi0, 6) = utoineg(0x53a792UL); gel(phi0, 7) = utoi(0x3b21af3UL); gel(phi0, 8) = utoineg(0x20d056d0UL); gel(phi0, 9) = utoi(0xe02db4a6UL); gel(phi0, 10) = uu32toineg(0x4UL, 0xb23400b0UL); gel(phi0, 11) = uu32toi(0x14UL, 0x57fbb906UL); gel(phi0, 12) = uu32toineg(0x49UL, 0xcf80c00UL); gel(phi0, 13) = uu32toi(0xdeUL, 0x84ff421UL); gel(phi0, 14) = uu32toineg(0x244UL, 0xc500c156UL); gel(phi0, 15) = uu32toi(0x52cUL, 0x79162979UL); gel(phi0, 16) = uu32toineg(0xa64UL, 0x8edc5650UL); gel(phi0, 17) = uu32toi(0x1289UL, 0x4225bb41UL); gel(phi0, 18) = uu32toineg(0x1d89UL, 0x2a15229aUL); gel(phi0, 19) = uu32toi(0x2a3eUL, 0x4539f1ebUL); gel(phi0, 20) = uu32toineg(0x366aUL, 0xa5ea1130UL); gel(phi0, 21) = uu32toi(0x3f47UL, 0xa19fecb4UL); gel(phi0, 22) = uu32toineg(0x4282UL, 0x91a3c4a0UL); gel(phi0, 23) = uu32toi(0x3f30UL, 0xbaa305b4UL); gel(phi0, 24) = uu32toineg(0x3635UL, 0xd11c2530UL); gel(phi0, 25) = uu32toi(0x29e2UL, 0x89df27ebUL); gel(phi0, 26) = uu32toineg(0x1d03UL, 0x6509d48aUL); gel(phi0, 27) = uu32toi(0x11e2UL, 0x272cc601UL); gel(phi0, 28) = uu32toineg(0x9b0UL, 0xacd58ff0UL); gel(phi0, 29) = uu32toi(0x485UL, 0x608d7db9UL); gel(phi0, 30) = uu32toineg(0x1bfUL, 0xa941546UL); gel(phi0, 31) = uu32toi(0x82UL, 0x56e48b21UL); gel(phi0, 32) = uu32toineg(0x13UL, 0xc36b2340UL); gel(phi0, 33) = uu32toineg(0x5UL, 0x6637257aUL); gel(phi0, 34) = uu32toi(0x5UL, 0x40f70bd0UL); gel(phi0, 35) = uu32toineg(0x1UL, 0xf70842daUL); gel(phi0, 36) = utoi(0x53eea5f0UL); gel(phi0, 37) = utoi(0xda17bf3UL); gel(phi0, 38) = utoineg(0xaf246c2UL); gel(phi0, 39) = utoi(0x278f847UL); gel(phi0, 40) = utoi(0xbf5550UL); gel(phi0, 41) = utoi(0x26f1fUL); gel(phi0, 42) = utoi(0x2b2UL); gel(phi0, 43) = gen_1; phi1 = cgetg(43, t_VEC); gel(phi1, 1) = gen_0; gel(phi1, 2) = gen_0; gel(phi1, 3) = gen_m1; gel(phi1, 4) = utoi(0x1aUL); gel(phi1, 5) = utoineg(0x111UL); gel(phi1, 6) = utoi(0x5e4UL); gel(phi1, 7) = utoineg(0x1318UL); gel(phi1, 8) = utoi(0x2804UL); gel(phi1, 9) = utoineg(0x3cd6UL); gel(phi1, 10) = utoi(0x467cUL); gel(phi1, 11) = utoineg(0x3cd6UL); gel(phi1, 12) = utoi(0x2804UL); gel(phi1, 13) = utoineg(0x1318UL); gel(phi1, 14) = utoi(0x5e3UL); gel(phi1, 15) = utoineg(0x10dUL); gel(phi1, 16) = utoineg(0x5ccUL); gel(phi1, 17) = utoi(0x100bUL); gel(phi1, 18) = utoineg(0x160e1UL); gel(phi1, 19) = utoi(0xd2cb0UL); gel(phi1, 20) = utoineg(0x4c85fcUL); gel(phi1, 21) = utoi(0x137cb98UL); gel(phi1, 22) = utoineg(0x3c75568UL); gel(phi1, 23) = utoi(0x95c69c8UL); gel(phi1, 24) = utoineg(0x131557bcUL); gel(phi1, 25) = utoi(0x20aacfd0UL); gel(phi1, 26) = utoineg(0x2f9164e6UL); gel(phi1, 27) = utoi(0x3b6a5e40UL); gel(phi1, 28) = utoineg(0x3ff54344UL); gel(phi1, 29) = utoi(0x3b6a9140UL); gel(phi1, 30) = utoineg(0x2f927fa6UL); gel(phi1, 31) = utoi(0x20ae6450UL); gel(phi1, 32) = utoineg(0x131cd87cUL); gel(phi1, 33) = utoi(0x967d1e8UL); gel(phi1, 34) = utoineg(0x3d48ca8UL); gel(phi1, 35) = utoi(0x14333b8UL); gel(phi1, 36) = utoineg(0x5406bcUL); gel(phi1, 37) = utoi(0x10c130UL); gel(phi1, 38) = utoineg(0x27ba1UL); gel(phi1, 39) = utoi(0x433cUL); gel(phi1, 40) = utoineg(0x4c6UL); gel(phi1, 41) = utoi(0x34UL); gel(phi1, 42) = gen_m1; gel(phi, 1) = phi0; gel(phi, 2) = phi1; gel(phi, 3) = utoi(15); return phi; } static GEN phi_w3w5_j(void) { GEN phi, phi0, phi1; phi = cgetg(4, t_VEC); phi0 = cgetg(26, t_VEC); gel(phi0, 1) = gen_1; gel(phi0, 2) = utoi(0x18UL); gel(phi0, 3) = utoi(0xb4UL); gel(phi0, 4) = utoineg(0x178UL); gel(phi0, 5) = utoineg(0x2d7eUL); gel(phi0, 6) = utoineg(0x89b8UL); gel(phi0, 7) = utoi(0x35c24UL); gel(phi0, 8) = utoi(0x128a18UL); gel(phi0, 9) = utoineg(0x12a911UL); gel(phi0, 10) = utoineg(0xcc0190UL); gel(phi0, 11) = utoi(0x94368UL); gel(phi0, 12) = utoi(0x1439d0UL); gel(phi0, 13) = utoi(0x96f931cUL); gel(phi0, 14) = utoineg(0x1f59ff0UL); gel(phi0, 15) = utoi(0x20e7e8UL); gel(phi0, 16) = utoineg(0x25fdf150UL); gel(phi0, 17) = utoineg(0x7091511UL); gel(phi0, 18) = utoi(0x1ef52f8UL); gel(phi0, 19) = utoi(0x341f2de4UL); gel(phi0, 20) = utoi(0x25d72c28UL); gel(phi0, 21) = utoi(0x95d2082UL); gel(phi0, 22) = utoi(0xd2d828UL); gel(phi0, 23) = utoi(0x281f4UL); gel(phi0, 24) = utoi(0x2b8UL); gel(phi0, 25) = gen_1; phi1 = cgetg(25, t_VEC); gel(phi1, 1) = gen_0; gel(phi1, 2) = gen_0; gel(phi1, 3) = gen_0; gel(phi1, 4) = gen_1; gel(phi1, 5) = utoi(0xfUL); gel(phi1, 6) = utoi(0x2eUL); gel(phi1, 7) = utoineg(0x1fUL); gel(phi1, 8) = utoineg(0x2dUL); gel(phi1, 9) = utoineg(0x5caUL); gel(phi1, 10) = utoineg(0x358UL); gel(phi1, 11) = utoi(0x2f1cUL); gel(phi1, 12) = utoi(0xd8eaUL); gel(phi1, 13) = utoineg(0x38c70UL); gel(phi1, 14) = utoineg(0x1a964UL); gel(phi1, 15) = utoi(0x93512UL); gel(phi1, 16) = utoineg(0x58f2UL); gel(phi1, 17) = utoineg(0x5af1eUL); gel(phi1, 18) = utoi(0x1afb8UL); gel(phi1, 19) = utoi(0xc084UL); gel(phi1, 20) = utoineg(0x7fcbUL); gel(phi1, 21) = utoi(0x1c89UL); gel(phi1, 22) = utoineg(0x32aUL); gel(phi1, 23) = utoi(0x2dUL); gel(phi1, 24) = gen_m1; gel(phi, 1) = phi0; gel(phi, 2) = phi1; gel(phi, 3) = utoi(8); return phi; } static GEN phi_w3w7_j(void) { GEN phi, phi0, phi1; phi = cgetg(4, t_VEC); phi0 = cgetg(34, t_VEC); gel(phi0, 1) = gen_1; gel(phi0, 2) = utoineg(0x14UL); gel(phi0, 3) = utoi(0x82UL); gel(phi0, 4) = utoi(0x1f8UL); gel(phi0, 5) = utoineg(0x2a45UL); gel(phi0, 6) = utoi(0x9300UL); gel(phi0, 7) = utoi(0x32abeUL); gel(phi0, 8) = utoineg(0x19c91cUL); gel(phi0, 9) = utoi(0xc1ba9UL); gel(phi0, 10) = utoi(0x1788f68UL); gel(phi0, 11) = utoineg(0x2b1989cUL); gel(phi0, 12) = utoineg(0x7a92408UL); gel(phi0, 13) = utoi(0x1238d56eUL); gel(phi0, 14) = utoi(0x13dd66a0UL); gel(phi0, 15) = utoineg(0x2dbedca8UL); gel(phi0, 16) = utoineg(0x34282eb8UL); gel(phi0, 17) = utoi(0x2c2a54d2UL); gel(phi0, 18) = utoi(0x98db81a8UL); gel(phi0, 19) = utoineg(0x4088be8UL); gel(phi0, 20) = utoineg(0xe424a220UL); gel(phi0, 21) = utoineg(0x67bbb232UL); gel(phi0, 22) = utoi(0x7dd8bb98UL); gel(phi0, 23) = uu32toi(0x1UL, 0xcaff744UL); gel(phi0, 24) = utoineg(0x1d46a378UL); gel(phi0, 25) = utoineg(0x82fa50f7UL); gel(phi0, 26) = utoineg(0x700ef38cUL); gel(phi0, 27) = utoi(0x20aa202eUL); gel(phi0, 28) = utoi(0x299b3440UL); gel(phi0, 29) = utoi(0xa476c4bUL); gel(phi0, 30) = utoi(0xd80558UL); gel(phi0, 31) = utoi(0x28a32UL); gel(phi0, 32) = utoi(0x2bcUL); gel(phi0, 33) = gen_1; phi1 = cgetg(33, t_VEC); gel(phi1, 1) = gen_0; gel(phi1, 2) = gen_0; gel(phi1, 3) = gen_0; gel(phi1, 4) = gen_m1; gel(phi1, 5) = utoi(0xeUL); gel(phi1, 6) = utoineg(0x31UL); gel(phi1, 7) = utoineg(0xeUL); gel(phi1, 8) = utoi(0x99UL); gel(phi1, 9) = utoineg(0x8UL); gel(phi1, 10) = utoineg(0x2eUL); gel(phi1, 11) = utoineg(0x5ccUL); gel(phi1, 12) = utoi(0x308UL); gel(phi1, 13) = utoi(0x2904UL); gel(phi1, 14) = utoineg(0x15700UL); gel(phi1, 15) = utoineg(0x2b9ecUL); gel(phi1, 16) = utoi(0xf0966UL); gel(phi1, 17) = utoi(0xb3cc8UL); gel(phi1, 18) = utoineg(0x38241cUL); gel(phi1, 19) = utoineg(0x8604cUL); gel(phi1, 20) = utoi(0x578a64UL); gel(phi1, 21) = utoineg(0x11a798UL); gel(phi1, 22) = utoineg(0x39c85eUL); gel(phi1, 23) = utoi(0x1a5084UL); gel(phi1, 24) = utoi(0xcdeb4UL); gel(phi1, 25) = utoineg(0xb0364UL); gel(phi1, 26) = utoi(0x129d4UL); gel(phi1, 27) = utoi(0x126fcUL); gel(phi1, 28) = utoineg(0x8649UL); gel(phi1, 29) = utoi(0x1aa2UL); gel(phi1, 30) = utoineg(0x2dfUL); gel(phi1, 31) = utoi(0x2aUL); gel(phi1, 32) = gen_m1; gel(phi, 1) = phi0; gel(phi, 2) = phi1; gel(phi, 3) = utoi(10); return phi; } static GEN phi_w3w13_j(void) { GEN phi, phi0, phi1; phi = cgetg(4, t_VEC); phi0 = cgetg(58, t_VEC); gel(phi0, 1) = gen_1; gel(phi0, 2) = utoineg(0x10UL); gel(phi0, 3) = utoi(0x58UL); gel(phi0, 4) = utoi(0x258UL); gel(phi0, 5) = utoineg(0x270cUL); gel(phi0, 6) = utoi(0x9c00UL); gel(phi0, 7) = utoi(0x2b40cUL); gel(phi0, 8) = utoineg(0x20e250UL); gel(phi0, 9) = utoi(0x4f46baUL); gel(phi0, 10) = utoi(0x1869448UL); gel(phi0, 11) = utoineg(0xa49ab68UL); gel(phi0, 12) = utoi(0x96c7630UL); gel(phi0, 13) = utoi(0x4f7e0af6UL); gel(phi0, 14) = utoineg(0xea093590UL); gel(phi0, 15) = utoineg(0x6735bc50UL); gel(phi0, 16) = uu32toi(0x5UL, 0x971a2e08UL); gel(phi0, 17) = uu32toineg(0x6UL, 0x29c9d965UL); gel(phi0, 18) = uu32toineg(0xdUL, 0xeb9aa360UL); gel(phi0, 19) = uu32toi(0x26UL, 0xe9c0584UL); gel(phi0, 20) = uu32toineg(0x1UL, 0xb0cadce8UL); gel(phi0, 21) = uu32toineg(0x62UL, 0x73586014UL); gel(phi0, 22) = uu32toi(0x66UL, 0xaf672e38UL); gel(phi0, 23) = uu32toi(0x6bUL, 0x93c28cdcUL); gel(phi0, 24) = uu32toineg(0x11eUL, 0x4f633080UL); gel(phi0, 25) = uu32toi(0x3cUL, 0xcc42461bUL); gel(phi0, 26) = uu32toi(0x17bUL, 0xdec0a78UL); gel(phi0, 27) = uu32toineg(0x166UL, 0x910d8bd0UL); gel(phi0, 28) = uu32toineg(0xd4UL, 0x47873030UL); gel(phi0, 29) = uu32toi(0x204UL, 0x811828baUL); gel(phi0, 30) = uu32toineg(0x50UL, 0x5d713960UL); gel(phi0, 31) = uu32toineg(0x198UL, 0xa27e42b0UL); gel(phi0, 32) = uu32toi(0xe1UL, 0x25685138UL); gel(phi0, 33) = uu32toi(0xe3UL, 0xaa5774bbUL); gel(phi0, 34) = uu32toineg(0xcfUL, 0x392a9a00UL); gel(phi0, 35) = uu32toineg(0x81UL, 0xfb334d04UL); gel(phi0, 36) = uu32toi(0xabUL, 0x59594a68UL); gel(phi0, 37) = uu32toi(0x42UL, 0x356993acUL); gel(phi0, 38) = uu32toineg(0x86UL, 0x307ba678UL); gel(phi0, 39) = uu32toineg(0xbUL, 0x7a9e59dcUL); gel(phi0, 40) = uu32toi(0x4cUL, 0x27935f20UL); gel(phi0, 41) = uu32toineg(0x2UL, 0xe0ac9045UL); gel(phi0, 42) = uu32toineg(0x24UL, 0x14495758UL); gel(phi0, 43) = utoi(0x20973410UL); gel(phi0, 44) = uu32toi(0x13UL, 0x99ff4e00UL); gel(phi0, 45) = uu32toineg(0x1UL, 0xa710d34aUL); gel(phi0, 46) = uu32toineg(0x7UL, 0xfe5405c0UL); gel(phi0, 47) = uu32toi(0x1UL, 0xcdee0f8UL); gel(phi0, 48) = uu32toi(0x2UL, 0x660c92a8UL); gel(phi0, 49) = utoi(0x3f13a35aUL); gel(phi0, 50) = utoineg(0xe4eb4ba0UL); gel(phi0, 51) = utoineg(0x6420f4UL); gel(phi0, 52) = utoi(0x2c624370UL); gel(phi0, 53) = utoi(0xb31b814UL); gel(phi0, 54) = utoi(0xdd3ad8UL); gel(phi0, 55) = utoi(0x29278UL); gel(phi0, 56) = utoi(0x2c0UL); gel(phi0, 57) = gen_1; phi1 = cgetg(57, t_VEC); gel(phi1, 1) = gen_0; gel(phi1, 2) = gen_0; gel(phi1, 3) = gen_0; gel(phi1, 4) = gen_m1; gel(phi1, 5) = utoi(0xdUL); gel(phi1, 6) = utoineg(0x34UL); gel(phi1, 7) = utoi(0x1aUL); gel(phi1, 8) = utoi(0xf7UL); gel(phi1, 9) = utoineg(0x16cUL); gel(phi1, 10) = utoineg(0xddUL); gel(phi1, 11) = utoi(0x28aUL); gel(phi1, 12) = utoineg(0xddUL); gel(phi1, 13) = utoineg(0x16cUL); gel(phi1, 14) = utoi(0xf6UL); gel(phi1, 15) = utoi(0x1dUL); gel(phi1, 16) = utoineg(0x31UL); gel(phi1, 17) = utoineg(0x5ceUL); gel(phi1, 18) = utoi(0x2e4UL); gel(phi1, 19) = utoi(0x252cUL); gel(phi1, 20) = utoineg(0x1b34cUL); gel(phi1, 21) = utoi(0xaf80UL); gel(phi1, 22) = utoi(0x1cc5f9UL); gel(phi1, 23) = utoineg(0x3e1aa5UL); gel(phi1, 24) = utoineg(0x86d17aUL); gel(phi1, 25) = utoi(0x2427264UL); gel(phi1, 26) = utoineg(0x691c1fUL); gel(phi1, 27) = utoineg(0x862ad4eUL); gel(phi1, 28) = utoi(0xab21e1fUL); gel(phi1, 29) = utoi(0xbc19ddcUL); gel(phi1, 30) = utoineg(0x24331db8UL); gel(phi1, 31) = utoi(0x972c105UL); gel(phi1, 32) = utoi(0x363d7107UL); gel(phi1, 33) = utoineg(0x39696450UL); gel(phi1, 34) = utoineg(0x1bce7c48UL); gel(phi1, 35) = utoi(0x552ecba0UL); gel(phi1, 36) = utoineg(0x1c7771b8UL); gel(phi1, 37) = utoineg(0x393029b8UL); gel(phi1, 38) = utoi(0x3755be97UL); gel(phi1, 39) = utoi(0x83402a9UL); gel(phi1, 40) = utoineg(0x24d5be62UL); gel(phi1, 41) = utoi(0xdb6d90aUL); gel(phi1, 42) = utoi(0xa0ef177UL); gel(phi1, 43) = utoineg(0x99ff162UL); gel(phi1, 44) = utoi(0xb09e27UL); gel(phi1, 45) = utoi(0x26a7adcUL); gel(phi1, 46) = utoineg(0x116e2fcUL); gel(phi1, 47) = utoineg(0x1383b5UL); gel(phi1, 48) = utoi(0x35a9e7UL); gel(phi1, 49) = utoineg(0x1082a0UL); gel(phi1, 50) = utoineg(0x4696UL); gel(phi1, 51) = utoi(0x19f98UL); gel(phi1, 52) = utoineg(0x8bb3UL); gel(phi1, 53) = utoi(0x18bbUL); gel(phi1, 54) = utoineg(0x297UL); gel(phi1, 55) = utoi(0x27UL); gel(phi1, 56) = gen_m1; gel(phi, 1) = phi0; gel(phi, 2) = phi1; gel(phi, 3) = utoi(16); return phi; } static GEN phi_w5w7_j(void) { GEN phi, phi0, phi1; phi = cgetg(4, t_VEC); phi0 = cgetg(50, t_VEC); gel(phi0, 1) = gen_1; gel(phi0, 2) = utoi(0xcUL); gel(phi0, 3) = utoi(0x2aUL); gel(phi0, 4) = utoi(0x10UL); gel(phi0, 5) = utoineg(0x69UL); gel(phi0, 6) = utoineg(0x318UL); gel(phi0, 7) = utoineg(0x148aUL); gel(phi0, 8) = utoineg(0x17c4UL); gel(phi0, 9) = utoi(0x1a73UL); gel(phi0, 10) = gen_0; gel(phi0, 11) = utoi(0x338a0UL); gel(phi0, 12) = utoi(0x61698UL); gel(phi0, 13) = utoineg(0x96e8UL); gel(phi0, 14) = utoi(0x140910UL); gel(phi0, 15) = utoineg(0x45f6b4UL); gel(phi0, 16) = utoineg(0x309f50UL); gel(phi0, 17) = utoineg(0xef9f8bUL); gel(phi0, 18) = utoineg(0x283167cUL); gel(phi0, 19) = utoi(0x625e20aUL); gel(phi0, 20) = utoineg(0x16186350UL); gel(phi0, 21) = utoi(0x46861281UL); gel(phi0, 22) = utoineg(0x754b96a0UL); gel(phi0, 23) = uu32toi(0x1UL, 0x421ca02aUL); gel(phi0, 24) = uu32toineg(0x2UL, 0xdb76a5cUL); gel(phi0, 25) = uu32toi(0x4UL, 0xf6afd8eUL); gel(phi0, 26) = uu32toineg(0x6UL, 0xaafd3cb4UL); gel(phi0, 27) = uu32toi(0x8UL, 0xda2539caUL); gel(phi0, 28) = uu32toineg(0xfUL, 0x84343790UL); gel(phi0, 29) = uu32toi(0xfUL, 0x914ff421UL); gel(phi0, 30) = uu32toineg(0x19UL, 0x3c123950UL); gel(phi0, 31) = uu32toi(0x15UL, 0x381f722aUL); gel(phi0, 32) = uu32toineg(0x15UL, 0xe01c0c24UL); gel(phi0, 33) = uu32toi(0x19UL, 0x3360b375UL); gel(phi0, 34) = utoineg(0x59fda9c0UL); gel(phi0, 35) = uu32toi(0x20UL, 0xff55024cUL); gel(phi0, 36) = uu32toi(0x16UL, 0xcc600800UL); gel(phi0, 37) = uu32toi(0x24UL, 0x1879c898UL); gel(phi0, 38) = uu32toi(0x1cUL, 0x37f97498UL); gel(phi0, 39) = uu32toi(0x19UL, 0x39ec4b60UL); gel(phi0, 40) = uu32toi(0x10UL, 0x52c660d0UL); gel(phi0, 41) = uu32toi(0x9UL, 0xcab00333UL); gel(phi0, 42) = uu32toi(0x4UL, 0x7fe69be4UL); gel(phi0, 43) = uu32toi(0x1UL, 0xa0c6f116UL); gel(phi0, 44) = utoi(0x69244638UL); gel(phi0, 45) = utoi(0xed560f7UL); gel(phi0, 46) = utoi(0xe7b660UL); gel(phi0, 47) = utoi(0x29d8aUL); gel(phi0, 48) = utoi(0x2c4UL); gel(phi0, 49) = gen_1; phi1 = cgetg(49, t_VEC); gel(phi1, 1) = gen_0; gel(phi1, 2) = gen_0; gel(phi1, 3) = gen_0; gel(phi1, 4) = gen_0; gel(phi1, 5) = gen_0; gel(phi1, 6) = gen_1; gel(phi1, 7) = utoi(0x7UL); gel(phi1, 8) = utoi(0x8UL); gel(phi1, 9) = utoineg(0x9UL); gel(phi1, 10) = gen_0; gel(phi1, 11) = utoineg(0x13UL); gel(phi1, 12) = utoineg(0x7UL); gel(phi1, 13) = utoineg(0x5ceUL); gel(phi1, 14) = utoineg(0xb0UL); gel(phi1, 15) = utoi(0x460UL); gel(phi1, 16) = utoineg(0x194bUL); gel(phi1, 17) = utoi(0x87c3UL); gel(phi1, 18) = utoi(0x3cdeUL); gel(phi1, 19) = utoineg(0xd683UL); gel(phi1, 20) = utoi(0x6099bUL); gel(phi1, 21) = utoineg(0x111ea8UL); gel(phi1, 22) = utoi(0xfa113UL); gel(phi1, 23) = utoineg(0x1a6561UL); gel(phi1, 24) = utoineg(0x1e997UL); gel(phi1, 25) = utoi(0x214e54UL); gel(phi1, 26) = utoineg(0x29c3f4UL); gel(phi1, 27) = utoi(0x67e102UL); gel(phi1, 28) = utoineg(0x227eaaUL); gel(phi1, 29) = utoi(0x191d10UL); gel(phi1, 30) = utoi(0x1a9cd5UL); gel(phi1, 31) = utoineg(0x58386fUL); gel(phi1, 32) = utoi(0x2e49f6UL); gel(phi1, 33) = utoineg(0x31194bUL); gel(phi1, 34) = utoi(0x9e07aUL); gel(phi1, 35) = utoi(0x260d59UL); gel(phi1, 36) = utoineg(0x189921UL); gel(phi1, 37) = utoi(0xeca4aUL); gel(phi1, 38) = utoineg(0xa3d9cUL); gel(phi1, 39) = utoineg(0x426daUL); gel(phi1, 40) = utoi(0x91875UL); gel(phi1, 41) = utoineg(0x3b55bUL); gel(phi1, 42) = utoineg(0x56f4UL); gel(phi1, 43) = utoi(0xcd1bUL); gel(phi1, 44) = utoineg(0x5159UL); gel(phi1, 45) = utoi(0x10f4UL); gel(phi1, 46) = utoineg(0x20dUL); gel(phi1, 47) = utoi(0x23UL); gel(phi1, 48) = gen_m1; gel(phi, 1) = phi0; gel(phi, 2) = phi1; gel(phi, 3) = utoi(12); return phi; } GEN double_eta_raw(long inv) { switch (inv) { case INV_W2W3: case INV_W2W3E2: return phi_w2w3_j(); case INV_W3W3: case INV_W3W3E2: return phi_w3w3_j(); case INV_W2W5: case INV_W2W5E2: return phi_w2w5_j(); case INV_W2W7: case INV_W2W7E2: return phi_w2w7_j(); case INV_W3W5: return phi_w3w5_j(); case INV_W3W7: return phi_w3w7_j(); case INV_W2W13: return phi_w2w13_j(); case INV_W3W13: return phi_w3w13_j(); case INV_W5W7: return phi_w5w7_j(); default: pari_err_BUG("double_eta_raw"); return NULL;/*LCOV_EXCL_LINE*/ } } /* SECTION: Select discriminant for given modpoly level. */ /* require an L1, useful for multi-threading */ #define MODPOLY_USE_L1 1 /* no bound on L1 other than the fixed bound MAX_L1 - needed to * handle small L for certain invariants (but not for j) */ #define MODPOLY_NO_MAX_L1 2 /* don't use any auxilliary primes - needed to handle small L for * certain invariants (but not for j) */ #define MODPOLY_NO_AUX_L 4 #define MODPOLY_IGNORE_SPARSE_FACTOR 8 INLINE double modpoly_height_bound(long L, long inv) { double nbits, nbits2; double c; long hf; /* proven bound (in bits), derived from: 6l*log(l)+16*l+13*sqrt(l)*log(l) */ nbits = 6.0*L*log2(L)+16/M_LN2*L+8.0*sqrt((double)L)*log2(L); /* alternative proven bound (in bits), derived from: 6l*log(l)+17*l */ nbits2 = 6.0*L*log2(L)+17/M_LN2*L; if ( nbits2 < nbits ) nbits = nbits2; hf = modinv_height_factor(inv); if (hf > 1) { /* IMPORTANT: when dividing by the height factor, we only want to reduce terms related to the bound on j (the roots of Phi_l(X,y)), not terms arising from binomial coefficients. These arise in lemmas 2 and 3 of the height bound paper, terms of (log 2)*L and 2.085*(L+1) which we convert here to binary logs */ /* Massive overestimate: if you care about speed, determine a good height * bound empirically as done for INV_F below */ nbits2 = nbits - 4.01*L -3.0; nbits = nbits2/hf + 4.01*L + 3.0; } if (inv == INV_F) { if (L < 30) c = 45; else if (L < 100) c = 36; else if (L < 300) c = 32; else if (L < 600) c = 26; else if (L < 1200) c = 24; else if (L < 2400) c = 22; else c = 20; nbits = (6.0*L*log2(L) + c*L)/hf; } return nbits; } /* small enough to write the factorization of a smooth in a BIL bit integer */ #define SMOOTH_PRIMES ((BITS_IN_LONG >> 1) - 1) #define MAX_ATKIN 255 /* Must have primes at least up to MAX_ATKIN */ static const long PRIMES[] = { 0, 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, 239, 241, 251, 257, 263, 269, 271, 277 }; #define MAX_L1 255 typedef struct D_entry_struct { ulong m; long D, h; } D_entry; /* Returns a form that generates the classes of norm p^2 in cl(p^2D) * (i.e. one with order p-1), where p is an odd prime that splits in D * and does not divide its conductor (but this is not verified) */ INLINE GEN qform_primeform2(long p, long D) { GEN a = sqru(p), Dp2 = mulis(a, D), M = Z_factor(utoipos(p - 1)); pari_sp av = avma; long k; for (k = D & 1; k <= p; k += 2) { long ord, c = (k * k - D) / 4; GEN Q, q; if (!(c % p)) continue; q = mkqfis(a, k * p, c, Dp2); Q = qfbred_i(q); /* TODO: How do we know that Q has order dividing p - 1? If we don't, then * the call to gen_order should be replaced with a call to something with * fastorder semantics (i.e. return 0 if ord(Q) \ndiv M). */ ord = itos(qfi_order(Q, M)); if (ord == p - 1) { /* TODO: This check that gen_order returned the correct result should be * removed when gen_order is replaced with fastorder semantics. */ if (qfb_equal1(gpowgs(Q, p - 1))) return q; break; } set_avma(av); } return NULL; } /* Let n = #cl(D); return x such that [L0]^x = [L] in cl(D), or -1 if x was * not found */ INLINE long primeform_discrete_log(long L0, long L, long n, long D) { pari_sp av = avma; GEN X, Q, R, DD = stoi(D); Q = primeform_u(DD, L0); R = primeform_u(DD, L); X = qfi_Shanks(R, Q, n); return gc_long(av, X? itos(X): -1); } /* Return the norm of a class group generator appropriate for a discriminant * that will be used to calculate the modular polynomial of level L and * invariant inv. Don't consider norms less than initial_L0 */ static long select_L0(long L, long inv, long initial_L0) { long L0, modinv_N = modinv_level(inv); if (modinv_N % L == 0) pari_err_BUG("select_L0"); /* TODO: Clean up these anomolous L0 choices */ /* I've no idea why the discriminant-finding code fails with L0=5 * when L=19 and L=29, nor why L0=7 and L0=11 don't work for L=19 * either, nor why this happens for the otherwise unrelated * invariants Weber-f and (2,3) double-eta. */ if (inv == INV_W3W3E2 && L == 5) return 2; if (inv == INV_F || inv == INV_F2 || inv == INV_F4 || inv == INV_F8 || inv == INV_W2W3 || inv == INV_W2W3E2 || inv == INV_W3W3 /* || inv == INV_W3W3E2 */) { if (L == 19) return 13; else if (L == 29 || L == 5) return 7; return 5; } if ((inv == INV_W2W5 || inv == INV_W2W5E2) && (L == 7 || L == 19)) return 13; if ((inv == INV_W2W7 || inv == INV_W2W7E2) && L == 11) return 13; if (inv == INV_W3W5) { if (L == 7) return 13; else if (L == 17) return 7; } if (inv == INV_W3W7) { if (L == 29 || L == 101) return 11; if (L == 11 || L == 19) return 13; } if (inv == INV_W5W7 && L == 17) return 3; /* L0 = smallest small prime different from L that doesn't divide modinv_N */ for (L0 = unextprime(initial_L0 + 1); L0 == L || modinv_N % L0 == 0; L0 = unextprime(L0 + 1)) ; return L0; } /* Return the order of [L]^n in cl(D), where #cl(D) = ord. */ INLINE long primeform_exp_order(long L, long n, long D, long ord) { pari_sp av = avma; GEN Q = gpowgs(primeform_u(stoi(D), L), n); long m = itos(qfi_order(Q, Z_factor(stoi(ord)))); return gc_long(av,m); } /* If an ideal of norm modinv_deg is equivalent to an ideal of norm L0, we * have an orientation ambiguity that we need to avoid. Note that we need to * check all the possibilities (up to 8), but we can cheaply check inverses * (so at most 2) */ static long orientation_ambiguity(long D1, long L0, long modinv_p1, long modinv_p2, long modinv_N) { pari_sp av = avma; long ambiguity = 0; GEN D = stoi(D1), Q1 = primeform_u(D, modinv_p1), Q2 = NULL; if (modinv_p2 > 1) { if (modinv_p1 == modinv_p2) Q1 = gsqr(Q1); else { GEN P2 = primeform_u(D, modinv_p2); GEN Q = gsqr(P2), R = gsqr(Q1); /* check that p1^2 != p2^{+/-2}, since this leads to * ambiguities when converting j's to f's */ if (equalii(gel(Q,1), gel(R,1)) && absequalii(gel(Q,2), gel(R,2))) { dbg_printf(3)("Bad D=%ld, a^2=b^2 problem between modinv_p1=%ld and modinv_p2=%ld\n", D1, modinv_p1, modinv_p2); ambiguity = 1; } else { /* generate both p1*p2 and p1*p2^{-1} */ Q2 = gmul(Q1, P2); P2 = ginv(P2); Q1 = gmul(Q1, P2); } } } if (!ambiguity) { GEN P = gsqr(primeform_u(D, L0)); if (equalii(gel(P,1), gel(Q1,1)) || (modinv_p2 && modinv_p1 != modinv_p2 && equalii(gel(P,1), gel(Q2,1)))) { dbg_printf(3)("Bad D=%ld, a=b^{+/-2} problem between modinv_N=%ld and L0=%ld\n", D1, modinv_N, L0); ambiguity = 1; } } return gc_long(av, ambiguity); } static long check_generators( long *n1_, long *m_, long D, long h, long n, long subgrp_sz, long L0, long L1) { long n1, m = primeform_exp_order(L0, n, D, h); if (m_) *m_ = m; n1 = n * m; if (!n1) pari_err_BUG("check_generators"); *n1_ = n1; if (n1 < subgrp_sz/2 || ( ! L1 && n1 < subgrp_sz)) { dbg_printf(3)("Bad D1=%ld with n1=%ld, h1=%ld, L1=%ld: " "L0 and L1 don't span subgroup of size d in cl(D1)\n", D, n, h, L1); return 0; } if (n1 < subgrp_sz && ! (n1 & 1)) { int res; /* check whether L1 is generated by L0, use the fact that it has order 2 */ pari_sp av = avma; GEN D1 = stoi(D); GEN Q = gpowgs(primeform_u(D1, L0), n1 / 2); res = gequal(Q, qfbred_i(primeform_u(D1, L1))); set_avma(av); if (res) { dbg_printf(3)("Bad D1=%ld, with n1=%ld, h1=%ld, L1=%ld: " "L1 generated by L0 in cl(D1)\n", D, n, h, L1); return 0; } } return 1; } /* Calculate solutions (p, t) to the norm equation * 4 p = t^2 - v^2 L^2 D (*) * corresponding to the descriminant described by Dinfo. * * INPUT: * - max: length of primes and traces * - xprimes: p to exclude from primes (if they arise) * - xcnt: length of xprimes * - minbits: sum of log2(p) must be larger than this * - Dinfo: discriminant, invariant and L for which we seek solutions to (*) * * OUTPUT: * - primes: array of p in (*) * - traces: array of t in (*) * - totbits: sum of log2(p) for p in primes. * * RETURN: * - the number of primes and traces found (these are always the same). * * NOTE: primes and traces are both NULL or both non-NULL. * xprimes can be zero, in which case it is treated as empty. */ static long modpoly_pickD_primes( ulong *primes, ulong *traces, long max, ulong *xprimes, long xcnt, long *totbits, long minbits, disc_info *Dinfo) { double bits; long D, m, n, vcnt, pfilter, one_prime, inv; ulong maxp; ulong a1, a2, v, t, p, a1_start, a1_delta, L0, L1, L, absD; ulong FF_BITS = BITS_IN_LONG - 2; /* BITS_IN_LONG - NAIL_BITS */ D = Dinfo->D1; absD = -D; L0 = Dinfo->L0; L1 = Dinfo->L1; L = Dinfo->L; inv = Dinfo->inv; /* make sure pfilter and D don't preclude the possibility of p=(t^2-v^2D)/4 being prime */ pfilter = modinv_pfilter(inv); if ((pfilter & IQ_FILTER_1MOD3) && ! (D % 3)) return 0; if ((pfilter & IQ_FILTER_1MOD4) && ! (D & 0xF)) return 0; /* Naively estimate the number of primes satisfying 4p=t^2-L^2D with * t=2 mod L and pfilter. This is roughly * #{t: t^2 < max p and t=2 mod L} / pi(max p) * filter_density, * where filter_density is 1, 2, or 4 depending on pfilter. If this quantity * is already more than twice the number of bits we need, assume that, * barring some obstruction, we should have no problem getting enough primes. * In this case we just verify we can get one prime (which should always be * true, assuming we chose D properly). */ one_prime = 0; *totbits = 0; if (max <= 1 && ! one_prime) { p = ((pfilter & IQ_FILTER_1MOD3) ? 2 : 1) * ((pfilter & IQ_FILTER_1MOD4) ? 2 : 1); one_prime = (1UL << ((FF_BITS+1)/2)) * (log2(L*L*(-D))-1) > p*L*minbits*FF_BITS*M_LN2; if (one_prime) *totbits = minbits+1; /* lie */ } m = n = 0; bits = 0.0; maxp = 0; for (v = 1; v < 100 && bits < minbits; v++) { /* Don't allow v dividing the conductor. */ if (ugcd(absD, v) != 1) continue; /* Avoid v dividing the level. */ if (v > 2 && modinv_is_double_eta(inv) && ugcd(modinv_level(inv), v) != 1) continue; /* can't get odd p with D=1 mod 8 unless v is even */ if ((v & 1) && (D & 7) == 1) continue; /* disallow 4 | v for L0=2 (removing this restriction is costly) */ if (L0 == 2 && !(v & 3)) continue; /* can't get p=3mod4 if v^2D is 0 mod 16 */ if ((pfilter & IQ_FILTER_1MOD4) && !((v*v*D) & 0xF)) continue; if ((pfilter & IQ_FILTER_1MOD3) && !(v%3) ) continue; /* avoid L0-volcanos with nonzero height */ if (L0 != 2 && ! (v % L0)) continue; /* ditto for L1 */ if (L1 && !(v % L1)) continue; vcnt = 0; if ((v*v*absD)/4 > (1L<> 2; if (!(a2 % L)) continue; t = a1*L + 2; p = a2*L*L + t - 1; /* double check calculation just in case of overflow or other weirdness */ if (!odd(p) || t*t + v*v*L*L*absD != 4*p) pari_err_BUG("modpoly_pickD_primes"); if (p > (1UL<= max) goto done; /* TODO: Implement test to filter primes that lead to * L-valuation != 2 */ primes[n] = p; traces[n] = t; } n++; vcnt++; bits += log2(p); if (p > maxp) maxp = p; if (one_prime) goto done; } if (vcnt) dbg_printf(3)("%ld primes with v=%ld, maxp=%ld (%.2f bits)\n", vcnt, v, maxp, log2(maxp)); } done: if (!n) { dbg_printf(3)("check_primes failed completely for D=%ld\n", D); return 0; } dbg_printf(3)("D=%ld: Found %ld primes totalling %0.2f of %ld bits\n", D, n, bits, minbits); if (!*totbits) *totbits = (long)bits; return n; } #define MAX_VOLCANO_FLOOR_SIZE 100000000 static long calc_primes_for_discriminants(disc_info Ds[], long Dcnt, long L, long minbits) { pari_sp av = avma; long i, j, k, m, n, D1, pcnt, totbits; ulong *primes, *Dprimes, *Dtraces; /* D1 is the discriminant with smallest absolute value among those we found */ D1 = Ds[0].D1; for (i = 1; i < Dcnt; i++) if (Ds[i].D1 > D1) D1 = Ds[i].D1; /* n is an upper bound on the number of primes we might get. */ n = ceil(minbits / (log2(L * L * (-D1)) - 2)) + 1; primes = (ulong *) stack_malloc(n * sizeof(*primes)); Dprimes = (ulong *) stack_malloc(n * sizeof(*Dprimes)); Dtraces = (ulong *) stack_malloc(n * sizeof(*Dtraces)); for (i = 0, totbits = 0, pcnt = 0; i < Dcnt && totbits < minbits; i++) { long np = modpoly_pickD_primes(Dprimes, Dtraces, n, primes, pcnt, &Ds[i].bits, minbits - totbits, Ds + i); ulong *T = (ulong *)newblock(2*np); Ds[i].nprimes = np; Ds[i].primes = T; memcpy(T , Dprimes, np * sizeof(*Dprimes)); Ds[i].traces = T+np; memcpy(T+np, Dtraces, np * sizeof(*Dtraces)); totbits += Ds[i].bits; pcnt += np; if (totbits >= minbits || i == Dcnt - 1) { Dcnt = i + 1; break; } /* merge lists */ for (j = pcnt - np - 1, k = np - 1, m = pcnt - 1; m >= 0; m--) { if (k >= 0) { if (j >= 0 && primes[j] > Dprimes[k]) primes[m] = primes[j--]; else primes[m] = Dprimes[k--]; } else { primes[m] = primes[j--]; } } } if (totbits < minbits) { dbg_printf(1)("Only obtained %ld of %ld bits using %ld discriminants\n", totbits, minbits, Dcnt); for (i = 0; i < Dcnt; i++) killblock((GEN)Ds[i].primes); Dcnt = 0; } return gc_long(av, Dcnt); } /* Select discriminant(s) to use when calculating the modular * polynomial of level L and invariant inv. * * INPUT: * - L: level of modular polynomial (must be odd) * - inv: invariant of modular polynomial * - L0: result of select_L0(L, inv) * - minbits: height of modular polynomial * - flags: see below * - tab: result of scanD0(L0) * - tablen: length of tab * * OUTPUT: * - Ds: the selected discriminant(s) * * RETURN: * - the number of Ds found * * The flags parameter is constructed by ORing zero or more of the * following values: * - MODPOLY_USE_L1: force use of second class group generator * - MODPOLY_NO_AUX_L: don't use auxillary class group elements * - MODPOLY_IGNORE_SPARSE_FACTOR: obtain D for which h(D) > L + 1 * rather than h(D) > (L + 1)/s */ static long modpoly_pickD(disc_info Ds[MODPOLY_MAX_DCNT], long L, long inv, long L0, long max_L1, long minbits, long flags, D_entry *tab, long tablen) { pari_sp ltop = avma, btop; disc_info Dinfo; pari_timer T; long modinv_p1, modinv_p2; /* const after next line */ const long modinv_deg = modinv_degree(&modinv_p1, &modinv_p2, inv); const long pfilter = modinv_pfilter(inv), modinv_N = modinv_level(inv); long i, k, use_L1, Dcnt, D0_i, d, cost, enum_cost, best_cost, totbits; const double L_bits = log2(L); if (!odd(L)) pari_err_BUG("modpoly_pickD"); timer_start(&T); if (flags & MODPOLY_IGNORE_SPARSE_FACTOR) d = L+2; else d = ceildivuu(L+1, modinv_sparse_factor(inv)) + 1; /* Now set level to 0 unless we will need to compute N-isogenies */ dbg_printf(1)("Using L0=%ld for L=%ld, d=%ld, modinv_N=%ld, modinv_deg=%ld\n", L0, L, d, modinv_N, modinv_deg); /* We use L1 if (L0|L) == 1 or if we are forced to by flags. */ use_L1 = (kross(L0,L) > 0 || (flags & MODPOLY_USE_L1)); Dcnt = best_cost = totbits = 0; dbg_printf(3)("use_L1=%ld\n", use_L1); dbg_printf(3)("minbits = %ld\n", minbits); /* Iterate over the fundamental discriminants for L0 */ for (D0_i = 0; D0_i < tablen; D0_i++) { D_entry D0_entry = tab[D0_i]; long m, n0, h0, deg, L1, H_cost, twofactor, D0 = D0_entry.D; double D0_bits; if (! modinv_good_disc(inv, D0)) continue; dbg_printf(3)("D0=%ld\n", D0); /* don't allow either modinv_p1 or modinv_p2 to ramify */ if (kross(D0, L) < 1 || (modinv_p1 > 1 && kross(D0, modinv_p1) < 1) || (modinv_p2 > 1 && kross(D0, modinv_p2) < 1)) { dbg_printf(3)("Bad D0=%ld due to nonsplit L or ramified level\n", D0); continue; } deg = D0_entry.h; /* class poly degree */ h0 = ((D0_entry.m & 2) ? 2*deg : deg); /* class number */ /* (D0_entry.m & 1) is 1 if ord(L0) < h0 (hence = h0/2), * is 0 if ord(L0) = h0 */ n0 = h0 / ((D0_entry.m & 1) + 1); /* = ord(L0) */ /* Look for L1: for each smooth prime p */ L1 = 0; for (i = 1 ; i <= SMOOTH_PRIMES; i++) { long p = PRIMES[i]; if (p <= L0) continue; /* If 1 + (D0 | p) = 1, i.e. p | D0 */ if (((D0_entry.m >> (2*i)) & 3) == 1) { /* XXX: Why (p | L) = -1? Presumably so (L^2 v^2 D0 | p) = -1? */ if (p <= max_L1 && modinv_N % p && kross(p,L) < 0) { L1 = p; break; } } } if (i > SMOOTH_PRIMES && (n0 < h0 || use_L1)) { /* Didn't find suitable L1 though we need one */ dbg_printf(3)("Bad D0=%ld because there is no good L1\n", D0); continue; } dbg_printf(3)("Good D0=%ld with L1=%ld, n0=%ld, h0=%ld, d=%ld\n", D0, L1, n0, h0, d); /* We're finished if we have sufficiently many discriminants that satisfy * the cost requirement */ if (totbits > minbits && best_cost && h0*(L-1) > 3*best_cost) break; D0_bits = log2(-D0); /* If L^2 D0 is too big to fit in a BIL bit integer, skip D0. */ if (D0_bits + 2 * L_bits > (BITS_IN_LONG - 1)) continue; /* m is the order of L0^n0 in L^2 D0? */ m = primeform_exp_order(L0, n0, L * L * D0, n0 * (L-1)); if (m < (L-1)/2) { dbg_printf(3)("Bad D0=%ld because %ld is less than (L-1)/2=%ld\n", D0, m, (L - 1)/2); continue; } /* Heuristic. Doesn't end up contributing much. */ H_cost = 2 * deg * deg; /* 0xc = 0b1100, so D0_entry.m & 0xc == 1 + (D0 | 2) */ if ((D0 & 7) == 5) /* D0 = 5 (mod 8) */ twofactor = ((D0_entry.m & 0xc) ? 1 : 3); else twofactor = 0; btop = avma; /* For each small prime... */ for (i = 0; i <= SMOOTH_PRIMES; i++) { long h1, h2, D1, D2, n1, n2, dl1, dl20, dl21, p, q, j; double p_bits; set_avma(btop); /* i = 0 corresponds to 1, which we do not want to skip! (i.e. DK = D) */ if (i) { if (modinv_odd_conductor(inv) && i == 1) continue; p = PRIMES[i]; /* Don't allow large factors in the conductor. */ if (p > max_L1) break; if (p == L0 || p == L1 || p == L || p == modinv_p1 || p == modinv_p2) continue; p_bits = log2(p); /* h1 is the class number of D1 = q^2 D0, where q = p^j (j defined in the loop below) */ h1 = h0 * (p - ((D0_entry.m >> (2*i)) & 0x3) + 1); /* q is the smallest power of p such that h1 >= d ~ "L + 1". */ for (j = 1, q = p; h1 < d; j++, q *= p, h1 *= p) ; D1 = q * q * D0; /* can't have D1 = 0 mod 16 and hope to get any primes congruent to 3 mod 4 */ if ((pfilter & IQ_FILTER_1MOD4) && !(D1 & 0xF)) continue; } else { /* i = 0, corresponds to "p = 1". */ h1 = h0; D1 = D0; p = q = j = 1; p_bits = 0; } /* include a factor of 4 if D1 is 5 mod 8 */ /* XXX: No idea why he does this. */ if (twofactor && (q & 1)) { if (modinv_odd_conductor(inv)) continue; D1 *= 4; h1 *= twofactor; } /* heuristic early abort; we may miss good D1's, but this saves time */ if (totbits > minbits && best_cost && h1*(L-1) > 2.2*best_cost) continue; /* log2(D0 * (p^j)^2 * L^2 * twofactor) > (BIL - 1) -- params too big. */ if (D0_bits + 2*j*p_bits + 2*L_bits + (twofactor && (q & 1) ? 2.0 : 0.0) > (BITS_IN_LONG-1)) continue; if (! check_generators(&n1, NULL, D1, h1, n0, d, L0, L1)) continue; if (n1 >= h1) dl1 = -1; /* fill it in later */ else if ((dl1 = primeform_discrete_log(L0, L, n1, D1)) < 0) continue; dbg_printf(3)("Good D0=%ld, D1=%ld with q=%ld, L1=%ld, n1=%ld, h1=%ld\n", D0, D1, q, L1, n1, h1); if (modinv_deg && orientation_ambiguity(D1, L0, modinv_p1, modinv_p2, modinv_N)) continue; D2 = L * L * D1; h2 = h1 * (L-1); /* m is the order of L0^n1 in cl(D2) */ if (!check_generators(&n2, &m, D2, h2, n1, d*(L-1), L0, L1)) continue; /* This restriction on m is not necessary, but simplifies life later */ if (m < (L-1)/2 || (!L1 && m < L-1)) { dbg_printf(3)("Bad D2=%ld for D1=%ld, D0=%ld, with n2=%ld, h2=%ld, L1=%ld, " "order of L0^n1 in cl(D2) is too small\n", D2, D1, D0, n2, h2, L1); continue; } dl20 = n1; dl21 = 0; if (m < L-1) { GEN Q1 = qform_primeform2(L, D1), Q2, X; if (!Q1) pari_err_BUG("modpoly_pickD"); Q2 = primeform_u(stoi(D2), L1); Q2 = qfbcomp(Q1, Q2); /* we know this element has order L-1 */ Q1 = primeform_u(stoi(D2), L0); k = ((n2 & 1) ? 2*n2 : n2)/(L-1); Q1 = gpowgs(Q1, k); X = qfi_Shanks(Q2, Q1, L-1); if (!X) { dbg_printf(3)("Bad D2=%ld for D1=%ld, D0=%ld, with n2=%ld, h2=%ld, L1=%ld, " "form of norm L^2 not generated by L0 and L1\n", D2, D1, D0, n2, h2, L1); continue; } dl20 = itos(X) * k; dl21 = 1; } if (! (m < L-1 || n2 < d*(L-1)) && n1 >= d && ! use_L1) L1 = 0; /* we don't need L1 */ if (!L1 && use_L1) { dbg_printf(3)("not using D2=%ld for D1=%ld, D0=%ld, with n2=%ld, h2=%ld, L1=%ld, " "because we don't need L1 but must use it\n", D2, D1, D0, n2, h2, L1); continue; } /* don't allow zero dl21 with L1 for the moment, since * modpoly doesn't handle it - we may change this in the future */ if (L1 && ! dl21) continue; dbg_printf(3)("Good D0=%ld, D1=%ld, D2=%ld with s=%ld^%ld, L1=%ld, dl2=%ld, n2=%ld, h2=%ld\n", D0, D1, D2, p, j, L1, dl20, n2, h2); /* This estimate is heuristic and fiddling with the * parameters 5 and 0.25 can change things quite a bit. */ enum_cost = n2 * (5 * L0 * L0 + 0.25 * L1 * L1); cost = enum_cost + H_cost; if (best_cost && cost > 2.2*best_cost) break; if (best_cost && cost >= 0.99*best_cost) continue; Dinfo.GENcode0 = evaltyp(t_VECSMALL)|_evallg(13); Dinfo.inv = inv; Dinfo.L = L; Dinfo.D0 = D0; Dinfo.D1 = D1; Dinfo.L0 = L0; Dinfo.L1 = L1; Dinfo.n1 = n1; Dinfo.n2 = n2; Dinfo.dl1 = dl1; Dinfo.dl2_0 = dl20; Dinfo.dl2_1 = dl21; Dinfo.cost = cost; if (!modpoly_pickD_primes(NULL, NULL, 0, NULL, 0, &Dinfo.bits, minbits, &Dinfo)) continue; dbg_printf(2)("Best D2=%ld, D1=%ld, D0=%ld with s=%ld^%ld, L1=%ld, " "n1=%ld, n2=%ld, cost ratio %.2f, bits=%ld\n", D2, D1, D0, p, j, L1, n1, n2, (double)cost/(d*(L-1)), Dinfo.bits); /* Insert Dinfo into the Ds array. Ds is sorted by ascending cost. */ for (j = 0; j < Dcnt; j++) if (Dinfo.cost < Ds[j].cost) break; if (n2 > MAX_VOLCANO_FLOOR_SIZE && n2*(L1 ? 2 : 1) > 1.2* (d*(L-1)) ) { dbg_printf(3)("Not using D1=%ld, D2=%ld for space reasons\n", D1, D2); continue; } if (j == Dcnt && Dcnt == MODPOLY_MAX_DCNT) continue; totbits += Dinfo.bits; if (Dcnt == MODPOLY_MAX_DCNT) totbits -= Ds[Dcnt-1].bits; if (Dcnt < MODPOLY_MAX_DCNT) Dcnt++; if (n2 > MAX_VOLCANO_FLOOR_SIZE) dbg_printf(3)("totbits=%ld, minbits=%ld\n", totbits, minbits); for (k = Dcnt-1; k > j; k--) Ds[k] = Ds[k-1]; Ds[k] = Dinfo; best_cost = (totbits > minbits)? Ds[Dcnt-1].cost: 0; /* if we were able to use D1 with s = 1, there is no point in * using any larger D1 for the same D0 */ if (!i) break; } /* END FOR over small primes */ } /* END WHILE over D0's */ dbg_printf(2)(" checked %ld of %ld fundamental discriminants to find suitable " "discriminant (Dcnt = %ld)\n", D0_i, tablen, Dcnt); if ( ! Dcnt) { dbg_printf(1)("failed completely for L=%ld\n", L); return 0; } Dcnt = calc_primes_for_discriminants(Ds, Dcnt, L, minbits); /* fill in any missing dl1's */ for (i = 0 ; i < Dcnt; i++) if (Ds[i].dl1 < 0 && (Ds[i].dl1 = primeform_discrete_log(L0, L, Ds[i].n1, Ds[i].D1)) < 0) pari_err_BUG("modpoly_pickD"); if (DEBUGLEVEL > 1+3) { err_printf("Selected %ld discriminants using %ld msecs\n", Dcnt, timer_delay(&T)); for (i = 0 ; i < Dcnt ; i++) { GEN H = classno(stoi(Ds[i].D0)); long h0 = itos(H); err_printf (" D0=%ld, h(D0)=%ld, D=%ld, L0=%ld, L1=%ld, " "cost ratio=%.2f, enum ratio=%.2f,", Ds[i].D0, h0, Ds[i].D1, Ds[i].L0, Ds[i].L1, (double)Ds[i].cost/(d*(L-1)), (double)(Ds[i].n2*(Ds[i].L1 ? 2 : 1))/(d*(L-1))); err_printf (" %ld primes, %ld bits\n", Ds[i].nprimes, Ds[i].bits); } } return gc_long(ltop, Dcnt); } static int _qsort_cmp(const void *a, const void *b) { D_entry *x = (D_entry *)a, *y = (D_entry *)b; long u, v; /* u and v are the class numbers of x and y */ u = x->h * (!!(x->m & 2) + 1); v = y->h * (!!(y->m & 2) + 1); /* Sort by class number */ if (u < v) return -1; if (u > v) return 1; /* Sort by discriminant (which is < 0, hence the sign reversal) */ if (x->D > y->D) return -1; if (x->D < y->D) return 1; return 0; } /* Build a table containing fundamental D, |D| <= maxD whose class groups * - are cyclic generated by an element of norm L0 * - have class number at most maxh * The table is ordered using _qsort_cmp above, which ranks the discriminants * by class number, then by absolute discriminant. * * INPUT: * - maxd: largest allowed discriminant * - maxh: largest allowed class number * - L0: norm of class group generator (2, 3, 5, or 7) * * OUTPUT: * - tablelen: length of return value * * RETURN: * - array of {D, h(D), kronecker symbols for small p} */ static D_entry * scanD0(long *tablelen, long *minD, long maxD, long maxh, long L0) { pari_sp av; D_entry *tab; long i, lF, cnt; GEN F; /* NB: As seen in the loop below, the real class number of D can be */ /* 2*maxh if cl(D) is cyclic. */ tab = (D_entry *) stack_malloc((maxD/4)*sizeof(*tab)); /* Overestimate */ F = vecfactorsquarefreeu_coprime(*minD, maxD, mkvecsmall(2)); lF = lg(F); for (av = avma, cnt = 0, i = 1; i < lF; i++, set_avma(av)) { GEN DD, ordL, f, q = gel(F,i); long j, k, n, h, L1, d, D; ulong m; if (!q) continue; /* not square-free */ /* restrict to possibly cyclic class groups */ k = lg(q) - 1; if (k > 2) continue; d = i + *minD - 1; /* q = prime divisors of d */ if ((d & 3) == 1) continue; D = -d; /* d = 3 (mod 4), D = 1 mod 4 fundamental */ if (kross(D, L0) < 1) continue; /* L1 initially the first factor of d if small enough, otherwise ignored */ L1 = (k > 1 && q[1] <= MAX_L1)? q[1]: 0; /* Check if h(D) is too big */ h = hclassno6u(d) / 6; if (h > 2*maxh || (!L1 && h > maxh)) continue; /* Check if ord(f) is not big enough to generate at least half the * class group (where f is the L0-primeform). */ DD = stoi(D); f = primeform_u(DD, L0); ordL = qfi_order(qfbred_i(f), stoi(h)); n = itos(ordL); if (n < h/2 || (!L1 && n < h)) continue; /* If f is big enough, great! Otherwise, for each potential L1, * do a discrete log to see if it is NOT in the subgroup generated * by L0; stop as soon as such is found. */ for (j = 1;; j++) { if (n == h || (L1 && !qfi_Shanks(primeform_u(DD, L1), f, n))) { dbg_printf(2)("D0=%ld good with L1=%ld\n", D, L1); break; } if (!L1) break; L1 = (j <= k && k > 1 && q[j] <= MAX_L1 ? q[j] : 0); } /* The first bit of m is set iff f generates a proper subgroup of cl(D) * (hence implying that we need L1). */ m = (n < h ? 1 : 0); /* bits j and j+1 give the 2-bit number 1 + (D|p) where p = prime(j) */ for (j = 1 ; j <= SMOOTH_PRIMES; j++) { ulong x = (ulong) (1 + kross(D, PRIMES[j])); m |= x << (2*j); } /* Insert d, h and m into the table */ tab[cnt].D = D; tab[cnt].h = h; tab[cnt].m = m; cnt++; } /* Sort the table */ qsort(tab, cnt, sizeof(*tab), _qsort_cmp); *tablelen = cnt; *minD = maxD + 3 - (maxD & 3); /* smallest d >= maxD, d = 3 (mod 4) */ return tab; } /* Populate Ds with discriminants (and attached data) that can be * used to calculate the modular polynomial of level L and invariant * inv. Return the number of discriminants found. */ static long discriminant_with_classno_at_least(disc_info bestD[MODPOLY_MAX_DCNT], long L, long inv, GEN Q, long ignore_sparse) { enum { SMALL_L_BOUND = 101 }; long max_max_D = 160000 * (inv ? 2 : 1); long minD, maxD, maxh, L0, max_L1, minbits, Dcnt, flags, s, d, i, tablen; D_entry *tab; double eps, cost, best_eps = -1.0, best_cost = -1.0; disc_info Ds[MODPOLY_MAX_DCNT]; long best_cnt = 0; pari_timer T; timer_start(&T); s = modinv_sparse_factor(inv); d = ceildivuu(L+1, s) + 1; /* maxD of 10000 allows us to get a satisfactory discriminant in * under 250ms in most cases. */ maxD = 10000; /* Allow the class number to overshoot L by 50%. Must be at least * 1.1*L, and higher values don't seem to provide much benefit, * except when L is small, in which case it's necessary to get any * discriminant at all in some cases. */ maxh = (L / s < SMALL_L_BOUND) ? 10 * L : 1.5 * L; flags = ignore_sparse ? MODPOLY_IGNORE_SPARSE_FACTOR : 0; L0 = select_L0(L, inv, 0); max_L1 = L / 2 + 2; /* for L=11 we need L1=7 for j */ minbits = modpoly_height_bound(L, inv); if (Q) minbits += expi(Q); minD = 7; while ( ! best_cnt) { while (maxD <= max_max_D) { /* TODO: Find a way to re-use tab when we need multiple modpolys */ tab = scanD0(&tablen, &minD, maxD, maxh, L0); dbg_printf(1)("Found %ld potential fundamental discriminants\n", tablen); Dcnt = modpoly_pickD(Ds, L, inv, L0, max_L1, minbits, flags, tab, tablen); eps = 0.0; cost = 0.0; if (Dcnt) { long n1 = 0; for (i = 0; i < Dcnt; i++) { n1 = maxss(n1, Ds[i].n1); cost += Ds[i].cost; } eps = (n1 * s - L) / (double)L; if (best_cost < 0.0 || cost < best_cost) { if (best_cnt) for (i = 0; i < best_cnt; i++) killblock((GEN)bestD[i].primes); (void) memcpy(bestD, Ds, Dcnt * sizeof(disc_info)); best_cost = cost; best_cnt = Dcnt; best_eps = eps; /* We're satisfied if n1 is within 5% of L. */ if (L / s <= SMALL_L_BOUND || eps < 0.05) break; } else { for (i = 0; i < Dcnt; i++) killblock((GEN)Ds[i].primes); } } else { if (log2(maxD) > BITS_IN_LONG - 2 * (log2(L) + 2)) { char *err = stack_sprintf("modular polynomial of level %ld and invariant %ld",L,inv); pari_err(e_ARCH, err); } } maxD *= 2; minD += 4; dbg_printf(0)(" Doubling discriminant search space (closest: %.1f%%, cost ratio: %.1f)...\n", eps*100, cost/(double)(d*(L-1))); } max_max_D *= 2; } if (DEBUGLEVEL > 3) { pari_sp av = avma; err_printf("Found discriminant(s):\n"); for (i = 0; i < best_cnt; ++i) { long h = itos(classno(stoi(bestD[i].D1))); set_avma(av); err_printf(" D = %ld, h = %ld, u = %ld, L0 = %ld, L1 = %ld, n1 = %ld, n2 = %ld, cost = %ld\n", bestD[i].D1, h, usqrt(bestD[i].D1 / bestD[i].D0), bestD[i].L0, bestD[i].L1, bestD[i].n1, bestD[i].n2, bestD[i].cost); } err_printf("(off target by %.1f%%, cost ratio: %.1f)\n", best_eps*100, best_cost/(double)(d*(L-1))); } return best_cnt; } pari-2.17.2/src/language/0000755000175000017500000000000014760315601013541 5ustar billbillpari-2.17.2/src/language/str.c0000644000175000017500000001366514676526175014550 0ustar billbill/* Copyright (C) 2018 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" /********************************************************************/ /** **/ /** CHARACTER STRINGS **/ /** **/ /********************************************************************/ /* Utillity functions */ char * stack_strdup(const char *s) { long n = strlen(s)+1; char *t = stack_malloc(n); memcpy(t,s,n); return t; } char * stack_strcat(const char *s, const char *t) { long ls = strlen(s), lt = strlen(t); long n = ls + lt + 1; char *u = stack_malloc(n); memcpy(u, s, ls); memcpy(u + ls,t, lt+1); return u; } char * pari_strdup(const char *s) { long n = strlen(s)+1; char *t = (char*)pari_malloc(n); memcpy(t,s,n); return t; } char * pari_strndup(const char *s, long n) { char *t = (char*)pari_malloc(n+1); memcpy(t,s,n); t[n] = 0; return t; } /* 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); /* +1 for trailing 0 */ GEN x = cgetg(n+1, t_STR); char *t = GSTR(x); x[n] = 0; /* avoid uninitialized memory */ strncpy(t, s, n0); t[n0] = 0; return x; } /* strntoGENstr would trigger gcc-8 stringop-truncation warning */ GEN strtoGENstr(const char *s) { long n0 = strlen(s) + 1, n = nchar2nlong(n0); GEN x = cgetg(n+1, t_STR); char *t = GSTR(x); x[n] = 0; strncpy(t, s, n0); return x; } GEN chartoGENstr(char c) { GEN x = cgetg(2, t_STR); char *t = GSTR(x); t[0] = c; t[1] = 0; return x; } 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_QFB : s="t_QFB"; break; case t_VEC : s="t_VEC"; break; case t_COL : s="t_COL"; break; case t_MAT : s="t_MAT"; break; case t_LIST : s="t_LIST"; break; case t_STR : s="t_STR"; break; case t_VECSMALL:s="t_VECSMALL";break; case t_CLOSURE: s="t_CLOSURE"; break; case t_ERROR: s="t_ERROR"; break; case t_INFINITY:s="t_INFINITY";break; default: pari_err_BUG("type"); s = NULL; /* LCOV_EXCL_LINE */ } return s; } GEN type0(GEN x) { const char *s = type_name(typ(x)); return strtoGENstr(s); } static char ltoc(long n) { if (n <= 0 || n > 255) pari_err(e_MISC, "out of range in integer -> character conversion (%ld)", n); return (char)n; } static char itoc(GEN x) { return ltoc(gtos(x)); } GEN pari_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; i> 2]; t[j+1] = base64[((s0 & 0x3) << 4) + ((s1 & 0xf0) >> 4)]; t[j+2] = i+1> 6)]: '='; t[j+3] = i+2 #if defined(_WIN32) || defined(__CYGWIN32__) # include "../systems/mingw/mingw.h" # include #endif #include "paricfg.h" #if defined(STACK_CHECK) && !defined(__EMX__) && !defined(_WIN32) # include # include # include #endif #if defined(HAS_WAITPID) && defined(HAS_SETSID) # include #endif #ifdef HAS_MMAP # include #endif #if defined(USE_GETTIMEOFDAY) || defined(USE_GETRUSAGE) || defined(USE_TIMES) # include #endif #if defined(USE_GETRUSAGE) # include #endif #if defined(USE_FTIME) || defined(USE_FTIMEFORWALLTIME) # include #endif #if defined(USE_CLOCK_GETTIME) || defined(USE_TIMES) # include #endif #if defined(USE_TIMES) # include #endif #define PARI_INIT #include "pari.h" #include "paripriv.h" #include "anal.h" const double LOG10_2 = 0.3010299956639812; /* log_10(2) */ const double LOG2_10 = 3.321928094887362; /* log_2(10) */ GEN gnil, gen_0, gen_1, gen_m1, gen_2, gen_m2, ghalf, err_e_STACK; static const ulong readonly_constants[] = { evaltyp(t_INT) | _evallg(2), /* gen_0 */ evallgefint(2), evaltyp(t_INT) | _evallg(2), /* gnil */ evallgefint(2), evaltyp(t_INT) | _evallg(3), /* gen_1 */ evalsigne(1) | evallgefint(3), 1, evaltyp(t_INT) | _evallg(3), /* gen_2 */ evalsigne(1) | evallgefint(3), 2, evaltyp(t_INT) | _evallg(3), /* gen_m1 */ evalsigne(-1) | evallgefint(3), 1, evaltyp(t_INT) | _evallg(3), /* gen_m2 */ evalsigne(-1) | evallgefint(3), 2, evaltyp(t_ERROR) | _evallg(2), /* err_e_STACK */ e_STACK, evaltyp(t_FRAC) | _evallg(3), /* ghalf */ (ulong)(readonly_constants+4), (ulong)(readonly_constants+7) }; THREAD GEN zetazone, bernzone, eulerzone, primetab; pari_prime *pari_PRIMES; 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 DEBUGLEVEL, DEBUGMEM; THREAD long DEBUGVAR; ulong pari_mt_nbthreads; long precreal; ulong precdl, pari_logstyle; gp_data *GP_DATA; entree **varentries; THREAD long *varpriority; THREAD pari_sp avma; THREAD struct pari_mainstack *pari_mainstack; static void ** MODULES; static pari_stack s_MODULES; const long functions_tblsz = 135; /* size of functions_hash */ entree **functions_hash, **defaults_hash; void (*cb_pari_display_hist)(long n); char *(*cb_pari_fgets_interactive)(char *s, int n, FILE *f); int (*cb_pari_get_line_interactive)(const char*, const char*, filtre_t *F); void (*cb_pari_quit)(long); void (*cb_pari_init_histfile)(void); void (*cb_pari_ask_confirm)(const char *); int (*cb_pari_handle_exception)(long); int (*cb_pari_err_handle)(GEN); int (*cb_pari_whatnow)(PariOUT *out, const char *, int); void (*cb_pari_sigint)(void); void (*cb_pari_pre_recover)(long); void (*cb_pari_err_recover)(long); int (*cb_pari_break_loop)(int); int (*cb_pari_is_interactive)(void); void (*cb_pari_start_output)(void); void (*cb_pari_long_help)(const char *s, long num); const char * pari_library_path = NULL; static THREAD GEN global_err_data; THREAD jmp_buf *iferr_env; const long CATCH_ALL = -1; static void pari_init_timer(void); /*********************************************************************/ /* */ /* BLOCKS & CLONES */ /* */ /*********************************************************************/ /*#define DEBUG*/ static THREAD long next_block; static THREAD GEN cur_block; /* current block in block list */ static THREAD GEN root_block; /* current block in block list */ static void pari_init_blocks(void) { next_block = 0; cur_block = NULL; root_block = NULL; } static void pari_close_blocks(void) { while (cur_block) killblock(cur_block); } static long blockheight(GEN bl) { return bl? bl_height(bl): 0; } static long blockbalance(GEN bl) { return bl ? blockheight(bl_left(bl)) - blockheight(bl_right(bl)): 0; } static void fix_height(GEN bl) { bl_height(bl) = maxss(blockheight(bl_left(bl)), blockheight(bl_right(bl)))+1; } static GEN bl_rotright(GEN y) { GEN x = bl_left(y), t = bl_right(x); bl_right(x) = y; bl_left(y) = t; fix_height(y); fix_height(x); return x; } static GEN bl_rotleft(GEN x) { GEN y = bl_right(x), t = bl_left(y); bl_left(y) = x; bl_right(x) = t; fix_height(x); fix_height(y); return y; } static GEN blockinsert(GEN x, GEN bl, long *d) { long b, c; if (!bl) { bl_left(x)=NULL; bl_right(x)=NULL; bl_height(x)=1; return x; } c = cmpuu((ulong)x, (ulong)bl); if (c < 0) bl_left(bl) = blockinsert(x, bl_left(bl), d); else if (c > 0) bl_right(bl) = blockinsert(x, bl_right(bl), d); else return bl; /* ??? Already exist in the tree ? */ fix_height(bl); b = blockbalance(bl); if (b > 1) { if (*d > 0) bl_left(bl) = bl_rotleft(bl_left(bl)); return bl_rotright(bl); } if (b < -1) { if (*d < 0) bl_right(bl) = bl_rotright(bl_right(bl)); return bl_rotleft(bl); } *d = c; return bl; } static GEN blockdelete(GEN x, GEN bl) { long b; if (!bl) return NULL; /* ??? Do not exist in the tree */ if (x < bl) bl_left(bl) = blockdelete(x, bl_left(bl)); else if (x > bl) bl_right(bl) = blockdelete(x, bl_right(bl)); else { if (!bl_left(bl) && !bl_right(bl)) return NULL; else if (!bl_left(bl)) return bl_right(bl); else if (!bl_right(bl)) return bl_left(bl); else { GEN r = bl_right(bl); while (bl_left(r)) r = bl_left(r); bl_right(r) = blockdelete(r, bl_right(bl)); bl_left(r) = bl_left(bl); bl = r; } } fix_height(bl); b = blockbalance(bl); if (b > 1) { if (blockbalance(bl_left(bl)) >= 0) return bl_rotright(bl); else { bl_left(bl) = bl_rotleft(bl_left(bl)); return bl_rotright(bl); } } if (b < -1) { if (blockbalance(bl_right(bl)) <= 0) return bl_rotleft(bl); else { bl_right(bl) = bl_rotright(bl_right(bl)); return bl_rotleft(bl); } } return bl; } static GEN blocksearch(GEN x, GEN bl) { if (isclone(x)) return x; if (isonstack(x) || is_universal_constant(x)) return NULL; while (bl) { if (x >= bl && x < bl + bl_size(bl)) return bl; bl = x < bl ? bl_left(bl): bl_right(bl); } return NULL; /* Unknown address */ } static int check_clone(GEN x) { GEN bl = root_block; if (isonstack(x) || is_universal_constant(x)) return 1; while (bl) { if (x >= bl && x < bl + bl_size(bl)) return 1; bl = x < bl ? bl_left(bl): bl_right(bl); } return 0; /* Unknown address */ } void clone_lock(GEN x) { GEN y = blocksearch(x, root_block); if (y && isclone(y)) { if (DEBUGMEM > 2) err_printf("locking block no %ld: %08lx from %08lx\n", bl_num(y), y, x); ++bl_refc(y); } } void clone_unlock(GEN x) { GEN y = blocksearch(x, root_block); if (y && isclone(y)) { if (DEBUGMEM > 2) err_printf("unlocking block no %ld: %08lx from %08lx\n", bl_num(y), y, x); gunclone(y); } } void clone_unlock_deep(GEN x) { GEN y = blocksearch(x, root_block); if (y && isclone(y)) { if (DEBUGMEM > 2) err_printf("unlocking deep block no %ld: %08lx from %08lx\n", bl_num(y), y, x); gunclone_deep(y); } } /* Return x, where: * x[-8]: AVL height * x[-7]: adress of left child or NULL * x[-6]: adress of right child or NULL * x[-5]: size * 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 d = 0; long *x; BLOCK_SIGINT_START x = (long *) pari_malloc((n + BL_HEAD)*sizeof(long)) + BL_HEAD; bl_size(x) = n; 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; root_block = blockinsert(x, root_block, &d); if (DEBUGMEM > 2) err_printf("new block, size %6lu (no %ld): %08lx\n", n, next_block-1, x); cur_block = x; BLOCK_SIGINT_END return cur_block; } GEN gcloneref(GEN x) { if (isclone(x)) { ++bl_refc(x); return x; } else return gclone(x); } void gclone_refc(GEN x) { ++bl_refc(x); } void gunclone(GEN x) { if (--bl_refc(x) > 0) return; BLOCK_SIGINT_START; root_block = blockdelete(x, root_block); 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; } static void vec_gunclone_deep(GEN x) { long i, l = lg(x); for (i = 1; i < l; i++) gunclone_deep(gel(x,i)); } /* Recursively look for clones in the container and kill them. Then kill * container if clone. */ void gunclone_deep(GEN x) { GEN v; if (isclone(x) && bl_refc(x) > 1) { --bl_refc(x); return; } BLOCK_SIGINT_START; switch(typ(x)) { case t_VEC: case t_COL: case t_MAT: vec_gunclone_deep(x); break; case t_LIST: if ((v = list_data(x))) { vec_gunclone_deep(v); gunclone(v); } break; } if (isclone(x)) gunclone(x); BLOCK_SIGINT_END; } int pop_entree_block(entree *ep, long loc) { GEN x = (GEN)ep->value; 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; } /*************************************************************************** ** ** ** Export ** ** ** ***************************************************************************/ static hashtable *export_hash; static void pari_init_export(void) { export_hash = hash_create_str(1,0); } static void pari_close_export(void) { hash_destroy(export_hash); } /* Exported values are blocks, but do not have the clone bit set so that they * are not affected by clone_lock and ensure_nb, etc. */ void export_add(const char *str, GEN val) { hashentry *h; val = gclone(val); unsetisclone(val); h = hash_search(export_hash, (void*) str); if (h) { GEN v = (GEN)h->val; h->val = val; setisclone(v); gunclone(v); } else hash_insert(export_hash,(void*)str, (void*) val); } void export_del(const char *str) { hashentry *h = hash_remove(export_hash,(void*)str); if (h) { GEN v = (GEN)h->val; setisclone(v); gunclone(v); pari_free(h); } } GEN export_get(const char *str) { return hash_haskey_GEN(export_hash,(void*)str); } void unexportall(void) { pari_sp av = avma; GEN keys = hash_keys(export_hash); long i, l = lg(keys); for (i = 1; i < l; i++) mt_export_del((const char *)keys[i]); set_avma(av); } void exportall(void) { long i; for (i = 0; i < functions_tblsz; i++) { entree *ep; for (ep = functions_hash[i]; ep; ep = ep->next) if (EpVALENCE(ep)==EpVAR) mt_export_add(ep->name, (GEN)ep->value); } } /*********************************************************************/ /* */ /* C STACK SIZE CONTROL */ /* */ /*********************************************************************/ /* Avoid core dump on deep recursion. Adapted Perl code by Dominic Dunlop */ THREAD void *PARI_stack_limit = NULL; #ifdef STACK_CHECK # ifdef __EMX__ /* Emulate */ void pari_stackcheck_init(void *pari_stack_base) { if (!pari_stack_base) { PARI_stack_limit = NULL; return; } PARI_stack_limit = get_stack(1./16, 32*1024); } # elif _WIN32 void pari_stackcheck_init(void *pari_stack_base) { ulong size = 1UL << 21; if (!pari_stack_base) { PARI_stack_limit = NULL; return; } if (size > (ulong)pari_stack_base) PARI_stack_limit = (void*)(((ulong)pari_stack_base) / 16); else PARI_stack_limit = (void*)((ulong)pari_stack_base - (size/16)*15); } # else /* !__EMX__ && !_WIN32 */ /* Set PARI_stack_limit to (a little above) the lowest safe address that can be * used on the stack. Leave PARI_stack_limit at its initial value (NULL) to * show no check should be made [init failed]. Assume stack grows downward. */ void pari_stackcheck_init(void *pari_stack_base) { struct rlimit rip; ulong size; if (!pari_stack_base) { PARI_stack_limit = NULL; return; } if (getrlimit(RLIMIT_STACK, &rip)) return; size = rip.rlim_cur; if (size == (ulong)RLIM_INFINITY || size > (ulong)pari_stack_base) PARI_stack_limit = (void*)(((ulong)pari_stack_base) / 16); else PARI_stack_limit = (void*)((ulong)pari_stack_base - (size/16)*15); } # endif /* !__EMX__ */ #else void pari_stackcheck_init(void *pari_stack_base) { (void) pari_stack_base; PARI_stack_limit = NULL; } #endif /* STACK_CHECK */ /*******************************************************************/ /* HEAP TRAVERSAL */ /*******************************************************************/ struct getheap_t { long n, l; }; /* x is a block, not necessarily a clone [x[0] may not be set] */ static void f_getheap(GEN x, void *D) { struct getheap_t *T = (struct getheap_t*)D; T->n++; T->l += bl_size(x) + BL_HEAD; } GEN getheap(void) { struct getheap_t T = { 0, 0 }; traverseheap(&f_getheap, &T); return mkvec2s(T.n, T.l); } static void traverseheap_r(GEN bl, void(*f)(GEN, void *), void *data) { if (!bl) return; traverseheap_r(bl_left(bl), f, data); traverseheap_r(bl_right(bl), f, data); f(bl, data); } void traverseheap( void(*f)(GEN, void *), void *data) { traverseheap_r(root_block,f, data); } /*********************************************************************/ /* DAEMON / FORK */ /*********************************************************************/ #if defined(HAS_WAITPID) && defined(HAS_SETSID) /* 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. The silly '!' avoids a gcc-8 warning (unused value) */ (void)!freopen("/dev/null","r",stdin); return 0; } #else int pari_daemon(void) { pari_err_IMPL("pari_daemon without waitpid & setsid"); return 0; } #endif /*********************************************************************/ /* */ /* SYSTEM INITIALIZATION */ /* */ /*********************************************************************/ static int try_to_recover = 0; THREAD VOLATILE int PARI_SIGINT_block = 0, PARI_SIGINT_pending = 0; /*********************************************************************/ /* SIGNAL HANDLERS */ /*********************************************************************/ static void dflt_sigint_fun(void) { pari_err(e_MISC, "user interrupt"); } #if defined(_WIN32) || defined(__CYGWIN32__) int win32ctrlc = 0, win32alrm = 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 } 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; #else return signal(sig,f); #endif } void pari_sighandler(int sig) { const char *msg; #ifndef HAS_SIGACTION /*SYSV reset the signal handler in the handler*/ (void)os_signal(sig,pari_sighandler); #endif switch(sig) { #ifdef SIGBREAK case SIGBREAK: if (PARI_SIGINT_block==1) { PARI_SIGINT_pending=SIGBREAK; mt_sigint(); } else pari_handle_SIGINT(); return; #endif #ifdef SIGINT case SIGINT: if (PARI_SIGINT_block==1) { PARI_SIGINT_pending=SIGINT; mt_sigint(); } else pari_handle_SIGINT(); return; #endif #ifdef SIGSEGV case SIGSEGV: msg="PARI/GP (Segmentation Fault)"; break; #endif #ifdef SIGBUS case SIGBUS: msg="PARI/GP (Bus Error)"; break; #endif #ifdef SIGFPE case SIGFPE: msg="PARI/GP (Floating Point Exception)"; break; #endif #ifdef SIGPIPE case SIGPIPE: { pariFILE *f = GP_DATA->pp->file; if (f && pari_outfile == f->file) { GP_DATA->pp->file = NULL; /* to avoid oo recursion on error */ pari_outfile = stdout; pari_fclose(f); pari_err(e_MISC, "Broken Pipe, resetting file stack..."); } return; /* LCOV_EXCL_LINE */ } #endif default: msg="signal handling"; break; } pari_err_BUG(msg); } void pari_sig_init(void (*f)(int)) { #ifdef SIGBUS (void)os_signal(SIGBUS,f); #endif #ifdef SIGFPE (void)os_signal(SIGFPE,f); #endif #ifdef SIGINT (void)os_signal(SIGINT,f); #endif #ifdef SIGBREAK (void)os_signal(SIGBREAK,f); #endif #ifdef SIGPIPE (void)os_signal(SIGPIPE,f); #endif #ifdef SIGSEGV (void)os_signal(SIGSEGV,f); #endif } /*********************************************************************/ /* STACK AND UNIVERSAL CONSTANTS */ /*********************************************************************/ static void init_universal_constants(void) { gen_0 = (GEN)readonly_constants; gnil = (GEN)readonly_constants+2; gen_1 = (GEN)readonly_constants+4; gen_2 = (GEN)readonly_constants+7; gen_m1 = (GEN)readonly_constants+10; gen_m2 = (GEN)readonly_constants+13; err_e_STACK = (GEN)readonly_constants+16; ghalf = (GEN)readonly_constants+18; } static void pari_init_errcatch(void) { iferr_env = NULL; global_err_data = NULL; } void setalldebug(long n) { long i, l = numberof(pari_DEBUGLEVEL_ptr); for (i = 0; i < l; i++) *pari_DEBUGLEVEL_ptr[i] = n; } /*********************************************************************/ /* INIT DEFAULTS */ /*********************************************************************/ void pari_init_defaults(void) { long i; initout(1); precreal = 128; precdl = 16; DEBUGLEVEL = 0; setalldebug(0); DEBUGMEM = 1; disable_color = 1; pari_logstyle = logstyle_none; current_psfile = pari_strdup("pari.ps"); current_logfile= pari_strdup("pari.log"); pari_logfile = NULL; pari_datadir = os_getenv("GP_DATA_DIR"); if (!pari_datadir) { #if defined(_WIN32) || defined(__CYGWIN32__) if (paricfg_datadir[0]=='@' && paricfg_datadir[1]==0) pari_datadir = win32_datadir(); else #endif pari_datadir = pari_strdup(paricfg_datadir); } else pari_datadir= pari_strdup(pari_datadir); for (i=0; isize and * st->bot. If not enough system memory is available, this can fail. * Return 1 if successful, 0 if failed (in that case, st->size is not * changed) */ static int pari_mainstack_setsize(struct pari_mainstack *st, size_t size) { pari_sp newbot = st->top - size; /* Align newbot to pagesize */ pari_sp alignbot = newbot & ~(pari_sp)(PARI_STACK_ALIGN - 1); if (pari_mainstack_mextend(alignbot, st->top)) { /* Making the memory available did not work: limit vsize to the * current actual stack size. */ st->vsize = st->size; pari_warn(warnstack, st->vsize); return 0; } pari_mainstack_mreset(st->vbot, alignbot); st->bot = newbot; st->size = size; return 1; } #else #define PARI_STACK_ALIGN (0x40UL) static void * pari_mainstack_malloc(size_t s) { char * tmp; BLOCK_SIGINT_START; tmp = malloc(s); /* NOT pari_malloc, e_MEM would be deadly */ BLOCK_SIGINT_END; return tmp; } static void pari_mainstack_mfree(void *s, size_t size) { (void) size; pari_free(s); } static int pari_mainstack_setsize(struct pari_mainstack *st, size_t size) { st->bot = st->top - size; st->size = size; return 1; } #endif static const size_t MIN_STACK = 500032UL; static size_t fix_size(size_t a) { size_t ps = PARI_STACK_ALIGN; size_t b = a & ~(ps - 1); /* Align */ if (b < a && b < ~(ps - 1)) b += ps; if (b < MIN_STACK) b = MIN_STACK; return b; } static void pari_mainstack_alloc(int numerr, struct pari_mainstack *st, size_t rsize, size_t vsize) { size_t sizemax = vsize ? vsize: rsize, s = fix_size(sizemax); for (;;) { st->vbot = (pari_sp)pari_mainstack_malloc(s); if (st->vbot) break; if (s == MIN_STACK) pari_err(e_MEM); /* no way out. Die */ s = fix_size(s >> 1); pari_warn(numerr, s); } st->vsize = vsize ? s: 0; st->rsize = minuu(rsize, s); st->top = st->vbot+s; if (!pari_mainstack_setsize(st, st->rsize)) { /* This should never happen since we only decrease the allocated space */ pari_err(e_MEM); } st->memused = 0; } static void pari_mainstack_free(struct pari_mainstack *st) { pari_mainstack_mfree((void*)st->vbot, st->vsize ? st->vsize : fix_size(st->rsize)); st->top = st->bot = st->vbot = 0; st->size = st->vsize = 0; } static void pari_mainstack_resize(struct pari_mainstack *st, size_t rsize, size_t vsize) { BLOCK_SIGINT_START; pari_mainstack_free(st); pari_mainstack_alloc(warnstack, st, rsize, vsize); BLOCK_SIGINT_END; } static void pari_mainstack_use(struct pari_mainstack *st) { pari_mainstack = st; avma = st->top; /* don't use set_avma */ } static void paristack_alloc(size_t rsize, size_t vsize) { pari_mainstack_alloc(warnstack, pari_mainstack, rsize, vsize); pari_mainstack_use(pari_mainstack); } void paristack_setsize(size_t rsize, size_t vsize) { pari_mainstack_resize(pari_mainstack, rsize, vsize); pari_mainstack_use(pari_mainstack); } void parivstack_resize(ulong newsize) { size_t s; if (newsize && newsize < pari_mainstack->rsize) pari_err_DIM("stack sizes [parisizemax < parisize]"); if (newsize == pari_mainstack->vsize) return; evalstate_reset(); paristack_setsize(pari_mainstack->rsize, newsize); s = pari_mainstack->vsize ? pari_mainstack->vsize : pari_mainstack->rsize; if (DEBUGMEM) pari_warn(warner,"new maximum stack size = %lu (%.3f Mbytes)", s, s/1048576.); pari_init_errcatch(); cb_pari_err_recover(-1); } void paristack_newrsize(ulong newsize) { size_t s, vsize = pari_mainstack->vsize; if (!newsize) newsize = pari_mainstack->rsize << 1; if (newsize != pari_mainstack->rsize) pari_mainstack_resize(pari_mainstack, newsize, vsize); evalstate_reset(); s = pari_mainstack->rsize; if (DEBUGMEM) pari_warn(warner,"new stack size = %lu (%.3f Mbytes)", s, s/1048576.); pari_init_errcatch(); cb_pari_err_recover(-1); } void paristack_resize(ulong newsize) { long size = pari_mainstack->size; if (!newsize) newsize = 2 * size; newsize = minuu(newsize, pari_mainstack->vsize); if (newsize <= pari_mainstack->size) return; if (pari_mainstack_setsize(pari_mainstack, newsize)) { if (DEBUGMEM) pari_warn(warner, "increasing stack size to %lu", pari_mainstack->size); } else { pari_mainstack_setsize(pari_mainstack, size); pari_err(e_STACK); } } void parivstack_reset(void) { pari_mainstack_setsize(pari_mainstack, pari_mainstack->rsize); if (avma < pari_mainstack->bot) pari_err_BUG("parivstack_reset [avma < bot]"); } /* Enlarge the stack if needed such that the unused portion of the stack * (between bot and avma) is large enough to contain x longs. */ void new_chunk_resize(size_t x) { if (pari_mainstack->vsize==0 || x > (avma-pari_mainstack->vbot) / sizeof(long)) pari_err(e_STACK); while (x > (avma-pari_mainstack->bot) / sizeof(long)) paristack_resize(0); } /*********************************************************************/ /* PARI THREAD */ /*********************************************************************/ /* Initial PARI thread structure t with a stack of size s and * argument arg */ static void pari_thread_set_global(struct pari_global_state *gs) { setdebugvar(gs->debugvar); push_localbitprec(gs->bitprec); pari_set_primetab(gs->primetab); pari_set_seadata(gs->seadata); pari_set_varstate(gs->varpriority, &gs->varstate); } static void pari_thread_get_global(struct pari_global_state *gs) { gs->debugvar = getdebugvar(); gs->bitprec = get_localbitprec(); gs->primetab = primetab; gs->seadata = pari_get_seadata(); varstate_save(&gs->varstate); gs->varpriority = varpriority; } void pari_thread_alloc(struct pari_thread *t, size_t s, GEN arg) { pari_mainstack_alloc(warnstackthread, &t->st,s,0); pari_thread_get_global(&t->gs); t->data = arg; } /* Initial PARI thread structure t with a stack of size s and virtual size v * and argument arg */ void pari_thread_valloc(struct pari_thread *t, size_t s, size_t v, GEN arg) { pari_mainstack_alloc(warnstackthread, &t->st,s,v); pari_thread_get_global(&t->gs); t->data = arg; } void pari_thread_free(struct pari_thread *t) { pari_mainstack_free(&t->st); } void pari_thread_init(void) { long var; pari_stackcheck_init((void*)&var); pari_init_blocks(); pari_init_errcatch(); pari_init_rand(); pari_init_floats(); pari_init_hgm(); pari_init_parser(); pari_init_compiler(); pari_init_evaluator(); pari_init_files(); pari_init_ellcondfile(); } void pari_thread_close(void) { pari_thread_close_files(); pari_close_evaluator(); pari_close_compiler(); pari_close_parser(); pari_close_floats(); pari_close_hgm(); pari_close_blocks(); } GEN pari_thread_start(struct pari_thread *t) { pari_mainstack_use(&t->st); pari_thread_init(); pari_thread_set_global(&t->gs); mt_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(); } static void dflt_pari_quit(long err) { (void)err; /*do nothing*/; } /* 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; pari_mt_nbthreads = 0; cb_pari_quit = dflt_pari_quit; cb_pari_init_histfile = NULL; cb_pari_get_line_interactive = NULL; cb_pari_fgets_interactive = NULL; cb_pari_whatnow = NULL; cb_pari_handle_exception = NULL; cb_pari_err_handle = pari_err_display; cb_pari_pre_recover = NULL; cb_pari_break_loop = NULL; cb_pari_is_interactive = NULL; cb_pari_start_output = NULL; cb_pari_sigint = dflt_sigint_fun; cb_pari_long_help = NULL; if (init_opts&INIT_JMPm) cb_pari_err_recover = dflt_err_recover; pari_stackcheck_init(&u); pari_init_homedir(); if (init_opts&INIT_DFTm) { pari_init_defaults(); GP_DATA = default_gp_data(); pari_init_paths(); } pari_mainstack = (struct pari_mainstack *) malloc(sizeof(*pari_mainstack)); paristack_alloc(parisize, 0); init_universal_constants(); pari_PRIMES = NULL; if (!(init_opts&INIT_noPRIMEm)) { GP_DATA->primelimit = maxprime; pari_init_primes(GP_DATA->primelimit); } if (!(init_opts&INIT_noINTGMPm)) pari_kernel_init(); pari_init_graphics(); pari_thread_init(); pari_set_primetab(NULL); pari_set_seadata(NULL); pari_init_functions(); pari_init_export(); pari_var_init(); pari_init_timer(); pari_init_buffers(); (void)getabstime(); try_to_recover = 1; if (!(init_opts&INIT_noIMTm)) pari_mt_init(); if ((init_opts&INIT_SIGm)) pari_sig_init(pari_sighandler); } void pari_init(size_t parisize, ulong maxprime) { pari_init_opts(parisize, maxprime, INIT_JMPm | INIT_SIGm | INIT_DFTm); } void pari_close_opts(ulong init_opts) { long i; BLOCK_SIGINT_START; if ((init_opts&INIT_SIGm)) pari_sig_init(SIG_DFL); if (!(init_opts&INIT_noIMTm)) pari_mt_close(); pari_var_close(); /* must come before destruction of functions_hash */ 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; } } pari_close_mf(); pari_thread_close(); pari_close_export(); pari_close_files(); pari_close_homedir(); if (!(init_opts&INIT_noINTGMPm)) pari_kernel_close(); free((void*)functions_hash); free((void*)defaults_hash); if (pari_PRIMES) pari_close_primes(); free(current_logfile); free(current_psfile); pari_mainstack_free(pari_mainstack); free((void*)pari_mainstack); pari_stack_delete(&s_MODULES); if (pari_datadir) free(pari_datadir); if (init_opts&INIT_DFTm) { /* delete GP_DATA */ pari_close_paths(); if (GP_DATA->hist->v) free((void*)GP_DATA->hist->v); if (GP_DATA->pp->cmd) free((void*)GP_DATA->pp->cmd); if (GP_DATA->help) free((void*)GP_DATA->help); if (GP_DATA->plothsizes) free((void*)GP_DATA->plothsizes); if (GP_DATA->colormap) pari_free(GP_DATA->colormap); if (GP_DATA->graphcolors) pari_free(GP_DATA->graphcolors); free((void*)GP_DATA->prompt); free((void*)GP_DATA->prompt_cont); free((void*)GP_DATA->histfile); } 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->prettyp = GP_DATA->fmt->prettyp; rec->listloc = next_block; rec->iferr_env = iferr_env; rec->err_data = global_err_data; varstate_save(&rec->var); evalstate_save(&rec->eval); parsestate_save(&rec->parse); filestate_save(&rec->file); } void gp_context_restore(struct gp_context* rec) { long i; if (!try_to_recover) return; /* disable gp_context_restore() and SIGINT */ try_to_recover = 0; BLOCK_SIGINT_START if (DEBUGMEM>2) err_printf("entering recover(), loc = %ld\n", rec->listloc); evalstate_restore(&rec->eval); parsestate_restore(&rec->parse); filestate_restore(&rec->file); global_err_data = rec->err_data; iferr_env = rec->iferr_env; GP_DATA->fmt->prettyp = rec->prettyp; for (i = 0; i < functions_tblsz; i++) { entree *ep = functions_hash[i]; while (ep) { entree *EP = ep->next; switch(EpVALENCE(ep)) { case EpVAR: while (pop_val_if_newer(ep,rec->listloc)) /* empty */; break; case EpNEW: break; } ep = EP; } } varstate_restore(&rec->var); if (DEBUGMEM>2) err_printf("leaving recover()\n"); BLOCK_SIGINT_END try_to_recover = 1; } static void err_recover(long numerr) { if (cb_pari_pre_recover) cb_pari_pre_recover(numerr); evalstate_reset(); killallfiles(); pari_init_errcatch(); 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 user) { const char *gp_function_name; out_puts(pariErr, " *** "); if (!user && (gp_function_name = closure_func_err())) out_printf(pariErr, "%s: ", gp_function_name); else out_puts(pariErr, " "); } void pari_warn(int numerr, ...) { char *ch1; va_list ap; va_start(ap,numerr); err_init(); err_init_msg(numerr==warnuser || numerr==warnstack); switch (numerr) { case warnuser: out_puts(pariErr, "user warning: "); out_print1(pariErr, NULL, va_arg(ap, GEN), f_RAW); break; case warnmem: out_puts(pariErr, "collecting garbage in "); ch1=va_arg(ap, char*); out_vprintf(pariErr, ch1,ap); out_putc(pariErr, '.'); break; case warner: out_puts(pariErr, "Warning: "); ch1=va_arg(ap, char*); out_vprintf(pariErr, ch1,ap); out_putc(pariErr, '.'); break; case warnprec: out_vprintf(pariErr, "Warning: increasing prec in %s; new prec = %ld", ap); break; case warnfile: out_puts(pariErr, "Warning: failed to "), ch1 = va_arg(ap, char*); out_printf(pariErr, "%s: %s", ch1, va_arg(ap, char*)); break; case warnstack: case warnstackthread: { ulong s = va_arg(ap, ulong); char buf[128]; const char * stk = numerr == warnstackthread || mt_is_thread() ? "thread": "PARI"; sprintf(buf,"Warning: not enough memory, new %s stack %lu", stk, s); out_puts(pariErr,buf); break; } } va_end(ap); out_term_color(pariErr, c_NONE); out_putc(pariErr, '\n'); pariErr->flush(); } void pari_sigint(const char *time_s) { int recover=0; BLOCK_SIGALRM_START err_init(); mt_break_recover(); closure_err(0); err_init_msg(0); out_puts(pariErr, "user interrupt after "); out_puts(pariErr, time_s); out_term_color(pariErr, c_NONE); pariErr->flush(); if (cb_pari_handle_exception) recover = cb_pari_handle_exception(-1); if (!recover && !block) PARI_SIGINT_pending = 0; BLOCK_SIGINT_END if (!recover) err_recover(e_MISC); } #define retmkerr2(x,y)\ do { GEN _v = cgetg(3, t_ERROR);\ _v[1] = (x);\ gel(_v,2) = (y); return _v; } while(0) #define retmkerr3(x,y,z)\ do { GEN _v = cgetg(4, t_ERROR);\ _v[1] = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z); return _v; } while(0) #define retmkerr4(x,y,z,t)\ do { GEN _v = cgetg(5, t_ERROR);\ _v[1] = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z);\ gel(_v,4) = (t); return _v; } while(0) #define retmkerr5(x,y,z,t,u)\ do { GEN _v = cgetg(6, t_ERROR);\ _v[1] = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z);\ gel(_v,4) = (t);\ gel(_v,5) = (u); return _v; } while(0) #define retmkerr6(x,y,z,t,u,v)\ do { GEN _v = cgetg(7, t_ERROR);\ _v[1] = (x);\ gel(_v,2) = (y);\ gel(_v,3) = (z);\ gel(_v,4) = (t);\ gel(_v,5) = (u);\ gel(_v,6) = (v); return _v; } while(0) static GEN pari_err2GEN(long numerr, va_list ap) { switch ((enum err_list) numerr) { case e_SYNTAX: { const char *msg = va_arg(ap, char*); const char *s = va_arg(ap,char *); const char *entry = va_arg(ap,char *); retmkerr3(numerr,strtoGENstr(msg), mkvecsmall2((long)s,(long)entry)); } case e_MISC: case e_ALARM: { const char *ch1 = va_arg(ap, char*); retmkerr2(numerr, gvsprintf(ch1,ap)); } case e_NOTFUNC: case e_USER: retmkerr2(numerr,va_arg(ap, GEN)); case e_FILE: { const char *f = va_arg(ap, const char*); retmkerr3(numerr, strtoGENstr(f), strtoGENstr(va_arg(ap, char*))); } case e_FILEDESC: { const char *f = va_arg(ap, const char*); retmkerr3(numerr, strtoGENstr(f), stoi(va_arg(ap, long))); } case e_OVERFLOW: case e_IMPL: case e_DIM: case e_CONSTPOL: case e_ROOTS0: case e_FLAG: case e_PREC: case e_BUG: case e_ARCH: case e_PACKAGE: retmkerr2(numerr, strtoGENstr(va_arg(ap, char*))); case e_MODULUS: case e_VAR: { const char *f = va_arg(ap, const char*); GEN x = va_arg(ap, GEN); GEN y = va_arg(ap, GEN); retmkerr4(numerr, strtoGENstr(f), x,y); } case e_INV: case e_IRREDPOL: case e_PRIME: case e_SQRTN: case e_TYPE: { const char *f = va_arg(ap, const char*); GEN x = va_arg(ap, GEN); retmkerr3(numerr, strtoGENstr(f), x); } case e_COPRIME: case e_OP: case e_TYPE2: { const char *f = va_arg(ap, const char*); GEN x = va_arg(ap, GEN); GEN y = va_arg(ap, GEN); retmkerr4(numerr,strtoGENstr(f),x,y); } case e_COMPONENT: { const char *f= va_arg(ap, const char *); const char *op = va_arg(ap, const char *); GEN l = va_arg(ap, GEN); GEN x = va_arg(ap, GEN); retmkerr5(numerr,strtoGENstr(f),strtoGENstr(op),l,x); } case e_DOMAIN: { const char *f = va_arg(ap, const char*); const char *v = va_arg(ap, const char *); const char *op = va_arg(ap, const char *); GEN l = va_arg(ap, GEN); GEN x = va_arg(ap, GEN); retmkerr6(numerr,strtoGENstr(f),strtoGENstr(v),strtoGENstr(op),l,x); } case e_PRIORITY: { const char *f = va_arg(ap, const char*); GEN x = va_arg(ap, GEN); const char *op = va_arg(ap, const char *); long v = va_arg(ap, long); retmkerr5(numerr,strtoGENstr(f),x,strtoGENstr(op),stoi(v)); } case e_MAXPRIME: retmkerr2(numerr, utoi(va_arg(ap, ulong))); case e_STACK: return err_e_STACK; case e_STACKTHREAD: retmkerr3(numerr, utoi(va_arg(ap, ulong)), utoi(va_arg(ap, ulong))); default: return mkerr(numerr); } } static char * type_dim(GEN x) { char *v = stack_malloc(64); switch(typ(x)) { case t_MAT: { long l = lg(x), r = (l == 1)? 1: lgcols(x); sprintf(v, "t_MAT (%ld x %ld)", r-1,l-1); break; } case t_COL: sprintf(v, "t_COL (%ld elts)", lg(x)-1); break; case t_VEC: sprintf(v, "t_VEC (%ld elts)", lg(x)-1); break; default: v = (char*)type_name(typ(x)); } return v; } static char * gdisplay(GEN x) { char *s = GENtostr_raw(x); if (strlen(s) < 1600) return s; if (! GP_DATA->breakloop) return (char*)"(...)"; return stack_sprintf("\n *** (...) Huge %s omitted; you can access it via dbg_err()", type_name(typ(x))); } char * pari_err2str(GEN e) { long numerr = err_get_num(e); switch ((enum err_list) numerr) { case e_ALARM: return pari_sprintf("alarm interrupt after %Ps.",gel(e,2)); case e_MISC: return pari_sprintf("%Ps.",gel(e,2)); case e_ARCH: return pari_sprintf("sorry, '%Ps' not available on this system.",gel(e,2)); case e_BUG: return pari_sprintf("bug in %Ps, please report.",gel(e,2)); case e_CONSTPOL: return pari_sprintf("constant polynomial in %Ps.", gel(e,2)); case e_COPRIME: return pari_sprintf("elements not coprime in %Ps:\n %s\n %s", gel(e,2), gdisplay(gel(e,3)), gdisplay(gel(e,4))); case e_DIM: return pari_sprintf("inconsistent dimensions in %Ps.", gel(e,2)); case e_FILE: return pari_sprintf("error opening %Ps: `%Ps'.", gel(e,2), gel(e,3)); case e_FILEDESC: return pari_sprintf("invalid file descriptor in %Ps [%Ps]", gel(e,2), gel(e,3)); case e_FLAG: return pari_sprintf("invalid flag in %Ps.", gel(e,2)); case e_IMPL: return pari_sprintf("sorry, %Ps is not yet implemented.", gel(e,2)); case e_PACKAGE: return pari_sprintf("package %Ps is required, please install it.", gel(e,2)); case e_INV: return pari_sprintf("impossible inverse in %Ps: %s.", gel(e,2), gdisplay(gel(e,3))); case e_IRREDPOL: return pari_sprintf("not an irreducible polynomial in %Ps: %s.", gel(e,2), gdisplay(gel(e,3))); case e_MAXPRIME: { const char * msg = "not enough precomputed primes"; ulong c = itou(gel(e,2)); if (c) return pari_sprintf("%s, need primelimit ~ %lu.",msg, c); else return pari_strdup(msg); } case e_MEM: return pari_strdup("not enough memory"); case e_MODULUS: { GEN x = gel(e,3), y = gel(e,4); return pari_sprintf("inconsistent moduli in %Ps: %s != %s", gel(e,2), gdisplay(x), gdisplay(y)); } case e_NONE: return NULL; case e_NOTFUNC: return pari_strdup("not a function in function call"); case e_OP: case e_TYPE2: { pari_sp av = avma; char *v; const char *f, *op = GSTR(gel(e,2)); const char *what = numerr == e_OP? "inconsistent": "forbidden"; GEN x = gel(e,3); GEN y = gel(e,4); switch(*op) { case '+': f = "addition"; break; case '*': f = "multiplication"; break; case '/': case '%': case '\\': f = "division"; break; case '=': op = "-->"; f = "assignment"; break; default: f = op; op = ","; break; } v = pari_sprintf("%s %s %s %s %s.", what,f,type_dim(x),op,type_dim(y)); set_avma(av); return v; } case e_COMPONENT: { const char *f= GSTR(gel(e,2)); const char *op= GSTR(gel(e,3)); GEN l = gel(e,4); if (!*f) return pari_sprintf("nonexistent component: index %s %Ps",op,l); return pari_sprintf("nonexistent component in %s: index %s %Ps",f,op,l); } case e_DOMAIN: { const char *f = GSTR(gel(e,2)); const char *v = GSTR(gel(e,3)); const char *op= GSTR(gel(e,4)); GEN l = gel(e,5); if (!*op) return pari_sprintf("domain error in %s: %s out of range",f,v); return pari_sprintf("domain error in %s: %s %s %Ps",f,v,op,l); } case e_PRIORITY: { const char *f = GSTR(gel(e,2)); long vx = gvar(gel(e,3)); const char *op= GSTR(gel(e,4)); long v = itos(gel(e,5)); return pari_sprintf("incorrect priority in %s: variable %Ps %s %Ps",f, pol_x(vx), op, pol_x(v)); } case e_OVERFLOW: return pari_sprintf("overflow in %Ps.", gel(e,2)); case e_PREC: return pari_sprintf("precision too low in %Ps.", gel(e,2)); case e_PRIME: return pari_sprintf("not a prime number in %Ps: %s.", gel(e,2), gdisplay(gel(e,3))); case e_ROOTS0: return pari_sprintf("zero polynomial in %Ps.", gel(e,2)); case e_SQRTN: return pari_sprintf("not an n-th power residue in %Ps: %s.", gel(e,2), gdisplay(gel(e,3))); case e_STACK: case e_STACKTHREAD: { const char *what = numerr == e_STACK? "PARI": "thread"; const char *var = numerr == e_STACK? "parisizemax": "threadsizemax"; size_t s = numerr == e_STACK? pari_mainstack->vsize: GP_DATA->threadsizemax; char *hint = (char *) pari_malloc(512*sizeof(char)); char *buf = (char *) pari_malloc(512*sizeof(char)); if (s) sprintf(hint,"you can increase '%s' using default()", var); else { s = (numerr != e_STACK || !GP_DATA->threadsize)? pari_mainstack->rsize : GP_DATA->threadsize; sprintf(hint,"set '%s' to a nonzero value in your GPRC", var); } sprintf(buf, "the %s stack overflows !\n" " current stack size: %lu (%.3f Mbytes)\n [hint] %s\n", what, (ulong)s, (double)s/1048576., hint); return buf; } case e_SYNTAX: return pari_strdup(GSTR(gel(e,2))); case e_TYPE: return pari_sprintf("incorrect type in %Ps (%s).", gel(e,2), type_name(typ(gel(e,3)))); case e_USER: return pari_sprint0("user error: ", gel(e,2), f_RAW); case e_VAR: { GEN x = gel(e,3), y = gel(e,4); return pari_sprintf("inconsistent variables in %Ps, %Ps != %Ps.", gel(e,2), pol_x(varn(x)), pol_x(varn(y))); } } return NULL; /*LCOV_EXCL_LINE*/ } int pari_err_display(GEN err) { long numerr=err_get_num(err); err_init(); if (numerr==e_SYNTAX) { const char *msg = GSTR(gel(err,2)); const char *s = (const char *) gmael(err,3,1); const char *entry = (const char *) gmael(err,3,2); print_errcontext(pariErr, msg, s, entry); } else { char *s; closure_err(0); err_init_msg(numerr==e_USER); s = pari_err2str(err); pariErr->puts(s); pari_free(s); if (numerr==e_NOTFUNC) { GEN fun = gel(err,2); if (gequalX(fun)) { entree *ep = varentries[varn(fun)]; const char *t = ep->name; if (cb_pari_whatnow) cb_pari_whatnow(pariErr,t,1); } } } out_term_color(pariErr, c_NONE); pariErr->flush(); return 0; } void pari_err(int numerr, ...) { va_list ap; GEN E; va_start(ap,numerr); if (numerr) E = pari_err2GEN(numerr,ap); else { E = va_arg(ap,GEN); numerr = err_get_num(E); } global_err_data = E; if (*iferr_env) longjmp(*iferr_env, numerr); mt_err_recover(numerr); va_end(ap); if (cb_pari_err_handle && cb_pari_err_handle(E)) return; if (cb_pari_handle_exception && cb_pari_handle_exception(numerr)) return; err_recover(numerr); } GEN pari_err_last(void) { return global_err_data; } const char * numerr_name(long numerr) { switch ((enum err_list) numerr) { case e_ALARM: return "e_ALARM"; case e_ARCH: return "e_ARCH"; case e_BUG: return "e_BUG"; case e_COMPONENT: return "e_COMPONENT"; case e_CONSTPOL: return "e_CONSTPOL"; case e_COPRIME: return "e_COPRIME"; case e_DIM: return "e_DIM"; case e_DOMAIN: return "e_DOMAIN"; case e_FILE: return "e_FILE"; case e_FILEDESC: return "e_FILEDESC"; case e_FLAG: return "e_FLAG"; case e_IMPL: return "e_IMPL"; case e_INV: return "e_INV"; case e_IRREDPOL: return "e_IRREDPOL"; case e_MAXPRIME: return "e_MAXPRIME"; case e_MEM: return "e_MEM"; case e_MISC: return "e_MISC"; case e_MODULUS: return "e_MODULUS"; case e_NONE: return "e_NONE"; case e_NOTFUNC: return "e_NOTFUNC"; case e_OP: return "e_OP"; case e_OVERFLOW: return "e_OVERFLOW"; case e_PACKAGE: return "e_PACKAGE"; case e_PREC: return "e_PREC"; case e_PRIME: return "e_PRIME"; case e_PRIORITY: return "e_PRIORITY"; case e_ROOTS0: return "e_ROOTS0"; case e_SQRTN: return "e_SQRTN"; case e_STACK: return "e_STACK"; case e_SYNTAX: return "e_SYNTAX"; case e_STACKTHREAD: return "e_STACKTHREAD"; case e_TYPE2: return "e_TYPE2"; case e_TYPE: return "e_TYPE"; case e_USER: return "e_USER"; case e_VAR: return "e_VAR"; } return "invalid error number"; } long name_numerr(const char *s) { if (!strcmp(s,"e_ALARM")) return e_ALARM; if (!strcmp(s,"e_ARCH")) return e_ARCH; if (!strcmp(s,"e_BUG")) return e_BUG; if (!strcmp(s,"e_COMPONENT")) return e_COMPONENT; if (!strcmp(s,"e_CONSTPOL")) return e_CONSTPOL; if (!strcmp(s,"e_COPRIME")) return e_COPRIME; if (!strcmp(s,"e_DIM")) return e_DIM; if (!strcmp(s,"e_DOMAIN")) return e_DOMAIN; if (!strcmp(s,"e_FILE")) return e_FILE; if (!strcmp(s,"e_FILEDESC")) return e_FILEDESC; if (!strcmp(s,"e_FLAG")) return e_FLAG; if (!strcmp(s,"e_IMPL")) return e_IMPL; if (!strcmp(s,"e_INV")) return e_INV; if (!strcmp(s,"e_IRREDPOL")) return e_IRREDPOL; if (!strcmp(s,"e_MAXPRIME")) return e_MAXPRIME; if (!strcmp(s,"e_MEM")) return e_MEM; if (!strcmp(s,"e_MISC")) return e_MISC; if (!strcmp(s,"e_MODULUS")) return e_MODULUS; if (!strcmp(s,"e_NONE")) return e_NONE; if (!strcmp(s,"e_NOTFUNC")) return e_NOTFUNC; if (!strcmp(s,"e_OP")) return e_OP; if (!strcmp(s,"e_OVERFLOW")) return e_OVERFLOW; if (!strcmp(s,"e_PACKAGE")) return e_PACKAGE; if (!strcmp(s,"e_PREC")) return e_PREC; if (!strcmp(s,"e_PRIME")) return e_PRIME; if (!strcmp(s,"e_PRIORITY")) return e_PRIORITY; if (!strcmp(s,"e_ROOTS0")) return e_ROOTS0; if (!strcmp(s,"e_SQRTN")) return e_SQRTN; if (!strcmp(s,"e_STACK")) return e_STACK; if (!strcmp(s,"e_SYNTAX")) return e_SYNTAX; if (!strcmp(s,"e_TYPE")) return e_TYPE; if (!strcmp(s,"e_TYPE2")) return e_TYPE2; if (!strcmp(s,"e_USER")) return e_USER; if (!strcmp(s,"e_VAR")) return e_VAR; pari_err(e_MISC,"unknown error name"); return -1; /* LCOV_EXCL_LINE */ } GEN errname(GEN err) { if (typ(err)!=t_ERROR) pari_err_TYPE("errname",err); return strtoGENstr(numerr_name(err_get_num(err))); } /* Try f (trapping error e), recover using r (break_loop, if NULL) */ GEN trap0(const char *e, GEN r, GEN f) { long numerr = CATCH_ALL; GEN x; if (!e || !*e) numerr = CATCH_ALL; else numerr = name_numerr(e); if (!f) { pari_warn(warner,"default handlers are no longer supported --> ignored"); return gnil; } x = closure_trapgen(f, numerr); if (x == (GEN)1L) x = r? closure_evalgen(r): gnil; return x; } /*******************************************************************/ /* */ /* CLONING & COPY */ /* Replicate an existing GEN */ /* */ /*******************************************************************/ /* lontyp[tx] = 0 (non recursive type) or number of codewords for type tx */ const long lontyp[] = { 0,0,0,1,1,2,1,2,1,1, 2,2,0,1,1,1,1,1,1,1, 2,0,0,2,2,1 }; static GEN list_internal_copy(GEN z, long nmax) { long i, l; GEN a; if (!z) return NULL; l = lg(z); a = newblock(nmax+1); for (i = 1; i < l; i++) gel(a,i) = gel(z,i)? gclone(gel(z,i)): gen_0; a[0] = z[0]; setisclone(a); 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 */ y[1] = evaltyp(list_typ(x))|evallg(nmax); list_data(y) = list_internal_copy(L, nmax); } /* transform a non-malloced list (e.g. from gtolist or gtomap) to a malloced * list suitable for listput */ GEN listinit(GEN x) { GEN y = cgetg(3, t_LIST); listassign(x, y); return y; } /* copy list on the PARI stack */ GEN listcopy(GEN x) { GEN y = mklist(), L = list_data(x); if (L) list_data(y) = gcopy(L); y[1] = evaltyp(list_typ(x)); 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 (; irebase = &shiftaddress; 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_canon(x); GENbin *p = (GENbin*)pari_malloc(sizeof(GENbin) + t*sizeof(long)); pari_sp AVMA = (pari_sp)(GENbinbase(p) + t); p->rebase = &shiftaddress_canon; 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 = gsizeclone(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) { GEN L = (GEN)((long)Lx+dec); shiftaddress_canon(L, dec); list_data(x) = gcopy(L); } break; } default: /* Fall through */ lx = lg(x); for (i=lontyp[tx]; i= lg(v)) pari_err_TYPE("obj_check", S); O = gel(v,K); return isintzero(O)? NULL: O; } GEN obj_checkbuild(GEN S, long tag, GEN (*build)(GEN)) { GEN O = obj_check(S, tag); if (!O) { pari_sp av = avma; O = obj_insert(S, tag, build(S)); set_avma(av); } return O; } GEN obj_checkbuild_prec(GEN S, long tag, GEN (*build)(GEN,long), long (*pr)(GEN), long prec) { pari_sp av = avma; GEN w = obj_check(S, tag); if (!w || pr(w) < prec) w = obj_insert(S, tag, build(S, prec)); set_avma(av); return gcopy(w); } GEN obj_checkbuild_realprec(GEN S, long tag, GEN (*build)(GEN,long), long prec) { return obj_checkbuild_prec(S,tag,build,gprecision,prec); } GEN obj_checkbuild_padicprec(GEN S, long tag, GEN (*build)(GEN,long), long prec) { return obj_checkbuild_prec(S,tag,build,padicprec_relative,prec); } /* Reset S [last position], freeing all clones */ void obj_free(GEN S) { GEN v = veclast(S); long i; if (typ(v) != t_VEC) pari_err_TYPE("obj_free", S); for (i = 1; i < lg(v); i++) { GEN o = gel(v,i); gel(v,i) = gen_0; gunclone_deep(o); } } /*******************************************************************/ /* */ /* STACK MANAGEMENT */ /* */ /*******************************************************************/ INLINE void dec_gerepile(pari_sp *x, pari_sp av0, pari_sp av, pari_sp tetpil, size_t dec) { if (*x < av && *x >= av0) { /* update address if in stack */ if (*x < tetpil) *x += dec; else pari_err_BUG("gerepile, significant pointers lost"); } } void gerepileallsp(pari_sp av, pari_sp tetpil, int n, ...) { const pari_sp av0 = avma; const size_t dec = av-tetpil; int i; va_list a; va_start(a, n); (void)gerepile(av,tetpil,NULL); for (i=0; i av) { pari_warn(warner,"bad object %Ps",x); return 0; } tx = typ(x); if (! is_recursive_t(tx)) return 1; lx = lg(x); for (i=lontyp[tx]; iltop in gerepile"); /* dec_gerepile(&q, av0, av, tetpil, dec), saving 1 comparison */ if (q >= (GEN)av0 && q < (GEN)tetpil) q = (GEN) (((pari_sp)q) + dec); for (x = (GEN)av, a = (GEN)tetpil; a > (GEN)av0; ) *--x = *--a; set_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 dbg_fill_stack(void) { #ifdef LONG_IS_64BIT const long JUNK = 0xBADC0FFEE0DDF00D; #else const long JUNK = 0xDEADBEEF; #endif GEN x = ((GEN)pari_mainstack->bot); while (x < (GEN)avma) *x++ = JUNK; } void debug_stack(void) { pari_sp top = pari_mainstack->top, bot = pari_mainstack->bot; GEN z; err_printf("bot=0x%lx\ttop=0x%lx\tavma=0x%lx\n", bot, top, avma); for (z = ((GEN)top)-1; z >= (GEN)avma; z--) err_printf("%p:\t0x%lx\t%lu\n",z,*z,*z); } void setdebugvar(long n) { DEBUGVAR=n; } long getdebugvar(void) { return DEBUGVAR; } long getstack(void) { return pari_mainstack->top-avma; } /*******************************************************************/ /* */ /* timer_delay */ /* */ /*******************************************************************/ #if defined(USE_CLOCK_GETTIME) #if defined(_POSIX_THREAD_CPUTIME) static THREAD clockid_t time_type = CLOCK_THREAD_CPUTIME_ID; #else static const THREAD clockid_t time_type = CLOCK_PROCESS_CPUTIME_ID; #endif static void pari_init_timer(void) { #if defined(_POSIX_THREAD_CPUTIME) time_type = CLOCK_PROCESS_CPUTIME_ID; #endif } void timer_start(pari_timer *T) { struct timespec t; clock_gettime(time_type,&t); T->us = t.tv_nsec / 1000; T->s = t.tv_sec; } #elif defined(USE_GETRUSAGE) #ifdef RUSAGE_THREAD static THREAD int rusage_type = RUSAGE_THREAD; #else static const THREAD int rusage_type = RUSAGE_SELF; #endif /*RUSAGE_THREAD*/ static void pari_init_timer(void) { #ifdef RUSAGE_THREAD rusage_type = RUSAGE_SELF; #endif } void timer_start(pari_timer *T) { struct rusage r; getrusage(rusage_type,&r); T->us = r.ru_utime.tv_usec; T->s = r.ru_utime.tv_sec; } #elif defined(USE_FTIME) static void pari_init_timer(void) { } void timer_start(pari_timer *T) { struct timeb t; ftime(&t); T->us = ((long)t.millitm) * 1000; T->s = t.time; } #else static void _get_time(pari_timer *T, long Ticks, long TickPerSecond) { T->us = (long) ((Ticks % TickPerSecond) * (1000000. / TickPerSecond)); T->s = Ticks / TickPerSecond; } # ifdef USE_TIMES static void pari_init_timer(void) { } 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(_WIN32) static void pari_init_timer(void) { } void timer_start(pari_timer *T) { _get_time(T, win32_timer(), 1000); } # else # include # ifndef CLOCKS_PER_SEC # define CLOCKS_PER_SEC 1000000 /* may be false on YOUR system */ # endif static void pari_init_timer(void) { } void timer_start(pari_timer *T) { _get_time(T, clock(), CLOCKS_PER_SEC); } # endif #endif /* round microseconds to milliseconds */ static long rndus(long x) { return (x + 500) / 1000; } static long timer_aux(pari_timer *T, pari_timer *U, void (*settime)(pari_timer *)) { long s = T->s, us = T->us; settime(U); return 1000 * (U->s - s) + rndus(U->us - us); } /* return delay, set timer checkpoint */ long timer_delay(pari_timer *T) { return timer_aux(T, T, &timer_start); } /* return delay, don't set checkpoint */ long timer_get(pari_timer *T) {pari_timer t; return timer_aux(T, &t, &timer_start);} static void timer_vprintf(pari_timer *T, const char *format, va_list args) { out_puts(pariErr, "Time "); out_vprintf(pariErr, format,args); out_printf(pariErr, ": %ld\n", timer_delay(T)); pariErr->flush(); } void timer_printf(pari_timer *T, const char *format, ...) { va_list args; va_start(args, format); timer_vprintf(T, format, args); va_end(args); } long timer(void) { static THREAD pari_timer T; return timer_delay(&T);} long gettime(void) { static THREAD pari_timer T; return timer_delay(&T);} static THREAD pari_timer timer2_T, abstimer_T; long timer2(void) { return timer_delay(&timer2_T);} void msgtimer(const char *format, ...) { va_list args; va_start(args, format); timer_vprintf(&timer2_T, format, args); va_end(args); } long getabstime(void) { return timer_get(&abstimer_T);} void walltimer_start(pari_timer *ti) { #if defined(USE_CLOCK_GETTIME) struct timespec t; if (!clock_gettime(CLOCK_REALTIME,&t)) { ti->s = t.tv_sec; ti->us = rndus(t.tv_nsec); return; } #elif defined(USE_GETTIMEOFDAY) struct timeval tv; if (!gettimeofday(&tv, NULL)) { ti->s = tv.tv_sec; ti->us = tv.tv_usec; return; } #elif defined(USE_FTIMEFORWALLTIME) struct timeb tp; if (!ftime(&tp)) { ti->s = tp.time; ti->us = tp.millitm*1000; return; } #endif timer_start(ti); } /* return delay, set timer checkpoint */ long walltimer_delay(pari_timer *T) { return timer_aux(T, T, &walltimer_start); } /* return delay, don't set checkpoint */ long walltimer_get(pari_timer *T) { pari_timer t; return timer_aux(T, &t, &walltimer_start); } static GEN timetoi(ulong s, ulong m) { pari_sp av = avma; return gerepileuptoint(av, addiu(muluu(s, 1000), m)); } GEN getwalltime(void) { pari_timer ti; walltimer_start(&ti); return timetoi(ti.s, rndus(ti.us)); } /*******************************************************************/ /* */ /* FUNCTIONS KNOWN TO THE ANALYZER */ /* */ /*******************************************************************/ GEN setdebug(const char *s, long n) { long i, l = numberof(pari_DEBUGLEVEL_str); GEN V, V1, V2; if (s) { if (n > 20) pari_err_DOMAIN("setdebug", "n", ">", utoipos(20), stoi(n)); for (i = 0; i < l; i++) if (!strcmp(s, pari_DEBUGLEVEL_str[i])) break; if (i == l) pari_err_DOMAIN("setdebug", s, "not a valid", strtoGENstr("debug domain"), strtoGENstr(s)); if (n >= 0) { *pari_DEBUGLEVEL_ptr[i] = n; return gnil; } return stoi(*pari_DEBUGLEVEL_ptr[i]); } V = cgetg(3,t_MAT); V1 = gel(V,1) = cgetg(l+1, t_COL); V2 = gel(V,2) = cgetg(l+1, t_COL); for (i = 0; i < l; i++) { gel(V1, i+1) = strtoGENstr(pari_DEBUGLEVEL_str[i]); gel(V2, i+1) = stoi(*pari_DEBUGLEVEL_ptr[i]); } return V; } GEN pari_version(void) { const ulong mask = (1UL<>= PARI_VERSION_SHIFT; minor = n & mask; n >>= PARI_VERSION_SHIFT; major = n; if (*paricfg_vcsversion) { const char *ver = paricfg_vcsversion; const char *s = strchr(ver, '-'); char t[8]; const long len = s-ver; GEN v; if (!s || len > 6) pari_err_BUG("pari_version()"); /* paranoia */ memcpy(t, ver, len); t[len] = 0; v = cgetg(6, t_VEC); gel(v,1) = utoi(major); gel(v,2) = utoi(minor); gel(v,3) = utoi(patch); gel(v,4) = stoi( atoi(t) ); gel(v,5) = strtoGENstr(s+1); return v; } else { GEN v = cgetg(4, t_VEC); gel(v,1) = utoi(major); gel(v,2) = utoi(minor); gel(v,3) = utoi(patch); return v; } } /* List of GP functions: generated from the description system. * Format (struct entree) : * char *name : name (under GP). * ulong valence: (EpNEW, EpALIAS,EpVAR, EpINSTALL)|EpSTATIC * void *value : For PREDEFINED FUNCTIONS: C function to call. * For USER FUNCTIONS: pointer to defining data (block) = * entree*: NULL, list of entree (arguments), NULL * char* : function text * long menu : which help section do we belong to * 1: Standard monadic or dyadic OPERATORS * 2: CONVERSIONS and similar elementary functions * 3: functions related to COMBINATORICS * 4: TRANSCENDENTAL functions, etc. * char *code : GP prototype, aka Parser Code (see libpari's manual) * if NULL, use valence instead. * char *help : short help text (init to NULL). * void *pvalue : push_val history. * long arity : maximum number of arguments. * entree *next : next entree (init to NULL, used in hashing code). */ #include "init.h" #include "default.h" pari-2.17.2/src/language/eval.c0000644000175000017500000022067314760123736014654 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; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #include "anal.h" #include "opcode.h" /********************************************************************/ /* */ /* break/next/return handling */ /* */ /********************************************************************/ static THREAD long br_status, br_count; static THREAD GEN br_res; long loop_break(void) { switch(br_status) { case br_MULTINEXT : if (! --br_count) br_status = br_NEXT; return 1; case br_BREAK : if (! --br_count) br_status = br_NONE; /* fall through */ case br_RETURN: return 1; case br_NEXT: br_status = br_NONE; /* fall through */ } return 0; } static void reset_break(void) { br_status = br_NONE; if (br_res) { gunclone_deep(br_res); br_res = NULL; } } GEN return0(GEN x) { GEN y = br_res; br_res = (x && x != gnil)? gcloneref(x): NULL; guncloneNULL_deep(y); br_status = br_RETURN; return NULL; } GEN next0(long n) { if (n < 1) pari_err_DOMAIN("next", "n", "<", gen_1, stoi(n)); if (n == 1) br_status = br_NEXT; else { br_count = n-1; br_status = br_MULTINEXT; } return NULL; } GEN break0(long n) { if (n < 1) pari_err_DOMAIN("break", "n", "<", gen_1, stoi(n)); br_count = n; br_status = br_BREAK; return NULL; } /*******************************************************************/ /* */ /* VARIABLES */ /* */ /*******************************************************************/ /* As a rule, ep->value is a clone (COPY). push_val and pop_val are private * functions for use in sumiter: we want a temporary ep->value, which is NOT * a clone (PUSH), to avoid unnecessary copies. */ enum {PUSH_VAL = 0, COPY_VAL = 1, DEFAULT_VAL = 2, REF_VAL = 3}; /* ep->args is the stack of old values (INITIAL if initial value, from * installep) */ typedef struct var_cell { struct var_cell *prev; /* cell attached 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* attached to 'value', to be restored * by pop_val */ } var_cell; #define INITIAL NULL /* Push x on value stack attached 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) { GEN old_val = (GEN) ep->value; /* protect against SIGINT */ ep->value = v->value; if (v->flag == COPY_VAL) gunclone_deep(old_val); ep->pvalue = (char*) v->prev; ep->valence=v->valence; pari_free((void*)v); } } void freeep(entree *ep) { if (EpSTATIC(ep)) return; /* gp function loaded at init time */ if (ep->help) {pari_free((void*)ep->help); ep->help=NULL;} if (ep->code) {pari_free((void*)ep->code); ep->code=NULL;} switch(EpVALENCE(ep)) { case EpVAR: while (ep->pvalue!=INITIAL) pop_val(ep); break; case EpALIAS: killblock((GEN)ep->value); ep->value=NULL; break; } } INLINE void pushvalue(entree *ep, GEN x) { new_val_cell(ep, x, COPY_VAL); } INLINE void zerovalue(entree *ep) { var_cell *v = (var_cell*) pari_malloc(sizeof(var_cell)); v->value = (GEN)ep->value; v->prev = (var_cell*) ep->pvalue; v->flag = COPY_VAL; v->valence= ep->valence; ep->value = gen_0; ep->pvalue= (char*)v; ep->valence=EpVAR; } /* as above IF ep->value was PUSHed, or was created after block number 'loc' return 0 if not deleted, 1 otherwise [for recover()] */ int pop_val_if_newer(entree *ep, long loc) { var_cell *v = (var_cell*) ep->pvalue; if (v == INITIAL) return 0; if (v->flag == COPY_VAL && !pop_entree_block(ep, loc)) return 0; ep->value = v->value; ep->pvalue= (char*) v->prev; ep->valence=v->valence; pari_free((void*)v); return 1; } /* set new value of ep directly to val (COPY), do not save last value unless * it's INITIAL. */ void changevalue(entree *ep, GEN x) { var_cell *v = (var_cell*) ep->pvalue; if (v == INITIAL) new_val_cell(ep, x, COPY_VAL); else { GEN old_val = (GEN) ep->value; /* beware: gunclone_deep may destroy old x */ ep->value = (void *) gclone(x); if (v->flag == COPY_VAL) gunclone_deep(old_val); else v->flag = COPY_VAL; } } INLINE GEN copyvalue(entree *ep) { var_cell *v = (var_cell*) ep->pvalue; if (v && v->flag != COPY_VAL) { ep->value = (void*) gclone((GEN)ep->value); v->flag = COPY_VAL; } return (GEN) ep->value; } INLINE void err_var(GEN x) { pari_err_TYPE("evaluator [variable name expected]", x); } enum chk_VALUE { chk_ERROR, chk_NOCREATE, chk_CREATE }; INLINE void checkvalue(entree *ep, enum chk_VALUE flag) { if (mt_is_thread()) pari_err(e_MISC,"mt: attempt to change exported variable '%s'",ep->name); if (ep->valence==EpNEW) switch(flag) { case chk_ERROR: /* Do nothing until we can report a meaningful error message The extra variable will be cleaned-up anyway */ case chk_CREATE: pari_var_create(ep); ep->valence = EpVAR; ep->value = initial_value(ep); break; case chk_NOCREATE: break; } else if (ep->valence!=EpVAR) pari_err(e_MISC, "attempt to change built-in %s", ep->name); } INLINE GEN checkvalueptr(entree *ep) { checkvalue(ep, chk_NOCREATE); return ep->valence==EpNEW? gen_0: (GEN)ep->value; } /* make GP variables safe for set_avma(top) */ static void lvar_make_safe(void) { long n; entree *ep; for (n = 0; n < functions_tblsz; n++) for (ep = functions_hash[n]; ep; ep = ep->next) if (EpVALENCE(ep) == EpVAR) { /* make sure ep->value is a COPY */ var_cell *v = (var_cell*)ep->pvalue; if (v && v->flag == PUSH_VAL) { GEN x = (GEN)ep->value; if (x) changevalue(ep, (GEN)ep->value); else pop_val(ep); } } } static void check_array_index(long c, long l) { if (c < 1) pari_err_COMPONENT("", "<", gen_1, stoi(c)); if (c >= l) pari_err_COMPONENT("", ">", stoi(l-1), stoi(c)); } GEN* safegel(GEN x, long l) { if (!is_matvec_t(typ(x))) pari_err_TYPE("safegel",x); check_array_index(l, lg(x)); return &(gel(x,l)); } GEN* safelistel(GEN x, long l) { GEN d; if (typ(x)!=t_LIST || list_typ(x)!=t_LIST_RAW) pari_err_TYPE("safelistel",x); d = list_data(x); check_array_index(l, lg(d)); return &(gel(d,l)); } long* safeel(GEN x, long l) { if (typ(x)!=t_VECSMALL) pari_err_TYPE("safeel",x); check_array_index(l, lg(x)); return &(x[l]); } GEN* safegcoeff(GEN x, long a, long b) { if (typ(x)!=t_MAT) pari_err_TYPE("safegcoeff", x); check_array_index(b, lg(x)); check_array_index(a, lg(gel(x,b))); return &(gcoeff(x,a,b)); } typedef struct matcomp { GEN *ptcell; GEN parent; int full_col, full_row; } matcomp; typedef struct gp_pointer { matcomp c; GEN x, ox; entree *ep; long vn; long sp; } gp_pointer; /* assign res at *pt in "simple array object" p and return it, or a copy.*/ static void change_compo(matcomp *c, GEN res) { GEN p = c->parent, *pt = c->ptcell, po; long i, t; if (typ(p) == t_VECSMALL) { if (typ(res) != t_INT || is_bigint(res)) pari_err_TYPE("t_VECSMALL assignment", res); *pt = (GEN)itos(res); return; } t = typ(res); if (c->full_row) { if (t != t_VEC) pari_err_TYPE("matrix row assignment", res); if (lg(res) != lg(p)) pari_err_DIM("matrix row assignment"); for (i=1; ifull_row,i); /* Protect against SIGINT */ gcoeff(p,c->full_row,i) = gclone(gel(res,i)); if (isclone(p1)) gunclone_deep(p1); } return; } if (c->full_col) { if (t != t_COL) pari_err_TYPE("matrix col assignment", res); if (lg(res) != lg(*pt)) pari_err_DIM("matrix col assignment"); } po = *pt; /* Protect against SIGINT */ *pt = gclone(res); gunclone_deep(po); } /*************************************************************************** ** ** ** Byte-code evaluator ** ** ** ***************************************************************************/ struct var_lex { long flag; GEN value; }; struct trace { long pc; GEN closure; }; static THREAD long sp, rp, dbg_level; static THREAD long *st, *precs; static THREAD GEN *locks; 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_trace, s_prec; static THREAD pari_stack s_lvars, s_locks; 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->flag!=REF_VAL) { v->value = gclone(v->value); v->flag = COPY_VAL; } return v->value; } INLINE void setreflex(long vn) { struct var_lex *v = var+s_var.n+vn; v->flag = REF_VAL; } 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(void) { struct var_lex *v=var+s_var.n-1; s_var.n--; if (v->flag == COPY_VAL) gunclone_deep(v->value); } INLINE void restore_vars(long nbmvar, long nblvar, long nblock) { long j; for(j=1; j<=nbmvar; j++) freelex(); for(j=1; j<=nblvar; j++) { s_lvars.n--; pop_val(lvars[s_lvars.n]); } for(j=1; j<=nblock; j++) { s_locks.n--; gunclone_deep(locks[s_locks.n]); } } INLINE void restore_trace(long nbtrace) { long j; for(j=1; j<=nbtrace; j++) { GEN C = trace[s_trace.n-j].closure; clone_unlock(C); } s_trace.n -= nbtrace; } INLINE long trace_push(long pc, GEN C) { long tr; BLOCK_SIGINT_START tr = pari_stack_new(&s_trace); trace[tr].pc = pc; clone_lock(C); trace[tr].closure = C; BLOCK_SIGINT_END return tr; } void push_lex(GEN a, GEN C) { long vn=pari_stack_new(&s_var); struct var_lex *v=var+vn; v->flag = PUSH_VAL; v->value = a; if (C) (void) trace_push(-1, C); } GEN get_lex(long vn) { struct var_lex *v=var+s_var.n+vn; return v->value; } void set_lex(long vn, GEN x) { struct var_lex *v=var+s_var.n+vn; if (v->flag == COPY_VAL) { gunclone_deep(v->value); v->flag = PUSH_VAL; } v->value = x; } void pop_lex(long n) { long j; for(j=1; j<=n; j++) freelex(); restore_trace(1); } static THREAD pari_stack s_relocs; static THREAD entree **relocs; void pari_init_evaluator(void) { sp=0; pari_stack_init(&s_st,sizeof(*st),(void**)&st); pari_stack_alloc(&s_st,32); s_st.n=s_st.alloc; rp=0; pari_stack_init(&s_ptrs,sizeof(*ptrs),(void**)&ptrs); pari_stack_alloc(&s_ptrs,16); s_ptrs.n=s_ptrs.alloc; pari_stack_init(&s_var,sizeof(*var),(void**)&var); pari_stack_init(&s_lvars,sizeof(*lvars),(void**)&lvars); pari_stack_init(&s_locks,sizeof(*locks),(void**)&locks); pari_stack_init(&s_trace,sizeof(*trace),(void**)&trace); br_res = NULL; pari_stack_init(&s_relocs,sizeof(*relocs),(void**)&relocs); pari_stack_init(&s_prec,sizeof(*precs),(void**)&precs); } void pari_close_evaluator(void) { pari_stack_delete(&s_st); pari_stack_delete(&s_ptrs); pari_stack_delete(&s_var); pari_stack_delete(&s_lvars); pari_stack_delete(&s_trace); pari_stack_delete(&s_relocs); pari_stack_delete(&s_prec); } static gp_pointer * new_ptr(void) { if (rp==s_ptrs.n-1) { long i; gp_pointer *old = ptrs; (void)pari_stack_new(&s_ptrs); if (old != ptrs) for(i=0; isp >= 0) gel(st,g->sp) = (GEN) &(g->x); } } return &ptrs[rp++]; } void push_localbitprec(long p) { long n = pari_stack_new(&s_prec); precs[n] = p; } void push_localprec(long p) { push_localbitprec(p); } void pop_localprec(void) { s_prec.n--; } long get_localbitprec(void) { return s_prec.n? precs[s_prec.n-1]: precreal; } long get_localprec(void) { return nbits2prec(get_localbitprec()); } static void checkprec(const char *f, long p, long M) { if (p < 1) pari_err_DOMAIN(f, "p", "<", gen_1, stoi(p)); if (p > M) pari_err_DOMAIN(f, "p", ">", utoipos(M), utoi(p)); } static long _prec(GEN p, const char *f) { pari_sp av = avma; if (typ(p) == t_INT) return itos(p); p = gceil(p); if (typ(p) != t_INT) pari_err_TYPE(f, p); return gc_long(av, itos(p)); } void localprec(GEN pp) { long p = _prec(pp, "localprec"); checkprec("localprec", p, prec2ndec(LGBITS)); p = ndec2nbits(p); push_localbitprec(p); } void localbitprec(GEN pp) { long p = _prec(pp, "localbitprec"); checkprec("localbitprec", p, (long)LGBITS); push_localbitprec(p); } long getlocalprec(long prec) { return prec2ndec(prec); } long getlocalbitprec(long bit) { return bit; } static GEN _precision0(GEN x) { long a = gprecision(x); return a? utoi(prec2ndec(a)): mkoo(); } GEN precision0(GEN x, long n) { return n? gprec(x,n): _precision0(x); } static GEN _bitprecision0(GEN x) { long a = gprecision(x); return a? utoi(a): mkoo(); } GEN bitprecision0(GEN x, long n) { if (n < 0) pari_err_DOMAIN("bitprecision", "bitprecision", "<", gen_0, stoi(n)); if (n) { pari_sp av = avma; GEN y = gprec_w(x, nbits2prec(n)); return gerepilecopy(av, y); } return _bitprecision0(x); } GEN precision00(GEN x, GEN n) { if (!n) return _precision0(x); return precision0(x, _prec(n, "precision")); } GEN bitprecision00(GEN x, GEN n) { if (!n) return _bitprecision0(x); return bitprecision0(x, _prec(n, "bitprecision")); } INLINE GEN copyupto(GEN z, GEN t) { if (is_universal_constant(z) || (z>(GEN)pari_mainstack->bot && z<=t)) return z; else return gcopy(z); } static void closure_eval(GEN C); INLINE GEN get_and_reset_break(void) { GEN z = br_res? gcopy(br_res): gnil; reset_break(); return z; } INLINE GEN closure_return(GEN C) { pari_sp av = avma; closure_eval(C); if (br_status) { set_avma(av); return get_and_reset_break(); } return gerepileupto(av, gel(st,--sp)); } /* for the break_loop debugger. Not memory clean */ GEN closure_evalbrk(GEN C, long *status) { closure_eval(C); *status = br_status; return br_status? get_and_reset_break(): gel(st,--sp); } INLINE long closure_varn(GEN x) { if (!x) return -1; if (!gequalX(x)) err_var(x); return varn(x); } INLINE void closure_castgen(GEN z, long mode) { switch (mode) { case Ggen: gel(st,sp++)=z; break; case Gsmall: st[sp++]=gtos(z); break; case Gusmall: st[sp++]=gtou(z); break; case Gvar: st[sp++]=closure_varn(z); break; case Gvoid: break; default: pari_err_BUG("closure_castgen, type unknown"); } } INLINE void closure_castlong(long z, long mode) { switch (mode) { case Gsmall: st[sp++]=z; break; case Gusmall: if (z < 0) pari_err_TYPE("stou [integer >=0 expected]", stoi(z)); st[sp++]=(ulong) z; break; case Ggen: gel(st,sp++)=stoi(z); break; case Gvar: err_var(stoi(z)); case Gvoid: break; default: pari_err_BUG("closure_castlong, type unknown"); } } const char * closure_func_err(void) { long fun=s_trace.n-1, pc; const char *code; GEN C, oper; if (fun < 0 || trace[fun].pc < 0) return NULL; pc = trace[fun].pc; C = trace[fun].closure; code = closure_codestr(C); oper = closure_get_oper(C); if (code[pc]==OCcallgen || code[pc]==OCcallgen2 || code[pc]==OCcallint || code[pc]==OCcalllong || code[pc]==OCcallvoid) return ((entree*)oper[pc])->name; return NULL; } /* return the next label for the call chain debugger closure_err(), * incorporating the name of the user of member function. Return NULL for an * anonymous (inline) closure. */ static char * get_next_label(const char *s, int member, char **next_fun) { const char *v, *t = s+1; char *u, *next_label; if (!is_keyword_char(*s)) return NULL; while (is_keyword_char(*t)) t++; /* e.g. (x->1/x)(0) instead of (x)->1/x */ if (t[0] == '-' && t[1] == '>') return NULL; next_label = (char*)pari_malloc(t - s + 32); sprintf(next_label, "in %sfunction ", member? "member ": ""); u = *next_fun = next_label + strlen(next_label); v = s; while (v < t) *u++ = *v++; *u++ = 0; return next_label; } static const char * get_arg_name(GEN C, long i) { GEN d = closure_get_dbg(C), frpc = gel(d,2), fram = gel(d,3); long j, l = lg(frpc); for (j=1; jname; return "(unnamed)"; } void closure_err(long level) { GEN base; const long lastfun = s_trace.n - 1 - level; char *next_label, *next_fun; long i = maxss(0, lastfun - 19); if (lastfun < 0) return; /*e.g. when called by gp_main_loop's simplify */ if (i > 0) while (lg(trace[i].closure)==6) i--; base = closure_get_text(trace[i].closure); /* gcc -Wall*/ next_label = pari_strdup(i == 0? "at top-level": "[...] at"); next_fun = next_label; for (; i <= lastfun; i++) { GEN C = trace[i].closure; if (lg(C) >= 7) base=closure_get_text(C); if ((i==lastfun || lg(trace[i+1].closure)>=7)) { GEN dbg = gel(closure_get_dbg(C),1); /* After a SIGINT, pc can be slightly off: ensure 0 <= pc < lg() */ long pc = minss(lg(dbg)-1, trace[i].pc>=0 ? trace[i].pc: 1); long offset = pc? dbg[pc]: 0; int member; const char *s, *sbase; if (typ(base)!=t_VEC) sbase = GSTR(base); else if (offset>=0) sbase = GSTR(gel(base,2)); else { sbase = GSTR(gel(base,1)); offset += strlen(sbase); } s = sbase + offset; member = offset>0 && (s[-1] == '.'); /* avoid "in function foo: foo" */ if (!next_fun || strcmp(next_fun, s)) { print_errcontext(pariErr, next_label, s, sbase); out_putc(pariErr, '\n'); } pari_free(next_label); if (i == lastfun) break; next_label = get_next_label(s, member, &next_fun); if (!next_label) { next_label = pari_strdup("in anonymous function"); next_fun = NULL; } } } } GEN pari_self(void) { long fun = s_trace.n - 1; if (fun > 0) while (lg(trace[fun].closure)==6) fun--; return fun >= 0 ? trace[fun].closure: NULL; } long closure_context(long start, long level) { const long lastfun = s_trace.n - 1 - level; long i, fun = lastfun; if (fun<0) return lastfun; while (fun>start && lg(trace[fun].closure)==6) fun--; for (i=fun; i <= lastfun; i++) push_frame(trace[i].closure, trace[i].pc,0); for ( ; i < s_trace.n; i++) push_frame(trace[i].closure, trace[i].pc,1); return s_trace.n-level; } INLINE void st_alloc(long n) { if (sp+n>s_st.n) { pari_stack_alloc(&s_st,n+16); s_st.n=s_st.alloc; if (DEBUGMEM>=2) pari_warn(warner,"doubling evaluator stack"); } } INLINE void ptr_proplock(gp_pointer *g, GEN C) { g->x = C; if (isclone(g->x)) { clone_unlock_deep(g->ox); g->ox = g->x; ++bl_refc(g->ox); } } static void closure_eval(GEN C) { const char *code=closure_codestr(C); GEN oper=closure_get_oper(C); GEN data=closure_get_data(C); long loper=lg(oper); long saved_sp=sp-closure_arity(C); long saved_rp=rp, saved_prec=s_prec.n; long j, nbmvar=0, nblvar=0, nblock=0; long pc, t; #ifdef STACK_CHECK GEN stackelt; if (PARI_stack_limit && (void*) &stackelt <= PARI_stack_limit) pari_err(e_MISC, "deep recursion"); #endif t = trace_push(0, C); if (lg(C)==8) { GEN z=closure_get_frame(C); long l=lg(z)-1; pari_stack_alloc(&s_var,l); s_var.n+=l; nbmvar+=l; for(j=1;j<=l;j++) { var[s_var.n-j].flag=PUSH_VAL; var[s_var.n-j].value=gel(z,j); } } for(pc=1;pcvalue; } else { GEN val = export_get(ep->name); if (!val) pari_err(e_MISC,"mt: please use export(%s)", ep->name); gel(st,sp++)=val; } 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; g->x = checkvalueptr(g->ep); g->ox = g->x; clone_lock(g->ox); g->sp = sp; gel(st,sp++) = (GEN)&(g->x); break; } case OCsimpleptrlex: { gp_pointer *g = new_ptr(); g->vn=operand; g->ep=(entree *)0x1L; g->x = (GEN) var[s_var.n+operand].value; g->ox = g->x; clone_lock(g->ox); g->sp = sp; gel(st,sp++) = (GEN)&(g->x); break; } case OCnewptrdyn: { entree *ep = (entree *)operand; gp_pointer *g = new_ptr(); matcomp *C; checkvalue(ep, chk_ERROR); g->sp = -1; g->x = copyvalue(ep); g->ox = g->x; clone_lock(g->ox); g->vn=0; g->ep=NULL; C=&g->c; C->full_col = C->full_row = 0; C->parent = (GEN) g->x; C->ptcell = (GEN *) &g->x; break; } case OCnewptrlex: { gp_pointer *g = new_ptr(); matcomp *C; g->sp = -1; g->x = copylex(operand); g->ox = g->x; clone_lock(g->ox); g->vn=0; g->ep=NULL; C=&g->c; C->full_col = C->full_row = 0; C->parent = (GEN) g->x; C->ptcell = (GEN *) &(g->x); break; } case OCpushptr: { gp_pointer *g = &ptrs[rp-1]; g->sp = sp; gel(st,sp++) = (GEN)&(g->x); } break; case OCendptr: for(j=0;jep) { if (g->vn) changelex(g->vn, g->x); else changevalue(g->ep, g->x); } else change_compo(&(g->c), g->x); clone_unlock_deep(g->ox); } break; case OCstoredyn: { entree *ep = (entree *)operand; checkvalue(ep, chk_NOCREATE); changevalue(ep, gel(st,--sp)); break; } case OCstorelex: changelex(operand,gel(st,--sp)); break; case OCstoreptr: { gp_pointer *g = &ptrs[--rp]; change_compo(&(g->c), gel(st,--sp)); clone_unlock_deep(g->ox); break; } case OCstackgen: { GEN z = gerepileupto(st[sp-2],gel(st,sp-1)); gmael(st,sp-3,operand) = copyupto(z,gel(st,sp-2)); st[sp-2] = avma; sp--; break; } case OCprecreal: st[sp++]=get_localprec(); break; case OCbitprecreal: st[sp++]=get_localbitprec(); break; case OCprecdl: st[sp++]=precdl; break; case OCavma: st[sp++]=avma; break; case OCcowvardyn: { entree *ep = (entree *)operand; checkvalue(ep, chk_ERROR); (void)copyvalue(ep); break; } case OCcowvarlex: (void)copylex(operand); break; case OCsetref: setreflex(operand); break; case OClock: { GEN v = gel(st,sp-1); if (isclone(v)) { long n = pari_stack_new(&s_locks); locks[n] = v; nblock++; ++bl_refc(v); } break; } case OCevalmnem: { entree *ep = (entree*) operand; const char *flags = ep->code; flags = strchr(flags, '\n'); /* Skip to the following '\n' */ st[sp-1] = eval_mnemonic(gel(st,sp-1), flags+1); break; } case OCstoi: gel(st,sp-1)=stoi(st[sp-1]); break; case OCutoi: gel(st,sp-1)=utoi(st[sp-1]); break; case OCitos: st[sp+operand]=gtos(gel(st,sp+operand)); break; case OCitou: st[sp+operand]=gtou(gel(st,sp+operand)); break; case OCtostr: { GEN z = gel(st,sp+operand); st[sp+operand] = (long) (z ? GENtostr_unquoted(z): NULL); break; } case OCvarn: st[sp+operand] = closure_varn(gel(st,sp+operand)); break; case OCcopy: gel(st,sp-1) = gcopy(gel(st,sp-1)); break; case OCgerepile: { pari_sp av; GEN x; sp--; av = st[sp-1]; x = gel(st,sp); if (isonstack(x)) { pari_sp av2 = (pari_sp)(x + lg(x)); if ((long) (av - av2) > 1000000L) { if (DEBUGMEM>=2) pari_warn(warnmem,"eval: recovering %ld bytes", av - av2); x = gerepileupto(av, x); } } else set_avma(av); gel(st,sp-1) = x; break; } case OCcopyifclone: if (isclone(gel(st,sp-1))) gel(st,sp-1) = gcopy(gel(st,sp-1)); break; case OCcompo1: { GEN p=gel(st,sp-2); long c=st[sp-1]; sp-=2; switch(typ(p)) { case t_VEC: case t_COL: check_array_index(c, lg(p)); closure_castgen(gel(p,c),operand); break; case t_LIST: { long lx; if (list_typ(p)!=t_LIST_RAW) pari_err_TYPE("_[_] OCcompo1 [not a vector]", p); p = list_data(p); lx = p? lg(p): 1; check_array_index(c, lx); closure_castgen(gel(p,c),operand); break; } case t_VECSMALL: check_array_index(c,lg(p)); closure_castlong(p[c],operand); break; default: pari_err_TYPE("_[_] OCcompo1 [not a vector]", p); break; } break; } case OCcompo1ptr: { long c=st[sp-1]; long lx; gp_pointer *g = &ptrs[rp-1]; matcomp *C=&g->c; GEN p = g->x; sp--; switch(typ(p)) { case t_VEC: case t_COL: check_array_index(c, lg(p)); C->ptcell = (GEN *) p+c; ptr_proplock(g, *(C->ptcell)); break; case t_VECSMALL: check_array_index(c, lg(p)); C->ptcell = (GEN *) p+c; g->x = stoi(p[c]); break; case t_LIST: if (list_typ(p)!=t_LIST_RAW) pari_err_TYPE("&_[_] OCcompo1 [not a vector]", p); p = list_data(p); lx = p? lg(p): 1; check_array_index(c,lx); C->ptcell = (GEN *) p+c; ptr_proplock(g, *(C->ptcell)); break; default: pari_err_TYPE("&_[_] OCcompo1ptr [not a vector]", p); } C->parent = p; break; } case OCcompo2: { GEN p=gel(st,sp-3); long c=st[sp-2]; long d=st[sp-1]; if (typ(p)!=t_MAT) pari_err_TYPE("_[_,_] OCcompo2 [not a matrix]", p); check_array_index(d, lg(p)); check_array_index(c, lg(gel(p,d))); sp-=3; closure_castgen(gcoeff(p,c,d),operand); break; } case OCcompo2ptr: { long c=st[sp-2]; long d=st[sp-1]; gp_pointer *g = &ptrs[rp-1]; matcomp *C=&g->c; GEN p = g->x; sp-=2; if (typ(p)!=t_MAT) pari_err_TYPE("&_[_,_] OCcompo2ptr [not a matrix]", p); check_array_index(d, lg(p)); check_array_index(c, lg(gel(p,d))); C->ptcell = (GEN *) gel(p,d)+c; C->parent = p; ptr_proplock(g, *(C->ptcell)); break; } case OCcompoC: { GEN p=gel(st,sp-2); long c=st[sp-1]; if (typ(p)!=t_MAT) pari_err_TYPE("_[,_] OCcompoC [not a matrix]", p); check_array_index(c, lg(p)); sp--; gel(st,sp-1) = gel(p,c); break; } case OCcompoCptr: { long c=st[sp-1]; gp_pointer *g = &ptrs[rp-1]; matcomp *C=&g->c; GEN p = g->x; sp--; if (typ(p)!=t_MAT) pari_err_TYPE("&_[,_] OCcompoCptr [not a matrix]", p); check_array_index(c, lg(p)); C->ptcell = (GEN *) p+c; C->full_col = c; C->parent = p; ptr_proplock(g, *(C->ptcell)); break; } case OCcompoL: { GEN p=gel(st,sp-2); long r=st[sp-1]; sp--; if (typ(p)!=t_MAT) pari_err_TYPE("_[_,] OCcompoL [not a matrix]", p); check_array_index(r,lg(p) == 1? 1: lgcols(p)); gel(st,sp-1) = row(p,r); break; } case OCcompoLptr: { long r=st[sp-1]; gp_pointer *g = &ptrs[rp-1]; matcomp *C=&g->c; GEN p = g->x, p2; sp--; if (typ(p)!=t_MAT) pari_err_TYPE("&_[_,] OCcompoLptr [not a matrix]", p); check_array_index(r,lg(p) == 1? 1: lgcols(p)); p2 = rowcopy(p,r); C->full_row = r; /* record row number */ C->ptcell = &p2; C->parent = p; g->x = p2; break; } case OCdefaultarg: if (var[s_var.n+operand].flag==DEFAULT_VAL) { GEN z = gel(st,sp-1); if (typ(z)==t_CLOSURE) { pushlex(operand, closure_evalnobrk(z)); copylex(operand); } else pushlex(operand, z); } sp--; break; case OClocalvar: { long n; entree *ep = (entree *)operand; checkvalue(ep, chk_NOCREATE); n = pari_stack_new(&s_lvars); lvars[n] = ep; nblvar++; pushvalue(ep,gel(st,--sp)); break; } case OClocalvar0: { long n; entree *ep = (entree *)operand; checkvalue(ep, chk_NOCREATE); n = pari_stack_new(&s_lvars); lvars[n] = ep; nblvar++; zerovalue(ep); break; } case OCexportvar: { entree *ep = (entree *)operand; mt_export_add(ep->name, gel(st,--sp)); break; } case OCunexportvar: { entree *ep = (entree *)operand; mt_export_del(ep->name); break; } #define EVAL_f(f, type, resEQ) \ switch (ep->arity) \ { \ case 0: resEQ ((type (*)(void))f)(); break; \ case 1: sp--; resEQ ((type (*)(long))f)(st[sp]); break; \ case 2: sp-=2; resEQ((type (*)(long,long))f)(st[sp],st[sp+1]); break; \ case 3: sp-=3; resEQ((type (*)(long,long,long))f)(st[sp],st[sp+1],st[sp+2]); break; \ case 4: sp-=4; resEQ((type (*)(long,long,long,long))f)(st[sp],st[sp+1],st[sp+2],st[sp+3]); break; \ case 5: sp-=5; resEQ((type (*)(long,long,long,long,long))f)(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4]); break; \ case 6: sp-=6; resEQ((type (*)(long,long,long,long,long,long))f)(st[sp],st[sp+1],st[sp+2],st[sp+3],st[sp+4],st[sp+5]); break; \ case 7: sp-=7; resEQ((type (*)(long,long,long,long,long,long,long))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; resEQ((type (*)(long,long,long,long,long,long,long,long))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; resEQ((type (*)(long,long,long,long,long,long,long,long,long))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; resEQ((type (*)(long,long,long,long,long,long,long,long,long,long))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; resEQ((type (*)(long,long,long,long,long,long,long,long,long,long,long))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; resEQ((type (*)(long,long,long,long,long,long,long,long,long,long,long,long))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; resEQ((type (*)(long,long,long,long,long,long,long,long,long,long,long,long,long))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; resEQ((type (*)(long,long,long,long,long,long,long,long,long,long,long,long,long,long))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; resEQ((type (*)(long,long,long,long,long,long,long,long,long,long,long,long,long,long,long))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; resEQ((type (*)(long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long))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; resEQ((type (*)(long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long))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; resEQ((type (*)(long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long))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; resEQ((type (*)(long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long))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; resEQ((type (*)(long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long,long))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; /*LCOV_EXCL_LINE*/ \ } 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(ep->value, GEN, res=); 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(ep->value, long, res=); if (br_status) goto endeval; st[sp++] = res; break; } case OCcallint: { entree *ep = (entree *)operand; long res; EVAL_f(ep->value, int, res=); if (br_status) goto endeval; st[sp++] = res; break; } case OCcallvoid: { entree *ep = (entree *)operand; EVAL_f(ep->value, void,(void)); if (br_status) goto endeval; break; } #undef EVAL_f case OCcalluser: { long n=operand; GEN fun = gel(st,sp-1-n); long arity, isvar; GEN z; if (typ(fun)!=t_CLOSURE) pari_err(e_NOTFUNC, fun); isvar = closure_is_variadic(fun); arity = closure_arity(fun); if (!isvar || n < arity) { st_alloc(arity-n); if (n>arity) pari_err(e_MISC,"too many parameters in user-defined function call"); for (j=n+1;j<=arity;j++) gel(st,sp++)=0; if (isvar) gel(st,sp-1) = cgetg(1,t_VEC); } else { GEN v; long j, m = n-arity+1; v = cgetg(m+1,t_VEC); sp-=m; for (j=1; j<=m; j++) gel(v,j) = gel(st,sp+j-1)? gcopy(gel(st,sp+j-1)): gen_0; gel(st,sp++)=v; } z = closure_return(fun); if (br_status) goto endeval; gel(st, sp-1) = z; break; } case OCnewframe: if (operand>0) nbmvar+=operand; else operand=-operand; pari_stack_alloc(&s_var,operand); s_var.n+=operand; for(j=1;j<=operand;j++) { var[s_var.n-j].flag=PUSH_VAL; var[s_var.n-j].value=gen_0; } break; case OCsaveframe: { GEN cl = (operand?gcopy:shallowcopy)(gel(st,sp-1)); GEN f = gel(cl, 7); long j, l = lg(f); GEN v = cgetg(l, t_VEC); for (j = 1; j < l; j++) if (signe(gel(f,l-j))==0) { GEN val = var[s_var.n-j].value; gel(v,j) = operand?gcopy(val):val; } else gel(v,j) = gnil; gel(cl,7) = v; gel(st,sp-1) = cl; } break; case OCpackargs: { GEN def = cgetg(operand+1, t_VECSMALL); GEN args = cgetg(operand+1, t_VEC); pari_stack_alloc(&s_var,operand); sp-=operand; for (j=0;j>=1UL,j--) if ((operand&1L) && gel(st,j)==NULL) pari_err(e_MISC,"missing mandatory argument"); break; case OCcheckargs0: for (j=sp-1;operand;operand>>=1UL,j--) if ((operand&1L) && gel(st,j)) pari_err(e_MISC,"argument type not implemented"); break; case OCdefaultlong: sp--; if (st[sp+operand]) st[sp+operand]=gtos(gel(st,sp+operand)); else st[sp+operand]=st[sp]; break; case OCdefaultulong: sp--; if (st[sp+operand]) st[sp+operand]=gtou(gel(st,sp+operand)); else st[sp+operand]=st[sp]; break; case OCdefaultgen: sp--; if (!st[sp+operand]) st[sp+operand]=st[sp]; break; case OCvec: gel(st,sp++)=cgetg(operand,t_VEC); st[sp++]=avma; break; case OCcol: gel(st,sp++)=cgetg(operand,t_COL); st[sp++]=avma; break; case OCmat: { GEN z; long l=st[sp-1]; z=cgetg(operand,t_MAT); for(j=1;jsaved_rp ; ) { gp_pointer *g = &ptrs[--rp]; clone_unlock_deep(g->ox); } } s_prec.n = saved_prec; s_trace.n--; restore_vars(nbmvar, nblvar, nblock); clone_unlock(C); } GEN closure_evalgen(GEN C) { pari_sp ltop=avma; closure_eval(C); if (br_status) return gc_NULL(ltop); return gerepileupto(ltop,gel(st,--sp)); } long evalstate_get_trace(void) { return s_trace.n; } void evalstate_set_trace(long lvl) { s_trace.n = lvl; } void evalstate_save(struct pari_evalstate *state) { state->avma = avma; state->sp = sp; state->rp = rp; state->prec = s_prec.n; state->var = s_var.n; state->lvars= s_lvars.n; state->locks= s_locks.n; state->trace= s_trace.n; compilestate_save(&state->comp); mtstate_save(&state->mt); } void evalstate_restore(struct pari_evalstate *state) { set_avma(state->avma); mtstate_restore(&state->mt); sp = state->sp; rp = state->rp; s_prec.n = state->prec; restore_vars(s_var.n-state->var, s_lvars.n-state->lvars, s_locks.n-state->locks); restore_trace(s_trace.n-state->trace); reset_break(); compilestate_restore(&state->comp); } GEN evalstate_restore_err(struct pari_evalstate *state) { GENbin* err = copy_bin(pari_err_last()); evalstate_restore(state); return bin_copy(err); } void evalstate_reset(void) { mtstate_reset(); restore_vars(s_var.n, s_lvars.n, s_locks.n); sp = rp = dbg_level = s_trace.n = 0; reset_break(); compilestate_reset(); parsestate_reset(); set_avma(pari_mainstack->top); } void evalstate_clone(void) { long i; for (i = 1; i<=s_var.n; i++) copylex(-i); lvar_make_safe(); for (i = 0; i< s_trace.n; i++) { GEN C = trace[i].closure; if (isonstack(C)) trace[i].closure = gclone(C); } } GEN closure_trapgen(GEN C, long numerr) { VOLATILE GEN x; struct pari_evalstate state; evalstate_save(&state); pari_CATCH(numerr) { x = (GEN)1L; } pari_TRY { x = closure_evalgen(C); } pari_ENDCATCH; if (x == (GEN)1L) evalstate_restore(&state); return x; } GEN closure_evalnobrk(GEN C) { pari_sp ltop=avma; closure_eval(C); if (br_status) pari_err(e_MISC, "break not allowed here"); return gerepileupto(ltop,gel(st,--sp)); } void closure_evalvoid(GEN C) { pari_sp ltop=avma; closure_eval(C); set_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); } GEN pareval_worker(GEN C) { return closure_callgenall(C, 0); } GEN pareval(GEN C) { pari_sp av = avma; long l = lg(C), i; GEN worker; if (!is_vec_t(typ(C))) pari_err_TYPE("pareval",C); for (i=1; i1) pari_warn(warnmem,"parsum_slice"); gerepileall(av,2,&a,&s); } } return gerepileupto(av,s); } GEN parsum(GEN a, GEN b, GEN code) { pari_sp av = avma; GEN worker, mG, v, s, N; long r, m, pending; struct pari_mt pt; pari_sp av2; if (typ(a) != t_INT) pari_err_TYPE("parsum",a); if (gcmp(b,a) < 0) return gen_0; b = gfloor(b); N = addiu(subii(b, a), 1); mG = sqrti(N); m = itou(mG); worker = snm_closure(is_entry("_parsum_slice_worker"), mkvec3(b,mG,code)); mt_queue_start_lim(&pt, worker, m); s = gen_0; a = setloop(a); v = mkvec(a); pending = 0; av2 = avma; for (r = 1; r <= m || pending; r++) { long workid; GEN done; mt_queue_submit(&pt, 0, r <= m? v: NULL); done = mt_queue_get(&pt, &workid, &pending); if (done) { s = gadd(s, done); if (gc_needed(av2,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"parsum"); s = gerepileupto(av2,s); } } a = incloop(a); gel(v,1) = a; } mt_queue_end(&pt); return gerepileupto(av, s); } void parfor(GEN a, GEN b, GEN code, void *E, long call(void*, GEN, GEN)) { pari_sp av = avma, av2; long running, pending = 0, lim; long status = br_NONE; GEN worker = snm_closure(is_entry("_parfor_worker"), mkvec(code)); GEN done, stop = NULL; struct pari_mt pt; if (typ(a) != t_INT) pari_err_TYPE("parfor",a); if (b) { if (gcmp(b,a) < 0) return; if (typ(b) == t_INFINITY) { if (inf_get_sign(b) < 0) return; b = NULL; } else b = gfloor(b); } lim = b ? itos_or_0(subii(addis(b,1),a)): 0; mt_queue_start_lim(&pt, worker, lim); a = mkvec(setloop(a)); av2 = avma; while ((running = (!stop && (!b || cmpii(gel(a,1),b) <= 0))) || pending) { mt_queue_submit(&pt, 0, running ? a: NULL); done = mt_queue_get(&pt, NULL, &pending); if (call && done && (!stop || cmpii(gel(done,1),stop) < 0)) if (call(E, gel(done,1), gel(done,2))) { status = br_status; br_status = br_NONE; stop = gerepileuptoint(av2, gel(done,1)); } gel(a,1) = incloop(gel(a,1)); if (!stop) set_avma(av2); } set_avma(av2); mt_queue_end(&pt); br_status = status; set_avma(av); } static void parforiter_init(struct parfor_iter *T, GEN code) { T->pending = 0; T->worker = snm_closure(is_entry("_parfor_worker"), mkvec(code)); mt_queue_start(&T->pt, T->worker); } static GEN parforiter_next(struct parfor_iter *T, GEN v) { mt_queue_submit(&T->pt, 0, v); return mt_queue_get(&T->pt, NULL, &T->pending); } static void parforiter_stop(struct parfor_iter *T) { while (T->pending) { mt_queue_submit(&T->pt, 0, NULL); (void) mt_queue_get(&T->pt, NULL, &T->pending); } mt_queue_end(&T->pt); } void parfor_init(parfor_t *T, GEN a, GEN b, GEN code) { if (typ(a) != t_INT) pari_err_TYPE("parfor",a); T->b = b ? gfloor(b): NULL; T->a = mkvec(setloop(a)); parforiter_init(&T->iter, code); } GEN parfor_next(parfor_t *T) { long running; while ((running=((!T->b || cmpii(gel(T->a,1),T->b) <= 0))) || T->iter.pending) { GEN done = parforiter_next(&T->iter, running ? T->a: NULL); gel(T->a,1) = incloop(gel(T->a,1)); if (done) return done; } mt_queue_end(&T->iter.pt); return NULL; } void parfor_stop(parfor_t *T) { parforiter_stop(&T->iter); } static long gp_evalvoid2(void *E, GEN x, GEN y) { GEN code =(GEN) E; push_lex(x, code); push_lex(y, NULL); closure_evalvoid(code); pop_lex(2); return loop_break(); } void parfor0(GEN a, GEN b, GEN code, GEN code2) { parfor(a, b, code, (void*)code2, code2 ? gp_evalvoid2: NULL); } static int negcmp(GEN x, GEN y) { return gcmp(y,x); } void parforstep(GEN a, GEN b, GEN s, GEN code, void *E, long call(void*, GEN, GEN)) { pari_sp av = avma, av2; long running, pending = 0; long status = br_NONE; GEN worker = snm_closure(is_entry("_parfor_worker"), mkvec(code)); GEN done, stop = NULL; struct pari_mt pt; long i, ss; GEN v = NULL, lim; int (*cmp)(GEN,GEN); b = gcopy(b); s = gcopy(s); av = avma; switch(typ(s)) { case t_VEC: case t_COL: { GEN vs = vecsum(s); ss = gsigne(vs); v = s; lim = gdiv(gmulgs(gadd(gsub(b,a),vs),lg(vs)-1),vs); break; } case t_INTMOD: if (typ(a) != t_INT) a = gceil(a); a = addii(a, modii(subii(gel(s,2),a), gel(s,1))); s = gel(s,1); /* FALL THROUGH */ default: ss = gsigne(s); lim = gdiv(gadd(gsub(b,a),s),s); } lim = ceil_safe(lim); if (!ss || typ(lim)!=t_INT) pari_err_DOMAIN("parforstep","step","=",gen_0,s); if (signe(lim)<=0) { set_avma(av); return; } cmp = (ss > 0)? &gcmp: &negcmp; i = 0; a = mkvec(a); mt_queue_start_lim(&pt, worker, itou_or_0(lim)); av2 = avma; while ((running = (!stop && (!b || cmp(gel(a,1),b) <= 0))) || pending) { mt_queue_submit(&pt, 0, running ? a: NULL); done = mt_queue_get(&pt, NULL, &pending); if (call && done && (!stop || cmp(gel(done,1),stop) < 0)) if (call(E, gel(done,1), gel(done,2))) { status = br_status; br_status = br_NONE; stop = gel(done,1); } if (running) { if (v) { if (++i >= lg(v)) i = 1; s = gel(v,i); } gel(a,1) = gadd(gel(a,1),s); if (!stop) gel(a,1) = gerepileupto(av2, gel(a,1)); } } mt_queue_end(&pt); br_status = status; set_avma(av); } void parforstep0(GEN a, GEN b, GEN s, GEN code, GEN code2) { parforstep(a, b, s, code, (void*)code2, code2 ? gp_evalvoid2: NULL); } void parforstep_init(parforstep_t *T, GEN a, GEN b, GEN s, GEN code) { long ss; if (typ(a) != t_INT) pari_err_TYPE("parfor",a); switch(typ(s)) { case t_VEC: case t_COL: ss = gsigne(vecsum(s)); break; case t_INTMOD: if (typ(a) != t_INT) a = gceil(a); a = addii(a, modii(subii(gel(s,2),a), gel(s,1))); s = gel(s,1); default: /* FALL THROUGH */ ss = gsigne(s); } T->cmp = (ss > 0)? &gcmp: &negcmp; T->s = s; T->i = 0; T->b = b; T->a = mkvec(a); parforiter_init(&T->iter, code); } GEN parforstep_next(parforstep_t *T) { long running; while ((running=((!T->b || T->cmp(gel(T->a,1),T->b) <= 0))) || T->iter.pending) { GEN done = parforiter_next(&T->iter, running ? T->a: NULL); if (running) { if (is_vec_t(typ(T->s))) { if (++(T->i) >= lg(T->s)) T->i = 1; gel(T->a,1) = gadd(gel(T->a,1), gel(T->s,T->i)); } else gel(T->a,1) = gadd(gel(T->a,1), T->s); } if (done) return done; } mt_queue_end(&T->iter.pt); return NULL; } void parforstep_stop(parforstep_t *T) { parforiter_stop(&T->iter); } void parforprimestep_init(parforprime_t *T, GEN a, GEN b, GEN q, GEN code) { forprimestep_init(&T->forprime, a, b, q); T->v = mkvec(gen_0); parforiter_init(&T->iter, code); } void parforprime_init(parforprime_t *T, GEN a, GEN b, GEN code) { parforprimestep_init(T, a, b, NULL, code); } GEN parforprime_next(parforprime_t *T) { long running; while ((running = !!forprime_next(&T->forprime)) || T->iter.pending) { GEN done; gel(T->v, 1) = T->forprime.pp; done = parforiter_next(&T->iter, running ? T->v: NULL); if (done) return done; } mt_queue_end(&T->iter.pt); return NULL; } void parforprime_stop(parforprime_t *T) { parforiter_stop(&T->iter); } void parforprimestep(GEN a, GEN b, GEN q, GEN code, void *E, long call(void*, GEN, GEN)) { pari_sp av = avma, av2; long running, pending = 0; long status = br_NONE; GEN worker = snm_closure(is_entry("_parfor_worker"), mkvec(code)); GEN v, done, stop = NULL; struct pari_mt pt; forprime_t T; if (!forprimestep_init(&T, a,b,q)) { set_avma(av); return; } mt_queue_start(&pt, worker); v = mkvec(gen_0); av2 = avma; while ((running = (!stop && forprime_next(&T))) || pending) { gel(v, 1) = T.pp; mt_queue_submit(&pt, 0, running ? v: NULL); done = mt_queue_get(&pt, NULL, &pending); if (call && done && (!stop || cmpii(gel(done,1),stop) < 0)) if (call(E, gel(done,1), gel(done,2))) { status = br_status; br_status = br_NONE; stop = gerepileuptoint(av2, gel(done,1)); } if (!stop) set_avma(av2); } set_avma(av2); mt_queue_end(&pt); br_status = status; set_avma(av); } void parforprime(GEN a, GEN b, GEN code, void *E, long call(void*, GEN, GEN)) { parforprimestep(a, b, NULL, code, E, call); } void parforprime0(GEN a, GEN b, GEN code, GEN code2) { parforprime(a, b, code, (void*)code2, code2? gp_evalvoid2: NULL); } void parforprimestep0(GEN a, GEN b, GEN q, GEN code, GEN code2) { parforprimestep(a, b, q, code, (void*)code2, code2? gp_evalvoid2: NULL); } void parforvec_init(parforvec_t *T, GEN x, GEN code, long flag) { forvec_init(&T->forvec, x, flag); T->v = mkvec(gen_0); parforiter_init(&T->iter, code); } GEN parforvec_next(parforvec_t *T) { GEN v = gen_0; while ((v = forvec_next(&T->forvec)) || T->iter.pending) { GEN done; if (v) gel(T->v, 1) = v; done = parforiter_next(&T->iter, v ? T->v: NULL); if (done) return done; } mt_queue_end(&T->iter.pt); return NULL; } void parforvec_stop(parforvec_t *T) { parforiter_stop(&T->iter); } void parforvec(GEN x, GEN code, long flag, void *E, long call(void*, GEN, GEN)) { pari_sp av = avma, av2; long running, pending = 0; long status = br_NONE; GEN worker = snm_closure(is_entry("_parfor_worker"), mkvec(code)); GEN done, stop = NULL; struct pari_mt pt; forvec_t T; GEN a, v = gen_0; if (!forvec_init(&T, x, flag)) { set_avma(av); return; } mt_queue_start(&pt, worker); a = mkvec(gen_0); av2 = avma; while ((running = (!stop && v && (v = forvec_next(&T)))) || pending) { gel(a, 1) = v; mt_queue_submit(&pt, 0, running ? a: NULL); done = mt_queue_get(&pt, NULL, &pending); if (call && done && (!stop || lexcmp(gel(done,1),stop) < 0)) if (call(E, gel(done,1), gel(done,2))) { status = br_status; br_status = br_NONE; stop = gerepilecopy(av2, gel(done,1)); } if (!stop) set_avma(av2); } set_avma(av2); mt_queue_end(&pt); br_status = status; set_avma(av); } void parforvec0(GEN x, GEN code, GEN code2, long flag) { parforvec(x, code, flag, (void*)code2, code2? gp_evalvoid2: NULL); } void parforeach_init(parforeach_t *T, GEN x, GEN code) { switch(typ(x)) { case t_LIST: x = list_data(x); /* FALL THROUGH */ if (!x) return; case t_MAT: case t_VEC: case t_COL: break; default: pari_err_TYPE("foreach",x); return; /*LCOV_EXCL_LINE*/ } T->x = x; T->i = 1; T->l = lg(x); T->W = mkvec(gen_0); T->iter.pending = 0; T->iter.worker = snm_closure(is_entry("_parvector_worker"), mkvec(code)); mt_queue_start(&T->iter.pt, T->iter.worker); } GEN parforeach_next(parforeach_t *T) { while (T->i < T->l || T->iter.pending) { GEN done; long workid; if (T->i < T->l) gel(T->W,1) = gel(T->x, T->i); mt_queue_submit(&T->iter.pt, T->i, T->i < T->l ? T->W: NULL); T->i = minss(T->i+1, T->l); done = mt_queue_get(&T->iter.pt, &workid, &T->iter.pending); if (done) return mkvec2(gel(T->x,workid),done); } mt_queue_end(&T->iter.pt); return NULL; } void parforeach_stop(parforeach_t *T) { parforiter_stop(&T->iter); } void parforeach(GEN x, GEN code, void *E, long call(void*, GEN, GEN)) { pari_sp av = avma, av2; long pending = 0, n, i, stop = 0; long status = br_NONE, workid; GEN worker = snm_closure(is_entry("_parvector_worker"), mkvec(code)); GEN done, W; struct pari_mt pt; switch(typ(x)) { case t_LIST: x = list_data(x); /* FALL THROUGH */ if (!x) return; case t_MAT: case t_VEC: case t_COL: break; default: pari_err_TYPE("foreach",x); return; /*LCOV_EXCL_LINE*/ } clone_lock(x); n = lg(x)-1; mt_queue_start_lim(&pt, worker, n); W = cgetg(2, t_VEC); av2 = avma; for (i=1; i<=n || pending; i++) { if (!stop && i <= n) gel(W,1) = gel(x,i); mt_queue_submit(&pt, i, !stop && i<=n? W: NULL); done = mt_queue_get(&pt, &workid, &pending); if (call && done && (!stop || workid < stop)) if (call(E, gel(x, workid), done)) { status = br_status; br_status = br_NONE; stop = workid; } } set_avma(av2); mt_queue_end(&pt); clone_unlock_deep(x); br_status = status; set_avma(av); } void parforeach0(GEN x, GEN code, GEN code2) { parforeach(x, code, (void*)code2, code2? gp_evalvoid2: NULL); } void closure_callvoid1(GEN C, GEN x) { long i, ar = closure_arity(C); gel(st,sp++) = x; for(i=2; i <= ar; i++) gel(st,sp++) = NULL; closure_evalvoid(C); } GEN closure_callgen0(GEN C) { GEN z; long i, ar = closure_arity(C); for(i=1; i<= ar; i++) gel(st,sp++) = NULL; z = closure_returnupto(C); return z; } GEN closure_callgen0prec(GEN C, long prec) { GEN z; long i, ar = closure_arity(C); for(i=1; i<= ar; i++) gel(st,sp++) = NULL; push_localprec(prec); z = closure_returnupto(C); pop_localprec(); return z; } GEN closure_callgen1(GEN C, GEN x) { long i, ar = closure_arity(C); gel(st,sp++) = x; for(i=2; i<= ar; i++) gel(st,sp++) = NULL; return closure_returnupto(C); } GEN closure_callgen1prec(GEN C, GEN x, long prec) { GEN z; long i, ar = closure_arity(C); gel(st,sp++) = x; for(i=2; i<= ar; i++) gel(st,sp++) = NULL; push_localprec(prec); z = closure_returnupto(C); pop_localprec(); return z; } GEN closure_callgen2(GEN C, GEN x, GEN y) { long i, ar = closure_arity(C); st_alloc(ar); gel(st,sp++) = x; gel(st,sp++) = y; for(i=3; i<=ar; i++) gel(st,sp++) = NULL; return closure_returnupto(C); } GEN closure_callgenvec(GEN C, GEN args) { long i, l = lg(args)-1, ar = closure_arity(C); st_alloc(ar); if (l > ar) pari_err(e_MISC,"too many parameters in user-defined function call"); if (closure_is_variadic(C) && l==ar && typ(gel(args,l))!=t_VEC) pari_err_TYPE("call", gel(args,l)); for (i = 1; i <= l; i++) gel(st,sp++) = gel(args,i); for( ; i <= ar; i++) gel(st,sp++) = NULL; return closure_returnupto(C); } GEN closure_callgenvecprec(GEN C, GEN args, long prec) { GEN z; push_localprec(prec); z = closure_callgenvec(C, args); pop_localprec(); return z; } GEN closure_callgenvecdef(GEN C, GEN args, GEN def) { long i, l = lg(args)-1, ar = closure_arity(C); st_alloc(ar); if (l > ar) pari_err(e_MISC,"too many parameters in user-defined function call"); if (closure_is_variadic(C) && l==ar && typ(gel(args,l))!=t_VEC) pari_err_TYPE("call", gel(args,l)); for (i = 1; i <= l; i++) gel(st,sp++) = def[i] ? gel(args,i): NULL; for( ; i <= ar; i++) gel(st,sp++) = NULL; return closure_returnupto(C); } GEN closure_callgenvecdefprec(GEN C, GEN args, GEN def, long prec) { GEN z; push_localprec(prec); z = closure_callgenvecdef(C, args, def); pop_localprec(); return z; } GEN closure_callgenall(GEN C, long n, ...) { va_list ap; long i, ar = closure_arity(C); va_start(ap,n); if (n > ar) pari_err(e_MISC,"too many parameters in user-defined function call"); st_alloc(ar); for (i = 1; i <=n; i++) gel(st,sp++) = va_arg(ap, GEN); for( ; i <=ar; i++) gel(st,sp++) = NULL; va_end(ap); return closure_returnupto(C); } GEN gp_eval(void *E, GEN x) { GEN code = (GEN)E; set_lex(-1,x); return closure_evalnobrk(code); } GEN gp_evalupto(void *E, GEN x) { pari_sp av = avma; return copyupto(gp_eval(E,x), (GEN)av); } GEN gp_evalprec(void *E, GEN x, long prec) { GEN z; push_localprec(prec); z = gp_eval(E, x); pop_localprec(); return z; } long gp_evalbool(void *E, GEN x) { pari_sp av = avma; return gc_long(av, !gequal0(gp_eval(E,x))); } 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); } GEN gp_callprec(void *E, GEN x, long prec) { GEN code = (GEN)E; return closure_callgen1prec(code, x, prec); } GEN gp_call2(void *E, GEN x, GEN y) { GEN code = (GEN)E; return closure_callgen2(code, x, y); } long gp_callbool(void *E, GEN x) { pari_sp av = avma; GEN code = (GEN)E; return gc_long(av, !gequal0(closure_callgen1(code, x))); } long gp_callvoid(void *E, GEN x) { GEN code = (GEN)E; closure_callvoid1(code, x); return loop_break(); } INLINE const char * disassemble_cast(long mode) { switch (mode) { case Gsmall: return "small"; case Ggen: return "gen"; case Gvar: return "var"; case Gvoid: return "void"; default: return "unknown"; } } void closure_disassemble(GEN C) { const char * code; GEN oper; long i; if (typ(C)!=t_CLOSURE) pari_err_TYPE("disassemble",C); code=closure_codestr(C); oper=closure_get_oper(C); for(i=1;iname); break; } case OCpushdyn: { entree *ep = (entree *)operand; pari_printf("pushdyn\t\t%s\n",ep->name); break; } case OCpushlex: pari_printf("pushlex\t\t%ld\n",operand); break; case OCstoredyn: { entree *ep = (entree *)operand; pari_printf("storedyn\t%s\n",ep->name); break; } case OCstorelex: pari_printf("storelex\t%ld\n",operand); break; case OCstoreptr: pari_printf("storeptr\n"); break; case OCsimpleptrdyn: { entree *ep = (entree *)operand; pari_printf("simpleptrdyn\t%s\n",ep->name); break; } case OCsimpleptrlex: pari_printf("simpleptrlex\t%ld\n",operand); break; case OCnewptrdyn: { entree *ep = (entree *)operand; pari_printf("newptrdyn\t%s\n",ep->name); break; } case OCnewptrlex: pari_printf("newptrlex\t%ld\n",operand); break; case OCpushptr: pari_printf("pushptr\n"); break; case OCstackgen: pari_printf("stackgen\t%ld\n",operand); break; case OCendptr: pari_printf("endptr\t\t%ld\n",operand); break; case OCprecreal: pari_printf("precreal\n"); break; case OCbitprecreal: pari_printf("bitprecreal\n"); break; case OCprecdl: pari_printf("precdl\n"); break; case OCstoi: pari_printf("stoi\n"); break; case OCutoi: pari_printf("utoi\n"); break; case OCitos: pari_printf("itos\t\t%ld\n",operand); break; case OCitou: pari_printf("itou\t\t%ld\n",operand); break; case OCtostr: pari_printf("tostr\t\t%ld\n",operand); break; case OCvarn: pari_printf("varn\t\t%ld\n",operand); break; case OCcopy: pari_printf("copy\n"); break; case OCcopyifclone: pari_printf("copyifclone\n"); break; case OCcompo1: pari_printf("compo1\t\t%s\n",disassemble_cast(operand)); break; case OCcompo1ptr: pari_printf("compo1ptr\n"); break; case OCcompo2: pari_printf("compo2\t\t%s\n",disassemble_cast(operand)); break; case OCcompo2ptr: pari_printf("compo2ptr\n"); break; case OCcompoC: pari_printf("compoC\n"); break; case OCcompoCptr: pari_printf("compoCptr\n"); break; case OCcompoL: pari_printf("compoL\n"); break; case OCcompoLptr: pari_printf("compoLptr\n"); break; case OCcheckargs: pari_printf("checkargs\t0x%lx\n",operand); break; case OCcheckargs0: pari_printf("checkargs0\t0x%lx\n",operand); break; case OCcheckuserargs: pari_printf("checkuserargs\t%ld\n",operand); break; case OCdefaultlong: pari_printf("defaultlong\t%ld\n",operand); break; case OCdefaultulong: pari_printf("defaultulong\t%ld\n",operand); break; case OCdefaultgen: pari_printf("defaultgen\t%ld\n",operand); break; case OCpackargs: pari_printf("packargs\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 OCexportvar: { entree *ep = (entree *)operand; pari_printf("exportvar\t%s\n",ep->name); break; } case OCunexportvar: { entree *ep = (entree *)operand; pari_printf("unexportvar\t%s\n",ep->name); break; } case OCcallgen: { entree *ep = (entree *)operand; pari_printf("callgen\t\t%s\n",ep->name); break; } case OCcallgen2: { entree *ep = (entree *)operand; pari_printf("callgen2\t%s\n",ep->name); break; } case OCcalllong: { entree *ep = (entree *)operand; pari_printf("calllong\t%s\n",ep->name); break; } case OCcallint: { entree *ep = (entree *)operand; pari_printf("callint\t\t%s\n",ep->name); break; } case OCcallvoid: { entree *ep = (entree *)operand; pari_printf("callvoid\t%s\n",ep->name); break; } case OCcalluser: pari_printf("calluser\t%ld\n",operand); break; case OCvec: pari_printf("vec\t\t%ld\n",operand); break; case OCcol: pari_printf("col\t\t%ld\n",operand); break; case OCmat: pari_printf("mat\t\t%ld\n",operand); break; case OCnewframe: pari_printf("newframe\t%ld\n",operand); break; case OCsaveframe: pari_printf("saveframe\t%ld\n", operand); break; case OCpop: pari_printf("pop\t\t%ld\n",operand); break; case OCdup: pari_printf("dup\t\t%ld\n",operand); break; case OCavma: pari_printf("avma\n",operand); break; case OCgerepile: pari_printf("gerepile\n",operand); break; case OCcowvardyn: { entree *ep = (entree *)operand; pari_printf("cowvardyn\t%s\n",ep->name); break; } case OCcowvarlex: pari_printf("cowvarlex\t%ld\n",operand); break; case OCsetref: pari_printf("setref\t\t%ld\n",operand); break; case OClock: pari_printf("lock\t\t%ld\n",operand); break; case OCevalmnem: { entree *ep = (entree *)operand; pari_printf("evalmnem\t%s\n",ep->name); break; } } } } static int opcode_need_relink(op_code opcode) { switch(opcode) { case OCpushlong: case OCpushgen: case OCpushgnil: case OCpushreal: case OCpushstoi: case OCpushlex: case OCstorelex: case OCstoreptr: case OCsimpleptrlex: case OCnewptrlex: case OCpushptr: case OCstackgen: case OCendptr: case OCprecreal: case OCbitprecreal: case OCprecdl: case OCstoi: case OCutoi: case OCitos: case OCitou: case OCtostr: case OCvarn: case OCcopy: case OCcopyifclone: case OCcompo1: case OCcompo1ptr: case OCcompo2: case OCcompo2ptr: case OCcompoC: case OCcompoCptr: case OCcompoL: case OCcompoLptr: case OCcheckargs: case OCcheckargs0: case OCcheckuserargs: case OCpackargs: case OCgetargs: case OCdefaultarg: case OCdefaultgen: case OCdefaultlong: case OCdefaultulong: case OCcalluser: case OCvec: case OCcol: case OCmat: case OCnewframe: case OCsaveframe: case OCdup: case OCpop: case OCavma: case OCgerepile: case OCcowvarlex: case OCsetref: case OClock: break; case OCpushvar: case OCpushdyn: case OCstoredyn: case OCsimpleptrdyn: case OCnewptrdyn: case OClocalvar: case OClocalvar0: case OCexportvar: case OCunexportvar: case OCcallgen: case OCcallgen2: case OCcalllong: case OCcallint: case OCcallvoid: case OCcowvardyn: case OCevalmnem: return 1; } return 0; } static void closure_relink(GEN C, hashtable *table) { const char *code = closure_codestr(C); GEN oper = closure_get_oper(C); GEN fram = gel(closure_get_dbg(C),3); long i, j; for(i=1;ival; for (i=1;ival; } void gen_relink(GEN x, hashtable *table) { long i, lx, tx = typ(x); switch(tx) { case t_CLOSURE: closure_relink(x, table); gen_relink(closure_get_data(x), table); if (lg(x)==8) gen_relink(closure_get_frame(x), table); break; case t_LIST: if (list_data(x)) gen_relink(list_data(x), table); break; case t_VEC: case t_COL: case t_MAT: case t_ERROR: lx = lg(x); for (i=lontyp[tx]; ivalue) continue; gen_unlink((GEN)ep->value); } } n = s_relocs.n-nold; v = cgetg(n+1, t_VECSMALL); for(i=0; iname); } gel(res,1) = vecsmall_copy(w); gel(res,2) = V; return res; } /* e = t_VECSMALL of entree *ep [ addresses ], * names = t_VEC of strtoGENstr(ep.names), * Return hashtable : ep => is_entry(ep.name) */ hashtable * hash_from_link(GEN e, GEN names, int use_stack) { long i, l = lg(e); hashtable *h = hash_create_ulong(l-1, use_stack); if (lg(names) != l) pari_err_DIM("hash_from_link"); for (i = 1; i < l; i++) { char *s = GSTR(gel(names,i)); hash_insert(h, (void*)e[i], (void*)fetch_entry(s)); } return h; } void bincopy_relink(GEN C, GEN V) { pari_sp av = avma; hashtable *table = hash_from_link(gel(V,1),gel(V,2),1); gen_relink(C, table); set_avma(av); } pari-2.17.2/src/language/anal.h0000644000175000017500000000340514567450071014635 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*************************************************************************/ /* */ /* Declarations specific to the analyzer */ /* */ /*************************************************************************/ BEGINEXTERN /* functions */ void changevalue(entree *ep, GEN val); void freeep(entree *ep); void pari_fill_hashtable(entree **table, entree *ep); void compile_err(const char *msg, const char *str); void compile_varerr(const char *str); #ifdef STACK_CHECK extern THREAD void *PARI_stack_limit; #endif extern entree **varentries; struct node_loc { const char *start,*end; }; union token_value { long val; }; int pari_lex(union token_value *yylval, struct node_loc *yylloc, char **lex); int pari_parse(char **lex); entree* fetch_entry_raw(const char *s, long len); entree* fetch_entry(const char *s); void optimizenode(long n); void push_frame(GEN C, long lpc, long flag); GEN gp_closure(long n); long eval_mnemonic(GEN str, const char *tmplate); ENDEXTERN pari-2.17.2/src/language/parse.y0000644000175000017500000002202614676526175015067 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; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #define PARI_STYPE union token_value #define PARI_LTYPE struct node_loc #define YYPTRDIFF_T long #define YYPTRDIFF_MAXIMUM LONG_MAX #define YYSIZE_T size_t #define YYLLOC_DEFAULT(Current, Rhs, N) \ ((Current).start = ((N)?(Rhs)[1].start:(Rhs)[0].end), \ (Current).end = (Rhs)[N].end) #include "parsec.h" #define NOARG(x) newnode(Fnoarg,-1,-1,&(x)) #define NORANGE(x) newnode(Fnorange,-1,-1,&(x)) %} %define parse.error verbose %define api.prefix {pari_} %define api.pure full %parse-param {char **lex} %lex-param {char **lex} %initial-action{ @$.start=@$.end=*lex; } %token KPARROW ")->" %token KARROW "->" %token KDOTDOT ".." %token KPE "+=" %token KSE "-=" %token KME "*=" %token KDE "/=" %token KDRE "\\/=" %token KEUCE "\\=" %token KMODE "%=" %token KAND "&&" %token KOR "||" %token KID "===" %token KEQ "==" %token KNE "!=" %token KGE ">=" %token KLE "<=" %token KSRE ">>=" %token KSLE "<<=" %token KSR ">>" %token KSL "<<" %token KDR "\\/" %token KPP "++" %token KSS "--" %token KINTEGER "integer" %token KREAL "real number" %token KENTRY "variable name" %token KSTRING "character string" %left SEQ DEFFUNC %left INT LVAL %right ")->" "->" %left ';' ',' ".." %right '=' "+=" "-=" "*=" "/=" "\\/=" "\\=" "%=" ">>=" "<<=" %left '&' "&&" "||" %left "===" "==" "!=" '>' ">=" '<' "<=" %left '+' '-' %left '%' "\\/" '\\' '/' '*' ">>" "<<" %left SIGN %right '^' %left '#' %left '!' '~' '[' DERIV %left '\'' %left '.' %left "++" "--" %left '(' %left ':' %type seq sequence %type range matrix matrix_index expr exprno %type lvalue deriv %type matrixelts matrixeltsno matrixlines arg listarg definition %type funcid memberid %type backticks history %type compr in inseq %destructor { pari_discarded++; } seq matrix range matrix_index expr exprno lvalue matrixelts matrixeltsno matrixlines arg listarg definition funcid memberid backticks history compr in inseq deriv %% sequence: seq {$$=$1; (void) pari_nerrs;} /* skip the destructor */ ; seq: /**/ %prec SEQ {$$=NOARG(@$);} | expr %prec SEQ {$$=$1;} | seq ';' {$$=$1; @$=@1;} | seq ';' expr {$$=newnode(Fseq,$1,$3,&@$);} ; range: /* */ { $$=newnode(Frange,NORANGE(@$),NORANGE(@$),&@$); } | expr { $$=newnode(Frange,$1,NORANGE(@$),&@$); } | expr ".." expr { $$=newnode(Frange,$1,$3,&@$); } | '^' expr { $$=newnode(Frange,NORANGE(@$),$2,&@$); } ; matrix_index: '[' range ',' range ']' {$$=newnode(Fmatrix,$2,$4,&@$);} | '[' range ']' {$$=newnode(Fmatrix,$2,-1,&@$);} ; backticks: '`' {$$=1;} | backticks '`' {$$=$1+1;} ; history: '%' {$$=newopcall(OPhist,-1,-1,&@$);} | '%' KINTEGER {$$=newopcall(OPhist,newintnode(&@2),-1,&@$);} | '%' backticks {$$=newopcall(OPhist,newnode(Fsmall,-$2,-1,&@$),-1,&@$);} | '%' '#' {$$=newopcall(OPhisttime,-1,-1,&@$);} | '%' '#' KINTEGER {$$=newopcall(OPhisttime,newintnode(&@3),-1,&@$);} | '%' '#' backticks{$$=newopcall(OPhisttime,newnode(Fsmall,-$3,-1,&@$),-1,&@$);} ; deriv: '\'' {$$ = 1;} | deriv '\'' {$$ = $1+1;} ; expr: KINTEGER %prec INT {$$=newintnode(&@1);} | KREAL {$$=newconst(CSTreal,&@$);} | '.' {$$=newconst(CSTreal,&@$);} | KINTEGER '.' KENTRY {$$=newnode(Ffunction,newconst(CSTmember,&@3), newintnode(&@1),&@$);} | KSTRING {$$=newconst(CSTstr,&@$);} | '\'' KENTRY {$$=newconst(CSTquote,&@$);} | history {$$=$1;} | expr '(' listarg ')' {$$=newnode(Fcall,$1,$3,&@$);} | funcid {$$=$1;} | lvalue %prec LVAL {$$=$1;} | matrix {$$=$1;} | compr {$$=$1;} | definition {$$=$1;} | matrix '=' expr {$$=newnode(Fassign,$1,$3,&@$);} | lvalue '=' expr {$$=newnode(Fassign,$1,$3,&@$);} | lvalue "++" {$$=newopcall(OPpp,$1,-1,&@$);} | lvalue "--" {$$=newopcall(OPss,$1,-1,&@$);} | lvalue "*=" expr {$$=newopcall(OPme,$1,$3,&@$);} | lvalue "/=" expr {$$=newopcall(OPde,$1,$3,&@$);} | lvalue "\\/=" expr {$$=newopcall(OPdre,$1,$3,&@$);} | lvalue "\\=" expr {$$=newopcall(OPeuce,$1,$3,&@$);} | lvalue "%=" expr {$$=newopcall(OPmode,$1,$3,&@$);} | lvalue "<<=" expr {$$=newopcall(OPsle,$1,$3,&@$);} | lvalue ">>=" expr {$$=newopcall(OPsre,$1,$3,&@$);} | lvalue "+=" expr {$$=newopcall(OPpe,$1,$3,&@$);} | lvalue "-=" expr {$$=newopcall(OPse,$1,$3,&@$);} | '!' expr {$$=newopcall(OPnb,$2,-1,&@$);} | '#' expr {$$=newopcall(OPlength,$2,-1,&@$);} | expr "||" expr {$$=newopcall(OPor,$1,$3,&@$);} | expr "&&" expr {$$=newopcall(OPand,$1,$3,&@$);} | expr '&' expr {$$=newopcall(OPand,$1,$3,&@$);} | expr "===" expr {$$=newopcall(OPid,$1,$3,&@$);} | expr "==" expr {$$=newopcall(OPeq,$1,$3,&@$);} | expr "!=" expr {$$=newopcall(OPne,$1,$3,&@$);} | expr ">=" expr {$$=newopcall(OPge,$1,$3,&@$);} | expr '>' expr {$$=newopcall(OPg,$1,$3,&@$);} | expr "<=" expr {$$=newopcall(OPle,$1,$3,&@$);} | expr '<' expr {$$=newopcall(OPl,$1,$3,&@$);} | expr '-' expr {$$=newopcall(OPs,$1,$3,&@$);} | expr '+' expr {$$=newopcall(OPp,$1,$3,&@$);} | expr "<<" expr {$$=newopcall(OPsl,$1,$3,&@$);} | expr ">>" expr {$$=newopcall(OPsr,$1,$3,&@$);} | expr '%' expr {$$=newopcall(OPmod,$1,$3,&@$);} | expr "\\/" expr {$$=newopcall(OPdr,$1,$3,&@$);} | expr '\\' expr {$$=newopcall(OPeuc,$1,$3,&@$);} | expr '/' expr {$$=newopcall(OPd,$1,$3,&@$);} | expr '*' expr {$$=newopcall(OPm,$1,$3,&@$);} | '+' expr %prec SIGN {$$=$2;} | '-' expr %prec SIGN {$$=newopcall(OPn,$2,-1,&@$);} | expr '^' expr {$$=newopcall(OPpow,$1,$3,&@$);} | expr '~' {$$=newopcall(OPtrans,$1,-1,&@$);} | expr deriv %prec DERIV {$$=newopcall(OPderivn,$1, newnode(Fsmall,$2,-1,&@$),&@$);} | expr '!' {$$=newopcall(OPfact,$1,-1,&@$);} | expr '#' {$$=newopcall(OPprim,$1,-1,&@$);} | expr matrix_index {$$=newnode(Fmatcoeff,$1,$2,&@$);} | memberid {$$=$1;} | expr ':' KENTRY {$$=newnode(Ftag,$1,0,&@$);} | '(' expr ')' {$$=$2;} ; lvalue: KENTRY %prec LVAL {$$=newnode(Fentry,newconst(CSTentry,&@1),-1,&@$);} | lvalue matrix_index {$$=newnode(Fmatcoeff,$1,$2,&@$);} | lvalue ':' KENTRY {$$=newnode(Ftag,$1,newconst(CSTentry,&@2),&@$);} ; exprno: expr {$$=$1;} | /**/ {$$=NOARG(@$);} matrixeltsno: matrixelts {$$=$1;} | /**/ {$$=NOARG(@$);} ; matrixelts: expr {$$=$1;} | matrixeltsno ',' exprno {$$=newnode(Fmatrixelts,$1,$3,&@$);} ; matrixlines: matrixelts ';' matrixelts {$$=newnode(Fmatrixlines,$1,$3,&@$);} | matrixlines ';' matrixelts {$$=newnode(Fmatrixlines,$1,$3,&@$);} ; matrix: '[' ']' {$$=newnode(Fvec,-1,-1,&@$);} | '[' expr ".." expr ']' {$$=newopcall(OPrange,$2,$4,&@$);} | '[' ';' ']' {$$=newnode(Fmat,-1,-1,&@$);} | '[' matrixelts ']' {$$=newnode(Fvec,$2,-1,&@$);} | '[' matrixlines ']' {$$=newnode(Fmat,$2,-1,&@$);} ; in: lvalue '<' '-' expr {$$=newnode(Flistarg,$4,$1,&@$);} ; inseq: in {$$=newopcall(OPcompr,$1,-2,&@$);} | in ',' expr {$$=newopcall3(OPcompr,$1,-2,$3,&@$);} | in ';' inseq {$$=newopcall(OPcomprc,$1,$3,&@$);} | in ',' expr ';' inseq {$$=newopcall3(OPcomprc,$1,$5,$3,&@$);} ; compr: '[' expr '|' inseq ']' {$$=addcurrexpr($4,$2,&@$);} ; arg: seq {$$=$1;} | lvalue '[' ".." ']' {$$=newnode(Fvararg,$1,-1,&@$);} | '&' lvalue {$$=newnode(Frefarg,$2,-1,&@$);} | '~' lvalue {$$=newnode(Findarg,$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,newnode(Findarg,$1,-1,&@1),$5,&@$);} | lvalue "->" seq {$$=newnode(Flambda, $1,$3,&@$);} | '(' listarg ")->" seq {$$=newnode(Flambda, $2,$4,&@$);} ; %% pari-2.17.2/src/language/intnum.c0000644000175000017500000023642114676526175015247 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_intnum static GEN intlin(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN tab, long prec); /********************************************************************/ /** 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)); } /* h and s are arrays of the same length L > D. The h[i] are (decreasing) * step sizes, s[i] is the computed Riemann sum for step size h[i]. * Interpolate the last D+1 values so that s ~ polynomial in h of degree D. * Guess that limit_{h->0} = s(0) */ static GEN interp(GEN h, GEN s, long L, long bit, long D) { pari_sp av = avma; long e1,e2; GEN ss = polintspec(h + L-D, s + L-D, gen_0, D+1, &e2); e1 = gexpo(ss); if (DEBUGLEVEL>2) { err_printf("romb: iteration %ld, guess: %Ps\n", L,ss); err_printf("romb: relative error < 2^-%ld [target %ld bits]\n",e1-e2,bit); } if (e1-e2 <= bit && (L <= 10 || e1 >= -bit)) return gc_NULL(av); return cxtoreal(ss); } static GEN qrom3(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, long bit) { const long JMAX = 25, KLOC = 4; GEN ss,s,h,p1,p2,qlint,del,x,sum; long j, j1, it, sig, prec = nbits2prec(bit); 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; j= KLOC && (ss = interp(h, s, j, bit-j-6, KLOC))) return gmulsg(sig,ss); } pari_err_IMPL("intnumromb recovery [too many iterations]"); return NULL; /* LCOV_EXCL_LINE */ } static GEN qrom2(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, long bit) { const long JMAX = 16, KLOC = 4; GEN ss,s,h,p1,qlint,del,ddel,x,sum; long j, j1, it, sig, prec = nbits2prec(bit); 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; j= KLOC && (ss = interp(h, s, j, bit-(3*j/2)+3, KLOC))) return gmulsg(sig, ss); } pari_err_IMPL("intnumromb recovery [too many iterations]"); return NULL; /* LCOV_EXCL_LINE */ } /* integrate after change of variables x --> 1/x */ static GEN qromi(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, long bit) { GEN A = ginv(b), B = ginv(a); invfun S; S.f = eval; S.E = E; return qrom2(&S, &_invf, A, B, bit); } /* a < b, assume b "small" (< 100 say) */ static GEN rom_bsmall(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, long bit) { if (gcmpgs(a,-100) >= 0) return qrom2(E,eval,a,b,bit); if (gcmpgs(b, -1) < 0) return qromi(E,eval,a,b,bit); /* a<-100, b<-1 */ /* a<-100, b>=-1, split at -1 */ return gadd(qromi(E,eval,a,gen_m1,bit), qrom2(E,eval,gen_m1,b,bit)); } static GEN rombint(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, long bit) { 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,bit); else /* split at 1 */ z = gadd(rom_bsmall(E,eval,a,gen_1,bit), qromi(E,eval,gen_1,b,bit)); } else z = rom_bsmall(E,eval,a,b,bit); if (l < 0) z = gneg(z); return z; } GEN intnumromb(void *E, GEN (*f)(void *, GEN), GEN a,GEN b, long fl, long B) { pari_sp av = avma; GEN z; switch(fl) { case 0: z = qrom3 (E, f, a, b, B); break; case 1: z = rombint(E, f, a, b, B); break; case 2: z = qromi (E, f, a, b, B); break; case 3: z = qrom2 (E, f, a, b, B); break; default: pari_err_FLAG("intnumromb"); return NULL; /* LCOV_EXCL_LINE */ } return gerepileupto(av, z); } GEN intnumromb0(GEN a, GEN b, GEN code, long flag, long bit) { EXPR_WRAP(code, intnumromb(EXPR_ARG, a, b, flag, bit)); } /********************************************************************/ /** NUMERICAL INTEGRATION (Gauss-Legendre) **/ /********************************************************************/ /* N > 1; S[n] = n^2. If !last, Newton step z - P_N(z) / P'_N(z), * else [z, (N-1)!P_{N-1}(z)]. */ static GEN Legendrenext(long N, GEN z, GEN S, int last) { GEN q, Z, a, b, z2 = sqrr(z); long n, n0, u; q = subrs(mulur(3, z2), 1); if (odd(N)) { n0 = 3; a = mulrr(z2, subrs(mulur(5, q), 4)); b = q; } else { n0 = 2; a = mulrr(q, z); b = z; } for (n = n0, u = 2*n0 + 1; n < N; n += 2, u += 4) { b = subrr(mulur(u, a), mulir(gel(S,n), b)); a = subrr(mulur(u + 2, mulrr(z2, b)), mulir(gel(S,n+1), a)); } q = divrr(a, subrr(a, mulur(N, b))); Z = subrr(z, divrr(mulrr(subrs(z2, 1), q), mulur(N, z))); return last? mkvec2(Z, mulrr(b, addrs(q, 1))): Z; } /* root ~ dz of Legendre polynomial P_N */ static GEN Legendreroot(long N, double dz, GEN S, long bit) { GEN z = dbltor(dz); long e = - dblexpo(1 - dz*dz), n = expu(bit + 32 - e) - 2; long j, pr = 1 + e + ((bit - e) >> n); for (j = 1; j <= n; j++) { pr = 2 * pr - e; z = Legendrenext(N, rtor(z, nbits2prec(pr)), S, j == n); } return z; } GEN intnumgaussinit(long N, long prec) { pari_sp av; long N2, j, k, l, lV; GEN res, V, W, F, S; double d; prec += EXTRAPREC64; if (N <= 0) { N = prec >> 2; if (odd(N)) N++; } if (N == 1) retmkvec2(mkvec(gen_0), mkvec(gen_2)); l = prec2lg(prec); res = cgetg(3, t_VEC); if (N == 2) { GEN z = cgetg(l, t_REAL); gel(res,1) = mkvec(z); gel(res,2) = mkvec(gen_1); av = avma; affrr(divru(sqrtr(utor(3,prec)), 3), z); return gc_const(av, res); } N2 = N >> 1; lV = (N+3)>> 1; gel(res,1) = V = cgetg(lV, t_VEC); gel(res,2) = W = cgetg(lV, t_VEC); gel(V,1) = odd(N)? gen_0: cgetg(l, t_REAL); gel(W,1) = cgetg(l, t_REAL); for (k = 2; k < lV; k++) { gel(V,k) = cgetg(l, t_REAL); gel(W,k) = cgetg(l, t_REAL); } av = avma; S = vecpowuu(N, 2); F = sqrr(mpfactr(N-1, prec)); if (!odd(N)) k = 1; else { GEN c = divrr(sqrr(sqrr(mpfactr(N2, prec))), mulri(F, gel(S,N))); shiftr_inplace(c, 2*N-1); affrr(c, gel(W,1)); k = 2; } F = divri(shiftr(F, 1), gel(S,N)); d = 1 - (N-1) / pow((double)(2*N),3); for (j = 4*N2-1; j >= 3; k++, j -= 4) { pari_sp av2 = avma; GEN zw = Legendreroot(N, d * cos(M_PI * j / (4*N+2)), S, prec); GEN z = gel(zw,1), w = gel(zw,2); affrr(z, gel(V,k)); w = mulrr(F, divrr(subsr(1, sqrr(z)), sqrr(w))); affrr(w, gel(W,k)); set_avma(av2); } return gc_const(av, res); } GEN intnumgauss(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN tab, long prec) { pari_sp ltop = avma; GEN R, W, bma, bpa, S; long n, i, prec2 = prec + EXTRAPREC64; if (!tab) tab = intnumgaussinit(0,prec); else if (typ(tab) != t_INT) { if (typ(tab) != t_VEC || lg(tab) != 3 || typ(gel(tab,1)) != t_VEC || typ(gel(tab,2)) != t_VEC || lg(gel(tab,1)) != lg(gel(tab,2))) pari_err_TYPE("intnumgauss",tab); } else tab = intnumgaussinit(itos(tab),prec); R = gel(tab,1); n = lg(R)-1; W = gel(tab,2); a = gprec_wensure(a, prec2); b = gprec_wensure(b, prec2); bma = gmul2n(gsub(b,a), -1); /* (b-a)/2 */ bpa = gadd(bma, a); /* (b+a)/2 */ if (!signe(gel(R,1))) { /* R[1] = 0, use middle node only once */ S = gmul(gel(W,1), eval(E, bpa)); i = 2; } else { S = gen_0; i = 1; } for (; i <= n; ++i) { GEN h = gmul(bma, gel(R,i)); /* != 0 */ GEN P = eval(E, gadd(bpa, h)); GEN M = eval(E, gsub(bpa, h)); S = gadd(S, gmul(gel(W,i), gadd(P,M))); S = gprec_wensure(S, prec2); } return gerepilecopy(ltop, gprec_wtrunc(gmul(bma,S), prec)); } GEN intnumgauss0(GEN a, GEN b, GEN code, GEN tab, long prec) { EXPR_WRAP(code, intnumgauss(EXPR_ARG, a, b, tab, prec)); } /********************************************************************/ /** DOUBLE EXPONENTIAL INTEGRATION **/ /********************************************************************/ typedef struct _intdata { long bit; /* bit accuracy of current precision */ long l; /* table lengths */ GEN tabx0; /* abscissa phi(0) for t = 0 */ GEN tabw0; /* weight phi'(0) for t = 0 */ GEN tabxp; /* table of abscissas phi(kh) for k > 0 */ GEN tabwp; /* table of weights phi'(kh) for k > 0 */ GEN tabxm; /* table of abscissas phi(kh) for k < 0, possibly empty */ GEN tabwm; /* table of weights phi'(kh) for k < 0, possibly empty */ GEN h; /* integration step */ } intdata; static const long LGTAB = 8; #define TABh(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) { return is_real_t(typ(z)); } 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) != LGTAB) 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) != LGTAB) 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)); } /* the TUNE parameter is heuristic */ static void intinit_start(intdata *D, long m, double TUNE, long prec) { long l, n; double d = prec*LOG10_2; GEN h, nh, pi = mppi(prec); n = (long)ceil(d*log(d) / TUNE); /* heuristic */ /* nh ~ log(2npi/log(n)) */ nh = logr_abs(divrr(mulur(2*n, pi), logr_abs(utor(n,prec)))); h = divru(nh, n); if (m > 0) { h = gmul2n(h,-m); n <<= m; } D->h = h; D->bit = prec; D->l = l = n+1; D->tabxp = cgetg(l, t_VEC); D->tabwp = cgetg(l, t_VEC); D->tabxm = cgetg(l, t_VEC); D->tabwm = cgetg(l, t_VEC); } static GEN intinit_end(intdata *D, long pnt, long mnt) { GEN v = cgetg(LGTAB, t_VEC); if (pnt < 0) pari_err_DOMAIN("intnuminit","table length","<",gen_0,stoi(pnt)); TABx0(v) = D->tabx0; TABw0(v) = D->tabw0; TABh(v) = D->h; 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) { shiftr_inplace(x, -1); return x; } /* phi(t)=tanh((Pi/2)sinh(t)): from -1 to 1, hence also from a to b compact * interval */ static GEN inittanhsinh(long m, long prec) { GEN e, ei, ek, eik, pi = mppi(prec); long k, l, nt = -1; intdata D; intinit_start(&D, m, 1.86, prec); D.tabx0 = real_0(prec); D.tabw0 = Pi2n(-1,prec); e = mpexp(D.h); ek = mulrr(pi, e); ei = invr(e); eik = mulrr(pi, ei); l = prec2lg(prec); for (k = 1; k < D.l; k++) { GEN xp, wp, ct, st, z; pari_sp av; gel(D.tabxp,k) = cgetg(l, t_REAL); gel(D.tabwp,k) = cgetg(l, t_REAL); av = avma; ct = divr2_ip(addrr(ek, eik)); /* Pi ch(kh) */ st = subrr(ek, ct); /* Pi sh(kh) */ z = invr( addrs(mpexp(st), 1) ); shiftr_inplace(z, 1); if (expo(z) < -D.bit) { nt = k-1; break; } xp = subsr(1, z); wp = divr2_ip(mulrr(ct, subsr(1, sqrr(xp)))); affrr(xp, gel(D.tabxp,k)); mulrrz(ek, e, ek); affrr(wp, gel(D.tabwp,k)); mulrrz(eik, ei, eik); set_avma(av); } return intinit_end(&D, nt, 0); } /* phi(t)=sinh(sinh(t)): from -oo to oo, slowly decreasing, at least * as 1/x^2. */ static GEN initsinhsinh(long m, long prec) { pari_sp av; GEN et, ct, st, ex; long k, l, nt = -1; intdata D; intinit_start(&D, m, 0.666, prec); D.tabx0 = real_0(prec); D.tabw0 = real_1(prec); et = ex = mpexp(D.h); l = prec2lg(prec); for (k = 1; k < D.l; k++) { GEN xp, wp, ext, exu; gel(D.tabxp,k) = cgetg(l, t_REAL); gel(D.tabwp,k) = cgetg(l, t_REAL); 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.bit) { nt = k-1; break; } affrr(xp, gel(D.tabxp,k)); affrr(wp, gel(D.tabwp,k)); et = gerepileuptoleaf(av, mulrr(et, ex)); } return intinit_end(&D, nt, 0); } /* phi(t)=2sinh(t): from -oo to oo, exponentially decreasing as exp(-x) */ static GEN initsinh(long m, long prec) { pari_sp av; GEN et, ex, eti, xp, wp; long k, l, nt = -1; intdata D; intinit_start(&D, m, 1.0, prec); D.tabx0 = real_0(prec); D.tabw0 = real2n(1, prec); et = ex = mpexp(D.h); l = prec2lg(prec); for (k = 1; k < D.l; k++) { gel(D.tabxp,k) = cgetg(l, t_REAL); gel(D.tabwp,k) = cgetg(l, t_REAL); av = avma; eti = invr(et); xp = subrr(et, eti); wp = addrr(et, eti); if (cmprs(xp, (long)(M_LN2*(expo(wp)+D.bit) + 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 intinit_end(&D, nt, 0); } /* phi(t)=exp(2sinh(t)): from 0 to oo, slowly decreasing at least as 1/x^2 */ static GEN initexpsinh(long m, long prec) { GEN et, ex; long k, nt = -1; intdata D; intinit_start(&D, m, 1.05, prec); D.tabx0 = real_1(prec); D.tabw0 = real2n(1, prec); ex = mpexp(D.h); et = real_1(prec); for (k = 1; k < D.l; k++) { GEN t, eti, xp; et = mulrr(et, ex); eti = invr(et); t = addrr(et, eti); xp = mpexp(subrr(et, eti)); gel(D.tabxp,k) = xp; gel(D.tabwp,k) = mulrr(xp, t); gel(D.tabxm,k) = invr(xp); gel(D.tabwm,k) = mulrr(gel(D.tabxm,k), t); if (expo(gel(D.tabxm,k)) < -D.bit) { nt = k-1; break; } } return intinit_end(&D, nt, nt); } /* phi(t)=exp(t-exp(-t)) : from 0 to +oo, exponentially decreasing. */ static GEN initexpexp(long m, long prec) { pari_sp av; GEN et, ex; long k, l, nt = -1; intdata D; intinit_start(&D, m, 1.76, prec); D.tabx0 = mpexp(real_m1(prec)); D.tabw0 = gmul2n(D.tabx0, 1); et = ex = mpexp(negr(D.h)); l = prec2lg(prec); for (k = 1; k < D.l; k++) { GEN xp, xm, wp, wm, eti, kh; gel(D.tabxp,k) = cgetg(l, t_REAL); gel(D.tabwp,k) = cgetg(l, t_REAL); gel(D.tabxm,k) = cgetg(l, t_REAL); gel(D.tabwm,k) = cgetg(l, t_REAL); av = avma; eti = invr(et); kh = mulur(k,D.h); xp = mpexp(subrr(kh, et)); xm = mpexp(negr(addrr(kh, eti))); wp = mulrr(xp, addsr(1, et)); if (expo(xm) < -D.bit && cmprs(xp, (long)(M_LN2*(expo(wp)+D.bit) + 1)) > 0) { nt = k-1; break; } wm = mulrr(xm, addsr(1, eti)); 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 intinit_end(&D, nt, nt); } /* phi(t)=(Pi/h)*t/(1-exp(-sinh(t))) from 0 to oo, sine oscillation */ static GEN initnumsine(long m, long prec) { pari_sp av; GEN invh, et, eti, ex, pi = mppi(prec); long exh, k, l, nt = -1; intdata D; intinit_start(&D, m, 0.666, prec); invh = invr(D.h); D.tabx0 = mulrr(pi, invh); D.tabw0 = gmul2n(D.tabx0,-1); exh = expo(invh); /* expo(1/h) */ et = ex = mpexp(D.h); l = prec2lg(prec); for (k = 1; k < D.l; k++) { GEN xp,xm, wp,wm, ct,st, extp,extp1,extp2, extm,extm1,extm2, kct, kpi; gel(D.tabxp,k) = cgetg(l, t_REAL); gel(D.tabwp,k) = cgetg(l, t_REAL); gel(D.tabxm,k) = cgetg(l, t_REAL); gel(D.tabwm,k) = cgetg(l, t_REAL); av = avma; eti = invr(et); /* exp(-kh) */ ct = divr2_ip(addrr(et, eti)); /* ch(kh) */ st = divr2_ip(subrr(et, eti)); /* sh(kh) */ extp = mpexp(st); extp1 = subsr(1, extp); extp2 = invr(extp1); /* 1/(1-exp(sh(kh))) */ extm = invr(extp); extm1 = subsr(1, extm); extm2 = invr(extm1);/* 1/(1-exp(sh(-kh))) */ kpi = mulur(k, pi); kct = mulur(k, ct); extm1 = mulrr(extm1, invh); extp1 = mulrr(extp1, invh); xp = mulrr(kpi, extm2); /* phi(kh) */ wp = mulrr(subrr(extm1, mulrr(kct, extm)), mulrr(pi, sqrr(extm2))); xm = mulrr(negr(kpi), extp2); /* phi(-kh) */ wm = mulrr(addrr(extp1, mulrr(kct, extp)), mulrr(pi, sqrr(extp2))); if (expo(wm) < -D.bit && expo(extm) + exh + expu(10 * k) < -D.bit) { 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 intinit_end(&D, nt, nt); } /* End of initialization functions. These functions can be executed once * and for all for a given accuracy and type of integral ([a,b], [a,oo[ or * ]-oo,a], ]-oo,oo[) */ /* The numbers below can be changed, but NOT the ordering */ enum { f_REG = 0, /* regular function */ f_SER = 1, /* power series */ f_SINGSER = 2, /* algebraic singularity, power series endpoint */ f_SING = 3, /* algebraic singularity */ f_YSLOW = 4, /* oo, slowly decreasing, at least x^(-2) */ f_YVSLO = 5, /* oo, very slowly decreasing, worse than x^(-2) */ f_YFAST = 6, /* oo, exponentially decreasing */ f_YOSCS = 7, /* oo, sine oscillating */ f_YOSCC = 8 /* oo, cosine oscillating */ }; /* is finite ? */ static int is_fin_f(long c) { return c == f_REG || c == f_SER || c == f_SING; } /* is oscillatory ? */ static int is_osc(long c) { long a = labs(c); return a == f_YOSCC|| a == f_YOSCS; } /* 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; long i, prec; pari_sp ltop = avma, av; if (!checktabsimp(tab)) pari_err_TYPE("intnum",tab); tabx0 = TABx0(tab); tabw0 = TABw0(tab); prec = gprecision(tabw0); tabxp = TABxp(tab); tabwp = TABwp(tab); bpa = gmul2n(gadd(b, a), -1); /* (b+a)/2 */ bma = gsub(bpa, a); /* (b-a)/2 */ av = avma; bmb = gmul(bma, tabx0); /* (b-a)/2 phi(0) */ /* phi'(0) f( (b+a)/2 + (b-a)/2 * phi(0) ) */ S = gmul(tabw0, eval(E, gadd(bpa, bmb))); for (i = lg(tabxp)-1; i > 0; i--) { GEN SP, SM; 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); S = gprec_wensure(S, prec); } return gerepileupto(ltop, gmul(S, gmul(bma, TABh(tab)))); } /* compute \int_a^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) { GEN tabx0, tabw0, tabxp, tabwp, ea, ba, S; long i, prec; pari_sp ltop = avma, av; if (!checktabsimp(tab)) pari_err_TYPE("intnum",tab); tabx0 = TABx0(tab); tabw0 = TABw0(tab); prec = gprecision(tabw0); tabxp = TABxp(tab); tabwp = TABwp(tab); ea = ginv(gaddsg(1, gel(a,2))); a = gel(a,1); ba = gdiv(gsub(b, a), gpow(gen_2, ea, prec)); av = avma; S = gmul(gmul(tabw0, ba), eval(E, gadd(gmul(ba, addsr(1, tabx0)), a))); for (i = lg(tabxp)-1; i > 0; i--) { GEN p = addsr(1, gel(tabxp,i)); GEN m = subsr(1, gel(tabxp,i)); GEN bp = gmul(ba, gpow(p, ea, prec)); GEN bm = gmul(ba, gpow(m, ea, prec)); GEN SP = gmul(gdiv(bp, p), eval(E, gadd(bp, a))); GEN SM = gmul(gdiv(bm, m), eval(E, gadd(bm, a))); S = gadd(S, gmul(gel(tabwp,i), gadd(SP, SM))); if ((i & 0x7f) == 1) S = gerepileupto(av, S); S = gprec_wensure(S, prec); } return gerepileupto(ltop, gmul(gmul(S, TABh(tab)), ea)); } static GEN id(GEN x) { return x; } /* compute \int_a^oo f(t)dt if si>0 or \int_{-oo}^a f(t)dt if si<0$. * 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 sb, GEN tab) { GEN tabx0, tabw0, tabxp, tabwp, tabxm, tabwm; GEN S; long L, i, prec; pari_sp av = avma; if (!checktabdoub(tab)) pari_err_TYPE("intnum",tab); tabx0 = TABx0(tab); tabw0 = TABw0(tab); prec = gprecision(tabw0); tabxp = TABxp(tab); tabwp = TABwp(tab); L = lg(tabxp); tabxm = TABxm(tab); tabwm = TABwm(tab); if (gequal0(a)) { GEN (*NEG)(GEN) = sb > 0? id: gneg; S = gmul(tabw0, eval(E, NEG(tabx0))); for (i = 1; i < L; i++) { GEN SP = eval(E, NEG(gel(tabxp,i))); GEN SM = eval(E, NEG(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); S = gprec_wensure(S, prec); } } else if (gexpo(a) <= 0 || is_osc(sb)) { /* a small */ GEN (*ADD)(GEN,GEN) = sb > 0? gadd: gsub; S = gmul(tabw0, eval(E, ADD(a, tabx0))); for (i = 1; i < L; i++) { GEN SP = eval(E, ADD(a, gel(tabxp,i))); GEN SM = eval(E, ADD(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); S = gprec_wensure(S, prec); } } else { /* a large, |a|*\int_sgn(a)^{oo} f(|a|*x)dx (sb > 0)*/ GEN (*ADD)(long,GEN) = sb > 0? addsr: subsr; long sa = gsigne(a); GEN A = sa > 0? a: gneg(a); pari_sp av2 = avma; S = gmul(tabw0, eval(E, gmul(A, ADD(sa, tabx0)))); for (i = 1; i < L; i++) { GEN SP = eval(E, gmul(A, ADD(sa, gel(tabxp,i)))); GEN SM = eval(E, gmul(A, ADD(sa, gel(tabxm,i)))); S = gadd(S, gadd(gmul(gel(tabwp,i), SP), gmul(gel(tabwm,i), SM))); if ((i & 0x7f) == 1) S = gerepileupto(av2, S); S = gprec_wensure(S, prec); } S = gmul(S,A); } return gerepileupto(av, gmul(S, TABh(tab))); } /* Compute \int_{-oo}^oo 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)). */ static GEN intninfinf(void *E, GEN (*eval)(void*, GEN), GEN tab) { GEN tabx0, tabw0, tabxp, tabwp, tabwm; GEN S; long L, i, prec, spf; pari_sp ltop = avma; if (!checktabsimp(tab)) pari_err_TYPE("intnum",tab); tabx0 = TABx0(tab); tabw0 = TABw0(tab); prec = gprecision(tabw0); tabxp = TABxp(tab); tabwp = TABwp(tab); L = lg(tabxp); tabwm = TABwm(tab); spf = (lg(tabwm) == lg(tabwp)); S = gmul(tabw0, eval(E, tabx0)); if (spf) S = gmul2n(real_i(S), -1); for (i = L-1; i > 0; i--) { GEN SP = eval(E, gel(tabxp,i)); if (spf) S = gadd(S, real_i(gmul(gel(tabwp,i), SP))); else { GEN SM = eval(E, negr(gel(tabxp,i))); S = gadd(S, gmul(gel(tabwp,i), gadd(SP,SM))); } if ((i & 0x7f) == 1) S = gerepileupto(ltop, S); S = gprec_wensure(S, prec); } if (spf) S = gmul2n(S,1); return gerepileupto(ltop, gmul(S, TABh(tab))); } /* general num integration routine int_a^b f(t)dt, where a and b are as follows: - a scalar : the scalar, no singularity worse than logarithmic at a. - [a, e] : the scalar a, singularity exponent -1 < e <= 0. - +oo: slowly decreasing function (at least O(t^-2)) - [[+oo], a], a nonnegative real : +oo, function behaving like exp(-a|t|) - [[+oo], e], e < -1 : +oo, function behaving like t^e - [[+oo], a*I], a > 0 real : +oo, function behaving like cos(at) - [[+oo], a*I], a < 0 real : +oo, function behaving like sin(at) and similarly at -oo */ static GEN f_getycplx(GEN a, long prec) { GEN a2R, a2I; long s; 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); return ginv(gprec_wensure(s ? a2I : a2R, prec)); } static void err_code(GEN a, const char *name) { char *s = stack_sprintf("intnum [incorrect %s]", name); pari_err_TYPE(s, a); } /* a = [[+/-oo], alpha]*/ static long code_aux(GEN a, const char *name) { GEN re, im, alpha = gel(a,2); long s; if (!isinC(alpha)) err_code(a, name); re = real_i(alpha); im = imag_i(alpha); s = gsigne(im); if (s) { if (!gequal0(re)) err_code(a, name); return s > 0 ? f_YOSCC : f_YOSCS; } if (gequal0(re) || gcmpgs(re, -2)<=0) return f_YSLOW; if (gsigne(re) > 0) return f_YFAST; if (gcmpgs(re, -1) >= 0) err_code(a, name); return f_YVSLO; } static long transcode(GEN a, const char *name) { GEN a1, a2; switch(typ(a)) { case t_VEC: break; case t_INFINITY: return inf_get_sign(a) == 1 ? f_YSLOW: -f_YSLOW; case t_SER: case t_POL: case t_RFRAC: return f_SER; default: if (!isinC(a)) err_code(a,name); return f_REG; } switch(lg(a)) { case 2: return gsigne(gel(a,1)) > 0 ? f_YSLOW : -f_YSLOW; case 3: break; default: err_code(a,name); } a1 = gel(a,1); a2 = gel(a,2); switch(typ(a1)) { case t_VEC: if (lg(a1) != 2) err_code(a,name); return gsigne(gel(a1,1)) * code_aux(a, name); case t_INFINITY: return inf_get_sign(a1) * code_aux(a, name); case t_SER: case t_POL: case t_RFRAC: if (!isinR(a2)) err_code(a,name); if (gcmpgs(a2, -1) <= 0) pari_err_IMPL("intnum with diverging non constant limit"); return gsigne(a2) < 0 ? f_SINGSER : f_SER; default: if (!isinC(a1) || !isinR(a2) || gcmpgs(a2, -1) <= 0) err_code(a,name); return gsigne(a2) < 0 ? f_SING : f_REG; } } /* 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(LGTAB, t_VEC); 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); TABh(z) = rcopy(TABh(tab)); 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(LGTAB, t_VEC); 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); TABh(v) = rcopy(TABh(tab)); return v; } static GEN init_fin(GEN b, long codeb, long m, long l, long prec) { switch(labs(codeb)) { case f_REG: case f_SING: return inittanhsinh(m,l); case f_YSLOW: return initexpsinh(m,l); case f_YVSLO: return exptab(initexpsinh(m,l), gel(b,2), prec); case f_YFAST: return homtab(initexpexp(m,l), f_getycplx(b,l)); /* f_YOSCS, f_YOSCC */ default: return homtab(initnumsine(m,l),f_getycplx(b,l)); } } static GEN intnuminit_i(GEN a, GEN b, long m, long prec) { long codea, codeb, l; GEN T, kma, kmb, tmp; if (m > 30) pari_err_OVERFLOW("intnuminit [m]"); if (m < 0) pari_err_DOMAIN("intnuminit", "m", "<", gen_0, stoi(m)); l = prec+EXTRAPREC64; codea = transcode(a, "a"); if (codea == f_SER) codea = f_REG; codeb = transcode(b, "b"); if (codeb == f_SER) codeb = f_REG; if (codea == f_SINGSER || codeb == f_SINGSER) pari_err_IMPL("intnuminit with singularity at non constant limit"); if (labs(codea) > labs(codeb)) { swap(a, b); lswap(codea, codeb); } if (codea == f_REG) { T = init_fin(b, codeb, m,l,prec); switch(labs(codeb)) { case f_YOSCS: if (gequal0(a)) break; case f_YOSCC: T = mkvec2(inittanhsinh(m,l), T); } return T; } if (codea == f_SING) { T = init_fin(b,codeb, m,l,prec); T = mkvec2(labs(codeb) == f_SING? T: inittanhsinh(m,l), T); return T; } /* now a and b are infinite */ if (codea * codeb > 0) return gen_0; kma = f_getycplx(a,l); codea = labs(codea); kmb = f_getycplx(b,l); codeb = labs(codeb); if (codea == f_YSLOW && codeb == f_YSLOW) return initsinhsinh(m, l); if (codea == f_YFAST && codeb == f_YFAST && gequal(kma, kmb)) return homtab(initsinh(m,l), kmb); T = cgetg(3, t_VEC); switch (codea) { case f_YSLOW: case f_YVSLO: tmp = initexpsinh(m,l); gel(T,1) = codea == f_YSLOW? tmp: exptab(tmp, gel(a,2), prec); switch (codeb) { case f_YVSLO: gel(T,2) = exptab(tmp, gel(b,2), prec); return T; case f_YFAST: gel(T,2) = homtab(initexpexp(m,l), kmb); return T; /* YOSC[CS] */ default: gel(T,2) = homtab(initnumsine(m,l), kmb); return T; } break; 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; /* YOSC[CS] */ default: gel(T,2) = homtab(initnumsine(m, l), kmb); return T; } default: /* YOSC[CS] */ tmp = initnumsine(m, l); gel(T,1) = homtab(tmp,kma); if (codea == f_YOSCC && codeb == f_YOSCC && !gequal(kma, kmb)) gel(T,2) = mkvec2(inittanhsinh(m,l), homtab(tmp,kmb)); else gel(T,2) = homtab(tmp,kmb); return T; } } GEN intnuminit(GEN a, GEN b, long m, long prec) { pari_sp av = avma; return gerepilecopy(av, intnuminit_i(a,b,m,prec)); } static GEN intnuminit0(GEN a, GEN b, GEN tab, long prec) { long m; if (!tab) m = 0; else if (typ(tab) != t_INT) { if (!checktab(tab)) pari_err_TYPE("intnuminit0",tab); return tab; } else m = itos(tab); return intnuminit(a, b, m, prec); } /* Assigns the values of the function weighted by w[k] at quadrature points x[k] * [replacing the weights]. Return the index of the last nonzero 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) */ static GEN intfuncinit_i(void *E, GEN (*eval)(void*, GEN), GEN tab) { GEN tabxp = TABxp(tab), tabwp = TABwp(tab); GEN tabxm = TABxm(tab), tabwm = TABwm(tab); long L, L0 = lg(tabxp); TABw0(tab) = gmul(TABw0(tab), eval(E, TABx0(tab))); if (lg(tabxm) == 1) { TABxm(tab) = tabxm = gneg(tabxp); TABwm(tab) = tabwm = leafcopy(tabwp); } /* update wp and wm in place */ L = minss(weight(E, eval, tabxp, tabwp), weight(E, eval, tabxm, 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 prec) { pari_sp av = avma; GEN tab = intnuminit_i(a, b, m, prec); if (lg(tab) == 3) pari_err_IMPL("intfuncinit with hard endpoint behavior"); if (is_fin_f(transcode(a,"intfuncinit")) || is_fin_f(transcode(b,"intfuncinit"))) pari_err_IMPL("intfuncinit with finite endpoints"); return gerepilecopy(av, intfuncinit_i(E, eval, tab)); } static GEN intnum_i(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN tab, long prec) { GEN S = gen_0, kma, kmb; long sb, sgns = 1, codea = transcode(a, "a"), codeb = transcode(b, "b"); if (codea == f_REG && typ(a) == t_VEC) a = gel(a,1); if (codeb == f_REG && typ(b) == t_VEC) b = gel(b,1); if (codea == f_REG && codeb == f_REG) return intn(E, eval, a, b, tab); if (codea == f_SER || codeb == f_SER) return intlin(E, eval, a, b, tab, prec); 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), sgns = -sgns; else { GEN c = gmul2n(gadd(gel(a,1), gel(b,1)), -1); S = gsub(intnsing(E, eval, a, c, gel(tab,1)), intnsing(E, eval, b, c, gel(tab,2))); } return (sgns < 0) ? gneg(S) : S; } /* now b is infinite */ sb = codeb > 0 ? 1 : -1; codeb = labs(codeb); if (codea == f_REG && codeb != f_YOSCC && (codeb != f_YOSCS || gequal0(a))) { S = intninfpm(E, eval, a, sb*codeb, tab); return sgns*sb < 0 ? gneg(S) : S; } if (is_fin_f(codea)) { /* either codea == f_SING or codea == f_REG and codeb = f_YOSCC * or (codeb == f_YOSCS and !gequal0(a)) */ GEN S2, c = real_i(codea == f_SING? gel(a,1): a); switch(codeb) { case f_YOSCC: case f_YOSCS: { GEN pi2p = gmul(Pi2n(1,prec), f_getycplx(b, prec)); GEN pis2p = gmul2n(pi2p, -2); if (codeb == f_YOSCC) c = gadd(c, pis2p); c = gdiv(c, pi2p); c = sb > 0? addiu(gceil(c), 1): subiu(gfloor(c), 1); c = gmul(pi2p, c); if (codeb == f_YOSCC) c = gsub(c, pis2p); break; } default: c = sb > 0? addiu(gceil(c), 1): subiu(gfloor(c), 1); break; } S = codea==f_SING? intnsing(E, eval, a, c, gel(tab,1)) : intn (E, eval, a, c, gel(tab,1)); S2 = intninfpm(E, eval, c, sb*codeb, gel(tab,2)); if (sb < 0) S2 = gneg(S2); S = gadd(S, S2); return sgns < 0 ? gneg(S) : S; } /* now a and b are infinite */ if (codea * sb > 0) { if (codea > 0) pari_warn(warner, "integral from oo to oo"); if (codea < 0) pari_warn(warner, "integral from -oo to -oo"); return gen_0; } if (sb < 0) sgns = -sgns; codea = labs(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 pis2 = Pi2n(-1, prec); GEN ca = (codea == f_YOSCC)? gmul(pis2, kma): gen_0; GEN cb = (codeb == f_YOSCC)? gmul(pis2, kmb): gen_0; GEN c = codea == f_YOSCC ? ca : cb; /*signe(a)=-sb*/ GEN SP, SN = intninfpm(E, eval, c, -sb*codea, gel(tab,1)); if (codea != f_YOSCC) SP = intninfpm(E, eval, cb, sb*codeb, gel(tab,2)); /* codea = codeb = f_YOSCC */ else if (gequal(kma, kmb)) SP = intninfpm(E, eval, cb, sb*codeb, gel(tab,2)); else { tab = gel(tab,2); SP = intninfpm(E, eval, cb, sb*codeb, gel(tab,2)); SP = gadd(SP, intn(E, eval, ca, cb, 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+EXTRAPREC64; GEN na = NULL, nb = NULL, S; if (transcode(a,"a") == f_SINGSER) { long v = gvar(gel(a,1)); if (v != NO_VARIABLE) { na = cgetg(3,t_VEC); gel(na,1) = polcoef_i(gel(a,1),0,v); gel(na,2) = gel(a,2); } a = gel(a,1); } if (transcode(b,"b") == f_SINGSER) { long v = gvar(gel(b,1)); if (v != NO_VARIABLE) { nb = cgetg(3,t_VEC); gel(nb,1) = polcoef_i(gel(b,1),0,v); gel(nb,2) = gel(b,2); } b = gel(b,1); } if (na || nb) { if (tab && typ(tab) != t_INT) pari_err_IMPL("non integer tab argument"); S = intnum(E, eval, na ? na : a, nb ? nb : b, tab, prec); if (na) S = gsub(S, intnum(E, eval, na, a, tab, prec)); if (nb) S = gsub(S, intnum(E, eval, b, nb, tab, prec)); return gerepilecopy(ltop, S); } tab = intnuminit0(a, b, tab, prec); S = intnum_i(E, eval, gprec_wensure(a, l), gprec_wensure(b, l), tab, prec); return gerepilecopy(ltop, gprec_wtrunc(S, prec)); } typedef struct auxint_s { GEN a, R, mult; GEN (*f)(void*, GEN); GEN (*w)(GEN, long); long prec; void *E; } auxint_t; static GEN auxcirc(void *E, GEN t) { auxint_t *D = (auxint_t*) E; GEN s, c, z; mpsincos(mulrr(t, D->mult), &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.mult = 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 auxlin(void *E, GEN t) { auxint_t *D = (auxint_t*) E; return D->f(D->E, gadd(D->a, gmul(D->mult, t))); } static GEN intlin(void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN tab, long prec) { auxint_t D; GEN z; if (typ(a) == t_VEC) a = gel(a,1); if (typ(b) == t_VEC) b = gel(b,1); z = toser_i(a); if (z) a = z; z = toser_i(b); if (z) b = z; D.a = a; D.mult = gsub(b,a); D.f = eval; D.E = E; z = intnum(&D, &auxlin, real_0(prec), real_1(prec), tab, prec); return gmul(D.mult, z); } 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 intfuncinit0(GEN a, GEN b, GEN code, long m, long prec) { EXPR_WRAP(code, intfuncinit(EXPR_ARG, a, b, m, 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 /* Given a continued fraction C output by QD convert it into an Euler * continued fraction A(n), B(n), where * 1 / (1 + C[2]z / (1+C[3]z / (1+..C[lim]z))) * = 1 / (1+A[1]*z+B[1]*z^2/(1+A[2]*z+B[2]*z^2/(1+...1/(1+A[lim\2]*z)))). */ static GEN contfrac_Euler(GEN C) { long i, n = lg(C) - 1, a = n/2, b = (n - 1)/2; GEN A = cgetg(a+1, t_VEC), B = cgetg(b+1, t_VEC); gel(A,1) = gel(C,2); if (!b) return mkvec2(A, B); gel(B,1) = gneg(gmul(gel(C,3), gel(C,2))); for (i = 2; i <= b; i++) { GEN u = gel(C,2*i); gel(A,i) = gadd(u, gel(C, 2*i-1)); gel(B,i) = gneg(gmul(gel(C, 2*i+1), u)); } if (a != b) gel(A,a) = gadd(gel(C, 2*a), gel(C, 2*a-1)); return mkvec2(A, B); } /* The quotient-difference algorithm. Given a vector M, convert the series * S = sum_{n >= 0} M[n+1] z^n into a continued fraction. * Compute the c[n] such that * S = c[1] / (1 + c[2]z / (1+c[3]z/(1+...c[lim]z))), * Assume lim <= #M. Does not work for certain M. */ static GEN QD(GEN M, long lim) { pari_sp av = avma; long lim2 = lim / 2, j, k; GEN e, q, c; e = zerovec(lim); c = zerovec(lim+1); gel(c, 1) = gel(M, 1); q = cgetg(lim+1, t_VEC); for (k = 1; k <= lim; ++k) { if (gequal0(gel(M, k))) return gc_NULL(av); gel(q, k) = gdiv(gel(M, k+1), gel(M, k)); } for (j = 1; j <= lim2; ++j) { long l = lim - 2*j; gel(c, 2*j) = gneg(gel(q, 1)); for (k = 0; k <= l; ++k) { GEN E = gsub(gadd(gel(e, k+2), gel(q, k+2)), gel(q, k+1)); if (gequal0(E)) return gc_NULL(av); gel(e, k+1) = E; } for (k = 0; k < l; ++k) gel(q, k+1) = gdiv(gmul(gel(q, k+2), gel(e, k+2)), gel(e, k+1)); gel(c, 2*j+1) = gneg(gel(e, 1)); if (gc_needed(av, 3)) { if (DEBUGMEM>1) pari_warn(warnmem,"contfracinit, %ld/%ld",j,lim2); gerepileall(av, 3, &e, &c, &q); } } if (odd(lim)) gel(c, lim+1) = gneg(gel(q, 1)); return c; } static GEN quodif_i(GEN M, long n) { switch(typ(M)) { case t_RFRAC: if (n < 0) pari_err_TYPE("contfracinit",M); M = gtoser(M, varn(gel(M,2)), n+3); /*fall through*/ case t_SER: M = gtovec(M); break; case t_POL: M = RgX_to_RgC(M, degpol(M)+1); break; case t_VEC: case t_COL: break; default: pari_err_TYPE("contfracinit", M); } if (n < 0) { n = lg(M)-2; if (n < 0) return cgetg(1,t_VEC); } else if (lg(M)-1 <= n) pari_err_COMPONENT("contfracinit", "<", stoi(lg(M)-1), stoi(n)); return QD(M, n); } GEN quodif(GEN M, long n) { pari_sp av = avma; GEN C = quodif_i(M, n); if (!C) pari_err(e_MISC, "0 divisor in QD algorithm"); return gerepilecopy(av, C); } GEN contfracinit(GEN M, long n) { pari_sp av = avma; GEN C = quodif_i(M, n); if (!C) pari_err(e_MISC, "0 divisor in QD algorithm"); if (lg(C) < 3) { set_avma(av); retmkvec2(cgetg(1,t_VEC), cgetg(1,t_VEC)); } return gerepilecopy(av, contfrac_Euler(C)); } GEN contfracinit_i(GEN M, long n) { GEN C = quodif_i(M, n); if (!C) return NULL; if (lg(C) < 3) return mkvec2(cgetg(1,t_VEC), cgetg(1,t_VEC)); return contfrac_Euler(C); } /* Evaluate at 1/tinv the nlim first terms of the continued fraction output by * contfracinit. Shallow. */ GEN contfraceval_inv(GEN CF, GEN tinv, long nlim) { pari_sp av; long j; GEN S = gen_0, S1, S2, A, B; if (typ(CF) != t_VEC || lg(CF) != 3) pari_err_TYPE("contfraceval", CF); A = gel(CF, 1); if (typ(A) != t_VEC) pari_err_TYPE("contfraceval", CF); B = gel(CF, 2); if (typ(B) != t_VEC) pari_err_TYPE("contfraceval", CF); if (nlim < 0) nlim = lg(A)-1; else if (lg(A) <= nlim) pari_err_COMPONENT("contfraceval", ">", stoi(lg(A)-1), stoi(nlim)); if (lg(B)+1 <= nlim) pari_err_COMPONENT("contfraceval", ">", stoi(lg(B)), stoi(nlim)); av = avma; if (nlim <= 1) return lg(A)==1? gen_0: gdiv(tinv, gadd(gel(A, 1), tinv)); switch(nlim % 3) { case 2: S = gdiv(gel(B, nlim-1), gadd(gel(A, nlim), tinv)); nlim--; break; case 0: S1 = gadd(gel(A, nlim), tinv); S2 = gadd(gmul(gadd(gel(A, nlim-1), tinv), S1), gel(B, nlim-1)); S = gdiv(gmul(gel(B, nlim-2), S1), S2); nlim -= 2; break; } /* nlim = 1 (mod 3) */ for (j = nlim; j >= 4; j -= 3) { GEN S3; S1 = gadd(gadd(gel(A, j), tinv), S); S2 = gadd(gmul(gadd(gel(A, j-1), tinv), S1), gel(B, j-1)); S3 = gadd(gmul(gadd(gel(A, j-2), tinv), S2), gmul(gel(B, j-2), S1)); S = gdiv(gmul(gel(B, j-3), S2), S3); if (gc_needed(av, 3)) S = gerepilecopy(av, S); } return gdiv(tinv, gadd(gadd(gel(A, 1), tinv), S)); } GEN contfraceval(GEN CF, GEN t, long nlim) { pari_sp av = avma; return gerepileupto(av, contfraceval_inv(CF, ginv(t), nlim)); } /* MONIEN SUMMATION */ /* basic Newton, find x ~ z such that Q(x) = 0 */ static GEN monrefine(GEN Q, GEN QP, GEN z, long prec) { pari_sp av = avma; GEN pr = poleval(Q, z); for(;;) { GEN prnew; z = gsub(z, gdiv(pr, poleval(QP, z))); prnew = poleval(Q, z); if (gcmp(gabs(prnew, prec), gabs(pr, prec)) >= 0) break; pr = prnew; } z = gprec_wensure(z, precdbl(prec)); z = gsub(z, gdiv(poleval(Q, z), poleval(QP, z))); return gerepileupto(av, z); } static GEN RX_realroots(GEN x, long prec) { return realroots(gprec_wtrunc(x,prec), NULL, prec); } /* (real) roots of Q, assuming QP = Q' and that half the roots are close to * k+1, ..., k+m, m = deg(Q)/2-1. N.B. All roots are real and >= 1 */ static GEN monroots(GEN Q, GEN QP, long k, long prec) { long j, n = degpol(Q), m = n/2 - 1; GEN v2, v1 = cgetg(m+1, t_VEC); for (j = 1; j <= m; ++j) gel(v1, j) = monrefine(Q, QP, stoi(k+j), prec); Q = gdivent(Q, roots_to_pol(v1, varn(Q))); v2 = RX_realroots(Q, prec); settyp(v2, t_VEC); return shallowconcat(v1, v2); } static void Pade(GEN M, GEN *pP, GEN *pQ) { pari_sp av = avma; long n = lg(M)-2, i; GEN v = QD(M, n), P = pol_0(0), Q = pol_1(0); if (!v) pari_err(e_MISC, "0 divisor in QD algorithm"); /* evaluate continued fraction => Pade approximants */ for (i = n-1; i >= 1; i--) { /* S = P/Q: S -> v[i]*x / (1+S) */ GEN R = RgX_shift_shallow(RgX_Rg_mul(Q,gel(v,i)), 1); Q = RgX_add(P,Q); P = R; if (gc_needed(av, 3)) { if (DEBUGMEM>1) pari_warn(warnmem,"Pade, %ld/%ld",i,n-1); gerepileall(av, 3, &P, &Q, &v); } } /* S -> 1+S */ *pP = RgX_add(P,Q); *pQ = Q; } static GEN veczetaprime(GEN a, GEN b, long N, long prec) { long B = prec / 2; GEN v, h = mkcomplex(gen_0, real2n(-B, prec)); v = veczeta(a, gadd(b, h), N, prec); return gmul2n(imag_i(v), B); } struct mon_w { GEN w, a, b; long n, j, prec; }; /* w(x) / x^(a*(j+k)+b), k >= 1; w a t_CLOSURE or t_INT [encodes log(x)^w] */ static GEN wrapmonw(void* E, GEN x) { struct mon_w *W = (struct mon_w*)E; long k, j = W->j, n = W->n, prec = W->prec, l = 2*n+4-j; GEN wx = typ(W->w) == t_CLOSURE? closure_callgen1prec(W->w, x, prec) : powgi(glog(x, prec), W->w); GEN v = cgetg(l, t_VEC); GEN xa = gpow(x, gneg(W->a), prec), w = gmul(wx, gpowgs(xa, j)); w = gdiv(w, gpow(x,W->b,prec)); for (k = 1; k < l; k++) { gel(v,k) = w; w = gmul(w, xa); } return v; } /* w(x) / x^(a*j+b) */ static GEN wrapmonw2(void* E, GEN x) { struct mon_w *W = (struct mon_w*)E; GEN wnx = closure_callgen1prec(W->w, x, W->prec); return gdiv(wnx, gpow(x, gadd(gmulgu(W->a, W->j), W->b), W->prec)); } static GEN M_from_wrapmon(struct mon_w *S, GEN wfast, GEN n0) { long j, N = 2*S->n+2; GEN M = cgetg(N+1, t_VEC), faj = gsub(wfast, S->b); for (j = 1; j <= N; j++) { faj = gsub(faj, S->a); if (gcmpgs(faj, -2) <= 0) { S->j = j; setlg(M,j); M = shallowconcat(M, sumnum((void*)S, wrapmonw, n0, NULL, S->prec)); break; } S->j = j; gel(M,j) = sumnum((void*)S, wrapmonw2, mkvec2(n0,faj), NULL, S->prec); } return M; } static void checkmonroots(GEN vr, long n) { if (lg(vr) != n+1) pari_err_IMPL("recovery when missing roots in sumnummonieninit"); } static GEN sumnummonieninit_i(GEN a, GEN b, GEN w, GEN n0, long prec) { GEN c, M, P, Q, Qp, vr, vabs, vwt, ga = gadd(a, b); double bit = 2*prec / gtodouble(ga), D = bit*M_LN2; double da = maxdd(1., gtodouble(a)); long n = (long)ceil(D / (da*(log(D)-1))); long j, prec2, prec0 = prec + EXTRAPREC64; double bit0 = ceil((2*n+1)*LOG2_10); int neg = 1; struct mon_w S; /* 2.05 is heuristic; with 2.03, sumnummonien(n=1,1/n^2) loses * 19 decimals at \p1500 */ prec = nbits2prec(maxdd(2.05*da*bit, bit0)); prec2 = nbits2prec(maxdd(1.3*da*bit, bit0)); S.w = w; S.a = a = gprec_wensure(a, precdbl(prec)); S.b = b = gprec_wensure(b, precdbl(prec)); S.n = n; S.j = 1; S.prec = prec; if (typ(w) == t_INT) { /* f(n) ~ \sum_{i > 0} f_i log(n)^k / n^(a*i + b); a > 0, a+b > 1 */ long k = itos(w); if (k == 0) M = veczeta(a, ga, 2*n+2, prec); else if (k == 1) M = veczetaprime(a, ga, 2*n+2, prec); else M = M_from_wrapmon(&S, gen_0, gen_1); if (odd(k)) neg = 0; } else { GEN wfast = gen_0; if (typ(w) == t_VEC) { wfast = gel(w,2); w = gel(w,1); } M = M_from_wrapmon(&S, wfast, n0); } /* M[j] = sum(n >= n0, w(n) / n^(a*j+b) */ Pade(M, &P,&Q); Qp = RgX_deriv(Q); if (gequal1(a)) a = NULL; if (!a && typ(w) == t_INT) { vabs = vr = monroots(Q, Qp, signe(w)? 1: 0, prec2); checkmonroots(vr, n); c = b; } else { vr = RX_realroots(Q, prec2); settyp(vr, t_VEC); checkmonroots(vr, n); if (!a) { vabs = vr; c = b; } else { GEN ai = ginv(a); vabs = cgetg(n+1, t_VEC); for (j = 1; j <= n; j++) gel(vabs,j) = gpow(gel(vr,j), ai, prec2); c = gdiv(b,a); } } vwt = cgetg(n+1, t_VEC); c = gsubgs(c,1); if (gequal0(c)) c = NULL; for (j = 1; j <= n; j++) { GEN r = gel(vr,j), t = gdiv(poleval(P,r), poleval(Qp,r)); if (c) t = gmul(t, gpow(r, c, prec)); gel(vwt,j) = neg? gneg(t): t; } if (typ(w) == t_INT && !equali1(n0)) { GEN h = subiu(n0,1); for (j = 1; j <= n; j++) gel(vabs,j) = gadd(gel(vabs,j), h); } return mkvec3(gprec_wtrunc(vabs,prec0), gprec_wtrunc(vwt,prec0), n0); } GEN sumnummonieninit(GEN asymp, GEN w, GEN n0, long prec) { pari_sp av = avma; const char *fun = "sumnummonieninit"; GEN a, b; if (!n0) n0 = gen_1; else if (typ(n0) != t_INT) pari_err_TYPE(fun, n0); if (!asymp) a = b = gen_1; else { if (typ(asymp) == t_VEC) { if (lg(asymp) != 3) pari_err_TYPE(fun, asymp); a = gel(asymp,1); b = gel(asymp,2); } else { a = gen_1; b = asymp; } if (gsigne(a) <= 0) pari_err_DOMAIN(fun, "a", "<=", gen_0, a); if (!isinR(b)) pari_err_TYPE(fun, b); if (gcmpgs(gadd(a,b), 1) <= 0) pari_err_DOMAIN(fun, "a+b", "<=", gen_1, mkvec2(a,b)); } if (!w) w = gen_0; else switch(typ(w)) { case t_INT: if (signe(w) < 0) pari_err_IMPL("log power < 0 in sumnummonieninit"); case t_CLOSURE: break; case t_VEC: if (lg(w) == 3 && typ(gel(w,1)) == t_CLOSURE) break; default: pari_err_TYPE(fun, w); } return gerepilecopy(av, sumnummonieninit_i(a, b, w, n0, prec)); } GEN sumnummonien(void *E, GEN (*eval)(void*,GEN), GEN n0, GEN tab, long prec) { pari_sp av = avma; GEN vabs, vwt, S; long l, i; if (typ(n0) != t_INT) pari_err_TYPE("sumnummonien", n0); if (!tab) tab = sumnummonieninit_i(gen_1, gen_1, gen_0, n0, prec); else { if (lg(tab) != 4 || typ(tab) != t_VEC) pari_err_TYPE("sumnummonien", tab); if (!equalii(n0, gel(tab,3))) pari_err(e_MISC, "incompatible initial value %Ps != %Ps", gel(tab,3),n0); } vabs= gel(tab,1); l = lg(vabs); vwt = gel(tab,2); if (typ(vabs) != t_VEC || typ(vwt) != t_VEC || lg(vwt) != l) pari_err_TYPE("sumnummonien", tab); S = gen_0; for (i = 1; i < l; i++) { S = gadd(S, gmul(gel(vwt,i), eval(E, gel(vabs,i)))); S = gprec_wensure(S, prec); } return gerepilecopy(av, gprec_wtrunc(S, prec)); } static GEN get_oo(GEN fast) { return mkvec2(mkoo(), fast); } GEN sumnuminit(GEN fast, long prec) { pari_sp av; GEN s, v, d, C, res = cgetg(6, t_VEC); long N, k, k2, m; double w; gel(res, 1) = d = mkfrac(gen_1, utoipos(4)); /* 1/4 */ av = avma; w = gtodouble(glambertW(ginv(d), 0, LOWDEFAULTPREC)); N = (long)ceil(M_LN2*prec/(w*(1+w))+5); k = (long)ceil(N*w); if (k&1) k--; prec += EXTRAPREC64; k2 = k/2; s = RgX_to_ser(monomial(real_1(prec),1,0), k+3); s = gmul2n(gasinh(s, prec), 2); /* asinh(x)/d, d = 1/4 */ gel(s, 2) = utoipos(4); s = gsub(ser_inv(gexpm1(s,prec)), ser_inv(s)); C = matpascal(k-1); v = cgetg(k2+1, t_VEC); for (m = 1; m <= k2; m++) { pari_sp av = avma; GEN S = real_0(prec); long j; for (j = m; j <= k2; j++) { /* s[X^(2j-1)] * binomial(2*j-1, j-m) */ GEN t = gmul(gel(s,2*j+1), gcoeff(C, 2*j,j-m+1)); t = gmul2n(t, 1-2*j); S = odd(j)? gsub(S,t): gadd(S,t); } if (odd(m)) S = gneg(S); gel(v,m) = gerepileupto(av, S); } v = RgC_gtofp(v,prec); settyp(v, t_VEC); gel(res, 4) = gerepileupto(av, v); gel(res, 2) = utoi(N); gel(res, 3) = utoi(k); if (!fast) fast = get_oo(gen_0); gel(res, 5) = intnuminit(gel(res,2), fast, 0, prec - EXTRAPREC64); return res; } static int checksumtab(GEN T) { if (typ(T) != t_VEC || lg(T) != 6) return 0; return typ(gel(T,2))==t_INT && typ(gel(T,3))==t_INT && typ(gel(T,4))==t_VEC; } GEN sumnum(void *E, GEN (*eval)(void*, GEN), GEN a, GEN tab, long prec) { pari_sp av = avma, av2; GEN v, tabint, S, d, fast; long as, N, k, m, prec2; if (!a) { a = gen_1; fast = get_oo(gen_0); } else switch(typ(a)) { case t_VEC: if (lg(a) != 3) pari_err_TYPE("sumnum", a); fast = get_oo(gel(a,2)); a = gel(a,1); break; default: fast = get_oo(gen_0); } if (typ(a) != t_INT) pari_err_TYPE("sumnum", a); if (!tab) tab = sumnuminit(fast, prec); else if (!checksumtab(tab)) pari_err_TYPE("sumnum",tab); as = itos(a); d = gel(tab,1); N = maxss(as, itos(gel(tab,2))); k = itos(gel(tab,3)); v = gel(tab,4); tabint = gel(tab,5); prec2 = prec+EXTRAPREC64; av2 = avma; S = gmul(eval(E, stoi(N)), real2n(-1,prec2)); for (m = as; m < N; m++) { S = gadd(S, eval(E, stoi(m))); if (gc_needed(av, 2)) { if (DEBUGMEM>1) pari_warn(warnmem,"sumnum [1], %ld/%ld",m,N); S = gerepileupto(av2, S); } S = gprec_wensure(S, prec2); } for (m = 1; m <= k/2; m++) { GEN t = gmulsg(2*m-1, d); GEN s = gsub(eval(E, gsubsg(N,t)), eval(E, gaddsg(N,t))); S = gadd(S, gmul(gel(v,m), s)); if (gc_needed(av2, 2)) { if (DEBUGMEM>1) pari_warn(warnmem,"sumnum [2], %ld/%ld",m,k/2); S = gerepileupto(av2, S); } S = gprec_wensure(S, prec2); } S = gadd(S, intnum(E, eval,stoi(N), fast, tabint, prec2)); return gerepilecopy(av, gprec_wtrunc(S, prec)); } GEN sumnummonien0(GEN a, GEN code, GEN tab, long prec) { EXPR_WRAP(code, sumnummonien(EXPR_ARG, a, tab, prec)); } GEN sumnum0(GEN a, GEN code, GEN tab, long prec) { EXPR_WRAP(code, sumnum(EXPR_ARG, a, tab, prec)); } /* Abel-Plana summation */ static GEN intnumgauexpinit(long prec) { pari_sp ltop = avma; GEN V, N, E, P, Q, R, vabs, vwt; long l, n, k, j, prec2, prec0 = prec + EXTRAPREC64; n = (long)ceil(prec*0.226); n |= 1; /* make n odd */ prec2 = maxss(prec0, nbits2prec(1.15*prec + 32)); prec = nbits2prec(1.5*prec + 32); constbern(n+3); V = cgetg(n + 4, t_VEC); for (k = 1; k <= n + 3; ++k) gel(V, k) = gtofp(gdivgs(bernfrac(2*k), odd(k)? 2*k: -2*k), prec); Pade(V, &P, &Q); N = RgX_recip(gsub(P, Q)); E = RgX_recip(Q); R = gdivgu(gdiv(N, RgX_deriv(E)), 2); vabs = RX_realroots(E,prec2); l = lg(vabs); settyp(vabs, t_VEC); vwt = cgetg(l, t_VEC); for (j = 1; j < l; ++j) { GEN a = gel(vabs,j); gel(vwt, j) = gprec_wtrunc(poleval(R, a), prec0); gel(vabs, j) = gprec_wtrunc(sqrtr_abs(a), prec0); } return gerepilecopy(ltop, mkvec2(vabs, vwt)); } /* Compute \int_{-oo}^oo w(x)f(x) dx, where w(x)=x/(exp(2pi x)-1) * for x>0 and w(-x)=w(x). For Abel-Plana (sumnumap). */ static GEN intnumgauexp(void *E, GEN (*eval)(void*,GEN), GEN gN, GEN tab, long prec) { pari_sp av = avma; GEN U = mkcomplex(gN, NULL), V = mkcomplex(gN, NULL), S = gen_0; GEN vabs = gel(tab, 1), vwt = gel(tab, 2); long l = lg(vabs), i; if (lg(vwt) != l || typ(vabs) != t_VEC || typ(vwt) != t_VEC) pari_err_TYPE("sumnumap", tab); for (i = 1; i < l; i++) { /* I * (w_i/a_i) * (f(N + I*a_i) - f(N - I*a_i)) */ GEN x = gel(vabs,i), w = gel(vwt,i), t; gel(U,2) = x; gel(V,2) = gneg(x); t = mulcxI(gsub(eval(E,U), eval(E,V))); S = gadd(S, gmul(gdiv(w,x), cxtoreal(t))); S = gprec_wensure(S, prec); } return gerepilecopy(av, gprec_wtrunc(S, prec)); } GEN sumnumapinit(GEN fast, long prec) { if (!fast) fast = mkoo(); retmkvec2(intnumgauexpinit(prec), intnuminit(gen_1, fast, 0, prec)); } typedef struct { GEN (*f)(void *E, GEN); void *E; long N; } expfn; /* f(Nx) */ static GEN _exfn(void *E, GEN x) { expfn *S = (expfn*)E; return S->f(S->E, gmulsg(S->N, x)); } GEN sumnumap(void *E, GEN (*eval)(void*,GEN), GEN a, GEN tab, long prec) { pari_sp av = avma; expfn T; GEN S, fast, gN; long as, m, N; if (!a) { a = gen_1; fast = get_oo(gen_0); } else switch(typ(a)) { case t_VEC: if (lg(a) != 3) pari_err_TYPE("sumnumap", a); fast = get_oo(gel(a,2)); a = gel(a,1); break; default: fast = get_oo(gen_0); } if (typ(a) != t_INT) pari_err_TYPE("sumnumap", a); if (!tab) tab = sumnumapinit(fast, prec); else if (typ(tab) != t_VEC || lg(tab) != 3) pari_err_TYPE("sumnumap",tab); as = itos(a); T.N = N = maxss(as + 1, (long)ceil(prec*0.327)); T.E = E; T.f = eval; gN = stoi(N); S = gtofp(gmul2n(eval(E, gN), -1), prec); for (m = as; m < N; ++m) { S = gadd(S, eval(E, stoi(m))); S = gprec_wensure(S, prec); } S = gadd(S, gmulsg(N, intnum(&T, &_exfn, gen_1, fast, gel(tab, 2), prec))); S = gadd(S, intnumgauexp(E, eval, gN, gel(tab, 1), prec)); return gerepileupto(av, S); } GEN sumnumap0(GEN a, GEN code, GEN tab, long prec) { EXPR_WRAP(code, sumnumap(EXPR_ARG, a, tab, prec)); } /* max (1, |zeros|), P a t_POL or scalar */ static double polmax(GEN P) { pari_sp av = avma; double r; if (typ(P) != t_POL || degpol(P) <= 0) return 1.0; r = gtodouble(polrootsbound(P, NULL)); return gc_double(av, maxdd(r, 1.0)); } /* max (1, |poles|), F a t_POL or t_RFRAC or scalar */ static double ratpolemax(GEN F) { if (typ(F) == t_POL) return 1.0; return polmax(gel(F,2)); } /* max (1, |poles|, |zeros|)) */ static double ratpolemax2(GEN F) { if (typ(F) == t_POL) return polmax(F); return maxdd(polmax(gel(F,1)), polmax(gel(F,2))); } static GEN sercoeff(GEN x, long n) { long N = n - valser(x); return (N < 0)? gen_0: gel(x,N+2); } static GEN rfrac_gtofp(GEN F, long prec) { return mkrfrac(gel(F,1), RgX_gtofp(gel(F,2), prec)); } /* Compute the integral from N to infinity of a rational function F, deg(F) < -1 * We must have N > 2 * r, r = max(1, |poles F|). */ static GEN intnumainfrat(GEN F, long N, double r, long prec) { long v, k, lim; GEN S, ser; pari_sp av = avma; lim = (long)ceil(prec / log2(N/r)); F = rfrac_gtofp(F, prec + EXTRAPREC64); ser = rfracrecip_to_ser_absolute(F, lim+2); v = valser(ser); S = gdivgu(sercoeff(ser,lim+1), lim*N); /* goes down to 2, but coeffs are 0 in degree < v */ for (k = lim; k >= v; k--) /* S <- (S + coeff(ser,k)/(k-1)) / N */ S = gdivgu(gadd(S, gdivgu(sercoeff(ser,k), k-1)), N); if (v-2) S = gdiv(S, powuu(N, v-2)); return gerepilecopy(av, gprec_wtrunc(S, prec)); } static GEN rfrac_eval0(GEN R) { GEN N, n, D = gel(R,2), d = constant_coeff(D); if (gequal0(d)) return NULL; N = gel(R,1); n = typ(N)==t_POL? constant_coeff(N): N; return gdiv(n, d); } static GEN rfrac_eval(GEN R, GEN a) { GEN D = gel(R,2), d = poleval(D,a); return gequal0(d)? NULL: gdiv(poleval(gel(R,1),a), d); } /* R = \sum_i vR[i], eval at a omitting poles */ static GEN RFRAC_eval(GEN R, GEN vR, GEN a) { GEN S = rfrac_eval(R,a); if (!S && vR) { long i, l = lg(vR); for (i = 1; i < l; i++) { GEN z = rfrac_eval(gel(vR,i), a); if (z) S = S? gadd(S,z): z; } } return S; } static GEN add_RFRAC_eval(GEN S, GEN R, GEN vR, GEN a) { GEN z = RFRAC_eval(R, vR, a); return z? gadd(S, z): S; } static GEN add_sumrfrac(GEN S, GEN R, GEN vR, long b) { long m; for (m = b; m >= 1; m--) S = add_RFRAC_eval(S,R,vR,utoipos(m)); return S; } static void get_kN(long r, long B, long *pk, long *pN) { long k = maxss(50, (long)ceil(0.241*B)); GEN z; if (k&1L) k++; *pk = k; constbern(k >> 1); z = sqrtnr_abs(gmul2n(gtofp(bernfrac(k), LOWDEFAULTPREC), B), k); *pN = maxss(2*r, r + 1 + itos(gceil(z))); } /* F a t_RFRAC, F0 = F(0) or NULL [pole], vF a vector of t_RFRAC summing to F * or NULL [F atomic] */ static GEN sumnumrat_i(GEN F, GEN F0, GEN vF, long prec) { long vx, j, k, N; GEN S, S1, S2, intf, _1; double r; if (poldegree(F, -1) > -2) pari_err(e_MISC, "sum diverges in sumnumrat"); vx = varn(gel(F,2)); r = ratpolemax(F); get_kN((long)ceil(r), prec, &k,&N); intf = intnumainfrat(F, N, r, prec); /* N > ratpolemax(F) is not a pole */ _1 = real_1(prec); S1 = gmul2n(gmul(_1, gsubst(F, vx, utoipos(N))), -1); S1 = add_sumrfrac(S1, F, vF, N-1); if (F0) S1 = gadd(S1, F0); S = gmul(_1, gsubst(F, vx, gaddgs(pol_x(vx), N))); S = rfrac_to_ser_i(S, k + 2); S2 = gen_0; for (j = 2; j <= k; j += 2) S2 = gadd(S2, gmul(gdivgu(bernfrac(j),j), sercoeff(S, j-1))); return gadd(intf, gsub(S1, S2)); } /* sum_{n >= a} F(n) */ GEN sumnumrat(GEN F, GEN a, long prec) { pari_sp av = avma; long vx; GEN vF, F0; switch(typ(F)) { case t_RFRAC: break; case t_INT: case t_REAL: case t_COMPLEX: case t_POL: if (gequal0(F)) return real_0(prec); default: pari_err_TYPE("sumnumrat",F); } vx = varn(gel(F,2)); switch(typ(a)) { case t_INT: if (signe(a)) F = gsubst(F, vx, deg1pol_shallow(gen_1,a,vx)); F0 = rfrac_eval0(F); vF = NULL; break; case t_INFINITY: if (inf_get_sign(a) == -1) { /* F(x) + F(-x). Could divide degree by 2, as G(x^2): pb with poles */ GEN F2 = gsubst(F, vx, RgX_neg(pol_x(vx))); vF = mkvec2(F,F2); F = gadd(F, F2); if (gequal0(F)) { set_avma(av); return real_0(prec); } F0 = rfrac_eval0(gel(vF,1)); break; } default: pari_err_TYPE("sumnumrat",a); return NULL; /* LCOV_EXCL_LINE */ } return gerepileupto(av, sumnumrat_i(F, F0, vF, prec)); } /* deg ((a / b) - 1), assuming b a t_POL of positive degree in main variable */ static long rfracm1_degree(GEN a, GEN b) { long da, db; if (typ(a) != t_POL || varn(a) != varn(b)) return 0; da = degpol(a); db = degpol(b); if (da != db) return maxss(da - db, 0); return degpol(RgX_sub(a,b)) - db; } /* prod_{n >= a} F(n) */ GEN prodnumrat(GEN F, long a, long prec) { pari_sp ltop = avma; long j, k, m, N, vx; GEN S, S1, S2, intf, G; double r; switch(typ(F)) { case t_RFRAC: break; case t_INT: case t_REAL: case t_COMPLEX: case t_POL: if (gequal1(F)) return real_1(prec); default: pari_err_TYPE("prodnumrat",F); } if (rfracm1_degree(gel(F,1), gel(F,2)) > -2) pari_err(e_MISC, "product diverges in prodnumrat"); vx = varn(gel(F,2)); if (a) F = gsubst(F, vx, gaddgs(pol_x(vx), a)); r = ratpolemax2(F); get_kN((long)ceil(r), prec, &k,&N); G = gdiv(deriv(F, vx), F); intf = intnumainfrat(gmul(pol_x(vx),G), N, r, prec); intf = gneg(gadd(intf, gmulsg(N, glog(gsubst(F, vx, stoi(N)), prec)))); S = rfrac_gtofp(gsubst(G, vx, gaddgs(pol_x(vx), N)), prec); S = rfrac_to_ser_i(S, k + 2); S1 = gsqrt(gsubst(F, vx, utoipos(N)), prec); for (m = 0; m < N; m++) S1 = gmul(S1, gsubst(F, vx, utoi(m))); S2 = gen_0; for (j = 2; j <= k; j += 2) S2 = gadd(S2, gmul(gdivgu(bernfrac(j),j*(j-1)), sercoeff(S, j-2))); return gerepileupto(ltop, gmul(S1, gexp(gsub(intf, S2), prec))); } /* fan = factoru(n); sum_{d | n} mu(d)/d * s[n/d] */ static GEN sdmob(GEN s, long n, GEN fan) { GEN D = divisorsu_moebius(gel(fan,1)), S = sercoeff(s, n); /* d = 1 */ long i, l = lg(D); for (i = 2; i < l; i++) S = gadd(S, gdivgs(sercoeff(s, n/labs(D[i])), D[i])); return S; } /* z * (1 - p^-s); ms = -s or NULL (in which case s is a t_INT) */ static GEN auxeuler(GEN z, GEN p, GEN s, GEN ms, long prec) { return ms? gsub(z, gmul(z, gpow(p, ms, prec))) : gsub(z, gdiv(z, powii(p, s))); } /* log (zeta(s) * prod_i (1 - P[i]^-s) */ static GEN logzetan(GEN s, GEN P, long N, long prec) { GEN Z, ms = NULL; pari_sp av; if (typ(s) != t_INT) ms = gneg(s); av = avma; Z = gzeta(s, prec); if (P) { long i, l = lg(P); for (i = 1; i < l; i++) { Z = auxeuler(Z, gel(P,i), s, ms, prec); if (gc_needed(av,2)) Z = gerepileupto(av, Z); } } else { forprime_t T; GEN p; forprime_init(&T, gen_2, utoi(N)); av = avma; while ((p = forprime_next(&T))) { Z = auxeuler(Z, p, s, ms, prec); if (gc_needed(av,2)) Z = gerepileupto(av, Z); } } return glog(Z, prec); } static GEN sumlogzeta(GEN ser, GEN s, GEN P, long N, double rs, double lN, long vF, long lim, long prec) { GEN z = gen_0, v; pari_sp av; long i, n; if (vF > lim) return z; v = vecfactoru_i(vF,lim); av = avma; if (typ(s) == t_INT) constbern((itos(s) * lim + 1) >> 1); for (n = lim, i = lg(v)-1; n >= vF; n--, i--) { GEN t = sdmob(ser, n, gel(v,i)); if (!gequal0(t)) { /* (n Re(s) - 1) log2(N) bits cancel in logzetan */ long prec2 = prec + nbits2extraprec((n*rs-1) * lN); GEN L = logzetan(gmulsg(n,gprec_wensure(s,prec2)), P, N, prec2); z = gerepileupto(av, gadd(z, gmul(L, t))); z = gprec_wensure(z, prec); } } return gprec_wtrunc(z, prec); } static GEN rfrac_evalfp(GEN F, GEN x, long prec) { GEN N = gel(F,1), D = gel(F,2), a, b = poleval(D, x); a = (typ(N) == t_POL && varn(N) == varn(D))? poleval(N, x): N; if (typ(a) != t_INT || typ(b) != t_INT || (lg2prec(lgefint(a)) <= prec && lg2prec(lgefint(b)) <= prec)) return gdiv(a, b); return rdivii(a, b, prec + EXTRAPREC64); } /* op_p F(p^s): p in P, p >= a, F t_RFRAC */ static GEN opFps(GEN(*op)(GEN,GEN), GEN P, long N, long a, GEN F, GEN s, long prec) { GEN S = op == gadd? gen_0: gen_1; pari_sp av = avma; if (P) { long i, j, l = lg(P); for (i = j = 1; i < l; i++) { GEN p = gel(P,i); if (cmpiu(p, a) < 0) continue; S = op(S, rfrac_evalfp(F, gpow(p, s, prec), prec)); if (gc_needed(av,2)) S = gerepileupto(av, S); } } else { forprime_t T; GEN p; forprime_init(&T, utoi(a), utoi(N)); av = avma; while ((p = forprime_next(&T))) { S = op(S, rfrac_evalfp(F, gpow(p, s, prec), prec)); if (gc_needed(av,2)) S = gerepileupto(av, S); } } return S; } static void euler_set_Fs(GEN *F, GEN *s) { if (!*s) *s = gen_1; if (typ(*F) == t_RFRAC) { long m; *F = rfrac_deflate_max(*F, &m); if (m != 1) *s = gmulgs(*s, m); } } /* sum_{p prime, p >= a} F(p^s), F rational function */ GEN sumeulerrat(GEN F, GEN s, long a, long prec) { pari_sp av = avma; GEN ser, z, P; double r, rs, RS, lN; long prec2 = prec + EXTRAPREC64, vF, N, lim; euler_set_Fs(&F, &s); switch(typ(F)) { case t_RFRAC: break; case t_INT: case t_REAL: case t_COMPLEX: case t_POL: if (gequal0(F)) return real_0(prec); default: pari_err_TYPE("sumeulerrat",F); } /* F t_RFRAC */ if (a < 2) a = 2; rs = gtodouble(real_i(s)); vF = -poldegree(F, -1); if (vF <= 0) pari_err(e_MISC, "sum diverges in sumeulerrat"); r = polmax(gel(F,2)); N = a; /* >= 2 */ /* if s not integral, computing p^-s at increased accuracy is too expensive */ if (typ(s) == t_INT) N = maxss(30, N); lN = log2((double)N); RS = maxdd(1./vF, log2(r) / lN); if (rs <= RS) pari_err_DOMAIN("sumeulerrat", "real(s)", "<=", dbltor(RS), dbltor(rs)); lim = (long)ceil(prec / (rs*lN - log2(r))); ser = rfracrecip_to_ser_absolute(rfrac_gtofp(F, prec2), lim+1); P = N < 1000000? primes_interval(gen_2, utoipos(N)): NULL; z = sumlogzeta(ser, s, P, N, rs, lN, vF, lim, prec); z = gadd(z, opFps(&gadd, P, N, a, F, s, prec)); return gerepilecopy(av, gprec_wtrunc(z, prec)); } /* F = N/D; return F'/F. Assume D a t_POL */ static GEN rfrac_logderiv(GEN N, GEN D) { GEN a; if (typ(N) != t_POL || varn(N) != varn(D) || !degpol(N)) return gdiv(gneg(RgX_deriv(D)), D); if (!degpol(D)) return gdiv(RgX_deriv(N), N); a = RgX_sub(RgX_mul(RgX_deriv(N), D), RgX_mul(RgX_deriv(D), N)); if (lg(a) > 3) gel(a,2) = gen_0; return gdiv(a, RgX_mul(N, D)); } /* prod_{p prime, p >= a} F(p^s), F rational function */ GEN prodeulerrat(GEN F, GEN s, long a, long prec) { pari_sp ltop = avma; GEN DF, NF, ser, P, z; double r, rs, RS, lN; long prec2 = prec + EXTRAPREC64, vF, N, lim; euler_set_Fs(&F, &s); switch(typ(F)) { case t_RFRAC: break; case t_INT: case t_REAL: case t_COMPLEX: case t_POL: if (gequal1(F)) return real_1(prec); default: pari_err_TYPE("prodeulerrat",F); } /* F t_RFRAC */ NF = gel(F, 1); DF = gel(F, 2); rs = gtodouble(real_i(s)); vF = - rfracm1_degree(NF, DF); if (rs * vF <= 1) pari_err(e_MISC, "product diverges in prodeulerrat"); r = ratpolemax2(F); N = maxss(a, (long)ceil(2*r)); if (typ(s) == t_INT) N = maxss(N, 30); lN = log2((double)N); RS = maxdd(1./vF, log2(r) / lN); if (rs <= RS) pari_err_DOMAIN("prodeulerrat", "real(s)", "<=", dbltor(RS), dbltor(rs)); lim = (long)ceil(prec / (rs*lN - log2(r))); (void)rfracrecip(&NF, &DF); /* returned value is 0 */ if (!RgX_is_ZX(DF) || !is_pm1(gel(DF,2)) || lim * log2(r) > 4 * prec) NF = gmul(NF, real_1(prec2)); ser = integser(rfrac_to_ser_i(rfrac_logderiv(NF,DF), lim+3)); /* ser = log f, f = F(1/x) + O(x^(lim+1)) */ P = N < 1000000? primes_interval(gen_2, utoipos(N)): NULL; z = gexp(sumlogzeta(ser, s, P, N, rs, lN, vF, lim, prec), prec); z = gmul(z, opFps(&gmul, P, N, a, F, s, prec)); return gerepilecopy(ltop, gprec_wtrunc(z, prec)); } /* Compute $\sum_{n\ge a}c(n)$ using Lagrange extrapolation. Assume that the $N$-th remainder term of the series has a regular asymptotic expansion in integral powers of $1/N$. */ static GEN sumnumlagrange1init(GEN c1, long flag, long prec) { pari_sp av = avma; GEN V, W, T; double c1d; long prec2; ulong n, N; c1d = c1 ? gtodouble(c1) : 0.332; if (c1d <= 0) pari_err_DOMAIN("sumnumlagrangeinit", "c1", "<=", gen_0, c1); N = (ulong)ceil(c1d*prec); if ((N&1L) == 0) N++; prec2 = nbits2prec(prec+(long)ceil(1.8444*N) + 16); W = vecbinomial(N); T = vecpowuu(N, N); V = cgetg(N+1, t_VEC); gel(V,N) = gel(T,N); for (n = N-1; n >= 1; n--) { pari_sp av = avma; GEN t = mulii(gel(W, n+1), gel(T,n)); if (!odd(n)) togglesign_safe(&t); if (flag) t = addii(gel(V, n+1), t); gel(V, n) = gerepileuptoint(av, t); } V = gdiv(RgV_gtofp(V, prec2), mpfact(N)); return gerepilecopy(av, mkvec4(gen_1, stoi(prec2), gen_1, V)); } static GEN sumnumlagrange2init(GEN c1, long flag, long prec) { pari_sp av = avma; GEN V, W, T, told; double c1d = c1 ? gtodouble(c1) : 0.228; long prec2; ulong n, N; N = (ulong)ceil(c1d*prec); if ((N&1L) == 0) N++; prec2 = nbits2prec(prec+(long)ceil(1.18696*N) + 16); W = vecbinomial(2*N); T = vecpowuu(N, 2*N); V = cgetg(N+1, t_VEC); gel(V, N) = told = gel(T,N); for (n = N-1; n >= 1; n--) { GEN tnew = mulii(gel(W, N-n+1), gel(T,n)); if (!odd(n)) togglesign_safe(&tnew); told = addii(told, tnew); if (flag) told = addii(gel(V, n+1), told); gel(V, n) = told; told = tnew; } V = gdiv(RgV_gtofp(V, prec2), mpfact(2*N)); return gerepilecopy(av, mkvec4(gen_2, stoi(prec2), gen_1, V)); } static GEN _mpmul(GEN x, GEN y) { if (!x) return y; return y? mpmul(x, y): x; } /* Used only for al = 2, 1, 1/2, 1/3, 1/4. */ static GEN sumnumlagrangeinit_i(GEN al, GEN c1, long flag, long prec) { pari_sp av = avma; GEN V, W; double c1d = 0.0, c2; long prec2, dal; ulong j, n, N; if (typ(al) == t_INT) { switch(itos_or_0(al)) { case 1: return sumnumlagrange1init(c1, flag, prec); case 2: return sumnumlagrange2init(c1, flag, prec); default: pari_err_IMPL("sumnumlagrange for this alpha"); } } if (typ(al) != t_FRAC) pari_err_TYPE("sumnumlagrangeinit",al); dal = itos_or_0(gel(al,2)); if (dal > 4 || !equali1(gel(al,1))) pari_err_IMPL("sumnumlagrange for this alpha"); switch(dal) { case 2: c2 = 2.6441; c1d = 0.62; break; case 3: c2 = 3.1578; c1d = 1.18; break; case 4: c2 = 3.5364; c1d = 3.00; break; default: return NULL; /* LCOV_EXCL_LINE */ } if (c1) { c1d = gtodouble(c1); if (c1d <= 0) pari_err_DOMAIN("sumnumlagrangeinit", "c1", "<=", gen_0, c1); } N = (ulong)ceil(c1d * prec); if ((N&1L) == 0) N++; prec2 = nbits2prec(prec + (long)ceil(c2*N) + 16); V = vecpowug(N, al, prec2); W = cgetg(N+1, t_VEC); for (n = 1; n <= N; ++n) { pari_sp av2 = avma; GEN t = NULL, vn = gel(V, n); for (j = 1; j <= N; j++) if (j != n) t = _mpmul(t, mpsub(vn, gel(V, j))); gel(W, n) = gerepileuptoleaf(av2, mpdiv(gpowgs(vn, N-1), t)); } if (flag) for (n = N-1; n >= 1; n--) gel(W, n) = gadd(gel(W, n+1), gel(W, n)); return gerepilecopy(av, mkvec4(al, stoi(prec2), gen_1, W)); } GEN sumnumlagrangeinit(GEN al, GEN c1, long prec) { pari_sp ltop = avma; GEN V, W, S, be; long n, prec2, fl, N; if (!al) return sumnumlagrange1init(c1, 1, prec); if (typ(al) != t_VEC) al = mkvec2(gen_1, al); else if (lg(al) != 3) pari_err_TYPE("sumnumlagrangeinit",al); be = gel(al,2); al = gel(al,1); if (gequal0(be)) return sumnumlagrangeinit_i(al, c1, 1, prec); V = sumnumlagrangeinit_i(al, c1, 0, prec); switch(typ(be)) { case t_CLOSURE: fl = 1; break; case t_INT: case t_FRAC: case t_REAL: fl = 0; break; default: pari_err_TYPE("sumnumlagrangeinit", be); return NULL; /* LCOV_EXCL_LINE */ } prec2 = itos(gel(V, 2)); W = gel(V, 4); N = lg(W) - 1; S = gen_0; V = cgetg(N+1, t_VEC); for (n = N; n >= 1; n--) { GEN tmp, gn = stoi(n); tmp = fl ? closure_callgen1prec(be, gn, prec2) : gpow(gn, gneg(be), prec2); tmp = gdiv(gel(W, n), tmp); S = gadd(S, tmp); gel(V, n) = (n == N)? tmp: gadd(gel(V, n+1), tmp); } return gerepilecopy(ltop, mkvec4(al, stoi(prec2), S, V)); } /* - sum_{n=1}^{as-1} f(n) */ static GEN sumaux(void *E, GEN (*eval)(void*,GEN,long), long as, long prec) { GEN S = gen_0; long n; if (as > 1) { for (n = 1; n < as; ++n) { S = gadd(S, eval(E, stoi(n), prec)); S = gprec_wensure(S, prec); } S = gneg(S); } else for (n = as; n <= 0; ++n) { S = gadd(S, eval(E, stoi(n), prec)); S = gprec_wensure(S, prec); } return S; } GEN sumnumlagrange(void *E, GEN (*eval)(void*,GEN,long), GEN a, GEN tab, long prec) { pari_sp av = avma; GEN s, S, al, V; long as, prec2; ulong n, l; if (typ(a) != t_INT) pari_err_TYPE("sumnumlagrange", a); if (!tab) tab = sumnumlagrangeinit(NULL, tab, prec); else if (lg(tab) != 5 || typ(gel(tab,2)) != t_INT || typ(gel(tab,4)) != t_VEC) pari_err_TYPE("sumnumlagrange", tab); as = itos(a); al = gel(tab, 1); prec2 = itos(gel(tab, 2)); S = gel(tab, 3); V = gel(tab, 4); l = lg(V); if (gequal(al, gen_2)) { s = sumaux(E, eval, as, prec2); as = 1; } else s = gen_0; for (n = 1; n < l; n++) { s = gadd(s, gmul(gel(V, n), eval(E, stoi(n+as-1), prec2))); s = gprec_wensure(s, prec); } if (!gequal1(S)) s = gdiv(s,S); return gerepilecopy(av, gprec_wtrunc(s, prec)); } GEN sumnumlagrange0(GEN a, GEN code, GEN tab, long prec) { EXPR_WRAP(code, sumnumlagrange(EXPR_ARGPREC, a, tab, prec)); } /********************************************************************/ /* SIDI type programs */ /********************************************************************/ GEN sumnumsidi(void *E, GEN (*f)(void*, GEN, long), GEN a, double mu, long prec) { pari_sp av; GEN M, N, Wkeep = gen_0, W = gen_0, _1, S, t, Wp; long n, s, fail = 0, BIG = LONG_MAX, ekeep = LONG_MAX, bit = prec; prec = nbits2prec((long)(mu * prec) + 33); _1 = real_1(prec); av = avma; S = real_0(prec); t = Wp = f(E, a, prec); M = N = cgetg(1, t_VEC); for (n = 1;; n++) { long e = BIG; GEN c; S = gadd(S, t); t = f(E, gaddsg(n, a), prec); if (gequal0(t)) c = divru(real2n(bit, prec), n); else c = gdiv(_1, gmulsg(n, t)); /* Sidi's W algorithm */ M = vec_append(M, gmul(S, c)); N = vec_append(N, c); if (n == 1) continue; for (s = n - 1; s >= 1; s--) { GEN d = sstoQ(s * n, n - s); gel(M, s) = gmul(d, gsub(gel(M, s), gel(M, s + 1))); gel(N, s) = gmul(d, gsub(gel(N, s), gel(N, s + 1))); } if (!gequal0(gel(N, 1))) /* if N[1] = 0, count as failure */ { W = gdiv(gel(M, 1), gel(N, 1)); e = gexpo(gsub(W, Wp)); if (e < -bit) break; } if (++fail >= 10) { if (DEBUGLEVEL) err_printf("sumnumsidi: reached accuracy of %ld bits.", -ekeep); bit = -ekeep; W = Wkeep; break; } if (e < ekeep) { fail = 0; ekeep = e; Wkeep = W; } if (gc_needed(av,2)) { if (DEBUGMEM>1) pari_warn(warnmem,"sumnumsidi"); gerepileall(av, 6, &W, &Wkeep, &S, &t, &M, &N); } Wp = W; } if (bit <= 0) pari_err(e_MISC,"sumnumsidi diverges"); return gprec_w(W, nbits2prec(bit)); } GEN sumnumsidi0(GEN a, GEN code, long safe, long prec) { EXPR_WRAP(code, sumnumsidi(EXPR_ARGPREC, a, safe ? 1.56 : 1., prec)); } struct _osc_wrap { void *E; GEN (*f)(void*, GEN); GEN a, H, tab; long prec; }; static GEN _int_eval(void *E, GEN (*f)(void*, GEN), GEN a, GEN n, GEN H, GEN T, long prec) { GEN u = gmul(n, H); if (a) u = gadd(a, u); return intnumgauss(E, f, u, gadd(u, H), T, prec); } static GEN osc_wrap(void* E, GEN n) { struct _osc_wrap *D = (struct _osc_wrap*)E; return _int_eval(D->E, D->f, D->a, n, D->H, D->tab, D->prec); } static GEN osc_wrap_prec(void* E, GEN n, long prec) { struct _osc_wrap *D = (struct _osc_wrap*)E; return _int_eval(D->E, D->f, D->a, n, D->H, D->tab, prec); } GEN intnumosc(void *E, GEN (*f)(void*, GEN), GEN a, GEN H, long flag, GEN tab, long prec) { pari_sp av = avma; struct _osc_wrap D; GEN S; if (flag < 0 || flag > 4) pari_err_FLAG("intnumosc"); if (!tab) tab = intnumgaussinit(0, prec + (flag == 0? (prec>>1): 0)); if (gequal0(a)) a = NULL; D.E = E; D.f = f; D.a = a; D.H = H; D.tab = tab; D.prec = prec; switch(flag) { case 0: S = sumnumsidi((void*)&D, osc_wrap_prec, gen_0, 1.56, prec); break; case 1: S = sumnumsidi((void*)&D, osc_wrap_prec, gen_0, 1.0, prec); break; case 2: S = sumalt((void*)&D, osc_wrap, gen_0, prec); break; case 3: S = sumnumlagrange((void*)&D, osc_wrap_prec, gen_0, NULL, prec); break; default: S = sumpos((void*)&D, osc_wrap, gen_0, prec); break; } return gerepilecopy(av, S); } GEN intnumosc0(GEN a, GEN code, GEN H, long flag, GEN tab, long prec) { EXPR_WRAP(code, intnumosc(EXPR_ARG, a, H, flag, tab, prec)); } pari-2.17.2/src/language/anal.c0000644000175000017500000007366314760123736014645 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #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. */ static int IS_ID(char c) { return isalnum((unsigned char)c) || c == '_'; } long eval_mnemonic(GEN str, const char *tmplate) { const char *arg, *etmplate; ulong retval = 0; if (typ(str)==t_INT) return itos(str); if (typ(str)!=t_STR) pari_err_TYPE("eval_mnemonic",str); arg = GSTR(str); etmplate = strchr(tmplate, '\n'); if (!etmplate) etmplate = tmplate + strlen(tmplate); while (1) { long numarg; const char *e, *id, *negated = NULL; int negate = 0; /* Arg has 'no' prefix removed */ ulong l; char *buf; static char b[80]; while (isspace((unsigned char)*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(e_MISC,"id too long in a mnemonic"); if (!l) pari_err(e_MISC,"mnemonic does not start with an id"); strncpy(b, arg, l); b[l] = 0; arg = e; e = buf = b; while ('0' <= *e && *e <= '9') e++; if (*e == 0) pari_err(e_MISC,"numeric id in a mnemonic"); FIND: id = tmplate; while ((id = strstr(id, buf)) && id < etmplate) { const char *s = id; id += l; if (s[l] != '|') continue; /* False positive */ if (s == tmplate || !IS_ID(s[-1])) break; /* Found as is */ /* If we found "no_ID", negate */ if (!negate && s >= tmplate+3 && (s == tmplate+3 || !IS_ID(s[-4])) && s[-3] == 'n' && s[-2] == 'o' && s[-1] == '_') { negated = id; break; } } if (!id && !negated && !negate && l > 3 && buf[0] == 'n' && buf[1] == 'o' && buf[2] == '_') { /* Try to find the flag without the prefix "no_". */ buf += 3; l -= 3; negate = 1; if (buf[0]) goto FIND; } /* Negated and AS_IS forms, prefer AS_IS otherwise use negated form */ if (!id) { if (!negated) pari_err(e_MISC,"Unrecognized id '%s' in mnemonic", b); id = negated; negate = 1; } if (*id++ != '|') pari_err(e_MISC,"Missing | in mnemonic template"); e = id; while (*e >= '0' && *e <= '9') e++; while (isspace((unsigned char)*e)) e++; if (*e && *e != ';' && *e != ',') pari_err(e_MISC, "Non-numeric argument in mnemonic template"); numarg = atol(id); if (negate) retval &= ~numarg; else retval |= numarg; while (isspace((unsigned char)*arg)) arg++; if (*arg && !ispunct((unsigned char)*arg++)) /* skip punctuation */ pari_err(e_MISC,"Junk after id in mnemonic"); } return retval; } /********************************************************************/ /** **/ /** HASH TABLE MANIPULATIONS **/ /** **/ /********************************************************************/ static void insertep(entree *ep, entree **table, ulong hash) { ep->hash = hash; hash %= functions_tblsz; ep->next = table[hash]; table[hash] = ep; } static entree * initep(const char *name, long len) { const long add = 4*sizeof(long); entree *ep = (entree *) pari_calloc(sizeof(entree) + add + len+1); entree *ep1 = initial_value(ep); char *u = (char *) ep1 + add; ep->name = u; memcpy(u, name,len); u[len]=0; ep->valence = EpNEW; ep->value = NULL; ep->menu = 0; ep->code = NULL; ep->help = NULL; ep->pvalue = NULL; ep->arity = 0; return ep; } /* Look for s of length len in T; if 'insert', insert if missing */ static entree * findentry(const char *s, long len, entree **T, int insert) { ulong hash = hash_str_len(s, len); entree *ep; for (ep = T[hash % functions_tblsz]; ep; ep = ep->next) if (ep->hash == hash) { const char *t = ep->name; if (!strncmp(t, s, len) && !t[len]) return ep; } /* not found */ if (insert) { ep = initep(s,len); insertep(ep, T, hash); } return ep; } entree * pari_is_default(const char *s) { return findentry(s, strlen(s), defaults_hash, 0); } entree * is_entry(const char *s) { return findentry(s, strlen(s), functions_hash, 0); } entree * fetch_entry_raw(const char *s, long len) { return findentry(s, len, functions_hash, 1); } entree * fetch_entry(const char *s) { return fetch_entry_raw(s, strlen(s)); } /*******************************************************************/ /* */ /* SYNTACTICAL ANALYZER FOR GP */ /* */ /*******************************************************************/ static GEN readseq_i(char *t) { if (gp_meta(t,0)) return gnil; return closure_evalres(pari_compile_str(t)); } GEN readseq(char *t) { pari_sp av = avma; return gerepileupto(av, readseq_i(t)); } /* filtered readseq = remove blanks and comments */ GEN gp_read_str(const char *s) { pari_sp av = avma; return gerepileupto(av, readseq_i(gp_filter(s))); } GEN compile_str(const char *s) { return pari_compile_str(gp_filter(s)); } GEN gp_read_str_prec(const char *s, long prec) { GEN x; push_localbitprec(prec); x = gp_read_str(s); pop_localprec(); return x; } /* Deprecated, keep for backward compatibility */ GEN gp_read_str_bitprec(const char *s, long bitprec) { return gp_read_str_prec(s, bitprec); } /* valid return type */ static int isreturn(char c) { return c == 'l' || c == 'v' || c == 'i' || c == 'm' || c == 'u'; } /* if is known that 2 commas follow s; base-10 signed integer followed * by comma? */ static int is_long(const char *s) { while (isspace((unsigned char)*s)) s++; if (*s == '+' || *s == '-') s++; while (isdigit((unsigned char)*s)) s++; return *s == ','; } /* if is known that 2 commas follow s; base-10 unsigned integer followed * by comma? */ static int is_ulong(const char *s) { while (isspace((unsigned char)*s)) s++; if (*s == '+') s++; while (isdigit((unsigned char)*s)) s++; return *s == ','; } static long check_proto(const char *code) { long arity = 0; const char *s = code; if (isreturn(*s)) s++; while (*s && *s != '\n') switch (*s++) { case '&': case 'C': case 'G': case 'I': case 'J': case 'U': case 'L': case 'M': case 'P': case 'W': case 'f': case 'n': case 'p': case 'b': case 'r': arity++; break; case 'E': case 's': if (*s == '*') s++; arity++; break; case 'D': switch(*s) { case 'G': case '&': case 'n': case 'I': case 'E': case 'P': case 's': case 'r': s++; arity++; break; case 'V': s++; break; case 0: pari_err(e_SYNTAX,"function has incomplete prototype", s,code); break; default: { const char *p; long i; for(i = 0, p = s; *p && i < 2; p++) i += *p==','; /* skip 2 commas */ if (i < 2) pari_err(e_SYNTAX,"missing comma",s,code); arity++; switch(p[-2]) { case 'L': if (!is_long(s)) pari_err(e_SYNTAX,"not a long",s,code); break; case 'U': if (!is_ulong(s)) pari_err(e_SYNTAX,"not an ulong",s,code); break; case 'G': case 'r': case 's': case 'M': break; default: pari_err(e_SYNTAX,"incorrect type",s-2,code); } s = p; } } break; case 'V': case '=': case ',': break; case '\n': break; /* Before the mnemonic */ default: if (isreturn(s[-1])) pari_err(e_SYNTAX, "this code has to come first", s-1, code); pari_err(e_SYNTAX, "unknown parser code", s-1, code); } if (arity > 20) pari_err_IMPL("functions with more than 20 parameters"); return arity; } static void check_name(const char *name) { const char *s = name; if (isalpha((unsigned char)*s)) while (is_keyword_char(*++s)) /* empty */; if (*s) pari_err(e_SYNTAX,"not a valid identifier", s, name); } entree * install(void *f, const char *name, const char *code) { long arity = check_proto(code); entree *ep; check_name(name); ep = fetch_entry(name); if (ep->valence != EpNEW) { if (ep->valence != EpINSTALL) pari_err(e_MISC,"[install] identifier '%s' already in use", name); pari_warn(warner, "[install] updating '%s' prototype; module not reloaded", name); if (ep->code) pari_free((void*)ep->code); } else { ep->value = f; ep->valence = EpINSTALL; } ep->code = pari_strdup(code); ep->arity = arity; return ep; } static void killep(entree *ep) { GEN p = (GEN)initial_value(ep); freeep(ep); *p = 0; /* otherwise pari_var_create won't regenerate it */ ep->valence = EpNEW; ep->value = NULL; ep->pvalue = NULL; } /* Kill ep, i.e free all memory it references, and reset to initial value */ void kill0(const char *e) { entree *ep = is_entry(e); if (!ep || EpSTATIC(ep)) pari_err(e_MISC,"can't kill that"); killep(ep); } void addhelp(const char *e, char *s) { entree *ep = fetch_entry(e); void *f = (void *) ep->help; ep->help = pari_strdup(s); if (f && !EpSTATIC(ep)) pari_free(f); } /*******************************************************************/ /* */ /* PARSER */ /* */ /*******************************************************************/ #ifdef LONG_IS_64BIT static const long MAX_DIGITS = 19; #else static const long MAX_DIGITS = 9; #endif static const long MAX_XDIGITS = BITS_IN_LONG>>2; static const long MAX_BDIGITS = BITS_IN_LONG; static int ishex(const char **s) { if (**s == '0' && ((*s)[1] == 'x' || (*s)[1] == 'X' )) { *s += 2; return 1; } else return 0; } static int isbin(const char **s) { if (**s == '0' && ((*s)[1] == 'b' || (*s)[1] == 'B' )) { *s += 2; return 1; } else return 0; } static ulong bin_number_len(const char *s, long n) { ulong m = 0; long i; for (i = 0; i < n; i++,s++) m = 2*m + (*s - '0'); return m; } static int pari_isbdigit(int c) { return c=='0' || c=='1'; } static ulong hex_number_len(const char *s, long n) { ulong m = 0; long i; for(i = 0; i < n; i++, s++) { ulong c; if( *s >= '0' && *s <= '9') c = *s - '0'; else if( *s >= 'A' && *s <= 'F') c = *s - 'A' + 10; else c = *s - 'a' + 10; m = 16*m + c; } return m; } static GEN strtobin_len(const char *s, long n, long B, ulong num(const char *s, long n)) { long i, l = (n+B-1)/B; GEN N, Np; N = cgetipos(l+2); Np = int_LSW(N); for (i=1; i 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((unsigned char)**s) || **s=='.') { if (**s == 'E' || **s == 'e') { n = exponent(s); if (!signe(y)) { set_avma(av); return real_0_digits(n); } break; } --*s; return y; /* member */ } if (isdigit((unsigned char)**s)) y = real_read_more(y, s); n = old - *s; if (**s != 'E' && **s != 'e') { if (!signe(y)) { set_avma(av); return real_0(prec); } break; } } /* Fall through */ case 'E': case 'e': n += exponent(s); if (!signe(y)) { set_avma(av); return real_0_digits(n); } } l = nbits2prec(bit_accuracy(lgefint(y))); if (l < prec) l = prec; else prec = l; if (!n) return itor(y, prec); incrprec(l); y = itor(y, l); if (n > 0) y = mulrr(y, rpowuu(10UL, (ulong)n, l)); else y = divrr(y, rpowuu(10UL, (ulong)-n, l)); return gerepileuptoleaf(av, rtor(y, prec)); } static GEN int_read(const char **s) { GEN y; if (isbin(s)) y = bin_read(s); else if (ishex(s)) y = hex_read(s); else y = dec_read(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 = dec_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((unsigned char)**lex)) ++*lex; } static int skipexponent(char **lex) { char *old=*lex; if ((**lex=='e' || **lex=='E')) { ++*lex; if ( **lex=='+' || **lex=='-' ) ++*lex; if (!isdigit((unsigned char)**lex)) { *lex=old; return KINTEGER; } skipdigits(lex); return KREAL; } return KINTEGER; } static int skipconstante(char **lex) { skipdigits(lex); if (**lex=='.') { char *old = ++*lex; if (**lex == '.') { --*lex; return KINTEGER; } if (isalpha((unsigned char)**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((unsigned char)**lex)) { while (is_keyword_char(**lex)) ++*lex; yylloc->end=*lex; return KENTRY; } if (**lex=='"') { ++*lex; skipstring(lex); if (!**lex) compile_err("run-away string",*lex-1); ++*lex; yylloc->end=*lex; return KSTRING; } if (**lex == '.') { int token; if ((*lex)[1]== '.') { *lex+=2; yylloc->end = *lex; return KDOTDOT; } token=skipconstante(lex); if (token==KREAL) { yylloc->end = *lex; return token; } ++*lex; yylloc->end=*lex; return '.'; } if (isbin((const char**)lex)) { while (**lex=='0' || **lex=='1') ++*lex; yylloc->end = *lex; return KINTEGER; } if (ishex((const char**)lex)) { while (isxdigit((unsigned int)**lex)) ++*lex; yylloc->end = *lex; return KINTEGER; } if (isdigit((unsigned char)**lex)) { int token=skipconstante(lex); yylloc->end = *lex; return token; } if ((*lex)[1]=='=') switch (**lex) { case '=': if ((*lex)[2]=='=') { *lex+=3; yylloc->end = *lex; return KID; } else { *lex+=2; yylloc->end = *lex; return KEQ; } case '>': *lex+=2; yylloc->end = *lex; return KGE; case '<': *lex+=2; yylloc->end = *lex; return KLE; case '*': *lex+=2; yylloc->end = *lex; return KME; case '/': *lex+=2; yylloc->end = *lex; return KDE; case '%': if ((*lex)[2]=='=') break; *lex+=2; yylloc->end = *lex; return KMODE; case '!': if ((*lex)[2]=='=') break; *lex+=2; yylloc->end = *lex; return KNE; case '\\': *lex+=2; yylloc->end = *lex; return KEUCE; case '+': *lex+=2; yylloc->end = *lex; return KPE; case '-': *lex+=2; yylloc->end = *lex; return KSE; } if (**lex==')' && (*lex)[1]=='-' && (*lex)[2]=='>') { *lex+=3; yylloc->end = *lex; return KPARROW; } if (**lex=='-' && (*lex)[1]=='>') { *lex+=2; yylloc->end = *lex; return KARROW; } if (**lex=='<' && (*lex)[1]=='>') { *lex+=2; yylloc->end = *lex; return KNE; } if (**lex=='\\' && (*lex)[1]=='/') switch((*lex)[2]) { case '=': *lex+=3; yylloc->end = *lex; return KDRE; default: *lex+=2; yylloc->end = *lex; return KDR; } if ((*lex)[1]==**lex) switch (**lex) { case '&': *lex+=2; yylloc->end = *lex; return KAND; case '|': *lex+=2; yylloc->end = *lex; return KOR; case '+': *lex+=2; yylloc->end = *lex; return KPP; case '-': *lex+=2; yylloc->end = *lex; return KSS; case '>': if ((*lex)[2]=='=') { *lex+=3; yylloc->end = *lex; return KSRE;} *lex+=2; yylloc->end = *lex; return KSR; case '<': if ((*lex)[2]=='=') { *lex+=3; yylloc->end = *lex; return KSLE; } *lex+=2; yylloc->end = *lex; return KSL; } yylloc->end = *lex+1; return (unsigned char) *(*lex)++; } /********************************************************************/ /* */ /* Formal variables management */ /* */ /********************************************************************/ static THREAD long max_priority, min_priority; static THREAD long max_avail; /* max variable not yet used */ static THREAD long nvar; /* first GP free variable */ static hashtable *h_polvar; void varstate_save(struct pari_varstate *s) { s->nvar = nvar; s->max_avail = max_avail; s->max_priority = max_priority; s->min_priority = min_priority; } static void varentries_set(long v, entree *ep) { hash_insert(h_polvar, (void*)ep->name, (void*)v); varentries[v] = ep; } static int _given_value(void *E, hashentry *e) { return e->val == E; } static void varentries_unset(long v) { entree *ep = varentries[v]; if (ep) { hashentry *e = hash_remove_select(h_polvar, (void*)ep->name, (void*)v, _given_value); if (!e) pari_err_BUG("varentries_unset [unknown var]"); varentries[v] = NULL; pari_free(e); if (v <= nvar && ep == is_entry(ep->name)) { /* known to the GP interpreter; entree in functions_hash is permanent */ GEN p = (GEN)initial_value(ep); if (ep->value == p) { ep->value = NULL; ep->valence = EpNEW; } *p = 0; } else /* from name_var() or a direct pari_var_create() */ pari_free(ep); } } static void varentries_reset(long v, entree *ep) { varentries_unset(v); varentries_set(v, ep); } static void var_restore(struct pari_varstate *s) { nvar = s->nvar; max_avail = s->max_avail; max_priority = s->max_priority; min_priority = s->min_priority; } void varstate_restore(struct pari_varstate *s) { long i; for (i = nvar; i >= s->nvar; i--) { varentries_unset(i); varpriority[i] = -i; } for (i = max_avail+1; i <= s->max_avail; i++) { varentries_unset(i); varpriority[i] = -i; } var_restore(s); } void pari_set_varstate(long *vp, struct pari_varstate *vs) { var_restore(vs); varpriority = (long*)newblock(MAXVARN+2) + 1; memcpy(varpriority-1,vp-1,(MAXVARN+2)*sizeof(long)); } /* must come before destruction of functions_hash */ void pari_var_close(void) { GEN h = hash_values(h_polvar); long i, l = lg(h); for (i = 1; i < l; i++) { long v = h[i]; entree *ep = varentries[v]; if (ep && ep != is_entry(ep->name)) pari_free(ep); } free((void*)varentries); free((void*)(varpriority-1)); hash_destroy(h_polvar); } void pari_var_init(void) { long i; varentries = (entree**) pari_calloc((MAXVARN+1)*sizeof(entree*)); varpriority = (long*)pari_malloc((MAXVARN+2)*sizeof(long)) + 1; varpriority[-1] = 1-LONG_MAX; h_polvar = hash_create_str(100, 0); nvar = 0; max_avail = MAXVARN; max_priority = min_priority = 0; (void)fetch_user_var("x"); (void)fetch_user_var("y"); /* initialize so that people can use pol_x(i) directly */ for (i = 2; i <= (long)MAXVARN; i++) varpriority[i] = -i; /* reserve varnum 1..9 for static temps with predictable priority wrt x */ nvar = 10; min_priority = -MAXVARN; } long pari_var_next(void) { return nvar; } long pari_var_next_temp(void) { return max_avail; } long pari_var_create(entree *ep) { GEN p = (GEN)initial_value(ep); long v; if (*p) return varn(p); if (nvar == max_avail) pari_err(e_MISC,"no more variables available"); v = nvar++; /* set p = pol_x(v) */ p[0] = evaltyp(t_POL) | _evallg(4); p[1] = evalsigne(1) | evalvarn(v); gel(p,2) = gen_0; gel(p,3) = gen_1; varentries_set(v, ep); varpriority[v]= min_priority--; return v; } long delete_var(void) { /* user wants to delete one of his/her/its variables */ if (max_avail == MAXVARN) return 0; /* nothing to delete */ max_avail++; if (varpriority[max_avail] == min_priority) min_priority++; else if (varpriority[max_avail] == max_priority) max_priority--; return max_avail+1; } long fetch_var(void) { if (nvar == max_avail) pari_err(e_MISC,"no more variables available"); varpriority[max_avail] = min_priority--; return max_avail--; } long fetch_var_higher(void) { if (nvar == max_avail) pari_err(e_MISC,"no more variables available"); varpriority[max_avail] = ++max_priority; return max_avail--; } static int _higher(void *E, hashentry *e) { long v = (long)e->val; return (varncmp(v, (long)E) < 0); } static int _lower(void *E, hashentry *e) { long v = (long)e->val; return (varncmp(v, (long)E) > 0); } static GEN var_register(long v, const char *s) { varentries_reset(v, initep(s, strlen(s))); return pol_x(v); } GEN varhigher(const char *s, long w) { long v; if (w >= 0) { hashentry *e = hash_select(h_polvar, (void*)s, (void*)w, _higher); if (e) return pol_x((long)e->val); } /* no luck: need to create */ if (nvar == max_avail) pari_err(e_MISC,"no more variables available"); v = nvar++; varpriority[v]= ++max_priority; return var_register(v, s); } GEN varlower(const char *s, long w) { long v; if (w >= 0) { hashentry *e = hash_select(h_polvar, (void*)s, (void*)w, _lower); if (e) return pol_x((long)e->val); } /* no luck: need to create */ v = fetch_var(); return var_register(v, s); } long fetch_user_var(const char *s) { entree *ep = fetch_entry(s); long v; switch (EpVALENCE(ep)) { case EpVAR: return pari_var_create(ep); case EpNEW: break; default: pari_err(e_MISC, "%s already exists with incompatible valence", s); } v = pari_var_create(ep); ep->valence = EpVAR; ep->value = initial_value(ep); return v; } GEN fetch_var_value(long v, GEN t) { entree *ep = varentries[v]; if (!ep) return NULL; if (t) { long vn = localvars_find(t,ep); if (vn) return get_lex(vn); } return (GEN)ep->value; } void name_var(long n, const char *s) { entree *ep; char *u; if (n < pari_var_next()) pari_err(e_MISC, "renaming a GP variable is forbidden"); if (n > (long)MAXVARN) pari_err_OVERFLOW("variable number"); ep = (entree*)pari_malloc(sizeof(entree) + strlen(s) + 1); u = (char *)initial_value(ep); ep->valence = EpVAR; ep->name = u; strcpy(u,s); ep->value = gen_0; /* in case geval is called */ varentries_reset(n, ep); } static int cmp_by_var(void *E,GEN x, GEN y) { (void)E; return varncmp((long)x,(long)y); } GEN vars_sort_inplace(GEN z) { gen_sort_inplace(z,NULL,cmp_by_var,NULL); return z; } GEN vars_to_RgXV(GEN h) { long i, l = lg(h); GEN z = cgetg(l, t_VEC); for (i = 1; i < l; i++) gel(z,i) = pol_x(h[i]); return z; } GEN gpolvar(GEN x) { long v; if (!x) { GEN h = hash_values(h_polvar); return vars_to_RgXV(vars_sort_inplace(h)); } if (typ(x)==t_PADIC) return gcopy( gel(x,2) ); v = gvar(x); if (v==NO_VARIABLE) return gen_0; return pol_x(v); } static void fill_hashtable_single(entree **table, entree *ep) { EpSETSTATIC(ep); insertep(ep, table, hash_str(ep->name)); 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 **/ /** **/ /********************************************************************/ GEN arity0(GEN C) { if (typ(C)!=t_CLOSURE) pari_err_TYPE("arity", C); return utoi(closure_arity(C)); } #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); e = fetch_entry(s); if (EpVALENCE(e) != EpALIAS && EpVALENCE(e) != EpNEW) pari_err(e_MISC,"can't replace an existing symbol by an alias"); freeep(e); x = cgetg_block(2, t_VECSMALL); gel(x,1) = (GEN)ep; e->value=x; e->valence=EpALIAS; } GEN ifpari(GEN g, GEN a/*closure*/, GEN b/*closure*/) { if (gequal0(g)) /* false */ return b? closure_evalgen(b): gnil; else /* true */ return a? closure_evalgen(a): gnil; } void ifpari_void(GEN g, GEN a/*closure*/, GEN b/*closure*/) { if (gequal0(g)) /* false */ { if (b) closure_evalvoid(b); } else /* true */ { if (a) closure_evalvoid(a); } } GEN ifpari_multi(GEN g, GEN a/*closure*/) { long i, nb = lg(a)-1; if (!gequal0(g)) /* false */ return closure_evalgen(gel(a,1)); for(i=2;iopcode=s_opcode.n; pos->accesslex=s_accesslex.n; pos->data=s_data.n; pos->offset=offset; pos->nblex=nblex; 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_accesslex.n=0; s_dbginfo.n=0; s_data.n=0; s_lvar.n=0; s_frame.n=0; offset=-1; nblex=0; dbgstart=NULL; } void compilestate_save(struct pari_compilestate *comp) { comp->opcode=s_opcode.n; comp->operand=s_operand.n; comp->accesslex=s_accesslex.n; comp->data=s_data.n; comp->offset=offset; comp->nblex=nblex; 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_accesslex.n=comp->accesslex; s_data.n=comp->data; offset=comp->offset; nblex=comp->nblex; s_lvar.n=comp->localvars; dbgstart=comp->dbgstart; s_dbginfo.n=comp->dbginfo; s_frame.n=comp->frames; } static GEN gcopyunclone(GEN x) { GEN y = gcopy(x); gunclone(x); return y; } static void access_push(long x) { long a = pari_stack_new(&s_accesslex); accesslex[a] = x; } static GEN genctx(long nbmvar, long paccesslex) { GEN acc = const_vec(nbmvar,gen_1); long i, lvl = 1 + nbmvar; for (i = paccesslex; i 0) { lvl+=a; continue; } a += lvl; if (a <= 0) pari_err_BUG("genctx"); if (a <= nbmvar) gel(acc, a) = gen_0; } s_accesslex.n = paccesslex; for (i = 1; i<=nbmvar; i++) if (signe(gel(acc,i))==0) access_push(i-nbmvar-1); return acc; } static GEN getfunction(const struct codepos *pos, long arity, long nbmvar, GEN text, long gap) { long lop = s_opcode.n+1 - pos->opcode; long ldat = s_data.n+1 - pos->data; long lfram = s_frame.n+1 - pos->frames; GEN cl = cgetg(nbmvar && text? 8: (text? 7: 6), t_CLOSURE); GEN frpc, fram, dbg, op, dat; char *s; long i; cl[1] = arity; gel(cl,2) = cgetg(nchar2nlong(lop)+1, t_STR); gel(cl,3) = op = cgetg(lop, t_VECSMALL); gel(cl,4) = dat = 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; s = GSTR(gel(cl,2)) - 1; for (i = 1; i < lop; i++) { long j = i+pos->opcode-1; s[i] = opcode[j]; op[i] = operand[j]; dbg[i] = dbginfo[j] - dbgstart; if (dbg[i] < 0) dbg[i] += gap; } s[i] = 0; s_opcode.n = pos->opcode; s_operand.n = pos->opcode; s_dbginfo.n = pos->opcode; if (lg(cl)==8) gel(cl,7) = genctx(nbmvar, pos->accesslex); else if (nbmvar==0) s_accesslex.n = pos->accesslex; else { pari_sp av = avma; (void) genctx(nbmvar, pos->accesslex); set_avma(av); } for (i = 1; i < ldat; i++) if (data[i+pos->data-1]) gel(dat,i) = gcopyunclone(data[i+pos->data-1]); s_data.n = pos->data; while (s_lvar.n > pos->localvars && !localvars[s_lvar.n-1].inl) { if (localvars[s_lvar.n-1].type==Lmy) nblex--; s_lvar.n--; } for (i = 1; i < lfram; i++) { long j = i+pos->frames-1; frpc[i] = frames[j].pc - pos->opcode+1; gel(fram, i) = gcopyunclone(frames[j].frame); } s_frame.n = pos->frames; offset = pos->offset; dbgstart = pos->dbgstart; return cl; } static GEN getclosure(struct codepos *pos, long nbmvar) { return getfunction(pos, 0, nbmvar, NULL, 0); } static void op_push_loc(op_code o, long x, const char *loc) { long n=pari_stack_new(&s_opcode); long m=pari_stack_new(&s_operand); long d=pari_stack_new(&s_dbginfo); opcode[n]=o; operand[m]=x; dbginfo[d]=loc; } static void op_push(op_code o, long x, long n) { op_push_loc(o,x,tree[n].str); } static void op_insert_loc(long k, op_code o, long x, const char *loc) { long i; long n=pari_stack_new(&s_opcode); (void) pari_stack_new(&s_operand); (void) pari_stack_new(&s_dbginfo); for (i=n-1; i>=k; i--) { opcode[i+1] = opcode[i]; operand[i+1]= operand[i]; dbginfo[i+1]= dbginfo[i]; } opcode[k] = o; operand[k] = x; dbginfo[k] = loc; } static long data_push(GEN x) { long n=pari_stack_new(&s_data); data[n] = x?gclone(x):x; return n-offset; } static void var_push(entree *ep, Ltype type) { long n=pari_stack_new(&s_lvar); localvars[n].ep = ep; localvars[n].inl = 0; localvars[n].type = type; if (type == Lmy) nblex++; } static void frame_push(GEN x) { long n=pari_stack_new(&s_frame); frames[n].pc = s_opcode.n-1; frames[n].frame = gclone(x); } static GEN pack_localvars(void) { GEN pack=cgetg(3,t_VEC); long i, l=s_lvar.n; GEN t=cgetg(1+l,t_VECSMALL); GEN e=cgetg(1+l,t_VECSMALL); gel(pack,1)=t; gel(pack,2)=e; for(i=1;i<=l;i++) { t[i]=localvars[i-1].type; e[i]=(long)localvars[i-1].ep; } for(i=1;i<=nblex;i++) access_push(-i); return pack; } void push_frame(GEN C, long lpc, long dummy) { const char *code=closure_codestr(C); GEN oper=closure_get_oper(C); GEN dbg=closure_get_dbg(C); GEN frpc=gel(dbg,2); GEN fram=gel(dbg,3); long pc, j=1, lfr = lg(frpc); if (lpc==-1) { long k; GEN e = gel(fram, 1); for(k=1; k0 && (code[pc]==OClocalvar || code[pc]==OClocalvar0)) var_push((entree*)oper[pc],Llocal); if (jname:"NULL")); } } GEN localvars_read_str(const char *x, GEN pack) { pari_sp av = avma; GEN code; long l=0, nbmvar=nblex; 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; nblex = nbmvar; return gerepileupto(av, closure_evalres(code)); } long localvars_find(GEN pack, entree *ep) { GEN t=gel(pack,1); GEN e=gel(pack,2); long i; long vn=0; for(i=lg(e)-1;i>=1;i--) { if(t[i]==Lmy) vn--; if(e[i]==(long)ep) return t[i]==Lmy?vn:0; } return 0; } /* Flags for copy optimisation: -- Freturn: The result will be returned. -- FLsurvive: The result must survive the closure. -- FLnocopy: The result will never be updated nor part of a user variable. -- FLnocopylex: The result will never be updated nor part of dynamic variable. */ enum FLflag {FLreturn=1, FLsurvive=2, FLnocopy=4, FLnocopylex=8}; static void addcopy(long n, long mode, long flag, long mask) { if (mode==Ggen && !(flag&mask)) { op_push(OCcopy,0,n); if (!(flag&FLsurvive) && DEBUGLEVEL) pari_warn(warner,"compiler generates copy for `%.*s'", tree[n].len,tree[n].str); } } static void compilenode(long n, int mode, long flag); typedef enum {PPend,PPstd,PPdefault,PPdefaultmulti,PPstar,PPauto} PPproto; static PPproto parseproto(char const **q, char *c, const char *str) { char const *p=*q; long i; switch(*p) { case 0: case '\n': return PPend; case 'D': switch(p[1]) { case 'G': case '&': case 'W': case 'V': case 'I': case 'E': case 'J': case 'n': case 'P': case 'r': case 's': *c=p[1]; *q=p+2; return PPdefault; default: for(i=0;*p && i<2;p++) i+=*p==','; /* assert(i>=2) because check_proto validated the protototype */ *c=p[-2]; *q=p; return PPdefaultmulti; } break; case 'C': case 'p': case 'b': case 'P': case 'f': *c=*p; *q=p+1; return PPauto; case '&': *c='*'; *q=p+1; return PPstd; case 'V': if (p[1]=='=') { if (p[2]!='G') compile_err("function prototype is not supported",str); *c='='; p+=2; } else *c=*p; *q=p+1; return PPstd; case 'E': case 's': if (p[1]=='*') { *c=*p++; *q=p+1; return PPstar; } /*fall through*/ } *c=*p; *q=p+1; return PPstd; } static long detag(long n) { while (tree[n].f==Ftag) n=tree[n].x; return n; } /* return type for GP functions */ static op_code get_ret_type(const char **p, long arity, Gtype *t, long *flag) { *flag = 0; if (**p == 'v') { (*p)++; *t=Gvoid; return OCcallvoid; } else if (**p == 'i') { (*p)++; *t=Gsmall; return OCcallint; } else if (**p == 'l') { (*p)++; *t=Gsmall; return OCcalllong; } else if (**p == 'u') { (*p)++; *t=Gusmall; return OCcalllong; } else if (**p == 'm') { (*p)++; *flag = FLnocopy; } *t=Ggen; return arity==2?OCcallgen2:OCcallgen; } static void U_compile_err(const char *s) { compile_err("this should be a small non-negative integer",s); } static void L_compile_err(const char *s) { compile_err("this should be a small integer",s); } /*supported types: * type: Gusmall, Gsmall, Ggen, Gvoid, Gvec, Gclosure * mode: Gusmall, Gsmall, Ggen, Gvar, Gvoid */ static void compilecast_loc(int type, int mode, const char *loc) { if (type==mode) return; switch (mode) { case Gusmall: if (type==Ggen) op_push_loc(OCitou,-1,loc); else if (type==Gvoid) op_push_loc(OCpushlong,0,loc); else if (type!=Gsmall) U_compile_err(loc); break; case Gsmall: if (type==Ggen) op_push_loc(OCitos,-1,loc); else if (type==Gvoid) op_push_loc(OCpushlong,0,loc); else if (type!=Gusmall) L_compile_err(loc); break; case Ggen: if (type==Gsmall) op_push_loc(OCstoi,0,loc); else if (type==Gusmall)op_push_loc(OCutoi,0,loc); else if (type==Gvoid) op_push_loc(OCpushgnil,0,loc); break; case Gvoid: op_push_loc(OCpop, 1,loc); break; case Gvar: if (type==Ggen) op_push_loc(OCvarn,-1,loc); else compile_varerr(loc); break; default: pari_err_BUG("compilecast [unknown type]"); } } static void compilecast(long n, int type, int mode) { compilecast_loc(type, mode, tree[n].str); } static entree * fetch_member_raw(const char *s, long len) { pari_sp av = avma; char *t = stack_malloc(len+2); entree *ep; t[0] = '_'; strncpy(t+1, s, len); t[++len] = 0; /* prepend '_' */ ep = fetch_entry_raw(t, len); set_avma(av); return ep; } static entree * getfunc(long n) { long x=tree[n].x; if (tree[x].x==CSTmember) /* str-1 points to '.' */ return do_alias(fetch_member_raw(tree[x].str - 1, tree[x].len + 1)); else return do_alias(fetch_entry_raw(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); } static entree * getvar(long n) { return getentry(n); } /* match Fentry that are not actually EpSTATIC functions called without parens*/ static entree * getvardyn(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 void ctxmvar(long n) { pari_sp av=avma; GEN ctx; long i; if (n==0) return; ctx = cgetg(n+1,t_VECSMALL); for(n=0, i=0; iname, s); } INLINE int is_node_zero(long n) { n = detag(n); return (tree[n].f==Fsmall && tree[n].x==0); } static void str_defproto(const char *p, const char *q, const char *loc) { long len = p-4-q; if (q[1]!='"' || q[len]!='"') compile_err("default argument must be a string",loc); op_push_loc(OCpushgen,data_push(strntoGENexp(q+1,len)),loc); } static long countmatrixelts(long n) { long x,i; if (n==-1 || tree[n].f==Fnoarg) return 0; for(x=n, i=0; tree[x].f==Fmatrixelts; x=tree[x].x) if (tree[tree[x].y].f!=Fnoarg) i++; if (tree[x].f!=Fnoarg) i++; return i; } static long countlisttogen(long n, Ffunc f) { long x,i; if (n==-1 || tree[n].f==Fnoarg) return 0; for(x=n, i=0; tree[x].f==f ;x=tree[x].x, i++); return i+1; } static GEN listtogen(long n, Ffunc f) { long x,i,nb = countlisttogen(n, f); GEN z=cgetg(nb+1, t_VECSMALL); if (nb) { for (x=n, i = nb-1; i>0; z[i+1]=tree[x].y, x=tree[x].x, i--); z[1]=x; } return z; } static long first_safe_arg(GEN arg, long mask) { long lnc, l=lg(arg); for (lnc=l-1; lnc>0 && (tree[arg[lnc]].flags&mask)==mask; lnc--); return lnc; } static void checkdups(GEN arg, GEN vep) { long l=vecsmall_duplicate(vep); if (l!=0) compile_err("variable declared twice",tree[arg[l]].str); } enum {MAT_range,MAT_std,MAT_line,MAT_column,VEC_std}; static int matindex_type(long n) { long x = tree[n].x, y = tree[n].y; long fxx = tree[tree[x].x].f, fxy = tree[tree[x].y].f; if (y==-1) { if (fxy!=Fnorange) return MAT_range; if (fxx==Fnorange) compile_err("missing index",tree[n].str); return VEC_std; } else { long fyx = tree[tree[y].x].f, fyy = tree[tree[y].y].f; if (fxy!=Fnorange || fyy!=Fnorange) return MAT_range; if (fxx==Fnorange && fyx==Fnorange) compile_err("missing index",tree[n].str); if (fxx==Fnorange) return MAT_column; if (fyx==Fnorange) return MAT_line; return MAT_std; } } static entree * getlvalue(long n) { while ((tree[n].f==Fmatcoeff && matindex_type(tree[n].y)!=MAT_range) || tree[n].f==Ftag) n=tree[n].x; return getvar(n); } INLINE void compilestore(long vn, entree *ep, long n) { if (vn) op_push(OCstorelex,vn,n); else { if (EpSTATIC(do_alias(ep))) compile_varerr(tree[n].str); op_push(OCstoredyn,(long)ep,n); } } INLINE void compilenewptr(long vn, entree *ep, long n) { if (vn) { access_push(vn); op_push(OCnewptrlex,vn,n); } else op_push(OCnewptrdyn,(long)ep,n); } static void compilelvalue(long n) { n = detag(n); if (tree[n].f==Fentry) return; else { long x = tree[n].x, y = tree[n].y; long yx = tree[y].x, yy = tree[y].y; long m = matindex_type(y); if (m == MAT_range) compile_err("not an lvalue",tree[n].str); if (m == VEC_std && tree[x].f==Fmatcoeff) { int mx = matindex_type(tree[x].y); if (mx==MAT_line) { int xy = tree[x].y, xyx = tree[xy].x; compilelvalue(tree[x].x); compilenode(tree[xyx].x,Gsmall,0); compilenode(tree[yx].x,Gsmall,0); op_push(OCcompo2ptr,0,y); return; } } compilelvalue(x); switch(m) { case VEC_std: compilenode(tree[yx].x,Gsmall,0); op_push(OCcompo1ptr,0,y); break; case MAT_std: compilenode(tree[yx].x,Gsmall,0); compilenode(tree[yy].x,Gsmall,0); op_push(OCcompo2ptr,0,y); break; case MAT_line: compilenode(tree[yx].x,Gsmall,0); op_push(OCcompoLptr,0,y); break; case MAT_column: compilenode(tree[yy].x,Gsmall,0); op_push(OCcompoCptr,0,y); break; } } } static void compilematcoeff(long n, int mode) { long x=tree[n].x, y=tree[n].y; long yx=tree[y].x, yy=tree[y].y; long m=matindex_type(y); compilenode(x,Ggen,FLnocopy); switch(m) { case VEC_std: compilenode(tree[yx].x,Gsmall,0); op_push(OCcompo1,mode,y); return; case MAT_std: compilenode(tree[yx].x,Gsmall,0); compilenode(tree[yy].x,Gsmall,0); op_push(OCcompo2,mode,y); return; case MAT_line: compilenode(tree[yx].x,Gsmall,0); op_push(OCcompoL,0,y); compilecast(n,Gvec,mode); return; case MAT_column: compilenode(tree[yy].x,Gsmall,0); op_push(OCcompoC,0,y); compilecast(n,Gvec,mode); return; case MAT_range: compilenode(tree[yx].x,Gsmall,0); compilenode(tree[yx].y,Gsmall,0); if (yy==-1) op_push(OCcallgen,(long)is_entry("_[_.._]"),n); else { compilenode(tree[yy].x,Gsmall,0); compilenode(tree[yy].y,Gsmall,0); op_push(OCcallgen,(long)is_entry("_[_.._,_.._]"),n); } compilecast(n,Gvec,mode); return; default: pari_err_BUG("compilematcoeff"); } } static void compilesmall(long n, long x, long mode) { if (mode==Ggen) op_push(OCpushstoi, x, n); else { if (mode==Gusmall && x < 0) U_compile_err(tree[n].str); op_push(OCpushlong, x, n); compilecast(n,Gsmall,mode); } } static void compilevec(long n, long mode, op_code op) { pari_sp ltop=avma; long x=tree[n].x; long i; GEN arg=listtogen(x,Fmatrixelts); long l=lg(arg); op_push(op,l,n); for (i=1;i0;i--) { long y=tree[x].y; x=tree[y].x; stack[i+1]=tree[y].y; } stack[1]=x; return stack; } static GEN compilelambda(long y, GEN vep, long nbmvar, struct codepos *pos) { long lev = vep ? lg(vep)-1 : 0; GEN text=cgetg(3,t_VEC); gel(text,1)=strtoGENstr(lev? ((entree*) vep[1])->name: ""); gel(text,2)=strntoGENstr(tree[y].str,tree[y].len); dbgstart = tree[y].str; compilenode(y,Ggen,FLsurvive|FLreturn); return getfunction(pos,lev,nbmvar,text,2); } static void compilecall(long n, int mode, entree *ep) { pari_sp ltop=avma; long j; long x=tree[n].x, tx = tree[x].x; long y=tree[n].y; GEN arg=listtogen(y,Flistarg); long nb=lg(arg)-1; long lnc=first_safe_arg(arg, COsafelex|COsafedyn); long lnl=first_safe_arg(arg, COsafelex); long fl = lnl==0? (lnc==0? FLnocopy: FLnocopylex): 0; if (ep==NULL) compilenode(x, Ggen, fl); else { long vn=getmvar(ep); if (vn) { access_push(vn); op_push(OCpushlex,vn,n); } else op_push(OCpushdyn,(long)ep,n); } for (j=1;j<=nb;j++) { long x = tree[arg[j]].x, f = tree[arg[j]].f; if (f==Fseq) compile_err("unexpected ';'", tree[x].str+tree[x].len); else if (f==Findarg) { long a = tree[arg[j]].x; entree *ep = getlvalue(a); long vn = getmvar(ep); if (vn) op_push(OCcowvarlex, vn, a); compilenode(a, Ggen,FLnocopy); op_push(OClock,0,n); } else if (tx==CSTmember) { compilenode(arg[j], Ggen,FLnocopy); op_push(OClock,0,n); } else if (f!=Fnoarg) compilenode(arg[j], Ggen,j>=lnl?FLnocopylex:0); else op_push(OCpushlong,0,n); } op_push(OCcalluser,nb,x); compilecast(n,Ggen,mode); set_avma(ltop); } static GEN compilefuncinline(long n, long c, long a, long flag, long isif, long lev, long *ev) { struct codepos pos; int type=c=='I'?Gvoid:Ggen; long rflag=c=='I'?0:FLsurvive; long nbmvar = nblex; GEN vep = NULL; if (isif && (flag&FLreturn)) rflag|=FLreturn; getcodepos(&pos); if (c=='J') ctxmvar(nbmvar); if (lev) { long i; GEN varg=cgetg(lev+1,t_VECSMALL); vep=cgetg(lev+1,t_VECSMALL); for(i=0;i=0) n += countmatrixelts(tree[x].x)-1; } } return n; } static void compileuninline(GEN arg) { long j; if (lg(arg) > 1) compile_err("too many arguments",tree[arg[1]].str); for(j=0; j=0) { GEN vars = listtogen(tree[x].x,Fmatrixelts); long nv = lg(vars)-1; for (j=1; j<=nv; j++) if (tree[vars[j]].f!=Fnoarg) { ver[++k] = vars[j]; vep[k] = (long)getvar(ver[k]); } continue; } else ver[++k] = x; } else ver[++k] = a; vep[k] = (long)getvar(ver[k]); } checkdups(ver,vep); for(i=1; i<=n; i++) var_push(NULL,Lmy); op_push_loc(OCnewframe,inl?-n:n,str); access_push(lg(vep)-1); frame_push(vep); for (k=0, i=1; i=0) { GEN vars = listtogen(tree[x].x,Fmatrixelts); long nv = lg(vars)-1, m = nv; compilenode(tree[a].y,Ggen,FLnocopy); for (j=1; j<=nv; j++) if (tree[vars[j]].f==Fnoarg) m--; if (m > 1) op_push(OCdup,m-1,x); for (j=1; j<=nv; j++) if (tree[vars[j]].f!=Fnoarg) { long v = detag(vars[j]); op_push(OCpushlong,j,v); op_push(OCcompo1,Ggen,v); k++; op_push(OCstorelex,-n+k-1,a); localvars[s_lvar.n-n+k-1].ep=(entree*)vep[k]; localvars[s_lvar.n-n+k-1].inl=inl; } continue; } else if (!is_node_zero(tree[a].y)) { compilenode(tree[a].y,Ggen,FLnocopy); op_push(OCstorelex,-n+k,a); } } k++; localvars[s_lvar.n-n+k-1].ep=(entree*)vep[k]; localvars[s_lvar.n-n+k-1].inl=inl; } } static long localpush(op_code op, long a) { entree *ep = getvardyn(a); long vep = (long) ep; op_push(op,vep,a); var_push(ep,Llocal); return vep; } static void compilelocal(GEN arg) { long i, j, k, l = lg(arg); long n = countvar(arg); GEN vep = cgetg(n+1,t_VECSMALL); GEN ver = cgetg(n+1,t_VECSMALL); for(k=0, i=1; i=0) { GEN vars = listtogen(tree[x].x,Fmatrixelts); long nv = lg(vars)-1, m = nv; compilenode(tree[a].y,Ggen,FLnocopy); for (j=1; j<=nv; j++) if (tree[vars[j]].f==Fnoarg) m--; if (m > 1) op_push(OCdup,m-1,x); for (j=1; j<=nv; j++) if (tree[vars[j]].f!=Fnoarg) { long v = detag(vars[j]); op_push(OCpushlong,j,v); op_push(OCcompo1,Ggen,v); vep[++k] = localpush(OClocalvar, v); ver[k] = v; } continue; } else if (!is_node_zero(tree[a].y)) { compilenode(tree[a].y,Ggen,FLnocopy); ver[++k] = x; vep[k] = localpush(OClocalvar, ver[k]); continue; } else ver[++k] = x; } else ver[++k] = a; vep[k] = localpush(OClocalvar0, ver[k]); } checkdups(ver,vep); } static void compileexport(GEN arg) { long i, l = lg(arg); for (i=1; i=OPnboperator) str=tree[x].str; else { if (nb==2) str=tree[arg[1]].str+tree[arg[1]].len; else if (nb==1) str=tree[arg[1]].str; else str=tree[n].str; while(*str==')') str++; } if (tree[n].f==Fassign) { nb=2; lnc=2; lnl=2; arg=mkvecsmall2(x,y); } else if (is_func_named(ep,"if")) { if (nb>=4) ep=is_entry("_multi_if"); else if (mode==Gvoid) ep=is_entry("_void_if"); } else if (is_func_named(ep,"return") && (flag&FLreturn) && nb<=1) { if (nb==0) op_push(OCpushgnil,0,n); else compilenode(arg[1],Ggen,FLsurvive|FLreturn); set_avma(ltop); return; } else if (is_func_named(ep,"inline")) { compilemy(arg, str, 1); compilecast(n,Gvoid,mode); set_avma(ltop); return; } else if (is_func_named(ep,"uninline")) { compileuninline(arg); compilecast(n,Gvoid,mode); set_avma(ltop); return; } else if (is_func_named(ep,"my")) { compilemy(arg, str, 0); compilecast(n,Gvoid,mode); set_avma(ltop); return; } else if (is_func_named(ep,"local")) { compilelocal(arg); compilecast(n,Gvoid,mode); set_avma(ltop); return; } else if (is_func_named(ep,"export")) { compileexport(arg); compilecast(n,Gvoid,mode); set_avma(ltop); return; } else if (is_func_named(ep,"unexport")) { compileunexport(arg); compilecast(n,Gvoid,mode); set_avma(ltop); return; } /*We generate dummy code for global() for compatibility with gp2c*/ else if (is_func_named(ep,"global")) { long i; for (i=1;i<=nb;i++) { long a=arg[i]; long en; if (tree[a].f==Fassign) { compilenode(tree[a].y,Ggen,0); a=tree[a].x; en=(long)getvardyn(a); op_push(OCstoredyn,en,a); } else { en=(long)getvardyn(a); op_push(OCpushdyn,en,a); op_push(OCpop,1,a); } } compilecast(n,Gvoid,mode); set_avma(ltop); return; } else if (is_func_named(ep,"O")) { if (nb!=1) compile_err("wrong number of arguments", tree[n].str+tree[n].len-1); ep=is_entry("O(_^_)"); if (tree[arg[1]].f==Ffunction && tree[arg[1]].x==OPpow) { arg = listtogen(tree[arg[1]].y,Flistarg); nb = lg(arg)-1; lnc = first_safe_arg(arg,COsafelex|COsafedyn); lnl = first_safe_arg(arg,COsafelex); } } else if (x==OPn && tree[y].f==Fsmall) { set_avma(ltop); compilesmall(y, -tree[y].x, mode); return; } else if (x==OPtrans && tree[y].f==Fvec) { set_avma(ltop); compilevec(y, mode, OCcol); return; } else if(x==OPlength && tree[y].f==Ffunction && tree[y].x==OPtrans) { arg[1] = tree[y].y; lnc = first_safe_arg(arg,COsafelex|COsafedyn); lnl = first_safe_arg(arg,COsafelex); ep = is_entry("#_~"); } else if (x==OPpow && nb==2) { long a = arg[2]; if (tree[a].f==Fsmall) { if(tree[a].x==2) { nb--; ep=is_entry("sqr"); } else ep=is_entry("_^s"); } else if (tree[a].f == Ffunction && tree[a].x == OPn) { long ay = tree[a].y; if (tree[ay].f==Fsmall) { if (tree[ay].x==1) {nb--; ep=is_entry("_inv"); } else ep=is_entry("_^s"); } } } else if (x==OPcat) compile_err("expected character: ',' or ')' instead of", tree[arg[1]].str+tree[arg[1]].len); p=ep->code; if (!ep->value) compile_err("unknown function",tree[n].str); nbopcodes = s_opcode.n; ret_op = get_ret_type(&p, ep->arity, &ret_typ, &ret_flag); j=1; if (*p) { q=p; while((mod=parseproto(&p,&c,tree[n].str))!=PPend) { if (j<=nb && tree[arg[j]].f!=Fnoarg && (mod==PPdefault || mod==PPdefaultmulti)) mod=PPstd; switch(mod) { case PPstd: if (j>nb) compile_err("too few arguments", tree[n].str+tree[n].len-1); if (c!='I' && c!='E' && c!='J') { long x = tree[arg[j]].x, f = tree[arg[j]].f; if (f==Fnoarg) compile_err("missing mandatory argument", tree[arg[j]].str); if (f==Fseq) compile_err("unexpected ';'", tree[x].str+tree[x].len); } switch(c) { case 'G': compilenode(arg[j],Ggen,j>=lnl?(j>=lnc?FLnocopy:FLnocopylex):0); j++; break; case 'W': { long a = tree[arg[j]].f==Findarg ? tree[arg[j]].x: arg[j]; entree *ep = getlvalue(a); long vn = getmvar(ep); if (vn) op_push(OCcowvarlex, vn, a); else op_push(OCcowvardyn, (long)ep, a); compilenode(a, Ggen,FLnocopy); j++; break; } case 'M': if (tree[arg[j]].f!=Fsmall) { const char *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,FLnocopy); op_push(OCevalmnem,(long)ep,n); } break; } case 'P': case 'L': compilenode(arg[j++],Gsmall,0); break; case 'U': compilenode(arg[j++],Gusmall,0); break; case 'n': compilenode(arg[j++],Gvar,0); break; 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) { access_push(vn); op_push(OCsimpleptrlex, vn,n); } else op_push(OCsimpleptrdyn, (long)ep,n); } else { compilenewptr(vn, ep, a); compilelvalue(a); op_push(OCpushptr, 0, a); } nbpointers++; break; } case 'I': case 'E': case 'J': { long a = arg[j++]; GEN d = compilefuncinline(n, c, a, flag, is_func_named(ep,"if"), lev, ev); op_push(OCpushgen, data_push(d), a); if (lg(d)==8) op_push(OCsaveframe,FLsurvive,n); break; } case 'V': { long a = arg[j++]; (void)getvar(a); ev[lev++] = a; break; } case '=': { long a = arg[j++]; ev[lev++] = tree[a].x; compilenode(tree[a].y, Ggen, FLnocopy); } break; case 'r': { long a=arg[j++]; if (tree[a].f==Fentry) { op_push(OCpushgen, data_push(strntoGENstr(tree[tree[a].x].str, tree[tree[a].x].len)),n); op_push(OCtostr, -1,n); } else { compilenode(a,Ggen,FLnocopy); op_push(OCtostr, -1,n); } break; } case 's': { long a = arg[j++]; GEN g = cattovec(a, OPcat); long l, nb = lg(g)-1; if (nb==1) { compilenode(g[1], Ggen, FLnocopy); op_push(OCtostr, -1, a); } else { op_push(OCvec, nb+1, a); for(l=1; l<=nb; l++) { compilenode(g[l], Ggen, FLsurvive); op_push(OCstackgen,l, a); } op_push(OCpop, 1, a); op_push(OCcallgen,(long)is_entry("Str"), a); op_push(OCtostr, -1, a); } break; } default: pari_err(e_MISC,"Unknown prototype code `%c' for `%.*s'",c, tree[x].len, tree[x].str); } break; case PPauto: switch(c) { case 'p': op_push(OCprecreal,0,n); break; case 'b': op_push(OCbitprecreal,0,n); break; case 'P': op_push(OCprecdl,0,n); break; case 'C': op_push(OCpushgen,data_push(pack_localvars()),n); break; case 'f': { static long foo; op_push(OCpushlong,(long)&foo,n); break; } } break; case PPdefault: j++; switch(c) { case 'G': case '&': case 'E': case 'I': case 'r': case 's': op_push(OCpushlong,0,n); break; case 'n': op_push(OCpushlong,-1,n); break; case 'V': ev[lev++] = -1; break; case 'P': op_push(OCprecdl,0,n); break; default: pari_err(e_MISC,"Unknown prototype code `%c' for `%.*s'",c, tree[x].len, tree[x].str); } break; case PPdefaultmulti: j++; switch(c) { case 'G': op_push(OCpushstoi,strtol(q+1,NULL,10),n); break; case 'L': case 'M': op_push(OCpushlong,strtol(q+1,NULL,10),n); break; case 'U': op_push(OCpushlong,(long)strtoul(q+1,NULL,10),n); break; case 'r': case 's': str_defproto(p, q, tree[n].str); op_push(OCtostr, -1, n); break; default: pari_err(e_MISC,"Unknown prototype code `%c' for `%.*s'",c, tree[x].len, tree[x].str); } break; case PPstar: switch(c) { case 'E': { long k, n=nb+1-j; GEN g=cgetg(n+1,t_VEC); int ismif = is_func_named(ep,"_multi_if"); for(k=1; k<=n; k++) gel(g, k) = compilefuncinline(n, c, arg[j+k-1], flag, ismif && (k==n || odd(k)), lev, ev); op_push(OCpushgen, data_push(g), arg[j]); j=nb+1; break; } case 's': { long n=nb+1-j; long k,l,l1,m; GEN g=cgetg(n+1,t_VEC); for(l1=0,k=1;k<=n;k++) { gel(g,k)=cattovec(arg[j+k-1],OPcat); l1+=lg(gel(g,k))-1; } op_push_loc(OCvec, l1+1, str); for(m=1,k=1;k<=n;k++) for(l=1;lnbopcodes+128) { op_insert_loc(nbopcodes,OCavma,0,str); op_push_loc(OCgerepile,0,str); } compilecast(n,ret_typ,mode); if (nbpointers) op_push_loc(OCendptr,nbpointers, str); set_avma(ltop); } static void genclosurectx(const char *loc, long nbdata) { long i; GEN vep = cgetg(nbdata+1,t_VECSMALL); for(i = 1; i <= nbdata; i++) { vep[i] = 0; op_push_loc(OCpushlex,-i,loc); } frame_push(vep); } static GEN genclosure(entree *ep, const char *loc, long nbdata, int check) { struct codepos pos; long nb=0; const char *code=ep->code,*p,*q; char c; GEN text; long index=ep->arity; long arity=0, maskarg=0, maskarg0=0, stop=0, dovararg=0; PPproto mod; Gtype ret_typ; long ret_flag; op_code ret_op=get_ret_type(&code,ep->arity,&ret_typ,&ret_flag); p=code; while ((mod=parseproto(&p,&c,NULL))!=PPend) { if (mod==PPauto) stop=1; else { if (stop) return NULL; if (c=='V') continue; maskarg<<=1; maskarg0<<=1; arity++; switch(mod) { case PPstd: maskarg|=1L; break; case PPdefault: switch(c) { case '&': case 'E': case 'I': maskarg0|=1L; break; } break; default: break; } } } if (check && EpSTATIC(ep) && maskarg==0) return gen_0; getcodepos(&pos); dbgstart = loc; if (nbdata > arity) pari_err(e_MISC,"too many parameters for closure `%s'", ep->name); if (nbdata) genclosurectx(loc, nbdata); text = strtoGENstr(ep->name); arity -= nbdata; if (maskarg) op_push_loc(OCcheckargs,maskarg,loc); if (maskarg0) op_push_loc(OCcheckargs0,maskarg0,loc); 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 'b': op_push_loc(OCbitprecreal,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 'U': op_push_loc(OCitou,-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': break; case 'r': case 's': op_push_loc(OCtostr,-index,loc); break; case 'n': op_push_loc(OCvarn,-index,loc); break; case 'P': op_push_loc(OCprecdl,0,loc); op_push_loc(OCdefaultlong,-index,loc); break; default: pari_err(e_MISC,"Unknown prototype code `D%c' for `%s'",c,ep->name); } break; case PPdefaultmulti: switch(c) { case 'G': op_push_loc(OCpushstoi,strtol(q+1,NULL,10),loc); op_push_loc(OCdefaultgen,-index,loc); break; case 'L': case 'M': op_push_loc(OCpushlong,strtol(q+1,NULL,10),loc); op_push_loc(OCdefaultlong,-index,loc); break; case 'U': op_push_loc(OCpushlong,(long)strtoul(q+1,NULL,10),loc); op_push_loc(OCdefaultulong,-index,loc); break; case 'r': case 's': str_defproto(p, q, loc); op_push_loc(OCdefaultgen,-index,loc); op_push_loc(OCtostr,-index,loc); break; default: pari_err(e_MISC, "Unknown prototype code `D...,%c,' for `%s'",c,ep->name); } break; case PPstar: switch(c) { case 's': dovararg = 1; break; case 'E': return NULL; default: pari_err(e_MISC,"Unknown prototype code `%c*' for `%s'",c,ep->name); } break; default: return NULL; } index--; q = p; } op_push_loc(ret_op, (long) ep, loc); if (ret_flag==FLnocopy) op_push_loc(OCcopy,0,loc); compilecast_loc(ret_typ, Ggen, loc); if (dovararg) nb|=VARARGBITS; return getfunction(&pos,nb+arity,nbdata,text,0); } GEN snm_closure(entree *ep, GEN data) { long i, n = data ? lg(data)-1: 0; GEN C = genclosure(ep,ep->name,n,0); for(i = 1; i <= n; i++) gmael(C,7,i) = gel(data,i); return C; } GEN strtoclosure(const char *s, long n, ...) { pari_sp av = avma; entree *ep = is_entry(s); GEN C; if (!ep) pari_err(e_NOTFUNC, strtoGENstr(s)); ep = do_alias(ep); if ((!EpSTATIC(ep) && EpVALENCE(ep)!=EpINSTALL) || !ep->value) pari_err(e_MISC,"not a built-in/install'ed function: \"%s\"",s); C = genclosure(ep,ep->name,n,0); if (!C) pari_err(e_MISC,"function prototype unsupported: \"%s\"",s); else { va_list ap; long i; va_start(ap,n); for(i = 1; i <= n; i++) gmael(C,7,i) = va_arg(ap, GEN); va_end(ap); } return gerepilecopy(av, C); } GEN strtofunction(const char *s) { return strtoclosure(s, 0); } GEN call0(GEN fun, GEN args) { if (!is_vec_t(typ(args))) pari_err_TYPE("call",args); switch(typ(fun)) { case t_STR: fun = strtofunction(GSTR(fun)); case t_CLOSURE: /* fall through */ return closure_callgenvec(fun, args); default: pari_err_TYPE("call", fun); return NULL; /* LCOV_EXCL_LINE */ } } 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); set_avma(ltop); } static void compileseq(long n, int mode, long flag) { pari_sp av = avma; GEN L = listtogen(n, Fseq); long i, l = lg(L)-1; for(i = 1; i < l; i++) compilenode(L[i],Gvoid,0); compilenode(L[l],mode,flag&(FLreturn|FLsurvive)); set_avma(av); } static void compilenode(long n, int mode, long flag) { long x,y; #ifdef STACK_CHECK if (PARI_stack_limit && (void*) &x <= PARI_stack_limit) pari_err(e_MISC, "expression nested too deeply"); #endif if (n<0) pari_err_BUG("compilenode"); x=tree[n].x; y=tree[n].y; switch(tree[n].f) { case Fseq: compileseq(n, mode, flag); return; case Fmatcoeff: compilematcoeff(n,mode); if (mode==Ggen && !(flag&FLnocopy)) op_push(OCcopy,0,n); return; case Fassign: x = detag(x); if (tree[x].f==Fvec && tree[x].x>=0) { GEN vars = listtogen(tree[x].x,Fmatrixelts); long i, l = lg(vars)-1, d = mode==Gvoid? l-1: l; compilenode(y,Ggen,mode==Gvoid?0:flag&FLsurvive); for (i=1; i<=l; i++) if (tree[vars[i]].f==Fnoarg) d--; if (d) op_push(OCdup, d, x); for(i=1; i<=l; i++) if (tree[vars[i]].f!=Fnoarg) { long a = detag(vars[i]); entree *ep=getlvalue(a); long vn=getmvar(ep); op_push(OCpushlong,i,a); op_push(OCcompo1,Ggen,a); if (tree[a].f==Fentry) compilestore(vn,ep,n); else { compilenewptr(vn,ep,n); compilelvalue(a); op_push(OCstoreptr,0,a); } } if (mode!=Gvoid) compilecast(n,Ggen,mode); } else { entree *ep=getlvalue(x); long vn=getmvar(ep); if (tree[x].f!=Fentry) { compilenewptr(vn,ep,n); compilelvalue(x); } compilenode(y,Ggen,mode==Gvoid?FLnocopy:flag&FLsurvive); if (mode!=Gvoid) op_push(OCdup,1,n); if (tree[x].f==Fentry) compilestore(vn,ep,n); else op_push(OCstoreptr,0,x); if (mode!=Gvoid) compilecast(n,Ggen,mode); } return; case Fconst: { pari_sp ltop=avma; if (tree[n].x!=CSTquote) { if (mode==Gvoid) return; if (mode==Gvar) compile_varerr(tree[n].str); } if (mode==Gsmall) L_compile_err(tree[n].str); if (mode==Gusmall && tree[n].x != CSTint) U_compile_err(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: { /* skip ' */ entree *ep = fetch_entry_raw(tree[n].str+1,tree[n].len-1); if (EpSTATIC(ep)) compile_varerr(tree[n].str+1); op_push(OCpushvar, (long)ep,n); compilecast(n,Ggen, mode); break; } default: pari_err_BUG("compilenode, unsupported constant"); } set_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 Findarg: compile_err("unexpected character '~':",tree[n].str); return; case Fentry: { entree *ep=getentry(n); long vn=getmvar(ep); if (vn) { access_push(vn); op_push(OCpushlex,(long)vn,n); addcopy(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); addcopy(n,mode,flag,FLnocopy); compilecast(n,Ggen,mode); } else closurefunc(ep,n,mode); return; } case Ffunction: { entree *ep=getfunc(n); if (getmvar(ep) || EpVALENCE(ep)==EpVAR || EpVALENCE(ep)==EpNEW) { if (tree[n].xstrictargs; GEN vep = cgetg_copy(arg, &lgarg); GEN text=cgetg(3,t_VEC); gel(text,1)=strntoGENstr(tree[x].str,tree[x].len); if (lgarg==2 && tree[x].str[0]!='~' && tree[x].f==Findarg) /* This occurs for member functions */ gel(text,1)=shallowconcat(strntoGENstr("~",1),gel(text,1)); gel(text,2)=strntoGENstr(tree[y].str,tree[y].len); getcodepos(&pos); dbgstart=tree[x].str+tree[x].len; gap = tree[y].str-dbgstart; nbmvar = nblex; ctxmvar(nbmvar); nb = lgarg-1; if (nb) { long i; for(i=1;i<=nb;i++) { long a = arg[i], f = tree[a].f; if (i==nb && f==Fvararg) { dovararg=1; vep[i]=(long)getvar(tree[a].x); } else vep[i]=(long)getvar(f==Fassign||f==Findarg?tree[a].x:a); var_push(NULL,Lmy); } checkdups(arg,vep); op_push(OCgetargs,nb,x); access_push(lg(vep)-1); frame_push(vep); for (i=1;i<=nb;i++) { long a = arg[i], f = tree[a].f; long y = tree[a].y; if (f==Fassign && (strict || !is_node_zero(y))) { if (tree[y].f==Fsmall) compilenode(y, Ggen, 0); else { struct codepos lpos; long nbmvar = nblex; getcodepos(&lpos); compilenode(y, Ggen, 0); op_push(OCpushgen, data_push(getclosure(&lpos,nbmvar)),a); } op_push(OCdefaultarg,-nb+i-1,a); } else if (f==Findarg) op_push(OCsetref, -nb+i-1, a); localvars[s_lvar.n-nb+i-1].ep=(entree*)vep[i]; } } if (strict) op_push(OCcheckuserargs,nb,x); dbgstart=tree[y].str; if (y>=0 && tree[y].f!=Fnoarg) compilenode(y,Ggen,FLsurvive|FLreturn); else compilecast(n,Gvoid,Ggen); if (dovararg) nb|=VARARGBITS; op_push(OCpushgen, data_push(getfunction(&pos,nb,nbmvar,text,gap)),n); if (nbmvar) op_push(OCsaveframe,!!(flag&FLsurvive),n); compilecast(n, Gclosure, mode); set_avma(ltop); return; } case Ftag: compilenode(x, mode,flag); return; case Fnoarg: compilecast(n,Gvoid,mode); return; case Fnorange: op_push(OCpushlong,LONG_MAX,n); compilecast(n,Gsmall,mode); return; default: pari_err_BUG("compilenode"); } } GEN gp_closure(long n) { struct codepos pos; getcodepos(&pos); dbgstart=tree[n].str; compilenode(n,Ggen,FLsurvive|FLreturn); return getfunction(&pos,0,0,strntoGENstr(tree[n].str,tree[n].len),0); } GEN closure_derivn(GEN G, long n) { pari_sp ltop = avma; struct codepos pos; long arity = closure_arity(G); const char *code; GEN t, text; if (arity == 0 || closure_is_variadic(G)) pari_err_TYPE("derivfun",G); t = closure_get_text(G); code = GSTR((typ(t) == t_STR)? t: GENtoGENstr(G)); if (n > 1) { text = cgetg(1+nchar2nlong(9+strlen(code)+n),t_STR); sprintf(GSTR(text), "derivn(%s,%ld)", code, n); } else { text = cgetg(1+nchar2nlong(4+strlen(code)),t_STR); sprintf(GSTR(text), (typ(t) == t_STR)? "%s'": "(%s)'",code); } getcodepos(&pos); dbgstart = code; op_push_loc(OCpackargs, arity, code); op_push_loc(OCpushgen, data_push(G), code); op_push_loc(OCpushlong, n, code); op_push_loc(OCprecreal, 0, code); op_push_loc(OCcallgen, (long)is_entry("_derivfun"), code); return gerepilecopy(ltop, getfunction(&pos, arity, 0, text, 0)); } GEN closure_deriv(GEN G) { return closure_derivn(G, 1); } 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; char c; GEN arg = listtogen(y,Flistarg); long nb=lg(arg)-1, ret_flag; if (is_func_named(ep,"if") && nb>=4) ep=is_entry("_multi_if"); p = ep->code; 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 'U': case 'P': optimizenode(arg[j]); fl&=tree[arg[j++]].flags; break; case 'I': case 'E': case 'J': optimizenode(arg[j]); fl&=tree[arg[j]].flags; tree[arg[j++]].flags=COsafelex|COsafedyn; break; case '&': case '*': { long a=arg[j]; if (c=='&') { if (tree[a].f!=Frefarg) compile_err("expected character: '&'", tree[a].str); a=tree[a].x; } optimizenode(a); tree[arg[j++]].flags=COsafelex|COsafedyn; fl=0; break; } case 'W': { long a = tree[arg[j]].f==Findarg ? tree[arg[j]].x: arg[j]; optimizenode(a); fl=0; j++; break; } case 'V': case 'r': tree[arg[j++]].flags=COsafelex|COsafedyn; break; case '=': { long a=arg[j++], y=tree[a].y; if (tree[a].f!=Fassign) compile_err("expected character: '=' instead of", tree[a].str+tree[a].len); optimizenode(y); fl&=tree[y].flags; } break; case 's': fl &= vec_optimize(cattovec(arg[j++], OPcat)); break; default: pari_err(e_MISC,"Unknown prototype code `%c' for `%.*s'",c, tree[x].len, tree[x].str); } break; case PPauto: break; case PPdefault: case PPdefaultmulti: if (j<=nb) optimizenode(arg[j++]); break; case PPstar: switch(c) { case 'E': { long n=nb+1-j; long k; for(k=1;k<=n;k++) { optimizenode(arg[j+k-1]); fl &= tree[arg[j+k-1]].flags; } j=nb+1; break; } case 's': { long n=nb+1-j; long k; for(k=1;k<=n;k++) fl &= vec_optimize(cattovec(arg[j+k-1],OPcat)); j=nb+1; break; } default: pari_err(e_MISC,"Unknown prototype code `%c*' for `%.*s'",c, tree[x].len, tree[x].str); } break; default: pari_err_BUG("optimizefun [unknown PPproto]"); } } if (j<=nb) compile_err("too many arguments",tree[arg[j]].str); } else (void)vec_optimize(arg); set_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); set_avma(av); } static void optimizeseq(long n) { pari_sp av = avma; GEN L = listtogen(n, Fseq); long i, l = lg(L)-1, flags=-1L; for(i = 1; i <= l; i++) { optimizenode(L[i]); flags &= tree[L[i]].flags; } set_avma(av); tree[n].flags = flags; } void optimizenode(long n) { long x,y; #ifdef STACK_CHECK if (PARI_stack_limit && (void*) &x <= PARI_stack_limit) pari_err(e_MISC, "expression nested too deeply"); #endif if (n<0) pari_err_BUG("optimizenode"); x=tree[n].x; y=tree[n].y; switch(tree[n].f) { case Fseq: optimizeseq(n); return; case Frange: optimizenode(x); optimizenode(y); tree[n].flags=tree[x].flags&tree[y].flags; break; case Fmatcoeff: optimizematcoeff(n); break; case Fassign: optimizenode(x); optimizenode(y); tree[n].flags=0; break; case Fnoarg: case Fnorange: 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 Findarg: return; case Fvararg: compile_err("unexpected characters '..'",tree[n].str); return; case Ffunction: { entree *ep=getfunc(n); if (EpVALENCE(ep)==EpVAR || EpVALENCE(ep)==EpNEW) optimizecall(n); else optimizefunc(ep,n); return; } case Fcall: optimizecall(n); return; case Flambda: optimizenode(y); tree[n].flags=COsafelex|COsafedyn; return; case Ftag: optimizenode(x); tree[n].flags=tree[x].flags; return; default: pari_err_BUG("optimizenode"); } } pari-2.17.2/src/language/readline.c0000644000175000017500000002737714760123736015516 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*******************************************************************/ /* */ /* INTERFACE TO READLINE COMPLETION */ /* */ /*******************************************************************/ #include "pari.h" #include "paripriv.h" /**************************************************************************/ static entree *current_ep = NULL; /* do we add () at the end of completed word? (is it a function?) */ static int add_paren(pari_rl_interface *rl, int end) { entree *ep; const char *s; if (end < 0 || (*rl->line_buffer)[end] == '(') return 0; /* not from command_generator or already there */ ep = do_alias(current_ep); /* current_ep set in command_generator */ if (EpVALENCE(ep) < EpNEW) { /* is it a constant masked as a function (e.g Pi)? */ s = ep->help; if (!s) return 1; while (is_keyword_char(*s)) s++; return (*s != '='); } switch(EpVALENCE(ep)) { case EpVAR: return typ((GEN)ep->value) == t_CLOSURE; case EpINSTALL: return 1; } return 0; } static void match_concat(char **matches, const char *s) { pari_realloc_ip((void**)matches, 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(pari_rl_interface *rl, int code, char **matches) { if (add_paren(rl, code)) { match_concat(matches,"()"); rl->back = 1; if (*rl->point == *rl->end) *rl->completion_append_character = '\0'; /* Do not append space. */ } else if (add_comma(code)) match_concat(matches,","); } #undef add_comma static char ** matches_for_emacs(const char *text, char **matches) { if (!matches) printf("@"); else { int i; printf("%s@", matches[0] + strlen(text)); if (matches[1]) print_fun_list(matches+1,0); /* we don't want readline to do anything, but insert some junk * which will be erased by emacs. */ for (i=0; matches[i]; i++) pari_free(matches[i]); pari_free(matches); } matches = (char **) pari_malloc(2*sizeof(char *)); matches[0] = (char*)pari_malloc(2); sprintf(matches[0],"_"); matches[1] = NULL; printf("@E_N_D"); pari_flush(); return matches; } /* Attempt to complete on the contents of TEXT. 'code' is used to * differentiate between callers when a single match is found. * Return the array of matches, NULL if there are none. */ static char ** get_matches(pari_rl_interface *rl, int code, const char *text, char *(*f)(const char*, int)) { char **matches = rl->completion_matches(text, f); if (matches && !matches[1]) treat_single(rl, code, matches); if (GP_DATA->flags & gpd_EMACS) matches = matches_for_emacs(text,matches); return matches; } 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--; if (j >= 7 && text[j] == '-' && !strncmp(text+(j-7),"refcard",7)) j -= 8; j++; *TEXT = (char*)text + j; *junk = j; *len = l - j; } static int is_internal(entree *ep) { return *ep->name == '_'; } /* Generator function for command completion. STATE lets us know whether * to start from scratch; without any state (i.e. STATE == 0), then we * 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) { const char **L = gphelp_keyword_list(); for ( ; L[n]; n++) if (!strncmp(L[n],TEXT,len)) return add_prefix(L[n++], text, junk); key = 0; state = 0; } return command_generator(text, state); } /* add a space between \ and following text. Attempting completion now * would delete char. Hitting again will complete properly */ static char ** add_space(pari_rl_interface *rl, int start) { char **m; int p = *rl->point + 1; *rl->point = start + 2; rl->insert(1, ' '); *rl->point = p; /*better: fake an empty completion, but don't append ' ' after it! */ *rl->completion_append_character = '\0'; m = (char**)pari_malloc(2 * sizeof(char*)); m[0] = (char*)pari_malloc(1); *(m[0]) = 0; m[1] = NULL; return m; } char ** pari_completion(pari_rl_interface *rl, char *text, int START, int END) { int i, first=0, start=START; char *line = *rl->line_buffer; *rl->completion_append_character = ' '; current_ep = NULL; while (line[first] && isspace((unsigned char)line[first])) first++; if (line[first] == '?') { if (line[first+1] == '?') return get_matches(rl, -1, text, ext_help_generator); return get_matches(rl, -1, text, command_generator); } /* 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 && line[start] != '~') start--; while (start && is_keyword_char(line[start])) start--; if (line[start] == '~') { char *(*f)(const char*, int); f = rl->username_completion_function; for(i=start+1;i<=END;i++) if (line[i] == '/') { f = rl->filename_completion_function; break; } return get_matches(rl, -1, text, f); } if (line[first] == '\\') { if (first == start) return add_space(rl, start); return get_matches(rl, -1, text, rl->filename_completion_function); } while (start && line[start] != '(' && line[start] != ',') start--; if (line[start] == '(' && start) { int iend, j,k; entree *ep; char buf[200]; i = start; while (i && isspace((unsigned char)line[i-1])) i--; iend = i; while (i && is_keyword_char(line[i-1])) i--; if (strncmp(line + i,"default",7) == 0) return get_matches(rl, -2, text, default_generator); if ( strncmp(line + i,"read",4) == 0 || strncmp(line + i,"write",5) == 0) return get_matches(rl, -1, text, rl->filename_completion_function); j = start + 1; while (j <= END && isspace((unsigned char)line[j])) j++; k = END; while (k > j && isspace((unsigned char)line[k])) k--; /* If we are in empty parens, insert the default arguments */ if ((GP_DATA->readline_state & DO_ARGS_COMPLETE) && k == j && (line[j] == ')' || !line[j]) && (iend - i < (long)sizeof(buf)) && ( strncpy(buf, line + i, iend - i), buf[iend - i] = 0, 1) && (ep = is_entry(buf)) && ep->help) { const char *s = ep->help; while (is_keyword_char(*s)) s++; if (*s++ == '(') { /* function call: insert arguments */ const char *e = s; while (*e && *e != ')' && *e != '(') e++; if (*e == ')') { /* we just skipped over the arguments in short help text */ char *str = strncpy((char*)pari_malloc(e-s + 1), s, e-s); char **ret = (char**)pari_malloc(sizeof(char*)*2); str[e-s] = 0; ret[0] = str; ret[1] = NULL; if (GP_DATA->flags & gpd_EMACS) ret = matches_for_emacs("",ret); return ret; } } } } for(i = END-1; i >= start; i--) if (!is_keyword_char(line[i])) { if (line[i] == '.') return get_matches(rl, -1, text, member_generator); break; } return get_matches(rl, END, text, command_generator); } static char * pari_completion_word(char *line, long end) { char *s = line + end, *found_quote = NULL; long i; *s = 0; /* truncate at cursor position */ for (i=0; i < end; i++) { /* first look for unclosed string */ switch(line[i]) { case '"': found_quote = found_quote? NULL: line + i; break; case '\\': i++; break; } } if (found_quote) return found_quote + 1; /* return next char after quote */ /* else find beginning of word */ while (s > line && is_keyword_char(s[-1])) s--; return s; } char ** pari_completion_matches(pari_rl_interface *rl, const char *s, long pos, long *wordpos) { char *text, *b; long w; if (*rl->line_buffer) pari_free(*rl->line_buffer); *rl->line_buffer = b = pari_strdup(s); text = pari_completion_word(b, pos); w = text - b; if (wordpos) *wordpos = w; /* text = start of expression we complete */ *rl->end = strlen(b)-1; *rl->point = pos; return pari_completion(rl, text, w, pos); } pari-2.17.2/src/language/parse.c0000644000175000017500000031641214676526575015052 0ustar billbill/* A Bison parser, made by GNU Bison 3.8.2. */ /* Bison implementation for Yacc-like parsers in C Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 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. */ /* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, especially those whose name start with YY_ or yy_. They are private implementation details that can be changed or removed. */ /* 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, and Bison version. */ #define YYBISON 30802 /* Bison version string. */ #define YYBISON_VERSION "3.8.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 2 /* Push parsers. */ #define YYPUSH 0 /* Pull parsers. */ #define YYPULL 1 /* Substitute the type names. */ #define YYSTYPE PARI_STYPE #define YYLTYPE PARI_LTYPE /* Substitute the variable and function names. */ #define yyparse pari_parse #define yylex pari_lex #define yyerror pari_error #define yydebug pari_debug #define yynerrs pari_nerrs /* First part of user prologue. */ #line 1 "../src/language/parse.y" /* Copyright (C) 2006 The PARI group. This file is part of the PARI package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #define PARI_STYPE union token_value #define PARI_LTYPE struct node_loc #define YYPTRDIFF_T long #define YYPTRDIFF_MAXIMUM LONG_MAX #define YYSIZE_T size_t #define YYLLOC_DEFAULT(Current, Rhs, N) \ ((Current).start = ((N)?(Rhs)[1].start:(Rhs)[0].end), \ (Current).end = (Rhs)[N].end) #include "parsec.h" #define NOARG(x) newnode(Fnoarg,-1,-1,&(x)) #define NORANGE(x) newnode(Fnorange,-1,-1,&(x)) #line 106 "../src/language/parse.c" # ifndef YY_CAST # ifdef __cplusplus # define YY_CAST(Type, Val) static_cast (Val) # define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast (Val) # else # define YY_CAST(Type, Val) ((Type) (Val)) # define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val)) # endif # endif # ifndef YY_NULLPTR # if defined __cplusplus # if 201103L <= __cplusplus # define YY_NULLPTR nullptr # else # define YY_NULLPTR 0 # endif # else # define YY_NULLPTR ((void*)0) # endif # endif #include "parse.h" /* Symbol kind. */ enum yysymbol_kind_t { YYSYMBOL_YYEMPTY = -2, YYSYMBOL_YYEOF = 0, /* "end of file" */ YYSYMBOL_YYerror = 1, /* error */ YYSYMBOL_YYUNDEF = 2, /* "invalid token" */ YYSYMBOL_KPARROW = 3, /* ")->" */ YYSYMBOL_KARROW = 4, /* "->" */ YYSYMBOL_KDOTDOT = 5, /* ".." */ YYSYMBOL_KPE = 6, /* "+=" */ YYSYMBOL_KSE = 7, /* "-=" */ YYSYMBOL_KME = 8, /* "*=" */ YYSYMBOL_KDE = 9, /* "/=" */ YYSYMBOL_KDRE = 10, /* "\\/=" */ YYSYMBOL_KEUCE = 11, /* "\\=" */ YYSYMBOL_KMODE = 12, /* "%=" */ YYSYMBOL_KAND = 13, /* "&&" */ YYSYMBOL_KOR = 14, /* "||" */ YYSYMBOL_KID = 15, /* "===" */ YYSYMBOL_KEQ = 16, /* "==" */ YYSYMBOL_KNE = 17, /* "!=" */ YYSYMBOL_KGE = 18, /* ">=" */ YYSYMBOL_KLE = 19, /* "<=" */ YYSYMBOL_KSRE = 20, /* ">>=" */ YYSYMBOL_KSLE = 21, /* "<<=" */ YYSYMBOL_KSR = 22, /* ">>" */ YYSYMBOL_KSL = 23, /* "<<" */ YYSYMBOL_KDR = 24, /* "\\/" */ YYSYMBOL_KPP = 25, /* "++" */ YYSYMBOL_KSS = 26, /* "--" */ YYSYMBOL_KINTEGER = 27, /* "integer" */ YYSYMBOL_KREAL = 28, /* "real number" */ YYSYMBOL_KENTRY = 29, /* "variable name" */ YYSYMBOL_KSTRING = 30, /* "character string" */ YYSYMBOL_SEQ = 31, /* SEQ */ YYSYMBOL_DEFFUNC = 32, /* DEFFUNC */ YYSYMBOL_INT = 33, /* INT */ YYSYMBOL_LVAL = 34, /* LVAL */ YYSYMBOL_35_ = 35, /* ';' */ YYSYMBOL_36_ = 36, /* ',' */ YYSYMBOL_37_ = 37, /* '=' */ YYSYMBOL_38_ = 38, /* '&' */ YYSYMBOL_39_ = 39, /* '>' */ YYSYMBOL_40_ = 40, /* '<' */ YYSYMBOL_41_ = 41, /* '+' */ YYSYMBOL_42_ = 42, /* '-' */ YYSYMBOL_43_ = 43, /* '%' */ YYSYMBOL_44_ = 44, /* '\\' */ YYSYMBOL_45_ = 45, /* '/' */ YYSYMBOL_46_ = 46, /* '*' */ YYSYMBOL_SIGN = 47, /* SIGN */ YYSYMBOL_48_ = 48, /* '^' */ YYSYMBOL_49_ = 49, /* '#' */ YYSYMBOL_50_ = 50, /* '!' */ YYSYMBOL_51_ = 51, /* '~' */ YYSYMBOL_52_ = 52, /* '[' */ YYSYMBOL_DERIV = 53, /* DERIV */ YYSYMBOL_54_ = 54, /* '\'' */ YYSYMBOL_55_ = 55, /* '.' */ YYSYMBOL_56_ = 56, /* '(' */ YYSYMBOL_57_ = 57, /* ':' */ YYSYMBOL_58_ = 58, /* ']' */ YYSYMBOL_59_ = 59, /* '`' */ YYSYMBOL_60_ = 60, /* ')' */ YYSYMBOL_61_ = 61, /* '|' */ YYSYMBOL_YYACCEPT = 62, /* $accept */ YYSYMBOL_sequence = 63, /* sequence */ YYSYMBOL_seq = 64, /* seq */ YYSYMBOL_range = 65, /* range */ YYSYMBOL_matrix_index = 66, /* matrix_index */ YYSYMBOL_backticks = 67, /* backticks */ YYSYMBOL_history = 68, /* history */ YYSYMBOL_deriv = 69, /* deriv */ YYSYMBOL_expr = 70, /* expr */ YYSYMBOL_lvalue = 71, /* lvalue */ YYSYMBOL_exprno = 72, /* exprno */ YYSYMBOL_matrixeltsno = 73, /* matrixeltsno */ YYSYMBOL_matrixelts = 74, /* matrixelts */ YYSYMBOL_matrixlines = 75, /* matrixlines */ YYSYMBOL_matrix = 76, /* matrix */ YYSYMBOL_in = 77, /* in */ YYSYMBOL_inseq = 78, /* inseq */ YYSYMBOL_compr = 79, /* compr */ YYSYMBOL_arg = 80, /* arg */ YYSYMBOL_81_1 = 81, /* $@1 */ YYSYMBOL_listarg = 82, /* listarg */ YYSYMBOL_funcid = 83, /* funcid */ YYSYMBOL_memberid = 84, /* memberid */ YYSYMBOL_definition = 85 /* definition */ }; typedef enum yysymbol_kind_t yysymbol_kind_t; #ifdef short # undef short #endif /* On compilers that do not define __PTRDIFF_MAX__ etc., make sure and (if available) are included so that the code can choose integer types of a good width. */ #ifndef __PTRDIFF_MAX__ # include /* INFRINGES ON USER NAME SPACE */ # if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ # include /* INFRINGES ON USER NAME SPACE */ # define YY_STDINT_H # endif #endif /* Narrow types that promote to a signed type and that can represent a signed or unsigned integer of at least N bits. In tables they can save space and decrease cache pressure. Promoting to a signed type helps avoid bugs in integer arithmetic. */ #ifdef __INT_LEAST8_MAX__ typedef __INT_LEAST8_TYPE__ yytype_int8; #elif defined YY_STDINT_H typedef int_least8_t yytype_int8; #else typedef signed char yytype_int8; #endif #ifdef __INT_LEAST16_MAX__ typedef __INT_LEAST16_TYPE__ yytype_int16; #elif defined YY_STDINT_H typedef int_least16_t yytype_int16; #else typedef short yytype_int16; #endif /* Work around bug in HP-UX 11.23, which defines these macros incorrectly for preprocessor constants. This workaround can likely be removed in 2023, as HPE has promised support for HP-UX 11.23 (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of . */ #ifdef __hpux # undef UINT_LEAST8_MAX # undef UINT_LEAST16_MAX # define UINT_LEAST8_MAX 255 # define UINT_LEAST16_MAX 65535 #endif #if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ typedef __UINT_LEAST8_TYPE__ yytype_uint8; #elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ && UINT_LEAST8_MAX <= INT_MAX) typedef uint_least8_t yytype_uint8; #elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX typedef unsigned char yytype_uint8; #else typedef short yytype_uint8; #endif #if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__ typedef __UINT_LEAST16_TYPE__ yytype_uint16; #elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \ && UINT_LEAST16_MAX <= INT_MAX) typedef uint_least16_t yytype_uint16; #elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX typedef unsigned short yytype_uint16; #else typedef int yytype_uint16; #endif #ifndef YYPTRDIFF_T # if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__ # define YYPTRDIFF_T __PTRDIFF_TYPE__ # define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__ # elif defined PTRDIFF_MAX # ifndef ptrdiff_t # include /* INFRINGES ON USER NAME SPACE */ # endif # define YYPTRDIFF_T ptrdiff_t # define YYPTRDIFF_MAXIMUM PTRDIFF_MAX # else # define YYPTRDIFF_T long # define YYPTRDIFF_MAXIMUM LONG_MAX # endif #endif #ifndef YYSIZE_T # ifdef __SIZE_TYPE__ # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t # elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else # define YYSIZE_T unsigned # endif #endif #define YYSIZE_MAXIMUM \ YY_CAST (YYPTRDIFF_T, \ (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \ ? YYPTRDIFF_MAXIMUM \ : YY_CAST (YYSIZE_T, -1))) #define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X)) /* Stored state numbers (used for stacks). */ typedef yytype_uint8 yy_state_t; /* State numbers in computations. */ typedef int yy_state_fast_t; #ifndef YY_ # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(Msgid) dgettext ("bison-runtime", Msgid) # endif # endif # ifndef YY_ # define YY_(Msgid) Msgid # endif #endif #ifndef YY_ATTRIBUTE_PURE # if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__) # define YY_ATTRIBUTE_PURE __attribute__ ((__pure__)) # else # define YY_ATTRIBUTE_PURE # endif #endif #ifndef YY_ATTRIBUTE_UNUSED # if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__) # define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) # else # define YY_ATTRIBUTE_UNUSED # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YY_USE(E) ((void) (E)) #else # define YY_USE(E) /* empty */ #endif /* Suppress an incorrect diagnostic about yylval being uninitialized. */ #if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__ # if __GNUC__ * 100 + __GNUC_MINOR__ < 407 # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ _Pragma ("GCC diagnostic push") \ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") # else # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ _Pragma ("GCC diagnostic push") \ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") # endif # define YY_IGNORE_MAYBE_UNINITIALIZED_END \ _Pragma ("GCC diagnostic pop") #else # define YY_INITIAL_VALUE(Value) Value #endif #ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN # define YY_IGNORE_MAYBE_UNINITIALIZED_END #endif #ifndef YY_INITIAL_VALUE # define YY_INITIAL_VALUE(Value) /* Nothing. */ #endif #if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__ # define YY_IGNORE_USELESS_CAST_BEGIN \ _Pragma ("GCC diagnostic push") \ _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"") # define YY_IGNORE_USELESS_CAST_END \ _Pragma ("GCC diagnostic pop") #endif #ifndef YY_IGNORE_USELESS_CAST_BEGIN # define YY_IGNORE_USELESS_CAST_BEGIN # define YY_IGNORE_USELESS_CAST_END #endif #define YY_ASSERT(E) ((void) (0 && (E))) #if 1 /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA # if YYSTACK_USE_ALLOCA # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # elif defined __BUILTIN_VA_ARG_INCR # include /* INFRINGES ON USER NAME SPACE */ # elif defined _AIX # define YYSTACK_ALLOC __alloca # elif defined _MSC_VER # include /* INFRINGES ON USER NAME SPACE */ # define alloca _alloca # else # define YYSTACK_ALLOC alloca # if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS # include /* INFRINGES ON USER NAME SPACE */ /* Use EXIT_SUCCESS as a witness for stdlib.h. */ # ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 # endif # endif # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's 'empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely invoke alloca (N) if N exceeds 4096. Use a slightly smaller number to allow for a few compiler-allocated temporary stack slots. */ # define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ # endif # else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif # if (defined __cplusplus && ! defined EXIT_SUCCESS \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ # ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc # if ! defined malloc && ! defined EXIT_SUCCESS void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free # if ! defined free && ! defined EXIT_SUCCESS void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif # endif #endif /* 1 */ #if (! defined yyoverflow \ && (! defined __cplusplus \ || (defined PARI_LTYPE_IS_TRIVIAL && PARI_LTYPE_IS_TRIVIAL \ && defined PARI_STYPE_IS_TRIVIAL && PARI_STYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { yy_state_t 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 (YYSIZEOF (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE) \ + YYSIZEOF (YYLTYPE)) \ + 2 * YYSTACK_GAP_MAXIMUM) # define YYCOPY_NEEDED 1 /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack_alloc, Stack) \ do \ { \ YYPTRDIFF_T yynewbytes; \ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ Stack = &yyptr->Stack_alloc; \ yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / YYSIZEOF (*yyptr); \ } \ while (0) #endif #if defined YYCOPY_NEEDED && YYCOPY_NEEDED /* Copy COUNT objects from SRC to DST. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(Dst, Src, Count) \ __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src))) # else # define YYCOPY(Dst, Src, Count) \ do \ { \ YYPTRDIFF_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (Dst)[yyi] = (Src)[yyi]; \ } \ while (0) # endif # endif #endif /* !YYCOPY_NEEDED */ /* YYFINAL -- State number of the termination state. */ #define YYFINAL 48 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 719 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 62 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 24 /* YYNRULES -- Number of rules. */ #define YYNRULES 116 /* YYNSTATES -- Number of states. */ #define YYNSTATES 197 /* YYMAXUTOK -- Last valid token kind. */ #define YYMAXUTOK 291 /* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM as returned by yylex, with out-of-bounds checking. */ #define YYTRANSLATE(YYX) \ (0 <= (YYX) && (YYX) <= YYMAXUTOK \ ? YY_CAST (yysymbol_kind_t, yytranslate[YYX]) \ : YYSYMBOL_YYUNDEF) /* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM as returned by yylex. */ static const yytype_int8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 50, 2, 49, 2, 43, 38, 54, 56, 60, 46, 41, 36, 42, 55, 45, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 57, 35, 40, 37, 39, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 52, 44, 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, 61, 2, 51, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 47, 53 }; #if PARI_DEBUG /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { 0, 90, 90, 93, 94, 95, 96, 99, 100, 101, 102, 105, 106, 109, 110, 113, 114, 115, 116, 117, 118, 121, 122, 125, 126, 127, 128, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 186, 187, 188, 191, 192, 194, 195, 198, 199, 202, 203, 206, 207, 208, 209, 210, 213, 216, 217, 218, 219, 222, 225, 226, 227, 228, 229, 229, 233, 234, 237, 240, 243, 245, 247, 248 }; #endif /** Accessing symbol of state STATE. */ #define YY_ACCESSING_SYMBOL(State) YY_CAST (yysymbol_kind_t, yystos[State]) #if 1 /* The user-facing name of the symbol whose (internal) number is YYSYMBOL. No bounds checking. */ static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED; /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "\"end of file\"", "error", "\"invalid token\"", "\")->\"", "\"->\"", "\"..\"", "\"+=\"", "\"-=\"", "\"*=\"", "\"/=\"", "\"\\\\/=\"", "\"\\\\=\"", "\"%=\"", "\"&&\"", "\"||\"", "\"===\"", "\"==\"", "\"!=\"", "\">=\"", "\"<=\"", "\">>=\"", "\"<<=\"", "\">>\"", "\"<<\"", "\"\\\\/\"", "\"++\"", "\"--\"", "\"integer\"", "\"real number\"", "\"variable name\"", "\"character string\"", "SEQ", "DEFFUNC", "INT", "LVAL", "';'", "','", "'='", "'&'", "'>'", "'<'", "'+'", "'-'", "'%'", "'\\\\'", "'/'", "'*'", "SIGN", "'^'", "'#'", "'!'", "'~'", "'['", "DERIV", "'\\''", "'.'", "'('", "':'", "']'", "'`'", "')'", "'|'", "$accept", "sequence", "seq", "range", "matrix_index", "backticks", "history", "deriv", "expr", "lvalue", "exprno", "matrixeltsno", "matrixelts", "matrixlines", "matrix", "in", "inseq", "compr", "arg", "$@1", "listarg", "funcid", "memberid", "definition", YY_NULLPTR }; static const char * yysymbol_name (yysymbol_kind_t yysymbol) { return yytname[yysymbol]; } #endif #define YYPACT_NINF (-163) #define yypact_value_is_default(Yyn) \ ((Yyn) == YYPACT_NINF) #define YYTABLE_NINF (-111) #define yytable_value_is_error(Yyn) \ 0 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ static const yytype_int16 yypact[] = { 663, -14, -163, 14, -163, 663, 663, 44, 663, 663, 597, 45, -163, 629, 73, 50, -163, 472, 109, 49, -163, -163, -163, -163, 59, 629, 99, 99, -163, 13, -163, 33, 86, -33, 43, -163, 177, 69, -20, 40, -163, 78, 78, 50, 333, 233, 6, 7, -163, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, -163, -163, -163, 646, -163, 81, 629, 82, -163, 58, 663, 663, 663, 663, 663, 663, 663, 663, 663, 663, -163, -163, 663, 85, -163, 663, -163, -24, -163, 33, -163, -163, 663, 78, 663, 663, -163, 663, -163, -163, -32, -32, -163, 289, -163, 663, 629, 472, 515, 515, 551, 551, 551, 551, 551, 99, 99, 99, 515, 551, 551, 566, 566, 99, 99, 99, 99, 99, 663, -19, 258, 87, -23, -163, -163, 50, 472, 472, 472, 472, 472, 472, 472, 472, 472, 472, -163, 472, 88, 381, -26, -8, 64, 472, -163, 472, 91, 91, 65, 663, 50, 29, 472, 646, -163, 663, 663, -163, 663, -163, 89, 78, 663, -163, -163, 472, 70, 472, 50, 50, 663, -163, 427, -163, 472, 78, -163 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. Performed when YYTABLE does not specify something else to do. Zero means the default is an error. */ static const yytype_int8 yydefact[] = { 3, 23, 24, 81, 27, 0, 0, 15, 0, 0, 87, 0, 25, 3, 0, 2, 29, 4, 32, 33, 34, 31, 78, 35, 0, 3, 70, 71, 16, 18, 13, 17, 50, 49, 0, 92, 88, 0, 86, 0, 28, 0, 0, 103, 4, 32, 0, 0, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 75, 73, 7, 21, 0, 3, 0, 77, 74, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 39, 0, 0, 82, 0, 26, 0, 19, 20, 14, 94, 0, 0, 85, 87, 95, 87, 96, 81, 105, 106, 80, 7, 107, 3, 3, 6, 52, 51, 54, 55, 56, 57, 59, 64, 63, 66, 53, 58, 60, 62, 61, 65, 67, 68, 69, 72, 0, 0, 8, 112, 0, 79, 22, 115, 47, 48, 40, 41, 42, 43, 44, 46, 45, 37, 83, 36, 111, 0, 0, 98, 0, 84, 89, 88, 90, 91, 0, 0, 116, 0, 10, 7, 12, 0, 3, 30, 3, 93, 0, 0, 0, 102, 104, 108, 0, 9, 114, 113, 0, 100, 99, 11, 97, 0, 101 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { -163, -163, 11, -41, -16, 110, -163, -163, -5, -7, -163, -163, -1, -163, -163, -163, -162, -163, 36, -163, -9, -163, -163, -163 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_uint8 yydefgoto[] = { 0, 14, 43, 139, 78, 31, 16, 79, 17, 18, 164, 37, 38, 39, 19, 161, 162, 20, 46, 169, 47, 21, 22, 23 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule whose number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_int16 yytable[] = { 26, 27, 94, 32, 33, 36, 45, 114, 44, -109, 115, 15, 116, 116, 180, 105, 97, 173, 45, 191, 73, 74, 75, 76, 77, 93, 73, 181, 182, 94, 114, 93, -110, 196, 110, 111, 158, 177, 106, 174, 98, 24, -109, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, -110, -109, 142, 140, 45, 25, 28, 30, 48, 40, 107, 146, 147, 148, 149, 150, 151, 152, 153, 154, 49, 95, 155, 96, -110, 157, 145, 100, 29, 94, 94, 160, 159, 108, 163, 165, 101, 165, 30, 166, 104, 167, 109, 140, 45, 141, 143, 144, 80, 156, 81, 82, 83, 84, 85, 86, 87, 183, 184, 176, 178, 170, -86, 193, 88, 89, 190, 186, 172, 90, 91, 71, 72, 73, 99, 74, 75, 76, 77, 94, 0, 92, 69, 70, 71, 72, 73, 171, 74, 75, 76, 77, 0, 0, 0, 0, 73, 0, 0, 185, 0, 93, 0, 140, 0, 187, 0, 0, 0, 160, 0, 0, 192, 0, 0, 0, 0, 102, 0, 0, 194, 0, 188, 160, 189, 50, 51, 52, 53, 54, 55, 56, 0, 0, 57, 58, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 61, 62, 63, 64, 65, 66, 67, 68, 0, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 0, 0, 80, 103, 81, 82, 83, 84, 85, 86, 87, 0, 0, 0, 0, 0, 0, 0, 88, 89, 0, 0, 0, 90, 91, 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 92, 50, 51, 52, 53, 54, 55, 56, 0, 0, 57, 58, 59, 0, 0, 113, 0, 0, 0, 0, 93, 0, 0, 0, 168, 0, 60, 61, 62, 63, 64, 65, 66, 67, 68, 0, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 0, 0, 0, 0, 138, 8, 9, 0, 10, 0, 11, 12, 13, 50, 51, 52, 53, 54, 55, 56, 0, 0, 57, 58, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 61, 62, 63, 64, 65, 66, 67, 68, 0, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 0, 0, 112, 50, 51, 52, 53, 54, 55, 56, 0, 0, 57, 58, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 61, 62, 63, 64, 65, 66, 67, 68, 0, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 179, 50, 51, 52, 53, 54, 55, 56, 0, 0, 57, 58, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 0, 0, 60, 61, 62, 63, 64, 65, 66, 67, 68, 0, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 50, 51, 52, 53, 54, 55, 56, 0, 0, 57, 58, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 61, 62, 63, 64, 65, 66, 67, 68, 0, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 52, 53, 54, 55, 56, 0, 0, 57, 58, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 62, 63, 64, 65, 66, 67, 68, 0, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 57, 58, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 58, 59, 0, 63, 64, 65, 66, 67, 68, 0, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 65, 66, 67, 68, 0, 69, 70, 71, 72, 73, 0, 74, 75, 76, 77, 1, 2, 3, 4, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 5, 6, 7, 0, 0, 0, 0, 0, 8, 9, 0, 10, 0, 11, 12, 13, 0, 35, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 5, 6, 7, 1, 2, 3, 4, 0, 8, 9, 42, 10, 0, 11, 12, 13, 0, 5, 6, 7, 1, 2, 3, 4, 138, 8, 9, 0, 10, 0, 11, 12, 13, 0, 5, 6, 7, 0, 0, 0, 0, 0, 8, 9, 0, 10, 0, 11, 12, 13 }; static const yytype_int16 yycheck[] = { 5, 6, 18, 8, 9, 10, 13, 1, 13, 3, 3, 0, 36, 36, 40, 35, 25, 36, 25, 181, 52, 54, 55, 56, 57, 57, 52, 35, 36, 45, 1, 57, 3, 195, 41, 42, 60, 60, 58, 58, 27, 55, 36, 36, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 36, 60, 76, 73, 76, 56, 27, 59, 0, 29, 35, 81, 82, 83, 84, 85, 86, 87, 88, 89, 35, 37, 92, 29, 60, 95, 80, 59, 49, 110, 111, 103, 102, 58, 104, 105, 58, 107, 59, 105, 36, 107, 29, 113, 116, 29, 29, 54, 4, 29, 6, 7, 8, 9, 10, 11, 12, 58, 58, 37, 37, 115, 36, 58, 20, 21, 42, 173, 138, 25, 26, 50, 51, 52, 29, 54, 55, 56, 57, 160, -1, 37, 48, 49, 50, 51, 52, 116, 54, 55, 56, 57, -1, -1, -1, -1, 52, -1, -1, 169, -1, 57, -1, 173, -1, 175, -1, -1, -1, 181, -1, -1, 182, -1, -1, -1, -1, 5, -1, -1, 190, -1, 176, 195, 178, 13, 14, 15, 16, 17, 18, 19, -1, -1, 22, 23, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 38, 39, 40, 41, 42, 43, 44, 45, 46, -1, 48, 49, 50, 51, 52, -1, 54, 55, 56, 57, -1, -1, 4, 61, 6, 7, 8, 9, 10, 11, 12, -1, -1, -1, -1, -1, -1, -1, 20, 21, -1, -1, -1, 25, 26, -1, -1, -1, 5, -1, -1, -1, -1, -1, -1, 37, 13, 14, 15, 16, 17, 18, 19, -1, -1, 22, 23, 24, -1, -1, 52, -1, -1, -1, -1, 57, -1, -1, -1, 5, -1, 38, 39, 40, 41, 42, 43, 44, 45, 46, -1, 48, 49, 50, 51, 52, -1, 54, 55, 56, 57, 27, 28, 29, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 41, 42, 43, -1, -1, -1, -1, 48, 49, 50, -1, 52, -1, 54, 55, 56, 13, 14, 15, 16, 17, 18, 19, -1, -1, 22, 23, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 38, 39, 40, 41, 42, 43, 44, 45, 46, -1, 48, 49, 50, 51, 52, -1, 54, 55, 56, 57, -1, -1, 60, 13, 14, 15, 16, 17, 18, 19, -1, -1, 22, 23, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 38, 39, 40, 41, 42, 43, 44, 45, 46, -1, 48, 49, 50, 51, 52, -1, 54, 55, 56, 57, 58, 13, 14, 15, 16, 17, 18, 19, -1, -1, 22, 23, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 35, -1, -1, 38, 39, 40, 41, 42, 43, 44, 45, 46, -1, 48, 49, 50, 51, 52, -1, 54, 55, 56, 57, 13, 14, 15, 16, 17, 18, 19, -1, -1, 22, 23, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 38, 39, 40, 41, 42, 43, 44, 45, 46, -1, 48, 49, 50, 51, 52, -1, 54, 55, 56, 57, 15, 16, 17, 18, 19, -1, -1, 22, 23, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 39, 40, 41, 42, 43, 44, 45, 46, -1, 48, 49, 50, 51, 52, -1, 54, 55, 56, 57, 22, 23, 24, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, 23, 24, -1, 41, 42, 43, 44, 45, 46, -1, 48, 49, 50, 51, 52, -1, 54, 55, 56, 57, 43, 44, 45, 46, -1, 48, 49, 50, 51, 52, -1, 54, 55, 56, 57, 27, 28, 29, 30, -1, -1, -1, -1, 35, -1, -1, -1, -1, -1, 41, 42, 43, -1, -1, -1, -1, -1, 49, 50, -1, 52, -1, 54, 55, 56, -1, 58, 27, 28, 29, 30, -1, -1, -1, -1, -1, -1, -1, 38, -1, -1, 41, 42, 43, 27, 28, 29, 30, -1, 49, 50, 51, 52, -1, 54, 55, 56, -1, 41, 42, 43, 27, 28, 29, 30, 48, 49, 50, -1, 52, -1, 54, 55, 56, -1, 41, 42, 43, -1, -1, -1, -1, -1, 49, 50, -1, 52, -1, 54, 55, 56 }; /* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of state STATE-NUM. */ static const yytype_int8 yystos[] = { 0, 27, 28, 29, 30, 41, 42, 43, 49, 50, 52, 54, 55, 56, 63, 64, 68, 70, 71, 76, 79, 83, 84, 85, 55, 56, 70, 70, 27, 49, 59, 67, 70, 70, 35, 58, 70, 73, 74, 75, 29, 38, 51, 64, 70, 71, 80, 82, 0, 35, 13, 14, 15, 16, 17, 18, 19, 22, 23, 24, 38, 39, 40, 41, 42, 43, 44, 45, 46, 48, 49, 50, 51, 52, 54, 55, 56, 57, 66, 69, 4, 6, 7, 8, 9, 10, 11, 12, 20, 21, 25, 26, 37, 57, 66, 37, 29, 82, 27, 67, 59, 58, 5, 61, 36, 35, 58, 35, 58, 29, 71, 71, 60, 52, 1, 3, 36, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 48, 65, 70, 29, 82, 29, 54, 64, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 29, 70, 60, 70, 71, 77, 78, 70, 72, 70, 74, 74, 5, 81, 64, 80, 70, 36, 58, 5, 37, 60, 37, 58, 40, 35, 36, 58, 58, 70, 65, 70, 64, 64, 42, 78, 70, 58, 70, 35, 78 }; /* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */ static const yytype_int8 yyr1[] = { 0, 62, 63, 64, 64, 64, 64, 65, 65, 65, 65, 66, 66, 67, 67, 68, 68, 68, 68, 68, 68, 69, 69, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 71, 71, 71, 72, 72, 73, 73, 74, 74, 75, 75, 76, 76, 76, 76, 76, 77, 78, 78, 78, 78, 79, 80, 80, 80, 80, 81, 80, 82, 82, 83, 84, 85, 85, 85, 85 }; /* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */ static const yytype_int8 yyr2[] = { 0, 2, 1, 0, 1, 2, 3, 0, 1, 3, 2, 5, 3, 1, 2, 1, 2, 2, 2, 3, 3, 1, 2, 1, 1, 1, 3, 1, 2, 1, 4, 1, 1, 1, 1, 1, 3, 3, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 2, 2, 2, 2, 2, 1, 3, 3, 1, 2, 3, 1, 0, 1, 0, 1, 3, 3, 3, 2, 5, 3, 3, 3, 4, 1, 3, 3, 5, 5, 1, 4, 2, 2, 0, 4, 1, 3, 4, 3, 6, 5, 3, 4 }; enum { YYENOMEM = -2 }; #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = PARI_EMPTY) #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab #define YYNOMEM goto yyexhaustedlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == PARI_EMPTY) \ { \ yychar = (Token); \ yylval = (Value); \ YYPOPSTACK (yylen); \ yystate = *yyssp; \ goto yybackup; \ } \ else \ { \ yyerror (&yylloc, lex, YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (0) /* Backward compatibility with an undocumented macro. Use PARI_error or PARI_UNDEF. */ #define YYERRCODE PARI_UNDEF /* 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). */ #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ do \ if (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 (0) #endif #define YYRHSLOC(Rhs, K) ((Rhs)[K]) /* Enable debugging if requested. */ #if PARI_DEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (0) /* YYLOCATION_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 YYLOCATION_PRINT # if defined YY_LOCATION_PRINT /* Temporary convenience wrapper in case some people defined the undocumented and private YY_LOCATION_PRINT macros. */ # define YYLOCATION_PRINT(File, Loc) YY_LOCATION_PRINT(File, *(Loc)) # elif defined PARI_LTYPE_IS_TRIVIAL && PARI_LTYPE_IS_TRIVIAL /* Print *YYLOCP on YYO. Private, do not rely on its existence. */ YY_ATTRIBUTE_UNUSED static int yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp) { int res = 0; int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0; if (0 <= yylocp->first_line) { res += YYFPRINTF (yyo, "%d", yylocp->first_line); if (0 <= yylocp->first_column) res += YYFPRINTF (yyo, ".%d", yylocp->first_column); } if (0 <= yylocp->last_line) { if (yylocp->first_line < yylocp->last_line) { res += YYFPRINTF (yyo, "-%d", yylocp->last_line); if (0 <= end_col) res += YYFPRINTF (yyo, ".%d", end_col); } else if (0 <= end_col && yylocp->first_column < end_col) res += YYFPRINTF (yyo, "-%d", end_col); } return res; } # define YYLOCATION_PRINT yy_location_print_ /* Temporary convenience wrapper in case some people defined the undocumented and private YY_LOCATION_PRINT macros. */ # define YY_LOCATION_PRINT(File, Loc) YYLOCATION_PRINT(File, &(Loc)) # else # define YYLOCATION_PRINT(File, Loc) ((void) 0) /* Temporary convenience wrapper in case some people defined the undocumented and private YY_LOCATION_PRINT macros. */ # define YY_LOCATION_PRINT YYLOCATION_PRINT # endif # endif /* !defined YYLOCATION_PRINT */ # define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ Kind, Value, Location, lex); \ YYFPRINTF (stderr, "\n"); \ } \ } while (0) /*-----------------------------------. | Print this symbol's value on YYO. | `-----------------------------------*/ static void yy_symbol_value_print (FILE *yyo, yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, char **lex) { FILE *yyoutput = yyo; YY_USE (yyoutput); YY_USE (yylocationp); YY_USE (lex); if (!yyvaluep) return; YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN YY_USE (yykind); YY_IGNORE_MAYBE_UNINITIALIZED_END } /*---------------------------. | Print this symbol on YYO. | `---------------------------*/ static void yy_symbol_print (FILE *yyo, yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, char **lex) { YYFPRINTF (yyo, "%s %s (", yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind)); YYLOCATION_PRINT (yyo, yylocationp); YYFPRINTF (yyo, ": "); yy_symbol_value_print (yyo, yykind, yyvaluep, yylocationp, lex); YYFPRINTF (yyo, ")"); } /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ static void yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop) { 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 (0) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ static void yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, char **lex) { int yylno = yyrline[yyrule]; int yynrhs = yyr2[yyrule]; int yyi; YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]), &yyvsp[(yyi + 1) - (yynrhs)], &(yylsp[(yyi + 1) - (yynrhs)]), lex); YYFPRINTF (stderr, "\n"); } } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ yy_reduce_print (yyssp, yyvsp, yylsp, Rule, lex); \ } while (0) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !PARI_DEBUG */ # define YYDPRINTF(Args) ((void) 0) # define YY_SYMBOL_PRINT(Title, Kind, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !PARI_DEBUG */ /* 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 /* Context of a parse error. */ typedef struct { yy_state_t *yyssp; yysymbol_kind_t yytoken; YYLTYPE *yylloc; } yypcontext_t; /* Put in YYARG at most YYARGN of the expected tokens given the current YYCTX, and return the number of tokens stored in YYARG. If YYARG is null, return the number of expected tokens (guaranteed to be less than YYNTOKENS). Return YYENOMEM on memory exhaustion. Return 0 if there are more than YYARGN expected tokens, yet fill YYARG up to YYARGN. */ static int yypcontext_expected_tokens (const yypcontext_t *yyctx, yysymbol_kind_t yyarg[], int yyargn) { /* Actual size of YYARG. */ int yycount = 0; int yyn = yypact[+*yyctx->yyssp]; if (!yypact_value_is_default (yyn)) { /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. In other words, skip the first -YYN actions for this state because they are default actions. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn + 1; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yyx; for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYSYMBOL_YYerror && !yytable_value_is_error (yytable[yyx + yyn])) { if (!yyarg) ++yycount; else if (yycount == yyargn) return 0; else yyarg[yycount++] = YY_CAST (yysymbol_kind_t, yyx); } } if (yyarg && yycount == 0 && 0 < yyargn) yyarg[0] = YYSYMBOL_YYEMPTY; return yycount; } #ifndef yystrlen # if defined __GLIBC__ && defined _STRING_H # define yystrlen(S) (YY_CAST (YYPTRDIFF_T, strlen (S))) # else /* Return the length of YYSTR. */ static YYPTRDIFF_T yystrlen (const char *yystr) { YYPTRDIFF_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. */ static char * yystpcpy (char *yydest, const char *yysrc) { 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 YYPTRDIFF_T yytnamerr (char *yyres, const char *yystr) { if (*yystr == '"') { YYPTRDIFF_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; else goto append; append: default: if (yyres) yyres[yyn] = *yyp; yyn++; break; case '"': if (yyres) yyres[yyn] = '\0'; return yyn; } do_not_strip_quotes: ; } if (yyres) return yystpcpy (yyres, yystr) - yyres; else return yystrlen (yystr); } #endif static int yy_syntax_error_arguments (const yypcontext_t *yyctx, yysymbol_kind_t yyarg[], int yyargn) { /* Actual size of YYARG. */ int yycount = 0; /* There are many possibilities here to consider: - If this state is a consistent state with a default action, then the only way this function was invoked is if the default action is an error action. In that case, don't check for expected tokens because there are none. - The only way there can be no lookahead present (in yychar) is if this state is a consistent state with a default action. Thus, detecting the absence of a lookahead is sufficient to determine that there is no unexpected or expected token to report. In that case, just report a simple "syntax error". - Don't assume there isn't a lookahead just because this state is a consistent state with a default action. There might have been a previous inconsistent state, consistent state with a non-default action, or user semantic action that manipulated yychar. - Of course, the expected token list depends on states to have correct lookahead information, and it depends on the parser not to perform extra reductions after fetching a lookahead from the scanner and before detecting a syntax error. Thus, state merging (from LALR or IELR) and default reductions corrupt the expected token list. However, the list is correct for canonical LR with one exception: it will still contain any token that will not be accepted due to an error action in a later state. */ if (yyctx->yytoken != YYSYMBOL_YYEMPTY) { int yyn; if (yyarg) yyarg[yycount] = yyctx->yytoken; ++yycount; yyn = yypcontext_expected_tokens (yyctx, yyarg ? yyarg + 1 : yyarg, yyargn - 1); if (yyn == YYENOMEM) return YYENOMEM; else yycount += yyn; } return yycount; } /* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message about the unexpected token YYTOKEN for the state stack whose top is YYSSP. Return 0 if *YYMSG was successfully written. Return -1 if *YYMSG is not large enough to hold the message. In that case, also set *YYMSG_ALLOC to the required number of bytes. Return YYENOMEM if the required number of bytes is too large to store. */ static int yysyntax_error (YYPTRDIFF_T *yymsg_alloc, char **yymsg, const yypcontext_t *yyctx) { enum { YYARGS_MAX = 5 }; /* Internationalized format string. */ const char *yyformat = YY_NULLPTR; /* Arguments of yyformat: reported tokens (one for the "unexpected", one per "expected"). */ yysymbol_kind_t yyarg[YYARGS_MAX]; /* Cumulated lengths of YYARG. */ YYPTRDIFF_T yysize = 0; /* Actual size of YYARG. */ int yycount = yy_syntax_error_arguments (yyctx, yyarg, YYARGS_MAX); if (yycount == YYENOMEM) return YYENOMEM; switch (yycount) { #define YYCASE_(N, S) \ case N: \ yyformat = S; \ break default: /* Avoid compiler warnings. */ YYCASE_(0, YY_("syntax error")); YYCASE_(1, YY_("syntax error, unexpected %s")); YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); #undef YYCASE_ } /* Compute error message size. Don't count the "%s"s, but reserve room for the terminator. */ yysize = yystrlen (yyformat) - 2 * yycount + 1; { int yyi; for (yyi = 0; yyi < yycount; ++yyi) { YYPTRDIFF_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyarg[yyi]]); if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) yysize = yysize1; else return YYENOMEM; } } if (*yymsg_alloc < yysize) { *yymsg_alloc = 2 * yysize; if (! (yysize <= *yymsg_alloc && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; return -1; } /* Avoid sprintf, as that infringes on the user's name space. Don't have undefined behavior even if the translation produced a string with the wrong number of "%s"s. */ { char *yyp = *yymsg; int yyi = 0; while ((*yyp = *yyformat) != '\0') if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) { yyp += yytnamerr (yyp, yytname[yyarg[yyi++]]); yyformat += 2; } else { ++yyp; ++yyformat; } } return 0; } /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ static void yydestruct (const char *yymsg, yysymbol_kind_t yykind, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, char **lex) { YY_USE (yyvaluep); YY_USE (yylocationp); YY_USE (lex); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN switch (yykind) { case YYSYMBOL_seq: /* seq */ #line 87 "../src/language/parse.y" { pari_discarded++; } #line 1516 "../src/language/parse.c" break; case YYSYMBOL_range: /* range */ #line 87 "../src/language/parse.y" { pari_discarded++; } #line 1522 "../src/language/parse.c" break; case YYSYMBOL_matrix_index: /* matrix_index */ #line 87 "../src/language/parse.y" { pari_discarded++; } #line 1528 "../src/language/parse.c" break; case YYSYMBOL_backticks: /* backticks */ #line 87 "../src/language/parse.y" { pari_discarded++; } #line 1534 "../src/language/parse.c" break; case YYSYMBOL_history: /* history */ #line 87 "../src/language/parse.y" { pari_discarded++; } #line 1540 "../src/language/parse.c" break; case YYSYMBOL_deriv: /* deriv */ #line 87 "../src/language/parse.y" { pari_discarded++; } #line 1546 "../src/language/parse.c" break; case YYSYMBOL_expr: /* expr */ #line 87 "../src/language/parse.y" { pari_discarded++; } #line 1552 "../src/language/parse.c" break; case YYSYMBOL_lvalue: /* lvalue */ #line 87 "../src/language/parse.y" { pari_discarded++; } #line 1558 "../src/language/parse.c" break; case YYSYMBOL_exprno: /* exprno */ #line 87 "../src/language/parse.y" { pari_discarded++; } #line 1564 "../src/language/parse.c" break; case YYSYMBOL_matrixeltsno: /* matrixeltsno */ #line 87 "../src/language/parse.y" { pari_discarded++; } #line 1570 "../src/language/parse.c" break; case YYSYMBOL_matrixelts: /* matrixelts */ #line 87 "../src/language/parse.y" { pari_discarded++; } #line 1576 "../src/language/parse.c" break; case YYSYMBOL_matrixlines: /* matrixlines */ #line 87 "../src/language/parse.y" { pari_discarded++; } #line 1582 "../src/language/parse.c" break; case YYSYMBOL_matrix: /* matrix */ #line 87 "../src/language/parse.y" { pari_discarded++; } #line 1588 "../src/language/parse.c" break; case YYSYMBOL_in: /* in */ #line 87 "../src/language/parse.y" { pari_discarded++; } #line 1594 "../src/language/parse.c" break; case YYSYMBOL_inseq: /* inseq */ #line 87 "../src/language/parse.y" { pari_discarded++; } #line 1600 "../src/language/parse.c" break; case YYSYMBOL_compr: /* compr */ #line 87 "../src/language/parse.y" { pari_discarded++; } #line 1606 "../src/language/parse.c" break; case YYSYMBOL_arg: /* arg */ #line 87 "../src/language/parse.y" { pari_discarded++; } #line 1612 "../src/language/parse.c" break; case YYSYMBOL_listarg: /* listarg */ #line 87 "../src/language/parse.y" { pari_discarded++; } #line 1618 "../src/language/parse.c" break; case YYSYMBOL_funcid: /* funcid */ #line 87 "../src/language/parse.y" { pari_discarded++; } #line 1624 "../src/language/parse.c" break; case YYSYMBOL_memberid: /* memberid */ #line 87 "../src/language/parse.y" { pari_discarded++; } #line 1630 "../src/language/parse.c" break; case YYSYMBOL_definition: /* definition */ #line 87 "../src/language/parse.y" { pari_discarded++; } #line 1636 "../src/language/parse.c" break; default: break; } YY_IGNORE_MAYBE_UNINITIALIZED_END } /*----------. | yyparse. | `----------*/ int yyparse (char **lex) { /* Lookahead token kind. */ int yychar; /* The semantic value of the lookahead symbol. */ /* Default value used for initialization, for pacifying older GCCs or non-GCC compilers. */ YY_INITIAL_VALUE (static YYSTYPE yyval_default;) YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); /* Location data for the lookahead symbol. */ static YYLTYPE yyloc_default # if defined PARI_LTYPE_IS_TRIVIAL && PARI_LTYPE_IS_TRIVIAL = { 1, 1, 1, 1 } # endif ; YYLTYPE yylloc = yyloc_default; /* Number of syntax errors so far. */ int yynerrs = 0; yy_state_fast_t yystate = 0; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus = 0; /* Refer to the stacks through separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* Their size. */ YYPTRDIFF_T yystacksize = YYINITDEPTH; /* The state stack: array, bottom, top. */ yy_state_t yyssa[YYINITDEPTH]; yy_state_t *yyss = yyssa; yy_state_t *yyssp = yyss; /* The semantic value stack: array, bottom, top. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs = yyvsa; YYSTYPE *yyvsp = yyvs; /* The location stack: array, bottom, top. */ YYLTYPE yylsa[YYINITDEPTH]; YYLTYPE *yyls = yylsa; YYLTYPE *yylsp = yyls; int yyn; /* The return value of yyparse. */ int yyresult; /* Lookahead symbol kind. */ yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; YYLTYPE yyloc; /* The locations where the error started and ended. */ YYLTYPE yyerror_range[3]; /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; char *yymsg = yymsgbuf; YYPTRDIFF_T yymsg_alloc = sizeof yymsgbuf; #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; YYDPRINTF ((stderr, "Starting parse\n")); yychar = PARI_EMPTY; /* Cause a token to be read. */ /* User initialization code. */ #line 33 "../src/language/parse.y" { yylloc.start=yylloc.end=*lex; } #line 1736 "../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 -- set current state (the top of the stack) to yystate. | `--------------------------------------------------------------------*/ yysetstate: YYDPRINTF ((stderr, "Entering state %d\n", yystate)); YY_ASSERT (0 <= yystate && yystate < YYNSTATES); YY_IGNORE_USELESS_CAST_BEGIN *yyssp = YY_CAST (yy_state_t, yystate); YY_IGNORE_USELESS_CAST_END YY_STACK_PRINT (yyss, yyssp); if (yyss + yystacksize - 1 <= yyssp) #if !defined yyoverflow && !defined YYSTACK_RELOCATE YYNOMEM; #else { /* Get the current used size of the three stacks, in elements. */ YYPTRDIFF_T yysize = yyssp - yyss + 1; # if defined 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. */ yy_state_t *yyss1 = yyss; YYSTYPE *yyvs1 = yyvs; 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 * YYSIZEOF (*yyssp), &yyvs1, yysize * YYSIZEOF (*yyvsp), &yyls1, yysize * YYSIZEOF (*yylsp), &yystacksize); yyss = yyss1; yyvs = yyvs1; yyls = yyls1; } # else /* defined YYSTACK_RELOCATE */ /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) YYNOMEM; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { yy_state_t *yyss1 = yyss; union yyalloc *yyptr = YY_CAST (union yyalloc *, YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize)))); if (! yyptr) YYNOMEM; 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 yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; yylsp = yyls + yysize - 1; YY_IGNORE_USELESS_CAST_BEGIN YYDPRINTF ((stderr, "Stack size increased to %ld\n", YY_CAST (long, yystacksize))); YY_IGNORE_USELESS_CAST_END if (yyss + yystacksize - 1 <= yyssp) YYABORT; } #endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ if (yystate == YYFINAL) YYACCEPT; goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. Read a lookahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yypact_value_is_default (yyn)) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ /* YYCHAR is either empty, or end-of-input, or a valid lookahead. */ if (yychar == PARI_EMPTY) { YYDPRINTF ((stderr, "Reading a token\n")); yychar = yylex (&yylval, &yylloc, lex); } if (yychar <= PARI_EOF) { yychar = PARI_EOF; yytoken = YYSYMBOL_YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } else if (yychar == PARI_error) { /* The scanner already issued an error message, process directly to error recovery. But do not keep the error token as lookahead, it is too special and may lead us to an endless loop in error recovery. */ yychar = PARI_UNDEF; yytoken = YYSYMBOL_YYerror; yyerror_range[1] = yylloc; goto yyerrlab1; } else { yytoken = YYTRANSLATE (yychar); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; yyn = yytable[yyn]; if (yyn <= 0) { if (yytable_value_is_error (yyn)) goto yyerrlab; yyn = -yyn; goto yyreduce; } /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; /* Shift the lookahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); yystate = yyn; YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; YY_IGNORE_MAYBE_UNINITIALIZED_END *++yylsp = yylloc; /* Discard the shifted token. */ yychar = PARI_EMPTY; 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); yyerror_range[1] = yyloc; YY_REDUCE_PRINT (yyn); switch (yyn) { case 2: /* sequence: seq */ #line 90 "../src/language/parse.y" {(yyval.val)=(yyvsp[0].val); (void) pari_nerrs;} #line 1949 "../src/language/parse.c" break; case 3: /* seq: %empty */ #line 93 "../src/language/parse.y" {(yyval.val)=NOARG((yyloc));} #line 1955 "../src/language/parse.c" break; case 4: /* seq: expr */ #line 94 "../src/language/parse.y" {(yyval.val)=(yyvsp[0].val);} #line 1961 "../src/language/parse.c" break; case 5: /* seq: seq ';' */ #line 95 "../src/language/parse.y" {(yyval.val)=(yyvsp[-1].val); (yyloc)=(yylsp[-1]);} #line 1967 "../src/language/parse.c" break; case 6: /* seq: seq ';' expr */ #line 96 "../src/language/parse.y" {(yyval.val)=newnode(Fseq,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 1973 "../src/language/parse.c" break; case 7: /* range: %empty */ #line 99 "../src/language/parse.y" { (yyval.val)=newnode(Frange,NORANGE((yyloc)),NORANGE((yyloc)),&(yyloc)); } #line 1979 "../src/language/parse.c" break; case 8: /* range: expr */ #line 100 "../src/language/parse.y" { (yyval.val)=newnode(Frange,(yyvsp[0].val),NORANGE((yyloc)),&(yyloc)); } #line 1985 "../src/language/parse.c" break; case 9: /* range: expr ".." expr */ #line 101 "../src/language/parse.y" { (yyval.val)=newnode(Frange,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc)); } #line 1991 "../src/language/parse.c" break; case 10: /* range: '^' expr */ #line 102 "../src/language/parse.y" { (yyval.val)=newnode(Frange,NORANGE((yyloc)),(yyvsp[0].val),&(yyloc)); } #line 1997 "../src/language/parse.c" break; case 11: /* matrix_index: '[' range ',' range ']' */ #line 105 "../src/language/parse.y" {(yyval.val)=newnode(Fmatrix,(yyvsp[-3].val),(yyvsp[-1].val),&(yyloc));} #line 2003 "../src/language/parse.c" break; case 12: /* matrix_index: '[' range ']' */ #line 106 "../src/language/parse.y" {(yyval.val)=newnode(Fmatrix,(yyvsp[-1].val),-1,&(yyloc));} #line 2009 "../src/language/parse.c" break; case 13: /* backticks: '`' */ #line 109 "../src/language/parse.y" {(yyval.val)=1;} #line 2015 "../src/language/parse.c" break; case 14: /* backticks: backticks '`' */ #line 110 "../src/language/parse.y" {(yyval.val)=(yyvsp[-1].val)+1;} #line 2021 "../src/language/parse.c" break; case 15: /* history: '%' */ #line 113 "../src/language/parse.y" {(yyval.val)=newopcall(OPhist,-1,-1,&(yyloc));} #line 2027 "../src/language/parse.c" break; case 16: /* history: '%' "integer" */ #line 114 "../src/language/parse.y" {(yyval.val)=newopcall(OPhist,newintnode(&(yylsp[0])),-1,&(yyloc));} #line 2033 "../src/language/parse.c" break; case 17: /* history: '%' backticks */ #line 115 "../src/language/parse.y" {(yyval.val)=newopcall(OPhist,newnode(Fsmall,-(yyvsp[0].val),-1,&(yyloc)),-1,&(yyloc));} #line 2039 "../src/language/parse.c" break; case 18: /* history: '%' '#' */ #line 116 "../src/language/parse.y" {(yyval.val)=newopcall(OPhisttime,-1,-1,&(yyloc));} #line 2045 "../src/language/parse.c" break; case 19: /* history: '%' '#' "integer" */ #line 117 "../src/language/parse.y" {(yyval.val)=newopcall(OPhisttime,newintnode(&(yylsp[0])),-1,&(yyloc));} #line 2051 "../src/language/parse.c" break; case 20: /* history: '%' '#' backticks */ #line 118 "../src/language/parse.y" {(yyval.val)=newopcall(OPhisttime,newnode(Fsmall,-(yyvsp[0].val),-1,&(yyloc)),-1,&(yyloc));} #line 2057 "../src/language/parse.c" break; case 21: /* deriv: '\'' */ #line 121 "../src/language/parse.y" {(yyval.val) = 1;} #line 2063 "../src/language/parse.c" break; case 22: /* deriv: deriv '\'' */ #line 122 "../src/language/parse.y" {(yyval.val) = (yyvsp[-1].val)+1;} #line 2069 "../src/language/parse.c" break; case 23: /* expr: "integer" */ #line 125 "../src/language/parse.y" {(yyval.val)=newintnode(&(yylsp[0]));} #line 2075 "../src/language/parse.c" break; case 24: /* expr: "real number" */ #line 126 "../src/language/parse.y" {(yyval.val)=newconst(CSTreal,&(yyloc));} #line 2081 "../src/language/parse.c" break; case 25: /* expr: '.' */ #line 127 "../src/language/parse.y" {(yyval.val)=newconst(CSTreal,&(yyloc));} #line 2087 "../src/language/parse.c" break; case 26: /* expr: "integer" '.' "variable name" */ #line 128 "../src/language/parse.y" {(yyval.val)=newnode(Ffunction,newconst(CSTmember,&(yylsp[0])), newintnode(&(yylsp[-2])),&(yyloc));} #line 2094 "../src/language/parse.c" break; case 27: /* expr: "character string" */ #line 130 "../src/language/parse.y" {(yyval.val)=newconst(CSTstr,&(yyloc));} #line 2100 "../src/language/parse.c" break; case 28: /* expr: '\'' "variable name" */ #line 131 "../src/language/parse.y" {(yyval.val)=newconst(CSTquote,&(yyloc));} #line 2106 "../src/language/parse.c" break; case 29: /* expr: history */ #line 132 "../src/language/parse.y" {(yyval.val)=(yyvsp[0].val);} #line 2112 "../src/language/parse.c" break; case 30: /* expr: expr '(' listarg ')' */ #line 133 "../src/language/parse.y" {(yyval.val)=newnode(Fcall,(yyvsp[-3].val),(yyvsp[-1].val),&(yyloc));} #line 2118 "../src/language/parse.c" break; case 31: /* expr: funcid */ #line 134 "../src/language/parse.y" {(yyval.val)=(yyvsp[0].val);} #line 2124 "../src/language/parse.c" break; case 32: /* expr: lvalue */ #line 135 "../src/language/parse.y" {(yyval.val)=(yyvsp[0].val);} #line 2130 "../src/language/parse.c" break; case 33: /* expr: matrix */ #line 136 "../src/language/parse.y" {(yyval.val)=(yyvsp[0].val);} #line 2136 "../src/language/parse.c" break; case 34: /* expr: compr */ #line 137 "../src/language/parse.y" {(yyval.val)=(yyvsp[0].val);} #line 2142 "../src/language/parse.c" break; case 35: /* expr: definition */ #line 138 "../src/language/parse.y" {(yyval.val)=(yyvsp[0].val);} #line 2148 "../src/language/parse.c" break; case 36: /* expr: matrix '=' expr */ #line 139 "../src/language/parse.y" {(yyval.val)=newnode(Fassign,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2154 "../src/language/parse.c" break; case 37: /* expr: lvalue '=' expr */ #line 140 "../src/language/parse.y" {(yyval.val)=newnode(Fassign,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2160 "../src/language/parse.c" break; case 38: /* expr: lvalue "++" */ #line 141 "../src/language/parse.y" {(yyval.val)=newopcall(OPpp,(yyvsp[-1].val),-1,&(yyloc));} #line 2166 "../src/language/parse.c" break; case 39: /* expr: lvalue "--" */ #line 142 "../src/language/parse.y" {(yyval.val)=newopcall(OPss,(yyvsp[-1].val),-1,&(yyloc));} #line 2172 "../src/language/parse.c" break; case 40: /* expr: lvalue "*=" expr */ #line 143 "../src/language/parse.y" {(yyval.val)=newopcall(OPme,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2178 "../src/language/parse.c" break; case 41: /* expr: lvalue "/=" expr */ #line 144 "../src/language/parse.y" {(yyval.val)=newopcall(OPde,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2184 "../src/language/parse.c" break; case 42: /* expr: lvalue "\\/=" expr */ #line 145 "../src/language/parse.y" {(yyval.val)=newopcall(OPdre,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2190 "../src/language/parse.c" break; case 43: /* expr: lvalue "\\=" expr */ #line 146 "../src/language/parse.y" {(yyval.val)=newopcall(OPeuce,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2196 "../src/language/parse.c" break; case 44: /* expr: lvalue "%=" expr */ #line 147 "../src/language/parse.y" {(yyval.val)=newopcall(OPmode,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2202 "../src/language/parse.c" break; case 45: /* expr: lvalue "<<=" expr */ #line 148 "../src/language/parse.y" {(yyval.val)=newopcall(OPsle,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2208 "../src/language/parse.c" break; case 46: /* expr: lvalue ">>=" expr */ #line 149 "../src/language/parse.y" {(yyval.val)=newopcall(OPsre,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2214 "../src/language/parse.c" break; case 47: /* expr: lvalue "+=" expr */ #line 150 "../src/language/parse.y" {(yyval.val)=newopcall(OPpe,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2220 "../src/language/parse.c" break; case 48: /* expr: lvalue "-=" expr */ #line 151 "../src/language/parse.y" {(yyval.val)=newopcall(OPse,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2226 "../src/language/parse.c" break; case 49: /* expr: '!' expr */ #line 152 "../src/language/parse.y" {(yyval.val)=newopcall(OPnb,(yyvsp[0].val),-1,&(yyloc));} #line 2232 "../src/language/parse.c" break; case 50: /* expr: '#' expr */ #line 153 "../src/language/parse.y" {(yyval.val)=newopcall(OPlength,(yyvsp[0].val),-1,&(yyloc));} #line 2238 "../src/language/parse.c" break; case 51: /* expr: expr "||" expr */ #line 154 "../src/language/parse.y" {(yyval.val)=newopcall(OPor,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2244 "../src/language/parse.c" break; case 52: /* expr: expr "&&" expr */ #line 155 "../src/language/parse.y" {(yyval.val)=newopcall(OPand,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2250 "../src/language/parse.c" break; case 53: /* expr: expr '&' expr */ #line 156 "../src/language/parse.y" {(yyval.val)=newopcall(OPand,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2256 "../src/language/parse.c" break; case 54: /* expr: expr "===" expr */ #line 157 "../src/language/parse.y" {(yyval.val)=newopcall(OPid,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2262 "../src/language/parse.c" break; case 55: /* expr: expr "==" expr */ #line 158 "../src/language/parse.y" {(yyval.val)=newopcall(OPeq,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2268 "../src/language/parse.c" break; case 56: /* expr: expr "!=" expr */ #line 159 "../src/language/parse.y" {(yyval.val)=newopcall(OPne,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2274 "../src/language/parse.c" break; case 57: /* expr: expr ">=" expr */ #line 160 "../src/language/parse.y" {(yyval.val)=newopcall(OPge,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2280 "../src/language/parse.c" break; case 58: /* expr: expr '>' expr */ #line 161 "../src/language/parse.y" {(yyval.val)=newopcall(OPg,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2286 "../src/language/parse.c" break; case 59: /* expr: expr "<=" expr */ #line 162 "../src/language/parse.y" {(yyval.val)=newopcall(OPle,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2292 "../src/language/parse.c" break; case 60: /* expr: expr '<' expr */ #line 163 "../src/language/parse.y" {(yyval.val)=newopcall(OPl,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2298 "../src/language/parse.c" break; case 61: /* expr: expr '-' expr */ #line 164 "../src/language/parse.y" {(yyval.val)=newopcall(OPs,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2304 "../src/language/parse.c" break; case 62: /* expr: expr '+' expr */ #line 165 "../src/language/parse.y" {(yyval.val)=newopcall(OPp,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2310 "../src/language/parse.c" break; case 63: /* expr: expr "<<" expr */ #line 166 "../src/language/parse.y" {(yyval.val)=newopcall(OPsl,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2316 "../src/language/parse.c" break; case 64: /* expr: expr ">>" expr */ #line 167 "../src/language/parse.y" {(yyval.val)=newopcall(OPsr,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2322 "../src/language/parse.c" break; case 65: /* expr: expr '%' expr */ #line 168 "../src/language/parse.y" {(yyval.val)=newopcall(OPmod,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2328 "../src/language/parse.c" break; case 66: /* expr: expr "\\/" expr */ #line 169 "../src/language/parse.y" {(yyval.val)=newopcall(OPdr,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2334 "../src/language/parse.c" break; case 67: /* expr: expr '\\' expr */ #line 170 "../src/language/parse.y" {(yyval.val)=newopcall(OPeuc,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2340 "../src/language/parse.c" break; case 68: /* expr: expr '/' expr */ #line 171 "../src/language/parse.y" {(yyval.val)=newopcall(OPd,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2346 "../src/language/parse.c" break; case 69: /* expr: expr '*' expr */ #line 172 "../src/language/parse.y" {(yyval.val)=newopcall(OPm,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2352 "../src/language/parse.c" break; case 70: /* expr: '+' expr */ #line 173 "../src/language/parse.y" {(yyval.val)=(yyvsp[0].val);} #line 2358 "../src/language/parse.c" break; case 71: /* expr: '-' expr */ #line 174 "../src/language/parse.y" {(yyval.val)=newopcall(OPn,(yyvsp[0].val),-1,&(yyloc));} #line 2364 "../src/language/parse.c" break; case 72: /* expr: expr '^' expr */ #line 175 "../src/language/parse.y" {(yyval.val)=newopcall(OPpow,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2370 "../src/language/parse.c" break; case 73: /* expr: expr '~' */ #line 176 "../src/language/parse.y" {(yyval.val)=newopcall(OPtrans,(yyvsp[-1].val),-1,&(yyloc));} #line 2376 "../src/language/parse.c" break; case 74: /* expr: expr deriv */ #line 177 "../src/language/parse.y" {(yyval.val)=newopcall(OPderivn,(yyvsp[-1].val), newnode(Fsmall,(yyvsp[0].val),-1,&(yyloc)),&(yyloc));} #line 2382 "../src/language/parse.c" break; case 75: /* expr: expr '!' */ #line 178 "../src/language/parse.y" {(yyval.val)=newopcall(OPfact,(yyvsp[-1].val),-1,&(yyloc));} #line 2388 "../src/language/parse.c" break; case 76: /* expr: expr '#' */ #line 179 "../src/language/parse.y" {(yyval.val)=newopcall(OPprim,(yyvsp[-1].val),-1,&(yyloc));} #line 2394 "../src/language/parse.c" break; case 77: /* expr: expr matrix_index */ #line 180 "../src/language/parse.y" {(yyval.val)=newnode(Fmatcoeff,(yyvsp[-1].val),(yyvsp[0].val),&(yyloc));} #line 2400 "../src/language/parse.c" break; case 78: /* expr: memberid */ #line 181 "../src/language/parse.y" {(yyval.val)=(yyvsp[0].val);} #line 2406 "../src/language/parse.c" break; case 79: /* expr: expr ':' "variable name" */ #line 182 "../src/language/parse.y" {(yyval.val)=newnode(Ftag,(yyvsp[-2].val),0,&(yyloc));} #line 2412 "../src/language/parse.c" break; case 80: /* expr: '(' expr ')' */ #line 183 "../src/language/parse.y" {(yyval.val)=(yyvsp[-1].val);} #line 2418 "../src/language/parse.c" break; case 81: /* lvalue: "variable name" */ #line 186 "../src/language/parse.y" {(yyval.val)=newnode(Fentry,newconst(CSTentry,&(yylsp[0])),-1,&(yyloc));} #line 2424 "../src/language/parse.c" break; case 82: /* lvalue: lvalue matrix_index */ #line 187 "../src/language/parse.y" {(yyval.val)=newnode(Fmatcoeff,(yyvsp[-1].val),(yyvsp[0].val),&(yyloc));} #line 2430 "../src/language/parse.c" break; case 83: /* lvalue: lvalue ':' "variable name" */ #line 188 "../src/language/parse.y" {(yyval.val)=newnode(Ftag,(yyvsp[-2].val),newconst(CSTentry,&(yylsp[-1])),&(yyloc));} #line 2436 "../src/language/parse.c" break; case 84: /* exprno: expr */ #line 191 "../src/language/parse.y" {(yyval.val)=(yyvsp[0].val);} #line 2442 "../src/language/parse.c" break; case 85: /* exprno: %empty */ #line 192 "../src/language/parse.y" {(yyval.val)=NOARG((yyloc));} #line 2448 "../src/language/parse.c" break; case 86: /* matrixeltsno: matrixelts */ #line 194 "../src/language/parse.y" {(yyval.val)=(yyvsp[0].val);} #line 2454 "../src/language/parse.c" break; case 87: /* matrixeltsno: %empty */ #line 195 "../src/language/parse.y" {(yyval.val)=NOARG((yyloc));} #line 2460 "../src/language/parse.c" break; case 88: /* matrixelts: expr */ #line 198 "../src/language/parse.y" {(yyval.val)=(yyvsp[0].val);} #line 2466 "../src/language/parse.c" break; case 89: /* matrixelts: matrixeltsno ',' exprno */ #line 199 "../src/language/parse.y" {(yyval.val)=newnode(Fmatrixelts,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2472 "../src/language/parse.c" break; case 90: /* matrixlines: matrixelts ';' matrixelts */ #line 202 "../src/language/parse.y" {(yyval.val)=newnode(Fmatrixlines,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2478 "../src/language/parse.c" break; case 91: /* matrixlines: matrixlines ';' matrixelts */ #line 203 "../src/language/parse.y" {(yyval.val)=newnode(Fmatrixlines,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2484 "../src/language/parse.c" break; case 92: /* matrix: '[' ']' */ #line 206 "../src/language/parse.y" {(yyval.val)=newnode(Fvec,-1,-1,&(yyloc));} #line 2490 "../src/language/parse.c" break; case 93: /* matrix: '[' expr ".." expr ']' */ #line 207 "../src/language/parse.y" {(yyval.val)=newopcall(OPrange,(yyvsp[-3].val),(yyvsp[-1].val),&(yyloc));} #line 2496 "../src/language/parse.c" break; case 94: /* matrix: '[' ';' ']' */ #line 208 "../src/language/parse.y" {(yyval.val)=newnode(Fmat,-1,-1,&(yyloc));} #line 2502 "../src/language/parse.c" break; case 95: /* matrix: '[' matrixelts ']' */ #line 209 "../src/language/parse.y" {(yyval.val)=newnode(Fvec,(yyvsp[-1].val),-1,&(yyloc));} #line 2508 "../src/language/parse.c" break; case 96: /* matrix: '[' matrixlines ']' */ #line 210 "../src/language/parse.y" {(yyval.val)=newnode(Fmat,(yyvsp[-1].val),-1,&(yyloc));} #line 2514 "../src/language/parse.c" break; case 97: /* in: lvalue '<' '-' expr */ #line 213 "../src/language/parse.y" {(yyval.val)=newnode(Flistarg,(yyvsp[0].val),(yyvsp[-3].val),&(yyloc));} #line 2520 "../src/language/parse.c" break; case 98: /* inseq: in */ #line 216 "../src/language/parse.y" {(yyval.val)=newopcall(OPcompr,(yyvsp[0].val),-2,&(yyloc));} #line 2526 "../src/language/parse.c" break; case 99: /* inseq: in ',' expr */ #line 217 "../src/language/parse.y" {(yyval.val)=newopcall3(OPcompr,(yyvsp[-2].val),-2,(yyvsp[0].val),&(yyloc));} #line 2532 "../src/language/parse.c" break; case 100: /* inseq: in ';' inseq */ #line 218 "../src/language/parse.y" {(yyval.val)=newopcall(OPcomprc,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2538 "../src/language/parse.c" break; case 101: /* inseq: in ',' expr ';' inseq */ #line 219 "../src/language/parse.y" {(yyval.val)=newopcall3(OPcomprc,(yyvsp[-4].val),(yyvsp[0].val),(yyvsp[-2].val),&(yyloc));} #line 2544 "../src/language/parse.c" break; case 102: /* compr: '[' expr '|' inseq ']' */ #line 222 "../src/language/parse.y" {(yyval.val)=addcurrexpr((yyvsp[-1].val),(yyvsp[-3].val),&(yyloc));} #line 2550 "../src/language/parse.c" break; case 103: /* arg: seq */ #line 225 "../src/language/parse.y" {(yyval.val)=(yyvsp[0].val);} #line 2556 "../src/language/parse.c" break; case 104: /* arg: lvalue '[' ".." ']' */ #line 226 "../src/language/parse.y" {(yyval.val)=newnode(Fvararg,(yyvsp[-3].val),-1,&(yyloc));} #line 2562 "../src/language/parse.c" break; case 105: /* arg: '&' lvalue */ #line 227 "../src/language/parse.y" {(yyval.val)=newnode(Frefarg,(yyvsp[0].val),-1,&(yyloc));} #line 2568 "../src/language/parse.c" break; case 106: /* arg: '~' lvalue */ #line 228 "../src/language/parse.y" {(yyval.val)=newnode(Findarg,(yyvsp[0].val),-1,&(yyloc));} #line 2574 "../src/language/parse.c" break; case 107: /* $@1: %empty */ #line 229 "../src/language/parse.y" {if (!pari_once) { yyerrok; } pari_once=1;} #line 2580 "../src/language/parse.c" break; case 108: /* arg: arg error $@1 expr */ #line 230 "../src/language/parse.y" {pari_once=0; (yyval.val)=newopcall(OPcat,(yyvsp[-3].val),(yyvsp[0].val),&(yyloc));} #line 2586 "../src/language/parse.c" break; case 109: /* listarg: arg */ #line 233 "../src/language/parse.y" {(yyval.val)=(yyvsp[0].val);} #line 2592 "../src/language/parse.c" break; case 110: /* listarg: listarg ',' arg */ #line 234 "../src/language/parse.y" {(yyval.val)=newnode(Flistarg,(yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2598 "../src/language/parse.c" break; case 111: /* funcid: "variable name" '(' listarg ')' */ #line 237 "../src/language/parse.y" {(yyval.val)=newnode(Ffunction,newconst(CSTentry,&(yylsp[-3])),(yyvsp[-1].val),&(yyloc));} #line 2604 "../src/language/parse.c" break; case 112: /* memberid: expr '.' "variable name" */ #line 240 "../src/language/parse.y" {(yyval.val)=newnode(Ffunction,newconst(CSTmember,&(yylsp[0])),(yyvsp[-2].val),&(yyloc));} #line 2610 "../src/language/parse.c" break; case 113: /* definition: "variable name" '(' listarg ')' '=' seq */ #line 244 "../src/language/parse.y" {(yyval.val)=newfunc(CSTentry,&(yylsp[-5]),(yyvsp[-3].val),(yyvsp[0].val),&(yyloc));} #line 2616 "../src/language/parse.c" break; case 114: /* definition: expr '.' "variable name" '=' seq */ #line 246 "../src/language/parse.y" {(yyval.val)=newfunc(CSTmember,&(yylsp[-2]),newnode(Findarg,(yyvsp[-4].val),-1,&(yylsp[-4])),(yyvsp[0].val),&(yyloc));} #line 2622 "../src/language/parse.c" break; case 115: /* definition: lvalue "->" seq */ #line 247 "../src/language/parse.y" {(yyval.val)=newnode(Flambda, (yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2628 "../src/language/parse.c" break; case 116: /* definition: '(' listarg ")->" seq */ #line 248 "../src/language/parse.y" {(yyval.val)=newnode(Flambda, (yyvsp[-2].val),(yyvsp[0].val),&(yyloc));} #line 2634 "../src/language/parse.c" break; #line 2638 "../src/language/parse.c" default: break; } /* User semantic actions sometimes alter yychar, and that requires that yytoken be updated with the new translation. We take the approach of translating immediately before every use of yytoken. One alternative is translating here after every semantic action, but that translation would be missed if the semantic action invokes YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an incorrect destructor might then be invoked immediately. In the case of YYERROR or YYBACKUP, subsequent parser actions might lead to an incorrect destructor call or verbose syntax error message before the lookahead is translated. */ YY_SYMBOL_PRINT ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc); YYPOPSTACK (yylen); yylen = 0; *++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. */ { const int yylhs = yyr1[yyn] - YYNTOKENS; const int yyi = yypgoto[yylhs] + *yyssp; yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp ? yytable[yyi] : yydefgoto[yylhs]); } goto yynewstate; /*--------------------------------------. | yyerrlab -- here on detecting error. | `--------------------------------------*/ yyerrlab: /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ yytoken = yychar == PARI_EMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar); /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; { yypcontext_t yyctx = {yyssp, yytoken, &yylloc}; char const *yymsgp = YY_("syntax error"); int yysyntax_error_status; yysyntax_error_status = yysyntax_error (&yymsg_alloc, &yymsg, &yyctx); if (yysyntax_error_status == 0) yymsgp = yymsg; else if (yysyntax_error_status == -1) { if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); yymsg = YY_CAST (char *, YYSTACK_ALLOC (YY_CAST (YYSIZE_T, yymsg_alloc))); if (yymsg) { yysyntax_error_status = yysyntax_error (&yymsg_alloc, &yymsg, &yyctx); yymsgp = yymsg; } else { yymsg = yymsgbuf; yymsg_alloc = sizeof yymsgbuf; yysyntax_error_status = YYENOMEM; } } yyerror (&yylloc, lex, yymsgp); if (yysyntax_error_status == YYENOMEM) YYNOMEM; } } yyerror_range[1] = yylloc; if (yyerrstatus == 3) { /* If just tried and failed to reuse lookahead token after an error, discard it. */ if (yychar <= PARI_EOF) { /* Return failure if at end of input. */ if (yychar == PARI_EOF) YYABORT; } else { yydestruct ("Error: discarding", yytoken, &yylval, &yylloc, lex); yychar = PARI_EMPTY; } } /* Else will try to reuse lookahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: /* Pacify compilers when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (0) YYERROR; ++yynerrs; /* Do not reclaim the symbols of the rule whose 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. */ /* Pop stack until we find a state that shifts the error token. */ for (;;) { yyn = yypact[yystate]; if (!yypact_value_is_default (yyn)) { yyn += YYSYMBOL_YYerror; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror) { yyn = yytable[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) YYABORT; yyerror_range[1] = *yylsp; yydestruct ("Error: popping", YY_ACCESSING_SYMBOL (yystate), yyvsp, yylsp, lex); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; YY_IGNORE_MAYBE_UNINITIALIZED_END yyerror_range[2] = yylloc; ++yylsp; YYLLOC_DEFAULT (*yylsp, yyerror_range, 2); /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp); yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturnlab; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturnlab; /*-----------------------------------------------------------. | yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. | `-----------------------------------------------------------*/ yyexhaustedlab: yyerror (&yylloc, lex, YY_("memory exhausted")); yyresult = 2; goto yyreturnlab; /*----------------------------------------------------------. | yyreturnlab -- parsing is finished, clean up and return. | `----------------------------------------------------------*/ yyreturnlab: if (yychar != PARI_EMPTY) { /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ yytoken = YYTRANSLATE (yychar); yydestruct ("Cleanup: discarding lookahead", yytoken, &yylval, &yylloc, lex); } /* Do not reclaim the symbols of the rule whose action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", YY_ACCESSING_SYMBOL (+*yyssp), yyvsp, yylsp, lex); YYPOPSTACK (1); } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); return yyresult; } #line 251 "../src/language/parse.y" pari-2.17.2/src/language/parsec.h0000644000175000017500000001175414676526175015217 0ustar billbill/* Copyright (C) 2006-2008 The PARI group. This file is part of the PARI package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #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; static THREAD GEN pari_lasterror; static void pari_error(PARI_LTYPE *yylloc, char **lex, const char *s) { (void) yylloc; (void) lex; if (pari_lasterror) cgiv(pari_lasterror); pari_lasterror=strtoGENstr(s); } static THREAD pari_stack s_node; THREAD node *pari_tree; void pari_init_parser(void) { long i; const char *opname[]={"_||_", "_&&_", "_===_", "_==_", "_!=_", "_>=_", "_>_", "_<=_", "_<_", "_-_","_+_","_<<_", "_>>_", "_%_", "_\\/_", "_\\_", "_/_", "_*_","_^_","__","_--","_++","_-=_", "_+=_", "_<<=_", "_>>=_", "_%=_", "_\\/=_", "_\\=_", "_/=_", "_*=_","+_","-_","!_","_!","_#","_'_","_~","[_.._]","[_|_<-_,_]","[_|_<-_,_;_]","%","%#","#_",""}; pari_stack_init(&s_node,sizeof(*pari_tree),(void **)&pari_tree); pari_stack_alloc(&s_node,OPnboperator); parsestate_reset(); for (i=0;inode = s_node.n; state->lex_start = pari_lex_start; 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_once = state->once; pari_discarded = state->discarded; pari_lasterror = state->lasterror; } GEN pari_compile_str(const char *lex) { pari_sp ltop=avma; GEN code; struct pari_parsestate state; parsestate_save(&state); pari_lex_start = lex; pari_once=1; pari_discarded=0; pari_lasterror=NULL; if (pari_parse((char**)&lex) || pari_discarded) { if (pari_lasterror) compile_err(GSTR(pari_lasterror),lex-1); else /* should not happen */ compile_err("syntax error",lex-1); } set_avma(ltop); optimizenode(s_node.n-1); code=gp_closure(s_node.n-1); parsestate_restore(&state); return code; } static long newnode(Ffunc f, long x, long y, struct node_loc *loc) { long n=pari_stack_new(&s_node); pari_tree[n].f=f; pari_tree[n].x=x; pari_tree[n].y=y; pari_tree[n].str=loc->start; pari_tree[n].len=loc->end-loc->start; pari_tree[n].flags=0; return n; } static long newconst(long x, struct node_loc *loc) { return newnode(Fconst,x,-1,loc); } static long newopcall(OPerator op, long x, long y, struct node_loc *loc) { if (y==-1) return newnode(Ffunction,op,x,loc); else return newnode(Ffunction,op,newnode(Flistarg,x,y,loc),loc); } static long newopcall3(OPerator op, long x, long y, long z, struct node_loc *loc) { return newopcall(op,newnode(Flistarg,x,y,loc),z,loc); } static long countarg(long n) { long i; for(i=1; pari_tree[n].f==Flistarg; i++) n = pari_tree[n].x; return i; } static long addcurrexpr(long n, long currexpr, struct node_loc *loc) { long y, m = n; while (pari_tree[m].x==OPcomprc) { y = pari_tree[m].y; if (countarg(y)==4) y = pari_tree[y].x; m = pari_tree[y].y; } y = pari_tree[m].y; if (countarg(y)==4) y = pari_tree[y].x; pari_tree[y].y = currexpr; pari_tree[n].str=loc->start; pari_tree[n].len=loc->end-loc->start; return n; } static long newintnode(struct node_loc *loc) { if (loc->end-loc->start<=(long)(1+LOG10_2*BITS_IN_LONG)) { pari_sp ltop=avma; GEN g=strtoi(loc->start); long s = itos_or_0(g), sg = signe(g); set_avma(ltop); if (sg==0 || s) return newnode(Fsmall,s,-1,loc); } return newconst(CSTint,loc); } static long newfunc(CSTtype t, struct node_loc *func, long args, long code, struct node_loc *loc) { long name=newnode(Fentry,newconst(t,func),-1,func); return newnode(Fassign,name,newnode(Flambda,args,code,loc),loc); } pari-2.17.2/src/language/gplib.c0000644000175000017500000016053114760123736015016 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*******************************************************************/ /** **/ /** LIBRARY ROUTINES FOR PARI CALCULATOR **/ /** **/ /*******************************************************************/ #ifdef _WIN32 # include "../systems/mingw/pwinver.h" # include # include "../systems/mingw/mingw.h" # include #endif #include "pari.h" #include "paripriv.h" /********************************************************************/ /** **/ /** STRINGS **/ /** **/ /********************************************************************/ void pari_skip_space(char **s) { char *t = *s; while (isspace((unsigned char)*t)) t++; *s = t; } void pari_skip_alpha(char **s) { char *t = *s; while (isalpha((unsigned char)*t)) t++; *s = t; } /*******************************************************************/ /** **/ /** BUFFERS **/ /** **/ /*******************************************************************/ static Buffer **bufstack; static pari_stack s_bufstack; void pari_init_buffers(void) { pari_stack_init(&s_bufstack, sizeof(Buffer*), (void**)&bufstack); } 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 */ void kill_buffers_upto(Buffer *B) { while (s_bufstack.n) { if (bufstack[ s_bufstack.n-1 ] == B) break; pop_buffer(); } } void kill_buffers_upto_including(Buffer *B) { while (s_bufstack.n) { if (bufstack[ s_bufstack.n-1 ] == B) { pop_buffer(); break; } pop_buffer(); } } static int disable_exception_handler = 0; #define BLOCK_EH_START \ { \ int block=disable_exception_handler;\ disable_exception_handler = 1; #define BLOCK_EH_END \ disable_exception_handler = block;\ } /* numerr < 0: from SIGINT */ int gp_handle_exception(long numerr) { if (disable_exception_handler) disable_exception_handler = 0; else if (GP_DATA->breakloop && cb_pari_break_loop && cb_pari_break_loop(numerr)) return 1; return 0; } /********************************************************************/ /** **/ /** HELP **/ /** **/ /********************************************************************/ void pari_hit_return(void) { int c; if (GP_DATA->flags & (gpd_EMACS|gpd_TEXMACS)) return; BLOCK_EH_START pari_puts("/*-- (type RETURN to continue) --*/"); pari_flush(); /* if called from a readline callback, may be in a funny TTY mode */ do c = fgetc(stdin); while (c >= 0 && c != '\n' && c != '\r'); pari_putc('\n'); BLOCK_EH_END } static int has_ext_help(void) { return (GP_DATA->help && *GP_DATA->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 nonzero. 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; pari_hit_return(); } continue; } len = maxlen - strlen(*l); while (len--) pari_putc(' '); } if (i) pari_putc('\n'); } static const long MAX_SECTION = 17; static void commands(long n) { long i; entree *ep; char **t_L; pari_stack s_L; pari_stack_init(&s_L, sizeof(*t_L), (void**)&t_L); for (i = 0; i < functions_tblsz; i++) for (ep = functions_hash[i]; ep; ep = ep->next) { long m; switch (EpVALENCE(ep)) { case EpVAR: if (typ((GEN)ep->value) == t_CLOSURE) break; /* fall through */ case EpNEW: continue; } m = ep->menu; if (m == n || (n < 0 && m && m <= MAX_SECTION)) pari_stack_pushp(&s_L, (void*)ep->name); } pari_stack_pushp(&s_L, NULL); print_fun_list(t_L, term_height()-4); pari_stack_delete(&s_L); } void pari_center(const char *s) { pari_sp av = avma; long i, l = strlen(s), pad = term_width() - l; char *buf, *u; if (pad<0) pad=0; else pad >>= 1; u = buf = stack_malloc(l + pad + 2); for (i=0; i-request@pari.math.u-bordeaux.fr\n\ with a Subject: field containing the word 'subscribe'.\n\n"); print_text("An archive is kept at the WWW site mentioned above. You can also \ reach the authors at pari@math.u-bordeaux.fr (answer not guaranteed)."); } static void gentypes(void) { pari_puts("List of the PARI types:\n\ t_INT : long integers [ cod1 ] [ cod2 ] [ man_1 ] ... [ man_k ]\n\ t_REAL : long real numbers [ cod1 ] [ cod2 ] [ man_1 ] ... [ man_k ]\n\ t_INTMOD : integermods [ code ] [ mod ] [ integer ]\n\ t_FRAC : irred. rationals [ code ] [ num. ] [ den. ]\n\ t_FFELT : finite field elt. [ code ] [ cod2 ] [ elt ] [ mod ] [ p ]\n\ t_COMPLEX: complex numbers [ code ] [ real ] [ imag ]\n\ t_PADIC : p-adic numbers [ cod1 ] [ cod2 ] [ p ] [ p^r ] [ int ]\n\ t_QUAD : quadratic numbers [ cod1 ] [ mod ] [ real ] [ imag ]\n\ t_POLMOD : poly mod [ code ] [ mod ] [ polynomial ]\n\ -------------------------------------------------------------\n\ t_POL : polynomials [ cod1 ] [ cod2 ] [ man_1 ] ... [ man_k ]\n\ t_SER : power series [ cod1 ] [ cod2 ] [ man_1 ] ... [ man_k ]\n\ t_RFRAC : irred. rat. func. [ code ] [ num. ] [ den. ]\n\ t_QFB : qfb [ code ] [ a ] [ b ] [ c ] [ disc ]\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 [ cod1 ] [ cod2 ] [ 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 ] [ proto ] [ operand ] ... \n\ t_ERROR : error context [ code ] [ errnum ] [ dat_1 ] ... [ dat_k ]\n\ t_INFINITY: a*infinity [ code ] [ a ]\n\ \n"); } static void menu_commands(void) { ulong i; const char *s[] = { "user-defined functions (aliases, installed and user functions)", "PROGRAMMING under GP", "Standard monadic or dyadic OPERATORS", "CONVERSIONS and similar elementary functions", "functions related to COMBINATORICS", "NUMBER THEORETICAL functions", "POLYNOMIALS and power series", "Vectors, matrices, LINEAR ALGEBRA and sets", "TRANSCENDENTAL functions", "SUMS, products, integrals and similar functions", "General NUMBER FIELDS", "Associative and central simple ALGEBRAS", "ELLIPTIC CURVES", "L-FUNCTIONS", "HYPERGEOMETRIC MOTIVES", "MODULAR FORMS", "MODULAR SYMBOLS", "GRAPHIC functions", "The PARI community" }; pari_puts("Help topics: for a list of relevant subtopics, type ?n for n in\n"); for (i = 0; i < numberof(s); i++) pari_printf(" %2lu: %s\n", i, s[i]); pari_puts("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\ ?? refcard-ell (or -lfun/-mf/-nf: specialized reference card)\n\ ?? keyword (long help text about \"keyword\" from the user's manual)\n\ ??? keyword (a propos: list of related functions)."); } static void slash_commands(void) { pari_puts("# : enable/disable timer\n\ ## : print time for last result\n\ \\\\ : comment up to end of line\n\ \\a {n} : print result in raw format (readable by PARI)\n\ \\B {n} : print result in beautified format\n\ \\c : list all commands (same effect as ?*)\n\ \\d : print all defaults\n\ \\e {n} : enable/disable echo (set echo=n)\n\ \\g {n} : set debugging level\n\ \\gf{n} : set file debugging level\n\ \\gm{n} : set memory debugging level\n\ \\h {m-n}: hashtable information\n\ \\l {f} : enable/disable logfile (set logfile=f)\n\ \\m {n} : print result in prettymatrix format\n\ \\o {n} : set output method (0=raw, 1=prettymatrix, 2=prettyprint, 3=2-dim)\n\ \\p {n} : change real precision\n\ \\pb{n} : change real bit precision\n\ \\ps{n} : change series precision\n\ \\q : quit completely this GP session\n\ \\r {f} : read in a file\n\ \\s : print stack information\n\ \\t : print the list of PARI types\n\ \\u : print the list of user-defined functions\n\ \\um : print the list of user-defined member functions\n\ \\uv : print the list of user-defined variables, excluding closures\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 quad,bid, bnf,bnr\n\ cyc : cyclic decomposition quad,bid, clgp,ell, bnf,bnr\n\ diff, codiff: different and codifferent nf,bnf,bnr\n\ disc : discriminant ell,nf,bnf,bnr,rnf\n\ e, f : inertia/residue degree prid\n\ fu : fundamental units bnf\n\ gen : generators bid,prid,clgp,ell, bnf,bnr, gal\n\ group: group ell, gal\n\ index: index nf,bnf,bnr\n\ j : j-invariant ell\n"); /* split: some compilers can't handle long constant strings */ pari_puts("\ mod : modulus bid, bnr, gal\n\ nf : number field nf,bnf,bnr,rnf\n\ no : number of elements quad,bid, clgp,ell, bnf,bnr\n\ normfu: quad\n\ omega, eta: [w1,w2] and [eta1, eta2] ell\n\ orders: relative orders of generators gal\n\ p : rational prime prid, ell,nf,bnf,bnr,rnf,gal\n\ pol : defining polynomial nf,bnf,bnr, gal\n\ polabs: defining polynomial over Q rnf\n\ reg : regulator quad, bnf\n\ roots: roots ell,nf,bnf,bnr, gal\n\ sign,r1,r2 : signature nf,bnf,bnr\n\ t2 : t2 matrix nf,bnf,bnr\n\ tate : Tate's [u^2, u, q, [a,b], L, Ei] ell\n\ tu : torsion unit and its order bnf\n\ zk : integral basis nf,bnf,bnr,rnf\n\ zkst : structure of (Z_K/m)* bid, bnr\n"); } #define QUOTE "_QUOTE" #define DOUBQUOTE "_DOUBQUOTE" #define BACKQUOTE "_BACKQUOTE" static char * _cat(char *s, const char *t) { *s = 0; strcat(s,t); return s + strlen(t); } static char * filter_quotes(const char *s) { int i, l = strlen(s); int quote = 0; int backquote = 0; int doubquote = 0; char *str, *t; for (i=0; i < l; i++) switch(s[i]) { case '\'': quote++; break; case '`' : backquote++; break; case '"' : doubquote++; } str = (char*)pari_malloc(l + quote * (strlen(QUOTE)-1) + doubquote * (strlen(DOUBQUOTE)-1) + backquote * (strlen(BACKQUOTE)-1) + 1); t = str; for (i=0; i < l; i++) switch(s[i]) { case '\'': t = _cat(t, QUOTE); break; case '`' : t = _cat(t, BACKQUOTE); break; case '"' : t = _cat(t, DOUBQUOTE); break; default: *t++ = s[i]; } *t = 0; return str; } static int nl_read(char *s) { size_t l = strlen(s); return s[l-1] == '\n'; } /* query external help program for s. num < 0 [keyword] or chapter number */ static void external_help(const char *s, long num) { long nbli = term_height()-3, li = 0; char buf[256], *str; const char *opt = "", *ar = ""; char *t, *help = GP_DATA->help; pariFILE *z; FILE *f; if (cb_pari_long_help) { cb_pari_long_help(s, num); return; } if (!has_ext_help()) pari_err(e_MISC,"no external help program"); t = filter_quotes(s); if (num < 0) opt = "-k"; else if (t[strlen(t)-1] != '@') ar = stack_sprintf("@%d",num); #ifdef _WIN32 if (*help == '@') { const char *basedir = win32_basedir(); help = stack_sprintf("%c:& cd %s & %s", *basedir, basedir, help+1); } #endif str = stack_sprintf("%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(t); while (fgets(buf, numberof(buf), f)) { if (!strncmp("ugly_kludge_done",buf,16)) break; pari_puts(buf); if (nl_read(buf) && ++li > nbli) { pari_hit_return(); li = 0; } } pari_fclose(z); } const char ** gphelp_keyword_list(void) { static const char *L[]={ "operator", "libpari", "member", "integer", "real", "readline", "refcard", "refcard-nf", "refcard-ell", "refcard-mf", "refcard-lfun", "tutorial", "tutorial-mf", "mf", "nf", "bnf", "bnr", "ell", "rnf", "hgm", "HGM", "ideal", "idele", "CFT", "bid", "modulus", "prototype", "Lmath", "Ldata", "Linit", "character", "sums", "products", "integrals", "gchar", "grossencharacter", "Grossencharacter", NULL}; return L; } static int ok_external_help(char **s) { const char **L; long n; if (!**s) return 1; if (!isalpha((unsigned char)**s)) return 3; /* operator or section number */ if (!strncmp(*s,"t_",2)) { *s += 2; return 2; } /* type name */ L = gphelp_keyword_list(); for (n=0; L[n]; n++) if (!strcmp(*s,L[n])) return 3; return 0; } static void cut_trailing_garbage(char *s) { char c; while ( (c = *s++) ) { if (c == '\\' && ! *s++) return; /* gobble next char, return if none. */ if (!is_keyword_char(c) && c != '@') { s[-1] = 0; return; } } } static void digit_help(char *s, long flag) { long n = atoi(s); if (n < 0 || n > MAX_SECTION+4) pari_err(e_SYNTAX,"no such section in help: ?",s,s); if (n == MAX_SECTION+1) community(); else if (flag & h_LONG) external_help(s,3); else commands(n); return; } long pari_community(void) { return MAX_SECTION+1; } static void simple_help(const char *s1, const char *s2) { pari_printf("%s: %s\n", s1, s2); } static void default_help(char *s, long flag) { if (flag & h_LONG) external_help(stack_strcat("se:def,",s),3); else simple_help(s,"default"); } static void help(const char *s0, int flag) { const long long_help = flag & h_LONG; long n; entree *ep; char *s = get_sep(s0); if (isdigit((unsigned char)*s)) { digit_help(s,flag); return; } if (flag & h_APROPOS) { external_help(s,-1); return; } /* Get meaningful answer on '\ps 5' (e.g. from ) */ if (*s == '\\' && isalpha((unsigned char)*(s+1))) { char *t = s+1; pari_skip_alpha(&t); *t = '\0'; } if (isalpha((unsigned char)*s)) { char *t = s; if (!strncmp(s, "default", 7)) { /* special-case ?default(dft_name), e.g. default(log) */ t += 7; pari_skip_space(&t); if (*t == '(') { t++; pari_skip_space(&t); cut_trailing_garbage(t); if (pari_is_default(t)) { default_help(t,flag); return; } } } if (!strncmp(s, "refcard-", 8)) t += 8; else if (!strncmp(s, "tutorial-", 9)) t += 9; if (strncmp(s, "se:", 3)) cut_trailing_garbage(t); } if (long_help && (n = ok_external_help(&s))) { external_help(s,n); return; } switch (*s) { case '*' : commands(-1); return; case '\0': menu_commands(); return; case '\\': slash_commands(); return; case '.' : member_commands(); return; } ep = is_entry(s); if (!ep) { if (pari_is_default(s)) default_help(s,flag); else if (long_help) external_help(s,3); else if (!cb_pari_whatnow || !cb_pari_whatnow(pariOut, s,1)) simple_help(s,"unknown identifier"); return; } if (EpVALENCE(ep) == EpALIAS) { pari_printf("%s is aliased to:\n\n",s); ep = do_alias(ep); } switch(EpVALENCE(ep)) { case EpVAR: if (!ep->help) { if (typ((GEN)ep->value)!=t_CLOSURE) simple_help(s, "user defined variable"); else { GEN str = closure_get_text((GEN)ep->value); if (typ(str) == t_VEC) pari_printf("%s =\n %Ps\n", ep->name, ep->value); } return; } break; case EpINSTALL: if (!ep->help) { simple_help(s, "installed function"); return; } break; case EpNEW: if (!ep->help) { simple_help(s, "new identifier"); return; }; break; default: /* built-in function */ if (!ep->help) pari_err_BUG("gp_help (no help found)"); /*paranoia*/ if (long_help) { external_help(ep->name,3); return; } } print_text(ep->help); } void gp_help(const char *s, long flag) { pari_sp av = avma; if ((flag & h_RL) == 0) { if (*s == '?') { flag |= h_LONG; s++; } if (*s == '?') { flag |= h_APROPOS; s++; } } term_color(c_HELP); help(s,flag); term_color(c_NONE); if ((flag & h_RL) == 0) pari_putc('\n'); set_avma(av); } /********************************************************************/ /** **/ /** GP HEADER **/ /** **/ /********************************************************************/ static char * what_readline(void) { #ifdef READLINE const char *v = READLINE; char *s = stack_malloc(3 + strlen(v) + 8); (void)sprintf(s, "v%s %s", v, GP_DATA->use_readline? "enabled": "disabled"); return s; #else return (char*)"not compiled in"; #endif } static char * what_cc(void) { char *s; #ifdef GCC_VERSION # ifdef __cplusplus s = stack_malloc(6 + strlen(GCC_VERSION) + 1); (void)sprintf(s, "(C++) %s", GCC_VERSION); # else s = stack_strdup(GCC_VERSION); # endif #else # ifdef _MSC_VER s = stack_malloc(32); (void)sprintf(s, "MSVC-%i", _MSC_VER); # else s = NULL; # endif #endif return s; } static char * convert_time(char *s, long delay) { if (delay >= 3600000) { sprintf(s, "%ldh, ", delay / 3600000); s+=strlen(s); delay %= 3600000; } if (delay >= 60000) { sprintf(s, "%ldmin, ", delay / 60000); s+=strlen(s); delay %= 60000; } if (delay >= 1000) { sprintf(s, "%ld,", delay / 1000); s+=strlen(s); delay %= 1000; if (delay < 100) { sprintf(s, "%s", (delay<10)? "00": "0"); s+=strlen(s); } } sprintf(s, "%ld ms", delay); s+=strlen(s); return s; } /* Format a time of 'delay' ms */ const char * gp_format_time(long delay) { char *buf = stack_malloc(64), *s = buf; term_get_color(s, c_TIME); s = convert_time(s + strlen(s), delay); term_get_color(s, c_NONE); return buf; } GEN strtime(long delay) { long n = nchar2nlong(64); GEN x = cgetg(n+1, t_STR); char *buf = GSTR(x), *t = buf + 64, *s = convert_time(buf, delay); s++; while (s < t) *s++ = 0; /* pacify valgrind */ return x; } /********************************************************************/ /* */ /* GPRC */ /* */ /********************************************************************/ /* LOCATE GPRC */ static void err_gprc(const char *s, char *t, char *u) { err_printf("\n"); pari_err(e_SYNTAX,s,t,u); } /* return $HOME or the closest we can find */ static const char * get_home(int *free_it) { char *drv, *pth = os_getenv("HOME"); if (pth) return pth; if ((drv = os_getenv("HOMEDRIVE")) && (pth = os_getenv("HOMEPATH"))) { /* looks like WinNT */ char *buf = (char*)pari_malloc(strlen(pth) + strlen(drv) + 1); sprintf(buf, "%s%s",drv,pth); *free_it = 1; return buf; } pth = pari_get_homedir(""); return pth? pth: "."; } static FILE * gprc_chk(const char *s) { FILE *f = fopen(s, "r"); if (f && !(GP_DATA->flags & gpd_QUIET)) err_printf("Reading GPRC: %s\n", s); return f; } /* Look for [._]gprc: $GPRC, then in $HOME, ., /etc, pari_datadir */ static FILE * gprc_get(void) { FILE *f = NULL; const char *gprc = os_getenv("GPRC"); if (gprc) f = gprc_chk(gprc); if (!f) { int free_it = 0; const char *home = get_home(&free_it); char *str, *s, c; long l; l = strlen(home); c = home[l-1]; /* + "/gprc.txt" + \0*/ str = strcpy((char*)pari_malloc(l+10), home); if (free_it) pari_free((void*)home); s = str + l; if (c != '/' && c != '\\') *s++ = '/'; #ifndef _WIN32 strcpy(s, ".gprc"); #else strcpy(s, "gprc.txt"); #endif f = gprc_chk(str); /* in $HOME */ if (!f) f = gprc_chk(s); /* in . */ #ifndef _WIN32 if (!f) f = gprc_chk("/etc/gprc"); #else if (!f) /* in basedir */ { const char *basedir = win32_basedir(); char *t = (char *) pari_malloc(strlen(basedir)+strlen(s)+2); sprintf(t, "%s/%s", basedir, s); f = gprc_chk(t); free(t); } #endif pari_free(str); } return f; } /* PREPROCESSOR */ static ulong read_uint(char **s) { long v = atol(*s); if (!isdigit((unsigned char)**s)) err_gprc("not an integer", *s, *s); while (isdigit((unsigned char)**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); } if (!strncmp(*s,"BITS_IN_LONG",12)) { *s += 12; if ((*s)[0] == '=' && (*s)[1] == '=') { *s += 2; return BITS_IN_LONG == read_uint(s); } } return -1; } /* PARSE GPRC */ /* 1) replace next separator by '\0' (t must be writable) * 2) return the next expression ("" if none) * see get_sep() */ static char * next_expr(char *t) { int outer = 1; char *s = t; for(;;) { char c; switch ((c = *s++)) { case '"': if (outer || (s >= t+2 && s[-2] != '\\')) outer = !outer; break; case '\0': return (char*)""; default: if (outer && c == ';') { s[-1] = 0; return s; } } } } Buffer * filtered_buffer(filtre_t *F) { Buffer *b = new_buffer(); init_filtre(F, b); pari_stack_pushp(&s_bufstack, (void*)b); return b; } /* parse src of the form s=t (or s="t"), set *ps to s, and *pt to t. * modifies src (replaces = by \0) */ void parse_key_val(char *src, char **ps, char **pt) { char *s_end, *t; t = src; while (*t && *t != '=') t++; if (*t != '=') err_gprc("missing '='",t,src); s_end = t; t++; if (*t == '"') (void)pari_translate_string(t, t, src); *s_end = 0; *ps = src; *pt = t; } /* parse src of the form (s,t) (or "s", or "t"), set *ps to s, and *pt to t. */ static void parse_key_val_paren(char *src, char **ps, char **pt) { char *s, *t, *s_end, *t_end; s = t = src + 1; while (*t && *t != ',') t++; if (*t != ',') err_gprc("missing ','",t,src); s_end = t; t++; while (*t && *t != ')') t++; if (*t != ')') err_gprc("missing ')'",t,src); if (t[1]) err_gprc("unexpected character",t+1,src); t_end = t; t = s_end + 1; if (*t == '"') (void)pari_translate_string(t, t, src); if (*s == '"') (void)pari_translate_string(s, s, src); *s_end = 0; *t_end = 0; *ps = s; *pt = t; } void gp_initrc(pari_stack *p_A) { FILE *file = gprc_get(); Buffer *b; filtre_t F; VOLATILE long c = 0; jmp_buf *env; pari_stack s_env; if (!file) return; b = filtered_buffer(&F); pari_stack_init(&s_env, sizeof(*env), (void**)&env); (void)pari_stack_new(&s_env); for(;;) { char *nexts, *s, *t; if (setjmp(env[s_env.n-1])) err_printf("...skipping line %ld.\n", c); c++; if (!get_line_from_file(NULL,&F,file)) break; s = b->buf; if (*s == '#') { /* preprocessor directive */ int z, NOT = 0; s++; if (strncmp(s,"if",2)) err_gprc("unknown directive",s,b->buf); s += 2; if (!strncmp(s,"not",3)) { NOT = !NOT; s += 3; } if (*s == '!') { NOT = !NOT; s++; } t = s; z = get_preproc_value(&s); if (z < 0) err_gprc("unknown preprocessor variable",t,b->buf); if (NOT) z = !z; if (!*s) { /* make sure at least an expr follows the directive */ if (!get_line_from_file(NULL,&F,file)) break; s = b->buf; } if (!z) continue; /* dump current line */ } /* parse line */ for ( ; *s; s = nexts) { nexts = next_expr(s); if (!strncmp(s,"read",4) && (s[4] == ' ' || s[4] == '\t' || s[4] == '"')) { /* read file */ s += 4; t = (char*)pari_malloc(strlen(s) + 1); if (*s == '"') (void)pari_translate_string(s, t, s-4); else strcpy(t,s); pari_stack_pushp(p_A,t); } else if (!strncmp(s, "default(", 8)) { s += 7; parse_key_val_paren(s, &s,&t); (void)setdefault(s,t,d_INITRC); } else if (!strncmp(s, "setdebug(", 9)) { s += 8; parse_key_val_paren(s, &s,&t); setdebug(s, atol(t)); } else { /* set default */ parse_key_val(s, &s,&t); (void)setdefault(s,t,d_INITRC); } } } pari_stack_delete(&s_env); pop_buffer(); if (!(GP_DATA->flags & gpd_QUIET)) err_printf("GPRC Done.\n\n"); fclose(file); } void gp_load_gprc(void) { pari_stack sA; char **A; long i; pari_stack_init(&sA,sizeof(*A),(void**)&A); gp_initrc(&sA); for (i = 0; i < sA.n; pari_free(A[i]),i++) { pari_CATCH(CATCH_ALL) { err_printf("... skipping file '%s'\n", A[i]); } pari_TRY { gp_read_file(A[i]); } pari_ENDCATCH; } pari_stack_delete(&sA); } /********************************************************************/ /* */ /* PROMPTS */ /* */ /********************************************************************/ /* if prompt is coloured, tell readline to ignore the ANSI escape sequences */ /* s must be able to store 14 chars (including final \0) */ #ifdef READLINE static void readline_prompt_color(char *s, int c) { #ifdef _WIN32 (void)s; (void)c; #else *s++ = '\001'; /*RL_PROMPT_START_IGNORE*/ term_get_color(s, c); s += strlen(s); *s++ = '\002'; /*RL_PROMPT_END_IGNORE*/ *s = 0; #endif } #endif /* s must be able to store 14 chars (including final \0) */ static void brace_color(char *s, int c, int force) { if (disable_color || (gp_colors[c] == c_NONE && !force)) return; #ifdef READLINE if (GP_DATA->use_readline) readline_prompt_color(s, c); else #endif term_get_color(s, c); } /* strlen(prompt) + 28 chars */ static const char * color_prompt(const char *prompt) { long n = strlen(prompt); char *t = stack_malloc(n + 28), *s = t; *s = 0; /* escape sequences bug readline, so use special bracing (if available) */ brace_color(s, c_PROMPT, 0); s += strlen(s); memcpy(s, prompt, n); s += n; *s = 0; brace_color(s, c_INPUT, 1); return t; } const char * gp_format_prompt(const char *prompt) { if (GP_DATA->flags & gpd_TEST) return prompt; else { char b[256]; /* longer is truncated */ strftime_expand(prompt, b, sizeof(b)); return color_prompt(b); } } /********************************************************************/ /* */ /* GP MAIN LOOP */ /* */ /********************************************************************/ static int is_interactive(void) { return cb_pari_is_interactive? cb_pari_is_interactive(): 0; } static char * strip_prompt(const char *s) { long l = strlen(s); char *t, *t0 = stack_malloc(l+1); t = t0; for (; *s; s++) { /* RL_PROMPT_START_IGNORE / RL_PROMPT_END_IGNORE */ if (*s == 1 || *s == 2) continue; if (*s == '\x1b') /* skip ANSI color escape sequence */ { while (*++s != 'm') if (!*s) goto end; continue; } *t = *s; t++; } end: *t = 0; return t0; } static void update_logfile(const char *prompt, const char *s) { pari_sp av; const char *p; if (!pari_logfile) return; av = avma; p = strip_prompt(prompt); /* raw prompt */ switch (pari_logstyle) { case logstyle_TeX: fprintf(pari_logfile, "\\PARIpromptSTART|%s\\PARIpromptEND|%s\\PARIinputEND|%%\n", p, s); break; case logstyle_plain: fprintf(pari_logfile,"%s%s\n",p, s); break; case logstyle_color: fprintf(pari_logfile,"%s%s%s%s%s\n",term_get_color(NULL,c_PROMPT), p, term_get_color(NULL,c_INPUT), s, term_get_color(NULL,c_NONE)); break; } set_avma(av); } void gp_echo_and_log(const char *prompt, const char *s) { if (!is_interactive()) { if (!GP_DATA->echo) return; /* not pari_puts(): would duplicate in logfile */ fputs(prompt, pari_outfile); fputs(s, pari_outfile); fputc('\n', pari_outfile); pari_set_last_newline(1); } update_logfile(prompt, s); pari_flush(); } /* prompt = NULL --> from gprc. Return 1 if new input, and 0 if EOF */ int get_line_from_file(const char *prompt, filtre_t *F, FILE *file) { char *s; input_method IM; IM.file = (void*)file; if (file==stdin && cb_pari_fgets_interactive) IM.myfgets = (fgets_t)cb_pari_fgets_interactive; else IM.myfgets = (fgets_t)&fgets; IM.getline = &file_input; IM.free = 0; if (! input_loop(F,&IM)) { if (file==stdin && cb_pari_start_output) cb_pari_start_output(); return 0; } s = F->buf->buf; /* don't log if from gprc or empty input */ if (*s && prompt && GP_DATA->echo != 2) gp_echo_and_log(prompt, s); return 1; } /* return 0 if no line could be read (EOF). If PROMPT = NULL, expand and * color default prompt; otherwise, use PROMPT as-is. */ int gp_read_line(filtre_t *F, const char *PROMPT) { static const char *DFT_PROMPT = "? "; Buffer *b = (Buffer*)F->buf; const char *p; int res, interactive; if (b->len > 100000) fix_buffer(b, 100000); interactive = is_interactive(); if (interactive || pari_logfile || GP_DATA->echo) { p = PROMPT; if (!p) { p = F->in_comment? GP_DATA->prompt_comment: GP_DATA->prompt; p = gp_format_prompt(p); } } else p = DFT_PROMPT; if (interactive) { BLOCK_EH_START if (!pari_last_was_newline()) pari_putc('\n'); if (cb_pari_get_line_interactive) res = cb_pari_get_line_interactive(p, GP_DATA->prompt_cont, F); else { pari_puts(p); pari_flush(); res = get_line_from_file(p, F, pari_infile); } BLOCK_EH_END } else { /* in case UI fakes noninteractivity, e.g. TeXmacs */ if (cb_pari_start_output && cb_pari_get_line_interactive) res = cb_pari_get_line_interactive(p, GP_DATA->prompt_cont, F); else res = get_line_from_file(p, F, pari_infile); } if (!disable_color && p != DFT_PROMPT && (gp_colors[c_PROMPT] != c_NONE || gp_colors[c_INPUT] != c_NONE)) { term_color(c_NONE); pari_flush(); } return res; } /********************************************************************/ /* */ /* EXCEPTION HANDLER */ /* */ /********************************************************************/ static THREAD pari_timer ti_alarm; #if defined(_WIN32) || defined(SIGALRM) static void gp_alarm_fun(void) { char buf[64]; if (cb_pari_start_output) cb_pari_start_output(); convert_time(buf, timer_get(&ti_alarm)); pari_err(e_ALARM, buf); } #endif /* SIGALRM */ void gp_sigint_fun(void) { char buf[150]; #if defined(_WIN32) if (win32alrm) { win32alrm = 0; gp_alarm_fun(); return;} #endif if (cb_pari_start_output) cb_pari_start_output(); convert_time(buf, timer_get(GP_DATA->T)); if (pari_mt_nbthreads > 1) { sprintf(buf + strlen(buf), " cpu time, "); convert_time(buf + strlen(buf), walltimer_get(GP_DATA->Tw)); sprintf(buf + strlen(buf), " real time"); } pari_sigint(buf); } #ifdef SIGALRM 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 */ /* */ /********************************************************************/ void gp_allocatemem(GEN z) { ulong newsize; if (!z) newsize = 0; else { if (typ(z) != t_INT) pari_err_TYPE("allocatemem",z); newsize = itou(z); if (signe(z) < 0) pari_err_DOMAIN("allocatemem","size","<",gen_0,z); } if (pari_mainstack->vsize) paristack_resize(newsize); else paristack_newrsize(newsize); } GEN gp_input(void) { filtre_t F; Buffer *b = filtered_buffer(&F); GEN x; while (! get_line_from_file("",&F,pari_infile)) if (popinfile()) { err_printf("no input ???"); cb_pari_quit(1); } x = readseq(b->buf); pop_buffer(); return x; } static GEN closure_alarmer(GEN C, long s) { struct pari_evalstate state; VOLATILE GEN x; if (!s) { pari_alarm(0); return closure_evalgen(C); } evalstate_save(&state); #if !defined(HAS_ALARM) && !defined(_WIN32) pari_err(e_ARCH,"alarm"); #endif pari_CATCH(CATCH_ALL) /* We need to stop the timer after any error */ { GEN E = pari_err_last(); if (err_get_num(E) != e_ALARM) { pari_alarm(0); pari_err(0, E); } x = evalstate_restore_err(&state); } pari_TRY { pari_alarm(s); x = closure_evalgen(C); pari_alarm(0); } pari_ENDCATCH; return x; } void pari_alarm(long s) { if (s < 0) pari_err_DOMAIN("alarm","delay","<",gen_0,stoi(s)); if (s) timer_start(&ti_alarm); #ifdef _WIN32 win32_alarm(s); #elif defined(HAS_ALARM) alarm(s); #else if (s) pari_err(e_ARCH,"alarm"); #endif } GEN gp_alarm(long s, GEN code) { if (!code) { pari_alarm(s); return gnil; } return closure_alarmer(code,s); } /*******************************************************************/ /** **/ /** EXTERNAL PRETTYPRINTER **/ /** **/ /*******************************************************************/ /* Wait for prettinprinter to finish, to prevent new prompt from overwriting * the output. Fill the output buffer, wait until it is read. * Better than sleep(2): give possibility to print */ static void prettyp_wait(FILE *out) { const char *s = " \n"; long i = 2000; fputs("\n\n", out); fflush(out); /* start translation */ while (--i) fputs(s, out); fputs("\n", out); fflush(out); } /* initialise external prettyprinter (tex2mail) */ static int prettyp_init(void) { gp_pp *pp = GP_DATA->pp; if (!pp->cmd) return 0; if (pp->file || (pp->file = try_pipe(pp->cmd, mf_OUT))) return 1; pari_warn(warner,"broken prettyprinter: '%s'",pp->cmd); pari_free(pp->cmd); pp->cmd = NULL; sd_output("1", d_SILENT); return 0; } /* assume prettyp_init() was called */ static void prettyp_GEN(GEN z) { FILE *log = pari_logfile, *out = GP_DATA->pp->file->file; pariout_t T = *(GP_DATA->fmt); /* copy */ /* output */ T.prettyp = f_TEX; fputGEN_pariout(z, &T, out); /* flush and restore, output to logfile */ prettyp_wait(out); if (log) { if (pari_logstyle == logstyle_TeX) { T.TeXstyle |= TEXSTYLE_BREAK; fputGEN_pariout(z, &T, log); fputc('%', log); } else { T.prettyp = f_RAW; fputGEN_pariout(z, &T, log); } fputc('\n', log); fflush(log); } } /* assume prettyp_init() was called. */ static void prettyp_output(long n) { FILE *log = pari_logfile, *out = GP_DATA->pp->file->file; pari_sp av = avma; const char *c_hist = term_get_color(NULL, c_HIST); const char *c_out = term_get_color(NULL, c_OUTPUT); GEN z = pari_get_hist(n); /* Emit first: there may be lines before the prompt */ term_color(c_OUTPUT); pari_flush(); /* history number */ if (!(GP_DATA->flags & gpd_QUIET)) { if (*c_hist || *c_out) fprintf(out, "\\LITERALnoLENGTH{%s}\\%%%ld =\\LITERALnoLENGTH{%s} ", c_hist, n, c_out); else fprintf(out, "\\%%%ld = ", n); } if (log) switch (pari_logstyle) { case logstyle_plain: fprintf(log, "%%%ld = ", n); break; case logstyle_color: fprintf(log, "%s%%%ld = %s", c_hist, n, c_out); break; case logstyle_TeX: fprintf(log, "\\PARIout{%ld}", n); break; } set_avma(av); prettyp_GEN(z); term_color(c_NONE); pari_flush(); } /*******************************************************************/ /** **/ /** FORMAT GP OUTPUT **/ /** **/ /*******************************************************************/ #define COLOR_LEN 16 static void str_lim_lines(pari_str *S, char *s, long n, long max_lin) { long lin, col, width; char COL[COLOR_LEN]; 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; str_puts(S, term_get_color(COL, c_ERR)); set_avma(av); str_puts(S,"[+++]"); return; } if (c == '\n') { col = -1; lin++; } else if (col == width) { col = 0; lin++; } pari_set_last_newline(c=='\n'); col++; str_putc(S, c); } } void str_display_hist(pari_str *S, long n) { long l = 0; char col[COLOR_LEN]; char *s; /* history number */ if (n) { char buf[64]; if (!(GP_DATA->flags & gpd_QUIET)) { str_puts(S, term_get_color(col, c_HIST)); sprintf(buf, "%%%ld = ", n); str_puts(S, buf); l = strlen(buf); } } /* output */ str_puts(S, term_get_color(col, c_OUTPUT)); s = GENtostr(pari_get_hist(n)); if (GP_DATA->lim_lines) str_lim_lines(S, s, l, GP_DATA->lim_lines); else str_puts(S, s); pari_free(s); str_puts(S,term_get_color(col, c_NONE)); } static void gp_classic_output(long n) { pari_sp av = avma; pari_str S; str_init(&S, 1); str_display_hist(&S, n); str_putc(&S, 0); pari_puts(S.string); pari_putc('\n'); pari_flush(); set_avma(av); } void gp_display_hist(long n) { if (cb_pari_display_hist) cb_pari_display_hist(n); else if (GP_DATA->fmt->prettyp == f_PRETTY && prettyp_init()) prettyp_output(n); else gp_classic_output(n); } /*******************************************************************/ /** **/ /** GP-SPECIFIC DEFAULTS **/ /** **/ /*******************************************************************/ static long atocolor(const char *s) { long l = atol(s); if (l & ~0xff) pari_err(e_MISC, "invalid 8bit RGB code: %ld", l); return l; } GEN sd_graphcolormap(const char *v, long flag) { char *p, *q; long i, j, l, a, s, *lp; if (v) { pari_sp av = avma; char *t = gp_filter(v); if (*t != '[' || t[strlen(t)-1] != ']') pari_err(e_SYNTAX, "incorrect value for graphcolormap", t, t); for (s = 0, p = t+1, l = 2, a=0; *p; p++) if (*p == '[') { a++; while (*++p != ']') if (!*p || *p == '[') pari_err(e_SYNTAX, "incorrect value for graphcolormap", p, t); } else if (*p == '"') { s += sizeof(long)+1; while (*p && *++p != '"') s++; if (!*p) pari_err(e_SYNTAX, "incorrect value for graphcolormap", p, t); s = (s+sizeof(long)-1) & ~(sizeof(long)-1); } else if (*p == ',') l++; if (l < 4) pari_err(e_MISC, "too few colors (< 4) in graphcolormap"); if (GP_DATA->colormap) pari_free(GP_DATA->colormap); GP_DATA->colormap = (GEN)pari_malloc((l+4*a)*sizeof(long) + s); GP_DATA->colormap[0] = evaltyp(t_VEC)|evallg(l); for (p = t+1, i = 1, lp = GP_DATA->colormap+l; i < l; p++) switch(*p) { case '"': gel(GP_DATA->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(GP_DATA->colormap, i) = lp; lp[0] = evaltyp(t_VECSMALL)|_evallg(4); for (ap[0] = ++p, j=0; *p && *p != ']'; p++) if (*p == ',' && j<2) { *p++ = 0; ap[++j] = p; } while (j<2) ap[++j] = "0"; if (j>2 || *p != ']') { char buf[100]; sprintf(buf, "incorrect value for graphcolormap[%ld]: ", i); pari_err(e_SYNTAX, buf, p, t); } *p = '\0'; lp[1] = atocolor(ap[0]); lp[2] = atocolor(ap[1]); lp[3] = atocolor(ap[2]); lp += 4; break; } case ',': case ']': i++; break; default: pari_err(e_SYNTAX, "incorrect value for graphcolormap", p, t); } set_avma(av); } if (flag == d_RETURN || flag == d_ACKNOWLEDGE) { GEN C = cgetg(lg(GP_DATA->colormap), t_VEC); long i, l = lg(C); for (i = 1; i < l; i++) { GEN c = gel(GP_DATA->colormap, i); gel(C, i) = (typ(c) == t_STR)? gcopy(c): zv_to_ZV(c); } if (flag == d_RETURN) return C; pari_printf(" graphcolormap = %Ps\n", C); } return gnil; } GEN sd_graphcolors(const char *v, long flag) { return sd_intarray(v, flag, &(GP_DATA->graphcolors), "graphcolors"); } GEN sd_plothsizes(const char *v, long flag) { return sd_intarray(v, flag, &(GP_DATA->plothsizes), "plothsizes"); } GEN sd_help(const char *v, long flag) { const char *str; if (v) { if (GP_DATA->secure) pari_err(e_MISC,"[secure mode]: can't modify 'help' default (to %s)",v); if (GP_DATA->help) pari_free((void*)GP_DATA->help); #ifndef _WIN32 GP_DATA->help = path_expand(v); #else GP_DATA->help = pari_strdup(v); #endif } str = GP_DATA->help? GP_DATA->help: "none"; if (flag == d_RETURN) return strtoGENstr(str); if (flag == d_ACKNOWLEDGE) pari_printf(" help = \"%s\"\n", str); return gnil; } static GEN sd_prompt_set(const char *v, long flag, const char *how, char **p) { if (v) { if (*p) free(*p); *p = pari_strdup(v); } if (flag == d_RETURN) return strtoGENstr(*p); if (flag == d_ACKNOWLEDGE) pari_printf(" prompt%s = \"%s\"\n", how, *p); return gnil; } GEN sd_prompt(const char *v, long flag) { return sd_prompt_set(v, flag, "", &(GP_DATA->prompt)); } GEN sd_prompt_cont(const char *v, long flag) { return sd_prompt_set(v, flag, "_cont", &(GP_DATA->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_ulong(v,flag,"echo", &(GP_DATA->echo), 0,2,NULL); } 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)); } GEN sd_psfile(const char *v, long flag) { return sd_string(v, flag, "psfile", ¤t_psfile); } GEN sd_lines(const char *v, long flag) { return sd_ulong(v,flag,"lines",&(GP_DATA->lim_lines), 0,LONG_MAX,NULL); } GEN sd_linewrap(const char *v, long flag) { ulong old = GP_DATA->linewrap, n = GP_DATA->linewrap; GEN z = sd_ulong(v,flag,"linewrap",&n, 0,LONG_MAX,NULL); if (old) { if (!n) resetout(1); } else { if (n) init_linewrap(n); } GP_DATA->linewrap = n; return z; } /* readline-specific defaults */ GEN sd_readline(const char *v, long flag) { const char *msg[] = { "(bits 0x2/0x4 control matched-insert/arg-complete)", NULL}; ulong state = GP_DATA->readline_state; GEN res = sd_ulong(v,flag,"readline", &GP_DATA->readline_state, 0, 7, msg); if (state != GP_DATA->readline_state) (void)sd_toggle(GP_DATA->readline_state? "1": "0", d_SILENT, "readline", &(GP_DATA->use_readline)); return res; } GEN sd_histfile(const char *v, long flag) { char *old = GP_DATA->histfile; GEN r = sd_string(v, flag, "histfile", &GP_DATA->histfile); if (v && !*v) { free(GP_DATA->histfile); GP_DATA->histfile = NULL; } else if (GP_DATA->histfile != old && (!old || strcmp(old,GP_DATA->histfile))) { if (cb_pari_init_histfile) cb_pari_init_histfile(); } return r; } /********************************************************************/ /** **/ /** METACOMMANDS **/ /** **/ /********************************************************************/ void pari_print_version(void) { pari_sp av = avma; char *buf, *ver = what_cc(); const char *kver = pari_kernel_version(); const char *date = paricfg_compiledate, *mt = paricfg_mt_engine; ulong t = pari_mt_nbthreads; pari_center(paricfg_version); buf = stack_malloc(strlen(paricfg_buildinfo) + 2 + strlen(kver)); (void)sprintf(buf, paricfg_buildinfo, kver); pari_center(buf); buf = stack_malloc(128 + strlen(date) + (ver? strlen(ver): 0)); if (ver) (void)sprintf(buf, "compiled: %s, %s", date, ver); else (void)sprintf(buf, "compiled: %s", date); pari_center(buf); if (t > 1) sprintf(buf, "threading engine: %s, nbthreads = %lu",mt,t); else sprintf(buf, "threading engine: %s",mt); pari_center(buf); ver = what_readline(); buf = stack_malloc(strlen(ver) + 64); (void)sprintf(buf, "(readline %s, extended help%s enabled)", ver, has_ext_help()? "": " not"); pari_center(buf); set_avma(av); } static int cmp_epname(void *E, GEN e, GEN f) { (void)E; return strcmp(((entree*)e)->name, ((entree*)f)->name); } /* if fun is set print only closures, else only non-closures * if member is set print only member functions, else only non-members */ static void print_all_user_obj(int fun, int member) { pari_sp av = avma; long i, iL = 0, lL = 1024; GEN L = cgetg(lL+1, t_VECSMALL); entree *ep; for (i = 0; i < functions_tblsz; i++) for (ep = functions_hash[i]; ep; ep = ep->next) if (EpVALENCE(ep) == EpVAR && fun == (typ((GEN)ep->value) == t_CLOSURE)) { const char *f = ep->name; if (member == (f[0] == '_' && f[1] == '.')) { if (iL >= lL) { lL *= 2; L = vecsmall_lengthen(L, lL); } L[++iL] = (long)ep; } } if (iL) { setlg(L, iL+1); gen_sort_inplace(L, NULL, &cmp_epname, NULL); for (i = 1; i <= iL; i++) { ep = (entree*)L[i]; pari_printf("%s =\n %Ps\n\n", ep->name, ep->value); } } set_avma(av); } /* get_sep, removing enclosing quotes */ static char * get_name(const char *s) { char *t = get_sep(s); if (*t == '"') { long n = strlen(t)-1; if (t[n] == '"') { t[n] = 0; t++; } } return t; } static void ack_debug(const char *s, long d) {pari_printf(" debug(\"%s\") = %ld\n",s,d);} static void ack_setdebug(const char *s, long d) {setdebug(s, d); ack_debug(s, d);} static void escape(const char *tch, int ismain) { const char *s = tch; long d; char c; GEN x; switch ((c = *s++)) { case 'w': case 'x': case 'a': case 'b': case 'B': case 'm': { /* history things */ if (c != 'w' && c != 'x') d = get_int(s,0); else { d = atol(s); if (*s == '-') s++; while (isdigit((unsigned char)*s)) s++; } x = pari_get_hist(d); switch (c) { case 'B': /* prettyprinter */ if (prettyp_init()) { pari_flush(); prettyp_GEN(x); pari_flush(); break; } case 'b': /* fall through */ case 'm': matbrute(x, GP_DATA->fmt->format, -1); break; case 'a': brute(x, GP_DATA->fmt->format, -1); break; case 'x': dbgGEN(x, get_int(s, -1)); break; case 'w': s = get_name(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': if (isdigit((unsigned char)*s)) { const char *t = s + 1; if (isdigit((unsigned char)*t)) t++; /* atol(s) < 99 */ t = get_name(t); if (*t) { d = atol(s); ack_setdebug(t, d); break; } } else if (*s == '"' || isalpha((unsigned char)*s)) { char *t = get_name(s); if (t[1] && !isdigit((unsigned char)t[1])) { char *T = t + strlen(t) - 1; if (isdigit((unsigned char)*T)) { if (isdigit((unsigned char)T[-1])) T--; /* < 99 */ d = atol(T); *T = 0; ack_setdebug(get_name(t), d); /* get_name in case of ".." */ } else { x = setdebug(t, -1); ack_debug(t, itos(x)); } } else switch (*t) { case 'm': s++; (void)sd_debugmem(*s? s: NULL,d_ACKNOWLEDGE); break; case 'f': s++; (void)sd_debugfiles(*s? s: NULL,d_ACKNOWLEDGE); break; } break; } (void)sd_debug(*s? s: NULL,d_ACKNOWLEDGE); break; break; case 'h': print_functions_hash(s); break; case 'l': s = get_name(s); if (*s) { if (pari_logfile) { (void)sd_logfile(s,d_ACKNOWLEDGE);break; } (void)sd_logfile(s,d_SILENT); } (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; case 'b' : s++; (void)sd_realbitprecision(*s? s: NULL,d_ACKNOWLEDGE); break; default : (void)sd_realprecision(*s? s: NULL,d_ACKNOWLEDGE); break; } break; case 'q': cb_pari_quit(0); break; case 'r': s = get_name(s); if (!ismain) { (void)gp_read_file(s); break; } switchin(s); if (file_is_binary(pari_infile)) { pari_sp av = avma; int vector; GEN x = readbin(s,pari_infile, &vector); popinfile(); if (!x) pari_err_FILE("input file",s); if (vector) /* many BIN_GEN */ { long i, l = lg(x); pari_warn(warner,"setting %ld history entries", l-1); for (i=1; isimplify)? "0": "1"; (void)sd_simplify(s,d_ACKNOWLEDGE); break; default: pari_err(e_SYNTAX,"unexpected character", tch,tch-1); } } static int chron(const char *s) { if (*s) { /* if "#" or "##" timer metacommand. Otherwise let the parser get it */ const char *t; if (*s == '#') s++; if (*s) return 0; t = gp_format_time(pari_get_histtime(0)); if (pari_mt_nbthreads==1) pari_printf(" *** last result computed in %s.\n", t); else { const char *r = gp_format_time(pari_get_histrtime(0)); pari_printf(" *** last result: cpu time %s, real time %s.\n", t,r); } } else { GP_DATA->chrono ^= 1; (void)sd_timer(NULL,d_ACKNOWLEDGE); } return 1; } /* return 0: can't interpret *buf as a metacommand * 1: did interpret *buf as a metacommand or empty command */ int gp_meta(const char *buf, int ismain) { switch(*buf++) { case '?': gp_help(buf, h_REGULAR); break; case '#': return chron(buf); case '\\': escape(buf, ismain); break; case '\0': break; default: return 0; } return 1; } void pari_breakpoint(void) { if (!pari_last_was_newline()) pari_putc('\n'); closure_err(0); if (cb_pari_break_loop && cb_pari_break_loop(-1)) return; cb_pari_err_recover(e_MISC); } pari-2.17.2/src/language/es.c0000644000175000017500000040437414760123736014336 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*******************************************************************/ /** **/ /** INPUT/OUTPUT SUBROUTINES **/ /** **/ /*******************************************************************/ #ifdef _WIN32 #include "../systems/mingw/pwinver.h" #include #include /* for getpid */ #include #include /* for setmode */ #include "../systems/mingw/mingw.h" #endif #include "paricfg.h" #ifdef HAS_STAT #include #elif defined(HAS_OPENDIR) #include #endif #ifdef HAS_WAITPID # include #endif #include "pari.h" #include "paripriv.h" #include "anal.h" #ifdef __EMSCRIPTEN__ #include "../systems/emscripten/emscripten.h" #endif #define DEBUGLEVEL DEBUGLEVEL_io typedef void (*OUT_FUN)(GEN, pariout_t *, pari_str *); static void bruti_sign(GEN g, pariout_t *T, pari_str *S, int addsign); static void matbruti(GEN g, pariout_t *T, pari_str *S); static void texi_sign(GEN g, pariout_t *T, pari_str *S, int addsign); static void bruti(GEN g, pariout_t *T, pari_str *S) { bruti_sign(g,T,S,1); } static void texi(GEN g, pariout_t *T, pari_str *S) { texi_sign(g,T,S,1); } void pari_ask_confirm(const char *s) { if (!cb_pari_ask_confirm) pari_err(e_MISC,"Can't ask for confirmation. Please define cb_pari_ask_confirm()"); cb_pari_ask_confirm(s); } static char * strip_last_nl(char *s) { ulong l = strlen(s); char *t; if (l && s[l-1] != '\n') return s; if (l>1 && s[l-2] == '\r') l--; t = stack_malloc(l); memcpy(t, s, l-1); t[l-1] = 0; return t; } /********************************************************************/ /** **/ /** INPUT FILTER **/ /** **/ /********************************************************************/ #define ONE_LINE_COMMENT 2 #define MULTI_LINE_COMMENT 1 #define LBRACE '{' #define RBRACE '}' static int in_help(filtre_t *F) { char c; if (!F->buf) return (*F->s == '?'); c = *F->buf->buf; return c? (c == '?'): (*F->s == '?'); } /* Filter F->s into F->t */ static char * filtre0(filtre_t *F) { const char *s = F->s; char c, *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((unsigned char)c)) continue; *t++ = c; switch(c) { case '/': if (*s == '*') { t--; F->in_comment = MULTI_LINE_COMMENT; } break; case '\\': if (!*s) { if (in_help(F)) break; /* '?...\' */ t--; if (!F->more_input) F->more_input = 1; goto END; } if (*s == '\r') s++; /* DOS */ if (*s == '\n') { if (in_help(F)) break; /* '?...\' */ t--; s++; if (!*s) { if (!F->more_input) F->more_input = 1; goto END; } } /* skip \ */ break; case '"': F->in_string = 1; break; case LBRACE: t--; if (F->wait_for_brace) pari_err_IMPL("embedded braces (in parser)"); F->more_input = 2; F->wait_for_brace = 1; break; case RBRACE: if (!F->wait_for_brace) pari_err(e_MISC,"unexpected closing brace"); F->more_input = 0; t--; F->wait_for_brace = 0; break; } } if (t != F->t) /* non empty input */ { c = t[-1]; /* last char */ if (c == '=') { if (!in_help(F)) F->more_input = 2; } else if (! F->wait_for_brace) F->more_input = 0; else if (c == RBRACE) { F->more_input = 0; t--; F->wait_for_brace--;} } END: F->end = t; *t = 0; return F->t; } #undef ONE_LINE_COMMENT #undef MULTI_LINE_COMMENT char * gp_filter(const char *s) { filtre_t T; T.buf = NULL; T.s = s; T.t = (char*)stack_malloc(strlen(s)+1); T.in_string = 0; T.more_input = 0; T.in_comment= 0; T.wait_for_brace = 0; return filtre0(&T); } void init_filtre(filtre_t *F, Buffer *buf) { F->buf = buf; F->in_string = 0; F->in_comment = 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; pari_realloc_ip((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 = (void*)fi; IM.myfgets = (fgets_t)&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 = NULL; while (gp_read_stream_buf(fi, b)) { if (*(b->buf)) { x = readseq(b->buf); break; } } delete_buffer(b); return x; } static GEN gp_read_from_input(input_method* IM, int loop, char *last) { Buffer *b = new_buffer(); GEN x = NULL; filtre_t F; if (last) *last = 0; for (;;) { char *s; init_filtre(&F, b); if (!input_loop(&F, IM)) break; s = b->buf; if (s[0]) { if (gp_meta(s,0)) continue; x = closure_evalres(pari_compile_str(s)); if (last) *last = s[strlen(s) - 1]; } if (!loop) break; } delete_buffer(b); return x; } GEN gp_read_file(const char *s) { GEN x = gnil; FILE *f = switchin(s); if (file_is_binary(f)) { x = readbin(s,f, NULL); if (!x) pari_err_FILE("input file",s); } else { pari_sp av = avma; Buffer *b = new_buffer(); x = gnil; for (;;) { if (!gp_read_stream_buf(f, b)) break; if (*(b->buf)) { set_avma(av); x = readseq(b->buf); } } delete_buffer(b); } popinfile(); return x; } static char* string_gets(char *s, int size, const char **ptr) { /* f is actually a const char** */ const char *in = *ptr; int i; char c; /* Copy from in to s */ for (i = 0; i+1 < size && in[i] != 0;) { s[i] = c = in[i]; i++; if (c == '\n') break; } s[i] = 0; /* Terminating 0 byte */ if (i == 0) return NULL; *ptr += i; return s; } GEN gp_read_str_multiline(const char *s, char *last) { input_method IM; const char *ptr = s; GEN z; IM.file = (void*)(&ptr); IM.myfgets = (fgets_t)&string_gets; IM.getline = &file_input; IM.free = 0; z = gp_read_from_input(&IM, 1, last); return z ? z: gnil; } static void gp_read_str_history(const char *s) { input_method IM; const char *ptr = s; char last = 0; pari_sp av = avma; IM.file = (void*)(&ptr); IM.myfgets = (fgets_t)&string_gets; IM.getline = &file_input; IM.free = 0; for(;ptr[0];) { GEN z; timer_start(GP_DATA->T); walltimer_start(GP_DATA->Tw); pari_set_last_newline(1); z = gp_read_from_input(&IM, 0, &last); pari_alarm(0); if (!pari_last_was_newline()) pari_putc('\n'); if (z) { long t = timer_delay(GP_DATA->T); long r = walltimer_delay(GP_DATA->Tw); if (t && GP_DATA->chrono) { if (pari_mt_nbthreads==1) { pari_puts("time = "); pari_puts(gp_format_time(t)); } else { pari_puts("cpu time = "); pari_puts(gp_format_time(t)); pari_puts(", real time = "); pari_puts(gp_format_time(r)); } pari_puts(".\n"); } if (GP_DATA->simplify) z = simplify_shallow(z); pari_add_hist(z, t, r); if (z != gnil && last!=';') gp_display_hist(pari_nb_hist()); } set_avma(av); parivstack_reset(); } } void gp_embedded_init(long rsize, long vsize) { pari_init(rsize, 1UL<<20); paristack_setsize(rsize, vsize); } long gp_embedded(const char *s) { long err = 0; struct gp_context state; gp_context_save(&state); timer_start(GP_DATA->T); timer_start(GP_DATA->Tw); pari_set_last_newline(1); pari_CATCH(CATCH_ALL) { pari_err_display(pari_err_last()); err_printf("\n"); gp_context_restore(&state); err = 1; } pari_TRY { gp_read_str_history(s); } pari_ENDCATCH; if (!pari_last_was_newline()) pari_putc('\n'); set_avma(pari_mainstack->top); return err; } 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); if (!x) pari_err_FILE("input file",s); } else x = gp_readvec_stream(f); popinfile(); return x; } char * file_getline(Buffer *b, char **s0, input_method *IM) { const ulong MAX = (1UL << 31) - 1; ulong used0, used; **s0 = 0; /* paranoia */ used0 = used = *s0 - b->buf; for(;;) { ulong left = b->len - used, l, read; char *s; /* If little space left, double the buffer size before next read. */ if (left < 512) { fix_buffer(b, b->len << 1); left = b->len - used; *s0 = b->buf + used0; } /* # of chars read by fgets is an int; be careful */ read = minuu(left, MAX); s = b->buf + used; if (! IM->myfgets(s, (int)read, IM->file)) return **s0? *s0: NULL; /* EOF */ l = strlen(s); if (l+1 < read || s[l-1] == '\n') return *s0; /* \n */ used += l; } } /* Read from file (up to '\n' or EOF) and copy at s0 (points in b->buf) */ char * file_input(char **s0, int junk, input_method *IM, filtre_t *F) { (void)junk; return file_getline(F->buf, s0, IM); } static void runaway_close(filtre_t *F) { if (F->in_string) { pari_warn(warner,"run-away string. Closing it"); F->in_string = 0; } if (F->in_comment) { pari_warn(warner,"run-away comment. Closing it"); F->in_comment = 0; } } /* 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)) ) { runaway_close(F); return 0; } /* buffer is not empty, init filter */ F->in_string = 0; F->more_input= 0; F->wait_for_brace = 0; for(;;) { if (GP_DATA->echo == 2) gp_echo_and_log("", strip_last_nl(to_read)); 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) { if (!*(b->buf)) runaway_close(F); break; } } return 1; } /********************************************************************/ /** **/ /** GENERAL PURPOSE PRINTING **/ /** **/ /********************************************************************/ PariOUT *pariOut, *pariErr; static void _fputs(const char *s, FILE *f ) { #ifdef _WIN32 win32_ansi_fputs(s, f); #else fputs(s, f); #endif } static void _putc_log(char c) { if (pari_logfile) (void)putc(c, pari_logfile); } static void _puts_log(const char *s) { FILE *f = pari_logfile; const char *p; if (!f) return; if (pari_logstyle != logstyle_color) while ( (p = strchr(s, '\x1b')) ) { /* skip ANSI color escape sequence */ if ( p!=s ) fwrite(s, 1, p-s, f); s = strchr(p, 'm'); if (!s) return; s++; } fputs(s, f); } static void _flush_log(void) { if (pari_logfile != NULL) (void)fflush(pari_logfile); } static void normalOutC(char c) { putc(c, pari_outfile); _putc_log(c); } static void normalOutS(const char *s) { _fputs(s, pari_outfile); _puts_log(s); } static void normalOutF(void) { fflush(pari_outfile); _flush_log(); } static PariOUT defaultOut = {normalOutC, normalOutS, normalOutF}; static void normalErrC(char c) { putc(c, pari_errfile); _putc_log(c); } static void normalErrS(const char *s) { _fputs(s, pari_errfile); _puts_log(s); } static void normalErrF(void) { fflush(pari_errfile); _flush_log(); } static PariOUT defaultErr = {normalErrC, normalErrS, normalErrF}; /** GENERIC PRINTING **/ void resetout(int initerr) { pariOut = &defaultOut; if (initerr) pariErr = &defaultErr; } void initout(int initerr) { pari_infile = stdin; pari_outfile = stdout; pari_errfile = stderr; resetout(initerr); } static int last_was_newline = 1; static void set_last_newline(char c) { last_was_newline = (c == '\n'); } void out_putc(PariOUT *out, char c) { set_last_newline(c); out->putch(c); } void pari_putc(char c) { out_putc(pariOut, c); } void out_puts(PariOUT *out, const char *s) { if (*s) { set_last_newline(s[strlen(s)-1]); out->puts(s); } } void pari_puts(const char *s) { out_puts(pariOut, s); } int pari_last_was_newline(void) { return last_was_newline; } void pari_set_last_newline(int last) { last_was_newline = last; } void pari_flush(void) { pariOut->flush(); } void err_flush(void) { pariErr->flush(); } static GEN log10_2(void) { return divrr(mplog2(LOWDEFAULTPREC), mplog(utor(10,LOWDEFAULTPREC))); } /* e binary exponent, return exponent in base ten */ static long ex10(long e) { pari_sp av; GEN z; if (e >= 0) { if (e < 1e15) return (long)(e*LOG10_2); av = avma; z = mulur(e, log10_2()); z = floorr(z); e = itos(z); } else /* e < 0 */ { if (e > -1e15) return (long)(-(-e*LOG10_2)-1); av = avma; z = mulsr(e, log10_2()); z = floorr(z); e = itos(z) - 1; } return gc_long(av, e); } static char * zeros(char *b, long nb) { while (nb-- > 0) *b++ = '0'; *b = 0; return b; } /* # of decimal digits, assume l > 0 */ static long numdig(ulong l) { if (l < 100000) { if (l < 100) return (l < 10)? 1: 2; if (l < 10000) return (l < 1000)? 3: 4; return 5; } if (l < 10000000) return (l < 1000000)? 6: 7; if (l < 1000000000) return (l < 100000000)? 8: 9; return 10; } /* let ndig <= 9, x < 10^ndig, write in p[-ndig..-1] the decimal digits of x */ static void utodec(char *p, ulong x, long ndig) { switch(ndig) { case 9: *--p = x % 10 + '0'; x = x/10; case 8: *--p = x % 10 + '0'; x = x/10; case 7: *--p = x % 10 + '0'; x = x/10; case 6: *--p = x % 10 + '0'; x = x/10; case 5: *--p = x % 10 + '0'; x = x/10; case 4: *--p = x % 10 + '0'; x = x/10; case 3: *--p = x % 10 + '0'; x = x/10; case 2: *--p = x % 10 + '0'; x = x/10; case 1: *--p = x % 10 + '0'; x = x/10; } } /* convert abs(x) != 0 to str. Prepend '-' if (sx < 0) */ static char * itostr_sign(GEN x, int sx, long *len) { long l, d; ulong *res = convi(x, &l); /* l 9-digits words (< 10^9) + (optional) sign + \0 */ char *s = (char*)new_chunk(nchar2nlong(l*9 + 1 + 1)), *t = s; if (sx < 0) *t++ = '-'; d = numdig(*--res); t += d; utodec(t, *res, d); while (--l > 0) { t += 9; utodec(t, *--res, 9); } *t = 0; *len = t - s; return s; } /********************************************************************/ /** **/ /** WRITE A REAL NUMBER **/ /** **/ /********************************************************************/ /* 19 digits (if 64 bits, at most 2^60-1) + 1 sign */ static const long MAX_EXPO_LEN = 20; /* write z to buf, inserting '.' at 'point', 0 < point < strlen(z) */ static void wr_dec(char *buf, char *z, long point) { char *s = buf + point; strncpy(buf, z, point); /* integer part */ *s++ = '.'; z += point; while ( (*s++ = *z++) ) /* empty */; } static char * zerotostr(void) { char *s = (char*)new_chunk(1); s[0] = '0'; s[1] = 0; return s; } /* write a real 0 of exponent ex in format f */ static char * real0tostr_width_frac(long width_frac) { char *buf, *s; if (width_frac == 0) return zerotostr(); buf = s = stack_malloc(width_frac + 3); *s++ = '0'; *s++ = '.'; (void)zeros(s, width_frac); return buf; } /* write a real 0 of exponent ex */ static char * real0tostr(long ex, char format, char exp_char, long wanted_dec) { char *buf, *buf0; if (format == 'f') { long width_frac = wanted_dec; if (width_frac < 0) width_frac = (ex >= 0)? 0: (long)(-ex * LOG10_2); return real0tostr_width_frac(width_frac); } else { buf0 = buf = stack_malloc(3 + MAX_EXPO_LEN + 1); *buf++ = '0'; *buf++ = '.'; *buf++ = exp_char; sprintf(buf, "%ld", ex10(ex) + 1); } return buf0; } /* format f, width_frac >= 0: number of digits in fractional part, */ static char * absrtostr_width_frac(GEN x, int width_frac) { long beta, ls, point, lx, sx = signe(x); char *s, *buf; GEN z; if (!sx) return real0tostr_width_frac(width_frac); /* x != 0 */ lx = realprec(x); beta = width_frac; if (beta) /* >= 0 */ { /* z = |x| 10^beta, 10^b = 5^b * 2^b, 2^b goes into exponent */ if (beta > 4e9) lx++; z = mulrr(x, rpowuu(5UL, (ulong)beta, lx+1)); setsigne(z, 1); shiftr_inplace(z, beta); } else z = mpabs(x); z = roundr_safe(z); if (!signe(z)) return real0tostr_width_frac(width_frac); s = itostr_sign(z, 1, &ls); /* ls > 0, number of digits in s */ point = ls - beta; /* position of . in s; <= ls, may be < 0 */ if (point > 0) /* write integer_part.fractional_part */ { /* '.', trailing \0 */ buf = stack_malloc( ls + 1+1 ); if (ls == point) strcpy(buf, s); /* no '.' */ else wr_dec(buf, s, point); } else { /* point <= 0, fractional part must be written */ char *t; /* '0', '.', zeroes, trailing \0 */ buf = t = stack_malloc( 1 + 1 - point + ls + 1 ); *t++ = '0'; *t++ = '.'; t = zeros(t, -point); strcpy(t, s); } return buf; } /* Return t_REAL |x| in floating point format. * Allocate freely, the caller must clean the stack. * FORMAT: E/e (exponential), F/f (floating point), G/g * wanted_dec: number of significant digits to print (all if < 0). */ static char * absrtostr(GEN x, int sp, char FORMAT, long wanted_dec) { const char format = (char)tolower((unsigned char)FORMAT), exp_char = (format == FORMAT)? 'e': 'E'; long beta, ls, point, lx, sx = signe(x), ex = expo(x); char *s, *buf, *buf0; GEN z; if (!sx) return real0tostr(ex, format, exp_char, wanted_dec); /* x != 0 */ lx = realprec(x); if (wanted_dec >= 0) { /* reduce precision if possible */ long w = ndec2prec(wanted_dec); /* digits -> pari precision in words */ if (lx > w) lx = w; /* truncature with guard, no rounding */ } beta = ex10(lx - ex); if (beta) { /* z = |x| 10^beta, 10^b = 5^b * 2^b, 2^b goes into exponent */ if (beta > 0) { if (beta > 18) { lx++; x = rtor(x, lx); } z = mulrr(x, rpowuu(5UL, (ulong)beta, lx+1)); } else { if (beta < -18) { lx++; x = rtor(x, lx); } z = divrr(x, rpowuu(5UL, (ulong)-beta, lx+1)); } setsigne(z, 1); shiftr_inplace(z, beta); } else z = x; z = roundr_safe(z); if (!signe(z)) return real0tostr(ex, format, exp_char, wanted_dec); s = itostr_sign(z, 1, &ls); /* ls > 0, number of digits in s */ if (wanted_dec < 0) wanted_dec = ls; else if (ls > wanted_dec) { beta -= ls - wanted_dec; ls = wanted_dec; if (s[ls] >= '5') /* round up */ { long i; for (i = ls-1; i >= 0; s[i--] = '0') if (++s[i] <= '9') break; if (i < 0) { s[0] = '1'; beta--; } } s[ls] = 0; } /* '.', " E", exponent, trailing \0 */ point = ls - beta; /* position of . in s; < 0 or > 0 */ if (beta <= 0 || format == 'e' || (format == 'g' && point-1 < -4)) { /* e format */ buf0 = buf = stack_malloc(ls+1+2+MAX_EXPO_LEN + 1); wr_dec(buf, s, 1); buf += ls + 1; if (sp) *buf++ = ' '; *buf++ = exp_char; sprintf(buf, "%ld", point-1); } else if (point > 0) /* f format, write integer_part.fractional_part */ { buf0 = buf = stack_malloc(ls+1 + 1); wr_dec(buf, s, point); /* point < ls since beta > 0 */ } else /* f format, point <= 0, write fractional part */ { buf0 = buf = stack_malloc(2-point+ls + 1); *buf++ = '0'; *buf++ = '.'; buf = zeros(buf, -point); strcpy(buf, s); } return buf0; } /* vsnprintf implementation rewritten from snprintf.c to be found at * * http://www.nersc.gov/~scottc/misc/docs/snort-2.1.1-RC1/snprintf_8c-source.html * The original code was * Copyright (C) 1998-2002 Martin Roesch * available under the terms of the GNU GPL version 2 or later. It * was itself adapted from an original version by Patrick Powell. */ /* Modifications for format %Ps: R.Butel IMB/CNRS 2007/12/03 */ /* l = old len, L = new len */ static void str_alloc0(pari_str *S, long l, long L) { if (S->use_stack) S->string = (char*) memcpy(stack_malloc(L), S->string, l); else pari_realloc_ip((void**)&S->string, L); S->cur = S->string + l; S->end = S->string + L; S->size = L; } /* make sure S is large enough to write l further words (<= l * 20 chars). * To avoid automatic extension in between av = avma / set_avma(av) pairs * [ would destroy S->string if (S->use_stack) ] */ static void str_alloc(pari_str *S, long l) { l *= 20; if (S->end - S->cur <= l) str_alloc0(S, S->cur - S->string, S->size + maxss(S->size, l)); } void str_putc(pari_str *S, char c) { *S->cur++ = c; if (S->cur == S->end) str_alloc0(S, S->size, S->size << 1); } void str_init(pari_str *S, int use_stack) { char *s; S->size = 1024; S->use_stack = use_stack; if (S->use_stack) s = (char*)stack_malloc(S->size); else s = (char*)pari_malloc(S->size); *s = 0; S->string = S->cur = s; S->end = S->string + S->size; } void str_puts(pari_str *S, const char *s) { while (*s) str_putc(S, *s++); } static void str_putscut(pari_str *S, const char *s, int cut) { if (cut < 0) str_puts(S, s); else { while (*s && cut-- > 0) str_putc(S, *s++); } } /* lbuf = strlen(buf), len < 0: unset */ static void outpad(pari_str *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(pari_str *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 '+'. Leaves a messy stack if * S->use_stack */ static void fmtnum(pari_str *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_COMPLEX: fmtnum(S, 0, gel(gvalue,1), base, signvalue, ljust,len,zpad); if (gsigne(gel(gvalue,2)) >= 0) str_putc(S, '+'); fmtnum(S, 0, gel(gvalue,2), base, signvalue, ljust,len,zpad); str_putc(S, '*'); str_putc(S, 'I'); return; case t_VEC: str_putc(S, '['); for (i = 1; i < l; i++) { fmtnum(S, 0, gel(gvalue,i), base, signvalue, ljust,len,zpad); if (i < l-1) str_putc(S, ','); } str_putc(S, ']'); return; case t_COL: str_putc(S, '['); for (i = 1; i < l; i++) { fmtnum(S, 0, gel(gvalue,i), base, signvalue, ljust,len,zpad); if (i < l-1) str_putc(S, ','); } str_putc(S, ']'); str_putc(S, '~'); return; case t_MAT: if (l == 1) str_puts(S, "[;]"); else { h = lgcols(gvalue); for (i=1; i 0) caps = 0; else { caps = 1; base = -base; } buf0 = buf = stack_malloc(mxl) + mxl; /* fill from the right */ *--buf = 0; /* trailing \0 */ if (gvalue) { if (base == 10) { long i, l, cnt; ulong *larray = convi(uvalue, &l); larray -= l; for (i = 0; i < l; i++) { cnt = 0; ulvalue = larray[i]; do { *--buf = '0' + ulvalue%10; ulvalue = ulvalue / 10; cnt++; } while (ulvalue); if (i + 1 < l) for (;cnt<9;cnt++) *--buf = '0'; } } else if (base == 16) { long i, l = lgefint(uvalue); GEN up = int_LSW(uvalue); for (i = 2; i < l; i++, up = int_nextW(up)) { ulong ucp = (ulong)*up; long j; for (j=0; j < BITS_IN_LONG/4; j++) { unsigned char cv = ucp & 0xF; *--buf = (caps? "0123456789ABCDEF":"0123456789abcdef")[cv]; ucp >>= 4; if (ucp == 0 && i+1 == l) break; } } /* loop on hex digits in word */ } else if (base == 8) { long i, l = lgefint(uvalue); GEN up = int_LSW(uvalue); ulong rem = 0; int shift = 0; int mask[3] = {0, 1, 3}; for (i = 2; i < l; i++, up = int_nextW(up)) { ulong ucp = (ulong)*up; long j, ldispo = BITS_IN_LONG; if (shift) { /* 0, 1 or 2 */ unsigned char cv = ((ucp & mask[shift]) <<(3-shift)) + rem; *--buf = "01234567"[cv]; ucp >>= shift; ldispo -= shift; }; shift = (shift + 3 - BITS_IN_LONG % 3) % 3; for (j=0; j < BITS_IN_LONG/3; j++) { unsigned char cv = ucp & 0x7; if (ucp == 0 && i+1 == l) { rem = 0; break; }; *--buf = "01234567"[cv]; ucp >>= 3; ldispo -= 3; rem = ucp; if (ldispo < 3) break; } } /* loop on hex digits in word */ if (rem) *--buf = "01234567"[rem]; } } else { /* not a gvalue, thus a standard integer */ do { *--buf = (caps? "0123456789ABCDEF":"0123456789abcdef")[ulvalue % (unsigned)base ]; ulvalue /= (unsigned)base; } while (ulvalue); } /* leading 0 if octal and alternate # form */ if (caps && base == 8) *--buf = '0'; lbuf = (buf0 - buf) - 1; END: outpad(S, buf, lbuf, signvalue, ljust, len, zpad); if (!S->use_stack) set_avma(av); } static GEN v_get_arg(pari_str *S, GEN arg_vector, int *index, const char *save_fmt) { if (*index >= lg(arg_vector)) { if (!S->use_stack) pari_free(S->string); pari_err(e_MISC, "missing arg %d for printf format '%s'", *index, save_fmt); } return gel(arg_vector, (*index)++); } static int dosign(int blank, int plus) { if (plus) return('+'); if (blank) return(' '); return 0; } /* x * 10 + 'digit whose char value is ch'. Do not check for overflow */ static int shift_add(int x, int ch) { if (x < 0) /* was unset */ x = ch - '0'; else x = x*10 + ch - '0'; return x; } static long get_sigd(GEN gvalue, char ch, int maxwidth) { long e; if (maxwidth < 0) return nbits2ndec(precreal); switch(ch) { case 'E': case 'e': return maxwidth+1; case 'F': case 'f': e = gexpo(gvalue); if (e == -(long)HIGHEXPOBIT) return 0; e = ex10(e); if (e < 0) e = 0; return e + 1 + maxwidth; } return maxwidth? maxwidth: 1; /* 'g', 'G' */ } static void fmtreal(pari_str *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_COMPLEX: fmtreal(S, gel(gvalue,1), space, signvalue, FORMAT, maxwidth, ljust,len,zpad); if (gsigne(gel(gvalue,2)) >= 0) str_putc(S, '+'); fmtreal(S, gel(gvalue,2), space, signvalue, FORMAT, maxwidth, ljust,len,zpad); str_putc(S, 'I'); return; case t_VEC: str_putc(S, '['); for (i = 1; i < l; i++) { fmtreal(S, gel(gvalue,i), space, signvalue, FORMAT, maxwidth, ljust,len,zpad); if (i < l-1) str_putc(S, ','); } str_putc(S, ']'); return; case t_COL: str_putc(S, '['); for (i = 1; i < l; i++) { fmtreal(S, gel(gvalue,i), space, signvalue, FORMAT, maxwidth, ljust,len,zpad); if (i < l-1) str_putc(S, ','); } str_putc(S, ']'); str_putc(S, '~'); return; case t_MAT: if (l == 1) str_puts(S, "[;]"); else { h = lgcols(gvalue); for (j=1; juse_stack) free(S->string); pari_err(e_MISC,"impossible conversion to t_REAL: %Ps",gvalue); } } if ((FORMAT == 'f' || FORMAT == 'F') && maxwidth >= 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); if (!S->use_stack) set_avma(av); } static long gtolong_OK(GEN x) { switch(typ(x)) { case t_INT: case t_REAL: case t_FRAC: return 1; case t_COMPLEX: return gequal0(gel(x,2)) && gtolong_OK(gel(x,1)); case t_QUAD: return gequal0(gel(x,3)) && gtolong_OK(gel(x,2)); } return 0; } /* 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. * Appent output to the pari_str S, which must be initialized; clean if * !S->use_stack, else leaves objects of stack. */ static void str_arg_vprintf(pari_str *S, 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; while ((ch = *fmt++) != '\0') { switch(ch) { case '%': ljust = zpad = 0; len = maxwidth = -1; GENflag = longflag = pointflag = 0; print_plus = print_blank = with_sharp = 0; nextch: ch = *fmt++; switch(ch) { case 0: pari_err(e_MISC, "printf: end of format"); /*------------------------------------------------------------------------ -- flags ------------------------------------------------------------------------*/ case '-': ljust = 1; goto nextch; case '+': print_plus = 1; goto nextch; case '#': with_sharp = 1; goto nextch; case ' ': print_blank = 1; goto nextch; case '0': /* appears as a flag: set zero padding */ if (len < 0 && !pointflag) { zpad = '0'; goto nextch; } /* else part of a field width or precision */ /* fall through */ /*------------------------------------------------------------------------ -- maxwidth or precision ------------------------------------------------------------------------*/ case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (pointflag) maxwidth = shift_add(maxwidth, ch); else len = shift_add(len, ch); goto nextch; case '*': { int *t = pointflag? &maxwidth: &len; if (arg_vector) { gvalue = v_get_arg(S, arg_vector, &index, save_fmt); if (!gtolong_OK(gvalue) && !S->use_stack) pari_free(S->string); *t = (int)gtolong(gvalue); } else *t = va_arg(args, int); goto nextch; } case '.': if (pointflag) pari_err(e_MISC, "two '.' in conversion specification"); pointflag = 1; goto nextch; /*------------------------------------------------------------------------ -- length modifiers ------------------------------------------------------------------------*/ case 'l': if (GENflag) pari_err(e_MISC, "P/l length modifiers in the same conversion"); #if !defined(_WIN64) if (longflag) pari_err_IMPL( "ll length modifier in printf"); #endif longflag = 1; goto nextch; case 'P': if (longflag) pari_err(e_MISC, "P/l length modifiers in the same conversion"); if (GENflag) pari_err(e_MISC, "'P' length modifier appears twice"); GENflag = 1; goto nextch; case 'h': /* dummy: va_arg promotes short into int */ goto nextch; /*------------------------------------------------------------------------ -- conversions ------------------------------------------------------------------------*/ case 'u': /* not a signed conversion: print_(blank|plus) ignored */ #define get_num_arg() \ if (arg_vector) { \ lvalue = 0; \ gvalue = v_get_arg(S, 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(S, 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; pari_sp av = avma; if (arg_vector) { gvalue = v_get_arg(S, 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) strvalue = GENtostr_unquoted(gvalue); fmtstr(S, strvalue, ljust, len, maxwidth); if (!S->use_stack) set_avma(av); break; } case 'c': gvalue = NULL; if (arg_vector) gvalue = v_get_arg(S, arg_vector, &index, save_fmt); else if (GENflag) gvalue = va_arg(args,GEN); else { ch = va_arg(args, int); str_putc(S, ch); break; } if (!gtolong_OK(gvalue) && !S->use_stack) free(S->string); str_putc(S, (int)gtolong(gvalue)); 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(S, 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); if (!S->use_stack) set_avma(av); break; } default: if (!S->use_stack) free(S->string); pari_err(e_MISC, "invalid conversion or specification %c in format `%s'", ch, save_fmt); } /* second switch on ch */ break; default: str_putc(S, ch); break; } /* first switch on ch */ } /* while loop on ch */ *S->cur = 0; } 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); } /* s must be able to store 12 chars (including final \0) */ char * term_get_color(char *s, long n) { long c[3], a; if (!s) s = stack_malloc(COLOR_LEN); if (disable_color) { *s = 0; return s; } if (n == c_NONE || (a = gp_colors[n]) == c_NONE) strcpy(s, "\x1b[0m"); /* 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, "\x1b[%ld;%ldm", c[0], c[1]); else { if (c[2]<8) c[2] += 40; else c[2] += 92; sprintf(s, "\x1b[%ld;%ld;%ldm", 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] == '\x1b' && t[1] == '[') { /* skip ANSI escape sequence */ t += 2; while (*t && *t++ != 'm') /* empty */; continue; } t++; len++; } return len; } #undef COLOR_LEN /********************************************************************/ /** **/ /** PRINTING BASED ON SCREEN WIDTH **/ /** **/ /********************************************************************/ #undef larg /* problems with SCO Unix headers (ioctl_arg) */ #ifdef HAS_TIOCGWINSZ # ifdef __sun # include # endif # include #endif static int term_width_intern(void) { #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) { #ifdef _WIN32 return win32_terminal_height(); #endif #ifdef HAS_TIOCGWINSZ { struct winsize s; if (!(GP_DATA->flags & (gpd_EMACS|gpd_TEXMACS)) && !ioctl(0, TIOCGWINSZ, &s)) return s.ws_row; } #endif { char *str; if ((str = os_getenv("LINES"))) return atoi(str); } #ifdef __EMX__ { int scrsize[2]; _scrsize(scrsize); return scrsize[1]; } #endif return 0; } #define DFT_TERM_WIDTH 80 #define DFT_TERM_HEIGHT 20 int term_width(void) { int n = term_width_intern(); return (n>1)? n: DFT_TERM_WIDTH; } int term_height(void) { int n = term_height_intern(); return (n>1)? n: DFT_TERM_HEIGHT; } static ulong col_index; /* output string wrapped after MAX_WIDTH characters (for gp -test) */ static void putc_lw(char c) { if (c == '\n') col_index = 0; else if (col_index >= GP_DATA->linewrap) { normalOutC('\n'); col_index = 1; } else col_index++; normalOutC(c); } static void puts_lw(const char *s) { while (*s) putc_lw(*s++); } static PariOUT pariOut_lw= {putc_lw, puts_lw, normalOutF}; void init_linewrap(long w) { col_index=0; GP_DATA->linewrap=w; pariOut=&pariOut_lw; } 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); memcpy(t, s - past, past); t[past] = 0; } /* suffix (past arrow) */ t = str; if (!past) *t++ = ' '; future = CONTEXT_LEN - past; strncpy(t, s, future); t[future] = 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; } } /* not stack clean */ static char * stack_GENtostr_fun(GEN x, pariout_t *T, OUT_FUN out) { pari_str S; str_init(&S, 1); out(x, T, &S); *S.cur = 0; return S.string; } /* same but remove quotes "" around t_STR */ static char * stack_GENtostr_fun_unquoted(GEN x, pariout_t *T, OUT_FUN out) { return (typ(x)==t_STR)? GSTR(x): stack_GENtostr_fun(x, T, out); } /* stack-clean: pari-malloc'ed */ static char * GENtostr_fun(GEN x, pariout_t *T, OUT_FUN out) { pari_sp av = avma; pari_str S; str_init(&S, 0); out(x, T, &S); *S.cur = 0; set_avma(av); return S.string; } /* returns a malloc-ed string, which should be freed after usage */ /* Returns pari_malloc()ed string */ char * GENtostr(GEN x) { return GENtostr_fun(x, GP_DATA->fmt, get_fun(GP_DATA->fmt->prettyp)); } char * GENtoTeXstr(GEN x) { return GENtostr_fun(x, GP_DATA->fmt, &texi); } char * GENtostr_unquoted(GEN x) { return stack_GENtostr_fun_unquoted(x, GP_DATA->fmt, &bruti); } /* alloc-ed on PARI stack */ char * GENtostr_raw(GEN x) { return stack_GENtostr_fun(x,GP_DATA->fmt,&bruti); } 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; } /********************************************************************/ /** **/ /** WRITE AN INTEGER **/ /** **/ /********************************************************************/ char * itostr(GEN x) { long sx = signe(x), l; return sx? itostr_sign(x, sx, &l): zerotostr(); } /* x != 0 t_INT, write abs(x) to S */ static void str_absint(pari_str *S, GEN x) { pari_sp av; long l; str_alloc(S, lgefint(x)); /* careful ! */ av = avma; str_puts(S, itostr_sign(x, 1, &l)); set_avma(av); } #define putsigne_nosp(S, x) str_putc(S, (x>0)? '+' : '-') #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 semicolon_sp(T,S) ((T)->sp? str_puts(S, "; "): str_putc(S, ';')) #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(pari_str *S, ulong e) { if (e == 0) str_putc(S, '0'); else { char buf[21], *p = buf + numberof(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(pari_str *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, pari_str *S, GEN g) { long i, l; str_puts(S, "Vecsmall(["); l = lg(g); for (i=1; i 0) ? '+' : '-'; } static void blancs(long nb) { while (nb-- > 0) pari_putc(' '); } /* write an "address" */ static void str_addr(pari_str *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,valser=%ld):", vsigne(x), varn(x), lg(x)-2, valser(x)); else if (tx == t_LIST) { pari_printf("(subtyp=%ld,lmax=%ld):", list_typ(x), 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%s):", closure_arity(x), closure_is_variadic(x)?"+":""); for (i=1; iname); dbg_addr((ulong)ep); pari_printf(": hash = %ld [%ld]\n", ep->hash % functions_tblsz, ep->hash); pari_printf(" menu = %2ld, code = %-10s", ep->menu, ep->code? ep->code: "NULL"); if (ep->next) { pari_printf("next = %s ",(ep->next)->name); 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((unsigned char)*s) || *s == '$') { m = functions_tblsz-1; n = atol(s); if (*s=='$') n = m; if (mnext) print_entree(ep); } return; } if (is_keyword_char(*s)) { ep = is_entry(s); if (!ep) pari_err(e_MISC,"no such function"); print_entree(ep); 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); 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; sprintf(buf,"t%d",(int)v); return buf; } static void do_append(char **sp, char c, char *last, int count) { if (*sp + count > last) pari_err(e_MISC, "TeX variable name too long"); while (count--) *(*sp)++ = c; } static char * get_texvar(long v, char *buf, unsigned int len) { entree *ep = varentries[v]; char *t = buf, *e = buf + len - 1; const char *s; if (!ep) pari_err(e_MISC, "this object uses debugging variables"); s = ep->name; if (strlen(s) >= len) pari_err(e_MISC, "TeX variable name too long"); while (isalpha((unsigned char)*s)) *t++ = *s++; *t = 0; if (isdigit((unsigned char)*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(); pari_sp top = pari_mainstack->top, bot = pari_mainstack->bot; nu = (top-avma)/sizeof(long); l = pari_mainstack->size/sizeof(long); pari_printf("\n Top : %lx Bottom : %lx Current stack : %lx\n", top, bot, avma); pari_printf(" Used : %ld long words (%ld K)\n", 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); set_avma(av); } /* 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_POL: for (i=lg(g)-1; i>1; i--) if (!isnull(gel(g,i))) return 0; return 1; } return 0; } /* 0 coeff to be omitted in t_POL ? */ static int isnull_for_pol(GEN g) { switch(typ(g)) { case t_INTMOD: return !signe(gel(g,2)); case t_POLMOD: return isnull_for_pol(gel(g,2)); default: return isnull(g); } } /* return 1 or -1 if g is 1 or -1, 0 otherwise*/ static long isone(GEN g) { long i; switch (typ(g)) { case t_INT: return (signe(g) && is_pm1(g))? signe(g): 0; case t_FFELT: return FF_equal1(g); case t_COMPLEX: return isnull(gel(g,2))? isone(gel(g,1)): 0; case t_QUAD: return isnull(gel(g,3))? isone(gel(g,2)): 0; case t_FRAC: case t_RFRAC: return isone(gel(g,1)) * isone(gel(g,2)); case t_POL: if (!signe(g)) return 0; for (i=lg(g)-1; i>2; i--) if (!isnull(gel(g,i))) return 0; return isone(gel(g,2)); } return 0; } /* if g is a "monomial", return its sign, 0 otherwise */ static long isfactor(GEN g) { long i,deja,sig; switch(typ(g)) { case t_INT: case t_REAL: return (signe(g)<0)? -1: 1; case t_FRAC: case t_RFRAC: return isfactor(gel(g,1)); case t_FFELT: return isfactor(FF_to_FpXQ_i(g)); case t_COMPLEX: if (isnull(gel(g,1))) return isfactor(gel(g,2)); if (isnull(gel(g,2))) return isfactor(gel(g,1)); return 0; case t_PADIC: return !signe(gel(g,4)); case t_QUAD: if (isnull(gel(g,2))) return isfactor(gel(g,3)); if (isnull(gel(g,3))) return isfactor(gel(g,2)); return 0; case t_POL: deja = 0; sig = 1; for (i=lg(g)-1; i>1; i--) if (!isnull_for_pol(gel(g,i))) { if (deja) return 0; sig=isfactor(gel(g,i)); deja=1; } return sig? sig: 1; case t_SER: for (i=lg(g)-1; i>1; i--) if (!isnull(gel(g,i))) return 0; return 1; case t_CLOSURE: 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(pari_str *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(pari_str *S, long e) { if (e != 1) { str_putc(S, '^'); str_long(S, e); } } /* v^e */ static void VpowE(pari_str *S, const char *v, long e) { str_puts(S, v); wrexpo(S,e); } static void texVpowE(pari_str *S, const char *v, long e) { str_puts(S, v); texexpo(S,e); } static void monome(pari_str *S, const char *v, long e) { if (e) VpowE(S, v, e); else str_putc(S, '1'); } static void texnome(pari_str *S, const char *v, long e) { if (e) texVpowE(S, v, e); else str_putc(S, '1'); } /* ( a ) */ static void paren(pariout_t *T, pari_str *S, GEN a) { str_putc(S, '('); bruti(a,T,S); str_putc(S, ')'); } static void texparen(pariout_t *T, pari_str *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(pari_str *S, const char *v, long d) { if (d) { str_puts(S, "\\*"); texnome(S,v,d); } } static void times_monome(pari_str *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, pari_str *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, pari_str *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, pari_str *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, pari_str *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, pari_str *S) { (void)T; str_long(S, (long)g); } static void quote_string(pari_str *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, pari_str *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_precontext(GEN g, pari_str *S, long tex) { if (lg(g)<8 || lg(gel(g,7))==1) return; else { long i, n = closure_arity(g); str_puts(S,"("); for(i=1; i<=n; i++) { str_puts(S,"v"); if (tex) str_puts(S,"_{"); str_ulong(S,i); if (tex) str_puts(S,"}"); if (i < n) str_puts(S,","); } str_puts(S,")->"); } } static void print_context(GEN g, pariout_t *T, pari_str *S, long tex) { GEN str = closure_get_text(g); if (lg(g)<8 || lg(gel(g,7))==1) return; if (typ(str)==t_VEC && lg(gel(closure_get_dbg(g),3)) >= 2) { GEN v = closure_get_frame(g), d = gmael(closure_get_dbg(g),3,1); long i, l = lg(v), n=0; for(i=1; iname); if (!isintzero(vi)) { str_putc(S,'='); if (tex) texi(gel(v,l-i),T,S); else bruti(gel(v,l-i),T,S); } if (--n) str_putc(S,','); } str_puts(S,");"); } else { GEN v = closure_get_frame(g); long i, l = lg(v), n = closure_arity(g); str_puts(S,"("); for(i=1; i<=n; i++) { str_puts(S,"v"); if (tex) str_puts(S,"_{"); str_ulong(S,i); if (tex) str_puts(S,"}"); str_puts(S,","); } for(i=1; isp, (char)toupper((unsigned char)T->format), T->sigd) ); set_avma(av); break; } case t_INTMOD: case t_POLMOD: str_puts(S, "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); v = cxq_init(g, tg, &a, &b, buf); 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 = valser(g); l = lg(g)-2; if (l) { /* See normalizeser(): Mod(0,2)*x^i*(1+O(x)), has valser = i+1 */ if (l == 1 && !signe(g) && isexactzero(gel(g,2))) i--; /* hack: we want g[i] = coeff of degree i */ l += i; g -= i-2; wr_lead_monome(T,S,gel(g,i),v,i,addsign); while (++i < l) { a = gel(g,i); if (!isnull_for_pol(a)) wr_monome(T,S,a,v,i); } sp_sign_sp(T,S,1); } str_puts(S, "O("); VpowE(S, v, i); str_putc(S, ')'); break; case t_PADIC: { GEN p = gel(g,2); pari_sp av, av0; char *ev; str_alloc(S, (precp(g)+1) * lgefint(p)); /* careful! */ av0 = avma; ev = itostr(p); av = avma; i = valp(g); l = precp(g)+i; g = gel(g,4); for (; i=7) { GEN str = closure_get_text(g); if (typ(str)==t_STR) { print_precontext(g, S, 0); str_puts(S, GSTR(str)); print_context(g, T, S, 0); } else { str_putc(S,'('); str_puts(S,GSTR(gel(str,1))); str_puts(S,")->"); print_context(g, T, S, 0); str_puts(S,GSTR(gel(str,2))); } } else { str_puts(S,"{\""); str_puts(S,GSTR(closure_get_code(g))); str_puts(S,"\","); wr_vecsmall(T,S,closure_get_oper(g)); str_putc(S,','); bruti(gel(g,4),T,S); str_putc(S,','); bruti(gel(g,5),T,S); str_putc(S,'}'); } break; case t_INFINITY: str_puts(S, inf_get_sign(g) == 1? "+oo": "-oo"); break; case t_MAT: { void (*print)(GEN,long,long,pariout_t *,pari_str *); r = lg(g); if (r==1) { str_puts(S, "[;]"); return; } l = lgcols(g); if (l==1) { mat0n(S, r-1); return; } print = (typ(gel(g,1)) == t_VECSMALL)? print_coef: print_gcoef; if (l==2) { str_puts(S, "Mat("); if (r == 2 && (print != print_gcoef || typ(gcoeff(g,1,1)) != t_MAT)) { print(g, 1, 1,T, S); str_putc(S, ')'); return; } } str_putc(S, '['); for (i=1; iuse_stack)*/ av2 = avma; str_init(&str, 1); for (j=1; j w) { pad = NULL; break; } /* doesn't fit, abort padding */ } set_avma(av2); } for (i=1; i 0) str_putc(S, ' '); } print(gcoeff(g,i,j),T,S); if (juse_stack) set_avma(av); } /********************************************************************/ /** **/ /** TeX OUTPUT **/ /** **/ /********************************************************************/ /* this follows bruti_sign */ static void texi_sign(GEN g, pariout_t *T, pari_str *S, int addsign) { long tg,i,j,l,r; GEN a,b; const char *v; char buf[67]; if (print_0_or_pm1(g, S, addsign)) return; tg = typ(g); switch(tg) { case t_INT: case t_REAL: case t_QFB: bruti_intern(g, T, S, addsign); break; case t_INTMOD: case t_POLMOD: texi(gel(g,2),T,S); str_puts(S, " mod "); texi(gel(g,1),T,S); break; case t_FRAC: if (addsign && isfactor(gel(g,1)) < 0) str_putc(S, '-'); str_puts(S, "\\frac{"); texi_sign(gel(g,1),T,S,0); str_puts(S, "}{"); texi_sign(gel(g,2),T,S,0); str_puts(S, "}"); break; case t_RFRAC: str_puts(S, "\\frac{"); texi(gel(g,1),T,S); /* too complicated otherwise */ str_puts(S, "}{"); texi(gel(g,2),T,S); str_puts(S, "}"); break; case t_FFELT: bruti_sign(FF_to_FpXQ_i(g),T,S,addsign); break; case t_COMPLEX: case t_QUAD: r = (tg==t_QUAD); v = cxq_init(g, tg, &a, &b, buf); if (isnull(a)) { wr_lead_texnome(T,S,b,v,1,addsign); break; } texi_sign(a,T,S,addsign); if (!isnull(b)) wr_texnome(T,S,b,v,1); break; case t_POL: v = get_texvar(varn(g), buf, sizeof(buf)); /* hack: we want g[i] = coeff of degree i. */ i = degpol(g); g += 2; while (isnull(gel(g,i))) i--; wr_lead_texnome(T,S,gel(g,i),v,i,addsign); while (i--) { a = gel(g,i); if (!isnull_for_pol(a)) wr_texnome(T,S,a,v,i); } break; case t_SER: v = get_texvar(varn(g), buf, sizeof(buf)); i = valser(g); if (lg(g)-2) { /* hack: we want g[i] = coeff of degree i. */ l = i + lg(g)-2; g -= i-2; wr_lead_texnome(T,S,gel(g,i),v,i,addsign); while (++i < l) { a = gel(g,i); if (!isnull_for_pol(a)) wr_texnome(T,S,a,v,i); } str_puts(S, "+ "); } str_puts(S, "O("); texnome(S,v,i); str_putc(S, ')'); break; case t_PADIC: { GEN p = gel(g,2); pari_sp av; char *ev; str_alloc(S, (precp(g)+1) * lgefint(p)); /* careful! */ av = avma; i = valp(g); l = precp(g)+i; g = gel(g,4); ev = itostr(p); for (; i=6) { GEN str = closure_get_text(g); if (typ(str)==t_STR) { print_precontext(g, S, 1); str_puts(S, GSTR(str)); print_context(g, T, S ,1); } else { str_putc(S,'('); str_puts(S,GSTR(gel(str,1))); str_puts(S,")\\mapsto "); print_context(g, T, S ,1); str_puts(S,GSTR(gel(str,2))); } } else { str_puts(S,"\\{\""); str_puts(S,GSTR(closure_get_code(g))); str_puts(S,"\","); texi(gel(g,3),T,S); str_putc(S,','); texi(gel(g,4),T,S); str_putc(S,','); texi(gel(g,5),T,S); str_puts(S,"\\}"); } break; case t_INFINITY: str_puts(S, inf_get_sign(g) == 1? "+\\infty": "-\\infty"); break; case t_MAT: { str_puts(S, "\\pmatrix{\n "); r = lg(g); if (r>1) { OUT_FUN print = (typ(gel(g,1)) == t_VECSMALL)? prints: texi; l = lgcols(g); for (i=1; iformat = f; T->sigd = sigd; T->sp = sp; } static void gen_output_fun(GEN x, pariout_t *T, OUT_FUN out) { pari_sp av = avma; pari_puts( stack_GENtostr_fun(x,T,out) ); set_avma(av); } void fputGEN_pariout(GEN x, pariout_t *T, FILE *out) { pari_sp av = avma; char *s = stack_GENtostr_fun(x, T, get_fun(T->prettyp)); if (*s) { set_last_newline(s[strlen(s)-1]); fputs(s, out); } set_avma(av); } 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 gen_output(GEN x) { gen_output_fun(x, GP_DATA->fmt, get_fun(GP_DATA->fmt->prettyp)); pari_putc('\n'); pari_flush(); } 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(); } /*******************************************************************/ /** FILES **/ /*******************************************************************/ /* to cache '~' expansion */ static char *homedir; /* last file read successfully from try_name() */ static THREAD char *last_filename; /* stack of temporary files (includes all infiles + some output) */ static THREAD pariFILE *last_tmp_file; /* stack of "permanent" (output) files */ static THREAD pariFILE *last_file; typedef struct gpfile { const char *name; FILE *fp; int type; long serial; } gpfile; static THREAD gpfile *gp_file; static THREAD pari_stack s_gp_file; static THREAD long gp_file_serial; #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 (DEBUGLEVEL) if (strcmp(name,"stdin") || DEBUGLEVEL > 9) 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 (DEBUGLEVEL) if (strcmp(f->name,"stdin") || DEBUGLEVEL > 9) err_printf("I/O: closing file %s (code %d) \n",f->name,f->type); pari_free(f); } void pari_fclose(pariFILE *f) { if (f->next) (f->next)->prev = f->prev; else if (f == last_tmp_file) last_tmp_file = f->prev; else if (f == last_file) last_file = f->prev; if (f->prev) (f->prev)->next = f->next; pari_kill_file(f); } static pariFILE * pari_open_file(FILE *f, const char *s, const char *mode) { if (!f) pari_err_FILE("requested file", s); if (DEBUGLEVEL) if (strcmp(s,"stdin") || DEBUGLEVEL > 9) err_printf("I/O: opening file %s (mode %s)\n", s, mode); return newfile(f,s,0); } pariFILE * pari_fopen_or_fail(const char *s, const char *mode) { return pari_open_file(fopen(s, mode), s, mode); } pariFILE * pari_fopen(const char *s, const char *mode) { FILE *f = fopen(s, mode); return f? pari_open_file(f, s, mode): NULL; } void pari_fread_chars(void *b, size_t n, FILE *f) { if (fread(b, sizeof(char), n, f) < n) pari_err_FILE("input file [fread]", "FILE*"); } /* FIXME: HAS_FDOPEN & allow standard open() flags */ #ifdef UNIX /* open tmpfile s (a priori for writing) avoiding symlink attacks */ pariFILE * pari_safefopen(const char *s, const char *mode) { long fd = open(s, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR); if (fd == -1) pari_err(e_MISC,"tempfile %s already exists",s); return pari_open_file(fdopen(fd, mode), s, mode); } #else pariFILE * pari_safefopen(const char *s, const char *mode) { return pari_fopen_or_fail(s, mode); } #endif void pari_unlink(const char *s) { if (unlink(s)) pari_warn(warner, "I/O: can\'t remove file %s", s); else if (DEBUGLEVEL) err_printf("I/O: removed file %s\n", s); } /* 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 tmp_restore(pariFILE *F) { pariFILE *f = last_tmp_file; int first = 1; 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 (DEBUGLEVEL>1) { first = 0; err_printf("restoring pari_infile to %s\n", f->name); } break; } } if (!f) { pari_infile = stdin; if (DEBUGLEVEL>1 && (!first || DEBUGLEVEL > 9)) { first = 0; err_printf("gp_context_restore: restoring pari_infile to stdin\n"); } } if (!first && DEBUGLEVEL>1) err_printf("done\n"); } void filestate_save(struct pari_filestate *file) { file->file = last_tmp_file; file->serial = gp_file_serial; } static void filestate_close(long serial) { long i; for (i = 0; i < s_gp_file.n; i++) if (gp_file[i].fp && gp_file[i].serial >= serial) gp_fileclose(i); gp_file_serial = serial; } void filestate_restore(struct pari_filestate *file) { tmp_restore(file->file); filestate_close(file->serial); } static void kill_file_stack(pariFILE **s) { pariFILE *f = *s; while (f) { pariFILE *t = f->prev; pari_kill_file(f); *s = f = t; /* have to update *s in case of ^C */ } } void killallfiles(void) { kill_file_stack(&last_tmp_file); pari_infile = stdin; } void pari_init_homedir(void) { homedir = NULL; } void pari_close_homedir(void) { if (homedir) pari_free(homedir); } void pari_init_files(void) { last_filename = NULL; last_tmp_file = NULL; last_file=NULL; pari_stack_init(&s_gp_file, sizeof(*gp_file), (void**)&gp_file); gp_file_serial = 0; } void pari_thread_close_files(void) { popinfile(); /* look for leaks */ kill_file_stack(&last_file); if (last_filename) pari_free(last_filename); kill_file_stack(&last_tmp_file); filestate_close(-1); pari_stack_delete(&s_gp_file); } void pari_close_files(void) { if (pari_logfile) { fclose(pari_logfile); pari_logfile = NULL; } pari_infile = stdin; } static int ok_pipe(FILE *f) { if (DEBUGLEVEL) err_printf("I/O: checking output pipe...\n"); pari_CATCH(CATCH_ALL) { return 0; } pari_TRY { int i; fprintf(f,"\n\n"); fflush(f); for (i=1; i<1000; i++) fprintf(f," \n"); fprintf(f,"\n"); fflush(f); } pari_ENDCATCH; return 1; } pariFILE * try_pipe(const char *cmd, int fl) { #ifndef HAVE_PIPES pari_err(e_ARCH,"pipes"); return NULL;/*LCOV_EXCL_LINE*/ #else FILE *file; const char *f; VOLATILE int flag = fl; # ifdef __EMX__ if (_osmode == DOS_MODE) /* no pipes under DOS */ { pari_sp av = avma; char *s; if (flag & mf_OUT) pari_err(e_ARCH,"pipes"); f = pari_unique_filename("pipe"); s = stack_malloc(strlen(cmd)+strlen(f)+4); sprintf(s,"%s > %s",cmd,f); file = system(s)? NULL: fopen(f,"r"); flag |= mf_FALSE; pari_free(f); set_avma(av); } else # endif { file = (FILE *) popen(cmd, (flag & mf_OUT)? "w": "r"); if (flag & mf_OUT) { if (!ok_pipe(file)) return NULL; flag |= mf_PERM; } f = cmd; } if (!file) pari_err(e_MISC,"[pipe:] '%s' failed",cmd); return newfile(file, f, mf_PIPE|flag); #endif } char * os_getenv(const char *s) { #ifdef HAS_GETENV return getenv(s); #else (void) s; return NULL; #endif } GEN gp_getenv(const char *s) { char *t = os_getenv(s); return t?strtoGENstr(t):gen_0; } /* FIXME: HAS_GETPWUID */ #if defined(UNIX) || defined(__EMX__) #include #include /* user = "": use current uid */ char * pari_get_homedir(const char *user) { struct passwd *p; char *dir = NULL; if (!*user) { if (homedir) dir = homedir; else { p = getpwuid(geteuid()); if (p) { dir = p->pw_dir; homedir = pari_strdup(dir); /* cache result */ } } } else { p = getpwnam(user); if (p) dir = p->pw_dir; /* warn, but don't kill session on startup (when expanding path) */ if (!dir) pari_warn(warner,"can't expand ~%s", user? user: ""); } return dir; } #else char * pari_get_homedir(const char *user) { (void) user; return NULL; } #endif /*******************************************************************/ /** **/ /** GP STANDARD INPUT AND OUTPUT **/ /** **/ /*******************************************************************/ #ifdef HAS_STAT static int is_dir_stat(const char *name) { struct stat buf; if (stat(name, &buf)) return 0; return S_ISDIR(buf.st_mode); } #elif defined(HAS_OPENDIR) /* slow, but more portable than stat + S_ISDIR */ static int is_dir_opendir(const char *name) { DIR *d = opendir(name); if (d) { (void)closedir(d); return 1; } return 0; } #endif /* Does name point to a directory? */ int pari_is_dir(const char *name) { #ifdef HAS_STAT return is_dir_stat(name); #elif defined(HAS_OPENDIR) return is_dir_opendir(name); #else (void) name; return 0; #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 { char *user = pari_strndup(s, t - s); dir = pari_get_homedir(user); pari_free(user); } if (!dir) return pari_strdup(s); ret = (char*)pari_malloc(strlen(dir) + strlen(t) + 1); sprintf(ret,"%s%s",dir,t); return ret; } /* expand environment variables in str, return a malloc'ed buffer * assume no \ remain and str can be freed */ static char * _expand_env(char *str) { long i, l, len = 0, xlen = 16, xnum = 0; char *s = str, *s0 = s; char **x = (char **)pari_malloc(xlen * sizeof(char*)); while (*s) { char *env; if (*s != '$') { s++; continue; } l = s - s0; if (l) { x[xnum++] = pari_strndup(s0, l); len += l; } if (xnum > xlen - 3) /* need room for possibly two more elts */ { xlen <<= 1; pari_realloc_ip((void**)&x, xlen * sizeof(char*)); } s0 = ++s; /* skip $ */ while (is_keyword_char(*s)) s++; l = s - s0; env = pari_strndup(s0, l); s0 = os_getenv(env); if (!s0) pari_warn(warner,"undefined environment variable: %s",env); else { l = strlen(s0); if (l) { x[xnum++] = pari_strndup(s0,l); len += l; } } pari_free(env); s0 = s; } l = s - s0; if (l) { x[xnum++] = pari_strndup(s0,l); len += l; } s = (char*)pari_malloc(len+1); *s = 0; for (i = 0; i < xnum; i++) { (void)strcat(s, x[i]); pari_free(x[i]); } pari_free(str); pari_free(x); return s; } char * path_expand(const char *s) { #ifdef _WIN32 char *ss, *p; ss = pari_strdup(s); for (p = ss; *p != 0; ++p) if (*p == '\\') *p = '/'; p = _expand_env(_path_expand(ss)); pari_free(ss); return p; #else return _expand_env(_path_expand(s)); #endif } #ifdef HAS_STRFTIME # include void strftime_expand(const char *s, char *buf, long max) { time_t t; BLOCK_SIGINT_START t = time(NULL); (void)strftime(buf,max,s,localtime(&t)); BLOCK_SIGINT_END } #else void strftime_expand(const char *s, char *buf, long max) { strcpy(buf,s); } #endif /* name is a malloc'ed (existing) filename. Accept it as new pari_infile * (unzip if needed). */ static pariFILE * pari_get_infile(const char *name, FILE *file) { #ifdef ZCAT long l = strlen(name); const char *end = name + l-1; if (l > 2 && (!strncmp(end-1,".Z",2) #ifdef GNUZCAT || !strncmp(end-2,".gz",3) #endif )) { /* compressed file (compress or gzip) */ char *cmd = stack_malloc(strlen(ZCAT) + l + 4); sprintf(cmd,"%s \"%s\"",ZCAT,name); fclose(file); return try_pipe(cmd, mf_IN); } #endif return newfile(file, name, mf_IN); } pariFILE * pari_fopengz(const char *s) { pari_sp av = avma; char *name; long l; FILE *f = fopen(s, "r"); pariFILE *pf; if (f) return pari_get_infile(s, f); #ifdef __EMSCRIPTEN__ if (pari_is_dir(pari_datadir)) { pari_emscripten_wget(s); f = fopen(s, "r"); if (f) return pari_get_infile(s, f); } #endif l = strlen(s); name = stack_malloc(l + 3 + 1); strcpy(name, s); (void)sprintf(name + l, ".gz"); f = fopen(name, "r"); pf = f ? pari_get_infile(name, f): NULL; set_avma(av); return pf; } static FILE* try_open(char *s) { if (!pari_is_dir(s)) return fopen(s, "r"); pari_warn(warner,"skipping directory %s",s); return NULL; } void forpath_init(forpath_t *T, gp_path *path, const char *s) { T->s = s; T->ls = strlen(s); T->dir = path->dirs; } char * forpath_next(forpath_t *T) { char *t, *dir = T->dir[0]; if (!dir) return NULL; /* done */ /* room for dir + '/' + s + '\0' */ t = (char*)pari_malloc(strlen(dir) + T->ls + 2); if (!t) return NULL; /* can't happen but kills a warning */ sprintf(t,"%s/%s", dir, T->s); T->dir++; return t; } /* If a file called "name" exists (possibly after appending ".gp") * record it in the file_stack (as a pipe if compressed). * name is malloc'ed, we free it before returning */ static FILE * try_name(char *name) { pari_sp av = avma; char *s = name; FILE *file = try_open(name); if (!file) { /* try appending ".gp" to name */ s = stack_malloc(strlen(name)+4); sprintf(s, "%s.gp", name); file = try_open(s); } if (file) { if (! last_tmp_file) { /* empty file stack, record this name */ if (last_filename) pari_free(last_filename); last_filename = pari_strdup(s); } file = pari_infile = pari_get_infile(s,file)->file; } pari_free(name); set_avma(av); return file; } static FILE * switchin_last(void) { char *s = last_filename; FILE *file; if (!s) pari_err(e_MISC,"You never gave me anything to read!"); file = try_open(s); if (!file) pari_err_FILE("input file",s); return pari_infile = pari_get_infile(s,file)->file; } /* return 1 if s starts by '/' or './' or '../' */ static int path_is_absolute(char *s) { #ifdef _WIN32 if( (*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z') ) { return *(s+1) == ':'; } #endif if (*s == '/') return 1; if (*s++ != '.') return 0; if (*s == '/') return 1; if (*s++ != '.') return 0; return *s == '/'; } /* If name = "", re-read last file */ FILE * switchin(const char *name) { FILE *f; char *s; if (!*name) return switchin_last(); s = path_expand(name); /* if s is an absolute path, don't use dir_list */ if (path_is_absolute(s)) { if ((f = try_name(s))) return f; } else { char *t; forpath_t T; forpath_init(&T, GP_DATA->path, s); while ( (t = forpath_next(&T)) ) if ((f = try_name(t))) { pari_free(s); return f; } pari_free(s); } pari_err_FILE("input file",name); return NULL; /*LCOV_EXCL_LINE*/ } static int is_magic_ok(FILE *f); static FILE * switchout_get_FILE(const char *name) { FILE* f; /* only for ordinary files (to avoid blocking on pipes). */ if (pari_is_file(name)) { f = fopen(name, "r"); if (f) { int magic = is_magic_ok(f); fclose(f); if (magic) pari_err_FILE("binary output file [ use writebin ! ]", name); } } f = fopen(name, "a"); if (!f) pari_err_FILE("output file",name); return f; } void switchout(const char *name) { if (name) pari_outfile = switchout_get_FILE(name); else if (pari_outfile != stdout) { fclose(pari_outfile); pari_outfile = stdout; } } /*******************************************************************/ /** **/ /** SYSTEM, READSTR/EXTERNSTR/EXTERN **/ /** **/ /*******************************************************************/ static void check_secure(const char *s) { if (GP_DATA->secure) pari_err(e_MISC, "[secure mode]: system commands not allowed\nTried to run '%s'",s); } long gpsystem(const char *s) { int x = -1; #ifdef HAS_SYSTEM check_secure(s); x = system(s); if (x < 0) pari_err(e_MISC, "system(\"%s\") failed", s); #if (defined(WIFEXITED)&&defined(WEXITSTATUS)) x = WIFEXITED(x)? WEXITSTATUS(x): -1; /* POSIX */ # endif #else pari_err(e_ARCH,"system"); #endif return (long)x; } static GEN get_lines(FILE *F) { pari_sp av = avma; long i, nz = 16; GEN z = cgetg(nz + 1, t_VEC); Buffer *b = new_buffer(); input_method IM; IM.myfgets = (fgets_t)&fgets; IM.file = (void*)F; for(i = 1;;) { char *s = b->buf, *e; if (!file_getline(b, &s, &IM)) break; if (i > nz) { nz <<= 1; z = vec_lengthen(z, nz); } e = s + strlen(s)-1; if (*e == '\n') *e = 0; gel(z,i++) = strtoGENstr(s); } delete_buffer(b); setlg(z, i); return gerepilecopy(av, z); } GEN externstr(const char *s) { pariFILE *F; GEN z; check_secure(s); F = try_pipe(s, mf_IN); z = get_lines(F->file); pari_fclose(F); return z; } GEN gpextern(const char *s) { pariFILE *F; GEN z; check_secure(s); F = try_pipe(s, mf_IN); z = gp_read_stream(F->file); pari_fclose(F); return z ? z : gnil; } GEN readstr(const char *s) { GEN z = get_lines(switchin(s)); popinfile(); return z; } /*******************************************************************/ /** **/ /** I/O IN BINARY FORM **/ /** **/ /*******************************************************************/ static void pari_fread_longs(void *a, size_t c, FILE *d) { if (fread(a,sizeof(long),c,d) < c) pari_err_FILE("input file [fread]", "FILE*"); } static void _fwrite(const void *a, size_t b, size_t c, FILE *d) { if (fwrite(a,b,c,d) < c) pari_err_FILE("output file [fwrite]", "FILE*"); } static void _lfwrite(const void *a, size_t b, FILE *c) { _fwrite(a,sizeof(long),b,c); } static void _cfwrite(const void *a, size_t b, FILE *c) { _fwrite(a,sizeof(char),b,c); } enum { BIN_GEN, NAM_GEN, VAR_GEN, RELINK_TABLE }; static long rd_long(FILE *f) { long L; pari_fread_longs(&L, 1UL, f); return L; } static void wr_long(long L, FILE *f) { _lfwrite(&L, 1UL, f); } /* append x to file f */ static void wrGEN(GEN x, FILE *f) { GENbin *p = copy_bin_canon(x); size_t L = p->len; wr_long(L,f); if (L) { wr_long((long)p->x,f); wr_long((long)p->base,f); _lfwrite(GENbinbase(p), L,f); } pari_free((void*)p); } static void wrstr(const char *s, FILE *f) { size_t L = strlen(s)+1; wr_long(L,f); _cfwrite(s, L, f); } static char * rdstr(FILE *f) { size_t L = (size_t)rd_long(f); char *s; if (!L) return NULL; s = (char*)pari_malloc(L); pari_fread_chars(s, L, f); return s; } static void writeGEN(GEN x, FILE *f) { fputc(BIN_GEN,f); wrGEN(x, f); } static void writenamedGEN(GEN x, const char *s, FILE *f) { fputc(x ? NAM_GEN : VAR_GEN,f); wrstr(s, f); if (x) wrGEN(x, f); } /* read a GEN from file f */ static GEN rdGEN(FILE *f) { size_t L = (size_t)rd_long(f); GENbin *p; if (!L) return gen_0; p = (GENbin*)pari_malloc(sizeof(GENbin) + L*sizeof(long)); p->len = L; p->x = (GEN)rd_long(f); p->base = (GEN)rd_long(f); p->rebase = &shiftaddress_canon; pari_fread_longs(GENbinbase(p), L,f); return bin_copy(p); } /* read a binary object in file f. Set *ptc to the object "type": * BIN_GEN: an anonymous GEN x; return x. * NAM_GEN: a named GEN x, with name v; set 'v to x (changevalue) and return x * VAR_GEN: a name v; create the (unassigned) variable v and return gnil * RELINK_TABLE: a relinking table for gen_relink(), to replace old adresses * in * the original session by new incarnations in the current session. * H is the current relinking table * */ static GEN readobj(FILE *f, int *ptc, hashtable *H) { int c = fgetc(f); GEN x = NULL; switch(c) { case BIN_GEN: x = rdGEN(f); if (H) gen_relink(x, H); break; case NAM_GEN: case VAR_GEN: { char *s = rdstr(f); if (!s) pari_err(e_MISC,"malformed binary file (no name)"); if (c == NAM_GEN) { x = rdGEN(f); if (H) gen_relink(x, H); err_printf("setting %s\n",s); changevalue(varentries[fetch_user_var(s)], x); } else { pari_var_create(fetch_entry(s)); x = gnil; } break; } case RELINK_TABLE: x = rdGEN(f); break; case EOF: break; default: pari_err(e_MISC,"unknown code in readobj"); } *ptc = c; return x; } #define MAGIC "\020\001\022\011-\007\020" /* ^P^A^R^I-^G^P */ #ifdef LONG_IS_64BIT # define ENDIAN_CHECK 0x0102030405060708L #else # define ENDIAN_CHECK 0x01020304L #endif static const long BINARY_VERSION = 1; /* since 2.2.9 */ static int is_magic_ok(FILE *f) { pari_sp av = avma; size_t L = strlen(MAGIC); char *s = stack_malloc(L); return gc_int(av, fread(s,1,L, f) == L && strncmp(s,MAGIC,L) == 0); } 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 r, c = fgetc(f); ungetc(c,f); r = (c != EOF && isprint((unsigned char)c) == 0 && isspace((unsigned char)c) == 0); #ifdef _WIN32 if (r) { setmode(fileno(f), _O_BINARY); rewind(f); } #endif return r; } void writebin(const char *name, GEN x) { FILE *f = fopen(name,"rb"); pari_sp av = avma; GEN V; int already = f? 1: 0; if (f) { int ok = check_magic(name,f); fclose(f); if (!ok) pari_err_FILE("binary output file",name); } f = fopen(name,"ab"); if (!f) pari_err_FILE("binary output file",name); if (!already) write_magic(f); V = copybin_unlink(x); if (lg(gel(V,1)) > 1) { fputc(RELINK_TABLE,f); wrGEN(V, f); } if (x) writeGEN(x,f); else { long v, maxv = pari_var_next(); for (v=0; vvalue,ep->name,f); } } set_avma(av); fclose(f); } /* read all objects in f. If f contains BIN_GEN that would be silently ignored * [i.e f contains more than one objet, not all of them 'named GENs'], return * them all in a vector and set 'vector'. */ GEN readbin(const char *name, FILE *f, int *vector) { pari_sp av = avma; hashtable *H = NULL; pari_stack s_obj; GEN obj, x, y; int cy; if (vector) *vector = 0; if (!check_magic(name,f)) return NULL; pari_stack_init(&s_obj, sizeof(GEN), (void**)&obj); /* HACK: push codeword so as to be able to treat s_obj.data as a t_VEC */ pari_stack_pushp(&s_obj, (void*) (evaltyp(t_VEC)|_evallg(1))); x = gnil; while ((y = readobj(f, &cy, H))) { x = y; switch(cy) { case BIN_GEN: pari_stack_pushp(&s_obj, (void*)y); break; case RELINK_TABLE: if (H) hash_destroy(H); H = hash_from_link(gel(y,1),gel(y,2), 0); } } if (H) hash_destroy(H); switch(s_obj.n) /* >= 1 */ { case 1: break; /* nothing but the codeword */ case 2: x = gel(obj,1); break; /* read a single BIN_GEN */ default: /* more than one BIN_GEN */ setlg(obj, s_obj.n); if (DEBUGLEVEL) pari_warn(warner,"%ld unnamed objects read. Returning then in a vector", s_obj.n - 1); x = gerepilecopy(av, obj); if (vector) *vector = 1; } pari_stack_delete(&s_obj); return x; } /*******************************************************************/ /** **/ /** GP I/O **/ /** **/ /*******************************************************************/ /* print a vector of GENs, in output context 'out', using 'sep' as a * separator between sucessive entries [ NULL = no separator ]*/ static void str_print0(pari_str *S, const char *sep, GEN g, long flag) { pari_sp av = avma; OUT_FUN f = get_fun(flag); long i, l = lg(g); for (i = 1; i < l; i++) { GEN x = gel(g,i); if (typ(x) == t_STR) str_puts(S, GSTR(x)); else f(x, GP_DATA->fmt, S); if (sep && i+1 < l) str_puts(S, sep); if (!S->use_stack) set_avma(av); } *(S->cur) = 0; } void out_print0(PariOUT *out, const char *sep, GEN g, long flag) { pari_sp av = avma; pari_str S; str_init(&S,1); str_print0(&S, sep, g, flag); str_putc(&S,'\n'); *(S.cur) = 0; out_puts(out, S.string); set_avma(av); } void out_print1(PariOUT *out, const char *sep, GEN g, long flag) { pari_sp av = avma; pari_str S; str_init(&S,1); str_print0(&S, sep, g, flag); out_puts(out, S.string); set_avma(av); } /* see print0(). Returns pari_malloc()ed string */ char * RgV_to_str(GEN g, long flag) { pari_str S; str_init(&S,0); str_print0(&S, NULL, g, flag); return S.string; } static GEN Str_fun(GEN g, long flag) { char *t = RgV_to_str(g, flag); GEN z = strtoGENstr(t); pari_free(t); return z; } GEN Str(GEN g) { return Str_fun(g, f_RAW); } GEN strtex(GEN g) { return Str_fun(g, f_TEX); } GEN strexpand(GEN g) { char *s = RgV_to_str(g, f_RAW), *t = path_expand(s); GEN z = strtoGENstr(t); pari_free(t); pari_free(s); return z; } /* display s, followed by the element of g */ char * pari_sprint0(const char *s, GEN g, long flag) { pari_str S; str_init(&S, 0); str_puts(&S, s); str_print0(&S, NULL, g, flag); return S.string; } static void print0_file(FILE *out, GEN g, long flag) { pari_sp av = avma; pari_str S; str_init(&S, 1); str_print0(&S, NULL, g, flag); fputs(S.string, out); set_avma(av); } static void printfl_0(GEN g, long flag) { out_print0(pariOut, NULL, g, flag); } static void printfl_1(GEN g, long flag) { out_print1(pariOut, NULL, g, flag); } void printsep(const char *s, GEN g) { out_print0(pariOut, s, g, f_RAW); pari_flush(); } void printsep1(const char *s, GEN g) { out_print1(pariOut, s, g, f_RAW); pari_flush(); } static char * sm_dopr(const char *fmt, GEN arg_vector, va_list args) { pari_str s; str_init(&s, 0); str_arg_vprintf(&s, fmt, arg_vector, args); return s.string; } char * pari_vsprintf(const char *fmt, va_list ap) { return sm_dopr(fmt, NULL, ap); } /* dummy needed to pass an empty va_list to sm_dopr */ static char * dopr_arg_vector(GEN arg_vector, const char* fmt, ...) { va_list ap; char *s; va_start(ap, fmt); s = sm_dopr(fmt, arg_vector, ap); va_end(ap); return s; } /* GP only */ void printf0(const char *fmt, GEN args) { char *s = dopr_arg_vector(args, fmt); pari_puts(s); pari_free(s); pari_flush(); } /* GP only */ GEN strprintf(const char *fmt, GEN args) { char *s = dopr_arg_vector(args, fmt); GEN z = strtoGENstr(s); pari_free(s); return z; } void out_vprintf(PariOUT *out, const char *fmt, va_list ap) { char *s = pari_vsprintf(fmt, ap); out_puts(out, s); pari_free(s); } void pari_vprintf(const char *fmt, va_list ap) { out_vprintf(pariOut, fmt, ap); } void err_printf(const char* fmt, ...) { va_list args; va_start(args, fmt); out_vprintf(pariErr,fmt,args); va_end(args); } /* 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); } GEN gvsprintf(const char *fmt, va_list ap) { char *s = pari_vsprintf(fmt, ap); GEN z = strtoGENstr(s); pari_free(s); return z; } char * pari_sprintf(const char *fmt, ...) /* variadic version of strprintf */ { char *s; va_list ap; va_start(ap, fmt); s = pari_vsprintf(fmt, ap); va_end(ap); return s; } void str_printf(pari_str *S, const char *fmt, ...) { va_list ap; va_start(ap, fmt); str_arg_vprintf(S, fmt, NULL, ap); va_end(ap); } char * stack_sprintf(const char *fmt, ...) { char *s, *t; va_list ap; va_start(ap, fmt); s = pari_vsprintf(fmt, ap); va_end(ap); t = stack_strdup(s); pari_free(s); return t; } GEN gsprintf(const char *fmt, ...) /* variadic version of gvsprintf */ { GEN s; va_list ap; va_start(ap, fmt); s = gvsprintf(fmt, ap); va_end(ap); return s; } /* variadic version of fprintf0. FIXME: fprintf0 not yet available */ void pari_vfprintf(FILE *file, const char *fmt, va_list ap) { char *s = pari_vsprintf(fmt, ap); fputs(s, file); pari_free(s); } void pari_fprintf(FILE *file, const char *fmt, ...) { va_list ap; va_start(ap, fmt); pari_vfprintf(file, fmt, ap); va_end(ap); } void print (GEN g) { printfl_0(g, f_RAW); pari_flush(); } void printp (GEN g) { printfl_0(g, f_PRETTYMAT); pari_flush(); } void printtex(GEN g) { printfl_0(g, f_TEX); pari_flush(); } void print1 (GEN g) { printfl_1(g, f_RAW); pari_flush(); } void error0(GEN g) { if (lg(g)==2 && typ(gel(g,1))==t_ERROR) pari_err(0, gel(g,1)); else pari_err(e_USER, g); } void warning0(GEN g) { pari_warn(warnuser, g); } static void wr_check(const char *t) { if (GP_DATA->secure) { char *msg = pari_sprintf("[secure mode]: about to write to '%s'",t); pari_ask_confirm(msg); pari_free(msg); } } /* write to file s */ static void wr(const char *s, GEN g, long flag, int addnl) { char *t = path_expand(s); FILE *out; wr_check(t); out = switchout_get_FILE(t); print0_file(out, g, flag); if (addnl) fputc('\n', out); fflush(out); if (fclose(out)) pari_warn(warnfile, "close", t); pari_free(t); } void write0 (const char *s, GEN g) { wr(s, g, f_RAW, 1); } void writetex(const char *s, GEN g) { wr(s, g, f_TEX, 1); } void write1 (const char *s, GEN g) { wr(s, g, f_RAW, 0); } void gpwritebin(const char *s, GEN x) { char *t = path_expand(s); wr_check(t); writebin(t, x); pari_free(t); } /*******************************************************************/ /** **/ /** HISTORY HANDLING **/ /** **/ /*******************************************************************/ /* history management function: * p > 0, called from %p or %#p * p <= 0, called from %` or %#` (|p| backquotes, possibly 0) */ static gp_hist_cell * history(long p) { gp_hist *H = GP_DATA->hist; ulong t = H->total, s = H->size; gp_hist_cell *c; if (!t) pari_err(e_MISC,"The result history is empty"); if (p <= 0) p += t; /* count |p| entries starting from last */ if (p <= 0 || p <= (long)(t - s) || (ulong)p > t) { long pmin = (long)(t - s) + 1; if (pmin <= 0) pmin = 1; pari_err(e_MISC,"History result %%%ld not available [%%%ld-%%%lu]", p,pmin,t); } c = H->v + ((p-1) % s); if (!c->z) pari_err(e_MISC,"History result %%%ld has been deleted (histsize changed)", p); return c; } GEN pari_get_hist(long p) { return history(p)->z; } long pari_get_histtime(long p) { return history(p)->t; } long pari_get_histrtime(long p) { return history(p)->r; } GEN pari_histtime(long p) { return mkvec2s(history(p)->t, history(p)->r); } void pari_add_hist(GEN x, long time, long rtime) { gp_hist *H = GP_DATA->hist; ulong i = H->total % H->size; H->total++; guncloneNULL(H->v[i].z); H->v[i].t = time; H->v[i].r = rtime; H->v[i].z = gclone(x); } ulong pari_nb_hist(void) { return GP_DATA->hist->total; } /*******************************************************************/ /** **/ /** TEMPORARY FILES **/ /** **/ /*******************************************************************/ #ifndef R_OK # define R_OK 4 # define W_OK 2 # define X_OK 1 # define F_OK 0 #endif #ifdef __EMX__ #include static int unix_shell(void) { char *base, *sh = getenv("EMXSHELL"); if (!sh) { sh = getenv("COMSPEC"); if (!sh) return 0; } base = _getname(sh); return (stricmp (base, "cmd.exe") && stricmp (base, "4os2.exe") && stricmp (base, "command.com") && stricmp (base, "4dos.com")); } #endif /* check if s has rwx permissions for us */ static int pari_is_rwx(const char *s) { /* FIXME: HAS_ACCESS */ #if defined(UNIX) || defined (__EMX__) return access(s, R_OK | W_OK | X_OK) == 0; #else (void) s; return 1; #endif } #if defined(UNIX) || defined (__EMX__) #include #include static int pari_file_exists(const char *s) { int id = open(s, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR); return id < 0 || close(id); } static int pari_dir_exists(const char *s) { return mkdir(s, 0777); } #elif defined(_WIN32) static int pari_file_exists(const char *s) { return GetFileAttributesA(s) != ~0UL; } static int pari_dir_exists(const char *s) { return mkdir(s); } #else static int pari_file_exists(const char *s) { return 0; } static int pari_dir_exists(const char *s) { return 0; } #endif static char * env_ok(const char *s) { char *t = os_getenv(s); if (t && !pari_is_rwx(t)) { pari_warn(warner,"%s is set (%s), but is not writable", s,t); t = NULL; } if (t && !pari_is_dir(t)) { pari_warn(warner,"%s is set (%s), but is not a directory", s,t); t = NULL; } return t; } static const char* pari_tmp_dir(void) { char *s; s = env_ok("GPTMPDIR"); if (s) return s; s = env_ok("TMPDIR"); if (s) return s; #if defined(_WIN32) || defined(__EMX__) s = env_ok("TMP"); if (s) return s; s = env_ok("TEMP"); if (s) return s; #endif #if defined(UNIX) || defined(__EMX__) if (pari_is_rwx("/tmp")) return "/tmp"; if (pari_is_rwx("/var/tmp")) return "/var/tmp"; #endif return "."; } /* loop through 26^2 variants [suffix 'aa' to 'zz'] */ static int get_file(char *buf, int test(const char *), const char *suf) { char c, d, *end = buf + strlen(buf) - 1; if (suf) end -= strlen(suf); for (d = 'a'; d <= 'z'; d++) { end[-1] = d; for (c = 'a'; c <= 'z'; c++) { *end = c; if (! test(buf)) return 1; if (DEBUGLEVEL) err_printf("I/O: file %s exists!\n", buf); } } return 0; } #if defined(__EMX__) || 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 /* s truncated to 8 chars, suf possibly NULL */ static char * init_unique(const char *s, const char *suf) { const char *pre = pari_tmp_dir(); char *buf, salt[64]; size_t lpre, lsalt, lsuf; #ifdef UNIX sprintf(salt,"-%ld-%ld", (long)getuid(), (long)getpid()); #else sprintf(salt,"-%ld", (long)time(NULL)); #endif lsuf = suf? strlen(suf): 0; lsalt = strlen(salt); lpre = strlen(pre); /* room for prefix + '/' + s + salt + suf + '\0' */ buf = (char*) pari_malloc(lpre + 1 + 8 + lsalt + lsuf + 1); strcpy(buf, pre); if (buf[lpre-1] != '/') { (void)strcat(buf, "/"); lpre++; } #if defined(__EMX__) || defined(_WIN32) swap_slash(buf); #endif sprintf(buf + lpre, "%.8s%s", s, salt); if (lsuf) strcat(buf, suf); if (DEBUGLEVEL) 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_suffix(const char *s, const char *suf) { char *buf = init_unique(s, suf); if (pari_file_exists(buf) && !get_file(buf, pari_file_exists, suf)) pari_err(e_MISC,"couldn't find a suitable name for a tempfile (%s)",s); return buf; } char* pari_unique_filename(const char *s) { return pari_unique_filename_suffix(s, NULL); } /* 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, NULL); if (pari_dir_exists(buf) && !get_file(buf, pari_dir_exists, NULL)) pari_err(e_MISC,"couldn't find a suitable name for a tempdir (%s)",s); return buf; } static long get_free_gp_file(void) { long i, l = s_gp_file.n; for (i=0; i= s_gp_file.n || !gp_file[n].fp) pari_err_FILEDESC(s, n); } static long new_gp_file(const char *s, FILE *f, int t) { long n; n = get_free_gp_file(); gp_file[n].name = pari_strdup(s); gp_file[n].fp = f; gp_file[n].type = t; gp_file[n].serial = gp_file_serial++; if (DEBUGLEVEL) err_printf("fileopen:%ld (%ld)\n", n, gp_file[n].serial); return n; } #if defined(ZCAT) && defined(HAVE_PIPES) static long check_compress(const char *name) { long l = strlen(name); const char *end = name + l-1; if (l > 2 && (!strncmp(end-1,".Z",2) #ifdef GNUZCAT || !strncmp(end-2,".gz",3) #endif )) { /* compressed file (compress or gzip) */ char *cmd = stack_malloc(strlen(ZCAT) + l + 4); sprintf(cmd,"%s \"%s\"",ZCAT,name); return gp_fileextern(cmd); } return -1; } #endif long gp_fileopen(char *s, char *mode) { FILE *f; if (mode[0]==0 || mode[1]!=0) pari_err_TYPE("fileopen",strtoGENstr(mode)); switch (mode[0]) { case 'r': #if defined(ZCAT) && defined(HAVE_PIPES) { long n = check_compress(s); if (n >= 0) return n; } #endif f = fopen(s, "r"); if (!f) pari_err_FILE("requested file", s); return new_gp_file(s, f, mf_IN); case 'w': case 'a': wr_check(s); f = fopen(s, mode[0]=='w' ? "w": "a"); if (!f) pari_err_FILE("requested file", s); return new_gp_file(s, f, mf_OUT); default: pari_err_TYPE("fileopen",strtoGENstr(mode)); return -1; /* LCOV_EXCL_LINE */ } } long gp_fileextern(char *s) { #ifndef HAVE_PIPES pari_err(e_ARCH,"pipes"); return NULL;/*LCOV_EXCL_LINE*/ #else FILE *f; check_secure(s); f = popen(s, "r"); if (!f) pari_err(e_MISC,"[pipe:] '%s' failed",s); return new_gp_file(s,f, mf_PIPE); #endif } void gp_fileclose(long n) { check_gp_file("fileclose", n); if (DEBUGLEVEL) err_printf("fileclose(%ld)\n",n); if (gp_file[n].type == mf_PIPE) pclose(gp_file[n].fp); else fclose(gp_file[n].fp); pari_free((void*)gp_file[n].name); gp_file[n].name = NULL; gp_file[n].fp = NULL; gp_file[n].type = mf_FALSE; gp_file[n].serial = -1; while (s_gp_file.n > 0 && !gp_file[s_gp_file.n-1].fp) s_gp_file.n--; } void gp_fileflush(long n) { check_gp_file("fileflush", n); if (DEBUGLEVEL) err_printf("fileflush(%ld)\n",n); if (gp_file[n].type == mf_OUT) (void)fflush(gp_file[n].fp); } void gp_fileflush0(GEN gn) { long i; if (gn) { if (typ(gn) != t_INT) pari_err_TYPE("fileflush",gn); gp_fileflush(itos(gn)); } else for (i = 0; i < s_gp_file.n; i++) if (gp_file[i].fp && gp_file[i].type == mf_OUT) gp_fileflush(i); } GEN gp_fileread(long n) { Buffer *b; FILE *fp; GEN z; int t; check_gp_file("fileread", n); t = gp_file[n].type; if (t!=mf_IN && t!=mf_PIPE) pari_err_FILEDESC("fileread",n); fp = gp_file[n].fp; b = new_buffer(); while(1) { if (!gp_read_stream_buf(fp, b)) { delete_buffer(b); return gen_0; } if (*(b->buf)) break; } z = strtoGENstr(b->buf); delete_buffer(b); return z; } void gp_filewrite(long n, const char *s) { FILE *fp; check_gp_file("filewrite", n); if (gp_file[n].type!=mf_OUT) pari_err_FILEDESC("filewrite",n); fp = gp_file[n].fp; fputs(s, fp); fputc('\n',fp); } void gp_filewrite1(long n, const char *s) { FILE *fp; check_gp_file("filewrite1", n); if (gp_file[n].type!=mf_OUT) pari_err_FILEDESC("filewrite1",n); fp = gp_file[n].fp; fputs(s, fp); } GEN gp_filereadstr(long n) { Buffer *b; char *s, *e; GEN z; int t; input_method IM; check_gp_file("filereadstr", n); t = gp_file[n].type; if (t!=mf_IN && t!=mf_PIPE) pari_err_FILEDESC("fileread",n); b = new_buffer(); IM.myfgets = (fgets_t)&fgets; IM.file = (void*) gp_file[n].fp; s = b->buf; if (!file_getline(b, &s, &IM)) { delete_buffer(b); return gen_0; } e = s + strlen(s)-1; if (*e == '\n') *e = 0; z = strtoGENstr(s); delete_buffer(b); return z; } /*******************************************************************/ /** **/ /** INSTALL **/ /** **/ /*******************************************************************/ #ifdef HAS_DLOPEN #include /* see try_name() */ static void * try_dlopen(const char *s, int flag) { void *h = dlopen(s, flag); pari_free((void*)s); return h; } /* like dlopen, but using default(sopath) */ static void * gp_dlopen(const char *name, int flag) { void *handle; char *s; if (!name) return dlopen(NULL, flag); s = path_expand(name); /* if sopath empty or path is absolute, use dlopen */ if (!GP_DATA || *(GP_DATA->sopath->PATH)==0 || path_is_absolute(s)) return try_dlopen(s, flag); else { forpath_t T; char *t; forpath_init(&T, GP_DATA->sopath, s); while ( (t = forpath_next(&T)) ) { if ( (handle = try_dlopen(t,flag)) ) { pari_free(s); return handle; } (void)dlerror(); /* clear error message */ } pari_free(s); } return NULL; } static void * install0(const char *name, const char *lib) { void *handle; #ifndef RTLD_GLOBAL /* OSF1 has dlopen but not RTLD_GLOBAL*/ # define RTLD_GLOBAL 0 #endif handle = gp_dlopen(lib, RTLD_LAZY|RTLD_GLOBAL); if (!handle) { const char *s = dlerror(); if (s) err_printf("%s\n\n",s); if (lib) pari_err(e_MISC,"couldn't open dynamic library '%s'",lib); pari_err(e_MISC,"couldn't open dynamic symbol table of process"); } return dlsym(handle, name); } #else # ifdef _WIN32 static HMODULE try_LoadLibrary(const char *s) { void *h = LoadLibrary(s); pari_free((void*)s); return h; } /* like LoadLibrary, but using default(sopath) */ static HMODULE gp_LoadLibrary(const char *name) { HMODULE handle; char *s = path_expand(name); /* if sopath empty or path is absolute, use LoadLibrary */ if (!GP_DATA || *(GP_DATA->sopath->PATH)==0 || path_is_absolute(s)) return try_LoadLibrary(s); else { forpath_t T; char *t; forpath_init(&T, GP_DATA->sopath, s); while ( (t = forpath_next(&T)) ) if ( (handle = try_LoadLibrary(t)) ) { pari_free(s); return handle; } pari_free(s); } return NULL; } static void * install0(const char *name, const char *lib) { HMODULE handle; if (lib == pari_library_path) { handle = GetModuleHandleA(NULL); void * fun = (void *) GetProcAddress(handle,name); if (fun) return fun; } handle = gp_LoadLibrary(lib); if (!handle) { if (lib) pari_err(e_MISC,"couldn't open dynamic library '%s'",lib); pari_err(e_MISC,"couldn't open dynamic symbol table of process"); } return (void *) GetProcAddress(handle,name); } # else static void * install0(const char *name, const char *lib) { pari_err(e_ARCH,"install"); return NULL; } #endif #endif static char * dft_help(const char *gp, const char *s, const char *code) { return stack_sprintf("%s: installed function\nlibrary name: %s\nprototype: %s" , gp, s, code); } void gpinstall(const char *s, const char *code, const char *gpname, const char *lib) { pari_sp av = avma; const char *gp = *gpname? gpname: s; int update_help; void *f; entree *ep; if (GP_DATA->secure) { char *msg = pari_sprintf("[secure mode]: about to install '%s'", s); pari_ask_confirm(msg); pari_free(msg); } f = install0(s, *lib ?lib :pari_library_path); if (!f) { if (*lib) pari_err(e_MISC,"can't find symbol '%s' in library '%s'",s,lib); pari_err(e_MISC,"can't find symbol '%s' in dynamic symbol table of process",s); } ep = is_entry(gp); /* Delete help if 1) help is the default (don't delete user addhelp) * and 2) default help changes */ update_help = (ep && ep->valence == EpINSTALL && ep->help && strcmp(ep->code, code) && !strcmp(ep->help, dft_help(gp,s,ep->code))); ep = install(f,gp,code); if (update_help || !ep->help) addhelp(gp, dft_help(gp,s,code)); mt_broadcast(snm_closure(is_entry("install"), mkvec4(strtoGENstr(s),strtoGENstr(code), strtoGENstr(gp),strtoGENstr(lib)))); set_avma(av); } pari-2.17.2/src/language/sumiter.c0000644000175000017500000016447714760123736015426 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" GEN iferrpari(GEN a, GEN b, GEN c) { GEN res; struct pari_evalstate state; evalstate_save(&state); pari_CATCH(CATCH_ALL) { GEN E; if (!b&&!c) return gnil; E = evalstate_restore_err(&state); if (c) { push_lex(E,c); res = closure_evalnobrk(c); pop_lex(1); if (gequal0(res)) pari_err(0, E); } if (!b) return gnil; push_lex(E,b); res = closure_evalgen(b); pop_lex(1); return res; } pari_TRY { res = closure_evalgen(a); } pari_ENDCATCH; return res; } /********************************************************************/ /** **/ /** ITERATIONS **/ /** **/ /********************************************************************/ static void forparii(GEN a, GEN b, GEN code) { pari_sp av, av0 = avma; GEN aa; if (gcmp(b,a) < 0) return; if (typ(b) != t_INFINITY) b = gfloor(b); aa = a = setloop(a); av=avma; push_lex(a,code); while (gcmp(a,b) <= 0) { closure_evalvoid(code); if (loop_break()) break; a = get_lex(-1); if (a == aa) { a = incloop(a); if (a != aa) { set_lex(-1,a); aa = a; } } else { /* 'code' modified a ! Be careful (and slow) from now on */ a = gaddgs(a,1); if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"forparii"); a = gerepileupto(av,a); } set_lex(-1,a); } } pop_lex(1); set_avma(av0); } void forpari(GEN a, GEN b, GEN code) { pari_sp ltop=avma, av; if (typ(a) == t_INT) { forparii(a,b,code); return; } b = gcopy(b); /* Kludge to work-around the a+(a=2) bug */ av=avma; push_lex(a,code); while (gcmp(a,b) <= 0) { closure_evalvoid(code); if (loop_break()) break; a = get_lex(-1); a = gaddgs(a,1); if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"forpari"); a = gerepileupto(av,a); } set_lex(-1, a); } pop_lex(1); set_avma(ltop); } void foreachpari(GEN x, GEN code) { long i, l; switch(typ(x)) { case t_LIST: x = list_data(x); /* FALL THROUGH */ if (!x) return; case t_MAT: case t_VEC: case t_COL: break; default: pari_err_TYPE("foreach",x); return; /*LCOV_EXCL_LINE*/ } clone_lock(x); l = lg(x); push_lex(gen_0,code); for (i = 1; i < l; i++) { set_lex(-1, gel(x,i)); closure_evalvoid(code); if (loop_break()) break; } pop_lex(1); clone_unlock_deep(x); } /* is it better to sieve [a,b] or to factor individually ? */ static int no_sieve(ulong a, ulong b) { return b - a < usqrt(b) / tridiv_boundu(b); } /* 0 < a <= b. Using small consecutive chunks to 1) limit memory use, 2) allow * cheap early abort */ static int forfactoredpos(ulong a, ulong b, GEN code) { ulong x1, step = maxuu(2 * usqrt(b), 1024); pari_sp av = avma; if (no_sieve(a, b)) { ulong n; for (n = a; n <= b; n++, set_avma(av)) { GEN m = factoru(n); set_lex(-1, mkvec2(utoipos(n), Flm_to_ZM(m))); closure_evalvoid(code); if (loop_break()) return 1; } return 0; } for(x1 = a;; x1 += step, set_avma(av)) { /* beware overflow, fuse last two bins (avoid a tiny remainder) */ ulong j, lv, x2 = (b >= 2*step && b - 2*step >= x1)? x1-1 + step: b; GEN v = vecfactoru_i(x1, x2); lv = lg(v); for (j = 1; j < lv; j++) { ulong n = x1-1 + j; set_lex(-1, mkvec2(utoipos(n), Flm_to_ZM(gel(v,j)))); closure_evalvoid(code); if (loop_break()) return 1; } if (x2 == b) break; set_lex(-1, gen_0); } return 0; } /* vector of primes to squarefree factorization */ static GEN zv_to_ZM(GEN v) { return mkmat2(zc_to_ZC(v), const_col(lg(v)-1,gen_1)); } /* vector of primes to negative squarefree factorization */ static GEN zv_to_mZM(GEN v) { long i, l = lg(v); GEN w = cgetg(l+1, t_COL); gel(w,1) = gen_m1; for (i = 1; i < l; i++) gel(w,i+1) = utoipos(v[i]); return mkmat2(w, const_col(l,gen_1)); } /* 0 <= a <= b. Using small consecutive chunks to 1) limit memory use, 2) allow * cheap early abort */ static void forsquarefreepos(ulong a, ulong b, GEN code) { const ulong step = maxuu(1024, 2 * usqrt(b)); pari_sp av = avma; ulong x1; if (no_sieve(a, b)) { ulong n; for (n = a; n <= b; n++, set_avma(av)) { GEN m = factoru(n); if (!uissquarefree_fact(m)) continue; set_lex(-1, mkvec2(utoipos(n), Flm_to_ZM(m))); closure_evalvoid(code); if (loop_break()) return; } return; } for(x1 = a;; x1 += step, set_avma(av)) { /* beware overflow, fuse last two bins (avoid a tiny remainder) */ ulong j, lv, x2 = (b >= 2*step && b - 2*step >= x1)? x1-1 + step: b; GEN v = vecfactorsquarefreeu(x1, x2); lv = lg(v); for (j = 1; j < lv; j++) if (gel(v,j)) { ulong n = x1-1 + j; set_lex(-1, mkvec2(utoipos(n), zv_to_ZM(gel(v,j)))); closure_evalvoid(code); if (loop_break()) return; } if (x2 == b) break; set_lex(-1, gen_0); } } /* 0 <= a <= b. Loop from -b, ... -a through squarefree integers */ static void forsquarefreeneg(ulong a, ulong b, GEN code) { const ulong step = maxuu(1024, 2 * usqrt(b)); pari_sp av = avma; ulong x2; if (no_sieve(a, b)) { ulong n; for (n = b; n >= a; n--, set_avma(av)) { GEN m = factoru(n); if (!uissquarefree_fact(m)) continue; set_lex(-1, mkvec2(utoineg(n), zv_to_mZM(gel(m,1)))); closure_evalvoid(code); if (loop_break()) return; } return; } for(x2 = b;; x2 -= step, set_avma(av)) { /* beware overflow, fuse last two bins (avoid a tiny remainder) */ ulong j, x1 = (x2 >= 2*step && x2-2*step >= a)? x2+1 - step: a; GEN v = vecfactorsquarefreeu(x1, x2); for (j = lg(v)-1; j > 0; j--) if (gel(v,j)) { ulong n = x1-1 + j; set_lex(-1, mkvec2(utoineg(n), zv_to_mZM(gel(v,j)))); closure_evalvoid(code); if (loop_break()) return; } if (x1 == a) break; set_lex(-1, gen_0); } } void forsquarefree(GEN a, GEN b, GEN code) { pari_sp av = avma; long s; if (typ(a) != t_INT) pari_err_TYPE("forsquarefree", a); if (typ(b) != t_INT) pari_err_TYPE("forsquarefree", b); if (cmpii(a,b) > 0) return; s = signe(a); push_lex(NULL,code); if (s < 0) { if (signe(b) <= 0) forsquarefreeneg(itou(b), itou(a), code); else { forsquarefreeneg(1, itou(a), code); forsquarefreepos(1, itou(b), code); } } else forsquarefreepos(itou(a), itou(b), code); pop_lex(1); set_avma(av); } /* convert factoru(n) to factor(-n); M pre-allocated factorization matrix * with (-1)^1 already set */ static void Flm2negfact(GEN v, GEN M) { GEN p = gel(v,1), e = gel(v,2), P = gel(M,1), E = gel(M,2); long i, l = lg(p); for (i = 1; i < l; i++) { gel(P,i+1) = utoipos(p[i]); gel(E,i+1) = utoipos(e[i]); } setlg(P,l+1); setlg(E,l+1); } /* 0 < a <= b, from -b to -a */ static int forfactoredneg(ulong a, ulong b, GEN code) { ulong x2, step = maxuu(2 * usqrt(b), 1024); GEN P, E, M; pari_sp av; P = cgetg(18, t_COL); gel(P,1) = gen_m1; E = cgetg(18, t_COL); gel(E,1) = gen_1; M = mkmat2(P,E); av = avma; if (no_sieve(a, b)) { ulong n; for (n = b; n >= a; n--, set_avma(av)) { GEN m = factoru(n); Flm2negfact(m, M); set_lex(-1, mkvec2(utoineg(n), M)); closure_evalvoid(code); if (loop_break()) return 1; } return 0; } for (x2 = b;; x2 -= step, set_avma(av)) { /* beware overflow, fuse last two bins (avoid a tiny remainder) */ ulong j, x1 = (x2 >= 2*step && x2-2*step >= a)? x2+1 - step: a; GEN v = vecfactoru_i(x1, x2); for (j = lg(v)-1; j; j--) { /* run backward: from factor(x1..x2) to factor(-x2..-x1) */ ulong n = x1-1 + j; Flm2negfact(gel(v,j), M); set_lex(-1, mkvec2(utoineg(n), M)); closure_evalvoid(code); if (loop_break()) return 1; } if (x1 == a) break; set_lex(-1, gen_0); } return 0; } static int eval0(GEN code) { pari_sp av = avma; set_lex(-1, mkvec2(gen_0, mkmat2(mkcol(gen_0),mkcol(gen_1)))); closure_evalvoid(code); set_avma(av); return loop_break(); } void forfactored(GEN a, GEN b, GEN code) { pari_sp av = avma; long sa, sb, stop = 0; if (typ(a) != t_INT) pari_err_TYPE("forfactored", a); if (typ(b) != t_INT) pari_err_TYPE("forfactored", b); if (cmpii(a,b) > 0) return; push_lex(NULL,code); sa = signe(a); sb = signe(b); if (sa < 0) { stop = forfactoredneg((sb < 0)? uel(b,2): 1UL, itou(a), code); if (!stop && sb >= 0) stop = eval0(code); if (!stop && sb > 0) forfactoredpos(1UL, b[2], code); } else { if (!sa) stop = eval0(code); if (!stop && sb) forfactoredpos(sa? uel(a,2): 1UL, itou(b), code); } pop_lex(1); set_avma(av); } void whilepari(GEN a, GEN b) { pari_sp av = avma; for(;;) { GEN res = closure_evalnobrk(a); if (gequal0(res)) break; set_avma(av); closure_evalvoid(b); if (loop_break()) break; } set_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; set_avma(av); } set_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; GEN v = NULL; int (*cmp)(GEN,GEN); b = gcopy(b); s = gcopy(s); av = avma; switch(typ(s)) { case t_VEC: case t_COL: ss = gsigne(vecsum(s)); v = s; break; case t_INTMOD: if (typ(a) != t_INT) a = gceil(a); a = addii(a, modii(subii(gel(s,2),a), gel(s,1))); s = gel(s,1); /* FALL THROUGH */ default: ss = gsigne(s); } if (!ss) pari_err_DOMAIN("forstep","step","=",gen_0,s); cmp = (ss > 0)? &gcmp: &negcmp; i = 0; push_lex(a,code); 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 (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"forstep"); a = gerepileupto(av,a); } set_lex(-1,a); } pop_lex(1); set_avma(av0); } static void _fordiv(GEN a, GEN code, GEN (*D)(GEN)) { pari_sp av = avma; long i, l; GEN t = D(a); push_lex(gen_0,code); l = lg(t); for (i=1; ia [over integers]*/ static GEN _next_i(forvec_t *d) { long i = d->n; if (d->first) { d->first = 0; return (GEN)d->a; } for (;;) { if (cmpii(d->a[i], d->M[i]) < 0) { d->a[i] = incloop(d->a[i]); return (GEN)d->a; } d->a[i] = resetloop(d->a[i], d->m[i]); if (--i <= 0) return NULL; } } /* increment and return d->a [generic]*/ static GEN _next(forvec_t *d) { long i = d->n; if (d->first) { d->first = 0; return (GEN)d->a; } for (;;) { d->a[i] = gaddgs(d->a[i], 1); if (gcmp(d->a[i], d->M[i]) <= 0) return (GEN)d->a; d->a[i] = d->m[i]; if (--i <= 0) return NULL; } } /* nondecreasing order [over integers] */ static GEN _next_le_i(forvec_t *d) { long i = d->n; if (d->first) { d->first = 0; return (GEN)d->a; } for (;;) { if (cmpii(d->a[i], d->M[i]) < 0) { d->a[i] = incloop(d->a[i]); /* m[i] < a[i] <= M[i] <= M[i+1] */ while (i < d->n) { GEN t; i++; if (cmpii(d->a[i-1], d->a[i]) <= 0) continue; /* a[i] < 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; } } /* nondecreasing order [generic] */ static GEN _next_le(forvec_t *d) { long i = d->n; if (d->first) { d->first = 0; return (GEN)d->a; } for (;;) { d->a[i] = gaddgs(d->a[i], 1); if (gcmp(d->a[i], d->M[i]) <= 0) { while (i < d->n) { GEN c; i++; if (gcmp(d->a[i-1], d->a[i]) <= 0) continue; /* M[i] >= M[i-1] >= a[i-1] > a[i] */ c = gceil(gsub(d->a[i-1], d->a[i])); d->a[i] = gadd(d->a[i], c); /* a[i-1] <= a[i] < M[i-1] + 1 => a[i] < M[i]+1 => a[i] <= M[i] */ } return (GEN)d->a; } d->a[i] = d->m[i]; if (--i <= 0) return NULL; } } /* strictly increasing order [over integers] */ static GEN _next_lt_i(forvec_t *d) { long i = d->n; if (d->first) { d->first = 0; return (GEN)d->a; } for (;;) { if (cmpii(d->a[i], d->M[i]) < 0) { d->a[i] = incloop(d->a[i]); /* m[i] < a[i] <= M[i] < M[i+1] */ while (i < d->n) { pari_sp av; GEN t; i++; if (cmpii(d->a[i-1], d->a[i]) < 0) continue; av = avma; /* M[i] > M[i-1] >= a[i-1] */ t = addiu(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]*/ set_avma(av); } return (GEN)d->a; } d->a[i] = resetloop(d->a[i], d->m[i]); if (--i <= 0) return NULL; } } /* strictly increasing order [generic] */ static GEN _next_lt(forvec_t *d) { long i = d->n; if (d->first) { d->first = 0; return (GEN)d->a; } for (;;) { d->a[i] = gaddgs(d->a[i], 1); if (gcmp(d->a[i], d->M[i]) <= 0) { while (i < d->n) { GEN c; i++; if (gcmp(d->a[i-1], d->a[i]) < 0) continue; /* M[i] > M[i-1] >= a[i-1] >= a[i] */ c = addiu(gfloor(gsub(d->a[i-1], d->a[i])), 1); /* > a[i-1] - a[i] */ d->a[i] = gadd(d->a[i], c); /* a[i-1] < a[i] <= M[i-1] + 1 => a[i] < M[i]+1 => a[i] <= M[i] */ } return (GEN)d->a; } d->a[i] = d->m[i]; if (--i <= 0) return NULL; } } /* on Z^n /(cyc Z^n) [over integers] * torsion (cyc>0) and free (cyc=0) components may be interleaved */ static GEN _next_mod_cyc(forvec_t *d) { /* keep free components indices t1 < t2 last nonzero < t3 */ long t, t1 = 0, t2 = 0, t3 = 0; if (d->first) { d->first = 0; return (GEN)d->a; } for (t = d->n; t > 0; t--) { if (signe(d->M[t]) > 0) { /* torsion component */ d->a[t] = incloop(d->a[t]); if (cmpii(d->a[t], d->M[t]) < 0) return (GEN)d->a; d->a[t] = resetloop(d->a[t], gen_0); } else { /* set or update t1,t2,t3 */ if (t2 && !t1) t1 = t; if (!t2 && signe(d->a[t])) t2 = t; if (!t2) t3 = t; } } if (!t3 && !t2) return NULL; /* no free component, stop */ if (!t2) d->a[t3] = resetloop(d->a[t3], gen_m1); else if (!t3 && signe(d->a[t2]) < 0) togglesign(d->a[t2]); else if (signe(d->a[t2]) < 0) { d->a[t2] = incloop(d->a[t2]); d->a[t3] = resetloop(d->a[t3], gen_m1); } else if (!t1) { d->a[t2] = incloop(d->a[t2]); togglesign(d->a[t2]); } else { if (signe(d->a[t1]) < 0) { d->a[t2] = incloop(d->a[t2]); togglesign(d->a[t2]); } else { togglesign(d->a[t2]); d->a[t2] = incloop(d->a[t2]); } d->a[t1] = incloop(d->a[t1]); } return (GEN)d->a; } /* for forvec(v=[],) */ static GEN _next_void(forvec_t *d) { if (d->first) { d->first = 0; return (GEN)d->a; } return NULL; } static int RgV_is_ZV_nonneg(GEN x) { long i; for (i = lg(x)-1; i > 0; i--) if (typ(gel(x,i)) != t_INT || signe(gel(x, i)) < 0) return 0; return 1; } /* x assumed to be cyc vector, l>1 */ static int forvec_mod_cyc_init(forvec_t *d, GEN x) { long i, tx = typ(x), l = lg(x); d->a = (GEN*)cgetg(l,tx); /* current */ d->M = (GEN*)cgetg(l,tx); /* cyc */ for (i = 1; i < l; i++) { d->a[i] = setloop(gen_0); d->M[i] = setloop(gel(x, i)); } d->first = 1; d->n = l-1; d->m = NULL; d->next = &_next_mod_cyc; return 1; } /* Initialize minima (m) and maxima (M); guarantee M[i] - m[i] integer and * if flag = 1: m[i-1] <= m[i] <= M[i] <= M[i+1] * if flag = 2: m[i-1] < m[i] <= M[i] < M[i+1], * for all i */ int forvec_init(forvec_t *d, GEN x, long flag) { long i, tx = typ(x), l = lg(x), t = t_INT; if (!is_vec_t(tx)) pari_err_TYPE("forvec [not a vector]", x); if (l > 1 && RgV_is_ZV_nonneg(x)) return forvec_mod_cyc_init(d, x); d->first = 1; d->n = l - 1; d->a = (GEN*)cgetg(l,tx); d->m = (GEN*)cgetg(l,tx); d->M = (GEN*)cgetg(l,tx); if (l == 1) { d->next = &_next_void; return 1; } for (i = 1; i < l; i++) { GEN a, e = gel(x,i), m = gel(e,1), M = gel(e,2); tx = typ(e); if (! is_vec_t(tx) || lg(e)!=3) pari_err_TYPE("forvec [expected vector not of type [min,MAX]]",e); if (typ(m) != t_INT) t = t_REAL; if (i > 1) switch(flag) { case 1: /* a >= m[i-1] - m */ a = gceil(gsub(d->m[i-1], m)); if (typ(a) != t_INT) pari_err_TYPE("forvec",a); if (signe(a) > 0) m = gadd(m, a); else m = gcopy(m); break; case 2: /* a > m[i-1] - m */ a = gfloor(gsub(d->m[i-1], m)); if (typ(a) != t_INT) pari_err_TYPE("forvec",a); a = addiu(a, 1); if (signe(a) > 0) m = gadd(m, a); else m = gcopy(m); break; default: m = gcopy(m); break; } M = gadd(m, gfloor(gsub(M,m))); /* ensure M-m is an integer */ if (gcmp(m,M) > 0) { d->a = NULL; d->next = &_next; return 0; } d->m[i] = m; d->M[i] = M; } if (flag == 1) for (i = l-2; i >= 1; i--) { GEN M = d->M[i], a = gfloor(gsub(d->M[i+1], M)); if (typ(a) != t_INT) pari_err_TYPE("forvec",a); /* M[i]+a <= M[i+1] */ if (signe(a) < 0) d->M[i] = gadd(M, a); } else if (flag == 2) for (i = l-2; i >= 1; i--) { GEN M = d->M[i], a = gceil(gsub(d->M[i+1], M)); if (typ(a) != t_INT) pari_err_TYPE("forvec",a); a = subiu(a, 1); /* M[i]+a < M[i+1] */ if (signe(a) < 0) d->M[i] = gadd(M, a); } if (t == t_INT) { for (i = 1; i < l; i++) { d->a[i] = setloop(d->m[i]); if (typ(d->M[i]) != t_INT) d->M[i] = gfloor(d->M[i]); } } else { for (i = 1; i < l; i++) d->a[i] = d->m[i]; } switch(flag) { case 0: d->next = t==t_INT? &_next_i: &_next; break; case 1: d->next = t==t_INT? &_next_le_i: &_next_le; break; case 2: d->next = t==t_INT? &_next_lt_i: &_next_lt; break; default: pari_err_FLAG("forvec"); } return 1; } GEN forvec_next(forvec_t *d) { return d->next(d); } void forvec(GEN x, GEN code, long flag) { pari_sp av = avma; forvec_t T; GEN v; if (!forvec_init(&T, x, flag)) { set_avma(av); return; } push_lex((GEN)T.a, code); while ((v = forvec_next(&T))) { closure_evalvoid(code); if (loop_break()) break; } pop_lex(1); set_avma(av); } /********************************************************************/ /** **/ /** SUMS **/ /** **/ /********************************************************************/ GEN somme(GEN a, GEN b, GEN code, GEN x) { pari_sp av, av0 = avma; GEN p1; if (typ(a) != t_INT) pari_err_TYPE("sum",a); if (!x) x = gen_0; if (gcmp(b,a) < 0) return gcopy(x); b = gfloor(b); a = setloop(a); av=avma; push_lex(a,code); for(;;) { p1 = closure_evalnobrk(code); x=gadd(x,p1); if (cmpii(a,b) >= 0) break; a = incloop(a); if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"sum"); x = gerepileupto(av,x); } set_lex(-1,a); } pop_lex(1); return gerepileupto(av0,x); } static GEN sum_init(GEN x0, GEN t) { long tp = typ(t); GEN x; if (is_vec_t(tp)) { x = const_vec(lg(t)-1, x0); settyp(x, tp); } else x = x0; return x; } GEN suminf(void *E, GEN (*eval)(void *, GEN), GEN a, long bit) { long fl = 0, G = bit + 1; pari_sp av0 = avma, av; GEN x = NULL, _1; if (typ(a) != t_INT) pari_err_TYPE("suminf",a); a = setloop(a); av = avma; for(;;) { GEN t = eval(E, a); if (!x) _1 = x = sum_init(real_1_bit(bit), t); x = gadd(x,t); if (!gequal0(t) && gexpo(t) > gexpo(x)-G) fl = 0; else if (++fl == 3) break; a = incloop(a); if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"suminf"); gerepileall(av,2, &x, &_1); } } return gerepileupto(av0, gsub(x, _1)); } GEN suminf0(GEN a, GEN code, long bit) { EXPR_WRAP(code, suminf(EXPR_ARG, a, bit)); } GEN sumdivexpr(GEN num, GEN code) { pari_sp av = avma; GEN y = gen_0, t = divisors(num); long i, l = lg(t); push_lex(gen_0, code); for (i=1; i= 0) break; a = incloop(a); if (gc_needed(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; long fl,G; GEN p1,x = real_1(prec); if (typ(a) != t_INT) pari_err_TYPE("prodinf",a); a = setloop(a); av = avma; fl=0; G = -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 (gc_needed(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; long fl,G; GEN p1,p2,x = real_1(prec); if (typ(a) != t_INT) pari_err_TYPE("prodinf1",a); a = setloop(a); av = avma; fl=0; G = -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 (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"prodinf1"); x = gerepileupto(av,x); } } return gerepilecopy(av0,x); } GEN prodinf0(GEN a, GEN code, long flag, long prec) { switch(flag) { case 0: EXPR_WRAP(code, prodinf (EXPR_ARG, a, prec)); case 1: EXPR_WRAP(code, prodinf1(EXPR_ARG, a, prec)); } pari_err_FLAG("prodinf"); return NULL; /* LCOV_EXCL_LINE */ } GEN prodeuler(void *E, GEN (*eval)(void *, GEN), GEN a, GEN b, long prec) { pari_sp av, av0 = avma; GEN x = real_1(prec), prime; forprime_t T; av = avma; if (!forprime_init(&T, a,b)) return gc_const(av, x); av = avma; while ( (prime = forprime_next(&T)) ) { x = gmul(x, eval(E, prime)); if (gc_needed(av,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"prodeuler"); x = gerepilecopy(av, x); } } return gerepilecopy(av0,x); } GEN prodeuler0(GEN a, GEN b, GEN code, long prec) { EXPR_WRAP(code, prodeuler(EXPR_ARG, a, b, prec)); } 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)pari_mainstack->bot && z<=t)) return z; else return gcopy(z); } GEN vecexpr0(GEN vec, GEN code, GEN pred) { switch(typ(vec)) { case t_LIST: { if (list_typ(vec)==t_LIST_MAP) vec = mapdomain_shallow(vec); else vec = list_data(vec); if (!vec) return cgetg(1, t_VEC); break; } case t_VECSMALL: vec = vecsmall_to_vec(vec); break; case t_VEC: case t_COL: case t_MAT: break; default: pari_err_TYPE("[_|_<-_,_]",vec); } if (pred && code) EXPR_WRAP(code,vecselapply((void*)pred,&gp_evalbool,EXPR_ARGUPTO,vec)) else if (code) EXPR_WRAP(code,vecapply(EXPR_ARGUPTO,vec)) else EXPR_WRAP(pred,vecselect(EXPR_ARGBOOL,vec)) } GEN vecexpr1(GEN vec, GEN code, GEN pred) { GEN v = vecexpr0(vec, code, pred); return lg(v) == 1? v: shallowconcat1(v); } GEN vecteur(GEN nmax, GEN code) { GEN y, c; long i, m = gtos(nmax); if (m < 0) pari_err_DOMAIN("vector", "dimension", "<", gen_0, stoi(m)); if (!code) return zerovec(m); c = cgetipos(3); /* left on stack */ y = cgetg(m+1,t_VEC); push_lex(c, code); for (i=1; i<=m; i++) { c[2] = i; gel(y,i) = copyupto(closure_evalnobrk(code), y); set_lex(-1,c); } pop_lex(1); return y; } GEN vecteursmall(GEN nmax, GEN code) { pari_sp av; GEN y, c; long i, m = gtos(nmax); if (m < 0) pari_err_DOMAIN("vectorsmall", "dimension", "<", gen_0, stoi(m)); if (!code) return zero_zv(m); c = cgetipos(3); /* left on stack */ y = cgetg(m+1,t_VECSMALL); push_lex(c,code); av = avma; for (i = 1; i <= m; i++) { c[2] = i; y[i] = gtos(closure_evalnobrk(code)); set_avma(av); 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 c1, c2, y; long i, m, n; n = gtos(nlig); m = ncol? gtos(ncol): n; if (m < 0) pari_err_DOMAIN("matrix", "nbcols", "<", gen_0, stoi(m)); if (n < 0) pari_err_DOMAIN("matrix", "nbrows", "<", gen_0, stoi(n)); if (!m) return cgetg(1,t_MAT); if (!code || !n) return zeromatcopy(n, m); c1 = cgetipos(3); push_lex(c1,code); c2 = cgetipos(3); push_lex(c2,NULL); /* c1,c2 left on stack */ y = cgetg(m+1,t_MAT); for (i = 1; i <= m; i++) { GEN z = cgetg(n+1,t_COL); long j; c2[2] = i; gel(y,i) = z; for (j = 1; j <= n; j++) { c1[2] = j; gel(z,j) = copyupto(closure_evalnobrk(code), y); set_lex(-2,c1); set_lex(-1,c2); } } pop_lex(2); return y; } /********************************************************************/ /** **/ /** SUMMING SERIES **/ /** **/ /********************************************************************/ /* h = (2+2x)g'- g; g has t_INT coeffs */ static GEN delt(GEN g, long n) { GEN h = cgetg(n+3,t_POL); long k; h[1] = g[1]; gel(h,2) = gel(g,2); for (k=1; k> 1, D = (d+1) >> 1; g = cgetg(d+2, t_POL); g[1] = evalsigne(1)|evalvarn(0); T = cgetg(d+1,t_VEC); /* T[k+1] = binomial(2d,2k+1), 0 <= k < d */ gel(T,1) = utoipos(d2); for (k = 1; k < D; k++) { long k2 = k<<1; gel(T,k+1) = diviiexact(mulii(gel(T,k), muluu(d2-k2+1, d2-k2)), muluu(k2,k2+1)); } for (; k < d; k++) gel(T,k+1) = gel(T,d-k); gel(g,2) = gel(T,d); /* binomial(2d, 2(d-1)+1) */ for (i = 1; i < d; i++) { pari_sp av2 = avma; GEN s, t = gel(T,d-i); /* binomial(2d, 2(d-1-i)+1) */ s = t; for (k = d-i; k < d; k++) { long k2 = k<<1; t = diviiexact(mulii(t, muluu(d2-k2+1, d-k)), muluu(k2+1,k-(d-i)+1)); s = addii(s, t); } /* g_i = sum_{d-1-i <= k < d}, binomial(2*d, 2*k+1)*binomial(k,d-1-i) */ gel(g,i+2) = gerepileuptoint(av2, s); } /* sum_{0 <= i < d} g_i x^i * (x+x^2)^r */ g = RgX_mulXn(gmul(g, gpowgs(deg1pol(gen_1,gen_1,0),r)), r); if (!odd(m)) g = delt(g, n); for (i = 1; i <= r; i++) { g = delt(ZX_deriv(g), n); if (gc_needed(av,4)) { if (DEBUGMEM>1) pari_warn(warnmem,"polzag, i = %ld/%ld", i,r); g = gerepilecopy(av, g); } } return g; } GEN polzag(long n, long m) { pari_sp av = avma; GEN g = polzag1(n,m); if (lg(g) == 2) return g; g = ZX_z_unscale(polzag1(n,m), -1); return gerepileupto(av, RgX_Rg_div(g,gel(g,2))); } /*0.39322 > 1/log_2(3+sqrt(8))*/ static ulong sumalt_N(long prec) { return (ulong)(0.39322*(prec + 7)); } GEN sumalt(void *E, GEN (*eval)(void *, GEN), GEN a, long prec) { ulong k, N; pari_sp av = avma, av2; GEN s, az, c, d; if (typ(a) != t_INT) pari_err_TYPE("sumalt",a); N = sumalt_N(prec); d = powru(addsr(3, sqrtr(utor(8,prec))), N); d = shiftr(addrr(d, invr(d)),-1); a = setloop(a); az = gen_m1; c = d; s = gen_0; av2 = avma; for (k=0; ; k++) /* k < N */ { c = addir(az,c); s = gadd(s, gmul(c, eval(E, a))); if (k==N-1) break; az = diviuuexact(muluui((N-k)<<1,N+k,az), k+1, (k<<1)+1); a = incloop(a); /* in place! */ if (gc_needed(av,4)) { if (DEBUGMEM>1) pari_warn(warnmem,"sumalt, k = %ld/%ld", k,N-1); gerepileall(av2, 3, &az,&c,&s); } } return gerepileupto(av, gdiv(s,d)); } GEN sumalt2(void *E, GEN (*eval)(void *, GEN), GEN a, long prec) { long k, N; pari_sp av = avma, av2; GEN s, dn, pol; if (typ(a) != t_INT) pari_err_TYPE("sumalt",a); N = (long)(0.307073*(prec + 5)); /*0.307073 > 1/log_2(\beta_B)*/ pol = ZX_div_by_X_1(polzag1(N,N>>1), &dn); a = setloop(a); N = degpol(pol); s = gen_0; av2 = avma; for (k=0; k<=N; k++) { GEN t = itor(gel(pol,k+2), prec+EXTRAPREC64); s = gadd(s, gmul(t, eval(E, a))); if (k == N) break; a = incloop(a); /* in place! */ if (gc_needed(av,4)) { if (DEBUGMEM>1) pari_warn(warnmem,"sumalt2, k = %ld/%ld", k,N-1); s = gerepileupto(av2, s); } } return gerepileupto(av, gdiv(s,dn)); } GEN sumalt0(GEN a, GEN code, long flag, long prec) { switch(flag) { case 0: EXPR_WRAP(code, sumalt (EXPR_ARG,a,prec)); case 1: EXPR_WRAP(code, sumalt2(EXPR_ARG,a,prec)); default: pari_err_FLAG("sumalt"); } return NULL; /* LCOV_EXCL_LINE */ } /* For k > 0, set S[k*2^i] <- g(k*2^i), k*2^i <= N = #S. * Only needed with k odd (but also works for g even). */ static void binsum(GEN S, ulong k, void *E, GEN (*f)(void *, GEN), GEN a, long G, long prec) { long e, i, N = lg(S)-1, l = expu(N / k); /* k 2^l <= N < k 2^(l+1) */ pari_sp av = avma; GEN t = real_0(prec); /* unused unless f(a + k < 0 */ for(i = l-1; i >= 0; i--) { /* t ~ g(2 * k*2^i) with error ~ 2^(G-i-1) */ GEN u; av = avma; u = gtofp(f(E, a? addiu(a, k << i): utoipos(k << i)), prec); if (typ(u) != t_REAL) pari_err_TYPE("sumpos",u); t = addrr(gtofp(u,prec), mpshift(t,1)); /* ~ g(k*2^i) */ gel(S, k << i) = t = gerepileuptoleaf(av, t); } } /* For k > 0, let g(k) := \sum_{e >= 0} 2^e f(a + k*2^e). * Return [g(k), 1 <= k <= N] */ static GEN sumpos_init(void *E, GEN (*f)(void *, GEN), GEN a, long N, long prec) { GEN S = cgetg(N+1,t_VEC); long k, G = -prec - 5; for (k=1; k<=N; k+=2) binsum(S,k, E,f, a,G,prec); return S; } GEN sumpos(void *E, GEN (*eval)(void *, GEN), GEN a, long prec) { ulong k, N; pari_sp av = avma; GEN s, az, c, d, S; if (typ(a) != t_INT) pari_err_TYPE("sumpos",a); a = subiu(a,1); N = sumalt_N(prec); if (odd(N)) N++; /* extra precision for free */ d = powru(addsr(3, sqrtr(utor(8,prec))), N); d = shiftr(addrr(d, invr(d)),-1); az = gen_m1; c = d; S = sumpos_init(E, eval, a, N, prec); s = gen_0; for (k=0; k>1), &dn); s = gen_0; for (k=0; k", gen_0, mkvec2(fa, fb)); SOLVE: bit0 = -prec; bit = 3+bit0; itmax = 1 - 2*bit0; fc = fb; e = d = NULL; for (iter = 1; iter <= itmax; ++iter) { /* b = current best guess, a and c auxiliary points */ long bit2, exb; GEN m; 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; } m = subrr(c, b); shiftr_inplace(m, -1); exb = expo(b); if (bit < exb) { bit2 = bit + exb - 1; if (expo(m) <= exb + bit0) break; /*SUCCESS*/ } else { /* b ~ 0 */ bit2 = 2*bit - 1; if (expo(m) <= bit2) break; /*SUCCESS*/ } if (gequal0(fb)) break; /*SUCCESS*/ if (expo(e) > bit2 && gexpo(fa) > gexpo(fb)) { /* interpolation, m != 0, |f(c)| >= |f(b)|, f(b)f(c) < 0 */ GEN min1, min2, p, q, s = gdiv(fb, fa); if (a == c || equalrr(a,c)) { p = gmul2n(gmul(m, s), 1); q = gsubsg(1, s); } else { GEN r = gdiv(fb, fc); q = gdiv(fa, fc); p = gmul2n(gmul(gsub(q, r), gmul(m, q)), 1); p = gmul(s, gsub(p, gmul(subrr(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(m,q)), gmul2n(gabs(q,0), bit2)); min2 = gabs(gmul(e, q), 0); if (gcmp(gmul2n(p, 1), gmin_shallow(min1, min2)) < 0) { e = d; d = gdiv(p, q); } /* interpolation OK */ else e = d = m; /* failed, use bisection */ } else e = d = m; /* bound decreasing too slowly, use bisection */ a = b; fa = fb; if (d == m) { b = addrr(c, b); shiftr_inplace(b,-1); } else if (gexpo(d) > bit2) b = gadd(b, d); else if (gsigne(m) > 0) b = addrr(b, real2n(bit2, LOWDEFAULTPREC)); else b = subrr(b, real2n(bit2, LOWDEFAULTPREC)); if (equalrr(a, b)) break; if (realprec(b) < prec) b = rtor(b, prec); fb = eval(E, b); } if (iter > itmax) pari_err_IMPL("solve recovery [too many iterations]"); return gerepileuptoleaf(av, rcopy(b)); } GEN zbrent0(GEN a, GEN b, GEN code, long prec) { EXPR_WRAP(code, zbrent(EXPR_ARG, a, b, prec)); } /* Find zeros of a function in the real interval [a,b] by interval splitting */ GEN solvestep(void *E, GEN (*f)(void *,GEN), GEN a, GEN b, GEN step, long flag, long prec) { const long ITMAX = 10; pari_sp av = avma; GEN fa, a0, b0; long sa0, it, bit = prec / 2, ct = 0, s = gcmp(a,b); if (!s) return gequal0(f(E, a)) ? gcopy(mkvec(a)): cgetg(1,t_VEC); if (s > 0) swap(a, b); if (flag&4) { if (gcmpgs(step,1)<=0) pari_err_DOMAIN("solvestep","step","<=",gen_1,step); if (gsigne(a) <= 0) pari_err_DOMAIN("solvestep","a","<=",gen_0,a); } else if (gsigne(step) <= 0) pari_err_DOMAIN("solvestep","step","<=",gen_0,step); a0 = a = gtofp(a, prec); fa = f(E, a); b0 = b = gtofp(b, prec); step = gtofp(step, prec); sa0 = gsigne(fa); if (gexpo(fa) < -bit) sa0 = 0; for (it = 0; it < ITMAX; it++) { pari_sp av2 = avma; GEN v = cgetg(1, t_VEC); long sa = sa0; a = a0; b = b0; while (gcmp(a,b) < 0) { GEN fc, c = (flag&4)? gmul(a, step): gadd(a, step); long sc; if (gcmp(c,b) > 0) c = b; fc = f(E, c); sc = gsigne(fc); if (gexpo(fc) < -bit) sc = 0; if (!sc || sa*sc < 0) { GEN z = sc? zbrent(E, f, a, c, prec): c; long e; (void)grndtoi(z, &e); if (e <= -bit) ct = 1; if ((flag&1) && ((!(flag&8)) || ct)) return gerepileupto(av, z); v = shallowconcat(v, z); } a = c; fa = fc; sa = sc; if (gc_needed(av2,1)) { if (DEBUGMEM>1) pari_warn(warnmem,"solvestep"); gerepileall(av2, 4, &a ,&fa, &v, &step); } } if ((!(flag&2) || lg(v) > 1) && (!(flag&8) || ct)) return gerepilecopy(av, v); step = (flag&4)? sqrtnr(step,4): gmul2n(step, -2); gerepileall(av2, 2, &fa, &step); } pari_err_IMPL("solvestep recovery [too many iterations]"); return NULL;/*LCOV_EXCL_LINE*/ } GEN solvestep0(GEN a, GEN b, GEN step, GEN code, long flag, long prec) { EXPR_WRAP(code, solvestep(EXPR_ARG, a,b, step, flag, prec)); } /********************************************************************/ /** Numerical derivation **/ /********************************************************************/ struct deriv_data { GEN code; GEN args; GEN def; }; static GEN deriv_eval(void *E, GEN x, long prec) { struct deriv_data *data=(struct deriv_data *)E; gel(data->args,1)=x; uel(data->def,1)=1; return closure_callgenvecdefprec(data->code, data->args, data->def, prec); } /* Rationale: (f(2^-e) - f(-2^-e) + O(2^-b)) / (2 * 2^-e) = f'(0) + O(2^-2e) * since 2nd derivatives cancel. * prec(LHS) = b - e * prec(RHS) = 2e, equal when b = 3e = 3/2 b0 (b0 = required final bitprec) * * For f'(x), x far from 0: prec(LHS) = b - e - expo(x) * --> pr = 3/2 b0 + expo(x) */ GEN derivnum(void *E, GEN (*eval)(void *, GEN, long), GEN x, long prec) { long newprec, e, ex = gexpo(x), p = precision(x); long b0 = prec2nbits(p? p: prec), b = (long)ceil(b0 * 1.5 + maxss(0,ex)); GEN eps, u, v, y; pari_sp av = avma; newprec = nbits2prec(b + BITS_IN_LONG); switch(typ(x)) { case t_REAL: case t_COMPLEX: x = gprec_w(x, newprec); } e = b0/2; /* 1/2 required prec (in sig. bits) */ b -= e; /* >= b0 */ eps = real2n(-e, ex < -e? newprec: nbits2prec(b)); u = eval(E, gsub(x, eps), newprec); v = eval(E, gadd(x, eps), newprec); y = gmul2n(gsub(v,u), e-1); return gerepilecopy(av, gprec_wtrunc(y, nbits2prec(b0))); } /* Fornberg interpolation algorithm for finite differences coefficients * using 2N+1 equidistant grid points around 0 [ assume 2N even >= M ]. * Compute \delta[m]_{N,i} for all derivation orders m = 0..M such that * h^m * f^{(m)}(0) = \sum_{i = 0}^n delta[m]_{N,i} f(a_i) + O(h^{N-m+1}), * for step size h. * Return a = [0,-1,1...,-N,N] and vector of vectors d: d[m+1][i+1] * = w'(a_i) delta[m]_{2N,i}, i = 0..2N */ static void FD(long M, long N2, GEN *pd, GEN *pa) { GEN d, a, b, W, F; long N = N2>>1, m, i; F = cgetg(N2+2, t_VEC); a = cgetg(N2+2, t_VEC); b = cgetg(N+1, t_VEC); gel(a,1) = gen_0; for (i = 1; i <= N; i++) { gel(a,2*i) = utoineg(i); gel(a,2*i+1) = utoipos(i); gel(b,i) = sqru(i); } /* w = \prod (X - a[i]) = x W(x^2) */ W = roots_to_pol(b, 0); gel(F,1) = RgX_inflate(W,2); for (i = 1; i <= N; i++) { pari_sp av = avma; GEN r, U, S; U = RgX_inflate(RgX_div_by_X_x(W, gel(b,i), &r), 2); U = RgXn_red_shallow(U, M); /* higher terms not needed */ U = RgX_shift_shallow(U,1); /* w(X) / (X^2-a[i]^2) mod X^(M+1) */ S = ZX_sub(RgX_shift_shallow(U,1), ZX_Z_mul(U, gel(a,2*i+1))); S = gerepileupto(av, S); gel(F,2*i) = S; gel(F,2*i+1) = ZX_z_unscale(S, -1); } /* F[i] = w(X) / (X-a[i]) + O(X^(M+1)) in Z[X] */ d = cgetg(M+2, t_VEC); for (m = 0; m <= M; m++) { GEN v = cgetg(N2+2, t_VEC); /* coeff(F[i],X^m) */ for (i = 0; i <= N2; i++) gel(v, i+1) = gmael(F, i+1, m+2); gel(d,m+1) = v; } *pd = d; *pa = a; } static void chk_ord(long m) { if (m < 0) pari_err_DOMAIN("derivnumk", "derivation order", "<", gen_0, stoi(m)); } /* m! / N! for m in ind; vecmax(ind) <= N. Result not a GEN if ind contains 0. */ static GEN vfact(GEN ind, long N, long prec) { GEN v, iN; long i, l; ind = vecsmall_uniq(ind); chk_ord(ind[1]); l = lg(ind); iN = invr(itor(mulu_interval(ind[1] + 1, N), prec)); v = const_vec(ind[l-1], NULL); gel(v, ind[1]) = iN; for (i = 2; i < l; i++) gel(v, ind[i]) = iN = mulri(iN, mulu_interval(ind[i-1] + 1, ind[i])); return v; } static GEN chk_ind(GEN ind, long *M) { *M = 0; switch(typ(ind)) { case t_INT: ind = mkvecsmall(itos(ind)); break; case t_VECSMALL: if (lg(ind) == 1) return NULL; break; case t_VEC: case t_COL: if (lg(ind) == 1) return NULL; if (RgV_is_ZV(ind)) { ind = ZV_to_zv(ind); break; } /* fall through */ default: pari_err_TYPE("derivnum", ind); return NULL; /*LCOV_EXCL_LINE*/ } *M = vecsmall_max(ind); chk_ord(*M); return ind; } GEN derivnumk(void *E, GEN (*eval)(void *, GEN, long), GEN x, GEN ind0, long prec) { GEN A, C, D, DM, T, X, F, v, ind, t; long M, N, N2, fpr, p, i, pr, l, lA, e, ex, emin, emax, newprec; pari_sp av = avma; int allodd = 1; ind = chk_ind(ind0, &M); if (!ind) return cgetg(1, t_VEC); l = lg(ind); F = cgetg(l, t_VEC); if (!M) /* silly degenerate case */ { X = eval(E, x, prec); for (i = 1; i < l; i++) { chk_ord(ind[i]); gel(F,i) = X; } if (typ(ind0) == t_INT) F = gel(F,1); return gerepilecopy(av, F); } N2 = 3*M - 1; if (odd(N2)) N2++; N = N2 >> 1; FD(M, N2, &D,&A); /* optimal if 'eval' uses quadratic time */ C = vecbinomial(N2); DM = gel(D,M); T = cgetg(N2+2, t_VEC); /* (2N)! / w'(i) = (2N)! / w'(-i) = (-1)^(N-i) binom(2*N, N-i) */ t = gel(C, N+1); gel(T,1) = odd(N)? negi(t): t; for (i = 1; i <= N; i++) { t = gel(C, N-i+1); gel(T,2*i) = gel(T,2*i+1) = odd(N-i)? negi(t): t; } N = N2 >> 1; emin = LONG_MAX; emax = 0; for (i = 1; i <= N; i++) { e = expi(gel(DM,i)) + expi(gel(T,i)); if (e < 0) continue; /* 0 */ if (e < emin) emin = e; else if (e > emax) emax = e; } p = precision(x); fpr = p ? p: prec; e = (fpr + 3*M*log2((double)M)) / (2*M); ex = gexpo(real_i(x)); if (ex < 0) ex = 0; /* near 0 */ pr = (long)ceil(fpr + e * M); /* ~ 3fpr/2 */ newprec = nbits2prec(pr + (emax - emin) + ex + BITS_IN_LONG); switch(typ(x)) { case t_REAL: case t_COMPLEX: x = gprec_w(x, newprec); } lA = lg(A); X = cgetg(lA, t_VEC); for (i = 1; i < l; i++) if (!odd(ind[i])) { allodd = 0; break; } /* if only odd derivation orders, the value at 0 (A[1]) is not needed */ gel(X, 1) = gen_0; for (i = allodd? 2: 1; i < lA; i++) { GEN t = eval(E, gadd(x, gmul2n(gel(A,i), -e)), newprec); t = gmul(t, gel(T,i)); if (!gprecision(t)) t = is_scalar_t(typ(t))? gtofp(t, newprec): gmul(t, real_1(newprec)); gel(X,i) = t; } v = vfact(ind, N2, nbits2prec(fpr + 32)); for (i = 1; i < l; i++) { long m = ind[i]; GEN t = RgV_dotproduct(gel(D,m+1), X); gel(F,i) = gmul(t, gmul2n(gel(v, m), e*m)); } if (typ(ind0) == t_INT) F = gel(F,1); return gerepilecopy(av, F); } /* v(t') */ static long rfrac_val_deriv(GEN t) { long v = varn(gel(t,2)); return gvaluation(deriv(t, v), pol_x(v)); } GEN derivfunk(void *E, GEN (*eval)(void *, GEN, long), GEN x, GEN ind0, long prec) { pari_sp av; GEN ind, xp, ixp, F, G; long i, l, vx, M; if (!ind0) return derivfun(E, eval, x, prec); switch(typ(x)) { case t_REAL: case t_INT: case t_FRAC: case t_COMPLEX: return derivnumk(E,eval, x, ind0, prec); case t_POL: ind = chk_ind(ind0,&M); if (!ind) return cgetg(1,t_VEC); xp = RgX_deriv(x); x = RgX_to_ser(x, precdl+2 + M * (1+RgX_val(xp))); break; case t_RFRAC: ind = chk_ind(ind0,&M); if (!ind) return cgetg(1,t_VEC); x = rfrac_to_ser_i(x, precdl+2 + M * (1+rfrac_val_deriv(x))); xp = derivser(x); break; case t_SER: ind = chk_ind(ind0,&M); if (!ind) return cgetg(1,t_VEC); xp = derivser(x); break; default: pari_err_TYPE("numerical derivation",x); return NULL; /*LCOV_EXCL_LINE*/ } av = avma; vx = varn(x); ixp = M? ginv(xp): NULL; F = cgetg(M+2, t_VEC); gel(F,1) = eval(E, x, prec); for (i = 1; i <= M; i++) gel(F,i+1) = gmul(deriv(gel(F,i),vx), ixp); l = lg(ind); G = cgetg(l, t_VEC); for (i = 1; i < l; i++) { long m = ind[i]; chk_ord(m); gel(G,i) = gel(F,m+1); } if (typ(ind0) == t_INT) G = gel(G,1); return gerepilecopy(av, G); } GEN derivfun(void *E, GEN (*eval)(void *, GEN, long), GEN x, long prec) { pari_sp av = avma; GEN xp; 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: xp = RgX_deriv(x); x = RgX_to_ser(x, precdl+2+ (1 + RgX_val(xp))); break; case t_RFRAC: x = rfrac_to_ser_i(x, precdl+2+ (1 + rfrac_val_deriv(x))); /* fall through */ case t_SER: xp = derivser(x); break; default: pari_err_TYPE("formal derivation",x); return NULL; /*LCOV_EXCL_LINE*/ } vx = varn(x); return gerepileupto(av, gdiv(deriv(eval(E, x, prec),vx), xp)); } GEN laurentseries(void *E, GEN (*f)(void*,GEN x, long), long M, long v, long prec) { pari_sp av = avma; long d; if (v < 0) v = 0; d = maxss(M+1,1); for (;;) { long i, dr, vr; GEN s; s = cgetg(d+2, t_SER); s[1] = evalsigne(1) | evalvalser(1) | evalvarn(v); gel(s, 2) = gen_1; for (i = 3; i <= d+1; i++) gel(s, i) = gen_0; s = f(E, s, prec); if (typ(s) != t_SER || varn(s) != v) pari_err_TYPE("laurentseries", s); vr = valser(s); if (M < vr) { set_avma(av); return zeroser(v, M); } dr = lg(s) + vr - 3 - M; if (dr >= 0) return gerepileupto(av, s); set_avma(av); d -= dr; } } static GEN _evalclosprec(void *E, GEN x, long prec) { GEN s; push_localprec(prec); s = closure_callgen1((GEN)E, x); pop_localprec(); return s; } #define CLOS_ARGPREC __E, &_evalclosprec GEN laurentseries0(GEN f, long M, long v, long prec) { if (typ(f) != t_CLOSURE || closure_arity(f) != 1 || closure_is_variadic(f)) pari_err_TYPE("laurentseries",f); EXPR_WRAP(f, laurentseries(CLOS_ARGPREC,M,v,prec)); } GEN derivnum0(GEN a, GEN code, GEN ind, long prec) { EXPR_WRAP(code, derivfunk(EXPR_ARGPREC,a,ind,prec)); } GEN derivfun0(GEN args, GEN def, GEN code, long k, long prec) { pari_sp av = avma; struct deriv_data E; GEN z; E.code=code; E.args=args; E.def=def; z = gel(derivfunk((void*)&E, deriv_eval, gel(args,1), mkvecs(k), prec),1); return gerepilecopy(av, z); } /********************************************************************/ /** Numerical extrapolation **/ /********************************************************************/ /* [u(n), u <= N] */ static GEN get_u(void *E, GEN (*f)(void *, GEN, long), long N, long prec) { long n; GEN u; if (f) { GEN v = f(E, utoipos(N), prec); u = cgetg(N+1, t_VEC); if (typ(v) != t_VEC || lg(v) != N+1) { gel(u,N) = v; v = NULL; } else { GEN w = f(E, gen_1, LOWDEFAULTPREC); if (typ(w) != t_VEC || lg(w) != 2) { gel(u,N) = v; v = NULL; } } if (v) u = v; else for (n = 1; n < N; n++) gel(u,n) = f(E, utoipos(n), prec); } else { GEN v = (GEN)E; long t = lg(v)-1; if (t < N) pari_err_COMPONENT("limitnum","<",stoi(N), stoi(t)); u = vecslice(v, 1, N); } for (n = 1; n <= N; n++) { GEN un = gel(u,n); if (is_rational_t(typ(un))) gel(u,n) = gtofp(un, prec); } return u; } struct limit { long prec; /* working accuracy */ long N; /* number of terms */ GEN na; /* [n^alpha, n <= N] */ GEN coef; /* or NULL (alpha != 1) */ }; static GEN _gi(void *E, GEN x) { GEN A = (GEN)E, y = gsubgs(x, 1); if (gequal0(y)) return A; return gdiv(gsubgs(gpow(x, A, LOWDEFAULTPREC), 1), y); } static GEN _g(void *E, GEN x) { GEN D = (GEN)E, A = gel(D,1), T = gel(D,2); const long prec = LOWDEFAULTPREC; return gadd(glog(x,prec), intnum((void*)A, _gi, gen_0, gaddgs(x,1), T, prec)); } /* solve log(b) + int_0^{b+1} (x^(1/a)-1) / (x-1) dx = 0, b in [0,1] * return -log_2(b), rounded up */ static double get_accu(GEN a) { pari_sp av = avma; const long prec = LOWDEFAULTPREC; const double We2 = 1.844434455794; /* (W(1/e) + 1) / log(2) */ GEN b, T; if (!a) return We2; if (typ(a) == t_INT) switch(itos_or_0(a)) { case 1: return We2; case 2: return 1.186955309668; case 3: return 0.883182331990; } else if (typ(a) == t_FRAC && equali1(gel(a,1))) switch(itos_or_0(gel(a,2))) { case 2: return 2.644090500290; case 3: return 3.157759214459; case 4: return 3.536383237500; } T = intnuminit(gen_0, gen_1, 0, prec); b = zbrent((void*)mkvec2(ginv(a), T), &_g, dbltor(1E-5), gen_1, prec); return gc_double(av, -dbllog2r(b)); } static double get_c(GEN a) { double A = a? gtodouble(a): 1.0; if (A <= 0) pari_err_DOMAIN("limitnum","alpha","<=",gen_0, a); if (A >= 2) return 0.2270; if (A >= 1) return 0.3318; if (A >= 0.5) return 0.6212; if (A >= 0.3333) return 1.2; return 3; /* only tested for A >= 0.25 */ } static void limit_Nprec(struct limit *L, GEN alpha, long prec) { L->N = ceil(get_c(alpha) * prec); L->prec = nbits2prec(prec + (long)ceil(get_accu(alpha) * L->N)); } /* solve x - a log(x) = b; a, b >= 3 */ static double solvedivlog(double a, double b) { return dbllemma526(a,1,1,b); } /* #u > 1, prod_{j != i} u[i] - u[j] */ static GEN proddiff(GEN u, long i) { pari_sp av = avma; long l = lg(u), j; GEN p = NULL; if (i == 1) { p = gsub(gel(u,1), gel(u,2)); for (j = 3; j < l; j++) p = gmul(p, gsub(gel(u,i), gel(u,j))); } else { p = gsub(gel(u,i), gel(u,1)); for (j = 2; j < l; j++) if (j != i) p = gmul(p, gsub(gel(u,i), gel(u,j))); } return gerepileupto(av, p); } static GEN vecpows(GEN u, long N) { long i, l; GEN v = cgetg_copy(u, &l); for (i = 1; i < l; i++) gel(v,i) = gpowgs(gel(u,i), N); return v; } static void limit_init(struct limit *L, GEN alpha, int asymp) { long n, N = L->N, a = 0; GEN c, v, T = NULL; if (!alpha) a = 1; else if (typ(alpha) == t_INT) { a = itos_or_0(alpha); if (a > 2) a = 0; } else if (typ(alpha) == t_FRAC) { long na = itos_or_0(gel(alpha,1)), da = itos_or_0(gel(alpha,2)); if (da && na && da <= 4 && na <= 4) { /* don't bother with other cases */ long e = (N-1) % da, k = (N-1) / da; if (e) { N += da - e; k++; } /* N = 1 (mod d) => simpler ^ (n/d)(N-1) */ L->N = N; T = vecpowuu(N, na * k); } } L->coef = v = cgetg(N+1, t_VEC); if (!a) { long prec2 = gprecision(alpha); GEN u; if (prec2 && prec2 < L->prec) alpha = gprec_w(alpha, L->prec); L->na = u = vecpowug(N, alpha, L->prec); if (!T) T = vecpows(u, N-1); for (n = 1; n <= N; n++) gel(v,n) = gdiv(gel(T,n), proddiff(u,n)); return; } L->na = asymp? vecpowuu(N, a): NULL; c = mpfactr(N-1, L->prec); if (a == 1) { c = invr(c); gel(v,1) = c; if (!odd(N)) togglesign(c); for (n = 2; n <= N; n++) gel(v,n) = divru(mulrs(gel(v,n-1), n-1-N), n); } else { /* a = 2 */ c = invr(mulru(sqrr(c), (N*(N+1)) >> 1)); gel(v,1) = c; if (!odd(N)) togglesign(c); for (n = 2; n <= N; n++) gel(v,n) = divru(mulrs(gel(v,n-1), n-1-N), N+n); } T = vecpowuu(N, a*N); for (n = 2; n <= N; n++) gel(v,n) = mulri(gel(v,n), gel(T,n)); } /* Zagier/Lagrange extrapolation */ static GEN limitnum_i(struct limit *L, GEN u, long prec) { return gprec_w(RgV_dotproduct(u,L->coef), prec); } GEN limitnum(void *E, GEN (*f)(void *, GEN, long), GEN alpha, long prec) { pari_sp av = avma; struct limit L; GEN u; limit_Nprec(&L, alpha, prec); limit_init(&L, alpha, 0); u = get_u(E, f, L.N, L.prec); return gerepilecopy(av, limitnum_i(&L, u, prec)); } typedef GEN (*LIMIT_FUN)(void*,GEN,long); static LIMIT_FUN get_fun(GEN u, const char *s) { switch(typ(u)) { case t_COL: case t_VEC: break; case t_CLOSURE: return gp_callprec; default: pari_err_TYPE(s, u); } return NULL; } GEN limitnum0(GEN u, GEN alpha, long prec) { return limitnum((void*)u,get_fun(u, "limitnum"), alpha, prec); } GEN asympnum(void *E, GEN (*f)(void *, GEN, long), GEN alpha, long prec) { const long MAX = 100; pari_sp av = avma; GEN u, A = cgetg(MAX+1, t_VEC); long i, B = prec2nbits(prec); double LB = 0.9*expu(B); /* 0.9 and 0.95 below are heuristic */ struct limit L; limit_Nprec(&L, alpha, prec); if (alpha) LB *= gtodouble(alpha); limit_init(&L, alpha, 1); u = get_u(E, f, L.N, L.prec); for(i = 1; i <= MAX; i++) { GEN a, v, q, s = limitnum_i(&L, u, prec); long n; /* NOT bestappr: lindep properly ignores the lower bits */ v = lindep_bit(mkvec2(gen_1, s), maxss((long)(0.95*floor(B - i*LB)), 32)); if (lg(v) == 1) break; q = gel(v,2); if (!signe(q)) break; a = gdiv(negi(gel(v,1)), q); s = gsub(s, a); /* |s|q^2 > eps */ if (!gequal0(s) && gexpo(s) + 2*expi(q) > -17) break; gel(A,i) = a; for (n = 1; n <= L.N; n++) gel(u,n) = gmul(gsub(gel(u,n), a), gel(L.na,n)); } setlg(A,i); return gerepilecopy(av, A); } GEN asympnumraw(void *E, GEN (*f)(void *,GEN,long), long LIM, GEN alpha, long prec) { pari_sp av = avma; double c, d, al; long i, B; GEN u, A; struct limit L; if (LIM < 0) return cgetg(1, t_VEC); c = get_c(alpha); d = get_accu(alpha); al = alpha? gtodouble(alpha): 1.0; B = prec2nbits(prec); L.N = ceil(solvedivlog(c * al * LIM / M_LN2, c * B)); L.prec = nbits2prec(ceil(B + L.N / c + d * L.N)); limit_init(&L, alpha, 1); u = get_u(E, f, L.N, L.prec); A = cgetg(LIM+2, t_VEC); for(i = 0; i <= LIM; i++) { GEN a = RgV_dotproduct(u,L.coef); long n; for (n = 1; n <= L.N; n++) gel(u,n) = gprec_wensure(gmul(gsub(gel(u,n), a), gel(L.na,n)), L.prec); gel(A,i+1) = gprec_wtrunc(a, prec); } return gerepilecopy(av, A); } GEN asympnum0(GEN u, GEN alpha, long prec) { return asympnum((void*)u,get_fun(u, "asympnum"), alpha, prec); } GEN asympnumraw0(GEN u, long LIM, GEN alpha, long prec) { return asympnumraw((void*)u,get_fun(u, "asympnumraw"), LIM, alpha, prec); } pari-2.17.2/src/language/parse.h0000644000175000017500000001064114676526575015052 0ustar billbill/* A Bison parser, made by GNU Bison 3.8.2. */ /* Bison interface for Yacc-like parsers in C Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 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. */ /* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, especially those whose name start with YY_ or yy_. They are private implementation details that can be changed or removed. */ #ifndef YY_PARI_SRC_LANGUAGE_PARSE_H_INCLUDED # define YY_PARI_SRC_LANGUAGE_PARSE_H_INCLUDED /* Debug traces. */ #ifndef PARI_DEBUG # if defined YYDEBUG #if YYDEBUG # define PARI_DEBUG 1 # else # define PARI_DEBUG 0 # endif # else /* ! defined YYDEBUG */ # define PARI_DEBUG 0 # endif /* ! defined YYDEBUG */ #endif /* ! defined PARI_DEBUG */ #if PARI_DEBUG extern int pari_debug; #endif /* Token kinds. */ #ifndef PARI_TOKENTYPE # define PARI_TOKENTYPE enum pari_tokentype { PARI_EMPTY = -2, PARI_EOF = 0, /* "end of file" */ PARI_error = 256, /* error */ PARI_UNDEF = 257, /* "invalid token" */ KPARROW = 258, /* ")->" */ KARROW = 259, /* "->" */ KDOTDOT = 260, /* ".." */ KPE = 261, /* "+=" */ KSE = 262, /* "-=" */ KME = 263, /* "*=" */ KDE = 264, /* "/=" */ KDRE = 265, /* "\\/=" */ KEUCE = 266, /* "\\=" */ KMODE = 267, /* "%=" */ KAND = 268, /* "&&" */ KOR = 269, /* "||" */ KID = 270, /* "===" */ KEQ = 271, /* "==" */ KNE = 272, /* "!=" */ KGE = 273, /* ">=" */ KLE = 274, /* "<=" */ KSRE = 275, /* ">>=" */ KSLE = 276, /* "<<=" */ KSR = 277, /* ">>" */ KSL = 278, /* "<<" */ KDR = 279, /* "\\/" */ KPP = 280, /* "++" */ KSS = 281, /* "--" */ KINTEGER = 282, /* "integer" */ KREAL = 283, /* "real number" */ KENTRY = 284, /* "variable name" */ KSTRING = 285, /* "character string" */ SEQ = 286, /* SEQ */ DEFFUNC = 287, /* DEFFUNC */ INT = 288, /* INT */ LVAL = 289, /* LVAL */ SIGN = 290, /* SIGN */ DERIV = 291 /* DERIV */ }; typedef enum pari_tokentype pari_token_kind_t; #endif /* Value type. */ /* Location type. */ #if ! defined PARI_LTYPE && ! defined PARI_LTYPE_IS_DECLARED typedef struct PARI_LTYPE PARI_LTYPE; struct PARI_LTYPE { int first_line; int first_column; int last_line; int last_column; }; # define PARI_LTYPE_IS_DECLARED 1 # define PARI_LTYPE_IS_TRIVIAL 1 #endif int pari_parse (char **lex); #endif /* !YY_PARI_SRC_LANGUAGE_PARSE_H_INCLUDED */ pari-2.17.2/src/language/pariinl.c0000644000175000017500000000136414567450071015355 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #define PARI_NO_MPINL_H #define INLINE #ifndef DISABLE_INLINE # define DISABLE_INLINE #endif #include "pari.h" pari-2.17.2/src/language/opcode.h0000644000175000017500000000342714676526175015211 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; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ BEGINEXTERN typedef enum {Gvoid, Gsmall, Gvec, Gvar, Ggen, Gclosure, Gusmall} Gtype; typedef enum {OCexportvar='!',OCunexportvar,OCsetref,OClock,OCpackargs,OCevalmnem, OCbitprecreal='@', OCpushlong,OCpushgnil,OCpushgen,OCpushreal,OCpushstoi,OCpushvar, OCpop, OCstoi,OCitos,OCtostr,OCvarn,OCcopy,OCcopyifclone, OCprecreal,OCprecdl, OCvec,OCmat,OCcol, OCstackgen, OCcompo1,OCcompo2,OCcompoC,OCcompoL, OCpushptr,OCendptr, OCcompo1ptr,OCcompo2ptr,OCcompoCptr,OCcompoLptr, OCcalllong,OCcallgen,OCcallgen2,OCcallint,OCcallvoid,OCcalluser, OCnewframe,OCsaveframe, OCpushdyn,OCstoredyn,OCnewptrdyn,OCsimpleptrdyn, OCpushlex,OCstorelex,OCnewptrlex,OCsimpleptrlex, OCgetargs,OCdefaultarg,OClocalvar,OClocalvar0, OCcheckargs,OCcheckargs0,OCdefaultgen,OCdefaultlong, OCavma,OCgerepile, OCcowvardyn,OCcowvarlex, OCdup,OCstoreptr,OCcheckuserargs, OCitou,OCutoi,OCdefaultulong} op_code; ENDEXTERN pari-2.17.2/src/language/paricfg.c0000644000175000017500000000177614567450071015341 0ustar billbill/* Copyright (C) 2010 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" const char *paricfg_datadir = GPDATADIR; const char *paricfg_version = PARIVERSION; const char *paricfg_buildinfo = PARIINFO; const long paricfg_version_code = PARI_VERSION_CODE; const char *paricfg_vcsversion = PARI_VCSVERSION; const char *paricfg_compiledate = __DATE__; const char *paricfg_mt_engine = PARI_MT_ENGINE; const char *paricfg_gphelp = GPHELP; pari-2.17.2/src/language/forprime.c0000644000175000017500000010547214760137411015542 0ustar billbill/* Copyright (C) 2016 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" /**********************************************************************/ /*** ***/ /*** Public prime table ***/ /*** ***/ /**********************************************************************/ static ulong _maxprimelim = 0; static GEN _prodprimes,_prodprimes_addr; typedef unsigned char *byteptr; /* Build/Rebuild table of prime differences. The actual work is done by the * following two subroutines; the user entry point is the function * initprimes() below; initprimes1() is the basecase, called when * maxnum (size) is moderate. Must be called after pari_init_stack() )*/ static void initprimes1(ulong size, long *lenp, pari_prime *p1) { pari_sp av = avma; long k; byteptr q, r, s, p = (byteptr)stack_calloc(size+2), fin = p + size; pari_prime *re; 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; } re = p1; *re++ = 2; *re++ = 3; /* 2 and 3 */ for (s=q=p+1; ; s=q) { do q++; while (*q); if (q > fin) break; *re++ = (pari_prime) 2*(q-p)+1; } *re++ = 0; *lenp = re - p1; set_avma(av); } /* Timing in ms (Athlon/850; reports 512K of secondary cache; looks like there is 64K of quickier cache too). arena| 30m 100m 300m 1000m 2000m <-- primelimit ================================================= 16K 1.1053 1.1407 1.2589 1.4368 1.6086 24K 1.0000 1.0625 1.1320 1.2443 1.3095 32K 1.0000 1.0469 1.0761 1.1336 1.1776 48K 1.0000 1.0000 1.0254 1.0445 1.0546 50K 1.0000 1.0000 1.0152 1.0345 1.0464 52K 1.0000 1.0000 1.0203 1.0273 1.0362 54K 1.0000 1.0000 1.0812 1.0216 1.0281 56K 1.0526 1.0000 1.0051 1.0144 1.0205 58K 1.0000 1.0000 1.0000 1.0086 1.0123 60K 0.9473 0.9844 1.0051 1.0014 1.0055 62K 1.0000 0.9844 0.9949 0.9971 0.9993 64K 1.0000 1.0000 1.0000 1.0000 1.0000 66K 1.2632 1.2187 1.2183 1.2055 1.1953 68K 1.4211 1.4844 1.4721 1.4425 1.4188 70K 1.7368 1.7188 1.7107 1.6767 1.6421 72K 1.9474 1.9531 1.9594 1.9023 1.8573 74K 2.2105 2.1875 2.1827 2.1207 2.0650 76K 2.4211 2.4219 2.4010 2.3305 2.2644 78K 2.5789 2.6250 2.6091 2.5330 2.4571 80K 2.8421 2.8125 2.8223 2.7213 2.6380 84K 3.1053 3.1875 3.1776 3.0819 2.9802 88K 3.5263 3.5312 3.5228 3.4124 3.2992 92K 3.7895 3.8438 3.8375 3.7213 3.5971 96K 4.0000 4.1093 4.1218 3.9986 3.9659 112K 4.3684 4.5781 4.5787 4.4583 4.6115 128K 4.7368 4.8750 4.9188 4.8075 4.8997 192K 5.5263 5.7188 5.8020 5.6911 5.7064 256K 6.0000 6.2187 6.3045 6.1954 6.1033 384K 6.7368 6.9531 7.0405 6.9181 6.7912 512K 7.3158 7.5156 7.6294 7.5000 7.4654 768K 9.1579 9.4531 9.6395 9.5014 9.1075 1024K 10.368 10.7497 10.9999 10.878 10.8201 1536K 12.579 13.3124 13.7660 13.747 13.4739 2048K 13.737 14.4839 15.0509 15.151 15.1282 3076K 14.789 15.5780 16.2993 16.513 16.3365 Now the same number relative to the model (1 + 0.36*sqrt(primelimit)/arena) * (arena <= 64 ? 1.05 : (arena-64)**0.38) [SLOW2_IN_ROOTS = 0.36, ALPHA = 0.38] arena| 30m 100m 300m 1000m 2000m <-- primelimit ================================================= 16K 1.014 0.9835 0.9942 0.9889 1.004 24K 0.9526 0.9758 0.9861 0.9942 0.981 32K 0.971 0.9939 0.9884 0.9849 0.9806 48K 0.9902 0.9825 0.996 0.9945 0.9885 50K 0.9917 0.9853 0.9906 0.9926 0.9907 52K 0.9932 0.9878 0.9999 0.9928 0.9903 54K 0.9945 0.9902 1.064 0.9939 0.9913 56K 1.048 0.9924 0.9925 0.993 0.9921 58K 0.9969 0.9945 0.9909 0.9932 0.9918 60K 0.9455 0.9809 0.9992 0.9915 0.9923 62K 0.9991 0.9827 0.9921 0.9924 0.9929 64K 1 1 1 1 1 66K 1.02 0.9849 0.9857 0.9772 0.9704 68K 0.8827 0.9232 0.9176 0.9025 0.8903 70K 0.9255 0.9177 0.9162 0.9029 0.8881 72K 0.9309 0.936 0.9429 0.9219 0.9052 74K 0.9715 0.9644 0.967 0.9477 0.9292 76K 0.9935 0.9975 0.9946 0.9751 0.9552 78K 0.9987 1.021 1.021 1.003 0.9819 80K 1.047 1.041 1.052 1.027 1.006 84K 1.052 1.086 1.092 1.075 1.053 88K 1.116 1.125 1.133 1.117 1.096 92K 1.132 1.156 1.167 1.155 1.134 96K 1.137 1.177 1.195 1.185 1.196 112K 1.067 1.13 1.148 1.15 1.217 128K 1.04 1.083 1.113 1.124 1.178 192K 0.9368 0.985 1.025 1.051 1.095 256K 0.8741 0.9224 0.9619 0.995 1.024 384K 0.8103 0.8533 0.8917 0.9282 0.9568 512K 0.7753 0.8135 0.8537 0.892 0.935 768K 0.8184 0.8638 0.9121 0.9586 0.9705 1024K 0.8241 0.8741 0.927 0.979 1.03 1536K 0.8505 0.9212 0.9882 1.056 1.096 2048K 0.8294 0.8954 0.9655 1.041 1.102 */ #ifndef SLOW2_IN_ROOTS /* SLOW2_IN_ROOTS below 3: some slowdown starts to be noticable * when things fit into the cache on Sparc. * The choice of 2.6 gives a slowdown of 1-2% on UltraSparcII, * but makes calculations for "maximum" of 436273009 * fit into 256K cache (still common for some architectures). * * One may change it when small caches become uncommon, but the gain * is not going to be very noticable... */ # ifdef i386 /* gcc defines this? */ # define SLOW2_IN_ROOTS 0.36 # else # define SLOW2_IN_ROOTS 2.6 # endif #endif #ifndef CACHE_ARENA # ifdef i386 /* gcc defines this? */ /* Due to smaller SLOW2_IN_ROOTS, smaller arena is OK; fit L1 cache */ # define CACHE_ARENA (63 * 1024UL) /* No slowdown even with 64K L1 cache */ # else # define CACHE_ARENA (200 * 1024UL) /* No slowdown even with 256K L2 cache */ # endif #endif #define CACHE_ALPHA (0.38) /* Cache performance model parameter */ #define CACHE_CUTOFF (0.018) /* Cache performance not smooth here */ static double slow2_in_roots = SLOW2_IN_ROOTS; typedef struct { ulong arena; double power; double cutoff; ulong bigarena; } cache_model_t; static cache_model_t cache_model = { CACHE_ARENA, CACHE_ALPHA, CACHE_CUTOFF, 0 }; /* Assume that some calculation requires a chunk of memory to be accessed often in more or less random fashion (as in sieving). Assume that the calculation can be done in steps by subdividing the chunk into smaller subchunks (arenas) and treating them separately. Assume that the overhead of subdivision is equivalent to the number of arenas. Find an optimal size of the arena taking into account the overhead of subdivision, and the overhead of arena not fitting into the cache. Assume that arenas of size slow2_in_roots slows down the calculation 2x (comparing to very big arenas; when cache hits do not matter). Since cache performance varies wildly with architecture, load, and wheather (especially with cache coloring enabled), use an idealized cache model based on benchmarks above. Assume that an independent region of FIXED_TO_CACHE bytes is accessed very often concurrently with the arena access. */ static ulong good_arena_size(ulong slow2_size, ulong total, ulong fixed_to_cache, cache_model_t *cache_model) { ulong asize, cache_arena = cache_model->arena; double Xmin, Xmax, A, B, C1, C2, D, V; double alpha = cache_model->power, cut_off = cache_model->cutoff; /* Estimated relative slowdown, with overhead = max((fixed_to_cache+arena)/cache_arena - 1, 0): 1 + slow2_size/arena due to initialization overhead; max(1, 4.63 * overhead^0.38 ) due to footprint > cache size. [The latter is hard to substantiate theoretically, but this function describes benchmarks pretty close; it does not hurt that one can minimize it explicitly too ;-). The switch between different choices of max() happens when overhead=0.018.] Thus the problem is minimizing (1 + slow2_size/arena)*overhead**0.29. This boils down to F=((X+A)/(X+B))X^alpha, X=overhead, B = (1 - fixed_to_cache/cache_arena), A = B + slow2_size/cache_arena, alpha = 0.38, and X>=0.018, X>-B. We need to find the rightmost root of (X+A)*(X+B) - alpha(A-B)X to the right of 0.018 (if such exists and is below Xmax). Then we manually check the remaining region [0, 0.018]. Since we cannot trust the purely-experimental cache-hit slowdown function, as a sanity check always prefer fitting into the cache (or "almost fitting") if F-law predicts that the larger value of the arena provides less than 10% speedup. */ /* The simplest case: we fit into cache */ asize = cache_arena - fixed_to_cache; if (total <= asize) return total; /* The simple case: fitting into cache doesn't slow us down more than 10% */ if (asize > 10 * slow2_size) 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, \\ 5: cache size (typically whole L2 or L3) in bytes to use in forprime() \\ 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; case 5: ret = (long)(cache_model.bigarena); break; default: pari_err_BUG("set_optimize"); break; } if (g != NULL) { ulong val = itou(g); switch (what) { case 1: cache_model.arena = val; break; case 2: slow2_in_roots = (double)val / 1000.; break; case 3: cache_model.power = (double)val / 1000.; break; case 4: cache_model.cutoff = (double)val / 1000.; break; case 5: cache_model.bigarena = val; break; } } return ret; } /* s is odd; prime (starting from 3 = known_primes[2]), terminated by a 0 byte. * Checks n odd numbers starting at 'start', setting bytes to 0 (composite) * or 1 (prime), starting at data */ static void sieve_chunk(pari_prime *known_primes, ulong s, byteptr data, ulong n) { ulong p, cnt = n-1, start = s; pari_prime *q; memset(data, 0, n); start >>= 1; /* (start - 1)/2 */ start += n; /* Corresponds to the end */ /* data corresponds to start, q runs over primediffs */ for (q = known_primes + 1, p = 3; p; p = *++q) { /* first odd number >= start > p and divisible by p = last odd number <= start + 2p - 2 and 0 (mod p) = p + last number <= start + p - 2 and 0 (mod 2p) = p + start+p-2 - (start+p-2) % 2p = start + 2(p - 1 - ((start-1)/2 + (p-1)/2) % p). */ long off = cnt - ((start+(p>>1)) % p); while (off >= 0) { data[off] = 1; off -= p; } } } static void set_prodprimes(void) { pari_sp ltop = avma, av; ulong b = 1UL << 8, M = minuu(maxprime(), GP_DATA->factorlimit); GEN W, w, v = primes_interval_zv(3, M); long s, u, j, jold, l = lg(v); W = cgetg(64+1, t_VEC); for (jold = j = u = 1; j < l; j++) if (j==l-1 || uel(v,j) >= b) { long lw = (j == l-1? l: j) - jold + 1; w = v+jold-1; w[0] = evaltyp(t_VECSMALL) | _evallg(lw); gel(W,u++) = zv_prod_Z(w); /* p_jold ... p_{j-1} */ jold = j; b *= 2; if (b > M) b = M; /* truncate last run */ } setlg(W, u); for (j = 2; j < u; j++) gel(W,j) = mulii(gel(W,j-1), gel(W,j)); s = gsizeword(W); w = (GEN)pari_malloc(s*sizeof(long)); av = (pari_sp)(w + s); _prodprimes_addr = w; _prodprimes = gcopy_avma(W, &av); set_avma(ltop); } static void initprimes0(ulong maxnum, long *lenp, pari_prime *p1) { pari_sp av = avma, bot = pari_mainstack->bot; long alloced, psize; byteptr q, end, p; ulong remains, curlow, rootnum, asize, prime_above, last; pari_prime *end1, *curdiff, *p_prime_above; if (!odd(maxnum)) maxnum--; /* make it odd. */ /* base case */ if (maxnum < 1ul<<17) { initprimes1(maxnum>>1, lenp, p1); return; } /* Checked to be enough up to 40e6, attained at 155893 */ rootnum = usqrt(maxnum) | 1; initprimes1(rootnum>>1, &psize, p1); last = rootnum; end1 = p1 + psize - 1; remains = (maxnum - last) >> 1; /* number of odd numbers to check */ /* we access primes array of psize too; but we access it consecutively, * thus we do not include it in fixed_to_cache */ asize = good_arena_size((ulong)(rootnum * slow2_in_roots), remains+1, 0, &cache_model) - 1; /* enough room on the stack ? */ alloced = (((byteptr)avma) <= ((byteptr)bot) + asize); p = (byteptr)(alloced? pari_malloc(asize+1): stack_malloc(asize+1)); end = p + asize; /* the 0 sentinel goes at end. */ curlow = last + 2; /* First candidate: know primes up to last (odd). */ curdiff = end1; /* During each iteration p..end-1 represents a range of odd numbers. */ p_prime_above = p1 + 2; prime_above = 3; while (remains) { /* cycle over arenas; performance not crucial */ pari_prime was_delta; if (asize > remains) { asize = remains; end = p + asize; } /* Fake the upper limit appropriate for the given arena */ while (prime_above*prime_above <= curlow + (asize << 1) && *p_prime_above) prime_above = *p_prime_above++; was_delta = *p_prime_above; *p_prime_above = 0; /* sentinel for sieve_chunk */ sieve_chunk(p1, curlow, p, asize); *p_prime_above = was_delta; /* restore */ p[asize] = 0; /* sentinel */ for (q = p; ; q++) { /* q runs over addresses corresponding to primes */ while (*q) q++; /* use sentinel at end */ if (q >= end) break; *curdiff++ = (pari_prime) 2*(q-p) + curlow; } remains -= asize; curlow += (asize<<1); } *curdiff++ = 0; /* sentinel */ *lenp = curdiff - p1; if (alloced) pari_free(p); else set_avma(av); } ulong maxprime(void) { return pari_PRIMES? pari_PRIMES[pari_PRIMES[0]]: 0; } ulong maxprimelim(void) { return pari_PRIMES? _maxprimelim: 0; } ulong maxprimeN(void) { return pari_PRIMES? pari_PRIMES[0]: 0; } GEN prodprimes(void) { return pari_PRIMES? _prodprimes: NULL; } void maxprime_check(ulong c) { if (maxprime() < c) pari_err_MAXPRIME(c); } static pari_prime* initprimes(ulong maxnum) { pari_prime *t; long len; ulong N; if (maxnum < 65537) { maxnum = 65537; N = 6543; } else N = (long) ceil(primepi_upper_bound((double)maxnum)); t = (pari_prime*) pari_malloc(sizeof(*t) * (N+2)); initprimes0(maxnum, &len, t+1); t[0] = (pari_prime)(len-1); _maxprimelim = maxnum; return (pari_prime*) pari_realloc(t, sizeof(*t) * (len+1)); } void initprimetable(ulong maxnum) { pari_prime *old = pari_PRIMES; #ifdef LONG_IS_64BIT maxnum = minuu(maxnum, 4294967295); #endif pari_PRIMES = initprimes(maxnum); if (old) free(old); set_prodprimes(); } /**********************************************************************/ /*** ***/ /*** forprime ***/ /*** ***/ /**********************************************************************/ /* return good chunk size for sieve, 16 | chunk + 2 */ static ulong optimize_chunk(ulong a, ulong b) { /* TODO: Optimize size (surely < 512k to stay in L2 cache, but not so large * as to force recalculating too often). */ /* bigarena is in bytes, we use bits, and only odds */ ulong defchunk = (a>>31) > 1 ? 0x80000UL : 0x8000; ulong chunk = (cache_model.bigarena ? cache_model.bigarena : defchunk)<<4; ulong tmp = (b - a) / chunk + 1; if (tmp == 1) chunk = b - a + 16; else chunk = (b - a) / tmp + 15; /* ensure 16 | chunk + 2 */ return (((chunk + 2)>>4)<<4) - 2; } static void sieve_init(forprime_t *T, ulong a, ulong b) { T->sieveb = b; T->chunk = optimize_chunk(a, b); /* >> 1 [only odds] + 3 [convert from bits to bytes] */ T->isieve = (unsigned char*)stack_malloc(((T->chunk+2) >> 4) + 1); T->cache[0] = 0; T->a = a; T->end = minuu(a + T->chunk, b); T->pos = T->maxpos = 0; } enum {PRST_none, PRST_diffptr, PRST_sieve, PRST_unextprime, PRST_nextprime}; static void u_forprime_set_prime_table(forprime_t *T, ulong a) { T->strategy = PRST_diffptr; if (a < 3) { T->p = 0; T->n = 0; } else { long n = PRIMES_search(a - 1); if (n < 0) n = - n - 1; T->n = n; T->p = pari_PRIMES[n]; } } /* Set p so that p + q the smallest integer = c (mod q) and > original p. * Assume 0 < c < q. */ static void arith_set(forprime_t *T) { ulong r = T->p % T->q; /* 0 <= r <= min(p, q-1) */ pari_sp av = avma; GEN d = adduu(T->p - r, T->c); /* = c mod q */ if (T->c > r) d = subiu(d, T->q); /* d = c mod q, d = c > r? p-r+c-q: p-r+c, so that * d <= p and d+q = c>r? p-r+c : p-r+c+q > p */ if (signe(d) <= 0) { T->p = 0; T->strategy = PRST_nextprime; affii(d, T->pp); } else T->p = itou_or_0(d); set_avma(av); } /* Run through primes in arithmetic progression = c (mod q). * Warning: b = ULONG_MAX may signal that we are called by higher level * function handling a continuation for larger b; this sentinel value * must not be modified */ static int u_forprime_sieve_arith_init(forprime_t *T, struct pari_sieve *psieve, ulong a, ulong b, ulong c, ulong q) { #ifdef LONG_IS_64BIT const ulong UPRIME_MAX = 18446744073709551557UL; #else const ulong UPRIME_MAX = 4294967291UL; #endif ulong Plim, P, P2, Y, sieveb; if (!odd(b) && b > 2) b--; if (a > b || b < 2) { T->strategy = PRST_diffptr; /* paranoia */ T->p = 0; /* empty */ T->b = 0; /* empty */ T->n = 0; return 0; } P = maxprime(); if (b != ULONG_MAX && b > UPRIME_MAX) b = UPRIME_MAX; if (q != 1) { ulong D; c %= q; D = ugcd(c, q); if (D != 1) { a = maxuu(a,D); if (b != ULONG_MAX) b = minuu(b,D); } if (odd(q) && (a > 2 || c != 2)) { /* only *odd* primes. If a <= c = 2, then p = 2 must be included :-( */ if (!odd(c)) c += q; q <<= 1; } } T->q = q; T->c = c; T->strategy = PRST_none; /* unknown */ T->psieve = psieve; /* unused for now */ T->isieve = NULL; /* unused for now */ T->b = b; if (P >= b) { /* [a,b] \subset prime table */ u_forprime_set_prime_table(T, a); return 1; } /* b > P */ if (a >= P) { T->p = a - 1; if (T->q != 1) arith_set(T); } else u_forprime_set_prime_table(T, a); if (T->strategy == PRST_none) T->strategy = PRST_unextprime; /* now strategy is either PRST_diffptr or PRST_unextprime */ P2 = (P & HIGHMASK)? 0 : P*P; sieveb = b; if (P2 && P2 < b) sieveb = P2; /* maxprime^2 >= sieveb */ Plim = maxprimelim(); if (a <= Plim) a = Plim + 1; if (sieveb < a + 16) return 1; Y = sieveb - a + 1; /* number of integers in sievable interval > 16 */ P = usqrt(sieveb); /* largest sieving prime */ /* FIXME: should sieve as well if q != 1, adapt sieve code */ if (q == 1 && (!P2 || P2 > a) && 3/M_LN2 * Y >= uprimepi(P)) /* Sieve implemented & possible & not too costly. Cost model is * - nextprime: about Y / log(b) primes to test [neglect cost for composites] * individual cost average = 3 log2(b) mulmod, total = 3 Y / log(2) mulmod * - sieve: pi(P) mod + Y loglog(b) add * Since loglog(b) < 4, and add < 10*mulmod, we neglect the Y loglog(b) term. * We have mod < mulmod < 2*mod; for now, assume mulmod ~ mod. */ { if (T->strategy == PRST_unextprime) T->strategy = PRST_sieve; sieve_init(T, a, sieveb); } return 1; } int u_forprime_arith_init(forprime_t *T, ulong a, ulong b, ulong c, ulong q) { return u_forprime_sieve_arith_init(T, NULL, a, b, c, q); } /* will run through primes in [a,b] */ int u_forprime_init(forprime_t *T, ulong a, ulong b) { return u_forprime_arith_init(T, a,b, 0,1); } /* will run through primes in [a,b] */ static int u_forprime_sieve_init(forprime_t *T, struct pari_sieve *s, ulong b) { return u_forprime_sieve_arith_init(T, s, s->start, b, s->c, s->q); } /* now only run through primes <= c; assume c <= b above */ void u_forprime_restrict(forprime_t *T, ulong c) { T->b = c; } /* b = NULL: loop forever */ int forprimestep_init(forprime_t *T, GEN a, GEN b, GEN q) { GEN c = NULL; long lb; a = gceil(a); if (typ(a) != t_INT) pari_err_TYPE("forprime_init",a); T->qq = NULL; T->q = 1; T->c = 0; if (q) { switch(typ(q)) { case t_INT: c = a; break; case t_INTMOD: c = gel(q,2); q = gel(q,1); /* first int >= initial a which is = c (mod q) */ a = addii(a, modii(subii(c,a), q)); break; default: pari_err_TYPE("forprimestep_init",q); } if (signe(q) <= 0) pari_err_TYPE("forprimestep_init (q <= 0)",q); if (equali1(q)) c = q = NULL; else { GEN D = gcdii(c, q); if (!is_pm1(D)) { /* at most one prime: c */ if (cmpii(a, D) < 0) a = D; if (gcmp(b, D) > 0) b = D; } if ((T->q = itou_or_0(q))) T->c = umodiu(c, T->q); else T->qq = q; } } if (signe(a) <= 0) a = q? modii(a, q): gen_1; if (b && typ(b) != t_INFINITY) { b = gfloor(b); if (typ(b) != t_INT) pari_err_TYPE("forprime_init",b); if (signe(b) < 0 || cmpii(a,b) > 0) { T->strategy = PRST_nextprime; /* paranoia */ T->bb = T->pp = gen_0; return 0; } lb = lgefint(b); T->bb = b; } else if (!b || inf_get_sign(b) > 0) { lb = lgefint(a) + 4; T->bb = NULL; } else /* b == -oo */ { T->strategy = PRST_nextprime; /* paranoia */ T->bb = T->pp = gen_0; return 0; } T->pp = cgeti(T->qq? maxuu(lb, lgefint(T->qq)): lb); /* a, b are positive integers, a <= b */ if (!T->qq && lgefint(a) == 3) /* lb == 3 implies b != NULL */ return u_forprime_arith_init(T, uel(a,2), lb == 3? uel(b,2): ULONG_MAX, T->c, T->q); T->strategy = PRST_nextprime; affii(T->qq? subii(a,T->qq): subiu(a,T->q), T->pp); return 1; } int forprime_init(forprime_t *T, GEN a, GEN b) { return forprimestep_init(T,a,b,NULL); } /* assume a <= b <= maxprime()^2, a,b odd, sieve[n] corresponds to * a+16*n, a+16*n+2, ..., a+16*n+14 (bits 0 to 7) * maxpos = index of last sieve cell. * b-a+2 must be divisible by 16 for use by u_forprime_next */ static void sieve_block(ulong a, ulong b, ulong maxpos, unsigned char* sieve) { ulong i, N = pari_PRIMES[0], lim = usqrt(b), sz = (b-a) >> 1; (void)memset(sieve, 0, maxpos+1); for (i = 2; i <= N; i++) { /* p is odd */ ulong k, r, p = pari_PRIMES[i]; /* starts at p = 3 */ if (p > lim) break; /* solve a + 2k = 0 (mod p) */ r = a % p; if (r == 0) k = 0; else { k = p - r; if (odd(k)) k += p; k >>= 1; } /* m = a + 2k is the smallest odd m >= a, p | m */ /* position n (corresponds to a+2n) is sieve[n>>3], bit n&7 */ while (k <= sz) { sieve[k>>3] |= 1 << (k&7); k += p; /* 2k += 2p */ } } } static void pari_sieve_init(struct pari_sieve *s, ulong a, ulong b) { ulong maxpos= (b - a) >> 4; s->start = a; s->end = b; s->sieve = (unsigned char*) pari_malloc(maxpos+1); s->c = 0; s->q = 1; sieve_block(a, b, maxpos, s->sieve); s->maxpos = maxpos; /* must be last in case of SIGINT */ } static struct pari_sieve pari_sieve_modular; #ifdef LONG_IS_64BIT #define PARI_MODULAR_BASE ((1UL<<((BITS_IN_LONG-2)>>1))+1) #else #define PARI_MODULAR_BASE ((1UL<<(BITS_IN_LONG-1))+1) #endif void pari_init_primes(ulong maxprime) { ulong a = PARI_MODULAR_BASE, b = a + (1UL<<20)-2; initprimetable(maxprime); pari_sieve_init(&pari_sieve_modular, a, b); } void pari_close_primes(void) { if (pari_PRIMES) { pari_free(pari_PRIMES); pari_free(_prodprimes_addr); } pari_free(pari_sieve_modular.sieve); } void init_modular_small(forprime_t *S) { #ifdef LONG_IS_64BIT u_forprime_sieve_init(S, &pari_sieve_modular, ULONG_MAX); #else ulong a = (1UL<<((BITS_IN_LONG-2)>>1))+1; u_forprime_init(S, a, ULONG_MAX); #endif } void init_modular_big(forprime_t *S) { #ifdef LONG_IS_64BIT u_forprime_init(S, HIGHBIT + 1, ULONG_MAX); #else u_forprime_sieve_init(S, &pari_sieve_modular, ULONG_MAX); #endif } /* T->cache is a 0-terminated list of primes, return the first one and * remove it from list. Most of the time the list contains a single prime */ static ulong shift_cache(forprime_t *T) { long i; T->p = T->cache[0]; for (i = 1;; i++) /* remove one prime from cache */ if (! (T->cache[i-1] = T->cache[i]) ) break; return T->p; } ulong u_forprime_next(forprime_t *T) { if (T->strategy == PRST_diffptr) { for(;;) { if (++T->n <= pari_PRIMES[0]) { T->p = pari_PRIMES[T->n]; if (T->p > T->b) return 0; if (T->q == 1 || T->p % T->q == T->c) return T->p; } else { /* beyond the table */ T->strategy = T->isieve? PRST_sieve: PRST_unextprime; if (T->q != 1) { arith_set(T); if (!T->p) return 0; } /* T->p possibly not a prime if q != 1 */ break; } } } if (T->strategy == PRST_sieve) { /* require sieveb - a >= 16 */ ulong n; if (T->cache[0]) return shift_cache(T); NEXT_CHUNK: if (T->psieve) { T->sieve = T->psieve->sieve; T->end = T->psieve->end; if (T->end > T->sieveb) T->end = T->sieveb; T->maxpos = T->psieve->maxpos; T->pos = 0; T->psieve = NULL; } for (n = T->pos; n < T->maxpos; n++) if (T->sieve[n] != 0xFF) { unsigned char mask = T->sieve[n]; ulong p = T->a + (n<<4); long i = 0; T->pos = n; if (!(mask & 1)) T->cache[i++] = p; if (!(mask & 2)) T->cache[i++] = p+2; if (!(mask & 4)) T->cache[i++] = p+4; if (!(mask & 8)) T->cache[i++] = p+6; if (!(mask & 16)) T->cache[i++] = p+8; if (!(mask & 32)) T->cache[i++] = p+10; if (!(mask & 64)) T->cache[i++] = p+12; if (!(mask &128)) T->cache[i++] = p+14; T->cache[i] = 0; T->pos = n+1; return shift_cache(T); } /* n = T->maxpos, last cell: check p <= b */ if (T->maxpos && n == T->maxpos && T->sieve[n] != 0xFF) { unsigned char mask = T->sieve[n]; ulong p = T->a + (n<<4); long i = 0; T->pos = n; if (!(mask & 1) && p <= T->sieveb) T->cache[i++] = p; if (!(mask & 2) && p <= T->sieveb-2) T->cache[i++] = p+2; if (!(mask & 4) && p <= T->sieveb-4) T->cache[i++] = p+4; if (!(mask & 8) && p <= T->sieveb-6) T->cache[i++] = p+6; if (!(mask & 16) && p <= T->sieveb-8) T->cache[i++] = p+8; if (!(mask & 32) && p <= T->sieveb-10) T->cache[i++] = p+10; if (!(mask & 64) && p <= T->sieveb-12) T->cache[i++] = p+12; if (!(mask &128) && p <= T->sieveb-14) T->cache[i++] = p+14; if (i) { T->cache[i] = 0; T->pos = n+1; return shift_cache(T); } } if (T->maxpos && T->end >= T->sieveb) /* done with sieves ? */ { if (T->sieveb == T->b && T->b != ULONG_MAX) return 0; T->strategy = PRST_unextprime; } else { /* initialize next chunk */ T->sieve = T->isieve; if (T->maxpos == 0) T->a |= 1; /* first time; ensure odd */ else T->a = (T->end + 2) | 1; T->end = T->a + T->chunk; /* may overflow */ if (T->end < T->a || T->end > T->sieveb) T->end = T->sieveb; /* end and a are odd; sieve[k] contains the a + 8*2k + (0,2,...,14). * The largest k is (end-a) >> 4 */ T->pos = 0; T->maxpos = (T->end - T->a) >> 4; /* >= 1 */ sieve_block(T->a, T->end, T->maxpos, T->sieve); goto NEXT_CHUNK; } } if (T->strategy == PRST_unextprime) { if (T->q == 1) { #ifdef LONG_IS_64BIT switch(T->p) { #define retp(x) return T->p = (HIGHBIT+x <= T->b)? HIGHBIT+x: 0 case HIGHBIT: retp(29); case HIGHBIT + 29: retp(99); case HIGHBIT + 99: retp(123); case HIGHBIT +123: retp(131); case HIGHBIT +131: retp(155); case HIGHBIT +155: retp(255); case HIGHBIT +255: retp(269); case HIGHBIT +269: retp(359); case HIGHBIT +359: retp(435); case HIGHBIT +435: retp(449); case HIGHBIT +449: retp(453); case HIGHBIT +453: retp(485); case HIGHBIT +485: retp(491); case HIGHBIT +491: retp(543); case HIGHBIT +543: retp(585); case HIGHBIT +585: retp(599); case HIGHBIT +599: retp(753); case HIGHBIT +753: retp(849); case HIGHBIT +849: retp(879); case HIGHBIT +879: retp(885); case HIGHBIT +885: retp(903); case HIGHBIT +903: retp(995); #undef retp } #endif T->p = unextprime(T->p + 1); if (T->p > T->b) return 0; } else do { T->p += T->q; if (T->p < T->q || T->p > T->b) { T->p = 0; break; } /* overflow */ } while (!uisprime(T->p)); if (T->p && T->p <= T->b) return T->p; /* overflow ulong, switch to GEN */ T->strategy = PRST_nextprime; } return 0; /* overflow */ } GEN forprime_next(forprime_t *T) { pari_sp av; GEN p; if (T->strategy != PRST_nextprime) { ulong u = u_forprime_next(T); if (u) { affui(u, T->pp); return T->pp; } /* failure */ if (T->strategy != PRST_nextprime) return NULL; /* we're done */ /* overflow ulong, switch to GEN */ u = ULONG_MAX; if (T->q > 1) u -= (ULONG_MAX-T->c) % T->q; affui(u, T->pp); } av = avma; p = T->pp; if (T->q == 1) { p = nextprime(addiu(p, 1)); if (T->bb && abscmpii(p, T->bb) > 0) return gc_NULL(av); } else do { p = T->qq? addii(p, T->qq): addiu(p, T->q); if (T->bb && abscmpii(p, T->bb) > 0) return gc_NULL(av); } while (!BPSW_psp(p)); affii(p, T->pp); return gc_const(av, T->pp); } void forprimestep(GEN a, GEN b, GEN q, GEN code) { pari_sp av = avma; forprime_t T; if (!forprimestep_init(&T, a,b,q)) { set_avma(av); return; } push_lex(T.pp,code); while(forprime_next(&T)) { closure_evalvoid(code); if (loop_break()) break; /* p changed in 'code', complain */ if (get_lex(-1) != T.pp) pari_err(e_MISC,"prime index read-only: was changed to %Ps", get_lex(-1)); } pop_lex(1); set_avma(av); } void forprime(GEN a, GEN b, GEN code) { return forprimestep(a,b,NULL,code); } int forcomposite_init(forcomposite_t *C, GEN a, GEN b) { pari_sp av = avma; a = gceil(a); if (typ(a)!=t_INT) pari_err_TYPE("forcomposite",a); if (b) { if (typ(b) == t_INFINITY) b = NULL; else { b = gfloor(b); if (typ(b)!=t_INT) pari_err_TYPE("forcomposite",b); } } if (signe(a) < 0) pari_err_DOMAIN("forcomposite", "a", "<", gen_0, a); if (abscmpiu(a, 4) < 0) a = utoipos(4); C->first = 1; if (!forprime_init(&C->T, a,b) && cmpii(a,b) > 0) { C->n = gen_1; /* in case caller forgets to check the return value */ C->b = gen_0; return gc_bool(av,0); } C->n = setloop(a); C->b = b; C->p = NULL; return 1; } GEN forcomposite_next(forcomposite_t *C) { if (C->first) /* first call ever */ { C->first = 0; C->p = forprime_next(&C->T); } else C->n = incloop(C->n); if (C->p) { if (cmpii(C->n, C->p) < 0) return C->n; C->n = incloop(C->n); /* n = p+1 */ C->p = forprime_next(&C->T); /* nextprime(p) > n */ if (C->p) return C->n; } if (!C->b || cmpii(C->n, C->b) <= 0) return C->n; return NULL; } void forcomposite(GEN a, GEN b, GEN code) { pari_sp av = avma; forcomposite_t T; GEN n; if (!forcomposite_init(&T,a,b)) return; push_lex(T.n,code); while((n = forcomposite_next(&T))) { closure_evalvoid(code); if (loop_break()) break; /* n changed in 'code', complain */ if (get_lex(-1) != n) pari_err(e_MISC,"index read-only: was changed to %Ps", get_lex(-1)); } pop_lex(1); set_avma(av); } pari-2.17.2/src/language/default.c0000644000175000017500000006454714676526175015371 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #ifdef _WIN32 # include "../systems/mingw/mingw.h" #endif /* Return all chars, up to next separator * [as strtok but must handle verbatim character string] */ char* get_sep(const char *t) { char *buf = stack_malloc(strlen(t)+1); char *s = buf; int outer = 1; for(;;) { switch(*s++ = *t++) { case '"': outer = !outer; break; case '\0': return buf; case ';': if (outer) { s[-1] = 0; return buf; } break; case '\\': /* gobble next char */ if (! (*s++ = *t++) ) return buf; } } } /* "atoul" + optional [kmg] suffix */ static ulong my_int(char *s, int size) { ulong n = 0; char *p = s; while (isdigit((unsigned char)*p)) { ulong m; if (n > (~0UL / 10)) pari_err(e_SYNTAX,"integer too large",s,s); n *= 10; m = n; n += *p++ - '0'; if (n < m) pari_err(e_SYNTAX,"integer too large",s,s); } if (n && *p) { long i = 0; ulong pow[] = {0, 1000UL, 1000000UL, 1000000000UL #ifdef LONG_IS_64BIT , 1000000000000UL #endif }; switch(*p) { case 'k': case 'K': p++; i = 1; break; case 'm': case 'M': p++; i = 2; break; case 'g': case 'G': p++; i = 3; break; #ifdef LONG_IS_64BIT case 't': case 'T': p++; i = 4; break; #endif } if (i) { if (*p == 'B' && p[-1] != 'm' && p[-1] != 'g' && size) { p++; n = umuluu_or_0(n, 1UL << (10*i)); } else n = umuluu_or_0(n, pow[i]); if (!n) pari_err(e_SYNTAX,"integer too large",s,s); } } if (*p) pari_err(e_SYNTAX,"I was expecting an integer here", s, s); return n; } long get_int(const char *s, long dflt) { pari_sp av = avma; char *p = get_sep(s); long n; int minus = 0; if (*p == '-') { minus = 1; p++; } if (!isdigit((unsigned char)*p)) return gc_long(av, dflt); n = (long)my_int(p, 0); if (n < 0) pari_err(e_SYNTAX,"integer too large",s,s); return gc_long(av, minus? -n: n); } static ulong get_uint(const char *s, int size) { pari_sp av = avma; char *p = get_sep(s); if (*p == '-') pari_err(e_SYNTAX,"arguments must be positive integers",s,s); return gc_ulong(av, my_int(p, size)); } #if defined(__EMX__) || defined(_WIN32) || defined(__CYGWIN32__) # define PATH_SEPARATOR ';' /* beware DOSish 'C:' disk drives */ #else # define PATH_SEPARATOR ':' #endif static const char * pari_default_path(void) { #if PATH_SEPARATOR == ';' return ".;C:;C:/gp"; #elif defined(UNIX) return ".:~:~/gp"; #else return "."; #endif } static 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); } } static void expand_path(gp_path *p) { char **dirs, *s, *v = p->PATH; int i, n = 0; delete_dirs(p); if (*v) { char *v0 = v = pari_strdup(v); while (*v == PATH_SEPARATOR) v++; /* empty leading path components */ /* First count non-empty path components. N.B. ignore empty ones */ for (s=v; *s; s++) if (*s == PATH_SEPARATOR) { /* implies s > v */ *s = 0; /* path component */ if (s[-1] && s[1]) n++; /* ignore if previous is empty OR we are last */ } dirs = (char**) pari_malloc((n + 2)*sizeof(char *)); for (s=v, i=0; i<=n; i++) { char *end, *f; while (!*s) s++; /* skip empty path components */ f = end = s + strlen(s); while (f > s && *--f == '/') *f = 0; /* skip trailing '/' */ dirs[i] = path_expand(s); s = end + 1; /* next path component */ } pari_free((void*)v0); } else { dirs = (char**) pari_malloc(sizeof(char *)); i = 0; } dirs[i] = NULL; p->dirs = dirs; } void pari_init_paths(void) { expand_path(GP_DATA->path); expand_path(GP_DATA->sopath); } static void delete_path(gp_path *p) { delete_dirs(p); free(p->PATH); } void pari_close_paths(void) { delete_path(GP_DATA->path); delete_path(GP_DATA->sopath); } /********************************************************************/ /* */ /* DEFAULTS */ /* */ /********************************************************************/ long getrealprecision(void) { return GP_DATA->fmt->sigd; } long setrealprecision(long n, long *prec) { GP_DATA->fmt->sigd = n; *prec = precreal = ndec2prec(n); return n; } GEN sd_toggle(const char *v, long flag, const char *s, int *ptn) { int state = *ptn; if (v) { int n = (int)get_int(v,0); if (n == state) return gnil; if (n != !state) { char *t = stack_malloc(64 + strlen(s)); (void)sprintf(t, "default: incorrect value for %s [0:off / 1:on]", s); pari_err(e_SYNTAX, t, v,v); } state = *ptn = n; } switch(flag) { case d_RETURN: return utoi(state); case d_ACKNOWLEDGE: if (state) pari_printf(" %s = 1 (on)\n", s); else pari_printf(" %s = 0 (off)\n", s); break; } return gnil; } static void sd_ulong_init(const char *v, const char *s, ulong *ptn, ulong Min, ulong Max, int size) { if (v) { ulong n = get_uint(v, size); if (n > Max || n < Min) { char *buf = stack_malloc(strlen(s) + 2 * 20 + 40); (void)sprintf(buf, "default: incorrect value for %s [%lu-%lu]", s, Min, Max); pari_err(e_SYNTAX, buf, v,v); } *ptn = n; } } static GEN sd_res(const char *v, long flag, const char *s, ulong n, ulong oldn, const char **msg) { switch(flag) { case d_RETURN: return utoi(n); case d_ACKNOWLEDGE: if (!v || n != oldn) { if (!msg) /* no specific message */ pari_printf(" %s = %lu\n", s, n); else if (!msg[1]) /* single message, always printed */ pari_printf(" %s = %lu %s\n", s, n, msg[0]); else /* print (new)-n-th message */ pari_printf(" %s = %lu %s\n", s, n, msg[n]); } break; } return gnil; } /* 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, 0); return sd_res(v, flag, s, *ptn, n, msg); } static GEN sd_size(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, 1); return sd_res(v, flag, s, *ptn, n, msg); } static void err_intarray(char *t, char *p, const char *s) { char *b = stack_malloc(64 + strlen(s)); sprintf(b, "incorrect value for %s", s); pari_err(e_SYNTAX, b, p, t); } static GEN parse_intarray(const char *v, const char *s) { pari_sp av = avma; char *p, *t = gp_filter(v); long i, l; GEN w; if (*t != '[') err_intarray(t, t, s); if (t[1] == ']') return gc_const(av, cgetalloc(1, t_VECSMALL)); for (p = t+1, l=2; *p; p++) if (*p == ',') l++; else if (*p < '0' || *p > '9') break; if (*p != ']') err_intarray(t, p, s); w = cgetalloc(l, t_VECSMALL); for (p = t+1, i=0; *p; p++) { long n = 0; while (*p >= '0' && *p <= '9') n = 10*n + (*p++ -'0'); w[++i] = n; } return gc_const(av, w); } GEN sd_intarray(const char *v, long flag, GEN *pz, const char *s) { if (v) { GEN z = *pz; *pz = parse_intarray(v, s); pari_free(z); } switch(flag) { case d_RETURN: return zv_to_ZV(*pz); case d_ACKNOWLEDGE: pari_printf(" %s = %Ps\n", s, zv_to_ZV(*pz)); } return gnil; } GEN sd_realprecision(const char *v, long flag) { pariout_t *fmt = GP_DATA->fmt; if (v) { ulong newnb = fmt->sigd; long prec; sd_ulong_init(v, "realprecision", &newnb, 1, prec2ndec(LGBITS), 0); if (fmt->sigd == (long)newnb) return gnil; if (fmt->sigd >= 0) fmt->sigd = newnb; prec = ndec2nbits(newnb); if (prec == precreal) return gnil; precreal = prec; } if (flag == d_RETURN) return stoi(nbits2ndec(precreal)); if (flag == d_ACKNOWLEDGE) { long n = nbits2ndec(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_realbitprecision(const char *v, long flag) { pariout_t *fmt = GP_DATA->fmt; if (v) { ulong newnb = precreal; long n; sd_ulong_init(v, "realbitprecision", &newnb, 1, LGBITS, 0); if ((long)newnb == precreal) return gnil; n = nbits2ndec(newnb); if (!n) n = 1; if (fmt->sigd >= 0) fmt->sigd = n; precreal = (long) newnb; } if (flag == d_RETURN) return stoi(precreal); if (flag == d_ACKNOWLEDGE) { pari_printf(" realbitprecision = %ld significant bits", precreal); if (fmt->sigd < 0) pari_puts(" (all digits displayed)"); else pari_printf(" (%ld decimal 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((unsigned)*v)) { c = atol(v); trans = 1; } /* color on transparent background */ else { if (*v == '[') { const char *a[3]; long i = 0; for (a[0] = s = ++v; *s && *s != ']'; s++) if (*s == ',') { *s = 0; a[++i] = s+1; } if (*s != ']') pari_err(e_SYNTAX,"expected character: ']'",s, *st); *s = 0; for (i++; i<3; i++) a[i] = ""; /* properties | color | background */ c = (atoi(a[2])<<8) | atoi(a[0]) | (atoi(a[1])<<4); trans = (*(a[1]) == 0); v = s + 1; } else { c = c_NONE; trans = 0; } } if (trans) c = c | (1L<<12); while (*v && *v++ != ',') /* empty */; if (c != c_NONE) disable_color = 0; *st = v; return c; } /* 1: error, 2: history, 3: prompt, 4: input, 5: output, 6: help, 7: timer */ GEN sd_colors(const char *v, long flag) { long c,l; if (v && !(GP_DATA->flags & (gpd_EMACS|gpd_TEXMACS))) { pari_sp av = avma; char *s; disable_color=1; l = strlen(v); if (l <= 2 && strncmp(v, "no", l) == 0) v = ""; else if (l <= 6 && strncmp(v, "darkbg", l) == 0) v = "1, 5, 3, 7, 6, 2, 3"; /* assume recent readline. */ else if (l <= 7 && strncmp(v, "lightbg", l) == 0) v = "1, 6, 3, 4, 5, 2, 3"; /* assume recent readline. */ else if (l <= 8 && strncmp(v, "brightfg", l) == 0) /* windows console */ v = "9, 13, 11, 15, 14, 10, 11"; else if (l <= 6 && strncmp(v, "boldfg", l) == 0) /* darkbg console */ v = "[1,,1], [5,,1], [3,,1], [7,,1], [6,,1], , [2,,1]"; s = gp_filter(v); for (c=c_ERR; c < c_LAST; c++) gp_colors[c] = gp_get_color(&s); set_avma(av); } if (flag == d_ACKNOWLEDGE || flag == d_RETURN) { char s[128], *t = s; long col[3], n; for (*t=0,c=c_ERR; c < c_LAST; c++) { n = gp_colors[c]; if (n == c_NONE) sprintf(t,"no"); else { decode_color(n,col); if (n & (1L<<12)) { if (col[0]) sprintf(t,"[%ld,,%ld]",col[1],col[0]); else sprintf(t,"%ld",col[1]); } else sprintf(t,"[%ld,%ld,%ld]",col[1],col[2],col[0]); } t += strlen(t); if (c < c_LAST - 1) { *t++=','; *t++=' '; } } if (flag==d_RETURN) return strtoGENstr(s); pari_printf(" colors = \"%s\"\n",s); } return gnil; } GEN sd_format(const char *v, long flag) { pariout_t *fmt = GP_DATA->fmt; if (v) { char c = *v; if (c!='e' && c!='f' && c!='g') pari_err(e_SYNTAX,"default: inexistent format",v,v); fmt->format = c; v++; if (isdigit((unsigned char)*v)) { while (isdigit((unsigned char)*v)) v++; } /* FIXME: skip obsolete field width */ if (*v++ == '.') { if (*v == '-') fmt->sigd = -1; else if (isdigit((unsigned char)*v)) fmt->sigd=atol(v); } } if (flag == d_RETURN) { char *s = stack_malloc(64); (void)sprintf(s, "%c.%ld", fmt->format, fmt->sigd); return strtoGENstr(s); } if (flag == d_ACKNOWLEDGE) pari_printf(" format = %c.%ld\n", fmt->format, fmt->sigd); return gnil; } GEN sd_compatible(const char *v, long flag) { const char *msg[] = { "(no backward compatibility)", "(no backward compatibility)", "(no backward compatibility)", "(no backward compatibility)", NULL }; ulong junk = 0; return sd_ulong(v,flag,"compatible",&junk, 0,3,msg); } GEN sd_secure(const char *v, long flag) { if (v && GP_DATA->secure) pari_ask_confirm("[secure mode]: About to modify the 'secure' flag"); return sd_toggle(v,flag,"secure", &(GP_DATA->secure)); } GEN sd_debug(const char *v, long flag) { GEN r = sd_ulong(v,flag,"debug",&DEBUGLEVEL, 0,20,NULL); if (v) setalldebug(DEBUGLEVEL); return r; } GEN sd_debugfiles(const char *v, long flag) { return sd_ulong(v,flag,"debugfiles",&DEBUGLEVEL_io, 0,20,NULL); } GEN sd_debugmem(const char *v, long flag) { return sd_ulong(v,flag,"debugmem",&DEBUGMEM, 0,20,NULL); } /* set D->hist to size = s / total = t */ static void init_hist(gp_data *D, size_t s, ulong t) { gp_hist *H = D->hist; H->total = t; H->size = s; H->v = (gp_hist_cell*)pari_calloc(s * sizeof(gp_hist_cell)); } GEN sd_histsize(const char *s, long flag) { gp_hist *H = GP_DATA->hist; ulong n = H->size; GEN r = sd_ulong(s,flag,"histsize",&n, 1, (LONG_MAX / sizeof(long)) - 1,NULL); if (n != H->size) { const ulong total = H->total; long g, h, k, kmin; gp_hist_cell *v = H->v, *w; /* v = old data, w = new one */ size_t sv = H->size, sw; init_hist(GP_DATA, n, total); if (!total) return r; w = H->v; sw= H->size; /* copy relevant history entries */ g = (total-1) % sv; h = k = (total-1) % sw; kmin = k - minss(sw, sv); for ( ; k > kmin; k--, g--, h--) { w[h] = v[g]; v[g].z = NULL; if (!g) g = sv; if (!h) h = sw; } /* clean up */ for ( ; v[g].z; g--) { gunclone(v[g].z); if (!g) g = sv; } pari_free((void*)v); } return r; } static void TeX_define(const char *s, const char *def) { fprintf(pari_logfile, "\\ifx\\%s\\undefined\n \\def\\%s{%s}\\fi\n", s,s,def); } static void TeX_define2(const char *s, const char *def) { fprintf(pari_logfile, "\\ifx\\%s\\undefined\n \\def\\%s#1#2{%s}\\fi\n", s,s,def); } static FILE * open_logfile(const char *s) { FILE *log = fopen(s, "a"); if (!log) pari_err_FILE("logfile",s); setbuf(log,(char *)NULL); return log; } GEN sd_log(const char *v, long flag) { const char *msg[] = { "(off)", "(on)", "(on with colors)", "(TeX output)", NULL }; ulong s = pari_logstyle; GEN res = sd_ulong(v,flag,"log", &s, 0, 3, msg); if (!s != !pari_logstyle) /* Compare converts to boolean */ { /* toggled LOG */ if (pari_logstyle) { /* close log */ if (flag == d_ACKNOWLEDGE) pari_printf(" [logfile was \"%s\"]\n", current_logfile); if (pari_logfile) { fclose(pari_logfile); pari_logfile = NULL; } } else { pari_logfile = open_logfile(current_logfile); if (flag == d_ACKNOWLEDGE) pari_printf(" [logfile is \"%s\"]\n", current_logfile); else if (flag == d_INITRC) pari_printf("Logging to %s\n", current_logfile); } } if (pari_logfile && s != pari_logstyle && s == logstyle_TeX) { TeX_define("PARIbreak", "\\hskip 0pt plus \\hsize\\relax\\discretionary{}{}{}"); TeX_define("PARIpromptSTART", "\\vskip\\medskipamount\\bgroup\\bf"); TeX_define("PARIpromptEND", "\\egroup\\bgroup\\tt"); TeX_define("PARIinputEND", "\\egroup"); TeX_define2("PARIout", "\\vskip\\smallskipamount$\\displaystyle{\\tt\\%#1} = #2$"); } /* don't record new value until we are sure everything is fine */ pari_logstyle = s; return res; } GEN sd_TeXstyle(const char *v, long flag) { const char *msg[] = { "(bits 0x2/0x4 control output of \\left/\\PARIbreak)", NULL }; ulong n = GP_DATA->fmt->TeXstyle; GEN z = sd_ulong(v,flag,"TeXstyle", &n, 0, 7, msg); GP_DATA->fmt->TeXstyle = n; return z; } GEN sd_nbthreads(const char *v, long flag) { return sd_ulong(v,flag,"nbthreads",&pari_mt_nbthreads, 1,LONG_MAX,NULL); } GEN sd_output(const char *v, long flag) { const char *msg[] = {"(raw)", "(prettymatrix)", "(prettyprint)", "(external prettyprint)", NULL}; ulong n = GP_DATA->fmt->prettyp; GEN z = sd_ulong(v,flag,"output", &n, 0,3,msg); GP_DATA->fmt->prettyp = n; GP_DATA->fmt->sp = (n != f_RAW); return z; } GEN sd_parisizemax(const char *v, long flag) { ulong size = pari_mainstack->vsize, n = size; GEN r = sd_size(v,flag,"parisizemax",&n, 0,LONG_MAX,NULL); if (n != size) { if (flag == d_INITRC) paristack_setsize(pari_mainstack->rsize, n); else parivstack_resize(n); } return r; } GEN sd_parisize(const char *v, long flag) { ulong rsize = pari_mainstack->rsize, n = rsize; GEN r = sd_size(v,flag,"parisize",&n, 10000,LONG_MAX,NULL); if (n != rsize) { if (flag == d_INITRC) paristack_setsize(n, pari_mainstack->vsize); else paristack_newrsize(n); } return r; } GEN sd_threadsizemax(const char *v, long flag) { ulong size = GP_DATA->threadsizemax, n = size; GEN r = sd_size(v,flag,"threadsizemax",&n, 0,LONG_MAX,NULL); if (n != size) GP_DATA->threadsizemax = n; return r; } GEN sd_threadsize(const char *v, long flag) { ulong size = GP_DATA->threadsize, n = size; GEN r = sd_size(v,flag,"threadsize",&n, 0,LONG_MAX,NULL); if (n != size) GP_DATA->threadsize = n; return r; } GEN sd_primelimit(const char *v, long flag) { return sd_ulong(v,flag,"primelimit",&(GP_DATA->primelimit), 0,2*(ulong)(LONG_MAX-1024) + 1,NULL); } GEN sd_factorlimit(const char *v, long flag) { GEN z = sd_ulong(v,flag,"factorlimit",&(GP_DATA->factorlimit), 0,2*(ulong)(LONG_MAX-1024) + 1,NULL); if (v && flag != d_INITRC) mt_broadcast(snm_closure(is_entry("default"), mkvec2(strtoGENstr("factorlimit"), strtoGENstr(v)))); if (GP_DATA->primelimit < GP_DATA->factorlimit) GP_DATA->primelimit = GP_DATA->factorlimit; return z; } GEN sd_simplify(const char *v, long flag) { return sd_toggle(v,flag,"simplify", &(GP_DATA->simplify)); } GEN sd_strictmatch(const char *v, long flag) { return sd_toggle(v,flag,"strictmatch", &(GP_DATA->strictmatch)); } GEN sd_strictargs(const char *v, long flag) { return sd_toggle(v,flag,"strictargs", &(GP_DATA->strictargs)); } GEN sd_string(const char *v, long flag, const char *s, char **pstr) { char *old = *pstr; if (v) { char *str, *ev = path_expand(v); long l = strlen(ev) + 256; str = (char *) pari_malloc(l); strftime_expand(ev,str, l-1); pari_free(ev); if (GP_DATA->secure) { char *msg=pari_sprintf("[secure mode]: About to change %s to '%s'",s,str); pari_ask_confirm(msg); pari_free(msg); } if (old) pari_free(old); *pstr = old = pari_strdup(str); pari_free(str); } else if (!old) old = (char*)""; if (flag == d_RETURN) return strtoGENstr(old); if (flag == d_ACKNOWLEDGE) pari_printf(" %s = \"%s\"\n",s,old); return gnil; } GEN sd_logfile(const char *v, long flag) { GEN r = sd_string(v, flag, "logfile", ¤t_logfile); if (v && pari_logfile) { FILE *log = open_logfile(current_logfile); fclose(pari_logfile); pari_logfile = log; } return r; } GEN sd_factor_add_primes(const char *v, long flag) { return sd_toggle(v,flag,"factor_add_primes", &factor_add_primes); } GEN sd_factor_proven(const char *v, long flag) { return sd_toggle(v,flag,"factor_proven", &factor_proven); } GEN sd_new_galois_format(const char *v, long flag) { return sd_toggle(v,flag,"new_galois_format", &new_galois_format); } GEN sd_datadir(const char *v, long flag) { const char *str; if (v) { if (flag != d_INITRC) mt_broadcast(snm_closure(is_entry("default"), mkvec2(strtoGENstr("datadir"), strtoGENstr(v)))); if (pari_datadir) pari_free(pari_datadir); pari_datadir = path_expand(v); } str = pari_datadir? pari_datadir: "none"; if (flag == d_RETURN) return strtoGENstr(str); if (flag == d_ACKNOWLEDGE) pari_printf(" datadir = \"%s\"\n", str); return gnil; } static GEN sd_PATH(const char *v, long flag, const char* s, gp_path *p) { if (v) { if (flag != d_INITRC) mt_broadcast(snm_closure(is_entry("default"), mkvec2(strtoGENstr(s), strtoGENstr(v)))); pari_free((void*)p->PATH); p->PATH = pari_strdup(v); if (flag == d_INITRC) return gnil; expand_path(p); } if (flag == d_RETURN) return strtoGENstr(p->PATH); if (flag == d_ACKNOWLEDGE) pari_printf(" %s = \"%s\"\n", s, p->PATH); return gnil; } GEN sd_path(const char *v, long flag) { return sd_PATH(v, flag, "path", GP_DATA->path); } GEN sd_sopath(char *v, int flag) { return sd_PATH(v, flag, "sopath", GP_DATA->sopath); } static const char *DFT_PRETTYPRINTER = "tex2mail -TeX -noindent -ragged -by_par"; GEN sd_prettyprinter(const char *v, long flag) { gp_pp *pp = GP_DATA->pp; if (v && !(GP_DATA->flags & gpd_TEXMACS)) { char *old = pp->cmd; int cancel = (!strcmp(v,"no")); if (GP_DATA->secure) pari_err(e_MISC,"[secure mode]: can't modify 'prettyprinter' default (to %s)",v); if (!strcmp(v,"yes")) v = DFT_PRETTYPRINTER; if (old && strcmp(old,v) && pp->file) { pariFILE *f; if (cancel) f = NULL; else { f = try_pipe(v, mf_OUT); if (!f) { pari_warn(warner,"broken prettyprinter: '%s'",v); return gnil; } } pari_fclose(pp->file); pp->file = f; } pp->cmd = cancel? NULL: pari_strdup(v); if (old) pari_free(old); if (flag == d_INITRC) return gnil; } if (flag == d_RETURN) return strtoGENstr(pp->cmd? pp->cmd: ""); if (flag == d_ACKNOWLEDGE) pari_printf(" prettyprinter = \"%s\"\n",pp->cmd? pp->cmd: ""); return gnil; } /* compare entrees s1 s2 according to the attached 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); } 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) pari_stack_pushp(s, ep); } /* ep attached to function f of arity 2. Call f(v,flag) */ static GEN call_f2(entree *ep, const char *v, long flag) { return ((GEN (*)(const char*,long))ep->value)(v, flag); } GEN setdefault(const char *s, const char *v, long flag) { entree *ep; if (!s) { /* list all defaults */ pari_stack st; entree **L; long i; pari_stack_init(&st, sizeof(*L), (void**)&L); defaults_list(&st); qsort (L, st.n, sizeof(*L), compare_name); for (i = 0; i < st.n; i++) (void)call_f2(L[i], NULL, d_ACKNOWLEDGE); pari_stack_delete(&st); return gnil; } ep = pari_is_default(s); if (!ep) { pari_err(e_MISC,"unknown default: %s",s); return NULL; /* LCOV_EXCL_LINE */ } return call_f2(ep, v, flag); } GEN default0(const char *a, const char *b) { return setdefault(a,b, b? d_SILENT: d_RETURN); } /********************************************************************/ /* */ /* INITIALIZE GP_DATA */ /* */ /********************************************************************/ /* initialize path */ static void init_path(gp_path *path, const char *v) { path->PATH = pari_strdup(v); path->dirs = NULL; } /* initialize D->fmt */ static void init_fmt(gp_data *D) { static pariout_t DFLT_OUTPUT = { 'g', 38, 1, f_PRETTYMAT, 0 }; 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; } static char * init_help(void) { char *h = os_getenv("GPHELP"); if (!h) h = (char*)paricfg_gphelp; #ifdef _WIN32 win32_set_pdf_viewer(); #endif if (h) h = pari_strdup(h); return h; } static void init_graphs(gp_data *D) { const char *cols[] = { "", "white","black","blue","violetred","red","green","grey","gainsboro" }; const long N = 8; GEN c = cgetalloc(3, t_VECSMALL), s; long i; c[1] = 4; c[2] = 5; D->graphcolors = c; c = (GEN)pari_malloc((N+1 + 4*N)*sizeof(long)); c[0] = evaltyp(t_VEC)|_evallg(N+1); for (i = 1, s = c+N+1; i <= N; i++, s += 4) { GEN lp = s; lp[0] = evaltyp(t_STR)|_evallg(4); strcpy(GSTR(lp), cols[i]); gel(c,i) = lp; } D->colormap = c; } gp_data * default_gp_data(void) { static gp_data __GPDATA, *D = &__GPDATA; static gp_hist __HIST; static gp_pp __PP; static gp_path __PATH, __SOPATH; static pari_timer __T, __Tw; D->flags = 0; D->factorlimit = D->primelimit = 1UL << 20; /* GP-specific */ D->breakloop = 1; D->echo = 0; D->lim_lines = 0; D->linewrap = 0; D->recover = 1; D->chrono = 0; D->strictargs = 0; D->strictmatch = 1; D->simplify = 1; D->secure = 0; D->use_readline= 0; D->T = &__T; D->Tw = &__Tw; D->hist = &__HIST; D->pp = &__PP; D->path = &__PATH; D->sopath=&__SOPATH; init_fmt(D); init_hist(D, 5000, 0); init_path(D->path, pari_default_path()); init_path(D->sopath, ""); init_pp(D); init_graphs(D); D->plothsizes = cgetalloc(1, t_VECSMALL); D->prompt_comment = (char*)"comment> "; D->prompt = pari_strdup("? "); D->prompt_cont = pari_strdup(""); D->help = init_help(); D->readline_state = DO_ARGS_COMPLETE; D->histfile = NULL; return D; } pari-2.17.2/src/language/init.h0000644000175000017500000076500114760125405014667 0ustar billbill/* This file is autogenerated from the database. */ /* See src/desc/gen_proto */ /* Do not edit*/ entree functions_basic[]={ {"!_",0,(void*)gnot,19,"G","!a: boolean operator \"not\"."}, {"#_",0,(void*)glength,19,"lG","#x: number of non code words in x, number of characters for a string."}, {"#_~",0,(void*)gtranslength,19,"lG","#x~: number of non code words in x~"}, {"%",0,(void*)pari_get_hist,19,"D0,L,","last history item."}, {"%#",0,(void*)pari_histtime,19,"D0,L,","time to compute last history item."}, {"+_",0,NULL,19,NULL,"+_: copy and return its argument"}, {"-_",0,(void*)gneg,19,"G","-_: negate argument"}, {"Catalan",0,(void*)mpcatalan,8,"p","Catalan=Catalan(): Catalan's number with current precision."}, {"Col",0,(void*)gtocol0,3,"GD0,L,","Col(x,{n}): transforms the object x into a column vector of dimension n."}, {"Colrev",0,(void*)gtocolrev0,3,"GD0,L,","Colrev(x,{n}): transforms the object x into a column vector of dimension n in reverse order with respect to Col(x,{n}). Empty vector if x is omitted."}, {"Euler",0,(void*)mpeuler,8,"p","Euler=Euler(): Euler's constant with current precision."}, {"I",0,(void*)gen_I,8,"","I=I(): square root of -1."}, {"List",0,(void*)gtolist,3,"DG","List({x=[]}): transforms the vector or list x into a list. Empty list if x is omitted."}, {"Map",0,(void*)gtomap,3,"DG","Map({x}): converts the matrix [a_1,b_1;a_2,b_2;...;a_n,b_n] to the map a_i->b_i."}, {"Mat",0,(void*)gtomat,3,"DG","Mat({x=[]}): transforms any GEN x into a matrix. Empty matrix if x is omitted."}, {"Mod",0,(void*)gmodulo,3,"GG","Mod(a,b): create 'a modulo b'."}, {"O",0,(void*)ggrando,6,"","O(p^e): p-adic or power series zero with precision given by e."}, {"O(_^_)",0,(void*)ggrando,21,"GD1,L,","O(p^e): p-adic or power series zero with precision given by e."}, {"Pi",0,(void*)mppi,8,"p","Pi=Pi(): the constant pi, with current precision."}, {"Pol",0,(void*)gtopoly,3,"GDn","Pol(t,{v='x}): convert t (usually a vector or a power series) into a polynomial with variable v, starting with the leading coefficient."}, {"Polrev",0,(void*)gtopolyrev,3,"GDn","Polrev(t,{v='x}): convert t (usually a vector or a power series) into a polynomial with variable v, starting with the constant term."}, {"Qfb",0,(void*)Qfb0,3,"GDGDG","Qfb(a,{b},{c}): binary quadratic form a*x^2+b*x*y+c*y^2."}, {"Ser",0,(void*)Ser0,3,"GDnDGDP","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,3,"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,3,"s*","Str({x}*): concatenates its (string) argument into a single string."}, {"Strchr",0,(void*)pari_strchr,1,"G","Strchr(x): deprecated alias for strchr."}, {"Strexpand",0,(void*)strexpand,1,"s*","Strexpand({x}*): deprecated alias for strexpand"}, {"Strprintf",0,(void*)strprintf,1,"ss*","Strprintf(fmt,{x}*): deprecated alias for strprintf."}, {"Strtex",0,(void*)strtex,1,"s*","Strtex({x}*): deprecated alias for strtex."}, {"Vec",0,(void*)gtovec0,3,"GD0,L,","Vec(x,{n}): transforms the object x into a vector of dimension n."}, {"Vecrev",0,(void*)gtovecrev0,3,"GD0,L,","Vecrev(x,{n}): transforms the object x into a vector of dimension n in reverse order with respect to Vec(x,{n})."}, {"Vecsmall",0,(void*)gtovecsmall0,3,"GD0,L,","Vecsmall(x,{n}): transforms the object x into a VECSMALL of dimension n."}, {"[_.._]",0,(void*)vecrange,21,"GG","[a..b] = [a,a+1,...,b]"}, {"[_|_<-_,_;_]",0,(void*)vecexpr1,21,"mGVDEDE","[a(x)|x<-b,c(x);...]"}, {"[_|_<-_,_]",0,(void*)vecexpr0,21,"GVDEDE","[a(x)|x<-b,c(x)] = apply(a,select(c,b))"}, {"_!",0,(void*)mpfact,19,"L","n!: factorial of n."}, {"_!=_",0,(void*)gne,19,"GG","a!=b: true if a and b are not equal."}, {"_#",0,(void*)mpprimorial,19,"L","n#: primorial of n."}, {"_%=_",0,(void*)gmode,19,"&G","x%=y: shortcut for x=x%y."}, {"_%_",0,(void*)gmod,19,"GG","x%y: Euclidean remainder of x and y."}, {"_&&_",0,(void*)andpari,19,"GE","a&&b: boolean operator \"and\"."}, {"_'",0,(void*)deriv,19,"GDn","x': derivative of x with respect to the main variable."}, {"_'_",0,(void*)derivn,19,"GLDn","x': derivative of x with respect to the main variable."}, {"_(_)",0,NULL,19,NULL,"f(a,b,...): evaluate the function f on a,b,..."}, {"_*=_",0,(void*)gmule,19,"&G","x*=y: shortcut for x=x*y."}, {"_*_",0,(void*)gmul,19,"GG","x*y: product of x and y."}, {"_++",0,(void*)gadd1e,19,"&","x++: set x to x+1."}, {"_+=_",0,(void*)gadde,19,"&G","x+=y: shortcut for x=x+y."}, {"_+_",0,(void*)gadd,19,"GG","x+y: sum of x and y."}, {"_--",0,(void*)gsub1e,19,"&","x--: set x to x-1."}, {"_-=_",0,(void*)gsube,19,"&G","x-=y: shortcut for x=x-y."}, {"_-_",0,(void*)gsub,19,"GG","x-y: difference of x and y."}, {"_.a1",0,(void*)member_a1,20,"mG","_.a1"}, {"_.a2",0,(void*)member_a2,20,"mG","_.a2"}, {"_.a3",0,(void*)member_a3,20,"mG","_.a3"}, {"_.a4",0,(void*)member_a4,20,"mG","_.a4"}, {"_.a6",0,(void*)member_a6,20,"mG","_.a6"}, {"_.area",0,(void*)member_area,20,"mG","_.area"}, {"_.b2",0,(void*)member_b2,20,"mG","_.b2"}, {"_.b4",0,(void*)member_b4,20,"mG","_.b4"}, {"_.b6",0,(void*)member_b6,20,"mG","_.b6"}, {"_.b8",0,(void*)member_b8,20,"mG","_.b8"}, {"_.bid",0,(void*)member_bid,20,"mG","_.bid"}, {"_.bnf",0,(void*)member_bnf,20,"mG","_.bnf"}, {"_.c4",0,(void*)member_c4,20,"mG","_.c4"}, {"_.c6",0,(void*)member_c6,20,"mG","_.c6"}, {"_.clgp",0,(void*)member_clgp,20,"mG","_.clgp"}, {"_.codiff",0,(void*)member_codiff,20,"mG","_.codiff"}, {"_.cyc",0,(void*)member_cyc,20,"mG","_.cyc"}, {"_.diff",0,(void*)member_diff,20,"mG","_.diff"}, {"_.disc",0,(void*)member_disc,20,"mG","_.disc"}, {"_.e",0,(void*)member_e,20,"mG","_.e"}, {"_.eta",0,(void*)member_eta,20,"mG","_.eta"}, {"_.f",0,(void*)member_f,20,"mG","_.f"}, {"_.fu",0,(void*)member_fu,20,"G","_.fu"}, {"_.gen",0,(void*)member_gen,20,"mG","_.gen"}, {"_.group",0,(void*)member_group,20,"mG","_.group"}, {"_.index",0,(void*)member_index,20,"mG","_.index"}, {"_.j",0,(void*)member_j,20,"mG","_.j"}, {"_.mod",0,(void*)member_mod,20,"mG","_.mod"}, {"_.nf",0,(void*)member_nf,20,"mG","_.nf"}, {"_.no",0,(void*)member_no,20,"mG","_.no"}, {"_.normfu",0,(void*)member_normfu,20,"mG","_.normfu"}, {"_.omega",0,(void*)member_omega,20,"mG","_.omega"}, {"_.orders",0,(void*)member_orders,20,"mG","_.orders"}, {"_.p",0,(void*)member_p,20,"mG","_.p"}, {"_.pol",0,(void*)member_pol,20,"mG","_.pol"}, {"_.polabs",0,(void*)member_polabs,20,"mG","_.polabs"}, {"_.r1",0,(void*)member_r1,20,"mG","_.r1"}, {"_.r2",0,(void*)member_r2,20,"mG","_.r2"}, {"_.reg",0,(void*)member_reg,20,"mG","_.reg"}, {"_.roots",0,(void*)member_roots,20,"mG","_.roots"}, {"_.sign",0,(void*)member_sign,20,"mG","_.sign"}, {"_.t2",0,(void*)member_t2,20,"G","_.t2"}, {"_.tate",0,(void*)member_tate,20,"mG","_.tate"}, {"_.tu",0,(void*)member_tu,20,"G","_.tu"}, {"_.zk",0,(void*)member_zk,20,"mG","_.zk"}, {"_.zkst",0,(void*)member_zkst,20,"mG","_.zkst"}, {"_/=_",0,(void*)gdive,19,"&G","x/=y: shortcut for x=x/y."}, {"_/_",0,(void*)gdiv,19,"GG","x/y: quotient of x and y."}, {"_<<=_",0,(void*)gshiftle,19,"&L","x<<=y: shortcut for x=x<=_",0,(void*)gge,19,"GG","x>=y: return 1 if x is greater or equal to y, 0 otherwise."}, {"_>>=_",0,(void*)gshiftre,19,"&L","x>>=y: shortcut for x=x>>y."}, {"_>>_",0,(void*)gshift_right,19,"GL","x>>y: compute shift(x,-y)."}, {"_>_",0,(void*)ggt,19,"GG","x>y: return 1 if x is strictly greater than y, 0 otherwise."}, {"_F2xq_log_Coppersmith_worker",0,(void*)F2xq_log_Coppersmith_worker,21,"GLGG","F2xq_log_Coppersmith_worker: worker for F2xq_log_Coppersmith"}, {"_Flxq_log_Coppersmith_worker",0,(void*)Flxq_log_Coppersmith_worker,21,"GLGG","Flxq_log_Coppersmith_worker: worker for Flxq_log_Coppersmith"}, {"_FpM_ratlift_worker",0,(void*)FpM_ratlift_worker,21,"GGG","worker for FpM_ratlift"}, {"_Fp_log_sieve_worker",0,(void*)Fp_log_sieve_worker,21,"LLGGGGGG","Fp_log_sieve_worker: worker for Fp_log_sieve"}, {"_QM_charpoly_ZX_worker",0,(void*)QM_charpoly_ZX_worker,21,"GGG","worker for QM_charpoly_ZX"}, {"_QXQ_div_worker",0,(void*)QXQ_div_worker,21,"GGGG","worker for QXQ_div"}, {"_QXQ_inv_worker",0,(void*)QXQ_inv_worker,21,"GGG","worker for QXQ_inv"}, {"_RgM_ZM_mul_worker",0,(void*)RgM_ZM_mul_worker,21,"GG","worker for RgM_ZM_mul"}, {"_ZM_det_worker",0,(void*)ZM_det_worker,21,"GG","worker for ZM_det"}, {"_ZM_gauss_worker",0,(void*)ZM_gauss_worker,21,"GGG","worker for ZM_gauss"}, {"_ZM_inv_worker",0,(void*)ZM_inv_worker,21,"GG","worker for ZM_inv"}, {"_ZM_ker_worker",0,(void*)ZM_ker_worker,21,"GG","worker for ZM_ker"}, {"_ZM_mul_worker",0,(void*)ZM_mul_worker,21,"GGG","worker for ZM_mul"}, {"_ZM_sqr_worker",0,(void*)ZM_sqr_worker,21,"GG","worker for ZM_sqr"}, {"_ZXQX_composedsum_worker",0,(void*)ZXQX_composedsum_worker,21,"GGGG","worker for ZXQX_composedsum"}, {"_ZXQX_resultant_worker",0,(void*)ZXQX_resultant_worker,21,"GGGGG","worker for ZXQX_resultant"}, {"_ZXQ_minpoly_worker",0,(void*)ZXQ_minpoly_worker,21,"GGGL","worker for ZXQ_minpoly"}, {"_ZX_ZXY_resultant_worker",0,(void*)ZX_ZXY_resultant_worker,21,"GGGGG","worker for ZX_ZXY_resultant"}, {"_ZX_composedsum_worker",0,(void*)ZX_composedsum_worker,21,"GGG","worker for ZX_composedsum"}, {"_ZX_gcd_worker",0,(void*)ZX_gcd_worker,21,"GGGG","worker for ZX_gcd"}, {"_ZX_resultant_worker",0,(void*)ZX_resultant_worker,21,"GGGG","worker for ZX_resultant"}, {"_ZabM_inv_worker",0,(void*)ZabM_inv_worker,21,"GGG","worker for ZabM_inv"}, {"_[_,]",0,NULL,19,NULL,"x[y,]: y-th row of x."}, {"_[_,_]",0,NULL,19,NULL,"x[i{,j}]: i coefficient of a vector, i,j coefficient of a matrix"}, {"_[_.._,_.._]",0,(void*)matslice0,19,"GD0,L,D0,L,D0,L,D0,L,","x[a..b,c..d] = [x[a,c], x[a+1,c], ...,x[b,c]; x[a,c+1],x[a+1,c+1],...,x[b,c+1]; ... ... ... x[a,d], x[a+1,d] ,...,x[b,d]]"}, {"_[_.._]",0,(void*)vecslice0,19,"GD0,L,L","x[a..b] = [x[a],x[a+1],...,x[b]]"}, {"_\\/=_",0,(void*)gdivrounde,19,"&G","x\\/=y: shortcut for x=x\\/y."}, {"_\\/_",0,(void*)gdivround,19,"GG","x\\/y: rounded Euclidean quotient of x and y."}, {"_\\=_",0,(void*)gdivente,19,"&G","x\\=y: shortcut for x=x\\y."}, {"_\\_",0,(void*)gdivent,19,"GG","x\\y: Euclidean quotient of x and y."}, {"_^_",0,(void*)gpow,19,"GGp","x^y: compute x to the power y."}, {"_^s",0,(void*)gpowgs,21,"GL","return x^n where n is a small integer"}, {"__",0,NULL,19,NULL,"__: integral concatenation of strings."}, {"_aprcl_step4_worker",0,(void*)aprcl_step4_worker,21,"UGGG","worker for isprime (APRCL step 4)"}, {"_aprcl_step6_worker",0,(void*)aprcl_step6_worker,21,"GLGGG","worker for isprime (APRCL step 6)"}, {"_chinese_unit_worker",0,(void*)chinese_unit_worker,21,"GGGGGG","worker for _.fu"}, {"_derivfun",0,(void*)derivfun0,21,"GGGD1,L,p","_derivfun(args,def,closure,k) numerical kth-derivation of closure with respect to the first variable at args"}, {"_dirartin_worker",0,(void*)dirartin_worker,21,"GUGGGG","lfunartin worker"}, {"_direllnf_worker",0,(void*)direllnf_worker,21,"GUG","ellan worker"}, {"_direllsympow_worker",0,(void*)direllsympow_worker,21,"GUGU","lfunsympow worker"}, {"_dirgenus2_worker",0,(void*)dirgenus2_worker,21,"GLG","lfungenus2 worker"}, {"_dirhgm_worker",0,(void*)dirhgm_worker,21,"GUGG","worker for hgmcoefs"}, {"_ecpp_ispsp_worker",0,(void*)ecpp_ispsp_worker,21,"G","worker for isprime (ECPP ispseudoprime step)"}, {"_ecpp_sqrt_worker",0,(void*)ecpp_sqrt_worker,21,"GGG","worker for isprime (ECPP sqrt step)"}, {"_ecpp_step2_worker",0,(void*)ecpp_step2_worker,21,"GGGL","worker for isprime (step 2)"}, {"_eisker_worker",0,(void*)eisker_worker,21,"GGGGG","worker for eisker"}, {"_ellQ_factorback_worker",0,(void*)ellQ_factorback_worker,21,"GGGGU","worker for ellQ_factorback"}, {"_eval_mnemonic",0,(void*)eval_mnemonic,21,"lGs","Convert a mnemonic string to a flag."}, {"_factor_Aurifeuille",0,(void*)factor_Aurifeuille,21,"GL","_factor_Aurifeuille(a,d): return an algebraic factor of Phi_d(a), a != 0"}, {"_factor_Aurifeuille_prime",0,(void*)factor_Aurifeuille_prime,21,"GL","_factor_Aurifeuille_prime(p,d): return an algebraic factor of Phi_d(p), p prime"}, {"_inv",0,(void*)ginv,21,"G","return x^-1 where n is a small integer"}, {"_lerch_worker",0,(void*)lerch_worker,21,"GG","_lerch_worker(E,t): worker for lerchzeta"}, {"_lfuninit_theta2_worker",0,(void*)lfuninit_theta2_worker,21,"LGGGGGG","worker for lfuninit using theta2"}, {"_lfuninit_worker",0,(void*)lfuninit_worker,21,"LGGGGGGGG","worker for lfuninit"}, {"_multi_if",0,(void*)ifpari_multi,21,"GE*","internal variant of if() that allows more than 3 arguments."}, {"_nflist_A462_worker",0,(void*)nflist_A462_worker,21,"GGGGG","nflist_A462_worker(P3,X,Xinf,listarch,GAL): auxiliary."}, {"_nflist_A46S46P_worker",0,(void*)nflist_A46S46P_worker,21,"GGGG","nflist_A46S46P_worker(P3,Xinf,sqX,cards): auxiliary."}, {"_nflist_A4S4_worker",0,(void*)nflist_A4S4_worker,21,"GGGG","nflist_A4S4_worker(P3,X,Xinf,cardsprec): auxiliary."}, {"_nflist_C32C4_worker",0,(void*)nflist_C32C4_worker,21,"GGGG","nflist_C32C4_worker(P4,X,Xinf,GAL): auxiliary."}, {"_nflist_C32D4_worker",0,(void*)nflist_C32D4_worker,21,"GGGG","nflist_C32D4_worker(P,X,Xinf,gs): auxiliary."}, {"_nflist_C3C3_worker",0,(void*)nflist_C3C3_worker,21,"GGGG","nflist_C3C3_worker(gi,V3,V3D,X): auxiliary."}, {"_nflist_C3_worker",0,(void*)nflist_C3_worker,21,"GG","nflist_C3_worker(gv,T): auxiliary."}, {"_nflist_C4vec_worker",0,(void*)nflist_C4vec_worker,21,"GGGG","nflist_C4vec_worker(gm,X,Xinf,X2,gs): auxiliary."}, {"_nflist_C5_worker",0,(void*)nflist_C5_worker,21,"GG","nflist_C5_worker(N,bnfC5): auxiliary."}, {"_nflist_C6_worker",0,(void*)nflist_C6_worker,21,"GGGGG","nflist_C6_worker(P3,X,Xinf,M,T): auxiliary."}, {"_nflist_C9_worker",0,(void*)nflist_C9_worker,21,"GGG","nflist_C9_worker(P,X,Xinf): auxiliary."}, {"_nflist_CL_worker",0,(void*)nflist_CL_worker,21,"GGG","nflist_CL_worker(Fcond,bnf,ellprec): auxiliary."}, {"_nflist_D4_worker",0,(void*)nflist_D4_worker,21,"GGGG","nflist_D4_worker(D,X,Xinf,listarch): auxiliary."}, {"_nflist_D612_worker",0,(void*)nflist_D612_worker,21,"GGGG","nflist_D612_worker(P3,X,Xinf,X2,limd2s2): auxiliary."}, {"_nflist_D9_worker",0,(void*)nflist_D9_worker,21,"GGG","nflist_D9_worker(P2,X,Xinf): auxiliary."}, {"_nflist_DL_worker",0,(void*)nflist_DL_worker,21,"GGGGGG","nflist_DL_worker(P2,X1p,X0p,X,Xinf,ells): auxiliary."}, {"_nflist_Mgen_worker",0,(void*)nflist_Mgen_worker,21,"GGGG","nflist_Mgen_worker(field,X,Xinf,ella): auxiliary."}, {"_nflist_S32_worker",0,(void*)nflist_S32_worker,21,"GGGGG","nflist_S32_worker(all1,X,Xinf,V3,sprec): auxiliary."}, {"_nflist_S36_worker",0,(void*)nflist_S36_worker,21,"GGG","nflist_S36_worker(pol,X,Xinf,X2): auxiliary."}, {"_nflist_S3C3_worker",0,(void*)nflist_S3C3_worker,21,"GGG","nflist_S3C3_worker(D2,X,Xinf,X2): auxiliary."}, {"_nflist_S3I_worker",0,(void*)nflist_S3I_worker,21,"GG","nflist_S3I_worker(ga,ALLCTS): auxiliary."}, {"_nflist_S3R_worker",0,(void*)nflist_S3R_worker,21,"GG","nflist_S3R_worker(ga,ALLCTS): auxiliary."}, {"_nflist_S462_worker",0,(void*)nflist_S462_worker,21,"GGGGG","nflist_S462_worker(P3,X,Xinf,listarch,GAL): auxiliary."}, {"_nflist_S46M_worker",0,(void*)nflist_S46M_worker,21,"GGGG","nflist_S46M_worker(P3,X,Xinf,sprec): auxiliary."}, {"_nflist_V4_worker",0,(void*)nflist_V4_worker,21,"GGGG","nflist_V4_worker(D1,X,Xinf,gs): auxiliary."}, {"_nxMV_polint_worker",0,(void*)nxMV_polint_center_tree_worker,21,"GGGGG","used for parallel chinese"}, {"_parapply_slice_worker",0,(void*)parapply_slice_worker,21,"GG","_parapply_slice_worker(v,C): return [C(x) | x<-v]."}, {"_pareval_worker",0,(void*)pareval_worker,21,"G","_pareval_worker(C): evaluate the closure C."}, {"_parfor_worker",0,(void*)parfor_worker,21,"GG","_parfor_worker(i,C): evaluate the closure C on i and return [i,C(i)]"}, {"_parsqf_worker",0,(void*)parsqf_worker,21,"GGG","_parsqf_worker(gk,vR,data): auxiliary."}, {"_parsum_slice_worker",0,(void*)parsum_slice_worker,21,"GGGG","_parsum_slice_worker(a,b,m,C): return sum(k=0,(b-a)\\m,C(a+k*m)). a and m must be integers and m must be positive."}, {"_parsumprimefun_worker",0,(void*)parsumprimefun_worker,21,"GGGGGG","_parsumprimefun_worker(gk,s,zerf,data,vW,f): auxiliary"}, {"_partmap_reverse_frac_worker",0,(void*)partmap_reverse_frac_worker,21,"GGGGGL","worker for partmap_reverse_frac"}, {"_parvector_worker",0,(void*)parvector_worker,21,"GG","_parvector_worker(i,C): evaluate the closure C on i."}, {"_polclass_worker",0,(void*)polclass_worker,21,"GGG","used by polclass"}, {"_polint_worker",0,(void*)nmV_polint_center_tree_worker,21,"GGGGG","used for parallel chinese"}, {"_polmodular_worker",0,(void*)polmodular_worker,21,"GUGGGGLGGGG","used by polmodular"}, {"_primecertisvalid_ecpp_worker",0,(void*)primecertisvalid_ecpp_worker,21,"G","worker for primecertisvalid"}, {"_ramanujantau_worker",0,(void*)ramanujantau_worker,21,"GGGG","worker for ramanujantau"}, {"_safecoeff",0,NULL,19,NULL,"safe version of x[a], x[,a] and x[a,b]. Must be lvalues."}, {"_serh_worker",0,(void*)serh_worker,21,"GGGGG","_serh_worker(gk,V,a,ns,gprec): auxiliary."}, {"_taugen_n_worker",0,(void*)taugen_n_worker,21,"GGG","worker for ramanujantau"}, {"_void_if",0,(void*)ifpari_void,21,"vGDIDI","internal variant of if() that does not return a value."}, {"_||_",0,(void*)orpari,19,"GE","a||b: boolean operator \"or\" (inclusive)."}, {"_~",0,(void*)gtrans,19,"G","x~: transpose of x."}, {"abs",0,(void*)gabs,8,"Gp","abs(x): absolute value (or modulus) of x."}, {"acos",0,(void*)gacos,8,"Gp","acos(x): arc cosine of x."}, {"acosh",0,(void*)gacosh,8,"Gp","acosh(x): inverse hyperbolic cosine of x."}, {"addhelp",0,(void*)addhelp,1,"vrs","addhelp(sym,str): add/change help message for the symbol sym."}, {"addprimes",0,(void*)addprimes,5,"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,8,"GGp","agm(x,y): arithmetic-geometric mean of x and y."}, {"airy",0,(void*)airy,8,"Gp","airy(z): Airy [Ai,Bi] function of argument z."}, {"alarm",0,(void*)gp_alarm,1,"D0,L,DE","alarm({s = 0},{code}): if code is omitted, trigger an \"e_ALARM\" exception after s seconds (wall-clock time), cancelling any previously set alarm; stop a pending alarm if s = 0 or is omitted. Otherwise, evaluate code, aborting after s seconds."}, {"algadd",0,(void*)algadd,11,"DGGG","algadd({al},x,y): element x+y in al (Hamilton quaternions if omitted)."}, {"algalgtobasis",0,(void*)algalgtobasis,11,"GG","algalgtobasis(al,x): transforms the element x of the algebra al into a column vector on the integral basis of al."}, {"algaut",0,(void*)algaut,11,"mG","algaut(al): the stored automorphism of the splitting field of the cyclic algebra al."}, {"algb",0,(void*)algb,11,"mG","algb(al): the element b of the center of the cyclic algebra al used to define it."}, {"algbasis",0,(void*)algbasis,11,"mG","algbasis(al): basis of the stored order of the central simple algebra al."}, {"algbasistoalg",0,(void*)algbasistoalg,11,"GG","algbasistoalg(al,x): transforms the column vector x on the integral basis of al into an element of al in algebraic form."}, {"algcenter",0,(void*)algcenter,11,"mG","algcenter(al): center of the algebra al."}, {"algcentralproj",0,(void*)alg_centralproj,11,"GGD0,L,","algcentralproj(al,z,{maps=0}): projections of the algebra al on the orthogonal central idempotents z[i]."}, {"algchar",0,(void*)algchar,11,"mG","algchar(al): characteristic of the algebra al."}, {"algcharpoly",0,(void*)algcharpoly,11,"DGGDnD0,L,","algcharpoly({al},b,{v='x},{abs=0}): (reduced) characteristic polynomial of b in al (Hamilton quaternions if omitted), with respect to the variable v."}, {"algdegree",0,(void*)algdegree,11,"lG","algdegree(al): degree of the central simple algebra al."}, {"algdep",0,(void*)algdep0,7,"GLD0,L,","algdep(z,k,{flag=0}): algebraic relations up to degree k of z, using lindep([1,z,...,z^(k-1)], flag)."}, {"algdim",0,(void*)algdim,11,"lGD0,L,","algdim(al,{abs=0}): dimension of the algebra al."}, {"algdisc",0,(void*)algdisc,11,"G","algdisc(al): discriminant of the stored order of the algebra al."}, {"algdivl",0,(void*)algdivl,11,"DGGG","algdivl({al},x,y): element x\\y in al (Hamilton quaternions if omitted)."}, {"algdivr",0,(void*)algdivr,11,"DGGG","algdivr({al},x,y): element x/y in al (Hamilton quaternions if omitted)."}, {"alggroup",0,(void*)alggroup,11,"GDG","alggroup(gal,{p=0}): constructs the group algebra of gal over Q (resp. Fp)."}, {"alggroupcenter",0,(void*)alggroupcenter,11,"GDGD&","alggroupcenter(gal,{p=0},{&cc}): constructs the center of the group algebra of gal over Q (resp. Fp), and sets cc to the conjugacy classes of gal."}, {"alghasse",0,(void*)alghasse,11,"GDG","alghasse(al,{pl}): the hasse invariant of the central simple algebra al at the place pl."}, {"alghassef",0,(void*)alghassef,11,"mG","alghassef(al): the hasse invariant of the central simple algebra al at finite places."}, {"alghassei",0,(void*)alghassei,11,"mG","alghassei(al): the hasse invariant of the central simple algebra al at infinite places."}, {"algindex",0,(void*)algindex,11,"lGDG","algindex(al,{pl}): the index of the central simple algebra al. If pl is set, it should be a prime ideal of the center or an integer between 1 and r1+r2, and in that case return the local index at the place pl instead."}, {"alginit",0,(void*)alginit,11,"GGDnD3,L,","alginit(B,C,{v},{flag=3}): initializes the central simple algebra defined by data B, C. Binary digits of the flag mean 1: compute a maximal order; 2: fully factor the discriminant instead of using a lazy factorisation."}, {"alginv",0,(void*)alginv,11,"DGG","alginv({al},x): element 1/x in al (Hamilton quaternions if omitted)."}, {"alginvbasis",0,(void*)alginvbasis,11,"mG","alginvbasis(al): basis of the natural order of the central simple algebra al in terms of the stored order."}, {"algisassociative",0,(void*)algisassociative,11,"iGD0,G,","algisassociative(mt,p=0): true (1) if the multiplication table mt is suitable for algtableinit(mt,p), false (0) otherwise."}, {"algiscommutative",0,(void*)algiscommutative,11,"iG","algiscommutative(al): test whether the algebra al is commutative."}, {"algisdivision",0,(void*)algisdivision,11,"iGDG","algisdivision(al,{pl}): tests whether the central simple algebra al is a division algebra. If pl is set, it should be a prime ideal of the center or an integer between 1 and r1+r2, and in that case tests whether al is locally a division algebra at the place pl instead."}, {"algisdivl",0,(void*)algisdivl,11,"iDGGGD&","algisdivl({al},x,y,{&z}): tests whether y is left divisible by x and sets z to the left quotient x\\y."}, {"algisinv",0,(void*)algisinv,11,"iDGGD&","algisinv({al},x,{&ix}): tests whether x is invertible in al (Hamilton quaternions if omitted) and sets ix to the inverse of x."}, {"algisramified",0,(void*)algisramified,11,"iGDG","algisramified(al,{pl}): tests whether the central simple algebra al is ramified, i.e. not isomorphic to a matrix ring over its center. If pl is set, it should be a prime ideal of the center or an integer between 1 and r1+r2, and in that case tests whether al is locally ramified at the place pl instead."}, {"algissemisimple",0,(void*)algissemisimple,11,"iG","algissemisimple(al): test whether the algebra al is semisimple."}, {"algissimple",0,(void*)algissimple,11,"iGD0,L,","algissimple(al,{ss=0}): test whether the algebra al is simple."}, {"algissplit",0,(void*)algissplit,11,"iGDG","algissplit(al,{pl}): tests whether the central simple algebra al is split, i.e. isomorphic to a matrix ring over its center. If pl is set, it should be a prime ideal of the center or an integer between 1 and r1+r2, and in that case tests whether al is locally split at the place pl instead."}, {"alglatadd",0,(void*)alglatadd,11,"GGGD&","alglatadd(al,lat1,lat2,{&ptinter}): the sum of the lattices lat1 and lat2. If ptinter is present, set it to the intersection of the lattices."}, {"alglatcontains",0,(void*)alglatcontains,11,"iGGGD&","alglatcontains(al,lat,x,{&ptc}): tests whether the lattice lat contains the element x. If ptc is present, sets it to the coordinates of x on the basis of lat."}, {"alglatelement",0,(void*)alglatelement,11,"GGG","alglatelement(al,lat,c): returns the element of al whose coordinates on the Z-basis of lat are c."}, {"alglathnf",0,(void*)alglathnf,11,"GGD0,G,","alglathnf(al,m,{d=0}): the lattice generated by the columns of m, assuming that this lattice contains d times the integral basis of al."}, {"alglatindex",0,(void*)alglatindex,11,"GGG","alglatindex(al,lat1,lat2): the generalized index (lat2:lat1)."}, {"alglatinter",0,(void*)alglatinter,11,"GGGD&","alglatinter(al,lat1,lat2,{&ptsum}): the intersection of the lattices lat1 and lat2. If ptsum is present, sets it to the sum of the lattices."}, {"alglatlefttransporter",0,(void*)alglatlefttransporter,11,"GGG","alglatlefttransporter(al,lat1,lat2): the set of x in al such that x*lat1 is contained in lat2."}, {"alglatmul",0,(void*)alglatmul,11,"GGG","alglatmul(al,lat1,lat2): the lattice generated by the products of elements of lat1 and lat2."}, {"alglatrighttransporter",0,(void*)alglatrighttransporter,11,"GGG","alglatrighttransporter(al,lat1,lat2): the set of x in al such that lat1*x is contained in lat2."}, {"alglatsubset",0,(void*)alglatsubset,11,"iGGGD&","alglatsubset(al,lat1,lat2,{&ptindex}): tests whether lat1 is contained in lat2 and if true and ptindex is present, sets it to the index (lat2:lat1)."}, {"algmakeintegral",0,(void*)algmakeintegral,11,"GD0,L,","algmakeintegral(mt,{maps=0}): computes an integral multiplication table for an isomorphic algebra."}, {"algmul",0,(void*)algmul,11,"DGGG","algmul({al},x,y): element x*y in al (Hamilton quaternions if omitted)."}, {"algmultable",0,(void*)algmultable,11,"mG","algmultable(al): multiplication table of al over its prime subfield."}, {"algneg",0,(void*)algneg,11,"DGG","algneg({al},x): element -x in al (Hamilton quaternions if omitted)."}, {"algnorm",0,(void*)algnorm,11,"DGGD0,L,","algnorm({al},x,{abs=0}): (reduced) norm of x."}, {"algpoleval",0,(void*)algpoleval,11,"DGGG","algpoleval({al},T,b): T in K[X] evaluate T(b) in al (Hamilton quaternions if omitted)."}, {"algpow",0,(void*)algpow,11,"DGGG","algpow({al},x,n): element x^n in al (Hamilton quaternions if omitted)."}, {"algprimesubalg",0,(void*)algprimesubalg,11,"G","algprimesubalg(al): prime subalgebra of the positive characteristic, semisimple algebra al."}, {"algquotient",0,(void*)alg_quotient,11,"GGD0,L,","algquotient(al,I,{maps=0}): quotient of the algebra al by the two-sided ideal I."}, {"algradical",0,(void*)algradical,11,"G","algradical(al): Jacobson radical of the algebra al."}, {"algramifiedplaces",0,(void*)algramifiedplaces,11,"G","algramifiedplaces(al): vector of the places of the center of al that ramify in al. Each place is described as an integer between 1 and r1 or as a prime ideal."}, {"algrandom",0,(void*)algrandom,11,"DGG","algrandom({al},b): random element in al (Hamilton quaternions if omitted) with coefficients in [-b,b]."}, {"algrelmultable",0,(void*)algrelmultable,11,"mG","algrelmultable(al): multiplication table of the central simple algebra al over its center."}, {"algsimpledec",0,(void*)algsimpledec,11,"GD0,L,","algsimpledec(al,{maps=0}): [J,dec] where J is the Jacobson radical of al and dec is the decomposition into simple algebras of the semisimple algebra al/J."}, {"algsplit",0,(void*)algsplit,11,"GDn","algsplit(al,{v='x}): computes an isomorphism between al and M_d(F_q)."}, {"algsplittingdata",0,(void*)algsplittingdata,11,"mG","algsplittingdata(al): data stored in the central simple algebra al to compute a splitting of al over an extension."}, {"algsplittingfield",0,(void*)algsplittingfield,11,"mG","algsplittingfield(al): the stored splitting field of the central simple algebra al."}, {"algsqr",0,(void*)algsqr,11,"DGG","algsqr({al},x): element x^2 in al (Hamilton quaternions if omitted)."}, {"algsub",0,(void*)algsub,11,"DGGG","algsub({al},x,y): element x-y in al (Hamilton quaternions if omitted)."}, {"algsubalg",0,(void*)algsubalg,11,"GG","algsubalg(al,B): subalgebra of al with basis B."}, {"algtableinit",0,(void*)algtableinit,11,"GDG","algtableinit(mt,{p=0}): initializes the associative algebra over Q (resp. Fp) defined by the multiplication table mt."}, {"algtensor",0,(void*)algtensor,11,"GGD3,L,","algtensor(al1,al2,{flag=3}): tensor product of al1 and al2."}, {"algtomatrix",0,(void*)algtomatrix,11,"DGGD0,L,","algtomatrix({al},x,{abs=0}): left multiplication table of x (table algebra or abs=1) or image of x under a splitting of al (CSA and abs=0)."}, {"algtrace",0,(void*)algtrace,11,"DGGD0,L,","algtrace({al},x,{abs=0}): (reduced) trace of x."}, {"algtype",0,(void*)algtype,11,"lG","algtype(al): type of the algebra al."}, {"alias",0,(void*)alias0,1,"vrr","alias(newsym,sym): defines the symbol newsym as an alias for the symbol sym."}, {"allocatemem",0,(void*)gp_allocatemem,1,"vDG","allocatemem({s=0}): allocates a new stack of s bytes. doubles the stack if s is omitted."}, {"apply",0,(void*)apply0,1,"GG","apply(f,A): apply function f to each entry in A."}, {"arg",0,(void*)garg,8,"Gp","arg(x): argument of x, such that -pi= x."}, {"centerlift",0,(void*)centerlift0,3,"GDn","centerlift(x,{v}): centered lift of x. Same as lift except for intmod and padic components."}, {"characteristic",0,(void*)characteristic,3,"mG","characteristic(x): characteristic of the base ring over which x is defined."}, {"charconj",0,(void*)charconj0,5,"GG","charconj(cyc,chi): given a finite abelian group (by its elementary divisors cyc) and a character chi, return the conjugate character."}, {"chardiv",0,(void*)chardiv0,5,"GGG","chardiv(cyc,a,b): given a finite abelian group (by its elementary divisors cyc) and two characters a and b, return the character a/b."}, {"chareval",0,(void*)chareval,5,"GGGDG","chareval(G,chi,x,{z}): given an abelian group structure affording a discrete logarithm method, e.g. G = znstar(N,1) or a bnr structure, let x be an element of G and let chi be a character of G. This function returns the value of chi at x, where the encoding depends on the optional argument z; if z is omitted, we fix a canonical o-th root of 1, zeta_o, where o is the character order and return the rational number c/o where chi(x) = (zeta_o)^c."}, {"chargalois",0,(void*)chargalois,5,"GDG","chargalois(cyc,{ORD}): let cyc represent a finite abelian group G by its elementary divisors cyc, return a list of representatives for the Galois orbits of characters of G. If ORD is present, select characters depending on their orders: if ORD is a t_INT, restrict to orders less than this bound; if ORD is a t_VEC or t_VECSMALL, restrict to orders in the list."}, {"charker",0,(void*)charker0,5,"GG","charker(cyc,chi): given a finite abelian group (by its elementary divisors cyc) and a character chi, return its kernel."}, {"charmul",0,(void*)charmul0,5,"GGG","charmul(cyc,a,b): given a finite abelian group (by its elementary divisors cyc) and two characters a and b, return the product character ab."}, {"charorder",0,(void*)charorder0,5,"GG","charorder(cyc,chi): given a finite abelian group (by its elementary divisors cyc) and a character chi, return the order of chi."}, {"charpoly",0,(void*)charpoly0,7,"GDnD5,L,","charpoly(A,{v='x},{flag=5}): det(v*Id-A)=characteristic polynomial of the matrix or polmod A. flag is optional and ignored unless A is a matrix; it may be set to 0 (Le Verrier), 1 (Lagrange interpolation), 2 (Hessenberg form), 3 (Berkowitz), 4 (modular) if A is integral, or 5 (default, choose best method). Algorithms 0 (Le Verrier) and 1 (Lagrange) assume that n! is invertible, where n is the dimension of the matrix."}, {"charpow",0,(void*)charpow0,5,"GGG","charpow(cyc,a,n): given a finite abelian group (by its elementary divisors cyc) a character a and an integer n return the character a^n."}, {"chinese",0,(void*)chinese,5,"GDG","chinese(x,{y}): x,y being both intmods (or polmods) computes z in the same residue classes as x and y."}, {"cmp",0,(void*)cmp_universal,2,"iGG","cmp(x,y): compare two arbitrary objects x and y (1 if x>y, 0 if x=y, -1 if x=0} M[n+1]z^n, transform it into a continued fraction suitable for evaluation."}, {"contfracpnqn",0,(void*)contfracpnqn,5,"GD-1,L,","contfracpnqn(x,{n=-1}): [p_n,p_{n-1}; q_n,q_{n-1}] corresponding to the continued fraction x. If n >= 0 is present, returns all convergents from p_0/q_0 up to p_n/q_n."}, {"core",0,(void*)core0,5,"GD0,L,","core(n,{flag=0}): unique squarefree integer d dividing n such that n/d is a square. If (optional) flag is nonzero, 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,5,"GD0,L,","coredisc(n,{flag=0}): discriminant of the quadratic field Q(sqrt(n)). If (optional) flag is nonzero, 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,8,"Gp","cos(x): cosine of x."}, {"cosh",0,(void*)gcosh,8,"Gp","cosh(x): hyperbolic cosine of x."}, {"cotan",0,(void*)gcotan,8,"Gp","cotan(x): cotangent of x."}, {"cotanh",0,(void*)gcotanh,8,"Gp","cotanh(x): hyperbolic cotangent of x."}, {"dbg_x",0,(void*)dbgGEN,1,"vGD-1,L,","dbg_x(A,{n}): print inner structure of A, complete if n is omitted, up to level n otherwise. Intended for debugging."}, {"default",0,(void*)default0,1,"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*)denominator,3,"GDG","denominator(f,{D}): denominator of f."}, {"deriv",0,(void*)deriv,6,"GDn","deriv(x,{v}): derivative of x with respect to v, or to the main variable of x if v is omitted."}, {"derivn",0,(void*)derivn,6,"GLDn","derivn(x,n,{v}): n-th derivative of x with respect to v, or to the main variable of x if v is omitted."}, {"derivnum",0,(void*)derivnum0,9,"V=GEDGp","derivnum(X=a,expr,{ind=1}): numerical derivation of expr with respect to X at X = a. The order of derivation is given by parameter 'ind', which can be a vector."}, {"diffop",0,(void*)diffop0,6,"GGGD1,L,","diffop(x,v,d,{n=1}): apply the differential operator D to x, where D is defined by D(v[i])=d[i], where v is a vector of variable names. D is 0 for variables outside of v unless they appear as modulus of a POLMOD. If the optional parameter n is given, return D^n(x) instead."}, {"digits",0,(void*)digits,3,"GDG","digits(x,{b}): gives the vector formed by the digits of x in base b."}, {"dilog",0,(void*)dilog,8,"Gp","dilog(x): dilogarithm of x."}, {"dirdiv",0,(void*)dirdiv,5,"GG","dirdiv(x,y): division of the Dirichlet series x by the Dirichlet series y."}, {"direuler",0,(void*)direuler0,5,"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,5,"GG","dirmul(x,y): multiplication of the Dirichlet series x by the Dirichlet series y."}, {"dirpowers",0,(void*)dirpowers,7,"LGp","dirpowers(n,x): return the vector [1^x,2^x,...,n^x]."}, {"dirpowerssum",0,(void*)dirpowerssum0,5,"GGDGD0,L,p","dirpowerssum(N,x,{f},{both=0}): return f(1)1^x + f(2)2^x + ... + f(N)N^x, where f is a completely multiplicative function (= 1 if omitted). If both is set, return the pair for arguments (x, f) and (-1-x, conj(f)). If both=2, assume in addition that f is real-valued."}, {"dirzetak",0,(void*)dirzetak,10,"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*)divisors0,5,"GD0,L,","divisors(x,{flag=0}): gives a vector formed by the divisors of x in increasing order. If flag = 1, return pairs [d, factor(d)]."}, {"divisorslenstra",0,(void*)divisorslenstra,5,"GGG","divisorslenstra(N,r,s): finds all divisors d of N such that d = r (mod s). Assume that (r,s) = 1 and s^3 > N."}, {"divrem",0,(void*)divrem,2,"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,8,"GDGp","eint1(x,{n}): exponential integral E1(x). If n is present and x > 0, computes the vector of the first n values of the exponential integral E1(n x)."}, {"ell2cover",0,(void*)ell2cover,12,"Gp","ell2cover(E): if E is an elliptic curve over Q, returns a basis of the set of everywhere locally soluble 2-covers of the curve E. For each cover a pair [R,P] is returned where y^2-R(x) is a quartic curve and P belongs to E(k), where k = Q(x)[y] / (y^2-R(x))."}, {"ellE",0,(void*)ellE,8,"Gp","ellE(k): Complete elliptic integral of the second kind for the complex parameter k using the agm."}, {"ellK",0,(void*)ellK,8,"Gp","ellK(k): Complete elliptic integral of the first kind for the complex parameter k using the agm."}, {"ellL1",0,(void*)ellL1,12,"GD0,L,b","ellL1(E,{r=0}): returns the value at s=1 of the derivative of order r of the L-function of the elliptic curve E."}, {"elladd",0,(void*)elladd,12,"GGG","elladd(E,z1,z2): sum of the points z1 and z2 on elliptic curve E."}, {"ellak",0,(void*)akell,12,"GG","ellak(E,n): computes the n-th Fourier coefficient of the L-function of the elliptic curve E (assumes E is an integral model)."}, {"ellan",0,(void*)ellan,12,"GL","ellan(E,n): computes the first n Fourier coefficients of the L-function of the elliptic curve E defined over a number field."}, {"ellanalyticrank",0,(void*)ellanalyticrank,12,"GDGb","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 nonzero derivative. To determine this order, it is assumed that any value less than eps is zero. If no value of eps is given, 2^(-bitprecision/2) is used."}, {"ellap",0,(void*)ellap,12,"GDG","ellap(E,{p}): given an elliptic curve E defined over a finite field Fq, return the trace of Frobenius a_p = q+1-#E(Fq); for other fields of definition K, p must define a finite residue field, (p prime for K = Qp or Q; p a maximal ideal for K a number field), return the order of the (nonsingular) reduction of E."}, {"ellbil",0,(void*)bilhell,12,"GGGp","ellbil(E,z1,z2): deprecated alias for ellheight(E,P,Q)."}, {"ellbsd",0,(void*)ellbsd,12,"Gp","ellbsd(E): E being an elliptic curve over a number field, returns a real number c such that the BSD conjecture predicts that lfun(E,1,r)/r! = c*R*S where r is the rank, R is the regulator and S is the cardinal of the Tate-Shafarevich group."}, {"ellcard",0,(void*)ellcard,12,"GDG","ellcard(E,{p}): given an elliptic curve E defined over a finite field Fq, return the order of the group E(Fq); for other fields of definition K, p must define a finite residue field, (p prime for K = Qp or Q; p a maximal ideal for K a number field), return the order of the (nonsingular) reduction of E."}, {"ellchangecurve",0,(void*)ellchangecurve,12,"GG","ellchangecurve(E,v): change data on elliptic curve according to v=[u,r,s,t]."}, {"ellchangepoint",0,(void*)ellchangepoint,12,"GG","ellchangepoint(x,v): change data on point or vector of points x on an elliptic curve according to v=[u,r,s,t]."}, {"ellchangepointinv",0,(void*)ellchangepointinv,12,"GG","ellchangepointinv(x,v): change data on point or vector of points x on an elliptic curve according to v=[u,r,s,t], inverse of ellchangepoint."}, {"ellconvertname",0,(void*)ellconvertname,12,"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,12,"GLDn","elldivpol(E,n,{v='x}): n-division polynomial f_n for the curve E in the variable v."}, {"elleisnum",0,(void*)elleisnum,12,"GLD0,L,p","elleisnum(w,k,{flag=0}): k being an even positive integer, computes the numerical value of the Eisenstein series of weight k at the lattice w, as given by ellperiods. When flag is nonzero and k=4 or 6, this gives the elliptic invariants g2 or g3 with the correct normalization."}, {"elleta",0,(void*)elleta,12,"Gp","elleta(w): w=[w1,w2], returns the vector [eta1,eta2] of quasi-periods attached to [w1,w2]."}, {"ellformaldifferential",0,(void*)ellformaldifferential,12,"GDPDn","ellformaldifferential(E,{n=seriesprecision},{t='x}) : E elliptic curve, n integer. Returns n terms of the power series [f, g] such that omega = dx/(2y+a_1x+a_3) = f(t) dt and eta = x(t) * omega = g(t) dt in the local parameter t=-x/y."}, {"ellformalexp",0,(void*)ellformalexp,12,"GDPDn","ellformalexp(E,{n=seriesprecision},{z='x}): E elliptic curve, returns n terms of the formal elliptic exponential on E as a series in z."}, {"ellformallog",0,(void*)ellformallog,12,"GDPDn","ellformallog(E,{n=seriesprecision},{v='x}): E elliptic curve, returns n terms of the elliptic logarithm as a series of t =-x/y."}, {"ellformalpoint",0,(void*)ellformalpoint,12,"GDPDn","ellformalpoint(E,{n=seriesprecision},{v='x}): E elliptic curve, n integer; return the coordinates [x(t), y(t)] on the elliptic curve as a formal expansion in the formal parameter t = -x/y."}, {"ellformalw",0,(void*)ellformalw,12,"GDPDn","ellformalw(E,{n=seriesprecision},{t='x}): E elliptic curve, n integer; returns n terms of the formal expansion of w = -1/y in the formal parameter t = -x/y."}, {"ellfromeqn",0,(void*)ellfromeqn,12,"G","ellfromeqn(P): given a genus 1 plane curve, defined by the affine equation f(x,y) = 0, return the coefficients [a1,a2,a3,a4,a6] of a Weierstrass equation for its Jacobian. This allows to recover a Weierstrass model for an elliptic curve given by a general plane cubic or by a binary quartic or biquadratic model."}, {"ellfromj",0,(void*)ellfromj,12,"G","ellfromj(j): returns the coefficients [a1,a2,a3,a4,a6] of a fixed elliptic curve with j-invariant j."}, {"ellgenerators",0,(void*)ellgenerators,12,"G","ellgenerators(E): if E is an elliptic curve over the rationals, return the generators of the Mordell-Weil group attached to the curve. This relies on the curve being referenced in the elldata database. If E is an elliptic curve over a finite field Fq as output by ellinit(), return a minimal set of generators for the group E(Fq)."}, {"ellglobalred",0,(void*)ellglobalred,12,"G","ellglobalred(E): E being an elliptic curve over a number field, returns [N, v, c, faN, L], where N is the conductor of E, c is the product of the local Tamagawa numbers c_p, faN is the factorization of N and L[i] is elllocalred(E, faN[i,1]); v is an obsolete field."}, {"ellgroup",0,(void*)ellgroup0,12,"GDGD0,L,","ellgroup(E,{p},{flag}): given an elliptic curve E defined over a finite field Fq, returns the structure of the group E(Fq); for other fields of definition K, p must define a finite residue field (p prime for K = Qp or Q; p a maximal ideal for K a number field) and we return the structure of the (nonsingular) reduction of E. If flag is 1, also returns generators, but the curve equation must be minimal at p."}, {"ellheegner",0,(void*)ellheegner,12,"G","ellheegner(E): return a rational nontorsion point on the elliptic curve E assumed to be of rank 1."}, {"ellheight",0,(void*)ellheight0,12,"GDGDGp","ellheight(E,{P},{Q}): Faltings height of the curve E, resp. canonical height of the point P on elliptic curve E, resp. the value of the attached bilinear form at (P,Q)."}, {"ellheightmatrix",0,(void*)ellheightmatrix,12,"GGp","ellheightmatrix(E,x): gives the height matrix for vector of points x on elliptic curve E."}, {"ellidentify",0,(void*)ellidentify,12,"G","ellidentify(E): look up the elliptic curve E in the elldata database and return [[N, M, ...], C] where N is the name of the curve in Cremona's database, M the minimal model and C the change of coordinates (see ellchangecurve)."}, {"ellinit",0,(void*)ellinit,12,"GDGp","ellinit(x,{D=1}): let x be a vector [a1,a2,a3,a4,a6], or [a4,a6] if a1=a2=a3=0, defining the curve Y^2 + a1.XY + a3.Y = X^3 + a2.X^2 + a4.X + a6; x can also be a string, in which case the curve with matching name is retrieved from the elldata database, if available. This function initializes an elliptic curve over the domain D (inferred from coefficients if omitted)."}, {"ellintegralmodel",0,(void*)ellintegralmodel,12,"GD&","ellintegralmodel(E,{&v}): given an elliptic curve E defined over a number field or Qp, returns an integral model. If v is present, sets the variable v to the corresponding change of variable."}, {"elliscm",0,(void*)elliscm,12,"lG","elliscm(E): return 0 if the elliptic curve E, defined over a number field, is not CM, otherwise return the discriminant of its endomorphism ring."}, {"ellisdivisible",0,(void*)ellisdivisible,12,"lGGGD&","ellisdivisible(E,P,n,{&Q}): given E/K and P in E(K), checks whether P = [n]R for some R in E(K) and sets Q to one such R if so; the integer n >= 0 may be given as ellxn(E,n)."}, {"ellisisom",0,(void*)ellisisom,12,"GG","ellisisom(E,F): return 0 if the elliptic curves E and F defined over the same number field are not isomorphic, otherwise return [u,r,s,t] suitable for ellchangecurve, mapping E to F."}, {"ellisogeny",0,(void*)ellisogeny,12,"GGD0,L,DnDn","ellisogeny(E,G,{only_image=0},{x='x},{y='y}): compute the image and isogeny corresponding to the quotient of E by the subgroup G."}, {"ellisogenyapply",0,(void*)ellisogenyapply,12,"GG","ellisogenyapply(f,g): given an isogeny f and g either a point P (in the domain of f) or an isogeny, apply f to g: return the image of P under f or the composite isogeny f o g."}, {"ellisomat",0,(void*)ellisomat,12,"GD0,L,D0,L,","ellisomat(E,{p=0},{flag=0}): E being an elliptic curve over a number field K, returns a list of representatives of the isomorphism classes of elliptic curves defined over K and K-isogenous to E, with the corresponding isogenies from E and their dual, and the matrix of the isogeny degrees between the curves. If flag is 1, the isogenies are not computed, which saves time. If p is set, it must be a prime number: in this case only isogenies of degree a power of p are considered."}, {"ellisoncurve",0,(void*)ellisoncurve,12,"GG","ellisoncurve(E,z): true(1) if z is on elliptic curve E, false(0) if not."}, {"ellisotree",0,(void*)ellisotree,12,"G","ellisotree(E): E being an elliptic curve over Q or a set of isogenous rational curves as given by ellisomat, return minimal models of the isomorphism classes of elliptic curves isogenous to E (or in the set) and the oriented graph of isogenies of prime degree (adjacency matrix)."}, {"ellissupersingular",0,(void*)ellissupersingular,12,"iGDG","ellissupersingular(E,{p}): return 1 if the elliptic curve E, defined over a number field or a finite field, is supersingular at p, and 0 otherwise."}, {"ellj",0,(void*)jell,12,"Gp","ellj(x): elliptic j invariant of x."}, {"elllocalred",0,(void*)elllocalred,12,"GDG","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,12,"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,12,"GGDGp","elllseries(E,s,{A=1}): L-series at s of the elliptic curve E, where A a cut-off point close to 1."}, {"ellmaninconstant",0,(void*)ellmaninconstant,12,"G","ellmaninconstant(E): let E be an elliptic curve over Q given by ellinit or a rational isogeny class given by ellisomat. Return the Manin constant of the curve, see ellweilcurve. The algorithm is slow but unconditional."}, {"ellminimaldisc",0,(void*)ellminimaldisc,12,"G","ellminimaldisc(E): E being an elliptic curve defined over a number field output by ellinit, return the minimal discriminant ideal of E."}, {"ellminimalmodel",0,(void*)ellminimalmodel,12,"GD&","ellminimalmodel(E,{&v}): determines whether the elliptic curve E defined over a number field admits a global minimal model. If so return it and sets v to the corresponding change of variable. Else return the (nonprincipal) Weierstrass class of E."}, {"ellminimaltwist",0,(void*)ellminimaltwist0,12,"GD0,L,","ellminimaltwist(E,{flag=0}): E being an elliptic curve defined over Q, return a discriminant D such that the twist of E by D is minimal among all possible quadratic twists, i.e., if flag=0, its minimal model has minimal discriminant, or if flag=1, it has minimal conductor."}, {"ellmoddegree",0,(void*)ellmoddegree,12,"G","ellmoddegree(e): e being an elliptic curve defined over Q output by ellinit, compute the modular degree of e divided by the square of the Manin constant."}, {"ellmodulareqn",0,(void*)ellmodulareqn,12,"LDnDn","ellmodulareqn(N,{x},{y}): given a prime N < 500, return a vector [P, t] where P(x,y) is a modular equation of level N. This requires the package seadata. The equation is either of canonical type (t=0) or of Atkin type (t=1)."}, {"ellmul",0,(void*)ellmul,12,"GGG","ellmul(E,z,n): n times the point z on elliptic curve E (n in Z)."}, {"ellneg",0,(void*)ellneg,12,"GG","ellneg(E,z): opposite of the point z on elliptic curve E."}, {"ellnonsingularmultiple",0,(void*)ellnonsingularmultiple,12,"GG","ellnonsingularmultiple(E,P): given E/Q and P in E(Q), returns the pair [R,n] where n is the least positive integer such that R = [n]P has everywhere good reduction. More precisely, its image in a minimal model is everywhere nonsingular."}, {"ellorder",0,(void*)ellorder,12,"GGDG","ellorder(E,z,{o}): order of the point z on the elliptic curve E over a number field or a finite field, 0 if nontorsion. The parameter o, if present, represents a nonzero multiple of the order of z."}, {"ellordinate",0,(void*)ellordinate,12,"GGp","ellordinate(E,x): y-coordinates corresponding to x-ordinate x on elliptic curve E."}, {"ellpadicL",0,(void*)ellpadicL,12,"GGLDGD0,L,DG","ellpadicL(E,p,n,{s=0},{r=0},{D=1}): returns the value on a character of Z_{p}^* represented by an integer s or a vector [s1,s2] of the derivative of order r of the p-adic L-function of the elliptic curve E (twisted by D, if present)."}, {"ellpadicbsd",0,(void*)ellpadicbsd,12,"GGLDG","ellpadicbsd(E,p,n,{D=1}): returns [r,Lp] where r is the (conjectural) analytic rank of the p-adic L-function attached to the quadratic twist E_D and Lp is (conjecturally) equal to the product of the p-adic regulator and the cardinal of the Tate-Shafarevich group."}, {"ellpadicfrobenius",0,(void*)ellpadicfrobenius,12,"GUL","ellpadicfrobenius(E,p,n): matrix of the Frobenius at p>2 in the standard basis of H^1_dR(E) to absolute p-adic precision p^n."}, {"ellpadicheight",0,(void*)ellpadicheight0,12,"GGLGDG","ellpadicheight(E,p,n,P,{Q}): E elliptic curve/Q, P in E(Q), p prime, n an integer; returns the cyclotomic p-adic heights of P. Resp. the value of the attached bilinear form at (P,Q)."}, {"ellpadicheightmatrix",0,(void*)ellpadicheightmatrix,12,"GGLG","ellpadicheightmatrix(E,p,n,Q): gives the height-pairing matrix for vector of points Q on elliptic curve E."}, {"ellpadiclambdamu",0,(void*)ellpadiclambdamu,12,"GLD1,L,D0,L,","ellpadiclambdamu(E,p,{D=1},{i=0}): returns the Iwasawa invariants for the p-adic L-function attached to E, twisted by (D,.) and the i-th power of the Teichmuller character."}, {"ellpadiclog",0,(void*)ellpadiclog,12,"GGLG","ellpadiclog(E,p,n,P): returns the logarithm of P (in the kernel of reduction) to relative p-adic precision p^n."}, {"ellpadicregulator",0,(void*)ellpadicregulator,12,"GGLG","ellpadicregulator(E,p,n,S): E elliptic curve/Q, S a vector of points in E(Q), p prime, n an integer; returns the p-adic cyclotomic regulator of the points of S at precision p^n."}, {"ellpadics2",0,(void*)ellpadics2,12,"GGL","ellpadics2(E,p,n): returns s2 to absolute p-adic precision p^n."}, {"ellperiods",0,(void*)ellperiods,12,"GD0,L,p","ellperiods(w,{flag=0}): w describes a complex period lattice ([w1,w2] or an ellinit structure). Returns normalized periods [W1,W2] generating the same lattice such that tau := W1/W2 satisfies Im(tau) > 0 and lies in the standard fundamental domain for SL2. If flag is 1, the return value is [[W1,W2], [e1,e2]], where e1, e2 are the quasi-periods attached to [W1,W2], satisfying e2 W1 - e1 W2 = 2 Pi I."}, {"ellpointtoz",0,(void*)zell,12,"GGp","ellpointtoz(E,P): lattice point z corresponding to the point P on the elliptic curve E."}, {"ellpow",0,(void*)ellmul,12,"GGG","ellpow(E,z,n): deprecated alias for ellmul."}, {"ellrank",0,(void*)ellrank,12,"GD0,L,DGp","ellrank(E,{effort=0},{points}): if E is an elliptic curve over Q, attempts to compute the Mordell-Weil group attached to the curve. The output is [r1,r2,s,L], where r1 <= rank(E) <= r2, s gives information on the Tate-Shafarevich group (see documentation), and and L is a list of independent, non-torsion rational points on the curve. E can also be given as the output of ellrankinit(E)."}, {"ellrankinit",0,(void*)ellrankinit,12,"Gp","ellrankinit(E): if E is an elliptic curve over Q, initialize data for further calls to ellrank."}, {"ellratpoints",0,(void*)ellratpoints,12,"GGD0,L,","ellratpoints(E,h,{flag=0}): E being an rational model of an elliptic curve, return a vector containing the affine rational points on the curve of naive height less than h. If fl=1, stop as soon as a point is found."}, {"ellrootno",0,(void*)ellrootno,12,"lGDG","ellrootno(E,{p}): root number for the L-function of the elliptic curve E/Q at a prime p (including 0, for the infinite place); global root number if p is omitted. If p is omitted, the curve can also be defined over a number field."}, {"ellsaturation",0,(void*)ellsaturation,12,"GGLp","ellsaturation(E,V,B): let E be an elliptic curve over Q and V be a vector of independent rational points on E of infinite order that generate a subgroup G of E(Q) of finite index. Return a new set W of the same length that generate a subgroup H of E(Q) containing G and such that [E(Q):H] is not divisible by any prime number less than B."}, {"ellsea",0,(void*)ellsea,12,"GD0,L,","ellsea(E,{tors=0}): computes the order of the group E(Fq) for the elliptic curve E, defined over a finite field, using SEA algorithm, with early abort for curves (or their quadratic twist) with nonprime order."}, {"ellsearch",0,(void*)ellsearch,12,"G","ellsearch(N): returns all curves in the elldata database matching constraint N: given name (N = \"11a1\" or [11,0,1]), given isogeny class (N = \"11a\" or [11,0]), or given conductor (N = 11, \"11\", or [11])."}, {"ellsigma",0,(void*)ellsigma,12,"GDGD0,L,p","ellsigma(L,{z='x},{flag=0}): computes the value at z of the Weierstrass sigma function attached to the lattice L, as given by ellperiods(,1). If flag = 1, returns an arbitrary determination of the logarithm of sigma."}, {"ellsub",0,(void*)ellsub,12,"GGG","ellsub(E,z1,z2): difference of the points z1 and z2 on elliptic curve E."}, {"ellsupersingularj",0,(void*)ellsupersingularj,12,"G","ellsupersingularj(p): return a random supersingular j-invariant defined over F_p^2 if p is prime number, over the (finite) field of definition of p otherwise"}, {"elltamagawa",0,(void*)elltamagawa,12,"G","elltamagawa(E): E being an elliptic curve over a number field, returns the global Tamagawa number of the curve."}, {"elltaniyama",0,(void*)elltaniyama,12,"GDP","elltaniyama(E,{n=seriesprecision}): modular parametrization of elliptic curve E/Q."}, {"elltatepairing",0,(void*)elltatepairing,12,"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*)elltors,12,"G","elltors(E): torsion subgroup of elliptic curve E: order, structure, generators."}, {"elltrace",0,(void*)elltrace,12,"GG","elltrace(E,P): sum of the Galois conjugates of the point P on elliptic curve E."}, {"elltwist",0,(void*)elltwist,12,"GDG","elltwist(E,{P}): returns an ell structure for the twist of the elliptic curve E by the quadratic extension defined by P (when P is a polynomial of degree 2) or quadpoly(P) (when P is an integer). If E is defined over a finite field, then P can be omitted."}, {"ellweilcurve",0,(void*)ellweilcurve,12,"GD&","ellweilcurve(E,{&ms}): let E be an elliptic curve over Q given by ellinit or a rational isogeny class given by ellisomat. Return a list of isomorphism classes of elliptic curves isogenous to E as given by ellisomat and the list of the Smith invariants of the lattice associated to E in H^1(E,Q) in the lattice associated to the modular form. If ms is present, it contains the output of msfromell(Emin,0) where Emin is the list of minimal models attached to the curves in the isogeny class."}, {"ellweilpairing",0,(void*)ellweilpairing,12,"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,12,"GDGD0,L,p","ellwp(w,{z='x},{flag=0}): computes the value at z of the Weierstrass P function attached to the lattice w, as given by ellperiods. Optional flag means 0 (default), compute only P(z), 1 compute [P(z),P'(z)]."}, {"ellxn",0,(void*)ellxn,12,"GLDn","ellxn(E,n,{v='x}): return polynomials [A,B] in the variable v such that x([n]P) = (A/B)(t) for any P = [t,u] on E outside of n-torsion."}, {"ellzeta",0,(void*)ellzeta,12,"GDGp","ellzeta(w,{z='x}): computes the value at z of the Weierstrass Zeta function attached to the lattice w, as given by ellperiods(,1)."}, {"ellztopoint",0,(void*)pointell,12,"GGp","ellztopoint(E,z): inverse of ellpointtoz. Returns the coordinates of point P on the curve E corresponding to a complex or p-adic z."}, {"erfc",0,(void*)gerfc,8,"Gp","erfc(x): complementary error function."}, {"errname",0,(void*)errname,1,"G","errname(E): returns the type of the error message E."}, {"error",0,(void*)error0,1,"vs*","error({str}*): abort script with error message str."}, {"eta",0,(void*)eta0,8,"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 nonzero, the function only applies to complex scalars and returns the true eta function, with the factor q^(1/24) included."}, {"eulerfrac",0,(void*)eulerfrac,4,"L","eulerfrac(n): Euler number E_n, as a rational number."}, {"eulerianpol",0,(void*)eulerianpol,4,"LDn","eulerianpol(n,{v='x}): Eulerian polynomial A_n, in variable v."}, {"eulerphi",0,(void*)eulerphi,5,"G","eulerphi(x): Euler's totient function of x."}, {"eulerpol",0,(void*)eulerpol,4,"LDn","eulerpol(n,{v='x}): Euler polynomial E_n, in variable v."}, {"eulerreal",0,(void*)eulerreal,4,"Lp","eulerreal(n): Euler number E_n, as a real number."}, {"eulervec",0,(void*)eulervec,4,"L","eulervec(n): returns a vector containing the nonzero Euler numbers E_0, E_2, ..., E_{2n}."}, {"eval",0,(void*)geval_gp,6,"GC","eval(x): evaluation of x, replacing variables by their value."}, {"exp",0,(void*)gexp,8,"Gp","exp(x): exponential of x."}, {"expm1",0,(void*)gexpm1,8,"Gp","expm1(x): exp(x)-1."}, {"exponent",0,(void*)gpexponent,3,"G","exponent(x): binary exponent of x"}, {"export",0,NULL,1,NULL,"export(x{=...},...,z{=...}): export the variables x,...,z to the parallel world."}, {"exportall",0,(void*)exportall,1,"v","exportall(): declare all current dynamic variables as exported variables."}, {"extern",0,(void*)gpextern,1,"s","extern(str): execute shell command str, and feeds the result to GP (as if loading from file)."}, {"externstr",0,(void*)externstr,1,"s","externstr(str): execute shell command str, and returns the result as a vector of GP strings, one component per output line."}, {"factor",0,(void*)factor0,5,"GDG","factor(x,{D}): factorization of x over domain D. If x and D are both integers, return partial factorization, using primes < D."}, {"factorback",0,(void*)factorback2,5,"GDG","factorback(f,{e}): given a factorization f, gives the factored object 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]."}, {"factorcantor",0,(void*)factmod,5,"GG","factorcantor(x,p): this function is obsolete, use factormod."}, {"factorff",0,(void*)factorff,5,"GDGDG","factorff(x,{p},{a}): obsolete, use factormod."}, {"factorial",0,(void*)mpfactr,5,"Lp","factorial(x): factorial of x, the result being given as a real number."}, {"factorint",0,(void*)factorint,5,"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,5,"GDGD0,L,","factormod(f,{D},{flag=0}): factors the polynomial f over the finite field defined by the domain D; flag is optional, and can be 0: default or 1: only the degrees of the irreducible factors are given."}, {"factormodDDF",0,(void*)factormodDDF,5,"GDG","factormodDDF(f,{D}): distinct-degree factorization of the squarefree polynomial f over the finite field defined by the domain D."}, {"factormodSQF",0,(void*)factormodSQF,5,"GDG","factormodSQF(f,{D}): squarefree factorization of the polynomial f over the finite field defined by the domain D."}, {"factormodcyclo",0,(void*)factormodcyclo,5,"LGD0,L,Dn","factormodcyclo(n,p,{single=0},{v='x}): factor n-th cyclotomic polynomial mod p."}, {"factornf",0,(void*)polfnf,10,"GG","factornf(x,t): this function is obsolete, use nffactor."}, {"factorpadic",0,(void*)factorpadic,6,"GGL","factorpadic(pol,p,r): p-adic factorization of the polynomial pol to precision r."}, {"ffcompomap",0,(void*)ffcompomap,5,"GG","ffcompomap(f,g): Let k, l, m be three finite fields and f a (partial) map from l to m and g a partial map from k to l, return the (partial) map f o g from k to m."}, {"ffembed",0,(void*)ffembed,5,"GG","ffembed(a,b): given two elements a and b in finite fields, return a map embedding the definition field of a to the definition field of b."}, {"ffextend",0,(void*)ffextend,5,"GGDn","ffextend(a,P,{v}): extend the field K of definition of a by a root of the polynomial P, assumed to be irreducible over K. Return [r, m] where r is a root of P in the extension field L and m is a map from K to L, see \\kbd{ffmap}. If v is given, the variable name is used to display the generator of L, else the name of the variable of P is used."}, {"fffrobenius",0,(void*)fffrobenius,5,"GD1,L,","fffrobenius(m,{n=1}): return the n-th power of the Frobenius map over the field of definition of m."}, {"ffgen",0,(void*)ffgen,5,"GDn","ffgen(k,{v = 'x}): return a generator of the finite field k (not necessarily a generator of its multiplicative group) as a t_FFELT. k can be given by its order q, the pair [p,f] with q=p^f, by an irreducible polynomial with t_INTMOD coefficients, or by a finite field element. If v is given, the variable name is used to display g, else the variable of the polynomial or finite field element, or x if only the order was given."}, {"ffinit",0,(void*)ffinit,5,"GLDn","ffinit(p,n,{v='x}): monic irreducible polynomial of degree n in F_p[v]."}, {"ffinvmap",0,(void*)ffinvmap,5,"G","ffinvmap(m): given a map m between finite fields, return a partial map that return the pre-images by the map m."}, {"fflog",0,(void*)fflog,5,"GGDG","fflog(x,g,{o}): return the discrete logarithm of the finite field element x in base g. If present, o must represent the multiplicative order of g. If no o is given, assume that g is a primitive root."}, {"ffmap",0,(void*)ffmap,5,"GG","ffmap(m,x): given a (partial) map m between two finite fields, return the image of x by m. The function is applied recursively to the component of vectors, matrices and polynomials. If m is a partial map that is not defined at x, return []"}, {"ffmaprel",0,(void*)ffmaprel,5,"GG","ffmaprel(m,x): given a (partial) map m between two finite fields, express x as an algebraic element over the codomain of m in a way which is compatible with m. The function is applied recursively to the component of vectors, matrices and polynomials."}, {"ffnbirred",0,(void*)ffnbirred0,5,"GLD0,L,","ffnbirred(q,n,{flag=0}): number of monic irreducible polynomials over F_q, of degree n (flag=0, default) or at most n (flag=1)."}, {"fforder",0,(void*)fforder,5,"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,5,"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)."}, {"fft",0,(void*)FFT,6,"GG","fft(w,P): given w from rootsof1, return the discrete Fourier transform of P."}, {"fftinv",0,(void*)FFTinv,6,"GG","fftinv(w,P): given w from rootsof1, return the inverse Fourier transform of P."}, {"fibonacci",0,(void*)fibo,4,"L","fibonacci(x): Fibonacci number of index x."}, {"fileclose",0,(void*)gp_fileclose,1,"vL","fileclose(n): close the file descriptor n."}, {"fileextern",0,(void*)gp_fileextern,1,"ls","fileextern(str): execute shell command str and returns a file descriptor attached to the command output as if it were read from a file."}, {"fileflush",0,(void*)gp_fileflush0,1,"vDG","fileflush({n}): flush the file descriptor n (all descriptors to output streams if n is omitted)."}, {"fileopen",0,(void*)gp_fileopen,1,"lsD\"r\",s,","fileopen(path,mode): open the file pointed to by 'path' and return a file descriptor which can be used with other file functions. The mode is \"r\" (default, read), \"w\" (write, truncate), \"a\" (write, append)."}, {"fileread",0,(void*)gp_fileread,1,"L","fileread(n): read a logical line from the file attached to the descriptor n, opened for reading with fileopen. Return 0 at end of file."}, {"filereadstr",0,(void*)gp_filereadstr,1,"L","filereadstr(n): read a raw line from the file attached to the descriptor n, opened for reading with fileopen. Discard the terminating newline. Return 0 at end of file."}, {"filewrite",0,(void*)gp_filewrite,1,"vLs","filewrite(n,s): write the string s to file attached to descriptor n, ending with a newline. The file must have been opened with fileopen in \"w\" or \"a\" mode."}, {"filewrite1",0,(void*)gp_filewrite1,1,"vLs","filewrite1(n,s): write the string s to file number n without ending with newline."}, {"floor",0,(void*)gfloor,3,"G","floor(x): floor of x = largest integer <= x."}, {"fold",0,(void*)fold0,1,"GG","fold(f,A): return f(...f(f(A[1],A[2]),A[3]),...,A[#A])."}, {"for",0,(void*)forpari,1,"vV=GGI","for(X=a,b,seq): the sequence is evaluated, X going from a up to b. If b is set to +oo, the loop will not stop."}, {"forcomposite",0,(void*)forcomposite,1,"vV=GDGI","forcomposite(n=a,{b},seq): the sequence is evaluated, n running over the composite numbers between a and b. Omitting b runs through composites >= a."}, {"fordiv",0,(void*)fordiv,1,"vGVI","fordiv(n,X,seq): the sequence is evaluated, X running over the divisors of n."}, {"fordivfactored",0,(void*)fordivfactored,1,"vGVI","fordivfactored(n,X,seq): the sequence is evaluated, X running over the [d, factor(d)], d a divisor of n."}, {"foreach",0,(void*)foreachpari,1,"vGVI","foreach(V,X,seq): the sequence is evaluated, X running over the components of V."}, {"forell",0,(void*)forell0,1,"vVLLID0,L,","forell(E,a,b,seq,{flag=0}): execute seq for each elliptic curves E of conductor between a and b in the elldata database. If flag is nonzero, select only the first curve in each isogeny class."}, {"forfactored",0,(void*)forfactored,1,"vV=GGI","forfactored(N=a,b,seq): the sequence is evaluated, N is of the form [n, factor(n)], n going from a up to b."}, {"forpart",0,(void*)forpart0,1,"vV=GIDGDG","forpart(X=k,seq,{a=k},{n=k}): evaluate seq where the Vecsmall X goes over the partitions of k. Optional parameter n (n=nmax or n=[nmin,nmax]) restricts the length of the partition. Optional parameter a (a=amax or a=[amin,amax]) restricts the range of the parts. Zeros are removed unless one sets amin=0 to get X of fixed length nmax (=k by default)."}, {"forperm",0,(void*)forperm0,1,"vGVI","forperm(a,p,seq): the sequence is evaluated, p going through permutations of a."}, {"forprime",0,(void*)forprime,1,"vV=GDGI","forprime(p=a,{b},seq): the sequence is evaluated, p running over the primes between a and b. Omitting b runs through primes >= a."}, {"forprimestep",0,(void*)forprimestep,1,"vV=GDGGI","forprimestep(p=a,b,q,seq): the sequence is evaluated, p running over the primes less than b in the arithmetic progression a + k*q, k >= 0. The parameter q can be a positive integer or an intmod (start at the first prime above a in the progression)."}, {"forqfvec",0,(void*)forqfvec0,7,"vVGDGI","forqfvec(v,q,b,expr): q being a square and symmetric integral matrix representing an positive definite quadratic form, evaluate expr for all pairs of nonzero vectors (-v, v) such that q(v)<=b."}, {"forsquarefree",0,(void*)forsquarefree,1,"vV=GGI","forsquarefree(N=a,b,seq): the sequence is evaluated, N is of the form [n, factor(n)], n going through squarefree integers from a up to b."}, {"forstep",0,(void*)forstep,1,"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 positive real number, an intmod for an arithmetic progression, or finally a vector of steps). If b is set to +oo the loop will not stop."}, {"forsubgroup",0,(void*)forsubgroup0,1,"vV=GDGI","forsubgroup(H=G,{bound},seq): execute seq for each subgroup H of the abelian group G, whose index is bounded by bound if not omitted. H is given as a left divisor of G in HNF form."}, {"forsubset",0,(void*)forsubset0,1,"vGVI","forsubset(nk,s,seq): if nk is an integer n, the sequence is evaluated, s going through all subsets of {1, 2, ..., n}; if nk is a pair [n,k] of integers s goes through k-subsets of {1, 2, ..., n}. The order is lexicographic among subsets of the same size and smaller subsets come first."}, {"forvec",0,(void*)forvec,1,"vV=GID0,L,","forvec(X=v,seq,{flag=0}): v being a 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. As a shortcut, v being a vector of nonnegative integers allows to loop over representatives of Z^n/vZ^n."}, {"frac",0,(void*)gfrac,3,"G","frac(x): fractional part of x = x-floor(x)."}, {"fromdigits",0,(void*)fromdigits,3,"GDG","fromdigits(x,{b=10}): gives the integer formed by the elements of x seen as the digits of a number in base b."}, {"galoischardet",0,(void*)galoischardet,10,"GGD1,L,","galoischardet(gal,chi,{o=1}): return the determinant character of the character chi."}, {"galoischarpoly",0,(void*)galoischarpoly,10,"GGD1,L,","galoischarpoly(gal,chi,{o=1}): return the list of characteristic polynomials of the representation attached to the character chi."}, {"galoischartable",0,(void*)galoischartable,10,"G","galoischartable(gal): return the character table of the underlying group of gal."}, {"galoisconjclasses",0,(void*)galoisconjclasses,10,"G","galoisconjclasses(gal): gal being output by galoisinit, return the list of conjugacy classes."}, {"galoisexport",0,(void*)galoisexport,10,"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,10,"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."}, {"galoisgetgroup",0,(void*)galoisgetgroup,10,"LD0,L,","galoisgetgroup(a,{b}): query the galpol package for a group of order a with index b in the GAP4 Small Group library. If b is omitted, return the number of isomorphism classes of groups of order a."}, {"galoisgetname",0,(void*)galoisgetname,10,"LL","galoisgetname(a,b): query the galpol package for a string describing the group of order a with index b in the GAP4 Small Group library."}, {"galoisgetpol",0,(void*)galoisgetpol,10,"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,10,"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,10,"GDG","galoisinit(pol,{den}): pol being a polynomial or a number field as output by nfinit defining a Galois extension of Q, compute the Galois group and all necessary information for computing fixed fields. den is optional and has the same meaning as in nfgaloisconj(,4)(see manual)."}, {"galoisisabelian",0,(void*)galoisisabelian,10,"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 matrix of gal if flag=2."}, {"galoisisnormal",0,(void*)galoisisnormal,10,"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,10,"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."}, {"galoissplittinginit",0,(void*)galoissplittinginit,10,"GDG","galoissplittinginit(P,{d}): Galois group over Q of the splitting field of P, for P integral, monic and irreducible or given by a nf structure. If d is given, it must be a multiple of the splitting field degree. The output is compatible with functions expecting a galoisinit structure."}, {"galoissubcyclo",0,(void*)galoissubcyclo,10,"GDGD0,L,Dn","galoissubcyclo(N,H,{flag=0},{v}): computes 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]]). 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, outputs only the conductor of the abelian extension. If flag is 2, outputs [pol,f] where pol is the polynomial and f the conductor. If flag is 3, outputs galoisinit(pol)."}, {"galoissubfields",0,(void*)galoissubfields,10,"GD0,L,Dn","galoissubfields(G,{flag=0},{v}): output all the subfields of G; flag has the same meaning as for galoisfixedfield."}, {"galoissubgroups",0,(void*)galoissubgroups,10,"G","galoissubgroups(G): output all the subgroups of G."}, {"gamma",0,(void*)ggamma,8,"Gp","gamma(s): gamma function at s, a complex or p-adic number, or a series."}, {"gammah",0,(void*)ggammah,8,"Gp","gammah(x): gamma of x+1/2 (x integer)."}, {"gammamellininv",0,(void*)gammamellininv,8,"GGD0,L,b","gammamellininv(G,t,{m=0}): returns G(t), where G is as output by gammamellininvinit (its m-th derivative if m is present)."}, {"gammamellininvasymp",0,(void*)gammamellininvasymp,8,"GDPD0,L,","gammamellininvasymp(A,n,{m=0}): return the first n terms of the asymptotic expansion at infinity of the m-th derivative K^m(t) of the inverse Mellin transform of the function f(s)=Gamma_R(s+a_1)*...*Gamma_R(s+a_d), where Vga is the vector [a_1,...,a_d] and Gamma_R(s)=Pi^(-s/2)*gamma(s/2). The result is a vector [M[1]...M[n]] with M[1]=1, such that K^m(t) = (an elementary factor) * sum_n M[n+1] / x^n, where x = pi t^(2n/d)."}, {"gammamellininvinit",0,(void*)gammamellininvinit,8,"GD0,L,b","gammamellininvinit(A,{m=0}): initialize data for the computation by gammamellininv() of the m-th derivative of the inverse Mellin transform of the function f(s) = Gamma_R(s+a1)*...*Gamma_R(s+ad), where A is the vector [a1,...,ad] and Gamma_R(s) = Pi^(-s/2)*gamma(s/2)."}, {"gcd",0,(void*)ggcd0,5,"GDG","gcd(x,{y}): greatest common divisor of x and y."}, {"gcdext",0,(void*)gcdext0,5,"GG","gcdext(x,y): returns [u,v,d] such that d=gcd(x,y) and u*x+v*y=d."}, {"gcharalgebraic",0,(void*)gcharalgebraic,10,"GDG","gcharalgebraic(gc,{type}): returns a matrix whose columns form a basis of the algebraic Grossencharacters in gc. If type is specified as a vector of integer exponents [p,q] for each complex place, returns a vector containing an algebraic character of that infinity type (or the empty vector if such a character does not exist)."}, {"gcharconductor",0,(void*)gchar_conductor,10,"GG","gcharconductor(gc,chi): returns the conductor of chi, as a modulus over gc.bnf."}, {"gcharduallog",0,(void*)gcharduallog,10,"GG","gcharduallog(gc,chi): returns logarithm vector of character chi in R^n. We have gchareval(gc,chi,x,0) = gcharduallog(gc,chi)*gcharlog(gc,x) in R/Z."}, {"gchareval",0,(void*)gchareval,10,"GGGD1,L,","gchareval(gc,chi,x,{flag=1}): computes the evaluation chi(x) in C* if flag=1 and in C/Z if flag=0."}, {"gcharidentify",0,(void*)gchar_identify,10,"GGGp","gcharidentify(gc,Lv,Lchiv): returns a Grossencharacter chi belonging to gc that approximately satisfies the constraints that chi_v is Lchiv[i] at the place v=Lv[i]."}, {"gcharinit",0,(void*)gcharinit,10,"GGp","gcharinit(bnf,f): given a bnf as output by bnfinit and a modulus f, initializes data related to the group of Grossencharacters of conductor dividing this modulus."}, {"gcharisalgebraic",0,(void*)gcharisalgebraic,10,"iGGD&","gcharisalgebraic(gc,chi,{&type}): returns 1 if chi is an algebraic (type A0) character. If type is present, it is set to the infinity type [p,q] of chi."}, {"gcharlocal",0,(void*)gcharlocal,10,"GGGpD&","gcharlocal(gc,chi,v,{&BID}): if v is a place, return the local character chi_v. If v is a prime dividing the modulus and the optional argument 'BID' is present, set BID to the corresponding idealstar structure."}, {"gcharlog",0,(void*)gcharlog,10,"GGp","gcharlog(gc,x): returns the internal representation (logarithm) of the ideal x suitable for computations in gc, as a column vector."}, {"gcharnewprec",0,(void*)gcharnewprec,10,"Gp","gcharnewprec(gc): given a Grossencharacter group \\kbd{gc}, recomputes its invariants to ensure accurate results to current precision."}, {"genus2igusa",0,(void*)genus2igusa,12,"GD0,L,","genus2igusa(PQ,{k}): let PQ be a polynomial P, resp. a vector [P,Q] of polynomials defined over a field F of characteristic != 2. Returns the Igusa invariants of the hyperelliptic curve C/F of genus 2 defined by y^2 = P, resp. y^2 + Q*y = P."}, {"genus2red",0,(void*)genus2red,12,"GDG","genus2red(PQ,{p}): let PQ be a polynomial P, resp. a vector [P,Q] of polynomials, with rational coefficients. Determines the reduction at p > 2 of the (proper, smooth) hyperelliptic curve C/Q of genus 2 defined by y^2 = P, resp. y^2 + Q*y = P. More precisely, determines the special fiber X_p of the minimal regular model X of C over Z."}, {"getabstime",0,(void*)getabstime,1,"l","getabstime(): milliseconds of CPU time since startup."}, {"getcache",0,(void*)getcache,1,"","getcache(): returns information about various auto-growing caches. For each resource, we report its name, its size, the number of cache misses (since the last extension) and the largest cache miss."}, {"getenv",0,(void*)gp_getenv,1,"s","getenv(s): value of the environment variable s, 0 if it is not defined."}, {"getheap",0,(void*)getheap,1,"","getheap(): 2-component vector giving the current number of objects in the heap and the space they occupy (in long words)."}, {"getlocalbitprec",0,(void*)getlocalbitprec,1,"lb","getlocalbitprec(): returns the current dynamic bit precision."}, {"getlocalprec",0,(void*)getlocalprec,1,"lp","getlocalprec(): returns the current dynamic precision, in decimal digits."}, {"getrand",0,(void*)getrand,1,"","getrand(): current value of random number seed."}, {"getstack",0,(void*)getstack,1,"l","getstack(): current value of stack pointer avma."}, {"gettime",0,(void*)gettime,1,"l","gettime(): milliseconds of CPU time used since the last call to gettime."}, {"getwalltime",0,(void*)getwalltime,1,"","getwalltime(): time (in milliseconds) since the UNIX Epoch."}, {"global",0,NULL,1,NULL,"global(list of variables): obsolete. Scheduled for deletion."}, {"halfgcd",0,(void*)ghalfgcd,5,"GG","halfgcd(x,y): return a vector [M, [a,b]~], where M is an invertible 2x2 matrix such that M*[x,y]~ = [a,b]~, where b is small. More precisely, if x,y are integers, we have b < sqrt(max(|x|,|y|)) <= a. If x,y are polynomials, we have deg b < ceil((max(|x|,|y|))/2) <= deg a."}, {"hammingweight",0,(void*)hammingweight,4,"lG","hammingweight(x): returns the Hamming weight of x."}, {"harmonic",0,(void*)harmonic0,4,"UDG","harmonic(n,{r=1}): generalized harmonic number of index n in power r."}, {"hgmalpha",0,(void*)hgmalpha,14,"G","hgmalpha(H): returns the alpha and beta parameters of the hypergeometric motive template H."}, {"hgmbydegree",0,(void*)hgmbydegree,14,"L","hgmbydegree(n): outputs [L(0),...,L(n-1)] where L(w) is the list of cyclotomic parameters of all possible hypergeometric motive templates of degree n and weight w."}, {"hgmcoef",0,(void*)hgmcoef,14,"GGG","hgmcoef(H,t,n): (H,t) being a hypergeometric motive, returns the n-th coefficient of its L-function."}, {"hgmcoefs",0,(void*)hgmcoefs,14,"GGL","hgmcoefs(H,t,n): (H,t) being a hypergeometric motive, returns the first n coefficients of its L-function, where Euler factors at wild primes are set to 1."}, {"hgmcyclo",0,(void*)hgmcyclo,14,"G","hgmcyclo(H): returns the cyclotomic parameters (D,E) of the hypergeometric motive template H."}, {"hgmeulerfactor",0,(void*)hgmeulerfactor,14,"GGLD&","hgmeulerfactor(H,t,p,{&e}): (H,t) being a hypergeometric motive, returns the Euler factor P_p at the prime p; if present, set e to the valuation of the conductor at p."}, {"hgmgamma",0,(void*)hgmgamma,14,"G","hgmgamma(H): returns the gamma vector of the hypergeometric motive template H."}, {"hgminit",0,(void*)hgminit,14,"GDG","hgminit(a,{b}): Create the template for a hypergeometric motive with parameters a and possibly b. The format of the parameters may be alpha: Galois invariant lists of rational numbers a=alpha and b=beta; or cyclo: lists A and B of positive integers corresponding to alpha and beta; or gamma: list of cn such that the hypergeometric quotient is prod_n(x^n-1)^cn."}, {"hgmissymmetrical",0,(void*)hgmissymmetrical,14,"lG","hgmissymmetrical(H): is the hypergeometric motive template H symmetrical at t=1?"}, {"hgmparams",0,(void*)hgmparams,14,"G","hgmparams(H): H being a hypergeometric motive template, returns [d, w, [P, T], M], where d is the degree, w the weight, P the Hodge polynomial and T the Tate twist number (so that the Hodge function itself is P/x^T); finally M is the so-called M-value."}, {"hgmtwist",0,(void*)hgmtwist,14,"G","hgmtwist(H): twist by 1/2 of alpha and beta of the hypergeometric motive template H."}, {"hilbert",0,(void*)hilbert,5,"lGGDG","hilbert(x,y,{p}): Hilbert symbol at p of x,y."}, {"hyperellchangecurve",0,(void*)hyperellchangecurve,12,"GG","hyperellchangecurve(C,m): C being a nonsingular hyperelliptic model of a curve, apply the change of coordinate given by m. C can be given either by a squarefree polynomial P such that C:y^2=P(x) or by a vector [P,Q] such that C:y^2+Q(x)*y=P(x) and Q^2+4P is squarefree."}, {"hyperellcharpoly",0,(void*)hyperellcharpoly,12,"G","hyperellcharpoly(X): X being a nonsingular hyperelliptic curve defined over a finite field, return the characteristic polynomial of the Frobenius automorphism. X can be given either by a squarefree polynomial P such that X:y^2=P(x) or by a vector [P,Q] such that X:y^2+Q(x)*y=P(x) and Q^2+4P is squarefree."}, {"hyperelldisc",0,(void*)hyperelldisc,12,"G","hyperelldisc(X): X being a nonsingular hyperelliptic model of a curve, defined over a field of characteristic distinct from 2, returns its discriminant. X can be given either by a squarefree polynomial P such that X:y^2=P(x) or by a vector [P,Q] such that X:y^2+Q(x)*y=P(x) and Q^2+4P is squarefree."}, {"hyperellisoncurve",0,(void*)hyperellisoncurve,12,"iGG","hyperellisoncurve(X,p): X being a nonsingular hyperelliptic model of a curve, test whether the point p is on the curve. X can be given either by a squarefree polynomial P such that X:y^2=P(x) or by a vector [P,Q] such that X:y^2+Q(x)*y=P(x) and Q^2+4P is squarefree."}, {"hyperellminimaldisc",0,(void*)hyperellminimaldisc,12,"GDG","hyperellminimaldisc(C,{pr}): C being a nonsingular integral hyperelliptic model of a curve, return the minimal discrminant of an integral model of C. If pr is given, it must be a list of primes and the discriminant is then only garanteed minimal at the elements of pr. C can be given either by a squarefree polynomial P such that C:y^2=P(x) or by a vector [P,Q] such that C:y^2+Q(x)*y=P(x) and Q^2+4P is squarefree."}, {"hyperellminimalmodel",0,(void*)hyperellminimalmodel,12,"GD&DG","hyperellminimalmodel(C,{&m},{pr}): C being a nonsingular integral hyperelliptic model of a curve, return an integral model of C with minimal discriminant. If pr is given, it must be a list of primes and the model is then only garanteed minimal at the elements of pr. C can be given either by a squarefree polynomial P such that C:y^2=P(x) or by a vector [P,Q] such that C:y^2+Q(x)*y=P(x) and Q^2+4P is squarefree."}, {"hyperellordinate",0,(void*)hyperellordinate,12,"GG","hyperellordinate(H,x): y-coordinates corresponding to x-ordinate x on hyperelliptic curve H."}, {"hyperellpadicfrobenius",0,(void*)hyperellpadicfrobenius0,12,"GGL","hyperellpadicfrobenius(Q,q,n): Q being a rational polynomial of degree d and X being the curve defined by y^2=Q(x), return the matrix of the Frobenius at the prime q >= d in the standard basis of H^1_dR(X) to absolute q-adic precision q^n; q may also be of the form [T,p] where T is an integral polynomial which is irreducible mod p."}, {"hyperellratpoints",0,(void*)hyperellratpoints,12,"GGD0,L,","hyperellratpoints(X,h,{flag=0}): X being a nonsingular hyperelliptic curve given by an rational model, return a vector containing the affine rational points on the curve of naive height less than h. If fl=1, stop as soon as a point is found. X can be given either by a squarefree polynomial P such that X:y^2=P(x) or by a vector [P,Q] such that X:y^2+Q(x)y=P(x) and Q^2+4P is squarefree."}, {"hyperellred",0,(void*)hyperellred,12,"GD&","hyperellred(C,{&m}): C being a nonsingular integral hyperelliptic model of a curve, return an integral model of C with the same discriminant but small coefficients. C can be given either by a squarefree polynomial P such that C:y^2=P(x) or by a vector [P,Q] such that C:y^2+Q(x)*y=P(x) and Q^2+4P is squarefree."}, {"hypergeom",0,(void*)hypergeom,8,"DGDGGp","hypergeom({N},{D},z): general hypergeometric function, where N and D are the vector of parameters in the numerator and denominator respectively, evaluated at the argument z."}, {"hyperu",0,(void*)hyperu,8,"GGGp","hyperu(a,b,z): U-confluent hypergeometric function."}, {"idealadd",0,(void*)idealadd,10,"GGG","idealadd(nf,x,y): sum of two ideals x and y in the number field defined by nf."}, {"idealaddtoone",0,(void*)idealaddtoone0,10,"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,10,"GGD0,L,","idealappr(nf,x,{flag}): 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; x may also be a prime ideal factorization with possibly zero exponents. flag is deprecated (ignored), kept for backward compatibility."}, {"idealchinese",0,(void*)idealchinese,10,"GGDG","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. If y is omitted, return a data structure which can be used in place of x in later calls."}, {"idealcoprime",0,(void*)idealcoprime,10,"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,10,"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 nonzero, the quotient is supposed to be an integral ideal (slightly faster)."}, {"idealdown",0,(void*)idealdown,10,"GG","idealdown(nf,x): finds the intersection of the ideal x with Q."}, {"idealfactor",0,(void*)gpidealfactor,10,"GGDG","idealfactor(nf,x,{lim}): factorization of the ideal x into prime ideals in the number field nf. If lim is set return partial factorization, using primes < lim."}, {"idealfactorback",0,(void*)idealfactorback,10,"GGDGD0,L,","idealfactorback(nf,f,{e},{flag = 0}): given a factorization 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 nonzero, perform idealred along the way."}, {"idealfrobenius",0,(void*)idealfrobenius,10,"GGG","idealfrobenius(nf,gal,pr): returns the Frobenius element (pr|nf/Q) attached to the unramified prime ideal pr in prid format, in the Galois group gal of the number field nf."}, {"idealhnf",0,(void*)idealhnf0,10,"GGDG","idealhnf(nf,u,{v}): hermite normal form of the ideal u in the number field nf if v is omitted. If called as idealhnf(nf,u,v), the ideal is given as uZ_K + vZ_K in the number field K defined by nf."}, {"idealintersect",0,(void*)idealintersect,10,"GGG","idealintersect(nf,A,B): intersection of two ideals A and B in the number field defined by nf."}, {"idealinv",0,(void*)idealinv,10,"GG","idealinv(nf,x): inverse of the ideal x in the number field nf."}, {"idealismaximal",0,(void*)idealismaximal,10,"GG","idealismaximal(nf,x): if x is a maximal ideal, return it in prid form, else return 0."}, {"idealispower",0,(void*)idealispower,10,"lGGLD&","idealispower(nf,A,n,{&B}): return 1 if A = B^n is an n-th power else return 0."}, {"ideallist",0,(void*)gideallist,10,"GGD4,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; 8: omit ideals which cannot be conductors."}, {"ideallistarch",0,(void*)ideallistarch,10,"GGG","ideallistarch(nf,list,arch): list is a vector of vectors 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,10,"DGGG","ideallog({nf},x,bid): if bid is a big ideal, as given by idealstar(nf,D,...), gives the vector of exponents on the generators bid.gen (even if these generators have not been explicitly computed)."}, {"idealmin",0,(void*)idealmin,10,"GGDG","idealmin(nf,ix,{vdir}): pseudo-minimum of the ideal ix in the direction vdir in the number field nf."}, {"idealmul",0,(void*)idealmul0,10,"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 nonzero, reduce the result."}, {"idealnorm",0,(void*)idealnorm,10,"GG","idealnorm(nf,x): norm of the ideal x in the number field nf."}, {"idealnumden",0,(void*)idealnumden,10,"GG","idealnumden(nf,x): returns [A,B], where A,B are coprime integer ideals such that x = A/B."}, {"idealpow",0,(void*)idealpow0,10,"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 nonzero, reduce the result."}, {"idealprimedec",0,(void*)idealprimedec_limit_f,10,"GGD0,L,","idealprimedec(nf,p,{f=0}): prime ideal decomposition of the prime number p in the number field nf as a vector of prime ideals. If f is present and nonzero, restrict the result to primes of residue degree <= f."}, {"idealprincipalunits",0,(void*)idealprincipalunits,10,"GGL","idealprincipalunits(nf,pr,k): returns the structure [no, cyc, gen] of the multiplicative group (1 + pr) / (1 + pr^k)."}, {"idealramgroups",0,(void*)idealramgroups,10,"GGG","idealramgroups(nf,gal,pr): let pr be a prime ideal in prid format, and gal the Galois group of the number field nf, return a vector g such that g[1] is the decomposition group of pr, g[2] is the inertia group, g[i] is the (i-2)th ramification group of pr, all trivial subgroups being omitted."}, {"idealred",0,(void*)idealred0,10,"GGDG","idealred(nf,I,{v=0}): LLL reduction of the ideal I in the number field nf along direction v, in HNF."}, {"idealredmodpower",0,(void*)idealredmodpower,10,"GGUD0,U,","idealredmodpower(nf,x,n,{B=factorlimit}): return b such that x * b^n = v is small."}, {"idealstar",0,(void*)idealstarmod,10,"DGGD1,L,DG","idealstar({nf},N,{flag=1},{cycmod}): gives the structure of (Z_K/N)^*, where N is a modulus (an ideal in any form or a vector [f0, foo], where f0 is an ideal and foo is a {0,1}-vector with r1 components. If the positive integer cycmod is present, only compute the group modulo cycmod-th powers. flag is optional, and can be 0: structure as an abelian group [h,d,g] where h is the order, d the orders of the cyclic factors and g the generators; if flag=1 (default), gives a bid structure used in ideallog to compute discrete logarithms; underlying generators are well-defined but not explicitly computed, which saves time; if flag=2, same as with flag=1 except that the generators are also given. If nf is omitted, N must be an integer and we return the structure of (Z/NZ)^*."}, {"idealtwoelt",0,(void*)idealtwoelt0,10,"GGDG","idealtwoelt(nf,x,{a}): two-element representation of an ideal x in the number field nf. If (optional) a is nonzero, first element will be equal to a."}, {"idealval",0,(void*)gpidealval,10,"GGG","idealval(nf,x,pr): valuation at pr given in idealprimedec format of the ideal x in the number field nf."}, {"if",0,(void*)ifpari,1,"GDEDE","if(a,{seq1},{seq2}): if a is nonzero, seq1 is evaluated, otherwise seq2. seq1 and seq2 are optional, and if seq2 is omitted, the preceding comma can be omitted also."}, {"iferr",0,(void*)iferrpari,1,"EVEDE","iferr(seq1,E,seq2,{pred}): evaluates the expression sequence seq1. If an error occurs, set the formal parameter E set to the error data. If pred is not present or evaluates to true, catch the error and evaluate seq2. Both pred and seq2 can reference E."}, {"imag",0,(void*)gimag,3,"G","imag(x): imaginary part of x."}, {"incgam",0,(void*)incgam0,8,"GGDGp","incgam(s,x,{g}): incomplete gamma function. g is optional and is the precomputed value of gamma(s)."}, {"incgamc",0,(void*)incgamc,8,"GGp","incgamc(s,x): complementary incomplete gamma function."}, {"inline",0,NULL,1,NULL,"inline(x,...,z): declares x,...,z as inline variables. DEPRECATED, use export."}, {"input",0,(void*)gp_input,1,"","input(): read an expression from the input file or standard input."}, {"install",0,(void*)gpinstall,1,"vrrD\"\",r,D\"\",s,","install(name,code,{gpname},{lib}): load from dynamic library 'lib' the function 'name'. Assign to it the name 'gpname' in this GP session, with prototype 'code'. If 'lib' is omitted, all symbols known to gp (includes the whole 'libpari.so' and possibly others) are available. If 'gpname' is omitted, use 'name'."}, {"intcirc",0,(void*)intcirc0,9,"V=GGEDGp","intcirc(X=a,R,expr,{tab}): numerical integration of expr on the circle |z-a|=R, divided by 2*I*Pi. tab is as in intnum."}, {"intformal",0,(void*)integ,6,"GDn","intformal(x,{v}): formal integration of x with respect to v, or to the main variable of x if v is omitted."}, {"intfuncinit",0,(void*)intfuncinit0,9,"V=GGED0,L,p","intfuncinit(t=a,b,f,{m=0}): initialize tables for integrations from a to b using a weight f(t). For integral transforms such as Fourier or Mellin transforms."}, {"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 +oo/-oo. Finally tab is either omitted (let the program choose the integration step), a nonnegative integer m (divide integration step by 2^m), or data precomputed with intnuminit."}, {"intnumgauss",0,(void*)intnumgauss0,9,"V=GGEDGp","intnumgauss(X=a,b,expr,{tab}): numerical integration of expr from a to b, a compact interval, with respect to X using Gauss-Legendre quadrature. tab is either omitted (and will be recomputed) or precomputed with intnumgaussinit."}, {"intnumgaussinit",0,(void*)intnumgaussinit,9,"D0,L,p","intnumgaussinit({n}): initialize tables for n-point Gauss-Legendre integration on a compact interval."}, {"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."}, {"intnumosc",0,(void*)intnumosc0,9,"V=GEGD0,L,DGp","intnumosc(x=a,expr,H,{flag=0},{tab}): numerical integration from a to oo of oscillating quasi-periodic function expr of half-period H. tab is either omitted (and will be recomputed) or precomputed with intnumgaussinit; flag is either 0 (Sidi extrapolation, safe mode), 1 (Sidi extrapolation, unsafe mode), 2 (sumalt), 3 (sumnumlagrange), 4 (sumpos)."}, {"intnumromb",0,(void*)intnumromb0,9,"V=GGED0,L,b","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."}, {"isfundamental",0,(void*)isfundamental,5,"lG","isfundamental(D): true(1) if D is a fundamental discriminant (including 1), false(0) if not."}, {"ispolygonal",0,(void*)ispolygonal,5,"lGGD&","ispolygonal(x,s,{&N}): true(1) if x is an s-gonal number, false(0) if not (s > 2). If N is given set it to n if x is the n-th s-gonal number."}, {"ispower",0,(void*)ispower,5,"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 nonzero result, set n to the k-th root of x."}, {"ispowerful",0,(void*)ispowerful,5,"lG","ispowerful(x): true(1) if x is a powerful integer (valuation at all primes dividing x is greater than 1), false(0) if not."}, {"isprime",0,(void*)gisprime,5,"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. If flag is 3, use ECPP."}, {"isprimepower",0,(void*)isprimepower,5,"lGD&","isprimepower(x,{&n}): if x = p^k is a prime power (p prime, k > 0), return k, else return 0. If n is present, and the function returns a nonzero result, set n to p, the k-th root of x."}, {"ispseudoprime",0,(void*)gispseudoprime,5,"GD0,L,","ispseudoprime(x,{flag}): true(1) if x is a strong pseudoprime, false(0) if not. If flag is 0 or omitted, use BPSW test, otherwise use strong Rabin-Miller test for flag randomly chosen bases."}, {"ispseudoprimepower",0,(void*)ispseudoprimepower,5,"lGD&","ispseudoprimepower(x,{&n}): if x = p^k is a pseudo-prime power (p pseudo-prime, k > 0), return k, else return 0. If n is present, and the function returns a nonzero result, set n to p, the k-th root of x."}, {"issquare",0,(void*)issquareall,5,"lGD&","issquare(x,{&n}): true(1) if x is a square, false(0) if not. If n is given puts the exact square root there if it was computed."}, {"issquarefree",0,(void*)issquarefree,5,"lG","issquarefree(x): true(1) if x is squarefree, false(0) if not."}, {"istotient",0,(void*)istotient,5,"lGD&","istotient(x,{&N}): true(1) if x = eulerphi(n) for some integer n, false(0) if not. If N is given, set N = n as well."}, {"kill",0,(void*)kill0,1,"vr","kill(sym): restores the symbol sym to its ``undefined'' status and kill attached help messages."}, {"kronecker",0,(void*)kronecker,5,"lGG","kronecker(x,y): kronecker symbol (x/y)."}, {"lambertw",0,(void*)glambertW,8,"GD0,L,p","lambertw(y,{branch=0}): solution of the implicit equation x*exp(x)=y. In the p-adic case, give a solution of x*exp(x)=y if y has valuation > 1 (or p odd and positive valuation), of log(x)+x=log(y) otherwise."}, {"laurentseries",0,(void*)laurentseries0,9,"GDPDnp","laurentseries(f,{M=seriesprecision},{x='x}): expand f around 0 as a Laurent series in x to order M."}, {"lcm",0,(void*)glcm0,5,"GDG","lcm(x,{y}): least common multiple of x and y, i.e. x*y / gcd(x,y) up to units."}, {"length",0,(void*)glength,3,"lG","length(x): number of non code words in x, number of characters for a string."}, {"lerchphi",0,(void*)lerchphi,8,"GGGp","lerchphi(z,s,a): Lerch transcendent equal to sum for n >= 0 of z^n / (n+a)^s for reasonable values of the arguments."}, {"lerchzeta",0,(void*)lerchzeta,8,"GGGp","lerchzeta(s,a,lam): Lerch zeta function equal to sum for n >= 0 of e^(2 pi i lam n) / (n+a)^s for reasonable values of the arguments."}, {"lex",0,(void*)lexcmp,2,"iGG","lex(x,y): compare x and y lexicographically (1 if x>y, 0 if x=y, -1 if xprod(i=1,#M[,1],eta(M[i,1]*z)^M[i,2])."}, {"lfuneuler",0,(void*)lfuneuler,13,"GGp","lfuneuler(L,p): return the Euler factor at p of the L-function given by L (Lmath, Ldata or Linit) assuming the L-function admits an Euler product factorization and that it can be determined."}, {"lfungenus2",0,(void*)lfungenus2,13,"G","lfungenus2(F): returns the Ldata structure attached to the L-function attached to the genus-2 curve defined by y^2=F(x) or y^2+Q(x)*y=P(x) if F=[P,Q]. Currently, only odd conductors are supported."}, {"lfunhardy",0,(void*)lfunhardy,13,"GGb","lfunhardy(L,t): variant of the Hardy L-function attached to L, used for plotting on the critical line."}, {"lfunhgm",0,(void*)lfunhgm,14,"GGDGb","lfunhgm(H,t,{hint}): (H,t) being a hypergeometric motive, returns the corresponding lfuncreate data for use with the L function package."}, {"lfuninit",0,(void*)lfuninit0,13,"GGD0,L,b","lfuninit(L,sdom,{der=0}): precompute data for evaluating the L-function given by 'L' (and its derivatives of order der, if set) in rectangular domain sdom = [center,w,h] centered on the real axis, |Re(s)-center| <= w, |Im(s)| <= h, where all three components of sdom are real and w,h are nonnegative. The subdomain [k/2, 0, h] on the critical line can be encoded as [h] for brevity."}, {"lfunlambda",0,(void*)lfunlambda0,13,"GGD0,L,b","lfunlambda(L,s,{D=0}): compute the completed L function Lambda(s), or if D is set, the derivative of order D at s. L is either an Lmath, an Ldata or an Linit."}, {"lfunmf",0,(void*)lfunmf,15,"GDGb","lfunmf(mf,{F}): If F is a modular form in mf, output the L-functions corresponding to its complex embeddings. If F is omitted, output the L-functions corresponding to all eigenforms in the new space."}, {"lfunmfspec",0,(void*)lfunmfspec,13,"Gb","lfunmfspec(L): L corresponding to a modular eigenform, returns [ve,vo,om,op] in even weight, where ve (resp., vo) is the vector of even (resp., odd) periods, and om and op the corresponding real numbers omega^- and omega^+. Returns [v,om] in odd weight."}, {"lfunmul",0,(void*)lfunmul,13,"GGb","lfunmul(L1,L2): creates the Ldata structure (without initialization) corresponding to the product of the Dirichlet series given by L1 and L2."}, {"lfunorderzero",0,(void*)lfunorderzero,13,"lGD-1,L,b","lfunorderzero(L,{m=-1}): computes the order of the possible zero of the L-function at the center k/2 of the critical strip. If m is given and has a nonnegative value, assumes the order is at most m."}, {"lfunparams",0,(void*)lfunparams,13,"Gp","lfunparams(ldata): returns the parameters [N, k, vga] of the L-function defined by ldata (see lfuncreate). The parameters Vga (gamma shifts) are returned to the current precision."}, {"lfunqf",0,(void*)lfunqf,13,"Gp","lfunqf(Q): returns the Ldata structure attached to the theta function of the lattice attached to the definite positive quadratic form Q."}, {"lfunrootres",0,(void*)lfunrootres,13,"Gb","lfunrootres(data): given the Ldata attached to an L-function (or the output of lfunthetainit), compute the root number and the residues. In the present implementation, if the polar part is not already known completely, at most a single pole is allowed. The output is a 3-component vector [[[a_1, r_1],...,[a_n, r_n],[[b_1, R_1],...[b_m,R_m]]~, w], where r_i is the polar part of L(s) at a_i, R_i is is the polar part of Lambda(s) at b_i, or [0,0,r] if there is no pole, and r is the root number."}, {"lfunshift",0,(void*)lfunshift,13,"GGD0,L,b","lfunshift(L,d,{flag}): creates the Ldata structure (without initialization) corresponding to the function Ld such that Ld(s) = L(s-d). If fl=1, return the product L*Ld instead."}, {"lfunsympow",0,(void*)lfunsympow,13,"GU","lfunsympow(E,m): returns the Ldata structure attached to the L-function attached to m-th symmetric power of the elliptic curve E defined over the rationals."}, {"lfuntheta",0,(void*)lfuntheta,13,"GGD0,L,b","lfuntheta(data,t,{m=0}): compute the value of the m-th derivative at t of the theta function attached to the L-function given by data. data can be either the standard L-function data, or the output of lfunthetainit."}, {"lfunthetacost",0,(void*)lfunthetacost0,13,"lGDGD0,L,b","lfunthetacost(L,{tdom},{m=0}): estimates the cost of running lfunthetainit(L,tdom,m) at current bit precision. Returns the number of coefficients an that would be computed. Subsequent evaluation of lfuntheta computes that many values of gammamellininv. If L is already an Linit, then tdom and m are ignored."}, {"lfunthetainit",0,(void*)lfunthetainit,13,"GDGD0,L,b","lfunthetainit(L,{tdom},{m=0}): precompute data for evaluating the m-th derivative of theta functions with argument in domain tdom (by default t is real >= 1)."}, {"lfuntwist",0,(void*)lfuntwist,13,"GGb","lfuntwist(L,chi): creates the Ldata structure (without initialization) corresponding to the twist of L by the primitive character attached to the Dirichlet L-function chi. This requires that the conductor of the character is coprime to the conductor of the L-function L."}, {"lfunzeros",0,(void*)lfunzeros,13,"GGD8,L,b","lfunzeros(L,lim,{divz=8}): lim being either an upper limit or a real interval, computes an ordered list of zeros of L(s) on the critical line up to the given upper limit or in the given interval. Use a naive algorithm which may miss some zeros. To use a finer search mesh, set divz to some integral value larger than the default (= 8)."}, {"lift",0,(void*)lift0,3,"GDn","lift(x,{v}): if v is omitted, lifts elements of Z/nZ to Z, of Qp to Q, and of K[x]/(P) to K[x]. Otherwise lift only polmods with main variable v."}, {"liftall",0,(void*)liftall,3,"G","liftall(x): lifts every element of Z/nZ to Z, of Qp to Q, and of K[x]/(P) to K[x]."}, {"liftint",0,(void*)liftint,3,"G","liftint(x): lifts every element of Z/nZ to Z and of Qp to Q."}, {"liftpol",0,(void*)liftpol,3,"G","liftpol(x): lifts every polmod component of x to polynomials."}, {"limitnum",0,(void*)limitnum0,9,"GDGp","limitnum(expr,{alpha=1}): numerical limit of sequence expr using Lagrange-Zagier extrapolation; assume u(n) ~ sum a_i n^(-alpha*i)."}, {"lindep",0,(void*)lindep0,7,"GD0,L,","lindep(v,{flag=0}): integral linear dependencies between components of v. flag is optional, and can be 0: default, guess a suitable accuracy, or positive: accuracy to use for the computation, in decimal digits."}, {"listcreate",0,(void*)listcreate_gp,1,"D0,L,","listcreate({n}): this function is obsolete, use List()."}, {"listinsert",0,(void*)listinsert0,1,"mWGL","listinsert(~L,x,n): insert x at index n in list L, shifting the remaining elements to the right."}, {"listkill",0,(void*)listkill,1,"vW","listkill(~L): obsolete, retained for backward compatibility."}, {"listpop",0,(void*)listpop0,1,"vWD0,L,","listpop(~list,{n}): removes n-th element from list. If n is omitted or greater than the current list length, removes last element."}, {"listput",0,(void*)listput0,1,"mWGD0,L,","listput(~list,x,{n}): sets n-th element of list equal to x. If n is omitted or greater than the current list length, appends x."}, {"listsort",0,(void*)listsort,1,"vWD0,L,","listsort(~L,{flag=0}): sort the list L in place. If flag is nonzero, suppress all but one occurrence of each element in list."}, {"lngamma",0,(void*)glngamma,8,"Gp","lngamma(x): logarithm of the gamma function of x."}, {"local",0,NULL,1,NULL,"local(x,...,z): declare x,...,z as (dynamically scoped) local variables."}, {"localbitprec",0,(void*)localbitprec,1,"vG","localbitprec(p): set the real precision to p bits in the dynamic scope."}, {"localprec",0,(void*)localprec,1,"vG","localprec(p): set the real precision to p in the dynamic scope and return p."}, {"log",0,(void*)glog,8,"Gp","log(x): natural logarithm of x."}, {"log1p",0,(void*)glog1p,8,"Gp","log1p(x): log(1+x)"}, {"logint",0,(void*)logint0,5,"lGGD&","logint(x,b,{&z}): return the largest non-negative integer e so that b^e <= x, where b > 1 is an integer and x >= 1 is a real number. If the parameter z is present, set it to b^e."}, {"mapapply",0,(void*)mapapply,1,"WGGDG","mapapply(~M,x,f,{u}): applies the closure f to the image of x by the map M and returns the evaluation of f."}, {"mapdelete",0,(void*)mapdelete,1,"vWG","mapdelete(~M,x): removes x from the domain of the map M."}, {"mapget",0,(void*)mapget,1,"GG","mapget(M,x): returns the image of x by the map M."}, {"mapisdefined",0,(void*)mapisdefined,1,"iGGD&","mapisdefined(M,x,{&z}): true (1) if x has an image by the map M, false (0) otherwise. If z is present, set it to the image of x, if it exists."}, {"mapput",0,(void*)mapput,1,"vWGG","mapput(~M,x,y): associates x to y in the map M."}, {"matadjoint",0,(void*)matadjoint0,7,"GD0,L,","matadjoint(M,{flag=0}): adjoint matrix of M using Leverrier-Faddeev's algorithm. If flag is 1, computes the characteristic polynomial independently first."}, {"matalgtobasis",0,(void*)matalgtobasis,10,"GG","matalgtobasis(nf,x): nfalgtobasis applied to every element of the vector or matrix x."}, {"matbasistoalg",0,(void*)matbasistoalg,10,"GG","matbasistoalg(nf,x): nfbasistoalg applied to every element of the matrix or vector x."}, {"matcompanion",0,(void*)matcompanion,7,"G","matcompanion(x): companion matrix to polynomial x."}, {"matconcat",0,(void*)matconcat,7,"G","matconcat(v): concatenate the entries of v and return the resulting matrix."}, {"matdet",0,(void*)det0,7,"GD0,L,","matdet(x,{flag=0}): determinant of the matrix x using an appropriate algorithm depending on the coefficients. If (optional) flag is set to 1, use classical Gaussian elimination (usually worse than the default)."}, {"matdetint",0,(void*)detint,7,"G","matdetint(B): some multiple of the determinant of the lattice generated by the columns of B (0 if not of maximal rank). Useful with mathnfmod."}, {"matdetmod",0,(void*)matdetmod,7,"GG","matdetmod(x,d): determinant of the matrix x modulo d."}, {"matdiagonal",0,(void*)diagonal,7,"G","matdiagonal(x): creates the diagonal matrix whose diagonal entries are the entries of the vector x."}, {"mateigen",0,(void*)mateigen,7,"GD0,L,p","mateigen(x,{flag=0}): complex eigenvectors of the matrix x given as columns of a matrix H. If flag=1, return [L,H], where L contains the eigenvalues and H the corresponding eigenvectors."}, {"matfrobenius",0,(void*)matfrobenius,7,"GD0,L,Dn","matfrobenius(M,{flag},{v='x}): return the Frobenius form of the square matrix M. If flag is 1, return only the elementary divisors as a vector of polynomials in the variable v. If flag is 2, return a two-components vector [F,B] where F is the Frobenius form and B is the basis change so that M=B^-1*F*B."}, {"mathess",0,(void*)hess,7,"G","mathess(x): Hessenberg form of x."}, {"mathilbert",0,(void*)mathilbert,7,"L","mathilbert(n): Hilbert matrix of order n."}, {"mathnf",0,(void*)mathnf0,7,"GD0,L,","mathnf(M,{flag=0}): (upper triangular) Hermite normal form of M, basis for the lattice formed by the columns of M. Basic values of flag are 0 (default): only return the Hermite normal form H, 1: return [H,U] such that H is the HNF of M, and U is an invertible matrix such that MU=H. These two use a naive algorithm; larger values of flag correspond to more involved algorithms and are restricted to integer matrices; flag = 4: returns [H,U] using LLL reduction along the way; flag = 5: return [H,U,P] where P is a permutation of row indices such that P applied to M U is H."}, {"mathnfmod",0,(void*)hnfmod,7,"GG","mathnfmod(x,d): (upper triangular) Hermite normal form of x, basis for the lattice formed by the columns of x, where d is a multiple of the nonzero determinant of this lattice."}, {"mathnfmodid",0,(void*)hnfmodid,7,"GG","mathnfmodid(x,d): (upper triangular) Hermite normal form of x concatenated with matdiagonal(d)."}, {"mathouseholder",0,(void*)mathouseholder,7,"GG","mathouseholder(Q,v): applies a sequence Q of Householder transforms to the vector or matrix v."}, {"matid",0,(void*)matid,7,"L","matid(n): identity matrix of order n."}, {"matimage",0,(void*)matimage0,7,"GD0,L,","matimage(x,{flag=0}): basis of the image of the matrix x. flag is optional and can be set to 0 or 1, corresponding to two different algorithms."}, {"matimagecompl",0,(void*)imagecompl,7,"G","matimagecompl(x): vector of column indices not corresponding to the indices given by the function matimage."}, {"matimagemod",0,(void*)matimagemod,7,"GGD&","matimagemod(x,d,&U): basis of the image of the matrix x modulo d."}, {"matindexrank",0,(void*)indexrank,7,"G","matindexrank(M): gives two extraction vectors (rows and columns) for the matrix M such that the extracted matrix is square of maximal rank."}, {"matintersect",0,(void*)intersect,7,"GG","matintersect(x,y): intersection of the vector spaces whose bases are the columns of x and y."}, {"matinverseimage",0,(void*)inverseimage,7,"GG","matinverseimage(x,y): an element of the inverse image of the vector y by the matrix x if one exists, the empty vector otherwise."}, {"matinvmod",0,(void*)matinvmod,7,"GG","matinvmod(x,d): left inverse of the matrix x modulo d."}, {"matisdiagonal",0,(void*)isdiagonal,7,"iG","matisdiagonal(x): true(1) if x is a diagonal matrix, false(0) otherwise."}, {"matker",0,(void*)matker0,7,"GD0,L,","matker(x,{flag=0}): basis of the kernel of the matrix x. flag is optional, and may be set to 0: default; nonzero: x is known to have integral entries."}, {"matkerint",0,(void*)matkerint0,7,"GD0,L,","matkerint(x,{flag=0}): LLL-reduced Z-basis of the kernel of the matrix x with integral entries; flag is deprecated, kept for backward compatibility."}, {"matkermod",0,(void*)matkermod,7,"GGD&","matkermod(x,d,&im): basis of the kernel of the matrix x modulo d."}, {"matmuldiagonal",0,(void*)matmuldiagonal,7,"GG","matmuldiagonal(x,d): product of matrix x by diagonal matrix whose diagonal coefficients are those of the vector d, equivalent but faster than x*matdiagonal(d)."}, {"matmultodiagonal",0,(void*)matmultodiagonal,7,"GG","matmultodiagonal(x,y): product of matrices x and y, knowing that the result will be a diagonal matrix. Much faster than general multiplication in that case."}, {"matpascal",0,(void*)matqpascal,7,"LDG","matpascal(n,{q}): Pascal triangle of order n if q is omitted. q-Pascal triangle otherwise."}, {"matpermanent",0,(void*)matpermanent,7,"G","matpermanent(x): permanent of the matrix x."}, {"matqr",0,(void*)matqr,7,"GD0,L,p","matqr(M,{flag=0}): returns [Q,R], the QR-decomposition of the square invertible matrix M. If flag=1, Q is given as a sequence of Householder transforms (faster and stabler)."}, {"matrank",0,(void*)rank,7,"lG","matrank(x): rank of the matrix x."}, {"matreduce",0,(void*)matreduce,7,"G","matreduce(m): reduce the factorization matrix m to canonical form (sorted first row with unique elements) matrix."}, {"matrix",0,(void*)matrice,7,"GDGDVDVDE","matrix(m,{n=m},{X},{Y},{expr=0}): m x n matrix of expression expr, where the row variable X goes from 1 to m and the column variable Y goes from 1 to n. By default, fill with 0s."}, {"matrixqz",0,(void*)matrixqz0,7,"GDG","matrixqz(A,{p=0}): if p>=0, transforms the rational or integral mxn (m>=n) matrix A into an integral matrix with gcd of maximal determinants coprime to p. If p=-1, finds a basis of the intersection with Z^n of the lattice spanned by the columns of A. If p=-2, finds a basis of the intersection with Z^n of the Q-vector space spanned by the columns of A."}, {"matsize",0,(void*)matsize,7,"G","matsize(x): number of rows and columns of the vector/matrix x as a 2-vector."}, {"matsnf",0,(void*)matsnf0,7,"GD0,L,","matsnf(X,{flag=0}): Smith normal form (i.e. elementary divisors) of the matrix X, expressed as a vector d; X must have integer or polynomial entries. Binary digits of flag mean 1: returns [u,v,d] where d=u*X*v, otherwise only the diagonal d is returned, 4: removes all information corresponding to entries equal to 1 in d."}, {"matsolve",0,(void*)gauss,7,"GG","matsolve(M,B): solution of MX=B (M matrix, B column vector or matrix)."}, {"matsolvemod",0,(void*)matsolvemod,7,"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 nonzero return all solutions."}, {"matsupplement",0,(void*)suppl,7,"G","matsupplement(x): supplement the columns of the matrix x to an invertible matrix."}, {"mattranspose",0,(void*)gtrans,7,"G","mattranspose(x): x~ = transpose of x."}, {"max",0,(void*)gmax,2,"GG","max(x,y): maximum of x and y."}, {"mfDelta",0,(void*)mfDelta,15,"","mfDelta(): mf corresponding to the Ramanujan Delta function."}, {"mfEH",0,(void*)mfEH,15,"G","mfEH(k): k>0 being in 1/2+Z, mf corresponding to the Cohen-Eisenstein series H_k of weight k on G_0(4)."}, {"mfEk",0,(void*)mfEk,15,"L","mfEk(k): mf corresponding to the standard Eisenstein series E_k for nonnegative even integer k."}, {"mfTheta",0,(void*)mfTheta,15,"DG","mfTheta({psi=1}): the unary theta function corresponding to the primitive Dirichlet character psi, hence of weight 1/2 if psi is even, of weight 3/2 if psi is odd."}, {"mfatkin",0,(void*)mfatkin,15,"GG","mfatkin(mfatk,f): Given an mfatk output by mfatk = mfatkininit(mf,Q) and a modular form f belonging to the space mf, returns the modular form g = C*f|W_Q where C = mfatk[3] is a normalizing constant so that g has the same field of coefficients as f; mfatk[1] = mf2 (or 0 if mf2=mf) which is the space to which g belongs."}, {"mfatkineigenvalues",0,(void*)mfatkineigenvalues,15,"GLp","mfatkineigenvalues(mf,Q): given a modular form space mf and a primitive divisor Q of the level of mf, outputs the corresponding Atkin-Lehner eigenvalues on the new space, grouped by orbit."}, {"mfatkininit",0,(void*)mfatkininit,15,"GLp","mfatkininit(mf,Q): initializes data necessary for working with Atkin--Lehner operators W_Q, for now only the function mfatkin. The result is a 4-component vector [mfB, MC, C, mf] where mfB is either 0 or the possibly different modular form space to which F|W_Q will belong (this does not depend on F in mf); MC is the matrix of W_Q on the basis of mf multiplied by a normalizing constant C."}, {"mfbasis",0,(void*)mfbasis,15,"GD4,L,","mfbasis(NK,{space=4}): If NK=[N,k,CHI] as in mfinit, gives a basis of the corresponding subspace of M_k(G_0(N),CHI). NK can also be the output of mfinit, in which case space is ignored. To obtain the eigenforms use mfeigenbasis."}, {"mfbd",0,(void*)mfbd,15,"GL","mfbd(F,d): F being a generalized modular form, return B(d)(F), where B(d) is the expanding operator tau -> d tau."}, {"mfbracket",0,(void*)mfbracket,15,"GGD0,L,","mfbracket(F,G,{m=0}): compute the m-th Rankin-Cohen bracket of the generalized modular forms F and G."}, {"mfcoef",0,(void*)mfcoef,15,"GL","mfcoef(F,n): Compute the n-th Fourier coefficient a(n) of the generalized modular form F."}, {"mfcoefs",0,(void*)mfcoefs,15,"GLD1,L,","mfcoefs(F,n,{d=1}): Compute the vector of coefficients [a[0],a[d],...,a[nd]] of the modular form F."}, {"mfconductor",0,(void*)mfconductor,15,"lGG","mfconductor(mf,F): mf being output by mfinit and F a modular form, gives the smallest level at which F is defined."}, {"mfcosets",0,(void*)mfcosets,15,"G","mfcosets(N): list of right cosets of G_0(N)\\G, i.e., matrices g_j in G such that G = U G_0(N) g_j. The g_j are chosen in the form [a,b; c,d] with c | N."}, {"mfcuspisregular",0,(void*)mfcuspisregular,15,"lGG","mfcuspisregular(NK,cusp): In the space defined by NK = [N,k,CHI] or NK = mf, determine if cusp in canonical format (oo or denominator dividing N) is regular or not."}, {"mfcusps",0,(void*)mfcusps,15,"G","mfcusps(N): list of cusps of G_0(N) in the form a/b with b dividing N."}, {"mfcuspval",0,(void*)mfcuspval,15,"GGGb","mfcuspval(mf,F,cusp): valuation of modular form F in the space mf at cusp, which can be either oo or any rational number. The result is either a rational number or oo if F is zero. Let chi be the Nebentypus of the space mf; if Q(F) != Q(chi), return the vector of valuations attached to the [Q(F):Q(chi)] complex embeddings of F."}, {"mfcuspwidth",0,(void*)mfcuspwidth,15,"lGG","mfcuspwidth(N,cusp): width of cusp in Gamma_0(N)."}, {"mfderiv",0,(void*)mfderiv,15,"GD1,L,","mfderiv(F,{m=1}): m-th formal derivative of the power series corresponding to the generalized modular form F, with respect to the differential operator q.d/dq (default m=1)."}, {"mfderivE2",0,(void*)mfderivE2,15,"GD1,L,","mfderivE2(F,{m=1}): compute the Serre derivative (q.d/dq)F - kE_2F/12 of the generalized modular form F of weight k; and if m > 1, the m-th iterate."}, {"mfdescribe",0,(void*)mfdescribe,15,"GD&","mfdescribe(F,{&G}): gives a human-readable description of F, which is either a modular form space or a modular form. If the address of G is given, puts into G the vector of parameters of the outmost operator defining F."}, {"mfdim",0,(void*)mfdim,15,"GD4,L,","mfdim(NK,{space=4}): If NK=[N,k,CHI] as in mfinit, gives the dimension of the corresponding subspace of M_k(G_0(N),chi). The subspace is described by a small integer 'space': 0 for the newspace, 1 for the cuspidal space, 2 for the oldspace, 3 for the space of Eisenstein series and 4 (default) for the full space M_k. NK can also be the output of mfinit, in which case space must be omitted."}, {"mfdiv",0,(void*)mfdiv,15,"GG","mfdiv(F,G): compute F/G for two modular forms F and G assuming that the quotient will not have poles at infinity. If this is the case, use mfshift before doing the division."}, {"mfeigenbasis",0,(void*)mfeigenbasis,15,"G","mfeigenbasis(mf): vector of the eigenforms for the space mf."}, {"mfeigensearch",0,(void*)mfeigensearch,15,"GDG","mfeigensearch(NK,{AP}): search for normalized rational eigen cuspforms with quadratic characters given a few initial coefficients. The meaning of the parameters is as follows: NK is of the form [N,k]: search given level N, weight k and quadratic character; note that the character is uniquely determined by (N,k). The level N can be replaced by a vector of allowed levels. AP is the search criterion, which can be omitted: a list of pairs [...,[p,a_p],...], where a_p is either a t_INT (exact match) or a t_INTMOD (match modulo the given integer). The result is a vector of newforms matching the search criteria, sorted by increasing level."}, {"mfeisenstein",0,(void*)mfeisenstein,15,"LDGDG","mfeisenstein(k,{CHI1},{CHI2}): create the Eisenstein E_k(CHI1,CHI2), where an omitted character is considered as trivial."}, {"mfembed",0,(void*)mfembed0,15,"GDGp","mfembed(f,{v}): if v is omitted, f must be a modular form or a modular form space with parameters [N,k,chi] and we return a vector of complex embeddings of Q(f) or Q(chi), respectively. If v is given, it must be a scalar in Q(f), or a vector/matrix of such, we apply the embeddings coefficientwise and return a vector of results. Finally f can be replaced by a single embedding produced by mfembed(f) and we apply that particular embedding to v. Note that, in our context, Q(chi) has a single canonical embeding given by s: Mod(t, polcyclo(n,t)) -> exp(2*I*Pi/n) and Q(f) has [Q(f):Q(chi)] induced embeddings attached to the complex roots of s(P) where P = mfparams(f)[4], as ordered by polroots. In the latter case, we only support an f with Q(f) = Q(chi) or an eigenform produced by mfeigenbasis."}, {"mfeval",0,(void*)mfeval,15,"GGGb","mfeval(mf,F,vtau): computes the numerical value of the modular form F at the point vtau or the vector vtau of points in the completed upper-half plane."}, {"mffields",0,(void*)mffields,15,"G","mffields(mf): If mf is output by mfinit, gives the vector of polynomials defining each Galois orbit of the new space."}, {"mffromell",0,(void*)mffromell,15,"G","mffromell(E): E being an elliptic curve defined over Q given by an integral model in ellinit format, computes a 3-component vector [mf,F,v], where F is the newform corresponding to E by modularity, mf is the newspace to which F belongs, and v gives the coefficients of F on mfbasis(mf)."}, {"mffrometaquo",0,(void*)mffrometaquo,15,"GD0,L,","mffrometaquo(eta,{flag=0}): modular form corresponding to the eta quotient matrix eta. If the valuation v at infinity is fractional, returns 0. If the eta quotient is not holomorphic but simply meromorphic, returns 0 if flag=0; returns the eta quotient (divided by q to the power -v if v < 0, i.e., with valuation 0) if flag is set."}, {"mffromlfun",0,(void*)mffromlfun,15,"Gp","mffromlfun(L): L being an L-function representing a self-dual modular form, return [NK,space,v] where mf=mfinit(NK,space) contains the form and mftobasis(mf, v) containing it and v is mftobasis(mf,f)."}, {"mffromqf",0,(void*)mffromqf,15,"GDG","mffromqf(Q,{P}): Q being an even positive definite quadratic form and P a homogeneous spherical polynomial for Q, computes a 3-component vector [mf,F,coeffs], where F is the theta function corresponding to (Q, P), mf is the corresponding space of modular forms from mfinit, and coeffs are the coefficients of F on mfbasis(mf)."}, {"mfgaloisprojrep",0,(void*)mfgaloisprojrep,15,"GGp","mfgaloisprojrep(mf,F): mf being an mf output by mfinit in weight 1, and F an eigenform, returns a polynomial defining the field fixed by the kernel of the projective representation associated to F."}, {"mfgaloistype",0,(void*)mfgaloistype,15,"GDG","mfgaloistype(NK,{F}): NK being either [N,1,CHI] or an mf output by mfinit in weight 1 , gives the vector of types of Galois representations attached to each cuspidal eigenform, unless the eigenform F is specified, in which case only for F. Types A_4, S_4, A_5 are represented by minus their cardinality -12, -24, or -60, and type D_n is represented by its cardinality, the integer 2*n."}, {"mfhecke",0,(void*)mfhecke,15,"GGL","mfhecke(mf,F,n): F being a modular form in space mf, returns T(n)F, where T(n) is the n-th Hecke operator. Warning: if F is of level M= 3/2, gives a basis B of the Kohnen + space of mf as a matrix whose columns are the coefficients of B on the basis of mf."}, {"mfkohnenbijection",0,(void*)mfkohnenbijection,15,"G","mfkohnenbijection(mf): mf being a cuspidal space of half-integral weight returns [mf2,M,K,shi], where M is a matrix giving a Hecke-module isomorphism from S_{2k-1}(N,CHI^2) given by mf2 to the Kohnen + space S_k+(4N,CHI), K is a basis of the Kohnen + space, and shi gives the linear combination of Shimura lifts giving M^(-1)."}, {"mfkohneneigenbasis",0,(void*)mfkohneneigenbasis,15,"GG","mfkohneneigenbasis(mf,bij): mf being a cuspidal space of half-integral weight k >= 3/2 and bij being the output of mfkohnenbijection(mf), outputs a 3-component vector [mf0,BNEW,BEIGEN], where BNEW and BEIGEN are two matrices whose columns are the coefficients of a basis of the Kohnen new space and of the eigenforms on the basis of mf respectively, and mf0 is the corresponding new space of integral weight 2k - 1."}, {"mflinear",0,(void*)mflinear,15,"GG","mflinear(vF,v): vF being a vector of modular forms and v a vector of coefficients of same length, compute the linear combination of the entries of vF with coefficients v."}, {"mfmanin",0,(void*)mfmanin,15,"Gb","mfmanin(FS): Given the modular symbol FS associated to an eigenform F by mfsymbol(mf,F), computes the even and odd special polynomials as well as the even and odd periods om+ and om- as a vector [[P+,P-],[om+,om-,r]], where r = imag(om+*conj(om-))/. If F has several embeddings into C, give the vector of results corresponding to each embedding."}, {"mfmul",0,(void*)mfmul,15,"GG","mfmul(F,G): Multiply the two forms F and G."}, {"mfnumcusps",0,(void*)mfnumcusps,15,"G","mfnumcusps(N): number of cusps of Gamma_0(N)"}, {"mfparams",0,(void*)mfparams,15,"G","mfparams(F): If F is a modular form space, returns [N,k,CHI,space,Phi]: level, weight, character, and space code; where Phi is the cyclotomic polynomial defining the field of values of CHI. If F is a modular form, returns [N,k,CHI,P,Phi], where P is the (polynomial giving the) field of definition of F: in that case the level N may be a multiple of the level of F and the polynomial P may define a larger field than Q(F)."}, {"mfperiodpol",0,(void*)mfperiodpol,15,"GGD0,L,b","mfperiodpol(mf,f,{flag=0}): period polynomial of the cuspidal part of the form f, in other words integral from 0 to ioo of (X-tau)^(k-2)f(tau). If flag=0, ordinary period polynomial, if flag=1 or -1, even or odd part of that polynomial. f can also be the modular symbol output by mfsymbol(mf,f)."}, {"mfperiodpolbasis",0,(void*)mfperiodpolbasis,15,"LD0,L,","mfperiodpolbasis(k,{flag=0}): basis of period polynomials for weight k. If flag=1 or -1, basis of odd or even period polynomials."}, {"mfpetersson",0,(void*)mfpetersson,15,"GDG","mfpetersson(fs,{gs}): Petersson scalar product of the modular forms f and g belonging to the same modular form space mf, given by the corresponding \"modular symbols\" fs and gs output by mfsymbol (also in weight 1 and half-integral weight). If gs is omitted it is understood to be equal to fs. The scalar product is normalized by the factor 1/[G:G_0(N)]."}, {"mfpow",0,(void*)mfpow,15,"GL","mfpow(F,n): compute F^n"}, {"mfsearch",0,(void*)mfsearch,15,"GGD4,L,","mfsearch(NK,V,{space}): NK being of the form [N,k] with k possibly half-integral, search for a modular form with rational coefficients, of weight k and level N, whose initial coefficients a(0),... are equal to V; space specifies the modular form spaces in which to search. The output is a list of matching forms with that given level and weight. Note that the character is of the form (D/.), where D is a (positive or negative) fundamental discriminant dividing N. N can be replaced by a vector of allowed levels, in which case the list of forms is sorted by increasing level, then increasing |D|. If a form is found at level N, any multiple of N with the same D is not considered Note that this is very different from mfeigensearch, which only searches for rational eigenforms."}, {"mfshift",0,(void*)mfshift,15,"GL","mfshift(F,s): Divide the form F by q^s omitting the remainder if there is one; s can be negative."}, {"mfshimura",0,(void*)mfshimura,15,"GGD1,L,","mfshimura(mf,F,{D=1}): F being a modular form of half-integral weight k >= 3/2 and D a positive squarefree integer, computes the Shimura lift G of weight 2k-1 corresponding to D. This function returns [mf2,G,v], where mf2 is a modular form space containing G, and v the vector of coefficients of G on mf."}, {"mfslashexpansion",0,(void*)mfslashexpansion,15,"GGGLLD&p","mfslashexpansion(mf,f,g,n,flrat,{¶ms}): g being in M_2^+(Q), computes the Fourier expansion of f|_k g to n terms. f must belong to the space mf. If params is given, it is set to the parameters [alpha,w,A]. If flrat is 1, the program tries to rationalize the expression; if flag is 0, it does not."}, {"mfspace",0,(void*)mfspace,15,"lGDG","mfspace(mf,{f}): identify the modular space mf, resp. the modular form f in mf. Returns 0 (newspace), 1 (cuspidal space), 2 (old space), 3 (Eisenstein space) or 4 (full space). Return -1 when the form does not belong to the space."}, {"mfsplit",0,(void*)mfsplit,15,"GD0,L,D0,L,","mfsplit(mf,{dimlim=0},{flag=0}): mf containing the new space split the new space into Galois orbits of eigenforms of the newspace and return [vF,vK], where vF gives the (Galois orbit of) eigenforms in terms of mfbasis(mf) and vK is a list of polynomials defining each Galois orbit. If dimlim is set only the Galois orbits of dimension <= dimlim are computed (i.e. the rational eigenforms if dimlim = 1 and the character is real). Flag speeds up computations when the dimension is large: if flag = d > 0, when the dimension of the eigenspace is > d, only the Galois polynomial is computed."}, {"mfsturm",0,(void*)mfsturm,15,"lG","mfsturm(NK): Sturm bound for modular forms on G_0(N) and weight k, i.e., an upper bound for the order of the zero at infinity of a nonzero form. NK is either [N,k] or an mfinit (exact bound in the latter case)."}, {"mfsymbol",0,(void*)mfsymbol,15,"GDGb","mfsymbol(mf,f): Initialize data for working with all period polynomials of the modular form f: this is essential for efficiency for functions such as mfsymboleval, mfmanin, and mfpetersson. By abuse of language, initialize data for working with mfpetersson in weight 1 or half-integral weight (where no symbol exist)."}, {"mfsymboleval",0,(void*)mfsymboleval,15,"GGDGb","mfsymboleval(fs,path,{ga=id}): evaluation of the modular symbol fs output by mfsymbol on the given path, where path is either a vector [s1,s2] or an integral matrix [a,b;c,d] representing the path [a/c,b/d]. In both cases, s1 or s2 (or a/c or b/d) can also be elements of the upper half-plane. The result is the polynomial equal to the integral between s1 and s2 of (X-tau)^{k-2}F(tau). If ga in GL_2+(Q) is given, replace F by F|_k ga. If the integral diverges, the result will be a rational function."}, {"mftaylor",0,(void*)mftaylor,15,"GLD0,L,p","mftaylor(F,n,{flreal=0}): F being a modular form in M_k(SL_2(Z)), computes the first n+1 canonical Taylor expansion of F around tau=I. If flreal=0, computes only an algebraic equivalence class. If flreal is set, compute p_n such that for tau close enough to I we have f(tau)=(2I/(tau+I))^ksum_{n>=0}p_n((tau-I)/(tau+I))^n."}, {"mftobasis",0,(void*)mftobasis,15,"GGD0,L,","mftobasis(mf,F,{flag=0}): coefficients of the form F on the basis given by the mfbasis(mf). A q-expansion or vector of coefficients can also be given instead of F, but in this case an error message may occur if the expansion is too short. An error message is also given if F does not belong to the modular form space. If flag is set, instead of error messages return an output as an affine space of solutions if a q-expansion or vector of coefficients is given, or the empty column otherwise."}, {"mftocoset",0,(void*)mftocoset,15,"UGG","mftocoset(N,M,Lcosets): M being a matrix in SL_2(Z) and Lcosets being mfcosets(N), find the right coset of G_0(N) to which M belongs. The output is a pair [ga,i] such that M = ga * Lcosets[i], with ga in G_0(N)."}, {"mftonew",0,(void*)mftonew,15,"GG","mftonew(mf,F): mf being a full or cuspidal space with parameters [N,k,chi] and F a cusp form in that space, returns a vector of 3-component vectors [M,d,G], where f(chi) divides M divides N, d divides N/M, and G is a form in S_k^new(G_0(M),chi) such that F is equal to the sum of the B(d)(G) over all these 3-component vectors."}, {"mftraceform",0,(void*)mftraceform,15,"GD0,L,","mftraceform(NK,{space=0}): If NK=[N,k,CHI,.] as in mfinit with k integral, gives the trace form in the corresponding subspace of S_k(G_0(N),chi). The supported values for space are 0: the newspace (default), 1: the full cuspidal space."}, {"mftwist",0,(void*)mftwist,15,"GG","mftwist(F,D): returns the twist of the form F by the integer D, i.e., the form G such that mfcoef(G,n)=(D/n)mfcoef(F,n), where (D/n) is the Kronecker symbol."}, {"min",0,(void*)gmin,2,"GG","min(x,y): minimum of x and y."}, {"minpoly",0,(void*)minpoly,7,"GDn","minpoly(A,{v='x}): minimal polynomial of the matrix or polmod A."}, {"modreverse",0,(void*)modreverse,10,"G","modreverse(z): reverse polmod of the polmod z, if it exists."}, {"moebius",0,(void*)moebius,5,"lG","moebius(x): Moebius function of x."}, {"msatkinlehner",0,(void*)msatkinlehner,16,"GLDG","msatkinlehner(M,Q,{H}): M being a full modular symbol space of level N, as given by msinit, let Q | N, (Q,N/Q) = 1, and let H be a subspace stable under the Atkin-Lehner involution w_Q. Return the matrix of w_Q acting on H (M if omitted)."}, {"mscosets",0,(void*)mscosets0,16,"GG","mscosets(gen,inH): gen being a system of generators for a group G and H being a subgroup of finite index of G, return a list of right cosets of H \\ G and the right action of G on H \\ G. The subgroup H is given by a criterion inH (closure) deciding whether an element of G belongs to H."}, {"mscuspidal",0,(void*)mscuspidal,16,"GD0,L,","mscuspidal(M,{flag=0}): M being a full modular symbol space, as given by msinit, return its cuspidal part S. If flag = 1, return [S,E] its decomposition into Eisenstein and cuspidal parts."}, {"msdim",0,(void*)msdim,16,"lG","msdim(M): M being a modular symbol space or subspace, return its dimension as a Q-vector space."}, {"mseisenstein",0,(void*)mseisenstein,16,"G","mseisenstein(M): M being a full modular symbol space, as given by msinit, return its Eisenstein subspace."}, {"mseval",0,(void*)mseval,16,"GGDG","mseval(M,s,{p}): M being a full modular symbol space, as given by msinit, s being a modular symbol from M and p being a path between two elements in P^1(Q), return s(p)."}, {"msfarey",0,(void*)msfarey0,16,"GGD&","msfarey(F,inH,{&CM}): F being a Farey symbol attached to a group G contained in SL2(Z) and H a subgroup of G, return a Farey symbol attached to H; H is given by a criterion inH (closure) deciding whether an element of G belongs to H."}, {"msfromcusp",0,(void*)msfromcusp,16,"GG","msfromcusp(M,c): returns the modular symbol attached to the cusp c, where M is a modular symbol space of level N."}, {"msfromell",0,(void*)msfromell,16,"GD0,L,","msfromell(E,{sign=0}): return the [M, x], where M is msinit(N,2) and x is the modular symbol in M attached to the elliptic curve E/Q."}, {"msfromhecke",0,(void*)msfromhecke,16,"GGDG","msfromhecke(M,v,{H}): given a msinit M and a vector v of pairs [p, P] (where p is prime and P is a polynomial with integer coefficients), return a basis of all modular symbols such that P(Tp) * s = 0. If H is present, it must be a Hecke-stable subspace and we restrict to s in H."}, {"msgetlevel",0,(void*)msgetlevel,16,"lG","msgetlevel(M): M being a full modular symbol space, as given by msinit, return its level N."}, {"msgetsign",0,(void*)msgetsign,16,"lG","msgetsign(M): M being a full modular symbol space, as given by msinit, return its sign."}, {"msgetweight",0,(void*)msgetweight,16,"lG","msgetweight(M): M being a full modular symbol space, as given by msinit, return its weight k."}, {"mshecke",0,(void*)mshecke,16,"GLDG","mshecke(M,p,{H}): M being a full modular symbol space, as given by msinit, p being a prime number, and H being a Hecke-stable subspace (M if omitted), return the matrix of T_p acting on H (U_p if p divides the level)."}, {"msinit",0,(void*)msinit,16,"GGD0,L,","msinit(G,V,{sign=0}): given G a finite index subgroup of SL(2,Z) and a finite dimensional representation V of GL(2,Q), creates a space of modular symbols, the G-module Hom_G(Div^0(P^1 Q), V). This is canonically isomorphic to H^1_c(X(G), V), and allows to compute modular forms for G. If sign is present and nonzero, it must be +1 or -1 and we consider the subspace defined by Ker (Sigma - sign), where Sigma is induced by [-1,0;0,1]. Currently the only supported groups are the Gamma_0(N), coded by the integer N. The only supported representation is V_k = Q[X,Y]_{k-2}, coded by the integer k >= 2."}, {"msissymbol",0,(void*)msissymbol,16,"GG","msissymbol(M,s): M being a full modular symbol space, as given by msinit, check whether s is a modular symbol attached to M."}, {"mslattice",0,(void*)mslattice,16,"GDG","mslattice(M,{H}): M being a full modular symbol space, as given by msinit, H a Q-subspace or a matrix of modular symbols. Return the canonical integral structure of H."}, {"msnew",0,(void*)msnew,16,"G","msnew(M): M being a full modular symbol space, as given by msinit, return its new cuspidal subspace."}, {"msomseval",0,(void*)msomseval,16,"GGG","msomseval(Mp,PHI,path): return the vectors of moments of the p-adic distribution attached to the path 'path' via the overconvergent modular symbol 'PHI'."}, {"mspadicL",0,(void*)mspadicL,16,"GDGD0,L,","mspadicL(mu,{s=0},{r=0}): given mu from mspadicmoments (p-adic distributions attached to an overconvergent symbol PHI) returns the value on a character of Z_p^* represented by s of the derivative of order r of the p-adic L-function attached to PHI."}, {"mspadicinit",0,(void*)mspadicinit,16,"GLLD-1,L,","mspadicinit(M,p,n,{flag}): M being a full modular symbol space, as given by msinit and a prime p, initialize technical data needed to compute with overconvergent modular symbols (modulo p^n). If flag is unset, allow all symbols; if flag = 0, restrict to ordinary symbols; else initialize for symbols phi such that Tp(phi) = a_p * phi, with v_p(a_p) >= flag."}, {"mspadicmoments",0,(void*)mspadicmoments,16,"GGD1,L,","mspadicmoments(Mp,PHI,{D=1}): given Mp from mspadicinit, an overconvergent eigensymbol PHI, and optionally a fundamental discriminant D coprime to p, return the moments of the p-1 distributions PHI^D([0]-[oo]) | (a + pZp), 0 < a < p. To be used by mspadicL and mspadicseries."}, {"mspadicseries",0,(void*)mspadicseries,16,"GD0,L,","mspadicseries(mu,{i=0}): given mu from mspadicmoments, returns the attached p-adic series with maximal p-adic precision, depending on the precision of M (i-th Teichmueller component, if present)."}, {"mspathgens",0,(void*)mspathgens,16,"G","mspathgens(M): M being a full modular symbol space, as given by msinit, return a set of Z[G]-generators for Div^0(P^1 Q). The output is [g,R], where g is a minimal system of generators and R the vector of Z[G]-relations between the given generators."}, {"mspathlog",0,(void*)mspathlog,16,"GG","mspathlog(M,p): M being a full modular symbol space, as given by msinit and p being a path between two elements in P^1(Q), return (p_i) in Z[G] such that p = \\sum p_i g_i, and the g_i are fixed Z[G]-generators for Div^0(P^1 Q), see mspathgens."}, {"mspetersson",0,(void*)mspetersson,16,"GDGDG","mspetersson(M,{F},{G=F}): M being a full modular symbol space, as given by msinit, calculate the intersection product {F,G} of modular symbols F and G on M."}, {"mspolygon",0,(void*)mspolygon,16,"GD0,L,","mspolygon(M,{flag=0}): M describes a subgroup G of finite index in the modular group PSL2(Z), as given by msinit or a positive integer N (encoding the group G = Gamma0(N)), or by msfarey (arbitrary subgroups). Return an hyperbolic polygon (Farey symbol) attached to G. Binary digits of flag mean: 1=normalized polygon, 2=also add graphical representations."}, {"msqexpansion",0,(void*)msqexpansion,16,"GGDP","msqexpansion(M,projH,{B = seriesprecision}): M being a full modular symbol space, as given by msinit, and projH being a projector on a Hecke-simple subspace, return the Fourier coefficients [a_n, n <= B] of the corresponding normalized newform. If B omitted, use seriesprecision."}, {"mssplit",0,(void*)mssplit,16,"GDGD0,L,","mssplit(M,{H},{dimlim}): M being a full modular symbol space, as given by msinit, and H being a subspace (the new subspace if omitted), split H into Hecke-simple subspaces. If dimlim is present and positive, restrict to dim <= dimlim."}, {"msstar",0,(void*)msstar,16,"GDG","msstar(M,{H}): M being a full modular symbol space, as given by msinit, return the matrix of the * involution, induced by complex conjugation, acting on the (stable) subspace H (M if omitted)."}, {"mstooms",0,(void*)mstooms,16,"GG","mstooms(Mp,phi): given Mp from mspadicinit, lift the (classical) eigen symbol phi to a distribution-valued overconvergent symbol in the sense of Pollack and Stevens. The resulting overconvergent eigensymbol can then be used in mspadicmoments, then mspadicL or mspadicseries."}, {"my",0,NULL,1,NULL,"my(x,...,z): declare x,...,z as lexically-scoped local variables."}, {"newtonpoly",0,(void*)newtonpoly,10,"GG","newtonpoly(x,p): Newton polygon of polynomial x with respect to the prime p."}, {"next",0,(void*)next0,1,"D1,L,","next({n=1}): interrupt execution of current instruction sequence, and start another iteration from the n-th innermost enclosing loops."}, {"nextprime",0,(void*)nextprime,5,"G","nextprime(x): smallest pseudoprime >= x."}, {"nfalgtobasis",0,(void*)algtobasis,10,"GG","nfalgtobasis(nf,x): transforms the algebraic number x into a column vector on the integral basis nf.zk."}, {"nfbasis",0,(void*)nfbasis,10,"GD&","nfbasis(T,{&dK}): integral basis of the field Q[a], where a is a root of the polynomial T, using the round 4 algorithm. An argument [T,listP] is possible, where listP is a list of primes or a prime bound, to get an order which is maximal at certain primes only. If present, dK is set to the discriminant of the returned order."}, {"nfbasistoalg",0,(void*)basistoalg,10,"GG","nfbasistoalg(nf,x): transforms the column vector x on the integral basis into an algebraic number."}, {"nfcertify",0,(void*)nfcertify,10,"G","nfcertify(nf): returns a vector of composite integers used to certify nf.zk and nf.disc unconditionally (both are correct when the output is the empty vector)."}, {"nfcompositum",0,(void*)nfcompositum,10,"GGGD0,L,","nfcompositum(nf,P,Q,{flag=0}): vector of all possible compositums of the number fields defined by the polynomials P and Q; flag is optional, whose binary digits mean 1: output for each compositum, not only the compositum polynomial pol, but a vector [R,a,b,k] where a (resp. b) is a root of P (resp. Q) expressed as a polynomial modulo R, and a small integer k such that al2+k*al1 is the chosen root of R; 2: assume that the number fields defined by P and Q are linearly disjoint."}, {"nfdetint",0,(void*)nfdetint,10,"GG","nfdetint(nf,x): multiple of the ideal determinant of the pseudo generating set x."}, {"nfdisc",0,(void*)nfdisc,10,"G","nfdisc(T): discriminant of the number field defined by the polynomial T. An argument [T,listP] is possible, where listP is a list of primes or a prime bound."}, {"nfdiscfactors",0,(void*)nfdiscfactors,10,"G","nfdiscfactors(T): [D, faD], where D = nfdisc(T), and faD is the factorization of |D|."}, {"nfeltadd",0,(void*)nfadd,10,"GGG","nfeltadd(nf,x,y): element x+y in nf."}, {"nfeltdiv",0,(void*)nfdiv,10,"GGG","nfeltdiv(nf,x,y): element x/y in nf."}, {"nfeltdiveuc",0,(void*)nfdiveuc,10,"GGG","nfeltdiveuc(nf,x,y): gives algebraic integer q such that x-qy is small."}, {"nfeltdivmodpr",0,(void*)nfdivmodpr,10,"GGGG","nfeltdivmodpr(nf,x,y,pr): this function is obsolete, use nfmodpr."}, {"nfeltdivrem",0,(void*)nfdivrem,10,"GGG","nfeltdivrem(nf,x,y): gives [q,r] such that r=x-qy is small."}, {"nfeltembed",0,(void*)nfeltembed,10,"GGDGp","nfeltembed(nf,x,{pl}): complex embeddings of x at places given by vector pl."}, {"nfeltispower",0,(void*)nfispower,10,"lGGLD&","nfeltispower(nf,x,n,{&y}): returns 1 if x is an n-th power in nf (and set y to an n-th root if present), else returns 0."}, {"nfeltissquare",0,(void*)nfissquare,10,"lGGD&","nfeltissquare(nf,x,{&y}): returns 1 if x is a square in nf (and sets y to a square root if present), else returns 0."}, {"nfeltmod",0,(void*)nfmod,10,"GGG","nfeltmod(nf,x,y): gives r such that r=x-qy is small with q algebraic integer."}, {"nfeltmul",0,(void*)nfmul,10,"GGG","nfeltmul(nf,x,y): element x.y in nf."}, {"nfeltmulmodpr",0,(void*)nfmulmodpr,10,"GGGG","nfeltmulmodpr(nf,x,y,pr): this function is obsolete, use nfmodpr."}, {"nfeltnorm",0,(void*)nfnorm,10,"GG","nfeltnorm(nf,x): norm of x."}, {"nfeltpow",0,(void*)nfpow,10,"GGG","nfeltpow(nf,x,k): element x^k in nf."}, {"nfeltpowmodpr",0,(void*)nfpowmodpr,10,"GGGG","nfeltpowmodpr(nf,x,k,pr): this function is obsolete, use nfmodpr."}, {"nfeltreduce",0,(void*)nfreduce,10,"GGG","nfeltreduce(nf,a,id): gives r such that a-r is in the ideal id and r is small."}, {"nfeltreducemodpr",0,(void*)nfreducemodpr,10,"GGG","nfeltreducemodpr(nf,x,pr): this function is obsolete, use nfmodpr."}, {"nfeltsign",0,(void*)nfeltsign,10,"GGDG","nfeltsign(nf,x,{pl}): signs of real embeddings of x at places given by vector pl."}, {"nfelttrace",0,(void*)nftrace,10,"GG","nfelttrace(nf,x): trace of x."}, {"nfeltval",0,(void*)gpnfvalrem,10,"GGGD&","nfeltval(nf,x,pr,{&y}): valuation of element x at the prime pr as output by idealprimedec."}, {"nffactor",0,(void*)nffactor,10,"GG","nffactor(nf,T): factor polynomial T in number field nf."}, {"nffactorback",0,(void*)nffactorback,10,"GGDG","nffactorback(nf,f,{e}): given a factorization f, returns the factored object back as an nf element."}, {"nffactormod",0,(void*)nffactormod,10,"GGG","nffactormod(nf,Q,pr): this routine is obsolete, use nfmodpr and factormod. Factor polynomial Q modulo prime ideal pr in number field nf."}, {"nfgaloisapply",0,(void*)galoisapply,10,"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,10,"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; 4: use Allombert's algorithm, complete if the field is Galois of degree <= 35 (see manual for details). nf can be simply a polynomial."}, {"nfgrunwaldwang",0,(void*)nfgrunwaldwang,10,"GGGGDn","nfgrunwaldwang(nf,Lpr,Ld,pl,{v='x}): a polynomial in the variable v defining a cyclic extension of nf (given in nf or bnf form) with local behavior prescribed by Lpr, Ld and pl: the extension has local degree a multiple of Ld[i] at the prime Lpr[i], and the extension is complex at the i-th real place of nf if pl[i]=-1 (no condition if pl[i]=0). The extension has degree the LCM of the local degrees."}, {"nfhilbert",0,(void*)nfhilbert0,10,"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 nontrivial solution (X,Y,Z) in nf, -1 otherwise. Otherwise compute the local symbol modulo the prime ideal pr."}, {"nfhnf",0,(void*)nfhnf0,10,"GGD0,L,","nfhnf(nf,x,{flag=0}): if x=[A,I], gives a pseudo-basis [B,J] of the module sum A_jI_j. If flag is nonzero, return [[B,J], U], where U is the transformation matrix such that AU = [0|B]."}, {"nfhnfmod",0,(void*)nfhnfmod,10,"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,10,"GD0,L,p","nfinit(pol,{flag=0}): pol being a nonconstant irreducible polynomial in Q[X], returns an nf structure attached to the number field Q[X] / (pol). Binary digits of flag mean 1: two-element vector [nf,Mod(a,P)], where Mod(a,P) is a polmod equal to Mod(x,pol) and P=nf.pol; 2: first use polredbest to find a simpler polynomial P; 4: do not LLL-reduce the maximal order basis nf.zk."}, {"nfisideal",0,(void*)isideal,10,"lGG","nfisideal(nf,x): true(1) if x is an ideal in the number field nf, false(0) if not."}, {"nfisincl",0,(void*)nfisincl0,10,"GGD0,L,","nfisincl(f,g,{flag=0}): let f and g define number fields, either irreducible rational polynomials or number fields as output by nfinit; tests whether the number field f is isomorphic to a subfield of g. Return 0 if not, and otherwise all the embeddings (flag=0, default), only one (flag=1), or all embeddings as rational functions (flag=2)."}, {"nfisisom",0,(void*)nfisisom,10,"GG","nfisisom(f,g): as nfisincl but tests whether f is isomorphic to g."}, {"nfislocalpower",0,(void*)nfislocalpower,10,"lGGGG","nfislocalpower(nf,pr,a,n): true(1) if a is an n-th power in the local field K_v, false(0) if not."}, {"nfkermodpr",0,(void*)nfkermodpr,10,"GGG","nfkermodpr(nf,x,pr): this function is obsolete, use nfmodpr."}, {"nflist",0,(void*)nflist,10,"GDGD-1,L,DG","nflist(G,{N},{s=-1},{F}): finds number fields (up to isomorphism) with Galois group of Galois closure isomorphic to G, and s complex places. If s = -1 (default) all signatures, s = -2 is identical to s = -1 except fields are separated by increasing number of complex places. If field F is specified (by a polynomial), gives only number fields having F as a subfield (or a resolvent field in the case of S3, Dl, A4, S4, F5, M21 and M42). The parameter N can be the following: a positive integer (absolute value of discriminant is N); a vector [a,b] (finds fields with absolute discriminant between a and b); a polynomial, in variable t say (regular extension of Q(t) with specified Galois group). If omitted (default), returns a few fields and F is ignored."}, {"nfmodpr",0,(void*)nfmodpr,10,"GGG","nfmodpr(nf,x,pr): map x to the residue field mod pr."}, {"nfmodprinit",0,(void*)nfmodprinit0,10,"GGDn","nfmodprinit(nf,pr,{v=variable(nf.pol)}): transform the prime ideal pr into modpr format necessary for all operations mod pr in the number field nf. Variable v is used to display finite field elements (see ffgen)."}, {"nfmodprlift",0,(void*)nfmodprlift,10,"GGG","nfmodprlift(nf,x,pr): lift x from residue field mod pr to nf."}, {"nfnewprec",0,(void*)nfnewprec,10,"Gp","nfnewprec(nf): transform the number field data nf into new data using the current (usually larger) precision."}, {"nfpolsturm",0,(void*)nfpolsturm,10,"GGDG","nfpolsturm(nf,T,{pl}): number of distinct real roots of the polynomial s(T) where s runs through the real embeddings given by vector pl."}, {"nfresolvent",0,(void*)nfresolvent,10,"GD0,L,","nfresolvent(pol,{flag=0}): In the case where the Galois closure of the number field defined by pol is S3, Dl, A4, S4, F5, A5, M21, or M42, gives the corresponding resolvent field. Otherwise, give a \"canonical\" subfield, or if flag >= 2 all \"canonical\" subfields. If flag is odd, give also the \"conductor\" f, whose definition is specific to each group."}, {"nfroots",0,(void*)nfroots,10,"DGG","nfroots({nf},x): roots of polynomial x belonging to nf (Q if omitted) without multiplicity."}, {"nfrootsof1",0,(void*)nfrootsof1,10,"G","nfrootsof1(nf): number of roots of unity and primitive root of unity in the number field nf."}, {"nfsnf",0,(void*)nfsnf0,10,"GGD0,L,","nfsnf(nf,x,{flag=0}): if x=[A,I,J], outputs D=[d_1,...d_n] Smith normal form of x. If flag is nonzero return [D,U,V], where UAV = Id."}, {"nfsolvemodpr",0,(void*)nfsolvemodpr,10,"GGGG","nfsolvemodpr(nf,a,b,P): this function is obsolete, use nfmodpr."}, {"nfsplitting",0,(void*)nfsplitting0,10,"GDGD0,L,","nfsplitting(P,{d},{fl}): defining polynomial S over Q for the splitting field of P, that is the smallest field over which P is totally split. P can also be given by a nf structure. If d is given, it must be a multiple of the splitting field degree. If fl=1, return [S,C] where C is an embedding of Q[x]/(P) in its splitting field."}, {"nfsubfields",0,(void*)nfsubfields0,10,"GD0,L,D0,L,","nfsubfields(pol,{d=0},{flag=0}): finds all subfields of degree d of number field defined by pol (all subfields if d is null or omitted). The result is a vector of subfields, each being given by [g,h] (default) or simply g (flag=1), 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."}, {"nfsubfieldscm",0,(void*)nfsubfieldscm,10,"GD0,L,","nfsubfieldscm(nf,{flag=0}): computes the maximal CM subfield of nf. Returns 0 if nf does not have a CM subfield, otherwise returns [g,h] (default) or g (flag=1) where g is an absolute equation and h expresses a root of g in terms of the generator of nf."}, {"nfsubfieldsmax",0,(void*)nfsubfieldsmax,10,"GD0,L,","nfsubfieldsmax(nf,{flag=0}): computes the list of maximal subfields of nf. The result is as in nfsubfields."}, {"nfweilheight",0,(void*)nfweilheight,10,"GGp","nfweilheight(nf, v): return the absolute Weil height of the vector v seen as an element of the projective space over the number field nf given by nfinit."}, {"norm",0,(void*)gnorm,3,"G","norm(x): norm of x."}, {"norml2",0,(void*)gnorml2,7,"G","norml2(x): square of the L2-norm of x."}, {"normlp",0,(void*)gnormlp,7,"GDGp","normlp(x,{p=oo}): Lp-norm of x; sup norm if p is omitted."}, {"numbpart",0,(void*)numbpart,4,"G","numbpart(n): number of partitions of n."}, {"numdiv",0,(void*)numdiv,5,"G","numdiv(x): number of divisors of x."}, {"numerator",0,(void*)numerator,3,"GDG","numerator(f,{D}): numerator of f."}, {"numtoperm",0,(void*)numtoperm,4,"LG","numtoperm(n,k): permutation number k (mod n!) of n letters (n C-integer)."}, {"omega",0,(void*)omega,5,"lG","omega(x): number of distinct prime divisors of x."}, {"oo",0,(void*)mkoo,3,"","oo=oo(): infinity."}, {"padicappr",0,(void*)padicappr,6,"GG","padicappr(pol,a): p-adic roots of the polynomial pol congruent to a mod p."}, {"padicfields",0,(void*)padicfields0,6,"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*)gppadicprec,3,"GG","padicprec(x,p): return the absolute p-adic precision of object x."}, {"parapply",0,(void*)parapply,1,"GG","parapply(f,x): parallel evaluation of f on the elements of x."}, {"pareval",0,(void*)pareval,1,"G","pareval(x): parallel evaluation of the elements of the vector of closures x."}, {"parfor",0,(void*)parfor0,1,"vV=GDGJDVDI","parfor(i=a,{b},expr1,{r},{expr2}): evaluates the expression expr1 in parallel for all i between a and b (if b is set to +oo, the loop will not stop), resulting in as many values; if r and expr2 are present, the expression expr2 in the formal variables r and i is evaluated with r running through all the different results obtained for expr1 and i takes the corresponding argument."}, {"parforeach",0,(void*)parforeach0,1,"vGVJDVDI","parforeach(V,x,expr1,{r},{expr2}): evaluates in parallel the expression expr1 for all components x of V. If the formal variables r and expr2 are present, evaluate sequentially expr2, in which x and r are replaced by the successive arguments and corresponding values."}, {"parforprime",0,(void*)parforprime0,1,"vV=GDGJDVDI","parforprime(p=a,{b},expr1,{r},{expr2}): evaluates the expression expr1 in parallel for all primes p between a and b (if b is set to +oo, the loop will not stop), resulting in as many values; if the formal variables r and expr2 are present, evaluate sequentially expr2, in which r has been replaced by the different results obtained for expr1 and p with the corresponding arguments."}, {"parforprimestep",0,(void*)parforprimestep0,1,"vV=GDGGJDVDI","parforprimestep(p=a,{b},q,expr1,{r},{expr2}): evaluates the expression expr1 in parallel for all primes p between a and b in an arithmetic progression of the form a + k*q, resulting in as many values; if the formal variables r and expr2 are present, evaluate sequentially expr2, in which r has been replaced by the different results obtained for expr1 and p with the corresponding arguments."}, {"parforstep",0,(void*)parforstep0,1,"vV=GDGGJDVDI","parforstep(i=a,{b},s,expr1,{r},{expr2}): evaluates the expression expr1 in parallel for i going from a to b in steps of s (can be a positive real number, an intmod for an arithmetic progression, or finally a vector of steps). If the formal variables r and expr2 are present, evaluates sequentially expr2, in which r has been replaced by the different results obtained for expr1 and i with the corresponding arguments."}, {"parforvec",0,(void*)parforvec0,1,"vV=GJDVDID0,L,","parforvec(X=v,expr1,{j},{expr2},{flag}): evaluates the sequence expr2 (dependent on X and j) for X as generated by forvec, in random order, computed in parallel. Substitute for j the value of expr1 (dependent on X)."}, {"parploth",0,(void*)parploth,17,"V=GGJD0,M,D0,L,p\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","parploth(X=a,b,expr,{flags=0},{n=0}): parallel version of ploth. Plot of expression expr, X goes from a to b in high resolution. Both flags and n are optional. Binary digits of flags mean: 1=Parametric, 2=Recursive, 4=no_Rescale, 8=no_X_axis, 16=no_Y_axis, 32=no_Frame, 64=no_Lines (do not join points), 128=Points_too (plot both lines and points), 256=Splines (use cubic splines), 512=no_X_ticks, 1024= no_Y_ticks, 2048=Same_ticks (plot all ticks with the same length), 4096=Complex (the two coordinates of each point are encoded as a complex number). n specifies number of reference points on the graph (0=use default value). Returns a vector for the bounding box."}, {"parplothexport",0,(void*)parplothexport,17,"GV=GGJD0,M,D0,L,p\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","parplothexport(fmt,X=a,b,expr,{flags=0},{n=0}): parallel version of plothexport. Plot of expression expr, X goes from a to b in high resolution, returning the resulting picture as a character string which can then be written to a file."}, {"parselect",0,(void*)parselect,1,"GGD0,L,","parselect(f,A,{flag=0}): (parallel select) selects elements of A according to the selection function f which is tested in parallel. If flag is 1, return the indices of those elements (indirect selection)."}, {"parsum",0,(void*)parsum,1,"V=GGJ","parsum(i=a,b,expr): the sum (i goes from a to b) of expression expr, evaluated in parallel (in random order)."}, {"partitions",0,(void*)partitions,4,"LDGDG","partitions(k,{a=k},{n=k}): vector of partitions of the integer k. You can restrict the length of the partitions with parameter n (n=nmax or n=[nmin,nmax]), or the range of the parts with parameter a (a=amax or a=[amin,amax]). By default remove zeros, but one can set amin=0 to get X of fixed length nmax (=k by default)."}, {"parvector",0,(void*)parvector,1,"LVJ","parvector(N,i,expr): as vector(N,i,expr) but the evaluations of expr are done in parallel."}, {"permcycles",0,(void*)permcycles,4,"G","permcycles(x): cycles of the permutation x."}, {"permorder",0,(void*)permorder,4,"G","permorder(x): order of the permutation x."}, {"permsign",0,(void*)permsign,4,"lG","permsign(x): signature of the permutation x."}, {"permtonum",0,(void*)permtonum,4,"G","permtonum(x): ordinal (between 0 and n!-1) of permutation x."}, {"plot",0,(void*)pariplot0,17,"vV=GGEDGDGp","plot(X=a,b,expr,{Ymin},{Ymax}): crude plot of expression expr, X goes from a to b, with Y ranging from Ymin to Ymax. If Ymin (resp. Ymax) is not given, the minimum (resp. the maximum) of the expression is used instead."}, {"plotarc",0,(void*)plotarc,17,"vLGGD0,L,","plotarc(w,x2,y2,{filled=0}): if the cursor is at position (x1,y1), draws the ellipse that fits inside the box with diagonal (x1,y1) and (x2,y2) in rectwindow w (cursor does not move). If filled=1, fill the ellipse"}, {"plotbox",0,(void*)plotbox,17,"vLGGD0,L,","plotbox(w,x2,y2,{filled=0}): 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). If filled=1, fill the box."}, {"plotclip",0,(void*)plotclip,17,"vL","plotclip(w): clip the contents of the rectwindow to the bounding box (except strings)."}, {"plotcolor",0,(void*)plotcolor,17,"LG","plotcolor(w,c): in rectwindow w, set default color to c. Possible values for c are [R,G,B] values, a color name or an index in the graphcolormap default: factory settings are 0=white, 1=black, 2=blue, 3=sienna, 4=red, 5=green, 6=grey, 7=gainsborough. Return [R,G,B] value attached to color."}, {"plotcopy",0,(void*)plotcopy,17,"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*)plotcursor,17,"L","plotcursor(w): current position of cursor in rectwindow w."}, {"plotdraw",0,(void*)plotdraw,17,"vGD0,L,","plotdraw(w,{flag=0}): draw rectwindow w. More generally, w can be of the form [w1,x1,y1, w2,x2,y2,etc.]: draw rectwindows wi at given xi,yi positions. If flag!=0, the xi,yi express fractions of the size of the current output device."}, {"plotexport",0,(void*)plotexport,17,"GGD0,L,","plotexport(fmt,list,{flag=0}): draw vector of rectwindows list as in plotdraw, returning the resulting picture as a character string; fmt is either \"ps\" or \"svg\"."}, {"ploth",0,(void*)ploth0,17,"V=GGED0,M,D0,L,p\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; No_MinMax|8192;","ploth(X=a,b,expr,{flag=0},{n=0}): plot of expression expr, X goes from a to b in high resolution. Both flag and n are optional. Binary digits of flag mean: 1=Parametric, 2=Recursive, 4=no_Rescale, 8=no_X_axis, 16=no_Y_axis, 32=no_Frame, 64=no_Lines (do not join points), 128=Points_too (plot both lines and points), 256=Splines (use cubic splines), 512=no_X_ticks, 1024= no_Y_ticks, 2048=Same_ticks (plot all ticks with the same length), 4096=Complex (the two coordinates of each point are encoded as a complex number). n specifies number of reference points on the graph (0=use default value). Returns a vector for the bounding box."}, {"plothexport",0,(void*)plothexport0,17,"GV=GGED0,M,D0,L,p\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","plothexport(fmt,X=a,b,expr,{flags=0},{n=0}): plot of expression expr, X goes from a to b in high resolution, returning the resulting picture as a character string which can then be written to a file."}, {"plothraw",0,(void*)plothraw,17,"GGD0,L,","plothraw(X,Y,{flag=0}): plot in high resolution points whose x (resp. y) coordinates are in X (resp. Y). If flag is 1, join points, other nonzero flags should be combinations of bits 8,16,32,64,128,256 meaning the same as for ploth()."}, {"plothrawexport",0,(void*)plothrawexport,17,"GGGD0,L,","plothrawexport(fmt,X,Y,{flag=0}): plot in high resolution points whose x (resp. y) coordinates are in X (resp. Y), returning the resulting picture as a character string. If flag is 1, join points, other nonzero flags should be combinations of bits 8,16,32,64,128,256 meaning the same as for ploth()."}, {"plothsizes",0,(void*)plothsizes,17,"D0,L,","plothsizes({flag=0}): returns array of 8 elements: terminal width and height, sizes for ticks in horizontal and vertical directions, width and height of characters, width and height of display (if applicable). If flag=0, sizes of ticks and characters are in pixels, otherwise are fractions of the terminal size."}, {"plotinit",0,(void*)plotinit,17,"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*)plotkill,17,"vL","plotkill(w): erase the rectwindow w."}, {"plotlines",0,(void*)plotlines,17,"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 nonzero, close the polygon."}, {"plotlinetype",0,(void*)plotlinetype,17,"vLL","plotlinetype(w,type): this function is obsolete; no graphing engine implement this functionality."}, {"plotmove",0,(void*)plotmove,17,"vLGG","plotmove(w,x,y): move cursor to position x,y in rectwindow w."}, {"plotpoints",0,(void*)plotpoints,17,"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*)plotpointsize,17,"vLG","plotpointsize(w,size): change the \"size\" of following points in rectwindow w. w=-1 changes global value."}, {"plotpointtype",0,(void*)plotpointtype,17,"vLL","plotpointtype(w,type): this function is obsolete; no graphing engine implement this functionality."}, {"plotrbox",0,(void*)plotrbox,17,"vLGGD0,L,","plotrbox(w,dx,dy,{filled}): 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). If filled=1, fill the box."}, {"plotrecth",0,(void*)plotrecth0,17,"LV=GGED0,M,D0,L,p\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*)plotrecthraw,17,"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*)plotrline,17,"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*)plotrmove,17,"vLGG","plotrmove(w,dx,dy): move cursor to position (dx,dy) relative to the present position in the rectwindow w."}, {"plotrpoint",0,(void*)plotrpoint,17,"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*)plotscale,17,"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 0 if f = Phi_n, the n-th cyclotomic polynomial."}, {"poliscycloprod",0,(void*)poliscycloprod,6,"lG","poliscycloprod(f): returns 1 if f is a product of cyclotomic polynonials, and 0 otherwise."}, {"polisirreducible",0,(void*)polisirreducible,6,"lG","polisirreducible(pol): true(1) if pol is an irreducible nonconstant polynomial, false(0) if pol is reducible or constant."}, {"pollaguerre",0,(void*)pollaguerre_eval0,6,"LDGDGD0,L,","pollaguerre(n,{a=0},{b='x},{flag=0}): Laguerre polynomial of degree n and parameter a evaluated at b. If flag is 1, return [L^{(a)_{n-1}(b), L^{(a)}_n(b)]."}, {"pollead",0,(void*)pollead,6,"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_eval0,6,"LDGD0,L,","pollegendre(n,{a='x},{flag=0}): legendre polynomial of degree n evaluated at a. If flag is 1, return [P_{n-1}(a), P_n(a)]."}, {"polmodular",0,(void*)polmodular,6,"LD0,L,DGDnD0,L,","polmodular(L,{inv=0},{x='x},{y='y},{derivs=0}): return the modular polynomial of level L and invariant inv."}, {"polrecip",0,(void*)polrecip,6,"G","polrecip(pol): reciprocal polynomial of pol."}, {"polred",0,(void*)polred0,10,"GD0,L,DG","polred(T,{flag=0}): deprecated, use polredbest. Reduction of the polynomial T (gives minimal polynomials only). The following binary digits of (optional) flag are significant 1: partial reduction, 2: gives also elements."}, {"polredabs",0,(void*)polredabs0,10,"GD0,L,","polredabs(T,{flag=0}): a smallest generating polynomial of the number field for the T2 norm on the roots, with smallest index for the minimal T2 norm. flag is optional, whose binary digit mean 1: give the element whose characteristic polynomial is the given polynomial. 4: give all polynomials of minimal T2 norm (give only one of P(x) and P(-x))."}, {"polredbest",0,(void*)polredbest,10,"GD0,L,","polredbest(T,{flag=0}): reduction of the polynomial T (gives minimal polynomials only). If flag=1, gives also elements."}, {"polredord",0,(void*)polredord,10,"G","polredord(x): this function is obsolete, use polredbest."}, {"polresultant",0,(void*)polresultant0,6,"GGDnD0,L,","polresultant(x,y,{v},{flag=0}): resultant of the polynomials x and y, with respect to the main variables of x and y if v is omitted, with respect to the variable v otherwise. flag is optional, and can be 0: default, uses either the subresultant algorithm, a modular algorithm or Sylvester's matrix, depending on the inputs; 1 uses Sylvester's matrix (should always be slower than the default)."}, {"polresultantext",0,(void*)polresultantext0,6,"GGDn","polresultantext(A,B,{v}): return [U,V,R] such that R=polresultant(A,B,v) and U*A+V*B = R, where A and B are polynomials."}, {"polroots",0,(void*)roots,6,"Gp","polroots(T): complex roots of the polynomial T using Schonhage's method, as modified by Gourdon."}, {"polrootsbound",0,(void*)polrootsbound,6,"GDG","polrootsbound(T,{tau=0.01}): return a sharp upper bound for the modulus of the largest complex root of the polynomial T with relative error tau."}, {"polrootsff",0,(void*)polrootsff,6,"GDGDG","polrootsff(x,{p},{a}): obsolete, use polrootsmod."}, {"polrootsmod",0,(void*)polrootsmod,6,"GDG","polrootsmod(f,{D}): roots of the polynomial f over the finite field defined by the domain D."}, {"polrootspadic",0,(void*)polrootspadic,6,"GGL","polrootspadic(f,p,r): p-adic roots of the polynomial f to precision r."}, {"polrootsreal",0,(void*)realroots,6,"GDGp","polrootsreal(T,{ab}): real roots of the polynomial T with real coefficients, using Uspensky's method. In interval ab = [a,b] if present."}, {"polsturm",0,(void*)sturmpart,6,"lGDGDG","polsturm(T,{ab}): number of distinct real roots of the polynomial T (in the interval ab = [a,b] if present)."}, {"polsubcyclo",0,(void*)polsubcyclo,6,"LLDn","polsubcyclo(n,d,{v='x}): finds an equation (in variable v) for the d-th degree subfields of Q(zeta_n). Output is a polynomial, or a vector of polynomials if there are several such fields or none."}, {"polsubcyclofast",0,(void*)polsubcyclofast,6,"GLD0,L,D0,L,","polsubcyclofast(n,d,{s=0},{exact=0}): If 1 <= d <= 6 or a prime, finds an equation for the subfields of Q(zeta_n) with galois group C_d. Contrary to polsubcyclo, the output is always a (possibly empty) vector of polynomials. If s = 0 (default) all signatures, otherwise s = 1 (resp., -1) for totally real (resp., totally complex). Set exact = 1 for subfields of exact conductor n."}, {"polsylvestermatrix",0,(void*)sylvestermatrix,6,"GG","polsylvestermatrix(x,y): forms the sylvester matrix attached to the two polynomials x and y. Warning: the polynomial coefficients are in columns, not in rows."}, {"polsym",0,(void*)polsym,6,"GL","polsym(x,n): column vector of symmetric powers of the roots of x up to n."}, {"poltchebi",0,(void*)polchebyshev1,6,"LDn","poltchebi(n,{v='x}): deprecated alias for polchebyshev."}, {"polteichmuller",0,(void*)polteichmuller,6,"GUL","polteichmuller(T,p,r): return the polynomial whose roots (resp. leading coef) are the Teichmuller lift of the roots (resp. leading coef) of T, to p-adic precision r."}, {"poltomonic",0,(void*)poltomonic,6,"GD&","poltomonic(T,{&L}): T in Q[x]; returns U monic in Z[x] such that U(x) = C T(x/L) for some rational C and L. If &L is given, set it to L."}, {"poltschirnhaus",0,(void*)tschirnhaus,10,"G","poltschirnhaus(x): random Tschirnhausen transformation of the polynomial x."}, {"polylog",0,(void*)polylog0,8,"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."}, {"polylogmult",0,(void*)polylogmult_interpolate,8,"GDGDGp","polylogmult(s,{z},{t=0}): multiple polylogarithm value at integral s = [s1,...,sr] with argument z = [z1,...,zr]. If z is omitted, assume z = [1,...,1], i.e., multiple zeta value. More generally, return Yamamoto's interpolation at t (ordinary multiple polylog at t = 0 and star value at t = 1)."}, {"polzagier",0,(void*)polzag,6,"LL","polzagier(n,m): Zagier's polynomials of index n,m."}, {"powers",0,(void*)gpowers0,7,"GLDG","powers(x,n,{x0}): return the vector [1,x,...,x^n] if x0 is omitted, and [x0, x0*x, ..., x0*x^n] otherwise."}, {"precision",0,(void*)precision00,3,"GDG","precision(x,{n}): if n is present, return x at precision n. If n is omitted, return real precision of object x."}, {"precprime",0,(void*)precprime,5,"G","precprime(x): largest pseudoprime <= x, 0 if x<=1."}, {"prime",0,(void*)prime,5,"L","prime(n): returns the n-th prime (n C-integer)."}, {"primecert",0,(void*)primecert0,5,"GD0,L,D0,L,","primecert(N,{flag=0},{partial=0}): If N is a prime, return a Primality Certificate. Return 0 otherwise. If flag = 0 return an ECPP certificate (Atkin-Morain); if flag = 1 return an N-1 certificate (Pocklington-Lehmer)"}, {"primecertexport",0,(void*)primecertexport,5,"GD0,L,","primecertexport(cert,{format=0}): Returns a string suitable for print/write to display a primality certificate."}, {"primecertisvalid",0,(void*)primecertisvalid,5,"lG","primecertisvalid(cert): Verifies if cert is a valid PARI ECPP Primality certificate."}, {"primepi",0,(void*)primepi,5,"G","primepi(x): the prime counting function pi(x) = #{p <= x, p prime}."}, {"primes",0,(void*)primes0,5,"G","primes(n): returns the vector of the first n primes (integer), or the primes in interval n = [a,b]."}, {"print",0,(void*)print,1,"vs*","print({str}*): outputs its string arguments (in raw format) ending with a newline."}, {"print1",0,(void*)print1,1,"vs*","print1({str}*): outputs its string arguments (in raw format) without ending with newline."}, {"printf",0,(void*)printf0,1,"vss*","printf(fmt,{x}*): prints its arguments according to the format fmt."}, {"printp",0,(void*)printp,1,"vs*","printp({str}*): outputs its string arguments (in prettymatrix format) ending with a newline."}, {"printsep",0,(void*)printsep,1,"vss*","printsep(sep,{str}*): outputs its string arguments (in raw format), separated by 'sep', ending with a newline."}, {"printsep1",0,(void*)printsep1,1,"vss*","printsep1(sep,{str}*): outputs its string arguments (in raw format), separated by 'sep', without ending with a newline."}, {"printtex",0,(void*)printtex,1,"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(p=a,b,expr): Euler product (p runs over the primes between a and b) of real or complex expression, as a floating point approximation."}, {"prodeulerrat",0,(void*)prodeulerrat,9,"GDGD2,L,p","prodeulerrat(F,{s=1},{a=2}): product from primes p = a to infinity of F(p^s), where F is a rational function."}, {"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."}, {"prodnumrat",0,(void*)prodnumrat,9,"GLp","prodnumrat(F,a): product from n = a to infinity of F(n), where F-1 is a rational function of degree less than or equal to -2."}, {"psdraw",0,(void*)psdraw,17,"vGD0,L,","psdraw(list,{flag=0}): obsolete function."}, {"psi",0,(void*)gpsi_der,8,"GD0,L,p","psi(x,{der}): psi-function at x (der-th derivative of psi if der is set)"}, {"psploth",0,(void*)psploth0,17,"V=GGED0,M,D0,L,p\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","psploth(X=a,b,expr,{flags=0},{n=0}): obsolete function."}, {"psplothraw",0,(void*)psplothraw,17,"GGD0,L,","psplothraw(listx,listy,{flag=0}): obsolete function."}, {"qfauto",0,(void*)qfauto0,7,"GDG","qfauto(G,{fl}): automorphism group of the positive definite quadratic form G."}, {"qfautoexport",0,(void*)qfautoexport,7,"GD0,L,","qfautoexport(qfa,{flag}): qfa being an automorphism group as output by qfauto, output a string representing the underlying matrix group in GAP notation (default) or Magma notation (flag = 1)."}, {"qfbclassno",0,(void*)qfbclassno0,5,"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."}, {"qfbcomp",0,(void*)qfbcomp,5,"GG","qfbcomp(x,y): Gaussian composition with reduction of the binary quadratic forms x and y."}, {"qfbcompraw",0,(void*)qfbcompraw,5,"GG","qfbcompraw(x,y): Gaussian composition without reduction of the binary quadratic forms x and y."}, {"qfbcornacchia",0,(void*)qfbcornacchia,5,"GG","qfbcornacchia(d,n): Solves the equation x^2+dy^2 = n in integers x and y where d > 0 and n is prime or 4 times a prime."}, {"qfbhclassno",0,(void*)hclassno,5,"G","qfbhclassno(x): Hurwitz-Kronecker class number of x>0."}, {"qfbil",0,(void*)qfbil,7,"GGDG","qfbil(x,y,{q}): this function is obsolete, use qfeval."}, {"qfbnucomp",0,(void*)nucomp,5,"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,5,"GGDG","qfbnupow(x,n,{L}): n-th power of primitive positive definite quadratic form x using nucomp and nudupl."}, {"qfbpow",0,(void*)qfbpow,5,"GG","qfbpow(x,n): n-th power with reduction of the binary quadratic form x."}, {"qfbpowraw",0,(void*)qfbpowraw,5,"GL","qfbpowraw(x,n): n-th power without reduction of the binary quadratic form x."}, {"qfbprimeform",0,(void*)primeform,5,"GG","qfbprimeform(x,p): returns the prime form of discriminant x, whose first coefficient is p."}, {"qfbred",0,(void*)qfbred0,5,"GD0,L,DGDG","qfbred(x,{flag=0},{isd},{sd}): reduction of the binary quadratic form x. All other args. are optional. The argument isd and sd, if present, supply the values of floor(sqrt(d)) and sqrt(d) respectively, where d is the discriminant. If d<0, its value is not used. flag can be any of 0: default; 1: do a single reduction step;"}, {"qfbredsl2",0,(void*)qfbredsl2,5,"GDG","qfbredsl2(x,{isD}): reduction of the binary quadratic form x, returns [y,g] where y is reduced and g in Sl(2,Z) is such that g.x = y; isD, if present, must be equal to sqrtint(D), where D > 0 is the discriminant of x."}, {"qfbsolve",0,(void*)qfbsolve,5,"GGD0,L,","qfbsolve(Q,n,{flag=0}): Solve the equation Q(x,y)=n in coprime integers x and y where Q is a binary quadratic form, up to the action of the special orthogonal group of Q over the integers. Binary digits of flag mean 1: return all solutions, 2: also include imprimitive solutions."}, {"qfcholesky",0,(void*)qfcholesky,7,"Gp","qfcholesky(q): given a square symmetric matrix M, return R such that R~*R = M, or [] if there is no solution."}, {"qfcvp",0,(void*)qfcvp0,7,"GGDGDGD0,L,","qfcvp(x,t,{B},{m},{flag=0}): x being a square and symmetric matrix representing a positive definite quadratic form, and t a vector of the same dimension, this function deals with the vectors of whose squared distance to t is less than B, enumerated using the Fincke-Pohst algorithm, storing at most m vectors (no limit if m is omitted). The function searches for the closest vectors to t if B is omitted or <= 0. The precise behavior depends on flag. 0: returns at most m vectors (unless m omitted), returns [N,M,V] where N is the number of vectors enumerated, M the maximum squared distance among these, and V lists the vectors. 1: ignores m and returns the first vector whose squared distance to t is less than B."}, {"qfeval",0,(void*)qfeval0,7,"DGGDG","qfeval({q},x,{y}): evaluate the quadratic form q (symmetric matrix) at x; if y is present, evaluate the polar form at (x,y); if q omitted, use the standard Euclidean form."}, {"qfgaussred",0,(void*)qfgaussred0,7,"GD0,L,","qfgaussred(q,{flag=0}): square reduction of the symmetric matrix q. flag=0: returns a square matrix A such that q(x) = sum_i A[i,i] (x[i] + sum_{j != i} A[i,j] x[j])^2; flag=1 return [U,V] where U is a square matrix and V a vector such that q = U~ * matdiagonal(V) * U"}, {"qfisom",0,(void*)qfisom0,7,"GGDGDG","qfisom(G,H,{fl},{grp}): find an isomorphism between the integral positive definite quadratic forms G and H if it exists. G can also be given by a qfisominit structure which is preferable if several forms need to be compared to G."}, {"qfisominit",0,(void*)qfisominit0,7,"GDGDG","qfisominit(G,{fl},{m}): G being a square and symmetric matrix representing an integral positive definite quadratic form, this function returns a structure allowing to compute isomorphisms between G and other quadratic form faster."}, {"qfjacobi",0,(void*)jacobi,7,"Gp","qfjacobi(A): eigenvalues and orthogonal matrix of eigenvectors of the real symmetric matrix A."}, {"qflll",0,(void*)qflll0,7,"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: disable FLATTER, 2: assumes x is integral, returns a partially reduced basis, 3: assumes x is integral, in place (return x*T), 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,7,"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: disable FLATTER, 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,7,"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 nonzero vectors if B is omitted. The precise behavior depends on flag. 0: returns at most 2m vectors (unless m omitted), returns [N,M,V] where N is the number of vectors enumerated, M the maximum norm among these, and V lists half the vectors (the other half is given by -V). 1: ignores m and returns the first vector whose norm is less than B. 2: as 0 but uses a more robust, slower implementation"}, {"qfminimize",0,(void*)qfminimize,7,"G","qfminimize(G): given a square symmetric matrix G with rational coefficients and non-zero determinant, of dimension n >= 1, return [H,U,c] such that H = c * U~*G*U for some rational c, and H integral with minimal determinant."}, {"qfnorm",0,(void*)qfnorm,7,"GDG","qfnorm(x,{q}): this function is obsolete, use qfeval."}, {"qforbits",0,(void*)qforbits,7,"GG","qforbits(G,V): return the orbits of V under the action of the group of linear transformation generated by the set G, which must stabilize V."}, {"qfparam",0,(void*)qfparam,7,"GGD0,L,","qfparam(G,sol,{flag=0}): coefficients of binary quadratic forms that parametrize the solutions of the ternary quadratic form G, using the particular solution sol."}, {"qfperfection",0,(void*)qfperfection,7,"G","qfperfection(G): rank of matrix of xx~ for x minimal vectors of a Gram matrix G."}, {"qfrep",0,(void*)qfrep0,7,"GGD0,L,","qfrep(q,B,{flag=0}): vector of (half) the number of vectors of norms from 1 to B for the integral and definite quadratic form q. If flag is 1, count vectors of even norm from 1 to 2B."}, {"qfsign",0,(void*)qfsign,7,"G","qfsign(x): signature of the symmetric matrix x."}, {"qfsolve",0,(void*)qfsolve,7,"G","qfsolve(G): solve over Q the quadratic equation X~ G X = 0, where G is a symmetric matrix."}, {"quadclassunit",0,(void*)quadclassunit0,5,"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,5,"G","quaddisc(x): discriminant of the quadratic field Q(sqrt(x))."}, {"quadgen",0,(void*)quadgen0,5,"GDn","quadgen(D,{v = 'w}): standard generator g of quadratic order of discriminant D. If v is given, the variable name is used to display g, else 'w' is used."}, {"quadhilbert",0,(void*)quadhilbert,5,"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,5,"GDn","quadpoly(D,{v='x}): quadratic polynomial corresponding to the discriminant D, in variable v."}, {"quadray",0,(void*)quadray,5,"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,5,"Gp","quadregulator(D): regulator of the real quadratic field of discriminant D."}, {"quadunit",0,(void*)quadunit0,5,"GDn","quadunit(D,{v = 'w}): fundamental unit u of the quadratic order of discriminant D where D must be positive. If v is given, the variable name is used to display u, else 'w' is used."}, {"quadunitindex",0,(void*)quadunitindex,5,"GG","quadunitindex(D,f): given a fundamental discriminant D, returns the index of the unit group of the order of conductor f."}, {"quadunitnorm",0,(void*)quadunitnorm,5,"lG","quadunitnorm(D): returns the norm of the fundamental unit of the quadratic order of discriminant D."}, {"ramanujantau",0,(void*)ramanujantau,5,"GD12,L,","ramanujantau(n,{ell=12}): compute the value of Ramanujan's tau function at n, assuming the GRH. If ell is 16, 18, 20, 22, or 26, same for the newform of level 1 and corresponding weight. Otherwise, compute the coefficient of the trace form at n. Algorithm in O(n^{1/2+eps})."}, {"random",0,(void*)genrand,3,"DG","random({N=2^31}): random object, depending on the type of N. Integer between 0 and N-1 (t_INT), int mod N (t_INTMOD), element in a finite field (t_FFELT), point on an elliptic curve (ellinit mod p or over a finite field)."}, {"randomprime",0,(void*)randomprime0,5,"DGDG","randomprime({N=2^31},{q}): returns a strong pseudo prime in [2, N-1]. If q is an integer, return a prime = 1 mod q; if q is an intmod, return a prime in the given congruence class."}, {"read",0,(void*)gp_read_file,1,"D\"\",s,","read({filename}): read from the input file filename. If filename is omitted, reread last input file, be it from read() or \\r."}, {"readstr",0,(void*)readstr,1,"D\"\",s,","readstr({filename}): returns the vector of GP strings containing the lines in filename."}, {"readvec",0,(void*)gp_readvec_file,1,"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,3,"G","real(x): real part of x."}, {"removeprimes",0,(void*)removeprimes,5,"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,1,"DG","return({x=0}): return from current subroutine with result x."}, {"rnfalgtobasis",0,(void*)rnfalgtobasis,10,"GG","rnfalgtobasis(rnf,x): relative version of nfalgtobasis, where rnf is a relative numberfield."}, {"rnfbasis",0,(void*)rnfbasis,10,"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,10,"GG","rnfbasistoalg(rnf,x): relative version of nfbasistoalg, where rnf is a relative numberfield."}, {"rnfcharpoly",0,(void*)rnfcharpoly,10,"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*)rnfconductor0,10,"GGD0,L,","rnfconductor(bnf,T,{flag=0}): conductor of the Abelian extension of bnf defined by T. The result is [conductor,bnr,subgroup], where conductor is the conductor itself, bnr the attached bnr structure, and subgroup the HNF defining the norm group (Artin or Takagi group) on the given generators bnr.gen. If flag is 1, return a bnr modulo deg(T), attached to Cl_f / (deg(T)); if flag is 2 only return [f, idealfactor(f[1])]."}, {"rnfdedekind",0,(void*)rnfdedekind,10,"GGDGD0,L,","rnfdedekind(nf,pol,{pr},{flag=0}): relative Dedekind criterion over the number field K, represented by nf, applied to the order Z_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 Z_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,10,"GG","rnfdet(nf,M): given a pseudo-matrix M, compute its determinant."}, {"rnfdisc",0,(void*)rnfdiscf,10,"GG","rnfdisc(nf,T): given a polynomial T with coefficients in nf, gives a 2-component vector [D,d], where D is the relative ideal discriminant, and d is the relative discriminant in nf^*/nf*^2."}, {"rnfeltabstorel",0,(void*)rnfeltabstorel,10,"GG","rnfeltabstorel(rnf,x): transforms the element x from absolute to relative representation."}, {"rnfeltdown",0,(void*)rnfeltdown0,10,"GGD0,L,","rnfeltdown(rnf,x,{flag=0}): expresses x on the base field if possible; returns an error otherwise."}, {"rnfeltnorm",0,(void*)rnfeltnorm,10,"GG","rnfeltnorm(rnf,x): returns the relative norm N_{L/K}(x), as an element of K."}, {"rnfeltreltoabs",0,(void*)rnfeltreltoabs,10,"GG","rnfeltreltoabs(rnf,x): transforms the element x from relative to absolute representation."}, {"rnfelttrace",0,(void*)rnfelttrace,10,"GG","rnfelttrace(rnf,x): returns the relative trace Tr_{L/K}(x), as an element of K."}, {"rnfeltup",0,(void*)rnfeltup0,10,"GGD0,L,","rnfeltup(rnf,x,{flag=0}): expresses x (belonging to the base field) on the relative field. As a t_POLMOD if flag = 0 and as a t_COL on the absolute field integer basis if flag = 1."}, {"rnfequation",0,(void*)rnfequation0,10,"GGD0,L,","rnfequation(nf,pol,{flag=0}): given a pol with coefficients in nf, gives an absolute equation z of the number field defined by pol. flag is optional, and can be 0: default, or nonzero, gives [z,al,k], where z defines the absolute equation L/Q as in the default behavior, al expresses as an element of L a root of the polynomial defining the base field nf, and k is a small integer such that t = b + k al is a root of z, for b a root of pol."}, {"rnfhnfbasis",0,(void*)rnfhnfbasis,10,"GG","rnfhnfbasis(bnf,M): given a bnf attached to a number field K and a projective Z_K module M given by a pseudo-matrix, returns either a true HNF basis of M if one exists, or zero otherwise. If M is a polynomial with coefficients in K, replace it by the pseudo-matrix returned by rnfpseudobasis."}, {"rnfidealabstorel",0,(void*)rnfidealabstorel,10,"GG","rnfidealabstorel(rnf,x): transforms the ideal x from absolute to relative representation."}, {"rnfidealdown",0,(void*)rnfidealdown,10,"GG","rnfidealdown(rnf,x): finds the intersection of the ideal x with the base field."}, {"rnfidealfactor",0,(void*)rnfidealfactor,10,"GG","rnfidealfactor(rnf,x): factor the ideal x into prime ideals in the number field nfinit(rnf)."}, {"rnfidealhnf",0,(void*)rnfidealhnf,10,"GG","rnfidealhnf(rnf,x): relative version of idealhnf, where rnf is a relative numberfield."}, {"rnfidealmul",0,(void*)rnfidealmul,10,"GGG","rnfidealmul(rnf,x,y): relative version of idealmul, where rnf is a relative numberfield."}, {"rnfidealnormabs",0,(void*)rnfidealnormabs,10,"GG","rnfidealnormabs(rnf,x): absolute norm of the ideal x."}, {"rnfidealnormrel",0,(void*)rnfidealnormrel,10,"GG","rnfidealnormrel(rnf,x): relative norm of the ideal x."}, {"rnfidealprimedec",0,(void*)rnfidealprimedec,10,"GG","rnfidealprimedec(rnf,pr): return prime ideal decomposition of the maximal ideal pr of K in L/K; pr is also allowed to be a prime number p, in which case return a pair of vectors [SK,SL], where SK contains the primes of K above p and SL[i] is the vector of primes of L above SK[i]."}, {"rnfidealreltoabs",0,(void*)rnfidealreltoabs0,10,"GGD0,L,","rnfidealreltoabs(rnf,x,{flag=0}): transforms the ideal x from relative to absolute representation. As a vector of t_POLMODs if flag = 0 and as an ideal in HNF in the absolute field if flag = 1."}, {"rnfidealtwoelt",0,(void*)rnfidealtwoelement,10,"GG","rnfidealtwoelt(rnf,x): relative version of idealtwoelt, where rnf is a relative numberfield."}, {"rnfidealup",0,(void*)rnfidealup0,10,"GGD0,L,","rnfidealup(rnf,x,{flag=0}): lifts the ideal x (of the base field) to the relative field. As a vector of t_POLMODs if flag = 0 and as an ideal in HNF in the absolute field if flag = 1."}, {"rnfinit",0,(void*)rnfinit0,10,"GGD0,L,","rnfinit(nf,T,{flag=0}): T being an irreducible polynomial defined over the number field nf, initializes a vector of data necessary for working in relative number fields (rnf functions). See manual for technical details."}, {"rnfisabelian",0,(void*)rnfisabelian,10,"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,10,"lGG","rnfisfree(bnf,M): given a bnf attached to a number field K and a projective Z_K module M given by a pseudo-matrix, return true (1) if M is free else return false (0)."}, {"rnfislocalcyclo",0,(void*)rnfislocalcyclo,10,"lG","rnfislocalcyclo(rnf): true(1) if the l-extension attached to rnf is locally cyclotomic (locally contained in the Z_l extension of K_v at all places v | l), false(0) if not."}, {"rnfisnorm",0,(void*)rnfisnorm,10,"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, you may 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 4log(disc(M))^2, where M is the normal closure of L/K."}, {"rnfisnorminit",0,(void*)rnfisnorminit,10,"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,10,"GDGp","rnfkummer(bnr,{subgp}): this function is deprecated. Use bnrclassfield."}, {"rnflllgram",0,(void*)rnflllgram,10,"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,10,"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,10,"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,10,"GGD0,L,","rnfpolredabs(nf,pol,{flag=0}): given an irreducible pol with coefficients in nf, finds a canonical relative polynomial defining the same field. Binary digits of flag mean: 1: return also the element whose characteristic polynomial is the given polynomial, 2: return an absolute polynomial, 16: partial reduction."}, {"rnfpolredbest",0,(void*)rnfpolredbest,10,"GGD0,L,","rnfpolredbest(nf,pol,{flag=0}): given a pol with coefficients in nf, finds a relative polynomial P defining the same field, hopefully simpler than pol; flag can be 0: default, 1: return [P,a], where a is a root of pol 2: return an absolute polynomial Pabs, 3: return [Pabs, a,b], where a is a root of nf.pol and b is a root of pol."}, {"rnfpseudobasis",0,(void*)rnfpseudobasis,10,"GG","rnfpseudobasis(nf,T): given an irreducible polynomial T with coefficients in nf, returns [A,J,D,d] where [A,J] is a pseudo basis of the maximal order of the extension, D is the relative ideal discriminant, and d is the relative discriminant in nf^*/nf*^2."}, {"rnfsteinitz",0,(void*)rnfsteinitz,10,"GG","rnfsteinitz(nf,M): given a nf attached to a number field K and a projective module M given by a pseudo-matrix, returns [A,I,D,d] where (A,I) is a pseudo basis for M where all the ideals except perhaps the last are trivial. If M is a polynomial with coefficients in K, replace it by the pseudo-matrix returned by rnfpseudobasis."}, {"rootsof1",0,(void*)grootsof1,8,"Lp","rootsof1(N): column vector of complex N-th roots of 1."}, {"round",0,(void*)round0,3,"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,1,"GGD0,L,","select(f,A,{flag=0}): selects elements of A according to the selection function f. If flag is 1, return the indices of those elements (indirect selection)."}, {"self",0,(void*)pari_self,1,"m","self(): return the calling function or closure. Useful for defining anonymous recursive functions."}, {"seralgdep",0,(void*)seralgdep,6,"GLL","seralgdep(s,p,r): find a linear relation between powers (1,s, ..., s^p) of the series s, with polynomial coefficients of degree <= r."}, {"serchop",0,(void*)serchop,3,"GD0,L,","serchop(s,{n=0}): remove all terms of degree strictly less than n in series s."}, {"serconvol",0,(void*)convol,6,"GG","serconvol(x,y): convolution (or Hadamard product) of two power series."}, {"serdiffdep",0,(void*)serdiffdep,6,"GLL","serdiffdep(s,p,r): find an inhomogenous linear differential equation satisfied by the series s, with polynomial coefficients of degree <= r. The result is a pair [E,P] such that E(d)(S)=P where E(d) is interpreted as a differential polynomial, or 0 in case no relation is found."}, {"serlaplace",0,(void*)laplace,6,"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))."}, {"serprec",0,(void*)gpserprec,3,"Gn","serprec(x,v): return the absolute precision x with respect to power series in the variable v."}, {"serreverse",0,(void*)serreverse,6,"G","serreverse(s): reversion of the power series s."}, {"setbinop",0,(void*)setbinop,7,"GGDG","setbinop(f,X,{Y}): the set {f(x,y), x in X, y in Y}. If Y is omitted, assume that X = Y and that f is symmetric."}, {"setdebug",0,(void*)setdebug,1,"DsD-1,L,","setdebug({D},{n}): sets debug level for domain D to n (n must be between 0 and 20). If n is omitted, returns the current level for domain D. if D is omitted, returns a two-column matrix which lists the available domains with their levels."}, {"setdelta",0,(void*)setdelta,7,"GG","setdelta(x,y): symmetric difference of the sets x and y."}, {"setintersect",0,(void*)setintersect,7,"GG","setintersect(x,y): intersection of the sets x and y."}, {"setisset",0,(void*)setisset,7,"lG","setisset(x): true(1) if x is a set (row vector with strictly increasing entries), false(0) if not."}, {"setminus",0,(void*)setminus,7,"GG","setminus(x,y): set of elements of x not belonging to y."}, {"setrand",0,(void*)setrand,1,"vG","setrand(n): reset the seed of the random number generator to n."}, {"setsearch",0,(void*)setsearch,7,"lGGD0,L,","setsearch(S,x,{flag=0}): determines whether x belongs to the set (or sorted list) S. If flag is 0 or omitted, returns 0 if it does not, otherwise returns the index j such that x==S[j]. If flag is nonzero, return 0 if x belongs to S, otherwise the index j where it should be inserted."}, {"setunion",0,(void*)setunion,7,"GG","setunion(x,y): union of the sets x and y."}, {"shift",0,(void*)gshift,2,"GL","shift(x,n): shift x left n bits if n>=0, right -n bits if n<0."}, {"shiftmul",0,(void*)gmul2n,2,"GL","shiftmul(x,n): multiply x by 2^n (n>=0 or n<0)."}, {"sigma",0,(void*)sumdivk,5,"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,2,"iG","sign(x): sign of x, of type integer, real or fraction."}, {"simplify",0,(void*)simplify,3,"G","simplify(x): simplify the object x as much as possible."}, {"sin",0,(void*)gsin,8,"Gp","sin(x): sine of x."}, {"sinc",0,(void*)gsinc,8,"Gp","sinc(x): sinc function of x."}, {"sinh",0,(void*)gsinh,8,"Gp","sinh(x): hyperbolic sine of x."}, {"sizebyte",0,(void*)gsizebyte,3,"lG","sizebyte(x): number of bytes occupied by the complete tree of the object x."}, {"sizedigit",0,(void*)sizedigit,3,"lG","sizedigit(x): rough upper bound for the number of decimal digits of (the components of) x. DEPRECATED."}, {"snfrank",0,(void*)snfrank,7,"lGDG","snfrank(D,{q=0}): assuming that D is a Smith normal form (i.e. vector of elementary divisors) for some module and q a power of an irreducible element or 0 (default if omitted), returns the rank of D/qD."}, {"solve",0,(void*)zbrent0,9,"V=GGEp","solve(X=a,b,expr): real root of expression expr (X between a and b), where either a or b is infinite or expr(a)*expr(b)<=0."}, {"solvestep",0,(void*)solvestep0,9,"V=GGGED0,L,p","solvestep(X=a,b,step,expr,{flag=0}): find zeros of a function in the real interval [a,b] by naive interval splitting."}, {"sqr",0,(void*)gsqr,8,"G","sqr(x): square of x. NOT identical to x*x."}, {"sqrt",0,(void*)gsqrt,8,"Gp","sqrt(x): square root of x."}, {"sqrtint",0,(void*)sqrtint0,5,"GD&","sqrtint(x,{&r}): integer square root y of x, where x is a nonnegative real number. If r is present, set it to the remainder x - y^2."}, {"sqrtn",0,(void*)gsqrtn,8,"GGD&p","sqrtn(x,n,{&z}): nth-root of x, n must be integer. If present, z is set to a suitable root of unity to recover all solutions. If it was not possible, z is set to zero."}, {"sqrtnint",0,(void*)sqrtnint,5,"GL","sqrtnint(x,n): integer n-th root of x, where x is nonnegative real number."}, {"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)."}, {"strchr",0,(void*)pari_strchr,1,"G","strchr(x): converts integer or vector of integers x to a string, translating each integer into a character using ASCII encoding."}, {"strexpand",0,(void*)strexpand,1,"s*","strexpand({x}*): concatenates its (string) arguments into a single string, performing tilde expansion."}, {"strjoin",0,(void*)strjoin,1,"GDG","strjoin(v,{p = \"\"}): joins the strings in vector v, separating them with delimiter p."}, {"strprintf",0,(void*)strprintf,1,"ss*","strprintf(fmt,{x}*): returns a string built from the remaining arguments according to the format fmt."}, {"strsplit",0,(void*)strsplit,1,"GDG","strsplit(s,{p = \"\"}): splits the string s into a vector of strings, with p acting as a delimiter between successive fields; if p is empty or omitted, split into characters."}, {"strtex",0,(void*)strtex,1,"s*","strtex({x}*): translates its (string) arguments to TeX format and returns the resulting string."}, {"strtime",0,(void*)strtime,1,"L","strtime(t): return a string describing the time t in milliseconds, in the format used by the GP timer."}, {"subcyclohminus",0,(void*)subcyclohminus,10,"GDG","subcyclohminus(fH,{p=0}): Let F be the abelian number field contained in Q(zeta_f) corresponding to the subgroup H of (Z/fZ)^*. Let h be the relative class number h^-(F) and Q the Hasse unit index in {1,2}. If Q could be computed, returns [h, Q]; else returns [2h/Q, 0]."}, {"subcycloiwasawa",0,(void*)subcycloiwasawa,10,"GGD0,L,","subcycloiwasawa(fH,p,{n=0}): Let F be the abelian number field contained in Q(zeta_f) corresponding to the subgroup H of (Z/fZ)^*. Returns the minus part of Iwasawa polynomials attached to the cyclotomic Z_p extension of F."}, {"subcyclopclgp",0,(void*)subcyclopclgp,10,"GGD0,L,","subcyclopclgp(fH,p,{flag=0}): Let F be the abelian number field contained in Q(zeta_f) corresponding to the subgroup H of (Z/fZ)^*. Returns the minus part of Iwasawa polynomials attached to the ideal class group of F."}, {"subgrouplist",0,(void*)subgrouplist0,10,"GDGD0,L,","subgrouplist(cyc,{bound},{flag=0}): cyc being any object which has a '.cyc' method giving the cyclic components for 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 'cyc' is a bnr struture output by bnrinit, gives only the subgroups for which the modulus is the conductor."}, {"subst",0,(void*)gsubst,6,"GnG","subst(x,y,z): in expression x, replace the variable y by the expression z."}, {"substpol",0,(void*)gsubstpol,6,"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,6,"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,5,"GG","sumdedekind(h,k): Dedekind sum attached to h,k."}, {"sumdigits",0,(void*)sumdigits0,5,"GDG","sumdigits(n,{B=10}): sum of digits in the integer n, when written in base B."}, {"sumdiv",0,(void*)sumdivexpr,9,"GVE","sumdiv(n,X,expr): sum of expression expr, X running over the divisors of n."}, {"sumdivmult",0,(void*)sumdivmultexpr0,9,"GVE","sumdivmult(n,d,expr): sum of multiplicative function expr, d running over the divisors of n."}, {"sumeulerrat",0,(void*)sumeulerrat,9,"GDGD2,L,p","sumeulerrat(F,{s=1},{a=2}): sum from primes p = a to infinity of F(p^s), where F is a rational function."}, {"sumformal",0,(void*)sumformal,6,"GDn","sumformal(f,{v}): formal sum of f with respect to v, or to the main variable of f if v is omitted."}, {"suminf",0,(void*)suminf0,9,"V=GEb","suminf(X=a,expr): naive summation (X goes from a to infinity) of real or complex expression expr."}, {"sumnum",0,(void*)sumnum0,9,"V=GEDGp","sumnum(n=a,f,{tab}): numerical summation of f(n) from n = a to +infinity using Euler-MacLaurin summation. Assume that f corresponds to a series with positive terms and is a C^oo function; a must be an integer, and tab, if given, is the output of sumnuminit."}, {"sumnumap",0,(void*)sumnumap0,9,"V=GEDGp","sumnumap(n=a,f,{tab}): numerical summation of f(n) from n = a to +infinity using Abel-Plana formula. Assume that f is holomorphic in the right half-plane Re(z) > a; a must be an integer, and tab, if given, is the output of sumnumapinit."}, {"sumnumapinit",0,(void*)sumnumapinit,9,"DGp","sumnumapinit({asymp}): initialize tables for Abel-Plana summation of a series."}, {"sumnuminit",0,(void*)sumnuminit,9,"DGp","sumnuminit({asymp}): initialize tables for Euler-MacLaurin delta summation of a series with positive terms."}, {"sumnumlagrange",0,(void*)sumnumlagrange0,9,"V=GEDGp","sumnumlagrange(n=a,f,{tab}): numerical summation of f(n) from n = a to +infinity using Lagrange summation. a must be an integer, and tab, if given, is the output of sumnumlagrangeinit."}, {"sumnumlagrangeinit",0,(void*)sumnumlagrangeinit,9,"DGDGp","sumnumlagrangeinit({asymp},{c1}): initialize tables for Lagrange summation of a series."}, {"sumnummonien",0,(void*)sumnummonien0,9,"V=GEDGp","sumnummonien(n=a,f,{tab}): numerical summation from n = a to +infinity using Monien summation."}, {"sumnummonieninit",0,(void*)sumnummonieninit,9,"DGDGDGp","sumnummonieninit({asymp},{w},{n0 = 1}): initialize tables for Monien summation of a series with positive terms."}, {"sumnumrat",0,(void*)sumnumrat,9,"GGp","sumnumrat(F,a): sum from n = a to infinity of F(n), where F is a rational function of degree less than or equal to -2."}, {"sumnumsidi",0,(void*)sumnumsidi0,9,"V=GED1,L,p","sumnumsidi(n=a,f,{safe=1}): numerical summation of f(n) from n = a to +infinity using Sidi summation; a must be an integer. If safe is set to 0, the function is faster but much less robust."}, {"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."}, {"system",0,(void*)gpsystem,1,"ls","system(str): str being a string, execute the system command str."}, {"tan",0,(void*)gtan,8,"Gp","tan(x): tangent of x."}, {"tanh",0,(void*)gtanh,8,"Gp","tanh(x): hyperbolic tangent of x."}, {"taylor",0,(void*)tayl,6,"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*)teichmuller,8,"GDG","teichmuller(x,{tab}): Teichmuller character of p-adic number x. If x = [p,n], return the lifts of all teichmuller(i + O(p^n)) for i = 1, ..., p-1. Such a vector can be fed back to teichmuller, as the optional argument tab, to speed up later computations."}, {"theta",0,(void*)theta,8,"GGp","theta(q,z): Jacobi sine theta-function."}, {"thetanullk",0,(void*)thetanullk,8,"GLp","thetanullk(q,k): k-th derivative at z=0 of theta(q,z)."}, {"thue",0,(void*)thue,6,"GGDG","thue(tnf,a,{sol}): solve the equation P(x,y)=a, where tnf was created with thueinit(P), and sol, if present, contains the solutions of Norm(x)=a modulo units in the number field defined by P. If tnf was computed without assuming GRH (flag 1 in thueinit), the result is unconditional. If tnf is a polynomial, compute thue(thueinit(P,0), a)."}, {"thueinit",0,(void*)thueinit,6,"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 nonzero, certify the result unconditionally. Otherwise, assume GRH (much faster of course)."}, {"trace",0,(void*)gtrace,7,"G","trace(x): trace of x."}, {"trap",0,(void*)trap0,1,"DrDEDE","trap({e},{rec},seq): this function is obsolete, use \"iferr\". Try to execute seq, trapping runtime error e (all of them if e omitted); sequence rec is executed if the error occurs and is the result of the command."}, {"truncate",0,(void*)trunc0,3,"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,1,"G","type(x): return the type of the GEN x."}, {"unexport",0,NULL,1,NULL,"unexport(x,...,z): remove x,...,z from the list of variables exported to the parallel world."}, {"unexportall",0,(void*)unexportall,1,"v","unexportall(): empty the list of variables exported to the parallel world."}, {"uninline",0,NULL,1,NULL,"uninline(): forget all inline variables. DEPRECATED, use export."}, {"until",0,(void*)untilpari,1,"vEI","until(a,seq): evaluate the expression sequence seq until a is nonzero."}, {"valuation",0,(void*)gpvaluation,3,"GDG","valuation(x,{p}): valuation of x with respect to p."}, {"varhigher",0,(void*)varhigher,3,"sDn","varhigher(name,{v}): return a variable 'name' whose priority is higher than the priority of v (of all existing variables if v is omitted)."}, {"variable",0,(void*)gpolvar,3,"DG","variable({x}): main variable of object x. Gives p for p-adic x, 0 if no variable can be attached to x. Returns the list of user variables if x is omitted."}, {"variables",0,(void*)variables_vec,3,"DG","variables({x}): all variables occurring in object x, sorted by decreasing priority. Returns the list of user variables if x is omitted."}, {"varlower",0,(void*)varlower,3,"sDn","varlower(name,{v}): return a variable 'name' whose priority is lower than the priority of v (of all existing variables if v is omitted."}, {"vecextract",0,(void*)extract0,7,"GGDG","vecextract(x,y,{z}): extraction of the components of the matrix or vector x according to y and z. If z is omitted, y represents columns, otherwise y corresponds to rows and z to columns. y and z can be vectors (of indices), strings (indicating ranges as in \"1..10\") or masks (integers whose binary representation indicates the indices to extract, from left to right 1, 2, 4, 8, etc.)."}, {"vecmax",0,(void*)vecmax0,2,"GD&","vecmax(x,{&v}): largest entry in the vector/matrix x. If v is present, set it to the index of a largest entry (indirect max)."}, {"vecmin",0,(void*)vecmin0,2,"GD&","vecmin(x,{&v}): smallest entry in the vector/matrix x. If v is present, set it to the index of a smallest entry (indirect min)."}, {"vecprod",0,(void*)vecprod,7,"G","vecprod(v): return the product of the components of the vector v."}, {"vecsearch",0,(void*)vecsearch,7,"lGGDG","vecsearch(v,x,{cmpf}): determines whether x belongs to the sorted vector v. If the comparison function cmpf is explicitly given, assume that v was sorted according to vecsort(, cmpf)."}, {"vecsort",0,(void*)vecsort0,7,"GDGD0,L,","vecsort(x,{cmpf},{flag=0}): sorts the vector x in ascending order, according to the comparison function cmpf, if not omitted. Binary digits of flag (if present) mean: 1: indirect sorting, return the permutation instead of the permuted vector, 4: use descending instead of ascending order, 8: remove duplicate entries."}, {"vecsum",0,(void*)vecsum,7,"G","vecsum(v): return the sum of the components of the vector v."}, {"vector",0,(void*)vecteur,7,"GDVDE","vector(n,{X},{expr=0}): row vector with n components of expression expr (X ranges from 1 to n). By default, fills with 0s."}, {"vectorsmall",0,(void*)vecteursmall,7,"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, fills with 0s."}, {"vectorv",0,(void*)vvecteur,7,"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,1,"","version(): returns the PARI version as [major,minor,patch] or [major,minor,patch,GITversion]."}, {"warning",0,(void*)warning0,1,"vs*","warning({str}*): display warning message str."}, {"weber",0,(void*)weber0,8,"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)."}, {"while",0,(void*)whilepari,1,"vEI","while(a,seq): while a is nonzero evaluate the expression sequence seq. Otherwise 0."}, {"write",0,(void*)write0,1,"vss*","write(filename,{str}*): appends the remaining arguments (same output as print) to filename."}, {"write1",0,(void*)write1,1,"vss*","write1(filename,{str}*): appends the remaining arguments (same output as print1) to filename."}, {"writebin",0,(void*)gpwritebin,1,"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,1,"vss*","writetex(filename,{str}*): appends the remaining arguments (same format as print) to filename, in TeX format."}, {"zeta",0,(void*)gzeta,8,"Gp","zeta(s): Riemann zeta function at s with s a complex or a p-adic number."}, {"zetahurwitz",0,(void*)zetahurwitz,8,"GGD0,L,b","zetahurwitz(s,x,{der=0}): Hurwitz zeta function at s, x, with s not 1 and x not a negative or zero integer. s can be a scalar, polynomial, rational function, or power series. If der>0, compute the der'th derivative with respect to s."}, {"zetamult",0,(void*)zetamult_interpolate,8,"GDGp","zetamult(s,{t=0}): multiple zeta value at integral s = [s1,...,sk]; more generally, return Yamamoto's t-MZV interpolation (star value for t = 1)."}, {"zetamultall",0,(void*)zetamultall,8,"LD0,L,p","zetamultall(k,{flag=0}): list of all multiple zeta values for weight up to k. Binary digits of flag mean: 0 = zetastar values if set, 1 = values up to duality if set, 2 = values of weight k if set (else all values up to weight k), 3 = return the 2-component vector [Z, M], where M is the vector of the corresponding indices m, i.e., such that zetamult(M[i]) = Z[i]."}, {"zetamultconvert",0,(void*)zetamultconvert,8,"GD1,L,","zetamultconvert(a,{flag=1}): a being either an evec, avec, or index m, converts into evec (flag=0), avec (flag=1), or index m (flag=2)."}, {"zetamultdual",0,(void*)zetamultdual,8,"G","zetamultdual(s): s being either an evec, avec, or index m, return the dual sequence in avec format."}, {"znchar",0,(void*)znchar,5,"G","znchar(D): given a datum D describing a group G = (Z/NZ)^* and a Dirichlet character chi, return the pair [G,chi]."}, {"zncharconductor",0,(void*)zncharconductor,5,"GG","zncharconductor(G,chi): let G be znstar(q,1) and chi be a Dirichlet character on (Z/qZ)*. Return the conductor of chi."}, {"znchardecompose",0,(void*)znchardecompose,5,"GGG","znchardecompose(G,chi,Q): given a znstar G = (Z/NZ)^* and a Dirichlet character chi, return the product of local characters chi_p for p | (N,Q)."}, {"znchargauss",0,(void*)znchargauss,5,"GGDGb","znchargauss(G,chi,{a=1}): given a Dirichlet character chi on G = (Z/NZ)^*, return the complex Gauss sum g(chi,a)."}, {"zncharinduce",0,(void*)zncharinduce,5,"GGG","zncharinduce(G,chi,N): let G be znstar(q,1), let chi be a Dirichlet character mod q and let N be a multiple of q. Return the character modulo N extending chi."}, {"zncharisodd",0,(void*)zncharisodd,5,"lGG","zncharisodd(G,chi): let G be znstar(N,1), let chi be a Dirichlet character mod N, return 1 if and only if chi(-1) = -1 and 0 otherwise."}, {"znchartokronecker",0,(void*)znchartokronecker,5,"GGD0,L,","znchartokronecker(G,chi,{flag=0}): let G be znstar(N,1), let chi be a Dirichlet character mod N, return the discriminant D if chi is real equal to the Kronecker symbol (D/.) and 0 otherwise. If flag is set, return the fundamental discriminant attached to the corresponding primitive character."}, {"znchartoprimitive",0,(void*)znchartoprimitive,5,"GG","znchartoprimitive(G,chi): let G be znstar(q,1) and chi be a Dirichlet character on (Z/qZ)* of conductor q0. Return [G0,chi0], where chi0 is the primitive character attached to chi and G0 is znstar(q0)."}, {"znconreychar",0,(void*)znconreychar,5,"GG","znconreychar(G,m): Dirichlet character attached to m in (Z/qZ)* in Conrey's notation, where G is znstar(q,1)."}, {"znconreyconductor",0,(void*)znconreyconductor,5,"GGD&","znconreyconductor(G,chi,{&chi0}): let G be znstar(q,1) and chi be a Dirichlet character on (Z/qZ)* given by its Conrey logarithm. Return the conductor of chi, and set chi0 to (the Conrey logarithm of) the attached primitive character. If chi0 != chi, return the conductor and its factorization."}, {"znconreyexp",0,(void*)znconreyexp,5,"GG","znconreyexp(G,chi): Conrey exponential attached to G = znstar(q, 1). Returns the element m in (Z/qZ)^* attached to the character chi on G: znconreylog(G, m) = chi."}, {"znconreylog",0,(void*)znconreylog,5,"GG","znconreylog(G,m): Conrey logarithm attached to m in (Z/qZ)*, where G is znstar(q,1)."}, {"zncoppersmith",0,(void*)zncoppersmith,5,"GGGDG","zncoppersmith(P,N,X,{B=N}): finds all integers x with |x| <= X such that gcd(N, P(x)) >= B. The parameter X should be smaller than exp((log B)^2 / (deg(P) log N)) and the leading coefficient of P should be coprime to N."}, {"znlog",0,(void*)znlog0,5,"GGDG","znlog(x,g,{o}): return the discrete logarithm of x in (Z/nZ)* in base g. If present, o represents the multiplicative order of g. Return [] if no solution exist."}, {"znorder",0,(void*)znorder,5,"GDG","znorder(x,{o}): order of the integermod x in (Z/nZ)*. Optional o represents a multiple of the order of the element."}, {"znprimroot",0,(void*)znprimroot,5,"G","znprimroot(n): returns a primitive root of n when it exists."}, {"znstar",0,(void*)znstar0,5,"GD0,L,","znstar(n,{flag=0}): 3-component vector v = [no,cyc,gen], giving the structure of the abelian group (Z/nZ)^*; no is the order (i.e. eulerphi(n)), cyc is a vector of cyclic components, and gen is a vector giving the corresponding generators."}, {"znsubgroupgenerators",0,(void*)znsubgroupgenerators,5,"GD0,L,","znsubgroupgenerators(H,{flag=0}): finds generators of the subgroup H of (Z/fZ)^*; H is given by a vector of length f of 1/0 values: the a-th component is 1 if and only if a belongs to H."}, {NULL,0,NULL,0,NULL,NULL} /* sentinel */ }; pari-2.17.2/src/language/members.c0000644000175000017500000003211014760137411015335 0ustar billbill/* Copyright (C) 2000-2003 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" /********************************************************************/ /** **/ /** MEMBER FUNCTIONS **/ /** **/ /********************************************************************/ INLINE int is_ell5(GEN x) { long lx; if (typ(x) != t_VEC) return 0; lx = lg(x); return lx == 17 || (lx == 6 && !is_vec_t(typ(gel(x,2)))); } INLINE int is_ell(GEN x) { long lx = lg(x); return (typ(x) == t_VEC && lx == 17); } static void member_err(const char *s, GEN y) { pari_err_TYPE(s,y); } GEN member_e(GEN x) { GEN y = get_prid(x); if (!y) member_err("e",x); return gel(y,3); } GEN member_f(GEN x) { GEN y = get_prid(x); if (!y) { if (typ(x) == t_FFELT) return utoipos(FF_f(x)); member_err("f",x); } return gel(y,4); } GEN member_p(GEN x) { long t; GEN y = get_nf(x,&t); if (y) return nf_get_ramified_primes(y); switch(t) { case typ_GAL: return gal_get_p(x); case typ_ELL: switch(ell_get_type(x)) { case t_ELL_Fp: case t_ELL_Fq: return ellff_get_p(x); case t_ELL_Qp: return ellQp_get_p(x); default: member_err("p",x); } case typ_MODPR: x = get_prid(x); case typ_PRID: return pr_get_p(x); case typ_RNF: return rnf_get_ramified_primes(x); } switch(typ(x)) { case t_PADIC: return gel(x,2); case t_FFELT: return FF_p_i(x); } member_err("p",x); return NULL; } GEN member_bid(GEN x) { long t; (void)get_nf(x,&t); switch(t) { case typ_BNR: return bnr_get_bid(x); case typ_BIDZ: case typ_BID: return x; } member_err("bid",x); return NULL; } GEN member_bnf(GEN x) { long t; GEN y = get_bnf(x,&t); if (!y) { if (t == typ_ELL && ell_get_type(x) == t_ELL_NF) { y = ellnf_get_bnf(x); if (y) return y; } member_err("bnf",x); } return y; } GEN member_nf(GEN x) { long t; GEN y = get_nf(x,&t); if (!y) { if (t == typ_RNF) return gel(x,10); if (t == typ_ELL && ell_get_type(x) == t_ELL_NF) return ellnf_get_nf(x); member_err("nf",x); } return y; } /* integral basis */ GEN member_zk(GEN x) { long t; GEN y = get_nf(x,&t); if (!y) { switch(t) { case typ_Q: y = cgetg(3,t_VEC); gel(y,1) = gen_1; gel(y,2) = pol_x(varn(gel(x,1))); return y; case typ_RNF: return gel(x,7); } member_err("zk",x); } return nf_get_zk(y); } GEN member_disc(GEN x) /* discriminant */ { long t; GEN y = get_nf(x,&t); if (!y) { switch(t) { case typ_Q : return quad_disc(x); case typ_QFB: return qfb_disc(x); case typ_ELL: return ell_get_disc(x); case typ_RNF: return rnf_get_disc(x); } member_err("disc",x); } return nf_get_disc(y); } GEN member_pol(GEN x) /* polynomial */ { long t; GEN y = get_nf(x,&t); if (!y) { switch(t) { case typ_POL: return x; case typ_Q : return deg1pol_shallow(gel(x,3), gel(x,2), varn(gel(x,1))); case typ_GAL: return gal_get_pol(x); case typ_RNF: return rnf_get_pol(x); } if (typ(x)==t_POLMOD) return gel(x,2); if (typ(x)==t_FFELT) return FF_to_FpXQ(x); member_err("pol",x); } return nf_get_pol(y); } GEN member_polabs(GEN x) { long t; (void)get_nf(x,&t); if (t != typ_RNF) member_err("pol",x); return rnf_get_polabs(x); } GEN member_mod(GEN x) /* modulus */ { long t; (void)get_nf(x,&t); switch(t) { case typ_GAL: return gal_get_mod(x); case typ_BNR: return bnr_get_mod(x); case typ_GCHAR: return gchar_get_mod(x); case typ_BIDZ: return bid_get_ideal(x); case typ_BID: return bid_get_mod(x); } 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); case t_VEC: if (checkmf_i(x)) { GEN T = mf_get_field(x), CHI = mf_get_CHI(x), P = mfcharpol(CHI); return (degpol(T) == 1)? P: (degpol(P) > 1? gmodulo(T, P): T); } else if (checkMF_i(x)) return mfcharpol(MF_get_CHI(x)); default: member_err("mod",x); } return gel(x,1); } GEN member_sign(GEN x) /* signature */ { long t; GEN y = get_nf(x,&t); if (!y) member_err("sign",x); return gel(y,2); } GEN member_r1(GEN x) { return gel(member_sign(x), 1); } GEN member_r2(GEN x) { return gel(member_sign(x), 2); } GEN member_normfu(GEN x) /* norm of fundamental unit */ { if (typ(x)!=t_VEC || lg(x)!=6 || typ(gel(x,1))!=t_INT || typ(gel(x,2))!=t_VEC) member_err("normfu",x); return gel(x,5); } GEN member_index(GEN x) { long t; GEN y = get_nf(x,&t); if (!y) { if (t == typ_RNF) return rnf_get_index(x); member_err("index",x); } return nf_get_index(y); } /* x assumed to be output by get_nf: ie a t_VEC with length 11 */ static GEN nfmats(GEN x) { GEN y; if (!x) return NULL; y = gel(x,5); if (typ(y) == t_VEC && lg(y) < 8) return NULL; return y; } GEN member_t2(GEN x) /* T2 matrix */ { long t; GEN y = nfmats(get_nf(x,&t)); if (!y) member_err("t2",x); return gram_matrix(gel(y,2)); } GEN member_diff(GEN x) /* different */ { long t; GEN y = nfmats(get_nf(x,&t)); if (!y) member_err("diff",x); return gel(y,5); } GEN member_codiff(GEN x) /* codifferent */ { long t; GEN T, d, Di, nf = get_nf(x,&t), y = nfmats(nf); if (!y) member_err("codiff",x); T = gel(y,4); Di = ZM_inv(T, &d); if (!d) return matid(lg(Di)-1); return RgM_Rg_div(ZM_hnfmodid(Di, d), d); } GEN member_roots(GEN x) /* roots */ { long t; GEN y = get_nf(x,&t); if (!y) { if (t == typ_GAL) return gal_get_roots(x); if (t == typ_ELL) switch(ell_get_type(x)) { case t_ELL_Qp: return mkcol( ellQp_root(x, ellQp_get_prec(x)) ); case t_ELL_Q: case t_ELL_Rg: return ellR_roots(x, ellR_get_prec(x)); } member_err("roots",x); } return nf_get_roots(y); } /* assume x output by get_bnf: ie a t_VEC with length 10 */ static GEN check_RES(GEN x, const char *s) { GEN y = gel(x,8); if (typ(y) != t_VEC || lg(y) < 4) member_err(s,x); return y; } /* y = get_bnf(x, &t) */ static GEN _member_clgp(GEN x, GEN y, long t) /* class group (3-component row vector) */ { if (!y) { switch(t) { case typ_QUA: return mkvec3(gel(x,1), gel(x,2), gel(x,3)); case typ_BIDZ: case typ_BID: return gel(x,2); } if (typ(x)==t_VEC) switch(lg(x)) { case 3: /* no gen */ case 4: return x; } member_err("clgp",x); } if (t==typ_BNR) return gel(x,5); y = check_RES(y, "clgp"); return gel(y,1); } static GEN _check_clgp(GEN x, GEN y, long t) { GEN c = _member_clgp(x,y,t); checkabgrp(c); return c; } GEN member_clgp(GEN x) { long t; GEN y = get_bnf(x,&t); return _check_clgp(x,y,t); } GEN member_reg(GEN x) /* regulator */ { long t; GEN y = get_bnf(x,&t); if (!y) { if (t == typ_QUA) return gel(x,4); member_err("reg",x); } if (t == typ_BNR) pari_err_IMPL("ray regulator"); y = check_RES(y, "reg"); return gel(y,2); } GEN member_fu(GEN x) /* fundamental units */ { long t; GEN fu, y = get_bnf(x,&t); if (!y) { switch(t) { case typ_Q: x = quad_disc(x); return (signe(x)<0)? cgetg(1,t_VEC): quadunit(x); } member_err("fu",x); } if (t == typ_BNR) pari_err_IMPL("ray units"); fu = bnf_get_fu_nocheck(y); if (typ(fu) == t_MAT) { /*missing units*/ GEN SUnits = bnf_get_sunits(y); if (!SUnits) return gen_0; fu = bnf_build_units(y); fu = vecslice(fu, 2, lg(fu)-1); /* remove torsion unit */ } return matbasistoalg(y, fu); } /* torsion units. return [w,e] where w is the number of roots of 1, and e a * polmod (or integer) generator */ GEN member_tu(GEN x) { long t; GEN bnf = get_bnf(x,&t), res = cgetg(3,t_VEC); if (!bnf) { GEN y; if (t != typ_Q) member_err("tu",x); y = quad_disc(x); if (signe(y) > 0 || abscmpiu(y,4) > 0) return mkvec2(gen_m1, gen_2); gel(res,1) = utoipos((itos(y) == -4)? 4: 6); gel(res,2) = gcopy(x); } else { GEN z = bnf_get_tuU(bnf); if (t == typ_BNR) pari_err_IMPL("ray torsion units"); gel(res,1) = utoipos( bnf_get_tuN(bnf) ); gel(res,2) = typ(z)==t_INT? gen_m1: basistoalg(bnf,z); } return res; } /* 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_BIDZ: case typ_BID: return bid_get_grp(x); case typ_BNR: { GEN bid = bnr_get_bid(x); if (typ(bid) == t_VEC && lg(bid) > 2) return bid_get_grp(bid); } } member_err("zkst",x); return NULL; /* LCOV_EXCL_LINE */ } GEN member_no(GEN x) /* number of elements of a group (of type clgp) */ { pari_sp av = avma; long t; GEN y = get_bnf(x,&t); if (t == typ_ELL) switch(ell_get_type(x)) { case t_ELL_Fp: case t_ELL_Fq: return ellcard(x, NULL); } x = _check_clgp(x,y,t); return gc_const(av, abgrp_get_no(x)); } GEN member_cyc(GEN x) /* cyclic decomposition (SNF) of a group (of type clgp) */ { pari_sp av = avma; long t; GEN y = get_bnf(x,&t); if (t == typ_ELL) switch(ell_get_type(x)) { case t_ELL_Fp: case t_ELL_Fq: return ellgroup(x, NULL); } if (t == typ_GCHAR) return gchar_get_cyc(x); x = _check_clgp(x,y,t); return gc_const(av, abgrp_get_cyc(x)); } /* SNF generators of a group (of type clgp), or generators of a prime * ideal */ GEN member_gen(GEN x) { pari_sp av; long t; GEN y = get_bnf(x,&t); switch(t) { case typ_MODPR: x = get_prid(x); case typ_PRID: return mkvec2(gel(x,1), gel(x,2)); case typ_GAL: return gal_get_gen(x); case typ_ELL: return ellgenerators(x); case typ_NULL: if (typ(x)==t_FFELT) return FF_gen(x); break; } av = avma; x = _check_clgp(x,y,t); if (lg(x)!=4) member_err("gen",x); return gc_const(av, abgrp_get_gen(x)); } GEN member_group(GEN x) { long t; (void)get_nf(x,&t); if (t == typ_GAL) return gal_get_group(x); if (t == typ_ELL) return ellgroup0(x, NULL, 1); member_err("group",x); return NULL; /* LCOV_EXCL_LINE */ } GEN member_orders(GEN x) { long t; (void)get_nf(x,&t); if (t == typ_GAL) return gal_get_orders(x); member_err("orders",x); return NULL; /* LCOV_EXCL_LINE */ } GEN member_a1(GEN x) { if (!is_ell5(x)) member_err("a1",x); return ell_get_a1(x); } GEN member_a2(GEN x) { if (!is_ell5(x)) member_err("a2",x); return ell_get_a2(x); } GEN member_a3(GEN x) { if (!is_ell5(x)) member_err("a3",x); return ell_get_a3(x); } GEN member_a4(GEN x) { if (!is_ell5(x)) member_err("a4",x); return ell_get_a4(x); } GEN member_a6(GEN x) { if (!is_ell5(x)) member_err("a6",x); return ell_get_a6(x); } GEN member_b2(GEN x) { if (!is_ell(x)) member_err("b2",x); return ell_get_b2(x); } GEN member_b4(GEN x) { if (!is_ell(x)) member_err("b4",x); return ell_get_b4(x); } GEN member_b6(GEN x) { if (!is_ell(x)) member_err("b6",x); return ell_get_b6(x); } GEN member_b8(GEN x) { if (!is_ell(x)) member_err("b8",x); return ell_get_b8(x); } GEN member_c4(GEN x) { if (!is_ell(x)) member_err("c4",x); return ell_get_c4(x); } GEN member_c6(GEN x) { if (!is_ell(x)) member_err("c6",x); return ell_get_c6(x); } GEN member_j(GEN x) { if (!is_ell(x)) member_err("j",x); return ell_get_j(x); } static int ell_is_complex(GEN x) { long t = ell_get_type(x); return t == t_ELL_Q || t == t_ELL_Rg; } static long ellnf_get_prec(GEN x) { return nf_get_prec(ellnf_get_nf(x)); } GEN member_omega(GEN x) { if (!is_ell(x)) member_err("omega",x); if (ell_get_type(x)==t_ELL_NF) return ellnf_vecomega(x, ellnf_get_prec(x)); if (!ell_is_complex(x)) pari_err_TYPE("omega [not defined over C]",x); return ellR_omega(x, ellR_get_prec(x)); } GEN member_eta(GEN x) { if (!is_ell(x)) member_err("eta",x); if (ell_get_type(x)==t_ELL_NF) return ellnf_veceta(x, ellnf_get_prec(x)); if (!ell_is_complex(x)) pari_err_TYPE("eta [not defined over C]",x); return ellR_eta(x, ellR_get_prec(x)); } GEN member_area(GEN x) { if (!is_ell(x)) member_err("area",x); if (ell_get_type(x)==t_ELL_NF) return ellnf_vecarea(x, ellnf_get_prec(x)); if (!ell_is_complex(x)) pari_err_TYPE("area [not defined over C]",x); return ellR_area(x, ellR_get_prec(x)); } GEN member_tate(GEN x) { long prec; if (!is_ell(x)) member_err("tate",x); if (ell_get_type(x) != t_ELL_Qp) pari_err_TYPE("tate [not defined over Qp]",x); prec = ellQp_get_prec(x); return ellQp_Tate_uniformization(x, prec); } pari-2.17.2/src/language/hash.c0000644000175000017500000002253714760123736014647 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #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 = numberof(hashprimes); INLINE void setlen(hashtable *h, ulong len) { h->maxnb = (ulong)ceil(len * 0.65); h->len = len; } static int get_prime_index(ulong len) { int i; for (i=0; i < hashprimes_len; i++) if (hashprimes[i] > len) return i; pari_err_OVERFLOW("hash table [too large]"); return -1; /* LCOV_EXCL_LINE */ } /* link hashentry e to hashtable h, setting e->hash / e->next */ INLINE void hash_link2(hashtable *h, hashentry *e, ulong hash) { ulong index; e->hash = hash; index = e->hash % h->len; e->next = h->table[index]; h->table[index] = e; } INLINE void hash_link(hashtable *h, hashentry *e) { hash_link2(h,e,h->hash(e->key));} hashtable * hash_create(ulong minsize, ulong (*hash)(void*), int (*eq)(void*,void*), int use_stack) { int i = get_prime_index(minsize); ulong len = hashprimes[i]; hashtable *h; if (use_stack) { h = (hashtable*)stack_malloc(sizeof(hashtable)); h->table = (hashentry**)stack_calloc(len * sizeof(hashentry*)); h->use_stack = 1; } else { h = (hashtable*)pari_malloc(sizeof(hashtable)); h->table = (hashentry**)pari_calloc(len * sizeof(hashentry*)); h->use_stack = 0; } h->pindex = i; h->nb = 0; h->hash = hash; h->eq = eq; setlen(h, len); return h; } static ulong hash_id(void *x) { return (ulong)x; } static int eq_id(void *x, void *y) { return x == y; } hashtable * hash_create_ulong(ulong s, long stack) { return hash_create(s, &hash_id, &eq_id, stack); } void hash_init(hashtable *h, ulong minsize, ulong (*hash)(void*), int (*eq)(void*,void*), int use_stack) { int i = get_prime_index(minsize); ulong len = hashprimes[i]; if (use_stack) h->table = (hashentry**)stack_calloc(len * sizeof(hashentry*)); else h->table = (hashentry**)pari_calloc(len * sizeof(hashentry*)); h->use_stack = use_stack; h->pindex = i; h->nb = 0; h->hash = hash; h->eq = eq; setlen(h, len); } void hash_init_GEN(hashtable *h, ulong minsize, int (*eq)(GEN,GEN), int use_stack) { hash_init(h, minsize,(ulong (*)(void*)) hash_GEN, (int (*)(void*,void*)) eq, use_stack); } void hash_init_ulong(hashtable *h, ulong minsize, int use_stack) { hash_init(h, minsize,hash_id, eq_id, use_stack); } void hash_insert2(hashtable *h, void *k, void *v, ulong hash) { hashentry *e; ulong index; if (h->use_stack) e = (hashentry*) stack_malloc(sizeof(hashentry)); else e = (hashentry*) pari_malloc(sizeof(hashentry)); if (++(h->nb) > h->maxnb && h->pindex < hashprimes_len-1) { /* double table size */ ulong i, newlen = hashprimes[++(h->pindex)]; hashentry *E, **newtable; if (h->use_stack) newtable = (hashentry**)stack_calloc(newlen*sizeof(hashentry*)); else newtable = (hashentry**)pari_calloc(newlen*sizeof(hashentry*)); for (i = 0; i < h->len; i++) while ( (E = h->table[i]) ) { h->table[i] = E->next; index = E->hash % newlen; E->next = newtable[index]; newtable[index] = E; } if (!h->use_stack) pari_free(h->table); h->table = newtable; setlen(h, newlen); } e->key = k; e->val = v; hash_link2(h, e, hash); } void hash_insert(hashtable *h, void *k, void *v) { hash_insert2(h,k,v,h->hash(k)); } void hash_insert_long(hashtable *h, void *k, long v) { hash_insert2(h,k,(void*)v,h->hash(k)); } /* the key 'k' may correspond to different values in the hash, return * one satisfying the selection callback */ hashentry * hash_select(hashtable *h, void *k, void *E,int(*select)(void *,hashentry *)) { ulong hash = h->hash(k); hashentry *e = h->table[ hash % h->len ]; while (e) { if (hash == e->hash && h->eq(k, e->key) && select(E,e)) return e; e = e->next; } return NULL; } GEN hash_keys(hashtable *h) { long k = 1; ulong i; GEN v = cgetg(h->nb+1, t_VECSMALL); for (i = 0; i < h->len; i++) { hashentry *e = h->table[i]; while (e) { v[k++] = (long)e->key; e = e->next; } } return v; } GEN hash_keys_GEN(hashtable *h) { long k = 1; ulong i; GEN v = cgetg(h->nb+1, t_VEC); for (i = 0; i < h->len; i++) { hashentry *e = h->table[i]; while (e) { gel(v,k++) = (GEN)e->key; e = e->next; } } return v; } GEN hash_values(hashtable *h) { long k = 1; ulong i; GEN v = cgetg(h->nb+1, t_VECSMALL); for (i = 0; i < h->len; i++) { hashentry *e = h->table[i]; while (e) { v[k++] = (long)e->val; e = e->next; } } return v; } /* assume hash = h->hash(k) */ hashentry * hash_search2(hashtable *h, void *k, ulong hash) { hashentry *e = h->table[ hash % h->len ]; while (e) { if (hash == e->hash && h->eq(k, e->key)) return e; e = e->next; } return NULL; /* not found */ } /* returns entry attached to key k or NULL */ hashentry * hash_search(hashtable *h, void *k) { if (h->nb == 0) return NULL; return hash_search2(h, k, h->hash(k)); } int hash_haskey_long(hashtable *h, void *k, long *v) { hashentry * e = hash_search(h, k); if (e) { *v = (long) e->val; return 1; } else return 0; } GEN hash_haskey_GEN(hashtable *h, void *k) { hashentry * e = hash_search(h, k); return e ? (GEN) e->val: NULL; } hashentry * hash_remove_select(hashtable *h, void *k, void *E, int (*select)(void*,hashentry*)) { ulong hash = h->hash(k), index = hash % h->len; hashentry **pE = &(h->table[index]), *e = *pE; while (e) { if (hash == e->hash && h->eq(k, e->key) && select(E,e)) { *pE = e->next; h->nb--; return e; } pE = &(e->next); e = e->next; } return NULL; } hashentry * hash_remove(hashtable *h, void *k) { ulong hash = h->hash(k), index = hash % h->len; hashentry **pE = &(h->table[index]), *e = *pE; while (e) { if (hash == e->hash && h->eq(k, e->key)) { *pE = e->next; h->nb--; return e; } pE = &(e->next); e = e->next; } return NULL; } void hash_destroy(hashtable *h) { ulong i; if (h->use_stack) return; for (i = 0; i < h->len; i++) { hashentry *e = h->table[i]; while (e) { hashentry *f = e; e = e->next; pari_free(f); } } pari_free(h->table); pari_free(h); } static int strequal(void *a, void *b) { return !strcmp((char*)a,(char*)b); } hashtable * hash_create_str(ulong s, long stack) { return hash_create(s, (ulong (*)(void *))&hash_str, strequal, stack); } hashtable * hashstr_import_static(hashentry *e, ulong size) { hashtable *h = hash_create_str(size, 0); for ( ; e->key; e++) { hash_link(h, e); h->nb++; } return h; } void hash_dbg(hashtable *h) { ulong n, Total = 0, Max = 0; hashentry *e, **table = h->table; for (n=0; n < h->len; n++) { ulong m=0; for (e=table[n]; e; e=e->next) m++; Total += m; if (Max < m) Max = m; pari_printf("%4ld:%2ld ",n,m); if (n%9 == 8) pari_putc('\n'); } pari_printf("\nTotal = %ld, Max = %ld\n", Total, Max); } /********************************************************************/ /* */ /* HASH FUNCTIONS */ /* */ /********************************************************************/ INLINE ulong glue(ulong h, ulong a) { return 404936533*h + a; } ulong hash_GEN(GEN x) { ulong h = x[0] & ~CLONEBIT; long tx = typ(x), lx, i; switch(tx) { /* non recursive types */ case t_INT: lx = lgefint(x); h &= TYPBITS; for (i = 1; i < lx; i++) h = glue(h, uel(x,i)); return h; case t_REAL: case t_STR: case t_VECSMALL: lx = lg(x); for (i = 1; i < lx; i++) h = glue(h, uel(x,i)); return h; /* one more special case */ case t_LIST: x = list_data(x); if (!x) return h; /* fall through */ default: if (lontyp[tx] == 2) { h = glue(h, x[1]); i = 2; } else i = 1; lx = lg(x); for (; i < lx; i++) h = glue(h, hash_GEN(gel(x,i))); return h; } } ulong hash_zv(GEN x) { long i, lx = lg(x); ulong h; if (lx == 1) return 0; h = x[1]; for (i = 1; i < lx; i++) h = glue(h, uel(x,i)); return h; } pari-2.17.2/src/language/tree.h0000644000175000017500000000335414676526175014676 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; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ BEGINEXTERN typedef enum {Fseq, Fmatrix,Frange, Fassign, Fmatcoeff, Fmatrixelts,Fmatrixlines, Fmat,Fvec,Fnoarg,Fnorange, Flistarg, Frefarg, Findarg, Fvararg, Fconst,Fsmall, Ftag, Fentry,Fcall,Ffunction,Flambda } Ffunc; typedef struct node_s { Ffunc f; /*node function */ long x; /*node left child */ long y; /*node right child*/ const char *str; /*text start */ size_t len; /*text length */ long flags; /*flags from the copy optimizer*/ } node; typedef enum {CSTstr, CSTquote, CSTint, CSTreal, CSTmember, CSTentry} CSTtype; typedef enum {OPor, OPand, OPid, OPeq, OPne, OPge, OPg, OPle, OPl, OPs, OPp, OPsl, OPsr, OPmod, OPdr, OPeuc, OPd, OPm, OPpow, OPcat, OPss, OPpp, OPse ,OPpe ,OPsle ,OPsre ,OPmode ,OPdre ,OPeuce ,OPde ,OPme, OPpl, OPn, OPnb, OPfact, OPprim, OPderivn, OPtrans, OPrange, OPcompr, OPcomprc, OPhist, OPhisttime, OPlength, OPnboperator} OPerator; extern THREAD node *pari_tree; ENDEXTERN pari-2.17.2/src/kernel/0000755000175000017500000000000014760315601013236 5ustar billbillpari-2.17.2/src/kernel/README0000644000175000017500000000267611636712103014126 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.17.2/src/kernel/gmp/0000755000175000017500000000000014760315601014021 5ustar billbillpari-2.17.2/src/kernel/gmp/gcdext.c0000644000175000017500000001207514567450071015456 0ustar billbill#line 2 "../src/kernel/gmp/gcdext.c" /* Copyright (C) 2000-2003 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*================================== * invmod(a,b,res) *================================== * If a is invertible, return 1, and set res = a^{ -1 } * Otherwise, return 0, and set res = gcd(a,b) */ int invmod(GEN a, GEN b, GEN *res) { if (!signe(b)) { *res=absi(a); return 0; } if (NLIMBS(b) < INVMOD_GMP_LIMIT) return invmod_pari(a,b,res); { /* General case: use gcdext(a+b, b) since mpn_gcdext require S1>=S2 */ pari_sp av = avma; GEN ca, cb, u, d; long l, su, sa = signe(a), lb,lna; mp_size_t lu; GEN na; if (!sa) { set_avma(av); *res = absi(b); return 0; } if (signe(b) < 0) b = negi(b); if (abscmpii(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)) {set_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); set_avma(av); *res=icopy(u); return 1; } } /*================================== * bezout(a,b,pu,pv) *================================== * Return g = gcd(a,b) >= 0, and assign GENs u,v through pointers pu,pv * such that g = u*a + v*b. * Special cases: * a == b == 0 ==> pick u=1, v=0 * a != 0 == b ==> keep v=0 * a == 0 != b ==> keep u=0 * |a| == |b| != 0 ==> keep u=0, set v=+-1 * Assignments through pu,pv will be suppressed when the corresponding * pointer is NULL (but the computations will happen nonetheless). */ GEN bezout(GEN a, GEN b, GEN *pu, GEN *pv) { long s, sa, sb; ulong g; ulong xu,xu1,xv,xv1; /* Lehmer stage recurrence matrix */ s = abscmpii(a,b); if (s < 0) { swap(a,b); pswap(pu,pv); } /* now |a| >= |b| */ sa = signe(a); sb = signe(b); if (!sb) { if (pv) *pv = gen_0; switch(sa) { case 0: if (pu) *pu = gen_0; return gen_0; case 1: if (pu) *pu = gen_1; return icopy(a); case -1: if (pu) *pu = gen_m1; return negi(a); } } if (s == 0) /* |a| == |b| != 0 */ { if (pu) *pu = gen_0; if (sb > 0) { if (pv) *pv = gen_1; return icopy(b); } else { if (pv) *pv = gen_m1; return negi(b); } } /* now |a| > |b| > 0 */ if (lgefint(a) == 3) /* single-word affair */ { g = xxgcduu((ulong)a[2], (ulong)b[2], 0, &xu, &xu1, &xv, &xv1, &s); sa = s > 0 ? sa : -sa; sb = s > 0 ? -sb : sb; if (pu) { if (xu == 0) *pu = gen_0; /* can happen when b divides a */ else if (xu == 1) *pu = sa < 0 ? gen_m1 : gen_1; else if (xu == 2) *pu = sa < 0 ? gen_m2 : gen_2; else { *pu = cgeti(3); (*pu)[1] = evalsigne(sa)|evallgefint(3); (*pu)[2] = xu; } } if (pv) { if (xv == 1) *pv = sb < 0 ? gen_m1 : gen_1; else if (xv == 2) *pv = sb < 0 ? gen_m2 : gen_2; else { *pv = cgeti(3); (*pv)[1] = evalsigne(sb)|evallgefint(3); (*pv)[2] = xv; } } if (g == 1) return gen_1; else if (g == 2) return gen_2; else return utoipos(g); } else { /* general case */ pari_sp av = avma; /*Copy serves two purposes: * 1) mpn_gcdext destroys its input and needs an extra limb * 2) allows us to use icopy instead of gerepile later. * NOTE: we must put u before d else the final icopy could fail. */ GEN ca = icopy_ef(a,lgefint(a)+1); GEN cb = icopy_ef(b,lgefint(b)+1); GEN u = cgeti(lgefint(a)+1), v = NULL; GEN d = cgeti(lgefint(a)+1); long su,l; mp_size_t lu; l = mpn_gcdext(LIMBS(d), LIMBS(u), &lu, LIMBS(ca), NLIMBS(ca), LIMBS(cb), NLIMBS(cb)); if (lu<=0) { if (lu==0) su=0; else {su=-1;lu=-lu;} } else su=1; if (sa<0) su=-su; d[1] = evalsigne(1)|evallgefint(l+2); u[1] = evalsigne(su)|evallgefint(lu+2); if (pv) v=diviiexact(subii(d,mulii(u,a)),b); set_avma(av); if (pu) *pu=icopy(u); if (pv) *pv=icopy(v); return icopy(d); } } pari-2.17.2/src/kernel/gmp/gcd.c0000644000175000017500000000427214567450071014735 0ustar billbill#line 2 "../src/kernel/gmp/gcd.c" /* Copyright (C) 2000-2003 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* 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 (abscmpii(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: "set_avma(av)" gerepile (erasing t) is valid */ av = avma; (void)new_chunk(lgefint(b)+1); /* HACK */ t = remii(a,b); if (!signe(t)) { set_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(abscmpii(a,b)) { case 0: set_avma(av); a=shifti(a,v); return a; case -1: swap(a,b); } if (is_pm1(b)) { set_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); set_avma(av); return shifti(res,v); } } pari-2.17.2/src/kernel/gmp/mp.c0000644000175000017500000010407614676526175014631 0ustar billbill#line 2 "../src/kernel/gmp/mp.c" /* Copyright (C) 2002-2003 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /***********************************************************************/ /** **/ /** GMP KERNEL **/ /** BA2002Sep24 **/ /***********************************************************************/ /* GMP t_INT as just like normal t_INT, just the mantissa is the other way * round * * `How would you like to live in Looking-glass House, Kitty? I * wonder if they'd give you milk in there? Perhaps Looking-glass * milk isn't good to drink--But oh, Kitty! now we come to the * passage. You can just see a little PEEP of the passage in * Looking-glass House, if you leave the door of our drawing-room * wide open: and it's very like our passage as far as you can see, * only you know it may be quite different on beyond. Oh, Kitty! * how nice it would be if we could only get through into Looking- * glass House! I'm sure it's got, oh! such beautiful things in it! * * Through the Looking Glass, Lewis Carrol * * (pityful attempt to beat GN code/comments rate) * */ #include #include "pari.h" #include "paripriv.h" #include "../src/kernel/none/tune-gen.h" /*We need PARI invmod renamed to invmod_pari*/ #define INVMOD_PARI static void *pari_gmp_realloc(void *ptr, size_t old_size, size_t new_size) { (void)old_size; return (void *) pari_realloc(ptr,new_size); } static void pari_gmp_free(void *ptr, size_t old_size){ (void)old_size; pari_free(ptr); } static void *(*old_gmp_malloc)(size_t new_size); static void *(*old_gmp_realloc)(void *ptr, size_t old_size, size_t new_size); static void (*old_gmp_free)(void *ptr, size_t old_size); void pari_kernel_init(void) { mp_get_memory_functions (&old_gmp_malloc, &old_gmp_realloc, &old_gmp_free); mp_set_memory_functions((void *(*)(size_t)) pari_malloc, pari_gmp_realloc, pari_gmp_free); } const char * pari_kernel_version(void) { #ifdef gmp_version return gmp_version; #else return ""; #endif } void pari_kernel_close(void) { void *(*new_gmp_malloc)(size_t new_size); void *(*new_gmp_realloc)(void *ptr, size_t old_size, size_t new_size); void (*new_gmp_free)(void *ptr, size_t old_size); mp_get_memory_functions (&new_gmp_malloc, &new_gmp_realloc, &new_gmp_free); if (new_gmp_malloc==pari_malloc) new_gmp_malloc = old_gmp_malloc; if (new_gmp_realloc==pari_gmp_realloc) new_gmp_realloc = old_gmp_realloc; if (new_gmp_free==pari_gmp_free) new_gmp_free = old_gmp_free; mp_set_memory_functions(new_gmp_malloc, new_gmp_realloc, new_gmp_free); } #define LIMBS(x) ((mp_limb_t *)((x)+2)) #define NLIMBS(x) (lgefint(x)-2) /*This one is for t_REALs to emphasize they are not t_INTs*/ #define RLIMBS(x) ((mp_limb_t *)((x)+2)) #define RNLIMBS(x) (lg(x)-2) INLINE void xmpn_copy(mp_limb_t *x, mp_limb_t *y, long n) { while (--n >= 0) x[n]=y[n]; } INLINE void xmpn_mirror(mp_limb_t *x, long n) { long i; for(i=0;i<(n>>1);i++) { ulong m=x[i]; x[i]=x[n-1-i]; x[n-1-i]=m; } } INLINE void xmpn_mirrorcopy(mp_limb_t *z, mp_limb_t *x, long n) { long i; for(i=0;i= 0) x[n]=0; } INLINE GEN icopy_ef(GEN x, long l) { long lx = lgefint(x); const GEN y = cgeti(l); while (--lx > 0) y[lx]=x[lx]; return y; } /* NOTE: arguments of "spec" routines (muliispec, addiispec, etc.) aren't * GENs but pairs (long *a, long na) representing a list of digits (in basis * BITS_IN_LONG) : a[0], ..., a[na-1]. [ In ordre to facilitate splitting: no * need to reintroduce codewords ] * Use speci(a,na) to visualize the corresponding GEN. */ /***********************************************************************/ /** **/ /** ADDITION / SUBTRACTION **/ /** **/ /***********************************************************************/ GEN setloop(GEN a) { pari_sp av = avma - 2 * sizeof(long); (void)cgetg(lgefint(a) + 3, t_VECSMALL); return icopy_avma(a, av); /* two cells of extra space after a */ } /* we had a = setloop(?), then some incloops. Reset a to b */ GEN resetloop(GEN a, GEN b) { a[0] = evaltyp(t_INT) | evallg(lgefint(b)); affii(b, a); return a; } /* assume a > 0, initialized by setloop. Do a++ */ static GEN incpos(GEN a) { long i, l = lgefint(a); for (i=2; i= y */ INLINE GEN subiuspec(GEN x, ulong s, long nx) { GEN zd; long lz; if (nx == 1) return utoi(x[0] - s); lz = nx + 2; zd = cgeti(lz); mpn_sub_1 (LIMBS(zd), (mp_limb_t *)x, nx, s); if (! zd[lz - 1]) { --lz; } zd[1] = evalsigne(1) | evallgefint(lz); return zd; } /* assume x > y */ INLINE GEN subiispec(GEN x, GEN y, long nx, long ny) { GEN zd; long lz; if (ny==1) return subiuspec(x,*y,nx); lz = nx+2; zd = cgeti(lz); mpn_sub (LIMBS(zd), (mp_limb_t *)x, nx, (mp_limb_t *)y, ny); while (lz >= 3 && zd[lz - 1] == 0) { lz--; } zd[1] = evalsigne(1) | evallgefint(lz); return zd; } static void roundr_up_ip(GEN x, long l) { long i = l; for(;;) { if (++((ulong*)x)[--i]) break; if (i == 2) { x[2] = HIGHBIT; shiftr_inplace(x, 1); break; } } } void affir(GEN x, GEN y) { const long s = signe(x), ly = lg(y); long lx, sh, i; if (!s) { y[1] = evalexpo(-bit_accuracy(ly)); return; } lx = lgefint(x); sh = bfffo(*int_MSW(x)); y[1] = evalsigne(s) | evalexpo(bit_accuracy(lx)-sh-1); if (sh) { if (lx <= ly) { for (i=lx; i> (BITS_IN_LONG-sh); xmpn_mirror(LIMBS(y),ly-2); /* lx > ly: round properly */ if ((uel(x,lx-ly+1)< ly: round properly */ if (uel(x,lx-ly+1) & HIGHBIT) roundr_up_ip(y, ly); } } INLINE GEN shiftispec(GEN x, long nx, long n) { long ny,m; GEN yd, y; if (!n) return icopyspec(x, nx); if (n > 0) { long d = dvmdsBIL(n, &m); long i; ny = nx + d + (m!=0); y = cgeti(ny + 2); yd = y + 2; for (i=0; i 0) { GEN z = (GEN)avma; long d = dvmdsBIL(n, &m); ly = lx+d; y = new_chunk(ly); for ( ; d; d--) *--z = 0; if (!m) for (i=2; i> sh; /* Extend y on the left? */ if (i) { ly++; y = new_chunk(1); y[2] = i; } } } else { ly = lx - dvmdsBIL(-n, &m); if (ly<3) return gen_0; y = new_chunk(ly); if (m) { shift_right(y,x, 2,ly, 0,m); if (y[2] == 0) { if (ly==3) return gc_const((pari_sp)(y+3), gen_0); ly--; set_avma((pari_sp)(++y)); } } else { for (i=2; i lg(x)) pari_err_PREC( "truncr (precision loss in truncation)"); y=cgeti(d); y[1] = evalsigne(s) | evallgefint(d); if (++m == BITS_IN_LONG) for (i=2; i= 0) return truncr(x); if ((e=expo(x)) < 0) return gen_m1; d = nbits2lg(e+1); m = remsBIL(e); lx=lg(x); if (d>lx) pari_err_PREC( "floorr (precision loss in truncation)"); y = cgeti(d+1); if (++m == BITS_IN_LONG) { for (i=2; i ly) return 1; return mpn_cmp((mp_limb_t*)x,(mp_limb_t*)y, lx); } INLINE int equaliispec(GEN x, GEN y, long lx, long ly) { if (lx != ly) return 0; return !mpn_cmp((mp_limb_t*)x,(mp_limb_t*)y, lx); } /***********************************************************************/ /** **/ /** MULTIPLICATION **/ /** **/ /***********************************************************************/ /* assume ny > 0 */ INLINE GEN muluispec(ulong x, GEN y, long ny) { if (ny == 1) return muluu(x, *y); else { long lz = ny+3; GEN z = cgeti(lz); ulong hi = mpn_mul_1 (LIMBS(z), (mp_limb_t *)y, ny, x); if (hi) { z[lz - 1] = hi; } else lz--; z[1] = evalsigne(1) | evallgefint(lz); return z; } } /* a + b*|y| */ GEN addumului(ulong a, ulong b, GEN y) { GEN z; long i, lz; ulong hi; if (!b || !signe(y)) return utoi(a); lz = lgefint(y)+1; z = cgeti(lz); z[2]=a; for(i=3;i 0)? hi: x - hi; } /* return |y| \/ x */ GEN absdiviu_rem(GEN y, ulong x, ulong *rem) { long ly; GEN z; if (!x) pari_err_INV("absdiviu_rem",gen_0); if (!signe(y)) { *rem = 0; return gen_0; } ly = lgefint(y); if (ly == 3 && (ulong)x > uel(y,2)) { *rem = uel(y,2); return gen_0; } z = cgeti(ly); *rem = mpn_divrem_1(LIMBS(z), 0, LIMBS(y), NLIMBS(y), x); if (z [ly - 1] == 0) ly--; z[1] = evallgefint(ly) | evalsigne(1); return z; } GEN divis_rem(GEN y, long x, long *rem) { long sy=signe(y),ly,s; GEN z; if (!x) pari_err_INV("divis_rem",gen_0); if (!sy) { *rem = 0; return gen_0; } if (x<0) { s = -sy; x = -x; } else s = sy; ly = lgefint(y); if (ly == 3 && (ulong)x > uel(y,2)) { *rem = itos(y); return gen_0; } z = cgeti(ly); *rem = mpn_divrem_1(LIMBS(z), 0, LIMBS(y), NLIMBS(y), x); if (sy<0) *rem = - *rem; if (z[ly - 1] == 0) ly--; z[1] = evallgefint(ly) | evalsigne(s); return z; } GEN divis(GEN y, long x) { long sy=signe(y),ly,s; GEN z; if (!x) pari_err_INV("divis",gen_0); if (!sy) return gen_0; if (x<0) { s = -sy; x = -x; } else s=sy; ly = lgefint(y); if (ly == 3 && (ulong)x > uel(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 = cgetg(lw+2, t_REAL); 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 (uel(r,lly-1) > (uel(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); return gc_const((pari_sp)w, 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 = cgetg(llx+2, t_REAL); 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 (uel(r,lly-1) > (uel(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); return gc_const((pari_sp)w, w); } GEN divri(GEN x, GEN y) { long s = signe(y); if (!s) pari_err_INV("divri",gen_0); if (!signe(x)) return real_0_bit(expo(x) - expi(y)); if (!is_bigint(y)) { GEN z = divru(x, y[2]); if (s < 0) togglesign(z); return z; } return divri_with_gmp(x,y); } GEN divrr(GEN x, GEN y) { long sx=signe(x), sy=signe(y), lx,ly,lr,e,i,j; ulong y0,y1; GEN r, r1; if (!sy) pari_err_INV("divrr",y); e = expo(x) - expo(y); if (!sx) return real_0_bit(e); if (sy<0) sx = -sx; lx=lg(x); ly=lg(y); if (ly==3) { ulong k = x[2], l = (lx>3)? x[3]: 0; LOCAL_HIREMAINDER; if (k < uel(y,2)) e--; else { l >>= 1; if (k&1) l |= HIGHBIT; k >>= 1; } hiremainder = k; k = divll(l,y[2]); if (hiremainder > (uel(y,2) >> 1) && !++k) { k = HIGHBIT; e++; } r = cgetg(3, t_REAL); r[1] = evalsigne(sx) | evalexpo(e); r[2] = k; return r; } if (ly >= prec2lg(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 uel(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 (uel(r1,1) != hiremainder) { if (uel(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 { uel(r1,1) -= hiremainder; while (r1[1]) { qp++; if (!qp) { j=i; do uel(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]); uel(r1,1) -= overflow; } } } *++r1 = qp; } /* i = lr-1 */ /* round correctly */ if (uel(r1,1) > (y0>>1)) { j=i; do uel(r,--j)++; while (j && !r[j]); } r1 = r-1; for (j=i; j>=2; j--) r[j]=r1[j]; if (r[0] == 0) e--; 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) pari_err_INV("dvmdii",y); if (!sx) { if (!z || z == ONLY_REM) return gen_0; *z=gen_0; return gen_0; } lx=lgefint(x); ly=lgefint(y); lq=lx-ly; if (lq <= 0) { if (lq == 0) { long s=mpn_cmp(LIMBS(x),LIMBS(y),NLIMBS(x)); if (s>0) goto DIVIDE; if (s==0) { if (z == ONLY_REM) return gen_0; if (z) *z = gen_0; if (sx < 0) sy = -sy; return stoi(sy); } } if (z == ONLY_REM) return icopy(x); if (z) *z = icopy(x); return gen_0; } DIVIDE: /* quotient is nonzero */ 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) { if (!si) return gc_const(av, gen_0); set_avma(av); 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) return gc_const(av, gen_0); /* exact division */ } r[1] = evalsigne(sx) | evallgefint(lr); return gc_const((pari_sp)r, 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) return gc_const((pari_sp)q, q); if (!r[lr - 1]) { while(lr>2 && !r[lr - 1]) lr--; if (lr == 2) { *z = gen_0; return gc_const((pari_sp)q, q); } /* exact */ } r[1] = evalsigne(sx) | evallgefint(lr); *z = gc_const((pari_sp)r, r); return q; } } /* Montgomery reduction. * N has k words, assume T >= 0 has less than 2k. * Return res := T / B^k mod N, where B = 2^BIL * such that 0 <= res < T/B^k + N and res has less than k words */ GEN red_montgomery(GEN T, GEN N, ulong inv) { pari_sp av; GEN Te, Td, Ne, Nd, scratch; ulong i, j, m, t, d, k = NLIMBS(N); int carry; LOCAL_HIREMAINDER; LOCAL_OVERFLOW; if (k == 0) return gen_0; d = NLIMBS(T); /* <= 2*k */ if (d == 0) return gen_0; #ifdef DEBUG if (d > 2*k) pari_err_BUG("red_montgomery"); #endif if (k == 1) { /* as below, special cased for efficiency */ ulong n = uel(N,2); if (d == 1) { hiremainder = uel(T,2); m = hiremainder * inv; (void)addmul(m, n); /* t + m*n = 0 */ return utoi(hiremainder); } else { /* d = 2 */ hiremainder = uel(T,2); m = hiremainder * inv; (void)addmul(m, n); /* t + m*n = 0 */ t = addll(hiremainder, uel(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 */ GEN NE = N + k+1; Td = Te; Nd = Ne; t = subll(*++Td, *++Nd); *Td = t; while (Nd < NE) { 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) return gc_const(av, gen_0); Td = (GEN)av - k; /* will write mantissa there */ (void)memmove(Td, Te+1, k*sizeof(long)); Td -= 2; Td[0] = evaltyp(t_INT) | evallg(k+2); Td[1] = evalsigne(1) | evallgefint(k+2); #ifdef DEBUG { long l = NLIMBS(N), s = BITS_IN_LONG*l; GEN R = int2n(s); GEN res = remii(mulii(T, Fp_inv(R, N)), N); if (k > lgefint(N) || !equalii(remii(Td,N),res) || cmpii(Td, addii(shifti(T, -s), N)) >= 0) pari_err_BUG("red_montgomery"); } #endif return gc_const((pari_sp)Td, Td); } /* EXACT INTEGER DIVISION */ /* 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); } #ifdef mpn_divexact_1 static GEN diviuexact_i(GEN x, ulong y) { long l = lgefint(x); GEN z = cgeti(l); mpn_divexact_1(LIMBS(z), LIMBS(x), NLIMBS(x), y); if (z[l-1] == 0) l--; z[1] = evallgefint(l) | evalsigne(signe(x)); return z; } #elif 1 && !defined(_WIN64) /* mpz_divexact_ui is not LLP64 friendly */ /* assume y != 0 and the division is exact */ static GEN diviuexact_i(GEN x, ulong y) { long l = lgefint(x); GEN z = cgeti(l); mpz_t X, Z; 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; } #else /* assume y != 0 and the division is exact */ static GEN diviuexact_i(GEN x, ulong y) { /*TODO: implement true exact division.*/ return divii(x,utoi(y)); } #endif GEN diviuexact(GEN x, ulong y) { GEN z; if (!signe(x)) return gen_0; z = diviuexact_i(x, y); if (lgefint(z) == 2) pari_err_OP("exact division", x, utoi(y)); return z; } /* Find z such that x=y*z, knowing that y | x (unchecked) */ GEN diviiexact(GEN x, GEN y) { GEN z; if (!signe(y)) pari_err_INV("diviiexact",y); if (!signe(x)) return gen_0; if (lgefint(y) == 3) { z = diviuexact_i(x, y[2]); if (signe(y) < 0) togglesign(z); } else { long l = lgefint(x); mpz_t X, Y, Z; 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); } if (lgefint(z) == 2) pari_err_OP("exact division", x, y); return z; } /* assume yz != and yz | x */ GEN diviuuexact(GEN x, ulong y, ulong z) { long tmp[4]; ulong t; LOCAL_HIREMAINDER; t = mulll(y, z); if (!hiremainder) return diviuexact(x, t); tmp[0] = evaltyp(t_INT)|_evallg(4); tmp[1] = evalsigne(1)|evallgefint(4); tmp[2] = t; tmp[3] = hiremainder; return diviiexact(x, tmp); } /********************************************************************/ /** **/ /** INTEGER MULTIPLICATION **/ /** **/ /********************************************************************/ /* nx >= ny = num. of digits of x, y (not GEN, see mulii) */ GEN muliispec(GEN x, GEN y, long nx, long ny) { GEN zd; long lz; ulong hi; if (nx < ny) swapspec(x,y, nx,ny); if (!ny) return gen_0; if (ny == 1) return muluispec((ulong)*y, x, nx); lz = nx+ny+2; zd = cgeti(lz); hi = mpn_mul(LIMBS(zd), (mp_limb_t *)x, nx, (mp_limb_t *)y, ny); if (!hi) lz--; /*else zd[lz-1]=hi; GH tell me it is not necessary.*/ zd[1] = evalsigne(1) | evallgefint(lz); return zd; } GEN muluui(ulong x, ulong y, GEN z) { long t, s = signe(z); GEN r; LOCAL_HIREMAINDER; if (!x || !y || !signe(z)) return gen_0; t = mulll(x,y); if (!hiremainder) r = muluispec(t, z+2, lgefint(z)-2); else { long tmp[2]; tmp[1] = hiremainder; tmp[0] = t; r = muliispec(z+2,tmp, lgefint(z)-2, 2); } setsigne(r,s); return r; } GEN sqrispec(GEN x, long nx) { GEN zd; long lz; if (!nx) return gen_0; if (nx==1) return sqru(*x); lz = (nx<<1)+2; zd = cgeti(lz); #ifdef mpn_sqr mpn_sqr(LIMBS(zd), (mp_limb_t *)x, nx); #else mpn_mul_n(LIMBS(zd), (mp_limb_t *)x, (mp_limb_t *)x, nx); #endif if (zd[lz-1]==0) lz--; zd[1] = evalsigne(1) | evallgefint(lz); return zd; } INLINE GEN sqrispec_mirror(GEN x, long nx) { GEN cx=new_chunk(nx); GEN z; xmpn_mirrorcopy((mp_limb_t *)cx,(mp_limb_t *)x,nx); z=sqrispec(cx, nx); xmpn_mirror(LIMBS(z), NLIMBS(z)); return z; } /* leaves garbage on the stack. */ INLINE GEN muliispec_mirror(GEN x, GEN y, long nx, long ny) { GEN cx, cy, z; long s = 0; while (nx && x[nx-1]==0) { nx--; s++; } while (ny && y[ny-1]==0) { ny--; s++; } cx=new_chunk(nx); cy=new_chunk(ny); xmpn_mirrorcopy((mp_limb_t *)cx,(mp_limb_t *)x,nx); xmpn_mirrorcopy((mp_limb_t *)cy,(mp_limb_t *)y,ny); z = nx>=ny ? muliispec(cx, cy, nx, ny): muliispec(cy, cx, ny, nx); if (s) { long i, lz = lgefint(z) + s; (void)new_chunk(s); z -= s; for (i=0; i= 0 */ GEN remi2n(GEN x, long n) { ulong hi; long l, k, lx, ly, sx = signe(x); GEN z, xd, zd; if (!sx || !n) return gen_0; k = dvmdsBIL(n, &l); lx = lgefint(x); if (lx < k+3) return icopy(x); xd = x + (2 + k); /* x = |k|...|1|#|... : copy the last l bits of # and the first k words * ^--- initial xd */ hi = ((ulong)*xd) & ((1UL<> 1; /* 2 + ceil(na/2) */ S = cgetipos(l); if (r) { GEN R = cgeti(2 + na); nr = mpn_sqrtrem(LIMBS(S), LIMBS(R), LIMBS(a), na); if (nr) R[1] = evalsigne(1) | evallgefint(nr+2); else { set_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 = cgetg(2 + l, t_REAL); res[1] = evalsigne(1) | evalexpo(er); if (e&1) { b = (mp_limb_t *) new_chunk(l<<1); xmpn_zero(b,l); xmpn_mirrorcopy(b+l, RLIMBS(a), l); c = (mp_limb_t *) new_chunk(l); n = mpn_sqrtrem(c,b,b,l<<1); /* c <- sqrt; b <- rem */ if (n>l || (n==l && mpn_cmp(b,c,l) > 0)) mpn_add_1(c,c,l,1); } else { ulong u; b = (mp_limb_t *) mantissa2nr(a,-1); b[1] = uel(a,l+1)<<(BITS_IN_LONG-1); b = (mp_limb_t *) new_chunk(l); xmpn_zero(b,l+1); /* overwrites the former b[0] */ c = (mp_limb_t *) new_chunk(l + 1); 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); return gc_const((pari_sp)res, res); } /* Normalize a nonnegative 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> $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/halfgcd.c $knone/ratlift.c\ $knone/invmod.c $kern1/gcd.c $kern1/gcdext.c $knone/mp_indep.c $knone/add.c mpker.c: \$(MP_C) cat \$(MP_C) > mpker.c mpker\$(_O): .headers mpker.c \$(CC) -c \$(CFLAGS) \$(KERNELCFLAGS) \$(DLCFLAGS) \$(CPPFLAGS) \$(GMPINCLUDE) -o mpker\$(_O) mpker.c EOT pari-2.17.2/src/kernel/hppa/0000755000175000017500000000000014760315601014166 5ustar billbillpari-2.17.2/src/kernel/hppa/asm0.h0000644000175000017500000000550514567450071015212 0ustar billbill#line 2 "../src/kernel/hppa/asm0.h" /* Copyright (C) 2004 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* 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 ulong hiremainder #define LOCAL_OVERFLOW 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.17.2/src/kernel/mips64/0000755000175000017500000000000014760315601014360 5ustar billbillpari-2.17.2/src/kernel/mips64/asm0.h0000644000175000017500000000607214567450071015404 0ustar billbill#line 2 "../src/kernel/mips64/asm0.h" /* Copyright (C) 2013 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* ASM mulll NOASM addll bfffo divll */ #ifdef ASMINLINE #define LOCAL_HIREMAINDER ulong hiremainder #define LOCAL_OVERFLOW ulong overflow #if defined(__mips_isa_rev) && __mips_isa_rev >= 6 #define mulll(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("dmuhu %1,%2,%3\n\tdmulu %0,%2,%3" \ : "=&r" (__value), "=&r" (hiremainder) \ : "r" (__arg1), "r" (__arg2) \ : ); \ __value; \ }) #define addmul(a, b) \ __extension__ ({ \ ulong __arg1 = (a), __arg2 = (b), __value, __tmp; \ __asm__ ("dmuhu %0,%3,%4\n\tdmulu %2,%3,%4\n\t" \ "daddu %1,%2,%5\n\tsltu %2,%1,%5\n\tdaddu %0,%0,%2" \ : "=&r" (hiremainder), "=&r" (__value), "=&r" (__tmp) \ : "r" (__arg1), "r" (__arg2), "r" (hiremainder) \ : ); \ __value; \ }) #else #define mulll(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("dmultu %2,%3\n\tmfhi %1" \ : "=&l" (__value), "=&r" (hiremainder) \ : "r" (__arg1), "r" (__arg2) \ : "hi"); \ __value; \ }) #define addmul(a, b) \ __extension__ ({ \ ulong __arg1 = (a), __arg2 = (b), __value, __tmp; \ __asm__ ("dmultu %3,%4\n\tmfhi %0\n\tmflo %2\n\t" \ "daddu %1,%2,%5\n\tsltu %2,%1,%5\n\tdaddu %0,%0,%2" \ : "=&r" (hiremainder), "=&r" (__value), "=&r" (__tmp) \ : "r" (__arg1), "r" (__arg2), "r" (hiremainder) \ : "hi", "lo"); \ __value; \ }) #endif #endif pari-2.17.2/src/kernel/none/0000755000175000017500000000000014760315601014175 5ustar billbillpari-2.17.2/src/kernel/none/invmod.c0000644000175000017500000001011114567450071015635 0ustar billbill#line 2 "../src/kernel/none/invmod.c" /* Copyright (C) 2003 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*================================== * 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; long s; ulong g; ulong xu,xu1,xv,xv1; /* Lehmer stage recurrence matrix */ int lhmres; /* Lehmer stage return value */ if (!signe(b)) { *res=absi(a); return 0; } av = avma; if (lgefint(b) == 3) /* single-word affair */ { ulong d1 = umodiu(a, uel(b,2)); if (d1 == 0) { if (b[2] == 1L) { *res = gen_0; return 1; } else { *res = absi(b); return 0; } } g = xgcduu(uel(b,2), d1, 1, &xv, &xv1, &s); set_avma(av); if (g != 1UL) { *res = utoipos(g); return 0; } xv = xv1 % uel(b,2); if (s < 0) xv = uel(b,2) - xv; *res = utoipos(xv); return 1; } (void)new_chunk(lgefint(b)); d = absi_shallow(b); d1 = modii(a,d); v=gen_0; v1=gen_1; /* general case */ av1 = avma; 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(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); } } } if (lhmres <= 0 && signe(d1)) { q = dvmdii(d,d1,&r); a = subii(v,mulii(q,v1)); v=v1; v1=a; d=d1; d1=r; } if (gc_needed(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(uel(d,2), uel(d1,2), 1, &xu, &xu1, &xv, &xv1, &s); if (g != 1UL) { set_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)); set_avma(av); *res = modii(v,b); return 1; } /* get here when the final sprint was skipped (d1 was zero already) */ set_avma(av); if (!equalii(d,gen_1)) { *res = icopy(d); return 0; } *res = modii(v,b); return 1; } pari-2.17.2/src/kernel/none/gcdext.c0000644000175000017500000001571514676526175015650 0ustar billbill#line 2 "../src/kernel/none/gcdext.c" /* Copyright (C) 2003 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*================================== * 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). */ static GEN bezout_lehmer(GEN a, GEN b, GEN *pu, GEN *pv) { GEN t,u,u1,v,v1,d,d1,q,r; GEN *pt; pari_sp av, av1; long s, sa, sb; ulong g; ulong xu,xu1,xv,xv1; /* Lehmer stage recurrence matrix */ int lhmres; /* Lehmer stage return value */ s = abscmpii(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(uel(a,2), uel(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_shallow(b); q = dvmdii(absi_shallow(a), d, &d1); if (!signe(d1)) /* a == qb */ { set_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_shallow(a); d1 = absi_shallow(b); u = v1 = gen_1; u1 = v = gen_0; } av1 = avma; /* 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); 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 (gc_needed(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(uel(d,2), uel(d1,2), 0, &xu, &xu1, &xv, &xv1, &s); u = subii(muliu(u,xu), muliu(u1, xv)); v = subii(muliu(v,xu), muliu(v1, xv)); if (s < 0) { sa = -sa; sb = -sb; } set_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. */ set_avma(av); if (pu) *pu = sa < 0 ? negi(u) : icopy(u); if (pv) *pv = sb < 0 ? negi(v) : icopy(v); return icopy(d); } static GEN addmulmul(GEN u, GEN v, GEN x, GEN y) { return addii(mulii(u, x),mulii(v, y)); } static GEN bezout_halfgcd(GEN x, GEN y, GEN *ptu, GEN *ptv) { pari_sp av=avma; GEN u, v, R = matid2(); while (lgefint(y)-2 >= EXTGCD_HALFGCD_LIMIT) { GEN M = HGCD0(x,y); R = ZM2_mul(R, gel(M, 1)); x = gel(M,2); y = gel(M,3); if (signe(y) && expi(y)= EXTGCD_HALFGCD_LIMIT) d = bezout_halfgcd(x, y, ptu, ptv); else d = bezout_lehmer(x, y, ptu, ptv); if (ptv) return gc_all(av,ptu?3:2, &d, ptv, ptu); return gc_all(av, ptu?2:1, &d, ptu); } pari-2.17.2/src/kernel/none/gcd.c0000644000175000017500000000716114567450071015111 0ustar billbill#line 2 "../src/kernel/none/gcd.c" /* Copyright (C) 2003 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* assume y > x > 0. return y mod x */ static ulong resiu(GEN y, ulong x) { long i, ly = lgefint(y); ulong xi = get_Fl_red(x); LOCAL_HIREMAINDER; hiremainder = 0; for (i=2; 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); set_avma(av); } /* uses modified right-shift binary algorithm now --GN 1998Jul23 */ static GEN gcdii_basecase(GEN a, GEN b) { long v, w; pari_sp av; GEN t, p1; switch (abscmpii(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: "set_avma(av)" gerepile (erasing t) is valid */ av = avma; (void)new_chunk(lgefint(b)); /* HACK */ t = remii(a,b); if (!signe(t)) { set_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(abscmpii(a,b)) { case 0: set_avma(av); a = shifti(a,v); return a; case -1: swap(a,b); } if (is_pm1(b)) { set_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)) { set_avma(av); return int2n(v); } switch(abscmpii(t,b)) { case -1: p1 = a; a = b; b = t; t = p1; break; case 1: swap(a,t); break; case 0: set_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]); set_avma(av); return shifti(r,v); } } GEN gcdii(GEN x, GEN y) { pari_sp av=avma; while (lgefint(y)-2 >= GCD_HALFGCD_LIMIT) { GEN M = HGCD0(x,y); x = gel(M,2); y = gel(M,3); if (signe(y) && expi(y) 0) { z[1] = evalsigne(sy) | evallgefint(3); z[2] = d; } else { z[1] = evalsigne(-sy) | evallgefint(3); z[2] =-d; } return z; } z = subiuspec(y+2,x, ly-2); setsigne(z,sy); return z; } GEN addui_sign(ulong x, GEN y, long sy) { long ly; GEN z; if (!x) return icopy_sign(y, sy); if (!sy) return utoipos(x); if (sy == 1) return adduispec(x,y+2, lgefint(y)-2); ly=lgefint(y); if (ly==3) { const ulong t = y[2]; if (x == t) return gen_0; z=cgeti(3); if (x < t) { z[1] = evalsigne(-1) | evallgefint(3); z[2] = t - x; } else { z[1] = evalsigne(1) | evallgefint(3); z[2] = x - t; } return z; } z = subiuspec(y+2,x, ly-2); setsigne(z,-1); return z; } /* return gen_0 when the sign is 0 */ GEN addii_sign(GEN x, long sx, GEN y, long sy) { long lx,ly; GEN z; if (!sx) return sy? icopy_sign(y, sy): gen_0; if (!sy) return icopy_sign(x, sx); lx = lgefint(x); ly = lgefint(y); if (sx==sy) z = addiispec(x+2,y+2,lx-2,ly-2); else { /* sx != sy */ long i = cmpiispec(x+2,y+2,lx-2,ly-2); if (!i) return gen_0; /* we must ensure |x| > |y| for subiispec */ if (i < 0) { sx = sy; z = subiispec(y+2,x+2,ly-2,lx-2); } else z = subiispec(x+2,y+2,lx-2,ly-2); } setsigne(z,sx); return z; } INLINE GEN rcopy_sign(GEN x, long sx) { GEN y = rcopy(x); setsigne(y,sx); return y; } GEN addir_sign(GEN x, long sx, GEN y, long sy) { long e, l, ly; GEN z; if (!sx) return rcopy_sign(y, sy); e = expo(y) - expi(x); if (!sy) { if (e >= 0) return rcopy_sign(y, sy); z = itor(x, nbits2prec(-e)); setsigne(z, sx); return z; } ly = lg(y); if (e > 0) { l = lg2prec(ly - divsBIL(e)); if (l < LOWDEFAULTPREC) return rcopy_sign(y, sy); } else l = lg2prec(ly) + nbits2extraprec(-e); z = (GEN)avma; y = addrr_sign(itor(x,l), sx, y, sy); ly = lg(y); while (ly--) *--z = y[ly]; set_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 = lg2prec(ly - divsBIL(e)); if (l < LOWDEFAULTPREC) return rcopy_sign(y, sy); } else l = lg2prec(ly) + nbits2extraprec(-e); z = (GEN)avma; y = addrr_sign(stor(x,l), sx, y, sy); ly = lg(y); while (ly--) *--z = y[ly]; set_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)); } 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 = nbits2lg(-e); lx = lg(x); if (lz > lx) lz = lx; z = cgetg(lz, t_REAL); while(--lz) z[lz] = x[lz]; setsigne(z,sx); return z; } if (!sx) { if (e <= 0) return real_0_bit(ex); lz = nbits2lg(e); ly = lg(y); if (lz > ly) lz = ly; z = cgetg(lz, t_REAL); 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) uel(x,lx) = uel(p1,lx-1) << sh; set_avma(av); /* HACK: cgetg(lz, t_REAL) 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 = cgetg(--lz, t_REAL); else { z = cgetg(lz, t_REAL); z[i] = garde; } } else { z = cgetg(lz, t_REAL); 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] = uel(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 - lg2prec(lx)); f2 = (uel(y,i) > uel(x,i)); } /* result is nonzero. f2 = (y > x) */ i = lz-1; z = cgetg(lz, t_REAL); 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] = uel(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); set_avma((pari_sp)z); return z; } pari-2.17.2/src/kernel/none/mp.c0000644000175000017500000015214414760123736014772 0ustar billbill#line 2 "../src/kernel/none/mp.c" /* Copyright (C) 2000-2003 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /***********************************************************************/ /** **/ /** MULTIPRECISION KERNEL **/ /** **/ /***********************************************************************/ #include "pari.h" #include "paripriv.h" #include "../src/kernel/none/tune-gen.h" void pari_kernel_init(void) { } void pari_kernel_close(void) { } const char * pari_kernel_version(void) { return ""; } /* 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 nonnegative 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) set_avma((pari_sp)x); else stackdummy((pari_sp)(x0+i), (pari_sp)x0); lx -= i; x[0] = evaltyp(t_INT) | evallg(lx); if (lx == 2) x[1] = evalsigne(0) | evallgefint(lx); else x[1] = evalsigne(1) | evallgefint(lx); return x; } /***********************************************************************/ /** **/ /** ADDITION / SUBTRACTION **/ /** **/ /***********************************************************************/ GEN setloop(GEN a) { pari_sp av = avma; (void)cgetg(lgefint(a) + 3, t_VECSMALL); return icopy_avma(a, av); /* two cells of extra space before a */ } /* we had a = setloop(?), then some incloops. Reset a to b */ GEN resetloop(GEN a, GEN b) { long lb = lgefint(b); a += lgefint(a) - lb; a[0] = evaltyp(t_INT) | evallg(lb); affii(b, a); return a; } /* assume a > 0, initialized by setloop. Do a++ */ static GEN incpos(GEN a) { long i, l = lgefint(a); for (i=l-1; i>1; i--) if (++a[i]) return a; l++; a--; /* use extra cell */ a[0]=evaltyp(t_INT) | _evallg(l); a[1]=evalsigne(1) | evallgefint(l); a[2]=1; return a; } /* assume a < 0, initialized by setloop. Do a++ */ static GEN incneg(GEN a) { long i, l = lgefint(a)-1; if (uel(a,l)--) { if (l == 2 && !a[2]) { a++; /* save one cell */ a[0] = evaltyp(t_INT) | _evallg(2); a[1] = evalsigne(0) | evallgefint(2); } return a; } for (i = l-1;; i--) /* finishes since a[2] != 0 */ if (uel(a,i)--) break; if (!a[2]) { a++; /* save one cell */ a[0] = evaltyp(t_INT) | _evallg(l); a[1] = evalsigne(-1) | evallgefint(l); } return a; } /* assume a initialized by setloop. Do a++ */ GEN incloop(GEN a) { switch(signe(a)) { case 0: a--; /* use extra cell */ a[0]=evaltyp(t_INT) | _evallg(3); a[1]=evalsigne(1) | evallgefint(3); a[2]=1; return a; case -1: return incneg(a); default: return incpos(a); } } INLINE GEN adduispec(ulong s, GEN x, long nx) { GEN xd, zd = (GEN)avma; long lz; if (nx == 1) return adduu(s, uel(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); return gc_const((pari_sp)zd, zd); } GEN adduispec_offset(ulong s, GEN x, long offset, long nx) { GEN xd = x+lgefint(x)-nx-offset; while (nx && *xd==0) {xd++; nx--;} if (!nx) return utoi(s); return adduispec(s,xd,nx); } static GEN addiispec(GEN x, GEN y, long nx, long ny) { GEN xd, yd, zd; long lz, i = -2; LOCAL_OVERFLOW; if (nx < ny) swapspec(x,y, nx,ny); if (ny == 1) return adduispec(*y,x,nx); zd = (GEN)avma; lz = nx+3; (void)new_chunk(lz); xd = x + nx; yd = y + ny; zd[-1] = addll(xd[-1], yd[-1]); #ifdef addllx8 for ( ; i-8 > -ny; i-=8) addllx8(xd+i, yd+i, zd+i, overflow); #endif for ( ; i >= -ny; i--) zd[i] = addllx(xd[i], yd[i]); if (overflow) for(;;) { if (i < -nx) { zd[i] = 1; i--; break; } /* enlarge z */ zd[i] = uel(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); return gc_const((pari_sp)zd, 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); return gc_const((pari_sp)zd, zd); } /* assume x > y */ static GEN subiispec(GEN x, GEN y, long nx, long ny) { GEN xd,yd,zd; long lz, i = -2; LOCAL_OVERFLOW; if (ny==1) return subiuspec(x,*y,nx); zd = (GEN)avma; lz = nx+2; (void)new_chunk(lz); xd = x + nx; yd = y + ny; zd[-1] = subll(xd[-1], yd[-1]); #ifdef subllx8 for ( ; i-8 > -ny; i-=8) subllx8(xd+i, yd+i, zd+i, overflow); #endif for ( ; i >= -ny; i--) zd[i] = subllx(xd[i], yd[i]); if (overflow) for(;;) { zd[i] = uel(xd,i) - 1; if (xd[i--]) break; } if (i>=-nx) for (; i >= -nx; i--) zd[i] = xd[i]; else while (zd[i+1] == 0) { i++; lz--; } /* shorten z */ zd += i+1; *--zd = evalsigne(1) | evallgefint(lz); *--zd = evaltyp(t_INT) | evallg(lz); return gc_const((pari_sp)zd, zd); } static void roundr_up_ip(GEN x, long l) { long i = l; for(;;) { if (++uel(x,--i)) break; if (i == 2) { x[2] = (long)HIGHBIT; shiftr_inplace(x, 1); break; } } } void affir(GEN x, GEN y) { const long s = signe(x), ly = lg(y); long lx, sh, i; if (!s) { y[1] = evalexpo(-bit_accuracy(ly)); return; } lx = lgefint(x); sh = bfffo(x[2]); y[1] = evalsigne(s) | evalexpo(bit_accuracy(lx)-sh-1); if (sh) { if (lx <= ly) { for (i=lx; i ly: round properly */ if ((uel(x,ly)< ly: round properly */ if (uel(x,ly) & HIGHBIT) roundr_up_ip(y, ly); } } INLINE GEN shiftispec(GEN x, long nx, long n) { long ny, i, m; GEN y, yd; if (!n) return icopyspec(x, nx); if (n > 0) { GEN z = (GEN)avma; long d = dvmdsBIL(n, &m); ny = nx+d; y = new_chunk(ny + 2); yd = y + 2; for ( ; d; d--) *--z = 0; if (!m) for (i=0; i> sh; /* Extend y on the left? */ if (i) { ny++; y = new_chunk(1); y[2] = i; } } } else { ny = nx - dvmdsBIL(-n, &m); if (ny<1) return gen_0; y = new_chunk(ny + 2); yd = y + 2; if (m) { shift_right(yd,x, 0,ny, 0,m); if (yd[0] == 0) { if (ny==1) return gc_const((pari_sp)(y+3), gen_0); ny--; set_avma((pari_sp)(++y)); } } else { for (i=0; i lg(x)) pari_err_PREC( "truncr (precision loss in truncation)"); y=cgeti(d); y[1] = evalsigne(s) | evallgefint(d); if (++m == BITS_IN_LONG) for (i=2; i= 0) return truncr(x); if ((e=expo(x)) < 0) return gen_m1; d = nbits2lg(e+1); m = remsBIL(e); lx=lg(x); if (d>lx) pari_err_PREC( "floorr (precision loss in truncation)"); y = new_chunk(d); if (++m == BITS_IN_LONG) { for (i=2; i=2; i--) { uel(y,i)++; if (y[i]) goto END; } y=new_chunk(1); y[2]=1; d++; END: y[1] = evalsigne(-1) | evallgefint(d); y[0] = evaltyp(t_INT) | evallg(d); return y; } INLINE int cmpiispec(GEN x, GEN y, long lx, long ly) { long i; if (lx < ly) return -1; if (lx > ly) return 1; i = 0; while (i uel(y,i))? 1: -1; } INLINE int equaliispec(GEN x, GEN y, long lx, long ly) { long i; if (lx != ly) return 0; i = ly-1; while (i>=0 && x[i]==y[i]) i--; return i < 0; } /***********************************************************************/ /** **/ /** MULTIPLICATION **/ /** **/ /***********************************************************************/ /* assume ny > 0 */ INLINE GEN muluispec(ulong x, GEN y, long ny) { GEN yd, z = (GEN)avma; long lz = ny+3; LOCAL_HIREMAINDER; (void)new_chunk(lz); yd = y + ny; *--z = mulll(x, *--yd); while (yd > y) *--z = addmul(x,*--yd); if (hiremainder) *--z = hiremainder; else lz--; *--z = evalsigne(1) | evallgefint(lz); *--z = evaltyp(t_INT) | evallg(lz); return gc_const((pari_sp)z, z); } /* a + b*|Y| */ GEN addumului(ulong a, ulong b, GEN Y) { GEN yd,y,z; long ny,lz; LOCAL_HIREMAINDER; LOCAL_OVERFLOW; if (!b || !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); return gc_const((pari_sp)z, z); } /***********************************************************************/ /** **/ /** DIVISION **/ /** **/ /***********************************************************************/ ulong umodiu(GEN y, ulong x) { long sy=signe(y),ly,i; ulong xi; LOCAL_HIREMAINDER; if (!x) pari_err_INV("umodiu",gen_0); if (!sy) return 0; ly = lgefint(y); if (x <= uel(y,2)) { hiremainder=0; if (ly==3) { hiremainder=uel(y,2)%x; if (!hiremainder) return 0; return (sy > 0)? hiremainder: x - hiremainder; } } else { if (ly==3) return (sy > 0)? uel(y,2): x - uel(y,2); hiremainder=uel(y,2); ly--; y++; } xi = get_Fl_red(x); for (i=2; i 0)? hiremainder: x - hiremainder; } /* return |y| \/ x */ GEN absdiviu_rem(GEN y, ulong x, ulong *rem) { long ly,i; GEN z; ulong xi; LOCAL_HIREMAINDER; if (!x) pari_err_INV("absdiviu_rem",gen_0); if (!signe(y)) { *rem = 0; return gen_0; } ly = lgefint(y); if (x <= uel(y,2)) { hiremainder=0; if (ly==3) { z = cgetipos(3); z[2] = divll(uel(y,2),x); *rem = hiremainder; return z; } } else { if (ly==3) { *rem = uel(y,2); return gen_0; } hiremainder = uel(y,2); ly--; y++; } xi = get_Fl_red(x); z = cgetipos(ly); for (i=2; i3)? x[3]: 0; LOCAL_HIREMAINDER; if (k < uel(y,2)) e--; else { l >>= 1; if (k&1) l |= HIGHBIT; k >>= 1; } hiremainder = k; k = divll(l,y[2]); if (hiremainder > (uel(y,2) >> 1) && !++k) { k = HIGHBIT; e++; } r = cgetg(3, t_REAL); r[1] = evalsigne(sx) | evalexpo(e); r[2] = k; return r; } lr = minss(lx,ly); r = new_chunk(lr); r1 = r-1; r1[1] = 0; for (i=2; ily)? x[lr]: 0; y0 = y[2]; y1 = y[3]; for (i=0; i y0) /* can't happen if i=0 */ { GEN y1 = y+1; j = lr-i; r1[j] = subll(r1[j],y1[j]); for (j--; j>0; j--) r1[j] = subllx(r1[j],y1[j]); j=i; do uel(r,--j)++; while (j && !uel(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 (uel(r1,1) != hiremainder) { if (uel(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 uel(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 (uel(r1,1) > (y0>>1)) { j=i; do uel(r,--j)++; while (j && !r[j]); } r1 = r-1; for (j=i; j>=2; j--) r[j]=r1[j]; if (r[0] == 0) e--; else if (r[0] == 1) { shift_right(r,r, 2,lr, 1,1); } else { /* possible only when rounding up to 0x2 0x0 ... */ r[2] = (long)HIGHBIT; e++; } r[0] = evaltyp(t_REAL)|evallg(lr); r[1] = evalsigne(sx) | evalexpo(e); return r; } GEN divri(GEN x, GEN y) { long lx, s = signe(y); pari_sp av; GEN z; if (!s) pari_err_INV("divri",y); if (!signe(x)) return real_0_bit(expo(x) - expi(y)); if (!is_bigint(y)) { GEN z = divru(x, y[2]); if (s < 0) togglesign(z); return z; } lx = lg(x); z = cgetg(lx, t_REAL); av = avma; affrr(divrr(x, itor(y, lg2prec(lx+1))), z); return gc_const(av, 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 = lgefint(y), lz, i, j, sh, lq, lr; pari_sp av; ulong y0,y0i,y1, *xd,*rd,*qd; GEN q, r, r1; if (!sx) { if (ly < 3) pari_err_INV("dvmdii",gen_0); if (!z || z == ONLY_REM) return gen_0; *z=gen_0; return gen_0; } if (ly <= 3) { ulong rem; if (ly < 3) pari_err_INV("dvmdii",gen_0); if (z == ONLY_REM) { rem = umodiu(x,uel(y,2)); if (!rem) return gen_0; return (sx < 0)? utoineg(uel(y,2) - rem): utoipos(rem); } q = absdiviu_rem(x, uel(y,2), &rem); if (sx != sy) togglesign(q); if (!z) return q; if (!rem) *z = gen_0; else *z = sx < 0? utoineg(rem): utoipos(rem); return q; } lx=lgefint(x); lz=lx-ly; if (lz <= 0) { if (lz == 0) { for (i=2; i uel(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 nonzero */ av=avma; if (sx<0) sy = -sy; r1 = new_chunk(lx); sh = bfffo(y[2]); if (sh) { /* normalize so that highbit(y) = 1 (shift left x and y by sh bits)*/ const ulong m = BITS_IN_LONG - sh; r = new_chunk(ly); shift_left(r, y,2,ly-1, 0,sh); y = r; shift_left(r1,x,2,lx-1, 0,sh); r1[1] = uel(x,2) >> m; } else { r1[1] = 0; for (j=2; j1; j--) { r1[j] = subll(r1[j], addmul(qp,y[j])); hiremainder += overflow; } if (uel(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); return gc_const((pari_sp)qd, (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); return gc_const((pari_sp)rd, (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; } return gc_const((pari_sp)qd, q); } /* Montgomery reduction. * N has k words, assume T >= 0 has less than 2k. * Return res := T / B^k mod N, where B = 2^BIL * such that 0 <= res < T/B^k + N and res has less than k words */ GEN red_montgomery(GEN T, GEN N, ulong inv) { pari_sp av; GEN Te, Td, Ne, Nd, scratch; ulong i, j, m, t, d, k = NLIMBS(N); int carry; LOCAL_HIREMAINDER; LOCAL_OVERFLOW; if (k == 0) return gen_0; d = NLIMBS(T); /* <= 2*k */ if (d == 0) return gen_0; #ifdef DEBUG if (d > 2*k) pari_err_BUG("red_montgomery"); #endif if (k == 1) { /* as below, special cased for efficiency */ ulong n = uel(N,2); if (d == 1) { hiremainder = uel(T,2); m = hiremainder * inv; (void)addmul(m, n); /* t + m*n = 0 */ return utoi(hiremainder); } else { /* d = 2 */ hiremainder = uel(T,3); m = hiremainder * inv; (void)addmul(m, n); /* t + m*n = 0 */ t = addll(hiremainder, uel(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) return gc_const(av, gen_0); k += 2; *--Td = evalsigne(1) | evallgefint(k); *--Td = evaltyp(t_INT) | evallg(k); #ifdef DEBUG { long l = NLIMBS(N), s = BITS_IN_LONG*l; GEN R = int2n(s); GEN res = remii(mulii(T, Fp_inv(R, N)), N); if (k > lgefint(N) || !equalii(remii(Td,N),res) || cmpii(Td, addii(shifti(T, -s), N)) >= 0) pari_err_BUG("red_montgomery"); } #endif return gc_const((pari_sp)Td, 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) { q = uel(x,2) / y; if (!q) pari_err_OP("exact division", x, utoi(y)); return utoipos(q); } yinv = invmod2BIL(y); lz = (y <= uel(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*uel(--x0,0); /* i-th quotient */ if (!q) continue; /* x := x - q * y */ { /* update neither lowest word (could set it to 0) nor highest ones */ GEN x1 = x0 - 1; LOCAL_HIREMAINDER; (void)mulll(q,y); if (hiremainder) { if (uel(x1,0) < hiremainder) { uel(x1,0) -= hiremainder; do uel(--x1,0)--; while (uel(x1,0) == ULONG_MAX); } else uel(x1,0) -= 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); if (lz == 2) pari_err_OP("exact division", x, utoi(y)); return gc_const((pari_sp)z, 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 = uel(x,2) / y; if (!q) pari_err_OP("exact division", x, utoi(y)); return (s > 0)? utoipos(q): utoineg(q); } av = avma; (void)new_chunk(lx); vy = vals(y); if (vy) { y >>= vy; if (y == 1) { set_avma(av); return shifti(x, -vy); } x = shifti(x, -vy); if (lx == 3) { ulong q = uel(x,2) / y; set_avma(av); if (!q) pari_err_OP("exact division", x, utoi(y)); return (s > 0)? utoipos(q): utoineg(q); } } else x = icopy(x); set_avma(av); z = diviuexact_i(x, y); setsigne(z, s); return z; } /* Find z such that x=y*z, knowing that y | x (unchecked) * Method: y0 z0 = x0 mod B = 2^BITS_IN_LONG ==> z0 = 1/y0 mod B. * Set x := (x - z0 y) / B, updating only relevant words, and repeat */ GEN diviiexact(GEN x, GEN y) { long lx, ly, lz, vy, i, ii, sx = signe(x), sy = signe(y); pari_sp av; ulong y0inv,q; GEN z; if (!sy) pari_err_INV("diviiexact",gen_0); if (!sx) return gen_0; lx = lgefint(x); if (lx == 3) { q = uel(x,2) / uel(y,2); if (!q) pari_err_OP("exact division", x, y); 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 */ set_avma(av); /* will erase our x,y when exiting */ /* now y is odd */ ly = lgefint(y); if (ly == 3) { z = diviuexact_i(x,uel(y,2)); /* x != 0 */ setsigne(z, (sx+sy)? 1: -1); return z; } y0inv = invmod2BIL(y[ly-1]); i=2; while (i=2; i--,ii--) { long limj; LOCAL_HIREMAINDER; LOCAL_OVERFLOW; z[i] = q = y0inv*uel(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 */ 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); if (lz == 2) pari_err_OP("exact division", x, y); return gc_const((pari_sp)z, z); } /* assume yz != and yz | x */ GEN diviuuexact(GEN x, ulong y, ulong z) { long tmp[4]; ulong t; LOCAL_HIREMAINDER; t = mulll(y, z); if (!hiremainder) return diviuexact(x, t); tmp[0] = evaltyp(t_INT)|_evallg(4); tmp[1] = evalsigne(1)|evallgefint(4); tmp[2] = hiremainder; tmp[3] = t; return diviiexact(x, tmp); } /********************************************************************/ /** **/ /** INTEGER MULTIPLICATION (BASECASE) **/ /** **/ /********************************************************************/ /* nx >= ny = num. of digits of x, y (not GEN, see mulii) */ INLINE GEN muliispec_basecase(GEN x, GEN y, long nx, long ny) { GEN z2e,z2d,yd,xd,ye,zd; long p1,lz; LOCAL_HIREMAINDER; if (ny == 1) return muluispec((ulong)*y, x, nx); if (ny == 0) return gen_0; zd = (GEN)avma; lz = nx+ny+2; (void)new_chunk(lz); xd = x + nx; yd = y + ny; ye = yd; p1 = *--xd; *--zd = mulll(p1, *--yd); z2e = zd; while (yd > y) *--zd = addmul(p1, *--yd); *--zd = hiremainder; while (xd > x) { LOCAL_OVERFLOW; yd = ye; p1 = *--xd; z2d = --z2e; *z2d = addll(mulll(p1, *--yd), *z2d); z2d--; while (yd > y) { hiremainder += overflow; *z2d = addll(addmul(p1, *--yd), *z2d); z2d--; } *--zd = hiremainder + overflow; } if (*zd == 0) { zd++; lz--; } /* normalize */ *--zd = evalsigne(1) | evallgefint(lz); *--zd = evaltyp(t_INT) | evallg(lz); return gc_const((pari_sp)zd, 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); return gc_const((pari_sp)zd, 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 = subiu(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)); set_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)); set_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)); set_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)); set_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)); set_avma(av2); } set_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)); set_avma(av); } return gerepileuptoint(ltop, muliifft_unspliti(FFT,bs,2+len)); } /********************************************************************/ /** **/ /** INTEGER MULTIPLICATION (KARATSUBA) **/ /** **/ /********************************************************************/ /* return (x shifted left d words) + y. Assume d > 0, x > 0 and y >= 0 */ static GEN addshiftw(GEN x, GEN y, long d) { GEN z,z0,y0,yd, zd = (GEN)avma; long a,lz,ly = lgefint(y); z0 = new_chunk(d); a = ly-2; yd = y+ly; if (a >= d) { y0 = yd-d; while (yd > y0) *--zd = *--yd; /* copy last d words of y */ a -= d; if (a) z = addiispec(LIMBS(x), LIMBS(y), NLIMBS(x), a); else z = icopy(x); } else { y0 = yd-a; while (yd > y0) *--zd = *--yd; /* copy last a words of y */ while (zd > z0) *--zd = 0; /* complete with 0s */ z = icopy(x); } lz = lgefint(z)+d; z[1] = evalsigne(1) | evallgefint(lz); z[0] = evaltyp(t_INT) | evallg(lz); return z; } /* Fast product (Karatsuba) of integers. a and b are "special" GENs * c,c0,c1,c2 are genuine GENs. */ GEN muliispec(GEN a, GEN b, long na, long nb) { GEN a0,c,c0; long n0, n0a, i; pari_sp av; if (na < nb) swapspec(a,b, na,nb); if (nb < MULII_KARATSUBA_LIMIT) return muliispec_basecase(a,b,na,nb); if (nb >= MULII_FFT_LIMIT) return muliispec_fft(a,b,na,nb); i=(na>>1); n0=na-i; na=i; av=avma; a0=a+na; n0a=n0; while (n0a && !*a0) { a0++; n0a--; } if (n0a && nb > n0) { /* nb <= na <= n0 */ GEN b0,c1,c2; long n0b; nb -= n0; c = muliispec(a,b,na,nb); b0 = b+nb; n0b = n0; while (n0b && !*b0) { b0++; n0b--; } if (n0b) { c0 = muliispec(a0,b0, n0a,n0b); c2 = addiispec(a0,a, n0a,na); c1 = addiispec(b0,b, n0b,nb); c1 = muliispec(LIMBS(c1),LIMBS(c2), NLIMBS(c1),NLIMBS(c2)); c2 = addiispec(LIMBS(c0),LIMBS(c), NLIMBS(c0),NLIMBS(c)); c1 = subiispec(LIMBS(c1),LIMBS(c2), NLIMBS(c1),NLIMBS(c2)); } else { c0 = gen_0; c1 = muliispec(a0,b, n0a,nb); } c = addshiftw(c,c1, n0); } else { c = muliispec(a,b,na,nb); c0 = muliispec(a0,b,n0a,nb); } return gerepileuptoint(av, addshiftw(c,c0, n0)); } GEN muluui(ulong x, ulong y, GEN z) { long t, s = signe(z); GEN r; LOCAL_HIREMAINDER; if (!x || !y || !signe(z)) return gen_0; t = mulll(x,y); if (!hiremainder) r = muluispec(t, z+2, lgefint(z)-2); else { long tmp[2]; tmp[0] = hiremainder; tmp[1] = t; r = muliispec(z+2,tmp,lgefint(z)-2,2); } setsigne(r,s); return r; } #define sqrispec_mirror sqrispec #define muliispec_mirror muliispec /* x % (2^n), assuming n >= 0 */ GEN remi2n(GEN x, long n) { long hi,l,k,lx,ly, sx = signe(x); GEN z, xd, zd; if (!sx || !n) return gen_0; k = dvmdsBIL(n, &l); lx = lgefint(x); if (lx < k+3) return icopy(x); xd = x + (lx-k-1); /* x = |_|...|#|1|...|k| : copy the last l bits of # and the last k words * ^--- initial xd */ hi = ((ulong)*xd) & ((1UL<= SQRI_FFT_LIMIT) return sqrispec_fft(a,na); i=(na>>1); n0=na-i; na=i; av=avma; a0=a+na; n0a=n0; while (n0a && !*a0) { a0++; n0a--; } c = sqrispec(a,na); if (n0a) { GEN t, c1, c0 = sqrispec(a0,n0a); #if 0 c1 = shifti(muliispec(a0,a, n0a,na),1); #else /* faster */ t = addiispec(a0,a,n0a,na); t = sqrispec(LIMBS(t),NLIMBS(t)); c1= addiispec(LIMBS(c0),LIMBS(c), NLIMBS(c0), NLIMBS(c)); c1= subiispec(LIMBS(t),LIMBS(c1), NLIMBS(t), NLIMBS(c1)); #endif c = addshiftw(c,c1, n0); c = addshiftw(c,c0, n0); } else c = addshiftw(c,gen_0,n0<<1); return gerepileuptoint(av, c); } /********************************************************************/ /** **/ /** KARATSUBA SQUARE ROOT **/ /** adapted from Paul Zimmermann's implementation of **/ /** his algorithm in GMP (mpn_sqrtrem) **/ /** **/ /********************************************************************/ /* Square roots table */ static const unsigned char approx_tab[192] = { 128,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142, 143,144,144,145,146,147,148,149,150,150,151,152,153,154,155,155, 156,157,158,159,160,160,161,162,163,163,164,165,166,167,167,168, 169,170,170,171,172,173,173,174,175,176,176,177,178,178,179,180, 181,181,182,183,183,184,185,185,186,187,187,188,189,189,190,191, 192,192,193,193,194,195,195,196,197,197,198,199,199,200,201,201, 202,203,203,204,204,205,206,206,207,208,208,209,209,210,211,211, 212,212,213,214,214,215,215,216,217,217,218,218,219,219,220,221, 221,222,222,223,224,224,225,225,226,226,227,227,228,229,229,230, 230,231,231,232,232,233,234,234,235,235,236,236,237,237,238,238, 239,240,240,241,241,242,242,243,243,244,244,245,245,246,246,247, 247,248,248,249,249,250,250,251,251,252,252,253,253,254,254,255 }; /* N[0], assume N[0] >= 2^(BIL-2). * Return r,s such that s^2 + r = N, 0 <= r <= 2s */ static void p_sqrtu1(ulong *N, ulong *ps, ulong *pr) { ulong prec, r, s, q, u, n0 = N[0]; q = n0 >> (BITS_IN_LONG - 8); /* 2^6 = 64 <= q < 256 = 2^8 */ s = approx_tab[q - 64]; /* 128 <= s < 255 */ r = (n0 >> (BITS_IN_LONG - 16)) - s * s; /* r <= 2*s */ if (r > (s << 1)) { r -= (s << 1) | 1; s++; } /* 8-bit approximation from the high 8-bits of N[0] */ prec = 8; n0 <<= 2 * prec; while (2 * prec < BITS_IN_LONG) { /* invariant: s has prec bits, and r <= 2*s */ r = (r << prec) + (n0 >> (BITS_IN_LONG - prec)); n0 <<= prec; u = 2 * s; q = r / u; u = r - q * u; s = (s << prec) + q; u = (u << prec) + (n0 >> (BITS_IN_LONG - prec)); q = q * q; r = u - q; if (u < q) { s--; r += (s << 1) | 1; } n0 <<= prec; prec = 2 * prec; } *ps = s; *pr = r; } /* N[0..1], assume N[0] >= 2^(BIL-2). * Return 1 if remainder overflows, 0 otherwise */ static int p_sqrtu2(ulong *N, ulong *ps, ulong *pr) { ulong cc, qhl, r, s, q, u, n1 = N[1]; LOCAL_OVERFLOW; p_sqrtu1(N, &s, &r); /* r <= 2s */ qhl = 0; while (r >= s) { qhl++; r -= s; } /* now r < s < 2^(BIL/2) */ r = (r << BITS_IN_HALFULONG) | (n1 >> BITS_IN_HALFULONG); u = s << 1; q = r / u; u = r - q * u; q += (qhl & 1) << (BITS_IN_HALFULONG - 1); qhl >>= 1; /* (initial r)<<(BIL/2) + n1>>(BIL/2) = (qhl<<(BIL/2) + q) * 2s + u */ s = ((s + qhl) << BITS_IN_HALFULONG) + q; cc = u >> BITS_IN_HALFULONG; r = (u << BITS_IN_HALFULONG) | (n1 & LOWMASK); r = subll(r, q * q); cc -= overflow + qhl; /* now subtract 2*q*2^(BIL/2) + 2^BIL if qhl is set */ if ((long)cc < 0) { if (s) { r = addll(r, s); cc += overflow; s--; } else { cc++; s = ~0UL; } r = addll(r, s); cc += overflow; } *ps = s; *pr = r; return cc; } static void xmpn_zero(GEN x, long n) { while (--n >= 0) x[n]=0; } static void xmpn_copy(GEN z, GEN x, long n) { long k = n; while (--k >= 0) z[k] = x[k]; } /* a[0..la-1] * 2^(lb BIL) | b[0..lb-1] */ static GEN catii(GEN a, long la, GEN b, long lb) { long l = la + lb + 2; GEN z = cgetipos(l); xmpn_copy(LIMBS(z), a, la); xmpn_copy(LIMBS(z) + la, b, lb); return int_normalize(z, 0); } /* sqrt n[0..1], assume n normalized */ static GEN sqrtispec2(GEN n, GEN *pr) { ulong s, r; int hi = p_sqrtu2((ulong*)n, &s, &r); GEN S = utoi(s); *pr = hi? uutoi(1,r): utoi(r); return S; } /* sqrt n[0], _dont_ assume n normalized */ static GEN sqrtispec1_sh(GEN n, GEN *pr) { GEN S; ulong r, s, u0 = uel(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 = uel(n,0), u1 = uel(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) { set_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 = cgetg(2 + l, t_REAL); 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] = uel(x,2)>>1; xmpn_zero(b + l+1,l+1); b = sqrtispec(b, l+1, &c); xmpn_copy(res+2, b+2, l); u = uel(b,l+2); if ( u&HIGHBIT || (u == ~HIGHBIT && cmpii(c,b) > 0)) roundr_up_ip(res, l+2); } return gc_const((pari_sp)res, 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 = cgetg(l, t_REAL); pari_sp av, av0 = avma; a = rtor(x, lg2prec(l+1)); t = cgetg(l+1, t_REAL); if (ex & 1) { /* odd exponent */ a[1] = evalsigne(1) | _evalexpo(1); t[2] = (long)sqrtu2((ulong*)a + 2); } else { /* even exponent */ a[1] = evalsigne(1) | _evalexpo(0); t[2] = (long)sqrtu2_1((ulong*)a + 2); } t[1] = evalsigne(1) | _evalexpo(0); for (i = 3; i <= l; i++) t[i] = 0; /* |x| = 2^(ex/2) a, t ~ sqrt(a) */ l--; l1 = 1; av = avma; while (l1 < l) { /* let t := (t + a/t)/2 */ l1 <<= 1; if (l1 > l) l1 = l; setlg(a, l1 + 2); setlg(t, l1 + 2); affrr(addrr(t, divrr(a,t)), t); shiftr_inplace(t, -1); set_avma(av); } affrr(t,y); shiftr_inplace(y, (ex>>1)); return gc_const(av0, 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); set_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 && uel(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.17.2/src/kernel/none/halfgcd.c0000644000175000017500000002520214710152352015727 0ustar billbill#line 2 "../src/kernel/none/halfgcd.c" /* Copyright (C) 2019 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ GEN ZM2_sqr(GEN A) { GEN a = gcoeff(A,1,1), b = gcoeff(A,1,2), a2 = sqri(a); GEN c = gcoeff(A,2,1), d = gcoeff(A,2,2), d2 = sqri(d), t = addii(a,d); if (equalii(b, c)) /* symetric, 3S + 1M */ { GEN b2 = sqri(b), M = cgetg(3, t_MAT), tb = mulii(b, t); gel(M,1) = mkcol2(addii(a2, b2), tb); gel(M,2) = mkcol2(tb, addii(b2, d2)); return M; } else { /* general, 2S + 3M */ GEN bc = mulii(b, c); retmkmat2(mkcol2(addii(bc, a2), mulii(c, t)), mkcol2(mulii(b, t), addii(bc, d2))); } } GEN ZM2_mul(GEN A, GEN B) { const long t = ZM2_MUL_LIMIT+2; GEN A11=gcoeff(A,1,1),A12=gcoeff(A,1,2), B11=gcoeff(B,1,1),B12=gcoeff(B,1,2); GEN A21=gcoeff(A,2,1),A22=gcoeff(A,2,2), B21=gcoeff(B,2,1),B22=gcoeff(B,2,2); if (lgefint(A11) < t || lgefint(B11) < t || lgefint(A22) < t || lgefint(B22) < t || lgefint(A12) < t || lgefint(B12) < t || lgefint(A21) < t || lgefint(B21) < t) { /* 8M */ GEN a = mulii(A11, B11), b = mulii(A12, B21); GEN c = mulii(A11, B12), d = mulii(A12, B22); GEN e = mulii(A21, B11), f = mulii(A22, B21); GEN g = mulii(A21, B12), h = mulii(A22, B22); retmkmat2(mkcol2(addii(a,b), addii(e,f)), mkcol2(addii(c,d), addii(g,h))); } else { /* Strassen: 7M */ GEN M1 = mulii(addii(A11,A22), addii(B11,B22)); GEN M2 = mulii(addii(A21,A22), B11); GEN M3 = mulii(A11, subii(B12,B22)); GEN M4 = mulii(A22, subii(B21,B11)); GEN M5 = mulii(addii(A11,A12), B22); GEN M6 = mulii(subii(A21,A11), addii(B11,B12)); GEN M7 = mulii(subii(A12,A22), addii(B21,B22)); GEN T1 = addii(M1,M4), T2 = subii(M7,M5); GEN T3 = subii(M1,M2), T4 = addii(M3,M6); retmkmat2(mkcol2(addii(T1,T2), addii(M2,M4)), mkcol2(addii(M3,M5), addii(T3,T4))); } } static GEN matid2(void) { retmkmat2(mkcol2(gen_1,gen_0), mkcol2(gen_0,gen_1)); } /* Return M*[q,1;1,0] */ static GEN mulq(GEN M, GEN q) { GEN u, v, res = cgetg(3, t_MAT); u = addii(mulii(gcoeff(M,1,1), q), gcoeff(M,1,2)); v = addii(mulii(gcoeff(M,2,1), q), gcoeff(M,2,2)); gel(res,1) = mkcol2(u, v); gel(res,2) = gel(M,1); return res; } static GEN mulqab(GEN M, GEN q, GEN *ap, GEN *bp) { GEN b = subii(*ap, mulii(*bp, q)); *ap = *bp; *bp = b; return mulq(M,q); } /* Return M*[q,1;1,0]^-1 */ static GEN mulqi(GEN M, GEN q, GEN *ap, GEN *bp) { GEN u, v, res, a; a = addii(mulii(*ap, q), *bp); *bp = *ap; *ap = a; res = cgetg(3, t_MAT); u = subii(gcoeff(M,1,1),mulii(gcoeff(M,1,2), q)); v = subii(gcoeff(M,2,1),mulii(gcoeff(M,2,2), q)); gel(res,1) = gel(M,2); gel(res,2) = mkcol2(u,v); return res; } /* test whether n is a power of 2 */ static long isint2n(GEN n) { GEN x; long lx = lgefint(n), i; if (lx == 2) return 0; x = int_MSW(n); if (*(ulong*)x != 1UL<= m) { GEN r, q = dvmdii(*a, *b, &r); *a = *b; *b = r; M = mulq(M, q); cnt++; }; if (cnt>6) pari_err_BUG("FIXUP0"); return M; } static long signdet(GEN Q) { long a = Mod4(gcoeff(Q,1,1)), b = Mod4(gcoeff(Q,1,2)); long c = Mod4(gcoeff(Q,2,1)), d = Mod4(gcoeff(Q,2,2)); return ((a*d-b*c)&3)==1 ? 1 : -1; } static GEN ZM_inv2(GEN M) { long e = signdet(M); if (e==1) return mkmat22(gcoeff(M,2,2),negi(gcoeff(M,1,2)), negi(gcoeff(M,2,1)),gcoeff(M,1,1)); else return mkmat22(negi(gcoeff(M,2,2)),gcoeff(M,1,2), gcoeff(M,2,1),negi(gcoeff(M,1,1))); } static GEN lastq(GEN Q) { GEN p = gcoeff(Q,1,1), q = gcoeff(Q,1,2), s = gcoeff(Q,2,2); if (signe(q)==0) pari_err_BUG("halfgcd"); if (signe(s)==0) return p; if (equali1(q)) return subiu(p,1); return divii(p, q); } static GEN mulT(GEN Q, GEN *ap, GEN *bp) { *ap = addii(*ap, *bp); *bp = negi(*bp); return mkmat2(gel(Q,1), mkcol2(subii(gcoeff(Q,1,1), gcoeff(Q,1,2)) , subii(gcoeff(Q,2,1), gcoeff(Q,2,2)))); } static GEN FIXUP1(GEN M, GEN a, GEN b, long m, long t, GEN *ap, GEN *bp) { GEN Q = gel(M,1), a0 = gel(M,2), b0 = gel(M,3); GEN q, am = remi2n(a, m), bm = remi2n(b, m); if (signdet(Q)==-1) { *ap = subii(mulii(bm, gcoeff(Q,1,2)),mulii(am, gcoeff(Q,2,2))); *bp = subii(mulii(am, gcoeff(Q,2,1)),mulii(bm, gcoeff(Q,1,1))); *ap = addii(*ap, shifti(addii(a0, gcoeff(Q,2,2)), m)); *bp = addii(*bp, shifti(subii(b0, gcoeff(Q,2,1)), m)); if (signe(*bp) >= 0) return Q; if (expi(addii(*ap,*bp)) >= m+t) return mulT(Q, ap ,bp); q = lastq(Q); Q = mulqi(Q, q, ap, bp); if (cmpiu(q, 2)>=0) return mulqab(Q, subiu(q,1), ap, bp); else return mulqi(Q, lastq(Q), ap, bp); } else { *ap = subii(mulii(am, gcoeff(Q,2,2)),mulii(bm, gcoeff(Q,1,2))); *bp = subii(mulii(bm, gcoeff(Q,1,1)),mulii(am, gcoeff(Q,2,1))); *ap = addii(*ap, shifti(subii(a0, gcoeff(Q,2,2)), m)); *bp = addii(*bp, shifti(addii(b0, gcoeff(Q,2,1)), m)); if (expi(*ap) >= m+t) return FIXUP0(Q, ap, bp, m+t); else return signe(gcoeff(Q,1,2))==0? Q: mulqi(Q, lastq(Q), ap, bp); } } static long magic_threshold(GEN a) { return (3+uexpi(a))>>1; } static GEN HGCD_basecase(GEN y, GEN x) { pari_sp av = avma; GEN d, d1, q, r; GEN u, u1, v, v1; ulong xu, xu1, xv, xv1; /* Lehmer stage recurrence matrix */ int lhmres; /* Lehmer stage return value */ long m = magic_threshold(y); /* There is no special case for single-word numbers since this is * mainly meant to be used with large moduli. */ if (cmpii(y,x) <= 0) { d = x; d1 = y; u = gen_1; u1 = gen_0; v = gen_0; v1 = gen_1; } else { d = y; d1 = x; u = gen_0; u1 = gen_1; v = gen_1; v1 = gen_0; } while (lgefint(d) > 3 && expi(d1) >= m + BITS_IN_LONG + 1) { /* do a Lehmer-Jebelean round */ lhmres = lgcdii((ulong *)d, (ulong *)d1, &xu, &xu1, &xv, &xv1, 0); if (lhmres) { if (lhmres == 1 || lhmres == -1) { if (xv1 == 1) { r = subii(d,d1); d = d1; d1 = r; r = addii(u,u1); u = u1; u1 = r; r = addii(v,v1); v = v1; v1 = r; } else { r = subii(d, mului(xv1,d1)); d = d1; d1 = r; r = addii(u, mului(xv1,u1)); u = u1; u1 = 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(u,xu), muliu(u1,xv)); u1 = addii(muliu(u,xu1), muliu(u1,xv1)); u = r; r = addii(muliu(v,xu), muliu(v1,xv)); v1 = addii(muliu(v,xu1), muliu(v1,xv1)); v = r; if (lhmres&1) togglesign(d); else togglesign(d1); } } /* lhmres != 0 */ if (expi(d1) < m) break; if (lhmres <= 0 && signe(d1)) { q = dvmdii(d,d1,&r); d = d1; d1 = r; r = addii(u, mulii(q,u1)); u = u1; u1 = r; r = addii(v, mulii(q,v1)); v = v1; v1 = r; } if (gc_needed(av,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"ratlift"); gerepileall(av, 6, &d, &d1, &u, &u1, &v, &v1); } } while (expi(d1) >= m) { GEN r, q = dvmdii(d,d1, &r); d = d1; d1 = r; swap(u,u1); swap(v,v1); u1 = addii(mulii(u, q), u1); v1 = addii(mulii(v, q), v1); } return gerepilecopy(av, mkvec3(mkmat22(u1,u,v1,v), d, d1)); } static GEN HGCD(GEN x, GEN y); /* Based on Klaus Thull and Chee K. Yap, A unified approach to HGCD algorithms for polynomials andintegers, 1990, Manuscript. URL: http://cs.nyu.edu/cs/faculty/yap/papers. */ static GEN HGCD_split(GEN a, GEN b) { pari_sp av = avma; long m = magic_threshold(a), t, l, k, tp; GEN a0, b0, ap, bp, c, d, c0, d0, cp, dp, R, S, T, q, r; if (signe(b) < 0 || cmpii(a,b)<0) pari_err_BUG("HGCD_split"); if (expi(b) < m) return gerepilecopy(av, mkvec3(matid2(), a, b)); a0 = addiu(shifti(a, -m), 1); if (cmpiu(a0,7) <= 0) { R = FIXUP0(matid2(), &a, &b, m); return gerepilecopy(av, mkvec3(R, a, b)); } b0 = shifti(b,-m); t = magic_threshold(a0); R = FIXUP1(HGCD(a0,b0),a, b, m, t, &ap, &bp); if (expi(bp) < m) return gerepilecopy(av, mkvec3(R, ap, bp)); q = dvmdii(ap, bp, &r); c = bp; d = r; if (cmpiu(shifti(c,-m),6) <= 0) { R = FIXUP0(mulq(R, q), &c, &d, m); return gerepilecopy(av, mkvec3(R, c, d)); } l = uexpi(c); k = 2*m-l-1; if (k<0) pari_err_BUG("halfgcd"); c0 = addiu(shifti(c, -k), 1); if (cmpiu(c0,8)<0) pari_err_BUG("halfgcd"); d0 = shifti(d, -k); tp = magic_threshold(c0); S = FIXUP1(HGCD(c0,d0), c, d, k, tp, &cp, &dp); if (!(expi(cp)>=m+1 && m+1 > expi(dp))) pari_err_BUG("halfgcd"); T = FIXUP0(ZM2_mul(mulq(R, q), S), &cp, &dp, m); return gerepilecopy(av, mkvec3(T, cp, dp)); } static GEN HGCD(GEN x, GEN y) { if (lgefint(y)-2 < HALFGCD_LIMIT) return HGCD_basecase(x, y); else return HGCD_split(x, y); } static GEN HGCD0(GEN x, GEN y) { if (signe(y) >= 0 && cmpii(x, y) >= 0) return HGCD(x, y); if (cmpii(x, y) < 0) { GEN M = HGCD0(y, x), Q = gel(M,1); return mkvec3(mkmat22(gcoeff(Q,2,1),gcoeff(Q,2,2),gcoeff(Q,1,1),gcoeff(Q,1,2)), gel(M,2),gel(M,3)); } /* Now y <= x*/ if (signe(x) <= 0) { /* y <= x <=0 */ GEN M = HGCD(negi(y), negi(x)), Q = gel(M,1); return mkvec3(mkmat22(negi(gcoeff(Q,2,1)),negi(gcoeff(Q,2,2)), negi(gcoeff(Q,1,1)),negi(gcoeff(Q,1,2))), gel(M,2),gel(M,3)); } else /* y <= 0 <=x */ { GEN M = HGCD0(x, negi(y)), Q = gel(M,1); return mkvec3(mkmat22(gcoeff(Q,1,1),gcoeff(Q,1,2),negi(gcoeff(Q,2,1)),negi(gcoeff(Q,2,2))), gel(M,2),gel(M,3)); } } GEN halfgcdii(GEN A, GEN B) { pari_sp av = avma; GEN M, Q, a, b, m = abscmpii(A, B)>0 ? A: B; M = HGCD0(A,B); Q = gel(M,1); a = gel(M,2); b = gel(M,3); while (signe(b) && abscmpii(sqri(b), m) >= 0) { GEN r, q = dvmdii(a, b, &r); a = b; b = r; Q = mulq(Q, q); } return gerepilecopy(av, mkvec2(ZM_inv2(Q),mkcol2(a,b))); } pari-2.17.2/src/kernel/none/tune-gen.h0000644000175000017500000001054014676526175016110 0ustar billbill#ifdef PARI_TUNE long AGM_ATAN_LIMIT = __AGM_ATAN_LIMIT; long DIVRR_GMP_LIMIT = __DIVRR_GMP_LIMIT; long EXPNEWTON_LIMIT = __EXPNEWTON_LIMIT; long EXTGCD_HALFGCD_LIMIT = __EXTGCD_HALFGCD_LIMIT; long F2x_MUL_KARATSUBA_LIMIT = __F2x_MUL_KARATSUBA_LIMIT; long F2x_MUL_MULII_LIMIT = __F2x_MUL_MULII_LIMIT; long F2xqX_BARRETT_LIMIT = __F2xqX_BARRETT_LIMIT; long F2xqX_DIVREM_BARRETT_LIMIT = __F2xqX_DIVREM_BARRETT_LIMIT; long F2xqX_EXTGCD_LIMIT = __F2xqX_EXTGCD_LIMIT; long F2xqX_GCD_LIMIT = __F2xqX_GCD_LIMIT; long F2xqX_HALFGCD_LIMIT = __F2xqX_HALFGCD_LIMIT; long F2xqX_INVBARRETT_LIMIT = __F2xqX_INVBARRETT_LIMIT; long F2xqX_REM_BARRETT_LIMIT = __F2xqX_REM_BARRETT_LIMIT; long Flx_BARRETT2_LIMIT = __Flx_BARRETT2_LIMIT; long Flx_BARRETT_LIMIT = __Flx_BARRETT_LIMIT; long Flx_DIVREM2_BARRETT_LIMIT = __Flx_DIVREM2_BARRETT_LIMIT; long Flx_DIVREM_BARRETT_LIMIT = __Flx_DIVREM_BARRETT_LIMIT; long Flx_EXTGCD2_LIMIT = __Flx_EXTGCD2_LIMIT; long Flx_EXTGCD_LIMIT = __Flx_EXTGCD_LIMIT; long Flx_GCD2_LIMIT = __Flx_GCD2_LIMIT; long Flx_GCD_LIMIT = __Flx_GCD_LIMIT; long Flx_HALFGCD2_LIMIT = __Flx_HALFGCD2_LIMIT; long Flx_HALFGCD_LIMIT = __Flx_HALFGCD_LIMIT; long Flx_INVBARRETT2_LIMIT = __Flx_INVBARRETT2_LIMIT; long Flx_INVBARRETT_LIMIT = __Flx_INVBARRETT_LIMIT; long Flx_MUL2_KARATSUBA_LIMIT = __Flx_MUL2_KARATSUBA_LIMIT; long Flx_MUL2_MULII_LIMIT = __Flx_MUL2_MULII_LIMIT; long Flx_MUL_KARATSUBA_LIMIT = __Flx_MUL_KARATSUBA_LIMIT; long Flx_MUL_MULII_LIMIT = __Flx_MUL_MULII_LIMIT; long Flx_REM2_BARRETT_LIMIT = __Flx_REM2_BARRETT_LIMIT; long Flx_REM_BARRETT_LIMIT = __Flx_REM_BARRETT_LIMIT; long Flx_SQR2_KARATSUBA_LIMIT = __Flx_SQR2_KARATSUBA_LIMIT; long Flx_SQR2_SQRI_LIMIT = __Flx_SQR2_SQRI_LIMIT; long Flx_SQR_KARATSUBA_LIMIT = __Flx_SQR_KARATSUBA_LIMIT; long Flx_SQR_SQRI_LIMIT = __Flx_SQR_SQRI_LIMIT; long FlxqX_BARRETT_LIMIT = __FlxqX_BARRETT_LIMIT; long FlxqX_DIVREM_BARRETT_LIMIT = __FlxqX_DIVREM_BARRETT_LIMIT; long FlxqX_EXTGCD_LIMIT = __FlxqX_EXTGCD_LIMIT; long FlxqX_GCD_LIMIT = __FlxqX_GCD_LIMIT; long FlxqX_HALFGCD_LIMIT = __FlxqX_HALFGCD_LIMIT; long FlxqX_INVBARRETT_LIMIT = __FlxqX_INVBARRETT_LIMIT; long FlxqX_REM_BARRETT_LIMIT = __FlxqX_REM_BARRETT_LIMIT; long FpXQX_BARRETT_LIMIT = __FpXQX_BARRETT_LIMIT; long FpXQX_DIVREM_BARRETT_LIMIT = __FpXQX_DIVREM_BARRETT_LIMIT; long FpXQX_EXTGCD_LIMIT = __FpXQX_EXTGCD_LIMIT; long FpXQX_GCD_LIMIT = __FpXQX_GCD_LIMIT; long FpXQX_HALFGCD_LIMIT = __FpXQX_HALFGCD_LIMIT; long FpXQX_INVBARRETT_LIMIT = __FpXQX_INVBARRETT_LIMIT; long FpXQX_REM_BARRETT_LIMIT = __FpXQX_REM_BARRETT_LIMIT; long FpX_BARRETT_LIMIT = __FpX_BARRETT_LIMIT; long FpX_DIVREM_BARRETT_LIMIT = __FpX_DIVREM_BARRETT_LIMIT; long FpX_EXTGCD_LIMIT = __FpX_EXTGCD_LIMIT; long FpX_GCD_LIMIT = __FpX_GCD_LIMIT; long FpX_HALFGCD_LIMIT = __FpX_HALFGCD_LIMIT; long FpX_INVBARRETT_LIMIT = __FpX_INVBARRETT_LIMIT; long FpX_REM_BARRETT_LIMIT = __FpX_REM_BARRETT_LIMIT; long Fp_POW_BARRETT_LIMIT = __Fp_POW_BARRETT_LIMIT; long Fp_POW_REDC_LIMIT = __Fp_POW_REDC_LIMIT; long GCD_HALFGCD_LIMIT = __GCD_HALFGCD_LIMIT; long HALFGCD_LIMIT = __HALFGCD_LIMIT; long INVMOD_GMP_LIMIT = __INVMOD_GMP_LIMIT; long INVNEWTON_LIMIT = __INVNEWTON_LIMIT; long LOGAGMCX_LIMIT = __LOGAGMCX_LIMIT; long LOGAGM_LIMIT = __LOGAGM_LIMIT; long MULII_FFT_LIMIT = __MULII_FFT_LIMIT; long MULII_KARATSUBA_LIMIT = __MULII_KARATSUBA_LIMIT; long MULRR_MULII_LIMIT = __MULRR_MULII_LIMIT; long RgX_MUL_LIMIT = __RgX_MUL_LIMIT; long RgX_SQR_LIMIT = __RgX_SQR_LIMIT; long SQRI_FFT_LIMIT = __SQRI_FFT_LIMIT; long SQRI_KARATSUBA_LIMIT = __SQRI_KARATSUBA_LIMIT; long SQRR_SQRI_LIMIT = __SQRR_SQRI_LIMIT; long ZM2_MUL_LIMIT = __ZM2_MUL_LIMIT; #endif pari-2.17.2/src/kernel/none/bfffo.h0000644000175000017500000000403714567450071015442 0ustar billbill#line 2 "../src/kernel/none/bfffo.h" /* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #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.17.2/src/kernel/none/ratlift.c0000644000175000017500000002640114676526175016031 0ustar billbill#line 2 "../src/kernel/none/ratlift.c" /* Copyright (C) 2003 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /*========================================================== * Fp_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 */ 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 */ } return vmax; } /* assume bmax <= sqrt(m), fast if amax <=sqrt(m) */ static int Fp_ratlift_hgcd(GEN n, GEN m, GEN amax, GEN bmax, GEN *pa, GEN *pb) { pari_sp av = avma; GEN x, y, a, b; GEN H = halfgcdii(n, m), M = gel(H,1), V = gel(H,2); x = gel(V,1); a = gel(V,2); y = gcoeff(M,1,1); b = gcoeff(M,2,1); while(abscmpii(b, bmax)<=0) { GEN q, r, u; if (abscmpii(a, amax)<=0) { if (signe(b)<0) { a = negi(a); b = negi(b); } *pa =a; *pb = b; gerepileall(av, 2, pb, pa); return 1; } q = dvmdii(x, a, &r); x = a; a = r; u = subii(y, mulii(b, q)); y = b; b = u; } return gc_bool(av, 0); } /* 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; 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; } if (amax == bmax || equalii(amax, bmax)) return Fp_ratlift_hgcd(x, m, amax, bmax, a, b); /* 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; /* 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=ULONG_MAX. 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) return gc_long(av, 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) { set_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 */ set_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); 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) return gc_long(av, 0); /* done, not found */ if (cmpii(d1,amax) <= 0) /* done, found */ { set_avma(av); if (signe(d1)) { *a = icopy(d1); setsigne(*a,s); } else *a = gen_0; *b = icopy(v1); return 1; } } if (gc_needed(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 */ r = addii(v,v1); if (cmpii(r,bmax) > 0) return gc_long(av, 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); 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) { set_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 */ set_avma(av); if (signe(d1)) { *a = icopy(d1); setsigne(*a,s); } else *a = gen_0; *b = icopy(v1); return 1; } } /* while */ /* We have run into d1 == 0 before returning. This cannot happen */ pari_err_BUG("ratlift failed to catch d1 == 0"); return 0; /* LCOV_EXCL_LINE */ } pari-2.17.2/src/kernel/none/int.h0000644000175000017500000000271714567450071015155 0ustar billbill#line 2 "../src/kernel/none/int.h" /* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #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.17.2/src/kernel/none/level1.h0000644000175000017500000011572514676526175015571 0ustar billbill#line 2 "../src/kernel/none/level1.h" /* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* 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 nbits2lg(long x) { return (long)(((ulong)x+3*BITS_IN_LONG-1) >> TWOPOTBITS_IN_LONG); } INLINE long lg2prec(long x){ return (x-2) * BITS_IN_LONG; } INLINE long evallg(long x) { if (x & ~LGBITS) pari_err_OVERFLOW("lg()"); return _evallg(x); } INLINE long evalvalp(long x) { long v = _evalvalp(x); if (v & ~VALPBITS) pari_err_OVERFLOW("valp()"); return v; } INLINE long evalvalser(long x) { long v = _evalvalser(x); if (v & ~VALSERBITS) pari_err_OVERFLOW("valser()"); return v; } INLINE long evalexpo(long x) { long v = _evalexpo(x); if (v & ~EXPOBITS) pari_err_OVERFLOW("expo()"); return v; } INLINE long evalprecp(long x) { long v = _evalprecp(x); if (x & ~((1UL<<(BITS_IN_LONG-VALPnumBITS))-1)) pari_err_OVERFLOW("precp()"); return v; } INLINE int varncmp(long x, long y) { if (varpriority[x] < varpriority[y]) return 1; if (varpriority[x] > varpriority[y]) return -1; return 0; } INLINE long varnmin(long x, long y) { return (varpriority[x] <= varpriority[y])? x: y; } INLINE long varnmax(long x, long y) { return (varpriority[x] >= varpriority[y])? x: y; } /* 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 ulong get_avma(void) { return avma; } INLINE void set_avma(ulong av) { avma = av; } INLINE double gc_double(pari_sp av, double d) { set_avma(av); return d; } INLINE long gc_long(pari_sp av, long s) { set_avma(av); return s; } INLINE ulong gc_ulong(pari_sp av, ulong s) { set_avma(av); return s; } INLINE int gc_bool(pari_sp av, int s) { set_avma(av); return s; } INLINE int gc_int(pari_sp av, int s) { set_avma(av); return s; } INLINE GEN gc_NULL(pari_sp av) { set_avma(av); return NULL; } INLINE GEN gc_const(pari_sp av, GEN x) { set_avma(av); return x; } INLINE GEN gc_stoi(pari_sp av, long x) { set_avma(av); return stoi(x); } INLINE GEN gc_utoi(pari_sp av, ulong x) { set_avma(av); return utoi(x); } INLINE GEN gc_utoipos(pari_sp av, ulong x) { set_avma(av); return utoipos(x); } INLINE GEN new_chunk(size_t x) /* x is a number of longs */ { GEN z = ((GEN) avma) - x; CHECK_CTRLC if (x > (avma-pari_mainstack->bot) / sizeof(long)) new_chunk_resize(x); set_avma((pari_sp)z); #ifdef MEMSTEP if (DEBUGMEM>1 && pari_mainstack->memused != DISABLE_MEMUSED) { long d = (long)pari_mainstack->memused - (long)z; if (labs(d) > 4*MEMSTEP) { pari_mainstack->memused = (pari_sp)z; err_printf("...%4.0lf Mbytes used\n", (pari_mainstack->top-pari_mainstack->memused)/1048576.); } } #endif return z; } INLINE char * stack_malloc(size_t N) { long n = nchar2nlong(N); return (char*)new_chunk(n); } INLINE char * stack_malloc_align(size_t N, long k) { ulong d = ((ulong)avma) % k, e = ((ulong)N) % k; if (d) (void)new_chunk(d/sizeof(long)); if (e) N += k-e; return (char*) new_chunk(nchar2nlong(N)); } INLINE char * stack_calloc(size_t N) { char *p = stack_malloc(N); memset(p, 0, N); return p; } INLINE char * stack_calloc_align(size_t N, long k) { ulong d = ((ulong)avma) % k, e = ((ulong)N) % k; if (d) (void)new_chunk(d/sizeof(long)); if (e) N += k-e; return stack_calloc(N); } /* cgetg(lg(x), typ(x)), set *lx. Implicit unsetisclone() */ INLINE GEN cgetg_copy(GEN x, long *plx) { GEN y; *plx = lg(x); y = new_chunk((size_t)*plx); y[0] = x[0] & (TYPBITS|LGBITS); return y; } INLINE GEN cgetg_block(long x, long y) { GEN z = newblock((size_t)x); z[0] = CLONEBIT | evaltyp(y) | evallg(x); return z; } INLINE GEN cgetg(long x, long y) { GEN z = new_chunk((size_t)x); z[0] = evaltyp(y) | evallg(x); return z; } INLINE GEN cgeti(long x) { GEN z = new_chunk((size_t)x); z[0] = evaltyp(t_INT) | evallg(x); return z; } INLINE GEN cgetipos(long x) { GEN z = cgeti(x); z[1] = evalsigne(1) | evallgefint(x); return z; } INLINE GEN cgetineg(long x) { GEN z = cgeti(x); z[1] = evalsigne(-1) | evallgefint(x); return z; } INLINE GEN cgetr_block(long x) { long l = nbits2lg(x); GEN z = newblock((size_t)l); z[0] = CLONEBIT | evaltyp(t_REAL) | evallg(l); return z; } INLINE GEN cgetr(long x) { long l = nbits2lg(x); GEN z = new_chunk((size_t)l); z[0] = evaltyp(t_REAL) | evallg(l); return z; } /*******************************************************************/ /* */ /* COPY, NEGATION, ABSOLUTE VALUE */ /* */ /*******************************************************************/ /* cannot do memcpy because sometimes x and y overlap */ INLINE GEN leafcopy(GEN x) { long lx = lg(x); GEN y = new_chunk(lx); /* can't use cgetg_copy, in case x,y overlap */ while (--lx > 0) y[lx] = x[lx]; y[0] = x[0] & (TYPBITS|LGBITS); return y; } INLINE GEN icopy(GEN x) { long i = lgefint(x), lx = i; GEN y = new_chunk(lx); /* can't use cgeti, in case x,y overlap */ while (--i > 0) y[i] = x[i]; y[0] = evaltyp(t_INT) | evallg(lx); return y; } INLINE GEN icopyspec(GEN x, long nx) { long i = nx+2, lx = i; GEN y = new_chunk(lx); /* can't use cgeti, in case x,y overlap */ x -= 2; while (--i >= 2) y[i] = x[i]; y[1] = evalsigne(1) | evallgefint(lx); y[0] = evaltyp(t_INT) | evallg(lx); return y; } INLINE GEN rcopy(GEN x) { return leafcopy(x); } INLINE GEN mpcopy(GEN x) { return leafcopy(x); } INLINE GEN mpabs(GEN x) { GEN y = leafcopy(x); setabssign(y); return y; } INLINE GEN mpabs_shallow(GEN x) { return signe(x) < 0? mpabs(x): x; } INLINE GEN absi(GEN x) { return mpabs(x); } INLINE GEN absi_shallow(GEN x) { return signe(x) < 0? negi(x): x; } INLINE GEN absr(GEN x) { return mpabs(x); } INLINE GEN mpneg(GEN x) { GEN y = leafcopy(x); togglesign(y); return y; } INLINE GEN negi(GEN x) { return mpneg(x); } INLINE GEN negr(GEN x) { return mpneg(x); } /* negate in place */ INLINE void togglesign(GEN x) { if (x[1] & SIGNBITS) { x[1] ^= HIGHBIT; } } INLINE void setabssign(GEN x) { x[1] &= ~HIGHBIT; } /* negate in place, except universal constants */ INLINE void togglesign_safe(GEN *px) { switch(*px - gen_1) /* gen_1, gen_2, gen_m1, gen_m2 */ { case 0: *px = gen_m1; break; case 3: *px = gen_m2; break; case 6: *px = gen_1; break; case 9: *px = gen_2; break; default: togglesign(*px); } } /* setsigne(y, signe(x)) */ INLINE void affectsign(GEN x, GEN y) { y[1] = (x[1] & SIGNBITS) | (y[1] & ~SIGNBITS); } /* copies sign in place, except for universal constants */ INLINE void affectsign_safe(GEN x, GEN *py) { if (((*py)[1] ^ x[1]) & HIGHBIT) togglesign_safe(py); } /*******************************************************************/ /* */ /* GEN -> LONG, LONG -> GEN */ /* */ /*******************************************************************/ /* assume x != 0, return -x as a t_INT */ INLINE GEN utoineg(ulong x) { GEN y = cgetineg(3); y[2] = x; return y; } /* assume x != 0, return utoi(x) */ INLINE GEN utoipos(ulong x) { GEN y = cgetipos(3); y[2] = x; return y; } INLINE GEN utoi(ulong x) { return x? utoipos(x): gen_0; } INLINE GEN stoi(long x) { if (!x) return gen_0; return x > 0? utoipos((ulong)x): utoineg((ulong)-x); } /* x 2^BIL + y */ INLINE GEN uutoi(ulong x, ulong y) { GEN z; if (!x) return utoi(y); z = cgetipos(4); *int_W_lg(z, 1, 4) = x; *int_W_lg(z, 0, 4) = y; return z; } /* - (x 2^BIL + y) */ INLINE GEN uutoineg(ulong x, ulong y) { GEN z; if (!x) return y? utoineg(y): gen_0; z = cgetineg(4); *int_W_lg(z, 1, 4) = x; *int_W_lg(z, 0, 4) = y; return z; } INLINE long itos(GEN x) { long s = signe(x); long u; if (!s) return 0; u = x[2]; if (lgefint(x) > 3 || u < 0) pari_err_OVERFLOW("t_INT-->long assignment"); return (s>0) ? u : -u; } /* as itos, but return 0 if too large. Cf is_bigint */ INLINE long itos_or_0(GEN x) { long n; if (lgefint(x) != 3 || (n = x[2]) & HIGHBIT) return 0; return signe(x) > 0? n: -n; } INLINE ulong itou(GEN x) { switch(lgefint(x)) { case 2: return 0; case 3: return x[2]; default: pari_err_OVERFLOW("t_INT-->ulong assignment"); return 0; /* LCOV_EXCL_LINE */ } } /* 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 ulong umuluu_or_0(ulong x, ulong y) { ulong z; LOCAL_HIREMAINDER; z = mulll(x, y); return hiremainder? 0: z; } /* return x*y if <= n, else 0. Beware overflow */ INLINE ulong umuluu_le(ulong x, ulong y, ulong n) { ulong z; LOCAL_HIREMAINDER; z = mulll(x, y); return (hiremainder || z > n)? 0: z; } INLINE GEN real_0_bit(long bitprec) { GEN x=cgetg(2, t_REAL); x[1]=evalexpo(bitprec); return x; } INLINE GEN real_0(long prec) { return real_0_bit(-prec); } INLINE GEN real_1_bit(long bit) { return real_1(nbits2prec(bit)); } INLINE GEN real_1(long prec) { GEN x = cgetr(prec); long i, l = lg(x); x[1] = evalsigne(1) | _evalexpo(0); x[2] = (long)HIGHBIT; for (i=3; i> r) & 1UL:0; } /*******************************************************************/ /* */ /* COMPARISON */ /* */ /*******************************************************************/ INLINE int cmpss(long a, long b) { return a>b? 1: (ab? 1: (a= expi(x)) return 0; return signe(x); } av=avma; z = itor(x, realprec(y)); set_avma(av); return cmprr(z,y); /* cmprr does no memory adjustment */ } INLINE int cmpri(GEN x, GEN y) { return -cmpir(y,x); } INLINE int cmpsr(long x, GEN y) { pari_sp av; GEN z; if (!x) return -signe(y); av=avma; z = stor(x, LOWDEFAULTPREC); set_avma(av); return cmprr(z,y); } INLINE int cmprs(GEN x, long y) { return -cmpsr(y,x); } /* compare x and y */ INLINE int cmpui(ulong x, GEN y) { ulong p; if (!x) return -signe(y); if (signe(y) <= 0) return 1; if (lgefint(y) > 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); } /* compare x and |y| */ INLINE int abscmpui(ulong x, GEN y) { long l = lgefint(y); ulong p; if (!x) return (l > 2)? -1: 0; if (l == 2) return 1; if (l > 3) return -1; p = y[2]; if (p == x) return 0; return p < x ? 1 : -1; } INLINE int abscmpiu(GEN x, ulong y) { return -abscmpui(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 equalui(ulong x, GEN y) { if (!x) return !signe(y); if (signe(y) <= 0 || lgefint(y) != 3) return 0; return ((ulong)y[2] == (ulong)x); } /* 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 absequalui(ulong x, GEN y) { if (!x) return !signe(y); return (lgefint(y) == 3 && (ulong)y[2] == x); } INLINE int absequaliu(GEN x, ulong y) { return absequalui(y,x); } INLINE int equalis(GEN x, long y) { return equalsi(y,x); } INLINE int equaliu(GEN x, ulong y) { return equalui(y,x); } /* assume x != 0, is |x| == 2^n ? */ INLINE int absrnz_equal2n(GEN x) { if ((ulong)x[2]==HIGHBIT) { long i, lx = lg(x); for (i = 3; i < lx; i++) if (x[i]) return 0; return 1; } return 0; } /* assume x != 0, is |x| == 1 ? */ INLINE int absrnz_equal1(GEN x) { return !expo(x) && absrnz_equal2n(x); } INLINE long maxss(long x, long y) { return x>y?x:y; } INLINE long minss(long x, long y) { return xy?x:y; } INLINE double maxdd(double x, double y) { return x>y?x:y; } INLINE double mindd(double x, double y) { return x 0) return y > 0? adduu(x,y): subuu(x, -y); if (y > 0) return subuu(y, -x); else { /* - adduu(-x, -y) */ ulong t = (-x)+(-y); return uutoineg((t < (ulong)(-x)), t); } } INLINE GEN subss(long x, long y) { return addss(-y,x); } INLINE GEN subii(GEN x, GEN y) { if (x==y) return gen_0; /* frequent with x = y = gen_0 */ return addii_sign(x, signe(x), y, -signe(y)); } INLINE GEN addii(GEN x, GEN y) { return addii_sign(x, signe(x), y, signe(y)); } INLINE GEN addrr(GEN x, GEN y) { return addrr_sign(x, signe(x), y, signe(y)); } INLINE GEN subrr(GEN x, GEN y) { return addrr_sign(x, signe(x), y, -signe(y)); } INLINE GEN addir(GEN x, GEN y) { return addir_sign(x, signe(x), y, signe(y)); } INLINE GEN subir(GEN x, GEN y) { return addir_sign(x, signe(x), y, -signe(y)); } INLINE GEN subri(GEN x, GEN y) { return addir_sign(y, -signe(y), x, signe(x)); } INLINE GEN addsi(long x, GEN y) { return addsi_sign(x, y, signe(y)); } INLINE GEN addui(ulong x, GEN y) { return addui_sign(x, y, signe(y)); } INLINE GEN subsi(long x, GEN y) { return addsi_sign(x, y, -signe(y)); } INLINE GEN subui(ulong x, GEN y) { return addui_sign(x, y, -signe(y)); } /*******************************************************************/ /* */ /* MOD, REM, DIV */ /* */ /*******************************************************************/ INLINE ulong mod2BIL(GEN x) { return *int_LSW(x); } INLINE long mod64(GEN x) { return mod2BIL(x) & 63; } INLINE long mod32(GEN x) { return mod2BIL(x) & 31; } INLINE long mod16(GEN x) { return mod2BIL(x) & 15; } INLINE long mod8(GEN x) { return mod2BIL(x) & 7; } INLINE long mod4(GEN x) { return mod2BIL(x) & 3; } INLINE long mod2(GEN x) { return mod2BIL(x) & 1; } INLINE int mpodd(GEN x) { return signe(x) && mod2(x); } /* x mod 2^n, n < BITS_IN_LONG */ INLINE ulong umodi2n(GEN x, long n) { long s = signe(x); const ulong _2n = 1UL << n; ulong m; if (!s) return 0; m = *int_LSW(x) & (_2n - 1); if (s < 0 && m) m = _2n - m; return m; } INLINE ulong Mod64(GEN x){ return umodi2n(x,6); } INLINE ulong Mod32(GEN x){ return umodi2n(x,5); } INLINE ulong Mod16(GEN x){ return umodi2n(x,4); } INLINE ulong Mod8(GEN x) { return umodi2n(x,3); } INLINE ulong Mod4(GEN x) { return umodi2n(x,2); } INLINE ulong Mod2(GEN x) { return umodi2n(x,1); } 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 utoi(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 ulong umodsu(long x, ulong y) { return x>=0 ? x%y: Fl_neg((-x)%y, y); } INLINE long sdivss_rem(long x, long y, long *r) { long q; LOCAL_HIREMAINDER; if (!y) pari_err_INV("sdivss_rem",gen_0); hiremainder = 0; q = divll((ulong)labs(x),(ulong)labs(y)); if (x < 0) { hiremainder = -((long)hiremainder); q = -q; } if (y < 0) q = -q; *r = hiremainder; return q; } INLINE GEN divss_rem(long x, long y, long *r) { return stoi(sdivss_rem(x,y,r)); } INLINE ulong udivuu_rem(ulong x, ulong y, ulong *r) { if (!y) pari_err_INV("udivuu_rem",gen_0); *r = x % y; return x / y; } INLINE ulong ceildivuu(ulong a, ulong b) { ulong c; if (!a) return 0; c = a / b; return (a % b)? c+1: c; } INLINE ulong uabsdivui_rem(ulong x, GEN y, ulong *r) { long q, s = signe(y); LOCAL_HIREMAINDER; if (!s) pari_err_INV("uabsdivui_rem",gen_0); if (!x || lgefint(y)>3) { *r = x; return 0; } hiremainder=0; q = (long)divll(x, (ulong)y[2]); if (s < 0) q = -q; *r = hiremainder; return q; } /* assume d != 0 and |n| / d can be represented as an ulong. * Return |n|/d, set *r = |n| % d */ INLINE ulong uabsdiviu_rem(GEN n, ulong d, ulong *r) { switch(lgefint(n)) { case 2: *r = 0; return 0; case 3: { ulong nn = n[2]; *r = nn % d; return nn / d; } default: /* 4 */ { ulong n1, n0, q; LOCAL_HIREMAINDER; n0 = *int_W(n,0); n1 = *int_W(n,1); hiremainder = n1; q = divll(n0, d); *r = hiremainder; return q; } } } INLINE long sdivsi_rem(long x, GEN y, long *r) { long q, s = signe(y); LOCAL_HIREMAINDER; if (!s) pari_err_INV("sdivsi_rem",gen_0); if (!x || lgefint(y)>3 || ((long)y[2]) < 0) { *r = x; return 0; } hiremainder=0; q = (long)divll(labs(x), (ulong)y[2]); if (x < 0) { hiremainder = -((long)hiremainder); q = -q; } if (s < 0) q = -q; *r = hiremainder; return q; } INLINE GEN divsi_rem(long s, GEN y, long *r) { return stoi(sdivsi_rem(s,y,r)); } INLINE long sdivsi(long x, GEN y) { long q, s = signe(y); if (!s) pari_err_INV("sdivsi",gen_0); if (!x || lgefint(y)>3 || ((long)y[2]) < 0) return 0; q = labs(x) / y[2]; if (x < 0) q = -q; if (s < 0) q = -q; return q; } INLINE GEN dvmdss(long x, long y, GEN *z) { long r; GEN q = divss_rem(x,y, &r); *z = stoi(r); return q; } INLINE long dvmdsBIL(long n, long *r) { *r = remsBIL(n); return divsBIL(n); } INLINE ulong dvmduBIL(ulong n, ulong *r) { *r = remsBIL(n); return divsBIL(n); } INLINE GEN dvmdsi(long x, GEN y, GEN *z) { long r; GEN q = divsi_rem(x,y, &r); *z = stoi(r); return q; } INLINE GEN dvmdis(GEN x, long y, GEN *z) { long r; GEN q = divis_rem(x,y, &r); *z = stoi(r); return q; } INLINE long smodis(GEN x, long y) { pari_sp av = avma; long r; (void)divis_rem(x,y, &r); return gc_long(av, (r >= 0)? r: labs(y) + r); } INLINE GEN modis(GEN x, long y) { return stoi(smodis(x,y)); } INLINE GEN modsi(long x, GEN y) { long r; (void)sdivsi_rem(x, y, &r); return (r >= 0)? stoi(r): addsi_sign(r, y, 1); } INLINE ulong umodui(ulong x, GEN y) { if (!signe(y)) pari_err_INV("umodui",gen_0); if (!x || lgefint(y) > 3) return x; return x % (ulong)y[2]; } INLINE ulong ugcdiu(GEN x, ulong y) { return ugcd(umodiu(x,y), y); } INLINE ulong ugcdui(ulong y, GEN x) { return ugcd(umodiu(x,y), y); } 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); return gc_stoi(av, 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); set_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); set_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); set_avma(av); return z; } INLINE void rdiviiz(GEN x, GEN y, GEN z) { long lz = lg(z), lx = lgefint(x), ly = lgefint(y); if (lx == 2) { affur(0, z); return; } if (ly == 3) { affir(x, z); if (signe(y) < 0) togglesign(z); affrr(divru(z, y[2]), z); } else if (lx > lz + 1 || ly > lz + 1) { affir(x,z); affrr(divri(z, y), z); } else { long b = lg2prec(lz) + expi(y) - expi(x) + 1; GEN q = divii(b > 0? shifti(x, b): x, y); affir(q, z); if (b > 0) shiftr_inplace(z, -b); } set_avma((ulong)z); } INLINE GEN rdivii(GEN x, GEN y, long prec) { GEN z = cgetr(prec); rdiviiz(x, y, z); 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; if (!signe(x)) return 1; if (!signe(y)) return 0; r = remii(x,y); return gc_bool(av, r == gen_0); } INLINE int dvdsi(long x, GEN y) { if (x == 0) return 1; if (!signe(y)) return 0; if (lgefint(y) != 3) return 0; return x % y[2] == 0; } INLINE int dvdui(ulong x, GEN y) { if (x == 0) return 1; if (!signe(y)) return 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); set_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 = absdiviu_rem(x,y, &r); set_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, p1 = dvmdii(x,y,&p2); if (signe(p2)) return gc_bool(av,0); affii(p1,z); return gc_bool(av,1); } INLINE ulong remlll_pre(ulong u2, ulong u1, ulong u0, ulong n, ulong ninv) { u1 = remll_pre(u2, u1, n, ninv); return remll_pre(u1, u0, n, ninv); } INLINE ulong Fl_sqr_pre(ulong a, ulong p, ulong pi) { ulong x; LOCAL_HIREMAINDER; x = mulll(a,a); return remll_pre(hiremainder, x, p, pi); } INLINE ulong Fl_mul_pre(ulong a, ulong b, ulong p, ulong pi) { ulong x; LOCAL_HIREMAINDER; x = mulll(a,b); return remll_pre(hiremainder, x, p, pi); } INLINE ulong Fl_addmul_pre(ulong y0, ulong x0, ulong x1, ulong p, ulong pi) { ulong l0, h0; LOCAL_HIREMAINDER; hiremainder = y0; l0 = addmul(x0, x1); h0 = hiremainder; return remll_pre(h0, l0, p, pi); } INLINE ulong Fl_addmulmul_pre(ulong x0, ulong y0, ulong x1, ulong y1, ulong p, ulong pi) { ulong l0, l1, h0, h1; LOCAL_OVERFLOW; LOCAL_HIREMAINDER; l0 = mulll(x0, y0); h0 = hiremainder; l1 = mulll(x1, y1); h1 = hiremainder; l0 = addll(l0, l1); h0 = addllx(h0, h1); return overflow ? remlll_pre(1, h0, l0, p, pi): remll_pre(h0, l0, p, pi); } INLINE ulong Fl_ellj_pre(ulong a4, ulong a6, ulong p, ulong pi) { /* a43 = 4 a4^3 */ ulong a43 = Fl_double(Fl_double( Fl_mul_pre(a4, Fl_sqr_pre(a4, p, pi), p, pi), p), p); /* a62 = 27 a6^2 */ ulong a62 = Fl_mul_pre(Fl_sqr_pre(a6, p, pi), 27 % p, p, pi); ulong z1 = Fl_mul_pre(a43, 1728 % p, p, pi); ulong z2 = Fl_add(a43, a62, p); return Fl_div(z1, z2, p); } /*******************************************************************/ /* */ /* MP (INT OR REAL) */ /* */ /*******************************************************************/ INLINE GEN mptrunc(GEN x) { return typ(x)==t_INT? icopy(x): truncr(x); } INLINE GEN mpfloor(GEN x) { return typ(x)==t_INT? icopy(x): floorr(x); } INLINE GEN mpceil(GEN x) { return typ(x)==t_INT? icopy(x): ceilr(x); } INLINE GEN mpround(GEN x) { return typ(x) == t_INT? icopy(x): roundr(x); } INLINE long mpexpo(GEN x) { return typ(x) == t_INT? expi(x): expo(x); } INLINE GEN mpadd(GEN x, GEN y) { if (typ(x)==t_INT) return (typ(y)==t_INT) ? addii(x,y) : addir(x,y); return (typ(y)==t_INT) ? addir(y,x) : addrr(x,y); } INLINE GEN mpsub(GEN x, GEN y) { if (typ(x)==t_INT) return (typ(y)==t_INT) ? subii(x,y) : subir(x,y); return (typ(y)==t_INT) ? subri(x,y) : subrr(x,y); } INLINE GEN mpmul(GEN x, GEN y) { if (typ(x)==t_INT) return (typ(y)==t_INT) ? mulii(x,y) : mulir(x,y); return (typ(y)==t_INT) ? mulir(y,x) : mulrr(x,y); } INLINE GEN mpsqr(GEN x) { return (typ(x)==t_INT) ? sqri(x) : sqrr(x); } INLINE GEN mpdiv(GEN x, GEN y) { if (typ(x)==t_INT) return (typ(y)==t_INT) ? divii(x,y) : divir(x,y); return (typ(y)==t_INT) ? divri(x,y) : divrr(x,y); } /*******************************************************************/ /* */ /* Z/nZ, n ULONG */ /* */ /*******************************************************************/ INLINE ulong Fl_double(ulong a, ulong p) { ulong res = a << 1; return (res >= p || res < a) ? res - p : res; } INLINE ulong Fl_triple(ulong a, ulong p) { ulong res = a << 1; if (res >= p || res < a) res -= p; res += a; return (res >= p || res < a)? res - p: res; } INLINE ulong Fl_halve(ulong a, ulong p) { ulong ap, ap2; if ((a&1UL)==0) return a>>1; ap = a + p; ap2 = ap>>1; return ap>=a ? ap2: (ap2|HIGHBIT); } INLINE ulong Fl_add(ulong a, ulong b, ulong p) { ulong res = a + b; 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) { ulong x; LOCAL_HIREMAINDER; x = mulll(a,b); if (!hiremainder) return x % p; (void)divll(x,p); return hiremainder; } INLINE ulong Fl_sqr(ulong a, ulong p) { ulong x; LOCAL_HIREMAINDER; x = mulll(a,a); if (!hiremainder) return x % p; (void)divll(x,p); return hiremainder; } /* don't assume that p is prime: can't special case a = 0 */ INLINE ulong Fl_div(ulong a, ulong b, ulong p) { return Fl_mul(a, Fl_inv(b, p), p); } /*******************************************************************/ /* */ /* DEFINED FROM EXISTING ONE EXPLOITING COMMUTATIVITY */ /* */ /*******************************************************************/ INLINE GEN addri(GEN x, GEN y) { return addir(y,x); } INLINE GEN addis(GEN x, long s) { return addsi(s,x); } INLINE GEN addiu(GEN x, ulong s) { return addui(s,x); } INLINE GEN addrs(GEN x, long s) { return addsr(s,x); } INLINE GEN subiu(GEN x, long y) { GEN z = subui(y, x); togglesign(z); return z; } INLINE GEN subis(GEN x, long y) { return addsi(-y,x); } INLINE GEN subrs(GEN x, long y) { return addsr(-y,x); } INLINE GEN mulis(GEN x, long s) { return mulsi(s,x); } INLINE GEN muliu(GEN x, ulong s) { return mului(s,x); } INLINE GEN mulru(GEN x, ulong s) { return mulur(s,x); } INLINE GEN mulri(GEN x, GEN s) { return mulir(s,x); } INLINE GEN mulrs(GEN x, long s) { return mulsr(s,x); } /*******************************************************************/ /* */ /* VALUATION, EXPONENT, SHIFTS */ /* */ /*******************************************************************/ INLINE long vali(GEN x) { long i; GEN xp; if (!signe(x)) return -1; xp=int_LSW(x); for (i=0; !*xp; i++) xp=int_nextW(xp); return vals(*xp) + i * BITS_IN_LONG; } /* assume x > 0 */ INLINE long expu(ulong x) { return (BITS_IN_LONG-1) - (long)bfffo(x); } INLINE long expi(GEN x) { const long lx=lgefint(x); return lx==2? -(long)HIGHEXPOBIT: bit_accuracy(lx)-(long)bfffo(*int_MSW(x))-1; } INLINE GEN shiftr(GEN x, long n) { const long e = evalexpo(expo(x)+n); const GEN y = rcopy(x); if (e & ~EXPOBITS) pari_err_OVERFLOW("expo()"); y[1] = (y[1]&~EXPOBITS) | e; return y; } INLINE GEN mpshift(GEN x,long s) { return (typ(x)==t_INT)?shifti(x,s):shiftr(x,s); } /* FIXME: adapt/use mpn_[lr]shift instead */ /* z2[imin..imax] := z1[imin..imax].f shifted left sh bits * (feeding f from the right). Assume sh > 0 */ INLINE void shift_left(GEN z2, GEN z1, long imin, long imax, ulong f, ulong sh) { GEN sb = z1 + imin, se = z1 + imax, te = z2 + imax; ulong l, m = BITS_IN_LONG - sh, k = f >> m; while (se > sb) { l = *se--; *te-- = (l << sh) | k; k = l >> m; } *te = (((ulong)*se) << sh) | k; } /* z2[imin..imax] := f.z1[imin..imax-1] shifted right sh bits * (feeding f from the left). Assume sh > 0 */ INLINE void shift_right(GEN z2, GEN z1, long imin, long imax, ulong f, ulong sh) { GEN sb = z1 + imin, se = z1 + imax, tb = z2 + imin; ulong k, l = *sb++, m = BITS_IN_LONG - sh; *tb++ = (l >> sh) | (f << m); while (sb < se) { k = l << m; l = *sb++; *tb++ = (l >> sh) | k; } } /* Backward compatibility. Inefficient && unused */ extern ulong hiremainder; INLINE ulong shiftl(ulong x, ulong y) { hiremainder = x>>(BITS_IN_LONG-y); return (x<>y); } INLINE void shiftr_inplace(GEN z, long d) { setexpo(z, expo(z)+d); } /*******************************************************************/ /* */ /* ASSIGNMENT */ /* */ /*******************************************************************/ INLINE void affii(GEN x, GEN y) { long lx = lgefint(x); if (lg(y)t_INT assignment"); while (--lx) y[lx] = x[lx]; } INLINE void affsi(long s, GEN x) { if (!s) x[1] = evalsigne(0) | evallgefint(2); else { if (s > 0) { x[1] = evalsigne( 1) | evallgefint(3); x[2] = s; } else { x[1] = evalsigne(-1) | evallgefint(3); x[2] = -s; } } } INLINE void affui(ulong u, GEN x) { if (!u) x[1] = evalsigne(0) | evallgefint(2); else { x[1] = evalsigne(1) | evallgefint(3); x[2] = u; } } INLINE void affsr(long x, GEN y) { long sh, i, ly = lg(y); if (!x) { y[1] = evalexpo(-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] = ((ulong)x)<> (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.17.2/src/kernel/none/addll.h0000644000175000017500000000627314567450071015444 0ustar billbill#line 2 "../src/kernel/none/addll.h" /* Copyright (C) 2003 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* 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 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.17.2/src/kernel/none/gcdll.c0000644000175000017500000010210214567450071015430 0ustar billbill#line 2 "../src/kernel/none/gcdll.c" /* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /***********************************************************************/ /** **/ /** 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. */ INLINE 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 */ 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; } long cgcd(long a,long b) { return (long)ugcd(labs(a), labs(b)); } /* 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*/ ulong ulcm(ulong a, ulong b) { ulong d = ugcd(a,b); if (!d) return 0; return d == 1? a*b: a*(b/d); } long clcm(long a,long b) { return ulcm(labs(a), labs(b)); } /********************************************************************/ /** **/ /** INTEGER EXTENDED GCD (AND INVMOD) **/ /** **/ /********************************************************************/ /* Two basic ideas - (1) avoid many integer divisions, especially when the * quotient is 1 which happens ~ 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. Jebelean's modifications consist in * inequalities from which we can quickly decide 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 thesis * [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 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. * (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. * * 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. */ 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; if (d <= 1UL) { xs=1; break; } /* possible loop exit */ /* repeat with inverted roles */ d1 -= d; if (d1 >= d) { hiremainder = 0; q = 1 + divll(d1,d); d1 = hiremainder; xv1 += q * xv; } else xv1 += xv; } 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) { /* no need to use subll */ d -= d1; if (d >= d1) { hiremainder = 0; q = 1 + divll(d,d1); d = hiremainder; xv += q * xv1; xu += q * xu1; } else { xv += xv1; xu += xu1; } if (d <= 1UL) { xs=1; break; } /* possible loop exit */ /* 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; } } 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; } } 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. */ 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; if (!b) { *vv=0L; if (!a) { *uu=1L; return 0L; } *uu = a < 0 ? -1L : 1L; return (long)d; } else if (!a || (d == d1)) { *uu = 0L; *vv = b < 0 ? -1L : 1L; return (long)d1; } else if (d == 1) /* frequently used by nfinit */ { *uu = a; *vv = 0L; 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; } /* 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; } 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,qj] thus obtained, where the leftmost * factor arises from the quotient of the first division step. * * For use in rational reconstruction, vmax can be given a nonzero value. * In this case, we will return early as soon as v1 > vmax (i.e. v <= vmax) * * MUST be called with d > d1 > 0, and with d occupying more than one * significant word. 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 * nonpositive, and the latest remainder after updating turns out to be * nonzero, the caller should at once attempt a full division, rather than * 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 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 assign anything to the last four args. * * The division chain might even run to completion. It is up to the caller to * detect this case. This routine does not change d or d1; this is also up to * the caller */ 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 infrequently. * 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, d1m1; long ld, ld1, lz; int skip = 0; LOCAL_OVERFLOW; LOCAL_HIREMAINDER; /* 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 */ d = int_MSW(d); dm1 = *int_precW(d); d1 = int_MSW(d1);d1m1 = *int_precW(d1); dd1lo = 0; /* unless we find something better */ sh = bfffo(*d); 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) + (*int_precW(int_precW(d1)) >> 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) + (*int_precW(int_precW(d)) >> shc); else ddlo = (dm1 << sh); } else { /* no shift needed */ if (lz) return 0; /* dividend longer than divisor: overflow */ dd1 = *d1; if (!(HIGHMASK & dd1)) return 0; if(ld1 > 3) dd1lo = d1m1; /* assume again that d has another significant word */ dd = *d; ddlo = dm1; } /* 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 */ { /* This actually happens. Now q==1 is known, but we underflow already. * OTOH we've just shortened d by a whole word. Thus we are happy and * return. */ *u = 0; *v = *u1 = *v1 = 1UL; return -1; /* Next step will be a full division. */ } } else { /* division indicated */ hiremainder = 0; xv1 = 1 + divll(dd, dd1); /* xv1: alternative spelling of `q', here ;) */ dd = hiremainder; if (dd < xv1) /* !(Jebelean cond'), nonextra 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 too large. Thanks to our decision * not to get here unless the original dd1 had bits set in the upper half * of the word, we now know that the correct quotient is in fact q-1. */ 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; 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 attached 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 1st division, even an a priori quotient of 1 cannot be * trusted until we've checked Jebelean's condition: 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 */ 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; if (xv > vmax) { *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 */ 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; if (xv1 > vmax) { *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; } } /* 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 and let caller * see to it that the initial subtraction is re-done usingall 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 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.) */ 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); /* > 0 */ 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 completes the swap; now dd is again the current divisor */ 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 */ /* 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 */ 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; if (xv > vmax) { *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 */ 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; if (xv1 > vmax) { *u = xu; *u1 = xu1; *v = xv; *v1 = xv1; return res; } } /* end of second loop */ return res; } /* 1 / Mod(x,p). Assume x < p */ ulong Fl_invsafe(ulong x, ulong p) { long s; ulong xv, xv1, g = xgcduu(p, x, 1, &xv, &xv1, &s); if (g != 1UL) return 0UL; xv = xv1 % p; if (s < 0) xv = p - xv; return xv; } /* 1 / Mod(x,p). Assume x < p */ ulong Fl_inv(ulong x, ulong p) { ulong xv = Fl_invsafe(x, p); if (!xv && p!=1UL) pari_err_INV("Fl_inv", mkintmod(utoi(x), utoi(p))); return xv; } pari-2.17.2/src/kernel/none/divll_pre.h0000644000175000017500000000764214567450071016345 0ustar billbill#line 2 "../src/kernel/none/divll_pre.h" /* Copyright (C) 2014 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #undef LOCAL_HIREMAINDER extern ulong hiremainder; #if defined(INLINE) && defined(__GNUC__) && !defined(DISABLE_INLINE) #define LOCAL_HIREMAINDER ulong hiremainder #else #define LOCAL_HIREMAINDER #endif #if defined(INLINE) && defined(__GNUC__) && !defined(DISABLE_INLINE) INLINE ulong /* precompute inverse of n */ get_Fl_red(ulong n) { LOCAL_HIREMAINDER; n <<= bfffo(n); hiremainder = ~n; return divll(~0UL, n); } #else INLINE ulong /* precompute inverse of n */ get_Fl_red(ulong n) { ulong q, oldhi = hiremainder; n <<= bfffo(n); hiremainder = ~n; q = divll(~0UL, n); hiremainder = oldhi; return q; } #endif INLINE ulong /* requires u1 <= n, n normalised */ divll_pre_normalized(ulong u1, ulong u0, ulong n, ulong ninv, ulong *pt_r) { ulong q0, q1, r; LOCAL_HIREMAINDER; LOCAL_OVERFLOW; q0 = mulll(ninv, u1); q1 = hiremainder; q0 = addll(q0, u0); q1 = addllx(q1+1, u1); r = u0 - q1 * n; if (r > q0) { r += n; q1--; } if (r >= n) { r -= n; q1++; } *pt_r = r; return q1; } INLINE ulong /* requires u1 <= n, n normalised */ remll_pre_normalized(ulong u1, ulong u0, ulong n, ulong ninv) { ulong q0, q1, r; LOCAL_HIREMAINDER; LOCAL_OVERFLOW; q0 = mulll(ninv, u1); q1 = hiremainder; q0 = addll(q0, u0); q1 = addllx(q1, u1); r = u0 - (q1 + 1) * n; if (r >= q0) r += n; return r < n ? r : r - n; } INLINE ulong /* reduce mod n */ remll_pre(ulong a_hi, ulong a_lo, ulong n, ulong ninv) { int norm = bfffo(n); int bits = BITS_IN_LONG - norm; ulong sn = n << norm; if (a_hi >= n) /* reduce a_hi first */ { const ulong u1 = norm ? a_hi >> bits : 0; const ulong u0 = a_hi << norm; a_hi = remll_pre_normalized(u1, u0, sn, ninv) >> norm; } /* now reduce */ { const ulong u1 = ((a_hi << norm) | (norm ? a_lo >> bits: 0)); const ulong u0 = a_lo << norm; return remll_pre_normalized(u1, u0, sn, ninv) >> norm; } } #if !defined(INLINE) extern ulong divll_pre(ulong a_lo, ulong n, ulong ninv); #else #if defined(__GNUC__) && !defined(DISABLE_INLINE) #define divll_pre(a, n, ninv) \ __extension__ ({ \ ulong __a = (a); \ ulong __n = (n); \ int norm = bfffo(__n); \ int bits = BITS_IN_LONG - norm; \ ulong r, sn = __n << norm; \ const ulong u1 = ((hiremainder << norm) | (norm ? __a >> bits: 0)); \ const ulong u0 = __a << norm; \ const ulong q = divll_pre_normalized(u1, u0, sn, ninv, &r); \ hiremainder = r>>norm; q; \ }) #else /* __GNUC__ */ INLINE ulong divll_pre(ulong a_lo, ulong n, ulong ninv) { int norm = bfffo(n); int bits = BITS_IN_LONG - norm; ulong r, sn = n << norm; const ulong u1 = ((hiremainder << norm) | (norm ? a_lo >> bits: 0)); const ulong u0 = a_lo << norm; const ulong q = divll_pre_normalized(u1, u0, sn, ninv, &r); hiremainder = r>>norm; return q; } #endif /* __GNUC__ */ #endif pari-2.17.2/src/kernel/none/mp_indep.c0000644000175000017500000005750414702752270016152 0ustar billbill#line 2 "../src/kernel/none/mp_indep.c" /* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* 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 i, lx, ly = lg(y); if (!signe(x)) { y[1] = evalexpo(minss(expo(x), -bit_accuracy(ly))); return; } y[1] = x[1]; lx = lg(x); if (lx <= ly) { for (i=2; i ly: round properly */ if (x[ly] & HIGHBIT) roundr_up_ip(y, ly); } GEN trunc2nr(GEN x, long n) { long ex; if (!signe(x)) return gen_0; ex = expo(x) + n; if (ex < 0) return gen_0; return mantissa2nr(x, ex - bit_prec(x) + 1); } /* x a t_REAL, x = i/2^e, i a t_INT */ GEN mantissa_real(GEN x, long *e) { *e = bit_prec(x)-1-expo(x); return mantissa2nr(x, 0); } GEN mului(ulong x, GEN y) { long s = signe(y); GEN z; if (!s || !x) return gen_0; z = muluispec(x, y+2, lgefint(y)-2); setsigne(z,s); return z; } GEN mulsi(long x, GEN y) { long s = signe(y); GEN z; if (!s || !x) return gen_0; if (x<0) { s = -s; x = -x; } z = muluispec((ulong)x, y+2, lgefint(y)-2); setsigne(z,s); return z; } GEN mulss(long x, long y) { ulong 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) { ulong 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) { ulong p1; LOCAL_HIREMAINDER; if (!x || !y) return gen_0; p1 = mulll(x,y); return uutoi(hiremainder, p1); } GEN sqru(ulong x) { ulong 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 = cgetg(lx, t_REAL); ulong garde; LOCAL_HIREMAINDER; y--; garde = mulll(x,y[lx]); for (i=lx-1; i>=3; i--) z[i]=addmul(x,y[i]); z[2]=hiremainder; /* != 0 since y normalized and |x| > 1 */ sh = bfffo(hiremainder); m = BITS_IN_LONG-sh; if (sh) shift_left(z,z, 2,lx-1, garde,sh); z[1] = evalsigne(s) | evalexpo(m+e); if ((garde << sh) & HIGHBIT) roundr_up_ip(z, lx); return z; } INLINE GEN mul0r(GEN x) { long l = realprec(x), e = expo(x); e = (l > 0)? e - l: (e < 0? 2*e: 0); return real_0_bit(e); } /* lg(x) > 2 */ INLINE GEN div0r(GEN x) { long l = realprec(x), e = expo(x); return real_0_bit(-l - e); } GEN mulsr(long x, GEN y) { long s; if (!x) return mul0r(y); s = signe(y); if (!s) { if (x < 0) x = -x; return real_0_bit( expo(y) + expu(x) ); } if (x==1) return rcopy(y); if (x==-1) return negr(y); if (x < 0) return mulur_2((ulong)-x, y, -s); else return mulur_2((ulong)x, y, s); } GEN mulur(ulong x, GEN y) { long s; if (!x) return mul0r(y); s = signe(y); if (!s) return real_0_bit( expo(y) + expu(x) ); if (x==1) return rcopy(y); return mulur_2(x, y, s); } INLINE void mulrrz_end(GEN z, GEN hi, long lz, long sz, long ez, ulong garde) { long i; if (hi[2] < 0) { if (z != hi) for (i=2; i1 && z[i]==0); if (i == 1) { z[2] = (long)HIGHBIT; ez++; } } z[1] = evalsigne(sz)|evalexpo(ez); } /* mulrrz_end for lz = 3, minor simplifications. z[2]=hiremainder from mulll */ INLINE void mulrrz_3end(GEN z, long sz, long ez, ulong garde) { if (z[2] < 0) { /* z2 < (2^BIL-1)^2 / 2^BIL, hence z2+1 != 0 */ if (garde & HIGHBIT) z[2]++; /* round properly */ ez++; } else { uel(z,2) = (uel(z,2)<<1) | (garde>>(BITS_IN_LONG-1)); if (garde & (1UL<<(BITS_IN_LONG-2))) { uel(z,2)++; /* round properly, z2+1 can overflow */ if (!uel(z,2)) { uel(z,2) = HIGHBIT; ez++; } } } z[1] = evalsigne(sz)|evalexpo(ez); } /* set z <-- x^2 != 0, floating point multiplication. * lz = lg(z) = lg(x) */ INLINE void sqrz_i(GEN z, GEN x, long lz) { long ez = 2*expo(x); long i, j, lzz, p1; ulong garde; GEN x1; LOCAL_HIREMAINDER; LOCAL_OVERFLOW; if (lz > prec2lg(SQRR_SQRI_LIMIT)) { pari_sp av = avma; GEN hi = sqrispec_mirror(x+2, lz-2); mulrrz_end(z, hi, lz, 1, ez, hi[lz]); set_avma(av); return; } if (lz == 3) { garde = mulll(x[2],x[2]); z[2] = hiremainder; mulrrz_3end(z, 1, ez, garde); return; } lzz = lz-1; p1 = x[lzz]; if (p1) { (void)mulll(p1,x[3]); garde = addmul(p1,x[2]); z[lzz] = hiremainder; } else { garde = 0; z[lzz] = 0; } for (j=lz-2, x1=x-j; j>=3; j--) { p1 = x[j]; x1++; if (p1) { (void)mulll(p1,x1[lz+1]); garde = addll(addmul(p1,x1[lz]), garde); for (i=lzz; i>j; i--) { hiremainder += overflow; z[i] = addll(addmul(p1,x1[i]), z[i]); } z[j] = hiremainder+overflow; } else z[j]=0; } p1 = x[2]; x1++; garde = addll(mulll(p1,x1[lz]), garde); for (i=lzz; i>2; i--) { hiremainder += overflow; z[i] = addll(addmul(p1,x1[i]), z[i]); } z[2] = hiremainder+overflow; mulrrz_end(z, z, lz, 1, ez, garde); } /* lz "large" = lg(y) = lg(z), lg(x) > lz if flag = 1 and >= if flag = 0 */ INLINE void mulrrz_int(GEN z, GEN x, GEN y, long lz, long flag, long sz) { pari_sp av = avma; GEN hi = muliispec_mirror(y+2, x+2, lz+flag-2, lz-2); mulrrz_end(z, hi, lz, sz, expo(x)+expo(y), hi[lz]); set_avma(av); } /* lz = 3 */ INLINE void mulrrz_3(GEN z, GEN x, GEN y, long flag, long sz) { ulong garde; LOCAL_HIREMAINDER; if (flag) { (void)mulll(x[2],y[3]); garde = addmul(x[2],y[2]); } else garde = mulll(x[2],y[2]); z[2] = hiremainder; mulrrz_3end(z, sz, expo(x)+expo(y), garde); } /* set z <-- x*y, floating point multiplication. Trailing 0s for x are * treated efficiently (important application: mulir). * lz = lg(z) = lg(x) <= ly <= lg(y), sz = signe(z). flag = lg(x) < lg(y) */ INLINE void mulrrz_i(GEN z, GEN x, GEN y, long lz, long flag, long sz) { long ez, i, j, lzz, p1; ulong garde; GEN y1; LOCAL_HIREMAINDER; LOCAL_OVERFLOW; if (x == y) { sqrz_i(z,x,lz); return; } if (lz > prec2lg(MULRR_MULII_LIMIT)) { mulrrz_int(z,x,y,lz,flag,sz); return; } if (lz == 3) { mulrrz_3(z,x,y,flag,sz); return; } ez = expo(x) + expo(y); if (flag) { (void)mulll(x[2],y[lz]); garde = hiremainder; } else garde = 0; lzz=lz-1; p1=x[lzz]; if (p1) { (void)mulll(p1,y[3]); garde = addll(addmul(p1,y[2]), garde); z[lzz] = overflow+hiremainder; } else z[lzz]=0; for (j=lz-2, y1=y-j; j>=3; j--) { p1 = x[j]; y1++; if (p1) { (void)mulll(p1,y1[lz+1]); garde = addll(addmul(p1,y1[lz]), garde); for (i=lzz; i>j; i--) { hiremainder += overflow; z[i] = addll(addmul(p1,y1[i]), z[i]); } z[j] = hiremainder+overflow; } else z[j]=0; } p1 = x[2]; y1++; garde = addll(mulll(p1,y1[lz]), garde); for (i=lzz; i>2; i--) { hiremainder += overflow; z[i] = addll(addmul(p1,y1[i]), z[i]); } z[2] = hiremainder+overflow; mulrrz_end(z, z, lz, sz, ez, garde); } GEN mulrr(GEN x, GEN y) { long flag, ly, lz, sx, sy; GEN z; if (x == y) return sqrr(x); sx = signe(x); if (!sx) return real_0_bit(expo(x) + expo(y)); sy = signe(y); if (!sy) return real_0_bit(expo(x) + expo(y)); if (sy < 0) sx = -sx; lz = lg(x); ly = lg(y); if (lz > ly) { lz = ly; swap(x, y); flag = 1; } else flag = (lz != ly); z = cgetg(lz, t_REAL); 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 = cgetg(lz, t_REAL); sqrz_i(z, x, lz); return z; } GEN mulir(GEN x, GEN y) { long sx = signe(x), sy; if (!sx) return mul0r(y); if (lgefint(x) == 3) { GEN z = mulur(uel(x,2), y); if (sx < 0) togglesign(z); return z; } sy = signe(y); if (!sy) return real_0_bit(expi(x) + expo(y)); if (sy < 0) sx = -sx; { long lz = lg(y), lx = lgefint(x); GEN hi, z = cgetg(lz, t_REAL); pari_sp av = avma; if (lx < (lz>>1) || (lx < lz && lz > prec2lg(MULRR_MULII_LIMIT))) { /* size mantissa of x < half size of mantissa z, or lx < lz so large * that mulrr will call mulii anyway: mulii */ x = itor(x, lg2prec(lx)); hi = muliispec_mirror(y+2, x+2, lz-2, lx-2); mulrrz_end(z, hi, lz, sx, expo(x)+expo(y), hi[lz]); } else /* dubious: complete x with 0s and call mulrr */ mulrrz_i(z, itor(x, lg2prec(lz)), y, lz, 0, sx); set_avma(av); return z; } } /* x + y*z, generic. If lgefint(z) <= 3, caller should use faster variants */ static GEN addmulii_gen(GEN x, GEN y, GEN z, long lz) { long lx = lgefint(x), ly; pari_sp av; GEN t; if (lx == 2) return mulii(z,y); ly = lgefint(y); if (ly == 2) return icopy(x); /* y = 0, wasteful copy */ av = avma; (void)new_chunk(lx+ly+lz); /*HACK*/ t = mulii(z, y); set_avma(av); return addii(t,x); } /* x + y*z, lgefint(z) == 3 */ static GEN addmulii_lg3(GEN x, GEN y, GEN z) { long s = signe(z), lx, ly; ulong w = z[2]; pari_sp av; GEN t; if (w == 1) return (s > 0)? addii(x,y): subii(x,y); /* z = +- 1 */ lx = lgefint(x); ly = lgefint(y); if (lx == 2) { /* x = 0 */ if (ly == 2) return gen_0; t = muluispec(w, y+2, ly-2); if (signe(y) < 0) s = -s; setsigne(t, s); return t; } if (ly == 2) return icopy(x); /* y = 0, wasteful copy */ av = avma; (void)new_chunk(1+lx+ly);/*HACK*/ t = muluispec(w, y+2, ly-2); if (signe(y) < 0) s = -s; setsigne(t, s); set_avma(av); return addii(x,t); } /* x + y*z */ GEN addmulii(GEN x, GEN y, GEN z) { long lz = lgefint(z); switch(lz) { case 2: return icopy(x); /* z = 0, wasteful copy */ case 3: return addmulii_lg3(x, y, z); default:return addmulii_gen(x, y, z, lz); } } /* x + y*z, returns x itself and not a copy when y*z = 0 */ GEN addmulii_inplace(GEN x, GEN y, GEN z) { long lz; if (lgefint(y) == 2) return x; lz = lgefint(z); switch(lz) { case 2: return x; case 3: return addmulii_lg3(x, y, z); default:return addmulii_gen(x, y, z, lz); } } /* written by Bruno Haible following an idea of Robert Harley */ long vals(ulong z) { static char tab[64]={-1,0,1,12,2,6,-1,13,3,-1,7,-1,-1,-1,-1,14,10,4,-1,-1,8,-1,-1,25,-1,-1,-1,-1,-1,21,27,15,31,11,5,-1,-1,-1,-1,-1,9,-1,-1,24,-1,-1,20,26,30,-1,-1,-1,-1,23,-1,19,29,-1,22,18,28,17,16,-1}; #ifdef LONG_IS_64BIT long s; #endif if (!z) return -1; #ifdef LONG_IS_64BIT if (! (z&0xffffffff)) { s = 32; z >>=32; } else s = 0; #endif z |= ~z + 1; z += z << 4; z += z << 6; z ^= z << 16; /* or z -= z<<16 */ #ifdef LONG_IS_64BIT return s + tab[(z&0xffffffff)>>26]; #else return tab[z>>26]; #endif } GEN divsi(long x, GEN y) { long p1, s = signe(y); LOCAL_HIREMAINDER; if (!s) pari_err_INV("divsi",gen_0); if (!x || lgefint(y)>3 || ((long)y[2])<0) return gen_0; hiremainder=0; p1=divll(labs(x),y[2]); if (x<0) { hiremainder = -((long)hiremainder); p1 = -p1; } if (s<0) p1 = -p1; return stoi(p1); } GEN divir(GEN x, GEN y) { GEN z; long ly = lg(y), lx = lgefint(x); pari_sp av; if (ly == 2) pari_err_INV("divir",y); if (lx == 2) return div0r(y); if (lx == 3) { z = divur(x[2], y); if (signe(x) < 0) togglesign(z); return z; } z = cgetg(ly, t_REAL); av = avma; affrr(divrr(itor(x, lg2prec(ly+1)), y), z); set_avma(av); return z; } GEN divur(ulong x, GEN y) { pari_sp av; long p = realprec(y); GEN z; if (p == 0) pari_err_INV("divur",y); if (!x) return div0r(y); if (p > INVNEWTON_LIMIT) { av = avma; z = invr(y); if (x == 1) return z; return gerepileuptoleaf(av, mulur(x, z)); } z = cgetr(p); av = avma; affrr(divrr(utor(x, p + BITS_IN_LONG), y), z); set_avma(av); return z; } GEN divsr(long x, GEN y) { pari_sp av; long p = realprec(y); GEN z; if (p == 0) pari_err_INV("divsr",y); if (!x) return div0r(y); if (p > 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(p); av = avma; affrr(divrr(stor(x,p + BITS_IN_LONG), y), z); set_avma(av); return z; } /* returns 1/y, assume y != 0 */ static GEN invr_basecase(GEN y) { long p = realprec(y); GEN z = cgetr(p); pari_sp av = avma; affrr(divrr(real_1(p + BITS_IN_LONG), y), z); set_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(prec2lg(INVNEWTON_LIMIT), (1L<>= 1; } x = cgetg(l, t_REAL); a = rcopy(b); a[1] = _evalexpo(0) | evalsigne(1); affrr(invr_basecase(rtor(a, lg2prec(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); set_avma((pari_sp)a); } x[1] = (b[1] & SIGNBITS) | evalexpo(expo(x)-expo(b)); set_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); set_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); set_avma(av); } GEN divrs(GEN x, long y) { GEN z; if (y < 0) { z = divru(x, (ulong)-y); togglesign(z); } else z = divru(x, (ulong)y); return z; } GEN divru(GEN x, ulong y) { long i, lx, sh, e, s = signe(x); ulong garde; GEN z; LOCAL_HIREMAINDER; if (!y) pari_err_INV("divru",gen_0); if (!s) return real_0_bit(expo(x) - expu(y)); if (!(y & (y-1))) /* power of 2 */ { if (y == 1) return rcopy(x); return shiftr(x, -expu(y)); } e = expo(x); lx = lg(x); z = cgetg(lx, t_REAL); if (lx == 3) { if (y <= uel(x,2)) { hiremainder = 0; z[2] = divll(x[2],y); /* we may have hiremainder != 0 ==> garde */ garde = divll(0,y); } else { hiremainder = x[2]; z[2] = divll(0,y); garde = hiremainder; e -= BITS_IN_LONG; } } else { ulong yp = get_Fl_red(y); if (y <= uel(x,2)) { hiremainder = 0; for (i=2; i garde */ garde = divll_pre(0,y,yp); } else { long l = lx-1; hiremainder = x[2]; for (i=2; i= 0) { if (z) *z = utoi(r); return q; } q = gerepileuptoint(av, addis(q, (y < 0)? 1: -1)); if (z) *z = utoi(r + labs(y)); return q; } GEN truedvmdsi(long x, GEN y, GEN *z) { long q, r; if (z == ONLY_REM) return modsi(x, y); q = sdivsi_rem(x,y,&r); if (r >= 0) { if (z) *z = utoi(r); return stoi(q); } q = q - signe(y); if (!z) return stoi(q); *z = subiuspec(y+2,(ulong)-r, lgefint(y)-2); return stoi(q); } /* 2^n = shifti(gen_1, n) */ GEN int2n(long n) { long i, m, l; GEN z; if (n < 0) return gen_0; if (n == 0) return gen_1; l = dvmdsBIL(n, &m) + 3; z = cgetipos(l); for (i = 2; i < l; i++) z[i] = 0; *int_MSW(z) = 1UL << 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) = 1UL << m; return z; } /* 2^n - 1 */ GEN int2um1(ulong n) { ulong i, m, l; GEN z; if (n == 0) return gen_0; l = dvmduBIL(n, &m); l += m? 3: 2; z = cgetipos(l); for (i = 2; i < l; i++) z[i] = ~0UL; if (m) *int_MSW(z) = (1UL << m) - 1; return z; } GEN shifti(GEN x, long n) { long s = signe(x); GEN y; if(s == 0) return gen_0; y = shiftispec(x + 2, lgefint(x) - 2, n); if (signe(y)) setsigne(y, s); return y; } /* actual operations will take place on a+2 and b+2: we strip the codewords */ GEN mulii(GEN a,GEN b) { long sa,sb; GEN z; sa=signe(a); if (!sa) return gen_0; sb=signe(b); if (!sb) return gen_0; if (sb<0) sa = -sa; z = muliispec(a+2,b+2, lgefint(a)-2,lgefint(b)-2); setsigne(z,sa); return z; } GEN sqri(GEN a) { return sqrispec(a+2, lgefint(a)-2); } /* sqrt()'s result may be off by 1 when a is not representable exactly as a * double [64bit machine] */ ulong usqrt(ulong a) { ulong x = (ulong)sqrt((double)a); #ifdef LONG_IS_64BIT if (x > LOWMASK || x*x > a) x--; #endif return x; } /********************************************************************/ /** **/ /** EXPONENT / CONVERSION t_REAL --> double **/ /** **/ /********************************************************************/ #ifdef LONG_IS_64BIT long dblexpo(double x) { union { double f; ulong i; } fi; const int mant_len = 52; /* mantissa bits (excl. hidden bit) */ const int exp_mid = 0x3ff;/* exponent bias */ if (x==0.) return -exp_mid; fi.f = x; return ((fi.i & (HIGHBIT-1)) >> mant_len) - exp_mid; } ulong dblmantissa(double x) { union { double f; ulong i; } fi; const int expo_len = 11; /* number of bits of exponent */ if (x==0.) return 0; fi.f = x; return (fi.i << expo_len) | HIGHBIT; } GEN dbltor(double x) { GEN z; long e; union { double f; ulong i; } fi; const int mant_len = 52; /* mantissa bits (excl. hidden bit) */ const int exp_mid = 0x3ff;/* exponent bias */ const int expo_len = 11; /* number of bits of exponent */ if (x==0.) return real_0_bit(-exp_mid); fi.f = x; z = cgetr(DEFAULTPREC); { const ulong a = fi.i; ulong A; e = ((a & (HIGHBIT-1)) >> mant_len) - exp_mid; if (e == exp_mid+1) pari_err_OVERFLOW("dbltor [NaN or Infinity]"); A = a << expo_len; if (e == -exp_mid) { /* unnormalized values */ int sh = bfffo(A); e -= sh-1; z[2] = A << sh; } else z[2] = HIGHBIT | A; z[1] = _evalexpo(e) | evalsigne(x<0? -1: 1); } return z; } double rtodbl(GEN x) { long ex,s=signe(x); ulong a; union { double f; ulong i; } fi; const int mant_len = 52; /* mantissa bits (excl. hidden bit) */ const int exp_mid = 0x3ff;/* exponent bias */ const int expo_len = 11; /* number of bits of exponent */ if (!s || (ex=expo(x)) < - exp_mid) return 0.0; /* start by rounding to closest */ a = (x[2] & (HIGHBIT-1)) + 0x400; if (a & HIGHBIT) { ex++; a=0; } if (ex >= exp_mid) pari_err_OVERFLOW("t_REAL->double conversion"); fi.i = ((ex + exp_mid) << mant_len) | (a >> expo_len); if (s<0) fi.i |= HIGHBIT; return fi.f; } #else /* LONG_IS_64BIT */ #if PARI_DOUBLE_FORMAT == 1 # define INDEX0 1 # define INDEX1 0 #elif PARI_DOUBLE_FORMAT == 0 # define INDEX0 0 # define INDEX1 1 #endif long dblexpo(double x) { union { double f; ulong i[2]; } fi; const int mant_len = 52; /* mantissa bits (excl. hidden bit) */ const int exp_mid = 0x3ff;/* exponent bias */ const int shift = mant_len-32; if (x==0.) return -exp_mid; fi.f = x; { const ulong a = fi.i[INDEX0]; return ((a & (HIGHBIT-1)) >> shift) - exp_mid; } } ulong dblmantissa(double x) { union { double f; ulong i[2]; } fi; const int expo_len = 11; /* number of bits of exponent */ if (x==0.) return 0; fi.f = x; { const ulong a = fi.i[INDEX0]; const ulong b = fi.i[INDEX1]; return HIGHBIT | b >> (BITS_IN_LONG-expo_len) | (a << expo_len); } } GEN dbltor(double x) { GEN z; long e; union { double f; ulong i[2]; } fi; const int mant_len = 52; /* mantissa bits (excl. hidden bit) */ const int exp_mid = 0x3ff;/* exponent bias */ const int expo_len = 11; /* number of bits of exponent */ const int shift = mant_len-32; if (x==0.) return real_0_bit(-exp_mid); fi.f = x; z = cgetr(DEFAULTPREC); { const ulong a = fi.i[INDEX0]; const ulong b = fi.i[INDEX1]; ulong A, B; e = ((a & (HIGHBIT-1)) >> shift) - exp_mid; if (e == exp_mid+1) pari_err_OVERFLOW("dbltor [NaN or Infinity]"); A = b >> (BITS_IN_LONG-expo_len) | (a << expo_len); B = b << expo_len; if (e == -exp_mid) { /* unnormalized values */ int sh; if (A) { sh = bfffo(A); e -= sh-1; z[2] = (A << sh) | (B >> (32-sh)); z[3] = B << sh; } else { sh = bfffo(B); /* B != 0 */ e -= sh-1 + 32; z[2] = B << sh; z[3] = 0; } } else { z[3] = B; z[2] = HIGHBIT | A; } z[1] = _evalexpo(e) | evalsigne(x<0? -1: 1); } return z; } double rtodbl(GEN x) { long ex,s=signe(x),lx=lg(x); ulong a,b,k; union { double f; ulong i[2]; } fi; const int mant_len = 52; /* mantissa bits (excl. hidden bit) */ const int exp_mid = 0x3ff;/* exponent bias */ const int expo_len = 11; /* number of bits of exponent */ const int shift = mant_len-32; if (!s || (ex=expo(x)) < - exp_mid) return 0.0; /* start by rounding to closest */ a = x[2] & (HIGHBIT-1); if (lx > 3) { b = x[3] + 0x400UL; if (b < 0x400UL) a++; if (a & HIGHBIT) { ex++; a=0; } } else b = 0; if (ex >= exp_mid) pari_err_OVERFLOW("t_REAL->double conversion"); ex += exp_mid; k = (a >> expo_len) | (ex << shift); if (s<0) k |= HIGHBIT; fi.i[INDEX0] = k; fi.i[INDEX1] = (a << (BITS_IN_LONG-expo_len)) | (b >> expo_len); return fi.f; } #endif /* LONG_IS_64BIT */ pari-2.17.2/src/kernel/none/cmp.c0000644000175000017500000000715714567450071015140 0ustar billbill#line 2 "../src/kernel/none/cmp.c" /* Copyright (C) 2002-2003 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /********************************************************************/ /** **/ /** Comparison routines **/ /** **/ /********************************************************************/ /*They depend on cmpiispec and equaliispec in mp.c*/ int equalii(GEN x, GEN y) { if ((x[1] & (LGBITS|SIGNBITS)) != (y[1] & (LGBITS|SIGNBITS))) return 0; return equaliispec(x+2, y+2, lgefint(x)-2, lgefint(y)-2); } int cmpii(GEN x, GEN y) { const long sx = signe(x), sy = signe(y); if (sxsy) return 1; if (!sx) return 0; if (sx>0) return cmpiispec(x+2, y+2, lgefint(x)-2, lgefint(y)-2); else return -cmpiispec(x+2, y+2, lgefint(x)-2, lgefint(y)-2); } int equalrr(GEN x, GEN y) { long lx, ly, i; if (!signe(x)) { if (!signe(y)) return 1; /* all zeroes are equal */ return expo(x) >= expo(y); } if (!signe(y)) return expo(y) >= expo(x); if (x[1] != y[1]) return 0; lx = lg(x); ly = lg(y); if (lx < ly) { i=2; while (i= expo(y)) return 0; return sy > 0? -1: 1; } if (!sy) { if (expo(y) >= expo(x)) return 0; return sx > 0? 1: -1; } if (sxsy) return 1; ex=expo(x); ey=expo(y); if (ex>ey) return sx; if (ex (ulong)y[i]) ? sx : -sx; if (lx>=ly) { while (iey) return 1; if (ex (ulong)y[i])? 1: -1; if (lx>=ly) { while (i> 1) - __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.17.2/src/kernel/none/tune.h0000644000175000017500000001462314676526175015347 0ustar billbill#ifdef LONG_IS_64BIT #define __AGM_ATAN_LIMIT 3584 #define __DIVRR_GMP_LIMIT -1 #define __EXPNEWTON_LIMIT 4224 #define __EXTGCD_HALFGCD_LIMIT 70 #define __F2x_MUL_KARATSUBA_LIMIT 11 #define __F2x_MUL_MULII_LIMIT 662 #define __F2xqX_BARRETT_LIMIT 56 #define __F2xqX_DIVREM_BARRETT_LIMIT 127 #define __F2xqX_EXTGCD_LIMIT 10 #define __F2xqX_GCD_LIMIT 468 #define __F2xqX_HALFGCD_LIMIT 64 #define __F2xqX_INVBARRETT_LIMIT 50 #define __F2xqX_REM_BARRETT_LIMIT 127 #define __Flx_BARRETT2_LIMIT 63 #define __Flx_BARRETT_LIMIT 131 #define __Flx_DIVREM2_BARRETT_LIMIT 28 #define __Flx_DIVREM_BARRETT_LIMIT 407 #define __Flx_EXTGCD2_LIMIT 31 #define __Flx_EXTGCD_LIMIT 17 #define __Flx_GCD2_LIMIT 2266 #define __Flx_GCD_LIMIT 621 #define __Flx_HALFGCD2_LIMIT 32 #define __Flx_HALFGCD_LIMIT 265 #define __Flx_INVBARRETT2_LIMIT 28 #define __Flx_INVBARRETT_LIMIT 316 #define __Flx_MUL2_KARATSUBA_LIMIT 10 #define __Flx_MUL2_MULII_LIMIT 14 #define __Flx_MUL_KARATSUBA_LIMIT 38 #define __Flx_MUL_MULII_LIMIT 66 #define __Flx_REM2_BARRETT_LIMIT 241 #define __Flx_REM_BARRETT_LIMIT 407 #define __Flx_SQR2_KARATSUBA_LIMIT 15 #define __Flx_SQR2_SQRI_LIMIT 28 #define __Flx_SQR_KARATSUBA_LIMIT 94 #define __Flx_SQR_SQRI_LIMIT 77 #define __FlxqX_BARRETT_LIMIT 17 #define __FlxqX_DIVREM_BARRETT_LIMIT 46 #define __FlxqX_EXTGCD_LIMIT 10 #define __FlxqX_GCD_LIMIT 407 #define __FlxqX_HALFGCD_LIMIT 57 #define __FlxqX_INVBARRETT_LIMIT 22 #define __FlxqX_REM_BARRETT_LIMIT 48 #define __FpXQX_BARRETT_LIMIT 12 #define __FpXQX_DIVREM_BARRETT_LIMIT 30 #define __FpXQX_EXTGCD_LIMIT 10 #define __FpXQX_GCD_LIMIT 152 #define __FpXQX_HALFGCD_LIMIT 43 #define __FpXQX_INVBARRETT_LIMIT 40 #define __FpXQX_REM_BARRETT_LIMIT 30 #define __FpX_BARRETT_LIMIT 85 #define __FpX_DIVREM_BARRETT_LIMIT 292 #define __FpX_EXTGCD_LIMIT 21 #define __FpX_GCD_LIMIT 282 #define __FpX_HALFGCD_LIMIT 56 #define __FpX_INVBARRETT_LIMIT 254 #define __FpX_REM_BARRETT_LIMIT 306 #define __Fp_POW_BARRETT_LIMIT 101 #define __Fp_POW_REDC_LIMIT 99 #define __GCD_HALFGCD_LIMIT 9 #define __HALFGCD_LIMIT 85 #define __INVMOD_GMP_LIMIT -1 #define __INVNEWTON_LIMIT 35200 #define __LOGAGMCX_LIMIT 832 #define __LOGAGM_LIMIT 1024 #define __MULII_FFT_LIMIT 1441 #define __MULII_KARATSUBA_LIMIT 23 #define __MULRR_MULII_LIMIT 13440 #define __RgX_MUL_LIMIT 9 #define __RgX_SQR_LIMIT 35 #define __SQRI_FFT_LIMIT 1651 #define __SQRI_KARATSUBA_LIMIT 36 #define __SQRR_SQRI_LIMIT 3456 #define __ZM2_MUL_LIMIT 13 #else #define __AGM_ATAN_LIMIT 5088 #define __DIVRR_GMP_LIMIT -1 #define __EXPNEWTON_LIMIT 2112 #define __EXTGCD_HALFGCD_LIMIT 83 #define __F2x_MUL_KARATSUBA_LIMIT 13 #define __F2x_MUL_MULII_LIMIT 6265 #define __F2xqX_BARRETT_LIMIT 58 #define __F2xqX_DIVREM_BARRETT_LIMIT 127 #define __F2xqX_EXTGCD_LIMIT 10 #define __F2xqX_GCD_LIMIT 257 #define __F2xqX_HALFGCD_LIMIT 43 #define __F2xqX_INVBARRETT_LIMIT 38 #define __F2xqX_REM_BARRETT_LIMIT 127 #define __Flx_BARRETT2_LIMIT 102 #define __Flx_BARRETT_LIMIT 433 #define __Flx_DIVREM2_BARRETT_LIMIT 194 #define __Flx_DIVREM_BARRETT_LIMIT 1888 #define __Flx_EXTGCD2_LIMIT 25 #define __Flx_EXTGCD_LIMIT 21 #define __Flx_GCD2_LIMIT 2817 #define __Flx_GCD_LIMIT 4986 #define __Flx_HALFGCD2_LIMIT 307 #define __Flx_HALFGCD_LIMIT 1245 #define __Flx_INVBARRETT2_LIMIT 1396 #define __Flx_INVBARRETT_LIMIT 1233 #define __Flx_MUL2_KARATSUBA_LIMIT 9 #define __Flx_MUL2_MULII_LIMIT 21 #define __Flx_MUL_KARATSUBA_LIMIT 57 #define __Flx_MUL_MULII_LIMIT 601 #define __Flx_REM2_BARRETT_LIMIT 296 #define __Flx_REM_BARRETT_LIMIT 1888 #define __Flx_SQR2_KARATSUBA_LIMIT 19 #define __Flx_SQR2_SQRI_LIMIT 67 #define __Flx_SQR_KARATSUBA_LIMIT 109 #define __Flx_SQR_SQRI_LIMIT 469 #define __FlxqX_BARRETT_LIMIT 17 #define __FlxqX_DIVREM_BARRETT_LIMIT 46 #define __FlxqX_EXTGCD_LIMIT 44 #define __FlxqX_GCD_LIMIT 898 #define __FlxqX_HALFGCD_LIMIT 174 #define __FlxqX_INVBARRETT_LIMIT 22 #define __FlxqX_REM_BARRETT_LIMIT 48 #define __FpXQX_BARRETT_LIMIT 12 #define __FpXQX_DIVREM_BARRETT_LIMIT 30 #define __FpXQX_EXTGCD_LIMIT 10 #define __FpXQX_GCD_LIMIT 177 #define __FpXQX_HALFGCD_LIMIT 47 #define __FpXQX_INVBARRETT_LIMIT 40 #define __FpXQX_REM_BARRETT_LIMIT 30 #define __FpX_BARRETT_LIMIT 144 #define __FpX_DIVREM_BARRETT_LIMIT 306 #define __FpX_EXTGCD_LIMIT 10 #define __FpX_GCD_LIMIT 826 #define __FpX_HALFGCD_LIMIT 108 #define __FpX_INVBARRETT_LIMIT 337 #define __FpX_REM_BARRETT_LIMIT 306 #define __Fp_POW_BARRETT_LIMIT 97 #define __Fp_POW_REDC_LIMIT 99 #define __GCD_HALFGCD_LIMIT 13 #define __HALFGCD_LIMIT 79 #define __INVMOD_GMP_LIMIT -1 #define __INVNEWTON_LIMIT 2112 #define __LOGAGMCX_LIMIT 1856 #define __LOGAGM_LIMIT 1760 #define __MULII_FFT_LIMIT 1386 #define __MULII_KARATSUBA_LIMIT 18 #define __MULRR_MULII_LIMIT 13504 #define __RgX_MUL_LIMIT 5 #define __RgX_SQR_LIMIT 26 #define __SQRI_FFT_LIMIT 1469 #define __SQRI_KARATSUBA_LIMIT 27 #define __SQRR_SQRI_LIMIT 640 #define __ZM2_MUL_LIMIT 13 #endif pari-2.17.2/src/kernel/none/mpinl.c0000644000175000017500000000142314567450071015466 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #define PARI_NO_PARIINL_H #define INLINE #ifndef DISABLE_INLINE # define DISABLE_INLINE #endif #include "pari.h" ulong hiremainder, overflow; pari-2.17.2/src/kernel/none/MakeLVL1.SH0000644000175000017500000000102014567450071015744 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/halfgcd.c $knone/ratlift.c\ $knone/invmod.c $kern1/gcd.c $kern1/gcdext.c $knone/mp_indep.c $knone/add.c mpker.c: \$(MP_C) cat \$(MP_C) > mpker.c mpker\$(_O): .headers mpker.c \$(CC) -c \$(CFLAGS) \$(KERNELCFLAGS) \$(DLCFLAGS) \$(CPPFLAGS) -o mpker\$(_O) mpker.c EOT pari-2.17.2/src/kernel/none/asm0.h0000644000175000017500000000125114567450071015213 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* NOASM addll mulll bfffo divll */ pari-2.17.2/src/kernel/sparcv8_super/0000755000175000017500000000000014760315601016042 5ustar billbillpari-2.17.2/src/kernel/sparcv8_super/MakeLVL0.SH0000644000175000017500000000025211636712103017605 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.17.2/src/kernel/sparcv8_super/asm0.h0000644000175000017500000000002211636712103017042 0ustar billbill/* NOASM divll */ pari-2.17.2/src/kernel/m68k/0000755000175000017500000000000014760315601014023 5ustar billbillpari-2.17.2/src/kernel/m68k/asm0.h0000644000175000017500000001207714567450071015051 0ustar billbill#line 2 "../src/kernel/m68k/asm0.h" /* Copyright (C) 2006 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* 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 ulong hiremainder #define LOCAL_OVERFLOW 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.17.2/src/kernel/ppc/0000755000175000017500000000000014760315601014020 5ustar billbillpari-2.17.2/src/kernel/ppc/asm0.h0000644000175000017500000000511314567450071015037 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* ASM addll mulll bfffo NOASM divll */ #ifdef ASMINLINE #define LOCAL_HIREMAINDER ulong hiremainder #define LOCAL_OVERFLOW 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.17.2/src/kernel/aarch64/0000755000175000017500000000000014760315601014466 5ustar billbillpari-2.17.2/src/kernel/aarch64/asm0.h0000644000175000017500000001134714567450071015513 0ustar billbill#line 2 "../src/kernel/aarch64/asm0.h" /* Copyright (C) 2015 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* ASM addll mulll bfffo NOASM divll */ #ifdef ASMINLINE #define LOCAL_HIREMAINDER ulong hiremainder #define LOCAL_OVERFLOW ulong overflow #define addll(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("adds %0,%2,%3\n\tadc %1,xzr,xzr\n\t" \ : "=&r" (__value), "=&r" (overflow) \ : "r" (__arg1), "r" (__arg2): "cc"); \ __value; \ }) #define addllx(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("subs xzr,%4,#1\n\tadcs %0,%2,%3\n\tadc %1,xzr,xzr\n\t" \ : "=&r" (__value), "=&r" (overflow) \ : "r" (__arg1), "r" (__arg2), "r" (overflow): "cc"); \ __value; \ }) #define addllx8(a,b,c,overflow) \ do { long *__arg1 = a, *__arg2 = b, *__out = c; \ ulong __temp1, __temp2; \ __asm__( \ "subs xzr,%6,#1\n\t" \ " ldr %0, [%3] \n\t ldr %1, [%4] \n\t adcs %1, %0, %1\n\t str %1, [%5] \n\t" \ " ldr %0, [%3,-8] \n\t ldr %1, [%4,-8] \n\t adcs %1, %0, %1\n\t str %1, [%5,-8] \n\t" \ " ldr %0, [%3,-16] \n\t ldr %1, [%4,-16]\n\t adcs %1, %0, %1\n\t str %1, [%5,-16]\n\t" \ " ldr %0, [%3,-24] \n\t ldr %1, [%4,-24]\n\t adcs %1, %0, %1\n\t str %1, [%5,-24]\n\t" \ " ldr %0, [%3,-32] \n\t ldr %1, [%4,-32]\n\t adcs %1, %0, %1\n\t str %1, [%5,-32]\n\t" \ " ldr %0, [%3,-40] \n\t ldr %1, [%4,-40]\n\t adcs %1, %0, %1\n\t str %1, [%5,-40]\n\t" \ " ldr %0, [%3,-48] \n\t ldr %1, [%4,-48]\n\t adcs %1, %0, %1\n\t str %1, [%5,-48]\n\t" \ " ldr %0, [%3,-56] \n\t ldr %1, [%4,-56]\n\t adcs %1, %0, %1\n\t str %1, [%5,-56]\n\t" \ "adc %2,xzr,xzr\n\t" \ : "=&r" (__temp1), "=&r" (__temp2), "=&r" (overflow) \ : "r" (__arg1), "r" (__arg2), "r" (__out), "r" (overflow), \ "0" ((ulong)0), "1" ((ulong)0) \ : "cc"); \ } while(0) #define subll(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("subs %0,%2,%3\n\tngc %1,xzr\n\tsub %1,xzr,%1\n\t" \ : "=&r" (__value), "=&r" (overflow) \ : "r" (__arg1), "r" (__arg2): "cc"); \ __value; \ }) #define subllx(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("subs xzr,xzr,%4\n\tsbcs %0,%2,%3\n\tngc %1,xzr\n\tsub %1,xzr,%1\n\t" \ : "=&r" (__value), "=&r" (overflow) \ : "r" (__arg1), "r" (__arg2), "r" (overflow): "cc"); \ __value; \ }) #define subllx8(a,b,c,overflow) \ do { long *__arg1 = a, *__arg2 = b, *__out = c; \ ulong __temp1, __temp2; \ __asm__( \ "subs xzr,xzr,%6\n\t" \ " ldr %0, [%3] \n\t ldr %1, [%4] \n\t sbcs %1, %0, %1\n\t str %1, [%5] \n\t" \ " ldr %0, [%3,-8] \n\t ldr %1, [%4,-8] \n\t sbcs %1, %0, %1\n\t str %1, [%5,-8] \n\t" \ " ldr %0, [%3,-16] \n\t ldr %1, [%4,-16]\n\t sbcs %1, %0, %1\n\t str %1, [%5,-16]\n\t" \ " ldr %0, [%3,-24] \n\t ldr %1, [%4,-24]\n\t sbcs %1, %0, %1\n\t str %1, [%5,-24]\n\t" \ " ldr %0, [%3,-32] \n\t ldr %1, [%4,-32]\n\t sbcs %1, %0, %1\n\t str %1, [%5,-32]\n\t" \ " ldr %0, [%3,-40] \n\t ldr %1, [%4,-40]\n\t sbcs %1, %0, %1\n\t str %1, [%5,-40]\n\t" \ " ldr %0, [%3,-48] \n\t ldr %1, [%4,-48]\n\t sbcs %1, %0, %1\n\t str %1, [%5,-48]\n\t" \ " ldr %0, [%3,-56] \n\t ldr %1, [%4,-56]\n\t sbcs %1, %0, %1\n\t str %1, [%5,-56]\n\t" \ "ngc %2,xzr\n\tsub %2,xzr,%2\n\t" \ : "=&r" (__temp1), "=&r" (__temp2), "=&r" (overflow) \ : "r" (__arg1), "r" (__arg2), "r" (__out), "r" (overflow), \ "0" ((ulong)0), "1" ((ulong)0) \ : "cc"); \ } while(0) #define mulll(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("mul %0,%1,%2\n\t" \ : "=r" (__value) : "r" (__arg1), "r" (__arg2)); \ __asm__ ("umulh %0,%1,%2\n\t" \ : "=r" (hiremainder) : "r" (__arg1), "r" (__arg2)); \ __value; \ }) #define addmul(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b), __hi; \ __asm__ ("madd %0,%1,%2,%3\n\t" \ : "=r" (__value) : "r" (__arg1), "r" (__arg2), "r" (hiremainder)); \ __asm__ ("umulh %0,%1,%2\n\t" \ : "=r" (__hi) : "r" (__arg1), "r" (__arg2)); \ hiremainder = (__value < hiremainder) ? __hi+1: __hi;\ __value; \ }) #define bfffo(a) \ __extension__ ({ ulong __a = (a), __value; \ __asm__ ("clz %0, %1" : "=r" (__value) : "r" (__a)); \ __value; \ }) #endif pari-2.17.2/src/kernel/riscv64/0000755000175000017500000000000014760315601014536 5ustar billbillpari-2.17.2/src/kernel/riscv64/asm0.h0000644000175000017500000000507714676526175015600 0ustar billbill#line 2 "../src/kernel/riscv64/asm0.h" /* Copyright (C) 2023 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* ASM addll mulll NOASM bfffo divll */ #ifdef ASMINLINE #define LOCAL_HIREMAINDER ulong hiremainder #define LOCAL_OVERFLOW ulong overflow #define addll(a, b)\ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("add %0,%2,%3\n\tsltu %1,%4,%2" \ : "=&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__ ("add %0,%3,%4\n\tsltu %2,%5,%3\n\tadd %0,%5,%6\n\tsltu %1,%5,%6\n\tadd %1,%6,%7\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__ ("sub %0,%2,%3\n\tsltu %1,%2,%4" \ : "=&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__ ("sub %2,%4,%5\n\tsltu %3,%4,%8\n\tsub %0,%8,%7\n\tsltu %1,%8,%6\n\tadd %1,%7,%9\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__ ("mulhu %1,%2,%3\n\tmul %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__ ("mulhu %2,%3,%4\n\tmul %0,%3,%4\n\tadd %0,%5,%6\n\tsltu %1,%5,%6\n\tadd %1,%7,%6\n\t" \ : "=&r" (__value), "=r" (hiremainder), "=r" (__temp) \ : "r" (__arg1), "r" (__arg2), "0" ((ulong) 0), "1" (hiremainder), "2" ((ulong) 0)); \ __value; \ }) #endif pari-2.17.2/src/kernel/hppa64/0000755000175000017500000000000014760315601014340 5ustar billbillpari-2.17.2/src/kernel/hppa64/asm0.h0000644000175000017500000001007014567450071015355 0ustar billbill#line 2 "../src/kernel/hppa64/asm0.h" /* Copyright (C) 2004 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* 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 ulong hiremainder #define LOCAL_OVERFLOW 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.17.2/src/kernel/x86_64/0000755000175000017500000000000014760315601014174 5ustar billbillpari-2.17.2/src/kernel/x86_64/asm0.h0000644000175000017500000001163314567450071015217 0ustar billbill#line 2 "../src/kernel/x86-64/asm0.h" /* Copyright (C) 2004 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* 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 ulong hiremainder #define LOCAL_OVERFLOW ulong overflow #define addll(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("addq %3,%0 ; adcq %1,%1" \ : "=r" (__value), "=r" (overflow) \ : "0" (__arg1), "g" (__arg2), "1" ((ulong)0) \ : "cc"); \ __value; \ }) #define addllx(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b), __temp; \ __asm__ ("subq %5,%2 ; adcq %4,%0 ; adcq %1,%1" \ : "=r" (__value), "=&r" (overflow), "=&r" (__temp) \ : "0" (__arg1), "g" (__arg2), "g" (overflow), "1" ((ulong)0), "2" ((ulong)0) \ : "cc"); \ __value; \ }) #define addllx8(a,b,c,overflow) \ do { long *__arg1 = a, *__arg2 = b, *__out = c; \ ulong __temp; \ __asm__ ("subq %5, %0 \n\t" \ "movq (%2), %0 ; adcq (%3),%0; movq %0, (%4) \n\t" \ "movq -8(%2), %0 ; adcq -8(%3),%0; movq %0, -8(%4) \n\t" \ "movq -16(%2), %0 ; adcq -16(%3),%0; movq %0, -16(%4) \n\t" \ "movq -24(%2), %0 ; adcq -24(%3),%0; movq %0, -24(%4) \n\t" \ "movq -32(%2), %0 ; adcq -32(%3),%0; movq %0, -32(%4) \n\t" \ "movq -40(%2), %0 ; adcq -40(%3),%0; movq %0, -40(%4) \n\t" \ "movq -48(%2), %0 ; adcq -48(%3),%0; movq %0, -48(%4) \n\t" \ "movq -56(%2), %0 ; adcq -56(%3),%0; movq %0, -56(%4) \n\t" \ "adcq %1, %1" \ : "=&r" (__temp), "=&r" (overflow) \ : "r" (__arg1), "r" (__arg2), "r" (__out), "g" (overflow), "0" ((ulong)0), "1" ((ulong)0) \ : "cc"); \ } while(0) #define subll(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("subq %3,%0 ; adcq %1,%1" \ : "=r" (__value), "=r" (overflow) \ : "0" (__arg1), "g" (__arg2), "1" ((ulong)0) \ : "cc"); \ __value; \ }) #define subllx(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b), __temp; \ __asm__ ("subq %5,%2 ; sbbq %4,%0 ; adcq %1,%1" \ : "=r" (__value), "=&r" (overflow), "=&r" (__temp) \ : "0" (__arg1), "g" (__arg2), "g" (overflow), "1" ((ulong)0), "2" ((ulong)0) \ : "cc"); \ __value; \ }) #define subllx8(a,b,c,overflow) \ do { long *__arg1 = a, *__arg2 = b, *__out = c; \ ulong __temp; \ __asm__ ("subq %5, %0 \n\t" \ "movq (%2), %0 ; sbbq (%3),%0; movq %0, (%4) \n\t" \ "movq -8(%2), %0 ; sbbq -8(%3),%0; movq %0, -8(%4) \n\t" \ "movq -16(%2), %0 ; sbbq -16(%3),%0; movq %0, -16(%4) \n\t" \ "movq -24(%2), %0 ; sbbq -24(%3),%0; movq %0, -24(%4) \n\t" \ "movq -32(%2), %0 ; sbbq -32(%3),%0; movq %0, -32(%4) \n\t" \ "movq -40(%2), %0 ; sbbq -40(%3),%0; movq %0, -40(%4) \n\t" \ "movq -48(%2), %0 ; sbbq -48(%3),%0; movq %0, -48(%4) \n\t" \ "movq -56(%2), %0 ; sbbq -56(%3),%0; movq %0, -56(%4) \n\t" \ "adcq %1, %1" \ : "=&r" (__temp), "=&r" (overflow) \ : "r" (__arg1), "r" (__arg2), "r" (__out), "g" (overflow), "0" ((ulong)0), "1" ((ulong)0) \ : "cc"); \ } while(0) #define mulll(a,b) \ __extension__ ({ ulong __valuelo, __arg1 = (a), __arg2 = (b); \ __asm__ ("mulq %3" \ : "=a" /* %eax */ (__valuelo), "=d" /* %edx */ (hiremainder) \ : "0" (__arg1), "rm" (__arg2)); \ __valuelo; \ }) #define addmul(a,b) \ __extension__ ({ ulong __valuelo, __arg1 = (a), __arg2 = (b), __temp; \ __asm__ ("mulq %4 ; addq %5,%0 ; adcq %6,%1" \ : "=a" /* %eax */ (__valuelo), "=&d" /* %edx */ (hiremainder), "=r" (__temp) \ : "0" (__arg1), "rm" (__arg2), "g" (hiremainder), "2" ((ulong)0)); \ __valuelo; \ }) #define divll(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("divq %4" \ : "=a" /* %eax */ (__value), "=d" /* %edx */ (hiremainder) \ : "0" /* %eax */ (__arg1), "1" /* %edx */ (hiremainder), "mr" (__arg2)); \ __value; \ }) #define bfffo(x) \ __extension__ ({ ulong __arg = (x); \ long leading_one_position; \ __asm__ ("bsrq %1,%0" : "=r" (leading_one_position) : "rm" (__arg)); \ 63 - leading_one_position; \ }) #endif pari-2.17.2/src/kernel/ppc64/0000755000175000017500000000000014760315601014172 5ustar billbillpari-2.17.2/src/kernel/ppc64/asm0.h0000644000175000017500000000511314567450071015211 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* ASM addll mulll bfffo NOASM divll */ #ifdef ASMINLINE #define LOCAL_HIREMAINDER ulong hiremainder #define LOCAL_OVERFLOW 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.17.2/src/kernel/loongarch64/0000755000175000017500000000000014760315601015364 5ustar billbillpari-2.17.2/src/kernel/loongarch64/asm0.h0000644000175000017500000000363214702761330016401 0ustar billbill#line 2 "../src/kernel/loongarch64/asm0.h" /* Copyright (C) 2013 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* ASM mulll NOASM addll bfffo divll */ #ifdef ASMINLINE #define LOCAL_HIREMAINDER ulong hiremainder #define LOCAL_OVERFLOW ulong overflow #define mulll(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("mulh.du %1,%2,%3\n\tmul.d %0,%2,%3\n" \ : "=&r" (__value), "=&r" (hiremainder) \ : "r" (__arg1), "r" (__arg2) \ : ); \ __value; \ }) #define addmul(a, b) \ __extension__ ({ \ ulong __arg1 = (a), __arg2 = (b), __value, __tmp; \ __asm__ ("mulh.du %0,%3,%4\n\tmul.d %2,%3,%4\n\t" \ "add.d %1,%2,%5\n\tsltu %2,%1,%5\n\tadd.d %0,%0,%2\n" \ : "=&r" (hiremainder), "=&r" (__value), "=&r" (__tmp) \ : "r" (__arg1), "r" (__arg2), "r" (hiremainder) \ : ); \ __value; \ }) #endif pari-2.17.2/src/kernel/ix86/0000755000175000017500000000000014760315601014034 5ustar billbillpari-2.17.2/src/kernel/ix86/asm0.h0000644000175000017500000001224414567450071015056 0ustar billbill#line 2 "../src/kernel/ix86/asm0.h" /* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* This file defines some "level 0" kernel functions for Intel ix86 */ /* It is intended for use with an external "asm" definition */ /* ASM addll mulll bfffo divll */ #ifdef ASMINLINE /* Written by Bruno Haible, 1996-1998. addllx8/subllx8 by Bill Allombert, 2011. */ /* This file can assume the GNU C extensions. (It is included only if __GNUC__ is defined.) */ /* Use local variables whenever possible. */ #define LOCAL_HIREMAINDER ulong hiremainder #define LOCAL_OVERFLOW ulong overflow #define addll(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("addl %3,%0 ; adcl %1,%1" \ : "=r" (__value), "=r" (overflow) \ : "0" (__arg1), "g" (__arg2), "1" ((ulong)0) \ : "cc"); \ __value; \ }) #define addllx(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b), __temp; \ __asm__ ("subl %5,%2 ; adcl %4,%0 ; adcl %1,%1" \ : "=r" (__value), "=&r" (overflow), "=&r" (__temp) \ : "0" (__arg1), "g" (__arg2), "g" (overflow), "1" ((ulong)0), "2" ((ulong)0) \ : "cc"); \ __value; \ }) #define addllx8(a,b,c,overflow) \ do { long *__arg1 = a, *__arg2 = b, *__out = c; \ ulong __temp; \ __asm__ ("subl %5, %0 \n\t" \ "movl (%2), %0 ; adcl (%3),%0; movl %0, (%4) \n\t" \ "movl -4(%2), %0 ; adcl -4(%3),%0; movl %0, -4(%4) \n\t" \ "movl -8(%2), %0 ; adcl -8(%3),%0; movl %0, -8(%4) \n\t" \ "movl -12(%2), %0 ; adcl -12(%3),%0; movl %0, -12(%4) \n\t" \ "movl -16(%2), %0 ; adcl -16(%3),%0; movl %0, -16(%4) \n\t" \ "movl -20(%2), %0 ; adcl -20(%3),%0; movl %0, -20(%4) \n\t" \ "movl -24(%2), %0 ; adcl -24(%3),%0; movl %0, -24(%4) \n\t" \ "movl -28(%2), %0 ; adcl -28(%3),%0; movl %0, -28(%4) \n\t" \ "adcl %1, %1" \ : "=&r" (__temp), "=&r" (overflow) \ : "r" (__arg1), "r" (__arg2), "r" (__out), "g" (overflow), "0" ((ulong)0), "1" ((ulong)0) : "cc"); \ } while(0) #define subll(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("subl %3,%0 ; adcl %1,%1" \ : "=r" (__value), "=r" (overflow) \ : "0" (__arg1), "g" (__arg2), "1" ((ulong)0) \ : "cc"); \ __value; \ }) #define subllx(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b), __temp; \ __asm__ ("subl %5,%2 ; sbbl %4,%0 ; adcl %1,%1" \ : "=r" (__value), "=&r" (overflow), "=&r" (__temp) \ : "0" (__arg1), "g" (__arg2), "g" (overflow), "1" ((ulong)0), "2" ((ulong)0) \ : "cc"); \ __value; \ }) #define subllx8(a,b,c,overflow) \ do { long *__arg1 = a, *__arg2 = b, *__out = c; \ ulong __temp; \ __asm__ ("subl %5, %0 \n\t" \ "movl (%2), %0 ; sbbl (%3),%0; movl %0, (%4) \n\t" \ "movl -4(%2), %0 ; sbbl -4(%3),%0; movl %0, -4(%4) \n\t" \ "movl -8(%2), %0 ; sbbl -8(%3),%0; movl %0, -8(%4) \n\t" \ "movl -12(%2), %0 ; sbbl -12(%3),%0; movl %0, -12(%4) \n\t" \ "movl -16(%2), %0 ; sbbl -16(%3),%0; movl %0, -16(%4) \n\t" \ "movl -20(%2), %0 ; sbbl -20(%3),%0; movl %0, -20(%4) \n\t" \ "movl -24(%2), %0 ; sbbl -24(%3),%0; movl %0, -24(%4) \n\t" \ "movl -28(%2), %0 ; sbbl -28(%3),%0; movl %0, -28(%4) \n\t" \ "adcl %1, %1" \ : "=&r" (__temp), "=&r" (overflow) \ : "r" (__arg1), "r" (__arg2), "r" (__out), "g" (overflow), "0" ((ulong)0), "1" ((ulong)0) : "cc"); \ } while(0) #define mulll(a,b) \ __extension__ ({ ulong __valuelo, __arg1 = (a), __arg2 = (b); \ __asm__ ("mull %3" \ : "=a" /* %eax */ (__valuelo), "=d" /* %edx */ (hiremainder) \ : "0" (__arg1), "rm" (__arg2)); \ __valuelo; \ }) #define addmul(a,b) \ __extension__ ({ ulong __valuelo, __arg1 = (a), __arg2 = (b), __temp; \ __asm__ ("mull %4 ; addl %5,%0 ; adcl %6,%1" \ : "=a" /* %eax */ (__valuelo), "=&d" /* %edx */ (hiremainder), "=r" (__temp) \ : "0" (__arg1), "rm" (__arg2), "g" (hiremainder), "2" ((ulong)0)); \ __valuelo; \ }) #define divll(a,b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("divl %4" \ : "=a" /* %eax */ (__value), "=d" /* %edx */ (hiremainder) \ : "0" /* %eax */ (__arg1), "1" /* %edx */ (hiremainder), "mr" (__arg2)); \ __value; \ }) #define bfffo(x) \ __extension__ ({ ulong __arg = (x); \ int leading_one_position; \ __asm__ ("bsrl %1,%0" : "=r" (leading_one_position) : "rm" (__arg)); \ 31 - leading_one_position; \ }) #endif pari-2.17.2/src/kernel/arm/0000755000175000017500000000000014760315601014015 5ustar billbillpari-2.17.2/src/kernel/arm/asm0.h0000644000175000017500000000503614567450071015040 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* ASM addll mulll NOASM bfffo divll */ #ifdef ASMINLINE #define LOCAL_HIREMAINDER ulong hiremainder #define LOCAL_OVERFLOW ulong overflow #define addll(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("adds %0,%2,%3\n\tadc %1,%4,%4\n\t" \ : "=&r" (__value), "=&r" (overflow) \ : "r" (__arg1), "r" (__arg2), "r" ((ulong)0): "cc"); \ __value; \ }) #define addllx(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("subs %1,%4,#1\n\tadcs %0,%2,%3\n\tadc %1,%5,%5\n\t" \ : "=&r" (__value), "=&r" (overflow) \ : "r" (__arg1), "r" (__arg2), "r" (overflow), "r" ((ulong)0) \ : "cc"); \ __value; \ }) #define subll(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("subs %0,%2,%3\n\tadc %1,%4,%4\n\trsb %1,%1,#1\n\t" \ : "=&r" (__value), "=&r" (overflow) \ : "r" (__arg1), "r" (__arg2), "r" ((ulong)0) \ : "cc"); \ __value; \ }) #define subllx(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("rsbs %1,%4,%5\n\tsbcs %0,%2,%3\n\tadc %1,%5,%5\n\trsb %1,%1,#1\n\t" \ : "=&r" (__value), "=&r" (overflow) \ : "r" (__arg1), "r" (__arg2), "r" (overflow), "r" ((ulong)0) \ : "cc"); \ __value; \ }) #define mulll(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("umull %0,%1,%2,%3\n\t" \ : "=&r" (__value), "=&r" (hiremainder) \ : "r" (__arg1), "r" (__arg2)); \ __value; \ }) #define addmul(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("umlal %0,%1,%2,%3\n\t" \ : "=&r" (__value), "=&r" (hiremainder) \ : "r" (__arg1), "r" (__arg2), "1" ((ulong) 0), "0" (hiremainder)); \ __value; \ }) #if 0 /* Not supported by all CPU */ #define bfffo(a) \ __extension__ ({ \ ulong __arg1 = (a), __value; \ __asm__ ("clz %0,%1\n\t" \ : "=&r" (__value) \ : "r" (__arg1)); \ __value; \ }) #endif #endif pari-2.17.2/src/kernel/mips/0000755000175000017500000000000014760315601014206 5ustar billbillpari-2.17.2/src/kernel/mips/asm0.h0000644000175000017500000000604414567450071015231 0ustar billbill#line 2 "../src/kernel/mips/asm0.h" /* Copyright (C) 2013 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* ASM mulll NOASM addll bfffo divll */ #ifdef ASMINLINE #define LOCAL_HIREMAINDER ulong hiremainder #define LOCAL_OVERFLOW ulong overflow #if defined(__mips_isa_rev) && __mips_isa_rev >= 6 #define mulll(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("muhu %0,%2,%3\n\tmulu %1,%2,%3" \ : "=&r" (__value), "=&r" (hiremainder) \ : "r" (__arg1), "r" (__arg2) \ : ); \ __value; \ }) #define addmul(a, b) \ __extension__ ({ \ ulong __arg1 = (a), __arg2 = (b), __value, __tmp; \ __asm__ ("muhu %0,%3,%4\n\tmulu %2,%3,%4\n\t" \ "addu %1,%2,%5\n\tsltu %2,%1,%5\n\taddu %0,%0,%2" \ : "=&r" (hiremainder), "=&r" (__value), "=&r" (__tmp) \ : "r" (__arg1), "r" (__arg2), "r" (hiremainder) \ : "hi", "lo"); \ __value; \ }) #else #define mulll(a, b) \ __extension__ ({ ulong __value, __arg1 = (a), __arg2 = (b); \ __asm__ ("multu %2,%3\n\tmfhi %1" \ : "=&l" (__value), "=&r" (hiremainder) \ : "r" (__arg1), "r" (__arg2) \ : "hi"); \ __value; \ }) #define addmul(a, b) \ __extension__ ({ \ ulong __arg1 = (a), __arg2 = (b), __value, __tmp; \ __asm__ ("multu %3,%4\n\tmfhi %0\n\tmflo %2\n\t" \ "addu %1,%2,%5\n\tsltu %2,%1,%5\n\taddu %0,%0,%2" \ : "=&r" (hiremainder), "=&r" (__value), "=&r" (__tmp) \ : "r" (__arg1), "r" (__arg2), "r" (hiremainder) \ : "hi", "lo"); \ __value; \ }) #endif #endif pari-2.17.2/src/kernel/sparcv8_micro/0000755000175000017500000000000014760315601016015 5ustar billbillpari-2.17.2/src/kernel/sparcv8_micro/MakeLVL0.SH0000644000175000017500000000020411636712103017555 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.17.2/src/kernel/sparcv8_micro/asm0-common.h0000644000175000017500000000507314567450071020327 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* 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.17.2/src/kernel/sparcv8_micro/asm0.h0000644000175000017500000000201514567450071017032 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* 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.17.2/src/kernel/ia64/0000755000175000017500000000000014760315601014001 5ustar billbillpari-2.17.2/src/kernel/ia64/asm1.h0000644000175000017500000000403714567450071015025 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__ ({ \ ulong _di, _x = (x), _y = (y), _q, _ql, _r; \ 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.17.2/src/kernel/ia64/asm0.h0000644000175000017500000000531114567450071015020 0ustar billbill#line 2 "../src/kernel/ia64/asm0.h" /* Copyright (C) 2006 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* ASM mulll bfffo NOASM addll divll */ #ifdef ASMINLINE /* Written by Guillaume Hanrot */ #define LOCAL_HIREMAINDER 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.17.2/src/kernel/alpha/0000755000175000017500000000000014760315601014323 5ustar billbillpari-2.17.2/src/kernel/alpha/asm1.h0000644000175000017500000000712214567450071015345 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* 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__ ({ \ ulong _di, _x = (x), _y = (y), _q, _ql, _r; \ 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) { ulong _di, _x = (x), _y = (y), _q, _ql, _r; 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.17.2/src/kernel/alpha/asm0.h0000644000175000017500000000506314567450071015346 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* ASM addll mulll NOASM bfffo divll */ #ifdef ASMINLINE #define LOCAL_HIREMAINDER ulong hiremainder #define LOCAL_OVERFLOW 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.17.2/src/desc/0000755000175000017500000000000014760315601012674 5ustar billbillpari-2.17.2/src/desc/PARI/0000755000175000017500000000000014760315601013427 5ustar billbillpari-2.17.2/src/desc/PARI/822.pm0000755000175000017500000000731314760123736014315 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", "Obsolete","Help", "Iterator","Wrapper","Description", "Doc","Variant"); 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}); warn("Unknown field $field in $func"); my $val=$data{$func}->{$field}; $val =~ s/\n/\n /g; print $STREAM $field.": $val\n"; } print $STREAM "\n"; } } 1; pari-2.17.2/src/desc/merge_8220000755000175000017500000000045214567450071014323 0ustar billbill#!/usr/bin/perl -w BEGIN { @INC=(".",@INC); } 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.17.2/src/desc/gen_tune0000755000175000017500000000434414760123736014441 0ustar billbill#! /usr/bin/perl -w use strict; sub gendefine { my($hash)=@_; for (sort keys %{$hash}) { printf TUNE "#define __%-30s %s\n",$_,$hash->{$_}; } } sub gendefinefile { my($file,$hash32,$hash64)=@_; open TUNE, ">$file"; print TUNE "#ifdef LONG_IS_64BIT\n"; gendefine $hash64; print TUNE "#else\n"; gendefine $hash32; print TUNE "#endif\n"; close TUNE; } sub gentune { my (%none32, %none64, %gmp32, %gmp64, @list); while(<>) { /^#/ and next; my($tunable,$none32,$gmp32,$none64,$gmp64) = split(' '); push @list,$tunable; $none32{$tunable}=$none32; $gmp32{$tunable}=$gmp32; $none64{$tunable}=$none64; $gmp64{$tunable}=$gmp64; } open TUNE, ">src/headers/paritune.h"; print TUNE <src/kernel/none/tune-gen.h"; print TUNE "#ifdef PARI_TUNE\n"; for (@list) { printf TUNE "long %-30s = __%s;\n",$_,$_; } print TUNE "#endif\n"; close TUNE; gendefinefile "src/kernel/none/tune.h",\%none32,\%none64; gendefinefile "src/kernel/gmp/tune.h",\%gmp32,\%gmp64; } sub gendesc { my ($file,$hash32,$hash64)=@_; open DESC, "<$file"; my $hash = $hash64; while() { /^#else/ and $hash=$hash32; /#define[ \t]+__([^ ]+)[ \t]+([0-9]+)/ and $hash->{$1}=$2; } close DESC; } sub cc { my $v = $_[0]; return $v if (defined $v); return -1; } sub gendescfile { my (%none32, %none64, %gmp32, %gmp64); gendesc "src/kernel/none/tune.h",\%none32,\%none64; gendesc "src/kernel/gmp/tune.h",\%gmp32,\%gmp64; my %hlist=map {$_=>1} (keys %none32, keys %none64, keys %gmp32, keys %gmp64); my @list = sort keys %hlist; printf "%-30s %7s %7s %7s %7s\n","#LIMIT","none32","gmp32","none64","gmp64"; for $_ (@list) { printf "%-30s %7s %7s %7s %7s\n",$_,cc($none32{$_}),cc($gmp32{$_}), cc($none64{$_}),cc($gmp64{$_}); } } my $arg = shift; if ($arg eq "--gendesc") { &gendescfile; } elsif ($arg eq "--gentune") { &gentune; } else { die("Error: gentune --gendesc|--gentune\n"); } pari-2.17.2/src/desc/deftune0000644000175000017500000001106614676526175014275 0ustar billbill#LIMIT none32 gmp32 none64 gmp64 AGM_ATAN_LIMIT 5088 2848 3584 3840 DIVRR_GMP_LIMIT -1 128 -1 256 EXPNEWTON_LIMIT 2112 6304 4224 4224 EXTGCD_HALFGCD_LIMIT 83 -1 70 -1 F2x_MUL_KARATSUBA_LIMIT 13 13 11 11 F2x_MUL_MULII_LIMIT 6265 774 662 41 F2xqX_BARRETT_LIMIT 58 48 56 48 F2xqX_DIVREM_BARRETT_LIMIT 127 127 127 97 F2xqX_EXTGCD_LIMIT 10 10 10 10 F2xqX_GCD_LIMIT 257 257 468 310 F2xqX_HALFGCD_LIMIT 43 61 64 89 F2xqX_INVBARRETT_LIMIT 38 40 50 50 F2xqX_REM_BARRETT_LIMIT 127 127 127 101 Flx_BARRETT2_LIMIT 102 52 63 31 Flx_BARRETT_LIMIT 433 164 131 92 Flx_DIVREM2_BARRETT_LIMIT 194 111 28 14 Flx_DIVREM_BARRETT_LIMIT 1888 470 407 161 Flx_EXTGCD2_LIMIT 25 24 31 22 Flx_EXTGCD_LIMIT 21 21 17 17 Flx_GCD2_LIMIT 2817 621 2266 937 Flx_GCD_LIMIT 4986 1246 621 426 Flx_HALFGCD2_LIMIT 307 119 32 31 Flx_HALFGCD_LIMIT 1245 586 265 120 Flx_INVBARRETT2_LIMIT 1396 397 28 22 Flx_INVBARRETT_LIMIT 1233 501 316 200 Flx_MUL2_KARATSUBA_LIMIT 9 9 10 11 Flx_MUL2_MULII_LIMIT 21 8 14 8 Flx_MUL_KARATSUBA_LIMIT 57 57 38 33 Flx_MUL_MULII_LIMIT 601 146 66 30 Flx_REM2_BARRETT_LIMIT 296 89 241 89 Flx_REM_BARRETT_LIMIT 1888 388 407 159 Flx_SQR2_KARATSUBA_LIMIT 19 18 15 15 Flx_SQR2_SQRI_LIMIT 67 20 28 14 Flx_SQR_KARATSUBA_LIMIT 109 112 94 93 Flx_SQR_SQRI_LIMIT 469 183 77 37 FlxqX_BARRETT_LIMIT 17 17 17 17 FlxqX_DIVREM_BARRETT_LIMIT 46 46 46 46 FlxqX_EXTGCD_LIMIT 44 19 10 21 FlxqX_GCD_LIMIT 898 245 407 116 FlxqX_HALFGCD_LIMIT 174 53 57 30 FlxqX_INVBARRETT_LIMIT 22 22 22 22 FlxqX_REM_BARRETT_LIMIT 48 48 48 48 FpXQX_BARRETT_LIMIT 12 12 12 12 FpXQX_DIVREM_BARRETT_LIMIT 30 30 30 30 FpXQX_EXTGCD_LIMIT 10 10 10 10 FpXQX_GCD_LIMIT 177 116 152 101 FpXQX_HALFGCD_LIMIT 47 30 43 29 FpXQX_INVBARRETT_LIMIT 40 40 40 40 FpXQX_REM_BARRETT_LIMIT 30 30 30 30 FpX_BARRETT_LIMIT 144 44 85 38 FpX_DIVREM_BARRETT_LIMIT 306 116 292 113 FpX_EXTGCD_LIMIT 10 10 21 19 FpX_GCD_LIMIT 826 234 282 194 FpX_HALFGCD_LIMIT 108 53 56 45 FpX_INVBARRETT_LIMIT 337 121 254 111 FpX_REM_BARRETT_LIMIT 306 127 306 111 Fp_POW_BARRETT_LIMIT 97 11 101 127 Fp_POW_REDC_LIMIT 99 3 99 17 GCD_HALFGCD_LIMIT 13 -1 9 -1 HALFGCD_LIMIT 79 58 85 66 INVMOD_GMP_LIMIT -1 3 -1 3 INVNEWTON_LIMIT 2112 2976 35200 4800 LOGAGMCX_LIMIT 1856 1024 832 1408 LOGAGM_LIMIT 1760 1440 1024 384 MULII_FFT_LIMIT 1386 -1 1441 -1 MULII_KARATSUBA_LIMIT 18 -1 23 -1 MULRR_MULII_LIMIT 13504 608 13440 3520 RgX_MUL_LIMIT 5 7 9 9 RgX_SQR_LIMIT 26 34 35 38 SQRI_FFT_LIMIT 1469 -1 1651 -1 SQRI_KARATSUBA_LIMIT 27 -1 36 -1 SQRR_SQRI_LIMIT 640 288 3456 768 ZM2_MUL_LIMIT 13 15 13 14 pari-2.17.2/src/desc/doc_make0000755000175000017500000001136114760123736014374 0ustar billbill#!/usr/bin/perl BEGIN { @INC=(".",@INC); } use warnings FATAL => 'all'; use strict; use PARI::822; my (%funcs, %Fun_by_sec, %sec_header, @SECTIONS); PARI::822::read(\%funcs, "pari.desc"); @SECTIONS = qw( programming/control programming/specific programming/parallel default operators conversions combinatorics number_theoretical polynomials linear_algebra transcendental sums number_fields algebras elliptic_curves hypergeometric_motives l_functions modular_forms modular_symbols graphic ); for (keys %funcs) { my ($s) = $funcs{$_}->{Section}; next if (!$s); my ($c) = $funcs{$_}->{Class}; if ($c eq 'header') { $sec_header{$s} = $funcs{$_}->{Doc} } else { push(@{$Fun_by_sec{$s}}, $_); } } for (@SECTIONS) { my ($sec) = $_; my ($head) = $sec_header{$sec}; print "$head\n" if defined($head); next if (!$Fun_by_sec{$sec}); for ( sort @{$Fun_by_sec{$sec}} ) { my ($fun) = $funcs{$_}; my ($doc) = $fun->{Doc}; next if (!defined($doc)); my ($args) = $fun->{Help}; my ($v); $doc =~ s/^[\n\t ]*(.)/uc($1)/e; $args =~ s/ *:.*//s; # sanity checks if ($args =~ /([_a-zA-Z0-9]*)\(/ && $fun->{Function} ne $1) { die "fix $fun->{Function} Help" } if ($fun->{Help} =~ /\$/) { die "\$ in $fun->{Function}"; } die "double parenthesis in $fun->{Function} proto" if ($args =~ /\)\)/); # ok 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/([a-zA-Z]\w+)/\\var{$1}/g; $v =~ s/\^([a-z])/\\hbox{\\kbd{\\pow}}$1/g; $v =~ s/\\var\{flag\}/\\fl/g; $v =~ s/\\var\{(\d+)\}/{$1}/g; $v =~ s/_/\\_/g; # don't merge with first subst: \var{} rule kills it $v =~ s/~/\\til{}/g; $v = "\$($v)\$"; } if ($doc !~ /\\syn\w*\{/ && $sec !~ /programming\/control/) { $doc .= library_syntax($fun, $args); } s/_def_//; my ($secname) = $_; my ($l) = ($fun->{Section} =~ 'default')? "def,$_": $_; my ($idx) = ($secname =~ s/_/\\_/g)? $l: $secname; print "\n\\subsec{$secname$v}\\kbdsidx{$idx}\\label{se:$l}\n$doc\n"; } } print '\vfill\eject'; sub library_syntax { my ($fun, $args) = @_; return '' if ($fun->{Class} =~ /^(gp|default|gp_default)$/); my ($Cname) = $fun->{'C-Name'}; return '' if (!$Cname); my ($Variant) = $fun->{Variant}; my ($Proto) = $fun->{Prototype}; $Proto =~ s/\\n.*//; # delete Mnemonics my (@proto) = split(//, $Proto); $args =~ s/[{}&]//g; $args =~ s/ *=[^,\)]*//g; # delete default values my (@ARGS) = split(/[,^] */, $args); # ^ for O(p^e) my ($type) = "GEN"; my (@vars)=(); $args = ''; for (my $i = 0; $i <= $#proto; ) { my ($c) = $proto[$i++]; if ($c eq 'i') { $type = "int"; next; } if ($c eq 'l') { $type = "long"; next; } if ($c eq 'v') { $type = "void"; next; } if ($c =~ /^[GWIJE]$/) {$args .= ", GEN " . shift(@ARGS); next;} if ($c eq 'U') {$args .= ", ulong " . 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]$/ and $i == $#proto && $proto[$i] eq '*') { my ($v) = shift(@ARGS); $v =~ s/\*$//; $args .= ", GEN vec_" . $v; next; } if ($c =~ /^[rs]$/) {$args .= ", const char *" . shift(@ARGS); next;} if ($c eq 'p') {$args .= ", long prec"; next;} if ($c eq 'b') {$args .= ", long bitprec"; next;} if ($c eq 'P') {$args .= ", long precdl"; next;} if ($c eq 'C') {$args .= ", GEN ctx"; next;} if ($c eq '') { next; } if ($c eq 'D') { $c = $proto[$i++]; if ($c eq 'G') {$args .= ", GEN " . shift(@ARGS) ." = NULL"; next;} if ($c =~ /^[rs]$/) {$args .= ", const char *" . shift(@ARGS) ." = NULL"; next;} if ($c eq '&') {$args .= ", GEN *". shift(@ARGS) ." = NULL"; next;} if ($c eq 'P') {$args .= ", long precdl"; next;} if ($c eq 'n') { my ($v) = shift(@ARGS); $args .= ", long $v = -1"; push @vars,"\\kbd{$v}"; next; } if ($c eq 'V') { next; } if ($c =~ /^[EI]$/) { $args .= ", GEN ". shift(@ARGS) ." = NULL"; next; } while (($c = $proto[$i++]) ne ',') {} } } $args =~ s/^, //; my ($post); my ($l)=scalar @vars; if ($l==0) { $post=''; } elsif ($l==1) { $post = " where $vars[0] is a variable number"; } else { my ($vl)=join(", ",@vars); $post = " where $vl are variable numbers"; } my ($txt) = "\n\nThe library syntax is \\fun{$type}{$Cname}{$args}$post."; $txt .= "\n$Variant" if ($Variant); return $txt; } pari-2.17.2/src/desc/gen_proto0000755000175000017500000000425514567450071014632 0ustar billbill#!/usr/bin/perl -w BEGIN { @INC=(".",@INC); } use PARI::822; $class=$ARGV[0]; $i = 2; # update MAX_SECTION in gplib.c when changing this %secnumber=( 'operators' => $i++, 'conversions' => $i++, 'combinatorics' => $i++, 'number_theoretical' => $i++, 'polynomials' => $i++, 'linear_algebra' => $i++, 'transcendental' => $i++, 'sums' => $i++, 'number_fields' => $i++, 'algebras' => $i++, 'elliptic_curves' => $i++, 'l_functions' => $i++, 'hypergeometric_motives'=> $i++, 'modular_forms' => $i++, 'modular_symbols' => $i++, 'graphic' => $i++, ); $i++;# skip next = PARI community $secnumber{'symbolic_operators'} = $i++; $secnumber{'member_functions'} = $i++; $secnumber{'programming/internals'} = $i++; $secnumber{'default'} = $i++; # join $secnumber{'programming/control'} = 1; $secnumber{'programming/specific'} = 1; $secnumber{'programming/parallel'} = 1; print <pending; if (workid) *workid = mt->workid; mt->pending = NULL; *pending = 0; return done; } static int single_is_thread = 0; static long single_trace_level = 0; static void mtsingle_queue_submit(struct mt_state *mt, long workid, GEN work) { int is_thread = single_is_thread; single_is_thread = 1; mt->pending = work? closure_callgenvec(mt->worker, work): NULL; single_is_thread = is_thread; mt->workid = workid; } static void mtsingle_queue_end(void) { } static GEN mtsequential_queue_get(struct mt_state *mt, long *workid, long *pending) { GEN done = mt->pending; if (workid) *workid = mt->workid; mt->pending = NULL; *pending = 0; return done; } static void mtsequential_queue_submit(struct mt_state *mt, long workid, GEN work) { mt->pending = work? closure_callgenvec(mt->worker, work): NULL; mt->workid = workid; } static void mtsequential_queue_end(void) { } int mtsingle_is_thread(void) { return single_is_thread; } void mtsingle_err_recover(long er) { (void) er; if (single_is_thread) { evalstate_set_trace(single_trace_level); single_is_thread = 0; } } void mtsingle_queue_start(struct pari_mt *pt, GEN worker) { pt->get = mtsingle_queue_get; pt->submit = mtsingle_queue_submit; pt->end = mtsingle_queue_end; pt->mt.worker = worker; pt->mt.pending = NULL; single_trace_level = evalstate_get_trace(); } void mtsequential_queue_start(struct pari_mt *pt, GEN worker) { pt->get = mtsequential_queue_get; pt->submit = mtsequential_queue_submit; pt->end = mtsequential_queue_end; pt->mt.worker = worker; pt->mt.pending = NULL; } void mt_queue_end(struct pari_mt *pt) { pt->end(); } void mt_queue_submit(struct pari_mt *pt, long workid, GEN work) { pt->submit(&pt->mt, workid, work); } GEN mt_queue_get(struct pari_mt *pt, long *workid, long *pending) { return pt->get(&pt->mt, workid, pending); } void mt_queue_start(struct pari_mt *pt, GEN worker) { return mt_queue_start_lim(pt, worker, 0); } void mtstate_save(struct pari_mtstate *mt) { if (mt_is_parallel()) { mt->is_thread = 0; mt->trace_level = 0; mt->pending_threads = 1; } else { mt->is_thread = single_is_thread; mt->trace_level = single_trace_level; mt->pending_threads = 0; } } void mtstate_restore(struct pari_mtstate *mt) { if (!mt_is_parallel()) { single_is_thread = mt->is_thread; single_trace_level = mt->trace_level; } if (!mt->pending_threads && mt_is_parallel()) mt_queue_reset(); } void mtstate_reset(void) { single_is_thread = 0; single_trace_level = 0; if (mt_is_parallel()) mt_queue_reset(); } pari-2.17.2/src/mt/mpi.c0000644000175000017500000002663414676526175013362 0ustar billbill/* Copyright (C) 2013 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include "pari.h" #include "paripriv.h" #include "../src/language/anal.h" #include "mt.h" #define DEBUGLEVEL DEBUGLEVEL_mt static THREAD int pari_MPI_size, pari_MPI_rank; static THREAD long nbreq = 0; enum PMPI_cmd { PMPI_close, PMPI_worker, PMPI_work, PMPI_eval, PMPI_exportadd, PMPI_exportdel}; struct mt_mstate { long n; int source; long nbint; long *workid; }; static struct mt_mstate pari_mt_data; static struct mt_mstate *pari_mt; static void send_long(long a, long dest) { BLOCK_SIGINT_START MPI_Send(&a, 1, MPI_LONG, dest, 0, MPI_COMM_WORLD); BLOCK_SIGINT_END } static void send_bcast_long(long a, MPI_Comm comm) { BLOCK_SIGINT_START MPI_Bcast(&a, 1, MPI_LONG, 0, comm); BLOCK_SIGINT_END } static long recv_bcast_long(MPI_Comm comm) { long a; BLOCK_SIGINT_START MPI_Bcast(&a, 1, MPI_LONG, 0, comm); BLOCK_SIGINT_END return a; } static void send_request(enum PMPI_cmd ecmd, long dest) { send_long((long)ecmd, dest); } static void send_request_all(enum PMPI_cmd ecmd, long n) { long i; for (i=1; i<=n; i++) send_long((long)ecmd, i); } static void send_GEN(GEN elt, int dest) { pari_sp av = avma; GEN reloc = copybin_unlink(elt); GENbin *buf = copy_bin_canon(mkvec2(elt,reloc)); long size = sizeof(GENbin) + buf->len*sizeof(ulong); { BLOCK_SIGINT_START MPI_Send(buf, size/sizeof(long), MPI_LONG, dest, 0, MPI_COMM_WORLD); BLOCK_SIGINT_END } pari_free(buf); set_avma(av); } static void send_bcast_GEN(GEN elt, MPI_Comm comm) { pari_sp av = avma; GEN reloc = copybin_unlink(elt); GENbin *buf = copy_bin_canon(mkvec2(elt,reloc)); long size = sizeof(GENbin) + buf->len*sizeof(ulong); { send_bcast_long(size, comm); BLOCK_SIGINT_START MPI_Bcast(buf, size/sizeof(long), MPI_LONG, 0, comm); BLOCK_SIGINT_END } pari_free(buf); set_avma(av); } static void send_bcast_vlong(long *a, long n, MPI_Comm comm) { BLOCK_SIGINT_START MPI_Bcast(a, n, MPI_LONG, 0, comm); BLOCK_SIGINT_END } static void send_request_GEN(enum PMPI_cmd ecmd, GEN elt, int dest) { send_request(ecmd, dest); send_GEN(elt, dest); } static long recvfrom_long(int src) { long a; BLOCK_SIGINT_START MPI_Recv(&a, 1, MPI_LONG, src, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); BLOCK_SIGINT_END return a; } static enum PMPI_cmd recvfrom_request(int src) { return (enum PMPI_cmd) recvfrom_long(src); } static GENbin * recvstatus_buf(int source, MPI_Status *status) { int size; GENbin *buf; BLOCK_SIGINT_START MPI_Get_count(status, MPI_LONG, &size); buf = (GENbin *)pari_malloc(size*sizeof(long)); MPI_Recv(buf, size, MPI_LONG, source, 0/* tag */, MPI_COMM_WORLD, MPI_STATUS_IGNORE); BLOCK_SIGINT_END return buf; } static GEN recvstatus_GEN(int source, MPI_Status *status) { GEN res; GENbin *buf = recvstatus_buf(source, status); buf->rebase = &shiftaddress_canon; res = bin_copy(buf); bincopy_relink(gel(res,1),gel(res,2)); return gel(res,1); } static void recvstatus_void(int source, MPI_Status *status) { GENbin *buf = recvstatus_buf(source, status); free(buf); } static GEN recvfrom_GEN(int src) { MPI_Status status; BLOCK_SIGINT_START MPI_Probe(src, 0, MPI_COMM_WORLD, &status); BLOCK_SIGINT_END return recvstatus_GEN(src, &status); } static GEN recv_bcast_GEN(MPI_Comm comm) { GEN res; GENbin *buf; long size; size = recv_bcast_long(comm); buf = (GENbin *)pari_malloc(size); BLOCK_SIGINT_START MPI_Bcast(buf, size/sizeof(long), MPI_LONG, 0, comm); BLOCK_SIGINT_END buf->rebase = &shiftaddress_canon; res = bin_copy(buf); bincopy_relink(gel(res,1),gel(res,2)); return gel(res,1); } static void recv_bcast_vlong(long *a, long n, MPI_Comm comm) { BLOCK_SIGINT_START MPI_Bcast(a, n, MPI_LONG, 0, comm); BLOCK_SIGINT_END } static GEN recvany_GEN(int *source) { MPI_Status status; BLOCK_SIGINT_START MPI_Probe(MPI_ANY_SOURCE, 0 /* tag */, MPI_COMM_WORLD, &status); *source = status.MPI_SOURCE; BLOCK_SIGINT_END return recvstatus_GEN(*source, &status); } static void recvany_void(int *source) { MPI_Status status; BLOCK_SIGINT_START MPI_Probe(MPI_ANY_SOURCE, 0 /* tag */, MPI_COMM_WORLD, &status); *source = status.MPI_SOURCE; BLOCK_SIGINT_END recvstatus_void(*source, &status); } static jmp_buf child_env; static void pari_MPI_child(void) { pari_sp av = avma; ulong rsize = 0, vsize = 0; GEN worker = NULL, work, done; struct gp_context rec; pari_mt_nbthreads = 1; gp_context_save(&rec); if (setjmp(child_env)) { send_GEN(pari_err_last(), 0); gp_context_restore(&rec); } while (1) switch (recvfrom_request(0)) { case PMPI_worker: { MPI_Comm comm; long n = recv_bcast_long(MPI_COMM_WORLD), status = pari_MPI_rank <= n; MPI_Comm_split(MPI_COMM_WORLD, status, pari_MPI_rank, &comm); if (status==0) { MPI_Comm_free(&comm); break; } rsize = recv_bcast_long(comm); vsize = recv_bcast_long(comm); precreal = recv_bcast_long(comm); recv_bcast_vlong(varpriority-1,MAXVARN+2,comm); { pari_sp ltop = avma; GEN tab = recv_bcast_GEN(comm); if (!gequal(tab, primetab)) { long i, l = lg(tab); GEN old = primetab, t = cgetg_block(l, t_VEC); for (i = 1; i < l; i++) gel(t,i) = gclone(gel(tab,i)); primetab = t; gunclone_deep(old); } set_avma(ltop); } paristack_setsize(rsize, vsize); worker = recv_bcast_GEN(comm); MPI_Comm_free(&comm); gp_context_save(&rec); av = avma; break; } case PMPI_work: work = recvfrom_GEN(0); done = closure_callgenvec(worker, work); send_GEN(done, 0); set_avma(av); break; case PMPI_eval: (void) closure_evalgen(recv_bcast_GEN(MPI_COMM_WORLD)); set_avma(av); break; case PMPI_exportadd: { GEN str = recv_bcast_GEN(MPI_COMM_WORLD); GEN val = recv_bcast_GEN(MPI_COMM_WORLD); entree *ep = fetch_entry(GSTR(str)); export_add(ep->name, val); set_avma(av); break; } case PMPI_exportdel: { GEN str = recv_bcast_GEN(MPI_COMM_WORLD); entree *ep = fetch_entry(GSTR(str)); export_del(ep->name); set_avma(av); break; } case PMPI_close: MPI_Barrier(MPI_COMM_WORLD); MPI_Finalize(); exit(0); break; } } void mt_err_recover(long er) { if (pari_MPI_rank) longjmp(child_env,er); else mtsingle_err_recover(er); } void mt_break_recover(void) { if (!pari_MPI_rank) mtsingle_err_recover(0); } void mt_sigint_block(void) { } void mt_sigint_unblock(void) { } void mt_sigint(void) {} void mt_thread_init(void) { } int mt_is_parallel(void) { return !!pari_mt; } int mt_is_thread(void) { return pari_MPI_rank ? 1 : mtsingle_is_thread(); } long mt_nbthreads(void) { return pari_mt || pari_MPI_rank || pari_MPI_size <= 2 ? 1: pari_mt_nbthreads; } void mt_export_add(const char *str, GEN val) { pari_sp av = avma; long n = pari_MPI_size-1; GEN s; if (pari_mt || pari_MPI_rank) pari_err(e_MISC,"export not allowed during parallel sections"); export_add(str, val); s = strtoGENstr(str); send_request_all(PMPI_exportadd, n); send_bcast_GEN(s, MPI_COMM_WORLD); send_bcast_GEN(val, MPI_COMM_WORLD); set_avma(av); } void mt_export_del(const char *str) { pari_sp av = avma; long n = pari_MPI_size-1; if (pari_MPI_rank) pari_err(e_MISC,"unexport not allowed during parallel sections"); export_del(str); send_request_all(PMPI_exportdel, n); send_bcast_GEN(strtoGENstr(str), MPI_COMM_WORLD); set_avma(av); } void mt_broadcast(GEN code) { if (!pari_MPI_rank && !pari_mt) { send_request_all(PMPI_eval, pari_MPI_size-1); send_bcast_GEN(code, MPI_COMM_WORLD); } } void pari_mt_init(void) { int res = MPI_Init(0, NULL); if (res == MPI_SUCCESS) { MPI_Comm_size(MPI_COMM_WORLD, &pari_MPI_size); MPI_Comm_rank(MPI_COMM_WORLD, &pari_MPI_rank); if (pari_MPI_rank) pari_MPI_child(); #ifdef _IOFBF /* HACK: most MPI implementation does not handle stdin well. stdinsize is sufficient for the largest test file to fit */ setvbuf(stdin,pari_malloc(128*1024),_IOFBF,128*1024); #endif if (!pari_mt_nbthreads) pari_mt_nbthreads = maxss(1, pari_MPI_size-1); } else { pari_MPI_size = 0; pari_MPI_rank = 0; pari_mt_nbthreads = 1; } pari_mt = NULL; } void pari_mt_close(void) { long i; if (!pari_MPI_rank) for (i = 1; i < pari_MPI_size; i++) send_request(PMPI_close, i); MPI_Barrier(MPI_COMM_WORLD); MPI_Finalize(); } static GEN mtmpi_queue_get(struct mt_state *junk, long *workid, long *pending) { struct mt_mstate *mt = pari_mt; GEN done; (void) junk; if (mt->nbint<=mt->n) { mt->source=mt->nbint; *pending = nbreq; return NULL; } done = recvany_GEN(&mt->source); nbreq--; *pending = nbreq; if (workid) *workid = mt->workid[mt->source]; if (typ(done) == t_ERROR) { if (err_get_num(done)==e_STACK) pari_err(e_STACKTHREAD); else pari_err(0,done); } return done; } static void mtmpi_queue_submit(struct mt_state *junk, long workid, GEN work) { struct mt_mstate *mt = pari_mt; (void) junk; if (!work) { mt->nbint=mt->n+1; return; } if (mt->nbint<=mt->n) mt->nbint++; nbreq++; mt->workid[mt->source] = workid; send_request_GEN(PMPI_work, work, mt->source); } void mt_queue_reset(void) { struct mt_mstate *mt = pari_mt; if (DEBUGLEVEL>0 && nbreq) pari_warn(warner,"%ld discarded threads (MPI)",nbreq); for( ;nbreq>0; nbreq--) recvany_void(&mt->source); pari_free(mt->workid); pari_mt = NULL; } void mt_queue_start_lim(struct pari_mt *pt, GEN worker, long lim) { if (lim==0) lim = pari_mt_nbthreads; else lim = minss(pari_mt_nbthreads, lim); if (pari_MPI_rank) mtsequential_queue_start(pt, worker); else if (pari_mt || pari_MPI_size <= 2 || lim <= 1) mtsingle_queue_start(pt, worker); else { MPI_Comm comm; struct mt_mstate *mt = &pari_mt_data; long n = minss(lim, pari_MPI_size-1); long mtparisize = GP_DATA->threadsize? GP_DATA->threadsize: pari_mainstack->rsize; long mtparisizemax = GP_DATA->threadsizemax; pari_mt = mt; mt->workid = (long*) pari_malloc(sizeof(long)*(n+1)); send_request_all(PMPI_worker, pari_MPI_size-1); send_bcast_long(n, MPI_COMM_WORLD); MPI_Comm_split(MPI_COMM_WORLD, 1, 0, &comm); send_bcast_long(mtparisize, comm); send_bcast_long(mtparisizemax, comm); send_bcast_long(get_localbitprec(), comm); send_bcast_vlong(varpriority-1,MAXVARN+2, comm); send_bcast_GEN(primetab, comm); send_bcast_GEN(worker, comm); MPI_Comm_free(&comm); mt->n = n; mt->nbint = 1; mt->source = 1; pt->get=&mtmpi_queue_get; pt->submit=&mtmpi_queue_submit; pt->end=&mt_queue_reset; } } pari-2.17.2/src/mt/pthread.c0000644000175000017500000002211614676526175014213 0ustar billbill/* Copyright (C) 2013 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include "pari.h" #include "paripriv.h" #include "mt.h" #if defined(_WIN32) # include "../systems/mingw/mingw.h" #endif #define DEBUGLEVEL DEBUGLEVEL_mt struct mt_queue { long no; pari_sp avma; struct pari_mainstack *mainstack; GEN input, output; GEN worker; long workid; pthread_cond_t cond; pthread_mutex_t mut; pthread_cond_t *pcond; pthread_mutex_t *pmut; }; struct mt_pstate { pthread_t *th; struct pari_thread *pth; struct mt_queue *mq; long n, nbint, last; long pending; pthread_cond_t pcond; pthread_mutex_t pmut; }; static THREAD long mt_thread_no = -1; static struct mt_pstate *pari_mt; #define LOCK(x) pthread_mutex_lock(x); do #define UNLOCK(x) while(0); pthread_mutex_unlock(x) void mt_sigint_block(void) { if (mt_thread_no>=0) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL); } void mt_sigint_unblock(void) { if (mt_thread_no>=0) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL); } void mt_err_recover(long er) { if (mt_thread_no>=0) { struct mt_pstate *mt = pari_mt; struct mt_queue *mq = mt->mq+mt_thread_no; GEN err = pari_err_last(); err = err_get_num(err)==e_STACK ? err_e_STACK: bin_copy(copy_bin(err)); LOCK(mq->pmut) { mq->output = err; pthread_cond_signal(mq->pcond); } UNLOCK(mq->pmut); pthread_exit((void*)1); } else mtsingle_err_recover(er); } void mt_break_recover(void) { if (mt_thread_no<0) mtsingle_err_recover(0); } void mt_sigint(void) { if (pari_mt) pthread_cond_broadcast(&pari_mt->pcond); } int mt_is_parallel(void) { return !!pari_mt; } int mt_is_thread(void) { return mt_thread_no>=0 ? 1: mtsingle_is_thread(); } long mt_nbthreads(void) { return pari_mt ? 1: pari_mt_nbthreads; } void mt_thread_init(void) { mt_thread_no = 0; } void mt_export_add(const char *str, GEN val) { if (pari_mt) pari_err(e_MISC,"export() not allowed during parallel sections"); export_add(str, val); } void mt_export_del(const char *str) { if (pari_mt) pari_err(e_MISC,"unexport() not allowed during parallel sections"); export_del(str); } void mt_broadcast(GEN code) {(void) code;} void pari_mt_init(void) { pari_mt = NULL; #ifdef _SC_NPROCESSORS_CONF if (!pari_mt_nbthreads) pari_mt_nbthreads = sysconf(_SC_NPROCESSORS_CONF); #elif defined(_WIN32) if (!pari_mt_nbthreads) pari_mt_nbthreads = win32_nbthreads(); #else pari_mt_nbthreads = 1; #endif } void pari_mt_close(void) { } static void mt_queue_cleanup(void *arg) { (void) arg; pari_thread_close(); } static void mt_queue_unlock(void *arg) { pthread_mutex_unlock((pthread_mutex_t*) arg); } static void* mt_queue_run(void *arg) { GEN args = pari_thread_start((struct pari_thread*) arg); pari_sp av = avma; struct mt_queue *mq = (struct mt_queue *) args; mt_thread_no = mq->no; pthread_cleanup_push(mt_queue_cleanup,NULL); LOCK(mq->pmut) { mq->mainstack = pari_mainstack; mq->avma = av; pthread_cond_signal(mq->pcond); } UNLOCK(mq->pmut); for(;;) { GEN work, done; LOCK(&mq->mut) { pthread_cleanup_push(mt_queue_unlock, &mq->mut); while(!mq->input) pthread_cond_wait(&mq->cond, &mq->mut); pthread_cleanup_pop(0); } UNLOCK(&mq->mut); pari_mainstack = mq->mainstack; set_avma(mq->avma); work = mq->input; pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL); done = closure_callgenvec(mq->worker,work); pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL); LOCK(mq->pmut) { mq->mainstack = pari_mainstack; mq->avma = av; mq->input = NULL; mq->output = done; pthread_cond_signal(mq->pcond); } UNLOCK(mq->pmut); } pthread_cleanup_pop(1); #ifdef __GNUC__ return NULL; /* LCOV_EXCL_LINE */ #endif } static long mt_queue_check(struct mt_pstate *mt) { long i; for(i=0; in; i++) { struct mt_queue *mq = mt->mq+i; if (mq->output) return i; } return -1; } static GEN mtpthread_queue_get(struct mt_state *junk, long *workid, long *pending) { struct mt_pstate *mt = pari_mt; struct mt_queue *mq; GEN done = NULL; long last; (void) junk; if (mt->nbintn) { mt->last = mt->nbint; *pending = mt->pending; return NULL; } BLOCK_SIGINT_START LOCK(&mt->pmut) { while ((last = mt_queue_check(mt)) < 0) { pthread_cond_wait(&mt->pcond, &mt->pmut); if (PARI_SIGINT_pending) { int sig = PARI_SIGINT_pending; PARI_SIGINT_pending = 0; pthread_mutex_unlock(&mt->pmut); PARI_SIGINT_block = 0; raise(sig); PARI_SIGINT_block = 1; pthread_mutex_lock(&mt->pmut); } } } UNLOCK(&mt->pmut); BLOCK_SIGINT_END mq = mt->mq+last; done = gcopy(mq->output); mq->output = NULL; if (workid) *workid = mq->workid; if (typ(done) == t_ERROR) { if (err_get_num(done)==e_STACK) pari_err(e_STACKTHREAD); else pari_err(0,done); } mt->last = last; mt->pending--; *pending = mt->pending; return done; } static void mtpthread_queue_submit(struct mt_state *junk, long workid, GEN work) { struct mt_pstate *mt = pari_mt; struct mt_queue *mq = mt->mq+mt->last; (void) junk; if (!work) { mt->nbint=mt->n; return; } BLOCK_SIGINT_START if (mt->nbintn) { mt->nbint++; LOCK(mq->pmut) { while(!mq->avma) pthread_cond_wait(mq->pcond, mq->pmut); } UNLOCK(mq->pmut); } LOCK(&mq->mut) { mq->output = NULL; mq->workid = workid; BLOCK_SIGINT_START { pari_sp av = avma; struct pari_mainstack *st = pari_mainstack; pari_mainstack = mq->mainstack; set_avma(mq->avma); mq->input = gcopy(work); mq->avma = avma; mq->mainstack = pari_mainstack; pari_mainstack = st; set_avma(av); } BLOCK_SIGINT_END pthread_cond_signal(&mq->cond); } UNLOCK(&mq->mut); mt->pending++; BLOCK_SIGINT_END } void mt_queue_reset(void) { struct mt_pstate *mt = pari_mt; long i; BLOCK_SIGINT_START for (i=0; in; i++) pthread_cancel(mt->th[i]); for (i=0; in; i++) pthread_join(mt->th[i],NULL); pari_mt = NULL; BLOCK_SIGINT_END if (DEBUGLEVEL) pari_warn(warner,"stopping %ld threads", mt->n); for (i=0;in;i++) { struct mt_queue *mq = mt->mq+i; pthread_cond_destroy(&mq->cond); pthread_mutex_destroy(&mq->mut); pari_thread_free(&mt->pth[i]); } pari_free(mt->mq); pari_free(mt->pth); pari_free(mt->th); pari_free(mt); } static long closure_has_clone(GEN fun) { if (isclone(fun)) return 1; if (lg(fun) >= 8) { GEN f = closure_get_frame(fun); long i, l = lg(f); for (i = 1; i < l; i++) if (isclone(gel(f,i))) return 1; } return 0; } void mt_queue_start_lim(struct pari_mt *pt, GEN worker, long lim) { if (lim==0) lim = pari_mt_nbthreads; else lim = minss(pari_mt_nbthreads, lim); if (mt_thread_no >= 0) mtsequential_queue_start(pt, worker); else if (pari_mt || lim <= 1) mtsingle_queue_start(pt, worker); else { struct mt_pstate *mt = (struct mt_pstate*) pari_malloc(sizeof(struct mt_pstate)); long mtparisize = GP_DATA->threadsize? GP_DATA->threadsize: pari_mainstack->rsize; long mtparisizemax = GP_DATA->threadsizemax; long i; if (closure_has_clone(worker)) worker = gcopy(worker); /* to avoid clone_lock race */ mt->mq = (struct mt_queue *) pari_malloc(sizeof(*mt->mq)*lim); mt->th = (pthread_t *) pari_malloc(sizeof(*mt->th)*lim); mt->pth = (struct pari_thread *) pari_malloc(sizeof(*mt->pth)*lim); mt->pending = 0; mt->n = lim; mt->nbint = 0; mt->last = 0; pthread_cond_init(&mt->pcond,NULL); pthread_mutex_init(&mt->pmut,NULL); for (i=0;imq+i; mq->no = i; mq->avma = 0; mq->mainstack = NULL; mq->worker = worker; mq->input = NULL; mq->output = NULL; mq->pcond = &mt->pcond; mq->pmut = &mt->pmut; pthread_cond_init(&mq->cond,NULL); pthread_mutex_init(&mq->mut,NULL); if (mtparisizemax) pari_thread_valloc(&mt->pth[i],mtparisize,mtparisizemax,(GEN)mq); else pari_thread_alloc(&mt->pth[i],mtparisize,(GEN)mq); } if (DEBUGLEVEL) pari_warn(warner,"starting %ld threads", lim); BLOCK_SIGINT_START for (i=0;ith[i],NULL, &mt_queue_run, (void*)&mt->pth[i]); pari_mt = mt; BLOCK_SIGINT_END pt->get=&mtpthread_queue_get; pt->submit=&mtpthread_queue_submit; pt->end=&mt_queue_reset; } } pari-2.17.2/src/mt/mt.h0000644000175000017500000000162014567450071013174 0ustar billbill/* Copyright (C) 2013 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ BEGINEXTERN void mtsingle_queue_start(struct pari_mt *pt, GEN worker); void mtsequential_queue_start(struct pari_mt *pt, GEN worker); int mtsingle_is_thread(void); void mtsingle_err_recover(long er); void mt_queue_reset(void); int mt_is_parallel(void); ENDEXTERN pari-2.17.2/src/functions/0000755000175000017500000000000014760315601013766 5ustar billbillpari-2.17.2/src/functions/programming/0000755000175000017500000000000014760315601016310 5ustar billbillpari-2.17.2/src/functions/programming/printsep0000644000175000017500000000070014676526175020114 0ustar billbillFunction: printsep Section: programming/specific C-Name: printsep Prototype: vss* Help: printsep(sep,{str}*): outputs its string arguments (in raw format), separated by 'sep', ending with a newline. Doc: outputs its arguments in raw format, ending with a newline. The arguments are converted to strings following the rules in \secref{se:strings}. Successive entries are separated by \var{sep}: \bprog ? printsep(":", 1,2,3,4) 1:2:3:4 @eprog pari-2.17.2/src/functions/programming/readstr0000644000175000017500000000060014567450071017701 0ustar billbillFunction: readstr Section: programming/specific C-Name: readstr Prototype: D"",s, Help: readstr({filename}): returns the vector of GP strings containing the lines in filename. Doc: Reads in the file \var{filename} and return a vector of GP strings, each component containing one line from the file. If \var{filename} is omitted, re-reads the last file that was fed into \kbd{gp}. pari-2.17.2/src/functions/programming/dbg_x0000644000175000017500000000071414676526175017340 0ustar billbillFunction: dbg_x Section: programming/control C-Name: dbgGEN Prototype: vGD-1,L, Help: dbg_x(A,{n}): print inner structure of A, complete if n is omitted, up to level n otherwise. Intended for debugging. Doc: Print the inner structure of $A$, complete if $n$ is omitted, up to level $n$ otherwise. This function is useful for debugging. It is similar to \b{x} but does not require $A$ to be a history entry. In particular, it can be used in the break loop. pari-2.17.2/src/functions/programming/strchr0000644000175000017500000000132014567450071017542 0ustar billbillFunction: strchr Section: programming/specific C-Name: pari_strchr Prototype: G Help: strchr(x): converts integer or vector of integers x to a string, translating each integer into a character using ASCII encoding. Doc: converts integer or vector of integers $x$ to a string, translating each integer (in the range $[1,255]$) into a character using ASCII encoding. \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 Function: Strchr Section: programming/specific C-Name: pari_strchr Prototype: G Obsolete: 2018-10-01 Help: Strchr(x): deprecated alias for strchr. Doc: deprecated alias for strchr. pari-2.17.2/src/functions/programming/listinsert0000644000175000017500000000173514676526175020461 0ustar billbillFunction: listinsert Section: programming/specific C-Name: listinsert0 Prototype: mWGL Help: listinsert(~L,x,n): insert x at index n in list L, shifting the remaining elements to the right. Description: (list, gen, small):gen listinsert($1, $2, $3) Doc: inserts the object $x$ at position $n$ in $L$ (which must be of type \typ{LIST}). This has complexity $O(\#L - n + 1)$: all the remaining elements of \var{list} (from position $n+1$ onwards) are shifted to the right. If $n$ is greater than the list length, appends $x$. \bprog ? L = List([1,2,3]); ? listput(~L, 4); L \\ listput inserts at end %4 = List([1, 2, 3, 4]) ? listinsert(~L, 5, 1); L \\insert at position 1 %5 = List([5, 1, 2, 3, 4]) ? listinsert(~L, 6, 1000); L \\ trying to insert beyond position #L %6 = List([5, 1, 2, 3, 4, 6]) \\ ... inserts at the end @eprog\noindent Note the \kbd{\til L}: this means that the function is called with a \emph{reference} to \kbd{L} and changes \kbd{L} in place. pari-2.17.2/src/functions/programming/HEADER0000644000175000017500000000446014567450071017175 0ustar billbillFunction: _header_programming/control Class: header Section: programming/control Doc: \section{Programming in GP: control statements} \sidx{programming}\label{se:programming} A number of control statements are available in GP. They are simpler and have a syntax slightly different from their C counterparts, but are quite powerful enough to write any kind of program. Some of them are specific to GP, since they are made for number theorists. As usual, $X$ will denote any simple variable name, and \var{seq} will always denote a sequence of expressions, including the empty sequence. \misctitle{Caveat} In constructs like \bprog for (X = a,b, seq) @eprog\noindent the variable \kbd{X} is lexically scoped to the loop, leading to possibly unexpected behavior: \bprog n = 5; for (n = 1, 10, if (something_nice(), break); ); \\ @com at this point \kbd{n} is 5 ! @eprog\noindent If the sequence \kbd{seq} modifies the loop index, then the loop is modified accordingly: \bprog ? for (n = 1, 10, n += 2; print(n)) 3 6 9 12 @eprog Function: _header_programming/specific Class: header Section: programming/specific Doc: \section{Programming in GP: other specific functions} \label{se:gp_program} In addition to the general PARI functions, it is necessary to have some functions which will be of use specifically for \kbd{gp}, though a few of these can be accessed under library mode. Before we start describing these, we recall the difference between \emph{strings} and \emph{keywords} (see \secref{se:strings}): the latter don't get expanded at all, and you can type them without any enclosing quotes. The former are dynamic objects, where everything outside quotes gets immediately expanded. Function: _header_programming/parallel Class: header Section: programming/parallel Doc: \section{Parallel programming} These function are only available if PARI was configured using \kbd{Configure --mt=\dots}. Two multithread interfaces are supported: \item POSIX threads \item Message passing interface (MPI) As a rule, POSIX threads are well-suited for single systems, while MPI is used by most clusters. However the parallel GP interface does not depend on the chosen multithread interface: a properly written GP program will work identically with both. pari-2.17.2/src/functions/programming/mapapply0000644000175000017500000000344714760123736020074 0ustar billbillFunction: mapapply Section: programming/specific C-Name: mapapply Prototype: WGGDG Help: mapapply(~M,x,f,{u}): applies the closure f to the image of x by the map M and returns the evaluation of f. Doc: applies the closure $f$ to the image $y$ of $x$ by the map $M$ and returns the evaluation $f(y)$. The closure $f$ is allowed to modify the components of $y$ in place. If $M$ is not defined at $x$, and the optional argument \kbd{u} (for \var{undefined}) is present and is a closure of arity $0$, return the evaluation $u()$. To apply $f$ to \emph{all} entries (values) of $M$, use \kbd{apply}$(f, M)$ instead. There are two main use-cases: \item performing a computation on a value directly, without using \kbd{mapget}, avoiding a copy: \bprog ? M = Map(); mapput(~M, "a", mathilbert(2000)); ? matsize(mapget(M, "a")) \\ Slow because mapget(M, "a") copies the value %2 = [2000, 2000] time = 101 ms. ? mapapply(~M, "a", matsize) \\ Fast time = 0 ms. %3 = [2000, 2000] @eprog \item modifying a value in place, for example to append an element to a value in a map of lists. This requires to use \kbd{\til} in the function declaration. In the following \kbd{maplistput}, $M$ is a map of lists and we append $v$ to the list \kbd{mapget(M,k)}, except this is done in place ! When the map is undefined at $k$, we use the $u$(ndefined) argument \kbd{()->List(v)} to convert $v$ to a list then insert it in the map: \bprog ? maplistput(~M, k, v) = mapapply(~M, k, (~y)->listput(~y,v), ()->List(v)); ? M = Map(); %2 = Map([;]) ? maplistput(~M, "a", 1); M %3 = Map(["a", List([1])]) ? maplistput(~M, "a", 2); M %4 = Map(["a", List([1, 2])]) ? maplistput(~M, "b", 3); M %5 = Map(["a", List([1, 2]); "b", List([3])]) ? maplistput(~M, "a", 4); M %6 = Map(["a", List([1, 2, 4]); "b", List([])]) @eprog pari-2.17.2/src/functions/programming/parsum0000644000175000017500000000227714760123736017560 0ustar billbillFunction: parsum Section: programming/parallel C-Name: parsum Prototype: V=GGJ Description: (gen,gen,closure):gen parsum($1, $2, $3) Help: parsum(i=a,b,expr): the sum (i goes from a to b) of expression expr, evaluated in parallel (in random order). Doc: sum of expression \var{expr}, the formal parameter going from $a$ to $b$, evaluated in parallel in random order. The expression \kbd{expr} must not access global variables or variables declared with \kbd{local()}, and must be free of side effects. \bprog ? parsum(i=1,1000,ispseudoprime(2^prime(i)-1)) cpu time = 1min, 26,776 ms, real time = 5,854 ms. %1 = 20 @eprog returns the number of prime numbers among the first $1000$ Mersenne numbers. \misctitle{Note} This function is only useful when summing entries that are too large to fit in memory simultaneously. To sum a small number of values, using \kbd{vecsum(parvector())} is likely to be more efficient; the sumation order also becomes deterministic. %\syn{NO} Function: _parsum_slice_worker Section: programming/internals C-Name: parsum_slice_worker Prototype: GGGG Help: _parsum_slice_worker(a,b,m,C): return sum(k=0,(b-a)\m,C(a+k*m)). a and m must be integers and m must be positive. pari-2.17.2/src/functions/programming/export0000644000175000017500000000130114567450071017555 0ustar billbillFunction: export Section: programming/specific Help: export(x{=...},...,z{=...}): export the variables x,...,z to the parallel world. Doc: Export the variables $x,\ldots, z$ to the parallel world. Such variables are visible inside parallel sections in place of global variables, but cannot be modified inside a parallel section. \kbd{export(a)} set the variable $a$ in the parallel world to current value of $a$. \kbd{export(a=z)} set the variable $a$ in the parallel world to $z$, without affecting the current value of $a$. \bprog ? fun(x)=x^2+1; ? parvector(10,i,fun(i)) *** mt: please use export(fun). ? export(fun) ? parvector(10,i,fun(i)) %4 = [2,5,10,17,26,37,50,65,82,101] @eprog pari-2.17.2/src/functions/programming/quit0000644000175000017500000000067614567450071017234 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 nonzero 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.17.2/src/functions/programming/parforvec0000644000175000017500000000253114760123736020231 0ustar billbillFunction: _parforvec_init Class: gp2c_internal Help: Initializes parameters for parforvec. Description: (parforvec,vec,closure,?small):void parforvec_init(&$1, $2, $3, $4) Function: _parforvec_next Class: gp2c_internal Help: Next value for parforvec. Description: (parforvec):gen parforvec_next(&$1) Function: _parforvec_stop Class: gp2c_internal Help: Stop function for parforvec. Description: (parforvec):void parforvec_stop(&$1) Function: parforvec Section: programming/parallel C-Name: parforvec0 Prototype: vV=GJDVDID0,L, Iterator: (vec,vec,closure,?notype,?small) (parforvec, _parforvec_init, _parforvec_next, _parforvec_stop) Help: parforvec(X=v,expr1,{j},{expr2},{flag}): evaluates the sequence expr2 (dependent on X and j) for X as generated by forvec, in random order, computed in parallel. Substitute for j the value of expr1 (dependent on X). Doc: evaluates the sequence \kbd{expr2} (dependent on $X$ and $j$) for $X$ as generated by \kbd{forvec}, in random order, computed in parallel. Substitute for $j$ the value of \kbd{expr1} (dependent on $X$). It is allowed fo \kbd{expr2} to exit the loop using \kbd{break}/\kbd{next}/\kbd{return}, however in that case, \kbd{expr2} will still be evaluated for all remaining value of $p$ less than the current one, unless a subsequent \kbd{break}/\kbd{next}/\kbd{return} happens. %\syn{NO} pari-2.17.2/src/functions/programming/parforstep0000644000175000017500000000342714676526175020446 0ustar billbillFunction: _parforstep_init Class: gp2c_internal Help: Initializes parameters for parforstep. Description: (parforstep, gen, ?gen, gen, gen):void parforstep_init(&$1, $2, $3, $4, $5) Function: _parforstep_next Class: gp2c_internal Help: Next value for parforstep Description: (parforstep):gen parforstep_next(&$1) Function: _parforstep_stop Class: gp2c_internal Help: Stop function for parforstep. Description: (parforstep):void parforstep_stop(&$1) Function: parforstep Section: programming/parallel C-Name: parforstep0 Prototype: vV=GDGGJDVDI Iterator: (gen,?gen,gen,?gen,closure,?notype) (parforstep, _parforstep_init, _parforstep_next, _parforstep_stop) Help: parforstep(i=a,{b},s,expr1,{r},{expr2}): evaluates the expression expr1 in parallel for i going from a to b in steps of s (can be a positive real number, an intmod for an arithmetic progression, or finally a vector of steps). If the formal variables r and expr2 are present, evaluates sequentially expr2, in which r has been replaced by the different results obtained for expr1 and i with the corresponding arguments. Doc: evaluates in parallel the expression \kbd{expr1} in the formal argument $i$ running from $a$ to $b$ in steps of $s$ (can be a positive real number, an intmod for an arithmetic progression, or finally a vector of steps, see \kbd{forstep}). If $r$ and \kbd{expr2} are present, the expression \kbd{expr2} in the formal variables $r$ and $i$ is evaluated with $r$ running through all the different results obtained for \kbd{expr1} and $i$ takes the corresponding argument. \bprog ? parforstep(i=3,8,2,2*i,x,print([i,x])) [3, 6] [5, 10] [7, 14] ? parforstep(i=3,8,Mod(1,3),2*i,x,print([i,x])) [4, 8] [7, 14] ? parforstep(i=3,10,[1,3],2*i,x,print([i,x])) [3, 6] [4, 8] [7, 14] [8, 16] @eprog pari-2.17.2/src/functions/programming/forcomposite0000644000175000017500000000272414567450071020757 0ustar billbillFunction: _forcomposite_init Class: gp2c_internal Help: Initialize forcomposite_t. Description: (forcomposite,int):void forcomposite_init(&$1, $2, NULL) (forcomposite,int,?int):void forcomposite_init(&$1, $2, $3) Function: _forcomposite_next Class: gp2c_internal Help: Compute the next composite. Description: (forcomposite):int forcomposite_next(&$1) Function: forcomposite Section: programming/control C-Name: forcomposite Prototype: vV=GDGI Help: forcomposite(n=a,{b},seq): the sequence is evaluated, n running over the composite numbers between a and b. Omitting b runs through composites >= a. Iterator: (gen,gen,?gen) (forcomposite, _forcomposite_init, _forcomposite_next) Doc: evaluates \var{seq}, where the formal variable $n$ ranges over the composite numbers between the nonnegative real numbers $a$ to $b$, including $a$ and $b$ if they are composite. Nothing is done if $a>b$. \bprog ? forcomposite(n = 0, 10, print(n)) 4 6 8 9 10 @eprog\noindent Omitting $b$ means we will run through all composites $\geq a$, starting an infinite loop; it is expected that the user will break out of the loop himself at some point, using \kbd{break} or \kbd{return}. Note that the value of $n$ cannot be modified within \var{seq}: \bprog ? forcomposite(n = 2, 10, n = []) *** at top-level: forcomposite(n=2,10,n=[]) *** ^--- *** index read-only: was changed to []. @eprog pari-2.17.2/src/functions/programming/until0000644000175000017500000000064513637407207017401 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.17.2/src/functions/programming/type0000644000175000017500000000114013637407207017216 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.17.2/src/functions/programming/mapdelete0000644000175000017500000000045014567450071020200 0ustar billbillFunction: mapdelete Section: programming/specific C-Name: mapdelete Prototype: vWG Help: mapdelete(~M,x): removes x from the domain of the map M. Doc: removes $x$ from the domain of the map $M$. \bprog ? M = Map(["a",1; "b",3; "c",7]); ? mapdelete(M,"b"); ? Mat(M) ["a" 1] ["c" 7] @eprog pari-2.17.2/src/functions/programming/listpop0000644000175000017500000000150314567450071017732 0ustar billbillFunction: listpop Section: programming/specific C-Name: listpop0 Prototype: vWD0,L, Help: listpop(~list,{n}): removes n-th element from list. If n is omitted or greater than the current list length, removes last element. Description: (list, small):void listpop($1, $2) Doc: removes the $n$-th element of the list \var{list} (which must be of type \typ{LIST}). If $n$ is omitted, or greater than the list current length, removes the last element. If the list is already empty, do nothing. This runs in time $O(\#L - n + 1)$. \bprog ? L = List([1,2,3,4]); ? listpop(~L); L \\ remove last entry %2 = List([1, 2, 3]) ? listpop(~L, 1); L \\ remove first entry %3 = List([2, 3]) @eprog\noindent Note the \kbd{\til L}: this means that the function is called with a \emph{reference} to \kbd{L} and changes \kbd{L} in place. pari-2.17.2/src/functions/programming/while0000644000175000017500000000061214567450071017350 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 nonzero, 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.17.2/src/functions/programming/select0000644000175000017500000000535114676526175017536 0ustar billbillFunction: select Section: programming/specific C-Name: select0 Prototype: GGD0,L, Help: select(f,A,{flag=0}): selects elements of A according to the selection function f. If flag is 1, return the indices of those elements (indirect selection). Wrapper: (bG) Description: (gen,gen):gen genselect(${1 cookie}, ${1 wrapper}, $2) (gen,gen,0):gen genselect(${1 cookie}, ${1 wrapper}, $2) (gen,gen,1):vecsmall genindexselect(${1 cookie}, ${1 wrapper}, $2) Doc: We first describe the default behavior, when $\fl$ is 0 or omitted. Given a vector or list \kbd{A} and a \typ{CLOSURE} \kbd{f}, \kbd{select} returns the elements $x$ of \kbd{A} such that $f(x)$ is nonzero. In other words, \kbd{f} is seen as a selection function returning a boolean value. \bprog ? select(x->isprime(x), vector(50,i,i^2+1)) %1 = [2, 5, 17, 37, 101, 197, 257, 401, 577, 677, 1297, 1601] ? select(x->(x<100), %) %2 = [2, 5, 17, 37] @eprog\noindent returns the primes of the form $i^{2}+1$ for some $i\leq 50$, then the elements less than 100 in the preceding result. The \kbd{select} function also applies to a matrix \kbd{A}, seen as a vector of columns, i.e. it selects columns instead of entries, and returns the matrix whose columns are the selected ones. \misctitle{Remark} For $v$ a \typ{VEC}, \typ{COL}, \typ{VECSMALL}, \typ{LIST} or \typ{MAT}, the alternative set-notations \bprog [g(x) | x <- v, f(x)] [x | x <- v, f(x)] [g(x) | x <- v] @eprog\noindent are available as shortcuts for \bprog apply(g, select(f, Vec(v))) select(f, Vec(v)) apply(g, Vec(v)) @eprog\noindent respectively: \bprog ? [ x | x <- vector(50,i,i^2+1), isprime(x) ] %1 = [2, 5, 17, 37, 101, 197, 257, 401, 577, 677, 1297, 1601] @eprog \noindent If $\fl = 1$, this function returns instead the \emph{indices} of the selected elements, and not the elements themselves (indirect selection): \bprog ? V = vector(50,i,i^2+1); ? select(x->isprime(x), V, 1) %2 = Vecsmall([1, 2, 4, 6, 10, 14, 16, 20, 24, 26, 36, 40]) ? vecextract(V, %) %3 = [2, 5, 17, 37, 101, 197, 257, 401, 577, 677, 1297, 1601] @eprog\noindent The following function lists the elements in $(\Z/N\Z)^{*}$: \bprog ? invertibles(N) = select(x->gcd(x,N) == 1, [1..N]) @eprog \noindent Finally \bprog ? select(x->x, M) @eprog\noindent selects the nonzero entries in \kbd{M}. If the latter is a \typ{MAT}, we extract the matrix of nonzero columns. Note that \emph{removing} entries instead of selecting them just involves replacing the selection function \kbd{f} with its negation: \bprog ? select(x->!isprime(x), vector(50,i,i^2+1)) @eprog \synt{genselect}{void *E, long (*fun)(void*,GEN), GEN a}. Also available is \fun{GEN}{genindexselect}{void *E, long (*fun)(void*, GEN), GEN a}, corresponding to $\fl = 1$. pari-2.17.2/src/functions/programming/forsquarefree0000644000175000017500000000660514676526175021133 0ustar billbillFunction: forsquarefree Section: programming/control C-Name: forsquarefree Prototype: vV=GGI Help: forsquarefree(N=a,b,seq): the sequence is evaluated, N is of the form [n, factor(n)], n going through squarefree integers from a up to b. Doc: evaluates \var{seq}, where the formal variable $N$ is $[n, \kbd{factor}(n)]$ and $n$ goes through squarefree integers from $a$ to $b$; $a$ and $b$ must be integers. Nothing is done if $a>b$. \bprog ? forsquarefree(N=-3,9,print(N)) [-3, [-1, 1; 3, 1]] [-2, [-1, 1; 2, 1]] [-1, Mat([-1, 1])] [1, matrix(0,2)] [2, Mat([2, 1])] [3, Mat([3, 1])] [5, Mat([5, 1])] [6, [2, 1; 3, 1]] [7, Mat([7, 1])] @eprog This function is only implemented for $|a|, |b| < 2^{64}$ ($2^{32}$ on a 32-bit machine). It uses a sieve and runs in time $O(\sqrt{b} + b-a)$. It should be at least 5 times faster than regular factorization as long as the interval length $b-a$ is much larger than $\sqrt{b}$ and get relatively faster as the bounds increase. The function slows down dramatically if $\kbd{primelimit} < \sqrt{b}$. It is comparable to \kbd{forfactored}, but about $\zeta(2) = \pi^{2}/6$ times faster due to the relative density of squarefree integers. \bprog ? B = 10^9; ? for (N = B, B+10^6, factor(N)) time = 2,463 ms. ? forfactored (N = B, B+10^6, [n,fan] = N) time = 567 ms. ? forsquarefree (N = B, B+10^6, [n,fan] = N) time = 343 ms. ? B = 10^11; ? for (N = B, B+10^6, factor(N)) time = 8,012 ms. ? forfactored (N = B, B+10^6, [n,fan] = N) time = 1,293 ms. ? forsquarefree (N = B, B+10^6, [n,fan] = N) time = 713 ms. ? B = 10^14; ? for (N = B, B+10^6, factor(N)) time = 41,283 ms. ? forsquarefree (N = B, B+10^6, [n,fan] = N) time = 33,399 ms. @eprog\noindent The last timing is with the default \kbd{primelimit} (500000) which is much less than $\sqrt{B+10^{6}}$; it goes down to \kbd{29,253ms} if \kbd{primelimit} gets bigger than that bound. In any case $\sqrt{B+10^{6}}$ is much larger than the interval length $10^{6}$ so \kbd{forsquarefree} gets relatively slower for that reason as well. Note that all PARI multiplicative functions accept the \kbd{[n,fan]} argument natively: \bprog ? s = 0; forsquarefree(N = 1, 10^7, s += moebius(N)*eulerphi(N)); s time = 2,003 ms. %1 = 6393738650 ? s = 0; for(N = 1, 10^7, s += moebius(N)*eulerphi(N)); s time = 18,024 ms. \\ slower, we must factor N. Twice. %2 = 6393738650 @eprog The following loops over the fundamental dicriminants less than $X$: \bprog ? X = 10^8; ? for(d=1,X, if (isfundamental(d),)) time = 53,387 ms. ? forfactored(d=1,X, if (isfundamental(d),)); time = 13,861 ms. ? forsquarefree(d=1,X, D = quaddisc(d); if (D <= X, )); time = 14,341 ms. @eprog\noindent Note that in the last loop, the fundamental discriminants $D$ are not evaluated in order (since \kbd{quaddisc(d)} for squarefree $d$ is either $d$ or $4d$) but the set of numbers we run through is the same. Not worth the complication since it's slower than testing \kbd{isfundamental}. A faster, more complicated approach uses two loops. For simplicity, assume $X$ is divisible by $4$: \bprog ? forsquarefree(d=1,X/4, D = quaddisc(d)); time = 3,642 ms. ? forsquarefree(d=X/4+1,X, if (d[1] % 4 == 1,)); time = 7,772 ms. @eprog\noindent This is the price we pay for a faster evaluation, We can run through negative fundamental discriminants in the same way: \bprog ? forfactored(d=-X,-1, if (isfundamental(d),)); @eprog pari-2.17.2/src/functions/programming/uninline0000644000175000017500000000037014567450071020062 0ustar billbillFunction: uninline Section: programming/specific Obsolete: 2018-11-27 Help: uninline(): forget all inline variables. DEPRECATED, use export. Doc: Exit the scope of all current \kbd{inline} variables. DEPRECATED, use \kbd{export} / \kbd{unexport}. pari-2.17.2/src/functions/programming/mapget0000644000175000017500000000100314567450071017510 0ustar billbillFunction: mapget Section: programming/specific C-Name: mapget Prototype: GG Help: mapget(M,x): returns the image of x by the map M. Doc: Returns the image of $x$ by the map $M$. \bprog ? M=Map(["a",23;"b",43]); ? mapget(M,"a") %2 = 23 ? mapget(M,"b") %3 = 43 @eprog\noindent Raises an exception when the key $x$ is not present in $M$. \bprog ? mapget(M,"c") *** at top-level: mapget(M,"c") *** ^------------- *** mapget: nonexistent component in mapget: index not in map @eprog pari-2.17.2/src/functions/programming/printtex0000644000175000017500000000127214676526175020132 0ustar billbillFunction: printtex Section: programming/specific C-Name: printtex Prototype: vs* Help: printtex({str}*): outputs its string arguments in TeX format. Doc: outputs its arguments in \TeX\ format. This output can then be used in a \TeX\ manuscript, see \kbd{strtex} for details. The arguments are converted to strings following the rules in \secref{se:strings}. 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 pari-2.17.2/src/functions/programming/exportall0000644000175000017500000000074414567450071020260 0ustar billbillFunction: exportall Section: programming/specific C-Name: exportall Prototype: v Help: exportall(): declare all current dynamic variables as exported variables. Doc: declare all current dynamic variables as exported variables. Such variables are visible inside parallel sections in place of global variables. \bprog ? fun(x)=x^2+1; ? parvector(10,i,fun(i)) *** mt: please use export(fun). ? exportall() ? parvector(10,i,fun(i)) %4 = [2,5,10,17,26,37,50,65,82,101] @eprog pari-2.17.2/src/functions/programming/strprintf0000644000175000017500000000151314676526175020306 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}. \bprog ? dir = "/home/pari"; file = "aprcl"; n = 10; ? strprintf("%s/%s%ld.tex", dir, file, n) %2 = "/home/pari/aprcl10.tex" @eprog Variant: The variadic version \fun{char *}{pari_sprintf}{const char *fmt, ...} is usually preferable. Function: Strprintf Section: programming/specific C-Name: strprintf Prototype: ss* Obsolete: 2018-10-01 Help: Strprintf(fmt,{x}*): deprecated alias for strprintf. Doc: deprecated alias for strprintf. pari-2.17.2/src/functions/programming/forsubset0000644000175000017500000000355414676526175020276 0ustar billbillFunction: _forsubset_init Class: gp2c_internal Help: Initialize forsubset_t Description: (forsubset,small):void forallsubset_init(&$1, $2) (forsubset,gen):void forsubset_init(&$1, $2) Function: _forsubset_next Class: gp2c_internal Help: Compute the next subset Description: (forsubset):vecsmall forsubset_next(&$1) Function: forsubset Section: programming/control C-Name: forsubset0 Prototype: vGVI Iterator: (gen,gen) (forsubset, _forsubset_init, _forsubset_next) Wrapper: (,vG,,) Help: forsubset(nk,s,seq): if nk is an integer n, the sequence is evaluated, s going through all subsets of {1, 2, ..., n}; if nk is a pair [n,k] of integers s goes through k-subsets of {1, 2, ..., n}. The order is lexicographic among subsets of the same size and smaller subsets come first. Doc: if \var{nk} is a nonnegative integer $n$, evaluates \kbd{seq}, where the formal variable $s$ goes through all subsets of $\{1, 2, \ldots, n\}$; if \var{nk} is a pair $[n,k]$ of integers, $s$ goes through subsets of size $k$ of $\{1, 2, \ldots, n\}$. In both cases $s$ goes through subsets in lexicographic order among subsets of the same size and smaller subsets come first. \bprog ? forsubset([5,3], s, print(s)) Vecsmall([1, 2, 3]) Vecsmall([1, 2, 4]) Vecsmall([1, 2, 5]) Vecsmall([1, 3, 4]) Vecsmall([1, 3, 5]) Vecsmall([1, 4, 5]) Vecsmall([2, 3, 4]) Vecsmall([2, 3, 5]) Vecsmall([2, 4, 5]) Vecsmall([3, 4, 5]) @eprog \bprog ? forsubset(3, s, print(s)) Vecsmall([]) Vecsmall([1]) Vecsmall([2]) Vecsmall([3]) Vecsmall([1, 2]) Vecsmall([1, 3]) Vecsmall([2, 3]) Vecsmall([1, 2, 3]) @eprog\noindent The running time is proportional to the number of subsets enumerated, respectively $2^{n}$ and \kbd{binomial}$(n,k)$: \bprog ? c = 0; forsubset([40,35],s,c++); c time = 128 ms. %4 = 658008 ? binomial(40,35) %5 = 658008 @eprog pari-2.17.2/src/functions/programming/for0000644000175000017500000000077114676526175017046 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. If b is set to +oo, the loop will not stop. Doc: evaluates \var{seq}, where the formal variable $X$ goes from $a$ to $b$, where $a$ and $b$ must be in $\R$. Nothing is done if $a>b$. If $b$ is set to \kbd{+oo}, the loop will not stop; it is expected that the caller will break out of the loop itself at some point, using \kbd{break} or \kbd{return}. pari-2.17.2/src/functions/programming/forstep0000644000175000017500000000236014676526175017736 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 positive real number, an intmod for an arithmetic progression, or finally a vector of steps). If b is set to +oo the loop will not stop. 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 1, print(name))) 389a1 433a1 446d1 ? c = 0; forell(E, 1, 500, c++); c \\ number of curves %2 = 2214 ? c = 0; forell(E, 1, 500, c++, 1); c \\ number of isogeny classes %3 = 971 @eprog\noindent The \tet{elldata} database must be installed and contain data for the specified conductors. \synt{forell}{void *data, long (*f)(void*,GEN), long a, long b, long flag}. pari-2.17.2/src/functions/programming/printf0000644000175000017500000001741214676526175017562 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 nonzero) 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 complex numbers, 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] ? printf("%.3g", Pi+I) 3.14+1.00I @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}}. Variant: The variadic version \fun{void}{pari_printf}{const char *fmt, ...} is usually preferable. pari-2.17.2/src/functions/programming/return0000644000175000017500000000043713637407207017564 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.17.2/src/functions/programming/unexportall0000644000175000017500000000035014567450071020614 0ustar billbillFunction: unexportall Section: programming/specific C-Name: unexportall Prototype: v Help: unexportall(): empty the list of variables exported to the parallel world. Doc: empty the list of variables exported to the parallel world. pari-2.17.2/src/functions/programming/parvector0000644000175000017500000000135014760123736020245 0ustar billbillFunction: parvector Section: programming/parallel C-Name: parvector Prototype: LVJ Description: (small,,closure):vec parvector($1, $3) Help: parvector(N,i,expr): as vector(N,i,expr) but the evaluations of expr are done in parallel. Doc: As \kbd{vector(N,i,expr)} but the evaluations of \kbd{expr} are done in parallel. The expression \kbd{expr} must not access global variables or variables declared with \kbd{local()}, and must be free of side effects. \bprog parvector(10,i,quadclassunit(2^(100+i)+1).no) @eprog\noindent computes the class numbers in parallel. %\syn{NO} Function: _parvector_worker Section: programming/internals C-Name: parvector_worker Prototype: GG Help: _parvector_worker(i,C): evaluate the closure C on i. pari-2.17.2/src/functions/programming/externstr0000644000175000017500000000070014567450071020274 0ustar billbillFunction: externstr 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.17.2/src/functions/programming/write0000644000175000017500000000113714676526175017407 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}). \misctitle{Variant} The high-level function \kbd{write} is expensive when many consecutive writes are expected because it cannot use buffering. The low-level interface \kbd{fileopen} / \kbd{filewrite} / \kbd{fileclose} is more efficient. It also allows to truncate existing files and replace their contents. pari-2.17.2/src/functions/programming/apply0000644000175000017500000000341614676526175017404 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}. \item If \kbd{A} is a scalar, return \kbd{f(A)}. \item If \kbd{A} is a polynomial or power series $\sum a_{i} x^{i}$ ($+ O(x^{N})$), apply \kbd{f} on all coefficients and return $\sum f(a_{i}) x^{i}$ ($+ O(x^{N})$). \item If \kbd{A} is a vector or list $[a_{1},\dots,a_{n}]$, return the vector or list $[f(a_{1}),\dots, f(a_{n})]$. 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 ? apply(sign, 2 - 3* x + 4*x^2 + O(x^3)) %4 = 1 - x + x^2 + O(x^3) @eprog\noindent Note that many functions already act componentwise on vectors or matrices, but they almost never act on lists; in this case, \kbd{apply} is a good solution: \bprog ? L = List([Mod(1,3), Mod(2,4)]); ? lift(L) *** at top-level: lift(L) *** ^------- *** lift: incorrect type in lift. ? apply(lift, L); %2 = List([1, 2]) @eprog \misctitle{Remark} For $v$ a \typ{VEC}, \typ{COL}, \typ{VECSMALL}, \typ{LIST} or \typ{MAT}, the alternative set-notations \bprog [g(x) | x <- v, f(x)] [x | x <- v, f(x)] [g(x) | x <- v] @eprog\noindent are available as shortcuts for \bprog apply(g, select(f, Vec(v))) select(f, Vec(v)) apply(g, Vec(v)) @eprog\noindent respectively: \bprog ? L = List([Mod(1,3), Mod(2,4)]); ? [ lift(x) | x<-L ] %2 = [1, 2] @eprog \synt{genapply}{void *E, GEN (*fun)(void*,GEN), GEN a}. pari-2.17.2/src/functions/programming/parplothexport0000644000175000017500000000301614676526175021346 0ustar billbillFunction: parplothexport Section: graphic C-Name: parplothexport Prototype: GV=GGJD0,M,D0,L,p\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 Description: (gen,gen,gen,closure,?small,?small):gen:prec parplothexport($1, $2, $3, $4, $5, $6, $prec) Help: parplothexport(fmt,X=a,b,expr,{flags=0},{n=0}): parallel version of plothexport. Plot of expression expr, X goes from a to b in high resolution, returning the resulting picture as a character string which can then be written to a file. Doc: parallel version of \kbd{plothexport}. Plot of expression \var{expr}, $X$ goes from $a$ to $b$ in high resolution, returning the resulting picture as a character string which can then be written to a file. The format \kbd{fmt} is either \kbd{"ps"} (PostScript output) or \kbd{"svg"} (Scalable Vector Graphics). All other parameters and flags are as in \kbd{ploth}. \bprog ? s = parplothexport("svg", x=1,10, x^2+3); ? write("graph.svg", s); @eprog\noindent The above only works if \kbd{graph.svg} does not already exist, otherwise \kbd{write} will append to the existing file and produce an invalid \kbd{svg}. Here is a version that truncates an existing file (beware!): \bprog ? n = fileopen("graph.svg", "w"); ? filewrite(n, s); ? fileclose(n); @eprog\noindent This is intentionally more complicated. \synt{parplothexport}{GEN fmt, GEN a, GEN b, GEN code, long flags, long n, long prec}, pari-2.17.2/src/functions/programming/getstack0000644000175000017500000000043513637407207020050 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.17.2/src/functions/programming/dbg_err0000644000175000017500000000127114557721031017642 0ustar billbillFunction: dbg_err Class: gp Section: programming/control C-Name: dbg_err Prototype: Help: dbg_err(): (break loop) return the error data of the current error, if any. Doc: In the break loop, return the error data of the current error, if any. See \tet{iferr} for details about error data. Compare: \bprog ? iferr(1/(Mod(2,12019)^(6!)-1),E,Vec(E)) %1 = ["e_INV", "Fp_inv", Mod(119, 12019)] ? 1/(Mod(2,12019)^(6!)-1) *** at top-level: 1/(Mod(2,12019)^(6!)- *** ^-------------------- *** _/_: impossible inverse in Fp_inv: Mod(119, 12019). *** Break loop: type 'break' to go back to GP prompt break> Vec(dbg_err()) ["e_INV", "Fp_inv", Mod(119, 12019)] @eprog pari-2.17.2/src/functions/programming/strtime0000644000175000017500000000077314567450071017737 0ustar billbillFunction: strtime Section: programming/specific C-Name: strtime Prototype: L Help: strtime(t): return a string describing the time t in milliseconds, in the format used by the GP timer. Doc: return a string describing the time t in milliseconds in the format used by the GP timer. \bprog ? print(strtime(12345678)) 3h, 25min, 45,678 ms ? { my(t=getabstime()); F=factor(2^256+1);t=getabstime()-t; print("factor(2^256+1) took ",strtime(t)); } factor(2^256+1) took 1,320 ms @eprog pari-2.17.2/src/functions/programming/addhelp0000644000175000017500000000212614567450071017643 0ustar billbillFunction: addhelp Section: programming/specific C-Name: addhelp Prototype: vrs Help: addhelp(sym,str): add/change help message for the symbol sym. Doc: changes the help message for the symbol \kbd{sym}. The string \var{str} is expanded on the spot and stored as the online help for \kbd{sym}. It is recommended to document global variables and user functions in this way, although \kbd{gp} will not protest if you don't. You can attach a help text to an alias, but it will never be shown: aliases are expanded by the \kbd{?} help operator and we get the help of the symbol the alias points to. Nothing prevents you from modifying the help of built-in PARI functions. But if you do, we would like to hear why you needed it! Without \tet{addhelp}, the standard help for user functions consists of its name and definition. \bprog gp> f(x) = x^2; gp> ?f f = (x)->x^2 @eprog\noindent Once addhelp is applied to $f$, the function code is no longer included. It can still be consulted by typing the function name: \bprog gp> addhelp(f, "Square") gp> ?f Square gp> f %2 = (x)->x^2 @eprog pari-2.17.2/src/functions/programming/localprec0000644000175000017500000000431014760123736020203 0ustar billbillFunction: localprec Section: programming/specific C-Name: localprec Prototype: vG Help: localprec(p): set the real precision to p in the dynamic scope and return p. Doc: set the real precision to $p$ in the dynamic scope and return $p$. All computations are performed as if \tet{realprecision} was $p$: transcendental constants (e.g.~\kbd{Pi}) and conversions from exact to floating point inexact data use $p$ decimal digits, as well as iterative routines implicitly using a floating point accuracy as a termination criterion (e.g.~\tet{solve} or \tet{intnum}). But \kbd{realprecision} itself is unaffected and is ``unmasked'' when we exit the dynamic (\emph{not} lexical) scope. In effect, this is similar to \bprog my(prec = default(realprecision)); default(realprecision,p); ... default(realprecision, prec); @eprog\noindent but is both less cumbersome, cleaner (no need to manipulate a global variable, which in fact never changes and is only temporarily masked) and more robust: if the above computation is interrupted or an exception occurs, \kbd{realprecision} will not be restored as intended. Such \kbd{localprec} statements can be nested, the innermost one taking precedence as expected. Beware that \kbd{localprec} follows the semantic of \tet{local}, not \tet{my}: a subroutine called from \kbd{localprec} scope uses the local accuracy: \bprog ? f()=precision(1.); ? f() %2 = 38 ? localprec(19); f() %3 = 19 @eprog\noindent \misctitle{Warning} Changing \kbd{realprecision} itself in programs is now deprecated in favor of \kbd{localprec}. Think about the \kbd{realprecision} default as an interactive command for the \kbd{gp} interpreter, best left out of GP programs. Indeed, the above rules imply that mixing both constructs yields surprising results: \bprog ? \p38 ? localprec(19); default(realprecision,100); Pi %1 = 3.141592653589793239 ? \p realprecision = 115 significant digits (100 digits displayed) @eprog\noindent Indeed, \kbd{realprecision} itself is ignored within \kbd{localprec} scope, so \kbd{Pi} is computed to a low accuracy. And when we leave \kbd{localprec} scope, \kbd{realprecision} only regains precedence, it is not ``restored'' to the original value. %\syn{NO} pari-2.17.2/src/functions/programming/forprime0000644000175000017500000000461314567450071020070 0ustar billbillFunction: _diffptr Class: gp2c_internal Help: Table of difference of primes. Description: ():bptr diffptr Function: _forprime_next Class: gp2c_internal Help: Compute the next prime from the diffptr table. Description: (*small,*bptr):void NEXT_PRIME_VIADIFF($1, $2) Function: _forprime_init Class: gp2c_internal Help: Initialize forprime_t. Description: (forprime,int,?int):void forprime_init(&$1, $2, $3); Function: _forprime_next_ Class: gp2c_internal Help: Compute the next prime. Description: (forprime):int forprime_next(&$1) Function: _u_forprime_init Class: gp2c_internal Help: Initialize forprime_t (ulong version). Description: (forprime,small,):void u_forprime_init(&$1, $2, LONG_MAX); (forprime,small,small):void u_forprime_init(&$1, $2, $3); Function: _u_forprime_next Class: gp2c_internal Help: Compute the next prime (ulong version). Description: (forprime):small u_forprime_next(&$1) Function: forprime Section: programming/control C-Name: forprime Prototype: vV=GDGI Help: forprime(p=a,{b},seq): the sequence is evaluated, p running over the primes between a and b. Omitting b runs through primes >= a. Iterator: (*notype,small,small) (forprime, _u_forprime_init, _u_forprime_next) (*notype,gen,gen,gen) (forprime, _forprime_init, _forprime_next_) (*small,gen,?gen) (forprime, _u_forprime_init, _u_forprime_next) (*int,gen,?gen) (forprime, _forprime_init, _forprime_next_) (gen,gen,?gen) (forprime, _forprime_init, _forprime_next_) Doc: evaluates \var{seq}, where the formal variable $p$ ranges over the prime numbers between the real numbers $a$ to $b$, including $a$ and $b$ if they are prime. More precisely, the value of $p$ is incremented to \kbd{nextprime($p$ + 1)}, the smallest prime strictly larger than $p$, at the end of each iteration. Nothing is done if $a>b$. \bprog ? forprime(p = 4, 10, print(p)) 5 7 @eprog\noindent Setting $b$ to \kbd{+oo} means we will run through all primes $\geq a$, starting an infinite loop; it is expected that the caller will break out of the loop itself at some point, using \kbd{break} or \kbd{return}. Note that the value of $p$ cannot be modified within \var{seq}: \bprog ? forprime(p = 2, 10, p = []) *** at top-level: forprime(p=2,10,p=[]) *** ^--- *** prime index read-only: was changed to []. @eprog pari-2.17.2/src/functions/programming/filewrite0000644000175000017500000000361214676526175020247 0ustar billbillFunction: filewrite Section: programming/specific C-Name: gp_filewrite Prototype: vLs Help: filewrite(n,s): write the string s to file attached to descriptor n, ending with a newline. The file must have been opened with fileopen in "w" or "a" mode. Doc: write the string $s$ to the file attached to descriptor $n$, ending with a newline. The file must have been opened with \kbd{fileopen} in \kbd{"w"} or \kbd{"a"} mode. There is no guarantee that $s$ is completely written to disk until \kbd{fileclose$(n)$} is executed, which is automatic when quitting \kbd{gp}. If the newline is not desired, use \kbd{filewrite1}. \misctitle{Variant} The high-level function \kbd{write} is expensive when many consecutive writes are expected because it cannot use buffering. The low-level interface \kbd{fileopen} / \kbd{filewrite} / \kbd{fileclose} is more efficient: \bprog ? f = "/tmp/bigfile"; ? for (i = 1, 10^5, write(f, i^2+1)) time = 240 ms. ? v = vector(10^5, i, i^2+1); time = 10 ms. \\ computing the values is fast ? write("/tmp/bigfile2",v) time = 12 ms. \\ writing them in one operation is fast ? n = fileopen("/tmp/bigfile", "w"); ? for (i = 1, 10^5, filewrite(n, i^2+1)) time = 24 ms. \\ low-level write is ten times faster ? fileclose(n); @eprog\noindent In the final example, the file needs not be in a consistent state until the ending \kbd{fileclose} is evaluated, e.g. some lines might be half-written or not present at all even though the corresponding \kbd{filewrite} was executed already. Both a single high-level \kbd{write} and a succession of low-level \kbd{filewrite}s achieve the same efficiency, but the latter is often more natural. In fact, concatenating naively the entries to be written is quadratic in the number of entries, hence much more expensive than the original write operations: \bprog ? v = []; for (i = 1, 10^5, v = concat(v,i)) time = 1min, 41,456 ms. @eprog pari-2.17.2/src/functions/programming/writebin0000644000175000017500000000366514567450071020076 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 as \kbd{t$n$} for some integer $n$ (the attached variable number). Installed functions and history objects can not be saved via this function. If $x$ is omitted, saves all user variables from the session, together with their names. Reading such a ``named object'' back in a \kbd{gp} session will set the corresponding user variable to the saved value. E.g after \bprog x = 1; writebin("log") @eprog\noindent reading \kbd{log} into a clean session will set \kbd{x} to $1$. The relative variables priorities (see \secref{se:priority}) of new variables set in this way remain the same (preset variables retain their former priority, but are set to the new value). In particular, reading such a session log into a clean session will restore all variables exactly as they were in the original one. Just as a regular input file, a binary file can be compressed using \tet{gzip}, provided the file name has the standard \kbd{.gz} extension.\sidx{binary file} In the present implementation, the binary files are architecture dependent and compatibility with future versions of \kbd{gp} is not guaranteed. Hence binary files should not be used for long term storage (also, they are larger and harder to compress than text files). pari-2.17.2/src/functions/programming/global0000644000175000017500000000027214760123736017502 0ustar billbillFunction: global Section: programming/specific Obsolete: 2007-10-03 Help: global(list of variables): obsolete. Scheduled for deletion. Doc: obsolete. Scheduled for deletion. % \syn{NO} pari-2.17.2/src/functions/programming/setdebug0000644000175000017500000000233514716371074020047 0ustar billbillFunction: setdebug Section: programming/control C-Name: setdebug Prototype: DsD-1,L, Help: setdebug({D},{n}): sets debug level for domain D to n (n must be between 0 and 20). If n is omitted, returns the current level for domain D. if D is omitted, returns a two-column matrix which lists the available domains with their levels. Doc: sets debug level for domain $D$ to $n$ ($0 \leq n \leq 20$). The domain $D$ is a character string describing a Pari feature or code module, such as \kbd{"bnf"}, \kbd{"qflll"} or \kbd{"polgalois"}. This allows to selectively increase or decrease the diagnostics attached to a particular feature. If $n$ is omitted, returns the current level for domain $D$. If $D$ is omitted, returns a two-column matrix which lists the available domains with their levels. The \kbd{debug} default allows to reset all debug levels to a given value. \bprog ? setdebug()[,1] \\ list of all domains ["alg", "arith", "bern", "bnf", "bnr", "bnrclassfield", ..., "zetamult"] ? \g 1 \\ sets all debug levels to 1 debug = 1 ? setdebug("bnf", 0); \\ kills messages related to bnfinit and bnfisrincipal @eprog Variant: Also available is \fun{void}{setalldebug}{long n}: sets all debug domains to level \var{n}. pari-2.17.2/src/functions/programming/install0000644000175000017500000000700714567450071017713 0ustar billbillFunction: install Section: programming/specific C-Name: gpinstall Prototype: vrrD"",r,D"",s, Help: install(name,code,{gpname},{lib}): load from dynamic library 'lib' the function 'name'. Assign to it the name 'gpname' in this GP session, with prototype 'code'. If 'lib' is omitted, all symbols known to gp (includes the whole 'libpari.so' and possibly others) are available. If 'gpname' is omitted, use 'name'. Doc: loads from dynamic library \var{lib} the function \var{name}. Assigns to it the name \var{gpname} in this \kbd{gp} session, with \emph{prototype} \var{code} (see below). If \var{gpname} is omitted, uses \var{name}. If \var{lib} is omitted, all symbols known to \kbd{gp} are available: this includes the whole of \kbd{libpari.so} and possibly others (such as \kbd{libc.so}). Most importantly, \kbd{install} gives you access to all nonstatic functions defined in the PARI library. For instance, the function \bprog GEN addii(GEN x, GEN y) @eprog\noindent adds two PARI integers, and is not directly accessible under \kbd{gp} (it is eventually called by the \kbd{+} operator of course): \bprog ? install("addii", "GG") ? addii(1, 2) %1 = 3 @eprog\noindent It also allows to add external functions to the \kbd{gp} interpreter. For instance, it makes the function \tet{system} obsolete: \bprog ? install(system, vs, sys,/*omitted*/) ? sys("ls gp*") gp.c gp.h gp_rl.c @eprog\noindent This works because \kbd{system} is part of \kbd{libc.so}, which is linked to \kbd{gp}. It is also possible to compile a shared library yourself and provide it to gp in this way: use \kbd{gp2c}, or do it manually (see the \kbd{modules\_build} variable in \kbd{pari.cfg} for hints). Re-installing a function will print a warning and update the prototype code if needed. However, it will not reload a symbol from the library, even if the latter has been recompiled. \misctitle{Prototype} We only give a simplified description here, covering most functions, but there are many more possibilities. The full documentation is available in \kbd{libpari.dvi}, see \bprog ??prototype @eprog \item First character \kbd{i}, \kbd{l}, \kbd{u}, \kbd{v} : return type \kbd{int} / \kbd{long} / \kbd{ulong} / \kbd{void}. (Default: \kbd{GEN}) \item One letter for each mandatory argument, in the same order as they appear in the argument list: \kbd{G} (\kbd{GEN}), \kbd{\&} (\kbd{GEN*}), \kbd{L} (\kbd{long}), \kbd{U} (\kbd{ulong}), \kbd{s} (\kbd{char *}), \kbd{n} (variable). \item \kbd{p} to supply \kbd{realprecision} (usually \kbd{long prec} in the argument list), \kbd{b} to supply \kbd{realbitprecision} (usually \kbd{long bitprec}), \kbd{P} to supply \kbd{seriesprecision} (usually \kbd{long precdl}). \noindent We also have special constructs for optional arguments and default values: \item \kbd{DG} (optional \kbd{GEN}, \kbd{NULL} if omitted), \item \kbd{D\&} (optional \kbd{GEN*}, \kbd{NULL} if omitted), \item \kbd{Dn} (optional variable, $-1$ if omitted), For instance the prototype corresponding to \bprog long issquareall(GEN x, GEN *n = NULL) @eprog\noindent is \kbd{lGD\&}. \misctitle{Caution} This function may not work on all systems, especially when \kbd{gp} has been compiled statically. In that case, the first use of an installed function will provoke a Segmentation Fault (this should never happen with a dynamically linked executable). If you intend to use this function, please check first on some harmless example such as the one above that it works properly on your machine. pari-2.17.2/src/functions/programming/unexport0000644000175000017500000000037614567450071020133 0ustar billbillFunction: unexport Section: programming/specific Help: unexport(x,...,z): remove x,...,z from the list of variables exported to the parallel world. Doc: remove $x,\ldots, z$ from the list of variables exported to the parallel world. See \key{export}. pari-2.17.2/src/functions/programming/getenv0000644000175000017500000000037414557721031017531 0ustar billbillFunction: getenv Section: programming/specific C-Name: gp_getenv Prototype: s Help: getenv(s): value of the environment variable s, 0 if it is not defined. Doc: return the value of the environment variable \kbd{s} if it is defined, otherwise return 0. pari-2.17.2/src/functions/programming/printsep10000644000175000017500000000074014676526175020201 0ustar billbillFunction: printsep1 Section: programming/specific C-Name: printsep1 Prototype: vss* Help: printsep1(sep,{str}*): outputs its string arguments (in raw format), separated by 'sep', without ending with a newline. Doc: outputs its arguments in raw format, without ending with a newline. The arguments are converted to strings following the rules in \secref{se:strings}. Successive entries are separated by \var{sep}: \bprog ? printsep1(":", 1,2,3,4);print("|") 1:2:3:4| @eprog pari-2.17.2/src/functions/programming/getwalltime0000644000175000017500000000054014567450071020556 0ustar billbillFunction: getwalltime Section: programming/specific C-Name: getwalltime Prototype: Help: getwalltime(): time (in milliseconds) since the UNIX Epoch. Doc: returns the time (in milliseconds) elapsed since 00:00:00 UTC Thursday 1, January 1970 (the Unix epoch). \bprog my (t = getwalltime()); ... print("Time: ", strtime(getwalltime() - t)); @eprog pari-2.17.2/src/functions/programming/dbg_up0000644000175000017500000000273514676526175017522 0ustar billbillFunction: dbg_up Class: gp Section: programming/control C-Name: dbg_up Prototype: vD1,L, Help: dbg_up({n=1}): (break loop) go up n frames, which allows to inspect data of the parent function. Doc: (In the break loop) go up $n$ frames, which allows to inspect data of the parent function. To cancel a \tet{dbg_up} call, use \tet{dbg_down}. \bprog ? x = 0; ? g(x) = x-3; ? f(x) = 1 / g(x+1); ? for (x = 1, 5, f(x+1)) *** at top-level: for(x=1,5,f(x+1)) *** ^------- *** in function f: 1/g(x+1) *** ^------- *** _/_: impossible inverse in gdiv: 0. *** Break loop: type 'break' to go back to GP prompt break> x 2 break> dbg_up() *** at top-level: for(x=1,5,f(x+1)) *** ^------- break> x 1 break> dbg_up() *** at top-level: for(x=1,5,f(x+1)) *** ^------- break> x 1 break> dbg_up() *** at top-level: for(x=1,5,f(x+1)) *** ^----------------- break> x 0 break> dbg_down() \\ back up once *** at top-level: for(x=1,5,f(x+1)) *** ^------- break> x 1 @eprog\noindent The above example shows that the notion of GP frame is finer than the usual stack of function calls (as given for instance by the GDB \kbd{backtrace} command): GP frames are attached to variable scopes and there are frames attached to control flow instructions such as a \kbd{for} loop above. pari-2.17.2/src/functions/programming/listput0000644000175000017500000000261414676526175017762 0ustar billbillFunction: listput Section: programming/specific C-Name: listput0 Prototype: mWGD0,L, Help: listput(~list,x,{n}): sets n-th element of list equal to x. If n is omitted or greater than the current list length, appends x. Description: (list, gen, small):gen listput($1, $2, $3) Doc: sets the $n$-th element of the list \var{list} (which must be of type \typ{LIST}) equal to $x$. If $n$ is omitted, or greater than the list length, appends $x$. \bprog ? L = List(); ? listput(~L, 1) ? listput(~L, 2) ? L %4 = List([1, 2]) @eprog\noindent Note the \kbd{\til L}: this means that the function is called with a \emph{reference} to \kbd{L} and changes \kbd{L} in place. 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. \bprog ? listput(~L, 3, 1) \\ insert at position 1 ? L %6 = List([3, 2]) ? L[2] = 4 \\ simpler %7 = List([3, 4]) ? L[10] = 1 \\ can't insert beyond the end of the list *** at top-level: L[10]=1 *** ^------ *** nonexistent component: index > 2 ? listput(L, 1, 10) \\ but listput can ? L %9 = List([3, 2, 1]) @eprog This function runs in time $O(\#L)$ in the worst case (when the list must be reallocated), but in time $O(1)$ on average: any number of successive \kbd{listput}s run in time $O(\#L)$, where $\#L$ denotes the list \emph{final} length. pari-2.17.2/src/functions/programming/pareval0000644000175000017500000000315714567450071017701 0ustar billbillFunction: pareval Section: programming/parallel C-Name: pareval Prototype: G Help: pareval(x): parallel evaluation of the elements of the vector of closures x. Doc: parallel evaluation of the elements of \kbd{x}, where \kbd{x} is a vector of closures. The closures must be of arity $0$, must not access global variables or variables declared with \kbd{local} and must be free of side effects. Here is an artificial example explaining the MOV attack on the elliptic discrete log problem (by reducing it to a standard discrete log over a finite field): \bprog { my(q = 2^30 + 3, m = 40 * q, p = 1 + m^2); \\ p, q are primes my(E = ellinit([0,0,0,1,0] * Mod(1,p))); my([P, Q] = ellgenerators(E)); \\ E(F_p) ~ Z/m P + Z/m Q and the order of the \\ Weil pairing in (Z/p)^* is m my(F = [m,factor(m)], e = random(m), R, wR, wQ); R = ellpow(E, Q, e); wR = ellweilpairing(E,P,R,m); wQ = ellweilpairing(E,P,Q,m); \\ wR = wQ^e pareval([()->znlog(wR,wQ,F), ()->elllog(E,R,Q), ()->e]) } @eprog\noindent Note the use of \kbd{my} to pass "arguments" to the functions we need to evaluate while satisfying the listed requirements: closures of arity $0$ and no global variables (another possibility would be to use \kbd{export}). As a result, the final three statements satisfy all the listed requirements and are run in parallel. (Which is silly for this computation but illustrates the use of pareval.) The function \kbd{parfor} is more powerful but harder to use. Function: _pareval_worker Section: programming/internals C-Name: pareval_worker Prototype: G Help: _pareval_worker(C): evaluate the closure C. pari-2.17.2/src/functions/programming/kill0000644000175000017500000000266514567450071017205 0ustar billbillFunction: kill Section: programming/specific C-Name: kill0 Prototype: vr Help: kill(sym): restores the symbol sym to its ``undefined'' status and kill attached help messages. Doc: restores the symbol \kbd{sym} to its ``undefined'' status, and deletes any help messages attached 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 attached 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 attached 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.17.2/src/functions/programming/whatnow0000644000175000017500000000164414567450071017735 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, 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, outputs the new function name and syntax, if it changed at all. Functions that where introduced since then, then modified are also recognized. \bprog ? whatnow("mu") New syntax: mu(n) ===> moebius(n) moebius(x): Moebius function of x. ? whatnow("sin") This function did not change @eprog When a function was removed and the underlying functionality is not available under a compatible interface, no equivalent is mentioned: \bprog ? whatnow("buchfu") This function no longer exists @eprog\noindent (The closest equivalent would be to set \kbd{K = bnfinit(T)} then access \kbd{K.fu}.) pari-2.17.2/src/functions/programming/listkill0000644000175000017500000000061414760123736020071 0ustar billbillFunction: listkill Section: programming/specific C-Name: listkill Prototype: vW Obsolete: 2007-08-10 Help: listkill(~L): obsolete, retained for backward compatibility. Doc: obsolete, retained for backward compatibility. Just use \kbd{L = List()} instead of \kbd{listkill(L)}. In most cases, you won't even need that, e.g. local variables are automatically cleared when a user function returns. pari-2.17.2/src/functions/programming/alarm0000644000175000017500000000431714567450071017342 0ustar billbillFunction: alarm Section: programming/specific C-Name: gp_alarm Prototype: D0,L,DE Help: alarm({s = 0},{code}): if code is omitted, trigger an "e_ALARM" exception after s seconds (wall-clock time), cancelling any previously set alarm; stop a pending alarm if s = 0 or is omitted. Otherwise, evaluate code, aborting after s seconds. Doc: if \var{code} is omitted, trigger an \var{e\_ALARM} exception after $s$ seconds (wall-clock time), cancelling any previously set alarm; stop a pending alarm if $s = 0$ or is omitted. Otherwise, if $s$ is positive, the function evaluates \var{code}, aborting after $s$ seconds. The return value is the value of \var{code} if it ran to completion before the alarm timeout, and a \typ{ERROR} object otherwise. \bprog ? p = nextprime(10^25); q = nextprime(10^26); N = p*q; ? E = alarm(1, factor(N)); ? type(E) %3 = "t_ERROR" ? print(E) %4 = error("alarm interrupt after 964 ms.") ? alarm(10, factor(N)); \\ enough time %5 = [ 10000000000000000000000013 1] [100000000000000000000000067 1] @eprog\noindent Here is a more involved example: the function \kbd{timefact(N,sec)} below tries to factor $N$ and gives up after \var{sec} seconds, returning a partial factorization. \bprog \\ Time-bounded partial factorization default(factor_add_primes,1); timefact(N,sec)= { F = alarm(sec, factor(N)); if (type(F) == "t_ERROR", factor(N, 2^24), F); } @eprog\noindent We either return the factorization directly, or replace the \typ{ERROR} result by a simple bounded factorization \kbd{factor(N, 2\pow 24)}. Note the \tet{factor_add_primes} trick: any prime larger than $2^{24}$ discovered while attempting the initial factorization is stored and remembered. When the alarm rings, the subsequent bounded factorization finds it right away. \misctitle{Caveat} It is not possible to set a new alarm \emph{within} another \kbd{alarm} code: the new timer erases the parent one. \misctitle{Caveat2} In a parallel-enabled \kbd{gp}, if the \var{code} involves parallel subtasks, then \kbd{alarm} may not return right away: il will prevent new tasks from being launched but will not interrupt previously launched secondary threads. This avoids leaving the system in an inconsistent state. pari-2.17.2/src/functions/programming/next0000644000175000017500000000101113637407207017210 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.17.2/src/functions/programming/forprimestep0000644000175000017500000000340514676526175020774 0ustar billbillFunction: _forprimestep_init Class: gp2c_internal Help: Initialize forprime_t. Description: (forprime,int,?int,int):void forprimestep_init(&$1,$2,$3,$4); Function: forprimestep Section: programming/control C-Name: forprimestep Prototype: vV=GDGGI Help: forprimestep(p=a,b,q,seq): the sequence is evaluated, p running over the primes less than b in the arithmetic progression a + k*q, k >= 0. The parameter q can be a positive integer or an intmod (start at the first prime above a in the progression). Iterator: (*notype,small,small,gen) (forprime, _forprimestep_init, _u_forprime_next) (*notype,gen,gen,gen) (forprime, _forprimestep_init, _forprime_next_) (*small,gen,?gen,gen) (forprime, _forprimestep_init, _u_forprime_next) (*int,gen,?gen,gen) (forprime, _forprimestep_init, _forprime_next_) (gen,gen,?gen,gen) (forprime, _forprimestep_init, _forprime_next_) Doc: evaluates \var{seq}, where the formal variable $p$ ranges over the prime numbers in an arithmetic progression in $[a,b]$: $q$ is either an integer ($p \equiv a \pmod{q}$) or an intmod \kbd{Mod(c,N)} and we restrict to that congruence class. Nothing is done if $a>b$. \bprog ? forprimestep(p = 4, 30, 5, print(p)) 19 29 ? forprimestep(p = 4, 30, Mod(1,5), print(p)) 11 @eprog\noindent Setting $b$ to \kbd{+oo} means we will run through all primes $\geq a$, starting an infinite loop; it is expected that the caller will break out of the loop itself at some point, using \kbd{break} or \kbd{return}. Note that the value of $p$ cannot be modified within \var{seq}: \bprog ? forprimestep(p = 2, 10, 3, p = []) *** at top-level: forprimestep(p=2,10,3,p=[]) *** ^--- *** prime index read-only: was changed to []. @eprog pari-2.17.2/src/functions/programming/forpart0000644000175000017500000000511714676526175017734 0ustar billbillFunction: _forpart_init Class: gp2c_internal Help: Initialize forpart_t Description: (forpart,small,?gen,?gen):void forpart_init(&$1, $2, $3, $4) Function: _forpart_next Class: gp2c_internal Help: Compute the next part Description: (forpart):vecsmall forpart_next(&$1) Function: forpart Section: programming/control C-Name: forpart0 Prototype: vV=GIDGDG Iterator: (gen,small,?gen,?gen) (forpart, _forpart_init, _forpart_next) Wrapper: (,vG,,) Description: (small,closure,?gen,?gen):void forpart(${2 cookie}, ${2 wrapper}, $1, $3, $4) Help: forpart(X=k,seq,{a=k},{n=k}): evaluate seq where the Vecsmall X goes over the partitions of k. Optional parameter n (n=nmax or n=[nmin,nmax]) restricts the length of the partition. Optional parameter a (a=amax or a=[amin,amax]) restricts the range of the parts. Zeros are removed unless one sets amin=0 to get X of fixed length nmax (=k by default). Doc: evaluate \var{seq} over the partitions $X=[x_{1},\dots x_{n}]$ of the integer $k$, i.e.~increasing sequences $x_{1}\leq x_{2}\dots \leq x_{n}$ of sum $x_{1}+\dots + x_{n}=k$. By convention, $0$ admits only the empty partition and negative numbers have no partitions. A partition is given by a \typ{VECSMALL}, where parts are sorted in nondecreasing order. The partitions are listed by increasing size and in lexicographic order when sizes are equal: \bprog ? forpart(X=4, print(X)) Vecsmall([4]) Vecsmall([1, 3]) Vecsmall([2, 2]) Vecsmall([1, 1, 2]) Vecsmall([1, 1, 1, 1]) @eprog\noindent Optional parameters $n$ and $a$ are as follows: \item $n=\var{nmax}$ (resp. $n=[\var{nmin},\var{nmax}]$) restricts partitions to length less than $\var{nmax}$ (resp. length between $\var{nmin}$ and $nmax$), where the \emph{length} is the number of nonzero entries. \item $a=\var{amax}$ (resp. $a=[\var{amin},\var{amax}]$) restricts the parts to integers less than $\var{amax}$ (resp. between $\var{amin}$ and $\var{amax}$). By default, parts are positive and we remove zero entries unless $amin\leq0$, in which case we fix the size $\#X = \var{nmax}$: \bprog \\ at most 3 nonzero parts, all <= 4 ? forpart(v=5,print(Vec(v)), 4, 3) [1, 4] [2, 3] [1, 1, 3] [1, 2, 2] \\ between 2 and 4 parts less than 5, fill with zeros ? forpart(v=5,print(Vec(v)),[0,5],[2,4]) [0, 0, 1, 4] [0, 0, 2, 3] [0, 1, 1, 3] [0, 1, 2, 2] [1, 1, 1, 2] \\ no partitions of 1 with 2 to 4 nonzero parts ? forpart(v=1,print(v),[0,5],[2,4]) ? @eprog\noindent The behavior is unspecified if $X$ is modified inside the loop. \synt{forpart}{void *data, long (*call)(void*,GEN), long k, GEN a, GEN n}. pari-2.17.2/src/functions/programming/strjoin0000644000175000017500000000062414567450071017733 0ustar billbillFunction: strjoin Section: programming/specific C-Name: strjoin Prototype: GDG Help: strjoin(v,{p = ""}): joins the strings in vector v, separating them with delimiter p. Doc: joins the strings in vector $v$, separating them with delimiter $p$. The reverse operation is \kbd{strsplit}. \bprog ? v = ["abc", "def", "ghi"] ? strjoin(v, "/") %2 = "abc/def/ghi" ? strjoin(v) %3 = "abcdefghi" @eprog pari-2.17.2/src/functions/programming/trap0000644000175000017500000000444114760123736017212 0ustar billbillFunction: trap Section: programming/specific C-Name: trap0 Prototype: DrDEDE Obsolete: 2012-01-17 Help: trap({e},{rec},seq): this function is obsolete, use "iferr". Try to execute seq, trapping runtime error e (all of them if e omitted); sequence rec is executed if the error occurs and is the result of the command. Wrapper: (,_,_) Description: (?str,?closure,?closure):gen trap0($1, $2, $3) Doc: This function is obsolete, use \tet{iferr}, which has a nicer and much more powerful interface. For compatibility's sake we now describe the \emph{obsolete} function \tet{trap}. This function tries to evaluate \var{seq}, trapping runtime error $e$, that is effectively preventing it from aborting computations in the usual way; the recovery sequence \var{rec} is executed if the error occurs and the evaluation of \var{rec} becomes the result of the command. If $e$ is omitted, all exceptions are trapped. See \secref{se:errorrec} for an introduction to error recovery under \kbd{gp}. \bprog ? \\@com trap division by 0 ? inv(x) = trap (e_INV, INFINITY, 1/x) ? inv(2) %1 = 1/2 ? inv(0) %2 = INFINITY @eprog\noindent Note that \var{seq} is effectively evaluated up to the point that produced the error, and the recovery sequence is evaluated starting from that same context, it does not "undo" whatever happened in the other branch (restore the evaluation context): \bprog ? x = 1; trap (, /* recover: */ x, /* try: */ x = 0; 1/x) %1 = 0 @eprog \misctitle{Note} The interface is currently not adequate for trapping individual exceptions. In the current version \vers, the following keywords are recognized, but the name list will be expanded and changed in the future (all library mode errors can be trapped: it's a matter of defining the keywords to \kbd{gp}): \kbd{e\_ALARM}: alarm time-out \kbd{e\_ARCH}: not available on this architecture or operating system \kbd{e\_STACK}: the PARI stack overflows \kbd{e\_INV}: impossible inverse \kbd{e\_IMPL}: not yet implemented \kbd{e\_OVERFLOW}: all forms of arithmetic overflow, including length or exponent overflow (when a larger value is supplied than the implementation can handle). \kbd{e\_SYNTAX}: syntax error \kbd{e\_MISC}: miscellaneous error \kbd{e\_TYPE}: wrong type \kbd{e\_USER}: user error (from the \kbd{error} function) pari-2.17.2/src/functions/programming/write10000644000175000017500000000045614676526175017473 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}). pari-2.17.2/src/functions/programming/_eval_mnemonic0000644000175000017500000000021013637407207021205 0ustar billbillFunction: _eval_mnemonic C-Name: eval_mnemonic Section: programming/internals Prototype: lGs Help: Convert a mnemonic string to a flag. pari-2.17.2/src/functions/programming/filewrite10000644000175000017500000000066214676526175020332 0ustar billbillFunction: filewrite1 Section: programming/specific C-Name: gp_filewrite1 Prototype: vLs Help: filewrite1(n,s): write the string s to file number n without ending with newline. Doc: write the string $s$ to the file attached to descriptor $n$. The file must have been opened with \kbd{fileopen} in \kbd{"w"} or \kbd{"a"} mode. If you want to append a newline at the end of $s$, you can use \kbd{Str(s,"\bs n")} or \kbd{filewrite}. pari-2.17.2/src/functions/programming/filereadstr0000644000175000017500000000120314567450071020541 0ustar billbillFunction: filereadstr Section: programming/specific C-Name: gp_filereadstr Prototype: L Help: filereadstr(n): read a raw line from the file attached to the descriptor n, opened for reading with fileopen. Discard the terminating newline. Return 0 at end of file. Doc: read a raw line from the file attached to the descriptor $n$, opened for reading with \kbd{fileopen}, discarding the terminating newline. In other words the line is read exactly as input, up to the next carriage return \kbd{\bs n}. By comparison, \kbd{fileread} would read a logical line, as assembled by gp's preprocessor (skipping blanks and comments for instance). pari-2.17.2/src/functions/programming/iferr0000644000175000017500000002400514676526175017363 0ustar billbillFunction: _iferr_CATCH Class: gp2c_internal Description: (0) pari_CATCH(CATCH_ALL) (small) pari_CATCH2(__iferr_old$1, CATCH_ALL) Function: _iferr_ENDCATCH Class: gp2c_internal Description: (0) pari_ENDCATCH (small) pari_ENDCATCH2(__iferr_old$1) Function: _iferr_CATCH_reset Class: gp2c_internal Description: (0):void pari_CATCH_reset() (small):void pari_CATCH2_reset(__iferr_old$1) Function: _iferr_error Class: gp2c_internal Description: ():error pari_err_last() Function: _iferr_rethrow Class: gp2c_internal Description: (error):void pari_err(0, $1) Function: iferr Section: programming/control C-Name: iferrpari Prototype: EVEDE Help: iferr(seq1,E,seq2,{pred}): evaluates the expression sequence seq1. If an error occurs, set the formal parameter E set to the error data. If pred is not present or evaluates to true, catch the error and evaluate seq2. Both pred and seq2 can reference E. Doc: evaluates the expression sequence \var{seq1}. If an error occurs, set the formal parameter \var{E} set to the error data. If \var{pred} is not present or evaluates to true, catch the error and evaluate \var{seq2}. Both \var{pred} and \var{seq2} can reference \var{E}. The error type is given by \kbd{errname(E)}, and other data can be accessed using the \tet{component} function. The code \var{seq2} should check whether the error is the one expected. In the negative the error can be rethrown using \tet{error(E)} (and possibly caught by an higher \kbd{iferr} instance). The following uses \kbd{iferr} to implement Lenstra's ECM factoring method \bprog ? ecm(N, B = 1000!, nb = 100)= { for(a = 1, nb, iferr(ellmul(ellinit([a,1]*Mod(1,N)), [0,1]*Mod(1,N), B), E, return(gcd(lift(component(E,2)),N)), errname(E)=="e_INV" && type(component(E,2)) == "t_INTMOD")) } ? ecm(2^101-1) %2 = 7432339208719 @eprog The return value of \kbd{iferr} itself is the value of \var{seq2} if an error occurs, and the value of \var{seq1} otherwise. We now describe the list of valid error types, and the attached error data \var{E}; in each case, we list in order the components of \var{E}, accessed via \kbd{component(E,1)}, \kbd{component(E,2)}, etc. \misctitle{Internal errors, ``system'' errors} \item \kbd{"e\_ARCH"}. A requested feature $s$ is not available on this architecture or operating system. \var{E} has one component (\typ{STR}): the missing feature name $s$. \item \kbd{"e\_BUG"}. A bug in the PARI library, in function $s$. \var{E} has one component (\typ{STR}): the function name $s$. \item \kbd{"e\_FILE"}. Error while trying to open a file. \var{E} has two components, 1 (\typ{STR}): the file type (input, output, etc.), 2 (\typ{STR}): the file name. \item \kbd{"e\_IMPL"}. A requested feature $s$ is not implemented. \var{E} has one component, 1 (\typ{STR}): the feature name $s$. \item \kbd{"e\_PACKAGE"}. Missing optional package $s$. \var{E} has one component, 1 (\typ{STR}): the package name $s$. \misctitle{Syntax errors, type errors} \item \kbd{"e\_DIM"}. The dimensions of arguments $x$ and $y$ submitted to function $s$ does not match up. E.g., multiplying matrices of inconsistent dimension, adding vectors of different lengths,\dots \var{E} has three component, 1 (\typ{STR}): the function name $s$, 2: the argument $x$, 3: the argument $y$. \item \kbd{"e\_FLAG"}. A flag argument is out of bounds in function $s$. \var{E} has one component, 1 (\typ{STR}): the function name $s$. \item \kbd{"e\_NOTFUNC"}. Generated by the PARI evaluator; tried to use a \kbd{GEN} $x$ which is not a \typ{CLOSURE} in a function call syntax (as in \kbd{f = 1; f(2);}). \var{E} has one component, 1: the offending \kbd{GEN} $x$. \item \kbd{"e\_OP"}. Impossible operation between two objects than cannot be typecast to a sensible common domain for deeper reasons than a type mismatch, usually for arithmetic reasons. As in \kbd{O(2) + O(3)}: it is valid to add two \typ{PADIC}s, provided the underlying prime is the same; so the addition is not forbidden a priori for type reasons, it only becomes so when inspecting the objects and trying to perform the operation. \var{E} has three components, 1 (\typ{STR}): the operator name \var{op}, 2: first argument, 3: second argument. \item \kbd{"e\_TYPE"}. An argument $x$ of function $s$ had an unexpected type. (As in \kbd{factor("blah")}.) \var{E} has two components, 1 (\typ{STR}): the function name $s$, 2: the offending argument $x$. \item \kbd{"e\_TYPE2"}. Forbidden operation between two objects than cannot be typecast to a sensible common domain, because their types do not match up. (As in \kbd{Mod(1,2) + Pi}.) \var{E} has three components, 1 (\typ{STR}): the operator name \var{op}, 2: first argument, 3: second argument. \item \kbd{"e\_PRIORITY"}. Object $o$ in function $s$ contains variables whose priority is incompatible with the expected operation. E.g.~\kbd{Pol([x,1], 'y)}: this raises an error because it's not possible to create a polynomial whose coefficients involve variables with higher priority than the main variable. $E$ has four components: 1 (\typ{STR}): the function name $s$, 2: the offending argument $o$, 3 (\typ{STR}): an operator $\var{op}$ describing the priority error, 4 (\typ{POL}): the variable $v$ describing the priority error. The argument satisfies $\kbd{variable}(x)~\var{op} \kbd{variable}(v)$. \item \kbd{"e\_VAR"}. The variables of arguments $x$ and $y$ submitted to function $s$ does not match up. E.g., considering the algebraic number \kbd{Mod(t,t\pow2+1)} in \kbd{nfinit(x\pow2+1)}. \var{E} has three component, 1 (\typ{STR}): the function name $s$, 2 (\typ{POL}): the argument $x$, 3 (\typ{POL}): the argument $y$. \misctitle{Overflows} \item \kbd{"e\_COMPONENT"}. Trying to access an inexistent component in a vector/matrix/list in a function: the index is less than $1$ or greater than the allowed length. \var{E} has four components, 1 (\typ{STR}): the function name 2 (\typ{STR}): an operator $\var{op}$ ($<$ or $>$), 2 (\typ{GEN}): a numerical limit $l$ bounding the allowed range, 3 (\kbd{GEN}): the index $x$. It satisfies $x$ \var{op} $l$. \item \kbd{"e\_DOMAIN"}. An argument is not in the function's domain. \var{E} has five components, 1 (\typ{STR}): the function name, 2 (\typ{STR}): the mathematical name of the out-of-domain argument 3 (\typ{STR}): an operator $\var{op}$ describing the domain error, 4 (\typ{GEN}): the numerical limit $l$ describing the domain error, 5 (\kbd{GEN}): the out-of-domain argument $x$. The argument satisfies $x$ \var{op} $l$, which prevents it from belonging to the function's domain. \item \kbd{"e\_MAXPRIME"}. A function using the precomputed list of prime numbers ran out of primes. \var{E} has one component, 1 (\typ{INT}): the requested prime bound, which overflowed \kbd{primelimit} or $0$ (bound is unknown). \item \kbd{"e\_MEM"}. A call to \tet{pari_malloc} or \tet{pari_realloc} failed. \var{E} has no component. \item \kbd{"e\_OVERFLOW"}. An object in function $s$ becomes too large to be represented within PARI's hardcoded limits. (As in \kbd{2\pow2\pow2\pow10} or \kbd{exp(1e100)}, which overflow in \kbd{lg} and \kbd{expo}.) \var{E} has one component, 1 (\typ{STR}): the function name $s$. \item \kbd{"e\_PREC"}. Function $s$ fails because input accuracy is too low. (As in \kbd{floor(1e100)} at default accuracy.) \var{E} has one component, 1 (\typ{STR}): the function name $s$. \item \kbd{"e\_STACK"}. The PARI stack overflows. \var{E} has no component. \misctitle{Errors triggered intentionally} \item \kbd{"e\_ALARM"}. A timeout, generated by the \tet{alarm} function. \var{E} has one component (\typ{STR}): the error message to print. \item \kbd{"e\_USER"}. A user error, as triggered by \tet{error}($g_{1},\dots,g_{n})$. \var{E} has one component, 1 (\typ{VEC}): the vector of $n$ arguments given to \kbd{error}. \misctitle{Mathematical errors} \item \kbd{"e\_CONSTPOL"}. An argument of function $s$ is a constant polynomial, which does not make sense. (As in \kbd{galoisinit(Pol(1))}.) \var{E} has one component, 1 (\typ{STR}): the function name $s$. \item \kbd{"e\_COPRIME"}. Function $s$ expected coprime arguments, and did receive $x,y$, which were not. \var{E} has three component, 1 (\typ{STR}): the function name $s$, 2: the argument $x$, 3: the argument $y$. \item \kbd{"e\_INV"}. Tried to invert a noninvertible object $x$ in function $s$. \var{E} has two components, 1 (\typ{STR}): the function name $s$, 2: the noninvertible $x$. If $x = \kbd{Mod}(a,b)$ is a \typ{INTMOD} and $a$ is not $0$ mod $b$, this allows to factor the modulus, as \kbd{gcd}$(a,b)$ is a nontrivial divisor of $b$. \item \kbd{"e\_IRREDPOL"}. Function $s$ expected an irreducible polynomial, and did receive $T$, which was not. (As in \kbd{nfinit(x\pow2-1)}.) \var{E} has two component, 1 (\typ{STR}): the function name $s$, 2 (\typ{POL}): the polynomial $x$. \item \kbd{"e\_MISC"}. Generic uncategorized error. \var{E} has one component (\typ{STR}): the error message to print. \item \kbd{"e\_MODULUS"}. moduli $x$ and $y$ submitted to function $s$ are inconsistent. As in \bprog nfalgtobasis(nfinit(t^3-2), Mod(t,t^2+1)) @eprog\noindent \var{E} has three component, 1 (\typ{STR}): the function $s$, 2: the argument $x$, 3: the argument $y$. \item \kbd{"e\_PRIME"}. Function $s$ expected a prime number, and did receive $p$, which was not. (As in \kbd{idealprimedec(nf, 4)}.) \var{E} has two component, 1 (\typ{STR}): the function name $s$, 2: the argument $p$. \item \kbd{"e\_ROOTS0"}. An argument of function $s$ is a zero polynomial, and we need to consider its roots. (As in \kbd{polroots(0)}.) \var{E} has one component, 1 (\typ{STR}): the function name $s$. \item \kbd{"e\_SQRTN"}. Trying to compute an $n$-th root of $x$, which does not exist, in function $s$. (As in \kbd{sqrt(Mod(-1,3))}.) \var{E} has two components, 1 (\typ{STR}): the function name $s$, 2: the argument $x$. pari-2.17.2/src/functions/programming/breakpoint0000644000175000017500000000124314676526175020411 0ustar billbillFunction: breakpoint Section: programming/control C-Name: pari_breakpoint Prototype: v Help: breakpoint(): interrupt the program and enter the breakloop. The program continues when the breakloop is exited. Doc: Interrupt the program and enter the breakloop. The program continues when the breakloop is exited. \bprog ? f(N,x)=my(z=x^2+1);breakpoint();gcd(N,z^2+1-z); ? f(221,3) *** at top-level: f(221,3) *** ^-------- *** in function f: my(z=x^2+1);breakpoint();gcd(N,z *** ^-------------------- *** Break loop: type to continue; 'break' to go back to GP break> z 10 break> %2 = 13 @eprog pari-2.17.2/src/functions/programming/parforprimestep0000644000175000017500000000316214760123736021465 0ustar billbillFunction: _parforprimestep_init Class: gp2c_internal Help: Initializes parameters for parforprime. Description: (parforprime, gen, ?gen, gen, gen):void parforprimestep_init(&$1, $2, $3, $4, $5) Function: parforprimestep Section: programming/parallel C-Name: parforprimestep0 Prototype: vV=GDGGJDVDI Iterator: (gen,gen,gen,?gen,closure,?notype) (parforprime, _parforprimestep_init, _parforprime_next, _parforprime_stop) Help: parforprimestep(p=a,{b},q,expr1,{r},{expr2}): evaluates the expression expr1 in parallel for all primes p between a and b in an arithmetic progression of the form a + k*q, resulting in as many values; if the formal variables r and expr2 are present, evaluate sequentially expr2, in which r has been replaced by the different results obtained for expr1 and p with the corresponding arguments. Doc: behaves exactly as \kbd{parfor}, but loops only over prime values $p$ in an arithmetic progression Precisely, the functions evaluates in parallel the expression \kbd{expr1} in the formal argument $p$ running through the primes from $a$ to $b$ in an arithmetic progression of the form $a + k\*q$. ($p \equiv a \pmod{q}$) or an intmod \kbd{Mod(c,N)}. If $b$ is set to \kbd{+oo}, the loop runs indefinitely. If $r$ and \kbd{expr2} are present, the expression \kbd{expr2} in the formal variables $r$ and $p$ is evaluated with $r$ running through all the different results obtained for \kbd{expr1} and $p$ takes the corresponding argument. It is allowed fo \kbd{expr2} to exit the loop using \kbd{break}/\kbd{next}/\kbd{return}; see the remarks in the documentation of \kbd{parfor} for details. %\syn{NO} pari-2.17.2/src/functions/programming/parselect0000644000175000017500000000111514676526175020233 0ustar billbillFunction: parselect Section: programming/parallel C-Name: parselect Prototype: GGD0,L, Help: parselect(f,A,{flag=0}): (parallel select) selects elements of A according to the selection function f which is tested in parallel. If flag is 1, return the indices of those elements (indirect selection). Doc: selects elements of $A$ according to the selection function $f$, done in parallel. If \fl is $1$, return the indices of those elements (indirect selection) The function \kbd{f} must not access global variables or variables declared with local(), and must be free of side effects. pari-2.17.2/src/functions/programming/fordiv0000644000175000017500000000213314567450071017531 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 (slower) routine loops over the divisors using essentially constant space: \bprog FORDIV(N)= { my(F = factor(N), P = F[,1], E = F[,2]); forvec(v = vector(#E, i, [0,E[i]]), X = factorback(P, v)); } ? for(i=1, 10^6, FORDIV(i)) time = 11,180 ms. ? for(i=1, 10^6, fordiv(i, d, )) time = 2,667 ms. @eprog\noindent Of course, the divisors are no longer sorted by inreasing size. pari-2.17.2/src/functions/programming/inline0000644000175000017500000000103614567450071017517 0ustar billbillFunction: inline Section: programming/specific Obsolete: 2018-11-27 Help: inline(x,...,z): declares x,...,z as inline variables. DEPRECATED, use export. Doc: declare $x,\ldots, z$ as inline variables. Such variables behave like lexically scoped variable (see my()) but with unlimited scope. It is however possible to exit the scope by using \kbd{uninline()}. When used in a GP script, it is recommended to call \kbd{uninline()} before the script's end to avoid inline variables leaking outside the script. DEPRECATED, use \kbd{export}. pari-2.17.2/src/functions/programming/parploth0000644000175000017500000000522514567450071020076 0ustar billbillFunction: parploth Section: graphic C-Name: parploth Prototype: V=GGJD0,M,D0,L,p\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 Description: (gen,gen,closure,?small,?small):vec:prec parploth($1, $2, $3, $4, $5, $prec) Help: parploth(X=a,b,expr,{flags=0},{n=0}): parallel version of ploth. Plot of expression expr, X goes from a to b in high resolution. Both flags and n are optional. Binary digits of flags mean: 1=Parametric, 2=Recursive, 4=no_Rescale, 8=no_X_axis, 16=no_Y_axis, 32=no_Frame, 64=no_Lines (do not join points), 128=Points_too (plot both lines and points), 256=Splines (use cubic splines), 512=no_X_ticks, 1024= no_Y_ticks, 2048=Same_ticks (plot all ticks with the same length), 4096=Complex (the two coordinates of each point are encoded as a complex number). n specifies number of reference points on the graph (0=use default value). Returns a vector for the bounding box. Doc: parallel version of \kbd{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{parploth} 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. The parameter $n$ specifies the number of reference point on the graph, where a value of 0 means we use the hardwired default values; the binary digits of \fl\ have the same meaning as in \kbd{ploth}: $1 = \kbd{Parametric}$; $2 = \kbd{Recursive}$; $4 = \kbd{no\_Rescale}$; $8 = \kbd{no\_X\_axis}$; $16 = \kbd{no\_Y\_axis}$; $32 = \kbd{no\_Frame}$; $64 = \kbd{no\_Lines}$; $128 = \kbd{Points\_too}$; $256 = \kbd{Splines}$; $512 = \kbd{no\_X\_ticks}$; $1024 = \kbd{no\_Y\_ticks}$; $2048 = \kbd{Same\_ticks}$; $4096 = \kbd{Complex}$. For instance: \bprog \\ circle parploth(X=0,2*Pi,[sin(X),cos(X)], "Parametric") \\ two entwined sinusoidal curves parploth(X=0,2*Pi,[sin(X),cos(X)]) \\ circle cut by the line y = x parploth(X=0,2*Pi,[X,X,sin(X),cos(X)], "Parametric") \\ circle parploth(X=0,2*Pi,exp(I*X), "Complex") \\ circle cut by the line y = x parploth(X=0,2*Pi,[(1+I)*X,exp(I*X)], "Complex") @eprog \synt{parploth}{GEN a,GEN b,GEN code, long flag, long n, long prec}. pari-2.17.2/src/functions/programming/mapisdefined0000644000175000017500000000160614676526175020706 0ustar billbillFunction: mapisdefined Section: programming/specific C-Name: mapisdefined Prototype: iGGD& Help: mapisdefined(M,x,{&z}): true (1) if x has an image by the map M, false (0) otherwise. If z is present, set it to the image of x, if it exists. Doc: Returns true ($1$) if $x$ has an image by the map $M$, false ($0$) otherwise. If $z$ is present, set $z$ to the image of $x$, if it exists. \bprog ? M1 = Map([1, 10; 2, 20]); ? mapisdefined(M1,3) %1 = 0 ? mapisdefined(M1, 1, &z) %2 = 1 ? z %3 = 10 @eprog \bprog ? M2 = Map(); N = 19; ? for (a=0, N-1, mapput(M2, a^3%N, a)); ? {for (a=0, N-1, if (mapisdefined(M2, a, &b), printf("%d is the cube of %d mod %d\n",a,b,N)));} 0 is the cube of 0 mod 19 1 is the cube of 11 mod 19 7 is the cube of 9 mod 19 8 is the cube of 14 mod 19 11 is the cube of 17 mod 19 12 is the cube of 15 mod 19 18 is the cube of 18 mod 19 @eprog pari-2.17.2/src/functions/programming/getlocalprec0000644000175000017500000000036314760123736020707 0ustar billbillFunction: getlocalprec Section: programming/specific C-Name: getlocalprec Prototype: lp Help: getlocalprec(): returns the current dynamic precision, in decimal digits. Doc: returns the current dynamic precision, in decimal digits. %\syn{NO} pari-2.17.2/src/functions/programming/errname0000644000175000017500000000061714567450071017676 0ustar billbillFunction: errname Section: programming/specific C-Name: errname Prototype: G Help: errname(E): returns the type of the error message E. Doc: returns the type of the error message \kbd{E} as a string. \bprog ? iferr(1 / 0, E, print(errname(E))) e_INV ? ?? e_INV [...] * "e_INV". Tried to invert a noninvertible object x in function s. [...] @eprog Description: (gen):errtyp err_get_num($1) pari-2.17.2/src/functions/programming/fileextern0000644000175000017500000000123614567450071020410 0ustar billbillFunction: fileextern Section: programming/specific C-Name: gp_fileextern Prototype: ls Help: fileextern(str): execute shell command str and returns a file descriptor attached to the command output as if it were read from a 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 the function returns a file descriptor attached to the command output as if it were read from a file. \bprog ? n = fileextern("ls -l"); ? while(l = filereadstr(n), print(l)) ? fileclose(n) @eprog\noindent If the \kbd{secure} default is set, this function will raise en exception. pari-2.17.2/src/functions/programming/forfactored0000644000175000017500000000406714676526175020560 0ustar billbillFunction: forfactored Section: programming/control C-Name: forfactored Prototype: vV=GGI Help: forfactored(N=a,b,seq): the sequence is evaluated, N is of the form [n, factor(n)], n going from a up to b. Doc: evaluates \var{seq}, where the formal variable $N$ is $[n, \kbd{factor}(n)]$ and $n$ goes from $a$ to $b$; $a$ and $b$ must be integers. Nothing is done if $a>b$. This function is only implemented for $|a|, |b| < 2^{64}$ ($2^{32}$ on a 32-bit machine). It uses a sieve and runs in time $O(\sqrt{b} + b-a)$. It should be at least 3 times faster than regular factorization as long as the interval length $b-a$ is much larger than $\sqrt{b}$ and get relatively faster as the bounds increase. The function slows down dramatically if $\kbd{primelimit} < \sqrt{b}$. \bprog ? B = 10^9; ? for (N = B, B+10^6, factor(N)) time = 4,538 ms. ? forfactored (N = B, B+10^6, [n,fan] = N) time = 1,031 ms. ? B = 10^11; ? for (N = B, B+10^6, factor(N)) time = 15,575 ms. ? forfactored (N = B, B+10^6, [n,fan] = N) time = 2,375 ms. ? B = 10^14; ? for (N = B, B+10^6, factor(N)) time = 1min, 4,948 ms. ? forfactored (N = B, B+10^6, [n,fan] = N) time = 58,601 ms. @eprog\noindent The last timing is with the default \kbd{primelimit} (500000) which is much less than $\sqrt{B+10^{6}}$; it goes down to \kbd{26,750ms} if \kbd{primelimit} gets bigger than that bound. In any case $\sqrt{B+10^{6}}$ is much larger than the interval length $10^{6}$ so \kbd{forfactored} gets relatively slower for that reason as well. Note that all PARI multiplicative functions accept the \kbd{[n,fan]} argument natively: \bprog ? s = 0; forfactored(N = 1, 10^7, s += moebius(N)*eulerphi(N)); s time = 6,001 ms. %1 = 6393738650 ? s = 0; for(N = 1, 10^7, s += moebius(N)*eulerphi(N)); s time = 28,398 ms. \\ slower, we must factor N. Twice. %2 = 6393738650 @eprog The following loops over the fundamental dicriminants less than $X$: \bprog ? X = 10^8; ? forfactored(d=1,X, if (isfundamental(d),)); time = 34,030 ms. ? for(d=1,X, if (isfundamental(d),)) time = 1min, 24,225 ms. @eprog pari-2.17.2/src/functions/programming/parapply0000644000175000017500000000143214676526175020103 0ustar billbillFunction: parapply Section: programming/parallel C-Name: parapply Prototype: GG Help: parapply(f,x): parallel evaluation of f on the elements of x. Doc: parallel evaluation of $f$ on the elements of $x$. The function $f$ must not access global variables or variables declared with local(), and must be free of side effects. \bprog parapply(factor,[2^256 + 1, 2^193 - 1]) @eprog factors $2^{256} + 1$ and $2^{193} - 1$ in parallel. \bprog { my(E = ellinit([1,3]), V = vector(12,i,randomprime(2^200))); parapply(p->ellcard(E,p), V) } @eprog computes the order of $E(\F_{p})$ for $12$ random primes of $200$ bits. Function: _parapply_slice_worker Section: programming/internals C-Name: parapply_slice_worker Prototype: GG Help: _parapply_slice_worker(v,C): return [C(x) | x<-v]. pari-2.17.2/src/functions/programming/self0000644000175000017500000000072014567450071017171 0ustar billbillFunction: self Section: programming/specific C-Name: pari_self Prototype: m Help: self(): return the calling function or closure. Useful for defining anonymous recursive functions. Doc: return the calling function or closure as a \typ{CLOSURE} object. This is useful for defining anonymous recursive functions. \bprog ? (n -> if(n==0,1,n*self()(n-1)))(5) %1 = 120 \\ 5! ? (n -> if(n<=1, n, self()(n-1)+self()(n-2)))(20) %2 = 6765 \\ Fibonacci(20) @eprog pari-2.17.2/src/functions/programming/print10000644000175000017500000000076614676526175017501 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 arguments in raw format, without ending with a newline. Note that you can still embed newlines within your strings, using the \b{n} notation~! The arguments are converted to strings following the rules in \secref{se:strings}. pari-2.17.2/src/functions/programming/getabstime0000644000175000017500000000065014567450071020366 0ustar billbillFunction: getabstime Section: programming/specific C-Name: getabstime Prototype: l Help: getabstime(): milliseconds of CPU time since startup. Doc: returns the CPU time (in milliseconds) elapsed since \kbd{gp} startup. This provides a reentrant version of \kbd{gettime}: \bprog my (t = getabstime()); ... print("Time: ", strtime(getabstime() - t)); @eprog For a version giving wall-clock time, see \tet{getwalltime}. pari-2.17.2/src/functions/programming/getcache0000644000175000017500000000332414676526175020020 0ustar billbillFunction: getcache Section: programming/specific C-Name: getcache Prototype: Help: getcache(): returns information about various auto-growing caches. For each resource, we report its name, its size, the number of cache misses (since the last extension) and the largest cache miss. Doc: returns information about various auto-growing caches. For each resource, we report its name, its size, the number of cache misses (since the last extension), the largest cache miss and the size of the cache in bytes. The caches are initially empty, then set automatically to a small inexpensive default value, then grow on demand up to some maximal value. Their size never decreases, they are only freed on exit. The current caches are \item Hurwitz class numbers $H(D)$ for $|D| \leq N$, computed in time $O(N^{3/2})$ using $O(N)$ space. \item Factorizations of small integers up to $N$, computed in time $O(N^{1+\varepsilon})$ using $O(N\log N)$ space. \item Divisors of small integers up to $N$, computed in time $O(N^{1+\varepsilon})$ using $O(N\log N)$ space. \item Coredisc's of negative integers down to $-N$, computed in time $O(N^{1+\varepsilon})$ using $O(N)$ space. \item Primitive dihedral forms of weight $1$ and level up to $N$, computed in time $O(N^{2+\varepsilon})$ and space $O(N^{2})$. \bprog ? getcache() \\ on startup, all caches are empty %1 = [ "Factors" 0 0 0 0] [ "Divisors" 0 0 0 0] [ "H" 0 0 0 0] ["CorediscF" 0 0 0 0] [ "Dihedral" 0 0 0 0] ? mfdim([500,1,0],0); \\ nontrivial computation time = 540 ms. ? getcache() %3 = [ "Factors" 50000 0 0 4479272] ["Divisors" 50000 1 100000 5189808] [ "H" 50000 0 0 400008] ["Dihedral" 1000 0 0 2278208] @eprog pari-2.17.2/src/functions/programming/my0000644000175000017500000000016313637407207016666 0ustar billbillFunction: my Section: programming/specific Help: my(x,...,z): declare x,...,z as lexically-scoped local variables. pari-2.17.2/src/functions/programming/error0000644000175000017500000000135414676526175017407 0ustar billbillFunction: _err_primes Class: gp2c_internal Description: ():void pari_err(e_MAXPRIME) Function: _err_type Class: gp2c_internal Description: (str,gen):void pari_err_TYPE($1,$2) Function: error Section: programming/specific C-Name: error0 Prototype: vs* Help: error({str}*): abort script with error message str. Description: (error):void pari_err(0, $1) (?gen,...):void pari_err(e_MISC, "${2 format_string}"${2 format_args}) Doc: outputs its argument list (each of them interpreted as a string), then interrupts the running \kbd{gp} program, returning to the input prompt. For instance \bprog error("n = ", n, " is not squarefree!") @eprog\noindent Variant: The variadic version \fun{void}{pari_err}{e_USER,...} is usually preferable. pari-2.17.2/src/functions/programming/forperm0000644000175000017500000000251314567450071017714 0ustar billbillFunction: _forperm_init Class: gp2c_internal Help: Initialize forperm_t Description: (forperm,gen):void forperm_init(&$1, $2) Function: _forperm_next Class: gp2c_internal Help: Compute the next permutation Description: (forperm):vecsmall forperm_next(&$1) Function: forperm Section: programming/control C-Name: forperm0 Prototype: vGVI Iterator: (gen,gen) (forperm, _forperm_init, _forperm_next) Wrapper: (,vG,,) Help: forperm(a,p,seq): the sequence is evaluated, p going through permutations of a. Doc: evaluates \var{seq}, where the formal variable $p$ goes through some permutations given by a \typ{VECSMALL}. If $a$ is a positive integer then $P$ goes through the permutations of $\{1, 2, ..., a\}$ in lexicographic order and if $a$ is a small vector then $p$ goes through the (multi)permutations lexicographically larger than or equal to $a$. \bprog ? forperm(3, p, print(p)) Vecsmall([1, 2, 3]) Vecsmall([1, 3, 2]) Vecsmall([2, 1, 3]) Vecsmall([2, 3, 1]) Vecsmall([3, 1, 2]) Vecsmall([3, 2, 1]) @eprog\noindent When $a$ is itself a \typ{VECSMALL} or a \typ{VEC} then $p$ iterates through multipermutations \bprog ? forperm([2,1,1,3], p, print(p)) Vecsmall([2, 1, 1, 3]) Vecsmall([2, 1, 3, 1]) Vecsmall([2, 3, 1, 1]) Vecsmall([3, 1, 1, 2]) Vecsmall([3, 1, 2, 1]) Vecsmall([3, 2, 1, 1]) @eprog\noindent pari-2.17.2/src/functions/programming/warning0000644000175000017500000000073214676526175017722 0ustar billbillFunction: warning Section: programming/specific C-Name: warning0 Prototype: vs* Help: warning({str}*): display warning message str. Description: (gen,...):void pari_warn(warnuser, mkvecn($#, $2)) 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 pari-2.17.2/src/functions/programming/getlocalbitprec0000644000175000017500000000033514760123736021405 0ustar billbillFunction: getlocalbitprec Section: programming/specific C-Name: getlocalbitprec Prototype: lb Help: getlocalbitprec(): returns the current dynamic bit precision. Doc: returns the current dynamic bit precision. %\syn{NO} pari-2.17.2/src/functions/programming/strsplit0000644000175000017500000000135214567450071020126 0ustar billbillFunction: strsplit Section: programming/specific C-Name: strsplit Prototype: GDG Help: strsplit(s,{p = ""}): splits the string s into a vector of strings, with p acting as a delimiter between successive fields; if p is empty or omitted, split into characters. Doc: splits the string $s$ into a vector of strings, with $p$ acting as a delimiter. If $p$ is empty or omitted, split the string into characters. \bprog ? strsplit("abc::def::ghi", "::") %1 = ["abc", "def", "ghi"] ? strsplit("abc", "") %2 = ["a", "b", "c"] ? strsplit("aba", "a") @eprog\noindent If $s$ starts (resp.~ends) with the pattern $p$, then the first (resp.~last) entry in the vector is the empty string: \bprog ? strsplit("aba", "a") %3 = ["", "b", ""] @eprog pari-2.17.2/src/functions/programming/default0000644000175000017500000000340314567450071017665 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.17.2/src/functions/programming/fileflush0000644000175000017500000000222614567450071020224 0ustar billbillFunction: fileflush Section: programming/specific C-Name: gp_fileflush0 Prototype: vDG Help: fileflush({n}): flush the file descriptor n (all descriptors to output streams if n is omitted). Doc: flushes the file descriptor $n$, created via \kbd{fileopen} or \kbd{fileextern}. On files opened for writing, this function forces a write of all buffered data to the file system and completes all pending write operations. This function is implicitly called by \kbd{fileclose} but you may want to call it explicitly at synchronization points, for instance after writing a large result to file and before printing diagnostics on screen. (In order to be sure that the file contains the expected content on inspection.) If $n$ is omitted, flush all descriptors to output streams. \bprog ? n = fileopen("./here", "w"); ? for (i = 1, 10^5, \ filewrite(n, i^2+1); \ if (i % 10000 == 0, fileflush(n))) @eprog Until a \kbd{fileflush} or \kbd{fileclose}, there is no guarantee that the file contains all the expected data from previous \kbd{filewrite}s. Variant: But the direct and more specific variant \fun{void}{gp_fileflush}{long n} is also available. pari-2.17.2/src/functions/programming/gettime0000644000175000017500000000071414567450071017701 0ustar billbillFunction: gettime Section: programming/specific C-Name: gettime Prototype: l Help: gettime(): milliseconds of CPU time used since the last call to gettime. Doc: returns the CPU time (in milliseconds) used since either the last call to \kbd{gettime}, or to the beginning of the containing GP instruction (if inside \kbd{gp}), whichever came last. For a reentrant version, see \tet{getabstime}. For a version giving wall-clock time, see \tet{getwalltime}. pari-2.17.2/src/functions/programming/read0000644000175000017500000000205714567450071017160 0ustar billbillFunction: read Section: programming/specific C-Name: gp_read_file Prototype: D"",s, Help: read({filename}): read from the input file filename. If filename is omitted, reread last input file, be it from read() or \r. 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. \misctitle{Variants} \kbd{readvec} allows to read a whole file at once; \kbd{fileopen} followed by either \kbd{fileread} (evaluated lines) or \kbd{filereadstr} (lines as nonevaluated strings) allows to read a file one line at a time. pari-2.17.2/src/functions/programming/parfor0000644000175000017500000000642614760123736017542 0ustar billbillFunction: _parfor_init Class: gp2c_internal Help: Initializes parameters for parfor. Description: (parfor, gen, gen, gen):void parfor_init(&$1, $2, $3, $4) Function: _parfor_next Class: gp2c_internal Help: Next value for parfor. Description: (parfor):gen parfor_next(&$1) Function: _parfor_stop Class: gp2c_internal Help: Stop function for parfor. Description: (parfor):void parfor_stop(&$1) Function: parfor Section: programming/parallel C-Name: parfor0 Prototype: vV=GDGJDVDI Iterator: (gen,gen,?gen,closure,?notype) (parfor, _parfor_init, _parfor_next, _parfor_stop) Help: parfor(i=a,{b},expr1,{r},{expr2}): evaluates the expression expr1 in parallel for all i between a and b (if b is set to +oo, the loop will not stop), resulting in as many values; if r and expr2 are present, the expression expr2 in the formal variables r and i is evaluated with r running through all the different results obtained for expr1 and i takes the corresponding argument. Doc: evaluates in parallel the expression \kbd{expr1} in the formal argument $i$ running from $a$ to $b$. If $b$ is set to \kbd{+oo}, the loop runs indefinitely. If $r$ and \kbd{expr2} are present, the expression \kbd{expr2} in the formal variables $r$ and $i$ is evaluated with $r$ running through all the different results obtained for \kbd{expr1} and $i$ takes the corresponding argument. The computations of \kbd{expr1} are \emph{started} in increasing order of $i$; otherwise said, the computation for $i=c$ is started after those for $i=1, \ldots, c-1$ have been started, but before the computation for $i=c+1$ is started. Notice that the order of \emph{completion}, that is, the order in which the different $r$ become available, may be different; \kbd{expr2} is evaluated sequentially on each $r$ as it appears. The following example computes the sum of the squares of the integers from $1$ to $10$ by computing the squares in parallel and is equivalent to \kbd{parsum (i=1, 10, i\^{}2)}: \bprog ? s=0; ? parfor (i=1, 10, i^2, r, s=s+r) ? s %3 = 385 @eprog More precisely, apart from a potentially different order of evaluation due to the parallelism, the line containing \kbd{parfor} is equivalent to \bprog ? my (r); for (i=1, 10, r=i^2; s=s+r) @eprog The sequentiality of the evaluation of \kbd{expr2} ensures that the variable \kbd{s} is not modified concurrently by two different additions, although the order in which the terms are added is nondeterministic. It is allowed for \kbd{expr2} to exit the loop using \kbd{break}/\kbd{next}/\kbd{return}. If that happens for $i=c$, then the evaluation of \kbd{expr1} and \kbd{expr2} is continued for all values $i 0$, a new stack of at least $s$ bytes is allocated. We may allocate more than $s$ bytes if $s$ is way too small, or for alignment reasons: the current formula is $\max(16*\ceil{s/16}, 500032)$ bytes. If $s=0$, the size of the new stack is twice the size of the old one. This command is much more useful if \tet{parisizemax} is nonzero, and we describe this case first. With \kbd{parisizemax} enabled, there are three sizes of interest: \item a virtual stack size, \tet{parisizemax}, which is an absolute upper limit for the stack size; this is set by \kbd{default(parisizemax, ...)}. \item the desired typical stack size, \tet{parisize}, that will grow as needed, up to \tet{parisizemax}; this is set by \kbd{default(parisize, ...)}. \item the current stack size, which is less that \kbd{parisizemax}, typically equal to \kbd{parisize} but possibly larger and increasing dynamically as needed; \kbd{allocatemem} allows to change that one explicitly. The \kbd{allocatemem} command forces stack usage to increase temporarily (up to \kbd{parisizemax} of course); for instance if you notice using \kbd{\bs gm2} that we seem to collect garbage a lot, e.g. \bprog ? \gm2 debugmem = 2 ? default(parisize,"32M") *** Warning: new stack size = 32000000 (30.518 Mbytes). ? bnfinit('x^2+10^30-1) *** bnfinit: collecting garbage in hnffinal, i = 1. *** bnfinit: collecting garbage in hnffinal, i = 2. *** bnfinit: collecting garbage in hnffinal, i = 3. @eprog\noindent and so on for hundred of lines. Then, provided the \tet{breakloop} default is set, you can interrupt the computation, type \kbd{allocatemem(100*10\pow6)} at the break loop prompt, then let the computation go on by typing \kbd{}. Back at the \kbd{gp} prompt, the desired stack size of \kbd{parisize} is restored. Note that changing either \kbd{parisize} or \kbd{parisizemax} at the break loop prompt would interrupt the computation, contrary to the above. In most cases, \kbd{parisize} will increase automatically (up to \kbd{parisizemax}) and there is no need to perform the above maneuvers. But that the garbage collector is sufficiently efficient that a given computation can still run without increasing the stack size, albeit very slowly due to the frequent garbage collections. \misctitle{Deprecated: when \kbd{parisizemax} is unset} This is currently still the default behavior in order not to break backward compatibility. The rest of this section documents the behavior of \kbd{allocatemem} in that (deprecated) situation: it becomes a synonym for \kbd{default(parisize,...)}. In that case, there is no notion of a virtual stack, and the stack size is always equal to \kbd{parisize}. If more memory is needed, the PARI stack overflows, aborting the computation. Thus, increasing \kbd{parisize} via \kbd{allocatemem} or \kbd{default(parisize,...)} before a big computation is important. Unfortunately, either must be typed at the \kbd{gp} prompt in interactive usage, or left by itself at the start of batch files. They cannot be used meaningfully in loop-like constructs, or as part of a larger expression sequence, e.g \bprog allocatemem(); x = 1; \\@com This will not set \kbd{x}! @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 are 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 reason for these unfortunate side-effects is that, with \kbd{parisizemax} disabled, increasing the stack size physically moves the stack, so temporary objects created during the current expression evaluation are not correct anymore. (In particular byte-compiled expressions, which are allocated on the stack.) To avoid accessing obsolete pointers to the old stack, this routine ends by a \kbd{longjmp}. pari-2.17.2/src/functions/programming/system0000644000175000017500000000130414567450071017563 0ustar billbillFunction: system Section: programming/specific C-Name: gpsystem Prototype: ls 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. Return the shell return value (which is system-dependent). Beware that UNIX shell convention for boolean is opposite to GP, true is $0$ and false is non-$0$. \bprog ? system("test -d /") \\ test if '/' is a directory (true) %1 = 0 ? system("test -f /") \\ test if '/' is a file (false) %2 = 1 @eprog pari-2.17.2/src/functions/programming/input0000644000175000017500000000135214567450071017401 0ustar billbillFunction: input Section: programming/specific C-Name: gp_input Prototype: Help: input(): read an expression from the input file or standard input. Doc: reads a string, interpreted as a GP expression, 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.17.2/src/functions/programming/local0000644000175000017500000000017513637407207017336 0ustar billbillFunction: local Section: programming/specific Help: local(x,...,z): declare x,...,z as (dynamically scoped) local variables. pari-2.17.2/src/functions/programming/fordivfactored0000644000175000017500000000256614567450071021253 0ustar billbillFunction: fordivfactored Section: programming/control C-Name: fordivfactored Prototype: vGVI Help: fordivfactored(n,X,seq): the sequence is evaluated, X running over the [d, factor(d)], d a divisor of n. Doc: evaluates \var{seq}, where the formal variable $X$ ranges through $[d, \kbd{factor}(d)]$, where $d$ is a divisors of $n$ (see \tet{divisors}, which is used as a subroutine). Note that such a pair is accepted as argument to all multiplicative functions. 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}$(,1)$ as a subroutine, then loops over the divisors. In particular, if $n$ is an integer, divisors are sorted by increasing size. This function is particularly useful when $n$ is hard to factor and one must evaluate multiplicative function on its divisors: we avoid refactoring each divisor in turn. It also provides a small speedup when $n$ is easy to factor; compare \bprog ? A = 10^8; B = A + 10^5; ? for (n = A, B, fordiv(n, d, eulerphi(d))); time = 2,091 ms. ? for (n = A, B, fordivfactored(n, d, eulerphi(d))); time = 1,298 ms. \\ avoid refactoring the divisors ? forfactored (n = A, B, fordivfactored(n, d, eulerphi(d))); time = 1,270 ms. \\ also avoid factoring the consecutive n's ! @eprog pari-2.17.2/src/functions/programming/printp0000644000175000017500000000104114676526175017563 0ustar billbillFunction: printp Section: programming/specific C-Name: printp Prototype: vs* Help: printp({str}*): outputs its string arguments (in prettymatrix format) ending with a newline. Description: (?gen,...):void pari_printf("${2 format_string}\n"${2 format_args}) Doc: outputs its arguments in prettymatrix format, ending with a newline. The arguments are converted to strings following the rules in \secref{se:strings}. \bprog ? m = matid(2); ? print(m) \\ raw format [1, 0; 0, 1] ? printp(m) \\ prettymatrix format [1 0] [0 1] @eprog pari-2.17.2/src/functions/programming/forsubgroup0000644000175000017500000000402714676526175020633 0ustar billbillFunction: forsubgroup Section: programming/control C-Name: forsubgroup0 Prototype: vV=GDGI Help: forsubgroup(H=G,{bound},seq): execute seq for each subgroup H of the abelian group G, whose index is bounded by bound if not omitted. H is given as a left divisor of G in HNF form. Wrapper: (,,vG) Description: (gen,?gen,closure):void forsubgroup(${3 cookie}, ${3 wrapper}, $1, $2) Doc: evaluates \var{seq} for each subgroup $H$ of the \emph{abelian} group $G$ (given in SNF\sidx{Smith normal form} form or as a vector of elementary divisors). If \var{bound} is present, and is a positive integer, restrict the output to subgroups of index less than \var{bound}. If \var{bound} is a vector containing a single positive integer $B$, then only subgroups of index exactly equal to $B$ are computed The subgroups are not ordered in any obvious way, unless $G$ is a $p$-group in which case Birkhoff's algorithm produces them by decreasing index. A \idx{subgroup} is given as a matrix whose columns give its generators on the implicit generators of $G$. For example, the following prints all subgroups of index less than 2 in $G = \Z/2\Z g_{1} \times \Z/2\Z g_{2}$: \bprog ? G = [2,2]; forsubgroup(H=G, 2, print(H)) [1; 1] [1; 2] [2; 1] [1, 0; 1, 1] @eprog\noindent The last one, for instance is generated by $(g_{1}, g_{1} + g_{2})$. This routine is intended to treat huge groups, when \tet{subgrouplist} is not an option due to the sheer size of the output. For maximal speed the subgroups have been left as produced by the algorithm. To print them in canonical form (as left divisors of $G$ in HNF form), one can for instance use \bprog ? G = matdiagonal([2,2]); forsubgroup(H=G, 2, print(mathnf(concat(G,H)))) [2, 1; 0, 1] [1, 0; 0, 2] [2, 0; 0, 1] [1, 0; 0, 1] @eprog\noindent Note that in this last representation, the index $[G:H]$ is given by the determinant. See \tet{galoissubcyclo} and \tet{galoisfixedfield} for applications to \idx{Galois} theory. \synt{forsubgroup}{void *data, long (*call)(void*,GEN), GEN G, GEN bound}. pari-2.17.2/src/functions/programming/fileclose0000644000175000017500000000415414567450071020212 0ustar billbillFunction: fileclose Section: programming/specific C-Name: gp_fileclose Prototype: vL Help: fileclose(n): close the file descriptor n. Doc: close the file descriptor $n$, created via \kbd{fileopen} or \kbd{fileextern}. Finitely many files can be opened at a given time, closing them recycles file descriptors and avoids running out of them: \bprog ? n = 0; while(n++, fileopen("/tmp/test", "w")) *** at top-level: n=0;while(n++,fileopen("/tmp/test","w")) *** ^-------------------------- *** fileopen: error opening requested file: `/tmp/test'. *** Break loop: type 'break' to go back to GP prompt break> n 65533 @eprog\noindent This is a limitation of the operating system and does not depend on PARI: if you open too many files in \kbd{gp} without closing them, the operating system will also prevent unrelated applications from opening files. Independently, your operating system (e.g. Windows) may prevent other applications from accessing or deleting your file while it is opened by \kbd{gp}. Quitting \kbd{gp} implicitly calls this function on all opened file descriptors. On files opened for writing, this function also forces a write of all buffered data to the file system and completes all pending write operations. This function is implicitly called for all open file descriptors when exiting \kbd{gp} but it is cleaner and safer to call it explicitly, for instance in case of a \kbd{gp} crash or general system failure, which could cause data loss. \bprog ? n = fileopen("./here"); ? while(l = fileread(n), print(l)); ? fileclose(n); ? n = fileopen("./there", "w"); ? for (i = 1, 100, filewrite(n, i^2+1)) ? fileclose(n) @eprog Until a \kbd{fileclose}, there is no guarantee that the file on disk contains all the expected data from previous \kbd{filewrite}s. (And even then the operating system may delay the actual write to hardware.) Closing a file twice raises an exception: \bprog ? n = fileopen("/tmp/test"); ? fileclose(n) ? fileclose(n) *** at top-level: fileclose(n) *** ^------------ *** fileclose: invalid file descriptor 0 @eprog pari-2.17.2/src/functions/programming/listsort0000644000175000017500000000226014567450071020124 0ustar billbillFunction: listsort Section: programming/specific C-Name: listsort Prototype: vWD0,L, Help: listsort(~L,{flag=0}): sort the list L in place. If flag is nonzero, suppress all but one occurrence of each element in list. Doc: sorts the \typ{LIST} \var{list} in place, with respect to the (somewhat arbitrary) universal comparison function \tet{cmp}. In particular, the ordering is the same as for sets and \tet{setsearch} can be used on a sorted list. No value is returned. If $\fl$ is nonzero, suppresses all repeated coefficients. \bprog ? L = List([1,2,4,1,3,-1]); listsort(~L); L %1 = List([-1, 1, 1, 2, 3, 4]) ? setsearch(L, 4) %2 = 6 ? setsearch(L, -2) %3 = 0 ? listsort(~L, 1); L \\ remove duplicates %4 = List([-1, 1, 2, 3, 4]) @eprog\noindent Note the \kbd{\til L}: this means that the function is called with a \emph{reference} to \kbd{L} and changes \kbd{L} in place: this is faster than the \kbd{vecsort} command since the list is sorted in place and we avoid unnecessary copies. \bprog ? v = vector(100,i,random); L = List(v); ? for(i=1,10^4, vecsort(v)) time = 162 ms. ? for(i=1,10^4, vecsort(L)) time = 162 ms. ? for(i=1,10^4, listsort(~L)) time = 63 ms. @eprog pari-2.17.2/src/functions/programming/setrand0000644000175000017500000000223314567450071017701 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 a small positive integer $0 < n < 2^{64}$ used to generate deterministically a suitable state array. All gp session start by an implicit \kbd{setrand(1)}, so resetting the seed to this value allows to replay all computations since the session start. Alternatively, running a randomized computation starting by \kbd{setrand}($n$) twice with the same $n$ will generate the exact same output. In the other direction, including a call to \kbd{setrand(getwalltime())} from your gprc will cause GP to produce different streams of random numbers in each session. (Unix users may want to use \kbd{/dev/urandom} instead of \kbd{getwalltime}.) For debugging purposes, one can also record a particular random state using \kbd{getrand} (the value is encoded as a huge integer) and feed it to \kbd{setrand}: \bprog ? state = getrand(); \\ record seed ... ? setrand(state); \\ we can now replay the exact same computations @eprog pari-2.17.2/src/functions/programming/break0000644000175000017500000000075213637407207017331 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.17.2/src/functions/programming/version0000644000175000017500000000451514567450071017733 0ustar billbillFunction: version Section: programming/specific C-Name: pari_version Prototype: Help: version(): returns the PARI version as [major,minor,patch] or [major,minor,patch,GITversion]. Doc: returns the current version number as a \typ{VEC} with three integer components (major version number, minor version number and patchlevel); if your sources were obtained through our version control system, this will be followed by further more precise arguments, including e.g.~a~\kbd{git} \emph{commit hash}. This function is present in all versions of PARI following releases 2.3.4 (stable) and 2.4.3 (testing). Unless you are working with multiple development versions, you probably only care about the 3 first numeric components. In any case, the \kbd{lex} function offers a clever way to check against a particular version number, since it will compare each successive vector entry, numerically or as strings, and will not mind if the vectors it compares have different lengths: \bprog if (lex(version(), [2,3,5]) >= 0, \\ code to be executed if we are running 2.3.5 or more recent. , \\ compatibility code ); @eprog\noindent On a number of different machines, \kbd{version()} could return either of \bprog %1 = [2, 3, 4] \\ released version, stable branch %1 = [2, 4, 3] \\ released version, testing branch %1 = [2, 6, 1, 15174, ""505ab9b"] \\ development @eprog In particular, if you are only working with released versions, the first line of the gp introductory message can be emulated by \bprog [M,m,p] = version(); printf("GP/PARI CALCULATOR Version %s.%s.%s", M,m,p); @eprog\noindent If you \emph{are} working with many development versions of PARI/GP, the 4th and/or 5th components can be profitably included in the name of your logfiles, for instance. \misctitle{Technical note} For development versions obtained via \kbd{git}, the 4th and 5th components are liable to change eventually, but we document their current meaning for completeness. The 4th component counts the number of reachable commits in the branch (analogous to \kbd{svn}'s revision number), and the 5th is the \kbd{git} commit hash. In particular, \kbd{lex} comparison still orders correctly development versions with respect to each others or to released versions (provided we stay within a given branch, e.g. \kbd{master})! pari-2.17.2/src/functions/programming/mapput0000644000175000017500000000071414567450071017551 0ustar billbillFunction: mapput Section: programming/specific C-Name: mapput Prototype: vWGG Help: mapput(~M,x,y): associates x to y in the map M. Doc: Associates $x$ to $y$ in the map $M$. The value $y$ can be retrieved with \tet{mapget}. \bprog ? M = Map(); ? mapput(~M, "foo", 23); ? mapput(~M, 7718, "bill"); ? mapget(M, "foo") %4 = 23 ? mapget(M, 7718) %5 = "bill" ? Vec(M) \\ keys %6 = [7718, "foo"] ? Mat(M) %7 = [ 7718 "bill"] ["foo" 23] @eprog pari-2.17.2/src/functions/programming/alias0000644000175000017500000000345714567450071017343 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 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.17.2/src/functions/programming/dbg_down0000644000175000017500000000267714676526175020052 0ustar billbillFunction: dbg_down Class: gp Section: programming/control C-Name: dbg_down Prototype: vD1,L, Help: dbg_down({n=1}): (break loop) go down n frames. Cancel a previous dbg_up. Doc: (In the break loop) go down $n$ frames. This allows to cancel a previous call to \kbd{dbg\_up}. \bprog ? x = 0; ? g(x) = x-3; ? f(x) = 1 / g(x+1); ? for (x = 1, 5, f(x+1)) *** at top-level: for(x=1,5,f(x+1)) *** ^------- *** in function f: 1/g(x+1) *** ^------- *** _/_: impossible inverse in gdiv: 0. *** Break loop: type 'break' to go back to GP prompt break> dbg_up(3) \\ go up 3 frames *** at top-level: for(x=1,5,f(x+1)) *** ^----------------- break> x 0 break> dbg_down() *** at top-level: for(x=1,5,f(x+1)) *** ^------- break> x 1 break> dbg_down() *** at top-level: for(x=1,5,f(x+1)) *** ^------- break> x 1 break> dbg_down() *** at top-level: for(x=1,5,f(x+1)) *** ^------- *** in function f: 1/g(x+1) *** ^------- break> x 2 @eprog\noindent The above example shows that the notion of GP frame is finer than the usual stack of function calls (as given for instance by the GDB \kbd{backtrace} command): GP frames are attached to variable scopes and there are frames attached to control flow instructions such as a \kbd{for} loop above. pari-2.17.2/src/functions/programming/if0000644000175000017500000000452714567450071016647 0ustar billbillFunction: if Section: programming/control C-Name: ifpari Prototype: GDEDE Help: if(a,{seq1},{seq2}): if a is nonzero, seq1 is evaluated, otherwise seq2. seq1 and seq2 are optional, and if seq2 is omitted, the preceding comma can be omitted also. Doc: evaluates the expression sequence \var{seq1} if $a$ is nonzero, otherwise the expression \var{seq2}. Of course, \var{seq1} or \var{seq2} may be empty: \kbd{if ($a$,\var{seq})} evaluates \var{seq} if $a$ is not equal to zero (you don't have to write the second comma), and does nothing otherwise, \kbd{if ($a$,,\var{seq})} evaluates \var{seq} if $a$ is equal to zero, and does nothing otherwise. You could get the same result using the \kbd{!} (\kbd{not}) operator: \kbd{if (!$a$,\var{seq})}. The value of an \kbd{if} statement is the value of the branch that gets evaluated: for instance \bprog x = if(n % 4 == 1, y, z); @eprog\noindent sets $x$ to $y$ if $n$ is $1$ modulo $4$, and to $z$ otherwise. Successive 'else' blocks can be abbreviated in a single compound \kbd{if} as follows: \bprog if (test1, seq1, test2, seq2, ... testn, seqn, seqdefault); @eprog\noindent is equivalent to \bprog if (test1, seq1 , if (test2, seq2 , ... if (testn, seqn, seqdefault)...)); @eprog For instance, this allows to write traditional switch / case constructions: \bprog if (x == 0, do0(), x == 1, do1(), x == 2, do2(), dodefault()); @eprog \misctitle{Remark} The boolean operators \kbd{\&\&} and \kbd{||} are evaluated according to operator precedence as explained in \secref{se:operators}, but, contrary to other operators, the evaluation of the arguments is stopped as soon as the final truth value has been determined. For instance \bprog if (x != 0 && f(1/x), ...) @eprog \noindent is a perfectly safe statement. \misctitle{Remark} Functions such as \kbd{break} and \kbd{next} operate on \emph{loops}, such as \kbd{for$xxx$}, \kbd{while}, \kbd{until}. The \kbd{if} statement is \emph{not} a loop. (Obviously!) Function: _void_if C-Name: ifpari_void Section: programming/internals Prototype: vGDIDI Help: internal variant of if() that does not return a value. Function: _multi_if C-Name: ifpari_multi Section: programming/internals Prototype: GE* Help: internal variant of if() that allows more than 3 arguments. pari-2.17.2/src/functions/programming/getheap0000644000175000017500000000057114567450071017661 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 (in long words). Doc: returns a two-component row vector giving the number of objects on the heap and the amount of memory they occupy in long words. Useful mainly for debugging purposes. pari-2.17.2/src/functions/programming/forvec0000644000175000017500000000560114676526175017541 0ustar billbillFunction: _forvec_init Class: gp2c_internal Help: Initializes parameters for forvec. Description: (forvec, gen, ?small):void forvec_init(&$1, $2, $3) Function: _forvec_next Class: gp2c_internal Help: Initializes parameters for forvec. Description: (forvec):vec forvec_next(&$1) Function: forvec Section: programming/control C-Name: forvec Prototype: vV=GID0,L, Iterator: (gen,gen,?small) (forvec, _forvec_init, _forvec_next) Help: forvec(X=v,seq,{flag=0}): v being a 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. As a shortcut, v being a vector of nonnegative integers allows to loop over representatives of Z^n/vZ^n. Doc: Let $v$ be an $n$-component vector (where $n$ is arbitrary) of two-component vectors $[a_{i},b_{i}]$ for $1\le i\le n$, where all entries $a_{i}$, $b_{i}$ are real numbers. This routine lets $X$ vary over the $n$-dimensional box given by $v$ with unit steps: $X$ is an $n$-dimensional vector whose $i$-th entry $X[i]$ runs through $a_{i}, a_{i}+1, a_{i}+2, \dots $ stopping with the first value greater than $b_{i}$ (note that neither $a_{i}$ nor $b_{i} - a_{i}$ are required to be integers). The values of $X$ are ordered lexicographically, like embedded \kbd{for} loops, and the expression \var{seq} is evaluated with the successive values of $X$. The type of $X$ is the same as the type of $v$: \typ{VEC} or \typ{COL}. If $\fl=1$, generate only nondecreasing vectors $X$, and if $\fl=2$, generate only strictly increasing vectors $X$. \bprog ? forvec (X=[[0,1],[-1,1]], print(X)); [0, -1] [0, 0] [0, 1] [1, -1] [1, 0] [1, 1] ? forvec (X=[[0,1],[-1,1]], print(X), 1); [0, 0] [0, 1] [1, 1] ? forvec (X=[[0,1],[-1,1]], print(X), 2) [0, 1] @eprog As a shortcut, a vector of the form $v=[[0,c_{1}-1],\dots [0,c_{n}-1]]$ can be abbreviated as $v=[c_{1},\dots c_{n}]$ and $\fl$ is ignored in this case. More generally, if $v$ is a vector of nonnegative integers $c_{i}$ the loop runs over representatives of $\Z^{n}/v\Z^{n}$; and $\fl$ is again ignored. The vector $v$ may contain zero entries, in which case the loop spans an infinite lattice. The values are ordered lexicographically, graded by increasing $L_{1}$-norm on free ($c_{i}=0$) components. This allows to iterate over elements of abelian groups using their \kbd{.cyc} vector. \bprog ? forvec (X=[2,3], print(X)); [0, 0] [0, 1] [0, 2] [1, 0] [1, 1] [1, 2] ? my(i);forvec (X=[0,0], print(X); if (i++ > 10, break)); [0, 0] [-1, 0] [0, -1] [0, 1] [1, 0] [-2, 0] [-1, -1] [-1, 1] [0, -2] [0, 2] [1, -1] ? zn = znstar(36,1); ? forvec (chi = zn.cyc, if (chareval(zn,chi,5) == 5/6, print(chi))); [1, 0] [1, 1] ? bnrchar(zn, [5], [5/6]) \\ much more efficient in general %5 = [[1, 1], [1, 0]] @eprog pari-2.17.2/src/functions/programming/writetex0000644000175000017500000000057614676526175020136 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. See \tet{strtex} for details: this function is essentially equivalent to calling \kbd{strtex} on remaining arguments and writing them to file. pari-2.17.2/src/functions/programming/fold0000644000175000017500000000132114676526175017174 0ustar billbillFunction: fold Section: programming/specific C-Name: fold0 Prototype: GG Help: fold(f,A): return f(...f(f(A[1],A[2]),A[3]),...,A[#A]). Wrapper: (GG) Description: (closure,gen):gen genfold(${1 cookie}, ${1 wrapper}, $2) Doc: Apply the \typ{CLOSURE} \kbd{f} of arity $2$ to the entries of \kbd{A}, in order to return \kbd{f(\dots f(f(A[1],A[2]),A[3])\dots ,A[\#A])}. \bprog ? fold((x,y)->x*y, [1,2,3,4]) %1 = 24 ? fold((x,y)->[x,y], [1,2,3,4]) %2 = [[[1, 2], 3], 4] ? fold((x,f)->f(x), [2,sqr,sqr,sqr]) %3 = 256 ? fold((x,y)->(x+y)/(1-x*y),[1..5]) %4 = -9/19 ? bestappr(tan(sum(i=1,5,atan(i)))) %5 = -9/19 @eprog Variant: Also available is \fun{GEN}{genfold}{void *E, GEN (*fun)(void*,GEN, GEN), GEN A}. pari-2.17.2/src/functions/programming/fileread0000644000175000017500000000214614567450071020017 0ustar billbillFunction: fileread Section: programming/specific C-Name: gp_fileread Prototype: L Help: fileread(n): read a logical line from the file attached to the descriptor n, opened for reading with fileopen. Return 0 at end of file. Doc: read a logical line from the file attached to the descriptor $n$, opened for reading with \kbd{fileopen}. Return 0 at end of file. A logical line is a full command as it is prepared by gp's preprocessor (skipping blanks and comments or assembling multiline commands between braces) before being fed to the interpreter. The function \kbd{filereadstr} would read a \emph{raw} line exactly as input, up to the next carriage return \kbd{\bs n}. Compare raw lines \bprog ? n = fileopen("examples/bench.gp"); ? while(l = filereadstr(n), print(l)); { u=v=p=q=1; for (k=1, 2000, [u,v] = [v,u+v]; p *= v; q = lcm(q,v); if (k%50 == 0, print(k, " ", log(p)/log(q)) ) ) } @eprog\noindent and logical lines \bprog ? n = fileopen("examples/bench.gp"); ? while(l = fileread(n), print(l)); u=v=p=q=1;for(k=1,2000,[u,v]=[v,u+v];p*=v;q=lcm(q,v);[...] @eprog pari-2.17.2/src/functions/programming/getrand0000644000175000017500000000067213637407207017672 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.17.2/src/functions/programming/parforprime0000644000175000017500000000333414760123736020572 0ustar billbillFunction: _parforprime_init Class: gp2c_internal Help: Initializes parameters for parforprime. Description: (parforprime, gen, ?gen, gen):void parforprime_init(&$1, $2, $3, $4) Function: _parforprime_next Class: gp2c_internal Help: Next value for parforprime Description: (parforprime):gen parforprime_next(&$1) Function: _parforprime_stop Class: gp2c_internal Help: Stop function for parforprime. Description: (parforprime):void parforprime_stop(&$1) Function: parforprime Section: programming/parallel C-Name: parforprime0 Prototype: vV=GDGJDVDI Iterator: (gen,gen,?gen,closure,?notype) (parforprime, _parforprime_init, _parforprime_next, _parforprime_stop) Help: parforprime(p=a,{b},expr1,{r},{expr2}): evaluates the expression expr1 in parallel for all primes p between a and b (if b is set to +oo, the loop will not stop), resulting in as many values; if the formal variables r and expr2 are present, evaluate sequentially expr2, in which r has been replaced by the different results obtained for expr1 and p with the corresponding arguments. Doc: behaves exactly as \kbd{parfor}, but loops only over prime values $p$. Precisely, the functions evaluates in parallel the expression \kbd{expr1} in the formal argument $p$ running through the primes from $a$ to $b$. If $b$ is set to \kbd{+oo}, the loop runs indefinitely. If $r$ and \kbd{expr2} are present, the expression \kbd{expr2} in the formal variables $r$ and $p$ is evaluated with $r$ running through all the different results obtained for \kbd{expr1} and $p$ takes the corresponding argument. It is allowed fo \kbd{expr2} to exit the loop using \kbd{break}/\kbd{next}/\kbd{return}; see the remarks in the documentation of \kbd{parfor} for details. %\syn{NO} pari-2.17.2/src/functions/programming/listcreate0000644000175000017500000000062014760123736020376 0ustar billbillFunction: listcreate Section: programming/specific C-Name: listcreate_gp Prototype: D0,L, Obsolete: 2007-08-10 Help: listcreate({n}): this function is obsolete, use List(). Description: (?gen):list mklist() Doc: This function is obsolete, use \kbd{List}. Creates an empty list. This routine used to have a mandatory argument, which is now ignored (for backward compatibility). % \syn{NO} pari-2.17.2/src/functions/programming/call0000644000175000017500000000306714676526175017174 0ustar billbillFunction: call Section: programming/specific C-Name: call0 Prototype: GG Help: call(f,A): A being a vector, evaluates f(A[1],...,A[#A]). Doc: $A=[a_{1},\dots, a_{n}]$ being a vector and $f$ being a function, returns the evaluation of $f(a_{1},\dots,a_{n})$. $f$ can also be the name of a built-in GP function. If $\# A =1$, \tet{call}($f,A$) = \tet{apply}($f,A$)[1]. If $f$ is variadic (has a variable number of arguments), then the variadic arguments are grouped in a vector in the last component of $A$. This function is useful \item when writing a variadic function, to call another one: \bprog fprintf(file,format,args[..]) = write(file, call(strprintf,[format,args])) @eprog \item when dealing with function arguments with unspecified arity. The function below implements a global memoization interface: \bprog memo=Map(); memoize(f,A[..])= { my(res); if(!mapisdefined(memo, [f,A], &res), res = call(f,A); mapput(memo,[f,A],res)); res; } @eprog for example: \bprog ? memoize(factor,2^128+1) %3 = [59649589127497217,1;5704689200685129054721,1] ? ## *** last result computed in 76 ms. ? memoize(factor,2^128+1) %4 = [59649589127497217,1;5704689200685129054721,1] ? ## *** last result computed in 0 ms. ? memoize(ffinit,3,3) %5 = Mod(1,3)*x^3+Mod(1,3)*x^2+Mod(1,3)*x+Mod(2,3) ? fibo(n)=if(n==0,0,n==1,1,memoize(fibo,n-2)+memoize(fibo,n-1)); ? fibo(100) %7 = 354224848179261915075 @eprog \item to call operators through their internal names without using \kbd{alias} \bprog matnbelts(M) = call("_*_",matsize(M)) @eprog pari-2.17.2/src/functions/programming/parforeach0000644000175000017500000000261514760123736020357 0ustar billbillFunction: _parforeach_init Class: gp2c_internal Help: Initializes parameters for parforeach. Description: (parforeach,gen,gen):void parforeach_init(&$1, $2, $3) Function: _parforeach_next Class: gp2c_internal Help: Next value for parforeach. Description: (parforeach):gen parforeach_next(&$1) Function: _parforeach_stop Class: gp2c_internal Help: Stop function for parforeach. Description: (parforeach):void parforeach_stop(&$1) Function: parforeach Section: programming/parallel C-Name: parforeach0 Prototype: vGVJDVDI Iterator: (gen,gen,closure,?notype) (parforeach, _parforeach_init, _parforeach_next, _parforeach_stop) Help: parforeach(V,x,expr1,{r},{expr2}): evaluates in parallel the expression expr1 for all components x of V. If the formal variables r and expr2 are present, evaluate sequentially expr2, in which x and r are replaced by the successive arguments and corresponding values. Doc: evaluates in parallel the expression \kbd{expr1} in the formal argument $x$, where $x$ runs through all components of $V$. If $r$ and \kbd{expr2} are present, evaluate sequentially the expression \kbd{expr2}, in which the formal variables $x$ and $r$ are replaced by the successive arguments and corresponding values. The sequential evaluation ordering is not specified: \bprog ? parforeach([50..100], x,isprime(x), r, if(r,print(x))) 53 67 71 79 83 89 97 73 59 61 @eprog %\syn{NO} pari-2.17.2/src/functions/programming/strexpand0000644000175000017500000000160014676526175020260 0ustar billbillFunction: strexpand Section: programming/specific C-Name: strexpand Prototype: s* Help: strexpand({x}*): concatenates its (string) arguments 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" ? module = "aprcl"; n = 10; ? strexpand("$HOME/doc/", module, n, ".tex") %3 = "/home/pari/doc/aprcl10.tex" @eprog The individual arguments are read in string context, see \secref{se:strings}. Function: Strexpand Section: programming/specific C-Name: strexpand Prototype: s* Obsolete: 2018-10-01 Help: Strexpand({x}*): deprecated alias for strexpand Doc: deprecated alias for strexpand pari-2.17.2/src/functions/programming/foreach0000644000175000017500000000063214567450071017651 0ustar billbillFunction: foreach Section: programming/control C-Name: foreachpari Prototype: vGVI Help: foreach(V,X,seq): the sequence is evaluated, X running over the components of V. Doc: evaluates \var{seq}, where the formal variable $X$ ranges through the components of $V$ (\typ{VEC}, \typ{COL}, \typ{LIST} or \typ{MAT}). A matrix argument is interpreted as a vector containing column vectors, as in \kbd{Vec}$(V)$. pari-2.17.2/src/functions/programming/strtex0000644000175000017500000000323414676526175017606 0ustar billbillFunction: strtex Section: programming/specific C-Name: strtex Prototype: s* Help: strtex({x}*): translates its (string) arguments to TeX format and returns the resulting string. Doc: translates its arguments to TeX format, and concatenates the results into a single character string (type \typ{STR}, the empty string if $x$ is omitted). The individual arguments are read in string context, see \secref{se:strings}. \bprog ? v = [1, 2, 3] %1 [1, 2, 3] ? strtex(v) %2 = "\\pmatrix{ 1&2&3\\cr}\n" @eprog \misctitle{\TeX-nical notes} The TeX output engine was originally written for plain TeX and designed for maximal portability. Unfortunately later \kbd{LaTeX} packages have obsoleted valid \TeX\ primitives, leading us to replace TeX's \kbd{\bs{}over} by LaTeX's \kbd{\bs{}frac} in PARI's TeX output. We have decided not to update further our TeX markup and let the users of various LaTeX engines customize their preambles. The following documents the precise changes you may need to include in your style files to incorporate PARI TeX output verbatim: \item if you enabled bit 4 in \tet{TeXstyle} default, you must define \kbd{\bs{}PARIbreak}; see \kbd{??TeXstyle}; \item if you use plain TeX only: you must define \kbd{\bs{}frac} as follows \bprog \def\frac#1#2{{#1\over#2}} @eprog \item if you use LaTeX and \kbd{amsmath}, \kbd{\bs{}pmatrix} is obsoleted in favor of the \kbd{pmatrix} environment; see \kbd{examples/parigp.sty} for how to re-enable the deprecated construct. Function: Strtex Section: programming/specific C-Name: strtex Prototype: s* Obsolete: 2018-10-01 Help: Strtex({x}*): deprecated alias for strtex. Doc: deprecated alias for strtex. pari-2.17.2/src/functions/programming/arity0000644000175000017500000000063614567450071017376 0ustar billbillFunction: arity Section: programming/specific C-Name: arity0 Prototype: G Help: arity(C): return the arity of the closure C. Doc: return the arity of the closure $C$, i.e., the number of its arguments. \bprog ? f1(x,y=0)=x+y; ? arity(f1) %1 = 2 ? f2(t,s[..])=print(t,":",s); ? arity(f2) %2 = 2 @eprog\noindent Note that a variadic argument, such as $s$ in \kbd{f2} above, is counted as a single argument. pari-2.17.2/src/functions/graphic/0000755000175000017500000000000014760315601015403 5ustar billbillpari-2.17.2/src/functions/graphic/plothraw0000644000175000017500000000127314676526175017211 0ustar billbillFunction: plothraw Section: graphic C-Name: plothraw Prototype: GGD0,L, Help: plothraw(X,Y,{flag=0}): plot in high resolution points whose x (resp. y) coordinates are in X (resp. Y). If flag is 1, join points, other nonzero flags should be combinations of bits 8,16,32,64,128,256 meaning the same as for ploth(). Doc: given $X$ and $Y$ two vectors of equal length, plots (in high precision) the points whose $(x,y)$-coordinates are given in $X$ and $Y$. Automatic positioning and scaling is done, but with the same scaling factor on $x$ and $y$. If $\fl$ is 1, join points, other nonzero flags toggle display options and should be combinations of bits $2^{k}$, $k \geq 3$ as in \kbd{ploth}. pari-2.17.2/src/functions/graphic/HEADER0000644000175000017500000000761014676526175016302 0ustar billbillFunction: _header_graphic Class: header Section: graphic Doc: \section{Plotting functions} Although plotting is not even a side purpose of PARI, a number of plotting functions are provided. 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 attached 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 attached 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 (including Openwindows and Motif), Windows's Graphical Device Interface, and the FLTK graphical libraries and one may even write the graphical objects to a PostScript or SVG file and use an external viewer to open it. 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 all memory unrelated to the graphics engine 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. \subsec{Functions for PostScript or SVG output} in the same way that \kbd{printtex} allows you to have a \TeX\ output corresponding to printed results, the functions \kbd{plotexport}, \kbd{plothexport} and \kbd{plothrawexport} convert a plot to a character string in either \tet{PostScript} or \tet{Scalable Vector Graphics} format. This string can then be written to a file in the customary way, using \kbd{write}. These export routines are available even if no Graphic Library is. \smallskip pari-2.17.2/src/functions/graphic/plotmove0000644000175000017500000000032114567450071017175 0ustar billbillFunction: plotmove Section: graphic C-Name: plotmove 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.17.2/src/functions/graphic/plotpointtype0000644000175000017500000000070614567450071020271 0ustar billbillFunction: plotpointtype Section: graphic C-Name: plotpointtype Prototype: vLL Obsolete: 2007-05-11 Help: plotpointtype(w,type): this function is obsolete; no graphing engine implement this functionality. Doc: This function is obsolete and currently a no-op. 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. pari-2.17.2/src/functions/graphic/plotinit0000644000175000017500000000234614567450071017203 0ustar billbillFunction: plotinit Section: graphic C-Name: plotinit 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.17.2/src/functions/graphic/psplothraw0000644000175000017500000000035514567450071017542 0ustar billbillFunction: psplothraw Section: graphic C-Name: psplothraw Prototype: GGD0,L, Obsolete: 2018-02-01 Help: psplothraw(listx,listy,{flag=0}): obsolete function. Doc: This function is obsolete, use plothrawexport and write the result to file. pari-2.17.2/src/functions/graphic/plotrecth0000644000175000017500000000130714760123736017341 0ustar billbillFunction: plotrecth Section: graphic C-Name: plotrecth0 Wrapper: (,,,G) Description: (small,gen,gen,gen,?small,?small):gen:prec plotrecth(${4 cookie}, ${4 wrapper}, $1, $2, $3, $5, $6, $prec) Prototype: LV=GGED0,M,D0,L,p\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. %\syn{NO} pari-2.17.2/src/functions/graphic/plothsizes0000644000175000017500000000166414567450071017547 0ustar billbillFunction: plothsizes Section: graphic C-Name: plothsizes Prototype: D0,L, Help: plothsizes({flag=0}): returns array of 8 elements: terminal width and height, sizes for ticks in horizontal and vertical directions, width and height of characters, width and height of display (if applicable). If flag=0, sizes of ticks and characters are in pixels, otherwise are fractions of the terminal size. Doc: return data corresponding to the output window in the form of a 8-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, width and height of display, if applicable. If display has no sense, e.g. for svg plots or postscript plots, then width and height of display are set to 0. If $\fl = 0$, sizes of ticks and characters are in pixels, otherwise are fractions of the screen size pari-2.17.2/src/functions/graphic/plothexport0000644000175000017500000000220414676526175017734 0ustar billbillFunction: plothexport Section: graphic C-Name: plothexport0 Wrapper: (,,,G) Description: (gen,gen,gen,gen,?small,?small):gen:prec plothexport($1, ${4 cookie}, ${4 wrapper}, $2, $3, $5, $6, $prec) Prototype: GV=GGED0,M,D0,L,p\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: plothexport(fmt,X=a,b,expr,{flags=0},{n=0}): plot of expression expr, X goes from a to b in high resolution, returning the resulting picture as a character string which can then be written to a file. Doc: plot of expression \var{expr}, $X$ goes from $a$ to $b$ in high resolution, returning the resulting picture as a character string which can then be written to a file. The format \kbd{fmt} is either \kbd{"ps"} (PostScript output) or \kbd{"svg"} (Scalable Vector Graphics). All other parameters and flags are as in \kbd{ploth}. \bprog ? s = plothexport("svg", x=1,10, x^2+3); ? write("graph.svg", s); @eprog \synt{plothexport}{GEN fmt, void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, long flags, long n, long prec}, pari-2.17.2/src/functions/graphic/plotcopy0000644000175000017500000000154114676526175017220 0ustar billbillFunction: plotcopy Section: graphic C-Name: plotcopy 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 $\fl$'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 $\fl$ vanish, otherwise of: 2: southwest, 4: southeast, 6: northeast corners. pari-2.17.2/src/functions/graphic/plotpoints0000644000175000017500000000223514567450071017551 0ustar billbillFunction: plotpoints Section: graphic C-Name: plotpoints 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)$. If you draw few points in the rectwindow, they will be hard to see; in this case, you can use filled boxes instead. Compare: \bprog ? plotinit(0, 100,100); plotpoints(0, 50,50); ? plotdraw(0) ? plotinit(1, 100,100); plotmove(1,48,48); plotrbox(1, 4,4, 1); ? plotdraw(1) @eprog pari-2.17.2/src/functions/graphic/plotrmove0000644000175000017500000000057514567450071017372 0ustar billbillFunction: plotrmove Section: graphic C-Name: plotrmove 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.17.2/src/functions/graphic/plotarc0000644000175000017500000000125414676526175017014 0ustar billbillFunction: plotarc Section: graphic C-Name: plotarc Prototype: vLGGD0,L, Help: plotarc(w,x2,y2,{filled=0}): if the cursor is at position (x1,y1), draws the ellipse that fits inside the box with diagonal (x1,y1) and (x2,y2) in rectwindow w (cursor does not move). If filled=1, fill the ellipse Doc: let $(x1,y1)$ be the current position of the virtual cursor. Draws in the rectwindow $w$ the outline of the ellipse that fits inside the box such that the points $(x1,y1)$ and $(x2,y2)$ are opposite corners. The virtual cursor does \emph{not} move. If $\var{filled}=1$, fills the ellipse. \bprog ? plotinit(1);plotmove(1,0,0); ? plotarc(1,50,50); plotdraw([1,100,100]); @eprog pari-2.17.2/src/functions/graphic/plotlinetype0000644000175000017500000000071714567450071020071 0ustar billbillFunction: plotlinetype Section: graphic C-Name: plotlinetype Prototype: vLL Obsolete: 2007-05-11 Help: plotlinetype(w,type): this function is obsolete; no graphing engine implement this functionality. Doc: This function is obsolete and currently a no-op. 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. pari-2.17.2/src/functions/graphic/plotscale0000644000175000017500000000132614567450071017324 0ustar billbillFunction: plotscale Section: graphic C-Name: plotscale 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=}, \kbd{>}, are available in GP. The result is 1 if the comparison is true, 0 if it is false. These operators allow to compare integers (\typ{INT}), rational (\typ{FRAC}) or real (\typ{REAL}) numbers, real quadratic numbers (\typ{QUAD} of positive discriminant) and infinity (\kbd{oo}, \typ{INFINITY}). By extension, two character strings (\typ{STR}) are compared using the standard lexicographic order. Comparing a string to an object of a different type raises an exception. See also the \tet{cmp} universal comparison function. \subsec{Equality} Two operators allow to test for equality: \kbd{==} (equality up to type coercion) and \kbd{===} (identity). The result is $1$ if equality is decided, else $0$. The operator \kbd{===} is strict: objects of different type or length are never identical, polynomials in different variables are never identical, even if constant. On the contrary, \kbd{==} is very liberal: $a~\kbd{==}~b$ decides whether there is a natural map sending $a$ to the domain of $b$ or sending $b$ to the domain of $a$, such that the comparison makes sense and equality holds. For instance \bprog ? 4 == Mod(1,3) \\ equal %1 = 1 ? 4 === Mod(1,3) \\ but not identical %2 = 0 ? 'x == 'y \\ not equal (nonconstant and different variables) %3 = 0 ? Pol(0,'x) == Pol(0,'y) \\ equal (constant: ignore variable) %4 = 1 ? Pol(0,'x) === Pol(0,'y) \\ not identical %5 = 0 ? 0 == Pol(0) \\ equal (not identical) %6 = 1 ? [0] == 0 \\ equal (not identical) %7 = 1 ? [0, 0] == 0 \\ equal (not identical) %8 = 1 ? [0] == [0,0] \\ not equal %9 = 0 @eprog\noindent In particular \kbd{==} is not transitive in general. The operator \kbd{===} is transitive. The \kbd{==} operator allows two equivalent negated forms: \kbd{!=} or \kbd{<>}; there is no negated form for \kbd{===}. Do not mistake \kbd{=} for \kbd{==}: the former is the assignment statement. \subseckbd{+$/$-} The expressions \kbd{+}$x$ and \kbd{-}$x$ refer to monadic operators: the first does nothing, the second negates $x$. The library syntax is \fun{GEN}{gneg}{GEN x} for \kbd{-}$x$. \subseckbd{+} The expression $x$ \kbd{+} $y$ is the \idx{sum} of $x$ and $y$. Addition between a scalar type $x$ and a \typ{COL} or \typ{MAT} $y$ returns respectively $[y[1] + x, y[2],\dots]$ and $y + x \text{Id}$. Other additions between a scalar type and a vector or a matrix, or between vector/matrices of incompatible sizes are forbidden. The library syntax is \fun{GEN}{gadd}{GEN x, GEN y}. \subseckbd{-} The expression $x$ \kbd{-} $y$ is the \idx{difference} of $x$ and $y$. Subtraction between a scalar type $x$ and a \typ{COL} or \typ{MAT} $y$ returns respectively $[y[1] - x, y[2],\dots]$ and $y - x \text{Id}$. Other subtractions between a scalar type and a vector or a matrix, or between vector/matrices of incompatible sizes are forbidden. The library syntax is \fun{GEN}{gsub}{GEN x, GEN y} for $x$ \kbd{-} $y$. \subseckbd{*} The expression $x$ \kbd{*} $y$ is the \idx{product} of $x$ and $y$. Among the prominent impossibilities are multiplication between vector/matrices of incompatible sizes, between a \typ{INTMOD} or \typ{PADIC}. Restricted to scalars, \kbd{*} is commutative; because of vector and matrix operations, it is not commutative in general. Multiplication between two \typ{VEC}s or two \typ{COL}s is not allowed; to take the \idx{scalar product} of two vectors of the same length, transpose one of the vectors (using the operator \kbd{\til} or the function \kbd{mattranspose}, see \secref{se:linear_algebra}) and multiply a row 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 nonintegral real number, \kbd{$x$\%$y$} is defined as \kbd{$x$ - ($x$\bs$y$)*$y$}. Otherwise, if $y$ is an integer, this is the smallest nonnegative 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{!} The expression \kbd{$n!$} is the factorial of the non-negative integer $n$. The library syntax is \fun{GEN}{mpfact}{long n} \subseckbd{\#} The expression \kbd{$n\#$} is the primorial of the non-negative integer $n$, that is the product of all prime numbers less than or equal to $x$. The library syntax is \fun{GEN}{mpprimorial}{long n} \subseckbd{op=} When \kbd{op} is a binary arithmetic operator among \kbd{+}, \kbd{-}, \kbd{*}, \kbd{\%}, \kbd{/}, \kbd{\bs} or \kbd{\bs/}, the construct $x$~\kbd{op=}~$y$ is a shortcut for $x$~\kbd{=}~$x\ \kbd{op}\ y$. \bprog ? v[1] += 10 \\ increment v[1] by 10 ? a /= 2 \\ divide a by 2 @eprog \subseckbd{++} \kbd{$x$++} is a shortcut for \kbd{$x$ = $x$ + 1} and for \kbd{$x$ += 1}. \subseckbd{--} \kbd{$x$--} is a shortcut for \kbd{$x$ = $x$ - 1} and for \kbd{$x$ -= 1}. \subseckbd{\pow} The expression $x\hbox{\kbd{\pow}}n$ is \idx{powering}. \item If the exponent $n$ is an integer, then exact operations are performed using binary (left-shift) powering techniques. By definition, $x^{0}$ is (an empty product interpreted as) an exact $1$ in the underlying prime ring: \bprog ? 0.0 ^ 0 %1 = 1 ? (1 + O(2^3)) ^ 0 %2 = 1 ? (1 + O(x)) ^ 0 %3 = 1 ? Mod(2,4)^0 %4 = Mod(1,4) ? Mod(x,x^2)^0 %5 = Mod(1, x^2) @eprog\noindent If $x$ is a $p$-adic number, its precision will increase if $v_{p}(n) > 0$ and $n \neq 0$. Powering a binary quadratic form (type \typ{QFB}) returns a representative of the class, which is reduced if the input was. (In particular, \kbd{x \pow 1} returns $x$ itself, whether it is reduced or not.) PARI rewrites the multiplication $x * x$ of two \emph{identical} objects as $x^{2}$. Here, identical means the operands are reference the same chunk of memory; no equality test is performed. This is no longer true when more than two arguments are involved. \bprog ? a = 1 + O(2); b = a; ? a * a \\ = a^2, precision increases %2 = 1 + O(2^3) ? a * b \\ not rewritten as a^2 %3 = 1 + O(2) ? a*a*a \\ not rewritten as a^3 %4 = 1 + O(2) @eprog \item If the exponent is a rational number $p/q$ the behaviour depends on~$x$. If $x$ is a complex number, return $\exp(n \log x)$ (principal branch), in an exact form if possible: \bprog ? 4^(1/2) \\ 4 being a square, this is exact %1 = 2 ? 2^(1/2) \\ now inexact %2 = 1.4142135623730950488016887242096980786 ? (-1/4)^(1/2) \\ exact again %3 = 1/2*I ? (-1)^(1/3) %4 = 0.500...+ 0.866...*I @eprog\noindent Note that even though $-1$ is an exact cube root of $-1$, it is not $\exp(\log(-1)/3)$; the latter is returned. Otherwise return a solution $y$ of $y^{q} = x^{p}$ if it exists; beware that this is defined up to $q$-th roots of 1 in the base field. Intmods modulo composite numbers are not supported. \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(1,4)^(1/2) *** at top-level: Mod(1,4)^(1/2) *** ^------ *** _^_: not a prime number in gpow: 4. @eprog \item If the exponent is a negative integer or rational number, an \idx{inverse} must be computed. For noninvertible \typ{INTMOD} $x$, this will fail and (for $n$ an integer) implicitly exhibit a 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 noninvertible \typ{POLMOD} $x$, the behavior is the same: \bprog ? Mod(x^2, x^3-x)^(-1) *** at top-level: Mod(x^2,x^3-x)^(-1) *** ^----- *** _^_: impossible inverse in RgXQ_inv: Mod(x^2, x^3 - x). @eprog\noindent Note that the underlying algorihm (subresultant) assumes that the base ring is a domain: \bprog ? a = Mod(3*y^3+1, 4); b = y^6+y^5+y^4+y^3+y^2+y+1; c = Mod(a,b); ? c^(-1) *** at top-level: Mod(a,b)^(-1) *** ^----- *** _^_: impossible inverse modulo: Mod(2, 4). @eprog\noindent In fact $c$ is invertible, but $\Z/4\Z$ is not a domain and the algorithm fails. It is possible for the algorithm to succeed in such situations and any returned result will be correct, but chances are that an error will occur first. In this specific case, one should work with $2$-adics. In general, one can also try the following approach \bprog ? inversemod(a, b) = { my(m, v = variable(b)); m = polsylvestermatrix(polrecip(a), polrecip(b)); m = matinverseimage(m, matid(#m)[,1]); Polrev(m[1..poldegree(b)], v); } ? 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 \kbd{matinverseimage} must also invert pivots. See \secref{se:linear_algebra}. For a \typ{MAT} $x$, the matrix is expected to be square and invertible, except in the special case \kbd{x\pow(-1)} which returns a left inverse if one exists (rectangular $x$ with full column rank). \bprog ? x = Mat([1;2]) %1 = [1] [2] ? x^(-1) %2 = [1 0] @eprog \item Finally, if the exponent $n$ is not an rational number, powering is treated as the transcendental function $\exp(n\log x)$, although it will be more precise than the latter when $n$ and $x$ are exact: \bprog ? s = 1/2 + 10^14 * I ? localprec(200); z = 2^s \\ for reference ? exponent(2^s - z) %3 = -127 \\ perfect ? exponent(exp(s * log(2)) - z) %4 = -84 \\ not so good @eprog\noindent The second computation is less precise because $\log(2)$ is first computed to $38$ decimal digits, then multiplied by $s$, which has a huge imaginary part amplifying the error. In this case, $x \mapsto x^{n}$ is treated as a transcendental function and and in particular acts componentwise on vector or matrices, even square matrices ! (See \secref{se:trans}.) If $x$ is $0$ and $n$ is an inexact $0$, this will raise an exception: \bprog ? 4 ^ 1.0 %1 = 4.0000000000000000000000000000000000000 ? 0^ 0.0 *** at top-level: 0^0.0 *** ^---- *** _^_: domain error in gpow(0,n): n <= 0 @eprog The library syntax is \fun{GEN}{gpow}{GEN x, GEN n, long prec} for $x\hbox{\kbd{\pow}}n$. pari-2.17.2/src/functions/operators/vecmin0000644000175000017500000000221414676526175017227 0ustar billbillFunction: vecmin Section: operators C-Name: vecmin0 Prototype: GD& Help: vecmin(x,{&v}): smallest entry in the vector/matrix x. If v is present, set it to the index of a smallest entry (indirect min). Description: (gen):gen vecmin($1) (gen, &gen):gen vecmin0($1, &$2) Doc: if $x$ is a list, vector or matrix, returns the smallest entry of $x$, otherwise returns a copy of $x$. Error if $x$ is empty. Here, smallest refers to the ordinary real ordering (\kbd{<=}). If $v$ is given, set it to the index of a smallest entry (indirect minimum), when $x$ is a vector or list. If $x$ is a matrix, set $v$ to coordinates $[i,j]$ such that $x[i,j]$ is a smallest entry. This argument $v$ is ignored for other types. When a vector has equal smallest entries, the first occurence is chosen; in a matrix, the smallest $j$ is chosen first, then the smallest $i$. \bprog ? vecmin([10, 20, -30, 40]) %1 = -30 ? vecmin([10, 20, -30, 40], &v); v %2 = 3 ? vecmin([10, 20; -30, 40], &v); v %3 = [2, 1] ? vecmin([1,0;0,0], &v); v %3 = [2, 1] @eprog Variant: When $v$ is not needed, the function \fun{GEN}{vecmin}{GEN x} is also available. pari-2.17.2/src/functions/operators/max0000644000175000017500000000104514567450071016522 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.17.2/src/functions/operators/shift0000644000175000017500000000105214676526175017062 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.17.2/src/functions/operators/min0000644000175000017500000000104514567450071016520 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.17.2/src/functions/operators/sign0000644000175000017500000000056314567450071016701 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; \typ{QUAD} with positive discriminants and \typ{INFINITY} are also supported. pari-2.17.2/src/functions/operators/cmp0000644000175000017500000000254514567450071016522 0ustar billbillFunction: cmp Section: operators C-Name: cmp_universal Prototype: iGG Help: cmp(x,y): compare two arbitrary objects x and y (1 if x>y, 0 if x=y, -1 if x$ vector $>$ scalar. For example: \bprog ? cmp(1, 2) %1 = -1 ? cmp(2, 1) %2 = 1 ? cmp(1, 1.0) \\ note that 1 == 1.0, but (1===1.0) is false. %3 = -1 ? cmp(x + Pi, []) %4 = -1 @eprog\noindent This function is mostly useful to handle sorted lists or vectors of arbitrary objects. For instance, if $v$ is a vector, the construction \kbd{vecsort(v, cmp)} is equivalent to \kbd{Set(v)}. pari-2.17.2/src/functions/operators/lex0000644000175000017500000000204514567450071016526 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 ? lex(2 - I, 1) %5 = 1 ? lex(2 - I, 2) %6 = -1 @eprog pari-2.17.2/src/functions/operators/shiftmul0000644000175000017500000000065314676526175017606 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.17.2/src/functions/operators/divrem0000644000175000017500000000214114567450071017221 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.17.2/src/functions/operators/vecmax0000644000175000017500000000215714676526175017237 0ustar billbillFunction: vecmax Section: operators C-Name: vecmax0 Prototype: GD& Help: vecmax(x,{&v}): largest entry in the vector/matrix x. If v is present, set it to the index of a largest entry (indirect max). Description: (gen):gen vecmax($1) (gen, &gen):gen vecmax0($1, &$2) Doc: if $x$ is a list, vector or matrix, returns the largest entry of $x$, otherwise returns a copy of $x$. Error if $x$ is empty. Here, largest refers to the ordinary real ordering (\kbd{<=}). If $v$ is given, set it to the index of a largest entry (indirect maximum), when $x$ is a vector or list. If $x$ is a matrix, set $v$ to coordinates $[i,j]$ such that $x[i,j]$ is a largest entry. This argument $v$ is ignored for other types. When the vector has equal largest entries, the first occurence is chosen; in a matrix, the smallest $j$ is chosen first, then the smallest $i$. vector or matrix. \bprog ? vecmax([10, 20, -30, 40]) %1 = 40 ? vecmax([10, 20, -30, 40], &v); v %2 = 4 ? vecmax([10, 20; -30, 40], &v); v %3 = [2, 2] @eprog Variant: When $v$ is not needed, the function \fun{GEN}{vecmax}{GEN x} is also available. pari-2.17.2/src/functions/elliptic_curves/0000755000175000017500000000000014760315601017162 5ustar billbillpari-2.17.2/src/functions/elliptic_curves/hyperellpadicfrobenius0000644000175000017500000000426314676526175023674 0ustar billbillFunction: hyperellpadicfrobenius Section: elliptic_curves C-Name: hyperellpadicfrobenius0 Prototype: GGL Help: hyperellpadicfrobenius(Q,q,n): Q being a rational polynomial of degree d and X being the curve defined by y^2=Q(x), return the matrix of the Frobenius at the prime q >= d in the standard basis of H^1_dR(X) to absolute q-adic precision q^n; q may also be of the form [T,p] where T is an integral polynomial which is irreducible mod p. Doc: Let $X$ be the curve defined by $y^{2}=Q(x)$, where $Q$ is a polynomial of degree $d$ over $\Q$ and $q\ge d$ is a prime such that $X$ has good reduction at $q$. Return the matrix of the Frobenius endomorphism $\varphi$ on the crystalline module $D_{p}(X) = \Q_{p} \otimes H^{1}_{dR}(X/\Q)$ with respect to the basis of the given model $(\omega, x\*\omega,\ldots,x^{g-1}\*\omega)$, where $\omega = dx/(2\*y)$ is the invariant differential, where $g$ is the genus of $X$ (either $d=2\*g+1$ or $d=2\*g+2$). The characteristic polynomial of $\varphi$ is the numerator of the zeta-function of the reduction of the curve $X$ modulo $q$. The matrix is computed to absolute $q$-adic precision $q^{n}$. Alternatively, $q$ may be of the form $[T,p]$ where $p$ is a prime, $T$ is a polynomial with integral coefficients whose projection to $\F_{p}[t]$ is irreducible, $X$ is defined over $K = \Q[t]/(T)$ and has good reduction to the finite field $\F_{q} = \F_{p}[t]/(T)$. The matrix of $\varphi$ on $D_{q}(X) = \Q_{q} \otimes H^{1}_{dR}(X/K)$ is computed to absolute $p$-adic precision $p^{n}$. \bprog ? M=hyperellpadicfrobenius(x^5+'a*x+1,['a^2+1,3],10); ? liftall(M) [48107*a + 38874 9222*a + 54290 41941*a + 8931 39672*a + 28651] [ 21458*a + 4763 3652*a + 22205 31111*a + 42559 39834*a + 40207] [ 13329*a + 4140 45270*a + 25803 1377*a + 32931 55980*a + 21267] [15086*a + 26714 33424*a + 4898 41830*a + 48013 5913*a + 24088] ? centerlift(simplify(liftpol(charpoly(M)))) %8 = x^4+4*x^2+81 ? hyperellcharpoly((x^5+Mod(a,a^2+1)*x+1)*Mod(1,3)) %9 = x^4+4*x^2+81 @eprog Variant: The functions \fun{GEN}{hyperellpadicfrobenius}{GEN H, ulong p, long n} and \fun{GEN}{nfhyperellpadicfrobenius}{GEN H, GEN T, ulong p, long n} are also available. pari-2.17.2/src/functions/elliptic_curves/ellchangepoint0000644000175000017500000000135714760123736022115 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^{2}x'+r$, $y=u^{3}y'+su^{2}x'+t$ (see also \kbd{ellchangecurve}). \bprog ? E0 = ellinit([1,1]); P0 = [0,1]; v = [1,2,3,4]; ? E = ellchangecurve(E0, v); ? P = ellchangepoint(P0,v) %3 = [-2, 3] ? ellisoncurve(E, P) %4 = 1 ? ellchangepointinv(P,v) %5 = [0, 1] @eprog Variant: The reciprocal function \fun{GEN}{ellchangepointinv}{GEN x, GEN ch} inverts the coordinate change. pari-2.17.2/src/functions/elliptic_curves/ellsea0000644000175000017500000000616214676526175020377 0ustar billbillFunction: ellsea Class: basic Section: elliptic_curves C-Name: ellsea Prototype: GD0,L, Help: ellsea(E,{tors=0}): computes the order of the group E(Fq) for the elliptic curve E, defined over a finite field, using SEA algorithm, with early abort for curves (or their quadratic twist) with nonprime order. Doc: Let $E$ be an \var{ell} structure as output by \kbd{ellinit}, defined over a finite field $\F_{q}$. This low-level function computes the order of the group $E(\F_{q})$ using the SEA algorithm; compared to the high-level function \kbd{ellcard}, which includes SEA among its choice of algorithms, the \kbd{tors} argument allows to speed up a search for curves having almost prime order and whose quadratic twist may also have almost prime order. When \kbd{tors} is set to a nonzero value, the function returns $0$ as soon as it detects that the order has a small prime factor not dividing \kbd{tors}; SEA considers modular polynomials of increasing prime degree $\ell$ and we return $0$ as soon as we hit an $\ell$ (coprime to \kbd{tors}) dividing $\#E(\F_{q})$: \bprog ? ellsea(ellinit([1,1], 2^56+3477), 1) %1 = 72057594135613381 ? forprime(p=2^128,oo, q = ellcard(ellinit([1,1],p)); if(isprime(q),break)) time = 6,571 ms. ? forprime(p=2^128,oo, q = ellsea(ellinit([1,1],p),1);if(isprime(q),break)) time = 522 ms. @eprog\noindent In particular, set \kbd{tors} to $1$ if you want a curve with prime order, to $2$ if you want to allow a cofactor which is a power of two (e.g. for Edwards's curves), etc. The early exit on bad curves yields a massive speedup compared to running the cardinal algorithm to completion. When \kbd{tors} is negative, similar checks are performed for the quadratic twist of the curve. The following function returns a curve of prime order over $\F_{p}$. \bprog cryptocurve(p) = { while(1, my(E, N, j = Mod(random(p), p)); E = ellinit(ellfromj(j)); N = ellsea(E, 1); if (!N, continue); if (isprime(N), return(E)); \\ try the quadratic twist for free if (isprime(2*p+2 - N), return(elltwist(E))); ); } ? p = randomprime([2^255, 2^256]); ? E = cryptocurve(p); \\ insist on prime order %2 = 47,447ms @eprog\noindent The same example without early abort (using \kbd{ellcard(E)} instead of \kbd{ellsea(E, 1)}) runs for about 5 minutes before finding a suitable curve. The availability of the \kbd{seadata} package will speed up the computation, and is strongly recommended. The generic function \kbd{ellcard} should be preferred when you only want to compute the cardinal of a given curve without caring about it having almost prime order: \item If the characteristic is too small ($p \leq 7$) or the field cardinality is tiny ($q \leq 523$) the generic algorithm \kbd{ellcard} is used instead and the \kbd{tors} argument is ignored. (The reason for this is that SEA is not implemented for $p \leq 7$ and that if $q \leq 523$ it is likely to run into an infinite loop.) \item If the field cardinality is smaller than about $2^{50}$, the generic algorithm will be faster. \item Contrary to \kbd{ellcard}, \kbd{ellsea} does not store the computed cardinality in $E$. pari-2.17.2/src/functions/elliptic_curves/HEADER0000644000175000017500000002454514676526175020067 0ustar billbillFunction: _header_elliptic_curves Class: header Section: elliptic_curves Doc: \section{Elliptic curves} \subsec{Elliptic curve structures} %GPHELPskip An elliptic curve is given by a Weierstrass model\sidx{Weierstrass equation} $$ y^{2} + a_{1} xy + a_{3} y = x^{3} + a_{2} x^{2} + a_{4} x + a_{6}, $$ whose discriminant is nonzero. One can also define an elliptic curve with a\sidx{short Weierstrass equation} $$ y^{2} = x^{3} + a_{4} x + a_{6}. $$ Affine points on \kbd{E} are represented as two-component vectors \kbd{[x,y]}; the point at infinity, i.e.~the identity element of the group law, is represented by the one-component vector \kbd{[0]}. Given a vector of coefficients $[a_{1},a_{2},a_{3},a_{4},a_{6}]$ or $[a_{4},a_{6}]$, the function \tet{ellinit} initializes and returns an \tev{ell} structure. An additional optional argument allows to specify the base field in case it cannot be inferred from the curve coefficients. This structure contains data needed by elliptic curve related functions, and is generally passed as a first argument. Expensive data are skipped on initialization: they will be dynamically computed when (and if) needed, and then inserted in the structure. The precise layout of the \tev{ell} structure is left undefined and should never be used directly. The following \idx{member functions} are available, depending on the underlying domain. \misctitle{All domains} %GPHELPskip \item \tet{a1}, \tet{a2}, \tet{a3}, \tet{a4}, \tet{a6}: coefficients of the elliptic curve. \item \tet{b2}, \tet{b4}, \tet{b6}, \tet{b8}: $b$-invariants of the curve; in characteristic $\neq 2$, for $Y = 2y + a_{1}x + a_{3}$, the curve equation becomes $$ Y^{2} = 4 x^{3} + b_{2} x^{2} + 2b_{4} x + b_{6} =: g(x). $$ \item \tet{c4}, \tet{c6}: $c$-invariants of the curve; in characteristic $\neq 2,3$, for $X = x + b_{2}/12$ and $Y = 2y + a_{1}x + a_{3}$, the curve equation becomes $$ Y^{2} = 4 X^{3} - (c_{4}/12) X - (c_{6}/216). $$ \item \tet{disc}: discriminant of the curve. This is only required to be nonzero, not necessarily a unit. \item \tet{j}: $j$-invariant of the curve. \noindent These are used as follows: \bprog ? E = ellinit([0,0,0, a4,a6]); ? E.b4 %2 = 2*a4 ? E.disc %3 = -64*a4^3 - 432*a6^2 @eprog \misctitle{Curves over $\C$} %GPHELPskip This in particular includes curves defined over $\Q$. All member functions in this section return data, as it is currently stored in the structure, if present; and otherwise compute it to the default accuracy, that was fixed \emph{at the time of ellinit} (via a \typ{REAL} $D$ domain argument, or \kbd{realprecision} by default). The function \tet{ellperiods} allows to recompute (and cache) the following data to \emph{current} \kbd{realprecision}. \item \tet{area}: volume of the complex lattice defining $E$. \item \tet{roots} is a vector whose three components contain the complex roots of the right hand side $g(x)$ of the attached $b$-model $Y^{2} = g(x)$. If the roots are all real, they are ordered by decreasing value. If only one is real, it is the first component. \item \tet{omega}: $[\omega_{1},\omega_{2}]$, periods forming a basis of the complex lattice defining $E$. The first component $\omega_{1}$ is the (positive) real period, in other words the integral of the N\'eron differential $dx/(2y+a_{1}x+a_{3})$ over the connected component of the identity component of $E(\R)$. The second component $\omega_{2}$ is a complex period, such that $\tau=\dfrac{\omega_{1}}{\omega_{2}}$ belongs to Poincar\'e's half-plane (positive imaginary part); not necessarily to the standard fundamental domain. It is normalized so that $\Im(\omega_{2}) < 0$ and either $\Re(\omega_{2}) = 0$, when \kbd{E.disc > 0} ($E(\R)$ has two connected components), or $\Re(\omega_{2}) = \omega_{1}/2$ \item \tet{eta} is a row vector containing the quasi-periods $\eta_{1}$ and $\eta_{2}$ such that $\eta_{i} = 2\zeta(\omega_{i}/2)$, where $\zeta$ is the Weierstrass zeta function attached to the period lattice; see \tet{ellzeta}. In particular, the Legendre relation holds: $\eta_{2}\omega_{1} - \eta_{1}\omega_{2} = 2\pi i$. \misctitle{Warning} As for the orientation of the basis of the period lattice, beware that many sources use the inverse convention where $\omega_{2}/\omega_{1}$ has positive imaginary part and our $\omega_{2}$ is the negative of theirs. Our convention $\tau = \omega_{1}/\omega_{2}$ ensures that the action of $\text{PSL}_{2}$ is the natural one: $$[a,b;c,d]\cdot\tau = (a\tau+b)/(c\tau+d) = (a \omega_{1} + b\omega_{2})/(c\omega_{1} + d\omega_{2}),$$ instead of a twisted one. (Our $\tau$ is $-1/\tau$ in the above inverse convention.) \misctitle{Curves over $\Q_{p}$} %GPHELPskip We advise to input a model defined over $\Q$ for such curves. In any case, if you input an approximate model with \typ{PADIC} coefficients, it will be replaced by a lift to $\Q$ (an exact model ``close'' to the one that was input) and all quantities will then be computed in terms of this lifted model. For the time being only curves with multiplicative reduction (split or nonsplit), i.e. $v_{p}(j) < 0$, are supported by nontrivial functions. In this case the curve is analytically isomorphic to $\bar{\Q}_{p}^{*}/q^{\Z} := E_{q}(\bar{\Q}_{p})$, for some $p$-adic integer $q$ (the Tate period). In particular, we have $j(q) = j(E)$. \item \tet{p} is the residual characteristic \item \tet{roots} is a vector with a single component, equal to the $p$-adic root $e_{1}$ of the right hand side $g(x)$ of the attached $b$-model $Y^{2} = g(x)$. The point $(e_{1},0)$ corresponds to $-1 \in \bar{\Q}_{p}^{*}/q^{\Z}$ under the Tate parametrization. \item \tet{tate} returns $[u^{2},u,q,[a,b],Ei,L]$ in the notation of Henniart-Mestre (CRAS t. 308, p.~391--395, 1989): $q$ is as above, $u\in \Q_{p}(\sqrt{-c_{6}})$ is such that $\phi^{*} dx/(2y + a_{1}x + a_{3}) = u dt/t$, where $\phi: E_{q}\to E$ is an isomorphism (well defined up to sign) and $dt/t$ is the canonical invariant differential on the Tate curve; $u^{2}\in\Q_{p}$ does not depend on $\phi$. (Technicality: if $u\not\in\Q_{p}$, it is stored as a quadratic \typ{POLMOD}.) The parameters $[a,b]$ satisfy $4u^{2} b \cdot \text{agm}(\sqrt{a/b},1)^{2} = 1$ as in Theorem~2 (\emph{loc.~cit.}). \kbd{Ei} describes the sequence of 2-isogenous curves (with kernel generated by $[0,0]$) $E_{i}: y^{2}=x(x+A_{i})(x+A_{i}-B_{i})$ converging quadratically towards the singular curve $E_{\infty}$. Finally, $L$ is Mazur-Tate-Teitelbaum's ${\cal L}$-invariant, equal to $\log_{p} q / v_{p}(q)$. \misctitle{Curves over $\F_{q}$} %GPHELPskip \item \tet{p} is the characteristic of $\F_{q}$. \item \tet{no} is $\#E(\F_{q})$. \item \tet{cyc} gives the cycle structure of $E(\F_{q})$. \item \tet{gen} returns the generators of $E(\F_{q})$. \item \tet{group} returns $[\kbd{no},\kbd{cyc},\kbd{gen}]$, i.e. $E(\F_{q})$ as an abelian group structure. \misctitle{Curves over $\Q$} %GPHELPskip All functions should return a correct result, whether the model is minimal or not, but it is a good idea to stick to minimal models whenever $\gcd(c_{4},c_{6})$ is easy to factor (minor speed-up). The construction \bprog E = ellminimalmodel(E0, &v) @eprog\noindent replaces the original model $E_{0}$ by a minimal model $E$, and the variable change $v$ allows to go between the two models: \bprog ellchangepoint(P0, v) ellchangepointinv(P, v) @eprog\noindent respectively map the point $P_{0}$ on $E_{0}$ to its image on $E$, and the point $P$ on $E$ to its pre-image on $E_{0}$. A few routines --- namely \tet{ellgenerators}, \tet{ellidentify}, \tet{ellsearch}, \tet{forell} --- require the optional package \tet{elldata} (John Cremona's database) to be installed. In that case, the function \tet{ellinit} will allow alternative inputs, e.g.~\kbd{ellinit("11a1")}. Functions using this package need to load chunks of a large database in memory and require at least 2MB stack to avoid stack overflows. \item \tet{gen} returns the generators of $E(\Q)$, if known (from John Cremona's database) \misctitle{Curves over number fields} %GPHELPskip \item \tet{nf} return the \var{nf} structure attached to the number field over which $E$ is defined. \item \tet{bnf} return the \var{bnf} structure attached to the number field over which $E$ is defined or raise an error (if only an \var{nf} is available). \item \tet{omega}, \tet{eta}, \tet{area}: vectors of complex periods, quasi-periods and lattice areas attached to the complex embeddings of $E$, in the same order as \kbd{E.nf.roots}. \subsec{Reduction} %GPHELPskip Let $E$ be a curve defined over $\Q_{p}$ given by a $p$-integral model; if the curve has good reduction at $p$, we may define its reduction $\tilde{E}$ over the finite field $\F_{p}$: \bprog ? E = ellinit([-3,1], O(5^10)); \\ @com $E/\Q_{5}$ ? Et = ellinit(E, 5) ? ellcard(Et) \\ @com $\tilde{E}/\F_{5}$ has 7 points %3 = 7 ? ellinit(E, 7) *** at top-level: ellinit(E,7) *** ^------------ *** ellinit: inconsistent moduli in ellinit: 5 != 7 @eprog\noindent Likewise, if a curve is defined over a number field $K$ and $\goth{p}$ is a maximal ideal with finite residue field $\F_{q}$, we define the reduction $\tilde{E}/\F_{q}$ provided $E$ has good reduction at $\goth{p}$. $E/\Q$ is an important special case: \bprog ? E = ellinit([-3,1]); ? factor(E.disc) %2 = [2 4] [3 4] ? Et = ellinit(E, 5); ? ellcard(Et) \\ @com $\tilde{E} / \F_{5}$ has 7 points %4 = 7 ? ellinit(E, 3) \\ bad reduction at 3 %5 = [] @eprog\noindent General number fields are similar: \bprog ? K = nfinit(x^2+1); E = ellinit([x,x+1], K); ? idealfactor(K, E.disc) \\ three primes of bad reduction %2 = [ [2, [1, 1]~, 2, 1, [1, -1; 1, 1]] 10] [ [5, [-2, 1]~, 1, 1, [2, -1; 1, 2]] 2] [[5, [2, 1]~, 1, 1, [-2, -1; 1, -2]] 2] ? P = idealprimedec(K, 3); \\ a prime of good reduction ? idealnorm(K, P) %4 = 9 ? Et = ellinit(E, P); ? ellcard(Et) \\ @com $\tilde{E} / \F_{9}$ has 4 points %6 = 4 @eprog\noindent If the model is not locally minimal at $\goth{p}$, the above will fail: \kbd{elllocalred} and \kbd{ellchangecurve} allow to reduce to that case. Some functions such as \kbd{ellap}, \kbd{ellcard}, \kbd{ellgroup} and \kbd{ellissupersingular} even implicitly replace the given equation by a local minimal model and consider the group of nonsingular points $\tilde{E}^{ns}$ so they make sense even when the curve has bad reduction. pari-2.17.2/src/functions/elliptic_curves/ellisotree0000644000175000017500000000262414676526175021300 0ustar billbillFunction: ellisotree Section: elliptic_curves C-Name: ellisotree Prototype: G Help: ellisotree(E): E being an elliptic curve over Q or a set of isogenous rational curves as given by ellisomat, return minimal models of the isomorphism classes of elliptic curves isogenous to E (or in the set) and the oriented graph of isogenies of prime degree (adjacency matrix). Doc: Given an elliptic curve $E$ defined over $\Q$ or a set of $\Q$-isogenous curves as given by \kbd{ellisomat}, return a pair $[L,M]$ where \item $L$ lists the minimal models of the isomorphism classes of elliptic curves $\Q$-isogenous to $E$ (or in the set of isogenous curves), \item $M$ is the adjacency matrix of the prime degree isogenies tree: there is an edge from $E_{i}$ to $E_{j}$ if there is an isogeny $E_{i} \to E_{j}$ of prime degree such that the N\'eron differential forms are preserved. \bprog ? E = ellinit("14a1"); ? [L,M] = ellisotree(E); ? M %3 = [0 0 3 2 0 0] [3 0 0 0 2 0] [0 0 0 0 0 2] [0 0 0 0 0 3] [0 0 0 3 0 0] [0 0 0 0 0 0] ? [L2,M2] = ellisotree(ellisomat(E,2,1)); %4 = [0 2] [0 0] ? [L3,M3] = ellisotree(ellisomat(E,3,1)); ? M3 %6 = [0 0 3] [3 0 0] [0 0 0] @eprog\noindent Compare with the result of \kbd{ellisomat}. \bprog ? [L,M]=ellisomat(E,,1); ? M %7 = [1 3 3 2 6 6] [3 1 9 6 2 18] [3 9 1 6 18 2] [2 6 6 1 3 3] [6 2 18 3 1 9] [6 18 2 3 9 1] @eprog pari-2.17.2/src/functions/elliptic_curves/ellisomat0000644000175000017500000000474314676526175021126 0ustar billbillFunction: ellisomat Section: elliptic_curves C-Name: ellisomat Prototype: GD0,L,D0,L, Help: ellisomat(E,{p=0},{flag=0}): E being an elliptic curve over a number field K, returns a list of representatives of the isomorphism classes of elliptic curves defined over K and K-isogenous to E, with the corresponding isogenies from E and their dual, and the matrix of the isogeny degrees between the curves. If flag is 1, the isogenies are not computed, which saves time. If p is set, it must be a prime number: in this case only isogenies of degree a power of p are considered. Doc: Given an elliptic curve $E$ defined over a number field~$K$, computes representatives of the set of isomorphism classes of elliptic curves defined over~$K$ and $K$-isogenous to $E$, assuming it is finite (see below). For any such curve $E_{i}$, let $f_{i}: E \to E_{i}$ be a rational isogeny of minimal degree and let $g_{i}: E_{i} \to E$ be the dual isogeny; and let $M$ be the matrix such that $M_{i,j}$ is the minimal degree for an isogeny $E_{i} \to E_{j}$. The function returns a vector $[L,M]$ where $L$ is a list of triples $[E_{i}, f_{i}, g_{i}]$ ($\fl = 0$), or simply the list of $E_{i}$ ($\fl = 1$, which saves time). The curves $E_{i}$ are given in $[a_{4},a_{6}]$ form and the first curve $E_{1}$ is isomorphic to $E$ by $f_{1}$. The set of isomorphism classes is finite except when $E$ has CM over a quadratic order contained in $K$. In that case the function only returns the discriminant of the quadratic order. If $p$ is set, it must be a prime number; in this which case only isogenies of degree a power of $p$ are considered. Over a number field, the possible isogeny degrees are determined by Billerey's algorithm. \bprog ? E = ellinit("14a1"); ? [L,M] = ellisomat(E); ? LE = apply(x->x[1], L) \\ list of curves %3 = [[215/48,-5291/864],[-675/16,6831/32],[-8185/48,-742643/864], [-1705/48,-57707/864],[-13635/16,306207/32],[-131065/48,-47449331/864]] ? L[2][2] \\ isogeny f_2 %4 = [x^3+3/4*x^2+19/2*x-311/12, 1/2*x^4+(y+1)*x^3+(y-4)*x^2+(-9*y+23)*x+(55*y+55/2),x+1/3] ? L[2][3] \\ dual isogeny g_2 %5 = [1/9*x^3-1/4*x^2-141/16*x+5613/64, -1/18*x^4+(1/27*y-1/3)*x^3+(-1/12*y+87/16)*x^2+(49/16*y-48)*x +(-3601/64*y+16947/512),x-3/4] ? apply(E->ellidentify(ellinit(E))[1][1], LE) %6 = ["14a1","14a4","14a3","14a2","14a6","14a5"] ? M %7 = [1 3 3 2 6 6] [3 1 9 6 2 18] [3 9 1 6 18 2] [2 6 6 1 3 3] [6 2 18 3 1 9] [6 18 2 3 9 1] @eprog pari-2.17.2/src/functions/elliptic_curves/ellrootno0000644000175000017500000000160514567450071021132 0ustar billbillFunction: ellrootno Section: elliptic_curves C-Name: ellrootno Prototype: lGDG Help: ellrootno(E,{p}): root number for the L-function of the elliptic curve E/Q at a prime p (including 0, for the infinite place); global root number if p is omitted. If p is omitted, the curve can also be defined over a number field. Doc: $E$ being an \kbd{ell} structure over $\Q$ as output by \kbd{ellinit}, this function computes the local root number of its $L$-series at the place $p$ (at the infinite place if $p = 0$). If $p$ is omitted, return the global root number and in this case the curve can also be defined over a number field. Note that the global root number is the sign of the functional equation and conjecturally is the parity of the rank of the \idx{Mordell-Weil group}. The equation for $E$ needs not be minimal at $p$, but if the model is already minimal the function will run faster. pari-2.17.2/src/functions/elliptic_curves/ellformalw0000644000175000017500000000137214760123736021262 0ustar billbillFunction: ellformalw Section: elliptic_curves C-Name: ellformalw Prototype: GDPDn Help: ellformalw(E,{n=seriesprecision},{t='x}): E elliptic curve, n integer; returns n terms of the formal expansion of w = -1/y in the formal parameter t = -x/y. Doc:Return the formal power series $w$ attached to the elliptic curve $E$, in the variable $t$: $$ w(t) = t^{3}(1 + a_{1} t + (a_{2} + a_{1}^{2}) t^{2} + \cdots + O(t^{n})),$$ which is the formal expansion of $-1/y$ in the formal parameter $t := -x/y$ at $\infty$ (take $n = \tet{seriesprecision}$ if $n$ is omitted). The coefficients of $w$ belong to $\Z[a_{1},a_{2},a_{3},a_{4},a_{6}]$. \bprog ? E=ellinit([3,2,-4,-2,5]); ellformalw(E, 5, 't) %1 = t^3 + 3*t^4 + 11*t^5 + 35*t^6 + 101*t^7 + O(t^8) @eprog pari-2.17.2/src/functions/elliptic_curves/ellweilpairing0000644000175000017500000000152314676526175022135 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: Let $E$ be an elliptic curve defined over a finite field and $m \geq 1$ be an integer. This function computes the Weil pairing of the two $m$-torsion points $P$ and $Q$ on $E$, which is an alternating bilinear map. More precisely, let $f_{m,R}$ denote a Miller function with divisor $m[R] - m[O_{E}]$; the algorithm returns the $m$-th root of unity $$\varepsilon(P,Q)^{m} \cdot f_{m,P}(Q) / f_{m,Q}(P),$$ where $f(R)$ is the extended evaluation of $f$ at the divisor $[R] - [O_{E}]$ and $\varepsilon(P,Q)\in \{\pm1\}$ is given by Weil reciprocity: $\varepsilon(P,Q) = 1$ if and only if $P, Q, O_{E}$ are not pairwise distinct. pari-2.17.2/src/functions/elliptic_curves/ellglobalred0000644000175000017500000000366314676526175021565 0ustar billbillFunction: ellglobalred Section: elliptic_curves C-Name: ellglobalred Prototype: G Help: ellglobalred(E): E being an elliptic curve over a number field, returns [N, v, c, faN, L], where N is the conductor of E, c is the product of the local Tamagawa numbers c_p, faN is the factorization of N and L[i] is elllocalred(E, faN[i,1]); v is an obsolete field. Description: (gen):gen ellglobalred($1) Doc: let $E$ be an \kbd{ell} structure as output by \kbd{ellinit} attached to an elliptic curve defined over a number field. This function calculates the arithmetic conductor and the global \idx{Tamagawa number} $c$. The result $[N,v,c,F,L]$ is slightly different if $E$ is defined over $\Q$ (domain $D = 1$ in \kbd{ellinit}) or over a number field (domain $D$ is a number field structure, including \kbd{nfinit(x)} representing $\Q$ !): \item $N$ is the arithmetic conductor of the curve, \item $v$ is an obsolete field, left in place for backward compatibility. If $E$ is defined over $\Q$, $v$ gives the coordinate change for $E$ to the standard minimal integral model (\tet{ellminimalmodel} provides it in a cheaper way); if $E$ is defined over another number field, $v$ gives a coordinate change to an integral model (\tet{ellintegralmodel} provides it in a cheaper way). \item $c$ is the product of the local Tamagawa numbers $c_{p}$, a quantity which enters in the \idx{Birch and Swinnerton-Dyer conjecture}, \item $F$ is the factorization of $N$, \item $L$ is a vector, whose $i$-th entry contains the local data at the $i$-th prime ideal divisor of $N$, i.e. \kbd{L[i] = elllocalred(E,F[i,1])}. If $E$ is defined over $\Q$, the local coordinate change has been deleted and replaced by a 0; if $E$ is defined over another number field the local coordinate change to a local minimal model is given relative to the integral model afforded by $v$ (so either start from an integral model so that $v$ be trivial, or apply $v$ first). pari-2.17.2/src/functions/elliptic_curves/ellintegralmodel0000644000175000017500000000132414676526175022450 0ustar billbillFunction: ellintegralmodel Section: elliptic_curves C-Name: ellintegralmodel Prototype: GD& Help: ellintegralmodel(E,{&v}): given an elliptic curve E defined over a number field or Qp, returns an integral model. If v is present, sets the variable v to the corresponding change of variable. Doc: Let $E$ be an \kbd{ell} structure over a number field $K$ or $\Q_{p}$. This function returns an integral model. If $v$ is present, sets $v = [u,0,0,0]$ to the corresponding change of variable: the return value is identical to that of \kbd{ellchangecurve(E, v)}. \bprog ? e = ellinit([1/17,1/42]); ? e = ellintegralmodel(e,&v); ? e[1..5] %3 = [0, 0, 0, 15287762448, 3154568630095008] ? v %4 = [1/714, 0, 0, 0] @eprog pari-2.17.2/src/functions/elliptic_curves/ellgroup0000644000175000017500000000712114676526175020757 0ustar billbillFunction: ellgroup Section: elliptic_curves C-Name: ellgroup0 Prototype: GDGD0,L, Help: ellgroup(E,{p},{flag}): given an elliptic curve E defined over a finite field Fq, returns the structure of the group E(Fq); for other fields of definition K, p must define a finite residue field (p prime for K = Qp or Q; p a maximal ideal for K a number field) and we return the structure of the (nonsingular) reduction of E. If flag is 1, also returns generators, but the curve equation must be minimal at p. Doc: Let \kbd{E} be an \kbd{ell} structure as output by \kbd{ellinit}, attached to an elliptic curve $E/K$. We first describe the function when the field $K = \F_{q}$ is finite, it computes the structure of the finite abelian group $E(\F_{q})$: \item if $\fl = 0$, returns the structure $[]$ (trivial group) or $[d_{1}]$ (nontrivial cyclic group) or $[d_{1},d_{2}]$ (noncyclic group) of $E(\F_{q}) \sim \Z/d_{1}\Z \times \Z/d_{2}\Z$, with $d_{2}\mid d_{1}$. \item if $\fl = 1$, returns a triple $[h,\var{cyc},\var{gen}]$, where $h$ is the curve cardinality, \var{cyc} gives the group structure as a product of cyclic groups (as per $\fl = 0$). More precisely, if $d_{2} > 1$, the output is $[d_{1}d_{2}, [d_{1},d_{2}], [P,Q]]$ where $P$ is of order $d_{1}$ and $[P,Q]$ generates the curve. \misctitle{Caution} It is not guaranteed that $Q$ has order $d_{2}$, which in the worst case requires an expensive discrete log computation. Only that \kbd{ellweilpairing}$(E, P, Q, d_{1})$ has order $d_{2}$. For other fields of definition and $p$ defining a finite residue field $\F_{q}$, returns the structure of the reduction of $E$: the argument $p$ is best left omitted if $K = \Q_{\ell}$ (else we must have $p = \ell$) and must be a prime number ($K = \Q$) or prime ideal ($K$ a general number field) with residue field $\F_{q}$ otherwise. The curve is allowed to have bad reduction at $p$ and in this case we consider the (cyclic) group of nonsingular points for the reduction of a minimal model at $p$. If $\fl = 0$, the equation need not be minimal or even integral at $p$; of course, a minimal model will be more efficient. If $\fl = 1$, the requested generators depend on the model, which must then be minimal at $p$, otherwise an exception is thrown. Use \kbd{ellintegralmodel} and/or \kbd{ellocalred} first to reduce to this case. \bprog ? E = ellinit([0,1]); \\ y^2 = x^3 + 0.x + 1, defined over Q ? ellgroup(E, 7) %2 = [6, 2] \\ Z/6 x Z/2, noncyclic ? E = ellinit([0,1] * Mod(1,11)); \\ defined over F_11 ? ellgroup(E) \\ no need to repeat 11 %4 = [12] ? ellgroup(E, 11) \\ ... but it also works %5 = [12] ? ellgroup(E, 13) \\ ouch, inconsistent input! *** at top-level: ellgroup(E,13) *** ^-------------- *** ellgroup: inconsistent moduli in Rg_to_Fp: 11 13 ? ellgroup(E, 7, 1) %6 = [12, [6, 2], [[Mod(2, 7), Mod(4, 7)], [Mod(4, 7), Mod(4, 7)]]] @eprog\noindent Let us now consider curves of bad reduction, in this case we return the structure of the (cyclic) group of nonsingular points, satisfying $\#E_{ns}(\F_{p}) = p - a_{p}$: \bprog ? E = ellinit([0,5]); ? ellgroup(E, 5, 1) %2 = [5, [5], [[Mod(4, 5), Mod(2, 5)]]] ? ellap(E, 5) %3 = 0 \\ additive reduction at 5 ? E = ellinit([0,-1,0,35,0]); ? ellgroup(E, 5, 1) %5 = [4, [4], [[Mod(2, 5), Mod(2, 5)]]] ? ellap(E, 5) %6 = 1 \\ split multiplicative reduction at 5 ? ellgroup(E, 7, 1) %7 = [8, [8], [[Mod(3, 7), Mod(5, 7)]]] ? ellap(E, 7) %8 = -1 \\ nonsplit multiplicative reduction at 7 @eprog Variant: Also available is \fun{GEN}{ellgroup}{GEN E, GEN p}, corresponding to $\fl = 0$. pari-2.17.2/src/functions/elliptic_curves/hyperellordinate0000644000175000017500000000050714760123736022467 0ustar billbillFunction: hyperellordinate Section: elliptic_curves C-Name: hyperellordinate Prototype: GG Help: hyperellordinate(H,x): y-coordinates corresponding to x-ordinate x on hyperelliptic curve H. Doc: gives a 0, 1 or 2-component vector containing the $y$-coordinates of the points of the curve $H$ having $x$ as $x$-coordinate. pari-2.17.2/src/functions/elliptic_curves/ellmoddegree0000644000175000017500000000243614676526175021562 0ustar billbillFunction: ellmoddegree Section: elliptic_curves C-Name: ellmoddegree Prototype: G Help: ellmoddegree(e): e being an elliptic curve defined over Q output by ellinit, compute the modular degree of e divided by the square of the Manin constant. Doc: $e$ being an elliptic curve defined over $\Q$ output by \kbd{ellinit}, compute the modular degree of $e$ divided by the square of the Manin constant $c$. It is conjectured that $c = 1$ for the strong Weil curve in the isogeny class (optimal quotient of $J_{0}(N)$) and this can be proven using \kbd{ellweilcurve} when the conductor $N$ is moderate. \bprog ? E = ellinit("11a1"); \\ from Cremona table: strong Weil curve and c = 1 ? [v,smith] = ellweilcurve(E); smith \\ proof of the above %2 = [[1, 1], [5, 1], [1, 1/5]] ? ellmoddegree(E) %3 = 1 ? [ellidentify(e)[1][1] | e<-v] %4 = ["11a1", "11a2", "11a3"] ? ellmoddegree(ellinit("11a2")) %5 = 5 ? ellmoddegree(ellinit("11a3")) %6 = 1/5 @eprog\noindent The modular degree of \kbd{11a1} is $1$ (because \kbd{ellweilcurve} or Cremona's table prove that the Manin constant is $1$ for this curve); the output of \kbd{ellweilcurve} also proves that the Manin constants of \kbd{11a2} and \kbd{11a3} are 1 and 5 respectively, so the actual modular degree of both \kbd{11a2} and \kbd{11a3} is 5. pari-2.17.2/src/functions/elliptic_curves/elltatepairing0000644000175000017500000000112714676526175022132 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: Let $E$ be an elliptic curve defined over a finite field $k$ and $m \geq 1$ be an integer. This function computes the (nonreduced) Tate pairing of the points $P$ and $Q$ on $E$, where $P$ is an $m$-torsion point. More precisely, let $f_{m,P}$ denote a Miller function with divisor $m[P] - m[O_{E}]$; the algorithm returns $f_{m,P}(Q) \in k^{*}/(k^{*})^{m}$. pari-2.17.2/src/functions/elliptic_curves/ellisisom0000644000175000017500000000162314676526175021127 0ustar billbillFunction: ellisisom Section: elliptic_curves C-Name: ellisisom Prototype: GG Help: ellisisom(E,F): return 0 if the elliptic curves E and F defined over the same number field are not isomorphic, otherwise return [u,r,s,t] suitable for ellchangecurve, mapping E to F. Doc: return $0$ if the elliptic curves $E$ and $F$ defined over the same number field are not isomorphic, otherwise return \kbd{[u,r,s,t]} suitable for \kbd{ellchangecurve}, mapping $E$ to $F$. \bprog ? E = ellinit([1,2]); ? ellisisom(E, ellinit([1,3])) %2 = 0 ? F = ellchangecurve(E, [-1,1,3,2]); ? ellisisom(E,F) %4 = [1, 1, -3, -2] @eprog \bprog ? nf = nfinit(a^3-2); E = ellinit([a^2+1,2*a-5], nf); ? F = ellchangecurve(E,Mod([a, a+1, a^2, a^2+a-3], nf.pol)); ? v = ellisisom(E,F) %3 = [Mod(-a, a^3 - 2), Mod(a + 1, a^3 - 2), Mod(-a^2, a^3 - 2), Mod(-a^2 - a + 3, a^3 - 2)] ? ellchangecurve(E,v) == F %4 = 1 @eprog pari-2.17.2/src/functions/elliptic_curves/ellwp0000644000175000017500000000357014676526175020255 0ustar billbillFunction: ellwp Section: elliptic_curves C-Name: ellwp0 Prototype: GDGD0,L,p Help: ellwp(w,{z='x},{flag=0}): computes the value at z of the Weierstrass P function attached to the lattice w, as given by ellperiods. Optional flag means 0 (default), compute only P(z), 1 compute [P(z),P'(z)]. Doc: Computes the value at $z$ of the Weierstrass $\wp$ function attached to the lattice $w$ as given by \tet{ellperiods}. It is also possible to directly input $w = [\omega_{1},\omega_{2}]$, or an elliptic curve $E$ as given by \kbd{ellinit} ($w = \kbd{E.omega}$). \bprog ? w = ellperiods([1,I]); ? ellwp(w, 1/2) %2 = 6.8751858180203728274900957798105571978 ? E = ellinit([1,1]); ? ellwp(E, 1/2) %4 = 3.9413112427016474646048282462709151389 @eprog\noindent One can also compute the series expansion around $z = 0$: \bprog ? E = ellinit([1,0]); ? ellwp(E) \\ 'x implicitly at default seriesprecision %5 = x^-2 - 1/5*x^2 + 1/75*x^6 - 2/4875*x^10 + O(x^14) ? ellwp(E, x + O(x^12)) \\ explicit precision %6 = x^-2 - 1/5*x^2 + 1/75*x^6 + O(x^9) @eprog Optional \fl\ means 0 (default): compute only $\wp(z)$, 1: compute $[\wp(z),\wp'(z)]$. For instance, the Dickson elliptic functions \var{sm} and \var{sn} can be implemented as follows \bprog smcm(z) = { my(a, b, E = ellinit([0,-1/(4*27)])); \\ ell. invariants (g2,g3)=(0,1/27) [a,b] = ellwp(E, z, 1); [6*a / (1-3*b), (3*b+1)/(3*b-1)]; } ? [s,c] = smcm(0.5); ? s %2 = 0.4898258757782682170733218609 ? c %3 = 0.9591820206453842491187464098 ? s^3+c^3 %4 = 1.000000000000000000000000000 ? smcm('x + O('x^11)) %5 = [x - 1/6*x^4 + 2/63*x^7 - 13/2268*x^10 + O(x^11), 1 - 1/3*x^3 + 1/18*x^6 - 23/2268*x^9 + O(x^10)] @eprog Variant: For $\fl = 0$, we also have \fun{GEN}{ellwp}{GEN w, GEN z, long prec}, and \fun{GEN}{ellwpseries}{GEN E, long v, long precdl} for the power series in variable $v$. pari-2.17.2/src/functions/elliptic_curves/hyperellisoncurve0000644000175000017500000000147314676526175022714 0ustar billbillFunction: hyperellisoncurve Section: elliptic_curves C-Name: hyperellisoncurve Prototype: iGG Help: hyperellisoncurve(X,p): X being a nonsingular hyperelliptic model of a curve, test whether the point p is on the curve. X can be given either by a squarefree polynomial P such that X:y^2=P(x) or by a vector [P,Q] such that X:y^2+Q(x)*y=P(x) and Q^2+4P is squarefree. Doc: $X$ being a nonsingular hyperelliptic model of a curve, test whether the point $p$ is on the curve. $X$ can be given either by a squarefree polynomial $P$ such that $X: y^{2} = P(x)$ or by a vector $[P,Q]$ such that $X: y^{2} + Q(x)\*y = P(x)$ and $Q^{2}+4\*P$ is squarefree. \bprog ? W = [2*x^6+3*x^5+x^4+x^3-x,x^3+1]; p = [px, py] = [1/3,-14/27]; ? hyperellisoncurve(W, p) %2 = 1 ? [Px,Qx]=subst(W,x,px); py^2+py*Qx == Px %3 = 1 @eprog pari-2.17.2/src/functions/elliptic_curves/elladd0000644000175000017500000000034314557721031020334 0ustar billbillFunction: elladd Section: elliptic_curves C-Name: elladd Prototype: GGG Help: elladd(E,z1,z2): sum of the points z1 and z2 on elliptic curve E. Doc: sum of the points $z1$ and $z2$ on the elliptic curve corresponding to $E$. pari-2.17.2/src/functions/elliptic_curves/ellfromeqn0000644000175000017500000000350114760123736021256 0ustar billbillFunction: ellfromeqn Section: elliptic_curves C-Name: ellfromeqn Prototype: G Help: ellfromeqn(P): given a genus 1 plane curve, defined by the affine equation f(x,y) = 0, return the coefficients [a1,a2,a3,a4,a6] of a Weierstrass equation for its Jacobian. This allows to recover a Weierstrass model for an elliptic curve given by a general plane cubic or by a binary quartic or biquadratic model. Doc: Given a genus $1$ plane curve, defined by the affine equation $f(x,y) = 0$, return the coefficients $[a_{1},a_{2},a_{3},a_{4},a_{6}]$ of a Weierstrass equation for its Jacobian. This allows to recover a Weierstrass model for an elliptic curve given by a general plane cubic or by a binary quartic or biquadratic model. The function implements the $f \mapsto f^{*}$ formulae of Artin, Tate and Villegas (Advances in Math. 198 (2005), pp. 366--382). In the example below, the function is used to convert between twisted Edwards coordinates and Weierstrass coordinates. \bprog ? e = ellfromeqn(a*x^2+y^2 - (1+d*x^2*y^2)) %1 = [0, -a - d, 0, -4*d*a, 4*d*a^2 + 4*d^2*a] ? E = ellinit(ellfromeqn(y^2-x^2 - 1 +(121665/121666*x^2*y^2)),2^255-19); ? isprime(ellcard(E) / 8) %3 = 1 @eprog The elliptic curve attached to the sum of two cubes is given by \bprog ? ellfromeqn(x^3+y^3 - a) %1 = [0, 0, -9*a, 0, -27*a^2] @eprog \misctitle{Congruent number problem} Let $n$ be an integer, if $a^{2}+b^{2}=c^{2}$ and $a\*b=2\*n$, then by substituting $b$ by $2\*n/a$ in the first equation, we get $((a^{2}+(2\*n/a)^{2})-c^{2})\*a^{2} = 0$. We set $x=a$, $y=a\*c$. \bprog ? En = ellfromeqn((x^2 + (2*n/x)^2 - (y/x)^2)*x^2) %1 = [0, 0, 0, -16*n^2, 0] @eprog For example $23$ is congruent since the curve has a point of infinite order, namely: \bprog ? ellheegner( ellinit(subst(En, n, 23)) ) %2 = [168100/289, 68053440/4913] @eprog pari-2.17.2/src/functions/elliptic_curves/ellheegner0000644000175000017500000000207114567450071021225 0ustar billbillFunction: ellheegner Section: elliptic_curves C-Name: ellheegner Prototype: G Help: ellheegner(E): return a rational nontorsion point on the elliptic curve E assumed to be of rank 1. Doc: Let $E$ be an elliptic curve over the rationals, assumed to be of (analytic) rank $1$. This returns a nontorsion rational point on the curve, whose canonical height is equal to the product of the elliptic regulator by the analytic Sha. This uses the Heegner point method, described in Cohen GTM 239; the complexity is proportional to the product of the square root of the conductor and the height of the point (thus, it is preferable to apply it to strong Weil curves). \bprog ? E = ellinit([-157^2,0]); ? u = ellheegner(E); print(u[1], "\n", u[2]) 69648970982596494254458225/166136231668185267540804 538962435089604615078004307258785218335/67716816556077455999228495435742408 ? ellheegner(ellinit([0,1])) \\ E has rank 0 ! *** at top-level: ellheegner(E=ellinit *** ^-------------------- *** ellheegner: The curve has even analytic rank. @eprog pari-2.17.2/src/functions/elliptic_curves/ellak0000644000175000017500000000244114676526175020216 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 (assumes E is an integral model). Doc: computes the coefficient $a_{n}$ of the $L$-function of the elliptic curve $E/\Q$, i.e.~coefficients of a newform of weight 2 by the modularity theorem (\idx{Taniyama-Shimura-Weil conjecture}). $E$ must be an \kbd{ell} structure over $\Q$ as output by \kbd{ellinit}. $E$ must be given by an integral model, not necessarily minimal, although a minimal model will make the function faster. \bprog ? E = ellinit([1,-1,0,4,3]); ? ellak(E, 10) %2 = -3 ? e = ellchangecurve(E, [1/5,0,0,0]); \\ made not minimal at 5 ? ellak(e, 10) \\ wasteful but works %3 = -3 ? E = ellminimalmodel(e); \\ now minimal ? ellak(E, 5) %5 = -3 @eprog\noindent If the model is not minimal at a number of bad primes, then the function will be slower on those $n$ divisible by the bad primes. The speed should be comparable for other $n$: \bprog ? for(i=1,10^6, ellak(E,5)) time = 699 ms. ? for(i=1,10^6, ellak(e,5)) \\ 5 is bad, markedly slower time = 1,079 ms. ? for(i=1,10^5,ellak(E,5*i)) time = 1,477 ms. ? for(i=1,10^5,ellak(e,5*i)) \\ still slower but not so much on average time = 1,569 ms. @eprog pari-2.17.2/src/functions/elliptic_curves/ellpow0000644000175000017500000000026714567450071020422 0ustar billbillFunction: ellpow Section: elliptic_curves C-Name: ellmul Prototype: GGG Obsolete: 2012-06-06 Help: ellpow(E,z,n): deprecated alias for ellmul. Doc: deprecated alias for \kbd{ellmul}. pari-2.17.2/src/functions/elliptic_curves/ellpadicL0000644000175000017500000001104114676526175021013 0ustar billbillFunction: ellpadicL Section: elliptic_curves C-Name: ellpadicL Prototype: GGLDGD0,L,DG Help: ellpadicL(E,p,n,{s=0},{r=0},{D=1}): returns the value on a character of Z_{p}^* represented by an integer s or a vector [s1,s2] of the derivative of order r of the p-adic L-function of the elliptic curve E (twisted by D, if present). Doc: Returns the value (or $r$-th derivative) on a character $\chi^{s}$ of $\Z_{p}^{*}$ of the $p$-adic $L$-function of the elliptic curve $E/\Q$, twisted by $D$, given modulo $p^{n}$. \misctitle{Characters} The set of continuous characters of $\text{Gal}(\Q(\mu_{p^{\infty}})/ \Q)$ is identified to $\Z_{p}^{*}$ via the cyclotomic character $\chi$ with values in $\overline{\Q_{p}}^{*}$. Denote by $\tau:\Z_{p}^{*}\to\Z_{p}^{*}$ the Teichm\"uller character, with values in the $(p-1)$-th roots of $1$ for $p\neq 2$, and $\{-1,1\}$ for $p = 2$; finally, let $\langle\chi\rangle =\chi \tau^{-1}$, with values in $1 + 2p\Z_{p}$. In GP, the continuous character of $\text{Gal}(\Q(\mu_{p^{\infty}})/ \Q)$ given by $\langle\chi\rangle^{s_{1}} \tau^{s_{2}}$ is represented by the pair of integers $s=(s_{1},s_{2})$, with $s_{1} \in \Z_{p}$ and $s_{2} \bmod p-1$ for $p > 2$, (resp. mod $2$ for $p = 2$); $s$ may be also an integer, representing $(s,s)$ or $\chi^{s}$. \misctitle{The $p$-adic $L$ function} The $p$-adic $L$ function $L_{p}$ is defined on the set of continuous characters of $\text{Gal}(\Q(\mu_{p^{\infty}})/ \Q)$, as $\int_{\Z_{p}^{*}} \chi^{s} d \mu$ for a certain $p$-adic distribution $\mu$ on $\Z_{p}^{*}$. The derivative is given by $$L_{p}^{(r)}(E, \chi^{s}) = \int_{\Z_{p}^{*}} \log_{p}^{r}(a) \chi^{s}(a) d\mu(a).$$ More precisely: \item When $E$ has good supersingular reduction, $L_{p}$ takes its values in $D := H^{1}_{dR}(E/\Q)\otimes_{\Q} \Q_{p}$ and satisfies $$(1-p^{-1} F)^{-2} L_{p}(E, \chi^{0})= (L(E,1) / \Omega) \cdot \omega$$ where $F$ is the Frobenius, $L(E,1)$ is the value of the complex $L$ function at $1$, $\omega$ is the N\'eron differential and $\Omega$ the attached period on $E(\R)$. Here, $\chi^{0}$ represents the trivial character. The function returns the components of $L_{p}^{(r)}(E,\chi^{s})$ in the basis $(\omega, F \omega)$. \item When $E$ has ordinary good reduction, this method only defines the projection of $L_{p}(E,\chi^{s})$ on the $\alpha$-eigenspace, where $\alpha$ is the unit eigenvalue for $F$. This is what the function returns. We have $$(1- \alpha^{-1})^{-2} L_{p,\alpha}(E,\chi^{0})= L(E,1) / \Omega.$$ Two supersingular examples: \bprog ? cxL(e) = bestappr( ellL1(e) / e.omega[1] ); ? e = ellinit("17a1"); p=3; \\ supersingular, a3 = 0 ? L = ellpadicL(e,p,4); ? F = [0,-p;1,ellap(e,p)]; \\ Frobenius matrix in the basis (omega,F(omega)) ? (1-p^(-1)*F)^-2 * L / cxL(e) %5 = [1 + O(3^5), O(3^5)]~ \\ [1,0]~ ? e = ellinit("116a1"); p=3; \\ supersingular, a3 != 0~ ? L = ellpadicL(e,p,4); ? F = [0,-p; 1,ellap(e,p)]; ? (1-p^(-1)*F)^-2*L~ / cxL(e) %9 = [1 + O(3^4), O(3^5)]~ @eprog Good ordinary reduction: \bprog ? e = ellinit("17a1"); p=5; ap = ellap(e,p) %1 = -2 \\ ordinary ? L = ellpadicL(e,p,4) %2 = 4 + 3*5 + 4*5^2 + 2*5^3 + O(5^4) ? al = padicappr(x^2 - ap*x + p, ap + O(p^7))[1]; ? (1-al^(-1))^(-2) * L / cxL(e) %4 = 1 + O(5^4) @eprog Twist and Teichm\"uller: \bprog ? e = ellinit("17a1"); p=5; \\ ordinary \\ 2nd derivative at tau^1, twist by -7 ? ellpadicL(e, p, 4, [0,1], 2, -7) %2 = 2*5^2 + 5^3 + O(5^4) @eprog We give an example of non split multiplicative reduction (see \tet{ellpadicbsd} for more examples). \bprog ? e=ellinit("15a1"); p=3; n=5; ? L = ellpadicL(e,p,n) %2 = 2 + 3 + 3^2 + 3^3 + 3^4 + O(3^5) ? (1 - ellap(e,p))^(-1) * L / cxL(e) %3 = 1 + O(3^5) @eprog This function is a special case of \tet{mspadicL} and it also appears as the first term of \tet{mspadicseries}: \bprog ? e = ellinit("17a1"); p=5; ? L = ellpadicL(e,p,4) %2 = 4 + 3*5 + 4*5^2 + 2*5^3 + O(5^4) ? [M,phi] = msfromell(e, 1); ? Mp = mspadicinit(M, p, 4); ? mu = mspadicmoments(Mp, phi); ? mspadicL(mu) %6 = 4 + 3*5 + 4*5^2 + 2*5^3 + 2*5^4 + 5^5 + O(5^6) ? mspadicseries(mu) %7 = (4 + 3*5 + 4*5^2 + 2*5^3 + 2*5^4 + 5^5 + O(5^6)) + (3 + 3*5 + 5^2 + 5^3 + O(5^4))*x + (2 + 3*5 + 5^2 + O(5^3))*x^2 + (3 + 4*5 + 4*5^2 + O(5^3))*x^3 + (3 + 2*5 + O(5^2))*x^4 + O(x^5) @eprog\noindent These are more cumbersome than \kbd{ellpadicL} but allow to compute at different characters, or successive derivatives, or to twist by a quadratic character essentially for the cost of a single call to \kbd{ellpadicL} due to precomputations. pari-2.17.2/src/functions/elliptic_curves/ellformaldifferential0000644000175000017500000000166714760123736023457 0ustar billbillFunction: ellformaldifferential Section: elliptic_curves C-Name: ellformaldifferential Prototype: GDPDn Help: ellformaldifferential(E,{n=seriesprecision},{t='x}) : E elliptic curve, n integer. Returns n terms of the power series [f, g] such that omega = dx/(2y+a_1x+a_3) = f(t) dt and eta = x(t) * omega = g(t) dt in the local parameter t=-x/y. Doc:Let $\omega := dx / (2y+a_{1}x+a_{3})$ be the invariant differential form attached to the model $E$ of some elliptic curve (\kbd{ellinit} form), and $\eta := x(t)\omega$. Return $n$ terms (\tet{seriesprecision} by default) of $f(t),g(t)$ two power series in the formal parameter $t=-x/y$ such that $\omega = f(t) dt$, $\eta = g(t) dt$: $$f(t) = 1+a_{1} t + (a_{1}^{2} + a_{2}) t^{2} + \dots,\quad g(t) = t^{-2} +\dots $$ \bprog ? E = ellinit([-1,1/4]); [f,g] = ellformaldifferential(E,7,'t); ? f %2 = 1 - 2*t^4 + 3/4*t^6 + O(t^7) ? g %3 = t^-2 - t^2 + 1/2*t^4 + O(t^5) @eprog pari-2.17.2/src/functions/elliptic_curves/ellsaturation0000644000175000017500000000325014676526175022013 0ustar billbillFunction: ellsaturation C-Name: ellsaturation Section: elliptic_curves Prototype: GGLp Help: ellsaturation(E,V,B): let E be an elliptic curve over Q and V be a vector of independent rational points on E of infinite order that generate a subgroup G of E(Q) of finite index. Return a new set W of the same length that generate a subgroup H of E(Q) containing G and such that [E(Q):H] is not divisible by any prime number less than B. Doc: Let $E$ be an elliptic curve over $\Q$ and and $V$ be a set of independent non-torsion rational points on $E$ of infinite order that generate a subgroup $G$ of $E(\Q)$ of finite index. Return a new set $W$ of the same length that generate a subgroup $H$ of $E(\Q)$ containing $G$ and such that $[E(\Q):H]$ is not divisible by any prime number less than $B$. The running time is roughly quadratic in $B$. \bprog ? E = ellinit([0,0, 1, -7, 6]); ? [r,R,s,V] = ellrank(E) %2 = [3, 3, 0, [[-1,3], [-3,0], [11,35]]] ? matdet(ellheightmatrix(E, V)) %3 = 3.7542920288254557283540759015628405708 ? W = ellsaturation(E, V, 2) \\ index is now odd time = 1 ms. %4 = [[-1, 3], [-3, 0], [11, 35]] ? W = ellsaturation(E, W, 10) \\ index not divisible by p <= 10 %5 = [[1, -1], [2, -1], [0, -3]] time = 2 ms. ? W = ellsaturation(E, V, 100) \\ looks OK now time = 171 ms. %6 = [[1, -1], [2, -1], [0, -3]] ? matdet(ellheightmatrix(E,V)) %7 = 0.41714355875838396981711954461809339675 ? lfun(E,1,3)/3! / ellbsd(E) \\ conductor is small, check assuming BSD %8 = 0.41714355875838396981711954461809339675 @eprog Function: _ellQ_factorback_worker C-Name: ellQ_factorback_worker Section: programming/internals Prototype: GGGGU Help: worker for ellQ_factorback pari-2.17.2/src/functions/elliptic_curves/hyperellratpoints0000644000175000017500000000252514676526175022721 0ustar billbillFunction: hyperellratpoints Section: elliptic_curves C-Name: hyperellratpoints Prototype: GGD0,L, Help: hyperellratpoints(X,h,{flag=0}): X being a nonsingular hyperelliptic curve given by an rational model, return a vector containing the affine rational points on the curve of naive height less than h. If fl=1, stop as soon as a point is found. X can be given either by a squarefree polynomial P such that X:y^2=P(x) or by a vector [P,Q] such that X:y^2+Q(x)y=P(x) and Q^2+4P is squarefree. Doc: $X$ being a nonsingular hyperelliptic curve given by an rational model, return a vector containing the affine rational points on the curve of naive height less than $h$. If $\fl=1$, stop as soon as a point is found; return either an empty vector or a vector containing a single point. $X$ is given either by a squarefree polynomial $P$ such that $X: y^{2}=P(x)$ or by a vector $[P,Q]$ such that $X: y^{2}+Q(x)\*y=P(x)$ and $Q^{2}+4\*P$ is squarefree. \noindent The parameter $h$ can be \item an integer $H$: find the points $[n/d,y]$ whose abscissas $x = n/d$ have naive height (= $\max(|n|, d)$) less than $H$; \item a vector $[N,D]$ with $D\leq N$: find the points $[n/d,y]$ with $|n| \leq N$, $d \leq D$. \item a vector $[N,[D_{1},D_{2}]]$ with $D_{1}^{s} \tau^{i}) (\hat{L}^{(i), D}(\gamma-1)) = L_{p}\big(E, <\chi>^{s}\tau^{i} (D/.)\big).$$ \item When $E$ has good ordinary or bad multiplicative reduction at $p$. By Weierstrass's preparation theorem the series $\hat{L}^{(i), D}$ can be written $p^{\mu} (X^{\lambda} + p G(X))$ up to a $p$-adic unit, where $G(X)\in \Z_{p}[X]$. The function returns $[\lambda,\mu]$. \item When $E$ has good supersingular reduction, we define a sequence of polynomials $P_{n}$ in $\Q_{p}[X]$ of degree $< p^{n}$ (and bounded denominators), such that $$\hat{L}^{(i), D} \equiv P_{n} \varphi^{n+1}\omega_{E} - \xi_{n} P_{n-1}\varphi^{n+2}\omega_{E} \bmod \big((1+X)^{p^{n}}-1\big) \Q_{p}[X]\otimes D_{cris},$$ where $\xi_{n} = \kbd{polcyclo}(p^{n}, 1+X)$. Let $\lambda_{n},\mu_{n}$ be the invariants of $P_{n}$. We find that \item $\mu_{n}$ is nonnegative and decreasing for $n$ of given parity hence $\mu_{2n}$ tends to a limit $\mu^{+}$ and $\mu_{2n+1}$ tends to a limit $\mu^{-}$ (both conjecturally $0$). \item there exists integers $\lambda^{+}$, $\lambda^{-}$ in $\Z$ (denoted with a $\til$ in the reference below) such that $$ \lim_{n\to\infty} \lambda_{2n} + 1/(p+1) = \lambda^{+} \quad \text{and} \quad \lim_{n\to\infty} \lambda_{2n+1} + p/(p+1) = \lambda^{-}.$$ The function returns $[[\lambda^{+}, \lambda^{-}], [\mu^{+},\mu^{-}]]$. \noindent Reference: B. Perrin-Riou, Arithm\'etique des courbes elliptiques \`a r\'eduction supersinguli\`ere en $p$, \emph{Experimental Mathematics}, {\bf 12}, 2003, pp. 155-186. pari-2.17.2/src/functions/elliptic_curves/ellorder0000644000175000017500000000352114567450071020724 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 a number field or a finite field, 0 if nontorsion. The parameter o, if present, represents a nonzero multiple of the order of z. Doc: gives the order of the point $z$ on the elliptic curve $E$, defined over a finite field or a number field. Return (the impossible value) zero if the point has infinite order. \bprog ? E = ellinit([-157^2,0]); \\ the "157-is-congruent" curve ? P = [2,2]; ellorder(E, P) %2 = 2 ? P = ellheegner(E); ellorder(E, P) \\ infinite order %3 = 0 ? K = nfinit(polcyclo(11,t)); E=ellinit("11a3", K); T = elltors(E); ? ellorder(E, T.gen[1]) %5 = 25 ? E = ellinit(ellfromj(ffgen(5^10))); ? ellcard(E) %7 = 9762580 ? P = random(E); ellorder(E, P) %8 = 4881290 ? p = 2^160+7; E = ellinit([1,2], p); ? N = ellcard(E) %9 = 1461501637330902918203686560289225285992592471152 ? o = [N, factor(N)]; ? for(i=1,100, ellorder(E,random(E))) time = 260 ms. @eprog The parameter $o$, is now mostly useless, and kept for backward compatibility. If present, it represents a nonzero multiple of the order of $z$, see \secref{se:DLfun}; the preferred format for this parameter is \kbd{[ord, factor(ord)]}, where \kbd{ord} is the cardinality of the curve. It is no longer needed since PARI is now able to compute it over large finite fields (was restricted to small prime fields at the time this feature was introduced), \emph{and} caches the result in $E$ so that it is computed and factored only once. Modifying the last example, we see that including this extra parameter provides no improvement: \bprog ? o = [N, factor(N)]; ? for(i=1,100, ellorder(E,random(E),o)) time = 260 ms. @eprog Variant: The obsolete form \fun{GEN}{orderell}{GEN e, GEN z} should no longer be used. pari-2.17.2/src/functions/elliptic_curves/ellminimalmodel0000644000175000017500000000406714676526175022300 0ustar billbillFunction: ellminimalmodel Section: elliptic_curves C-Name: ellminimalmodel Prototype: GD& Help: ellminimalmodel(E,{&v}): determines whether the elliptic curve E defined over a number field admits a global minimal model. If so return it and sets v to the corresponding change of variable. Else return the (nonprincipal) Weierstrass class of E. Doc: Let $E$ be an \kbd{ell} structure over a number field $K$. This function determines whether $E$ admits a global minimal integral model. If so, it returns it and sets $v = [u,r,s,t]$ to the corresponding change of variable: the return value is identical to that of \kbd{ellchangecurve(E, v)}. Else return the (nonprincipal) Weierstrass class of $E$, i.e. the class of $\prod \goth{p}^{(v_{\goth{p}}{\Delta} - \delta_{\goth{p}}) / 12}$ where $\Delta = \kbd{E.disc}$ is the model's discriminant and $\goth{p}^{\delta_{\goth{p}}}$ is the local minimal discriminant. This function requires either that $E$ be defined over the rational field $\Q$ (with domain $D = 1$ in \kbd{ellinit}), in which case a global minimal model always exists, or over a number field given by a \var{bnf} structure. The Weierstrass class is given in \kbd{bnfisprincipal} format, i.e. in terms of the \kbd{K.gen} generators. The resulting model has integral coefficients and is everywhere minimal, the coefficients $a_{1}$ and $a_{3}$ are reduced modulo $2$ (in terms of the fixed integral basis \kbd{K.zk}) and $a_{2}$ is reduced modulo $3$. Over $\Q$, we further require that $a_{1}$ and $a_{3}$ be $0$ or $1$, that $a_{2}$ be $0$ or $\pm 1$ and that $u > 0$ in the change of variable: both the model and the change of variable $v$ are then unique.\sidx{minimal model} \bprog ? e = ellinit([6,6,12,55,233]); \\ over Q ? E = ellminimalmodel(e, &v); ? E[1..5] %3 = [0, 0, 0, 1, 1] ? v %4 = [2, -5, -3, 9] @eprog \bprog ? K = bnfinit(a^2-65); \\ over a nonprincipal number field ? K.cyc %2 = [2] ? u = Mod(8+a, K.pol); ? E = ellinit([1,40*u+1,0,25*u^2,0], K); ? ellminimalmodel(E) \\ no global minimal model exists over Z_K %6 = [1]~ @eprog pari-2.17.2/src/functions/elliptic_curves/ellminimaldisc0000644000175000017500000000055214567450071022103 0ustar billbillFunction: ellminimaldisc Section: elliptic_curves C-Name: ellminimaldisc Prototype: G Help: ellminimaldisc(E): E being an elliptic curve defined over a number field output by ellinit, return the minimal discriminant ideal of E. Doc: $E$ being an elliptic curve defined over a number field output by \kbd{ellinit}, return the minimal discriminant ideal of E. pari-2.17.2/src/functions/elliptic_curves/ellchangepointinv0000644000175000017500000000133314760123736022624 0ustar billbillFunction: ellchangepointinv Section: elliptic_curves C-Name: ellchangepointinv Prototype: GG Help: ellchangepointinv(x,v): change data on point or vector of points x on an elliptic curve according to v=[u,r,s,t], inverse of ellchangepoint. Doc: changes the coordinates of the point or vector of points $x$ using the inverse of the isomorphism attached to \kbd{v=[u,r,s,t]}, i.e.~if $x'$ and $y'$ are the old coordinates, then $x=u^{2}x'+r$, $y=u^{3}y'+su^{2}x'+t$ (inverse of \kbd{ellchangepoint}). \bprog ? E0 = ellinit([1,1]); P0 = [0,1]; v = [1,2,3,4]; ? E = ellchangecurve(E0, v); ? P = ellchangepoint(P0,v) %3 = [-2, 3] ? ellisoncurve(E, P) %4 = 1 ? ellchangepointinv(P,v) %5 = [0, 1] \\ we get back P0 @eprog pari-2.17.2/src/functions/elliptic_curves/ellj0000644000175000017500000000043113637407207020037 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.17.2/src/functions/elliptic_curves/ellperiods0000644000175000017500000000273214676526175021273 0ustar billbillFunction: ellperiods Section: elliptic_curves C-Name: ellperiods Prototype: GD0,L,p Help: ellperiods(w,{flag=0}): w describes a complex period lattice ([w1,w2] or an ellinit structure). Returns normalized periods [W1,W2] generating the same lattice such that tau := W1/W2 satisfies Im(tau) > 0 and lies in the standard fundamental domain for SL2. If flag is 1, the return value is [[W1,W2], [e1,e2]], where e1, e2 are the quasi-periods attached to [W1,W2], satisfying e2 W1 - e1 W2 = 2 Pi I. Doc: Let $w$ describe a complex period lattice ($w = [w_{1},w_{2}]$ or an \kbd{ellinit} structure). Returns normalized periods $[W_{1},W_{2}]$ generating the same lattice such that $\tau := W_{1}/W_{2}$ has positive imaginary part and lies in the standard fundamental domain for $\text{SL}_{2}(\Z)$. If $\fl = 1$, the function returns $[[W_{1},W_{2}], [\eta_{1},\eta_{2}]]$, where $\eta_{1}$ and $\eta_{2}$ are the quasi-periods attached to $[W_{1},W_{2}]$, satisfying $\eta_{2} W_{1} - \eta_{1} W_{2} = 2 i \pi$. The output of this function is meant to be used as the first argument given to ellwp, ellzeta, ellsigma or elleisnum. Quasi-periods are needed by ellzeta and ellsigma only. \bprog ? L = ellperiods([1,I],1); ? [w1,w2] = L[1]; [e1,e2] = L[2]; ? e2*w1 - e1*w2 %3 = 6.2831853071795864769252867665590057684*I ? ellzeta(L, 1/2 + 2*I) %4 = 1.5707963... - 6.283185307...*I ? ellzeta([1,I], 1/2 + 2*I) \\ same but less efficient %4 = 1.5707963... - 6.283185307...*I @eprog pari-2.17.2/src/functions/elliptic_curves/hyperellred0000644000175000017500000000261614676526175021451 0ustar billbillFunction: hyperellred Section: elliptic_curves C-Name: hyperellred Prototype: GD& Help: hyperellred(C,{&m}): C being a nonsingular integral hyperelliptic model of a curve, return an integral model of C with the same discriminant but small coefficients. C can be given either by a squarefree polynomial P such that C:y^2=P(x) or by a vector [P,Q] such that C:y^2+Q(x)*y=P(x) and Q^2+4P is squarefree. Doc: Let $C$ be a nonsingular integral hyperelliptic model of a curve of positive genus $g > 0$. Return an integral model of $C$ with the same discriminant but small coefficients, using Cremona-Stoll reduction. The optional argument $m$ is set to the mapping from the original model to the new one, given by a three-component vector \kbd{[1,[a,b;c,d],H]} such that $a*d-b*c=1$ and if $(x,y)$ is a point on $W$, the corresponding point $(X,Y)$ on $C$ is given by $$ X = (a*x + b) / (c*x + d), \quad Y = (y + H(x)) / (c*x + d)^{g+1}. $$ $C$ can be given either by a squarefree polynomial $P$ such that $C: y^{2} = P(x)$ or by a vector $[P,Q]$ such that $C: y^{2} + Q(x)\*y = P(x)$ and $Q^{2}+4\*P$ is squarefree. \bprog ? P = 1001*x^4 + 3704*x^3 + 5136*x^2 + 3163*x + 730; ? hyperellred(P, &m) %2 = [x^3 + 1, 0] ? hyperellchangecurve(P, m) %3 = [x^3 + 1, 0] @eprog Variant: Also available is \fun{GEN}{ZX_hyperellred}{GEN P, GEN *M} where $C: y^{2} = P(x)$ and *M is set to \kbd{[a,b;c,d]} pari-2.17.2/src/functions/elliptic_curves/ellisogeny0000644000175000017500000000203014676526175021272 0ustar billbillFunction: ellisogeny Section: elliptic_curves C-Name: ellisogeny Prototype: GGD0,L,DnDn Help: ellisogeny(E,G,{only_image=0},{x='x},{y='y}): compute the image and isogeny corresponding to the quotient of E by the subgroup G. Doc: Given an elliptic curve $E$, a finite subgroup $G$ of $E$ is given either as a generating point $P$ (for a cyclic $G$) or as a polynomial whose roots vanish on the $x$-coordinates of the nonzero elements of $G$ (general case and more efficient if available). This function returns the $[a_{1},a_{2},a_{3},a_{4},a_{6}]$ invariants of the quotient elliptic curve $E/G$ and (if \var{only\_image} is zero (the default)) a vector of rational functions $[f, g, h]$ such that the isogeny $E \to E/G$ is given by $(x,y) \mapsto (f(x)/h(x)^{2}, g(x,y)/h(x)^{3})$. \bprog ? E = ellinit([0,1]); ? elltors(E) %2 = [6, [6], [[2, 3]]] ? ellisogeny(E, [2,3], 1) \\ Weierstrass model for E/

%3 = [0, 0, 0, -135, -594] ? ellisogeny(E,[-1,0]) %4 = [[0,0,0,-15,22], [x^3+2*x^2+4*x+3, y*x^3+3*y*x^2-2*y, x+1]] @eprog pari-2.17.2/src/functions/elliptic_curves/hyperellminimalmodel0000644000175000017500000000302314676526175023337 0ustar billbillFunction: hyperellminimalmodel Section: elliptic_curves C-Name: hyperellminimalmodel Prototype: GD&DG Help: hyperellminimalmodel(C,{&m},{pr}): C being a nonsingular integral hyperelliptic model of a curve, return an integral model of C with minimal discriminant. If pr is given, it must be a list of primes and the model is then only garanteed minimal at the elements of pr. C can be given either by a squarefree polynomial P such that C:y^2=P(x) or by a vector [P,Q] such that C:y^2+Q(x)*y=P(x) and Q^2+4P is squarefree. Doc: $C$ being a nonsingular integral hyperelliptic model of a curve, return an integral model of $C$ with minimal discriminant. If $pr$ is given, it must be a list of primes and the model is then only garanteed minimal at the elements of $pr$. If present, $m$ is set to the mapping from the original model to the new one: a three-component vector $[e,[a,b;c,d],H]$ such that if $(x,y)$ is a point on $W$, the corresponding point on $C$ is given by $$ x_{C} = (a*x+b)/(c*x+d) $$ $$ y_{C} = (e*y+H(x))/(c*x+d)^{g+1} $$ where $g$ is the genus. $C$ can be given either by a squarefree polynomial $P$ such that $C: y^{2} = P(x)$ or by a vector $[P,Q]$ such that $C: y^{2} + Q(x)\*y = P(x)$ and $Q^{2}+4\*P$ is squarefree. \bprog ? W = [x^6+216*x^3+324,0]; ? D = hyperelldisc(W) %2 = 1828422898924853919744000 ? Wn = hyperellminimalmodel(W,&M) %3 = [2*x^6+18*x^3+1,x^3]; ? M %4 = [18, [3, 0; 0, 1], 9*x^3] ? hyperelldisc(Wn) %5 = 29530050606000 ? hyperellchangecurve(W, M) %6 = [2*x^6+18*x^3+1,x^3] @eprog pari-2.17.2/src/functions/elliptic_curves/elleta0000644000175000017500000000113314676526175020371 0ustar billbillFunction: elleta Section: elliptic_curves C-Name: elleta Prototype: Gp Help: elleta(w): w=[w1,w2], returns the vector [eta1,eta2] of quasi-periods attached to [w1,w2]. Doc: returns the quasi-periods $[\eta_{1},\eta_{2}]$ attached to the lattice basis $\var{w} = [\omega_{1}, \omega_{2}]$. Alternatively, \var{w} can be an elliptic curve $E$ as output by \kbd{ellinit}, in which case, the quasi periods attached 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.17.2/src/functions/elliptic_curves/ellordinate0000644000175000017500000000046313637407207021420 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.17.2/src/functions/elliptic_curves/ellrankinit0000644000175000017500000000111314567450071021423 0ustar billbillFunction: ellrankinit Section: elliptic_curves C-Name: ellrankinit Prototype: Gp Help: ellrankinit(E): if E is an elliptic curve over Q, initialize data for further calls to ellrank. Doc: if $E$ is an elliptic curve over $\Q$, initialize data to speed up further calls to \kbd{ellrank}. \bprog ? E = ellinit([0,2429469980725060,0,275130703388172136833647756388,0]); ? rk = ellrankinit(E); ? [r, R, s, P] = ellrank(rk) %3 = [12, 14, 0, [...]] ? [r, R, s, P] = ellrank(rk, 1, P) \\ more effort, using known points %4 = [14, 14, 0, [...]] \\ this time all points are found @eprog pari-2.17.2/src/functions/elliptic_curves/hyperellchangecurve0000644000175000017500000000153714676526175023172 0ustar billbillFunction: hyperellchangecurve Section: elliptic_curves C-Name: hyperellchangecurve Prototype: GG Help: hyperellchangecurve(C,m): C being a nonsingular hyperelliptic model of a curve, apply the change of coordinate given by m. C can be given either by a squarefree polynomial P such that C:y^2=P(x) or by a vector [P,Q] such that C:y^2+Q(x)*y=P(x) and Q^2+4P is squarefree. Doc: $C$ being a nonsingular hyperelliptic model of a curve, apply the change of coordinate given by $m = [e, [a,b;c,d], H]$. If $(x,y)$ is a point on the new model, the corresponding point $(X,Y)$ on $C$ is given by $$ X = (a*x + b) / (c*x + d), \quad Y = e (y + H(x)) / (c*x + d)^{g+1}. $$ $C$ can be given either by a squarefree polynomial $P$ such that $C: y^{2} = P(x)$ or by a vector $[P,Q]$ such that $C: y^{2} + Q(x)\*y = P(x)$ and $Q^{2}+4\*P$ is squarefree. pari-2.17.2/src/functions/elliptic_curves/ellratpoints0000644000175000017500000000151214567450071021632 0ustar billbillFunction: ellratpoints Section: elliptic_curves C-Name: ellratpoints Prototype: GGD0,L, Help: ellratpoints(E,h,{flag=0}): E being an rational model of an elliptic curve, return a vector containing the affine rational points on the curve of naive height less than h. If fl=1, stop as soon as a point is found. Doc: $E$ being an integral model of elliptic curve , return a vector containing the affine rational points on the curve of naive height less than $h$. If $\fl=1$, stop as soon as a point is found; return either an empty vector or a vector containing a single point. See \kbd{hyperellratpoints} for how $h$ can be specified. \bprog ? E=ellinit([-25,1]); ? ellratpoints(E,10) %2 = [[-5,1],[-5,-1],[-3,7],[-3,-7],[-1,5],[-1,-5], [0,1],[0,-1],[5,1],[5,-1],[7,13],[7,-13]] ? ellratpoints(E,10,1) %3 = [[-5,1]] @eprog pari-2.17.2/src/functions/elliptic_curves/elltwist0000644000175000017500000000303514676526175020775 0ustar billbillFunction: elltwist Section: elliptic_curves C-Name: elltwist Prototype: GDG Help: elltwist(E,{P}): returns an ell structure for the twist of the elliptic curve E by the quadratic extension defined by P (when P is a polynomial of degree 2) or quadpoly(P) (when P is an integer). If E is defined over a finite field, then P can be omitted. Doc: returns an \kbd{ell} structure (as given by \kbd{ellinit}) for the twist of the elliptic curve $E$ by the quadratic extension of the coefficient ring defined by $P$ (when $P$ is a polynomial) or \kbd{quadpoly(P)} when $P$ is an integer. If $E$ is defined over a finite field, then $P$ can be omitted, in which case a random model of the unique nontrivial twist is returned. If $E$ is defined over a number field, the model should be replaced by a minimal model (if one exists). The elliptic curve $E$ can be given in some of the formats allowed by \kbd{ellinit}: an \kbd{ell} structure, a $5$-component vector $[a_{1},a_{2},a_{3},a_{4},a_{6}]$ or a $2$-component vector $[a_{4},a_{6}]$. Twist by discriminant $-3$: \bprog ? elltwist([0,a2,0,a4,a6], -3)[1..5] %1 = [0, -3*a2, 0, 9*a4, -27*a6] ? elltwist([a4,a6], -3)[1..5] %2 = [0, 0, 0, 9*a4, -27*a6] @eprog Twist by the Artin-Schreier extension given by $x^{2}+x+T$ in characteristic $2$: \bprog ? lift(elltwist([a1,a2,a3,a4,a6]*Mod(1,2), x^2+x+T)[1..5]) %1 = [a1, a2+a1^2*T, a3, a4, a6+a3^2*T] @eprog Twist of an elliptic curve defined over a finite field: \bprog ? E = elltwist([1,7]*Mod(1,19)); lift([E.a4, E.a6]) %1 = [11, 12] @eprog pari-2.17.2/src/functions/elliptic_curves/ellmodulareqn0000644000175000017500000000435214676526175021775 0ustar billbillFunction: ellmodulareqn Section: elliptic_curves C-Name: ellmodulareqn Prototype: LDnDn Help: ellmodulareqn(N,{x},{y}): given a prime N < 500, return a vector [P, t] where P(x,y) is a modular equation of level N. This requires the package seadata. The equation is either of canonical type (t=0) or of Atkin type (t=1). Doc: given a prime $N < 500$, return a vector $[P,t]$ where $P(x,y)$ is a modular equation of level $N$, i.e.~a bivariate polynomial with integer coefficients; $t$ indicates the type of this equation: either \emph{canonical} ($t = 0$) or \emph{Atkin} ($t = 1$). This function requires the \kbd{seadata} package and its only use is to give access to the package contents. See \tet{polmodular} for a more general and more flexible function. Let $j$ be the $j$-invariant function. The polynomial $P$ satisfies the functional equation, $$ P(f,j) = P(f \mid W_{N}, j \mid W_{N}) = 0 $$ for some modular function $f = f_{N}$ (hand-picked for each fixed $N$ to minimize its size, see below), where $W_{N}(\tau) = -1 / (N\*\tau)$ is the Atkin-Lehner involution. These two equations allow to compute the values of the classical modular polynomial $\Phi_{N}$, such that $\Phi_{N}(j(\tau), j(N\tau)) = 0$, while being much smaller than the latter. More precisely, we have $j(W_{N}(\tau)) = j(N\*\tau)$; the function $f$ is invariant under $\Gamma_{0}(N)$ and also satisfies \item for Atkin type: $f \mid W_{N} = f$; \item for canonical type: let $s = 12/\gcd(12,N-1)$, then $f \mid W_{N} = N^{s} / f$. In this case, $f$ has a simple definition: $f(\tau) = N^{s} \* \big(\eta(N\*\tau) / \eta(\tau) \big)^{2\*s}$, where $\eta$ is Dedekind's eta function. The following GP function returns values of the classical modular polynomial by eliminating $f_{N}(\tau)$ in the above functional equation, for $N\leq 31$ or $N\in\{41,47,59,71\}$. \bprog classicaleqn(N, X='X, Y='Y)= { my([P,t] = ellmodulareqn(N), Q, d); if (poldegree(P,'y) > 2, error("level unavailable in classicaleqn")); if (t == 0, \\ Canonical my(s = 12/gcd(12,N-1)); Q = 'x^(N+1) * substvec(P,['x,'y],[N^s/'x,Y]); d = N^(s*(2*N+1)) * (-1)^(N+1); , \\ Atkin Q = subst(P,'y,Y); d = (X-Y)^(N+1)); polresultant(subst(P,'y,X), Q) / d; } @eprog pari-2.17.2/src/functions/elliptic_curves/elleisnum0000644000175000017500000000266614676526175021134 0ustar billbillFunction: elleisnum Section: elliptic_curves C-Name: elleisnum Prototype: GLD0,L,p Help: elleisnum(w,k,{flag=0}): k being an even positive integer, computes the numerical value of the Eisenstein series of weight k at the lattice w, as given by ellperiods. When flag is nonzero and k=4 or 6, this gives the elliptic invariants g2 or g3 with the correct normalization. Doc: $k$ being an even positive integer, computes the numerical value of the Eisenstein series of weight $k$ at the lattice $w$, as given by \tet{ellperiods}, namely $$ (2i \pi/\omega_{2})^{k} \Big(1 + 2/\zeta(1-k) \sum_{n\geq 1} n^{k-1}q^{n} / (1-q^{n})\Big), $$ where $q = \exp(2i\pi \tau)$ and $\tau:=\omega_{1}/\omega_{2}$ belongs to the complex upper half-plane. It is also possible to directly input $w = [\omega_{1},\omega_{2}]$, or an elliptic curve $E$ as given by \kbd{ellinit}. \bprog ? w = ellperiods([1,I]); ? elleisnum(w, 4) %2 = 2268.8726415508062275167367584190557607 ? elleisnum(w, 6) %3 = -3.977978632282564763 E-33 ? E = ellinit([1, 0]); ? elleisnum(E, 4) %5 = -48.000000000000000000000000000000000000 @eprog When \fl\ is nonzero 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$. \bprog ? g2 = elleisnum(E, 4, 1) %6 = -4.0000000000000000000000000000000000000 ? g3 = elleisnum(E, 6, 1) \\ ~ 0 %7 = 0.E-114 - 3.909948178422242682 E-57*I @eprog pari-2.17.2/src/functions/elliptic_curves/ellL10000644000175000017500000000245314676526175020102 0ustar billbillFunction: ellL1 Section: elliptic_curves C-Name: ellL1 Prototype: GD0,L,b Help: ellL1(E,{r=0}): returns the value at s=1 of the derivative of order r of the L-function of the elliptic curve E. Doc: returns the value at $s=1$ of the derivative of order $r$ of the $L$-function of the elliptic curve $E/\Q$. \bprog ? E = ellinit("11a1"); \\ order of vanishing is 0 ? ellL1(E) %2 = 0.2538418608559106843377589233 ? E = ellinit("389a1"); \\ order of vanishing is 2 ? ellL1(E) %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 ? E = ellinit("5077a1"); ellanalyticrank(E) time = 8 ms. %1 = [3, 10.3910994007158041] ? \p200 realprecision = 202 significant digits (200 digits displayed) ? ellL1(E, 3) time = 104 ms. %3 = 10.3910994007158041387518505103609170697263563756570092797@com$[\dots]$ @eprog\noindent Analogous and more general functionalities for $E$ defined over general number fields are available through \kbd{lfun}. pari-2.17.2/src/functions/elliptic_curves/ellisoncurve0000644000175000017500000000113214760123736021622 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.17.2/src/functions/elliptic_curves/elllocalred0000644000175000017500000000252514676526175021413 0ustar billbillFunction: elllocalred Section: elliptic_curves C-Name: elllocalred Prototype: GDG 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 $p$. $E$ must be an \kbd{ell} structure as output by \kbd{ellinit}, over $\Q_{\ell}$ ($p$ better left omitted, else equal to $\ell$) over $\Q$ ($p$ a rational prime) or a number field $K$ ($p$ a maximal ideal given by a \kbd{prid} structure). The result is a 4-component vector $[f,kod,v,c]$. Here $f$ is the exponent of $p$ in the arithmetic conductor of $E$, and $kod$ is the Kodaira type which is coded as follows: 1 means good reduction (type I$_{0}$), 2, 3 and 4 mean types II, III and IV respectively, $4+\nu$ with $\nu>0$ means type I$_{\nu}$; finally the opposite values $-1$, $-2$, etc.~refer to the starred types I$_{0}^{*}$, II$^{*}$, etc. The third component $v$ is itself a vector $[u,r,s,t]$ giving the coordinate changes done during the local reduction; $u = 1$ if and only if the given equation was already minimal at $p$. Finally, the last component $c$ is the local \idx{Tamagawa number} $c_{p}$. pari-2.17.2/src/functions/elliptic_curves/genus2red0000644000175000017500000001365714760123736021025 0ustar billbillFunction: genus2red Section: elliptic_curves C-Name: genus2red Prototype: GDG Help: genus2red(PQ,{p}): let PQ be a polynomial P, resp. a vector [P,Q] of polynomials, with rational coefficients. Determines the reduction at p > 2 of the (proper, smooth) hyperelliptic curve C/Q of genus 2 defined by y^2 = P, resp. y^2 + Q*y = P. More precisely, determines the special fiber X_p of the minimal regular model X of C over Z. Doc: Let $PQ$ be a polynomial $P$, resp. a vector $[P,Q]$ of polynomials, with rational coefficients. Determines the reduction at $p > 2$ of the (proper, smooth) genus~2 curve $C/\Q$, defined by the hyperelliptic equation $y^{2} = P(x)$, resp. $y^{2} + Q(x)*y = P(x)$. (The special fiber $X_{p}$ of the minimal regular model $X$ of $C$ over $\Z$.) If $p$ is omitted, determines the reduction type for all (odd) prime divisors of the discriminant. \noindent This function was rewritten from an implementation of Liu's algorithm by Cohen and Liu (1994), \kbd{genus2reduction-0.3}, see \url{https://www.math.u-bordeaux.fr/~liu/G2R/}. \misctitle{CAVEAT} The function interface may change: for the time being, it returns $[N,\var{FaN}, [P_{m}, Q_{m}], V]$ where $N$ is either the local conductor at $p$ or the global conductor, \var{FaN} is its factorization, $y^{2} +Q_{m}\*y= P_{m}$ defines a minimal model over $\Z$ and $V$ describes the reduction type at the various considered~$p$. Unfortunately, the program is not complete for $p = 2$, and we may return the odd part of the conductor only: this is the case if the factorization includes the (impossible) term $2^{-1}$; if the factorization contains another power of $2$, then this is the exact local conductor at $2$ and $N$ is the global conductor. \bprog ? default(debuglevel, 1); ? genus2red(x^6 + 3*x^3 + 63, 3) (potential) stable reduction: [1, []] reduction at p: [III{9}] page 184, [3, 3], f = 10 %1 = [59049, Mat([3, 10]), x^6 + 3*x^3 + 63, [3, [1, []], ["[III{9}] page 184", [3, 3]]]] ? [N, FaN, T, V] = genus2red(x^3-x^2-1, x^2-x); \\ X_1(13), global reduction p = 13 (potential) stable reduction: [5, [Mod(0, 13), Mod(0, 13)]] reduction at p: [I{0}-II-0] page 159, [], f = 2 ? N %3 = 169 ? FaN %4 = Mat([13, 2]) \\ in particular, good reduction at 2 ! ? T %5 = x^6 + 58*x^5 + 1401*x^4 + 18038*x^3 + 130546*x^2 + 503516*x + 808561 ? V %6 = [[13, [5, [Mod(0, 13), Mod(0, 13)]], ["[I{0}-II-0] page 159", []]]] @eprog\noindent We now first describe the format of the vector $V = V_{p}$ in the case where $p$ was specified (local reduction at~$p$): it is a triple $[p, \var{stable}, \var{red}]$. The component $\var{stable} = [\var{type}, \var{vecj}]$ contains information about the stable reduction after a field extension; depending on \var{type}s, the stable reduction is \item 1: smooth (i.e. the curve has potentially good reduction). The Jacobian $J(C)$ has potentially good reduction. \item 2: an elliptic curve $E$ with an ordinary double point; \var{vecj} contains $j$ mod $p$, the modular invariant of $E$. The (potential) semi-abelian reduction of $J(C)$ is the extension of an elliptic curve (with modular invariant $j$ mod $p$) by a torus. \item 3: a projective line with two ordinary double points. The Jacobian $J(C)$ has potentially multiplicative reduction. \item 4: the union of two projective lines crossing transversally at three points. The Jacobian $J(C)$ has potentially multiplicative reduction. \item 5: the union of two elliptic curves $E_{1}$ and $E_{2}$ intersecting transversally at one point; \var{vecj} contains their modular invariants $j_{1}$ and $j_{2}$, which may live in a quadratic extension of $\F_{p}$ and need not be distinct. The Jacobian $J(C)$ has potentially good reduction, isomorphic to the product of the reductions of $E_{1}$ and $E_{2}$. \item 6: the union of an elliptic curve $E$ and a projective line which has an ordinary double point, and these two components intersect transversally at one point; \var{vecj} contains $j$ mod $p$, the modular invariant of $E$. The (potential) semi-abelian reduction of $J(C)$ is the extension of an elliptic curve (with modular invariant $j$ mod $p$) by a torus. \item 7: as in type 6, but the two components are both singular. The Jacobian $J(C)$ has potentially multiplicative reduction. The component $\var{red} = [\var{NUtype}, \var{neron}]$ contains two data concerning the reduction at $p$ without any ramified field extension. The \var{NUtype} is a \typ{STR} describing the reduction at $p$ of $C$, following Namikawa-Ueno, \emph{The complete classification of fibers in pencils of curves of genus two}, Manuscripta Math., vol. 9, (1973), pages 143-186. The reduction symbol is followed by the corresponding page number or page range in this article. The second datum \var{neron} is the group of connected components (over an algebraic closure of $\F_{p}$) of the N\'eron model of $J(C)$, given as a finite abelian group (vector of elementary divisors). \smallskip If $p = 2$, the \var{red} component may be omitted altogether (and replaced by \kbd{[]}, in the case where the program could not compute it. When $p$ was not specified, $V$ is the vector of all $V_{p}$, for all considered $p$. \misctitle{Notes about Namikawa-Ueno types} \item A lower index is denoted between braces: for instance, \kbd{[I\obr2\cbr-II-5]} means \kbd{[I\_2-II-5]}. \item If $K$ and $K'$ are Kodaira symbols for singular fibers of elliptic curves, then \kbd{[$K$-$K'$-m]} and \kbd{[$K'$-$K$-m]} are the same. We define a total ordering on Kodaira symbol by fixing $\kbd{I} < \kbd{I*} < \kbd{II} < \kbd{II*}, \dots$. If the reduction type is the same, we order by the number of components, e.g. $\kbd{I}_{2} < \kbd{I}_{4}$, etc. Then we normalize our output so that $K \leq K'$. \item \kbd{[$K$-$K'$-$-1$]} is \kbd{[$K$-$K'$-$\alpha$]} in the notation of Namikawa-Ueno. \item The figure \kbd{[2I\_0-m]} in Namikawa-Ueno, page 159, must be denoted by \kbd{[2I\_0-(m+1)]}. pari-2.17.2/src/functions/elliptic_curves/ellisogenyapply0000644000175000017500000000170314676526175022346 0ustar billbillFunction: ellisogenyapply Section: elliptic_curves C-Name: ellisogenyapply Prototype: GG Help: ellisogenyapply(f,g): given an isogeny f and g either a point P (in the domain of f) or an isogeny, apply f to g: return the image of P under f or the composite isogeny f o g. Doc: Given an isogeny of elliptic curves $f:E'\to E$ (being the result of a call to \tet{ellisogeny}), apply $f$ to $g$: \item if $g$ is a point $P$ in the domain of $f$, return the image $f(P)$; \item if $g:E''\to E'$ is a compatible isogeny, return the composite isogeny $f \circ g: E''\to E$. \bprog ? one = ffgen(101, 't)^0; ? E = ellinit([6, 53, 85, 32, 34] * one); ? P = [84, 71] * one; ? ellorder(E, P) %4 = 5 ? [F, f] = ellisogeny(E, P); \\ f: E->F = E/

? ellisogenyapply(f, P) %6 = [0] ? F = ellinit(F); ? Q = [89, 44] * one; ? ellorder(F, Q) %9 = 2 ? [G, g] = ellisogeny(F, Q); \\ g: F->G = F/ ? gof = ellisogenyapply(g, f); \\ gof: E -> G @eprog pari-2.17.2/src/functions/elliptic_curves/ellneg0000644000175000017500000000027614557721031020362 0ustar billbillFunction: ellneg Section: elliptic_curves C-Name: ellneg Prototype: GG Help: ellneg(E,z): opposite of the point z on elliptic curve E. Doc: Opposite of the point $z$ on elliptic curve $E$. pari-2.17.2/src/functions/elliptic_curves/ellzeta0000644000175000017500000000273614676526175020575 0ustar billbillFunction: ellzeta Section: elliptic_curves C-Name: ellzeta Prototype: GDGp Help: ellzeta(w,{z='x}): computes the value at z of the Weierstrass Zeta function attached to the lattice w, as given by ellperiods(,1). Doc: Computes the value at $z$ of the Weierstrass $\zeta$ function attached to the lattice $w$ as given by \tet{ellperiods}$(,1)$: including quasi-periods is useful, otherwise there are recomputed from scratch for each new $z$. $$ \zeta(z, L) = \dfrac{1}{z} + z^{2}\sum_{\omega\in L^{*}} \dfrac{1}{\omega^{2}(z-\omega)}.$$ It is also possible to directly input $w = [\omega_{1},\omega_{2}]$, or an elliptic curve $E$ as given by \kbd{ellinit} ($w = \kbd{E.omega}$). The quasi-periods of $\zeta$, such that $$\zeta(z + a\omega_{1} + b\omega_{2}) = \zeta(z) + a\eta_{1} + b\eta_{2} $$ for integers $a$ and $b$ are obtained as $\eta_{i} = 2\zeta(\omega_{i}/2)$. Or using directly \tet{elleta}. \bprog ? w = ellperiods([1,I],1); ? ellzeta(w, 1/2) %2 = 1.5707963267948966192313216916397514421 ? E = ellinit([1,0]); ? ellzeta(E, E.omega[1]/2) %4 = 0.84721308479397908660649912348219163647 @eprog\noindent One can also compute the series expansion around $z = 0$ (the quasi-periods are useless in this case): \bprog ? E = ellinit([0,1]); ? ellzeta(E) \\ at 'x, implicitly at default seriesprecision %4 = x^-1 + 1/35*x^5 - 1/7007*x^11 + O(x^15) ? ellzeta(E, x + O(x^20)) \\ explicit precision %5 = x^-1 + 1/35*x^5 - 1/7007*x^11 + 1/1440257*x^17 + O(x^18) @eprog\noindent pari-2.17.2/src/functions/elliptic_curves/ellconvertname0000644000175000017500000000115413637407207022132 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.17.2/src/functions/elliptic_curves/ellbil0000644000175000017500000000031714567450071020357 0ustar billbillFunction: ellbil Section: elliptic_curves C-Name: bilhell Prototype: GGGp Obsolete: 2014-05-21 Help: ellbil(E,z1,z2): deprecated alias for ellheight(E,P,Q). Doc: deprecated alias for \kbd{ellheight(E,P,Q)}. pari-2.17.2/src/functions/elliptic_curves/elltors0000644000175000017500000000144714567450071020605 0ustar billbillFunction: elltors Section: elliptic_curves C-Name: elltors Prototype: G Help: elltors(E): torsion subgroup of elliptic curve E: order, structure, generators. Doc: if $E$ is an elliptic curve defined over a number field or a finite field, outputs the torsion subgroup of $E$ as a 3-component vector \kbd{[t,v1,v2]}, where \kbd{t} is the order of the torsion group, \kbd{v1} gives the structure of the torsion group as a product of cyclic groups (sorted by decreasing order), and \kbd{v2} gives generators for these cyclic groups. $E$ must be an \kbd{ell} structure as output by \kbd{ellinit}. \bprog ? E = ellinit([-1,0]); ? elltors(E) %1 = [4, [2, 2], [[0, 0], [1, 0]]] @eprog\noindent Here, the torsion subgroup is isomorphic to $\Z/2\Z \times \Z/2\Z$, with generators $[0,0]$ and $[1,0]$. pari-2.17.2/src/functions/elliptic_curves/elllog0000644000175000017500000000221714676526175020405 0ustar billbillFunction: elllog Section: elliptic_curves C-Name: elllog Prototype: GGGDG Help: elllog(E,P,G,{o}): return the discrete logarithm of the point P of the elliptic curve E in base G. If present, o represents the order of G. If not present, assume that G generates the curve. Doc: given two points $P$ and $G$ on the elliptic curve $E/\F_{q}$, returns the discrete logarithm of $P$ in base $G$, i.e. the smallest nonnegative integer $n$ such that $P = [n]G$. See \tet{znlog} for the limitations of the underlying discrete log algorithms. If present, $o$ represents the order of $G$, see \secref{se:DLfun}; the preferred format for this parameter is \kbd{[N, factor(N)]}, where $N$ is the order of $G$. If no $o$ is given, assume that $G$ generates the curve. The function also assumes that $P$ is a multiple of $G$. \bprog ? a = ffgen(ffinit(2,8),'a); ? E = ellinit([a,1,0,0,1]); \\ over F_{2^8} ? x = a^3; y = ellordinate(E,x)[1]; ? P = [x,y]; G = ellmul(E, P, 113); ? ord = [242, factor(242)]; \\ P generates a group of order 242. Initialize. ? ellorder(E, G, ord) %4 = 242 ? e = elllog(E, P, G, ord) %5 = 15 ? ellmul(E,G,e) == P %6 = 1 @eprog pari-2.17.2/src/functions/elliptic_curves/ellpadicheight0000644000175000017500000000650714676526175022103 0ustar billbillFunction: ellpadicheight Section: elliptic_curves C-Name: ellpadicheight0 Prototype: GGLGDG Help: ellpadicheight(E,p,n,P,{Q}): E elliptic curve/Q, P in E(Q), p prime, n an integer; returns the cyclotomic p-adic heights of P. Resp. the value of the attached bilinear form at (P,Q). Doc: cyclotomic $p$-adic height of the rational point $P$ on the elliptic curve $E$ (defined over $\Q$), given to $n$ $p$-adic digits. If the argument $Q$ is present, computes the value of the bilinear form $(h(P+Q)-h(P-Q)) / 4$. Let $D := H^{1}_{dR}(E) \otimes_{\Q} \Q_{p}$ be the $\Q_{p}$ vector space spanned by $\omega$ (invariant differential $dx/(2y+a_{1}x+a_{3})$ related to the given model) and $\eta = x \omega$. Then the cyclotomic $p$-adic height $h_{E}$ associates to $P\in E(\Q)$ an element $f \omega + g \eta$ in $D$. This routine returns the vector $[f, g]$ to $n$ $p$-adic digits. If $P\in E(\Q)$ is in the kernel of reduction mod $p$ and if its reduction at all finite places is non singular, then $g = -(\log_{E} P)^{2}$, where $\log_{E}$ is the logarithm for the formal group of $E$ at $p$. If furthermore the model is of the form $Y^{2} = X^{3} + a X + b$ and $P = (x,y)$, then $$ f = \log_{p}(\kbd{denominator}(x)) - 2 \log_{p}(\sigma(P))$$ where $\sigma(P)$ is given by \kbd{ellsigma}$(E,P)$. Recall (\emph{Advanced topics in the arithmetic of elliptic curves}, Theorem~3.2) that the local height function over the complex numbers is of the form $$ \lambda(z) = -\log (|\kbd{E.disc}|) / 6 + \Re(z \eta(z)) - 2 \log( \sigma(z)). $$ (N.B. our normalization for local and global heights is twice that of Silverman's). \bprog ? E = ellinit([1,-1,1,0,0]); P = [0,0]; ? ellpadicheight(E,5,3, P) %2 = [3*5 + 5^2 + 2*5^3 + O(5^4), 5^2 + 4*5^4 + O(5^5)] ? E = ellinit("11a1"); P = [5,5]; \\ torsion point ? ellpadicheight(E,19,6, P) %4 = [0, 0] ? E = ellinit([0,0,1,-4,2]); P = [-2,1]; ? ellpadicheight(E,3,3, P) %6 = [2*3^2 + 2*3^3 + 3^4 + O(3^5), 2*3^2 + 3^4 + O(3^5)] ? ellpadicheight(E,3,5, P, elladd(E,P,P)) %7 = [3^2 + 2*3^3 + O(3^7), 3^2 + 3^3 + 2*3^4 + 3^5 + O(3^7)] @eprog \item When $E$ has good ordinary reduction at $p$ or non split multiplicative reduction, the ``canonical'' $p$-adic height is given by \bprog s2 = ellpadics2(E,p,n); ellpadicheight(E, p, n, P) * [1,-s2]~ @eprog\noindent Since $s_{2}$ does not depend on $P$, it is preferable to compute it only once: \bprog ? E = ellinit("5077a1"); p = 5; n = 7; \\ rank 3 ? s2 = ellpadics2(E,p,n); ? M = ellpadicheightmatrix(E,p, n, E.gen) * [1,-s2]~; ? matdet(M) \\ p-adic regulator on the points in E.gen %4 = 5 + 5^2 + 4*5^3 + 2*5^4 + 2*5^5 + 2*5^6 + O(5^7) @eprog \item When $E$ has split multiplicative reduction at $p$ (Tate curve), the ``canonical'' $p$-adic height is given by \bprog Ep = ellinit(E[1..5], O(p^(n))); \\ E seen as a Tate curve over Qp [u2,u,q] = Ep.tate; ellpadicheight(E, p, n, P) * [1,-s2 + 1/log(q)/u2]]~ @eprog\noindent where $s_{2}$ is as above. For example, \bprog ? E = ellinit("91b1"); P =[-1, 3]; p = 7; n = 5; ? Ep = ellinit(E[1..5], O(p^(n))); ? s2 = ellpadics2(E,p,n); ? [u2,u,q] = Ep.tate; ? H = ellpadicheight(E,p, n, P) * [1,-s2 + 1/log(q)/u2]~ %5 = 2*7 + 7^2 + 5*7^3 + 6*7^4 + 2*7^5 + O(7^6) @eprog These normalizations are chosen so that $p$-adic BSD conjectures are easy to state, see \tet{ellpadicbsd}. pari-2.17.2/src/functions/elliptic_curves/ellnonsingularmultiple0000644000175000017500000000155214567450071023726 0ustar billbillFunction: ellnonsingularmultiple Section: elliptic_curves C-Name: ellnonsingularmultiple Prototype: GG Help: ellnonsingularmultiple(E,P): given E/Q and P in E(Q), returns the pair [R,n] where n is the least positive integer such that R = [n]P has everywhere good reduction. More precisely, its image in a minimal model is everywhere nonsingular. Doc: given an elliptic curve $E/\Q$ (more precisely, a model defined over $\Q$ of a curve) and a rational point $P \in E(\Q)$, returns the pair $[R,n]$, where $n$ is the least positive integer such that $R := [n]P$ has good reduction at every prime. More precisely, its image in a minimal model is everywhere nonsingular. \bprog ? e = ellinit("57a1"); P = [2,-2]; ? ellnonsingularmultiple(e, P) %2 = [[1, -1], 2] ? e = ellinit("396b2"); P = [35, -198]; ? [R,n] = ellnonsingularmultiple(e, P); ? n %5 = 12 @eprog pari-2.17.2/src/functions/elliptic_curves/ellinit0000644000175000017500000001160614676526175020571 0ustar billbillFunction: ellinit Section: elliptic_curves C-Name: ellinit Prototype: GDGp Help: ellinit(x,{D=1}): let x be a vector [a1,a2,a3,a4,a6], or [a4,a6] if a1=a2=a3=0, defining the curve Y^2 + a1.XY + a3.Y = X^3 + a2.X^2 + a4.X + a6; x can also be a string, in which case the curve with matching name is retrieved from the elldata database, if available. This function initializes an elliptic curve over the domain D (inferred from coefficients if omitted). Description: (gen, gen, small):ell:prec ellinit($1, $2, $prec) Doc: initialize an \tet{ell} structure, attached to the elliptic curve $E$. $E$ is either \item a $5$-component vector $[a_{1},a_{2},a_{3},a_{4},a_{6}]$ defining the elliptic curve with Weierstrass equation $$ Y^{2} + a_{1} XY + a_{3} Y = X^{3} + a_{2} X^{2} + a_{4} X + a_{6}, $$ \item a $2$-component vector $[a_{4},a_{6}]$ defining the elliptic curve with short Weierstrass equation $$ Y^{2} = X^{3} + a_{4} X + a_{6}, $$ \item a single-component vector $[j]$ giving the $j$-invariant for the curve, with the same coefficients as given by \kbd{ellfromj}. \item a character string in Cremona's notation, e.g. \kbd{"11a1"}, in which case the curve is retrieved from the \tet{elldata} database if available. The optional argument $D$ describes the domain over which the curve is defined: \item the \typ{INT} $1$ (default): the field of rational numbers $\Q$. \item a \typ{INT} $p$, where $p$ is a prime number: the prime finite field $\F_{p}$. \item an \typ{INTMOD} \kbd{Mod(a, p)}, where $p$ is a prime number: the prime finite field $\F_{p}$. \item a \typ{FFELT}, as returned by \tet{ffgen}: the corresponding finite field $\F_{q}$. \item a \typ{PADIC}, $O(p^{n})$: the field $\Q_{p}$, where $p$-adic quantities will be computed to a relative accuracy of $n$ digits. We advise to input a model defined over $\Q$ for such curves. In any case, if you input an approximate model with \typ{PADIC} coefficients, it will be replaced by a lift to $\Q$ (an exact model ``close'' to the one that was input) and all quantities will then be computed in terms of this lifted model, at the given accuracy. \item a \typ{REAL} $x$: the field $\C$ of complex numbers, where floating point quantities are by default computed to a relative accuracy of \kbd{precision}$(x)$. If no such argument is given, the value of \kbd{realprecision} at the time \kbd{ellinit} is called will be used. \item a number field $K$, given by a \kbd{nf} or \kbd{bnf} structure; a \kbd{bnf} is required for \kbd{ellminimalmodel}. \item a prime ideal $\goth{p}$, given by a \kbd{prid} structure; valid if $x$ is a curve defined over a number field $K$ and the equation is integral and minimal at $\goth{p}$. This argument $D$ is indicative: the curve coefficients are checked for compatibility, possibly changing $D$; for instance if $D = 1$ and an \typ{INTMOD} is found. If inconsistencies are detected, an error is raised: \bprog ? ellinit([1 + O(5), 1], O(7)); *** at top-level: ellinit([1+O(5),1],O *** ^-------------------- *** ellinit: inconsistent moduli in ellinit: 7 != 5 @eprog\noindent If the curve coefficients are too general to fit any of the above domain categories, only basic operations, such as point addition, will be supported later. If the curve (seen over the domain $D$) is singular, fail and return an empty vector $[]$. \bprog ? E = ellinit([0,0,0,0,1]); \\ y^2 = x^3 + 1, over Q ? E = ellinit([0,1]); \\ the same curve, short form ? E = ellinit("36a1"); \\ sill the same curve, Cremona's notations ? E = ellinit([0]); \\ a curve of j-invariant 0 ? E = ellinit([0,1], 2) \\ over F2: singular curve %4 = [] ? E = ellinit(['a4,'a6] * Mod(1,5)); \\ over F_5[a4,a6], basic support ! @eprog\noindent Note that the given curve of $j$-invariant $0$ happens to be \kbd{36a1} but a priori any model for an arbitrary twist could have been returned. See \kbd{ellfromj}. The result of \tet{ellinit} is an \tev{ell} structure. It contains at least the following information in its components: % $$ a_{1},a_{2},a_{3},a_{4},a_{6},b_{2},b_{4},b_{6},b_{8},c_{4},c_{6}, \Delta,j.$$ % All are accessible via member functions. In particular, the discriminant is \kbd{$E$.disc}, and the $j$-invariant is \kbd{$E$.j}. \bprog ? E = ellinit([a4, a6]); ? E.disc %2 = -64*a4^3 - 432*a6^2 ? E.j %3 = -6912*a4^3/(-4*a4^3 - 27*a6^2) @eprog Further components contain domain-specific data, which are in general dynamic: only computed when needed, and then cached in the structure. \bprog ? E = ellinit([2,3], 10^60+7); \\ E over F_p, p large ? ellap(E) time = 4,440 ms. %2 = -1376268269510579884904540406082 ? ellcard(E); \\ now instantaneous ! time = 0 ms. ? ellgenerators(E); time = 5,965 ms. ? ellgenerators(E); \\ second time instantaneous time = 0 ms. @eprog See the description of member functions related to elliptic curves at the beginning of this section. pari-2.17.2/src/functions/elliptic_curves/ellheight0000644000175000017500000000207414567450071021063 0ustar billbillFunction: ellheight Section: elliptic_curves C-Name: ellheight0 Prototype: GDGDGp Help: ellheight(E,{P},{Q}): Faltings height of the curve E, resp. canonical height of the point P on elliptic curve E, resp. the value of the attached bilinear form at (P,Q). Doc: Let $E$ be an elliptic curve defined over $K = \Q$ or a number field, as output by \kbd{ellinit}; it needs not be given by a minimal model although the computation will be faster if it is. \item Without arguments $P,Q$, returns the Faltings height of the curve $E$ using Deligne normalization. For a rational curve, the normalization is such that the function returns \kbd{-(1/2)*log(ellminimalmodel(E).area)}. \item If the argument $P \in E(K)$ is present, returns the global N\'eron-Tate height $h(P)$ of the point, using the normalization in Cremona's \emph{Algorithms for modular elliptic curves}. \item If the argument $Q \in E(K)$ is also present, computes the value of the bilinear form $(h(P+Q)-h(P-Q)) / 4$. Variant: Also available is \fun{GEN}{ellheight}{GEN E, GEN P, long prec} ($Q$ omitted). pari-2.17.2/src/functions/elliptic_curves/ellpadicfrobenius0000644000175000017500000000163214702762523022606 0ustar billbillFunction: ellpadicfrobenius Section: elliptic_curves C-Name: ellpadicfrobenius Prototype: GUL Help: ellpadicfrobenius(E,p,n): matrix of the Frobenius at p>2 in the standard basis of H^1_dR(E) to absolute p-adic precision p^n. Doc: If $p>2$ is a prime and $E$ is an elliptic curve on $\Q$ with good reduction at $p$, return the matrix of the Frobenius endomorphism $\varphi$ on the crystalline module $D_{p}(E)= \Q_{p} \otimes H^{1}_{dR}(E/\Q)$ with respect to the basis of the given model $(\omega, \eta=x\*\omega)$, where $\omega = dx/(2\*y+a_{1}\*x+a_{3})$ is the invariant differential. The characteristic polynomial of $\varphi$ is $x^{2} - a_{p}\*x + p$. The matrix is computed to absolute $p$-adic precision $p^{n}$. \bprog ? E = ellinit([1,-1,1,0,0]); ? F = ellpadicfrobenius(E,5,3); ? lift(F) %3 = [120 29] [ 55 5] ? charpoly(F) %4 = x^2 + O(5^3)*x + (5 + O(5^3)) ? ellap(E, 5) %5 = 0 @eprog pari-2.17.2/src/functions/elliptic_curves/ellsub0000644000175000017500000000036114557721031020375 0ustar billbillFunction: ellsub Section: elliptic_curves C-Name: ellsub Prototype: GGG Help: ellsub(E,z1,z2): difference of the points z1 and z2 on elliptic curve E. Doc: difference of the points $z1$ and $z2$ on the elliptic curve corresponding to $E$. pari-2.17.2/src/functions/elliptic_curves/elllseries0000644000175000017500000000134614567450071021262 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. Obsolete: 2016-08-08 Doc: This function is deprecated, use \kbd{lfun(E,s)} instead. $E$ being an elliptic curve, given by an arbitrary model over $\Q$ as output by \kbd{ellinit}, this function computes the value of the $L$-series of $E$ at the (complex) point $s$. This function uses an $O(N^{1/2})$ algorithm, where $N$ is the conductor. The optional parameter $A$ fixes a cutoff point for the integral and is best left omitted; the result must be independent of $A$, up to \kbd{realprecision}, so this allows to check the function's accuracy. pari-2.17.2/src/functions/elliptic_curves/ellcard0000644000175000017500000000335414760123736020526 0ustar billbillFunction: ellcard Section: elliptic_curves C-Name: ellcard Prototype: GDG Help: ellcard(E,{p}): given an elliptic curve E defined over a finite field Fq, return the order of the group E(Fq); for other fields of definition K, p must define a finite residue field, (p prime for K = Qp or Q; p a maximal ideal for K a number field), return the order of the (nonsingular) reduction of E. Doc: Let \kbd{E} be an \kbd{ell} structure as output by \kbd{ellinit}, attached to an elliptic curve $E/K$. If $K = \F_{q}$ is finite, return the order of the group $E(\F_{q})$. \bprog ? E = ellinit([-3,1], 5); ellcard(E) %1 = 7 ? t = ffgen(3^5,'t); E = ellinit([t,t^2+1]); ellcard(E) %2 = 217 @eprog\noindent For other fields of definition and $p$ defining a finite residue field $\F_{q}$, return the order of the reduction of $E$: the argument $p$ is best left omitted if $K = \Q_{\ell}$ (else we must have $p = \ell$) and must be a prime number ($K = \Q$) or prime ideal ($K$ a general number field) with residue field $\F_{q}$ otherwise. The equation need not be minimal or even integral at $p$; of course, a minimal model will be more efficient. The function considers the group of nonsingular points of the reduction of a minimal model of the curve at $p$, so also makes sense when the curve has bad reduction. \bprog ? E = ellinit([-3,1]); ? factor(E.disc) %2 = [2 4] [3 4] ? ellcard(E, 5) \\ as above ! %3 = 7 ? ellcard(E, 2) \\ additive reduction %4 = 2 @eprog When the characteristic of the finite field is large, the availability of the \kbd{seadata} package will speed the computation. See also \tet{ellap} for the list of implemented algorithms. Variant: Also available is \fun{GEN}{ellcard}{GEN E, GEN p} where $p$ is not \kbd{NULL}. pari-2.17.2/src/functions/elliptic_curves/ellsigma0000644000175000017500000000220214676526175020716 0ustar billbillFunction: ellsigma Section: elliptic_curves C-Name: ellsigma Prototype: GDGD0,L,p Help: ellsigma(L,{z='x},{flag=0}): computes the value at z of the Weierstrass sigma function attached to the lattice L, as given by ellperiods(,1). If flag = 1, returns an arbitrary determination of the logarithm of sigma. Doc: Computes the value at $z$ of the Weierstrass $\sigma$ function attached to the lattice $L$ as given by \tet{ellperiods}$(,1)$: including quasi-periods is useful, otherwise there are recomputed from scratch for each new $z$. $$ \sigma(z, L) = z \prod_{\omega\in L^{*}} \left(1 - \dfrac{z}{\omega}\right) e^{\dfrac{z}{\omega} + \dfrac{z^{2}}{2\omega^{2}}}.$$ It is also possible to directly input $L = [\omega_{1},\omega_{2}]$, or an elliptic curve $E$ as given by \kbd{ellinit} ($L = \kbd{E.omega}$). \bprog ? w = ellperiods([1,I], 1); ? ellsigma(w, 1/2) %2 = 0.47494937998792065033250463632798296855 ? E = ellinit([1,0]); ? ellsigma(E) \\ at 'x, implicitly at default seriesprecision %4 = x + 1/60*x^5 - 1/10080*x^9 - 23/259459200*x^13 + O(x^17) @eprog If $\fl=1$, computes an arbitrary determination of $\log(\sigma(z))$. pari-2.17.2/src/functions/elliptic_curves/ellidentify0000644000175000017500000000131514567450071021423 0ustar billbillFunction: ellidentify Section: elliptic_curves C-Name: ellidentify Prototype: G Help: ellidentify(E): look up the elliptic curve E in the elldata database and return [[N, M, ...], C] where N is the name of the curve in Cremona's database, M the minimal model and C the change of coordinates (see ellchangecurve). Doc: look up the elliptic curve $E$, defined by an arbitrary model over $\Q$, in the \tet{elldata} database. Return \kbd{[[N, M, G], C]} where $N$ is the curve name in Cremona's elliptic curve database, $M$ is the minimal model, $G$ is a $\Z$-basis of the free part of the \idx{Mordell-Weil group} $E(\Q)$ and $C$ is the change of coordinates from $E$ to $M$, suitable for \kbd{ellchangecurve}. pari-2.17.2/src/functions/elliptic_curves/ellan0000644000175000017500000000153414676526175020223 0ustar billbillFunction: ellan Section: elliptic_curves C-Name: ellan Prototype: GL Help: ellan(E,n): computes the first n Fourier coefficients of the L-function of the elliptic curve E defined over a number field. Doc: computes the vector of the first $n$ Fourier coefficients $a_{k}$ corresponding to the elliptic curve $E$ defined over a number field. If $E$ is defined over $\Q$, the curve may be given by an arbitrary model, not necessarily minimal, although a minimal model will make the function faster. Over a more general number field, the model must be locally minimal at all primes above $2$ and $3$. Variant: Also available is \fun{GEN}{ellanQ_zv}{GEN e, long n}, which returns a \typ{VECSMALL} instead of a \typ{VEC}, saving on memory. Function: _direllnf_worker Section: programming/internals C-Name: direllnf_worker Prototype: GUG Help: ellan worker pari-2.17.2/src/functions/elliptic_curves/ellpointtoz0000644000175000017500000000616514676526175021520 0ustar billbillFunction: ellpointtoz Section: elliptic_curves C-Name: zell Prototype: GGp Help: ellpointtoz(E,P): lattice point z corresponding to the point P on the elliptic curve E. Doc: if $E/\C \simeq \C/\Lambda$ is a complex elliptic curve ($\Lambda = \kbd{E.omega}$), computes a complex number $z$, well-defined modulo the lattice $\Lambda$, corresponding to the point $P$; i.e.~such that $P = [\wp_{\Lambda}(z),\wp'_{\Lambda}(z)]$ satisfies the equation $$y^{2} = 4x^{3} - g_{2} x - g_{3},$$ where $g_{2}$, $g_{3}$ are the elliptic invariants. If $E$ is defined over $\R$ and $P\in E(\R)$, we have more precisely, $0 \leq \Re(t) < w1$ and $0 \leq \Im(t) < \Im(w2)$, where $(w1,w2)$ are the real and complex periods of $E$. \bprog ? E = ellinit([0,1]); P = [2,3]; ? z = ellpointtoz(E, P) %2 = 3.5054552633136356529375476976257353387 ? ellwp(E, z) %3 = 2.0000000000000000000000000000000000000 ? ellztopoint(E, z) - P %4 = [2.548947057811923643 E-57, 7.646841173435770930 E-57] ? ellpointtoz(E, [0]) \\ the point at infinity %5 = 0 @eprog If $E$ is defined over a general number field, the function returns the values corresponding to the various complex embeddings of the curve and of the point, in the same order as \kbd{E.nf.roots}: \bprog ? E=ellinit([-22032-15552*x,0], nfinit(x^2-2)); ? P=[-72*x-108,0]; ? ellisoncurve(E,P) %3 = 1 ? ellpointtoz(E,P) %4 = [-0.52751724240790530394437835702346995884*I, -0.090507650025885335533571758708283389896*I] ? E.nf.roots %5 = [-1.4142135623730950488016887242096980786, \\ x-> -sqrt(2) 1.4142135623730950488016887242096980786] \\ x-> sqrt(2) @eprog If $E/\Q_{p}$ has multiplicative reduction, then $E/\bar{\Q_{p}}$ is analytically isomorphic to $\bar{\Q}_{p}^{*}/q^{\Z}$ (Tate curve) for some $p$-adic integer $q$. The behavior is then as follows: \item If the reduction is split ($E.\kbd{tate[2]}$ is a \typ{PADIC}), we have an isomorphism $\phi: E(\Q_{p}) \simeq \Q_{p}^{*}/q^{\Z}$ and the function returns $\phi(P)\in \Q_{p}$. \item If the reduction is \emph{not} split ($E.\kbd{tate[2]}$ is a \typ{POLMOD}), we only have an isomorphism $\phi: E(K) \simeq K^{*}/q^{\Z}$ over the unramified quadratic extension $K/\Q_{p}$. In this case, the output $\phi(P)\in K$ is a \typ{POLMOD}; the function is not fully implemented in this case and may fail with a ``$u$ not in $\Q_{p}$'' exception: \bprog ? E = ellinit([0,-1,1,0,0], O(11^5)); P = [0,0]; ? [u2,u,q] = E.tate; type(u) \\ split multiplicative reduction %2 = "t_PADIC" ? ellmul(E, P, 5) \\ P has order 5 %3 = [0] ? z = ellpointtoz(E, [0,0]) %4 = 3 + 11^2 + 2*11^3 + 3*11^4 + 6*11^5 + 10*11^6 + 8*11^7 + O(11^8) ? z^5 %5 = 1 + O(11^9) ? E = ellinit(ellfromj(1/4), O(2^6)); x=1/2; y=ellordinate(E,x)[1]; ? z = ellpointtoz(E,[x,y]); \\ t_POLMOD of t_POL with t_PADIC coeffs ? liftint(z) \\ lift all p-adics %8 = Mod(8*u + 7, u^2 + 437) ? x=33/4; y=ellordinate(E,x)[1]; z = ellpointtoz(E,[x,y]) *** at top-level: ...;y=ellordinate(E,x)[1];z=ellpointtoz(E,[x,y]) *** ^-------------------- *** ellpointtoz: sorry, ellpointtoz when u not in Qp is not yet implemented. @eprog pari-2.17.2/src/functions/elliptic_curves/ellsupersingularj0000644000175000017500000000201214676526175022672 0ustar billbillFunction: ellsupersingularj Section: elliptic_curves C-Name: ellsupersingularj Prototype: G Help: ellsupersingularj(p): return a random supersingular j-invariant defined over F_p^2 if p is prime number, over the (finite) field of definition of p otherwise Doc: return a random supersingular $j$-invariant defined over $\F_{p}^{2}$ as a \typ{FFELT} in the variable \kbd{w}, if $p$ is a prime number, or over the field of definition of $p$ if $p$ is a \typ{FFELT}. The field must be of even degree. The random distribution is close to uniform except when $0$ or $1728$ are supersingular $j$-invariants, in which case they are less likely to be returned. This bias becomes negligible as $p$ grows. \bprog ? j = ellsupersingularj(1009) %1 = 12*w+295 ? ellissupersingular(j) %2 = 1 ? a = ffgen([1009,2],'a); ? j = ellsupersingularj(a) %4 = 867*a+721 ? ellissupersingular(j) %5 = 1 ? E = ellinit([j]); ? F = elltwist(E); ? ellissupersingular(F) %8 = 1 ? ellap(E) %9 = 2018 ? ellap(F) %10 = -2018 @eprog pari-2.17.2/src/functions/elliptic_curves/elltamagawa0000644000175000017500000000124114676526175021402 0ustar billbillFunction: elltamagawa Section: elliptic_curves C-Name: elltamagawa Prototype: G Help: elltamagawa(E): E being an elliptic curve over a number field, returns the global Tamagawa number of the curve. Doc: The object $E$ being an elliptic curve over a number field, returns the global Tamagawa number of the curve (including the factor at infinite places). \bprog ? e = ellinit([1, -1, 1, -3002, 63929]); \\ curve "90c6" from elldata ? elltamagawa(e) %2 = 288 ? [elllocalred(e,p)[4] | p<-[2,3,5]] %3 = [6, 4, 6] ? vecprod(%) \\ since e.disc > 0 the factor at infinity is 2 %4 = 144 ? ellglobalred(e)[4] \\ product without the factor at infinity %5 = 144 @eprog pari-2.17.2/src/functions/elliptic_curves/ellisdivisible0000644000175000017500000000227714676526175022140 0ustar billbillFunction: ellisdivisible Section: elliptic_curves C-Name: ellisdivisible Prototype: lGGGD& Help: ellisdivisible(E,P,n,{&Q}): given E/K and P in E(K), checks whether P = [n]R for some R in E(K) and sets Q to one such R if so; the integer n >= 0 may be given as ellxn(E,n). Doc: given $E/K$ a number field and $P$ in $E(K)$ return $1$ if $P = [n]R$ for some $R$ in $E(K)$ and set $Q$ to one such $R$; and return $0$ otherwise. \bprog ? K = nfinit(polcyclo(11,t)); ? E = ellinit([0,-1,1,0,0], K); ? P = [0,0]; ? ellorder(E,P) %4 = 5 ? ellisdivisible(E,P,5, &Q) %5 = 1 ? lift(Q) %6 = [-t^7-t^6-t^5-t^4+1, -t^9-2*t^8-2*t^7-3*t^6-3*t^5-2*t^4-2*t^3-t^2-1] ? ellorder(E, Q) %7 = 25 @eprog\noindent We use a fast multimodular algorithm over $\Q$ whose complexity is essentially independent of $n$ (polynomial in $\log n$). Over number fields, we compute roots of division polynomials and the algebraic complexity of the underlying algorithm is in $O(p^{4})$, where $p$ is the largest prime divisor of $n$. The integer $n \geq 0$ may be given as \kbd{ellxn(E,n)}, if many points need to be tested; this provides a modest speedup over number fields but is likely to slow down the algorithm over $\Q$. pari-2.17.2/src/functions/elliptic_curves/ellformalexp0000644000175000017500000000131314676526175021615 0ustar billbillFunction: ellformalexp Section: elliptic_curves C-Name: ellformalexp Prototype: GDPDn Help: ellformalexp(E,{n=seriesprecision},{z='x}): E elliptic curve, returns n terms of the formal elliptic exponential on E as a series in z. Doc: The elliptic formal exponential \kbd{Exp} attached to $E$ is the isomorphism from the formal additive law to the formal group of $E$. It is normalized so as to be the inverse of the elliptic logarithm (see \tet{ellformallog}): $\kbd{Exp} \circ L = \Id$. Return $n$ terms of this power series: \bprog ? E=ellinit([-1,1/4]); Exp = ellformalexp(E,10,'z) %1 = z + 2/5*z^5 - 3/28*z^7 + 2/15*z^9 + O(z^11) ? L = ellformallog(E,10,'t); ? subst(Exp,z,L) %3 = t + O(t^11) @eprog pari-2.17.2/src/functions/elliptic_curves/ellxn0000644000175000017500000000171614676526175020254 0ustar billbillFunction: ellxn Section: elliptic_curves C-Name: ellxn Prototype: GLDn Help: ellxn(E,n,{v='x}): return polynomials [A,B] in the variable v such that x([n]P) = (A/B)(t) for any P = [t,u] on E outside of n-torsion. Doc: For any affine point $P = (t,u)$ on the curve $E$, we have $$[n]P = (\phi_{n}(P)\psi_{n}(P) : \omega_{n}(P) : \psi_{n}(P)^{3})$$ for some $\phi_{n},\omega_{n},\psi_{n}$ in $\Z[a_{1},a_{2},a_{3},a_{4},a_{6}][t,u]$ modulo the curve equation. This function returns a pair $[A,B]$ of polynomials in $\Z[a_{1},a_{2},a_{3},a_{4},a_{6}][v]$ such that $[A(t),B(t)] = [\phi_{n}(P),\psi_{n}(P)^{2}]$ in the function field of $E$, whose quotient give the abscissa of $[n]P$. If $P$ is an $n$-torsion point, then $B(t) = 0$. \bprog ? E = ellinit([17,42]); [t,u] = [114,1218]; ? T = ellxn(E, 2, 'X) %2 = [X^4 - 34*X^2 - 336*X + 289, 4*X^3 + 68*X + 168] ? [a,b] = subst(T,'X,t); %3 = [168416137, 5934096] ? a / b == ellmul(E, [t,u], 2)[1] %4 = 1 @eprog pari-2.17.2/src/functions/elliptic_curves/ellpadicheightmatrix0000644000175000017500000000206214676526175023320 0ustar billbillFunction: ellpadicheightmatrix Section: elliptic_curves C-Name: ellpadicheightmatrix Prototype: GGLG Help: ellpadicheightmatrix(E,p,n,Q): gives the height-pairing matrix for vector of points Q on elliptic curve E. Doc: $Q$ being a vector of points, this function returns the ``Gram matrix'' $[F,G]$ of the cyclotomic $p$-adic height $h_{E}$ with respect to the basis $(\omega, \eta)$ of $D=H^{1}_{dR}(E) \otimes_{\Q} \Q_{p}$ given to $n$ $p$-adic digits. In other words, if \kbd{ellpadicheight}$(E,p,n, Q[i],Q[j]) = [f,g]$, corresponding to $f \omega + g \eta$ in $D$, then $F[i,j] = f$ and $G[i,j] = g$. \bprog ? E = ellinit([0,0,1,-7,6]); Q = [[-2,3],[-1,3]]; p = 5; n = 5; ? [F,G] = ellpadicheightmatrix(E,p,n,Q); ? lift(F) \\ p-adic entries, integral approximation for readability %3 = [2364 3100] [3100 3119] ? G %4 = [25225 46975] [46975 61850] ? [F,G] * [1,-ellpadics2(E,p,n)]~ %5 = [4 + 2*5 + 4*5^2 + 3*5^3 + O(5^5) 4*5^2 + 4*5^3 + 5^4 + O(5^5)] [ 4*5^2 + 4*5^3 + 5^4 + O(5^5) 4 + 3*5 + 4*5^2 + 4*5^3 + 5^4 + O(5^5)] @eprog pari-2.17.2/src/functions/elliptic_curves/ellztopoint0000644000175000017500000000376714676526175021525 0ustar billbillFunction: ellztopoint Section: elliptic_curves C-Name: pointell Prototype: GGp Help: ellztopoint(E,z): inverse of ellpointtoz. Returns the coordinates of point P on the curve E corresponding to a complex or p-adic 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 or $p$-adic parameter $z$. Hence this is the inverse function of \kbd{ellpointtoz}. \item If $E$ is defined over a $p$-adic field and has multiplicative reduction, then $z$ is understood as an element on the Tate curve $\bar{Q}_{p}^{*} / q^{\Z}$. \bprog ? E = ellinit([0,-1,1,0,0], O(11^5)); ? [u2,u,q] = E.tate; type(u) %2 = "t_PADIC" \\ split multiplicative reduction ? z = ellpointtoz(E, [0,0]) %3 = 3 + 11^2 + 2*11^3 + 3*11^4 + 6*11^5 + 10*11^6 + 8*11^7 + O(11^8) ? ellztopoint(E,z) %4 = [O(11^9), O(11^9)] ? E = ellinit(ellfromj(1/4), O(2^6)); x=1/2; y=ellordinate(E,x)[1]; ? z = ellpointtoz(E,[x,y]); \\ nonsplit: t_POLMOD with t_PADIC coefficients ? P = ellztopoint(E, z); ? P[1] \\ y coordinate is analogous, more complicated %8 = Mod(O(2^4)*x + (2^-1 + O(2^5)), x^2 + (1 + 2^2 + 2^4 + 2^5 + O(2^7))) @eprog \item If $E$ is defined over the complex numbers (for instance over $\Q$), $z$ is understood as a complex number in $\C/\Lambda_{E}$. If the short Weierstrass equation is $y^{2} = 4x^{3} - g_{2}x - g_{3}$, then $[x,y]$ represents the Weierstrass $\wp$-function\sidx{Weierstrass $\wp$-function} and its derivative. For a general Weierstrass equation we have $$x = \wp(z) - b_{2}/12,\quad y = \wp'(z)/2 - (a_{1} x + a_{3})/2.$$ If $z$ is in the lattice defining $E$ over $\C$, the result is the point at infinity $[0]$. \bprog ? E = ellinit([0,1]); P = [2,3]; ? z = ellpointtoz(E, P) %2 = 3.5054552633136356529375476976257353387 ? ellwp(E, z) %3 = 2.0000000000000000000000000000000000000 ? ellztopoint(E, z) - P %4 = [2.548947057811923643 E-57, 7.646841173435770930 E-57] ? ellztopoint(E, 0) %5 = [0] \\ point at infinity @eprog pari-2.17.2/src/functions/elliptic_curves/ellpadicregulator0000644000175000017500000000411714760123736022620 0ustar billbillFunction: ellpadicregulator Section: elliptic_curves C-Name: ellpadicregulator Prototype: GGLG Help:ellpadicregulator(E,p,n,S): E elliptic curve/Q, S a vector of points in E(Q), p prime, n an integer; returns the p-adic cyclotomic regulator of the points of S at precision p^n. Doc: Let $E/\Q$ be an elliptic curve. Return the determinant of the Gram matrix of the vector of points $S=(S_{1},\cdots, S_{r})$ with respect to the ``canonical'' cyclotomic $p$-adic height on $E$, given to $n$ ($p$-adic) digits. When $E$ has ordinary reduction at $p$, this is the expected Gram deteterminant in $\Q_{p}$. In the case of supersingular reduction of $E$ at $p$, the definition requires care: the regulator $R$ is an element of $D := H^{1}_{dR}(E) \otimes_{\Q} \Q_{p}$, which is a two-dimensional $\Q_{p}$-vector space spanned by $\omega$ and $\eta = x \omega$ (which are defined over $\Q$) or equivalently but now over $\Q_{p}$ by $\omega$ and $F\omega$ where $F$ is the Frobenius endomorphism on $D$ as defined in \kbd{ellpadicfrobenius}. On $D$ we define the cyclotomic height $h_{E} = f \omega + g \eta$ (see \tet{ellpadicheight}) and a canonical alternating bilinear form $[.,.]_{D}$ such that $[\omega, \eta]_{D} = 1$. For any $\nu \in D$, we can define a height $h_{\nu} := [ h_{E}, \nu ]_{D}$ from $E(\Q)$ to $\Q_{p}$ and $\langle \cdot, \cdot \rangle_{\nu}$ the attached bilinear form. In particular, if $h_{E} = f \omega + g\eta$, then $h_{\eta} = [ h_{E}, \eta ]_{D}$ = f and $h_{\omega} = [ h_{E}, \omega ]_{D} = - g$ hence $h_{E} = h_{\eta} \omega - h_{\omega} \eta$. Then, $R$ is the unique element of $D$ such that $$[\omega,\nu]_{D}^{r-1} [R, \nu]_{D} = \det(\langle S_{i}, S_{j} \rangle_{\nu})$$ for all $\nu \in D$ not in $\Q_{p} \omega$. The \kbd{ellpadicregulator} function returns $R$ in the basis $(\omega, F\omega)$, which was chosen so that $p$-adic BSD conjectures are easy to state, see \kbd{ellpadicbsd}. Note that by definition $$[R, \eta]_{D} = \det(\langle S_{i}, S_{j} \rangle_{\eta})$$ and $$[R, \omega+\eta]_{D} =\det(\langle S_{i}, S_{j} \rangle_{\omega+\eta}).$$ pari-2.17.2/src/functions/elliptic_curves/hyperelldisc0000644000175000017500000000147714676526175021625 0ustar billbillFunction: hyperelldisc Section: elliptic_curves C-Name: hyperelldisc Prototype: G Help: hyperelldisc(X): X being a nonsingular hyperelliptic model of a curve, defined over a field of characteristic distinct from 2, returns its discriminant. X can be given either by a squarefree polynomial P such that X:y^2=P(x) or by a vector [P,Q] such that X:y^2+Q(x)*y=P(x) and Q^2+4P is squarefree. Doc: $X$ being a nonsingular hyperelliptic model of a curve, defined over a field of characteristic distinct from 2, returns its discriminant. $X$ can be given either by a squarefree polynomial $P$ such that $X$ has equation $y^{2} = P(x)$ or by a vector $[P,Q]$ such that $X$ has equation $y^{2} + Q(x)\*y = P(x)$ and $Q^{2}+4\*P$ is squarefree. \bprog ? hyperelldisc([x^3,1]) %1 = -27 ? hyperelldisc(x^5+1) %2 = 800000 @eprog pari-2.17.2/src/functions/elliptic_curves/ellbsd0000644000175000017500000000220014676526175020364 0ustar billbillFunction: ellbsd Section: elliptic_curves C-Name: ellbsd Prototype: Gp Help: ellbsd(E): E being an elliptic curve over a number field, returns a real number c such that the BSD conjecture predicts that lfun(E,1,r)/r! = c*R*S where r is the rank, R is the regulator and S is the cardinal of the Tate-Shafarevich group. Doc: $E$ being an elliptic curve over a number field, returns a real number $c$ such that the Birch and Swinnerton-Dyer conjecture predicts that $L_{E}^{(r)}(1)/r!{} = c\*R\*S$, where $r$ is the rank, $R$ the regulator and $S$ the cardinal of the Tate-Shafarevich group. \bprog ? e = ellinit([0,-1,1,-10,-20]); \\ rank 0 ? ellbsd(e) %2 = 0.25384186085591068433775892335090946105 ? lfun(e,1) %3 = 0.25384186085591068433775892335090946104 ? e = ellinit([0,0,1,-1,0]); \\ rank 1 ? P = ellheegner(e); ? ellbsd(e)*ellheight(e,P) %6 = 0.30599977383405230182048368332167647445 ? lfun(e,1,1) %7 = 0.30599977383405230182048368332167647445 ? e = ellinit([1+a,0,1,0,0],nfinit(a^2+1)); \\ rank 0 ? ellbsd(e) %9 = 0.42521832235345764503001271536611593310 ? lfun(e,1) %10 = 0.42521832235345764503001271536611593309 @eprog pari-2.17.2/src/functions/elliptic_curves/elldivpol0000644000175000017500000000240514676526175021120 0ustar billbillFunction: elldivpol Section: elliptic_curves C-Name: elldivpol Prototype: GLDn Help: elldivpol(E,n,{v='x}): n-division polynomial f_n for the curve E in the variable v. Doc: $n$-division polynomial $f_{n}$ for the curve $E$ in the variable $v$. In standard notation, for any affine point $P = (X,Y)$ on the curve and any integer $n \geq 0$, we have $$[n]P = (\phi_{n}(P)\psi_{n}(P) : \omega_{n}(P) : \psi_{n}(P)^{3})$$ for some polynomials $\phi_{n},\omega_{n},\psi_{n}$ in $\Z[a_{1},a_{2},a_{3},a_{4},a_{6}][X,Y]$. We have $f_{n}(X) = \psi_{n}(X)$ for $n$ odd, and $f_{n}(X) = \psi_{n}(X,Y) (2Y + a_{1}X+a_{3})$ for $n$ even. We have $$ f_{0} = 0,\quad f_{1} = 1,\quad f_{2} = 4X^{3} + b_{2}X^{2} + 2b_{4} X + b_{6}, \quad f_{3} = 3 X^{4} + b_{2} X^{3} + 3b_{4} X^{2} + 3 b_{6} X + b8, $$ $$ f_{4} = f_{2}(2X^{6} + b_{2} X^{5} + 5b_{4} X^{4} + 10 b_{6} X^{3} + 10 b_{8} X^{2} + (b_{2}b_{8}-b_{4}b_{6})X + (b_{8}b_{4} - b_{6}^{2})), \dots $$ When $n$ is odd, the roots of $f_{n}$ are the $X$-coordinates of the affine points in the $n$-torsion subgroup $E[n]$; when $n$ is even, the roots of $f_{n}$ are the $X$-coordinates of the affine points in $E[n]\setminus E[2]$ when $n > 2$, resp.~in $E[2]$ when $n = 2$. For $n < 0$, we define $f_{n} := - f_{-n}$. pari-2.17.2/src/functions/elliptic_curves/ellissupersingular0000644000175000017500000000236414676526175023066 0ustar billbillFunction: ellissupersingular Section: elliptic_curves C-Name: ellissupersingular Prototype: iGDG Help: ellissupersingular(E,{p}): return 1 if the elliptic curve E, defined over a number field or a finite field, is supersingular at p, and 0 otherwise. Doc: Return 1 if the elliptic curve $E$ defined over a number field, $\Q_{p}$ or a finite field is supersingular at $p$, and $0$ otherwise. If the curve is defined over $\Q$ or a number field, $p$ must be explicitly given, and must be a prime number, resp.~a maximal ideal; we return $1$ if and only if $E$ has supersingular good reduction at $p$. Alternatively, $E$ can be given by its $j$-invariant in a finite field. In this case $p$ must be omitted. \bprog ? g = ffprimroot(ffgen(7^5)) %1 = 4*x^4+5*x^3+6*x^2+5*x+6 ? [g^n | n <- [1 .. 7^5 - 1], ellissupersingular(g^n)] %2 = [6] ? j = ellsupersingularj(2^31-1) %3 = 1618591527*w+1497042960 ? ellissupersingular(j) %4 = 1 ? K = nfinit(y^3-2); P = idealprimedec(K, 2)[1]; ? E = ellinit([y,1], K); ? ellissupersingular(E, P) %7 = 1 ? Q = idealprimedec(K,5)[1]; ? ellissupersingular(E, Q) %9 = 0 @eprog Variant: Also available is \fun{int}{elljissupersingular}{GEN j} where $j$ is a $j$-invariant of a curve over a finite field. pari-2.17.2/src/functions/elliptic_curves/ellformallog0000644000175000017500000000124214676526175021603 0ustar billbillFunction: ellformallog Section: elliptic_curves C-Name: ellformallog Prototype: GDPDn Help: ellformallog(E,{n=seriesprecision},{v='x}): E elliptic curve, returns n terms of the elliptic logarithm as a series of t =-x/y. Doc: The formal elliptic logarithm is a series $L$ in $t K[[t]]$ such that $d L = \omega = dx / (2y + a_{1}x + a_{3})$, the canonical invariant differential attached to the model $E$. It gives an isomorphism from the formal group of $E$ to the additive formal group. \bprog ? E = ellinit([-1,1/4]); L = ellformallog(E, 9, 't) %1 = t - 2/5*t^5 + 3/28*t^7 + 2/3*t^9 + O(t^10) ? [f,g] = ellformaldifferential(E,8,'t); ? L' - f %3 = O(t^8) @eprog pari-2.17.2/src/functions/elliptic_curves/elltrace0000644000175000017500000000313414676526175020721 0ustar billbillFunction: elltrace Section: elliptic_curves C-Name: elltrace Prototype: GG Help: elltrace(E,P): sum of the Galois conjugates of the point P on elliptic curve E. Doc: let $E$ be an elliptic curve over a base field and a point $P$ defined over an extension field using \typ{POLMOD} constructs. Returns the sum of the Galois conjugates of $P$. The field over which $P$ is defined must be specified, even in the (silly) case of a trivial extension: \bprog ? E = ellinit([1,15]); \\ y^2 = x^3 + x + 15, over Q ? P = Mod([a/8-1, 1/32*a^2-11/32*a-19/4], a^3-135*a-408); ? ellisoncurve(E,P) \\ P defined over a cubic extension %3 = 1 ? elltrace(E,P) %4 = [2,-5] @eprog \bprog ? E = ellinit([-13^2, 0]); ? P = Mod([13,0], a^2-2); \\ defined over Q, seen over a quadratic extension ? elltrace(E,P) == ellmul(E,P,2) %3 = 1 ? elltrace(E,[13,0]) \\ number field of definition of the point unspecified! *** at top-level: elltrace(E,[13,0]) *** ^------------------ *** elltrace: incorrect type in elltrace (t_INT). ? elltrace(E,Mod([13,0],a)) \\ trivial extension %5 = [Mod(13, a), Mod(0, a)] ? P = Mod([-10*x^3+10*x-13, -16*x^3+16*x-34], x^4-x^3+2*x-1); ? ellisoncurve(E,P) %7 = 1 ? Q = elltrace(E,P) %8 = [11432100241 / 375584400, 1105240264347961 / 7278825672000] ? ellisoncurve(E,Q) %9 = 1 @eprog \bprog ? E = ellinit([2,3], 19); \\ over F_19 ? T = a^5+a^4+15*a^3+16*a^2+3*a+1; \\ irreducible ? P = Mod([11*a^3+11*a^2+a+12,15*a^4+9*a^3+18*a^2+18*a+6], T); ? ellisoncurve(E, P) %4 = 1 ? Q = elltrace(E, P) %5 = [Mod(1,19), Mod(14,19)] ? ellisoncurve(E, Q) %6 = 1 @eprog pari-2.17.2/src/functions/elliptic_curves/elltaniyama0000644000175000017500000000210214676526175021420 0ustar billbillFunction: elltaniyama Section: elliptic_curves C-Name: elltaniyama Prototype: GDP Help: elltaniyama(E,{n=seriesprecision}): modular parametrization of elliptic curve E/Q. Doc: computes the modular parametrization of the elliptic curve $E/\Q$, where $E$ is an \kbd{ell} structure as output by \kbd{ellinit}. This returns a two-component vector $[u,v]$ of power series, given to $n$ significant terms (\tet{seriesprecision} by default), characterized by the following two properties. First the point $(u,v)$ satisfies the equation of the elliptic curve. Second, let $N$ be the conductor of $E$ and $\Phi: X_{0}(N)\to E$ be a modular parametrization; the pullback by $\Phi$ of the N\'eron differential $du/(2v+a_{1}u+a_{3})$ is equal to $2i\pi f(z)dz$, a holomorphic differential form. The variable used in the power series for $u$ and $v$ is $x$, which is implicitly understood to be equal to $\exp(2i\pi z)$. The algorithm assumes that $E$ is a \emph{strong} \idx{Weil curve} and that the Manin constant is equal to 1: in fact, $f(x) = \sum_{n > 0} \kbd{ellak}(E, n) x^{n}$. pari-2.17.2/src/functions/elliptic_curves/ellminimaltwist0000644000175000017500000000262714760123736022340 0ustar billbillFunction: ellminimaltwist Section: elliptic_curves C-Name: ellminimaltwist0 Prototype: GD0,L, Help: ellminimaltwist(E,{flag=0}): E being an elliptic curve defined over Q, return a discriminant D such that the twist of E by D is minimal among all possible quadratic twists, i.e., if flag=0, its minimal model has minimal discriminant, or if flag=1, it has minimal conductor. Doc: Let $E$ be an elliptic curve defined over $\Q$, return a discriminant $D$ such that the twist of $E$ by $D$ is minimal among all possible quadratic twists, i.e. if $\fl=0$, its minimal model has minimal discriminant, or if $\fl=1$, it has minimal conductor. In the example below, we find a curve with $j$-invariant $3$ and minimal conductor. \bprog ? E = ellminimalmodel(ellinit(ellfromj(3))); ? ellglobalred(E)[1] %2 = 357075 ? D = ellminimaltwist(E,1) %3 = -15 ? E2 = ellminimalmodel(elltwist(E,D)); ? ellglobalred(E2)[1] %5 = 14283 @eprog In the example below, $\fl=0$ and $\fl=1$ give different results. \bprog ? E = ellinit([1,0]); ? D0 = ellminimaltwist(E,0) %7 = 1 ? D1 = ellminimaltwist(E,1) %8 = 8 ? E0 = ellminimalmodel(elltwist(E,D0)); ? [E0.disc, ellglobalred(E0)[1]] %10 = [-64, 64] ? E1 = ellminimalmodel(elltwist(E,D1)); ? [E1.disc, ellglobalred(E1)[1]] %12 = [-4096, 32] @eprog Variant: Also available are \fun{GEN}{ellminimaltwist}{E} for $\fl=0$, and \fun{GEN}{ellminimaltwistcond}{E} for $\fl=1$. pari-2.17.2/src/functions/elliptic_curves/ellheightmatrix0000644000175000017500000000146014567450071022306 0ustar billbillFunction: ellheightmatrix Section: elliptic_curves C-Name: ellheightmatrix Prototype: GGp Help: ellheightmatrix(E,x): gives the height matrix for vector of points x on elliptic curve E. Doc: $x$ being a vector of points, this function outputs the Gram matrix of $x$ with respect to the N\'eron-Tate height, in other words, the $(i,j)$ component of the matrix is equal to \kbd{ellheight($E$,x[$i$],x[$j$])}. The rank of this matrix, at least in some approximate sense, gives the rank of the set of points, and if $x$ is a basis of the \idx{Mordell-Weil group} of $E$, its determinant is equal to the regulator of $E$. Note our height normalization follows Cremona's \emph{Algorithms for modular elliptic curves}: this matrix should be divided by 2 to be in accordance with, e.g., Silverman's normalizations. pari-2.17.2/src/functions/elliptic_curves/ellgenerators0000644000175000017500000000301314676526175021770 0ustar billbillFunction: ellgenerators Section: elliptic_curves C-Name: ellgenerators Prototype: G Help: ellgenerators(E): if E is an elliptic curve over the rationals, return the generators of the Mordell-Weil group attached to the curve. This relies on the curve being referenced in the elldata database. If E is an elliptic curve over a finite field Fq as output by ellinit(), return a minimal set of generators for the group E(Fq). Doc: If $E$ is an elliptic curve over the rationals, return a $\Z$-basis of the free part of the \idx{Mordell-Weil group} attached to $E$. This relies on the \tet{elldata} database being installed and referencing the curve, and so is only available for curves over $\Z$ of small conductors. If $E$ is an elliptic curve over a finite field $\F_{q}$ as output by \tet{ellinit}, return a minimal set of generators for the group $E(\F_{q})$. \misctitle{Caution} When the group is not cyclic, of shape $\Z/d_{1}\Z \times \Z/d_{2}\Z$ with $d_{2}\mid d_{1}$, the points $[P,Q]$ returned by ellgenerators need not have order $d_{1}$ and $d_{2}$: it is true that $P$ has order $d_{1}$, but we only know that $Q$ is a generator of $E(\F_{q})/

$ and that the Weil pairing $w(P,Q)$ has order $d_{2}$, see \kbd{??ellgroup}. If you need generators $[P,R]$ with $R$ of order $d_{2}$, find $x$ such that $R = Q-[x]P$ has order $d_{2}$ by solving the discrete logarithm problem $[d_{2}]Q = [x]([d_{2}]P)$ in a cyclic group of order $d_{1}/d_{2}$. This will be very expensive if $d_{1}/d_{2}$ has a large prime factor. pari-2.17.2/src/functions/elliptic_curves/hyperellminimaldisc0000644000175000017500000000213214676526175023161 0ustar billbillFunction: hyperellminimaldisc Section: elliptic_curves C-Name: hyperellminimaldisc Prototype: GDG Help: hyperellminimaldisc(C,{pr}): C being a nonsingular integral hyperelliptic model of a curve, return the minimal discrminant of an integral model of C. If pr is given, it must be a list of primes and the discriminant is then only garanteed minimal at the elements of pr. C can be given either by a squarefree polynomial P such that C:y^2=P(x) or by a vector [P,Q] such that C:y^2+Q(x)*y=P(x) and Q^2+4P is squarefree. Doc: $C$ being a nonsingular integral hyperelliptic model of a curve, return the minimal discriminant of an integral model of $C$. If $pr$ is given, it must be a list of primes and the discriminant is then only garanteed minimal at the elements of $pr$. $C$ can be given either by a squarefree polynomial $P$ such that $C: y^{2} = P(x)$ or by a vector $[P,Q]$ such that $C: y^{2} + Q(x)\*y = P(x)$ and $Q^{2}+4\*P$ is squarefree. \bprog ? W = [x^6+216*x^3+324,0]; ? D = hyperelldisc(W) %2 = 1828422898924853919744000 ? M = hyperellminimaldisc(W) %4 = 29530050606000 @eprog pari-2.17.2/src/functions/elliptic_curves/ellpadicbsd0000644000175000017500000000651714676526175021404 0ustar billbillFunction: ellpadicbsd Section: elliptic_curves C-Name: ellpadicbsd Prototype: GGLDG Help: ellpadicbsd(E,p,n,{D=1}): returns [r,Lp] where r is the (conjectural) analytic rank of the p-adic L-function attached to the quadratic twist E_D and Lp is (conjecturally) equal to the product of the p-adic regulator and the cardinal of the Tate-Shafarevich group. Doc: Given an elliptic curve $E$ over $\Q$, its quadratic twist $E_{D}$ and a prime number $p$, this function is a $p$-adic analog of the complex functions \tet{ellanalyticrank} and \tet{ellbsd}. It calls \kbd{ellpadicL} with initial accuracy $p^{n}$ and may increase it internally; it returns a vector $[r, L_{p}]$ where \item $L_{p}$ is a $p$-adic number (resp. a pair of $p$-adic numbers if $E$ has good supersingular reduction) defined modulo $p^{N}$, conjecturally equal to $R_{p} S$, where $R_{p}$ is the $p$-adic regulator as given by \tet{ellpadicregulator} (in the basis $(\omega, F \omega)$) and $S$ is the cardinal of the Tate-Shafarevich group for the quadratic twist $E_{D}$. \item $r$ is an upper bound for the analytic rank of the $p$-adic $L$-function attached to $E_{D}$: we know for sure that the $i$-th derivative of $L_{p}(E_{D},.)$ at $\chi^{0}$ is $O(p^{N})$ for all $i < r$ and that its $r$-th derivative is nonzero; it is expected that the true analytic rank is equal to the rank of the Mordell-Weil group $E_{D}(\Q)$, plus $1$ if the reduction of $E_{D}$ at $p$ is split multiplicative; if $r = 0$, then both the analytic rank and the Mordell-Weil rank are unconditionnally $0$. Recall that the $p$-adic BSD conjecture (Mazur, Tate, Teitelbaum, Bernardi, Perrin-Riou) predicts an explicit link between $R_{p} S$ and $$(1-p^{-1} F)^{-2} \cdot L_{p}^{(r)}(E_{D}, \chi^{0}) / r! $$ where $r$ is the analytic rank of the $p$-adic $L$-function attached to $E_{D}$ and $F$ is the Frobenius on $H^{1}_{dR}$; see \tet{ellpadicL} for definitions. \bprog ? E = ellinit("11a1"); p = 7; n = 5; \\ good ordinary ? ellpadicbsd(E, 7, 5) \\ rank 0, %2 = [0, 1 + O(7^5)] ? E = ellinit("91a1"); p = 7; n = 5; \\ non split multiplicative ? [r,Lp] = ellpadicbsd(E, p, n) %5 = [1, 2*7 + 6*7^2 + 3*7^3 + 7^4 + O(7^5)] ? R = ellpadicregulator(E, p, n, E.gen) %6 = 2*7 + 6*7^2 + 3*7^3 + 7^4 + 5*7^5 + O(7^6) ? sha = Lp/R %7 = 1 + O(7^4) ? E = ellinit("91b1"); p = 7; n = 5; \\ split multiplicative ? [r,Lp] = ellpadicbsd(E, p, n) %9 = [2, 2*7 + 7^2 + 5*7^3 + O(7^4)] ? ellpadicregulator(E, p, n, E.gen) %10 = 2*7 + 7^2 + 5*7^3 + 6*7^4 + 2*7^5 + O(7^6) ? [rC, LC] = ellanalyticrank(E); ? [r, rC] %12 = [2, 1] \\ r = rC+1 because of split multiplicative reduction ? E = ellinit("53a1"); p = 5; n = 5; \\ supersingular ? [r, Lp] = ellpadicbsd(E, p, n); ? r %15 = 1 ? Lp %16 = [3*5 + 2*5^2 + 2*5^5 + O(5^6), \ 5 + 3*5^2 + 4*5^3 + 2*5^4 + 5^5 + O(5^6)] ? R = ellpadicregulator(E, p, n, E.gen) %17 = [3*5 + 2*5^2 + 2*5^5 + O(5^6), 5 + 3*5^2 + 4*5^3 + 2*5^4 + O(5^5)] \\ expect Lp = R*#Sha, hence (conjecturally) #Sha = 1 ? E = ellinit("84a1"); p = 11; n = 6; D = -443; ? [r,Lp] = ellpadicbsd(E, 11, 6, D) \\ Mordell-Weil rank 0, no regulator %19 = [0, 3 + 2*11 + O(11^6)] ? lift(Lp) \\ expected cardinal for Sha is 5^2 %20 = 25 ? ellpadicbsd(E, 3, 12, D) \\ at 3 %21 = [1, 1 + 2*3 + 2*3^2 + O(3^8)] ? ellpadicbsd(E, 7, 8, D) \\ and at 7 %22 = [0, 4 + 3*7 + O(7^8)] @eprog pari-2.17.2/src/functions/elliptic_curves/ellmaninconstant0000644000175000017500000000143214760123736022464 0ustar billbillFunction:ellmaninconstant Section: elliptic_curves C-Name: ellmaninconstant Prototype: G Help: ellmaninconstant(E): let E be an elliptic curve over Q given by ellinit or a rational isogeny class given by ellisomat. Return the Manin constant of the curve, see ellweilcurve. The algorithm is slow but unconditional. Doc: let $E$ be an elliptic curve over $Q$ given by \kbd{ellinit} or a rational isogeny class given by ellisomat. Return the Manin constant of the curve, see \kbd{ellweilcurve}. The algorithm is slow but unconditional. The function also accepts the output of \kbd{ellisomat} and returns the list of Manin constants for all the isogeny class. \bprog ? E = ellinit("11a3"); ? ellmaninconstant(E) %2 = 5 ? L=ellisomat(E,,1); ? ellmaninconstant(L) %4 = [5,1,1] @eprog pari-2.17.2/src/functions/elliptic_curves/ellfromj0000644000175000017500000000230614676526175020740 0ustar billbillFunction: ellfromj Section: elliptic_curves C-Name: ellfromj Prototype: G Help: ellfromj(j): returns the coefficients [a1,a2,a3,a4,a6] of a fixed elliptic curve with j-invariant j. Doc: returns the coefficients $[a_{1},a_{2},a_{3},a_{4},a_{6}]$ of a fixed elliptic curve with $j$-invariant $j$. The given model is arbitrary; for instance, over the rationals, it is in general not minimal nor even integral. \bprog ? v = ellfromj(1/2) %1 = [0, 0, 0, 10365/4, 11937025/4] ? E = ellminimalmodel(ellinit(v)); E[1..5] %2 = [0, 0, 0, 41460, 190992400] ? F = ellminimalmodel(elltwist(E, 24)); F[1..5] %3 = [1, 0, 0, 72, 13822] ? [E.disc, F.disc] %4 = [-15763098924417024000, -82484842750] @eprog\noindent For rational $j$, the following program returns the integral curve of minimal discriminant and given $j$ invariant: \bprog ellfromjminimal(j)= { my(E = ellinit(ellfromj(j))); my(D = ellminimaltwist(E)); ellminimalmodel(elltwist(E,D)); } ? e = ellfromjminimal(1/2); e.disc %1 = -82484842750 @eprog Using $\fl = 1$ in \kbd{ellminimaltwist} would instead return the curve of minimal conductor. For instance, if $j = 1728$, this would return a different curve (of conductor $32$ instead of $64$). pari-2.17.2/src/functions/elliptic_curves/ellchangecurve0000644000175000017500000000113514676526175022114 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^{2}x'+r$, $y=u^{3}y'+su^{2}x'+t$. $E$ must be an \kbd{ell} structure as output by \kbd{ellinit}. The special case $v = 1$ is also used instead of $[1,0,0,0]$ to denote the trivial coordinate change. pari-2.17.2/src/functions/elliptic_curves/ellpadics20000644000175000017500000000255714676526175021160 0ustar billbillFunction: ellpadics2 Section: elliptic_curves C-Name: ellpadics2 Prototype: GGL Help: ellpadics2(E,p,n): returns s2 to absolute p-adic precision p^n. Doc: If $p>2$ is a prime and $E/\Q$ is an elliptic curve with ordinary good reduction at $p$, returns the slope of the unit eigenvector of \kbd{ellpadicfrobenius(E,p,n)}, i.e., the action of Frobenius $\varphi$ on the crystalline module $D_{p}(E)= \Q_{p} \otimes H^{1}_{dR}(E/\Q)$ in the basis of the given model $(\omega, \eta=x\*\omega)$, where $\omega$ is the invariant differential $dx/(2\*y+a_{1}\*x+a_{3})$. In other words, $\eta + s_{2}\omega$ is an eigenvector for the unit eigenvalue of $\varphi$. \bprog ? e=ellinit([17,42]); ? ellpadics2(e,13,4) %2 = 10 + 2*13 + 6*13^3 + O(13^4) @eprog This slope is the unique $c \in 3^{-1}\Z_{p}$ such that the odd solution $\sigma(t) = t + O(t^{2})$ of $$ - d(\dfrac{1}{\sigma} \dfrac{d \sigma}{\omega}) = (x(t) + c) \omega$$ is in $t\Z_{p}[[t]]$. It is equal to $b_{2}/12 - E_{2}/12$ where $E_{2}$ is the value of the Katz $p$-adic Eisenstein series of weight 2 on $(E,\omega)$. This is used to construct a canonical $p$-adic height when $E$ has good ordinary reduction at $p$ as follows \bprog s2 = ellpadics2(E,p,n); h(E,p,n, P, s2) = ellpadicheight(E, [p,[1,-s2]],n, P); @eprog\noindent Since $s_{2}$ does not depend on the point $P$, we compute it only once. pari-2.17.2/src/functions/conversions/0000755000175000017500000000000014760315601016336 5ustar billbillpari-2.17.2/src/functions/conversions/valuation0000644000175000017500000000224114567450071020270 0ustar billbillFunction: valuation Section: conversions C-Name: gpvaluation Prototype: GDG 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 \kbd{+oo} if $x$ is an exact object. If $x$ is a $p$-adic numbers or power series, the result is the exponent of the zero. Any other type combinations gives an error. Finally, $p$ can be omitted if $x$ is a \typ{PADIC} (taken to be the underlying prime), a \typ{SER} or a \typ{POL} (taken to be the main variable). Variant: Also available is \fun{long}{gvaluation}{GEN x, GEN p}, which returns \tet{LONG_MAX} if $x = 0$ and the valuation as a \kbd{long} integer. pari-2.17.2/src/functions/conversions/HEADER0000644000175000017500000000077214567450071017225 0ustar billbillFunction: _header_conversions Class: header Section: conversions Doc: \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. pari-2.17.2/src/functions/conversions/precision0000644000175000017500000000273114567450071020265 0ustar billbillFunction: precision Section: conversions C-Name: precision00 Prototype: GDG Help: precision(x,{n}): if n is present, return x at precision n. If n is omitted, return real precision of object x. Doc: the function behaves differently according to whether $n$ is present or not. If $n$ is missing, the function returns the floating point precision in decimal digits of the PARI object $x$. If $x$ has no floating point component, the function returns \kbd{+oo}. \bprog ? precision(exp(1e-100)) %1 = 154 \\ 154 significant decimal digits ? precision(2 + x) %2 = +oo \\ exact object ? precision(0.5 + O(x)) %3 = 38 \\ floating point accuracy, NOT series precision ? precision( [ exp(1e-100), 0.5 ] ) %4 = 38 \\ minimal accuracy among components @eprog\noindent Using \kbd{getlocalprec()} allows to retrieve the working precision (as modified by possible \kbd{localprec} statements). If $n$ is present, the function creates a new object equal to $x$ with a new floating point precision $n$: $n$ is the number of desired significant \emph{decimal} digits. If $n$ is smaller than the precision of a \typ{REAL} component of $x$, it is truncated, otherwise it is extended with zeros. For non-floating-point types, no change. 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.17.2/src/functions/conversions/exponent0000644000175000017500000000277714676526175020156 0ustar billbillFunction: exponent Section: conversions C-Name: gpexponent Prototype: G Help: exponent(x): binary exponent of x Doc: When $x$ is a \typ{REAL}, the result is the binary exponent $e$ of $x$. For a nonzero $x$, this is the unique integer $e$ such that $2^{e} \leq |x| < 2^{e+1}$. For a real $0$, this returns the PARI exponent $e$ attached to $x$ (which may represent any floating-point number less than $2^{e}$ in absolute value). \bprog ? exponent(Pi) %1 = 1 ? exponent(4.0) %2 = 2 ? exponent(0.0) %3 = -128 ? default(realbitprecision) %4 = 128 @eprog\noindent This definition extends naturally to nonzero integers, and the exponent of an exact $0$ is $-\kbd{oo}$ by convention. For convenience, we \emph{define} the exponent of a \typ{FRAC} $a/b$ as the difference of \kbd{exponent}$(a)$ and \kbd{exponent}$(b)$; note that, if $e'$ denotes the exponent of \kbd{$a/b$ * 1.0}, then the exponent $e$ we return is either $e'$ or $e'+1$, thus $2^{e+1}$ is an upper bound for $|a/b|$. \bprog ? [ exponent(9), exponent(10), exponent(9/10), exponent(9/10*1.) ] %5 = [3, 3, 0, -1] @eprog For a PARI object of type \typ{COMPLEX}, \typ{POL}, \typ{SER}, \typ{VEC}, \typ{COL}, \typ{MAT} this returns the largest exponent found among the components of $x$. Hence $2^{e+1}$ is a quick upper bound for the sup norm of real matrices or polynomials; and $2^{e+(3/2)}$ for complex ones. \bprog ? exponent(3*x^2 + 15*x - 100) %5 = 6 ? exponent(0) %6 = -oo @eprog Variant: Also available is \fun{long}{gexpo}{GEN x}. pari-2.17.2/src/functions/conversions/Col0000644000175000017500000000277414676526175017030 0ustar billbillFunction: Col Section: conversions C-Name: gtocol0 Prototype: GD0,L, Help: Col(x,{n}): transforms the object x into a column vector of dimension n. Description: (gen):vec gtocol($1) Doc: transforms the object $x$ into a column vector. The dimension of the resulting vector can be optionally specified via the extra parameter $n$. If $n$ is omitted or $0$, the dimension depends on the type of $x$; the vector has a single component, except when $x$ is \item a vector or a quadratic form (in which case the resulting vector is simply the initial object considered as a row vector), \item a polynomial or a power series. In the case of a polynomial, the coefficients of the vector start with the leading coefficient of the polynomial, while for power series only the significant coefficients are taken into account, but this time by increasing order of degree. In this last case, \kbd{Vec} is the reciprocal function of \kbd{Pol} and \kbd{Ser} respectively, \item a matrix (the column of row vector comprising the matrix is returned), \item a character string (a vector of individual characters is returned). In the last two cases (matrix and character string), $n$ is meaningless and must be omitted or an error is raised. Otherwise, if $n$ is given, $0$ entries are appended at the end of the vector if $n > 0$, and prepended at the beginning if $n < 0$. The dimension of the resulting vector is $|n|$. See ??Vec for examples and further details. Variant: \fun{GEN}{gtocol}{GEN x} is also available. pari-2.17.2/src/functions/conversions/centerlift0000644000175000017500000000201114760123736020420 0ustar billbillFunction: centerlift Section: conversions C-Name: centerlift0 Prototype: GDn Help: centerlift(x,{v}): centered lift of x. Same as lift except for intmod and padic components. Description: (pol):pol centerlift($1) (vec):vec centerlift($1) (gen):gen centerlift($1) (pol, var):pol centerlift0($1, $2) (vec, var):vec centerlift0($1, $2) (gen, var):gen centerlift0($1, $2) Doc: Same as \tet{lift}, except that \typ{INTMOD} and \typ{PADIC} components are lifted using centered residues: \item for a \typ{INTMOD} $x\in \Z/n\Z$, the lift $y$ is such that $-n/2b_i. Description: ():list mkmap() (gen):list listinit(gtomap($1)) Doc: A ``Map'' is an associative array, or dictionary: a data type composed of a collection of (\emph{key}, \emph{value}) pairs, such that each key appears just once in the collection. This function converts the matrix $[a_{1},b_{1};a_{2},b_{2};\dots;a_{n},b_{n}]$ to the map $a_{i}\mapsto b_{i}$. \bprog ? M = Map(factor(13!)); ? mapget(M, 3) %2 = 5 ? P = Map(matreduce(primes([1,20]))) %3 = Map([2,1;3,1;5,1;7,1;11,1;13,1;17,1;19,1]) ? select(i->mapisdefined(P,i), [1..20]) %4 = [2, 3, 5, 7, 11, 13, 17, 19] @eprog\noindent If the argument $x$ is omitted, creates an empty map, which may be filled later via \tet{mapput}. pari-2.17.2/src/functions/conversions/round0000644000175000017500000000303114676526175017425 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 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.17.2/src/functions/conversions/bittest0000644000175000017500000000203414676526175017756 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. For $x\ge1$, the highest 1-bit is at $n = \kbd{logint}(x)$ (and bigger $n$ gives $0$). \bprog ? bittest(7, 0) %1 = 1 \\ the bit 0 is 1 ? bittest(7, 2) %2 = 1 \\ the bit 2 is 1 ? bittest(7, 3) %3 = 0 \\ the bit 3 is 0 @eprog\noindent See \secref{se:bitand} for the behavior at negative arguments. Variant: For a \typ{INT} $x$, the variant \fun{long}{bittest}{GEN x, long n} is generally easier to use, and if furthermore $n\ge 0$ the low-level function \fun{ulong}{int_bit}{GEN x, long n} returns \kbd{bittest(abs(x),n)}. pari-2.17.2/src/functions/conversions/sizedigit0000644000175000017500000000132714676526175020277 0ustar billbillFunction: sizedigit Section: conversions C-Name: sizedigit Prototype: lG Obsolete: 2015-01-13 Help: sizedigit(x): rough upper bound for the number of decimal digits of (the components of) x. DEPRECATED. Doc: This function is DEPRECATED, essentially meaningless, and provided for backwards compatibility only. Don't use it! outputs a quick upper bound for the number of decimal digits of (the components of) $x$, off by at most $1$. More precisely, for a positive integer $x$, it computes (approximately) the ceiling of $$\kbd{floor}(1 + \log_{2} x) \log_{10}2,$$ To count the number of decimal digits of a positive integer $x$, use \kbd{\#digits(x)}. To estimate (recursively) the size of $x$, use \kbd{normlp(x)}. pari-2.17.2/src/functions/conversions/Qfb0000644000175000017500000000074314676526175017015 0ustar billbillFunction: Qfb Section: conversions C-Name: Qfb0 Prototype: GDGDG Help: Qfb(a,{b},{c}): binary quadratic form a*x^2+b*x*y+c*y^2. Doc: creates the binary quadratic form\sidx{binary quadratic form} $ax^{2}+bxy+cy^{2}$. Negative definite forms are not implemented, use their positive definite counterpart instead. The syntax \kbd{Qfb(V)} is also allowed with $V$ being either a \typ{VEC} $[a,b,c]$, a \typ{POL} $ax^{2}+bx+c$ or a \typ{MAT} $[a,b_{0};b_{1},c]$ with $b_{0}+b_{1}=b$. pari-2.17.2/src/functions/conversions/real0000644000175000017500000000065014567450071017213 0ustar billbillFunction: real Section: conversions C-Name: greal Prototype: G Help: real(x): real part of x. Doc: real part of $x$. When $x$ is a quadratic number, this is the coefficient of $1$ in the ``canonical'' integral basis $(1,\omega)$. \bprog ? real(3 + I) %1 = 3 ? x = 3 + quadgen(-23); ? real(x) \\ as a quadratic number %3 = 3 ? real(x * 1.) \\ as a complex number %4 = 3.5000000000000000000000000000000000000 @eprog pari-2.17.2/src/functions/conversions/Vecrev0000644000175000017500000000104714676526175017535 0ustar billbillFunction: Vecrev Section: conversions C-Name: gtovecrev0 Prototype: GD0,L, Help: Vecrev(x,{n}): transforms the object x into a vector of dimension n in reverse order with respect to Vec(x,{n}). Description: (gen):vec gtovecrev($1) Doc: as $\kbd{Vec}(x, -n)$, then reverse the result. In particular, \kbd{Vecrev} is the reciprocal function of \kbd{Polrev}: the coefficients of the vector start with the constant coefficient of the polynomial and the others follow by increasing degree. Variant: \fun{GEN}{gtovecrev}{GEN x} is also available. pari-2.17.2/src/functions/conversions/liftpol0000644000175000017500000000131614567450071017741 0ustar billbillFunction: liftpol Section: conversions C-Name: liftpol Prototype: G Help: liftpol(x): lifts every polmod component of x to polynomials. Description: (pol):pol liftpol($1) (vec):vec liftpol($1) (gen):gen liftpol($1) Doc: recursively lift all components of $x$ which are polmods to polynomials. \typ{FFELT} are not lifted, nor are List elements: you may convert the latter to vectors first, or use \kbd{apply(liftpol,L)}. More generally, components for which such lifts are meaningless (e.g. character strings) are copied verbatim. \bprog ? liftpol(x * (1 + O(3)) + Mod(2,3)) %1 = (1 + O(3))*x + Mod(2, 3) ? liftpol(x * Mod(y,y^2+1) + Mod(2,3)*Mod(z,z^2)) %2 = y*x + Mod(2, 3)*z @eprog pari-2.17.2/src/functions/conversions/Mat0000644000175000017500000000173614567450071017017 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. Description: ():vec cgetg(1, t_MAT) (gen):vec gtomat($1) 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 attached big matrix is returned. If $x$ is a binary quadratic form, creates the attached $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.17.2/src/functions/conversions/random0000644000175000017500000001025514676526175017564 0ustar billbillFunction: random Section: conversions C-Name: genrand Prototype: DG Help: random({N=2^31}): random object, depending on the type of N. Integer between 0 and N-1 (t_INT), int mod N (t_INTMOD), element in a finite field (t_FFELT), point on an elliptic curve (ellinit mod p or over a finite field). Description: (?int):int genrand($1) (real):real genrand($1) (gen):gen genrand($1) Doc: returns a random element in various natural sets depending on the argument $N$. \item \typ{INT}: let $n = |N|-1$; if $N > 0$ returns an integer uniformly distributed in $[0, n]$; if $N < 0$ returns an integer uniformly distributed in $[-n, n]$. Omitting the argument is equivalent to \kbd{random(2\pow31)}. \item \typ{REAL}: returns a real number in $[0,1[$ with the same accuracy as $N$ (whose mantissa has the same number of significant words). \item \typ{INTMOD}: returns a random intmod for the same modulus. \item \typ{FFELT}: returns a random element in the same finite field. \item \typ{VEC} of length $2$, $N = [a,b]$: returns an integer uniformly distributed between $a$ and $b$. \item \typ{VEC} generated by \kbd{ellinit} over a finite field $k$ (coefficients are \typ{INTMOD}s modulo a prime or \typ{FFELT}s): returns a ``random'' $k$-rational \emph{affine} point on the curve. More precisely if the curve has a single point (at infinity!) we return it; otherwise we return an affine point by drawing an abscissa uniformly at random until \tet{ellordinate} succeeds. Note that this is definitely not a uniform distribution over $E(k)$, but it should be good enough for applications. \item \typ{POL} return a random polynomial of degree at most the degree of $N$. The coefficients are drawn by applying \kbd{random} to the leading coefficient of $N$. \bprog ? random(10) %1 = 9 ? random(Mod(0,7)) %2 = Mod(1, 7) ? a = ffgen(ffinit(3,7), 'a); random(a) %3 = a^6 + 2*a^5 + a^4 + a^3 + a^2 + 2*a ? E = ellinit([3,7]*Mod(1,109)); random(E) %4 = [Mod(103, 109), Mod(10, 109)] ? E = ellinit([1,7]*a^0); random(E) %5 = [a^6 + a^5 + 2*a^4 + 2*a^2, 2*a^6 + 2*a^4 + 2*a^3 + a^2 + 2*a] ? random(Mod(1,7)*x^4) %6 = Mod(5, 7)*x^4 + Mod(6, 7)*x^3 + Mod(2, 7)*x^2 + Mod(2, 7)*x + Mod(5, 7) @eprog These variants all depend on a single internal generator, and are independent from your operating system's random number generators. A random seed may be obtained via \tet{getrand}, and reset using \tet{setrand}: from a given seed, and given sequence of \kbd{random}s, the exact same values will be generated. The same seed is used at each startup, reseed the generator yourself if this is a problem. Note that internal functions also call the random number generator; adding such a function call in the middle of your code will change the numbers produced. \misctitle{Technical note} Up to version 2.4 included, the internal generator produced pseudo-random numbers by means of linear congruences, which were not well distributed in arithmetic progressions. We now use Brent's XORGEN algorithm, based on Feedback Shift Registers, see \url{https://wwwmaths.anu.edu.au/~brent/random.html}. The generator has period $2^{4096}-1$, passes the Crush battery of statistical tests of L'Ecuyer and Simard, but is not suitable for cryptographic purposes: one can reconstruct the state vector from a small sample of consecutive values, thus predicting the entire sequence. \misctitle{Parallelism} In multi-threaded programs, each thread has a separate generator. They all start in the same \kbd{setrand(1)} state, so will all produce the same sequence of pseudo-random numbers although the various states are not shared. To avoid this, use \kbd{setrand} to provide a different starting state to each thread: \bprog \\ with 8 threads ? parvector(8, i, random()) \\ all 8 threads return the same number %1 = [1546275796, 1546275796, ... , 1546275796] ? parvector(8, i, random()) \\ ... and again since they are restarted %2 = [1546275796, 1546275796, ... , 1546275796] ? s = [1..8]; \\ 8 random seeds; we could use vector(8,i,random()) ? parvector(8, i, setrand(s[i]); random()) \\ now we get 8 different numbers @eprog Variant: Also available: \fun{GEN}{ellrandom}{GEN E} and \fun{GEN}{ffrandom}{GEN a}. pari-2.17.2/src/functions/conversions/Colrev0000644000175000017500000000111514676526175017531 0ustar billbillFunction: Colrev Section: conversions C-Name: gtocolrev0 Prototype: GD0,L, Help: Colrev(x,{n}): transforms the object x into a column vector of dimension n in reverse order with respect to Col(x,{n}). Empty vector if x is omitted. Description: (gen):vec gtocolrev($1) Doc: as $\kbd{Col}(x, -n)$, then reverse the result. In particular, \kbd{Colrev} is the reciprocal function of \kbd{Polrev}: the coefficients of the vector start with the constant coefficient of the polynomial and the others follow by increasing degree. Variant: \fun{GEN}{gtocolrev}{GEN x} is also available. pari-2.17.2/src/functions/conversions/padicprec0000644000175000017500000000211514567450071020220 0ustar billbillFunction: padicprec Section: conversions C-Name: gppadicprec Prototype: GG Help: padicprec(x,p): return the absolute p-adic precision of object x. Doc: returns the absolute $p$-adic precision of the object $x$; this is the minimum precision of the components of $x$. The result is \tet{+oo} if $x$ is an exact object (as a $p$-adic): \bprog ? padicprec((1 + O(2^5)) * x + (2 + O(2^4)), 2) %1 = 4 ? padicprec(x + 2, 2) %2 = +oo ? padicprec(2 + x + O(x^2), 2) %3 = +oo @eprog\noindent The function raises an exception if it encounters an object incompatible with $p$-adic computations: \bprog ? padicprec(O(3), 2) *** at top-level: padicprec(O(3),2) *** ^----------------- *** padicprec: inconsistent moduli in padicprec: 3 != 2 ? padicprec(1.0, 2) *** at top-level: padicprec(1.0,2) *** ^---------------- *** padicprec: incorrect type in padicprec (t_REAL). @eprog Variant: Also available is the function \fun{long}{padicprec}{GEN x, GEN p}, which returns \tet{LONG_MAX} if $x = 0$ and the $p$-adic precision as a \kbd{long} integer. pari-2.17.2/src/functions/conversions/lift0000644000175000017500000000362014676526175017240 0ustar billbillFunction: lift Section: conversions C-Name: lift0 Prototype: GDn Help: lift(x,{v}): if v is omitted, lifts elements of Z/nZ to Z, of Qp to Q, and of K[x]/(P) to K[x]. Otherwise lift only polmods with main variable v. Description: (pol):pol lift($1) (vec):vec lift($1) (gen):gen lift($1) (pol, var):pol lift0($1, $2) (vec, var):vec lift0($1, $2) (gen, var):gen lift0($1, $2) Doc: if $v$ is omitted, lifts intmods from $\Z/n\Z$ in $\Z$, $p$-adics from $\Q_{p}$ to $\Q$ (as \tet{truncate}), and polmods to polynomials. Otherwise, lifts only polmods whose modulus has main variable~$v$. \typ{FFELT} are not lifted, nor are List elements: you may convert the latter to vectors first, or use \kbd{apply(lift,L)}. More generally, components for which such lifts are meaningless (e.g. character strings) are copied verbatim. \bprog ? lift(Mod(5,3)) %1 = 2 ? lift(3 + O(3^9)) %2 = 3 ? lift(Mod(x,x^2+1)) %3 = x ? lift(Mod(x,x^2+1)) %4 = x @eprog Lifts are performed recursively on an object components, but only by \emph{one level}: once a \typ{POLMOD} is lifted, the components of the result are \emph{not} lifted further. \bprog ? lift(x * Mod(1,3) + Mod(2,3)) %4 = x + 2 ? lift(x * Mod(y,y^2+1) + Mod(2,3)) %5 = y*x + Mod(2, 3) \\@com do you understand this one? ? lift(x * Mod(y,y^2+1) + Mod(2,3), 'x) %6 = Mod(y, y^2 + 1)*x + Mod(Mod(2, 3), y^2 + 1) ? lift(%, y) %7 = y*x + Mod(2, 3) @eprog\noindent To recursively lift all components not only by one level, but as long as possible, use \kbd{liftall}. To lift only \typ{INTMOD}s and \typ{PADIC}s components, use \tet{liftint}. To lift only \typ{POLMOD}s components, use \tet{liftpol}. Finally, \tet{centerlift} allows to lift \typ{INTMOD}s and \typ{PADIC}s using centered residues (lift of smallest absolute value). Variant: Also available is \fun{GEN}{lift}{GEN x} corresponding to \kbd{lift0(x,-1)}. pari-2.17.2/src/functions/conversions/serchop0000644000175000017500000000071414676526175017746 0ustar billbillFunction: serchop Section: conversions C-Name: serchop Prototype: GD0,L, Help: serchop(s,{n=0}): remove all terms of degree strictly less than n in series s. Doc: remove all terms of degree strictly less than $n$ in series $s$. When the series contains no terms of degree $< n$, return $O(x^{n})$. \bprog ? s = 1/x + x + 2*x^2 + O(x^3); ? serchop(s) %2 = x + 2*x^3 + O(x^3) ? serchop(s, 2) %3 = 2*x^2 + O(x^3) ? serchop(s, 100) %4 = O(x^100) @eprog pari-2.17.2/src/functions/conversions/digits0000644000175000017500000000215214676526175017564 0ustar billbillFunction: digits Section: conversions C-Name: digits Prototype: GDG Help: digits(x,{b}): gives the vector formed by the digits of x in base b. Doc: outputs the vector of the digits of $x$ in base $b$, where $x$ and $b$ are integers ($b = 10$ by default), from most significant down to least significant, the digits being the the integers $0$, $1$, \dots $|b|-1$. If $b>0$ and $x<0$, return the digits of $|x|$. For $x\ge1$ and $b>0$, the number of digits is $\kbd{logint}(x,b) + 1$. See \kbd{fromdigits} for the reverse operation. We also allow $x$ an integral $p$-adic in which case $b$ should be omitted or equal to $p$. Digits are still ordered from most significant to least significant in the $p$-adic sense (meaning we start from $x$ mod $p$); trailing zeros are truncated. \bprog ? digits(1230) %1 = [1, 2, 3, 0] ? digits(10, 2) \\ base 2 %2 = [1, 0, 1, 0] @eprog\noindent By convention, $0$ has no digits: \bprog ? digits(0) %3 = [] ? digits(10,-2) \\ base -2 %4 = [1, 1, 1, 1, 0] \\ 10 = -2 + 4 - 8 + 16 ? 1105 + O(5^5) %5 = 5 + 4*5^2 + 3*5^3 + O(5^5) ? digits(%) %6 = [0, 1, 4, 3] @eprog pari-2.17.2/src/functions/conversions/simplify0000644000175000017500000000176213637407207020131 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.17.2/src/functions/conversions/serprec0000644000175000017500000000124614567450071017735 0ustar billbillFunction: serprec Section: conversions C-Name: gpserprec Prototype: Gn Help: serprec(x,v): return the absolute precision x with respect to power series in the variable v. Doc: returns the absolute precision of $x$ with respect to power series in the variable $v$; this is the minimum precision of the components of $x$. The result is \tet{+oo} if $x$ is an exact object (as a series in $v$): \bprog ? serprec(x + O(y^2), y) %1 = 2 ? serprec(x + 2, x) %2 = +oo ? serprec(2 + x + O(x^2), y) %3 = +oo @eprog Variant: Also available is \fun{long}{serprec}{GEN x, GEN p}, which returns \tet{LONG_MAX} if $x = 0$, otherwise the series precision as a \kbd{long} integer. pari-2.17.2/src/functions/conversions/component0000644000175000017500000000332414567450071020273 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 ".". Description: (error,small):gen err_get_compo($1, $2) (gen,small):gen compo($1,$2) 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{polcoef}, 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 accuracy) ? component(x, 1) %3 = 3 \\ p ? q = Qfb(1,2,3); ? component(q, 1) %5 = 1 @eprog pari-2.17.2/src/functions/conversions/imag0000644000175000017500000000066714567450071017215 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)$. \bprog ? imag(3 + I) %1 = 1 ? x = 3 + quadgen(-23); ? imag(x) \\ as a quadratic number %3 = 1 ? imag(x * 1.) \\ as a complex number %4 = 2.3979157616563597707987190320813469600 @eprog pari-2.17.2/src/functions/conversions/bitprecision0000644000175000017500000000323014567450071020757 0ustar billbillFunction: bitprecision Section: conversions C-Name: bitprecision00 Prototype: GDG Help: bitprecision(x,{n}): if n is present and positive, return x at precision n bits. If n is omitted, return real precision of object x in bits. Doc: the function behaves differently according to whether $n$ is present or not. If $n$ is missing, the function returns the (floating point) precision in bits of the PARI object $x$. If $x$ is an exact object, the function returns \kbd{+oo}. \bprog ? bitprecision(exp(1e-100)) %1 = 512 \\ 512 bits ? bitprecision( [ exp(1e-100), 0.5 ] ) %2 = 128 \\ minimal accuracy among components ? bitprecision(2 + x) %3 = +oo \\ exact object @eprog\noindent Use \kbd{getlocalbitprec()} to retrieve the working bit precision (as modified by possible \kbd{localbitprec} statements). If $n$ is present and positive, the function creates a new object equal to $x$ with the new bit-precision roughly $n$. In fact, the smallest multiple of 64 (resp.~32 on a 32-bit machine) larger than or equal to $n$. For $x$ a vector or a matrix, the operation is done componentwise; for series and polynomials, the operation is done coefficientwise. For real $x$, $n$ is the number of desired significant \emph{bits}. If $n$ is smaller than the precision of $x$, $x$ is truncated, otherwise $x$ is extended with zeros. For exact or non-floating-point types, no change. \bprog ? bitprecision(Pi, 10) \\ actually 64 bits ~ 19 decimal digits %1 = 3.141592653589793239 ? bitprecision(1, 10) %2 = 1 ? bitprecision(1 + O(x), 10) %3 = 1 + O(x) ? bitprecision(2 + O(3^5), 10) %4 = 2 + O(3^5) @eprog\noindent pari-2.17.2/src/functions/conversions/Pol0000644000175000017500000000336314676526175017040 0ustar billbillFunction: Pol Section: conversions C-Name: gtopoly Prototype: GDn Description: (gen,?var):pol gtopoly($1, $2) Help: Pol(t,{v='x}): convert t (usually a vector or a power series) into a polynomial with variable v, starting with the leading coefficient. Doc: transforms the object $t$ into a polynomial with main variable $v$. If $t$ is a scalar, this gives a constant polynomial. If $t$ is a power series with nonnegative valuation or a rational function, the effect is similar to \kbd{truncate}, i.e.~we chop off the $O(X^{k})$ or compute the Euclidean quotient of the numerator by the denominator, then change the main variable of the result to $v$. The main use of this function is when $t$ is a vector: it creates the polynomial whose coefficients are given by $t$, with $t[1]$ being the leading coefficient (which can be zero). It is much faster to evaluate \kbd{Pol} on a vector of coefficients in this way, than the corresponding formal expression $a_{n} X^{n} + \dots + a_{0}$, which is evaluated naively exactly as written (linear versus quadratic time in $n$). \tet{Polrev} can be used if one wants $x[1]$ to be the constant coefficient: \bprog ? Pol([1,2,3]) %1 = x^2 + 2*x + 3 ? Polrev([1,2,3]) %2 = 3*x^2 + 2*x + 1 @eprog\noindent The reciprocal function of \kbd{Pol} (resp.~\kbd{Polrev}) is \kbd{Vec} (resp.~ \kbd{Vecrev}). \bprog ? Vec(Pol([1,2,3])) %1 = [1, 2, 3] ? Vecrev( Polrev([1,2,3]) ) %2 = [1, 2, 3] @eprog\noindent \misctitle{Warning} This is \emph{not} a substitution function. It will not transform an object containing variables of higher priority than~$v$. \bprog ? Pol(x + y, y) *** at top-level: Pol(x+y,y) *** ^---------- *** Pol: variable must have higher priority in gtopoly. @eprog pari-2.17.2/src/functions/conversions/bitxor0000644000175000017500000000117714676526175017616 0ustar billbillFunction: bitxor Section: conversions C-Name: gbitxor Prototype: GG Help: bitxor(x,y): bitwise "exclusive or" of two integers x and y. Negative numbers behave as if modulo big power of 2. Description: (small, small):small:parens $(1)^$(2) (gen, gen):int gbitxor($1, $2) Doc: bitwise (exclusive) \tet{or} \sidx{bitwise exclusive or}of two integers $x$ and $y$, that is the integer $$\sum (x_{i}~\kbd{xor}~y_{i}) 2^{i}$$ See \secref{se:bitand} for the behavior for negative arguments. Variant: Also available is \fun{GEN}{ibitxor}{GEN x, GEN y}, which returns the bitwise \emph{xor} of $|x|$ and $|y|$, two integers. pari-2.17.2/src/functions/conversions/fromdigits0000644000175000017500000000143414676526175020452 0ustar billbillFunction: fromdigits Section: conversions C-Name: fromdigits Prototype: GDG Help: fromdigits(x,{b=10}): gives the integer formed by the elements of x seen as the digits of a number in base b. Doc: gives the integer formed by the elements of $x$ seen as the digits of a number in base $b$ ($b = 10$ by default); $b$ must be an integer satisfying $|b|>1$. This is the reverse of \kbd{digits}: \bprog ? digits(1234, 5) %1 = [1,4,4,1,4] ? fromdigits([1,4,4,1,4],5) %2 = 1234 @eprog\noindent By convention, $0$ has no digits: \bprog ? fromdigits([]) %3 = 0 @eprog\noindent This function works with $x$ a \typ{VECSMALL}; and also with $b < 0$ or $x[i]$ not an actual digit in base $b$ (i.e., $x[i] < 0$ or $x[i] \geq b$): if $x$ has length $n$, we return $\sum_{i=1}^{n} x[i] b^{n-i}$. pari-2.17.2/src/functions/conversions/varlower0000644000175000017500000000634014567450071020133 0ustar billbillFunction: varlower Section: conversions C-Name: varlower Prototype: sDn Help: varlower(name,{v}): return a variable 'name' whose priority is lower than the priority of v (of all existing variables if v is omitted. Doc: return a variable \emph{name} whose priority is lower than the priority of $v$ (of all existing variables if $v$ is omitted). This is a counterpart to \tet{varhigher}. New GP variables directly created by the interpreter always have lower priority than existing GP variables, but it is not easy to check whether an identifier is currently unused, so that the corresponding variable has the expected priority when it's created! Thus, depending on the session history, the same command may fail or succeed: \bprog ? t; z; \\ now t > z ? rnfequation(t^2+1,z^2-t) *** at top-level: rnfequation(t^2+1,z^ *** ^-------------------- *** rnfequation: incorrect priority in rnfequation: variable t >= t @eprog\noindent Restart and retry: \bprog ? z; t; \\ now z > t ? rnfequation(t^2+1,z^2-t) %2 = z^4 + 1 @eprog\noindent It is quite annoying for package authors, when trying to define a base ring, to notice that the package may fail for some users depending on their session history. The safe way to do this is as follows: \bprog ? z; t; \\ In new session: now z > t ... ? t = varlower("t", 'z); ? rnfequation(t^2+1,z^2-2) %2 = z^4 - 2*z^2 + 9 ? variable() %3 = [x, y, z, t] @eprog \bprog ? t; z; \\ In new session: now t > z ... ? t = varlower("t", 'z); \\ create a new variable, still printed "t" ? rnfequation(t^2+1,z^2-2) %2 = z^4 - 2*z^2 + 9 ? variable() %3 = [x, y, t, z, t] @eprog\noindent Now both constructions succeed. Note that in the first case, \kbd{varlower} is essentially a no-op, the existing variable $t$ has correct priority. While in the second case, two different variables are displayed as \kbd{t}, one with higher priority than $z$ (created in the first line) and another one with lower priority (created by \kbd{varlower}). \misctitle{Caution 1} The \emph{name} is an arbitrary character string, only used for display purposes and need not be related to the GP variable holding the result, nor to be a valid variable name. In particular the \emph{name} can not be used to retrieve the variable, it is not even present in the parser's hash tables. \bprog ? x = varlower("#"); ? x^2 %2 = #^2 @eprog \misctitle{Caution 2} There are a limited number of variables and if no existing variable with the given display name has the requested priority, the call to \kbd{varlower} uses up one such slot. Do not create new variables in this way unless it's absolutely necessary, reuse existing names instead and choose sensible priority requirements: if you only need a variable with higher priority than $x$, state so rather than creating a new variable with highest priority. \bprog \\ quickly use up all variables ? n = 0; while(1,varlower("x"); n++) *** at top-level: n=0;while(1,varlower("x");n++) *** ^------------------- *** varlower: no more variables available. *** Break loop: type 'break' to go back to GP prompt break> n 65510 \\ infinite loop: here we reuse the same 'tmp' ? n = 0; while(1,varlower("tmp", x); n++) @eprog pari-2.17.2/src/functions/conversions/varhigher0000644000175000017500000000477414567450071020262 0ustar billbillFunction: varhigher Section: conversions C-Name: varhigher Prototype: sDn Help: varhigher(name,{v}): return a variable 'name' whose priority is higher than the priority of v (of all existing variables if v is omitted). Doc: return a variable \emph{name} whose priority is higher than the priority of $v$ (of all existing variables if $v$ is omitted). This is a counterpart to \tet{varlower}. \bprog ? Pol([x,x], t) *** at top-level: Pol([x,x],t) *** ^------------ *** Pol: incorrect priority in gtopoly: variable x <= t ? t = varhigher("t", x); ? Pol([x,x], t) %3 = x*t + x @eprog\noindent This routine is useful since new GP variables directly created by the interpreter always have lower priority than existing GP variables. When some basic objects already exist in a variable that is incompatible with some function requirement, you can now create a new variable with a suitable priority instead of changing variables in existing objects: \bprog ? K = nfinit(x^2+1); ? rnfequation(K,y^2-2) *** at top-level: rnfequation(K,y^2-2) *** ^-------------------- *** rnfequation: incorrect priority in rnfequation: variable y >= x ? y = varhigher("y", x); ? rnfequation(K, y^2-2) %3 = y^4 - 2*y^2 + 9 @eprog\noindent \misctitle{Caution 1} The \emph{name} is an arbitrary character string, only used for display purposes and need not be related to the GP variable holding the result, nor to be a valid variable name. In particular the \emph{name} can not be used to retrieve the variable, it is not even present in the parser's hash tables. \bprog ? x = varhigher("#"); ? x^2 %2 = #^2 @eprog \misctitle{Caution 2} There are a limited number of variables and if no existing variable with the given display name has the requested priority, the call to \kbd{varhigher} uses up one such slot. Do not create new variables in this way unless it's absolutely necessary, reuse existing names instead and choose sensible priority requirements: if you only need a variable with higher priority than $x$, state so rather than creating a new variable with highest priority. \bprog \\ quickly use up all variables ? n = 0; while(1,varhigher("tmp"); n++) *** at top-level: n=0;while(1,varhigher("tmp");n++) *** ^------------------- *** varhigher: no more variables available. *** Break loop: type 'break' to go back to GP prompt break> n 65510 \\ infinite loop: here we reuse the same 'tmp' ? n = 0; while(1,varhigher("tmp", x); n++) @eprog pari-2.17.2/src/functions/conversions/Vec0000644000175000017500000000537714760123736017020 0ustar billbillFunction: Vec Section: conversions C-Name: gtovec0 Prototype: GD0,L, Help: Vec(x,{n}): transforms the object x into a vector of dimension n. Description: (gen):vec gtovec($1) Doc: transforms the object $x$ into a row vector. The dimension of the resulting vector can be optionally specified via the extra parameter $n$. If $n$ is omitted or $0$, the dimension depends on the type of $x$; the vector has a single component, except when $x$ is \item a vector or a quadratic form: returns the initial object considered as a row vector, \item a polynomial or a power series: returns a vector consisting of the coefficients. 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 particular the valuation is ignored (which makes the function useful for series of negative valuation): \bprog ? Vec(3*x^2 + x) %1 = [3, 1, 0] ? Vec(x^2 + 3*x^3 + O(x^5)) %2 = [1, 3, 0] ? Vec(x^-2 + 3*x^-1 + O(x)) %3 = [1, 3, 0] @eprog\noindent \kbd{Vec} is the reciprocal function of \kbd{Pol} for a polynomial and of \kbd{Ser} for power series of valuation $0$. \item a matrix: returns the vector of columns comprising the matrix, \bprog ? m = [1,2,3;4,5,6] %4 = [1 2 3] [4 5 6] ? Vec(m) %5 = [[1, 4]~, [2, 5]~, [3, 6]~] @eprog \item a character string: returns the vector of individual characters (as strings of length $1$), \bprog ? Vec("PARI") %6 = ["P", "A", "R", "I"] @eprog \item a map: returns the vector of the domain of the map, \item an error context (\typ{ERROR}): returns the error components, see \tet{iferr}. In the last four cases (matrix, character string, map, error), $n$ is meaningless and must be omitted or an error is raised. Otherwise, if $n$ is given, $0$ entries are appended at the end of the vector if $n > 0$, and prepended at the beginning if $n < 0$. The dimension of the resulting vector is $|n|$. If the original object had fewer than $|n|$ components, it is truncated from the right if $n > 0$ and from the left if $n < 0$: \bprog ? v = [1,2,3,4]; ? forstep(i=5, 2, -1, print(Vec(v, i))); [1, 2, 3, 4, 0] [1, 2, 3, 4] [1, 2, 3] \\ truncated from the right [1, 2] ? forstep(i=5, 2, -1, print(Vec(v, -i))); [0, 1, 2, 3, 4] [1, 2, 3, 4] [2, 3, 4] \\ truncated from the left [3, 4] @eprog These rules allow to write a conversion function for series that takes positive valuations into account: \bprog ? serVec(s) = Vec(s, -serprec(s,variable(s))); ? serVec(x^2 + 3*x^3 + O(x^5)) %2 = [0, 0, 1, 3, 0] @eprog\noindent (That function is not intended for series of negative valuation.) Variant: \fun{GEN}{gtovec}{GEN x} is also available. pari-2.17.2/src/functions/conversions/binary0000644000175000017500000000123014567450071017547 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. \bprog ? binary(10) %1 = [1, 0, 1, 0] ? binary(3.14) %2 = [[1, 1], [0, 0, 1, 0, 0, 0, [...]] ? binary([1,2]) %3 = [[1], [1, 0]] @eprog\noindent For integer $x\ge1$, the number of bits is $\kbd{logint}(x,2) + 1$. By convention, $0$ has no digits: \bprog ? binary(0) %4 = [] @eprog pari-2.17.2/src/functions/conversions/bitand0000644000175000017500000000160214676526175017541 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 nonnegative 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.17.2/src/functions/conversions/conj0000644000175000017500000000062113637407207017217 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.17.2/src/functions/conversions/bitor0000644000175000017500000000115614676526175017423 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{or} of $|x|$ and $|y|$, two integers. pari-2.17.2/src/functions/conversions/numerator0000644000175000017500000000201414567450071020300 0ustar billbillFunction: numerator Section: conversions C-Name: numerator Prototype: GDG Help: numerator(f,{D}): numerator of f. Doc: numerator of $f$. This is defined as \kbd{f * denominator(f,D)}, see \kbd{denominator} for details. The optional argument $D$ allows to control over which ring we compute the denominator: \item $1$: we only consider the underlying $\Q$-structure and the denominator is a (positive) rational integer \item a simple variable, say \kbd{'x}: all entries as rational functions in $K(x)$ and the denominator is a polynomial in $x$. \bprog ? f = x + 1/y + 1/2; ? numerator(f) \\ a t_POL in x %2 = x + ((y + 2)/(2*y)) ? numerator(f, 1) \\ Q-denominator is 2 %3 = x + ((y + 2)/y) ? numerator(f, y) \\ as a rational function in y %5 = 2*y*x + (y + 2) @eprog Variant: Also available are \fun{GEN}{numer}{GEN x} which implements the not very useful default behaviour ($D$ is \kbd{NULL}) and \fun{GEN}{Q_remove_denom}{GEN x, GEN *ptd} ($D = 1$) and also returns the denominator (coding $1$ as \kbd{NULL}). pari-2.17.2/src/functions/conversions/norm0000644000175000017500000000066314676526175017261 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.17.2/src/functions/conversions/bitneg0000644000175000017500000000115114676526175017547 0ustar billbillFunction: bitneg Section: conversions C-Name: gbitneg Prototype: GD-1,L, Help: bitneg(x,{n=-1}): bitwise negation of an integers x truncated to n bits. n=-1 means represent infinite sequences of bit 1 as negative numbers. Negative numbers behave as if modulo big power of 2. Doc: \idx{bitwise negation} of an integer $x$, truncated to $n$ bits, $n\geq 0$, that is the integer $$\sum_{i=0}^{n-1} \kbd{not}(x_{i}) 2^{i}.$$ The special case $n=-1$ means no truncation: an infinite sequence of leading $1$ is then represented as a negative number. See \secref{se:bitand} for the behavior for negative arguments. pari-2.17.2/src/functions/conversions/ceil0000644000175000017500000000100113637407207017173 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.17.2/src/functions/conversions/oo0000644000175000017500000000060114567450071016701 0ustar billbillFunction: oo Section: conversions C-Name: mkoo Prototype: Help: oo=oo(): infinity. Doc: returns an object meaning $+\infty$, for use in functions such as \kbd{intnum}. It can be negated (\kbd{-oo} represents $-\infty$), and compared to real numbers (\typ{INT}, \typ{FRAC}, \typ{REAL}), with the expected meaning: $+\infty$ is greater than any real number and $-\infty$ is smaller. pari-2.17.2/src/functions/conversions/variables0000644000175000017500000000241614676526175020254 0ustar billbillFunction: variables Section: conversions C-Name: variables_vec Prototype: DG Help: variables({x}): all variables occurring in object x, sorted by decreasing priority. Returns the list of user variables if x is omitted. Doc: returns the list of all variables occurring in object $x$ sorted by decreasing priority. If $x$ is omitted, return all polynomial variables known to the interpreter (this will include \kbd{x} and \kbd{y}, which are always defined on startup); user variables which do not occur in \typ{POL} or \typ{SER} constructions are \emph{not} included. To see all user variables, use \b{uv}. \bprog ? variables([x^2 + y*z + O(t), a+x]) %1 = [x, y, z, t, a] @eprog\noindent The construction \bprog if (!variables(x),...) @eprog\noindent can be used to test whether a variable is attached to $x$. If \kbd{varhigher} or \kbd{varlower} are used, it is quite possible to end up with different variables (having different priorities) printed in the same way. They will then appear multiple times in the output: \bprog ? y1 = varhigher("y"); y2 = varlower("y"); ? variables(y*y1*y2) %2 = [y, y, y] @eprog Variant: Also available is \fun{GEN}{variables_vecsmall}{GEN x} which returns the (sorted) variable numbers instead of the attached monomials of degree 1. pari-2.17.2/src/functions/conversions/liftall0000644000175000017500000000140714676526175017732 0ustar billbillFunction: liftall Section: conversions C-Name: liftall Prototype: G Help: liftall(x): lifts every element of Z/nZ to Z, of Qp to Q, and of K[x]/(P) to K[x]. Description: (pol):pol liftall($1) (vec):vec liftall($1) (gen):gen liftall($1) Doc: recursively lift all components of $x$ from $\Z/n\Z$ to $\Z$, from $\Q_{p}$ to $\Q$ (as \tet{truncate}), and polmods to polynomials. \typ{FFELT} are not lifted, nor are List elements: you may convert the latter to vectors first, or use \kbd{apply(liftall,L)}. More generally, components for which such lifts are meaningless (e.g. character strings) are copied verbatim. \bprog ? liftall(x * (1 + O(3)) + Mod(2,3)) %1 = x + 2 ? liftall(x * Mod(y,y^2+1) + Mod(2,3)*Mod(z,z^2)) %2 = y*x + 2*z @eprog pari-2.17.2/src/functions/conversions/characteristic0000644000175000017500000000073614567450071021265 0ustar billbillFunction: characteristic Section: conversions C-Name: characteristic Prototype: mG Help: characteristic(x): characteristic of the base ring over which x is defined. Doc: returns the characteristic of the base ring over which $x$ is defined (as defined by \typ{INTMOD} and \typ{FFELT} components). The function raises an exception if incompatible primes arise from \typ{FFELT} and \typ{PADIC} components. \bprog ? characteristic(Mod(1,24)*x + Mod(1,18)*y) %1 = 6 @eprog pari-2.17.2/src/functions/conversions/Set0000644000175000017500000000135114567450071017022 0ustar billbillFunction: Set Section: conversions C-Name: gtoset Prototype: DG Help: Set({x=[]}): convert x into a set, i.e. a row vector with strictly increasing coefficients. Empty set if x is omitted. Description: ():vec cgetg(1,t_VEC) (gen):vec gtoset($1) Doc: converts $x$ into a set, i.e.~into a row vector, with strictly increasing entries with respect to the (somewhat arbitrary) universal comparison function \tet{cmp}. Standard container types \typ{VEC}, \typ{COL}, \typ{LIST} and \typ{VECSMALL} are converted to the set with corresponding elements. All others are converted to a set with one element. \bprog ? Set([1,2,4,2,1,3]) %1 = [1, 2, 3, 4] ? Set(x) %2 = [x] ? Set(Vecsmall([1,3,2,1,3])) %3 = [1, 2, 3] @eprog pari-2.17.2/src/functions/conversions/truncate0000644000175000017500000000326114676526175020130 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.17.2/src/functions/conversions/variable0000644000175000017500000000351114567450071020054 0ustar billbillFunction: variable Section: conversions C-Name: gpolvar Prototype: DG Help: variable({x}): main variable of object x. Gives p for p-adic x, 0 if no variable can be attached to x. Returns the list of user variables if x is omitted. Description: (pol):var:parens:copy $var:1 (gen):gen gpolvar($1) Doc: gives the main variable of the object $x$ (the variable with the highest priority used in $x$), and $p$ if $x$ is a $p$-adic number. Return $0$ if $x$ has no variable attached to it. \bprog ? variable(x^2 + y) %1 = x ? variable(1 + O(5^2)) %2 = 5 ? variable([x,y,z,t]) %3 = x ? variable(1) %4 = 0 @eprog\noindent The construction \bprog if (!variable(x),...) @eprog\noindent can be used to test whether a variable is attached to $x$. If $x$ is omitted, returns the list of user variables known to the interpreter, by order of decreasing priority. (Highest priority is initially $x$, which come first until \tet{varhigher} is used.) If \kbd{varhigher} or \kbd{varlower} are used, it is quite possible to end up with different variables (with different priorities) printed in the same way: they will then appear multiple times in the output: \bprog ? varhigher("y"); ? varlower("y"); ? variable() %4 = [y, x, y] @eprog\noindent Using \kbd{v = variable()} then \kbd{v[1]}, \kbd{v[2]}, etc.~allows to recover and use existing variables. Variant: However, in library mode, this function should not be used for $x$ non-\kbd{NULL}, since \tet{gvar} is more appropriate. Instead, for $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.17.2/src/functions/conversions/length0000644000175000017500000000236414676526175017567 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 maps: number of entries (0 for empty maps), \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 ? M = Map([a,b; c,d; e,f]); #M %6 = 3 @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. Variant: Also available is \fun{long}{gtranslength}{GEN x} which return the length of \kbd{x~}, that is the number of lines of matrices. pari-2.17.2/src/functions/conversions/bitnegimply0000644000175000017500000000131014676526175020617 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.17.2/src/functions/number_theoretical/0000755000175000017500000000000014760315601017641 5ustar billbillpari-2.17.2/src/functions/number_theoretical/sqrtint0000644000175000017500000000154014676526175021310 0ustar billbillFunction: sqrtint Section: number_theoretical C-Name: sqrtint0 Prototype: GD& Help: sqrtint(x,{&r}): integer square root y of x, where x is a nonnegative real number. If r is present, set it to the remainder x - y^2. Description: (gen):int sqrtint($1) Doc: returns the integer square root of $x$, i.e. the largest integer $y$ such that $y^{2} \leq x$, where $x$ a nonnegative real number. If $r$ is present, set it to the remainder $r = x - y^{2}$, which satisfies $0\leq r < 2y + 1$. Further, when $x$ is an integer, $r$ is an integer satisfying $0 \leq r \leq 2y$. \bprog ? x = 120938191237; sqrtint(x) %1 = 347761 ? sqrt(x) %2 = 347761.68741970412747602130964414095216 ? y = sqrtint(x, &r); r %3 = 478116 ? x - y^2 %4 = 478116 ? sqrtint(9/4, &r) \\ not 3/2 ! %5 = 1 ? r %6 = 5/4 @eprog Variant: Also available is \fun{GEN}{sqrtint}{GEN a}. pari-2.17.2/src/functions/number_theoretical/factorint0000644000175000017500000000404614676526175021601 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 if 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.17.2/src/functions/number_theoretical/prime0000644000175000017500000000072214676526175020721 0ustar billbillFunction: prime Section: number_theoretical C-Name: prime Prototype: L Help: prime(n): returns the n-th prime (n C-integer). Doc: the $n^{\text{th}}$ prime number \bprog ? prime(10^9) %1 = 22801763489 @eprog\noindent Uses checkpointing and a naive $O(n)$ algorithm. Will need about 30 minutes for $n$ up to $10^{11}$; make sure to start gp with \kbd{primelimit} at least $\sqrt{p_{n}}$, e.g. the value $\sqrt{n\log (n\log n)}$ is guaranteed to be sufficient. pari-2.17.2/src/functions/number_theoretical/ffprimroot0000644000175000017500000000213714676526175021776 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 factorization \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.17.2/src/functions/number_theoretical/charpow0000644000175000017500000000332314676526175021250 0ustar billbillFunction: charpow Section: number_theoretical C-Name: charpow0 Prototype: GGG Help: charpow(cyc,a,n): given a finite abelian group (by its elementary divisors cyc) a character a and an integer n return the character a^n. Doc: let \var{cyc} represent a finite abelian group by its elementary divisors, i.e. $(d_{j})$ represents $\sum_{j \leq k} \Z/d_{j}\Z$ with $d_{k} \mid \dots \mid d_{1}$; any object which has a \kbd{.cyc} method is also allowed, e.g.~the output of \kbd{znstar} or \kbd{bnrinit}. A character on this group is given by a row vector $\chi = [a_{1},\ldots,a_{n}]$ such that $\chi(\prod g_{j}^{n_{j}}) = \exp(2\pi i\sum_{j} a_{j} n_{j} / d_{j})$, where $g_{j}$ denotes the generator (of order $d_{j}$) of the $j$-th cyclic component. Given $n\in \Z$ and a character $a$, return the character $a^{n}$. \bprog ? cyc = [15,5]; a = [1,1]; ? charpow(cyc, a, 3) %2 = [3, 3] ? charpow(cyc, a, 5) %2 = [5, 0] ? bnf = bnfinit(x^2+23); ? bnf.cyc %4 = [3] ? charpow(bnf, [1], 3) %5 = [0] @eprog\noindent For Dirichlet characters on $(\Z/N\Z)^{*}$, additional representations are available (Conrey labels, Conrey logarithm), see \secref{se:dirichletchar} or \kbd{??character} and the output uses the same format as the input. \bprog ? G = znstar(100, 1); ? G.cyc %2 = [20, 2] ? a = [10, 1]; \\ standard representation for characters ? b = 7; \\ Conrey label; ? c = znconreylog(G, 11); \\ Conrey log ? charpow(G, a,3) %6 = [10, 1] \\ standard representation ? charpow(G, b,3) %7 = 43 \\ Conrey label ? charpow(G, c,3) %8 = [1, 8]~ \\ Conrey log @eprog Variant: Also available is \fun{GEN}{charpow}{GEN cyc, GEN a, GEN n}, when \kbd{cyc} is known to be a vector of elementary divisors (no check). pari-2.17.2/src/functions/number_theoretical/dirpowerssum0000644000175000017500000000432414676526175022352 0ustar billbillFunction: dirpowerssum Section: number_theoretical C-Name: dirpowerssum0 Prototype: GGDGD0,L,p Help: dirpowerssum(N,x,{f},{both=0}): return f(1)1^x + f(2)2^x + ... + f(N)N^x, where f is a completely multiplicative function (= 1 if omitted). If both is set, return the pair for arguments (x, f) and (-1-x, conj(f)). If both=2, assume in addition that f is real-valued. Doc: for positive integer $N$ and complex number $x$, return the sum $f(1)1^{x} + f(2)2^{x} + \dots + f(N)N^{x}$, where $f$ is a completely multiplicative function. If $f$ is omitted, return $1^{x} + \dots + N^{x}$. When $N \le 0$, the function returns $0$. If \kbd{both} is set, return the pair for arguments $(x,f)$ and $(-1-x,\overline{f})$. If \kbd{both=2}, assume in addition that $f$ is real-valued (which is true when $f$ is omitted, i.e. represents the constant function $f(n) = 1$). \misctitle{Caveat} when {\tt both} is set, the present implementation assumes that $|f(n)|$ is either $0$ or $1$, which is the case for Dirichlet characters. A vector-valued multiplicative function $f$ is allowed, in which case the above conditions must be met componentwise and the vector length must be constant. Unlike variants using \kbd{dirpowers(N,x)}, this function uses $O(\sqrt{N})$ memory instead of $O(N)$. And it is faster for large $N$. The return value is usually a floating point number, but it will be exact if the result is an integer. On the other hand, rational numbers are converted to floating point approximations, since they are likely to blow up for large $N$. \bprog ? dirpowers(5, 2) %1 = [1, 4, 9, 16, 25] ? vecsum(%) %2 = 55 ? dirpowerssum(5, 2) %3 = 55 ? dirpowerssum(5, -2) %4 = 1.4636111111111111111111111111111111111 ? \p200 ? s = 1/2 + I * sqrt(3); N = 10^7; ? dirpowerssum(N, s); time = 11,425 ms. ? vecsum(dirpowers(N, s)) time = 19,365 ms. ? dirpowerssum(N, s, n->kronecker(-23,n)) time = 10,981 ms. @eprog\noindent The \kbd{dirpowerssum} commands work with default stack size, the \kbd{dirpowers} one requires a stacksize of at least 5GB. \synt{dirpowerssumfun}{ulong N, GEN x, void *E, GEN (*f)(void*, ulong, long), long prec}. When $f = \kbd{NULL}$, one may use \fun{GEN}{dirpowerssum}{ulong N, GEN x, long prec}. pari-2.17.2/src/functions/number_theoretical/gcd0000644000175000017500000000456414567450071020340 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{gcdext} function. $x$ and $y$ can have rather quite general types, for instance both rational numbers. If $y$ is omitted and $x$ is a vector, returns the $\text{gcd}$ of all components of $x$, i.e.~this is equivalent to \kbd{content(x)}. When $x$ and $y$ are both given and one of them is a vector/matrix type, the GCD is again taken recursively on each component, but in a different way. If $y$ is a vector, resp.~matrix, then the result has the same type as $y$, and components equal to \kbd{gcd(x, y[i])}, resp.~\kbd{gcd(x, y[,i])}. Else if $x$ is a vector/matrix the result has the same type as $x$ and an analogous definition. Note that for these types, \kbd{gcd} is not commutative. The algorithm used is a naive \idx{Euclid} except for the following inputs: \item integers: use modified right-shift binary (``plus-minus'' variant). \item univariate polynomials with coefficients in the same number field (in particular rational): use modular gcd algorithm. \item general polynomials: use the \idx{subresultant algorithm} if coefficient explosion is likely (non modular coefficients). If $u$ and $v$ are polynomials in the same variable with \emph{inexact} coefficients, their gcd is defined to be scalar, so that \bprog ? a = x + 0.0; gcd(a,a) %1 = 1 ? b = y*x + O(y); gcd(b,b) %2 = y ? c = 4*x + O(2^3); gcd(c,c) %3 = 4 @eprog\noindent A good quantitative check to decide whether such a gcd ``should be'' nontrivial, is to use \tet{polresultant}: a value close to $0$ means that a small deformation of the inputs has nontrivial gcd. You may also use \tet{gcdext}, which does try to compute an approximate gcd $d$ and provides $u$, $v$ to check whether $u x + v y$ is close to $d$. Variant: Also available are \fun{GEN}{ggcd}{GEN x, GEN y}, if \kbd{y} is not \kbd{NULL}, and \fun{GEN}{content}{GEN x}, if $\kbd{y} = \kbd{NULL}$. Function: _ZX_gcd_worker C-Name: ZX_gcd_worker Prototype: GGGG Section: programming/internals Help: worker for ZX_gcd pari-2.17.2/src/functions/number_theoretical/HEADER0000644000175000017500000001604614676526175020543 0ustar billbillFunction: _header_number_theoretical Class: header Section: number_theoretical Doc: \section{Arithmetic functions}\label{se:arithmetic} These functions are by definition functions whose natural domain of definition is either $\Z$ (or $\Z_{>0}$). The way these functions are used is completely different from transcendental functions in that there are no automatic type conversions: in general only integers are accepted as arguments. An integer argument $N$ can be given in the following alternate formats: \item \typ{MAT}: its factorization \kbd{fa = factor($N$)}, \item \typ{VEC}: a pair \kbd{[$N$, fa]} giving both the integer and its factorization. This allows to compute different arithmetic functions at a given $N$ while factoring the latter only once. \bprog ? N = 10!; faN = factor(N); ? eulerphi(N) %2 = 829440 ? eulerphi(faN) %3 = 829440 ? eulerphi(S = [N, faN]) %4 = 829440 ? sigma(S) %5 = 15334088 @eprog \subsec{Arithmetic functions and the factoring engine} All arithmetic functions in the narrow sense of the word~--- Euler's totient\sidx{Euler totient function} function, the \idx{Moebius} function, the sums over divisors or powers of divisors etc.--- call, after trial division by small primes, the same versatile factoring machinery described under \kbd{factorint}. It includes \idx{Shanks SQUFOF}, \idx{Pollard Rho}, \idx{ECM} and \idx{MPQS} stages, and has an early exit option for the functions \teb{moebius} and (the integer function underlying) \teb{issquarefree}. This machinery relies on a fairly strong probabilistic primality test, see \kbd{ispseudoprime}, but you may also set \bprog default(factor_proven, 1) @eprog\noindent to ensure that all tentative factorizations are fully proven. This should not slow down PARI too much, unless prime numbers with hundreds of decimal digits occur frequently in your application. \subsec{Orders in finite groups and Discrete Logarithm functions} \label{se:DLfun} The following functions compute the order of an element in a finite group: \kbd{ellorder} (the rational points on an elliptic curve defined over a finite field), \kbd{fforder} (the multiplicative group of a finite field), \kbd{znorder} (the invertible elements in $\Z/n\Z$). The following functions compute discrete logarithms in the same groups (whenever this is meaningful) \kbd{elllog}, \kbd{fflog}, \kbd{znlog}. All such functions allow an optional argument specifying an integer $N$, representing the order of the group. (The \emph{order} functions also allows any nonzero multiple of the order, with a minor loss of efficiency.) That optional argument follows the same format as given above: \item \typ{INT}: the integer $N$, \item \typ{MAT}: the factorization \kbd{fa = factor($N$)}, \item \typ{VEC}: this is the preferred format and provides both the integer $N$ and its factorization in a two-component vector \kbd{[$N$, fa]}. When the group is fixed and many orders or discrete logarithms will be computed, it is much more efficient to initialize this data once and pass it to the relevant functions, as in \bprog ? p = nextprime(10^30); ? 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 \subsec{Dirichlet characters}\label{se:dirichletchar} The finite abelian group $G = (\Z/N\Z)^{*}$ can be written $G = \oplus_{i\leq n} (\Z/d_{i}\Z) g_{i}$, with $d_{n} \mid \dots \mid d_{2} \mid d_{1}$ (SNF condition), all $d_{i} > 0$, and $\prod_{i} d_{i} = \phi(N)$. The positivity and SNF condition make the $d_{i}$ unique, but the generators $g_{i}$, of respective order $d_{i}$, are definitely not unique. The $\oplus$ notation means that all elements of $G$ can be written uniquely as $\prod_{i} g_{i}^{n_{i}}$ where $n_{i} \in \Z/d_{i}\Z$. The $g_{i}$ are the so-called \tev{SNF generators} of $G$. \item a \tev{character} on the abelian group $\oplus_{j} (\Z/d_{j}\Z) g_{j}$ is given by a row vector $\chi = [a_{1},\ldots,a_{n}]$ of integers $0\leq a_{i} < d_{i}$ such that $\chi(g_{j}) = e(a_{j} / d_{j})$ for all $j$, with the standard notation $e(x) := \exp(2i\pi x)$. In other words, $\chi(\prod_{j} g_{j}^{n_{j}}) = e(\sum_{j} a_{j} n_{j} / d_{j})$. This will be generalized to more general abelian groups in later sections (Hecke characters), but in the present case of $(\Z/N\Z)^{*}$, there is a useful alternate convention : namely, it is not necessary to impose the SNF condition and we can use Chinese remainders instead. If $N = \prod p^{e_{p}}$ is the factorization of $N$ into primes, the so-called \tev{Conrey generators} of $G$ are the generators of the $(\Z/p^{e_{p}}\Z)^{*}$ lifted to $(\Z/N\Z)^{*}$ by requesting that they be congruent to $1$ modulo $N/p^{e_{p}}$ (for $p$ odd we take the smallest positive primitive root mod $p^{2}$, and for $p = 2$ we take $-1$ if $e_{2} > 1$ and additionally $5$ if $e_{2} > 2$). We can again write $G = \oplus_{i\leq n} (\Z/D_{i}\Z) G_{i}$, where again $\prod_{i} D_{i} = \phi(N)$. These generators don't satisfy the SNF condition in general since their orders are now $(p-1)p^{e_{p}-1}$ for $p$ odd; for $p = 2$, the generator $-1$ has order $2$ and $5$ has order $2^{e_{2}-2}$ $(e_{2} > 2)$. Nevertheless, any $m\in (\Z/N\Z)^{*}$ can be uniquely decomposed as $m = \prod_{j} G_{i}^{m_{i}}$ for some $m_{i}$ modulo $D_{i}$ and we can define a character by $\chi(G_{j}) = e(m_{j} / D_{j})$ for all $j$. \item The \emph{column vector} of the $m_{j}$, $0 \leq m_{j} < D_{j}$ is called the \tev{Conrey logarithm} of $m$ (discrete logarithm in terms of the Conrey generators). Note that discrete logarithms in PARI/GP are always expressed as \typ{COL}s. \item The attached character is called the \tev{Conrey character} attached to $m$. To sum up a Dirichlet character can be defined by a \typ{INTMOD} \kbd{Mod}$(m, N)$, a \typ{INT} lift (the Conrey label $m$), a \typ{COL} (the Conrey logarithm of $m$, in terms of the Conrey generators) or a \typ{VEC} (in terms of the SNF generators). The \typ{COL} format, i.e. Conrey logarithms, is the preferred (fastest) representation. Concretely, this works as follows: \kbd{G = znstar(N, 1)} initializes $(\Z/N\Z)^{*}$, which must be given as first arguments to all functions handling Dirichlet characters. \kbd{znconreychar} transforms \typ{INT}, \typ{INTMOD} and \typ{COL} to a SNF character. \kbd{znconreylog} transforms \typ{INT}, \typ{INTMOD} and \typ{VEC} to a Conrey logarithm. \kbd{znconreyexp} transforms \typ{VEC} and \typ{COL} to a Conrey label. Also available are \kbd{charconj}, \kbd{chardiv}, \kbd{charmul}, \kbd{charker}, \kbd{chareval}, \kbd{charorder}, \kbd{zncharinduce}, \kbd{znconreyconductor} (also computes the primitive character attached to the input character). The prefix \kbd{char} indicates that the function applies to all characters, the prefix \kbd{znchar} that it is specific to Dirichlet characters (on $(\Z/N\Z)^{*}$) and the prefix \kbd{znconrey} that it is specific to Conrey representation. pari-2.17.2/src/functions/number_theoretical/halfgcd0000644000175000017500000000174414567450071021170 0ustar billbillFunction: halfgcd Section: number_theoretical C-Name: ghalfgcd Prototype: GG Help: halfgcd(x,y): return a vector [M, [a,b]~], where M is an invertible 2x2 matrix such that M*[x,y]~ = [a,b]~, where b is small. More precisely, if x,y are integers, we have b < sqrt(max(|x|,|y|)) <= a. If x,y are polynomials, we have deg b < ceil((max(|x|,|y|))/2) <= deg a. Doc: Let inputs $x$ and $y$ be both integers, or both polynomials in the same variable. Return a vector \kbd{[M, [a,b]\til]}, where $M$ is an invertible $2\times 2$ matrix such that \kbd{M*[x,y]\til = [a,b]\til}, where $b$ is small. More precisely, \item polynomial case: $\det M$ has degree $0$ and we have $$\deg a \geq \ceil{\max(\deg x,\deg y))/2} > \deg b.$$ \item integer case: $\det M = \pm 1$ and we have $$a \geq \ceil{\sqrt{\max(|x|,|y|)}} > b.$$ Assuming $x$ and $y$ are nonnegative, then $M^{-1}$ has nonnegative coefficients, and $\det M$ is equal to the sign of both main diagonal terms $M[1,1]$ and $M[2,2]$. pari-2.17.2/src/functions/number_theoretical/factormodSQF0000644000175000017500000000326314676526175022140 0ustar billbillFunction: factormodSQF Section: number_theoretical C-Name: factormodSQF Prototype: GDG Help: factormodSQF(f,{D}): squarefree factorization of the polynomial f over the finite field defined by the domain D. Doc: squarefree factorization of the polynomial $f$ over the finite field defined by the domain $D$ as follows: \item $D = p$ a prime: factor over $\F_{p}$; \item $D = [T,p]$ for a prime $p$ and $T$ an irreducible polynomial over $\F_{p}$: factor over $\F_{p}[x]/(T)$; \item $D$ a \typ{FFELT}: factor over the attached field; \item $D$ omitted: factor over the field of definition of $f$, which must be a finite field. The coefficients of $f$ must be operation-compatible with the corresponding finite field. The result is a two-column matrix: \item the first column contains monic squarefree pairwise coprime polynomials dividing $f$; \item the second column contains the power to which the polynomial in column $1$ divides $f$; This is somewhat faster than full factorization. The factors are ordered by increasing exponent and the result is obviously canonical. \bprog ? f = (x^2 + 1)^3 * (x^2-1)^2; ? factormodSQF(f, 3) \\ over F_3 %1 = [Mod(1, 3)*x^2 + Mod(2, 3) 2] [Mod(1, 3)*x^2 + Mod(1, 3) 3] ? for(i=1,10^5,factormodSQF(f,3)) time = 192 ms. ? for(i=1,10^5,factormod(f,3)) \\ full factorization is slower time = 409 ms. ? liftall( factormodSQF((x^2 + 1)^3, [3, t^2+1]) ) \\ over F_9 %4 = [x^2 + 1 3] ? t = ffgen(t^2+Mod(1,3)); factormodSQF((x^2 + t^0)^3) \\ same using t_FFELT %5 = [x^2 + 1 3] ? factormodSQF(x^8 + x^7 + x^6 + x^2 + x + Mod(1,2)) %6 = [ Mod(1, 2)*x + Mod(1, 2) 2] [Mod(1, 2)*x^2 + Mod(1, 2)*x + Mod(1, 2) 3] @eprog pari-2.17.2/src/functions/number_theoretical/numdiv0000644000175000017500000000033514557721031021071 0ustar billbillFunction: numdiv Section: number_theoretical C-Name: numdiv Prototype: G Help: numdiv(x): number of divisors of x. Description: (gen):int numdiv($1) Doc: number of divisors of $|x|$. $x$ must be of type integer. pari-2.17.2/src/functions/number_theoretical/issquare0000644000175000017500000000347414676526175021450 0ustar billbillFunction: issquare Section: number_theoretical C-Name: issquareall Prototype: lGD& Help: issquare(x,{&n}): true(1) if x is a square, false(0) if not. If n is given puts the exact square root there if it was computed. Description: (int):bool Z_issquare($1) (gen):bool issquare($1) (int, &int):bool Z_issquareall($1, &$2) (gen, &gen):bool issquareall($1, &$2) Doc: true (1) if $x$ is a square, false (0) if not. What ``being a square'' means depends on the type of $x$: all \typ{COMPLEX} are squares, as well as all nonnegative \typ{REAL}; for exact types such as \typ{INT}, \typ{FRAC} and \typ{INTMOD}, squares are numbers of the form $s^{2}$ with $s$ in $\Z$, $\Q$ and $\Z/N\Z$ respectively. \bprog ? issquare(3) \\ as an integer %1 = 0 ? issquare(3.) \\ as a real number %2 = 1 ? issquare(Mod(7, 8)) \\ in Z/8Z %3 = 0 ? issquare( 5 + O(13^4) ) \\ in Q_13 %4 = 0 @eprog If $n$ is given, a square root of $x$ is put into $n$. \bprog ? issquare(4, &n) %1 = 1 ? n %2 = 2 @eprog For polynomials, either we detect that the characteristic is 2 (and check directly odd and even-power monomials) or we assume that $2$ is invertible and check whether squaring the truncated power series for the square root yields the original input. For \typ{POLMOD} $x$, we only support \typ{POLMOD}s of \typ{INTMOD}s encoding finite fields, assuming without checking that the intmod modulus $p$ is prime and that the polmod modulus is irreducible modulo $p$. \bprog ? issquare(Mod(Mod(2,3), x^2+1), &n) %1 = 1 ? n %2 = Mod(Mod(2, 3)*x, Mod(1, 3)*x^2 + Mod(1, 3)) @eprog Variant: Also available is \fun{long}{issquare}{GEN x}. Deprecated GP-specific functions \fun{GEN}{gissquare}{GEN x} and \fun{GEN}{gissquareall}{GEN x, GEN *pt} return \kbd{gen\_0} and \kbd{gen\_1} instead of a boolean value. pari-2.17.2/src/functions/number_theoretical/primes0000644000175000017500000000115314567450071021071 0ustar billbillFunction: primes Section: number_theoretical C-Name: primes0 Prototype: G Help: primes(n): returns the vector of the first n primes (integer), or the primes in interval n = [a,b]. Doc: creates a row vector whose components are the first $n$ prime numbers. (Returns the empty vector for $n \leq 0$.) A \typ{VEC} $n = [a,b]$ is also allowed, in which case the primes in $[a,b]$ are returned \bprog ? primes(10) \\ the first 10 primes %1 = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] ? primes([0,29]) \\ the primes up to 29 %2 = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] ? primes([15,30]) %3 = [17, 19, 23, 29] @eprog pari-2.17.2/src/functions/number_theoretical/lcm0000644000175000017500000000276114567450071020353 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) up to units. Description: (int, int):int lcmii($1, $2) (gen):gen glcm0($1, NULL) (gen, gen):gen glcm($1, $2) Doc: least common multiple of $x$ and $y$, i.e.~such that $\lcm(x,y)*\gcd(x,y) = x*y$, up to units. If $y$ is omitted and $x$ is a vector, returns the $\text{lcm}$ of all components of $x$. For integer arguments, return the nonnegative \text{lcm}. When $x$ and $y$ are both given and one of them is a vector/matrix type, the LCM is again taken recursively on each component, but in a different way. 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^5, i, random); ? lcm(v); time = 546 ms. ? l = v[1]; for (i = 1, #v, l = lcm(l, v[i])) time = 4,561 ms. @eprog pari-2.17.2/src/functions/number_theoretical/primepi0000644000175000017500000000077414567450071021247 0ustar billbillFunction: primepi Section: number_theoretical C-Name: primepi Prototype: G Help: primepi(x): the prime counting function pi(x) = #{p <= x, p prime}. Description: (gen):int primepi($1) Doc: the prime counting function. Returns the number of primes $p$, $p \leq x$. \bprog ? primepi(10) %1 = 4; ? primes(5) %2 = [2, 3, 5, 7, 11] ? primepi(10^11) %3 = 4118054813 @eprog\noindent Uses checkpointing and a naive $O(x)$ algorithm; make sure to start gp with \kbd{primelimit} at least $\sqrt{x}$. pari-2.17.2/src/functions/number_theoretical/znsubgroupgenerators0000644000175000017500000000627314676526175024124 0ustar billbillFunction: znsubgroupgenerators Section: number_theoretical C-Name: znsubgroupgenerators Prototype: GD0,L, Help: znsubgroupgenerators(H,{flag=0}): finds generators of the subgroup H of (Z/fZ)^*; H is given by a vector of length f of 1/0 values: the a-th component is 1 if and only if a belongs to H. Doc: Finds a minimal set of generators for the subgroup of $(\Z/f\Z)^{*}$ given by a vector (or vectorsmall) $H$ of length $f$: for $1\leq a\leq f$, \kbd{H[a]} is 1 or 0 according as $a\in H_{F}$ or $a\not\in H_{F}$. In most PARI functions, subgroups of an abelian group are given as HNF left-divisors of a diagonal matrix, representing the discrete logarithms of the subgroup generators in terms of a fixed generators for the group cyclic components. The present function allows to convert an enumeration of the subgroup elements to this representation as follows: \bprog ? G = znstar(f, 1); ? v = znsubgroupgenerators(H); ? subHNF(G, v) = mathnfmodid(Mat([znlog(h, G) | h<-v]), G.cyc); @eprog\noindent The function \kbd{subHNF} can be applied to any elements of $(\Z/f\Z)^{*}$, yielding the subgroup they generate, but using \kbd{znsubgroupgenerators} first allows to reduce the number of discrete logarithms to be computed. For example, if $H=\{\,1,4,11,14\,\}\subset(\Z/15\Z)^{\times}$, then we have \bprog ? f = 15; H = vector(f); H[1]=H[4]=H[11]=H[14] = 1; ? v = znsubgroupgenerators(H) %2 = [4, 11] ? G = znstar(f, 1); G.cyc %3 = [4, 2] ? subHNF(G, v) %4 = [2 0] [0 1] ? subHNF(G, [1,4,11,14]) %5 = [2 0] [0 1] @eprog\noindent This function is mostly useful when $f$ is large and $H$ has small index: if $H$ has few elements, one may just use \kbd{subHNF} directly on the elements of $H$. For instance, let $K = \Q(\zeta_{p}, \sqrt{m}) \subset L = \Q(\zeta_{f})$, where $p$ is a prime, $\sqrt{m}$ is a quadratic number and $f$ is the conductor of the abelian extension $K/\Q$. The following GP script creates $H$ as the Galois group of $L/K$, as a subgroub of $(\Z/fZ)^{*}$: \bprog HK(m, p, flag = 0)= { my(d = quaddisc(m), f = lcm(d, p), H); H = vectorsmall(f, a, a % p == 1 && kronecker(d,a) > 0); [f, znsubgroupgenerators(H,flag)]; } ? [f, v] = HK(36322, 5) time = 193 ms. %1 = [726440, [41, 61, 111, 131]] ? G = znstar(f,1); G.cyc %2 = [1260, 12, 2, 2, 2, 2] ? A = subHNF(G, v) %3 = [2 0 1 1 0 1] [0 4 0 0 0 2] [0 0 1 0 0 0] [0 0 0 1 0 0] [0 0 0 0 1 0] [0 0 0 0 0 1] \\ Double check ? p = 5; d = quaddisc(36322); ? w = select(a->a % p == 1 && kronecker(d,a) > 0, [1..f]); #w time = 133 ms. %5 = 30240 \\ w enumerates the elements of H ? subHNF(G, w) == A \\ same result, about twice slower time = 242 ms. %6 = 1 @eprog\noindent This shows that $K=\Q(\sqrt{36322},\zeta_{5})$ is contained in $\Q(\zeta_{726440})$ and $H=\langle 41, 61, 111, 131 \rangle$. Note that $H=\langle 41\rangle\langle 61\rangle\langle 111 \rangle \langle 131\rangle$ is not a direct product. If $\fl=1$, then the function finds generators which decompose $H$ to direct factors: \bprog ? HK(36322, 5, 1) %3 = [726440, [41, 31261, 324611, 506221]] @eprog\noindent This time $H=\langle 41\rangle\times \langle 31261\rangle \times \langle 324611 \rangle \times \langle 506221 \rangle$. pari-2.17.2/src/functions/number_theoretical/bezout0000644000175000017500000000026714567450071021107 0ustar billbillFunction: bezout Section: number_theoretical C-Name: gcdext0 Prototype: GG Obsolete: 2013-04-03 Help: bezout(x,y): deprecated alias for gcdext. Doc: deprecated alias for \kbd{gcdext} pari-2.17.2/src/functions/number_theoretical/factormodDDF0000644000175000017500000000363214676526175022104 0ustar billbillFunction: factormodDDF Section: number_theoretical C-Name: factormodDDF Prototype: GDG Help: factormodDDF(f,{D}): distinct-degree factorization of the squarefree polynomial f over the finite field defined by the domain D. Doc: distinct-degree factorization of the squarefree polynomial $f$ over the finite field defined by the domain $D$ as follows: \item $D = p$ a prime: factor over $\F_{p}$; \item $D = [T,p]$ for a prime $p$ and $T$ an irreducible polynomial over $\F_{p}$: factor over $\F_{p}[x]/(T)$; \item $D$ a \typ{FFELT}: factor over the attached field; \item $D$ omitted: factor over the field of definition of $f$, which must be a finite field. If $f$ is not squarefree, the result is undefined. The coefficients of $f$ must be operation-compatible with the corresponding finite field. The result is a two-column matrix: \item the first column contains monic (squarefree, pairwise coprime) polynomials dividing $f$, all of whose irreducible factors have the same degree $d$; \item the second column contains the degrees of the irreducible factors. The factorization is ordered by increasing degree $d$ of irreducible factors, and the result is obviously canonical. This function is somewhat faster than full factorization. \bprog ? f = (x^2 + 1) * (x^2-1); ? factormodSQF(f,3) \\ squarefree over F_3 %2 = [Mod(1, 3)*x^4 + Mod(2, 3) 1] ? factormodDDF(f, 3) %3 = [Mod(1, 3)*x^2 + Mod(2, 3) 1] \\ two degree 1 factors [Mod(1, 3)*x^2 + Mod(1, 3) 2] \\ irred of degree 2 ? for(i=1,10^5,factormodDDF(f,3)) time = 424 ms. ? for(i=1,10^5,factormod(f,3)) \\ full factorization is a little slower time = 464 ms. ? liftall( factormodDDF(x^2 + 1, [3, t^2+1]) ) \\ over F_9 %6 = [x^2 + 1 1] \\ product of two degree 1 factors ? t = ffgen(t^2+Mod(1,3)); factormodDDF(x^2 + t^0) \\ same using t_FFELT %7 = [x^2 + 1 1] ? factormodDDF(x^2-Mod(1,3)) %8 = [Mod(1, 3)*x^2 + Mod(2, 3) 1] @eprog pari-2.17.2/src/functions/number_theoretical/qfbprimeform0000644000175000017500000000100314567450071022255 0ustar billbillFunction: qfbprimeform Section: number_theoretical C-Name: primeform Prototype: GG 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{QFB} are not implemented.) pari-2.17.2/src/functions/number_theoretical/moebius0000644000175000017500000000030014567450071021226 0ustar billbillFunction: moebius Section: number_theoretical C-Name: moebius Prototype: lG Help: moebius(x): Moebius function of x. Doc: \idx{Moebius} $\mu$-function of $|x|$; $x$ must be a nonzero integer. pari-2.17.2/src/functions/number_theoretical/dirmul0000644000175000017500000000127014676526175021100 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 nonzero coefficient. \bprog ? dirmul([0,1], [0,1]); %2 = [0, 0, 0, 1] @eprog pari-2.17.2/src/functions/number_theoretical/qfbnucomp0000644000175000017500000000154414567450071021570 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{QFB}) 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/4|^{1/4}$, i.e. \kbd{sqrtnint(abs(D)>>2,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 slower than the generic routine for small $D$, and becomes faster when $D$ has about $45$ bits. Variant: Also available is \fun{GEN}{nudupl}{GEN x, GEN L} when $x=y$. pari-2.17.2/src/functions/number_theoretical/precprime0000644000175000017500000000162214567450071021561 0ustar billbillFunction: precprime Section: number_theoretical C-Name: precprime Prototype: G Help: precprime(x): largest pseudoprime <= x, 0 if x<=1. Description: (gen):int precprime($1) Doc: finds the largest pseudoprime (see \tet{ispseudoprime}) less than or equal to $x$; the input $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$. \bprog ? precprime(2) %1 = 2 ? precprime(Pi) %2 = 3 ? precprime(-10) %3 = 0 \\ primes are positive @eprog\noindent The function name comes from \emph{prec}eding \emph{prime}. Despite the name, please note that the function is not guaranteed to return a prime number (although no counter-example is known at present); the return value \emph{is} a guaranteed prime if $x \leq 2^{64}$. To rigorously prove that the result is prime in all cases, use \kbd{isprime}. pari-2.17.2/src/functions/number_theoretical/zncharconductor0000644000175000017500000000124014676526175023007 0ustar billbillFunction: zncharconductor Section: number_theoretical C-Name: zncharconductor Prototype: GG Help: zncharconductor(G,chi): let G be znstar(q,1) and chi be a Dirichlet character on (Z/qZ)*. Return the conductor of chi. Doc: Let \var{G} be attached to $(\Z/q\Z)^{*}$ (as per \kbd{G = znstar(q, 1)}) and \kbd{chi} be a Dirichlet character on $(\Z/q\Z)^{*}$ (see \secref{se:dirichletchar} or \kbd{??character}). Return the conductor of \kbd{chi}: \bprog ? G = znstar(126000, 1); ? zncharconductor(G,11) \\ primitive %2 = 126000 ? zncharconductor(G,1) \\ trivial character, not primitive! %3 = 1 ? zncharconductor(G,1009) \\ character mod 5^3 %4 = 125 @eprog pari-2.17.2/src/functions/number_theoretical/factorial0000644000175000017500000000053313637407207021537 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.17.2/src/functions/number_theoretical/factormodcyclo0000644000175000017500000000473714676526175022627 0ustar billbillFunction: factormodcyclo Section: number_theoretical C-Name: factormodcyclo Prototype: LGD0,L,Dn Help: factormodcyclo(n,p,{single=0},{v='x}): factor n-th cyclotomic polynomial mod p. Doc: Factors $n$-th cyclotomic polynomial $\Phi_{n}(x)$ mod $p$, where $p$ is a prime number not dividing $n$. Much faster than \kbd{factormod(polcyclo(n), p)}; the irreducible factors should be identical and given in the same order. If \var{single} is set, return a single irreducible factor; else (default) return all the irreducible factors. Note that repeated calls of this function with the \var{single} flag set may return different results because the algorithm is probabilistic. Algorithms used are as follows. Let $F=\Q(\zeta_{n})$. Let $K$ be the splitting field of $p$ in $F$ and $e$ the conductor of $K$. Then $\Phi_{n}(x)$ and $\Phi_{e}(x)$ have the same number of irreducible factors mod $p$ and there is a simple algorithm constructing irreducible factors of $\Phi_{n}(x)$ from irreducible factors of $\Phi_{e}(x)$. So we may assume $n$ is equal to the conductor of $K$. Let $d$ be the order of $p$ in $(\Z/n\Z)^{\times}$ and $\varphi(n)=df$. Then $\Phi_{n}(x)$ has $f$ irreducible factors $g_{i}(x)\;(1\leq i\leq f)$ of degree $d$ over $\F_{p}$ or $\Z_{p}$. \item If $d$ is small, then we factor $g_{i}(x)$ into $d$ linear factors $g_{ij}(x)$, $1\leq j\leq d$ in $\F_{q}[x]\;(q=p^{d})$ and construct $G_{i}(x)=\prod_{j=1}^{d} g_{ij}(x)\in \F_{q}[x]$. Then $G_{i}(x)\in\F_{p}[x]$ and $g_{i}(x)=G_{i}(x)$. \item If $f$ is small, then we work in $K$, which is a Galois extension of degree $f$ over $\Q$. The Gaussian period $\theta_{k}=\text{Tr}_{F/K}(\zeta_{n}^{k})$ is a sum of $k$-th power of roots of $g_{i}(x)$ and $K=\Q(\theta_{1})$. Now, for each $k$, there is a polynomial $T_{k}(x)\in\Q[x]$ satisfying $\theta_{k}=T_{k}(\theta_{1})$ because all $\theta_{k}$ are in $K$. Let $T(x)\in\Z[x]$ be the minimal polynomial of $\theta_{1}$ over $\Q$. We get $\theta_{1}$ mod $p$ from $T(x)$ and construct $\theta_{1},\cdots,\theta_{d}$ mod $p$ using $T_{k}(x)$. Finally we recover $g_{i}(x)$ from $\theta_{1},\cdots,\theta_{d}$ by Newton's formula. \bprog ? lift(factormodcyclo(15, 11)) %1 = [x^2 + 9*x + 4, x^2 + 4*x + 5, x^2 + 3*x + 9, x^2 + 5*x + 3] ? factormodcyclo(15, 11, 1) \\ single %2 = Mod(1, 11)*x^2 + Mod(5, 11)*x + Mod(3, 11) ? z1 = lift(factormod(polcyclo(12345),11311)[,1]); time = 32,498 ms. ? z2 = factormodcyclo(12345,11311); time = 47 ms. ? z1 == z2 %4 = 1 @eprog pari-2.17.2/src/functions/number_theoretical/ispseudoprimepower0000644000175000017500000000157414676526175023560 0ustar billbillFunction: ispseudoprimepower Section: number_theoretical C-Name: ispseudoprimepower Prototype: lGD& Help: ispseudoprimepower(x,{&n}): if x = p^k is a pseudo-prime power (p pseudo-prime, k > 0), return k, else return 0. If n is present, and the function returns a nonzero result, set n to p, the k-th root of x. Doc: if $x = p^{k}$ is a pseudo-prime power ($p$ pseudo-prime as per \tet{ispseudoprime}, $k > 0$), return $k$, else return 0. If a second argument $\&n$ is given and $x$ is indeed the $k$-th power of a prime $p$, sets $n$ to $p$. More precisely, $k$ is always the largest integer such that $x = n^{k}$ for some integer $n$ and, when $n \leq 2^{64}$ the function returns $k > 0$ if and only if $n$ is indeed prime. When $n > 2^{64}$ is larger than the threshold, the function may return $1$ even though $n$ is composite: it only passed an \kbd{ispseudoprime(n)} test. pari-2.17.2/src/functions/number_theoretical/znchargauss0000644000175000017500000000153214676526175022135 0ustar billbillFunction: znchargauss Section: number_theoretical C-Name: znchargauss Prototype: GGDGb Help: znchargauss(G,chi,{a=1}): given a Dirichlet character chi on G = (Z/NZ)^*, return the complex Gauss sum g(chi,a). Doc: Given a Dirichlet character $\chi$ on $G = (\Z/N\Z)^{*}$ (see \kbd{znchar}), return the complex Gauss sum $$g(\chi,a) = \sum_{n = 1}^{N} \chi(n) e(a n/N)$$ \bprog ? [G,chi] = znchar(-3); \\ quadratic Gauss sum: I*sqrt(3) ? znchargauss(G,chi) %2 = 1.7320508075688772935274463415058723670*I ? [G,chi] = znchar(5); ? znchargauss(G,chi) \\ sqrt(5) %2 = 2.2360679774997896964091736687312762354 ? G = znstar(300,1); chi = [1,1,12]~; ? znchargauss(G,chi) / sqrt(300) - exp(2*I*Pi*11/25) \\ = 0 %4 = 2.350988701644575016 E-38 + 1.4693679385278593850 E-39*I ? lfuntheta([G,chi], 1) \\ = 0 %5 = -5.79[...] E-39 - 2.71[...] E-40*I @eprog pari-2.17.2/src/functions/number_theoretical/primecertexport0000644000175000017500000000322614676526175023043 0ustar billbillFunction: primecertexport Section: number_theoretical C-Name: primecertexport Prototype: GD0,L, Help: primecertexport(cert,{format=0}): Returns a string suitable for print/write to display a primality certificate. Doc: Returns a string suitable for print/write to display a primality certificate from \tet{primecert}, the format of which depends on the value of \kbd{format}: \item 0 (default): Human-readable format. See \kbd{??primecert} for the meaning of the successive $N, t, s, a, m, q, E, P$. The integer $D$ is the negative fundamental discriminant \kbd{coredisc}$(t^{2} - 4N)$. \item 1: Primo format 4. \item 2: MAGMA format. Currently, only ECPP Primality Certificates are supported. \bprog ? cert = primecert(10^35+69); ? s = primecertexport(cert); \\ Human-readable ? print(s) [1] N = 100000000000000000000000000000000069 t = 546867911035452074 s = 2963504668391148 a = 0 D = -3 m = 99999999999999999453132088964547996 q = 33743830764501150277 E = [0, 1] P = [21567861682493263464353543707814204, 49167839501923147849639425291163552] [2] N = 33743830764501150277 t = -11610830419 s = 734208843 a = 0 D = -3 m = 33743830776111980697 q = 45959444779 E = [0, 25895956964997806805] P = [29257172487394218479, 3678591960085668324] \\ Primo format ? s = primecertexport(cert,1); write("cert.out", s); \\ Magma format, write to file ? s = primecertexport(cert,2); write("cert.m", s); ? cert = primecert(10^35+69, 1); \\ N-1 certificate ? primecertexport(cert) *** at top-level: primecertexport(cert) *** ^--------------------- *** primecertexport: sorry, N-1 certificate is not yet implemented. @eprog pari-2.17.2/src/functions/number_theoretical/qfbpowraw0000644000175000017500000000052114567450071021600 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 nonnegative and $n<2^{31}$. pari-2.17.2/src/functions/number_theoretical/hilbert0000644000175000017500000000103014760123736021215 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.17.2/src/functions/number_theoretical/factorback0000644000175000017500000000220414567450071021667 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 factorization f, gives the factored object 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]. 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^2 * 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.17.2/src/functions/number_theoretical/qfbclassno0000644000175000017500000000547014676526175021745 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$, for ``small'' values of $D$. \item if $D > 0$ or $\fl = 1$, use a $O(|D|^{1/2})$ algorithm (compute $L(1,\chi_{D})$ with the approximate functional equation). This is slower than \tet{quadclassunit} as soon as $|D| \approx 10^{2}$ or so and is not meant to be used for large $D$. \item if $D < 0$ and $\fl = 0$ (or omitted), use a $O(|D|^{1/4})$ algorithm (Shanks's baby-step/giant-step method). It should be faster than \tet{quadclassunit} for small values of $D$, say $|D| < 10^{18}$. \misctitle{Important warning} In the latter case, this function only implements part of \idx{Shanks}'s method (which allows to speed it up considerably). It gives unconditionnally correct results for $|D| < 2\cdot 10^{10}$, but may give incorrect results for larger values if the class group has many cyclic factors. We thus recommend to double-check results using the function \kbd{quadclassunit}, which is about 2 to 3 times slower in the range $|D| \in [10^{10}, 10^{18}]$, assuming GRH. We currently have no counter-examples but they should exist: we would appreciate a bug report if you find one. \misctitle{Warning} Contrary to what its name implies, this routine does not compute the number of classes of binary primitive forms of discriminant $D$, 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 && quadunitnorm(D) > 0, 2, 1) ? QFBclassno(136) %1 = 4 ? qfbclassno(136) %2 = 2 ? quadunitnorm(136) %3 = 1 ? bnfnarrow(bnfinit(x^2 - 136)).cyc %4 = [4] \\ narrow class group is cyclic ~ Z/4Z @eprog\noindent Note that the use of \kbd{bnfnarrow} above is only valid because $136$ is a fundamental discriminant: that function is asymptotically faster (and returns the group structure, not only its order) but only supports \emph{maximal} orders. Here are a few more examples: \bprog ? qfbclassno(400000028) \\ D > 0: slow time = 3,140 ms. %1 = 1 ? quadclassunit(400000028).no time = 20 ms. \\@com{ much faster, assume GRH} %2 = 1 ? qfbclassno(-400000028) \\ D < 0: fast enough time = 0 ms. %3 = 7253 ? quadclassunit(-400000028).no time = 0 ms. %4 = 7253 @eprog\noindent See also \kbd{qfbhclassno}. pari-2.17.2/src/functions/number_theoretical/ffinvmap0000644000175000017500000000104214567450071021375 0ustar billbillFunction: ffinvmap Section: number_theoretical C-Name: ffinvmap Prototype: G Help: ffinvmap(m): given a map m between finite fields, return a partial map that return the pre-images by the map m. Doc: $m$ being a map from $K$ to $L$ two finite fields, return the partial map $p$ from $L$ to $K$ such that for all $k\in K$, $p(m(k))=k$. \bprog ? a = ffgen([3,5],'a); ? b = ffgen([3,10],'b); ? m = ffembed(a, b); ? p = ffinvmap(m); ? u = random(a); ? v = ffmap(m, u); ? ffmap(p, v^2+v+2) == u^2+u+2 %7 = 1 ? ffmap(p, b) %8 = [] @eprog pari-2.17.2/src/functions/number_theoretical/content0000644000175000017500000000335614567450071021253 0ustar billbillFunction: content Section: number_theoretical C-Name: content0 Prototype: GDG Help: content(x,{D}): 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\noindent The content of a \typ{VECSMALL} is computed assuming the entries are signed integers. The optional argument $D$ allows to control over which ring we compute and get a more predictable behaviour: \item $1$: we only consider the underlying $\Q$-structure and the denominator is a (positive) rational number \item a simple variable, say \kbd{'x}: all entries are considered as rational functions in $K(x)$ for some field $K$ and the content is an element of $K$. \bprog ? f = x + 1/y + 1/2; ? content(f) \\ as a t_POL in x %2 = 1/(2*y) ? content(f, 1) \\ Q-content %3 = 1/2 ? content(f, y) \\ as a rational function in y %4 = 1/2 ? g = x^2*y + y^2*x; ? content(g, x) %6 = y ? content(g, y) %7 = x @eprog pari-2.17.2/src/functions/number_theoretical/eulerphi0000644000175000017500000000102114676526175021413 0ustar billbillFunction: eulerphi Section: number_theoretical C-Name: eulerphi Prototype: G Help: eulerphi(x): Euler's totient function of x. Description: (gen):int eulerphi($1) Doc: Euler's $\phi$ (totient)\sidx{Euler totient function} function of the integer $|x|$, in other words $|(\Z/x\Z)^{*}|$. \bprog ? eulerphi(40) %1 = 16 @eprog\noindent According to this definition we let $\phi(0) := 2$, since $\Z^{*} = \{-1,1\}$; this is consistent with \kbd{znstar(0)}: we have \kbd{znstar$(n)$.no = eulerphi(n)} for all $n\in\Z$. pari-2.17.2/src/functions/number_theoretical/ispolygonal0000644000175000017500000000073714557721031022135 0ustar billbillFunction: ispolygonal Section: number_theoretical C-Name: ispolygonal Prototype: lGGD& Help: ispolygonal(x,s,{&N}): true(1) if x is an s-gonal number, false(0) if not (s > 2). If N is given set it to n if x is the n-th s-gonal number. Doc: true (1) if the integer $x$ is an s-gonal number, false (0) if not. The parameter $s > 2$ must be a \typ{INT}. If $N$ is given, set it to $n$ if $x$ is the $n$-th $s$-gonal number. \bprog ? ispolygonal(36, 3, &N) %1 = 1 ? N @eprog pari-2.17.2/src/functions/number_theoretical/quadunitindex0000644000175000017500000000232714676526175022472 0ustar billbillFunction: quadunitindex Section: number_theoretical C-Name: quadunitindex Prototype: GG Help: quadunitindex(D,f): given a fundamental discriminant D, returns the index of the unit group of the order of conductor f. Doc: given a fundamental discriminant $D$, returns the index of the unit group of the order of conductor $f$ in the units of $\Q(\sqrt{D})$. This function uses the continued fraction algorithm and has $O(D^{1/2 + \varepsilon} f^{\varepsilon})$ complexity; \kbd{quadclassunit} is asymptotically faster but depends on the GRH. \bprog ? quadunitindex(-3, 2) %1 = 3 ? quadunitindex(5, 2^32) \\ instantaneous %2 = 3221225472 ? quadregulator(5 * 2^64) / quadregulator(5) time = 3min, 1,488 ms. %3 = 3221225472.0000000000000000000000000000 @eprog\noindent The conductor $f$ can be given in factored form or as $[f, \kbd{factor}(f)]$: \bprog ? quadunitindex(5, [100, [2,2;5,2]]) %4 = 150 ? quadunitindex(5, 100) %5 = 150 ? quadunitindex(5, [2,2;5,2]) %6 = 150 @eprog If $D$ is not fundamental, the result is undefined; you may use the following script instead: \bprog index(d, f) = { my([D,F] = coredisc(d, 1)); quadunitindex(D, f * F) / quadunitindex(D, F) } ? index(5 * 10^2, 10) %7 = 10 @eprog pari-2.17.2/src/functions/number_theoretical/factor0000644000175000017500000002664014676526175021072 0ustar billbillFunction: factor Section: number_theoretical C-Name: factor0 Prototype: GDG Help: factor(x,{D}): factorization of x over domain D. If x and D are both integers, return partial factorization, using primes < D. Description: (int):vec Z_factor($1) (int,):vec Z_factor($1) (int,small):vec Z_factor_limit($1, $2) (gen):vec factor($1) (gen,):vec factor($1) (gen,gen):vec factor0($1, $2) Doc: factor $x$ over domain $D$; if $D$ is omitted, it is determined from $x$. For instance, if $x$ is an integer, it is factored in $\Z$, if it is a polynomial with rational coefficients, it is factored in $\Q[x]$, etc., see below for details. 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{$x \in \Q$} See \tet{factorint} for the algorithms used. The factorization includes the unit $-1$ when $x < 0$ and all other factors are positive; a denominator is factored with negative exponents. The factors are sorted in increasing order. \bprog ? factor(-7/106) %1 = [-1 1] [ 2 -1] [ 7 1] [53 -1] @eprog\noindent By convention, $1$ is factored as \kbd{matrix(0,2)} (the empty factorization, printed as \kbd{[;]}). Large rational ``primes'' $ > 2^{64}$ in the factorization are in fact \var{pseudoprimes} (see \kbd{ispseudoprime}), a priori not rigorously proven primes. Use \kbd{isprime} to prove primality of these factors, as in \bprog ? fa = factor(2^2^7 + 1) %2 = [59649589127497217 1] [5704689200685129054721 1] ? isprime( fa[,1] ) %3 = [1, 1]~ \\ both entries are proven primes @eprog\noindent Another possibility is to globally set the default \tet{factor_proven}, which will perform a rigorous primality proof for each pseudoprime factor but will slow down PARI. A \typ{INT} argument $D$ can be added, meaning that we only trial divide by all primes $p < D$ and the \kbd{addprimes} entries, then skip all expensive factorization methods. The limit $D$ must be nonnegative. In this case, one entry in the factorization may be a composite number: all factors less than $D^{2}$ and primes from the \kbd{addprimes} table are actual primes. But (at most) one entry may not verify this criterion, and it may be prime or composite: it is only known to be coprime to all other entries and not a pure power. \bprog ? factor(2^2^7 +1, 10^5) %4 = [340282366920938463463374607431768211457 1] @eprog\noindent \misctitle{Deprecated feature} Setting $D=0$ is the same as setting it to $\kbd{factorlimit} + 1$. \smallskip This routine uses trial division and perfect power tests, and should not be used for huge values of $D$ (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 more efficient way. \bprog ? F = (2^2^7 + 1) * 1009 * (10^5+3); factor(F, 10^5) \\ fast, incomplete time = 0 ms. %5 = [1009 1] [34029257539194609161727850866999116450334371 1] ? factor(F, 10^9) \\ slow time = 3,260 ms. %6 = [1009 1] [100003 1] [340282366920938463463374607431768211457 1] ? factorint(F, 1+8) \\ much faster and all small primes were found time = 8 ms. %7 = [1009 1] [100003 1] [340282366920938463463374607431768211457 1] ? factor(F) \\ complete factorization time = 60 ms. %8 = [1009 1] [100003 1] [59649589127497217 1] [5704689200685129054721 1] @eprog \misctitle{$x \in \Q(i)$} The factorization is performed with Gaussian primes in $\Z[i]$ and includes Gaussian units in $\{\pm1, \pm i\}$; factors are sorted by increasing norm. Except for a possible leading unit, the Gaussian factors are normalized: rational factors are positive and irrational factors have positive imaginary part. Unless \tet{factor_proven} is set, large factors are actually pseudoprimes, not proven primes; a rational factor is prime if less than $2^{64}$ and an irrational one if its norm is less than $2^{64}$. \bprog ? factor(5*I) %9 = [ 2 + I 1] [1 + 2*I 1] @eprog\noindent One can force the factorization of a rational number by setting the domain $D = I$: \bprog ? factor(-5, I) %10 = [ I 1] [ 2 + I 1] [1 + 2*I 1] ? factorback(%) %11 = -5 @eprog \misctitle{Univariate polynomials and rational functions} PARI can factor univariate polynomials in $K[t]$. The following base fields $K$ are currently supported: $\Q$, $\R$, $\C$, $\Q_{p}$, finite fields and number fields. See \tet{factormod} and \tet{factorff} for the algorithms used over finite fields and \tet{nffactor} for the algorithms over number fields. The irreducible factors are sorted by increasing degree and normalized: they are monic except when $K = \Q$ where they are primitive in $\Z[t]$. The content is \emph{not} included in the factorization, in particular \kbd{factorback} will in general recover the original $x$ only up to multiplication by an element of $K^{*}$: when $K\neq\Q$, this scalar is \kbd{pollead}$(x)$ (since irreducible factors are monic); and when $K = \Q$ you can either ask for the $\Q$-content explicitly of use factorback: \bprog ? P = t^2 + 5*t/2 + 1; F = factor(P) %12 = [t + 2 1] [2*t + 1 1] ? content(P, 1) \\ Q-content %13 = 1/2 ? pollead(factorback(F)) / pollead(P) %14 = 2 @eprog You can specify $K$ using the optional ``domain'' argument $D$ as follows \item $K = \Q$ : $D$ a rational number (\typ{INT} or \typ{FRAC}), \item $K = \Z/p\Z$ with $p$ prime : $D$ a \typ{INTMOD} modulo $p$; factoring modulo a composite number is not supported. \item $K = \F_{q}$ : $D$ a \typ{FFELT} encoding the finite field; you can also use a \typ{POLMOD} of \typ{INTMOD} modulo a prime $p$ but this is usualy less convenient; \item $K = \Q[X]/(T)$ a number field : $D$ a \typ{POLMOD} modulo $T$, \item $K = \Q(i)$ (alternate syntax for special case): $D = I$, \item $K = \Q(w)$ a quadratic number field (alternate syntax for special case): $D$ a \typ{QUAD}, \item $K = \R$ : $D$ a real number (\typ{REAL}); truncate the factorization at accuracy \kbd{precision}$(D)$. If $x$ is inexact and \kbd{precision}$(x)$ is less than \kbd{precision}$(D)$, then the precision of $x$ is used instead. \item $K = \C$ : $D$ a complex number with a \typ{REAL} component, e.g. \kbd{I * 1.}; truncate the factorization as for $K = \R$, \item $K = \Q_{p}$ : $D$ a \typ{PADIC}; truncate the factorization at $p$-adic accuracy \kbd{padicprec}$(D)$, possibly less if $x$ is inexact with insufficient $p$-adic accuracy; \bprog ? T = x^2+1; ? factor(T, 1); \\ over Q ? factor(T, Mod(1,3)) \\ over F_3 ? factor(T, ffgen(ffinit(3,2,'t))^0) \\ over F_{3^2} ? factor(T, Mod(Mod(1,3), t^2+t+2)) \\ over F_{3^2}, again ? factor(T, O(3^6)) \\ over Q_3, precision 6 ? factor(T, 1.) \\ over R, current precision ? factor(T, I*1.) \\ over C ? factor(T, Mod(1, y^3-2)) \\ over Q(2^{1/3}) @eprog\noindent In most cases, it is possible and simpler to call a specialized variant rather than use the above scheme: \bprog ? factormod(T, 3) \\ over F_3 ? factormod(T, [t^2+t+2, 3]) \\ over F_{3^2} ? factormod(T, ffgen(3^2, 't)) \\ over F_{3^2} ? factorpadic(T, 3,6) \\ over Q_3, precision 6 ? nffactor(y^3-2, T) \\ over Q(2^{1/3}) ? polroots(T) \\ over C ? polrootsreal(T) \\ over R (real polynomial) @eprog It is also possible to let the routine use the smallest field 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): \bprog ? T = x^2+1; ? factor(T); \\ over Q ? factor(T*Mod(1,3)) \\ over F_3 ? factor(T*ffgen(ffinit(3,2,'t))^0) \\ over F_{3^2} ? factor(T*Mod(Mod(1,3), t^2+t+2)) \\ over F_{3^2}, again ? factor(T*(1 + O(3^6)) \\ over Q_3, precision 6 ? factor(T*1.) \\ over R, current precision ? factor(T*(1.+0.*I)) \\ over C ? factor(T*Mod(1, y^3-2)) \\ over Q(2^{1/3}) @eprog\noindent Multiplying by a suitable field element equal to $1 \in K$ in this way is error-prone and is not recommanded. Factoring existing polynomials with obvious fields of coefficients is fine, the domain argument $D$ should be used instead ad hoc conversions. \misctitle{Note on inexact polynomials} Polynomials with inexact coefficients (e.g. floating point or $p$-adic numbers) are first rounded to an exact representation, then factored to (potentially) infinite accuracy and we return a truncated approximation of that virtual factorization. To avoid pitfalls, we advise to only factor \emph{exact} polynomials: \bprog ? factor(x^2-1+O(2^2)) \\ rounded to x^2 + 3, irreducible in Q_2 %1 = [(1 + O(2^2))*x^2 + O(2^2)*x + (1 + 2 + O(2^2)) 1] ? factor(x^2-1+O(2^3)) \\ rounded to x^2 + 7, reducible ! %2 = [ (1 + O(2^3))*x + (1 + 2 + O(2^3)) 1] [(1 + O(2^3))*x + (1 + 2^2 + O(2^3)) 1] ? factor(x^2-1, O(2^2)) \\ no ambiguity now %3 = [ (1 + O(2^2))*x + (1 + O(2^2)) 1] [(1 + O(2^2))*x + (1 + 2 + O(2^2)) 1] @eprog \misctitle{Note about inseparable polynomials} Polynomials with inexact coefficients are considered to be squarefree: indeed, there exist a squarefree polynomial arbitrarily close to the input, and they cannot be distinguished at the input accuracy. This means that irreducible factors are repeated according to their apparent multiplicity. On the contrary, using a specialized function such as \kbd{factorpadic} with an \emph{exact} rational input yields the correct multiplicity when the (now exact) input is not separable. Compare: \bprog ? factor(z^2 + O(5^2))) %1 = [(1 + O(5^2))*z + O(5^2) 1] [(1 + O(5^2))*z + O(5^2) 1] ? factor(z^2, O(5^2)) %2 = [1 + O(5^2))*z + O(5^2) 2] @eprog \misctitle{Multivariate polynomials and rational functions} PARI recursively factors \emph{multivariate} polynomials in $K[t_{1},\dots, t_{d}]$ for the same fields $K$ as above and the argument $D$ is used in the same way to specify $K$. The irreducible factors are sorted by their main variable (least priority first) then by increasing degree. \bprog ? factor(x^2 + y^2, Mod(1,5)) %1 = [ x + Mod(2, 5)*y 1] [Mod(1, 5)*x + Mod(3, 5)*y 1] ? factor(x^2 + y^2, O(5^2)) %2 = [ (1 + O(5^2))*x + (O(5^2)*y^2 + (2 + 5 + O(5^2))*y + O(5^2)) 1] [(1 + O(5^2))*x + (O(5^2)*y^2 + (3 + 3*5 + O(5^2))*y + O(5^2)) 1] ? lift(%) %3 = [ x + 7*y 1] [x + 18*y 1] @eprog\noindent Note that the implementation does not really support inexact real fields ($\R$ or $\C$) and usually misses factors even if the input is exact: \bprog ? factor(x^2 + y^2, I) \\ over Q(i) %4 = [x - I*y 1] [x + I*y 1] ? factor(x^2 + y^2, I*1.) \\ over C %5 = [x^2 + y^2 1] @eprog Variant: \fun{GEN}{factor}{GEN x} \fun{GEN}{boundfact}{GEN x, ulong lim}. 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.17.2/src/functions/number_theoretical/znstar0000644000175000017500000000273114676526175021130 0ustar billbillFunction: znstar Section: number_theoretical C-Name: znstar0 Prototype: GD0,L, Help: znstar(n,{flag=0}): 3-component vector v = [no,cyc,gen], giving the structure of the abelian group (Z/nZ)^*; no is the order (i.e. eulerphi(n)), cyc is a vector of cyclic components, and gen is a vector giving the corresponding generators. Doc: gives the structure of the multiplicative group $(\Z/n\Z)^{*}$. The output $G$ depends on the value of \fl: \item $\fl = 0$ (default), an abelian group structure $[h,d,g]$, where $h = \phi(n)$ is the order (\kbd{G.no}), $d$ (\kbd{G.cyc}) is a $k$-component row-vector $d$ of integers $d_{i}$ such that $d_{i}>1$, $d_{i} \mid d_{i-1}$ for $i \ge 2$ and $$ (\Z/n\Z)^{*} \simeq \prod_{i=1}^{k} (\Z/d_{i}\Z), $$ and $g$ (\kbd{G.gen}) is a $k$-component row vector giving generators of the image of the cyclic groups $\Z/d_{i}\Z$. \item $\fl = 1$ the result is a \kbd{bid} structure; this allows computing discrete logarithms using \tet{znlog} (also in the noncyclic case!). \bprog ? G = znstar(40) %1 = [16, [4, 2, 2], [Mod(17, 40), Mod(21, 40), Mod(11, 40)]] ? G.no \\ eulerphi(40) %2 = 16 ? G.cyc \\ cycle structure %3 = [4, 2, 2] ? G.gen \\ generators for the cyclic components %4 = [Mod(17, 40), Mod(21, 40), Mod(11, 40)] ? apply(znorder, G.gen) %5 = [4, 2, 2] @eprog\noindent For user convenience, we define \kbd{znstar(0)} as \kbd{[2, [2], [-1]]}, corresponding to $\Z^{*}$, but $\fl = 1$ is not implemented in this trivial case. pari-2.17.2/src/functions/number_theoretical/nextprime0000644000175000017500000000157514676526175021627 0ustar billbillFunction: nextprime Section: number_theoretical C-Name: nextprime Prototype: G Help: nextprime(x): smallest pseudoprime >= x. Description: (gen):int nextprime($1) Doc: finds the smallest pseudoprime (see \tet{ispseudoprime}) greater than or equal to $x$. $x$ can be of any real type. Note that if $x$ is a pseudoprime, this function returns $x$ and not the smallest pseudoprime strictly larger than $x$. To rigorously prove that the result is prime, use \kbd{isprime}. \bprog ? nextprime(2) %1 = 2 ? nextprime(Pi) %2 = 5 ? nextprime(-10) %3 = 2 \\ primes are positive @eprog\noindent Despite the name, please note that the function is not guaranteed to return a prime number, although no counter-example is known at present. The return value \emph{is} a guaranteed prime if $x \leq 2^{64}$. To rigorously prove that the result is prime in all cases, use \kbd{isprime}. pari-2.17.2/src/functions/number_theoretical/qfbcornacchia0000644000175000017500000000353614676526175022376 0ustar billbillFunction: qfbcornacchia Section: number_theoretical C-Name: qfbcornacchia Prototype: GG Help: qfbcornacchia(d,n): Solves the equation x^2+dy^2 = n in integers x and y where d > 0 and n is prime or 4 times a prime. Doc: Solves the equation $x^{2} + dy^{2} = n$ in integers $x$ and $y$, where $d > 0$ and $n$ is prime. Returns the empty vector \kbd{[]} when no solution exists. It is also allowed to try $n = 4$ times a prime but the answer is then guaranteed only if $d$ is $3$ mod $4$; more precisely if $d \neq 3$ mod $4$, the algorithm may fail to find a non-primitive solution. This function is a special case of \kbd{qfbsolve} applied to the principal form in the imaginary quadratic order of discriminant $-4d$ (returning the solution with non-negative $x$ and $y$). As its name implies, \kbd{qfbcornacchia} uses Cornacchia's algorithm and runs in time quasi-linear in $\log n$ (using \kbd{halfgcd}); in practical ranges, \kbd{qfbcornacchia} should be about twice faster than \kbd{qfbsolve} unless we indicate to the latter that its second argument is prime (see below). \bprog ? qfbcornacchia(1, 113) %1 = [8, 7] ? qfbsolve(Qfb(1,0,1), 113) %2 = [8, 7] ? qfbcornacchia(1, 4*113) \\ misses the non-primitive solution 2*[8,7] %3 = [] ? qfbcornacchia(1, 4*109) \\ finds a non-primitive solution %4 = [20, 6] ? p = 122838793181521; isprime(p) %5 = 1 ? qfbcornacchia(24, p) %6 = [10547339, 694995] ? Q = Qfb(1,0,24); qfbsolve(Q,p) %7 = [10547339, 694995] ? for (i=1, 10^5, qfbsolve(Q, p)) time = 345 ms. ? for (i=1, 10^5, qfbcornacchia(24,p)) \\ faster time = 251 ms. ? for (i=1, 10^5, qfbsolve(Q, Mat([p,1]))) \\ just as fast time = 251 ms. @eprog\noindent We used \kbd{Mat([p,1])} to indicate that $p^{1}$ was the integer factorization of $p$, i.e., that $p$ is prime. Without it, \kbd{qfbsolve} attempts to factor $p$ and wastes a little time. pari-2.17.2/src/functions/number_theoretical/factorcantor0000644000175000017500000000033014567450071022253 0ustar billbillFunction: factorcantor Section: number_theoretical C-Name: factmod Prototype: GG Obsolete: 2018-02-28 Help: factorcantor(x,p): this function is obsolete, use factormod. Doc: this function is obsolete, use factormod. pari-2.17.2/src/functions/number_theoretical/kronecker0000644000175000017500000000136614557721031021557 0ustar billbillFunction: kronecker Section: number_theoretical C-Name: kronecker Prototype: lGG Help: kronecker(x,y): kronecker symbol (x/y). Description: (small, small):small kross($1, $2) (int, small):small krois($1, $2) (small, int):small krosi($1, $2) (gen, gen):small kronecker($1, $2) Doc: \idx{Kronecker symbol} $(x|y)$, where $x$ and $y$ must be of type integer. By definition, this is the extension of \idx{Legendre symbol} to $\Z \times \Z$ by total multiplicativity in both arguments with the following special rules for $y = 0, -1$ or $2$: \item $(x|0) = 1$ if $|x| = 1$ and $0$ otherwise. \item $(x|-1) = 1$ if $x \geq 0$ and $-1$ otherwise. \item $(x|2) = 0$ if $x$ is even and $1$ if $x = 1,-1 \mod 8$ and $-1$ if $x=3,-3 \mod 8$. pari-2.17.2/src/functions/number_theoretical/quadhilbert0000644000175000017500000000110113637407207022067 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.17.2/src/functions/number_theoretical/znorder0000644000175000017500000000121514676526175021266 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):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 nonzero 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. pari-2.17.2/src/functions/number_theoretical/istotient0000644000175000017500000000067214557721031021615 0ustar billbillFunction: istotient Section: number_theoretical C-Name: istotient Prototype: lGD& Help: istotient(x,{&N}): true(1) if x = eulerphi(n) for some integer n, false(0) if not. If N is given, set N = n as well. Doc: true (1) if $x = \phi(n)$ for some integer $n$, false (0) if not. \bprog ? istotient(14) %1 = 0 ? istotient(100) %2 = 0 @eprog If $N$ is given, set $N = n$ as well. \bprog ? istotient(4, &n) %1 = 1 ? n %2 = 10 @eprog pari-2.17.2/src/functions/number_theoretical/qfbcomp0000644000175000017500000000063114676526175021233 0ustar billbillFunction: qfbcomp Section: number_theoretical C-Name: qfbcomp Prototype: GG Help: qfbcomp(x,y): Gaussian composition with reduction of the binary quadratic forms x and y. Doc: \idx{composition} of the binary quadratic forms $x$ and $y$, with \idx{reduction} of the result. \bprog ? x=Qfb(2,3,-10);y=Qfb(5,3,-4); ? qfbcomp(x,y) %2 = Qfb(-2, 9, 1) ? qfbcomp(x,y)==qfbred(qfbcompraw(x,y)) %3 = 1 @eprog pari-2.17.2/src/functions/number_theoretical/core0000644000175000017500000000122714676526175020536 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 nonzero, 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 nonzero, 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.17.2/src/functions/number_theoretical/randomprime0000644000175000017500000000337414676526175022130 0ustar billbillFunction: randomprime Section: number_theoretical C-Name: randomprime0 Prototype: DGDG Help: randomprime({N=2^31},{q}): returns a strong pseudo prime in [2, N-1]. If q is an integer, return a prime = 1 mod q; if q is an intmod, return a prime in the given congruence class. Doc: returns a strong pseudo prime (see \tet{ispseudoprime}) in $[2,N-1]$. A \typ{VEC} $N = [a,b]$ is also allowed, with $a \leq b$ in which case a pseudo prime $a \leq p \leq b$ is returned; if no prime exists in the interval, the function will run into an infinite loop. If the upper bound is less than $2^{64}$ the pseudo prime returned is a proven prime. \bprog ? randomprime(100) %1 = 71 ? randomprime([3,100]) %2 = 61 ? randomprime([1,1]) *** at top-level: randomprime([1,1]) *** ^------------------ *** randomprime: domain error in randomprime: *** floor(b) - max(ceil(a),2) < 0 ? randomprime([24,28]) \\ infinite loop @eprog If the optional parameter $q$ is an integer, return a prime congruent to $1 \mod q$; if $q$ is an intmod, return a prime in the given congruence class. If the class contains no prime in the given interval, the function will raise an exception if the class is not invertible, else run into an infinite loop \bprog ? randomprime(100, 4) \\ 1 mod 4 %1 = 71 ? randomprime(100, 4) %2 = 13 ? randomprime([10,100], Mod(2,5)) %3 = 47 ? randomprime(100, Mod(0,2)) \\ silly but works %4 = 2 ? randomprime([3,100], Mod(0,2)) \\ not invertible *** at top-level: randomprime([3,100],Mod(0,2)) *** ^----------------------------- *** randomprime: elements not coprime in randomprime: 0 2 ? randomprime(100, 97) \\ infinite loop @eprog Variant: Also available is \fun{GEN}{randomprime}{GEN N = NULL}. pari-2.17.2/src/functions/number_theoretical/factorff0000644000175000017500000000033114567450071021361 0ustar billbillFunction: factorff Section: number_theoretical C-Name: factorff Prototype: GDGDG Obsolete: 2018-03-11 Help: factorff(x,{p},{a}): obsolete, use factormod. Doc: obsolete, kept for backward compatibility: use factormod. pari-2.17.2/src/functions/number_theoretical/quaddisc0000644000175000017500000000104214676526175021376 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 \'etale algebra $\Q(\sqrt{x})$, where $x\in\Q^{*}$. This is the same as \kbd{coredisc}$(d)$ where $d$ is the integer squarefree part of $x$, so $x=d f^{2}$ with $f\in \Q^{*}$ and $d\in\Z$. This returns $0$ for $x = 0$, $1$ for $x$ square and the discriminant of the quadratic field $\Q(\sqrt{x})$ otherwise. \bprog ? quaddisc(7) %1 = 28 ? quaddisc(-7) %2 = -7 @eprog pari-2.17.2/src/functions/number_theoretical/ffembed0000644000175000017500000000104614676526175021175 0ustar billbillFunction: ffembed Section: number_theoretical C-Name: ffembed Prototype: GG Help: ffembed(a,b): given two elements a and b in finite fields, return a map embedding the definition field of a to the definition field of b. Doc: given two finite fields elements $a$ and $b$, return a \var{map} embedding the definition field of $a$ to the definition field of $b$. Assume that the latter contains the former. \bprog ? a = ffgen([3,5],'a); ? b = ffgen([3,10],'b); ? m = ffembed(a, b); ? A = ffmap(m, a); ? minpoly(A) == minpoly(a) %5 = 1 @eprog pari-2.17.2/src/functions/number_theoretical/contfrac0000644000175000017500000000563214676526175021411 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_{1}a_{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.17.2/src/functions/number_theoretical/fflog0000644000175000017500000000347514676526175020712 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 represent the multiplicative order of g. If no o is given, assume that g is a primitive root. Doc: discrete logarithm of the finite field element $x$ in base $g$, i.e.~an $e$ in $\Z$ such that $g^{e} = o$. If present, $o$ represents the multiplicative order of $g$, see \secref{se:DLfun}; the preferred format for this parameter is \kbd{[ord, factor(ord)]}, where \kbd{ord} is the order of $g$. It may be set as a side effect of calling \tet{ffprimroot}. The result is undefined if $e$ does not exist. This function uses \item a combination of generic discrete log algorithms (see \tet{znlog}) \item a cubic sieve index calculus algorithm for large fields of degree at least $5$. \item Coppersmith's algorithm for fields of characteristic at most $5$. \bprog ? t = ffgen(ffinit(7,5)); ? o = fforder(t) %2 = 5602 \\@com \emph{not} a primitive root. ? fflog(t^10,t) %3 = 10 ? fflog(t^10,t, o) %4 = 10 ? g = ffprimroot(t, &o); ? o \\ order is 16806, bundled with its factorization matrix %6 = [16806, [2, 1; 3, 1; 2801, 1]] ? fforder(g, o) %7 = 16806 ? fflog(g^10000, g, o) %8 = 10000 @eprog Function: _Flxq_log_Coppersmith_worker C-Name: Flxq_log_Coppersmith_worker Prototype: GLGG Section: programming/internals Help: Flxq_log_Coppersmith_worker: worker for Flxq_log_Coppersmith Function: _F2xq_log_Coppersmith_worker C-Name: F2xq_log_Coppersmith_worker Prototype: GLGG Section: programming/internals Help: F2xq_log_Coppersmith_worker: worker for F2xq_log_Coppersmith Function: _Fp_log_sieve_worker C-Name: Fp_log_sieve_worker Prototype: LLGGGGGG Section: programming/internals Help: Fp_log_sieve_worker: worker for Fp_log_sieve pari-2.17.2/src/functions/number_theoretical/gcdext0000644000175000017500000000214314557721031021044 0ustar billbillFunction: gcdext Section: number_theoretical C-Name: gcdext0 Prototype: GG Help: gcdext(x,y): returns [u,v,d] such that d=gcd(x,y) and u*x+v*y=d. Doc: Returns $[u,v,d]$ such that $d$ is the gcd of $x,y$, $x*u+y*v=\gcd(x,y)$, and $u$ and $v$ minimal in a natural sense. The arguments must be integers or polynomials. \sidx{extended gcd} \sidx{Bezout relation} \bprog ? [u, v, d] = gcdext(32,102) %1 = [16, -5, 2] ? d %2 = 2 ? gcdext(x^2-x, x^2+x-2) %3 = [-1/2, 1/2, x - 1] @eprog If $x,y$ are polynomials in the same variable and \emph{inexact} coefficients, then compute $u,v,d$ such that $x*u+y*v = d$, where $d$ approximately divides both and $x$ and $y$; in particular, we do not obtain \kbd{gcd(x,y)} which is \emph{defined} to be a scalar in this case: \bprog ? a = x + 0.0; gcd(a,a) %1 = 1 ? gcdext(a,a) %2 = [0, 1, x + 0.E-28] ? gcdext(x-Pi, 6*x^2-zeta(2)) %3 = [-6*x - 18.8495559, 1, 57.5726923] @eprog\noindent For inexact inputs, the output is thus not well defined mathematically, but you obtain explicit polynomials to check whether the approximation is close enough for your needs. pari-2.17.2/src/functions/number_theoretical/sigma0000644000175000017500000000072314557721031020670 0ustar billbillFunction: sigma Section: number_theoretical C-Name: sumdivk Prototype: GD1,L, Help: sigma(x,{k=1}): sum of the k-th powers of the divisors of x. k is optional and if omitted is assumed to be equal to 1. Description: (gen, ?1):int sumdiv($1) (gen, 0):int numdiv($1) Doc: sum of the $k^{\text{th}}$ powers of the positive divisors of $|x|$. $x$ and $k$ must be of type integer. Variant: Also available is \fun{GEN}{sumdiv}{GEN n}, for $k = 1$. pari-2.17.2/src/functions/number_theoretical/dirdiv0000644000175000017500000000051613637407207021055 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.17.2/src/functions/number_theoretical/ffmaprel0000644000175000017500000000171414676526175021403 0ustar billbillFunction: ffmaprel Section: number_theoretical C-Name: ffmaprel Prototype: GG Help: ffmaprel(m,x): given a (partial) map m between two finite fields, express x as an algebraic element over the codomain of m in a way which is compatible with m. The function is applied recursively to the component of vectors, matrices and polynomials. Doc: given a (partial) map $m$ between two finite fields, express $x$ as an algebraic element over the codomain of $m$ in a way which is compatible with $m$. The function is applied recursively to the component of vectors, matrices and polynomials. \bprog ? a = ffgen([3,5],'a); ? b = ffgen([3,10],'b); ? m = ffembed(a, b); ? mi= ffinvmap(m); ? R = ffmaprel(mi,b) %5 = Mod(b,b^2+(a+1)*b+(a^2+2*a+2)) @eprog In particular, this function can be used to compute the relative minimal polynomial, norm and trace: \bprog ? minpoly(R) %6 = x^2+(a+1)*x+(a^2+2*a+2) ? trace(R) %7 = 2*a+2 ? norm(R) %8 = a^2+2*a+2 @eprog pari-2.17.2/src/functions/number_theoretical/divisorslenstra0000644000175000017500000000162214676526175023040 0ustar billbillFunction: divisorslenstra Section: number_theoretical C-Name: divisorslenstra Prototype: GGG Help: divisorslenstra(N,r,s): finds all divisors d of N such that d = r (mod s). Assume that (r,s) = 1 and s^3 > N. Doc: Given three integers $N > s > r \geq 0$ such that $(r,s) = 1$ and $s^{3} > N$, find all divisors $d$ of $N$ such that $d \equiv r \pmod{s}$. There are at most $11$ such divisors (Lenstra). \bprog ? N = 245784; r = 19; s = 65 ; ? divisorslenstra(N, r, s) %2 = [19, 84, 539, 1254, 3724, 245784] ? [ d | d <- divisors(N), d % s == r] %3 = [19, 84, 539, 1254, 3724, 245784] @eprog\noindent When the preconditions are not met, the result is undefined: \bprog ? N = 4484075232; r = 7; s = 1303; s^3 > N %4 = 0 ? divisorslenstra(N, r, s) ? [ d | d <- divisors(N), d % s == r ] %6 = [7, 2613, 9128, 19552, 264516, 3407352, 344928864] @eprog\noindent (Divisors were missing but $s^{3} < N$.) pari-2.17.2/src/functions/number_theoretical/omega0000644000175000017500000000055214557721031020660 0ustar billbillFunction: omega Section: number_theoretical C-Name: omega Prototype: lG Help: omega(x): number of distinct prime divisors of x. Doc: number of distinct prime divisors of $|x|$. $x$ must be of type integer. \bprog ? factor(392) %1 = [2 3] [7 2] ? omega(392) %2 = 2; \\ without multiplicity ? bigomega(392) %3 = 5; \\ = 3+2, with multiplicity @eprog pari-2.17.2/src/functions/number_theoretical/bigomega0000644000175000017500000000056314557721031021344 0ustar billbillFunction: bigomega Section: number_theoretical C-Name: bigomega Prototype: lG Help: bigomega(x): number of prime divisors of x, counted with multiplicity. Doc: number of prime divisors of the integer $|x|$ counted with multiplicity: \bprog ? factor(392) %1 = [2 3] [7 2] ? bigomega(392) %2 = 5; \\ = 3+2 ? omega(392) %3 = 2; \\ without multiplicity @eprog pari-2.17.2/src/functions/number_theoretical/contfracpnqn0000644000175000017500000000301414676526175022276 0ustar billbillFunction: contfracpnqn Section: number_theoretical C-Name: contfracpnqn Prototype: GD-1,L, Help: contfracpnqn(x,{n=-1}): [p_n,p_{n-1}; q_n,q_{n-1}] corresponding to the continued fraction x. If n >= 0 is present, returns all convergents from p_0/q_0 up to p_n/q_n. Doc: when $x$ is a vector or a one-row matrix, $x$ is considered as the list of partial quotients $[a_{0},a_{1},\dots,a_{n}]$ of a rational number, and the result is the 2 by 2 matrix $[p_{n},p_{n-1};q_{n},q_{n-1}]$ in the standard notation of continued fractions, so $p_{n}/q_{n}=a_{0}+1/(a_{1}+\dots+1/a_{n})$. If $x$ is a matrix with two rows $[b_{0},b_{1},\dots,b_{n}]$ and $[a_{0},a_{1},\dots,a_{n}]$, this is then considered as a generalized continued fraction and we have similarly $p_{n}/q_{n}=(1/b_{0})(a_{0}+b_{1}/(a_{1}+\dots+b_{n}/a_{n}))$. Note that in this case one usually has $b_{0}=1$. If $n \geq 0$ is present, returns all convergents from $p_{0}/q_{0}$ up to $p_{n}/q_{n}$. (All convergents if $x$ is too small to compute the $n+1$ requested convergents.) \bprog ? a = contfrac(Pi,10) %1 = [3, 7, 15, 1, 292, 1, 1, 1, 3] ? allpnqn(x) = contfracpnqn(x,#x) \\ all convergents ? allpnqn(a) %3 = [3 22 333 355 103993 104348 208341 312689 1146408] [1 7 106 113 33102 33215 66317 99532 364913] ? contfracpnqn(a) \\ last two convergents %4 = [1146408 312689] [ 364913 99532] ? contfracpnqn(a,3) \\ first three convergents %5 = [3 22 333 355] [1 7 106 113] @eprog Variant: also available is \fun{GEN}{pnqn}{GEN x} for $n = -1$. pari-2.17.2/src/functions/number_theoretical/zncharinduce0000644000175000017500000000335314676526175022265 0ustar billbillFunction: zncharinduce Section: number_theoretical C-Name: zncharinduce Prototype: GGG Help: zncharinduce(G,chi,N): let G be znstar(q,1), let chi be a Dirichlet character mod q and let N be a multiple of q. Return the character modulo N extending chi. Doc: Let $G$ be attached to $(\Z/q\Z)^{*}$ (as per \kbd{G = znstar(q,1)}) and let \kbd{chi} be a Dirichlet character on $(\Z/q\Z)^{*}$, given by \item a \typ{VEC}: a standard character on \kbd{bid.gen}, \item a \typ{INT} or a \typ{COL}: a Conrey index in $(\Z/q\Z)^{*}$ or its Conrey logarithm; see \secref{se:dirichletchar} or \kbd{??character}. Let $N$ be a multiple of $q$, return the character modulo $N$ extending \kbd{chi}. As usual for arithmetic functions, the new modulus $N$ can be given as a \typ{INT}, via a factorization matrix or a pair \kbd{[N, factor(N)]}, or by \kbd{znstar(N,1)}. \bprog ? G = znstar(4, 1); ? chi = znconreylog(G,1); \\ trivial character mod 4 ? zncharinduce(G, chi, 80) \\ now mod 80 %3 = [0, 0, 0]~ ? zncharinduce(G, 1, 80) \\ same using directly Conrey label %4 = [0, 0, 0]~ ? G2 = znstar(80, 1); ? zncharinduce(G, 1, G2) \\ same %4 = [0, 0, 0]~ ? chi = zncharinduce(G, 3, G2) \\ extend the nontrivial character mod 4 %5 = [1, 0, 0]~ ? [G0,chi0] = znchartoprimitive(G2, chi); ? G0.mod %7 = 4 ? chi0 %8 = [1]~ @eprog\noindent Here is a larger example: \bprog ? G = znstar(126000, 1); ? label = 1009; ? chi = znconreylog(G, label) %3 = [0, 0, 0, 14, 0]~ ? [G0,chi0] = znchartoprimitive(G, label); \\ works also with 'chi' ? G0.mod %5 = 125 ? chi0 \\ primitive character mod 5^3 attached to chi %6 = [14]~ ? G0 = znstar(N0, 1); ? zncharinduce(G0, chi0, G) \\ induce back %8 = [0, 0, 0, 14, 0]~ ? znconreyexp(G, %) %9 = 1009 @eprog pari-2.17.2/src/functions/number_theoretical/quadray0000644000175000017500000000114614676526175021254 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.17.2/src/functions/number_theoretical/removeprimes0000644000175000017500000000073413637407207022313 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.17.2/src/functions/number_theoretical/bestapprPade0000644000175000017500000000537014760123736022211 0ustar billbillFunction: bestapprPade Section: number_theoretical C-Name: bestapprPade0 Prototype: GD-1,L,D-1,L, Help: bestapprPade(x,{B},{Q}): returns a rational function approximation to x. This function applies to series, polmods, and rational functions of course. Otherwise it applies recursively to all components. Doc: using variants of the extended Euclidean algorithm (Pad\'{e} approximants), returns a rational function approximation $a/b$ to $x$, whose denominator is limited by $B$, if present. If $B$ is omitted, return the best approximation affordable given the input accuracy; if you are looking for true rational functions, presumably approximated to sufficient accuracy, you should first try that option. Otherwise, $B$ must be a nonnegative real (impose $0 \leq \text{degree}(b) \leq B$). \item If $x$ is a \typ{POLMOD} modulo $N$ this function performs rational modular reconstruction modulo $N$. The routine then returns the unique rational function $a/b$ in coprime polynomials, with $\text{degree}(b)\leq B$ and $\text{degree}(a)$ minimal, which is congruent to $x$ modulo $N$. Omitting $B$ amounts to choosing it equal to the floor of $\text{degree}(N) / 2$. If rational reconstruction is not possible (no suitable $a/b$ exists), returns $[]$. \bprog ? T = Mod(x^3 + x^2 + x + 3, x^4 - 2); ? bestapprPade(T) %2 = (2*x - 1)/(x - 1) ? U = Mod(1 + x + x^2 + x^3 + x^5, x^9); ? bestapprPade(U) \\ internally chooses B = 4 %3 = [] ? bestapprPade(U, 5) \\ with B = 5, a solution exists %4 = (2*x^4 + x^3 - x - 1)/(-x^5 + x^3 + x^2 - 1) @eprog \item If $x$ is a \typ{SER}, we implicitly convert the input to a \typ{POLMOD} modulo $N = t^{k}$ where $k$ is the series absolute precision. \bprog ? T = 1 + t + t^2 + t^3 + t^4 + t^5 + t^6 + O(t^7); \\ mod t^7 ? bestapprPade(T) %1 = 1/(-t + 1) @eprog \item If $x$ is a \typ{SER} and both $B$ and $Q$ are nonnegative, returns a rational function approximation $a/b$ to $x$, with $a$ of degree at most $B$ and $b$ of degree at most $Q$, with $x-a/b=O(t^{B+Q+1+v})$ if $t$ is the variable, where $v$ is the valuation of $x$, the empty vector if not possible. \item If $x$ is a \typ{RFRAC}, we implicitly convert the input to a \typ{POLMOD} modulo $N = t^{k}$ where $k = 2B + 1$. If $B$ was omitted, we return $x$: \bprog ? T = (4*t^2 + 2*t + 3)/(t+1)^10; ? bestapprPade(T,1) %2 = [] \\ impossible ? bestapprPade(T,2) %3 = 27/(337*t^2 + 84*t + 9) ? bestapprPade(T,3) %4 = (4253*t - 3345)/(-39007*t^3 - 28519*t^2 - 8989*t - 1115) @eprog\noindent The function applies recursively to components of complex objects (polynomials, vectors, \dots). If rational reconstruction fails for even a single entry, return $[]$. Variant: \fun{GEN}{bestapprPade}{GEN x, long B} as \kbd{bestapprPade0} when Q is ommited. pari-2.17.2/src/functions/number_theoretical/znchar0000644000175000017500000000340214676526175021070 0ustar billbillFunction: znchar Section: number_theoretical C-Name: znchar Prototype: G Help: znchar(D): given a datum D describing a group G = (Z/NZ)^* and a Dirichlet character chi, return the pair [G,chi]. Doc: Given a datum $D$ describing a group $(\Z/N\Z)^{*}$ and a Dirichlet character $\chi$, return the pair \kbd{[G, chi]}, where \kbd{G} is \kbd{znstar(N, 1)}) and \kbd{chi} is a GP character. The following possibilities for $D$ are supported \item a nonzero \typ{INT} congruent to $0,1$ modulo $4$, return the real character modulo $D$ given by the Kronecker symbol $(D/.)$; \item a \typ{INTMOD} \kbd{Mod(m, N)}, return the Conrey character modulo $N$ of index $m$ (see \kbd{znconreylog}). \item a modular form space as per \kbd{mfinit}$([N,k,\chi])$ or a modular form for such a space, return the underlying Dirichlet character $\chi$ (which may be defined modulo a divisor of $N$ but need not be primitive). In the remaining cases, \kbd{G} is initialized by \kbd{znstar(N, 1)}. \item a pair \kbd{[G, chi]}, where \kbd{chi} is a standard GP Dirichlet character $c = (c_{j})$ on \kbd{G} (generic character \typ{VEC} or Conrey characters \typ{COL} or \typ{INT}); given generators $G = \oplus (\Z/d_{j}\Z) g_{j}$, $\chi(g_{j}) = e(c_{j}/d_{j})$. \item a pair \kbd{[G, chin]}, where \kbd{chin} is a \emph{normalized} representation $[n, \tilde{c}]$ of the Dirichlet character $c$; $\chi(g_{j}) = e(\tilde{c}_{j} / n)$ where $n$ is minimal (order of $\chi$). \bprog ? [G,chi] = znchar(-3); ? G.cyc %2 = [2] ? chareval(G, chi, 2) %3 = 1/2 ? kronecker(-3,2) %4 = -1 ? znchartokronecker(G,chi) %5 = -3 ? mf = mfinit([28, 5/2, Mod(2,7)]); [f] = mfbasis(mf); ? [G,chi] = znchar(mf); [G.mod, chi] %7 = [7, [2]~] ? [G,chi] = znchar(f); chi %8 = [28, [0, 2]~] @eprog pari-2.17.2/src/functions/number_theoretical/znconreychar0000644000175000017500000000563514676526175022322 0ustar billbillFunction: znconreychar Section: number_theoretical C-Name: znconreychar Prototype: GG Help: znconreychar(G,m): Dirichlet character attached to m in (Z/qZ)* in Conrey's notation, where G is znstar(q,1). Doc: Given a \var{znstar} $G$ attached to $(\Z/q\Z)^{*}$ (as per \kbd{G = znstar(q,1)}), this function returns the Dirichlet character attached to $m \in (\Z/q\Z)^{*}$ via Conrey's logarithm, which establishes a ``canonical'' bijection between $(\Z/q\Z)^{*}$ and its dual. Let $q = \prod_{p} p^{e_{p}}$ be the factorization of $q$ into distinct primes. For all odd $p$ with $e_{p} > 0$, let $g_{p}$ be the element in $(\Z/q\Z)^{*}$ which is \item congruent to $1$ mod $q/p^{e_{p}}$, \item congruent mod $p^{e_{p}}$ to the smallest positive integer that generates $(\Z/p^{2}\Z)^{*}$. For $p = 2$, we let $g_{4}$ (if $2^{e_{2}} \geq 4$) and $g_{8}$ (if furthermore ($2^{e_{2}} \geq 8$) be the elements in $(\Z/q\Z)^{*}$ which are \item congruent to $1$ mod $q/2^{e_{2}}$, \item $g_{4} = -1 \mod 2^{e_{2}}$, \item $g_{8} = 5 \mod 2^{e_{2}}$. Then the $g_{p}$ (and the extra $g_{4}$ and $g_{8}$ if $2^{e_{2}}\geq 2$) are independent generators of $(\Z/q\Z)^{*}$, i.e. every $m$ in $(\Z/q\Z)^{*}$ can be written uniquely as $\prod_{p} g_{p}^{m_{p}}$, where $m_{p}$ is defined modulo the order $o_{p}$ of $g_{p}$ and $p \in S_{q}$, the set of prime divisors of $q$ together with $4$ if $4 \mid q$ and $8$ if $8 \mid q$. Note that the $g_{p}$ are in general \emph{not} SNF generators as produced by \kbd{znstar} whenever $\omega(q) \geq 2$, although their number is the same. They however allow to handle the finite abelian group $(\Z/q\Z)^{*}$ in a fast and elegant way. (Which unfortunately does not generalize to ray class groups or Hecke characters.) The Conrey logarithm of $m$ is the vector $(m_{p})_{p\in S_{q}}$, obtained via \tet{znconreylog}. The Conrey character $\chi_{q}(m,\cdot)$ attached to $m$ mod $q$ maps each $g_{p}$, $p\in S_{q}$ to $e(m_{p} / o_{p})$, where $e(x) = \exp(2i\pi x)$. This function returns the Conrey character expressed in the standard PARI way in terms of the SNF generators \kbd{G.gen}. \bprog ? G = znstar(8,1); ? G.cyc %2 = [2, 2] \\ Z/2 x Z/2 ? G.gen %3 = [7, 3] ? znconreychar(G,1) \\ 1 is always the trivial character %4 = [0, 0] ? znconreychar(G,2) \\ 2 is not coprime to 8 !!! *** at top-level: znconreychar(G,2) *** ^----------------- *** znconreychar: elements not coprime in Zideallog: 2 8 *** Break loop: type 'break' to go back to GP prompt break> ? znconreychar(G,3) %5 = [0, 1] ? znconreychar(G,5) %6 = [1, 1] ? znconreychar(G,7) %7 = [1, 0] @eprog\noindent We indeed get all 4 characters of $(\Z/8\Z)^{*}$. For convenience, we allow to input the \emph{Conrey logarithm} of $m$ instead of $m$: \bprog ? G = znstar(55, 1); ? znconreychar(G,7) %2 = [7, 0] ? znconreychar(G, znconreylog(G,7)) %3 = [7, 0] @eprog pari-2.17.2/src/functions/number_theoretical/qfbredsl20000644000175000017500000000144414676526175021473 0ustar billbillFunction: qfbredsl2 Section: number_theoretical C-Name: qfbredsl2 Prototype: GDG Help: qfbredsl2(x,{isD}): reduction of the binary quadratic form x, returns [y,g] where y is reduced and g in Sl(2,Z) is such that g.x = y; isD, if present, must be equal to sqrtint(D), where D > 0 is the discriminant of x. Doc: reduction of the (real or imaginary) binary quadratic form $x$, returns $[y,g]$ where $y$ is reduced and $g$ in $\text{SL}(2,\Z)$ is such that $g \cdot x = y$; \var{isD}, if present, must be equal to $\kbd{sqrtint}(D)$, where $D > 0$ is the discriminant of $x$. The action of $g$ on $x$ can be computed using \kbd{qfeval(x,g)} \bprog ? q1 = Qfb(33947,-39899,11650); ? [q2,U] = qfbredsl2(q1) %2 = [Qfb(749,2207,-1712),[-1,3;-2,5]] ? qfeval(q1,U) %3 = Qfb(749,2207,-1712) @eprog pari-2.17.2/src/functions/number_theoretical/issquarefree0000644000175000017500000000274114567450071022274 0ustar billbillFunction: issquarefree Section: number_theoretical C-Name: issquarefree Prototype: lG Help: issquarefree(x): true(1) if x is squarefree, false(0) if not. Description: (gen):bool issquarefree($1) Doc: true (1) if $x$ is squarefree, false (0) if not. Here $x$ can be an integer or a polynomial with coefficients in an integral domain. \bprog ? issquarefree(12) %1 = 0 ? issquarefree(6) %2 = 1 ? issquarefree(x^3+x^2) %3 = 0 ? issquarefree(Mod(1,4)*(x^2+x+1)) \\ Z/4Z is not a domain ! *** at top-level: issquarefree(Mod(1,4)*(x^2+x+1)) *** ^-------------------------------- *** issquarefree: impossible inverse in Fp_inv: Mod(2, 4). @eprog\noindent A polynomial is declared squarefree if \kbd{gcd}$(x,x')$ is $1$. In particular a nonzero polynomial with inexact coefficients is considered to be squarefree. Note that this may be inconsistent with \kbd{factor}, which first rounds the input to some exact approximation before factoring in the apropriate domain; this is correct when the input is not close to an inseparable polynomial (the resultant of $x$ and $x'$ is not close to $0$). An integer can be input in factored form as in arithmetic functions. \bprog ? issquarefree(factor(6)) %1 = 1 \\ count squarefree integers up to 10^8 ? c = 0; for(d = 1, 10^8, if (issquarefree(d), c++)); c time = 3min, 2,590 ms. %2 = 60792694 ? c = 0; forfactored(d = 1, 10^8, if (issquarefree(d), c++)); c time = 45,348 ms. \\ faster ! %3 = 60792694 @eprog pari-2.17.2/src/functions/number_theoretical/sumdedekind0000644000175000017500000000051114567450071022063 0ustar billbillFunction: sumdedekind Section: number_theoretical C-Name: sumdedekind Prototype: GG Help: sumdedekind(h,k): Dedekind sum attached to h,k. Doc: returns the \idx{Dedekind sum} attached 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.17.2/src/functions/number_theoretical/sqrtnint0000644000175000017500000000104314676526175021464 0ustar billbillFunction: sqrtnint Section: number_theoretical C-Name: sqrtnint Prototype: GL Help: sqrtnint(x,n): integer n-th root of x, where x is nonnegative real number. Description: (gen,small):int sqrtnint($1, $2) Doc: returns the integer $n$-th root of $x$, i.e. the largest integer $y$ such that $y^{n} \leq x$, where $x$ is a nonnegative real number. \bprog ? N = 120938191237; sqrtnint(N, 5) %1 = 164 ? N^(1/5) %2 = 164.63140849829660842958614676939677391 ? sqrtnint(Pi^2, 3) %3 = 2 @eprog\noindent The special case $n = 2$ is \tet{sqrtint} pari-2.17.2/src/functions/number_theoretical/fffrobenius0000644000175000017500000000074614567450071022111 0ustar billbillFunction: fffrobenius Section: number_theoretical C-Name: fffrobenius Prototype: GD1,L, Help: fffrobenius(m,{n=1}): return the n-th power of the Frobenius map over the field of definition of m. Doc: return the $n$-th power of the Frobenius map over the field of definition of $m$. \bprog ? a = ffgen([3,5],'a); ? f = fffrobenius(a); ? ffmap(f,a) == a^3 %3 = 1 ? g = fffrobenius(a, 5); ? ffmap(g,a) == a %5 = 1 ? h = fffrobenius(a, 2); ? h == ffcompomap(f,f) %7 = 1 @eprog pari-2.17.2/src/functions/number_theoretical/znlog0000644000175000017500000000537114676526175020743 0ustar billbillFunction: znlog Section: number_theoretical C-Name: znlog0 Prototype: GGDG Help: znlog(x,g,{o}): return the discrete logarithm of x in (Z/nZ)* in base g. If present, o represents the multiplicative order of g. Return [] if no solution exist. Doc: This functions allows two distinct modes of operation depending on $g$: \item if $g$ is the output of \tet{znstar} (with initialization), we compute the discrete logarithm of $x$ with respect to the generators contained in the structure. See \tet{ideallog} for details. \item else $g$ is an explicit element in $(\Z/N\Z)^{*}$, we compute the discrete logarithm of $x$ in $(\Z/N\Z)^{*}$ in base $g$. The rest of this entry describes the latter possibility. The result is $[]$ when $x$ is not a power of $g$, though the function may also enter an infinite loop in this case. If present, $o$ represents the multiplicative order of $g$, see \secref{se:DLfun}; the preferred format for this parameter is \kbd{[ord, factor(ord)]}, where \kbd{ord} is the order of $g$. This provides a definite speedup when the discrete log problem is simple: \bprog ? p = nextprime(10^4); g = znprimroot(p); o = [p-1, factor(p-1)]; ? for(i=1,10^4, znlog(i, g, o)) time = 163 ms. ? for(i=1,10^4, znlog(i, g)) time = 200 ms. \\ a little slower @eprog The result is undefined if $g$ is not invertible mod $N$ or if the supplied order is incorrect. This function uses \item a combination of generic discrete log algorithms (see below). \item in $(\Z/N\Z)^{*}$ when $N$ is prime: a linear sieve index calculus method, suitable for $N < 10^{50}$, say, is used for large prime divisors of the order. The generic discrete log algorithms are: \item Pohlig-Hellman algorithm, to reduce to groups of prime order $q$, where $q | p-1$ and $p$ is an odd prime divisor of $N$, \item Shanks baby-step/giant-step ($q < 2^{32}$ is small), \item Pollard rho method ($q > 2^{32}$). The latter two algorithms require $O(\sqrt{q})$ operations in the group on average, hence will not be able to treat cases where $q > 10^{30}$, say. In addition, Pollard rho is not able to handle the case where there are no solutions: it will enter an infinite loop. \bprog ? g = znprimroot(101) %1 = Mod(2,101) ? znlog(5, g) %2 = 24 ? g^24 %3 = Mod(5, 101) ? G = znprimroot(2 * 101^10) %4 = Mod(110462212541120451003, 220924425082240902002) ? znlog(5, G) %5 = 76210072736547066624 ? G^% == 5 %6 = 1 ? N = 2^4*3^2*5^3*7^4*11; g = Mod(13, N); znlog(g^110, g) %7 = 110 ? znlog(6, Mod(2,3)) \\ no solution %8 = [] @eprog\noindent For convenience, $g$ is also allowed to be a $p$-adic number: \bprog ? g = 3+O(5^10); znlog(2, g) %1 = 1015243 ? g^% %2 = 2 + O(5^10) @eprog Variant: The function \fun{GEN}{znlog}{GEN x, GEN g, GEN o} is also available pari-2.17.2/src/functions/number_theoretical/znconreyexp0000644000175000017500000000217714676526175022177 0ustar billbillFunction: znconreyexp Section: number_theoretical C-Name: znconreyexp Prototype: GG Help: znconreyexp(G,chi): Conrey exponential attached to G = znstar(q, 1). Returns the element m in (Z/qZ)^* attached to the character chi on G: znconreylog(G, m) = chi. Doc: Given a \var{znstar} $G$ attached to $(\Z/q\Z)^{*}$ (as per \kbd{G = znstar(q, 1)}), this function returns the Conrey exponential of the character \var{chi}: it returns the integer $m \in (\Z/q\Z)^{*}$ such that \kbd{znconreylog(G, $m$)} is \var{chi}. The character \var{chi} is given either as a \item \typ{VEC}: in terms of the generators \kbd{G.gen}; \item \typ{COL}: a Conrey logarithm. \bprog ? G = znstar(126000, 1) ? znconreylog(G,1) %2 = [0, 0, 0, 0, 0]~ ? znconreyexp(G,%) %3 = 1 ? G.cyc \\ SNF generators %4 = [300, 12, 2, 2, 2] ? chi = [100, 1, 0, 1, 0]; \\ some random character on SNF generators ? znconreylog(G, chi) \\ in terms of Conrey generators %6 = [0, 3, 3, 0, 2]~ ? znconreyexp(G, %) \\ apply to a Conrey log %7 = 18251 ? znconreyexp(G, chi) \\ ... or a char on SNF generators %8 = 18251 ? znconreychar(G,%) %9 = [100, 1, 0, 1, 0] @eprog pari-2.17.2/src/functions/number_theoretical/ffinit0000644000175000017500000000130114760137411021037 0ustar billbillFunction: ffinit Section: number_theoretical C-Name: ffinit Prototype: GLDn Help: ffinit(p,n,{v='x}): monic irreducible polynomial of degree n in F_p[v]. Description: (int, small, ?var):pol ffinit($1, $2, $3) Doc: computes a monic polynomial of degree $n$ which is irreducible over $\F_{p}$, where $p$ is assumed to be prime. This function uses a fast variant of Adleman and Lenstra's algorithm. It is useful in conjunction with \tet{ffgen}; for instance if \kbd{P = ffinit(3,2)}, you can represent elements in $\F_{3^{2}}$ in term of \kbd{g = ffgen(P,'t)}. This can be abbreviated as \kbd{g = ffgen(3\pow2, 't)}, where the defining polynomial $P$ can be later recovered as \kbd{g.mod}. pari-2.17.2/src/functions/number_theoretical/znconreyconductor0000644000175000017500000000317014676526175023375 0ustar billbillFunction: znconreyconductor Section: number_theoretical C-Name: znconreyconductor Prototype: GGD& Help: znconreyconductor(G,chi,{&chi0}): let G be znstar(q,1) and chi be a Dirichlet character on (Z/qZ)* given by its Conrey logarithm. Return the conductor of chi, and set chi0 to (the Conrey logarithm of) the attached primitive character. If chi0 != chi, return the conductor and its factorization. Doc: Let \var{G} be attached to $(\Z/q\Z)^{*}$ (as per \kbd{G = znstar(q, 1)}) and \kbd{chi} be a Dirichlet character on $(\Z/q\Z)^{*}$, given by \item a \typ{VEC}: a standard character on \kbd{bid.gen}, \item a \typ{INT} or a \typ{COL}: a Conrey index in $(\Z/q\Z)^{*}$ or its Conrey logarithm; see \secref{se:dirichletchar} or \kbd{??character}. Return the conductor of \kbd{chi}, as the \typ{INT} \kbd{bid.mod} if \kbd{chi} is primitive, and as a pair \kbd{[N, faN]} (with \kbd{faN} the factorization of $N$) otherwise. If \kbd{chi0} is present, set it to the Conrey logarithm of the attached primitive character. \bprog ? G = znstar(126000, 1); ? znconreyconductor(G,11) \\ primitive %2 = 126000 ? znconreyconductor(G,1) \\ trivial character, not primitive! %3 = [1, matrix(0,2)] ? N0 = znconreyconductor(G,1009, &chi0) \\ character mod 5^3 %4 = [125, Mat([5, 3])] ? chi0 %5 = [14]~ ? G0 = znstar(N0, 1); \\ format [N,factor(N)] accepted ? znconreyexp(G0, chi0) %7 = 9 ? znconreyconductor(G0, chi0) \\ now primitive, as expected %8 = 125 @eprog\noindent The group \kbd{G0} is not computed as part of \kbd{znconreyconductor} because it needs to be computed only once per conductor, not once per character. pari-2.17.2/src/functions/number_theoretical/quadpoly0000644000175000017500000000116614567450071021434 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. \bprog ? quadpoly(5,'y) %1 = y^2 - y - 1 ? quadpoly(0,'y) *** at top-level: quadpoly(0,'y) *** ^-------------- *** quadpoly: domain error in quadpoly: issquare(disc) = 1 @eprog pari-2.17.2/src/functions/number_theoretical/coredisc0000644000175000017500000000215214676526175021377 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 nonzero, 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 nonzero integer $n$, this routine returns the (unique) fundamental discriminant $d$ such that $n=df^{2}$, $f$ a positive rational number. If $\fl$ is nonzero, 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.17.2/src/functions/number_theoretical/znprimroot0000644000175000017500000000131114676526175022023 0ustar billbillFunction: znprimroot Section: number_theoretical C-Name: znprimroot Prototype: G Help: znprimroot(n): returns a primitive root of n when it exists. Doc: returns a primitive root (generator) of $(\Z/n\Z)^{*}$, whenever this latter group is cyclic ($n = 4$ or $n = 2p^{k}$ or $n = p^{k}$, where $p$ is an odd prime and $k \geq 0$). If the group is not cyclic, the function will raise an exception. If $n$ is a prime power, then the smallest positive primitive root is returned. This may not be true for $n = 2p^{k}$, $p$ odd. Note that this function requires factoring $p-1$ for $p$ as above, in order to determine the exact order of elements in $(\Z/n\Z)^{*}$: this is likely to be costly if $p$ is large. pari-2.17.2/src/functions/number_theoretical/znchartokronecker0000644000175000017500000000236114676526175023342 0ustar billbillFunction: znchartokronecker Section: number_theoretical C-Name: znchartokronecker Prototype: GGD0,L, Help: znchartokronecker(G,chi,{flag=0}): let G be znstar(N,1), let chi be a Dirichlet character mod N, return the discriminant D if chi is real equal to the Kronecker symbol (D/.) and 0 otherwise. If flag is set, return the fundamental discriminant attached to the corresponding primitive character. Doc: Let $G$ be attached to $(\Z/N\Z)^{*}$ (as per \kbd{G = znstar(N,1)}) and let \kbd{chi} be a Dirichlet character on $(\Z/N\Z)^{*}$, given by \item a \typ{VEC}: a standard character on \kbd{bid.gen}, \item a \typ{INT} or a \typ{COL}: a Conrey index in $(\Z/q\Z)^{*}$ or its Conrey logarithm; see \secref{se:dirichletchar} or \kbd{??character}. If $\fl = 0$, return the discriminant $D$ if \kbd{chi} is real equal to the Kronecker symbol $(D/.)$ and $0$ otherwise. The discriminant $D$ is fundamental if and only if \kbd{chi} is primitive. If $\fl = 1$, return the fundamental discriminant attached to the corresponding primitive character. \bprog ? G = znstar(8,1); CHARS = [1,3,5,7]; \\ Conrey labels ? apply(t->znchartokronecker(G,t), CHARS) %2 = [4, -8, 8, -4] ? apply(t->znchartokronecker(G,t,1), CHARS) %3 = [1, -8, 8, -4] @eprog pari-2.17.2/src/functions/number_theoretical/charconj0000644000175000017500000000306614676526175021400 0ustar billbillFunction: charconj Section: number_theoretical C-Name: charconj0 Prototype: GG Help: charconj(cyc,chi): given a finite abelian group (by its elementary divisors cyc) and a character chi, return the conjugate character. Doc: let \var{cyc} represent a finite abelian group by its elementary divisors, i.e. $(d_{j})$ represents $\sum_{j \leq k} \Z/d_{j}\Z$ with $d_{k} \mid \dots \mid d_{1}$; any object which has a \kbd{.cyc} method is also allowed, e.g.~the output of \kbd{znstar} or \kbd{bnrinit}. A character on this group is given by a row vector $\chi = [a_{1},\ldots,a_{n}]$ such that $\chi(\prod g_{j}^{n_{j}}) = \exp(2\pi i\sum_{j} a_{j} n_{j} / d_{j})$, where $g_{j}$ denotes the generator (of order $d_{j}$) of the $j$-th cyclic component. This function returns the conjugate character. \bprog ? cyc = [15,5]; chi = [1,1]; ? charconj(cyc, chi) %2 = [14, 4] ? bnf = bnfinit(x^2+23); ? bnf.cyc %4 = [3] ? charconj(bnf, [1]) %5 = [2] @eprog\noindent For Dirichlet characters (when \kbd{cyc} is \kbd{znstar(q,1)}), characters in Conrey representation are available, see \secref{se:dirichletchar} or \kbd{??character}: \bprog ? G = znstar(16, 1); \\ (Z/16Z)^* ? charconj(G, 3) \\ Conrey label %2 = [1, 1]~ ? znconreyexp(G, %) %3 = 11 \\ attached Conrey label; indeed 11 = 3^(-1) mod 16 ? chi = znconreylog(G, 3); ? charconj(G, chi) \\ Conrey logarithm %5 = [1, 1]~ @eprog Variant: Also available is \fun{GEN}{charconj}{GEN cyc, GEN chi}, when \kbd{cyc} is known to be a vector of elementary divisors and \kbd{chi} a compatible character (no checks). pari-2.17.2/src/functions/number_theoretical/ispowerful0000644000175000017500000000074414567450071021776 0ustar billbillFunction: ispowerful Section: number_theoretical C-Name: ispowerful Prototype: lG Help: ispowerful(x): true(1) if x is a powerful integer (valuation at all primes dividing x is greater than 1), false(0) if not. Doc: true (1) if $x$ is a powerful integer, false (0) if not; an integer is powerful if and only if its valuation at all primes dividing $x$ is greater than 1. \bprog ? ispowerful(50) %1 = 0 ? ispowerful(100) %2 = 1 ? ispowerful(5^3*(10^1000+1)^2) %3 = 1 @eprog pari-2.17.2/src/functions/number_theoretical/chareval0000644000175000017500000000634414676526175021400 0ustar billbillFunction: chareval Section: number_theoretical C-Name: chareval Prototype: GGGDG Help: chareval(G,chi,x,{z}): given an abelian group structure affording a discrete logarithm method, e.g. G = znstar(N,1) or a bnr structure, let x be an element of G and let chi be a character of G. This function returns the value of chi at x, where the encoding depends on the optional argument z; if z is omitted, we fix a canonical o-th root of 1, zeta_o, where o is the character order and return the rational number c/o where chi(x) = (zeta_o)^c. Doc: Let $G$ be an abelian group structure affording a discrete logarithm method, e.g $G = \kbd{znstar}(N, 1)$ for $(\Z/N\Z)^{*}$ or a \kbd{bnr} structure, let $x$ be an element of $G$ and let \var{chi} be a character of $G$ (see the note below for details). This function returns the value of \var{chi} at~$x$. \misctitle{Note on characters} Let $K$ be some field. If $G$ is an abelian group, let $\chi: G \to K^{*}$ be a character of finite order and let $o$ be a multiple of the character order such that $\chi(n) = \zeta^{c(n)}$ for some fixed $\zeta\in K^{*}$ of multiplicative order $o$ and a unique morphism $c: G \to (\Z/o\Z,+)$. Our usual convention is to write $$G = (\Z/o_{1}\Z) g_{1} \oplus \cdots \oplus (\Z/o_{d}\Z) g_{d}$$ for some generators $(g_{i})$ of respective order $d_{i}$, where the group has exponent $o := \text{lcm}_{i} o_{i}$. Since $\zeta^{o} = 1$, the vector $(c_{i})$ in $\prod_{i} (\Z/o_{i}\Z)$ defines a character $\chi$ on $G$ via $\chi(g_{i}) = \zeta^{c_{i} (o/o_{i})}$ for all $i$. Classical Dirichlet characters have values in $K = \C$ and we can take $\zeta = \exp(2i\pi/o)$. \misctitle{Note on Dirichlet characters} In the special case where \var{bid} is attached to $G = (\Z/q\Z)^{*}$ (as per \kbd{G = znstar(q,1)}), the Dirichlet character \var{chi} can be written in one of the usual 3 formats: a \typ{VEC} in terms of \kbd{bid.gen} as above, a \typ{COL} in terms of the Conrey generators, or a \typ{INT} (Conrey label); see \secref{se:dirichletchar} or \kbd{??character}. The character value is encoded as follows, depending on the optional argument $z$: \item If $z$ is omitted: return the rational number $c(x)/o$ for $x$ coprime to $q$, where we normalize $0\leq c(x) < o$. If $x$ can not be mapped to the group (e.g. $x$ is not coprime to the conductor of a Dirichlet or Hecke character) we return the sentinel value $-1$. \item If $z$ is an integer $o$, then we assume that $o$ is a multiple of the character order and we return the integer $c(x)$ when $x$ belongs to the group, and the sentinel value $-1$ otherwise. \item $z$ can be of the form $[\var{zeta}, o]$, where \var{zeta} is an $o$-th root of $1$ and $o$ is a multiple of the character order. We return $\zeta^{c(x)}$ if $x$ belongs to the group, and the sentinel value $0$ otherwise. (Note that this coincides with the usual extension of Dirichlet characters to $\Z$, or of Hecke characters to general ideals.) \item Finally, $z$ can be of the form $[\var{vzeta}, o]$, where \var{vzeta} is a vector of powers $\zeta^{0}, \dots, \zeta^{o-1}$ of some $o$-th root of $1$ and $o$ is a multiple of the character order. As above, we return $\zeta^{c(x)}$ after a table lookup. Or the sentinel value $0$. pari-2.17.2/src/functions/number_theoretical/ffgen0000644000175000017500000000432114676526175020671 0ustar billbillFunction: ffgen Section: number_theoretical C-Name: ffgen Prototype: GDn Help: ffgen(k,{v = 'x}): return a generator of the finite field k (not necessarily a generator of its multiplicative group) as a t_FFELT. k can be given by its order q, the pair [p,f] with q=p^f, by an irreducible polynomial with t_INTMOD coefficients, or by a finite field element. If v is given, the variable name is used to display g, else the variable of the polynomial or finite field element, or x if only the order was given. Doc: return a generator for the finite field $k$ as a \typ{FFELT}. The field $k$ can be given by \item its order $q$ \item the pair $[p,f]$ where $q=p^{f}$ \item a monic irreducible polynomial with \typ{INTMOD} coefficients modulo a prime. \item a \typ{FFELT} belonging to $k$. If \kbd{v} is given, the variable name is used to display $g$, else the variable of the polynomial or the \typ{FFELT} is used, else $x$ is used. For efficiency, the characteristic is not checked to be prime; similarly if a polynomial is given, we do not check whether it is irreducible. When only the order is specified, the function uses the polynomial generated by \kbd{ffinit} and is deterministic: two calls to the function with the same parameters will always give the same generator. To obtain a multiplicative generator, call \kbd{ffprimroot} on the result (which is randomized). Its minimal polynomial then gives a \emph{primitive} polynomial, which can be used to redefine the finite field so that all subsequent computations use the new primitive polynomial: \bprog ? g = ffgen(16, 't); ? g.mod \\ recover the underlying polynomial. %2 = t^4 + t^3 + t^2 + t + 1 ? g.pol \\ lift g as a t_POL %3 = t ? g.p \\ recover the characteristic %4 = 2 ? fforder(g) \\ g is not a multiplicative generator %5 = 5 ? a = ffprimroot(g) \\ recover a multiplicative generator %6 = t^3 + t^2 + t ? fforder(a) %7 = 15 ? T = minpoly(a) \\ primitive polynomial %8 = Mod(1, 2)*x^4 + Mod(1, 2)*x^3 + Mod(1, 2) ? G = ffgen(T); \\ is now a multiplicative generator ? fforder(G) %10 = 15 @eprog Variant: To create a generator for a prime finite field, the function \fun{GEN}{p_to_GEN}{GEN p, long v} returns \kbd{ffgen(p,v)\^{}0}. pari-2.17.2/src/functions/number_theoretical/qfbcompraw0000644000175000017500000000130514676526175021744 0ustar billbillFunction: qfbcompraw Section: number_theoretical C-Name: qfbcompraw Prototype: GG Help: qfbcompraw(x,y): Gaussian composition without reduction of the binary quadratic forms x and y. Doc: \idx{composition} of the binary quadratic forms $x$ and $y$, without \idx{reduction} of the result. This is useful e.g.~to compute a generating element of an ideal. The result is undefined if $x$ and $y$ do not have the same discriminant. \bprog ? x=Qfb(2,3,-10);y=Qfb(5,3,-4); ? qfbcompraw(x,y) %2 = Qfb(10, 3, -2) ? x=Qfb(2,3,-10);y=Qfb(1,-1,1); ? qfbcompraw(x,y) *** at top-level: qfbcompraw(x,y) *** ^--------------- *** qfbcompraw: inconsistent qfbcompraw t_QFB , t_QFB. @eprog pari-2.17.2/src/functions/number_theoretical/znchartoprimitive0000644000175000017500000000212714676526175023367 0ustar billbillFunction: znchartoprimitive Section: number_theoretical C-Name: znchartoprimitive Prototype: GG Help: znchartoprimitive(G,chi): let G be znstar(q,1) and chi be a Dirichlet character on (Z/qZ)* of conductor q0. Return [G0,chi0], where chi0 is the primitive character attached to chi and G0 is znstar(q0). Doc: Let \var{G} be attached to $(\Z/q\Z)^{*}$ (as per \kbd{G = znstar(q, 1)}) and \kbd{chi} be a Dirichlet character on $(\Z/q\Z)^{*}$, of conductor $q_{0} \mid q$. \bprog ? G = znstar(126000, 1); ? [G0,chi0] = znchartoprimitive(G,11) ? G0.mod %3 = 126000 ? chi0 %4 = 11 ? [G0,chi0] = znchartoprimitive(G,1);\\ trivial character, not primitive! ? G0.mod %6 = 1 ? chi0 %7 = []~ ? [G0,chi0] = znchartoprimitive(G,1009) ? G0.mod %4 = 125 ? chi0 %5 = [14]~ @eprog\noindent Note that \kbd{znconreyconductor} is more efficient since it can return $\chi_{0}$ and its conductor $q_{0}$ without needing to initialize $G_{0}$. The price to pay is a more cryptic format and the need to initalize $G_{0}$ later, but that needs to be done only once for all characters with conductor $q_{0}$. pari-2.17.2/src/functions/number_theoretical/qfbhclassno0000644000175000017500000000077614676526175022121 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$, when $x$ is nonnegative and congruent to 0 or 3 modulo 4, and $0$ for other values. For $x > 5\cdot 10^{5}$, we assume the GRH, and use \kbd{quadclassunit} with default parameters. \bprog ? qfbhclassno(1) \\ not 0 or 3 mod 4 %1 = 0 ? qfbhclassno(3) %2 = 1/3 ? qfbhclassno(4) %3 = 1/2 ? qfbhclassno(23) %4 = 3 @eprog pari-2.17.2/src/functions/number_theoretical/isfundamental0000644000175000017500000000135714567450071022432 0ustar billbillFunction: isfundamental Section: number_theoretical C-Name: isfundamental Prototype: lG Help: isfundamental(D): true(1) if D is a fundamental discriminant (including 1), false(0) if not. Description: (int):bool Z_isfundamental($1) (gen):bool isfundamental($1) Doc: true (1) if $D$ is equal to 1 or to the discriminant of a quadratic field, false (0) otherwise. $D$ can be input in factored form as for arithmetic functions: \bprog ? isfundamental(factor(-8)) %1 = 1 \\ count fundamental discriminants up to 10^8 ? c = 0; forfactored(d = 1, 10^8, if (isfundamental(d), c++)); c time = 40,840 ms. %2 = 30396325 ? c = 0; for(d = 1, 10^8, if (isfundamental(d), c++)); c time = 1min, 33,593 ms. \\ slower ! %3 = 30396325 @eprog pari-2.17.2/src/functions/number_theoretical/quadclassunit0000644000175000017500000000635014676526175022470 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$. By default, the results are conditional on the GRH. This function should be used instead of \tet{qfbclassno} or \tet{quadregulator} 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). \item \kbd{$v$.normfu} (for positive $D$ only) return the norm of the fundamental unit, either $1$ or $-1$. Note that a result of $-1$ is unconditional and no longer depends on the GRH. 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 nonnegative real numbers which control the execution time and the stack size, see \ref{se:GRHbnf}. The parameter is used as a threshold to balance the relation finding phase against the final linear algebra. Increasing the default $c_{1}$ means that relations are easier to find, but more relations are needed and the linear algebra will be harder. The default value for $c_{1}$ is $0$ and means that it is taken equal to $c_{2}$. The parameter $c_{2}$ is mostly obsolete and should not be changed, but we still document it for completeness: we compute a tentative class group by generators and relations using a factorbase of prime ideals $\leq c_{1} (\log |D|)^{2}$, then prove that ideals of norm $\leq c_{2} (\log |D|)^{2}$ do not generate a larger group. By default an optimal $c_{2}$ is chosen, so that the result is provably correct under the GRH --- a result of Greni\'e and Molteni states that $c_{2} = 23/6 \approx 3.83$ is fine (and even $c_{2} = 15/4 \approx 3.75$ for large $|D| > 2.41 E8$). 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 will be more convenient to use \fun{GEN}{Buchquad}{GEN D, double c1, double c2, long prec}. pari-2.17.2/src/functions/number_theoretical/quadunitnorm0000644000175000017500000000526014676526175022335 0ustar billbillFunction: quadunitnorm Section: number_theoretical C-Name: quadunitnorm Prototype: lG Help: quadunitnorm(D): returns the norm of the fundamental unit of the quadratic order of discriminant D. Doc: returns the norm ($1$ or $-1$) of the fundamental unit of the quadratic order of discriminant $D$. The integer $D$ must be congruent to $0$ or $1$ modulo $4$ and not a square. This is of course equal to \kbd{norm(quadunit(D))} but faster. \bprog ? quadunitnorm(-3) \\ the result is always 1 in the imaginary case %1 = 1 ? quadunitnorm(5) %2 = -1 ? quadunitnorm(17345) %3 = -1 ? u = quadunit(17345) %4 = 299685042291 + 4585831442*w ? norm(u) %5 = -1 @eprog\noindent This function computes the parity of the continued fraction expansion and runs in time $\tilde{O}(D^{1/2})$. If $D$ is fundamental, the function \kbd{bnfinit} is asymptotically faster but depends of the GRH. If $D = df^{2}$ is not fundamental, it will usually be faster to first compute \kbd{quadunitindex}$(d, f)$. If it is even, the result is $1$, else the result is \kbd{quadunitnorm}$(d)$. The narrow class number of the order of discriminant $D$ is equal to the class number if the unit norm is $1$ and to twice the class number otherwise. \misctitle{Important remark} Assuming GRH, using \kbd{bnfinit} is \emph{much} faster, running in time subexponential in $\log D$ (instead of exponential for \kbd{quadunitnorm}). We give examples for the maximal order: \bprog ? GRHunitnorm(bnf) = vecprod(bnfsignunit(bnf)[,1]) ? bnf = bnfinit(x^2 - 17345, 1); GRHunitnorm(bnf) %2 = -1 ? bnf = bnfinit(x^2 - nextprime(2^60), 1); GRHunitnorm(bnf) time = 119 ms. %3 = -1 ? quadunitnorm(nextprime(2^60)) time = 24,086 ms. %4 = -1 @eprog\noindent Note that if the result is $-1$, it is unconditional because (if GRH is false) it could happen that our tentative fundamental unit in \var{bnf} is actually a power $u^{k}$ of the true fundamental unit, but we would still have $\text{Norm}(u) = -1$ (and $k$ odd). We can also remove the GRH assumption when the result is $1$ with a little more work: \bprog ? v = bnfunits(bnf)[1][1] \\ a unit in factored form ? v[,2] %= 2; ? nfeltissquare(bnf, nffactorback(bnf, v)) %7 = 0 @eprog\noindent Under GRH, we know that $v$ is the fundamental unit, but as above it can be a power $u^{k}$ of the true fundamental unit $u$. But the final two lines prove that $v$ is not a square, hence $k$ is odd and $\text{Norm}(u)$ must also be $1$. We modified the factorization matrix giving $v$ by reducing all exponents modulo $2$: this allows to computed \kbd{nffactorback} even when the factorization involves huge exponents. And of course the new $v$ is a square if and only if the original one was. pari-2.17.2/src/functions/number_theoretical/fforder0000644000175000017500000000153414557721031021220 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.17.2/src/functions/number_theoretical/zncoppersmith0000644000175000017500000000641614676526175022520 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. The parameter X should be smaller than exp((log B)^2 / (deg(P) log N)) and the leading coefficient of P should be coprime to N. Doc: \idx{Coppersmith}'s algorithm. $N$ being an integer and $P\in \Z[t]$, finds in polynomial time in $\log(N)$ and $d = \text{deg}(P)$ all integers $x$ with $|x| \leq X$ such that $$\gcd(N, P(x)) \geq B.$$ This is a famous application of the \idx{LLL} algorithm meant to help in the factorization of $N$. Notice that $P$ may be reduced modulo $N\Z[t]$ without affecting the situation. The parameter $X$ must not be too large: assume for now that the leading coefficient of $P$ is coprime to $N$, then we must have $$d \log X \log N < \log^{2} B,$$ i.e., $X < N^{1/d}$ when $B = N$. Let now $P_{0}$ be the gcd of the leading coefficient of $P$ and $N$. In applications to factorization, we should have $P_{0} = 1$; otherwise, either $P_{0} = N$ and we can reduce the degree of $P$, or $P_{0}$ is a non trivial factor of $N$. For completeness, we nevertheless document the exact conditions that $X$ must satisfy in this case: let $p := \log_{N} P_{0}$, $b := \log_{N} B$, $x := \log_{N} X$, then \item either $p \geq d / (2d-1)$ is large and we must have $x d < 2b - 1$; \item or $p < d / (2d-1)$ and we must have both $p < b < 1 - p + p/d$ and $x(d + p(1-2d)) < (b - p)^{2}$. Note that this reduces to $x d < b^{2}$ when $p = 0$, i.e., the condition described above. Some $x$ larger than $X$ may be returned if you are very lucky. The routine runs in polynomial time in $\log N$ and $d$ but the smaller $B$, or the larger $X$, the slower. 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 nontrivial factors of $N$, given some partial information on the factors; in that case $B$ must obviously be smaller than the largest nontrivial divisor of $N$. \bprog setrand(1); \\ to make the example reproducible [a,b] = [10^30, 10^31]; D = 20; p = randomprime([a,b]); q = randomprime([a,b]); N = p*q; \\ assume we know 0) p | N; 1) p in [a,b]; 2) the last D digits of p p0 = p % 10^D; ? L = zncoppersmith(10^D*x + p0, N, b \ 10^D, a) time = 1ms. %6 = [738281386540] ? gcd(L[1] * 10^D + p0, N) == p %7 = 1 @eprog\noindent and we recovered $p$, faster than by trying all possibilities $ x < 10^{11}$. The second application is an attack on RSA with low exponent, when the message $x$ is short and the padding $P$ is known to the attacker. We use the same RSA modulus $N$ as in the first example: \bprog setrand(1); P = random(N); \\ known padding e = 3; \\ small public encryption exponent X = floor(N^0.3); \\ N^(1/e - epsilon) x0 = random(X); \\ unknown short message C = lift( (Mod(x0,N) + P)^e ); \\ known ciphertext, with padding P zncoppersmith((P + x)^3 - C, N, X) \\ result in 244ms. %14 = [2679982004001230401] ? %[1] == x0 %15 = 1 @eprog\noindent We guessed an integer of the order of $10^{18}$, almost instantly. pari-2.17.2/src/functions/number_theoretical/qfbnupow0000644000175000017500000000105714567450071021436 0ustar billbillFunction: qfbnupow Section: number_theoretical C-Name: nupow Prototype: GGDG Help: qfbnupow(x,n,{L}): 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; if set, $L$ should be equal to \kbd{sqrtnint(abs(D)>>2,4)}, where $D < 0$ is the discriminant of $x$. The current implementation is slower than the generic routine for small discriminant $D$, and becomes faster for $D \approx 2^{45}$. pari-2.17.2/src/functions/number_theoretical/ramanujantau0000644000175000017500000000351514676526175022276 0ustar billbillFunction: ramanujantau Section: number_theoretical C-Name: ramanujantau Prototype: GD12,L, Help: ramanujantau(n,{ell=12}): compute the value of Ramanujan's tau function at n, assuming the GRH. If ell is 16, 18, 20, 22, or 26, same for the newform of level 1 and corresponding weight. Otherwise, compute the coefficient of the trace form at n. Algorithm in O(n^{1/2+eps}). Doc: compute the value of Ramanujan's tau function at an individual $n$, assuming the truth of the GRH (to compute quickly class numbers of imaginary quadratic fields using \tet{quadclassunit}). If \kbd{ell} is 16, 18, 20, 22, or 26, same for the newform of level 1 and corresponding weight. Otherwise, compute the coefficient of the trace form at $n$. The complexity is in $\tilde{O}(n^{1/2})$ using $O(\log n)$ space. If all values up to $N$ are required, then $$\sum \tau(n)q^{n} = q \prod_{n\geq 1} (1-q^{n})^{24}$$ and more generally, setting $u = \ell - 13$ and $C = 2/\zeta(-u)$ for $\ell > 12$, $$\sum\tau_{\ell}(n)q^{n} = q \prod_{n\geq 1} (1-q^{n})^{24} \Big( 1 + C\sum_{n\ge1}n^{u} q^{n} / (1-q^{n})\Big)$$ produces them in time $\tilde{O}(N)$, against $\tilde{O}(N^{3/2})$ for individual calls to \kbd{ramanujantau}; of course the space complexity then becomes $\tilde{O}(N)$. For other values of $\ell$, \kbd{mfcoefs(mftraceform([1,ell]),N)} is much faster. \bprog ? tauvec(N) = Vec(q*eta(q + O(q^N))^24); ? N = 10^4; v = tauvec(N); time = 26 ms. ? ramanujantau(N) %3 = -482606811957501440000 ? w = vector(N, n, ramanujantau(n)); \\ much slower ! time = 13,190 ms. ? v == w %4 = 1 @eprog Function: _ramanujantau_worker C-Name: ramanujantau_worker Prototype: GGGG Section: programming/internals Help: worker for ramanujantau Function: _taugen_n_worker C-Name: taugen_n_worker Prototype: GGG Section: programming/internals Help: worker for ramanujantau pari-2.17.2/src/functions/number_theoretical/primecert0000644000175000017500000001266114676526175021604 0ustar billbillFunction: primecert Section: number_theoretical C-Name: primecert0 Prototype: GD0,L,D0,L, Help: primecert(N,{flag=0},{partial=0}): If N is a prime, return a Primality Certificate. Return 0 otherwise. If flag = 0 return an ECPP certificate (Atkin-Morain); if flag = 1 return an N-1 certificate (Pocklington-Lehmer) Doc: If N is a prime, return a PARI Primality Certificate for the prime $N$, as described below. Otherwise, return 0. A Primality Certificate $c$ can be checked using \tet{primecertisvalid}$(c)$. If $\fl = 0$ (default), return an ECPP certificate (Atkin-Morain) If $\fl = 0$ and $\var{partial}>0$, return a (potentially) partial ECPP certificate. A PARI ECPP Primality Certificate for the prime $N$ is either a prime integer $N < 2^{64}$ or a vector \kbd{C} of length $\ell$ whose $i$th component \kbd{C[i]} is a vector $[N_{i}, t_{i}, s_{i}, a_{i}, P_{i}]$ of length $5$ where $N_{1} = N$. It is said to be \emph{valid} if for each $i = 1, \ldots, \ell$, all of the following conditions are satisfied \item $N_{i}$ is a positive integer \item $t_{i}$ is an integer such that $t_{i}^{2} < 4N_{i}$ \item $s_{i}$ is a positive integer which divides $m_{i}$ where $m_{i} = N_{i} + 1 - t_{i}$ \item If we set $q_{i} = \dfrac{m_{i}}{s_{i}}$, then \quad\item $q_{i} > (N_{i}^{1/4}+1)^{2}$ \quad\item $q_{i} = N_{i+1}$ if $1 \leq i < l$ \quad\item $q_{\ell} \leq 2^{64}$ is prime \item $a_{i}$ is an integer \quad\item \kbd{P[i]} is a vector of length $2$ representing the affine point $P_{i} = (x_{i}, y_{i})$ on the elliptic curve $E: y^{2} = x^{3} + a_{i}x + b_{i}$ modulo $N_{i}$ where $b_{i} = y_{i}^{2} - x_{i}^{3} - a_{i}x_{i}$ satisfying the following: \quad\item $m_{i} P_{i} = \infty$ \quad\item $s_{i} P_{i} \neq \infty$ Using the following theorem, the data in the vector \kbd{C} allows to recursively certify the primality of $N$ (and all the $q_{i}$) under the single assumption that $q_{\ell}$ be prime. \misctitle{Theorem} If $N$ is an integer and there exist positive integers $m, q$ and a point $P$ on the elliptic curve $E: y^{2} = x^{3} + ax + b$ defined modulo $N$ such that $q > (N^{1/4} + 1)^{2}$, $q$ is a prime divisor of $m$, $mP = \infty$ and $\dfrac{m}{q}P \neq \infty$, then $N$ is prime. A partial certificate is identical except that the condition $q_{\ell} \leq 2^{64}$ is replaced by $q_{\ell} \leq 2^{partial}$. Such partial certificate $C$ can be extended to a full certificate by calling $C=primecert(C)$, or to a longer partial certificate by calling $C=primecert(C,,b)$ with $b 2^{64}$ satisfying the following properties: \item $p_{i}$ is a prime divisor of $N - 1$; \item $a_{i}$ is an integer such that $a_{i}^{N-1} \equiv 1 \pmod{N}$ and $a_{i}^{(N-1)/p_{i}} - 1$ is coprime with $N$; \item $C_{i}$ is an $N-1$ Primality Certificate for $p_{i}$ \item The product $F$ of the $p_{i}^{v_{p_{i}}(N-1)}$ is strictly larger than $N^{1/3}$. Provided that all $p_{i}$ are indeed primes, this implies that any divisor of $N$ is congruent to $1$ modulo $F$. \item The Brillhart--Lehmer--Selfridge criterion is satisfied: when we write $N = 1 + c_{1} F + c_{2} F^{2}$ in base $F$ the polynomial $1 + c_{1} X + c_{2} X^{2}$ is irreducible over $\Z$, i.e. $c_{1}^{2} - 4c_{2}$ is not a square. This implies that $N$ is prime. This algorithm requires factoring partially $p-1$ for various prime integers $p$ with an unfactored parted $\leq p^{2/3}$ and this may be exceedingly slow compared to the default. 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 the algorithm at a high enough debug level, you may see warnings about untested integers being declared primes. This is normal: we ask for partial factorizations (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 Primality Certificate. Variant: Also available is \fun{GEN}{ecpp0}{GEN N, long partial} ($\fl = 0$). pari-2.17.2/src/functions/number_theoretical/ffextend0000644000175000017500000000216414676526175021412 0ustar billbillFunction: ffextend Section: number_theoretical C-Name: ffextend Prototype: GGDn Help: ffextend(a,P,{v}): extend the field K of definition of a by a root of the polynomial P, assumed to be irreducible over K. Return [r, m] where r is a root of P in the extension field L and m is a map from K to L, see \kbd{ffmap}. If v is given, the variable name is used to display the generator of L, else the name of the variable of P is used. Doc: extend the field $K$ of definition of $a$ by a root of the polynomial $P\in K[X]$ assumed to be irreducible over $K$. Return $[r, m]$ where $r$ is a root of $P$ in the extension field $L$ and $m$ is a map from $K$ to $L$, see \kbd{ffmap}. If $v$ is given, the variable name is used to display the generator of $L$, else the name of the variable of $P$ is used. A generator of $L$ can be recovered using $b=ffgen(r)$. The image of $P$ in $L[X]$ can be recovered using $PL=ffmap(m,P)$. \bprog ? a = ffgen([3,5],'a); ? P = x^2-a; polisirreducible(P) %2 = 1 ? [r,m] = ffextend(a, P, 'b); ? r %3 = b^9+2*b^8+b^7+2*b^6+b^4+1 ? subst(ffmap(m, P), x, r) %4 = 0 ? ffgen(r) %5 = b @eprog pari-2.17.2/src/functions/number_theoretical/isprime0000644000175000017500000000464114567450071021247 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. If flag is 3, use ECPP. Description: (int, ?0):bool isprime($1) (gen, ?small):gen gisprime($1, $2) Doc: true (1) if $x$ is a prime number, false (0) otherwise. A prime number is a positive integer having exactly two distinct divisors among the natural numbers, namely 1 and itself. This routine proves or disproves rigorously that a number is prime, which can be very slow when $x$ is indeed a large prime integer. For instance a $1000$ digits prime should require 15 to 30 minutes with default algorithms. Use \tet{ispseudoprime} to quickly check for compositeness. Use \tet{primecert} in order to obtain a primality proof instead of a yes/no answer; see also \kbd{factor}. The function accepts vector/matrices arguments, and is then applied componentwise. If $\fl=0$, use a combination of \item Baillie-Pomerance-Selfridge-Wagstaff compositeness test (see \tet{ispseudoprime}), \item Selfridge ``$p-1$'' test if $x-1$ is smooth enough, \item Adleman-Pomerance-Rumely-Cohen-Lenstra (APRCL) for general medium-sized $x$ (less than 1500 bits), \item Atkin-Morain's Elliptic Curve Primality Prover (ECPP) for general large $x$. If $\fl=1$, use Selfridge-Pocklington-Lehmer ``$p-1$'' test; this requires partially factoring various auxilliary integers and is likely to be very slow. If $\fl=2$, use APRCL only. If $\fl=3$, use ECPP only. Function: _aprcl_step4_worker Section: programming/internals C-Name: aprcl_step4_worker Prototype: UGGG Help: worker for isprime (APRCL step 4) Function: _aprcl_step6_worker Section: programming/internals C-Name: aprcl_step6_worker Prototype: GLGGG Help: worker for isprime (APRCL step 6) Function: _ecpp_sqrt_worker Section: programming/internals C-Name: ecpp_sqrt_worker Prototype: GGG Help: worker for isprime (ECPP sqrt step) Function: _ecpp_ispsp_worker Section: programming/internals C-Name: ecpp_ispsp_worker Prototype: G Help: worker for isprime (ECPP ispseudoprime step) Function: _ecpp_step2_worker Section: programming/internals C-Name: ecpp_step2_worker Prototype: GGGL Help: worker for isprime (step 2) pari-2.17.2/src/functions/number_theoretical/ffcompomap0000644000175000017500000000130214676526175021727 0ustar billbillFunction: ffcompomap Section: number_theoretical C-Name: ffcompomap Prototype: GG Help: ffcompomap(f,g): Let k, l, m be three finite fields and f a (partial) map from l to m and g a partial map from k to l, return the (partial) map f o g from k to m. Doc: Let $k$, $l$, $m$ be three finite fields and $f$ a (partial) map from $l$ to $m$ and $g$ a (partial) map from $k$ to $l$, return the (partial) map $f \circ g$ from $k$ to $m$. \bprog a = ffgen([3,5],'a); b = ffgen([3,10],'b); c = ffgen([3,20],'c); m = ffembed(a, b); n = ffembed(b, c); rm = ffinvmap(m); rn = ffinvmap(n); nm = ffcompomap(n,m); ffmap(n,ffmap(m,a)) == ffmap(nm, a) %5 = 1 ffcompomap(rm, rn) == ffinvmap(nm) %6 = 1 @eprog pari-2.17.2/src/functions/number_theoretical/qfbpow0000644000175000017500000000040714567450071021071 0ustar billbillFunction: qfbpow Section: number_theoretical C-Name: qfbpow Prototype: GG Help: qfbpow(x,n): n-th power with reduction of the binary quadratic form x. Doc: $n$-th power of the binary quadratic form $x$, computed with \idx{reduction} (i.e.~using \kbd{qfbcomp}). pari-2.17.2/src/functions/number_theoretical/isprimepower0000644000175000017500000000073114676526175022332 0ustar billbillFunction: isprimepower Section: number_theoretical C-Name: isprimepower Prototype: lGD& Help: isprimepower(x,{&n}): if x = p^k is a prime power (p prime, k > 0), return k, else return 0. If n is present, and the function returns a nonzero result, set n to p, the k-th root of x. Doc: if $x = p^{k}$ is a prime power ($p$ prime, $k > 0$), return $k$, else return 0. If a second argument $\&n$ is given and $x$ is indeed the $k$-th power of a prime $p$, sets $n$ to $p$. pari-2.17.2/src/functions/number_theoretical/chardiv0000644000175000017500000000345314676526175021231 0ustar billbillFunction: chardiv Section: number_theoretical C-Name: chardiv0 Prototype: GGG Help: chardiv(cyc,a,b): given a finite abelian group (by its elementary divisors cyc) and two characters a and b, return the character a/b. Doc: let \var{cyc} represent a finite abelian group by its elementary divisors, i.e. $(d_{j})$ represents $\sum_{j \leq k} \Z/d_{j}\Z$ with $d_{k}. \mid \dots \mid d_{1}$; any object which has a \kbd{.cyc} method is also allowed, e.g.~the output of \kbd{znstar} or \kbd{bnrinit}. A character on this group is given by a row vector $a = [a_{1},\ldots,a_{n}]$ such that $\chi(\prod g_{j}^{n_{j}}) = \exp(2\pi i\sum_{j} a_{j} n_{j} / d_{j})$, where $g_{j}$ denotes the generator (of order $d_{j}$) of the $j$-th cyclic component. Given two characters $a$ and $b$, return the character $a / b = a \overline{b}$. \bprog ? cyc = [15,5]; a = [1,1]; b = [2,4]; ? chardiv(cyc, a,b) %2 = [14, 2] ? bnf = bnfinit(x^2+23); ? bnf.cyc %4 = [3] ? chardiv(bnf, [1], [2]) %5 = [2] @eprog\noindent For Dirichlet characters on $(\Z/N\Z)^{*}$, additional representations are available (Conrey labels, Conrey logarithm), see \secref{se:dirichletchar} or \kbd{??character}. If the two characters are in the same format, the result is given in the same format, otherwise a Conrey logarithm is used. \bprog ? G = znstar(100, 1); ? G.cyc %2 = [20, 2] ? a = [10, 1]; \\ usual representation for characters ? b = 7; \\ Conrey label; ? c = znconreylog(G, 11); \\ Conrey log ? chardiv(G, b,b) %6 = 1 \\ Conrey label ? chardiv(G, a,b) %7 = [0, 5]~ \\ Conrey log ? chardiv(G, a,c) %7 = [0, 14]~ \\ Conrey log @eprog Variant: Also available is \fun{GEN}{chardiv}{GEN cyc, GEN a, GEN b}, when \kbd{cyc} is known to be a vector of elementary divisors and $a, b$ are compatible characters (no checks). pari-2.17.2/src/functions/number_theoretical/chargalois0000644000175000017500000000254614676526175021727 0ustar billbillFunction: chargalois Section: number_theoretical C-Name: chargalois Prototype: GDG Help: chargalois(cyc,{ORD}): let cyc represent a finite abelian group G by its elementary divisors cyc, return a list of representatives for the Galois orbits of characters of G. If ORD is present, select characters depending on their orders: if ORD is a t_INT, restrict to orders less than this bound; if ORD is a t_VEC or t_VECSMALL, restrict to orders in the list. Doc: Let \var{cyc} represent a finite abelian group by its elementary divisors (any object which has a \kbd{.cyc} method is also allowed, i.e. the output of \kbd{znstar} or \kbd{bnrinit}). Return a list of representatives for the Galois orbits of complex characters of $G$. If \kbd{ORD} is present, select characters depending on their orders: \item if \kbd{ORD} is a \typ{INT}, restrict to orders less than this bound; \item if \kbd{ORD} is a \typ{VEC} or \typ{VECSMALL}, restrict to orders in the list. \bprog ? G = znstar(96); ? #chargalois(G) \\ 16 orbits of characters mod 96 %2 = 16 ? #chargalois(G,4) \\ order less than 4 %3 = 12 ? chargalois(G,[1,4]) \\ order 1 or 4; 5 orbits %4 = [[0, 0, 0], [2, 0, 0], [2, 1, 0], [2, 0, 1], [2, 1, 1]] @eprog\noindent Given a character $\chi$, of order $n$ (\kbd{charorder(G,chi)}), the elements in its orbit are the $\phi(n)$ characters $\chi^{i}$, $(i,n)=1$. pari-2.17.2/src/functions/number_theoretical/sumdigits0000644000175000017500000000120614676526175021613 0ustar billbillFunction: sumdigits Section: number_theoretical C-Name: sumdigits0 Prototype: GDG Help: sumdigits(n,{B=10}): sum of digits in the integer n, when written in base B. Doc: sum of digits in the integer $n$, when written in base $B$. \bprog ? sumdigits(123456789) %1 = 45 ? sumdigits(123456789, 2) %2 = 16 ? sumdigits(123456789, -2) %3 = 15 @eprog\noindent Note that the sum of bits in $n$ is also returned by \tet{hammingweight}. This function is much faster than \kbd{vecsum(digits(n,B))} when $B$ is $10$ or a power of $2$, and only slightly faster in other cases. Variant: Also available is \fun{GEN}{sumdigits}{GEN n}, for $B = 10$. pari-2.17.2/src/functions/number_theoretical/quadunit0000644000175000017500000000274714676526175021450 0ustar billbillFunction: quadunit Section: number_theoretical C-Name: quadunit0 Prototype: GDn Help: quadunit(D,{v = 'w}): fundamental unit u of the quadratic order of discriminant D where D must be positive. If v is given, the variable name is used to display u, else 'w' is used. Doc: a fundamental unit\sidx{fundamental units} $u$ of the real quadratic order of discriminant $D$. The integer $D$ must be congruent to 0 or 1 modulo 4 and not a square; the result is a quadratic number (see \secref{se:quadgen}). If $D$ is not a fundamental discriminant, the algorithm is wasteful: if $D = df^{2}$ with $d$ fundamental, it will be faster to compute \kbd{quadunit}$(d)$ then raise it to the power \kbd{quadunitindex}$(d,f)$; or keep it in factored form. If \var{v} is given, the variable name is used to display $u$ else 'w' is used. The algorithm computes the continued fraction of $(1 + \sqrt{D}) / 2$ or $\sqrt{D}/2$ (see GTM 138, algorithm 5.7.2). Although the continued fraction length is only $O(\sqrt{D})$, the function still runs in time $\tilde{O}(D)$, in part because the output size is not polynomially bounded in terms of $\log D$. See \kbd{bnfinit} and \kbd{bnfunits} for a better alternative for large $D$, running in time subexponential in $\log D$ and returning the fundamental units in compact form (as a short list of $S$-units of size $O(\log D)^{3}$ raised to possibly large exponents). Variant: When \var{v} does not matter, the function \fun{GEN}{quadunit}{GEN D} is also available. pari-2.17.2/src/functions/number_theoretical/ffnbirred0000644000175000017500000000122314676526175021543 0ustar billbillFunction: ffnbirred Section: number_theoretical C-Name: ffnbirred0 Prototype: GLD0,L, Help: ffnbirred(q,n,{flag=0}): number of monic irreducible polynomials over F_q, of degree n (flag=0, default) or at most n (flag=1). Description: (int, small, ?0):int ffnbirred($1, $2) (int, small, 1):int ffsumnbirred($1, $2) (int, small, ?small):int ffnbirred0($1, $2, $3) Doc: computes the number of monic irreducible polynomials over $\F_{q}$ of degree exactly $n$ ($\fl=0$ or omitted) or at most $n$ ($\fl=1$). Variant: Also available are \fun{GEN}{ffnbirred}{GEN q, long n} (for $\fl=0$) and \fun{GEN}{ffsumnbirred}{GEN q, long n} (for $\fl=1$). pari-2.17.2/src/functions/number_theoretical/charorder0000644000175000017500000000262614676526175021563 0ustar billbillFunction: charorder Section: number_theoretical C-Name: charorder0 Prototype: GG Help: charorder(cyc,chi): given a finite abelian group (by its elementary divisors cyc) and a character chi, return the order of chi. Doc: let \var{cyc} represent a finite abelian group by its elementary divisors, i.e. $(d_{j})$ represents $\sum_{j \leq k} \Z/d_{j}\Z$ with $d_{k} \mid \dots \mid d_{1}$; any object which has a \kbd{.cyc} method is also allowed, e.g.~the output of \kbd{znstar} or \kbd{bnrinit}. A character on this group is given by a row vector $\chi = [a_{1},\ldots,a_{n}]$ such that $\chi(\prod g_{j}^{n_{j}}) = \exp(2\pi i\sum_{j} a_{j} n_{j} / d_{j})$, where $g_{j}$ denotes the generator (of order $d_{j}$) of the $j$-th cyclic component. This function returns the order of the character \kbd{chi}. \bprog ? cyc = [15,5]; chi = [1,1]; ? charorder(cyc, chi) %2 = 15 ? bnf = bnfinit(x^2+23); ? bnf.cyc %4 = [3] ? charorder(bnf, [1]) %5 = 3 @eprog\noindent For Dirichlet characters (when \kbd{cyc} is \kbd{znstar(q, 1)}), characters in Conrey representation are available, see \secref{se:dirichletchar} or \kbd{??character}: \bprog ? G = znstar(100, 1); \\ (Z/100Z)^* ? charorder(G, 7) \\ Conrey label %2 = 4 @eprog Variant: Also available is \fun{GEN}{charorder}{GEN cyc, GEN chi}, when \kbd{cyc} is known to be a vector of elementary divisors and \kbd{chi} a compatible character (no checks). pari-2.17.2/src/functions/number_theoretical/direuler0000644000175000017500000000307214567450071021407 0ustar billbillFunction: direuler Section: number_theoretical C-Name: direuler0 Prototype: V=GGEDG Help: direuler(p=a,b,expr,{c}): Dirichlet Euler product of expression expr from p=a to p=b, limited to b terms. Expr should be a polynomial or rational function in p and X, and X is understood to mean p^(-s). If c is present, output only the first c terms. Wrapper: (,,G) Description: (gen,gen,closure,?gen):gen direuler(${3 cookie}, ${3 wrapper}, $1, $2, $4) Doc: computes the \idx{Dirichlet series} attached 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 omitted, output the first $b$ coefficients of the series; otherwise, output the first $c$ coefficients. The following command computes the \teb{sigma} function, attached 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] ? direuler(p=2, 10, 1/((1-X)*(1-p*X)), 5) \\ fewer terms %2 = [1, 3, 4, 7, 6] @eprog\noindent Setting $c < b$ is useless (the same effect would be achieved by setting $b = c)$. If $c > b$, the computed coefficients are ``missing'' Euler factors: \bprog ? direuler(p=2, 10, 1/((1-X)*(1-p*X)), 15) \\ more terms, no longer = sigma ! %3 = [1, 3, 4, 7, 6, 12, 8, 15, 13, 18, 0, 28, 0, 24, 24] @eprog \synt{direuler}{void *E, GEN (*eval)(void*,GEN), GEN a, GEN b} pari-2.17.2/src/functions/number_theoretical/addprimes0000644000175000017500000000213614567450071021544 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. \bprog ? addprimes(37975227936943673922808872755445627854565536638199) ? factor(15226050279225333605356183781326374297180681149613806\ 88657908494580122963258952897654000350692006139) %2 = [37975227936943673922808872755445627854565536638199 1] [40094690950920881030683735292761468389214899724061 1] ? ## *** last result computed in 0 ms. @eprog 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.17.2/src/functions/number_theoretical/bestapprnf0000644000175000017500000000303514567450071021737 0ustar billbillFunction: bestapprnf Section: linear_algebra C-Name: bestapprnf Prototype: GGDGp Help: bestapprnf(V,T,{rootT}): T being an integral polynomial and V being a scalar, vector, or matrix, return a reasonable approximation of V with polmods modulo T. The rootT argument, if present, must be an element of polroots(T), i.e. a root of T fixing a complex embedding of Q[x]/(T). Doc: $T$ being an integral polynomial and $V$ being a scalar, vector, or matrix with complex coefficients, return a reasonable approximation of $V$ with polmods modulo $T$. $T$ can also be any number field structure, in which case the minimal polynomial attached to the structure (\kbd{$T$}.pol) is used. The \var{rootT} argument, if present, must be an element of \kbd{polroots($T$)} (or \kbd{$T$}.pol), i.e.~a complex root of $T$ fixing an embedding of $\Q[x]/(T)$ into $\C$. \bprog ? bestapprnf(sqrt(5), polcyclo(5)) %1 = Mod(-2*x^3 - 2*x^2 - 1, x^4 + x^3 + x^2 + x + 1) ? bestapprnf(sqrt(5), polcyclo(5), exp(4*I*Pi/5)) %2 = Mod(2*x^3 + 2*x^2 + 1, x^4 + x^3 + x^2 + x + 1) @eprog\noindent When the output has huge rational coefficients, try to increase the working \kbd{realbitprecision}: if the answer does not stabilize, consider that the reconstruction failed. Beware that if $T$ is not Galois over $\Q$, some embeddings may not allow to reconstruct $V$: \bprog ? T = x^3-2; vT = polroots(T); z = 3*2^(1/3)+1; ? bestapprnf(z, T, vT[1]) %2 = Mod(3*x + 1, x^3 - 2) ? bestapprnf(z, T, vT[2]) %3 = 4213714286230872/186454048314072 \\ close to 3*2^(1/3) + 1 @eprog pari-2.17.2/src/functions/number_theoretical/ispseudoprime0000644000175000017500000000336714676526175022505 0ustar billbillFunction: ispseudoprime Section: number_theoretical C-Name: gispseudoprime Prototype: GD0,L, Help: ispseudoprime(x,{flag}): true(1) if x is a strong pseudoprime, false(0) if not. If flag is 0 or omitted, use BPSW test, otherwise use strong Rabin-Miller test for flag randomly chosen bases. Description: (int,?0):bool BPSW_psp($1) (int,#small):bool millerrabin($1,$2) (int,small):bool ispseudoprime($1, $2) (gen,?small):gen gispseudoprime($1, $2) Doc: true (1) if $x$ is a strong pseudo prime (see below), false (0) otherwise. If this function returns false, $x$ is not prime; if, on the other hand it returns true, it is only highly likely that $x$ is a prime number. Use \tet{isprime} (which is of course much slower) to prove that $x$ is indeed prime. The function accepts vector/matrices arguments, and is then applied componentwise. If $\fl = 0$, checks whether $x$ has no small prime divisors (up to $101$ included) and is a Baillie-Pomerance-Selfridge-Wagstaff pseudo prime. Such a pseudo prime passes a Rabin-Miller test for base $2$, followed by a Lucas test for the sequence $(P,1)$, where $P \geq 3$ is the smallest odd integer such that $P^{2} - 4$ is not a square mod $x$. (Technically, we are using an ``almost extra strong Lucas test'' that checks whether $V_{n}$ is $\pm 2$, without computing $U_{n}$.) There are no known composite numbers passing the above test, although it is expected that infinitely many such numbers exist. In particular, all composites $\leq 2^{64}$ are correctly detected (checked using \url{https://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.17.2/src/functions/number_theoretical/primecertisvalid0000644000175000017500000000174214567450071023144 0ustar billbillFunction: primecertisvalid Section: number_theoretical C-Name: primecertisvalid Prototype: lG Help: primecertisvalid(cert): Verifies if cert is a valid PARI ECPP Primality certificate. Doc: Verifies if cert is a valid PARI ECPP Primality certificate, as described in \kbd{??primecert}. \bprog ? cert = primecert(10^35 + 69) %1 = [[100000000000000000000000000000000069, 5468679110354 52074, 2963504668391148, 0, [60737979324046450274283740674 208692, 24368673584839493121227731392450025]], [3374383076 4501150277, -11610830419, 734208843, 0, [26740412374402652 72 4, 6367191119818901665]], [45959444779, 299597, 2331, 0 , [18022351516, 9326882 51]]] ? primecertisvalid(cert) %2 = 1 ? cert[1][1]++; \\ random perturbation ? primecertisvalid(cert) %4 = 0 \\ no longer valid ? primecertisvalid(primecert(6)) %5 = 0 @eprog Function: _primecertisvalid_ecpp_worker Section: programming/internals C-Name: primecertisvalid_ecpp_worker Prototype: G Help: worker for primecertisvalid pari-2.17.2/src/functions/number_theoretical/bestappr0000644000175000017500000000414514676526175021430 0ustar billbillFunction: bestappr Section: number_theoretical C-Name: bestappr Prototype: GDG Help: bestappr(x,{B}): return a rational approximation to x, whose denominator is limited by B, if present. This function applies to reals, intmods, p-adics, and rationals of course. Otherwise it applies recursively to all components. Doc: using variants of the extended Euclidean algorithm, returns a rational approximation $a/b$ to $x$, whose denominator is limited by $B$, if present. If $B$ is omitted, returns the best approximation affordable given the input accuracy; if you are looking for true rational numbers, presumably approximated to sufficient accuracy, you should first try that option. Otherwise, $B$ must be a positive real scalar (impose $0 < b \leq B$). \item If $x$ is a \typ{REAL} or a \typ{FRAC}, this function uses continued fractions. \bprog ? bestappr(Pi, 100) %1 = 22/7 ? bestappr(0.1428571428571428571428571429) %2 = 1/7 ? bestappr([Pi, sqrt(2) + 'x], 10^3) %3 = [355/113, x + 1393/985] @eprog By definition, $a/b$ is the best rational approximation to $x$ if $|b x - a| < |v x - u|$ for all integers $(u,v)$ with $0 < v \leq B$. (Which implies that $n/d$ is a convergent of the continued fraction of $x$.) \item If $x$ is a \typ{INTMOD} modulo $N$ or a \typ{PADIC} of precision $N = p^{k}$, this function performs rational modular reconstruction modulo $N$. The routine then returns the unique rational number $a/b$ in coprime integers $|a| < N/2B$ and $b\leq B$ which is congruent to $x$ modulo $N$. Omitting $B$ amounts to choosing it of the order of $\sqrt{N/2}$. If rational reconstruction is not possible (no suitable $a/b$ exists), returns $[]$. \bprog ? bestappr(Mod(18526731858, 11^10)) %1 = 1/7 ? bestappr(Mod(18526731858, 11^20)) %2 = [] ? bestappr(3 + 5 + 3*5^2 + 5^3 + 3*5^4 + 5^5 + 3*5^6 + O(5^7)) %2 = -1/3 @eprog\noindent In most concrete uses, $B$ is a prime power and we performed Hensel lifting to obtain $x$. The function applies recursively to components of complex objects (polynomials, vectors, \dots). If rational reconstruction fails for even a single entry, returns $[]$. pari-2.17.2/src/functions/number_theoretical/quadregulator0000644000175000017500000000101714567450071022450 0ustar billbillFunction: quadregulator Section: number_theoretical C-Name: quadregulator Prototype: Gp Help: quadregulator(D): regulator of the real quadratic field of discriminant D. Doc: regulator of the quadratic order of positive discriminant $D$ in time $\tilde{O}(D^{1/2})$ using the continued fraction algorithm. Raise an error if $D$ is not a discriminant (fundamental or not) or if $D$ is a square. The function \kbd{quadclassunit} is asymptotically faster (and also in practice for $D > 10^{10}$ or so) but depends on the GRH. pari-2.17.2/src/functions/number_theoretical/chinese0000644000175000017500000000442314760123736021213 0ustar billbillFunction: chinese Section: number_theoretical C-Name: chinese Prototype: GDG Help: chinese(x,{y}): x,y being both intmods (or polmods) computes z in the same residue classes as x and y. Description: (gen):gen chinese1($1) (gen, gen):gen chinese($1, $2) Doc: if $x$ and $y$ are both intmods or both polmods, creates (with the same type) a $z$ in the same residue class as $x$ and in the same residue class as $y$, if it is possible. \bprog ? chinese(Mod(1,2), Mod(2,3)) %1 = Mod(5, 6) ? chinese(Mod(x,x^2-1), Mod(x+1,x^2+1)) %2 = Mod(-1/2*x^2 + x + 1/2, x^4 - 1) @eprog\noindent This function also allows vector and matrix arguments, in which case the operation is recursively applied to each component of the vector or matrix. \bprog ? chinese([Mod(1,2),Mod(1,3)], [Mod(1,5),Mod(2,7)]) %3 = [Mod(1, 10), Mod(16, 21)] @eprog\noindent For polynomial arguments in the same variable, the function is applied to each coefficient; if the polynomials have different degrees, the high degree terms are copied verbatim in the result, as if the missing high degree terms in the polynomial of lowest degree had been \kbd{Mod(0,1)}. Since the latter behavior is usually \emph{not} the desired one, we propose to convert the polynomials to vectors of the same length first: \bprog ? P = x+1; Q = x^2+2*x+1; ? chinese(P*Mod(1,2), Q*Mod(1,3)) %4 = Mod(1, 3)*x^2 + Mod(5, 6)*x + Mod(3, 6) ? chinese(Vec(P,3)*Mod(1,2), Vec(Q,3)*Mod(1,3)) %5 = [Mod(1, 6), Mod(5, 6), Mod(4, 6)] ? Pol(%) %6 = Mod(1, 6)*x^2 + Mod(5, 6)*x + Mod(4, 6) @eprog If $y$ is omitted, and $x$ is a vector, \kbd{chinese} is applied recursively to the components of $x$, yielding a residue belonging to the same class as all components of $x$. Finally $\kbd{chinese}(x,x) = x$ regardless of the type of $x$; this allows vector arguments to contain other data, so long as they are identical in both vectors. Variant: \fun{GEN}{chinese1}{GEN x} is also available. Function: _polint_worker Section: programming/internals C-Name: nmV_polint_center_tree_worker Prototype: GGGGG Help: used for parallel chinese Doc: used for parallel chinese Function: _nxMV_polint_worker Section: programming/internals C-Name: nxMV_polint_center_tree_worker Prototype: GGGGG Help: used for parallel chinese Doc: used for parallel chinese pari-2.17.2/src/functions/number_theoretical/factormod0000644000175000017500000000472514676526175021572 0ustar billbillFunction: factormod Section: number_theoretical C-Name: factormod0 Prototype: GDGD0,L, Help: factormod(f,{D},{flag=0}): factors the polynomial f over the finite field defined by the domain D; flag is optional, and can be 0: default or 1: only the degrees of the irreducible factors are given. Doc: factors the polynomial $f$ over the finite field defined by the domain $D$ as follows: \item $D = p$ a prime: factor over $\F_{p}$; \item $D = [T,p]$ for a prime $p$ and $T(y)$ an irreducible polynomial over $\F_{p}$: factor over $\F_{p}[y]/(T)$ (as usual the main variable of $T$ must have lower priority than the main variable of $f$); \item $D$ a \typ{FFELT}: factor over the attached field; \item $D$ omitted: factor over the field of definition of $f$, which must be a finite field. The coefficients of $f$ must be operation-compatible with the corresponding finite field. The result is a two-column matrix, the first column being the irreducible polynomials dividing $f$, and the second the exponents. By convention, the $0$ polynomial factors as $0^{1}$; a nonzero constant polynomial has empty factorization, a $0\times 2$ matrix. The irreducible factors are ordered by increasing degree and the result is canonical: it will not change across multiple calls or sessions. \bprog ? factormod(x^2 + 1, 3) \\ over F_3 %1 = [Mod(1, 3)*x^2 + Mod(1, 3) 1] ? liftall( factormod(x^2 + 1, [t^2+1, 3]) ) \\ over F_9 %2 = [ x + t 1] [x + 2*t 1] \\ same, now letting GP choose a model ? T = ffinit(3,2,'t) %3 = Mod(1, 3)*t^2 + Mod(1, 3)*t + Mod(2, 3) ? liftall( factormod(x^2 + 1, [T, 3]) ) %4 = \\ t is a root of T ! [ x + (t + 2) 1] [x + (2*t + 1) 1] ? t = ffgen(t^2+Mod(1,3)); factormod(x^2 + t^0) \\ same using t_FFELT %5 = [ x + t 1] [x + 2*t 1] ? factormod(x^2+Mod(1,3)) %6 = [Mod(1, 3)*x^2 + Mod(1, 3) 1] ? liftall( factormod(x^2 + Mod(Mod(1,3), y^2+1)) ) %7 = [ x + y 1] [x + 2*y 1] @eprog If $\fl$ is nonzero, outputs only the \emph{degrees} of the irreducible polynomials (for example to compute an $L$-function). By convention, a constant polynomial (including the $0$ polynomial) has empty factorization. The degrees appear in increasing order but need not correspond to the ordering with $\fl =0$ when multiplicities are present. \bprog ? f = x^3 + 2*x^2 + x + 2; ? factormod(f, 5) \\ (x+2)^2 * (x+3) %1 = [Mod(1, 5)*x + Mod(2, 5) 2] [Mod(1, 5)*x + Mod(3, 5) 1] ? factormod(f, 5, 1) \\ (deg 1) * (deg 1)^2 %2 = [1 1] [1 2] @eprog pari-2.17.2/src/functions/number_theoretical/znconreylog0000644000175000017500000000605014676526175022156 0ustar billbillFunction: znconreylog Section: number_theoretical C-Name: znconreylog Prototype: GG Help: znconreylog(G,m): Conrey logarithm attached to m in (Z/qZ)*, where G is znstar(q,1). Doc: Given a \var{znstar} attached to $(\Z/q\Z)^{*}$ (as per \kbd{G = znstar(q,1)}), this function returns the Conrey logarithm of $m \in (\Z/q\Z)^{*}$. Let $q = \prod_{p} p^{e_{p}}$ be the factorization of $q$ into distinct primes, where we assume $e_{2} = 0$ or $e_{2} \geq 2$. (If $e_{2} = 1$, we can ignore $2$ from the factorization, as if we replaced $q$ by $q/2$, since $(\Z/q\Z)^{*} \sim (\Z/(q/2)\Z)^{*}$.) For all odd $p$ with $e_{p} > 0$, let $g_{p}$ be the element in $(\Z/q\Z)^{*}$ which is \item congruent to $1$ mod $q/p^{e_{p}}$, \item congruent mod $p^{e_{p}}$ to the smallest positive integer that generates $(\Z/p^{2}\Z)^{*}$. For $p = 2$, we let $g_{4}$ (if $2^{e_{2}} \geq 4$) and $g_{8}$ (if furthermore ($2^{e_{2}} \geq 8$) be the elements in $(\Z/q\Z)^{*}$ which are \item congruent to $1$ mod $q/2^{e_{2}}$, \item $g_{4} = -1 \mod 2^{e_{2}}$, \item $g_{8} = 5 \mod 2^{e_{2}}$. Then the $g_{p}$ (and the extra $g_{4}$ and $g_{8}$ if $2^{e_{2}}\geq 2$) are independent generators of $\Z/q\Z^{*}$, i.e. every $m$ in $(\Z/q\Z)^{*}$ can be written uniquely as $\prod_{p} g_{p}^{m_{p}}$, where $m_{p}$ is defined modulo the order $o_{p}$ of $g_{p}$ and $p \in S_{q}$, the set of prime divisors of $q$ together with $4$ if $4 \mid q$ and $8$ if $8 \mid q$. Note that the $g_{p}$ are in general \emph{not} SNF generators as produced by \kbd{znstar} whenever $\omega(q) \geq 2$, although their number is the same. They however allow to handle the finite abelian group $(\Z/q\Z)^{*}$ in a fast and elegant way. (Which unfortunately does not generalize to ray class groups or Hecke characters.) The Conrey logarithm of $m$ is the vector $(m_{p})_{p\in S_{q}}$. The inverse function \tet{znconreyexp} recovers the Conrey label $m$ from a character. \bprog ? G = znstar(126000, 1); ? znconreylog(G,1) %2 = [0, 0, 0, 0, 0]~ ? znconreyexp(G, %) %3 = 1 ? znconreylog(G,2) \\ 2 is not coprime to modulus !!! *** at top-level: znconreylog(G,2) *** ^----------------- *** znconreylog: elements not coprime in Zideallog: 2 126000 *** Break loop: type 'break' to go back to GP prompt break> ? znconreylog(G,11) \\ wrt. Conrey generators %4 = [0, 3, 1, 76, 4]~ ? log11 = ideallog(,11,G) \\ wrt. SNF generators %5 = [178, 3, -75, 1, 0]~ @eprog\noindent For convenience, we allow to input the ordinary discrete log of $m$, $\kbd{ideallog(,m,bid)}$, which allows to convert discrete logs from \kbd{bid.gen} generators to Conrey generators. \bprog ? znconreylog(G, log11) %7 = [0, 3, 1, 76, 4]~ @eprog\noindent We also allow a character (\typ{VEC}) on \kbd{bid.gen} and return its representation on the Conrey generators. \bprog ? G.cyc %8 = [300, 12, 2, 2, 2] ? chi = [10,1,0,1,1]; ? znconreylog(G, chi) %10 = [1, 3, 3, 10, 2]~ ? n = znconreyexp(G, chi) %11 = 84149 ? znconreychar(G, n) %12 = [10, 1, 0, 1, 1] @eprog pari-2.17.2/src/functions/number_theoretical/charker0000644000175000017500000000316114676526175021224 0ustar billbillFunction: charker Section: number_theoretical C-Name: charker0 Prototype: GG Help: charker(cyc,chi): given a finite abelian group (by its elementary divisors cyc) and a character chi, return its kernel. Doc: let \var{cyc} represent a finite abelian group by its elementary divisors, i.e. $(d_{j})$ represents $\sum_{j \leq k} \Z/d_{j}\Z$ with $d_{k} \mid \dots \mid d_{1}$; any object which has a \kbd{.cyc} method is also allowed, e.g.~the output of \kbd{znstar} or \kbd{bnrinit}. A character on this group is given by a row vector $\chi = [a_{1},\ldots,a_{n}]$ such that $\chi(\prod g_{j}^{n_{j}}) = \exp(2\pi i\sum_{j} a_{j} n_{j} / d_{j})$, where $g_{j}$ denotes the generator (of order $d_{j}$) of the $j$-th cyclic component. This function returns the kernel of $\chi$, as a matrix $K$ in HNF which is a left-divisor of \kbd{matdiagonal(d)}. Its columns express in terms of the $g_{j}$ the generators of the subgroup. The determinant of $K$ is the kernel index. \bprog ? cyc = [15,5]; chi = [1,1]; ? charker(cyc, chi) %2 = [15 12] [ 0 1] ? bnf = bnfinit(x^2+23); ? bnf.cyc %4 = [3] ? charker(bnf, [1]) %5 = [3] @eprog\noindent Note that for Dirichlet characters (when \kbd{cyc} is \kbd{znstar(q, 1)}), characters in Conrey representation are available, see \secref{se:dirichletchar} or \kbd{??character}. \bprog ? G = znstar(8, 1); \\ (Z/8Z)^* ? charker(G, 1) \\ Conrey label for trivial character %2 = [1 0] [0 1] @eprog Variant: Also available is \fun{GEN}{charker}{GEN cyc, GEN chi}, when \kbd{cyc} is known to be a vector of elementary divisors and \kbd{chi} a compatible character (no checks). pari-2.17.2/src/functions/number_theoretical/logint0000644000175000017500000000210014676526175021071 0ustar billbillFunction: logint Section: number_theoretical C-Name: logint0 Prototype: lGGD& Help: logint(x,b,{&z}): return the largest non-negative integer e so that b^e <= x, where b > 1 is an integer and x >= 1 is a real number. If the parameter z is present, set it to b^e. Description: (int,2):small expi($1) (gen,gen):small logint0($1, $2, NULL) (gen,gen,&int):small logint0($1, $2, &$3) Doc: Return the largest non-negative integer $e$ so that $b^{e} \leq x$, where $b > 1$ is an integer and $x \geq 1$ is a real number. If the parameter $z$ is present, set it to $b^{e}$. \bprog ? logint(1000, 2) %1 = 9 ? 2^9 %2 = 512 ? logint(1000, 2, &z) %3 = 9 ? z %4 = 512 ? logint(Pi^2, 2, &z) %5 = 3 ? z %6 = 8 @eprog\noindent The number of digits used to write $x$ in base $b$ is \kbd{1 + logint(x,b)}: \bprog ? #digits(1000!, 10) %5 = 2568 ? logint(1000!, 10) %6 = 2567 @eprog\noindent This function may conveniently replace \bprog floor( log(x) / log(b) ) @eprog\noindent which may not give the correct answer since PARI does not guarantee exact rounding. pari-2.17.2/src/functions/number_theoretical/ispower0000644000175000017500000000243114676526175021274 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 nonzero 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. What it means to be a $k$-th power depends on the type of $x$; see \tet{issquare} for details. 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 ^ x.f - 1) / fforder(x) @eprog Variant: Also available is \fun{long}{gisanypower}{GEN x, GEN *pty} ($k$ omitted). pari-2.17.2/src/functions/number_theoretical/charmul0000644000175000017500000000345314676526175021244 0ustar billbillFunction: charmul Section: number_theoretical C-Name: charmul0 Prototype: GGG Help: charmul(cyc,a,b): given a finite abelian group (by its elementary divisors cyc) and two characters a and b, return the product character ab. Doc: let \var{cyc} represent a finite abelian group by its elementary divisors, i.e. $(d_{j})$ represents $\sum_{j \leq k} \Z/d_{j}\Z$ with $d_{k} \mid \dots \mid d_{1}$; any object which has a \kbd{.cyc} method is also allowed, e.g.~the output of \kbd{znstar} or \kbd{bnrinit}. A character on this group is given by a row vector $\chi = [a_{1},\ldots,a_{n}]$ such that $\chi(\prod g_{j}^{n_{j}}) = \exp(2\pi i\sum_{j} a_{j} n_{j} / d_{j})$, where $g_{j}$ denotes the generator (of order $d_{j}$) of the $j$-th cyclic component. Given two characters $a$ and $b$, return the product character $ab$. \bprog ? cyc = [15,5]; a = [1,1]; b = [2,4]; ? charmul(cyc, a,b) %2 = [3, 0] ? bnf = bnfinit(x^2+23); ? bnf.cyc %4 = [3] ? charmul(bnf, [1], [2]) %5 = [0] @eprog\noindent For Dirichlet characters on $(\Z/N\Z)^{*}$, additional representations are available (Conrey labels, Conrey logarithm), see \secref{se:dirichletchar} or \kbd{??character}. If the two characters are in the same format, their product is given in the same format, otherwise a Conrey logarithm is used. \bprog ? G = znstar(100, 1); ? G.cyc %2 = [20, 2] ? a = [10, 1]; \\ usual representation for characters ? b = 7; \\ Conrey label; ? c = znconreylog(G, 11); \\ Conrey log ? charmul(G, b,b) %6 = 49 \\ Conrey label ? charmul(G, a,b) %7 = [0, 15]~ \\ Conrey log ? charmul(G, a,c) %7 = [0, 6]~ \\ Conrey log @eprog Variant: Also available is \fun{GEN}{charmul}{GEN cyc, GEN a, GEN b}, when \kbd{cyc} is known to be a vector of elementary divisors and $a, b$ are compatible characters (no checks). pari-2.17.2/src/functions/number_theoretical/znchardecompose0000644000175000017500000000232314676526175022770 0ustar billbillFunction: znchardecompose Section: number_theoretical C-Name: znchardecompose Prototype: GGG Help: znchardecompose(G,chi,Q): given a znstar G = (Z/NZ)^* and a Dirichlet character chi, return the product of local characters chi_p for p | (N,Q). Doc: Let $N = \prod_{p} p^{e_{p}}$ and a Dirichlet character $\chi$, we have a decomposition $\chi = \prod_{p} \chi_{p}$ into character modulo $N$ where the conductor of $\chi_{p}$ divides $p^{e_{p}}$; it equals $p^{e_{p}}$ for all $p$ if and only if $\chi$ is primitive. Given a \var{znstar} G describing a group $(\Z/N\Z)^{*}$, a Dirichlet character \kbd{chi} and an integer $Q$, return $\prod_{p \mid (Q,N)} \chi_{p}$. For instance, if $Q = p$ is a prime divisor of $N$, the function returns $\chi_{p}$ (as a character modulo $N$), given as a Conrey character (\typ{COL}). \bprog ? G = znstar(40, 1); ? G.cyc %2 = [4, 2, 2] ? chi = [2, 1, 1]; ? chi2 = znchardecompose(G, chi, 2) %4 = [1, 1, 0]~ ? chi5 = znchardecompose(G, chi, 5) %5 = [0, 0, 2]~ ? znchardecompose(G, chi, 3) %6 = [0, 0, 0]~ ? c = charmul(G, chi2, chi5) %7 = [1, 1, 2]~ \\ t_COL: in terms of Conrey generators ! ? znconreychar(G,c) %8 = [2, 1, 1] \\ t_VEC: in terms of SNF generators @eprog pari-2.17.2/src/functions/number_theoretical/ffmap0000644000175000017500000000134314676526175020676 0ustar billbillFunction: ffmap Section: number_theoretical C-Name: ffmap Prototype: GG Help: ffmap(m,x): given a (partial) map m between two finite fields, return the image of x by m. The function is applied recursively to the component of vectors, matrices and polynomials. If m is a partial map that is not defined at x, return [] Doc: given a (partial) map $m$ between two finite fields, return the image of $x$ by $m$. The function is applied recursively to the component of vectors, matrices and polynomials. If $m$ is a partial map that is not defined at $x$, return $[]$. \bprog ? a = ffgen([3,5],'a); ? b = ffgen([3,10],'b); ? m = ffembed(a, b); ? P = x^2+a*x+1; ? Q = ffmap(m,P); ? ffmap(m,poldisc(P)) == poldisc(Q) %6 = 1 @eprog pari-2.17.2/src/functions/number_theoretical/quadgen0000644000175000017500000000163714567450071021225 0ustar billbillFunction: quadgen Section: number_theoretical C-Name: quadgen0 Prototype: GDn Help: quadgen(D,{v = 'w}): standard generator g of quadratic order of discriminant D. If v is given, the variable name is used to display g, else 'w' is used. 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. If \var{v} is given, the variable name is used to display $g$ else 'w' is used. \bprog ? w = quadgen(5, 'w); w^2 - w - 1 %1 = 0 ? w = quadgen(0, 'w) *** at top-level: w=quadgen(0) *** ^---------- *** quadgen: domain error in quadpoly: issquare(disc) = 1 @eprog Variant: When \var{v} does not matter, the function \fun{GEN}{quadgen}{GEN D} is also available. pari-2.17.2/src/functions/number_theoretical/divisors0000644000175000017500000000373514567450071021444 0ustar billbillFunction: divisors Section: number_theoretical C-Name: divisors0 Prototype: GD0,L, Help: divisors(x,{flag=0}): gives a vector formed by the divisors of x in increasing order. If flag = 1, return pairs [d, factor(d)]. Description: (gen,?0):vec divisors($1) (gen,1):vec divisors_factored($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. If $\fl = 1$, return pairs $[d, \kbd{factor}(d)]$. 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. \bprog ? divisors(12) %1 = [1, 2, 3, 4, 6, 12] ? divisors(12, 1) \\ include their factorization %2 = [[1, matrix(0,2)], [2, Mat([2, 1])], [3, Mat([3, 1])], [4, Mat([2, 2])], [6, [2, 1; 3, 1]], [12, [2, 2; 3, 1]]] ? divisors(x^4 + 2*x^3 + x^2) \\ also works for polynomials %3 = [1, x, x^2, x + 1, x^2 + x, x^3 + x^2, x^2 + 2*x + 1, x^3 + 2*x^2 + x, x^4 + 2*x^3 + x^2] @eprog This function requires a lot of memory if $x$ has many divisors. The following idiom runs through all divisors using very little memory, in no particular order this time: \bprog F = factor(x); P = F[,1]; E = F[,2]; forvec(e = vectorv(#E,i,[0,E[i]]), d = factorback(P,e); ...) @eprog If the factorization of $d$ is also desired, then $[P,e]$ almost provides it but not quite: $e$ may contain $0$ exponents, which are not allowed in factorizations. These must be sieved out as in: \bprog ? tofact(P,E) = matreduce(Mat([P,E])); ? tofact([2,3,5,7]~, [4,0,2,0]~) %4 = [2 4] [5 2] @eprog We can then run the above loop with \kbd{tofact(P,e)} instead of, or together with, \kbd{factorback}. Variant: The functions \fun{GEN}{divisors}{GEN N} ($\fl = 0$) and \fun{GEN}{divisors_factored}{GEN N} ($\fl = 1$) are also available. pari-2.17.2/src/functions/number_theoretical/qfbred0000644000175000017500000000172414567450071021041 0ustar billbillFunction: qfbred Section: number_theoretical C-Name: qfbred0 Prototype: GD0,L,DGDG Help: qfbred(x,{flag=0},{isd},{sd}): reduction of the binary quadratic form x. All other args. are optional. The argument isd and sd, if present, supply the values of floor(sqrt(d)) and sqrt(d) respectively, where d is the discriminant. If d<0, its value is not used. flag can be any of 0: default; 1: do a single reduction step; Doc: reduces the binary quadratic form $x$ (updating Shanks's distance function $d$ if $x = [q,d]$ is an extended \emph{indefinite} form). If $\fl$ is $1$, the function performs a single \idx{reduction} step, and a complete reduction otherwise. The arguments \var{isd}, \var{sd}, if present, supply the values of $\floor{\sqrt{D}}$, and $\sqrt{D}$ respectively, where $D$ is the discriminant (this is not checked). If $d < 0$ these values are useless. Variant: Also available is \fun{GEN}{qfbred}{GEN x} (\fl is 0, \kbd{isd} and \kbd{sd} are \kbd{NULL}) pari-2.17.2/src/functions/number_theoretical/qfbsolve0000644000175000017500000000500714676526175021427 0ustar billbillFunction: qfbsolve Section: number_theoretical C-Name: qfbsolve Prototype: GGD0,L, Help: qfbsolve(Q,n,{flag=0}): Solve the equation Q(x,y)=n in coprime integers x and y where Q is a binary quadratic form, up to the action of the special orthogonal group of Q over the integers. Binary digits of flag mean 1: return all solutions, 2: also include imprimitive solutions. Doc: Solve the equation $Q(x,y)=n$ in coprime integers $x$ and $y$ (primitive solutions), where $Q$ is a binary quadratic form and $n$ an integer, up to the action of the special orthogonal group $G=SO(Q,\Z)$, which is isomorphic to the group of units of positive norm of the quadratic order of discriminant $D = \disc Q$. If $D>0$, $G$ is infinite. If $D<-4$, $G$ is of order $2$, if $D=-3$, $G$ is of order $6$ and if $D=-4$, $G$ is of order $4$. Binary digits of $\fl$ mean: 1: return all solutions if set, else a single solution; return $[]$ if a single solution is wanted (bit unset) but none exist. 2: also include imprimitive solutions. When $\fl = 2$ (return a single solution, possibly imprimitive), the algorithm returns a solution with minimal content; in particular, a primitive solution exists if and only if one is returned. The integer $n$ can also be given by its factorization matrix \kbd{\var{fa} = factor(n)} or by the pair $[n, \var{fa}]$. \bprog ? qfbsolve(Qfb(1,0,2), 603) \\ a single primitive solution %1 = [5, 17] ? qfbsolve(Qfb(1,0,2), 603, 1) \\ all primitive solutions %2 = [[5, 17], [-19, -11], [19, -11], [5, -17]] ? qfbsolve(Qfb(1,0,2), 603, 2) \\ a single, possibly imprimitive solution %3 = [5, 17] \\ actually primitive ? qfbsolve(Qfb(1,0,2), 603, 3) \\ all solutions %4 = [[5, 17], [-19, -11], [19, -11], [5, -17], [-21, 9], [-21, -9]] ? N = 2^128+1; F = factor(N); ? qfbsolve(Qfb(1,0,1),[N,F],1) %3 = [[-16382350221535464479,8479443857936402504], [18446744073709551616,-1],[-18446744073709551616,-1], [16382350221535464479,8479443857936402504]] @eprog For fixed $Q$, assuming the factorisation of $n$ is given, the algorithm runs in probabilistic polynomial time in $\log p$, where $p$ is the largest prime divisor of $n$, through the computation of square roots of $D$ modulo $4\*p$). The dependency on $Q$ is more complicated: polynomial time in $\log |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 assuming the GRH. pari-2.17.2/src/functions/number_theoretical/zncharisodd0000644000175000017500000000143714676526175022121 0ustar billbillFunction: zncharisodd Section: number_theoretical C-Name: zncharisodd Prototype: lGG Help: zncharisodd(G,chi): let G be znstar(N,1), let chi be a Dirichlet character mod N, return 1 if and only if chi(-1) = -1 and 0 otherwise. Doc: Let $G$ be attached to $(\Z/N\Z)^{*}$ (as per \kbd{G = znstar(N,1)}) and let \kbd{chi} be a Dirichlet character on $(\Z/N\Z)^{*}$, given by \item a \typ{VEC}: a standard character on \kbd{G.gen}, \item a \typ{INT} or a \typ{COL}: a Conrey index in $(\Z/q\Z)^{*}$ or its Conrey logarithm; see \secref{se:dirichletchar} or \kbd{??character}. Return $1$ if and only if \kbd{chi}$(-1) = -1$ and $0$ otherwise. \bprog ? G = znstar(8, 1); ? zncharisodd(G, 1) \\ trivial character %2 = 0 ? zncharisodd(G, 3) %3 = 1 ? chareval(G, 3, -1) %4 = 1/2 @eprog pari-2.17.2/src/functions/number_fields/0000755000175000017500000000000014760315601016604 5ustar billbillpari-2.17.2/src/functions/number_fields/bnrmap0000644000175000017500000000431114676526175020025 0ustar billbillFunction: bnrmap Section: number_fields C-Name: bnrmap Prototype: GG Help: bnrmap(A,B): if A and B are bnr structures for the same bnf attached to moduli mA and mB with mB | mA, return the canonical surjection from A to B. Alternatively, if A is a map from bnrmap and B is a congruence subgroup or ray class character modulo mA, return the corresponding object on Cl(mB). Doc: This function has two different uses: \item if $A$ and $B$ are \var{bnr} structures for the same \var{bnf} attached to moduli $m_{A}$ and $m_{B}$ with $m_{B} \mid m_{A}$, return the canonical surjection from $A$ to $B$, i.e. from the ray class group moodulo $m_{A}$ to the ray class group modulo $m_{B}$. The map is coded by a triple $[M,\var{cyc}_{A},\var{cyc}_{B}]$: $M$ gives the image of the fixed ray class group generators of $A$ in terms of the ones in $B$, $\var{cyc}_{A}$ and $\var{cyc}_{B}$ are the cyclic structures \kbd{A.cyc} and \kbd{B.cyc} respectively. Note that this function does \emph{not} need $A$ or $B$ to contain explicit generators for the ray class groups: they may be created using \kbd{bnrinit(,0)}. If $B$ is only known modulo $N$-th powers (from \kbd{bnrinit(,N)}), the result is correct provided $N$ is a multiple of the exponent of $A$. \item if $A$ is a projection map as above and $B$ is either a congruence subgroup $H$, or a ray class character $\chi$, or a discrete logarithm (from \kbd{bnrisprincipal}) modulo $m_{A}$ whose conductor divides $m_{B}$, return the image of the subgroup (resp. the character, the discrete logarighm) as defined modulo $m_{B}$. The main use of this variant is to compute the primitive subgroup or character attached to a \var{bnr} modulo their conductor. This is more efficient than \tet{bnrconductor} in two respects: the \var{bnr} attached to the conductor need only be computed once and, most importantly, the ray class group can be computed modulo $N$-th powers, where $N$ is a multiple of the exponent of $\text{Cl}_{m_{A}} / H$ (resp. of the order of $\chi$). Whereas \kbd{bnrconductor} is specified to return a \var{bnr} attached to the full ray class group, which may lead to untractable discrete logarithms in the full ray class group instead of a tiny quotient. pari-2.17.2/src/functions/number_fields/galoissplittinginit0000644000175000017500000000140214676526175022644 0ustar billbillFunction: galoissplittinginit Section: number_fields C-Name: galoissplittinginit Prototype: GDG Help: galoissplittinginit(P,{d}): Galois group over Q of the splitting field of P, for P integral, monic and irreducible or given by a nf structure. If d is given, it must be a multiple of the splitting field degree. The output is compatible with functions expecting a galoisinit structure. Doc: compute the Galois group over $Q$ of the splitting field of $P$, that is the smallest field over which $P$ is totally split. $P$ is assumed to be integral, monic and irreducible; it can also be given by a \kbd{nf} structure. If $d$ is given, it must be a multiple of the splitting field degree. The output is compatible with functions expecting a \kbd{galoisinit} structure. pari-2.17.2/src/functions/number_fields/nfgrunwaldwang0000644000175000017500000000360514676526175021577 0ustar billbillFunction: nfgrunwaldwang Section: number_fields C-Name: nfgrunwaldwang Prototype: GGGGDn Help: nfgrunwaldwang(nf,Lpr,Ld,pl,{v='x}): a polynomial in the variable v defining a cyclic extension of nf (given in nf or bnf form) with local behavior prescribed by Lpr, Ld and pl: the extension has local degree a multiple of Ld[i] at the prime Lpr[i], and the extension is complex at the i-th real place of nf if pl[i]=-1 (no condition if pl[i]=0). The extension has degree the LCM of the local degrees. Doc: Given \var{nf} a number field in \var{nf} or \var{bnf} format, a \typ{VEC} \var{Lpr} of primes of \var{nf} and a \typ{VEC} \var{Ld} of positive integers of the same length, a \typ{VECSMALL} \var{pl} of length $r_{1}$ the number of real places of \var{nf}, computes a polynomial with coefficients in \var{nf} defining a cyclic extension of \var{nf} of minimal degree satisfying certain local conditions: \item at the prime~$Lpr[i]$, the extension has local degree a multiple of~$Ld[i]$; \item at the $i$-th real place of \var{nf}, it is complex if $pl[i]=-1$ (no condition if $pl[i]=0$). The extension has degree the LCM of the local degrees. Currently, the degree is restricted to be a prime power for the search, and to be prime for the construction because of the \kbd{rnfkummer} restrictions. When \var{nf} is $\Q$, prime integers are accepted instead of \kbd{prid} structures. However, their primality is not checked and the behavior is undefined if you provide a composite number. \misctitle{Warning} If the number field \var{nf} does not contain the $n$-th roots of unity where $n$ is the degree of the extension to be computed, the function triggers the computation of the \var{bnf} of $nf(\zeta_{n})$, which may be costly. \bprog ? nf = nfinit(y^2-5); ? pr = idealprimedec(nf,13)[1]; ? pol = nfgrunwaldwang(nf, [pr], [2], [0,-1], 'x) %3 = x^2 + Mod(3/2*y + 13/2, y^2 - 5) @eprog pari-2.17.2/src/functions/number_fields/idealfrobenius0000644000175000017500000000170714676526175021547 0ustar billbillFunction: idealfrobenius Section: number_fields C-Name: idealfrobenius Prototype: GGG Help: idealfrobenius(nf,gal,pr): returns the Frobenius element (pr|nf/Q) attached to 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 \var{pr} is an unramified prime ideal $\goth{p}$ in \kbd{prid} format. This function returns a permutation of \kbd{gal.group} which defines the Frobenius element $\Frob_{\goth{p}}$ attached to $\goth{p}$. If $p$ is the unique prime number in $\goth{p}$, then $\Frob(x)\equiv x^{p}\mod\goth{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.17.2/src/functions/number_fields/nfmodprlift0000644000175000017500000000200014760123736021051 0ustar billbillFunction: nfmodprlift Section: number_fields C-Name: nfmodprlift Prototype: GGG Help: nfmodprlift(nf,x,pr): lift x from residue field mod pr to nf. Doc: lift the \typ{FFELT} $x$ (from \tet{nfmodpr}) in the residue field modulo \var{pr} to the ring of integers. Vectors and matrices are also supported. For polynomials, use \kbd{apply} and the present function. The argument \var{pr} is either a maximal ideal in \kbd{idealprimedec} format or, preferably, a \var{modpr} structure from \tet{nfmodprinit}. There are no compatibility checks to try and decide whether $x$ is attached the same residue field as defined by \var{pr}: the result is undefined if not. The function \tet{nfmodpr} allows to reduce to the residue field. \bprog ? K = nfinit(y^3-250); ? P = idealprimedec(K, 5)[2]; ? modP = nfmodprinit(K,P); ? K.zk %4 = [1, 1/5*y, 1/25*y^2] ? apply(t->nfmodpr(K,t,modP), K.zk) %5 = [1, y, 2*y + 1] ? nfmodprlift(K, %, modP) %6 = [1, 1/5*y, 2/5*y + 1] ? nfeltval(K, %[3] - K.zk[3], P) %7 = 1 @eprog pari-2.17.2/src/functions/number_fields/gcharisalgebraic0000644000175000017500000000205414760123736022010 0ustar billbillFunction: gcharisalgebraic Section: number_fields C-Name: gcharisalgebraic Prototype: iGGD& Help: gcharisalgebraic(gc,chi,{&type}): returns 1 if chi is an algebraic (type A0) character. If type is present, it is set to the infinity type [p,q] of chi. Doc: \var{gc} being the structure returned by \kbd{gcharinit} and \var{chi} a character on \var{gc}, returns 1 if and only if \var{chi} is an algebraic (Weil type A0) character, so that its infinity type at every complex embedding~$\tau$ can be written $$ z \mapsto z^{-p_{\tau}}\bar{z}^{-q_{\tau}} $$ for some pair of integers $(p_{\tau},q_{\tau})$. If \var{type} is given, it is set to the \typ{VEC} of exponents $[p_{\tau},q_{\tau}]$. \bprog ? bnf = bnfinit(x^4+1,1); ? gc = gcharinit(bnf,1); ? gc.cyc % = [0, 0, 0, 0.E-57] ? chi1 = [0,0,1]~; ? gcharisalgebraic(gc,chi1) % = 0 ? gcharlocal(gc,chi1,1) % = [-3, -0.89110698909568455588720672648627467040] ? chi2 = [1,0,0,-3]~; ? gcharisalgebraic(gc,chi2,&typ) % = 1 ? typ % = [[6, 0], [2, 4]] ? gcharlocal(gc,chi2,1) % = [-6, 3*I] @eprog pari-2.17.2/src/functions/number_fields/bnfdecodemodule0000644000175000017500000000111714567450071021654 0ustar billbillFunction: bnfdecodemodule Section: number_fields C-Name: decodemodule Prototype: GG Help: bnfdecodemodule(nf,m): given a coded module m as in bnrdisclist, gives the true module. Doc: if $m$ is a module as output in the first component of an extension given by \kbd{bnrdisclist}, outputs the true module. \bprog ? K = bnfinit(x^2+23); L = bnrdisclist(K, 10); s = L[2] %1 = [[[Vecsmall([8]), Vecsmall([1])], [[0, 0, 0]]], [[Vecsmall([9]), Vecsmall([1])], [[0, 0, 0]]]] ? bnfdecodemodule(K, s[1][1]) %2 = [2 0] [0 1] ? bnfdecodemodule(K,s[2][1]) %3 = [2 1] [0 1] @eprog pari-2.17.2/src/functions/number_fields/nfweilheight0000644000175000017500000000147714760123736021223 0ustar billbillFunction: nfweilheight Section: number_fields C-Name: nfweilheight Prototype: GGp Help: nfweilheight(nf, v): return the absolute Weil height of the vector v seen as an element of the projective space over the number field nf given by nfinit. Doc: let \var{nf} be attached to a number field $K$, let $v$ be a vector of elements of $K$, not all of them $0$, seen as element of the projective space of dimension \kbd{\#v - 1}. Return the absolute logarithmic Weil height of that element, which does not depend on the number field used to compute it. When the entries of $v$ are rational, the height is \kbd{log(normlp(v / content(v), oo))}. \bprog ? v = [1, 2, -3, 101]; Q = nfinit(x); Qi = nfinit(x^2 + 1); ? exponent(nfweilheight(Q, v) - log(101)) %2 = -125 ? exponent(nfweilheight(Qi, v) - log(101)) %3 = -125 @eprog pari-2.17.2/src/functions/number_fields/galoisinit0000644000175000017500000001004414676526175020710 0ustar billbillFunction: galoisinit Section: number_fields C-Name: galoisinit Prototype: GDG Help: galoisinit(pol,{den}): pol being a polynomial or a number field as output by nfinit defining a Galois extension of Q, compute the Galois group and all necessary information for computing fixed fields. den is optional and has the same meaning as in nfgaloisconj(,4)(see manual). Description: (gen, ?int):gal galoisinit($1, $2) Doc: computes the Galois group and all necessary information for computing the fixed fields of the Galois extension $K/\Q$ where $K$ is the number field defined by $\var{pol}$ (monic irreducible polynomial in $\Z[X]$ or a number field as output by \tet{nfinit}). The extension $K/\Q$ must be Galois with Galois group ``weakly'' super-solvable, see below; returns 0 otherwise. Hence this permits to quickly check whether a polynomial of order strictly less than $48$ 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 $izeta_12^3, g2->zeta_3 @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{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{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{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 The member functions \kbd{.codiff}, \kbd{.t2} and \kbd{.zk} perform a computation and are relatively expensive in large degree: move them out of tight loops and store them in variables. 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 nonmonic 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 nonnegative real numbers. By default they are chosen so that the result is correct under GRH. For $i = 1,2$, let $B_{i} = c_{i}(\log |d_{K}|)^{2}$, and denote by $S(B)$ the set of maximal ideals of $K$ whose norm is less than $B$. We want $S(B_{1})$ to generate $\Cl(K)$ and hope that $S(B_{2})$ can be \emph{proven} to generate $\Cl(K)$. More precisely, $S(B_{1})$ is a factorbase used to compute a tentative $\Cl(K)$ by generators and relations. We then check explicitly, using essentially \kbd{bnfisprincipal}, that the elements of $S(B_{2})$ belong to the span of $S(B_{1})$. Under the assumption that $S(B_{2})$ generates $\Cl(K)$, we are done. User-supplied $c_{i}$ are only used to compute initial guesses for the bounds $B_{i}$, and the algorithm increases them until one can \emph{prove} under GRH that $S(B_{2})$ generates $\Cl(K)$. A uniform result of Greni\'e and Molteni says that $c_{2} = 4$ is always suitable, but this bound is very pessimistic and a direct algorithm due to Belabas-Diaz-Friedman, improved by Greni\'e and Molteni, is used to check the condition, assuming GRH. The default values are $c_{1} = c_{2} = 0$. When $c_{1}$ is equal to $0$ the algorithm takes it equal to $c_{2}$. $\var{nrpid}$ is the maximal number of small norm relations attached 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. \subsec{Hecke Grossencharacters}\label{se:GCHAR} Hecke Grossencharacters are continuous characters of the id\`ele class group; they generalize classical Hecke characters on ray class groups obtained through the $\var{bnr}$ structure. Let $K$ be a number field, $\A^{\times}$ its group of id\`eles. Every Grossencharacter $$ \chi \colon \A^{\times}/K^{\times} \to \C^{\times} $$ can be uniquely written~$\chi = \chi_{0} \|\cdot \|^{s}$ for some~$s\in\C$ and some character~$\chi_{0}$ of the compact group~$\A^{\times}/(K^{\times}\cdot\R_{>0})$, where~$\|a\| = \prod_{v} |a_{v}|_{v}$ is the id\`ele norm. Let~$\goth{m}$ be a modulus (an integral ideal and a finite set of real places). Let $U(\goth{m})$ be the subgroup of id\`eles congruent to $1$ modulo $\goth{m}$ (units outside $\goth{m}$, positive at real places in $\goth{m}$). The Hecke Grossencharacters defined modulo $\goth{m}$ are the characters of the id\`ele class group $$ C_{K}(\goth{m}) = \A^{\times}/(K^{\times}\cdot U(\goth{m})), $$ that is, combinations of an archimedean character $\chi_{\infty}$ on the connected component $K_{\infty}^{\times \circ}$ and a ray class group character $\chi_{f}$ satisfying a compatibility condition $\chi_{\infty}(a)\chi_{f}(a)=1$ for all units $a$ congruent to 1 modulo $\goth{m}$. \varsidx{gchar} % \item \var{gc} denotes a structure allowing to compute with Hecke Grossencharacters. \item \kbd{gcharinit(\var{bnf},\var{mod})} initializes the structure \var{gc}. The underlying number field and modulus can be accessed using \var{gc}\kbd{.bnf} and \var{gc}\kbd{.mod}. \item \var{gc}\kbd{.cyc} describes the finite abelian group structure of \var{gc}, the torsion part corresponding to finite order ray class characters, the exact zeros corresponding to a lattice of infinite order Grossencharacters, and the approximate zero being a placeholder for the complex powers of the id\`ele norm. \item A Hecke character of modulus~$\goth{m}$ is described as a \typ{COL} of coordinates corresponding to~\var{gc}\kbd{.cyc}: all the coordinates are integers except the last one, which can be an arbitrary complex number, or omitted instead of~$0$. \item Hecke Grossencharacters have $L$-functions and can be given to all \kbd{lfun} functions as a 2 components vector \kbd{[\var{gc},\var{chi}]}, see also Section~\ref{se:lfungchar}. pari-2.17.2/src/functions/number_fields/nfsubfields0000644000175000017500000000363414676526175021061 0ustar billbillFunction: nfsubfields Section: number_fields C-Name: nfsubfields0 Prototype: GD0,L,D0,L, Help: nfsubfields(pol,{d=0},{flag=0}): finds all subfields of degree d of number field defined by pol (all subfields if d is null or omitted). The result is a vector of subfields, each being given by [g,h] (default) or simply g (flag=1), 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]$ (default) or simply $g$ ($\fl=1$), 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 \item Allombert's \tet{galoissubfields} when \var{nf} is Galois (with weakly supersolvable Galois group).\sidx{Galois}\sidx{subfield} \item Kl\"uners's or van Hoeij--Kl\"uners--Novocin algorithm in the general case. The latter runs in polynomial time and is generally superior unless there exists a small unramified prime $p$ such that \var{pol} has few irreducible factors modulo $p$. An input of the form~\kbd{[nf, fa]} is also allowed, where~\kbd{fa} is the factorisation of~\var{nf.pol} over~\var{nf}, expressed as a famat of polynomials with coefficients in the variable of~\kbd{nf}, in which case the van Hoeij--Kl\"uners--Novocin algorithm is used. \bprog ? pol = x^4 - x^3 - x^2 + x + 1; ? nfsubfields(pol) %2 = [[x, 0], [x^2 - x + 1, x^3 - x^2 + 1], [x^4 - x^3 - x^2 + x + 1, x]] ? nfsubfields(pol,,1) %2 = [x, x^2 - x + 1, x^4 - x^3 - x^2 + x + 1] ? y=varhigher("y"); fa = nffactor(pol,subst(pol,x,y)); ? #nfsubfields([pol,fa]) %5 = 3 @eprog Variant: Also available is \fun{GEN}{nfsubfields}{GEN nf, long d}, corresponding to $\fl = 0$. pari-2.17.2/src/functions/number_fields/rnfelttrace0000644000175000017500000000074614676526175021067 0ustar billbillFunction: rnfelttrace Section: number_fields C-Name: rnfelttrace Prototype: GG Help: rnfelttrace(rnf,x): returns the relative trace Tr_{L/K}(x), as an element of K. Doc: $\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ being an element of $L$, returns the relative trace $Tr_{L/K}(x)$ as an element of $K$. \bprog ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y); ? rnfelttrace(L, Mod(x, L.pol)) %2 = 0 ? rnfelttrace(L, 2) %3 = 4 @eprog pari-2.17.2/src/functions/number_fields/idealismaximal0000644000175000017500000000237214567450071021524 0ustar billbillFunction: idealismaximal Section: number_fields C-Name: idealismaximal Prototype: GG Help: idealismaximal(nf,x): if x is a maximal ideal, return it in prid form, else return 0. Doc: given \var{nf} a number field as output by \kbd{nfinit} and an ideal $x$, return $0$ if $x$ is not a maximal ideal. Otherwise return a \kbd{prid} structure \var{nf} attached to the ideal. This function uses \kbd{ispseudoprime} and may return a wrong result in case the underlying rational pseudoprime is not an actual prime number: apply \kbd{isprime(pr.p)} to guarantee correctness. If $x$ is an extended ideal, the extended part is ignored. \bprog ? K = nfinit(y^2 + 1); ? idealismaximal(K, 3) \\ 3 is inert %2 = [3, [3, 0]~, 1, 2, 1] ? idealismaximal(K, 5) \\ 5 is not %3 = 0 ? pr = idealprimedec(K,5)[1] \\ already a prid %4 = [5, [-2, 1]~, 1, 1, [2, -1; 1, 2]] ? idealismaximal(K, pr) \\ trivial check %5 = [5, [-2, 1]~, 1, 1, [2, -1; 1, 2]] ? x = idealhnf(K, pr) %6 = [5 3] [0 1] ? idealismaximal(K, x) \\ converts from matrix form to prid %7 = [5, [-2, 1]~, 1, 1, [2, -1; 1, 2]] @eprog\noindent This function is noticeably faster than \kbd{idealfactor} since it never involves an actually factorization, in particular when $x \cap \Z$ is not a prime number. pari-2.17.2/src/functions/number_fields/bnflogdegree0000644000175000017500000000222414676526175021172 0ustar billbillFunction: bnflogdegree Section: number_fields C-Name: bnflogdegree Prototype: GGG Help: bnflogdegree(nf,A,l): let A be an ideal, return exp(deg_F A) the exponential of the l-adic logarithmic degree. Doc: Let \var{nf} be a \var{nf} structure attached to a number field $F$, and let $l$ be a prime number (hereafter denoted $\ell$). The $\ell$-adified group of id\`{e}les of $F$ quotiented by the group of logarithmic units is identified to the $\ell$-group of logarithmic divisors $\oplus \Z_{\ell} [\goth{p}]$, generated by the maximal ideals of $F$. The \emph{degree} map $\deg_{F}$ is additive with values in $\Z_{\ell}$, defined by $\deg_{F} \goth{p} = \tilde{f}_{\goth{p}} \deg_{\ell} p$, where the integer $\tilde{f}_{\goth{p}}$ is as in \tet{bnflogef} and $\deg_{\ell} p$ is $\log_{\ell} p$ for $p\neq \ell$, $\log_{\ell} (1 + \ell)$ for $p = \ell\neq 2$ and $\log_{\ell} (1 + 2^{2})$ for $p = \ell = 2$. Let $A = \prod \goth{p}^{n_{\goth{p}}}$ be an ideal and let $\tilde{A} = \sum n_{\goth{p}} [\goth{p}]$ be the attached logarithmic divisor. Return the exponential of the $\ell$-adic logarithmic degree $\deg_{F} A$, which is a natural number. pari-2.17.2/src/functions/number_fields/idealnumden0000644000175000017500000000061114567450071021020 0ustar billbillFunction: idealnumden Section: number_fields C-Name: idealnumden Prototype: GG Help: idealnumden(nf,x): returns [A,B], where A,B are coprime integer ideals such that x = A/B. Doc: returns $[A,B]$, where $A,B$ are coprime integer ideals such that $x = A/B$, in the number field $\var{nf}$. \bprog ? nf = nfinit(x^2+1); ? idealnumden(nf, (x+1)/2) %2 = [[1, 0; 0, 1], [2, 1; 0, 1]] @eprog pari-2.17.2/src/functions/number_fields/nfinit0000644000175000017500000002341514676526175020043 0ustar billbillFunction: nfinit Section: number_fields C-Name: nfinit0 Prototype: GD0,L,p Help: nfinit(pol,{flag=0}): pol being a nonconstant irreducible polynomial in Q[X], returns an nf structure attached to the number field Q[X] / (pol). Binary digits of flag mean 1: two-element vector [nf,Mod(a,P)], where Mod(a,P) is a polmod equal to Mod(x,pol) and P=nf.pol; 2: first use polredbest to find a simpler polynomial P; 4: do not LLL-reduce the maximal order basis nf.zk. Description: (gen, ?0):nf:prec nfinit0($1, 0, $prec) (gen, 1):nf:prec nfinit0($1, nf_ORIG, $prec) (gen, 2):nf:prec nfinit0($1, nf_RED, $prec) (gen, 3):gen:prec nfinit0($1, nf_ORIG|nf_RED, $prec) (gen, 4):gen:prec nfinit0($1, nf_NOLLL, $prec) (gen, #small):void $"incorrect flag in nfinit" (gen, small):gen:prec nfinit0($1, $2, $prec) Doc: \var{pol} being a nonconstant irreducible polynomial in $\Q[X]$, preferably monic and integral, initializes a \emph{number field} (or \var{nf}) structure attached 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 given 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$, \var{MD}, \var{TI}, \var{MDI} and a vector \var{vP} defined as follows: \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 \var{TI} is equal to the primitive part of $T^{-1}$, which has integral coefficients. \quad\item \var{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). This is used in \tet{idealinv}. \quad\item \var{vP} is the list of prime divisors of the field discriminant, i.e, the ramified primes (\kbd{\var{nf}.p}); \kbd{nfdiscfactors(nf)} is the preferred way to access that information. $\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 a $\Z$-basis for $d\Z_{K}$, where $d = [\Z_{K}:\Z(\theta)]$, expressed on the powers of $\theta$. The multiplication by $d$ ensures that all polynomials have integral coefficients and $\var{nf}[7] / d$ (\kbd{\var{nf}.zk}) is an integral basis for $\Z_{K}$. 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 or non integral polynomial is input, \kbd{nfinit} will transform it, and return a structure attached to the new (monic integral) polynomial together with the attached change of variables, see $\fl=3$. It is allowed, though not very useful given the existence of \tet{nfnewprec}, to input a \var{nf} or a \var{bnf} instead of a polynomial. It is also allowed to input a \var{rnf}, in which case an \kbd{nf} structure attached to the absolute defining polynomial \kbd{polabs} is returned (\fl is then ignored). \bprog ? nf = nfinit(x^3 - 12); \\ initialize number field Q[X] / (X^3 - 12) ? nf.pol \\ defining polynomial %2 = x^3 - 12 ? nf.disc \\ field discriminant %3 = -972 ? nf.index \\ index of power basis order in maximal order %4 = 2 ? nf.zk \\ integer basis, lifted to Q[X] %5 = [1, x, 1/2*x^2] ? nf.sign \\ signature %6 = [1, 1] ? factor(abs(nf.disc )) \\ determines ramified primes %7 = [2 2] [3 5] ? idealfactor(nf, 2) %8 = [[2, [0, 0, -1]~, 3, 1, [0, 1, 0]~] 3] \\ @com $\goth{p}_{2}^{3}$ @eprog \misctitle{Huge discriminants, helping nfdisc} In case \var{pol} has a huge discriminant which is difficult to factor, it is hard to compute from scratch the maximal order. The following special input formats are also accepted: \item $[\var{pol}, B]$ where \var{pol} is a monic integral polynomial and $B$ is the lift of an integer basis, as would be computed by \tet{nfbasis}: a vector of polynomials with first element $1$ (implicitly modulo \var{pol}). This is useful if the maximal order is known in advance. \item $[\var{pol}, B, P]$ where \var{pol} and $B$ are as above (a monic integral polynomial and the lift of an integer basis), and $P$ is the list of ramified primes in the extension. \item $[\var{pol}, \kbd{listP}]$ where \var{pol} is a rational polynomial and \kbd{listP} specifies a list of primes as in \tet{nfbasis}. Instead of the maximal order, \kbd{nfinit} then computes an order which is maximal at these particular primes as well as the primes contained in the private prime table, see \tet{addprimes}. The result has a good chance of being correct when the discriminant \kbd{nf.disc} factors completely over this set of primes but this is not guaranteed. The function \tet{nfcertify} automates this: \bprog ? pol = polcompositum(x^5 - 101, polcyclo(7))[1]; ? nf = nfinit( [pol, 10^3] ); ? nfcertify(nf) %3 = [] @eprog\noindent A priori, \kbd{nf.zk} defines an order which is only known to be maximal at all primes $\leq 10^{3}$ (no prime $\leq 10^{3}$ divides \kbd{nf.index}). The certification step proves the correctness of the computation. Had it failed, that particular \kbd{nf} structure could not have been trusted and may have caused routines using it to fail randomly. One particular function that remains trustworthy in all cases is \kbd{idealprimedec} when applied to a prime included in the above list of primes or, more generally, a prime not dividing any entry in \kbd{nfcertify} output. \medskip In order to explain the meaning of $\fl$, let $P = \kbd{polredbest}(\var{pol})$, a polynomial defining the same number field obtained using the LLL algorithm on the lattice $(\Z_{K}, T_{2})$, which may be equal to \var{pol} but is usually different and simpler. Binary digits of $\fl$ mean: \item $1$: return $[\var{nf},\kbd{Mod}(a,P)]$, where $\var{nf}$ is \kbd{nfinit}$(P)$ and $\kbd{Mod}(a,P)=\kbd{Mod}(x,\var{pol})$ gives the change of variables. If only this bit is set, the behaviour is useless since we have $P = \var{pol}$. \item $2$: return \kbd{nfinit}$(P)$. Both flags are set automatically when \var{pol} is not monic or not integral: first a linear change of variables is performed, to get a monic integral polynomial, then \kbd{polredbest}. \item $4$: do not LLL-reduce \kbd{nf.zk}, which saves time in large degrees, you may expect to gain a factor $2$ or so in degree $n\geq 100$ or more, at the expense of \emph{possibly} slowing down later uses of the \var{nf} structure. Use this flag if you only need basic arithmetic (the \kbd{nfelt*}, \kbd{nfmodpr*} and \kbd{ideal*} functions); or if you expect the natural basis of the maximal order to contain small elements, this will be the case for cyclotomic fields for instance. On the other hand, functions involving LLL reduction of rank $n$ lattices should be avoided since each call will be about as costly as the initial LLL reduction that the flag prevents and may become more costly because of this missing initial reduction. In particular it is silly to use this flag in addition to the first two, although GP will not protest. \bprog ? T = polcyclo(307); ? K = nfinit(T); time = 19,390 ms. ? a = idealhnf(K,1-x); time = 477ms ? idealfactor(K, a) time = 294ms ? Kno = nfinit(T, 4); time = 11,256 ms. ? ano = idealhnf(Kno,1-x); \\ no slowdown, even sligthly faster time = 460ms ? idealfactor(Kno, ano) time = 264ms ? nfinit(T, 2); \\ polredbest is very slow in high degree time = 4min, 34,870 ms. ? norml2(%.pol) == norml2(T) \\ and gains nothing here %9 = 1 @eprog 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 an or-ed combination of \item \tet{nf_RED}: find a simpler defining polynomial, \item \tet{nf_ORIG}: also return the change of variable, \item \tet{nf_NOLLL}: do not LLL-reduce the maximal order $\Z$-basis. pari-2.17.2/src/functions/number_fields/polredord0000644000175000017500000000031614567450071020527 0ustar billbillFunction: polredord Section: number_fields C-Name: polredord Prototype: G Obsolete: 2008-07-20 Help: polredord(x): this function is obsolete, use polredbest. Doc: This function is obsolete, use polredbest. pari-2.17.2/src/functions/number_fields/galoischarpoly0000644000175000017500000000227314676526175021573 0ustar billbillFunction: galoischarpoly Section: number_fields C-Name: galoischarpoly Prototype: GGD1,L, Help: galoischarpoly(gal,chi,{o=1}): return the list of characteristic polynomials of the representation attached to the character chi. Doc: Let $G$ be the group attached to the \kbd{galoisinit} structure~\var{gal}, and let $\chi$ be the character of some representation $\rho$ of the group $G$, where a polynomial variable is to be interpreted as an $o$-th root of 1, e.g., if \kbd{[T,o] = galoischartable(gal)} and $\chi$ is a column of \kbd{T}. Return the list of characteristic polynomials $\det(1 - \rho(g)T)$, where $g$ runs through representatives of the conjugacy classes in \kbd{galoisconjclasses(gal)}, with the same ordering. \bprog ? T = x^5 - x^4 - 5*x^3 + 4*x^2 + 3*x - 1; ? polgalois(T) %2 = [10, 1, 1, "D(5) = 5:2"] ? K = nfsplitting(T); ? gal = galoisinit(K); \\ dihedral of order 10 ? [T,o] = galoischartable(gal); ? o %5 = 5 ? galoischarpoly(gal, T[,1], o) \\ T[,1] is the trivial character %6 = [-x + 1, -x + 1, -x + 1, -x + 1]~ ? galoischarpoly(gal, T[,3], o) %7 = [x^2 - 2*x + 1, x^2 + (y^3 + y^2 + 1)*x + 1, -x^2 + 1, x^2 + (-y^3 - y^2)*x + 1]~ @eprog pari-2.17.2/src/functions/number_fields/idealintersect0000644000175000017500000000136114557721031021531 0ustar billbillFunction: idealintersect Section: number_fields C-Name: idealintersect Prototype: GGG Help: idealintersect(nf,A,B): intersection of two ideals A and B in the number field defined by nf. Doc: intersection of the two ideals $A$ and $B$ in the number field $\var{nf}$. The result is given in HNF. \bprog ? nf = nfinit(x^2+1); ? idealintersect(nf, 2, x+1) %2 = [2 0] [0 2] @eprog This function does not apply to general $\Z$-modules, e.g.~orders, since its arguments are replaced by the ideals they generate. The following script intersects $\Z$-modules $A$ and $B$ given by matrices of compatible dimensions with integer coefficients: \bprog ZM_intersect(A,B) = { my(Ker = matkerint(concat(A,B))); mathnf( A * Ker[1..#A,] ) } @eprog pari-2.17.2/src/functions/number_fields/bnrconductorofchar0000644000175000017500000000037214567450071022424 0ustar billbillFunction: bnrconductorofchar Section: number_fields C-Name: bnrconductorofchar Prototype: GG Obsolete: 2015-11-11 Help: bnrconductorofchar(bnr,chi): this function is obsolete, use bnrconductor. Doc: This function is obsolete, use \tev{bnrconductor}. pari-2.17.2/src/functions/number_fields/nfalgtobasis0000644000175000017500000000110414567450071021205 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)) %5 = [0, 2]~ @eprog This is the inverse function of \kbd{nfbasistoalg}. pari-2.17.2/src/functions/number_fields/bnrgaloisapply0000644000175000017500000000070414676526175021576 0ustar billbillFunction: bnrgaloisapply Section: number_fields C-Name: bnrgaloisapply Prototype: GGG Help: bnrgaloisapply(bnr,mat,H): apply the automorphism given by its matrix mat to the congruence subgroup H given as a HNF matrix. The matrix mat can be computed with bnrgaloismatrix. Doc: apply the automorphism given by its matrix \var{mat} to the congruence subgroup $H$ given as a HNF matrix. The matrix \var{mat} can be computed with \tet{bnrgaloismatrix}. pari-2.17.2/src/functions/number_fields/gcharalgebraic0000644000175000017500000000757214760123736021466 0ustar billbillFunction: gcharalgebraic Section: number_fields C-Name: gcharalgebraic Prototype: GDG Help: gcharalgebraic(gc,{type}): returns a matrix whose columns form a basis of the algebraic Grossencharacters in gc. If type is specified as a vector of integer exponents [p,q] for each complex place, returns a vector containing an algebraic character of that infinity type (or the empty vector if such a character does not exist). Doc: \var{gc} being the structure returned by \kbd{gcharinit}, returns a \typ{MAT} whose columns form a basis of the subgroup of algebraic Grossencharacters in \var{gc} (Weil type A0). The last component is interpreted as a power of the norm. If \var{type} is a \typ{VEC} of length $\var{gc}\kbd{.r1}+\var{gc}\kbd{.r2}$, containing a pair of integers $[p_{\tau},q_{\tau}]$ for each complex embedding~$\tau$, returns a \typ{VEC} containing a character whose infinity type at~$\tau$ is $$ z \mapsto z^{-p_{\tau}}\bar{z}^{-q_{\tau}} $$ if such a character exists, or empty otherwise. The full set of characters of that infinity type is obtained by multiplying by the group of finite order characters. \bprog ? bnf = bnfinit(x^4-2*x^3+23*x^2-22*x+6,1); ? gc = gcharinit(bnf,1); ? gc.cyc % = [6, 0, 0, 0, 0.E-57] ? gcharalgebraic(gc) % = [1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 0] [0 0 -1/2 -1] ? gcharalgebraic(gc,[[1,1],[0,1]]) % = [] \\ @com $p_{\tau}+q_{\tau}$ must be constant for an algebraic character to exist ? chi = gcharalgebraic(gc,[[1,1],[0,2]])[1] % = [0, 1, 2, 0, -1]~ ? for(i=0,5,print(lfuneuler([gc,chi+[i,0,0,0,0]~],3))); \\@com all characters with this infinity type: multiply by finite order characters @eprog When the torsion subgroup is not cyclic, we can enumerate the characters of a given type with \kbd{forvec}. \bprog ? bnf = bnfinit(x^4+15*x^2+45,1); ? gc = gcharinit(bnf,1); ? gc.cyc % = [2, 2, 0, 0, 0, 0.E-57] ? [chi] = gcharalgebraic(gc,[[2,0],[2,0]]); ? {forvec(v=vectorv(2,i,[0,gc.cyc[i]-1]), print(round(lfunan([gc,chi+concat(v,[0,0,0,0]~)],20))); )}; [1, 0, 0, 4, -5, 0, 0, 0, -9, 0, 16, 0, 0, 0, 0, 16, 0, 0, 16, -20] [1, 0, 0, -4, 5, 0, 0, 0, 9, 0, 16, 0, 0, 0, 0, 16, 0, 0, -16, -20] [1, 0, 0, 4, 5, 0, 0, 0, 9, 0, -16, 0, 0, 0, 0, 16, 0, 0, 16, 20] [1, 0, 0, -4, -5, 0, 0, 0, -9, 0, -16, 0, 0, 0, 0, 16, 0, 0, -16, 20] @eprog Some algebraic Hecke characters are related to CM Abelian varieties. We first show an example with an elliptic curve. \bprog ? E = ellinit([0, 0, 1, -270, -1708]); \\@com elliptic curve with potential CM by $\Q(\sqrt{-3})$ ? bnf = bnfinit(x^2+3,1); ? p3 = idealprimedec(bnf,3)[1]; ? gc = gcharinit(bnf,Mat([p3,2])); ? gc.cyc % = [0, 0.E-57] ? [chi] = gcharalgebraic(gc,[[1,0]]) % = [[-1, -1/2]~] ? LE = lfuncreate(E); ? lfunan(LE,20) % = [1, 0, 0, -2, 0, 0, -1, 0, 0, 0, 0, 0, 5, 0, 0, 4, 0, 0, -7, 0] ? Lchi = lfuncreate([gc,chi]); ? round(lfunan(Lchi,20)) % = [1, 0, 0, -2, 0, 0, -1, 0, 0, 0, 0, 0, 5, 0, 0, 4, 0, 0, -7, 0] @eprog Here is an example with a CM Abelian surface. \bprog ? L = lfungenus2([-2*x^4 - 2*x^3 + 2*x^2 + 3*x - 2, x^3]); ? bnf = bnfinit(a^4 - a^3 + 2*a^2 + 4*a + 3, 1); ? pr = idealprimedec(bnf,13)[1]; ? gc = gcharinit(bnf,pr); ? gc.cyc % = [3, 0, 0, 0, 0.E-57] ? chitors = [1,0,0,0,0]~; ? typ = [[1,0],[1,0]]; ? [chi0] = gcharalgebraic(gc,typ); ? igood = oo; nbgood = 0; ? {for(i=0,gc.cyc[1]-1, chi = chi0 + i*chitors; Lchi = lfuncreate([gc,chi]); if(lfunparams(L) == lfunparams(Lchi) && exponent(lfunan(L,10) - lfunan(Lchi,10)) < -50, igood=i; nbgood++ ); )}; ? nbgood % = 1 ? chi = chi0 + igood*chitors; ? Lchi = lfuncreate([gc,chi]); ? lfunan(L,30) % = [1, 0, -3, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -6, 0, -3, 0] ? round(lfunan(Lchi,30)) % = [1, 0, -3, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -6, 0, -3, 0] @eprog pari-2.17.2/src/functions/number_fields/nfcertify0000644000175000017500000000174414567450071020534 0ustar billbillFunction: nfcertify Section: number_fields C-Name: nfcertify Prototype: G Help: nfcertify(nf): returns a vector of composite integers used to certify nf.zk and nf.disc unconditionally (both are correct when the output is the empty vector). Doc: $\var{nf}$ being as output by \kbd{nfinit}, checks whether the integer basis is known unconditionally. This is in particular useful when the argument to \kbd{nfinit} was of the form $[T, \kbd{listP}]$, specifying a finite list of primes when $p$-maximality had to be proven, or a list of coprime integers to which Buchmann-Lenstra algorithm was to be applied. The function returns a vector of coprime composite integers. If this vector is empty, then \kbd{nf.zk} and \kbd{nf.disc} are correct. Otherwise, the result is dubious. In order to obtain a certified result, one must completely factor each of the given integers, then \kbd{addprime} each of their prime factors, then check whether \kbd{nfdisc(nf.pol)} is equal to \kbd{nf.disc}. pari-2.17.2/src/functions/number_fields/nfeltdivmodpr0000644000175000017500000000105414567450071021412 0ustar billbillFunction: nfeltdivmodpr Section: number_fields C-Name: nfdivmodpr Prototype: GGGG Obsolete: 2016-08-09 Help: nfeltdivmodpr(nf,x,y,pr): this function is obsolete, use nfmodpr. Doc: this function is obsolete, use \kbd{nfmodpr}. 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.17.2/src/functions/number_fields/ideallist0000644000175000017500000000552014710152217020500 0ustar billbillFunction: ideallist Section: number_fields C-Name: gideallist Prototype: GGD4,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; 8: omit ideals which cannot be conductors. 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. The information is inferred from local data and Chinese remainders and less expensive than computing than a direct global computation. The binary digits of $\fl$ mean: \item 1: if the ideals are given by a \var{bid}, include generators; otherwise don't. \item 2: if this bit is set, \var{nf} must be a \var{bnf} with units. Each component is of the form $[\var{bid},U]$, where \var{bid} is attached to an ideal $f$ and $U$ is a vector of discrete logarithms of the units in $(\Z_{K}/f)^{*}$. More precisely, $U$ gives the \kbd{ideallog}s with respect to \var{bid} of $(\zeta,u_{1},\dots,u_{r})$ where $\zeta$ is the torsion unit generator \kbd{bnf.tu[2]} and $(u_{i})$ are the fundamental units in \kbd{bnf.fu}. This structure is technical, meant to be used in conjunction with \tet{bnrclassnolist} or \tet{bnrdisclist}. \item 4: give only the ideal (in HNF), else a \var{bid}. \item 8: omit ideals which cannot be conductors, i.e. divisible exactly by a prime ideal of norm $2$. \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 65 in $\Z[i]$ @eprog If one wants more information: \bprog ? L = ideallist(nf, 100, 0); ? l = L[25]; vector(#l, i, l[i].clgp) %6 = [[20, [20]], [16, [4, 4]], [20, [20]]] ? l[1].mod %7 = [[25, 18; 0, 1], []] ? l[2].mod %8 = [[5, 0; 0, 5], []] ? l[3].mod %9 = [[25, 7; 0, 1], []] @eprog\noindent where we ask for the structures of the $(\Z[i]/f)^{*}$ 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. Finally, one can input a negative \kbd{bound}. The function then returns the ideals of norm $|\kbd{bound}|$, given by their factorization matrix. The only valid value of \fl\ is then the default. If needed, one can obtain their HNF using \kbd{idealfactorback}, and the corresponding \var{bid} structures using \kbd{idealstar} (which accepts ideals in factored form). Variant: Also available is \fun{GEN}{ideallist0}{GEN nf,long bound, long flag} for a non-negative bound. pari-2.17.2/src/functions/number_fields/bnrclassnolist0000644000175000017500000000223714557721031021575 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.17.2/src/functions/number_fields/nfroots0000644000175000017500000000323314567450071020230 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 then be computed internally. This is useful in two situations: when you do not need the \kbd{nf} elsewhere, or when you cannot initialize an \kbd{nf} due to integer factorization difficulties when attempting to compute the field discriminant and maximal order. \misctitle{Caveat} \kbd{nfinit([T, listP])} allows to compute in polynomial time a conditional \var{nf} structure, which sets \kbd{nf.zk} to an order which is not guaranteed to be maximal at all primes. Always either use \kbd{nfcertify} first (which may not run in polynomial time) or make sure to input \kbd{nf.pol} instead of the conditional \var{nf}: \kbd{nfroots} is able to recover in polynomial time in this case, instead of potentially missing a factor. Variant: See also \fun{GEN}{nfrootsQ}{GEN x}, corresponding to $\kbd{nf} = \kbd{NULL}$. pari-2.17.2/src/functions/number_fields/bnfisunit0000644000175000017500000000650314676526175020554 0ustar billbillFunction: bnfisunit Section: number_fields C-Name: bnfisunit0 Prototype: GGDG Help: bnfisunit(bnf,x,{U}): bnf being output by bnfinit, give 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. If U is present, as given by bnfunits, decompose x on the attached S-units generators. Doc: \var{bnf} being the number field data output by \kbd{bnfinit} and $x$ being an algebraic number (type integer, rational or polmod), this outputs the decomposition of $x$ on the fundamental units and the roots of unity if $x$ is a unit, the empty vector otherwise. More precisely, if $u_{1}$,\dots,$u_{r}$ are the fundamental units, and $\zeta$ is the generator of the group of roots of unity (\kbd{bnf.tu}), the output is a vector $[x_{1},\dots,x_{r},x_{r+1}]$ such that $x=u_{1}^{x_{1}}\cdots u_{r}^{x_{r}}\cdot\zeta^{x_{r+1}}$. The $x_{i}$ are integers but the last one ($i = r+1$) is only defined modulo the order $w$ of $\zeta$ and is guaranteed to be in $[0,w[$. Note that \var{bnf} need not contain the fundamental units explicitly: it may contain the placeholder $0$ instead: \bprog ? setrand(1); bnf = bnfinit(x^2-x-100000); ? bnf.fu %2 = 0 ? u = [119836165644250789990462835950022871665178127611316131167, \ 379554884019013781006303254896369154068336082609238336]~; ? bnfisunit(bnf, u) %3 = [-1, 0]~ @eprog\noindent The given $u$ is $1/u_{1}$, where $u_{1}$ is the fundamental unit implicitly stored in \var{bnf}. In this case, $u_{1}$ was not computed and stored in algebraic form since the default accuracy was too low. Re-run the \kbd{bnfinit} command at \kbd{\bs g1} or higher to see such diagnostics. This function allows $x$ to be given in factored form, but it then assumes that $x$ is an actual unit. (Because it is general too costly to check whether this is the case.) \bprog ? { v = [2, 85; 5, -71; 13, -162; 17, -76; 23, -37; 29, -104; [224, 1]~, -66; [-86, 1]~, 86; [-241, 1]~, -20; [44, 1]~, 30; [124, 1]~, 11; [125, -1]~, -11; [-214, 1]~, 33; [-213, -1]~, -33; [189, 1]~, 74; [190, -1]~, 104; [-168, 1]~, 2; [-167, -1]~, -8]; } ? bnfisunit(bnf,v) %5 = [1, 0]~ @eprog\noindent Note that $v$ is the fundamental unit of \kbd{bnf} given in compact (factored) form. If the argument \kbd{U} is present, as output by \kbd{bnfunits(bnf, S)}, then the function decomposes $x$ on the $S$-units generators given in \kbd{U[1]}. \bprog ? bnf = bnfinit(x^4 - x^3 + 4*x^2 + 3*x + 9, 1); ? bnf.sign %2 = [0, 2] ? S = idealprimedec(bnf,5); #S %3 = 2 ? US = bnfunits(bnf,S); ? g = US[1]; #g \\ #S = #g, four S-units generators, in factored form %5 = 4 ? g[1] %6 = [[6, -3, -2, -2]~ 1] ? g[2] %7 = [[-1, 1/2, -1/2, -1/2]~ 1] [ [4, -2, -1, -1]~ 1] ? [nffactorback(bnf, x) | x <- g] %8 = [[6, -3, -2, -2]~, [-5, 5, 0, 0]~, [-1, 1, -1, 0]~, [1, -1, 0, 0]~] ? u = [10,-40,24,11]~; ? a = bnfisunit(bnf, u, US) %9 = [2, 0, 1, 4]~ ? nffactorback(bnf, g, a) \\ prod_i g[i]^a[i] still in factored form %10 = [[6, -3, -2, -2]~ 2] [ [0, 0, -1, -1]~ 1] [ [2, -1, -1, 0]~ -2] [ [1, 1, 0, 0]~ 2] [ [-1, 1, 1, 1]~ -1] [ [1, -1, 0, 0]~ 4] ? nffactorback(bnf,%) \\ u = prod_i g[i]^a[i] %11 = [10, -40, 24, 11]~ @eprog Variant: Also available is \fun{GEN}{bnfisunit}{GEN bnf, GEN x} for $U = \kbd{NULL}$. pari-2.17.2/src/functions/number_fields/rnfnormgroup0000644000175000017500000000233714567450071021300 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, but the function will return the empty matrix \kbd{[;]} if it detects a problem; it may also not detect the problem and return a wrong result. pari-2.17.2/src/functions/number_fields/idealval0000644000175000017500000000103614567450071020316 0ustar billbillFunction: idealval Section: number_fields C-Name: gpidealval Prototype: GGG Help: idealval(nf,x,pr): valuation at pr given in idealprimedec format of the ideal x in the number field nf. Doc: gives the valuation of the ideal $x$ at the prime ideal \var{pr} in the number field $\var{nf}$, where \var{pr} is in \kbd{idealprimedec} format. The valuation of the $0$ ideal is \kbd{+oo}. Variant: Also available is \fun{long}{idealval}{GEN nf, GEN x, GEN pr}, which returns \tet{LONG_MAX} if $x = 0$ and the valuation as a \kbd{long} integer. pari-2.17.2/src/functions/number_fields/nfeltmod0000644000175000017500000000064714567450071020354 0ustar billbillFunction: nfeltmod Section: number_fields C-Name: nfmod Prototype: GGG Help: nfeltmod(nf,x,y): gives r such that r=x-qy 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.17.2/src/functions/number_fields/idealinv0000644000175000017500000000063613637407207020335 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.17.2/src/functions/number_fields/bnfnarrow0000644000175000017500000000151114567450071020531 0ustar billbillFunction: bnfnarrow Section: number_fields C-Name: bnfnarrow 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}: 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 \var{bnf} need not contain fundamental units. pari-2.17.2/src/functions/number_fields/subgrouplist0000644000175000017500000000505314676526175021314 0ustar billbillFunction: subgrouplist Section: number_fields C-Name: subgrouplist0 Prototype: GDGD0,L, Help: subgrouplist(cyc,{bound},{flag=0}): cyc being any object which has a '.cyc' method giving the cyclic components for 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 'cyc' is a bnr struture output by bnrinit, gives only the subgroups for which the modulus is the conductor. Doc: \var{cyc} being a vector of positive integers giving the cyclic components for a finite Abelian group $G$ (or any object which has a \kbd{.cyc} method), 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{cyc} is a \var{bnr} structure output by \kbd{bnrinit}, gives only the subgroups whose modulus is the conductor. Otherwise, all subgroups are given. 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{bnrclassfield}.) \misctitle{Warning} This function requires factoring the exponent of $G$. If you are only interested in subgroups of index $n$ (or dividing $n$), you may considerably speed up the function by computing the subgroups of $G/G^{n}$, whose cyclic components are \kbd{apply(x->gcd(n,x), C)} (where $C$ gives the cyclic components of $G$). If you want the \var{bnr} variant, now is a good time to use \kbd{bnrinit(,,, n)} as well, to directly compute the ray class group modulo $n$-th powers. pari-2.17.2/src/functions/number_fields/rnfidealnormrel0000644000175000017500000000067514567450071021730 0ustar billbillFunction: rnfidealnormrel Section: number_fields C-Name: rnfidealnormrel Prototype: GG Help: rnfidealnormrel(rnf,x): relative norm of the ideal x. Doc: let $\var{rnf}$ be a relative number field extension $L/K$ as output by \kbd{rnfinit} and let $x$ be a relative ideal (which can be, as in the absolute case, of many different types, including of course elements). This function computes the relative norm of $x$ as an ideal of $K$ in HNF. pari-2.17.2/src/functions/number_fields/nfmodprinit0000644000175000017500000000242314760123736021067 0ustar billbillFunction: nfmodprinit Section: number_fields C-Name: nfmodprinit0 Prototype: GGDn Help: nfmodprinit(nf,pr,{v=variable(nf.pol)}): transform the prime ideal pr into modpr format necessary for all operations mod pr in the number field nf. Variable v is used to display finite field elements (see ffgen). Doc: transforms the prime ideal \var{pr} into \tet{modpr} format necessary for all operations modulo \var{pr} in the number field \var{nf}. The functions \tet{nfmodpr} and \tet{nfmodprlift} allow to project to and lift from the residue field. The variable $v$ is used to display finite field elements (see \kbd{ffgen}). \bprog ? K = nfinit(y^3-250); ? P = idealprimedec(K, 5)[2]; ? modP = nfmodprinit(K, P, 't); ? K.zk %4 = [1, 1/5*y, 1/25*y^2] ? apply(t->nfmodpr(K,t,modP), K.zk) %5 = [1, t, 2*t + 1] ? %[1].mod %6 = t^2 + 3*t + 4 ? K.index %7 = 125 @eprog\noindent For clarity, we represent elements in the residue field $\F_{5}[t]/(T)$ as polynomials in the variable $t$. Whenever the underlying rational prime does not divide \kbd{K.index}, it is actually the case that $t$ is the reduction of $y$ in $\Q[y]/(\kbd{K.pol})$ modulo an irreducible factor of \kbd{K.pol} over $\F_{p}$. In the above example, $5$ divides the index and $t$ is actually the reduction of $y/5$. pari-2.17.2/src/functions/number_fields/polgalois0000644000175000017500000001052114676526175020537 0ustar billbillFunction: polgalois Section: number_fields C-Name: polgalois Prototype: Gp Help: polgalois(T): Galois group of the polynomial T (see manual for group coding). Return [n, s, k, name] where n is the group order, s the signature, k the index and name is the GAP4 name of the transitive group. Doc: \idx{Galois} group of the nonconstant polynomial $T\in\Q[X]$. In the present version \vers, $T$ must be irreducible and the degree $d$ of $T$ must be less than or equal to 7. If the \tet{galdata} package has been installed, degrees 8, 9, 10 and 11 are also implemented. By definition, if $K = \Q[x]/(T)$, this computes the action of the Galois group of the Galois closure of $K$ on the $d$ distinct roots of $T$, up to conjugacy (corresponding to different root orderings). The output is a 4-component vector $[n,s,k,name]$ with the following meaning: $n$ is the cardinality of the group, $s$ is its signature ($s=1$ if the group is a subgroup of the alternating group $A_{d}$, $s=-1$ otherwise) and name is a character string containing name of the transitive group according to the GAP 4 transitive groups library by Alexander Hulpke. $k$ is more arbitrary and the choice made up to version~2.2.3 of PARI is rather unfortunate: for $d > 7$, $k$ is the numbering of the group among all transitive subgroups of $S_{d}$, as given in ``The transitive groups of degree up to eleven'', G.~Butler and J.~McKay, \emph{Communications in Algebra}, vol.~11, 1983, pp.~863--911 (group $k$ is denoted $T_{k}$ there). And for $d \leq 7$, it was ad hoc, so as to ensure that a given triple would denote a unique group. Specifically, for polynomials of degree $d\leq 7$, the groups are coded as follows, using standard notations \smallskip In degree 1: $S_{1}=[1,1,1]$. \smallskip In degree 2: $S_{2}=[2,-1,1]$. \smallskip In degree 3: $A_{3}=C_{3}=[3,1,1]$, $S_{3}=[6,-1,1]$. \smallskip In degree 4: $C_{4}=[4,-1,1]$, $V_{4}=[4,1,1]$, $D_{4}=[8,-1,1]$, $A_{4}=[12,1,1]$, $S_{4}=[24,-1,1]$. \smallskip In degree 5: $C_{5}=[5,1,1]$, $D_{5}=[10,1,1]$, $M_{20}=[20,-1,1]$, $A_{5}=[60,1,1]$, $S_{5}=[120,-1,1]$. \smallskip In degree 6: $C_{6}=[6,-1,1]$, $S_{3}=[6,-1,2]$, $D_{6}=[12,-1,1]$, $A_{4}=[12,1,1]$, $G_{18}=[18,-1,1]$, $S_{4}^{-}=[24,-1,1]$, $A_{4}\times C_{2}=[24,-1,2]$, $S_{4}^{+}=[24,1,1]$, $G_{36}^{-}=[36,-1,1]$, $G_{36}^{+}=[36,1,1]$, $S_{4}\times C_{2}=[48,-1,1]$, $A_{5}=PSL_{2}(5)=[60,1,1]$, $G_{72}=[72,-1,1]$, $S_{5}=PGL_{2}(5)=[120,-1,1]$, $A_{6}=[360,1,1]$, $S_{6}=[720,-1,1]$. \smallskip In degree 7: $C_{7}=[7,1,1]$, $D_{7}=[14,-1,1]$, $M_{21}=[21,1,1]$, $M_{42}=[42,-1,1]$, $PSL_{2}(7)=PSL_{3}(2)=[168,1,1]$, $A_{7}=[2520,1,1]$, $S_{7}=[5040,-1,1]$. \smallskip This is deprecated and obsolete, but for reasons of backward compatibility, we cannot change this behavior yet. So you can use the default \tet{new_galois_format} to switch to a consistent naming scheme, namely $k$ is always the standard numbering of the group among all transitive subgroups of $S_{n}$. If this default is in effect, the above groups will be coded as: \smallskip In degree 1: $S_{1}=[1,1,1]$. \smallskip In degree 2: $S_{2}=[2,-1,1]$. \smallskip In degree 3: $A_{3}=C_{3}=[3,1,1]$, $S_{3}=[6,-1,2]$. \smallskip In degree 4: $C_{4}=[4,-1,1]$, $V_{4}=[4,1,2]$, $D_{4}=[8,-1,3]$, $A_{4}=[12,1,4]$, $S_{4}=[24,-1,5]$. \smallskip In degree 5: $C_{5}=[5,1,1]$, $D_{5}=[10,1,2]$, $M_{20}=[20,-1,3]$, $A_{5}=[60,1,4]$, $S_{5}=[120,-1,5]$. \smallskip In degree 6: $C_{6}=[6,-1,1]$, $S_{3}=[6,-1,2]$, $D_{6}=[12,-1,3]$, $A_{4}=[12,1,4]$, $G_{18}=[18,-1,5]$, $A_{4}\times C_{2}=[24,-1,6]$, $S_{4}^{+}=[24,1,7]$, $S_{4}^{-}=[24,-1,8]$, $G_{36}^{-}=[36,-1,9]$, $G_{36}^{+}=[36,1,10]$, $S_{4}\times C_{2}=[48,-1,11]$, $A_{5}=PSL_{2}(5)=[60,1,12]$, $G_{72}=[72,-1,13]$, $S_{5}=PGL_{2}(5)=[120,-1,14]$, $A_{6}=[360,1,15]$, $S_{6}=[720,-1,16]$. \smallskip In degree 7: $C_{7}=[7,1,1]$, $D_{7}=[14,-1,2]$, $M_{21}=[21,1,3]$, $M_{42}=[42,-1,4]$, $PSL_{2}(7)=PSL_{3}(2)=[168,1,5]$, $A_{7}=[2520,1,6]$, $S_{7}=[5040,-1,7]$. \smallskip \misctitle{Warning} The method used is that of resolvent polynomials and is sensitive to the current precision. The precision is updated internally but, in very rare cases, a wrong result may be returned if the initial precision was not sufficient. Variant: To enable the new format in library mode, set the global variable \tet{new_galois_format} to $1$. pari-2.17.2/src/functions/number_fields/nfkermodpr0000644000175000017500000000073514676526175020723 0ustar billbillFunction: nfkermodpr Section: number_fields C-Name: nfkermodpr Prototype: GGG Obsolete: 2016-08-09 Help: nfkermodpr(nf,x,pr): this function is obsolete, use nfmodpr. Doc: this function is obsolete, use \kbd{nfmodpr}. 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.17.2/src/functions/number_fields/gcharconductor0000644000175000017500000000214414676526175021555 0ustar billbillFunction: gcharconductor Section: number_fields C-Name: gchar_conductor Prototype: GG Help: gcharconductor(gc,chi): returns the conductor of chi, as a modulus over gc.bnf. Doc: returns the conductor of \kbd{chi}, as a modulus over \kbd{gc.bnf}. This is the minimum modulus $\goth{m}$ such that $U(\goth{m})\subset\text{ker}(\var{chi})$ indicating the exact ramification of \var{chi}. \item for a real place $v$, $v\mid \goth{m}$ iff $\chi_{v}(-1)=-1$. \item for a finite place~$\goth{p}$, the prime power~$\goth{p}^{e}$ divides exactly $\goth{m}$ if $e\ge 0$ is the smallest integer such that $\chi_{\goth{p}} (U_{e})=1$ where~$U_{0} = \Z_{\goth{p}}^{\times}$ and~$U_{i} = 1+\goth{p}^{i}\Z_{\goth{p}}$ for~$i>0$. \bprog ? bnf = bnfinit(x^2-5,1); ? gc = gcharinit(bnf,[(13*19)^2,[1,1]]); ? gc.cyc % = [8892, 6, 2, 0, 0.E-57] ? chi = [0,0,1,1]~; ? gcharconductor(gc,chi) % = [[61009, 7267; 0, 169], [1, 0]] ? gcharconductor(gc,13*chi) % = [[4693, 559; 0, 13], [1, 0]] ? gcharconductor(gc,13*19*chi) % = [[247, 65; 0, 13], [1, 0]] ? gcharconductor(gc,13*19*168*chi) % = [[19, 5; 0, 1], [0, 0]] @eprog pari-2.17.2/src/functions/number_fields/idealfactor0000644000175000017500000000223414567450071021013 0ustar billbillFunction: idealfactor Section: number_fields C-Name: gpidealfactor Prototype: GGDG Help: idealfactor(nf,x,{lim}): factorization of the ideal x into prime ideals in the number field nf. If lim is set return partial factorization, using primes < lim. 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. If \var{lim} is set, return partial factorization, including only prime ideals above rational primes $< \var{lim}$. \bprog ? nf = nfinit(x^3-2); ? idealfactor(nf, x) \\ a prime ideal above 2 %2 = [[2, [0, 1, 0]~, 3, 1, ...] 1] ? A = idealhnf(nf, 6*x, 4+2*x+x^2) %3 = [6 0 4] [0 6 2] [0 0 1] ? idealfactor(nf, A) %4 = [[2, [0, 1, 0]~, 3, 1, ...] 2] [[3, [1, 1, 0]~, 3, 1, ...] 2] ? idealfactor(nf, A, 3) \\ restrict to primes above p < 3 %5 = [[2, [0, 1, 0]~, 3, 1, ...] 2] @eprog Variant: This function should only be used by the \kbd{gp} interface. Use directly \fun{GEN}{idealfactor}{GEN nf, GEN x} or \fun{GEN}{idealfactor_limit}{GEN nf, GEN x, ulong lim}. pari-2.17.2/src/functions/number_fields/subcyclohminus0000644000175000017500000000757614676526175021635 0ustar billbillFunction: subcyclohminus Section: number_fields C-Name: subcyclohminus Prototype: GDG Help: subcyclohminus(fH,{p=0}): Let F be the abelian number field contained in Q(zeta_f) corresponding to the subgroup H of (Z/fZ)^*. Let h be the relative class number h^-(F) and Q the Hasse unit index in {1,2}. If Q could be computed, returns [h, Q]; else returns [2h/Q, 0]. Doc: Let $F$ be the abelian number field contained in $\Q(\zeta_{f})$ corresponding to the subgroup $H$ of $(\Z/f\Z)^{*}$. Computes the relative class number $h^{-}(F)=h(F)/h(F^{+})$ of $F$. The argument \kbd{fH} encodes $F$ and the data $[f,H]$ as follows: \item $\kbd{fH} = [f, H]$, where $H$ is given by a vector of integral generators, \item $\kbd{fH} = [\var{bnr}, H]$, where \var{bnr} is attached to $\Cl_{f}(\Q)$ and $H$ is a congruence subgroup, \item $\kbd{fH} = [G, H]$, where $G$ is \kbd{idealstar}$(f,1)$, and $H$ is a subgroup of $(\Z/f\Z)^{\times}$, \item $\kbd{fH} = f$, where we assume that $H = \{1\}$, i.e., $F = \Q(\zeta_{f})$, \item an irreducible integral polynomial defining a primitive element for $F$. The algorithm is based on an analytic class number formula: $$h^{-}(F)=Q(F)w(F)\prod_{K\subset F}N_{\Q(\zeta_{d})/\Q} \Bigl(-B_{1,\chi}/2\Bigr)\;,$$ where $Q(F)$ is the unit index of $F$, $w(F)$ is the number of roots of unity contained in $F$ and $K$ runs through all imaginary cyclic subfields of $F$. For each $K$, $d$ is the degree $[K:\Q]$, $\chi$ is an arbitrary injective character of $G(K/\Q)$ to $\C^{\times}$ and the Bernoulli number is given by $$B_{1,\chi}=(1/f_{\chi})\sum_{a=1}^{f_{\chi}}a\chi(a)= -(1/(2-\overline{\chi}(2)) \sum_{1\leq a\leq f_{\chi}/2}\chi(a)\;,$$ where $f_{\chi}$ is the conductor of $\chi$, namely the conductor of $K$. The unit index $Q\in\{1,2\}$ is difficult to determine in general. If it could be computed, the function returns $[a, b] = [h^{-}, Q]$; else it returns $[2h^{-}/Q, 0]$. More precisely, the second component is $0$ unless we are in one of the following cases: \item If $f=p^{a}$ with a prime number $p$, then $Q=1$. \item If $F=\Q(\zeta_{f})$, then $Q=1$ if and only if $f=p^{a}$. \item If $f=4p^{a}$ or $p^{a}q^{b}$ with odd prime numbers $p,\,q$, then $Q=1$ if and only if $[\Q(\zeta_{f}):F]$ is even. Finally, the optional parameter $p$ is an \emph{odd} prime number. If $p$ is given, then \kbd{subcyclohminus} outputs the valuation at $p$ of $h^{-}(F)$, in other words the maximal integer $e$ such that $p^{e}\,|\,h^{-}(F)$ by evaluating $p$-adic valuations of Bernoulli numbers. Since $p$ is odd and $Q\in \{1,2\}$, the latter can be disregarded and the result is the same as \kbd{valuation(subcyclohminus(f,H)[1], p)}, but adding this argument $p$ can be much faster when $p$ does not divide $[F:\Q]$ or if a high power of $p$ divides $[F:\Q]$. \bprog ? [a,b] = subcyclohminus(22220); b %1 = 2 \\ = Q ? sizedigit(a) %2 = 4306 \\ huge... ? valuation(a, 101) %3 = 41 ? subcyclohminus(22220, 101) \\ directly compute the valuation %4 = 41 @eprog\noindent shows that $101^{41}$ divides $h^{-}(\Q(\zeta_{22220}))$ exactly. Let $k_{n}$ be the $n$-th layer of the cyclotomic $\Z_{3}$-extension of $k=\Q(\sqrt{-1501391})$; the following computes $e_{n}$ for $1 \leq n \leq 3$, where $3^{e_{n}}$ is the $3$-part of the relative class number $h^{-}(k_{n})$: \bprog ? d = 1501391; ? subcyclohminus([9*d, [28,10,8]], 3) %1 = 5 ? subcyclohminus([27*d, [28,188,53]], 3) %2 = 12 ? subcyclohminus([81*d, [161,80,242]], 3) %3 = 26 @eprog\noindent Note that $h^{+}(k_{n})$ is prime to $3$ for all $n\geq 0$. The following example computes the $3$-part of $h^{-}(F)$, where $F$ is the subfield of the $7860079$-th cyclotomic field with degree $2\cdot 3^{8}$. \bprog ? p=7860079; a=znprimroot(p)^(2*3^8); ? valuation(subcyclohminus([p,a])[1], 3) time = 1min, 47,896 ms. %2 = 65 ? subcyclohminus([p,a], 3) time = 1,290 ms. %3 = 65 @eprog\noindent pari-2.17.2/src/functions/number_fields/rnflllgram0000644000175000017500000000121013637407207020667 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.17.2/src/functions/number_fields/ideallistarch0000644000175000017500000000331414676526175021360 0ustar billbillFunction: ideallistarch Section: number_fields C-Name: ideallistarch Prototype: GGG Help: ideallistarch(nf,list,arch): list is a vector of vectors 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 $(\Z_{K}/f)^{*}$. 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]; %4 = [2, 12, 2] @eprog pari-2.17.2/src/functions/number_fields/bnflogef0000644000175000017500000000175014676526175020334 0ustar billbillFunction: bnflogef Section: number_fields C-Name: bnflogef Prototype: GG Help: bnflogef(nf,pr): return [e~, f~] the logarithmic ramification and residue degrees for the maximal ideal pr. Doc: let \var{nf} be a \var{nf} structure attached to a number field $F$ and let \var{pr} be a \var{prid} structure attached to a maximal ideal $\goth{p} / p$. Return $[\tilde{e}(F_{\goth{p}} / \Q_{p}), \tilde{f}(F_{\goth{p}} / \Q_{p})]$ the logarithmic ramification and residue degrees. Let $\Q_{p}^{c}/\Q_{p}$ be the cyclotomic $\Z_{p}$-extension, then $\tilde{e} = [F_{\goth{p}} \colon F_{\goth{p}} \cap \Q_{p}^{c}]$ and $\tilde{f} = [F_{\goth{p}} \cap \Q_{p}^{c} \colon \Q_{p}]$. Note that $\tilde{e}\tilde{f} = e(\goth{p}/p) f(\goth{p}/p)$, where $e(\goth{p}/p)$ and $f(\goth{p}/p)$ denote the usual ramification and residue degrees. \bprog ? F = nfinit(y^6 - 3*y^5 + 5*y^3 - 3*y + 1); ? bnflogef(F, idealprimedec(F,2)[1]) %2 = [6, 1] ? bnflogef(F, idealprimedec(F,5)[1]) %3 = [1, 2] @eprog pari-2.17.2/src/functions/number_fields/bnrrootnumber0000644000175000017500000000264214676526175021451 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 attached 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 attached \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 attached to $L$. 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]]); 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}^{a}g_{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.17.2/src/functions/number_fields/factornf0000644000175000017500000000250114567450071020335 0ustar billbillFunction: factornf Section: number_fields C-Name: polfnf Prototype: GG Obsolete: 2016-08-08 Help: factornf(x,t): this function is obsolete, use nffactor. Doc: This function is obsolete, use \kbd{nffactor}. 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 nonrational 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.17.2/src/functions/number_fields/nfeltembed0000644000175000017500000000223014676526175020651 0ustar billbillFunction: nfeltembed Section: number_fields C-Name: nfeltembed Prototype: GGDGp Help: nfeltembed(nf,x,{pl}): complex embeddings of x at places given by vector pl. Doc: given an element $x$ in the number field \var{nf}, return the (real or) complex embeddings of $x$ specified by optional argument \var{pl}, at the current \kbd{realprecision}: \item \var{pl} omitted: return the vector of embeddings at all $r_{1}+r_{2}$ places; \item \var{pl} an integer between $1$ and $r_{1}+r_{2}$: return the $i$-th embedding of $x$, attached to the $i$-th root of \kbd{nf.pol}, i.e. \kbd{nf.roots$[i]$}; \item \var{pl} a vector or \typ{VECSMALL}: return the vector of embeddings; the $i$-th entry gives the embedding at the place attached to the $\var{pl}[i]$-th real root of \kbd{nf.pol}. \bprog ? nf = nfinit('y^3 - 2); ? nf.sign %2 = [1, 1] ? nfeltembed(nf, 'y) %3 = [1.25992[...], -0.62996[...] + 1.09112[...]*I]] ? nfeltembed(nf, 'y, 1) %4 = 1.25992[...] ? nfeltembed(nf, 'y, 3) \\ there are only 2 arch. places *** at top-level: nfeltembed(nf,'y,3) *** ^----------------- *** nfeltembed: domain error in nfeltembed: index > 2 @eprog pari-2.17.2/src/functions/number_fields/idealtwoelt0000644000175000017500000000375314676526175021074 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 nonzero, first element will be equal to a. Doc: computes a two-element representation of the ideal $x$ in the number field $\var{nf}$, combining a random search and an approximation theorem; $x$ is an ideal in any form (possibly an extended ideal, whose principal part is ignored) \item When called as \kbd{idealtwoelt(nf,x)}, the result is a row vector $[a,\alpha]$ with two components such that $x=a\Z_{K}+\alpha\Z_{K}$ and $a$ is chosen to be the positive generator of $x\cap\Z$, unless $x$ was given as a principal ideal in which case we may choose $a = 0$. The algorithm uses a fast lazy factorization of $x\cap \Z$ and runs in randomized polynomial time. \bprog ? K = nfinit(t^5-23); ? x = idealhnf(K, t^2*(t+1), t^3*(t+1)) %2 = \\ some random ideal of norm 552*23 [552 23 23 529 23] [ 0 23 0 0 0] [ 0 0 1 0 0] [ 0 0 0 1 0] [ 0 0 0 0 1] ? [a,alpha] = idealtwoelt(K, x) %3 = [552, [23, 0, 1, 0, 0]~] ? nfbasistoalg(K, alpha) %4 = Mod(t^2 + 23, t^5 - 23) @eprog \item When called as \kbd{idealtwoelt(nf,x,a)} with an explicit nonzero $a$ supplied as third argument, the function assumes that $a \in x$ and returns $\alpha\in x$ such that $x = a\Z_{K} + \alpha\Z_{K}$. Note that we must factor $a$ in this case, and the algorithm is generally slower than the default variant and gives larger generators: \bprog ? alpha2 = idealtwoelt(K, x, 552) %5 = [-161, -161, -183, -207, 0]~ ? idealhnf(K, 552, alpha2) == x %6 = 1 @eprog\noindent Note that, in both cases, the return value is \emph{not} recognized as an ideal by GP functions; one must use \kbd{idealhnf} as above to recover a valid ideal structure from the two-element representation. Variant: Also available are \fun{GEN}{idealtwoelt}{GEN nf, GEN x} and \fun{GEN}{idealtwoelt2}{GEN nf, GEN x, GEN a}. pari-2.17.2/src/functions/number_fields/nfeltpow0000644000175000017500000000054414676526175020410 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.17.2/src/functions/number_fields/polred0000644000175000017500000000347414760123736020032 0ustar billbillFunction: polred Section: number_fields C-Name: polred0 Prototype: GD0,L,DG Obsolete: 2013-03-27 Help: polred(T,{flag=0}): deprecated, use polredbest. Reduction of the polynomial T (gives minimal polynomials only). The following binary digits of (optional) flag are significant 1: partial reduction, 2: gives also elements. Doc: This function is \emph{deprecated}, use \tet{polredbest} instead. Finds polynomials with reasonably small coefficients defining subfields of the number field defined by $T$. One of the polynomials always defines $\Q$ (hence has degree $1$), and another always defines the same number field as $T$ if $T$ is irreducible. All $T$ accepted by \tet{nfinit} are also allowed here; in particular, the format \kbd{[T, listP]} is recommended, e.g. with $\kbd{listP} = 10^{5}$ or a vector containing all ramified primes. Otherwise, the maximal order of $\Q[x]/(T)$ must be computed. The following binary digits of $\fl$ are significant: 1: Possibly use a suborder of the maximal order. The primes dividing the index of the order chosen are larger than \tet{primelimit} or divide integers stored in the \tet{addprimes} table. This flag is \emph{deprecated}, the \kbd{[T, listP]} format is more flexible. 2: gives also elements. The result is a two-column matrix, the first column giving primitive elements defining these subfields, the second giving the corresponding minimal polynomials. \bprog ? M = polred(x^4 + 8, 2) %1 = [ 1 x - 1] [ 1/2*x^2 + 1 x^2 - 2*x + 3] [-1/2*x^2 + 1 x^2 - 2*x + 3] [ 1/2*x^2 x^2 + 2] [ 1/4*x^3 x^4 + 2] ? minpoly(Mod(M[4,1], x^4+8)) %2 = x^2 + 2 @eprog \synt{polred}{GEN T} ($\fl = 0$). Also available is \fun{GEN}{polred2}{GEN T} ($\fl = 2$). The function \kbd{polred0} is deprecated, provided for backward compatibility. pari-2.17.2/src/functions/number_fields/nfresolvent0000644000175000017500000000436514676526175021124 0ustar billbillFunction: nfresolvent Section: number_fields C-Name: nfresolvent Prototype: GD0,L, Help: nfresolvent(pol,{flag=0}): In the case where the Galois closure of the number field defined by pol is S3, Dl, A4, S4, F5, A5, M21, or M42, gives the corresponding resolvent field. Otherwise, give a "canonical" subfield, or if flag >= 2 all "canonical" subfields. If flag is odd, give also the "conductor" f, whose definition is specific to each group. Doc: Let \kbd{pol} be an irreducible integral polynomial defining a number field $K$ with Galois closure $\tilde{K}$. This function is limited to the Galois groups supported by \kbd{nflist}; in the following $\ell$ denotes an odd prime. If $\text{Gal}(\tilde{K}/\Q)$ is $D_{\ell}$, $A_{4}$, $S_{4}$, $F_{5}$ ($M_{20}$), $A_{5}$, $M_{21}$ or $M_{42}$, returns a polynomial $R$ defining the corresponding resolvent field (quadratic for $D_{\ell}$, cyclic cubic for $A_{4}$ and $M_{21}$, noncyclic cubic for $S_{4}$, cyclic quartic for $F_{5}$, $A_{5}(6)$ sextic for $A_{5}$, and cyclic sextic for $M_{42}$). In the $A_{5}(6)$ case, returns the $A_{5}$ field of which it is the resolvent. Otherwise, gives a ``canonical'' subfield, or $0$ if the Galois group is not supported. The binary digits of \fl\ correspond to 1: returns a pair $[R,f]$ where $f$ is a ``conductor'' whose definition is specific to each group and given below; 2: returns all ``canonical'' subfields. Let $D$ be the discriminant of the resolvent field \kbd{nfdisc}$(R)$: \item In cases $C_{\ell}$, $D_{\ell}$, $A_{4}$, or $S_{4}$, $\text{disc}(K) =(Df^{2})^{m}$ with $m=(\ell-1)/2$ in the first two cases, and $1$ in the last two. \item In cases where $K$ is abelian over the resolvent subfield, the conductor of the relative extension. \item In case $F_{5}$, $\text{disc}(K)=Df^{4}$ if $f>0$ or $5^{2}Df^{4}$ if $f<0$. \item In cases $M_{21}$ or $M_{42}$, $\text{disc}(K)=D^{m}f^{6}$ if $f>0$ or $7^{3}D^{m}f^{6}$ if $f<0$, where $m=2$ for $M_{21}$ and $m=1$ for $M_{42}$. \item In cases $A_{5}$ and $A_{5}(6)$, $\fl$ is currently ignored. \bprog ? pol = x^6-3*x^5+7*x^4-9*x^3+7*x^2-3*x+1; \\ Galois closure D_6 ? nfresolvent(pol) %2 = x^3 + x - 1 ? nfresolvent(pol,1) %3 = [x^3 + x - 1, [[31, 21, 3; 0, 1, 0; 0, 0, 1], [1]]] @eprog pari-2.17.2/src/functions/number_fields/rnfidealreltoabs0000644000175000017500000000316514676526175022074 0ustar billbillFunction: rnfidealreltoabs Section: number_fields C-Name: rnfidealreltoabs0 Prototype: GGD0,L, Help: rnfidealreltoabs(rnf,x,{flag=0}): transforms the ideal x from relative to absolute representation. As a vector of t_POLMODs if flag = 0 and as an ideal in HNF in the absolute field if flag = 1. Doc: Let $\var{rnf}$ be a relative number field extension $L/K$ as output by \kbd{rnfinit} and let $x$ be a relative ideal, given as a $\Z_{K}$-module by a pseudo matrix $[A,I]$. This function returns the ideal $x$ as an absolute ideal of $L/\Q$. If $\fl = 0$, the result is given by a vector of \typ{POLMOD}s modulo \kbd{rnf.pol} forming a $\Z$-basis; if $\fl = 1$, it is given in HNF in terms of the fixed $\Z$-basis for $\Z_{L}$, see \secref{se:rnfinit}. \bprog ? K = nfinit(y^2+1); rnf = rnfinit(K, x^2-y); ? P = idealprimedec(K,2)[1]; ? P = rnfidealup(rnf, P) %3 = [2, x^2 + 1, 2*x, x^3 + x] ? Prel = rnfidealhnf(rnf, P) %4 = [[1, 0; 0, 1], [[2, 1; 0, 1], [2, 1; 0, 1]]] ? rnfidealreltoabs(rnf,Prel) %5 = [2, x^2 + 1, 2*x, x^3 + x] ? rnfidealreltoabs(rnf,Prel,1) %6 = [2 1 0 0] [0 1 0 0] [0 0 2 1] [0 0 0 1] @eprog The reason why we do not return by default ($\fl = 0$) the customary HNF in terms of a fixed $\Z$-basis for $\Z_{L}$ is precisely because a \var{rnf} does not contain such a basis by default. Completing the structure so that it contains a \var{nf} structure for $L$ is polynomial time but costly when the absolute degree is large, thus it is not done by default. Note that setting $\fl = 1$ will complete the \var{rnf}. Variant: Also available is \fun{GEN}{rnfidealreltoabs}{GEN rnf, GEN x} ($\fl = 0$). pari-2.17.2/src/functions/number_fields/rnfisabelian0000644000175000017500000000067013637407207021175 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.17.2/src/functions/number_fields/galoissubgroups0000644000175000017500000000145614567450071021773 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 cardinality of a subgroup is the product of the relative orders. Such subgroup can be used instead of a Galois group in the following command: \kbd{galoisisabelian}, \kbd{galoissubgroups}, \kbd{galoisexport} and \kbd{galoisidentify}. To get the subfield fixed by a subgroup \var{sub} of \var{gal}, use \bprog galoisfixedfield(gal,sub[1]) @eprog pari-2.17.2/src/functions/number_fields/rnfidealdown0000644000175000017500000000074214567450071021214 0ustar billbillFunction: rnfidealdown Section: number_fields C-Name: rnfidealdown Prototype: GG Help: rnfidealdown(rnf,x): finds the intersection of the ideal x with the base field. Doc: let $\var{rnf}$ be a relative number field extension $L/K$ as output by \kbd{rnfinit}, and $x$ an ideal of $L$, given either in relative form or by a $\Z$-basis of elements of $L$ (see \secref{se:rnfidealabstorel}). This function returns the ideal of $K$ below $x$, i.e.~the intersection of $x$ with $K$. pari-2.17.2/src/functions/number_fields/nfgaloisconj0000644000175000017500000000436314567450071021217 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; 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 nonconstant 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=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,al,S, ala,k, vR); R *= Mod(1, nfK.pol); \\ convert coeffs to polmod elts of K vR = variable(R); al = Mod(variable(nfK.pol),nfK.pol); [polabs,ala,k] = rnfequation(nfK, R, 1); Rt = if(k==0,R,subst(R,vR,vR-al*k)); N = nfgaloisconj(polabs) % Rt; \\ Q-automorphisms of L S = select(s->subst(Rt, vR, Mod(s,Rt)) == 0, N); if (k==0, S, apply(s->subst(s,vR,vR+k*al)-k*al,S)); } 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.17.2/src/functions/number_fields/bnrL10000644000175000017500000000547214676526175017535 0ustar billbillFunction: bnrL1 Section: number_fields C-Name: bnrL1 Prototype: GDGD0,L,p Help: bnrL1(bnr,{H},{flag=0}): bnr being output by bnrinit and H being a square matrix defining a congruence subgroup of bnr (the trivial subgroup if omitted), for each character of bnr trivial on this subgroup, compute L(1, chi) (or equivalently the first nonzero 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 nontrivial characters), 2: if 0 then compute the value of the primitive L-function attached to chi, if 1 then compute the value of the L-function L_S(s, chi) where S is the set of places dividing the modulus of bnr (and the infinite places), 3: return also the characters. Doc: let \var{bnr} be the number field data output by \kbd{bnrinit} and \var{H} be a square matrix defining a congruence subgroup of the ray class group corresponding to \var{bnr} (the trivial congruence subgroup if omitted). This function returns, for each \idx{character} $\chi$ of the ray class group which is trivial on $H$, the value at $s = 1$ (or $s = 0$) of the abelian $L$-function attached to $\chi$. For the value at $s = 0$, the function returns in fact for each $\chi$ a vector $[r_{\chi}, c_{\chi}]$ where $$L(s, \chi) = c \cdot s^{r} + O(s^{r + 1})$$ \noindent near $0$. The argument \fl\ is optional, its binary digits mean 1: compute at $s = 0$ if unset or $s = 1$ if set, 2: compute the primitive $L$-function attached to $\chi$ if unset or the $L$-function with Euler factors at prime ideals dividing the modulus of \var{bnr} removed if set (that is $L_{S}(s, \chi)$, where $S$ is the set of infinite places of the number field together with the finite prime ideals dividing the modulus of \var{bnr}), 3: return also the character if set. \bprog K = bnfinit(x^2-229); bnr = bnrinit(K,1); bnrL1(bnr) @eprog\noindent returns the order and the first nonzero term of $L(s, \chi)$ at $s = 0$ where $\chi$ runs through the characters of the class group of $K = \Q(\sqrt{229})$. Then \bprog bnr2 = bnrinit(K,2); bnrL1(bnr2,,2) @eprog\noindent returns the order and the first nonzero terms of $L_{S}(s, \chi)$ at $s = 0$ where $\chi$ runs through the characters of the class group of $K$ and $S$ is the set of infinite places of $K$ together with the finite prime $2$. Note that the ray class group modulo $2$ is in fact the class group, so \kbd{bnrL1(bnr2,0)} returns the same answer as \kbd{bnrL1(bnr,0)}. This function will fail with the message \bprog *** bnrL1: overflow in zeta_get_N0 [need too many primes]. @eprog\noindent if the approximate functional equation requires us to sum too many terms (if the discriminant of $K$ is too large). pari-2.17.2/src/functions/number_fields/galoisgetgroup0000644000175000017500000000152414567450071021572 0ustar billbillFunction: galoisgetgroup Section: number_fields C-Name: galoisgetgroup Prototype: LD0,L, Description: (small):int galoisnbpol($1) (small,):int galoisnbpol($1) (small,small):vec galoisgetgroup($1, $2) Help: galoisgetgroup(a,{b}): query the galpol package for a group of order a with index b in the GAP4 Small Group library. If b is omitted, return the number of isomorphism classes of groups of order a. Doc: Query the \kbd{galpol} package for a group of order $a$ with index $b$ in the GAP4 Small Group library, by Hans Ulrich Besche, Bettina Eick and Eamonn O'Brien. The current version of \kbd{galpol} supports groups of order $a\leq 143$. If $b$ is omitted, return the number of isomorphism classes of groups of order $a$. Variant: Also available is \fun{GEN}{galoisnbpol}{long a} when $b$ is omitted. pari-2.17.2/src/functions/number_fields/bnrgaloismatrix0000644000175000017500000000361114567450071021743 0ustar billbillFunction: bnrgaloismatrix Section: number_fields C-Name: bnrgaloismatrix Prototype: GG Help: bnrgaloismatrix(bnr,aut): return the matrix of the action of the automorphism aut of the base field bnf.nf on the generators of the ray class field bnr.gen; aut can be given as a polynomial, or a vector of automorphisms or a galois group as output by galoisinit, in which case a vector of matrices is returned (in the later case, only for the generators aut.gen). Doc: return the matrix of the action of the automorphism \var{aut} of the base field \kbd{bnf.nf} on the generators of the ray class field \kbd{bnr.gen}. The automorphism \var{aut} can be given as a polynomial, an algebraic number, or a vector of automorphisms and must stabilize the modulus \kbd{bnr.mod}. We also allow a Galois group as output by \kbd{galoisinit}, in which case a vector of matrices is returned corresponding to the generators \kbd{aut.gen}. Note: This function only makes sense when the ray class field attached to \var{bnr} is Galois, which is not checked. The generators \kbd{bnr.gen} need not be explicitly computed in the input \var{bnr}, which saves time: the result is well defined in this case also. \bprog ? K = bnfinit(a^4-3*a^2+253009); B = bnrinit(K,9); B.cyc %1 = [8400, 12, 6, 3] ? G = nfgaloisconj(K) %2 = [-a, a, -1/503*a^3 + 3/503*a, 1/503*a^3 - 3/503*a]~ ? bnrgaloismatrix(B, G[2]) \\ G[2] = Id ... %3 = [1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1] ? bnrgaloismatrix(B, G[3]) \\ automorphism of order 2 %4 = [799 0 0 2800] [ 0 7 0 4] [ 4 0 5 2] [ 0 0 0 2] ? M = %^2; for (i=1, #B.cyc, M[i,] %= B.cyc[i]); M %5 = \\ acts on ray class group as automorphism of order 2 [1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1] @eprog See \kbd{bnrisgalois} for further examples. Variant: When $aut$ is a polynomial or an algebraic number, \fun{GEN}{bnrautmatrix}{GEN bnr, GEN aut} is available. pari-2.17.2/src/functions/number_fields/rnfisnorm0000644000175000017500000000446214676526175020572 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, you may 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 4log(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 but you may want to add more primes to $S$ to produce different elements, possibly smaller; 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 $4\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.17.2/src/functions/number_fields/idealdiv0000644000175000017500000000213014676526175020324 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 nonzero, 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 nonzero, 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. More precisely, the algorithm cheaply removes all maximal ideals above rational primes such that $v_{p}(Nx) = v_{p}(Ny)$. 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.17.2/src/functions/number_fields/idealhnf0000644000175000017500000000413514676526175020324 0ustar billbillFunction: idealhnf Section: number_fields C-Name: idealhnf0 Prototype: GGDG Help: idealhnf(nf,u,{v}): hermite normal form of the ideal u in the number field nf if v is omitted. If called as idealhnf(nf,u,v), the ideal is given as uZ_K + vZ_K in the number field K defined by nf. Doc: gives the \idx{Hermite normal form} of the ideal $u\Z_{K}+v\Z_{K}$, where $u$ and $v$ are elements of the number field $K$ defined by \var{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 $v$ is omitted, returns the HNF of the ideal defined by $u$: $u$ may be an algebraic number (defining a principal ideal), a maximal ideal (as given by \kbd{idealprimedec} or \kbd{idealfactor}), or a matrix whose columns give generators for the ideal. This last format is a little complicated, but useful to reduce general modules to the canonical form once in a while: \item if strictly less than $N = [K:\Q]$ generators are given, $u$ is the $\Z_{K}$-module they generate, \item if $N$ or more are given, it is \emph{assumed} that they form a $\Z$-basis of the ideal, in particular that the matrix has maximal rank $N$. This acts as \kbd{mathnf} since the $\Z_{K}$-module structure is (taken for granted hence) not taken into account in this case. \bprog ? idealhnf(nf, idealprimedec(nf,2)[1]) %4 = [2 0 0] [0 1 0] [0 0 1] ? idealhnf(nf, [1,2;2,3;3,4]) %5 = [1 0 0] [0 1 0] [0 0 1] @eprog\noindent Finally, when $K$ is quadratic with discriminant $D_{K}$, we allow $u =$ \kbd{Qfb(a,b,c)}, provided $b^{2} - 4ac = D_{K}$. As usual, this represents the ideal $a \Z + (1/2)(-b + \sqrt{D_{K}}) \Z$. \bprog ? K = nfinit(x^2 - 60); K.disc %1 = 60 ? idealhnf(K, qfbprimeform(60,2)) %2 = [2 1] [0 1] ? idealhnf(K, Qfb(1,2,3)) *** at top-level: idealhnf(K,Qfb(1,2,3 *** ^-------------------- *** idealhnf: Qfb(1, 2, 3) has discriminant != 60 in idealhnf. @eprog Variant: Also available is \fun{GEN}{idealhnf}{GEN nf, GEN a}, where \kbd{nf} is a true \var{nf} structure. pari-2.17.2/src/functions/number_fields/poltschirnhaus0000644000175000017500000000072114567450071021603 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 nonconstant 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.17.2/src/functions/number_fields/rnfidealabstorel0000644000175000017500000000344314676526175022073 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 let $x$ be an ideal of the absolute extension $L/\Q$. Returns the relative pseudo-matrix in HNF giving the ideal $x$ considered as an ideal of the relative extension $L/K$, i.e.~as a $\Z_{K}$-module. Let \kbd{Labs} be an (absolute) \kbd{nf} structure attached to $L$, obtained via \kbd{Labs = nfinit(rnf))}. Then \kbd{rnf} ``knows'' about \kbd{Labs} and $x$ may be given in any format attached to \kbd{Labs}, e.g. a prime ideal or an ideal in HNF wrt. \kbd{Labs.zk}: \bprog ? K = nfinit(y^2+1); rnf = rnfinit(K, x^2-y); Labs = nfinit(rnf); ? m = idealhnf(Labs, 17, x^3+2); \\ some ideal in HNF wrt. Labs.zk ? B = rnfidealabstorel(rnf, m) %3 = [[1, 8; 0, 1], [[17, 4; 0, 1], 1]] \\ pseudo-basis for m as Z_K-module ? A = rnfidealreltoabs(rnf, B) %4 = [17, x^2 + 4, x + 8, x^3 + 8*x^2] \\ Z-basis for m in Q[x]/(rnf.polabs) ? mathnf(matalgtobasis(Labs, A)) == m %5 = 1 @eprog\noindent If on the other hand, we do not have a \kbd{Labs} at hand, because it would be too expensive to compute, but we nevertheless have a $\Z$-basis for $x$, then we can use the function with this basis as argument. The entries of $x$ may be given either modulo \kbd{rnf.polabs} (absolute form, possibly lifted) or modulo \kbd{rnf.pol} (relative form as \typ{POLMOD}s): \bprog ? K = nfinit(y^2+1); rnf = rnfinit(K, x^2-y); ? rnfidealabstorel(rnf, [17, x^2 + 4, x + 8, x^3 + 8*x^2]) %2 = [[1, 8; 0, 1], [[17, 4; 0, 1], 1]] ? rnfidealabstorel(rnf, Mod([17, y + 4, x + 8, y*x + 8*y], x^2-y)) %3 = [[1, 8; 0, 1], [[17, 4; 0, 1], 1]] @eprog pari-2.17.2/src/functions/number_fields/matbasistoalg0000644000175000017500000000061714567450071021373 0ustar billbillFunction: matbasistoalg Section: number_fields C-Name: matbasistoalg Prototype: GG Obsolete: 2016-08-08 Help: matbasistoalg(nf,x): nfbasistoalg applied to every element of the matrix or vector x. Doc: This function is deprecated, use \kbd{apply}. $\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.17.2/src/functions/number_fields/idealispower0000644000175000017500000000123014676526175021232 0ustar billbillFunction: idealispower Section: number_fields C-Name: idealispower Prototype: lGGLD& Help: idealispower(nf,A,n,{&B}): return 1 if A = B^n is an n-th power else return 0. Doc: let \var{nf} be a number field and $n > 0$ be a positive integer. Return $1$ if the fractional ideal $A = B^{n}$ is an $n$-th power and $0$ otherwise. If the argument $B$ is present, set it to the $n$-th root of $A$, in HNF. \bprog ? K = nfinit(x^3 - 2); ? A = [46875, 30966, 9573; 0, 3, 0; 0, 0, 3]; ? idealispower(K, A, 3, &B) %3 = 1 ? B %4 = [75 22 41] [ 0 1 0] [ 0 0 1] ? A = [9375, 2841, 198; 0, 3, 0; 0, 0, 3]; ? idealispower(K, A, 3) %5 = 0 @eprog\noindent pari-2.17.2/src/functions/number_fields/rnfidealtwoelt0000644000175000017500000000072114676526175021572 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.17.2/src/functions/number_fields/idealfactorback0000644000175000017500000000344014760123736021634 0ustar billbillFunction: idealfactorback Section: number_fields C-Name: idealfactorback Prototype: GGDGD0,L, Help: idealfactorback(nf,f,{e},{flag = 0}): given a factorization 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 nonzero, 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 $\fl$ is nonzero, 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.17.2/src/functions/number_fields/rnfinit0000644000175000017500000001302314676526175020217 0ustar billbillFunction: rnfinit Section: number_fields C-Name: rnfinit0 Prototype: GGD0,L, Help: rnfinit(nf,T,{flag=0}): T being an irreducible polynomial defined over the number field nf, initializes a vector of data necessary for working in relative number fields (rnf functions). See manual for technical details. Doc: given an \var{nf} structure attached to a number field $K$, as output by \kbd{nfinit}, and a monic irreducible polynomial $T$ in $\Z_{K}[x]$ defining a relative extension $L = K[x]/(T)$, this computes data to work in $L/K$ The main variable of $T$ must be of higher priority (see \secref{se:priority}) than that of $\var{nf}$, and the coefficients of $T$ must be in $K$. The result is a row vector, whose components are technical. We let $m = [K:\Q]$ the degree of the base field, $n = [L:K]$ the relative degree, $r_{1}$ and $r_{2}$ the number of real and complex places of $K$. Access to this information via \emph{member functions} is preferred since the specific data organization specified below will change in the future. If $\fl = 1$, add an \var{nf} structure attached to $L$ to \var{rnf}. This is likely to be very expensive if the absolute degree $mn$ is large, but fixes an integer basis for $\Z_{L}$ as a $\Z$-module and allows to input and output elements of $L$ in absolute form: as \typ{COL} for elements, as \typ{MAT} in HNF for ideals, as \kbd{prid} for prime ideals. Without such a call, elements of $L$ are represented as \typ{POLMOD}, etc. Note that a subsequent \kbd{nfinit}$(\var{rnf})$ will also explicitly add such a component, and so will the following functions \kbd{rnfidealmul}, \kbd{rnfidealtwoelt}, \kbd{rnfidealprimedec}, \kbd{rnfidealup} (with flag 1) and \kbd{rnfidealreltoabs} (with flag 1). The absolute \var{nf} structure attached to $L$ can be recovered using \kbd{nfinit(rnf)}. $\var{rnf}[1]$(\kbd{rnf.pol}) contains the relative polynomial $T$. $\var{rnf}[2]$ contains the integer basis $[A,d]$ of $K$, as (integral) elements of $L/\Q$. More precisely, $A$ is a vector of polynomial with integer coefficients, $d$ is a denominator, and the integer basis is given by $A/d$. $\var{rnf}[3]$ (\kbd{rnf.disc}) is a two-component row vector $[\goth{d}(L/K),s]$ where $\goth{d}(L/K)$ is the relative ideal discriminant of $L/K$ and $s$ is the discriminant of $L/K$ viewed as an element of $K^{*}/(K^{*})^{2}$, in other words it is the output of \kbd{rnfdisc}. $\var{rnf}[4]$(\kbd{rnf.index}) is the ideal index $\goth{f}$, i.e.~such that $d(T)\Z_{K}=\goth{f}^{2}\goth{d}(L/K)$. $\var{rnf}[5]$(\kbd{rnf.p}) is the list of rational primes dividing the norm of the relative discriminant ideal. $\var{rnf}[7]$ (\kbd{rnf.zk}) is the pseudo-basis $(A,I)$ for the maximal order $\Z_{L}$ as a $\Z_{K}$-module: $A$ is the relative integral pseudo basis expressed as polynomials (in the variable of $T$) with polmod coefficients in $\var{nf}$, and the second component $I$ is the ideal list of the pseudobasis in HNF. $\var{rnf}[8]$ is the inverse matrix of the integral basis matrix, with coefficients polmods in $\var{nf}$. $\var{rnf}[9]$ is currently unused. $\var{rnf}[10]$ (\kbd{rnf.nf}) is $\var{nf}$. $\var{rnf}[11]$ is an extension of \kbd{rnfequation(K, T, 1)}. Namely, a vector $[P, a, k, \kbd{K.pol}, T]$ describing the \emph{absolute} extension $L/\Q$: $P$ is an absolute equation, more conveniently obtained as \kbd{rnf.polabs}; $a$ expresses the generator $\alpha = y \mod \kbd{K.pol}$ of the number field $K$ as an element of $L$, i.e.~a polynomial modulo the absolute equation $P$; $k$ is a small integer such that, if $\beta$ is an abstract root of $T$ and $\alpha$ the generator of $K$ given above, then $P(\beta + k\alpha) = 0$. It is guaranteed that $k = 0$ if $\Q(\beta) = L$. \misctitle{Caveat} Be careful if $k\neq0$ when dealing simultaneously with absolute and relative quantities since $L = \Q(\beta + k\alpha) = K(\alpha)$, and the generator chosen for the absolute extension is not the same as for the relative one. If this happens, one can of course go on working, but we advise to change the relative polynomial so that its root becomes $\beta + k \alpha$. Typical GP instructions would be \bprog [P,a,k] = rnfequation(K, T, 1); if (k, T = subst(T, x, x - k*Mod(y, K.pol))); L = rnfinit(K, T); @eprog $\var{rnf}[12]$ is by default unused and set equal to 0. This field is used to store further information about the field as it becomes available (which is rarely needed, hence would be too expensive to compute during the initial \kbd{rnfinit} call). \misctitle{Huge discriminants, helping rnfdisc} When $T$ has a discriminant which is difficult to factor, it is hard to compute $\Z_{L}$. As in \kbd{nfinit}, the special input format $[T,B]$ is also accepted, where $T$ is a polynomial as above and $B$ specifies a list of maximal ideals. The following formats are recognized for $B$: \item an integer: the list of all maximal ideals above a rational prime $p < B$. \item a vector of rational primes or prime ideals: the list of all maximal ideals dividing an element in the list. Instead of $\Z_{L}$, this produces an order which is maximal at all such maximal ideals primes. The result may actually be a complete and correct \var{rnf} structure if the relative ideal discriminant factors completely over this list of maximal ideals but this is not guaranteed. In general, the order may not be maximal at primes $\goth{p}$ not in the list such that $\goth{p}^{2}$ divides the relative ideal discriminant. Variant: Also available is \fun{GEN}{rnfinit}{GEN nf,GEN T} ($\fl = 0$). pari-2.17.2/src/functions/number_fields/nfeltispower0000644000175000017500000000071414676526175021272 0ustar billbillFunction: nfeltispower Section: number_fields C-Name: nfispower Prototype: lGGLD& Help: nfeltispower(nf,x,n,{&y}): returns 1 if x is an n-th power in nf (and set y to an n-th root if present), else returns 0. Doc: returns $1$ if $x$ is an $n$-th power in the number field \kbd{nf} (and sets $y$ to an $n$-th root if the argument is present), else returns 0. \bprog ? nf = nfinit(1+x^2); ? nfeltispower(nf, -4, 4, &y) %2 = 1 ? y %3 = [-1, -1]~ @eprog pari-2.17.2/src/functions/number_fields/bnrconductor0000644000175000017500000000567214676526175021263 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)$, without generators unless the input contained a \var{bnr} with generators. In place of a subgroup $H$, this function also accepts a character \kbd{chi} $=(a_{j})$, expressed as usual in terms of the generators \kbd{bnr.gen}: $\chi(g_{j}) = \exp(2i\pi a_{j} / d_{j})$, where $g_{j}$ has order $d_{j} = \kbd{bnr.cyc[j]}$. In which case, the function returns respectively If $\fl = 0$, the conductor $f$ of $\text{Ker} \chi$. If $\fl = 1$, $[f, Cl_{f}, \chi_{f}]$, where $\chi_{f}$ is $\chi$ expressed on the minimal ray class group, whose modulus is the conductor. If $\fl = 2$, $[f, \var{bnr}(f), \chi_{f}]$. \misctitle{Note} Using this function with $\fl \neq 0$ is usually a bad idea and kept for compatibility and convenience only: $\fl = 1$ has always been useless, since it is no faster than $\fl = 2$ and returns less information; $\fl = 2$ is mostly OK with two subtle drawbacks: $\bullet$ it returns the full \var{bnr} attached to the full ray class group, whereas in applications we only need $Cl_{f}$ modulo $N$-th powers, where $N$ is any multiple of the exponent of $Cl_{f}/H$. Computing directly the conductor, then calling \kbd{bnrinit} with optional argument $N$ avoids this problem. $\bullet$ computing the \var{bnr} needs only be done once for each conductor, which is not possible using this function. For maximal efficiency, the recommended procedure is as follows. Starting from data (character or congruence subgroups) attached to a modulus $m$, we can first compute the conductors using this function with default $\fl = 0$. Then for all data with a common conductor $f \mid m$, compute (once!) the \var{bnr} attached to $f$ using \kbd{bnrinit} (modulo $N$-th powers for a suitable $N$!) and finally map original data to the new \var{bnr} using \kbd{bnrmap}. Variant: Also available are \fun{GEN}{bnrconductor}{GEN bnr, GEN H, long flag} and \fun{GEN}{bnrconductormod}{GEN bnr, GEN H, long flag, GEN cycmod} which returns ray class groups modulo \kbd{cycmod}-th powers. pari-2.17.2/src/functions/number_fields/rnfidealmul0000644000175000017500000000063213637407207021040 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.17.2/src/functions/number_fields/nfsubfieldsmax0000644000175000017500000000100714676526175021557 0ustar billbillFunction: nfsubfieldsmax Section: number_fields C-Name: nfsubfieldsmax Prototype: GD0,L, Help: nfsubfieldsmax(nf,{flag=0}): computes the list of maximal subfields of nf. The result is as in nfsubfields. Doc: Computes the list of maximal subfields of \var{nf}. The result is a vector as in \tet{nfsubfields}. An input of the form~\kbd{[nf, fa]} is also allowed, where~\kbd{fa} is the factorisation of~\var{nf.pol} over~\var{nf}, and~\var{nf} is also allowed to be a monic defining polynomial for the number field. pari-2.17.2/src/functions/number_fields/nfelttrace0000644000175000017500000000022613637407207020664 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.17.2/src/functions/number_fields/rnfbasis0000644000175000017500000000210714676526175020356 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 a monic 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. \misctitle{Huge discriminants, helping rnfdisc} The format $[T,B]$ is also accepted instead of $T$ and computes an order which is maximal at all maximal ideals specified by $B$, see \kbd{??rnfinit}: the valuation of $D$ is then correct at all such maximal ideals but may be incorrect at other primes. pari-2.17.2/src/functions/number_fields/bnrclassfield0000644000175000017500000000465214676526175021371 0ustar billbillFunction: bnrclassfield Section: number_fields C-Name: bnrclassfield Prototype: GDGD0,L,p Help: bnrclassfield(bnr,{subgp},{flag=0}): bnr being as output by bnrinit, find a relative equation for the class field corresponding to the congruence subgroup described by (bnr,subgp). If flag=0, return a vector of polynomials such that the compositum of the corresponding fields is the class field; if flag=1 return a single relative polynomial; if flag=2 return a single absolute polynomial. Doc: \var{bnr} being as output by \kbd{bnrinit}, returns a relative equation for the class field corresponding to the congruence group defined by $(\var{bnr},\var{subgp})$ (the full ray class field if \var{subgp} is omitted). The subgroup can also be a \typ{INT}~$n$, meaning~$n \cdot \text{Cl}_{f}$. The function also handles a vector of subgroup, e.g, from \tet{subgrouplist} and returns the vector of individual results in this case. If $\fl=0$, returns a vector of polynomials such that the compositum of the corresponding fields is the class field; if $\fl=1$ returns a single polynomial; if $\fl=2$ returns a single absolute polynomial. \bprog ? bnf = bnfinit(y^3+14*y-1); bnf.cyc %1 = [4, 2] ? pol = bnrclassfield(bnf,,1) \\ Hilbert class field %2 = x^8 - 2*x^7 + ... + Mod(11*y^2 - 82*y + 116, y^3 + 14*y - 1) ? rnfdisc(bnf,pol)[1] %3 = 1 ? bnr = bnrinit(bnf,3*5*7); bnr.cyc %4 = [24, 12, 12, 2] ? bnrclassfield(bnr,2) \\ maximal 2-elementary subextension %5 = [x^2 + (-21*y - 105), x^2 + (-5*y - 25), x^2 + (-y - 5), x^2 + (-y - 1)] \\ quadratic extensions of maximal conductor ? bnrclassfield(bnr, subgrouplist(bnr,[2])) %6 = [[x^2 - 105], [x^2 + (-105*y^2 - 1260)], [x^2 + (-105*y - 525)], [x^2 + (-105*y - 105)]] ? #bnrclassfield(bnr,subgrouplist(bnr,[2],1)) \\ all quadratic extensions %7 = 15 @eprog\noindent When the subgroup contains $n \text{Cl}_{f}$, where $n$ is fixed, it is advised to directly compute the \kbd{bnr} modulo $n$ to avoid expensive discrete logarithms: \bprog ? bnf = bnfinit(y^2-5); p = 1594287814679644276013; ? bnr = bnrinit(bnf,p); \\ very slow time = 24,146 ms. ? bnrclassfield(bnr, 2) \\ ... even though the result is trivial %3 = [x^2 - 1594287814679644276013] ? bnr2 = bnrinit(bnf,p,,2); \\ now fast time = 1 ms. ? bnrclassfield(bnr2, 2) %5 = [x^2 - 1594287814679644276013] @eprog\noindent This will save a lot of time when the modulus contains a maximal ideal whose residue field is large. pari-2.17.2/src/functions/number_fields/nfcompositum0000644000175000017500000000645114676526175021300 0ustar billbillFunction: nfcompositum Section: number_fields C-Name: nfcompositum Prototype: GGGD0,L, Help: nfcompositum(nf,P,Q,{flag=0}): vector of all possible compositums of the number fields defined by the polynomials P and Q; flag is optional, whose binary digits mean 1: output for each compositum, not only the compositum polynomial pol, but a vector [R,a,b,k] where a (resp. b) is a root of P (resp. Q) expressed as a polynomial modulo R, and a small integer k such that al2+k*al1 is the chosen root of R; 2: assume that the number fields defined by P and Q are linearly disjoint. Doc: Let \var{nf} be a number field structure attached to the field $K$ and let \sidx{compositum} $P$ and $Q$ be squarefree polynomials in $K[X]$ in the same variable. Outputs the simple factors of the \'etale $K$-algebra $A = K[X, Y] / (P(X), Q(Y))$. The factors are given by a list of polynomials $R$ in $K[X]$, attached to the number field $K[X]/ (R)$, and sorted by increasing degree (with respect to lexicographic ordering for factors of equal degrees). Returns an error if one of the polynomials is not squarefree. Note that it is more efficient to reduce to the case where $P$ and $Q$ are irreducible first. The routine will not perform this for you, since it may be expensive, and the inputs are irreducible in most applications anyway. In this case, there will be a single factor $R$ if and only if the number fields defined by $P$ and $Q$ are linearly disjoint (their intersection is $K$). The binary digits of $\fl$ mean 1: outputs a vector of 4-component vectors $[R,a,b,k]$, where $R$ ranges through the list of all possible compositums as above, and $a$ (resp. $b$) expresses the root of $P$ (resp. $Q$) as an element of $K[X]/(R)$. Finally, $k$ is a small integer such that $b + ka = X$ modulo $R$. 2: assume that $P$ and $Q$ define number fields that are linearly disjoint: both polynomials are irreducible and the corresponding number fields have no common subfield besides $K$. This allows to save a costly factorization over $K$. In this case return the single simple factor instead of a vector with one element. A compositum is often defined by a complicated polynomial, which it is advisable to reduce before further work. Here is an example involving the field $K(\zeta_{5}, 5^{1/10})$, $K=\Q(\sqrt{5})$: \bprog ? K = nfinit(y^2-5); ? L = nfcompositum(K, x^5 - y, polcyclo(5), 1); \\@com list of $[R,a,b,k]$ ? [R, a] = L[1]; \\@com pick the single factor, extract $R,a$ (ignore $b,k$) ? lift(R) \\@com defines the compositum %4 = x^10 + (-5/2*y + 5/2)*x^9 + (-5*y + 20)*x^8 + (-20*y + 30)*x^7 + \ (-45/2*y + 145/2)*x^6 + (-71/2*y + 121/2)*x^5 + (-20*y + 60)*x^4 + \ (-25*y + 5)*x^3 + 45*x^2 + (-5*y + 15)*x + (-2*y + 6) ? a^5 - y \\@com a fifth root of $y$ %5 = 0 ? [T, X] = rnfpolredbest(K, R, 1); ? lift(T) \\@com simpler defining polynomial for $K[x]/(R)$ %7 = x^10 + (-11/2*y + 25/2) ? liftall(X) \\ @com root of $R$ in $K[x]/(T(x))$ %8 = (3/4*y + 7/4)*x^7 + (-1/2*y - 1)*x^5 + 1/2*x^2 + (1/4*y - 1/4) ? a = subst(a.pol, 'x, X); \\@com \kbd{a} in the new coordinates ? liftall(a) %10 = (-3/4*y - 7/4)*x^7 - 1/2*x^2 ? a^5 - y %11 = 0 @eprog The main variables of $P$ and $Q$ must be the same and have higher priority than that of \var{nf} (see~\kbd{varhigher} and~\kbd{varlower}). pari-2.17.2/src/functions/number_fields/rnfisnorminit0000644000175000017500000000204414760123736021436 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.17.2/src/functions/number_fields/bnrstarkunit0000644000175000017500000000230014676526175021270 0ustar billbillFunction: bnrstarkunit Section: number_fields C-Name: bnrstarkunit Prototype: GDG Help: bnrstarkunit(bnr,{subgroup}): bnr being as output by bnrinit, returns the characteristic polynomial of the (conjectural) Stark unit corresponding to the module in bnr and the given congruence subgroup (the trivial subgroup if omitted). The ground field must be totally real and all but one infinite place must become complex in the class field. Doc: \var{bnr} being as output by \kbd{bnrinit}, returns the characteristic polynomial of the (conjectural) Stark unit 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 ground field attached to \var{bnr} must be totally real and all but one infinite place must become complex in the class field, which must be a quadratic extension of its totally real subfield. Finally, the output is given as a polynomial in $x$, so the main variable of \var{bnr} must not be $x$. Here is an example: \bprog ? bnf = bnfinit(y^2 - 2); ? bnr = bnrinit(bnf, [15, [1,0]]); ? lift(bnrstarkunit(bnr)) %3 = x^8 + (-9000*y - 12728)*x^7 + (57877380*y + 81850978)*x^6 + ... + 1 @eprog pari-2.17.2/src/functions/number_fields/nfpolsturm0000644000175000017500000000262714676526175020767 0ustar billbillFunction: nfpolsturm Section: number_fields C-Name: nfpolsturm Prototype: GGDG Help: nfpolsturm(nf,T,{pl}): number of distinct real roots of the polynomial s(T) where s runs through the real embeddings given by vector pl. Doc: given a polynomial $T$ with coefficients in the number field \var{nf}, returns the number of real roots of the $s(T)$ where $s$ runs through the real embeddings of the field specified by optional argument \var{pl}: \item \var{pl} omitted: all $r_{1}$ real places; \item \var{pl} an integer between $1$ and $r_{1}$: the embedding attached to the $i$-th real root of \kbd{nf.pol}, i.e. \kbd{nf.roots$[i]$}; \item \var{pl} a vector or \typ{VECSMALL}: the embeddings attached to the $\var{pl}[i]$-th real roots of \kbd{nf.pol}. \bprog ? nf = nfinit('y^2 - 2); ? nf.sign %2 = [2, 0] ? nf.roots %3 = [-1.414..., 1.414...] ? T = x^2 + 'y; ? nfpolsturm(nf, T, 1) \\ subst(T,y,sqrt(2)) has two real roots %5 = 2 ? nfpolsturm(nf, T, 2) \\ subst(T,y,-sqrt(2)) has no real root %6 = 0 ? nfpolsturm(nf, T) \\ all embeddings together %7 = [2, 0] ? nfpolsturm(nf, T, [2,1]) \\ second then first embedding %8 = [0, 2] ? nfpolsturm(nf, x^3) \\ number of distinct roots ! %9 = [1, 1] ? nfpolsturm(nf, x, 6) \\ there are only 2 real embeddings ! *** at top-level: nfpolsturm(nf,x,6) *** ^----------------- *** nfpolsturm: domain error in nfpolsturm: index > 2 @eprog pari-2.17.2/src/functions/number_fields/idealredmodpower0000644000175000017500000000274514676526175022105 0ustar billbillFunction: idealredmodpower Section: number_fields C-Name: idealredmodpower Prototype: GGUD0,U, Help: idealredmodpower(nf,x,n,{B=factorlimit}): return b such that x * b^n = v is small. Doc: let \var{nf} be a number field, $x$ an ideal in \var{nf} and $n > 0$ be a positive integer. Return a number field element $b$ such that $x b^{n} = v$ is small. If $x$ is integral, then $v$ is also integral. More precisely, \kbd{idealnumden} reduces the problem to $x$ integral. Then, factoring out the prime ideals dividing a rational prime $p \leq B$, we rewrite $x = I J^{n}$ where the ideals $I$ and $J$ are both integral and $I$ is $B$-smooth. Then we return a small element $b$ in $J^{-1}$. The bound $B$ avoids a costly complete factorization of $x$; as soon as the $n$-core of $x$ is $B$-smooth (i.e., as soon as $I$ is $n$-power free), then $J$ is as large as possible and so is the expected reduction. \bprog ? T = x^6+108; nf = nfinit(T); a = Mod(x,T); ? setrand(1); u = (2*a^2+a+3)*random(2^1000*x^6)^6; ? sizebyte(u) %3 = 4864 ? b = idealredmodpower(nf,u,2); ? v2 = nfeltmul(nf,u, nfeltpow(nf,b,2)) %5 = [34, 47, 15, 35, 9, 3]~ ? b = idealredmodpower(nf,u,6); ? v6 = nfeltmul(nf,u, nfeltpow(nf,b,6)) %7 = [3, 0, 2, 6, -7, 1]~ @eprog\noindent The last element \kbd{v6}, obtained by reducing modulo $6$-th powers instead of squares, looks smaller than \kbd{v2} but its norm is actually a little larger: \bprog ? idealnorm(nf,v2) %8 = 81309 ? idealnorm(nf,v6) %9 = 731781 @eprog pari-2.17.2/src/functions/number_fields/polredbest0000644000175000017500000000436614676526175020723 0ustar billbillFunction: polredbest Section: number_fields C-Name: polredbest Prototype: GD0,L, Help: polredbest(T,{flag=0}): reduction of the polynomial T (gives minimal polynomials only). If flag=1, gives also elements. Doc: finds a polynomial with reasonably small coefficients defining the same number field as $T$. All $T$ accepted by \tet{nfinit} are also allowed here (e.g. nonmonic polynomials, \kbd{nf}, \kbd{bnf}, \kbd{[T,Z\_K\_basis]}). Contrary to \tet{polredabs}, this routine runs in polynomial time, but it offers no guarantee as to the minimality of its result. This routine computes an LLL-reduced basis for an order in $\Q[X]/(T)$, then examines small linear combinations of the basis vectors, computing their characteristic polynomials. It returns the \emph{separable} polynomial $P$ of smallest discriminant, the one with lexicographically smallest \kbd{abs(Vec(P))} in case of ties. This is a good candidate for subsequent number field computations since it guarantees that the denominators of algebraic integers, when expressed in the power basis, are reasonably small. With no claim of minimality, though. It can happen that iterating this functions yields better and better polynomials, until it stabilizes: \bprog ? \p5 ? P = X^12+8*X^8-50*X^6+16*X^4-3069*X^2+625; ? poldisc(P)*1. %2 = 1.2622 E55 ? P = polredbest(P); ? poldisc(P)*1. %4 = 2.9012 E51 ? P = polredbest(P); ? poldisc(P)*1. %6 = 8.8704 E44 @eprog\noindent In this example, the initial polynomial $P$ is the one returned by \tet{polredabs}, and the last one is stable. If $\fl = 1$: outputs a two-component row vector $[P,a]$, where $P$ is the default output and \kbd{a}, a \typ{POLMOD} modulo~\kbd{P}, is a root of the original $T$. \bprog ? [P,a] = polredbest(x^4 + 8, 1) %1 = [x^4 + 2, Mod(x^3, x^4 + 2)] ? charpoly(a) %2 = x^4 + 8 @eprog\noindent In particular, the map $\Q[x]/(T) \to \Q[x]/(P)$, $x\mapsto \kbd{a}$ defines an isomorphism of number fields, which can be computed as \bprog subst(lift(Q), 'x, a) @eprog\noindent if $Q$ is a \typ{POLMOD} modulo $T$; \kbd{b = modreverse(a)} returns a \typ{POLMOD} giving the inverse of the above map (which should be useless since $\Q[x]/(P)$ is a priori a better representation for the number field and its elements). pari-2.17.2/src/functions/number_fields/galoisisnormal0000644000175000017500000000105713637407207021563 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.17.2/src/functions/number_fields/nfdiscfactors0000644000175000017500000000275714676526175021412 0ustar billbillFunction: nfdiscfactors Section: number_fields C-Name: nfdiscfactors Prototype: G Help: nfdiscfactors(T): [D, faD], where D = nfdisc(T), and faD is the factorization of |D|. Doc: given a polynomial $T$ with integer coefficients, return $[D, \var{faD}]$ where $D$ is \kbd{nfdisc}$(T)$ and \var{faD} is the factorization of $|D|$. All the variants \kbd{[T,listP]} are allowed (see \kbd{??nfdisc}), in which case \var{faD} is the factorization of the discriminant underlying order (which need not be maximal at the primes not specified by \kbd{listP}) and the factorization may contain large composites. \bprog ? T = x^3 - 6021021*x^2 + 12072210077769*x - 8092423140177664432; ? [D,faD] = nfdiscfactors(T); print(faD); D [3, 3; 500009, 2] %2 = -6750243002187] ? T = x^3 + 9*x^2 + 27*x - 125014250689643346789780229390526092263790263725; ? [D,faD] = nfdiscfactors(T); print(faD); D [3, 3; 1000003, 2] %4 = -27000162000243 ? [D,faD] = nfdiscfactors([T, 10^3]); print(faD) [3, 3; 125007125141751093502187, 2] @eprog\noindent In the final example, we only get a partial factorization, which is only guaranteed correct at primes $\leq 10^{3}$. The function also accept number field structures, for instance as output by \kbd{nfinit}, and returns the field discriminant and its factorization: \bprog ? T = x^3 + 9*x^2 + 27*x - 125014250689643346789780229390526092263790263725; ? nf = nfinit(T); [D,faD] = nfdiscfactors(T); print(faD); D %2 = -27000162000243 ? nf.disc %3 = -27000162000243 @eprog pari-2.17.2/src/functions/number_fields/ideallog0000644000175000017500000000312314676526175020326 0ustar billbillFunction: ideallog Section: number_fields C-Name: ideallog Prototype: DGGG Help: ideallog({nf},x,bid): if bid is a big ideal, as given by idealstar(nf,D,...), gives the vector of exponents on the generators bid.gen (even if these generators have not been explicitly computed). Doc: $\var{nf}$ is a number field, \var{bid} is as output by \kbd{idealstar(nf, D, \dots)} and $x$ an element of \var{nf} which must have valuation equal to 0 at all prime ideals in the support of $\kbd{D}$ and need not be integral. This function computes the discrete logarithm of $x$ on the generators given in \kbd{\var{bid}.gen}. In other words, if $g_{i}$ are these generators, of orders $d_{i}$ respectively, the result is a column vector of integers $(x_{i})$ such that $0\le x_{i} B && !isprime(P[i]), warning("nf may be incorrect"))); @eprog\noindent This is a sufficient but not a necessary condition, hence the warning, instead of an error. The function \tet{nfcertify} speeds up and automates the above process: \bprog ? B = 10^5; ? nf = nfinit([T, B]); ? nfcertify(nf) %3 = [] \\ nf is unconditionally correct ? [basis, disc] = [nf.zk, nf.disc]; @eprog pari-2.17.2/src/functions/number_fields/nfeltmul0000644000175000017500000000034114567450071020361 0ustar billbillFunction: nfeltmul Section: number_fields C-Name: nfmul Prototype: GGG Help: nfeltmul(nf,x,y): element x.y in nf. Doc: given two elements $x$ and $y$ in \var{nf}, computes their product $x*y$ in the number field $\var{nf}$. pari-2.17.2/src/functions/number_fields/nfeltadd0000644000175000017500000000046314567450071020321 0ustar billbillFunction: nfeltadd Section: number_fields C-Name: nfadd Prototype: GGG Help: nfeltadd(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}$. \bprog ? nf = nfinit(1+x^2); ? nfeltadd(nf, 1, x) \\ 1 + I %2 = [1, 1]~ @eprog pari-2.17.2/src/functions/number_fields/bnrdisclist0000644000175000017500000000510714676526175021072 0ustar billbillFunction: bnrdisclist Section: number_fields C-Name: bnrdisclist0 Prototype: GGDG Help: bnrdisclist(bnf,bound,{arch}): list of discriminants of ray class fields of all conductors up to norm bound. 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, where $v[k]$ is itself a vector $w$, whose length is the number of ideals of norm $k$. \item 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 attached 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. \item 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} are (much) more efficient. pari-2.17.2/src/functions/number_fields/idealramgroups0000644000175000017500000000326514676526175021573 0ustar billbillFunction: idealramgroups Section: number_fields C-Name: idealramgroups Prototype: GGG Help: idealramgroups(nf,gal,pr): let pr be a prime ideal in prid format, and gal the Galois group of the number field nf, return a vector g such that g[1] is the decomposition group of pr, g[2] is the inertia group, g[i] is the (i-2)th ramification group of pr, all trivial subgroups being omitted. Doc: Let $K$ be the number field defined by \var{nf} and assume that $K/\Q$ is Galois with Galois group $G$ given by \kbd{gal=galoisinit(nf)}. Let \var{pr} be the prime ideal $\goth{P}$ in prid format. This function returns a vector $g$ of subgroups of \kbd{gal} as follows: \item \kbd{g[1]} is the decomposition group of $\goth{P}$, \item \kbd{g[2]} is $G_{0}(\goth{P})$, the inertia group of $\goth{P}$, and for $i\geq 2$, \item \kbd{g[i]} is $G_{i-2}(\goth{P})$, the $i-2$-th \idx{ramification group} of $\goth{P}$. \noindent The length of $g$ is the number of nontrivial groups in the sequence, thus is $0$ if $e=1$ and $f=1$, and $1$ if $f>1$ and $e=1$. The following function computes the cardinality of a subgroup of $G$, as given by the components of $g$: \bprog card(H) =my(o=H[2]); prod(i=1,#o,o[i]); @eprog \bprog ? nf=nfinit(x^6+3); gal=galoisinit(nf); pr=idealprimedec(nf,3)[1]; ? g = idealramgroups(nf, gal, pr); ? apply(card,g) %3 = [6, 6, 3, 3, 3] \\ cardinalities of the G_i @eprog \bprog ? nf=nfinit(x^6+108); gal=galoisinit(nf); pr=idealprimedec(nf,2)[1]; ? iso=idealramgroups(nf,gal,pr)[2] %5 = [[Vecsmall([2, 3, 1, 5, 6, 4])], Vecsmall([3])] ? nfdisc(galoisfixedfield(gal,iso,1)) %6 = -3 @eprog\noindent The field fixed by the inertia group of $2$ is not ramified at $2$. pari-2.17.2/src/functions/number_fields/galoisexport0000644000175000017500000000246714557721031021262 0ustar billbillFunction: galoisexport Section: number_fields C-Name: galoisexport Prototype: GD0,L, Help: galoisexport(gal,{flag}): gal being a Galois group as output by galoisinit, output a string representing the underlying permutation group in GAP notation (default) or Magma notation (flag = 1). Doc: \var{gal} being be a Galois group as output by \tet{galoisinit}, export the underlying permutation group as a string suitable for (no flags or $\fl=0$) GAP or ($\fl=1$) Magma. The following example compute the index of the underlying abstract group in the GAP library: \bprog ? G = galoisinit(x^6+108); ? s = galoisexport(G) %2 = "Group((1, 2, 3)(4, 5, 6), (1, 4)(2, 6)(3, 5))" ? extern("echo \"IdGroup("s");\" | gap -q") %3 = [6, 1] ? galoisidentify(G) %4 = [6, 1] @eprog\noindent This command also accepts subgroups returned by \kbd{galoissubgroups}. To \emph{import} a GAP permutation into gp (for \tet{galoissubfields} for instance), the following GAP function may be useful: \bprog PermToGP := function(p, n) return Permuted([1..n],p); end; gap> p:= (1,26)(2,5)(3,17)(4,32)(6,9)(7,11)(8,24)(10,13)(12,15)(14,27) (16,22)(18,28)(19,20)(21,29)(23,31)(25,30) gap> PermToGP(p,32); [ 26, 5, 17, 32, 2, 9, 11, 24, 6, 13, 7, 15, 10, 27, 12, 22, 3, 28, 20, 19, 29, 16, 31, 8, 30, 1, 14, 18, 21, 25, 23, 4 ] @eprog pari-2.17.2/src/functions/number_fields/rnfalgtobasis0000644000175000017500000000074113637407207021375 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.17.2/src/functions/number_fields/galoissubfields0000644000175000017500000000064214676526175021730 0ustar billbillFunction: galoissubfields Section: number_fields C-Name: galoissubfields Prototype: GD0,L,Dn Help: galoissubfields(G,{flag=0},{v}): output all the subfields of G; flag has 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 $\fl$ is the same as for \kbd{galoisfixedfield}. pari-2.17.2/src/functions/number_fields/rnfpolred0000644000175000017500000000143214567450071020530 0ustar billbillFunction: rnfpolred Section: number_fields C-Name: rnfpolred Prototype: GGp Obsolete: 2013-12-28 Help: rnfpolred(nf,pol): given a pol with coefficients in nf, finds a list of relative polynomials defining some subfields, hopefully simpler. Doc: This function is obsolete: use \tet{rnfpolredbest} instead. Relative version of \kbd{polred}. Given a monic polynomial \var{pol} with coefficients in $\var{nf}$, finds a list of relative polynomials defining some subfields, hopefully simpler and containing the original field. In the present version \vers, this is slower and less efficient than \kbd{rnfpolredbest}. \misctitle{Remark} This function is based on an incomplete reduction theory of lattices over number fields, implemented by \kbd{rnflllgram}, which deserves to be improved. pari-2.17.2/src/functions/number_fields/idealprincipalunits0000644000175000017500000000141414676526175022612 0ustar billbillFunction: idealprincipalunits Section: number_fields C-Name: idealprincipalunits Prototype: GGL Help: idealprincipalunits(nf,pr,k): returns the structure [no, cyc, gen] of the multiplicative group (1 + pr) / (1 + pr^k). Doc: given a prime ideal in \tet{idealprimedec} format, returns the multiplicative group $(1 + \var{pr}) / (1 + \var{pr}^{k})$ as an abelian group. This function is much faster than \tet{idealstar} when the norm of \var{pr} is large, since it avoids (useless) work in the multiplicative group of the residue field. \bprog ? K = nfinit(y^2+1); ? P = idealprimedec(K,2)[1]; ? G = idealprincipalunits(K, P, 20); ? G.cyc %4 = [512, 256, 4] \\ Z/512 x Z/256 x Z/4 ? G.gen %5 = [[-1, -2]~, 1021, [0, -1]~] \\ minimal generators of given order @eprog pari-2.17.2/src/functions/number_fields/rnfidealfactor0000644000175000017500000000174714567450071021531 0ustar billbillFunction: rnfidealfactor Section: number_fields C-Name: rnfidealfactor Prototype: GG Help: rnfidealfactor(rnf,x): factor the ideal x into prime ideals in the number field nfinit(rnf). Doc: factor into prime ideal powers the ideal $x$ in the attached absolute number field $L = \kbd{nfinit}(\var{rnf})$. 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 for $L$. \bprog ? rnf = rnfinit(nfinit(y^2+1), x^2-y+1); ? rnfidealfactor(rnf, y+1) \\ P_2^2 %2 = [[2, [0,0,1,0]~, 4, 1, [0,0,0,2;0,0,-2,0;-1,-1,0,0;1,-1,0,0]] 2] ? rnfidealfactor(rnf, x) \\ P_2 %3 = [[2, [0,0,1,0]~, 4, 1, [0,0,0,2;0,0,-2,0;-1,-1,0,0;1,-1,0,0]] 1] ? L = nfinit(rnf); ? id = idealhnf(L, idealhnf(L, 25, (x+1)^2)); ? idealfactor(L, id) == rnfidealfactor(rnf, id) %6 = 1 @eprog\noindent Note that ideals of the base field $K$ must be explicitly lifted to $L$ via \kbd{rnfidealup} before they can be factored. pari-2.17.2/src/functions/number_fields/idealstar0000644000175000017500000000663014676526175020524 0ustar billbillFunction: idealstar Section: number_fields C-Name: idealstarmod Prototype: DGGD1,L,DG Help: idealstar({nf},N,{flag=1},{cycmod}): gives the structure of (Z_K/N)^*, where N is a modulus (an ideal in any form or a vector [f0, foo], where f0 is an ideal and foo is a {0,1}-vector with r1 components. If the positive integer cycmod is present, only compute the group modulo cycmod-th powers. flag is optional, and can be 0: structure as an abelian group [h,d,g] where h is the order, d the orders of the cyclic factors and g the generators; if flag=1 (default), gives a bid structure used in ideallog to compute discrete logarithms; underlying generators are well-defined but not explicitly computed, which saves time; if flag=2, same as with flag=1 except that the generators are also given. If nf is omitted, N must be an integer and we return the structure of (Z/NZ)^*. Doc: outputs a \kbd{bid} structure, necessary for computing in the finite abelian group $G = (\Z_{K}/N)^{*}$. Here, \var{nf} is a number field and $N$ is a \var{modulus}: either an ideal in any form, or a row vector whose first component is an ideal and whose second component is a row vector of $r_{1}$ 0 or 1. Ideals can also be given by a factorization into prime ideals, as produced by \tet{idealfactor}. If the positive integer \kbd{cycmod} is present, only compute the group modulo \kbd{cycmod}-th powers, which may save a lot of time when some maximal ideals in the modulus have a huge residue field. Whereas you might only be interested in quadratic or cubic residuosity; see also \kbd{bnrinit} for applications in class field theory. 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 \kbd{bid} structure without generators: they are well defined but not explicitly computed, which saves time. If $\fl=2$, as $\fl=1$, but including generators. If $\fl=0$, only outputs $(\Z_{K}/N)^{*}$ 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. If \var{nf} is omitted, we take it to be the rational number fields, $N$ must be an integer and we return the structure of $(\Z/N\Z)^{*}$. In other words \kbd{idealstar(, N, flag)} is short for \bprog idealstar(nfinit(x), N, flag) @eprog\noindent but faster. The alternative syntax \kbd{znstar(N, flag)} is also available for an analogous effect but, due to an unfortunate historical oversight, the default value of $\fl$ is different in the two functions (\kbd{znstar} does not initialize by default, you probably want \kbd{znstar(N,1)}). Variant: Instead the above hardcoded numerical flags, one should rather use \fun{GEN}{Idealstarmod}{GEN nf, GEN ideal, long flag, GEN cycmod} or \fun{GEN}{Idealstar}{GEN nf, GEN ideal, long flag} (\kbd{cycmod} is \kbd{NULL}), where $\fl$ 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. The \kbd{nf} argument must be a true \var{nf} structure. pari-2.17.2/src/functions/number_fields/nfeltreducemodpr0000644000175000017500000000105114567450071022074 0ustar billbillFunction: nfeltreducemodpr Section: number_fields C-Name: nfreducemodpr Prototype: GGG Obsolete: 2016-08-09 Help: nfeltreducemodpr(nf,x,pr): this function is obsolete, use nfmodpr. Doc: this function is obsolete, use \kbd{nfmodpr}. 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.17.2/src/functions/number_fields/rnfkummer0000644000175000017500000000035314567450071020544 0ustar billbillFunction: rnfkummer Section: number_fields C-Name: rnfkummer Obsolete: 2020-05-22 Prototype: GDGp Help: rnfkummer(bnr,{subgp}): this function is deprecated. Use bnrclassfield. Doc: This function is deprecated, use \kbd{bnrclassfield}. pari-2.17.2/src/functions/number_fields/idealmul0000644000175000017500000000237214567450071020335 0ustar billbillFunction: idealmul Section: number_fields C-Name: idealmul0 Prototype: GGGD0,L, Help: idealmul(nf,x,y,{flag=0}): product of the two ideals x and y in the number field nf. If (optional) flag is nonzero, reduce the result. Description: (gen, gen, gen, ?0):gen idealmul($1, $2, $3) (gen, gen, gen, 1):gen idealmulred($1, $2, $3) (gen, gen, gen, #small):gen $"invalid flag in idealmul" (gen, gen, gen, small):gen idealmul0($1, $2, $3, $4) Doc: ideal multiplication of the ideals $x$ and $y$ in the number field \var{nf}; the result is the ideal product in HNF. If either $x$ or $y$ are extended ideals\sidx{ideal (extended)}, their principal part is suitably updated: i.e. multiplying $[I,t]$, $[J,u]$ yields $[IJ, tu]$; multiplying $I$ and $[J, u]$ yields $[IJ, u]$. \bprog ? nf = nfinit(x^2 + 1); ? idealmul(nf, 2, x+1) %2 = [4 2] [0 2] ? idealmul(nf, [2, x], x+1) \\ extended ideal * ideal %3 = [[4, 2; 0, 2], x] ? idealmul(nf, [2, x], [x+1, x]) \\ two extended ideals %4 = [[4, 2; 0, 2], [-1, 0]~] @eprog\noindent If $\fl$ is nonzero, reduce the result using \kbd{idealred}. Variant: \noindent See also \fun{GEN}{idealmul}{GEN nf, GEN x, GEN y} ($\fl=0$) and \fun{GEN}{idealmulred}{GEN nf, GEN x, GEN y} ($\fl\neq0$). pari-2.17.2/src/functions/number_fields/idealappr0000644000175000017500000000221214676526175020505 0ustar billbillFunction: idealappr Section: number_fields C-Name: idealappr0 Prototype: GGD0,L, Help: idealappr(nf,x,{flag}): 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; x may also be a prime ideal factorization with possibly zero exponents. flag is deprecated (ignored), kept for backward compatibility. 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 nonzero, we have $v_{\goth{p}}(\alpha)=v_{\goth{p}}(x)$, and $v_{\goth{p}}(\alpha)\ge0$ for all other $\goth{p}$. The argument $x$ may also be given as a prime ideal factorization, as output by \kbd{idealfactor}, but allowing zero exponents. This yields an element $\alpha$ such that for all prime ideals $\goth{p}$ occurring in $x$, $v_{\goth{p}}(\alpha) = v_{\goth{p}}(x)$; for all other prime ideals, $v_{\goth{p}}(\alpha)\ge0$. $\fl$ is deprecated (ignored), kept for backward compatibility. Variant: Use directly \fun{GEN}{idealappr}{GEN nf, GEN x} since $\fl$ is ignored. pari-2.17.2/src/functions/number_fields/bnfissunit0000644000175000017500000000033714567450071020724 0ustar billbillFunction: bnfissunit Section: number_fields C-Name: bnfissunit Prototype: GGG Obsolete: 2020-01-15 Help: bnfissunit(bnf,sfu,x): this function is obsolete, use bnfisunit. Doc: this function is obsolete, use \kbd{bnfisunit}. pari-2.17.2/src/functions/number_fields/nfisideal0000644000175000017500000000036313637407207020475 0ustar billbillFunction: nfisideal Section: number_fields C-Name: isideal Prototype: lGG Help: nfisideal(nf,x): true(1) if x is an ideal in the number field nf, false(0) if not. Doc: returns 1 if $x$ is an ideal in the number field $\var{nf}$, 0 otherwise. pari-2.17.2/src/functions/number_fields/rnfconductor0000644000175000017500000000462014676526175021257 0ustar billbillFunction: rnfconductor Section: number_fields C-Name: rnfconductor0 Prototype: GGD0,L, Help: rnfconductor(bnf,T,{flag=0}): conductor of the Abelian extension of bnf defined by T. The result is [conductor,bnr,subgroup], where conductor is the conductor itself, bnr the attached bnr structure, and subgroup the HNF defining the norm group (Artin or Takagi group) on the given generators bnr.gen. If flag is 1, return a bnr modulo deg(T), attached to Cl_f / (deg(T)); if flag is 2 only return [f, idealfactor(f[1])]. Doc: given a \var{bnf} structure attached to a number field $K$, as produced by \kbd{bnfinit}, and $T$ an irreducible polynomial in $K[x]$ defining an \idx{Abelian extension} $L = K[x]/(T)$, computes the class field theory conductor of this Abelian extension. If $T$ does not define an Abelian extension over $K$, the result is undefined; it may be the integer $0$ (in which case the extension is definitely not Abelian) or a wrong result. The result is a 3-component vector $[f,\var{bnr},H]$, where $f$ is the conductor of the extension given as a 2-component row vector $[f_{0},f_{\infty}]$, \var{bnr} is the attached \kbd{bnr} structure and $H$ is a matrix in HNF defining the subgroup of the ray class group on the ray class group generators \kbd{bnr.gen}; in particular, it is a left divisor of the diagonal matrix attached to \kbd{bnr.cyc} and $|\det H| = N = \deg T$. \item If \fl\ is $1$, return $[f,\var{bnrmod}, H]$, where \kbd{bnrmod} is now attached to $\text{Cl}_{f} / \text{Cl}_{f}^{N}$, and $H$ is as before since it contains the $N$-th powers. This is useful when $f$ contains a maximal ideal with huge residue field, since the corresponding tough discrete logarithms are trivialized: in the quotient group, all elements have small order dividing $N$. This allows to work in $\text{Cl}_{f}/H$ but no longer in $\text{Cl}_{f}$. \item If \fl\ is $2$, only return $[f, \kbd{fa}]$ where \kbd{fa} is the factorization of the conductor finite part ($=f[1]$). \misctitle{Huge discriminants, helping rnfdisc} The format $[T,B]$ is also accepted instead of $T$ and computes the conductor of the extension provided it factors completely over the maximal ideals specified by $B$, see \kbd{??rnfinit}: the valuation of $f_{0}$ is then correct at all such maximal ideals but may be incorrect at other primes. Variant: Also available is \fun{GEN}{rnfconductor}{GEN bnf, GEN T} when $\fl = 0$. pari-2.17.2/src/functions/number_fields/nfsubfieldscm0000644000175000017500000000234614676526175021400 0ustar billbillFunction: nfsubfieldscm Section: number_fields C-Name: nfsubfieldscm Prototype: GD0,L, Help: nfsubfieldscm(nf,{flag=0}): computes the maximal CM subfield of nf. Returns 0 if nf does not have a CM subfield, otherwise returns [g,h] (default) or g (flag=1) where g is an absolute equation and h expresses a root of g in terms of the generator of nf. Doc: Computes the maximal CM subfield of \var{nf}. Returns $0$ if \var{nf} does not have a CM subfield, otherwise returns~$[g,h]$ (default) or $g$ ($\fl=1$) where~$g$ is an absolute equation and~$h$ expresses a root of $g$ in terms of the generator of~\var{nf}. Moreover, the CM involution is given by $X\bmod g(X) \mapsto -X\bmod g(X)$, i.e. $X\bmod g(X)$ is a totally imaginary element. An input of the form~\kbd{[nf, fa]} is also allowed, where~\kbd{fa} is the factorisation of~\var{nf.pol} over~\var{nf}, and~\var{nf} is also allowed to be a monic defining polynomial for the number field. \bprog ? nf = nfinit(x^8 + 20*x^6 + 10*x^4 - 4*x^2 + 9); ? nfsubfieldscm(nf) %2 = [x^4 + 4480*x^2 + 3612672, 3*x^5 + 58*x^3 + 5*x] ? pol = y^16-8*y^14+29*y^12-60*y^10+74*y^8-48*y^6+8*y^4+4*y^2+1; ? fa = nffactor(pol, subst(pol,y,x)); ? nfsubfieldscm([pol,fa]) %5 = [y^8 + ... , ...] @eprog pari-2.17.2/src/functions/number_fields/bnrclassno0000644000175000017500000000227514567450071020707 0ustar billbillFunction: bnrclassno Section: number_fields C-Name: bnrclassno0 Prototype: GDGDG Help: bnrclassno(A,{B},{C}): relative degree of the class field defined by A,B,C. [A,{B},{C}] is of type [bnr], [bnr,subgroup], [bnf,modulus], or [bnf,modulus,subgroup]. Faster than bnrinit if only the ray class number is wanted. Doc: let $A$, $B$, $C$ define a class field $L$ over a ground field $K$ (of type \kbd{[\var{bnr}]}, \kbd{[\var{bnr}, \var{subgroup}]}, or \kbd{[\var{bnf}, \var{modulus}]}, or \kbd{[\var{bnf}, \var{modulus},\var{subgroup}]}, \secref{se:CFT}); this function returns the relative degree $[L:K]$. In particular if $A$ is a \var{bnf} (with units), and $B$ a modulus, this function returns the corresponding ray class number modulo $B$. One can input the attached \var{bid} (with generators if the subgroup $C$ is non trivial) for $B$ instead of the module itself, saving some time. This function is faster than \kbd{bnrinit} and should be used if only the ray class number is desired. See \tet{bnrclassnolist} if you need ray class numbers for all moduli less than some bound. Variant: Also available is \fun{GEN}{bnrclassno}{GEN bnf,GEN f} to compute the ray class number modulo~$f$. pari-2.17.2/src/functions/number_fields/modreverse0000644000175000017500000000302314676526175020720 0ustar billbillFunction: modreverse Section: number_fields C-Name: modreverse Prototype: G Help: modreverse(z): reverse polmod of the polmod z, if it exists. Doc: let $z = \kbd{Mod(A, T)}$ be a polmod, and $Q$ be its minimal polynomial, which must satisfy $\text{deg}(Q) = \text{deg}(T)$. Returns a ``reverse polmod'' \kbd{Mod(B, Q)}, which is a root of $T$. This is quite useful when one changes the generating element in algebraic extensions: \bprog ? u = Mod(x, x^3 - x -1); v = u^5; ? w = modreverse(v) %2 = Mod(x^2 - 4*x + 1, x^3 - 5*x^2 + 4*x - 1) @eprog\noindent which means that $x^{3} - 5x^{2} + 4x -1$ is another defining polynomial for the cubic field $$\Q(u) = \Q[x]/(x^{3} - x - 1) = \Q[x]/(x^{3} - 5x^{2} + 4x - 1) = \Q(v),$$ and that $u \to v^{2} - 4v + 1$ gives an explicit isomorphism. From this, it is easy to convert elements between the $A(u)\in \Q(u)$ and $B(v)\in \Q(v)$ representations: \bprog ? A = u^2 + 2*u + 3; subst(lift(A), 'x, w) %3 = Mod(x^2 - 3*x + 3, x^3 - 5*x^2 + 4*x - 1) ? B = v^2 + v + 1; subst(lift(B), 'x, v) %4 = Mod(26*x^2 + 31*x + 26, x^3 - x - 1) @eprog If the minimal polynomial of $z$ has lower degree than expected, the routine fails \bprog ? u = Mod(-x^3 + 9*x, x^4 - 10*x^2 + 1) ? modreverse(u) *** modreverse: domain error in modreverse: deg(minpoly(z)) < 4 *** Break loop: type 'break' to go back to GP prompt break> Vec( dbg_err() ) \\ ask for more info ["e_DOMAIN", "modreverse", "deg(minpoly(z))", "<", 4, Mod(-x^3 + 9*x, x^4 - 10*x^2 + 1)] break> minpoly(u) x^2 - 8 @eprog pari-2.17.2/src/functions/number_fields/nfsnf0000644000175000017500000000271414676526175017665 0ustar billbillFunction: nfsnf Section: number_fields C-Name: nfsnf0 Prototype: GGD0,L, Help: nfsnf(nf,x,{flag=0}): if x=[A,I,J], outputs D=[d_1,...d_n] Smith normal form of x. If flag is nonzero return [D,U,V], where UAV = Id. Doc: given a torsion $\Z_{K}$-module $x$ attached to the square integral invertible pseudo-matrix $(A,I,J)$, returns an ideal list $D=[d_{1},\dots,d_{n}]$ which is the \idx{Smith normal form} of $x$. In other words, $x$ is isomorphic to $\Z_{K}/d_{1}\oplus\cdots\oplus\Z_{K}/d_{n}$ and $d_{i}$ divides $d_{i-1}$ for $i\ge2$. If $\fl$ is nonzero return $[D,U,V]$, where $UAV$ is the identity. See \secref{se:ZKmodules} for the definition of integral pseudo-matrix; briefly, it is input as a 3-component row vector $[A,I,J]$ where $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_{1}e_{1}\oplus\cdots\oplus b_{n}e_{n}) / (a_{1}A_{1}\oplus\cdots\oplus a_{n}A_{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$. Variant: Also available: \fun{GEN}{nfsnf}{GEN nf, GEN x} ($\fl = 0$). pari-2.17.2/src/functions/number_fields/gcharlocal0000644000175000017500000000440014676526175020644 0ustar billbillFunction: gcharlocal Section: number_fields C-Name: gcharlocal Prototype: GGGpD& Help: gcharlocal(gc,chi,v,{&BID}): if v is a place, return the local character chi_v. If v is a prime dividing the modulus and the optional argument 'BID' is present, set BID to the corresponding idealstar structure. Doc: \kbd{gc} being a gchar structure initialised by \kbd{gcharinit}, returns the local component $\chi_{v}$, where $v$ is either an integer between~$1$ and~$r_{1}+r_{2}$ encoding an infinite place, or a prime ideal structure encoding a finite place. \item if~$v$ is a real place, $\chi_{v}(x) = {\rm sign}(x)^{k} |x|^{i\varphi}$ is encoded as~$[k,\varphi]$; \item if~$v$ is a complex place, $\chi_{v}(z) = (z/|z|)^{k} |z|^{2i\varphi}$ is encoded as~$[k,\varphi]$; \item if~$v = \goth{p}$ is a finite place not dividing~\var{gc}\kbd{.mod}, $\chi_{v}(\pi_{v}) = \exp(2i\pi \theta)$ is encoded as~$[\theta]$; \item if~$v = \goth{p}$ is a finite place dividing~\var{gc}\kbd{.mod}, we can define a \var{bid} structure attached to the multiplicative group $G = (\Z_{K}/\goth{p}^{k})^{*}$, where $\goth{p}^{k}$ divides exactly \var{gc}\kbd{.mod} (see \kbd{idealstar}). Then~$\chi_{v}$ is encoded as~$[c_{1},\dots,c_{n},\theta]$ where~$[c_{1},\dots,c_{n}]$ defines a character on $G$ (see \kbd{gchareval}) and~$\chi_{v}(\pi_{v}) = \exp(2i\pi\theta)$. This \var{bid} structure only depends on \kbd{gc} and $v$ (and not on the character $\chi$); it can be recovered through the optional argument \var{BID}. \bprog ? bnf = bnfinit(x^3-x-1); ? gc = gcharinit(bnf,1); ? gc.cyc % = [0, 0, 0.E-57] ? chi = [0,1,1/3]~; ? pr = idealprimedec(bnf,5)[1]; ? gcharlocal(gc,chi,1) % = [0, -4.8839310048284836274074581373242545693 - 1/3*I] ? gcharlocal(gc,chi,2) % = [6, 2.4419655024142418137037290686621272847 - 1/3*I] ? gcharlocal(gc,chi,pr) % = [0.115465135184293124024408915 + 0.0853833331211293579127218326*I] ? bnf = bnfinit(x^2+1,1); ? pr3 = idealprimedec(bnf,3)[1]; ? pr5 = idealprimedec(bnf,5)[1]; ? gc = gcharinit(bnf,[pr3,2;pr5,3]); ? gc.cyc % = [600, 3, 0, 0.E-57] ? chi = [1,1,1]~; ? gcharlocal(gc,chi,pr3,&bid) % = [1, 1, -21/50] ? bid.cyc % = [24, 3] ? gcharlocal(gc,chi,pr5,&bid) % = [98, -0.30120819117478336291229946188762973702] ? bid.cyc % = [100] @eprog pari-2.17.2/src/functions/number_fields/bnrcompositum0000644000175000017500000000162514567450071021442 0ustar billbillFunction: bnrcompositum Section: number_fields C-Name: bnrcompositum Prototype: GG Help: bnrcompositum(A,B): compositum [bnr,H] of the two abelian extensions given by A = [bnr1,H1] and B = [bnr2,H2], where bnr1 and bnr2 are attached to the same base field. Doc: given two abelian extensions $A = \kbd{[bnr1, H1]}$ and $B = \kbd{[bnr2, H2]}$, where \kbd{bnr1} and \kbd{bnr2} are two \kbd{bnr} structures attached to the same base field, return their compositum as \kbd{[bnr, H]}. The modulus attached to \kbd{bnr} need not be the conductor of the compositum. \bprog ? Q = bnfinit(y); ? bnr1 = bnrinit(Q, [7, [1]]); bnr1.cyc %2 = [6] ? bnr2 = bnrinit(Q, [13, [1]]); bnr2.cyc %3 = [12] ? H1 = Mat(2); bnrclassfield(bnr1, H1) %4 = [x^2 + 7] ? H2 = Mat(2); bnrclassfield(bnr2, H2) %5 = [x^2 - 13] ? [bnr,H] = bnrcompositum([bnr1, H1], [bnr2,H2]); ? bnrclassfield(bnr,H) %7 = [x^2 - 13, x^2 + 7] @eprog pari-2.17.2/src/functions/number_fields/galoisconjclasses0000644000175000017500000000210014567450071022234 0ustar billbillFunction: galoisconjclasses Section: number_fields C-Name: galoisconjclasses Prototype: G Help: galoisconjclasses(gal): gal being output by galoisinit, return the list of conjugacy classes. Doc: \var{gal} being output by \kbd{galoisinit}, return the list of conjugacy classes of the underlying group. The ordering of the classes is consistent with \kbd{galoischartable} and the trivial class comes first. \bprog ? G = galoisinit(x^6+108); ? galoisidentify(G) %2 = [6, 1] \\ S_3 ? S = galoisconjclasses(G) %3 = [[Vecsmall([1,2,3,4,5,6])], [Vecsmall([3,1,2,6,4,5]),Vecsmall([2,3,1,5,6,4])], [Vecsmall([6,5,4,3,2,1]),Vecsmall([5,4,6,2,1,3]), Vecsmall([4,6,5,1,3,2])]] ? [[permorder(c[1]),#c] | c <- S ] %4 = [[1,1], [3,2], [2,3]] @eprog\noindent This command also accepts subgroups returned by \kbd{galoissubgroups}: \bprog ? subs = galoissubgroups(G); H = subs[5]; ? galoisidentify(H) %2 = [2, 1] \\ Z/2 ? S = galoisconjclasses(subgroups_of_G[5]); ? [[permorder(c[1]),#c] | c <- S ] %4 = [[1,1], [2,1]] @eprog\noindent pari-2.17.2/src/functions/number_fields/idealaddtoone0000644000175000017500000000154614676526175021351 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.17.2/src/functions/number_fields/nffactor0000644000175000017500000000370214567450071020341 0ustar billbillFunction: nffactor Section: number_fields C-Name: nffactor Prototype: GG Help: nffactor(nf,T): factor polynomial T in number field nf. Doc: factorization of the univariate polynomial (or rational function) $T$ over the number field $\var{nf}$ given by \kbd{nfinit}; $T$ has coefficients in $\var{nf}$ (i.e.~either scalar, polmod, polynomial or column vector). The factors are sorted by increasing degree. The main variable of $\var{nf}$ must be of \emph{lower} priority than that of $T$, see \secref{se:priority}. However if the polynomial defining the number field occurs explicitly in the coefficients of $T$ as modulus of a \typ{POLMOD} or as a \typ{POL} coefficient, its main variable must be \emph{the same} as the main variable of $T$. For example, \bprog ? nf = nfinit(y^2 + 1); ? nffactor(nf, x^2 + y); \\@com OK ? nffactor(nf, x^2 + Mod(y, y^2+1)); \\ @com OK ? nffactor(nf, x^2 + Mod(z, z^2+1)); \\ @com WRONG @eprog It is possible to input a defining polynomial for \var{nf} instead, but this is in general less efficient since parts of an \kbd{nf} structure will then be computed internally. This is useful in two situations: when you do not need the \kbd{nf} elsewhere, or when you cannot initialize an \kbd{nf} due to integer factorization difficulties when attempting to compute the field discriminant and maximal order. In all cases, the function runs in polynomial time using Belabas's variant of \idx{van Hoeij}'s algorithm, which copes with hundreds of modular factors. \misctitle{Caveat} \kbd{nfinit([T, listP])} allows to compute in polynomial time a conditional \var{nf} structure, which sets \kbd{nf.zk} to an order which is not guaranteed to be maximal at all primes. Always either use \kbd{nfcertify} first (which may not run in polynomial time) or make sure to input \kbd{nf.pol} instead of the conditional \var{nf}: \kbd{nffactor} is able to recover in polynomial time in this case, instead of potentially missing a factor. pari-2.17.2/src/functions/number_fields/bnrchar0000644000175000017500000000304514676526175020170 0ustar billbillFunction: bnrchar Section: number_fields C-Name: bnrchar Prototype: GGDG Help: bnrchar(G,g,{v}): returns all characters chi on G such that chi(g[i]) = e(v[i]); if v is omitted, returns all characters that are trivial on the g[i]. Doc: returns all characters $\chi$ on $G$ such that $\chi(g_{i}) = e(v_{i})$, where $e(x) = \exp(2i\pi x)$. $G$ is allowed to be a \var{bnr} struct (representing a ray class group) or a \var{znstar} (representing $(\Z/N\Z)^{*}$). If $v$ is omitted, returns all characters that are trivial on the $g_{i}$. Else the vectors $g$ and $v$ must have the same length, the $g_{i}$ must be elements of $G$, and each $v_{i}$ is a rational number whose denominator must divide the order of $g_{i}$ in $G$. For convenience, the vector of the $g_{i}$ can be replaced by a matrix whose columns give their discrete logarithm in $G$, for instance as given by \kbd{bnrisprincipal} if $G$ is a \var{bnr}; in this particular case, $G$ can be any finite abelian group given by a vector of elementary divisors. \bprog ? G = bnrinit(bnfinit(x), [160,[1]], 1); /* (Z/160Z)^* */ ? G.cyc %2 = [8, 4, 2] ? g = G.gen; ? bnrchar(G, g, [1/2,0,0]) %4 = [[4, 0, 0]] \\ a unique character ? bnrchar(G, [g[1],g[3]]) \\ all characters trivial on g[1] and g[3] %5 = [[0, 1, 0], [0, 2, 0], [0, 3, 0], [0, 0, 0]] ? bnrchar(G, [1,0,0;0,1,0;0,0,2]) %6 = [[0, 0, 1], [0, 0, 0]] \\ characters trivial on given subgroup ? G = znstar(75, 1); ? bnrchar(G, [2, 7], [11/20, 1/4]) %8 = [[1, 1]] \\ Dirichlet char: chi(2) = e(11/20), chi(7) = e(1/4) @eprog pari-2.17.2/src/functions/number_fields/nfeltdiv0000644000175000017500000000034214567450071020347 0ustar billbillFunction: nfeltdiv Section: number_fields C-Name: nfdiv Prototype: GGG Help: nfeltdiv(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.17.2/src/functions/number_fields/rnfpolredbest0000644000175000017500000000365714567450071021421 0ustar billbillFunction: rnfpolredbest Section: number_fields C-Name: rnfpolredbest Prototype: GGD0,L, Help: rnfpolredbest(nf,pol,{flag=0}): given a pol with coefficients in nf, finds a relative polynomial P defining the same field, hopefully simpler than pol; flag can be 0: default, 1: return [P,a], where a is a root of pol 2: return an absolute polynomial Pabs, 3: return [Pabs, a,b], where a is a root of nf.pol and b is a root of pol. Doc: relative version of \kbd{polredbest}. Given a polynomial \var{pol} with coefficients in $\var{nf}$, finds a simpler relative polynomial $P$ defining the same field. As opposed to \tet{rnfpolredabs} this function does not return a \emph{smallest} (canonical) polynomial with respect to some measure, but it does run in polynomial time. The binary digits of $\fl$ correspond to $1$: add information to convert elements to the new representation, $2$: absolute polynomial, instead of relative. More precisely: 0: default, return $P$ 1: returns $[P,a]$ where $P$ is the default output and $a$, a \typ{POLMOD} modulo $P$, is a root of \var{pol}. 2: returns \var{Pabs}, an absolute, instead of a relative, polynomial. Same as but faster than \bprog rnfequation(nf, rnfpolredbest(nf,pol)) @eprog 3: returns $[\var{Pabs},a,b]$, where \var{Pabs} is an absolute polynomial as above, $a$, $b$ are \typ{POLMOD} modulo \var{Pabs}, roots of \kbd{nf.pol} and \var{pol} respectively. \bprog ? K = nfinit(y^3-2); pol = x^2 +x*y + y^2; ? [P, a] = rnfpolredbest(K,pol,1); ? P %3 = x^2 - x + Mod(y - 1, y^3 - 2) ? a %4 = Mod(Mod(2*y^2+3*y+4,y^3-2)*x + Mod(-y^2-2*y-2,y^3-2), x^2 - x + Mod(y-1,y^3-2)) ? subst(K.pol,y,a) %5 = 0 ? [Pabs, a, b] = rnfpolredbest(K,pol,3); ? Pabs %7 = x^6 - 3*x^5 + 5*x^3 - 3*x + 1 ? a %8 = Mod(-x^2+x+1, x^6-3*x^5+5*x^3-3*x+1) ? b %9 = Mod(2*x^5-5*x^4-3*x^3+10*x^2+5*x-5, x^6-3*x^5+5*x^3-3*x+1) ? subst(K.pol,y,a) %10 = 0 ? substvec(pol,[x,y],[a,b]) %11 = 0 @eprog pari-2.17.2/src/functions/number_fields/idealcoprime0000644000175000017500000000071114567450071021171 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$. In fact, $\beta$ is also guaranteed to be integral outside primes dividing $y$. pari-2.17.2/src/functions/number_fields/nfislocalpower0000644000175000017500000000153314676526175021600 0ustar billbillFunction: nfislocalpower Section: number_fields C-Name: nfislocalpower Prototype: lGGGG Help: nfislocalpower(nf,pr,a,n): true(1) if a is an n-th power in the local field K_v, false(0) if not. Doc: Let \var{nf} be a \var{nf} structure attached to a number field $K$, let $a \in K$ and let \var{pr} be a \var{prid} structure attached to a maximal ideal $v$. Return $1$ if $a$ is an $n$-th power in the completed local field $K_{v}$, and $0$ otherwise. \bprog ? K = nfinit(y^2+1); ? P = idealprimedec(K,2)[1]; \\ the ramified prime above 2 ? nfislocalpower(K,P,-1, 2) \\ -1 is a square %3 = 1 ? nfislocalpower(K,P,-1, 4) \\ ... but not a 4-th power %4 = 0 ? nfislocalpower(K,P,2, 2) \\ 2 is not a square %5 = 0 ? Q = idealprimedec(K,5)[1]; \\ a prime above 5 ? nfislocalpower(K,Q, [0, 32]~, 30) \\ 32*I is locally a 30-th power %7 = 1 @eprog pari-2.17.2/src/functions/number_fields/nfdisc0000644000175000017500000000352114760123736020004 0ustar billbillFunction: nfdisc Section: number_fields C-Name: nfdisc Prototype: G Help: nfdisc(T): discriminant of the number field defined by the polynomial T. An argument [T,listP] is possible, where listP is a list of primes or a prime bound. Doc: \idx{field discriminant} of the number field defined by the integral, preferably monic, irreducible polynomial $T(X)$. Returns the discriminant of the number field $\Q[X]/(T)$, using the Round $4$ algorithm. \misctitle{Local discriminants, valuations at certain primes} As in \kbd{nfbasis}, the argument $T$ can be replaced by $[T,\var{listP}]$, where \kbd{listP} is as in \kbd{nfbasis}: a vector of pairwise coprime integers (usually distinct primes), a factorization matrix, or a single integer. In that case, the function returns the discriminant of an order whose basis is given by \kbd{nfbasis(T,listP)}, which need not be the maximal order, and whose valuation at a prime entry in \kbd{listP} is the same as the valuation of the field discriminant. In particular, if \kbd{listP} is $[p]$ for a prime $p$, we can return the $p$-adic discriminant of the maximal order of $\Z_{p}[X]/(T)$, as a power of $p$, as follows: \bprog ? padicdisc(T,p) = p^valuation(nfdisc([T,[p]]), p); ? nfdisc(x^2 + 6) %2 = -24 ? padicdisc(x^2 + 6, 2) %3 = 8 ? padicdisc(x^2 + 6, 3) %4 = 3 @eprog\noindent The following function computes the discriminant of the maximal order under the assumption that $P$ is a vector of prime numbers containing (at least) all prime divisors of the field discriminant: \bprog globaldisc(T, P) = { my (D = nfdisc([T, P])); sign(D) * vecprod([p^valuation(D,p) | p <-P]); } ? globaldisc(x^2 + 6, [2, 3, 5]) %1 = -24 @eprog \synt{nfdisc}{GEN T}. Also available is \fun{GEN}{nfbasis}{GEN T, GEN *d}, which returns the order basis, and where \kbd{*d} receives the order discriminant. pari-2.17.2/src/functions/number_fields/rnfeltnorm0000644000175000017500000000077214676526175020743 0ustar billbillFunction: rnfeltnorm Section: number_fields C-Name: rnfeltnorm Prototype: GG Help: rnfeltnorm(rnf,x): returns the relative norm N_{L/K}(x), as an element of K. Doc: $\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ being an element of $L$, returns the relative norm $N_{L/K}(x)$ as an element of $K$. \bprog ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y); ? rnfeltnorm(L, Mod(x, L.pol)) %2 = Mod(x, x^2 + Mod(-y, y^2 + 1)) ? rnfeltnorm(L, 2) %3 = 4 @eprog pari-2.17.2/src/functions/number_fields/bnfunits0000644000175000017500000000472614676526175020410 0ustar billbillFunction: bnfunits Section: number_fields C-Name: bnfunits Prototype: GDG Help: bnfunits(bnf,{S}): return the fundamental units of the number field bnf output by bnfinit; if S is present and is a list of prime ideals, compute fundamental S-units instead. The first component of the result contains the S-units, followed by fundamental units, followed by the torsion unit. The result may be used as an optional argument to bnfisunit. Doc: return the fundamental units of the number field bnf output by bnfinit; if $S$ is present and is a list of prime ideals, compute fundamental $S$-units instead. The first component of the result contains independent integral $S$-units generators: first nonunits, then $r_{1}+r_{2}-1$ fundamental units, then the torsion unit. The result may be used as an optional argument to bnfisunit. The units are given in compact form: no expensive computation is attempted if the \var{bnf} does not already contain units. \bprog ? bnf = bnfinit(x^4 - x^3 + 4*x^2 + 3*x + 9, 1); ? bnf.sign \\ r1 + r2 - 1 = 1 %2 = [0, 2] ? U = bnfunits(bnf); u = U[1]; ? #u \\ r1 + r2 = 2 units %5 = 2; ? u[1] \\ fundamental unit as factorization matrix %6 = [[0, 0, -1, -1]~ 1] [[2, -1, -1, 0]~ -2] [ [1, 1, 0, 0]~ 2] [ [-1, 1, 1, 1]~ -1] ? u[2] \\ torsion unit as factorization matrix %7 = [[1, -1, 0, 0]~ 1] ? [nffactorback(bnf, z) | z <- u] \\ same units in expanded form %8 = [[-1, 1, -1, 0]~, [1, -1, 0, 0]~] @eprog Now an example involving $S$-units for a nontrivial $S$: \bprog ? S = idealprimedec(bnf,5); #S %9 = 2 ? US = bnfunits(bnf, S); uS = US[1]; ? g = [nffactorback(bnf, z) | z <- uS] \\ now 4 units %11 = [[6, -3, -2, -2]~, [-5, 5, 0, 0]~, [-1, 1, -1, 0]~, [1, -1, 0, 0]~] ? bnfisunit(bnf,[10,-40,24,11]~) %12 = []~ \\ not a unit ? e = bnfisunit(bnf, [10,-40,24,11]~, US) %13 = [2, 0, 1, 4]~ \\ ...but an S-unit ? nffactorback(bnf, g, e) %14 = [10, -40, 24, 11]~ ? nffactorback(bnf, uS, e) \\ in factored form %15 = [[6, -3, -2, -2]~ 2] [ [0, 0, -1, -1]~ 1] [ [2, -1, -1, 0]~ -2] [ [1, 1, 0, 0]~ 2] [ [-1, 1, 1, 1]~ -1] [ [1, -1, 0, 0]~ 4] @eprog\noindent Note that in more complicated cases, any \kbd{nffactorback} fully expanding an element in factored form could be \emph{very} expensive. On the other hand, the final example expands a factorization whose components are themselves in factored form, hence the result is a factored form: this is a cheap operation. pari-2.17.2/src/functions/number_fields/bnfinit0000644000175000017500000001547714676526175020216 0ustar billbillFunction: bnfinit Section: number_fields C-Name: bnfinit0 Prototype: GD0,L,DGp Help: bnfinit(P,{flag=0},{tech=[]}): compute the necessary data for future use in ideal and unit group computations, including fundamental units if they are not too large. flag and tech are both optional. flag can be any of 0: default, 1: include all data in algebraic form (compact units). See manual for details about tech. Description: (gen):bnf:prec Buchall($1, 0, $prec) (gen, 0):bnf:prec Buchall($1, 0, $prec) (gen, 1):bnf:prec Buchall($1, nf_FORCE, $prec) (gen, ?small, ?gen):bnf:prec bnfinit0($1, $2, $3, $prec) Doc: initializes a \kbd{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. The meaning of $\fl$ is as follows: \item $\fl = 0$ (default). This is the historical behavior, kept for compatibility reasons and speed. It has severe drawbacks but is likely to be a little faster than the alternative, twice faster say, so only use it if speed is paramount, you obtain a useful speed gain for the fields under consideration, and you are only interested in the field invariants such as the classgroup structure or its regulator. The computations involve exact algebraic numbers which are replaced by floating point embeddings for the sake of speed. If the precision is insufficient, \kbd{gp} may not be able to compute fundamental units, nor to solve some discrete logarithm problems. It \emph{may} be possible to increase the precision of the \kbd{bnf} structure using \kbd{nfnewprec} but this may fail, in particular when fundamental units are large. In short, the resulting \kbd{bnf} structure is correct and contains useful information but later function calls to \kbd{bnfisprincpal} or \kbd{bnrclassfield} may fail. When $\fl=1$, we keep an exact algebraic version of all floating point data and this allows to guarantee that functions using the structure will always succeed, as well as to compute the fundamental units exactly. The units are computed in compact form, as a product of small $S$-units, possibly with huge exponents. This flag also allows \kbd{bnfisprincipal} to compute generators of principal ideals in factored form as well. Be warned that expanding such products explicitly can take a very long time, but they can easily be mapped to floating point or $\ell$-adic embeddings of bounded accuracy, or to $K^{*}/(K^{*})^{\ell}$, and this is enough for applications. In short, this flag should be used by default, unless you have a very good reason for it, for instance building massive tables of class numbers, and you do not care about units or the effect large units would have on your computation. $\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} are technical. 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]$ 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}, the number of roots of unity and a generator \kbd{\var{bnf}.tu}, the fundamental units \emph{in expanded form} \kbd{\var{bnf}.fu}. If the fundamental units were omitted in the \var{bnf}, \kbd{\var{bnf}.fu} returns the sentinel value $0$. If $\fl = 1$, this vector contain also algebraic data corresponding to the fundamental units and to the discrete logarithm problem (see \kbd{bnfisprincipal}). In particular, if $\fl = 1$ we may \emph{only} know the units in factored form: the first call to \kbd{\var{bnf}.fu} expands them, which may be very costly, then caches the result. $\var{bnf}[9]$ is a 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}]$, followed by technical exact components which allow to recompute $g_{a}$ and $GD_{a}$ to higher accuracy. $\var{bnf}[10]$ is by default unused and set equal to 0. This field is used to store further information about the field as it becomes available, which is rarely needed, hence would be too expensive to compute during the initial \kbd{bnfinit} call. For instance, the generators of the principal ideals \kbd{bnf.gen[i]\pow bnf.cyc[i]} (during a call to \tet{bnrisprincipal}), or those corresponding to the relations in $W$ and $B$ (when the \kbd{bnf} internal precision needs to be increased). Variant: Also available is \fun{GEN}{Buchall}{GEN P, long flag, long prec}, corresponding to \kbd{tech = NULL}, where $\fl$ is either $0$ (default) or \tet{nf_FORCE} (include all data in algebraic form). The function \fun{GEN}{Buchall_param}{GEN P, double c1, double c2, long nrpid, long flag, long prec} gives direct access to the technical parameters. pari-2.17.2/src/functions/number_fields/nfmodpr0000644000175000017500000000233114760123736020201 0ustar billbillFunction: nfmodpr Section: number_fields C-Name: nfmodpr Prototype: GGG Help: nfmodpr(nf,x,pr): map x to the residue field mod pr. Doc: map $x$ to a \typ{FFELT} in the residue field modulo \var{pr}. The argument \var{pr} is either a maximal ideal in \kbd{idealprimedec} format or, preferably, a \var{modpr} structure from \tet{nfmodprinit}. The function \tet{nfmodprlift} allows to lift back to $\Z_{K}$. Note that the function applies to number field elements and not to vector / matrices / polynomials of such. Use \kbd{apply} to convert recursive structures. \bprog ? K = nfinit(y^3-250); ? P = idealprimedec(K, 5)[2]; ? modP = nfmodprinit(K, P, 't); ? K.zk %4 = [1, 1/5*y, 1/25*y^2] ? apply(t->nfmodpr(K,t,modP), K.zk) %5 = [1, t, 2*t + 1] ? %[1].mod %6 = t^2 + 3*t + 4 ? K.index %7 = 125 @eprog\noindent For clarity, we represent elements in the residue field $\F_{5}[t]/(T)$ as polynomials in the variable $t$. Whenever the underlying rational prime does not divide \kbd{K.index}, it is actually the case that $t$ is the reduction of $y$ in $\Q[y]/(\kbd{K.pol})$ modulo an irreducible factor of \kbd{K.pol} over $\F_{p}$. In the above example, $5$ divides the index and $t$ is actually the reduction of $y/5$. pari-2.17.2/src/functions/number_fields/nfnewprec0000644000175000017500000000155014676526175020537 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}, a \var{bnr} or a \var{rnf} (update structure to current precision). \emph{If} the original \var{bnf} structure was \emph{not} computed by \kbd{bnfinit(,1)}, then this may be quite slow and even fail: many generators of principal ideals have to be computed and the algorithm may fail because the accuracy is not sufficient to bootstrap the required generators and fundamental units. Variant: See also \fun{GEN}{bnfnewprec}{GEN bnf, long prec} and \fun{GEN}{bnrnewprec}{GEN bnr, long prec}. pari-2.17.2/src/functions/number_fields/rnfdedekind0000644000175000017500000000672214712416772021023 0ustar billbillFunction: rnfdedekind Section: number_fields C-Name: rnfdedekind Prototype: GGDGD0,L, Help: rnfdedekind(nf,pol,{pr},{flag=0}): relative Dedekind criterion over the number field K, represented by nf, applied to the order Z_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 Z_K[X]. Returns [max,basis,v], where basis is a pseudo-basis of the enlarged order, max is 1 iff this order is pr-maximal, and v is the valuation at pr of the order discriminant. If flag is set, just return 1 if the order is maximal, and 0 if not. Doc: given a number field $K$ coded by $\var{nf}$ and a monic polynomial $P\in \Z_{K}[X]$, irreducible over $K$ and thus defining a relative extension $L$ of $K$, applies \idx{Dedekind}'s criterion to the order $\Z_{K}[X]/(P)$, at the prime ideal \var{pr}. It is possible to set \var{pr} to a vector of prime ideals (test maximality at all primes in the vector), or to omit altogether, in which case maximality at \emph{all} primes is tested; in this situation \fl\ is automatically set to $1$. The default historic behavior (\fl\ is 0 or omitted and \var{pr} is a single prime ideal) is not so useful since \kbd{rnfpseudobasis} gives more information and is generally not that much slower. It returns a 3-component vector $[\var{max}, \var{basis}, v]$: \item \var{basis} is a pseudo-basis of an enlarged order $O$ produced by Dedekind's criterion, containing the original order $\Z_{K}[X]/(P)$ with index a power of \var{pr}. Possibly equal to the original order. \item \var{max} is a flag equal to 1 if the enlarged order $O$ could be proven to be \var{pr}-maximal and to 0 otherwise; it may still be maximal in the latter case if \var{pr} is ramified in $L$, \item $v$ is the valuation at \var{pr} of the order discriminant. If \fl\ is nonzero, 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) %3 = [1, [[1, 0, 0; 0, 1, 0; 0, 0, 1], [1, 1, 1]], 8] ? rnfdedekind(nf, P, pr3, 1) %4 = 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) %6 = 0 ? rnfdedekind(nf, P, pr2) %7 = [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) %8 = [[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) %9 = 2 @eprog\noindent It is possible to use this routine with nonmonic $P = \sum_{i\leq n} p_{i} X^{i} \in \Z_{K}[X]$ if $\fl = 1$; in this case, we test maximality of Dedekind's order generated by $$1, p_{n} \alpha, p_{n}\alpha^{2} + p_{n-1}\alpha, \dots, p_{n}\alpha^{n-1} + p_{n-1}\alpha^{n-2} + \cdots + p_{1}\alpha.$$ The routine will fail if $P$ vanishes on the projective line over the residue field $\Z_{K}/\kbd{pr}$ (FIXME). pari-2.17.2/src/functions/number_fields/bnfsignunit0000644000175000017500000000177314676526175021105 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 K.tu, K.fu */ tpuexpo(K)= { my(M, S = bnfsignunit(K), [m,n] = matsize(S)); \\ m = K.r1, n = r1+r2-1 S = matrix(m,n, i,j, if (S[i,j] < 0, 1,0)); S = concat(vectorv(m,i,1), S); \\ add sign(-1) M = matkermod(S, 2); if (M, mathnfmodid(M, 2), 2*matid(n+1)) } /* totally positive fundamental units of bnf K */ tpu(K)= { my(ex = tpuexpo(K)[,^1]); \\ remove ex[,1], corresponds to 1 or -1 my(v = concat(K.tu[2], K.fu)); [ nffactorback(K, v, c) | c <- ex]; } @eprog pari-2.17.2/src/functions/number_fields/bnrstark0000644000175000017500000000431014567450071020361 0ustar billbillFunction: bnrstark Section: number_fields C-Name: bnrstark Prototype: GDGp Help: bnrstark(bnr,{subgroup}): 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 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}, 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); 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 rnfpolredbest(bnf, pol) \\@com compute a reduced relative polynomial rnfpolredbest(bnf, pol, 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. We decided that it was useful to keep the extra information thus made available, hence the user has to take the compositum herself, see \kbd{nfcompositum}. 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{bnrclassfield}: \bprog ? bnr = bnrinit(bnfinit(y^8-12*y^6+36*y^4-36*y^2+9,1), 2); ? bnrstark(bnr) *** at top-level: bnrstark(bnr) *** ^------------- *** bnrstark: need 3919350809720744 coefficients in initzeta. *** Computation impossible. ? bnrclassfield(bnr) time = 20 ms. %2 = [x^2 + (-2/3*y^6 + 7*y^4 - 14*y^2 + 3)] @eprog pari-2.17.2/src/functions/number_fields/nfbasistoalg0000644000175000017500000000107114567450071021210 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 \var{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)) %5 = Mod(y, y^2 + 4) @eprog This is the inverse function of \kbd{nfalgtobasis}. pari-2.17.2/src/functions/number_fields/rnfidealhnf0000644000175000017500000000072714676526175021035 0ustar billbillFunction: rnfidealhnf Section: number_fields C-Name: rnfidealhnf Prototype: GG Help: rnfidealhnf(rnf,x): relative version of idealhnf, where rnf is a relative numberfield. Doc: $\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ being a relative ideal (which can be, as in the absolute case, of many different types, including of course elements), computes the HNF pseudo-matrix attached to $x$, viewed as a $\Z_{K}$-module. pari-2.17.2/src/functions/number_fields/idealmin0000644000175000017500000000060113637407207020314 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.17.2/src/functions/number_fields/nfhnfmod0000644000175000017500000000103313637407207020331 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.17.2/src/functions/number_fields/rnfsteinitz0000644000175000017500000000210214676526175021121 0ustar billbillFunction: rnfsteinitz Section: number_fields C-Name: rnfsteinitz Prototype: GG Help: rnfsteinitz(nf,M): given a nf attached to a number field K and a projective module M given by a pseudo-matrix, returns [A,I,D,d] where (A,I) is a pseudo basis for M where all the ideals except perhaps the last are trivial. If M is a polynomial with coefficients in K, replace it by the pseudo-matrix returned by rnfpseudobasis. Doc: given a $\var{nf}$ attached to a number field $K$ and a projective module $M$ given by a pseudo-matrix, returns a 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}$. If $M$ is a polynomial with coefficients in $K$, replace it by the pseudo-matrix returned by \kbd{rnfpseudobasis} and return the four-component row vector $[A,I,D,d]$ where $(A,I)$ are as before and $(D,d)$ are discriminants as returned by \kbd{rnfpseudobasis}. The ideal class of the last ideal of $I$ is well defined; it is the \idx{Steinitz class} of $M$ (its image in $SK_{0}(\Z_{K})$). pari-2.17.2/src/functions/number_fields/subcycloiwasawa0000644000175000017500000002325314760123736021742 0ustar billbillFunction: subcycloiwasawa Section: number_fields C-Name: subcycloiwasawa Prototype: GGD0,L, Help: subcycloiwasawa(fH,p,{n=0}): Let F be the abelian number field contained in Q(zeta_f) corresponding to the subgroup H of (Z/fZ)^*. Returns the minus part of Iwasawa polynomials attached to the cyclotomic Z_p extension of F. Doc: Let $F$ be the abelian number field contained in $\Q(\zeta_{f})$ corresponding to the subgroup $H$ of $(\Z/f\Z)^{*}$, let $p > 2$ be an odd prime not dividing $[F:\Q]$, let $F_{\infty}$ be the cyclotomic $\Z_{p}$-extension of $F$ and let $F_{n}$ by its $n$-th layer. Computes the minus part of Iwasawa polynomials and $\lambda$-invariants attached to $F_{\infty}$, using the Stickelberger elements $\xi_{n}^{\chi}$ belonging to $F_{n}$. The function is only implemented when $p$, $n$ and $f$ are relatively small: all of $p^{4}$, $p^{n+1}$ and $f$ must fit into an \kbd{unsigned long} integer. The argument \kbd{fH} encodes the data $[f,H]$ as follows: \item $\kbd{fH} = [f, H]$, where $H$ is given by a vector of integral generators, \item $\kbd{fH} = [\var{bnr}, H]$, where \var{bnr} is attached to $\Cl_{f}(\Q)$ and $H$ is a congruence subgroup, \item $\kbd{fH} = [G, H]$, where $G$ is \kbd{idealstar}$(f,1)$, and $H$ is a subgroup of $(\Z/f\Z)^{\times}$, \item $\kbd{fH} = f$, where we assume that $H = \{1\}$, i.e., $F = \Q(\zeta_{f})$, \item an irreducible integral polynomial defining a primitive element for $F$. \noindent If $F$ is quadratic, we also allow $p = 2$ and more data is output (see below). For a number field $K$, we write $K_{n}$ for the $n$-th layer of the cyclotomic $\Z_{p}$-extension of $K$. The algorithm considers all cyclic subfields $K$ of $F$ and all injective odd characters $\chi:\text{Gal}(K/\Q)\rightarrow\overline{\Q}_{p}^{\times}$. Let $\Sigma_{n} = \text{Gal}(K_{n}/K)$, which is cyclic generated by the Frobenius automorphism $\sigma$; we write $K_{\chi}=\Q_{p}(\chi)$, ${\cal O}_{\chi}=\Z_{p}[\chi]$ with maximal ideal $\goth{p}$. The Stickelberger element $\xi_{n}^{\chi}$ belongs to ${\cal O}_{\chi}[\Sigma_{n}]$; the polynomial $f_{n}^{\chi}(x)\in{\cal O}_{\chi}[x]$ is constructed from $\xi_{n}^{\chi}$ by the correspondence $\sigma \mapsto 1+x$. If $n$ is sufficiently large, then $\goth{p}$ does not divide $f_{n}^{\chi}(x)$ and the distinguished polynomial $g_{n}^{\chi}(x)\in{\cal O}_{\chi}[x]$ is uniquely determined by the relation $f_{n}^{\chi}(x)=u(x)g_{n}^{\chi}(x),\,u(x)\in{\cal O}_{\chi}[x]^{\times}$. Owing to Iwasawa Main Conjecture proved by Mazur-Wiles, we can define the Iwasawa polynomial $g_{\chi}(x)=\lim_{n\rightarrow\infty}g_{n}^{\chi}(x)\in{\cal O}_{\chi}[x]$. If $r$ is the smallest integer satisfying $\deg g_{n}^{\chi}\leq p^{r}$, then we have $$g_{\chi}(x)\equiv g_{n}^{\chi}(x)\pmod{\goth{p}^{n+1-r}}\;.$$ Applying the norm from $K_{\chi}$ down to $\Q_{p}$, we obtain polynomials $G_{\chi}(x), G_{n}^{\chi}(x)\in\Z_{p}[x]$ satisfying the congruence $$G_{\chi}(x)\equiv G_{n}^{\chi}(x)\pmod{p^{n+1-r}}\;.$$ Note that $\lambda_{p}^{-}(F)=\sum_{K,\chi} \deg G_{\chi}(x)$ is the Iwasawa $\lambda^{-}$-invariant of $F$, while the $\mu$-invariant $\mu_{p}(F)$ is known to be zero by the theorem of Ferrero-Washington. If $n = 0$, the function returns $[\lambda_{p}^{-}(F)]$ (the vector may contain further useful components, see below); for positive $n$, it returns all non-constant $G_{n}^{\chi}(x)\bmod{p^{n+1-r}}$ as $(K,\chi)$ vary. \bprog ? subcycloiwasawa(22220, 41) \\ f = 22220, H = {1} %1 = [217] ? P = polcompositum(x^2 - 42853, polcyclo(5))[1]; ? subcycloiwasawa(P, 5) %3 = [3] ? subcycloiwasawa(P, 5, 4) \\ the sum of the degrees is indeed 3 %4 = [T + 585, T^2 + 405*T] @eprog The first example corresponds to $F = \Q(\zeta_{22220})$ and shows, that $\lambda_{41}^{-}(F) = 217$. The second one builds $F=\Q(\sqrt{42853}, \zeta_{5})$ then lists the non-constant $G_{4}^{\chi}(x)\bmod{p^{4}}$ for $p=5$. Note that in this case all degrees are $\leq 5$ hence $r \leq 1$ and $n+1-r\geq n$; so the above also gives $G_{\chi}$ modulo $p^{4}$. We henceforth restrict to the quadratic case, where more information is available, and $p = 2$ is now allowed: we write $F = \Q(\sqrt{d})$ of discriminant $d$ ($\neq 1$) and character $\chi$. \misctitle{Algorithm and output for $n = 0$, $F = \Q(\sqrt{d})$} Currently, only the case $d < 0$ ($F$ quadratic imaginary, i.e.~$\chi(-1)=-1$) is implemented. \item If $p > 2$, the function returns $[\lambda, \nu, [e_{0},\dots,e_{k}]]$, where $\lambda=\lambda_{p}^{-}(F)$, $p^{e_{n}}$ denotes the $p$-part of the class number of $F_{n}$ and $e_{n} = \lambda n + \nu$ for all $n > k$. We use Gold's theorem (Acta Arith. vol.26 (1974), pp.~21--32, vol.26 (1975), pp.~233--240). Then as soon as $e_{n} - e_{n-1} < \varphi(p^{n})$ for some $n \geq 1$, we have $\lambda_{p}(F)=e_{n}-e_{n-1}$; if $\chi(p)=1$ we can weaken the hypothesis to $e_{n}-e_{n-1}\leq \varphi(p^{n})$ for some $n\geq 1$ and obtain the same conclusion. To compute $e_{n} - e_{n-1}$ we use Bernoulli numbers (\kbd{subcyclohminus}) if $\chi(p) = 0$ and a much faster algorithm of Gold (Pacific J. Math. vol.40 (1972), pp.83--88) otherwise. \item For $p=2$, we use Kida's formula (Tohoku Math. J. vol. 31 (1979), pp.~91--96) and only return $[\lambda^{-}]$. When $d > 1$, \kbd{subcycloiwasawa} should calculate $\lambda_{p}(F)=\lambda_{p}^{+}(F)$, which is conjectured to be zero. But this is not yet implemented. \bprog ? subcycloiwasawa(x^2+11111, 2) %1 = [5] /*@Ccom $\lambda_{2}(\Q(\sqrt{-11111}))=5$ */ ? subcycloiwasawa(x^2+11111, 3) %2 = [1, 0, []] ? subcycloiwasawa(x^2+11111, 11) %3 = [0, 0, []] @eprog\noindent This shows that for $p = 3$, we have $\lambda = 1$, $\nu = 0$, and $e_{n} = n$ for all $n \geq 0$. And at $p = 11$, we have $e_{n} = 0$ for all $n \geq 0$. \bprog ? subcycloiwasawa(x^2+1501391, 3) time = 23 ms. %4 = [14, -16, [2, 5]] @eprog\noindent computes $e_{n}$ by Gold's algorithm for $F=\Q(\sqrt{-1501391})$. This shows that at $p = 3$, we have $\lambda=14$, $\nu=-16$, then $e_{0}=2$, $e_{1}=5$, and $e_{n}=14n-16$ for $n\geq 2$. \bprog ? subcycloiwasawa(x^2+956238, 3) time = 141 ms. %5 = [14, -19, [1, 3]] @eprog\noindent computes $e_{n}$ using Bernoulli numbers for $F=\Q(\sqrt{-956238})$. This shows that $e_{0}=1$, $e_{1}=3$ and $e_{n}=14n-19$ for $n \geq 2$. \misctitle{Algorithm and output for $n > 0$; $F = \Q(\sqrt{d})$} \item When $d < 0$ and $n\geq 1$, \kbd{subcycloiwasawa} computes the Stickelberger element $\xi_{n} = \xi_{n}^{\chi}\in\Z_{p}[\Sigma_{n}]$ and the Iwasawa polynomial $g(x) = g_{\chi}(x)\in\Z_{p}[x]$ from the $n$-th layer $F_{n}$ of the cyclotomic $\Z_{p}$-extension of $F$. Let $q$ be $p$ ($p$ odd) or 4 ($p = 2$) and let $q_{0}$ be the lcm of $q$ and the discriminant $d$ of $F$, and let $q_{n}=q_{0}p^{n}$. Then $\Sigma_{n}=\text{Gal}(\Q_{n}/\Q)=\text{Gal}(F_{n}/F) =\langle\,s\,\rangle$, where $s$ is the Frobenius automorphism $(\Q_{n}/\Q,1+q_{0})$ and $$\xi_{n}=q_{n}^{-1}\sum_{a=1, (a,q_{n})=1}^{q_{n}} a\chi(a)^{-1}(\Q_{n}/\Q,a)^{-1}$$ is an element of $\Q[\Sigma_{n}]$. For $(p,d)=(2,-1),(2,-2),(2,-3), (2,-6),(3,-3)$, we know that $\lambda_{p}(F)=0$ and there is nothing to do. For the other cases, it is proved that $(1/2)\xi_{n}\in\Z_{p}[\Sigma_{n}]$. The polynomial $f_{n}(x)\in\Z_{p}[x]$ is constructed from $(1/2)\xi_{n}$ by the correspondence $s\mapsto 1+x$. If $n$ is sufficiently large, then $p$ does not divide $f_{n}(x)$ and the distinguished polynomial $g_{n}(x)\in\Z_{p}[x]$ is uniquely determined by the relation $f_{n}(x)=u(x)g_{n}(x)$, $u(x)\in\Z_{p}[[x]]^{\times}$. The Iwasawa polynomial $g(x)$ is defined by $g(x)=\lim_{n\rightarrow\infty}g_{n}(x)$; if $r$ is the smallest integer satisfying $\deg g=\lambda_{p}(F)\leq p^{r}$, then we have $g(x)\equiv g_{n}(x)\pmod{\,p^{n+1-r}}$ when $p>2$ and modulo $2^{n-r}$ otherwise. \noindent Conjecturally, we have further 1. case $q_{0}=p$: $\xi_{n}\in\Z[\Sigma_{n}]$. 2. case $d=-1$ and $\chi(p)=-1$: $\xi_{n}\in\Z[\Sigma_{n}]$. 3. case $d=-3$ and $\chi(p)=-1$: $(3/2)\xi_{n}\in\Z[\Sigma_{n}]$. 4. other cases: $(1/2)\xi_{n}\in\Z[\Sigma_{n}]$. \noindent Finally, \kbd{subcycloiwasawa} outputs $[g]$ where $g$ is $g_{n}(x)\bmod{p^{n+1-r}}$ ($p$ odd) or $\bmod{2^{n-r}}$ ($p = 2$). \bprog ? subcycloiwasawa(x^2+239, 3, 10) %6 = [x^6 + 18780*x^5 + 14526*x^4 + 18168*x^3 + 3951*x^2 + 1128*x] @eprog\noindent This is $g(x)\bmod{3^{9}}$. Indeed, $n = 10$, $\lambda = 6$ (the degree), hence $r = 2$ and $n + 1 - r = 2$. \item When $d > 1$ and $n\geq 1$, $\xi_{n}^{*}\in\Q[\Sigma_{n}]$ is constructed from $\chi^{*}=\chi^{-1}\omega$, where $\chi$ is the character of $F=\Q(\sqrt{d}\,)$ and $\omega$ is the Teichm\"uller character $\bmod{\,q}$. Next we construct $f_{n}^{*}(x)\in\Z_{p}[x]$ from $(1/2)\xi_{n}^{*}$ by the correspondence $s^{-1}\mapsto (1+x)(1+q_{0})^{-1}$ and define the distinguished polynomial $g_{n}^{*}(x)\in\Z_{p}[x]$ using $f_{n}^{*}(x)$. Then $g^{*}(x)=\lim_{n\rightarrow\infty}g_{n}^{*}(x)$ is the Iwasawa polynomial, which has a connection with Greenberg conjecture for $F$. Let $r$ be the smallest integer satisfying $\deg g^{*}\leq p^{r}$, then we have $g^{*}(x)\equiv g_{n}^{*}(x)\pmod{\,p^{n+1-r}}$ when $p>2$ and $g^{*}(x)\equiv g_{n}^{*}(x)\pmod{\,2^{n-r}}$ when $p=2$. Finally, \kbd{subcycloiwasawa} outputs $[g^{*}]$ where $g^{*}$ is $g_{n}^{*}(x)\bmod{p^{n+1-r}}$ ($p$ odd) or $\bmod{2^{n-r}}$ ($p = 2$). \bprog ? subcycloiwasawa(x^2-13841, 2, 19) time = 1min, 17,238 ms. %7 = [x^3 + 30644*x^2 + 126772*x + 44128] @eprog \noindent This is $g^{*}(x)\bmod{\,2^{17}}$ ($r = 2$), the distinguished polynomial treated in a paper of T. Fukuda, K. Komatsu, M. Ozaki and T. Tsuji (Funct. Approx. Comment. Math. vol.54.1, pp.~7--17, 2016). pari-2.17.2/src/functions/number_fields/nfisisom0000644000175000017500000000312714567450071020367 0ustar billbillFunction: nfisisom Section: number_fields C-Name: nfisisom Prototype: GG Help: nfisisom(f,g): as nfisincl but tests whether f is isomorphic to g. Doc: as \tet{nfisincl}, but tests for isomorphism. More efficient if $f$ or $g$ is a number field structure. \bprog ? f = x^6 + 30*x^5 + 495*x^4 + 1870*x^3 + 16317*x^2 - 22560*x + 59648; ? g = x^6 + 42*x^5 + 999*x^4 + 8966*x^3 + 36117*x^2 + 21768*x + 159332; ? h = x^6 + 30*x^5 + 351*x^4 + 2240*x^3 + 10311*x^2 + 35466*x + 58321; ? #nfisisom(f,g) \\ two isomorphisms %3 = 2 ? nfisisom(f,h) \\ not isomorphic %4 = 0 \\ comparative bench ? K = nfinit(f); L = nfinit(g); B = 10^3; ? for (i=1, B, nfisisom(f,g)) time = 6,124 ms. ? for (i=1, B, nfisisom(K,g)) time = 3,356 ms. ? for (i=1, B, nfisisom(f,L)) time = 3,204 ms. ? for (i=1, B, nfisisom(K,L)) time = 3,173 ms. @eprog\noindent The function is usually very fast when the fields are nonisomorphic, whenever the fields can be distinguished via a simple invariant such as degree, signature or discriminant. It may be slower when the fields share all invariants, but still faster than computing actual isomorphisms: \bprog \\ usually very fast when the answer is 'no': ? for (i=1, B, nfisisom(f,h)) time = 32 ms. \\ but not always ? u = x^6 + 12*x^5 + 6*x^4 - 377*x^3 - 714*x^2 + 5304*x + 15379 ? v = x^6 + 12*x^5 + 60*x^4 + 166*x^3 + 708*x^2 + 6600*x + 23353 ? nfisisom(u,v) %13 = 0 ? polsturm(u) == polsturm(v) %14 = 1 ? nfdisc(u) == nfdisc(v) %15 = 1 ? for(i=1,B, nfisisom(u,v)) time = 1,821 ms. ? K = nfinit(u); L = nfinit(v); ? for(i=1,B, nfisisom(K,v)) time = 232 ms. @eprog pari-2.17.2/src/functions/number_fields/rnfeltdown0000644000175000017500000000315414676526175020734 0ustar billbillFunction: rnfeltdown Section: number_fields C-Name: rnfeltdown0 Prototype: GGD0,L, Help: rnfeltdown(rnf,x,{flag=0}): 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 (or as a \typ{COL} on \kbd{nfinit(rnf).zk}), computes $x$ as an element of $K$ as a \typ{POLMOD} if $\fl = 0$ and as a \typ{COL} otherwise. If $x$ is not in $K$, a domain error occurs. Note that if $x$ is in fact rational, it is returned as a rational number, ignoring \fl. \bprog ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y); ? L.pol %2 = x^4 + 1 ? rnfeltdown(L, Mod(x^2, L.pol)) %3 = Mod(y, y^2 + 1) ? rnfeltdown(L, Mod(x^2, L.pol), 1) %4 = [0, 1]~ ? rnfeltdown(L, Mod(y, x^2-y)) %5 = Mod(y, y^2 + 1) ? rnfeltdown(L, Mod(y,K.pol)) %6 = Mod(y, y^2 + 1) ? rnfeltdown(L, Mod(x, L.pol)) *** at top-level: rnfeltdown(L,Mod(x,x *** ^-------------------- *** rnfeltdown: domain error in rnfeltdown: element not in the base field ? rnfeltdown(L, Mod(y, x^2-y), 1) \\ as a t_COL %7 = [0, 1]~ ? rnfeltdown(L, [0,0,1,0]~) \\ not allowed without absolute nf struct *** rnfeltdown: incorrect type in rnfeltdown (t_COL). ? nfinit(L); \\ add absolute nf structure to L ? rnfeltdown(L, [0,0,1,0]~) \\ now OK %8 = Mod(y, y^2 + 1) @eprog\noindent If we had started with \kbd{L = rnfinit(K, x\pow2-y, 1)}, then the final command would have worked directly. Variant: Also available is \fun{GEN}{rnfeltdown}{GEN rnf, GEN x} ($\fl = 0$). pari-2.17.2/src/functions/number_fields/nffactorback0000644000175000017500000000146214567450071021163 0ustar billbillFunction: nffactorback Section: number_fields C-Name: nffactorback Prototype: GGDG Help: nffactorback(nf,f,{e}): given a factorization f, returns the factored object back as an nf element. Doc: gives back the \var{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.17.2/src/functions/number_fields/nfeltnorm0000644000175000017500000000022113637407207020534 0ustar billbillFunction: nfeltnorm Section: number_fields C-Name: nfnorm Prototype: GG Help: nfeltnorm(nf,x): norm of x. Doc: returns the absolute norm of $x$. pari-2.17.2/src/functions/number_fields/bnfsunit0000644000175000017500000000222514567450071020366 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. 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 obsoleted component, now the empty vector. $v[4]$ is the $S$-regulator (this is the product of the regulator, the $S$-class number and the natural logarithms of the norms of the ideals in $S$). $v[5]$ gives the $S$-class group structure, in the usual abelian group format: a vector whose three components give in order the $S$-class number, the cyclic components and the generators. $v[6]$ is a copy of $S$. Variant: Also available is \fun{GEN}{sunits_mod_units}{GEN bnf, GEN S} which returns only $v[1]$. pari-2.17.2/src/functions/number_fields/galoisisabelian0000644000175000017500000000112414567450071021661 0ustar billbillFunction: galoisisabelian Section: number_fields C-Name: galoisisabelian Prototype: GD0,L, Help: galoisisabelian(gal,{flag=0}): gal being as output by galoisinit, return 0 if gal is not abelian, the HNF matrix of gal over gal.gen if flag=0, 1 if flag is 1, and the SNF matrix of gal if flag=2. Doc: \var{gal} being as output by \kbd{galoisinit}, return $0$ if \var{gal} is not an abelian group, and the HNF matrix of \var{gal} over \kbd{gal.gen} if $\fl=0$, $1$ if $\fl=1$, and the SNF matrix of \var{gal} if $\fl=2$. This command also accepts subgroups returned by \kbd{galoissubgroups}. pari-2.17.2/src/functions/number_fields/galoispermtopol0000644000175000017500000000154114567450071021756 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}, attached to 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.17.2/src/functions/number_fields/rnfpolredabs0000644000175000017500000000404214567450071021216 0ustar billbillFunction: rnfpolredabs Section: number_fields C-Name: rnfpolredabs Prototype: GGD0,L, Help: rnfpolredabs(nf,pol,{flag=0}): given an irreducible pol with coefficients in nf, finds a canonical relative 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 an irreducible monic polynomial \var{pol} with coefficients in the maximal order of $\var{nf}$, finds a canonical relative polynomial defining the same field, hopefully with small coefficients. Note that the equation is only canonical for a fixed \var{nf}, using a different defining polynomial in the \var{nf} structure will produce a different relative equation. The binary digits of $\fl$ correspond to $1$: add information to convert elements to the new representation, $2$: absolute polynomial, instead of relative, $16$: possibly use a suborder of the maximal order. More precisely: 0: default, return $P$ 1: returns $[P,a]$ where $P$ is the default output and $a$, a \typ{POLMOD} modulo $P$, is a root of \var{pol}. 2: returns \var{Pabs}, an absolute, instead of a relative, polynomial. This polynomial is canonical and does not depend on the \var{nf} structure. Same as but faster than \bprog polredabs(rnfequation(nf, pol)) @eprog 3: returns $[\var{Pabs},a,b]$, where \var{Pabs} is an absolute polynomial as above, $a$, $b$ are \typ{POLMOD} modulo \var{Pabs}, roots of \kbd{nf.pol} and \var{pol} respectively. 16: (OBSOLETE) possibly use a suborder of the maximal order. This makes \kbd{rnfpolredabs} behave as \kbd{rnfpolredbest}. Just use the latter. \misctitle{Warning} The complexity of \kbd{rnfpolredabs} is exponential in the absolute degree. The function \tet{rnfpolredbest} runs in polynomial time, and tends to return polynomials with smaller discriminants. It also supports polynomials with arbitrary coefficients in \var{nf}, neither integral nor necessarily monic. pari-2.17.2/src/functions/number_fields/bnrdisc0000644000175000017500000000273514676526175020202 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{bnr}, \var{character}]}, \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.17.2/src/functions/number_fields/nfeltpowmodpr0000644000175000017500000000104214676526175021444 0ustar billbillFunction: nfeltpowmodpr Section: number_fields C-Name: nfpowmodpr Prototype: GGGG Obsolete: 2016-08-09 Help: nfeltpowmodpr(nf,x,k,pr): this function is obsolete, use nfmodpr. Doc: this function is obsolete, use \kbd{nfmodpr}. 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.17.2/src/functions/number_fields/rnfeltup0000644000175000017500000000221114676526175020402 0ustar billbillFunction: rnfeltup Section: number_fields C-Name: rnfeltup0 Prototype: GGD0,L, Help: rnfeltup(rnf,x,{flag=0}): expresses x (belonging to the base field) on the relative field. As a t_POLMOD if flag = 0 and as a t_COL on the absolute field integer basis if flag = 1. Doc: $\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ being an element of $K$, computes $x$ as an element of the absolute extension $L/\Q$. As a \typ{POLMOD} modulo \kbd{\var{rnf}.pol} if $\fl = 0$ and as a \typ{COL} on the absolute field integer basis if $\fl = 1$. Note that if $x$ is in fact rational, it is returned as a rational number, ignoring \fl. \bprog ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y); ? L.pol %2 = x^4 + 1 ? rnfeltup(L, Mod(y, K.pol)) %3 = Mod(x^2, x^4 + 1) ? rnfeltup(L, y) %4 = Mod(x^2, x^4 + 1) ? rnfeltup(L, [1,2]~) \\ in terms of K.zk %5 = Mod(2*x^2 + 1, x^4 + 1) ? rnfeltup(L, y, 1) \\ in terms of nfinit(L).zk %6 = [0, 1, 0, 0]~ ? rnfeltup(L, [1,2]~, 1) %7 = [1, 2, 0, 0]~ ? rnfeltup(L, [1,0]~) \\ rational %8 = 1 @eprog Variant: Also available is \fun{GEN}{rnfeltup}{GEN rnf, GEN x} ($\fl = 0$). pari-2.17.2/src/functions/number_fields/gcharlog0000644000175000017500000000406014676526175020335 0ustar billbillFunction: gcharlog Section: number_fields C-Name: gcharlog Prototype: GGp Help: gcharlog(gc,x): returns the internal representation (logarithm) of the ideal x suitable for computations in gc, as a column vector. Doc: Returns the internal (logarithmic) representation of the ideal $x$ suitable for computations in $gc$, as a \typ{COL} in $\R^{n}$. Its $n = \kbd{ns+nc}+(r_{1}+r_{2})+r_{2}+1$ components correspond to a logarithm map on the group of fractional ideals~${\cal L}: I \to \R^{n}$, see \kbd{gcharinit}. More precisely, let $x = (\alpha) \prod \goth{p}_{i}^{a_{i}}$ a principalization of $x$ on a set $S$ of primes generating the class group (see \kbd{bnfisprincipal}), then the logarithm of $x$ is the \typ{COL} $$ {\cal L}(x) = \left[ (a_{i}), \log_{f}(\alpha), \dfrac{\log|x/\alpha|_{\tau}}{2\pi}, \dfrac{\arg(x/\alpha)_{\tau}}{2\pi}, \dfrac{\log N(x)}{2\pi}\cdot i \right] $$ where \item the exponent vector $(a_{i})$ has \kbd{ns} components, where $\kbd{ns}=\#S$ is the number of prime ideals used to generate the class group, \item $\log_{f}(\alpha)$ is a discrete logarithm of $\alpha$ in the \kbd{idealstar} group $(\Z_{K}/f)^{\times}$, with \kbd{nc} components, \item $\log|x/\alpha|_{\tau}$ has $r_{1}+r_{2}$ components, one for each real embedding and pair of complex embeddings $\tau\colon K\to\C$ (and $|z|_{\tau}=|z|^{2}$ for complex $\tau$). \item $\arg{(x/\alpha)_{\tau}}$ has $r_{2}$ components, one for each pair of complex embeddings $\tau\colon K\to\C$. \item $N(x)$ is the norm of the ideal~$x$. \bprog ? bnf = bnfinit(x^3-x^2+5*x+1,1); ? gc = gcharinit(bnf,3); ? gc.cyc % = [3, 0, 0, 0.E-57] ? chi = [1,1,0,-1]~; ? f = gcharduallog(gc,chi); ? pr = idealprimedec(bnf,5)[1]; ? v = gcharlog(gc,pr) % = [2, -5, -1, 0.0188115475004995312411, -0.0188115475004995312411, -0.840176314833856764413, 0.256149999363388073738*I]~ ? exp(2*I*Pi*f*v) % = -4.5285995080704456583673312 + 2.1193835177957097598574507*I ? gchareval(gc,chi,pr) % = -4.5285995080704456583673312 + 2.1193835177957097598574507*I @eprog pari-2.17.2/src/functions/number_fields/galoisfixedfield0000644000175000017500000000373314676526175022057 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}). In this case, $P$ is also expressed in the variable $v$ for compatibility with $F$. Example: \bprog ? G = galoisinit(x^4+1); ? galoisfixedfield(G,G.group[2],2) %2 = [y^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.17.2/src/functions/number_fields/nfgaloisapply0000644000175000017500000000423214567450071021406 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 nontrivial 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] %6 = 0 \\ !!!! ? idealval(nf, nfgaloisapply(nf, aut, P[2]), P[1]) %7 = 1 @eprog\noindent The surprising failure of the equality test (\kbd{\%7}) is due to the fact that although the corresponding prime ideals are equal, their representations are not. (A prime ideal is specified by a uniformizer, and there is no guarantee that applying automorphisms yields the same elements as a direct \kbd{idealprimedec} call.) The automorphism can also be given as a column vector, representing the image of \kbd{Mod(x, nf.pol)} as an algebraic number. This last representation is more efficient and should be preferred if a given automorphism must be used in many such calls. \bprog ? nf = nfinit(x^3 - 37*x^2 + 74*x - 37); ? aut = nfgaloisconj(nf)[2]; \\ @com an automorphism in basistoalg form %2 = -31/11*x^2 + 1109/11*x - 925/11 ? AUT = nfalgtobasis(nf, aut); \\ @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 = 463 ms. ? for (i=1,10^5, nfgaloisapply(nf, AUT, v)) time = 343 ms. \\ @com but the latter is faster @eprog pari-2.17.2/src/functions/number_fields/galoischartable0000644000175000017500000000457114676526175021702 0ustar billbillFunction: galoischartable Section: number_fields C-Name: galoischartable Prototype: G Help: galoischartable(gal): return the character table of the underlying group of gal. Doc: Compute the character table of~$G$, where~$G$ is the underlying group of the \kbd{galoisinit} structure~\var{gal}. The input~\var{gal} is also allowed to be a \typ{VEC} of permutations that is closed under products. Let~$N$ be the number of conjugacy classes of~$G$. Return a \typ{VEC}~$[M,\var{e}]$ where $e \geq 1$ is an integer and $M$ is a square \typ{MAT} of size~$N$ giving the character table of~$G$. \item Each column corresponds to an irreducible character; the characters are ordered by increasing dimension and the first column is the trivial character (hence contains only $1$'s). \item Each row corresponds to a conjugacy class; the conjugacy classes are ordered as specified by \kbd{galoisconjclasses(gal)}, in particular the first row corresponds to the identity and gives the dimension $\chi(1)$ of the irreducible representation attached to the successive characters $\chi$. The value $M[i,j]$ of the character $j$ at the conjugacy class $i$ is represented by a polynomial in \kbd{y} whose variable should be interpreted as an $e$-th root of unity, i.e. as the lift of \bprog Mod(y, polcyclo(e,'y)) @eprog\noindent (Note that $M$ is the transpose of the usual orientation for character tables.) The integer $e$ divides the exponent of the group $G$ and is chosen as small as posible; for instance $e = 1$ when the characters are all defined over $\Q$, as is the case for $S_{n}$. Examples: \bprog ? K = nfsplitting(x^4+x+1); ? gal = galoisinit(K); ? [M,e] = galoischartable(gal); ? M~ \\ take the transpose to get the usual orientation %4 = [1 1 1 1 1] [1 -1 -1 1 1] [2 0 0 -1 2] [3 -1 1 0 -1] [3 1 -1 0 -1] ? e %5 = 1 ? {G = [Vecsmall([1, 2, 3, 4, 5]), Vecsmall([1, 5, 4, 3, 2]), Vecsmall([2, 1, 5, 4, 3]), Vecsmall([2, 3, 4, 5, 1]), Vecsmall([3, 2, 1, 5, 4]), Vecsmall([3, 4, 5, 1, 2]), Vecsmall([4, 3, 2, 1, 5]), Vecsmall([4, 5, 1, 2, 3]), Vecsmall([5, 1, 2, 3, 4]), Vecsmall([5, 4, 3, 2, 1])];} \\G = D10 ? [M,e] = galoischartable(G); ? M~ %8 = [1 1 1 1] [1 -1 1 1] [2 0 -y^3 - y^2 - 1 y^3 + y^2] [2 0 y^3 + y^2 -y^3 - y^2 - 1] ? e %9 = 5 @eprog pari-2.17.2/src/functions/number_fields/bnfcertify0000644000175000017500000000271214676526175020704 0ustar billbillFunction: bnfcertify Section: number_fields C-Name: bnfcertify0 Prototype: lGD0,L, Help: bnfcertify(bnf,{flag = 0}): certify the correctness (i.e. remove the GRH) of the bnf data output by bnfinit. If flag is present, only certify that the class group is a quotient of the one computed in bnf (much simpler in general). Doc: $\var{bnf}$ being as output by \kbd{bnfinit}, checks whether the result is correct, i.e.~whether it is possible to remove the assumption of the Generalized Riemann Hypothesis\sidx{GRH}. It is correct if and only if the answer is 1. If it is incorrect, the program may output some error message, or loop indefinitely. You can check its progress by increasing the debug level. The \var{bnf} structure must contain the fundamental units: \bprog ? K = bnfinit(x^3+2^2^3+1); bnfcertify(K) *** at top-level: K=bnfinit(x^3+2^2^3+1);bnfcertify(K) *** ^------------- *** bnfcertify: precision too low in makeunits [use bnfinit(,1)]. ? K = bnfinit(x^3+2^2^3+1, 1); \\ include units ? bnfcertify(K) %3 = 1 @eprog If $\fl$ is present, only certify that the class group is a quotient of the one computed in bnf (much simpler in general); likewise, the computed units may form a subgroup of the full unit group. In this variant, the units are no longer needed: \bprog ? K = bnfinit(x^3+2^2^3+1); bnfcertify(K, 1) %4 = 1 @eprog Variant: Also available is \fun{GEN}{bnfcertify}{GEN bnf} ($\fl=0$). pari-2.17.2/src/functions/number_fields/rnfidealnormabs0000644000175000017500000000107414567450071021705 0ustar billbillFunction: rnfidealnormabs Section: number_fields C-Name: rnfidealnormabs Prototype: GG Help: rnfidealnormabs(rnf,x): absolute norm of the ideal x. Doc: let $\var{rnf}$ be a relative number field extension $L/K$ as output by \kbd{rnfinit} and let $x$ be a relative ideal (which can be, as in the absolute case, of many different types, including of course elements). This function computes the norm of the $x$ considered as an ideal of the absolute extension $L/\Q$. This is identical to \bprog idealnorm(rnf, rnfidealnormrel(rnf,x)) @eprog\noindent but faster. pari-2.17.2/src/functions/number_fields/idealdown0000644000175000017500000000115114567450071020501 0ustar billbillFunction: idealdown Section: number_fields C-Name: idealdown Prototype: GG Help: idealdown(nf,x): finds the intersection of the ideal x with Q. Doc: let $\var{nf}$ be a number field as output by \kbd{nfinit}, and $x$ a fractional ideal. This function returns the nonnegative rational generator of $x \cap \Q$. If $x$ is an extended ideal, the extended part is ignored. \bprog ? nf = nfinit(y^2+1); ? idealdown(nf, -1/2) %2 = 1/2 ? idealdown(nf, (y+1)/3) %3 = 2/3 ? idealdown(nf, [2, 11]~) %4 = 125 ? x = idealprimedec(nf, 2)[1]; idealdown(nf, x) %5 = 2 ? idealdown(nf, [130, 94; 0, 2]) %6 = 130 @eprog pari-2.17.2/src/functions/number_fields/bnrisconductor0000644000175000017500000000120314567450071021567 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: fast variant of \kbd{bnrconductor}$(A,B,C)$; $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} when the character or subgroup is not primitive. pari-2.17.2/src/functions/number_fields/galoissubcyclo0000644000175000017500000000551014676526175021572 0ustar billbillFunction: galoissubcyclo Section: number_fields C-Name: galoissubcyclo Prototype: GDGD0,L,Dn Help: galoissubcyclo(N,H,{flag=0},{v}): computes 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]]). 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, outputs only the conductor of the abelian extension. If flag is 2, outputs [pol,f] where pol is the polynomial and f the conductor. If flag is 3, outputs galoisinit(pol). Doc: computes the subextension $L$ 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). This function output is somewhat canonical, as it returns the minimal polynomial of a Gaussian period $\text{Tr}_{\Q(\zeta_{n})/L}(\zeta_{n})$. \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)$ or \kbd{znstar}$(n,1)$. $H$ as in the first case above, or a matrix, taken to be a HNF left divisor of the SNF for $(\Z/n\Z)^{*}$ (\kbd{$N$.cyc}), giving the generators of $H$ in terms of \kbd{$N$.gen}. \item $N$ the output of \kbd{bnrinit(bnfinit(y), $m$)} 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$.bid.gen} (= \kbd{$N$}.gen if $N$ includes generators). 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$, computes a polynomial (in the variable \var{v}) defining the subfield of $\Q(\zeta_{n})$ fixed by the subgroup \var{H} of $(\Z/n\Z)^{*}$. If $\fl=1$, computes only the conductor of the abelian extension, as a module. If $\fl=2$, outputs $[pol, N]$, where $pol$ is the polynomial as output when $\fl=0$ and $N$ the conductor as output when $\fl=1$. If $\fl=3$; outputs \kbd{galoisinit(pol)}. 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 subcyclo(n, d = -1)= { my(bnr,L,IndexBound); IndexBound = if (d < 0, n, [d]); bnr = bnrinit(bnfinit(y), [n,[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.17.2/src/functions/number_fields/rnfislocalcyclo0000644000175000017500000000153014676526175021734 0ustar billbillFunction: rnfislocalcyclo Section: number_fields C-Name: rnfislocalcyclo Prototype: lG Help: rnfislocalcyclo(rnf): true(1) if the l-extension attached to rnf is locally cyclotomic (locally contained in the Z_l extension of K_v at all places v | l), false(0) if not. Doc: Let \var{rnf} be a relative number field extension $L/K$ as output by \kbd{rnfinit} whose degree $[L:K]$ is a power of a prime $\ell$. Return $1$ if the $\ell$-extension is locally cyclotomic (locally contained in the cyclotomic $\Z_{\ell}$-extension of $K_{v}$ at all places $v | \ell$), and $0$ if not. \bprog ? K = nfinit(y^2 + y + 1); ? L = rnfinit(K, x^3 - y); /* = K(zeta_9), globally cyclotomic */ ? rnfislocalcyclo(L) %3 = 1 \\ we expect 3-adic continuity by Krasner's lemma ? vector(5, i, rnfislocalcyclo(rnfinit(K, x^3 - y + 3^i))) %5 = [0, 1, 1, 1, 1] @eprog pari-2.17.2/src/functions/number_fields/rnfidealup0000644000175000017500000000262314676526175020703 0ustar billbillFunction: rnfidealup Section: number_fields C-Name: rnfidealup0 Prototype: GGD0,L, Help: rnfidealup(rnf,x,{flag=0}): lifts the ideal x (of the base field) to the relative field. As a vector of t_POLMODs if flag = 0 and as an ideal in HNF in the absolute field if flag = 1. Doc: let $\var{rnf}$ be a relative number field extension $L/K$ as output by \kbd{rnfinit} and let $x$ be an ideal of $K$. This function returns the ideal $x\Z_{L}$ as an absolute ideal of $L/\Q$, in the form of a $\Z$-basis. If $\fl = 0$, the result is given by a vector of polynomials (modulo \kbd{rnf.pol}); if $\fl = 1$, it is given in HNF in terms of the fixed $\Z$-basis for $\Z_{L}$, see \secref{se:rnfinit}. \bprog ? K = nfinit(y^2+1); rnf = rnfinit(K, x^2-y); ? P = idealprimedec(K,2)[1]; ? rnfidealup(rnf, P) %3 = [2, x^2 + 1, 2*x, x^3 + x] ? rnfidealup(rnf, P,1) %4 = [2 1 0 0] [0 1 0 0] [0 0 2 1] [0 0 0 1] @eprog The reason why we do not return by default ($\fl = 0$) the customary HNF in terms of a fixed $\Z$-basis for $\Z_{L}$ is precisely because a \var{rnf} does not contain such a basis by default. Completing the structure so that it contains a \var{nf} structure for $L$ is polynomial time but costly when the absolute degree is large, thus it is not done by default. Note that setting $\fl = 1$ will complete the \var{rnf}. Variant: Also available is \fun{GEN}{rnfidealup}{GEN rnf, GEN x} ($\fl = 0$). pari-2.17.2/src/functions/number_fields/rnfhnfbasis0000644000175000017500000000126414676526175021055 0ustar billbillFunction: rnfhnfbasis Section: number_fields C-Name: rnfhnfbasis Prototype: GG Help: rnfhnfbasis(bnf,M): given a bnf attached to a number field K and a projective Z_K module M given by a pseudo-matrix, returns either a true HNF basis of M if one exists, or zero otherwise. If M is a polynomial with coefficients in K, replace it by the pseudo-matrix returned by rnfpseudobasis. Doc: given a \var{bnf} attached to a number field $K$ and a projective $\Z_{K}$-module $M$ given by a pseudo-matrix, returns either a true HNF basis of $M$ if one exists, or zero otherwise. If $M$ is a polynomial with coefficients in $K$, replace it by the pseudo-matrix returned by \kbd{rnfpseudobasis}. pari-2.17.2/src/functions/number_fields/polredabs0000644000175000017500000001245314676526175020527 0ustar billbillFunction: polredabs Section: number_fields C-Name: polredabs0 Prototype: GD0,L, Help: polredabs(T,{flag=0}): a smallest generating polynomial of the number field for the T2 norm on the roots, with smallest index for the minimal T2 norm. flag is optional, whose binary digit mean 1: give the element whose characteristic polynomial is the given polynomial. 4: give all polynomials of minimal T2 norm (give only one of P(x) and P(-x)). Doc: returns a canonical defining polynomial $P$ for the number field $\Q[X]/(T)$ defined by $T$, such that the sum of the squares of the modulus of the roots (i.e.~the $T_{2}$-norm) is minimal. Different $T$ defining isomorphic number fields will yield the same $P$. All $T$ accepted by \tet{nfinit} are also allowed here, e.g. nonmonic polynomials, or pairs \kbd{[T, listP]} specifying that a nonmaximal order may be used. For convenience, any number field structure (\var{nf}, \var{bnf},\dots) can also be used instead of $T$. \bprog ? polredabs(x^2 + 16) %1 = x^2 + 1 ? K = bnfinit(x^2 + 16); polredabs(K) %2 = x^2 + 1 @eprog \misctitle{Warning 1} Using a \typ{POL} $T$ requires computing and fully factoring the discriminant $d_{K}$ of the maximal order which may be very hard. You can use the format \kbd{[T, listP]}, where \kbd{listP} encodes a list of known coprime divisors of $\disc(T)$ (see \kbd{??nfbasis}), to help the routine, thereby replacing this part of the algorithm by a polynomial time computation But this may only compute a suborder of the maximal order, when the divisors are not squarefree or do not include all primes dividing $d_{K}$. The routine attempts to certify the result independently of this order computation as per \tet{nfcertify}: we try to prove that the computed order is maximal. If the certification fails, the routine then fully factors the integers returned by \kbd{nfcertify}. You can also use \tet{polredbest} to avoid this factorization step; in this case, the result is small but no longer canonical. \misctitle{Warning 2} Apart from the factorization of the discriminant of $T$, this routine runs in polynomial time for a \emph{fixed} degree. But the complexity is exponential in the degree: this routine may be exceedingly slow when the number field has many subfields, hence a lot of elements of small $T_{2}$-norm. If you do not need a canonical polynomial, the function \tet{polredbest} is in general much faster (it runs in polynomial time), and tends to return polynomials with smaller discriminants. The binary digits of $\fl$ mean 1: outputs a two-component row vector $[P,a]$, where $P$ is the default output and \kbd{Mod(a, P)} is a root of the original $T$. 4: gives \emph{all} polynomials of minimal $T_{2}$ norm; of the two polynomials $P(x)$ and $\pm P(-x)$, only one is given. 16: (OBSOLETE) Possibly use a suborder of the maximal order, \emph{without} attempting to certify the result as in Warning 1. This makes \kbd{polredabs} behave like \kbd{polredbest}. Just use the latter. \bprog ? T = x^16 - 136*x^14 + 6476*x^12 - 141912*x^10 + 1513334*x^8 \ - 7453176*x^6 + 13950764*x^4 - 5596840*x^2 + 46225 ? T1 = polredabs(T); T2 = polredbest(T); ? [ norml2(polroots(T1)), norml2(polroots(T2)) ] %3 = [88.0000000, 120.000000] ? [ sizedigit(poldisc(T1)), sizedigit(poldisc(T2)) ] %4 = [75, 67] @eprog The precise definition of the output of \tet{polredabs} is as follows. \item Consider the finite list of characteristic polynomials of primitive elements of~$K$ that are in~$\Z_{K}$ and minimal for the~$T_{2}$ norm; now remove from the list the polynomials whose discriminant do not have minimal absolute value. Note that this condition is restricted to the original list of polynomials with minimal $T_{2}$ norm and does not imply that the defining polynomial for the field with smallest discriminant belongs to the list ! \item To a polynomial $P(x) = x^{n} + \dots + a_{n} \in \R[x]$ we attach the sequence $S(P)$ given by $|a_{1}|, a_{1}, \dots, |a_{n}|, a_{n}$. Order the polynomials $P$ by the lexicographic order on the coefficient vectors $S(P)$. Then the output of \tet{polredabs} is the smallest polynomial in the above list for that order. In other words, the monic polynomial which is lexicographically smallest with respect to the absolute values of coefficients, favouring negative coefficients to break ties, i.e. choosing $x^{3}-2$ rather than $x^{3}+2$. Variant: Instead of the above hardcoded numerical flags, one should use an or-ed combination of \item \tet{nf_PARTIALFACT} (OBSOLETE): possibly use a suborder of the maximal order, \emph{without} attempting to certify the result. \item \tet{nf_ORIG}: return $[P, a]$, where \kbd{Mod(a, P)} is a root of $T$. \item \tet{nf_RAW}: return $[P, b]$, where \kbd{Mod(b, T)} is a root of $P$. The algebraic integer $b$ is the raw result produced by the small vectors enumeration in the maximal order; $P$ was computed as the characteristic polynomial of \kbd{Mod(b, T)}. \kbd{Mod(a, P)} as in \tet{nf_ORIG} is obtained with \tet{modreverse}. \item \tet{nf_ADDZK}: if $r$ is the result produced with some of the above flags (of the form $P$ or $[P,c]$), return \kbd{[r,zk]}, where \kbd{zk} is a $\Z$-basis for the maximal order of $\Q[X]/(P)$. \item \tet{nf_ALL}: return a vector of results of the above form, for all polynomials of minimal $T_{2}$-norm. pari-2.17.2/src/functions/number_fields/bnrisprincipal0000644000175000017500000000734214676526175021574 0ustar billbillFunction: bnrisprincipal Section: number_fields C-Name: bnrisprincipal Prototype: GGD1,L, Help: bnrisprincipal(bnr,x,{flag=1}): bnr being output by bnrinit and x being an ideal coprime to bnr.mod, returns [v,alpha], where v is the vector of exponents on the ray class group generators and alpha is the generator of the resulting principal ideal. If (optional) flag is set to 0, output only v. Doc: let \var{bnr} be the ray class group data output by \kbd{bnrinit}$(,,1)$ and let $x$ be an ideal in any form, coprime to the modulus $f = \kbd{bnr.mod}$. Solves the discrete logarithm problem in the ray class group, with respect to the generators \kbd{bnr.gen}, in a way similar to \tet{bnfisprincipal}. If $x$ is not coprime to the modulus of \var{bnr} the result is undefined. Note that \var{bnr} need not contain the ray class group generators, i.e.~it may be created with \kbd{bnrinit}$(,,0)$; in that case, although \kbd{bnr.gen} is undefined, we can still fix natural generators for the ray class group (in terms of the generators in \kbd{bnr.bnf.gen} and \kbd{bnr.bid.gen}) and compute with respect to them. The binary digits of $\fl$ (default $\fl = 1$) mean: \item $1$: If set returns a 2-component vector $[e,\alpha]$ where $e$ is the vector of components of $x$ on the ray class group generators, $\alpha$ is an element congruent to $1~\text{mod}^{*} f$ such that $x = \alpha \prod_{i} g_{i}^{e_{i}}$. If unset, returns only $e$. \item $4$: If set, returns $[e,\alpha]$ where $\alpha$ is given in factored form (compact representation). This is orders of magnitude faster. \bprog ? K = bnfinit(x^2 - 30); bnr = bnrinit(K, [4, [1,1]]); ? bnr.clgp \\ ray class group is isomorphic to Z/4 x Z/2 x Z/2 %2 = [16, [4, 2, 2]] ? P = idealprimedec(K, 3)[1]; \\ the ramified prime ideal above 3 ? bnrisprincipal(bnr,P) \\ bnr.gen undefined ! %5 = [[3, 0, 0]~, 9] ? bnrisprincipal(bnr,P, 0) \\ omit principal part %5 = [3, 0, 0]~ ? bnr = bnrinit(bnr, bnr.bid, 1); \\ include explicit generators ? bnrisprincipal(bnr,P) \\ ... alpha is different ! %7 = [[3, 0, 0]~, 1/128625] @eprog It may be surprising that the generator $\alpha$ is different although the underlying \var{bnf} and \var{bid} are the same. This defines unique generators for the ray class group as ideal \emph{classes}, whether we use \kbd{bnrinit(,0)} or \kbd{bnrinit(,1)}. But the actual ideal representatives (implicit if $\fl=0$, computed and stored in the \var{bnr} if $\fl=1$) are in general different and this is what happens here. Indeed, the implicit generators are naturally expressed in terms of \kbd{bnr.bnf.gen} and \kbd{bnr.bid.gen} and \emph{then} expanded and simplified (in the same ideal class) so that we obtain ideal representatives for \kbd{bnr.gen} which are as simple as possible. And indeed the quotient of the two $\alpha$ found is $1$ modulo the conductor (and positive at the infinite places it contains), and this is the only guaranteed property. Beware that, when \kbd{bnr} is generated using \kbd{bnrinit(, cycmod)}, the results are given in $\text{Cl}_{f}$ modulo \kbd{cycmod}-th powers: \bprog ? bnr2 = bnrinit(K, bnr.mod,, 2); \\ modulo squares ? bnr2.clgp %9 = [8, [2, 2, 2]] \\ bnr.clgp tensored by Z/2Z ? bnrisprincipal(bnr2,P, 0) %10 = [1, 0, 0]~ @eprog Variant: Instead of hardcoded numerical flags, one should rather use \fun{GEN}{isprincipalray}{GEN bnr, GEN x} for $\fl = 0$, and if you want generators: \bprog bnrisprincipal(bnr, x, nf_GEN) @eprog Also available is \fun{GEN}{bnrisprincipalmod}{GEN bnr, GEN x, GEN mod, long flag} that returns the discrete logarithm of~$x$ modulo the~\typ{INT} \kbd{mod}; the value~$\kbd{mod = NULL}$ is treated as~$0$ (full discrete logarithm), and~$\fl=1$ is not allowed if~\kbd{mod} is set. pari-2.17.2/src/functions/number_fields/gcharnewprec0000644000175000017500000000074314676526175021223 0ustar billbillFunction: gcharnewprec Section: number_fields C-Name: gcharnewprec Prototype: Gp Help: gcharnewprec(gc): given a Grossencharacter group \kbd{gc}, recomputes its invariants to ensure accurate results to current precision. Doc: $\var{gc}$ being a Grossencharacter group output by \kbd{gcharinit}, recomputes its archimedean components ensuring accurate computations to current precision. It is advisable to increase the precision before computing several values at large ideals. pari-2.17.2/src/functions/number_fields/galoisgetname0000644000175000017500000000205314567450071021354 0ustar billbillFunction: galoisgetname Section: number_fields C-Name: galoisgetname Prototype: LL Help: galoisgetname(a,b): query the galpol package for a string describing the group of order a with index b in the GAP4 Small Group library. Doc: Query the \kbd{galpol} package for a string describing the group of order $a$ with index $b$ in the GAP4 Small Group library, by Hans Ulrich Besche, Bettina Eick and Eamonn O'Brien. The strings were generated using the GAP4 function \kbd{StructureDescription}. The command below outputs the names of all abstract groups of order 12: \bprog ? o = 12; N = galoisgetgroup(o); \\ # of abstract groups of order 12 ? for(i=1, N, print(i, ". ", galoisgetname(o,i))) 1. C3 : C4 2. C12 3. A4 4. D12 5. C6 x C2 @eprog\noindent The current version of \kbd{galpol} supports groups of order $a\leq 143$. For $a \geq 16$, it is possible for different groups to have the same name: \bprog ? o = 20; N = galoisgetgroup(o); ? for(i=1, N, print(i, ". ", galoisgetname(o,i))) 1. C5 : C4 2. C20 3. C5 : C4 4. D20 5. C10 x C2 @eprog pari-2.17.2/src/functions/number_fields/idealpow0000644000175000017500000000160314676526175020353 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 nonzero, 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 nonzero, reduce the result using \kbd{idealred}, \emph{throughout the (binary) powering process}; in particular, this is \emph{not} the same 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.17.2/src/functions/number_fields/bnfisprincipal0000644000175000017500000000725514676526175021563 0ustar billbillFunction: bnfisprincipal Section: number_fields C-Name: bnfisprincipal0 Prototype: GGD1,L, Help: bnfisprincipal(bnf,x,{flag=1}): bnf being output by bnfinit, gives [e,t], where e is the vector of exponents on the class group generators and t is the generator of the resulting principal ideal. In particular x is principal if and only if e is the zero vector. flag is optional, whose binary digits mean 1: output [e,t] (only e if unset); 2: increase precision until t can be computed (do not insist if unset); 4: return t in factored form (compact representation). 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 a 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 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 the \kbd{bnf} structure 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{lengthy} computations, and the result may be too large to be physically representable in any case. You should consider using $\fl=4$ instead. \item $4$: Return $t$ in factored form (compact representation), as a small product of $S$-units for a small set of finite places $S$, possibly with huge exponents. This kind of result can be cheaply mapped to $K^{*}/(K^{*})^{\ell}$ or to $\C$ or $\Q_{p}$ to bounded accuracy and this is usually enough for applications. Explicitly expanding such a compact representation is possible using \kbd{nffactorback} but may be \emph{very} costly. The algorithm is guaranteed to succeed if the \kbd{bnf} was computed using \kbd{bnfinit(,1)}. If not, the algorithm may fail to compute a huge generator in this case (and replace it by \kbd{[]\til}). This is orders of magnitude faster than $\fl=2$ when the generators are indeed large. 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), \tet{nf_GENMAT} (include generators in compact form) and \tet{nf_FORCE} (insist on finding the generators, a no-op if \tet{nf_GENMAT} is included). pari-2.17.2/src/functions/number_fields/idealchinese0000644000175000017500000000533614676526175021173 0ustar billbillFunction: idealchinese Section: number_fields C-Name: idealchinese Prototype: GGDG Help: idealchinese(nf,x,{y}): x being a prime ideal factorization and y a vector of elements, gives an element b such that v_p(b-y_p)>=v_p(x) for all prime ideals p dividing x, and v_p(b)>=0 for all other p. If y is omitted, return a data structure which can be used in place of x in later calls. Doc: $x$ being a prime ideal factorization (i.e.~a 2-columns matrix whose first column contains prime ideals and the second column contains 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}$. \bprog ? K = nfinit(t^2-2); ? x = idealfactor(K, 2^2*3) %2 = [[2, [0, 1]~, 2, 1, [0, 2; 1, 0]] 4] [ [3, [3, 0]~, 1, 2, 1] 1] ? y = [t,1]; ? idealchinese(K, x, y) %4 = [4, -3]~ @eprog The argument $x$ may also be of the form $[x, s]$ where the first component is as above and $s$ is a vector of signs, with $r_{1}$ components $s_{i}$ in $\{-1,0,1\}$: if $\sigma_{i}$ denotes the $i$-th real embedding of the number field, the element $b$ returned satisfies further $\kbd{sign}(\sigma_{i}(b)) = s_{i}$ for all $i$ such that $s_{i} = \pm1$. In other words, the sign is fixed to $s_{i}$ at the $i$-th embedding whenever $s_{i}$ is nonzero. \bprog ? idealchinese(K, [x, [1,1]], y) %5 = [16, -3]~ ? idealchinese(K, [x, [-1,-1]], y) %6 = [-20, -3]~ ? idealchinese(K, [x, [1,-1]], y) %7 = [4, -3]~ @eprog If $y$ is omitted, return a data structure which can be used in place of $x$ in later calls and allows to solve many chinese remainder problems for a given $x$ more efficiently. In this case, the right hand side $y$ is not allowed to have denominators, unless they are coprime to $x$. \bprog ? C = idealchinese(K, [x, [1,1]]); ? idealchinese(K, C, y) \\ as above %9 = [16, -3]~ ? for(i=1,10^4, idealchinese(K,C,y)) \\ ... but faster ! time = 80 ms. ? for(i=1,10^4, idealchinese(K,[x,[1,1]],y)) time = 224 ms. @eprog Finally, this structure is itself allowed in place of $x$, the new $s$ overriding the one already present in the structure. This allows to initialize for different sign conditions more efficiently when the underlying ideal factorization remains the same. \bprog ? D = idealchinese(K, [C, [1,-1]]); \\ replaces [1,1] ? idealchinese(K, D, y) %13 = [4, -3]~ ? for(i=1,10^4,idealchinese(K,[C,[1,-1]])) time = 40 ms. \\ faster than starting from scratch ? for(i=1,10^4,idealchinese(K,[x,[1,-1]])) time = 128 ms. @eprog Variant: Also available is \fun{GEN}{idealchineseinit}{GEN nf, GEN x} when $y = \kbd{NULL}$. pari-2.17.2/src/functions/number_fields/nfhnf0000644000175000017500000000143614567450071017640 0ustar billbillFunction: nfhnf Section: number_fields C-Name: nfhnf0 Prototype: GGD0,L, Help: nfhnf(nf,x,{flag=0}): if x=[A,I], gives a pseudo-basis [B,J] of the module sum A_jI_j. If flag is nonzero, return [[B,J], U], where U is the transformation matrix such that AU = [0|B]. Doc: given a pseudo-matrix $(A,I)$, finds a pseudo-basis $(B,J)$ in \idx{Hermite normal form} of the module it generates. If $\fl$ is nonzero, also return the transformation matrix $U$ such that $AU = [0|B]$. Variant: Also available: \fun{GEN}{nfhnf}{GEN nf, GEN x} ($\fl = 0$). \fun{GEN}{rnfsimplifybasis}{GEN bnf, GEN x} simplifies the pseudo-basis $x = (A,I)$, returning a pseudo-basis $(B,J)$. The ideals in the list $J$ are integral, primitive and either trivial (equal to the full ring of integer) or nonprincipal. pari-2.17.2/src/functions/number_fields/gcharinit0000644000175000017500000000602314676526175020520 0ustar billbillFunction: gcharinit Section: number_fields C-Name: gcharinit Prototype: GGp Help: gcharinit(bnf,f): given a bnf as output by bnfinit and a modulus f, initializes data related to the group of Grossencharacters of conductor dividing this modulus. Doc: $\var{bnf}$ being a number field output by \kbd{bnfinit} (including fundamental units), $f$ a modulus, initializes a structure (\kbd{gc}) describing the group of Hecke Grossencharacters of modulus $f$. (As in \tet{idealstar}, the finite part of the conductor may be given by a factorization into prime ideals, as produced by \tet{idealfactor}.) The following member functions are available on the result: \kbd{.bnf} is the underlying \var{bnf}, \kbd{.mod} the modulus, \kbd{.cyc} its elementary divisors. The internal representation uses a logarithm map on ideals ${\cal L}: I \to \R^{n}$, so that a Hecke Grossencharacter $\chi$ can be described by a $n$ components vector $v$ via $\chi: a\in I \mapsto \exp(2i\pi v\cdot{{\cal L}(a)})$. See \kbd{gcharlog} for more details on the map ${\cal L}$. \bprog ? bnf = bnfinit(polcyclo(5),1); \\ @com initializes number field $\Q(\zeta_5)$ ? pr = idealprimedec(bnf,5)[1]; \\ @com prime $\goth{p}=(1-\zeta_5)$ above 5 ? gc = gcharinit(bnf,idealpow(bnf,pr,2)); \\ @com characters of modulus dividing $\goth{p}^{2}$ ? gc.cyc \\ @com structure as an abelian group % = [0,0,0,0.E-57] ? chi = [1,1,-1,0]~; \\ @com a character ? gcharconductor(gc,chi)[1] % = [5 4 1 4] [0 1 0 0] [0 0 1 0] [0 0 0 1] @eprog Currently, \kbd{gc} is a row vector with 11 components: $\var{gc}[1]$ is a matrix whose rows describe a system of generators of the characters as vectors of $\R^{n}$, under the above description. $\var{gc}[2]$ contains the underlying number field \var{bnf} (\kbd{\var{gc}.bnf}). $\var{gc}[3]$ contains the underlying number field \var{nf} (\kbd{\var{gc}.nf}), possibly stored at higher precision than \var{bnf}. $\var{gc}[4]$ contains data for computing in $(\Z_{K}/f)^{\times}$. $\var{gc}[5]$ is a vector $S$ of prime ideals which generate the class group. $\var{gc}[6]$ contains data to compute discrete logarithms with respect to $S$ in the class group. $\var{gc}[7]$ is a vector \kbd{[Sunits,m]}, where \kbd{Sunits} describes the $S$-units of $\var{bnf}$ and $m$ is a relation matrix for internal usage. $\var{gc}[8]$ is \kbd{[Vecsmall([evalprec,prec,nfprec]), Vecsmall([ntors,nfree,nalg])]} caching precisions and various dimensions. $\var{gc}[9]$ is a vector describing $\var{gc}$ as a $\Z$-module via its SNF invariants (\kbd{\var{gc}.cyc}), the last component representing the norm character. $\var{gc}[10]$ is a vector \kbd{[R,U,Ui]} allowing to convert characters from SNF basis to internal combination of generators. Specifically, a character \kbd{chi} in SNF basis has coordinates \kbd{chi*Ui} in internal basis (the rows of $\var{gc}[1]$). $\var{gc}[11]=m$ is the matrix of ${\cal L}(v)$ for all $S$-units $v$. $\var{gc}[12]=u$ is an integral base change matrix such that $\var{gc}[1]$ corresponds to $(mu)^{-1}$. pari-2.17.2/src/functions/number_fields/nfeltmulmodpr0000644000175000017500000000105114567450071021422 0ustar billbillFunction: nfeltmulmodpr Section: number_fields C-Name: nfmulmodpr Prototype: GGGG Obsolete: 2016-08-09 Help: nfeltmulmodpr(nf,x,y,pr): this function is obsolete, use nfmodpr. Doc: this function is obsolete, use \kbd{nfmodpr}. 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.17.2/src/functions/number_fields/dirzetak0000644000175000017500000000053213637407207020352 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.17.2/src/functions/number_fields/bnflog0000644000175000017500000000253314760123736020007 0ustar billbillFunction: bnflog Section: number_fields C-Name: bnflog Prototype: GG Help: bnflog(bnf,l): let bnf be attached to a number field F and let l be a prime number. Return the logarithmic l-class group Cl~_F. Doc: let \var{bnf} be a \var{bnf} structure attached to the number field $F$ and let $l$ be a prime number (hereafter denoted $\ell$ for typographical reasons). Return the logarithmic $\ell$-class group $\widetilde{Cl}_{F}$ of $F$. This is an abelian group, conjecturally finite (known to be finite if $F/\Q$ is abelian). The function returns if and only if the group is indeed finite (otherwise it would run into an infinite loop). Let $S = \{ \goth{p}_{1},\dots, \goth{p}_{k}\}$ be the set of $\ell$-adic places (maximal ideals containing $\ell$). The function returns $[D, G(\ell), G']$, where \item $D$ is the vector of elementary divisors for $\widetilde{Cl}_{F}$. \item $G(\ell)$ is the vector of elementary divisors for the (conjecturally finite) abelian group $$\widetilde{\Cl}(\ell) = \{ \goth{a} = \sum_{i \leq k} a_{i} \goth{p}_{i} :~\deg_{F} \goth{a} = 0\},$$ where the $\goth{p}_{i}$ are the $\ell$-adic places of $F$; this is a subgroup of $\widetilde{\Cl}$. \item $G'$ is the vector of elementary divisors for the $\ell$-Sylow $Cl'$ of the $S$-class group of $F$; the group $\widetilde{\Cl}$ maps to $Cl'$ with a simple co-kernel. pari-2.17.2/src/functions/number_fields/bnfisnorm0000644000175000017500000000277514676526175020557 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, you may set flag=0 (in this case, x is a norm iff b=1). If flag is nonzero 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 4log(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}, you may set $\fl=0$ (in this case, $x$ is a norm iff $b=1$). If $\fl$ is nonzero 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 $4\log(\disc(\var{Bnf}))^{2}$, where $\var{Bnf}$ is the Galois closure of $\var{bnf}$. See also \tet{bnfisintnorm}. pari-2.17.2/src/functions/number_fields/galoischardet0000644000175000017500000000221414676526175021357 0ustar billbillFunction: galoischardet Section: number_fields C-Name: galoischardet Prototype: GGD1,L, Help: galoischardet(gal,chi,{o=1}): return the determinant character of the character chi. Doc: Let $G$ be the group attached to the \kbd{galoisinit} structure~\var{gal}, and let $\chi$ be the character of some representation $\rho$ of the group $G$, where a polynomial variable is to be interpreted as an $o$-th root of 1. For instance, if \kbd{[T,o] = galoischartable(gal)} the characters $\chi$ are input as the columns of \kbd{T}. Return the degree-$1$ character $\det\rho$ as the list of $\det \rho(g)$, where $g$ runs through representatives of the conjugacy classes in \kbd{galoisconjclasses(gal)}, with the same ordering. \bprog ? P = x^5 - x^4 - 5*x^3 + 4*x^2 + 3*x - 1; ? polgalois(P) %2 = [10, 1, 1, "D(5) = 5:2"] ? K = nfsplitting(P); ? gal = galoisinit(K); \\ dihedral of order 10 ? [T,o] = galoischartable(gal); ? chi = T[,1]; \\ trivial character ? galoischardet(gal, chi, o) %7 = [1, 1, 1, 1]~ ? [galoischardet(gal, T[,i], o) | i <- [1..#T]] \\ all characters %8 = [[1, 1, 1, 1]~, [1, 1, -1, 1]~, [1, 1, -1, 1]~, [1, 1, -1, 1]~] @eprog pari-2.17.2/src/functions/number_fields/nfhilbert0000644000175000017500000000142114760123736020510 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 nontrivial 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 nf,GEN a,GEN b} (global quadratic Hilbert symbol), where \kbd{nf} is a true \var{nf} structure. pari-2.17.2/src/functions/number_fields/nfrootsof10000644000175000017500000000232414676526175020650 0ustar billbillFunction: nfrootsof1 Section: number_fields C-Name: nfrootsof1 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. It is possible to input a defining polynomial for \var{nf} instead. \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. pari-2.17.2/src/functions/number_fields/subcyclopclgp0000644000175000017500000002114714760123736021413 0ustar billbillFunction: subcyclopclgp Section: number_fields C-Name: subcyclopclgp Prototype: GGD0,L, Help: subcyclopclgp(fH,p,{flag=0}): Let F be the abelian number field contained in Q(zeta_f) corresponding to the subgroup H of (Z/fZ)^*. Returns the minus part of Iwasawa polynomials attached to the ideal class group of F. Doc: Let $F$ be the abelian number field contained in $\Q(\zeta_{f})$ corresponding to the subgroup $H$ of $(\Z/f\Z)^{*}$, let $p > 2$ be an odd prime not dividing $[F:\Q]$. Computes the $p$-Sylow subgroup $A_{F}$ of the ideal class group using an unconditional algorithm of M.~Aoki and T.~Fukuda (LNCS. vol.4076, pp.56--71, 2006). The argument \kbd{fH} encodes the data $[f,H]$ as follows: \item $\kbd{fH} = [f, H]$, where $H$ is given by a vector of integral generators, \item $\kbd{fH} = [\var{bnr}, H]$, where \var{bnr} is attached to $\Cl_{f}(\Q)$ and $H$ is a congruence subgroup, \item $\kbd{fH} = [G, H]$, where $G$ is \kbd{idealstar}$(f,1)$, and $H$ is a subgroup of $(\Z/f\Z)^{\times}$, \item $\kbd{fH} = f$, where we assume that $H = \{1\}$, i.e., $F = \Q(\zeta_{f})$, \item an irreducible integral polynomial defining a primitive element for $F$. \noindent The result is a 6-component vector $v$, and components $2$ or $3$ can be left empty or only partially computed to save time (see \fl\ below): $v[1]$ is $p$. $v[2]$ contains $[E, [e_{1},\dots,e_{k}]]$ with $E = \sum_{i} e_{i}$, meaning that the order of $A_{F}^{+}$ is $p^{E}$ and its cyclic structure is $\Z/p^{e_{1}}\Z \times \dots \Z/p^{e_{k}}\Z$ $v[3]$ similarly describes the order and the structure of $A_{F}^{-}$. $v[4]$ contains the structure of $\text{Gal}(F/\Q)$ as a product of cyclic groups (elementary divisors). $v[5]$ is the number of cyclic subfields $K$ of $F$ except for $\Q$. $v[6]$ is the number of $\Q_{p}$-conjugacy classes of injective characters $\chi:\text{Gal}(K/\Q)\rightarrow\overline{\Q}_{p}^{\times}$. \noindent A vector of primes $p$ is also accepted and the result is then a vector of vectors as above, in the same order as the primes. The group $A_{F}$ is the direct sum of $A_{F}^{+}$ and $A_{F}^{-}$; each of $A_{F}^{+}$ and $A_{F}^{-}$ is decomposed into $\chi$-parts $A_{\chi}$. By default, the function computes only $|A_{F}^{-}|$ and an upper bound for $|A_{F}^{+}|$ (expected to be equal to $|A_{F}^{+}|$) separately with different algorithms. This is expected to be fast. The behavior is controled by the binary digits of \fl: 1: if $|A_{F}^{+}|$ or $|A_{F}^{-}|$ is computed, also determines its group structure and guarantees informations about $A_{F}^{+}$. This last part is usually costly. 2: do not compute quantities related to $A_{F}^{+}$ (the corresponding $(e_{i})$ in $v[2]$ is replaced with a dummy empty vector). 4: do not compute quantities related to $A_{F}^{-}$ (the corresponding $(e_{i})$ in $v[3]$ is replaced with a dummy empty vector). 8: ignores proper subfields of $F$. This is motivated by the following kind of problems: let $\Q(p^{k})$ be the $k$-th layer of the cyclotomic $\Z_{p}$-extension of $\Q$ and define $\Q(n)=\Q(p_{1}^{e_{1}})\cdots\Q(p_{r}^{e_{r}})$ when $n$ factors as $n=p_{1}^{e_{1}}\cdots p_{r}^{e_{r}}$, which is a real cyclic field of degree $n$ satisfying $\Q(n) \subset \Q(m)$ when $n\mid m$. What are the prime factors of the class number $h(n)$ of $\Q(n)$ ? The new prime factors of $h(n)$, not occurring in a lower level, will all be present when using this \fl. The other values are technical and only useful when bit 1 (certification and structure) is set; do not set them unless you run into difficulties with default parameters. 16: when this bit is set, the function tries to save memory, sacrificing speed; this typically uses half the memory for a slowdown of a factor $2$. 32: likely to speed up the algorithm when the rank of $A_{\chi}$ is large and to create a minor slowdown otherwise. Though the effect is restricted, the $3$-class group of $\Q(\sqrt{15338}, \zeta_{5})$ is computed 4 times faster when this bit is set (see below). \misctitle{Examples} With default $\fl=0$, the function (quickly) determines the exact value of $|A_{F}^{-}|$ and a rigorous upper bound of $|A_{F}^{+}|$ which is expected to be equal to $|A_{F}^{+}|$; of course, when the upper bound is $0$, we know for sure that $A_{F}^{+}$ is trivial. With $\fl=1$ we obtain the group structure of $A_{F}$ completely and guarantee the informations about $A_{F}^{+}$ (slow). \bprog ? subcyclopclgp(22220, 101) time = 113 ms. %1 = [101, [0, []], [41, [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]], [100, 20, 2, 2], 479, 7999] @eprog\noindent This computes the 101-part $A_{F}$ of the ideal class group of $F=\Q(\zeta_{22220})$. The output says that $A_{F}^{+}=0$, which is rigorous (since trivial), and $|A_{F}^{-}|=101^{41}$, more precisely $A_{F}^{-}$ is isomorphic to $(\Z/101\Z)^{41}$ which is also rigorous (since the description of $A_{F}^{-}$ is always rigorous). The Galois group $\text{Gal}(F/\Q)$ is $\Z/100\Z\oplus\Z/20\Z\oplus\Z/2\Z\oplus\Z/2\Z$. The field $F$ has 479 cyclic subfields different from $\Q$ and there are 7999 $\Q_{101}$-conjugacy classes of injective characters $\chi:\text{Gal}(K/\Q)\rightarrow\overline{\Q}_{101}^{\times}$. \bprog ? subcyclopclgp(22220, 11) time = 83 ms. %2 = [11, [2, [1, 1]], [16, []], [100, 20, 2, 2], 479, 1799] @eprog\noindent This computes the 11-part $A_{F}$ for the same $F$. The result says that $|A_{F}^{+}|=11^{2}$, $A_{F}^{+}$ is isomorphic to $(\Z/11\Z)^{2}$ which is not rigorous and is only an upper bound, and $|A_{F}^{-}|=11^{16}$ which is rigorous. The group structure of $A_{F}^{-}$ is unknown. \bprog ? subcyclopclgp(22220, 11, 1) time = 185 ms. %3 = [11, [2, [1, 1]], [16, [2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]], [100, 20, 2, 2], 479, 1799] @eprog\noindent now guarantees that $A_{F}^{+}$ is isomorphic to $(\Z/11\Z)^{2}$ and determines that $A_{F}^{-}$ is isomorphic to $\Z/11^{2}\Z\oplus(\Z/11\Z)^{14}$, at the expense of slightly increasing the running time. We now try a much harder example: $F=\Q(\sqrt{36322},\zeta_{5})$, which we could define using $f = 726440$ and $H = [41, 61, 111, 131]$ (prove it!). We will use a defining polynomial instead: \bprog ? T = polcompositum(x^2-36322, polcyclo(5), 2); ? subcyclopclgp(T, 5) \\ fast when non rigorous for A^+ time = 82 ms. %4 = [5, [1, [1]], [4, []], [4, 2], 5, 7] \\ try to certify; requires about 2GB of memory ? subcyclopclgp(T, 5, 1) *** subcyclopclgp: the PARI stack overflows ! current stack size: 1000003072 (1907.352 Mbytes) ? default(parisizemax,"2G"); ? subcyclopclgp(T, 5, 1) \\ with more memory, we get an answer time = 36,201 ms. %6 = [5, [1, [1]], [4, [3, 1]], [4, 2], 5, 7] \\ trying to reduce memory use does not work (still need 2GB); slower ? subcyclopclgp(T, 5, 1+16) time = 39,450 ms. @eprog\noindent This shows that $A_{F}^{+}$ is isomorphic to $\Z/5\Z$ and $A_{F}^{-}$ is isomorphic to $\Z/5^{3}\Z\oplus\Z/5\Z$ for $p=5$. For this example, trying to reduce memory use with $\fl = 1+16$ fails: the computation becomes slower and still needs 2GB; $\fl = 1+16+32$ is a disaster: it requires about 8GB and 9 minutes of computation. Here's a situation where the technical flags make a difference: let $F = \Q(\sqrt{15338}, \zeta_{5})$. \bprog ? T = polcompositum(x^2-15338, polcyclo(5), 2); ? subcyclopclgp(T, 3) time = 123 ms. %2 = [3, [1, [1]], [4, []], [4, 2], 5, 5] ? subcyclopclgp(T, 3, 1) \\ requires a stack of 8GB time = 4min, 47,822 ms. %3 = [3, [1, [1]], [4, [1, 1, 1, 1]], [4, 2], 5, 5] ? subcyclopclgp(T, 3, 1+16); time = 7min, 20,876 ms. \\ works with 5GB, but slower ? subcyclopclgp(T, 3, 1+32); time = 1min, 11,424 ms. \\ also works with 5GB, 4 times faster than original ? subcyclopclgp(T, 3, 1+16+32); time = 1min, 47,285 ms. \\ now works with 2.5GB @eprog Let $F = \Q(106)$ defined as above; namely, $F$ is the composite field of $\Q(\sqrt{2})$ and the subfield of $\Q(\zeta_{53^{2}})$ with degree 53. This time we shall build the compositum using class field theory: \bprog ? Q = bnfinit(y); ? bnr1 = bnrinit(Q, 8); H1 = Mat(2); ? bnr2 = bnrinit(Q, [53^2, [1]]); H2 = Mat(53); ? [bnr,H] = bnrcompositum([bnr1, H1], [bnr2, H2]); ? subcyclopclgp([bnr,H], 107) time = 10 ms. %5 = [107, [1, [1]], [0, []], [106], 3, 105] ? subcyclopclgp([bnr,H], 107, 1) \\ requires 2.5GB time = 15min, 13,537 ms. %6 = [107, [1, [1]], [0, []], [106], 3, 105] @eprog\noindent Both results are identical (and they were expected to be), but only the second is rigorous. Flag bit 32 has a minor impact in this case (reduces timings by 20 s.) pari-2.17.2/src/functions/number_fields/rnfpseudobasis0000644000175000017500000000364214676526175021603 0ustar billbillFunction: rnfpseudobasis Section: number_fields C-Name: rnfpseudobasis Prototype: GG Help: rnfpseudobasis(nf,T): given an irreducible polynomial T with coefficients in nf, returns [A,J,D,d] where [A,J] is a pseudo basis of the maximal order of the extension, D is the relative ideal discriminant, and d is the relative discriminant in nf^*/nf*^2. Doc: given an \var{nf} structure attached to a number field $K$, as output by \kbd{nfinit}, and a monic irreducible polynomial $T$ in $\Z_{K}[x]$ defining a relative extension $L = K[x]/(T)$, computes the relative discriminant of $L$ and a pseudo-basis $(A,J)$ for the maximal order $\Z_{L}$ viewed as a $\Z_{K}$-module. This is output as a vector $[A,J,D,d]$, where $D$ is the relative ideal discriminant and $d$ is the relative discriminant considered as an element of $K^{*}/{K^{*}}^{2}$. \bprog ? K = nfinit(y^2+1); ? [A,J,D,d] = rnfpseudobasis(K, x^2+y); ? A %3 = [1 0] [0 1] ? J %4 = [1, 1] ? D %5 = [0, -4]~ ? d %6 = [0, -1]~ @eprog \misctitle{Huge discriminants, helping rnfdisc} The format $[T,B]$ is also accepted instead of $T$ and produce an order which is maximal at all prime ideals specified by $B$, see \kbd{??rnfinit}. \bprog ? p = 585403248812100232206609398101; ? q = 711171340236468512951957953369; ? T = x^2 + 3*(p*q)^2; ? [A,J,D,d] = V = rnfpseudobasis(K, T); D time = 22,178 ms. %10 = 3 ? [A,J,D,d] = W = rnfpseudobasis(K, [T,100]); D time = 5 ms. %11 = 3 ? V == W %12 = 1 ? [A,J,D,d] = W = rnfpseudobasis(K, [T, [3]]); D %13 = 3 ? V == W %14 = 1 @eprog\noindent In this example, the results are identical since $D \cap \Z$ factors over primes less than $100$ (and in fact, over $3$). Had it not been the case, the order would have been guaranteed maximal at primes $\goth{p} | p $ for $p \leq 100$ only (resp.~$\goth{p} | 3$). And might have been nonmaximal at any other prime ideal $\goth{p}$ such that $\goth{p}^{2}$ divided $D$. pari-2.17.2/src/functions/number_fields/nfeltval0000644000175000017500000000352014676526175020362 0ustar billbillFunction: nfeltval Section: number_fields C-Name: gpnfvalrem Prototype: GGGD& Help: nfeltval(nf,x,pr,{&y}): valuation of element x at the prime pr as output by idealprimedec. Doc: given an element $x$ in \var{nf} and a prime ideal \var{pr} in the format output by \kbd{idealprimedec}, computes the valuation $v$ at \var{pr} of the element $x$. The valuation of $0$ is \kbd{+oo}. \bprog ? nf = nfinit(x^2 + 1); ? P = idealprimedec(nf, 2)[1]; ? nfeltval(nf, x+1, P) %3 = 1 @eprog\noindent This particular valuation can also be obtained using \kbd{idealval(\var{nf},x,\var{pr})}, since $x$ is then converted to a principal ideal. If the $y$ argument is present, sets $y = x \tau^{v}$, where $\tau$ is a fixed ``anti-uniformizer'' for \var{pr}: its valuation at \var{pr} is $-1$; its valuation is $0$ at other prime ideals dividing \kbd{\var{pr}.p} and nonnegative at all other primes. In other words $y$ is the part of $x$ coprime to \var{pr}. If $x$ is an algebraic integer, so is $y$. \bprog ? nfeltval(nf, x+1, P, &y); y %4 = [0, 1]~ @eprog For instance if $x = \prod_{i} x_{i}^{e_{i}}$ is known to be coprime to \var{pr}, where the $x_{i}$ are algebraic integers and $e_{i}\in\Z$ then, if $v_{i} = \kbd{nfeltval}(\var{nf}, x_{i}, \var{pr}, \&y_{i})$, we still have $x = \prod_{i} y_{i}^{e_{i}}$, where the $y_{i}$ are still algebraic integers but now all of them are coprime to \var{pr}. They can then be mapped to the residue field of \var{pr} more efficiently than if the product had been expanded beforehand: we can reduce mod \var{pr} after each ring operation. Variant: Also available are \fun{long}{nfvalrem}{GEN nf, GEN x, GEN pr, GEN *y = NULL}, which returns \tet{LONG_MAX} if $x = 0$ and the valuation as a \kbd{long} integer, and \fun{long}{nfval}{GEN nf, GEN x, GEN pr}, which only returns the valuation ($y = \kbd{NULL}$). pari-2.17.2/src/functions/number_fields/rnfbasistoalg0000644000175000017500000000064613637407207021401 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.17.2/src/functions/number_fields/galoisidentify0000644000175000017500000000212113637407207021543 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.17.2/src/functions/number_fields/idealadd0000644000175000017500000000246214676526175020302 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: nonsquare t_MAT in idealtyp. ? c = [2, 0; 2, 0]; idealadd(K, c, c) \\ nonsense %6 = [2 0] [0 2] ? d = [1, 0; 0, 2]; idealadd(K, d, d) \\ nonsense %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 $\Z_{K}$-module. To add arbitrary $\Z$-modules generated by the columns of matrices $A$ and $B$, use \kbd{mathnf(concat(A,B))}. pari-2.17.2/src/functions/number_fields/bnrinit0000644000175000017500000000672314676526175020224 0ustar billbillFunction: bnrinit Section: number_fields C-Name: bnrinitmod Prototype: GGD0,L,DG Help: bnrinit(bnf,f,{flag=0},{cycmod}): 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. If the positive integer cycmod is present, only compute the ray class group modulo cycmod-th powers. Description: (gen,gen,?small):bnr bnrinit0($1, $2, $3) Doc: $\var{bnf}$ is as output by \kbd{bnfinit} (including fundamental units), $f$ is a modulus, initializes data linked to the ray class group structure corresponding to this module, a so-called \kbd{bnr} structure. One can input the attached \var{bid} with generators for $f$ instead of the module itself, saving some time. (As in \tet{idealstar}, the finite part of the conductor may be given by a factorization into prime ideals, as produced by \tet{idealfactor}.) If the positive integer \kbd{cycmod} is present, only compute the ray class group modulo \kbd{cycmod}, which may save a lot of time when some maximal ideals in $f$ have a huge residue field. In applications, we are given a congruence subgroup $H$ and study the class field attached to $\text{Cl}_{f}/H$. If that finite Abelian group has an exponent which divides \kbd{cycmod}, then we have changed nothing theoretically, while trivializing expensive discrete logs in residue fields (since computations can be made modulo \kbd{cycmod}-th powers). This is useful in \kbd{bnrclassfield}, for instance when computing $p$-elementary extensions. The following member functions are available on the result: \kbd{.bnf} is the underlying \var{bnf}, \kbd{.mod} the modulus, \kbd{.bid} the \kbd{bid} structure attached to the modulus; finally, \kbd{.clgp}, \kbd{.no}, \kbd{.cyc}, \kbd{.gen} refer to the ray class group (as a finite abelian group), its cardinality, its elementary divisors, its generators (only computed if $\fl = 1$). The last group of functions are different from the members of the underlying \var{bnf}, which refer to the class group; use \kbd{\var{bnr}.bnf.\var{xxx}} to access these, e.g.~\kbd{\var{bnr}.bnf.cyc} to get the cyclic decomposition of the class group. They are also different from the members of the underlying \var{bid}, which refer to $(\Z_{K}/f)^{*}$; use \kbd{\var{bnr}.bid.\var{xxx}} to access these, e.g.~\kbd{\var{bnr}.bid.no} to get $\phi(f)$. If $\fl=0$ (default), the generators of the ray class group are not explicitly computed, which saves time. Hence \kbd{\var{bnr}.gen} would produce an error. Note that implicit generators are still fixed and stored in the \var{bnr} (and guaranteed to be the same for fixed \var{bnf} and \var{bid} inputs), in terms of \kbd{bnr.bnf.gen} and \kbd{bnr.bid.gen}. The computation which is not performed is the expansion of such products in the ray class group so as to fix eplicit ideal representatives. If $\fl=1$, as the default, except that generators are computed. Variant: Instead of the above hardcoded numerical flags, one should rather use \fun{GEN}{Buchraymod}{GEN bnf, GEN module, long flag, GEN cycmod} where an omitted \kbd{cycmod} is coded as \kbd{NULL} and $\fl$ is an or-ed combination of \kbd{nf\_GEN} (include generators) and \kbd{nf\_INIT} (if omitted, return just the cardinality of the ray class group and its structure), possibly 0. Or simply \fun{GEN}{Buchray}{GEN bnf, GEN module, long flag} when \kbd{cycmod} is \kbd{NULL}. pari-2.17.2/src/functions/number_fields/nfeltissquare0000644000175000017500000000065514676526175021442 0ustar billbillFunction: nfeltissquare Section: number_fields C-Name: nfissquare Prototype: lGGD& Help: nfeltissquare(nf,x,{&y}): returns 1 if x is a square in nf (and sets y to a square root if present), else returns 0. Doc: returns $1$ if $x$ is a square in \kbd{nf} (and sets $y$ to a square root if the argument is present), else returns 0. \bprog ? nf = nfinit(1+x^2); ? nfeltissquare(nf, -1, &y) %2 = 1 ? y %3 = [0, -1]~ @eprog pari-2.17.2/src/functions/number_fields/matalgtobasis0000644000175000017500000000061714567450071021373 0ustar billbillFunction: matalgtobasis Section: number_fields C-Name: matalgtobasis Prototype: GG Obsolete: 2016-08-08 Help: matalgtobasis(nf,x): nfalgtobasis applied to every element of the vector or matrix x. Doc: This function is deprecated, use \kbd{apply}. $\var{nf}$ being a number field in \kbd{nfinit} format, and $x$ a (row or column) vector or matrix, apply \tet{nfalgtobasis} to each entry of $x$. pari-2.17.2/src/functions/number_fields/nfeltsign0000644000175000017500000000226014676526175020540 0ustar billbillFunction: nfeltsign Section: number_fields C-Name: nfeltsign Prototype: GGDG Help: nfeltsign(nf,x,{pl}): signs of real embeddings of x at places given by vector pl. Doc: given an element $x$ in the number field \var{nf}, returns the signs of the real embeddings of $x$ specified by optional argument \var{pl}: \item \var{pl} omitted: return the vector of signs at all $r_{1}$ real places; \item \var{pl} an integer between $1$ and $r_{1}$: return the sign of the $i$-th embedding of $x$, attached to the $i$-th real root of \kbd{nf.pol}, i.e. \kbd{nf.roots$[i]$}; \item \var{pl} a vector or \typ{VECSMALL}: return the vector of signs; the $i$-th entry gives the sign at the real place attached to the $\var{pl}[i]$-th real root of \kbd{nf.pol}. \bprog ? nf = nfinit(polsubcyclo(11,5,'y)); \\ Q(cos(2 pi/11)) ? nf.sign %2 = [5, 0] ? x = Mod('y, nf.pol); ? nfeltsign(nf, x) %4 = [-1, -1, -1, 1, 1] ? nfeltsign(nf, x, 1) %5 = -1 ? nfeltsign(nf, x, [1..4]) %6 = [-1, -1, -1, 1] ? nfeltsign(nf, x, 6) \\ there are only 5 real embeddings *** at top-level: nfeltsign(nf,x,6) *** ^----------------- *** nfeltsign: domain error in nfeltsign: index > 5 @eprog pari-2.17.2/src/functions/number_fields/galoisgetpol0000644000175000017500000000310014567450071021220 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 \kbd{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 current version of \kbd{galpol} supports groups of order $a\leq 143$. The output is a vector [\kbd{pol}, \kbd{den}] where \item \kbd{pol} is the polynomial of degree $a$ \item \kbd{den} is the denominator of \kbd{nfgaloisconj(pol)}. Pass it as an optional argument to \tet{galoisinit} or \tet{nfgaloisconj} to speed them up: \bprog ? [pol,den] = galoisgetpol(64,4,1); ? G = galoisinit(pol); time = 352ms ? galoisinit(pol, den); \\ passing 'den' speeds up the computation time = 264ms ? % == %` %4 = 1 \\ same answer @eprog If $b$ and $s$ are omitted, return the number of isomorphism classes of groups of order $a$. Variant: Also available is \fun{GEN}{galoisnbpol}{long a} when $b$ and $s$ are omitted. pari-2.17.2/src/functions/number_fields/bnfisintnorm0000644000175000017500000000423514760123736021251 0ustar billbillFunction: bnfisintnorm Section: number_fields C-Name: bnfisintnorm0 Prototype: GGD0,L, Help: bnfisintnorm(bnf,x,{flag=0}): 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). If (optional) flag is set, allow returning solutions in factored form. 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}. If (optional) flag is set, allow returning solutions in factored form, which helps a lot when the fundamental units are large (equivalently, when \kbd{bnf.reg} is large); having an exact algebraic $\var{bnf}$ from \kbd{bnfinit(,1)} is necessary in this case, else setting the flag will mostly be a no-op. \bprog ? bnf = bnfinit(x^4-2, 1); ? bnfisintnorm(bnf,7) %2 = [-x^2 + x - 1, x^2 + x + 1] ? bnfisintnorm(bnf,-7) %3 = [-x^3 - 1, x^3 + 2*x^2 + 2*x + 1] ? bnf = bnfinit(x^2-2305843005992468481, 1); ? bnfisintnorm(bnf, 2305843008139952128) \\ stack overflow with 100GB parisize ? bnf.reg \\ fundamental unit is huge %6 = 14054016.227457155120413774802385952043 ? v = bnfisintnorm(bnf, 2305843008139952128, 1); #v %7 = 31 \\ succeeds instantly ? s = v[1]; [type(s), matsize(s)] %8 = ["t_MAT", [165, 2]] \\ solution 1 is a product of 165 factors ? exponent(s[,2]) %9 = 105 @eprog\noindent The \emph{exponents} have $105$ bits, so there is indeed little hope of writing down the solutions in expanded form. See also \tet{bnfisnorm}. Variant: The function \fun{GEN}{bnfisintnormabs0}{GEN bnf, GEN a, long flag}, where \kbd{bnf} is a true \var{bnf} structure, returns a complete system of solutions modulo units of the absolute norm equation $|\Norm(x)| = |a|$. As fast as \kbd{bnfisintnorm}, but solves the two equations $\Norm(x) = \pm a$ simultaneously. The functions \fun{GEN}{bnfisintnormabs}{GEN bnf, GEN a}, \fun{GEN}{bnfisintnorm}{GEN bnf, GEN a} correspond to $\fl = 0$. pari-2.17.2/src/functions/number_fields/rnfeltabstorel0000644000175000017500000000254114676526175021577 0ustar billbillFunction: rnfeltabstorel Section: number_fields C-Name: rnfeltabstorel Prototype: GG Help: rnfeltabstorel(rnf,x): transforms the element x from absolute to relative representation. Doc: Let $\var{rnf}$ be a relative number field extension $L/K$ as output by \kbd{rnfinit} and let $x$ be an element of $L$ expressed either \item as a polynomial modulo the absolute equation \kbd{\var{rnf}.polabs}, \item or in terms of the absolute $\Z$-basis for $\Z_{L}$ if \var{rnf} contains one (as in \kbd{rnfinit(nf,pol,1)}, or after a call to \kbd{nfinit(rnf)}). Computes $x$ as an element of the relative extension $L/K$ as a polmod with polmod coefficients. If $x$ is actually rational, return it as a rational number: \bprog ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y); ? L.polabs %2 = x^4 + 1 ? rnfeltabstorel(L, Mod(x, L.polabs)) %3 = Mod(x, x^2 + Mod(-y, y^2 + 1)) ? rnfeltabstorel(L, 1/3) %4 = 1/3 ? rnfeltabstorel(L, Mod(x, x^2-y)) %5 = Mod(x, x^2 + Mod(-y, y^2 + 1)) ? rnfeltabstorel(L, [0,0,0,1]~) \\ Z_L not initialized yet *** at top-level: rnfeltabstorel(L,[0, *** ^-------------------- *** rnfeltabstorel: incorrect type in rnfeltabstorel, apply nfinit(rnf). ? nfinit(L); \\ initialize now ? rnfeltabstorel(L, [0,0,0,1]~) %6 = Mod(Mod(y, y^2 + 1)*x, x^2 + Mod(-y, y^2 + 1)) ? rnfeltabstorel(L, [1,0,0,0]~) %7 = 1 @eprog pari-2.17.2/src/functions/number_fields/nffactormod0000644000175000017500000000224714567450071021044 0ustar billbillFunction: nffactormod Section: number_fields C-Name: nffactormod Obsolete: 2016-09-18 Prototype: GGG Help: nffactormod(nf,Q,pr): this routine is obsolete, use nfmodpr and factormod. Factor polynomial Q modulo prime ideal pr in number field nf. Doc: this routine is obsolete, use \kbd{nfmodpr} and \kbd{factormod}. Factors the univariate polynomial $Q$ modulo the prime ideal \var{pr} in the number field $\var{nf}$. The coefficients of $Q$ belong to the number field (scalar, polmod, polynomial, even column vector) and the main variable of $\var{nf}$ must be of lower priority than that of $Q$ (see \secref{se:priority}). The prime ideal \var{pr} is either in \tet{idealprimedec} or (preferred) \tet{modprinit} format. The coefficients of the polynomial factors are lifted to elements of \var{nf}: \bprog ? K = nfinit(y^2+1); ? P = idealprimedec(K, 3)[1]; ? nffactormod(K, x^2 + y*x + 18*y+1, P) %3 = [x + (2*y + 1) 1] [x + (2*y + 2) 1] ? P = nfmodprinit(K, P); \\ convert to nfmodprinit format ? nffactormod(K, x^2 + y*x + 18*y+1) %5 = [x + (2*y + 1) 1] [x + (2*y + 2) 1] @eprog\noindent Same result, of course, here about 10\% faster due to the precomputation. pari-2.17.2/src/functions/number_fields/rnfequation0000644000175000017500000000434714567450071021100 0ustar billbillFunction: rnfequation Section: number_fields C-Name: rnfequation0 Prototype: GGD0,L, Help: rnfequation(nf,pol,{flag=0}): given a pol with coefficients in nf, gives an absolute equation z of the number field defined by pol. flag is optional, and can be 0: default, or nonzero, gives [z,al,k], where z defines the absolute equation L/Q as in the default behavior, al expresses as an element of L a root of the polynomial defining the base field nf, and k is a small integer such that t = b + k al is a root of z, for b a root of pol. Doc: given a number field $\var{nf}$ as output by \kbd{nfinit} (or simply a monic irreducible integral polynomial defining the field) and a polynomial \var{pol} with coefficients in $\var{nf}$ defining a relative extension $L$ of $\var{nf}$, computes an absolute equation of $L$ over $\Q$. The main variable of $\var{nf}$ \emph{must} be of lower priority than that of \var{pol} (see \secref{se:priority}). Note that for efficiency, this does not check whether the relative equation is irreducible over $\var{nf}$, but only if it is squarefree. If it is reducible but squarefree, the result will be the absolute equation of the \'etale algebra defined by \var{pol}. If \var{pol} is not squarefree, raise an \kbd{e\_DOMAIN} exception. \bprog ? rnfequation(y^2+1, x^2 - y) %1 = x^4 + 1 ? T = y^3-2; rnfequation(nfinit(T), (x^3-2)/(x-Mod(y,T))) %2 = x^6 + 108 \\ Galois closure of Q(2^(1/3)) @eprog If $\fl$ is nonzero, outputs a 3-component row vector $[z,a,k]$, where \item $z$ is the absolute equation of $L$ over $\Q$, as in the default behavior, \item $a$ expresses as a \typ{POLMOD} modulo $z$ a root $\alpha$ of the polynomial defining the base field $\var{nf}$, \item $k$ is a small integer such that $\theta = \beta+k\alpha$ is a root of $z$, where $\beta$ is a root of $\var{pol}$. It is guaranteed that $k=0$ whenever $\Q(\beta) = L$. \bprog ? T = y^3-2; pol = x^2 +x*y + y^2; ? [z,a,k] = rnfequation(T, pol, 1); ? z %3 = x^6 + 108 ? subst(T, y, a) %4 = 0 ? alpha= Mod(y, T); ? beta = Mod(x*Mod(1,T), pol); ? subst(z, x, beta + k*alpha) %7 = 0 @eprog Variant: Also available are \fun{GEN}{rnfequation}{GEN nf, GEN pol} ($\fl = 0$) and \fun{GEN}{rnfequation2}{GEN nf, GEN pol} ($\fl = 1$). pari-2.17.2/src/functions/number_fields/idealnorm0000644000175000017500000000032613637407207020510 0ustar billbillFunction: idealnorm Section: number_fields C-Name: idealnorm Prototype: GG Help: idealnorm(nf,x): norm of the ideal x in the number field nf. Doc: computes the norm of the ideal~$x$ in the number field~$\var{nf}$. pari-2.17.2/src/functions/number_fields/nfsolvemodpr0000644000175000017500000000147114567450071021256 0ustar billbillFunction: nfsolvemodpr Section: number_fields C-Name: nfsolvemodpr Prototype: GGGG Obsolete: 2016-08-09 Help: nfsolvemodpr(nf,a,b,P): this function is obsolete, use nfmodpr. Doc: this function is obsolete, use \kbd{nfmodpr}. Let $P$ be a prime ideal in \key{modpr} format (see \kbd{nfmodprinit}), let $a$ be a matrix, invertible over the residue field, and let $b$ be a column vector or matrix. This function returns a solution of $a\cdot x = b$; the coefficients of $x$ are lifted to \var{nf} elements. \bprog ? K = nfinit(y^2+1); ? P = idealprimedec(K, 3)[1]; ? P = nfmodprinit(K, P); ? a = [y+1, y; y, 0]; b = [1, y]~ ? nfsolvemodpr(K, a,b, P) %5 = [1, 2]~ @eprog Variant: This function is normally useless in library mode. Project your inputs to the residue field using \kbd{nfM\_to\_FqM}, then work there. pari-2.17.2/src/functions/number_fields/nfsplitting0000644000175000017500000000571414676526175021117 0ustar billbillFunction: nfsplitting Section: number_fields C-Name: nfsplitting0 Prototype: GDGD0,L, Help: nfsplitting(P,{d},{fl}): defining polynomial S over Q for the splitting field of P, that is the smallest field over which P is totally split. P can also be given by a nf structure. If d is given, it must be a multiple of the splitting field degree. If fl=1, return [S,C] where C is an embedding of Q[x]/(P) in its splitting field. Doc: defining polynomial $S$ over~$\Q$ for the splitting field of $\var{P} \in \Q[x]$, that is the smallest field over which $P$ is totally split. If irreducible, the polynomial $P$ can also be given by a~\kbd{nf} structure, which is more efficient. If $d$ is given, it must be a multiple of the splitting field degree. Note that if $P$ is reducible the splitting field degree can be smaller than the degree of $P$. If $\fl$ is non-zero, we assume $P$ to be monic, integral and irreducible and the return value depends on $\fl$: \item $\fl = 1$: return $[S,C]$ where $S$ is as before and $C$ is an embedding of $\Q[x]/(P)$ in its splitting field given by a polynomial (implicitly modulo $S$, as in \kbd{nfisincl}). \item $\fl = 2$: return $[S,C]$ where $C$ is vector of rational functions whose image in $\Q[x]/(S)$ yields the embedding; this avoids inverting the denominator, which is costly. when the degree of the splitting field is huge. \item $\fl = 3$: return $[S, v, p]$ a data structure allowing to quickly compute the Galois group of the splitting field, which is used by \kbd{galoissplittinginit}; more precisely, $p$ is a prime splitting completely in the splitting field and $v$ is a vector with $\deg S$ elements describing the automorphisms of $S$ acting on the roots of $S$ modulo $p$. \bprog ? K = nfinit(x^3 - 2); ? nfsplitting(K) %2 = x^6 + 108 ? nfsplitting(x^8 - 2) %3 = x^16 + 272*x^8 + 64 ? S = nfsplitting(x^6 - 8) \\ reducible %4 = x^4 + 2*x^2 + 4 ? lift(nfroots(subst(S,x,a),x^6-8)) %5 = [-a, a, -1/2*a^3 - a, -1/2*a^3, 1/2*a^3, 1/2*a^3 + a] ? P = x^8-2; ? [S,C] = nfsplitting(P,,1) %7 = [x^16 + 272*x^8 + 64, -7/768*x^13 - 239/96*x^5 + 1/2*x] ? subst(P, x, Mod(C,S)) %8 = Mod(0, x^16 + 272*x^8 + 64) @eprog\noindent Specifying the degree $d$ of the splitting field can make the computation faster; if $d$ is not a multiple of the true degree, it will be ignored with a warning. \bprog ? nfsplitting(x^17-123); time = 3,607 ms. ? poldegree(%) %2 = 272 ? nfsplitting(x^17-123,272); time = 150 ms. ? nfsplitting(x^17-123,273); *** nfsplitting: Warning: ignoring incorrect degree bound 273 time = 3,611 ms. @eprog \noindent The complexity of the algorithm is polynomial in the degree $d$ of the splitting field and the bitsize of $T$; if $d$ is large the result will likely be unusable, e.g. \kbd{nfinit} will not be an option: \bprog ? nfsplitting(x^6-x-1) [... degree 720 polynomial deleted ...] time = 11,020 ms. @eprog Variant: Also available is \fun{GEN}{nfsplitting}{GEN T, GEN D} for $\fl = 0$. pari-2.17.2/src/functions/number_fields/nfdetint0000644000175000017500000000052514567450071020352 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 nonzero ideal contained in (i.e.~multiple of) the determinant of $x$. This is particularly useful in conjunction with \kbd{nfhnfmod}. pari-2.17.2/src/functions/number_fields/rnfidealprimedec0000644000175000017500000000253014676526175022044 0ustar billbillFunction: rnfidealprimedec Section: number_fields C-Name: rnfidealprimedec Prototype: GG Help: rnfidealprimedec(rnf,pr): return prime ideal decomposition of the maximal ideal pr of K in L/K; pr is also allowed to be a prime number p, in which case return a pair of vectors [SK,SL], where SK contains the primes of K above p and SL[i] is the vector of primes of L above SK[i]. Doc: let \var{rnf} be a relative number field extension $L/K$ as output by \kbd{rnfinit}, and \var{pr} a maximal ideal of $K$ (\var{prid}), this function completes the \var{rnf} with a \var{nf} structure attached to $L$ (see \secref{se:rnfinit}) and returns the vector $S$ of prime ideals of $\Z_{L}$ above \var{pr}. \bprog ? K = nfinit(y^2+1); rnf = rnfinit(K, x^3+y+1); ? pr = idealprimedec(K, 2)[1]; ? S = rnfidealprimedec(rnf, pr); ? #S %4 = 1 @eprog\noindent The relative ramification indices and residue degrees can be obtained as \kbd{PR.e / pr.e} and \kbd{PR.f / PR.f}, if \kbd{PR} is an element of $S$. The argument \var{pr} is also allowed to be a prime number $p$, in which case the function returns a pair of vectors \kbd{[SK,SL]}, where \kbd{SK} contains the primes of $K$ above $p$ and \kbd{SL}$[i]$ is the vector of primes of $L$ above \kbd{SK}$[i]$. \bprog ? [SK,SL] = rnfidealprimedec(rnf, 5); ? [#SK, vector(#SL,i,#SL[i])] %6 = [2, [2, 2]] @eprog pari-2.17.2/src/functions/number_fields/gchareval0000644000175000017500000000147614676526175020513 0ustar billbillFunction: gchareval Section: number_fields C-Name: gchareval Prototype: GGGD1,L, Help: gchareval(gc,chi,x,{flag=1}): computes the evaluation chi(x) in C* if flag=1 and in C/Z if flag=0. Doc: \var{gc} being the structure returned by \kbd{gcharinit}, \var{chi} a character in \var{gc}, and \var{x} an ideal of the base field, returns the value~$\chi(x)$. If~$\fl=1$ (default), returns a value in~$\C^{\times}$; if~$\fl=0$, returns a value in~$\C/\Z$, normalized so that the real part is between~$-1/2$ and~$1/2$. \bprog ? bnf = bnfinit(x^2-5); ? gc = gcharinit(bnf,1); ? chi = [1]~; ? pr = idealprimedec(bnf,11)[1]; ? a = gchareval(gc,chi,pr) % = -0.3804107379142448929315340886 - 0.9248176417432464199580504588*I ? b = gchareval(gc,chi,pr,0) % = -0.3121086861831031476247589216 ? a == exp(2*Pi*I*b) %7 = 1 @eprog pari-2.17.2/src/functions/number_fields/nfisincl0000644000175000017500000000727514676526175020367 0ustar billbillFunction: nfisincl Section: number_fields C-Name: nfisincl0 Prototype: GGD0,L, Description: (gen, gen, ?0):gen nfisincl($1, $2) (gen, gen, small):gen nfisincl0($1, $2, $3) Help: nfisincl(f,g,{flag=0}): let f and g define number fields, either irreducible rational polynomials or number fields as output by nfinit; tests whether the number field f is isomorphic to a subfield of g. Return 0 if not, and otherwise all the embeddings (flag=0, default), only one (flag=1), or all embeddings as rational functions (flag=2). Doc: let $f$ and $g$ define number fields, where $f$ and $g$ are irreducible polynomials in $\Q[X]$ and \var{nf} structures as output by \kbd{nfinit}. If either $f$ or $g$ is not irreducible, the result is undefined. Tests whether the number field $f$ is conjugate to a subfield of the field $g$. If not, the output is the integer 0; if it is, the output depends on the value of $\fl$: \item $\fl = 0$ (default): return a vector of polynomials $[a_{1},\dots,a_{n}]$ with rational coefficients, representing all distinct embeddings: we have $g\mid f\circ a_{i}$ for all $i$. \item $\fl = 1$: return a single polynomial $a$ representing a single embedding; this can be $n$ times faster than the default when the embeddings have huge coefficients. \item $\fl = 2$: return a vector of rational functions $[r_{1},\dots,r_{n}]$ whose denominators are coprime to $g$ and such that $r_{i} \% g$ is the polynomial $a_{i}$ from $\fl = 0$. This variant is always faster than $\fl = 0$ but produces results which are harder to use. If the denominators are hard to invert in $\Q[X]/(g)$, this may be even faster than $\fl = 1$. \bprog ? T = x^6 + 3*x^4 - 6*x^3 + 3*x^2 + 18*x + 10; ? U = x^3 + 3*x^2 + 3*x - 2 ? nfisincl(U, T) %3 = [24/179*x^5-27/179*x^4+80/179*x^3-234/179*x^2+380/179*x+94/179] ? a = nfisincl(U, T, 1) %4 = 24/179*x^5-27/179*x^4+80/179*x^3-234/179*x^2+380/179*x+94/179 ? subst(U, x, Mod(a,T)) %5 = Mod(0, x^6 + 3*x^4 - 6*x^3 + 3*x^2 + 18*x + 10) ? nfisincl(U, T, 2) \\ a as a t_RFRAC %6 = [(2*x^3 - 3*x^2 + 2*x + 4)/(3*x^2 - 1)] ? (a - %[1]) % T %7 = 0 ? #nfisincl(x^2+1, T) \\ two embeddings %8 = 2 \\ same result with nf structures ? L = nfinit(T); K = nfinit(U); v = [a]; ? nfisincl(U, L) == v %10 = 1 ? nfisincl(K, T) == v %11 = 1 ? nfisincl(K, L) == v %12 = 1 \\ comparative bench: an nf is a little faster, esp. for the subfield ? B = 2000; ? for (i=1, B, nfisincl(U,T)) time = 1,364 ms. ? for (i=1, B, nfisincl(K,T)) time = 988 ms. ? for (i=1, B, nfisincl(U,L)) time = 1,341 ms. ? for (i=1, B, nfisincl(K,L)) time = 880 ms. @eprog\noindent Using an \var{nf} structure for the tentative subfield is faster if the structure is already available. On the other hand, the gain in \kbd{nfisincl} is usually not sufficient to make it worthwhile to initialize only for that purpose. \bprog ? for (i=1, B, nfinit(U)) time = 590 ms. @eprog\noindent A final more complicated example \bprog ? f = x^8 - 72*x^6 + 1944*x^4 - 30228*x^2 - 62100*x - 34749; ? g = nfsplitting(f); poldegree(g) %2 = 96 ? #nfisincl(f, g) time = 559 ms. %3 = 8 ? nfisincl(f,g,1); time = 172 ms. ? v = nfisincl(f,g,2); time = 199 ms. ? apply(x->poldegree(denominator(x)), v) %6 = [81, 81, 81, 81, 81, 81, 80, 81] ? v % g; time = 407 ms. @eprog\noindent This final example shows that mapping rational functions to $\Q[X]/(g)$ can be more costly than that the rest of the algorithm. Note that \kbd{nfsplitting} also admits a $\fl$ yielding an embedding. Variant: Also available is \fun{GEN}{nfisisom}{GEN a, GEN b} ($\fl = 0$). Function: _partmap_reverse_frac_worker C-Name: partmap_reverse_frac_worker Prototype: GGGGGL Section: programming/internals Help: worker for partmap_reverse_frac pari-2.17.2/src/functions/number_fields/nfeltdiveuc0000644000175000017500000000062614567450071021051 0ustar billbillFunction: nfeltdiveuc Section: number_fields C-Name: nfdiveuc Prototype: GGG Help: nfeltdiveuc(nf,x,y): gives algebraic integer q such that x-qy is small. Doc: given two elements $x$ and $y$ in \var{nf}, computes an algebraic integer $q$ in the number field $\var{nf}$ such that the components of $x-qy$ are reasonably small. In fact, this is functionally identical to \kbd{round(nfdiv(\var{nf},x,y))}. pari-2.17.2/src/functions/number_fields/rnfeltreltoabs0000644000175000017500000000167114676526175021602 0ustar billbillFunction: rnfeltreltoabs Section: number_fields C-Name: rnfeltreltoabs Prototype: GG Help: rnfeltreltoabs(rnf,x): transforms the element x from relative to absolute representation. Doc: $\var{rnf}$ being a relative number field extension $L/K$ as output by \kbd{rnfinit} and $x$ being an element of $L$ expressed as a polynomial or polmod with polmod coefficients, computes $x$ as an element of the absolute extension $L/\Q$ as a polynomial modulo the absolute equation \kbd{\var{rnf}.polabs}. \bprog ? K = nfinit(y^2+1); L = rnfinit(K, x^2-y); ? L.polabs %2 = x^4 + 1 ? rnfeltreltoabs(L, Mod(x, L.pol)) %3 = Mod(x, x^4 + 1) ? rnfeltreltoabs(L, Mod(y, x^2-y)) %4 = Mod(x^2, x^4 + 1) ? rnfeltreltoabs(L, Mod(y,K.pol)) %5 = Mod(x^2, x^4 + 1) @eprog\noindent If the input is actually rational, then \kbd{rnfeltreltoabs} returns it as a rational number instead of a \typ{POLMOD}: \bprog ? rnfeltreltoabs(L, Mod(2, K.pol)) %6 = 2 @eprog pari-2.17.2/src/functions/number_fields/newtonpoly0000644000175000017500000000073614567450071020761 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 \kbd{+oo}. pari-2.17.2/src/functions/number_fields/nfeltdivrem0000644000175000017500000000053114567450071021053 0ustar billbillFunction: nfeltdivrem Section: number_fields C-Name: nfdivrem Prototype: GGG Help: nfeltdivrem(nf,x,y): gives [q,r] such that r=x-qy is small. Doc: given two elements $x$ and $y$ in \var{nf}, gives a two-element row vector $[q,r]$ such that $x=qy+r$, $q$ is an algebraic integer in $\var{nf}$, and the components of $r$ are reasonably small. pari-2.17.2/src/functions/number_fields/gcharduallog0000644000175000017500000000352514676526175021210 0ustar billbillFunction: gcharduallog Section: number_fields C-Name: gcharduallog Prototype: GG Help: gcharduallog(gc,chi): returns logarithm vector of character chi in R^n. We have gchareval(gc,chi,x,0) = gcharduallog(gc,chi)*gcharlog(gc,x) in R/Z. Doc: Returns internal logarithm vector of character \kbd{chi} as a \typ{VEC} in $\R^{n}$, so that for all \var{x}, \kbd{gchareval}(\var{gc},\var{chi},\var{x},$0$) is equal to \kbd{gcharduallog}(\var{gc},\var{chi}) * \kbd{gcharlog}(\var{gc},\var{x}) in $\R/ \Z$. The components are organized as follows: \item the first \kbd{ns} components are in~$\R$ and describe the character on the class group generators: $\theta$ encodes~$\goth{p}\mapsto \exp(2i\pi\theta)$, \item the next \kbd{nc} components are in~$\R$ and describe the \kbd{idealstar} group character via its image on generators: $\theta$ encodes the image~$\exp(2i\pi\theta)$, \item the next $r_{1}+r_{2}$ components are in $\R$ and correspond to characters of $\R$ for each infinite place: $\varphi$ encodes~$x\mapsto |x|^{i\varphi}$ in the real case and~$z\mapsto |z|^{2i\varphi}$ in the complex case, \item the last $r_{2}$ components are in $\Z$ and correspond to characters of $\R/\Z$ for each complex place: $k$ encodes~$z\mapsto (z/|z|)^{k}$. \item the last component~$s$ is in~$\C$ and corresponds to a power~$\|\cdot\|^{s}$ of the ad\'elic norm. See also \kbd{gcharlog}. \bprog ? bnf = bnfinit(x^3+4*x-1,1); ? gc = gcharinit(bnf,[1,[1]]); ? gc.cyc % = [2, 0, 0, 0.E-57] ? chi = [0,1,0]~; ? f = gcharduallog(gc,chi) % = [0.153497221319231, 1/2, 0.776369647248353, -0.388184823624176, 1, 0] ? pr = idealprimedec(bnf,2)[1]; ? v = gcharlog(gc,pr); ? exp(2*I*Pi*f*v) % = -0.569867696226731232993110144 - 0.821736459454756074068598760*I ? gchareval(gc,chi,pr) % = -0.569867696226731232993110144 - 0.821736459454756074068598760*I @eprog pari-2.17.2/src/functions/number_fields/rnfisfree0000644000175000017500000000103614676526175020532 0ustar billbillFunction: rnfisfree Section: number_fields C-Name: rnfisfree Prototype: lGG Help: rnfisfree(bnf,M): given a bnf attached to a number field K and a projective Z_K module M given by a pseudo-matrix, return true (1) if M is free else return false (0). Doc: given a $\var{bnf}$ attached to a number field $K$ and a projective $\Z_{K}$-module $M$ given by a pseudo-matrix, return true (1) if $M$ is free else return false (0). If $M$ is a polynomial with coefficients in $K$, replace it by the pseudo-matrix returned by \kbd{rnfpseudobasis}. pari-2.17.2/src/functions/number_fields/idealprimedec0000644000175000017500000000420714676526175021341 0ustar billbillFunction: idealprimedec Section: number_fields C-Name: idealprimedec_limit_f Prototype: GGD0,L, Description: (gen, gen):vec idealprimedec($1, $2) (gen, gen, ?small):vec idealprimedec_limit_f($1, $2, $3) Help: idealprimedec(nf,p,{f=0}): prime ideal decomposition of the prime number p in the number field nf as a vector of prime ideals. If f is present and nonzero, restrict the result to primes of residue degree <= f. Doc: computes the prime ideal decomposition of the (positive) prime number $p$ in the number field $K$ represented by \var{nf}. If a nonprime $p$ is given the result is undefined. If $f$ is present and nonzero, restrict the result to primes of residue degree $\leq f$. The result is a vector of \tev{prid} structures, each representing one of the prime ideals above $p$ in the number field $\var{nf}$. The representation $\kbd{pr}=[p,a,e,f,\var{mb}]$ of a prime ideal means the following: $a$ is an algebraic integer in the maximal order $\Z_{K}$ and the prime ideal is equal to $\goth{p} = p\Z_{K} + a\Z_{K}$; $e$ is the ramification index; $f$ is the residual index; finally, \var{mb} is the multiplication table attached to an algebraic integer $b$ such that $\goth{p}^{-1}=\Z_{K}+ b/ p\Z_{K}$, which is used internally to compute valuations. In other words if $p$ is inert, then \var{mb} is the integer $1$, and otherwise it is a square \typ{MAT} whose $j$-th column is $b \cdot \kbd{nf.zk[j]}$. 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); ? P = idealprimedec(K, 5); ? #P \\ 2 primes above 5 in Q(2^(1/3)) %3 = 2 ? [p1,p2] = P; ? [p1.e, p1.f] \\ the first is unramified of degree 1 %5 = [1, 1] ? [p2.e, p2.f] \\ the second is unramified of degree 2 %6 = [1, 2] ? p1.gen %7 = [5, [2, 1, 0]~] ? nfbasistoalg(K, %[2]) \\ a uniformizer for p1 %8 = Mod(x + 2, x^3 - 2) ? #idealprimedec(K, 5, 1) \\ restrict to f = 1 %9 = 1 \\ now only p1 @eprog pari-2.17.2/src/functions/number_fields/nflist0000644000175000017500000003071314676526175020052 0ustar billbillFunction: nflist Section: number_fields C-Name: nflist Prototype: GDGD-1,L,DG Help: nflist(G,{N},{s=-1},{F}): finds number fields (up to isomorphism) with Galois group of Galois closure isomorphic to G, and s complex places. If s = -1 (default) all signatures, s = -2 is identical to s = -1 except fields are separated by increasing number of complex places. If field F is specified (by a polynomial), gives only number fields having F as a subfield (or a resolvent field in the case of S3, Dl, A4, S4, F5, M21 and M42). The parameter N can be the following: a positive integer (absolute value of discriminant is N); a vector [a,b] (finds fields with absolute discriminant between a and b); a polynomial, in variable t say (regular extension of Q(t) with specified Galois group). If omitted (default), returns a few fields and F is ignored. Doc: finds number fields (up to isomorphism) with Galois group of Galois closure isomorphic to $G$ with $s$ complex places. The number fields are given by polynomials. This function supports the following groups: \item degree $2$: $C_{2}=2T1$; \item degree $3$: $C_{3}=3T1$ and $S_{3}=3T2$; \item degree $4$: $C_{4}=4T1$, $V_{4}=4T2$, $D_{4}=4T3$, $A_{4}=4T4$ and $S_{4}=4T5$; \item degree $5$: $C_{5}=5T1$, $D_{5}=5T2$, $F_{5} = M_{{}20}=5T3$ and $A_{5}=5T4$; \item degree $6$: $C_{6}=6T1$, $S_{3}(6) = D_{6}(6)=6T2$, $D_{6}(12)=6T3$, $A_{4}(6)=6T4$, $S_{3}\times C_{3}=6T5$, $A_{4}(6)\times C_{2}=6T6$, $S_{4}(6)^{+}=6T7$, $S_{4}(6)^{-}=6T8$, $S_{3}^{2}=6T9$, $C_{3}^{2}:C_{4}=6T10$, $S_{4}(6)\times C_{2}=6T11$, $A_{5}(6)=PSL_{2}(5)=6T12$ and $C_{3}^{2}:D_{4}=6T13$; \item degree $7$: $C_{7}=7T1$, $D_{7}=7T2$, $M_{{}21}=7T3$ and $M_{{}42}=7T4$; \item degree $9$: $C_{9}=9T1$, $C_{3}\times C_{3}=9T2$ and $D_{9}=9T3$; \item degree $\ell$ with $\ell$ prime: $C_{\ell}=\ell T1$ and $D_{\ell}=\ell T2$. The groups $A_{5}$ and $A_{5}(6)$ require the optional package \kbd{nflistdata}. In addition, if $N$ is a polynomial, all transitive subgroups of $S_{n}$ with $n\le 15$, as well as alternating groups $A_{n}$ and the full symmetric group $S_{n}$ for all $n$ (see below for details and explanations). The groups are coded as $[n,k]$ using the \kbd{nTk} format where $n$ is the degree and $k$ is the $T$-number, the index in the classification of transitive subgroups of $S_{n}$. Alternatively, the groups $C_{n}$, $D_{n}$, $A_{n}$, $S_{n}$, $V_{4}$, $F_{5} = M_{20}$, $M_{21}$ and $M_{42}$ can be input as character strings exactly as written, lifting subscripts; for instance \kbd{"S4"} or \kbd{"M21"}. If the group is not recognized or is unsupported the function raises an exception. The number fields are computed on the fly (and not from a preexisting table) using a variety of algorithms, with the exception of $A_{5}$ and $A_{5}(6)$ which are obtained by table lookup. The algorithms are recursive and use the following ingredients: build distinguished subfields (or resolvent fields in Galois closures) of smaller degrees, use class field theory to build abelian extensions over a known base, select subfields using Galois theory. Because of our use of class field theory, and ultimately \kbd{bnfinit}, all results depend on the GRH in degree $n > 3$. To avoid wasting time, the output polynomials defining the number fields are usually not the simplest possible, use \kbd{polredbest} or \kbd{polredabs} to reduce them. The non-negative integer $s$ specifies the number of complex places, between $0$ and $n/2$. Additional supported values are: \item $s = -1$ (default) all signatures; \item $s = -2$ all signatures, given by increasing number of complex places; in degree $n$, this means a vector with $1 + \text{floor}(n/2)$ components: the $i$-th entry corresponds to $s = i - 1$. If the irreducible monic polynomial $F\in \Z[X]$ is specified, gives only number fields having $\Q[X]/(F)$ as a subfield, or in the case of $S_{3}$, $D_{\ell}$, $A_{4}$, $S_{4}$, $F_{5}$, $M_{21}$ and $M_{42}$, as a resolvent field (see also the function \kbd{nfresolvent} for these cases). The parameter $N$ can be the following: \item a positive integer: finds all fields with absolute discriminant $N$ (recall that the discriminant over $\Q$ is $(-1)^{s} N$). \item a pair of non-negative real numbers $[a,b]$ specifying a real interval: finds all fields with absolute value of discriminant between $a$ and $b$. For most Galois groups, this is faster than iterating on individual $N$. \item omitted (default): a few fields of small discriminant (not always those with smallest absolute discriminant) are output with given $G$ and $s$; usually about 10, less if too difficult to find. The parameter $F$ is ignored. \item a polynomial with main variable, say $t$, of priority lower than $x$. The program outputs a \emph{regular} polynomial in $\Q(t)[x]$ (in fact in $\Z[x,t]$) with the given Galois group. By Hilbert irreducibility, almost all specializations of $t$ will give suitable polynomials. The parameters $s$ and $F$ are ignored. This is implemented for all transitive subgroups of $S_{n}$ with $n\le15$ as well as for the alternating and symmetric groups $A_{n}$ and $S_{n}$ for all $n$. Polynomials for $A_{n}$ were inspired by J.-F.~Mestre, a few polynomials in degree $\leq 8$ come from G.~W.~Smith, ``Some polynomials over $\Q(t)$ and their Galois groups'', \emph{Math. Comp.}, {\bf 69} (230), 1999, pp.~775--796 most others in degree $\leq 11$ were provided by J.~Kl\"uners and G.~Malle (see G.~Malle and B.~H.~Matzat, \emph{Inverse Galois Theory}, Springer, 1999) and T.~Dokchitser completed the list up to degree~$15$. But for $A_{n}$ and $S_{n}$, subgroups of $S_{n}$ for $n > 7$ require the optional \kbd{nflistdata} package. \misctitle{Complexity} : For a positive integer $N$, the complexity is subexponential in $\log N$ (and involves factoring $N$). For an interval $[a,b]$, the complexity is roughly as follows, ignoring terms which are subexponential in $\log b$. It is usually linear in the output size. \item $C_{n}$: $O(b^{1/\phi(n)})$ for $n = 2, 4, 6, 9$ or any odd prime; \item $D_{n}$: $O(b^{2/\phi(n)})$ for $n = 4$ or any odd prime; \item $V_{4}$, $A_{4}$: $O(b^{1/2})$, $S_{4}$: $O(b)$; N.B. The subexponential terms are expensive for $A_{4}$ and $S_{4}$. \item $M_{20}$: $O(b)$. \item $S_{4}(6)^{-}$, $S_{4}(6)^{+}$ $A_{4}(6)\times C_{2}$, $S_{3}\times S_{3}$, $S_{4}(6)\times C_{2}$ : $O(b)$, $D_{6}(12)$, $A_{4}(6)$, $S_{3}(6)$, $S_{3}\times C_{3}$, $C_{3}^{2}:C_{4}$: $O(b^{1/2})$. \item $M_{21}$, $M_{42}$: $O(b)$. \item $C_{3}\times C_{3}$: $O(b^{1/3})$, $D_{9}$: $O(b^{5/12})$. \bprog ? #nflist("S3", [1, 10^5]) \\ S3 cubic fields %1 = 21794 ? #nflist("S3", [1, 10^5], 0) \\ real S3 cubic fields (0 complex place) %2 = 4753 ? #nflist("S3", [1, 10^5], 1) \\ complex cubic fields (1 complex place) %3 = 17041 ? v = nflist("S3", [1, 10^5], -2); apply(length,v) %4 = [4753, 17041] ? nflist("S4") \\ a few S4 fields %5 = [x^4 + 12*x^2 - 8*x + 16, x^4 - 2*x^2 - 8*x + 25, ...] ? nflist("S4",,0) \\ a few real S4 fields %6 = [x^4 - 52*x^2 - 56*x + 48, x^4 - 26*x^2 - 8*x + 1, ...] ? nflist("S4",,-2) \\ a few real S4 fields, by signature %7 = [[x^4 - 52*x^2 - 56*x + 48, ...], [x^4 - 8*x - 16, ... ], [x^4 + 138*x^2 - 8*x + 4541, ...]] ? nflist("S3",,,x^2+23) \\ a few cubic fields with resolvent Q(sqrt(-23)) %8 = [x^3 + x + 1, x^3 + 2*x + 1, ...] ? nflist("C3", 3969) \\ C3 fields of given discriminant %9 = [x^3 - 21*x + 28, x^3 - 21*x - 35] ? nflist([3,1], 3969) \\ C3 fields, using nTt label %10 = [x^3 - 21*x + 28, x^3 - 21*x - 35] ? P = nflist([8,12],t) \\ geometric 8T12 polynomial %11 = x^8 + (-t^2 - 803)*x^6 + (264*t^2 + 165528)*x^4 + (-2064*t^2 - 1724976)*x^2 + 4096*t^2 ? polgalois(subst(P, t, 11)) %12 = [24, 1, 12, "2A_4(8)=[2]A(4)=SL(2,3)"] ? nflist("S11") *** at top-level: nflist("S11") *** ^------------- *** nflist: unsupported group (S11). Use one of "C1"=[1,1]; "C2"=[2,1]; "C3"=[3,1], "S3"=[3,2]; "C4"=[4,1], "V4"=[4,2], "D4"=[4,3], "A4"=[4,4], "S4"=[4,5]; "C5"=[5,1], "D5"=[5,2], "F5"="M20"=[5,3], "A5"=[5,4]; "C6"=[6,1], "D6"=[6,2], [6,3], ..., [6,13]; "C7"=[7,1], "D7"=[7,2], "M21"=[7,3], "M42"=[7,4]; "C9"=[9,1], [9,2], "D9"=[9,3]." Also supported are "Cp"=[p,1] and "Dp"=[p,2] for any odd prime p. ? nflist("S25", 't) %13 = x^25 + x*t + 1 @eprog Function: _nflist_C3_worker Section: programming/internals C-Name: nflist_C3_worker Prototype: GG Help: nflist_C3_worker(gv,T): auxiliary. Doc: auxiliary Function: _nflist_C4vec_worker Section: programming/internals C-Name: nflist_C4vec_worker Prototype: GGGG Help: nflist_C4vec_worker(gm,X,Xinf,X2,gs): auxiliary. Doc: auxiliary Function: _nflist_V4_worker Section: programming/internals C-Name: nflist_V4_worker Prototype: GGGG Help: nflist_V4_worker(D1,X,Xinf,gs): auxiliary. Doc: auxiliary Function: _nflist_D4_worker Section: programming/internals C-Name: nflist_D4_worker Prototype: GGGG Help: nflist_D4_worker(D,X,Xinf,listarch): auxiliary. Doc: auxiliary Function: _nflist_A4S4_worker Section: programming/internals C-Name: nflist_A4S4_worker Prototype: GGGG Help: nflist_A4S4_worker(P3,X,Xinf,cardsprec): auxiliary. Doc: auxiliary Function: _nflist_C5_worker Section: programming/internals C-Name: nflist_C5_worker Prototype: GG Help: nflist_C5_worker(N,bnfC5): auxiliary. Doc: auxiliary Function: _nflist_CL_worker Section: programming/internals C-Name: nflist_CL_worker Prototype: GGG Help: nflist_CL_worker(Fcond,bnf,ellprec): auxiliary. Doc: auxiliary Function: _nflist_DL_worker Section: programming/internals C-Name: nflist_DL_worker Prototype: GGGGGG Help: nflist_DL_worker(P2,X1p,X0p,X,Xinf,ells): auxiliary. Doc: auxiliary Function: _nflist_Mgen_worker Section: programming/internals C-Name: nflist_Mgen_worker Prototype: GGGG Help: nflist_Mgen_worker(field,X,Xinf,ella): auxiliary. Doc: auxiliary Function: _nflist_C6_worker Section: programming/internals C-Name: nflist_C6_worker Prototype: GGGGG Help: nflist_C6_worker(P3,X,Xinf,M,T): auxiliary. Doc: auxiliary Function: _nflist_D612_worker Section: programming/internals C-Name: nflist_D612_worker Prototype: GGGG Help: nflist_D612_worker(P3,X,Xinf,X2,limd2s2): auxiliary. Doc: auxiliary Function: _nflist_A46S46P_worker Section: programming/internals C-Name: nflist_A46S46P_worker Prototype: GGGG Help: nflist_A46S46P_worker(P3,Xinf,sqX,cards): auxiliary. Doc: auxiliary Function: _nflist_S46M_worker Section: programming/internals C-Name: nflist_S46M_worker Prototype: GGGG Help: nflist_S46M_worker(P3,X,Xinf,sprec): auxiliary. Doc: auxiliary Function: _nflist_A462_worker Section: programming/internals C-Name: nflist_A462_worker Prototype: GGGGG Help: nflist_A462_worker(P3,X,Xinf,listarch,GAL): auxiliary. Doc: auxiliary Function: _nflist_S3C3_worker Section: programming/internals C-Name: nflist_S3C3_worker Prototype: GGG Help: nflist_S3C3_worker(D2,X,Xinf,X2): auxiliary. Doc: auxiliary Function: _nflist_S462_worker Section: programming/internals C-Name: nflist_S462_worker Prototype: GGGGG Help: nflist_S462_worker(P3,X,Xinf,listarch,GAL): auxiliary. Doc: auxiliary Function: _nflist_S36_worker Section: programming/internals C-Name: nflist_S36_worker Prototype: GGG Help: nflist_S36_worker(pol,X,Xinf,X2): auxiliary. Doc: auxiliary Function: _nflist_C32C4_worker Section: programming/internals C-Name: nflist_C32C4_worker Prototype: GGGG Help: nflist_C32C4_worker(P4,X,Xinf,GAL): auxiliary. Doc: auxiliary Function: _nflist_C32D4_worker Section: programming/internals C-Name: nflist_C32D4_worker Prototype: GGGG Help: nflist_C32D4_worker(P,X,Xinf,gs): auxiliary. Doc: auxiliary Function: _nflist_C9_worker Section: programming/internals C-Name: nflist_C9_worker Prototype: GGG Help: nflist_C9_worker(P,X,Xinf): auxiliary. Doc: auxiliary Function: _nflist_C3C3_worker Section: programming/internals C-Name: nflist_C3C3_worker Prototype: GGGG Help: nflist_C3C3_worker(gi,V3,V3D,X): auxiliary. Doc: auxiliary Function: _nflist_S3R_worker Section: programming/internals C-Name: nflist_S3R_worker Prototype: GG Help: nflist_S3R_worker(ga,ALLCTS): auxiliary. Doc: auxiliary Function: _nflist_S3I_worker Section: programming/internals C-Name: nflist_S3I_worker Prototype: GG Help: nflist_S3I_worker(ga,ALLCTS): auxiliary. Doc: auxiliary Function: _nflist_D9_worker Section: programming/internals C-Name: nflist_D9_worker Prototype: GGG Help: nflist_D9_worker(P2,X,Xinf): auxiliary. Doc: auxiliary Function: _nflist_S32_worker Section: programming/internals C-Name: nflist_S32_worker Prototype: GGGGG Help: nflist_S32_worker(all1,X,Xinf,V3,sprec): auxiliary. Doc: auxiliary pari-2.17.2/src/functions/number_fields/rnfdet0000644000175000017500000000035313637407207020020 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.17.2/src/functions/number_fields/rnfcharpoly0000644000175000017500000000110114557721031021051 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.17.2/src/functions/number_fields/gcharidentify0000644000175000017500000000502414676526175021370 0ustar billbillFunction: gcharidentify Section: number_fields C-Name: gchar_identify Prototype: GGGp Help: gcharidentify(gc,Lv,Lchiv): returns a Grossencharacter chi belonging to gc that approximately satisfies the constraints that chi_v is Lchiv[i] at the place v=Lv[i]. Doc: \var{gc} being a Grossencharacter group as output by \kbd{gcharinit}, $Lv$ being \typ{VEC} of places~$v$ encoded by a \typ{INT} (infinite place) or a prime ideal structure representing a prime not dividing the modulus of~$gc$ (finite place), and $Lchiv$ being a \typ{VEC} of local characters~$\chi_{v}$ encoded by~$[k,\varphi]$ with~$k$ a \typ{INT} and $\varphi$ a \typ{REAL} or \typ{COMPLEX} representing~$x\mapsto \text{sign}(x)^{k}|x|^{i\varphi}$ (real place) or~$z\mapsto (z/|z|)^{k}|z|^{2i\varphi}$(complex place) or by a \typ{REAL} or \typ{COMPLEX}~$\theta$ representing~$\goth{p} \mapsto \exp(2i\pi \theta)$ (finite place), returns a Grossencharacter~$\psi$ belonging to~$g$ such that~$\psi_{v} \approx \chi_{v}$ for all~$v$. At finite places, in place of a scalar one can provide a \typ{VEC} whose last component is $\theta$, as output by \kbd{gcharlocal}. To ensure proper identification, it is recommended to provide all infinite places together with a set of primes that generate the ray class group of modulus \var{gc}\kbd{.mod}. \bprog ? bnf = bnfinit(x^2-5,1); ? gc = gcharinit(bnf,1); ? chi = gcharidentify(gc,[2],[[0,13.]]); ? gcharlocal(gc,chi,2) % = [0, 13.057005210545987626926134713745179631] ? pr = idealprimedec(bnf,11)[1]; ? chi = gcharidentify(gc,[pr],[0.3]); ? gchareval(gc,chi,pr,0) % = 0.30000006229129706787363344444425752636 @eprog If you know only few digits, it may be a good idea to reduce the current precision to obtain a meaningful result. \bprog ? bnf = bnfinit(x^2-5,1); ? gc = gcharinit(bnf,1); ? pr = idealprimedec(bnf,11)[1]; ? chi = gcharidentify(gc,[pr],[0.184760]) % = [-420226]~ \\ @com unlikely to be meaningful ? gchareval(gc,chi,pr,0) % = 0.18475998070331376194260927294721168954 ? \p 10 realprecision = 19 significant digits (10 digits displayed) ? chi = gcharidentify(gc,[pr],[0.184760]) % = [-7]~ \\ @com probably what we were looking for ? gchareval(gc,chi,pr,0) % = 0.1847608033 ? \p 38 realprecision = 38 significant digits ? gchareval(gc,chi,pr,0) % = 0.18476080328172203337331245154966763237 @eprog The output may be a quasi-character. \bprog ? bnf = bnfinit(x^2-2,1); ? gc = gcharinit(bnf,1); gc.cyc % = [0, 0.E-57] ? gcharidentify(gc,[1,2],[[0,3.5+1/3*I],[0,-3.5+1/3*I]]) % = [-1, 1/3]~ @eprog pari-2.17.2/src/functions/sums/0000755000175000017500000000000014760315601014755 5ustar billbillpari-2.17.2/src/functions/sums/HEADER0000644000175000017500000001304714676526175015655 0ustar billbillFunction: _header_sums Class: header Section: sums Doc: \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} The ``double exponential'' (DE) univariate integration method is implemented in \tet{intnum} and its variants. Romberg integration is still available under the name \tet{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 noncompact, 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)$. Assume the bitprecision is $b$, so we try to achieve an absolute error less than $2^{-b}$. DE methods use $O(b \log b)$ function evaluations and should work for both compact and non-compact intervals as long as the integrand is the restriction of an analytic function to a suitable domain and its behaviour at infinity is correctly described. When integrating regular functions on a \emph{compact} interval, away from poles of the integrand, Gauss-Legendre integration (\tet{intnumgauss}) is the best choice, using $O(b)$ function evaluations. To integrate oscillating functions on non-compact interval, the slower but robust \tet{intnumosc} is available, performing Gaussian integration on intervals of length the half-period (or quasi-period) and using Sidi's $mW$ algorithm to extrapolate their sum. If poles are close to the integration interval, Gaussian integration may run into difficulties and it is then advisable to split the integral using \kbd{intnum} to get away from poles, then \kbd{intnumosc} for the remainder. For maximal efficiency, abscissas and integration weights can be precomputed, respectively using \tet{intnuminit} ($O(b^{2})$) or \tet{intnumgaussinit} ($O(b^{3})$). \misctitle{Numerical summation}\sidx{numerical summation} Many numerical summation methods are available to approximate $\sum_{n\geq n_{0}} f(n)$ at accuracy $2^{-b}$: the overall best choice should be \tet{sumnum}, which uses Euler-MacLaurin (and $O(b\log b)$ function evaluations); initialization time (\tet{sumnuminit}) is $O(b^{3})$. Also available are \item Abel-Plana summation (\tet{sumnumap}), also $O(b\log b)$ function evaluations and $O(b^{3})$ initialization (\tet{sumnumapinit}) with a larger implied constant; \item Lagrange summation (\tet{sumnumlagrange}) uses $O(b)$ evaluations but more brittle and the asymptotic behaviour of $f$ must be correctly indicated. Initialization (\tet{sumnumlagrangeinit}) can vary from $O(b^{2})$ to $O(b^{3})$ depending on the asymptotic behaviour. \item Sidi summation (\tet{sumnumsidi}) uses $O(b)$ evaluations and should be more robust than Lagrange summation. No initialization is needed. \item Monien summation (\tet{sumnummonien}) uses $O(b/\log b)$ evaluations but is even more brittle than Lagrange and also has a $O(b^{3})$ initialization (\kbd{summonieninit}). \item To sum rational functions, use \tet{sumnumrat}. All the function so far require $f$ to be be the restriction to integers of a regular function on the reals, and even on the complex numbers for Monien summation. The following algorithms allow functions defined only on the integers, under asumptions that are hard to verify. They are best used heuristically since they in fact are often valid when those asumptions do not hold, and for instance often yield a result for divergent series (e.g., Borel resummation). \item To sum alternating series, use \tet{sumalt}, which requires $O(b)$ function evaluations. \item To sum functions of a fixed sign, \tet{sumpos} uses van Wijngarten's trick to reduce to an alternating series, for a cost of $O(b\log b)$ function evaluations but beware that $f$ must be evaluated at large integers, of the order of $2^{b/\alpha}$ if we assume that $f(n) = O(1 / n^{\alpha+1})$ for some $\alpha > 0$. pari-2.17.2/src/functions/sums/suminf0000644000175000017500000000405414676526175016224 0ustar billbillFunction: suminf Section: sums C-Name: suminf0 Prototype: V=GEb Help: suminf(X=a,expr): naive summation (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: Naive summation of expression \var{expr}, the formal parameter $X$ going from $a$ to infinity. The evaluation stops when the relative error of the expression is less than the default bit precision for 3 consecutive evaluations. The expressions must evaluate to a complex number. If the expression tends slowly to $0$, like $n^{-a}$ for some $a > 1$, make sure $b = \kbd{realbitprecision}$ is low: indeed, the algorithm will require $O(2^{b/a})$ function evaluations and we expect only about $b(1-1/a)$ correct bits in the answer. If the series is alternating, we can expect $b$ correct bits but the \tet{sumalt} function should be used instead since its complexity is polynomial in $b$, instead of exponential. More generally, \kbd{sumpos} should be used if the terms have a constant sign and \kbd{sumnum} if the function is $C^{\infty}$. \bprog ? \pb25 realbitprecision = 25 significant bits (7 decimal digits displayed) ? exponent(suminf(i = 1, (-1)^i / i) + log(2)) time = 2min, 2,602 ms. %1 = -29 ? \pb45 realbitprecision = 45 significant bits (13 decimal digits displayed) ? exponent(suminf(i = 1, 1 / i^2) - zeta(2)) time = 2,186 ms. %2 = -23 \\ alternatives are much faster ? \pb 10000 realbitprecision = 10000 significant bits (3010 decimal digits displayed) ? exponent(sumalt(i = 1, (-1)^i / i) + log(2)) time = 25 ms. %3 = -10043 ? \pb 4000 realbitprecision = 4000 significant bits (1204 decimal digits displayed))) ? exponent(sumpos(i = 1, 1 / i^2) - zeta(2)) time = 22,593 ms. %4 = -4030 ? exponent(sumnum(i = 1, 1 / i^2) - zeta(2)) time = 7,032 ms. %5 = -4031 \\ but suminf is perfect for geometrically converging series ? exponent(suminf(i = 1, 2^-i) - 1) time = 25 ms. %6 = -4003 @eprog \synt{suminf}{void *E, GEN (*eval)(void*,GEN), GEN a, long prec}. pari-2.17.2/src/functions/sums/sumnumrat0000644000175000017500000000147614567450071016751 0ustar billbillFunction: sumnumrat Section: sums C-Name: sumnumrat Prototype: GGp Help: sumnumrat(F,a): sum from n = a to infinity of F(n), where F is a rational function of degree less than or equal to -2. Doc: $\sum_{n\geq a}F(n)$, where $F$ is a rational function of degree less than or equal to $-2$ and where poles of $F$ at integers $\geq a$ are omitted from the summation. The argument $a$ must be a \typ{INT} or \kbd{-oo}. \bprog ? sumnumrat(1/(x^2+1)^2,0) %1 = 1.3068369754229086939178621382829073480 ? sumnumrat(1/x^2, -oo) \\ value at x=0 is discarded %2 = 3.2898681336964528729448303332920503784 ? 2*zeta(2) %3 = 3.2898681336964528729448303332920503784 @eprog\noindent When $\deg F = -1$, we define $$\sum_{-\infty}^{\infty} F(n) := \sum_{n\geq 0} (F(n) + F(-1-n)):$$ \bprog ? sumnumrat(1/x, -oo) %4 = 0.E-38 @eprog pari-2.17.2/src/functions/sums/sumalt0000644000175000017500000000643314676526175016233 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} $(-1)^{k} a_{k}$, the formal variable $X$ starting at $a$. Use an algorithm of Cohen, Villegas and Zagier (\emph{Experiment. Math.} {\bf 9} (2000), no.~1, 3--12). If $\fl=0$, assuming that the $a_{k}$ are the moments of a positive measure on $[0,1]$, the relative error is $O(3+\sqrt8)^{-n}$ after using $a_{k}$ for $k\leq n$. If \kbd{realprecision} is $p$, we thus set $n = \log(10)p/\log(3+\sqrt8)\approx 1.3 p$; besides the time needed to compute the $a_{k}$, $k\leq n$, the algorithm overhead is negligible: time $O(p^{2})$ and space $O(p)$. If $\fl=1$, use a variant with more complicated polynomials, see \tet{polzagier}. If the $a_{k}$ are the moments of $w(x)dx$ where $w$ (or only $xw(x^{2})$) is a smooth function extending analytically to the whole complex plane, convergence is in $O(14.4^{-n})$. If $xw(x^{2})$ extends analytically to a smaller region, we still have exponential convergence, with worse constants. Usually faster when the computation of $a_{k}$ is expensive. If \kbd{realprecision} is $p$, we thus set $n = \log(10)p/\log(14.4)\approx 0.86 p$; besides the time needed to compute the $a_{k}$, $k\leq n$, the algorithm overhead is \emph{not} negligible: time $O(p^{3})$ and space $O(p^{2})$. Thus, even if the analytic conditions for rigorous use are met, this variant is only worthwile if the $a_{k}$ are hard to compute, at least $O(p^{2})$ individually on average: otherwise we gain a small constant factor (1.5, say) in the number of needed $a_{k}$ at the expense of a large overhead. The conditions for rigorous use are hard to check but the routine is best used heuristically: even divergent alternating series can sometimes be summed by this method, as well as series which are not exactly alternating (see for example \secref{se:user_defined}). It should be used to try and guess the value of an infinite sum. (However, see the example at the end of \secref{se:userfundef}.) If the series already converges geometrically, \tet{suminf} is often a better choice: \bprog ? \p38 ? sumalt(i = 1, -(-1)^i / i) - log(2) time = 0 ms. %1 = 0.E-38 ? suminf(i = 1, -(-1)^i / i) \\@com Had to hit \kbd{Ctrl-C} *** 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.17.2/src/functions/sums/asympnumraw0000644000175000017500000000377214676526175017314 0ustar billbillFunction: asympnumraw Section: sums C-Name: asympnumraw0 Prototype: GLDGp Help: asympnumraw(expr,N,{alpha = 1}): N+1 first terms of asymptotic expansion of expr as floating point numbers; alpha is as in limitnum. Doc: Return the $N+1$ first terms of asymptotic expansion of \var{expr}, corresponding to a sequence $u(n)$, as floating point numbers. Assume that the expansion has the shape $$u(n) \approx \sum_{i \geq 0} a_{i} n^{-i\alpha}$$ and return approximation of $[a_{0}, a_{1},\dots, a_{N}]$. The algorithm is heuristic and performs repeated calls to limitnum, with \kbd{alpha} as in \kbd{limitnum}. As in \kbd{limitnum}, $u(n)$ may be given either by a closure $n\mapsto u(n)$ or as a closure $N\mapsto [u(1),\dots,u(N)]$, the latter being often more efficient. This function is related to, but more flexible than, \kbd{asympnum}, which requires rational asymptotic expansions. \bprog ? f(n) = n! / (n^n*exp(-n)*sqrt(n)); ? asympnum(f) %2 = [] \\ failure ! ? v = asympnumraw(f, 10); ? v[1] - sqrt(2*Pi) %4 = 0.E-37 ? bestappr(v / v[1], 2^60) %5 = [1, 1/12, 1/288, -139/51840, -571/2488320, 163879/209018880,...] @eprog\noindent and we indeed get a few terms of Stirling's expansion (the first 9 terms are correct). If $u(n)$ has an asymptotic expansion in $n^{-\alpha}$ with $\alpha$ not an integer, the default $alpha=1$ is inaccurate: \bprog ? f(n) = (1+1/n^(7/2))^(n^(7/2)); ? v1 = asympnumraw(f,10); ? v1[1] - exp(1) %8 = 4.62... E-12 ? v2 = asympnumraw(f,10,7/2); ? v2[1] - exp(1) %7 0.E-37 @eprog\noindent As in \kbd{asympnum}, if \kbd{alpha} is not a rational number, loss of accuracy is expected, so it should be precomputed to double accuracy, say. \synt{asympnumraw}{void *E, GEN (*u)(void *,GEN,long), long N, GEN alpha, long prec}, where \kbd{u(E, n, prec)} must return either $u(n)$ or $[u(1),\dots,u(n)]$ in precision \kbd{prec}. Also available is \fun{GEN}{asympnumraw0}{GEN u, GEN alpha, long prec} where $u$ is either a closure as above or a vector of sufficient length. pari-2.17.2/src/functions/sums/sumnummonieninit0000644000175000017500000000621514676526175020342 0ustar billbillFunction: sumnummonieninit Section: sums C-Name: sumnummonieninit Prototype: DGDGDGp Help: sumnummonieninit({asymp},{w},{n0 = 1}): initialize tables for Monien summation of a series with positive terms. Doc: initialize tables for Monien summation of a series $\sum_{n\geq n_{0}} f(n)$ where $f(1/z)$ has a complex analytic continuation in a (complex) neighbourhood of the segment $[0,1]$. By default, assume that $f(n) = O(n^{-2})$ and has a nonzero asymptotic expansion $$f(n) = \sum_{i\geq 2} a_{i} / n^{i}$$ at infinity. Note that the sum starts at $i = 2$! The argument \kbd{asymp} allows to specify different expansions: \item a real number $\beta > 0$ means $$f(n) = \sum_{i\geq 1} a_{i} / n^{i + \beta}$$ (Now the summation starts at $1$.) \item a vector $[\alpha,\beta]$ of reals, where we must have $\alpha > 0$ and $\alpha + \beta > 1$ to ensure convergence, means that $$f(n) = \sum_{i\geq 1} a_{i} / n^{\alpha i + \beta}$$ Note that $\kbd{asymp} = [1, \beta]$ is equivalent to $\kbd{asymp}=\beta$. \bprog ? \p57 ? s = sumnum(n = 1, sin(1/sqrt(n)) / n); \\ reference point ? \p38 ? sumnummonien(n = 1, sin(1/sqrt(n)) / n) - s %2 = -0.001[...] \\ completely wrong ? t = sumnummonieninit(1/2); \\ f(n) = sum_i 1 / n^(i+1/2) ? sumnummonien(n = 1, sin(1/sqrt(n)) / n, t) - s %3 = 0.E-37 \\ now correct @eprog\noindent (As a matter of fact, in the above summation, the result given by \kbd{sumnum} at \kbd{\bs p38} is slighly incorrect, so we had to increase the accuracy to \kbd{\bs p57}.) The argument $w$ is used to sum expressions of the form $$ \sum_{n\geq n_{0}} f(n) w(n),$$ for varying $f$ \emph{as above}, and fixed weight function $w$, where we further assume that the auxiliary sums $$g_{w}(m) = \sum_{n\geq n_{0}} w(n) / n^{\alpha m + \beta} $$ converge for all $m\geq 1$. Note that for nonnegative integers $k$, and weight $w(n) = (\log n)^{k}$, the function $g_{w}(m) = \zeta^{(k)}(\alpha m + \beta)$ has a simple expression; for general weights, $g_{w}$ is computed using \kbd{sumnum}. The following variants are available \item an integer $k \geq 0$, to code $w(n) = (\log n)^{k}$; \item a \typ{CLOSURE} computing the values $w(n)$, where we assume that $w(n) = O(n^{\epsilon})$ for all $\epsilon > 0$; \item a vector $[w, \kbd{fast}]$, where $w$ is a closure as above and \kbd{fast} is a scalar; we assume that $w(n) = O(n^{\kbd{fast}+\epsilon})$; note that $\kbd{w} = [w, 0]$ is equivalent to $\kbd{w} = w$. Note that if $w$ decreases exponentially, \kbd{suminf} should be used instead. The subsequent calls to \kbd{sumnummonien} \emph{must} use the same value of $n_{0}$ as was used here. \bprog ? \p300 ? sumnummonien(n = 1, n^-2*log(n)) + zeta'(2) time = 328 ms. %1 = -1.323[...]E-6 \\ completely wrong, f does not satisfy hypotheses ! ? tab = sumnummonieninit(, 1); \\ codes w(n) = log(n) time = 3,993 ms. ? sumnummonien(n = 1, n^-2, tab) + zeta'(2) time = 41 ms. %3 = -5.562684646268003458 E-309 \\ now perfect ? tab = sumnummonieninit(, n->log(n)); \\ generic, slower time = 9,808 ms. ? sumnummonien(n = 1, n^-2, tab) + zeta'(2) time = 40 ms. %5 = -5.562684646268003458 E-309 \\ identical result @eprog pari-2.17.2/src/functions/sums/sumnuminit0000644000175000017500000000174714567450071017127 0ustar billbillFunction: sumnuminit Section: sums C-Name: sumnuminit Prototype: DGp Help: sumnuminit({asymp}): initialize tables for Euler-MacLaurin delta summation of a series with positive terms. Doc: initialize tables for Euler--MacLaurin delta summation of a series with positive terms. If given, \kbd{asymp} is of the form $[\kbd{+oo}, \alpha]$, as in \tet{intnum} and indicates the decrease rate at infinity of functions to be summed. A positive $\alpha > 0$ encodes an exponential decrease of type $\exp(-\alpha n)$ and a negative $-2 < \alpha < -1$ encodes a slow polynomial decrease of type $n^{\alpha}$. \bprog ? \p200 ? sumnum(n=1, n^-2); time = 200 ms. ? tab = sumnuminit(); time = 188 ms. ? sumnum(n=1, n^-2, tab); \\ faster time = 8 ms. ? tab = sumnuminit([+oo, log(2)]); \\ decrease like 2^-n time = 200 ms. ? sumnum(n=1, 2^-n, tab) time = 44 ms. ? tab = sumnuminit([+oo, -4/3]); \\ decrease like n^(-4/3) time = 200 ms. ? sumnum(n=1, n^(-4/3), tab); time = 221 ms. @eprog pari-2.17.2/src/functions/sums/intnuminit0000644000175000017500000000471714676526175017127 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],oo)} is equivalent to {\tt intnuminit([-1,-1/2], -oo)}; on the other hand, the order matters and {\tt intnuminit([0,-1/2], [1,-1/3])} is \emph{not} equivalent to {\tt intnuminit([0,-1/3], [1,-1/2])} ! If $m$ is present, it must be nonnegative and we multiply the default number of sampling points by $2^{m}$ (increasing the running time by a similar factor). The result is technical and liable to change in the future, but we document it here for completeness. Let $x=\phi(t)$, $t\in ]-\infty,\infty[$ be an internally chosen change of variable, achieving double exponential decrease of the integrand at infinity. The integrator \kbd{intnum} will compute $$ h \sum_{|n| < N} \phi'(nh) F(\phi(nh)) $$ for some integration step $h$ and truncation parameter $N$. In basic use, let \bprog [h, x0, w0, xp, wp, xm, wm] = intnuminit(a,b); @eprog \item $h$ is the integration step \item $x_{0} = \phi(0)$ and $w_{0} = \phi'(0)$, \item \var{xp} contains the $\phi(nh)$, $0 < n < N$, \item \var{xm} contains the $\phi(nh)$, $0 < -n < N$, or is empty. \item \var{wp} contains the $\phi'(nh)$, $0 < n < N$, \item \var{wm} contains the $\phi'(nh)$, $0 < -n < N$, or is empty. The arrays \var{xm} and \var{wm} are left empty when $\phi$ is an odd function. In complicated situations, \kbd{intnuminit} may return up to $3$ such arrays, corresponding to a splitting of up to $3$ integrals of basic type. If the functions to be integrated later are of the form $F = f(t) k(t,z)$ for some kernel $k$ (e.g. Fourier, Laplace, Mellin, \dots), it is useful to also precompute the values of $f(\phi(nh))$, which is accomplished by \tet{intfuncinit}. The hard part is to determine the behavior of $F$ at endpoints, depending on $z$. pari-2.17.2/src/functions/sums/sumeulerrat0000644000175000017500000000070114676526175017266 0ustar billbillFunction: sumeulerrat Section: sums C-Name: sumeulerrat Prototype: GDGD2,L,p Help: sumeulerrat(F,{s=1},{a=2}): sum from primes p = a to infinity of F(p^s), where F is a rational function. Doc: $\sum_{p\ge a}F(p^{s})$, where the sum is taken over prime numbers and $F$ is a rational function. \bprog ? sumeulerrat(1/p^2) %1 = 0.45224742004106549850654336483224793417 ? sumeulerrat(1/p, 2) %2 = 0.45224742004106549850654336483224793417 @eprog pari-2.17.2/src/functions/sums/sumdivmult0000644000175000017500000000105514567450071017120 0ustar billbillFunction: sumdivmult Section: sums C-Name: sumdivmultexpr0 Prototype: GVE Wrapper: (,,G) Description: (gen,,gen):gen sumdivmultexpr(${3 cookie}, ${3 wrapper}, $1) Help: sumdivmult(n,d,expr): sum of multiplicative function expr, d running over the divisors of n. Doc: sum of \emph{multiplicative} expression \var{expr} over the positive divisors $d$ of $n$. Assume that \var{expr} evaluates to $f(d)$ where $f$ is multiplicative: $f(1) = 1$ and $f(ab) = f(a)f(b)$ for coprime $a$ and $b$. \synt{sumdivmultexpr}{void *E, GEN (*eval)(void*,GEN), GEN d} pari-2.17.2/src/functions/sums/sumnumlagrange0000644000175000017500000000366414676526175017756 0ustar billbillFunction: sumnumlagrange Section: sums C-Name: sumnumlagrange0 Prototype: V=GEDGp Help: sumnumlagrange(n=a,f,{tab}): numerical summation of f(n) from n = a to +infinity using Lagrange summation. a must be an integer, and tab, if given, is the output of sumnumlagrangeinit. Wrapper: (,Gp) Description: (gen,gen,?gen):gen:prec sumnumlagrange(${2 cookie}, ${2 wrapper}, $1, $3, $prec) Doc: Numerical summation of $f(n)$ from $n=a$ to $+\infty$ using Lagrange summation; $a$ must be an integer, and the optional argument \kbd{tab} is the output of \kbd{sumnumlagrangeinit}. By default, the program assumes that the $N$th remainder has an asymptotic expansion in integral powers of $1/N$. If not, initialize \kbd{tab} using \kbd{sumnumlagrangeinit(al)}, where the asymptotic expansion of the remainder is integral powers of $1/N^{al}$; $al$ can be equal to $1$ (default), $1/2$, $1/3$, or $1/4$, and also equal to $2$, but in this latter case it is the $N$th remainder minus one half of the last summand which has an asymptotic expansion in integral powers of $1/N^{2}$. \bprog ? \p1000 ? z3 = zeta(3); ? sumpos(n = 1, n^-3) - z3 time = 4,440 ms. %2 = -2.08[...] E-1001 ? sumnumlagrange(n = 1, n^-3) - z3 \\ much faster than sumpos time = 25 ms. %3 = 0.E-1001 ? tab = sumnumlagrangeinit(); time = 21 ms. ? sumnumlagrange(n = 1, n^-3, tab) - z3 time = 2 ms. /* even faster */ %5 = 0.E-1001 ? \p115 ? tab = sumnumlagrangeinit([1/3,1/3]); time = 316 ms. ? sumnumlagrange(n = 1, n^-(7/3), tab) - zeta(7/3) time = 24 ms. %7 = 0.E-115 ? sumnumlagrange(n = 1, n^(-2/3) - 3*(n^(1/3)-(n-1)^(1/3)), tab) - zeta(2/3) time = 32 ms. %8 = 1.0151767349262596893 E-115 @eprog \misctitle{Complexity} The function $f$ is evaluated at $O(D)$ integer arguments, where $D \approx \kbd{realprecision} \cdot \log(10)$. \synt{sumnumlagrange}{(void *E, GEN (*eval)(void*, GEN), GEN a, GEN tab, long prec)} where an omitted \var{tab} is coded as \kbd{NULL}. pari-2.17.2/src/functions/sums/prodnumrat0000644000175000017500000000060614567450071017103 0ustar billbillFunction: prodnumrat Section: sums C-Name: prodnumrat Prototype: GLp Help: prodnumrat(F,a): product from n = a to infinity of F(n), where F-1 is a rational function of degree less than or equal to -2. Doc: $\prod_{n\ge a}F(n)$, where $F-1$ is a rational function of degree less than or equal to $-2$. \bprog ? prodnumrat(1+1/x^2,1) %1 = 3.6760779103749777206956974920282606665 @eprog pari-2.17.2/src/functions/sums/intnum0000644000175000017500000003360014676526175016234 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 +oo/-oo. Finally tab is either omitted (let the program choose the integration step), a nonnegative integer m (divide integration step by 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$, using the double-exponential method, and thus $O(D\log D)$ evaluation of the integrand in precision $D$. 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 \kbd{+oo} or \kbd{-oo}, as expected: \bprog ? intnum(x = 1,+oo, 1/x^2) %3 = 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: overflow in expo(). @eprog\noindent We shall see in a moment how to avoid that last problem, after describing the last \emph{optional} argument \var{tab}. \misctitle{The \var{tab} argument} The routine uses weights $w_{i}$, which are mostly independent of the function being integrated, evaluated at many sampling points $x_{i}$ and approximates the integral by $\sum w_{i} f(x_{i})$. If \var{tab} is \item a nonnegative integer $m$, we multiply the number of sampling points by $2^{m}$, hopefully increasing accuracy. Note that the running time increases roughly by a factor $2^{m}$. One may try consecutive values of $m$ until they give the same value up to an accepted error. \item a set of integration tables containing precomputed $x_{i}$ and $w_{i}$ as output by \tet{intnuminit}. This is useful if several integrations of the same type are performed (on the same kind of interval and functions, for a given accuracy): we skip a precomputation of $O(D\log D)$ elementary functions in accuracy $D$, whose running time has the same order of magnitude as the evaluation of the integrand. This is in particular useful for multivariate integrals. \misctitle{Specifying the behavior at endpoints} This is done as follows. An endpoint $a$ is either given as such (a scalar, real or complex, \kbd{oo} or \kbd{-oo} for $\pm\infty$), or as a two component vector $[a,\alpha]$, to indicate the behavior of the integrand in a neighborhood of $a$. If $a$ is finite, the code $[a,\alpha]$ means the function has a singularity of the form $(x-a)^{\alpha}$, up to logarithms. (If $\alpha \ge 0$, we only assume the function is regular, which is the default assumption.) If a wrong singularity exponent is used, the result will lose decimals: \bprog ? c = -9/10; ? intnum(x=0, 1, x^c) \\@com assume $x^{-9/10}$ is regular at 0 %1 = 9.9999839078827082322596783301939063944 ? intnum(x=[0,c], 1, x^c) \\@com no, it's not %2 = 10.000000000000000000000000000000000000 ? intnum(x=[0,c/2], 1, x^c) \\@com using a wrong exponent is bad %3 = 9.9999999997122749095442279375719919769 @eprog If $a$ is $\pm\infty$, which is coded as \kbd{+oo} or \kbd{-oo}, the situation is more complicated, and $[\pm\kbd{oo},\alpha]$ means: \item $\alpha=0$ (or no $\alpha$ at all, i.e. simply $\pm\kbd{oo}$) assumes that the integrand tends to zero moderately quickly, at least as $O(x^{-2})$ but not exponentially fast. \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 ? 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)) \\@com OK! %1 = 0.50000000000000000000000000000000000000 ? intnum(x=0, [+oo, 3], exp(-2*x)) \\@com imprecise exponent, still OK ! %2 = 0.50000000000000000000000000000000000000 ? intnum(x=0, [+oo, 10], exp(-2*x)) \\@com wrong exponent $\Rightarrow$ disaster %3 = 0.49999999999952372962457451698256707393 @eprog\noindent As the last exemple shows, the exponential decrease rate \emph{must} be indicated to avoid overflow, but the method is robust enough for a rough guess to be acceptable. \item $\alpha<-1$ assumes that the function tends to $0$ slowly, like $x^{\alpha}$. Here the algorithm is less robust and it is essential to give a sharp $\alpha$, unless $\alpha \le -2$ in which case we use the default algorithm as if $\alpha$ were missing (or equal to $0$). \bprog ? intnum(x=1, +oo, x^(-3/2)) \\ default %1 = 1.9999999999999999999999999999646391207 ? intnum(x=1, [+oo,-3/2], x^(-3/2)) \\ precise decrease rate %2 = 2.0000000000000000000000000000000000000 ? intnum(x=1, [+oo,-11/10], x^(-3/2)) \\ worse than default %3 = 2.0000000000000000000000000089298011973 @eprog \smallskip The last two codes are reserved for oscillating functions. Let $k > 0$ real, and $g(x)$ a nonoscillating 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)$. Note that the (slower) function \kbd{intnumosc} is more robust and should be able to integrate much more general quasi-periodic functions such as fractional parts or Bessel $J$ and $Y$ functions. \bprog ? \pb1664 ? exponent(intnum(x=0,+oo, sinc(x)) - Pi/2) time = 308 ms. %1 = 5 \\ junk ? exponent(intnum(x=0,[+oo,-I], sinc(x)) - Pi/2) time = 493 ms. %2 = -1663 \\ perfect when k is given ? exponent(intnum(x=0,[+oo,-0.999*I], sinc(x)) - Pi/2) time = 604 ms. %3 = -14 \\ junk when k is off \\ intnumosc requires the half-period ? exponent(intnumosc(x=0, sinc(x), Pi) - Pi/2) time = 20,570 ms. %4 = -1663 \\ slower but perfect ? exponent(intnumosc(x=0, sinc(x), Pi, 1) - Pi/2) time = 7,976 ms. %4 = -1663 \\ also perfect in fast unsafe mode ? exponent(intnumosc(x=0, sinc(x), Pi+0.001, 1) - Pi/2) time = 23,115 ms. %5 = -1278 \\ loses some accuracy when period is off, but much less @eprog \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 $[\pm\kbd{oo},\alpha]$ and $[\pm\kbd{oo},k* I]$, but a good rule of thumb is that if the oscillations are weaker than the exponential decrease, choose $[\pm\kbd{oo},\alpha]$, otherwise choose $[\pm\kbd{oo},k*I]$, although the latter can reasonably be used in all cases, while the former cannot. To take a specific example, in most inverse Mellin transforms, the integrand is 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{intfuncinit}. On the other hand using the exponential type of integral, we obtain less accurate results, but we skip expensive recomputations. See \kbd{intfuncinit} for more explanations. \misctitle{Power series limits} The limits $a$ and $b$ can be power series of nonnegative valuation, giving a power series expansion for the integral -- provided it exists. \bprog ? intnum(t=0,X + O(X^3), exp(t)) %4 = 1.000...*X - 0.5000...*X^2 + O(X^3) ? bestappr( intnum(t=0,X + O(X^17), exp(t)) )- exp(X) + 1 %5 = O(X^17) @eprog\noindent The valuation of the limit cannot be negative since $\int_{0}^{1/X}(1+t^{2})^{-1}\, dt = \pi/2 - \kbd{sign}(X)+O(X^{2})$. Polynomials and rational functions are also allowed and converted to power series using current \kbd{seriesprecision}: \bprog ? bestappr( intnum(t=1,1+X, 1/t) ) %6 = X - 1/2*X^2 + 1/3*X^3 - 1/4*X^4 + [...] + 1/15*X^15 + O(X^16) @eprog\noindent The function does not work if the integral is singular with the constant coefficient of the series as limit: \bprog ? intnum(t=X^2+O(X^4),1, 1/sqrt(t)) %8 = 2.000... - 6.236608109630992528 E28*X^2 + O(X^4) @eprog\noindent however you can use \bprog ? intnum(t=[X^2+O(X^4),-1/2],1, 1/sqrt(t)) %10 = 2.000000000000000000000000000-2.000000000000000000000000000*X^2+O(X^4) @eprog\noindent whis is translated internally to \bprog ? intnum(t=[0,-1/2],1, 1/sqrt(t))-intnum(t=[0,-1/2],X^2+O(X^4), 1/sqrt(t)) @eprog\noindent For this form the argument \var{tab} can be used only as an integer, not a table precomputed by \kbd{intnuminit}. \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 $115$ decimal digits. We first type \bprog ? \p 115 @eprog \misctitle{Apparent singularities} In many cases, apparent singularities can be ignored. 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 = 0.E-115 @eprog\noindent But close to $0$ the function $f$ is computed with an enormous loss of accuracy, and we are in fact lucky that it get multiplied by weights which are sufficiently close to $0$ to hide this: \bprog ? f(1e-200) %2 = -3.885337784451458142 E84 @eprog A more robust solution is to define the function differently near special points, e.g. by a Taylor expansion \bprog ? F = truncate( f(t + O(t^10)) ); \\@com expansion around t = 0 ? poldegree(F) %4 = 7 ? g(x) = if (x > 1e-18, f(x), subst(F,t,x)); \\@com note that $7 \cdot 18 > 105$ ? intnum(x = 0, [oo,1], g(x)) - Euler %2 = 0.E-115 @eprog\noindent It is up to the user to determine constants such as the $10^{-18}$ and $10$ used above. \misctitle{True singularities} With true singularities the result is worse. For instance \bprog ? intnum(x = 0, 1, x^(-1/2)) - 2 %1 = -3.5... E-68 \\@com only $68$ correct decimals ? intnum(x = [0,-1/2], 1, x^(-1/2)) - 2 %2 = 0.E-114 \\@com better @eprog \misctitle{Oscillating functions} \bprog ? intnum(x = 0, oo, sin(x) / x) - Pi/2 %1 = 16.19.. \\@com nonsense ? intnum(x = 0, [oo,1], sin(x)/x) - Pi/2 %2 = -0.006.. \\@com bad ? intnum(x = 0, [oo,-I], sin(x)/x) - Pi/2 %3 = 0.E-115 \\@com perfect ? intnum(x = 0, [oo,-I], sin(2*x)/x) - Pi/2 \\@com oops, wrong $k$ %4 = 0.06... ? intnum(x = 0, [oo,-2*I], sin(2*x)/x) - Pi/2 %5 = 0.E-115 \\@com perfect ? intnum(x = 0, [oo,-I], sin(x)^3/x) - Pi/4 %6 = -0.0008... \\@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 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.0003... \\@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 = 0.E-115 \\@com perfect ? intnum(x = 0, [oo, 1], sin(x)^3*exp(-x)) - 0.3 %3 = -7.34... E-55 \\@com bad ? intnum(x = 0, [oo,-I], sin(x)^3*exp(-x)) - 0.3 %4 = 8.9... E-103 \\@com better. Try higher $m$ ? tab = intnuminit(0,[oo,-I], 1); \\@com double number of sampling points ? intnum(x = 0, oo, sin(x)^3*exp(-x), tab) - 0.3 %6 = 0.E-115 \\@com perfect @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) - Pi/2 %2 = -7.1... E-115 \\@com OK @eprog\noindent The first \var{tab} is essential, the second optional. Compare: \bprog ? tab = intnuminit(-1,1); time = 4 ms. ? intnum(x=-1,1, intnum(y=-sqrt(1-x^2),sqrt(1-x^2), x^2+y^2)); time = 3,092 ms. \\@com slow ? intnum(x=-1,1, intnum(y=-sqrt(1-x^2),sqrt(1-x^2), x^2+y^2, tab), tab); time = 252 ms. \\@com faster ? intnum(x=-1,1, intnum(y=-sqrt(1-x^2),sqrt(1-x^2), x^2+y^2, tab)); time = 261 ms. \\@com the \emph{internal} integral matters most @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.17.2/src/functions/sums/prod0000644000175000017500000000263214676526175015667 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.17.2/src/functions/sums/sumnumap0000644000175000017500000001224114567450071016553 0ustar billbillFunction: sumnumap Section: sums C-Name: sumnumap0 Prototype: V=GEDGp Help: sumnumap(n=a,f,{tab}): numerical summation of f(n) from n = a to +infinity using Abel-Plana formula. Assume that f is holomorphic in the right half-plane Re(z) > a; a must be an integer, and tab, if given, is the output of sumnumapinit. Wrapper: (,G) Description: (gen,gen,?gen):gen:prec sumnumap(${2 cookie}, ${2 wrapper}, $1, $3, $prec) Doc: Numerical summation of $f(n)$ at high accuracy using Abel-Plana, the variable $n$ taking values from $a$ to $+\infty$, where $f$ is holomorphic in the right half-place $\Re(z) > a$; \kbd{a} must be an integer and \kbd{tab}, if given, is the output of \kbd{sumnumapinit}. The latter precomputes abscissas and weights, speeding up the computation; it also allows to specify the behavior at infinity via \kbd{sumnumapinit([+oo, asymp])}. \bprog ? \p500 ? z3 = zeta(3); ? sumpos(n = 1, n^-3) - z3 time = 2,332 ms. %2 = 2.438468843 E-501 ? sumnumap(n = 1, n^-3) - z3 \\ here slower than sumpos time = 2,565 ms. %3 = 0.E-500 @eprog \misctitle{Complexity} The function $f$ will be evaluated at $O(D \log D)$ real arguments and $O(D)$ complex arguments, where $D \approx \kbd{realprecision} \cdot \log(10)$. The routine is geared towards slowly decreasing functions: if $f$ decreases exponentially fast, then one of \kbd{suminf} or \kbd{sumpos} should be preferred. The default algorithm \kbd{sumnum} is usually a little \emph{slower} than \kbd{sumnumap} but its initialization function \kbd{sumnuminit} becomes much faster as \kbd{realprecision} increases. If $f$ satisfies the stronger hypotheses required for Monien summation, i.e. if $f(1/z)$ is holomorphic in a complex neighbourhood of $[0,1]$, then \tet{sumnummonien} will be faster since it only requires $O(D/\log D)$ evaluations: \bprog ? sumnummonien(n = 1, 1/n^3) - z3 time = 1,128 ms. %3 = 0.E-500 @eprog\noindent The \kbd{tab} argument precomputes technical data not depending on the expression being summed and valid for a given accuracy, speeding up immensely later calls: \bprog ? tab = sumnumapinit(); time = 2,567 ms. ? sumnumap(n = 1, 1/n^3, tab) - z3 \\ now much faster than sumpos time = 39 ms. %5 = 0.E-500 ? tabmon = sumnummonieninit(); \\ Monien summation allows precomputations too time = 1,125 ms. ? sumnummonien(n = 1, 1/n^3, tabmon) - z3 time = 2 ms. %7 = 0.E-500 @eprog\noindent The speedup due to precomputations becomes less impressive when the function $f$ is expensive to evaluate, though: \bprog ? sumnumap(n = 1, lngamma(1+1/n)/n, tab); time = 10,762 ms. ? sumnummonien(n = 1, lngamma(1+1/n)/n, tabmon); \\ fewer evaluations time = 205 ms. @eprog \misctitle{Behaviour at infinity} By default, \kbd{sumnumap} assumes that \var{expr} decreases slowly at infinity, but at least like $O(n^{-2})$. If the function decreases like $n^{\alpha}$ for some $-2 < \alpha < -1$, then it must be indicated via \bprog tab = sumnumapinit([+oo, alpha]); /* alpha < 0 slow decrease */ @eprog\noindent otherwise loss of accuracy is expected. If the functions decreases quickly, like $\exp(-\alpha n)$ for some $\alpha > 0$, then it must be indicated via \bprog tab = sumnumapinit([+oo, alpha]); /* alpha > 0 exponential decrease */ @eprog\noindent otherwise exponent overflow will occur. \bprog ? sumnumap(n=1,2^-n) *** at top-level: sumnumap(n=1,2^-n) *** ^---- *** _^_: overflow in expo(). ? tab = sumnumapinit([+oo,log(2)]); sumnumap(n=1,2^-n, tab) %1 = 1.000[...] @eprog As a shortcut, one can also input \bprog sumnumap(n = [a, asymp], f) @eprog\noindent instead of \bprog tab = sumnumapinit(asymp); sumnumap(n = a, f, tab) @eprog \misctitle{Further examples} \bprog ? \p200 ? sumnumap(n = 1, n^(-2)) - zeta(2) \\ accurate, fast time = 169 ms. %1 = -4.752728915737899559 E-212 ? sumpos(n = 1, n^(-2)) - zeta(2) \\ even faster time = 79 ms. %2 = 0.E-211 ? sumpos(n=1,n^(-4/3)) - zeta(4/3) \\ now much slower time = 10,518 ms. %3 = -9.980730723049589073 E-210 ? sumnumap(n=1,n^(-4/3)) - zeta(4/3) \\ fast but inaccurate time = 309 ms. %4 = -2.57[...]E-78 ? sumnumap(n=[1,-4/3],n^(-4/3)) - zeta(4/3) \\ decrease rate: now accurate time = 329 ms. %6 = -5.418110963941205497 E-210 ? tab = sumnumapinit([+oo,-4/3]); time = 160 ms. ? sumnumap(n=1, n^(-4/3), tab) - zeta(4/3) \\ faster with precomputations time = 175 ms. %5 = -5.418110963941205497 E-210 ? sumnumap(n=1,-log(n)*n^(-4/3), tab) - zeta'(4/3) time = 258 ms. %7 = 9.125239518216767153 E-210 @eprog Note that in the case of slow decrease ($\alpha < 0$), the exact decrease rate must be indicated, while in the case of exponential decrease, a rough value will do. In fact, for exponentially decreasing functions, \kbd{sumnumap} is given for completeness and comparison purposes only: one of \kbd{suminf} or \kbd{sumpos} should always be preferred. \bprog ? sumnumap(n=[1, 1], 2^-n) \\ pretend we decrease as exp(-n) time = 240 ms. %8 = 1.000[...] \\ perfect ? sumpos(n=1, 2^-n) %9 = 1.000[...] \\ perfect and instantaneous @eprog \synt{sumnumap}{(void *E, GEN (*eval)(void*,GEN), GEN a, GEN tab, long prec)} where an omitted \var{tab} is coded as \kbd{NULL}. pari-2.17.2/src/functions/sums/sumnummonien0000644000175000017500000000170114676526175017451 0ustar billbillFunction: sumnummonien Section: sums C-Name: sumnummonien0 Prototype: V=GEDGp Help: sumnummonien(n=a,f,{tab}): numerical summation from n = a to +infinity using Monien summation. Wrapper: (,G) Description: (gen,gen,?gen):gen:prec sumnummonien(${2 cookie}, ${2 wrapper}, $1, $3, $prec) Doc: numerical summation $\sum_{n\geq a} f(n)$ at high accuracy, the variable $n$ taking values from the integer $a$ to $+\infty$ using Monien summation, which assumes that $f(1/z)$ has a complex analytic continuation in a (complex) neighbourhood of the segment $[0,1]$. The function $f$ is evaluated at $O(D / \log D)$ real arguments, where $D \approx \kbd{realprecision} \cdot \log(10)$. By default, assume that $f(n) = O(n^{-2})$ and has a nonzero asymptotic expansion $$f(n) = \sum_{i\geq 2} a_{i} n^{-i}$$ at infinity. To handle more complicated behaviors and allow time-saving precomputations (for a given \kbd{realprecision}), see \kbd{sumnummonieninit}. pari-2.17.2/src/functions/sums/sumnumlagrangeinit0000644000175000017500000000446714676526175020644 0ustar billbillFunction: sumnumlagrangeinit Section: sums C-Name: sumnumlagrangeinit Prototype: DGDGp Help: sumnumlagrangeinit({asymp},{c1}): initialize tables for Lagrange summation of a series. Doc: initialize tables for Lagrange summation of a series. By default, assume that the remainder $R(n) = \sum_{m \geq n} f(m)$ has an asymptotic expansion $$R(n) = \sum_{m \geq n} f(n) \approx \sum_{i\geq 1} a_{i} / n^{i}$$ at infinity. The argument \kbd{asymp} allows to specify different expansions: \item a real number $\beta$ means $$ R(n) = n^{-\beta} \sum_{i\geq 1} a_{i} / n^{i} $$ \item a \typ{CLOSURE} $g$ means $$R(n) = g(n) \sum_{i\geq 1} a_{i} / n^{i}$$ (The preceding case corresponds to $g(n) = n^{-\beta}$.) \item a pair $[\alpha,\beta]$ where $\beta$ is as above and $\alpha\in \{2, 1, 1/2, 1/3, 1/4\}$. We let $R_{2}(n) = R(n) - f(n)/2$ and $R_{\alpha}(n) = R(n)$ for $\alpha\neq 2$. Then $$R_{\alpha}(n) = g(n) \sum_{i\geq 1} a_{i} / n^{i\alpha}$$ Note that the initialization times increase considerable for the $\alpha$ is this list ($1/4$ being the slowest). The constant $c1$ is technical and computed by the program, but can be set by the user: the number of interpolation steps will be chosen close to $c1\cdot B$, where $B$ is the bit accuracy. \bprog ? \p2000 ? sumnumlagrange(n=1, n^-2); time = 173 ms. ? tab = sumnumlagrangeinit(); time = 172 ms. ? sumnumlagrange(n=1, n^-2, tab); time = 4 ms. ? \p115 ? sumnumlagrange(n=1, n^(-4/3)) - zeta(4/3); %1 = -0.1093[...] \\ junk: expansion in n^(1/3) time = 84 ms. ? tab = sumnumlagrangeinit([1/3,0]); \\ alpha = 1/3 time = 336 ms. ? sumnumlagrange(n=1, n^(-4/3), tab) - zeta(4/3) time = 84 ms. %3 = 1.0151767349262596893 E-115 \\ now OK ? tab = sumnumlagrangeinit(1/3); \\ alpha = 1, beta = 1/3: much faster time = 3ms ? sumnumlagrange(n=1, n^(-4/3), tab) - zeta(4/3) \\ ... but wrong %5 = -0.273825[...] \\ junk ! ? tab = sumnumlagrangeinit(-2/3); \\ alpha = 1, beta = -2/3 time = 3ms ? sumnumlagrange(n=1, n^(-4/3), tab) - zeta(4/3) %6 = 2.030353469852519379 E-115 \\ now OK @eprog\noindent in The final example with $\zeta(4/3)$, the remainder $R_{1}(n)$ is of the form $n^{-1/3} \sum_{i\geq 0} a_{i} / n^{i}$, i.e. $n^{2/3} \sum_{i\geq 1} a_{i} / n^{i}$. The explains the wrong result for $\beta = 1/3$ and the correction with $\beta = -2/3$. pari-2.17.2/src/functions/sums/derivnum0000644000175000017500000000455714567450071016552 0ustar billbillFunction: derivnum Section: sums C-Name: derivnum0 Prototype: V=GEDGp Help: derivnum(X=a,expr,{ind=1}): numerical derivation of expr with respect to X at X = a. The order of derivation is given by parameter 'ind', which can be a vector. Wrapper: (,Gp) Description: (gen,gen):gen:prec derivnum(${2 cookie}, ${2 wrapper}, $1, $prec) (gen,gen,gen):gen:prec derivfunk(${2 cookie}, ${2 wrapper}, $1, $3, $prec) Doc: numerical derivation of \var{expr} with respect to $X$ at $X=a$. The order of derivation is 1 by default. \bprog ? derivnum(x=0, sin(exp(x))) - cos(1) %1 = 0.E-38 @eprog A clumsier approach, which would not work in library mode, is \bprog ? f(x) = sin(exp(x)) ? f'(0) - cos(1) %2 = 0.E-38 @eprog \item When $a$ is a numerical type (integer, rational number, real number or \typ{COMPLEX} of such), performs numerical derivation. \item When $a$ is a (polynomial, rational function or) power series, compute \kbd{derivnum(t=a,f)} as $f'(a) = (f(a))'/a'$: \bprog ? derivnum(x = 1 + t, sqrt(x)) %1 = 1/2 - 1/4*t + 3/16*t^2 - 5/32*t^3 + ... + O(t^16) ? derivnum(x = 1/(1 + t), sqrt(x)) %2 = 1/2 + 1/4*t - 1/16*t^2 + 1/32*t^3 + ... + O(t^16) ? derivnum(x = 1 + t + O(t^17), sqrt(x)) %3 = 1/2 - 1/4*t + 3/16*t^2 - 5/32*t^3 + ... + O(t^16) @eprog If the parameter \var{ind} is present, it can be \item a nonnegative integer $m$, in which case we return $f^{(m)}(x)$; \item or a vector of orders, in which case we return the vector of derivatives. \bprog ? derivnum(x = 0, exp(sin(x)), 16) \\ 16-th derivative %1 = -52635599.000000000000000000000000000000 ? round( derivnum(x = 0, exp(sin(x)), [0..13]) ) \\ 0-13-th derivatives %2 = [1, 1, 1, 0, -3, -8, -3, 56, 217, 64, -2951, -12672, 5973, 309376] @eprog \synt{derivfunk}{void *E, GEN (*eval)(void*,GEN), GEN a, GEN ind, long prec}. Also available is \fun{GEN}{derivfun}{void *E, GEN (*eval)(void *, GEN), GEN a, long prec}. If $a$ is a numerical type (\typ{INT}, \typ{FRAC}, \typ{REAL} or \typ{COMPLEX} of such, we have \fun{GEN}{derivnumk}{void *E, GEN (*eval)(void *, GEN, long), GEN a, GEN ind, long prec} and \fun{GEN}{derivnum}{void *E, GEN (*eval)(void *, GEN, long prec), GEN a, long prec} Function: _derivfun Section: programming/internals C-Name: derivfun0 Prototype: GGGD1,L,p Help: _derivfun(args,def,closure,k) numerical kth-derivation of closure with respect to the first variable at args pari-2.17.2/src/functions/sums/sum0000644000175000017500000000114414760123736015512 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 % \syn{NO} pari-2.17.2/src/functions/sums/sumpos0000644000175000017500000000565114676526175016255 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 uses Van Wijngaarden's trick for converting such a series into an alternating one, then \tet{sumalt}. For regular functions, the function \kbd{sumnum} is in general much faster once the initializations have been made using \kbd{sumnuminit}. Contrary to \kbd{sumnum}, \kbd{sumpos} allows functions defined only at integers: \bprog ? sumnum(n = 0, 1/n!) *** at top-level: sumnum(n=1,1/n!) *** ^--- *** incorrect type in gtos [integer expected] (t_FRAC). ? sumpos(n = 0, 1/n!) - exp(1) %2 = -1.0862155548773347717 E-33 @eprog\noindent On the other hand, when the function accepts general real numbers, it is usually advantageous to replace $n$ by \kbd{$n$ * 1.0} in the sumpos call in particular when rational functions are involved: \bprog ? \p500 ? sumpos(n = 0, n^7 / (n^9+n+1)); time = 6,108 ms. ? sumpos(n = 0, n *= 1.; n^7 / (n^9+n+1)); time = 2,788 ms. ? sumnumrat(n^7 / (n^9+n+1), 0); time = 4 ms. @eprog\noindent In the last example, \kbd{sumnumrat} is of course much faster but it only applies to rational functions. 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 \kbd{sumalt}$(,1)$ instead of \kbd{sumalt}$(,0)$, see \secref{se:sumalt}. Requiring more stringent analytic properties for rigorous use, but allowing to compute fewer series terms. To reach accuracy $10^{-p}$, both algorithms require $O(p^{2})$ space; furthermore, assuming the terms decrease polynomially (in $O(n^{-C})$), both need to compute $O(p^{2})$ terms. The \kbd{sumpos}$(,1)$ variant has a smaller implied constant (roughly 1.5 times smaller). Since the \kbd{sumalt}$(,1)$ overhead is now small compared to the time needed to compute series terms, this last variant should be about 1.5 faster. On the other hand, the achieved accuracy may be much worse: as for \tet{sumalt}, since conditions for rigorous use are hard to check, the routine is best used heuristically. \synt{sumpos}{void *E, GEN (*eval)(void*,GEN),GEN a,long prec}. Also available is \tet{sumpos2} with the same arguments ($\fl = 1$). pari-2.17.2/src/functions/sums/prodinf0000644000175000017500000000167614567450071016361 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,?0):gen:prec prodinf(${2 cookie}, ${2 wrapper}, $1, $prec) (gen,gen,1):gen:prec prodinf(${2 cookie}, ${2 wrapper}, $1, $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, divergent 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.17.2/src/functions/sums/laurentseries0000644000175000017500000000355314676526175017613 0ustar billbillFunction: laurentseries Section: sums C-Name: laurentseries0 Prototype: GDPDnp Help: laurentseries(f,{M=seriesprecision},{x='x}): expand f around 0 as a Laurent series in x to order M. Doc: Expand $f$ as a Laurent series around $x = 0$ to order $M$. This function computes $f(x + O(x^{n}))$ until $n$ is large enough: it must be possible to evaluate $f$ on a power series with $0$ constant term. \bprog ? laurentseries(t->sin(t)/(1-cos(t)), 5) %1 = 2*x^-1 - 1/6*x - 1/360*x^3 - 1/15120*x^5 + O(x^6) ? laurentseries(log) *** at top-level: laurentseries(log) *** ^------------------ *** in function laurentseries: log *** ^--- *** log: domain error in log: series valuation != 0 @eprog Note that individual Laurent coefficients of order $\leq M$ can be retrieved from $s = \kbd{laurentseries}(f,M)$ via \kbd{polcoef(s,i)} for any $i \leq M$. The series $s$ may occasionally be more precise that the required $O(x^{M+1})$. With respect to successive calls to \tet{derivnum}, \kbd{laurentseries} is both faster and more precise: \bprog ? laurentseries(t->log(3+t),1) %1 = 1.0986122886681096913952452369225257047 + 1/3*x - 1/18*x^2 + O(x^3) ? derivnum(t=0,log(3+t),1) %2 = 0.33333333333333333333333333333333333333 ? derivnum(t=0,log(3+t),2) %3 = -0.11111111111111111111111111111111111111 ? f = x->sin(exp(x)); ? polcoef(laurentseries(x->f(x+2), 1), 1) %5 = 3.3129294231043339804683687620360224365 ? exp(2) * cos(exp(2)); %6 = 3.3129294231043339804683687620360224365 ? derivnum(x = 2, f(x)) %7 = 3.3129294231043339804683687620360224364 \\ 1 ulp off ? default(realprecision,115); ? for(i=1,10^4, laurentseries(x->f(x+2),1)) time = 279 ms. ? for(i=1,10^4, derivnum(x=2,f(x))) \\ ... and slower time = 1,134 ms. @eprog \synt{laurentseries}{void *E, GEN (*f)(void*,GEN,long), long M, long v, long prec}. pari-2.17.2/src/functions/sums/prodeulerrat0000644000175000017500000000071414676526175017432 0ustar billbillFunction: prodeulerrat Section: sums C-Name: prodeulerrat Prototype: GDGD2,L,p Help: prodeulerrat(F,{s=1},{a=2}): product from primes p = a to infinity of F(p^s), where F is a rational function. Doc: $\prod_{p\ge a}F(p^{s})$, where the product is taken over prime numbers and $F$ is a rational function. \bprog ? prodeulerrat(1+1/q^3,1) %1 = 1.1815649490102569125693997341604542605 ? zeta(3)/zeta(6) %2 = 1.1815649490102569125693997341604542606 @eprog pari-2.17.2/src/functions/sums/intnumgauss0000644000175000017500000000265414567450071017272 0ustar billbillFunction: intnumgauss Section: sums C-Name: intnumgauss0 Prototype: V=GGEDGp Help: intnumgauss(X=a,b,expr,{tab}): numerical integration of expr from a to b, a compact interval, with respect to X using Gauss-Legendre quadrature. tab is either omitted (and will be recomputed) or precomputed with intnumgaussinit. Wrapper: (,,G) Description: (gen,gen,gen,?gen):gen:prec intnumgauss(${3 cookie}, ${3 wrapper}, $1, $2, $4, $prec) Doc: numerical integration of \var{expr} on the compact interval $[a,b]$ with respect to $X$ using Gauss-Legendre quadrature; \kbd{tab} is either omitted or precomputed with \kbd{intnumgaussinit}. As a convenience, it can be an integer $n$ in which case we call \kbd{intnumgaussinit}$(n)$ and use $n$-point quadrature. \bprog ? test(n, b = 1) = T=intnumgaussinit(n);\ intnumgauss(x=-b,b, 1/(1+x^2),T) - 2*atan(b); ? test(0) \\ default %1 = -9.490148553624725335 E-22 ? test(40) %2 = -6.186629001816965717 E-31 ? test(50) %3 = -1.1754943508222875080 E-38 ? test(50, 2) \\ double interval length %4 = -4.891779568527713636 E-21 ? test(90, 2) \\ n must almost be doubled as well! %5 = -9.403954806578300064 E-38 @eprog\noindent On the other hand, we recommend to split the integral and change variables rather than increasing $n$ too much: \bprog ? f(x) = 1/(1+x^2); ? b = 100; ? intnumgauss(x=0,1, f(x)) + intnumgauss(x=1,1/b, f(1/x)*(-1/x^2)) - atan(b) %3 = -1.0579449157400587572 E-37 @eprog pari-2.17.2/src/functions/sums/solve0000644000175000017500000000222414676526175016050 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 either a or b is infinite or 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$. If both $a$ and $b$ are finite, the condition is that $\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.) If only one between $a$ and $b$ is finite, say $a$, then $b=\pm\infty$. The routine will test all $b=a\pm 2^{r}$, with $r\geq \log_{2}(|a|)$ until it finds a bracket for the root which satisfies the abovementioned condition. If both $a$ and $b$ are infinite, the routine will test $0$ and all $\pm 2^{r}$, $r\geq 0$, until it finds a bracket for the root which satisfies the condition. 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.17.2/src/functions/sums/sumnumapinit0000644000175000017500000000204014567450071017433 0ustar billbillFunction: sumnumapinit Section: sums C-Name: sumnumapinit Prototype: DGp Help: sumnumapinit({asymp}): initialize tables for Abel-Plana summation of a series. Doc: initialize tables for Abel--Plana summation of a series $\sum f(n)$, where $f$ is holomorphic in a right half-plane. If given, \kbd{asymp} is of the form $[\kbd{+oo}, \alpha]$, as in \tet{intnum} and indicates the decrease rate at infinity of functions to be summed. A positive $\alpha > 0$ encodes an exponential decrease of type $\exp(-\alpha n)$ and a negative $-2 < \alpha < -1$ encodes a slow polynomial decrease of type $n^{\alpha}$. \bprog ? \p200 ? sumnumap(n=1, n^-2); time = 163 ms. ? tab = sumnumapinit(); time = 160 ms. ? sumnumap(n=1, n^-2, tab); \\ faster time = 7 ms. ? tab = sumnumapinit([+oo, log(2)]); \\ decrease like 2^-n time = 164 ms. ? sumnumap(n=1, 2^-n, tab) - 1 time = 36 ms. %5 = 3.0127431466707723218 E-282 ? tab = sumnumapinit([+oo, -4/3]); \\ decrease like n^(-4/3) time = 166 ms. ? sumnumap(n=1, n^(-4/3), tab); time = 181 ms. @eprog pari-2.17.2/src/functions/sums/intnumgaussinit0000644000175000017500000000377714676526175020177 0ustar billbillFunction: intnumgaussinit Section: sums C-Name: intnumgaussinit Prototype: D0,L,p Help: intnumgaussinit({n}): initialize tables for n-point Gauss-Legendre integration on a compact interval. Doc: initialize tables for $n$-point Gauss-Legendre integration of a smooth function $f$ on a compact interval $[a,b]$. If $n$ is omitted, make a default choice $n \approx B / 4$, where $B$ is \kbd{realbitprecision}, suitable for analytic functions on $[-1,1]$. The error is bounded by $$ \dfrac{(b-a)^{2n+1} (n!)^{4}}{(2n+1)!(2n)!} \dfrac{f^{(2n)}}{(2n)!} (\xi) , \qquad a < \xi < b. $$ If $r$ denotes the distance of the nearest pole to the interval $[a,b]$, then this is of the order of $((b-a) / (4r))^{2n}$. In particular, the integral must be subdivided if the interval length $b - a$ becomes close to $4r$. The default choice $n \approx B / 4$ makes this quantity of order $2^{-B}$ when $b - a = r$, as is the case when integrating $1/(1+t)$ on $[0,1]$ for instance. If the interval length increases, $n$ should be increased as well. Specifically, the function returns a pair of vectors $[x,w]$, where $x$ contains the nonnegative roots of the $n$-th Legendre polynomial $P_{n}$ and $w$ the corresponding Gaussian integration weights $Q_{n}(x_{j})/P'_{n}(x_{j}) = 2 / ((1-x_{j}^{2})P'_{n}(x_{j}))^{2}$ such that $$ \int_{-1}^{1} f(t)\, dt \approx \sum_{j} w_{j} f(x_{j})\;. $$ \bprog ? T = intnumgaussinit(); ? intnumgauss(t=-1,1,exp(t), T) - exp(1)+exp(-1) %1 = -5.877471754111437540 E-39 ? intnumgauss(t=-10,10,exp(t), T) - exp(10)+exp(-10) %2 = -8.358367809712546836 E-35 ? intnumgauss(t=-1,1,1/(1+t^2), T) - Pi/2 \\ b - a = 2r %3 = -9.490148553624725335 E-22 \\ ... loses half the accuracy ? T = intnumgaussinit(50); ? intnumgauss(t=-1,1,1/(1+t^2), T) - Pi/2 %5 = -1.1754943508222875080 E-38 ? intnumgauss(t=-5,5,1/(1+t^2), T) - 2*atan(5) %6 = -1.2[...]E-8 @eprog On the other hand, we recommend to split the integral and change variables rather than increasing $n$ too much, see \tet{intnumgauss}. pari-2.17.2/src/functions/sums/intnumosc0000644000175000017500000001575414676526175016753 0ustar billbillFunction: intnumosc Section: sums C-Name: intnumosc0 Prototype: V=GEGD0,L,DGp Help: intnumosc(x=a,expr,H,{flag=0},{tab}): numerical integration from a to oo of oscillating quasi-periodic function expr of half-period H. tab is either omitted (and will be recomputed) or precomputed with intnumgaussinit; flag is either 0 (Sidi extrapolation, safe mode), 1 (Sidi extrapolation, unsafe mode), 2 (sumalt), 3 (sumnumlagrange), 4 (sumpos). Doc: numerical integration from $a$ to $\infty$ of oscillating quasi-periodic function \var{expr} of half-period $H$, meaning that we at least expect the distance between the function's consecutive zeros to be close to $H$: the sine or cosine functions ($H = \pi$) are paradigmatic examples, but the Bessel $J_{\nu}$ or $Y_{\nu}$ functions ($H = \pi/2$) can also be handled. The integral from $a$ to $\infty$ is computed by summing the integral between two consecutive multiples of $H$; \fl determines the summation algorithm used: either $0$ (Sidi extrapolation, safe mode), 1 (Sidi extrapolation, unsafe mode), 2 (\kbd{sumalt}), 3 (\kbd{sumnumlagrange}) or 4 (\kbd{sumpos}). For the last two modes (Lagrange and Sumpos), one should input the period $2H$ instead of the half-period $H$. The default is $\fl = 0$; Sidi summation should be the most robust algorithm; you can try it in unsafe mode when the integrals between two consecutive multiples of $H$ form an alternating series, this should be about twice faster than the default and not lose accuracy. Sumpos should be by far the slowest method, but also very robust and may be able to handle integrals where Sidi fails. Sumalt should be fast but often wrong, especially when the integrals between two consecutive multiples of $H$ do not form an alternating series), and Lagrange should be as fast as Sumalt but more often wrong. When one of the Sidi modes runs into difficulties, it will return the result to the accuracy believed to be correct (the other modes do not perform extrapolation and do not have this property) : \bprog ? f(x)=besselj(0,x)^4*log(x+1); ? \pb384 ? intnumosc(x = 0, f(x), Pi) %1 = 0.4549032054850867417 \\ fewer digits than expected ! ? bitprecision(%) %2 = 64 ? \g1 \\ increase debug level to see diagnostics ? intnumosc(x = 0, f(x), Pi) sumsidi: reached accuracy of 23 bits. %2 = 0.4549032054850867417 @eprog\noindent The algorithm could extrapolate the series to 23 bits of accuracy, then diverged. So only the absolute error is likely to be around $2^{-23}$ instead of the possible $2^{-64}$ (or the requested $2^{-384}$). We'll come back to this example at the end. In case of difficulties, you may try to replace the half-(quasi)-period $H$ by a multiple, such as the quasi-period $2H$: since we do not expect alternating behaviour, \kbd{sumalt} mode will almost surely be broken, but others may improve, in particular Lagrange or Sumpos. \kbd{tab} is either omitted or precomputed with \kbd{intnumgaussinit}; if using Sidi summation in safe mode ($\fl = 0$) \emph{and} precompute \kbd{tab}, you should use a precision roughly 50\% larger than the target (this is not necessary for any of the other summations). First an alternating example: \bprog ? \pb384 \\ Sidi, safe mode ? exponent(intnumosc(x=0,sinc(x),Pi) - Pi/2) time = 183 ms. %1 = -383 ? exponent(intnumosc(x=0,sinc(x),2*Pi) - Pi/2) time = 224 ms. %2 = -383 \\ also works with 2H, a little slower \\ Sidi, unsafe mode ? exponent(intnumosc(x=0,sinc(x),Pi,1) - Pi/2) time = 79 ms. %3 = -383 \\ alternating: unsafe mode is fine and almost twice faster ? exponent(intnumosc(x=0,sinc(x),2*Pi,1) - Pi/2) time = 86 ms. %4 = -285 \\ but this time 2H loses accuracy \\ Sumalt ? exponent(intnumosc(x=0,sinc(x),Pi,2) - Pi/2) time = 115 ms. \\ sumalt is just as accurate and fast %5 = -383 ? exponent(intnumosc(x=0,sinc(x),2*Pi,2) - Pi/2) time = 115 ms. %6 = -10 \\ ...but breaks completely with 2H \\ Lagrange ? exponent(intnumosc(x=0,sinc(x),Pi,2) - Pi/2) time = 100 ms. \\ junk %7 = 224 ? exponent(intnumosc(x=0,sinc(x),2*Pi,2) - Pi/2) time = 100 ms. %8 = -238 \\ ...a little better with 2H \\ Sumpos ? exponent(intnumosc(x=0,sinc(x),Pi,4) - Pi/2) time = 17,961 ms. %9 = 7 \\ junk; slow ? exponent(intnumosc(x=0,sinc(x),2*Pi,4) - Pi/2) time = 19,105 ms. %10 = -4 \\ still junk @eprog Now a non-alternating one: \bprog ? exponent(intnumosc(x=0,sinc(x)^2,Pi) - Pi/2) time = 277 ms. %1 = -383 \\ safe mode is still perfect ? exponent(intnumosc(x=0,sinc(x)^2,Pi,1) - Pi/2) time = 97 ms. %2 = -284 \\ non-alternating; this time, Sidi's unsafe mode loses accuracy ? exponent(intnumosc(x=0,sinc(x)^2,Pi,2) - Pi/2) time = 113 ms. %3 = -10 \\ this time sumalt fails completely ? exponent(intnumosc(x=0,sinc(x)^2,Pi,3) - Pi/2) time = 103 ms. %4 = -237 \\ Lagrange loses accuracy (same with 2H = 2*Pi) ? exponent(intnumosc(x=0,sinc(x)^2,Pi,4) - Pi/2) time = 17,681 ms. %4 = -381 \\ and Sumpos is good but slow (perfect with 2H) @eprog Exemples of a different flavour: \bprog ? exponent(intnumosc(x = 0, besselj(0,x)*sin(3*x), Pi) - 1/sqrt(8)) time = 4,615 ms. %1 = -385 \\ more expensive but correct ? exponent(intnumosc(x = 0, besselj(0,x)*sin(3*x), Pi, 1) - 1/sqrt(8)) time = 1,424 ms. %2 = -279 \\ unsafe mode loses some accuracy (other modes return junk) ? S = log(2*Pi)- Euler - 1; ? exponent(intnumosc(t=1, (frac(t)/t)^2, 1/2) - S) time = 21 ms. %4 = -6 \\ junk ? exponent(intnumosc(t=1, (frac(t)/t)^2, 1) - S) time = 66ms. %5 = -384 \\ perfect with 2H ? exponent(intnumosc(t=1, (frac(t)/t)^2, 1, 1) - S) time = 20 ms. %6 = -286 \\ unsafe mode loses accuracy ? exponent(intnumosc(t=1, (frac(t)/t)^2, 1, 3) - S) time = 30 ms. %7 = -236 \\ and so does Lagrange (Sumalt fails) ? exponent(intnumosc(t=1, (frac(t)/t)^2, 1, 4) - S) time = 2,315 ms. %8 = -382 \\ Sumpos is perfect but slow @eprog\noindent Again, Sidi extrapolation behaves well, especially in safe mode, but $2H$ is required here. If the integrand has singularities close to the interval of integration, it is advisable to split the integral in two: use the more robust \kbd{intnum} to handle the singularities, then \kbd{intnumosc} for the remainder: \bprog ? \p38 ? f(x) = besselj(0,x)^3 * log(x); \\ mild singularity at 0 ? g() = intnumosc(x = 0, f(x), Pi); \\ direct ? h() = intnum(x = 0, Pi, f(x)) + intnumosc(x = Pi, f(x), Pi); \\ split at Pi ? G = g(); time = 293 ms. ? H = h(); time = 320 ms. \\ about as fast ? exponent(G-H) %6 = -12 \\ at least one of them is junk ? \p77 \\ increase accuracy ? G2=g(); H2=h(); ? exponent(G - G2) %8 = -13 \\ g() is not consistent ? exponent(H - H2) %9 = -128 \\ not a proof, but h() looks good @eprog\noindent Finally, here is an exemple where all methods fail, even when splitting the integral, except Sumpos: \bprog ? \p38 ? f(x)=besselj(0,x)^4*log(x+1); ? F = intnumosc(x=0,f(x), Pi, 4) time = 2,437 ms. %2 = 0.45489838778971732178155161172638343214 ? \p76 \\ double accuracy to check ? exponent(F - intnumosc(x = 0,f(x), Pi, 4)) time = 18,817 ms. %3 = -122 \\ F was almost perfect @eprog pari-2.17.2/src/functions/sums/contfracinit0000644000175000017500000000212014676526175017376 0ustar billbillFunction: contfracinit Section: sums C-Name: contfracinit Prototype: GD-1,L, Help: contfracinit(M,{lim = -1}): given M representing the power series S = sum_{n>=0} M[n+1]z^n, transform it into a continued fraction suitable for evaluation. Doc: Given $M$ representing the power series $S=\sum_{n\ge0} M[n+1]z^{n}$, transform it into a continued fraction in Euler form, using the quotient-difference algorithm; restrict to $n\leq \kbd{lim}$ if latter is nonnegative. $M$ can be a vector, a power series, a polynomial; if the limiting parameter \kbd{lim} is present, a rational function is also allowed (and converted to a power series of that accuracy). The result is a 2-component vector $[A,B]$ such that $S = M[1] / (1+A[1]z+B[1]z^{2}/(1+A[2]z+B[2]z^{2}/(1+\dots 1/(1+A[lim/2]z))))$. Does not work if any coefficient of $M$ vanishes, nor for series for which certain partial denominators vanish. Variant: Also available is \fun{GEN}{quodif}{GEN M, long n} which returns the standard continued fraction, as a vector $C$ such that $S = c[1] / (1 + c[2]z / (1+c[3]z/(1+\dots...c[lim]z)))$. pari-2.17.2/src/functions/sums/contfraceval0000644000175000017500000000103214567450071017351 0ustar billbillFunction: contfraceval Section: sums C-Name: contfraceval Prototype: GGD-1,L, Help: contfraceval(CF,t,{lim=-1}): given a continued fraction CF from contfracinit, evaluate the first lim terms of the continued fraction at t (all terms if lim is negative or omitted). Doc: Given a continued fraction \kbd{CF} output by \kbd{contfracinit}, evaluate the first \kbd{lim} terms of the continued fraction at \kbd{t} (all terms if \kbd{lim} is negative or omitted; if positive, \kbd{lim} must be less than or equal to the length of \kbd{CF}. pari-2.17.2/src/functions/sums/intcirc0000644000175000017500000000152514567450071016344 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 time = 496 ms. %1 = 1.2883911040127271720 E-101 + 0.E-118*I @eprog \synt{intcirc}{void *E, GEN (*eval)(void*,GEN), GEN a,GEN R,GEN tab, long prec}. pari-2.17.2/src/functions/sums/sumnum0000644000175000017500000001351014676526175016244 0ustar billbillFunction: sumnum Section: sums C-Name: sumnum0 Prototype: V=GEDGp Help: sumnum(n=a,f,{tab}): numerical summation of f(n) from n = a to +infinity using Euler-MacLaurin summation. Assume that f corresponds to a series with positive terms and is a C^oo function; a must be an integer, and tab, if given, is the output of sumnuminit. Wrapper: (,G) Description: (gen,gen,?gen):gen:prec sumnum(${2 cookie}, ${2 wrapper}, $1, $3, $prec) Doc: Numerical summation of $f(n)$ at high accuracy using Euler-MacLaurin, the variable $n$ taking values from $a$ to $+\infty$, where $f$ is assumed to have positive values and is a $C^{\infty}$ function; \kbd{a} must be an integer and \kbd{tab}, if given, is the output of \kbd{sumnuminit}. The latter precomputes abscissas and weights, speeding up the computation; it also allows to specify the behavior at infinity via \kbd{sumnuminit([+oo, asymp])}. \bprog ? \p500 ? z3 = zeta(3); ? sumpos(n = 1, n^-3) - z3 time = 2,332 ms. %2 = 2.438468843 E-501 ? sumnum(n = 1, n^-3) - z3 \\ here slower than sumpos time = 2,752 ms. %3 = 0.E-500 @eprog \misctitle{Complexity} The function $f$ will be evaluated at $O(D \log D)$ real arguments, where $D \approx \kbd{realprecision} \cdot \log(10)$. The routine is geared towards slowly decreasing functions: if $f$ decreases exponentially fast, then one of \kbd{suminf} or \kbd{sumpos} should be preferred. If $f$ satisfies the stronger hypotheses required for Monien summation, i.e. if $f(1/z)$ is holomorphic in a complex neighbourhood of $[0,1]$, then \tet{sumnummonien} will be faster since it only requires $O(D/\log D)$ evaluations: \bprog ? sumnummonien(n = 1, 1/n^3) - z3 time = 1,985 ms. %3 = 0.E-500 @eprog\noindent The \kbd{tab} argument precomputes technical data not depending on the expression being summed and valid for a given accuracy, speeding up immensely later calls: \bprog ? tab = sumnuminit(); time = 2,709 ms. ? sumnum(n = 1, 1/n^3, tab) - z3 \\ now much faster than sumpos time = 40 ms. %5 = 0.E-500 ? tabmon = sumnummonieninit(); \\ Monien summation allows precomputations too time = 1,781 ms. ? sumnummonien(n = 1, 1/n^3, tabmon) - z3 time = 2 ms. %7 = 0.E-500 @eprog\noindent The speedup due to precomputations becomes less impressive when the function $f$ is expensive to evaluate, though: \bprog ? sumnum(n = 1, lngamma(1+1/n)/n, tab); time = 14,180 ms. ? sumnummonien(n = 1, lngamma(1+1/n)/n, tabmon); \\ fewer evaluations time = 717 ms. @eprog \misctitle{Behaviour at infinity} By default, \kbd{sumnum} assumes that \var{expr} decreases slowly at infinity, but at least like $O(n^{-2})$. If the function decreases like $n^{\alpha}$ for some $-2 < \alpha < -1$, then it must be indicated via \bprog tab = sumnuminit([+oo, alpha]); /* alpha < 0 slow decrease */ @eprog\noindent otherwise loss of accuracy is expected. If the functions decreases quickly, like $\exp(-\alpha n)$ for some $\alpha > 0$, then it must be indicated via \bprog tab = sumnuminit([+oo, alpha]); /* alpha > 0 exponential decrease */ @eprog\noindent otherwise exponent overflow will occur. \bprog ? sumnum(n=1,2^-n) *** at top-level: sumnum(n=1,2^-n) *** ^---- *** _^_: overflow in expo(). ? tab = sumnuminit([+oo,log(2)]); sumnum(n=1,2^-n, tab) %1 = 1.000[...] @eprog As a shortcut, one can also input \bprog sumnum(n = [a, asymp], f) @eprog\noindent instead of \bprog tab = sumnuminit(asymp); sumnum(n = a, f, tab) @eprog \misctitle{Further examples} \bprog ? \p200 ? sumnum(n = 1, n^(-2)) - zeta(2) \\ accurate, fast time = 200 ms. %1 = -2.376364457868949779 E-212 ? sumpos(n = 1, n^(-2)) - zeta(2) \\ even faster time = 96 ms. %2 = 0.E-211 ? sumpos(n=1,n^(-4/3)) - zeta(4/3) \\ now much slower time = 13,045 ms. %3 = -9.980730723049589073 E-210 ? sumnum(n=1,n^(-4/3)) - zeta(4/3) \\ fast but inaccurate time = 365 ms. %4 = -9.85[...]E-85 ? sumnum(n=[1,-4/3],n^(-4/3)) - zeta(4/3) \\ with decrease rate, now accurate time = 416 ms. %5 = -4.134874156691972616 E-210 ? tab = sumnuminit([+oo,-4/3]); time = 196 ms. ? sumnum(n=1, n^(-4/3), tab) - zeta(4/3) \\ faster with precomputations time = 216 ms. %5 = -4.134874156691972616 E-210 ? sumnum(n=1,-log(n)*n^(-4/3), tab) - zeta'(4/3) time = 321 ms. %7 = 7.224147951921607329 E-210 @eprog Note that in the case of slow decrease ($\alpha < 0$), the exact decrease rate must be indicated, while in the case of exponential decrease, a rough value will do. In fact, for exponentially decreasing functions, \kbd{sumnum} is given for completeness and comparison purposes only: one of \kbd{suminf} or \kbd{sumpos} should always be preferred. \bprog ? sumnum(n=[1, 1], 2^-n) \\ pretend we decrease as exp(-n) time = 240 ms. %8 = 1.000[...] \\ perfect ? sumpos(n=1, 2^-n) %9 = 1.000[...] \\ perfect and instantaneous @eprog \misctitle{Beware cancellation} The function $f(n)$ is evaluated for huge values of $n$, so beware of cancellation in the evaluation: \bprog ? f(n) = 2 - 1/n - 2*n*log(1+1/n); \\ result is O(1/n^2) ? z = -2 + log(2*Pi) - Euler; ? sumnummonien(n=1, f(n)) - z time = 149 ms. %12 = 0.E-212 \\ perfect ? sumnum(n=1, f(n)) - z time = 116 ms. %13 = -948.216[...] \\ junk @eprog\noindent As \kbd{sumnum(n=1, print(n))} shows, we evaluate $f(n)$ for $n > 1e233$ and our implementation of $f$ suffers from massive cancellation since we are summing two terms of the order of $O(1)$ for a result in $O(1/n^{2})$. You can either rewrite your sum so that individual terms are evaluated without cancellation or locally replace $f(n)$ by an accurate asymptotic expansion: \bprog ? F = truncate( f(1/x + O(x^30)) ); ? sumnum(n=1, if(n > 1e7, subst(F,x,1/n), f(n))) - z %15 = 1.1 E-212 \\ now perfect @eprog \synt{sumnum}{(void *E, GEN (*eval)(void*, GEN), GEN a, GEN tab, long prec)} where an omitted \var{tab} is coded as \kbd{NULL}. pari-2.17.2/src/functions/sums/sumnumsidi0000644000175000017500000000264314567450071017110 0ustar billbillFunction: sumnumsidi Section: sums C-Name: sumnumsidi0 Prototype: V=GED1,L,p Help: sumnumsidi(n=a,f,{safe=1}): numerical summation of f(n) from n = a to +infinity using Sidi summation; a must be an integer. If safe is set to 0, the function is faster but much less robust. Wrapper: (,Gb) Description: (gen,gen,?long):gen:prec sumnumsidi(${2 cookie}, ${2 wrapper}, $1, $3, $prec) Doc: Numerical summation of $f(n)$ from $n=a$ to $+\infty$ using Sidi summation; $a$ must be an integer. The optional argument \kbd{safe} (set by default to $1$) can be set to $0$ for a faster but much less robust program; this is likely to lose accuracy when the sum is non-alternating. \bprog ? \pb3328 ? z = zeta(2); ? exponent(sumnumsidi(n = 1, 1/n^2) - z) time = 1,507 ms. %2 = -3261 \\ already loses some decimals ? exponent(sumnumsidi(n = 1, 1/n^2, 0) - z) time = 442 ms. \\ unsafe is much faster %3 = -2108 \\ ... but very wrong ? l2 = log(2); ? exponent(sumnumsidi(n = 1,(-1)^(n-1)/n) - z) time = 718 ms. %5 = -3328 \\ not so slow and perfect ? exponent(sumnumsidi(n = 1,(-1)^(n-1)/n, 0) - z) time = 504 ms. %5 = -3328 \\ still perfect in unsafe mode, not so much faster @eprog \misctitle{Complexity} If the bitprecision is $b$, we try to achieve an absolute error less than $2^{-b}$. The function $f$ is evaluated at $O(b)$ consecutive integer arguments at bit accuracy $1.56 b$ (resp.~$b$) in safe (resp.~unsafe) mode. pari-2.17.2/src/functions/sums/sumdiv0000644000175000017500000000067714760123736016227 0ustar billbillFunction: sumdiv Section: sums C-Name: sumdivexpr Prototype: GVE Help: sumdiv(n,X,expr): sum of expression expr, X running over the divisors of n. Doc: sum of expression \var{expr} over the positive divisors of $n$. This function is a trivial wrapper essentially equivalent to \bprog D = divisors(n); sum (i = 1, #D, my(X = D[i]); eval(expr)) @eprog\noindent If \var{expr} is a multiplicative function, use \tet{sumdivmult}. %\syn{NO} pari-2.17.2/src/functions/sums/asympnum0000644000175000017500000000632014676526175016572 0ustar billbillFunction: asympnum Section: sums C-Name: asympnum0 Prototype: GDGp Help: asympnum(expr,{alpha = 1}): asymptotic expansion of expr assuming it has rational coefficients with reasonable height; alpha is as in limitnum. Doc: Asymptotic expansion of \var{expr}, corresponding to a sequence $u(n)$, assuming it has the shape $$u(n) \approx \sum_{i \geq 0} a_{i} n^{-i\alpha}$$ with rational coefficients $a_{i}$ with reasonable height; the algorithm is heuristic and performs repeated calls to limitnum, with \kbd{alpha} as in \kbd{limitnum}. As in \kbd{limitnum}, $u(n)$ may be given either by a closure $n\mapsto u(n)$ or as a closure $N\mapsto [u(1),\dots,u(N)]$, the latter being often more efficient. \bprog ? f(n) = n! / (n^n*exp(-n)*sqrt(n)); ? asympnum(f) %2 = [] \\ failure ! ? localprec(57); l = limitnum(f) %3 = 2.5066282746310005024157652848110452530 ? asympnum(n->f(n)/l) \\ normalize %4 = [1, 1/12, 1/288, -139/51840, -571/2488320, 163879/209018880, 5246819/75246796800] @eprog\noindent and we indeed get a few terms of Stirling's expansion. Note that it definitely helps to normalize with a limit computed to higher accuracy (as a rule of thumb, multiply the bit accuracy by $1.612$): \bprog ? l = limitnum(f) ? asympnum(n->f(n) / l) \\ failure again !!! %6 = [] @eprog\noindent We treat again the example of the Motzkin numbers $M_{n}$ given in \kbd{limitnum}: \bprog \\ [M_k, M_{k*2}, ..., M_{k*N}] / (3^n / n^(3/2)) ? vM(N, k = 1) = { my(q = k*N, V); if (q == 1, return ([1/3])); V = vector(q); V[1] = V[2] = 1; for(n = 2, q - 1, V[n+1] = ((2*n + 1)*V[n] + 3*(n - 1)*V[n-1]) / (n + 2)); f = (n -> 3^n / n^(3/2)); return (vector(N, n, V[n*k] / f(n*k))); } ? localprec(100); l = limitnum(n->vM(n,10)); \\ 3/sqrt(12*Pi) ? \p38 ? asympnum(n->vM(n,10)/l) %2 = [1, -3/32, 101/10240, -1617/1638400, 505659/5242880000, ...] @eprog If \kbd{alpha} is not a rational number, loss of accuracy is expected, so it should be precomputed to double accuracy, say: \bprog ? \p38 ? asympnum(n->log(1+1/n^Pi),Pi) %1 = [0, 1, -1/2, 1/3, -1/4, 1/5] ? localprec(76); a = Pi; ? asympnum(n->log(1+1/n^Pi), a) \\ more terms %3 = [0, 1, -1/2, 1/3, -1/4, 1/5, -1/6, 1/7, -1/8, 1/9, -1/10, 1/11, -1/12] ? asympnum(n->log(1+1/sqrt(n)),1/2) \\ many more terms %4 = 49 @eprog The expression is evaluated for $n = 1, 2, \dots, N$ for an $N = O(B)$ if the current bit accuracy is $B$. If it is not defined for one of these values, translate or rescale accordingly: \bprog ? asympnum(n->log(1-1/n)) \\ can't evaluate at n = 1 ! *** at top-level: asympnum(n->log(1-1/n)) *** ^----------------------- *** in function asympnum: log(1-1/n) *** ^---------- *** log: domain error in log: argument = 0 ? asympnum(n->-log(1-1/(2*n))) %5 = [0, 1/2, 1/8, 1/24, ...] ? asympnum(n->-log(1-1/(n+1))) %6 = [0, 1, -1/2, 1/3, -1/4, ...] @eprog\noindent \synt{asympnum}{void *E, GEN (*u)(void *,GEN,long), GEN alpha, long prec}, where \kbd{u(E, n, prec)} must return either $u(n)$ or $[u(1),\dots,u(n)]$ in precision \kbd{prec}. Also available is \fun{GEN}{asympnum0}{GEN u, GEN alpha, long prec}, where $u$ is a closure as above or a vector of sufficient length. pari-2.17.2/src/functions/sums/prodeuler0000644000175000017500000000221314676526175016717 0ustar billbillFunction: prodeuler Section: sums C-Name: prodeuler0 Prototype: V=GGEp Help: prodeuler(p=a,b,expr): Euler product (p runs over the primes between a and b) of real or complex expression, as a floating point approximation. Doc: product of expression \var{expr}, initialized at \kbd{1.0} (i.e.~to a floating point number equal to 1 to the current \kbd{realprecision}), the formal parameter $p$ ranging over the prime numbers between $a$ and $b$.\sidx{Euler product} \bprog ? prodeuler(p = 2, 10^4, 1 - p^-2) %1 = 0.60793306911405513018380499671124428015 ? P = 1; forprime(p = 2, 10^4, P *= (1 - p^-2)) ? exponent(numerator(P)) %3 = 22953 @eprog\noindent The function returns a floating point number because, as the second expression shows, such products are usually intractably large rational numbers when computed symbolically. If the expression is a rational function, \kbd{prodeulerrat} computes the product over all primes: \bprog ? prodeulerrat(1 - p^-2) %4 = 0.60792710185402662866327677925836583343 ? 6/Pi^2 %3 = 0.60792710185402662866327677925836583343 @eprog \synt{prodeuler}{void *E, GEN (*eval)(void*,GEN), GEN a,GEN b, long prec}. pari-2.17.2/src/functions/sums/intfuncinit0000644000175000017500000000645614676526175017265 0ustar billbillFunction: intfuncinit Section: sums C-Name: intfuncinit0 Prototype: V=GGED0,L,p Help: intfuncinit(t=a,b,f,{m=0}): initialize tables for integrations from a to b using a weight f(t). For integral transforms such as Fourier or Mellin transforms. Wrapper: (,,G) Description: (gen,gen,gen,?small):gen:prec intfuncinit(${3 cookie}, ${3 wrapper}, $1, $2, $4, $prec) Doc: initialize tables for use with integral transforms (such as Fourier, Laplace or Mellin transforms) in order to compute $$ \int_{a}^{b} f(t) k(t,z) \, dt $$ for some kernel $k(t,z)$. The endpoints $a$ and $b$ are coded as in \kbd{intnum}, $f$ is the function to which the integral transform is to be applied and the nonnegative integer $m$ is as in \kbd{intnum}: multiply the number of sampling points roughly by $2^{m}$, hopefully increasing the accuracy. This function is particularly useful when the function $f$ is hard to compute, such as a gamma product. \misctitle{Limitation} The endpoints $a$ and $b$ must be at infinity, with the same asymptotic behavior. Oscillating types are not supported. This is easily overcome by integrating vectors of functions, see example below. \misctitle{Examples} \item numerical Fourier transform $$F(z) = \int_{-\infty}^{+\infty} f(t)e^{-2i\pi z t}\, dt. $$ First the easy case, assume that $f$ decrease exponentially: \bprog f(t) = exp(-t^2); A = [-oo,1]; B = [+oo,1]; \p200 T = intfuncinit(t = A,B , f(t)); F(z) = { my(a = -2*I*Pi*z); intnum(t = A,B, exp(a*t), T); } ? F(1) - sqrt(Pi)*exp(-Pi^2) %1 = -1.3... E-212 @eprog\noindent Now the harder case, $f$ decrease slowly: we must specify the oscillating behavior. Thus, we cannot precompute usefully since everything depends on the point we evaluate at: \bprog f(t) = 1 / (1+ abs(t)); \p200 \\ Fourier cosine transform FC(z) = { my(a = 2*Pi*z); intnum(t = [-oo, a*I], [+oo, a*I], cos(a*t)*f(t)); } FC(1) @eprog \item Fourier coefficients: we must integrate over a period, but \kbd{intfuncinit} does not support finite endpoints. The solution is to integrate a vector of functions ! \bprog FourierSin(f, T, k) = \\ first k sine Fourier coeffs { my (w = 2*Pi/T); my (v = vector(k+1)); intnum(t = -T/2, T/2, my (z = exp(I*w*t)); v[1] = z; for (j = 2, k, v[j] = v[j-1]*z); f(t) * imag(v)) * 2/T; } FourierSin(t->sin(2*t), 2*Pi, 10) @eprog\noindent The same technique can be used instead of \kbd{intfuncinit} to integrate $f(t) k(t,z)$ whenever the list of $z$-values is known beforehand. Note that the above code includes an unrelated optimization: the $\sin(j w t)$ are computed as imaginary parts of $\exp(i j w t)$ and the latter by successive multiplications. \item numerical Mellin inversion $$F(z) = (2i\pi)^{-1} \int_{c -i\infty}^{c+i\infty} f(s)z^{-s}\, ds = (2\pi)^{-1} \int_{-\infty}^{+\infty} f(c + i t)e^{-\log z(c + it)}\, dt. $$ We take $c = 2$ in the program below: \bprog f(s) = gamma(s)^3; \\ f(c+it) decrease as exp(-3Pi|t|/2) c = 2; \\ arbitrary A = [-oo,3*Pi/2]; B = [+oo,3*Pi/2]; T = intfuncinit(t=A,B, f(c + I*t)); F(z) = { my (a = -log(z)); intnum(t=A,B, exp(a*I*t), T)*exp(a*c) / (2*Pi); } @eprog \synt{intfuncinit}{void *E, GEN (*eval)(void*,GEN), GEN a,GEN b,long m, long prec}. pari-2.17.2/src/functions/sums/limitnum0000644000175000017500000001477314676526175016572 0ustar billbillFunction: limitnum Section: sums C-Name: limitnum0 Prototype: GDGp Help: limitnum(expr,{alpha=1}): numerical limit of sequence expr using Lagrange-Zagier extrapolation; assume u(n) ~ sum a_i n^(-alpha*i). Doc: Lagrange-Zagier numerical extrapolation of \var{expr}, corresponding to a sequence $u_{n}$, either given by a closure \kbd{n->u(n)}. I.e., assuming that $u_{n}$ tends to a finite limit $\ell$, try to determine $\ell$. The routine assume that $u_{n}$ has an asymptotic expansion in $n^{-\alpha}$ : $$u_{n} = \ell + \sum_{i\geq 1} a_{i} n^{-i\alpha}$$ for some $a_{i}$. It is purely numerical and heuristic, thus may or may not work on your examples. The expression will be evaluated for $n = 1, 2, \dots, N$ for an $N = O(B)$ at a bit accuracy bounded by $1.612 B$. \bprog ? limitnum(n -> n*sin(1/n)) %1 = 1.0000000000000000000000000000000000000 ? limitnum(n -> (1+1/n)^n) - exp(1) %2 = 0.E-37 ? limitnum(n -> 2^(4*n+1)*(n!)^4 / (2*n)! /(2*n+1)! ) - Pi %3 = 0.E -37 @eprog\noindent It is not mandatory to specify $\alpha$ when the $u_{n}$ have an asymptotic expansion in $n^{-1}$. However, if the series in $n^{-1}$ is lacunary, specifying $\alpha$ allows faster computation: \bprog ? \p1000 ? limitnum(n->(1+1/n^2)^(n^2)) - exp(1) time = 1min, 44,681 ms. %4 = 0.E-1001 ? limitnum(n->(1+1/n^2)^(n^2), 2) - exp(1) time = 27,271 ms. %5 = 0.E-1001 \\ still perfect, 4 times faster @eprog\noindent When $u_{n}$ has an asymptotic expansion in $n^{-\alpha}$ with $\alpha$ not an integer, leaving $\alpha$ unspecified will bring an inexact limit. Giving a satisfying optional argument improves precision; the program runs faster when the optional argument gives non lacunary series. \bprog ? \p50 ? limitnum(n->(1+1/n^(7/2))^(n^(7/2))) - exp(1) time = 982 ms. %6 = 4.13[...] E-12 ? limitnum(n->(1+1/n^(7/2))^(n^(7/2)), 1/2) - exp(1) time = 16,745 ms. %7 = 0.E-57 ? limitnum(n->(1+1/n^(7/2))^(n^(7/2)), 7/2) - exp(1) time = 105 ms. %8 = 0.E-57 @eprog\noindent Alternatively, $u_{n}$ may be given by a closure $N\mapsto [u_{1},\dots, u_{N}]$ which can often be programmed in a more efficient way, for instance when $u_{n+1}$ is a simple function of the preceding terms: \bprog ? \p2000 ? limitnum(n -> 2^(4*n+1)*(n!)^4 / (2*n)! /(2*n+1)! ) - Pi time = 1,755 ms. %9 = 0.E-2003 ? vu(N) = \\ exploit hypergeometric property { my(v = vector(N)); v[1] = 8./3;\ for (n=2, N, my(q = 4*n^2); v[n] = v[n-1]*q/(q-1));\ return(v); } ? limitnum(vu) - Pi \\ much faster time = 106 ms. %11 = 0.E-2003 @eprog\noindent All sums and recursions can be handled in the same way. In the above it is essential that $u_{n}$ be defined as a closure because it must be evaluated at a higher precision than the one expected for the limit. Make sure that the closure does not depend on a global variable which would be computed at a priori fixed accuracy. For instance, precomputing \kbd{v1 = 8.0/3} first and using \kbd{v1} in \kbd{vu} above would be wrong because the resulting vector of values will use the accuracy of \kbd{v1} instead of the ambient accuracy at which \kbd{limitnum} will call it. Alternatively, and more clumsily, $u_{n}$ may be given by a vector of values: it must be long and precise enough for the extrapolation to make sense. Let $B$ be the current \kbd{realbitprecision}, the vector length must be at least $1.102 B$ and the values computed with bit accuracy $1.612 B$. \bprog ? limitnum(vector(10,n,(1+1/n)^n)) *** ^-------------------- *** limitnum: nonexistent component in limitnum: index < 43 \\ at this accuracy, we must have at least 43 values ? limitnum(vector(43,n,(1+1/n)^n)) - exp(1) %12 = 0.E-37 ? v = vector(43); ? s = 0; for(i=1,#v, s += 1/i; v[i]= s - log(i)); ? limitnum(v) - Euler %15 = -1.57[...] E-16 ? v = vector(43); \\ ~ 128 bit * 1.612 ? localbitprec(207);\ s = 0; for(i=1,#v, s += 1/i; v[i]= s - log(i)); ? limitnum(v) - Euler %18 = 0.E-38 @eprog Because of the above problems, the preferred format is thus a closure, given either a single value or the vector of values $[u_{1},\dots,u_{N}]$. The function distinguishes between the two formats by evaluating the closure at $N\neq 1$ and $1$ and checking whether it yields vectors of respective length $N$ and $1$ or not. \misctitle{Warning} The expression is evaluated for $n = 1, 2, \dots, N$ for an $N = O(B)$ if the current bit accuracy is $B$. If it is not defined for one of these values, translate or rescale accordingly: \bprog ? limitnum(n->log(1-1/n)) \\ can't evaluate at n = 1 ! *** at top-level: limitnum(n->log(1-1/n)) *** ^----------------------- *** in function limitnum: log(1-1/n) *** ^---------- *** log: domain error in log: argument = 0 ? limitnum(n->-log(1-1/(2*n))) %19 = -6.11[...] E-58 @eprog We conclude with a complicated example. Since the function is heuristic, it is advisable to check whether it produces the same limit for $u_{n}, u_{2n}, \dots u_{km}$ for a suitable small multiplier $k$. The following function implements the recursion for the Motzkin numbers $M_{n}$ which count the number of ways to draw non intersecting chords between $n$ points on a circle: $$ M_{n} = M_{n-1} + \sum_{i < n-1} M_{i} M_{n-2-i} = ((n+1)M_{n-1}+(3n-3)M_{n-2}) / (n+2).$$ It is known that $M_{n}^2 \sim \dfrac{9^{n+1}}{12\pi n^{3}}$. \bprog \\ [M_k, M_{k*2}, ..., M_{k*N}] / (3^n / n^(3/2)) vM(N, k = 1) = { my(q = k*N, V); if (q == 1, return ([1/3])); V = vector(q); V[1] = V[2] = 1; for(n = 2, q - 1, V[n+1] = ((2*n + 1)*V[n] + 3*(n - 1)*V[n-1]) / (n + 2)); f = (n -> 3^n / n^(3/2)); return (vector(N, n, V[n*k] / f(n*k))); } ? limitnum(vM) - 3/sqrt(12*Pi) \\ complete junk %1 = 35540390.753542730306762369615276452646 ? limitnum(N->vM(N,5)) - 3/sqrt(12*Pi) \\ M_{5n}: better %2 = 4.130710262178469860 E-25 ? limitnum(N->vM(N,10)) - 3/sqrt(12*Pi) \\ M_{10n}: perfect %3 = 0.E-38 ? \p2000 ? limitnum(N->vM(N,10)) - 3/sqrt(12*Pi) \\ also at high accuracy time = 409 ms. %4 = 1.1048895470044788191 E-2004 @eprog\noindent In difficult cases such as the above a multiplier of 5 to 10 is usually sufficient. The above example is typical: a good multiplier usually remains sufficient when the requested precision increases! \synt{limitnum}{void *E, GEN (*u)(void *,GEN,long), GEN alpha, long prec}, where \kbd{u(E, n, prec)} must return $u(n)$ in precision \kbd{prec}. Also available is \fun{GEN}{limitnum0}{GEN u, GEN alpha, long prec}, where $u$ must be a vector of sufficient length as above. pari-2.17.2/src/functions/sums/intnumromb0000644000175000017500000000561514760123736017107 0ustar billbillFunction: intnumromb Section: sums C-Name: intnumromb0 Prototype: V=GGED0,L,b 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, $bitprec) Doc: numerical integration of \var{expr} (smooth in $]a,b[$), with respect to $X$. Suitable for low accuracy; if \var{expr} is very regular (e.g. analytic in a large region) and high accuracy is desired, try \tet{intnum} first. Set $\fl=0$ (or omit it altogether) when $a$ and $b$ are not too large, the function is smooth, and can be evaluated exactly everywhere on the interval $[a,b]$. If $\fl=1$, uses a general driver routine for doing numerical integration, making no particular assumption (slow). $\fl=2$ is tailored for being used when $a$ or $b$ are infinite using the change of variable $t = 1/X$. 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 at $a$ (but right continuous) or $b$ (left continuous), for example the function $\sin(x)/x$ between $x=0$ and $1$. The user should not require too much accuracy: \tet{realprecision} about 30 decimal digits (\tet{realbitprecision} about 100 bits) 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 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, which can often be accomplished through integration by parts. Finally, the function to be integrated should not be very small (compared to the current precision) on the entire interval. This can of course be accomplished by just multiplying by an appropriate constant. Note that \idx{infinity} can be represented with essentially no loss of accuracy by an appropriate huge number. However beware of real underflow when dealing with rapidly decreasing functions. For example, in order to compute the $\int_{0}^{\infty} e^{-x^{2}}\,dx$ to 38 decimal digits, then one can set infinity equal to 10 for example, and certainly not to \kbd{1e1000}. %\syn{NO} The library syntax is \fun{GEN}{intnumromb}{void *E, GEN (*eval)(void*,GEN), GEN a, GEN b, long flag, long bitprec}, 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.17.2/src/functions/sums/solvestep0000644000175000017500000000234614567450071016737 0ustar billbillFunction: solvestep Section: sums C-Name: solvestep0 Prototype: V=GGGED0,L,p Help: solvestep(X=a,b,step,expr,{flag=0}): find zeros of a function in the real interval [a,b] by naive interval splitting. Wrapper: (,,,G) Description: (gen,gen,gen,gen,?small):gen:prec solvestep(${4 cookie}, ${4 wrapper}, $1, $2, $3, $5, $prec) Doc: find zeros of a continuous function in the real interval $[a,b]$ by naive interval splitting. This function is heuristic and may or may not find the intended zeros. Binary digits of \fl\ mean \item 1: return as soon as one zero is found, otherwise return all zeros found; \item 2: refine the splitting until at least one zero is found (may loop indefinitely if there are no zeros); \item 4: do a multiplicative search (we must have $a > 0$ and $\var{step} > 1$), otherwise an additive search; \var{step} is the multiplicative or additive step. \item 8: refine the splitting until at least one zero is very close to an integer. \bprog ? solvestep(X=0,10,1,sin(X^2),1) %1 = 1.7724538509055160272981674833411451828 ? solvestep(X=1,12,2,besselj(4,X),4) %2 = [7.588342434..., 11.064709488...] @eprog\noindent \synt{solvestep}{void *E, GEN (*eval)(void*,GEN), GEN a,GEN b, GEN step,long flag,long prec}. pari-2.17.2/src/functions/l_functions/0000755000175000017500000000000014760315601016311 5ustar billbillpari-2.17.2/src/functions/l_functions/lfunorderzero0000644000175000017500000000167414676526175021164 0ustar billbillFunction: lfunorderzero Section: l_functions C-Name: lfunorderzero Prototype: lGD-1,L,b Help: lfunorderzero(L,{m=-1}): computes the order of the possible zero of the L-function at the center k/2 of the critical strip. If m is given and has a nonnegative value, assumes the order is at most m. Doc: Computes the order of the possible zero of the $L$-function at the center $k/2$ of the critical strip; return $0$ if $L(k/2)$ does not vanish. If $m$ is given and has a nonnegative value, assumes the order is at most $m$. Otherwise, the algorithm chooses a sensible default: \item if the $L$ argument is an \kbd{Linit}, assume that a multiple zero at $s = k / 2$ has order less than or equal to the maximal allowed derivation order. \item else assume the order is less than $4$. You may explicitly increase this value using optional argument~$m$; this overrides the default value above. (Possibly forcing a recomputation of the \kbd{Linit}.) pari-2.17.2/src/functions/l_functions/lfunparams0000644000175000017500000000125014676526175020422 0ustar billbillFunction: lfunparams Section: l_functions C-Name: lfunparams Prototype: Gp Help: lfunparams(ldata): returns the parameters [N, k, vga] of the L-function defined by ldata (see lfuncreate). The parameters Vga (gamma shifts) are returned to the current precision. Doc: returns the parameters $[N, k, Vga]$ of the $L$-function defined by \kbd{ldata}, corresponding respectively to the conductor, the functional equation relating values at $s$ and $k-s$, and the gamma shifts of the $L$-function (see \kbd{lfuncreate}). The gamma shifts are returned to the current precision. \bprog ? L = lfuncreate(1); /* Riemann zeta function */ ? lfunparams(L) %2 = [1, 1, [0]] @eprog pari-2.17.2/src/functions/l_functions/HEADER0000644000175000017500000004141414676526175017210 0ustar billbillFunction: _header_l_functions Class: header Section: l_functions Doc: \section{$L$-functions} This section describes routines related to $L$-functions. We first introduce the basic concept and notations, then explain how to represent them in GP. Let $\Gamma_{\R}(s) = \pi^{-s/2}\Gamma(s/2)$, where $\Gamma$ is Euler's gamma function. Given $d \geq 1$ and a $d$-tuple $A=[\alpha_{1},\dots,\alpha_{d}]$ of complex numbers, we let $\gamma_{A}(s) = \prod_{\alpha \in A} \Gamma_{\R}(s + \alpha)$. Given a sequence $a = (a_{n})_{n\geq 1}$ of complex numbers (such that $a_{1} = 1$), a positive \emph{conductor} $N \in \Z$, and a \emph{gamma factor} $\gamma_{A}$ as above, we consider the Dirichlet series $$ L(a,s) = \sum_{n\geq 1} a_{n} n^{-s} $$ and the attached completed function $$ \Lambda(a,s) = N^{s/2}\gamma_{A}(s) \cdot L(a,s). $$ Such a datum defines an \emph{$L$-function} if it satisfies the three following assumptions: \item [Convergence] The $a_{n} = O_{\epsilon}(n^{k_{1}+\epsilon})$ have polynomial growth, equivalently $L(s)$ converges absolutely in some right half-plane $\Re(s) > k_{1} + 1$. \item [Analytic continuation] $L(s)$ has a meromorphic continuation to the whole complex plane with finitely many poles. \item [Functional equation] There exist an integer $k$, a complex number $\epsilon$ (usually of modulus~$1$), and an attached sequence $a^{*}$ defining both an $L$-function $L(a^{*},s)$ satisfying the above two assumptions and a completed function $\Lambda(a^{*},s) = N^{s/2}\gamma_{A}(s) \cdot L(a^{*},s)$, such that $$\Lambda(a,k-s) = \epsilon \Lambda(a^{*},s)$$ for all regular points. More often than not in number theory we have $a^{*} = \overline{a}$ (which forces $|\epsilon| = 1$), but this needs not be the case. If $a$ is a real sequence and $a = a^{*}$, we say that $L$ is \emph{self-dual}. We do not assume that the $a_{n}$ are multiplicative, nor equivalently that $L(s)$ has an Euler product. \misctitle{Remark} Of course, $a$ determines the $L$-function, but the (redundant) datum $a,a^{*}, A, N, k, \epsilon$ describes the situation in a form more suitable for fast computations; knowing the polar part $r$ of $\Lambda(s)$ (a rational function such that $\Lambda-r$ is holomorphic) is also useful. A subset of these, including only finitely many $a_{n}$-values will still completely determine $L$ (in suitable families), and we provide routines to try and compute missing invariants from whatever information is available. \misctitle{Important Caveat} The implementation assumes that the implied constants in the $O_{\epsilon}$ are small. In our generic framework, it is impossible to return proven results without more detailed information about the $L$ function. The intended use of the $L$-function package is not to prove theorems, but to experiment and formulate conjectures, so all numerical results should be taken with a grain of salt. One can always increase \kbd{realbitprecision} and recompute: the difference estimates the actual absolute error in the original output. \misctitle{Note} The requested precision has a major impact on runtimes. Because of this, most $L$-function routines, in particular \kbd{lfun} itself, specify the requested precision in \emph{bits}, not in decimal digits. This is transparent for the user once \tet{realprecision} or \tet{realbitprecision} are set. We advise to manipulate precision via \tet{realbitprecision} as it allows finer granularity: \kbd{realprecision} increases by increments of 64 bits, i.e. 19 decimal digits at a time. \subsec{Theta functions} %GPHELPskip Given an $L$-function as above, we define an attached theta function via Mellin inversion: for any positive real $t > 0$, we let $$ \theta(a,t) := \dfrac{1}{2\pi i}\int_{\Re(s) = c} t^{-s} \Lambda(s)\, ds $$ where $c$ is any positive real number $c > k_{1}+1$ such that $c + \Re(a) > 0$ for all $a\in A$. In fact, we have $$\theta(a,t) = \sum_{n\geq 1} a_{n} K(nt/N^{1/2}) \quad\text{where}\quad K(t) := \dfrac{1}{2\pi i}\int_{\Re(s) = c} t^{-s} \gamma_{A}(s)\, ds.$$ Note that this function is analytic and actually makes sense for complex $t$, such that $\Re(t^{2/d}) > 0$, i.e. in a cone containing the positive real half-line. The functional equation for $\Lambda$ translates into $$ \theta(a,1/t) - \epsilon t^{k}\theta(a^{*},t) = P_{\Lambda}(t), $$ where $P_{\Lambda}$ is an explicit polynomial in $t$ and $\log t$ given by the Taylor expansion of the polar part of $\Lambda$: there are no $\log$'s if all poles are simple, and $P = 0$ if $\Lambda$ is entire. The values $\theta(t)$ are generally easier to compute than the $L(s)$, and this functional equation provides a fast way to guess possible values for missing invariants in the $L$-function definition. \subsec{Data structures describing $L$ and theta functions} %GPHELPskip We have 3 levels of description: \item an \tet{Lmath} is an arbitrary description of the underlying mathematical situation (to which e.g., we associate the $a_{p}$ as traces of Frobenius elements); this is done via constructors to be described in the subsections below. \item an \tet{Ldata} is a computational description of situation, containing the complete datum ($a,a^{*},A,k,N,\epsilon,r$). Where $a$ and $a^{*}$ describe the coefficients (given $n,b$ we must be able to compute $[a_{1},\dots,a_{n}]$ with bit accuracy $b$), $A$ describes the Euler factor, the (classical) weight is $k$, $N$ is the conductor, and $r$ describes the polar part of $L(s)$. This is obtained via the function \tet{lfuncreate}. N.B. For motivic $L$-functions, the motivic weight $w$ is $w = k-1$; but we also support nonmotivic $L$-functions. \misctitle{Technical note} When some components of an \kbd{Ldata} cannot be given exactly, usually $r$ or $\epsilon$, the \kbd{Ldata} may be given as a \emph{closure}. When evaluated at a given precision, the closure must return all components as exact data or floating point numbers at the requested precision, see \kbd{??lfuncreate}. The reason for this technicality is that the accuracy to which we must compute is not bounded a priori and unknown at this stage: it depends on the domain where we evaluate the $L$-function. \item an \tet{Linit} contains an \kbd{Ldata} and everything needed for fast \emph{numerical} computations. It specifies the functions to be considered (either $L^{(j)}(s)$ or $\theta^{(j)}(t)$ for derivatives of order $j \leq m$, where $m$ is now fixed) and specifies a \emph{domain} which limits the range of arguments ($t$ or $s$, respectively to certain cones and rectangular regions) and the output accuracy. This is obtained via the functions \tet{lfuninit} or \tet{lfunthetainit}. All the functions which are specific to $L$ or theta functions share the prefix \kbd{lfun}. They take as first argument either an \kbd{Lmath}, an \kbd{Ldata}, or an \kbd{Linit}. If a single value is to be computed, this makes no difference, but when many values are needed (e.g. for plots or when searching for zeros), one should first construct an \kbd{Linit} attached to the search range and use it in all subsequent calls. If you attempt to use an \kbd{Linit} outside the range for which it was initialized, a warning is issued, because the initialization is performed again, a major inefficiency: \bprog ? Z = lfuncreate(1); \\ Riemann zeta ? L = lfuninit(Z, [1/2, 0, 100]); \\ zeta(1/2+it), |t| < 100 ? lfun(L, 1/2) \\ OK, within domain %3 = -1.4603545088095868128894991525152980125 ? lfun(L, 0) \\ not on critical line ! *** lfun: Warning: lfuninit: insufficient initialization. %4 = -0.50000000000000000000000000000000000000 ? lfun(L, 1/2, 1) \\ attempt first derivative ! *** lfun: Warning: lfuninit: insufficient initialization. %5 = -3.9226461392091517274715314467145995137 @eprog For many $L$-functions, passing from \kbd{Lmath} to an \kbd{Ldata} is inexpensive: in that case one may use \kbd{lfuninit} directly from the \kbd{Lmath} even when evaluations in different domains are needed. The above example could equally have skipped the \kbd{lfuncreate}: \bprog ? L = lfuninit(1, [1/2, 0, 100]); \\ zeta(1/2+it), |t| < 100 @eprog\noindent In fact, when computing a single value, you can even skip \kbd{lfuninit}: \bprog ? L = lfun(1, 1/2, 1); \\ zeta'(1/2) ? L = lfun(1, 1+x+O(x^5)); \\ first 5 terms of Taylor expansion at 1 @eprog\noindent Both give the desired results with no warning. \misctitle{Complexity} The implementation requires $O(N(|t|+1))^{1/2}$ coefficients $a_{n}$ to evaluate $L$ of conductor $N$ at $s = \sigma + i t$. We now describe the available high-level constructors, for built-in $L$ functions. \subsec{Dirichlet $L$-functions} %GPHELPskip Given a Dirichlet character $\chi:(\Z/N\Z)^{*}\to \C$, we let $$L(\chi, s) = \sum_{n\geq 1} \chi(n) n^{-s}.$$ Only primitive characters are supported. Given a nonzero integer $D$, the \typ{INT} $D$ encodes the function $L((D_{0}/.), s)$, for the quadratic Kronecker symbol attached to the fundamental discriminant $D_{0} = \kbd{coredisc}(D)$. This includes Riemann $\zeta$ function via the special case $D = 1$. More general characters can be represented in a variety of ways: \item via Conrey notation (see \tet{znconreychar}): $\chi_{N}(m,\cdot)$ is given as the \typ{INTMOD} \kbd{Mod(m,N)}. \item via a \var{znstar} structure describing the abelian group $(\Z/N\Z)^{*}$, where the character is given in terms of the \var{znstar} generators: \bprog ? G = znstar(100, 1); \\ (Z/100Z)^* ? G.cyc \\ ~ Z/20 . g1 + Z/2 . g2 for some generators g1 and g2 %2 = [20, 2] ? G.gen %3 = [77, 51] ? chi = [a, b] \\ maps g1 to e(a/20) and g2 to e(b/2); e(x) = exp(2ipi x) @eprog\noindent More generally, let $(\Z/N\Z)^{*} = \oplus (\Z/d_{j}\Z) g_{j}$ be given via a \var{znstar} structure $G$ (\kbd{G.cyc} gives the $d_{j}$ and \kbd{G.gen} the $g_{j}$). A \tev{character} $\chi$ on $G$ is given by a row vector $v = [a_{1},\ldots,a_{n}]$ such that $\chi(\prod_{j} g_{j}^{n_{j}}) = \exp(2\pi i\sum_{j} a_{j} n_{j} / d_{j})$. The pair $[G, v]$ encodes the \emph{primitive} character attached to $\chi$. \item in fact, this construction $[G, m]$ describing a character is more general: $m$ is also allowed to be a Conrey label as seen above, or a Conrey logarithm (see \tet{znconreylog}), and the latter format is actually the fastest one. Instead of a single character as above, one may use the construction \kbd{lfuncreate([G, vchi])} where \kbd{vchi} is a nonempty vector of characters \emph{of the same conductor} (more precisely, whose attached primitive characters have the same conductor) and \emph{same parity}. The function is then vector-valued, where the values are ordered as the characters in \kbd{vchi}. Conrey labels cannot be used in this last format because of the need to distinguish a single character given by a row vector of integers and a vector of characters given by their labels: use \kbd{znconreylog(G,i)} first to convert a label to Conrey logarithm. \item it is also possible to view Dirichlet characters as Hecke characters over $K = \Q$ (see below), for a modulus $[N, [1]]$ but this is both more complicated and less efficient. In all cases, a nonprimitive character is replaced by the attached primitive character. \subsec{Hecke $L$-functions of finite order characters} %GPHELPskip The Dedekind zeta function of a number field $K = \Q[X]/(T)$ is encoded either by the defining polynomial $T$, or any absolute number fields structure (a \var{nf} is enough). An alternative description for the Dedekind zeta function of an Abelian extension of a number field is to use class-field theory parameters $[\var{bnr}, \var{subg}]$, see \kbd{bnrinit}. \bprog ? bnf = bnfinit(a^2 - a - 9); ? bnr = bnrinit(bnf, [2, [0,0]]); subg = Mat(3); ? L = lfuncreate([bnr, subg]); @eprog Let $K$ be a number field given as a \kbd{bnfinit}. Given a finite order Hecke character $\chi: Cl_{f}(K)\to \C$, we let $$L(\chi, s) = \sum_{A \subset O_{K}} \chi(A)\, \left(N_{K/\Q}A\right)^{-s}.$$ Let $Cl_{f}(K) = \oplus (\Z/d_{j}\Z) g_{j}$ given by a \var{bnr} structure with generators: the $d_{j}$ are given by \kbd{K.cyc} and the $g_{j}$ by \kbd{K.gen}. A \tev{character} $\chi$ on the ray class group is given by a row vector $v = [a_{1},\ldots,a_{n}]$ such that $\chi(\prod_{j} g_{j}^{n_{j}}) = \exp(2\pi i\sum_{j} a_{j} n_{j} / d_{j})$. The pair $[\var{bnr}, v]$ encodes the \emph{primitive} character attached to $\chi$. \bprog ? K = bnfinit(x^2-60); ? Cf = bnrinit(K, [7, [1,1]], 1); \\ f = 7 oo_1 oo_2 ? Cf.cyc %3 = [6, 2, 2] ? Cf.gen %4 = [[2, 1; 0, 1], [22, 9; 0, 1], [-6, 7]~] ? lfuncreate([Cf, [1,0,0]]); \\@com $\chi(g_{1}) = \zeta_{6}$, $\chi(g_{2})=\chi(g_{3})=1$ @eprog \noindent Dirichlet characters on $(\Z/N\Z)^{*}$ are a special case, where $K = \Q$: \bprog ? Q = bnfinit(x); ? Cf = bnrinit(Q, [100, [1]]); \\ for odd characters on (Z/100Z)* @eprog\noindent For even characters, replace by \kbd{bnrinit(K, N)}. Note that the simpler direct construction in the previous section will be more efficient. Instead of a single character as above, one may use the construction \kbd{lfuncreate([Cf, vchi])} where \kbd{vchi} is a nonempty vector of characters \emph{of the same conductor} (more precisely, whose attached primitive characters have the same conductor). The function is then vector-valued, where the values are ordered as the characters in \kbd{vchi}. \subsec{General Hecke $L$-functions} \label{se:lfungchar} %GPHELPskip Given a Hecke \tev{Grossencharacter} $\chi: \A^{\times}\to \C^{\times}$ of conductor~$\goth{f}$, we let $$L(\chi, s) = \sum_{A \subset \Z_{K},\ A+\goth{f}=\Z_{K}} \chi(A)\, \left(N_{K/\Q}A\right)^{-s}.$$ Let $C_{K}(\goth{m})=\A^{\times}/(K^{\times}\cdot U(\goth{m}))$ be an id\`ele class group of modulus $\goth{m}$ given by a \var{gchar} structure~\var{gc} (see \tet{gcharinit} and Section~\ref{se:GCHAR}). A Grossencharacter $\chi$ on $C_{K}(\goth{m})$ is given by a row vector of size \kbd{\#\var{gc}.cyc}. \bprog ? gc = gcharinit(x^3+4*x-1,[5,[1]]); \\ mod = 5.oo ? gc.cyc %3 = [4, 2, 0, 0] ? gcharlog(gc,idealprimedec(gc.bnf,5)[1]) \\@com logarithm map $C_{K}(\goth{m})\to \R^{n}$ ? chi = [1,0,0,1,0]~; ? gcharduallog(gc,chi) \\@com row vector of coefficients in $\R^{n}$ ? L = lfuncreate([gc,chi]); \\@com non algebraic $L$-function ? lfunzeros(L,1) ? lfuneuler(L,2) \\@com Euler factor at 2 @eprog Finite order Hecke characters are a special case. \subsec{Artin $L$ functions} %GPHELPskip Given a Galois number field $N/\Q$ with group $G = \kbd{galoisinit}(N)$, a representation $\rho$ of $G$ over the cyclotomic field $\Q(\zeta_{n})$ is specified by the matrices giving the images of $\kbd{G.gen}$ by $\rho$. The corresponding Artin $L$ function is created using \tet{lfunartin}. \bprog P = quadhilbert(-47); \\ degree 5, Galois group D_5 N = nfinit(nfsplitting(P)); \\ Galois closure G = galoisinit(N); [s,t] = G.gen; \\ order 5 and 2 L = lfunartin(N,G, [[a,0;0,a^-1],[0,1;1,0]], 5); \\ irr. degree 2 @eprog\noindent In the above, the polynomial variable (here \kbd{a}) represents $\zeta_{5} := \exp(2i\pi/5)$ and the two matrices give the images of $s$ and $t$. Here, priority of \kbd{a} must be lower than the priority of \kbd{x}. \subsec{$L$-functions of algebraic varieties} %GPHELPskip $L$-function of elliptic curves over number fields are supported. \bprog ? E = ellinit([1,1]); ? L = lfuncreate(E); \\ L-function of E/Q ? E2 = ellinit([1,a], nfinit(a^2-2)); ? L2 = lfuncreate(E2); \\ L-function of E/Q(sqrt(2)) @eprog $L$-function of hyperelliptic genus-$2$ curve can be created with \kbd{lfungenus2}. To create the $L$ function of the curve $y^{2}+(x^{3}+x^{2}+1)y = x^{2}+x$: \bprog ? L = lfungenus2([x^2+x, x^3+x^2+1]); @eprog Currently, the model needs to be minimal at $2$, and if the conductor is even, its valuation at $2$ might be incorrect (a warning is issued). \subsec{Eta quotients / Modular forms} %GPHELPskip An eta quotient is created by applying \tet{lfunetaquo} to a matrix with 2 columns $[m, r_{m}]$ representing $$ f(\tau) := \prod_{m} \eta(m\tau)^{r_{m}}. $$ It is currently assumed that $f$ is a self-dual cuspidal form on $\Gamma_{0}(N)$ for some $N$. For instance, the $L$-function $\sum \tau(n) n^{-s}$ attached to Ramanujan's $\Delta$ function is encoded as follows \bprog ? L = lfunetaquo(Mat([1,24])); ? lfunan(L, 100) \\ first 100 values of tau(n) @eprog More general modular forms defined by modular symbols will be added later. \subsec{Low-level Ldata format} %GPHELPskip When no direct constructor is available, you can still input an $L$ function directly by supplying $[a, a^{*},A, k, N, \epsilon, r]$ to \kbd{lfuncreate} (see \kbd{??lfuncreate} for details). It is \emph{strongly} suggested to first check consistency of the created $L$-function: \bprog ? L = lfuncreate([a, as, A, k, N, eps, r]); ? lfuncheckfeq(L) \\ check functional equation @eprog pari-2.17.2/src/functions/l_functions/lfuncreate0000644000175000017500000001762014676526175020412 0ustar billbillFunction: lfuncreate Section: l_functions C-Name: lfuncreate Prototype: G Help: lfuncreate(obj): given either an object such as a polynomial, elliptic curve, Dirichlet or Hecke character, eta quotient, etc., or an explicit 6 or 7 component vector [dir,real,Vga,k,N,eps,r], create the Ldata structure necessary for lfun computation. Doc: This low-level routine creates \tet{Ldata} structures, needed by \var{lfun} functions, describing an $L$-function and its functional equation. We advise using a high-level constructor when one is available, see \kbd{??lfun}, and this function accepts them: \bprog ? L = lfuncreate(1); \\ Riemann zeta ? L = lfuncreate(5); \\ Dirichlet L-function for quadratic character (5/.) ? L = lfuncreate(x^2+1); \\ Dedekind zeta for Q(i) ? L = lfuncreate(ellinit([0,1])); \\ L-function of E/Q: y^2=x^3+1 @eprog\noindent One can then use, e.g., \kbd{lfun(L,s)} to directly evaluate the respective $L$-functions at $s$, or \kbd{lfuninit(L, [c,w,h]} to initialize computations in the rectangular box $\Re(s-c) \leq w$, $\Im(s) \leq h$. We now describe the low-level interface, used to input nonbuiltin $L$-functions. The input is now a $6$ or $7$ component vector $V=[a, astar, Vga, k, N, eps, poles]$, whose components are as follows: \item \kbd{V[1]=a} encodes the Dirichlet series coefficients $(a_{n})$. The preferred format is a closure of arity 1: \kbd{n->vector(n,i,a(i))} giving the vector of the first $n$ coefficients. The closure is allowed to return a vector of more than $n$ coefficients (only the first $n$ will be considered) or even less than $n$, in which case loss of accuracy will occur and a warning that \kbd{\#an} is less than expected is issued. This allows to precompute and store a fixed large number of Dirichlet coefficients in a vector $v$ and use the closure \kbd{n->v}, which does not depend on $n$. As a shorthand for this latter case, you can input the vector $v$ itself instead of the closure. \bprog ? z = lfuncreate([n->vector(n,i,1), 1, [0], 1, 1, 1, 1]); \\ Riemann zeta ? lfun(z,2) - Pi^2/6 %2 = -5.877471754111437540 E-39 @eprog A second format is limited to $L$-functions affording an Euler product. It is a closure of arity 2 \kbd{(p,d)->F(p)} giving the local factor $L_{p}(X)$ at $p$ as a rational function, to be evaluated at $p^{-s}$ as in \kbd{direuler}; $d$ is set to \kbd{logint}$(n,p)$ + 1, where $n$ is the total number of Dirichlet coefficients $(a_{1},\dots,a_{n})$ that will be computed. In other words, the smallest integer $d$ such that $p^{d} > n$. This parameter $d$ allows to compute only part of $L_{p}$ when $p$ is large and $L_{p}$ expensive to compute: any polynomial (or \typ{SER}) congruent to $L_{p}$ modulo $X^{d}$ is acceptable since only the coefficients of $X^{0}, \dots, X^{d-1}$ are needed to expand the Dirichlet series. The closure can of course ignore this parameter: \bprog ? z = lfuncreate([(p,d)->1/(1-x), 1, [0], 1, 1, 1, 1]); \\ Riemann zeta ? lfun(z,2) - Pi^2/6 %4 = -5.877471754111437540 E-39 @eprog\noindent One can describe separately the generic local factors coefficients and the bad local factors by setting $\kbd{dir} = [F, L_{bad}]$, were $L_{bad} = [[p_{1},L_{p_{1}}], \dots,[p_{k},L_{p_{k}}]]$, where $F$ describes the generic local factors as above, except that when $p = p_{i}$ for some $i \leq k$, the coefficient $a_{p}$ is directly set to $L_{p_{i}}$ instead of calling $F$. \bprog N = 15; E = ellinit([1, 1, 1, -10, -10]); \\ = "15a1" F(p,d) = 1 / (1 - ellap(E,p)*'x + p*'x^2); Lbad = [[3, 1/(1+'x)], [5, 1/(1-'x)]]; L = lfuncreate([[F,Lbad], 0, [0,1], 2, N, ellrootno(E)]); @eprog\noindent Of course, in this case, \kbd{lfuncreate(E)} is preferable! \item \kbd{V[2]=astar} is the Dirichlet series coefficients of the dual function, encoded as \kbd{a} above. The sentinel values $0$ and $1$ may be used for the special cases where $a = a^{*}$ and $a = \overline{a^{*}}$, respectively. \item \kbd{V[3]=Vga} is the vector of $\alpha_{j}$ such that the gamma factor of the $L$-function is equal to $$\gamma_{A}(s)=\prod_{1\le j\le d}\Gamma_{\R}(s+\alpha_{j}),$$ where $\Gamma_{\R}(s)=\pi^{-s/2}\Gamma(s/2)$. This same syntax is used in the \kbd{gammamellininv} functions. In particular the length $d$ of \kbd{Vga} is the degree of the $L$-function. In the present implementation, the $\alpha_{j}$ are assumed to be exact rational numbers. However when calling theta functions with \emph{complex} (as opposed to real) arguments, determination problems occur which may give wrong results when the $\alpha_{j}$ are not integral. \item \kbd{V[4]=k} is a positive integer $k$. The functional equation relates values at $s$ and $k-s$. For instance, for an Artin $L$-series such as a Dedekind zeta function we have $k = 1$, for an elliptic curve $k = 2$, and for a modular form, $k$ is its weight. For motivic $L$-functions, the \emph{motivic} weight $w$ is $w = k-1$. By default we assume that $a_{n} = O_{\epsilon}(n^{k_{1}+\epsilon})$, where $k_{1} = w$ and even $k_{1} = w/2$ when the $L$ function has no pole (Ramanujan-Petersson). If this is not the case, you can replace the $k$ argument by a vector $[k,k_{1}]$, where $k_{1}$ is the upper bound you can assume. \item \kbd{V[5]=N} is the conductor, an integer $N\ge1$, such that $\Lambda(s)=N^{s/2}\gamma_{A}(s)L(s)$ with $\gamma_{A}(s)$ as above. \item \kbd{V[6]=eps} is the root number $\varepsilon$, i.e., the complex number (usually of modulus $1$) such that $\Lambda(a, k-s) = \varepsilon \Lambda(a^{*}, s)$. \item The last optional component \kbd{V[7]=poles} encodes the poles of the $L$ or $\Lambda$-functions, and is omitted if they have no poles. A polar part is given by a list of $2$-component vectors $[\beta,P_{\beta}(x)]$, where $\beta$ is a pole and the power series $P_{\beta}(x)$ describes the attached polar part, such that $L(s) - P_{\beta}(s-\beta)$ is holomorphic in a neighbourhood of $\beta$. For instance $P_{\beta} = r/x+O(1)$ for a simple pole at $\beta$ or $r_{1}/x^{2}+r_{2}/x+O(1)$ for a double pole. The type of the list describing the polar part allows to distinguish between $L$ and $\Lambda$: a \typ{VEC} is attached to $L$, and a \typ{COL} is attached to $\Lambda$. Unless $a = \overline{a^{*}}$ (coded by \kbd{astar} equal to $0$ or $1$), it is mandatory to specify the polar part of $\Lambda$ rather than those of $L$ since the poles of $L^{*}$ cannot be infered from the latter ! Whereas the functional equation allows to deduce the polar part of $\Lambda^{*}$ from the polar part of $\Lambda$. Finally, if $a = \overline{a^{*}}$, we allow a shortcut to describe the frequent situation where $L$ has at most simple pole, at $s = k$, with residue $r$ a complex scalar: you may then input $\kbd{poles} = r$. This value $r$ can be set to $0$ if unknown and it will be computed. \misctitle{When one component is not exact} Alternatively, \kbd{obj} can be a closure of arity $0$ returning the above vector to the current real precision. This is needed if some components are not available exactly but only through floating point approximations. The closure allows algorithms to recompute them to higher accuracy when needed. Compare \bprog ? Ld1() = [n->lfunan(Mod(2,7),n),1,[0],1,7,((-13-3*sqrt(-3))/14)^(1/6)]; ? Ld2 = [n->lfunan(Mod(2,7),n),1,[0],1,7,((-13-3*sqrt(-3))/14)^(1/6)]; ? L1 = lfuncreate(Ld1); ? L2 = lfuncreate(Ld2); ? lfun(L1,1/2+I*200) \\ OK %5 = 0.55943925130316677665287870224047183265 - 0.42492662223174071305478563967365980756*I ? lfun(L2,1/2+I*200) \\ all accuracy lost %6 = 0.E-38 + 0.E-38*I @eprog\noindent The accuracy lost in \kbd{Ld2} is due to the root number being given to an insufficient precision. To see what happens try \bprog ? Ld3() = printf("prec needed: %ld bits",getlocalbitprec());Ld1() ? L3 = lfuncreate(Ld3); prec needed: 64 bits ? z3 = lfun(L3,1/2+I*200) prec needed: 384 bits %16 = 0.55943925130316677665287870224047183265 - 0.42492662223174071305478563967365980756*I @eprog pari-2.17.2/src/functions/l_functions/lfunzeros0000644000175000017500000000330014676526175020277 0ustar billbillFunction: lfunzeros Section: l_functions C-Name: lfunzeros Prototype: GGD8,L,b Help: lfunzeros(L,lim,{divz=8}): lim being either an upper limit or a real interval, computes an ordered list of zeros of L(s) on the critical line up to the given upper limit or in the given interval. Use a naive algorithm which may miss some zeros. To use a finer search mesh, set divz to some integral value larger than the default (= 8). Doc: \kbd{lim} being either a positive upper limit or a nonempty real interval, computes an ordered list of zeros of $L(s)$ on the critical line up to the given upper limit or in the given interval. Use a naive algorithm which may miss some zeros: it assumes that two consecutive zeros at height $T \geq 1$ differ at least by $2\pi/\omega$, where $$\omega := \kbd{divz} \cdot \big(d\log(T/2\pi) + d+ 2\log(N/(\pi/2)^{d})\big).$$ To use a finer search mesh, set divz to some integral value larger than the default (= 8). \bprog ? lfunzeros(1, 30) \\ zeros of Rieman zeta up to height 30 %1 = [14.134[...], 21.022[...], 25.010[...]] ? #lfunzeros(1, [100,110]) \\ count zeros with 100 <= Im(s) <= 110 %2 = 4 @eprog\noindent The algorithm also assumes that all zeros are simple except possibly on the real axis at $s = k/2$ and that there are no poles in the search interval. (The possible zero at $s = k/2$ is repeated according to its multiplicity.) If you pass an \kbd{Linit} to the function, the algorithm assumes that a multiple zero at $s = k / 2$ has order less than or equal to the maximal derivation order allowed by the \kbd{Linit}. You may increase that value in the \kbd{Linit} but this is costly: only do it for zeros of low height or in \kbd{lfunorderzero} instead. pari-2.17.2/src/functions/l_functions/lfuntheta0000644000175000017500000000236614676526175020255 0ustar billbillFunction: lfuntheta Section: l_functions C-Name: lfuntheta Prototype: GGD0,L,b Help: lfuntheta(data,t,{m=0}): compute the value of the m-th derivative at t of the theta function attached to the L-function given by data. data can be either the standard L-function data, or the output of lfunthetainit. Doc: compute the value of the $m$-th derivative at $t$ of the theta function attached to the $L$-function given by \kbd{data}. \kbd{data} can be either the standard $L$-function data, or the output of \kbd{lfunthetainit}. The result is given with absolute error less than $2^{-B}$, where $B = \text{realbitprecision}$. The theta function is defined by the formula $\Theta(t)=\sum_{n\ge1}a(n)K(nt/\sqrt{N})$, where $a(n)$ are the coefficients of the Dirichlet series, $N$ is the conductor, and $K$ is the inverse Mellin transform of the gamma product defined by the \kbd{Vga} component. Its Mellin transform is equal to $\Lambda(s)-P(s)$, where $\Lambda(s)$ is the completed $L$-function and the rational function $P(s)$ its polar part. In particular, if the $L$-function is the $L$-function of a modular form $f(\tau)=\sum_{n\ge0}a(n)q^{n}$ with $q=\exp(2\pi i\tau)$, we have $\Theta(t)=2(f(it/\sqrt{N})-a(0))$. Note that $a(0)=-L(f,0)$ in this case. pari-2.17.2/src/functions/l_functions/lfunmfspec0000644000175000017500000000270714676526175020424 0ustar billbillFunction: lfunmfspec Section: l_functions C-Name: lfunmfspec Prototype: Gb Help: lfunmfspec(L): L corresponding to a modular eigenform, returns [ve,vo,om,op] in even weight, where ve (resp., vo) is the vector of even (resp., odd) periods, and om and op the corresponding real numbers omega^- and omega^+. Returns [v,om] in odd weight. Doc: let $L$ be the $L$-function attached to a modular eigenform $f$ of weight $k$, as given by \kbd{lfunmf}. In even weight, returns \kbd{[ve,vo,om,op]}, where \kbd{ve} (resp., \kbd{vo}) is the vector of even (resp., odd) periods of $f$ and \kbd{om} and \kbd{op} the corresponding real numbers $\omega^{-}$ and $\omega^{+}$ normalized in a noncanonical way. In odd weight \kbd{ominus} is the same as \kbd{op} and we return \kbd{[v,op]} where $v$ is the vector of all periods. \bprog ? D = mfDelta(); mf = mfinit(D); L = lfunmf(mf, D); ? [ve, vo, om, op] = lfunmfspec(L) %2 = [[1, 25/48, 5/12, 25/48, 1], [1620/691, 1, 9/14, 9/14, 1, 1620/691],\ 0.0074154209298961305890064277459002287248,\ 0.0050835121083932868604942901374387473226] ? DS = mfsymbol(mf, D); bestappr(om*op / mfpetersson(DS), 10^8) %3 = 8192/225 ? mf = mfinit([4, 9, -4], 0); ? F = mfeigenbasis(mf)[1]; L = lfunmf(mf, F); ? [v, om] = lfunmfspec(L) %6 = [[1, 10/21, 5/18, 5/24, 5/24, 5/18, 10/21, 1],\ 1.1302643192034974852387822584241400608] ? FS = mfsymbol(mf, F); bestappr(om^2 / mfpetersson(FS), 10^8) %7 = 113246208/325 @eprog pari-2.17.2/src/functions/l_functions/lfunlarge0000644000175000017500000000076114676526175020237 0ustar billbillFunction: _parsumprimefun_worker Section: programming/internals C-Name: parsumprimefun_worker Prototype: GGGGGG Help: _parsumprimefun_worker(gk,s,zerf,data,vW,f): auxiliary Doc: auxiliary Function: _parsqf_worker Section: programming/internals C-Name: parsqf_worker Prototype: GGG Help: _parsqf_worker(gk,vR,data): auxiliary. Doc: auxiliary Function: _serh_worker Section: programming/internals C-Name: serh_worker Prototype: GGGGG Help: _serh_worker(gk,V,a,ns,gprec): auxiliary. Doc: auxiliary pari-2.17.2/src/functions/l_functions/lfuncheckfeq0000644000175000017500000000726614676526175020725 0ustar billbillFunction: lfuncheckfeq Section: l_functions C-Name: lfuncheckfeq Prototype: lGDGb Help: lfuncheckfeq(L,{t}): given an L-function (Lmath, Ldata or Linit), check whether the functional equation is satisfied. If the function has poles, the polar part must be specified. The program returns a bit accuracy which should be a large negative value close to the current bit accuracy. If t is given, it checks the functional equation for the theta function at t and 1/t. Doc: Given the data attached to an $L$-function (\kbd{Lmath}, \kbd{Ldata} or \kbd{Linit}), check whether the functional equation is satisfied. This is most useful for an \kbd{Ldata} constructed ``by hand'', via \kbd{lfuncreate}, to detect mistakes. If the function has poles, the polar part must be specified. The routine returns a bit accuracy $b$ such that $|w - \hat{w}| < 2^{b}$, where $w$ is the root number contained in \kbd{data}, and $$\hat{w} = \theta(1/t) t^{-k} / \overline{\theta}(t)$$ is a computed value derived from the assumed functional equation. Of course, the expected result is a large negative value of the order of \kbd{realbitprecision}. But if $\overline{\theta}$ is very small at $t$, you should first increase \kbd{realbitprecision} by $-\log_{2} |\overline{\theta}(t)|$, which is positive if $\theta$ is small, to get a meaningful result. Note that $t$ should be close to the unit disc for efficiency and such that $\overline{\theta}(t) \neq 0$. If the parameter $t$ is omitted, we check the functional equation at the ``random'' complex number $t = 335/339 + I/7$. \bprog ? \pb 128 \\ 128 bits of accuracy ? default(realbitprecision) %1 = 128 ? L = lfuncreate(1); \\ Riemann zeta ? lfuncheckfeq(L) %3 = -124 @eprog\noindent i.e. the given data is consistent to within 4 bits for the particular check consisting of estimating the root number from all other given quantities. Checking away from the unit disc will either fail with a precision error, or give disappointing results (if $\theta(1/t)$ is large it will be computed with a large absolute error) \bprog ? lfuncheckfeq(L, 2+I) %4 = -115 ? lfuncheckfeq(L,10) *** at top-level: lfuncheckfeq(L,10) *** ^------------------ *** lfuncheckfeq: precision too low in lfuncheckfeq. @eprog \misctitle{The case of Dedekind zeta functions} Dedekind zeta function for a number field $K = \Q[X]/(T)$ is in general computed (assuming Artin conjecture) as $(\zeta_{K}/\zeta_{k}) \times \zeta_{k}$, where $k$ is a maximal subfield, applied recursively if possible. When $K/\Q$ is Galois, the zeta function is directly decomposed as a product of Artin $L$-functions. These decompositions are computed when \kbd{lfuninit} is called. The behavior of \kbd{lfuncheckfeq} is then different depending of its argument \item the artificial query \kbd{lfuncheckfeq}$(T)$ serves little purpose since we already know that the technical parameters are theoretically correct; we just obtain an estimate on the accuracy they allow. This is computed directly, without using the above decomposition. And is likely to be very costly if the degree of $T$ is large, possibly overflowing the possibilities of the implementation. \item a query \kbd{L = lfuninit(T, ...); lfuncheckfeq(L)} on the other hand returns the maximum of the \kbd{lfuncheckfeq} values for all involved $L$-functions, giving a general consistency check and again an estimate for the accuracy of computed values. At the default accuracy of 128 bits: \bprog ? T = polcyclo(43); ? lfuncheckfeq(T); *** at top-level: lfuncheckfeq(T) *** ^--------------- *** lfuncheckfeq: overflow in lfunthetacost. ? lfuncheckfeq(lfuninit(T, [2])) time = 107 ms. %2 = -122 @eprog pari-2.17.2/src/functions/l_functions/lfunan0000644000175000017500000000104114567450071017521 0ustar billbillFunction: lfunan Section: l_functions C-Name: lfunan Prototype: GLp Help: lfunan(L,n): compute the first n terms of the Dirichlet series attached to the L-function given by L (Lmath, Ldata or Linit). Doc: Compute the first $n$ terms of the Dirichlet series attached to the $L$-function given by \kbd{L} (\kbd{Lmath}, \kbd{Ldata} or \kbd{Linit}). \bprog ? lfunan(1, 10) \\ Riemann zeta %1 = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] ? lfunan(5, 10) \\ Dirichlet L-function for kronecker(5,.) %2 = [1, -1, -1, 1, 0, 1, -1, -1, 1, 0] @eprog pari-2.17.2/src/functions/l_functions/lfun0000644000175000017500000000362514676526175017226 0ustar billbillFunction: lfun Section: l_functions C-Name: lfun0 Prototype: GGD0,L,b Help: lfun(L,s,{D=0}): compute the L-function value L(s), or if D is set, the derivative of order D at s. L is either an Lmath, an Ldata or an Linit. Description: (gen,gen):gen:prec lfun($1, $2, $bitprec) (gen,gen,?0):gen:prec lfun($1, $2, $bitprec) (gen,gen,small):gen:prec lfun0($1, $2, $3, $bitprec) Doc: compute the L-function value $L(s)$, or if \kbd{D} is set, the derivative of order \kbd{D} at $s$. The parameter \kbd{L} is either an Lmath, an Ldata (created by \kbd{lfuncreate}, or an Linit (created by \kbd{lfuninit}), preferrably the latter if many values are to be computed. The argument $s$ is also allowed to be a power series; for instance, if $s = \alpha + x + O(x^{n})$, the function returns the Taylor expansion of order $n$ around $\alpha$. The result is given with absolute error less than $2^{-B}$, where $B = \text{realbitprecision}$. \misctitle{Caveat} The requested precision has a major impact on runtimes. It is advised to manipulate precision via \tet{realbitprecision} as explained above instead of \tet{realprecision} as the latter allows less granularity: \kbd{realprecision} increases by increments of 64 bits, i.e. 19 decimal digits at a time. \bprog ? lfun(x^2+1, 2) \\ Lmath: Dedekind zeta for Q(i) at 2 %1 = 1.5067030099229850308865650481820713960 ? L = lfuncreate(ellinit("5077a1")); \\ Ldata: Hasse-Weil zeta function ? lfun(L, 1+x+O(x^4)) \\ zero of order 3 at the central point %3 = 0.E-58 - 5.[...] E-40*x + 9.[...] E-40*x^2 + 1.7318[...]*x^3 + O(x^4) \\ Linit: zeta(1/2+it), |t| < 100, and derivative ? L = lfuninit(1, [100], 1); ? T = lfunzeros(L, [1,25]); %5 = [14.134725[...], 21.022039[...]] ? z = 1/2 + I*T[1]; ? abs( lfun(L, z) ) %7 = 8.7066865533412207420780392991125136196 E-39 ? abs( lfun(L, z, 1) ) %8 = 0.79316043335650611601389756527435211412 \\ simple zero @eprog pari-2.17.2/src/functions/l_functions/lfundual0000644000175000017500000000136514567450071020061 0ustar billbillFunction: lfundual Section: l_functions C-Name: lfundual Prototype: Gb Help: lfundual(L): creates the Ldata structure (without initialization) corresponding to the dual L-function of L. Doc: creates the \kbd{Ldata} structure (without initialization) corresponding to the dual L-function $\hat{L}$ of $L$. If $k$ and $\varepsilon$ are respectively the weight and root number of $L$, then the following formula holds outside poles, up to numerical errors: $$\Lambda(L, s) = \varepsilon \Lambda(\hat{L}, k - s).$$ \bprog ? L = lfunqf(matdiagonal([1,2,3,4])); ? eps = lfunrootres(L)[3]; k = L[4]; ? M = lfundual(L); lfuncheckfeq(M) %3 = -127 ? s= 1+Pi*I; ? a = lfunlambda(L,s); ? b = eps * lfunlambda(M,k-s); ? exponent(a - b) %7 = -130 @eprog pari-2.17.2/src/functions/l_functions/lfunsympow0000644000175000017500000000102614676526175020476 0ustar billbillFunction: lfunsympow Section: l_functions C-Name: lfunsympow Prototype: GU Help: lfunsympow(E,m): returns the Ldata structure attached to the L-function attached to m-th symmetric power of the elliptic curve E defined over the rationals. Doc: returns the \kbd{Ldata} structure attached to the $L$ function attached to the $m$-th symmetric power of the elliptic curve $E$ defined over the rationals. Function: _direllsympow_worker Section: programming/internals C-Name: direllsympow_worker Prototype: GUGU Help: lfunsympow worker pari-2.17.2/src/functions/l_functions/lfundiv0000644000175000017500000000105314676526175017722 0ustar billbillFunction: lfundiv Section: l_functions C-Name: lfundiv Prototype: GGb Help: lfundiv(L1,L2): creates the Ldata structure (without initialization) corresponding to the quotient of the Dirichlet series given by L1 and L2. Doc: creates the \kbd{Ldata} structure (without initialization) corresponding to the quotient of the Dirichlet series $L_{1}$ and $L_{2}$ given by \kbd{L1} and \kbd{L2}. Assume that $v_{z}(L_{1}) \geq v_{z}(L_{2})$ at all complex numbers $z$: the construction may not create new poles, nor increase the order of existing ones. pari-2.17.2/src/functions/l_functions/lfunthetainit0000644000175000017500000000312614567450071021122 0ustar billbillFunction: lfunthetainit Section: l_functions C-Name: lfunthetainit Prototype: GDGD0,L,b Help: lfunthetainit(L,{tdom},{m=0}): precompute data for evaluating the m-th derivative of theta functions with argument in domain tdom (by default t is real >= 1). Doc: Initalization function for evaluating the $m$-th derivative of theta functions with argument $t$ in domain \var{tdom}. By default (\var{tdom} omitted), $t$ is real, $t \geq 1$. Otherwise, \var{tdom} may be \item a positive real scalar $\rho$: $t$ is real, $t \geq \rho$. \item a nonreal complex number: compute at this particular $t$; this allows to compute $\theta(z)$ for any complex $z$ satisfying $|z|\geq |t|$ and $|\arg z| \leq |\arg t|$; we must have $|2 \arg z / d| < \pi/2$, where $d$ is the degree of the $\Gamma$ factor. \item a pair $[\rho,\alpha]$: assume that $|t| \geq \rho$ and $|\arg t| \leq \alpha$; we must have $|2\alpha / d| < \pi/2$, where $d$ is the degree of the $\Gamma$ factor. \bprog ? \p500 ? L = lfuncreate(1); \\ Riemann zeta ? t = 1+I/2; ? lfuntheta(L, t); \\ direct computation time = 30 ms. ? T = lfunthetainit(L, 1+I/2); time = 30 ms. ? lfuntheta(T, t); \\ instantaneous @eprog\noindent The $T$ structure would allow to quickly compute $\theta(z)$ for any $z$ in the cone delimited by $t$ as explained above. On the other hand \bprog ? lfuntheta(T,I) *** at top-level: lfuntheta(T,I) *** ^-------------- *** lfuntheta: domain error in lfunthetaneed: arg t > 0.785398163397448 @eprog The initialization is equivalent to \bprog ? lfunthetainit(L, [abs(t), arg(t)]) @eprog pari-2.17.2/src/functions/l_functions/lfunartin0000644000175000017500000000615314676526175020263 0ustar billbillFunction: lfunartin Section: l_functions C-Name: lfunartin Prototype: GGGLb Help: lfunartin(nf,gal,rho,n): returns the Ldata structure attached to the Artin L-function provided by the representation rho of the Galois group of the extension K/Q, defined over the cyclotomic field Q(zeta_n), where nf is the nfinit structure attached to K, gal is the galoisinit structure attached to K/Q, and rho is given either by the values of its character on the conjugacy classes or by the matrices that are the images of the generators. Cyclotomic numbers in rho are represented by polynomials, whose variable is understood as the complex number exp(2*I*Pi/n). Doc: returns the \kbd{Ldata} structure attached to the Artin $L$-function provided by the representation $\rho$ of the Galois group of the extension $K/\Q$, defined over the cyclotomic field $\Q(\zeta_{n})$, where \var{nf} is the nfinit structure attached to $K$, \var{gal} is the galoisinit structure attached to $K/\Q$, and \var{rho} is given either \item by the values of its character on the conjugacy classes (see \kbd{galoisconjclasses} and \kbd{galoischartable}) \item or by the matrices that are the images of the generators \kbd{\var{gal}.gen}. Cyclotomic numbers in \kbd{rho} are represented by polynomials, whose variable is understood as the complex number $\exp(2\*i\*\pi/n)$. In the following example we build the Artin $L$-functions attached to the two irreducible degree $2$ representations of the dihedral group $D_{10}$ defined over $\Q(\zeta_{5})$, for the extension $H/\Q$ where $H$ is the Hilbert class field of $\Q(\sqrt{-47})$. We show numerically some identities involving Dedekind $\zeta$ functions and Hecke $L$ series. \bprog ? P = quadhilbert(-47) %1 = x^5 + 2*x^4 + 2*x^3 + x^2 - 1 ? N = nfinit(nfsplitting(P)); ? G = galoisinit(N); \\ D_10 ? [T,n] = galoischartable(G); ? T \\ columns give the irreducible characters %5 = [1 1 2 2] [1 -1 0 0] [1 1 -y^3 - y^2 - 1 y^3 + y^2] [1 1 y^3 + y^2 -y^3 - y^2 - 1] ? n %6 = 5 ? L2 = lfunartin(N,G, T[,2], n); ? L3 = lfunartin(N,G, T[,3], n); ? L4 = lfunartin(N,G, T[,4], n); ? s = 1 + x + O(x^4); ? lfun(-47,s) - lfun(L2,s) %11 ~ 0 ? lfun(1,s)*lfun(-47,s)*lfun(L3,s)^2*lfun(L4,s)^2 - lfun(N,s) %12 ~ 0 ? lfun(1,s)*lfun(L3,s)*lfun(L4,s) - lfun(P,s) %13 ~ 0 ? bnr = bnrinit(bnfinit(x^2+47),1,1); ? bnr.cyc %15 = [5] \\ Z/5Z: 4 nontrivial ray class characters ? lfun([bnr,[1]], s) - lfun(L3, s) %16 ~ 0 ? lfun([bnr,[2]], s) - lfun(L4, s) %17 ~ 0 ? lfun([bnr,[3]], s) - lfun(L3, s) %18 ~ 0 ? lfun([bnr,[4]], s) - lfun(L4, s) %19 ~ 0 @eprog The first identity identifies the nontrivial abelian character with $(-47,\cdot)$; the second is the factorization of the regular representation of $D_{10}$; the third is the factorization of the natural representation of $D_{10}\subset S_{5}$; and the final four are the expressions of the degree $2$ representations as induced from degree $1$ representations. Function: _dirartin_worker Section: programming/internals C-Name: dirartin_worker Prototype: GUGGGG Help: lfunartin worker pari-2.17.2/src/functions/l_functions/lfunhardy0000644000175000017500000000337614676526175020261 0ustar billbillFunction: lfunhardy Section: l_functions C-Name: lfunhardy Prototype: GGb Help: lfunhardy(L,t): variant of the Hardy L-function attached to L, used for plotting on the critical line. Doc: Variant of the Hardy $Z$-function given by \kbd{L}, used for plotting or locating zeros of $L(k/2+it)$ on the critical line. The precise definition is as follows: let $k/2$ be the center of the critical strip, $d$ be the degree, $\kbd{Vga} = (\alpha_{j})_{j\leq d}$ given the gamma factors, and $\varepsilon$ be the root number; we set $s = k/2+it = \rho e^{i\theta}$ and $2E = d(k/2-1) + \Re(\sum_{1\le j\le d}\alpha_{j})$. Assume first that $\Lambda$ is self-dual, then the computed function at $t$ is equal to $$Z(t) = \varepsilon^{-1/2}\Lambda(s) \cdot \rho^{-E}e^{dt\theta/2}\;,$$ which is a real function of $t$ vanishing exactly when $L(k/2+it)$ does on the critical line. The normalizing factor $|s|^{-E}e^{dt\theta/2}$ compensates the exponential decrease of $\gamma_{A}(s)$ as $t\to\infty$ so that $Z(t) \approx 1$. For non-self-dual $\Lambda$, the definition is the same except we drop the $\varepsilon^{-1/2}$ term (which is not well defined since it depends on the chosen dual sequence $a^{*}(n)$): $Z(t)$ is still of the order of $1$ and still vanishes where $L(k/2+it)$ does, but it needs no longer be real-valued. \bprog ? T = 100; \\ maximal height ? L = lfuninit(1, [T]); \\ initialize for zeta(1/2+it), |t|= 1 %1 = 15 ? lfunthetacost(L, 1 + I); \\ cost for theta(1+I). Domain error ! *** at top-level: lfunthetacost(1,1+I) *** ^-------------------- *** lfunthetacost: domain error in lfunthetaneed: arg t > 0.785 ? lfunthetacost(L, 1 + I/2) \\ for theta(1+I/2). %2 = 23 ? lfunthetacost(L, 1 + I/2, 10) \\ for theta^((10))(1+I/2). %3 = 24 ? lfunthetacost(L, [2, 1/10]) \\ cost for theta(t), |t| >= 2, |arg(t)| < 1/10 %4 = 8 ? L = lfuncreate( ellinit([1,1]) ); ? lfunthetacost(L) \\ for t >= 1 %6 = 2471 @eprog pari-2.17.2/src/functions/l_functions/lfunetaquo0000644000175000017500000000147614676526175020447 0ustar billbillFunction: lfunetaquo Section: l_functions C-Name: lfunetaquo Prototype: G Help: lfunetaquo(M): returns the Ldata structure attached to the modular form z->prod(i=1,#M[,1],eta(M[i,1]*z)^M[i,2]). Doc: returns the \kbd{Ldata} structure attached to the $L$ function attached to the modular form $z\mapsto \prod_{i=1}^{n} \eta(M_{i,1}\*z)^{M_{i,2}}$ It is currently assumed that $f$ is a self-dual cuspidal form on $\Gamma_{0}(N)$ for some $N$. For instance, the $L$-function $\sum \tau(n) n^{-s}$ attached to Ramanujan's $\Delta$ function is encoded as follows \bprog ? L = lfunetaquo(Mat([1,24])); ? lfunan(L, 100) \\ first 100 values of tau(n) @eprog\noindent For convenience, a \typ{VEC} is also accepted instead of a factorization matrix with a single row: \bprog ? L = lfunetaquo([1,24]); \\ same as above @eprog pari-2.17.2/src/functions/l_functions/lfunlambda0000644000175000017500000000130414567450071020345 0ustar billbillFunction: lfunlambda Section: l_functions C-Name: lfunlambda0 Prototype: GGD0,L,b Help: lfunlambda(L,s,{D=0}): compute the completed L function Lambda(s), or if D is set, the derivative of order D at s. L is either an Lmath, an Ldata or an Linit. Doc: compute the completed $L$-function $\Lambda(s) = N^{s/2}\gamma(s)L(s)$, or if \kbd{D} is set, the derivative of order \kbd{D} at $s$. The parameter \kbd{L} is either an \kbd{Lmath}, an \kbd{Ldata} (created by \kbd{lfuncreate}, or an \kbd{Linit} (created by \kbd{lfuninit}), preferrably the latter if many values are to be computed. The result is given with absolute error less than $2^{-B}|\gamma(s)N^{s/2}|$, where $B = \text{realbitprecision}$. pari-2.17.2/src/functions/l_functions/lfunrootres0000644000175000017500000000300614676526175020635 0ustar billbillFunction: lfunrootres Section: l_functions C-Name: lfunrootres Prototype: Gb Help: lfunrootres(data): given the Ldata attached to an L-function (or the output of lfunthetainit), compute the root number and the residues. In the present implementation, if the polar part is not already known completely, at most a single pole is allowed. The output is a 3-component vector [[[a_1, r_1],...,[a_n, r_n],[[b_1, R_1],...[b_m,R_m]]~, w], where r_i is the polar part of L(s) at a_i, R_i is is the polar part of Lambda(s) at b_i, or [0,0,r] if there is no pole, and r is the root number. Doc: Given the \kbd{Ldata} attached to an $L$-function (or the output of \kbd{lfunthetainit}), compute the root number and the residues. The output is a 3-component vector $[[[a_{1},r_{1}],\cdots,[a_{n}, r_{n}], [[b_{1}, R_{1}],\cdots,[b_{m}, R_{m}]]~, w]$, where $r_{i}$ is the polar part of $L(s)$ at $a_{i}$, $R_{i}$ is is the polar part of $\Lambda(s)$ at $b_{i}$ or $[0,0,r]$ if there is no pole, and $w$ is the root number. In the present implementation, \item either the polar part must be completely known (and is then arbitrary): the function determines the root number, \bprog ? L = lfunmul(1,1); \\ zeta^2 ? [r,R,w] = lfunrootres(L); ? r \\ single pole at 1, double %3 = [[1, 1.[...]*x^-2 + 1.1544[...]*x^-1 + O(x^0)]] ? w %4 = 1 ? R \\ double pole at 0 and 1 %5 = [[1,[...]], [0,[...]]]~ @eprog \item or at most a single pole is allowed: the function computes both the root number and the residue ($0$ if no pole). pari-2.17.2/src/functions/l_functions/lfuncost0000644000175000017500000001101514676526175020107 0ustar billbillFunction: lfuncost Section: l_functions C-Name: lfuncost0 Prototype: GDGD0,L,b Help: lfuncost(L,{sdom},{der=0}): estimate the cost of running lfuninit(L,sdom,der) at current bit precision. Returns [t,b], to indicate that t coefficients a_n will be computed at bit accuracy b. Subsequent evaluation of lfun at s evaluates a polynomial of degree t at exp(h s). If L is already an Linit, then sdom and der are ignored. Doc: estimate the cost of running \kbd{lfuninit(L,sdom,der)} at current bit precision, given by a vector $[t, b]$. \item If $L$ contains the root number, indicate that $t$ coefficients $a_{n}$ will be computed, as well as $t$ values of \tet{gammamellininv}, all at bit accuracy $b$. A subsequent call to \kbd{lfun} at $s$ evaluates a polynomial of degree $t$ at $\exp(h s)$ for some real parameter $h$, at the same bit accuracy $b$. \item If the root number is \emph{not} known, then more values of $a_{n}$ may be needed in order to compute it, and the returned value of $t$ takes this into account (it may not be the exact value in this case but is always an upper bound). Fewer than $t$ \kbd{gammamellininv} will be needed, and a call to \kbd{lfun} evaluates a polynomial of degree less that $t$, still at bit accuracy $b$. If $L$ is already an \kbd{Linit}, then \var{sdom} and \var{der} are ignored and are best left omitted; the bit accuracy is also inferred from $L$: in short we get an estimate of the cost of using that particular \kbd{Linit}. Note that in this case, the root number is always already known and you get the right value of $t$ (corresponding to the number of past calls to \kbd{gammamellinv} and the actual degree of the evaluated polynomial). \bprog ? \pb 128 ? lfuncost(1, [100]) \\ for zeta(1/2+I*t), |t| < 100 %1 = [7, 242] \\ 7 coefficients, 242 bits ? lfuncost(1, [1/2, 100]) \\ for zeta(s) in the critical strip, |Im s| < 100 %2 = [7, 246] \\ now 246 bits ? lfuncost(1, [100], 10) \\ for zeta(1/2+I*t), |t| < 100 %3 = [8, 263] \\ 10th derivative increases the cost by a small amount ? lfuncost(1, [10^5]) %3 = [158, 113438] \\ larger imaginary part: huge accuracy increase ? L = lfuncreate(polcyclo(5)); \\ Dedekind zeta for Q(zeta_5) ? lfuncost(L, [100]) \\ at s = 1/2+I*t), |t| < 100 %5 = [11457, 582] ? lfuncost(L, [200]) \\ twice higher %6 = [36294, 1035] ? lfuncost(L, [10^4]) \\ much higher: very costly ! %7 = [70256473, 45452] ? \pb 256 ? lfuncost(L, [100]); \\ doubling bit accuracy is cheaper %8 = [17080, 710] ? \p38 ? K = bnfinit(y^2 - 4493); [P] = idealprimedec(K,1123); f = [P,[1,1]]; ? R = bnrinit(K, f); R.cyc %10 = [1122] ? L = lfuncreate([R, [7]]); \\ Hecke L-function ? L[6] %12 = 0 \\ unknown root number ? \pb 3000 ? lfuncost(L, [0], 1) %13 = [1171561, 3339] ? L = lfuninit(L, [0], 1); time = 1min, 56,426 ms. ? lfuncost(L) %14 = [826966, 3339] @eprog\noindent In the final example, the root number was unknown and extra coefficients $a_{n}$ were needed to compute it ($1171561$). Once the initialization is performed we obtain the lower value $t = 826966$, which corresponds to the number of \kbd{gammamellinv} computed and the actual degree of the polynomial to be evaluated to compute a value within the prescribed domain. Finally, some $L$ functions can be factorized algebraically by the \kbd{lfuninit} call, e.g. the Dedekind zeta function of abelian fields, leading to much faster evaluations than the above upper bounds. In that case, the function returns a vector of costs as above for each individual function in the product actually evaluated: \bprog ? L = lfuncreate(polcyclo(5)); \\ Dedekind zeta for Q(zeta_5) ? lfuncost(L, [100]) \\ a priori cost %2 = [11457, 582] ? L = lfuninit(L, [100]); \\ actually perform all initializations ? lfuncost(L) %4 = [[16, 242], [16, 242], [7, 242]] @eprog\noindent The Dedekind function of this abelian quartic field is the product of four Dirichlet $L$-functions attached to the trivial character, a nontrivial real character and two complex conjugate characters. The nontrivial characters happen to have the same conductor (hence same evaluation costs), and correspond to two evaluations only since the two conjugate characters are evaluated simultaneously. For a total of three $L$-functions evaluations, which explains the three components above. Note that the actual cost is much lower than the a priori cost in this case. Variant: Also available is \fun{GEN}{lfuncost}{GEN L, GEN dom, long der, long bitprec} when $L$ is \emph{not} an \kbd{Linit}; the return value is a \typ{VECSMALL} in this case. pari-2.17.2/src/functions/l_functions/lfuntwist0000644000175000017500000000114114567450071020276 0ustar billbillFunction: lfuntwist Section: l_functions C-Name: lfuntwist Prototype: GGb Help: lfuntwist(L,chi): creates the Ldata structure (without initialization) corresponding to the twist of L by the primitive character attached to the Dirichlet L-function chi. This requires that the conductor of the character is coprime to the conductor of the L-function L. Doc: creates the Ldata structure (without initialization) corresponding to the twist of L by the primitive character attached to the Dirichlet character \kbd{chi}. The conductor of the character must be coprime to the conductor of the L-function $L$. pari-2.17.2/src/functions/l_functions/lfunconductor0000644000175000017500000000655514676526175021154 0ustar billbillFunction: lfunconductor Section: l_functions C-Name: lfunconductor Prototype: GDGD0,L,b Help: lfunconductor(L,{setN=10000},{flag=0}): gives the conductor of the given L-function, expecting to find it in the interval [1,setN]. If flag=0 (default), gives either the conductor found as an integer, or a vector of conductors found, possibly empty. If flag=1, same but gives the computed floating point approximations to the conductors found, without rounding to integers. If flag=2, gives all the conductors found, even those far from integers. Alternatively, setN can contain a list of possible conductors and we select the best one according to lfuncheckfeq; in this case, flag is ignored and we return [N, lfuncheckfeq for that N]. Doc: Computes the conductor of the given $L$-function (if the structure contains a conductor, it is ignored). Two methods are available, depending on what we know about the conductor, encoded in the \kbd{setN} parameter: \item \kbd{setN} is a scalar: we know nothing but expect that the conductor lies in the interval $[1, \kbd{setN}]$. If $\fl$ is $0$ (default), gives either the conductor found as an integer, or a vector (possibly empty) of conductors found. If $\fl$ is $1$, same but gives the computed floating point approximations to the conductors found, without rounding to integers. It $\fl$ is $2$, gives all the conductors found, even those far from integers. \misctitle{Caveat} This is a heuristic program and the result is not proven in any way: \bprog ? L = lfuncreate(857); \\ Dirichlet L function for kronecker(857,.) ? \p19 realprecision = 19 significant digits ? lfunconductor(L) %2 = [17, 857] ? lfunconductor(L,,1) \\ don't round %3 = [16.99999999999999999, 857.0000000000000000] ? \p38 realprecision = 38 significant digits ? lfunconductor(L) %4 = 857 @eprog\noindent Increasing \kbd{setN} or increasing \kbd{realbitprecision} slows down the program but gives better accuracy for the result. This algorithm should only be used if the primes dividing the conductor are unknown, which is uncommon. \item \kbd{setN} is a vector of possible conductors; for instance of the form \kbd{D1 * divisors(D2)}, where $D_{1}$ is the known part of the conductor and $D_{2}$ is a multiple of the contribution of the bad primes. In that case, $\fl$ is ignored and the routine uses \kbd{lfuncheckfeq}. It returns $[N,e]$ where $N$ is the best conductor in the list and $e$ is the value of \kbd{lfuncheckfeq} for that $N$. When no suitable conductor exist or there is a tie among best potential conductors, return the empty vector \kbd{[]}. \bprog ? E = ellinit([0,0,0,4,0]); /* Elliptic curve y^2 = x^3+4x */ ? E.disc \\ |disc E| = 2^12 %2 = -4096 \\ create Ldata by hand. Guess that root number is 1 and conductor N ? L(N) = lfuncreate([n->ellan(E,n), 0, [0,1], 2, N, 1]); \\ lfunconductor ignores conductor = 1 in Ldata ! ? lfunconductor(L(1), divisors(E.disc)) %5 = [32, -127] ? fordiv(E.disc, d, print(d,": ",lfuncheckfeq(L(d)))) \\ direct check 1: 0 2: 0 4: -1 8: -2 16: -3 32: -127 64: -3 128: -2 256: -2 512: -1 1024: -1 2048: 0 4096: 0 @eprog\noindent The above code assumed that root number was $1$; had we set it to $-1$, none of the \kbd{lfuncheckfeq} values would have been acceptable: \bprog ? L2 = lfuncreate([n->ellan(E,n), 0, [0,1], 2, 0, -1]); ? lfunconductor(L2, divisors(E.disc)) %7 = [] @eprog pari-2.17.2/src/functions/symbolic_operators/0000755000175000017500000000000014760315601017705 5ustar billbillpari-2.17.2/src/functions/symbolic_operators/eq0000644000175000017500000000257414567450071020253 0ustar billbillFunction: _==_ Help: x==y: return 1 if x and y are equal, 0 otherwise. Section: symbolic_operators C-Name: geq Prototype: GG Description: (small, small):bool:parens $(1) == $(2) (lg, lg):bool:parens $(1) == $(2) (small, int):bool equalsi($1, $2) (mp, 0):bool !signe($1) (int, 1):bool equali1($1) (int, -1):bool equalim1($1) (int, small):bool equalis($1, $2) (int, int):bool equalii($1, $2) (gen, 0):bool gequal0($1) (gen, 1):bool gequal1($1) (gen, -1):bool gequalm1($1) (real,real):bool equalrr($1, $2) (mp, mp):bool:parens mpcmp($1, $2) == 0 (errtyp, errtyp):bool:parens $(1) == $(2) (errtyp, #str):bool:parens $(1) == $(errtyp:2) (#str, errtyp):bool:parens $(errtyp:1) == $(2) (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.17.2/src/functions/symbolic_operators/range0000644000175000017500000000030314557721031020722 0ustar billbillFunction: [_.._] Section: programming/internals C-Name: vecrange Prototype: GG Help: [a..b] = [a,a+1,...,b] Description: (gen,gen):vec vecrange($1, $2) (small,small):vec vecrangess($1, $2) pari-2.17.2/src/functions/symbolic_operators/divent0000644000175000017500000000102213637407207021122 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.17.2/src/functions/symbolic_operators/shiftl0000644000175000017500000000040314567450071021124 0ustar billbillFunction: _<<_ Section: symbolic_operators C-Name: gshift Prototype: GL Help: x<_ Help: x>y: return 1 if x is strictly greater than y, 0 otherwise. Section: symbolic_operators C-Name: ggt Prototype: GG Description: (small, small):bool:parens $(1) > $(2) (lg, lg):bool:parens $(1) > $(2) (small, lg):bool:parens $(1) >= $(2) (small, int):bool:parens cmpsi($1, $2) > 0 (int, small):bool:parens cmpis($1, $2) > 0 (int, int):bool:parens cmpii($1, $2) > 0 (mp, mp):bool:parens mpcmp($1, $2) > 0 (str, str):bool:parens strcmp($1, $2) > 0 (small, gen):bool:parens gcmpsg($1, $2) > 0 (gen, small):bool:parens gcmpgs($1, $2) > 0 (gen, gen):bool:parens gcmp($1, $2) > 0 pari-2.17.2/src/functions/symbolic_operators/sub0000644000175000017500000000220014567450071020421 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) (Fp, Fp):Fp Fp_sub($1, $2, p) (Fp, FpX):FpX Fp_FpX_sub($1, $2, p) (FpX, Fp):FpX FpX_Fp_sub($1, $2, p) (FpX, FpX):FpX FpX_sub($1, $2, p) (Fq, Fq):Fq Fq_sub($1, $2, T, p) (FqX, Fq):FqX FqX_Fq_sub($1, $2, T, p) (FqX, FqX):FqX FqX_sub($1, $2, T, p) pari-2.17.2/src/functions/symbolic_operators/divente0000644000175000017500000000060113637407207021271 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.17.2/src/functions/symbolic_operators/concat0000644000175000017500000000051214567450071021103 0ustar billbillFunction: __ Help: __: integral concatenation of strings. Section: symbolic_operators Description: (genstr, genstr):genstr gconcat($1, $2) (genstr, gen):genstr gconcat($1, $2) (gen, genstr):genstr gconcat($1, $2) (gen, gen):genstr gconcat($genstr:1, $2) pari-2.17.2/src/functions/symbolic_operators/hist0000644000175000017500000000034214567450071020604 0ustar billbillFunction: % C-Name: pari_get_hist Prototype: D0,L, Section: symbolic_operators Help: last history item. Function: %# C-Name: pari_histtime Prototype: D0,L, Section: symbolic_operators Help: time to compute last history item. pari-2.17.2/src/functions/symbolic_operators/shiftre0000644000175000017500000000056413637407207021307 0ustar billbillFunction: _>>=_ 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.17.2/src/functions/symbolic_operators/deriv0000644000175000017500000000066114567450071020752 0ustar billbillFunction: _'_ Section: symbolic_operators C-Name: derivn Prototype: GLDn Help: x': derivative of x with respect to the main variable. Description: (gen,1):gen deriv($1, -1) (FpX,1):FpX FpX_deriv($1, p) (FqX,1):FqX FqX_deriv($1, T, p) Function: _' Section: symbolic_operators C-Name: deriv Prototype: GDn Help: x': derivative of x with respect to the main variable. pari-2.17.2/src/functions/symbolic_operators/div0000644000175000017500000000215614567450071020424 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) (Fp, 2):Fp Fp_halve($1, p) (Fp, Fp):Fp Fp_div($1, $2, p) (Fq, 2):Fq Fq_halve($1, T, p) (Fq, Fq):Fq Fq_div($1, $2, T, p) Function: _QXQ_inv_worker C-Name: QXQ_inv_worker Prototype: GGG Section: programming/internals Help: worker for QXQ_inv Function: _QXQ_div_worker C-Name: QXQ_div_worker Prototype: GGGG Section: programming/internals Help: worker for QXQ_div pari-2.17.2/src/functions/symbolic_operators/ne0000644000175000017500000000223714567450071020244 0ustar billbillFunction: _!=_ Help: a!=b: true if a and b are not equal. Section: symbolic_operators C-Name: gne Prototype: GG Description: (small, small):bool:parens $(1) != $(2) (lg, lg):bool:parens $(1) != $(2) (small, int):negbool equalsi($1, $2) (int, small):negbool equalis($1, $2) (int, 1):negbool equali1($1) (int, -1):negbool equalim1($1) (int, int):negbool equalii($1, $2) (real,real):negbool equalrr($1, $2) (mp, mp):bool:parens mpcmp($1, $2) != 0 (errtyp, errtyp):bool:parens $(1) != $(2) (errtyp, #str):bool:parens $(1) != $(errtyp:2) (#str, errtyp):bool:parens $(errtyp:1) != $(2) (typ, typ):bool:parens $(1) != $(2) (typ, #str):bool:parens $(1) != $(typ:2) (#str, typ):bool:parens $(typ:1) != $(2) (str, str):bool strcmp($1, $2) (small, gen):negbool gequalsg($1, $2) (gen, small):negbool gequalgs($1, $2) (gen, gen):negbool gequal($1, $2) pari-2.17.2/src/functions/symbolic_operators/add0000644000175000017500000000240614567450071020370 0ustar billbillFunction: _+_ Section: symbolic_operators C-Name: gadd Prototype: GG Help: x+y: sum of x and y. Description: (lg, 1):small:parens $(1) (small, small):small:parens $(1) + $(2) (lg, small):lg:parens $(1) + $(2) (small, lg):lg:parens $(1) + $(2) (int, small):int addis($1, $2) (small, int):int addsi($1, $2) (int, int):int addii($1, $2) (real, small):real addrs($1, $2) (small, real):real addsr($1, $2) (real, real):real addrr($1, $2) (mp, real):real mpadd($1, $2) (real, mp):real mpadd($1, $2) (mp, mp):mp mpadd($1, $2) (gen, small):gen gaddgs($1, $2) (small, gen):gen gaddsg($1, $2) (gen, gen):gen gadd($1, $2) (Fp, Fp):Fp Fp_add($1, $2, p) (FpX, Fp):FpX FpX_Fp_add($1, $2, p) (Fp, FpX):FpX FpX_Fp_add($2, $1, p) (FpX, FpX):FpX FpX_add($1, $2, p) (Fq, Fq):Fq Fq_add($1, $2, T, p) (FqX, Fq):FqX FqX_Fq_add($1, $2, T, p) (Fq, FqX):FqX FqX_Fq_add($2, $1, T, p) (FqX, FqX):FqX FqX_add($1, $2, T, p) pari-2.17.2/src/functions/symbolic_operators/pow0000644000175000017500000000334514676526175020462 0ustar billbillFunction: _^_ Help: x^y: compute x to the power y. Section: symbolic_operators C-Name: gpow Prototype: GGp Description: (usmall,2):int sqru($1) (small,2):int sqrs($1) (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) (Fp, 2):Fp Fp_sqr($1, p) (Fp, usmall):Fp Fp_powu($1, $2, p) (Fp, small):Fp Fp_pows($1, $2, p) (Fp, int):Fp Fp_pow($1, $2, p) (FpX, 2):FpX FpX_sqr($1, p) (FpX, usmall):FpX FpX_powu($1, $2, p) (Fq, 2):Fq Fq_sqr($1, T, p) (Fq, usmall):Fq Fq_powu($1, $2, T, p) (Fq, int):Fq Fq_pow($1, $2, T, p) (Fq, 2):Fq Fq_sqr($1, T, p) (Fq, usmall):Fq Fq_powu($1, $2, T, p) (Fq, int):Fq Fq_pow($1, $2, T, p) (FqX, 2):FqX FqX_sqr($1, T, p) (FqX, usmall):FqX FqX_powu($1, $2, T, p) Function: _^s Help: return x^n where n is a small integer Section: programming/internals C-Name: gpowgs Prototype: GL Function: _inv Help: return x^-1 where n is a small integer Section: programming/internals C-Name: ginv Prototype: G pari-2.17.2/src/functions/symbolic_operators/or0000644000175000017500000000027114567450071020256 0ustar billbillFunction: _||_ C-Name: orpari Prototype: GE Help: a||b: boolean operator "or" (inclusive). Section: symbolic_operators Description: (bool, bool):bool:parens $(1) || $(2) pari-2.17.2/src/functions/symbolic_operators/slice0000644000175000017500000000067014557721031020734 0ustar billbillFunction: _[_.._] Section: symbolic_operators C-Name: vecslice0 Prototype: GD0,L,L Help: x[a..b] = [x[a],x[a+1],...,x[b]] Function: _[_.._,_.._] Section: symbolic_operators C-Name: matslice0 Prototype: GD0,L,D0,L,D0,L,D0,L, Help: x[a..b,c..d] = [x[a,c], x[a+1,c], ...,x[b,c]; x[a,c+1],x[a+1,c+1],...,x[b,c+1]; ... ... ... x[a,d], x[a+1,d] ,...,x[b,d]] pari-2.17.2/src/functions/symbolic_operators/sube0000644000175000017500000000157413637407207020603 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.17.2/src/functions/symbolic_operators/shiftr0000644000175000017500000000050214567450071021132 0ustar billbillFunction: _>>_ Section: symbolic_operators C-Name: gshift_right Prototype: GL Help: x>>y: compute shift(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.17.2/src/functions/symbolic_operators/mul0000644000175000017500000000430014676526175020442 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 gmulsg($1, $2) (mp, 0):small ($1, 0)/*for side effect*/ (real, #small):real mulrs($1, $2) (real, small):mp gmulgs($1, $2) (real, real):real mulrr($1, $2) (mp, mp):mp gmul($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) (usmall,Fp):Fp Fp_mulu($2, $1, p) (small,Fp):Fp Fp_muls($2, $1, p) (Fp, usmall):Fp Fp_mulu($1, $2, p) (Fp, small):Fp Fp_muls($1, $2, p) (usmall,FpX):FpX FpX_mulu($2, $1, p) (FpX, usmall):FpX FpX_mulu($1, $2, p) (Fp, FpX):FpX FpX_Fp_mul($2, $1, p) (FpX, Fp):FpX FpX_Fp_mul($1, $2, p) (FpX, FpX):FpX FpX_mul($1, $2, p) (usmall,Fq):Fq Fq_mulu($2, $1, T, p) (Fq, usmall):Fq Fq_mulu($1, $2, T, p) (Fq,Fp):Fq Fq_Fp_mul($1, $2, T, p) (Fp,Fq):Fq Fq_Fp_mul($2, $1, T, p) (usmall,FqX):FqX FqX_mulu($2, $1, T, p) (FqX, usmall):FqX FqX_mulu($1, $2, T, p) (FqX,Fp):FqX FqX_Fp_mul($1, $2, T, p) (Fp,FqX):FqX FqX_Fp_mul($2, $1, T, p) (Fq, FqX):FqX FqX_Fq_mul($2, $1, T, p) (FqX, Fq):FqX FqX_Fq_mul($1, $2, T, p) (FqX, FqX):FqX FqX_mul($1, $2, T, p) Function: _ZM_mul_worker C-Name: ZM_mul_worker Prototype: GGG Section: programming/internals Help: worker for ZM_mul Function: _RgM_ZM_mul_worker C-Name: RgM_ZM_mul_worker Prototype: GG Section: programming/internals Help: worker for RgM_ZM_mul pari-2.17.2/src/functions/symbolic_operators/mule0000644000175000017500000000150713637407207020603 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.17.2/src/functions/symbolic_operators/shiftle0000644000175000017500000000055313637407207021277 0ustar billbillFunction: _<<=_ Section: symbolic_operators C-Name: gshiftle Prototype: &L Help: x<<=y: shortcut for x=x<=_ Help: x>=y: return 1 if x is greater or equal to y, 0 otherwise. Section: symbolic_operators C-Name: gge Prototype: GG Description: (small, small):bool:parens $(1) >= $(2) (lg, lg):bool:parens $(1) >= $(2) (lg, small):bool:parens $(1) > $(2) (small, int):bool:parens cmpsi($1, $2) >= 0 (int, small):bool:parens cmpis($1, $2) >= 0 (int, int):bool:parens cmpii($1, $2) >= 0 (mp, mp):bool:parens mpcmp($1, $2) >= 0 (str, str):bool:parens strcmp($1, $2) >= 0 (small, gen):bool:parens gcmpsg($1, $2) >= 0 (gen, small):bool:parens gcmpgs($1, $2) >= 0 (gen, gen):bool:parens gcmp($1, $2) >= 0 pari-2.17.2/src/functions/symbolic_operators/divround0000644000175000017500000000037513637407207021475 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.17.2/src/functions/symbolic_operators/adde0000644000175000017500000000157413637407207020542 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.17.2/src/functions/symbolic_operators/neg0000644000175000017500000000065214567450071020412 0ustar billbillFunction: -_ Help: -_: negate argument 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) (Fp):Fp Fp_neg($1, p) (FpX):FpX FpX_neg($1, p) (Fq):Fq Fq_neg($1, T, p) (FqX):FqX FqX_neg($1, T, p) pari-2.17.2/src/functions/symbolic_operators/coeff0000644000175000017500000000227514567450071020726 0ustar billbillFunction: _[_,_] Section: symbolic_operators Help: x[i{,j}]: i coefficient of a vector, i,j coefficient of a matrix 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) (vecvecsmall,small):vecsmall gel($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: _safecoeff Section: symbolic_operators Help: safe version of x[a], x[,a] and x[a,b]. Must be lvalues. Description: (vecsmall,small):small *safeel($1, $2) (list,small):gen:copy *safelistel($1, $2) (gen,small):gen:copy *safegel($1, $2) (gen,small,small):gen:copy *safegcoeff($1, $2, $3) Function: _[_,] Section: 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.17.2/src/functions/symbolic_operators/not0000644000175000017500000000030414567450071020433 0ustar billbillFunction: !_ Help: !a: boolean operator "not". Section: symbolic_operators C-Name: gnot Prototype: G Description: (negbool):bool:parens $1 (bool):negbool:parens $1 pari-2.17.2/src/functions/symbolic_operators/le0000644000175000017500000000151614557721031020235 0ustar billbillFunction: _<=_ Help: x<=y: return 1 if x is less or equal to y, 0 otherwise. Section: symbolic_operators C-Name: gle Prototype: GG Description: (small, small):bool:parens $(1) <= $(2) (small, lg):bool:parens $(1) < $(2) (lg, lg):bool:parens $(1) <= $(2) (small, int):bool:parens cmpsi($1, $2) <= 0 (int, lg):bool:parens cmpis($1, $2) < 0 (int, small):bool:parens cmpis($1, $2) <= 0 (int, int):bool:parens cmpii($1, $2) <= 0 (mp, mp):bool:parens mpcmp($1, $2) <= 0 (str, str):bool:parens strcmp($1, $2) <= 0 (small, gen):bool:parens gcmpsg($1, $2) <= 0 (gen, small):bool:parens gcmpgs($1, $2) <= 0 (gen, gen):bool:parens gcmp($1, $2) <= 0 pari-2.17.2/src/functions/symbolic_operators/dive0000644000175000017500000000134613637407207020571 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.17.2/src/functions/symbolic_operators/trans0000644000175000017500000000030613637407207020764 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.17.2/src/functions/symbolic_operators/and0000644000175000017500000000025714567450071020404 0ustar billbillFunction: _&&_ C-Name: andpari Prototype: GE Help: a&&b: boolean operator "and". Section: symbolic_operators Description: (bool, bool):bool:parens $(1) && $(2) pari-2.17.2/src/functions/symbolic_operators/mode0000644000175000017500000000073413637407207020566 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.17.2/src/functions/symbolic_operators/pl0000644000175000017500000000050314567450071020247 0ustar billbillFunction: +_ Help: +_: copy and return its argument 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.17.2/src/functions/symbolic_operators/pound0000644000175000017500000000067014676526175021000 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) Function: #_~ Section: symbolic_operators C-Name: gtranslength Prototype: lG Help: #x~: number of non code words in x~ Description: (gen):small gtranslength($1) pari-2.17.2/src/functions/symbolic_operators/call0000644000175000017500000000047014567450071020552 0ustar billbillFunction: _(_) Section: symbolic_operators Help: f(a,b,...): evaluate 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.17.2/src/functions/symbolic_operators/divrounde0000644000175000017500000000052113637407207021633 0ustar billbillFunction: _\/=_ Section: symbolic_operators C-Name: gdivrounde Prototype: &G Help: x\/=y: shortcut for x=x\/y. Description: (*int, int):int:parens $1 = gdivround($1, $2) (*pol, gen):gen:parens $1 = gdivround($1, $2) (*gen, gen):gen:parens $1 = gdivround($1, $2) pari-2.17.2/src/functions/symbolic_operators/mm0000644000175000017500000000102314567450071020243 0ustar billbillFunction: _-- Section: symbolic_operators C-Name: gsub1e Prototype: & Help: x--: set x to x-1. 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.17.2/src/functions/symbolic_operators/lt0000644000175000017500000000141214557721031020247 0ustar billbillFunction: _<_ Help: x= 0, binomial(n, k)); @eprog The argument $k$ may be omitted if $n$ is a nonnegative integer; in this case, return the vector with $n+1$ components whose $k+1$-th entry is \kbd{binomial}$(n,k)$ \bprog ? binomial(4) %4 = [1, 4, 6, 4, 1] @eprog pari-2.17.2/src/functions/combinatorics/eulerpol0000644000175000017500000000056214676526175020417 0ustar billbillFunction: eulerpol Section: combinatorics C-Name: eulerpol Prototype: LDn Help: eulerpol(n,{v='x}): Euler polynomial E_n, in variable v. Doc: \idx{Euler polynomial} $E_{n}$ in variable $v$ defined by $$ \sum_{n=0}^{\infty} E_{n}(x)\dfrac{T^{n}}{n!} = \dfrac{2e^{xT}}{e^{T}+1}. $$ \bprog ? eulerpol(1) %1 = x - 1/2 ? eulerpol(3) %2 = x^3 - 3/2*x^2 + 1/4 @eprog pari-2.17.2/src/functions/combinatorics/bernfrac0000644000175000017500000000115714676526175020353 0ustar billbillFunction: bernfrac Section: combinatorics C-Name: bernfrac Prototype: L Help: bernfrac(n): Bernoulli number B_n, as a rational number. Doc: Bernoulli number\sidx{Bernoulli numbers} $B_{n}$, where $B_{0}=1$, $B_{1}=-1/2$, $B_{2}=1/6$,\dots, expressed as a rational number. The argument $n$ should be a nonnegative integer. The function \tet{bernvec} creates a cache of successive Bernoulli numbers which greatly speeds up later calls to \kbd{bernfrac}: \bprog ? bernfrac(20000); time = 107 ms. ? bernvec(10000); \\ cache B_0, B_2, ..., B_20000 time = 35,957 ms. ? bernfrac(20000); \\ now instantaneous ? @eprog pari-2.17.2/src/functions/combinatorics/bernpol0000644000175000017500000000153314676526175020230 0ustar billbillFunction: bernpol Section: combinatorics C-Name: bernpol_eval Prototype: LDG Help: bernpol(n,{a='x}): Bernoulli polynomial B_n, evaluated at a Doc: \idx{Bernoulli polynomial} $B_{n}$ evaluated at $a$ (\kbd{'x} by default), defined by $$ \sum_{n=0}^{\infty}B_{n}(x)\dfrac{T^{n}}{n!} = \dfrac{Te^{xT}}{e^{T}-1}. $$ \bprog ? bernpol(1) %1 = x - 1/2 ? bernpol(3) %2 = x^3 - 3/2*x^2 + 1/2*x ? bernpol(3, 2) %3 = 3 @eprog\noindent Note that evaluation at $a$ is only provided for convenience and uniformity of interface: contrary to, e.g., \kbd{polcyclo}, computing the evaluation is no faster than \bprog B = bernpol(k); subst(B, 'x, a) @eprog\noindent and the latter allows to reuse $B$ to evaluate $B_{k}$ at different values. Variant: The variant \fun{GEN}{bernpol}{long k, long v} returns the $k$-the Bernoulli polynomial in variable $v$. pari-2.17.2/src/functions/combinatorics/numbpart0000644000175000017500000000100714567450071020401 0ustar billbillFunction: numbpart Section: combinatorics 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.17.2/src/functions/combinatorics/eulerianpol0000644000175000017500000000063014676526175021103 0ustar billbillFunction: eulerianpol Section: combinatorics C-Name: eulerianpol Prototype: LDn Help: eulerianpol(n,{v='x}): Eulerian polynomial A_n, in variable v. Doc: \idx{Eulerian polynomial} $A_{n}$ in variable $v$ defined by $$ \sum_{n=0}^{\infty} A_{n}(x) \dfrac{T^{n}}{n!} = \dfrac{x-1}{x-e^{(x-1)T}}. $$ \bprog ? eulerianpol(2) %1 = x + 1 ? eulerianpol(5, 't) %2 = t^4 + 26*t^3 + 66*t^2 + 26*t + 1 @eprog pari-2.17.2/src/functions/combinatorics/permsign0000644000175000017500000000043714567450071020403 0ustar billbillFunction: permsign Section: combinatorics C-Name: permsign Prototype: lG Help: permsign(x): signature of the permutation x. Doc: given a permutation $x$ on $n$ elements, return its signature. \bprog ? p = Vecsmall([3,1,4,2,5]); ? permsign(p) %2 = -1 ? permsign(p^2) %3 = 1 @eprog pari-2.17.2/src/functions/combinatorics/numtoperm0000644000175000017500000000103014567450071020573 0ustar billbillFunction: numtoperm Section: combinatorics C-Name: numtoperm Prototype: LG Description: (small,int):vecsmall Z_to_perm($1, $2) (small,gen):vecsmall numtoperm($1, $2) Help: numtoperm(n,k): permutation number k (mod n!) of n letters (n C-integer). Doc: generates the $k$-th permutation (as a row vector of length $n$) of the numbers $1$ to $n$. The number $k$ is taken modulo $n!\,$, i.e.~inverse function of \tet{permtonum}. The numbering used is the standard lexicographic ordering, starting at $0$. pari-2.17.2/src/functions/combinatorics/eulerfrac0000644000175000017500000000100214676526175020526 0ustar billbillFunction: eulerfrac Section: combinatorics C-Name: eulerfrac Prototype: L Help: eulerfrac(n): Euler number E_n, as a rational number. Doc: Euler number\sidx{Euler numbers} $E_{n}$, where $E_{0}=1$, $E_{1}=0$, $E_{2}=-1$, \dots, are integers such that $$ \dfrac{1}{\cosh t} = \sum_{n\geq 0} \dfrac{E_{n}}{n!} t^{n}. $$ The argument $n$ should be a nonnegative integer. \bprog ? vector(10,i,eulerfrac(i)) %1 = [0, -1, 0, 5, 0, -61, 0, 1385, 0, -50521] ? eulerfrac(20000); ? sizedigit(%)) %3 = 73416 @eprog pari-2.17.2/src/functions/combinatorics/harmonic0000644000175000017500000000166314676526175020373 0ustar billbillFunction: harmonic Section: combinatorics C-Name: harmonic0 Prototype: UDG Help: harmonic(n,{r=1}): generalized harmonic number of index n in power r. Doc: generalized harmonic number of index $n \geq 0$ in power $r$, as a rational number. If $r = 1$ (or omitted), this is the harmonic number $$ H_{n} = \sum_{i = 1}^{n} \dfrac{1}{i}.$$ In general, this is $$ H_{n,r} = \sum_{i = 1}^{n} \dfrac{1}{i^{r}}.$$ The function runs in time $\tilde{O}(r n)$, essentially linear in the size of the output. \bprog ? harmonic(0) %1 = 0 ? harmonic(1) %2 = 1 ? harmonic(10) %3 = 7381/2520 ? harmonic(10, 2) %4 = 1968329/1270080 ? harmonic(10, -2) %5 = 385 @eprog\noindent Note that the numerator and denominator are of order $\exp((r+o(1))n)$ and this will overflow for large $n$. To obtain $H_{n}$ as a floating point number, use $H_{n} = \kbd{psi}(n+1) + \kbd{Euler}$. Variant: Also available is \fun{GEN}{harmonic}{ulong n} for $r = 1$. pari-2.17.2/src/functions/combinatorics/stirling0000644000175000017500000000305114676526175020417 0ustar billbillFunction: stirling Section: combinatorics 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 nonnegative 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$ nonempty subsets. Note that if all $s(n,k)$ are needed, it is much faster to compute $$\sum_{k} s(n,k) x^{k} = x(x-1)\dots(x-n+1).$$ Similarly, if a large number of $S(n,k)$ are needed for the same $k$, one should use $$\sum_{n} S(n,k) x^{n} = \dfrac{x^{k}}{(1-x)\dots(1-kx)}.$$ (Should be implemented using a divide and conquer product.) Here are simple variants for $n$ fixed: \bprog /* list of s(n,k), k = 1..n */ vecstirling(n) = Vec( factorback(vector(n-1,i,1-i*'x)) ) /* list of S(n,k), k = 1..n */ vecstirling2(n) = { my(Q = x^(n-1), t); vector(n, i, t = divrem(Q, x-i); Q=t[1]; simplify(t[2])); } /* Bell numbers, B_n = B[n+1] = sum(k = 0, n, S(n,k)), n = 0..N */ vecbell(N)= { my (B = vector(N+1)); B[1] = B[2] = 1; for (n = 2, N, my (C = binomial(n-1)); B[n+1] = sum(k = 1, n, C[k]*B[k]); ); B; } @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.17.2/src/functions/combinatorics/partitions0000644000175000017500000000426514676526175020770 0ustar billbillFunction: partitions Section: combinatorics C-Name: partitions Prototype: LDGDG Help: partitions(k,{a=k},{n=k}): vector of partitions of the integer k. You can restrict the length of the partitions with parameter n (n=nmax or n=[nmin,nmax]), or the range of the parts with parameter a (a=amax or a=[amin,amax]). By default remove zeros, but one can set amin=0 to get X of fixed length nmax (=k by default). Description: (small,?gen,?gen):vecvecsmall partitions($1, $2, $3) Doc: returns the vector of partitions of the integer $k$ as a sum of positive integers (parts); for $k < 0$, it returns the empty set \kbd{[]}, and for $k = 0$ the trivial partition (no parts). A partition is given by a \typ{VECSMALL}, where parts are sorted in nondecreasing order: \bprog ? partitions(3) %1 = [Vecsmall([3]), Vecsmall([1, 2]), Vecsmall([1, 1, 1])] @eprog\noindent correspond to $3$, $1+2$ and $1+1+1$. The number of (unrestricted) partitions of $k$ is given by \tet{numbpart}: \bprog ? #partitions(50) %1 = 204226 ? numbpart(50) %2 = 204226 @eprog \noindent Optional parameters $n$ and $a$ are as follows: \item $n=\var{nmax}$ (resp. $n=[\var{nmin},\var{nmax}]$) restricts partitions to length less than $\var{nmax}$ (resp. length between $\var{nmin}$ and $nmax$), where the \emph{length} is the number of nonzero entries. \item $a=\var{amax}$ (resp. $a=[\var{amin},\var{amax}]$) restricts the parts to integers less than $\var{amax}$ (resp. between $\var{amin}$ and $\var{amax}$). \bprog ? partitions(4, 2) \\ parts bounded by 2 %1 = [Vecsmall([2, 2]), Vecsmall([1, 1, 2]), Vecsmall([1, 1, 1, 1])] ? partitions(4,, 2) \\ at most 2 parts %2 = [Vecsmall([4]), Vecsmall([1, 3]), Vecsmall([2, 2])] ? partitions(4,[0,3], 2) \\ at most 2 parts %3 = [Vecsmall([1,3]), Vecsmall([2,2])] @eprog\noindent By default, parts are positive and we remove zero entries unless $amin\leq0$, in which case $nmin$ is ignored and we fix $\#X = \var{nmax}$: \bprog ? partitions(4, [0,3]) \\ parts between 0 and 3 %1 = [Vecsmall([0, 0, 1, 3]), Vecsmall([0, 0, 2, 2]),\ Vecsmall([0, 1, 1, 2]), Vecsmall([1, 1, 1, 1])] ? partitions(1, [0,3], [2,4]) \\ no partition with 2 to 4 nonzero parts %2 = [] @eprog pari-2.17.2/src/functions/combinatorics/fibonacci0000644000175000017500000000023514567450071020470 0ustar billbillFunction: fibonacci Section: combinatorics C-Name: fibo Prototype: L Help: fibonacci(x): Fibonacci number of index x. Doc: $x^{\text{th}}$ Fibonacci number. pari-2.17.2/src/functions/combinatorics/bernreal0000644000175000017500000000106614676526175020362 0ustar billbillFunction: bernreal Section: combinatorics C-Name: bernreal Prototype: Lp Help: bernreal(n): Bernoulli number B_n, as a real number with the current precision. Doc: Bernoulli number\sidx{Bernoulli numbers} $B_{n}$, as \kbd{bernfrac}, but $B_{n}$ is returned as a real number (with the current precision). The argument $n$ should be a nonnegative integer. The function slows down as the precision increases: \bprog ? \p1000 ? bernreal(200000); time = 5 ms. ? \p10000 ? bernreal(200000); time = 18 ms. ? \p100000 ? bernreal(200000); time = 84 ms. @eprog pari-2.17.2/src/functions/member_functions/0000755000175000017500000000000014760315601017325 5ustar billbillpari-2.17.2/src/functions/member_functions/b80000644000175000017500000000021013637407207017560 0ustar billbillFunction: _.b8 Section: member_functions C-Name: member_b8 Prototype: mG Help: _.b8 Description: (ell):gen:copy ell_get_b8($1) pari-2.17.2/src/functions/member_functions/eta0000644000175000017500000000012713637407207020027 0ustar billbillFunction: _.eta Help: _.eta Section: member_functions C-Name: member_eta Prototype: mG pari-2.17.2/src/functions/member_functions/nf0000644000175000017500000000026013637407207017657 0ustar billbillFunction: _.nf Help: _.nf Section: member_functions C-Name: member_nf Prototype: mG Description: (nf):nf:parens $1 (gen):nf:copy member_nf($1) pari-2.17.2/src/functions/member_functions/a20000644000175000017500000000021013637407207017551 0ustar billbillFunction: _.a2 Section: member_functions C-Name: member_a2 Prototype: mG Help: _.a2 Description: (ell):gen:copy ell_get_a2($1) pari-2.17.2/src/functions/member_functions/clgp0000644000175000017500000000041213637407207020200 0ustar billbillFunction: _.clgp Help: _.clgp Section: member_functions C-Name: member_clgp Prototype: mG Description: (bnf):clgp:copy:parens $clgp:1 (bnr):clgp:copy:parens $clgp:1 (clgp):clgp:parens $1 (gen):clgp:copy member_clgp($1) pari-2.17.2/src/functions/member_functions/pol0000644000175000017500000000036213637407207020051 0ustar billbillFunction: _.pol Help: _.pol Section: member_functions C-Name: member_pol Prototype: mG Description: (gal):gen:copy gal_get_pol($1) (nf):gen:copy nf_get_pol($1) (gen):gen:copy member_pol($1) pari-2.17.2/src/functions/member_functions/r20000644000175000017500000000027513637407207017605 0ustar billbillFunction: _.r2 Section: member_functions C-Name: member_r2 Prototype: mG Help: _.r2 Description: (nf):small nf_get_r2($1) (gen):int:copy member_r2($1) pari-2.17.2/src/functions/member_functions/e0000644000175000017500000000020013637407207017472 0ustar billbillFunction: _.e Help: _.e Section: member_functions C-Name: member_e Prototype: mG Description: (prid):small pr_get_e($1) pari-2.17.2/src/functions/member_functions/tate0000644000175000017500000000013213637407207020207 0ustar billbillFunction: _.tate Help: _.tate Section: member_functions C-Name: member_tate Prototype: mG pari-2.17.2/src/functions/member_functions/a10000644000175000017500000000021013637407207017550 0ustar billbillFunction: _.a1 Section: member_functions C-Name: member_a1 Prototype: mG Help: _.a1 Description: (ell):gen:copy ell_get_a1($1) pari-2.17.2/src/functions/member_functions/a30000644000175000017500000000021013637407207017552 0ustar billbillFunction: _.a3 Section: member_functions C-Name: member_a3 Prototype: mG Help: _.a3 Description: (ell):gen:copy ell_get_a3($1) pari-2.17.2/src/functions/member_functions/tu0000644000175000017500000000020513637407207017703 0ustar billbillFunction: _.tu Help: _.tu Section: member_functions C-Name: member_tu Prototype: G Description: (gen):gen:copy member_tu($1) pari-2.17.2/src/functions/member_functions/disc0000644000175000017500000000037113637407207020201 0ustar billbillFunction: _.disc Section: member_functions C-Name: member_disc Prototype: mG Help: _.disc Description: (nf):int:copy nf_get_disc($1) (ell):gen:copy ell_get_disc($1) (gen):gen:copy member_disc($1) pari-2.17.2/src/functions/member_functions/codiff0000644000175000017500000000014013637407207020503 0ustar billbillFunction: _.codiff Help: _.codiff Section: member_functions C-Name: member_codiff Prototype: mG pari-2.17.2/src/functions/member_functions/c40000644000175000017500000000021013637407207017555 0ustar billbillFunction: _.c4 Section: member_functions C-Name: member_c4 Prototype: mG Help: _.c4 Description: (ell):gen:copy ell_get_c4($1) pari-2.17.2/src/functions/member_functions/cyc0000644000175000017500000000043613637407207020037 0ustar billbillFunction: _.cyc Help: _.cyc Section: member_functions C-Name: member_cyc Prototype: mG Description: (bnr):vec:copy bnr_get_cyc($1) (bnf):vec:copy bnf_get_cyc($1) (clgp):vec:copy gel($1, 2) (gen):vec:copy member_cyc($1) pari-2.17.2/src/functions/member_functions/diff0000644000175000017500000000030713637407207020166 0ustar billbillFunction: _.diff Help: _.diff Section: member_functions C-Name: member_diff Prototype: mG Description: (nf):gen:copy nf_get_diff($1) (gen):gen:copy member_diff($1) pari-2.17.2/src/functions/member_functions/a60000644000175000017500000000021113637407207017556 0ustar billbillFunction: _.a6 Section: member_functions C-Name: member_a6 Prototype: mG Help: _.a6 Description: (ell):gen:copy ell_get_a6($1) pari-2.17.2/src/functions/member_functions/fu0000644000175000017500000000055014567450071017670 0ustar billbillFunction: _.fu Help: _.fu Section: member_functions C-Name: member_fu Prototype: G Description: (bnr):void $"ray units not implemented" (bnf):gen:copy bnf_get_fu($1) (gen):gen member_fu($1) Function: _chinese_unit_worker C-Name: chinese_unit_worker Prototype: GGGGGG Section: programming/internals Help: worker for _.fu pari-2.17.2/src/functions/member_functions/c60000644000175000017500000000021013637407207017557 0ustar billbillFunction: _.c6 Section: member_functions C-Name: member_c6 Prototype: mG Help: _.c6 Description: (ell):gen:copy ell_get_c6($1) pari-2.17.2/src/functions/member_functions/zk0000644000175000017500000000025313637407207017702 0ustar billbillFunction: _.zk Help: _.zk Section: member_functions C-Name: member_zk Prototype: mG Description: (nf):vec:copy nf_get_zk($1) (gen):vec:copy member_zk($1) pari-2.17.2/src/functions/member_functions/omega0000644000175000017500000000013513637407207020345 0ustar billbillFunction: _.omega Help: _.omega Section: member_functions C-Name: member_omega Prototype: mG pari-2.17.2/src/functions/member_functions/mod0000644000175000017500000000012713637407207020035 0ustar billbillFunction: _.mod Help: _.mod Section: member_functions C-Name: member_mod Prototype: mG pari-2.17.2/src/functions/member_functions/b60000644000175000017500000000021713637407207017565 0ustar billbillFunction: _.b6 Section: member_functions C-Name: member_b6 Prototype: mG Help: _.b6 Description: (ell):gen:copy ell_get_b6($1) pari-2.17.2/src/functions/member_functions/bnf0000644000175000017500000000033513637407207020024 0ustar billbillFunction: _.bnf Help: _.bnf Section: member_functions C-Name: member_bnf Prototype: mG Description: (bnf):bnf:parens $1 (bnr):bnf:copy:parens $bnf:1 (gen):bnf:copy member_bnf($1) pari-2.17.2/src/functions/member_functions/b20000644000175000017500000000021113637407207017553 0ustar billbillFunction: _.b2 Section: member_functions C-Name: member_b2 Prototype: mG Help: _.b2 Description: (ell):gen:copy ell_get_b2($1) pari-2.17.2/src/functions/member_functions/j0000644000175000017500000000020413637407207017503 0ustar billbillFunction: _.j Section: member_functions C-Name: member_j Prototype: mG Help: _.j Description: (ell):gen:copy ell_get_j($1) pari-2.17.2/src/functions/member_functions/sign0000644000175000017500000000030213637407207020211 0ustar billbillFunction: _.sign Help: _.sign Section: member_functions C-Name: member_sign Prototype: mG Description: (nf):vec:copy gel($1, 2) (gen):vec:copy member_sign($1) pari-2.17.2/src/functions/member_functions/roots0000644000175000017500000000037614557721031020426 0ustar billbillFunction: _.roots Section: member_functions C-Name: member_roots Prototype: mG Help: _.roots Description: (gal):vec:copy gal_get_roots($1) (nf):vec:copy nf_get_roots($1) (gen):vec:copy member_roots($1) pari-2.17.2/src/functions/member_functions/t20000644000175000017500000000021613637407207017602 0ustar billbillFunction: _.t2 Help: _.t2 Section: member_functions C-Name: member_t2 Prototype: G Description: (gen):vec member_t2($1) pari-2.17.2/src/functions/member_functions/gen0000644000175000017500000000051714567450071020032 0ustar billbillFunction: _.gen Help: _.gen Section: member_functions C-Name: member_gen Prototype: mG Description: (bnr):vec:copy bnr_get_gen($1) (bnf):vec:copy bnf_get_gen($1) (gal):vecvecsmall:copy gal_get_gen($1) (clgp):vec:copy gel($1, 3) (prid):gen:copy pr_get_gen($1) (gen):gen:copy member_gen($1) pari-2.17.2/src/functions/member_functions/zkst0000644000175000017500000000021613637407207020250 0ustar billbillFunction: _.zkst Help: _.zkst Section: member_functions C-Name: member_zkst Prototype: mG Description: (bnr):gen:copy bnr_get_bid($1) pari-2.17.2/src/functions/member_functions/f0000644000175000017500000000017713637407207017510 0ustar billbillFunction: _.f Help: _.f Section: member_functions C-Name: member_f Prototype: mG Description: (prid):small pr_get_f($1) pari-2.17.2/src/functions/member_functions/b40000644000175000017500000000021013637407207017554 0ustar billbillFunction: _.b4 Section: member_functions C-Name: member_b4 Prototype: mG Help: _.b4 Description: (ell):gen:copy ell_get_b4($1) pari-2.17.2/src/functions/member_functions/reg0000644000175000017500000000035413637407207020035 0ustar billbillFunction: _.reg Help: _.reg Section: member_functions C-Name: member_reg Prototype: mG Description: (bnr):real $"ray regulator not implemented" (bnf):real:copy bnf_get_reg($1) (gen):real:copy member_reg($1) pari-2.17.2/src/functions/member_functions/normfu0000644000175000017500000000014014676526175020571 0ustar billbillFunction: _.normfu Help: _.normfu Section: member_functions C-Name: member_normfu Prototype: mG pari-2.17.2/src/functions/member_functions/r10000644000175000017500000000027513637407207017604 0ustar billbillFunction: _.r1 Section: member_functions C-Name: member_r1 Prototype: mG Help: _.r1 Description: (nf):small nf_get_r1($1) (gen):int:copy member_r1($1) pari-2.17.2/src/functions/member_functions/polabs0000644000175000017500000000014014567450071020531 0ustar billbillFunction: _.polabs Help: _.polabs Section: member_functions C-Name: member_polabs Prototype: mG pari-2.17.2/src/functions/member_functions/area0000644000175000017500000000013214557721031020156 0ustar billbillFunction: _.area Help: _.area Section: member_functions C-Name: member_area Prototype: mG pari-2.17.2/src/functions/member_functions/bid0000644000175000017500000000030313637407207020010 0ustar billbillFunction: _.bid Section: member_functions C-Name: member_bid Prototype: mG Help: _.bid Description: (bnr):gen:copy bnr_get_bid($1) (gen):gen:copy member_bid($1) pari-2.17.2/src/functions/member_functions/p0000644000175000017500000000034613637407207017520 0ustar billbillFunction: _.p Help: _.p Section: member_functions C-Name: member_p Prototype: mG Description: (gal):int:copy gal_get_p($1) (prid):int:copy pr_get_p($1) (gen):int:copy member_p($1) pari-2.17.2/src/functions/member_functions/index0000644000175000017500000000031413637407207020363 0ustar billbillFunction: _.index Section: member_functions C-Name: member_index Prototype: mG Help: _.index Description: (nf):int:copy nf_get_index($1) (gen):int:copy member_index($1) pari-2.17.2/src/functions/member_functions/no0000644000175000017500000000043013637407207017667 0ustar billbillFunction: _.no Help: _.no Section: member_functions C-Name: member_no Prototype: mG Description: (bnr):int:copy bnr_get_no($1) (bnf):int:copy bnf_get_no($1) (clgp):int:copy gel($1, 1) (gen):int:copy member_no($1) pari-2.17.2/src/functions/member_functions/a40000644000175000017500000000021013637407207017553 0ustar billbillFunction: _.a4 Section: member_functions C-Name: member_a4 Prototype: mG Help: _.a4 Description: (ell):gen:copy ell_get_a4($1) pari-2.17.2/src/functions/member_functions/orders0000644000175000017500000000022713637407207020555 0ustar billbillFunction: _.orders Help: _.orders Section: member_functions C-Name: member_orders Prototype: mG Description: (gal):vecsmall:copy gal_get_orders($1) pari-2.17.2/src/functions/member_functions/group0000644000175000017500000000031314567450071020407 0ustar billbillFunction: _.group Help: _.group Section: member_functions C-Name: member_group Prototype: mG Description: (gal):vecvecsmall:copy gal_get_group($1) (gen):vecvecsmall:copy member_group($1) pari-2.17.2/src/functions/polynomials/0000755000175000017500000000000014760315601016334 5ustar billbillpari-2.17.2/src/functions/polynomials/polsubcyclofast0000644000175000017500000000442514676526175021520 0ustar billbillFunction: polsubcyclofast Section: polynomials C-Name: polsubcyclofast Prototype: GLD0,L,D0,L, Help: polsubcyclofast(n,d,{s=0},{exact=0}): If 1 <= d <= 6 or a prime, finds an equation for the subfields of Q(zeta_n) with galois group C_d. Contrary to polsubcyclo, the output is always a (possibly empty) vector of polynomials. If s = 0 (default) all signatures, otherwise s = 1 (resp., -1) for totally real (resp., totally complex). Set exact = 1 for subfields of exact conductor n. Doc: If $1 \leq d\leq 6$ or a prime, finds an equation for the subfields of $\Q(\zeta_{n})$ with Galois group $C_{d}$; the special value $d = -4$ provides the subfields with group $V_{4}=C_{2}\times C_{2}$. Contrary to \kbd{polsubcyclo}, the output is always a (possibly empty) vector of polynomials. If $s = 0$ (default) all signatures, otherwise $s = 1$ (resp., $-1$) for totally real (resp., totally complex). Set \kbd{exact = 1} for subfields of conductor $n$. The argument $n$ can be given as in arithmetic functions: as an integer, as a factorization matrix, or (preferred) as a pair $[N, \kbd{factor}(N)]$. \misctitle{Comparison with \kbd{polsubcyclo}} First \kbd{polsubcyclofast} does not usually return Gaussian periods, but ad hoc polynomials which do generate the same field. Roughly speaking (ignoring logarithmic factors), the complexity of \kbd{polsubcyclo} is independent of $d$ and the complexity of \kbd{polsubcyclofast} is independent of $n$. Ignoring logarithmic factors, \kbd{polsubcylo} runs in time $O(n)$ and \kbd{polsubcyclofast} in time $O(d^{4})$. So the latter is \emph{much} faster than \kbd{polsubcyclo} if $n$ is large, but gets slower as $d$ increases and becomes unusable for $d \geq 40$ or so. \bprog ? polsubcyclo(10^7+19,7); time = 1,852 ms. ? polsubcyclofast(10^7+19,7); time = 15 ms. ? polsubcyclo(10^17+21,5); \\ won't finish *** polsubcyclo: user interrupt after 2h ? polsubcyclofast(10^17+21,5); time = 3 ms. ? polsubcyclofast(10^17+3,7); time = 26 ms. ? polsubcyclo(10^6+117,13); time = 193 ms. ? polsubcyclofast(10^6+117,13); time = 50 ms. ? polsubcyclofast(10^6+199,19); time = 202 ms. ? polsubcyclo(10^6+199,19); \\ about as fast time = 3191ms. ? polsubcyclo(10^7+271,19); time = 2,067 ms. ? polsubcyclofast(10^7+271,19); time = 201 ms. @eprog pari-2.17.2/src/functions/polynomials/poldegree0000644000175000017500000000134314567450071020234 0ustar billbillFunction: poldegree Section: polynomials C-Name: gppoldegree Prototype: GDn Help: poldegree(x,{v}): degree of the polynomial or rational function x with respect to main variable if v is omitted, with respect to v otherwise. For scalar x, return 0 if x is nonzero and -oo otherwise. Doc: degree of the polynomial $x$ in the main variable if $v$ is omitted, in the variable $v$ otherwise. The degree of $0$ is \kbd{-oo}. The degree of a nonzero scalar is $0$. Finally, when $x$ is a nonzero polynomial or rational function, returns the ordinary degree of $x$. Raise an error otherwise. Variant: Also available is \fun{long}{poldegree}{GEN x, long v}, which returns \tet{-LONG_MAX} if $x = 0$ and the degree as a \kbd{long} integer. pari-2.17.2/src/functions/polynomials/polmodular0000644000175000017500000000325214676526175020457 0ustar billbillFunction: polmodular Section: polynomials C-Name: polmodular Prototype: LD0,L,DGDnD0,L, Help: polmodular(L,{inv=0},{x='x},{y='y},{derivs=0}): return the modular polynomial of level L and invariant inv. Doc: Return the modular polynomial of prime level $L$ in variables $x$ and $y$ for the modular function specified by \kbd{inv}. If \kbd{inv} is 0 (the default), use the modular $j$ function, if \kbd{inv} is 1 use the Weber-$f$ function, and if \kbd{inv} is 5 use $\gamma_{2} = \sqrt[3]{j}$. See \kbd{polclass} for the full list of invariants. If $x$ is given as \kbd{Mod(j, p)} or an element $j$ of a finite field (as a \typ{FFELT}), then return the modular polynomial of level $L$ evaluated at $j$. If $j$ is from a finite field and \kbd{derivs} is nonzero, then return a triple where the last two elements are the first and second derivatives of the modular polynomial evaluated at $j$. \bprog ? polmodular(3) %1 = x^4 + (-y^3 + 2232*y^2 - 1069956*y + 36864000)*x^3 + ... ? polmodular(7, 1, , 'J) %2 = x^8 - J^7*x^7 + 7*J^4*x^4 - 8*J*x + J^8 ? polmodular(7, 5, 7*ffgen(19)^0, 'j) %3 = j^8 + 4*j^7 + 4*j^6 + 8*j^5 + j^4 + 12*j^2 + 18*j + 18 ? polmodular(7, 5, Mod(7,19), 'j) %4 = Mod(1, 19)*j^8 + Mod(4, 19)*j^7 + Mod(4, 19)*j^6 + ... ? u = ffgen(5)^0; T = polmodular(3,0,,'j)*u; ? polmodular(3, 0, u,'j,1) %6 = [j^4 + 3*j^2 + 4*j + 1, 3*j^2 + 2*j + 4, 3*j^3 + 4*j^2 + 4*j + 2] ? subst(T,x,u) %7 = j^4 + 3*j^2 + 4*j + 1 ? subst(T',x,u) %8 = 3*j^2 + 2*j + 4 ? subst(T'',x,u) %9 = 3*j^3 + 4*j^2 + 4*j + 2 @eprog Function: _polmodular_worker Section: programming/internals C-Name: polmodular_worker Prototype: GUGGGGLGGGG Help: used by polmodular Doc: used by polmodular pari-2.17.2/src/functions/polynomials/HEADER0000644000175000017500000000055414567450071017221 0ustar billbillFunction: _header_polynomials Class: header Section: polynomials Doc: \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. pari-2.17.2/src/functions/polynomials/polcyclo0000644000175000017500000000161214676526175020123 0ustar billbillFunction: polcyclo Section: polynomials C-Name: polcyclo_eval Prototype: LDG Help: polcyclo(n,{a = 'x}): n-th cyclotomic polynomial evaluated at a. Description: (small,?var):gen polcyclo($1,$2) (small,gen):gen polcyclo_eval($1,$2) Doc: $n$-th cyclotomic polynomial, evaluated at $a$ (\kbd{'x} by default). The integer $n$ must be positive. Algorithm used: reduce to the case where $n$ is squarefree; to compute the cyclotomic polynomial, use $\Phi_{np}(x)=\Phi_{n}(x^{p})/\Phi(x)$; to compute it evaluated, use $\Phi_{n}(x) = \prod_{d\mid n} (x^{d}-1)^{\mu(n/d)}$. In the evaluated case, the algorithm assumes that $a^{d} - 1$ is either $0$ or invertible, for all $d\mid n$. If this is not the case (the base ring has zero divisors), use \kbd{subst(polcyclo(n),x,a)}. Variant: The variant \fun{GEN}{polcyclo}{long n, long v} returns the $n$-th cyclotomic polynomial in variable $v$. pari-2.17.2/src/functions/polynomials/bezoutres0000644000175000017500000000032714567450071020311 0ustar billbillFunction: bezoutres Section: polynomials C-Name: polresultantext0 Prototype: GGDn Obsolete: 2015-01-13 Help: bezoutres(A,B,{v}): deprecated alias for polresultantext. Doc: deprecated alias for \kbd{polresultantext} pari-2.17.2/src/functions/polynomials/polsym0000644000175000017500000000043513637407207017612 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.17.2/src/functions/polynomials/polrootsbound0000644000175000017500000000222414676526175021210 0ustar billbillFunction: polrootsbound Section: polynomials C-Name: polrootsbound Prototype: GDG Help: polrootsbound(T,{tau=0.01}): return a sharp upper bound for the modulus of the largest complex root of the polynomial T with relative error tau. Doc: return a sharp upper bound $B$ for the modulus of the largest complex root of the polynomial $T$ with complex coefficients with relative error $\tau$. More precisely, we have $|z| \leq B$ for all roots and there exist one root such that $|z_{0}| \geq B \exp(-2\tau)$. Much faster than either polroots or polrootsreal. \bprog ? T=poltchebi(500); ? vecmax(abs(polroots(T))) time = 5,706 ms. %2 = 0.99999506520185816611184481744870013191 ? vecmax(abs(polrootsreal(T))) time = 1,972 ms. %3 = 0.99999506520185816611184481744870013191 ? polrootsbound(T) time = 217 ms. %4 = 1.0098792554165905155 ? polrootsbound(T, log(2)/2) \\ allow a factor 2, much faster time = 51 ms. %5 = 1.4065759938190154354 ? polrootsbound(T, 1e-4) time = 504 ms. %6 = 1.0000920717983847741 ? polrootsbound(T, 1e-6) time = 810 ms. %7 = 0.9999960628901692905 ? polrootsbound(T, 1e-10) time = 1,351 ms. %8 = 0.9999950652993869760 @eprog pari-2.17.2/src/functions/polynomials/taylor0000644000175000017500000000130014676526175017603 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.17.2/src/functions/polynomials/poldisc0000644000175000017500000000137114567450071017724 0ustar billbillFunction: poldisc Section: polynomials C-Name: poldisc0 Prototype: GDn Help: poldisc(pol,{v}): discriminant of the polynomial pol, with respect to main variable if v is omitted, with respect to v otherwise. Description: (gen):gen poldisc0($1, -1) (gen, var):gen poldisc0($1, $2) Doc: discriminant of the polynomial \var{pol} in the main variable if $v$ is omitted, in $v$ otherwise. Uses a modular algorithm over $\Z$ or $\Q$, and the \idx{subresultant algorithm} otherwise. \bprog ? T = x^4 + 2*x+1; ? poldisc(T) %2 = -176 ? poldisc(T^2) %3 = 0 @eprog For convenience, the function also applies to types \typ{QUAD} and \typ{QFB}: \bprog ? z = 3*quadgen(8) + 4; ? poldisc(z) %2 = 8 ? q = Qfb(1,2,3); ? poldisc(q) %4 = -8 @eprog pari-2.17.2/src/functions/polynomials/factorpadic0000644000175000017500000000273114676526175020561 0ustar billbillFunction: factorpadic Section: polynomials C-Name: factorpadic Prototype: GGL Help: factorpadic(pol,p,r): p-adic factorization of the polynomial pol to precision r. Doc: $p$-adic factorization of the polynomial \var{pol} to precision $r$, the result being a two-column matrix as in \kbd{factor}. Note that this is not the same as a factorization over $\Z/p^{r}\Z$ (polynomials over that ring do not form a unique factorization domain, anyway), but approximations in $\Q/p^{r}\Z$ of the true factorization in $\Q_{p}[X]$. \bprog ? factorpadic(x^2 + 9, 3,5) %1 = [(1 + O(3^5))*x^2 + O(3^5)*x + (3^2 + O(3^5)) 1] ? factorpadic(x^2 + 1, 5,3) %2 = [ (1 + O(5^3))*x + (2 + 5 + 2*5^2 + O(5^3)) 1] [(1 + O(5^3))*x + (3 + 3*5 + 2*5^2 + O(5^3)) 1] @eprog\noindent The factors are normalized so that their leading coefficient is a power of $p$. The method used is a modified version of the \idx{round 4} algorithm of \idx{Zassenhaus}. If \var{pol} has inexact \typ{PADIC} coefficients, this is not always well-defined; in this case, the polynomial is first made integral by dividing out the $p$-adic content, then lifted to $\Z$ using \tet{truncate} coefficientwise. Hence we actually factor exactly a polynomial which is only $p$-adically close to the input. To avoid pitfalls, we advise to only factor polynomials with exact rational coefficients. \synt{factorpadic}{GEN f,GEN p, long r} . The function \kbd{factorpadic0} is deprecated, provided for backward compatibility. pari-2.17.2/src/functions/polynomials/deriv0000644000175000017500000000300714567450071017376 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$; and also use $x''$, etc., for multiple derivatives altough \kbd{derivn} is often preferrable. 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$. \bprog ? f = (x/y)^5; ? deriv(f) %2 = 5/y^5*x^4 ? f' %3 = 5/y^5*x^4 ? deriv(f, 'x) \\ same since 'x is the main variable %4 = 5/y^5*x^4 ? deriv(f, 'y) %5 = -5/y^6*x^5 @eprog This function also operates on closures, in which case the variable must be omitted. It returns a closure performing a numerical differentiation as per \kbd{derivnum}: \bprog ? f(x) = x^2; ? g = deriv(f) ? g(1) %3 = 2.0000000000000000000000000000000000000 ? f(x) = sin(exp(x)); ? deriv(f)(0) %5 = 0.54030230586813971740093660744297660373 ? cos(1) %6 = 0.54030230586813971740093660744297660373 @eprog pari-2.17.2/src/functions/polynomials/pollead0000644000175000017500000000114214567450071017703 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_coeff($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.17.2/src/functions/polynomials/polgraeffe0000644000175000017500000000037514676526175020416 0ustar billbillFunction: polgraeffe Section: polynomials C-Name: polgraeffe Prototype: G Help: polgraeffe(f): returns the Graeffe transform g of f, such that g(x^2) = f(x)f(-x). Doc: returns the \idx{Graeffe} transform $g$ of $f$, such that $g(x^{2}) = f(x) f(-x)$. pari-2.17.2/src/functions/polynomials/polclass0000644000175000017500000001052714676526175020124 0ustar billbillFunction: polclass Section: polynomials C-Name: polclass Prototype: GD0,L,Dn Help: polclass(D,{inv=0},{x='x}): return a polynomial generating the Hilbert class field of Q(sqrt(D)) for the discriminant D<0. Doc: Return a polynomial in $\Z[x]$ generating the Hilbert class field for the imaginary quadratic discriminant $D$. If $inv$ is 0 (the default), use the modular $j$-function and return the classical Hilbert polynomial, otherwise use a class invariant. The following invariants correspond to the different values of $inv$, where $f$ denotes Weber's function \kbd{weber}, and $w_{p,q}$ the double eta quotient given by $w_{p,q} = \dfrac{ \eta(x/p)\*\eta(x/q) }{ \eta(x)\*\eta(x/{pq}) }$ The invariants $w_{p,q}$ are not allowed unless they satisfy the following technical conditions ensuring they do generate the Hilbert class field and not a strict subfield: \item if $p\neq q$, we need them both noninert, prime to the conductor of $\Z[\sqrt{D}]$. Let $P, Q$ be prime ideals above $p$ and $q$; if both are unramified, we further require that $P^{\pm 1} Q^{\pm 1}$ be all distinct in the class group of $\Z[\sqrt{D}]$; if both are ramified, we require that $PQ \neq 1$ in the class group. \item if $p = q$, we want it split and prime to the conductor and the prime ideal above it must have order $\neq 1, 2, 4$ in the class group. \noindent Invariants are allowed under the additional conditions on $D$ listed below. \item 0 : $j$ \item 1 : $f$, $D = 1 \mod 8$ and $D = 1,2 \mod 3$; \item 2 : $f^{2}$, $D = 1 \mod 8$ and $D = 1,2 \mod 3$; \item 3 : $f^{3}$, $D = 1 \mod 8$; \item 4 : $f^{4}$, $D = 1 \mod 8$ and $D = 1,2 \mod 3$; \item 5 : $\gamma_{2}= j^{1/3}$, $D = 1,2 \mod 3$; \item 6 : $w_{2,3}$, $D = 1 \mod 8$ and $D = 1,2 \mod 3$; \item 8 : $f^{8}$, $D = 1 \mod 8$ and $D = 1,2 \mod 3$; \item 9 : $w_{3,3}$, $D = 1 \mod 2$ and $D = 1,2 \mod 3$; \item 10: $w_{2,5}$, $D \neq 60 \mod 80$ and $D = 1,2 \mod 3$; \item 14: $w_{2,7}$, $D = 1 \mod 8$; \item 15: $w_{3,5}$, $D = 1,2 \mod 3$; \item 21: $w_{3,7}$, $D = 1 \mod 2$ and $21$ does not divide $D$ \item 23: $w_{2,3}^{2}$, $D = 1,2 \mod 3$; \item 24: $w_{2,5}^{2}$, $D = 1,2 \mod 3$; \item 26: $w_{2,13}$, $D \neq 156 \mod 208$; \item 27: $w_{2,7}^{2}$, $D\neq 28 \mod 112$; \item 28: $w_{3,3}^{2}$, $D = 1,2 \mod 3$; \item 35: $w_{5,7}$, $D = 1,2 \mod 3$; \item 39: $w_{3,13}$, $D = 1 \mod 2$ and $D = 1,2 \mod 3$; The algorithm for computing the polynomial does not use the floating point approach, which would evaluate a precise modular function in a precise complex argument. Instead, it relies on a faster Chinese remainder based approach modulo small primes, in which the class invariant is only defined algebraically by the modular polynomial relating the modular function to $j$. So in fact, any of the several roots of the modular polynomial may actually be the class invariant, and more precise assertions cannot be made. For instance, while \kbd{polclass(D)} returns the minimal polynomial of $j(\tau)$ with $\tau$ (any) quadratic integer for the discriminant $D$, the polynomial returned by \kbd{polclass(D, 5)} can be the minimal polynomial of any of $\gamma_{2} (\tau)$, $\zeta_{3} \gamma_{2} (\tau)$ or $\zeta_{3}^{2} \gamma_{2} (\tau)$, the three roots of the modular polynomial $j = \gamma_{2}^{3}$, in which $j$ has been specialised to $j (\tau)$. The modular polynomial is given by $j = {(f^{24}-16)^{3} \over f^{24}}$ for Weber's function $f$. For the double eta quotients of level $N = p q$, all functions are covered such that the modular curve $X_{0}^{+} (N)$, the function field of which is generated by the functions invariant under $\Gamma^{0} (N)$ and the Fricke--Atkin--Lehner involution, is of genus $0$ with function field generated by (a power of) the double eta quotient $w$. This ensures that the full Hilbert class field (and not a proper subfield) is generated by class invariants from these double eta quotients. Then the modular polynomial is of degree $2$ in $j$, and of degree $\psi (N) = (p+1)(q+1)$ in $w$. \bprog ? polclass(-163) %1 = x + 262537412640768000 ? polclass(-51, , 'z) %2 = z^2 + 5541101568*z + 6262062317568 ? polclass(-151,1) x^7 - x^6 + x^5 + 3*x^3 - x^2 + 3*x + 1 @eprog Function: _polclass_worker Section: programming/internals C-Name: polclass_worker Prototype: GGG Help: used by polclass Doc: used by polclass pari-2.17.2/src/functions/polynomials/polrecip0000644000175000017500000000060514567450071020103 0ustar billbillFunction: polrecip Section: polynomials C-Name: polrecip Prototype: G Help: polrecip(pol): reciprocal polynomial of pol. Doc: reciprocal polynomial of \var{pol} with respect to its main variable, i.e.~the coefficients of the result are in reverse order; \var{pol} must be a polynomial. \bprog ? polrecip(x^2 + 2*x + 3) %1 = 3*x^2 + 2*x + 1 ? polrecip(2*x + y) %2 = y*x + 2 @eprog pari-2.17.2/src/functions/polynomials/substpol0000644000175000017500000000212114676526175020146 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.17.2/src/functions/polynomials/substvec0000644000175000017500000000167214676526175020143 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\noindent As in \kbd{subst}, variables may be replaced by a vector of values, in which case the cartesian product is returned: \bprog ? substvec([x,y], [x,y], [[1,2], 3]) %3 = [[1, 3], [2, 3]] ? substvec([x,y], [x,y], [[1,2], [3,4]]) %4 = [[1, 3], [2, 3], [1, 4], [2, 4]] @eprog pari-2.17.2/src/functions/polynomials/intformal0000644000175000017500000000256514567450071020270 0ustar billbillFunction: intformal Section: polynomials C-Name: integ Prototype: GDn Help: intformal(x,{v}): formal integration of x with respect to v, or to the main variable of x if v is omitted. Doc: \idx{formal integration} of $x$ with respect to the variable $v$ (wrt. the main variable if $v$ is omitted). Since PARI cannot represent logarithmic or arctangent terms, any such term in the result will yield an error: \bprog ? intformal(x^2) %1 = 1/3*x^3 ? intformal(x^2, y) %2 = y*x^2 ? intformal(1/x) *** at top-level: intformal(1/x) *** ^-------------- *** intformal: domain error in intformal: residue(series, pole) != 0 @eprog The argument $x$ can be of any type. When $x$ is a rational function, we assume that the base ring is an integral domain of characteristic zero. By definition, the main variable of a \typ{POLMOD} is the main variable among the coefficients from its two polynomial components (representative and modulus); in other words, assuming a polmod represents an element of $R[X]/(T(X))$, the variable $X$ is a mute variable and the integral is taken with respect to the main variable used in the base ring $R$. In particular, it is meaningless to integrate with respect to the main variable of \kbd{x.mod}: \bprog ? intformal(Mod(1,x^2+1), 'x) *** intformal: incorrect priority in intformal: variable x = x @eprog pari-2.17.2/src/functions/polynomials/polcyclofactors0000644000175000017500000000162014567450071021472 0ustar billbillFunction: polcyclofactors Section: polynomials C-Name: polcyclofactors Prototype: G Help: polcyclofactors(f): returns a vector of polynomials, whose product is the product of distinct cyclotomic polynomials dividing f. Doc: returns a vector of polynomials, whose product is the product of distinct cyclotomic polynomials dividing $f$. \bprog ? f = x^10+5*x^8-x^7+8*x^6-4*x^5+8*x^4-3*x^3+7*x^2+3; ? v = polcyclofactors(f) %2 = [x^2 + 1, x^2 + x + 1, x^4 - x^3 + x^2 - x + 1] ? apply(poliscycloprod, v) %3 = [1, 1, 1] ? apply(poliscyclo, v) %4 = [4, 3, 10] @eprog\noindent In general, the polynomials are products of cyclotomic polynomials and not themselves irreducible: \bprog ? g = x^8+2*x^7+6*x^6+9*x^5+12*x^4+11*x^3+10*x^2+6*x+3; ? polcyclofactors(g) %2 = [x^6 + 2*x^5 + 3*x^4 + 3*x^3 + 3*x^2 + 2*x + 1] ? factor(%[1]) %3 = [ x^2 + x + 1 1] [x^4 + x^3 + x^2 + x + 1 1] @eprog pari-2.17.2/src/functions/polynomials/pollaguerre0000644000175000017500000000137314676526175020624 0ustar billbillFunction: pollaguerre Section: polynomials C-Name: pollaguerre_eval0 Prototype: LDGDGD0,L, Help: pollaguerre(n,{a=0},{b='x},{flag=0}): Laguerre polynomial of degree n and parameter a evaluated at b. If flag is 1, return [L^{(a)_{n-1}(b), L^{(a)}_n(b)]. Doc: $n^{\text{th}}$ \idx{Laguerre polynomial} $L^{(a)}_{n}$ of degree $n$ and parameter $a$ evaluated at $b$ (\kbd{'x} by default), i.e. $$ L_{n}^{(a)}(x) = \dfrac{x^{-a}e^{x}}{n!} \dfrac{d^{n}}{dx^{n}}\big(e^{-x}x^{n+a}\big).$$ If \fl\ is $1$, return $[L^{(a)}_{n-1}(b), L_{n}^{(a)}(b)]$. Variant: To obtain the $n$-th Laguerre polynomial in variable $v$, use \fun{GEN}{pollaguerre}{long n, GEN a, GEN b, long v}. To obtain $L^{(a)}_{n}(b)$, use \fun{GEN}{pollaguerre_eval}{long n, GEN a, GEN b}. pari-2.17.2/src/functions/polynomials/thueinit0000644000175000017500000000721314676526175020133 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 nonzero, certify the result unconditionally. Otherwise, assume GRH (much faster of course). Doc: initializes the \var{tnf} corresponding to $P$, a nonconstant univariate polynomial with integer coefficients. The result is meant to be used in conjunction with \tet{thue} to solve Thue equations $P(X / Y)Y^{\deg P} = a$, where $a$ is an integer. Accordingly, $P$ must either have at least two distinct irreducible factors over $\Q$, or have one irreducible factor $T$ with degree $>2$ or two conjugate complex roots: under these (necessary and sufficient) conditions, the equation has finitely many integer solutions. \bprog ? S = thueinit(t^2+1); ? thue(S, 5) %2 = [[-2, -1], [-2, 1], [-1, -2], [-1, 2], [1, -2], [1, 2], [2, -1], [2, 1]] ? S = thueinit(t+1); *** at top-level: thueinit(t+1) *** ^------------- *** thueinit: domain error in thueinit: P = t + 1 @eprog\noindent The hardest case is when $\deg P > 2$ and $P$ is irreducible with at least one real root. The routine then uses Bilu-Hanrot's algorithm. If $\fl$ is nonzero, 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 unconditional. \misctitle{Note} The general philosophy is to disprove the existence of large solutions then to enumerate bounded solutions naively. The implementation will overflow when there exist huge solutions and the equation has degree $> 2$ (the quadratic imaginary case is special, since we can stick to \kbd{bnfisintnorm}, there are no fundamental units): \bprog ? thue(t^3+2, 10^30) *** at top-level: L=thue(t^3+2,10^30) *** ^----------------- *** thue: overflow in thue (SmallSols): y <= 80665203789619036028928. ? thue(x^2+2, 10^30) \\ quadratic case much easier %1 = [[-1000000000000000, 0], [1000000000000000, 0]] @eprog \misctitle{Note} It is sometimes possible to circumvent the above, and in any case obtain an important speed-up, if you can write $P = Q(x^{d})$ for some $d > 1$ and $Q$ still satisfying the \kbd{thueinit} hypotheses. You can then solve the equation attached to $Q$ then eliminate all solutions $(x,y)$ such that either $x$ or $y$ is not a $d$-th power. \bprog ? thue(x^4+1, 10^40); \\ stopped after 10 hours ? filter(L,d) = my(x,y); [[x,y] | v<-L, ispower(v[1],d,&x)&&ispower(v[2],d,&y)]; ? L = thue(x^2+1, 10^40); ? filter(L, 2) %4 = [[0, 10000000000], [10000000000, 0]] @eprog\noindent The last 2 commands use less than 20ms. \misctitle{Note} When $P$ is irreducible without a real root, the equation can be solved unconditionnally in time $|a|^{1/\deg P}$. When this latter quantity is huge and the equation has no solutions, this fact may still be ascertained via arithmetic conditions but this now implies solving norm equations, computing a \var{bnf} and possibly assuming the GRH. When there is no real root, the code does not compute a \var{bnf} (with certification if $\fl = 1$) if it expects this to be an ``easy'' computation (because the result would only be used for huge values of $a$). See \kbd{thue} for a way to compute an expensive \var{bnf} on your own and still get a result where this default cheap strategy fails. pari-2.17.2/src/functions/polynomials/seralgdep0000644000175000017500000000146314676526175020251 0ustar billbillFunction: seralgdep Section: polynomials C-Name: seralgdep Prototype: GLL Help: seralgdep(s,p,r): find a linear relation between powers (1,s, ..., s^p) of the series s, with polynomial coefficients of degree <= r. Doc: \sidx{algebraic dependence} finds a linear relation between powers $(1,s, \dots, s^{p})$ of the series $s$, with polynomial coefficients of degree $\leq r$. In case no relation is found, return $0$. \bprog ? s = 1 + 10*y - 46*y^2 + 460*y^3 - 5658*y^4 + 77740*y^5 + O(y^6); ? seralgdep(s, 2, 2) %2 = -x^2 + (8*y^2 + 20*y + 1) ? subst(%, x, s) %3 = O(y^6) ? seralgdep(s, 1, 3) %4 = (-77*y^2 - 20*y - 1)*x + (310*y^3 + 231*y^2 + 30*y + 1) ? seralgdep(s, 1, 2) %5 = 0 @eprog\noindent The series main variable must not be $x$, so as to be able to express the result as a polynomial in $x$. pari-2.17.2/src/functions/polynomials/polrootspadic0000644000175000017500000000331714676526175021165 0ustar billbillFunction: polrootspadic Section: polynomials C-Name: polrootspadic Prototype: GGL Help: polrootspadic(f,p,r): p-adic roots of the polynomial f to precision r. Doc: vector of $p$-adic roots of the polynomial \var{pol}, given to $p$-adic precision $r$; the integer $p$ is assumed to be a prime. Multiple roots are \emph{not} repeated. Note that this is not the same as the roots in $\Z/p^{r}\Z$, rather it gives approximations in $\Z/p^{r}\Z$ of the true roots living in $\Q_{p}$: \bprog ? polrootspadic(x^3 - x^2 + 64, 2, 4) %1 = [2^3 + O(2^4), 2^3 + O(2^4), 1 + O(2^4)]~ ? polrootspadic(x^3 - x^2 + 64, 2, 5) %2 = [2^3 + O(2^5), 2^3 + 2^4 + O(2^5), 1 + O(2^5)]~ @eprog\noindent As the second commands show, the first two roots \emph{are} distinct in $\Q_{p}$, even though they are equal modulo $2^{4}$. More generally, if $T$ is an integral polynomial irreducible mod $p$ and $f$ has coefficients in $\Q[t]/(T)$, the argument $p$ may be replaced by the vector $[T,p]$; we then return the roots of $f$ in the unramified extension $\Q_{p}[t]/(T)$. \bprog ? polrootspadic(x^3 - x^2 + 64*y, [y^2+y+1,2], 5) %3 = [Mod((2^3 + O(2^5))*y + (2^3 + O(2^5)), y^2 + y + 1), Mod((2^3 + 2^4 + O(2^5))*y + (2^3 + 2^4 + O(2^5)), y^2 + y + 1), Mod(1 + O(2^5), y^2 + y + 1)]~ @eprog If \var{pol} has inexact \typ{PADIC} coefficients, this need not well-defined; in this case, the polynomial is first made integral by dividing out the $p$-adic content, then lifted to $\Z$ using \tet{truncate} coefficientwise. Hence the roots given are approximations of the roots of an exact polynomial which is $p$-adically close to the input. To avoid pitfalls, we advise to only factor polynomials with exact rational coefficients. pari-2.17.2/src/functions/polynomials/poltchebi0000644000175000017500000000031614567450071020236 0ustar billbillFunction: poltchebi Section: polynomials C-Name: polchebyshev1 Prototype: LDn Obsolete: 2013-04-03 Help: poltchebi(n,{v='x}): deprecated alias for polchebyshev. Doc: deprecated alias for \kbd{polchebyshev} pari-2.17.2/src/functions/polynomials/polinterpolate0000644000175000017500000001035414676526175021343 0ustar billbillFunction: polinterpolate Section: polynomials C-Name: polint Prototype: GDGDGD& Help: polinterpolate(X,{Y},{t = 'x},{&e}): polynomial interpolation at t according to data vectors X, Y, i.e., given P of minimal degree such that P(X[i]) = Y[i] for all i, return P(t). If Y is omitted, take P such that P(i) = X[i]. If present and t is numeric, e will contain an error estimate on the returned value (Neville's algorithm). 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} $P$ of minimal degree passing through these points and evaluates it at~$t$. If $Y$ is omitted, the polynomial $P$ interpolates the $(i,X[i])$. \bprog ? v = [1, 2, 4, 8, 11, 13]; ? P = polinterpolate(v) \\ formal interpolation %1 = 7/120*x^5 - 25/24*x^4 + 163/24*x^3 - 467/24*x^2 + 513/20*x - 11 ? [ subst(P,'x,a) | a <- [1..6] ] %2 = [1, 2, 4, 8, 11, 13] ? polinterpolate(v,, 10) \\ evaluate at 10 %3 = 508 ? subst(P, x, 10) %4 = 508 ? P = polinterpolate([1,2,4], [9,8,7]) %5 = 1/6*x^2 - 3/2*x + 31/3 ? [subst(P, 'x, a) | a <- [1,2,4]] %6 = [9, 8, 7] ? P = polinterpolate([1,2,4], [9,8,7], 0) %7 = 31/3 @eprog\noindent If the goal is to extrapolate a function at a unique point, it is more efficient to use the $t$ argument rather than interpolate formally then evaluate: \bprog ? x0 = 1.5; ? v = vector(20, i,random([-10,10])); ? for(i=1,10^3, subst(polinterpolate(v),'x, x0)) time = 352 ms. ? for(i=1,10^3, polinterpolate(v,,x0)) time = 111 ms. ? v = vector(40, i,random([-10,10])); ? for(i=1,10^3, subst(polinterpolate(v), 'x, x0)) time = 3,035 ms. ? for(i=1,10^3, polinterpolate(v,, x0)) time = 436 ms. @eprog\noindent The threshold depends on the base field. Over small prime finite fields, interpolating formally first is more efficient \bprog ? bench(p, N, T = 10^3) = { my (v = vector(N, i, random(Mod(0,p)))); my (x0 = Mod(3, p), t1, t2); gettime(); for(i=1, T, subst(polinterpolate(v), 'x, x0)); t1 = gettime(); for(i=1, T, polinterpolate(v,, x0)); t2 = gettime(); [t1, t2]; } ? p = 101; ? bench(p, 4, 10^4) \\ both methods are equivalent %3 = [39, 40] ? bench(p, 40) \\ with 40 points formal is much faster %4 = [45, 355] @eprog\noindent As the cardinality increases, formal interpolation requires more points to become interesting: \bprog ? p = nextprime(2^128); ? bench(p, 4) \\ formal is slower %3 = [16, 9] ? bench(p, 10) \\ formal has become faster %4 = [61, 70] ? bench(p, 100) \\ formal is much faster %5 = [1682, 9081] ? p = nextprime(10^500); ? bench(p, 4) \\ formal is slower %7 = [72, 354] ? bench(p, 20) \\ formal is still slower %8 = [1287, 962] ? bench(p, 40) \\ formal has become faster %9 = [3717, 4227] ? bench(p, 100) \\ faster but relatively less impressive %10 = [16237, 32335] @eprog If $t$ is a complex numeric value and $e$ is present, $e$ will contain an error estimate on the returned value. More precisely, let $P$ be the interpolation polynomial on the given $n$ points; there exist a subset of $n-1$ points and $Q$ the attached interpolation polynomial such that $e = \kbd{exponent}(P(t) - Q(t))$ (Neville's algorithm). \bprog ? f(x) = 1 / (1 + 25*x^2); ? x0 = 975/1000; ? test(X) = { my (P, e); P = polinterpolate(X, [f(x) | x <- X], x0, &e); [ exponent(P - f(x0)), e ]; } \\ equidistant nodes vs. Chebyshev nodes ? test( [-10..10] / 10 ) %4 = [6, 5] ? test( polrootsreal(polchebyshev(21)) ) %5 = [-15, -10] ? test( [-100..100] / 100 ) %7 = [93, 97] \\ P(x0) is way different from f(x0) ? test( polrootsreal(polchebyshev(201)) ) %8 = [-60, -55] @eprog\noindent This is an example of Runge's phenomenon: increasing the number of equidistant nodes makes extrapolation much worse. Note that the error estimate is not a guaranteed upper bound (cf \%4), but is reasonably tight in practice. \misctitle{Numerical stability} The interpolation is performed in a numerically stable way using $\prod_{j\neq i} (X[i] - X[j])$ instead of $Q'(X[i])$ with $Q = \prod_{i} (x - X[i])$. Centering the interpolation points $X[i]$ around $0$, thereby reconstructing $P(x - m)$, for a suitable $m$ will further reduce the numerical error. pari-2.17.2/src/functions/polynomials/poliscyclo0000644000175000017500000000066714676526175020470 0ustar billbillFunction: poliscyclo Section: polynomials C-Name: poliscyclo Prototype: lG Help: poliscyclo(f): returns 0 if f is not a cyclotomic polynomial, and n > 0 if f = Phi_n, the n-th cyclotomic polynomial. Doc: returns 0 if $f$ is not a cyclotomic polynomial, and $n > 0$ if $f = \Phi_{n}$, the $n$-th cyclotomic polynomial. \bprog ? poliscyclo(x^4-x^2+1) %1 = 12 ? polcyclo(12) %2 = x^4 - x^2 + 1 ? poliscyclo(x^4-x^2-1) %3 = 0 @eprog pari-2.17.2/src/functions/polynomials/fft0000644000175000017500000000154214676526175017060 0ustar billbillFunction: fft Section: polynomials C-Name: FFT Prototype: GG Help: fft(w,P): given w from rootsof1, return the discrete Fourier transform of P. Doc: Let $w=[1,z,\ldots,z^{N-1}]$ from some primitive $N$-roots of unity $z$ where $N$ is a power of $2$, and $P$ be a polynomial $< N$, return the unnormalized discrete Fourier transform of $P$, $\{ P(w[i]), 1 \leq i \leq N\}$. Also allow $P$ to be a vector $[p_{0},\dots,p_{n}]$ representing the polynomial $\sum_{i} p_{i} X^{i}$. Composing \kbd{fft} and \kbd{fftinv} returns $N$ times the original input coefficients. \bprog ? w = rootsof1(4); fft(w, x^3+x+1) %1 = [3, 1, -1, 1] ? fftinv(w, %) %2 = [4, 4, 0, 4] ? Polrev(%) / 4 %3 = x^3 + x + 1 ? w = powers(znprimroot(5),3); fft(w, x^3+x+1) %4 = [Mod(3,5),Mod(1,5),Mod(4,5),Mod(1,5)] ? fftinv(w, %) %5 = [Mod(4,5),Mod(4,5),Mod(0,5),Mod(4,5)] @eprog pari-2.17.2/src/functions/polynomials/pollegendre0000644000175000017500000000133614676526175020602 0ustar billbillFunction: pollegendre Section: polynomials C-Name: pollegendre_eval0 Prototype: LDGD0,L, Help: pollegendre(n,{a='x},{flag=0}): legendre polynomial of degree n evaluated at a. If flag is 1, return [P_{n-1}(a), P_n(a)]. Description: (small,?var):gen pollegendre($1,$2) (small,gen):gen pollegendre_eval($1,$2) Doc: $n^{\text{th}}$ \idx{Legendre polynomial} $P_{n}$ evaluated at $a$ (\kbd{'x} by default), where $$P_{n}(x) = \dfrac{1}{2^{n} n!} \dfrac{d^{n}}{dx^{n}}(x^{2}-1)^{n}\;.$$ If \fl\ is 1, return $[P_{n-1}(a), P_{n}(a)]$. Variant: To obtain the $n$-th Legendre polynomial $P_{n}$ in variable $v$, use \fun{GEN}{pollegendre}{long n, long v}. To obtain $P_{n}(a)$, use \fun{GEN}{pollegendre_eval}{long n, GEN a}. pari-2.17.2/src/functions/polynomials/serconvol0000644000175000017500000000053314676526175020312 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.17.2/src/functions/polynomials/serdiffdep0000644000175000017500000000205514676526175020414 0ustar billbillFunction: serdiffdep Section: polynomials C-Name: serdiffdep Prototype: GLL Help: serdiffdep(s,p,r): find an inhomogenous linear differential equation satisfied by the series s, with polynomial coefficients of degree <= r. The result is a pair [E,P] such that E(d)(S)=P where E(d) is interpreted as a differential polynomial, or 0 in case no relation is found. Doc: find a linear relation between the derivatives $(s, s', \dots, s^{p})$ of the series $s$ and $1$, with polynomial coefficients of degree $\leq r$. In case no relation is found, return $0$, otherwise return $[E,P]$ such that $E(d)(S)=P$ where $d$ is the standard derivation. \bprog ? S = sum(i=0, 50, binomial(3*i,i)*T^i) + O(T^51); ? serdiffdep(S, 3, 3) %2 = [(27*T^2 - 4*T)*x^2 + (54*T - 2)*x + 6, 0] ? (27*T^2 - 4*T)*S'' + (54*T - 2)*S' + 6*S %3 = O(T^50) ? S = exp(T^2) + T^2; ? serdiffdep(S, 3, 3) %5 = [x-2*T, -2*T^3+2*T] ? S'-2*T*S %6 = 2*T-2*T^3+O(T^17) @eprog \noindent The series main variable must not be $x$, so as to be able to express the result as a polynomial in $x$. pari-2.17.2/src/functions/polynomials/padicappr0000644000175000017500000000175214676526175020247 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 \var{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 \emph{unramified} extension $\Q_{p}[X]/(T)$ of $\Q_{p}$, given as a \typ{POLMOD} \kbd{Mod}$(A,T)$ at least one of whose coefficients is a \typ{PADIC} and $T$ irreducible modulo $p$. In this case, the result is the vector of roots belonging to the same extension of $\Q_{p}$ as $a$. The polynomial \var{pol} should have exact coefficients; if not, its coefficients are first rounded to $\Q$ or $\Q[X]/(T)$ and this is the polynomial whose roots we consider. Variant: Also available is \fun{GEN}{Zp_appr}{GEN f, GEN a} when $a$ is a \typ{PADIC}. pari-2.17.2/src/functions/polynomials/O0000644000175000017500000000154014567450071016463 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.17.2/src/functions/polynomials/polhermite0000644000175000017500000000170614676526175020453 0ustar billbillFunction: polhermite Section: polynomials C-Name: polhermite_eval0 Prototype: LDGD0,L, Help: polhermite(n,{a='x},{flag=0}): Hermite polynomial H(n,v) of degree n, evaluated at a. If flag is nonzero, return [H_{n-1}(a), H_n(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}}.$$ If \fl\ is nonzero and $n > 0$, return $[H_{n-1}(a), H_{n}(a)]$. \bprog ? polhermite(5) %1 = 32*x^5 - 160*x^3 + 120*x ? polhermite(5, -2) \\ H_5(-2) %2 = 16 ? polhermite(5,,1) %3 = [16*x^4 - 48*x^2 + 12, 32*x^5 - 160*x^3 + 120*x] ? polhermite(5,-2,1) %4 = [76, 16] @eprog Variant: The variant \fun{GEN}{polhermite}{long n, long v} returns the $n$-th Hermite polynomial in variable $v$. To obtain $H_{n}(a)$, use \fun{GEN}{polhermite_eval}{long n, GEN a}. pari-2.17.2/src/functions/polynomials/sumformal0000644000175000017500000000202214676526175020300 0ustar billbillFunction: sumformal Section: polynomials C-Name: sumformal Prototype: GDn Help: sumformal(f,{v}): formal sum of f with respect to v, or to the main variable of f if v is omitted. Doc: \idx{formal sum} of the polynomial expression $f$ with respect to the main variable if $v$ is omitted, with respect to the variable $v$ otherwise; it is assumed that the base ring has characteristic zero. In other words, considering $f$ as a polynomial function in the variable $v$, returns $F$, a polynomial in $v$ vanishing at $0$, such that $F(b) - F(a) = sum_{v = a+1}^{b} f(v)$: \bprog ? sumformal(n) \\ 1 + ... + n %1 = 1/2*n^2 + 1/2*n ? f(n) = n^3+n^2+1; ? F = sumformal(f(n)) \\ f(1) + ... + f(n) %3 = 1/4*n^4 + 5/6*n^3 + 3/4*n^2 + 7/6*n ? sum(n = 1, 2000, f(n)) == subst(F, n, 2000) %4 = 1 ? sum(n = 1001, 2000, f(n)) == subst(F, n, 2000) - subst(F, n, 1000) %5 = 1 ? sumformal(x^2 + x*y + y^2, y) %6 = y*x^2 + (1/2*y^2 + 1/2*y)*x + (1/3*y^3 + 1/2*y^2 + 1/6*y) ? x^2 * y + x * sumformal(y) + sumformal(y^2) == % %7 = 1 @eprog pari-2.17.2/src/functions/polynomials/polcoef0000644000175000017500000000167114567450071017721 0ustar billbillFunction: polcoef Section: polynomials C-Name: polcoef Prototype: GLDn Help: polcoef(x,n,{v}): coefficient of degree n of x. With respect to the main variable if v is omitted, with respect to the variable v otherwise. Description: (pol, 0):gen:copy constant_coeff($1) (pol, 0,):gen:copy constant_coeff($1) (pol, small):gen:copy RgX_coeff($1, $2) (pol, small,):gen:copy RgX_coeff($1, $2) (gen, small, ?var):gen polcoeff0($1, $2, $3) Doc: coefficient of degree $n$ of the polynomial $x$, with respect to the main variable if $v$ is omitted, with respect to $v$ otherwise. If $n$ 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. pari-2.17.2/src/functions/polynomials/polchebyshev0000644000175000017500000000234514676526175020776 0ustar billbillFunction: polchebyshev Section: polynomials C-Name: polchebyshev_eval Prototype: LD1,L,DG Help: polchebyshev(n,{flag=1},{a='x}): Chebyshev polynomial of the first (flag = 1) or second (flag = 2) kind, of degree n, evaluated at a. Description: (small,?1,?var):gen polchebyshev1($1,$3) (small,2,?var):gen polchebyshev2($1,$3) (small,small,?var):gen polchebyshev($1,$2,$3) Doc: returns the $n^{\text{th}}$ \idx{Chebyshev} polynomial of the first kind $T_{n}$ ($\fl=1$) or the second kind $U_{n}$ ($\fl=2$), evaluated at $a$ (\kbd{'x} by default). Both series of polynomials satisfy the 3-term relation $$ P_{n+1} = 2xP_{n} - P_{n-1}, $$ and are determined by the initial conditions $U_{0} = T_{0} = 1$, $T_{1} = x$, $U_{1} = 2x$. In fact $T_{n}' = n U_{n-1}$ and, for all complex numbers $z$, we have $T_{n}(\cos z) = \cos (nz)$ and $U_{n-1}(\cos z) = \sin(nz)/\sin z$. If $n \geq 0$, then these polynomials have degree $n$. For $n < 0$, $T_{n}$ is equal to $T_{-n}$ and $U_{n}$ is equal to $-U_{-2-n}$. In particular, $U_{-1} = 0$. Variant: Also available are \fun{GEN}{polchebyshev}{long n, long flag, long v}, \fun{GEN}{polchebyshev1}{long n, long v} and \fun{GEN}{polchebyshev2}{long n, long v} for $T_{n}$ and $U_{n}$ respectively. pari-2.17.2/src/functions/polynomials/polhensellift0000644000175000017500000000216214676526175021150 0ustar billbillFunction: polhensellift Section: polynomials C-Name: polhensellift Prototype: GGGL Help: polhensellift(A,B,p,e): lift the factorization B of A modulo p to a factorization modulo p^e using Hensel lift. The factors in B must be pairwise relatively prime modulo p. Doc: given a prime $p$, an integral polynomial $A$ whose leading coefficient is a $p$-unit, a vector $B$ of integral polynomials that are monic and pairwise relatively prime modulo $p$, and whose product is congruent to $A/\text{lc}(A)$ modulo $p$, lift the elements of $B$ to polynomials whose product is congruent to $A$ modulo $p^{e}$. More generally, if $T$ is an integral polynomial irreducible mod $p$, and $B$ is a factorization of $A$ over the finite field $\F_{p}[t]/(T)$, you can lift it to $\Z_{p}[t]/(T, p^{e})$ by replacing the $p$ argument with $[p,T]$: \bprog ? { T = t^3 - 2; p = 7; A = x^2 + t + 1; B = [x + (3*t^2 + t + 1), x + (4*t^2 + 6*t + 6)]; r = polhensellift(A, B, [p, T], 6) } %1 = [x + (20191*t^2 + 50604*t + 75783), x + (97458*t^2 + 67045*t + 41866)] ? liftall( r[1] * r[2] * Mod(Mod(1,p^6),T) ) %2 = x^2 + (t + 1) @eprog pari-2.17.2/src/functions/polynomials/poldiscreduced0000644000175000017500000000102013637407207021247 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.17.2/src/functions/polynomials/polisirreducible0000644000175000017500000000071514567450071021630 0ustar billbillFunction: polisirreducible Section: polynomials C-Name: polisirreducible Prototype: lG Help: polisirreducible(pol): true(1) if pol is an irreducible nonconstant 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 nonconstant and irreducible, 0 otherwise. Irreducibility is checked over the smallest base field over which \var{pol} seems to be defined. pari-2.17.2/src/functions/polynomials/diffop0000644000175000017500000000367014676526175017554 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. \misctitle{Examples} This function can be used to differentiate formal expressions: if $E=\exp(X^{2})$ then we have $E'=2*X*E$. We derivate $X*exp(X^{2})$ as follows: \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 follows, 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(x, v, dv, var = i->eval(Str("X",i))); 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), polcoef(x,n,'X)); } @eprog Variant: For $n=1$, the function \fun{GEN}{diffop}{GEN x, GEN v, GEN d} is also available. pari-2.17.2/src/functions/polynomials/polsubcyclo0000644000175000017500000000253614676526175020643 0ustar billbillFunction: polsubcyclo Section: polynomials C-Name: polsubcyclo Prototype: LLDn Help: polsubcyclo(n,d,{v='x}): finds an equation (in variable v) for the d-th degree subfields of Q(zeta_n). Output is a polynomial, or a vector of polynomials if there are several such fields or none. Doc: gives polynomials (in variable $v$) defining the (Abelian) subextensions 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))}. Each such polynomial is the minimal polynomial for a Gaussian period $\text{Tr}_{\Q(\zeta_{f})/L} (\zeta_{f})$, where $L$ is the degree $d$ subextension of $\Q(\zeta_{n})$ and $f | n$ is its conductor. In Galois-theoretic terms, $L = \Q(\zeta_{n})^{H}$, where $H$ runs through all index $d$ subgroups of $(\Z/n\Z)^{*}$. The function \tet{galoissubcyclo} allows to specify exactly which sub-Abelian extension should be computed by giving $H$. \misctitle{Complexity} Ignoring logarithmic factors, \kbd{polsubcyclo} runs in time $O(n)$. The function \kbd{polsubcyclofast} returns different, less canonical, polynomials but runs in time $O(d^{4})$, again ignoring logarithmic factors; thus it can handle much larger values of $n$. pari-2.17.2/src/functions/polynomials/polrootsmod0000644000175000017500000000220214676526175020654 0ustar billbillFunction: polrootsmod Section: polynomials C-Name: polrootsmod Prototype: GDG Help: polrootsmod(f,{D}): roots of the polynomial f over the finite field defined by the domain D. Doc: vector of roots of the polynomial $f$ over the finite field defined by the domain $D$ as follows: \item $D = p$ a prime: factor over $\F_{p}$; \item $D = [T,p]$ for a prime $p$ and $T(y)$ an irreducible polynomial over $\F_{p}$: factor over $\F_{p}[y]/(T)$ (as usual the main variable of $T$ must have lower priority than the main variable of $f$); \item $D$ a \typ{FFELT}: factor over the attached field; \item $D$ omitted: factor over the field of definition of $f$, which must be a finite field. \noindent Multiple roots are \emph{not} repeated. \bprog ? polrootsmod(x^2-1,2) %1 = [Mod(1, 2)]~ ? polrootsmod(x^2+1,3) %2 = []~ ? polrootsmod(x^2+1, [y^2+1,3]) %3 = [Mod(Mod(1, 3)*y, Mod(1, 3)*y^2 + Mod(1, 3)), Mod(Mod(2, 3)*y, Mod(1, 3)*y^2 + Mod(1, 3))]~ ? polrootsmod(x^2 + Mod(1,3)) %4 = []~ ? liftall( polrootsmod(x^2 + Mod(Mod(1,3),y^2+1)) ) %5 = [y, 2*y]~ ? t = ffgen(y^2+Mod(1,3)); polrootsmod(x^2 + t^0) %6 = [y, 2*y]~ @eprog pari-2.17.2/src/functions/polynomials/polresultantext0000644000175000017500000000147314557721031021543 0ustar billbillFunction: polresultantext Section: polynomials C-Name: polresultantext0 Prototype: GGDn Help: polresultantext(A,B,{v}): return [U,V,R] such that R=polresultant(A,B,v) and U*A+V*B = R, where A and B are polynomials. Doc: finds polynomials $U$ and $V$ such that $A*U + B*V = R$, where $R$ is the resultant of $U$ and $V$ with respect to the main variables of $A$ and $B$ if $v$ is omitted, and with respect to $v$ otherwise. Returns the row vector $[U,V,R]$. The algorithm used (subresultant) assumes that the base ring is a domain. \bprog ? A = x*y; B = (x+y)^2; ? [U,V,R] = polresultantext(A, B) %2 = [-y*x - 2*y^2, y^2, y^4] ? A*U + B*V %3 = y^4 ? [U,V,R] = polresultantext(A, B, y) %4 = [-2*x^2 - y*x, x^2, x^4] ? A*U+B*V %5 = x^4 @eprog Variant: Also available is \fun{GEN}{polresultantext}{GEN x, GEN y}. pari-2.17.2/src/functions/polynomials/polrootsff0000644000175000017500000000033414716370773020470 0ustar billbillFunction: polrootsff Section: polynomials C-Name: polrootsff Prototype: GDGDG Obsolete: 2018-03-11 Help: polrootsff(x,{p},{a}): obsolete, use polrootsmod. Doc: obsolete, kept for backward compatibility: use polrootsmod. pari-2.17.2/src/functions/polynomials/polroots0000644000175000017500000000222014567450071020142 0ustar billbillFunction: polroots Section: polynomials C-Name: roots Prototype: Gp Description: (gen):vec:prec roots($1, $prec) Help: polroots(T): complex roots of the polynomial T using Schonhage's method, as modified by Gourdon. Doc: complex roots of the polynomial $T$, given as a column vector where each root is repeated according to its multiplicity and given as floating point complex numbers at the current \kbd{realprecision}: \bprog ? polroots(x^2) %1 = [0.E-38 + 0.E-38*I, 0.E-38 + 0.E-38*I]~ ? polroots(x^3+1) %2 = [-1.00... + 0.E-38*I, 0.50... - 0.866...*I, 0.50... + 0.866...*I]~ @eprog The algorithm used is a modification of Sch\"onhage\sidx{Sch\"onage}'s root-finding algorithm, due to and originally implemented by Gourdon. It runs in polynomial time in $\text{deg}(T)$ and the precision. If furthermore $T$ has rational coefficients, roots are guaranteed to the required relative accuracy. If the input polynomial $T$ is exact, then the ordering of the roots does not depend on the precision: they are ordered by increasing $|\Im z|$, then by increasing $\Re z$; in case of tie (conjugates), the root with negative imaginary part comes first. pari-2.17.2/src/functions/polynomials/eval0000644000175000017500000000304414567450071017215 0ustar billbillFunction: eval Section: polynomials C-Name: geval_gp Prototype: GC Help: eval(x): evaluation of x, replacing variables by their value. Description: (gen):gen geval($1) Doc: replaces in $x$ the formal variables by the values that have been assigned to them after the creation of $x$. This is mainly useful in GP, and not in library mode. Do not confuse this with substitution (see \kbd{subst}). If $x$ is a character string, \kbd{eval($x$)} executes $x$ as a GP command, as if directly input from the keyboard, and returns its output. \bprog ? x1 = "one"; x2 = "two"; ? n = 1; eval(Str("x", n)) %2 = "one" ? f = "exp"; v = 1; ? eval(Str(f, "(", v, ")")) %4 = 2.7182818284590452353602874713526624978 @eprog\noindent Note that the first construct could be implemented in a simpler way by using a vector \kbd{x = ["one","two"]; x[n]}, and the second by using a closure \kbd{f = exp; f(v)}. The final example is more interesting: \bprog ? genmat(u,v) = matrix(u,v,i,j, eval( Str("x",i,j) )); ? genmat(2,3) \\ generic 2 x 3 matrix %2 = [x11 x12 x13] [x21 x22 x23] @eprog A syntax error in the evaluation expression raises an \kbd{e\_SYNTAX} exception, which can be trapped as usual: \bprog ? 1a *** syntax error, unexpected variable name, expecting $end or ';': 1a *** ^- ? E(expr) = { iferr(eval(expr), e, print("syntax error"), errname(e) == "e_SYNTAX"); } ? E("1+1") %1 = 2 ? E("1a") syntax error @eprog \synt{geval}{GEN x}. pari-2.17.2/src/functions/polynomials/poldiscfactors0000644000175000017500000000255414567450071021312 0ustar billbillFunction: poldiscfactors Section: polynomials C-Name: poldiscfactors Prototype: GD0,L, Help: poldiscfactors(T,{flag=0}): [D, faD], where D = discriminant of the polynomial T, and faD is a cheap partial factorization of D (entries are coprime but need not be primes); if flag is 1, finish the factorization via factorint. Doc: given a polynomial $T$ with integer coefficients, return $[D, \var{faD}]$ where $D$ is the discriminant of $T$ and \var{faD} is a cheap partial factorization of $|D|$: entries in its first column are coprime and not perfect powers but need not be primes. The factors are obtained by a combination of trial division, testing for perfect powers, factorizations in coprimes, and computing Euclidean remainder sequences for $(T,T')$ modulo composite factors $d$ of $D$ (which is likely to produce $0$-divisors in $\Z/d\Z$). If \fl\ is $1$, finish the factorization using \kbd{factorint}. \bprog ? T = x^3 - 6021021*x^2 + 12072210077769*x - 8092423140177664432; ? [D,faD] = poldiscfactors(T); print(faD); D [3, 3; 7, 2; 373, 2; 500009, 2; 24639061, 2] %2 = -27937108625866859018515540967767467 ? T = x^3 + 9*x^2 + 27*x - 125014250689643346789780229390526092263790263725; ? [D,faD] = poldiscfactors(T); print(faD) [2, 6; 3, 3; 125007125141751093502187, 4] ? [D,faD] = poldiscfactors(T, 1); print(faD) [2, 6; 3, 3; 500009, 12; 1000003, 4] @eprog pari-2.17.2/src/functions/polynomials/polsturm0000644000175000017500000000316314760123736020155 0ustar billbillFunction: polsturm Section: polynomials C-Name: sturmpart Prototype: lGDGDG Help: polsturm(T,{ab}): number of distinct real roots of the polynomial T (in the interval ab = [a,b] if present). Doc: number of distinct real roots of the real polynomial \var{T}. If the argument \var{ab} is present, it must be a vector $[a,b]$ with two real components (of type \typ{INT}, \typ{REAL}, \typ{FRAC} or \typ{INFINITY}) and we count roots belonging to that closed interval. If possible, you should stick to exact inputs, that is avoid \typ{REAL}s in $T$ and the bounds $a,b$: the result is then guaranteed and we use a fast algorithm (Uspensky's method, relying on Descartes's rule of sign, see \tet{polrootsreal}). Otherwise, the polynomial is rescaled and rounded first and the result may be wrong due to that initial error. If only $a$ or $b$ is inexact, on the other hand, the interval is first thickened using rational endpoints and the result remains guaranteed unless there exist a root \emph{very} close to a nonrational endpoint (which may be missed or unduly included). \bprog ? T = (x-1)*(x-2)*(x-3); ? polsturm(T) %2 = 3 ? polsturm(T, [-oo,2]) %3 = 2 ? polsturm(T, [1/2,+oo]) %4 = 3 ? polsturm(T, [1, Pi]) \\ Pi inexact: not recommended ! %5 = 3 ? polsturm(T*1., [0, 4]) \\ T*1. inexact: not recommended ! %6 = 3 ? polsturm(T^2, [0, 4]) \\ not squarefree: roots are not repeated! %7 = 3 @eprog %\syn{NO} The library syntax is \fun{long}{RgX_sturmpart}{GEN T, GEN ab} or \fun{long}{sturm}{GEN T} (for the case \kbd{ab = NULL}). The function \fun{long}{sturmpart}{GEN T, GEN a, GEN b} is obsolete and deprecated. pari-2.17.2/src/functions/polynomials/polzagier0000644000175000017500000000202714676526175020274 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$), see ``Convergence acceleration of alternating series'', Cohen et al., \emph{Experiment.~Math.}, vol.~9, 2000, pp.~3--12. If $m < 0$ or $m \ge n$, $P_{n}^{(m)} = 0$. We have $P_{n} := P_{n}^{(0)}$ is $T_{n}(2x-1)$, where $T_{n}$ is the Legendre polynomial of the second kind. For $n > m > 0$, $P_{n}^{(m)}$ is the $m$-th difference with step $2$ of the sequence $n^{m+1}P_{n}$; in this case, it satisfies $$2 P_{n}^{(m)}(sin^{2} t) = \dfrac{d^{m+1}}{dt^{m+1}} (\sin(2t)^{m} \sin(2(n-m)t)).$$ %@article {MR2001m:11222, % AUTHOR = {Cohen, Henri and Rodriguez Villegas, Fernando and Zagier, Don}, % TITLE = {Convergence acceleration of alternating series}, % JOURNAL = {Experiment. Math.}, % VOLUME = {9}, % YEAR = {2000}, % NUMBER = {1}, % PAGES = {3--12}, %} pari-2.17.2/src/functions/polynomials/fftinv0000644000175000017500000000166414676526175017602 0ustar billbillFunction: fftinv Section: polynomials C-Name: FFTinv Prototype: GG Help: fftinv(w,P): given w from rootsof1, return the inverse Fourier transform of P. Doc: Let $w=[1,z,\ldots,z^{N-1}]$ from some primitive $N$-roots of unity $z$ where $N$ is a power of $2$, and $P$ be a polynomial $< N$, return the unnormalized discrete Fourier transform of $P$, $\{ P(1 / w[i]), 1 \leq i \leq N\}$. Also allow $P$ to be a vector $[p_{0},\dots,p_{n}]$ representing the polynomial $\sum_{i} p_{i} X^{i}$. Composing \kbd{fft} and \kbd{fftinv} returns $N$ times the original input coefficients. \bprog ? w = rootsof1(4); fft(w, x^3+x+1) %1 = [3, 1, -1, 1] ? fftinv(w, %) %2 = [4, 4, 0, 4] ? Polrev(%) / 4 %3 = x^3 + x + 1 ? N = 512; w = rootsof1(N); T = random(1000 * x^(N-1)); ? U = fft(w, T); time = 3 ms. ? V = vector(N, i, subst(T, 'x, w[i])); time = 65 ms. ? exponent(V - U) %7 = -97 ? round(Polrev(fftinv(w,U) / N)) == T %8 = 1 @eprog pari-2.17.2/src/functions/polynomials/poltomonic0000644000175000017500000000232314676526175020462 0ustar billbillFunction: poltomonic Section: polynomials C-Name: poltomonic Prototype: GD& Help: poltomonic(T,{&L}): T in Q[x]; returns U monic in Z[x] such that U(x) = C T(x/L) for some rational C and L. If &L is given, set it to L. Doc: let $T \in \Q[x]$ be a nonzero polynomial; returns $U$ monic in $\Z[x]$ such that $U(x) = C T(x/L)$ for some $C,L\in \Q$. If the pointer argument \kbd{\&L} is present, set \kbd{L} to $L$. \bprog ? poltomonic(9*x^2 - 1/2) %1 = x^2 - 2 ? U = poltomonic(9*x^2 - 1/2, &L) %2 = x^2 - 2 ? L %3 = 6 ? U / subst(9*x^2 - 1/2, x, x/L) %4 = 4 @eprog This function does not compute discriminants or maximal orders and runs with complexity almost linear in the input size. If $T$ is already monic with integer coefficient, \kbd{poltomonic} may still transform it if $\Z[x]/(T)$ is contained in a trivial subring of the maximal order, generated by $L x$: \bprog ? poltomonic(x^2 + 4, &L) %5 = x^2 + 1 ? L %6 = 1/2 @eprog\noindent If $T$ is irreducible, the functions \kbd{polredabs} (exponential time) and \kbd{polredbest} (polynomial time) also find a monic integral generating polynomial for the number field $\Q[x]/(T)$, with explicit guarantees on its size, but are orders of magnitude slower. pari-2.17.2/src/functions/polynomials/polresultant0000644000175000017500000000434314760123736021025 0ustar billbillFunction: polresultant Section: polynomials C-Name: polresultant0 Prototype: GGDnD0,L, Help: polresultant(x,y,{v},{flag=0}): resultant of the polynomials x and y, with respect to the main variables of x and y if v is omitted, with respect to the variable v otherwise. flag is optional, and can be 0: default, uses either the subresultant algorithm, a modular algorithm or Sylvester's matrix, depending on the inputs; 1 uses Sylvester's matrix (should always be slower than the default). Doc: resultant of the two polynomials $x$ and $y$ with exact entries, with respect to the main variables of $x$ and $y$ if $v$ is omitted, with respect to the variable $v$ otherwise. The algorithm assumes the base ring is a domain. If you also need the $u$ and $v$ such that $x*u + y*v = \text{Res}(x,y)$, use the \tet{polresultantext} function. If $\fl=0$ (default), uses the 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. If $x$ or $y$ are multivariate with a huge \emph{polynomial} content, it is advisable to remove it before calling this function. Compare: \bprog ? a = polcyclo(7) * ((t+1)/(t+2))^100; ? b = polcyclo(11)* ((t+2)/(t+3))^100); ? polresultant(a,b); time = 3,833 ms. ? ca = content(a); cb = content(b); \ polresultant(a/ca,b/cb)*ca^poldegree(b)*cb*poldegree(a); \\ instantaneous @eprog\noindent The function only removes rational denominators and does not compute automatically the content because it is generically small and potentially \emph{very} expensive (e.g. in multivariate contexts). The choice is yours, depending on your application. Function: _ZX_resultant_worker C-Name: ZX_resultant_worker Prototype: GGGG Section: programming/internals Help: worker for ZX_resultant Function: _ZX_ZXY_resultant_worker C-Name: ZX_ZXY_resultant_worker Prototype: GGGGG Section: programming/internals Help: worker for ZX_ZXY_resultant Function: _ZXQX_resultant_worker C-Name: ZXQX_resultant_worker Prototype: GGGGG Section: programming/internals Help: worker for ZXQX_resultant pari-2.17.2/src/functions/polynomials/poliscycloprod0000644000175000017500000000076114557721031021332 0ustar billbillFunction: poliscycloprod Section: polynomials C-Name: poliscycloprod Prototype: lG Help: poliscycloprod(f): returns 1 if f is a product of cyclotomic polynonials, and 0 otherwise. Doc: returns 1 if $f$ is a product of cyclotomic polynomial, and $0$ otherwise. \bprog ? f = x^6+x^5-x^3+x+1; ? poliscycloprod(f) %2 = 1 ? factor(f) %3 = [ x^2 + x + 1 1] [x^4 - x^2 + 1 1] ? [ poliscyclo(T) | T <- %[,1] ] %4 = [3, 12] ? polcyclo(3) * polcyclo(12) %5 = x^6 + x^5 - x^3 + x + 1 @eprog pari-2.17.2/src/functions/polynomials/derivn0000644000175000017500000000277014567450071017562 0ustar billbillFunction: derivn Section: polynomials C-Name: derivn Prototype: GLDn Help: derivn(x,n,{v}): n-th derivative of x with respect to v, or to the main variable of x if v is omitted. Doc: $n$-th derivative of $x$ with respect to the main variable if $v$ is omitted, and with respect to $v$ otherwise; the integer $n$ must be nonnegative. The derivative of a scalar type is zero, and the derivative of a vector or matrix is done componentwise. One can use $x'$, $x''$, etc., 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$. \bprog ? f = (x/y)^5; ? derivn(f, 2) %2 = 20/y^5*x^3 ? f'' %3 = 20/y^5*x^3 ? derivn(f, 2, 'x) \\ same since 'x is the main variable %4 = 20/y^5*x^3 ? derivn(f, 2, 'y) %5 = 30/y^7*x^5 @eprog This function also operates on closures, in which case the variable must be omitted. It returns a closure performing a numerical differentiation as per \kbd{derivnum}: \bprog ? f(x) = x^10; ? g = derivn(f, 5) ? g(1) %3 = 30240.000000000000000000000000000000000 ? derivn(zeta, 2)(0) %4 = -2.0063564559085848512101000267299604382 ? zeta''(0) %5 = -2.0063564559085848512101000267299604382 @eprog pari-2.17.2/src/functions/polynomials/polcoeff0000644000175000017500000000063714567450071020070 0ustar billbillFunction: polcoeff Section: polynomials C-Name: polcoef Prototype: GLDn Help: polcoeff(x,n,{v}): deprecated alias for polcoef. Description: (pol, 0):gen:copy constant_coeff($1) (pol, 0,):gen:copy constant_coeff($1) (pol, small):gen:copy RgX_coeff($1, $2) (pol, small,):gen:copy RgX_coeff($1, $2) (gen, small, ?var):gen polcoef($1, $2, $3) Obsolete: 2018-05-14 Doc: Deprecated alias for polcoef. pari-2.17.2/src/functions/polynomials/polisclass0000644000175000017500000000127614676526175020461 0ustar billbillFunction: polisclass Section: polynomials C-Name: polisclass Prototype: lG Help: polisclass(P): P being a monic irreducible polynomial with integer coefficients, return 0 if P is not a class polynomial for the j-invariant, otherwise return the discriminant D<0 such that P=polclass(D). Doc: $P$ being a monic irreducible polynomial with integer coefficients, return $0$ if $P$ is not a class polynomial for the $j$-invariant, otherwise return the discriminant $D<0$ such that \kbd{P=polclass(D)}. \bprog ? polisclass(polclass(-47)) %1 = -47 ? polisclass(x^5+x+1) %2 = 0 ? apply(polisclass,factor(poldisc(polmodular(5)))[,1]) %3 = [-16,-4,-3,-11,-19,-64,-36,-24,-51,-91,-99,-96,-84]~ @eprog pari-2.17.2/src/functions/polynomials/subst0000644000175000017500000000220414567450071017423 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$. If $z$ is a vector, return the vector of the evaluated expressions \kbd{subst(x, y, z[i])}. 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. 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.17.2/src/functions/polynomials/thue0000644000175000017500000000620114567450071017231 0ustar billbillFunction: thue Section: polynomials C-Name: thue Prototype: GGDG Help: thue(tnf,a,{sol}): solve the equation P(x,y)=a, where tnf was created with thueinit(P), and sol, if present, contains the solutions of Norm(x)=a modulo units in the number field defined by P. If tnf was computed without assuming GRH (flag 1 in thueinit), the result is unconditional. If tnf is a polynomial, compute thue(thueinit(P,0), a). Doc: returns all solutions of the equation $P(x,y)=a$ in integers $x$ and $y$, where \var{tnf} was created with $\kbd{thueinit}(P)$. If present, \var{sol} must contain the solutions of $\Norm(x)=a$ modulo units of positive norm in the number field defined by $P$ (as computed by \kbd{bnfisintnorm}). If there are infinitely many solutions, an error is issued. It is allowed to input directly the polynomial $P$ instead of a \var{tnf}, in which case, the function first performs \kbd{thueinit(P,0)}. This is very wasteful if more than one value of $a$ is required. If \var{tnf} was computed without assuming GRH (flag $1$ in \tet{thueinit}), then the result is unconditional. Otherwise, it depends in principle of the truth of the GRH, but may still be unconditionally correct in some favorable cases. The result is conditional on the GRH if $a\neq \pm 1$ and $P$ has a single irreducible rational factor, whose attached tentative class number $h$ and regulator $R$ (as computed assuming the GRH) satisfy \item $h > 1$, \item $R/0.2 > 1.5$. Here's how to solve the Thue equation $x^{13} - 5y^{13} = - 4$: \bprog ? tnf = thueinit(x^13 - 5); ? thue(tnf, -4) %1 = [[1, 1]] @eprog\noindent In this case, one checks that \kbd{bnfinit(x\pow13 -5).no} is $1$. Hence, the only solution is $(x,y) = (1,1)$ and the result is unconditional. On the other hand: \bprog ? P = x^3-2*x^2+3*x-17; tnf = thueinit(P); ? thue(tnf, -15) %2 = [[1, 1]] \\ a priori conditional on the GRH. ? K = bnfinit(P); K.no %3 = 3 ? K.reg %4 = 2.8682185139262873674706034475498755834 @eprog This time the result is conditional. All results computed using this particular \var{tnf} are likewise conditional, \emph{except} for a right-hand side of $\pm 1$. The above result is in fact correct, so we did not just disprove the GRH: \bprog ? tnf = thueinit(x^3-2*x^2+3*x-17, 1 /*unconditional*/); ? thue(tnf, -15) %4 = [[1, 1]] @eprog Note that reducible or nonmonic 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. \misctitle{Note} When $P$ is irreducible without a real root, the default strategy is to use brute force enumeration in time $|a|^{1/\deg P}$ and avoid computing a tough \var{bnf} attached to $P$, see \kbd{thueinit}. Besides reusing a quantity you might need for other purposes, the default argument \emph{sol} can also be used to use a different strategy and prove that there are no solutions; of course you need to compute a \var{bnf} on you own to obtain \emph{sol}. If there \emph{are} solutions this won't help unless $P$ is quadratic, since the enumeration will be performed in any case. pari-2.17.2/src/functions/polynomials/serlaplace0000644000175000017500000000054314676526175020414 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 nonnegative exponents or a polynomial. If $x=\sum (a_{k}/k!)*X^{k}$ then the result isi $\sum a_{k}*X^{k}$. pari-2.17.2/src/functions/polynomials/polrootsreal0000644000175000017500000000345514676526175021033 0ustar billbillFunction: polrootsreal Section: polynomials C-Name: realroots Prototype: GDGp Description: (gen,?gen):vec:prec realroots($1, $2, $prec) Help: polrootsreal(T,{ab}): real roots of the polynomial T with real coefficients, using Uspensky's method. In interval ab = [a,b] if present. Doc: real roots of the polynomial $T$ with real coefficients, multiple roots being included according to their multiplicity. If the polynomial does not have rational coefficients, it is first rescaled and rounded. The roots are given to a relative accuracy of \kbd{realprecision}. If argument \var{ab} is present, it must be a vector $[a,b]$ with two components (of type \typ{INT}, \typ{FRAC} or \typ{INFINITY}) and we restrict to roots belonging to that closed interval. \bprog ? \p9 ? polrootsreal(x^2-2) %1 = [-1.41421356, 1.41421356]~ ? polrootsreal(x^2-2, [1,+oo]) %2 = [1.41421356]~ ? polrootsreal(x^2-2, [2,3]) %3 = []~ ? polrootsreal((x-1)*(x-2), [2,3]) %4 = [2.00000000]~ @eprog\noindent The algorithm used is a modification of Uspensky's method (relying on Descartes's rule of sign), following Rouillier and Zimmerman's article ``Efficient isolation of a polynomial real roots'' (\url{https://hal.inria.fr/inria-00072518/}). Barring bugs, it is guaranteed to converge and to give the roots to the required accuracy. \misctitle{Remark} If the polynomial $T$ is of the form $Q(x^{h})$ for some $h\geq 2$ and \var{ab} is omitted, the routine will apply the algorithm to $Q$ (restricting to nonnegative roots when $h$ is even), then take $h$-th roots. On the other hand, if you want to specify \var{ab}, you should apply the routine to $Q$ yourself and a suitable interval $[a',b']$ using approximate $h$-th roots adapted to your problem: the function will not perform this change of variables if \var{ab} is present. pari-2.17.2/src/functions/polynomials/padicfields0000644000175000017500000000346714676526175020560 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 nonisomorphic extensions; in particular, the number of polynomials is the number of classes of nonisomorphic 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.17.2/src/functions/polynomials/polsylvestermatrix0000644000175000017500000000121614567450071022265 0ustar billbillFunction: polsylvestermatrix Section: polynomials C-Name: sylvestermatrix Prototype: GG Help: polsylvestermatrix(x,y): forms the sylvester matrix attached 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.17.2/src/functions/polynomials/polfromroots0000644000175000017500000000075714676526175021055 0ustar billbillFunction: polfromroots Section: polynomials C-Name: polfromroots Prototype: GDn Help: polfromroots(a,{v=x}): returns the monic polynomial in variable v whose roots are the components of the vector a with multiplicities. Doc: returns the monic polynomial in variable \kbd{v} whose roots are the components of the vector $a$ with multiplicities, that is $\prod_{i} (x - a_{i})$. \bprog ? polfromroots([1,2,3]) %1 = x^3 - 6*x^2 + 11*x - 6 ? polfromroots([z, -z], 'y) %2 = y^2 - z^2 @eprog pari-2.17.2/src/functions/polynomials/polteichmuller0000644000175000017500000000216314676526175021331 0ustar billbillFunction: polteichmuller Section: polynomials C-Name: polteichmuller Prototype: GUL Help: polteichmuller(T,p,r): return the polynomial whose roots (resp. leading coef) are the Teichmuller lift of the roots (resp. leading coef) of T, to p-adic precision r. Doc: given $T \in \F_{p}[X]$ return the polynomial $P\in \Z_{p}[X]$ whose roots (resp.~leading coefficient) are the Teichmuller lifts of the roots (resp.~leading coefficient) of $T$, to $p$-adic precision $r$. If $T$ is monic, $P$ is the reduction modulo $p^{r}$ of the unique monic polynomial congruent to $T$ modulo $p$ such that $P(X^{p}) = 0 \pmod{P(X),p^{r}}$. \bprog ? T = ffinit(3, 3, 't) %1 = Mod(1,3)*t^3 + Mod(1,3)*t^2 + Mod(1,3)*t + Mod(2,3) ? P = polteichmuller(T,3,5) %2 = t^3 + 166*t^2 + 52*t + 242 ? subst(P, t, t^3) % (P*Mod(1,3^5)) %3 = Mod(0, 243) ? [algdep(a+O(3^5),2) | a <- Vec(P)] %4 = [x - 1, 5*x^2 + 1, x^2 + 4*x + 4, x + 1] @eprog\noindent When $T$ is monic and irreducible mod $p$, this provides a model $\Q_{p}[X]/(P)$ of the unramified extension $\Q_{p}[X] / (T)$ where the Frobenius has the simple form $X \mod P \mapsto X^{p} \mod P$. pari-2.17.2/src/functions/polynomials/serreverse0000644000175000017500000000061614567450071020455 0ustar billbillFunction: serreverse Section: polynomials C-Name: serreverse Prototype: G Help: serreverse(s): reversion of the power series s. Doc: reverse power series of $s$, i.e. the series $t$ such that $t(s) = x$; $s$ must be a power series whose valuation is exactly equal to one. \bprog ? \ps 8 ? t = serreverse(tan(x)) %2 = x - 1/3*x^3 + 1/5*x^5 - 1/7*x^7 + O(x^8) ? tan(t) %3 = x + O(x^8) @eprog pari-2.17.2/src/functions/linear_algebra/0000755000175000017500000000000014760315601016715 5ustar billbillpari-2.17.2/src/functions/linear_algebra/qfgaussred0000644000175000017500000000360614676526175021031 0ustar billbillFunction: qfgaussred Section: linear_algebra C-Name: qfgaussred0 Prototype: GD0,L, Help: qfgaussred(q,{flag=0}): square reduction of the symmetric matrix q. flag=0: returns a square matrix A such that q(x) = sum_i A[i,i] (x[i] + sum_{j != i} A[i,j] x[j])^2; flag=1 return [U,V] where U is a square matrix and V a vector such that q = U~ * matdiagonal(V) * U Doc: \idx{decomposition into squares} of the quadratic form represented by the symmetric matrix $q$. If $\fl=0$ (default), the result is a matrix $M$ 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_{i,i} (x_{i} + \sum_{j \neq i} a_{i,j} 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}$. Singular matrices are supported, in which case some diagonal coefficients vanish: \bprog ? qfgaussred([1,1;1,1]) %2 = [1 1] [1 0] @eprog\noindent This means that $x^{2} + 2xy + y^{2} = (x+y)^{2}$. If $\fl=1$, return \kbd{[U,V]} where $U$ is a square matrix and $V$ a vector, such that if \kbd{D=matdiagonal(V)}, $q = {^{t}} U D U$. More precisely $$ q(x) = \sum_{i} D_{i} (\sum_{j} U_{i,j} x_{j})^{2} $$ and the matrix $M$ is recovered as $M = U + D - 1$. \bprog ? q = [0,1;1,0]; ? [U,V] = qfgaussred(q,1); D = matdiagonal(V); ? U~*D*U %5 = [0 1] [1 0] ? U+D-1 %6 = [1/2 1] [ -1 -1/2] @eprog Variant: See also the functions \fun{GEN}{qfgaussred}{GEN a} (for \kbd{qfgaussred(a,0)}), \fun{GEN}{qfgaussred2}{GEN a} (for \kbd{qfgaussred0(a,1)}). Finally, the function \fun{GEN}{qfgaussred_positive}{GEN q} assumes that $q$ is positive definite and is a little faster; returns \kbd{NULL} if a vector with negative norm occurs (non positive matrix or too many rounding errors). pari-2.17.2/src/functions/linear_algebra/qfeval0000644000175000017500000000514314567450071020127 0ustar billbillFunction: qfeval Section: linear_algebra C-Name: qfeval0 Prototype: DGGDG Help: qfeval({q},x,{y}): evaluate the quadratic form q (symmetric matrix) at x; if y is present, evaluate the polar form at (x,y); if q omitted, use the standard Euclidean form. Doc: evaluate the quadratic form $q$ (given by a symmetric matrix) at the vector $x$; if $y$ is present, evaluate the polar form at $(x,y)$; if $q$ omitted, use the standard Euclidean scalar product, corresponding to the identity matrix. Roughly equivalent to \kbd{x\til * q * y}, but a little faster and more convenient (does not distinguish between column and row vectors): \bprog ? x = [1,2,3]~; y = [-1,3,1]~; q = [1,2,3;2,2,-1;3,-1,9]; ? qfeval(q,x,y) %2 = 23 ? for(i=1,10^6, qfeval(q,x,y)) time = 661ms ? for(i=1,10^6, x~*q*y) time = 697ms @eprog\noindent The speedup is noticeable for the quadratic form, compared to \kbd{x\til * q * x}, since we save almost half the operations: \bprog ? for(i=1,10^6, qfeval(q,x)) time = 487ms @eprog\noindent The special case $q = \text{Id}$ is handled faster if we omit $q$ altogether: \bprog ? qfeval(,x,y) %6 = 8 ? q = matid(#x); ? for(i=1,10^6, qfeval(q,x,y)) time = 529 ms. ? for(i=1,10^6, qfeval(,x,y)) time = 228 ms. ? for(i=1,10^6, x~*y) time = 274 ms. @eprog We also allow \typ{MAT}s of compatible dimensions for $x$, and return \kbd{x\til * q * x} in this case as well: \bprog ? M = [1,2,3;4,5,6;7,8,9]; qfeval(,M) \\ Gram matrix %5 = [66 78 90] [78 93 108] [90 108 126] ? q = [1,2,3;2,2,-1;3,-1,9]; ? for(i=1,10^6, qfeval(q,M)) time = 2,008 ms. ? for(i=1,10^6, M~*q*M) time = 2,368 ms. ? for(i=1,10^6, qfeval(,M)) time = 1,053 ms. ? for(i=1,10^6, M~*M) time = 1,171 ms. @eprog If $q$ is a \typ{QFB}, it is implicitly converted to the attached symmetric \typ{MAT}. This is done more efficiently than by direct conversion, since we avoid introducing a denominator $2$ and rational arithmetic: \bprog ? q = Qfb(2,3,4); x = [2,3]; ? qfeval(q, x) %2 = 62 ? Q = Mat(q) %3 = [ 2 3/2] [3/2 4] ? qfeval(Q, x) %4 = 62 ? for (i=1, 10^6, qfeval(q,x)) time = 758 ms. ? for (i=1, 10^6, qfeval(Q,x)) time = 1,110 ms. @eprog Finally, when $x$ is a \typ{MAT} with \emph{integral} coefficients, we allow a \typ{QFB} for $q$ and return the binary quadratic form $q \circ M$. Again, the conversion to \typ{MAT} is less efficient in this case: \bprog ? q = Qfb(2,3,4); Q = Mat(q); x = [1,2;3,4]; ? qfeval(q, x) %2 = Qfb(47, 134, 96) ? qfeval(Q,x) %3 = [47 67] [67 96] ? for (i=1, 10^6, qfeval(q,x)) time = 701 ms. ? for (i=1, 10^6, qfeval(Q,x)) time = 1,639 ms. @eprog pari-2.17.2/src/functions/linear_algebra/matrixqz0000644000175000017500000000311314676526175020535 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$. If $p=-1$, returns a basis of the lattice $\Z^{m} \cap \text{Im}_{\Z} A$. If $p=-2$, returns a basis of the lattice $\Z^{m} \cap \text{Im}_{\Q} A$. \misctitle{Caveat} ($p=-1$ or $-2$) For efficiency reason, we do not compute the HNF of the resulting basis. \bprog ? minors(x) = vector(#x[,1], i, matdet(x[^i,])); ? A = [3,1/7; 5,3/7; 7,5/7]; minors(A) %1 = [4/7, 8/7, 4/7] \\ determinants of all 2x2 minors ? B = matrixqz(A) %2 = [3 1] [5 2] [7 3] ? minors(%) %3 = [1, 2, 1] \\ B integral with coprime minors ? matrixqz(A,-1) %4 = [3 1] [5 3] [7 5] ? matrixqz(A,-2) %5 = [3 1] [5 2] [7 3] @eprog pari-2.17.2/src/functions/linear_algebra/HEADER0000644000175000017500000000162114567450071017576 0ustar billbillFunction: _header_linear_algebra Class: header Section: linear_algebra Doc: \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 nonzero pivot turns out to be noninvertible. Some functions, e.g.~\kbd{mathnf} or \kbd{mathnfmod}, specifically assume that the base ring is $\Z$. pari-2.17.2/src/functions/linear_algebra/matqr0000644000175000017500000000167014567450071017776 0ustar billbillFunction: matqr Section: linear_algebra C-Name: matqr Prototype: GD0,L,p Help: matqr(M,{flag=0}): returns [Q,R], the QR-decomposition of the square invertible matrix M. If flag=1, Q is given as a sequence of Householder transforms (faster and stabler). Doc: returns $[Q,R]$, the \idx{QR-decomposition} of the square invertible matrix $M$ with real entries: $Q$ is orthogonal and $R$ upper triangular. If $\fl=1$, the orthogonal matrix is returned as a sequence of Householder transforms: applying such a sequence is stabler and faster than multiplication by the corresponding $Q$ matrix.\sidx{Householder transform} More precisely, if \bprog [Q,R] = matqr(M); [q,r] = matqr(M, 1); @eprog\noindent then $r = R$ and \kbd{mathouseholder}$(q, M)$ is (close to) $R$; furthermore \bprog mathouseholder(q, matid(#M)) == Q~ @eprog\noindent the inverse of $Q$. This function raises an error if the precision is too low or $x$ is singular. pari-2.17.2/src/functions/linear_algebra/mathnfmod0000644000175000017500000000143014567450071020621 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 nonzero 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 (nonzero) 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.17.2/src/functions/linear_algebra/matindexrank0000644000175000017500000000115714567450071021337 0ustar billbillFunction: matindexrank Section: linear_algebra C-Name: indexrank Prototype: G Description: (gen):vecvecsmall indexrank($1) Help: matindexrank(M): gives two extraction vectors (rows and columns) for the matrix M such that the extracted matrix is square of maximal rank. Doc: $M$ 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}(M,y,z)$ is invertible. The vectors $y$ and $z$ are sorted in increasing order. pari-2.17.2/src/functions/linear_algebra/qfrep0000644000175000017500000000212614557721031017760 0ustar billbillFunction: qfrep Section: linear_algebra C-Name: qfrep0 Prototype: GGD0,L, Help: qfrep(q,B,{flag=0}): vector of (half) the number of vectors of norms from 1 to B for the integral and definite quadratic form q. If flag is 1, count vectors of even norm from 1 to 2B. Doc: $q$ being a square and symmetric matrix with integer entries representing a positive definite quadratic form, count the vectors representing successive integers. \item If $\fl = 0$, count all vectors. Outputs the vector whose $i$-th entry, $1 \leq i \leq B$ is half the number of vectors $v$ such that $q(v)=i$. \item If $\fl = 1$, count vectors of even norm. Outputs the vector whose $i$-th entry, $1 \leq i \leq B$ is half the number of vectors such that $q(v) = 2i$. \bprog ? q = [2, 1; 1, 3]; ? qfrep(q, 5) %2 = Vecsmall([0, 1, 2, 0, 0]) \\ 1 vector of norm 2, 2 of norm 3, etc. ? qfrep(q, 5, 1) %3 = Vecsmall([1, 0, 0, 1, 0]) \\ 1 vector of norm 2, 0 of norm 4, etc. @eprog\noindent This routine uses a naive algorithm based on \tet{qfminim}, and will fail if any entry becomes larger than $2^{31}$ (or $2^{63}$). pari-2.17.2/src/functions/linear_algebra/matadjoint0000644000175000017500000000216714676526175021020 0ustar billbillFunction: matadjoint Section: linear_algebra C-Name: matadjoint0 Prototype: GD0,L, Help: matadjoint(M,{flag=0}): adjoint matrix of M using Leverrier-Faddeev's algorithm. If flag is 1, computes the characteristic polynomial independently first. Doc: \idx{adjoint matrix} of $M$, i.e.~a matrix $N$ of cofactors of $M$, satisfying $M*N=\det(M)*\Id$. $M$ must be a (not necessarily invertible) square matrix of dimension $n$. If $\fl$ is 0 or omitted, we try to use Leverrier-Faddeev's algorithm, which assumes that $n!$ invertible. If it fails or $\fl = 1$, computes $T = \kbd{charpoly}(M)$ independently first and returns $(-1)^{n-1} (T(x)-T(0))/x$ evaluated at $M$. \bprog ? a = [1,2,3;3,4,5;6,7,8] * Mod(1,4); ? matadjoint(a) %2 = [Mod(1, 4) Mod(1, 4) Mod(2, 4)] [Mod(2, 4) Mod(2, 4) Mod(0, 4)] [Mod(1, 4) Mod(1, 4) Mod(2, 4)] @eprog\noindent Both algorithms use $O(n^{4})$ operations in the base ring. Over a field, they are usually slower than computing the characteristic polynomial or the inverse of $M$ directly. Variant: Also available are \fun{GEN}{adj}{GEN x} ($\fl=0$) and \fun{GEN}{adjsafe}{GEN x} ($\fl=1$). pari-2.17.2/src/functions/linear_algebra/setunion0000644000175000017500000000044214557721031020506 0ustar billbillFunction: setunion Section: linear_algebra C-Name: setunion Prototype: GG Help: setunion(x,y): union of the sets x and y. Description: (vec, vec):vec setunion($1, $2) Doc: union of the two sets $x$ and $y$ (see \kbd{setisset}). If $x$ or $y$ is not a set, the result is undefined. pari-2.17.2/src/functions/linear_algebra/matsolvemod0000644000175000017500000000321314676526175021211 0ustar billbillFunction: matsolvemod Section: linear_algebra C-Name: matsolvemod 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 nonzero return all solutions. Doc: $M$ being any integral matrix, $D$ a column vector of nonnegative integer moduli, and $B$ an integral column vector, gives an 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 the integer zero. Note that we explicitly allow $d_{i} = 0$ corresponding to an equality in $\Z$. 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$). Again, $D = 0$ solves the linear system of equations over $\Z$. \bprog ? M = [1,2;3,4]; ? matsolvemod(M, [3,4]~, [1,2]~) %2 = [10, 0]~ ? matsolvemod(M, 3, 1) \\ M X = [1,1]~ over F_3 %3 = [2, 1]~ ? matsolvemod(M, [3,0]~, [1,2]~) \\ x + 2y = 1 (mod 3), 3x + 4y = 2 (in Z) %4 = [6, -4]~ ? matsolvemod(M, 0, [1,2]~) \\ no solution in Z for x + 2y = 1, 3x + 4y = 2 @eprog If $\fl=1$, all solutions are returned in the form of a two-component row vector $[x,u]$, where $x$ is an 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.17.2/src/functions/linear_algebra/mathilbert0000644000175000017500000000050714567450071021003 0ustar billbillFunction: mathilbert Section: linear_algebra C-Name: mathilbert Prototype: L Help: mathilbert(n): Hilbert matrix of order n. Doc: creates the \idx{Hilbert matrix} of order $n \geq 0$, i.e.~the square matrix $H$ whose coefficient $H[i,j]$ is $1 / (i+j-1)$. This matrix is ill-conditionned but its inverse has integer entries. pari-2.17.2/src/functions/linear_algebra/concat0000644000175000017500000000502214567450071020114 0ustar billbillFunction: concat Section: linear_algebra C-Name: gconcat 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: (vecvecsmall,vecvecsmall):vecvecsmall gconcat($1, $2) (vecvecsmall):vecsmall gconcat1($1) (mp,mp):vec gconcat($1, $2) (vec,mp):vec gconcat($1, $2) (mp,vec):vec gconcat($1, $2) (vec,vec):vec gconcat($1, $2) (list,list):list gconcat($1, $2) (genstr,gen):genstr gconcat($1, $2) (gen,genstr):genstr gconcat($1, $2) (gen):gen gconcat1($1) (gen,):gen gconcat1($1) (gen,gen):gen gconcat($1, $2) Doc: concatenation of $x$ and $y$. If $x$ or $y$ is not a vector or matrix, it is considered as a one-dimensional vector. All types are allowed for $x$ and $y$, but the sizes must be compatible. Note that matrices are concatenated horizontally, i.e.~the number of rows stays the same. Using transpositions, one can concatenate them vertically, but it is often simpler to use \tet{matconcat}. \bprog ? x = matid(2); y = 2*matid(2); ? concat(x,y) %2 = [1 0 2 0] [0 1 0 2] ? concat(x~,y~)~ %3 = [1 0] [0 1] [2 0] [0 2] ? matconcat([x;y]) %4 = [1 0] [0 1] [2 0] [0 2] @eprog\noindent To concatenate vectors sideways (i.e.~to obtain a two-row or two-column matrix), use \tet{Mat} instead, or \tet{matconcat}: \bprog ? x = [1,2]; ? y = [3,4]; ? concat(x,y) %3 = [1, 2, 3, 4] ? Mat([x,y]~) %4 = [1 2] [3 4] ? matconcat([x;y]) %5 = [1 2] [3 4] @eprog Concatenating a row vector to a matrix having the same number of columns will add the row to the matrix (top row if the vector is $x$, i.e.~comes first, and bottom row otherwise). The empty matrix \kbd{[;]} is considered to have a number of rows compatible with any operation, in particular concatenation. (Note that this is \emph{not} the case for empty vectors \kbd{[~]} or \kbd{[~]\til}.) If $y$ is omitted, $x$ has to be a row vector or a list, in which case its elements are concatenated, from left to right, using the above rules. \bprog ? concat([1,2], [3,4]) %1 = [1, 2, 3, 4] ? a = [[1,2]~, [3,4]~]; concat(a) %2 = [1 3] [2 4] ? concat([1,2; 3,4], [5,6]~) %3 = [1 2 5] [3 4 6] ? concat([%, [7,8]~, [1,2,3,4]]) %5 = [1 2 5 7] [3 4 6 8] [1 2 3 4] @eprog Variant: \fun{GEN}{gconcat1}{GEN x} is a shortcut for \kbd{gconcat(x,NULL)}. pari-2.17.2/src/functions/linear_algebra/minpoly0000644000175000017500000000067414567450071020344 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$. Function: _ZXQ_minpoly_worker C-Name: ZXQ_minpoly_worker Prototype: GGGL Section: programming/internals Help: worker for ZXQ_minpoly pari-2.17.2/src/functions/linear_algebra/normlp0000644000175000017500000000267614676526175020202 0ustar billbillFunction: normlp Section: linear_algebra C-Name: gnormlp Prototype: GDGp Help: normlp(x,{p=oo}): Lp-norm of x; sup norm if p is omitted. Description: (gen):gen:prec gsupnorm($1, $prec) (gen,):gen:prec gsupnorm($1, $prec) (gen,1):gen:prec gnorml1($1, $prec) Doc: $L^{p}$-norm of $x$; sup norm if $p$ is omitted or \kbd{+oo}. More precisely, if $x$ is a scalar, \kbd{normlp}$(x, p)$ is defined to be \kbd{abs}$(x)$. If $x$ is a polynomial, a (row or column) vector or a matrix: \item if $p$ is omitted or \kbd{+oo}, then \kbd{normlp($x$)} is defined recursively as $\max_{i} \kbd{normlp}(x_{i}))$, where $x_{i}$ runs through the components of~$x$. In particular, this yields the usual sup norm if $x$ is a polynomial or vector with complex components. \item otherwise, \kbd{normlp($x$, $p$)} is defined recursively as $(\sum_{i} \kbd{normlp}^{p}(x_{i},p))^{1/p}$. In particular, this yields the usual $(\sum_{i} |x_{i}|^{p})^{1/p}$ if $x$ is a polynomial or vector with complex components. \bprog ? v = [1,-2,3]; normlp(v) \\ vector %1 = 3 ? normlp(v, +oo) \\ same, more explicit %2 = 3 ? M = [1,-2;-3,4]; normlp(M) \\ matrix %3 = 4 ? T = (1+I) + I*x^2; normlp(T) %4 = 1.4142135623730950488016887242096980786 ? normlp([[1,2], [3,4], 5, 6]) \\ recursively defined %5 = 6 ? normlp(v, 1) %6 = 6 ? normlp(M, 1) %7 = 10 ? normlp(T, 1) %8 = 2.4142135623730950488016887242096980786 @eprog pari-2.17.2/src/functions/linear_algebra/matid0000644000175000017500000000030413637407207017741 0ustar billbillFunction: matid Section: linear_algebra C-Name: matid Prototype: L Help: matid(n): identity matrix of order n. Description: (small):vec matid($1) Doc: creates the $n\times n$ identity matrix. pari-2.17.2/src/functions/linear_algebra/matsnf0000644000175000017500000000403514676526175020152 0ustar billbillFunction: matsnf Section: linear_algebra C-Name: matsnf0 Prototype: GD0,L, Help: matsnf(X,{flag=0}): Smith normal form (i.e. elementary divisors) of the matrix X, expressed as a vector d; X must have integer or polynomial entries. Binary digits of flag mean 1: returns [u,v,d] where d=u*X*v, otherwise only the diagonal d is returned, 4: removes all information corresponding to entries equal to 1 in d. Doc: if $X$ is a (singular or nonsingular) 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}$. $X$ must have integer or polynomial entries; in the latter case, $X$ must be a square matrix. 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. 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. If $v$ is an output from \kbd{matsnf} and $p$ is a power of an irreducible element, then \kbd{snfrank(v, p)} returns the $p$-rank of the attached module. \bprog ? X = [27,0; 0,3; 1,1; 0,0]; matsnf(X) %1 = [0, 0, 3, 1] ? [U,V,D] = v = matsnf(X, 1); U*X*V == D %2 ? U %3 = [0 0 0 1] [1 9 -27 0] [0 1 0 0] [0 0 1 0] ? V %4 = [-1 1] [ 1 0] ? snfrank(v, 3) %5 = 3 @eprog\noindent Continuing the same example after cleanup: \bprog ? [U,V,D] = v = matsnf(X, 1+4); U*X*V == D %6 = 1 ? D %7 = [0] [0] [3] ? snfrank(v, 3) %8 = 3 ? snfrank(v, 2) %9 = 2 @eprog pari-2.17.2/src/functions/linear_algebra/matfrobenius0000644000175000017500000000130614567450071021344 0ustar billbillFunction: matfrobenius Section: linear_algebra C-Name: matfrobenius Prototype: GD0,L,Dn Help: matfrobenius(M,{flag},{v='x}): return the Frobenius form of the square matrix M. If flag is 1, return only the elementary divisors as a vector of polynomials in the variable v. If flag is 2, return a two-components vector [F,B] where F is the Frobenius form and B is the basis change so that M=B^-1*F*B. Doc: returns the Frobenius form of the square matrix \kbd{M}. If $\fl=1$, returns only the elementary divisors as a vector of polynomials in the variable \kbd{v}. If $\fl=2$, returns a two-components vector [F,B] where \kbd{F} is the Frobenius form and \kbd{B} is the basis change so that $M=B^{-1}FB$. pari-2.17.2/src/functions/linear_algebra/matdet0000644000175000017500000000242414760123736020126 0ustar billbillFunction: matdet Section: linear_algebra C-Name: det0 Prototype: GD0,L, Help: matdet(x,{flag=0}): determinant of the matrix x using an appropriate algorithm depending on the coefficients. If (optional) flag is set to 1, use classical Gaussian elimination (usually worse than the default). Description: (gen, ?0):gen det($1) (gen, 1):gen det2($1) (gen, #small):gen $"incorrect flag in matdet" (gen, small):gen det0($1, $2) Doc: determinant of the square matrix $x$. If $\fl=0$, uses an appropriate algorithm depending on the coefficients: \item integer entries: modular method due to Dixon, Pernet and Stein. \item real or $p$-adic entries: classical Gaussian elimination using maximal pivot. \item intmod entries: classical Gaussian elimination using first nonzero pivot. \item other cases: Gauss-Bareiss. If $\fl=1$, uses classical Gaussian elimination with appropriate pivoting strategy (maximal pivot for real or $p$-adic coefficients). This is usually worse than the default. Variant: Also available are \fun{GEN}{det}{GEN x} ($\fl=0$), \fun{GEN}{det2}{GEN x} ($\fl=1$) and \fun{GEN}{ZM_det}{GEN x} for integer entries. Function: _ZM_det_worker C-Name: ZM_det_worker Prototype: GG Section: programming/internals Help: worker for ZM_det pari-2.17.2/src/functions/linear_algebra/matinvmod0000644000175000017500000000110414567450071020640 0ustar billbillFunction: matinvmod Section: linear_algebra C-Name: matinvmod Prototype: GG Help: matinvmod(x,d): left inverse of the matrix x modulo d. Doc: computes a left inverse of the matrix~$x$ modulo~$d$. The matrix $x$ must have \typ{INT} entries, and $d$ can be an arbitrary positive integer. \bprog ? A = [3,1,2;1,2,1;3,1,1]; ? U = matinvmod(A,6) %2 = [1 1 3] [2 3 5] [1 0 5] ? (U*A)%6 %3 = [1 0 0] [0 1 0] [0 0 1] ? matinvmod(A,5) *** at top-level: matinvmod(A,5) *** ^-------------- *** matinvmod: impossible inverse in gen_inv: 0. @eprog pari-2.17.2/src/functions/linear_algebra/matkermod0000644000175000017500000000122114676526175020637 0ustar billbillFunction: matkermod Section: linear_algebra C-Name: matkermod Prototype: GGD& Help: matkermod(x,d,&im): basis of the kernel of the matrix x modulo d. Doc: gives a Howell basis (unique representation for submodules of~$(\Z/d\Z)^{n}$, cf. \kbd{matimagemod}) for the kernel of the matrix $x$ modulo $d$ as columns of a matrix. The matrix $x$ must have \typ{INT} entries, and $d$ can be an arbitrary positive integer. If $im$ is present, set it to a basis of the image of~$x$ (which is computed on the way). \bprog ? A = [1,2,3;5,1,4] %1 = [1 2 3] [5 1 4] ? K = matkermod(A,6) %2 = [2 1] [2 1] [0 3] ? (A*K)%6 %3 = [0 0] [0 0] @eprog pari-2.17.2/src/functions/linear_algebra/mateigen0000644000175000017500000000267614676526175020464 0ustar billbillFunction: mateigen Section: linear_algebra C-Name: mateigen Prototype: GD0,L,p Help: mateigen(x,{flag=0}): complex eigenvectors of the matrix x given as columns of a matrix H. If flag=1, return [L,H], where L contains the eigenvalues and H the corresponding eigenvectors. Doc: returns the (complex) eigenvectors of $x$ as columns of a matrix. If $\fl=1$, return $[L,H]$, where $L$ contains the eigenvalues and $H$ the corresponding eigenvectors; multiple eigenvalues are repeated according to the eigenspace dimension (which may be less than the eigenvalue multiplicity in the characteristic polynomial). This function first computes the characteristic polynomial of $x$ and approximates its complex roots $(\lambda_{i})$, then tries to compute the eigenspaces as kernels of the $x - \lambda_{i}$. This algorithm is ill-conditioned and is likely to miss kernel vectors if some roots of the characteristic polynomial are close, in particular if it has multiple roots. \bprog ? A = [13,2; 10,14]; mateigen(A) %1 = [-1/2 2/5] [ 1 1] ? [L,H] = mateigen(A, 1); ? L %3 = [9, 18] ? H %4 = [-1/2 2/5] [ 1 1] ? A * H == H * matdiagonal(L) %5 = 1 @eprog\noindent For symmetric matrices, use \tet{qfjacobi} instead; for Hermitian matrices, compute \bprog A = real(x); B = imag(x); y = matconcat([A, -B; B, A]); @eprog\noindent and apply \kbd{qfjacobi} to $y$. Variant: Also available is \fun{GEN}{eigen}{GEN x, long prec} ($\fl = 0$) pari-2.17.2/src/functions/linear_algebra/matsize0000644000175000017500000000053513637407207020325 0ustar billbillFunction: matsize Section: linear_algebra C-Name: matsize Prototype: G Help: matsize(x): number of rows and columns of the vector/matrix x as a 2-vector. Doc: $x$ being a vector or matrix, returns a row vector with two components, the first being the number of rows (1 for a row vector), the second the number of columns (1 for a column vector). pari-2.17.2/src/functions/linear_algebra/qflll0000644000175000017500000001026414676526175017775 0ustar billbillFunction: qflll Section: linear_algebra C-Name: qflll0 Prototype: GD0,L, Help: qflll(x,{flag=0}): LLL reduction of the vectors forming the matrix x (gives the unimodular transformation matrix T such that x*T is LLL-reduced). flag is optional, and can be 0: default, 1: disable FLATTER, 2: assumes x is integral, returns a partially reduced basis, 3: assumes x is integral, in place (return x*T), 4: assumes x is integral, returns [K,T] where K is the integer kernel of x and T the LLL reduced image, 5: same as 4 but x may have polynomial coefficients, 8: same as 0 but x may have polynomial coefficients. Description: (vec, ?0):vec lll($1) (vec, 2):vec lllintpartial($1) (vec, 4):vec lllkerim($1) (vec, 5):vec lllkerimgen($1) (vec, 8):vec lllgen($1) (vec, #small):vec $"Bad flag in qflll" (vec, small):vec qflll0($1, $2) Doc: \idx{LLL} algorithm applied to the \emph{columns} of the matrix $x$. The columns of $x$ may be linearly dependent. The result is by default 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$. 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}) as building blocks for the FLATTER (block recursive) algorithm of Heninger and Ryan. If $\fl=1$, disable use of FLATTER algorithm; use \kbd{fplll}. This flag is provided to experiment with the concrete speed-ups allowed by FLATTER, as well as to genuinely disable it on the rare classes of lattices for which it turns out it performs badly: many such classes are detected in the code, which then restricts to stock \kbd{fplll}, but new exemples may turn up. 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=3$, as $\fl=0$, but the reduction is performed in place: the routine returns $x \cdot T$. This is usually faster for knapsack-type lattices. If $\fl=4$, as $\fl=0$, 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 $\fl=4$, but $x$ may have polynomial coefficients. If $\fl=8$, same as $\fl=0$, but $x$ may have polynomial coefficients. \bprog ? \p500 realprecision = 500 significant digits ? a = 2*cos(2*Pi/97); ? C = 10^450; ? v = powers(a,48); b = round(matconcat([matid(48),C*v]~)); ? p = b * qflll(b)[,1]; \\ tiny linear combination of powers of 'a' time = 4,470 ms. ? exponent(v * p / C) %5 = -1418 ? p3 = qflll(b,3)[,1]; \\ compute in place, faster time = 3,790 ms. ? p3 == p \\ same result %7 = 1 ? p2 = b * qflll(b,2)[,1]; \\ partial reduction: faster, not as good time = 343 ms. ? exponent(v * p2 / C) %9 = -1190 @eprog Variant: Also available are \fun{GEN}{lll}{GEN x} ($\fl=0$), \fun{GEN}{lllint}{GEN x} ($\fl=1$), and \fun{GEN}{lllkerim}{GEN x} ($\fl=4$). pari-2.17.2/src/functions/linear_algebra/qfsign0000644000175000017500000000055114567450071020136 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.17.2/src/functions/linear_algebra/qforbits0000644000175000017500000000146514676526175020517 0ustar billbillFunction: qforbits Section: linear_algebra C-Name: qforbits Prototype: GG Help: qforbits(G,V): return the orbits of V under the action of the group of linear transformation generated by the set G, which must stabilize V. Doc: return the orbits of $V$ under the action of the group of linear transformation generated by the set $G$. It is assumed that $G$ contains minus identity, and only one vector in $\{v, -v\}$ should be given. If $G$ does not stabilize $V$, the function return $0$. In the example below, we compute representatives and lengths of the orbits of the vectors of norm $\leq 3$ under the automorphisms of the lattice $\Z^{6}$. \bprog ? Q=matid(6); G=qfauto(Q); V=qfminim(Q,3); ? apply(x->[x[1],#x],qforbits(G,V)) %2 = [[[0,0,0,0,0,1]~,6],[[0,0,0,0,1,-1]~,30],[[0,0,0,1,-1,-1]~,80]] @eprog pari-2.17.2/src/functions/linear_algebra/algdep0000644000175000017500000000565314676526175020125 0ustar billbillFunction: algdep Section: linear_algebra C-Name: algdep0 Prototype: GLD0,L, Help: algdep(z,k,{flag=0}): algebraic relations up to degree k of z, using lindep([1,z,...,z^(k-1)], flag). Doc: \sidx{algebraic dependence} $z$ being real/complex, or $p$-adic, finds a polynomial (in the variable \kbd{'x}) of degree at most $k$, with integer coefficients, having $z$ 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} or \tet{polrootspadic}). Internally, \tet{lindep}$([1,z,\ldots,z^{k}], \fl)$ is used. A nonzero 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: if $\fl > 0$ the computation is done with an accuracy of $\fl$ decimal digits; to get meaningful results, the parameter $\fl$ should be smaller than the number of correct decimal digits in the input. But default values are usually sufficient, so try without $\fl$ first: \bprog ? \p200 ? z = 2^(1/6)+3^(1/5); ? algdep(z, 30); \\ right in 63ms ? algdep(z, 30, 100); \\ wrong in 39ms ? algdep(z, 30, 170); \\ right in 61ms ? algdep(z, 30, 200); \\ wrong in 146ms ? \p250 ? z = 2^(1/6)+3^(1/5); \\ recompute to new, higher, accuracy ! ? algdep(z, 30); \\ right in 68ms ? algdep(z, 30, 200); \\ right in 68ms ? \p500 ? algdep(2^(1/6)+3^(1/5), 30); \\ right in 138ms ? \p1000 ? algdep(2^(1/6)+3^(1/5), 30); \\ right in 276s @eprog\noindent The changes in \kbd{realprecision} 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: a 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 195 digits, and from then on a steady stream of correct results: \bprog \\ assume T contains the correct result, for comparison forstep(d=100, 250, 5, \ localprec(d); \ print(d, " ", algdep(2^(1/6)+3^(1/5),30) == T)) @eprog\noindent This example is the test case studied in a 2000 paper by Borwein and Lisonek: Applications of integer relation algorithms, \emph{Discrete Math.}, {\bf 217}, p.~65--82. The version of PARI tested there was 1.39, which succeeded reliably from precision 265 on, in about 1000 as much time as the current version (on slower hardware of course). Note that this function does not work if $z$ is a power series. The function \kbd{seralgdep} can be used in this case to find linear relations wich polynomial coefficients between powers of $z$. Variant: Also available is \fun{GEN}{algdep}{GEN z, long k} ($\fl=0$). pari-2.17.2/src/functions/linear_algebra/setminus0000644000175000017500000000055614557721031020517 0ustar billbillFunction: setminus Section: linear_algebra C-Name: setminus Prototype: GG Help: setminus(x,y): set of elements of x not belonging to y. Description: (vec, vec):vec setminus($1, $2) Doc: difference of the two sets $x$ and $y$ (see \kbd{setisset}), i.e.~set of elements of $x$ which do not belong to $y$. If $x$ or $y$ is not a set, the result is undefined. pari-2.17.2/src/functions/linear_algebra/matrix0000644000175000017500000000126114760123736020152 0ustar billbillFunction: matrix Section: linear_algebra C-Name: matrice Prototype: GDGDVDVDE Help: matrix(m,{n=m},{X},{Y},{expr=0}): m x n matrix of expression expr, where the row variable X goes from 1 to m and the column variable Y goes 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. If $n$ is omitted, return a square $m \times m$ matrix. %\syn{NO} pari-2.17.2/src/functions/linear_algebra/qflllgram0000644000175000017500000000344414676526175020646 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: disable FLATTER, 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. 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}) and FLATTER algorithm for Heninger and Ryan. If $\fl=1$, disable use of FLATTER algorithm. $\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.17.2/src/functions/linear_algebra/matimagecompl0000644000175000017500000000104714557721031021463 0ustar billbillFunction: matimagecompl Section: linear_algebra C-Name: imagecompl Prototype: G Description: (gen):vecsmall imagecompl($1) Help: matimagecompl(x): vector of column indices not corresponding to the indices given by the function matimage. Doc: gives the vector of the column indices which are not extracted by the function \kbd{matimage}, as a permutation (\typ{VECSMALL}). Hence the number of components of \kbd{matimagecompl(x)} plus the number of columns of \kbd{matimage(x)} is equal to the number of columns of the matrix $x$. pari-2.17.2/src/functions/linear_algebra/qfisominit0000644000175000017500000000246414567450071021036 0ustar billbillFunction: qfisominit Section: linear_algebra C-Name: qfisominit0 Prototype: GDGDG Help: qfisominit(G,{fl},{m}): G being a square and symmetric matrix representing an integral positive definite quadratic form, this function returns a structure allowing to compute isomorphisms between G and other quadratic form faster. Doc: $G$ being a square and symmetric matrix with integer entries representing a positive definite quadratic form, return an \kbd{isom} structure allowing to compute isomorphisms between $G$ and other quadratic forms faster. The interface of this function is experimental and will likely change in future release. If present, the optional parameter \var{fl} must be a \typ{VEC} with two components. It allows to specify the invariants used, which can make the computation faster or slower. The components are \item \kbd{fl[1]} Depth of scalar product combination to use. \item \kbd{fl[2]} Maximum level of Bacher polynomials to use. If present, $m$ must be the set of vectors of norm up to the maximal of the diagonal entry of $G$, either as a matrix or as given by \kbd{qfminim}. Otherwise this function computes the minimal vectors so it become very lengthy as the dimension of $G$ grows. Variant: Also available is \fun{GEN}{qfisominit}{GEN F, GEN fl} where $F$ is a vector of \kbd{zm}. pari-2.17.2/src/functions/linear_algebra/matpermanent0000644000175000017500000000074014760123736021342 0ustar billbillFunction: matpermanent Section: linear_algebra C-Name: matpermanent Prototype: G Help: matpermanent(x): permanent of the matrix x. Doc: permanent of the square matrix $x$ using Ryser's formula in Gray code order. \bprog ? n = 20; m = matrix(n,n,i,j, i!=j); ? matpermanent(m) %2 = 895014631192902121 ? n! * sum(i=0,n, (-1)^i/i!) %3 = 895014631192902121 @eprog\noindent This function runs in time $O(2^{n} n)$ for a matrix of size $n$ and is not implemented for $n$ large. pari-2.17.2/src/functions/linear_algebra/mathnfmodid0000644000175000017500000000117514567450071021144 0ustar billbillFunction: mathnfmodid Section: linear_algebra C-Name: hnfmodid Prototype: GG Help: mathnfmodid(x,d): (upper triangular) Hermite normal form of x concatenated with matdiagonal(d). Doc: outputs the (upper triangular) \idx{Hermite normal form} of $x$ concatenated with the diagonal matrix with diagonal $d$. Assumes that $x$ has integer entries. Variant: if $d$ is an integer instead of a vector, concatenate $d$ times the identity matrix. \bprog ? m=[0,7;-1,0;-1,-1] %1 = [ 0 7] [-1 0] [-1 -1] ? mathnfmodid(m, [6,2,2]) %2 = [2 1 1] [0 1 0] [0 0 1] ? mathnfmodid(m, 10) %3 = [10 7 3] [ 0 1 0] [ 0 0 1] @eprog pari-2.17.2/src/functions/linear_algebra/matimagemod0000644000175000017500000000177014676526175021151 0ustar billbillFunction: matimagemod Section: linear_algebra C-Name: matimagemod Prototype: GGD& Help: matimagemod(x,d,&U): basis of the image of the matrix x modulo d. Doc: gives a Howell basis (unique representation for submodules of~$(\Z/d\Z)^{n}$) for the image of the matrix $x$ modulo $d$ as columns of a matrix $H$. The matrix $x$ must have \typ{INT} entries, and $d$ can be an arbitrary positive integer. If $U$ is present, set it to a matrix such that~$AU = H$. \bprog ? A = [2,1;0,2]; ? matimagemod(A,6,&U) %2 = [1 0] [0 2] ? U %3 = [5 1] [3 4] ? (A*U)%6 %4 = [1 0] [0 2] @eprog \misctitle{Caveat} In general the number of columns of the Howell form is not the minimal number of generators of the submodule. Example: \bprog ? matimagemod([1;2],4) %5 = [2 1] [0 2] @eprog \misctitle{Caveat 2} In general the matrix $U$ is not invertible, even if~$A$ and~$H$ have the same size. Example: \bprog ? matimagemod([4,1;0,4],8,&U) %6 = [2 1] [0 4] ? U %7 = [0 0] [2 1] @eprog pari-2.17.2/src/functions/linear_algebra/qfcvp0000644000175000017500000000475614760137411017774 0ustar billbillFunction: qfcvp Section: linear_algebra C-Name: qfcvp0 Prototype: GGDGDGD0,L, Help: qfcvp(x,t,{B},{m},{flag=0}): x being a square and symmetric matrix representing a positive definite quadratic form, and t a vector of the same dimension, this function deals with the vectors of whose squared distance to t is less than B, enumerated using the Fincke-Pohst algorithm, storing at most m vectors (no limit if m is omitted). The function searches for the closest vectors to t if B is omitted or <= 0. The precise behavior depends on flag. 0: returns at most m vectors (unless m omitted), returns [N,M,V] where N is the number of vectors enumerated, M the maximum squared distance among these, and V lists the vectors. 1: ignores m and returns the first vector whose squared distance to t is less than B. Doc: $x$ being a square and symmetric matrix of dimension $d$ representing a positive definite quadratic form, and $t$ a vector of the same dimension $d$. This function deals with the vectors whose squared distance to $t$ is less than $B$, enumerated using the Fincke-Pohst algorithm, storing at most $m$ vectors. There is no limit if $m$ is omitted: beware that this may be a huge vector! The vectors are returned in no particular order. The function searches for the closest vectors to $t$ if $B$ is omitted or $\leq 0$. 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$. \item If $\fl=0$ (default), return $[N, M, V]$, where $N$ is the number of vectors enumerated (possibly larger than $m$), $M \leq B$ is the maximum squared distance found, and $V$ is a matrix whose columns are found vectors. \item If $\fl=1$, ignore $m$ and return $[M,v]$, where $v$ is a vector at squared distance $M \leq B$. If no vector has distance $\leq B$, return $[]$. In these two cases, $x$ must have integral \emph{small} entries: more precisely, we definitely must have $d\cdot \|x\|_\infty^2 < 2^{53}$ but even that may not be enough. The implementation uses low precision floating point computations for maximal speed and gives incorrect results when $x$ has large entries. That condition is checked in the code and the routine raises an error if large rounding errors occur. \bprog ? M = [2,1;1,2]; t = [1/2, -1/2]; ? qfcvp(M, t, 0) %2 = [2, 0.5000000000000000000, [0, 1; 0, -1]] ? qfcvp(M, t, 1.5) %3 = [4, 1.5000000000000000000, [1, 0, 1, 0; 0, 0, -1, -1]] @eprog pari-2.17.2/src/functions/linear_algebra/vecsum0000644000175000017500000000044214567450071020150 0ustar billbillFunction: vecsum Section: linear_algebra C-Name: vecsum Prototype: G Help: vecsum(v): return the sum of the components of the vector v. Doc: return the sum of the components of the vector $v$. Return $0$ on an empty vector. \bprog ? vecsum([1,2,3]) %1 = 6 ? vecsum([]) %2 = 0 @eprog pari-2.17.2/src/functions/linear_algebra/qfparam0000644000175000017500000000162614676526175020314 0ustar billbillFunction: qfparam Section: linear_algebra C-Name: qfparam Prototype: GGD0,L, Help: qfparam(G,sol,{flag=0}): coefficients of binary quadratic forms that parametrize the solutions of the ternary quadratic form G, using the particular solution sol. Doc: coefficients of binary quadratic forms that parametrize the solutions of the ternary quadratic form $G$, using the particular solution~\var{sol}. $\fl$ is optional and can be 1, 2, or 3, in which case the $\fl$-th form is reduced. The default is $\fl=0$ (no reduction). \bprog ? G = [1,0,0;0,1,0;0,0,-34]; ? M = qfparam(G, qfsolve(G)) %2 = [ 3 -10 -3] [-5 -6 5] [ 1 0 1] @eprog Indeed, the solutions can be parametrized as $$(3x^{2}-10xy-3y^{2})^{2} + (-5x^{2}-6xy+5y^{2})^{2} -34(x^{2}+y^{2})^{2} = 0.$$ \bprog ? v = y^2 * M*[1,x/y,(x/y)^2]~ %3 = [3*x^2 - 10*y*x - 3*y^2, -5*x^2 - 6*y*x + 5*y^2, -x^2 - y^2]~ ? v~*G*v %4 = 0 @eprog pari-2.17.2/src/functions/linear_algebra/qfisom0000644000175000017500000000236314676526175020162 0ustar billbillFunction: qfisom Section: linear_algebra C-Name: qfisom0 Prototype: GGDGDG Help: qfisom(G,H,{fl},{grp}): find an isomorphism between the integral positive definite quadratic forms G and H if it exists. G can also be given by a qfisominit structure which is preferable if several forms need to be compared to G. Doc: $G$, $H$ being square and symmetric matrices with integer entries representing positive definite quadratic forms, return an invertible matrix $S$ such that $G={^{t}}S\*H\*S$. This defines a isomorphism between the corresponding lattices. Since this requires computing the minimal vectors, the computations can become very lengthy as the dimension grows. See \kbd{qfisominit} for the meaning of \var{fl}. If \var{grp} is given it must be the automorphism group of $H$. It will be used to speed up the computation. $G$ can also be given by an \kbd{qfisominit} structure which is preferable if several forms $H$ need to be compared to $G$. This function implements an algorithm of Plesken and Souvignier, following Souvignier's implementation. Variant: Also available is \fun{GEN}{qfisom}{GEN G, GEN H, GEN fl, GEN grp} where $G$ is a vector of \kbd{zm}, and $H$ is a \kbd{zm}, and $grp$ is either \kbd{NULL} or a vector of \kbd{zm}. pari-2.17.2/src/functions/linear_algebra/vectorsmall0000644000175000017500000000067414760123736021210 0ustar billbillFunction: vectorsmall Section: linear_algebra C-Name: vecteursmall Prototype: GDVDE Help: vectorsmall(n,{X},{expr=0}): VECSMALL with n components of expression expr (X ranges from 1 to n) which must be small integers. By default, fills with 0s. Doc: creates a row vector of small integers (type \typ{VECSMALL}) with $n$ components whose components are the expression \var{expr} evaluated at the integer points between 1 and $n$. %\syn{NO} pari-2.17.2/src/functions/linear_algebra/powers0000644000175000017500000000146514676526175020205 0ustar billbillFunction: powers Section: linear_algebra C-Name: gpowers0 Prototype: GLDG Description: (gen, small):vec gpowers($1, $2) Help: powers(x,n,{x0}): return the vector [1,x,...,x^n] if x0 is omitted, and [x0, x0*x, ..., x0*x^n] otherwise. Doc: for nonnegative $n$, return the vector with $n+1$ components $[1,x,\dots,x^{n}]$ if \kbd{x0} is omitted, and $[x_{0}, x_{0}*x, ..., x_{0}*x^{n}]$ otherwise. \bprog ? powers(Mod(3,17), 4) %1 = [Mod(1, 17), Mod(3, 17), Mod(9, 17), Mod(10, 17), Mod(13, 17)] ? powers(Mat([1,2;3,4]), 3) %2 = [[1, 0; 0, 1], [1, 2; 3, 4], [7, 10; 15, 22], [37, 54; 81, 118]] ? powers(3, 5, 2) %3 = [2, 6, 18, 54, 162, 486] @eprog\noindent When $n < 0$, the function returns the empty vector \kbd{[]}. Variant: Also available is \fun{GEN}{gpowers}{GEN x, long n} when \kbd{x0} is \kbd{NULL}. pari-2.17.2/src/functions/linear_algebra/matpascal0000644000175000017500000000070514567450071020615 0ustar billbillFunction: matpascal Section: linear_algebra C-Name: matqpascal Prototype: LDG Help: matpascal(n,{q}): Pascal triangle of order n if q is omitted. q-Pascal triangle otherwise. Doc: creates as a matrix the lower triangular \idx{Pascal triangle} of order $x+1$ (i.e.~with binomial coefficients up to $x$). If $q$ is given, compute the $q$-Pascal triangle (i.e.~using $q$-binomial coefficients). Variant: Also available is \fun{GEN}{matpascal}{GEN x}. pari-2.17.2/src/functions/linear_algebra/matmultodiagonal0000644000175000017500000000066013637407207022211 0ustar billbillFunction: matmultodiagonal Section: linear_algebra C-Name: matmultodiagonal Prototype: GG Help: matmultodiagonal(x,y): product of matrices x and y, knowing that the result will be a diagonal matrix. Much faster than general multiplication in that case. Doc: product of the matrices $x$ and $y$ assuming that the result is a diagonal matrix. Much faster than $x*y$ in that case. The result is undefined if $x*y$ is not diagonal. pari-2.17.2/src/functions/linear_algebra/matreduce0000644000175000017500000000311314760123736020615 0ustar billbillFunction: matreduce Section: linear_algebra C-Name: matreduce Prototype: G Help: matreduce(m): reduce the factorization matrix m to canonical form (sorted first row with unique elements) matrix. Doc: let $m$ be a factorization matrix, i.e., a 2-column matrix whose columns contains arbitrary ``generators'' and integer ``exponents'' respectively. Returns the canonical form of $m$: the first column is sorted with unique elements and the second one contains the merged ``exponents'' (exponents of identical entries in the first column of $m$ are added, rows attached to $0$ exponents are deleted). The generators are sorted with respect to the universal \kbd{cmp} routine; in particular, this function is the identity on true integer factorization matrices, but not on other factorizations (in products of polynomials or maximal ideals, say). It is idempotent. For convenience, this function also allows a vector $m$, which is handled as a factorization with all exponents equal to $1$, as in \kbd{factorback}. \bprog ? A=[x,2;y,4]; B=[x,-2; y,3; 3, 4]; C=matconcat([A,B]~) %1 = [x 2] [y 4] [x -2] [y 3] [3 4] ? matreduce(C) %2 = [3 4] [y 7] ? matreduce([x,x,y,x,z,x,y]) \\ vector argument %3 = [x 4] [y 2] [z 1] @eprog\noindent The following one-line functions will list elements occurring exactly once (resp. more than once) in the vector or list $v$: \bprog unique(v) = [ x[1] | x <- matreduce(v)~, x[2] == 1 ]; duplicates(v) = [ x[1] | x <- matreduce(v)~, x[2] > 1 ]; ? v = [0,1,2,3,1,2]; ? unique(v) %2 = [0, 3] ? duplicates(v) %3 = [1, 2] @eprog pari-2.17.2/src/functions/linear_algebra/matrank0000644000175000017500000000021213637407207020276 0ustar billbillFunction: matrank Section: linear_algebra C-Name: rank Prototype: lG Help: matrank(x): rank of the matrix x. Doc: rank of the matrix $x$. pari-2.17.2/src/functions/linear_algebra/setsearch0000644000175000017500000000322414676526175020642 0ustar billbillFunction: setsearch Section: linear_algebra C-Name: setsearch Prototype: lGGD0,L, Help: setsearch(S,x,{flag=0}): determines whether x belongs to the set (or sorted list) S. If flag is 0 or omitted, returns 0 if it does not, otherwise returns the index j such that x==S[j]. If flag is nonzero, return 0 if x belongs to S, otherwise the index j where it should be inserted. Doc: determines whether $x$ belongs to the set or sorted list $S$ (see \kbd{setisset}). We first describe the default behavior, when $\fl$ is zero or omitted. If $x$ belongs to the set $S$, returns the index $j$ such that $S[j]=x$, otherwise returns 0. \bprog ? T = [7,2,3,5]; S = Set(T); ? setsearch(S, 2) %2 = 1 ? setsearch(S, 4) \\ not found %3 = 0 ? setsearch(T, 7) \\ search in a randomly sorted vector %4 = 0 \\ WRONG ! @eprog\noindent If $S$ is not a set, we also allow sorted lists with respect to the \tet{cmp} sorting function, without repeated entries, as per \tet{listsort}$(L,1)$; otherwise the result is undefined. \bprog ? L = List([1,4,2,3,2]); setsearch(L, 4) %1 = 0 \\ WRONG ! ? listsort(L, 1); L \\ sort L first %2 = List([1, 2, 3, 4]) ? setsearch(L, 4) %3 = 4 \\ now correct @eprog\noindent If $\fl$ is nonzero, this function returns the index $j$ where $x$ should be inserted, and $0$ if it already belongs to $S$. This is meant to be used for dynamically growing (sorted) lists, in conjunction with \kbd{listinsert}. \bprog ? L = List([1,5,2,3,2]); listsort(L,1); L %1 = List([1,2,3,5]) ? j = setsearch(L, 4, 1) \\ 4 should have been inserted at index j %2 = 4 ? listinsert(L, 4, j); L %3 = List([1, 2, 3, 4, 5]) @eprog pari-2.17.2/src/functions/linear_algebra/matconcat0000644000175000017500000000410014676526175020624 0ustar billbillFunction: matconcat Section: linear_algebra C-Name: matconcat Prototype: G Help: matconcat(v): concatenate the entries of v and return the resulting matrix. Doc: returns a \typ{MAT} built from the entries of $v$, which may be a \typ{VEC} (concatenate horizontally), a \typ{COL} (concatenate vertically), or a \typ{MAT} (concatenate vertically each column, and concatenate vertically the resulting matrices). The entries of $v$ are always considered as matrices: they can themselves be \typ{VEC} (seen as a row matrix), a \typ{COL} seen as a column matrix), a \typ{MAT}, or a scalar (seen as an $1 \times 1$ matrix). \bprog ? A=[1,2;3,4]; B=[5,6]~; C=[7,8]; D=9; ? matconcat([A, B]) \\ horizontal %1 = [1 2 5] [3 4 6] ? matconcat([A, C]~) \\ vertical %2 = [1 2] [3 4] [7 8] ? matconcat([A, B; C, D]) \\ block matrix %3 = [1 2 5] [3 4 6] [7 8 9] @eprog\noindent If the dimensions of the entries to concatenate do not match up, the above rules are extended as follows: \item each entry $v_{i,j}$ of $v$ has a natural length and height: $1 \times 1$ for a scalar, $1 \times n$ for a \typ{VEC} of length $n$, $n \times 1$ for a \typ{COL}, $m \times n$ for an $m\times n$ \typ{MAT} \item let $H_{i}$ be the maximum over $j$ of the lengths of the $v_{i,j}$, let $L_{j}$ be the maximum over $i$ of the heights of the $v_{i,j}$. The dimensions of the $(i,j)$-th block in the concatenated matrix are $H_{i} \times L_{j}$. \item a scalar $s = v_{i,j}$ is considered as $s$ times an identity matrix of the block dimension $\min (H_{i},L_{j})$ \item blocks are extended by 0 columns on the right and 0 rows at the bottom, as needed. \bprog ? matconcat([1, [2,3]~, [4,5,6]~]) \\ horizontal %4 = [1 2 4] [0 3 5] [0 0 6] ? matconcat([1, [2,3], [4,5,6]]~) \\ vertical %5 = [1 0 0] [2 3 0] [4 5 6] ? matconcat([B, C; A, D]) \\ block matrix %6 = [5 0 7 8] [6 0 0 0] [1 2 9 0] [3 4 0 9] ? U=[1,2;3,4]; V=[1,2,3;4,5,6;7,8,9]; ? matconcat(matdiagonal([U, V])) \\ block diagonal %7 = [1 2 0 0 0] [3 4 0 0 0] [0 0 1 2 3] [0 0 4 5 6] [0 0 7 8 9] @eprog pari-2.17.2/src/functions/linear_algebra/matisdiagonal0000644000175000017500000000034613637407207021465 0ustar billbillFunction: matisdiagonal Section: linear_algebra C-Name: isdiagonal Prototype: iG Help: matisdiagonal(x): true(1) if x is a diagonal matrix, false(0) otherwise. Doc: returns true (1) if $x$ is a diagonal matrix, false (0) if not. pari-2.17.2/src/functions/linear_algebra/setbinop0000644000175000017500000000117214557721031020466 0ustar billbillFunction: setbinop Section: linear_algebra C-Name: setbinop Prototype: GGDG Help: setbinop(f,X,{Y}): the set {f(x,y), x in X, y in Y}. If Y is omitted, assume that X = Y and that f is symmetric. Doc: the set whose elements are the f(x,y), where x,y run through X,Y. respectively. If $Y$ is omitted, assume that $X = Y$ and that $f$ is symmetric: $f(x,y) = f(y,x)$ for all $x,y$ in $X$. \bprog ? X = [1,2,3]; Y = [2,3,4]; ? setbinop((x,y)->x+y, X,Y) \\ set X + Y %2 = [3, 4, 5, 6, 7] ? setbinop((x,y)->x-y, X,Y) \\ set X - Y %3 = [-3, -2, -1, 0, 1] ? setbinop((x,y)->x+y, X) \\ set 2X = X + X %2 = [2, 3, 4, 5, 6] @eprog pari-2.17.2/src/functions/linear_algebra/qfbil0000644000175000017500000000031214567450071017737 0ustar billbillFunction: qfbil Section: linear_algebra C-Name: qfbil Prototype: GGDG Obsolete: 2016-08-08 Help: qfbil(x,y,{q}): this function is obsolete, use qfeval. Doc: this function is obsolete, use \kbd{qfeval}. pari-2.17.2/src/functions/linear_algebra/snfrank0000644000175000017500000000246614676526175020332 0ustar billbillFunction: snfrank Section: linear_algebra C-Name: snfrank Prototype: lGDG Help: snfrank(D,{q=0}): assuming that D is a Smith normal form (i.e. vector of elementary divisors) for some module and q a power of an irreducible element or 0 (default if omitted), returns the rank of D/qD. Doc: assuming that $D$ is a Smith normal form (i.e. vector of elementary divisors) for some module and $q$ a power of an irreducible element or $0$, returns the minimal number of generators for $D/qD$. For instance, if $q=p^{n}$ where $p$ is a prime number, this is the dimension of $(p^{n-1}D)/p^{n}D$ as an $\F_{p}$-vector space. An argument $q = 0$ may be omitted. \bprog ? snfrank([4,4,2], 2) %1 = 3 ? snfrank([4,4,2], 4) %2 = 2 ? snfrank([4,4,2], 8) %3 = 0 ? snfrank([4,4,2]) \\ or snfrank([4,4,2], 0) %4 = 3 @eprog\noindent The function also works for $K[x]$-modules: \bprog ? D=matsnf([-x-5,-1,-1,0; 0,x^2+10*x+26,-1,-x-5; 1,-x-5,-x-5,1; -1,0,0,1]); ? snfrank(D, x^2 + 10*x + 27) %6 = 2 ? A=matdiagonal([x-1,x^2+1,x-1,(x^2+1)^2,x,(x-1)^2]); D=matsnf(A); ? snfrank(D,x-1) %8 = 3 ? snfrank(D,(x-1)^2) %9 = 1 ? snfrank(D,(x-1)^3) %9 = 0 ? snfrank(D,x^2+1) %10 = 2 @eprog\noindent Finally this function supports any output from \kbd{matsnf} (e.g., with transformation matrices included, with or without cleanup). pari-2.17.2/src/functions/linear_algebra/matimage0000644000175000017500000000131414760123736020431 0ustar billbillFunction: matimage Section: linear_algebra C-Name: matimage0 Prototype: GD0,L, Help: matimage(x,{flag=0}): basis of the image of the matrix x. flag is optional and can be set to 0 or 1, corresponding to two different algorithms. Description: (gen, ?0):vec image($1) (gen, 1):vec image2($1) (gen, #small) $"incorrect flag in matimage" (gen, small):vec matimage0($1, $2) Doc: gives a basis for the image of the matrix $x$ as columns of a matrix. A priori the matrix can have entries of any type. If $\fl=0$, use standard Gauss pivot. If $\fl=1$, use \kbd{matsupplement} (much slower: keep the default flag!). Variant: Also available is \fun{GEN}{image}{GEN x} ($\fl=0$). pari-2.17.2/src/functions/linear_algebra/matdetint0000644000175000017500000000203014676526175020644 0ustar billbillFunction: matdetint Section: linear_algebra C-Name: detint Prototype: G Help: matdetint(B): some multiple of the determinant of the lattice generated by the columns of B (0 if not of maximal rank). Useful with mathnfmod. Doc: Let $B$ be an $m\times n$ matrix with integer coefficients. The \emph{determinant} $D$ of the lattice generated by the columns of $B$ is the square root of $\det(B^{T} B)$ if $B$ has maximal rank $m$, and $0$ otherwise. This function uses the Gauss-Bareiss algorithm to compute a positive \emph{multiple} of $D$. When $B$ is square, the function actually returns $D = |\det B|$. This function is useful in conjunction with \kbd{mathnfmod}, which needs to know such a multiple. If the rank is maximal but the matrix is nonsquare, you can obtain $D$ exactly using \bprog matdet( mathnfmod(B, matdetint(B)) ) @eprog\noindent Note that as soon as one of the dimensions gets large ($m$ or $n$ is larger than 20, say), it will often be much faster to use \kbd{mathnf(B, 1)} or \kbd{mathnf(B, 4)} directly. pari-2.17.2/src/functions/linear_algebra/qfauto0000644000175000017500000000242114676526175020156 0ustar billbillFunction: qfauto Section: linear_algebra C-Name: qfauto0 Prototype: GDG Help: qfauto(G,{fl}): automorphism group of the positive definite quadratic form G. Doc: $G$ being a square and symmetric matrix with integer entries representing a positive definite quadratic form, outputs the automorphism group of the associate lattice. Since this requires computing the minimal vectors, the computations can become very lengthy as the dimension grows. $G$ can also be given by an \kbd{qfisominit} structure. See \kbd{qfisominit} for the meaning of \var{fl}. The output is a two-components vector $[o,g]$ where $o$ is the group order and $g$ is the list of generators (as a vector). For each generator $H$, the equality $G={^{t}}H\*G\*H$ holds. The interface of this function is experimental and will likely change in the future. This function implements an algorithm of Plesken and Souvignier, following Souvignier's implementation. \bprog ? K = matkerint(Mat(concat([vector(23,i,2*i+1), 51, 145]))); ? M = matdiagonal(vector(25,i,if(i==25,-1,1))); ? L24 = K~ * M * K; \\ the Leech lattice ? [o,g] = qfauto(L24); o %4 = 8315553613086720000 ? #g %5 = 2 @eprog Variant: The function \fun{GEN}{qfauto}{GEN G, GEN fl} is also available where $G$ is a vector of \kbd{zm} matrices. pari-2.17.2/src/functions/linear_algebra/matmuldiagonal0000644000175000017500000000065013637407207021645 0ustar billbillFunction: matmuldiagonal Section: linear_algebra C-Name: matmuldiagonal Prototype: GG Help: matmuldiagonal(x,d): product of matrix x by diagonal matrix whose diagonal coefficients are those of the vector d, equivalent but faster than x*matdiagonal(d). Doc: product of the matrix $x$ by the diagonal matrix whose diagonal entries are those of the vector $d$. Equivalent to, but much faster than $x*\kbd{matdiagonal}(d)$. pari-2.17.2/src/functions/linear_algebra/norml20000644000175000017500000000156314676526175020076 0ustar billbillFunction: norml2 Section: linear_algebra C-Name: gnorml2 Prototype: G Help: norml2(x): square of the L2-norm of x. Doc: square of the $L^{2}$-norm of $x$. More precisely, if $x$ is a scalar, $\kbd{norml2}(x)$ is defined to be the square of the complex modulus of $x$ (real \typ{QUAD}s are not supported). If $x$ is a polynomial, a (row or column) vector or a matrix, \kbd{norml2($x$)} is defined recursively as $\sum_{i} \kbd{norml2}(x_{i})$, where $(x_{i})$ run through the components of $x$. In particular, this yields the usual $\sum_{i} |x_{i}|^{2}$ (resp.~$\sum_{i,j} |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.17.2/src/functions/linear_algebra/vectorv0000644000175000017500000000044014760123736020334 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.17.2/src/functions/linear_algebra/vecsearch0000644000175000017500000000363514567450071020620 0ustar billbillFunction: vecsearch Section: linear_algebra C-Name: vecsearch Prototype: lGGDG Help: vecsearch(v,x,{cmpf}): determines whether x belongs to the sorted vector v. If the comparison function cmpf is explicitly given, assume that v was sorted according to vecsort(, cmpf). Doc: determines whether $x$ belongs to the sorted vector or list $v$: return the (positive) index where $x$ was found, or $0$ if it does not belong to $v$. If the comparison function cmpf is omitted, we assume that $v$ is sorted in increasing order, according to the standard comparison function \kbd{lex}, thereby restricting the possible types for $x$ and the elements of $v$ (integers, fractions, reals, and vectors of such). We also transparently allow a \typ{VECSMALL} $x$ in this case, for the natural ordering of the integers. If \kbd{cmpf} is present, it is understood as a comparison function and we assume that $v$ is sorted according to it, see \tet{vecsort} for how to encode comparison functions. \bprog ? v = [1,3,4,5,7]; ? vecsearch(v, 3) %2 = 2 ? vecsearch(v, 6) %3 = 0 \\ not in the list ? vecsearch([7,6,5], 5) \\ unsorted vector: result undefined %4 = 0 @eprog\noindent Note that if we are sorting with respect to a key which is expensive to compute (e.g. a discriminant), one should rather precompute all keys, sort that vector and search in the vector of keys, rather than searching in the original vector with respect to a comparison function. By abuse of notation, $x$ is also allowed to be a matrix, seen as a vector of its columns; again by abuse of notation, a \typ{VEC} is considered as part of the matrix, if its transpose is one of the matrix columns. \bprog ? v = vecsort([3,0,2; 1,0,2]) \\ sort matrix columns according to lex order %1 = [0 2 3] [0 2 1] ? vecsearch(v, [3,1]~) %2 = 3 ? vecsearch(v, [3,1]) \\ can search for x or x~ %3 = 3 ? vecsearch(v, [1,2]) %4 = 0 \\ not in the list @eprog\noindent pari-2.17.2/src/functions/linear_algebra/qfjacobi0000644000175000017500000000155614567450071020433 0ustar billbillFunction: qfjacobi Section: linear_algebra C-Name: jacobi Prototype: Gp Help: qfjacobi(A): eigenvalues and orthogonal matrix of eigenvectors of the real symmetric matrix A. Doc: apply Jacobi's eigenvalue algorithm to the real symmetric matrix $A$. This returns $[L, V]$, where \item $L$ is the vector of (real) eigenvalues of $A$, sorted in increasing order, \item $V$ is the corresponding orthogonal matrix of eigenvectors of $A$. \bprog ? \p19 ? A = [1,2;2,1]; mateigen(A) %1 = [-1 1] [ 1 1] ? [L, H] = qfjacobi(A); ? L %3 = [-1.000000000000000000, 3.000000000000000000]~ ? H %4 = [ 0.7071067811865475245 0.7071067811865475244] [-0.7071067811865475244 0.7071067811865475245] ? norml2( (A-L[1])*H[,1] ) \\ approximate eigenvector %5 = 9.403954806578300064 E-38 ? norml2(H*H~ - 1) %6 = 2.350988701644575016 E-38 \\ close to orthogonal @eprog pari-2.17.2/src/functions/linear_algebra/qfnorm0000644000175000017500000000031214567450071020144 0ustar billbillFunction: qfnorm Section: linear_algebra C-Name: qfnorm Prototype: GDG Obsolete: 2016-08-08 Help: qfnorm(x,{q}): this function is obsolete, use qfeval. Doc: this function is obsolete, use \kbd{qfeval}. pari-2.17.2/src/functions/linear_algebra/matintersect0000644000175000017500000000124414676526175021363 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, finds a basis of the vector space equal to the intersection of the spaces spanned by the columns of $x$ and $y$ respectively. For efficiency, the columns of $x$ (resp.~$y$) should be independent. The faster function \tet{idealintersect} can be used to intersect fractional ideals (projective $\Z_{K}$ modules of rank $1$); the slower but more general function \tet{nfhnf} can be used to intersect general $\Z_{K}$-modules. pari-2.17.2/src/functions/linear_algebra/vecprod0000644000175000017500000000045714567450071020316 0ustar billbillFunction: vecprod Section: linear_algebra C-Name: vecprod Prototype: G Help: vecprod(v): return the product of the components of the vector v. Doc: return the product of the components of the vector $v$. Return $1$ on an empty vector. \bprog ? vecprod([1,2,3]) %1 = 6 ? vecprod([]) %2 = 1 @eprog pari-2.17.2/src/functions/linear_algebra/vecsort0000644000175000017500000001123014676526175020342 0ustar billbillFunction: vecsort Section: linear_algebra C-Name: vecsort0 Prototype: GDGD0,L, Help: vecsort(x,{cmpf},{flag=0}): sorts the vector x in ascending order, according to the comparison function cmpf, if not omitted. Binary digits of flag (if present) mean: 1: indirect sorting, return the permutation instead of the permuted vector, 4: use descending instead of ascending order, 8: remove duplicate entries. Description: (vecsmall,?gen,?small):vecsmall vecsort0($1, $2, $3) (vecvecsmall, ,?0):vecvecsmall sort($1) (vec, , ?0):vec sort($1) (vec, , 1):vecsmall indexsort($1) (vec, , 2):vec lexsort($1) (vec, gen):vec vecsort0($1, $2, 0) (vec, ?gen, 1):vecsmall vecsort0($1, $2, 1) (vec, ?gen, 3):vecsmall vecsort0($1, $2, 3) (vec, ?gen, 5):vecsmall vecsort0($1, $2, 5) (vec, ?gen, 7):vecsmall vecsort0($1, $2, 7) (vec, ?gen, 9):vecsmall vecsort0($1, $2, 9) (vec, ?gen, 11):vecsmall vecsort0($1, $2, 11) (vec, ?gen, 13):vecsmall vecsort0($1, $2, 13) (vec, ?gen, 15):vecsmall vecsort0($1, $2, 15) (vec, ?gen, #small):vec vecsort0($1, $2, $3) (vec, ?gen, small):gen vecsort0($1, $2, $3) Doc: sorts the vector $x$ in ascending order, using a mergesort method. $x$ must be a list, vector or matrix (seen as a vector of its columns). Note that mergesort is stable, hence the initial ordering of ``equal'' entries (with respect to the sorting criterion) is not changed. If \kbd{cmpf} is omitted, we use the standard comparison function \kbd{lex}, thereby restricting the possible types for the elements of $x$ (integers, fractions or reals and vectors of those). We also transparently allow a \typ{VECSMALL} $x$ in this case, for the standard ordering on the integers. If \kbd{cmpf} is present, it is understood as a comparison function and we sort according to it. The following possibilities exist: \item an integer $k$: sort according to the value of the $k$-th subcomponents of the components of~$x$. \item a vector: sort lexicographically according to the components listed in the vector. For example, if $\kbd{cmpf}=\kbd{[2,1,3]}$, sort with respect to the second component, and when these are equal, with respect to the first, and when these are equal, with respect to the third. \item a comparison function: \typ{CLOSURE} with two arguments $x$ and $y$, and returning a real number which is $<0$, $>0$ or $=0$ if $xy$ or $x=y$ respectively. \item a key: \typ{CLOSURE} with one argument $x$ and returning the value $f(x)$ with respect to which we sort. \bprog ? vecsort([3,0,2; 1,0,2]) \\ sort columns according to lex order %1 = [0 2 3] [0 2 1] ? vecsort(v, (x,y)->y-x) \\@com reverse sort ? vecsort(v, (x,y)->abs(x)-abs(y)) \\@com sort by increasing absolute value ? vecsort(v, abs) \\@com sort by increasing absolute value, using key ? cmpf(x,y) = my(dx = poldisc(x), dy = poldisc(y)); abs(dx) - abs(dy); ? v = [x^2+1, x^3-2, x^4+5*x+1] vecsort(v, cmpf) \\@com comparison function ? vecsort(v, x->abs(poldisc(x))) \\@com key @eprog\noindent The \kbd{abs} and \kbd{cmpf} examples show how to use a named function instead of an anonymous function. It is preferable to use a \var{key} whenever possible rather than include it in the comparison function as above since the key is evaluated $O(n)$ times instead of $O(n\log n)$, where $n$ is the number of entries. A direct approach is also possible and equivalent to using a sorting key: \bprog ? T = [abs(poldisc(x)) | x<-v]; ? perm = vecsort(T,,1); \\@com indirect sort ? vecextract(v, perm) @eprog\noindent This also provides the vector $T$ of all keys, which is interesting for instance in later \tet{vecsearch} calls: it is more efficient to sort $T$ (\kbd{T = vecextract(T, perm)}) then search for a key in $T$ rather than to search in $v$ using a comparison function or a key. Note also that \tet{mapisdefined} is often easier to use and faster than \kbd{vecsearch}. \noindent The binary digits of \fl\ mean: \item 1: indirect sorting of the vector $x$, i.e.~if $x$ is an $n$-component vector, returns a permutation of $[1,2,\dots,n]$ which applied to the components of $x$ sorts $x$ in increasing order. For example, \kbd{vecextract(x, vecsort(x,,1))} is equivalent to \kbd{vecsort(x)}. \item 4: use descending instead of ascending order. \item 8: remove ``duplicate'' entries with respect to the sorting function (keep the first occurring entry). For example: \bprog ? vecsort([Pi,Mod(1,2),z], (x,y)->0, 8) \\@com make everything compare equal %1 = [3.141592653589793238462643383] ? vecsort([[2,3],[0,1],[0,3]], 2, 8) %2 = [[0, 1], [2, 3]] @eprog pari-2.17.2/src/functions/linear_algebra/charpoly0000644000175000017500000000554414676526175020511 0ustar billbillFunction: charpoly Section: linear_algebra C-Name: charpoly0 Prototype: GDnD5,L, Help: charpoly(A,{v='x},{flag=5}): det(v*Id-A)=characteristic polynomial of the matrix or polmod A. flag is optional and ignored unless A is a matrix; it may be set to 0 (Le Verrier), 1 (Lagrange interpolation), 2 (Hessenberg form), 3 (Berkowitz), 4 (modular) if A is integral, or 5 (default, choose best method). Algorithms 0 (Le Verrier) and 1 (Lagrange) assume that n! is invertible, where n is the dimension of the matrix. Doc: \idx{characteristic polynomial} of $A$ with respect to the variable $v$, i.e.~determinant of $v*I-A$ if $A$ is a square matrix. \bprog ? charpoly([1,2;3,4]); %1 = x^2 - 5*x - 2 ? charpoly([1,2;3,4],, 't) %2 = t^2 - 5*t - 2 @eprog\noindent If $A$ is not a square matrix, the function returns the characteristic polynomial of the map ``multiplication by $A$'' if $A$ is a scalar: \bprog ? charpoly(Mod(x+2, x^3-2)) %1 = x^3 - 6*x^2 + 12*x - 10 ? charpoly(I) %2 = x^2 + 1 ? charpoly(quadgen(5)) %3 = x^2 - x - 1 ? charpoly(ffgen(ffinit(2,4))) %4 = Mod(1, 2)*x^4 + Mod(1, 2)*x^3 + Mod(1, 2)*x^2 + Mod(1, 2)*x + Mod(1, 2) @eprog The value of $\fl$ is only significant for matrices, and we advise to stick to the default value. Let $n$ be the dimension of $A$. If $\fl=0$, same method (Le Verrier's) as for computing the adjoint matrix, i.e.~using the traces of the powers of $A$. Assumes that $n!$ is invertible; uses $O(n^{4})$ scalar operations. If $\fl=1$, uses Lagrange interpolation which is usually the slowest method. Assumes that $n!$ is invertible; uses $O(n^{4})$ scalar operations. If $\fl=2$, uses the Hessenberg form. Assumes that the base ring is a field. Uses $O(n^{3})$ scalar operations, but suffers from coefficient explosion unless the base field is finite or $\R$. If $\fl=3$, uses Berkowitz's division free algorithm, valid over any ring (commutative, with unit). Uses $O(n^{4})$ scalar operations. If $\fl=4$, $x$ must be integral. Uses a modular algorithm: Hessenberg form for various small primes, then Chinese remainders. If $\fl=5$ (default), uses the ``best'' method given $x$. This means we use Berkowitz unless the base ring is $\Z$ (use $\fl=4$) or a field where coefficient explosion does not occur, e.g.~a finite field or the reals (use $\fl=2$). Variant: Also available are \fun{GEN}{charpoly}{GEN x, long v} ($\fl=5$), \fun{GEN}{caract}{GEN A, long v} ($\fl=1$), \fun{GEN}{carhess}{GEN A, long v} ($\fl=2$), \fun{GEN}{carberkowitz}{GEN A, long v} ($\fl=3$) and \fun{GEN}{caradj}{GEN A, long v, GEN *pt}. In this last case, if \var{pt} is not \kbd{NULL}, \kbd{*pt} receives the address of the adjoint matrix of $A$ (see \tet{matadjoint}), so both can be obtained at once. Function: _QM_charpoly_ZX_worker C-Name: QM_charpoly_ZX_worker Prototype: GGG Section: programming/internals Help: worker for QM_charpoly_ZX pari-2.17.2/src/functions/linear_algebra/matkerint0000644000175000017500000000116414567450071020646 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 deprecated, kept for backward compatibility. Doc: gives an \idx{LLL}-reduced $\Z$-basis for the lattice equal to the kernel of the matrix $x$ with rational entries. \fl{} is deprecated, kept for backward compatibility. The function \kbd{matsolvemod} allows to solve more general linear systems over $\Z$. Variant: Use directly \fun{GEN}{kerint}{GEN x} if $x$ is known to have integer entries, and \tet{Q_primpart} first otherwise. pari-2.17.2/src/functions/linear_algebra/matdetmod0000644000175000017500000000126214567450071020625 0ustar billbillFunction: matdetmod Section: linear_algebra C-Name: matdetmod Prototype: GG Help: matdetmod(x,d): determinant of the matrix x modulo d. Doc: Given a matrix $x$ with \typ{INT} entries and $d$ an arbitrary positive integer, return the determinant of $x$ modulo $d$. \bprog ? A = [4,2,3; 4,5,6; 7,8,9] ? matdetmod(A,27) %2 = 9 @eprog Note that using the generic function \kbd{matdet} on a matrix with \typ{INTMOD} entries uses Gaussian reduction and will fail in general when the modulus is not prime. \bprog ? matdet(A * Mod(1,27)) *** at top-level: matdet(A*Mod(1,27)) *** ^------------------ *** matdet: impossible inverse in Fl_inv: Mod(3, 27). @eprog pari-2.17.2/src/functions/linear_algebra/qfcholesky0000644000175000017500000000046714760123736021025 0ustar billbillFunction: qfcholesky Section: linear_algebra C-Name: qfcholesky Prototype: Gp Help: qfcholesky(q): given a square symmetric matrix M, return R such that R~*R = M, or [] if there is no solution. Doc: given a square symmetric \typ{MAT} $M$, return $R$ such that $^t{}R\*R = M$, or $[]$ if there is no solution. pari-2.17.2/src/functions/linear_algebra/dirpowers0000644000175000017500000000071014676526175020674 0ustar billbillFunction: dirpowers Section: linear_algebra C-Name: dirpowers Prototype: LGp Help: dirpowers(n,x): return the vector [1^x,2^x,...,n^x]. Doc: for nonnegative $n$ and complex number $x$, return the vector with $n$ components $[1^{x},2^{x},\dots,n^{x}]$. \bprog ? dirpowers(5, 2) %1 = [1, 4, 9, 16, 25] ? dirpowers(5, 1/2) %2 = [1, 1.414..., 1.732..., 2.000..., 2.236...] @eprog\noindent When $n \le 0$, the function returns the empty vector \kbd{[]}. pari-2.17.2/src/functions/linear_algebra/matsupplement0000644000175000017500000000154214557721031021542 0ustar billbillFunction: matsupplement Section: linear_algebra C-Name: suppl Prototype: G Help: matsupplement(x): supplement the columns of the matrix x to an invertible matrix. Doc: assuming that the columns of the matrix $x$ are linearly independent (if they are not, an error message is issued), finds a square invertible matrix whose first columns are the columns of $x$, i.e.~supplement the columns of $x$ to a basis of the whole space. \bprog ? matsupplement([1;2]) %1 = [1 0] [2 1] @eprog Raises an error if $x$ has 0 columns, since (due to a long standing design bug), the dimension of the ambient space (the number of rows) is unknown in this case: \bprog ? matsupplement(matrix(2,0)) *** at top-level: matsupplement(matrix *** ^-------------------- *** matsupplement: sorry, suppl [empty matrix] is not yet implemented. @eprog pari-2.17.2/src/functions/linear_algebra/forqfvec0000644000175000017500000000256714760123736020473 0ustar billbillFunction: forqfvec Section: linear_algebra C-Name: forqfvec0 Prototype: vVGDGI Wrapper: (,,,vG) Description: (,gen,?gen,closure):void forqfvec1(${4 cookie}, ${4 wrapper}, $2, $3) Help:forqfvec(v,q,b,expr): q being a square and symmetric integral matrix representing an positive definite quadratic form, evaluate expr for all pairs of nonzero vectors (-v, v) such that q(v)<=b. Doc: $q$ being a square and symmetric integral matrix representing a positive definite quadratic form, evaluate \kbd{expr} for all pairs of nonzero vectors $(-v,v)$ such that $q(v)\leq b$. The formal variable $v$ runs through representatives of all such pairs in turn. \bprog ? forqfvec(v, [3,2;2,3], 3, print(v)) [0, 1]~ [1, 0]~ [-1, 1]~ @eprog Variant: The following functions are also available: \fun{void}{forqfvec}{void *E, long (*fun)(void *, GEN, GEN, double), GEN q, GEN b}: Evaluate \kbd{fun(E,U,v,m)} on all $v$ such that $q(U\*v)= 1, return [H,U,c] such that H = c * U~*G*U for some rational c, and H integral with minimal determinant. Doc: Given a square symmetric matrix $G$ with rational coefficients, and non-zero determinant, of dimension $n \geq 1$, return \kbd{[H,U,c]} such that \kbd{H = c*U\til*G*U} for some rational $c$, and $H$ integral with minimal determinant. The coefficients of $U$ are usually nonintegral. \bprog ? G = matdiagonal([650, -104329, -104329]); ? [H,U,c]=qfminimize(G); H %2 = [-1,0,0;0,-1,0;0,0,1] ? U %3 = [0,0,1/5;5/323,-1/323,0;-1/323,-5/323,0] ? c %4 = 1/26 ? c * U~ * G * U %4 = [-1,0,0;0,-1,0;0,0,1] @eprog pari-2.17.2/src/functions/linear_algebra/matsolve0000644000175000017500000000327714760123736020511 0ustar billbillFunction: matsolve Section: linear_algebra C-Name: gauss Prototype: GG Help: matsolve(M,B): solution of MX=B (M matrix, B column vector or matrix). Doc: Let $M$ be a left-invertible matrix and $B$ a column vector such that there exists a solution $X$ to the system of linear equations $MX = B$; return the (unique) solution $X$. This has the same effect as, but is faster, than $M^{-1}*B$. Uses Dixon $p$-adic lifting method if $M$ and $B$ are integral and Gaussian elimination otherwise. When there is no solution, the function returns an $X$ such that $MX - B$ is nonzero although it has at least $\#M$ zero entries: \bprog ? M = [1,2;3,4;5,6]; ? B = [4,6,8]~; X = matsolve(M, B) %2 = [-2, 3]~ ? M*X == B %3 = 1 ? B = [1,2,4]~; X = matsolve(M, [1,2,4]~) %4 = [0, 1/2]~ ? M*X - B %5 = [0, 0, -1]~ @eprog\noindent Raises an exception if $M$ is not left-invertible, even if there is a solution: \bprog ? M = [1,1;1,1]; matsolve(M, [1,1]~) *** at top-level: matsolve(M,[1,1]~) *** ^------------------ *** matsolve: impossible inverse in gauss: [1, 1; 1, 1]. @eprog\noindent The function also works when $B$ is a matrix and we return the unique matrix solution $X$ provided it exists. Again, if there is no solution, the function returns an $X$ such that $MX - B$ is nonzero although it has at least $\#M$ zero rows. Function: _ZM_inv_worker C-Name: ZM_inv_worker Prototype: GG Section: programming/internals Help: worker for ZM_inv Function: _ZM_gauss_worker C-Name: ZM_gauss_worker Prototype: GGG Section: programming/internals Help: worker for ZM_gauss Function: _ZabM_inv_worker C-Name: ZabM_inv_worker Prototype: GGG Section: programming/internals Help: worker for ZabM_inv pari-2.17.2/src/functions/linear_algebra/matker0000644000175000017500000000200414760123736020125 0ustar billbillFunction: matker Section: linear_algebra C-Name: matker0 Prototype: GD0,L, Help: matker(x,{flag=0}): basis of the kernel of the matrix x. flag is optional, and may be set to 0: default; nonzero: x is known to have integral entries. Description: (gen, ?0):vec ker($1) (gen, 1):vec ZM_ker($1) (gen, #small) $"incorrect flag in matker" (gen, small):vec matker0($1, $2) Doc: gives a basis for the kernel of the matrix $x$ as columns of a matrix. The matrix can have entries of any type, provided they are compatible with the generic arithmetic operations ($+$, $\times$ and $/$). If $x$ is known to have integral entries, set $\fl=1$. Variant: Also available are \fun{GEN}{ker}{GEN x} ($\fl=0$), \fun{GEN}{ZM_ker}{GEN x} ($\fl=1$). Function: _ZM_ker_worker C-Name: ZM_ker_worker Prototype: GG Section: programming/internals Help: worker for ZM_ker Function: _FpM_ratlift_worker C-Name: FpM_ratlift_worker Prototype: GGG Section: programming/internals Help: worker for FpM_ratlift pari-2.17.2/src/functions/linear_algebra/qfminim0000644000175000017500000001446714760123736020322 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 nonzero vectors if B is omitted. The precise behavior depends on flag. 0: returns at most 2m vectors (unless m omitted), returns [N,M,V] where N is the number of vectors enumerated, M the maximum norm among these, and V lists half the vectors (the other half is given by -V). 1: ignores m and returns the first vector whose norm is less than B. 2: as 0 but uses a more robust, slower implementation Doc: $x$ being a square and symmetric matrix of dimension $d$ 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$ pairs of vectors: only one vector is given for each pair $\pm v$. There is no limit if $m$ is omitted: beware that this may be a huge vector! The vectors are returned in no particular order. The function searches for the minimal nonzero 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$. \item If $\fl=0$ (default), return $[N, M, V]$, where $N$ is the number of vectors enumerated (an even number, possibly larger than $2m$), $M \leq B$ is the maximum norm found, and $V$ is a matrix whose columns are found vectors. \item If $\fl=1$, ignore $m$ and return $[M,v]$, where $v$ is a nonzero vector of length $M \leq B$. If no nonzero vector has length $\leq B$, return $[]$. If no explicit $B$ is provided, return a vector of smallish norm, namely the vector of smallest length (usually the first one but not always) in an LLL-reduced basis for $x$. In these two cases, $x$ must have integral \emph{small} entries: more precisely, we definitely must have $d\cdot \|x\|_{\infty}^{2} < 2^{53}$ but even that may not be enough. The implementation uses low precision floating point computations for maximal speed and gives incorrect results when $x$ has large entries. That 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: \item If $\fl=2$, $x$ can have non integral real entries, but this is also useful when $x$ has large integral entries. Return $[N, M, V]$ as in case $\fl = 0$, where $M$ is returned as a floating point number. If $x$ is inexact and $B$ is omitted, the ``minimal'' vectors in $V$ only have approximately the same norm (up to the internal working accuracy). This version is very robust but still offers no hard and fast guarantee about the result: it involves floating point operations performed at a high floating point precision depending on your input, but done without rigorous tracking of roundoff errors (as would be provided by interval arithmetic for instance). No example is known where the input is exact but the function returns a wrong result. \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 = \\ The Leech lattice [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) \\ 0: don't store minimal vectors time = 121 ms. %4 = [196560, 4, [;]] \\ 196560 minimal vectors of norm 4 ? qfminim(x) \\ store all minimal vectors ! time = 821 ms. ? qfminim(x,,0,2); \\ safe algorithm. Slower and unnecessary here. time = 5,540 ms. %6 = [196560, 4.000061035156250000, [;]] ? qfminim(x,,,2); \\ safe algorithm; store all minimal vectors time = 6,602 ms. @eprog\noindent\sidx{Leech lattice}\sidx{minimal vector} In this example, storing 0 vectors limits memory use; storing all of them requires a \kbd{parisize} about 50MB. All minimal vectors are nevertheless enumerated in both cases of course, which means the speedup is likely to be marginal. Variant: Also available are \fun{GEN}{minim}{GEN x, GEN B = NULL, GEN m = NULL} ($\fl=0$), \fun{GEN}{minim2}{GEN x, GEN B = NULL, GEN m = NULL} ($\fl=1$). \fun{GEN}{minim_raw}{GEN x, GEN B = NULL, GEN m = NULL} (do not perform LLL reduction on x and return \kbd{NULL} on accuracy error). \fun{GEN}{minim_zm}{GEN x, GEN B = NULL, GEN m = NULL} ($\fl=0$, return vectors as \typ{VECSMALL} to save memory) pari-2.17.2/src/functions/linear_algebra/vecextract0000644000175000017500000000541114676526175021031 0ustar billbillFunction: vecextract Section: linear_algebra C-Name: extract0 Prototype: GGDG Description: (vec,gen,?gen):vec extract0($1, $2, $3) Help: vecextract(x,y,{z}): extraction of the components of the matrix or vector x according to y and z. If z is omitted, y represents columns, otherwise y corresponds to rows and z to columns. y and z can be vectors (of indices), strings (indicating ranges as in "1..10") or masks (integers whose binary representation indicates the indices to extract, from left to right 1, 2, 4, 8, etc.). Doc: extraction of components of the vector or matrix $x$ according to $y$. In case $x$ is a matrix, its components are the \emph{columns} of $x$. The parameter $y$ is a component specifier, which is either an integer, a string describing a range, or a vector. If $y$ is an integer, it is considered as a mask: the binary bits of $y$ are read from right to left, but correspond to taking the components from left to right. For example, if $y=13=(1101)_{2}$ then the components 1,3 and 4 are extracted. If $y$ is a vector (\typ{VEC}, \typ{COL} or \typ{VECSMALL}), which must have integer entries, these entries correspond to the component numbers to be extracted, in the order specified. If $y$ is a string, it can be \item a single (nonzero) index giving a component number (a negative index means we start counting from the end). \item a range of the form \kbd{"$a$..$b$"}, where $a$ and $b$ are indexes as above. Any of $a$ and $b$ can be omitted; in this case, we take as default values $a = 1$ and $b = -1$, i.e.~ the first and last components respectively. We then extract all components in the interval $[a,b]$, in reverse order if $b < a$. In addition, if the first character in the string is \kbd{\pow}, the complement of the given set of indices is taken. If $z$ is not omitted, $x$ must be a matrix. $y$ is then the \emph{row} specifier, and $z$ the \emph{column} specifier, where the component specifier is as explained above. \bprog ? v = [a, b, c, d, e]; ? vecextract(v, 5) \\@com mask %1 = [a, c] ? vecextract(v, [4, 2, 1]) \\@com component list %2 = [d, b, a] ? vecextract(v, "2..4") \\@com interval %3 = [b, c, d] ? vecextract(v, "-1..-3") \\@com interval + reverse order %4 = [e, d, c] ? vecextract(v, "^2") \\@com complement %5 = [a, c, d, e] ? vecextract(matid(3), "2..", "..") %6 = [0 1 0] [0 0 1] @eprog The range notations \kbd{v[i..j]} and \kbd{v[\pow i]} (for \typ{VEC} or \typ{COL}) and \kbd{M[i..j, k..l]} and friends (for \typ{MAT}) implement a subset of the above, in a simpler and \emph{faster} way, hence should be preferred in most common situations. The following features are not implemented in the range notation: \item reverse order, \item omitting either $a$ or $b$ in \kbd{$a$..$b$}. pari-2.17.2/src/functions/linear_algebra/qfsolve0000644000175000017500000000224414676526175020341 0ustar billbillFunction: qfsolve Section: linear_algebra C-Name: qfsolve Prototype: G Help: qfsolve(G): solve over Q the quadratic equation X~ G X = 0, where G is a symmetric matrix. Doc: Given a square symmetric matrix $G$ of dimension $n \geq 1$, solve over $\Q$ the quadratic equation ${^{t}}X G X = 0$. The matrix $G$ must have rational coefficients. When $G$ is integral, the argument can also be a vector $[G,F]$ where $F$ is the factorization matrix of the absolute value of the determinant of $G$. The solution might be a single nonzero column vector (\typ{COL}) or a matrix (whose columns generate a totally isotropic subspace). If no solution exists, returns an integer, that can be a prime $p$ such that there is no local solution at $p$, or $-1$ if there is no real solution, or $-2$ if $n = 2$ and $-\det G$ is not a square (which implies there is a real solution, but no local solution at some $p$ dividing $\det G$). \bprog ? G = [1,0,0;0,1,0;0,0,-34]; ? qfsolve(G) %1 = [-3, -5, 1]~ ? qfsolve([1,0; 0,2]) %2 = -1 \\ no real solution ? qfsolve([1,0,0;0,3,0; 0,0,-2]) %3 = 3 \\ no solution in Q_3 ? qfsolve([1,0; 0,-2]) %4 = -2 \\ no solution, n = 2 @eprog pari-2.17.2/src/functions/linear_algebra/matinverseimage0000644000175000017500000000146414760123736022033 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.17.2/src/functions/linear_algebra/vector0000644000175000017500000000216514760123736020154 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, fills 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 the last two arguments are omitted, fills the vector with zeroes. \bprog ? vector(3,i, 5*i) %1 = [5, 10, 15] ? vector(3) %2 = [0, 0, 0] @eprog The variable $X$ is lexically scoped to each evaluation of \var{expr}. Any change to $X$ within \var{expr} does not affect subsequent evaluations, it still runs 1 to $n$. A local change allows for example different indexing: \bprog vector(10, i, i=i-1; f(i)) \\ i = 0, ..., 9 vector(10, i, i=2*i; f(i)) \\ i = 2, 4, ..., 20 @eprog\noindent This per-element scope for $X$ differs from \kbd{for} loop evaluations, as the following example shows: \bprog n = 3 v = vector(n); vector(n, i, i++) ----> [2, 3, 4] v = vector(n); for (i = 1, n, v[i] = i++) ----> [2, 0, 4] @eprog\noindent %\syn{NO} pari-2.17.2/src/functions/linear_algebra/qfperfection0000644000175000017500000000120214676526175021340 0ustar billbillFunction: qfperfection Section: linear_algebra C-Name: qfperfection Prototype: G Help: qfperfection(G): rank of matrix of xx~ for x minimal vectors of a Gram matrix G. Doc: $G$ being a square and symmetric matrix with integer entries representing a positive definite quadratic form, outputs the perfection rank of the form. That is, gives the rank of the family of the $s$ symmetric matrices $v{^{t}}v$, where $v$ runs through the minimal vectors. A form is perfect if and only if its perfection rank is $d(d+1)/2$ where $d$ is the dimension of $G$. The algorithm computes the minimal vectors and its runtime is exponential in $d$. pari-2.17.2/src/functions/linear_algebra/mattranspose0000644000175000017500000000031713637407207021367 0ustar billbillFunction: mattranspose Section: linear_algebra C-Name: gtrans Prototype: G Help: mattranspose(x): x~ = transpose of x. Doc: transpose of $x$ (also $x\til$). This has an effect only on vectors and matrices. pari-2.17.2/src/functions/linear_algebra/qfautoexport0000644000175000017500000000141714567450071021412 0ustar billbillFunction: qfautoexport Section: linear_algebra C-Name: qfautoexport Prototype: GD0,L, Help: qfautoexport(qfa,{flag}): qfa being an automorphism group as output by qfauto, output a string representing the underlying matrix group in GAP notation (default) or Magma notation (flag = 1). Doc: \var{qfa} being an automorphism group as output by \tet{qfauto}, export the underlying matrix group as a string suitable for (no flags or $\fl=0$) GAP or ($\fl=1$) Magma. The following example computes the size of the matrix group using GAP: \bprog ? G = qfauto([2,1;1,2]) %1 = [12, [[-1, 0; 0, -1], [0, -1; 1, 1], [1, 1; 0, -1]]] ? s = qfautoexport(G) %2 = "Group([[-1, 0], [0, -1]], [[0, -1], [1, 1]], [[1, 1], [0, -1]])" ? extern("echo \"Order("s");\" | gap -q") %3 = 12 @eprog pari-2.17.2/src/functions/linear_algebra/setintersect0000644000175000017500000000050014557721031021351 0ustar billbillFunction: setintersect Section: linear_algebra C-Name: setintersect Prototype: GG Help: setintersect(x,y): intersection of the sets x and y. Description: (vec, vec):vec setintersect($1, $2) Doc: intersection of the two sets $x$ and $y$ (see \kbd{setisset}). If $x$ or $y$ is not a set, the result is undefined. pari-2.17.2/src/functions/linear_algebra/mathess0000644000175000017500000000036313637407207020314 0ustar billbillFunction: mathess Section: linear_algebra C-Name: hess Prototype: G Help: mathess(x): Hessenberg form of x. Doc: returns a matrix similar to the square matrix $x$, which is in upper Hessenberg form (zero entries below the first subdiagonal). pari-2.17.2/src/functions/linear_algebra/setdelta0000644000175000017500000000101214676526175020457 0ustar billbillFunction: setdelta Section: linear_algebra C-Name: setdelta Prototype: GG Help: setdelta(x,y): symmetric difference of the sets x and y. Description: (vec, vec):vec setdelta($1, $2) Doc: symmetric difference of the two sets $x$ and $y$ (see \kbd{setisset}). If $x$ or $y$ is not a set, the result is undefined. \bprog ? a=[1,2,2,3];b=[4,2,3,4]; ? setdelta(Set(a), Set(b)) %2 = [1, 4] \\ the symmetric difference of the two sets ? setdelta(a,b) %3 = [1, 2, 2, 3, 4, 2, 3, 4] \\ undefined result @eprog pari-2.17.2/src/functions/linear_algebra/trace0000644000175000017500000000061414567450071017745 0ustar billbillFunction: trace Section: linear_algebra C-Name: gtrace Prototype: G Help: trace(x): trace of x. Doc: this applies to quite general $x$. If $x$ is not a matrix, it is equal to the sum of $x$ and its conjugate, except for polmods where it is the trace as an algebraic number. For $x$ a square matrix, it is the ordinary trace. If $x$ is a nonsquare matrix (but not a vector), an error occurs. pari-2.17.2/src/functions/linear_algebra/mathouseholder0000644000175000017500000000302014567450071021664 0ustar billbillFunction: mathouseholder Section: linear_algebra C-Name: mathouseholder Prototype: GG Help: mathouseholder(Q,v): applies a sequence Q of Householder transforms to the vector or matrix v. Doc: \sidx{Householder transform}applies a sequence $Q$ of Householder transforms, as returned by \kbd{matqr}$(M,1)$ to the vector or matrix $v$. \bprog ? m = [2,1; 3,2]; \\ some random matrix ? [Q,R] = matqr(m); ? Q %3 = [-0.554... -0.832...] [-0.832... 0.554...] ? R %4 = [-3.605... -2.218...] [0 0.277...] ? v = [1, 2]~; \\ some random vector ? Q * v %6 = [-2.218..., 0.277...]~ ? [q,r] = matqr(m, 1); ? exponent(r - R) \\ r is the same as R %8 = -128 ? q \\ but q has a different structure %9 = [[0.0494..., [5.605..., 3]]]] ? mathouseholder(q, v) \\ applied to v %10 = [-2.218..., 0.277...]~ @eprog\noindent The point of the Householder structure is that it efficiently represents the linear operator $v \mapsto Q \* v$ in a more stable way than expanding the matrix $Q$: \bprog ? m = mathilbert(20); v = vectorv(20,i,i^2+1); ? [Q,R] = matqr(m); ? [q,r] = matqr(m, 1); ? \p100 ? [q2,r2] = matqr(m, 1); \\ recompute at higher accuracy ? exponent(R - r) %5 = -127 ? exponent(R - r2) %6 = -127 ? exponent(mathouseholder(q,v) - mathouseholder(q2,v)) %7 = -119 ? exponent(Q*v - mathouseholder(q2,v)) %8 = 9 @eprog\noindent We see that $R$ is OK with or without a flag to \kbd{matqr} but that multiplying by $Q$ is considerably less precise than applying the sequence of Householder transforms encoded by $q$. pari-2.17.2/src/functions/linear_algebra/lindep0000644000175000017500000000416314567450071020125 0ustar billbillFunction: lindep Section: linear_algebra C-Name: lindep0 Prototype: GD0,L, Help: lindep(v,{flag=0}): integral linear dependencies between components of v. flag is optional, and can be 0: default, guess a suitable accuracy, or positive: accuracy to use for the computation, in decimal digits. Doc: \sidx{linear dependence} finds a small nontrivial integral linear combination between components of $v$. If none can be found return an empty vector. If $v$ is a vector with real/complex entries we use a floating point (variable precision) LLL algorithm. If $\fl = 0$ the accuracy is chosen internally using a crude heuristic. If $\fl > 0$ the computation is done with an accuracy of $\fl$ decimal digits. To get meaningful results in the latter case, the parameter $\fl$ should be smaller than the number of correct decimal digits in the input. \bprog ? lindep([sqrt(2), sqrt(3), sqrt(2)+sqrt(3)]) %1 = [-1, -1, 1]~ @eprog If $v$ is $p$-adic, $\fl$ is ignored and the algorithm LLL-reduces a suitable (dual) lattice. \bprog ? lindep([1, 2 + 3 + 3^2 + 3^3 + 3^4 + O(3^5)]) %2 = [1, -2]~ @eprog If $v$ is a matrix (or a vector of column vectors, or a vector of row vectors), $\fl$ is ignored and the function returns a non trivial kernel vector if one exists, else an empty vector. \bprog ? lindep([1,2,3;4,5,6;7,8,9]) %3 = [1, -2, 1]~ ? lindep([[1,0], [2,0]]) %4 = [2, -1]~ ? lindep([[1,0], [0,1]]) %5 = []~ @eprog If $v$ contains polynomials or power series over some base field, finds a linear relation with coefficients in the field. \bprog ? lindep([x*y, x^2 + y, x^2*y + x*y^2, 1]) %4 = [y, y, -1, -y^2]~ @eprog\noindent For better control, it is preferable to use \typ{POL} rather than \typ{SER} in the input, otherwise one gets a linear combination which is $t$-adically small, but not necessarily $0$. Indeed, power series are first converted to the minimal absolute accuracy occurring among the entries of $v$ (which can cause some coefficients to be ignored), then truncated to polynomials: \bprog ? v = [t^2+O(t^4), 1+O(t^2)]; L=lindep(v) %1 = [1, 0]~ ? v*L %2 = t^2+O(t^4) \\ small but not 0 @eprog pari-2.17.2/src/functions/linear_algebra/mathnf0000644000175000017500000000760314676526175020143 0ustar billbillFunction: mathnf Section: linear_algebra C-Name: mathnf0 Prototype: GD0,L, Help: mathnf(M,{flag=0}): (upper triangular) Hermite normal form of M, basis for the lattice formed by the columns of M. Basic values of flag are 0 (default): only return the Hermite normal form H, 1: return [H,U] such that H is the HNF of M, and U is an invertible matrix such that MU=H. These two use a naive algorithm; larger values of flag correspond to more involved algorithms and are restricted to integer matrices; flag = 4: returns [H,U] using LLL reduction along the way; flag = 5: return [H,U,P] where P is a permutation of row indices such that P applied to M U is H. Doc: let $R$ be a Euclidean ring, equal to $\Z$ or to $K[X]$ for some field $K$. If $M$ is a (not necessarily square) matrix with entries in $R$, this routine finds the \emph{upper triangular} \idx{Hermite normal form} of $M$. If the rank of $M$ is equal to its number of rows, this is a square matrix. In general, the columns of the result form a basis of the $R$-module spanned by the columns of $M$. The values of $\fl$ are: \item 0 (default): only return the Hermite normal form $H$ \item 1 (complete output): return $[H,U]$, where $H$ is the Hermite normal form of $M$, and $U$ is a transformation matrix such that $MU=[0|H]$. The matrix $U$ belongs to $\text{GL}(R)$. When $M$ has a large kernel, the entries of $U$ are in general huge. \noindent For these two values, we use a naive algorithm, which behaves well in small dimension only. Larger values correspond to different algorithms, are restricted to \emph{integer} matrices, and all output the unimodular matrix $U$. From now on all matrices have integral entries. \item $\fl=4$, returns $[H,U]$ as in ``complete output'' above, using a variant of \idx{LLL} reduction along the way. The matrix $U$ is provably small in the $L_{2}$ sense, and often close to optimal; but the reduction is in general slow, although provably polynomial-time. If $\fl=5$, uses Batut's algorithm and output $[H,U,P]$, such that $H$ and $U$ are as before and $P$ is a permutation of the rows such that $P$ applied to $MU$ gives $H$. This is in general faster than $\fl=4$ but the matrix $U$ is usually worse; it is heuristically smaller than with the default algorithm. When the matrix is dense and the dimension is large (bigger than 100, say), $\fl = 4$ will be fastest. When $M$ has maximal rank, then \bprog H = mathnfmod(M, matdetint(M)) @eprog\noindent will be even faster. You can then recover $U$ as $M^{-1}H$. \bprog ? M = matrix(3,4,i,j,random([-5,5])) %1 = [ 0 2 3 0] [-5 3 -5 -5] [ 4 3 -5 4] ? [H,U] = mathnf(M, 1); ? U %3 = [-1 0 -1 0] [ 0 5 3 2] [ 0 3 1 1] [ 1 0 0 0] ? H %5 = [19 9 7] [ 0 9 1] [ 0 0 1] ? M*U %6 = [0 19 9 7] [0 0 9 1] [0 0 0 1] @eprog For convenience, $M$ is allowed to be a \typ{VEC}, which is then automatically converted to a \typ{MAT}, as per the \tet{Mat} function. For instance to solve the generalized extended gcd problem, one may use \bprog ? v = [116085838, 181081878, 314252913,10346840]; ? [H,U] = mathnf(v, 1); ? U %2 = [ 103 -603 15 -88] [-146 13 -1208 352] [ 58 220 678 -167] [-362 -144 381 -101] ? v*U %3 = [0, 0, 0, 1] @eprog\noindent This also allows to input a matrix as a \typ{VEC} of \typ{COL}s of the same length (which \kbd{Mat} would concatenate to the \typ{MAT} having those columns): \bprog ? v = [[1,0,4]~, [3,3,4]~, [0,-4,-5]~]; mathnf(v) %1 = [47 32 12] [ 0 1 0] [ 0 0 1] @eprog Variant: Also available are \fun{GEN}{hnf}{GEN M} ($\fl=0$) and \fun{GEN}{hnfall}{GEN M} ($\fl=1$). To reduce \emph{huge} relation matrices (sparse with small entries, say dimension $400$ or more), you can use the pair \kbd{hnfspec} / \kbd{hnfadd}. Since this is quite technical and the calling interface may change, they are not documented yet. Look at the code in \kbd{basemath/hnf\_snf.c}. pari-2.17.2/src/functions/gp2c_internal/0000755000175000017500000000000014760315601016515 5ustar billbillpari-2.17.2/src/functions/gp2c_internal/_formatcode0000644000175000017500000000043114567450071020726 0ustar billbillFunction: _formatcode Class: gp2c_internal Description: (#small):void $1 (small):small %ld (small_int):small_int %d (#str):void $%1 (str):str %s (gen):gen %Ps pari-2.17.2/src/functions/gp2c_internal/_cgetg0000644000175000017500000000024013637407207017672 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.17.2/src/functions/gp2c_internal/_gerepileupto0000644000175000017500000000053013637407207021307 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.17.2/src/functions/gp2c_internal/_cast0000644000175000017500000000644214567450071017545 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, bool, usmall, small) (empty, void, negbool, bool) (empty, typ, str, genstr,gen) (empty, errtyp, str) (empty, vecsmall, gen) (empty, vecvecsmall, vec, gen) (empty, list, gen) (empty, closure, gen) (empty, error, gen) (empty, bnr, bnf, nf, vec) (empty, bnr, bnf, clgp, vec) (empty, ell, vec) (empty, prid, vec) (empty, gal, vec) (empty, var, pol, gen) (empty, Fp, Fq, gen) (empty, FpX, FqX, 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 (usmall):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):usmall (typ):usmall (small):usmall (bool):small (typ):small (small_int):small (usmall):small (bptr):small *$(1) (int):small itos($1) (int):usmall itou($1) (#lg):small:parens ${1 value 1 sub} (lg):small:parens $(1)-1 (gen):small gtos($1) (gen):usmall gtou($1) (void):int gen_0 (-2):int gen_m2 (-1):int gen_m1 (0):int gen_0 (1):int gen_1 (2):int gen_2 (bool):int stoi($1) (small):int stoi($1) (usmall):int utoi($1) (mp):int (gen):int (mp):real (gen):real (int):mp (real):mp (gen):mp (#bool):lg:parens ${1 1 value add} (bool):lg:parens $(1)+1 (#small):lg:parens ${1 1 value add} (small):lg:parens $(1)+1 (gen):error (gen):closure (gen):vecsmall (nf):vec (bnf):vec (bnr):vec (ell):vec (clgp):vec (prid):vec (gal):vec (vecvecsmall):vec (gen):vec (vec):vecvecsmall (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 (vecvecsmall):gen (list):gen (pol):gen (genstr):gen (error):gen (closure):gen (Fp):gen (FpX):gen (Fq):gen (FqX):gen (gen):Fp (gen):FpX (gen):Fq (gen):FqX (gen):genstr GENtoGENstr($1) (str):genstr strtoGENstr($1) (gen):str GENtostr_unquoted($1) (genstr):str GSTR($1) (typ):str type_name($1) (errtyp):str numerr_name($1) (#str):typ ${1 str_format} (#str):errtyp ${1 str_format} (bnf):nf bnf_get_nf($1) (gen):nf (bnr):bnf bnr_get_bnf($1) (gen):bnf (gen):bnr (bnf):clgp bnf_get_clgp($1) (bnr):clgp bnr_get_clgp($1) (gen):clgp (gen):ell (gen):gal (gen):prid (Fp):Fq pari-2.17.2/src/functions/gp2c_internal/_norange0000644000175000017500000000011414567450071020232 0ustar billbillFunction: _norange Class: gp2c_internal Description: ():small LONG_MAX pari-2.17.2/src/functions/gp2c_internal/_tovec0000644000175000017500000000157614567450071017736 0ustar billbillFunction: _tovec Class: gp2c_internal Help: Create a vector holding the arguments (shallow) Description: ():vec cgetg(1, t_VEC) (gen):vec mkvec($1) (gen,gen):vec mkvec2($1, $2) (gen,gen,gen):vec mkvec3($1, $2, $3) (gen,gen,gen,gen):vec mkvec4($1, $2, $3, $4) (gen,gen,gen,gen,gen):vec mkvec5($1, $2, $3, $4, $5) (gen,...):vec mkvecn($#, $2) Function: _tovecprec Class: gp2c_internal Help: Create a vector holding the arguments and prec (shallow) Description: ():vec:prec mkvecs($prec) (gen):vec:prec mkvec2($1, stoi($prec)) (gen,gen):vec:prec mkvec3($1, $2, stoi($prec)) (gen,gen,gen):vec:prec mkvec4($1, $2, $3, stoi($prec)) (gen,gen,gen,gen):vec:prec mkvec5($1, $2, $3, $4, stoi($prec)) (gen,...):vec:prec mkvecn(${nbarg 1 add}, $2, stoi($prec)) pari-2.17.2/src/functions/gp2c_internal/_gc_needed0000644000175000017500000000014714567450071020504 0ustar billbillFunction: _gc_needed Class: gp2c_internal Description: (pari_sp):bool gc_needed($1, 1) pari-2.17.2/src/functions/gp2c_internal/_const0000644000175000017500000000101114567450071017724 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: ("x"):var 0 ("y"):var 1 (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.17.2/src/functions/gp2c_internal/_badtype0000644000175000017500000000145114567450071020236 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 (list):bool:parens typ($1) != t_LIST (*nf):void:parens $1 = checknf($1) (*bnf):void:parens $1 = checkbnf($1) (bnr):void checkbnr($1) (prid):void checkprid($1) (clgp):void checkabgrp($1) (ell):void checkell($1) (*gal):void:parens $1 = checkgal($1) pari-2.17.2/src/functions/gp2c_internal/_typedef0000644000175000017500000000523614676526175020265 0ustar billbillFunction: _decl_base Class: gp2c_internal Description: (C!void) void (C!long) long (C!ulong) ulong (C!int) int (C!GEN) GEN (C!char*) char (C!byteptr) byteptr (C!pari_sp) pari_sp (C!func_GG) GEN (C!forprime_t) forprime_t (C!forcomposite_t) forcomposite_t (C!forpart_t) forpart_t (C!forperm_t) forperm_t (C!forvec_t) forvec_t (C!forsubset_t) forsubset_t (C!parfor_t) parfor_t (C!parforstep_t) parforstep_t (C!parforeach_t) parforeach_t (C!parforprime_t) parforprime_t (C!parforvec_t) parforvec_t Function: _decl_ext Class: gp2c_internal Description: (C!char*) *$1 (C!func_GG) (*$1)(GEN, GEN) Function: _typedef Class: gp2c_internal Description: (empty) void (void) void (negbool) long (bool) long (small_int) int (usmall) ulong (small) long (int) GEN (real) GEN (mp) GEN (lg) long (vecsmall) GEN (vec) GEN (vecvecsmall) GEN (list) GEN (var) long (pol) GEN (gen) GEN (closure) GEN (error) GEN (genstr) GEN (str) char* (bptr) byteptr (forcomposite) forcomposite_t (forpart) forpart_t (forperm) forperm_t (forprime) forprime_t (forsubset) forsubset_t (forvec) forvec_t (parfor) parfor_t (parforstep) parforstep_t (parforeach) parforeach_t (parforprime) parforprime_t (parforvec) parforvec_t (func_GG) func_GG (pari_sp) pari_sp (typ) long (errtyp) long (nf) GEN (bnf) GEN (bnr) GEN (ell) GEN (clgp) GEN (prid) GEN (gal) GEN (Fp) GEN (FpX) GEN (Fq) GEN (FqX) 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!ulong) u (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!ulong) U (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.17.2/src/functions/gp2c_internal/_prec0000644000175000017500000000026514567450071017541 0ustar billbillFunction: _ndec2prec Class: gp2c_internal Description: (small):small ndec2prec($1) Function: _ndec2nbits Class: gp2c_internal Description: (small):small ndec2nbits($1) pari-2.17.2/src/functions/gp2c_internal/_strtoclosure0000644000175000017500000000025313637407207021355 0ustar billbillFunction: _strtoclosure Class: gp2c_internal Description: (str):closure strtofunction($1) (str,gen,...):closure strtoclosure($1, ${nbarg 1 sub}, $3) pari-2.17.2/src/functions/gp2c_internal/_maxprime0000644000175000017500000000013213637407207020423 0ustar billbillFunction: _maxprime Class: gp2c_internal Description: ():small maxprime() pari-2.17.2/src/functions/gp2c_internal/_wrap0000644000175000017500000000101114567450071017547 0ustar billbillFunction: _wrap_G Class: gp2c_internal C-Name: gp_call Prototype: G Description: (gen):gen $1 Function: _wrap_Gp Class: gp2c_internal C-Name: gp_callprec Prototype: Gp Description: (gen):gen $1 Function: _wrap_GG Class: gp2c_internal C-Name: gp_call2 Prototype: GG Description: (gen):gen $1 Function: _wrap_vG Class: gp2c_internal C-Name: gp_callvoid Prototype: lG Description: (void):small 0 Function: _wrap_bG Class: gp2c_internal C-Name: gp_callbool Prototype: lG Description: (bool):bool $1 pari-2.17.2/src/functions/gp2c_internal/_avma0000644000175000017500000000012213637407207017524 0ustar billbillFunction: _avma Class: gp2c_internal Description: ():pari_sp avma pari-2.17.2/src/functions/gp2c_internal/_gerepileall0000644000175000017500000000030113637407207021064 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.17.2/src/functions/gp2c_internal/_stack_lim0000644000175000017500000000034313637407207020553 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.17.2/src/functions/gp2c/0000755000175000017500000000000014760315601014621 5ustar billbillpari-2.17.2/src/functions/gp2c/copy0000644000175000017500000000066014567450071015526 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) (list):list listinit($1) (gen):gen gcopy($1) pari-2.17.2/src/functions/gp2c/unclone0000644000175000017500000000015413637407207016215 0ustar billbillFunction: unclone Class: gp2c Description: (small):void (void)0 /*unclone*/ (gen):void gunclone($1) pari-2.17.2/src/functions/gp2c/DEBUGLEVEL0000644000175000017500000000017314557721031016165 0ustar billbillFunction: DEBUGLEVEL C-Name: DEBUGLEVEL Prototype: v Class: gp2c Description: ():small DEBUGLEVEL pari-2.17.2/src/functions/gp2c/clone0000644000175000017500000000102014567450071015643 0ustar billbillFunction: clone Class: gp2c Description: (small):small:parens $1 (int):int gclone($1) (real):real gclone($1) (mp):mp gclone($1) (vecsmall):vecsmall gclone($1) (vec):vec gclone($1) (pol):pol gclone($1) (list):list gclone($1) (closure):closure gclone($1) (genstr):genstr gclone($1) (gen):gen gclone($1) pari-2.17.2/src/functions/algebras/0000755000175000017500000000000014760315601015546 5ustar billbillpari-2.17.2/src/functions/algebras/algiscommutative0000644000175000017500000000110714567450071021053 0ustar billbillFunction: algiscommutative Section: algebras C-Name: algiscommutative Prototype: iG Help: algiscommutative(al): test whether the algebra al is commutative. Doc: \var{al} being a table algebra output by \tet{algtableinit} or a central simple algebra output by \tet{alginit}, tests whether the algebra \var{al} is commutative. \bprog ? mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]]; ? A = algtableinit(mt); ? algiscommutative(A) %3 = 0 ? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]]; ? A = algtableinit(mt,2); ? algiscommutative(A) %6 = 1 @eprog pari-2.17.2/src/functions/algebras/alglatelement0000644000175000017500000000111514567450071020313 0ustar billbillFunction: alglatelement Section: algebras C-Name: alglatelement Prototype: GGG Help: alglatelement(al,lat,c): returns the element of al whose coordinates on the Z-basis of lat are c. Doc: Given an algebra \var{al}, a lattice \var{lat} and a~\typ{COL}~\var{c}, returns the element of~\var{al} whose coordinates on the \Z-basis of~\var{lat} are given by~\var{c}. \bprog ? al = alginit(nfinit(y^2+7), [-1,-1]); ? a1 = [1,-1,0,1,2,0,1,2]~; ? lat1 = alglathnf(al,a1); ? c = [1..8]~; ? elt = alglatelement(al,lat1,c); ? alglatcontains(al,lat1,elt,&c2) %6 = 1 ? c==c2 %7 = 1 @eprog pari-2.17.2/src/functions/algebras/HEADER0000644000175000017500000001632514760123736016436 0ustar billbillFunction: _header_algebras Class: header Section: algebras Doc: \section{Associative and central simple algebras} This section collects functions related to associative algebras and central simple algebras (CSA) over number fields. \subsec{Algebra definitions} %GPHELPskip Let $A$ be a finite-dimensional unital associative algebra over a field $K$. The algebra $A$ is \emph{central} if its center is $K$ and it is \emph{simple} if it has no nontrivial two-sided ideals. We provide functions to handle associative algebras of finite dimension over~$\Q$ or~$\F_{p}$. We represent them by the left multiplication table on a basis over the prime subfield; the function \kbd{algtableinit} creates the object representing an associative algebra. We also provide functions to handle central simple algebras over a number field $K$. We represent them either by the left multiplication table on a basis over the center $K$ or by a cyclic algebra (see below); the function~\kbd{alginit} creates the object representing a central simple algebra. The set of elements of an algebra~$A$ that annihilate every simple left $A$-module is a two-sided ideal, called the \emph{Jacobson radical} of~$A$. If the Jacobson radical is trivial, the algebra is \emph{semisimple}: it is isomorphic to a direct product of simple algebras. The dimension of a CSA over its center $K$ is always a square $d^{2}$ and the integer $d$ is called the \emph{degree} of the algebra over~$K$. A CSA over a field~$K$ is always isomorphic to~$M_{k}(D)$ for some integer~$k$ and some central division algebra~$D$ of degree~$e$: the integer~$e$ is the \emph{index} of the algebra. Let $L/K$ be a cyclic extension of degree $d$, let $\sigma$ be a generator of $\text{Gal}(L/K)$ and let $b\in K^{*}$. Then the \emph{cyclic algebra} $(L/K,\sigma,b)$ is the algebra $\bigoplus_{i=0}^{d-1}x^{i}L$ with $x^{d}=b$ and $\ell x=x\sigma(\ell)$ for all~$\ell\in L$. The algebra $(L/K,\sigma,b)$ is a central simple $K$-algebra of degree~$d$, and it is an $L$-vector space. Left multiplication is $L$-linear and induces a $K$-algebra isomorphism $(L/K,\sigma,b)\otimes_{K} L\to M_{d}(L)$. Let $K$ be a nonarchimedean local field with uniformizer $\pi$, and let $L/K$ be the unique unramified extension of degree $d$. Then every central simple algebra $A$ of degree $d$ over $K$ is isomorphic to $(L/K, \Frob, \pi^{h})$ for some integer $h$. The element $h/d\in \Q/\Z$ is called the \emph{Hasse invariant} of $A$. Let ${\bf H}$ be the Hamilton quaternion algebra, that is the 4-dimensional algebra over $\R$ with basis~$1,i,j,ij$ and multiplication given by~$i^{2}=j^{2}=-1$ and $ji=-ij$, which is also the cyclic algebra~$(\C/\R,z\mapsto \bar{z},-1)$. Every central simple algebra $A$ of degree $d$ over $\R$ is isomorphic to~$M_{d}(\R)$ or $M_{d/2}({\bf H})$. We define the \emph{Hasse invariant} of~$A$ to be~$0\in\Q/\Z$ in the first case and~$1/2\in\Q/\Z$ in the second case. \subsec{Orders in algebras} %GPHELPskip Let~$A$ be an algebra of finite dimension over~$\Q$. An \emph{order} in~$A$ is a finitely generated $\Z$-submodule~${\cal O}$ such that~$\Q{\cal O} = A$, that is also a subring with unit. By default the data computed by~\kbd{alginit} contains a~$\Z$-basis of a maximal order~${\cal O}_{0}$. We define natural orders in central simple algebras defined by a cyclic algebra or by a multiplication table over the center. Let~$A = (L/K,\sigma,b) = \bigoplus_{i=0}^{d-1}x^{i}L$ be a cyclic algebra over a number field~$K$ of degree~$n$ with ring of integers~$\Z_{K}$. Let~$\Z_{L}$ be the ring of integers of~$L$, and assume that~$b$ is integral. Then the submodule~${\cal O} = \bigoplus_{i=0}^{d-1}x^{i}\Z_{L}$ is an order in~$A$, called the \emph{natural order}. Let~$\omega_{0},\dots,\omega_{nd-1}$ be a~$\Z$-basis of~$\Z_{L}$. The \emph{natural basis} of~${\cal O}$ is~$b_{0},\dots,b_{nd^{2}-1}$ where~$b_{i} = x^{i/(nd)}\omega_{(i \mod nd)}$. Now let~$A$ be a central simple algebra of degree~$d$ over a number field~$K$ of degree~$n$ with ring of integers~$\Z_{K}$. Let~$e_{0},\dots,e_{d^{2}-1}$ be a basis of~$A$ over~$K$ and assume that the left multiplication table of~$A$ on~$(e_{i})$ is integral. Then the submodule~${\cal O} = \bigoplus_{i=0}^{d^{2}-1}\Z_{K} e_{i}$ is an order in~$A$, called the \emph{natural order}. Let~$\omega_{0},\dots,\omega_{n-1}$ be a~$\Z$-basis of~$\Z_{K}$. The \emph{natural basis} of~${\cal O}$ is~$b_{0},\dots,b_{nd^{2}-1}$ where~$b_{i} = \omega_{(i \mod n)}e_{i/n}$. \subsec{Lattices in algebras} %GPHELPskip We also provide functions to handle full lattices in algebras over~$\Q$. A full lattice~$J\subset A$ is represented by a $2$-component \typ{VEC}~$[I,t]$ representing~$J = tI$, where \item $I$ is an integral nonsingular upper-triangular matrix representing a sublattice of~${\cal O}_{0}$ expressed on the integral basis, and \item $t\in\Q_{>0}$ is a \typ{INT} or \typ{FRAC}. For the sake of efficiency you should use matrices~$I$ that are primitive and in Hermite Normal Form; this makes the representation unique. No GP function uses this property, but all GP functions return lattices in this form. The prefix for lattice functions is \kbd{alglat}. \subsec{GP conventions for algebras} %GPHELPskip As with number fields, we represent elements of central simple algebras in two ways, called the \emph{algebraic representation} and the \emph{basis representation}, and you can convert betweeen the two with the functions \kbd{algalgtobasis} and \kbd{algbasistoalg}. In every central simple algebra object, we store a~$\Z$-basis of an order~${\cal O}_{0}$, and the basis representation is simply a \typ{COL} with coefficients in~$\Q$ expressing the element in that basis. If no maximal order was computed by~\kbd{alginit}, then~${\cal O}_{0}$ is the natural order. If a maximal order was computed, then~${\cal O}_{0}$ is a maximal order containing the natural order. For a cyclic algebra~$A = (L/K,\sigma,b)$, the algebraic representation is a \typ{COL} with coefficients in~$L$ representing the element in the decomposition~$A = \bigoplus_{i=0}^{d-1}x^{i}L$. For a central simple algebra defined by a multiplication table over its center~$K$ on a basis~$(e_{i})$, the algebraic representation is a \typ{COL} with coefficients in~$K$ representing the element on the basis~$(e_{i})$. \misctitle{Warning} The coefficients in the decomposition~$A = \bigoplus_{i=0}^{d-1}x^{i}L$ are not the same as those in the decomposition~$A = \bigoplus_{i=0}^{d-1}Lx^{i}$! The $i$-th coefficients are related by conjugating by~$x^{i}$, which on~$L$ amounts to acting by~$\sigma^{i}$. \misctitle{Warning} For a central simple algebra over $\Q$ defined by a multiplication table, we cannot distinguish between the basis and the algebraic representations from the size of the vectors. The behavior is then to always interpret the column vector as a basis representation if the coefficients are \typ{INT} or \typ{FRAC}, and as an algebraic representation if the coefficients are \typ{POL} or \typ{POLMOD}. An element of the Hamilton quaternion algebra ${\bf H}$ can be represented as a \typ{REAL}, a \typ{COMPLEX} representing an element of~$\C = \R+\R i\subset {\bf H}$, or a $4$ components \typ{COL} of \typ{REAL} encoding the coordinates on the basis~$1,i,j,ij$. pari-2.17.2/src/functions/algebras/algdegree0000644000175000017500000000051114567450071017413 0ustar billbillFunction: algdegree Section: algebras C-Name: algdegree Prototype: lG Help: algdegree(al): degree of the central simple algebra al. Doc: Given a central simple algebra \var{al} output by \tet{alginit}, returns the degree of \var{al}. \bprog ? nf = nfinit(y^3-y+1); ? A = alginit(nf, [-1,-1]); ? algdegree(A) %3 = 2 @eprog pari-2.17.2/src/functions/algebras/algdivl0000644000175000017500000000135714676526175017141 0ustar billbillFunction: algdivl Section: algebras C-Name: algdivl Prototype: DGGG Help: algdivl({al},x,y): element x\y in al (Hamilton quaternions if omitted). Doc: Given two elements $x$ and $y$ in \var{al} (Hamilton quaternions if omitted), computes their left quotient $x\backslash y$ in the algebra \var{al}: an element $z$ such that $xz=y$ (such an element is not unique when $x$ is a zerodivisor). If~$x$ is invertible, this is the same as $x^{-1}y$. Assumes that $y$ is left divisible by $x$ (i.e. that $z$ exists). Also accepts square matrices with coefficients in~\var{al}. \bprog ? A = alginit(nfinit(y),[-1,1]); ? x = [1,1]~; algisinv(A,x) % = 0 ? z = algmul(A,x,algrandom(A,2)) % = [0, 0, 0, 8]~ ? algdivl(A,x,z) % = [4, 4, 0, 0]~ @eprog pari-2.17.2/src/functions/algebras/algisassociative0000644000175000017500000000154614760123736021037 0ustar billbillFunction: algisassociative Section: algebras C-Name: algisassociative Prototype: iGD0,G, Help: algisassociative(mt,p=0): true (1) if the multiplication table mt is suitable for algtableinit(mt,p), false (0) otherwise. Doc: Returns 1 if the multiplication table \kbd{mt} is suitable for \kbd{algtableinit(mt,p)}, 0 otherwise. More precisely, \kbd{mt} should be a \typ{VEC} of $n$ matrices in $M_{n}(K)$, giving the left multiplications by the basis elements $e_{1}, \dots, e_{n}$ (structure constants). We check whether the first basis element $e_{1}$ is $1$ and $e_{i}(e_{j}e_{k}) = (e_{i}e_{j})e_{k}$ for all $i,j,k$. \bprog ? mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]]; ? algisassociative(mt) %2 = 1 @eprog May be used to check a posteriori an algebra: we also allow \kbd{mt} as output by \tet{algtableinit} ($p$ is ignored in this case). pari-2.17.2/src/functions/algebras/algsubalg0000644000175000017500000000160214567450071017437 0ustar billbillFunction: algsubalg Section: algebras C-Name: algsubalg Prototype: GG Help: algsubalg(al,B): subalgebra of al with basis B. Doc: \var{al} being a table algebra output by \tet{algtableinit} and \var{B} being a basis of a subalgebra of~\var{al} represented by a matrix, computes an algebra~\var{al2} isomorphic to \var{B}. Returns $[\var{al2},\var{B2}]$ where \var{B2} is a possibly different basis of the subalgebra \var{al2}, with respect to which the multiplication table of \var{al2} is defined. \bprog ? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]]; ? A = algtableinit(mt,2); ? B = algsubalg(A,[1,0; 0,0; 0,1]); ? algdim(A) %4 = 3 ? algdim(B[1]) %5 = 2 ? m = matcompanion(x^4+1); ? mt = [m^i | i <- [0..3]]; ? al = algtableinit(mt); ? B = [1,0;0,0;0,1/2;0,0]; ? al2 = algsubalg(al,B); ? algdim(al2[1]) ? al2[2] %13 = [1 0] [0 0] [0 1] [0 0] @eprog pari-2.17.2/src/functions/algebras/algb0000644000175000017500000000066214567450071016410 0ustar billbillFunction: algb Section: algebras C-Name: algb Prototype: mG Help: algb(al): the element b of the center of the cyclic algebra al used to define it. Doc: Given a cyclic algebra $\var{al} = (L/K,\sigma,b)$ output by \tet{alginit}, returns the element $b\in K$. \bprog nf = nfinit(y); ? p = idealprimedec(nf,7)[1]; ? p2 = idealprimedec(nf,11)[1]; ? A = alginit(nf,[3,[[p,p2],[1/3,2/3]],[0]]); ? algb(A) %5 = Mod(-77, y) @eprog pari-2.17.2/src/functions/algebras/algdivr0000644000175000017500000000046614676526175017147 0ustar billbillFunction: algdivr Section: algebras C-Name: algdivr Prototype: DGGG Help: algdivr({al},x,y): element x/y in al (Hamilton quaternions if omitted). Doc: Given two elements $x$ and $y$ in \var{al} (Hamilton quaternions if omitted), returns $xy^{-1}$. Also accepts square matrices with coefficients in \var{al}. pari-2.17.2/src/functions/algebras/alglatinter0000644000175000017500000000124114567450071020003 0ustar billbillFunction: alglatinter Section: algebras C-Name: alglatinter Prototype: GGGD& Help: alglatinter(al,lat1,lat2,{&ptsum}): the intersection of the lattices lat1 and lat2. If ptsum is present, sets it to the sum of the lattices. Doc: Given an algebra \var{al} and two lattices \var{lat1} and \var{lat2} in~\var{al}, computes the intersection~$lat1\cap lat2$. If \var{ptsum} is present, sets it to the sum~$lat1 + lat2$. \bprog ? al = alginit(nfinit(y^2+7), [-1,-1]); ? lat1 = alglathnf(al,[1,1,0,0,0,0,0,0]~); ? lat2 = alglathnf(al,[1,0,1,0,0,0,0,0]~); ? latinter = alglatinter(al,lat1,lat2,&latsum); ? matdet(latsum[1]) %5 = 4 ? matdet(latinter[1]) %6 = 64 @eprog pari-2.17.2/src/functions/algebras/algsimpledec0000644000175000017500000000227714676526175020152 0ustar billbillFunction: algsimpledec Section: algebras C-Name: algsimpledec Prototype: GD0,L, Help: algsimpledec(al,{maps=0}): [J,dec] where J is the Jacobson radical of al and dec is the decomposition into simple algebras of the semisimple algebra al/J. Doc: \var{al} being the output of \tet{algtableinit}, returns a \typ{VEC} $[J,[\var{al}_{1},\dots,\var{al}_{n}]]$ where $J$ is a basis of the Jacobson radical of \var{al} and~$\var{al}/J$ is isomorphic to the direct product of the simple algebras~$\var{al}_{i}$. When $\var{maps}=1$, each~$\var{al}_{i}$ is replaced with a \typ{VEC} $[\var{al}_{i},\var{proj}_{i},\var{lift}_{i}]$ where $\var{proj}_{i}$ and~$\var{lift}_{i}$ are matrices respectively representing the projection map~$\var{al} \to \var{al}_{i}$ and a section of it. Modulo~$J$, the images of the $\var{lift}_{i}$ form a direct sum in~$\var{al}/J$, so that the images of~$1\in\var{al}_{i}$ under~$\var{lift}_{i}$ are central primitive idempotents of~$\var{al}/J$. The factors are sorted by increasing dimension, then increasing dimension of the center. This ensures that the ordering of the isomorphism classes of the factors is deterministic over finite fields, but not necessarily over~$\Q$. pari-2.17.2/src/functions/algebras/alglathnf0000644000175000017500000000162514760123736017443 0ustar billbillFunction: alglathnf Section: algebras C-Name: alglathnf Prototype: GGD0,G, Help: alglathnf(al,m,{d=0}): the lattice generated by the columns of m, assuming that this lattice contains d times the integral basis of al. Doc: Given an algebra \var{al} and a matrix \var{m} with columns representing elements of \var{al}, returns the lattice $L$ generated by the columns of \var{m}. If provided, \var{d} must be a rational number such that $L$ contains \var{d} times the natural basis of~\var{al}. The argument \var{m} is also allowed to be a \typ{VEC} of \typ{MAT}, in which case \var{m} is replaced by the concatenation of the matrices, or a \typ{COL}, in which case \var{m} is replaced by its left multiplication table as an element of \var{al}. \bprog ? al = alginit(nfinit(y^2+7), [-1,-1]); ? a = [1,1,-1/2,1,1/3,-1,1,1]~; ? mt = algtomatrix(al,a,1); ? lat = alglathnf(al,mt); ? lat[2] %5 = 1/6 @eprog pari-2.17.2/src/functions/algebras/algcentralproj0000644000175000017500000000204514676526175020521 0ustar billbillFunction: algcentralproj Section: algebras C-Name: alg_centralproj Prototype: GGD0,L, Help: algcentralproj(al,z,{maps=0}): projections of the algebra al on the orthogonal central idempotents z[i]. Doc: Given a table algebra \var{al} output by \tet{algtableinit} and a \typ{VEC} $\var{z}=[z_{1},\dots,z_{n}]$ of orthogonal central idempotents, returns a \typ{VEC} $[al_{1},\dots,al_{n}]$ of algebras such that $al_{i} = z_{i}\, al$. If $\var{maps}=1$, each $al_{i}$ is a \typ{VEC} $[quo,proj,lift]$ where \var{quo} is the quotient algebra, \var{proj} is a \typ{MAT} representing the projection onto this quotient and \var{lift} is a \typ{MAT} representing a lift. A simple example: $\F_{2}\times \F_{4}$, generated by~$1=(1,1)$, $e=(1,0)$ and~$x$ such that~$x^{2}+x+1=0$. We have~$e^{2}=e$, $x^{2}=x+1$ and~$ex=0$. \bprog ? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]]; ? A = algtableinit(mt,2); ? e = [0,1,0]~; ? e2 = algsub(A,[1,0,0]~,e); ? [a,a2] = algcentralproj(A,[e,e2]); ? algdim(a) %6 = 1 ? algdim(a2) %7 = 2 @eprog pari-2.17.2/src/functions/algebras/alghasse0000644000175000017500000000140714676526175017302 0ustar billbillFunction: alghasse Section: algebras C-Name: alghasse Prototype: GDG Help: alghasse(al,{pl}): the hasse invariant of the central simple algebra al at the place pl. Doc: Given a central simple algebra \var{al} output by \tet{alginit} and a prime ideal or an integer between $1$ and $r_{1}+r_{2}$, returns a \typ{FRAC} $h$ : the local Hasse invariant of \var{al} at the place specified by \var{pl}. If \var{al} is an algebra over $\R$, returns the Hasse invariant of \var{al} \bprog ? nf = nfinit(y^2-5); ? A = alginit(nf, [-1,y]); ? alghasse(A, 1) %3 = 1/2 ? alghasse(A, 2) %4 = 0 ? alghasse(A, idealprimedec(nf,2)[1]) %5 = 1/2 ? alghasse(A, idealprimedec(nf,5)[1]) %6 = 0 ? H = alginit(1.,1/2); \\ Hamilton quaternion algebra ? alghasse(H) %8 = 1/2 @eprog pari-2.17.2/src/functions/algebras/algindex0000644000175000017500000000164714676526175017314 0ustar billbillFunction: algindex Section: algebras C-Name: algindex Prototype: lGDG Help: algindex(al,{pl}): the index of the central simple algebra al. If pl is set, it should be a prime ideal of the center or an integer between 1 and r1+r2, and in that case return the local index at the place pl instead. Doc: Returns the index of the central simple algebra~$A$ over~$K$ (as output by alginit), that is the degree~$e$ of the unique central division algebra~$D$ over $K$ such that~$A$ is isomorphic to some matrix algebra~$M_{k}(D)$. If \var{pl} is set, it should be a prime ideal of~$K$ or an integer between~$1$ and~$r_{1}+r_{2}$, and in that case return the local index at the place \var{pl} instead. \bprog ? nf = nfinit(y^2-5); ? A = alginit(nf, [-1,y]); ? algindex(A, 1) %3 = 2 ? algindex(A, 2) %4 = 1 ? algindex(A, idealprimedec(nf,2)[1]) %5 = 2 ? algindex(A, idealprimedec(nf,5)[1]) %6 = 1 ? algindex(A) %7 = 2 @eprog pari-2.17.2/src/functions/algebras/algalgtobasis0000644000175000017500000000114714567450071020316 0ustar billbillFunction: algalgtobasis Section: algebras C-Name: algalgtobasis Prototype: GG Help: algalgtobasis(al,x): transforms the element x of the algebra al into a column vector on the integral basis of al. Doc: Given an element \var{x} in the central simple algebra \var{al} output by \tet{alginit}, transforms it to a column vector on the integral basis of \var{al}. This is the inverse function of \tet{algbasistoalg}. \bprog ? A = alginit(nfinit(y^2-5),[2,y]); ? algalgtobasis(A,[y,1]~) %2 = [0, 2, 0, -1, 2, 0, 0, 0]~ ? algbasistoalg(A,algalgtobasis(A,[y,1]~)) %3 = [Mod(Mod(y, y^2 - 5), x^2 - 2), 1]~ @eprog pari-2.17.2/src/functions/algebras/alglatadd0000644000175000017500000000123614760123736017416 0ustar billbillFunction: alglatadd Section: algebras C-Name: alglatadd Prototype: GGGD& Help: alglatadd(al,lat1,lat2,{&ptinter}): the sum of the lattices lat1 and lat2. If ptinter is present, set it to the intersection of the lattices. Doc: Given an algebra \var{al} and two lattices \var{lat1} and \var{lat2} in~\var{al}, computes the sum~$lat1 + lat2$. If \var{ptinter} is present, set it to the intersection~$lat1 \cap lat2$. \bprog ? al = alginit(nfinit(y^2+7), [-1,-1]); ? lat1 = alglathnf(al,[1,1,0,0,0,0,0,0]~); ? lat2 = alglathnf(al,[1,0,1,0,0,0,0,0]~); ? latsum = alglatadd(al,lat1,lat2,&latinter); ? matdet(latsum[1]) %5 = 4 ? matdet(latinter[1]) %6 = 64 @eprog pari-2.17.2/src/functions/algebras/alglatcontains0000644000175000017500000000121214567450071020476 0ustar billbillFunction: alglatcontains Section: algebras C-Name: alglatcontains Prototype: iGGGD& Help: alglatcontains(al,lat,x,{&ptc}): tests whether the lattice lat contains the element x. If ptc is present, sets it to the coordinates of x on the basis of lat. Doc: Given an algebra \var{al}, a lattice \var{lat} and \var{x} in~\var{al}, tests whether~$x\in lat$. If~\var{ptc} is present, sets it to the~\typ{COL} of coordinates of~$x$ in the basis of~\var{lat}. \bprog ? al = alginit(nfinit(y^2+7), [-1,-1]); ? a1 = [1,-1,0,1,2,0,1,2]~; ? lat1 = alglathnf(al,a1); ? alglatcontains(al,lat1,a1,&c) %4 = 1 ? c %5 = [-1, -2, -1, 1, 2, 0, 1, 1]~ @eprog pari-2.17.2/src/functions/algebras/alginit0000644000175000017500000001625714760123736017141 0ustar billbillFunction: alginit Section: algebras C-Name: alginit Prototype: GGDnD3,L, Help: alginit(B,C,{v},{flag=3}): initializes the central simple algebra defined by data B, C. Binary digits of the flag mean 1: compute a maximal order; 2: fully factor the discriminant instead of using a lazy factorisation. Doc: initializes the central simple algebra defined by data $B$, $C$ and variable $v$, as follows. \item (multiplication table) $B$ is the base number field $K$ in \tet{nfinit} form, $C$ is a ``multiplication table'' over $K$. As a $K$-vector space, the algebra is generated by a basis $(e_{1} = 1,\dots, e_{n})$; the table is given as a \typ{VEC} of $n$ matrices in $M_{n}(K)$, giving the left multiplication by the basis elements~$e_{i}$, in the given basis. Assumes that $e_{1}= 1$, that the multiplication table is integral, and that $(\bigoplus_{i=1}^{n}K e_{i},C)$ describes a central simple algebra over $K$. \bprog { mi = [0,-1,0, 0; 1, 0,0, 0; 0, 0,0,-1; 0, 0,1, 0]; mj = [0, 0,-1,0; 0, 0, 0,1; 1, 0, 0,0; 0,-1, 0,0]; mk = [0, 0, 0, -1; 0, 0,-1, 0; 0, 1, 0, 0; 1, 0, 0, 0]; A = alginit(nfinit(y), [matid(4), mi,mj,mk], , 0); } @eprog represents (in a complicated way) the quaternion algebra $(-1,-1)_{\Q}$. See below for a simpler solution. \item (cyclic algebra) $B$ is an \kbd{rnf} structure attached to a cyclic number field extension $L/K$ of degree $d$, $C$ is a \typ{VEC} \kbd{[sigma,b]} with 2 components: \kbd{sigma} is a \typ{POLMOD} representing an automorphism generating $\text{Gal}(L/K)$, $b$ is an element in $K^{*}$. This represents the cyclic algebra~$(L/K,\sigma,b)$. Currently the element $b$ has to be integral. \bprog ? Q = nfinit(y); T = polcyclo(5, 'x); F = rnfinit(Q, T); ? A = alginit(F, [Mod(x^2,T), 3]); @eprog defines the cyclic algebra $(L/\Q, \sigma, 3)$, where $L = \Q(\zeta_{5})$ and $\sigma:\zeta\mapsto\zeta^{2}$ generates $\text{Gal}(L/\Q)$. \item (quaternion algebra, special case of the above) $B$ is an \kbd{nf} structure attached to a number field $K$, $C = [a,b]$ is a vector containing two elements of $K^{*}$ with $a$ not a square in $K$, returns the quaternion algebra $(a,b)_{K}$. The variable $v$ (\kbd{'x} by default) must have higher priority than the variable of $K$\kbd{.pol} and is used to represent elements in the splitting field $L = K[x]/(x^{2}-a)$. \bprog ? Q = nfinit(y); A = alginit(Q, [-1,-1]); \\@com $(-1,-1)_{\Q}$ @eprog \item (algebra/$K$ defined by local Hasse invariants) $B$ is an \kbd{nf} structure attached to a number field $K$, $C = [d, [\kbd{PR},h_{f}], h_{i}]$ is a triple containing an integer $d > 1$, a pair $[\kbd{PR}, h_{f}]$ describing the Hasse invariants at finite places, and $h_{i}$ the Hasse invariants at archimedean (real) places. A local Hasse invariant belongs to $(1/d)\Z/\Z \subset \Q/\Z$, and is given either as a \typ{FRAC} (lift to $(1/d)\Z$), a \typ{INT} or \typ{INTMOD} modulo $d$ (lift to $\Z/d\Z$); a whole vector of local invariants can also be given as a \typ{VECSMALL}, whose entries are handled as \typ{INT}s. \kbd{PR} is a list of prime ideals (\kbd{prid} structures), and $h_{f}$ is a vector of the same length giving the local invariants at those maximal ideals. The invariants at infinite real places are indexed by the real roots $K$\kbd{.roots}: if the Archimedean place $v$ is attached to the $j$-th root, the value of $h_{v}$ is given by $h_{i}[j]$, must be $0$ or $1/2$ (or~$d/2$ modulo~$d$), and can be nonzero only if~$d$ is even. By class field theory, provided the local invariants $h_{v}$ sum to $0$, up to Brauer equivalence, there is a unique central simple algebra over $K$ with given local invariants and trivial invariant elsewhere. In particular, up to isomorphism, there is a unique such algebra $A$ of degree $d$. We realize $A$ as a cyclic algebra through class field theory. The variable $v$ (\kbd{'x} by default) must have higher priority than the variable of $K$\kbd{.pol} and is used to represent elements in the (cyclic) splitting field extension $L/K$ for $A$. \bprog ? nf = nfinit(y^2+1); ? PR = idealprimedec(nf,5); #PR %2 = 2 ? hi = []; ? hf = [PR, [1/3,-1/3]]; ? A = alginit(nf, [3,hf,hi]); ? algsplittingfield(A).pol %6 = x^3 - 21*x + 7 @eprog \item (matrix algebra, toy example) $B$ is an \kbd{nf} structure attached to a number field $K$, $C = d$ is a positive integer. Returns a cyclic algebra isomorphic to the matrix algebra $M_{d}(K)$. \item (algebras over~$\R$) If $B$ is a \typ{REAL} and $C = 1/2$, returns a structure representing the Hamilton quaternion algebra~${\bf H} = (-1,-1)_{\R}$. If $B$ is a \typ{REAL} and $C = 0$, returns an algebra structure representing~$\R$. If $B$ is a \typ{COMPLEX} and $C = 0$, returns an algebra structure representing~$\C$. In all cases over a number field, this function factors various discriminants and computes a maximal order for the algebra by default, which may require a lot of time. This can be controlled by $\fl$, whose binary digits mean: \item $1$: compute a maximal order. \item $2$: fully factor the discriminants instead of using a lazy factorisation. If this digit of $\fl$ is set to~$0$, the local Hasse invariants are not computed. If only a partial factorisation is known, the computed order is only guaranteed to be maximal at the known prime factors. The pari object representing such an algebra $A$ is a \typ{VEC} with the following data: \item A splitting field $L$ of $A$ of the same degree over $K$ as $A$, in \kbd{rnfinit} format, accessed with \kbd{algsplittingfield}. \item The Hasse invariants at the real places of $K$, accessed with \kbd{alghassei}. \item The Hasse invariants of $A$ at the finite primes of $K$ that ramify in the natural order of $A$, accessed with \kbd{alghassef}. \item A basis of an order ${\cal O}_{0}$ expressed on the basis of the natural order, accessed with \kbd{algbasis}. \item A basis of the natural order expressed on the basis of ${\cal O}_{0}$, accessed with \kbd{alginvbasis}. \item The left multiplication table of ${\cal O}_{0}$ on the previous basis, accessed with \kbd{algmultable}. \item The characteristic of $A$ (always $0$), accessed with \kbd{algchar}. \item The absolute traces of the elements of the basis of ${\cal O}_{0}$. \item If $A$ was constructed as a cyclic algebra~$(L/K,\sigma,b)$ of degree $d$, a \typ{VEC} $[\sigma,\sigma^{2},\dots,\sigma^{d-1}]$. The function \kbd{algaut} returns $\sigma$. \item If $A$ was constructed as a cyclic algebra~$(L/K,\sigma,b)$, the element $b$, accessed with \kbd{algb}. \item If $A$ was constructed with its multiplication table $mt$ over $K$, the \typ{VEC} of \typ{MAT} $mt$, accessed with \kbd{algrelmultable}. \item If $A$ was constructed with its multiplication table $mt$ over $K$, a \typ{VEC} with three components: a \typ{COL} representing an element of $A$ generating the splitting field $L$ as a maximal subfield of $A$, a \typ{MAT} representing an $L$-basis ${\cal B}$ of $A$ expressed on the $\Z$-basis of ${\cal O}_{0}$, and a \typ{MAT} representing the $\Z$-basis of ${\cal O}_{0}$ expressed on ${\cal B}$. This data is accessed with \kbd{algsplittingdata}. pari-2.17.2/src/functions/algebras/algrandom0000644000175000017500000000126014676526175017454 0ustar billbillFunction: algrandom Section: algebras C-Name: algrandom Prototype: DGG Help: algrandom({al},b): random element in al (Hamilton quaternions if omitted) with coefficients in [-b,b]. Doc: Given an algebra \var{al} and a nonnegative integer \var{b}, returns a random element in \var{al} with coefficients in~$[-b,b]$. \bprog ? al = alginit(nfinit(y),[-1,-1]); ? algrandom(al,3) % = [2, 0, 3, -1]~ @eprog If~\var{al} is an algebra over $\R$ (Hamilton quaternions if omitted) and \var{b} is a positive \typ{REAL}, returns a random element of~\var{al} with coefficients in~$[-b,b]$. \bprog ? algrandom(,1.) % = [-0.1806334680, -0.2810504190, 0.5011479961, 0.9498643737]~ @eprog pari-2.17.2/src/functions/algebras/algdim0000644000175000017500000000120214676526175016741 0ustar billbillFunction: algdim Section: algebras C-Name: algdim Prototype: lGD0,L, Help: algdim(al,{abs=0}): dimension of the algebra al. Doc: If \var{al} is a table algebra output by \tet{algtableinit} or if~$abs=1$, returns the dimension of \var{al} over its prime subfield ($\Q$ or $\F_{p}$) or over $\R$ for real algebras. If~\var{al} is a central simple algebra output by \tet{alginit} and~$abs=0$, returns the dimension of \var{al} over its center. \bprog ? nf = nfinit(y^3-y+1); ? A = alginit(nf, [-1,-1]); ? algdim(A) %3 = 4 ? algdim(A,1) %4 = 12 ? C = alginit(I,0); \\ complex numbers as a real algebra ? algdim(C,1) %6 = 2 @eprog pari-2.17.2/src/functions/algebras/algissimple0000644000175000017500000000177114676526175020030 0ustar billbillFunction: algissimple Section: algebras C-Name: algissimple Prototype: iGD0,L, Help: algissimple(al,{ss=0}): test whether the algebra al is simple. Doc: \var{al} being a table algebra output by \tet{algtableinit} or a central simple algebra output by \tet{alginit}, tests whether the algebra \var{al} is simple. If $\var{ss}=1$, assumes that the algebra~\var{al} is semisimple without testing it. \bprog ? mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]]; ? A = algtableinit(mt); \\ matrices [*,*; 0,*] ? algissimple(A) %3 = 0 ? algissimple(A,1) \\ incorrectly assume that A is semisimple %4 = 1 ? m_i=[0,-1,0,0;1,0,0,0;0,0,0,-1;0,0,1,0]; ? m_j=[0,0,-1,0;0,0,0,1;1,0,0,0;0,-1,0,0]; ? m_k=[0,0,0,-1;0,0,b,0;0,1,0,0;1,0,0,0]; ? mt = [matid(4), m_i, m_j, m_k]; ? A = algtableinit(mt); \\ quaternion algebra (-1,-1) ? algissimple(A) %10 = 1 ? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]]; ? A = algtableinit(mt,2); \\ direct product F_4 x F_2 ? algissimple(A) %13 = 0 @eprog pari-2.17.2/src/functions/algebras/algpow0000644000175000017500000000107114676526175017001 0ustar billbillFunction: algpow Section: algebras C-Name: algpow Prototype: DGGG Help: algpow({al},x,n): element x^n in al (Hamilton quaternions if omitted). Doc: Given an element $x$ in \var{al} (Hamilton quaternions if omitted) and an integer $n$, computes the power $x^{n}$ in the algebra \var{al}. \bprog ? A = alginit(nfinit(y), [-1,-1]); ? algpow(A,[1,1,0,0]~,7) %2 = [8, -8, 0, 0]~ ? algpow(,[1,2,3,sqrt(3)]~,-3) \\ Hamilton quaternions % = [-0.0095664563, 0.0052920822, 0.0079381233, 0.0045830776]~ @eprog Also accepts a square matrix with coefficients in \var{al}. pari-2.17.2/src/functions/algebras/algmultable0000644000175000017500000000173714676526175020012 0ustar billbillFunction: algmultable Section: algebras C-Name: algmultable Prototype: mG Help: algmultable(al): multiplication table of al over its prime subfield. Doc: returns a multiplication table of \var{al} over its prime subfield ($\Q$ or $\F_{p}$) or over~$\R$ for real algebras, as a \typ{VEC} of \typ{MAT}: the left multiplication tables of basis elements. If \var{al} was output by \tet{algtableinit}, returns the multiplication table used to define \var{al}. If \var{al} was output by \tet{alginit}, returns the multiplication table of the order~${\cal O}_{0}$ stored in \var{al}. \bprog ? A = alginit(nfinit(y), [-1,-1]); ? M = algmultable(A); ? #M %3 = 4 ? M[1] \\ multiplication by e_1 = 1 %4 = [1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1] ? M[2] %5 = [0 -1 1 0] [1 0 1 1] [0 0 1 1] [0 0 -2 -1] ? H = alginit(1.,1/2); \\ Hamilton quaternions ? algmultable(H)[3] \\ multiplication by j %7 = [0 0 -1 0] [0 0 0 1] [1 0 0 0] [0 -1 0 0] @eprog pari-2.17.2/src/functions/algebras/alghassei0000644000175000017500000000104514676526175017451 0ustar billbillFunction: alghassei Section: algebras C-Name: alghassei Prototype: mG Help: alghassei(al): the hasse invariant of the central simple algebra al at infinite places. Doc: Given a central simple algebra \var{al} output by \tet{alginit}, returns a \typ{VECSMALL} $h_{i}$ of $r_{1}$ integers modulo the degree $d$ of \var{al}, where $r_{1}$ is the number of real places of the center: the local Hasse invariants of \var{al} at infinite places. \bprog ? nf = nfinit(y^2-5); ? A = alginit(nf, [-1,y]); ? alghassei(A) %3 = Vecsmall([1, 0]) @eprog pari-2.17.2/src/functions/algebras/alghassef0000644000175000017500000000144614676526175017453 0ustar billbillFunction: alghassef Section: algebras C-Name: alghassef Prototype: mG Help: alghassef(al): the hasse invariant of the central simple algebra al at finite places. Doc: Given a central simple algebra \var{al} output by \tet{alginit}, returns a \typ{VEC} $[\kbd{PR}, h_{f}]$ describing the local Hasse invariants at the finite places of the center: \kbd{PR} is a \typ{VEC} of primes and $h_{f}$ is a \typ{VECSMALL} of integers modulo the degree $d$ of \var{al}. The Hasse invariant of~\var{al} at the primes outside~\kbd{PR} is~$0$, but~\kbd{PR} can include primes at which the Hasse invariant is~$0$. \bprog ? nf = nfinit(y^2-5); ? A = alginit(nf, [-1,2*y-1]); ? [PR,hf] = alghassef(A); ? PR %4 = [[19, [10, 2]~, 1, 1, [-8, 2; 2, -10]], [2, [2, 0]~, 1, 2, 1]] ? hf %5 = Vecsmall([1, 0]) @eprog pari-2.17.2/src/functions/algebras/algisdivl0000644000175000017500000000123314676526175017466 0ustar billbillFunction: algisdivl Section: algebras C-Name: algisdivl Prototype: iDGGGD& Help: algisdivl({al},x,y,{&z}): tests whether y is left divisible by x and sets z to the left quotient x\y. Doc: Given two elements $x$ and $y$ in \var{al} (Hamilton quaternions if omitted), tests whether $y$ is left divisible by $x$, that is whether there exists~$z$ in \var{al} such that~$xz=y$, and sets $z$ to this element if it exists. \bprog ? A = alginit(nfinit(y), [-1,1]); ? algisdivl(A,[x+2,-x-2]~,[x,1]~) %2 = 0 ? algisdivl(A,[x+2,-x-2]~,[-x,x]~,&z) %3 = 1 ? z %4 = [Mod(-2/5*x - 1/5, x^2 + 1), 0]~ @eprog Also accepts square matrices with coefficients in \var{al}. pari-2.17.2/src/functions/algebras/algramifiedplaces0000644000175000017500000000120014676526175021136 0ustar billbillFunction: algramifiedplaces Section: algebras C-Name: algramifiedplaces Prototype: G Help: algramifiedplaces(al): vector of the places of the center of al that ramify in al. Each place is described as an integer between 1 and r1 or as a prime ideal. Doc: Given a central simple algebra \var{al} output by \tet{alginit}, returns a \typ{VEC} containing the list of places of the center of \var{al} that are ramified in \var{al}. Each place is described as an integer between~$1$ and~$r_{1}$ or as a prime ideal. \bprog ? nf = nfinit(y^2-5); ? A = alginit(nf, [-1,y]); ? algramifiedplaces(A) %3 = [1, [2, [2, 0]~, 1, 2, 1]] @eprog pari-2.17.2/src/functions/algebras/algchar0000644000175000017500000000056314567450071017104 0ustar billbillFunction: algchar Section: algebras C-Name: algchar Prototype: mG Help: algchar(al): characteristic of the algebra al. Doc: Given an algebra \var{al} output by \tet{alginit} or \tet{algtableinit}, returns the characteristic of \var{al}. \bprog ? mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]]; ? A = algtableinit(mt,13); ? algchar(A) %3 = 13 @eprog pari-2.17.2/src/functions/algebras/algisramified0000644000175000017500000000176314760123736020306 0ustar billbillFunction: algisramified Section: algebras C-Name: algisramified Prototype: iGDG Help: algisramified(al,{pl}): tests whether the central simple algebra al is ramified, i.e. not isomorphic to a matrix ring over its center. If pl is set, it should be a prime ideal of the center or an integer between 1 and r1+r2, and in that case tests whether al is locally ramified at the place pl instead. Doc: Given a central simple algebra \var{al} output by \tet{alginit}, tests whether \var{al} is ramified, i.e. not isomorphic to a matrix algebra over its center. If \var{pl} is set, it should be a prime ideal of~$K$ or an integer between~$1$ and~$r_{1}+r_{2}$, and in that case tests whether \var{al} is locally ramified at the place \var{pl} instead. \bprog ? nf = nfinit(y^2-5); ? A = alginit(nf, [-1,y]); ? algisramified(A, 1) %3 = 1 ? algisramified(A, 2) %4 = 0 ? algisramified(A, idealprimedec(nf,2)[1]) %5 = 1 ? algisramified(A, idealprimedec(nf,5)[1]) %6 = 0 ? algisramified(A) %7 = 1 @eprog pari-2.17.2/src/functions/algebras/alginv0000644000175000017500000000107514676526175016774 0ustar billbillFunction: alginv Section: algebras C-Name: alginv Prototype: DGG Help: alginv({al},x): element 1/x in al (Hamilton quaternions if omitted). Doc: Given an element $x$ in \var{al} (Hamilton quaternions if omitted), computes its inverse $x^{-1}$ in the algebra \var{al}. Assumes that $x$ is invertible. \bprog ? A = alginit(nfinit(y), [-1,-1]); ? alginv(A,[1,1,0,0]~) %2 = [1/2, 1/2, 0, 0]~ ? alginv(,[1,0,Pi,sqrt(2)]~) \\ Hamilton quaternions %3 = [0.0777024661, 0, -0.2441094967, -0.1098878814]~ @eprog Also accepts square matrices with coefficients in \var{al}. pari-2.17.2/src/functions/algebras/algsqr0000644000175000017500000000077214676526175017010 0ustar billbillFunction: algsqr Section: algebras C-Name: algsqr Prototype: DGG Help: algsqr({al},x): element x^2 in al (Hamilton quaternions if omitted). Doc: Given an element $x$ in \var{al} (Hamilton quaternions if omitted), computes its square $x^{2}$ in the algebra \var{al}. \bprog ? A = alginit(nfinit(y), [-1,-1]); ? algsqr(A,[1,0,2,0]~) %2 = [-3, 0, 4, 0]~ ? algsqr(,[0,0,0,Pi]~) \\ Hamilton quaternions %3 = [-9.8696044010, 0, 0, 0]~ @eprog Also accepts a square matrix with coefficients in \var{al}. pari-2.17.2/src/functions/algebras/algbasistoalg0000644000175000017500000000117514567450071020317 0ustar billbillFunction: algbasistoalg Section: algebras C-Name: algbasistoalg Prototype: GG Help: algbasistoalg(al,x): transforms the column vector x on the integral basis of al into an element of al in algebraic form. Doc: Given an element \var{x} in the central simple algebra \var{al} output by \tet{alginit}, transforms it to its algebraic representation in \var{al}. This is the inverse function of \tet{algalgtobasis}. \bprog ? A = alginit(nfinit(y^2-5),[2,y]); ? z = algbasistoalg(A,[0,1,0,0,2,-3,0,0]~); ? liftall(z) %3 = [(-1/2*y - 2)*x + (-1/4*y + 5/4), -3/4*y + 7/4]~ ? algalgtobasis(A,z) %4 = [0, 1, 0, 0, 2, -3, 0, 0]~ @eprog pari-2.17.2/src/functions/algebras/alggroup0000644000175000017500000000121414676526175017327 0ustar billbillFunction: alggroup Section: algebras C-Name: alggroup Prototype: GDG Help: alggroup(gal,{p=0}): constructs the group algebra of gal over Q (resp. Fp). Doc: initializes the group algebra~$K[G]$ over~$K=\Q$ ($p$ omitted) or~$\F_{p}$ where~$G$ is the underlying group of the \kbd{galoisinit} structure~\var{gal}. The input~\var{gal} is also allowed to be a \typ{VEC} of permutations that is closed under products. Example: \bprog ? K = nfsplitting(x^3-x+1); ? gal = galoisinit(K); ? al = alggroup(gal); ? algissemisimple(al) %4 = 1 ? G = [Vecsmall([1,2,3]), Vecsmall([1,3,2])]; ? al2 = alggroup(G, 2); ? algissemisimple(al2) %8 = 0 @eprog pari-2.17.2/src/functions/algebras/algsplittingdata0000644000175000017500000000255614567450071021042 0ustar billbillFunction: algsplittingdata Section: algebras C-Name: algsplittingdata Prototype: mG Help: algsplittingdata(al): data stored in the central simple algebra al to compute a splitting of al over an extension. Doc: Given a central simple algebra \var{al} output by \tet{alginit} defined by a multiplication table over its center~$K$ (a number field), returns data stored to compute a splitting of \var{al} over an extension. This data is a \typ{VEC} \kbd{[t,Lbas,Lbasinv]} with $3$ components: \item an element $t$ of \var{al} such that $L=K(t)$ is a maximal subfield of \var{al}; \item a matrix \kbd{Lbas} expressing a $L$-basis of \var{al} (given an $L$-vector space structure by multiplication on the right) on the integral basis of \var{al}; \item a matrix \kbd{Lbasinv} expressing the integral basis of \var{al} on the previous $L$-basis. \bprog ? nf = nfinit(y^3-5); a = y; b = y^2; ? {m_i = [0,a,0,0; 1,0,0,0; 0,0,0,a; 0,0,1,0];} ? {m_j = [0, 0,b, 0; 0, 0,0,-b; 1, 0,0, 0; 0,-1,0, 0];} ? {m_k = [0, 0,0,-a*b; 0, 0,b, 0; 0,-a,0, 0; 1, 0,0, 0];} ? mt = [matid(4), m_i, m_j, m_k]; ? A = alginit(nf,mt,'x); ? [t,Lb,Lbi] = algsplittingdata(A); ? t %8 = [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]~; ? matsize(Lb) %9 = [12, 2] ? matsize(Lbi) %10 = [2, 12] @eprog pari-2.17.2/src/functions/algebras/algsplit0000644000175000017500000000345414676526175017336 0ustar billbillFunction: algsplit Section: algebras C-Name: algsplit Prototype: GDn Help: algsplit(al,{v='x}): computes an isomorphism between al and M_d(F_q). Doc: If \var{al} is a table algebra over~$\F_{p}$ output by \tet{algtableinit} that represents a simple algebra, computes an isomorphism between \var{al} and a matrix algebra~$M_{d}(\F_{p^{n}})$ where~$N = nd^{2}$ is the dimension of~\var{al}. Returns a \typ{VEC}~$[map,mapi]$, where: \item \var{map} is a \typ{VEC} of~$N$ matrices of size~$d\times d$ with \typ{FFELT} coefficients using the variable~\var{v}, representing the image of the basis of~\var{al} under the isomorphism. \item \var{mapi} is an~$N\times N$ matrix with \typ{INT} coefficients, representing the image in \var{al} by the inverse isomorphism of the basis~$(b_{i})$ of~$M_{d}(\F_{p}[\alpha])$ (where~$\alpha$ has degree~$n$ over~$\F_{p}$) defined as follows: let~$E_{i,j}$ be the matrix having all coefficients~$0$ except the~$(i,j)$-th coefficient equal to~$1$, and define $$b_{i_{3}+n(i_{2}+di_{1})+1} = E_{i_{1}+1,i_{2}+1} \alpha^{i_{3}},$$ where~$0\le i_{1},i_{2} \kbd{factorlimit}$ have a certain property (the equation order is $p$-maximal). This is never done by default, and must be explicitly set by the user of such functions. Nevertheless, these functions now provide a more flexible interface, and their use of the global default \kbd{factorlimit} is deprecated. \misctitle{Deprecated feature} \kbd{factor(N, 0)} is used to partially factor integers by removing all prime factors $\leq$ \kbd{factorlimit}. Don't use this, supply an explicit bound: \kbd{factor(N, bound)}, which avoids relying on an unpredictable global variable. The default value is $2^{20} = 1048576$. pari-2.17.2/src/functions/default/strictargs0000644000175000017500000000150014567450071017524 0ustar billbillFunction: _def_strictargs Class: default Section: default C-Name: sd_strictargs Prototype: Help: Doc: this toggle is either 1 (on) or 0 (off). If on, all arguments to \emph{new} user functions are mandatory unless the function supplies an explicit default value. Otherwise arguments have the default value $0$. In this example, \bprog fun(a,b=2)=a+b @eprog \kbd{a} is mandatory, while \kbd{b} is optional. If \kbd{strictargs} is on: \bprog ? fun() *** at top-level: fun() *** ^----- *** in function fun: a,b=2 *** ^----- *** missing mandatory argument 'a' in user function. @eprog This applies to functions defined while \kbd{strictargs} is on. Changing \kbd{strictargs} does not affect the behavior of previously defined functions. The default value is \kbd{0}. pari-2.17.2/src/functions/default/echo0000644000175000017500000000124114567450071016257 0ustar billbillFunction: _def_echo Class: default Section: default C-Name: sd_echo Prototype: Help: Doc: this default can be 0 (off), 1 (on) or 2 (on, raw). 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}). When \kbd{echo} is set to 1 the input is cleaned up, removing white space and comments and uniting multi-line input. When set to 2 (raw), the input is written as-is, without any pre-processing. The default value is \kbd{0} (no echo). pari-2.17.2/src/functions/default/prompt_cont0000644000175000017500000000053314567450071017710 0ustar billbillFunction: _def_prompt_cont Class: default Section: default C-Name: sd_prompt_cont Prototype: Help: Doc: a string that will be printed to prompt for continuation lines (e.g. in between braces, or after a line-terminating backslash). Everything that applies to \kbd{prompt} applies to \kbd{prompt\_cont} as well. The default value is \kbd{""}. pari-2.17.2/src/functions/default/threadsize0000644000175000017500000000220414676526175017515 0ustar billbillFunction: _def_threadsize Class: default Section: default C-Name: sd_threadsize Prototype: Help: Doc: This default is specific to the \emph{parallel} version of PARI and gp (built via \kbd{Configure --mt=pthread} or \kbd{mpi}) and is ignored otherwise. In parallel mode, each thread allocates its own private \tev{stack} for its computations, see \kbd{parisize}. This value determines the size in bytes of the stacks of each thread, so the total memory allocated will be $\kbd{parisize}+\kbd{nbthreads}\times\kbd{threadsize}$. If set to $0$, the value used is the same as \kbd{parisize}. It is not easy to estimate reliably a sufficient value for this parameter because PARI itself will parallelize computations and we recommend to not set this value explicitly unless it solves a specific problem for you. For instance if you see frequent messages of the form \bprog *** Warning: not enough memory, new thread stack 10000002048 @eprog (Meaning that \kbd{threadsize} had to be temporarily increased.) On the other hand we strongly recommend to set \kbd{parisizemax} and \kbd{threadsizemax} to a nonzero value. The default value is $0$. pari-2.17.2/src/functions/default/graphcolormap0000644000175000017500000000310114676526175020206 0ustar billbillFunction: _def_graphcolormap Class: 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 color names, 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 or a \kbd{\#} followed by 6 hexadecimal digits. For instance \kbd{[250, 235, 215]}, \kbd{"\#faebd7"} and \kbd{"antiquewhite"} all represent the same color. The default value is [\kbd{"white"}, \kbd{"black"}, \kbd{"blue"}, \kbd{"violetred"}, \kbd{"red"}, \kbd{"green"}, \kbd{"grey"}, \kbd{"gainsboro"}]. The colormap elements can not be changed individually as in a vector (you must either leave the colormap alone or change it globally). All color functions allow you either to hardcode a color given its descriptive name or RGB code, or to use a relative color scheme by changing the colormap and referring to an index in that table: for historical and compatibility reasons, the indexing is $0$-based (as in C) and not $1$-based as would be expected in a GP vector. This means that the index~$0$ in the default colormap represents \kbd{"white"}, $1$ is \kbd{"black"}, and so on. pari-2.17.2/src/functions/default/debugmem0000644000175000017500000000170714567450071017135 0ustar billbillFunction: _def_debugmem Class: default Section: default C-Name: sd_debugmem Prototype: Help: Doc: memory debugging level (see \b{gm}). If this is nonzero, \kbd{gp} will print increasingly precise notifications about memory use: \item $\kbd{debugmem} > 0$, notify when \kbd{parisize} changes (within the boundaries set by \kbd{parisizemax}); \item $\kbd{debugmem} > 1$, indicate any important garbage collection and the function it is taking place in; \item $\kbd{debugmem} > 2$, indicate the creation/destruction of ``blocks'' (or clones); expect lots of messages. \noindent {\bf Important Note:} if you are running a version compiled for debugging (see Appendix~A) and $\kbd{debugmem} > 1$, \kbd{gp} will further regularly print information on memory usage, notifying whenever stack usage goes up or down by 1 MByte. This functionality is disabled on non-debugging builds as it noticeably slows down the performance. The default value is \kbd{1}. pari-2.17.2/src/functions/default/simplify0000644000175000017500000000154413637407207017203 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.17.2/src/functions/default/compatible0000644000175000017500000000024214567450071017460 0ustar billbillFunction: _def_compatible Class: default Section: default C-Name: sd_compatible Prototype: Help: Obsolete: 2014-10-11 Doc: Obsolete. This default is now a no-op. pari-2.17.2/src/functions/default/factor_add_primes0000644000175000017500000000141014567450071021004 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 prime factors that were difficult to find (larger than $2^{24}$), so they are automatically tried first in other factorizations. If a routine is performing (or has performed) a factorization and is interrupted by an error or via Control-C, this lets you recover the prime factors already found. The downside is that a huge \kbd{addprimes} table unrelated to the current computations will slow down arithmetic functions relying on integer factorization; one should then empty the table using \tet{removeprimes}. The default value is \kbd{0}. pari-2.17.2/src/functions/default/colors0000644000175000017500000000423314676526175016660 0ustar billbillFunction: _def_colors Class: default Section: default C-Name: sd_colors Prototype: Help: Doc: this default is only usable if \kbd{gp} is running within certain color-capable terminals. For instance \kbd{rxvt}, \kbd{color\_xterm} and modern versions of \kbd{xterm} under X Windows, or standard Linux/DOS text consoles. It causes \kbd{gp} to use a small palette of colors for its output. With xterms, the colormap used corresponds to the resources \kbd{Xterm*color$n$} where $n$ ranges from $0$ to $15$ (see the file \kbd{misc/color.dft} for an example). Accepted values for this default are strings \kbd{"$a_{1}$,\dots,$a_{k}$"} where $k\le7$ and each $a_{i}$ is either \noindent\item the keyword \kbd{no} (use the default color, usually black on transparent background) \noindent\item an integer between 0 and 15 corresponding to the aforementioned colormap \noindent\item a triple $[c_{0},c_{1},c_{2}]$ where $c_{0}$ stands for foreground color, $c_{1}$ for background color, and $c_{2}$ for attributes (0 is default, 1 is bold, 4 is underline). The output objects thus affected are respectively error messages, history numbers, prompt, input line, output, help messages, timer (that's seven of them). If $k < 7$, the remaining $a_{i}$ are assumed to be \kbd{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.17.2/src/functions/default/timer0000644000175000017500000000236114676526175016477 0ustar billbillFunction: _def_timer Class: default Section: default C-Name: sd_timer Prototype: Help: Doc: this toggle is either 1 (on) or 0 (off). Every instruction sequence in the gp calculator (anything ended by a newline in your input) is timed, to some accuracy depending on the hardware and operating system. When \tet{timer} is on, each such timing is printed immediately before the output as follows: \bprog ? factor(2^2^7+1) time = 108 ms. \\ this line omitted if 'timer' is 0 %1 = [ 59649589127497217 1] [5704689200685129054721 1] @eprog\noindent (See also \kbd{\#} and \kbd{\#\#}.) The time measured is the user \idx{CPU time}, not including the time for printing the results. If the time is negligible ($< 1$ ms.), nothing is printed: in particular, no timing should be printed when defining a user function or an alias, or installing a symbol from the library. If you are using a parallel version of \kbd{gp}, the output is more complex, such as \bprog ? isprime( 10^300 + 331 ) cpu time = 3,206 ms, real time = 1,289 ms. \\ omitted if 'timer' is 0 %1 = 1 @eprog\noindent Now, \kbd{real time} is the wallclock time, and \kbd{cpu time} is the sum of the CPU times spent by the different threads. The default value is \kbd{0} (off). pari-2.17.2/src/functions/default/factor_proven0000644000175000017500000000124014567450071020207 0ustar billbillFunction: _def_factor_proven Class: default Section: default C-Name: sd_factor_proven Prototype: Help: Doc: this toggle is either 1 (on) or 0 (off). By default, the factors output by the integer factorization machinery are only pseudo-primes, not proven primes. If this toggle is set, a primality proof is done for each factor and all results depending on integer factorization are fully proven. This flag does not affect partial factorization when it is explicitly requested. It also does not affect the private table managed by \tet{addprimes}: its entries are included as is in factorizations, without being tested for primality. The default value is \kbd{0}. pari-2.17.2/src/functions/default/recover0000644000175000017500000000046514567450071017015 0ustar billbillFunction: _def_recover Class: 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.17.2/src/functions/default/parisizemax0000644000175000017500000000230714567450071017701 0ustar billbillFunction: _def_parisizemax Class: default Section: default C-Name: sd_parisizemax Prototype: Help: Doc: \kbd{gp}, and in fact any program using the PARI library, needs a \tev{stack} in which to do its computations. If nonzero, \tet{parisizemax} is the maximum size the stack can grow to, in bytes. If zero, the stack will not automatically grow, and will be limited to the value of \kbd{parisize}. When \kbd{parisizemax} is set, PARI tries to fit its computations within about \kbd{parisize} bytes, but will increase the stack size if needed, roughly doubling it each time (up to \kbd{parisizemax} of course!) and printing a message such as \kbd{Warning: increasing stack size to} \var{some value}. Once the memory intensive computation is over, PARI will restore the stack size to the originally requested \kbd{parisize} without printing further messages. We \emph{strongly} recommend to set \tet{parisizemax} permanently to a large nonzero value in your \tet{gprc}, about what you believe your machine can stand. It is possible to increase or decrease \kbd{parisizemax} inside a running \kbd{gp} session, just use \kbd{default} as usual. The default value is $0$, for backward compatibility reasons. pari-2.17.2/src/functions/default/debugfiles0000644000175000017500000000052314567450071017454 0ustar billbillFunction: _def_debugfiles Class: default Section: default C-Name: sd_debugfiles Obsolete: 2021-06-14 Prototype: Help: Doc: This is a deprecated alias for \kbd{setdebug("io",)}. If nonzero, \kbd{gp} will print information on file descriptors in use and I/O operations (see~\b{gf}). The default value is \kbd{0} (no debugging messages). pari-2.17.2/src/functions/default/output0000644000175000017500000000257314567450071016712 0ustar billbillFunction: _def_output Class: default Section: default C-Name: sd_output Prototype: Help: Doc: there are three possible values: 0 (=~\var{raw}), 1 (=~\var{prettymatrix}), or 3 (=~\var{external} \var{prettyprint}). This means that, independently of the default \kbd{format} for reals which we explained above, you can print results in three ways: \item \tev{raw format}, i.e.~a format which is equivalent to what you input, including explicit multiplication signs, and everything typed on a line instead of two dimensional boxes. This can have several advantages, for instance it allows you to pick the result with a mouse or an editor, and to paste it somewhere else. \item \tev{prettymatrix format}: this is identical to raw format, except that matrices are printed as boxes instead of horizontally. This is prettier, but takes more space and cannot be used for input. Column vectors are still printed horizontally. \item \tev{external prettyprint}: pipes all \kbd{gp} output in TeX format to an external prettyprinter, according to the value of \tet{prettyprinter}. The default script (\tet{tex2mail}) converts its input to readable two-dimensional text. Independently of the setting of this default, an object can be printed in any of the three formats at any time using the commands \b{a} and \b{m} and \b{B} respectively. The default value is \kbd{1} (\var{prettymatrix}). pari-2.17.2/src/functions/default/log0000644000175000017500000000225114567450071016124 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}. \misctitle{Note} Logging starts as soon as \kbd{log} is set to a nonzero value. In particular, when \kbd{log} is set in \kbd{gprc}, warnings and errors triggered from the rest of the file will be written in the logfile. For instance, on clean startup, the logfile will start by \kbd{Done.} (from the \kbd{Reading GPRC:\dots Done.} diagnostic printed when starting \kbd{gp}), then the \kbd{gp} header and prompt. pari-2.17.2/src/functions/default/psfile0000644000175000017500000000035314567450071016626 0ustar billbillFunction: _def_psfile Class: default Section: default C-Name: sd_psfile Prototype: Obsolete: 2018-02-01 Help: Doc: This default is obsolete, use one of plotexport, plothexport or plothrawexport functions and write the result to file. pari-2.17.2/src/functions/default/path0000644000175000017500000000131013637407207016272 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.17.2/src/functions/default/secure0000644000175000017500000000071013637407207016627 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.17.2/src/functions/default/threadsizemax0000644000175000017500000000157214567450071020220 0ustar billbillFunction: _def_threadsizemax Class: default Section: default C-Name: sd_threadsizemax Prototype: Help: Doc: This default is specific to the \emph{parallel} version of PARI and gp (built via \kbd{Configure --mt=pthread} or \kbd{mpi}) and is ignored otherwise. In parallel mode, each threads allocates its own private \tev{stack} for its computations, see \kbd{parisize} and \kbd{parisizemax}. The values of \kbd{threadsize} and \kbd{threadsizemax} determine the usual and maximal size in bytes of the stacks of each thread, so the total memory allocated will be between $\kbd{parisize}+\kbd{nbthreads}\times\kbd{threadsize}$. and $\kbd{parisizemax}+\kbd{nbthreads}\times\kbd{threadsizemax}$. If set to $0$, the value used is the same as \kbd{threadsize}. We strongy recommend to set both \kbd{parisizemax} and \kbd{threadsizemax} to a nonzero value. The default value is $0$. pari-2.17.2/src/functions/default/readline0000644000175000017500000000066314567450071017133 0ustar billbillFunction: _def_readline Class: 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.17.2/src/functions/default/TeXstyle0000644000175000017500000000123114567450071017121 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. You \emph{must} then define \kbd{{\bs}PARIbreak} as follows: \bprog \def\PARIbreak{\hskip 0pt plus \hsize\relax\discretionary{}{}{}} @eprog The default value is \kbd{0}. pari-2.17.2/src/functions/default/help0000644000175000017500000000110514567450071016270 0ustar billbillFunction: _def_help Class: default Section: default C-Name: sd_help Prototype: Help: Doc: name of the external help program to use from within \kbd{gp} when extended help is invoked, usually through a \kbd{??} or \kbd{???} request (see \secref{se:exthelp}), or \kbd{M-H} under readline (see \secref{se:readline}). \misctitle{Windows-specific note} On Windows operating systems, if the first character of \kbd{help} is \kbd{@}, it is replaced by ``the directory where the \kbd{gp} binary is installed''. The default value is the path to the \kbd{gphelp} script we install. pari-2.17.2/src/functions/default/seriesprecision0000644000175000017500000000040113637407207020544 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.17.2/src/functions/default/prompt0000644000175000017500000000265114567450071016670 0ustar billbillFunction: _def_prompt Class: 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.17.2/src/functions/default/prettyprinter0000644000175000017500000000061313637407207020276 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.17.2/src/functions/default/parisize0000644000175000017500000000173314676526175017207 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 recommended to increase this default using a \tet{gprc}, to the value you believe PARI should be happy with, given your typical computation. We strongly recommend to also set \tet{parisizemax} to a much larger value in your \kbd{gprc}, about what you believe your machine can stand: PARI will then try to fit its computations within about \kbd{parisize} bytes, but will increase the stack size if needed (up to \kbd{parisizemax}). PARI will restore the stack size to the originally requested \kbd{parisize} once we get back to the user's prompt. If \tet{parisizemax} is unset, this command has a very unintuitive behaviour since it must abort pending operations, see \kbd{??allocatemem}. The default value is 8M. pari-2.17.2/src/functions/default/logfile0000644000175000017500000000037113637407207016765 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.17.2/src/functions/default/sopath0000644000175000017500000000147214557721031016641 0ustar billbillFunction: _def_sopath Class: default Section: default C-Name: sd_sopath Prototype: Help: Doc: this is a list of directories, separated by colons ':' (semicolons ';' in the DOS world, since colons are preempted for drive names). When asked to \tet{install} an external symbol from a shared library whose name is not given by an absolute path (does not start with \kbd{/}, \kbd{./} or \kbd{../}), \kbd{gp} will look for it in these directories, in the order they were written in \kbd{sopath}. Here, as usual, \kbd{.} means the current directory, and \kbd{..} its immediate parent. Environment expansion is performed. The default value is \kbd{""}, corresponding to an empty list of directories: \tet{install} will use the library name as input (and look in the current directory if the name is not an absolute path). pari-2.17.2/src/functions/default/histfile0000644000175000017500000000131114567450071017146 0ustar billbillFunction: _def_histfile Class: 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$>$}. Note that, by default, the number of history entries saved is not limited: set \kbd{history-size} in readline's \kbd{.inputrc} to limit the file size. The default value is \kbd{$<$undefined$>$} (no history file). pari-2.17.2/src/functions/modular_symbols/0000755000175000017500000000000014760315601017201 5ustar billbillpari-2.17.2/src/functions/modular_symbols/HEADER0000644000175000017500000000306114676526175020074 0ustar billbillFunction: _header_modular_symbols Class: header Section: modular_symbols Doc: \section{Modular symbols} Let $\Delta_{0} := \text{Div}^{0}(\P^{1}(\Q))$ be the abelian group of divisors of degree $0$ on the rational projective line. The standard $\text{GL}(2,\Q)$ action on $\P^{1}(\Q)$ via homographies naturally extends to $\Delta_{0}$. Given \item $G$ a finite index subgroup of $\text{SL}(2,\Z)$, \item a field $F$ and a finite dimensional representation $V/F$ of $\text{GL}(2,\Q)$, \noindent we consider the space of \emph{modular symbols} $M := \Hom_{G}(\Delta_{0}, V)$. This finite dimensional $F$-vector space is a $G$-module, canonically isomorphic to $H^{1}_{c}(X(G), V)$, and allows to compute modular forms for $G$. Currently, we only support the groups $\Gamma_{0}(N)$ ($N > 0$ an integer) and the representations $V_{k} = \Q[X,Y]_{k-2}$ ($k \geq 2$ an integer) over $\Q$. We represent a space of modular symbols by an \var{ms} structure, created by the function \tet{msinit}. It encodes basic data attached to the space: chosen $\Z[G]$-generators $(g_{i})$ for $\Delta_{0}$ (and relations among those) and an $F$-basis of $M$. A modular symbol $s$ is thus given either in terms of this fixed basis, or as a collection of values $s(g_{i})$ satisfying certain relations. A subspace of $M$ (e.g. the cuspidal or Eisenstein subspaces, the new or old modular symbols, etc.) is given by a structure allowing quick projection and restriction of linear operators; its first component is a matrix whose columns form an $F$-basis of the subspace. pari-2.17.2/src/functions/modular_symbols/mspadicmoments0000644000175000017500000000330414676526175022167 0ustar billbillFunction: mspadicmoments Section: modular_symbols C-Name: mspadicmoments Prototype: GGD1,L, Help: mspadicmoments(Mp,PHI,{D=1}): given Mp from mspadicinit, an overconvergent eigensymbol PHI, and optionally a fundamental discriminant D coprime to p, return the moments of the p-1 distributions PHI^D([0]-[oo]) | (a + pZp), 0 < a < p. To be used by mspadicL and mspadicseries. Doc: given \kbd{Mp} from \kbd{mspadicinit}, an overconvergent eigensymbol \kbd{PHI} from \kbd{mstooms} and a fundamental discriminant $D$ coprime to $p$, let $\kbd{PHI}^{D}$ denote the twisted symbol. This function computes the distribution $\mu = \kbd{PHI}^{D}([0] - \infty]) \mid \Z_{p}^{*}$ restricted to $\Z_{p}^{*}$. More precisely, it returns the moments of the $p-1$ distributions $\kbd{PHI}^{D}([0]-[\infty]) \mid (a + p\Z_{p})$, $0 < a < p$. We also allow \kbd{PHI} to be given as a classical symbol, which is then lifted to an overconvergent symbol by \kbd{mstooms}; but this is wasteful if more than one twist is later needed. The returned data $\mu$ ($p$-adic distributions attached to \kbd{PHI}) can then be used in \tet{mspadicL} or \tet{mspadicseries}. This precomputation allows to quickly compute derivatives of different orders or values at different characters. \bprog ? M = msinit(3,6, 1); ? phi = [5,-3,-1]~; ? msissymbol(M, phi) %3 = 1 ? p = 5; mshecke(M,p) * phi \\ eigenvector of T_5, a_5 = 6 %4 = [30, -18, -6]~ ? Mp = mspadicinit(M, p, 10, 0); \\ restrict to ordinary symbols, mod p^10 ? PHI = mstooms(Mp, phi); ? mu = mspadicmoments(Mp, PHI); ? mspadicL(mu) %8 = 5 + 2*5^2 + 2*5^3 + ... ? mu = mspadicmoments(Mp, PHI, 12); \\ twist by 12 ? mspadicL(mu) %10 = 5 + 5^2 + 5^3 + 2*5^4 + ... @eprog pari-2.17.2/src/functions/modular_symbols/msqexpansion0000644000175000017500000000277414676526175021703 0ustar billbillFunction: msqexpansion Section: modular_symbols C-Name: msqexpansion Prototype: GGDP Help: msqexpansion(M,projH,{B = seriesprecision}): M being a full modular symbol space, as given by msinit, and projH being a projector on a Hecke-simple subspace, return the Fourier coefficients [a_n, n <= B] of the corresponding normalized newform. If B omitted, use seriesprecision. Doc: $M$ being a full modular symbol space, as given by \kbd{msinit}, and \var{projH} being a projector on a Hecke-simple subspace (as given by \tet{mssplit}), return the Fourier coefficients $a_{n}$, $n\leq B$ of the corresponding normalized newform. If $B$ is omitted, use \kbd{seriesprecision}. This function uses a naive $O(B^{2} d^{3})$ algorithm, where $d = O(kN)$ is the dimension of $M_{k}(\Gamma_{0}(N))$. \bprog ? M = msinit(11,2, 1); \\ M_2(Gamma_0(11))^+ ? L = mssplit(M, msnew(M)); ? msqexpansion(M,L[1], 20) %3 = [1, -2, -1, 2, 1, 2, -2, 0, -2, -2, 1, -2, 4, 4, -1, -4, -2, 4, 0, 2] ? ellan(ellinit("11a1"), 20) %4 = [1, -2, -1, 2, 1, 2, -2, 0, -2, -2, 1, -2, 4, 4, -1, -4, -2, 4, 0, 2] @eprog\noindent The shortcut \kbd{msqexpansion(M, s, B)} is available for a symbol $s$, provided it is a Hecke eigenvector: \bprog ? E = ellinit("11a1"); ? [M,S] = msfromell(E); [sp,sm] = S; ? msqexpansion(M,sp,10) \\ in the + eigenspace %3 = [1, -2, -1, 2, 1, 2, -2, 0, -2, -2] ? msqexpansion(M,sm,10) \\ in the - eigenspace %4 = [1, -2, -1, 2, 1, 2, -2, 0, -2, -2] ? ellan(E, 10) %5 = [1, -2, -1, 2, 1, 2, -2, 0, -2, -2] @eprog pari-2.17.2/src/functions/modular_symbols/msinit0000644000175000017500000000333514676526175020453 0ustar billbillFunction: msinit Section: modular_symbols C-Name: msinit Prototype: GGD0,L, Help: msinit(G,V,{sign=0}): given G a finite index subgroup of SL(2,Z) and a finite dimensional representation V of GL(2,Q), creates a space of modular symbols, the G-module Hom_G(Div^0(P^1 Q), V). This is canonically isomorphic to H^1_c(X(G), V), and allows to compute modular forms for G. If sign is present and nonzero, it must be +1 or -1 and we consider the subspace defined by Ker (Sigma - sign), where Sigma is induced by [-1,0;0,1]. Currently the only supported groups are the Gamma_0(N), coded by the integer N. The only supported representation is V_k = Q[X,Y]_{k-2}, coded by the integer k >= 2. Doc: given $G$ a finite index subgroup of $\text{SL}(2,\Z)$ and a finite dimensional representation $V$ of $\text{GL}(2,\Q)$, creates a space of modular symbols, the $G$-module $\Hom_{G}(\text{Div}^{0}(\P^{1}(\Q)), V)$. This is canonically isomorphic to $H^{1}_{c}(X(G), V)$, and allows to compute modular forms for $G$. If \emph{sign} is present and nonzero, it must be $\pm1$ and we consider the subspace defined by $\text{Ker} (\sigma - \var{sign})$, where $\sigma$ is induced by \kbd{[-1,0;0,1]}. Currently the only supported groups are the $\Gamma_{0}(N)$, coded by the integer $N > 0$. The only supported representation is $V_{k} = \Q[X,Y]_{k-2}$, coded by the integer $k \geq 2$. \bprog ? M = msinit(11,2); msdim(M) \\ Gamma0(11), weight 2 %1 = 3 ? mshecke(M,2) \\ T_2 acting on M %2 = [3 1 1] [0 -2 0] [0 0 -2] ? msstar(M) \\ * involution %3 = [1 0 0] [0 0 1] [0 1 0] ? Mp = msinit(11,2, 1); msdim(Mp) \\ + part %4 = 2 ? mshecke(Mp,2) \\ T_2 action on M^+ %5 = [3 2] [0 -2] ? msstar(Mp) %6 = [1 0] [0 1] @eprog pari-2.17.2/src/functions/modular_symbols/msgetweight0000644000175000017500000000052214567450071021460 0ustar billbillFunction: msgetweight Section: modular_symbols C-Name: msgetweight Prototype: lG Help: msgetweight(M): M being a full modular symbol space, as given by msinit, return its weight k. Doc: $M$ being a full modular symbol space, as given by \kbd{msinit}, return its weight $k$. \bprog ? M = msinit(11,4); ? msgetweight(M) %2 = 4 @eprog pari-2.17.2/src/functions/modular_symbols/mseisenstein0000644000175000017500000000142214567450071021637 0ustar billbillFunction: mseisenstein Section: modular_symbols C-Name: mseisenstein Prototype: G Help: mseisenstein(M): M being a full modular symbol space, as given by msinit, return its Eisenstein subspace. Doc: $M$ being a full modular symbol space, as given by \kbd{msinit}, return its Eisenstein subspace. A subspace is given by a structure allowing quick projection and restriction of linear operators; its first component is a matrix with integer coefficients whose columns form a $\Q$-basis of the subspace. This is the same basis as given by the second component of \kbd{mscuspidal}$(M, 1)$. \bprog ? M = msinit(2,8, 1); \\ M_8(Gamma_0(2))^+ ? E = mseisenstein(M); ? E[1] \\ 2-dimensional %3 = [0 -10] [0 -15] [0 -3] [1 0] ? E == mscuspidal(M,1)[2] %4 = 1 @eprog pari-2.17.2/src/functions/modular_symbols/mstooms0000644000175000017500000000476614676526175020662 0ustar billbillFunction: mstooms Section: modular_symbols C-Name: mstooms Prototype: GG Help: mstooms(Mp,phi): given Mp from mspadicinit, lift the (classical) eigen symbol phi to a distribution-valued overconvergent symbol in the sense of Pollack and Stevens. The resulting overconvergent eigensymbol can then be used in mspadicmoments, then mspadicL or mspadicseries. Doc: given \kbd{Mp} from \kbd{mspadicinit}, lift the (classical) eigen symbol \kbd{phi} to a $p$-adic distribution-valued overconvergent symbol in the sense of Pollack and Stevens. More precisely, let $\phi$ belong to the space $W$ of modular symbols of level $N$, $v_{p}(N) \leq 1$, and weight $k$ which is an eigenvector for the Hecke operator $T_{N}(p)$ for a nonzero eigenvalue $a_{p}$ and let $N_{0} = \text{lcm}(N,p)$. Under the action of $T_{N_{0}}(p)$, $\phi$ generates a subspace $W_{\phi}$ of dimension $1$ (if $p\mid N$) or $2$ (if $p$ does not divide $N$) in the space of modular symbols of level $N_{0}$. Let $V_{p}=[p,0;0,1]$ and $C_{p}=[a_{p},p^{k-1};-1,0]$. When $p$ does not divide $N$ and $a_{p}$ is divisible by $p$, \kbd{mstooms} returns the lift $\Phi$ of $(\phi,\phi|_{k} V_{p})$ such that $$T_{N_{0}}(p) \Phi = C_{p} \Phi$$ When $p$ does not divide $N$ and $a_{p}$ is not divisible by $p$, \kbd{mstooms} returns the lift $\Phi$ of $\phi - \alpha^{-1} \phi|_{k} V_{p}$ which is an eigenvector of $T_{N_{0}}(p)$ for the unit eigenvalue where $\alpha^{2} - a_{p} \alpha + p^{k-1}=0$. The resulting overconvergent eigensymbol can then be used in \tet{mspadicmoments}, then \tet{mspadicL} or \tet{mspadicseries}. \bprog ? M = msinit(3,6, 1); p = 5; ? Tp = mshecke(M, p); factor(charpoly(Tp)) %2 = [x - 3126 2] [ x - 6 1] ? phi = matker(Tp - 6)[,1] \\ generator of p-Eigenspace, a_p = 6 %3 = [5, -3, -1]~ ? Mp = mspadicinit(M, p, 10, 0); \\ restrict to ordinary symbols, mod p^10 ? PHI = mstooms(Mp, phi); ? mu = mspadicmoments(Mp, PHI); ? mspadicL(mu) %7 = 5 + 2*5^2 + 2*5^3 + ... @eprog A non ordinary symbol. \bprog ? M = msinit(4,6,1); p = 3; ? Tp = mshecke(M, p); factor(charpoly(Tp)) %2 = [x - 244 3] [ x + 12 1] ? phi = matker(Tp + 12)[,1] \\ a_p = -12 is divisible by p = 3 %3 = [-1/32, -1/4, -1/32, 1]~ ? msissymbol(M,phi) %4 = 1 ? Mp = mspadicinit(M,3,5,0); ? PHI = mstooms(Mp,phi); *** at top-level: PHI=mstooms(Mp,phi) *** ^--------------- *** mstooms: incorrect type in mstooms [v_p(ap) > mspadicinit flag] (t_VEC). ? Mp = mspadicinit(M,3,5,1); ? PHI = mstooms(Mp,phi); @eprog pari-2.17.2/src/functions/modular_symbols/mscosets0000644000175000017500000000324514676526175021010 0ustar billbillFunction: mscosets Section: modular_symbols C-Name: mscosets0 Prototype: GG Help: mscosets(gen,inH): gen being a system of generators for a group G and H being a subgroup of finite index of G, return a list of right cosets of H \ G and the right action of G on H \ G. The subgroup H is given by a criterion inH (closure) deciding whether an element of G belongs to H. Doc: \kbd{gen} being a system of generators for a group $G$ and $H$ being a subgroup of finite index in $G$, return a list of right cosets of $H\backslash G$ and the right action of $G$ on $H\backslash G$. The subgroup $H$ is given by a criterion \kbd{inH} (closure) deciding whether an element of $G$ belongs to $H$. The group $G$ is restricted to types handled by generic multiplication (\kbd{*}) and inversion (\kbd{g\pow (-1)}), such as matrix groups or permutation groups. Let $\kbd{gens} = [g_{1}, \dots, g_{r}]$. The function returns $[C,M]$ where $C$ lists the $h = [G:H]$ representatives $[\gamma_{1}, \dots, \gamma_{h}]$ for the right cosets $H\gamma_{1},\dots,H\gamma_{h}$; $\gamma_{1}$ is always the neutral element in $G$. For all $i \leq h$, $j \leq r$, if $M[i][j] = k$ then $H \gamma_{i} g_{j} = H\gamma_{k}$. \bprog ? PSL2 = [[0,1;-1,0], [1,1;0,1]]; \\ S and T \\ G = PSL2, H = Gamma0(2) ? [C, M] = mscosets(PSL2, g->g[2,1] % 2 == 0); ? C \\ three cosets %3 = [[1, 0; 0, 1], [0, 1; -1, 0], [0, 1; -1, -1]] ? M %4 = [Vecsmall([2, 1]), Vecsmall([1, 3]), Vecsmall([3, 2])] @eprog\noindent Looking at $M[1]$ we see that $S$ belongs to the second coset and $T$ to the first (trivial) coset. Variant: Also available is the function \fun{GEN}{mscosets}{GEN G, void *E, long (*inH)(void *, GEN)} pari-2.17.2/src/functions/modular_symbols/msnew0000644000175000017500000000115714567450071020267 0ustar billbillFunction: msnew Section: modular_symbols C-Name: msnew Prototype: G Help: msnew(M): M being a full modular symbol space, as given by msinit, return its new cuspidal subspace. Doc: $M$ being a full modular symbol space, as given by \kbd{msinit}, return the \emph{new} part of its cuspidal subspace. A subspace is given by a structure allowing quick projection and restriction of linear operators; its first component is a matrix with integer coefficients whose columns form a $\Q$-basis of the subspace. \bprog ? M = msinit(11,8, 1); \\ M_8(Gamma_0(11))^+ ? N = msnew(M); ? #N[1] \\ 6-dimensional %3 = 6 @eprog pari-2.17.2/src/functions/modular_symbols/mspathgens0000644000175000017500000000407414676526175021322 0ustar billbillFunction: mspathgens Section: modular_symbols C-Name: mspathgens Prototype: G Help: mspathgens(M): M being a full modular symbol space, as given by msinit, return a set of Z[G]-generators for Div^0(P^1 Q). The output is [g,R], where g is a minimal system of generators and R the vector of Z[G]-relations between the given generators. Doc: Let $\Delta_{0}:=\text{Div}^{0}(\P^{1}(\Q))$. Let $M$ being a full modular symbol space, as given by \kbd{msinit}, return a set of $\Z[G]$-generators for $\Delta_{0}$. The output is $[g,R]$, where $g$ is a minimal system of generators and $R$ the vector of $\Z[G]$-relations between the given generators. A relation is coded by a vector of pairs $[a_{i},i]$ with $a_{i}\in \Z[G]$ and $i$ the index of a generator, so that $\sum_{i} a_{i} g[i] = 0$. An element $[v]-[u]$ in $\Delta_{0}$ is coded by the ``path'' $[u,v]$, where \kbd{oo} denotes the point at infinity $(1:0)$ on the projective line. An element of $\Z[G]$ is either an integer $n$ ($= n [\text{id}_{2}]$) or a ``factorization matrix'': the first column contains distinct elements $g_{i}$ of $G$ and the second integers $n_{i}$ and the matrix codes $\sum_{i} n_{i} [g_{i}]$: \bprog ? M = msinit(11,8); \\ M_8(Gamma_0(11)) ? [g,R] = mspathgens(M); ? g %3 = [[+oo, 0], [0, 1/3], [1/3, 1/2]] \\ 3 paths ? #R \\ a single relation %4 = 1 ? r = R[1]; #r \\ ...involving all 3 generators %5 = 3 ? r[1] %6 = [[1, 1; [1, 1; 0, 1], -1], 1] ? r[2] %7 = [[1, 1; [7, -2; 11, -3], -1], 2] ? r[3] %8 = [[1, 1; [8, -3; 11, -4], -1], 3] @eprog\noindent The given relation is of the form $\sum_{i} (1-\gamma_{i}) g_{i} = 0$, with $\gamma_{i}\in \Gamma_{0}(11)$. There will always be a single relation involving all generators (corresponding to a round trip along all cusps), then relations involving a single generator (corresponding to $2$ and $3$-torsion elements in the group: \bprog ? M = msinit(2,8); \\ M_8(Gamma_0(2)) ? [g,R] = mspathgens(M); ? g %3 = [[+oo, 0], [0, 1]] @eprog\noindent Note that the output depends only on the group $G$, not on the representation $V$. pari-2.17.2/src/functions/modular_symbols/msgetlevel0000644000175000017500000000041614567450071021302 0ustar billbillFunction: msgetlevel Section: modular_symbols C-Name: msgetlevel Prototype: lG Help: msgetlevel(M): M being a full modular symbol space, as given by msinit, return its level N. Doc: $M$ being a full modular symbol space, as given by \kbd{msinit}, return its level $N$. pari-2.17.2/src/functions/modular_symbols/msomseval0000644000175000017500000000106214760123736021137 0ustar billbillFunction: msomseval Section: modular_symbols C-Name: msomseval Prototype: GGG Help: msomseval(Mp,PHI,path): return the vectors of moments of the p-adic distribution attached to the path 'path' via the overconvergent modular symbol 'PHI'. Doc:return the vectors of moments of the $p$-adic distribution attached to the path \kbd{path} by the overconvergent modular symbol \kbd{PHI}. \bprog ? M = msinit(3,6,1); ? Mp= mspadicinit(M,5,10); ? phi = [5,-3,-1]~; ? msissymbol(M,phi) %4 = 1 ? PHI = mstooms(Mp,phi); ? ME = msomseval(Mp,PHI,[oo, 0]); @eprog pari-2.17.2/src/functions/modular_symbols/msfromhecke0000644000175000017500000000226314676526175021452 0ustar billbillFunction: msfromhecke Section: modular_symbols C-Name: msfromhecke Prototype: GGDG Help: msfromhecke(M,v,{H}): given a msinit M and a vector v of pairs [p, P] (where p is prime and P is a polynomial with integer coefficients), return a basis of all modular symbols such that P(Tp) * s = 0. If H is present, it must be a Hecke-stable subspace and we restrict to s in H. Doc: given a msinit $M$ and a vector $v$ of pairs $[p, P]$ (where $p$ is prime and $P$ is a polynomial with integer coefficients), return a basis of all modular symbols such that $P(T_{p})(s) = 0$. If $H$ is present, it must be a Hecke-stable subspace and we restrict to $s \in H$. When $T_{p}$ has a rational eigenvalue and $P(x) = x-a_{p}$ has degree $1$, we also accept the integer $a_{p}$ instead of $P$. \bprog ? E = ellinit([0,-1,1,-10,-20]) \\11a1 ? ellap(E,2) %2 = -2 ? ellap(E,3) %3 = -1 ? M = msinit(11,2); ? S = msfromhecke(M, [[2,-2],[3,-1]]) %5 = [ 1 1] [-5 0] [ 0 -5] ? mshecke(M, 2, S) %6 = [-2 0] [ 0 -2] ? M = msinit(23,4); ? S = msfromhecke(M, [[5, x^4-14*x^3-244*x^2+4832*x-19904]]); ? factor( charpoly(mshecke(M,5,S)) ) %9 = [x^4 - 14*x^3 - 244*x^2 + 4832*x - 19904 2] @eprog pari-2.17.2/src/functions/modular_symbols/mshecke0000644000175000017500000000174114676526175020566 0ustar billbillFunction: mshecke Section: modular_symbols C-Name: mshecke Prototype: GLDG Help: mshecke(M,p,{H}): M being a full modular symbol space, as given by msinit, p being a prime number, and H being a Hecke-stable subspace (M if omitted), return the matrix of T_p acting on H (U_p if p divides the level). Doc: $M$ being a full modular symbol space, as given by \kbd{msinit}, $p$ being a prime number, and $H$ being a Hecke-stable subspace ($M$ if omitted), return the matrix of $T_{p}$ acting on $H$ ($U_{p}$ if $p$ divides $N$). Result is undefined if $H$ is not stable by $T_{p}$ (resp.~$U_{p}$). \bprog ? M = msinit(11,2); \\ M_2(Gamma_0(11)) ? T2 = mshecke(M,2) %2 = [3 0 0] [1 -2 0] [1 0 -2] ? M = msinit(11,2, 1); \\ M_2(Gamma_0(11))^+ ? T2 = mshecke(M,2) %4 = [ 3 0] [-1 -2] ? N = msnew(M)[1] \\ Q-basis of new cuspidal subspace %5 = [-2] [-5] ? p = 1009; mshecke(M, p, N) \\ action of T_1009 on N %6 = [-10] ? ellap(ellinit("11a1"), p) %7 = -10 @eprog pari-2.17.2/src/functions/modular_symbols/mspetersson0000644000175000017500000000374014676526175021532 0ustar billbillFunction: mspetersson Section: modular_symbols C-Name: mspetersson Prototype: GDGDG Help: mspetersson(M,{F},{G=F}): M being a full modular symbol space, as given by msinit, calculate the intersection product {F,G} of modular symbols F and G on M. Doc: $M$ being a full modular symbol space for $\Gamma = \Gamma_{0}(N)$, as given by \kbd{msinit}, calculate the intersection product $\{F, G\}$ of modular symbols $F$ and $G$ on $M=\Hom_{\Gamma}(\Delta_{0}, V_{k})$ extended to an hermitian bilinear form on $M \otimes \C$ whose radical is the Eisenstein subspace of $M$. Suppose that $f_{1}$ and $f_{2}$ are two parabolic forms. Let $F_{1}$ and $F_{2}$ be the attached modular symbols $$ F_{i}(\delta)= \int_{\delta} f_{i}(z) \cdot (z X + Y)^{k-2} \,dz$$ and let $F^{\R}_{1}$, $F^{\R}_{2}$ be the attached real modular symbols $$ F^{\R}_{i}(\delta)= \int_{\delta} \Re\big(f_{i}(z) \cdot (z X + Y)^{k-2} \,dz\big) $$ Then we have $$ \{ F^{\R}_{1}, F^{\R}_{2} \} = -2 (2i)^{k-2} \cdot \Im(_{\var{Petersson}}) $$ and $$\{ F_{1}, \bar{F_{2}} \} = (2i)^{k-2} _{\var{Petersson}}$$ In weight 2, the intersection product $\{F, G\}$ has integer values on the $\Z$-structure on $M$ given by \kbd{mslattice} and defines a Riemann form on $H^{1}_{par}(\Gamma,\R)$. For user convenience, we allow $F$ and $G$ to be matrices and return the attached Gram matrix. If $F$ is omitted: treat it as the full modular space attached to $M$; if $G$ is omitted, take it equal to $F$. \bprog ? M = msinit(37,2); ? C = mscuspidal(M)[1]; ? mspetersson(M, C) %3 = [ 0 -17 -8 -17] [17 0 -8 -25] [ 8 8 0 -17] [17 25 17 0] ? mspetersson(M, mslattice(M,C)) %4 = [0 -1 0 -1] [1 0 0 -1] [0 0 0 -1] [1 1 1 0] ? E = ellinit("33a1"); ? [M,xpm] = msfromell(E); [xp,xm,L] = xpm; ? mspetersson(M, mslattice(M,L)) %7 = [0 -3] [3 0] ? ellmoddegree(E) %8 = [3, -126] @eprog \noindent The coefficient $3$ in the matrix is the degree of the modular parametrization. pari-2.17.2/src/functions/modular_symbols/msstar0000644000175000017500000000107314567450071020444 0ustar billbillFunction: msstar Section: modular_symbols C-Name: msstar Prototype: GDG Help: msstar(M,{H}): M being a full modular symbol space, as given by msinit, return the matrix of the * involution, induced by complex conjugation, acting on the (stable) subspace H (M if omitted). Doc: $M$ being a full modular symbol space, as given by \kbd{msinit}, return the matrix of the \kbd{*} involution, induced by complex conjugation, acting on the (stable) subspace $H$ ($M$ if omitted). \bprog ? M = msinit(11,2); \\ M_2(Gamma_0(11)) ? w = msstar(M); ? w^2 == 1 %3 = 1 @eprog pari-2.17.2/src/functions/modular_symbols/msfarey0000644000175000017500000000417014676526175020614 0ustar billbillFunction: msfarey Section: modular_symbols C-Name: msfarey0 Prototype: GGD& Help: msfarey(F,inH,{&CM}): F being a Farey symbol attached to a group G contained in SL2(Z) and H a subgroup of G, return a Farey symbol attached to H; H is given by a criterion inH (closure) deciding whether an element of G belongs to H. Doc: $F$ being a Farey symbol attached to a group $G$ contained in $\text{PSL}_{2}(\Z)$ and $H$ a subgroup of $G$, return a Farey symbol attached to $H$. The subgroup $H$ is given by a criterion \kbd{inH} (closure) deciding whether an element of $G$ belongs to $H$. The symbol $F$ can be created using \item \kbd{mspolygon}: $G = \Gamma_{0}(N)$, which runs in time $\tilde{O}(N)$; \item or \kbd{msfarey} itself, which runs in time $O([G:H]^{2})$. If present, the argument \kbd{CM} is set to \kbd{mscosets(F[3])}, giving the right cosets of $H \backslash G$ and the action of $G$ by right multiplication. Since \kbd{msfarey}'s algorithm is quadratic in the index $[G:H]$, it is advisable to construct subgroups by a chain of inclusions if possible. \bprog \\ Gamma_0(N) G0(N) = mspolygon(N); \\ Gamma_1(N): direct construction, slow G1(N) = msfarey(mspolygon(1), g -> my(a = g[1,1]%N, c = g[2,1]%N);\ c == 0 && (a == 1 || a == N-1)); \\ Gamma_1(N) via Gamma_0(N): much faster G1(N) = msfarey(G0(N), g -> my(a=g[1,1]%N); a==1 || a==N-1); @eprog\noindent Note that the simpler criterion \kbd{g[1,1]\%N == 1} would not be correct since it must apply to elements of $\text{PSL}_{2}(\Z)$ hence be invariant under $g \mapsto -g$. Here are other examples: \bprog \\ Gamma(N) G(N) = msfarey(G1(N), g -> g[1,2]%N==0); G_00(N) = msfarey(G0(N), x -> x[1,2]%N==0); G1_0(N1,N2) = msfarey(G0(1), x -> x[2,1]%N1==0 && x[1,2]%N2==0); \\ Gamma_0(91) has 4 elliptic points of order 3, Gamma_1(91) has none D0 = mspolygon(G0(91), 2)[4]; D1 = mspolygon(G1(91), 2)[4]; write("F.tex","\\documentclass{article}\\usepackage{tikz}\\begin{document}",\ D0,"\n",D1,"\\end{document}"); @eprog Variant: Also available is \fun{GEN}{msfarey}{GEN F, void *E, long (*inH)(void *, GEN), GEN *pCM}. pari-2.17.2/src/functions/modular_symbols/msfromell0000644000175000017500000000553614676526175021155 0ustar billbillFunction: msfromell Section: modular_symbols C-Name: msfromell Prototype: GD0,L, Help: msfromell(E,{sign=0}): return the [M, x], where M is msinit(N,2) and x is the modular symbol in M attached to the elliptic curve E/Q. Doc: Let $E/\Q$ be an elliptic curve of conductor $N$. For $\varepsilon = \pm1$, we define the (cuspidal, new) modular symbol $x^{\varepsilon}$ in $H^{1}_{c}(X_{0}(N),\Q)^{\varepsilon}$ attached to $E$. For all primes $p$ not dividing $N$ we have $T_{p}(x^{\varepsilon}) = a_{p} x^{\varepsilon}$, where $a_{p} = p+1-\#E(\F_{p})$. Let $\Omega^{+} = \kbd{E.omega[1]}$ be the real period of $E$ (integration of the N\'eron differential $dx/(2y+a_{1}x+a_{3})$ on the connected component of $E(\R)$, i.e.~the generator of $H_{1}(E,\Z)^{+}$) normalized by $\Omega^{+}>0$. Let $i\Omega^{-}$ the integral on a generator of $H_{1}(E,\Z)^{-}$ with $\Omega^{-} \in \R_{>0}$. If $c_{\infty}$ is the number of connected components of $E(\R)$, $\Omega^{-}$ is equal to $(-2/c_{\infty}) \times \kbd{imag(E.omega[2])}$. The complex modular symbol is defined by $$F: \delta \to 2i\pi \int_{\delta} f(z) dz$$ The modular symbols $x^{\varepsilon}$ are normalized so that $ F = x^{+} \Omega^{+} + x^{-} i\Omega^{-}$. In particular, we have $$ x^{+}([0]-[\infty]) = L(E,1) / \Omega^{+},$$ which defines $x^{\pm}$ unless $L(E,1)=0$. Furthermore, for all fundamental discriminants $D$ such that $\varepsilon \cdot D > 0$, we also have $$\sum_{0\leq a<|D|} (D|a) x^{\varepsilon}([a/|D|]-[\infty]) = L(E,(D|.),1) / \Omega^{\varepsilon},$$ where $(D|.)$ is the Kronecker symbol. The period $\Omega^{-}$ is also $2/c_{\infty} \times$ the real period of the twist $E^{(-4)} = \kbd{elltwist(E,-4)}$. This function returns the pair $[M, x]$, where $M$ is \kbd{msinit}$(N,2)$ and $x$ is $x^{\var{sign}}$ as above when $\var{sign}= \pm1$, and $x = [x^{+},x^{-}, L_{E}]$ when \var{sign} is $0$, where $L_{E}$ is a matrix giving the canonical $\Z$-lattice attached to $E$ in the sense of \kbd{mslattice} applied to $\Q x^{+} + \Q x^{-}$. Explicitly, it is generated by $(x^{+},x^{-})$ when $E(\R)$ has two connected components and by $(x^{+} - x^{-},2x^{-})$ otherwise. The modular symbols $x^{\pm}$ are given as a \typ{COL} (in terms of the fixed basis of $\Hom_{G}(\Delta_{0},\Q)$ chosen in $M$). \bprog ? E=ellinit([0,-1,1,-10,-20]); \\ X_0(11) ? [M,xp]= msfromell(E,1); ? xp %3 = [1/5, -1/2, -1/2]~ ? [M,x]= msfromell(E); ? x \\ x^+, x^- and L_E %5 = [[1/5, -1/2, -1/2]~, [0, 1/2, -1/2]~, [1/5, 0; -1, 1; 0, -1]] ? p = 23; (mshecke(M,p) - ellap(E,p))*x[1] %6 = [0, 0, 0]~ \\ true at all primes, including p = 11; same for x[2] ? (mshecke(M,p) - ellap(E,p))*x[3] == 0 %7 = 1 @eprog \noindent Instead of a single curve $E$, one may use instead a vector of \emph{isogenous} curves. The function then returns $M$ and the vector of attached modular symbols. pari-2.17.2/src/functions/modular_symbols/mscuspidal0000644000175000017500000000177014676526175021315 0ustar billbillFunction: mscuspidal Section: modular_symbols C-Name: mscuspidal Prototype: GD0,L, Help: mscuspidal(M,{flag=0}): M being a full modular symbol space, as given by msinit, return its cuspidal part S. If flag = 1, return [S,E] its decomposition into Eisenstein and cuspidal parts. Doc: $M$ being a full modular symbol space, as given by \kbd{msinit}, return its cuspidal part $S$. If $\fl = 1$, return $[S,E]$ its decomposition into cuspidal and Eisenstein parts. A subspace is given by a structure allowing quick projection and restriction of linear operators; its first component is a matrix with integer coefficients whose columns form a $\Q$-basis of the subspace. \bprog ? M = msinit(2,8, 1); \\ M_8(Gamma_0(2))^+ ? [S,E] = mscuspidal(M, 1); ? E[1] \\ 2-dimensional %3 = [0 -10] [0 -15] [0 -3] [1 0] ? S[1] \\ 1-dimensional %4 = [ 3] [30] [ 6] [-8] @eprog Function: _eisker_worker Section: programming/internals C-Name: eisker_worker Prototype: GGGGG Help: worker for eisker pari-2.17.2/src/functions/modular_symbols/msissymbol0000644000175000017500000000155514567450071021341 0ustar billbillFunction: msissymbol Section: modular_symbols C-Name: msissymbol Prototype: GG Help: msissymbol(M,s): M being a full modular symbol space, as given by msinit, check whether s is a modular symbol attached to M. Doc: $M$ being a full modular symbol space, as given by \kbd{msinit}, check whether $s$ is a modular symbol attached to $M$. If $A$ is a matrix, check whether its columns represent modular symbols and return a $0-1$ vector. \bprog ? M = msinit(7,8, 1); \\ M_8(Gamma_0(7))^+ ? A = msnew(M)[1]; ? s = A[,1]; ? msissymbol(M, s) %4 = 1 ? msissymbol(M, A) %5 = [1, 1, 1] ? S = mseval(M,s); ? msissymbol(M, S) %7 = 1 ? [g,R] = mspathgens(M); g %8 = [[+oo, 0], [0, 1/2], [1/2, 1]] ? #R \\ 3 relations among the generators g_i %9 = 3 ? T = S; T[3]++; \\ randomly perturb S(g_3) ? msissymbol(M, T) %11 = 0 \\ no longer satisfies the relations @eprog pari-2.17.2/src/functions/modular_symbols/mspadicL0000644000175000017500000001020714676526175020700 0ustar billbillFunction: mspadicL Section: modular_symbols C-Name: mspadicL Prototype: GDGD0,L, Help: mspadicL(mu,{s=0},{r=0}): given mu from mspadicmoments (p-adic distributions attached to an overconvergent symbol PHI) returns the value on a character of Z_p^* represented by s of the derivative of order r of the p-adic L-function attached to PHI. Doc: Returns the value (or $r$-th derivative) on a character $\chi^{s}$ of $\Z_{p}^{*}$ of the $p$-adic $L$-function attached to \kbd{mu}. Let $\Phi$ be the $p$-adic distribution-valued overconvergent symbol attached to a modular symbol $\phi$ for $\Gamma_{0}(N)$ (eigenvector for $T_{N}(p)$ for the eigenvalue $a_{p}$). Then $L_{p}(\Phi,\chi^{s})=L_{p}(\mu,s)$ is the $p$-adic $L$ function defined by $$L_{p}(\Phi,\chi^{s})= \int_{\Z_{p}^{*}} \chi^{s}(z) d\mu(z)$$ where $\mu$ is the distribution on $\Z_{p}^{*}$ defined by the restriction of $\Phi([\infty]-[0])$ to $\Z_{p}^{*}$. The $r$-th derivative is taken in direction $\langle \chi\rangle$: $$L_{p}^{(r)}(\Phi,\chi^{s})= \int_{\Z_{p}^{*}} \chi^{s}(z) (\log z)^{r} d\mu(z).$$ In the argument list, \item \kbd{mu} is as returned by \tet{mspadicmoments} (distributions attached to $\Phi$ by restriction to discs $a + p^{\nu}\Z_{p}$, $(a,p)=1$). \item $s=[s_{1},s_{2}]$ with $s_{1} \in \Z \subset \Z_{p}$ and $s_{2} \bmod p-1$ or $s_{2} \bmod 2$ for $p=2$, encoding the $p$-adic character $\chi^{s} := \langle \chi \rangle^{s_{1}} \tau^{s_{2}}$; here $\chi$ is the cyclotomic character from $\text{Gal}(\Q_{p}(\mu_{p^{\infty}})/\Q_{p})$ to $\Z_{p}^{*}$, and $\tau$ is the Teichm\"uller character (for $p>2$ and the character of order 2 on $(\Z/4\Z)^{*}$ if $p=2$); for convenience, the character $[s,s]$ can also be represented by the integer $s$. When $a_{p}$ is a $p$-adic unit, $L_{p}$ takes its values in $\Q_{p}$. When $a_{p}$ is not a unit, it takes its values in the two-dimensional $\Q_{p}$-vector space $D_{cris}(M(\phi))$ where $M(\phi)$ is the ``motive'' attached to $\phi$, and we return the two $p$-adic components with respect to some fixed $\Q_{p}$-basis. \bprog ? M = msinit(3,6,1); phi=[5, -3, -1]~; ? msissymbol(M,phi) %2 = 1 ? Mp = mspadicinit(M, 5, 4); ? mu = mspadicmoments(Mp, phi); \\ no twist \\ End of initializations ? mspadicL(mu,0) \\ L_p(chi^0) %5 = 5 + 2*5^2 + 2*5^3 + 2*5^4 + ... ? mspadicL(mu,1) \\ L_p(chi), zero for parity reasons %6 = [O(5^13)]~ ? mspadicL(mu,2) \\ L_p(chi^2) %7 = 3 + 4*5 + 4*5^2 + 3*5^5 + ... ? mspadicL(mu,[0,2]) \\ L_p(tau^2) %8 = 3 + 5 + 2*5^2 + 2*5^3 + ... ? mspadicL(mu, [1,0]) \\ L_p() %9 = 3*5 + 2*5^2 + 5^3 + 2*5^7 + 5^8 + 5^10 + 2*5^11 + O(5^13) ? mspadicL(mu,0,1) \\ L_p'(chi^0) %10 = 2*5 + 4*5^2 + 3*5^3 + ... ? mspadicL(mu, 2, 1) \\ L_p'(chi^2) %11 = 4*5 + 3*5^2 + 5^3 + 5^4 + ... @eprog Now several quadratic twists: \tet{mstooms} is indicated. \bprog ? PHI = mstooms(Mp,phi); ? mu = mspadicmoments(Mp, PHI, 12); \\ twist by 12 ? mspadicL(mu) %14 = 5 + 5^2 + 5^3 + 2*5^4 + ... ? mu = mspadicmoments(Mp, PHI, 8); \\ twist by 8 ? mspadicL(mu) %16 = 2 + 3*5 + 3*5^2 + 2*5^4 + ... ? mu = mspadicmoments(Mp, PHI, -3); \\ twist by -3 < 0 ? mspadicL(mu) %18 = O(5^13) \\ always 0, phi is in the + part and D < 0 @eprog One can locate interesting symbols of level $N$ and weight $k$ with \kbd{msnew} and \kbd{mssplit}. Note that instead of a symbol, one can input a 1-dimensional Hecke-subspace from \kbd{mssplit}: the function will automatically use the underlying basis vector. \bprog ? M=msinit(5,4,1); \\ M_4(Gamma_0(5))^+ ? L = mssplit(M, msnew(M)); \\ list of irreducible Hecke-subspaces ? phi = L[1]; \\ one Galois orbit of newforms ? #phi[1] \\... this one is rational %4 = 1 ? Mp = mspadicinit(M, 3, 4); ? mu = mspadicmoments(Mp, phi); ? mspadicL(mu) %7 = 1 + 3 + 3^3 + 3^4 + 2*3^5 + 3^6 + O(3^9) ? M = msinit(11,8, 1); \\ M_8(Gamma_0(11))^+ ? Mp = mspadicinit(M, 3, 4); ? L = mssplit(M, msnew(M)); ? phi = L[1]; #phi[1] \\ ... this one is two-dimensional %11 = 2 ? mu = mspadicmoments(Mp, phi); *** at top-level: mu=mspadicmoments(Mp,ph *** ^-------------------- *** mspadicmoments: incorrect type in mstooms [dim_Q (eigenspace) > 1] @eprog pari-2.17.2/src/functions/modular_symbols/mssplit0000644000175000017500000000271214567450071020627 0ustar billbillFunction: mssplit Section: modular_symbols C-Name: mssplit Prototype: GDGD0,L, Help: mssplit(M,{H},{dimlim}): M being a full modular symbol space, as given by msinit, and H being a subspace (the new subspace if omitted), split H into Hecke-simple subspaces. If dimlim is present and positive, restrict to dim <= dimlim. Doc: Let $M$ denote a full modular symbol space, as given by \kbd{msinit}$(N,k,1)$ or $\kbd{msinit}(N,k,-1)$ and let $H$ be a Hecke-stable subspace of \kbd{msnew}$(M)$ (the full new subspace if $H$ is omitted). This function splits $H$ into Hecke-simple subspaces. If \kbd{dimlim} is present and positive, restrict to subspaces of dimension $\leq \kbd{dimlim}$. A subspace is given by a structure allowing quick projection and restriction of linear operators; its first component is a matrix with integer coefficients whose columns form a $\Q$-basis of the subspace. \bprog ? M = msinit(11,8, 1); \\ M_8(Gamma_0(11))^+ ? L = mssplit(M); \\ split msnew(M) ? #L %3 = 2 ? f = msqexpansion(M,L[1],5); f[1].mod %4 = x^2 + 8*x - 44 ? lift(f) %5 = [1, x, -6*x - 27, -8*x - 84, 20*x - 155] ? g = msqexpansion(M,L[2],5); g[1].mod %6 = x^4 - 558*x^2 + 140*x + 51744 @eprog\noindent To a Hecke-simple subspace corresponds an orbit of (normalized) newforms, defined over a number field. In the above example, we printed the polynomials defining the said fields, as well as the first 5 Fourier coefficients (at the infinite cusp) of one such form. pari-2.17.2/src/functions/modular_symbols/mspadicinit0000644000175000017500000000367414676526175021462 0ustar billbillFunction: mspadicinit Section: modular_symbols C-Name: mspadicinit Prototype: GLLD-1,L, Help: mspadicinit(M,p,n,{flag}): M being a full modular symbol space, as given by msinit and a prime p, initialize technical data needed to compute with overconvergent modular symbols (modulo p^n). If flag is unset, allow all symbols; if flag = 0, restrict to ordinary symbols; else initialize for symbols phi such that Tp(phi) = a_p * phi, with v_p(a_p) >= flag. Doc: $M$ being a full modular symbol space, as given by \kbd{msinit}, and $p$ a prime, initialize technical data needed to compute with overconvergent modular symbols, modulo $p^{n}$. If $\fl$ is unset, allow all symbols; else initialize only for a restricted range of symbols depending on $\fl$: if $\fl = 0$ restrict to ordinary symbols, else restrict to symbols $\phi$ such that $T_{p}(\phi) = a_{p} \phi$, with $v_{p}(a_{p}) \geq \fl$, which is faster as $\fl$ increases. (The fastest initialization is obtained for $\fl = 0$ where we only allow ordinary symbols.) For supersingular eigensymbols, such that $p\mid a_{p}$, we must further assume that $p$ does not divide the level. \bprog ? E = ellinit("11a1"); ? [M,phi] = msfromell(E,1); ? ellap(E,3) %3 = -1 ? Mp = mspadicinit(M, 3, 10, 0); \\ commit to ordinary symbols ? PHI = mstooms(Mp,phi); @eprog If we restrict the range of allowed symbols with \fl (for faster initialization), exceptions will occur if $v_{p}(a_{p})$ violates this bound: \bprog ? E = ellinit("15a1"); ? [M,phi] = msfromell(E,1); ? ellap(E,7) %3 = 0 ? Mp = mspadicinit(M,7,5,0); \\ restrict to ordinary symbols ? PHI = mstooms(Mp,phi) *** at top-level: PHI=mstooms(Mp,phi) *** ^--------------- *** mstooms: incorrect type in mstooms [v_p(ap) > mspadicinit flag] (t_VEC). ? Mp = mspadicinit(M,7,5); \\ no restriction ? PHI = mstooms(Mp,phi); @eprog\noindent This function uses $O(N^{2}(n+k)^{2}p)$ memory, where $N$ is the level of $M$. pari-2.17.2/src/functions/modular_symbols/msfromcusp0000644000175000017500000000310414676526175021340 0ustar billbillFunction: msfromcusp Section: modular_symbols C-Name: msfromcusp Prototype: GG Help: msfromcusp(M,c): returns the modular symbol attached to the cusp c, where M is a modular symbol space of level N. Doc: returns the modular symbol attached to the cusp $c$, where $M$ is a modular symbol space of level $N$, attached to $G = \Gamma_{0}(N)$. The cusp $c$ in $\P^{1}(\Q)/G$ is given either as \kbd{oo} ($=(1:0)$) or as a rational number $a/b$ ($=(a:b)$). The attached symbol maps the path $[b] - [a] \in \text{Div}^{0} (\P^{1}(\Q))$ to $E_{c}(b) - E_{c}(a)$, where $E_{c}(r)$ is $0$ when $r \neq c$ and $X^{k-2} \mid \gamma_{r}$ otherwise, where $\gamma_{r} \cdot r = (1:0)$. These symbols span the Eisenstein subspace of $M$. \bprog ? M = msinit(2,8); \\ M_8(Gamma_0(2)) ? E = mseisenstein(M); ? E[1] \\ two-dimensional %3 = [0 -10] [0 -15] [0 -3] [1 0] ? s = msfromcusp(M,oo) %4 = [0, 0, 0, 1]~ ? mseval(M, s) %5 = [1, 0] ? s = msfromcusp(M,1) %6 = [-5/16, -15/32, -3/32, 0]~ ? mseval(M,s) %7 = [-x^6, -6*x^5 - 15*x^4 - 20*x^3 - 15*x^2 - 6*x - 1] @eprog In case $M$ was initialized with a nonzero \emph{sign}, the symbol is given in terms of the fixed basis of the whole symbol space, not the $+$ or $-$ part (to which it need not belong). \bprog ? M = msinit(2,8, 1); \\ M_8(Gamma_0(2))^+ ? E = mseisenstein(M); ? E[1] \\ still two-dimensional, in a smaller space %3 = [ 0 -10] [ 0 3] [-1 0] ? s = msfromcusp(M,oo) \\ in terms of the basis for M_8(Gamma_0(2)) ! %4 = [0, 0, 0, 1]~ ? mseval(M, s) \\ same symbol as before %5 = [1, 0] @eprog pari-2.17.2/src/functions/modular_symbols/mslattice0000644000175000017500000000340714676526175021135 0ustar billbillFunction: mslattice Section: modular_symbols C-Name: mslattice Prototype: GDG Help: mslattice(M,{H}): M being a full modular symbol space, as given by msinit, H a Q-subspace or a matrix of modular symbols. Return the canonical integral structure of H. Doc: Let $\Delta_{0}:=\text{Div}^{0}(\P^{1}(\Q))$ and $V_{k} = \Q[x,y]_{k-2}$. Let $M$ be a full modular symbol space, as given by \kbd{msinit} and let $H$ be a subspace, e.g. as given by \kbd{mscuspidal}. This function returns a canonical $\Z$-structure on $H$ defined as follows. Consider the map $c: M=\Hom_{\Gamma_{0}(N)}(\Delta_{0}, V_{k}) \to H^{1}(\Gamma_{0}(N), V_{k})$ given by $\phi \mapsto \var{class}(\gamma \to \phi(\{0, \gamma^{-1} 0\}))$. Let $L_{k}=\Z[x,y]_{k-2}$ be the natural $\Z$-structure of $V_{k}$. The result of \kbd{mslattice} is a $\Z$-basis of the inverse image by $c$ of $H^{1}(\Gamma_{0}(N), L_{k})$ in the space of modular symbols generated by $H$. For user convenience, $H$ can be defined by a matrix representing the $\Q$-basis of $H$ (in terms of the canonical $\Q$-basis of $M$ fixed by \kbd{msinit} and used to represent modular symbols). If omitted, $H$ is the cuspidal part of $M$ as given by \kbd{mscuspidal}. The Eisenstein part $\Hom_{\Gamma_{0}(N)}(\text{Div}(\P^{1}(\Q)), V_{k})$ is in the kernel of $c$, so the result has no meaning for the Eisenstein part \kbd{H}. \bprog ? M=msinit(11,2); ? [S,E] = mscuspidal(M,1); S[1] \\ a primitive Q-basis of S %2 = [ 1 1] [-5 0] [ 0 -5] ? mslattice(M,S) %3 = [-1/5 -1/5] [ 1 0] [ 0 1] ? mslattice(M,E) %4 = [1] [0] [0] ? M=msinit(5,4); ? S=mscuspidal(M); S[1] %6 = [ 7 20] [ 3 3] [-10 -23] [-30 -30] ? mslattice(M,S) %7 = [-1/10 -11/130] [ 0 -1/130] [ 1/10 6/65] [ 0 1/13] @eprog pari-2.17.2/src/functions/modular_symbols/mseval0000644000175000017500000000436714676526175020445 0ustar billbillFunction: mseval Section: modular_symbols C-Name: mseval Prototype: GGDG Help: mseval(M,s,{p}): M being a full modular symbol space, as given by msinit, s being a modular symbol from M and p being a path between two elements in P^1(Q), return s(p). Doc: Let $\Delta_{0}:=\text{Div}^{0}(\P^{1} (\Q))$. Let $M$ be a full modular symbol space, as given by \kbd{msinit}, let $s$ be a modular symbol from $M$, i.e. an element of $\Hom_{G}(\Delta_{0}, V)$, and let $p=[a,b] \in \Delta_{0}$ be a path between two elements in $\P^{1}(\Q)$, return $s(p)\in V$. The path extremities $a$ and $b$ may be given as \typ{INT}, \typ{FRAC} or $\kbd{oo} = (1:0)$; it is also possible to describe the path by a $2 \times 2$ integral matrix whose columns give the two cusps. The symbol $s$ is either \item a \typ{COL} coding a modular symbol in terms of the fixed basis of $\Hom_{G}(\Delta_{0},V)$ chosen in $M$; if $M$ was initialized with a nonzero \emph{sign} ($+$ or $-$), then either the basis for the full symbol space or the $\pm$-part can be used (the dimension being used to distinguish the two). \item a \typ{MAT} whose columns encode modular symbols as above. This is much faster than evaluating individual symbols on the same path $p$ independently. \item a \typ{VEC} $(v_{i})$ of elements of $V$, where the $v_{i} = s(g_{i})$ give the image of the generators $g_{i}$ of $\Delta_{0}$, see \tet{mspathgens}. We assume that $s$ is a proper symbol, i.e.~that the $v_{i}$ satisfy the \kbd{mspathgens} relations. If $p$ is omitted, convert a single symbol $s$ to the second form: a vector of the $s(g_{i})$. A \typ{MAT} is converted to a vector of such. \bprog ? M = msinit(2,8,1); \\ M_8(Gamma_0(2))^+ ? g = mspathgens(M)[1] %2 = [[+oo, 0], [0, 1]] ? N = msnew(M)[1]; #N \\ Q-basis of new subspace, dimension 1 %3 = 1 ? s = N[,1] \\ t_COL representation %4 = [-3, 6, -8]~ ? S = mseval(M, s) \\ t_VEC representation %5 = [64*x^6-272*x^4+136*x^2-8, 384*x^5+960*x^4+192*x^3-672*x^2-432*x-72] ? mseval(M,s, g[1]) %6 = 64*x^6 - 272*x^4 + 136*x^2 - 8 ? mseval(M,S, g[1]) %7 = 64*x^6 - 272*x^4 + 136*x^2 - 8 @eprog\noindent Note that the symbol should have values in $V = \Q[x,y]_{k-2}$, we return the de-homogenized values corresponding to $y = 1$ instead. pari-2.17.2/src/functions/modular_symbols/mspadicseries0000644000175000017500000000622214676526175022001 0ustar billbillFunction: mspadicseries Section: modular_symbols C-Name: mspadicseries Prototype: GD0,L, Help: mspadicseries(mu,{i=0}): given mu from mspadicmoments, returns the attached p-adic series with maximal p-adic precision, depending on the precision of M (i-th Teichmueller component, if present). Doc: Let $\Phi$ be the $p$-adic distribution-valued overconvergent symbol attached to a modular symbol $\phi$ for $\Gamma_{0}(N)$ (eigenvector for $T_{N}(p)$ for the eigenvalue $a_{p}$). If $\mu$ is the distribution on $\Z_{p}^{*}$ defined by the restriction of $\Phi([\infty]-[0])$ to $\Z_{p}^{*}$, let $$\hat{L}_{p}(\mu,\tau^{i})(x) = \int_{\Z_{p}^{*}} \tau^{i}(t) (1+x)^{\log_{p}(t)/\log_{p}(u)}d\mu(t)$$ Here, $\tau$ is the Teichm\"uller character and $u$ is a specific multiplicative generator of $1+2p\Z_{p}$, namely $1+p$ if $p>2$ or $5$ if $p=2$. To explain the formula, let $G_{\infty} := \text{Gal}(\Q(\mu_{p^{\infty}})/ \Q)$, let $\chi:G_{\infty}\to \Z_{p}^{*}$ be the cyclotomic character (isomorphism) and $\gamma$ the element of $G_{\infty}$ such that $\chi(\gamma)=u$; then $\chi(\gamma)^{\log_{p}(t)/\log_{p}(u)}= \langle t \rangle$. The $p$-padic precision of individual terms is maximal given the precision of the overconvergent symbol $\mu$. \bprog ? [M,phi] = msfromell(ellinit("17a1"),1); ? Mp = mspadicinit(M, 5,7); ? mu = mspadicmoments(Mp, phi,1); \\ overconvergent symbol ? mspadicseries(mu) %4 = (4 + 3*5 + 4*5^2 + 2*5^3 + 2*5^4 + 5^5 + 4*5^6 + 3*5^7 + O(5^9)) \ + (3 + 3*5 + 5^2 + 5^3 + 2*5^4 + 5^6 + O(5^7))*x \ + (2 + 3*5 + 5^2 + 4*5^3 + 2*5^4 + O(5^5))*x^2 \ + (3 + 4*5 + 4*5^2 + O(5^3))*x^3 \ + (3 + O(5))*x^4 + O(x^5) @eprog\noindent An example with nonzero Teichm\"uller: \bprog ? [M,phi] = msfromell(ellinit("11a1"),1); ? Mp = mspadicinit(M, 3,10); ? mu = mspadicmoments(Mp, phi,1); ? mspadicseries(mu, 2) %4 = (2 + 3 + 3^2 + 2*3^3 + 2*3^5 + 3^6 + 3^7 + 3^10 + 3^11 + O(3^12)) \ + (1 + 3 + 2*3^2 + 3^3 + 3^5 + 2*3^6 + 2*3^8 + O(3^9))*x \ + (1 + 2*3 + 3^4 + 2*3^5 + O(3^6))*x^2 \ + (3 + O(3^2))*x^3 + O(x^4) @eprog\noindent Supersingular example (not checked) \bprog ? E = ellinit("17a1"); ellap(E,3) %1 = 0 ? [M,phi] = msfromell(E,1); ? Mp = mspadicinit(M, 3,7); ? mu = mspadicmoments(Mp, phi,1); ? mspadicseries(mu) %5 = [(2*3^-1 + 1 + 3 + 3^2 + 3^3 + 3^4 + 3^5 + 3^6 + O(3^7)) \ + (2 + 3^3 + O(3^5))*x \ + (1 + 2*3 + O(3^2))*x^2 + O(x^3),\ (3^-1 + 1 + 3 + 3^2 + 3^3 + 3^4 + 3^5 + 3^6 + O(3^7)) \ + (1 + 2*3 + 2*3^2 + 3^3 + 2*3^4 + O(3^5))*x \ + (3^-2 + 3^-1 + O(3^2))*x^2 + O(3^-2)*x^3 + O(x^4)] @eprog\noindent Example with a twist: \bprog ? E = ellinit("11a1"); ? [M,phi] = msfromell(E,1); ? Mp = mspadicinit(M, 3,10); ? mu = mspadicmoments(Mp, phi,5); \\ twist by 5 ? L = mspadicseries(mu) %5 = (2*3^2 + 2*3^4 + 3^5 + 3^6 + 2*3^7 + 2*3^10 + O(3^12)) \ + (2*3^2 + 2*3^6 + 3^7 + 3^8 + O(3^9))*x \ + (3^3 + O(3^6))*x^2 + O(3^2)*x^3 + O(x^4) ? mspadicL(mu) %6 = [2*3^2 + 2*3^4 + 3^5 + 3^6 + 2*3^7 + 2*3^10 + O(3^12)]~ ? ellpadicL(E,3,10,,5) %7 = 2 + 2*3^2 + 3^3 + 2*3^4 + 2*3^5 + 3^6 + 2*3^7 + O(3^10) ? mspadicseries(mu,1) \\ must be 0 %8 = O(3^12) + O(3^9)*x + O(3^6)*x^2 + O(3^2)*x^3 + O(x^4) @eprog pari-2.17.2/src/functions/modular_symbols/mspathlog0000644000175000017500000000255014676526175021144 0ustar billbillFunction: mspathlog Section: modular_symbols C-Name: mspathlog Prototype: GG Help: mspathlog(M,p): M being a full modular symbol space, as given by msinit and p being a path between two elements in P^1(Q), return (p_i) in Z[G] such that p = \sum p_i g_i, and the g_i are fixed Z[G]-generators for Div^0(P^1 Q), see mspathgens. Doc: Let $\Delta_{0}:=\text{Div}^{0}(\P^{1}(\Q))$. Let $M$ being a full modular symbol space, as given by \kbd{msinit}, encoding fixed $\Z[G]$-generators $(g_{i})$ of $\Delta_{0}$ (see \tet{mspathgens}). A path $p=[a,b]$ between two elements in $\P^{1}(\Q)$ corresponds to $[b]-[a]\in \Delta_{0}$. The path extremities $a$ and $b$ may be given as \typ{INT}, \typ{FRAC} or $\kbd{oo} = (1:0)$. Finally, we also allow to input a path as a $2\times 2$ integer matrix, whose first and second column give $a$ and $b$ respectively, with the convention $[x,y]\til = (x:y)$ in $\P^{1}(\Q)$. Returns $(p_{i})$ in $\Z[G]$ such that $p = \sum_{i} p_{i} g_{i}$. \bprog ? M = msinit(2,8); \\ M_8(Gamma_0(2)) ? [g,R] = mspathgens(M); ? g %3 = [[+oo, 0], [0, 1]] ? p = mspathlog(M, [1/2,2/3]); ? p[1] %5 = [[1, 0; 2, 1] 1] ? p[2] %6 = [[1, 0; 0, 1] 1] [[3, -1; 4, -1] 1] ? mspathlog(M, [1,2;2,3]) == p \\ give path via a 2x2 matrix %7 = 1 @eprog\noindent Note that the output depends only on the group $G$, not on the representation $V$. pari-2.17.2/src/functions/modular_symbols/msatkinlehner0000644000175000017500000000153214676526175022011 0ustar billbillFunction: msatkinlehner Section: modular_symbols C-Name: msatkinlehner Prototype: GLDG Help: msatkinlehner(M,Q,{H}): M being a full modular symbol space of level N, as given by msinit, let Q | N, (Q,N/Q) = 1, and let H be a subspace stable under the Atkin-Lehner involution w_Q. Return the matrix of w_Q acting on H (M if omitted). Doc: Let $M$ be a full modular symbol space of level $N$, as given by \kbd{msinit}, let $Q \mid N$, $(Q,N/Q) = 1$, and let $H$ be a subspace stable under the Atkin-Lehner involution $w_{Q}$. Return the matrix of $w_{Q}$ acting on $H$ ($M$ if omitted). \bprog ? M = msinit(36,2); \\ M_2(Gamma_0(36)) ? w = msatkinlehner(M,4); w^2 == 1 %2 = 1 ? #w \\ involution acts on a 13-dimensional space %3 = 13 ? M = msinit(36,2, -1); \\ M_2(Gamma_0(36))^- ? w = msatkinlehner(M,4); w^2 == 1 %5 = 1 ? #w %6 = 4 @eprog pari-2.17.2/src/functions/modular_symbols/mspolygon0000644000175000017500000001352714676526175021203 0ustar billbillFunction: mspolygon Section: modular_symbols C-Name: mspolygon Prototype: GD0,L, Help: mspolygon(M,{flag=0}): M describes a subgroup G of finite index in the modular group PSL2(Z), as given by msinit or a positive integer N (encoding the group G = Gamma0(N)), or by msfarey (arbitrary subgroups). Return an hyperbolic polygon (Farey symbol) attached to G. Binary digits of flag mean: 1=normalized polygon, 2=also add graphical representations. Doc: $M$ describes a subgroup $G$ of finite index in the modular group $\text{PSL}_{2}(\Z)$, as given by \kbd{msinit} or a positive integer $N$ (encoding the group $G = \Gamma_{0}(N)$), or by \kbd{msfarey} (arbitrary subgroup). Return an hyperbolic polygon (Farey symbol) attached to $G$. More precisely: \item Its vertices are an ordered list in $\P^{1}(\Q)$ and contain a representatives of all cusps. \item Its edges are hyperbolic arcs joining two consecutive vertices; each edge $e$ is labelled by an integer $\mu(e) \in \{\infty,2,3\}$. \item Given a path $(a,b)$ between two elements of $\P^{1}(\Q)$, let $\overline{(a,b)} = (b,a)$ be the opposite path. There is an involution $e \to e^{*}$ on the edges. We have $\mu(e) = \infty$ if and only if $e\neq e^{*}$; when $\mu(e) \neq 3$, $e$ is $G$-equivalent to $\overline{e^{*}}$, i.e. there exists $\gamma_{e} \in G$ such that $e = \gamma_{e} \overline{e^{*}}$; if $\mu(e)=3$ there exists $\gamma_{e} \in G$ of order $3$ such that the hyperbolic triangle $(e, \gamma_{e} e, \gamma_{e}^{2} e)$ is invariant by $\gamma_{e}$. In all cases, to each edge we have attached $\gamma_{e} \in G$ of order $\mu(e)$. \noindent The polygon is given by a triple $[E, A, g]$ \item The list $E$ of its consecutive edges as matrices in $M_{2}(\Z)$. \item The permutation $A$ attached to the involution: if $e = E[i]$ is the $i$-th edge, then \kbd{A[i]} is the index of $e^{*}$ in $E$. \item The list $g$ of pairing matrices $\gamma_{e}$. Remark that $\gamma_{e^{*}}=\gamma_{e}^{-1}$ if $\mu(e) \neq 3$, i.e., $g[i]^{-1} = g[A[i]]$ whenever $i\neq A[i]$ ($\mu(g[i]) = 1$) or $\mu(g[i]) = 2$ ($g[i]^{2} = 1$). Modulo these trivial relations, the pairing matrices form a system of independant generators of $G$. Note that $\gamma_{e}$ is elliptic if and only if $e^{*} = e$. \noindent The above data yields a fundamental domain for $G$ acting on Poincar\'e's half-plane: take the convex hull of the polygon defined by \item The edges in $E$ such that $e \neq e^{*}$ or $e^{*}=e$, where the pairing matrix $\gamma_{e}$ has order $2$; \item The edges $(r,t)$ and $(t,s)$ where the edge $e = (r,s) \in E$ is such that $e = e^{*}$ and $\gamma_{e}$ has order $3$ and the triangle $(r,t,s)$ is the image of $(0,\exp(2i\pi/3), \infty)$ by some element of $PSL_{2}(\Q)$ formed around the edge. Binary digits of flag mean: 1: return a normalized hyperbolic polygon if set, else a polygon with unimodular edges (matrices of determinant $1$). A polygon is normalized in the sense of compact orientable surfaces if the distance $d(a,a^{*})$ between an edge $a$ and its image by the involution $a^{*}$ is less than 2, with equality if and only if $a$ is \emph{linked} with another edge $b$ ($a$, $b$, $a^{*}$ et $b^{*}$ appear consecutively in $E$ up to cyclic permutation). In particular, the vertices of all edges such that that $d(a,a^{*}) \neq 1$ (distance is 0 or 2) are all equivalent to $0$ modulo $G$. The external vertices of $a a^{*}$ such that $d(a,a^{*}) = 1$ are also equivalent to $0$; the internal vertices $a\cap a^{*}$ (a single point), together with $0$, form a system of representatives of the cusps of $G\bs \P^{1}(\Q)$. This is useful to compute the homology group $H_{1}(G,\Z)$ as it gives a symplectic basis for the intersection pairing. In this case, the number of parabolic matrices (trace 2) in the system of generators $G$ is $2(t-1)$, where $t$ is the number of non equivalent cusps for $G$. This is currently only implemented for $G = \Gamma_{0}(N)$. 2: add graphical representations (in LaTeX form) for the hyperbolic polygon in Poincar\'e's half-space and the involution $a\to a^{*}$ of the Farey symbol. The corresponding character strings can be included in a LaTeX document provided the preamble contains \kbd{\bs usepackage\obr tikz\cbr}. \bprog ? [V,A,g] = mspolygon(3); ? V %2 = [[-1, 1; -1, 0], [1, 0; 0, 1], [0, 1; -1, 1]] ? A %3 = Vecsmall([2, 1, 3]) ? g %4 = [[-1, -1; 0, -1], [1, -1; 0, 1], [1, -1; 3, -2]] ? [V,A,g, D1,D2] = mspolygon(11,2); \\ D1 and D2 contains pictures ? {write("F.tex", "\\documentclass{article}\\usepackage{tikz}\\begin{document}" D1, "\n", D2, "\\end{document}");} ? [V1,A1] = mspolygon(6,1); \\ normalized ? V1 %8 = [[-1, 1; -1, 0], [1, 0; 0, 1], [0, 1; -1, 3], [1, -2; 3, -5], [-2, 1; -5, 2], [1, -1; 2, -1]] ? A1 %9 = Vecsmall([2, 1, 4, 3, 6, 5]) ? [V0,A0] = mspolygon(6); \\ not normalized V[3]^* = V[6], d(V[3],V[6]) = 3 ? A0 %11 = Vecsmall([2, 1, 6, 5, 4, 3]) ? [V,A] = mspolygon(14, 1); ? A %13 = Vecsmall([2, 1, 4, 3, 6, 5, 9, 10, 7, 8]) @eprog One can see from this last example that the (normalized) polygon has the form $$(a_{1}, a_{1}^{*}, a_{2}, a_{2}^{*}, a_{3}, a_{3}^{*}, a_{4}, a_{5}, a_{4}^{*}, a_{5}^{*}),$$ that $X_{0}(14)$ is of genus 1 (in general the genus is the number of blocks of the form $aba^{*}b^{*}$), has no elliptic points ($A$ has no fixed point) and 4 cusps (number of blocks of the form $aa^{*}$ plus 1). The vertices of edges $a_{4}$ and $a_{5}$ all project to $0$ in $X_{0}(14)$: the paths $a_{4}$ and $a_{5}$ project as loops in $X_{0}(14)$ and give a symplectic basis of the homology $H_{1}(X_{0}(14),\Z)$. \bprog ? [V,A] = mspolygon(15); ? apply(matdet, V) \\ all unimodular %2 = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] ? [V,A] = mspolygon(15,1); ? apply(matdet, V) \\ normalized polygon but no longer unimodular edges %4 = [1, 1, 1, 1, 2, 2, 47, 11, 47, 11] @eprog pari-2.17.2/src/functions/modular_symbols/msgetsign0000644000175000017500000000060514567450071021133 0ustar billbillFunction: msgetsign Section: modular_symbols C-Name: msgetsign Prototype: lG Help: msgetsign(M): M being a full modular symbol space, as given by msinit, return its sign. Doc: $M$ being a full modular symbol space, as given by \kbd{msinit}, return its sign: $\pm1$ or 0 (unset). \bprog ? M = msinit(11,4, 1); ? msgetsign(M) %2 = 1 ? M = msinit(11,4); ? msgetsign(M) %4 = 0 @eprog pari-2.17.2/src/functions/modular_symbols/msdim0000644000175000017500000000135414567450071020246 0ustar billbillFunction: msdim Section: modular_symbols C-Name: msdim Prototype: lG Help: msdim(M): M being a modular symbol space or subspace, return its dimension as a Q-vector space. Doc: $M$ being a full modular symbol space or subspace, for instance as given by \kbd{msinit} or \kbd{mscuspidal}, return its dimension as a $\Q$-vector space. \bprog ? M = msinit(11,4); msdim(M) %1 = 6 ? M = msinit(11,4,1); msdim(M) %2 = 4 \\ dimension of the '+' part ? [S,E] = mscuspidal(M,1); ? [msdim(S), msdim(E)] %4 = [2, 2] @eprog\noindent Note that \kbd{mfdim([N,k])} is going to be much faster if you only need the dimension of the space and not really to work with it. This function is only useful to quickly check the dimension of an existing space. pari-2.17.2/src/functions/modular_forms/0000755000175000017500000000000014760315601016637 5ustar billbillpari-2.17.2/src/functions/modular_forms/mfgaloisprojrep0000644000175000017500000000301214676526175022001 0ustar billbillFunction: mfgaloisprojrep Section: modular_forms C-Name: mfgaloisprojrep Prototype: GGp Help: mfgaloisprojrep(mf,F): mf being an mf output by mfinit in weight 1, and F an eigenform, returns a polynomial defining the field fixed by the kernel of the projective representation associated to F. Doc: \var{mf} being an \kbd{mf} output by \kbd{mfinit} in weight $1$, return a polynomial defining the field fixed by the kernel of the projective Artin representation attached to \var{F} (by Deligne--Serre). Currently only implemented for projective images $A_{4}$, $A_{5}$ and $S_{4}$. The type $A_{5}$ requires the \kbd{nflistdata} package to be installed. \bprog \\ A4 example ? mf = mfinit([4*31,1,Mod(87,124)],0); ? F = mfeigenbasis(mf)[1]; ? mfgaloistype(mf,F) %3 = -12 ? pol = mfgaloisprojrep(mf,F) %4 = x^12 + 68*x^10 + 4808*x^8 + ... + 4096 ? G = galoisinit(pol); galoisidentify(G) %5 = [12,3] \\A4 ? pol4 = polredbest(galoisfixedfield(G,G.gen[3], 1)) %6 = x^4 + 7*x^2 - 2*x + 14 ? polgalois(pol4) %7 = [12, 1, 1, "A4"] ? factor(nfdisc(pol4)) %8 = [ 2 4] [31 2] \\ S4 example ? mf = mfinit([4*37,1,Mod(105,148)],0); ? F = mfeigenbasis(mf)[1]; ? mfgaloistype(mf,F) %11 = -24 ? pol = mfgaloisprojrep(mf,F) %12 = x^24 + 24*x^22 + 256*x^20 + ... + 255488256 ? G = galoisinit(pol); galoisidentify(G) %13 = [24, 12] \\S4 ? pol4 = polredbest(galoisfixedfield(G,G.gen[3..4], 1)) %14 = x^4 - x^3 + 5*x^2 - 7*x + 12 ? polgalois(pol4) %15 = [24, -1, 1, "S4"] ? factor(nfdisc(pol4)) %16 = [ 2 2] [37 3] @eprog pari-2.17.2/src/functions/modular_forms/mfkohneneigenbasis0000644000175000017500000000251314567450071022430 0ustar billbillFunction: mfkohneneigenbasis Section: modular_forms C-Name: mfkohneneigenbasis Prototype: GG Help: mfkohneneigenbasis(mf,bij): mf being a cuspidal space of half-integral weight k >= 3/2 and bij being the output of mfkohnenbijection(mf), outputs a 3-component vector [mf0,BNEW,BEIGEN], where BNEW and BEIGEN are two matrices whose columns are the coefficients of a basis of the Kohnen new space and of the eigenforms on the basis of mf respectively, and mf0 is the corresponding new space of integral weight 2k - 1. Doc: \kbd{mf} being a cuspidal space of half-integral weight $k\ge3/2$ and \kbd{bij} being the output of \kbd{mfkohnenbijection(mf)}, outputs a $3$-component vector \kbd{[mf0,BNEW,BEIGEN]}, where \kbd{BNEW} and \kbd{BEIGEN} are two matrices whose columns are the coefficients of a basis of the Kohnen new space and of the eigenforms on the basis of \kbd{mf} respectively, and \kbd{mf0} is the corresponding new space of integral weight $2k-1$. \bprog ? mf=mfinit([44,5/2],1);bij=mfkohnenbijection(mf); ? [mf0,BN,BE]=mfkohneneigenbasis(mf,bij); ? BN~ %2 = [2 0 0 -2 2 0 -8] [2 0 0 4 14 0 -32] ? BE~ %3 = [1 0 0 Mod(y-1, y^2-3) Mod(2*y+1, y^2-3) 0 Mod(-4*y-4, y^2-3)] ? lift(mfcoefs(mf,20)*BE[,1]) %4 = [0, 1, 0, 0, y - 1, 2*y + 1, 0, 0, 0, -4*y - 4, 0, 0,\ -5*y + 3, 0, 0, 0, -6, 0, 0, 0, 7*y + 9]~ @eprog pari-2.17.2/src/functions/modular_forms/mfbracket0000644000175000017500000000076414567450071020535 0ustar billbillFunction: mfbracket Section: modular_forms C-Name: mfbracket Prototype: GGD0,L, Help: mfbracket(F,G,{m=0}): compute the m-th Rankin-Cohen bracket of the generalized modular forms F and G. Doc: compute the $m$-th Rankin--Cohen bracket of the generalized modular forms $F$ and $G$. \bprog ? E4 = mfEk(4); E6 = mfEk(6); ? D1 = mfbracket(E4,E4,2); mfcoefs(D1,5)/4800 %2 = [0, 1, -24, 252, -1472, 4830] ? D2 = mfbracket(E4,E6,1); mfcoefs(D2,10)/(-3456) %3 = [0, 1, -24, 252, -1472, 4830] @eprog pari-2.17.2/src/functions/modular_forms/mfisequal0000644000175000017500000000106414567450071020557 0ustar billbillFunction: mfisequal Section: modular_forms C-Name: mfisequal Prototype: lGGD0,L, Help: mfisequal(F,G,{lim=0}): Checks whether the modular forms F and G are equal. If lim is nonzero, only check equality of the first lim+1 Fourier coefficients. Doc: Checks whether the modular forms $F$ and $G$ are equal. If \kbd{lim} is nonzero, only check equality of the first $lim+1$ Fourier coefficients and the function then also applies to generalized modular forms. \bprog ? D = mfDelta(); F = mfderiv(D); ? G = mfmul(mfEk(2), D); ? mfisequal(F, G) %2 = 1 @eprog pari-2.17.2/src/functions/modular_forms/HEADER0000644000175000017500000000701514676526175017535 0ustar billbillFunction: _header_modular_forms Class: header Section: modular_forms Doc: \section{Modular forms} This section describes routines for working with modular forms and modular form spaces. \subsec{Modular form spaces} %GPHELPskip These structures are initialized by the \kbd{mfinit} command; supported modular form \emph{spaces} with corresponding flags are the following: \item The full modular form space $M_{k}(\Gamma_{0}(N),\chi)$, where $k$ is an integer or a half-integer and $\chi$ a Dirichlet character modulo $N$ ($\fl=4$, the default). \item The cuspidal space $S_{k}(\Gamma_{0}(N),\chi)$ ($\fl=1$). \item The Eisenstein space ${\cal E}_{k}(\Gamma_{0}(N),\chi)$ ($\fl=3$), so that $M_{k}={\cal E}_{k}\oplus S_{k}$. \item The new space $S_{k}^{\text{new}}(\Gamma_{0}(N),\chi)$ ($\fl=0$). \item The old space $S_{k}^{\text{old}}(\Gamma_{0}(N),\chi)$ ($\fl=2$), so that $S_{k}=S_{k}^{\text{new}}\oplus S_{k}^{\text{old}}$. These resulting \kbd{mf} structure contains a basis of modular forms, which is accessed by the function \kbd{mfbasis}; the elements of this basis have Fourier coefficients in the cyclotomic field $\Q(\chi)$. These coefficients are given algebraically, as rational numbers or \typ{POLMOD}s. The member function \kbd{mf.mod} recovers the modulus used to define $\Q(\chi)$, which is a cyclotomic polynomial $\Phi_{n}(t)$. When needed, the elements of $\Q(\chi)$ are considered to be canonically embedded into $\C$ via $\kbd{Mod}(t,\Phi_{n}(t)) \mapsto \exp(2i\pi/n)$. The basis of eigenforms for the new space is obtained by the function \kbd{mfeigenbasis}: the elements of this basis now have Fourier coefficients in a relative field extension of $\Q(\chi)$. Note that if the space is larger than the new space (i.e. is the cuspidal or full space) we nevertheless obtain only the eigenbasis for the new space. \subsec{Generalized modular forms} %GPHELPskip A modular form is represented in a special internal format giving the possibility to compute an arbitrary number of terms of its Fourier coefficients at infinity $[a(0),a(1),...,a(n)]$ using the function \kbd{mfcoefs}. These coefficients are given algebraically, as rational numbers or \typ{POLMOD}s. The member function \kbd{f.mod} recovers the modulus used in the coefficients of $f$, which will be the same as for $k = \Q(\chi)$ (a cyclotomic polynomial), or define a number field extension $K/k$. Modular forms are obtained either directly from other mathematical objects, e.g., elliptic curves, or by a specific formula, e.g., Eisenstein series or Ramanujan's Delta function, or by applying standard operators to existing forms (Hecke operators, Rankin--Cohen brackets, \dots). A function \kbd{mfparams} is provided so that one can recover the level, weight, character and field of definition corresponding to a given modular form. A number of creation functions and operations are provided. It is however important to note that strictly speaking some of these operations create objects which are \emph{not} modular forms: typical examples are derivation or integration of modular forms, the Eisenstein series $E_{2}$, eta quotients, or quotients of modular forms. These objects are nonetheless very important in the theory, so are not considered as errors; however the user must be aware that no attempt is made to check that the objects that he handles are really modular. When the documentation of a function does not state that it applies to generalized modular forms, then the output is undefined if the input is not a true modular form. pari-2.17.2/src/functions/modular_forms/mfslashexpansion0000644000175000017500000000770314676526175022173 0ustar billbillFunction: mfslashexpansion Section: modular_forms C-Name: mfslashexpansion Prototype: GGGLLD&p Help: mfslashexpansion(mf,f,g,n,flrat,{¶ms}): g being in M_2^+(Q), computes the Fourier expansion of f|_k g to n terms. f must belong to the space mf. If params is given, it is set to the parameters [alpha,w,A]. If flrat is 1, the program tries to rationalize the expression; if flag is 0, it does not. Doc: let \var{mf} be a modular form space in level $N$, $f$ a modular form belonging to \var{mf} and let $g$ be in $M_{2}^{+}(Q)$. This function computes the Fourier expansion of $f|_{k} g$ to $n$ terms. We first describe the behaviour when \kbd{flrat} is 0: the result is a vector $v$ of floating point complex numbers such that $$f|_{k} g(\tau) = q^{\alpha} \sum_{m\ge0} v[m+1] q^{m/w},$$ where $q = e(\tau)$, $w$ is the width of the cusp $g(i\infty)$ (namely $(N/(c^{2},N)$ if $g$ is integral) and $\alpha$ is a rational number. If \kbd{params} is given, it is set to the parameters $[\alpha,w, \kbd{matid}(2)]$. If \kbd{flrat} is 1, the program tries to rationalize the expression, i.e., to express the coefficients as rational numbers or polmods. We write $g = \lambda \cdot M \cdot A$ where $\lambda \in \Q^{*}$, $M\in \text{SL}_{2}(\Z)$ and $A = [a,b;0,d]$ is upper triangular, integral and primitive with $a > 0$, $d > 0$ and $0 \leq b < d$. Let $\alpha$ and $w$ by the parameters attached to the expansion of $F := f |_{k} M$ as above, i.e. $$ F(\tau) = q^{\alpha} \sum_{m\ge0} v[m+1] q^{m/w}.$$ The function returns the expansion $v$ of $F = f |_{k} M$ and sets the parameters to $[\alpha, w, A]$. Finally, the desired expansion is $(a/d)^{k/2} F(\tau + b/d)$. The latter is identical to the returned expansion when $A$ is the identity, i.e. when $g\in \text{PSL}_{2}(\Z)$. If this is not the case, the expansion differs from $v$ by the multiplicative constant $(a/d)^{k/2} e(\alpha b/(dw))$ and a twist by a root of unity $q^{1/w} \to e(b/(dw)) q^{1/w}$. The complications introduced by this extra matrix $A$ allow to recognize the coefficients in a much smaller cyclotomic field, hence to obtain a simpler description overall. (Note that this rationalization step may result in an error if the program cannot perform it.) \bprog ? mf = mfinit([32,4],0); f = mfbasis(mf)[1]; ? mfcoefs(f, 10) %2 = [0, 3, 0, 0, 0, 2, 0, 0, 0, 47, 0] ? mfatk = mfatkininit(mf,32); mfcoefs(mfatkin(mfatk,f),10) / mfatk[3] %3 = [0, 1, 0, 16, 0, 22, 0, 32, 0, -27, 0] ? mfatk[3] \\ here normalizing constant C = 1, but need in general %4 = 1 ? mfslashexpansion(mf,f,[0,-1;1,0],10,1,¶ms) * 32^(4/2) %5 = [0, 1, 0, 16, 0, 22, 0, 32, 0, -27, 0] ? params %6 = [0, 32, [1, 0; 0, 1]] ? mf = mfinit([12,8],0); f = mfbasis(mf)[1]; ? mfslashexpansion(mf,f,[1,0;2,1],7,0) %7 = [0, 0, 0, 0.6666666... + 0.E-38*I, 0, -3.999999... + 6.92820...*I, 0,\ -11.99999999... - 20.78460969...*I] ? mfslashexpansion(mf,f,[1,0;2,1],7,1, ¶ms) %8 = [0, 0, 0, 2/3, 0, Mod(8*t, t^2+t+1), 0, Mod(-24*t-24, t^2+t+1)] ? params %9 = [0, 3, [1, 0; 0, 1]] @eprog If $[\Q(f):\Q(\chi)]>1$, the coefficients may be polynomials in $y$, where $y$ is any root of the polynomial giving the field of definition of $f$ (\kbd{f.mod} or \kbd{mfparams(f)[4]}). \bprog ? mf=mfinit([23,2],0);f=mfeigenbasis(mf)[1]; ? mfcoefs(f,5) %1 = [Mod(0, y^2 - y - 1), Mod(1, y^2 - y - 1), Mod(-y, y^2 - y - 1),\ Mod(2*y - 1, y^2 - y - 1), Mod(y - 1, y^2 - y - 1), Mod(-2*y, y^2 - y - 1)] ? mfslashexpansion(mf,f,[1,0;0,1],5,1) %2 = [0, 1, -y, 2*y - 1, y - 1, -2*y] ? mfslashexpansion(mf,f,[0,-1;1,0],5,1) %3 = [0, -1/23, 1/23*y, -2/23*y + 1/23, -1/23*y + 1/23, 2/23*y] @eprog \misctitle{Caveat} In half-integral weight, we \emph{define} the ``slash'' operation as $$(f |_{k} g)(\tau) := \big((c \tau + d)^{-1/2}\big)^{2k} f( g\cdot \tau),$$ with the principal determination of the square root. In particular, the standard cocycle condition is no longer satisfied and we only have $f | (gg') = \pm (f | g) | g'$. pari-2.17.2/src/functions/modular_forms/mfshimura0000644000175000017500000000256714676526175020607 0ustar billbillFunction: mfshimura Section: modular_forms C-Name: mfshimura Prototype: GGD1,L, Help: mfshimura(mf,F,{D=1}): F being a modular form of half-integral weight k >= 3/2 and D a positive squarefree integer, computes the Shimura lift G of weight 2k-1 corresponding to D. This function returns [mf2,G,v], where mf2 is a modular form space containing G, and v the vector of coefficients of G on mf. Doc: $F$ being a modular form of half-integral weight $k\geq 3/2$ and $D$ a positive squarefree integer, returns the Shimura lift $G$ of weight $2k-1$ corresponding to $D$. This function returns $[\var{mf2},G,v]$ where \var{mf2} is a modular form space containing $G$ and $v$ expresses $G$ in terms of \kbd{mfbasis}$(\var{mf2})$; so that $G$ is \kbd{mflinear}$(\var{mf2},v)$. \bprog ? F = mfpow(mfTheta(), 7); mf = mfinit(F); ? [mf2, G, v] = mfshimura(mf, F, 3); mfcoefs(G,5) %2 = [-5/9, 280, 9240, 68320, 295960, 875280] ? mfparams(G) \\ the level may be lower than expected %3 = [1, 6, 1, y, t - 1] ? mfparams(mf2) %4 = [2, 6, 1, 4, t - 1] ? v %5 = [280, 0]~ ? mfcoefs(mf2, 5) %6 = [-1/504 -1/504] [ 1 0] [ 33 1] [ 244 0] [ 1057 33] [ 3126 0] ? mf = mfinit([60,5/2],1); F = mflinear(mf,mfkohnenbasis(mf)[,1]); ? mfparams(mfshimura(mf,F)[2]) %8 = [15, 4, 1, y, t - 1] ? mfparams(mfshimura(mf,F,6)[2]) %9 = [15, 4, 1, y, t - 1] @eprog pari-2.17.2/src/functions/modular_forms/mfeval0000644000175000017500000000313314676526175020054 0ustar billbillFunction: mfeval Section: modular_forms C-Name: mfeval Prototype: GGGb Help: mfeval(mf,F,vtau): computes the numerical value of the modular form F at the point vtau or the vector vtau of points in the completed upper-half plane. Doc: Computes the numerical value of the modular form $F$, belonging to \var{mf}, at the complex number \kbd{vtau} or the vector \kbd{vtau} of complex numbers in the completed upper-half plane. The result is given with absolute error less than $2^{-B}$, where $B = \text{realbitprecision}$. If the field of definition $\Q(F)$ is larger than $\Q(\chi)$ then $F$ may be embedded into $\C$ in $d=[\Q(F):\Q(\chi)]$ ways, in which case a vector of the $d$ results is returned. \bprog ? mf = mfinit([11,2],0); F = mfbasis(mf)[1]; mfparams(F) %1 = [11, 2, 1, y, t-1] \\ Q(F) = Q(chi) = Q ? mfeval(mf,F,I/2) %2 = 0.039405471130100890402470386372028382117 ? mf = mfinit([35,2],0); F = mfeigenbasis(mf)[2]; mfparams(F) %3 = [35, 2, 1, y^2 - y - 4, t - 1] \\ [Q(F) : Q(chi)] = 2 ? mfeval(mf,F,I/2) %4 = [0.045..., 0.0385...] \\ sigma_1(F) and sigma_2(F) at I/2 ? mf = mfinit([12,4],1); F = mfbasis(mf)[1]; ? mfeval(mf, F, 0.318+10^(-7)*I) %6 = 3.379... E-21 + 6.531... E-21*I \\ instantaneous ! @eprog\noindent In order to maximize the imaginary part of the argument, the function computes $(f \mid_{k} \gamma)(\gamma^{-1}\cdot\tau)$ for a suitable $\gamma$ not necessarily in $\Gamma_{0}(N)$ (in which case $f \mid \gamma$ is evaluated using \kbd{mfslashexpansion}). \bprog ? T = mfTheta(); mf = mfinit(T); mfeval(mf,T,[0,1/2,1,oo]) %1 = [1/2 - 1/2*I, 0, 1/2 - 1/2*I, 1] @eprog pari-2.17.2/src/functions/modular_forms/mfatkineigenvalues0000644000175000017500000000304714676526175022467 0ustar billbillFunction: mfatkineigenvalues Section: modular_forms C-Name: mfatkineigenvalues Prototype: GLp Help: mfatkineigenvalues(mf,Q): given a modular form space mf and a primitive divisor Q of the level of mf, outputs the corresponding Atkin-Lehner eigenvalues on the new space, grouped by orbit. Doc: Given a modular form space \kbd{mf} of integral weight $k$ and a primitive divisor $Q$ of the level $N$ of \kbd{mf}, outputs the Atkin--Lehner eigenvalues of $w_{Q}$ on the new space, grouped by orbit. If the Nebentypus $\chi$ of \kbd{mf} is a (trivial or) quadratic character defined modulo $N/Q$, the result is rounded and the eigenvalues are $\pm i^{k}$. \bprog ? mf = mfinit([35,2],0); mffields(mf) %1 = [y, y^2 - y - 4] \\ two orbits, dimension 1 and 2 ? mfatkineigenvalues(mf,5) %2 = [[1], [-1, -1]] ? mf = mfinit([12,7,Mod(3,4)],0); ? mfatkineigenvalues(mf,3) %4 = [[I, -I, -I, I, I, -I]] \\ one orbit @eprog To obtain the eigenvalues on a larger space than the new space, e.g., the full space, you can directly call \kbd{[mfB,M,C]=mfatkininit} and compute the eigenvalues as the roots of the characteristic polynomial of $M/C$, by dividing the roots of \kbd{charpoly(M)} by $C$. Note that the characteristic polynomial is computed exactly since $M$ has coefficients in $\Q(\chi)$, whereas $C$ may be given by a complex number. If the coefficients of the characteristic polynomial are polmods modulo $T$ they must be embedded to $\C$ first using \kbd{subst(lift(), t, exp(2*I*Pi/n))}, when $T$ is \kbd{poliscyclo(n)}; note that $T = \kbd{mf.mod}$. pari-2.17.2/src/functions/modular_forms/mfcuspwidth0000644000175000017500000000104314676526175021135 0ustar billbillFunction: mfcuspwidth Section: modular_forms C-Name: mfcuspwidth Prototype: lGG Help: mfcuspwidth(N,cusp): width of cusp in Gamma_0(N). Doc: width of \kbd{cusp} in $\Gamma_{0}(N)$. \bprog ? mfcusps(12) %1 = [0, 1/2, 1/3, 1/4, 1/6, 1/12] ? [mfcuspwidth(12,c) | c <- mfcusps(12)] %2 = [12, 3, 4, 3, 1, 1] ? mfcuspwidth(12, oo) %3 = 1 @eprog\noindent We also allow the argument $N$ to be a modular form space, in which case it is replaced by the level of the space: \bprog ? M = mfinit([4, 12, 1], 0); mfcuspwidth(M, 1/2) %4 = 1 @eprog pari-2.17.2/src/functions/modular_forms/mffromlfun0000644000175000017500000000351214567450071020744 0ustar billbillFunction: mffromlfun Section: modular_forms C-Name: mffromlfun Prototype: Gp Help: mffromlfun(L): L being an L-function representing a self-dual modular form, return [NK,space,v] where mf=mfinit(NK,space) contains the form and mftobasis(mf, v) containing it and v is mftobasis(mf,f). Doc: Let $L$ being an $L$-function in any of the \kbd{lfun} formats representing a self-dual modular form (for instance an eigenform). Return \kbd{[NK,space,v]} when \kbd{mf = mfinit(NK,space)} is the modular form space containing the form and \kbd{mftobasis(mf, v)} will represent it on the space basis. If $L$ has rational coefficients, this will be enough to recognize the modular form in \var{mf}: \bprog ? L = lfuncreate(x^2+1); ? lfunan(L,10) %2 = [1, 1, 0, 1, 2, 0, 0, 1, 1, 2] ? [NK,space,v] = mffromlfun(L); NK %4 = [4, 1, -4] ? mf=mfinit(NK,space); w = mftobasis(mf,v) %5 = [1.0000000000000000000000000000000000000]~ ? [f] = mfbasis(mf); mfcoefs(f,10) \\ includes a_0 ! %6 = [1/4, 1, 1, 0, 1, 2, 0, 0, 1, 1, 2] @eprog If $L$ has inexact complex coefficients, one can for instance compute an eigenbasis for \var{mf} and check whether one of the attached $L$-function is reasonably close to $L$. In the example, we cheat by producing the $L$ function from an eigenform in a known space, but the function does not use this information: \bprog ? mf = mfinit([32,6,Mod(5,32)],0); ? [poldegree(K) | K<-mffields(mf)] %2 = [19] \\ one orbit, [Q(F) : Q(chi)] = 19 ? L = lfunmf(mf)[1][1]; \\ one of the 19 L-functions attached to F ? lfunan(L,3) %4 = [1, 5.654... - 0.1812...*I, -7.876... - 19.02...*I] ? [NK,space,v] = mffromlfun(L); NK %5 = [32, 6, Mod(5, 32)] ? vL = concat(lfunmf(mf)); \\ L functions for all cuspidal eigenforms ? an = lfunan(L,10); ? for (i = 1, #vL, if (normlp(lfunan(vL[i],10) - an, oo) < 1e-10, print(i))); 1 @eprog pari-2.17.2/src/functions/modular_forms/mfmul0000644000175000017500000000056314567450071017714 0ustar billbillFunction: mfmul Section: modular_forms C-Name: mfmul Prototype: GG Help: mfmul(F,G): Multiply the two forms F and G. Doc: Multiply the two generalized modular forms $F$ and $G$. \bprog ? E4 = mfEk(4); G = mfmul(mfmul(E4,E4),E4); ? mfcoefs(G, 4) %2 = [1, 720, 179280, 16954560, 396974160] ? mfcoefs(mfpow(E4,3), 4) %3 = [1, 720, 179280, 16954560, 396974160] @eprog pari-2.17.2/src/functions/modular_forms/mfsymboleval0000644000175000017500000000560714676526175021312 0ustar billbillFunction: mfsymboleval Section: modular_forms C-Name: mfsymboleval Prototype: GGDGb Help: mfsymboleval(fs,path,{ga=id}): evaluation of the modular symbol fs output by mfsymbol on the given path, where path is either a vector [s1,s2] or an integral matrix [a,b;c,d] representing the path [a/c,b/d]. In both cases, s1 or s2 (or a/c or b/d) can also be elements of the upper half-plane. The result is the polynomial equal to the integral between s1 and s2 of (X-tau)^{k-2}F(tau). If ga in GL_2+(Q) is given, replace F by F|_k ga. If the integral diverges, the result will be a rational function. Doc: evaluation of the modular symbol $fs$ (corresponding to the modular form $f$) output by \kbd{mfsymbol} on the given path \kbd{path}, where \kbd{path} is either a vector $[s_{1},s_{2}]$ or an integral matrix $[a,b;c,d]$ representing the path $[a/c,b/d]$. In both cases $s_{1}$ or $s_{2}$ (or $a/c$ or $b/d$) can also be elements of the upper half-plane. To avoid possibly lengthy \kbd{mfsymbol} computations, the program also accepts $fs$ of the form \kbd{[mf,F]}, but in that case $s_{1}$ and $s_{2}$ are limited to \kbd{oo} and elements of the upper half-plane. The result is the polynomial equal to $\int_{s_{1}}^{s_{2}}(X-\tau)^{k-2}F(\tau)\,d\tau$, the integral being computed along a geodesic joining $s_{1}$ and $s_{2}$. If \kbd{ga} in $GL_{2}^{+}(\Q)$ is given, replace $F$ by $F|_{k}\gamma$. Note that if the integral diverges, the result will be a rational function. If the field of definition $\Q(f)$ is larger than $\Q(\chi)$ then $f$ can be embedded into $\C$ in $d=[\Q(f):\Q(\chi)]$ ways, in which case a vector of the $d$ results is returned. \bprog ? mf=mfinit([35,2],1);f=mfbasis(mf)[1];fs=mfsymbol(mf,f); ? mfsymboleval(fs,[0,oo]) %1 = 0.31404011074188471664161704390256378537*I ? mfsymboleval(fs,[1,3;2,5]) %2 = -0.1429696291... - 0.2619975641...*I ? mfsymboleval(fs,[I,2*I]) %3 = 0.00088969563028739893631700037491116258378*I ? E2=mfEk(2);E22=mflinear([E2,mfbd(E2,2)],[1,-2]);mf=mfinit(E22); ? E2S = mfsymbol(mf,E22); ? mfsymboleval(E2S,[0,1]) %6 = (-1.00000...*x^2 + 1.00000...*x - 0.50000...)/(x^2 - x) @eprog The rational function which is given in case the integral diverges is easy to interpret. For instance: \bprog ? E4=mfEk(4);mf=mfinit(E4);ES=mfsymbol(mf,E4); ? mfsymboleval(ES,[I,oo]) %2 = 1/3*x^3 - 0.928067...*I*x^2 - 0.833333...*x + 0.234978...*I ? mfsymboleval(ES,[0,I]) %3 = (-0.234978...*I*x^3 - 0.833333...*x^2 + 0.928067...*I*x + 0.333333...)/x @eprog\noindent \kbd{mfsymboleval(ES,[a,oo])} is the limit as $T\to\infty$ of $$\int_{a}^{iT}(X-\tau)^{k-2}F(\tau)\,d\tau + a(0)(X-iT)^{k-1}/(k-1)\;,$$ where $a(0)$ is the $0$th coefficient of $F$ at infinity. Similarly, \kbd{mfsymboleval(ES,[0,a])} is the limit as $T\to\infty$ of $$\int_{i/T}^{a}(X-\tau)^{k-2}F(\tau)\,d\tau+b(0)(1+iTX)^{k-1}/(k-1)\;,$$ where $b(0)$ is the $0$th coefficient of $F|_{k} S$ at infinity. pari-2.17.2/src/functions/modular_forms/mfeigensearch0000644000175000017500000000365014676526175021406 0ustar billbillFunction: mfeigensearch Section: modular_forms C-Name: mfeigensearch Prototype: GDG Help: mfeigensearch(NK,{AP}): search for normalized rational eigen cuspforms with quadratic characters given a few initial coefficients. The meaning of the parameters is as follows: NK is of the form [N,k]: search given level N, weight k and quadratic character; note that the character is uniquely determined by (N,k). The level N can be replaced by a vector of allowed levels. AP is the search criterion, which can be omitted: a list of pairs [...,[p,a_p],...], where a_p is either a t_INT (exact match) or a t_INTMOD (match modulo the given integer). The result is a vector of newforms matching the search criteria, sorted by increasing level. Doc: search for a normalized rational eigen cuspform with quadratic character given restrictions on a few initial coefficients. The meaning of the parameters is as follows: \item \kbd{NK} governs the limits of the search: it is of the form $[N,k]$: search for given level $N$, weight $k$ and quadratic character; note that the character $(D/.)$ is uniquely determined by $(N,k)$. The level $N$ can be replaced by a vector of allowed levels. \item \kbd{AP} is the search criterion, which can be omitted: a list of pairs $[\ldots, [p,a_{p}], \ldots]$, where $p$ is a prime number and $a_{p}$ is either a \typ{INT} (the $p$-th Fourier coefficient must match $a_{p}$ exactly) or a \typ{INTMOD} \kbd{Mod}$(a,b)$ (the $p$-th coefficient must be congruent to $a$ modulo $b$). The result is a vector of newforms $f$ matching the search criteria, sorted by increasing level then increasing $|D|$. \bprog ? #mfeigensearch([[1..80],2], [[2,2],[3,-1]]) %1 = 1 ? #mfeigensearch([[1..80],2], [[2,2],[5,2]]) %2 = 1 ? v = mfeigensearch([[1..20],2], [[3,Mod(2,3)],[7,Mod(5,7)]]); #v %3 = 1 ? F=v[1]; [mfparams(F)[1], mfcoefs(F,15)] %4 = [11, [0, 1, -2, -1, 2, 1, 2, -2, 0, -2, -2, 1, -2, 4, 4, -1]] @eprog pari-2.17.2/src/functions/modular_forms/mfbd0000644000175000017500000000061414567450071017501 0ustar billbillFunction: mfbd Section: modular_forms C-Name: mfbd Prototype: GL Help: mfbd(F,d): F being a generalized modular form, return B(d)(F), where B(d) is the expanding operator tau -> d tau. Doc: $F$ being a generalized modular form, return $B(d)(F)$, where $B(d)$ is the expanding operator $\tau\mapsto d\tau$. \bprog ? D2=mfbd(mfDelta(),2); mfcoefs(D2, 6) %1 = [0, 0, 1, 0, -24, 0, 252] @eprog pari-2.17.2/src/functions/modular_forms/mfhecke0000644000175000017500000000345614676526175020214 0ustar billbillFunction: mfhecke Section: modular_forms C-Name: mfhecke Prototype: GGL Help: mfhecke(mf,F,n): F being a modular form in space mf, returns T(n)F, where T(n) is the n-th Hecke operator. Warning: if F is of level M. If F has several embeddings into C, give the vector of results corresponding to each embedding. Doc: Given the modular symbol $FS$ associated to an eigenform $F$ by \kbd{mfsymbol(mf,F)}, computes the even and odd special polynomials as well as the even and odd periods $\omega^{+}$ and $\omega^{-}$ as a vector $[[P^{+},P^{-}],[\omega^{+},\omega^{-},r]]$, where $r=\Im(\omega^{+}\overline{\omega^{-}})/$. If $F$ has several embeddings into $\C$, give the vector of results corresponding to each embedding. \bprog ? D=mfDelta(); mf=mfinit(D); DS=mfsymbol(mf,D); ? [pols,oms]=mfmanin(DS); pols %2 = [[4*x^9 - 25*x^7 + 42*x^5 - 25*x^3 + 4*x],\ [-36*x^10 + 691*x^8 - 2073*x^6 + 2073*x^4 - 691*x^2 + 36]] ? oms %3 = [0.018538552324740326472516069364750571812,\ -0.00033105361053212432521308691198949874026*I, 4096/691] ? mf=mfinit([11,2],0); F=mfeigenbasis(mf)[1]; FS=mfsymbol(mf,F); ? [pols,oms]=mfmanin(FS);pols %5 = [[0, 0, 0, 1, 1, 0, 0, -1, -1, 0, 0, 0],\ [2, 0, 10, 5, -5, -10, -10, -5, 5, 10, 0, -2]] ? oms[3] %6 = 24/5 @eprog pari-2.17.2/src/functions/modular_forms/mfgaloistype0000644000175000017500000000306614676526175021312 0ustar billbillFunction: mfgaloistype Section: modular_forms C-Name: mfgaloistype Prototype: GDG Help: mfgaloistype(NK,{F}): NK being either [N,1,CHI] or an mf output by mfinit in weight 1 , gives the vector of types of Galois representations attached to each cuspidal eigenform, unless the eigenform F is specified, in which case only for F. Types A_4, S_4, A_5 are represented by minus their cardinality -12, -24, or -60, and type D_n is represented by its cardinality, the integer 2*n. Doc: \kbd{NK} being either \kbd{[N,1,CHI]} or an \kbd{mf} output by \kbd{mfinit} in weight $1$, gives the vector of types of Galois representations attached to each cuspidal eigenform, unless the modular form \kbd{F} is specified, in which case only for \kbd{F} (note that it is not tested whether \kbd{F} belongs to the correct modular form space, nor whether it is a cuspidal eigenform). Types $A_{4}$, $S_{4}$, $A_{5}$ are represented by minus their cardinality $-12$, $-24$, or $-60$, and type $D_{n}$ is represented by its cardinality, the integer $2n$: \bprog ? mfgaloistype([124,1, Mod(67,124)]) \\ A4 %1 = [-12] ? mfgaloistype([148,1, Mod(105,148)]) \\ S4 %2 = [-24] ? mfgaloistype([633,1, Mod(71,633)]) \\ D10, A5 %3 = [10, -60] ? mfgaloistype([239,1, -239]) \\ D6, D10, D30 %4 = [6, 10, 30] ? mfgaloistype([71,1, -71]) %5 = [14] ? mf = mfinit([239,1, -239],0); F = mfeigenbasis(mf)[2]; ? mfgaloistype(mf, F) %7 = 10 @eprog The function may also return~$0$ as a type when it failed to determine it; in this case the correct type is either~$-12$ or~$-60$, and most likely~$-12$. pari-2.17.2/src/functions/modular_forms/mfEH0000644000175000017500000000136714676526175017430 0ustar billbillFunction: mfEH Section: modular_forms C-Name: mfEH Prototype: G Help: mfEH(k): k>0 being in 1/2+Z, mf corresponding to the Cohen-Eisenstein series H_k of weight k on G_0(4). Doc: $k$ being in $1/2+\Z_{\geq 0}$, return the mf structure corresponding to the Cohen-Eisenstein series $H_{k}$ of weight $k$ on $\Gamma_{0}(4)$. \bprog ? H = mfEH(13/2); mfcoefs(H,4) %1 = [691/32760, -1/252, 0, 0, -2017/252] @eprog The coefficients of $H$ are given by the Cohen-Hurwitz function $H(k-1/2,N)$ and can be obtained for moderately large values of $N$ (the algorithm uses $\tilde{O}(N)$ time): \bprog ? mfcoef(H,10^5+1) time = 55 ms. %2 = -12514802881532791504208348 ? mfcoef(H,10^7+1) time = 6,044 ms. %3 = -1251433416009877455212672599325104476 @eprog pari-2.17.2/src/functions/modular_forms/mfatkininit0000644000175000017500000000506114676526175021121 0ustar billbillFunction: mfatkininit Section: modular_forms C-Name: mfatkininit Prototype: GLp Help: mfatkininit(mf,Q): initializes data necessary for working with Atkin--Lehner operators W_Q, for now only the function mfatkin. The result is a 4-component vector [mfB, MC, C, mf] where mfB is either 0 or the possibly different modular form space to which F|W_Q will belong (this does not depend on F in mf); MC is the matrix of W_Q on the basis of mf multiplied by a normalizing constant C. Doc: given a modular form space with parameters $N,k,\chi$ and a primitive divisor $Q$ of the level $N$, initializes data necessary for working with the Atkin--Lehner operator $W_{Q}$, for now only the function \kbd{mfatkin}. We write $\chi \sim \chi_{Q} \chi_{N/Q}$ where the two characters are primitive with (coprime) conductors dividing $Q$ and $N/Q$ respectively. For $F\in M_{k}(\Gamma_{0}(N),\chi)$, the form $F | W_{Q}$ still has level $N$ and weight $k$ but its Nebentypus may no longer be $\chi$: it becomes $\overline{\chi_{Q}} \chi_{N/Q})$ if $k$ is integral and $\overline{\chi_{Q}} \chi_{N/Q})(4Q/\cdot)$ if not. The result is a technical 4-component vector \kbd{[mfB, MC, C, mf]}, where \item \kbd{mfB} encodes the modular form space to which $F|W_{Q}$ belongs when $F \in M_{k}(\Gamma_{0}(N), \chi)$: an \kbd{mfinit} corresponding to a new Nebentypus or the integer $0$ when the character does not change. This does not depend on $F$. \item \kbd{MC} is the matrix of $W_{Q}$ on the bases of \kbd{mf} and \kbd{mfB} multiplied by a normalizing constant $C(k,\chi,Q)$. This matrix has polmod coefficients in $\Q(\chi)$. \item \kbd{C} is the complex constant $C(k,\chi,Q)$. For $k$ integral, let $A(k,\chi, Q) = Q^{\varepsilon}/g(\chi_{Q})$, where $\varepsilon = 0$ for $k$ even and $1/2$ for $k$ odd and where $g(\chi_{Q})$ is the Gauss sum attached to $\chi_{Q}$). (A similar, more complicated, definition holds in half-integral weight depending on the parity of $k - 1/2$.) Then if $M$ denotes the matrix of $W_{Q}$ on the bases of \kbd{mf} and \kbd{mfB}, $A \cdot M$ has coefficients in $\Q(\chi)$. If $A$ is rational, we let $C = 1$ and $C = A$ as a floating point complex number otherwise, and finally $\kbd{MC} := M \cdot C$. \bprog ? mf=mfinit([32,4],0); [mfB,MC,C]=mfatkininit(mf,32); MC %1 = [5/16 11/2 55/8] [ 1/8 0 -5/4] [1/32 -1/4 11/16] ? C %2 = 1 ? mf=mfinit([32,4,8],0); [mfB,MC,C]=mfatkininit(mf,32); MC %3 = [ 1/8 -7/4] [-1/16 -1/8] ? C %4 = 0.35355339059327376220042218105242451964 ? algdep(C,2) \\ C = 1/sqrt(8) %5 = 8*x^2 - 1 @eprog pari-2.17.2/src/functions/modular_forms/mfdescribe0000644000175000017500000000221014567450071020666 0ustar billbillFunction: mfdescribe Section: modular_forms C-Name: mfdescribe Prototype: GD& Help: mfdescribe(F,{&G}): gives a human-readable description of F, which is either a modular form space or a modular form. If the address of G is given, puts into G the vector of parameters of the outmost operator defining F. Doc: gives a human-readable description of $F$, which is either a modular form space or a generalized modular form. If the address of $G$ is given, puts into $G$ the vector of parameters of the outermost operator defining $F$; this vector is empty if $F$ is a leaf (an atomic object such as \kbd{mfDelta()}, not defined in terms of other forms) or a modular form space. \bprog ? E1 = mfeisenstein(4,-3,-4); mfdescribe(E1) %1 = "F_4(-3, -4)" ? E2 = mfeisenstein(3,5,-7); mfdescribe(E2) %2 = "F_3(5, -7)" ? E3 = mfderivE2(mfmul(E1,E2), 3); mfdescribe(E3,&G) %3 = "DERE2^3(MUL(F_4(-3, -4), F_3(5, -7)))" ? mfdescribe(G[1][1]) %4 = "MUL(F_4(-3, -4), F_3(5, -7))" ? G[2] %5 = 3 ? for (i = 0, 4, mf = mfinit([37,4],i); print(mfdescribe(mf))); S_4^new(G_0(37, 1)) S_4(G_0(37, 1)) S_4^old(G_0(37, 1)) E_4(G_0(37, 1)) M_4(G_0(37, 1)) @eprog pari-2.17.2/src/functions/modular_forms/mfparams0000644000175000017500000000414114567450071020376 0ustar billbillFunction: mfparams Section: modular_forms C-Name: mfparams Prototype: G Help: mfparams(F): If F is a modular form space, returns [N,k,CHI,space,Phi]: level, weight, character, and space code; where Phi is the cyclotomic polynomial defining the field of values of CHI. If F is a modular form, returns [N,k,CHI,P,Phi], where P is the (polynomial giving the) field of definition of F: in that case the level N may be a multiple of the level of F and the polynomial P may define a larger field than Q(F). Doc: If $F$ is a modular form space, returns \kbd{[N,k,CHI,space,$\Phi$]}, level, weight, character $\chi$, and space code; where $\Phi$ is the cyclotomic polynomial defining the field of values of \kbd{CHI}. If $F$ is a generalized modular form, returns \kbd{[N,k,CHI,P,$\Phi$]}, where $P$ is the (polynomial giving the) field of definition of $F$ as a relative extension of the cyclotomic field $\Q(\chi) = \Q[t]/(\Phi)$: in that case the level $N$ may be a multiple of the level of $F$ and the polynomial $P$ may define a larger field than $\Q(F)$. If you want the true level of $F$ from this result, use \kbd{mfconductor(mfinit(F),F)}. The polynomial $P$ defines an extension of $\Q(\chi) = \Q[t]/(\Phi(t))$; it has coefficients in that number field (polmods in $t$). In contrast with \kbd{mfparams(F)[4]} which always gives the polynomial $P$ defining the relative extension $\Q(F)/\Q(\chi)$, the member function \kbd{$F$.mod} returns the polynomial used to define $\Q(F)$ over $\Q$ (either a cyclotomic polynomial or a polynomial with cyclotomic coefficients). \bprog ? E1 = mfeisenstein(4,-3,-4); E2 = mfeisenstein(3,5,-7); E3 = mfmul(E1,E2); ? apply(mfparams, [E1,E2,E3]) %2 = [[12, 4, 12, y, t-1], [35, 3, -35, y, t-1], [420, 7, -420, y, t-1]] ? mf = mfinit([36,2,Mod(13,36)],0); [f] = mfeigenbasis(mf); mfparams(mf) %3 = [36, 2, Mod(13, 36), 0, t^2 + t + 1] ? mfparams(f) %4 = [36, 2, Mod(13, 36), y, t^2 + t + 1] ? f.mod %5 = t^2 + t + 1 ? mf = mfinit([36,4,Mod(13,36)],0); [f] = mfeigenbasis(mf); ? lift(mfparams(f)) %7 = [36, 4, 13, y^3 + (2*t-2)*y^2 + (-4*t+6)*y + (10*t-1), t^2+t+1] @eprog pari-2.17.2/src/functions/modular_forms/mfcoefs0000644000175000017500000000166314676526175020232 0ustar billbillFunction: mfcoefs Section: modular_forms C-Name: mfcoefs Prototype: GLD1,L, Help: mfcoefs(F,n,{d=1}): Compute the vector of coefficients [a[0],a[d],...,a[nd]] of the modular form F. Doc: Compute the vector of Fourier coefficients $[a[0],a[d],...,a[nd]]$ of the generalized modular form $F$; $d$ must be positive and $d = 1$ by default. \bprog ? D = mfDelta(); ? mfcoefs(D,10) %2 = [0, 1, -24, 252, -1472, 4830, -6048, -16744, 84480, -113643, -115920] ? mfcoefs(D,5,2) %3 = [0, -24, -1472, -6048, 84480, -115920] ? mfcoef(D,10) %4 = -115920 @eprog\noindent This function also applies when $F$ is a modular form space as output by \kbd{mfinit}; it then returns the matrix whose columns give the Fourier expansions of the elements of \kbd{mfbasis}$(F)$: \bprog ? mf = mfinit([1,12]); ? mfcoefs(mf,5) %2 = [691/65520 0] [ 1 1] [ 2049 -24] [ 177148 252] [ 4196353 -1472] [ 48828126 4830] @eprog pari-2.17.2/src/functions/modular_forms/mfcosets0000644000175000017500000000203514676526175020425 0ustar billbillFunction: mfcosets Section: modular_forms C-Name: mfcosets Prototype: G Help: mfcosets(N): list of right cosets of G_0(N)\G, i.e., matrices g_j in G such that G = U G_0(N) g_j. The g_j are chosen in the form [a,b; c,d] with c | N. Doc: let $N$ be a positive integer. Return the list of right cosets of $\Gamma_{0}(N) \bs \Gamma$, i.e., matrices $\gamma_{j} \in \Gamma$ such that $\Gamma = \bigsqcup_{j} \Gamma_{0}(N) \gamma_{j}$. The $\gamma_{j}$ are chosen in the form $[a,b;c,d]$ with $c \mid N$. \bprog ? mfcosets(4) %1 = [[0, -1; 1, 0], [1, 0; 1, 1], [0, -1; 1, 2], [0, -1; 1, 3],\ [1, 0; 2, 1], [1, 0; 4, 1]] @eprog\noindent We also allow the argument $N$ to be a modular form space, in which case it is replaced by the level of the space: \bprog ? M = mfinit([4, 12, 1], 0); mfcosets(M) %2 = [[0, -1; 1, 0], [1, 0; 1, 1], [0, -1; 1, 2], [0, -1; 1, 3],\ [1, 0; 2, 1], [1, 0; 4, 1]] @eprog \misctitle{Warning} In the present implementation, the trivial coset is represented by $[1,0;N,1]$ and is the last in the list. pari-2.17.2/src/functions/modular_forms/mfeigenbasis0000644000175000017500000000510614676526175021240 0ustar billbillFunction: mfeigenbasis Section: modular_forms C-Name: mfeigenbasis Prototype: G Help: mfeigenbasis(mf): vector of the eigenforms for the space mf. Doc: vector of the eigenforms for the space \kbd{mf}. The initial basis of forms computed by \kbd{mfinit} before splitting is also available via \kbd{mfbasis}. \bprog ? mf = mfinit([26,2],0); ? see(L) = for(i=1,#L,print(mfcoefs(L[i],6))); ? see( mfeigenbasis(mf) ) [0, 1, -1, 1, 1, -3, -1] [0, 1, 1, -3, 1, -1, -3] ? see( mfbasis(mf) ) [0, 2, 0, -2, 2, -4, -4] [0, -2, -4, 10, -2, 0, 8] @eprog The eigenforms are internally expressed as (algebraic) linear combinations of \kbd{mfbasis(mf)} and it is very inefficient to compute many coefficients of those forms individually: you should rather use \kbd{mfcoefs(mf)} to expand the basis once and for all, then multiply by \kbd{mftobasis(mf,f)} for the forms you're interested in: \bprog ? mf = mfinit([96,6],0); B = mfeigenbasis(mf); #B %1 = 8; ? vector(#B, i, mfcoefs(B[i],1000)); \\ expanded individually: slow time = 7,881 ms. ? M = mfcoefs(mf, 1000); \\ initialize once time = 982 ms. ? vector(#B, i, M * mftobasis(mf,B[i])); \\ then expand: much faster time = 623 ms. @eprog When the eigenforms are defined over an extension field of $\Q(\chi)$ for a nonrational character, their coefficients are hard to read and you may want to lift them or to express them in an absolute number field. In the construction below $T$ defines $\Q(f)$ over $\Q$, $a$ is the image of the generator \kbd{Mod}$(t, t^{2}+t+1)$ of $\Q(\chi)$ in $\Q(f)$ and $y - ka$ is the image of the root $y$ of \kbd{f.mod}: \bprog ? mf = mfinit([31, 2, Mod(25,31)], 0); [f] = mfeigenbasis(mf); ? f.mod %2 = Mod(1, t^2 + t + 1)*y^2 + Mod(2*t + 2, t^2 + t + 1) ? v = liftpol(mfcoefs(f,5)) %3 = [0, 1, (-t - 1)*y - 1, t*y + (t + 1), (2*t + 2)*y + 1, t] ? [T,a,k] = rnfequation(mf.mod, f.mod, 1) %4 = [y^4 + 2*y^2 + 4, Mod(-1/2*y^2 - 1, y^4 + 2*y^2 + 4), 0] ? liftpol(substvec(v, [t,y], [a, y-k*a])) %5 = [0, 1, 1/2*y^3 - 1, -1/2*y^3 - 1/2*y^2 - y, -y^3 + 1, -1/2*y^2 - 1] @eprog\noindent Beware that the meaning of $y$ has changed in the last line is different: it now represents of root of $T$, no longer of \kbd{f.mod} (the notions coincide if $k = 0$ as here but it will not always be the case). This can be avoided with an extra variable substitution, for instance \bprog ? [T,a,k] = rnfequation(mf.mod, subst(f.mod,'y,'x), 1) %6 = [x^4 + 2*x^2 + 4, Mod(-1/2*x^2 - 1, x^4 + 2*x^2 + 4), 0] ? liftpol(substvec(v, [t,y], [a, x-k*a])) %7 = [0, 1, 1/2*x^3 - 1, -1/2*x^3 - 1/2*x^2 - x, -x^3 + 1, -1/2*x^2 - 1] @eprog pari-2.17.2/src/functions/modular_forms/mfshift0000644000175000017500000000077014676526175020246 0ustar billbillFunction: mfshift Section: modular_forms C-Name: mfshift Prototype: GL Help: mfshift(F,s): Divide the form F by q^s omitting the remainder if there is one; s can be negative. Doc: Divide the generalized modular form $F$ by $q^{s}$, omitting the remainder if there is one. One can have $s<0$. \bprog ? D=mfDelta(); mfcoefs(mfshift(D,1), 4) %1 = [1, -24, 252, -1472, 4830] ? mfcoefs(mfshift(D,2), 4) %2 = [-24, 252, -1472, 4830, -6048] ? mfcoefs(mfshift(D,-1), 4) %3 = [0, 0, 1, -24, 252] @eprog pari-2.17.2/src/functions/modular_forms/mfkohnenbasis0000644000175000017500000000221714567450071021421 0ustar billbillFunction: mfkohnenbasis Section: modular_forms C-Name: mfkohnenbasis Prototype: G Help: mfkohnenbasis(mf): mf being a cuspidal space of half-integral weight k >= 3/2, gives a basis B of the Kohnen + space of mf as a matrix whose columns are the coefficients of B on the basis of mf. Doc: \kbd{mf} being a cuspidal space of half-integral weight $k\ge3/2$ with level $N$ and character $\chi$, gives a basis $B$ of the Kohnen $+$-space of \kbd{mf} as a matrix whose columns are the coefficients of $B$ on the basis of \kbd{mf}. The conductor of either $\chi$ or $\chi \cdot (-4/.)$ must divide $N/4$. \bprog ? mf = mfinit([36,5/2],1); K = mfkohnenbasis(mf); K~ %1 = [-1 0 0 2 0 0] [ 0 0 0 0 1 0] ? (mfcoefs(mf,20) * K)~ %4 = [0 -1 0 0 2 0 0 0 0 0 0 0 0 -6 0 0 8 0 0 0 0] [0 0 0 0 0 1 0 0 -2 0 0 0 0 0 0 0 0 1 0 0 2] ? mf = mfinit([40,3/2,8],1); mfkohnenbasis(mf) *** at top-level: mfkohnenbasis(mf) *** ^----------------- *** mfkohnenbasis: incorrect type in mfkohnenbasis [incorrect CHI] (t_VEC). @eprog In the final example both $\chi = (8/.)$ and $\chi \cdot (-4/.)$ have conductor $8$, which does not divide N/4 = 10. pari-2.17.2/src/functions/modular_forms/mftaylor0000644000175000017500000000156714676526175020450 0ustar billbillFunction: mftaylor Section: modular_forms C-Name: mftaylor Prototype: GLD0,L,p Help: mftaylor(F,n,{flreal=0}): F being a modular form in M_k(SL_2(Z)), computes the first n+1 canonical Taylor expansion of F around tau=I. If flreal=0, computes only an algebraic equivalence class. If flreal is set, compute p_n such that for tau close enough to I we have f(tau)=(2I/(tau+I))^ksum_{n>=0}p_n((tau-I)/(tau+I))^n. Doc: $F$ being a form in $M_{k}(SL_{2}(\Bbb Z))$, computes the first $n+1$ canonical Taylor expansion of $F$ around $\tau=I$. If \kbd{flreal=0}, computes only an algebraic equivalence class. If \kbd{flreal} is set, compute $p_{n}$ such that for $\tau$ close enough to $I$ we have $$f(\tau)=(2I/(\tau+I))^{k}\sum_{n>=0}p_{n}((\tau-I)/(\tau+I))^{n}\;.$$ \bprog ? D=mfDelta(); ? mftaylor(D,8) %2 = [1/1728, 0, -1/20736, 0, 1/165888, 0, 1/497664, 0, -11/3981312] @eprog pari-2.17.2/src/functions/modular_forms/mfatkin0000644000175000017500000000214514676526175020235 0ustar billbillFunction: mfatkin Section: modular_forms C-Name: mfatkin Prototype: GG Help: mfatkin(mfatk,f): Given an mfatk output by mfatk = mfatkininit(mf,Q) and a modular form f belonging to the space mf, returns the modular form g = C*f|W_Q where C = mfatk[3] is a normalizing constant so that g has the same field of coefficients as f; mfatk[1] = mf2 (or 0 if mf2=mf) which is the space to which g belongs. Doc: Given a \kbd{mfatk} output by \kbd{mfatk = mfatkininit(mf,Q)} and a modular form $f$ belonging to the pace \kbd{mf}, returns the modular form $g = C \times f|W_{Q}$, where $C = \kbd{mfatk[3]}$ is a normalizing constant such that $g$ has the same field of coefficients as $f$; \kbd{mfatk[3]} gives the constant $C$, and \kbd{mfatk[1]} gives the modular form space to which $g$ belongs (or is set to $0$ if it is \kbd{mf}). \bprog ? mf = mfinit([35,2],0); [f] = mfbasis(mf); ? mfcoefs(f, 4) %2 = [0, 3, -1, 0, 3] ? mfatk = mfatkininit(mf,7); ? g = mfatkin(mfatk, f); mfcoefs(g, 4) %4 = [0, 1, -1, -2, 7] ? mfatk = mfatkininit(mf,35); ? g = mfatkin(mfatk, f); mfcoefs(g, 4) %6 = [0, -3, 1, 0, -3] @eprog pari-2.17.2/src/functions/modular_forms/mfsymbol0000644000175000017500000000355014567450071020423 0ustar billbillFunction: mfsymbol Section: modular_forms C-Name: mfsymbol Prototype: GDGb Help: mfsymbol(mf,f): Initialize data for working with all period polynomials of the modular form f: this is essential for efficiency for functions such as mfsymboleval, mfmanin, and mfpetersson. By abuse of language, initialize data for working with mfpetersson in weight 1 or half-integral weight (where no symbol exist). Doc: Initialize data for working with all period polynomials of the modular form $f$: this is essential for efficiency for functions such as \kbd{mfsymboleval}, \kbd{mfmanin}, and \kbd{mfpetersson}. An \kbd{mfsymbol} contains an \kbd{mf} structure and can always be used whenever an \kbd{mf} would be needed. \bprog ? mf=mfinit([23,2],0);F=mfeigenbasis(mf)[1]; ? FS=mfsymbol(mf,F); ? mfsymboleval(FS,[0,oo]) %3 = [8.762565143790690142 E-39 + 0.0877907874...*I, -5.617375463602574564 E-39 + 0.0716801031...*I] ? mfpetersson(FS) %4 = [0.0039488965740025031688548076498662860143 1.2789721111175127425 E-40] [1.2630501762985554269 E-40 0.0056442542987647835101583821368582485396] @eprog\noindent By abuse of language, initialize data for working with \kbd{mfpetersson} in weight $1$ and half-integral weight (where no symbol exist); the \kbd{mf} argument may be an \kbd{mfsymbol} attached to a form on the space, which avoids recomputing data independent of the form. \bprog ? mf=mfinit([12,9/2],1); F=mfbasis(mf); ? fs=mfsymbol(mf,F[1]); time = 476 ms ? mfpetersson(fs) %2 = 1.9722437519492014682047692073275406145 E-5 ? f2s = mfsymbol(mf,F[2]); time = 484 ms. ? mfpetersson(f2s) %4 = 1.2142222531326333658647877864573002476 E-5 ? gs = mfsymbol(fs,F[2]); \\ re-use existing symbol, a little faster time = 430 ms. ? mfpetersson(gs) == %4 \\ same value %6 = 1 @eprog For simplicity, we also allow \kbd{mfsymbol(f)} instead of \kbd{mfsymbol(mfinit(f), f)}: pari-2.17.2/src/functions/modular_forms/mfheckemat0000644000175000017500000000121314567450071020671 0ustar billbillFunction: mfheckemat Section: modular_forms C-Name: mfheckemat Prototype: GG Help: mfheckemat(mf,vecn): if vecn is an integer, matrix of the Hecke operator T(n) on the basis formed by mfbasis(mf), if it is a vector, vector of such matrices. Doc: if \kbd{vecn} is an integer, matrix of the Hecke operator $T(n)$ on the basis formed by \kbd{mfbasis(mf)}. If it is a vector, vector of such matrices, usually faster than calling each one individually. \bprog ? mf=mfinit([32,4],0); mfheckemat(mf,3) %1 = [0 44 0] [1 0 -10] [0 -2 0] ? mfheckemat(mf,[5,7]) %2 = [[0, 0, 220; 0, -10, 0; 1, 0, 12], [0, 88, 0; 2, 0, -20; 0, -4, 0]] @eprog pari-2.17.2/src/functions/modular_forms/mfEk0000644000175000017500000000056214676526175017467 0ustar billbillFunction: mfEk Section: modular_forms C-Name: mfEk Prototype: L Help: mfEk(k): mf corresponding to the standard Eisenstein series E_k for nonnegative even integer k. Doc: k being an even nonnegative integer, return the mf structure corresponding to the standard Eisenstein series $E_{k}$. \bprog ? mfcoefs(mfEk(8), 4) %1 = [1, 480, 61920, 1050240, 7926240] @eprog pari-2.17.2/src/functions/modular_forms/mfderivE20000644000175000017500000000121514676526175020424 0ustar billbillFunction: mfderivE2 Section: modular_forms C-Name: mfderivE2 Prototype: GD1,L, Help: mfderivE2(F,{m=1}): compute the Serre derivative (q.d/dq)F - kE_2F/12 of the generalized modular form F of weight k; and if m > 1, the m-th iterate. Doc: compute the Serre derivative $(q \* d/dq)F - kE_{2}F/12$ of the generalized modular form $F$, which has weight $k+2$; if $F$ is a true modular form, then its Serre derivative is also modular. If $m>1$, compute the $m$-th iterate, of weight $k + 2m$. \bprog ? mfcoefs(mfderivE2(mfEk(4)),5)*(-3) %1 = [1, -504, -16632, -122976, -532728] ? mfcoefs(mfEk(6),5) %2 = [1, -504, -16632, -122976, -532728] @eprog pari-2.17.2/src/functions/modular_forms/mftwist0000644000175000017500000000157714676526175020311 0ustar billbillFunction: mftwist Section: modular_forms C-Name: mftwist Prototype: GG Help: mftwist(F,D): returns the twist of the form F by the integer D, i.e., the form G such that mfcoef(G,n)=(D/n)mfcoef(F,n), where (D/n) is the Kronecker symbol. Doc: $F$ being a generalized modular form, returns the twist of $F$ by the integer $D$, i.e., the form $G$ such that \kbd{mfcoef(G,n)=}$(D/n)$\kbd{mfcoef(F,n)}, where $(D/n)$ is the Kronecker symbol. \bprog ? mf = mfinit([11,2],0); F = mfbasis(mf)[1]; mfcoefs(F, 5) %1 = [0, 1, -2, -1, 2, 1] ? G = mftwist(F,-3); mfcoefs(G, 5) %2 = [0, 1, 2, 0, 2, -1] ? mf2 = mfinit([99,2],0); mftobasis(mf2, G) %3 = [1/3, 0, 1/3, 0]~ @eprog\noindent Note that twisting multiplies the level by $D^{2}$. In particular it is not an involution: \bprog ? H = mftwist(G,-3); mfcoefs(H, 5) %4 = [0, 1, -2, 0, 2, 1] ? mfparams(G) %5 = [99, 2, 1, y, t - 1] @eprog pari-2.17.2/src/functions/modular_forms/mfpow0000644000175000017500000000044714676526175017737 0ustar billbillFunction: mfpow Section: modular_forms C-Name: mfpow Prototype: GL Help: mfpow(F,n): compute F^n Doc: Compute $F^{n}$, where $n$ is an integer and $F$ is a generalized modular form: \bprog ? G = mfpow(mfEk(4), 3); \\ E4^3 ? mfcoefs(G, 4) %2 = [1, 720, 179280, 16954560, 396974160] @eprog pari-2.17.2/src/functions/modular_forms/mfsplit0000644000175000017500000000507014676526175020262 0ustar billbillFunction: mfsplit Section: modular_forms C-Name: mfsplit Prototype: GD0,L,D0,L, Help: mfsplit(mf,{dimlim=0},{flag=0}): mf containing the new space split the new space into Galois orbits of eigenforms of the newspace and return [vF,vK], where vF gives the (Galois orbit of) eigenforms in terms of mfbasis(mf) and vK is a list of polynomials defining each Galois orbit. If dimlim is set only the Galois orbits of dimension <= dimlim are computed (i.e. the rational eigenforms if dimlim = 1 and the character is real). Flag speeds up computations when the dimension is large: if flag = d > 0, when the dimension of the eigenspace is > d, only the Galois polynomial is computed. Doc: \kbd{mf} from \kbd{mfinit} with integral weight containing the new space (either the new space itself or the cuspidal space or the full space), and preferably the newspace itself for efficiency, split the space into Galois orbits of eigenforms of the newspace, satisfying various restrictions. The functions returns $[vF, vK]$, where $vF$ gives (Galois orbit of) eigenforms and $vK$ is a list of polynomials defining each Galois orbit. The eigenforms are given in \kbd{mftobasis} format, i.e. as a matrix whose columns give the forms with respect to \kbd{mfbasis(mf)}. If \kbd{dimlim} is set, only the Galois orbits of dimension $\leq \kbd{dimlim}$ are computed (i.e. the rational eigenforms if $\kbd{dimlim} = 1$ and the character is real). This can considerably speed up the function when a Galois orbit is defined over a large field. $\fl$ speeds up computations when the dimension is large: if $\fl=d>0$, when the dimension of the eigenspace is $>d$, only the Galois polynomial is computed. Note that the function \kbd{mfeigenbasis} returns all eigenforms in an easier to use format (as modular forms which can be input as is in other functions); \kbd{mfsplit} is only useful when you can restrict to orbits of small dimensions, e.g. rational eigenforms. \bprog ? mf=mfinit([11,2],0); f=mfeigenbasis(mf)[1]; mfcoefs(f,16) %1 = [0, 1, -2, -1, ...] ? mf=mfinit([23,2],0); f=mfeigenbasis(mf)[1]; mfcoefs(f,16) %2 = [Mod(0, z^2 - z - 1), Mod(1, z^2 - z - 1), Mod(-z, z^2 - z - 1), ...] ? mf=mfinit([179,2],0); apply(poldegree, mffields(mf)) %3 = [1, 3, 11] ? mf=mfinit([719,2],0); ? [vF,vK] = mfsplit(mf, 5); \\ fast when restricting to small orbits time = 192 ms. ? #vF \\ a single orbit %5 = 1 ? poldegree(vK[1]) \\ of dimension 5 %6 = 5 ? [vF,vK] = mfsplit(mf); \\ general case is slow time = 2,104 ms. ? apply(poldegree,vK) %8 = [5, 10, 45] \\ because degree 45 is large... @eprog pari-2.17.2/src/functions/modular_forms/mfisetaquo0000644000175000017500000000152714567450071020752 0ustar billbillFunction: mfisetaquo Section: modular_forms C-Name: mfisetaquo Prototype: GD0,L, Help: mfisetaquo(f,{flag=0}): if the generalized modular form f is a holomorphic eta quotient, return the eta quotient matrix, else return 0. If flag is set, also accept meromorphic eta quotients. Doc: if the generalized modular form $f$ is a holomorphic eta quotient, return the eta quotient matrix, else return 0. If \fl is set, also accept meromorphic eta quotients: check whether $f = q^{-v(g)} g(q)$ for some eta quotient $g$; if so, return the eta quotient matrix attached to $g$, else return $0$. See \kbd{mffrometaquo}. \bprog ? mfisetaquo(mfDelta()) %1 = [1 24] ? f = mffrometaquo([1,1;23,1]); ? mfisetaquo(f) %3 = [ 1 1] [23 1] ? f = mffrometaquo([1,-24], 1); ? mfisetaquo(f) \\ nonholomorphic %5 = 0 ? mfisetaquo(f,1) %6 = [1 -24] @eprog pari-2.17.2/src/functions/modular_forms/mfcoef0000644000175000017500000000067114567450071020033 0ustar billbillFunction: mfcoef Section: modular_forms C-Name: mfcoef Prototype: GL Help: mfcoef(F,n): Compute the n-th Fourier coefficient a(n) of the generalized modular form F. Doc: Compute the $n$-th Fourier coefficient $a(n)$ of the generalized modular form $F$. Note that this is the $n+1$-st component of the vector \kbd{mfcoefs(F,n)} as well as the second component of \kbd{mfcoefs(F,1,n)}. \bprog ? mfcoef(mfDelta(),10) %1 = -115920 @eprog pari-2.17.2/src/functions/modular_forms/mfsturm0000644000175000017500000000143214676526175020277 0ustar billbillFunction: mfsturm Section: modular_forms C-Name: mfsturm Prototype: lG Help: mfsturm(NK): Sturm bound for modular forms on G_0(N) and weight k, i.e., an upper bound for the order of the zero at infinity of a nonzero form. NK is either [N,k] or an mfinit (exact bound in the latter case). Doc: Gives the Sturm bound for modular forms on $\Gamma_{0}(N)$ and weight $k$, i.e., an upper bound for the order of the zero at infinity of a nonzero form. \kbd{NK} is either \item a pair $[N,k]$, in which case the bound is the floor of $(kN/12) \cdot \prod_{p\mid N} (1+1/p)$; \item or the output of \tet{mfinit} in which case the exact upper bound is returned. \bprog ? NK = [96,6]; mfsturm(NK) %1 = 97 ? mf=mfinit(NK,1); mfsturm(mf) %2 = 76 ? mfdim(NK,0) \\ new space %3 = 72 @eprog pari-2.17.2/src/functions/modular_forms/mfpetersson0000644000175000017500000000561014676526175021151 0ustar billbillFunction: mfpetersson Section: modular_forms C-Name: mfpetersson Prototype: GDG Help: mfpetersson(fs,{gs}): Petersson scalar product of the modular forms f and g belonging to the same modular form space mf, given by the corresponding "modular symbols" fs and gs output by mfsymbol (also in weight 1 and half-integral weight). If gs is omitted it is understood to be equal to fs. The scalar product is normalized by the factor 1/[G:G_0(N)]. Doc: Petersson scalar product of the modular forms $f$ and $g$ belonging to the same modular form space \kbd{mf}, given by the corresponding ``modular symbols'' \kbd{fs} and \kbd{gs} output by \kbd{mfsymbol} (also in weight $1$ and half-integral weight, where symbols do not exist). If \kbd{gs} is omitted it is understood to be equal to \kbd{fs}. The scalar product is normalized by the factor $1/[\Gamma:\Gamma_{0}(N)]$. Note that $f$ and $g$ can both be noncuspidal, in which case the program returns an error if the product is divergent. If the fields of definition $\Q(f)$ and $\Q(g)$ are equal to $\Q(\chi)$ the result is a scalar. If $[\Q(f):\Q(\chi)]=d>1$ and $[\Q(g):\Q(\chi)]=e>1$ the result is a $d\times e$ matrix corresponding to all the embeddings of $f$ and $g$. In the intermediate cases $d=1$ or $e=1$ the result is a row or column vector. \bprog ? D=mfDelta(); mf=mfinit(D); DS=mfsymbol(mf,D); mfpetersson(DS) %1 = 1.0353620568043209223478168122251645932 E-6 ? mf=mfinit([11,6],0);B=mfeigenbasis(mf);BS=vector(#B,i,mfsymbol(mf,B[i])); ? mfpetersson(BS[1]) %3 = 1.6190120685220988139111708455305245466 E-5 ? mfpetersson(BS[1],BS[2]) %4 = [-3.826479006582967148 E-42 - 2.801547395385577002 E-41*I,\ 1.6661127341163336125 E-41 + 1.1734725972345985061 E-41*I,\ 0.E-42 - 6.352626992842664490 E-41*I]~ ? mfpetersson(BS[2]) %5 = [ 2.7576133733... E-5 2.0... E-42 6.3... E-43 ] [ -4.1... E-42 6.77837030070... E-5 3.3...E-42 ] [ -6.32...E-43 3.6... E-42 2.27268958069... E-5] ? mf=mfinit([23,2],0); F=mfeigenbasis(mf)[1]; FS=mfsymbol(mf,F); ? mfpetersson(FS) %5 = [0.0039488965740025031688548076498662860143 -3.56 ... E-40] [ -3.5... E-40 0.0056442542987647835101583821368582485396] @eprog Noncuspidal example: \bprog ? E1=mfeisenstein(5,1,-3);E2=mfeisenstein(5,-3,1); ? mf=mfinit([12,5,-3]); cusps=mfcusps(12); ? apply(x->mfcuspval(mf,E1,x),cusps) %3 = [0, 0, 1, 0, 1, 1] ? apply(x->mfcuspval(mf,E2,x),cusps) %4 = [1/3, 1/3, 0, 1/3, 0, 0] ? E1S=mfsymbol(mf,E1);E2S=mfsymbol(mf,E2); ? mfpetersson(E1S,E2S) %6 = -1.884821671646... E-5 - 1.9... E-43*I @eprog Weight 1 and 1/2-integral weight example: \bprog ? mf=mfinit([23,1,-23],1);F=mfbasis(mf)[1];FS=mfsymbol(mf,F); ? mfpetersson(mf,FS) %2 = 0.035149946790370230814006345508484787443 ? mf=mfinit([4,9/2],1);F=mfbasis(mf)[1];FS=mfsymbol(mf,F); ? mfpetersson(FS) %4 = 0.00015577084407139192774373662467908966030 @eprog pari-2.17.2/src/functions/modular_forms/mfdiv0000644000175000017500000000137414567450071017702 0ustar billbillFunction: mfdiv Section: modular_forms C-Name: mfdiv Prototype: GG Help: mfdiv(F,G): compute F/G for two modular forms F and G assuming that the quotient will not have poles at infinity. If this is the case, use mfshift before doing the division. Doc: Given two generalized modular forms $F$ and $G$, compute $F/G$ assuming that the quotient will not have poles at infinity. If this is the case, use \kbd{mfshift} before doing the division. \bprog ? D = mfDelta(); \\ Delta ? H = mfpow(mfEk(4), 3); ? J = mfdiv(H, D) *** at top-level: J=mfdiv(H,mfdeltac *** ^-------------------- *** mfdiv: domain error in mfdiv: ord(G) > ord(F) ? J = mfdiv(H, mfshift(D,1)); ? mfcoefs(J, 4) %4 = [1, 744, 196884, 21493760, 864299970] @eprog pari-2.17.2/src/functions/modular_forms/mftraceform0000644000175000017500000000144514676526175021113 0ustar billbillFunction: mftraceform Section: modular_forms C-Name: mftraceform Prototype: GD0,L, Help: mftraceform(NK,{space=0}): If NK=[N,k,CHI,.] as in mfinit with k integral, gives the trace form in the corresponding subspace of S_k(G_0(N),chi). The supported values for space are 0: the newspace (default), 1: the full cuspidal space. Doc: If $NK=[N,k,CHI,.]$ as in \kbd{mfinit} with $k$ integral, gives the trace form in the corresponding subspace of $S_{k}(\Gamma_{0}(N),\chi)$. The supported values for \kbd{space} are 0: the newspace (default), 1: the full cuspidal space. \bprog ? F = mftraceform([23,2]); mfcoefs(F,16) %1 = [0, 2, -1, 0, -1, -2, -5, 2, 0, 4, 6, -6, 5, 6, 4, -10, -3] ? F = mftraceform([23,1,-23]); mfcoefs(F,16) %2 = [0, 1, -1, -1, 0, 0, 1, 0, 1, 0, 0, 0, 0, -1, 0, 0, -1] @eprog pari-2.17.2/src/functions/modular_forms/mffromell0000644000175000017500000000155014567450071020554 0ustar billbillFunction: mffromell Section: modular_forms C-Name: mffromell Prototype: G Help: mffromell(E): E being an elliptic curve defined over Q given by an integral model in ellinit format, computes a 3-component vector [mf,F,v], where F is the newform corresponding to E by modularity, mf is the newspace to which F belongs, and v gives the coefficients of F on mfbasis(mf). Doc: $E$ being an elliptic curve defined over $Q$ given by an integral model in \kbd{ellinit} format, computes a 3-component vector \kbd{[mf,F,v]}, where $F$ is the newform corresponding to $E$ by modularity, \kbd{mf} is the newspace to which $F$ belongs, and \kbd{v} gives the coefficients of $F$ on \kbd{mfbasis(mf)}. \bprog ? E = ellinit("26a1"); ? [mf,F,co] = mffromell(E); ? co %2 = [3/4, 1/4]~ ? mfcoefs(F, 5) %3 = [0, 1, -1, 1, 1, -3] ? ellan(E, 5) %4 = [1, -1, 1, 1, -3] @eprog pari-2.17.2/src/functions/modular_forms/mftocoset0000644000175000017500000000122514702762523020572 0ustar billbillFunction: mftocoset Section: modular_forms C-Name: mftocoset Prototype: UGG Help: mftocoset(N,M,Lcosets): M being a matrix in SL_2(Z) and Lcosets being mfcosets(N), find the right coset of G_0(N) to which M belongs. The output is a pair [ga,i] such that M = ga * Lcosets[i], with ga in G_0(N). Doc: $M$ being a matrix in $SL_{2}(Z)$ and \kbd{Lcosets} being \kbd{mfcosets(N)}, a list of right cosets of $\Gamma_{0}(N)$, find the coset to which $M$ belongs. The output is a pair $[\gamma,i]$ such that $M = \gamma \kbd{Lcosets}[i]$, $\gamma\in\Gamma_{0}(N)$. \bprog ? N = 4; L = mfcosets(N); ? mftocoset(N, [1,1;2,3], L) %2 = [[-1, 1; -4, 3], 5] @eprog pari-2.17.2/src/functions/modular_forms/mfperiodpol0000644000175000017500000000172614676526175021130 0ustar billbillFunction: mfperiodpol Section: modular_forms C-Name: mfperiodpol Prototype: GGD0,L,b Help: mfperiodpol(mf,f,{flag=0}): period polynomial of the cuspidal part of the form f, in other words integral from 0 to ioo of (X-tau)^(k-2)f(tau). If flag=0, ordinary period polynomial, if flag=1 or -1, even or odd part of that polynomial. f can also be the modular symbol output by mfsymbol(mf,f). Doc: period polynomial of the cuspidal part of the form $f$, in other words $\int_{0}^{i\infty}(X-\tau)^{k-2}f(\tau)\,d\tau$. If $\fl=0$, ordinary period polynomial. If it is $1$ or $-1$, even or odd part of that polynomial. $f$ can also be the modular symbol output by \kbd{mfsymbol}(mf,f). \bprog ? D = mfDelta(); mf = mfinit(D,0); ? PP = mfperiodpol(mf, D, -1); PP/=polcoef(PP, 1); bestappr(PP) %1 = x^9 - 25/4*x^7 + 21/2*x^5 - 25/4*x^3 + x ? PM = mfperiodpol(mf, D, 1); PM/=polcoef(PM, 0); bestappr(PM) %2 = -x^10 + 691/36*x^8 - 691/12*x^6 + 691/12*x^4 - 691/36*x^2 + 1 @eprog pari-2.17.2/src/functions/modular_forms/lfunmf0000644000175000017500000000255314567450071020064 0ustar billbillFunction: lfunmf Section: modular_forms C-Name: lfunmf Prototype: GDGb Help: lfunmf(mf,{F}): If F is a modular form in mf, output the L-functions corresponding to its complex embeddings. If F is omitted, output the L-functions corresponding to all eigenforms in the new space. Doc: If $F$ is a modular form in \kbd{mf}, output the L-functions corresponding to its $[\Q(F):\Q(\chi)]$ complex embeddings, ready for use with the \kbd{lfun} package. If $F$ is omitted, output the $L$-functions attached to all eigenforms in the new space; the result is a vector whose length is the number of Galois orbits of newforms. Each entry contains the vector of $L$-functions corresponding to the $d$ complex embeddings of an orbit of dimension $d$ over $\Q(\chi)$. \bprog ? mf = mfinit([35,2],0);mffields(mf) %1 = [y, y^2 - y - 4] ? f = mfeigenbasis(mf)[2]; mfparams(f) \\ orbit of dimension two %2 = [35, 2, 1, y^2 - y - 4, t - 1] ? [L1,L2] = lfunmf(mf, f); \\ Two L-functions ? lfun(L1,1) %4 = 0.81018461849460161754947375433874745585 ? lfun(L2,1) %5 = 0.46007635204895314548435893464149369804 ? [ lfun(L,1) | L <- concat(lfunmf(mf)) ] %6 = [0.70291..., 0.81018..., 0.46007...] @eprog\noindent The \kbd{concat} instruction concatenates the vectors corresponding to the various (here two) orbits, so that we obtain the vector of all the $L$-functions attached to eigenforms. pari-2.17.2/src/functions/modular_forms/mfspace0000644000175000017500000000206414567450071020210 0ustar billbillFunction: mfspace Section: modular_forms C-Name: mfspace Prototype: lGDG Help: mfspace(mf,{f}): identify the modular space mf, resp. the modular form f in mf. Returns 0 (newspace), 1 (cuspidal space), 2 (old space), 3 (Eisenstein space) or 4 (full space). Return -1 when the form does not belong to the space. Doc: identify the modular space \var{mf}, resp.~the modular form $f$ in \var{mf} if present, as the flag given to \kbd{mfinit}. Returns 0 (newspace), 1 (cuspidal space), 2 (old space), 3 (Eisenstein space) or 4 (full space). \bprog ? mf = mfinit([1,12],1); mfspace(mf) %1 = 1 ? mfspace(mf, mfDelta()) %2 = 0 \\ new space @eprog\noindent This function returns $-1$ when the form $f$ is modular but does not belong to the space. \bprog ? mf = mfinit([1,2]; mfspace(mf, mfEk(2)) %3 = -1 @eprog When $f$ is not modular and is for instance only quasi-modular, the function returns nonsense: \bprog ? M6 = mfinit([1,6]); ? dE4 = mfderiv(mfEk(4)); \\ not modular ! ? mfspace(M6,dE4) \\ asserts (wrongly) that E4' belongs to new space %3 = 0 @eprog pari-2.17.2/src/functions/modular_forms/mfbasis0000644000175000017500000000241114676526175020224 0ustar billbillFunction: mfbasis Section: modular_forms C-Name: mfbasis Prototype: GD4,L, Help: mfbasis(NK,{space=4}): If NK=[N,k,CHI] as in mfinit, gives a basis of the corresponding subspace of M_k(G_0(N),CHI). NK can also be the output of mfinit, in which case space is ignored. To obtain the eigenforms use mfeigenbasis. Doc: If $NK=[N,k,\var{CHI}]$ as in \kbd{mfinit}, gives a basis of the corresponding subspace of $M_{k}(\Gamma_{0}(N),\chi)$. $NK$ can also be the output of \kbd{mfinit}, in which case \kbd{space} can be omitted. To obtain the eigenforms, use \kbd{mfeigenbasis}. If \kbd{space} is a full space $M_{k}$, the output is the union of first, a basis of the space of Eisenstein series, and second, a basis of the cuspidal space. \bprog ? see(L) = apply(f->mfcoefs(f,3), L); ? mf = mfinit([35,2],0); ? see( mfbasis(mf) ) %2 = [[0, 3, -1, 0], [0, -1, 9, -8], [0, 0, -8, 10]] ? see( mfeigenbasis(mf) ) %3 = [[0, 1, 0, 1], [Mod(0, z^2 - z - 4), Mod(1, z^2 - z - 4), \ Mod(-z, z^2 - z - 4), Mod(z - 1, z^2 - z - 4)]] ? mf = mfinit([35,2]); ? see( mfbasis(mf) ) %5 = [[1/6, 1, 3, 4], [1/4, 1, 3, 4], [17/12, 1, 3, 4], \ [0, 3, -1, 0], [0, -1, 9, -8], [0, 0, -8, 10]] ? see( mfbasis([48,4],0) ) %6 = [[0, 3, 0, -3], [0, -3, 0, 27], [0, 2, 0, 30]] @eprog pari-2.17.2/src/functions/modular_forms/mfembed0000644000175000017500000000755514676526175020215 0ustar billbillFunction: mfembed Section: modular_forms C-Name: mfembed0 Prototype: GDGp Help: mfembed(f,{v}): if v is omitted, f must be a modular form or a modular form space with parameters [N,k,chi] and we return a vector of complex embeddings of Q(f) or Q(chi), respectively. If v is given, it must be a scalar in Q(f), or a vector/matrix of such, we apply the embeddings coefficientwise and return a vector of results. Finally f can be replaced by a single embedding produced by mfembed(f) and we apply that particular embedding to v. Note that, in our context, Q(chi) has a single canonical embeding given by s: Mod(t, polcyclo(n,t)) -> exp(2*I*Pi/n) and Q(f) has [Q(f):Q(chi)] induced embeddings attached to the complex roots of s(P) where P = mfparams(f)[4], as ordered by polroots. In the latter case, we only support an f with Q(f) = Q(chi) or an eigenform produced by mfeigenbasis. Doc: let $f$ be a generalized modular form with parameters $[N,k,\chi,P]$ (see \kbd{mfparams}, we denote $\Q(\chi)$ the subfield of $\C$ generated by the values of $\chi$ and $\Q(f)$ the field of definition of $f$. In this context $\Q(\chi)$ has a single canonical complex embeding given by $s: \kbd{Mod(t, polcyclo(n,t))} \mapsto \exp(2i\pi/n)$ and the number field $\Q(f)$ has $[\Q(f):\Q(\chi)]$ induced embeddings attached to the complex roots of the polynomial $s(P)$. If $\Q(f)$ is stricly larger than $\Q(\chi)$ we only allow an $f$ which is an eigenform, produced by \kbd{mfeigenbasis}. This function is meant to create embeddings of $\Q(f)$ and/or apply them to the object $v$, typically a vector of Fourier coefficients of $f$ from \kbd{mfcoefs}. \item If $v$ is omitted and $f$ is a modular form as above, we return the embedding of $\Q(\chi)$ if $\Q(\chi) = \Q(f)$ and a vector containing $[\Q(f):\Q(\chi)]$ embeddings of $\Q(f)$ otherwise. \item If $v$ is given, it must be a scalar in $\Q(f)$, or a vector/matrix of such, we apply the embeddings coefficientwise and return either a single result if $\Q(f) = \Q(\chi)$ and a vector of $[\Q(f):\Q(\chi)]$ results otherwise. \item Finally $f$ can be replaced by a single embedding produced by \kbd{mfembed}$(f)$ ($v$ was omitted) and we apply that particular embedding to $v$. \bprog ? mf = mfinit([35,2,Mod(11,35)], 0); ? [f] = mfbasis(mf); ? f.mod \\@com $\Q(\chi) = \Q(\zeta_{3})$ %3 = t^2 + t + 1 ? v = mfcoefs(f,5); lift(v) \\@com coefficients in $\Q(\chi)$ %4 = [0, 2, -2*t - 2, 2*t, 2*t, -2*t - 2] ? mfembed(f, v) \\ single embedding %5 = [0, 2, -1 - 1.7320...*I, -1 + 1.73205...*I, -1 + 1.7320...*I, ...] ? [F] = mfeigenbasis(mf); ? mffields(mf) %7 = [y^2 + Mod(-2*t, t^2 + t + 1)] \\@com $[\Q(f):\Q(\chi)] = 2$ ? V = liftpol( mfcoefs(F,5) ); %8 = [0, 1, y + (-t - 1), (t + 1)*y + t, (-2*t - 2)*y + t, -t - 1] ? vall = mfembed(F, V); #vall %9 = 2 \\ 2 embeddings, both applied to V ? vall[1] \\ the first %10 = [0, 1, -1.2071... - 2.0907...*I, 0.2071... - 0.3587...*I, ...] ? vall[2] \\ and the second one %11 = [0, 1, 0.2071... + 0.3587...*I, -1.2071... + 2.0907...*I, ...] ? vE = mfembed(F); #vE \\ same 2 embeddings %12 = 2 ? mfembed(vE[1], V) \\ apply first embedding to V %13 = [0, 1, -1.2071... - 2.0907...*I, 0.2071... - 0.3587...*I, ...] @eprog For convenience, we also allow a modular form space from \kbd{mfinit} instead of $f$, corresponding to the single embedding of $\Q(\chi)$. \bprog ? [mfB,MC,C] = mfatkininit(mf,7); MC \\@com coefs in $\Q(\chi)$ %13 = [ Mod(2/7*t, t^2 + t + 1) Mod(-1/7*t - 2/7, t^2 + t + 1)] [Mod(-1/7*t - 2/7, t^2 + t + 1) Mod(2/7*t, t^2 + t + 1)] ? C \\ normalizing constant %14 = 0.33863... - 0.16787*I ? M = mfembed(mf, MC) / C \\ the true matrix for the action of w_7 [-0.6294... + 0.4186...*I -0.3625... - 0.5450...*I] [-0.3625... - 0.5450...*I -0.6294... + 0.4186...*I] ? exponent(M*conj(M) - 1) \\ M * conj(M) is close to 1 %16 = -126 @eprog pari-2.17.2/src/functions/modular_forms/mffromqf0000644000175000017500000000313114760123736020403 0ustar billbillFunction: mffromqf Section: modular_forms C-Name: mffromqf Prototype: GDG Help: mffromqf(Q,{P}): Q being an even positive definite quadratic form and P a homogeneous spherical polynomial for Q, computes a 3-component vector [mf,F,coeffs], where F is the theta function corresponding to (Q, P), mf is the corresponding space of modular forms from mfinit, and coeffs are the coefficients of F on mfbasis(mf). Doc: $Q$ being an even integral positive definite quadratic form and $P$ a homogeneous spherical polynomial for $Q$, computes a 3-component vector $[\var{mf},F,v]$, where $F$ is the theta function corresponding to $(Q,P)$, \var{mf} is the corresponding space of modular forms (from \kbd{mfinit}), and $v$ gives the coefficients of $F$ on \kbd{mfbasis(mf)}. \bprog ? [mf,F,v] = mffromqf(2*matid(10)); v %1 = [64/5, 4/5, 32/5]~ ? mfcoefs(F, 5) %2 = [1, 20, 180, 960, 3380, 8424] ? mfcoef(F, 10000) \\ number of ways of writing 10000 as sum of 10 squares %3 = 128205250571893636 ? mfcoefs(F, 10000); \\ fast ! time = 220ms ? [mf,F,v] = mffromqf([2,0;0,2],x^4-6*x^2*y^2+y^4); ? mfcoefs(F,10) %6 = [0, 4, -16, 0, 64, -56, 0, 0, -256, 324, 224] ? mfcoef(F,100000) \\ instantaneous %7 = 41304367104 @eprog Odd dimensions are supported, corresponding to forms of half-integral weight: \bprog ? [mf,F,v] = mffromqf(2*matid(3)); ? mfisequal(F, mfpow(mfTheta(),3)) %2 = 1 ? mfcoefs(F, 32) \\ illustrate Legendre's 3-square theorem %3 = [ 1, 6, 12, 8, 6, 24, 24, 0, 12, 30, 24, 24, 8, 24, 48, 0, 6, 48, 36, 24,24, 48, 24, 0, 24, 30, 72, 32, 0, 72, 48, 0, 12] @eprog pari-2.17.2/src/functions/modular_forms/mfcuspval0000644000175000017500000000264014567450071020572 0ustar billbillFunction: mfcuspval Section: modular_forms C-Name: mfcuspval Prototype: GGGb Help: mfcuspval(mf,F,cusp): valuation of modular form F in the space mf at cusp, which can be either oo or any rational number. The result is either a rational number or oo if F is zero. Let chi be the Nebentypus of the space mf; if Q(F) != Q(chi), return the vector of valuations attached to the [Q(F):Q(chi)] complex embeddings of F. Doc: valuation of modular form $F$ in the space \kbd{mf} at \kbd{cusp}, which can be either $\infty$ or any rational number. The result is either a rational number or $\infty$ if $F$ is zero. Let $\chi$ be the Nebentypus of the space \kbd{mf}; if $\Q(F) \neq \Q(\chi)$, return the vector of valuations attached to the $[\Q(F):\Q(chi)]$ complex embeddings of $F$. \bprog ? T=mfTheta(); mf=mfinit([12,1/2]); mfcusps(12) %1 = [0, 1/2, 1/3, 1/4, 1/6, 1/12] ? apply(x->mfcuspval(mf,T,x), %1) %2 = [0, 1/4, 0, 0, 1/4, 0] ? mf=mfinit([12,6,12],1); F=mfbasis(mf)[5]; ? apply(x->mfcuspval(mf,F,x),%1) %4 = [1/12, 1/6, 1/2, 2/3, 1/2, 2] ? mf=mfinit([12,3,-4],1); F=mfbasis(mf)[1]; ? apply(x->mfcuspval(mf,F,x),%1) %6 = [1/12, 1/6, 1/4, 2/3, 1/2, 1] ? mf = mfinit([625,2],0); [F] = mfeigenbasis(mf); mfparams(F) %7 = [625, 2, 1, y^2 - y - 1, t - 1] \\ [Q(F):Q(chi)] = 2 ? mfcuspval(mf, F, 1/25) %8 = [1, 2] \\ one conjugate has valuation 1, and the other is 2 ? mfcuspval(mf, F, 1/5) %9 = [1/25, 1/25] @eprog pari-2.17.2/src/functions/modular_forms/mfisCM0000644000175000017500000000166614676526175017771 0ustar billbillFunction: mfisCM Section: modular_forms C-Name: mfisCM Prototype: G Help: mfisCM(F): Tests whether the eigenform F is a CM form. The answer is 0 if it is not, and if it is, either the unique negative discriminant of the CM field, or the pair of two negative discriminants of CM fields, this latter case occurring only in weight 1 when the projective image is D2=C2xC2, i.e., coded 4 by mfgaloistype. Doc: Tests whether the eigenform $F$ is a CM form. The answer is $0$ if it is not, and if it is, either the unique negative discriminant of the CM field, or the pair of two negative discriminants of CM fields, this latter case occurring only in weight $1$ when the projective image is $D_{2}=C_{2}\times C_{2}$, i.e., coded $4$ by \kbd{mfgaloistype}. \bprog ? F = mffromell(ellinit([0,1]))[2]; mfisCM(F) %1 = -3 ? mf = mfinit([39,1,-39],0); F=mfeigenbasis(mf)[1]; mfisCM(F) %2 = Vecsmall([-3, -39]) ? mfgaloistype(mf) %3 = [4] @eprog pari-2.17.2/src/functions/modular_forms/mfdim0000644000175000017500000000541314676526175017701 0ustar billbillFunction: mfdim Section: modular_forms C-Name: mfdim Prototype: GD4,L, Help: mfdim(NK,{space=4}): If NK=[N,k,CHI] as in mfinit, gives the dimension of the corresponding subspace of M_k(G_0(N),chi). The subspace is described by a small integer 'space': 0 for the newspace, 1 for the cuspidal space, 2 for the oldspace, 3 for the space of Eisenstein series and 4 (default) for the full space M_k. NK can also be the output of mfinit, in which case space must be omitted. Doc: If $NK=[N,k,\var{CHI}]$ as in \kbd{mfinit}, gives the dimension of the corresponding subspace of $M_{k}(\Gamma_{0}(N),\chi)$. $NK$ can also be the output of \kbd{mfinit}, in which case space must be omitted. The subspace is described by the small integer \kbd{space}: $0$ for the newspace $S_{k}^{\text{new}}(\Gamma_{0}(N),\chi)$, $1$ for the cuspidal space $S_{k}$, $2$ for the oldspace $S_{k}^{\text{old}}$, $3$ for the space of Eisenstein series $E_{k}$ and $4$ for the full space $M_{k}$. \misctitle{Wildcards} As in \kbd{mfinit}, \var{CHI} may be the wildcard 0 (all Galois orbits of characters); in this case, the output is a vector of $[\var{order}, \var{conrey}, \var{dim}, \var{dimdih}]$ corresponding to the nontrivial spaces, where \item \var{order} is the order of the character, \item \var{conrey} its Conrey label from which the character may be recovered via \kbd{znchar}$(\var{conrey})$, \item \var{dim} the dimension of the corresponding space, \item \var{dimdih} the dimension of the subspace of dihedral forms corresponding to Hecke characters if $k = 1$ (this is not implemented for the old space and set to $-1$ for the time being) and 0 otherwise. The spaces are sorted by increasing order of the character; the characters are taken up to Galois conjugation and the Conrey number is the minimal one among Galois conjugates. In weight $1$, this is only implemented when the space is 0 (newspace), 1 (cusp space), 2(old space) or 3(Eisenstein series). \misctitle{Wildcards for sets of characters} \var{CHI} may be a set of characters, and we return the set of $[\var{dim},\var{dimdih}]$. \misctitle{Wildcard for $M_{k}(\Gamma_{1}(N))$} Additionally, the wildcard $\var{CHI} = -1$ is available in which case we output the total dimension of the corresponding subspace of $M_{k}(\Gamma_{1}(N))$. In weight $1$, this is not implemented when the space is 4 (fullspace). \bprog ? mfdim([23,2], 0) \\ new space %1 = 2 ? mfdim([96,6], 0) %2 = 10 ? mfdim([10^9,4], 3) \\ Eisenstein space %1 = 40000 ? mfdim([10^9+7,4], 3) %2 = 2 ? mfdim([68,1,-1],0) %3 = 3 ? mfdim([68,1,0],0) %4 = [[2, Mod(67, 68), 1, 1], [4, Mod(47, 68), 1, 1]] ? mfdim([124,1,0],0) %5 = [[6, Mod(67, 124), 2, 0]] @eprog This last example shows that there exists a nondihedral form of weight 1 in level 124. pari-2.17.2/src/functions/modular_forms/mftobasis0000644000175000017500000000560214676526175020574 0ustar billbillFunction: mftobasis Section: modular_forms C-Name: mftobasis Prototype: GGD0,L, Help: mftobasis(mf,F,{flag=0}): coefficients of the form F on the basis given by the mfbasis(mf). A q-expansion or vector of coefficients can also be given instead of F, but in this case an error message may occur if the expansion is too short. An error message is also given if F does not belong to the modular form space. If flag is set, instead of error messages return an output as an affine space of solutions if a q-expansion or vector of coefficients is given, or the empty column otherwise. Doc: coefficients of the form $F$ on the basis given by \kbd{mfbasis(mf)}. A $q$-expansion or vector of coefficients can also be given instead of $F$, but in this case an error message may occur if the expansion is too short. An error message is also given if $F$ does not belong to the modular form space. If $\fl$ is set, instead of error messages the output is an affine space of solutions if a $q$-expansion or vector of coefficients is given, or the empty column otherwise. \bprog ? mf = mfinit([26,2],0); mfdim(mf) %1 = 2 ? F = mflinear(mf,[a,b]); mftobasis(mf,F) %2 = [a, b]~ @eprog A $q$-expansion or vector of coefficients can also be given instead of $F$. \bprog ? Th = 1 + 2*sum(n=1, 8, q^(n^2), O(q^80)); ? mf = mfinit([4,5,Mod(3,4)]); ? mftobasis(mf, Th^10) %3 = [64/5, 4/5, 32/5]~ @eprog If $F$ does not belong to the corresponding space, the result is incorrect and simply matches the coefficients of $F$ up to some bound, and the function may either return an empty column or an error message. If $\fl$ is set, there are no error messages, and the result is an empty column if $F$ is a modular form; if $F$ is supplied via a series or vector of coefficients which does not contain enough information to force a unique (potential) solution, the function returns $[v,K]$ where $v$ is a solution and $K$ is a matrix of maximal rank describing the affine space of potential solutions $v + K\cdot x$. \bprog ? mf = mfinit([4,12],1); ? mftobasis(mf, q-24*q^2+O(q^3), 1) %2 = [[43/64, -63/8, 800, 21/64]~, [1, 0; 24, 0; 2048, 768; -1, 0]] ? mftobasis(mf, [0,1,-24,252], 1) %3 = [[1, 0, 1472, 0]~, [0; 0; 768; 0]] ? mftobasis(mf, [0,1,-24,252,-1472], 1) %4 = [1, 0, 0, 0]~ \\ now uniquely determined ? mftobasis(mf, [0,1,-24,252,-1472,0], 1) %5 = [1, 0, 0, 0]~ \\ wrong result: no such form exists ? mfcoefs(mflinear(mf,%), 5) \\ double check %6 = [0, 1, -24, 252, -1472, 4830] ? mftobasis(mf, [0,1,-24,252,-1472,0]) *** at top-level: mftobasis(mf,[0,1, *** ^-------------------- *** mftobasis: domain error in mftobasis: form does not belong to space ? mftobasis(mf, mfEk(10)) *** at top-level: mftobasis(mf,mfEk( *** ^-------------------- *** mftobasis: domain error in mftobasis: form does not belong to space ? mftobasis(mf, mfEk(10), 1) %7 = []~ @eprog pari-2.17.2/src/functions/modular_forms/mfnumcusps0000644000175000017500000000042014676526175020776 0ustar billbillFunction: mfnumcusps Section: modular_forms C-Name: mfnumcusps Prototype: G Help: mfnumcusps(N): number of cusps of Gamma_0(N) Doc: number of cusps of $\Gamma_{0}(N)$ \bprog ? mfnumcusps(24) %1 = 8 ? mfcusps(24) %1 = [0, 1/2, 1/3, 1/4, 1/6, 1/8, 1/12, 1/24] @eprog pari-2.17.2/src/functions/modular_forms/mfderiv0000644000175000017500000000106314567450071020224 0ustar billbillFunction: mfderiv Section: modular_forms C-Name: mfderiv Prototype: GD1,L, Help: mfderiv(F,{m=1}): m-th formal derivative of the power series corresponding to the generalized modular form F, with respect to the differential operator q.d/dq (default m=1). Doc: $m$-th formal derivative of the power series corresponding to the generalized modular form $F$, with respect to the differential operator $qd/dq$ (default $m=1$). \bprog ? D=mfDelta(); ? mfcoefs(D, 4) %2 = [0, 1, -24, 252, -1472] ? mfcoefs(mfderiv(D), 4) %3 = [0, 1, -48, 756, -5888] @eprog pari-2.17.2/src/functions/modular_forms/mflinear0000644000175000017500000000330114567450071020362 0ustar billbillFunction: mflinear Section: modular_forms C-Name: mflinear Prototype: GG Help: mflinear(vF,v): vF being a vector of modular forms and v a vector of coefficients of same length, compute the linear combination of the entries of vF with coefficients v. Doc: \kbd{vF} being a vector of generalized modular forms and \kbd{v} a vector of coefficients of same length, compute the linear combination of the entries of \kbd{vF} with coefficients \kbd{v}. \misctitle{Note} Use this in particular to subtract two forms $F$ and $G$ (with $vF=[F,G]$ and $v=[1,-1]$), or to multiply an form by a scalar $\lambda$ (with $vF=[F]$ and $v=[\lambda]$). \bprog ? D = mfDelta(); G = mflinear([D],[-3]); ? mfcoefs(G,4) %2 = [0, -3, 72, -756, 4416] @eprog For user convenience, we allow \item a modular form space \kbd{mf} as a \kbd{vF} argument, which is understood as \kbd{mfbasis(mf)}; \item in this case, we also allow a modular form $f$ as $v$, which is understood as \kbd{mftobasis}$(\var{mf}, f)$. \bprog ? T = mfpow(mfTheta(),7); F = mfShimura(T,-3); \\ Shimura lift for D=-3 ? mfcoefs(F,8) %2 = [-5/9, 280, 9240, 68320, 295960, 875280, 2254560, 4706240, 9471000] ? mf = mfinit(F); G = mflinear(mf,F); ? mfcoefs(G,8) %4 = [-5/9, 280, 9240, 68320, 295960, 875280, 2254560, 4706240, 9471000] @eprog\noindent This last construction allows to replace a general modular form by a simpler linear combination of basis functions, which is often more efficient: \bprog ? T10=mfpow(mfTheta(),10); mfcoef(T10, 10^4) \\ direct evaluation time = 399 ms. %5 = 128205250571893636 ? mf=mfinit(T10); F=mflinear(mf,T10); \\ instantaneous ? mfcoef(F, 10^4) \\ after linearization time = 67 ms. %7 = 128205250571893636 @eprog pari-2.17.2/src/functions/modular_forms/mffrometaquo0000644000175000017500000000261514676526175021313 0ustar billbillFunction: mffrometaquo Section: modular_forms C-Name: mffrometaquo Prototype: GD0,L, Help: mffrometaquo(eta,{flag=0}): modular form corresponding to the eta quotient matrix eta. If the valuation v at infinity is fractional, returns 0. If the eta quotient is not holomorphic but simply meromorphic, returns 0 if flag=0; returns the eta quotient (divided by q to the power -v if v < 0, i.e., with valuation 0) if flag is set. Doc: modular form corresponding to the eta quotient matrix \kbd{eta}. If the valuation $v$ at infinity is fractional, returns $0$. If the eta quotient is not holomorphic but simply meromorphic, returns $0$ if $\fl=0$; returns the eta quotient (divided by $q$ to the power $-v$ if $v < 0$, i.e., with valuation $0$) if $\fl$ is set. \bprog ? mffrometaquo(Mat([1,1]),1) %1 = 0 ? mfcoefs(mffrometaquo(Mat([1,24])),6) %2 = [0, 1, -24, 252, -1472, 4830, -6048] ? mfcoefs(mffrometaquo([1,1;23,1]),10) %3 = [0, 1, -1, -1, 0, 0, 1, 0, 1, 0, 0] ? F = mffrometaquo([1,2;2,-1]); mfparams(F) %4 = [16, 1/2, 1, y, t - 1] ? mfcoefs(F,10) %5 = [1, -2, 0, 0, 2, 0, 0, 0, 0, -2, 0] ? mffrometaquo(Mat([1,-24])) %6 = 0 ? f = mffrometaquo(Mat([1,-24]),1); mfcoefs(f,6) %7 = [1, 24, 324, 3200, 25650, 176256, 1073720] @eprog\noindent For convenience, a \typ{VEC} is also accepted instead of a factorization matrix with a single row: \bprog ? f = mffrometaquo([1,24]); \\ also valid @eprog pari-2.17.2/src/functions/modular_forms/mfsearch0000644000175000017500000000434014676526175020373 0ustar billbillFunction: mfsearch Section: modular_forms C-Name: mfsearch Prototype: GGD4,L, Help: mfsearch(NK,V,{space}): NK being of the form [N,k] with k possibly half-integral, search for a modular form with rational coefficients, of weight k and level N, whose initial coefficients a(0),... are equal to V; space specifies the modular form spaces in which to search. The output is a list of matching forms with that given level and weight. Note that the character is of the form (D/.), where D is a (positive or negative) fundamental discriminant dividing N. N can be replaced by a vector of allowed levels, in which case the list of forms is sorted by increasing level, then increasing |D|. If a form is found at level N, any multiple of N with the same D is not considered Note that this is very different from mfeigensearch, which only searches for rational eigenforms. Doc: \kbd{NK} being of the form \kbd{[N,k]} with $k$ possibly half-integral, search for a modular form with rational coefficients, of weight $k$ and level $N$, whose initial coefficients $a(0)$,... are equal to $V$; \kbd{space} specifies the modular form spaces in which to search, in \kbd{mfinit} or \kbd{mfdim} notation. The output is a list of matching forms with that given level and weight. Note that the character is of the form $(D/.)$, where $D$ is a (positive or negative) fundamental discriminant dividing $N$. The forms are sorted by increasing $|D|$. The parameter $N$ can be replaced by a vector of allowed levels, in which case the list of forms is sorted by increasing level, then increasing $|D|$. If a form is found at level $N$, any multiple of $N$ with the same $D$ is not considered. Some useful possibilities are \item \kbd{[$N_{1}$..$N_{2}$]}: all levels between $N_{1}$ and $N_{2}$, endpoints included; \item \kbd{$F$ * [$N_{1}$..$N_{2}$]}: same but levels divisible by $F$; \item \kbd{divisors}$(N_{0})$: all levels dividing $N_{0}$. Note that this is different from \kbd{mfeigensearch}, which only searches for rational eigenforms. \bprog ? F = mfsearch([[1..40], 2], [0,1,2,3,4], 1); #F %1 = 3 ? [ mfparams(f)[1..3] | f <- F ] %2 = [[38, 2, 1], [40, 2, 8], [40, 2, 40]] ? mfcoefs(F[1],10) %3 = [0, 1, 2, 3, 4, -5, -8, 1, -7, -5, 7] @eprog pari-2.17.2/src/functions/modular_forms/mfperiodpolbasis0000644000175000017500000000076514676526175022154 0ustar billbillFunction: mfperiodpolbasis Section: modular_forms C-Name: mfperiodpolbasis Prototype: LD0,L, Help: mfperiodpolbasis(k,{flag=0}): basis of period polynomials for weight k. If flag=1 or -1, basis of odd or even period polynomials. Doc: Basis of period polynomials for weight $k$. If $\fl=1$ or $-1$, basis of odd or even period polynomials. \bprog ? mfperiodpolbasis(12,1) %1 = [x^8 - 3*x^6 + 3*x^4 - x^2, x^10 - 1] ? mfperiodpolbasis(12,-1) %2 = [4*x^9 - 25*x^7 + 42*x^5 - 25*x^3 + 4*x] @eprog pari-2.17.2/src/functions/modular_forms/mfcusps0000644000175000017500000000103614676526175020262 0ustar billbillFunction: mfcusps Section: modular_forms C-Name: mfcusps Prototype: G Help: mfcusps(N): list of cusps of G_0(N) in the form a/b with b dividing N. Doc: let $N$ be a positive integer. Return the list of cusps of $\Gamma_{0}(N)$ in the form $a/b$ with $b\mid N$. \bprog ? mfcusps(24) %1 = [0, 1/2, 1/3, 1/4, 1/6, 1/8, 1/12, 1/24] @eprog\noindent We also allow the argument $N$ to be a modular form space, in which case it is replaced by the level of the space: \bprog ? M = mfinit([4, 12, 1], 0); mfcusps(M) %2 = [0, 1/2, 1/4] @eprog pari-2.17.2/src/functions/modular_forms/mffields0000644000175000017500000000216614676526175020400 0ustar billbillFunction: mffields Section: modular_forms C-Name: mffields Prototype: G Help: mffields(mf): If mf is output by mfinit, gives the vector of polynomials defining each Galois orbit of the new space. Doc: Given \kbd{mf} as output by \kbd{mfinit} with parameters $(N,k,\chi)$, returns the vector of polynomials defining each Galois orbit of newforms over $\Q(\chi)$. \bprog ? mf = mfinit([35,2],0); mffields(mf) %1 = [y, y^2 - y - 4] @eprog\noindent Here the character is trivial so $\Q(\chi) = \Q)$ and there are 3 newforms: one is rational (corresponding to $y$), the other two are conjugate and defined over the quadratic field $\Q[y]/(y^{2}-y-4)$. \bprog ? [G,chi] = znchar(Mod(3,35)); ? zncharconductor(G,chi) %2 = 35 ? charorder(G,chi) %3 = 12 ? mf = mfinit([35, 2, [G,chi]],0); mffields(mf) %4 = [y, y] @eprog Here the character is primitive of order 12 and the two newforms are defined over $\Q(\chi) = \Q(\zeta_{12})$. \bprog ? mf = mfinit([35, 2, Mod(13,35)],0); mffields(mf) %3 = [y^2 + Mod(5*t, t^2 + 1)] @eprog This time the character has order 4 and there are two conjugate newforms over $\Q(\chi) = Q(i)$. pari-2.17.2/src/functions/modular_forms/mfkohnenbijection0000644000175000017500000000607714676526175022310 0ustar billbillFunction: mfkohnenbijection Section: modular_forms C-Name: mfkohnenbijection Prototype: G Help: mfkohnenbijection(mf): mf being a cuspidal space of half-integral weight returns [mf2,M,K,shi], where M is a matrix giving a Hecke-module isomorphism from S_{2k-1}(N,CHI^2) given by mf2 to the Kohnen + space S_k+(4N,CHI), K is a basis of the Kohnen + space, and shi gives the linear combination of Shimura lifts giving M^(-1). Doc: Let \kbd{mf} be a cuspidal space of half-integral weight and weight $4N$, with $N$ squarefree and let $S_{k}^{+}(\Gamma_{0}(4N),\chi)$ be the Kohnen $+$-space. Returns \kbd{[mf2,M,K,shi]}, where \item \kbd{mf2} gives the cuspidal space $S_{2k-1}(\Gamma_{0}(N),\chi^{2})$; \item $M$ is a matrix giving a Hecke-module isomorphism from that space to the Kohnen $+$-space $S_{k}^{+}(\Gamma_{0}(4N),\chi)$; \item \kbd{K} represents a basis $B$ of the Kohnen $+$-space as a matrix whose columns are the coefficients of $B$ on the basis of \kbd{mf}; \item \kbd{shi} is a vector of pairs $(t_{i},n_{i})$ gives the linear combination of Shimura lifts giving $M^{-1}$: $t_{i}$ is a squarefree positive integer and $n_{i}$ is a small nonzero integer. \bprog ? mf=mfinit([60,5/2],1); [mf2,M,K,shi]=mfkohnenbijection(mf); M %2 = [-3 0 5/2 7/2] [ 1 -1/2 -7 -7] [ 1 1/2 0 -3] [ 0 0 5/2 5/2] ? shi %2 = [[1, 1], [2, 1]] @eprog This last command shows that the map giving the bijection is the sum of the Shimura lift with $t=1$ and the one with $t=2$. Since it gives a bijection of Hecke modules, this matrix can be used to transport modular form data from the easily computed space of level $N$ and weight $2k-1$ to the more difficult space of level $4N$ and weight $k$: matrices of Hecke operators, new space, splitting into eigenspaces and eigenforms. Examples: \bprog ? K^(-1)*mfheckemat(mf,121)*K /* matrix of T_11^2 on K. Slowish. */ time = 1,280 ms. %1 = [ 48 24 24 24] [ 0 32 0 -20] [-48 -72 -40 -72] [ 0 0 0 52] ? M*mfheckemat(mf2,11)*M^(-1) /* instantaneous via T_11 on S_{2k-1} */ time = 0 ms. %2 = [ 48 24 24 24] [ 0 32 0 -20] [-48 -72 -40 -72] [ 0 0 0 52] ? mf20=mfinit(mf2,0); [mftobasis(mf2,b) | b<-mfbasis(mf20)] %3 = [[0, 0, 1, 0]~, [0, 0, 0, 1]~] ? F1=M*[0,0,1,0]~ %4 = [1/2, 1/2, -3/2, -1/2]~ ? F2=M*[0,0,0,1]~ %5 = [3/2, 1/2, -9/2, -1/2] ? K*F1 %6 = [1, 0, 0, 1, 1, 0, 0, 1, -3, 0, 0, -3, 0, 0]~ ? K*F2 %7 = [3, 0, 0, 3, 1, 0, 0, 1, -9, 0, 0, -3, 0, 0]~ @eprog This gives a basis of the new space of $S_{5/2}^{+}(\Gamma_{0}(60))$ expressed on the initial basis of $S_{5/2}(\Gamma_{0}(60))$. To obtain the eigenforms, we write instead: \bprog ? BE=mfeigenbasis(mf20);[E1,E2]=apply(x->K*M*mftobasis(mf2,x),BE) %1 = [[1, 0, 0, 1, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0]~,\ [0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, -3, 0, 0]~ ? EI1 = mflinear(mf, E1); EI2=mflinear(mf, E2); @eprog\noindent These are the two eigenfunctions in the space \kbd{mf}, the first (resp., second) will have Shimura image a multiple of $BE[1]$ (resp., $BE[2]$). The function \kbd{mfkohneneigenbasis} does this directly. pari-2.17.2/src/functions/modular_forms/mfeisenstein0000644000175000017500000000455614676526175021305 0ustar billbillFunction: mfeisenstein Section: modular_forms C-Name: mfeisenstein Prototype: LDGDG Help: mfeisenstein(k,{CHI1},{CHI2}): create the Eisenstein E_k(CHI1,CHI2), where an omitted character is considered as trivial. Doc: create the Eisenstein series $E_{k}(\chi_{1},\chi_{2})$, where $k \geq 1$, $\chi_{i}$ are Dirichlet characters and an omitted character is considered as trivial. This form belongs to ${\cal E}_{k}(\Gamma_{0}(N), \chi)$ with $\chi = \chi_{1}\chi_{2}$ and $N$ is the product of the conductors of $\chi_{1}$ and $\chi_{2}$. \bprog ? CHI = Mod(3,4); ? E = mfeisenstein(3, CHI); ? mfcoefs(E, 6) %2 = [-1/4, 1, 1, -8, 1, 26, -8] ? CHI2 = Mod(4,5); ? mfcoefs(mfeisenstein(3,CHI,CHI2), 6) %3 = [0, 1, -1, -10, 1, 25, 10] ? mfcoefs(mfeisenstein(4,CHI,CHI), 6) %4 = [0, 1, 0, -28, 0, 126, 0] ? mfcoefs(mfeisenstein(4), 6) %5 = [1/240, 1, 9, 28, 73, 126, 252] @eprog\noindent Note that \kbd{mfeisenstein}$(k)$ is 0 for $k$ odd and $-B_{k}/(2k) \cdot E_{k}$ for $k$ even, where $$E_{k}(q) = 1 - (2k/B_{k})\sum_{n\geq 1} \sigma_{k-1}(n) q^{n}$$ is the standard Eisenstein series. In other words it is normalized so that its linear coefficient is $1$. \misctitle{Important note} This function is currently implemented only when $\Q(\chi)$ is the field of definition of $E_{k}(\chi_{1},\chi_{2})$. If it is a strict subfield, an error is raised: \bprog ? mfeisenstein(6, Mod(7,9), Mod(4,9)); *** at top-level: mfeisenstein(6,Mod(7,9),Mod(4,9)) *** ^--------------------------------- *** mfeisenstein: sorry, mfeisenstein for these characters is not *** yet implemented. @eprog\noindent The reason for this is that each modular form is attached to a modular form space $M_{k}(\Gamma_{0}(N),\chi)$. This is a $\C$-vector space but it allows a basis of forms defined over $\Q(\chi)$ and is only implemented as a $\Q(\chi)$-vector space: there is in general no mechanism to take linear combinations of forms in the space with coefficients belonging to a larger field. (Due to their importance, eigenforms are the single exception to this restriction; for an eigenform $F$, $\Q(F)$ is built on top of $\Q(\chi)$.) When the property $\Q(\chi) = \Q(E_{k}(\chi_{1},\chi_{2})$ does not hold, we cannot express $E$ as a $\Q(\chi)$-linear combination of the basis forms and many operations will fail. For this reason, the construction is currently disabled. pari-2.17.2/src/functions/modular_forms/mfinit0000644000175000017500000000545014676526175020074 0ustar billbillFunction: mfinit Section: modular_forms C-Name: mfinit Prototype: GD4,L, Help: mfinit(NK,{space=4}): Create the space of modular forms corresponding to the data contained in NK and space. NK is a vector which can be either [N,k] (N level, k weight) corresponding to a subspace of M_k(G_0(N)), or [N,k,CHI] (CHI a character) corresponding to a subspace of M_k(G_0(N),chi). The subspace is described by a small integer 'space': 0 for the newspace, 1 for the cuspidal space, 2 for the oldspace, 3 for the space of Eisenstein series and 4 (default) for the full space M_k Doc: Create the space of modular forms corresponding to the data contained in \kbd{NK} and \kbd{space}. \kbd{NK} is a vector which can be either $[N,k]$ ($N$ level, $k$ weight) corresponding to a subspace of $M_{k}(\Gamma_{0}(N))$, or $[N,k,\var{CHI}]$ (\var{CHI} a character) corresponding to a subspace of $M_{k}(\Gamma_{0}(N),\chi)$. Alternatively, it can be a modular form $F$ or modular form space, in which case we use \kbd{mfparams} to define the space parameters. The subspace is described by the small integer \kbd{space}: $0$ for the newspace $S_{k}^{\text{new}}(\Gamma_{0}(N),\chi)$, $1$ for the cuspidal space $S_{k}$, $2$ for the oldspace $S_{k}^{\text{old}}$, $3$ for the space of Eisenstein series $E_{k}$ and $4$ for the full space $M_{k}$. \misctitle{Wildcards} For given level and weight, it is advantageous to compute simultaneously spaces attached to different Galois orbits of characters, especially in weight $1$. The parameter \var{CHI} may be set to 0 (wildcard), in which case we return a vector of all \kbd{mfinit}(s) of non trivial spaces in $S_{k}(\Gamma_{1}(N))$, one for each Galois orbit (see \kbd{znchargalois}). One may also set \var{CHI} to a vector of characters and we return a vector of all mfinits of subspaces of $M_{k}(G_{0}(N),\chi)$ for $\chi$ in the list, in the same order. In weight $1$, only $S_{1}^{\text{new}}$, $S_{1}$ and $E_{1}$ support wildcards. The output is a technical structure $S$, or a vector of structures if \var{CHI} was a wildcard, which contains the following information: $[N,k,\chi]$ is given by \kbd{mfparams}$(S)$, the space dimension is \kbd{mfdim}$(S)$ and a $\C$-basis for the space is \kbd{mfbasis}$(S)$. The structure is entirely algebraic and does not depend on the current \kbd{realbitprecision}. \bprog ? S = mfinit([36,2], 0); \\ new space ? mfdim(S) %2 = 1 ? mfparams %3 = [36, 2, 1, y] \\ trivial character ? f = mfbasis(S)[1]; mfcoefs(f,10) %4 = [0, 1, 0, 0, 0, 0, 0, -4, 0, 0, 0] ? vS = mfinit([36,2,0],0); \\ with wildcard ? #vS %6 = 4 \\ 4 non trivial spaces (mod Galois action) ? apply(mfdim,vS) %7 = [1, 2, 1, 4] ? mfdim([36,2,0], 0) %8 = [[1, Mod(1, 36), 1, 0], [2, Mod(35, 36), 2, 0], [3, Mod(13, 36), 1, 0], [6, Mod(11, 36), 4, 0]] @eprog pari-2.17.2/src/functions/modular_forms/mfcuspisregular0000644000175000017500000000074514676526175022023 0ustar billbillFunction: mfcuspisregular Section: modular_forms C-Name: mfcuspisregular Prototype: lGG Help: mfcuspisregular(NK,cusp): In the space defined by NK = [N,k,CHI] or NK = mf, determine if cusp in canonical format (oo or denominator dividing N) is regular or not. Doc: In the space defined by \kbd{NK = [N,k,CHI]} or \kbd{NK = mf}, determine if \kbd{cusp} in canonical format (oo or denominator dividing $N$) is regular or not. \bprog ? mfcuspisregular([4,3,-4],1/2) %1 = 0 @eprog pari-2.17.2/src/functions/transcendental/0000755000175000017500000000000014760315601016773 5ustar billbillpari-2.17.2/src/functions/transcendental/besselk0000644000175000017500000000031113637407207020347 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.17.2/src/functions/transcendental/gammamellininvinit0000644000175000017500000000317614676526175022631 0ustar billbillFunction: gammamellininvinit Section: transcendental C-Name: gammamellininvinit Prototype: GD0,L,b Help: gammamellininvinit(A,{m=0}): initialize data for the computation by gammamellininv() of the m-th derivative of the inverse Mellin transform of the function f(s) = Gamma_R(s+a1)*...*Gamma_R(s+ad), where A is the vector [a1,...,ad] and Gamma_R(s) = Pi^(-s/2)*gamma(s/2). Doc: initialize data for the computation by \tet{gammamellininv} of the $m$-th derivative of the inverse Mellin transform of the function $$f(s) = \Gamma_{\R}(s+a_{1})\*\ldots\*\Gamma_{\R}(s+a_{d})$$ where \kbd{A} is the vector $[a_{1},\ldots,a_{d}]$ and $\Gamma_{\R}(s)=\pi^{-s/2}\*\Gamma(s/2)$ (Euler's \kbd{gamma}). This is the special case of Meijer's $G$ functions used to compute $L$-values via the approximate functional equation. By extension, $A$ is allowed to be an \kbd{Ldata} or an \kbd{Linit}, understood as the inverse Mellin transform of the $L$-function gamma factor. \misctitle{Caveat} Contrary to the PARI convention, this function guarantees an \emph{absolute} (rather than relative) error bound. For instance, the inverse Mellin transform of $\Gamma_{\R}(s)$ is $2\exp(-\pi z^{2})$: \bprog ? G = gammamellininvinit([0]); ? gammamellininv(G, 2) - 2*exp(-Pi*2^2) %2 = -4.484155085839414627 E-44 @eprog The inverse Mellin transform of $\Gamma_{\R}(s+1)$ is $2 z\exp(-\pi z^{2})$, and its second derivative is $ 4\pi z \exp(-\pi z^{2})(2\pi z^{2} - 3)$: \bprog ? G = gammamellininvinit([1], 2); ? a(z) = 4*Pi*z*exp(-Pi*z^2)*(2*Pi*z^2-3); ? b(z) = gammamellininv(G,z); ? t(z) = b(z) - a(z); ? t(3/2) %3 = -1.4693679385278593850 E-39 @eprog pari-2.17.2/src/functions/transcendental/zetamultconvert0000644000175000017500000000166114676526175022210 0ustar billbillFunction: zetamultconvert Section: transcendental C-Name: zetamultconvert Prototype: GD1,L, Help: zetamultconvert(a,{flag=1}): a being either an evec, avec, or index m, converts into evec (flag=0), avec (flag=1), or index m (flag=2). Doc: \kbd{a} being either an \kbd{evec}, \kbd{avec}, or index \kbd{m}, converts into \kbd{evec} ($\fl=0$), \kbd{avec} ($\fl=1$), or index \kbd{m} ($\fl=2$). \bprog ? zetamultconvert(10) %1 = Vecsmall([3, 2]) ? zetamultconvert(13) %2 = Vecsmall([2, 2, 1]) ? zetamultconvert(10, 0) %3 = Vecsmall([0, 0, 1, 0, 1]) ? zetamultconvert(13, 0) %4 = Vecsmall([0, 1, 0, 1, 1]) @eprog\noindent The last two lines imply that $[3,2]$ and $[2,2,1]$ are dual (reverse order of bits and swap $0$ and $1$ in \kbd{evec} form). Hence they have the same zeta value: \bprog ? zetamult([3,2]) %5 = 0.22881039760335375976874614894168879193 ? zetamult([2,2,1]) %6 = 0.22881039760335375976874614894168879193 @eprog pari-2.17.2/src/functions/transcendental/eta0000644000175000017500000000212714676526175017511 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 nonzero, 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 nonzero, $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.17.2/src/functions/transcendental/gammamellininv0000644000175000017500000000126514567450071021730 0ustar billbillFunction: gammamellininv Section: transcendental C-Name: gammamellininv Prototype: GGD0,L,b Help: gammamellininv(G,t,{m=0}): returns G(t), where G is as output by gammamellininvinit (its m-th derivative if m is present). Doc: returns the value at $t$ of the inverse Mellin transform $G$ initialized by \tet{gammamellininvinit}. If the optional parameter $m$ is present, return the $m$-th derivative $G^{(m)}(t)$. \bprog ? G = gammamellininvinit([0]); ? gammamellininv(G, 2) - 2*exp(-Pi*2^2) %2 = -4.484155085839414627 E-44 @eprog The shortcut \bprog gammamellininv(A,t,m) @eprog\noindent for \bprog gammamellininv(gammamellininvinit(A,m), t) @eprog\noindent is available. pari-2.17.2/src/functions/transcendental/HEADER0000644000175000017500000001472114676526175017673 0ustar billbillFunction: _header_transcendental Class: header Section: transcendental Doc: \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}, which can be view and manipulated using the defaults \tet{realprecision} (in decimal digits) or \tet{realbitprecision} (in bits). This precision can be changed indifferently \item in decimal digits: use \b{p} or \kbd{default(realprecision,...)}. \item in bits: use \b{pb} or \kbd{default(realbitprecision,...)}. 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 functions allow a \kbd{bitprec} argument instead which allow finer granularity.) Some accuracies attainable on 32-bit machines cannot be attained on 64-bit machines for parity reasons. For example, an accuracy of 28 decimal digits on 32-bit machines corresponds to \var{prec} having the value 5, for a mantissa of $3 \times 32 = 96$ bits. But this cannot be attained on 64-bit machines: we can attain either 64 or 128 bits, but values in between. \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 \bprog x = gtoser(x, gvar(x), seriesprec) @eprog\noindent 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 \emph{componentwise} evaluation of the function. In particular, transcendental functions on square matrices, are not built-in. For this you can use the following technique, which is neither very efficient nor numerical stable, but is often good enough provided we restrict to diagonalizable matrices: \bprog mateval(f, M) = { my([L, H] = mateigen(M, 1)); H * matdiagonal(f(L)) * H^(-1); } ? A = [13,2;10,14]; ? a = mateval(sqrt, A) /*@Ccom approximates $\sqrt{A}$ */ %2 = [3.5522847498307933... 0.27614237491539669...] [1.3807118745769834... 3.69035593728849174...] ? exponent(a^2 - A) %3 = -123 \\ OK ? b = mateval(exp, A); ? exponent(mateval(log, b) - A) %5 = -115 \\ tolerable @eprog The absolute error depends on the condition number of the base change matrix $H$ and on the largest $|f(\lambda)|$, where $\lambda$ runs through the eigenvalues. If $M$ is real symmetric, you may use \kbd{qfjacobi} instead of \kbd{mateigen}. Of course when the input is not diagonalizable, this function produces junk: \bprog ? mateval(sqrt, [0,1;0,0]) %6 = \\ oops ... [0.E-57 0] [ 0 0] @eprog pari-2.17.2/src/functions/transcendental/zetahurwitz0000644000175000017500000000366614760123736021337 0ustar billbillFunction: zetahurwitz Section: transcendental C-Name: zetahurwitz Prototype: GGD0,L,b Help: zetahurwitz(s,x,{der=0}): Hurwitz zeta function at s, x, with s not 1 and x not a negative or zero integer. s can be a scalar, polynomial, rational function, or power series. If der>0, compute the der'th derivative with respect to s. Doc: Hurwitz zeta function $\zeta(s,x)=\sum_{n\ge0}(n+x)^{-s}$ and analytically continued, with $s\ne1$ and $x$ not a negative or zero integer. Note that $\zeta(s,1) = \zeta(s)$. $s$ can also be a polynomial, rational function, or power series. If \kbd{der} is positive, compute the \kbd{der}'th derivative with respect to $s$. Note that the derivative with respect to $x$ is simply $-s\zeta(s+1,x)$. \bprog ? zetahurwitz(Pi,Pi) %1 = 0.056155444497585099925180502385781494484 ? zetahurwitz(2,1) - zeta(2) %2 = -2.350988701644575016 E-38 ? zetahurwitz(Pi,3) - (zeta(Pi)-1-1/2^Pi) %3 = -2.2040519077917890774 E-39 ? zetahurwitz(-7/2,1) - zeta(-7/2) %4 = -2.295887403949780289 E-41 ? zetahurwitz(-2.3,Pi+I*log(2)) %5 = -5.1928369229555125820137832704455696057\ - 6.1349660138824147237884128986232049582*I ? zetahurwitz(-1+x^2+O(x^3),1) %6 = -0.083333333333333333333333333333333333333\ - 0.16542114370045092921391966024278064276*x^2 + O(x^3) ? zetahurwitz(1+x+O(x^4),2) %7 = 1.0000000000000000000000000000000000000*x^-1\ - 0.42278433509846713939348790991759756896\ + 0.072815845483676724860586375874901319138*x + O(x^2) ? zetahurwitz(2,1,2) \\ zeta''(2) %8 = 1.9892802342989010234208586874215163815 @eprog The derivative can be used to compute Barnes' multiple gamma functions. For instance: \bprog ? mygamma(z)=exp(zetahurwitz(0,z,1)-zeta'(0)); /* Alternate way to compute the gamma function */ ? BarnesG(z)=exp(-zetahurwitz(-1,z,1)+(z-1)*lngamma(z)+zeta'(-1)); /* Barnes G function, satisfying G(z+1)=gamma(z)*G(z): */ ? BarnesG(6)/BarnesG(5) % = 24.000000000000000000000000000000000002 @eprog pari-2.17.2/src/functions/transcendental/asinh0000644000175000017500000000056714676526175020050 0ustar billbillFunction: asinh Section: transcendental C-Name: gasinh Prototype: Gp Help: asinh(x): inverse hyperbolic sine of x. Doc: principal branch of $\sinh^{-1}(x) = \log(x + \sqrt{1+x^{2}})$. In particular $\Im(\text{asinh}(x))\in [-\pi/2,\pi/2]$. The branch cut is in two pieces: $]-i \infty ,-i]$, continuous with quadrant III and $[+i,+i \infty[$, continuous with quadrant I. pari-2.17.2/src/functions/transcendental/tanh0000644000175000017500000000034414567450071017657 0ustar billbillFunction: tanh Section: transcendental C-Name: gtanh Prototype: Gp Description: (mp):real:prec gtanh($1, $prec) (gen):gen:prec gtanh($1, $prec) Help: tanh(x): hyperbolic tangent of x. Doc: hyperbolic tangent of $x$. pari-2.17.2/src/functions/transcendental/besselh10000644000175000017500000000032214676526175020441 0ustar billbillFunction: besselh1 Section: transcendental C-Name: hbessel1 Prototype: GGp Help: besselh1(nu,x): H^1-bessel function of index nu and argument x. Doc: $H^{1}$-Bessel function of index \var{nu} and argument $x$. pari-2.17.2/src/functions/transcendental/zetamultdual0000644000175000017500000000150714567450071021442 0ustar billbillFunction: zetamultdual Section: transcendental C-Name: zetamultdual Prototype: G Help: zetamultdual(s): s being either an evec, avec, or index m, return the dual sequence in avec format. Doc: $s$ being either an \kbd{evec}, \kbd{avec}, or index \kbd{m}, return the dual sequence in \kbd{avec} format. The dual of a sequence of length $r$ and weight $k$ has length $k-r$ and weight $k$. Duality is an involution and zeta values attached to dual sequences are the same: \bprog ? zetamultdual([4]) %1 = Vecsmall([2, 1, 1]) ? zetamultdual(%) %2 = Vecsmall([4]) ? zetamult(%1) - zetamult(%2) %3 = 0.E-38 @eprog In \kbd{evec} form, duality simply reverses the order of bits and swaps $0$ and $1$: \bprog ? zetamultconvert([4], 0) %4 = Vecsmall([0, 0, 0, 1]) ? zetamultconvert([2,1,1], 0) %5 = Vecsmall([0, 1, 1, 1]) @eprog pari-2.17.2/src/functions/transcendental/besselh20000644000175000017500000000032214676526175020442 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.17.2/src/functions/transcendental/arg0000644000175000017500000000030514567450071017473 0ustar billbillFunction: arg Section: transcendental C-Name: garg Prototype: Gp Help: arg(x): argument of x, such that -pi0$ and even, and using modular forms for $s>0$ and odd. Power series are also allowed: \bprog ? zeta(2) - Pi^2/6 %1 = 0.E-38 ? zeta(1+x+O(x^3)) %2 = 1.0000000000000000000000000000000000000*x^-1 + \ 0.57721566490153286060651209008240243104 + O(x) @eprog For $s\neq 1$ 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$). Power series are not allowed in this case. \bprog ? zeta(-3+O(5^10)) %1 = 4*5^-1 + 4 + 3*5 + 4*5^3 + 4*5^5 + 4*5^7 + O(5^9))))) ? (1-5^3) * zeta(-3) %2 = -1.0333333333333333333333333333333333333 ? bestappr(%) %3 = -31/30 ? zeta(-3+O(5^10)) - (-31/30) %4 = O(5^9) @eprog pari-2.17.2/src/functions/transcendental/besseli0000644000175000017500000000055614676526175020372 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.17.2/src/functions/transcendental/cosh0000644000175000017500000000034214567450071017657 0ustar billbillFunction: cosh Section: transcendental C-Name: gcosh Prototype: Gp Description: (mp):real:prec gcosh($1, $prec) (gen):gen:prec gcosh($1, $prec) Help: cosh(x): hyperbolic cosine of x. Doc: hyperbolic cosine of $x$. pari-2.17.2/src/functions/transcendental/agm0000644000175000017500000000101614557721031017462 0ustar billbillFunction: agm Section: transcendental C-Name: agm Prototype: GGp Help: agm(x,y): arithmetic-geometric mean of x and y. Doc: arithmetic-geometric mean of $x$ and $y$. In the case of complex or negative numbers, the optimal AGM is returned (the largest in absolute value over all choices of the signs of the square roots). $p$-adic or power series arguments are also allowed. Note that a $p$-adic agm exists only if $x/y$ is congruent to 1 modulo $p$ (modulo 16 for $p=2$). $x$ and $y$ cannot both be vectors or matrices. pari-2.17.2/src/functions/transcendental/ellK0000644000175000017500000000050414676526175017624 0ustar billbillFunction: ellK Section: transcendental C-Name: ellK Prototype: Gp Help: ellK(k): Complete elliptic integral of the first kind for the complex parameter k using the agm. Doc: Complete elliptic integral of the first kind $$K(k)=\int_{0}^{\pi/2}(1-k^{2}\sin(t)^{2})^{-1/2}\,dt$$ for the complex parameter $k$ using the agm. pari-2.17.2/src/functions/transcendental/ellE0000644000175000017500000000101014676526175017607 0ustar billbillFunction: ellE Section: transcendental C-Name: ellE Prototype: Gp Help: ellE(k): Complete elliptic integral of the second kind for the complex parameter k using the agm. Doc: Complete elliptic integral of the second kind $$E(k)=\int_{0}^{\pi/2}(1-k^{2}\sin(t)^{2})^{1/2}\,dt$$ for the complex parameter $k$ using the agm. In particular, the perimeter of an ellipse of semi-major and semi-minor axes $a$ and $b$ is given by \bprog e = sqrt(1 - (b/a)^2); \\ eccentricity 4 * a * ellE(e) \\ perimeter @eprog pari-2.17.2/src/functions/transcendental/erfc0000644000175000017500000000144314676526175017657 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 = \text{sign(x)}\kbd{incgam}(1/2,x^{2})/\sqrt\pi$ for real $x \neq 0$. The latter expression extends the function definition from real $x$ to complex $x$ with positive real part (or zero real part and positive imaginary part). This is extended to the whole complex plane by the functional equation $\kbd{erfc}(-x) = 2 - \kbd{erfc}(x)$. \bprog ? erfc(0) %1 = 1.0000000000000000000000000000000000000 ? erfc(1) %2 = 0.15729920705028513065877936491739074071 ? erfc(1+I) %3 = -0.31615128169794764488027108024367036903 - 0.19045346923783468628410886196916244244*I @eprog pari-2.17.2/src/functions/transcendental/cotanh0000644000175000017500000000036214567450071020201 0ustar billbillFunction: cotanh Section: transcendental C-Name: gcotanh Prototype: Gp Description: (mp):real:prec gcotanh($1, $prec) (gen):gen:prec gcotanh($1, $prec) Help: cotanh(x): hyperbolic cotangent of x. Doc: hyperbolic cotangent of $x$. pari-2.17.2/src/functions/transcendental/cos0000644000175000017500000000107214676526175017522 0ustar billbillFunction: cos Section: transcendental C-Name: gcos Prototype: Gp Description: (real):real mpcos($1) (mp):real:prec gcos($1, $prec) (gen):gen:prec gcos($1, $prec) Help: cos(x): cosine of x. Doc: cosine of $x$. Note that, for real $x$, cosine and sine can be obtained simultaneously as \bprog cs(x) = my(z = exp(I*x)); [real(z), imag(z)]; @eprog and for general complex $x$ as \bprog cs2(x) = my(z = exp(I*x), u = 1/z); [(z+u)/2, (z-u)/2]; @eprog Note that the latter function suffers from catastrophic cancellation when $z^{2} \approx \pm1$. pari-2.17.2/src/functions/transcendental/Catalan0000644000175000017500000000057114676526175020304 0ustar billbillFunction: Catalan Section: transcendental C-Name: mpcatalan Prototype: p Help: Catalan=Catalan(): Catalan's number with current precision. Description: ():real:prec mpcatalan($prec) Doc: Catalan's constant $G = \sum_{n>=0}\dfrac{(-1)^{n}}{(2n+1)^{2}} =0.91596\cdots$. Note that \kbd{Catalan} is one of the few reserved names which cannot be used for user variables. pari-2.17.2/src/functions/transcendental/sin0000644000175000017500000000106614676526175017532 0ustar billbillFunction: sin Section: transcendental C-Name: gsin Prototype: Gp Description: (real):real mpsin($1) (mp):real:prec gsin($1, $prec) (gen):gen:prec gsin($1, $prec) Help: sin(x): sine of x. Doc: sine of $x$. Note that, for real $x$, cosine and sine can be obtained simultaneously as \bprog cs(x) = my(z = exp(I*x)); [real(z), imag(z)]; @eprog and for general complex $x$ as \bprog cs2(x) = my(z = exp(I*x), u = 1/z); [(z+u)/2, (z-u)/2]; @eprog Note that the latter function suffers from catastrophic cancellation when $z^{2} \approx \pm1$. pari-2.17.2/src/functions/transcendental/cotan0000644000175000017500000000032714567450071020032 0ustar billbillFunction: cotan Section: transcendental C-Name: gcotan Prototype: Gp Description: (mp):real:prec gcotan($1, $prec) (gen):gen:prec gcotan($1, $prec) Help: cotan(x): cotangent of x. Doc: cotangent of $x$. pari-2.17.2/src/functions/transcendental/acosh0000644000175000017500000000053714567450071020026 0ustar billbillFunction: acosh Section: transcendental C-Name: gacosh Prototype: Gp Help: acosh(x): inverse hyperbolic cosine of x. Doc: principal branch of $\cosh^{-1}(x) = 2 \log(\sqrt{(x+1)/2} + \sqrt{(x-1)/2})$. In particular, $\Re(\text{acosh}(x))\geq 0$ and $\Im(\text{acosh}(x))\in ]-\pi,\pi]$; if $x\in \R$ and $x<1$, then $\text{acosh}(x)$ is complex. pari-2.17.2/src/functions/transcendental/lerchphi0000644000175000017500000000051714676526175020537 0ustar billbillFunction: lerchphi Section: transcendental C-Name: lerchphi Prototype: GGGp Help: lerchphi(z,s,a): Lerch transcendent equal to sum for n >= 0 of z^n / (n+a)^s for reasonable values of the arguments. Doc: Lerch transcendent $\Phi(z,s,a)=\sum_{n\ge0}z^{n}(n+a)^{-s}$ and analytically continued, for reasonable values of the arguments. pari-2.17.2/src/functions/transcendental/thetanullk0000644000175000017500000000074014676526175021112 0ustar billbillFunction: thetanullk Section: transcendental C-Name: thetanullk Prototype: GLp Help: thetanullk(q,k): k-th derivative at z=0 of theta(q,z). Doc: $k$-th derivative at $z=0$ of $\kbd{theta}(q,z)$. Variant: \fun{GEN}{vecthetanullk}{GEN q, long k, long prec} returns the vector of all $\dfrac{d^{i}\theta}{dz^{i}}(q,0)$ for all odd $i = 1, 3, \dots, 2k-1$. \fun{GEN}{vecthetanullk_tau}{GEN tau, long k, long prec} returns \kbd{vecthetanullk\_tau} at $q = \exp(2i\pi \kbd{tau})$. pari-2.17.2/src/functions/transcendental/gamma0000644000175000017500000000233214676526175020020 0ustar billbillFunction: gamma Section: transcendental C-Name: ggamma Prototype: Gp Help: gamma(s): gamma function at s, a complex or p-adic number, or a series. Doc: For $s$ a complex number, evaluates Euler's gamma function\sidx{gamma-function}, which is the analytic continuation of $$\Gamma(s)=\int_{0}^{\infty} t^{s-1}\exp(-t)\,dt,\quad \Re(s) > 0.$$ Error if $s$ is a nonpositive integer, where $\Gamma$ has a (simple) pole. \bprog ? gamma(5) \\ @com $\Gamma(n) = (n-1)!$ for a positive integer $n$ %1 = 24.000000000000000000000000000000000000 ? gamma(0) *** at top-level: gamma(0) *** ^-------- *** gamma: domain error in gamma: argument = nonpositive integer ? gamma(x + O(x^3)) %2 = x^-1 - 0.57721566490153286060651209008240243104 + O(x) @eprog For $s$ a \typ{PADIC}, evaluates the Morita gamma function at $s$, that is the unique continuous $p$-adic function on the $p$-adic integers extending $\Gamma_{p}(k)=(-1)^{k} \prod_{j\dots>n_{k}>0} n_{1}^{-s_{1}}\dots n_{k}^{-s_{k}}$$ of length $k$ and weight $\sum_{i} s_{i}$. More generally, return Yamamoto's $t$-MZV interpolation evaluated at $t$: for $t = 0$, this is the ordinary MZV; for $t = 1$, we obtain the MZSV star value, with $\geq$ instead of strict inequalities; and of course, for $t = \kbd{'x}$ we obtain Yamamoto's one-variable polynomial. \bprog ? zetamult([2,1]) - zeta(3) \\ Euler's identity %1 = 0.E-38 ? zetamult([2,1], 1) \\ star value %2 = 2.4041138063191885707994763230228999815 ? zetamult([2,1], 'x) %3 = 1.20205[...]*x + 1.20205[...] @eprog\noindent If the bit precision is $B$, this function runs in time $\tilde{O}(k(B+k)^{2})$ if $t = 0$, and $\tilde{O}(kB^{3})$ otherwise. In addition to the above format (\kbd{avec}), the function also accepts a binary word format \kbd{evec} (each $s_{i}$ is replaced by $s_{i}$ bits, all of them 0 but the last one) giving the MZV representation as an iterated integral, and an \kbd{index} format (if $e$ is the positive integer attached the \kbd{evec} vector of bits, the index is the integer $e + 2^{k-2}$). The function \kbd{zetamultconvert} allows to pass from one format to the other; the function \kbd{zetamultall} computes simultaneously all MZVs of weight $\sum_{i\leq k} s_{i}$ up to $n$. Variant: Also available is \fun{GEN}{zetamult}{GEN s, long prec} for $t = 0$. pari-2.17.2/src/functions/transcendental/expm10000644000175000017500000000174214567450071017762 0ustar billbillFunction: expm1 Section: transcendental C-Name: gexpm1 Prototype: Gp Help: expm1(x): exp(x)-1. Description: (real):real mpexpm1($1) Doc: return $\exp(x)-1$, computed in a way that is also accurate when the real part of $x$ is near $0$. A naive direct computation would suffer from catastrophic cancellation; PARI's direct computation of $\exp(x)$ alleviates this well known problem at the expense of computing $\exp(x)$ to a higher accuracy when $x$ is small. Using \kbd{expm1} is recommended instead: \bprog ? default(realprecision, 10000); x = 1e-100; ? a = expm1(x); time = 4 ms. ? b = exp(x)-1; time = 4 ms. ? default(realprecision, 10040); x = 1e-100; ? c = expm1(x); \\ reference point ? abs(a-c)/c \\ relative error in expm1(x) %7 = 1.4027986153764843997 E-10019 ? abs(b-c)/c \\ relative error in exp(x)-1 %8 = 1.7907031188259675794 E-9919 @eprog\noindent As the example above shows, when $x$ is near $0$, \kbd{expm1} is more accurate than \kbd{exp(x)-1}. pari-2.17.2/src/functions/transcendental/gammah0000644000175000017500000000025314567450071020156 0ustar billbillFunction: gammah Section: transcendental C-Name: ggammah Prototype: Gp Help: gammah(x): gamma of x+1/2 (x integer). Doc: gamma function evaluated at the argument $x+1/2$. pari-2.17.2/src/functions/transcendental/besseljh0000644000175000017500000000067514567450071020533 0ustar billbillFunction: besseljh Section: transcendental C-Name: jbesselh Prototype: GGp Help: besseljh(n,x): J-bessel function of index n+1/2 and argument x, where n is a nonnegative integer. Doc: $J$-Bessel function of half integral index. More precisely, $\kbd{besseljh}(n,x)$ computes $J_{n+1/2}(x)$ where $n$ must be of type integer, and $x$ is any element of $\C$. In the present version \vers, this function is not very accurate when $x$ is small. pari-2.17.2/src/functions/transcendental/incgam0000644000175000017500000000116714676526175020201 0ustar billbillFunction: incgam Section: transcendental C-Name: incgam0 Prototype: GGDGp Help: incgam(s,x,{g}): incomplete gamma function. g is optional and is the precomputed value of gamma(s). Doc: incomplete gamma function $\int_{x}^{\infty} e^{-t}t^{s-1}\,dt$, extended by analytic continuation to all complex $x, s$ not both $0$. The relative error is bounded in terms of the precision of $s$ (the accuracy of $x$ is ignored when determining the output precision). When $g$ is given, assume that $g=\Gamma(s)$. For small $|x|$, this will speed up the computation. Variant: Also available is \fun{GEN}{incgam}{GEN s, GEN x, long prec}. pari-2.17.2/src/functions/transcendental/besseljzero0000644000175000017500000000226514676526175021272 0ustar billbillFunction: besseljzero Section: transcendental C-Name: besseljzero Prototype: GD1,L,b Help: besseljzero(nu,{k=1}): k-th zero of the J-bessel function of index nu. Works for real and complex ordrers but the result is guaranteed only if nu is nonnegative. Doc: $k$-th zero of the $J$-Bessel function of index \var{nu}, close to $\pi(\nu/2 + k - 1/4)$, usually noted $j_{\nu,k}$. \bprog ? besseljzero(0) \\ @com{first zero of $J_{0}$} %1 = 2.4048255576957727686216318793264546431 ? besselj(0, %) %2 = 7.1951595399463653939930598011247182898 E-41 ? besseljzero(0, 2) \\ @com{second zero} %3 = 5.5200781102863106495966041128130274252 ? besseljzero(I) \\ @com{also works for complex orders, here $J_{i}$} %4 = 2.5377... + 1.4753...*I @eprog\noindent The function uses a Newton iteration due to Temme. If $\nu$ is real and nonnegative, the result is guaranteed and the function really returns the $k$-th positive zero of $J_{\nu}$. For general $\nu$, the result is not well defined, given by the Newton iteration with $\pi(\nu/2 + k - 1/4)$ as a starting value. (N.B. Using this method for large real $\nu$ would give completely different results than the $j_{\nu,k}$ unless $k$ is large enough.) pari-2.17.2/src/functions/transcendental/I0000644000175000017500000000021713637407207017114 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.17.2/src/functions/transcendental/bessely0000644000175000017500000000031114567450071020365 0ustar billbillFunction: bessely Section: transcendental C-Name: ybessel Prototype: GGp Help: bessely(nu,x): Y-bessel function of index nu and argument x. Doc: $Y$-Bessel function of index \var{nu} and argument $x$. pari-2.17.2/src/functions/transcendental/polylog0000644000175000017500000000317014676526175020424 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^{k}B_{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.17.2/src/functions/transcendental/hyperu0000644000175000017500000000063414676526175020255 0ustar billbillFunction: hyperu Section: transcendental C-Name: hyperu Prototype: GGGp Help: hyperu(a,b,z): U-confluent hypergeometric function. Doc: $U$-confluent hypergeometric function with complex parameters $a, b, z$. Note that $_{2}F_{0}(a,b,z) = (-z)^{-a}U(a, a+1-b, -1/z)$, \bprog ? hyperu(1, 3/2, I) %1 = 0.23219... - 0.80952...*I ? -I * hypergeom([1, 1+1-3/2], [], -1/I) %2 = 0.23219... - 0.80952...*I @eprog pari-2.17.2/src/functions/transcendental/lerchzeta0000644000175000017500000000102114676526175020711 0ustar billbillFunction: lerchzeta Section: transcendental C-Name: lerchzeta Prototype: GGGp Help: lerchzeta(s,a,lam): Lerch zeta function equal to sum for n >= 0 of e^(2 pi i lam n) / (n+a)^s for reasonable values of the arguments. Doc: Lerch zeta function $$L(s,a,\lambda)=\sum_{n\ge0}e^{2\pi i\lambda n}(n+a)^{-s}$$ and analytically continued, for reasonable values of the arguments. Function: _lerch_worker Section: programming/internals C-Name: lerch_worker Prototype: GG Help: _lerch_worker(E,t): worker for lerchzeta Doc: auxiliary. pari-2.17.2/src/functions/transcendental/rootsof10000644000175000017500000000103414567450071020476 0ustar billbillFunction: rootsof1 Section: transcendental C-Name: grootsof1 Prototype: Lp Help: rootsof1(N): column vector of complex N-th roots of 1. Doc: return the column vector $v$ of all complex $N$-th roots of $1$, where $N$ is a positive integer. In other words, $v[k] = \exp(2I(k-1)\pi/N)$ for $k = 1, \dots, N$. Rational components (e.g., the roots $\pm1$ and $\pm I$) are given exactly, not as floating point numbers: \bprog ? rootsof1(4) %1 = [1, I, -1, -I]~ ? rootsof1(3) %2 = [1, -1/2 + 0.866025...*I, -1/2 - 0.866025...*I]~ @eprog pari-2.17.2/src/functions/transcendental/log0000644000175000017500000000210714676526175017517 0ustar billbillFunction: log Section: transcendental C-Name: glog Prototype: Gp Help: log(x): natural logarithm of x. Description: (gen):gen:prec glog($1, $prec) Doc: principal branch of the natural logarithm of $x \in \C^{*}$, i.e.~such that $\Im(\log(x))\in{} ]-\pi,\pi]$. The branch cut lies along the negative real axis, continuous with quadrant 2, i.e.~such that $\lim_{b\to 0^{+}} \log (a+bi) = \log a$ for $a \in\R^{*}$. The result is complex (with imaginary part equal to $\pi$) if $x\in \R$ and $x < 0$. In general, the algorithm uses the formula $$\log(x) \approx {\pi\over 2\text{agm}(1, 4/s)} - m \log 2, $$ if $s = x 2^{m}$ is large enough. (The result is exact to $B$ bits provided $s > 2^{B/2}$.) At low accuracies, the series expansion near $1$ is used. $p$-adic arguments are also accepted for $x$, with the convention that $\log(p)=0$. Hence in particular $\exp(\log(x))/x$ is not in general equal to 1 but to a $(p-1)$-th root of unity (or $\pm1$ if $p=2$) times a power of $p$. Variant: For a \typ{PADIC} $x$, the function \fun{GEN}{Qp_log}{GEN x} is also available. pari-2.17.2/src/functions/transcendental/abs0000644000175000017500000000151214567450071017470 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.17.2/src/functions/transcendental/sinh0000644000175000017500000000033614567450071017667 0ustar billbillFunction: sinh Section: transcendental C-Name: gsinh Prototype: Gp Description: (mp):real:prec gsinh($1, $prec) (gen):gen:prec gsinh($1, $prec) Help: sinh(x): hyperbolic sine of x. Doc: hyperbolic sine of $x$. pari-2.17.2/src/functions/transcendental/sinc0000644000175000017500000000060514676526175017673 0ustar billbillFunction: sinc Section: transcendental C-Name: gsinc Prototype: Gp Description: (mp):real:prec gsinc($1, $prec) (gen):gen:prec gsinc($1, $prec) Help: sinc(x): sinc function of x. Doc: cardinal sine of $x$, i.e. $\sin(x)/x$ if $x\neq 0$, $1$ otherwise. Note that this function also allows to compute $$(1-\cos(x)) / x^{2} = \kbd{sinc}(x/2)^{2} / 2$$ accurately near $x = 0$. pari-2.17.2/src/functions/transcendental/besselyzero0000644000175000017500000000224114676526175021303 0ustar billbillFunction: besselyzero Section: transcendental C-Name: besselyzero Prototype: GD1,L,b Help: besselyzero(nu,{k=1}): k-th zero of the Y-bessel function of index nu. Works for real and complex ordrers but the result is guaranteed only if nu is nonnegative. Doc: $k$-th zero of the $Y$-Bessel function of index \var{nu}, close to $\pi(\nu/2 + k - 3/4)$, usually noted $y_{\nu,k}$. \bprog ? besselyzero(0) \\ @com{first zero of $Y_{0}$} %1 = 0.89357696627916752158488710205833824123 ? bessely(0, %) %2 = 1.8708573650996561952 E-39 ? besselyzero(0, 2) \\ @com{second zero} %3 = 3.9576784193148578683756771869174012814 ? besselyzero(I) \\ @com{also works for complex orders, here $Y_{i}$} %4 = 1.03930... + 1.3266...*I @eprog\noindent The function uses a Newton iteration due to Temme. If $\nu$ is real and nonnegative, the result is guaranteed and the function really returns the $k$-th positive zero of $Y_{\nu}$. For general $\nu$, the result is not well defined, given by Newton iteration with $\pi(\nu/2 + k - 3/4)$ as a starting value. (N.B. Using this method for large real $\nu$ would give completely different results than the $y_{\nu,k}$ unless $k$ is large enough.) pari-2.17.2/src/functions/transcendental/sqrt0000644000175000017500000000146414567450071017722 0ustar billbillFunction: sqrt Section: transcendental C-Name: gsqrt Prototype: Gp Help: sqrt(x): square root of x. Description: (real):gen sqrtr($1) (gen):gen:prec gsqrt($1, $prec) Doc: principal branch of the square root of $x$, defined as $\sqrt{x} = \exp(\log x / 2)$. In particular, we have $\text{Arg}(\text{sqrt}(x))\in{} ]-\pi/2, \pi/2]$, and if $x\in \R$ and $x<0$, then the result is complex with positive imaginary part. Intmod a prime $p$, \typ{PADIC} and \typ{FFELT} are allowed as arguments. In the first 2 cases (\typ{INTMOD}, \typ{PADIC}), the square root (if it exists) which is returned is the one whose first $p$-adic digit is in the interval $[0,p/2]$. For other arguments, the result is undefined. Variant: For a \typ{PADIC} $x$, the function \fun{GEN}{Qp_sqrt}{GEN x} is also available. pari-2.17.2/src/functions/transcendental/log1p0000644000175000017500000000156114567450071017751 0ustar billbillFunction: log1p Section: transcendental C-Name: glog1p Prototype: Gp Help: log1p(x): log(1+x) Doc: return $\log(1+x)$, computed in a way that is also accurate when the real part of $x$ is near $0$. This is the reciprocal function of \kbd{expm1}$(x) = \exp(x)-1$. \bprog ? default(realprecision, 10000); x = Pi*1e-100; ? (expm1(log1p(x)) - x) / x %2 = -7.668242895059371866 E-10019 ? (log1p(expm1(x)) - x) / x %3 = -7.668242895059371866 E-10019 @eprog\noindent When $x$ is small, this function is both faster and more accurate than $\log(1+x)$: \bprog ? \p38 ? x = 1e-20; ? localprec(100); c = log1p(x); \\ reference point ? a = log1p(x); abs((a - c)/c) %6 = 0.E-38 ? b = log(1+x); abs((b - c)/c) \\ slightly less accurate %7 = 1.5930919111324522770 E-38 ? for (i=1,10^5,log1p(x)) time = 81 ms. ? for (i=1,10^5,log(1+x)) time = 100 ms. \\ slower, too @eprog pari-2.17.2/src/functions/transcendental/atan0000644000175000017500000000072614567450071017654 0ustar billbillFunction: atan Section: transcendental C-Name: gatan Prototype: Gp Help: atan(x): arc tangent of x. Doc: principal branch of $\text{tan}^{-1}(x) = \log ((1+ix)/(1-ix)) / 2i$. In particular the real part of $\text{atan}(x)$ belongs to $]-\pi/2,\pi/2[$. The branch cut is in two pieces: $]-i\infty,-i[$, continuous with quadrant IV, and $]i,+i \infty[$ continuous with quadrant II. The function satisfies $\text{atan}(x) = -i\text{atanh}(ix)$ for all $x\neq \pm i$. pari-2.17.2/src/functions/transcendental/tan0000644000175000017500000000031114567450071017501 0ustar billbillFunction: tan Section: transcendental C-Name: gtan Prototype: Gp Description: (mp):real:prec gtan($1, $prec) (gen):gen:prec gtan($1, $prec) Help: tan(x): tangent of x. Doc: tangent of $x$. pari-2.17.2/src/functions/transcendental/Pi0000644000175000017500000000045614567450071017301 0ustar billbillFunction: Pi Section: transcendental C-Name: mppi Prototype: p Help: Pi=Pi(): the constant pi, with current precision. Description: ():real:prec mppi($prec) Doc: the constant $\pi$ ($3.14159\cdots$). Note that \kbd{Pi} is one of the few reserved names which cannot be used for user variables. pari-2.17.2/src/functions/transcendental/weber0000644000175000017500000000177514676526175020054 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). 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_{1}f_{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.17.2/src/functions/transcendental/zetamultall0000644000175000017500000000567314676526175021307 0ustar billbillFunction: zetamultall Section: transcendental C-Name: zetamultall Prototype: LD0,L,p Help: zetamultall(k,{flag=0}): list of all multiple zeta values for weight up to k. Binary digits of flag mean: 0 = zetastar values if set, 1 = values up to duality if set, 2 = values of weight k if set (else all values up to weight k), 3 = return the 2-component vector [Z, M], where M is the vector of the corresponding indices m, i.e., such that zetamult(M[i]) = Z[i]. Doc: list of all multiple zeta values (MZVs) for weight $s_{1} + \dots + s_{r}$ up to $k$. Binary digits of $\fl$ mean : 0 = star values if set; 1 = values up to to duality if set (see \kbd{zetamultdual}, ignored if star values); 2 = values of weight $k$ if set (else all values up to weight $k$); 3 = return the 2-component vector \kbd{[Z, M]}, where $M$ is the vector of the corresponding indices $m$, i.e., such that \kbd{zetamult(M[i])} = \kbd{Z[i]}. Note that it is necessary to use \kbd{zetamultconvert} to have the corresponding \kbd{avec} $(s_{1},\dots, s_{r})$. With the default value $\fl=0$, the function returns a vector with $2^{k-1}-1$ components whose $i$-th entry is the MZV of \kbd{index} $i$ (see \kbd{zetamult}). If the bit precision is $B$, this function runs in time $O(2^{k} k B^{2})$ for an output of size $O(2^{k} B)$. \bprog ? Z = zetamultall(5); #Z \\ 2^4 - 1 MZVs of weight <= 5 %1 = 15 ? Z[10] %2 = 0.22881039760335375976874614894168879193 ? zetamultconvert(10) %3 = Vecsmall([3, 2]) \\ @com{index $10$ corresponds to $\zeta(3,2)$} ? zetamult(%) \\ double check %4 = 0.22881039760335375976874614894168879193 ? zetamult(10) \\ we can use the index directly %5 = 0.22881039760335375976874614894168879193 @eprog\noindent If we use flag bits 1 and 2, we avoid unnecessary computations and copying, saving a potential factor 4: half the values are in lower weight and computing up to duality save another rough factor 2. Unfortunately, the indexing now no longer corresponds to the new shorter vector of MZVs: \bprog ? Z = zetamultall(5, 2); #Z \\ up to duality %6 = 9 ? Z = zetamultall(5, 2); #Z \\ only weight 5 %7 = 8 ? Z = zetamultall(5, 2 + 4); #Z \\ both %8 = 4 @eprog\noindent So how to recover the value attached to index 10 ? Flag bit 3 returns the actual indices used: \bprog ? [Z, M] = zetamultall(5, 2 + 8); M \\ other indices were not included %9 = Vecsmall([1, 2, 4, 5, 6, 8, 9, 10, 12]) ? Z[8] \\ index m = 10 is now in M[8] %10 = 0.22881039760335375976874614894168879193 ? [Z, M] = zetamultall(5, 2 + 4 + 8); M %11 = Vecsmall([8, 9, 10, 12]) ? Z[3] \\ index m = 10 is now in M[3] %12 = 0.22881039760335375976874614894168879193 @eprog\noindent The following construction automates the above programmatically, looking up the MZVs of index $10$ ($=\zeta(3,2)$) in all cases, without inspecting the various index sets $M$ visually: \bprog ? Z[vecsearch(M, 10)] \\ works in all the above settings %13 = 0.22881039760335375976874614894168879193 @eprog pari-2.17.2/src/functions/transcendental/acos0000644000175000017500000000073714676526175017672 0ustar billbillFunction: acos Section: transcendental C-Name: gacos Prototype: Gp Help: acos(x): arc cosine of x. Doc: principal branch of $\cos^{-1}(x) = -i \log (x + i\sqrt{1-x^{2}})$. In particular, $\Re(\text{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.17.2/src/functions/transcendental/lngamma0000644000175000017500000000305514676526175020355 0ustar billbillFunction: lngamma Section: transcendental C-Name: glngamma Prototype: Gp Help: lngamma(x): logarithm of the gamma function of x. Doc: principal branch of the logarithm of the gamma function of $x$. This function is analytic on the complex plane with nonpositive integers removed, and can have much larger arguments than \kbd{gamma} itself. For $x$ a power series such that $x(0)$ is not a pole of \kbd{gamma}, compute the Taylor expansion. (PARI only knows about regular power series and can't include logarithmic terms.) \bprog ? lngamma(1+x+O(x^2)) %1 = -0.57721566490153286060651209008240243104*x + O(x^2) ? lngamma(x+O(x^2)) *** at top-level: lngamma(x+O(x^2)) *** ^----------------- *** lngamma: domain error in lngamma: valuation != 0 ? lngamma(-1+x+O(x^2)) *** lngamma: Warning: normalizing a series with 0 leading term. *** at top-level: lngamma(-1+x+O(x^2)) *** ^-------------------- *** lngamma: domain error in intformal: residue(series, pole) != 0 @eprog For $x$ a \typ{PADIC}, return the $p$-adic $\log\Gamma_{p}$ function, which is the $p$-adic logarithm of Morita's gamma function for $x \in \Z_{p}$, and Diamond's function if $|x| > 1$. \bprog ? lngamma(5+O(5^7)) %2 = 4*5^2 + 4*5^3 + 5^4 + 2*5^5 + O(5^6) ? log(gamma(5+O(5^7))) %3 = 4*5^2 + 4*5^3 + 5^4 + 2*5^5 + O(5^6) ? lngamma(1/5+O(5^4)) %4 = 4*5^-1 + 4 + 2*5 + 5^2 + 5^3 + O(5^4) ? gamma(1/5+O(5^4)) *** at top-level: gamma(1/5+O(5^4)) *** ^----------------- *** gamma: domain error in gamma: v_p(x) < 0 @eprog pari-2.17.2/src/functions/transcendental/eint10000644000175000017500000000232514676526175017760 0ustar billbillFunction: eint1 Section: transcendental C-Name: veceint1 Prototype: GDGp Help: eint1(x,{n}): exponential integral E1(x). If n is present and x > 0, computes the vector of the first n values of the exponential integral E1(n x). Doc: exponential integral $\int_{x}^{\infty} \dfrac{e^{-t}}{t}\,dt = \kbd{incgam}(0, x)$, where the latter expression extends the function definition from real $x > 0$ to all complex $x \neq 0$. If $n$ is present, we must have $x > 0$; the function returns the $n$-dimensional vector $[\kbd{eint1}(x),\dots,\kbd{eint1}(nx)]$. Contrary to other transcendental functions, and to the default case ($n$ omitted), the values are correct up to a bounded \emph{absolute}, rather than relative, error $10^{-n}$, where $n$ is \kbd{precision}$(x)$ if $x$ is a \typ{REAL} and defaults to \kbd{realprecision} otherwise. (In the most important application, to the computation of $L$-functions via approximate functional equations, those values appear as weights in long sums and small individual relative errors are less useful than controlling the absolute error.) This is faster than repeatedly calling \kbd{eint1($i$ * x)}, but less precise. Variant: Also available is \fun{GEN}{eint1}{GEN x, long prec}. pari-2.17.2/src/functions/transcendental/dilog0000644000175000017500000000036414676526175020037 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 $\text{Li}_{2}(x)=\sum_{n\ge1}x^{n}/n^{2}$. pari-2.17.2/src/functions/transcendental/sqr0000644000175000017500000000215614676526175017547 0ustar billbillFunction: sqr Section: transcendental C-Name: gsqr Prototype: G Help: sqr(x): square of x. NOT identical to x*x. Description: (usmall):int sqru($1) (small):int sqrs($1) (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). Function: _ZM_sqr_worker C-Name: ZM_sqr_worker Prototype: GG Section: programming/internals Help: worker for ZM_sqr pari-2.17.2/src/functions/transcendental/psi0000644000175000017500000000110714676526175017530 0ustar billbillFunction: psi Section: transcendental C-Name: gpsi_der Prototype: GD0,L,p Help: psi(x,{der}): psi-function at x (der-th derivative of psi if der is set) Doc: the $\psi$-function of $x$, i.e.~the logarithmic derivative $\Gamma'(x)/\Gamma(x)$. If $\var{der}$ is set, return the $\var{der}$-th derivative. For $s$ a \typ{PADIC}, evaluates the $\var{der}$-th derivative of the Morita $\psi$ function at $s$. Variant: For a \typ{PADIC} $x$, the function \fun{GEN}{Qp_psi}{GEN x, long der} is also available. For $\var{der} = 0$, \fun{GEN}{gpsi}{GEN x, long prec} is also available. pari-2.17.2/src/functions/transcendental/airy0000644000175000017500000000047114567450071017672 0ustar billbillFunction: airy Section: transcendental C-Name: airy Prototype: Gp Help: airy(z): Airy [Ai,Bi] function of argument z. Doc: airy $[Ai,Bi]$ functions of argument $z$. \bprog ? [A,B] = airy(1); ? A %2 = 0.13529241631288141552414742351546630617 ? B %3 = 1.2074235949528712594363788170282869954 @eprog\noindent pari-2.17.2/src/functions/transcendental/besseln0000644000175000017500000000027214567450071020360 0ustar billbillFunction: besseln Section: transcendental C-Name: ybessel Prototype: GGp Obsolete: 2018-12-10 Help: besseln(nu,x): deprecated alias for bessely. Doc: deprecated alias for \kbd{bessely}. pari-2.17.2/src/functions/transcendental/hypergeom0000644000175000017500000000704414676526175020742 0ustar billbillFunction: hypergeom Section: transcendental C-Name: hypergeom Prototype: DGDGGp Help: hypergeom({N},{D},z): general hypergeometric function, where N and D are the vector of parameters in the numerator and denominator respectively, evaluated at the argument z. Doc: general hypergeometric function, where \kbd{N} and \kbd{D} are the vector of parameters in the numerator and denominator respectively, evaluated at the argument $z$, which may be complex, $p$-adic or a power series. This function implements hypergeometric functions $$_{p}F_{q}((a_{i})_{1\le i\le p},(b_{j})_{1\le j\le q};z) = \sum_{n\ge0}\dfrac{\prod_{1\le i\le p}(a_{i})_{n}}{\prod_{1\le j\le q}(b_{j})_{n}} \dfrac{z^{n}}{n!}\;,$$ where $(a)_{n}=a(a+1)\cdots(a+n-1)$ is the rising Pochhammer symbol. For this to make sense, none of the $b_{j}$ must be a negative or zero integer. The corresponding general GP command is \bprog hypergeom([a1,a2,...,ap], [b1,b2,...,bq], z) @eprog\noindent Whenever $p = 1$ or $q = 1$, a one-element vector can be replaced by the element it contains. Whenever $p = 0$ or $q = 0$, an empty vector can be omitted. For instance hypergeom(,b,z) computes $_{0}F_{1}(;b;z)$. The non-archimedean cases ($z$ a $p$-adic or power series) are handled trivially. We now discuss the case of a complex $z$; we distinguish three kinds of such functions according to their radius of convergence $R$: \item $q\ge p$: $R = \infty$. \item $q=p-1$: $R=1$. Nonetheless, by integral representations, $_{p}F_{q}$ can be analytically continued outside the disc of convergence. \item $q\le p-2$: $R=0$. By integral representations, one can make sense of the function in a suitable domain, by analytic continuation. The list of implemented functions and their domain of validity in our implementation is as follows: \kbd{F01}: \kbd{hypergeom(,a,z)} (or \kbd{[a]}). This is essentially a Bessel function and computed as such. $R=\infty$. \kbd{F10}: \kbd{hypergeom(a,,z)} This is $(1-z)^{-a}$. \kbd{F11}: \kbd{hypergeom(a,b,z)} is the Kummer confluent hypergeometric function, computed by summing the series. $R=\infty$ \kbd{F20}: \kbd{hypergeom([a,b],,z)}. $R=0$, computed as $$\dfrac{1}{\Gamma(a)}\int_{0}^{\infty} t^{a-1}(1-zt)^{-b}e^{-t}\,dt\;.$$ \kbd{F21}: \kbd{hypergeom([a,b],c,z)} (or \kbd{[c]}). $R=1$, extended by $$\dfrac{\Gamma(c)}{\Gamma(b)\Gamma(c-b)} \int_{0}^{1} t^{b-1}(1-t)^{c-b-1}(1-zt)^{a}\,dt\;.$$ This is Gauss's Hypergeometric function, and almost all of the implementation work is done for this function. \kbd{F31}: \kbd{hypergeom([a,b,c],d,z)} (or \kbd{[d]}). $R=0$, computed as $$\dfrac{1}{\Gamma(a)}\int_{0}^{\infty} t^{a-1}e^{-t} {}_{2}F_{1}(b,c;d;tz)\,dt\;.$$ \kbd{F32}: \kbd{hypergeom([a,b,c],[d,e],z)}. $R=1$, extended by $$\dfrac{\Gamma(e)}{\Gamma(c)\Gamma(e-c)} \int_{0}^{1}t^{c-1}(1-t)^{e-c-1}{}_{2}F_{1}(a,b;d;tz)\,dt\;.$$ For other inputs: if $R=\infty$ or $R=1$ and $|z| < 1- \varepsilon$ is not too close to the circle of convergence, we simply sum the series. \bprog ? hypergeom([3,2], 3.4, 0.7) \\ 2F1(3,2; 3.4; 0.7) %1 = 7.9999999999999999999999999999999999999 ? a=5/3; T1=hypergeom([1,1,1],[a,a],1) \\ 3F2(1,1,1; a,a; 1) %2 = 3.1958592952314032651578713968927593818 ? T2=hypergeom([2,1,1],[a+1,a+1],1) %3 = 1.6752931349345765309211012564734179541 ? T3=hypergeom([2*a-1,1,1],[a+1,a+1],1) %4 = 1.9721037126267142061807688820853354440 ? T1 + (a-1)^2/(a^2*(2*a-3)) * (T2-2*(a-1)*T3) \\ - gamma(a)^2/((2*a-3)*gamma(2*a-2)) %5 = -1.880790961315660013 E-37 \\ ~ 0 @eprog\noindent This identity is due to Bercu. pari-2.17.2/src/functions/transcendental/polylogmult0000644000175000017500000000375514676526175021337 0ustar billbillFunction: polylogmult Section: transcendental C-Name: polylogmult_interpolate Prototype: GDGDGp Help: polylogmult(s,{z},{t=0}): multiple polylogarithm value at integral s = [s1,...,sr] with argument z = [z1,...,zr]. If z is omitted, assume z = [1,...,1], i.e., multiple zeta value. More generally, return Yamamoto's interpolation at t (ordinary multiple polylog at t = 0 and star value at t = 1). Doc: For $s$ a vector of positive integers and $z$ a vector of complex numbers of the same length, returns the multiple polylogarithm value (MPV) $$\zeta(s_{1},\dots, s_{r}; z_{1},\dots,z_{r}) = \sum_{n_{1}>\dots>n_{r}>0} \prod_{1\le i\le r}z_{i}^{n_{i}}/n_{i}^{s_{i}}.$$ If $z$ is omitted, assume $z=[1,\dots,1]$, i.e., Multiple Zeta Value. More generally, return Yamamoto's interpolation between ordinary multiple polylogarithms ($t = 0$) and star polylogarithms ($t = 1$, using the condition $n_{1}\ge \dots \ge n_{r} > 0$), evaluated at $t$. We must have $|z_{1}\cdots z_{i}|\le1$ for all $i$, and if $s_{1}=1$ we must have $z_{1}\ne1$. \bprog ? 8*polylogmult([2,1],[-1,1]) - zeta(3) %1 = 0.E-38 @eprog\noindent \misctitle{Warning} The algorithm used converges when the $z_{i}$ are $\pm 1$. It may not converge as some $z_{i} \neq 1$ becomes too close to $1$, even at roots of $1$ of moderate order: \bprog ? polylogmult([2,1], (99+20*I)/101 * [1,1]) *** polylogmult: sorry, polylogmult in this range is not yet implemented. ? polylogmult([2,1], exp(I*Pi/20)* [1,1]) *** polylogmult: sorry, polylogmult in this range is not yet implemented. @eprog\noindent More precisely, if $y_{i} := 1 / (z_{1}\cdots z_{i})$ and $$ v := \min_{i < j; y_{i} \neq 1} |(1 - y_{i}) y_{j}| > 1/4$$ then the algorithm computes the value up to a $2^{-b}$ absolute error in $O(k^{2}N)$ operations on floating point numbers of $O(N)$ bits, where $k = \sum_{i} s_{i}$ is the weight and $N = b / \log_{2} (4v)$. Variant: Also available is \fun{GEN}{polylogmult}{GEN s, GEN z, long prec} ($t$ is \kbd{NULL}). pari-2.17.2/src/functions/transcendental/incgamc0000644000175000017500000000063514676526175020343 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.17.2/src/functions/transcendental/lambertw0000644000175000017500000000212614676526175020554 0ustar billbillFunction: lambertw Section: transcendental C-Name: glambertW Prototype: GD0,L,p Help: lambertw(y,{branch=0}): solution of the implicit equation x*exp(x)=y. In the p-adic case, give a solution of x*exp(x)=y if y has valuation > 1 (or p odd and positive valuation), of log(x)+x=log(y) otherwise. Doc: Lambert $W$ function, solution of the implicit equation $xe^{x}=y$. \item For real inputs $y$: If \kbd{branch = 0}, principal branch $W_{0}$ defined for $y\ge-\exp(-1)$. If \kbd{branch = -1}, branch $W_{-1}$ defined for $-\exp(-1)\le y<0$. \item For $p$-adic inputs, $p$ odd: give a solution of $x\exp(x)=y$ if $y$ has positive valuation, of $\log(x)+x=\log(y)$ otherwise. \item For $2$-adic inputs: give a solution of $x\exp(x)=y$ if $y$ has valuation $> 1$, of $\log(x)+x=\log(y)$ otherwise. \misctitle{Caveat} Complex values of $y$ are also supported but experimental. The other branches $W_{k}$ for $k$ not equal to $0$ or $-1$ (set \kbd{branch} to $k$) are also experimental. For $k\ge1$, $W_{-1-k}(x)=\overline{W_{k}(x)}$, and $\Im(W_{k}(x))$ is close to $(\pi/2)(4k-\text{sign}(x))$. pari-2.17.2/src/functions/transcendental/atanh0000644000175000017500000000052014567450071020014 0ustar billbillFunction: atanh Section: transcendental C-Name: gatanh Prototype: Gp Help: atanh(x): inverse hyperbolic tangent of x. Doc: principal branch of $\text{tanh}^{-1}(x) = \log ((1+x)/(1-x)) / 2$. In particular the imaginary part of $\text{atanh}(x)$ belongs to $[-\pi/2,\pi/2]$; if $x\in \R$ and $|x|>1$ then $\text{atanh}(x)$ is complex. pari-2.17.2/src/functions/transcendental/teichmuller0000644000175000017500000000450714676526175021261 0ustar billbillFunction: teichmuller Section: transcendental C-Name: teichmuller Prototype: GDG Help: teichmuller(x,{tab}): Teichmuller character of p-adic number x. If x = [p,n], return the lifts of all teichmuller(i + O(p^n)) for i = 1, ..., p-1. Such a vector can be fed back to teichmuller, as the optional argument tab, to speed up later computations. 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$. If $x$ is of the form $[p,n]$, for a prime $p$ and integer $n$, return the lifts to $\Z$ of the images of $i + O(p^{n})$ for $i = 1, \dots, p-1$, i.e. all roots of $1$ ordered by residue class modulo $p$. Such a vector can be fed back to \kbd{teichmuller}, as the optional argument \kbd{tab}, to speed up later computations. \bprog ? z = teichmuller(2 + O(101^5)) %1 = 2 + 83*101 + 18*101^2 + 69*101^3 + 62*101^4 + O(101^5) ? z^100 %2 = 1 + O(101^5) ? T = teichmuller([101, 5]); ? teichmuller(2 + O(101^5), T) %4 = 2 + 83*101 + 18*101^2 + 69*101^3 + 62*101^4 + O(101^5) @eprog\noindent As a rule of thumb, if more than $$p \,/\, 2(\log_{2}(p) + \kbd{hammingweight}(p))$$ values of \kbd{teichmuller} are to be computed, then it is worthwile to initialize: \bprog ? p = 101; n = 100; T = teichmuller([p,n]); \\ instantaneous ? for(i=1,10^3, vector(p-1, i, teichmuller(i+O(p^n), T))) time = 60 ms. ? for(i=1,10^3, vector(p-1, i, teichmuller(i+O(p^n)))) time = 1,293 ms. ? 1 + 2*(log(p)/log(2) + hammingweight(p)) %8 = 22.316[...] @eprog\noindent Here the precomputation induces a speedup by a factor $1293/ 60 \approx 21.5$. \misctitle{Caveat} If the accuracy of \kbd{tab} (the argument $n$ above) is lower than the precision of $x$, the \emph{former} is used, i.e. the cached value is not refined to higher accuracy. It the accuracy of \kbd{tab} is larger, then the precision of $x$ is used: \bprog ? Tlow = teichmuller([101, 2]); \\ lower accuracy ! ? teichmuller(2 + O(101^5), Tlow) %10 = 2 + 83*101 + O(101^5) \\ no longer a root of 1 ? Thigh = teichmuller([101, 10]); \\ higher accuracy ? teichmuller(2 + O(101^5), Thigh) %12 = 2 + 83*101 + 18*101^2 + 69*101^3 + 62*101^4 + O(101^5) @eprog Variant: Also available are the functions \fun{GEN}{teich}{GEN x} (\kbd{tab} is \kbd{NULL}) as well as \fun{GEN}{teichmullerinit}{long p, long n}. pari-2.17.2/src/functions/transcendental/theta0000644000175000017500000000035314676526175020044 0ustar billbillFunction: theta Section: transcendental C-Name: theta Prototype: GGp Help: theta(q,z): Jacobi sine theta-function. Doc: Jacobi sine theta-function $$ \theta_{1}(z, q) = 2q^{1/4} \sum_{n\geq 0} (-1)^{n} q^{n(n+1)} \sin((2n+1)z).$$ pari-2.17.2/src/functions/transcendental/besselj0000644000175000017500000000055614676526175020373 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.17.2/src/functions/transcendental/asin0000644000175000017500000000074114676526175017672 0ustar billbillFunction: asin Section: transcendental C-Name: gasin Prototype: Gp Help: asin(x): arc sine of x. Doc: principal branch of $\sin^{-1}(x) = -i \log(ix + \sqrt{1 - x^{2}})$. In particular, $\Re(\text{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.17.2/src/modules/0000755000175000017500000000000014760315601013426 5ustar billbillpari-2.17.2/src/modules/ellfromeqn.c0000644000175000017500000002377514760123736015762 0ustar billbill/* Copyright (C) 2015 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" /* This file is a C version by Bill Allombert of a GP script by Fernando Rodriguez-Villegas */ /* --------------- GP code --------------------------------------- */ /* http://www.ma.utexas.edu/users/villegas/cnt/jacobians.gp */ /* */ /* Description: Compute long Weierstrass equation for genus 1 curve */ /* given by a plane curve */ /* */ /* Original Author: Fernando Rodriguez-Villegas */ /* villegas@math.utexas.edu */ /* University of Texas at Austin */ /* */ /* Created: Tue Jun 7 2005 */ /* */ /*----------------------------------------------------------------- */ /* The mathematic behind this is described in On the Jacobians of plane cubics, Artin, Michael and Rodriguez-Villegas, Fernando and Tate, John, Advances in Mathematics, 198, 2005, 1, 366--382 DOI: 10.1016/j.aim.2005.06.004 URL: http://dx.doi.org/10.1016/j.aim.2005.06.004 PDF: http://www.sciencedirect.com/science/article/pii/S0001870805001775 */ /* Input: coefficients of a cubic */ /*t0*y^3+(s1+s0*x)*y^2 +(r2+r1*x+r0*x^2)*y+(q3+q2*x+q1*x^2+q0*x^3)=0*/ static GEN jac_cubic(GEN t0, GEN s0, GEN s1, GEN r0, GEN r1, GEN r2, GEN q0, GEN q1, GEN q2, GEN q3) { GEN t0_2 = gsqr(t0); GEN s0_2 = gsqr(s0), s0_3 = gmul(s0, s0_2); GEN s1_2 = gsqr(s1), s1_3 = gmul(s1, s1_2); GEN r0_2 = gsqr(r0), r0_3 = gmul(r0, r0_2); GEN r1_2 = gsqr(r1), r1_3 = gmul(r1, r1_2); GEN r2_2 = gsqr(r2), r2_3 = gmul(r2, r2_2); GEN q0_2 = gsqr(q0); GEN q1_2 = gsqr(q1), q1_3 = gmul(q1, q1_2); GEN q2_2 = gsqr(q2), q2_3 = gmul(q2, q2_2); GEN q3_2 = gsqr(q3); GEN p1 = cgetg(6, t_VEC); gel(p1, 1) = r1; gel(p1, 2) = gneg(gadd(gadd(gmul(s0, q2), gmul(s1, q1)), gmul(r0, r2))); gel(p1, 3) = gadd(gmul(gsub(gmul(gmulsg(9, t0), q0), gmul(s0, r0)), q3), gadd(gmul(gsub(gmul(gneg(t0), q1), gmul(s1, r0)), q2), gsub(gmul(gmul(gneg(s0), r2), q1), gmul(gmul(s1, r2), q0)))); gel(p1, 4) = gadd(gmul(gadd(gmul(gadd(gmul(gmulsg(-3, t0), r0), s0_2), q1), gadd(gmul(gmul(gmulsg(-3, s1), s0), q0), gmul(s1, r0_2))), q3), gadd(gadd(gmul(gmul(t0, r0), q2_2), gmul(gadd(gmul(gmul(s1, s0), q1), gadd(gmul(gadd(gmul(gmulsg(-3, t0), r2), s1_2), q0), gmul(gmul(s0, r0), r2))), q2)), gadd(gadd(gmul(gmul(t0, r2), q1_2), gmul(gmul(gmul(s1, r0), r2), q1)), gmul(gmul(s0, r2_2), q0)))); gel(p1, 5) = gadd(gadd(gmul(gsub(gadd(gmul(gmulsg(-27, t0_2), q0_2), gmul(gsub(gmul(gmul(gmulsg(9, t0), s0), r0), s0_3), q0)), gmul(t0, r0_3)), q3_2), gmul(gadd(gmul(gadd(gmul(gsub(gmul(gmulsg(9, t0_2), q0), gmul(gmul(t0, s0), r0)), q1), gadd(gmul(gadd(gmul(gmul(gmulsg(-3, t0), s0), r1), gadd(gmul(gmul(gmulsg(3, t0), s1), r0), gmul(gmulsg(2, s1), s0_2))), q0), gsub(gmul(gmul(t0, r0_2), r1), gmul(gmul(s1, s0), r0_2)))), q2), gadd(gadd(gadd(gmul(gneg(t0_2), q1_3), gmul(gadd(gmul(gmul(t0, s0), r1), gsub(gmul(gmul(gmulsg(2, t0), s1), r0), gmul(s1, s0_2))), q1_2)), gmul(gadd(gmul(gadd(gmul(gmul(gmulsg(3, t0), s0), r2), gadd(gmul(gmul(gmulsg(-3, t0), s1), r1), gmul(gmulsg(2, s1_2), s0))), q0), gadd(gmul(gsub(gmul(gmulsg(2, t0), r0_2), gmul(s0_2, r0)), r2), gsub(gadd(gmul(gmul(gneg(t0), r0), r1_2), gmul(gmul(gmul(s1, s0), r0), r1)), gmul(s1_2, r0_2)))), q1)), gadd(gmul(gsub(gmul(gmul(gmulsg(9, t0), s1), r2), s1_3), q0_2), gmul(gadd(gmul(gsub(gmul(gadd(gmul(gmulsg(-3, t0), r0), s0_2), r1), gmul(gmul(s1, s0), r0)), r2), gadd(gsub(gmul(t0, r1_3), gmul(gmul(s1, s0), r1_2)), gmul(gmul(s1_2, r0), r1))), q0)))), q3)), gadd(gadd(gadd(gmul(gmul(gneg(t0_2), q0), q2_3), gmul(gadd(gmul(gmul(gmul(gneg(t0), s1), r0), q1), gsub(gmul(gadd(gmul(gmul(gmulsg(2, t0), s0), r2), gsub(gmul(gmul(t0, s1), r1), gmul(s1_2, s0))), q0), gmul(gmul(t0, r0_2), r2))), q2_2)), gmul(gadd(gadd(gmul(gmul(gmul(gneg(t0), s0), r2), q1_2), gmul(gadd(gmul(gmul(gmul(gneg(t0), s1), r2), q0), gmul(gsub(gmul(gmul(t0, r0), r1), gmul(gmul(s1, s0), r0)), r2)), q1)), gmul(gadd(gmul(gsub(gmul(gmulsg(2, t0), r0), s0_2), r2_2), gmul(gsub(gadd(gmul(gneg(t0), r1_2), gmul(gmul(s1, s0), r1)), gmul(s1_2, r0)), r2)), q0)), q2)), gsub(gadd(gmul(gmul(gmul(gneg(t0), r0), r2_2), q1_2), gmul(gmul(gmul(gsub(gmul(t0, r1), gmul(s1, s0)), r2_2), q0), q1)), gmul(gmul(t0, r2_3), q0_2)))); return p1; } /* Input: coefficients of an equation */ /* t0*y^2+(s0*x^2+s1*x+s2)*y+(r0*x^4+r1*x^3+r2*x^2+r3*x+r4)=0 */ static GEN jac_quart(GEN t0, GEN s0, GEN s1, GEN s2, GEN r0, GEN r1, GEN r2, GEN r3, GEN r4) { GEN t0_2 = gsqr(t0), t0_3 = gmul(t0, t0_2); GEN s0_2 = gsqr(s0); GEN s1_2 = gsqr(s1); GEN s2_2 = gsqr(s2); GEN r1_2 = gsqr(r1); GEN r3_2 = gsqr(r3); GEN p1 = cgetg(6, t_VEC); gel(p1, 1) = s1; gel(p1, 2) = gsub(gmul(gneg(t0), r2), gmul(s0, s2)); gel(p1, 3) = gsub(gmul(gmul(gneg(t0), s2), r1), gmul(gmul(t0, s0), r3)); gel(p1, 4) = gadd(gadd(gadd(gmul(gneg(gsub(gmul(gmulsg(4, t0_2), r4), gmul(t0, s2_2))), r0), gmul(gmul(t0_2, r1), r3)), gmul(gmul(gmul(t0, s0), s2), r2)), gmul(gmul(t0, s0_2), r4)); gel(p1, 5) = gsub(gsub(gsub(gmul(gneg(gadd(gsub(gadd(gmul(gneg(gsub(gmul(gmulsg(4, t0_3), r4), gmul(t0_2, s2_2))), r2), gmul(t0_3, r3_2)), gmul(gmul(gmul(t0_2, s1), s2), r3)), gmul(gmul(t0_2, s1_2), r4))), r0), gmul(gmul(t0_3, r1_2), r4)), gmul(gsub(gmul(gmul(gmul(t0_2, s0), s2), r3), gmul(gmul(gmul(t0_2, s0), s1), r4)), r1)), gmul(gmul(gmul(t0_2, s0_2), r2), r4)); return p1; } /* Input: coefficients of an equation */ /* (t0*x^2+t1*x+t2)*y^2+(r0*x^2+r1*x+r2)*y+(s0*x^2+s1*x+s2)=0 */ static GEN jac_biquadr(GEN t0, GEN t1, GEN t2, GEN r0, GEN r1, GEN r2, GEN s0, GEN s1, GEN s2) { GEN t0_2 = gsqr(t0); GEN t1_2 = gsqr(t1); GEN t2_2 = gsqr(t2); GEN s0_2 = gsqr(s0); GEN s1_2 = gsqr(s1); GEN s2_2 = gsqr(s2); GEN r0_2 = gsqr(r0); GEN r1_2 = gsqr(r1); GEN r2_2 = gsqr(r2); GEN p1 = cgetg(6, t_VEC); gel(p1, 1) = r1; gel(p1, 2) = gneg(gadd(gadd(gadd(gmul(s2, t0), gmul(t2, s0)), gmul(t1, s1)), gmul(r2, r0))); gel(p1, 3) = gadd(gmul(gmul(gneg(r2), s1), t0), gadd(gmul(gmul(gneg(t1), r2), s0), gsub(gmul(gmul(gneg(t2), r0), s1), gmul(gmul(t1, r0), s2)))); gel(p1, 4) = gadd(gmul(gadd(gmul(gadd(gmul(gmulsg(-4, t2), s2), r2_2), s0), gadd(gadd(gmul(t2, s1_2), gmul(gmul(t1, s2), s1)), gmul(gmul(r2, r0), s2))), t0), gadd(gmul(gadd(gmul(gmul(t2, t1), s1), gadd(gmul(t1_2, s2), gmul(gmul(t2, r2), r0))), s0), gadd(gmul(gmul(gmul(t1, r2), r0), s1), gmul(gmul(t2, r0_2), s2)))); gel(p1, 5) = gadd(gadd(gmul(gsub(gmul(gsub(gmul(gmulsg(4, t2), s2_2), gmul(r2_2, s2)), s0), gmul(gmul(t2, s2), s1_2)), t0_2), gmul(gadd(gadd(gmul(gsub(gmul(gmulsg(4, t2_2), s2), gmul(t2, r2_2)), s0_2), gmul(gadd(gadd(gmul(gneg(t2_2), s1_2), gmul(gsub(gmul(gmul(t2, r2), r1), gmul(t1, r2_2)), s1)), gadd(gmul(gneg(t1_2), s2_2), gmul(gadd(gmul(gneg(t2), r1_2), gmul(gmul(t1, r2), r1)), s2))), s0)), gsub(gadd(gmul(gmul(gmul(gneg(t2), r2), r0), s1_2), gmul(gmul(gmul(gsub(gmul(t2, r1), gmul(t1, r2)), r0), s2), s1)), gmul(gmul(t2, r0_2), s2_2))), t0)), gsub(gadd(gmul(gmul(gmul(gneg(t2), t1_2), s2), s0_2), gmul(gadd(gmul(gmul(gmul(gmul(gneg(t2), t1), r2), r0), s1), gmul(gadd(gmul(gneg(t2_2), r0_2), gmul(gsub(gmul(gmul(t2, t1), r1), gmul(t1_2, r2)), r0)), s2)), s0)), gmul(gmul(gmul(gmul(t2, t1), r0_2), s2), s1))); return p1; } INLINE long dg(GEN P, long v) { if (typ(P)!=t_POL || varn(P)!=v || !signe(P)) return -1; return degpol(P); } INLINE GEN co(GEN P, long i, long v) { if (typ(P)!=t_POL || varn(P)!=v) return i==0 ? P: gen_0; if (i>degpol(P)) return gen_0; return gel(P, i+2); } GEN ellfromeqn(GEN P) { pari_sp av = avma; long vx, vy, dx, dy, dm; GEN r = gen_0; if (typ(P)!=t_POL) pari_err_TYPE("ellfromeqn",P); vx = varn(P); vy = gvar2(P); if (vy==NO_VARIABLE) pari_err_TYPE("ellfromeqn",P); dx = poldegree(P, vx); dy = poldegree(P, vy); dm = maxss(dx, dy); if (dm == 2) { GEN p_0 = co(P, 0, vx), p_1 = co(P, 1, vx), p_2 = co(P, 2, vx); r = jac_biquadr(co(p_2, 2, vy), co(p_2, 1, vy), co(p_2, 0, vy), co(p_1, 2, vy), co(p_1, 1, vy), co(p_1, 0, vy), co(p_0, 2, vy), co(p_0, 1, vy), co(p_0, 0, vy)); } else if (dm == 3) { GEN p_0 = co(P, 0, vx), p_1 = co(P, 1, vx), p_2 = co(P, 2, vx), p_3 = co(P, 3, vx); if (dg(p_3, vy) > 0 || dg(p_2, vy) > 1 || dg(p_1, vy) > 2) r = gen_0; /* genus > 1 */ else r = jac_cubic( co(p_3, 0, vy), co(p_2, 1, vy), co(p_2, 0, vy), co(p_1, 2, vy), co(p_1, 1, vy), co(p_1, 0, vy), co(p_0, 3, vy), co(p_0, 2, vy), co(p_0, 1, vy), co(p_0, 0, vy)); } else if (dm == 4 && dx == 2) { GEN p_0 = co(P, 0, vx), p_1 = co(P, 1, vx), p_2 = co(P, 2, vx); if (dg(p_2, vy) > 0 || dg(p_1, vy) > 2) r = gen_0; /* genus > 1 */ else r = jac_quart( co(p_2, 0, vy), co(p_1, 2, vy), co(p_1, 1, vy), co(p_1, 0, vy), co(p_0, 4, vy), co(p_0, 3, vy), co(p_0, 2, vy), co(p_0, 1, vy), co(p_0, 0, vy)); } else if (dm == 4 && dx == 4) { GEN p_0 = co(P, 0, vx), p_1 = co(P, 1, vx), p_2 = co(P, 2, vx), p_3 = co(P, 3, vx), p_4 = co(P, 4, vx); if (dg(p_4, vy) > 0 || dg(p_3, vy) > 0 || dg(p_2, vy) > 1 || dg(p_1, vy) > 1 || dg(p_0, vy) > 2) r = gen_0; /* genus > 1 */ else r = jac_quart(co(p_0, 2, vy), co(p_2, 1, vy), co(p_1, 1, vy), co(p_0, 1, vy), co(p_4, 0, vy), co(p_3, 0, vy), co(p_2, 0, vy), co(p_1, 0, vy), co(p_0, 0, vy)); } if (r==gen_0) pari_err_DOMAIN("ellfromeqn", "genus", "!=", gen_1,P); return gerepilecopy(av, r); } pari-2.17.2/src/modules/forsubset.c0000644000175000017500000000443714567450071015624 0ustar billbill/* Copyright (C) 2017 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" void forksubset_init(forsubset_t *T, long n, long k) { T->all = 0; T->first = 1; T->n = n; T->k = k; T->v = identity_perm(k); } void forallsubset_init(forsubset_t *T, long n) { T->all = 1; T->first = 1; T->n = n; T->k = 0; T->v = vecsmalltrunc_init(n + 1); } static GEN forksubset_next(forsubset_t *T) { GEN v = T->v; long i, n = T->n, k = T->k; if (T->first) { T->first = 0; return (k >= 0 && k <= n) ? v: NULL; } if (k <= 0 || k >= n) return NULL; if (v[k] < n) { v[k]++; return v; } for (i = k - 1; i >= 1 && v[i+1] == v[i] + 1; i--); if (i == 0) return NULL; v[i]++; for (; i < k; i++) v[i+1] = v[i] + 1; return v; } static GEN forallsubset_next(forsubset_t *T) { long i; if (forksubset_next(T)) return T->v; else if (T->k < T->n) { (T->k)++; setlg(T->v, T->k+1); for (i = 1; i <= T->k; i++) (T->v)[i] = i; return T->v; } return NULL; } GEN forsubset_next(forsubset_t *T) { return T->all? forallsubset_next(T): forksubset_next(T); } void forsubset_init(forsubset_t *T, GEN nk) { switch(typ(nk)) { case t_INT: forallsubset_init(T, itos(nk)); return; case t_VEC: if (lg(nk) == 3) { GEN n = gel(nk,1), k = gel(nk,2); if (typ(n) == t_INT && typ(k) == t_INT) return forksubset_init(T, itos(n),itos(k)); } default: pari_err_TYPE("forsubset", nk); } } void forsubset0(GEN nk, GEN code) { pari_sp av = avma; forsubset_t T; void *E = (void*)code; GEN v; push_lex(gen_0, code); forsubset_init(&T, nk); while ((v = forsubset_next(&T))) if (gp_evalvoid(E, v)) break; pop_lex(1); set_avma(av); } pari-2.17.2/src/modules/galois.c0000644000175000017500000022050714676526175015076 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_polgalois /**************************************************************/ /* Galois group for degree in [8, 11] */ /**************************************************************/ #define NMAX 11 /* maximum degree */ typedef GEN PERM; typedef PERM *GROUP; typedef struct { PERM *a; long nm, nv; } resolv; /* resolvent */ typedef struct { long pr, prmax, N; GEN p, r, coef; } buildroot; static long isin_G_H(buildroot *BR, long n1, long n2); /* 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 *par_vec) { long i; if (n <= 0) { GEN t = cgetg(k, t_VECSMALL); for (i=1; i 7) { err_printf("Partitions of %ld (%ld)\n",n, p); for (i=1; i<=p; i++) err_printf("i = %ld: %Ps\n",i,gel(T,i)); } T[0] = evallg(p + 1) | evaltyp(t_VEC); return T; } /* affect to the permutation x the N arguments that follow */ static void _aff(long N, PERM x,...) { va_list args; long i; va_start(args,x); for (i=1; i<=N; i++) x[i] = va_arg(args,int); va_end(args); } /* return an array of length |len| from the arguments (for galoismodulo) */ static GEN _gr(long len,...) { va_list args; long i, l = labs(len); GEN x = new_chunk(l+1); va_start(args,len); x[0] = len; for (i=1; i<=l; i++) x[i] = va_arg(args,int); va_end(args); return x; } /* return a VECSMALL of length l from the arguments (for galoismodulo11) */ static GEN _typ(long l,...) { va_list args; long i; GEN x = cgetg(l+1, t_VECSMALL); va_start(args,l); for (i=1; i<=l; i++) x[i] = va_arg(args,int); va_end(args); return x; } /* create a permutation with the N arguments of the function */ static PERM _cr(long N, long a,...) { va_list args; long i; GEN x = new_chunk(NMAX+1); va_start(args, a); x[0] = N; x[1] = a; for (i=2; i<=N; i++) x[i] = va_arg(args,int); va_end(args); return x; } static PERM permmul(PERM s1, PERM s2) { long i, n1 = s1[0]; PERM s3 = (PERM)stack_malloc((n1+1) * sizeof(long)); for (i=1; i<=n1; i++) s3[i] = s1[s2[i]]; s3[0] = n1; return s3; } static void printperm(PERM perm) { long i, n = perm[0]; err_printf("("); for (i=1; i<=n; i++) err_printf(" %d",perm[i]); err_printf(" )\n"); } static int raye(long *g, long num) { long i, nb = labs(g[0]); for (i=1; i<=nb; i++) if (g[i] == num) return 0; return 1; } /* we can never determine the group completely in there */ static long rayergroup11(long EVEN, long num, long *gr) { long r = 0; if (EVEN) switch(num) { case 2: case 5: if (gr[3]) { gr[3]=0; r++; } case 3: case 6: case 7: if (gr[2]) { gr[2]=0; r++; } case 4: if (gr[1]) { gr[1]=0; r++; } } else switch(num) { case 2: case 3: if (gr[1]) { gr[1]=0; r++; } } return r; } static long rayergroup(long EVEN, long **GR, long num, long *gr) { long i,nbgr,r; if (!GR) return rayergroup11(EVEN,num,gr); nbgr = lg(GR); r = 0 ; if (EVEN) { for (i=1; i 0 && raye(GR[i],num)) { gr[i]=0; r++; } } return r; } static long galmodp(long EVEN, GEN pol, GEN dpol, GEN TYP, long *gr, long **GR) { long i,k,l,n,nbremain; GEN p1, dtyp; forprime_t T; switch(degpol(pol)) { case 8: nbremain = EVEN? 28: 22; break; case 9: nbremain = EVEN? 18: 16; break; case 10: nbremain = EVEN? 12: 33; break; default: nbremain = EVEN? 5: 3; break; /* case 11 */ } u_forprime_init(&T, 2, ULONG_MAX); dtyp = new_chunk(NMAX+1); k = gr[0]; for (i=1; ir; long i, l = lg(r), p = BR->pr; if (p > BR->prmax) pari_err_BUG("fixprex [precision too large]"); for (i = 1; i < l; i++) preci(gel(r,i), p); } static long getpreci(buildroot *BR) { GEN x = gmael(BR->r,1,1); return (typ(x)==t_COMPLEX)? realprec(gel(x,1)): realprec(x); } #define setcard_obj(x,n) ((x)[0] = (PERM)(n)) #define getcard_obj(x) ((long)((x)[0])) /* allocate a list of m arrays of length n (index 0 is codeword) */ static PERM * alloc_pobj(long n, long m) { long i; PERM *g = (PERM*) stack_malloc( (m+1)*sizeof(PERM) + (n+1)*m * sizeof(long) ); PERM gpt = (PERM) (g + (m+1)); for (i=1; i<=m; i++) { g[i] = gpt; gpt += (n+1); } setcard_obj(g, m); return g; } static GROUP allocgroup(long n, long card) { GROUP gr = alloc_pobj(n,card); long i; for (i=1; i<=card; i++) gr[i][0] = n; return gr; } static pariFILE * galopen(const char *pre, long n, long n1, long n2) { pari_sp av = avma; pariFILE *f; char *s = stack_sprintf("%s/galdata/%s%ld_%ld_%ld", pari_datadir, pre, n, n1, n2); f = pari_fopengz(s); if (!f) pari_err_FILE("galois file",s); set_avma(av); return f; } static char bin(char c) { if (c>='0' && c<='9') c -= '0'; else if (c>='A' && c<='Z') c -= 'A'-10; else if (c>='a' && c<='z') c -= 'a'-36; else pari_err_TYPE("bin [not alphanumeric]", stoi(c)); return c; } #define BUFFS 512 /* fill in g[i][j] (i<=n, j<=m) with (buffered) data from f->file */ static void read_obj(PERM *g, pariFILE *f, long n, long m) { long i, j, k, N = m*n; char *ch = stack_malloc(N); pari_fread_chars(ch, N, f->file); for (k = 0, i = 1; i <= n; i++) for (j = 1; j <= m; j++,k++) g[i][j] = bin(ch[k]); pari_fclose(f); } #undef BUFFS /* the first 8 bytes contain size data (possibly padded with \0) */ static GROUP lirecoset(long n1, long n2, long n) { GROUP gr; char c, ch[8]; long m, cardgr; pariFILE *f = galopen("COS", n, n1, n2); pari_fread_chars(&c, 1, f->file); m=bin(c); pari_fread_chars(&c, 1, f->file); pari_fread_chars(ch, 6, f->file); cardgr=atol(ch); gr=allocgroup(m,cardgr); read_obj(gr, f,cardgr,m); return gr; } static void lireresolv(long n1, long n2, long n, resolv *R) { char ch[5]; long nm, nv; pariFILE *f = galopen("RES", n, n1, n2); pari_fread_chars(ch,5,f->file); nm = atol(ch); pari_fread_chars(ch,3,f->file); nv = atol(ch); R->a = alloc_pobj(nv,nm); read_obj(R->a, f,nm,nv); R->nm = nm; R->nv = nv; } static int cmp_re(GEN x, GEN y) { if (typ(x) != t_COMPLEX) return -1; if (typ(y) != t_COMPLEX) return 1; /* t_REALS are smallest */ return gcmp(gel(x,1), gel(y,1)); } /* multiply the r o bb. Sort first to detect pairs of conjugate */ static GEN Monomial(GEN r, PERM bb, long nbv) { GEN t, R = cgetg(nbv + 1, t_VEC); long i, s = 1; for (i = 1; i <= nbv; i++) { t = gel(r,bb[i]); if (typ(t) == t_COMPLEX && signe(gel(t,1)) < 0) { s = -s; t = gneg(t); } gel(R,i) = t; } if (nbv > 2) gen_sort_inplace(R, (void*)&cmp_re, cmp_nodata, NULL); else if (nbv == 2 && typ(gel(R,2)) != t_COMPLEX) swap(gel(R,1), gel(R,2)); t = NULL; for (i=1; i<=nbv; i++) { GEN c = gel(R,i); if (typ(c) == t_COMPLEX && i < nbv) { /* detect conjugates */ GEN n = gel(R,++i); if (!abscmprr(gel(n,1), gel(c,1)) && !abscmprr(gel(n,2), gel(c,2)) && signe(gel(c,2)) != signe(gel(n,2))) c = addrr(sqrr(gel(c,1)), sqrr(gel(c,2))); else c = gmul(c,n); } t = t? gmul(t, c): c; } if (s < 0) t = gneg(t); return t; } /* sum(i = 1, R->nm, Monomial(r, R->a[i], R->nv)). Sort real / imaginary part * separately by increasing absolute values, to increase stability */ static GEN gpolynomial(GEN r, resolv *R) { GEN RE = cgetg(R->nm+1, t_VEC), IM = cgetg(R->nm+1, t_VEC), re, im; long i, k; for (i = k = 1; i <= R->nm; i++) { GEN m = Monomial(r,R->a[i], R->nv); if (typ(m) == t_REAL) gel(RE, i) = m; else { gel(RE, i) = gel(m,1); gel(IM, k++) = gel(m,2); } } setlg(IM, k); gen_sort_inplace(RE, (void*)&abscmprr, cmp_nodata, NULL); gen_sort_inplace(IM, (void*)&abscmprr, cmp_nodata, NULL); re = gel(RE,1); for (i = 2; i <= R->nm; i++) re = addrr(re, gel(RE,i)); if (k == 1) return re; im = gel(IM,1); for (i = 2; i < k; i++) im = addrr(im, gel(IM,i)); return mkcomplex(re, im); } static void zaux1(GEN *z, GEN *r) { GEN p2,p1; p2=gsub(r[1], gadd(r[2],r[5])); p2=gmul(p2, gsub(r[2],r[5])); p1=gmul(p2,r[1]); p2=gsub(r[3],gadd(r[2],r[4])); p2=gmul(p2,gsub(r[4],r[2])); p1=gadd(p1,gmul(p2,r[3])); p2=gmul(r[5],gsub(r[4],r[5])); z[1]=gadd(p1,gmul(p2,r[4])); p2=gsub(r[1],gadd(r[3],r[4])); p2=gmul(p2,gsub(r[3],r[4])); p1=gmul(p2,r[1]); p2=gsub(r[5],gadd(r[3],r[2])); p2=gmul(p2,gsub(r[2],r[3])); p1=gadd(p1,gmul(p2,r[5])); p2=gmul(r[4],gsub(r[2],r[4])); z[2]=gadd(p1,gmul(p2,r[2])); } static void zaux(GEN *z, GEN *r) { zaux1(z, r); zaux1(z+2, r+5); } static GEN gpoly(GEN rr, long n1, long n2) { const long N = lg(rr)-1; GEN p1,p2,z[6], *r = (GEN*)rr; /* syntaxic kludge */ long i,j; if (N==8) { if (n1==47 && n2==46) { p1=gsub(r[3],r[4]); for (i=1; i<3; i++) for (j=i+1; j<5; j++) p1 = gmul(p1,gsub(r[i],r[j])); for (i=5; i<8; i++) for (j=i+1; j<9; j++) p1 = gmul(p1,gsub(r[i],r[j])); p2=r[1]; for (i=2; i<5; i++) p2=gadd(p2,r[i]); for (i=5; i<9; i++) p2=gsub(p2,r[i]); } else /* n1==44 && n2==40 */ { for (i=1; i<5; i++) z[i] = gadd(r[2*i-1],r[2*i]); p1 = gsub(r[1],r[2]); for (i=2; i<5; i++) p1 = gmul(p1,gsub(r[2*i-1],r[2*i])); p2=gsub(z[3],z[4]); for (i=1; i<3; i++) for (j=i+1; j<5; j++) p2 = gmul(p2,gsub(z[i],z[j])); } return gmul(p1,p2); } if (N==9) { if (n1==31 && n2==29) { p1=gsub(r[2],r[3]); for (j=2; j<4; j++) p1 = gmul(p1,gsub(r[1],r[j])); for (i=4; i<6; i++) for (j=i+1; j<7; j++) p1 = gmul(p1,gsub(r[i],r[j])); p2 = gsub(r[8],r[9]); for (j=8; j<10; j++) p2 = gmul(p2,gsub(r[7],r[j])); } else /* ((n1==34 && n2==31) || (n1=33 && n2==30)) */ { p1=r[1]; for (i=2; i<4; i++) p1=gadd(p1,r[i]); p2=r[4]; for (i=5; i<7; i++) p2=gadd(p2,r[i]); p1=gmul(p1,p2); p2=r[7]; for (i=8; i<10; i++) p2=gadd(p2,r[i]); } return gmul(p1,p2); } if (N==10) { if ((n1==45 && n2==43) || (n1==44 && n2==42)) { p1=r[1]; for (i=2; i<6; i++) p1=gadd(p1,r[i]); p2=r[6]; for (i=7; i<11; i++) p2=gadd(p2,r[i]); return gmul(p1,p2); } else if ((n1==45 && n2==39) || (n1==44 && n2==37)) { p1 = gadd(r[1],r[2]); for (i=2; i<6; i++) p1 = gmul(p1,gadd(r[2*i-1],r[2*i])); return p1; } else if ((n1==43 && n2==41) || (n1==33 && n2==27)) { p1=gsub(r[4],r[5]); for (i=1; i<4; i++) for (j=i+1; j<6; j++) p1=gmul(p1,gsub(r[i],r[j])); p2=gsub(r[9],r[10]); for (i=6; i<9; i++) for (j=i+1; j<11; j++) p2=gmul(p2,gsub(r[i],r[j])); return gmul(p1,p2); } else if ((n1==43 && n2==33) || (n1==42 && n2==28) || (n1==41 && n2==27) || (n1==40 && n2==21)) { p2=gadd(r[2],r[5]); p2=gsub(p2,gadd(r[3],r[4])); p1=gmul(p2,r[1]); p2=gsub(r[3],gadd(r[4],r[5])); p1=gadd(p1,gmul(p2,r[2])); p2=gsub(r[4],r[5]); p1=gadd(p1,gmul(p2,r[3])); z[1]=gadd(p1,gmul(r[4],r[5])); p2=gadd(r[7],r[10]); p2=gsub(p2,gadd(r[8],r[9])); p1=gmul(p2,r[6]); p2=gsub(r[8],gadd(r[9],r[10])); p1=gadd(p1,gmul(p2,r[7])); p2=gsub(r[9],r[10]); p1=gadd(p1,gmul(p2,r[8])); z[2]=gadd(p1,gmul(r[9],r[10])); return gadd(gsqr(z[1]), gsqr(z[2])); } else if (n1==41 && n2==40) { p1=gsub(r[4],r[5]); for (i=1; i<4; i++) for (j=i+1; j<6; j++) p1 = gmul(p1,gsub(r[i],r[j])); p2=gsub(r[9],r[10]); for (i=6; i<9; i++) for (j=i+1; j<11; j++) p2 = gmul(p2,gsub(r[i],r[j])); return gadd(p1,p2); } else if ((n1==41 && n2==22) || (n1==40 && n2==11) || (n1==17 && n2==5) || (n1==10 && n2==4) || (n1==9 && n2==3) || (n1==6 && n2==1)) { p1=gadd(r[1],r[6]); for (i=2; i<6; i++) p1=gmul(p1,gadd(r[i],r[i+5])); return p1; } else if ((n1==39 && n2==38) || (n1==29 && n2==25)) { for (i=1; i<6; i++) z[i]=gadd(r[2*i-1],r[2*i]); p1=gsub(r[1],r[2]); for (i=2; i<6; i++) p1=gmul(p1,gsub(r[2*i-1],r[2*i])); p2=gsub(z[4],z[5]); for (i=1; i<4; i++) for (j=i+1; j<6; j++) p2=gmul(p2,gsub(z[i],z[j])); return gmul(p1,p2); } else if ((n1==39 && n2==36) || (n1==37 && n2==34) || (n1==29 && n2==23) || (n1==24 && n2==15)) { for (i=1; i<6; i++) z[i]=gadd(r[2*i-1],r[2*i]); p1=gsub(z[4],z[5]); p2=gmul(gsub(z[3],z[4]),gsub(z[3],z[5])); for (i=1; i<3; i++) for (j=i+1; j<6; j++) p2=gmul(p2,gsub(z[i],z[j])); return gmul(p1,p2); } else if ((n1==39 && n2==29) || (n1==38 && n2==25) || (n1==37 && n2==24) || (n1==36 && n2==23) || (n1==34 && n2==15)) { for (i=1; i<6; i++) z[i]=gadd(r[2*i-1],r[2*i]); p2=gadd(z[2],z[5]); p2=gsub(p2,gadd(z[3],z[4])); p1=gmul(p2,z[1]); p2=gsub(z[3],gadd(z[4],z[5])); p1=gadd(p1,gmul(p2,z[2])); p2=gsub(z[4],z[5]); p1=gadd(p1,gmul(p2,z[3])); p1=gadd(p1,gmul(z[4],z[5])); return gsqr(p1); } else if ((n1==39 && n2==22) || (n1==38 && n2==12) || (n1==36 && n2==11) || (n1==29 && n2== 5) || (n1==25 && n2== 4) || (n1==23 && n2== 3) || (n1==16 && n2== 2) || (n1==14 && n2== 1)) { p1=r[1]; for (i=2; i<6; i++) p1=gadd(p1,r[2*i-1]); p2=r[2]; for (i=2; i<6; i++) p2=gadd(p2,r[2*i]); return gmul(p1,p2); } else if (n1==28 && n2==18) { zaux(z, r); p1=gmul(z[1],gsub(z[3],z[4])); p2=gmul(z[2],gadd(z[3],z[4])); return gadd(p1,p2); } else if (n1==27 && n2==20) { zaux(z, r); p1=gmul(z[1],z[3]); p2=gmul(z[2],z[4]); p1 = gsub(p1,p2); p2=r[1]; for (i=2; i<6 ; i++) p2=gadd(p2,r[i]); for ( ; i<11; i++) p2=gsub(p2,r[i]); return gmul(p1,p2); } else if (n1==27 && n2==19) { zaux(z, r); p1=gmul(z[1],z[3]); p2=gmul(z[2],z[4]); return gsub(p1,p2); } else if ((n1==27 && n2==17) || (n1==21 && n2==9)) { zaux(z, r); p1=gmul(z[1],z[3]); p2=gmul(z[2],z[4]); return gadd(p1,p2); } else if (n1==23 && n2==16) { for (i=1; i<6; i++) z[i]=gadd(r[2*i-1],r[2*i]); p1=gsub(z[1],gadd(z[2],z[5])); p1=gmul(p1,gsub(z[2],z[5])); p2=gmul(p1,z[1]); p1=gsub(z[3],gadd(z[2],z[4])); p1=gmul( p1,gsub(z[4],z[2])); p2=gadd(p2,gmul(p1,z[3])); p1=gmul(z[5],gsub(z[4],z[5])); p2=gadd(p2,gmul(p1,z[4])); p1=gsub(r[1],r[2]); for (i=2; i<6; i++) p1=gmul(p1,gsub(r[2*i-1],r[2*i])); return gmul(p1,p2); } else if (n1==22 && n2==12) { for (i=1; i<6; i++) z[i]=gadd(r[i],r[i+5]); p1=gsub(r[1],r[6]); for (i=2; i<6; i++) p1=gmul(p1,gsub(r[i],r[i+5])); p2=gsub(z[4],z[5]); for (i=1; i<4; i++) for (j=i+1; j<6; j++) p2=gmul(p2,gsub(z[i],z[j])); return gmul(p1,p2); } else if ((n1==22 && n2==11) || (n1==5 && n2==3)) { for (i=1; i<6; i++) z[i]=gadd(r[i],r[i+5]); p1=gsub(z[4],z[5]); p2=gmul(gsub(z[3],z[4]),gsub(z[3],z[5])); for (i=1; i<3; i++) for (j=i+1; j<6; j++) p2=gmul(p2,gsub(z[i],z[j])); return gmul(p1,p2); } else if ((n1==22 && n2==5) || (n1==12 && n2==4) || (n1==11 && n2==3)) { for (i=1; i<6; i++) z[i]=gadd(r[i],r[i+5]); p2=gadd(z[2],z[5]); p2=gsub(p2,gadd(z[3],z[4])); p1=gmul(p2,z[1]); p2=gsub(z[3],gadd(z[4],z[5])); p1=gadd(p1,gmul(p2,z[2])); p2=gsub(z[4],z[5]); p1=gadd(p1,gmul(p2,z[3])); p1=gadd(p1,gmul(z[4],z[5])); return gsqr(p1); } else if (n1==21 && n2==10) { zaux(z, r); p1=gmul(z[1],z[4]); p2=gmul(z[2],z[3]); return gsub(p1,p2); } } pari_err_TYPE("gpoly [undefined invariant polynomial]", mkvecsmall2(n1,n2)); return NULL; /* LCOV_EXCL_LINE */ } /* a is a t_VECSMALL representing a polynomial */ static GEN new_pol(long N, GEN r, GEN a) { long i, j, l = lg(a); GEN x, z, v = cgetg(N+1, t_VEC); for (i=1; i<=N; i++) { z = gel(r,i); x = gaddsg(a[2], z); for (j = 3; j < l; j++) x = gaddsg(a[j], gmul(z,x)); gel(v,i) = x; } return gclone(v); } /* BR->r[l], BR->coef[l] hold data related to Tschirnausen transform of * degree l - 1 */ static void tschirn(buildroot *BR) { long i, k, v = varn(BR->p), l = lg(BR->r); GEN a, h, r; if (l >= BR->N) pari_err_BUG("tschirn"); if (DEBUGLEVEL) err_printf("\n$$$$$ Tschirnhaus transformation of degree %ld: $$$$$\n",l-1); a = gel(BR->coef,l); /* fill with random polynomial of degree <= l-1 */ do { a[1]=0; for (i=2; i < l+2; i++) a[i] = random_bits(3) + 1; h = Flx_to_ZX(Flx_renormalize(a,l+2)); } while (degpol(h) <= 0 || !ZX_is_squarefree(h)); setvarn(h, v); k = 0; (void)ZXQ_charpoly_sqf(BR->p, h, &k, v); a[2] += k; r = gel(BR->r,1); preci(r, BR->prmax); /* max accuracy original roots */ vectrunc_append(BR->r, new_pol(BR->N, r, a)); fixprec(BR); /* restore accuracy */ } static GEN sortroots(GEN newr, GEN oldr) { long e, e0, i, j, k, l = lg(newr); GEN r = cgetg(l, t_VEC), z = cgetg(l, t_VEC), t = const_vecsmall(l-1, 1); k = 0; /* gcc -Wall */ for (i=1; ir; long i, l = lg(r); for (i = 1; i < l; i++) gunclone(gel(r,i)); setlg(r, 1); } /* increase the roots accuracy */ static void moreprec(buildroot *BR) { long d = BR->pr - BR->prmax; if (d > 0) { /* recompute roots */ pari_sp av = avma; long l = lg(BR->r); GEN ro; if (d < BIGDEFAULTPREC) d = BIGDEFAULTPREC; BR->prmax = maxss(BR->prmax+d, (long)(BR->prmax * 1.2)); if (DEBUGLEVEL) err_printf("$$$$$ New prec = %ld\n",BR->prmax); ro = sortroots(QX_complex_roots(BR->p,BR->prmax), gel(BR->r,1)); delete_roots(BR); vectrunc_append(BR->r, gclone(ro)); for (d = 2; d < l; d++) vectrunc_append(BR->r, new_pol(BR->N, ro, gel(BR->coef,d))); set_avma(av); } fixprec(BR); } /* determine "sufficient" extra bit-precision such that we may decide * (heuristic) whether z is an integer. */ static GEN get_ro(long N, GEN rr, PERM S1, PERM S2, resolv *R) { GEN r = cgetg(N+1, t_VEC); long i; for (i=1; i<=N; i++) r[i] = rr[ S1[S2[i] ] ]; return R->a? gpolynomial(r, R): gpoly(r,R->nm,R->nv); } /* typ(z) = t_REAL, return zi = t_INT approximation */ static long sufprec_r(GEN z) { long p = bit_prec(z); /* bit accuracy of fractional part large enough ? */ return ( p - expo(z) > maxss(3*32, (long)0.2*p) ); } /* typ(z) = t_REAL or t_COMPLEX, return zi = t_INT approximation */ static long sufprec(GEN z) { if (typ(z) == t_REAL) return sufprec_r(z); else return sufprec_r(gel(z,2)) && sufprec_r(gel(z,1)); } static GEN get_ro_perm(PERM S1, PERM S2, long d, resolv *R, buildroot *BR) { GEN ro, roi; long e; for (;;) { ro = get_ro(BR->N, gel(BR->r, d), S1,S2,R); roi = grndtoi(ro, &e); if (e < 0) { if (e < -64 || sufprec(ro)) break; e = 0; } BR->pr += nbits2extraprec(e + 10); moreprec(BR); } if (e > -10 || typ(roi) == t_COMPLEX) return NULL; /* compute with 128 more bits */ BR->pr += MEDDEFAULTPREC; moreprec(BR); ro = get_ro(BR->N, gel(BR->r, d), S1,S2,R); BR->pr -= MEDDEFAULTPREC; 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]); } #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; 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++, set_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); set_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++, set_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) { set_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]]); } } set_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); return gc_long(av, res? (EVEN? 49: 50): 0); } /* 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); set_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); return gc_long(av, res? (EVEN? 44:45): 0); } /* 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 = veclast(compositum(h, h)); if (degpol(r) == 22) return 2; /* D11 */ h = leafcopy(h); setvarn(h, fetch_var()); setvarn(r, 0); r = nffactor(h, r); /* S11 (P10*P10*P90) or F_110[11] (11 factors of degree 10) */ (void)delete_var(); return (lgcols(r)-1 == 11)? 4: 8; } } 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); return gc_long(av, res? (EVEN? 7: 8): 0); } 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); 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); } for (i = 1; i < l; i++) { GEN p1 = gel(BR->r,i); for (j=1; j<=N; j++) gel(z,j) = gel(p1,s0[j]); for (j=1; j<=N; j++) gel(p1,j) = gel(z,j); } return gc_long(av, n2); } if (DEBUGLEVEL) err_printf(" Output of isin_%ld_G_H(%ld,%ld): not included.\n",N,n1,n2); return gc_long(av, 0); } static GEN polgaloisnamesbig(long n, long k) { pari_sp av = avma; pariFILE *f; GEN V; char *s = stack_sprintf("%s/galdata/NAM%ld", pari_datadir, n); f = pari_fopengz(s); V = f? gp_read_stream(f->file): NULL; if (!V || typ(V)!=t_VEC || k>=lg(V)) pari_err_FILE("galois file %s",s); pari_fclose(f); return gerepilecopy(av, gel(V,k)); } /* pol a monic ZX */ static 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"); } 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; /* LCOV_EXCL_LINE */ } if (!t) { buildroot BR; long i; GEN r, z = cgetg(N + 1, t_VEC); for (i = 1; i <= N; i++) { GEN v = cgetg(i+2,t_VECSMALL); gel(z,i) = v; v[1] = 0; } BR.coef = z; BR.p = pol; BR.pr = prec + nbits2extraprec((long)fujiwara_bound(pol)); BR.prmax = BR.pr + BIGDEFAULTPREC; BR.N = N; BR.r = vectrunc_init(N+1); r = gclone ( QX_complex_roots(BR.p, BR.prmax) ); vectrunc_append(BR.r, r); preci(r, BR.pr); switch(N) { case 8: t = closure8(EVEN, &BR); break; case 9: t = closure9(EVEN, &BR); break; case 10: t = closure10(EVEN, &BR); break; case 11: t = closure11(EVEN, &BR); break; } for (i = 1; i < lg(BR.r); i++) gunclone(gel(BR.r,i)); } set_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; } /**************************************************************/ /* Galois group for degree <= 7 */ /**************************************************************/ /* 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; } /* 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) { GEN z = cgetg(5,t_VEC); long kk; if (new_galois_format) kk = k; else kk = (d == 6 && (k==6 || k==2))? 2: 1; gel(z,1) = stoi(n); gel(z,2) = stoi(s); gel(z,3) = stoi(kk); gel(z,4) = polgaloisnames(d,k); return z; } GEN polgalois(GEN x, long prec) { pari_sp av = avma, av1; long i,j,k,n,f,l,l2,e,e1,pr,ind; GEN x1,p1,p2,p3,p4,p5,w,z,ee; const int ind5[20]={2,5,3,4, 1,3,4,5, 1,5,2,4, 1,2,3,5, 1,4,2,3}; const int ind6[60]={3,5,4,6, 2,6,4,5, 2,3,5,6, 2,4,3,6, 2,5,3,4, 1,4,5,6, 1,5,3,6, 1,6,3,4, 1,3,4,5, 1,6,2,5, 1,2,4,6, 1,5,2,4, 1,3,2,6, 1,2,3,5, 1,4,2,3}; if (typ(x)!=t_POL) pari_err_TYPE("galois",x); n=degpol(x); if (n>11) pari_err_IMPL("galois of degree higher than 11"); x = Q_primpart(x); RgX_check_ZX(x, "galois"); if (!ZX_is_irred(x)) pari_err_IRREDPOL("galois",x); if (n<4) { if (n == 1) { set_avma(av); return galois_res(n,1, 1,1); } if (n == 2) { set_avma(av); return galois_res(n,2,-1,1); } /* n = 3 */ f = Z_issquare(ZX_disc(x)); set_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 fb = fujiwara_bound(x); switch(n) { case 4: z = cgetg(7,t_VEC); prec = nbits2prec((long)(fb*18.) + 64); for(;;) { p1=QX_complex_roots(x,prec); gel(z,1) = F4(p1); gel(z,2) = F4(transroot(p1,1,2)); gel(z,3) = F4(transroot(p1,1,3)); gel(z,4) = F4(transroot(p1,1,4)); gel(z,5) = F4(transroot(p1,2,3)); gel(z,6) = F4(transroot(p1,3,4)); p5 = roots_to_ZX(z, &e); if (e <= -10) break; prec = precdbl(prec); } if (!ZX_is_squarefree(p5)) goto tchi; p2 = gel(ZX_factor(p5),1); switch(lg(p2)-1) { case 1: f = Z_issquare(ZX_disc(x)); set_avma(av); return f? galois_res(n,12,1,4): galois_res(n,24,-1,5); case 2: set_avma(av); return galois_res(n,8,-1,3); case 3: set_avma(av); return (degpol(gel(p2,1))==2)? galois_res(n,4,1,2) : galois_res(n,4,-1,1); default: pari_err_BUG("galois (bug1)"); } case 5: z = cgetg(7,t_VEC); ee= cgetg(7,t_VECSMALL); w = cgetg(7,t_VECSMALL); prec = nbits2prec((long)(fb*21.) + 64); for(;;) { for(;;) { p1=QX_complex_roots(x,prec); for (l=1; l<=6; l++) { p2=(l==1)?p1: ((l<6)?transroot(p1,1,l): transroot(p1,2,5)); p3=gen_0; for (k=0,i=1; i<=5; i++,k+=4) { p5 = gadd(gmul(gel(p2,ind5[k]),gel(p2,ind5[k+1])), gmul(gel(p2,ind5[k+2]),gel(p2,ind5[k+3]))); p3 = gadd(p3, gmul(gsqr(gel(p2,i)),p5)); } gel(w,l) = grndtoi(real_i(p3),&e); e1 = gexpo(imag_i(p3)); if (e1>e) e=e1; ee[l]=e; gel(z,l) = p3; } p5 = roots_to_ZX(z, &e); if (e <= -10) break; prec = precdbl(prec); } if (!ZX_is_squarefree(p5)) goto tchi; p3=gel(ZX_factor(p5),1); f=Z_issquare(ZX_disc(x)); if (lg(p3)-1==1) { set_avma(av); return f? galois_res(n,60,1,4): galois_res(n,120,-1,5); } if (!f) { set_avma(av); return galois_res(n,20,-1,3); } pr = - (prec >> 1); for (l=1; l<=6; l++) if (ee[l] <= pr && gequal0(poleval(p5,gel(w,l)))) break; if (l>6) pari_err_BUG("galois (bug4)"); p2=(l==6)? transroot(p1,2,5):transroot(p1,1,l); p3=gen_0; for (i=1; i<=5; i++) { j = (i == 5)? 1: i+1; p3 = gadd(p3,gmul(gmul(gel(p2,i),gel(p2,j)), gsub(gel(p2,j),gel(p2,i)))); } p5=gsqr(p3); p4=grndtoi(real_i(p5),&e); e1 = gexpo(imag_i(p5)); if (e1>e) e=e1; if (e <= -10) { if (gequal0(p4)) goto tchi; f = Z_issquare(p4); set_avma(av); return f? galois_res(n,5,1,1): galois_res(n,10,1,2); } prec = precdbl(prec); } case 6: z = cgetg(7, t_VEC); prec = nbits2prec((long) (fb * 42) + 64); for(;;) { for(;;) { p1=QX_complex_roots(x,prec); for (l=1; l<=6; l++) { p2=(l==1)?p1:transroot(p1,1,l); p3=gen_0; k=0; for (i=1; i<=5; i++) for (j=i+1; j<=6; j++) { p5=gadd(gmul(gel(p2,ind6[k]),gel(p2,ind6[k+1])), gmul(gel(p2,ind6[k+2]),gel(p2,ind6[k+3]))); p3=gadd(p3,gmul(gsqr(gmul(gel(p2,i),gel(p2,j))),p5)); k += 4; } gel(z,l) = p3; } p5 = roots_to_ZX(z, &e); if (e <= -10) break; prec = precdbl(prec); } if (!ZX_is_squarefree(p5)) goto tchi; p2=gel(ZX_factor(p5),1); switch(lg(p2)-1) { case 1: z = cgetg(11,t_VEC); ind=0; p3=gadd(gmul(gmul(gel(p1,1),gel(p1,2)),gel(p1,3)), gmul(gmul(gel(p1,4),gel(p1,5)),gel(p1,6))); gel(z,++ind) = p3; for (i=1; i<=3; i++) for (j=4; j<=6; j++) { p2=transroot(p1,i,j); p3=gadd(gmul(gmul(gel(p2,1),gel(p2,2)),gel(p2,3)), gmul(gmul(gel(p2,4),gel(p2,5)),gel(p2,6))); gel(z,++ind) = p3; } p5 = roots_to_ZX(z, &e); if (e <= -10) { if (!ZX_is_squarefree(p5)) goto tchi; p2 = gel(ZX_factor(p5),1); f = Z_issquare(ZX_disc(x)); set_avma(av); if (lg(p2)-1==1) return f? galois_res(n,360,1,15): galois_res(n,720,-1,16); else return f? galois_res(n,36,1,10): galois_res(n,72,-1,13); } prec = precdbl(prec); break; case 2: l2=degpol(gel(p2,1)); if (l2>3) l2=6-l2; switch(l2) { case 1: f = Z_issquare(ZX_disc(x)); set_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) { set_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)); set_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))); set_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)); set_avma(av); return f? galois_res(n,6,-1,1): galois_res(n,12,-1,3); } else { f = Z_issquare(ZX_disc(x)); set_avma(av); return f? galois_res(n,12,1,4): galois_res(n,24,-1,8); } case 4: set_avma(av); return galois_res(n,6,-1,2); default: pari_err_BUG("galois (bug3)"); } } case 7: z = cgetg(36,t_VEC); prec = nbits2prec((long)(fb*7.) + 64); for(;;) { ind = 0; p1=QX_complex_roots(x,prec); for (i=1; i<=5; i++) for (j=i+1; j<=6; j++) { GEN t = gadd(gel(p1,i),gel(p1,j)); for (k=j+1; k<=7; k++) gel(z,++ind) = gadd(t, gel(p1,k)); } p5 = roots_to_ZX(z, &e); if (e <= -10) break; prec = precdbl(prec); } if (!ZX_is_squarefree(p5)) goto tchi; p2=gel(ZX_factor(p5),1); switch(lg(p2)-1) { case 1: f = Z_issquare(ZX_disc(x)); set_avma(av); return f? galois_res(n,2520,1,6): galois_res(n,5040,-1,7); case 2: f = degpol(gel(p2,1)); set_avma(av); return (f==7 || f==28)? galois_res(n,168,1,5): galois_res(n,42,-1,4); case 3: set_avma(av); return galois_res(n,21,1,3); case 4: set_avma(av); return galois_res(n,14,-1,2); case 5: set_avma(av); return galois_res(n,7,1,1); default: pari_err_BUG("galois (bug2)"); } } tchi: set_avma(av1); x = tschirnhaus(x1); } } pari-2.17.2/src/modules/galpol.c0000644000175000017500000000635514567450071015067 0ustar billbill/* Copyright (C) 2000-2018 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" GEN galoisnbpol(long a) { GEN n; pariFILE *F; char *s = stack_sprintf("%s/galpol/%ld/nb", pari_datadir, a); F = pari_fopengz(s); if (!F) pari_err_FILE("galpol file",s); n = gp_read_stream(F->file); if (!n || typ(n)!=t_INT) pari_err_FILE("galpol file [incompatible]",s); pari_fclose(F); return n; } GEN galoisgetpol(long a, long b, long sig) { pariFILE *F; GEN V; const char *si; char *s; if (a<=0) pari_err_DOMAIN("galoisgetpol", "degree", "<=", gen_0, stoi(a)); if (b<0) pari_err_DOMAIN("galoisgetpol", "index", "<", gen_0, stoi(b)); if (!b) return galoisnbpol(a); switch(sig) { case 1: si="real"; break; case 2: if (a%2==0) { si="complex"; break; } pari_err_DOMAIN("galoisgetpol", "s", ">", gen_1, stoi(sig)); default: pari_err_FLAG("galoisgetpol"); return NULL;/*LCOV_EXCL_LINE*/ } /* left on stack */ s = stack_sprintf("%s/galpol/%ld/%ld/%s", pari_datadir, a,b,si); F = pari_fopengz(s); if (!F) { long n = itos(galoisnbpol(a)); if (b > n) pari_err_DOMAIN("galoisgetpol", "group index", ">", stoi(n), stoi(b)); else pari_err_FILE("galpol file", s); } V = gp_read_stream(F->file); if (!V || typ(V)!=t_VEC) pari_err_FILE("galpol file", F->name); pari_fclose(F); return V; } GEN galoisgetgroup(long a, long b) { pariFILE *F; GEN V; char *s; if (a<=0) pari_err_DOMAIN("galoisgetgroup", "degree", "<=", gen_0, stoi(a)); if (b<0) pari_err_DOMAIN("galoisgetgroup", "index", "<", gen_0, stoi(b)); if (!b) return galoisnbpol(a); /* left on stack */ s = stack_sprintf("%s/galpol/%ld/%ld/group", pari_datadir, a,b); F = pari_fopengz(s); if (!F) { long n = itos(galoisnbpol(a)); if (b > n) pari_err_DOMAIN("galoisgetgroup", "group index", ">", stoi(n), stoi(b)); else pari_err_FILE("galpol file", s); } V = gp_read_stream(F->file); if (!V || typ(V)!=t_VEC) pari_err_FILE("galpol file", F->name); pari_fclose(F); return V; } GEN galoisgetname(long a, long b) { pariFILE *F; GEN V; char *s; if (a<=0) pari_err_DOMAIN("galoisgetname", "degree", "<=", gen_0, stoi(a)); if (b<0) pari_err_DOMAIN("galoisgetname", "index", "<", gen_0, stoi(b)); /* left on stack */ s = stack_sprintf("%s/galpol/%ld/%ld/name", pari_datadir, a,b); F = pari_fopengz(s); if (!F) { long n = itos(galoisnbpol(a)); if (b > n) pari_err_DOMAIN("galoisgetname", "group index", ">", stoi(n), stoi(b)); else pari_err_FILE("galpol file", s); } V = gp_read_stream(F->file); if (!V || typ(V)!=t_STR) pari_err_FILE("galpol file", F->name); pari_fclose(F); return V; } pari-2.17.2/src/modules/ratpoints.c0000644000175000017500000016060714676526175015647 0ustar billbill/* Copyright (C) 2017 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* This file is based on ratpoints-2.2.1 by Michael Stoll, see * http://www.mathe2.uni-bayreuth.de/stoll/programs/ * Original copyright / license: */ /*********************************************************************** * ratpoints-2.2.1 * * Copyright (C) 2008, 2009, 2022 Michael Stoll * * - A program to find rational points on hyperelliptic curves * * * * 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. * ***********************************************************************/ #include "paricfg.h" #ifdef HAS_AVX #include #elif defined(HAS_SSE2) #include #endif #include "pari.h" #include "paripriv.h" #define pel(a,b) gel((a),(b)+2) #define RATPOINTS_ARRAY_SIZE 256 /* Array size in longs */ #define RATPOINTS_DEFAULT_SP1 11 /* Default value for sp1 */ #define RATPOINTS_DEFAULT_SP2 19 /* Default value for sp2 */ #define RATPOINTS_DEFAULT_NUM_PRIMES 30 /* Default value for num_primes */ #define RATPOINTS_DEFAULT_BIT_PRIMES 7 /* Default value for bit_primes */ #define RATPOINTS_DEFAULT_MAX_FORBIDDEN 30 /* Default value for max_forbidden */ typedef struct {double low; double up;} ratpoints_interval; /* Define the flag bits for the flags component: */ #define RATPOINTS_NO_REVERSE 0x0004UL #define RATPOINTS_FLAGS_INPUT_MASK (RATPOINTS_NO_REVERSE) /* Flags bits for internal purposes */ #define RATPOINTS_REVERSED 0x0100UL #define RATPOINTS_CHECK_DENOM 0x0200UL #define RATPOINTS_USE_SQUARES 0x0400UL #define RATPOINTS_USE_SQUARES1 0x0800UL #define LONG_MASK (~(-(1UL<>TWOPOTBITS_IN_LONG, rsh = sh & (BITS_IN_LONG-1); \ for(l = 0; l < qsh; l++) { *survl++ = 0UL; }; *survl &= (~0UL)<>TWOPOTBITS_IN_LONG), rsh = sh & (BITS_IN_LONG-1); \ survl += qsh; *survl++ &= (~0UL)>>rsh; \ for(l = qsh+1; l < RBA_PACK; l++) { *survl++ = 0UL; } } #elif defined(HAS_AVX) /* Use AVX 256 bit registers for the bit arrays */ typedef ulong ratpoints_bit_array __attribute__ ((vector_size (32))); #define EXT0(a) ((ulong)a[0]) #define EXT(a,i) ((ulong)a[i]) #ifdef __AVX2__ #define TEST(a) ( _mm256_movemask_epi8(_mm256_cmpeq_epi8((__m256i)(a), (__m256i)RBA(0))) != 0xffffffffL ) #elif defined(__AVX__) #define TEST(a) ( !_mm256_testz_si256((__m256i)(a), (__m256i)(a)) ) #else #define TEST(a) (EXT(a,0) || EXT(a,1) || EXT(a,2) || EXT(a,3)) #endif #define RBA(a) ((ratpoints_bit_array){((ulong) a), ((ulong) a), ((ulong) a), ((ulong) a)}) #define RBA_SHIFT (8) #define MASKL(a,s) { unsigned long *survl = (unsigned long *)(a); long sh = (s); \ if(sh >= 2*BITS_IN_LONG) \ { sh -= 2*BITS_IN_LONG; survl[0] = 0UL; survl[1] = 0UL; \ if(sh >= BITS_IN_LONG) \ { survl[2] = 0UL; survl[3] &= (~0UL)<<(sh - BITS_IN_LONG); } \ else { survl[2] &= ~(0UL)<= BITS_IN_LONG) { survl[0] = 0UL; survl[1] &= (~0UL)<<(sh - BITS_IN_LONG); } \ else { survl[0] &= ~(0UL)<= 2*BITS_IN_LONG) \ { sh -= 2*BITS_IN_LONG; survl[3] = 0UL; survl[2] = 0UL; \ if(sh >= BITS_IN_LONG) \ { survl[0] &= ~(0UL)>>(sh - BITS_IN_LONG); survl[1] = 0UL; } \ else { survl[1] &= ~(0UL)>>sh; } } \ else if(sh >= BITS_IN_LONG) { survl[2] &= ~(0UL)>>(sh - BITS_IN_LONG); survl[3] = 0UL; } \ else { survl[3] &= ~(0UL)>>sh; } } #elif defined(HAS_SSE2) || defined(HAS_NEON) #ifdef HAS_SSE2 /* Use SSE 128 bit registers for the bit arrays */ typedef __v2di ratpoints_bit_array; #define EXT0(a) ((ulong)__builtin_ia32_vec_ext_v2di((__v2di)(a), 0)) #define EXT(a,i) ((ulong)__builtin_ia32_vec_ext_v2di((__v2di)(a), 1)) #else typedef ulong ratpoints_bit_array __attribute__ ((vector_size (16))); #define EXT0(a) ((ulong)a[0]) #define EXT(a,i) ((ulong)a[i]) #endif #define TEST(a) (EXT0(a) || EXT(a,1)) #define RBA(a) ((ratpoints_bit_array){((long) a), ((long) a)}) #define RBA_SHIFT (7) #define MASKL(a,s) { unsigned long *survl = (unsigned long *)(a); long sh = (s); \ if(sh >= BITS_IN_LONG) { survl[0] = 0UL; survl[1] &= (~0UL)<<(sh - BITS_IN_LONG); } \ else { survl[0] &= ~(0UL)<= BITS_IN_LONG) { survl[0] &= ~(0UL)>>(sh - BITS_IN_LONG); survl[1] = 0UL; } \ else { survl[1] &= ~(0UL)>>sh; } } #else /* Use ulong for the bit arrays */ typedef ulong ratpoints_bit_array; #define EXT0(a) (a) #define TEST(a) (a) #define RBA(a) (a) #define RBA_SHIFT TWOPOTBITS_IN_LONG #define MASKL(a,s) { *(a) &= ~(0UL)<<(s); } #define MASKU(a,s) { *(a) &= ~(0UL)>>(s); } #undef RBA_USE_VX #endif #define RBA_SIZE (sizeof(ratpoints_bit_array)) #define RBA_LENGTH (RBA_SIZE<<3) #define RBA_PACK (RBA_LENGTH>>TWOPOTBITS_IN_LONG) #ifdef RBA_USE_VX #define RATPOINTS_CHUNK 16 #define CODE_INIT_SIEVE_COPY \ { ulong k; \ for (a = 0; a < p; a++) \ for(k = 1; k < RBA_PACK; k++) \ si[a+k*p] = si[a]; \ for(a = 0; (ulong)a < (RATPOINTS_CHUNK-1)*RBA_PACK; a++) \ si[a+p*RBA_PACK] = si[a];\ } #else #define RATPOINTS_CHUNK 1 #define CODE_INIT_SIEVE_COPY #endif typedef struct { long p; long offset; ratpoints_bit_array *ptr; ratpoints_bit_array *start; ratpoints_bit_array *end; } sieve_spec; typedef enum { num_all, num_even, num_odd, num_none } bit_selection; typedef struct { long p; int *is_f_square; const long *inverses; long offset; ratpoints_bit_array** sieve; } ratpoints_sieve_entry; typedef struct { long p; ulong *start; ulong *end; ulong *curr; } forbidden_entry; typedef struct { GEN cof, listprime; ratpoints_interval *domain; long height, b_low, b_high, sp1, sp2, array_size; long num_inter, num_primes, bit_primes, max_forbidden; ulong flags; /* from here: private data */ GEN bc; ratpoints_sieve_entry *se_buffer; ratpoints_sieve_entry *se_next; ratpoints_bit_array *ba_buffer; ratpoints_bit_array *ba_next; int *int_buffer, *int_next; forbidden_entry *forb_ba; long *forbidden; GEN inverses, offsets, den_info, divisors; ulong **sieves0; } ratpoints_args; static ratpoints_bit_array * sieve_init1(long p, ratpoints_sieve_entry *se1, long b1, ratpoints_args *args1) { ratpoints_sieve_entry *se = se1; ratpoints_args *args = args1; int *isfs = se->is_f_square; long b = b1; long lmp = BITS_IN_LONG % p; long ldp = BITS_IN_LONG / p; long p1 = (ldp + 1) * p; long diff_shift = p1 & LONG_MASK; long diff = BITS_IN_LONG - diff_shift; ulong help0; long a; long d = se->inverses[b]; long ab = 0; /* a/b mod p */ ulong test = 1UL; ulong he0 = 0UL; for (a = 0; a < p; a++) { if (isfs[ab]) he0 |= test; ab += d; if (ab >= p) ab -= p; test <<= 1; } help0 = he0; { ulong help1; /* repeat bit pattern floor(BITS_IN_LONG/p) times */ ulong pattern = help0; long i; /* the p * (floor(BITS_IN_LONG/p) + 1) - BITS_IN_LONG = p - (BITS_IN_LONG mod p) upper bits into help[b][1] : shift away the BITS_IN_LONG mod p lower bits */ help1 = pattern >> lmp; for (i = p; i < BITS_IN_LONG; i <<= 1) help0 |= help0 << i; { /* fill the bit pattern from help0/help1 into sieve[b][]. sieve[b][a0] has the same semantics as help0/help1, but here, a0 runs from 0 to p-1 and all bits are filled. */ long a; ulong *si = (ulong *)args->ba_next; args->ba_next += p + RATPOINTS_CHUNK-1; /* copy the first chunk into sieve[b][] */ si[0] = help0; /* now keep repeating the bit pattern, rotating it in help0/help1 */ for (a = 1 ; a < p; a++) { ulong temp = help0 >> diff; help0 = help1 | (help0 << diff_shift); si[a] = help0; help1 = temp; } CODE_INIT_SIEVE_COPY /* set sieve array */ se->sieve[b] = (ratpoints_bit_array *)si; return (ratpoints_bit_array *)si; } } } /* This is for p > BITS_IN_LONG */ static ratpoints_bit_array * sieve_init2(long p, ratpoints_sieve_entry *se1, long b1, ratpoints_args *args1) { pari_sp av = avma; ratpoints_sieve_entry *se = se1; ratpoints_args *args = args1; int *isfs = se->is_f_square; long b = b1; /* long ldp = 0; = BITS_IN_LONG / p */ /* long p1 = p; = (ldp + 1) * p; */ long wp = p >> TWOPOTBITS_IN_LONG; long diff_shift = p & LONG_MASK; long diff = BITS_IN_LONG - diff_shift; ulong *help = (ulong *) new_chunk((p>>TWOPOTBITS_IN_LONG) + 2); /* initialize help */ { ulong *he = &help[0]; ulong *he1 = &he[(p>>TWOPOTBITS_IN_LONG) + 2]; while (he1 != he) { he1--; *he1 = 0UL; } } { ulong work = 0UL; long a; long ab = 0; /* a/b mod p */ long d = se->inverses[b]; long n = 0; ulong test = 1UL; for (a = 0; a < p; ) { if (isfs[ab]) work |= test; ab += d; if (ab >= p) ab -= p; test <<= 1; a++; if ((a & LONG_MASK) == 0) { help[n] = work; n++; work = 0UL; test = 1UL; } } help[n] = work; } { /* fill the bit pattern from help[] into sieve[b][]. sieve[b][a0] has the same semantics as help[b][a0], but here, a0 runs from 0 to p-1 and all bits are filled. */ ulong *si = (ulong *)args->ba_next; long a1; long a; args->ba_next += p + RATPOINTS_CHUNK-1; /* copy the first chunk from help[] into sieve[num][b][] */ for (a = 0; a < wp; a++) si[a] = help[a]; /* now keep repeating the bit pattern, rotating it in help */ for (a1 = a ; a < p; a++) { long t = (a1 == wp) ? 0 : a1+1; help[a1] |= help[t]<>= diff; } CODE_INIT_SIEVE_COPY /* set sieve array */ se->sieve[b] = (ratpoints_bit_array *)si; set_avma(av); return (ratpoints_bit_array *)si; } } static GEN gen_squares(GEN listprime) { long nbprime = lg(listprime)-1; GEN sq = cgetg(nbprime+1, t_VEC); long n; for (n = 1; n <= nbprime; n++) { ulong i, p = uel(listprime,n); GEN w = zero_zv(p), work = w+1; work[0] = 1; /* record nonzero squares mod p, p odd */ for (i = 1; i < p; i += 2) work[(i*i) % p] = 1; gel(sq, n) = w; } return sq; } static GEN gen_offsets(GEN P) { long n, l = lg(P); GEN of = cgetg(l, t_VEC); for (n = 1; n < l; n++) { ulong p = uel(P,n); uel(of, n) = Fl_inv((2*RBA_LENGTH)%p, p); } return of; } static GEN gen_inverses(GEN P) { long n, l = lg(P); GEN iv = cgetg(l, t_VEC); for (n = 1; n < l; n++) { ulong i, p = uel(P,n); GEN w = cgetg(p, t_VECSMALL); for (i = 1; i < p; i++) uel(w, i) = Fl_inv(i, p); gel(iv, n) = w; } return iv; } static ulong ** gen_sieves0(GEN listprime) { long n; long nbprime = lg(listprime)-1; ulong ** w = (ulong**) new_chunk(nbprime+1); for (n = 1; n <= nbprime; n++) { ulong a, p = uel(listprime,n); ulong *si = (ulong *) stack_malloc_align((p+RATPOINTS_CHUNK-1)*RBA_SIZE, RBA_SIZE); for (a = 0; a < p; a++) si[a] = ~0UL; for (a = 0; a < BITS_IN_LONG; a++) uel(si,(p*a)>>TWOPOTBITS_IN_LONG) &= ~(1UL<<((p*a) & LONG_MASK)); CODE_INIT_SIEVE_COPY w[n] = si; } return w; } static void gen_sieve(ratpoints_args *args) { GEN listprimes = args->listprime; args->offsets = gen_offsets(listprimes); args->inverses = gen_inverses(listprimes); args->sieves0 = gen_sieves0(listprimes); } static GEN ZX_positive_region(GEN P, long h, long bitprec) { long prec = nbits2prec(bitprec); GEN it = mkvec2(stoi(-h),stoi(h)); GEN R = realroots(P, it, prec); long nR = lg(R)-1; long s = signe(ZX_Z_eval(P,gel(it,1))); long i=1, j; GEN iv, st, en; if (s<0 && nR==0) return NULL; iv = cgetg(((nR+1+(s>=0))>>1)+1, t_VEC); if (s>=0) st = itor(gel(it,1),prec); else { st = gel(R,i); i++; } for (j=1; idomain; args->num_inter = posint(ivlist, args->cof, (long) ivlist[0].up); return args->num_inter; } /************************************************************************** * Try to avoid divisions * **************************************************************************/ INLINE long mod(long a, long b) { long b1 = b << 4; /* b1 = 16*b */ if (a < -b1) { a %= b; if (a < 0) { a += b; } return a ; } if (a < 0) { a += b1; } else { if (a >= b1) { return a % b; } } b1 >>= 1; /* b1 = 8*b */ if (a >= b1) { a -= b1; } b1 >>= 1; /* b1 = 4*b */ if (a >= b1) { a -= b1; } b1 >>= 1; /* b1 = 2*b */ if (a >= b1) { a -= b1; } if (a >= b) { a -= b; } return a; } static void set_bc(long b, ratpoints_args *args) { GEN w0 = gen_1; GEN c = args->cof, bc; long k, degree = degpol(c); bc = cgetg(degree+2, t_POL); for (k = degree-1; k >= 0; k--) { w0 = muliu(w0, b); gel(bc,k+2) = mulii(gel(c,k+2), w0); } args->bc = bc; } /************************************************************************** * Check a `survivor' of the sieve if it really gives a point. * **************************************************************************/ static long _ratpoints_check_point(long a, long b, ratpoints_args *args, int *quit, int process(long, long, GEN, void*, int*), void *info) { pari_sp av = avma; GEN w0, w2, c = args->cof, bc = args->bc; long k, degree = degpol(c); int reverse = args->flags & RATPOINTS_REVERSED; /* Compute F(a, b), where F is the homogenized version of f of smallest possible even degree */ w2 = gel(c, degree+2); for (k = degree-1; k >= 0; k--) { w2 = mulis(w2, a); w2 = addii(w2, gel(bc,k+2)); } if (odd(degree)) w2 = muliu(w2, b); /* check if f(x,z) is a square; if so, process the point(s) */ if (signe(w2) >= 0 && Z_issquareall(w2, &w0)) { if (reverse) { if (a >= 0) (void)process(b, a, w0, info, quit); else (void)process(-b, -a, w0, info, quit); } else (void)process(a, b, w0, info, quit); if (!*quit && signe(w0) != 0) { GEN nw0 = negi(w0); if (reverse) { if (a >= 0) (void)process(b, a, nw0, info, quit); else (void)process(-b, -a, nw0, info, quit); } else (void)process(a, b, nw0, info, quit); } return 1; } set_avma(av); return 0; } /************************************************************************** * The inner loop of the sieving procedure * **************************************************************************/ static long _ratpoints_sift0(long b, long w_low, long w_high, ratpoints_args *args, bit_selection which_bits, ratpoints_bit_array *survivors, sieve_spec *sieves, int *quit, int process(long, long, GEN, void*, int*), void *info) { long sp1 = args->sp1, sp2 = args->sp2; long i, n, nb = 0, absb = labs(b), base = 0; ratpoints_bit_array *surv0; /* now do the sieving (fast!) */ #if (RATPOINTS_CHUNK == 16) long w_low_new; ratpoints_bit_array *surv = survivors; /* first set the start fields for the first and second phases of sieving */ for(n = 0; n < sp2; n++) sieves[n].start = sieves[n].ptr + mod(w_low + sieves[n].offset, sieves[n].p); /* Take RATPOINTS_CHUNK bit-arrays and apply phase 1 to them, * then repeat with the next RATPOINTS_CHUNK bit-arrays. */ for(w_low_new = w_low; w_low_new < w_high; surv += RATPOINTS_CHUNK, w_low_new += RATPOINTS_CHUNK) { /* read data from memory into registers */ ratpoints_bit_array reg0 = surv[0]; ratpoints_bit_array reg1 = surv[1]; ratpoints_bit_array reg2 = surv[2]; ratpoints_bit_array reg3 = surv[3]; ratpoints_bit_array reg4 = surv[4]; ratpoints_bit_array reg5 = surv[5]; ratpoints_bit_array reg6 = surv[6]; ratpoints_bit_array reg7 = surv[7]; ratpoints_bit_array reg8 = surv[8]; ratpoints_bit_array reg9 = surv[9]; ratpoints_bit_array reg10 = surv[10]; ratpoints_bit_array reg11 = surv[11]; ratpoints_bit_array reg12 = surv[12]; ratpoints_bit_array reg13 = surv[13]; ratpoints_bit_array reg14 = surv[14]; ratpoints_bit_array reg15 = surv[15]; for(n = 0; n < sp1; n++) { /* retrieve the pointer to the beginning of the relevant bits */ ratpoints_bit_array *siv1 = sieves[n].start; reg0 &= *siv1++; reg1 &= *siv1++; reg2 &= *siv1++; reg3 &= *siv1++; reg4 &= *siv1++; reg5 &= *siv1++; reg6 &= *siv1++; reg7 &= *siv1++; reg8 &= *siv1++; reg9 &= *siv1++; reg10 &= *siv1++; reg11 &= *siv1++; reg12 &= *siv1++; reg13 &= *siv1++; reg14 &= *siv1++; reg15 &= *siv1++; /* update the pointer for the next round * (RATPOINTS_CHUNK-1 bit-arrays after sieves[n].end) */ while(siv1 >= sieves[n].end) siv1 -= sieves[n].p; sieves[n].start = siv1; } /* store the contents of the registers back into memory */ surv[0] = reg0; surv[1] = reg1; surv[2] = reg2; surv[3] = reg3; surv[4] = reg4; surv[5] = reg5; surv[6] = reg6; surv[7] = reg7; surv[8] = reg8; surv[9] = reg9; surv[10] = reg10; surv[11] = reg11; surv[12] = reg12; surv[13] = reg13; surv[14] = reg14; surv[15] = reg15; } #else /* RATPOINTS_CHUNK not between 2 and 16 */ long range = w_high - w_low; for (n = 0; n < sp1; n++) { ratpoints_bit_array *sieve_n = sieves[n].ptr; long p = sieves[n].p; long r = mod(-w_low-sieves[n].offset, p); ratpoints_bit_array *surv = survivors; if (w_high < w_low + r) { /* if we get here, r > 0, since w_high >= w_low always */ ratpoints_bit_array *siv1 = &sieve_n[p-r]; ratpoints_bit_array *siv0 = siv1 + range; while (siv1 != siv0) { *surv &= *siv1++; surv++; } } else { ratpoints_bit_array *siv1 = &sieve_n[p-r]; ratpoints_bit_array *surv_end = &survivors[range - p]; long i; for (i = r; i; i--) { *surv &= *siv1++; surv++; } siv1 -= p; while (surv <= surv_end) { for (i = p; i; i--) { *surv &= *siv1++; surv++; } siv1 -= p; } surv_end += p; while (surv < surv_end) { *surv &= *siv1++; surv++; } } } /* initialize pointers in sieve for the second phase */ for(n = sp1; n < sp2; n++) sieves[n].start = sieves[n].ptr + mod(w_low + sieves[n].offset, sieves[n].p); #endif /* RATPOINTS_CHUNK */ /* 2nd phase of the sieve: test each surviving bit array with more primes */ surv0 = &survivors[0]; for (i = w_low; i < w_high; i++, base++) { ratpoints_bit_array nums = *surv0++; sieve_spec *ssp = &sieves[sp1]; long n; for (n = sp2-sp1; n && TEST(nums); n--) { ratpoints_bit_array *ptr = (ssp->start) + base; long p = ssp->p; while(ptr >= ssp->end) ptr -= p; nums &= *ptr; ssp++; } /* Check the survivors of the sieve if they really give points */ if (TEST(nums)) { long a0, a, d; ulong nums0 = EXT0(nums); /* a will be the numerator corresponding to the selected bit */ if (which_bits == num_all) { d = 1; a0 = i * RBA_LENGTH; } else { d = 2; a0 = i * 2 * RBA_LENGTH; if (which_bits == num_odd) a0++; } for (a = a0; nums0; a += d, nums0 >>= 1) { /* test one bit */ if (odd(nums0) && ugcd(labs(a), absb)==1) { if (!args->bc) set_bc(b, args); nb += _ratpoints_check_point(a, b, args, quit, process, info); if (*quit) return nb; } } #ifdef RBA_USE_VX { ulong k, da = d<>= 1) { /* test one bit */ if (odd(nums1) && ugcd(labs(a), absb)==1) { if (!args->bc) set_bc(b, args); nb += _ratpoints_check_point(a, b, args, quit, process, info); if (*quit) return nb; } } } } #endif } } return nb; } typedef struct { double r; ratpoints_sieve_entry *ssp; } entry; static const int squares16[16] = {1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0}; /* Says if a is a square mod 16, for a = 0..15 */ /************************************************************************** * Initialization and cleanup of ratpoints_args structure * **************************************************************************/ static ratpoints_sieve_entry* alloc_sieve(long nbprime, long maxp) { long i; ratpoints_sieve_entry * s = (ratpoints_sieve_entry*) stack_malloc(nbprime*sizeof(ratpoints_sieve_entry)); for (i=0; idegree must be set */ static void find_points_init(ratpoints_args *args, long bit_primes) { long need = 0, n, nbprime, maxp; args->listprime = primes_interval_zv(3, 1<listprime)-1; maxp = args->listprime[nbprime]; /* allocate space for se_buffer */ args->se_buffer = alloc_sieve(nbprime, maxp); args->se_next = args->se_buffer; for (n = 1; n <= nbprime; n++) { ulong p = args->listprime[n]; need += p*(p + RATPOINTS_CHUNK-1); } args->ba_buffer = (ratpoints_bit_array*) stack_malloc_align(need*RBA_SIZE,RBA_SIZE); args->ba_next = args->ba_buffer; /* allocate space for int_buffer */ args->int_buffer = (int *) stack_malloc(nbprime*(maxp+1)*sizeof(int)); args->int_next = args->int_buffer; args->forb_ba = (forbidden_entry*) stack_malloc((nbprime + 1)*sizeof(forbidden_entry)); args->forbidden = new_chunk(nbprime + 1); gen_sieve(args); return; } /* f = leading coeff; b = b1*b2, b1 maximal with (b1, 2*f) = 1; * return Jacobi symbol (f, b1) */ INLINE int rpjacobi(long b, GEN lcf) { ulong f; b >>= vals(b); f = umodiu(lcf, b); return krouu(f, u_ppo(b,f)); } /************************************************************************ * Set up information on possible denominators * * when polynomial is of odd degree with leading coefficient != +-1 * ************************************************************************/ static void setup_us1(ratpoints_args *args, GEN w0) { GEN F = Z_issmooth_fact(w0, 1000), P, E, S, D; long i, l; if (!F) return; P = gel(F,1); l = lg(P); E = gel(F,2); D = cgetg(1+(1<<(l-1)), t_VECSMALL); /* factorization is complete, set up array of squarefree divisors */ D[1] = 1; for (i = 1; i < l; i++) { /* multiply all divisors known so far by next prime */ long k, n = 1<<(i-1); for (k=0; k v_p(f_d) - v_p(f_k), k = 0,...,d-1} */ GEN c = args->cof; long p = P[i], v = E[i]; long k, n = 1, d = degpol(c); for (k = d - 1; k >= 0; k--) { long t = 1 + v - Z_lval(gel(c,k+2), p); long m = CEIL(t, d - k); if (m > n) n = m; } S[i] = n; } args->divisors = D; args->flags |= RATPOINTS_USE_SQUARES1; args->den_info = mkvec3(P, E, S); } /************************************************************************ * Consider 2-adic information * ************************************************************************/ static bit_selection get_2adic_info(ratpoints_args *args, ulong *den_bits, ratpoints_bit_array *num_bits) { GEN c = args->cof; long degree = degpol(c); int is_f_square16[24]; long *cmp = new_chunk(degree+1); long npe = 0, npo = 0; bit_selection result; long n, a, b; /* compute coefficients mod 16 */ for (n = 0; n <= degree; n++) cmp[n] = Mod16(gel(c,n+2)); for (a = 0 ; a < 16; a++) { ulong s = cmp[degree]; long n; for (n = degree - 1 ; n >= 0 ; n--) s = s*a + cmp[n]; s &= 0xf; if ((is_f_square16[a] = squares16[s])) { if (odd(a)) npo++; else npe++; } } /* even denominators: is_f_square16[16+k] says if f((2k+1)/2) is a square, k = 0..3 is_f_square16[20+k] says if f((2k+1)/4) is a square, k = 0,1 is_f_square16[22] says if f(odd/8) is a square is_f_square16[23] says if f(odd/2^n), n >= 4, can be a square */ { long np1 = 0, np2 = 0, np3 = 0, np4 = 0; if (odd(degree)) { long a, cf = 4*cmp[degree-1]; if (degree >= 2) cf += 8*cmp[degree-2]; for (a = 0; a < 4; a++) { /* Compute 2 c[d] k^d + 4 c[d-1] k^(d-1) + 8 c[d-2] k^(d-2), k = 2a+1. Note that k^d = k mod 8, k^(d-1) = 1 mod 8. */ long k = 2*a+1; long s = (2*k*cmp[degree] + cf) & 0xf; if ((is_f_square16[16+a] = squares16[s])) np1++; } if ((is_f_square16[20] = squares16[(4*cmp[degree]) & 0xf])) np2++; if ((is_f_square16[21] = squares16[(12*cmp[degree]) & 0xf])) np2++; if ((is_f_square16[22] = squares16[(8*cmp[degree]) & 0xf])) np3++; is_f_square16[23] = 1; np4++; } else { long a, cf = (degree >= 2) ? 4*cmp[degree-2] : 0; if (degree >= 3) cf += 8*cmp[degree-3]; for (a = 0; a < 4; a++) { /* compute c[d] k^d + 2 c[d-1] k^(d-1) + ... + 8 c[d-3] k^(d-3), k = 2a+1. Note that k^d = k^2 mod 16, k^(d-1) = k mod 8. */ long k = 2*a+1; long s = ((cmp[degree]*k + 2*cmp[degree-1])*k + cf) & 0xf; if ((is_f_square16[16+a] = squares16[s])) np1++; } if ((is_f_square16[20] = squares16[(cmp[degree]+4*cmp[degree-1]) & 0xf])) np2++; if ((is_f_square16[21] = squares16[(cmp[degree]+12*cmp[degree-1]) & 0xf])) np2++; if ((is_f_square16[22] = squares16[(cmp[degree]+8*cmp[degree-1]) & 0xf])) np3++; if ((is_f_square16[23] = squares16[cmp[degree]])) np4++; } /* set den_bits */ { ulong db = 0; long i; if (npe + npo > 0) db |= 0xaaaaUL; /* odd denominators */ if (np1 > 0) db |= 0x4444UL; /* v_2(den) = 1 */ if (np2 > 0) db |= 0x1010UL; /* v_2(den) = 2 */ if (np3 > 0) db |= 0x0100UL; /* v_2(den) = 3 */ if (np4 > 0) db |= 0x0001UL; /* v_2(den) >= 4 */ if (db == 0) { for (i = 0 ; i < 16; i++) num_bits[i] = RBA(0UL); *den_bits = 0UL; return num_none; } for (i = 16; i < BITS_IN_LONG; i <<= 1) db |= db << i; *den_bits = db; } result = (npe == 0) ? (npo == 0) ? num_none : num_odd : (npo == 0) ? num_even : num_all; } /* set up num_bits[16] */ /* odd denominators */ switch(result) { case num_all: for (b = 1; b < 16; b += 2) { ulong work = 0, bit = 1; long i, invb = b; /* inverse of b mod 16 */ if (b & 2) invb ^= 8; if (b & 4) invb ^= 8; for (i = 0; i < 16; i++) { if (is_f_square16[(invb*i) & 0xf]) work |= bit; bit <<= 1; } /* now repeat the 16 bits */ for (i = 16; i < BITS_IN_LONG; i <<= 1) work |= work << i; num_bits[b] = RBA(work); } break; case num_odd: for (b = 1; b < 16; b += 2) { ulong work = 0, bit = 1; long i, invb = b; /* inverse of b mod 16 */ if (b & 2) invb ^= 8; if (b & 4) invb ^= 8; for (i = 1; i < 16; i += 2) { if (is_f_square16[(invb*i) & 0xf]) work |= bit; bit <<= 1; } /* now repeat the 8 bits */ for (i = 8; i < BITS_IN_LONG; i <<= 1) { work |= work << i; } num_bits[b] = RBA(work); } break; case num_even: for (b = 1; b < 16; b += 2) { ulong work = 0, bit = 1; long i, invb = b; /* inverse of b mod 16 */ if (b & 2) invb ^= 8; if (b & 4) invb ^= 8; for (i = 0; i < 16; i += 2) { if (is_f_square16[(invb*i) & 0xf]) work |= bit; bit <<= 1; } /* now repeat the 8 bits */ for (i = 8; i < BITS_IN_LONG; i <<= 1) work |= work << i; num_bits[b] = RBA(work); } break; case num_none: for (b = 1; b < 16; b += 2) num_bits[b] = RBA(0UL); break; } /* v_2(den) = 1 : only odd numerators */ for (b = 1; b < 8; b += 2) { ulong work = 0, bit = 1; long i; for (i = 1; i < 16; i += 2) { if (is_f_square16[16 + (((b*i)>>1) & 0x3)]) work |= bit; bit <<= 1; } /* now repeat the 8 bits */ for (i = 8; i < BITS_IN_LONG; i <<= 1) work |= work << i; num_bits[2*b] = RBA(work); } /* v_2(den) = 2 : only odd numerators */ for (b = 1; b < 4; b += 2) { ulong work = 0, bit = 1; long i; for (i = 1; i < 8; i += 2) { if (is_f_square16[20 + (((b*i)>>1) & 0x1)]) work |= bit; bit <<= 1; } /* now repeat the 4 bits */ for (i = 4; i < BITS_IN_LONG; i <<= 1) work |= work << i; num_bits[4*b] = RBA(work); } /* v_2(den) = 3, >= 4 : only odd numerators */ num_bits[8] = (is_f_square16[22]) ? RBA(~(0UL)) : RBA(0UL); num_bits[0] = (is_f_square16[23]) ? RBA(~(0UL)) : RBA(0UL); return result; } /************************************************************************** * This is a comparison function needed for sorting in order to determine * * the `best' primes for sieving. * **************************************************************************/ static int compare_entries(const void *a, const void *b) { double diff = ((entry *)a)->r - ((entry *)b)->r; return (diff > 0) ? 1 : (diff < 0) ? -1 : 0; } /************************************************************************ * Collect the sieving information * ************************************************************************/ static long sieving_info(ratpoints_args *args, ratpoints_sieve_entry **sieve_list) { GEN c = args->cof; GEN inverses = args->inverses, squares; GEN offsets = args->offsets; ulong ** sieves0 = args->sieves0; long degree = degpol(c); long fba = 0, fdc = 0; long pn, pnp = 0; long n; long nbprime = lg(args->listprime)-1; long * coeffs_mod_p; entry *prec = (entry*) stack_malloc(nbprime*sizeof(entry)); /* This array is used for sorting in order to determine the `best' sieving primes. */ forbidden_entry *forb_ba = args->forb_ba; long *forbidden = args->forbidden; ulong bound = (1UL)<<(BITS_IN_LONG - args->bit_primes); pari_sp av = avma; squares = gen_squares(args->listprime); coeffs_mod_p = (long *) new_chunk(degree+1); /* initialize sieve in se_buffer */ for (pn = 1; pn <= args->num_primes; pn++) { ulong a, p = args->listprime[pn], np; long n; int *is_f_square = args->int_next; args->int_next += p + 1; /* need space for (p+1) int's */ /* compute coefficients mod p */ for (n = 0; n <= degree; n++) coeffs_mod_p[n] = umodiu(pel(c,n), p); np = umael(squares,pn,coeffs_mod_p[0]+1); is_f_square[0] = np; for (a = 1 ; a < p; a++) { ulong s = coeffs_mod_p[degree]; if ((degree+1)*args->bit_primes <= BITS_IN_LONG) { for (n = degree - 1 ; n >= 0 ; n--) s = s*a + coeffs_mod_p[n]; /* here, s < p^(degree+1) <= max. long */ s %= p; } else { for (n = degree - 1 ; n >= 0 ; n--) { s = s*a + coeffs_mod_p[n]; if (s+1 >= bound) s %= p; } s %= p; } if ((is_f_square[a] = mael(squares,pn,s+1))) np++; } is_f_square[p] = odd(degree) || mael(squares,pn,coeffs_mod_p[degree]+1); /* check if there are no solutions mod p */ if (np == 0 && !is_f_square[p]) return gc_long(av,p); /* Fill arrays with info for p */ if (np < p) { /* only when there is some information */ ulong i; ratpoints_sieve_entry *se = args->se_next; double r = is_f_square[p] ? ((double)(np*(p-1) + p))/((double)(p*p)) : (double)np/(double)p; prec[pnp].r = r; args->se_next ++; se->p = p; se->is_f_square = is_f_square; se->inverses = gel(inverses,pn); se->offset = offsets[pn]; se->sieve[0] = (ratpoints_bit_array *)sieves0[pn]; for (i = 1; i < p; i++) se->sieve[i] = NULL; prec[pnp].ssp = se; pnp++; } if ((args->flags & RATPOINTS_CHECK_DENOM) && fba + fdc < args->max_forbidden && !is_f_square[p]) { /* record forbidden divisors of the denominator */ if (coeffs_mod_p[degree] == 0) { /* leading coeff. divisible by p */ GEN r; long v = Z_lvalrem(pel(c,degree), p, &r); if (odd(v) || !mael(squares,pn, umodiu(r,p)+1)) { /* Can only get something when valuation is odd or when valuation is even and lcf is not a p-adic square. Compute smallest n such that if v(den) >= n, the leading term determines the valuation. Then we must have v(den) < n. */ long k, n = 1; for (k = degree-1; k >= 0; k--) { if (coeffs_mod_p[k] == 0) { long t = 1 + v - Z_lval(pel(c,k), p); long m = CEIL(t, (degree-k)); if (m > n) n = m; } } if (n == 1) { forb_ba[fba].p = p; forb_ba[fba].start = sieves0[pn]; forb_ba[fba].end = sieves0[pn]+p; forb_ba[fba].curr = forb_ba[fba].start; fba++; } else { forbidden[fdc] = upowuu(p, n); fdc++; } } } else /* leading coefficient is a nonsquare mod p */ { /* denominator divisible by p is excluded */ forb_ba[fba].p = p; forb_ba[fba].start = sieves0[pn]; forb_ba[fba].end = sieves0[pn]+p; forb_ba[fba].curr = forb_ba[fba].start; fba++; } } } /* end for pn */ /* update sp2 and sp1 if necessary */ if (args->sp2 > pnp) args->sp2 = pnp; if (args->sp1 > args->sp2) args->sp1 = args->sp2; /* sort the array to get at the best primes */ qsort(prec, pnp, sizeof(entry), compare_entries); /* put the sorted entries into sieve_list */ for (n = 0; n < args->sp2; n++) sieve_list[n] = prec[n].ssp; /* terminate array of forbidden divisors */ if (args->flags & RATPOINTS_CHECK_DENOM) { long n; for (n = args->num_primes+1; fba + fdc < args->max_forbidden && n <= nbprime; n++) { ulong p = args->listprime[n]; if (p*p > (ulong) args->b_high) break; if (kroiu(pel(c,degree), p) == -1) { forb_ba[fba].p = p; forb_ba[fba].start = sieves0[n]; forb_ba[fba].end = sieves0[n]+p; forb_ba[fba].curr = forb_ba[fba].start; fba++; } } forb_ba[fba].p = 0; /* terminating zero */ forbidden[fdc] = 0; /* terminating zero */ args->max_forbidden = fba + fdc; /* note actual number */ } if (fba + fdc == 0) args->flags &= ~RATPOINTS_CHECK_DENOM; return gc_long(av,0); } /************************************************************************** * The sieving procedure itself * **************************************************************************/ static void sift(long b, ratpoints_bit_array *survivors, ratpoints_args *args, bit_selection which_bits, ratpoints_bit_array bits16, ratpoints_sieve_entry **sieve_list, long *bp_list, int *quit, int process(long, long, GEN, void*, int*), void *info) { pari_sp av = avma; int do_setup = 1; long k, height = args->height, nb; sieve_spec *ssp = (sieve_spec *) stack_malloc(args->sp2*sizeof(sieve_spec)); if (odd(b) == 0) which_bits = num_odd; /* even denominator */ /* Note that b is new */ args->bc = NULL; nb = 0; for (k = 0; k < args->num_inter; k++) { ratpoints_interval inter = args->domain[k]; long low, high; /* Determine relevant interval [low, high] of numerators. */ if (b*inter.low <= -height) low = -height; else { if (b*inter.low > height) break; low = ceil(b*inter.low); } if (b*inter.up >= height) high = height; else { if (b*inter.up < -height) continue; high = floor(b*inter.up); } if (do_setup) { /* set up the sieve information */ long n; do_setup = 0; /* only do it once for every b */ for (n = 0; n < args->sp2; n++) { ratpoints_sieve_entry *se = sieve_list[n]; long p = se->p; long bp = bp_list[n]; ratpoints_bit_array *sptr; if (which_bits != num_all) /* divide by 2 mod p */ bp = odd(bp) ? (bp+p) >> 1 : bp >> 1; sptr = se->sieve[bp]; ssp[n].p = p; ssp[n].offset = (which_bits == num_odd) ? se->offset : 0; /* copy if already initialized, else initialize */ ssp[n].ptr = sptr ? sptr : (p>= 1; high--; high >>= 1; break; case num_even: low++; low >>= 1; high >>= 1; break; } /* now turn the bit interval into [low, high[ */ high++; if (low < high) { long w_low, w_high, w_low0, w_high0, range = args->array_size; /* Now the range of longwords (= bit_arrays) */ w_low = low >> RBA_SHIFT; w_high = (high + (long)(RBA_LENGTH-1)) >> RBA_SHIFT; w_low0 = w_low; w_high0 = w_low0 + range; for ( ; w_low0 < w_high; w_low0 = w_high0, w_high0 += range) { long i; if (w_high0 > w_high) { w_high0 = w_high; range = w_high0 - w_low0; } /* initialise the bits */ for (i = range; i; i--) survivors[i-1] = bits16; /* boundary words */ if (w_low0 == w_low) MASKL(survivors,low - RBA_LENGTH * w_low) if (w_high0 == w_high) MASKU(&survivors[range-1], RBA_LENGTH * w_high - high) #if (RATPOINTS_CHUNK > 1) while(range%RATPOINTS_CHUNK != 0) { survivors[range] = RBA(0); range++; w_high0++; } #endif nb += _ratpoints_sift0(b, w_low0, w_high0, args, which_bits, survivors, &ssp[0], quit, process, info); if (*quit) return; } } } if (nb==0) set_avma(av); } /************************************************************************** * Find points by looping over the denominators and sieving numerators * **************************************************************************/ static void find_points_work(ratpoints_args *args, int process(long, long, GEN, void*, int*), void *info) { int quit = 0; GEN c = args->cof; long degree = degpol(c); long nbprime = lg(args->listprime)-1; long height = args->height; int point_at_infty = 0; /* indicates if there are points at infinity */ int lcfsq = Z_issquare(pel(c,degree)); forbidden_entry *forb_ba = args->forb_ba; long *forbidden = args->forbidden; /* The forbidden divisors, a zero-terminated array. Used when degree is even and leading coefficient is not a square */ /* These are used when degree is odd and leading coeff. is not +-1 */ ratpoints_sieve_entry **sieve_list = (ratpoints_sieve_entry**) stack_malloc(nbprime*sizeof(ratpoints_sieve_entry*)); bit_selection which_bits = num_all; ulong den_bits; ratpoints_bit_array num_bits[16]; args->flags &= RATPOINTS_FLAGS_INPUT_MASK; args->flags |= RATPOINTS_CHECK_DENOM; /* initialize memory management */ args->se_next = args->se_buffer; args->ba_next = args->ba_buffer; args->int_next = args->int_buffer; /* Some sanity checks */ args->num_inter = 0; if (args->num_primes > nbprime) args->num_primes = nbprime; if (args->sp2 > args->num_primes) args->sp2 = args->num_primes; if (args->sp1 > args->sp2) args->sp1 = args->sp2; if (args->b_low < 1) args->b_low = 1; if (args->b_high < 1) args->b_high = height; if (args->max_forbidden < 0) args->max_forbidden = RATPOINTS_DEFAULT_MAX_FORBIDDEN; if (args->max_forbidden > nbprime) args->max_forbidden = nbprime; if (args->array_size <= 0) args->array_size = RATPOINTS_ARRAY_SIZE; { long s = 2*maxss(1,CEIL(height, BITS_IN_LONG)); if (args->array_size > s) args->array_size = s; } /* make sure that array size is a multiple of RATPOINTS_CHUNK */ args->array_size = CEIL(args->array_size, RATPOINTS_CHUNK)*RATPOINTS_CHUNK; /* Don't reverse if intervals are specified or limits for the denominator are given */ if (args->num_inter > 0 || args->b_low > 1 || args->b_high != height) args->flags |= RATPOINTS_NO_REVERSE; /* Check if reversal of polynomial might be better: * case 1: degree is even, but trailing coefficient is zero * case 2: degree is even, leading coefficient is a square, but * trailing coefficient is not * case 3: degree is odd, |leading coefficient| > 1, * trailing coefficient is zero, |coeff. of x| = 1 */ if (!(args->flags & RATPOINTS_NO_REVERSE)) { if (!odd(degree) && degree>0) { if (signe(pel(c,0)) == 0 && signe(pel(c,1))!=0) { /* case 1 */ long n; args->flags |= RATPOINTS_REVERSED; for (n = 0; n < degree>>1; n++) swap(pel(c,n), pel(c,degree-n)); degree--; setlg(c,degree+3); } else if (lcfsq && !Z_issquare(pel(c,0))) { /* case 2 */ long n; args->flags |= RATPOINTS_REVERSED; for (n = 0; n < degree>>1; n++) swap(pel(c,n), pel(c,degree-n)); lcfsq = 0; } } else { /* odd degree, case 3*/ if (!is_pm1(pel(c,degree)) && !signe(pel(c,0)) && is_pm1(pel(c,1))) { long n; args->flags |= RATPOINTS_REVERSED; for (n = 1; n <= degree>>1; n++) swap(pel(c,n),pel(c,degree+1-n)); } } } /* Deal with the intervals */ if (args->num_inter == 0) { /* default interval (effectively ]-oo,oo[) if none is given */ args->domain = (ratpoints_interval*) stack_malloc(2*degree*sizeof(ratpoints_interval)); args->domain[0].low = -height; args->domain[0].up = height; args->num_inter = 1; } ratpoints_compute_sturm(args); /* Point(s) at infinity? */ if (odd(degree) || lcfsq) { args->flags &= ~RATPOINTS_CHECK_DENOM; point_at_infty = 1; } /* Can use only squares as denoms if degree is odd and poly is +-monic */ if (odd(degree)) { GEN w1 = pel(c,degree); if (is_pm1(w1)) args->flags |= RATPOINTS_USE_SQUARES; else /* set up information on divisors of leading coefficient */ setup_us1(args, absi_shallow(w1)); } /* deal with f mod powers of 2 */ which_bits = get_2adic_info(args, &den_bits, &num_bits[0]); /* which_bits says whether to consider even and/or odd numerators * when the denominator is odd. * * Bit k in den_bits is 0 if b congruent to k mod BITS_IN_LONG need * not be considered as a denominator. * * Bit k in num_bits[b] is 0 is numerators congruent to * k (which_bits = den_all) * 2k (which_bits = den_even) * 2k+1 (which_bits = den_odd) * need not be considered for denominators congruent to b mod 16. */ /* set up the sieve data structure */ if (sieving_info(args, sieve_list)) return; /* deal with point(s) at infinity */ if (point_at_infty) { long a = 1, b = 0; if (args->flags & RATPOINTS_REVERSED) { a = 0; b = 1; } if (odd(degree)) (void)process(a, b, gen_0, info, &quit); else { GEN w0 = sqrti(pel(c,degree)); (void)process(a, b, w0, info, &quit); (void)process(a, b, negi(w0), info, &quit); } if (quit) return; } /* now do the sieving */ { ratpoints_bit_array *survivors = (ratpoints_bit_array *) stack_malloc_align((args->array_size)*RBA_SIZE, RBA_SIZE); long *bp_list = (long *) new_chunk(args->sp2); if (args->flags & (RATPOINTS_USE_SQUARES | RATPOINTS_USE_SQUARES1)) { if (args->flags & RATPOINTS_USE_SQUARES) /* need only take squares as denoms */ { long b, bb; long last_b = args->b_low; long n; for (n = 0; n < args->sp2; n++) bp_list[n] = mod(args->b_low, sieve_list[n]->p); for (b = 1; bb = b*b, bb <= args->b_high; b++) if (bb >= args->b_low) { ratpoints_bit_array bits = num_bits[bb & 0xf]; if (TEST(bits)) { long n; long d = bb - last_b; /* fill bp_list */ for (n = 0; n < args->sp2; n++) bp_list[n] = mod(bp_list[n] + d, sieve_list[n]->p); last_b = bb; sift(bb, survivors, args, which_bits, bits, sieve_list, &bp_list[0], &quit, process, info); if (quit) break; } } } else /* args->flags & RATPOINTS_USE_SQUARES1 */ { GEN den_info = args->den_info; GEN divisors = args->divisors; long ld = lg(divisors); long k; long b, bb; for (k = 1; k < ld; k++) { long d = divisors[k]; long last_b = d; long n; if (d > args->b_high) continue; for (n = 0; n < args->sp2; n++) bp_list[n] = mod(d, sieve_list[n]->p); for (b = 1; bb = d*b*b, bb <= args->b_high; b++) { if (bb >= args->b_low) { int flag = 1; ratpoints_bit_array bits = num_bits[bb & 0xf]; if (EXT0(bits)) { long i, n, l = lg(gel(den_info,1)); long d = bb - last_b; /* fill bp_list */ for (n = 0; n < args->sp2; n++) bp_list[n] = mod(bp_list[n] + d, sieve_list[n]->p); last_b = bb; for(i = 1; i < l; i++) { long v = z_lval(bb, mael(den_info,1,i)); if((v >= mael(den_info,3,i)) && odd(v + (mael(den_info,2,i)))) { flag = 0; break; } } if (flag) { sift(bb, survivors, args, which_bits, bits, sieve_list, &bp_list[0], &quit, process, info); if (quit) break; } } } } if (quit) break; } } } else { if (args->flags & RATPOINTS_CHECK_DENOM) { long *forb; long b; long last_b = args->b_low; ulong b_bits; long n; for (n = 0; n < args->sp2; n++) bp_list[n] = mod(args->b_low, sieve_list[n]->p); { forbidden_entry *fba = &forb_ba[0]; long b_low = args->b_low; long w_low = (b_low-1) >> TWOPOTBITS_IN_LONG; b_bits = den_bits; while (fba->p) { fba->curr = fba->start + mod(w_low, fba->p); b_bits &= *(fba->curr); fba++; } b_bits >>= (b_low-1) & LONG_MASK; } for (b = args->b_low; b <= args->b_high; b++) { ratpoints_bit_array bits = num_bits[b & 0xf]; if ((b & LONG_MASK) == 0) { /* next b_bits */ forbidden_entry *fba = &forb_ba[0]; b_bits = den_bits; while (fba->p) { fba->curr++; if (fba->curr == fba->end) fba->curr = fba->start; b_bits &= *(fba->curr); fba++; } } else b_bits >>= 1; if (odd(b_bits) && EXT0(bits)) { /* check if denominator is excluded */ for (forb = &forbidden[0] ; *forb && (b % (*forb)); forb++) continue; if (*forb == 0 && rpjacobi(b, pel(c,degree)) == 1) { long n, d = b - last_b; /* fill bp_list */ for (n = 0; n < args->sp2; n++) { long bp = bp_list[n] + d; long p = sieve_list[n]->p; while (bp >= p) bp -= p; bp_list[n] = bp; } last_b = b; sift(b, survivors, args, which_bits, bits, sieve_list, &bp_list[0], &quit, process, info); if (quit) break; } } } } /* if (args->flags & RATPOINTS_CHECK_DENOM) */ else { long b, n; long last_b = args->b_low; for (n = 0; n < args->sp2; n++) bp_list[n] = mod(args->b_low, sieve_list[n]->p); for (b = args->b_low; b <= args->b_high; b++) { ratpoints_bit_array bits = num_bits[b & 0xf]; if (EXT0(bits)) { long n; long d = b - last_b; /* fill bp_list */ for (n = 0; n < args->sp2; n++) { long bp = bp_list[n] + d; long p = sieve_list[n]->p; while (bp >= p) bp -= p; bp_list[n] = bp; } last_b = b; sift(b, survivors, args, which_bits, bits, sieve_list, &bp_list[0], &quit, process, info); if (quit) break; } } } } } } static GEN vec_append_grow(GEN z, long i, GEN x) { long n = lg(z)-1; if (i > n) { n <<= 1; z = vec_lengthen(z,n); } gel(z,i) = x; return z; } struct points { GEN z; long i, f; }; static int process(long a, long b, GEN y, void *info0, int *quit) { struct points *p = (struct points *) info0; if (b==0 && (p->f&2L)) return 0; *quit = (p->f&1); p->z = vec_append_grow(p->z, ++p->i, mkvec3(stoi(a),y,stoi(b))); return 1; } static int args_h(ratpoints_args *args, GEN D) { long H, h, l = 1; GEN L; switch(typ(D)) { case t_INT: if (signe(D) <= 0) return 0; H = h = itos(D); break; case t_VEC: if (lg(D) != 3) return 0; H = gtos(gel(D,1)); L = gel(D,2); if (typ(L)==t_INT) { h = itos(L); break; } if (typ(L)==t_VEC && lg(L)==3) { l = gtos(gel(L,1)); h = gtos(gel(L,2)); break; } default: return 0; } args->height = H; args->b_low = l; args->b_high = h; return 1; } static GEN ZX_hyperellratpoints(GEN P, GEN h, long flag) { pari_sp av = avma; ratpoints_args args; struct points data; ulong flags = 0; if (!args_h(&args, h)) { pari_err_TYPE("hyperellratpoints", h); return NULL;/*LCOV_EXCL_LINE*/ } find_points_init(&args, RATPOINTS_DEFAULT_BIT_PRIMES); args.cof = shallowcopy(P); args.num_inter = 0; args.sp1 = RATPOINTS_DEFAULT_SP1; args.sp2 = RATPOINTS_DEFAULT_SP2; args.array_size = RATPOINTS_ARRAY_SIZE; args.num_primes = RATPOINTS_DEFAULT_NUM_PRIMES; args.bit_primes = RATPOINTS_DEFAULT_BIT_PRIMES; args.max_forbidden = RATPOINTS_DEFAULT_MAX_FORBIDDEN; args.flags = flags; data.z = cgetg(17,t_VEC); data.i = 0; data.f = flag; find_points_work(&args, process, (void *)&data); setlg(data.z, data.i+1); return gerepilecopy(av, data.z); } /* The ordinates of the points returned need to be divided by den * by the caller to get the actual solutions */ static GEN QX_hyperellratpoints(GEN P, GEN h, long flag, GEN *den) { GEN Q = Q_remove_denom(P, den); if (*den) Q = ZX_Z_mul(Q, *den); return ZX_hyperellratpoints(Q, h, flag); } static GEN ZX_homogenous_evalpow(GEN Q, GEN A, GEN B) { pari_sp av = avma; long i, d = degpol(Q); GEN s = gel(Q, d+2); for (i = d-1; i >= 0; i--) s = addii(mulii(s, A), mulii(gel(B,d+1-i), gel(Q,i+2))); return d? gerepileupto(av, s): s; } static GEN to_RgX(GEN a, long v) { return typ(a)==t_POL? a: scalarpol(a,v); } static int hyperell_check(GEN PQ, GEN *P, GEN *Q) { *P = *Q = NULL; if (typ(PQ) == t_POL) { if (!RgX_is_QX(PQ)) return 0; *P = PQ; } else { long v = gvar(PQ); if (v == NO_VARIABLE || typ(PQ) != t_VEC || lg(PQ) != 3) return 0; *P = to_RgX(gel(PQ,1), v); if (!RgX_is_QX(*P)) return 0; *Q = to_RgX(gel(PQ,2), v); if (!RgX_is_QX(*Q)) return 0; if (!signe(*Q)) *Q = NULL; } return 1; } GEN hyperellratpoints(GEN PQ, GEN h, long flag) { pari_sp av = avma; GEN P, Q, H, L, den, denQ; long i, l, dy, dQ; if (flag<0 || flag>1) pari_err_FLAG("ellratpoints"); if (!hyperell_check(PQ, &P, &Q)) pari_err_TYPE("hyperellratpoints",PQ); if (!Q) { L = QX_hyperellratpoints(P, h, flag|2L, &den); dy = (degpol(P)+1)>>1; l = lg(L); for (i = 1; i < l; i++) { GEN Li = gel(L,i), x = gel(Li,1), y = gel(Li,2), z = gel(Li,3); GEN zdy = powiu(z, dy); if (den) zdy = mulii(zdy, den); gel(L,i) = mkvec2(gdiv(x,z), gdiv(y, zdy)); } return gerepilecopy(av, L); } H = RgX_add(RgX_muls(P,4), RgX_sqr(Q)); dy = (degpol(H)+1)>>1; dQ = degpol(Q); L = QX_hyperellratpoints(H, h, flag|2L, &den); Q = Q_remove_denom(Q, &denQ); l = lg(L); for (i = 1; i < l; i++) { GEN Li = gel(L,i), x = gel(Li,1), y = gel(Li,2), z = gel(Li,3); GEN Qx, B = gpowers(z, dQ), zdy = powiu(z, dy), dQx = gel(B, dQ+1); if (denQ) dQx = mulii(dQx, denQ); Qx = gdiv(ZX_homogenous_evalpow(Q, x, B), dQx); if (den) zdy = mulii(zdy, den); gel(L,i) = mkvec2(gdiv(x,z), gmul2n(gsub(gdiv(y,zdy),Qx),-1)); } return gerepilecopy(av, L); } GEN ellratpoints(GEN E, GEN h, long flag) { pari_sp av = avma; GEN L, a1, a3, den; long i, l; checkell_Q(E); if (flag<0 || flag>1) pari_err_FLAG("ellratpoints"); if (!RgV_is_QV(vecslice(E,1,5))) pari_err_TYPE("ellratpoints",E); a1 = ell_get_a1(E); a3 = ell_get_a3(E); L = QX_hyperellratpoints(ec_bmodel(E,0), h, flag|2L, &den); l = lg(L); for (i = 1; i < l; i++) { GEN P, Li = gel(L,i), x = gel(Li,1), y = gel(Li,2), z = gel(Li,3); if (!signe(z)) P = ellinf(); else { GEN z2 = sqri(z); if (den) y = gdiv(y, den); y = gsub(y, gadd(gmul(a1, mulii(x,z)), gmul(a3,z2))); P = mkvec2(gdiv(x,z), gdiv(y,shifti(z2,1))); } gel(L,i) = P; } return gerepilecopy(av, L); } pari-2.17.2/src/modules/genus2red.c0000644000175000017500000021111714760123736015501 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_genus2red /* extract coefficients of a polynomial a0 X^6 + ... + a6, of degree <= 6 */ static void RgX_to_06(GEN q, GEN *a0, GEN *a1, GEN *a2, GEN *a3, GEN *a4, GEN *a5, GEN *a6) { *a0 = gen_0; *a1 = gen_0; *a2 = gen_0; *a3 = gen_0; *a4 = gen_0; *a5 = gen_0; *a6 = gen_0; switch(degpol(q)) { case 6: *a0 = gel(q,8); /*fall through*/ case 5: *a1 = gel(q,7); /*fall through*/ case 4: *a2 = gel(q,6); /*fall through*/ case 3: *a3 = gel(q,5); /*fall through*/ case 2: *a4 = gel(q,4); /*fall through*/ case 1: *a5 = gel(q,3); /*fall through*/ case 0: *a6 = gel(q,2); /*fall through*/ } } /********************************************************************/ /** **/ /** IGUSA INVARIANTS **/ /** (GP2C-generated) **/ /** **/ /********************************************************************/ /* j2(a0,a1,a2,a3,a4,a5,a6) = (-120*a0*a6+20*a1*a5-8*a2*a4+3*a3^2) / 4; */ static GEN igusaj2(GEN a0, GEN a1, GEN a2, GEN a3, GEN a4, GEN a5, GEN a6) { pari_sp av = avma; return gerepileupto(av, gmul2n(gadd(gsub(gadd(gmul(gmulsg(-120, a0), a6), gmul(gmulsg(20, a1), a5)), gmul(gmulsg(8, a2), a4)), gmulsg(3, gsqr(a3))), -2)); } /* j4(a0,a1,a2,a3,a4,a5,a6) = (240*(a0*a3*a4*a5+a1*a2*a3*a6)-400*(a0*a2*a5^2+a1^2*a4*a6)-64*(a0*a4^3+a2^3*a6)+16*(a1*a3*a4^2+a2^2*a3*a5)-672*a0*a3^2*a6+240*a1^2*a5^2-112*a1*a2*a4*a5-8*a1*a3^2*a5+16*a2^2*a4^2-16*a2*a3^2*a4+3*a3^4+2640*a0^2*a6^2-880*a0*a1*a5*a6+1312*a0*a2*a4*a6) / 2^7 */ static GEN igusaj4(GEN a0, GEN a1, GEN a2, GEN a3, GEN a4, GEN a5, GEN a6) { pari_sp av = avma; return gerepileupto(av, gmul2n(gadd(gsub(gadd(gadd(gsub(gadd(gsub(gsub(gadd(gsub(gadd(gsub(gsub(gmulsg(240, gadd(gmul(gmul(gmul(a0, a3), a4), a5), gmul(gmul(gmul(a1, a2), a3), a6))), gmulsg(400, gadd(gmul(gmul(a0, a2), gsqr(a5)), gmul(gmul(gsqr(a1), a4), a6)))), gmulsg(64, gadd(gmul(a0, gpowgs(a4, 3)), gmul(gpowgs(a2, 3), a6)))), gmulsg(16, gadd(gmul(gmul(a1, a3), gsqr(a4)), gmul(gmul(gsqr(a2), a3), a5)))), gmul(gmul(gmulsg(672, a0), gsqr(a3)), a6)), gmul(gmulsg(240, gsqr(a1)), gsqr(a5))), gmul(gmul(gmul(gmulsg(112, a1), a2), a4), a5)), gmul(gmul(gmulsg(8, a1), gsqr(a3)), a5)), gmul(gmulsg(16, gsqr(a2)), gsqr(a4))), gmul(gmul(gmulsg(16, a2), gsqr(a3)), a4)), gmulsg(3, gpowgs(a3, 4))), gmul(gmulsg(2640, gsqr(a0)), gsqr(a6))), gmul(gmul(gmul(gmulsg(880, a0), a1), a5), a6)), gmul(gmul(gmul(gmulsg(1312, a0), a2), a4), a6)), -7)); } /* j6(a0,a1,a2,a3,a4,a5,a6) = (1600*(a0^2*a4^2*a5^2+a1^2*a2^2*a6^2)+1600*(a0*a1*a2*a5^3+a1^3*a4*a5*a6)+640*(a0*a1*a3*a4*a5^2+a1^2*a2*a3*a5*a6)-4000*(a0^2*a3*a5^3+a1^3*a3*a6^2)-384*(a0*a1*a4^3*a5+a1*a2^3*a5*a6)-640*(a0*a2^2*a4*a5^2+a1^2*a2*a4^2*a6)+80*(a0*a2*a3^2*a5^2+a1^2*a3^2*a4*a6)+192*(a0*a2*a3*a4^2*a5+a1*a2^2*a3*a4*a6)-48*(a0*a3^3*a4*a5+a1*a2*a3^3*a6)-224*(a1^2*a3*a4^2*a5+a1*a2^2*a3*a5^2)+64*(a1^2*a4^4+a2^4*a5^2)-64*(a1*a2*a3*a4^3+a2^3*a3*a4*a5)+16*(a1*a3^3*a4^2+a2^2*a3^3*a5)-4096*(a0^2*a4^3*a6+a0*a2^3*a6^2)+6400*(a0^2*a2*a5^2*a6+a0*a1^2*a4*a6^2)+10560*(a0^2*a3*a4*a5*a6+a0*a1*a2*a3*a6^2)+2624*(a0*a1*a3*a4^2*a6+a0*a2^2*a3*a5*a6)-4432*a0*a1*a3^2*a5*a6-8*a2*a3^4*a4+a3^6-320*a1^3*a5^3+64*a1^2*a2*a4*a5^2+176*a1^2*a3^2*a5^2+128*a1*a2^2*a4^2*a5+112*a1*a2*a3^2*a4*a5-28*a1*a3^4*a5+16*a2^2*a3^2*a4^2+5120*a0^3*a6^3-2544*a0^2*a3^2*a6^2+312*a0*a3^4*a6-14336*a0^2*a2*a4*a6^2+1024*a0*a2^2*a4^2*a6-2560*a0^2*a1*a5*a6^2-2240*a0*a1^2*a5^2*a6-6528*a0*a1*a2*a4*a5*a6-1568*a0*a2*a3^2*a4*a6) / 2^10 */ static GEN igusaj6(GEN a0, GEN a1, GEN a2, GEN a3, GEN a4, GEN a5, GEN a6) { pari_sp av = avma; return gerepileupto(av, gmul2n(gsub(gsub(gsub(gsub(gadd(gsub(gadd(gsub(gadd(gadd(gsub(gadd(gadd(gadd(gadd(gsub(gadd(gsub(gsub(gadd(gadd(gadd(gsub(gadd(gsub(gadd(gsub(gsub(gadd(gadd(gsub(gsub(gsub(gadd(gadd(gmulsg(1600, gadd(gmul(gmul(gsqr(a0), gsqr(a4)), gsqr(a5)), gmul(gmul(gsqr(a1), gsqr(a2)), gsqr(a6)))), gmulsg(1600, gadd(gmul(gmul(gmul(a0, a1), a2), gpowgs(a5, 3)), gmul(gmul(gmul(gpowgs(a1, 3), a4), a5), a6)))), gmulsg(640, gadd(gmul(gmul(gmul(gmul(a0, a1), a3), a4), gsqr(a5)), gmul(gmul(gmul(gmul(gsqr(a1), a2), a3), a5), a6)))), gmulsg(4000, gadd(gmul(gmul(gsqr(a0), a3), gpowgs(a5, 3)), gmul(gmul(gpowgs(a1, 3), a3), gsqr(a6))))), gmulsg(384, gadd(gmul(gmul(gmul(a0, a1), gpowgs(a4, 3)), a5), gmul(gmul(gmul(a1, gpowgs(a2, 3)), a5), a6)))), gmulsg(640, gadd(gmul(gmul(gmul(a0, gsqr(a2)), a4), gsqr(a5)), gmul(gmul(gmul(gsqr(a1), a2), gsqr(a4)), a6)))), gmulsg(80, gadd(gmul(gmul(gmul(a0, a2), gsqr(a3)), gsqr(a5)), gmul(gmul(gmul(gsqr(a1), gsqr(a3)), a4), a6)))), gmulsg(192, gadd(gmul(gmul(gmul(gmul(a0, a2), a3), gsqr(a4)), a5), gmul(gmul(gmul(gmul(a1, gsqr(a2)), a3), a4), a6)))), gmulsg(48, gadd(gmul(gmul(gmul(a0, gpowgs(a3, 3)), a4), a5), gmul(gmul(gmul(a1, a2), gpowgs(a3, 3)), a6)))), gmulsg(224, gadd(gmul(gmul(gmul(gsqr(a1), a3), gsqr(a4)), a5), gmul(gmul(gmul(a1, gsqr(a2)), a3), gsqr(a5))))), gmulsg(64, gadd(gmul(gsqr(a1), gpowgs(a4, 4)), gmul(gpowgs(a2, 4), gsqr(a5))))), gmulsg(64, gadd(gmul(gmul(gmul(a1, a2), a3), gpowgs(a4, 3)), gmul(gmul(gmul(gpowgs(a2, 3), a3), a4), a5)))), gmulsg(16, gadd(gmul(gmul(a1, gpowgs(a3, 3)), gsqr(a4)), gmul(gmul(gsqr(a2), gpowgs(a3, 3)), a5)))), gmulsg(4096, gadd(gmul(gmul(gsqr(a0), gpowgs(a4, 3)), a6), gmul(gmul(a0, gpowgs(a2, 3)), gsqr(a6))))), gmulsg(6400, gadd(gmul(gmul(gmul(gsqr(a0), a2), gsqr(a5)), a6), gmul(gmul(gmul(a0, gsqr(a1)), a4), gsqr(a6))))), gmulsg(10560, gadd(gmul(gmul(gmul(gmul(gsqr(a0), a3), a4), a5), a6), gmul(gmul(gmul(gmul(a0, a1), a2), a3), gsqr(a6))))), gmulsg(2624, gadd(gmul(gmul(gmul(gmul(a0, a1), a3), gsqr(a4)), a6), gmul(gmul(gmul(gmul(a0, gsqr(a2)), a3), a5), a6)))), gmul(gmul(gmul(gmul(gmulsg(4432, a0), a1), gsqr(a3)), a5), a6)), gmul(gmul(gmulsg(8, a2), gpowgs(a3, 4)), a4)), gpowgs(a3, 6)), gmul(gmulsg(320, gpowgs(a1, 3)), gpowgs(a5, 3))), gmul(gmul(gmul(gmulsg(64, gsqr(a1)), a2), a4), gsqr(a5))), gmul(gmul(gmulsg(176, gsqr(a1)), gsqr(a3)), gsqr(a5))), gmul(gmul(gmul(gmulsg(128, a1), gsqr(a2)), gsqr(a4)), a5)), gmul(gmul(gmul(gmul(gmulsg(112, a1), a2), gsqr(a3)), a4), a5)), gmul(gmul(gmulsg(28, a1), gpowgs(a3, 4)), a5)), gmul(gmul(gmulsg(16, gsqr(a2)), gsqr(a3)), gsqr(a4))), gmul(gmulsg(5120, gpowgs(a0, 3)), gpowgs(a6, 3))), gmul(gmul(gmulsg(2544, gsqr(a0)), gsqr(a3)), gsqr(a6))), gmul(gmul(gmulsg(312, a0), gpowgs(a3, 4)), a6)), gmul(gmul(gmul(gmulsg(14336, gsqr(a0)), a2), a4), gsqr(a6))), gmul(gmul(gmul(gmulsg(1024, a0), gsqr(a2)), gsqr(a4)), a6)), gmul(gmul(gmul(gmulsg(2560, gsqr(a0)), a1), a5), gsqr(a6))), gmul(gmul(gmul(gmulsg(2240, a0), gsqr(a1)), gsqr(a5)), a6)), gmul(gmul(gmul(gmul(gmul(gmulsg(6528, a0), a1), a2), a4), a5), a6)), gmul(gmul(gmul(gmul(gmulsg(1568, a0), a2), gsqr(a3)), a4), a6)), -10)); } static GEN igusaj8_fromj246(GEN j2, GEN j4, GEN j6) { return gmul2n(gsub(gmul(j2,j6), gsqr(j4)), -2); } static GEN igusaj8(GEN a0, GEN a1, GEN a2, GEN a3, GEN a4, GEN a5, GEN a6) { pari_sp av = avma; GEN j2 = igusaj2(a0,a1,a2,a3,a4,a5,a6); GEN j4 = igusaj4(a0,a1,a2,a3,a4,a5,a6); GEN j6 = igusaj6(a0,a1,a2,a3,a4,a5,a6); return gerepileupto(av, igusaj8_fromj246(j2,j4,j6)); } static GEN igusaj10(GEN a0, GEN a1, GEN a2, GEN a3, GEN a4, GEN a5, GEN a6) { pari_sp av = avma; GEN polr = mkpoln(7, a0, a1, a2, a3, a4, a5, a6); GEN disc = RgX_disc(polr); GEN j10 = degpol(polr) < 6? gmul(gsqr(a1), disc): disc; return gerepileupto(av, gmul2n(j10, -12)); } static GEN igusaall(GEN a0, GEN a1, GEN a2, GEN a3, GEN a4, GEN a5, GEN a6) { GEN j2, j4, j6, V = cgetg(6,t_VEC); pari_sp av; gel(V,1) = j2 = igusaj2(a0,a1,a2,a3,a4,a5,a6); gel(V,2) = j4 = igusaj4(a0,a1,a2,a3,a4,a5,a6); gel(V,3) = j6 = igusaj6(a0,a1,a2,a3,a4,a5,a6); av = avma; gel(V,4) = gerepileupto(av, igusaj8_fromj246(j2, j4, j6)); gel(V,5) = igusaj10(a0,a1,a2,a3,a4,a5,a6); return V; } GEN genus2igusa(GEN P, long n) { pari_sp av = avma; GEN a0, a1, a2, a3, a4, a5, a6, r; if (typ(P) == t_VEC && lg(P) == 3) P = gadd(gmul2n(gel(P,1), 2), gsqr(gel(P,2))); else P = gmul2n(P, 2); if (typ(P)!=t_POL || degpol(P)> 6) pari_err_TYPE("genus2igusa",P); RgX_to_06(P, &a0,&a1,&a2,&a3,&a4,&a5,&a6); switch(n) { case 0: r = igusaall(a0,a1,a2,a3,a4,a5,a6); break; case 2: r = igusaj2(a0,a1,a2,a3,a4,a5,a6); break; case 4: r = igusaj4(a0,a1,a2,a3,a4,a5,a6); break; case 6: r = igusaj6(a0,a1,a2,a3,a4,a5,a6); break; case 8: r = igusaj8(a0,a1,a2,a3,a4,a5,a6); break; case 10:r = igusaj10(a0,a1,a2,a3,a4,a5,a6); break; default: pari_err_FLAG("genus2igusa"); return NULL; /* LCOV_EXCL_LINE */ } return gerepileupto(av, r); } /********************************************************************/ /** **/ /** A REDUCTION ALGORITHM "A LA TATE" FOR CURVES OF GENUS 2 **/ /** **/ /********************************************************************/ /* Based on genus2reduction-0.3, http://www.math.u-bordeaux.fr/~liu/G2R/ * by Qing Liu * and Henri Cohen * Qing Liu: Modeles minimaux des courbes de genre deux * J. fuer die Reine und Angew. Math., 453 (1994), 137-164. * http://www.math.u-bordeaux.fr/~liu/articles/modregE.ps */ /* some auxiliary polynomials, gp2c-generated */ /* apol2(a0,a1,a2) = -5*a1^2+12*a0*a2; */ static GEN apol2(GEN a0, GEN a1, GEN a2) { return gadd(gmulsg(-5, gsqr(a1)), gmul(gmulsg(12, a0), a2)); } /* apol3(a0,a1,a2,a3) = 5*a1^3+9*a0*(-2*a1*a2+3*a0*a3); */ static GEN apol3(GEN a0, GEN a1, GEN a2, GEN a3) { return gadd(gmulsg(5, gpowgs(a1, 3)), gmul(gmulsg(9, a0), gadd(gmul(gmulsg(-2, a1), a2), gmul(gmulsg(3, a0), a3)))); } /* apol5(a0,a1,a2,a3,a4,a5) = a1^5+3*a0*(-2*a1^3*a2+9*a0*a1^2*a3-36*a0^2*a1*a4+108*a0^3*a5); */ static GEN apol5(GEN a0, GEN a1, GEN a2, GEN a3, GEN a4, GEN a5) { return gadd(gpowgs(a1, 5), gmul(gmulsg(3, a0), gadd(gsub(gadd(gmul(gmulsg(-2, gpowgs(a1, 3)), a2), gmul(gmul(gmulsg(9, a0), gsqr(a1)), a3)), gmul(gmul(gmulsg(36, gsqr(a0)), a1), a4)), gmul(gmulsg(108, gpowgs(a0, 3)), a5)))); } /* bpol2(a0,a1,a2,a3,a4) = 2*a2^2-5*a1*a3+10*a0*a4; */ static GEN bpol2(GEN a0, GEN a1, GEN a2, GEN a3, GEN a4) { return gadd(gsub(gmulsg(2, gsqr(a2)), gmul(gmulsg(5, a1), a3)), gmul(gmulsg(10, a0), a4)); } static const long VERYBIG = (1L<<20); static long myval(GEN x, GEN p) { return signe(x)? Z_pval(x,p): VERYBIG; } static long my3val(GEN x) { return signe(x)? Z_lval(x,3): VERYBIG; } /* b in Z[i], return v_3(b) */ static long myval_zi(GEN b) { return minss(my3val(real_i(b)), my3val(imag_i(b))); } /* b in Z[i, Y]/(Y^2-3), return v_Y(b) */ static long myval_zi2(GEN b) { long v0, v1; b = lift_shallow(b); v0 = myval_zi(RgX_coeff(b,0)); v1 = myval_zi(RgX_coeff(b,1)); return minss(2*v0, 2*v1+1); } /* min(a,b,c) */ static long min3(long a, long b, long c) { long m = a; if (b < m) m = b; if (c < m) m = c; return m; } /* Vector of p-adic factors (over Q_p) to accuracy r of pol. */ static GEN padicfactors(GEN pol, GEN p, long r) { return gel(factorpadic(pol,p,r),1); } /* x(1/t)*t^6, deg x <= 6 */ static GEN RgX_recip6(GEN x) { long lx = lg(x), i, j; GEN y = cgetg(9, t_POL); y[1] = x[1]; for (i=8,j=2; j < lx; i--,j++) gel(y,i) = gel(x,j); for ( ; j < 9; i--,j++) gel(y,i) = gen_0; return normalizepol_lg(y, 9); } /* extract coefficients a0,...a3 of a polynomial a0 X^6 + ... + a6 */ static void RgX_to_03(GEN q, GEN *a0, GEN *a1, GEN *a2, GEN *a3) { *a0 = gen_0; *a1 = gen_0; *a2 = gen_0; *a3 = gen_0; switch(degpol(q)) { case 6: *a0 = gel(q,8); /*fall through*/ case 5: *a1 = gel(q,7); /*fall through*/ case 4: *a2 = gel(q,6); /*fall through*/ case 3: *a3 = gel(q,5); /*fall through*/ } } /* deg(H mod p) = 3, return v_p( disc(corresponding p-adic factor) ) */ static long discpart(GEN H, GEN p, long prec) { GEN list, prod, dis; long i, j; if (degpol(FpX_red(H,p)) != 3) pari_err_BUG("discpart [must not reach]"); /* LCOV_EXCL_LINE */ list = padicfactors(H,p,prec); prod = pol_1(varn(H)); for(i = 1; i < lg(list); i++) { GEN t = gel(list,i); for(j = 3; j < lg(t); j++) /* include if nonconstant mod p */ if (!valp(gel(t,j))) { prod = RgX_mul(prod,t); break; } } if (degpol(prod) != 3) pari_err_BUG("discpart [prod degree]"); dis = RgX_disc(prod); return gequal0(dis)? prec+1: valp(dis); } /* B = b0 X^6 + ... + b6 a ZX, 0 <= j <= 3. * Let theta_j(H) := min { v_p(b_i) / (i - j), j < i <= 6 } >= 0. * Return 60 theta \in Z */ static long theta_j(GEN B, GEN p, long j) { long i, t = VERYBIG; for(i = 1+j; i <= 6; i++) t = minss(t, myval(RgX_coeff(B,6-i), p) * (60 / (i-j))); return t; } /* compute 6 * theta_3 for B in Z[i][X], p = 3 */ static long theta_3_zi(GEN B) { long v2 = myval_zi(RgX_coeff(B,2)); long v1 = myval_zi(RgX_coeff(B,1)); long v0 = myval_zi(RgX_coeff(B,0)); return min3(6*v2, 3*v1, 2*v0); } /* compute 6 * theta_3 for B in (Z[i,Y]/(Y^2-3))[X], p = 3 */ static long theta_3_zi2(GEN B) { long v2 = myval_zi2(RgX_coeff(B,2)); long v1 = myval_zi2(RgX_coeff(B,1)); long v0 = myval_zi2(RgX_coeff(B,0)); return min3(6*v2, 3*v1, 2*v0); } /* Set maxord to the maximal multiplicity of a factor. If there is at least * a triple root (=> maxord >= 3) return it, else return NULL */ static GEN factmz(GEN Q, GEN p, long *maxord) { GEN z = FpX_factor_squarefree(Q, p); long m = lg(z)-1; /* maximal multiplicity */ *maxord = m; return (m >= 3)? FpX_oneroot(gel(z,m), p): NULL; } static long get_lambda(GEN H, GEN p) { if (!dvdii(RgX_coeff(H,3), p)) return 3; if (!dvdii(RgX_coeff(H,4), p)) return 2; if (!dvdii(RgX_coeff(H,5), p)) return 1; if (!dvdii(RgX_coeff(H,6), p)) return 0; return -1; } /* H integral ZX of degree 5 or 6, p > 2. Modify until * y^2 = p^alpha H is minimal over Z_p, alpha = 0,1 * Return [H,lambda,60*theta,alpha,quad,beta], where * - quad = 1 if H has a root of order 3 in F_p^2 \ F_p, 0 otherwise * - 0 <= lambda <= 3, index of a coefficient with valuation 0 * - theta = theta_j(H(x + r), p, lambda), 60*theta in Z, where r is a root * of H mod p * - beta >= -1 s.t. H = p^n H0(r + p^beta * X) for some n, r in Z, where * H0 is the initial H or polrecip(H) */ static GEN polymini(GEN H, GEN p) { long t60, alpha, lambda, quad = 0, beta = 0; GEN Hp; alpha = ZX_pvalrem(H, p, &H) & 1; lambda = get_lambda(H, p); if (lambda < 0) { H = RgX_recip6(H); lambda = get_lambda(H, p); } for(;;) { for(;;) { /* lambda <= 3, t60 = 60*theta */ GEN rac; long e, maxord; t60 = theta_j(H,p,lambda); e = t60 / 60; if (e) { GEN pe = powiu(p,e); /* H <- H(p^e X) / p^(e(6-lambda)) */ H = ZX_unscale_divpow(H, pe, 6-lambda); alpha = (alpha + lambda*e)&1; beta += e; t60 -= 60*e; } /* 0 <= t < 60 */ Hp = FpX_red(H, p); if (t60) break; rac = factmz(Hp,p, &maxord); if (maxord <= 2) { if (degpol(Hp) <= 3) break; goto end; } /* maxord >= 3 */ if (!rac) { quad = 1; goto end; } if (signe(rac)) H = ZX_translate(H, rac); lambda = 6 - maxord; } if (lambda <= 2) { if (myval(RgX_coeff(H,2),p) > 1-alpha && myval(RgX_coeff(H,1),p) > 2-alpha && myval(RgX_coeff(H,0),p) > 3-alpha) { H = ZX_unscale(H, p); if (alpha) H = ZX_Z_mul(H, p); return polymini(H, p); } break; } /* lambda = 3 */ if (alpha == 0) break; if (degpol(Hp) == 3) { if (myval(RgX_coeff(H,6),p) >= 3 && myval(RgX_coeff(H,5),p) >= 2) { /* too close to root [Kodaira symbol for y^2 = p^alpha*H not implemented when alpha = 1]: go back one step */ H = ZX_rescale(H, p); /* H(x/p)p^(deg H) */ H = ZX_Z_divexact(H, powiu(p, degpol(H)-3)); /* H(x/p)p^3 */ t60 += 60; alpha = 0; beta--; } break; } if (degpol(Hp) != 6) break; if (t60) { long m, maxord; GEN v, T, rac = factmz(RgX_mulXn(Hp, -3), p, &maxord); if (maxord <= 2) break; T = ZX_affine(H, p, rac); /* H(rac + px) */ if (ZX_pval(T,p) < 3) break; H = ZX_Z_divexact(T, powiu(p,3)); alpha = 0; beta++; v = FpX_factor_squarefree(FpX_red(H,p), p); m = lg(v)-1; /* maximal multiplicity */ if (m > 1) { rac = FpX_oneroot(gel(v,m), p); /* v[m] is linear */ H = ZX_translate(H,rac); t60 = theta_j(H,p,3); if (t60 < 60) break; } } } end: return mkvec2(H, mkvecsmall5(lambda,t60,alpha,quad,beta)); } /* a in Q[i], return a^3 mod 3 */ static GEN zi_pow3mod(GEN a) { GEN x, y; if (typ(a) != t_COMPLEX) return gmodgs(a,3); x = gmodgs(gel(a,1), 3); y = gmodgs(gel(a,2), 3); return mkcomplex(x, negi(y)); } static GEN polymini_zi(GEN pol) /* polynome minimal dans Z[i] */ { GEN polh, rac, a0, a1, a2, a3, a4, a5, a6, p = utoipos(3); long alpha, beta = 0, t6; alpha = ZX_pval(pol,p) & 1; polh = alpha? RgX_Rg_div(pol, p): pol; rac = mkcomplex(Fp_div(RgX_coeff(polh,3), RgX_coeff(polh,6), p), gen_1); for(;;) { long e; polh = RgX_translate(polh, rac); t6 = theta_3_zi(polh); e = t6 / 6; if (e) { GEN pe = powiu(p,e); polh = RgX_Rg_div(RgX_unscale(polh,pe), powiu(pe,3)); alpha = (alpha+e)&1; t6 -= e * 6; beta += e; } RgX_to_06(polh, &a0,&a1,&a2,&a3,&a4,&a5,&a6); if (t6 || !myval_zi(a4) || !myval_zi(a5)) break; rac = zi_pow3mod(gdiv(a6, gneg(a3))); } if (alpha && myval_zi(a0) >= 3 && myval_zi(a1) >= 2 && myval_zi(a2) >= 1) { t6 += 6; beta--; alpha = 0; } if (alpha && beta >= 1) pari_err_BUG("quadratic"); return mkvecsmall3(t6, alpha, beta); } /* pol is a ZX, minimal polynomial over Z_3[i,Y]/(Y^2-3) */ static GEN polymini_zi2(GEN pol) { long alpha, beta, t6; GEN a0, a1, a2, a3, a4, a5, a6; GEN polh, rac, y = pol_x(fetch_var()), p = utoipos(3); if (ZX_pval(pol,p)) pari_err_BUG("polymini_zi2 [polynomial not minimal]"); y = mkpolmod(y, gsubgs(gsqr(y), 3)); /* mod(y,y^2-3) */ polh = gdivgs(RgX_unscale(pol, y),27); /* H(y*x) / 27 */ if (myval_zi2(RgX_coeff(polh,4)) <= 0 || myval_zi2(RgX_coeff(polh,2)) <= 0) { (void)delete_var(); return mkvecsmall2(0,0); } if (myval_zi2(gsub(RgX_coeff(polh,6), RgX_coeff(polh,0))) > 0) rac = gen_I(); else rac = gen_1; alpha = 0; beta = 0; for(;;) { long e; polh = RgX_translate(polh, rac); t6 = theta_3_zi2(polh); e = t6 / 6; if (e) { GEN pent = gpowgs(y, e); polh = RgX_Rg_div(RgX_unscale(polh, pent), gpowgs(pent,3)); alpha = (alpha+e)&1; t6 -= 6*e; beta += e; } RgX_to_06(polh, &a0,&a1,&a2,&a3,&a4,&a5,&a6); if (t6 || !myval_zi2(a4) || !myval_zi2(a5)) break; a3 = liftpol_shallow(a3); if (typ(a3)==t_POL) a3 = RgX_coeff(a3,0); a6 = liftpol_shallow(a6); if (typ(a6)==t_POL) a6 = RgX_coeff(a6,0); rac = zi_pow3mod(gdiv(a6,gneg(a3))); } if (alpha) { if (myval_zi2(a0) < 3 || myval_zi2(a1) < 2 || myval_zi2(a2) < 1) pari_err_BUG("polymini_zi2 [alpha]"); t6 += 6; beta--; } (void)delete_var(); if (odd(beta)) pari_err_BUG("quartic [type over Z[i] must be [K-K-(2*m)]]"); return mkvecsmall2(t6, beta); } struct igusa { GEN j2, i4, j4, j6, j8, j10, i12; GEN a0, A2, A3, A5, B2; }; struct igusa_p { long eps, tt, r1, r2, tame; GEN p, stable, val, neron; const char *type; }; /* initialize Ip */ static void stable_reduction(struct igusa *I, struct igusa_p *Ip, GEN p) { static const long d[9] = { 0,60,30,30,20,15,12,10 }; /* 120 / deg(X) */ GEN j2 = I->j2, i4 = I->i4, j4 = I->j4, j6 = I->j6, j8 = I->j8; GEN val, J, v, Ieps, j10 = I->j10, i12 = I->i12; long s, r1, r2, r3, r4, i, eps; Ip->tame = 0; Ip->neron = NULL; Ip->type = NULL; Ip->p = p; Ip->val = val = cgetg(9, t_VECSMALL); val[1] = myval(j2,p); val[2] = myval(j4,p); val[3] = myval(i4,p); val[4] = myval(j6,p); val[5] = myval(j8,p); val[6] = myval(j10,p); val[7] = myval(i12,p); switch(itos_or_0(p)) { case 2: eps = 4; val[8] = val[5]; Ieps = j8; break; case 3: eps = 3; val[8] = val[4]; Ieps = j6; break; default: eps = 1; val[8] = val[1]; Ieps = gdivgs(j2,12); break; } v = cgetg(8,t_VECSMALL); for(i = 1; i <= 7; i++) v[i] = val[i] * d[i]; s = vecsmall_min(v); Ip->eps = eps; r1 = 3*eps*val[3]; r3 = eps*val[6] + val[8]; r2 = eps*val[7]; r4 = min3(r1, r2, r3); /* s = max(v_p(X) / deg(X)) */ J = cgetg(1, t_VEC); if (s == v[6]) Ip->tt = 1; else if (s == v[7]) { J = mkvec( Fp_to_mod(gmod(gdiv(gpowgs(i4,3),i12), p), p) ); Ip->tt = 2; } else if (s == v[3]) Ip->tt = (val[2] == val[3] || 2*val[4] == 3*val[3])? 3: 4; else if (r3 == r4) { GEN a,b, P, sj, pj, t = gmul(gpowgs(j10,eps),Ieps); sj = gaddsg(1728, gdiv(gpowgs(i12,eps), t)); pj = gdiv(gpowgs(i4,3*eps), t); a = gmod(sj, p); b = gmod(pj, p); P = mkpoln(3, gen_1, Fp_neg(a,p), b, 0); /* X^2 - SX + P: roots j1,j2 */ J = FpX_roots(P, p); switch(lg(J)-1) { case 0: P = FpX_to_mod(P, p); a = FpX_to_mod(pol_x(0), p); b = FpX_to_mod(deg1pol_shallow(b, gen_m1,0), p); J = mkvec2(mkpolmod(a,P), mkpolmod(b,P)); break; case 1: a = Fp_to_mod(gel(J,1), p); J = mkvec2(a, a); break; case 2: settyp(J, t_VEC); J = FpV_to_mod(J, p); break; } Ip->tt = 5; } else if (r2 == r4) { J = mkvec( Fp_to_mod(gmod(gdiv(gpowgs(i4,3),i12), p), p) ); Ip->tt = 6; } else Ip->tt = 7; /* r1 == r4 */ Ip->stable = mkvec2(stoi(Ip->tt), J); } struct red { const char *t, *pages; double tnum; GEN g; }; /* destroy v */ static GEN zv_snf(GEN v) { long i, l = lg(v); for (i = 1; i < l; i++) { long j, a = v[i]; for (j = i+1; j < l; j++) { long b = v[j], d = ugcd(a,b); v[i] = a = a*(b/d); v[j] = d; } } for (i = l-1; i > 0; i--) if (v[i] != 1) { setlg(v, i+1); break; } return zv_to_ZV(v); } static GEN cyclic(long n) { return (n <= 1)? cgetg(1, t_VECSMALL): mkvecsmall(n); } static GEN dicyclic(long a, long b) { long d; if (!a) a = 1; if (!b) b = 1; if (a < b) lswap(a,b); d = ugcd(a,b); if (d == 1) return cyclic(a*b); return mkvecsmall2(a*b/d, d); } /* Z/2xZ/2, resp Z/4 for n even, resp. odd */ static GEN groupH(long n) { return odd(n)? cyclic(4): dicyclic(2,2); } static long get_red(struct red *S, struct igusa_p *Ip, GEN polh, GEN p, long alpha, long r) { GEN val = Ip->val; long indice; switch(r) { case 0: indice = FpX_is_squarefree(FpX_red(polh,p), p) ? 0 : val[6] - val[7] + val[8]/Ip->eps; S->t = stack_sprintf("I{%ld}", indice); S->tnum = 1; S->pages = "159-177"; S->g = cyclic(indice); return indice ? indice: 1; case 6: if (alpha == 0) polh = ZX_unscale_divpow(polh, p, 3); /* H(px) /p^3 */ indice = FpX_is_squarefree(FpX_red(polh,p), p) ? 0 : val[6] - val[7] + val[8]/Ip->eps; S->t = stack_sprintf("I*{%ld}", indice); S->tnum = 1.5; S->pages = "159-177"; S->g = groupH(indice); return indice + 5; case 3: S->t = "III"; S->tnum = 3; S->pages = "161-177"; S->g = cyclic(2); return 2; case 9: S->t = "III*"; S->tnum = 3.5; S->pages = "162-177"; S->g = cyclic(2); return 8; case 2: S->t = "II"; S->tnum = 2; S->pages = "159-174"; S->g = cyclic(1); return 1; case 8: S->t = "IV*"; S->tnum = 4.5; S->pages = "160-175"; S->g = cyclic(3); return 7; case 4: S->t = "IV"; S->tnum = 4; S->pages = "160-174"; S->g = cyclic(3); return 3; case 10: S->t = "II*"; S->tnum = 2.5; S->pages = "160-174"; S->g = cyclic(1); return 9; default: pari_err_BUG("get_red [type]"); S->t = ""; S->tnum = 0; S->pages = ""; /* gcc -Wall */ S->g = NULL; return -1; /*LCOV_EXCL_LINE*/ } } /* reduce a/b; assume b > 0 */ static void ssQ_red(long a, long b, long *n, long *d) { long g = ugcd(labs(a), b); if (g > 1) { a /= g; b /= g; } *n = a; *d = b; } /* denom(a/b); assume b > 0 */ static long ssQ_denom(long a, long b) { long g = ugcd(labs(a), b); return g == 1? b: b / g; } /* n = lcm(d, denom(a/b)); r = (a/b * n mod n); assume b > 0 and d > 0 */ static void get_nr(long d, long a, long b, long *n, long *r) { long c, A, B; ssQ_red(a, b, &A,&B); c = d / ugcd(d, B); *n = B * c; *r = umodsu(A * c, *n); } /* n = lcm(denom(a/b), denom(c/d)); r = (a/b * n mod n); q = (c/d * n mod n); * assume b > 0 and d > 0 */ static void get_nrq(long a, long b, long c, long d, long *n, long *r, long *q) { long g, A, B, C, D; ssQ_red(a, b, &A,&B); ssQ_red(c, d, &C,&D); g = ugcd(B,D); *n = B * (D/g); *r = umodsu(A * (D/g), *n); *q = umodsu(C * (B/g), *n); } /* Ip->tt = 1 */ static long tame_1(struct igusa *I, struct igusa_p *Ip) { GEN p = Ip->p, val = Ip->val; long condp = -1, va0, va5, r, n; va0 = myval(I->a0,p); va5 = myval(I->A5,p); if (!gequal0(I->A5) && 20*va0+val[6] > 6*va5) get_nr(ssQ_denom(5*val[6]-6*va5, 40), val[6]-2*va5, 20, &n,&r); else get_nr(ssQ_denom(5*va0-val[6], 10), 10*va0-val[6], 30, &n,&r); switch(n) { case 1: condp = 0; Ip->type = "[I{0-0-0}] page 155"; Ip->neron = cyclic(1); break; case 2: switch(r) { case 0: condp = 4; Ip->type = "[I*{0-0-0}] page 155"; Ip->neron = mkvecsmall4(2,2,2,2); break; case 1: condp = 2; Ip->type = "[II] page 155"; Ip->neron = cyclic(1); break; default: pari_err_BUG("tame_1 [bug1]"); } break; case 4: condp = 4; Ip->type = "[VI] page 156"; Ip->neron = dicyclic(2,2); break; default: pari_err_BUG("tame_1 [bug8]"); } return condp; } /* (4.2) */ static long tame_234_init(struct igusa *I, struct igusa_p *Ip, long *n, long *q, long *r) { long va0, va5, vb2, v12 = -1, flc = 1; GEN p = Ip->p; switch(Ip->tt) { case 2: v12 = myval(I->i12, Ip->p); break; case 3: v12 = 3*myval(I->i4, Ip->p); break; case 4: v12 = 6*myval(I->j2, Ip->p); break; } va0 = myval(I->a0,p); va5 = myval(I->A5,p); vb2 = myval(I->B2,p); if (9*vb2 >= 6*va0+v12 && 36*va5 >= 120*va0+5*v12) { get_nrq(12*va0-v12,36, 6*va0-v12,12, n, r, q); } else if (120*va0+5*v12 > 36*va5 && 60*vb2 >= 12*va5+5*v12) { ssQ_red(36*va5-25*v12,240, q,n); *r = umodsu(-2* *q, *n); } else /* 6*va0+v12 > 9*vb2 && 12*va5+5*v12 > 60*vb2 */ { get_nrq(v12-6*vb2,12, v12-9*vb2,12, n,r,q); flc = 0; } return flc; } /* Ip->tt = 2 */ static long tame_2(struct igusa *I, struct igusa_p *Ip) { long condp = -1, d, n, q, r; GEN val = Ip->val; (void)tame_234_init(I, Ip, &n, &q, &r); d = n * (6*val[6]-5*val[7]) / 6; switch(n) { case 1: condp = 1; Ip->type = stack_sprintf("[I{%ld-0-0}] page 170", d); Ip->neron = cyclic(d); break; case 2: switch(r) { case 0: condp = 4; Ip->type = stack_sprintf("[I*{%ld-0-0}] page 171",d/2); Ip->neron = shallowconcat(dicyclic(2,2),groupH(d/2)); break; case 1: switch(q) { case 0: condp = 2; Ip->type = stack_sprintf("[II*{%ld-0}] page 172",d/2); Ip->neron = cyclic(1); break; case 1: condp = 3; Ip->type = stack_sprintf("[II{%ld-0}] page 171",d/2); Ip->neron = cyclic(2*d); break; default: pari_err_BUG("tame2 [bug10]"); } break; default: pari_err_BUG("tame2 [bug11]"); } break; case 3: condp = 3; Ip->neron = cyclic(d); switch(r) { case 1: Ip->type = stack_sprintf("[II{%ld}-IV] page 175", (d-2)/3); break; case 2: Ip->type = stack_sprintf("[II{%ld}-IV*] page 175", (d-1)/3); break; default: pari_err_BUG("tame2 [bug12]"); } break; case 4: switch(r) { case 1: switch(q) { case 1: condp = 3; Ip->type = stack_sprintf("[II{%ld}-III] page 177",(d-2)/4); Ip->neron = cyclic(d/2); break; case 3: condp = 4; Ip->type = stack_sprintf("[II*{%ld}-III*] page 178",(d-2)/4); Ip->neron = cyclic(8); break; default: pari_err_BUG("tame2 [bug13]"); } break; case 3: switch(q) { case 1: condp = 4; Ip->type = stack_sprintf("[II*{%ld}-III] page 178",(d-2)/4); Ip->neron = cyclic(8); break; case 3: condp = 3; Ip->type = stack_sprintf("[II{%ld}-III*] page 178",(d-2)/4); Ip->neron = cyclic(d/2); break; default: pari_err_BUG("tame2 [bug14]"); } break; default: pari_err_BUG("tame2 [bug15]"); } break; case 6: switch(r) { case 2: condp = 4; Ip->type = stack_sprintf("[II*-II*{%ld}] page 176", (d-4)/6); Ip->neron = groupH((d+2)/6); break; case 4: condp = 4; Ip->type = stack_sprintf("[II-II*{%ld}] page 176", (d-2)/6); Ip->neron = groupH((d+4)/6); break; default: pari_err_BUG("tame2 [bug16]"); } break; default: pari_err_BUG("tame2 [bug17]"); } return condp; } /* Ip->tt = 3 */ static long tame_3(struct igusa *I, struct igusa_p *Ip) { long condp = -1, n, q, r, va5, d1, d2; long flc = tame_234_init(I, Ip, &n, &q, &r); GEN val = Ip->val; va5 = 2*val[6]-5*val[3]; d1 = minss(n * (val[7]-3*val[3]), n * va5 / 4); d2 = n * va5 / 2 - d1; switch(n) { case 1: condp = 2; Ip->type = stack_sprintf("[I{%ld-%ld-0}] page 179", d1,d2); Ip->neron = dicyclic(d1,d2); break; case 2: switch(r) { case 0: condp = 4; Ip->type = stack_sprintf("[I*{%ld-%ld-0}] page 180", d1/2,d2/2); Ip->neron = shallowconcat(groupH(d1/2),groupH(d2/2)); break; case 1: condp = 3; if (flc) { Ip->type = stack_sprintf("[2I{%ld}-0] page 181", d1); Ip->neron = cyclic(d1); } else { /* FIXME: "or" same with d1<->d2 */ Ip->type = stack_sprintf("[II{%ld-%ld}] page 182",d1/2,d2/2); Ip->neron = ((d1*d2-4)&7)? cyclic(2*d1): dicyclic(d1,2); } break; default: pari_err_BUG("tame3 [bug20]"); } break; case 4: condp = 4; Ip->type = stack_sprintf("[III{%ld}] page 182", d1/2); Ip->neron = groupH(d1/2); break; default: pari_err_BUG("tame3 [bug21]"); } return condp; } /* Ip->tt = 4 */ static long tame_4(struct igusa *I, struct igusa_p *Ip) { long condp = -1, d1,d2,d3, f1,f2, g, h, n, q, r, vl,vn,vm, e1,e2,e3; GEN val = Ip->val; (void)tame_234_init(I, Ip, &n, &q, &r); vl = val[6]-5*val[1]; vn = val[7]-6*val[1]; vm = val[2]-2*val[1]; /* all >= 0 */ e1 = min3(2*vl, 3*vn, 6*vm); e2 = minss(6*vl - e1, 12*vn - 2*e1); /* >= 0 */ e3 = 12*vl - (2*e1+e2); /* >= 0 */ d1 = e1*n / 6; d2 = e2*n / 12; d3 = e3*n / 12; g = d1*d2 + d1*d3 + d2*d3; h = ugcd(ugcd(d1,d2),d3); switch(n) { case 1: condp = 2; Ip->type = stack_sprintf("[I{%ld-%ld-%ld}] page 182",d1,d2,d3); Ip->neron = dicyclic(h,g/h); break; case 2: switch(r) { case 0: condp = 4; Ip->type = stack_sprintf("[I*{%ld-%ld-%ld}] page 183",d1/2,d2/2,d3/2); Ip->neron = shallowconcat(groupH(g/4), groupH(2-((h&2)>>1))); break; case 1: if (d1 == d2 || d1 == d3) f2 = d1; else if (d2 == d3) f2 = d2; else { pari_err_BUG("tame4 [bug23]"); return -1; /*LCOV_EXCL_LINE*/ } f1 = d1+d2+d3-2*f2; switch(q) { case 0: condp = 3; Ip->type = stack_sprintf("[II*{%ld-%ld}] page 184", f1/2,f2); Ip->neron = cyclic(f2); break; case 1: condp = 3; Ip->type = stack_sprintf("[II{%ld-%ld}] page 183", f1/2,f2); Ip->neron = cyclic(2*f1+f2); break; default: pari_err_BUG("tame4 [bug24]"); } break; default: pari_err_BUG("tame4 [bug25]"); } break; case 3: condp = 4; Ip->type = stack_sprintf("[III{%ld}] page 184",d1); Ip->neron = (d1%3)? cyclic(9): dicyclic(3,3); break; case 6: condp = 4; Ip->type = stack_sprintf("[III*{%ld}] page 184",d1/2); Ip->neron = cyclic(1); break; default: pari_err_BUG("tame4 [bug26]"); } return condp; } /* p = 3 */ static void tame_567_init_3(struct igusa_p *Ip, long dk, long *pd, long *pn, long *pdm, long *pr) { long n = 1 + Ip->r1/6; *pd = n * dk / 36; /* / (12*Ip->eps) */ *pn = n; *pr = -1; /* unused */ *pdm = 0; } /* (4.3) */ static void tame_567_init(struct igusa *I, struct igusa_p *Ip, long dk, long *pd, long *pn, long *pdm, long *pr) { long ndk, ddk; GEN p = Ip->p, val = Ip->val; if (equaliu(p,3)) { tame_567_init_3(Ip, dk, pd, pn, pdm, pr); return; } /* assume p > 3, Ip->eps = 1 */ ssQ_red(dk, 12, &ndk, &ddk); if (! odd(val[8])) { long va0 = myval(I->a0,p), va2 = myval(I->A2,p), va3 = myval(I->A3,p); long va5 = myval(I->A5,p), vb2 = myval(I->B2,p); long v1 = 2*va3-4*va0-val[1], v2 = 6*va5-20*va0-5*val[1]; long v3 = 3*vb2-2*va0-2*val[1], v4 = 10*vb2-2*va5-5*val[1]; if (v3 >= 0 && v2 >= 0 && v1 >= 0) { if (v1==0 || v2==0) get_nr(ddk, va0+val[1], 6,pn,pr); /* Prop 4.3.1 (a) */ else { /* Prop 4.3.1 (d) */ long v5 = myval(subii(mulii(I->A2,I->A3),mului(3,I->A5)),p); if (gequal0(I->A2)) pari_err_BUG("tame567 [bug27]"); get_nr(ddk, 12*va0 + min3(dk, 6*va3-9*va2, 4*v5 - 10*va2), 24, pn,pr); } } else if (v2 < 0 && v4 >= 0) get_nr(ddk, 2*va5+val[1], 8, pn,pr); /* Prop 4.3.1 (b) */ else /* (v3 < 0 && v4 < 0) */ get_nr(ddk, vb2, 4, pn,pr); /* Prop 4.3.1 (c) */ *pd = (*pn/ddk) * ndk; } else { *pr = ndk; *pn = 2*ddk; *pd = 2*ndk; } *pdm = umodsu(*pd, *pn); } static long tame_5(struct igusa *I, struct igusa_p *Ip) { long condp = -1, d, n, dm, r, dk; GEN val = Ip->val; dk = Ip->eps*val[6]-5*val[8]; tame_567_init(I, Ip, dk, &d, &n, &dm, &r); if (! odd(val[8])) { switch(n) { case 1: condp = 0; Ip->type = stack_sprintf("[I{0}-I{0}-%ld] page 158", d); Ip->neron = cyclic(1); break; case 2: switch(dm) { case 0: condp = 4; Ip->type = stack_sprintf("[I*{0}-I*{0}-%ld] page 158",(d-2)/2); Ip->neron = mkvecsmall4(2,2,2,2); break; case 1: condp = 2; Ip->type = stack_sprintf("[I{0}-I*{0}-%ld] page 159",(d-1)/2); Ip->neron = dicyclic(2,2); break; } break; case 3: switch(dm) { case 0: condp = 4; Ip->type = stack_sprintf("[IV-IV*-%ld] page 165",(d-3)/3); Ip->neron = dicyclic(3,3); break; case 1: switch(r) { case 0: case 1: condp = 2; Ip->type = stack_sprintf("[I{0}-IV-%ld] page 160",(d-1)/3); Ip->neron = cyclic(3); break; case 2: condp = 4; Ip->type = stack_sprintf("[IV*-IV*-%ld] page 166",(d-4)/3); Ip->neron = dicyclic(3,3); break; } break; case 2: switch(r) { case 0: case 2: condp = 2; Ip->type = stack_sprintf("[I{0}-IV*-%ld] page 160",(d-2)/3); Ip->neron = cyclic(3); break; case 1: condp = 4; Ip->type = stack_sprintf("[IV-IV-%ld] page 165",(d-2)/3); Ip->neron = dicyclic(3,3); break; } break; } break; case 4: switch(dm) { case 0: condp = 4; Ip->type = stack_sprintf("[III-III*-%ld] page 169",(d-4)/4); Ip->neron = dicyclic(2,2); break; case 1: switch(r) { case 0: case 1: condp = 2; Ip->type = stack_sprintf("[I{0}-III-%ld] page 161",(d-1)/4); Ip->neron = cyclic(2); break; case 2: case 3: condp = 4; Ip->type = stack_sprintf("[I*{0}-III*-%ld] page 162",(d-5)/4); Ip->neron = mkvecsmall3(2,2,2); break; } break; case 2: condp = 4; Ip->neron = dicyclic(2,2); switch(r) { case 1: Ip->type = stack_sprintf("[III-III-%ld] page 169",(d-2)/4); break; case 3: Ip->type = stack_sprintf("[III*-III*-%ld] page 169",(d-6)/4); break; default: pari_err_BUG("tame5 [bug29]"); } break; case 3: switch(r) { case 0: case 3: condp = 2; Ip->type = stack_sprintf("[I{0}-III*-%ld] page 162",(d-3)/4); Ip->neron = cyclic(2); break; case 1: case 2: condp = 4; Ip->type = stack_sprintf("[I*{0}-III-%ld] page 162",(d-3)/4); Ip->neron = mkvecsmall3(2,2,2); break; } break; } break; case 6: switch(dm) { case 0: condp = 4; Ip->type = stack_sprintf("[II-II*-%ld] page 163",(d-6)/6); Ip->neron = cyclic(1); break; case 1: switch(r) { case 0: case 1: condp = 2; Ip->type = stack_sprintf("[I{0}-II-%ld] page 159",(d-1)/6); Ip->neron = cyclic(1); break; case 2: case 5: condp = 4; Ip->type = stack_sprintf("[II*-IV-%ld] page 164",(d-7)/6); Ip->neron = cyclic(3); break; case 3: case 4: condp = 4; Ip->type = stack_sprintf("[I*{0}-IV*-%ld] page 161",(d-7)/6); Ip->neron = mkvecsmall2(6,2); break; } break; case 2: switch(r) { case 1: condp = 4; Ip->type = stack_sprintf("[II-II-%ld] page 163",(d-2)/6); Ip->neron = cyclic(1); break; case 3: case 5: condp = 4; Ip->type = stack_sprintf("[I*{0}-II*-%ld] page 160",(d-8)/6); Ip->neron = dicyclic(2,2); break; default: pari_err_BUG("tame5 [bug30]"); } break; case 3: Ip->neron = cyclic(3); switch(r) { case 1: case 2: condp = 4; Ip->type = stack_sprintf("[II-IV-%ld] page 164",(d-3)/6); break; case 4: case 5: condp = 4; Ip->type = stack_sprintf("[II*-IV*-%ld] page 164",(d-9)/6); break; default: pari_err_BUG("tame5 [bug31]"); } break; case 4: switch(r) { case 1: case 3: condp = 4; Ip->type = stack_sprintf("[I*{0}-II-%ld] page 160",(d-4)/6); Ip->neron = dicyclic(2,2); break; case 5: condp = 4; Ip->type = stack_sprintf("[II*-II*-%ld] page 163",(d-10)/6); Ip->neron = cyclic(1); break; default: pari_err_BUG("tame5 [bug32]"); } break; case 5: switch(r) { case 0: case 5: condp = 2; Ip->type = stack_sprintf("[I{0}-II*-%ld] page 160",(d-5)/6); Ip->neron = cyclic(1); break; case 1: case 4: condp = 4; Ip->type = stack_sprintf("[II-IV*-%ld] page 164",(d-5)/6); Ip->neron = cyclic(3); break; case 2: case 3: condp = 4; Ip->type = stack_sprintf("[I*{0}-IV-%ld] page 161",(d-5)/6); Ip->neron = mkvecsmall2(6,2); break; } break; default: pari_err_BUG("tame5 [bug33]"); } break; case 12: condp = 4; switch(dm) { case 1: switch(r) { case 3: case 10: Ip->type = stack_sprintf("[II*-III-%ld] page 166",(d-13)/12); Ip->neron = cyclic(2); break; case 4: case 9: Ip->type = stack_sprintf("[III*-IV-%ld] page 167",(d-13)/12); Ip->neron = cyclic(6); break; default: pari_err_BUG("tame5 [bug34]"); } break; case 5: switch(r) { case 2: case 3: Ip->type = stack_sprintf("[II-III-%ld] page 166",(d-5)/12); Ip->neron = cyclic(2); break; case 8: case 9: Ip->type = stack_sprintf("[III*-IV*-%ld] page 168",(d-17)/12); Ip->neron = cyclic(6); break; default: pari_err_BUG("tame5 [bug35]"); } break; case 7: switch(r) { case 3: case 4: Ip->type = stack_sprintf("[III-IV-%ld] page 167",(d-7)/12); Ip->neron = cyclic(6); break; case 9: case 10: Ip->type = stack_sprintf("[II*-III*-%ld] page 167",(d-19)/12); Ip->neron = cyclic(2); break; default: pari_err_BUG("tame5 [bug36]"); } break; case 11: switch(r) { case 3: case 8: Ip->type = stack_sprintf("[III-IV*-%ld] page 168",(d-11)/12); Ip->neron = cyclic(6); break; case 2: case 9: Ip->type = stack_sprintf("[II-III*-%ld] page 166",(d-11)/12); Ip->neron = cyclic(2); break; default: pari_err_BUG("tame5 [bug37]"); } break; default: pari_err_BUG("tame5 [bug38]"); } break; default: pari_err_BUG("tame5 [bug39]"); } } else { r %= (n >> 1); switch(n) { case 2: condp = 2; Ip->type = stack_sprintf("[2I{0}-%ld] page 159",(d/2)); Ip->neron = cyclic(1); break; case 4: condp = 4; Ip->type = stack_sprintf("[2I*{0}-%ld] page 159",(d/2-1)/2); Ip->neron = dicyclic(2,2); break; case 6: condp = 4; Ip->neron = cyclic(3); switch(r) { case 1: Ip->type = stack_sprintf("[2IV-%ld] page 165",(d/2-1)/3); break; case 2: Ip->type = stack_sprintf("[2IV*-%ld] page 165",(d/2-2)/3); break; default: pari_err_BUG("tame5 [bug40]"); } break; case 8: condp = 4; Ip->neron = cyclic(2); switch(r) { case 1: Ip->type = stack_sprintf("[2III-%ld] page 168",(d/2-1)/4); break; case 3: Ip->type = stack_sprintf("[2III*-%ld] page 168",(d/2-3)/4); break; default: pari_err_BUG("tame5 [bug41]"); } break; case 12: condp = 4; Ip->neron = cyclic(1); switch(r) { case 1: Ip->type = stack_sprintf("[2II-%ld] page 162",(d/2-1)/6); break; case 5: Ip->type = stack_sprintf("[2II*-%ld] page 163",(d/2-5)/6); break; default: pari_err_BUG("tame5 [bug42]"); } break; default: pari_err_BUG("tame5 [bug43]"); } } return condp; } static long tame_6(struct igusa *I, struct igusa_p *Ip) { long condp = -1, d, d1, n, dm, r, dk; GEN val = Ip->val; dk = Ip->eps*val[7]-6*val[8]; tame_567_init(I, Ip, dk, &d, &n, &dm, &r); d1 = n * (Ip->eps*(val[6]-val[7])+val[8]) / Ip->eps; switch(n) { case 1: condp = 1; Ip->type = stack_sprintf("[I{0}-I{%ld}-%ld] page 170",d1,d); Ip->neron = cyclic(d1); break; case 2: switch(dm) { case 0: condp = 4; Ip->type=stack_sprintf("[I*{0}-I*{%ld}-%ld] page 171", d1/2,(d-2)/2); Ip->neron = shallowconcat(groupH(d1/2), dicyclic(2,2)); break; case 1: return -1; default: pari_err_BUG("tame6 [bug44]"); } break; case 3: condp = 3; Ip->neron = dicyclic(3,d1/3); switch(dm) { case 1: Ip->type = stack_sprintf("[I{%ld}-IV-%ld] page 173",d1/3,(d-1)/3); break; case 2: Ip->type = stack_sprintf("[I{%ld}-IV*-%ld] page 173",d1/3,(d-2)/3); break; default: pari_err_BUG("tame6 [bug45]"); } break; case 4: switch(dm) { case 1: switch(r) { case 0: case 1: condp = 3; Ip->type=stack_sprintf("[I{%ld}-III-%ld] page 176",d1/4,(d-1)/4); Ip->neron = dicyclic(2,d1/4); break; case 2: case 3: condp = 4; Ip->type=stack_sprintf("[I*{%ld}-III*-%ld] page 177",d1/4,(d-5)/4); Ip->neron = shallowconcat(groupH(d1/4), cyclic(2)); break; default: pari_err_BUG("tame6 [bug46]"); } break; case 3: switch(r) { case 0: case 3: condp = 3; Ip->type=stack_sprintf("[I{%ld}-III*-%ld] page 176",d1/4,(d-3)/4); Ip->neron = dicyclic(2,d1/4); break; case 1: case 2: condp = 4; Ip->type=stack_sprintf("[I*{%ld}-III-%ld] page 177",d1/4,(d-3)/4); Ip->neron = shallowconcat(groupH(d1/4), cyclic(2)); break; default: pari_err_BUG("tame6 [bug47]"); } break; default: pari_err_BUG("tame6 [bug48]"); } break; case 6: switch(dm) { case 1: switch(r) { case 0: case 1: condp = 3; Ip->type = stack_sprintf("[I{%ld}-II-%ld] page 172",d1/6,(d-1)/6); Ip->neron = cyclic(d1/6); break; case 3: case 4: condp = 4; Ip->type=stack_sprintf("[I*{%ld}-IV*-%ld] page 174",d1/6,(d-7)/6); Ip->neron = shallowconcat(groupH(d1/6), cyclic(3)); break; default: pari_err_BUG("tame6 [bug49]"); } break; case 2: condp = 4; Ip->type = stack_sprintf("[I*{%ld}-II*-%ld] page 174",d1/6,(d-8)/6); Ip->neron = groupH(d1/6); break; case 4: condp = 4; Ip->type = stack_sprintf("[I*{%ld}-II-%ld] page 173",d1/6,(d-4)/6); Ip->neron = groupH(d1/6); break; case 5: switch(r) { case 0: case 5: condp = 3; Ip->type=stack_sprintf("[I{%ld}-II*-%ld] page 172",d1/6,(d-5)/6); Ip->neron = cyclic(d1/6); break; case 2: case 3: condp = 4; Ip->type=stack_sprintf("[I*{%ld}-IV-%ld] page 174",d1/6,(d-5)/6); Ip->neron = shallowconcat(groupH(d1/6), cyclic(3)); break; default: pari_err_BUG("tame6 [bug50]"); } break; default: pari_err_BUG("tame6 [bug51]"); } break; default: pari_err_BUG("tame6 [bug52]"); } return condp; } static long tame_7(struct igusa *I, struct igusa_p *Ip) { long condp = -1, d, D, d1, d2, n, dm, r, dk; GEN val = Ip->val; dk = 3*(Ip->eps*val[3]-2*val[8]); tame_567_init(I, Ip, dk, &d, &n, &dm, &r); D = n * (Ip->eps*(val[6]-3*val[3])+val[8]) / Ip->eps; d1 = minss(n * (val[7]-3*val[3]), D/2); d2 = D - d1; /* d1 <= d2 */ switch(n) { case 1: condp = 2; Ip->type = stack_sprintf("[I{%ld}-I{%ld}-%ld] page 179",d1,d2,d); Ip->neron = dicyclic(d1,d2); break; case 2: if (odd(val[8])) { condp = 3; Ip->type = stack_sprintf("[2I{%ld}-%ld] page 181",d1,d/2); Ip->neron = cyclic(d1); } else if (dm == 0) { condp = 4; Ip->type = stack_sprintf("[I*{%ld}-I*{%ld}-%ld] page 180", d1/2,d2/2,(d-2)/2); Ip->neron = shallowconcat(groupH(d1/2),groupH(d2/2)); } else { GEN H; if (d1 != d2) return -1; condp = 3; H = groupH(d1/2); Ip->type = stack_sprintf("[I{%ld}-I*{%ld}-%ld] page 180", d1/2,d1/2,(d-1)/2); Ip->neron = shallowconcat(H, H); } break; case 4: condp = 4; Ip->type = stack_sprintf("[2I*{%ld}-%ld] page 181",d1/2,(d-2)/4); Ip->neron = groupH(d1/2); break; default: pari_err_BUG("tame7 [bug55]"); } return condp; } static long labelm3(GEN polh, long t60, long alpha, long Dmin, struct igusa *I, struct igusa_p *Ip); static long tame(GEN polh, long t60, long alpha, long Dmin, struct igusa *I, struct igusa_p *Ip) { long d; Ip->tame = 1; switch(Ip->tt) { case 1: return tame_1(I,Ip); case 2: return tame_2(I,Ip); case 3: return tame_3(I,Ip); case 4: return tame_4(I,Ip); case 5: return tame_5(I,Ip); case 6: d = tame_6(I,Ip); break; default:d = tame_7(I,Ip); break; } if (d < 0) d = labelm3(polh,t60,alpha,Dmin,I,Ip); /* => tt=6 or 7 */ return d; } /* maxc = maximum conductor valuation at p */ static long get_maxc(GEN p) { switch (itos_or_0(p)) { case 2: return 20; break; case 3: return 10; break; case 5: return 9; break; default: return 4; break; /* p > 5 */ } } /* p = 3 */ static long quartic(GEN polh, long alpha, long Dmin, struct igusa_p *Ip) { GEN val = Ip->val, p = Ip->p; GEN polf = polymini_zi2(ZX_Z_mul(polh, powiu(p, alpha))); long condp = -1, d, R, r1, beta; r1 = polf[1]; beta = polf[2]; R = beta/2; switch(Ip->tt) { case 1: case 5: d = 0;break; case 3: d = val[6] - 5*val[3]/2;break; case 7: d = val[6] - 3*val[3] + val[8]/Ip->eps;break; default: pari_err_BUG("quartic [type choices]"); d = 0; /*LCOV_EXCL_LINE*/ } switch(r1) { case 0: if (d) { condp = 3; Ip->type = stack_sprintf("[2I{%ld}-%ld] page 181",d,R); Ip->neron = cyclic(d); } else { condp = 2; Ip->neron = cyclic(1); if (R) Ip->type = stack_sprintf("[2I{0}-%ld] page 159",R); else Ip->type = "[II] page 155"; } break; case 6: condp = 4; Ip->type = stack_sprintf("[2I*{%ld}-%ld] pages 159, 181",d,R); Ip->neron = dicyclic(2,2); break; case 3: condp = 4; Ip->type = stack_sprintf("[2III-%ld] page 168",R); Ip->neron = cyclic(2); break; case 9: condp = 4; Ip->type = stack_sprintf("[2III*-%ld] page 168",R); Ip->neron = cyclic(2); break; case 2: condp = Dmin-12*R-13; Ip->type = stack_sprintf("[2II-%ld] page 162",R); Ip->neron = cyclic(1); break; case 8: condp = Dmin-12*R-19; Ip->type = stack_sprintf("[2IV*-%ld] page 165",R); Ip->neron = cyclic(3); break; case 4: condp = Dmin-12*R-15; Ip->type = stack_sprintf("[2IV-%ld] page 165",R); Ip->neron = cyclic(3); break; case 10: condp = Dmin-12*R-21; Ip->type = stack_sprintf("[2II*-%ld] page 163",R); Ip->neron = cyclic(1); break; default: pari_err_BUG("quartic [type1]"); } if (condp > get_maxc(p) || condp < 0) pari_err_BUG("quartic [conductor]"); return condp; } static long litredtp(long alpha, long alpha1, long t60, long t60_1, GEN polh, GEN polh1, long Dmin, long R, struct igusa *I, struct igusa_p *Ip) { GEN val = Ip->val, p = Ip->p; long condp = -1, indice, d; if ((Ip->r1 == 0||Ip->r1 == 6) && (Ip->r2 == 0||Ip->r2 == 6)) { /* (r1,r2) = (0,0), (0,6), (6,0) or (6,6) */ if (Ip->tt == 5) { switch(Ip->r1 + Ip->r2) { case 0: /* (0,0) */ condp = 0; Ip->type = stack_sprintf("[I{0}-I{0}-%ld] page 158",R); Ip->neron = cyclic(1); break; case 6: /* (0,6) or (6,0) */ condp = 2; Ip->type = stack_sprintf("[I{0}-I*{0}-%ld] page 159",R); Ip->neron = dicyclic(2,2); break; case 12: /* (6,6) */ condp = 4; Ip->type = stack_sprintf("[I*{0}-I*{0}-%ld] page 158",R); Ip->neron = mkvecsmall4(2,2,2,2); break; } return condp; } if (Ip->r1 == Ip->r2) return tame(polh, t60, alpha, Dmin, I, Ip); if (Ip->tt == 6) { d = val[6] - val[7] + val[8]/Ip->eps; if (Ip->r1 && alpha1 == 0) polh1 = ZX_unscale_divpow(polh1, p, 3); if (FpX_is_squarefree(FpX_red(polh1,p),p)) { indice = 0; condp = 3-Ip->r2/6; } else { indice = d; condp = 3-Ip->r1/6; } } else { /* Ip->tt == 7 */ long d1; d = val[6] - 3*val[3] + val[8]/Ip->eps; if (t60_1 == 60) polh1 = ZX_unscale_divpow(polh1, p, 3); d1 = minss(val[7]-3*val[3],d/2); if (d == 2*d1) indice = d1; else { indice = discpart(polh1,p,d1+1); if (indice>= d1+1) indice = d-d1; else indice = d1; } condp = 3; } if (Ip->r1) indice = d - indice; /* (r1,r2) = (6,0) */ Ip->neron = shallowconcat(cyclic(indice),groupH(d-indice)); Ip->type = stack_sprintf("[I{%ld}-I*{%ld}-%ld] page %ld", indice,d-indice,R, (Ip->tt==6)? 170L: 180L); return condp; } if (Ip->tt == 7) pari_err_BUG("litredtp [switch ri]"); { struct red __S1, __S2, *S1 = &__S1, *S2 = &__S2; long f1 = get_red(S1, Ip, polh1, p, alpha1, Ip->r1); long f2 = get_red(S2, Ip, polh, p, alpha, Ip->r2); /* reorder to normalize representation */ if (S1->tnum > S2->tnum || (S1->tnum == S2->tnum && f1 > f2)) { struct red *S = S1; S1 = S2; S2 = S; } Ip->type = stack_sprintf("[%s-%s-%ld] pages %s", S1->t,S2->t, R, S1->pages); Ip->neron = shallowconcat(S1->g, S2->g); condp = Dmin - (f1 + f2) + ((R >= 0)? 2-12*R: 4); } if (condp > get_maxc(p)) pari_err_BUG("litredtp [conductor]"); return condp; } static long labelm3(GEN h1, long t60_1, long alpha1, long Dmin, struct igusa *I, struct igusa_p *Ip) { GEN h, pm, vs, val = Ip->val, p = Ip->p; long alpha, t60, lambda, beta, R; pm = polymini(ZX_Z_mul(RgX_recip6(h1), powiu(p,alpha1)), p); h = gel(pm,1); vs = gel(pm,2); lambda= vs[1]; t60 = vs[2]; alpha = vs[3]; beta = vs[5]; if (lambda != 3) pari_err_BUG("labelm3 [lambda != 3]"); R = beta-(alpha1+alpha); if (odd(R)) pari_err_BUG("labelm3 [R odd]"); R /= 2; if (R <= -2) pari_err_BUG("labelm3 [R <= -2]"); if (val[8] % (2*Ip->eps)) pari_err_BUG("labelm3 [val(eps2)]"); if (R >= 0 && (alpha+alpha1) >= 1) pari_err_BUG("labelm3 [minimal equation]"); Ip->r1 = t60_1 / 10 + 6*alpha1; Ip->r2 = t60 / 10 + 6*alpha; return litredtp(alpha, alpha1, t60, t60_1, h, h1, Dmin, R, I, Ip); } /* p = 3 */ static long quadratic(GEN polh, long alpha, long Dmin, struct igusa *I, struct igusa_p *Ip) { long alpha1 = alpha, beta, t6, R; GEN vs = polymini_zi(ZX_Z_mul(polh, powiu(Ip->p,alpha))); t6 = vs[1]; alpha = vs[2]; beta = vs[3]; R = beta-alpha; if (R >= 0 && alpha1) { Dmin -= 10; if (DEBUGLEVEL) err_printf("(Care: minimal discriminant over Z[i] smaller than over Z)\n"); } Ip->r2 = Ip->r1 = t6 + 6*alpha; return litredtp(alpha, alpha, t6*10, t6*10, polh, polh, Dmin, R, I, Ip); } static long genus2localred(struct igusa *I, struct igusa_p *Ip, GEN p, GEN polmini) { GEN val, vs, polh, list, c1, c2, c3, c4, c5, c6, prod; long i, vb5, vb6, d, Dmin, alpha, lambda, t60; long condp = -1, indice, vc6, mm, nb, dism; stable_reduction(I, Ip, p); val = Ip->val; Dmin = val[6]; if (Dmin == 0) { Ip->tame = 1; Ip->type = "[I{0-0-0}] page 155"; Ip->neron = cyclic(1); return 0; } if (Dmin == 1) { Ip->type = "[I{1-0-0}] page 170"; Ip->neron = cyclic(1); return 1; } if (Dmin == 2) switch(Ip->tt) { case 2: Ip->type = "[I{2-0-0}] page 170"; Ip->neron = cyclic(2); return 1; case 3: Ip->type = "[I{1-1-0}] page 179"; Ip->neron = cyclic(1); return 2; case 5: if (cmpis(p,3) <= 0) pari_err_BUG("genus2localred [tt 1]"); Ip->type = "[I{0}-II-0] page 159"; Ip->neron = cyclic(1); return 2; default: pari_err_BUG("genus2localred [tt 2]"); } if (absequaliu(p,2)) return -1; polh = gel(polmini,1); vs = gel(polmini,2); lambda = vs[1]; t60 = vs[2]; alpha = vs[3]; if (vs[4]) return equaliu(p,3)? quadratic(polh, alpha, Dmin, I, Ip): tame(polh, t60, alpha, Dmin, I, Ip); if (!t60 && lambda<= 2) { if (Ip->tt >= 5) pari_err_BUG("genus2localred [tt 3]"); return tame(polh, t60, alpha, Dmin, I, Ip); } if (Dmin == 3) { switch(Ip->tt) { case 2: return tame(polh, t60, alpha, Dmin, I, Ip); case 3: Ip->type = "[I{2-1-0}] page 179"; Ip->neron = cyclic(2); return 2; case 4: Ip->type = "[I{1-1-1}] page 182"; Ip->neron = cyclic(3); return 2; case 5: if (equaliu(p,3) && t60 != 30) return labelm3(polh,t60,alpha,Dmin,I,Ip); Ip->type = "[I{0}-III-0] page 161"; Ip->neron = cyclic(2); return 2; case 6: if (equaliu(p,3)) pari_err_BUG("genus2localred [conductor]"); Ip->type = "[I{1}-II-0] page 172"; Ip->neron = cyclic(1); return 3; } pari_err_BUG("genus2localred [switch tt 4]"); return -1; /* LCOV_EXCL_LINE */ } switch(lambda) { case 0: switch(t60+alpha) { case 10: condp = Dmin-1; Ip->type = "[V] page 156"; Ip->neron = cyclic(3); break; case 11: condp = Dmin-11; Ip->type = "[V*] page 156"; Ip->neron = cyclic(3); break; case 12: condp = Dmin-2; Ip->type = "[IX-2] page 157"; Ip->neron = cyclic(5); break; case 13: condp = Dmin-12; Ip->type = "[VIII-4] page 157"; Ip->neron = cyclic(1); break; case 24: condp = Dmin-8; Ip->type = "[IX-4] page 158"; Ip->neron = cyclic(5); break; case 15: case 16: if (Ip->tt>= 5) pari_err_BUG("genus2localred [tt 6]"); return tame(polh, t60, alpha, Dmin, I, Ip); case 20: case 21: { GEN b0, b1, b2, b3, b4, b5, b6, b02, b03, b04, b05; RgX_to_06(polh, &b0,&b1,&b2,&b3,&b4,&b5,&b6); vb5 = myval(b5,p); vb6 = myval(b6,p); if (vb6 >= 3) { if (vb5 < 2) pari_err_BUG("genus2localred [red1]"); if (vb5 >= 3) { condp = Dmin-8; Ip->type = "[II*-IV-(-1)] page 164"; Ip->neron = cyclic(3); } else { condp = Dmin-7; Ip->type = "[IV-III*-(-1)] page 167"; Ip->neron = cyclic(6); } break; } if (dvdii(b0,p)) pari_err_BUG("genus2localred [b0]"); b02 = gsqr(b0); b03 = gmul(b02, b0); b04 = gmul(b03, b0); b05 = gmul(b04, b0); c1 = gmul2n(b1,-1); c2 = gmul2n(gsub(gmul(b0,b2), gsqr(c1)),-1); c3 = gmul2n(gsub(gmul(b02,b3), gmul2n(gmul(c1,c2),1)),-1); c4 = gsub(gmul(b03,b4), gadd(gmul2n(gmul(c1,c3),1),gsqr(c2))); c5 = gsub(gmul(b04,b5), gmul2n(gmul(c2,c3),1)); c6 = gsub(gmul(b05,b6), gsqr(c3)); /* b0^5*H(x/b0) = (x^3+c1*x^2+c2*x+c3)^2+c4*x^2+c5*x+c6 */ vc6 = myval(c6,p); if (vc6 == 2) { if (alpha) { condp = Dmin-16; Ip->type = "[IV] page 155"; Ip->neron = cyclic(1); } else { condp = Dmin-6; Ip->type = "[III] page 155"; Ip->neron = dicyclic(3,3); } } else { if (myval(c3,p) > 1) pari_err_BUG("genus2localred [c3]"); mm = min3(3*myval(c4,p)-4, 3*myval(c5,p)-5, 3*vc6-6); if (alpha) { condp = Dmin-mm-16; Ip->type = stack_sprintf("[III*{%ld}] page 184", mm); Ip->neron = cyclic(1); } else { condp = Dmin-mm-6; Ip->type = stack_sprintf("[III{%ld}] page 184", mm); Ip->neron = (mm%3)? cyclic(9): dicyclic(3,3); } } } break; case 30: return equaliu(p,3)? quartic(polh, alpha, Dmin, Ip) : tame(polh, t60, alpha, Dmin, I, Ip); default: pari_err_BUG("genus2localred [red2]"); } break; case 1: switch(t60+alpha) { case 12: condp = Dmin; Ip->type = "[VIII-1] page 156"; Ip->neron = cyclic(1); break; case 13: condp = Dmin-10; Ip->type = "[IX-3] page 157"; Ip->neron = cyclic(5); break; case 24: condp = Dmin-4; Ip->type = "[IX-1] page 157"; Ip->neron = cyclic(5); break; case 25: condp = Dmin-14; Ip->type = "[VIII-3] page 157"; Ip->neron = cyclic(1); break; case 36: condp = Dmin-8; Ip->type = "[VIII-2] page 157"; Ip->neron = cyclic(1); break; case 15: condp = Dmin-1; Ip->type = "[VII] page 156"; Ip->neron = cyclic(2); break; case 16: condp = Dmin-11; Ip->type = "[VII*] page 156"; Ip->neron = cyclic(2); break; case 20: if (cmpis(p,3)) { d = 6*val[6]-5*val[7]-2; if (d%6) pari_err_BUG("genus2localred [index]"); dism = (d/6); } else { list = padicfactors(polh,p,Dmin-5); nb = lg(list); prod = pol_1(varn(polh)); for(i = 1;i 2) pari_err_BUG("genus2localred [padicfactors]"); dism = valp(RgX_disc(prod)) - 1; } condp = Dmin-dism-3; Ip->type = stack_sprintf("[II-II*{%ld}] page 176", dism); Ip->neron = groupH(dism+1); break; case 21: vb6 = myval(RgX_coeff(polh,0),p); if (vb6<2) pari_err_BUG("genus2localred [red3]"); condp = Dmin-14; Ip->type = "[IV*-II{0}] page 175"; Ip->neron = cyclic(1); break; case 30: vb5 = myval(RgX_coeff(polh,1),p); if (vb5 == 2) { if (Ip->tt >= 5) pari_err_BUG("genus2localred [tt 6]"); return tame(polh, t60, alpha, Dmin, I, Ip); } condp = Dmin-7; Ip->type = "[II*-III-(-1)] page 167"; Ip->neron = cyclic(2); break; } break; case 2: if (ugcd(t60, 60) == 15) /* denom(theta) = 4 */ { if (Ip->tt>4) pari_err_BUG("genus2localred [tt 5]"); return tame(polh, t60, alpha, Dmin, I, Ip); } if (!equaliu(p,3) && ugcd(t60, 60) == 20) /* denom(theta) = 3 */ return tame(polh, t60, alpha, Dmin, I, Ip); list = padicfactors(polh,p,Dmin-10*alpha); nb = lg(list); prod = pol_1(varn(polh)); for(i = 1;itype = stack_sprintf("[IV-II{%ld}] page 175", dism); Ip->neron = cyclic(3*dism+2); break; case 1: condp = Dmin-dism-10; Ip->type = stack_sprintf("[II*-II*{%ld}] page 176",dism); Ip->neron = groupH(dism+1); break; case 2: case 3: if (myval(RgX_coeff(polh,0),p) == 2) { if (Ip->tt>4) pari_err_BUG("genus2localred [tt 5]"); return tame(polh, t60, alpha, Dmin, I, Ip); } dism++; indice = val[6]-(5*val[3]/2)-dism; condp = Dmin-dism-indice-2; Ip->type = stack_sprintf("[II{%ld-%ld}] page 182", dism,indice); Ip->neron = both_odd(dism,indice)? dicyclic(2,2*dism): cyclic(4*dism); break; case 4: condp = Dmin-dism-5; Ip->type = stack_sprintf("[IV*-II{%ld}] page 175",dism+1); Ip->neron = cyclic(3*dism+4); break; } break; case 3: if (!equaliu(p,3) || Ip->tt <= 4) return tame(polh, t60, alpha, Dmin, I, Ip); return labelm3(polh,t60,alpha,Dmin,I,Ip); /* p = 3 */ default: pari_err_BUG("genus2localred [switch lambda]"); } if (condp < 2 || condp > get_maxc(p)) pari_err_BUG("genus2localred [conductor]"); return condp; } static GEN hyperellintegralmodel(GEN PQ) { GEN D; PQ = Q_remove_denom(PQ, &D); if (!D) return PQ; if (typ(PQ)==t_POL) return gmul(PQ,D); if (typ(PQ) == t_VEC && lg(PQ) == 3) return mkvec2(gmul(gel(PQ,1),D), gel(PQ,2)); pari_err_TYPE("hyperellintegralmodel",PQ); return NULL; /* LCOV_EXCL_LINE */ } /* P,Q are ZX, study Y^2 + Q(X) Y = P(X) */ GEN genus2red(GEN PQ, GEN p) { pari_sp av = avma; struct igusa I; GEN P, Q; GEN j22, j42, j2j6, a0,a1,a2,a3,a4,a5,a6, V,polr,facto,factp, vecmini, cond; long i, l, dd; PQ = hyperellminimalmodel(hyperellintegralmodel(PQ), NULL, p ? mkvec(p): p); P = gel(PQ,1); Q = gel(PQ,2); if (p && typ(p) != t_INT) pari_err_TYPE("genus2red", p); polr = ZX_add(ZX_sqr(Q), gmul2n(P,2)); /* ZX */ switch(degpol(polr)) { case 5: case 6: break; default: pari_err_DOMAIN("genus2red","genus","!=", gen_2,mkvec2(P,Q)); } RgX_to_03(polr, &a0,&a1,&a2,&a3); I.j10 = !signe(a0)? mulii(sqri(a1), ZX_disc(polr)): ZX_disc(polr); if (!signe(I.j10)) pari_err_DOMAIN("genus2red","genus","<",gen_2,mkvec2(P,Q)); I.j10 = gmul2n(I.j10, -12); /* t_INT */ if (p == NULL) { facto = absZ_factor(I.j10); factp = gel(facto,1); } else { factp = mkcol(p); facto = mkmat2(factp, mkcol(gen_1)); } l = lg(factp); vecmini = cgetg(l, t_COL); for(i = 1; i= 0) N = zv_snf(Ip.neron); if (DEBUGLEVEL) { if (!p) err_printf("p = %Ps\n", q); err_printf("(potential) stable reduction: %Ps\n", Ip.stable); if (f >= 0) { err_printf("reduction at p: %s, %Ps", Ip.type, N); err_printf(", f = %ld\n", f); } } red = f >= 0? mkvec2(strtoGENstr(Ip.type), N): cgetg(1, t_VEC); gel(V, i) = mkvec3(q, Ip.stable, red); } if (p) V = gel(V,1); cond = factorback(facto); /* remove denominator 2 coming from f = -1 in genuslocalred(, p = 2) */ if (typ(cond) != t_INT) cond = gel(cond,1); return gerepilecopy(av, mkvec4(cond, facto, PQ, V)); } pari-2.17.2/src/modules/mpqs.h0000644000175000017500000004157714760123736014603 0ustar billbill/* - debug support */ #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 /* - non-configurable sizing parameters */ /* 'large primes' must be smaller than min(MPQS_LP_BOUND, largest_FB_p) */ #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 */ /* - structures, types, and constants */ /* -- reasonably-sized integers */ #ifdef LONG_IS_64BIT typedef int mpqs_int32_t; typedef unsigned int mpqs_uint32_t; #else typedef long mpqs_int32_t; typedef ulong mpqs_uint32_t; #endif /* -- 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 { /* the prime p, the two arith. prog. mod p, sqrt(kN) mod p */ mpqs_int32_t __p, __start1, __start2, __sqrt_kN; float __flogp; /* log(p) as a 4-byte float */ 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_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: */ #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 */ /* TODO (tentative): one bit to mark normal FB primes, * one to mark the factors of k, * one to mark primes used in sieving, * later maybe one to mark primes of which we'll be tracking the square, * one to mark primes currently in use for A; * once we segment the FB, one bit marking the members of the first segment */ /* -- multiplier k and attached quantities */ typedef struct mpqs_multiplier { mpqs_uint32_t k; /* the multiplier (odd, squarefree) */ mpqs_uint32_t omega_k; /* number (0, 1 or 2) of primes dividing k */ mpqs_uint32_t kp[2]; /* prime factors of k, if any */ } mpqs_multiplier_t; #define MPQS_POSSIBLE_MULTIPLIERS 15 /* how many values for k we'll try */ /* following must be in range of the cand_multipliers table below */ 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[MPQS_I(i)].fbe_p) #define MPQS_LP(i) (FB[MPQS_I(i)].fbe_flogp) #define MPQS_SQRT(i) (FB[MPQS_I(i)].fbe_sqrt_kN) #define MPQS_FLG(i) (FB[MPQS_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 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 attached 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 to keep track of everything used through one factorization * attempt. The order of the fields is determined by keeping most frequently * used stuff near the beginning. */ typedef struct mpqs_handle { /* pointers */ 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 */ 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 */ GEN N, kN; /* number to be factored, with multiplier */ GEN A, B; /* leading, middle coefficient */ 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 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 */ /* further sizing parameters: */ mpqs_int32_t target_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 */ /* subscripts determining where to pick primes for A */ /* FIXME: lp_bound might have to be mpqs_int64_t ? */ long lp_bound; /* cutoff for Large Primes */ long digit_size_kN; const mpqs_multiplier_t *_k; /* multiplier k and attached 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 */ /* 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 */ /* For "tolerance", see 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 separate (smaller) primes used for normal * XXX sieving from larger ones used with transaction buffers * XXX (and the locate_A_range and attached 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 */ 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 */ } 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 */ { /*9*/ 0.8, 1, 350, 19, 3, 5}, { /*10*/ 0.8, 1, 300, 23, 3, 5}, { /*11*/ 0.8, 1, 1000, 27, 3, 5}, { /*12*/ 0.8, 1, 1100, 27, 3, 5}, { /*13*/ 0.8, 1, 1400, 31, 3, 5}, { /*14*/ 0.8, 1, 2200, 33, 3, 5}, { /*15*/ 0.8, 1, 2300, 39, 3, 5}, { /*16*/ 0.8, 1, 2900, 43, 3, 5}, { /*17*/ 0.8, 1, 3200, 51, 3, 5}, { /*18*/ 0.8, 1, 2800, 55, 3, 5}, { /*19*/ 0.8, 1, 3400, 65, 3, 5}, { /*20*/ 0.8, 1, 3400, 71, 3, 5}, { /*21*/ 0.8, 1, 5400, 90, 3, 5}, { /*22*/ 0.8, 1, 5700, 95, 3, 5}, { /*23*/ 0.8, 1, 5700, 110, 3, 5}, { /*24*/ 0.8, 1, 6000, 130, 4, 7}, { /*25*/ 0.8, 1, 6500, 140, 4, 7}, { /*26*/ 0.9, 1, 9000, 160, 4, 7}, { /*27*/ 1.12, 1, 10000, 160, 4, 7}, { /*28*/ 1.17, 1, 13000, 180, 4, 11}, { /*29*/ 1.22, 1, 14000, 220, 4, 11}, { /*30*/ 1.30, 1, 13000, 240, 4, 11}, { /*31*/ 1.33, 1, 11000, 240, 4, 13}, { /*32*/ 1.36, 1, 14000, 300, 5, 13}, { /*33*/ 1.40, 1, 15000, 340, 5, 13}, { /*34*/ 1.43, 1, 15000, 380, 5, 17}, { /*35*/ 1.48, 30, 15000, 380, 5, 17}, { /*36*/ 1.53, 45, 16000, 440, 5, 17}, { /*37*/ 1.60, 60, 15000, 420, 6, 19}, { /*38*/ 1.66, 70, 15000, 520, 6, 19}, { /*39*/ 1.69, 80, 16000, 540, 6, 23}, /* around here, the largest prime in FB becomes comparable to M in size */ { /*40*/ 1.69, 80, 16000, 600, 6, 23}, { /*41*/ 1.69, 80, 16000, 700, 6, 23}, { /*42*/ 1.69, 80, 24000, 900, 6, 29}, { /*43*/ 1.69, 80, 26000, 1000, 6, 29}, { /*44*/ 1.69, 80, 18000, 1100, 7, 31}, { /*45*/ 1.69, 80, 20000, 1200, 7, 31}, { /*46*/ 1.69, 80, 22000, 1300, 7, 37}, { /*47*/ 1.69, 80, 24000, 1400, 7, 37}, { /*48*/ 1.69, 80, 24000, 1600, 7, 37}, { /*49*/ 1.72, 80, 28000, 1900, 7, 41}, { /*50*/ 1.75, 80, 36000, 2100, 7, 41}, { /*51*/ 1.80, 80, 32000, 2100, 7, 43}, { /*52*/ 1.85, 80, 44000, 2300, 7, 43}, { /*53*/ 1.90, 80, 44000, 2600, 7, 47}, { /*54*/ 1.95, 80, 40000, 2700, 7, 47}, { /*55*/ 1.95, 80, 48000, 3200, 7, 53}, { /*56*/ 1.95, 80, 56000, 3400, 7, 53}, { /*57*/ 2.00, 80, 40000, 3000, 8, 53}, { /*58*/ 2.05, 80, 64000, 3400, 8, 59}, { /*59*/ 2.10, 80, 64000, 3800, 8, 59}, { /*60*/ 2.15, 80, 80000, 4300, 8, 61}, { /*61*/ 2.20, 80, 80000, 4800, 8, 61}, { /*62*/ 2.25, 80, 80000, 4600, 8, 67}, { /*63*/ 2.39, 80, 80000, 4800, 8, 67}, { /*64*/ 2.30, 80, 88000, 5400, 8, 67}, { /*65*/ 2.31, 80, 120000, 6600, 8, 71}, { /*66*/ 2.32, 80, 120000, 6800, 8, 71}, { /*67*/ 2.33, 80, 144000, 7600, 8, 73}, { /*68*/ 2.34, 80, 144000, 9000, 8, 73}, { /*69*/ 2.35, 80, 160000, 9500, 8, 79}, { /*70*/ 2.36, 80, 176000, 10500, 8, 79}, { /*71*/ 2.37, 80, 240000, 11000, 9, 79}, { /*72*/ 2.38, 80, 240000, 12500, 9, 83}, { /*73*/ 2.41, 80, 240000, 13000, 9, 83}, { /*74*/ 2.46, 80, 256000, 13250, 9, 83}, { /*75*/ 2.51, 80, 256000, 14500, 9, 89}, { /*76*/ 2.56, 80, 256000, 15250, 9, 89}, { /*77*/ 2.58, 80, 320000, 17000, 9, 89}, { /*78*/ 2.60, 80, 320000, 18000, 9, 89}, { /*79*/ 2.63, 80, 320000, 19500, 9, 97}, { /*80*/ 2.65, 80, 448000, 21000, 9, 97}, { /*81*/ 2.72, 80, 448000, 22000, 9, 97}, { /*82*/ 2.77, 80, 448000, 24000, 9, 101}, { /*83*/ 2.82, 80, 480000, 23000, 10, 101}, { /*84*/ 2.84, 80, 480000, 24000, 10, 103}, { /*85*/ 2.86, 80, 512000, 28000, 10, 103}, { /*86*/ 2.88, 80, 448000, 29000, 10, 107}, /* 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, 512000, 32000, 10, 107}, { /*88*/ 2.91, 80, 512000, 35000, 10, 109}, { /*89*/ 2.92, 80, 512000, 38000, 10, 109}, { /*90*/ 2.93, 80, 512000, 40000, 10, 113}, { /*91*/ 2.94, 80, 770000, 32200, 10, 113}, /* entries below due to Thomas Denny, never tested */ { /*92*/ 3.6, 90, 2000000, 35000, 9, 113}, { /*93*/ 3.7, 90, 2000000, 37000, 9, 113}, { /*94*/ 3.7, 90, 2000000, 39500, 9, 127}, { /*95*/ 3.7, 90, 2500000, 41500, 9, 127}, { /*96*/ 3.8, 90, 2500000, 45000, 10, 127}, { /*97*/ 3.8, 90, 2500000, 47500, 10, 131}, { /*98*/ 3.7, 90, 3000000, 51000, 10, 131}, { /*99*/ 3.8, 90, 3000000, 53000, 10, 133}, {/*100*/ 3.8, 90, 875000, 50000, 10, 133}, {/*101*/ 3.8, 90, 3500000, 54000, 10, 139}, {/*102*/ 3.8, 90, 3500000, 57000, 10, 139}, {/*103*/ 3.9, 90, 4000000, 61000, 10, 139}, {/*104*/ 3.9, 90, 4000000, 66000, 10, 149}, {/*105*/ 3.9, 90, 4000000, 70000, 10, 149}, {/*106*/ 3.9, 90, 4000000, 75000, 10, 151}, {/*107*/ 3.9, 90, 4000000, 80000, 10, 151}, }; #define MPQS_MAX_DIGIT_SIZE_KN 107 pari-2.17.2/src/modules/part.c0000644000175000017500000002610714676526175014566 0ustar billbill/* Copyright (C) 2002 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* Original code contributed by: Ralf Stephan (ralf@ark.in-berlin.de). * Updated by Bill Allombert (2014) to use Selberg formula for L * following http://dx.doi.org/10.1112/S1461157012001088 * * This program is basically the implementation of the script * * Psi(n, q) = my(a=sqrt(2/3)*Pi/q, b=n-1/24, c=sqrt(b)); * (sqrt(q)/(2*sqrt(2)*b*Pi))*(a*cosh(a*c)-(sinh(a*c)/c)) * L(n,q)=sqrt(k/3)*sum(l=0,2*k-1, if(((3*l^2+l)/2+n)%k==0,(-1)^l*cos((6*l+1)/(6*k)*Pi))) * part(n) = round(sum(q=1,5 + 0.24*sqrt(n),L(n,q)*Psi(n,q))) * * only faster. * * ------------------------------------------------------------------ * 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 c = sqrt(2/3)*Pi*sqrt(N-1/24) * Psi(N, q) = my(a = c/q); sqrt(q) * (a*cosh(a) - sinh(a)) */ static GEN psi(GEN c, ulong q, long prec) { 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(utor(q,prec)), subrr(mulrr(a,cha), sha)); } /* L(n,q)=sqrt(k/3)*sum(l=0,2*k-1, if(((3*l^2+l)/2+n)%k==0,(-1)^l*cos((6*l+1)/(6*k)*Pi))) * Never called with q < 3, so ignore this case */ static GEN L(GEN n, ulong k, long bitprec) { ulong r, l, m; long pr = nbits2prec(bitprec / k + k); GEN s = utor(0,pr), pi = mppi(pr); pari_sp av = avma; r = 2; m = umodiu(n,k); for (l = 0; l < 2*k; l++) { if (m == 0) { GEN c = mpcos(divru(mulru(pi, 6*l+1), 6*k)); if (odd(l)) subrrz(s, c, s); else addrrz(s, c, s); set_avma(av); } m += r; if (m >= k) m -= k; r += 3; if (r >= k) r -= k; } /* multiply by sqrt(k/3) */ return mulrr(s, sqrtr((k % 3)? rdivss(k,3,pr): utor(k/3,pr))); } /* Return a low precision estimate of log p(n). */ 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( utor(3,DEFAULTPREC) )); return gerepileupto(av, mplog(p1)); } /* c = sqrt(2/3)*Pi*sqrt(n-1/24); d = 1 / ((2*b)^(3/2) * Pi); */ static void pinit(GEN n, GEN *c, GEN *d, ulong prec) { GEN b = divru( itor( subiu(muliu(n,24), 1), prec ), 24 ); /* n - 1/24 */ GEN sqrtb = sqrtr(b), Pi = mppi(prec), pi2sqrt2, pisqrt2d3; pisqrt2d3 = mulrr(Pi, sqrtr( divru(utor(2, prec), 3) )); pi2sqrt2 = mulrr(Pi, sqrtr( utor(8, prec) )); *c = mulrr(pisqrt2d3, sqrtb); *d = invr( mulrr(pi2sqrt2, mulrr(b,sqrtb)) ); } /* part(n) = round(sum(q=1,5 + 0.24*sqrt(n), L(n,q)*Psi(n,q))) */ GEN numbpart(GEN n) { pari_sp ltop = avma, av; GEN sum, est, C, D, p1, p2; long prec, bitprec; ulong q; if (typ(n) != t_INT) pari_err_TYPE("partition function",n); if (signe(n) < 0) return gen_0; if (abscmpiu(n, 2) < 0) return gen_1; if (cmpii(n, uu32toi(0x38d7e, 0xa4c68000)) >= 0) pari_err_OVERFLOW("numbpart [n < 10^15]"); est = estim(n); bitprec = (long)(rtodbl(est)/M_LN2) + 32; prec = nbits2prec(bitprec); pinit(n, &C, &D, prec); sum = utor(0, prec); /* Because N < 10^16 and q < sqrt(N), q fits into a long * In fact q < 2 LONG_MAX / 3 */ av = avma; togglesign(est); for (q = (ulong)(sqrt(gtodouble(n))*0.24 + 5); q >= 3; q--, set_avma(av)) { GEN t = L(n, q, bitprec); if (abscmprr(t, mpexp(divru(est,q))) < 0) continue; t = mulrr(t, psi(gprec_w(C, nbits2prec(bitprec / q + 32)), q, prec)); affrr(addrr(sum, t), sum); } p1 = addrr(sum, psi(C, 1, prec)); p2 = psi(C, 2, prec); affrr(mod2(n)? subrr(p1,p2): addrr(p1,p2), sum); return gerepileuptoint (ltop, roundr(mulrr(D,sum))); } /* for loop over partitions of integer k. * nbounds can restrict partitions to have length between nmin and nmax * (the length is the number of non zero entries) and * abounds restrict to integers between amin and amax. * * Start from central partition. * By default, remove zero entries on the left. * * Algorithm: * * A partition of k is an increasing sequence v1,... vn with sum(vi)=k * The starting point is the minimal n-partition of k: a,...a,a+1,.. a+1 * (a+1 is repeated r times with k = a * n + r). * * The procedure to obtain the next partition: * - find the last index i*amax || *amin<0 || *amax<=0) pari_err_TYPE("forpart [expect 0<=min<=max, 0amin=1; if (abound) parse_interval(abound,&T->amin,&T->amax); else T->amax = k; /* strip leading zeros ? */ T->strip = (T->amin > 0) ? 1 : 0; /* bound on number of nonzero coefficients */ T->nmin=0; if (nbound) parse_interval(nbound,&T->nmin,&T->nmax); else T->nmax = k; /* non empty if nmin*amin <= k <= amax*nmax */ if ( T->amin*T->nmin > k || k > T->amax * T->nmax ) { T->nmin = T->nmax = 0; } else { /* to reach nmin one must have k <= nmin*amax, otherwise increase nmin */ if ( T->nmin * T->amax < k ) T->nmin = 1 + (k - 1) / T->amax; /* ceil( k/tmax ) */ /* decrease nmax (if strip): k <= amin*nmax */ if (T->strip && T->nmax > k/T->amin) T->nmax = k / T->amin; /* strip implies amin>0 */ /* fixme: take ceil( ) */ /* no need to change amin */ /* decrease amax if amax + (nmin-1)*amin > k */ if ( T->amax + (T->nmin-1)* T->amin > k ) T->amax = k - (T->nmin-1)* T->amin; } if ( T->amax < T->amin ) T->nmin = T->nmax = 0; T->v = zero_zv(T->nmax); /* partitions will be of length <= nmax */ T->k = k; } GEN forpart_next(forpart_t *T) { GEN v = T->v; long n = lg(v)-1; long i, s, a, k, vi, vn; if (n>0 && v[n]) { /* find index to increase: i s.t. v[i+1],...v[n] is central a,..a,a+1,..a+1 keep s = v[i] + v[i+1] + ... + v[n] */ s = a = v[n]; for(i = n-1; i>0 && v[i]+1 >= a; s += v[i--]); if (i == 0) { /* v is central [ a, a, .. a, a+1, .. a+1 ] */ if ((n+1) * T->amin > s || n == T->nmax) return NULL; i = 1; n++; setlg(v, n+1); vi = T->amin; } else { s += v[i]; vi = v[i]+1; } } else { /* init v */ s = T->k; if (T->amin == 0) T->amin = 1; if (T->strip) { n = T->nmin; setlg(T->v, n+1); } if (s==0) { if (n==0 && T->nmin==0) {T->nmin++; return v;} return NULL; } if (n==0) return NULL; vi = T->amin; i = T->strip ? 1 : n + 1 - T->nmin; /* first nonzero index */ if (s <= (n-i)*vi) return NULL; } /* now fill [ v[i],... v[n] ] with s, start at vi */ vn = s - (n-i)*vi; /* expected value for v[n] */ if (T->amax && vn > T->amax) { /* do not exceed amax */ long ai, q, r; vn -= vi; ai = T->amax - vi; q = vn / ai; /* number of nmax */ r = vn % ai; /* value before nmax */ /* fill [ v[i],... v[n] ] as [ vi,... vi, vi+r, amax,... amax ] */ while ( q-- ) v[n--] = T->amax; if ( n >= i ) v[n--] = vi + r; while ( n >= i ) v[n--] = vi; } else { /* fill as [ v[i], ... v[i], vn ] */ for ( k=i; kv; long n = lg(v)-1; long j, ni, q, r; long i, s; if (n>0 && v[n]) { /* find index to decrease: start of last constant sequence, excluding v[n] */ i = n-1; s = v[n]; while (i>1 && (v[i-1]==v[i] || v[i+1]==T->amax)) s+= v[i--]; if (!i) return NULL; /* amax condition: cannot decrease i if maximal on the right */ if ( v[i+1] == T->amax ) return NULL; /* amin condition: stop if below except if strip & try to remove */ if (v[i] == T->amin) { if (!T->strip) return NULL; s += v[i]; v[i] = 0; } else { v[i]--; s++; } /* zero case... */ if (v[i] == 0) { if (T->nmin > n-i) return NULL; /* need too many non zero coeffs */ /* reduce size of v ? */ if (T->strip) { i = 0; n--; setlg(v, n+1); } } } else { s = T->k; i = 0; if (s==0) { if (n==0 && T->nmin==0) {T->nmin++; return v;} return NULL; } if (n*T->amax < s || s < T->nmin*T->amin) return NULL; } /* set minimal partition of sum s starting from index i+1 */ ni = n-i; q = s / ni; r = s % ni; for(j=i+1; j<=n-r; j++) v[j]=q; for(j=n-r+1; j<=n; j++) v[j]=q + 1; return v; } static long countpart(long k, GEN abound, GEN nbound) { pari_sp av = avma; long n; forpart_t T; if (k<0) return 0; forpart_init(&T, k, abound, nbound); for (n=0; forpart_next(&T); n++) set_avma(av); return n; } GEN partitions(long k, GEN abound, GEN nbound) { GEN v; forpart_t T; long i, n = countpart(k,abound,nbound); if (n==0) return cgetg(1, t_VEC); forpart_init(&T, k, abound, nbound); v = cgetg(n+1, t_VEC); for (i=1; i<=n; i++) gel(v,i)=zv_copy(forpart_next(&T)); return v; } void forpart(void *E, long call(void*, GEN), long k, GEN abound, GEN nbound) { pari_sp av = avma; GEN v; forpart_t T; forpart_init(&T, k, abound, nbound); while ((v=forpart_next(&T))) if (call(E, v)) break; set_avma(av); } void forpart0(GEN k, GEN code, GEN abound, GEN nbound) { pari_sp av = avma; if (typ(k) != t_INT) pari_err_TYPE("forpart",k); if (signe(k)<0) return; push_lex(gen_0, code); forpart((void*)code, &gp_evalvoid, itos(k), abound, nbound); pop_lex(1); set_avma(av); } pari-2.17.2/src/modules/forperm.c0000644000175000017500000000365014567450071015256 0ustar billbill/* Copyright (C) 2017 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* for loop over permutations in lexicographic order * This implements the algorithm L in D. Knuth "The Art Of Computer Programming" * Fascicle 2b */ #include "pari.h" #include "paripriv.h" void forperm_init(forperm_t *T, GEN k) { switch (typ(k)) { case t_INT: if (signe(k) < 0) pari_err_DOMAIN("forperm", "a", "<", gen_0, k); T->v = identity_perm(itou(k)); break; case t_VEC: T->v = vec_to_vecsmall(k); break; case t_VECSMALL: T->v = vecsmall_copy(k); break; default: pari_err_TYPE("forperm", k); return; /* LCOV_EXCL_LINE */ } T->first = 1; T->k = lg(T->v) - 1; } GEN forperm_next(forperm_t *T) { long k = T->k, m1, m2, *p, *q; GEN v = T->v; if (T->first) { T->first = 0; return v; } m1 = k-1; while (m1 > 0 && v[m1] >= v[m1+1]) m1--; if (m1 <= 0) return NULL; m2 = k; while (v[m1] >= v[m2]) m2--; lswap(v[m1], v[m2]); p = v + m1 + 1; q = v + k; while (p < q) { lswap(*p, *q); p++; q--; } return v; } void forperm(void *E, long call(void *, GEN), GEN k) { pari_sp av = avma; forperm_t T; GEN v; forperm_init(&T, k); while ((v = forperm_next(&T))) if (call(E, v)) break; set_avma(av); } void forperm0(GEN k, GEN code) { push_lex(gen_0, code); forperm((void *)code, &gp_evalvoid, k); pop_lex(1); } pari-2.17.2/src/modules/thue.c0000644000175000017500000014331514760123736014554 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_thue /********************************************************************/ /** **/ /** 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. See also * "Solving Thue equations without the full unit group", Math. Comp. (2000) */ /* Check whether tnf is a valid structure */ static int checktnf(GEN tnf) { long l = lg(tnf); GEN v; if (typ(tnf)!=t_VEC || (l!=8 && l!=4)) return 0; v = gel(tnf,1); if (typ(v) != t_VEC || lg(v) != 4) return 0; if (l == 4) return 1; /* s=0 */ (void)checkbnf(gel(tnf,2)); return (typ(gel(tnf,3)) == t_COL && typ(gel(tnf,4)) == t_COL && typ(gel(tnf,5)) == t_MAT && typ(gel(tnf,6)) == t_MAT && typ(gel(tnf,7)) == t_VEC); } /* Compensates rounding errors for computation/display of the constants. * Round up if dir > 0, down otherwise */ static GEN myround(GEN x, long dir) { GEN eps = powis(stoi(dir > 0? 10: -10), -10); return gmul(x, gadd(gen_1, eps)); } /* v a t_VEC/t_VEC */ static GEN vecmax_shallow(GEN v) { return gel(v, vecindexmax(v)); } static GEN tnf_get_roots(GEN poly, long prec, long S, long T) { GEN R0 = QX_complex_roots(poly, prec), R = cgetg(lg(R0), t_COL); long k; for (k=1; k<=S; k++) gel(R,k) = gel(R0,k); /* swap roots to get the usual order */ for (k=1; k<=T; k++) { gel(R,k+S) = gel(R0,2*k+S-1); gel(R,k+S+T)= gel(R0,2*k+S); } return R; } /* Computation of the logarithmic height of x (given by embeddings) */ static GEN LogHeight(GEN x, long prec) { pari_sp av = avma; long i, n = lg(x)-1; GEN LH = gen_1; for (i=1; i<=n; i++) { GEN t = gabs(gel(x,i), prec); if (gcmpgs(t,1) > 0) LH = gmul(LH, t); } return gerepileupto(av, gdivgu(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; } /* find a few large primes such that p Z_K = P1 P2 P3 Q, with f(Pi/p) = 1 * From x - \alpha y = \prod u_i^b_i we will deduce 3 equations in F_p * in check_prinfo. Eliminating x,y we get a stringent condition on (b_i). */ static GEN get_prime_info(GEN bnf) { long n = 1, e = gexpo(bnf_get_reg(bnf)), nbp = e < 20? 1: 2; GEN L = cgetg(nbp+1, t_VEC), nf = bnf_get_nf(bnf), fu = bnf_get_fu(bnf); GEN X = pol_x(nf_get_varn(nf)); ulong p; for(p = 2147483659UL; n <= nbp; p = unextprime(p+1)) { GEN PR, A, U, LP = idealprimedec_limit_f(bnf, utoipos(p), 1); long i; if (lg(LP) < 4) continue; A = cgetg(5, t_VECSMALL); U = cgetg(4, t_VEC); PR = cgetg(4, t_VEC); for (i = 1; i <= 3; i++) { GEN modpr = zkmodprinit(nf, gel(LP,i)); GEN a = nf_to_Fq(nf, X, modpr); GEN u = nfV_to_FqV(fu, nf, modpr); A[i] = itou(a); gel(U,i) = ZV_to_Flv(u,p); gel(PR,i) = modpr; } A[4] = p; gel(L,n++) = mkvec3(A,U,PR); } return L; } /* Performs basic computations concerning the equation. * Returns a "tnf" structure containing * 1) the polynomial * 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 fu, MatFU, x0, tnf, tmp, gpmin, dP, csts, ALH, eps5, ro, c1, c2; GEN Ind = gen_1; long s,t, k,j, prec_roots, n = degpol(P); if (!bnf) { bnf = Buchall(P, nf_FORCE, maxss(prec, DEFAULTPREC)); if (flag) (void)bnfcertify(bnf); else Ind = floorr(mulru(bnf_get_reg(bnf), 5)); } nf_get_sign(bnf_get_nf(bnf), &s, &t); fu = bnf_get_fu(bnf); prec_roots = prec + nbits2extraprec(gexpo(Q_primpart(fu))); for(;;) { ro = tnf_get_roots(P, prec_roots, s, t); MatFU = Conj_LH(fu, &ALH, ro, prec); if (MatFU) break; prec_roots = precdbl(prec_roots); if (DEBUGLEVEL>1) pari_warn(warnprec, "inithue", prec_roots); } dP = ZX_deriv(P); c1 = NULL; /* min |P'(r_i)|, i <= s */ for (k=1; k<=s; k++) { tmp = gabs(poleval(dP,gel(ro,k)),prec); if (!c1 || gcmp(tmp,c1) < 0) c1 = tmp; } c1 = gdiv(int2n(n-1), c1); c1 = gprec_w(myround(c1, 1), DEFAULTPREC); c2 = NULL; /* max |r_i - r_j|, i!=j */ for (k=1; k<=n; k++) for (j=k+1; j<=n; j++) { tmp = gabs(gsub(gel(ro,j),gel(ro,k)), prec); if (!c2 || gcmp(c2,tmp) > 0) c2 = tmp; } c2 = gprec_w(myround(c2, -1), DEFAULTPREC); if (t==0) x0 = real_1(DEFAULTPREC); else { gpmin = NULL; /* min |P'(r_i)|, i > s */ for (k=1; k<=t; k++) { tmp = gabs(poleval(dP,gel(ro,s+k)), prec); if (!gpmin || gcmp(tmp,gpmin) < 0) gpmin = tmp; } gpmin = gprec_w(gpmin, DEFAULTPREC); /* Compute x0. See paper, Prop. 2.2.1 */ x0 = gmul(gpmin, vecmax_shallow(gabs(imag_i(ro), prec))); x0 = sqrtnr(gdiv(int2n(n-1), x0), n); } if (DEBUGLEVEL>1) err_printf("c1 = %Ps\nc2 = %Ps\nIndice <= %Ps\n", c1, c2, Ind); ALH = gmul2n(ALH, 1); tnf = cgetg(8,t_VEC); csts = cgetg(9,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; gel(csts,8) = get_prime_info(bnf); return tnf; } typedef struct { GEN c10, c11, c13, c15, c91, bak, NE, Ind, hal, MatFU, divro, Hmu; GEN delta, lambda, inverrdelta, ro, Pi, Pi2; long r, iroot, deg; } baker_s; static void other_roots(long iroot, long *i1, long *i2) { switch (iroot) { case 1: *i1=2; *i2=3; break; case 2: *i1=1; *i2=3; break; default: *i1=1; *i2=2; break; } } /* low precision */ static GEN abslog(GEN x) { return gabs(glog(gtofp(x,DEFAULTPREC),0), 0); } /* Compute Baker's bound c9 and B_0, the bound for the b_i's. See Thm 2.3.1 */ static GEN Baker(baker_s *BS) { GEN tmp, B0, hb0, c9, Indc11; long i1, i2; other_roots(BS->iroot, &i1,&i2); /* Compute a bound for the h_0 */ hb0 = gadd(gmul2n(BS->hal,2), gmul2n(gadd(BS->Hmu,mplog2(DEFAULTPREC)), 1)); tmp = gmul(BS->divro, gdiv(gel(BS->NE,i1), gel(BS->NE,i2))); tmp = gmax_shallow(gen_1, abslog(tmp)); hb0 = gmax_shallow(hb0, gdiv(tmp, BS->bak)); c9 = gmul(BS->c91,hb0); c9 = gprec_w(myround(c9, 1), DEFAULTPREC); Indc11 = rtor(mulir(BS->Ind,BS->c11), DEFAULTPREC); /* Compute B0 according to Lemma 2.3.3 */ B0 = mulir(shifti(BS->Ind,1), divrr(addrr(mulrr(c9,mplog(divrr(mulir(BS->Ind, c9),BS->c10))), mplog(Indc11)), BS->c10)); B0 = gmax_shallow(B0, dbltor(2.71828183)); B0 = gmax_shallow(B0, mulrr(divir(BS->Ind, BS->c10), mplog(divrr(Indc11, BS->Pi2)))); 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_i( 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)), NULL); 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), NULL); triv = shiftr(sqrr(B0), 1); } else triv = addir(sqri(BS->Ind), sqrr(B0)); gcoeff(lllmat, 3, 1) = grndtoi(negr(mulir(C, BS->lambda)), &e); if (e >= 0) return -1; gcoeff(lllmat, 3, 2) = grndtoi(negr(mulir(C, BS->delta)), &e); if (e >= 0) return -1; gcoeff(lllmat, 3, 3) = C; lllmat = ZM_lll(lllmat, 0.99, LLL_IM|LLL_INPLACE); l0 = gnorml2(gel(lllmat,1)); l0 = subrr(divir(l0, dbltor(1.8262)), triv); /* delta = 0.99 */ if (signe(l0) <= 0) return 0; l1 = shiftr(addri(shiftr(B0,1), BS->Ind), -1); l0 = divri(subrr(sqrtr(l0), l1), C); if (signe(l0) <= 0) return 0; get_B0Bx(BS, l0, &B0, &Bx); if (DEBUGLEVEL>=2) { err_printf("LLL_First_Pass successful\n"); err_printf("B0 -> %Ps\n", B0); err_printf("x <= %Ps\n", Bx); } *pB0 = B0; *pBx = Bx; return 1; } /* add solution (x,y) if not already known */ static void add_sol(GEN *pS, GEN x, GEN y) { *pS = vec_append(*pS, mkvec2(x,y)); } /* z = P(p,q), d = deg P, |z| = |rhs|. Check signs and (possibly) * add solutions (p,q), (-p,-q) */ static void add_pm(GEN *pS, GEN p, GEN q, GEN z, long d, GEN rhs) { 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)); } /* Check whether a potential solution is a true solution. Return 0 if * truncation error (increase precision) */ static int CheckSol(GEN *pS, GEN z1, GEN z2, GEN P, GEN rhs, GEN ro) { GEN x, y, ro1 = gel(ro,1), ro2 = gel(ro,2); long e; y = grndtoi(real_i(gdiv(gsub(z2,z1), gsub(ro1,ro2))), &e); if (e > 0) return 0; if (!signe(y)) return 1; /* y = 0 taken care of in SmallSols */ x = gadd(z1, gmul(ro1, y)); x = grndtoi(real_i(x), &e); if (e > 0) return 0; if (e <= -13) { /* y != 0 and rhs != 0; check whether P(x,y) = rhs or P(-x,-y) = rhs */ GEN z = ZX_Z_eval(ZX_rescale(P,y),x); if (absequalii(z, rhs)) add_pm(pS, x,y, z, degpol(P), rhs); } return 1; } static const long EXPO1 = 7; static int round_to_b(GEN v, long B, long b, GEN Delta2, long i1, GEN L) { long i, l = lg(v); if (!b) { for (i = 1; i < l; i++) { long c; if (i == i1) c = 0; else { GEN d = gneg(gel(L,i)); long e; d = grndtoi(d,&e); if (e > -EXPO1 || is_bigint(d)) return 0; c = itos(d); if (labs(c) > B) return 0; } v[i] = c; } } else { for (i = 1; i < l; i++) { long c; if (i == i1) c = b; else { GEN d = gsub(gmulgs(gel(Delta2,i), b), gel(L,i)); long e; d = grndtoi(d,&e); if (e > -EXPO1 || is_bigint(d)) return 0; c = itos(d); if (labs(c) > B) return 0; } v[i] = c; } } return 1; } /* mu \prod U[i]^b[i] */ static ulong Fl_factorback(ulong mu, GEN U, GEN b, ulong p) { long i, l = lg(U); ulong r = mu; for (i = 1; i < l; i++) { long c = b[i]; ulong u = U[i]; if (!c) continue; if (c < 0) { u = Fl_inv(u,p); c = -c; } r = Fl_mul(r, Fl_powu(u,c,p), p); } return r; } /* x - alpha y = \pm mu \prod \mu_i^{b_i}. Reduce mod 3 distinct primes of * degree 1 above the same p, and eliminate x,y => drastic conditions on b_i */ static int check_pr(GEN bi, GEN Lmu, GEN L) { GEN A = gel(L,1), U = gel(L,2); ulong a = A[1], b = A[2], c = A[3], p = A[4]; ulong r = Fl_mul(Fl_sub(c,b,p), Fl_factorback(Lmu[1],gel(U,1),bi, p), p); ulong s = Fl_mul(Fl_sub(a,c,p), Fl_factorback(Lmu[2],gel(U,2),bi, p), p); ulong t = Fl_mul(Fl_sub(b,a,p), Fl_factorback(Lmu[3],gel(U,3),bi, p), p); return Fl_add(Fl_add(r,s,p),t,p) == 0; } static int check_prinfo(GEN b, GEN Lmu, GEN prinfo) { long i; for (i = 1; i < lg(prinfo); i++) if (!check_pr(b, gel(Lmu,i), gel(prinfo,i))) return 0; return 1; } /* For each possible value of b_i1, compute the b_i's * and 2 conjugates of z = x - alpha y. Then check. */ static int TrySol(GEN *pS, GEN B0, long i1, GEN Delta2, GEN Lambda, GEN ro, GEN Lmu, GEN NE, GEN MatFU, GEN prinfo, GEN P, GEN rhs) { long bi1, i, B = itos(gceil(B0)), l = lg(Delta2); GEN b = cgetg(l,t_VECSMALL), L = cgetg(l,t_VEC); for (i = 1; i < l; i++) { if (i == i1) gel(L,i) = gen_0; else { GEN delta = gel(Delta2,i); gel(L, i) = gsub(gmul(delta,gel(Lambda,i1)), gel(Lambda,i)); } } for (bi1 = -B; bi1 <= B; bi1++) { GEN z1, z2; if (!round_to_b(b, B, bi1, Delta2, i1, L)) continue; if (!check_prinfo(b, Lmu, prinfo)) continue; z1 = gel(NE,1); z2 = gel(NE,2); for (i = 1; i < l; i++) { z1 = gmul(z1, gpowgs(gcoeff(MatFU,1,i), b[i])); z2 = gmul(z2, gpowgs(gcoeff(MatFU,2,i), b[i])); } if (!CheckSol(pS, z1,z2,P,rhs,ro)) return 0; } return 1; } /* find q1,q2,q3 st q1 b + q2 c + q3 ~ 0 */ static GEN GuessQi(GEN b, GEN c, GEN *eps) { const long shift = 65; GEN Q, Lat; Lat = matid(3); gcoeff(Lat,3,1) = ground(gmul2n(b, shift)); gcoeff(Lat,3,2) = ground(gmul2n(c, shift)); gcoeff(Lat,3,3) = int2n(shift); Q = gel(lllint(Lat),1); if (gequal0(gel(Q,2))) return NULL; /* FAIL */ *eps = mpadd(mpadd(gel(Q,3), mpmul(gel(Q,1),b)), mpmul(gel(Q,2),c)); *eps = mpabs_shallow(*eps); return Q; } /* x a t_REAL */ static GEN myfloor(GEN x) { return expo(x) > 30 ? ceil_safe(x): floorr(x); } /* Check for not-so-small solutions. Return a t_REAL or NULL */ static GEN MiddleSols(GEN *pS, GEN bound, GEN roo, GEN P, GEN rhs, long s, GEN c1) { long j, k, nmax, d; GEN bndcf; if (expo(bound) < 0) return bound; d = degpol(P); bndcf = sqrtnr(shiftr(c1,1), d - 2); if (cmprr(bound, bndcf) < 0) return bound; /* divide by log2((1+sqrt(5))/2) * 1 + ==> ceil * 2 + ==> continued fraction is normalized if last entry is 1 * 3 + ==> start at a0, not a1 */ nmax = 3 + (long)(dbllog2(bound) * 1.44042009041256); bound = myfloor(bound); for (k = 1; k <= s; k++) { GEN ro = real_i(gel(roo,k)), t = gboundcf(ro, 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; pari_sp av; p = addii(mulii(p0, gel(t,j)), pm1); pm1 = p0; p0 = p; q = addii(mulii(q0, gel(t,j)), qm1); qm1 = q0; q0 = q; if (cmpii(q, bound) > 0) break; if (DEBUGLEVEL >= 2) err_printf("Checking (+/- %Ps, +/- %Ps)\n",p, q); av = avma; z = ZX_Z_eval(ZX_rescale(P,q), p); /* = P(p/q) q^dep(P) */ Q = dvmdii(rhs, z, &R); if (R != gen_0) { set_avma(av); continue; } setabssign(Q); if (Z_ispowerall(Q, d, &Q)) { if (!is_pm1(Q)) { p = mulii(p, Q); q = mulii(q, Q); } add_pm(pS, p, q, z, d, rhs); } } if (j == lg(t)) { long prec; if (j > nmax) pari_err_BUG("thue [short continued fraction]"); /* the theoretical value is bit_prec = gexpo(ro)+1+log2(bound) */ prec = precdbl(precision(ro)); if (DEBUGLEVEL>1) pari_warn(warnprec,"thue",prec); roo = ZX_realroots_irred(P, prec); if (lg(roo)-1 != s) pari_err_BUG("thue [realroots]"); k--; } } return bndcf; } static void check_y_root(GEN *pS, GEN P, GEN Y) { GEN r = nfrootsQ(P); long j; for (j = 1; j < lg(r); j++) if (typ(gel(r,j)) == t_INT) add_sol(pS, gel(r,j), Y); } static void check_y(GEN *pS, GEN P, GEN poly, GEN Y, GEN rhs) { long j, l = lg(poly); GEN Yn = Y; gel(P, l-1) = gel(poly, l-1); for (j = l-2; j >= 2; j--) { gel(P,j) = mulii(Yn, gel(poly,j)); if (j > 2) Yn = mulii(Yn, Y); } gel(P,2) = subii(gel(P,2), rhs); /* P = poly(Y/y)*y^deg(poly) - rhs */ check_y_root(pS, P, Y); } /* Check for solutions under a small bound (see paper) */ static GEN SmallSols(GEN S, GEN x3, GEN poly, GEN rhs) { pari_sp av = avma; GEN X, P, rhs2; long j, l = lg(poly), n = degpol(poly); ulong y, By; x3 = myfloor(x3); if (DEBUGLEVEL>1) err_printf("* Checking for small solutions <= %Ps\n", x3); if (lgefint(x3) > 3) pari_err_OVERFLOW(stack_sprintf("thue (SmallSols): y <= %Ps", x3)); By = itou(x3); /* y = 0 first: solve X^n = rhs */ if (odd(n)) { if (Z_ispowerall(absi_shallow(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)) { set_avma(av2); continue; } /* no solution found */ if (gc_needed(av,1)) { if(DEBUGMEM>1) pari_warn(warnmem,"SmallSols"); gerepileall(av, 2, &S, &rhs2); P = cgetg(l, t_POL); P[1] = poly[1]; } } return S; } /* Computes [x]! */ static double fact(double x) { double ft = 1.0; x = floor(x); while (x>1) { ft *= x; x--; } return ft ; } /* 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 s, lfa, dpol; if (checktnf(pol)) { bnf = checkbnf(gel(pol,2)); pol = gel(pol,1); } if (typ(pol)!=t_POL) pari_err_TYPE("thueinit",pol); dpol = degpol(pol); if (dpol <= 0) pari_err_CONSTPOL("thueinit"); RgX_check_ZX(pol, "thueinit"); if (varn(pol)) { pol = leafcopy(pol); setvarn(pol, 0); } POL = Q_primitive_part(pol, &C); L = gen_1; fa = ZX_factor(POL); lfa = lgcols(fa); if (lfa > 2 || itos(gcoeff(fa,1,2)) > 1) { /* reducible polynomial, no need to reduce to the monic case */ GEN P, Q, R, g, f = gcoeff(fa,1,1), E = gcoeff(fa,1,2); long e = itos(E); long vy = fetch_var(); long va = fetch_var(); long vb = fetch_var(); C = C? ginv(C): gen_1; if (e != 1) { if (lfa == 2) { tnf = mkvec3(mkvec3(POL,C,L), thueinit(f, flag, prec), E); delete_var(); delete_var(); delete_var(); return gerepilecopy(av, tnf); } P = gpowgs(f,e); } else P = f; g = RgX_div(POL, P); P = RgX_Rg_sub(RgX_homogenize(f, vy), pol_x(va)); Q = RgX_Rg_sub(RgX_homogenize(g, vy), pol_x(vb)); R = polresultant0(P, Q, -1, 0); tnf = mkvec3(mkvec3(POL,C,L), mkvecsmall4(degpol(f), e, va,vb), R); delete_var(); delete_var(); delete_var(); return gerepilecopy(av, tnf); } /* POL monic irreducible: POL(x) = C pol(x/L), L integer */ POL = ZX_primitive_to_monic(POL, &L); C = gdiv(powiu(L, dpol), gel(pol, dpol+2)); pol = POL; s = ZX_sturm_irred(pol); if (s) { long PREC, n = degpol(pol); double d, dr, dn = (double)n; if (dpol <= 2) pari_err_DOMAIN("thueinit", "P","=",pol,pol); dr = (double)((s+n-2)>>1); /* s+t-1 */ d = dn*(dn-1)*(dn-2); /* Guess precision by approximating Baker's bound. The guess is most of * the time not sharp, ie 10 to 30 decimal digits above what is _really_ * necessary. Note that the limiting step is the reduction. See paper. */ PREC = nbits2prec((long)((5.83 + (dr+4)*5 + log(fact(dr+3)) + (dr+3)*log(dr+2) + (dr+3)*log(d) + log(log(2*d*(dr+2))) + (dr+1)) /10.)*32+32); if (flag == 0) PREC = (long)(2.2 * PREC); /* Lazy, to be improved */ if (PREC < prec) PREC = prec; if (DEBUGLEVEL >=2) err_printf("prec = %d\n", PREC); for (;;) { if (( tnf = inithue(pol, bnf, flag, PREC) )) break; PREC = precdbl(PREC); if (DEBUGLEVEL>1) pari_warn(warnprec,"thueinit",PREC); bnf = NULL; set_avma(av); } } else { GEN ro, c0; long k,l; if (!bnf) { bnf = gen_0; if (expi(ZX_disc(pol)) <= 50) { bnf = Buchall(pol, nf_FORCE, DEFAULTPREC); if (flag) (void)bnfcertify(bnf); } } ro = typ(bnf)==t_VEC? nf_get_roots(bnf_get_nf(bnf)) : QX_complex_roots(pol, DEFAULTPREC); l = lg(ro); c0 = imag_i(gel(ro,1)); for (k = 2; k < l; k++) c0 = mulrr(c0, imag_i(gel(ro,k))); setsigne(c0,1); c0 = invr(c0); tnf = mkvec3(pol, bnf, c0); } gel(tnf,1) = mkvec3(gel(tnf,1), C, L); return gerepilecopy(av,tnf); } /* arg(t^2) / 2Pi; arg(t^2) = arg(t/conj(t)) */ static GEN argsqr(GEN t, GEN Pi) { GEN v, u = divrr(garg(t,0), Pi); /* in -1 < u <= 1 */ /* reduce mod Z to -1/2 < u <= 1/2 */ if (signe(u) > 0) { v = subrs(u,1); /* ]-1,0] */ if (abscmprr(v,u) < 0) u = v; } else { v = addrs(u,1);/* ]0,1] */ if (abscmprr(v,u) <= 0) u = v; } return u; } /* i1 != i2 */ static void init_get_B(long i1, long i2, GEN Delta2, GEN Lambda, GEN Deps5, baker_s *BS, long prec) { GEN delta, lambda; if (BS->r > 1) { delta = gel(Delta2,i2); lambda = gsub(gmul(delta,gel(Lambda,i1)), gel(Lambda,i2)); if (Deps5) BS->inverrdelta = divrr(Deps5, addsr(1,delta)); } else { /* r == 1: i1 = s = t = 1; i2 = 2 */ GEN fu = gel(BS->MatFU,1), ro = BS->ro, t; t = gel(fu,2); delta = argsqr(t, BS->Pi); if (Deps5) BS->inverrdelta = shiftr(gabs(t,prec), prec-1); t = gmul(gsub(gel(ro,1), gel(ro,2)), gel(BS->NE,3)); lambda = argsqr(t, BS->Pi); } BS->delta = delta; BS->lambda = lambda; } static GEN get_B0(long i1, GEN Delta2, GEN Lambda, GEN Deps5, long prec, baker_s *BS) { GEN B0 = Baker(BS); long step = 0, i2 = (i1 == 1)? 2: 1; for(;;) /* i2 from 1 to r unless r = 1 [then i2 = 2] */ { init_get_B(i1,i2, Delta2,Lambda,Deps5, BS, prec); /* 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 = mpadd(B0, absi_shallow(gel(Q,1))); q = denom_i( bestappr(BS->delta, denbound) ); l0 = subrr(errnum(BS->delta, q), ep); if (signe(l0) <= 0) break; B0 = divrr(logr_abs(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_shallow(oldB0, B0); else step++; } i2++; if (i2 == i1) i2++; if (i2 > BS->r) break; } pari_err_BUG("thue (totally rational case)"); return NULL; /* LCOV_EXCL_LINE */ } static GEN get_Bx_LLL(long i1, GEN Delta2, GEN Lambda, long prec, baker_s *BS) { GEN B0 = Baker(BS), Bx = NULL; long step = 0, i2 = (i1 == 1)? 2: 1; for(;;) /* i2 from 1 to r unless r = 1 [then i2 = 2] */ { init_get_B(i1,i2, Delta2,Lambda,NULL, BS, prec); if (DEBUGLEVEL>1) err_printf(" Entering LLL...\n"); /* Reduce B0 as long as we make progress: newB0 < oldB0 - 0.1 */ for (;;) { GEN oldBx = Bx, kappa = utoipos(10); const long cfMAX = 10; long cf; for (cf = 0; cf < cfMAX; cf++, kappa = muliu(kappa,10)) { int res = LLL_1stPass(&B0, kappa, BS, &Bx); if (res < 0) return NULL; if (res) break; if (DEBUGLEVEL>1) err_printf("LLL failed. Increasing kappa\n"); } /* FIXME: TO BE COMPLETED */ if (!step && cf == cfMAX) { /* Semirational or totally rational case */ GEN Q, Q1, Q2, ep, q, l0, denbound; if (! (Q = GuessQi(BS->delta, BS->lambda, &ep)) ) break; /* Q[2] != 0 */ Q1 = absi_shallow(gel(Q,1)); Q2 = absi_shallow(gel(Q,2)); denbound = gadd(mulri(B0, Q1), mulii(BS->Ind, Q2)); q = denom_i( bestappr(BS->delta, denbound) ); l0 = divri(subrr(errnum(BS->delta, q), ep), Q2); if (signe(l0) <= 0) break; get_B0Bx(BS, l0, &B0, &Bx); if (DEBUGLEVEL>1) err_printf("Semirat. reduction: B0 -> %Ps x <= %Ps\n",B0, Bx); } /* if no progress, stop */ if (oldBx && gcmp(oldBx, Bx) <= 0) return oldBx; else step++; } i2++; if (i2 == i1) i2++; if (i2 > BS->r) break; } pari_err_BUG("thue (totally rational case)"); return NULL; /* LCOV_EXCL_LINE */ } static GEN LargeSols(GEN P, GEN tnf, GEN rhs, GEN ne) { GEN S = NULL, Delta0, ro, ALH, bnf, nf, MatFU, A, csts, dP, Bx; GEN c1,c2,c3,c4,c90,c91,c14, x0, x1, x2, x3, tmp, eps5, prinfo; long iroot, ine, n, r, Prec, prec, s,t; baker_s BS; pari_sp av = avma; prec = 0; /*-Wall*/ bnf = NULL; /*-Wall*/ iroot = 1; ine = 1; START: if (S) /* restart from precision problems */ { S = gerepilecopy(av, S); prec = precdbl(prec); if (DEBUGLEVEL) pari_warn(warnprec,"thue",prec); tnf = inithue(P, bnf, 0, prec); } else S = cgetg(1, t_VEC); bnf= gel(tnf,2); nf = bnf_get_nf(bnf); csts = gel(tnf,7); nf_get_sign(nf, &s, &t); BS.r = r = s+t-1; n = degpol(P); ro = gel(tnf,3); ALH = gel(tnf,4); MatFU = gel(tnf,5); A = gel(tnf,6); c1 = mpmul(absi_shallow(rhs), gel(csts,1)); c2 = gel(csts,2); BS.hal = gel(csts,3); x0 = gel(csts,4); eps5 = gel(csts,5); Prec = itos(gel(csts,6)); BS.Ind = gel(csts,7); BS.MatFU = MatFU; BS.bak = muluu(n, (n-1)*(n-2)); /* safe */ BS.deg = n; prinfo = gel(csts,8); if (t) x0 = gmul(x0, absisqrtn(rhs, n, Prec)); tmp = divrr(c1,c2); c3 = mulrr(dbltor(1.39), tmp); c4 = mulur(n-1, c3); c14 = mulrr(c4, vecmax_shallow(RgM_sumcol(gabs(A,DEFAULTPREC)))); x1 = gmax_shallow(x0, sqrtnr(shiftr(tmp,1),n)); x2 = gmax_shallow(x1, sqrtnr(mulur(10,c14), n)); x3 = gmax_shallow(x2, sqrtnr(shiftr(c14, EXPO1+1),n)); c90 = gmul(shiftr(mulur(18,mppi(DEFAULTPREC)), 5*(4+r)), gmul(gmul(mpfact(r+3), powiu(muliu(BS.bak,r+2), r+3)), glog(muliu(BS.bak,2*(r+2)),DEFAULTPREC))); dP = ZX_deriv(P); Delta0 = RgM_sumcol(A); for (; iroot<=s; iroot++) { GEN Delta = Delta0, Delta2, D, Deps5, MatNE, Hmu, diffRo, c5, c7, ro0; long i1, iroot1, iroot2, k; if (iroot <= r) Delta = RgC_add(Delta, RgC_Rg_mul(gel(A,iroot), stoi(-n))); D = gabs(Delta,Prec); i1 = vecindexmax(D); c5 = gel(D, i1); Delta2 = RgC_Rg_div(Delta, gel(Delta, i1)); c5 = myround(gprec_w(c5,DEFAULTPREC), 1); Deps5 = divrr(subrr(c5,eps5), eps5); c7 = mulur(r,c5); BS.c10 = divur(n,c7); BS.c13 = divur(n,c5); if (DEBUGLEVEL>1) { err_printf("* real root no %ld/%ld\n", iroot,s); err_printf(" c10 = %Ps\n",BS.c10); err_printf(" c13 = %Ps\n",BS.c13); } prec = Prec; for (;;) { if (( MatNE = Conj_LH(ne, &Hmu, ro, prec) )) break; prec = precdbl(prec); if (DEBUGLEVEL>1) pari_warn(warnprec,"thue",prec); ro = tnf_get_roots(P, prec, s, t); } ro0 = gel(ro,iroot); BS.ro = ro; BS.iroot = iroot; BS.Pi = mppi(prec); BS.Pi2 = Pi2n(1,prec); diffRo = cgetg(r+1, t_VEC); for (k=1; k<=r; k++) { GEN z = gel(ro,k); z = (k == iroot)? gdiv(rhs, poleval(dP, z)): gsub(ro0, z); gel(diffRo,k) = gabs(z, prec); } other_roots(iroot, &iroot1,&iroot2); BS.divro = gdiv(gsub(ro0, gel(ro,iroot2)), gsub(ro0, gel(ro,iroot1))); /* Compute h_1....h_r */ c91 = c90; for (k=1; k<=r; k++) { GEN z = gdiv(gcoeff(MatFU,iroot1,k), gcoeff(MatFU,iroot2,k)); z = gmax_shallow(gen_1, abslog(z)); c91 = gmul(c91, gmax_shallow(gel(ALH,k), gdiv(z, BS.bak))); } BS.c91 = c91; for (; ine1) err_printf(" - norm sol. no %ld/%ld\n",ine,lg(ne)-1); for (k=1; k<=r; k++) { GEN z = gdiv(gel(diffRo,k), gabs(gel(NE,k), prec)); gel(v,k) = glog(z, prec); } Lambda = RgM_RgC_mul(A,v); c6 = addrr(dbltor(0.1), vecmax_shallow(gabs(Lambda,DEFAULTPREC))); c6 = myround(c6, 1); c8 = addrr(dbltor(1.23), mulur(r,c6)); BS.c11= mulrr(shiftr(c3,1) , mpexp(divrr(mulur(n,c8),c7))); BS.c15= mulrr(shiftr(c14,1), mpexp(divrr(mulur(n,c6),c5))); BS.NE = NE; BS.Hmu = gel(Hmu,ine); if (is_pm1(BS.Ind)) { GEN mu = gel(ne,ine), Lmu = cgetg(lg(prinfo),t_VEC); long i, j; for (i = 1; i < lg(prinfo); i++) { GEN v = gel(prinfo,i), PR = gel(v,3), L = cgetg(4, t_VECSMALL); for (j = 1; j <= 3; j++) L[j] = itou(nf_to_Fq(nf, mu, gel(PR,j))); gel(Lmu, i) = L; } if (! (B0 = get_B0(i1, Delta2, Lambda, Deps5, prec, &BS)) || !TrySol(&S, B0, i1, Delta2, Lambda, ro, Lmu, NE,MatFU,prinfo, P,rhs)) goto START; if (lg(S) == lS) set_avma(av2); } else { if (! (Bx = get_Bx_LLL(i1, Delta2, Lambda, prec, &BS)) ) goto START; x3 = gerepileupto(av2, gmax_shallow(Bx, x3)); } } ine = 1; } x3 = gmax_shallow(x0, MiddleSols(&S, x3, ro, P, rhs, s, c1)); return SmallSols(S, x3, P, rhs); } /* restrict to solutions (x,y) with L | x, replacing each by (x/L, y) */ 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 filter_sol_Z(GEN S) { long i, k = 1, l = lg(S); for (i = 1; i < l; i++) { GEN s = gel(S,i); if (RgV_is_ZV(s)) gel(S, k++) = s; } setlg(S, k); return S; } static GEN bnfisintnorm_i(GEN bnf, GEN a, long s, GEN z, long flag); static GEN tnf_get_Ind(GEN tnf) { return gmael(tnf,7,7); } static GEN tnf_get_bnf(GEN tnf) { return gel(tnf,2); } static void maybe_warn(GEN bnf, GEN a, GEN Ind) { if (!is_pm1(Ind) && !is_pm1(bnf_get_no(bnf)) && !is_pm1(a)) pari_warn(warner, "The result returned by 'thue' is conditional on the GRH"); } /* true bnf; return solutions of Norm(x) = a mod U(K)^+ */ static GEN get_ne(GEN bnf, GEN a, GEN fa, GEN Ind) { if (DEBUGLEVEL) maybe_warn(bnf,a,Ind); return bnfisintnorm_i(bnf, a, signe(a), bnfisintnormabs(bnf, mkvec2(a,fa)), 0); } /* return solutions of |Norm(x)| = |a| mod U(K) */ static GEN get_neabs(GEN bnf, GEN a, GEN Ind) { if (DEBUGLEVEL) maybe_warn(bnf,a,Ind); return bnfisintnormabs(bnf, a); } /* Let P(z)=z^2+Bz+C, convert t=u+v*z (mod P) solution of norm equation N(t)=A * to [x,y] = [u,-v] form: y^2P(x/y) = A */ static GEN ne2_to_xy(GEN t) { GEN u,v; if (typ(t) != t_POL) { u = t; v = gen_0; } else switch(degpol(t)) { case -1: u = v = gen_0; break; case 0: u = gel(t,2); v = gen_0; break; default: u = gel(t,2); v = gneg(gel(t,3)); } return mkvec2(u, v); } static GEN ne2V_to_xyV(GEN v) { long i, l; GEN w = cgetg_copy(v,&l); for (i=1; i= BITS_IN_LONG) return absZ_factor(rhs); F = absZ_factor_limit_strict(rhs, 500000, &U); return U? NULL: F; } /* Given a tnf structure as returned by thueinit, a RHS and * optionally the solutions to the norm equation, returns the solutions to * the Thue equation F(x,y)=a */ GEN thue(GEN tnf, GEN rhs, GEN ne) { pari_sp av = avma; GEN POL, C, L, x3, S; if (typ(tnf) == t_POL) tnf = thueinit(tnf, 0, DEFAULTPREC); if (!checktnf(tnf)) pari_err_TYPE("thue [please apply thueinit()]", tnf); if (typ(rhs) != t_INT) pari_err_TYPE("thue",rhs); if (ne && typ(ne) != t_VEC) pari_err_TYPE("thue",ne); /* solve P(x,y) = rhs <=> POL(L x, y) = C rhs, with POL monic in Z[X] */ POL = gel(tnf,1); C = gel(POL,2); rhs = gmul(C, rhs); if (typ(rhs) != t_INT) { set_avma(av); return cgetg(1, t_VEC); } if (!signe(rhs)) { GEN v = gel(tnf,2); set_avma(av); /* at least 2 irreducible factors, one of which has degree 1 */ if (typ(v) == t_VECSMALL && v[1] ==1) pari_err_DOMAIN("thue","#sols","=",strtoGENstr("oo"),rhs); return sol_0(); } L = gel(POL,3); POL = gel(POL,1); if (lg(tnf) == 8) { if (!ne) { GEN F = absZ_factor(rhs); ne = get_ne(tnf_get_bnf(tnf), rhs, F, tnf_get_Ind(tnf)); } if (lg(ne) == 1) { set_avma(av); return cgetg(1, t_VEC); } S = LargeSols(POL, tnf, rhs, ne); } else if (typ(gel(tnf,3)) == t_REAL) { /* Case s=0. All solutions are "small". */ GEN bnf = tnf_get_bnf(tnf); GEN c0 = gel(tnf,3), F; x3 = sqrtnr(mulir(absi_shallow(rhs),c0), degpol(POL)); x3 = addrr(x3, dbltor(0.1)); /* guard from round-off errors */ S = cgetg(1,t_VEC); if (!ne && typ(bnf) == t_VEC && expo(x3) > 10) { F = absZ_factor_if_easy(rhs, x3); if (F) ne = get_ne(bnf, rhs, F, gen_1); } if (ne) { if (lg(ne) == 1) { set_avma(av); return cgetg(1,t_VEC); } if (degpol(POL) == 2) /* quadratic imaginary */ { GEN u = NULL; long w = 2; if (typ(bnf) == t_VEC) { u = bnf_get_tuU(bnf); w = bnf_get_tuN(bnf); } else { GEN D = coredisc(ZX_disc(POL)); if (cmpis(D, -4) >= 0) { GEN F, T = quadpoly_i(D); w = equalis(D, -4)? 4: 6; setvarn(T, fetch_var_higher()); F = gcoeff(nffactor(POL, T), 1, 1); u = gneg(lift_shallow(gel(F,2))); delete_var(); } } if (w == 4) /* u = I */ ne = shallowconcat(ne, RgXQV_RgXQ_mul(ne,u,POL)); else if (w == 6) /* u = j */ { GEN u2 = RgXQ_sqr(u,POL); ne = shallowconcat1(mkvec3(ne, RgXQV_RgXQ_mul(ne,u,POL), RgXQV_RgXQ_mul(ne,u2,POL))); } S = ne2V_to_xyV(ne); S = filter_sol_Z(S); S = shallowconcat(S, RgV_neg(S)); } } if (lg(S) == 1) S = SmallSols(S, x3, POL, rhs); } else if (typ(gel(tnf,3)) == t_INT) /* reducible case, pure power*/ { GEN bnf, ne1 = NULL, ne2 = NULL; long e = itos( gel(tnf,3) ); if (!Z_ispowerall(rhs, e, &rhs)) { set_avma(av); return cgetg(1, t_VEC); } tnf = gel(tnf,2); bnf = tnf_get_bnf(tnf); ne = get_neabs(bnf, rhs, lg(tnf)==8?tnf_get_Ind(tnf): gen_1); ne1= bnfisintnorm_i(bnf,rhs,1,ne,0); S = thue(tnf, rhs, ne1); if (!odd(e) && lg(tnf)==8) /* if s=0, norms are positive */ { ne2 = bnfisintnorm_i(bnf,rhs,-1,ne,0); S = shallowconcat(S, thue(tnf, negi(rhs), ne2)); } } else /* other reducible cases */ { /* solve f^e * g = rhs, f irreducible factor of smallest degree */ GEN P, D, v = gel(tnf, 2), R = gel(tnf, 3); long i, l, e = v[2], va = v[3], vb = v[4]; P = cgetg(lg(POL), t_POL); P[1] = POL[1]; D = divisors(rhs); l = lg(D); S = cgetg(1,t_VEC); for (i = 1; i < l; i++) { GEN Rab, df = gel(D,i), dg = gel(D,l-i); /* df*dg=|rhs| */ if (e > 1 && !Z_ispowerall(df, e, &df)) continue; /* Rab: univariate polynomial in Z[Y], whose roots are the possible y. */ /* Here and below, Rab != 0 */ if (signe(rhs) < 0) dg = negi(dg); /* df*dg=rhs */ Rab = gsubst(gsubst(R, va, df), vb, dg); sols_from_R(Rab, &S,P,POL,rhs); Rab = gsubst(gsubst(R, va, negi(df)), vb, odd(e)? negi(dg): dg); sols_from_R(Rab, &S,P,POL,rhs); } } S = filter_sol_x(S, L); S = gen_sort_uniq(S, (void*)lexcmp, cmp_nodata); return gerepileupto(av, S); } /********************************************************************/ /** **/ /** 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); } } /* 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)); set_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)); set_avma(av); } } } static int get_sol_abs(struct sol_abs *T, GEN bnf, GEN nf, GEN fact, GEN *ptPR) { GEN P = gel(fact,1), E = gel(fact,2), PR; long N = nf_get_degree(nf), nP = lg(P)-1, Ngen, max, nPR, i, j; max = nP*N; /* upper bound for T->nPR */ T->f = new_chunk(max+1); T->n = new_chunk(max+1); T->next = new_chunk(max+1); *ptPR = PR = cgetg(max+1, t_COL); /* 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"); 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); if (bnf) { T->cyc = bnf_get_cyc(bnf); Ngen = lg(T->cyc)-1; } else { T->cyc = NULL; Ngen = 0; } 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; } /* Return unit of norm -1 (NULL if it doesn't exit). */ static GEN get_unit_1(GEN bnf, long flag) { GEN v; long i; if (DEBUGLEVEL > 2) err_printf("looking for a fundamental unit of norm -1\n"); if (odd(nf_get_degree(bnf_get_nf(bnf)))) return gen_m1; v = nfsign_fu(bnf, NULL); for (i = 1; i < lg(v); i++) if (Flv_sum( gel(v,i), 2)) { GEN fu = NULL; if (flag) { fu = bnf_build_cheapfu(bnf); if (!fu) fu = bnf_compactfu(bnf); } if (!fu) fu = bnf_get_fu(bnf); return gel(fu, i); } return NULL; } GEN bnfisintnormabs0(GEN bnf, GEN a, long flag) { struct sol_abs T; GEN nf, res, PR, F; long i, fl = nf_FORCE | nf_GEN_IF_PRINCIPAL | (flag ? nf_GENMAT: 0); if ((F = check_arith_all(a,"bnfisintnormabs"))) { a = typ(a) == t_VEC? gel(a,1): factorback(F); if (signe(a) < 0) F = clean_Z_factor(F); } nf = bnf_get_nf(bnf); if (!signe(a)) return mkvec(gen_0); if (is_pm1(a)) return mkvec(gen_1); if (!F) F = absZ_factor(a); if (!get_sol_abs(&T, bnf, nf, F, &PR)) return cgetg(1, t_VEC); /* |a| > 1 => T.nPR > 0 */ res = cgetg(T.sindex+1, t_VEC); for (i=1; i<=T.sindex; i++) { GEN x = vecsmall_to_col( gel(T.normsol,i) ); x = isprincipalfact(bnf, NULL, PR, x, fl); if (!flag) x = nf_to_scalar_or_alg(nf, x); gel(res,i) = x; /* solution, up to sign */ } return res; } GEN bnfisintnormabs(GEN bnf, GEN a) { return bnfisintnormabs0(bnf, a, 0); } /* true nf */ GEN ideals_by_norm(GEN nf, GEN a) { struct sol_abs T; GEN res, PR, F; long i; if ((F = check_arith_pos(a,"ideals_by_norm"))) a = typ(a) == t_VEC? gel(a,1): factorback(F); if (is_pm1(a)) return mkvec(trivial_fact()); if (!F) F = absZ_factor(a); if (!get_sol_abs(&T, NULL, nf, F, &PR)) return cgetg(1, t_VEC); res = cgetg(T.sindex+1, t_VEC); for (i=1; i<=T.sindex; i++) { GEN x = vecsmall_to_col( gel(T.normsol,i) ); gel(res,i) = famat_remove_trivial(mkmat2(PR, x)); } return res; } /* largest prime used in factorbase */ static ulong bnf_get_lastp(GEN bnf) { GEN vbase = gel(bnf,5); long l = lg(vbase), i; ulong P = 0; for (i = 1; i < l; i++) { GEN pr = gel(vbase,i); ulong p = itou(pr_get_p(pr)); if (p > P) P = p; } return P; } /* true bnf; z = bnfisintnormabs0(bnf,a,flag), sa = 1 or -1, * return bnfisintnorm0(bnf,sa*|a|,flag). If flag is set, allow returning * elements in factored form */ static GEN bnfisintnorm_i(GEN bnf, GEN a, long sa, GEN z, long flag) { GEN nf = bnf_get_nf(bnf), T = nf_get_pol(nf), f = nf_get_index(nf), unit = gen_0; GEN Tp, A = signe(a) == sa? a: negi(a); long sNx, i, j, N = degpol(T), l = lg(z); ulong p, Ap = 0; /* gcc -Wall */ forprime_t S; if (!signe(a)) return z; u_forprime_init(&S, flag? bnf_get_lastp(bnf): 3, ULONG_MAX); while((p = u_forprime_next(&S))) if (umodiu(f,p) && (Ap = umodiu(A,p))) break; Tp = ZX_to_Flx(T,p); /* p > 2 doesn't divide A nor Q_denom(z in Z_K)*/ /* update z in place to get correct signs: multiply by unit of norm -1 if * it exists, otherwise delete solution with wrong sign */ for (i = j = 1; i < l; i++) { GEN x = gel(z,i); long tx = typ(x); switch(tx) { case t_POL: { GEN dx, y = Q_remove_denom(x,&dx); ulong Np = Flx_resultant(Tp, ZX_to_Flx(y,p), p); ulong dA = dx? Fl_mul(Ap, Fl_powu(umodiu(dx,p), N, p), p): Ap; /* Nx = Res(T,y) / dx^N = A or -A. Check mod p */ sNx = dA == Np? sa: -sa; break; } case t_MAT: { GEN G = gel(x,1), E = gel(x,2); long k, lG = lg(G); GEN g = cgetg(lG, t_VECSMALL), e = cgetg(lG, t_VECSMALL); ulong Np; for (k = 1; k < lG; k++) { GEN NGk = nfnorm(nf, gel(G,k)); (void)Z_lvalrem(NGk, p, &NGk); g[k] = umodiu(NGk, p); e[k] = umodiu(gel(E,k), p-1); } /* N.B. p can appear in Norm(G_k), where G = \prod G_k^{e_k}, * but total v_p(Norm(G)) = v_p(A) = 0 */ Np = Flv_factorback(g, e, p); sNx = Np == Ap? sa: -sa; break; } default: sNx = gsigne(x) < 0 && odd(N) ? -1 : 1; } if (sNx != sa) { if (unit == gen_0) unit = get_unit_1(bnf, flag); if (!unit) { if (DEBUGLEVEL > 2) err_printf("%Ps eliminated because of sign\n",x); continue; } switch(tx) { case t_POL: x = (unit == gen_m1)? RgX_neg(x): RgXQ_mul(unit,x,T); break; case t_MAT: x = famat_mul(x, unit); break; default: x = (unit == gen_m1)? gneg(x): RgX_Rg_mul(unit,x); break; } } gel(z,j++) = x; } setlg(z, j); return z; } GEN bnfisintnorm(GEN bnf, GEN a) { return bnfisintnorm0(bnf, a, 0); } GEN bnfisintnorm0(GEN bnf, GEN a, long flag) { pari_sp av = avma; GEN ne; bnf = checkbnf(bnf); if (flag < 0 || flag > 1) pari_err_FLAG("bnfisintnorm"); ne = bnfisintnormabs0(bnf, a, flag); switch(typ(a)) { case t_VEC: a = gel(a,1); break; case t_MAT: a = factorback(a); break; } return gerepilecopy(av, bnfisintnorm_i(bnf, a, signe(a), ne, flag)); } pari-2.17.2/src/modules/krasner.c0000644000175000017500000006314014760123736015251 0ustar billbill/* Copyright (C) 2009 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_padicfields /************************************************************/ /* Computation of all the extensions of a given */ /* degree of a p-adic field */ /* Xavier Roblot */ /************************************************************/ /* cf. Math. Comp, vol. 70, No. 236, pp. 1641-1659 for more details. Note that n is now e (since the e from the paper is always = 1) and l is now f */ /* Structure for a given type of extension */ typedef struct { GEN p; long e, f, j; long a, b, c; long v; /* auxiliary variable */ long r; /* pr = p^r */ GEN pr; /* p-adic precision for poly. reduction */ GEN q, qm1; /* p^f, q - 1 */ GEN T; /* polynomial defining K^ur */ GEN frob; /* Frobenius acting of the root of T (mod pr) */ GEN u; /* suitable root of unity (expressed in terms of the root of T) */ GEN nbext; /* number of extensions */ GEN roottable; /* table of roots of polynomials over the residue field */ GEN pk; /* powers of p: [p^1, p^2, ..., p^c] */ } KRASNER_t; /* Structure containing the field data (constructed with FieldData) */ typedef struct { GEN p; GEN top; /* absolute polynomial of a = z + pi (mod pr) */ GEN topr; /* top mod p */ GEN z; /* root of T in terms of a (mod pr) */ GEN eis; /* relative polynomial of pi in terms of z (mod pr) */ GEN pi; /* prime element in terms of a */ GEN ipi; /* p/pi in terms of a (mod pr) (used to divide by pi) */ GEN pik; /* [1, pi, ..., pi^(e-1), pi^e/p] in terms of a (mod pr). Note the last one is different! */ long cj; /* number of conjugate fields */ } FAD_t; #undef CHECK /* Eval P(x) assuming P has positive coefficients and the result is a long */ static ulong ZX_z_eval(GEN P, ulong x) { long i, l = lg(P); ulong z; if (typ(P) == t_INT) return itou(P); if (l == 2) return 0; z = itou(gel(P, l-1)); for (i = l-2; i > 1; i--) z = z*x + itou(gel(P,i)); return z; } /* Eval P(x, y) assuming P has positive coefficients and the result is a long */ static ulong ZXY_z_eval(GEN P, ulong x, ulong y) { long i, l = lg(P); ulong z; if (l == 2) return 0; z = ZX_z_eval(gel(P, l-1), y); for (i = l-2; i > 1; i--) z = z*x + ZX_z_eval(gel(P, i), y); return z; } /* P an Fq[X], where Fq = Fp[Y]/(T(Y)), a an FpX representing the automorphism * y -> a(y). Return a(P), applying a() coefficientwise. */ static GEN FqX_FpXQ_eval(GEN P, GEN a, GEN T, GEN p) { long i, l; GEN Q = cgetg_copy(P, &l); Q[1] = P[1]; for (i = 2; i < l; i++) { GEN cf = gel(P, i); if (typ(cf) == t_POL) { switch(degpol(cf)) { case -1: cf = gen_0; break; case 0: cf = gel(cf,2); break; default: cf = FpX_FpXQ_eval(cf, a, T, p); cf = simplify_shallow(cf); break; } } gel(Q, i) = cf; } return Q; } /* Sieving routines */ static GEN InitSieve(long l) { return zero_F2v(l); } static long NextZeroValue(GEN sv, long i) { for(; i <= sv[1]; i++) if (!F2v_coeff(sv, i)) return i; return 0; /* sieve is full or out of the sieve! */ } static void SetSieveValue(GEN sv, long i) { if (i >= 1 && i <= sv[1]) F2v_set(sv, i); } /* return 1 if the data verify Ore condition and 0 otherwise */ static long VerifyOre(GEN p, long e, long j) { long nv, b, vb, nb; if (j < 0) return 0; nv = e * u_pval(e, p); b = j%e; if (b == 0) return (j == nv); if (j > nv) return 0; /* j < nv */ vb = u_pval(b, p); nb = vb*e; return (nb <= j); } /* Given [K:Q_p] = m and disc(K/Q_p) = p^d, return all decompositions K/K^ur/Q_p * as [e, f, j] with * K^ur/Q_p unramified of degree f, * K/K^ur totally ramified of degree e and discriminant p^(e+j-1); * thus d = f*(e+j-1) and j > 0 iff ramification is wild */ static GEN possible_efj_by_d(GEN p, long m, long d) { GEN rep, div; long i, ctr, l; if (d == 0) return mkvec(mkvecsmall3(1, m, 0)); /* unramified */ div = divisorsu(ugcd(m, d)); l = lg(div); ctr = 1; rep = cgetg(l, t_VEC); for (i = 1; i < l; i++) { long f = div[i], e = m/f, j = d/f - e + 1; if (VerifyOre(p, e, j)) gel(rep, ctr++) = mkvecsmall3(e, f, j); } setlg(rep, ctr); return rep; } /* return the number of extensions corresponding to (e,f,j) */ static GEN NumberExtensions(KRASNER_t *data) { ulong pp, pa; long e, a, b; GEN p, q, s0, p1; e = data->e; p = data->p; q = data->q; a = data->a; /* floor(j/e) <= v_p(e), hence p^a | e */ b = data->b; /* j % e */ if (is_bigint(p)) /* implies a = 0 */ return b == 0? utoipos(e): mulsi(e, data->qm1); pp = p[2]; switch(a) { case 0: pa = 1; s0 = utoipos(e); break; case 1: pa = pp; s0 = mului(e, powiu(q, e / pa)); break; default: pa = upowuu(pp, a); /* p^a */ s0 = mulsi(e, powiu(q, (e / pa) * ((pa - 1) / (pp - 1)))); } /* s0 = e * q^(e*sum(p^-i, i=1...a)) */ if (b == 0) return s0; /* q^floor((b-1)/p^(a+1)) */ p1 = powiu(q, sdivsi(b-1, muluu(pa, pp))); return mulii(mulii(data->qm1, s0), p1); } static GEN get_topx(KRASNER_t *data, GEN eis) { GEN p1, p2, rpl, c; pari_sp av; long j; /* top poly. is the minimal polynomial of root(T) + root(eis) */ if (data->f == 1) return eis; c = FpX_neg(pol_x(data->v),data->pr); rpl = FqX_translate(eis, c, data->T, data->pr); p1 = p2 = rpl; av = avma; for (j = 1; j < data->f; j++) { /* compute conjugate polynomials using the Frobenius */ p1 = FqX_FpXQ_eval(p1, data->frob, data->T, data->pr); p2 = FqX_mul(p2, p1, data->T, data->pr); if (gc_needed(av,2)) gerepileall(av, 2, &p1,&p2); } return simplify_shallow(p2); /* ZX */ } /* eis (ZXY): Eisenstein polynomial over the field defined by T. * topx (ZX): absolute equation of root(T) + root(eis). * 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, p2, p3, z, 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); if (data->f == 1) z = gen_0; else { /* Compute a root of T in K(top) using Hensel's lift */ z = pol_x(data->v); p1 = FpX_deriv(data->T, data->p); /* First lift to a root mod p */ for (;;) { p2 = FpX_FpXQ_eval(data->T, z, fdata->top, data->p); if (gequal0(p2)) break; p3 = FpX_FpXQ_eval(p1, z, fdata->top, data->p); z = FpX_sub(z, FpXQ_div(p2, p3, fdata->top, data->p), data->p); } /* Then a root mod p^r */ z = ZpX_ZpXQ_liftroot(data->T, z, fdata->top, data->p, data->r); } fdata->z = z; fdata->eis = eis; fdata->pi = Fq_sub(pol_x(data->v), fdata->z, 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 set to pi^e/p (so we compute pi^e with one extra precision) */ p2 = mulii(data->pr, data->p); p1 = FpXQ_powers(fdata->pi, data->e, fdata->topr, p2); 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) return gc_NULL(av); } return FpX_red(P, pp); } /* return pol# = pol~/pi^vpi(pol~) mod pp where pol~(x) = pol(pi.x + beta) * has coefficients in the field defined by top and pi is a prime element */ static GEN GetSharp(FAD_t *fdata, GEN pp, GEN ppp, GEN pol, GEN beta, long *pl) { GEN p1, p2; long i, v, l, d = degpol(pol); pari_sp av = avma; if (!gequal0(beta)) p1 = FqX_translate(pol, beta, fdata->topr, pp); else p1 = shallowcopy(pol); p2 = p1; for (v = 0;; v++) { for (i = 0; i <= v; i++) { GEN c = gel(p2, i+2); c = DivideByPi(fdata, pp, ppp, c); if (!c) break; gel(p2, i+2) = c; } if (i <= v) break; p1 = shallowcopy(p2); } if (!v) pari_err_BUG("GetSharp [no division]"); for (l = v; l >= 0; l--) { GEN c = gel(p1, l+2); c = DivideByPi(fdata, pp, ppp, c); if (!c) { break; } } *pl = l; if (l < 2) return NULL; /* adjust powers */ for (i = v+1; i <= d; i++) gel(p1, i+2) = Fq_mul(gel(p1, i+2), gel(fdata->pik, i-v+1), fdata->topr, pp); return gerepilecopy(av, normalizepol(p1)); } /* 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; if (data->f == 1) pol = FpXY_evalx(pol, gen_0, data->p); else pol = FqX_red(pol, data->T, 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->T, 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++) guncloneNULL(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 nonzero, 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) { long l; pol = GetSharp(fdata, pp, ppp, pol, alpha, &l); if (l <= 1) return l; /* 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. Computations 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 nonzero 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->z, fdata->top, data->pr); nb = RootCountingAlgorithm(data, fdata, p1, 1); if (nb) return gc_long(av, nb); if (j < data->f) pol = FqX_FpXQ_eval(pol, data->frob, data->T, data->pr); } return gc_long(av,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); set_avma(av); return; } nb = 0; for (j = 1; j <= data->f; j++) { /* Transform to pol. in z to pol. in a */ GEN p1 = FqX_FpXQ_eval(pol, fdata->z, fdata->top, data->pr); nb += RootCountingAlgorithm(data, fdata, p1, 0); /* Look at the roots of conjugates polynomials */ if (j < data->f) pol = FqX_FpXQ_eval(pol, data->frob, data->T, data->pr); } set_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; long g = ugcdui(data->e, data->qm1); /* (e, q-1) */ GEN rep, eis, Xe = gpowgs(pol_x(0), data->e), m = stoi(data->e / g); rep = zerovec(g); eis = gadd(Xe, data->p); gel(rep, 1) = mkvec2(get_topx(data,eis), m); if (g > 1) { ulong pmodg = umodiu(data->p, g); long r = 1, ct = 1; GEN sv = InitSieve(g-1); /* let Frobenius act to get a minimal set of polynomials over Q_p */ while (r) { long gr; GEN p1 = (typ(data->u) == t_INT)? mulii(Fp_powu(data->u, r, data->p), data->p): ZX_Z_mul(FpXQ_powu(data->u, r, data->T, data->p), data->p); eis = gadd(Xe, p1); /* add cst coef */ ct++; gel(rep, ct) = mkvec2(get_topx(data,eis), m); gr = r; do { SetSieveValue(sv, gr); gr = Fl_mul(gr, pmodg, g); } while (gr != r); r = NextZeroValue(sv, r); } setlg(rep, ct+1); } return gerepilecopy(av, rep); } static long function_l(GEN p, long a, long b, long i) { long l = 1 + a - z_pval(i, p); if (i < b) l++; return (l < 1)? 1: l; } /* Structure of the coefficients set Omega. Each coefficient is [start, zr] * meaning all the numbers of the form: * zeta_0 * p^start + ... + zeta_s * p^c (s = c - start) * with zeta_i roots of unity (powers of zq + zero), zeta_0 = 0 is * possible iff zr = 1 */ static GEN StructureOmega(KRASNER_t *data, GEN *pnbpol) { GEN nbpol, O = cgetg(data->e + 1, t_VEC); long i; /* i = 0 */ gel(O, 1) = mkvecsmall2(1, 0); nbpol = mulii(data->qm1, powiu(data->q, data->c - 1)); for (i = 1; i < data->e; i++) { long v_start, zero = 0; GEN nbcf, p1; v_start = function_l(data->p, data->a, data->b, i); p1 = powiu(data->q, data->c - v_start); if (i == data->b) nbcf = mulii(p1, data->qm1); else { nbcf = mulii(p1, data->q); zero = 1; } gel(O, i+1) = mkvecsmall2(v_start, zero); nbpol = mulii(nbpol, nbcf); } *pnbpol = nbpol; return O; } /* a random element of the finite field */ static GEN RandomFF(KRASNER_t *data) { long i, l = data->f + 2, p = itou(data->p); GEN c = cgetg(l, t_POL); c[1] = evalvarn(data->v); for (i = 2; i < l; i++) gel(c, i) = utoi(random_Fl(p)); return ZX_renormalize(c, l); } static GEN RandomPol(KRASNER_t *data, GEN Omega) { long i, j, l = data->e + 3, end = data->c; GEN pol = cgetg(l, t_POL); pol[1] = evalsigne(1) | evalvarn(0); for (i = 1; i <= data->e; i++) { GEN c, cf = gel(Omega, i); long st = cf[1], zr = cf[2]; /* c = sum_{st <= j <= end} x_j p^j, where x_j are random Fq mod (p,upl) * If (!zr), insist on x_st != 0 */ for (;;) { c = RandomFF(data); if (zr || signe(c)) break; } for (j = 1; j <= end-st; j++) c = ZX_add(c, ZX_Z_mul(RandomFF(data), gel(data->pk, j))); c = ZX_Z_mul(c, gel(data->pk, st)); c = FpX_red(c, data->pr); switch(degpol(c)) { case -1: c = gen_0; break; case 0: c = gel(c,2); break; } gel(pol, i+1) = c; } gel(pol, i+1) = gen_1; /* monic */ return pol; } static void CloneFieldData(FAD_t *fdata) { fdata->top = gclone(fdata->top); fdata->topr= gclone(fdata->topr); fdata->z = gclone(fdata->z); 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->z); gunclone(fdata->eis); gunclone(fdata->pi); gunclone(fdata->ipi); gunclone(fdata->pik); } static GEN WildlyRamifiedCase(KRASNER_t *data) { long nbext, ct, fd, nb = 0, j; GEN nbpol, rpl, rep, Omega; FAD_t **vfd; pari_timer T; pari_sp av = avma, av2; /* Omega = vector giving the structure of the set Omega */ /* nbpol = number of polynomials to consider = |Omega| */ Omega = StructureOmega(data, &nbpol); nbext = itos_or_0(data->nbext); if (!nbext || (nbext & ~LGBITS)) pari_err_OVERFLOW("padicfields [too many extensions]"); if (DEBUGLEVEL>0) { err_printf("There are %ld extensions to find and %Ps polynomials to consider\n", nbext, nbpol); timer_start(&T); } vfd = (FAD_t**)new_chunk(nbext); for (j = 0; j < nbext; j++) vfd[j] = (FAD_t*)new_chunk(sizeof(FAD_t)); ct = 0; fd = 0; av2 = avma; while (fd < nbext) { /* Jump randomly among the polynomials : seems best... */ rpl = RandomPol(data, Omega); if (DEBUGLEVEL>3) err_printf("considering polynomial %Ps\n", rpl); 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 *f = (FAD_t*)vfd[ct]; FieldData(data, f, rpl, topx); CloneFieldData(f); NbConjugateFields(data, f); nb = f->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)); } set_avma(av2); } rep = cgetg(ct+1, t_VEC); for (j = 0; j < ct; j++) { FAD_t *f = (FAD_t*)vfd[j]; GEN topx = ZX_copy(f->top); setvarn(topx, 0); gel(rep, j+1) = mkvec2(topx, stoi(f->cj)); FreeFieldData(f); } FreeRootTable(data->roottable); return gerepileupto(av, rep); } /* return the minimal polynomial T of a generator of K^ur and the expression (mod pr) * in terms of T of a root of unity u such that u is l-maximal for all primes l * dividing g = (e,q-1). */ static void setUnramData(KRASNER_t *d) { if (d->f == 1) { d->T = pol_x(d->v); d->u = pgener_Fp(d->p); d->frob = pol_x(d->v); } else { GEN L, z, T, p = d->p; d->T = T = init_Fq(p, d->f, d->v); L = gel(factoru(ugcdui(d->e, d->qm1)), 1); z = gener_FpXQ_local(T, p, zv_to_ZV(L)); d->u = ZpXQ_sqrtnlift(pol_1(d->v), d->qm1, z, T, p, d->r); d->frob = ZpX_ZpXQ_liftroot(T, FpXQ_pow(pol_x(d->v), p, T, p), T, p, d->r); } } /* return [ p^1, p^2, ..., p^c ] */ static GEN get_pk(KRASNER_t *data) { long i, l = data->c + 1; GEN pk = cgetg(l, t_VEC), p = data->p; gel(pk, 1) = p; for (i = 2; i <= data->c; i++) gel(pk, i) = mulii(gel(pk, i-1), p); return pk; } /* Compute an absolute polynomial for all the totally ramified extensions of Q_p(z) of degree e and discriminant p^{e + j - 1} where z is a root of upl defining an unramified extension of Q_p */ /* See padicfields for the meaning of flag */ static GEN GetRamifiedPol(GEN p, GEN efj, long flag) { long e = efj[1], f = efj[2], j = efj[3], i, l; const long v = 1; GEN L, pols; KRASNER_t data; pari_sp av = avma; if (DEBUGLEVEL>1) err_printf(" Computing extensions with decomposition [e, f, j] = [%ld, %ld, %ld]\n", e,f,j); data.p = p; data.e = e; data.f = f; data.j = j; data.a = j/e; data.b = j%e; data.c = (e+2*j)/e+1; data.q = powiu(p, f); data.qm1 = subiu(data.q, 1); data.v = v; data.r = 1 + (long)ceildivuu(2*j + 3, e); /* enough precision */ data.pr = powiu(p, data.r); data.nbext = NumberExtensions(&data); if (flag == 2) return data.nbext; setUnramData(&data); if (DEBUGLEVEL>1) err_printf(" Unramified part %Ps\n", data.T); data.roottable = NULL; if (j) { if (lgefint(data.q) == 3) { ulong npol = upowuu(data.q[2], e+1); if (npol && npol < (1<<19)) data.roottable = const_vec(npol, NULL); } data.pk = get_pk(&data); L = WildlyRamifiedCase(&data); } else L = TamelyRamifiedCase(&data); pols = cgetg_copy(L, &l); if (flag == 1) { GEN E = utoipos(e), F = utoipos(f), D = utoi(f*(e+j-1)); for (i = 1; i < l; i++) { GEN T = gel(L,i); gel(pols, i) = mkvec5(ZX_copy(gel(T, 1)), E,F,D, icopy(gel(T, 2))); } } else { for (i = 1; i < l; i++) { GEN T = gel(L,i); gel(pols, i) = ZX_copy(gel(T,1)); } } return gerepileupto(av, pols); } static GEN possible_efj(GEN p, long m) { /* maximal possible discriminant valuation d <= m * (1+v_p(m)) - 1 */ /* 1) [j = 0, tame] d = m - f with f | m and v_p(f) = v_p(m), or * 2) [j > 0, wild] d >= m, j <= v_p(e)*e */ ulong m1, pve, pp = p[2]; /* pp used only if v > 0 */ long ve, v = u_pvalrem(m, p, &m1); GEN L, D = divisorsu(m1); long i, taum1 = lg(D)-1, nb = 0; if (v) { for (pve = 1,ve = 1; ve <= v; ve++) { pve *= pp; nb += pve * ve; } nb = itos_or_0(muluu(nb, zv_sum(D))); if (!nb || is_bigint( mului(pve, sqru(v)) ) ) pari_err_OVERFLOW("padicfields [too many ramification possibilities]"); } nb += taum1; /* upper bound for the number of possible triples [e,f,j] */ L = cgetg(nb + 1, t_VEC); /* 1) tame */ for (nb=1, i=1; i < lg(D); i++) { long e = D[i], f = m / e; gel(L, nb++) = mkvecsmall3(e, f, 0); } /* 2) wild */ /* Ore's condition: either * 1) j = v_p(e) * e, or * 2) j = a e + b, with 0 < b < e and v_p(b) <= a < v_p(e) */ for (pve = 1, ve = 1; ve <= v; ve++) { pve *= pp; /* = p^ve */ for (i = 1; i < lg(D); i++) { long a,b, e = D[i] * pve, f = m / e; for (b = 1; b < e; b++) for (a = u_lval(b, pp); a < ve; a++) gel(L, nb++) = mkvecsmall3(e, f, a*e + b); gel(L, nb++) = mkvecsmall3(e, f, ve*e); } } setlg(L, nb); return L; } #ifdef CHECK static void checkpols(GEN p, GEN EFJ, GEN pols) { GEN pol, p1, p2; long c1, c2, e, f, j, i, l = lg(pols); if (typ(pols) == t_INT) return; e = EFJ[1]; f = EFJ[2]; j = EFJ[3]; for (i = 1; i < l; i++) { pol = gel(pols, i); if (typ(pol) == t_VEC) pol = gel(pol, 1); if (!polisirreducible(pol)) pari_err_BUG("Polynomial is reducible"); p1 = poldisc0(pol, -1); if (gvaluation(p1, p) != f*(e+j-1)) pari_err_BUG("Discriminant is incorrect"); /* only compute a p-maximal order */ p1 = nfinit0(mkvec2(pol, mkvec(p)), 0, DEFAULTPREC); p2 = idealprimedec(p1, p); if(lg(p2) > 2) pari_err_BUG("Prime p is split"); p2 = gel(p2, 1); if (cmpis(gel(p2, 3), e)) pari_err_BUG("Ramification index is incorrect"); if (cmpis(gel(p2, 4), f)) pari_err_BUG("inertia degree is incorrect"); } if (l == 2) return; if (e*f > 20) return; /* TODO: check that (random) distinct polynomials give nonisomorphic extensions */ for (i = 1; i < 3*l; i++) { c1 = random_Fl(l-1)+1; c2 = random_Fl(l-1)+1; if (c1 == c2) continue; p1 = gel(pols, c1); if (typ(p1) == t_VEC) p1 = gel(p1, 1); p2 = gel(pols, c2); if (typ(p2) == t_VEC) p2 = gel(p2, 1); pol = polcompositum0(p1, p2, 0); pol = gel(pol, 1); if (poldegree(pol, -1) > 100) continue; p1 = factorpadic(pol, p, 2); p1 = gmael(p1, 1, 1); if (poldegree(p1, -1) == e*f) pari_err_BUG("fields are isomorphic"); /* p1 = nfinit0(mkvec2(pol, mkvec(p)), 0, DEFAULTPREC); p2 = idealprimedec_galois(p1, p); if (!cmpis(mulii(gel(p2, 3), gel(p2, 4)), e*f)) pari_err_BUG("fields are isomorphic"); */ } } #endif static GEN pols_from_efj(pari_sp av, GEN EFJ, GEN p, long flag) { long i, l; GEN L = cgetg_copy(EFJ, &l); if (l == 1) { set_avma(av); return flag == 2? gen_0: cgetg(1, t_VEC); } for (i = 1; i < l; i++) { gel(L,i) = GetRamifiedPol(p, gel(EFJ,i), flag); #ifdef CHECK checkpols(p, gel(EFJ, i), gel(L, i)); #endif } if (flag == 2) return gerepileuptoint(av, ZV_sum(L)); return gerepilecopy(av, shallowconcat1(L)); } /* return a minimal list of polynomials generating all the extensions of Q_p of given degree N; if N is a t_VEC [n,d], return extensions of degree n and discriminant p^d. */ /* Return only the polynomials if flag = 0 (default), also the ramification degree, the residual degree and the discriminant if flag = 1 and only the number of extensions if flag = 2 */ GEN padicfields0(GEN p, GEN N, long flag) { pari_sp av = avma; long m = 0, d = -1; GEN L; if (typ(p) != t_INT) pari_err_TYPE("padicfields",p); /* be nice to silly users */ if (!BPSW_psp(p)) pari_err_PRIME("padicfields",p); switch(typ(N)) { case t_VEC: if (lg(N) != 3) pari_err_TYPE("padicfields",N); d = gtos(gel(N,2)); N = gel(N,1); /* fall through */ case t_INT: m = itos(N); if (m <= 0) pari_err_DOMAIN("padicfields", "degree", "<=", gen_0,N); break; default: pari_err_TYPE("padicfields",N); } if (d >= 0) return padicfields(p, m, d, flag); L = possible_efj(p, m); return pols_from_efj(av, L, p, flag); } GEN padicfields(GEN p, long m, long d, long flag) { long av = avma; GEN L = possible_efj_by_d(p, m, d); return pols_from_efj(av, L, p, flag); } pari-2.17.2/src/modules/groupid.c0000644000175000017500000005105214676526175015266 0ustar billbill/* Copyright (C) 2003 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #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_orderu(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) /*2qr*/ { long q = p[2],q2 = q*q, qc = 1-q+q2, qd = 1+q+q2; long r = p[3],r2 = r*r, rc = 1-r+r2, rd = 1+r+r2; long pmq = (r%q==1)? 2: 0; if (pmq && s==3*r*(q2-q)+rd) return 1; /* r:2q */ if (pmq && s==3*(r2+(q2-q-1)*r+1)) return 2; /* r:qx2 */ if (s==qd*rc) return 1+pmq; /* D2qxr */ if (s==rd*qc) return 2+pmq; /* D2rxq */ if (s==3*qc*rc) return 4+pmq; /* 2qr */ return 3+pmq; /* q:2+r:2 */ } 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, 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, 126, 1533, 2037, 3397, 3477, 2749, 7869, 777, 937, 721, 1281, 1425, 2881, 1369, 1849, 1201, 3225, -1, 132, 4995, 2947, 2595, 8547, 1663, 3441, 2639, 3663, 2463, 5439, -1, 136, 3547, 11739, 1499, 3275, 3207, 3139, 2183, 2115, 6279, 5187, 7371, 987, 1159, 2047, 4095, -1, 140, 4429, 3885, 2989, 9933, 3053, 1613, 1697, 3297, 3569, 2849, 6321, -1, -1}; long i; const long *t; for(t=tab;*t!=-1;t++) { if (t[0]==n) { for(i=1; t[i] != -1; i++) if (t[i]==s) return i; return -1; } while (*t>=0) t++; } } { const long tab[]={ 16, 1710031, 550075, 70099, 70075, 870059, 110059, 30079, 30071, 30063, 470131, 70155, 70107, 110115, 310307, -1, 32, 6830063, 150323, 1830171, /*230171*/0, 230227, 30283, 30251, 30203, /*70267*/0, 70219, 110227, /*230171*/0, /*70187*/0, /*70187*/0, 110155, 3430123, 430123, 30191, 30175, 30159, 1110387, 150563, 150387, 230323, 230411, 230299, 70619, 70467, 70355, /*70379*/0, /*70379*/0, /*70267*/0, 70291, 70555, 70331, 1750291, 230291, 430275, 70411, 70363, 70315, 110331, 30371, 30323, 950819, 150995, 150643, 230691, 30747, 30635, 632451, -1, 48, 430156, 11970124, 10219, 430324, 110324, 30396, 30444, 30348, 230300, 110300, 230396, /*70396*/0, /*70396*/0, 70540, 30412, 30364, 30380, 30332, 70492, 3850300, 490396, 490300, 6090236, 770236, 210316, 210284, 210252, 30299, 30371, 30363, 110299, 70311, 110271, 70588, 230732, 70876, 110636, 30868, 30628, 30596, 30644, 150684, 70828, 3290524, 490620, 490428, 770460, 30627, 70571, 10643, 151740, 2171228, -1, 54, 10256, 16410120, 70292, 610232, 10373, 10292, 10616, 70517, 5610228, 210309, 210228, 250448, 70616, 11696, 2370552, -1, /*64*/ 72, 110307, 26230195, 210272, 30523, 110631, 30739, 70575, 30683, 14030351, 1830403, 1830299, 770346, 110586, 10750330, 10620, 210420, 71223, 9150663, 30426, 30858, 30978, 30954, 31074, 30762, 210452, 210538, 770634, 210730, 490626, 210722, 31018, 111234, 31450, 71106, 31322, 5750594, 750682, 750506, 10346, 10826, 10490, 70620, 11124, 10716, 30786, 31746, 210636, 491202, 72402, 3751122, -1, 80, 430250, 35910186, 110282, 430530, 110530, 30650, 30730, 30570, 230482, 110482, 230642, /*70642*/0, /*70642*/0, 70882, 30666, 30586, 30618, 30538, 70786, 11550450, 1470594, 1470450, 18270354, 2310354, 630474, 630426, 630378, 110562, 30562, 110722, 30722, 70546, 30546, 30946, 70962, 231202, 71442, 111042, 31426, 31026, 30978, 31058, 151106, 71346, 9870786, 1470930, 1470642, 2310690, 10467, 71266, 152866, 6511842, -1, 81,49210121, 6730319, 250427, 250319, 16450238, 610238, 70454, 70346, 70400, 70319, 5650670, 250994, 250670, 610589, 2412452, -1, /*96*/ 100, 30393, 57310217, 10481, 30693, 36470341, 630408, 30968, 13310392, 210416, 10576, 11256, 10856, 11096, 630648, 31768, 8470616, -1, 108, 30552, 60170280, 610359, 30984, 38290440, 210660, 1830540, 30849, 30660, 31308, 211137, 20570532, 770721, 770532, 70769, 11636, 11813, 610647, 70647, 250674, 70674, 70890, 211092, 1830852, 31389, 31092, 32388, 211965, 13090836, 491133, 490836, 751080, 211416, 33576, 8691288, 70904, 11048, 71720, 13688, 12344, 251538, 751608, 212280, 36600, 5532024,-1, 112, 430344, 73530248, 430736, 110736, 30904, 31016, 30792, 230664, 110664, 230888, 0/*70888*/, 0/*70888*/, 71224, 30920, 30808, 30856, 30744, 71080, 23650600, 3010792, 3010600, 37410472, 4730472, 1290632, 1290568, 1290504, 71336, 231672, 72008, 111448, 31984, 31424, 31360, 31472, 151528, 71864, 20211048, 3011240, 3010856, 4730920, 30643, 153992, 13332456,-1, 120, 2310456, 770488, 110648, 63210360, 30763, 210552, 30712, 31256, 31240, 31336, 31400, 31496, 31480, 31096, 630498, 210808, 770968, 211128, 490904, 211064, 630744, 2310888, 631032, 1470840, 630984, 31128, 111368, 31608, 71224, 31464, 33810648, 4410744, 4410552, 11211, 31263, 11416, 210858, 11290, 11090, 211032, 31352, 32600, 630738, 491864, 1471704, 72664, 22051224, -1, 135, 114870240, 39270456, 1470618, 1470456, 16591104 , -1, -1}; long i; const long *t; GEN Z = groupelts_center(S), L = galoissubgroups(G); long scenter = groupelts_sumorders(Z), svecgroup = vecgroup_sumorders(L); long u = svecgroup+10000*scenter; /*This is used as a hash value*/ for(t=tab; *t!=-1; t++) { if (t[0]==n) { for(i=1; t[i] != -1; i++) if (t[i]==u) return i; switch(n) { case 32: switch(u) { case 230171: { const long good[]={2,0}, bad[]={4,5,0}; return indexgroupcentre(G,Z,good,bad)? 4: 12; } case 70267: if (s==135) return 9; return 32; case 70187: { const long good[]={8,0}, bad[]={7,9,0}; return indexgroupcentre(G,Z,good,bad)? 13: 14; } case 70379: { const long good[]={4,0},bad[]={0}; return indexgroupsubgroup(L,8,good,bad)? 31: 30; } } break; case 48: case 80: { const long good[]={5,8,0},bad[]={6,7,0}; return indexgroupcentre(G,Z,good,bad)? 12: 13; } case 112: { const long good[]={7,4,0},bad[]={5,6,0}; return indexgroupcentre(G,Z,good,bad)? 11: 12; } } return -1; } while (*t!=-1) t++; } { const long tab[]={ 64, 1270001, /*4270003*/0, /*4270003*/0, 8190072, 6430073, 6670445, 5550446, 8190278, 7070279, 6350071, 5230072, 8110154, /*5870155*/0, /*5870155*/0, /*4270042*/0, /*4270042*/0, 7710246, 7390277, 6750037, 8032377, 8670266, 6750397, 11390022, 7710267, 7070277, /*3630046*/0, /*3630046*/0, 3630057, 4830196, 4830207, 4671808, 9070697, 6670700, 8750094, 6990091, 6350111, 5870115, 6671599, 5711601, 5551702, 5871512, 6351709, 5391711, /*3630046*/0, 3630047, 4111467, /*4430156*/0, /*4430156*/0, 3790166, /*2510026*/0, /*2510026*/0, 4470028, 4150300, 3830030, 13470021, 20350065, 10910041, 16514365, /*12190433*/0, 34110271, /*16514475*/0, 15230465, /*10910433*/0, 9630041, 13470233, /*16514475*/0, 20834696, /*10910433*/0, 13954343, /*12190433*/0, 19553542, 13474377, 25790466, 15870467, 18914476, 14110477, /*14590443*/0, 13310443, 11550043, /*14590443*/0, 10270043, 8990002, 8990546, 8990646, 8993647, 8356896, 13310905, 13310915, 12039018, 16990866, 12670888, 15071116, 11551217, 12038218, 16031739, 12512740, 12353138, 12993048, 15391849, 11872850, 12993551, 12353851, 8991446, 8991447, 8354830, 9951566, 9951666, 8674709, 9317039, 8031897, 8030187, 7713641, 7714641, 7074743, 9236585, 9236415, 9236586, 10990821, 9879066, 8751833, 9873399, 8751766, 10990754, 8593054, 8593087, 6830446, 6833546, 17472434, 13953445, 14432313, 16352544, 12833555, 13313423, 15635143, 13234877, 13874853, 12755287, 17870919, 14190949, 13075209, 11955310, 10835253, 9715354, 11312124, 10193135, 11074927, 12197529, 9957664, 11074970, 12196539, 9956674, 9958907, 10439497, 9479551, 9554015, 8433958, 9553915, 8434058, 8918081, 7798421, 10110856, 10110756, 9476648, 8991757, 8991857, 8356682, 10994275, 8750435, 8590474, 9230510, 10355254, 8115355, 13556790, 15790679, 11310691, 12275539, 14035061, 11795172, 8750465, 7474472, 8750475, 8114920, 6110196, 6111806, 5951808, 10191819, 9238364, 8271841, 8590736, 9390959, 8432079, 25470255, 41792701, 25470275, 20355344, 27233751, 18593673, 19717567, 23394762, 17312707, 19717633, 46115277, 31557088, 22917189, 24677288, 24039835, 24676366, 16032362, 17793529, 17153269, 38432486, 21153763, 23393635, 16037076, 27710971, 27074338, 20995174, 23396204, 20193482, 17157790, 19550231, 14751475, 17153832, 19070249, 16038080, 33391110, 25875097, 22197835, 22195018, 21070221, 24590112, 18999456, 15952565, 18356361, 17237769, 18359003, 15951169, 14832955, 16110295, 18350268, 21392354, 22030301, 18353365, 15955257, 13550032, 18430405, 18434015, 17150260, 17154128, 27234036, 23710639, 20194057, 21157900, 24198470, 20679613, 21158141, 22435065, 21318520, 20197076, 67390501, 83715011, 51070497, 54590283, 58915129, 50275230, 52035340, 263870051, -1, -1}; long i; const long *t; GEN V=vecgroup_idxlist(L,32); long idxlist=vecsmall_pack(V,10,9967); long w=10000*svecgroup+idxlist; /*This is used as a hash value*/ for(t=tab; *t!=-1; t++) { if (t[0]==n) { for(i=1; t[i] != -1; i++) if (t[i]==w) return i; switch(n) { case 64: switch(w) { case 4270003: return (scenter==439)? 2: 3; case 5870155: { const long good[]={8,9,0},bad[]={7,0}; return indexgroupcentre(G,Z,good,bad)? 13: 14; } case 4270042: { const long good[]={13,0},bad[]={14,0}; return indexgroupcentre(G,Z,good,bad)? 15: 16; } case 4430156: { const long good[]={18,20,0},bad[]={19,0}; return indexgroupcentre(G,Z,good,bad)? 47: 48; } case 2510026: return scenter==1367? 50: 51; case 12190433: return scenter==47? 59: 70; case 16514475: { const long good[]={22,24,28,0},bad[]={23,25,27,30,0}; return indexgroupcentre(G,Z,good,bad)? 61: 66; } case 10910433: { const long good[]={23,31,0},bad[]={25,26,29,30,33,0}; return indexgroupcentre(G,Z,good,bad)? 63: 68; } case 14590443: { const long good[]={28,33,0},bad[]={30,34,0}; return indexgroupcentre(G,Z,good,bad)? 77: 80; } case 3630046: { const long good[]={3,0},bad[]={12,16,0}; if (scenter==695) return 26; return indexgroupcentre(G,Z,good,bad)? 27: 44; } } break; } return -1; } while (*t!=-1) t++; } } { const long tab[]={ 96, 316010002, 252010002, 707020000, 676160124, 676170124, 87180027, 988190278, 892200028, 876030110, 876040110, 876120110, 215111237, 503062153, 972141052, 972131052, 455091156, 167101154, 620160033, 620170033, 908031033, 908121033, 908041033, 199101564, 7130153, 7140153, 812150123, 247051165, 487091566, 812151024, 391071276, 103081274, 247111377, 988180195, 892190205, 924190197, 828200207, 103050134, 679020464, 295091075, 199070145, 391060235, 103101076, 7080146, 135111157, 295020044, 684030223, 684040223, 908050274, 135060255, 7070285, 812080286, 71092475, 876102476, 908112287, 684120223, 748130243, 748140243, 620150254, 492160043, 492170043, 764180045, 700190477, 636200047, 963110003, 779050031, 935100032, 799110033, 819210003, 791260032, 246270050, 723330003, 987340003, 651360031, 623380033, 647263930, 839351534, 455321350, 178211335, 791244031, 322256848, 189340236, 130316409, 599331360, 743244548, 935295937, 551333907, 189222029, 274255883, 525275609, 82306043, 610289391, 82315641, 82307025, 647262487, 839353950, 0/*455322385*/, 0/*455322385*/, 178233588, 791245051, 322256982, 130307015, 658286619, 983297004, 983297037, 599333858, 631365165, 631376165, 535386399, 66408676, 354390966, 871428265, 775411064, 631376407, 535386309, 114430028, 823441008, 314398920, 74437993, 831420054, 42405827, 90439425, 799440830, 847426805, 767410275, 815440314, 863429143, 487360134, 487371044, 66211564, 66231664, 871295713, 66231764, 679242567, 125228724, 210253894, 18306803, 546288536, 162390938, 919437378, 871401018, 162255761, 967304398, 967313318, 413274329, 498283470, 498288163, 29345108, 967401139, 727449579, 679411219, 775352619, 583261276, 919295225, 66312839, 423381047, 2437470, 759424560, 711448550, 770222372, 109272382, 551210244, 258222592, 551230264, 295242430, 647254411, 199262266, 482272602, 871283751, 423293752, 519303751, 519312662, 71320222, 167332232, 226340245, 327352266, 167360274, 167372584, 103382587, 647392595, 455406162, 263412616, 327428742, 487438955, 295440098, 358290331, 622253358, 886280358, 322410312, 754400322, 394443122, 282440313, 354423123, 522430323, 726220349, 990273529, 470450359, 742460359, 522470032, 198470031, 282480353, 290490033, 274500353, 414470000, 614490000, 605473864, 664459790, 723464091, 893482714, 675465704, 845486215, 184493728, 653478045, 941489155, 605501588, 925482982, 264492577, 589502601, 312450472, 371466994, 285450492, 989464902, 578470486, 770489139, 994490497, 546500507, 604460529, 65270050, 684510049, 468510050, 134510562, 831510052, -1 -1}; long i; const long *t; GEN V=vecgroup_idxlist(L,48); long idx48=vecsmall_pack(V,10,9967); long idx32=vecgroup_idxlist(L,32)[1]; long w=1000000*(svecgroup%997)+10000*idx32+idx48; /*This is used as a hash value*/ for(t=tab; *t!=-1; t++) { if (t[0]==n) { for(i=1; t[i] != -1; i++) if (t[i]==w) return i; switch(n) { case 96: switch(w) { case 455322385: { const long good[]={37,40,0},bad[]={34,41,0}; return indexgroupcentre(G,Z,good,bad)? 96: 97; } } break; } return -1; } while (*t!=-1) t++; } } } return 0; } long group_ident(GEN G, GEN S) { pari_sp av = avma; long idx = group_ident_i(G, S); if (idx < 0) pari_err_TYPE("group_ident [not a group]", G); if (!idx) pari_err_IMPL("galoisidentify for groups of order > 127"); return gc_long(av, idx); } long group_ident_trans(GEN G, GEN S) { const long tab[]={ 4, 1, 2, -1, 6, 2, 1, -1, 8, 1, 2, 4, 5, 3, -1, 9, 1, 2, -1, 10, 2, 1, -1, 12, 5, 1, 4, 3, 2, -1, 14, 2, 1, -1, 15, 1, -1, 16, 1, 4, 10, 8, 5, 6, 13, 12, 14, 2, 9, 7, 11, 3, -1, 18, 5, 1, 3, 4, 2, -1, 20, 2, 1, 5, 4, 3, -1, 21, 2, 1, -1, 22, 2, 1, -1, 24, 8, 1, 7, 5, 12, 13, 6, 14, 2, 15, 4, 10, 9, 11, 3, -1, 25, 1, 2, -1, 26, 2, 1, -1, 27, 1, 2, 3, 5, 4, -1, 28, 3, 1, 4, 2, -1, 30, 2, 4, 3, 1, -1, -1}; long n = group_order(G), s; const long *t; if (n == 1) return 1; /* N.B. known up to 32 (Cannon-Holt) */ if (n > 30) pari_err_IMPL("group_ident_trans [n > 30]"); if (uisprime(n)) return 1; s = group_ident(G,S); for(t=tab;*t>=0;t++) { if (t[0]==n) return t[s]; while (*t>=0) t++; } return 0; /*LCOV_EXCL_LINE*/ } pari-2.17.2/src/modules/elldata.c0000644000175000017500000001612614567450071015214 0ustar billbill/* Copyright (C) 2005 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /********************************************************************/ /** **/ /** INTERFACE TO JOHN CREMONA ELLIPTIC CURVES DATABASE **/ /** **/ /********************************************************************/ #include "pari.h" #include "paripriv.h" static long strtoclass(const char *s) { long c=0; while (*s && *s<='9') s++; if (!*s) return -1; while ('a'<=*s && *s<='z') c = 26*c + *(s++)-'a'; return c; } /*Take a curve name like "100a2" and set * f to the conductor, (100) * c to the isogeny class (in base 26), ("a" or 0) * i to the curve index (2). * return 0 if parse error. */ static int ellparsename(const char *s, long *f, long *c, long *i) { long j; *f=-1; *c=-1; *i=-1; if (*s<'0' || *s>'9') return 0; *f=0; for (j=0;j<10 && '0'<=*s && *s<='9';j++) *f=10**f+*(s++)-'0'; if (j==10) {*f=-1; return 0;} if (*s<'a' || *s>'z') return !*s; *c=0; for (j=0; j<7 && 'a'<=*s && *s<='z';j++) *c=26**c+*(s++)-'a'; if (j==7) {*c=-1; return 0;} if (*s<'0' || *s>'9') return !*s; *i=0; for (j=0; j<10 && '0'<=*s && *s<='9';j++) *i=10**i+*(s++)-'0'; if (j==10) {*i=-1; return 0;} return !*s; } /* Take an integer and convert it to base 26 */ static GEN ellrecode(long x) { GEN str; char *s; long d = 0, n = x; do { d++; n /= 26; } while (n); str = cgetg(nchar2nlong(d+1)+1, t_STR); s = GSTR(str); s[d] = 0; n = x; do { s[--d] = n%26 + 'a'; n /= 26; } while (n); return str; } GEN ellconvertname(GEN n) { switch(typ(n)) { case t_STR: { long f,i,c; if (!ellparsename(GSTR(n),&f,&c,&i)) pari_err_TYPE("ellconvertname", n); if (f<0 || c<0 || i<0) pari_err_TYPE("ellconvertname [incomplete name]", n); return mkvec3s(f,c,i); } case t_VEC: if (lg(n)==4) { pari_sp av = avma; GEN f=gel(n,1), c=gel(n,2), s=gel(n,3); if (typ(f)!=t_INT || typ(c)!=t_INT || typ(s)!=t_INT) pari_err_TYPE("ellconvertname",n); return gerepilecopy(av, shallowconcat1(mkvec3(f, ellrecode(itos(c)), s))); } /*fall through*/ } pari_err_TYPE("ellconvertname",n); return NULL; /*LCOV_EXCL_LINE*/ } THREAD GEN ellcondfile_cache; THREAD long ellcondfile_cache_cond; void pari_init_ellcondfile(void) { ellcondfile_cache = NULL; ellcondfile_cache_cond = -1; } static GEN ellcondfile(long n) { if (ellcondfile_cache_cond >= 0 && n == ellcondfile_cache_cond) return gcopy(ellcondfile_cache); else { pari_sp av = avma; pariFILE *F; GEN V; char *s = stack_sprintf("%s/elldata/ell%ld", pari_datadir, n); F = pari_fopengz(s); if (!F) pari_err_FILE("elldata file",s); set_avma(av); V = gp_read_stream(F->file); if (!V || typ(V)!=t_VEC ) pari_err_FILE("elldata file [read]",s); ellcondfile_cache_cond = -1; /* disable cache until update */ if (ellcondfile_cache) gunclone(ellcondfile_cache); ellcondfile_cache = gclone(V); ellcondfile_cache_cond = n; /* re-enable cache */ pari_fclose(F); return V; } } /* return the vector of all curves of conductor f */ static int cmpi1(GEN x, GEN v) { return cmpii(x, gel(v,1)); } static GEN ellcondlist(long f) { pari_sp av = avma; GEN V = ellcondfile(f/1000); long i = tablesearch(V, utoipos(f), &cmpi1); if (i) { GEN v = gel(V,i); return vecslice(v,2, lg(v)-1); } set_avma(av); return cgetg(1,t_VEC); } static GEN ellsearchbyname(GEN V, char *name) { GEN x; long j; for (j=1; j=2 ? gtos(gel(A,2)): -1; i = l>=3 ? gtos(gel(A,3)): -1; if (l>=3) A = ellconvertname(A); } else if (typ(A)==t_STR) { if (!ellparsename(GSTR(A),&f,&c,&i)) pari_err_TYPE("ellsearch",A); } else { pari_err_TYPE("ellsearch",A); return NULL;/*LCOV_EXCL_LINE*/ } if (f <= 0) pari_err_DOMAIN("ellsearch", "conductor", "<=", gen_0,stoi(f)); V = ellcondlist(f); if (c >= 0) V = (i < 0)? ellsearchbyclass(V,c): ellsearchbyname(V, GSTR(A)); return gerepilecopy(av, V); } GEN ellsearchcurve(GEN name) { pari_sp ltop=avma; long f, c, i; if (!ellparsename(GSTR(name),&f,&c,&i)) pari_err_TYPE("ellsearch",name); if (f<0 || c<0 || i<0) pari_err_TYPE("ellsearch [incomplete name]", name); return gerepilecopy(ltop, ellsearchbyname(ellcondlist(f), GSTR(name))); } GEN ellidentify(GEN E) { pari_sp ltop=avma; long j; GEN V, M, G, N; checkell_Q(E); G = ellglobalred(E); N = gel(G,1); V = ellcondlist(itos(N)); M = ellchangecurve(vecslice(E,1,5),gel(G,2)); for (j=1; jb) break; for(k=2; k>1); GEN x = gel(chi,2); x = gpowgs(x, labs(nn)); if (nn < 0) x = conj_i(x); return x; } /* return n such that C(elt) = z^n */ static ulong CHI_eval_n(CHI_t *C, GEN logelt) { GEN n = ZV_dotproduct(C->chi, logelt); return umodiu(n, C->ord); } /* return C(elt) */ static GEN CHI_eval(CHI_t *C, GEN logelt) { return C->val[CHI_eval_n(C, logelt)]; } static void init_CHI(CHI_t *c, GEN CHI, GEN z) { long i, d = chi_get_deg(CHI); GEN *v = (GEN*)new_chunk(d); v[0] = gen_1; if (d != 1) { v[1] = z; for (i=2; ichi = chi_get_c(CHI); c->ord = d; c->val = v; } /* as t_POLMOD */ static void init_CHI_alg(CHI_t *c, GEN CHI) { long d = chi_get_deg(CHI); 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)); } 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] */ } /* enumerate all group elements; trivial elt comes last */ GEN cyc2elts(GEN cyc) { long i, n; GEN z; GROUP_t G; G.cyc = typ(cyc)==t_VECSMALL? cyc: gtovecsmall(cyc); n = zv_prod(G.cyc); G.r = lg(cyc)-1; G.j = zero_zv(G.r); z = cgetg(n+1, t_VEC); gel(z,n) = leafcopy(G.j); /* trivial elt comes last */ for (i = 1; i < n; i++) { (void)NextElt(&G); gel(z,i) = leafcopy(G.j); } return z; } /* nchi: a character given by a vector [d, (c_i)], e.g. from char_normalize * such that chi(x) = e((c . log(x)) / d) where log(x) on bnr.gen */ static GEN get_Char(GEN nchi, long prec) { return mkvec2(nchi, rootsof1_cx(gel(nchi,1), prec)); } /* prime divisors of conductor */ static GEN divcond(GEN bnr) {GEN bid = bnr_get_bid(bnr); return gel(bid_get_fact(bid),1);} /* vector of prime ideals dividing bnr but not bnrc */ static GEN get_prdiff(GEN D, GEN Dc) { long n, i, l = lg(D); GEN diff = cgetg(l, t_COL); for (n = i = 1; i < l; i++) if (!tablesearch(Dc, gel(D,i), &cmp_prime_ideal)) gel(diff,n++) = gel(D,i); setlg(diff, n); return diff; } #define ch_prec(x) realprec(gel(x,1)) #define ch_C(x) gel(x,1) #define ch_bnr(x) gel(x,2) #define ch_3(x) gel(x,3) #define ch_q(x) gel(x,3)[1] #define ch_CHI(x) gel(x,4) #define ch_diff(x) gel(x,5) #define ch_CHI0(x) gel(x,6) #define ch_small(x) gel(x,7) #define ch_comp(x) gel(x,7)[1] #define ch_phideg(x) gel(x,7)[2] static long ch_deg(GEN dtcr) { return chi_get_deg(ch_CHI(dtcr)); } /********************************************************************/ /* 1rst part: find the field K */ /********************************************************************/ static GEN AllStark(GEN data, 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 subgroup C */ static GEN InitQuotient(GEN C) { GEN U, D = ZM_snfall_i(C, &U, NULL, 1), h = ZV_prod(D); return mkvec5(h, D, U, C, cyc_normalize(D)); } /* lift chi character on A/C [Qt from InitQuotient] to character on A [cyc]*/ static GEN LiftChar(GEN Qt, GEN cyc, GEN chi) { GEN ncyc = gel(Qt,5), U = gel(Qt,3), nchi = char_normalize(chi, ncyc); GEN c = ZV_ZM_mul(gel(nchi,2), U), d = gel(nchi,1); return char_denormalize(cyc, d, c); } /* Let C be a subgroup, system of representatives of the quotient */ static GEN subgroup_classes(GEN C) { GEN U, D = ZM_snfall_i(C, &U, NULL, 1), e = cyc2elts(D); long i, l = lg(e); if (ZM_isidentity(U)) for (i = 1; i < l; i++) (void)vecsmall_to_vec_inplace(gel(e,i)); else { GEN Ui = ZM_inv(U,NULL); for (i = 1; i < l; i++) gel(e,i) = ZM_zc_mul(Ui, gel(e,i)); } return e; } /* Let s: A -> B given by [P,cycA,cycB] A and B, compute the kernel of s. */ GEN abmap_kernel(GEN S) { GEN U, P = gel(S,1), cycA = gel(S,2), DB = diagonal_shallow(gel(S,3)); long nA = lg(cycA)-1, rk; rk = nA + lg(DB) - lg(ZM_hnfall_i(shallowconcat(P, DB), &U, 1)); return ZM_hnfmodid(matslice(U, 1,nA, 1,rk), cycA); } /* let H be a subgroup of A; return s(H) */ GEN abmap_subgroup_image(GEN S, GEN H) { return ZM_hnfmodid(ZM_mul(gel(S,1), H), gel(S,3)); } /* 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 S = bnrsurjection(bnrm, bnrn); GEN P = ZM_mul(gel(dtQ,3), gel(S,1)); return gerepileupto(av, abmap_kernel(mkvec3(P, gel(S,2), gel(dtQ,2)))); } static long cyc_is_cyclic(GEN cyc) { return lg(cyc) <= 2 || equali1(gel(cyc,2)); } /* Let H be a subgroup of cl(bnr)/sugbroup, return 1 if cl(bnr)/subgoup/H is cyclic and the signature of the corresponding field is equal to sig and no finite prime dividing cond(bnr) is totally split in this field. Return 0 otherwise. */ static long IsGoodSubgroup(GEN H, GEN bnr, GEN map) { pari_sp av = avma; GEN S, mod, modH, p1, U, P, PH, bnrH, iH, qH; long j; p1 = InitQuotient(H); /* quotient is non cyclic */ if (!cyc_is_cyclic(gel(p1,2))) return gc_long(av,0); (void)ZM_hnfall_i(shallowconcat(map,H), &U, 0); setlg(U, lg(H)); for (j = 1; j < lg(U); j++) setlg(gel(U,j), lg(H)); p1 = ZM_hnfmodid(U, bnr_get_cyc(bnr)); /* H as a subgroup of bnr */ modH = bnrconductor_raw(bnr, p1); mod = bnr_get_mod(bnr); /* is the signature correct? */ if (!gequal(gel(modH,2), gel(mod,2))) return gc_long(av, 0); /* finite part are the same: OK */ if (gequal(gel(modH,1), gel(mod,1))) return gc_long(av, 1); /* need to check the splitting of primes dividing mod but not modH */ bnrH = Buchray(bnr, modH, nf_INIT); P = divcond(bnr); PH = divcond(bnrH); S = bnrsurjection(bnr, bnrH); /* H as a subgroup of bnrH */ iH = abmap_subgroup_image(S, p1); qH = InitQuotient(iH); for (j = 1; j < lg(P); j++) { GEN pr = gel(P, j), e; /* if pr divides modH, it is ramified, so it's good */ if (tablesearch(PH, pr, cmp_prime_ideal)) continue; /* inertia degree of pr in bnr(modH)/H is charorder(cycH, e) */ e = ZM_ZC_mul(gel(qH,3), isprincipalray(bnrH, pr)); e = ZV_ZV_mod(e, gel(qH,2)); if (ZV_equal0(e)) return gc_long(av,0); /* f = 1 */ } return gc_long(av,1); } /* compute list of nontrivial characters trivial on H, modulo complex * conjugation. If flag is set, impose a nontrivial conductor at infinity */ static GEN AllChars(GEN bnr, GEN dtQ, long flag) { GEN v, vchi, cyc = bnr_get_cyc(bnr); long n, i, hD = itos(gel(dtQ,1)); hashtable *S; v = cgetg(hD+1, t_VEC); /* nonconjugate chars */ vchi = cyc2elts(gel(dtQ,2)); S = hash_create(hD, (ulong(*)(void*))&hash_GEN, (int(*)(void*,void*))&ZV_equal, 1); for (i = n = 1; i < hD; i++) /* remove i = hD: trivial char */ { /* lift a character of D in Clk(m) */ GEN F, lchi = LiftChar(dtQ, cyc, zv_to_ZV(gel(vchi,i))), cchi = NULL; if (hash_search(S, lchi)) continue; F = bnrconductor_raw(bnr, lchi); if (flag && gequal0(gel(F,2))) continue; /* f_oo(chi) trivial ? */ if (abscmpiu(charorder(cyc,lchi), 2) > 0) { /* nonreal chi: add its conjugate character to S */ cchi = charconj(cyc, lchi); hash_insert(S, cchi, (void*)1); } gel(v, n++) = cchi? mkvec3(lchi, F, cchi): mkvec2(lchi, F); } setlg(v, n); return v; } static GEN InitChar(GEN bnr, GEN CR, long flag, long prec); static void CharNewPrec(GEN data, long prec); /* Given a conductor and a subgroups, return the corresponding complexity and * precision required using quickpol. Fill data[5] with dataCR */ static long CplxModulus(GEN data, long *newprec) { long dprec = DEFAULTPREC; pari_sp av = avma; for (;;) { GEN cpl, pol = AllStark(data, 1, dprec); cpl = RgX_fpnorml2(pol, LOWDEFAULTPREC); dprec = maxss(dprec, nbits2extraprec(gexpo(pol))) + EXTRAPREC64; if (!gequal0(cpl)) { *newprec = dprec; return gexpo(cpl); } set_avma(av); if (DEBUGLEVEL>1) pari_warn(warnprec, "CplxModulus", dprec); CharNewPrec(data, dprec); } } /* return A \cap B in abelian group defined by cyc. NULL = whole group */ static GEN subgp_intersect(GEN cyc, GEN A, GEN B) { GEN H, U; long k, lH; if (!A) return B; if (!B) return A; H = ZM_hnfall_i(shallowconcat(A,B), &U, 1); setlg(U, lg(A)); lH = lg(H); for (k = 1; k < lg(U); k++) setlg(gel(U,k), lH); return ZM_hnfmodid(ZM_mul(A,U), cyc); } static void CharNewPrec(GEN dataCR, long prec); /* Let (f,C) be a conductor without infinite part and a congruence group mod f. * Compute (m,D) such that D is a congruence group of conductor m, f | m, * divisible by all the infinite places but one, D is a subgroup of index 2 of * Cm = Ker: Clk(m) -> Clk(f)/C. Consider further the subgroups H of Clk(m)/D * with cyclic quotient Clk(m)/H such that no place dividing m is totally split * in the extension KH corresponding to H: we want their intersection to be * trivial. These H correspond to (the kernels of Galois orbits of) characters * chi of Clk(m)/D such that chi(log_gen_arch(m_oo)) != 1 and for all pr | m * we either have * - chi(log_gen_pr(pr,1)) != 1 [pr | cond(chi) => ramified in KH] * - or [pr \nmid cond(chi)] chi lifted to Clk(m/pr^oo) is not trivial at pr. * We want the map from Clk(m)/D given by the vector of such characters to have * trivial kernel. Return bnr(m), D, Ck(m)/D and Clk(m)/Cm */ static GEN FindModulus(GEN bnr, GEN dtQ, long *newprec) { const long LIMNORM = 400; long n, i, maxnorm, minnorm, N, pr, rb, iscyc, olde = LONG_MAX; pari_sp av = avma; GEN bnf, nf, f, varch, m, rep = NULL; bnf = bnr_get_bnf(bnr); nf = bnf_get_nf(bnf); N = nf_get_degree(nf); f = gel(bnr_get_mod(bnr), 1); /* if cpl < rb, it is not necessary to try another modulus */ rb = expi( powii(mulii(nf_get_disc(nf), ZM_det_triangular(f)), gmul2n(bnr_get_no(bnr), 3)) ); /* Initialization of the possible infinite part */ varch = cgetg(N+1,t_VEC); for (i = 1; i <= N; i++) { GEN a = const_vec(N,gen_1); gel(a, N+1-i) = gen_0; gel(varch, i) = a; } m = cgetg(3, t_VEC); /* Go from minnorm up to maxnorm; if necessary, increase these values. * If the extension is cyclic then a suitable conductor exists and we go on * until we find it. Else, stop at norm LIMNORM. */ minnorm = 1; maxnorm = 50; iscyc = cyc_is_cyclic(gel(dtQ,2)); if (DEBUGLEVEL>1) err_printf("Looking for a modulus of norm: "); for(;;) { GEN listid = ideallist0(nf, maxnorm, 4+8); /* ideals of norm <= maxnorm */ pari_sp av1 = avma; for (n = minnorm; n <= maxnorm; n++, set_avma(av1)) { GEN idnormn = gel(listid,n); long nbidnn = lg(idnormn) - 1; if (DEBUGLEVEL>1) err_printf(" %ld", n); for (i = 1; i <= nbidnn; i++) { /* finite part of the conductor */ long s; gel(m,1) = idealmul(nf, f, gel(idnormn,i)); for (s = 1; s <= N; s++) { /* infinite part */ GEN candD, Cm, bnrm; long lD, c; gel(m,2) = gel(varch,s); /* compute Clk(m), check if m is a conductor */ bnrm = Buchray(bnf, m, nf_INIT); if (!bnrisconductor(bnrm, NULL)) continue; /* compute Im(C) in Clk(m)... */ Cm = ComputeKernel(bnrm, bnr, dtQ); /* ... and its subgroups of index 2 with conductor m */ candD = subgrouplist_cond_sub(bnrm, Cm, mkvec(gen_2)); lD = lg(candD); for (c = 1; c < lD; c++) { GEN data, CR, D = gel(candD,c), QD = InitQuotient(D); GEN ord = gel(QD,1), cyc = gel(QD,2), map = gel(QD,3); long e; if (!cyc_is_cyclic(cyc)) /* cyclic => suitable, else test */ { GEN lH = subgrouplist(cyc, NULL), IK = NULL; long j, ok = 0; for (j = 1; j < lg(lH); j++) { GEN H = gel(lH, j), IH = subgp_intersect(cyc, IK, H); /* if H > IK, no need to test H */ if (IK && gidentical(IH, IK)) continue; if (IsGoodSubgroup(H, bnrm, map)) { IK = IH; /* intersection of all good subgroups */ if (equalii(ord, ZM_det_triangular(IK))) { ok = 1; break; } } } if (!ok) continue; } CR = InitChar(bnrm, AllChars(bnrm, QD, 1), 0, DEFAULTPREC); data = mkvec4(bnrm, D, subgroup_classes(Cm), CR); if (DEBUGLEVEL>1) err_printf("\nTrying modulus = %Ps and subgroup = %Ps\n", bnr_get_mod(bnrm), D); e = CplxModulus(data, &pr); if (DEBUGLEVEL>1) err_printf("cpl = 2^%ld\n", e); if (e < olde) { guncloneNULL(rep); rep = gclone(data); *newprec = pr; olde = e; } if (olde < rb) goto END; /* OK */ if (DEBUGLEVEL>1) err_printf("Trying to find another modulus..."); } } if (rep) 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)); CharNewPrec(rep, *newprec); return gerepilecopy(av, rep); } /********************************************************************/ /* 2nd part: compute W(X) */ /********************************************************************/ /* find ilambda s.t. Diff*f*ilambda integral and coprime to f and ilambda >> 0 at foo, fa = factorization of f */ static GEN get_ilambda(GEN nf, GEN fa, GEN foo) { GEN x, w, E2, P = gel(fa,1), E = gel(fa,2), D = nf_get_diff(nf); long i, l = lg(P); if (l == 1) return gen_1; w = cgetg(l, t_VEC); E2 = cgetg(l, t_COL); for (i = 1; i < l; i++) { GEN pr = gel(P,i), t = pr_get_tau(pr); long e = itou(gel(E,i)), v = idealval(nf, D, pr); if (v) { D = idealdivpowprime(nf, D, pr, utoipos(v)); e += v; } gel(E2,i) = stoi(e+1); if (typ(t) == t_MAT) t = gel(t,1); gel(w,i) = gdiv(nfpow(nf, t, stoi(e)), powiu(pr_get_p(pr),e)); } x = mkmat2(P, E2); return idealchinese(nf, mkvec2(x, foo), w); } /* 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)). */ static GEN ArtinNumber(GEN bnr, GEN LCHI, long prec) { long ic, i, j, nz, nChar = lg(LCHI)-1; pari_sp av2; GEN sqrtnc, cond, condZ, cond0, cond1, nf, T, cyc, vN, vB, diff, vt, idh; GEN zid, gen, z, nchi, indW, W, classe, s0, s, den, ilambda, 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 (chi_get_deg(CHI) <= 2) { gel(W,i) = gen_1; continue; } 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 = gel(cond,2); sqrtnc = gsqrt(idealnorm(nf, cond0), prec); ilambda = get_ilambda(nf, bid_get_fact(bnr_get_bid(bnr)), cond1); idh = idealmul(nf, ilambda, idealmul(nf, diff, cond0)); /* integral */ ilambda = Q_remove_denom(ilambda, &den); z = den? rootsof1_cx(den, prec): NULL; /* compute a system of generators of (Ok/cond)^*, we'll make them * cond1-positive in the main loop */ zid = Idealstar(nf, cond0, nf_GEN); cyc = abgrp_get_cyc(zid); gen = abgrp_get_gen(zid); nz = lg(gen) - 1; sarch = nfarchstar(nf, cond0, vec01_to_indices(cond1)); nchi = cgetg(nChar+1, t_VEC); for (ic = 1; ic <= nChar; ic++) gel(nchi,ic) = cgetg(nz + 1, t_VECSMALL); for (i = 1; i <= nz; i++) { if (is_bigint(gel(cyc,i))) pari_err_OVERFLOW("ArtinNumber [conductor too large]"); gel(gen,i) = set_sign_mod_divisor(nf, NULL, gel(gen,i), sarch); classe = isprincipalray(bnr, gel(gen,i)); for (ic = 1; ic <= nChar; ic++) { GEN n = gel(nchi,ic); n[i] = CHI_eval_n(lC[ic], classe); } } /* Sum chi(beta) * exp(2i * Pi * Tr(beta * ilambda) where beta runs through the classes of (Ok/cond0)^* and beta cond1-positive */ vt = gel(T,1); /* ( Tr(w_i) )_i */ if (typ(ilambda) == t_COL) vt = ZV_ZM_mul(vt, zk_multable(nf, ilambda)); else vt = ZC_Z_mul(vt, ilambda); /*vt = den . (Tr(w_i * ilambda))_i */ G.cyc = gtovecsmall(cyc); G.r = nz; G.j = zero_zv(nz); vN = zero_Flm_copy(nz, nChar); av2 = avma; vB = const_vec(nz, gen_1); s0 = z? powgi(z, modii(gel(vt,1), den)): gen_1; /* for beta = 1 */ s = const_vec(nChar, s0); while ( (i = NextElt(&G)) ) { GEN b = gel(vB,i); b = nfmuli(nf, b, gel(gen,i)); b = typ(b) == t_COL? FpC_red(b, condZ): modii(b, condZ); for (j=1; j<=i; j++) gel(vB,j) = b; for (ic = 1; ic <= nChar; ic++) { GEN v = gel(vN,ic), n = gel(nchi,ic); v[i] = Fl_add(v[i], n[i], lC[ic]->ord); for (j=1; jval[ v[i] ]; gel(s,ic) = gadd(gel(s,ic), gmul(val, s0)); } if (gc_needed(av2, 1)) { if (DEBUGMEM > 1) pari_warn(warnmem,"ArtinNumber"); gerepileall(av2, 2, &s, &vB); } } classe = isprincipalray(bnr, idh); z = powIs(- (lg(gel(sarch,1))-1)); for (ic = 1; ic <= nChar; ic++) { s0 = gmul(gel(s,ic), CHI_eval(lC[ic], classe)); gel(W, indW[ic]) = gmul(gdiv(s0, sqrtnc), z); } return W; } static GEN AllArtinNumbers(GEN CR, long prec) { pari_sp av = avma; GEN vChar = gel(CR,1), dataCR = gel(CR,2); 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, prec); for (k = 1; k < l; k++) gel(W,LChar[k]) = gel(WbyCond,k); } return gerepilecopy(av, W); } /* 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) { pari_sp av = avma; GEN cyc, W; if (flag < 0 || flag > 1) pari_err_FLAG("bnrrootnumber"); checkbnr(bnr); if (flag) { cyc = bnr_get_cyc(bnr); if (!char_check(cyc,chi)) pari_err_TYPE("bnrrootnumber [character]", chi); } else { bnr_char_sanitize(&bnr, &chi); cyc = bnr_get_cyc(bnr); } chi = char_normalize(chi, cyc_normalize(cyc)); chi = get_Char(chi, prec); W = ArtinNumber(bnr, mkvec(chi), prec); return gerepilecopy(av, gel(W,1)); } /********************************************************************/ /* 3rd part: initialize the characters */ /********************************************************************/ /* 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. */ static GEN AChi(GEN dtcr, long *r, long flag, long prec) { GEN A, diff = ch_diff(dtcr), bnrc = ch_bnr(dtcr), chi = ch_CHI0(dtcr); long i, l = lg(diff); A = gen_1; *r = 0; for (i = 1; i < l; i++) { GEN B, pr = gel(diff,i), z = CharEval(chi, isprincipalray(bnrc, pr)); if (flag) B = gsubsg(1, gdiv(z, pr_norm(pr))); else if (gequal1(z)) { B = glog(pr_norm(pr), prec); (*r)++; } else B = gsubsg(1, z); A = gmul(A, B); } return A; } /* simplified version of Achi: return 1 if L(0,chi) = 0 */ static int L_vanishes_at_0(GEN D) { GEN diff = ch_diff(D), bnrc = ch_bnr(D), chi = ch_CHI0(D); long i, l = lg(diff); for (i = 1; i < l; i++) { GEN pr = gel(diff,i); if (!CharEval_n(chi, isprincipalray(bnrc, pr))) return 1; } return 0; } static GEN _data3(GEN arch, long r2) { GEN z = cgetg(4, t_VECSMALL); long i, r1 = lg(arch) - 1, q = 0; for (i = 1; i <= r1; i++) if (signe(gel(arch,i))) q++; z[1] = q; z[2] = r1 - q; z[3] = r2; return z; } static void ch_get3(GEN dtcr, long *a, long *b, long *c) { GEN v = ch_3(dtcr); *a = v[1]; *b = v[2]; *c = v[3]; } /* 2^(2*r2) pi^N */ static GEN get_P(GEN nf, long prec) { long r2 = nf_get_r2(nf), N = nf_get_degree(nf); GEN P = powru(mppi(prec), N); shiftr_inplace(P, 2*r2); return P; } /* sort chars according to conductor */ static GEN sortChars(GEN ch) { long j, l = lg(ch); GEN F = cgetg(l, t_VEC); for (j = 1; j < l; j++) gel(F, j) = gmael(ch,j,2); return vec_equiv(F); } /* Given a list [chi, F = cond(chi)] of characters over Cl(bnr), return * [vChar, dataCR], where vChar contains the equivalence classes of * characters with the same conductor, and dataCR contains for each character: * - bnr(F) * - the constant C(F) [t_REAL] * - [q, r1 - q, r2, rc] where * q = number of real places in F * rc = max{r1 + r2 - q + 1, r2 + q} * - diff(chi) primes dividing m but not F * - chi in bnr(m) * - chi in bnr(F). * If all is unset, only compute characters s.t. L(chi,0) != 0 */ static GEN InitChar(GEN bnr, GEN ch, long all, long prec) { GEN bnf = checkbnf(bnr), nf = bnf_get_nf(bnf), mod = bnr_get_mod(bnr); GEN P, dataCR, ncyc, dk = nf_get_disc(nf), vChar = sortChars(ch); long n, l, r2 = nf_get_r2(nf), prec2 = precdbl(prec) + EXTRAPREC64; long lv = lg(vChar); P = get_P(nf, prec2); ncyc = cyc_normalize(bnr_get_cyc(bnr)); dataCR = cgetg_copy(ch, &l); for (n = 1; n < lv; n++) { GEN D, bnrc, v = gel(vChar, n); /* indices of chars of given cond */ long a, i = v[1], lc = lg(v); GEN F = gmael(ch,i,2); gel(dataCR, i) = D = cgetg(8, t_VEC); ch_C(D) = sqrtr_abs(divir(mulii(dk, ZM_det_triangular(gel(F,1))), P)); ch_3(D) = _data3(gel(F,2), r2); if (gequal(F, mod)) { ch_bnr(D) = bnrc = bnr; ch_diff(D) = cgetg(1, t_VEC); } else { ch_bnr(D) = bnrc = Buchray(bnf, F, nf_INIT); ch_diff(D) = get_prdiff(divcond(bnr), divcond(bnrc)); } for (a = 1; a < lc; a++) { long i = v[a]; GEN chi = gmael(ch,i,1); if (a > 1) gel(dataCR, i) = D = leafcopy(D); chi = char_normalize(chi,ncyc); ch_CHI(D) = get_Char(chi, prec2); if (bnrc == bnr) ch_CHI0(D) = ch_CHI(D); else { chi = bnrchar_primitive(bnr, chi, bnrc); ch_CHI0(D) = get_Char(chi, prec2); } /* set last */ ch_small(D) = mkvecsmall2(all || !L_vanishes_at_0(D), eulerphiu(itou(gel(chi,1)))); } } return mkvec2(vChar, dataCR); } /* recompute dataCR with the new precision, in place. Don't modify bnr * components in place */ static void CharNewPrec(GEN data, long prec) { long j, l, prec2 = precdbl(prec) + EXTRAPREC64; GEN P, nf, dataCR = gmael(data,4,2), D = gel(dataCR,1); if (ch_prec(D) >= prec2) return; nf = bnr_get_nf(ch_bnr(D)); if (nf_get_prec(nf) < prec) nf = nfnewprec_shallow(nf, prec); /* not prec2 */ P = get_P(nf, prec2); l = lg(dataCR); for (j = 1; j < l; j++) { GEN f0, bnr; D = gel(dataCR,j); f0 = gel(bnr_get_mod(ch_bnr(D)), 1); ch_C(D) = sqrtr_abs(divir(mulii(nf_get_disc(nf),ZM_det_triangular(f0)), P)); ch_bnr(D) = bnr = shallowcopy(ch_bnr(D)); gel(bnr,1) = shallowcopy(gel(bnr,1)); gmael(bnr,1,7) = nf; ch_CHI(D) = get_Char(gel(ch_CHI(D),1), prec2); ch_CHI0(D)= get_Char(gel(ch_CHI0(D),1), prec2); } } /********************************************************************/ /* 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; } set_avma(av); } /* evaluate the Coeff. No Garbage collector */ static GEN EvalCoeff(GEN z, int* c, long deg) { long i,j; GEN r, e = NULL; #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 */ 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; } /* a2 <- copy the n x m array */ 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]; } } 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 = umuluu_le(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; pari_sp av1; int **an2; GEN bnrc, diff; 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++) { GEN pr = gel(diff,j); long Np = upr_norm(pr); GEN chi = CHI_eval(&C, isprincipalray(bnrc, pr)); an_AddMul(an,an2,Np,n,deg,chi,reduc); set_avma(av1); } FreeMat(an2, n); set_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; int **an, **reduc, **an2; GEN L; CHI_t C; init_CHI_alg(&C, ch_CHI(dtcr)); an = InitMatAn(n, deg, 0); an2 = InitMatAn(n, deg, 0); reduc = InitReduction(C.ord, 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); set_avma(av); return an; } /********************************************************************/ /* 5th part: compute L-functions at s=1 */ /********************************************************************/ static void deg11(LISTray *R, long p, GEN bnr, GEN pr) { vecsmalltrunc_append(R->L1, p); vectrunc_append(R->L1ray, isprincipalray(bnr, pr)); } static void deg12(LISTray *R, long p, GEN bnr, GEN pr) { vecsmalltrunc_append(R->L11, p); vectrunc_append(R->L11ray, isprincipalray(bnr, pr)); } static void deg0(LISTray *R, long p) { vecsmalltrunc_append(R->L0, p); } static void deg2(LISTray *R, long p) { vecsmalltrunc_append(R->L2, p); } static void InitPrimesQuad(GEN bnr, ulong N0, LISTray *R) { pari_sp av = avma; GEN bnf = bnr_get_bnf(bnr), F = gel(bnr_get_mod(bnr), 1); GEN v, N, nf = bnf_get_nf(bnf), dk = nf_get_disc(nf); long l = 1 + primepi_upper_bound(N0); ulong i, p, FZ = itou(gcoeff(F,1,1)), FZ2 = itou(gcoeff(F,2,2)); forprime_t T; FZ2 = ugcd(FZ, FZ2); /* content(F) */ R->L0 = vecsmalltrunc_init(l); R->L2 = vecsmalltrunc_init(l); R->condZ = FZ; R->L1 = vecsmalltrunc_init(l); R->L1ray = vectrunc_init(l); R->L11= vecsmalltrunc_init(l); R->L11ray= vectrunc_init(l); N = utoipos(2); u_forprime_init(&T, 2, N0); while ( (p = u_forprime_next(&T)) ) { N[2] = p; switch (kroiu(dk, p)) { case -1: /* inert */ if (FZ % p == 0) deg0(R,p); else deg2(R,p); break; case 1: /* split */ if (FZ2 % p == 0) deg0(R,p); else { GEN Lpr = idealprimedec(nf, N); if (FZ % p) deg12(R, p, bnr, gel(Lpr,1)); else { long t = ZC_prdvd(gel(F,2), gel(Lpr,1))? 2: 1; deg11(R, p, bnr, gel(Lpr,t)); } } break; default: /* ramified */ if (FZ % p == 0) deg0(R,p); else deg11(R, p, bnr, idealprimedec_galois(nf, N)); break; } } /* precompute isprincipalray(x), x in Z */ v = coprimes_zv(FZ); R->rayZ = cgetg(FZ, t_VEC); for (i = 1; i < FZ; i++) { N[2] = i; gel(R->rayZ,i) = v[i]? isprincipalray(bnr, N): gen_0; } gerepileall(av, 7, &(R->L0), &(R->L2), &(R->rayZ), &(R->L1), &(R->L1ray), &(R->L11), &(R->L11ray)); } static void InitPrimes(GEN bnr, ulong N0, LISTray *R) { GEN bnf = bnr_get_bnf(bnr), cond = gel(bnr_get_mod(bnr), 1); long p, l, condZ, N = lg(cond)-1; GEN DL, prime, BOUND, nf = bnf_get_nf(bnf); forprime_t T; R->condZ = condZ = itos(gcoeff(cond,1,1)); l = primepi_upper_bound(N0) * N; DL = cgetg(N+1, t_VEC); R->L1 = vecsmalltrunc_init(l); R->L1ray = vectrunc_init(l); u_forprime_init(&T, 2, N0); prime = utoipos(2); BOUND = utoi(N0); while ( (p = u_forprime_next(&T)) ) { pari_sp av = avma; long j, k, lP; GEN P; prime[2] = p; if (DEBUGLEVEL>1 && (p & 2047) == 1) err_printf("%ld ", p); P = idealprimedec_limit_norm(nf, prime, BOUND); lP = lg(P); for (j = 1; j < lP; j++) { GEN pr = gel(P,j), dl = NULL; if (condZ % p || !idealval(nf, cond, pr)) { dl = gclone( isprincipalray(bnr, pr) ); vecsmalltrunc_append(R->L1, upowuu(p, pr_get_f(pr))); } gel(DL,j) = dl; } set_avma(av); for (k = 1; k < j; k++) { if (!DL[k]) continue; vectrunc_append(R->L1ray, ZC_copy(gel(DL,k))); gunclone(gel(DL,k)); } } } static GEN /* cf polcoef */ _sercoeff(GEN x, long n) { long i = n - valser(x); return (i < 0)? gen_0: gel(x,i+2); } static void affect_coeff(GEN q, long n, GEN y, long t) { GEN x = _sercoeff(q,-n); if (x == gen_0) gel(y,n) = NULL; else { affgr(x, gel(y,n)); shiftr_inplace(gel(y,n), t); } } /* (x-i)(x-(i+1)) */ static GEN d2(long i) { return deg2pol_shallow(gen_1, utoineg(2*i+1), muluu(i,i+1), 0); } /* x-i */ static GEN d1(long i) { return deg1pol_shallow(gen_1, stoi(-i), 0); } 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 */ static void ppgamma(ST_t *T, long prec) { GEN G, G1, G2, A, E, O, x, sqpi, aij, bij; long c = T->c, r = T->r, i0 = T->i0, i, j, s, t, dx; pari_sp av; T->aij = aij = cgetg(i0+1, t_VEC); T->bij = bij = cgetg(i0+1, t_VEC); for (i = 1; i <= i0; i++) { GEN p1, p2; 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); sqpi = sqrtr_abs(mppi(prec)); /* Gamma(1/2) */ G1 = gexp(integser(psi1series(r-1, 0, prec)), prec); /* Gamma(1 + x) */ G = shallowcopy(G1); setvalser(G,-1); /* Gamma(x) */ /* expansion of log(Gamma(u) / Gamma(1/2)) at u = 1/2 */ G2 = cgetg(r+2, t_SER); G2[1] = evalsigne(1) | _evalvalser(1) | evalvarn(0); gel(G2,2) = gneg(gadd(gmul2n(mplog2(prec), 1), mpeuler(prec))); for (i = 1; i < r; i++) gel(G2,i+2) = mulri(gel(G1,i+2), int2um1(i)); G2 = gmul(sqpi, gexp(G2, 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 (T->b > T->a) { t = T->a; s = T->b; dx = 1; E = ser_unscale(G, ghalf); O = gmul2n(gdiv(ser_unscale(G2, ghalf), d1(1)), 1); /* Gamma((x-1)/2) */ } else { t = T->b; s = T->a; dx = 0; E = ser_unscale(G2, ghalf); O = ser_unscale(G, ghalf); } /* (sqrt(Pi) 2^{1-x})^t Gamma(x)^{t+c} */ A = gmul(gmul(powru(gmul2n(sqpi,1), t), gpowgs(G, t+c)), gpow(gen_2, RgX_to_ser(gmulgs(x,-t), r+2), prec)); /* A * Gamma((x - dx + 1)/2)^{s-t} */ E = gmul(A, gpowgs(E, s-t)); /* A * Gamma((x - dx)/2)^{s-t} */ O = gdiv(gmul(A, gpowgs(O, s-t)), gpowgs(gsubgs(x, 1), t+c)); for (i = 0; i < i0/2; i++) { GEN p1, q1, A1 = gel(aij,2*i+1), B1 = gel(bij,2*i+1); GEN p2, q2, A2 = gel(aij,2*i+2), B2 = gel(bij,2*i+2); long t1 = i * (s+t), t2 = t1 + t; p1 = gdiv(E, d1(2*i)); q1 = gdiv(E, d1(2*i+1)); p2 = gdiv(O, d1(2*i+1)); q2 = gdiv(O, d1(2*i+2)); for (j = 1; j <= r; j++) { affect_coeff(p1, j, A1, t1); affect_coeff(q1, j, B1, t1); affect_coeff(p2, j, A2, t2); affect_coeff(q2, j, B2, t2); } E = gdiv(E, gmul(gpowgs(d1(2*i+1+dx), s-t), gpowgs(d2(2*i+1), t+c))); O = gdiv(O, gmul(gpowgs(d1(2*i+2+dx), s-t), gpowgs(d2(2*i+2), t+c))); } set_avma(av); } /* chi != 1. Return L(1, chi) if fl & 1, else [r, c] where L(s, chi) ~ c s^r * at s = 0. */ static GEN GetValue(GEN dtcr, GEN W, GEN S, GEN T, long fl, long prec) { GEN cf, z; long q, b, c, r; int isreal = (ch_deg(dtcr) <= 2); ch_get3(dtcr, &q, &b, &c); 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, AChi(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, conj_i(S)), conj_i(T)); if (isreal) z = real_i(z); z = gdiv(z, cf); r = 0; if (fl & 2) z = gmul(z, AChi(dtcr, &r, 0, prec)); z = mkvec2(utoi(b + c + r), z); } return z; } /* return the order and the first nonzero 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 = bnr_get_bnf(bnr), nf = bnf_get_nf(bnf); GEN h = bnf_get_no(bnf), R = bnf_get_reg(bnf); GEN c = gdivgs(mpmul(h, R), -bnf_get_tuN(bnf)); long r = lg(nf_get_roots(nf)) - 2; /* r1 + r2 - 1 */; if (flag) { GEN diff = divcond(bnr); long i, l = lg(diff); r += l - 1; for (i = 1; i < l; i++) c = gmul(c, glog(pr_norm(gel(diff,i)), prec)); } return mkvec2(utoi(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_shallow(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) ); /* pop 1st elt */ 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, ct = 0, prec2; FP_chk_fun chk = { &chk_reccoeff, &chk_reccoeff_init, NULL, NULL, 0 }; chk.data = (void*)d; d->G = minss(-10, -prec >> 4); BIG = maxss(32, -2*d->G); tB = sqrtnr(real2n(BIG-N,DEFAULTPREC), N-1); Bd = grndtoi(gmin_shallow(B, tB), &e); if (e > 0) return NULL; /* failure */ Bd = addiu(Bd, 1); prec2 = nbits2prec( expi(Bd) + 192 ); prec2 = maxss(precdbl(prec), prec2); B2 = sqri(Bd); C2 = shifti(B2, BIG<<1); LABrcf: ct++; beta2 = gprec_w(beta, prec2); nf2 = nfnewprec_shallow(nf, prec2); d->M = M = nf_get_M(nf2); A = cgetg(N+2, t_MAT); for (i = 1; i <= N+1; i++) gel(A,i) = cgetg(N+2, t_COL); gcoeff(A, 1, 1) = gadd(gmul(C2, gsqr(beta2)), B2); for (j = 2; j <= N+1; j++) { p1 = gmul(C2, gmul(gneg_i(beta2), gcoeff(M, v, j-1))); gcoeff(A, 1, j) = gcoeff(A, j, 1) = p1; } for (i = 2; i <= N+1; i++) for (j = i; j <= N+1; j++) { p1 = gen_0; for (k = 1; k <= N; k++) { GEN p2 = gmul(gcoeff(M, k, j-1), gcoeff(M, k, i-1)); if (k == v) p2 = gmul(C2, p2); p1 = gadd(p1,p2); } gcoeff(A, i, j) = gcoeff(A, j, i) = p1; } nB = mului(N+1, B2); d->nB = nB; cand = fincke_pohst(A, nB, -1, prec2, &chk); if (!cand) { if (ct > 3) return NULL; prec2 = precdbl(prec2); if (DEBUGLEVEL>1) pari_warn(warnprec,"RecCoeff", prec2); goto LABrcf; } cand = gel(cand,1); if (lg(cand) == 2) return gel(cand,1); if (DEBUGLEVEL>1) err_printf("RecCoeff3: no solution found!\n"); return NULL; } /* Using linear dependence 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 bit, min, max, lM = lg(M); d->G = minss(-20, -prec >> 4); vec = vec_prepend(row(M, d->v), gneg(beta)); min = (long)prec * 0.75; max = (long)prec * 0.98; av = avma; for (bit = max; bit >= min; bit-=32, set_avma(av)) { long e; GEN v = lindep_bit(vec, bit), z = gel(v,1); if (!signe(z)) continue; *++v = evaltyp(t_COL) | _evallg(lM); /* pop 1st elt */ v = grndtoi(gdiv(v, z), &e); if (e > 0) break; if (TestOne(RgM_RgC_mul(M, v), d)) return 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 a certain bound at all the other places. This bound is obtained by assuming that the roots at the other places are, in absolute values, less than 2 if flag == 0, and less than 1 if flag = 1. */ static GEN RecCoeff(GEN nf, GEN pol, long v, long flag, 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 (precision(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 = binomial(utoipos(cl), cf); if (flag == 0) bound = shifti(bound, 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) = coltoalg(nf,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); set_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, chi1; CHI_t C; init_CHI_alg(&C, ch_CHI(dtcr)); condZ= R->condZ; an = InitMatAn(n, deg, 1); reduc = InitReduction(C.ord, 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 = umuluu_le(q,p, n)) ) break; an_mul(an,p,q,n,deg,chi,reduc); if (! (q = umuluu_le(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 = umuluu_le(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 = CHI_eval(&C, ray1); chi12 = CHI_eval(&C, ray2); chi1 = gadd(chi11, chi12); chi2 = chi12; for(q=p;;) { an_mul(an,p,q,n,deg,chi1,reduc); if (! (q = umuluu_le(q,p, n)) ) break; chi2 = gmul(chi2, chi12); chi1 = gadd(chi2, gmul(chi1, chi11)); } } CorrectCoeff(dtcr, an, reduc, n, deg); FreeMat(reduc, deg-1); set_avma(av); return an; } /* return the vector of A^i/i for i = 1...n */ static GEN mpvecpowdiv(GEN A, long n) { pari_sp av = avma; long i; GEN v = powersr(A, n); GEN w = cgetg(n+1, t_VEC); gel(w,1) = rcopy(gel(v,2)); for (i=2; i<=n; i++) gel(w,i) = divru(gel(v,i+1), i); return gerepileupto(av, w); } static void GetST0(GEN bnr, GEN *pS, GEN *pT, GEN CR, long prec); /* allocate memory for GetST answer */ static void ST_alloc(GEN *pS, GEN *pT, long l, long prec) { long j; *pS = cgetg(l, t_VEC); *pT = cgetg(l, t_VEC); for (j = 1; j < l; j++) { gel(*pS,j) = cgetc(prec); gel(*pT,j) = cgetc(prec); } } /* compute S and T for the quadratic case. The following cases are: * 1) bnr complex; * 2) bnr real and no infinite place divide cond_chi (TODO); * 3) bnr real and one infinite place divide cond_chi; * 4) bnr real and both infinite places divide cond_chi (TODO) */ static void QuadGetST(GEN bnr, GEN *pS, GEN *pT, GEN CR, long prec) { pari_sp av, av1, av2; long ncond, n, j, k, n0; GEN vChar = gel(CR,1), dataCR = gel(CR,2), S, T, an, cs, N0, C; LISTray LIST; /* initializations */ ST_alloc(pS, pT, lg(dataCR), prec); T = *pT; S = *pS; av = avma; ncond = lg(vChar)-1; C = cgetg(ncond+1, t_VEC); N0 = cgetg(ncond+1, t_VECSMALL); cs = cgetg(ncond+1, t_VECSMALL); n0 = 0; for (j = 1; j <= ncond; j++) { GEN dtcr = gel(dataCR, mael(vChar,j,1)), c = ch_C(dtcr); long r1, r2; gel(C,j) = c; nf_get_sign(bnr_get_nf(ch_bnr(dtcr)), &r1, &r2); if (r1 == 2) /* real quadratic */ { cs[j] = 2 + ch_q(dtcr); if (cs[j] == 2 || cs[j] == 4) { /* NOT IMPLEMENTED YET */ GetST0(bnr, pS, pT, CR, prec); return; } /* FIXME: is this value of N0 correct for the general case ? */ N0[j] = (long)prec * 0.35 * gtodouble(c); } else /* complex quadratic */ { cs[j] = 1; N0[j] = (long)prec * 0.7 * gtodouble(c); } if (n0 < N0[j]) n0 = N0[j]; } if (DEBUGLEVEL>1) err_printf("N0 = %ld\n", n0); InitPrimesQuad(bnr, n0, &LIST); av1 = avma; /* loop over conductors */ for (j = 1; j <= ncond; j++) { GEN c0 = gel(C,j), c1 = divur(1, c0), c2 = divur(2, c0); GEN ec1 = mpexp(c1), ec2 = mpexp(c2), LChar = gel(vChar,j); GEN vf0, vf1, cf0, cf1; const long nChar = lg(LChar)-1, NN = N0[j]; if (DEBUGLEVEL>1) err_printf("* conductor no %ld/%ld (N = %ld)\n\tInit: ", j,ncond,NN); if (realprec(ec1) > prec) ec1 = rtor(ec1, prec); if (realprec(ec2) > prec) ec2 = rtor(ec2, prec); switch(cs[j]) { case 1: cf0 = gen_1; cf1 = c0; vf0 = mpveceint1(rtor(c1, prec), ec1, NN); vf1 = mpvecpowdiv(invr(ec1), NN); break; case 3: cf0 = sqrtr(mppi(prec)); cf1 = gmul2n(cf0, 1); cf0 = gmul(cf0, c0); vf0 = mpvecpowdiv(invr(ec2), NN); vf1 = mpveceint1(rtor(c2, prec), ec2, NN); break; default: cf0 = cf1 = NULL; /* FIXME: not implemented */ vf0 = vf1 = NULL; } for (k = 1; k <= nChar; k++) { long u = LChar[k], d, c; GEN dtcr = gel(dataCR, u), z, s, t; int **matan; if (!ch_comp(dtcr)) continue; if (DEBUGLEVEL>1) err_printf("\tchar no: %ld (%ld/%ld)\n", u,k,nChar); d = ch_phideg(dtcr); z = gel(ch_CHI(dtcr), 2); s = t = gen_0; av2 = avma; matan = computean(gel(dataCR,u), &LIST, NN, d); for (n = 1, c = 0; n <= NN; n++) if ((an = EvalCoeff(z, matan[n], d))) { s = gadd(s, gmul(an, gel(vf0,n))); t = gadd(t, gmul(an, gel(vf1,n))); if (++c == 256) { gerepileall(av2,2, &s,&t); c = 0; } } gaffect(gmul(cf0, s), gel(S,u)); gaffect(gmul(cf1, conj_i(t)), gel(T,u)); FreeMat(matan,NN); set_avma(av2); } if (DEBUGLEVEL>1) err_printf("\n"); set_avma(av1); } set_avma(av); } /* s += t*u. All 3 of them t_REAL, except we allow s or u = NULL (for 0) */ static GEN _addmulrr(GEN s, GEN t, GEN u) { if (u) { GEN v = mulrr(t, u); return s? addrr(s, v): v; } return s; } /* s += t. Both real, except we allow s or t = NULL (for exact 0) */ static GEN _addrr(GEN s, GEN t) { return t? (s? addrr(s, t): t) : s; } /* S & T for the general case. This is time-critical: optimize */ static void get_cS_cT(ST_t *T, long n) { pari_sp av; GEN csurn, nsurc, lncsurn, A, B, s, t, Z, aij, bij; long i, j, r, i0; if (gel(T->cS,n)) return; av = avma; aij = T->aij; i0= T->i0; bij = T->bij; r = T->r; Z = cgetg(r+1, t_VEC); gel(Z,1) = NULL; /* unused */ csurn = divru(T->c1, n); nsurc = invr(csurn); lncsurn = logr_abs(csurn); if (r > 1) { gel(Z,2) = lncsurn; /* r >= 2 */ for (i = 3; i <= r; i++) gel(Z,i) = divru(mulrr(gel(Z,i-1), lncsurn), i-1); /* Z[i] = ln^(i-1)(c1/n) / (i-1)! */ } /* i = i0 */ A = gel(aij,i0); t = _addrr(NULL, gel(A,1)); B = gel(bij,i0); s = _addrr(NULL, gel(B,1)); for (j = 2; j <= r; j++) { s = _addmulrr(s, gel(Z,j),gel(B,j)); t = _addmulrr(t, gel(Z,j),gel(A,j)); } for (i = i0 - 1; i > 1; i--) { A = gel(aij,i); if (t) t = mulrr(t, nsurc); B = gel(bij,i); if (s) s = mulrr(s, nsurc); for (j = odd(i)? T->rc2: T->rc1; j > 1; j--) { s = _addmulrr(s, gel(Z,j),gel(B,j)); t = _addmulrr(t, gel(Z,j),gel(A,j)); } s = _addrr(s, gel(B,1)); t = _addrr(t, gel(A,1)); } /* i = 1 */ A = gel(aij,1); if (t) t = mulrr(t, nsurc); B = gel(bij,1); if (s) s = mulrr(s, nsurc); s = _addrr(s, gel(B,1)); t = _addrr(t, gel(A,1)); for (j = 2; j <= r; j++) { s = _addmulrr(s, gel(Z,j),gel(B,j)); t = _addmulrr(t, gel(Z,j),gel(A,j)); } s = _addrr(s, T->b? mulrr(csurn, gel(T->powracpi,T->b+1)): csurn); if (!s) s = gen_0; if (!t) t = gen_0; gel(T->cS,n) = gclone(s); gel(T->cT,n) = gclone(t); set_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) { ch_get3(dtcr, &T->a, &T->b, &T->c); 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); } /* return a t_REAL */ static GEN zeta_get_limx(long r1, long r2, long bit) { pari_sp av = avma; GEN p1, p2, c0, c1, A0; long r = r1 + r2, N = r + r2; /* c1 = N 2^(-2r2 / N) */ c1 = mulrs(powrfrac(real2n(1, DEFAULTPREC), -2*r2, N), N); p1 = powru(Pi2n(1, DEFAULTPREC), r - 1); p2 = mulir(powuu(N,r), p1); shiftr_inplace(p2, -r2); c0 = sqrtr( divrr(p2, powru(c1, r+1)) ); A0 = logr_abs( gmul2n(c0, bit) ); p2 = divrr(A0, c1); p1 = divrr(mulur(N*(r+1), logr_abs(p2)), addsr(2*(r+1), gmul2n(A0,2))); return gerepileuptoleaf(av, divrr(addrs(p1, 1), powruhalf(p2, N))); } /* N_0 = floor( C_K / limx ). Large */ static long zeta_get_N0(GEN C, GEN limx) { long e; pari_sp av = avma; GEN z = gcvtoi(gdiv(C, limx), &e); /* avoid truncation error */ if (e >= 0 || is_bigint(z)) pari_err_OVERFLOW("zeta_get_N0 [need too many primes]"); return gc_long(av, itos(z)); } static GEN eval_i(long r1, long r2, GEN limx, long i) { 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))); } return t; } /* "small" even i such that limx^i ( (i\2)! )^r1 ( i! )^r2 > B. */ static long get_i0(long r1, long r2, GEN B, GEN limx) { long imin = 1, imax = 1400; while (mpcmp(eval_i(r1,r2,limx, imax), B) < 0) { imin = imax; imax *= 2; } while(imax - imin >= 4) { long m = (imax + imin) >> 1; if (mpcmp(eval_i(r1,r2,limx, m), B) >= 0) imax = m; else imin = m; } return imax & ~1; /* make it even */ } /* limx = zeta_get_limx(r1, r2, bit), a t_REAL */ static 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)); return gc_long(av, get_i0(r1, r2, B, limx)); } static void GetST0(GEN bnr, GEN *pS, GEN *pT, GEN CR, long prec) { pari_sp av, av1, av2; long n, j, k, jc, n0, prec2, i0, r1, r2, ncond; GEN nf = bnr_get_nf(bnr); GEN vChar = gel(CR,1), dataCR = gel(CR,2), N0, C, an, limx, S, T; LISTray LIST; ST_t cScT; ST_alloc(pS, pT, lg(dataCR), prec); T = *pT; S = *pS; av = avma; nf_get_sign(nf,&r1,&r2); ncond = lg(vChar)-1; C = cgetg(ncond+1, t_VEC); N0 = cgetg(ncond+1, t_VECSMALL); n0 = 0; limx = zeta_get_limx(r1, r2, 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]; } cScT.i0 = i0 = zeta_get_i0(r1, r2, prec, limx); if (DEBUGLEVEL>1) err_printf("i0 = %ld, N0 = %ld\n",i0, n0); InitPrimes(bnr, n0, &LIST); prec2 = precdbl(prec) + EXTRAPREC64; cScT.powracpi = powersr(sqrtr(mppi(prec2)), r1); 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; av1 = avma; for (jc = 1; jc <= ncond; jc++) { GEN LChar = gel(vChar,jc); long nChar = lg(LChar)-1, N = N0[jc]; /* Can discard completely a conductor if all chars satisfy L(0,chi) = 0 * Not sure whether this is possible. */ if (DEBUGLEVEL>1) err_printf("* conductor no %ld/%ld (N = %ld)\n\tInit: ", jc,ncond,N); cScT.c1 = gel(C,jc); init_cScT(&cScT, gel(dataCR, LChar[1]), N, prec2); av2 = avma; for (k = 1; k <= nChar; k++) { long d, c, u = LChar[k]; GEN dtcr = gel(dataCR, u), z, s, t; int **matan; if (!ch_comp(dtcr)) continue; if (DEBUGLEVEL>1) err_printf("\tchar no: %ld (%ld/%ld)\n", u,k,nChar); z = gel(ch_CHI(dtcr), 2); d = ch_phideg(dtcr); s = t = gen_0; matan = ComputeCoeff(dtcr, &LIST, N, d); for (n = 1, c = 0; n <= N; n++) if ((an = EvalCoeff(z, matan[n], d))) { get_cS_cT(&cScT, n); s = gadd(s, gmul(an, gel(cScT.cS,n))); t = gadd(t, gmul(an, gel(cScT.cT,n))); if (++c == 256) { gerepileall(av2,2, &s,&t); c = 0; } } gaffect(s, gel(S,u)); gaffect(conj_i(t), gel(T,u)); FreeMat(matan, N); set_avma(av2); } if (DEBUGLEVEL>1) err_printf("\n"); set_avma(av1); } clear_cScT(&cScT, n0); set_avma(av); } static void GetST(GEN bnr, GEN *pS, GEN *pT, GEN CR, long prec) { if (nf_get_degree(bnr_get_nf(bnr)) == 2) QuadGetST(bnr, pS, pT, CR, prec); else GetST0(bnr, pS, pT, CR, prec); } /*******************************************************************/ /* */ /* Class fields of real quadratic fields using Stark units */ /* */ /*******************************************************************/ /* compute the Hilbert class field using genus class field theory when the exponent of the class group is exactly 2 (trivial group not covered) */ /* Cf Herz, Construction of class fields, LNM 21, Theorem 1 (VII-6) */ static GEN GenusFieldQuadReal(GEN disc) { GEN T = NULL, p0 = NULL, P = gel(Z_factor(disc), 1); long i, i0 = 0, 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 (absequaliu(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_composedsum(T, t): t; } return polredbest(T, 0); } static GEN GenusFieldQuadImag(GEN disc) { GEN T = NULL, P = gel(absZ_factor(disc), 1); long i, n = lg(P)-1; for (i = 1; i < n; i++) /* remove last prime */ { GEN p = gel(P,i), d, t; if (absequaliu(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_composedsum(T, t): t; } return polredbest(T, 0); } /* if flag = 1, computes a fast and crude approximation of the trace of the Stark unit if flag = 2, computes the Stark unit */ static GEN AllStark(GEN data, 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), nf = bnr_get_nf(bnr), p1, p2, S, T; GEN CR = gel(data,4), dataCR = gel(CR,2); GEN polrelnum, polrel, Lp, W, vzeta, C, 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); v = 1; while (gequal1(gel(cond1,v))) v++; cl = lg(dataCR)-1; h = itos(ZM_det_triangular(gel(data,2))) >> 1; LABDOUB: if (DEBUGLEVEL) timer_start(&ti); av = avma; W = AllArtinNumbers(CR, newprec); if (DEBUGLEVEL) timer_printf(&ti,"Compute W"); Lp = cgetg(cl + 1, t_VEC); if (flag != 1) { GetST(bnr, &S, &T, CR, newprec); if (DEBUGLEVEL) timer_printf(&ti, "S&T"); for (i = 1; i <= cl; i++) { GEN chi = gel(dataCR, i), vv = gen_0; if (ch_comp(chi)) vv = gel(GetValue(chi, gel(W,i), gel(S,i), gel(T,i), 2, newprec), 2); gel(Lp, i) = vv; } } 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, 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); long d = ch_phideg(dtcr); matan = ComputeCoeff(dtcr, &LIST, n, d); av2 = avma; p1 = real_0(newprec); p2 = gel(ch_CHI(dtcr), 2); for (j = 1; j <= n; j++) if ( (an = EvalCoeff(p2, matan[j], d)) ) p1 = gadd(p1, gdivgu(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 = AChi(gel(dataCR,i), &r, 0, newprec); WW = gmul(gel(C,i), gmul(A, gel(W,i))); gel(Lp,i) = gdiv(gmul(WW, conj_i(gel(L1,i))), p1); } } p1 = gel(data,3); den = (flag == 0) ? 2*h: h; if (flag == 2) vzeta = cgetg(2*h + 1, t_VEC); else vzeta = 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), CharEval(CHI, sig)); if (chi_get_deg(CHI) != 2) t = gmul2n(t, 1); /* character not real */ z = gadd(z, t); } z = gdivgu(z, den); if (flag == 2) { gel(vzeta, i) = gexp(gmul2n(z,1), newprec); gel(vzeta, i+h) = ginv(gel(vzeta,i)); } /* if flag == 0, we first try with the square-root of the Stark unit */ else gel(vzeta,i) = gmul2n(gcosh(z, newprec), 1); } polrelnum = roots_to_pol(vzeta, 0); if (DEBUGLEVEL) { if (DEBUGLEVEL>1) { err_printf("polrelnum = %Ps\n", polrelnum); err_printf("zetavalues = %Ps\n", vzeta); if (flag == 0) err_printf("Checking the square-root of the Stark unit...\n"); } timer_printf(&ti, "Compute %s", flag? "quickpol": "polrelnum"); } if (flag == 1) return gerepilecopy(av, polrelnum); /* try to recognize this polynomial */ polrel = RecCoeff(nf, polrelnum, v, flag, newprec); /* if this doesn't work, maybe the Stark unit is not a square */ if (!polrel && flag == 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"); } for (j = 1; j <= h; j++) gel(vzeta,j) = gsubgs(gsqr(gel(vzeta,j)), 2); polrelnum = roots_to_pol(vzeta, 0); polrel = RecCoeff(nf, polrelnum, v, 0, newprec); } if (!polrel) /* FAILED */ { const long EXTRA_BITS = 64; long incr_pr; if (++cpt >= 3) pari_err_PREC( "stark (computation impossible)"); /* estimate needed precision */ incr_pr = gprecision(polrelnum) - gexpo(polrelnum); if (incr_pr < 0) incr_pr = -incr_pr + EXTRA_BITS; newprec += nbits2extraprec(maxss(3*EXTRA_BITS, cpt*incr_pr)); if (DEBUGLEVEL) pari_warn(warnprec, "AllStark", newprec); CharNewPrec(data, newprec); nf = bnr_get_nf(ch_bnr(gel(dataCR,1))); 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 bnrstark_cyclic(GEN bnr, GEN dtQ, long prec) { GEN v, vH, cyc = gel(dtQ,2), U = gel(dtQ,3), M = ZM_inv(U, NULL); long i, j, l = lg(M); /* M = indep. generators of Cl_f/subgp, restrict to cyclic components */ vH = cgetg(l, t_VEC); for (i = j = 1; i < l; i++) { if (is_pm1(gel(cyc,i))) break; gel(vH, j++) = ZM_hnfmodid(vecsplice(M,i), cyc); } setlg(vH, j); v = cgetg(l, t_VEC); for (i = 1; i < j; i++) gel(v,i) = bnrstark(bnr, gel(vH,i), prec); return v; } GEN bnrstark(GEN bnr, GEN subgrp, long prec) { long newprec; pari_sp av = avma; GEN nf, data, dtQ; /* check the bnr */ checkbnr(bnr); nf = bnr_get_nf(bnr); if (nf_get_degree(nf) == 1) return galoissubcyclo(bnr, subgrp, 0, 0); if (!nf_get_varn(nf)) pari_err_PRIORITY("bnrstark", nf_get_pol(nf), "=", 0); if (nf_get_r2(nf)) pari_err_DOMAIN("bnrstark", "r2", "!=", gen_0, nf); /* compute bnr(conductor) */ bnr_subgroup_sanitize(&bnr, &subgrp); if (gequal1(ZM_det_triangular(subgrp))) { set_avma(av); return pol_x(0); } /* check the class field */ if (!gequal0(gel(bnr_get_mod(bnr), 2))) pari_err_DOMAIN("bnrstark", "r2(class field)", "!=", gen_0, bnr); /* find a suitable extension N */ dtQ = InitQuotient(subgrp); data = FindModulus(bnr, dtQ, &newprec); if (!data) return gerepileupto(av, bnrstark_cyclic(bnr, dtQ, prec)); if (DEBUGLEVEL>1 && newprec > prec) err_printf("new precision: %ld\n", newprec); return gerepileupto(av, AllStark(data, 0, newprec)); } GEN bnrstarkunit(GEN bnr, GEN subgrp) { long newprec, deg; pari_sp av = avma; GEN nf, data, dtQ, bnf, bnrf, Cm, candD, D, QD, CR; /* check the input */ checkbnr(bnr); bnf = bnr_get_bnf(bnr); nf = bnf_get_nf(bnf); if (!nf_get_varn(nf)) pari_err_PRIORITY("bnrstarkunit", nf_get_pol(nf), "=", 0); deg = nf_get_degree(nf); if (deg == 1) pari_err_IMPL("bnrstarkunit for basefield Q"); if (nf_get_r2(nf)) pari_err_DOMAIN("bnrstarkunit", "r2", "!=", gen_0, nf); bnr_subgroup_sanitize(&bnr, &subgrp); if (lg(bid_get_archp(bnr_get_bid(bnr)))-1 != deg-1) pari_err_DOMAIN("bnrstarkunit", "# unramified places", "!=", gen_1, bnr); bnrf = Buchray(bnf, gel(bnr_get_mod(bnr), 1), nf_INIT); subgrp = abmap_subgroup_image(bnrsurjection(bnr, bnrf), subgrp); dtQ = InitQuotient(subgrp); Cm = ComputeKernel(bnr, bnrf, dtQ); candD = subgrouplist_cond_sub(bnr, Cm, mkvec(gen_2)); if (lg(candD) != 2) pari_err(e_MISC, "incorrect modulus in bnrstark"); D = gel(candD, 1); QD = InitQuotient(D); CR = InitChar(bnr, AllChars(bnr, QD, 1), 0, DEFAULTPREC); data = mkvec4(bnr, D, subgroup_classes(Cm), CR); CplxModulus(data, &newprec); return gerepileupto(av, AllStark(data, 2, newprec)); } /* For each character of Cl(bnr)/subgp, compute L(1, chi) (or equivalently * the first nonzero term c(chi) of the expansion at s = 0). * If flag & 1: compute the value at s = 1 (for nontrivial 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 attached to chi, * If flag & 4: return also the character */ GEN bnrL1(GEN bnr, GEN subgp, long flag, long prec) { GEN L1, ch, Qt, z; long l, h; pari_sp av = avma; checkbnr(bnr); if (flag < 0 || flag > 8) pari_err_FLAG("bnrL1"); subgp = bnr_subgroup_check(bnr, subgp, NULL); if (!subgp) subgp = diagonal_shallow(bnr_get_cyc(bnr)); Qt = InitQuotient(subgp); ch = AllChars(bnr, Qt, 0); l = lg(ch); h = itou(gel(Qt,1)); L1 = cgetg((flag&1)? h: h+1, t_VEC); if (l > 1) { GEN W, S, T, CR = InitChar(bnr, ch, 1, prec), dataCR = gel(CR,2); long i, j; GetST(bnr, &S, &T, CR, prec); W = AllArtinNumbers(CR, prec); for (i = j = 1; i < l; i++) { GEN chi = gel(ch,i); z = GetValue(gel(dataCR,i), gel(W,i), gel(S,i), gel(T,i), flag, prec); gel(L1,j++) = (flag & 4)? mkvec2(gel(chi,1), z): z; if (lg(chi) == 4) { /* nonreal */ z = conj_i(z); gel(L1, j++) = (flag & 4)? mkvec2(gel(chi,3), z): z; } } } if (!(flag & 1)) { /* trivial character */ z = GetValue1(bnr, flag & 2, prec); if (flag & 4) { GEN chi = zerovec(lg(bnr_get_cyc(bnr))-1); z = mkvec2(chi, z); } gel(L1,h) = z; } 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; P = lift_shallow(P); split_pol_quad(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_oneroot(nfpol, p); /* 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) { ulong o = perm_orderu(perm); if (o != 2) perm = perm_powu(perm, o >> 1); /* perm has order two and doesn't belong to Gal(H_k/k) */ return polredbest(galoisfixedfield(G, perm, 1, varn(P)), 0); } } pari_err_BUG("makescind"); return NULL; /*LCOV_EXCL_LINE*/ } /* pbnf = NULL if no bnf is needed, f = NULL may be passed for a trivial * conductor */ static void quadray_init(GEN *pD, GEN *pbnf, long prec) { GEN D = *pD, nf, bnf = NULL; if (typ(D) == t_INT) { int isfund; if (pbnf) { bnf = Buchall(quadpoly0(D, 1), nf_FORCE, prec); nf = bnf_get_nf(bnf); isfund = equalii(D, nf_get_disc(nf)); } else isfund = Z_isfundamental(D); if (!isfund) pari_err_DOMAIN("quadray", "isfundamental(D)", "=",gen_0, D); } else { bnf = checkbnf(D); nf = bnf_get_nf(bnf); if (nf_get_degree(nf) != 2) pari_err_DOMAIN("quadray", "degree", "!=", gen_2, nf_get_pol(nf)); D = nf_get_disc(nf); } if (pbnf) *pbnf = bnf; *pD = D; } /* compute the polynomial over Q of the Hilbert class field of Q(sqrt(D)) where D is a positive fundamental discriminant */ static GEN quadhilbertreal(GEN D, long prec) { GEN bnf, bnr, dtQ, data, M; long newprec; pari_timer T; quadray_init(&D, &bnf, prec); switch(itou_or_0(cyc_get_expo(bnf_get_cyc(bnf)))) { case 1: return pol_x(0); case 2: return GenusFieldQuadReal(D); } bnr = Buchray(bnf, gen_1, nf_INIT); M = diagonal_shallow(bnr_get_cyc(bnr)); dtQ = InitQuotient(M); if (DEBUGLEVEL) timer_start(&T); data = FindModulus(bnr, dtQ, &newprec); if (DEBUGLEVEL) timer_printf(&T,"FindModulus"); if (!data) return bnrstark_cyclic(bnr, dtQ, prec); return makescind(bnf_get_nf(bnf), AllStark(data, 0, newprec)); } /*******************************************************************/ /* */ /* 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) || absequalii(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((double)d) * log2(d)), t_VEC); b2 = b = (d&1); h = 0; if (!b) /* b = 0 treated separately to avoid special cases */ { t = d >> 2; /* (b^2 - D) / 4*/ for (a=1; a*a<=t; a++) if (c = t/a, t == c*a) gel(L,++h) = mkvecsmall3(a,0,c); b = 2; b2 = 4; } /* now b > 0, b = D (mod 2) */ for ( ; b2 <= dover3; b += 2, b2 = b*b) { t = (b2 + d) >> 2; /* (b^2 - D) / 4*/ /* b = a */ if (c = t/b, t == c*b) gel(L,++h) = mkvecsmall3(b,b,c); /* b < a < c */ for (a = b+1; a*a < t; a++) if (c = t/a, t == c*a) { gel(L,++h) = mkvecsmall3(a, b,c); gel(L,++h) = mkvecsmall3(a,-b,c); } /* a = c */ if (a * a == t) gel(L,++h) = mkvecsmall3(a,b,a); } setlg(L,h+1); return L; } /* gcd(n, 24) */ static long GCD24(long n) { switch(n % 24) { case 0: return 24; case 1: return 1; case 2: return 2; case 3: return 3; case 4: return 4; case 5: return 1; case 6: return 6; case 7: return 1; case 8: return 8; case 9: return 3; case 10: return 2; case 11: return 1; case 12: return 12; case 13: return 1; case 14: return 2; case 15: return 3; case 16: return 8; case 17: return 1; case 18: return 6; case 19: return 1; case 20: return 4; case 21: return 3; case 22: return 2; case 23: return 1; default: return 0; } } struct gpq_data { long p, q; GEN sqd; /* sqrt(D), t_REAL */ GEN u, D; GEN pq, pq2; /* p*q, 2*p*q */ GEN qfpq ; /* class of \P * \Q */ }; /* find P and Q two non principal prime ideals (above p <= q) such that * cl(P) = cl(Q) if P,Q have order 2 in Cl(K). * Ensure that e = 24 / gcd(24, (p-1)(q-1)) = 1 */ /* D t_INT, discriminant */ static void init_pq(GEN D, struct gpq_data *T) { const long Np = 6547; /* N.B. primepi(50000) = 5133 */ const ulong maxq = 50000; GEN listp = cgetg(Np + 1, t_VECSMALL); /* primes p */ GEN listP = cgetg(Np + 1, t_VEC); /* primeform(p) if of order 2, else NULL */ GEN gcd24 = cgetg(Np + 1, t_VECSMALL); /* gcd(p-1, 24) */ forprime_t S; long l = 1; double best = 0.; ulong q; u_forprime_init(&S, 2, ULONG_MAX); T->D = D; T->p = T->q = 0; for(;;) { GEN Q; long i, gcdq, mod; int order2, store; double t; q = u_forprime_next(&S); if (best > 0 && q >= maxq) { if (DEBUGLEVEL) pari_warn(warner,"possibly suboptimal (p,q) for D = %Ps", D); break; } if (kroiu(D, q) < 0) continue; /* inert */ Q = qfbred_i(primeform_u(D, q)); if (is_pm1(gel(Q,1))) continue; /* Q | q is principal */ store = 1; order2 = hasexp2(Q); gcd24[l] = gcdq = GCD24(q-1); mod = 24 / gcdq; /* mod must divide p-1 otherwise e > 1 */ listp[l] = q; gel(listP,l) = order2 ? Q : NULL; t = (q+1)/(double)(q-1); for (i = 1; i < l; i++) /* try all (p, q), p < q in listp */ { long p = listp[i], gcdp = gcd24[i]; double b; /* P,Q order 2 => cl(Q) = cl(P) */ if (order2 && gel(listP,i) && !gequal(gel(listP,i), Q)) continue; if (gcdp % gcdq == 0) store = 0; /* already a better one in the list */ if ((p-1) % mod) continue; b = (t*(p+1)) / (p-1); /* (p+1)(q+1) / (p-1)(q-1) */ if (b > best) { store = 0; /* (p,q) always better than (q,r) for r >= q */ best = b; T->q = q; T->p = p; if (DEBUGLEVEL>2) err_printf("p,q = %ld,%ld\n", p, q); } /* won't improve with this q as largest member */ if (best > 0) break; } /* if !store or (q,r) won't improve on current best pair, forget that q */ if (store && t*t > best) if (++l >= Np) pari_err_BUG("quadhilbert (not enough primes)"); if (!best) /* (p,q) with p < q always better than (q,q) */ { /* try (q,q) */ if (gcdq >= 12 && umodiu(D, q)) /* e = 1 and unramified */ { double b = (t*q) / (q-1); /* q(q+1) / (q-1)^2 */ if (b > best) { best = b; T->q = T->p = q; if (DEBUGLEVEL>2) err_printf("p,q = %ld,%ld\n", q, q); } } } /* If (p1+1)(q+1) / (p1-1)(q-1) <= best, we can no longer improve * even with best p : stop */ if ((listp[1]+1)*t <= (listp[1]-1)*best) break; } if (DEBUGLEVEL>1) err_printf("(p, q) = %ld, %ld; gain = %f\n", T->p, T->q, 12*best); } static GEN gpq(GEN form, struct gpq_data *T) { pari_sp av = avma; long a = form[1], b = form[2], c = form[3], p = T->p, q = T->q; GEN form2, w, z; int fl, real = 0; form2 = qfbcomp_i(T->qfpq, mkqfb(stoi(a), stoi(-b), stoi(c), T->D)); /* 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; 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 (! (h & (h - 1))) /* 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 = qfbcompraw(qfp, qfp); u = gel(qfbp2,2); T.u = modii(u, T.pq2); T.qfpq = qfbred_i(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 = qfbcomp_i(qfp, qfq); } /* u modulo 2pq */ prec = LOWDEFAULTPREC; Pr = cgetg(h+1,t_VEC); Pi = cgetg(h+1,t_VEC); for(;;) { long ex, exmax = 0, r1 = 0, r2 = 0; pari_sp av0 = avma; T.sqd = sqrtr_abs(itor(D, prec)); for (i=1; i<=h; i++) { GEN s = gpq(gel(L,i), &T); if (DEBUGLEVEL>3) err_printf("%ld ", i); if (!s) continue; if (typ(s) != t_COMPLEX) gel(Pr, ++r1) = s; /* real root */ else gel(Pi, ++r2) = s; ex = gexpo(s); if (ex > 0) exmax += ex; } if (DEBUGLEVEL>1) timer_printf(&ti,"roots"); setlg(Pr, r1+1); setlg(Pi, r2+1); P = roots_to_pol_r1(shallowconcat(Pr,Pi), 0, r1); P = grndtoi(P,&exmax); if (DEBUGLEVEL>1) timer_printf(&ti,"product, error bits = %ld",exmax); if (exmax <= -10) break; set_avma(av0); prec += nbits2extraprec(DEFAULTPREC + exmax); if (DEBUGLEVEL) pari_warn(warnprec,"quadhilbertimag",prec); } return P; } GEN quadhilbert(GEN D, long prec) { pari_sp av = avma; GEN d = D; quadray_init(&d, NULL, 0); return gerepileupto(av, signe(d)>0? quadhilbertreal(D,prec) : quadhilbertimag(d)); } /* return a vector of all roots of 1 in bnf [not necessarily quadratic] */ static GEN getallrootsof1(GEN bnf) { GEN T, u, nf = bnf_get_nf(bnf), tu; long i, n = bnf_get_tuN(bnf); if (n == 2) { long N = nf_get_degree(nf); return mkvec2(scalarcol_shallow(gen_m1, N), scalarcol_shallow(gen_1, N)); } tu = poltobasis(nf, bnf_get_tuU(bnf)); T = zk_multable(nf, tu); u = cgetg(n+1, t_VEC); gel(u,1) = tu; for (i=2; i <= n; i++) gel(u,i) = ZM_ZC_mul(T, gel(u,i-1)); return u; } /* assume bnr has the right conductor */ static GEN get_lambda(GEN bnr) { GEN bnf = bnr_get_bnf(bnr), nf = bnf_get_nf(bnf), pol = nf_get_pol(nf); GEN f = gel(bnr_get_mod(bnr), 1), labas, lamodf, u; long a, b, f2, i, lu, v = varn(pol); f2 = 2 * itos(gcoeff(f,1,1)); u = getallrootsof1(bnf); lu = lg(u); for (i=1; i1) err_printf("quadray: looking for [a,b] != unit mod 2f\n[a,b] = "); for (a=0; a1) err_printf("[%ld,%ld] ",a,b); labas = poltobasis(nf, la); lamodf = ZC_hnfrem(labas, f); for (i=1; i1) err_printf("\n"); err_printf("lambda = %Ps\n",la); } return labas; } pari_err_BUG("get_lambda"); return NULL;/*LCOV_EXCL_LINE*/ } 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; i 20 || gexpo(p2) > minss(prec,realprec(p2)) - 10) return NULL; return gexp(p1,prec); } /* Computes P_2(X)=polynomial in Z_K[X] closest to prod_gc(X-th2(gc)) where the product is over the ray class group bnr.*/ static GEN computeP2(GEN bnr, long prec) { long clrayno, i, first = 1; pari_sp av=avma, av2; GEN listray, P0, P, lanum, la = get_lambda(bnr); GEN nf = bnr_get_nf(bnr), f = gel(bnr_get_mod(bnr), 1); listray = getallelts(bnr); clrayno = lg(listray)-1; av2 = avma; PRECPB: if (!first) { if (DEBUGLEVEL) pari_warn(warnprec,"computeP2",prec); nf = gerepilecopy(av2, nfnewprec_shallow(bnr_get_nf(bnr),prec)); } first = 0; lanum = to_approx(nf,la); P = cgetg(clrayno+1,t_VEC); for (i=1; i<=clrayno; i++) { GEN om = get_om(nf, idealdiv(nf,f,gel(listray,i))); GEN s = computeth2(om,lanum,prec); if (!s) { prec = precdbl(prec); goto PRECPB; } gel(P,i) = s; } P0 = roots_to_pol(P, 0); P = findbezk_pol(nf, P0); if (!P) { prec = get_prec(P0, prec); goto PRECPB; } return gerepilecopy(av, P); } #define nexta(a) (a>0 ? -a : 1-a) static GEN do_compo(GEN A0, GEN B) { long a, i, l = lg(B), v = fetch_var_higher(); GEN A, z; /* now v > x = pol_x(0) > nf variable */ B = leafcopy(B); setvarn(B, v); for (i = 2; i < l; i++) gel(B,i) = monomial(gel(B,i), l-i-1, 0); /* B := x^deg(B) B(v/x) */ A = A0 = leafcopy(A0); setvarn(A0, v); for (a = 0;; a = nexta(a)) { if (a) A = RgX_translate(A0, stoi(a)); z = resultant(A,B); /* in variable 0 */ if (issquarefree(z)) break; } (void)delete_var(); 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); /* prime */ if (absequalui(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_i(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_shallow(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, RgX_coeff(polLK,1))); /* s(b) = Tr(b) - b */ s = gadd(pol_x(vx), gsub(sb, b)); /* s(t) = t + s(b) - b */ p3 = gmul(p3, galoisapplypol(nfL, s, p3)); return findquad_pol(nf_get_pol(nf), a, p3); } /* 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 (absequaliu(D,3)) /* Q(j) */ { if (i == 4 || i == 5 || i == 7) return polcyclo(i,0); if (!absequaliu(gcoeff(f,1,1),9) || !absequaliu(Z_content(f),3)) return NULL; /* f = P_3^3 */ p1 = mkpolmod(bnf_get_tuU(bnf), nf_get_pol(nf)); return gadd(pol_xn(3,0), p1); /* x^3+j */ } if (absequaliu(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(pol_xn(2,0), p1); /* x^2+i */ } Ds = smodis(D,48); if (i) { if (i==2 && Ds%16== 8) return compocyclo(D, 4); if (i==3 && Ds% 3== 1) return compocyclo(D, 3); if (i==4 && Ds% 8== 1) return compocyclo(D, 4); if (i==6 && Ds ==40) return compocyclo(D,12); return NULL; } p1 = gcoeff(f,1,1); /* integer > 0 */ tryf = itou_or_0(p1); if (!tryf) return NULL; p2 = gcoeff(f,2,2); /* integer > 0 */ if (is_pm1(p2)) fl = 0; else { if (Ds % 16 != 8 || !absequaliu(Z_content(f),2)) return NULL; fl = 1; tryf >>= 1; } if (tryf <= 3 || umodiu(D, tryf) || !uisprime(tryf)) return NULL; if (fl) tryf <<= 2; return compocyclop(nf, tryf); } GEN quadray(GEN D, GEN f, long prec) { GEN bnr, y, bnf, H = NULL; pari_sp av = avma; if (isint1(f)) return quadhilbert(D, prec); if (typ(D) == t_INT && typ(f) != t_INT) pari_err_TYPE("quadray [conductor]", f); quadray_init(&D, &bnf, prec); bnr = Buchray(bnf, f, nf_INIT|nf_GEN); if (is_pm1(bnr_get_no(bnr))) { set_avma(av); return pol_x(0); } if (signe(D) > 0) y = bnrstark(bnr, H, prec); else { bnr_subgroup_sanitize(&bnr, &H); y = treatspecialsigma(bnr); if (!y) y = computeP2(bnr, prec); } return gerepileupto(av, y); } pari-2.17.2/src/modules/mpqs.c0000644000175000017500000017435314760123736014575 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* Self-Initializing Multi-Polynomial Quadratic Sieve, based on code developed * as part of the LiDIA project. * * Original version: Thomas Papanikolaou and Xavier Roblot * 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 squarefree * multiplier k so as to make kN = 1 mod 4 and to have many small primes over * which X^2 - kN splits. We compute a factor base FB of such primes then * look for values x0 such that Q0(x0) = x0^2 - kN can be decomposed over FB, * up to a possible factor dividing k and a possible "large prime". Relations * involving the latter can be combined into full relations which don't; full * relations, by Gaussian elimination over F2 for the exponent vectors 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. * * Candidates x0 are found by sieving along arithmetic progressions modulo the * small primes in FB and evaluation of candidates picks out those x0 where * many of these progressions coincide, resulting in a highly divisible Q0(x0). * * The Multi-Polynomial version improves this by choosing a modest subset of * FB primes (let A be their product) and forcing these to divide Q0(x). * Write Q(x) = Q0(2Ax + B) = (2Ax + B)^2 - kN = 4A(Ax^2 + Bx + C), where B is * suitably chosen. For each A, there are 2^omega_A possible values for B * but we'll use only half of these, since the other half is easily covered by * exploiting the symmetry x -> -x of the original Q0. The "Self-Initializating" * bit refers to the fact that switching from one B to the next is fast, whereas * switching to the next A involves some recomputation (C is never needed). * Thus we quickly run through many polynomials sharing the same A. * * The sieve ranges over values x0 such that |x0| < M (we use x = x0 + M * as array subscript). The coefficients A are chosen so that A*M ~ sqrt(kN). * Then |B| is bounded by ~ (j+4)*A, and |C| = -C ~ (M/4)*sqrt(kN), so * Q(x0)/(4A) takes values roughly between -|C| and 3|C|. * * Refinements. We do not use the smallest FB primes for sieving, incorporating * them only after selecting candidates). The substitution of 2Ax+B into * X^2 - kN, with odd B, forces 2 to occur; when kN is 1 mod 8, it occurs at * least to the 3rd power; when kN = 5 mod 8, it occurs exactly to the 2nd * power. We never sieve on 2 and always pull out the power of 2 directly. The * prime factors of k show up whenever 2Ax + B has a factor in common with k; * we don't sieve on these either but easily recognize them in a candidate. */ #include "paricfg.h" #ifdef HAS_SSE2 #include #endif #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_mpqs /** DEBUG **/ /* #define MPQS_DEBUG_VERBOSE 1 */ #include "mpqs.h" #define REL_OFFSET 20 #define REL_MASK ((1UL<digit_size_kN = D = decimal_len(h->kN); if (D > MPQS_MAX_DIGIT_SIZE_KN) return 0; P = &(mpqs_parameters[maxss(0, D - 9)]); h->tolerance = P->tolerance; h->lp_scale = P->lp_scale; /* make room for prime factors of k if any: */ h->size_of_FB = s = 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_rels = (s >= 200 ? s + 10 : (mpqs_int32_t)(s * 1.05)); 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; if (DEBUGLEVEL >= 5) { err_printf("MPQS: kN = %Ps\n", h->kN); err_printf("MPQS: kN has %ld decimal digits\n", D); err_printf("\t(estimated memory needed: %4.1fMBy)\n", (s + 1)/8388608. * h->target_rels); } return 1; } /*********************************************************************/ /** OBJECT HOUSEKEEPING **/ /*********************************************************************/ /* 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*)stack_malloc(size_FB_chunk + 64); char *iahp = (char*)stack_malloc(size_IAH_chunk + 64); long fbl, iahl; h->FB_chunk = (void *)fbp; h->invAH_chunk = (void *)iahp; /* round up to next higher 64-bytes-aligned address */ fbl = (((long)fbp) + 64) & ~0x3FL; /* and put the actual array there */ h->FB = (mpqs_FB_entry_t *)fbl; iahl = (((long)iahp) + 64) & ~0x3FL; h->inv_A_H = (mpqs_inv_A_H_t *)iahl; return (mpqs_FB_entry_t *)fbl; } /* sieve array constructor; also allocates the candidates array * 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 *) stack_calloc_align(size, sizeof(mpqs_mask)); h->sieve_array_end = h->sieve_array + size - 2; h->sieve_array_end[1] = 255; /* sentinel */ h->candidates = (long *)stack_malloc(MPQS_CANDIDATE_ARRAY_SIZE * sizeof(long)); /* 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 > MAX_PE_PAIR) size_of_FB = MAX_PE_PAIR; /* and for tracking which primes occur in the current relation: */ h->relaprimes = (long *) stack_malloc((size_of_FB << 1) * sizeof(long)); } /* allocate GENs for current polynomial and self-initialization scratch data */ static void mpqs_poly_ctor(mpqs_handle_t *h) { mpqs_int32_t i, w = h->omega_A; h->per_A_pr = (mpqs_per_A_prime_t *) stack_calloc(w * sizeof(mpqs_per_A_prime_t)); /* A is the product of w primes, each below word size. * |B| <= (w + 4) * A, so can have at most one word more * H holds residues modulo A: the same size as used for A is sufficient. */ h->A = cgeti(w + 2); h->B = cgeti(w + 3); for (i = 0; i < w; i++) h->per_A_pr[i]._H = cgeti(w + 2); } /*********************************************************************/ /** FACTOR BASE SETUP **/ /*********************************************************************/ /* fill in the best-guess multiplier k for N. We force kN = 1 mod 4. * Caller should proceed to fill in kN * See Knuth-Schroeppel function in * Robert D. Silverman * The multiple polynomial quadratic sieve * Math. Comp. 48 (1987), 329-339 * https://www.ams.org/journals/mcom/1987-48-177/S0025-5718-1987-0866119-8/ */ static ulong mpqs_find_k(mpqs_handle_t *h) { const pari_sp av = avma; const long N_mod_8 = mod8(h->N), N_mod_4 = N_mod_8 & 3; long dl = decimal_len(h->N); long D = maxss(0, minss(dl,MPQS_MAX_DIGIT_SIZE_KN)-9); long MPQS_MULTIPLIER_SEARCH_DEPTH = mpqs_parameters[D].size_of_FB; forprime_t S; struct { const mpqs_multiplier_t *_k; long np; /* number of primes in factorbase so far for this k */ double value; /* the larger, the better */ } cache[MPQS_POSSIBLE_MULTIPLIERS]; ulong MPQS_NB_MULTIPLIERS = dl < 40 ? 5 : MPQS_POSSIBLE_MULTIPLIERS; ulong p, i, nbk; for (i = nbk = 0; i < numberof(cand_multipliers); i++) { const mpqs_multiplier_t *cand_k = &cand_multipliers[i]; long k = cand_k->k; double v; if ((k & 3) != N_mod_4) continue; /* want kN = 1 (mod 4) */ v = -log((double)k)/2; if ((k & 7) == N_mod_8) v += M_LN2; /* kN = 1 (mod 8) */ cache[nbk].np = 0; cache[nbk]._k = cand_k; cache[nbk].value = v; if (++nbk == MPQS_NB_MULTIPLIERS) break; /* enough */ } /* next test is an impossible situation: kills spurious gcc-5.1 warnings * "array subscript is above array bounds" */ if (nbk > MPQS_POSSIBLE_MULTIPLIERS) nbk = MPQS_POSSIBLE_MULTIPLIERS; u_forprime_init(&S, 2, ULONG_MAX); while ( (p = u_forprime_next(&S)) ) { long kroNp = kroiu(h->N, p), seen = 0; if (!kroNp) return p; for (i = 0; i < nbk; i++) { long krokp; if (cache[i].np > MPQS_MULTIPLIER_SEARCH_DEPTH) continue; seen++; krokp = krouu(cache[i]._k->k % p, p); if (krokp == kroNp) /* kronecker(k*N, p)=1 */ { cache[i].value += 2*log((double) p)/p; cache[i].np++; } else if (krokp == 0) { cache[i].value += log((double) p)/p; cache[i].np++; } } if (!seen) break; /* we're gone through SEARCH_DEPTH primes for all k */ } if (!p) pari_err_OVERFLOW("mpqs_find_k [ran out of primes]"); { long best_i = 0; double v = cache[0].value; for (i = 1; i < nbk; i++) if (cache[i].value > v) { best_i = i; v = cache[i].value; } h->_k = cache[best_i]._k; return gc_ulong(av,0); } } /* Create a factor base of 'size' primes p_i such that legendre(k*N, p_i) != -1 * We could have shifted subscripts down from their historical arrangement, * but this seems too risky for the tiny potential gain in memory economy. * The real constraint is that the subscripts of anything which later shows * up at the Gauss stage must be nonnegative, because the exponent vectors * there use the same subscripts to refer to the same FB entries. Thus in * particular, the entry representing -1 could be put into FB[0], but could * not be moved to FB[-1] (although mpqs_FB_ctor() could be easily adapted * to support negative subscripts).-- The historically grown layout is: * FB[0] is unused. * FB[1] is not explicitly used but stands for -1. * FB[2] contains 2 (always). * Before we are called, the size_of_FB field in the handle will already have * been adjusted by _k->omega_k, so there's room for the primes dividing k, * which when present will occupy FB[3] and following. * The "real" odd FB primes begin at FB[h->index0_FB]. * FB[size_of_FB+1] is the last prime p_i. * FB[size_of_FB+2] is a sentinel to simplify some of our loops. * Thus we allocate size_of_FB+3 slots for FB. * * If a prime factor of N is found during the construction, it is returned * in f, otherwise f = 0. */ /* returns the FB array pointer for convenience */ static mpqs_FB_entry_t * mpqs_create_FB(mpqs_handle_t *h, ulong *f) { mpqs_FB_entry_t *FB = mpqs_FB_ctor(h); const pari_sp av = avma; mpqs_int32_t size = h->size_of_FB; long i; mpqs_uint32_t k = h->_k->k; forprime_t S; h->largest_FB_p = 0; /* -Wall */ 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; for (i = 3; i < h->index0_FB; i++) { /* this loop executes h->_k->omega_k = 0, 1, or 2 times */ 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 no need so far */ FB[i].fbe_flags = MPQS_FBE_CLEAR; FB[i].fbe_flogp = (float)log2((double) kp); FB[i].fbe_sqrt_kN = 0; } (void)u_forprime_init(&S, 3, ULONG_MAX); while (i < size + 2) { ulong p = u_forprime_next(&S); if (p > k || k % p) { ulong kNp = umodiu(h->kN, p); long kr = krouu(kNp, p); if (kr != -1) { if (kr == 0) { *f = p; return FB; } FB[i].fbe_p = (mpqs_uint32_t) p; FB[i].fbe_flags = MPQS_FBE_CLEAR; /* dyadic logarithm of p; single precision suffices */ FB[i].fbe_flogp = (float)log2((double)p); /* cannot yet fill in fbe_logval because the scaling multiplier * depends on the largest prime in FB, as yet unknown */ /* x such that x^2 = kN (mod p_i) */ FB[i++].fbe_sqrt_kN = (mpqs_uint32_t)Fl_sqrt(kNp, p); } } } set_avma(av); if (MPQS_DEBUGLEVEL >= 7) { err_printf("MPQS: FB [-1,2"); for (i = 3; i < h->index0_FB; i++) err_printf(",<%lu>", FB[i].fbe_p); for (; i < size + 2; i++) err_printf(",%lu", FB[i].fbe_p); err_printf("]\n"); } FB[i].fbe_p = 0; /* sentinel */ h->largest_FB_p = FB[i-1].fbe_p; /* at subscript size_of_FB + 1 */ /* locate the smallest prime that will be used for sieving */ for (i = h->index0_FB; FB[i].fbe_p != 0; i++) if (FB[i].fbe_p >= h->pmin_index1) break; h->index1_FB = i; /* with our parameters this will never fall off 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 * (artificially 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; double log_maxval, log_multiplier; long i; 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"); } if (DEBUGLEVEL >= 5) err_printf("MPQS: sieve threshold: %ld\n",h->sieve_threshold); /* Now fill in the byte-sized approximate scaled logarithms of p_i */ if (DEBUGLEVEL >= 5) err_printf("MPQS: computing logarithm approximations for p_i in FB\n"); for (i = h->index0_FB; i < h->size_of_FB + 2; i++) FB[i].fbe_logval = (unsigned char) (log_multiplier * FB[i].fbe_flogp); } /* Given the partially populated handle, find the optimum place in the FB * to pick prime factors for A from. The lowest admissible subscript is * index0_FB, but unless kN is very small, we stay away a bit from that. * The highest admissible is size_of_FB + 1, where the largest FB prime * resides. The ideal corner is about (sqrt(kN)/M) ^ (1/omega_A), * so that A will end up of size comparable to sqrt(kN)/M; experimentally * it seems desirable to stay slightly below this. Moreover, the selection * of the individual primes happens to err on the large side, for which we * compensate a bit, using the (small positive) quantity MPQS_A_FUDGE. * We rely on a few auxiliary fields in the handle to be already set by * mqps_set_sieve_threshold() before we are called. * Return 1 on success, and 0 otherwise. */ static int mpqs_locate_A_range(mpqs_handle_t *h) { /* i will be counted up to the desirable index2_FB + 1, and omega_A is never * less than 3, and we want * index2_FB - (omega_A - 1) + 1 >= index0_FB + omega_A - 3, * so: */ long i = h->index0_FB + 2*(h->omega_A) - 4; double l2_target_pA; mpqs_FB_entry_t *FB = h->FB; h->l2_target_A = (h->l2sqrtkN - h->l2M - MPQS_A_FUDGE); l2_target_pA = h->l2_target_A / h->omega_A; /* find the sweet spot, normally shouldn't take long */ while (FB[i].fbe_p && FB[i].fbe_flogp <= l2_target_pA) i++; /* check whether this hasn't walked off the top end... */ /* The following should actually NEVER happen. */ if (i > h->size_of_FB - 3) { /* this isn't going to work at all. */ pari_warn(warner, "MPQS: sizing out of tune, FB too small or\n\tway too few primes in A"); return 0; } h->index2_FB = i - 1; return 1; /* assert: index0_FB + (omega_A - 3) [the lowest FB subscript used in primes * for A] + (omega_A - 2) <= 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]. Moreover, * index2_FB indicates the last prime below the ideal size, unless (when kN * is tiny) the ideal size was too small to use. */ } /*********************************************************************/ /** SELF-INITIALIZATION **/ /*********************************************************************/ #ifdef MPQS_DEBUG /* Debug-only helper routine: check correctness of the root z mod p_i * by evaluating A * z^2 + B * z + C mod p_i (which should be 0). */ static void check_root(mpqs_handle_t *h, GEN mC, long p, long start) { pari_sp av = avma; long z = start - ((long)(h->M) % p); if (umodiu(subii(mulsi(z, addii(h->B, mulsi(z, h->A))), mC), 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", negi(mC)); err_printf("MPQS: z = %ld\n", z); pari_err_BUG("MPQS: self_init: found wrong polynomial"); } set_avma(av); } #endif /* 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; switch (*x & 0x1F) { /* 32-way computed jump handles 22 out of 32 cases */ 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: 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 cases which couldn't be finalized above */ 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; } /* self-init (1): advancing the bit pattern, and choice of primes for A. * On first call, h->bin_index = 0. 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 (use per_A_pr to find 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. * Return 1 when all is fine and 0 when we found we'd be using more bits to * the left in bin_index than we have matching primes 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; the caller, after checking that index2_FB * has not become too large, should just call us again, which then succeeds: * 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. */ 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; /* 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. We need * >= omega_A - 1 of them, and it is guaranteed by mpqs_locate_A_range() that * this many are available: the lowest FB slot used for A is never less than * index0_FB + omega_A - 3. 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 1 bits. Caller has 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 old flags */ for (i = 0; i < omega_A; i++) MPQS_FLG(i) = MPQS_FBE_CLEAR; prev_last_p_idx = MPQS_I(omega_A-1); if (room > 30) room = 30; room_mask = ~((1UL << room) - 1); /* bump bin_index to next acceptable value. If index2_moved is off, call * mpqs_increment() once; otherwise, repeat until there's something in the * least significant 2 bits - 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 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); } /* 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_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_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; /* i = 0 */ v2 = vals((long)bits); /* > 0 */ bits >>= v2; j -= 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); j++) if (FB[j].fbe_flogp > l2_last_p) break; /* The following trick avoids generating a large proportion of duplicate * relations when the last prime falls 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 gets rid of a major part of the potential * duplication. */ if (p && j == prev_last_p_idx) { j++; p = FB[j].fbe_p; } MPQS_I(omega_A - 1) = p? j: h->size_of_FB + 1; MPQS_FLG(omega_A - 1) |= MPQS_FBE_DIVIDES_A; if (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; } /* There are 4 parts to self-initialization, exercised at different times: * - choosing a new sqfree coef. A (selecting its prime factors, FB bookkeeping) * - doing the actual computations attached to a new A * - choosing a new B keeping the same A (much simpler) * - a small common bit that needs to happen in both cases. * As to the first item, the scheme works as follows: 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 log2(A) ~ l2_target_A. * 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 (for very small input), 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 the same A. (The choice of the upper "flyer" prime is * constrained by the size of the FB, which normally should never a problem. * For tiny kN, we might have to live with a nonoptimal choice.) * * Mathematically, we solve a quadratic (over F_p for each prime p in the FB * which doesn't divide A), a linear equation for each prime p | A, and * precompute differences between roots mod p so we can adjust the roots * quickly when we change B. See Thomas Sosnowski's Diplomarbeit. */ /* compute coefficients of sieving polynomial for self initializing variant. * Coefficients A and B are set (preallocated GENs) and several tables are * updated. */ static int 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, A = h->A, B = h->B; mpqs_per_A_prime_t *per_A_pr = h->per_A_pr; long i, j; #ifdef MPQS_DEBUG err_printf("MPQS DEBUG: enter self init, avma = 0x%lX\n", (ulong)avma); #endif if (++h->index_j == (mpqs_uint32_t)h->no_B) { /* all the B's have been used, choose new A; this is indicated by setting * index_j to 0 */ h->index_j = 0; h->index_i++; /* count finished A's */ } if (h->index_j == 0) { /* compute first polynomial with new A */ GEN a, b, A2; if (!mpqs_si_choose_primes(h)) { /* Ran out of room towards small primes, and index2_FB was raised. */ if (size_of_FB - h->index2_FB < 4) return 0; /* Fail */ (void)mpqs_si_choose_primes(h); /* now guaranteed to succeed */ } /* bin_index and per_A_pr now populated with consistent values */ /* compute A = product of omega_A primes given by bin_index */ a = b = NULL; for (i = 0; i < h->omega_A; i++) { ulong p = MPQS_AP(i); a = a? muliu(a, p): utoipos(p); } affii(a, A); /* 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. */ for (i = 0; i < h->omega_A; i++) { ulong p = MPQS_AP(i); GEN t = divis(A, (long)p); t = remii(mulii(t, muluu(Fl_inv(umodiu(t, p), p), MPQS_SQRT(i))), A); affii(t, MPQS_H(i)); b = b? addii(b, t): t; } affii(b, B); set_avma(av); /* ensure B = 1 mod 4 */ if (mod2(B) == 0) affii(addii(B, mului(mod4(A), A)), B); /* B += (A % 4) * A; */ A2 = 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 does The Right Thing for 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 s, mb, t, m, p, iA2, iA; if (FB[j].fbe_flags & MPQS_FBE_DIVIDES_A) continue; p = (ulong)FB[j].fbe_p; m = h->M % p; iA2 = Fl_inv(umodiu(A2, p), p); /* = 1/(2*A) mod p_j */ iA = iA2 << 1; if (iA > p) iA -= p; mb = umodiu(B, p); if (mb) mb = p - mb; /* mb = -B mod p */ s = FB[j].fbe_sqrt_kN; t = Fl_add(m, Fl_mul(Fl_sub(mb, s, p), iA2, p), p); FB[j].fbe_start1 = (mpqs_int32_t)t; FB[j].fbe_start2 = (mpqs_int32_t)Fl_add(t, Fl_mul(s, iA, p), p); for (i = 0; i < h->omega_A - 1; i++) { ulong h = umodiu(MPQS_H(i), p); MPQS_INV_A_H(i,j) = Fl_mul(h, iA, p); /* 1/A * H[i] mod p_j */ } } } else { /* 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 p, v2 = vals(h->index_j); /* new starting positions for sieving */ j = h->index_j >> v2; 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); } /* p=2 is a special case. start1[2], start2[2] are never looked at, * so don't bother setting them. */ /* compute zeros of polynomials that have only one zero mod p since p | A */ p1 = diviiexact(subii(h->kN, sqri(B)), shifti(A, 2)); /* coefficient -C */ for (i = 0; i < h->omega_A; i++) { ulong p = MPQS_AP(i), s = h->M + Fl_div(umodiu(p1, p), umodiu(B, p), p); FB[MPQS_I(i)].fbe_start1 = FB[MPQS_I(i)].fbe_start2 = (mpqs_int32_t)(s % p); } #ifdef MPQS_DEBUG for (j = 3; j <= size_of_FB; j++) { check_root(h, p1, FB[j].fbe_p, FB[j].fbe_start1); check_root(h, p1, FB[j].fbe_p, FB[j].fbe_start2); } #endif if (MPQS_DEBUGLEVEL >= 6) 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_shallow(h->B)); set_avma(av); #ifdef MPQS_DEBUG err_printf("MPQS DEBUG: leave self init, avma = 0x%lX\n", (ulong)avma); #endif return 1; } /*********************************************************************/ /** THE SIEVE **/ /*********************************************************************/ /* p4 = 4*p, logp ~ log(p), B/E point to the beginning/end of a sieve array */ INLINE void mpqs_sieve_p(unsigned char *B, unsigned char *E, long p4, long p, unsigned char logp) { unsigned char *e = E - p4; /* Unrolled loop. 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 */ while (e - B >= 0) /* signed comparison */ { (*B) += logp, B += p; (*B) += logp, B += p; (*B) += logp, B += p; (*B) += logp, B += p; } while (E - B >= 0) (*B) += logp, B += p; } INLINE void mpqs_sieve_p1(unsigned char *B, unsigned char *E, long s1, long s2, unsigned char logp) { while (E - B >= 0) { (*B) += logp, B += s1; if (E - B < 0) break; (*B) += logp, B += s2; } } INLINE void mpqs_sieve_p2(unsigned char *B, unsigned char *E, long p4, long s1, long s2, unsigned char logp) { unsigned char *e = E - p4; /* Unrolled loop. 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 */ while (e - B >= 0) /* signed comparison */ { (*B) += logp, B += s1; (*B) += logp, B += s2; (*B) += logp, B += s1; (*B) += logp, B += s2; (*B) += logp, B += s1; (*B) += logp, B += s2; (*B) += logp, B += s1; (*B) += logp, B += s2; } while (E - B >= 0) {(*B) += logp, B += s1; if (E - B < 0) break; (*B) += logp, B += s2;} } static void mpqs_sieve(mpqs_handle_t *h) { long p, l = h->index1_FB; mpqs_FB_entry_t *FB = &(h->FB[l]); unsigned char *S = h->sieve_array, *Send = h->sieve_array_end; long size = h->M << 1, size4 = size >> 3; memset((void*)S, 0, size * sizeof(unsigned char)); for ( ; (p = FB->fbe_p) && p <= size4; FB++) /* l++ */ { unsigned char logp = FB->fbe_logval; long s1 = FB->fbe_start1, s2 = FB->fbe_start2; /* sieve with FB[l] from start1[l], and from start2[l] if s1 != s2 */ if (s1 == s2) mpqs_sieve_p(S + s1, Send, p << 2, p, logp); else { if (s1>s2) lswap(s1,s2) mpqs_sieve_p2(S + s1, Send, p << 2, s2-s1,p+s1-s2, logp); } } for ( ; (p = FB->fbe_p) && p <= size; FB++) /* l++ */ { unsigned char logp = FB->fbe_logval; long s1 = FB->fbe_start1, s2 = FB->fbe_start2; /* sieve with FB[l] from start1[l], and from start2[l] if s1 != s2 */ if (s1 == s2) mpqs_sieve_p(S + s1, Send, p << 2, p, logp); else { if (s1>s2) lswap(s1,s2) mpqs_sieve_p1(S + s1, Send, s2-s1, p+s1-s2, logp); } } for ( ; (p = FB->fbe_p); FB++) { unsigned char logp = FB->fbe_logval; long s1 = FB->fbe_start1, s2 = FB->fbe_start2; if (s1 < size) S[s1] += logp; if (s2!=s1 && s2 < size) S[s2] += logp; } } /* Could use the fact that 4 | M, but let the compiler worry about unrolling. */ static long mpqs_eval_sieve(mpqs_handle_t *h) { long x = 0, count = 0, M2 = h->M << 1; unsigned char t = h->sieve_threshold; unsigned char *S = h->sieve_array; mpqs_bit_array * U = (mpqs_bit_array *) S; long *cand = h->candidates; const long sizemask = sizeof(mpqs_mask); /* Exploiting the sentinel, we don't need to check for x < M2 in the inner * while loop; more than makes up for the lack of explicit unrolling. */ while (count < MPQS_CANDIDATE_ARRAY_SIZE - 1) { long j, y; while (!TEST(U[x]&mpqs_mask)) x++; y = x*sizemask; for (j=0; j= M2) { cand[count] = 0; return count; } if (S[y]>=t) cand[count++] = y; } x++; } cand[count] = 0; return count; } /*********************************************************************/ /** CONSTRUCTING RELATIONS **/ /*********************************************************************/ /* only used for debugging */ static void split_relp(GEN rel, GEN *prelp, GEN *prelc) { long j, l = lg(rel); GEN relp, relc; *prelp = relp = cgetg(l, t_VECSMALL); *prelc = relc = cgetg(l, t_VECSMALL); for (j=1; j> REL_OFFSET; relp[j] = rel[j] & REL_MASK; } } #ifdef MPQS_DEBUG static GEN mpqs_factorback(mpqs_handle_t *h, GEN relp) { GEN N = h->N, Q = gen_1; long j, l = lg(relp); for (j = 1; j < l; j++) { long e = relp[j] >> REL_OFFSET, i = relp[j] & REL_MASK; if (i == 1) Q = Fp_neg(Q,N); /* special case -1 */ else Q = Fp_mul(Q, Fp_powu(utoipos(h->FB[i].fbe_p), e, N), N); } return Q; } static void mpqs_check_rel(mpqs_handle_t *h, GEN c) { pari_sp av = avma; int LP = (lg(c) == 4); GEN rhs = mpqs_factorback(h, rel_p(c)); GEN Y = rel_Y(c), Qx_2 = remii(sqri(Y), h->N); if (LP) rhs = modii(mulii(rhs, rel_q(c)), h->N); if (!equalii(Qx_2, rhs)) { GEN relpp, relpc; split_relp(rel_p(c), &relpp, &relpc); err_printf("MPQS: %Ps : %Ps %Ps\n", Y, relpp,relpc); err_printf("\tQx_2 = %Ps\n", Qx_2); err_printf("\t rhs = %Ps\n", rhs); pari_err_BUG(LP? "MPQS: wrong large prime relation found" : "MPQS: wrong full relation found"); } PRINT_IF_VERBOSE(LP? "\b(;)": "\b(:)"); set_avma(av); } #endif static void rel_to_ei(GEN ei, GEN relp) { long j, l = lg(relp); for (j=1; j> REL_OFFSET, i = relp[j] & REL_MASK; ei[i] += e; } } static void mpqs_add_factor(GEN relp, long *i, ulong ei, ulong pi) { relp[++*i] = pi | (ei << REL_OFFSET); } static int zv_is_even(GEN V) { long i, l = lg(V); for (i=1; isize_of_FB + 1, nb = 0; GEN ei, relp, iq, q = rel_q(rel1); if (!invmod(q, h->N, &iq)) return equalii(iq, h->N)? NULL: iq; /* rare */ ei = zero_zv(lei); rel_to_ei(ei, rel_p(rel1)); rel_to_ei(ei, rel_p(rel2)); if (zv_is_even(ei)) return NULL; new_Y = modii(mulii(mulii(Y1, Y2), iq), h->N); new_Y1 = subii(h->N, new_Y); if (abscmpii(new_Y1, new_Y) < 0) new_Y = new_Y1; relp = cgetg(MAX_PE_PAIR+1,t_VECSMALL); if (odd(ei[1])) mpqs_add_factor(relp, &nb, 1, 1); for (l = 2; l <= lei; l++) if (ei[l]) mpqs_add_factor(relp, &nb, ei[l],l); setlg(relp, nb+1); if (DEBUGLEVEL >= 6) { GEN relpp, relpc, rel1p, rel1c, rel2p, rel2c; split_relp(relp,&relpp,&relpc); split_relp(rel1,&rel1p,&rel1c); split_relp(rel2,&rel2p,&rel2c); err_printf("MPQS: combining\n"); err_printf(" {%Ps @ %Ps : %Ps}\n", q, Y1, rel1p, rel1c); err_printf(" * {%Ps @ %Ps : %Ps}\n", q, Y2, rel2p, rel2c); err_printf(" == {%Ps, %Ps}\n", relpp, relpc); } #ifdef MPQS_DEBUG { pari_sp av1 = avma; if (!equalii(modii(sqri(new_Y), h->N), mpqs_factorback(h, relp))) pari_err_BUG("MPQS: combined large prime relation is false"); set_avma(av1); } #endif return mkvec2(new_Y, relp); } /* nc candidates */ static GEN mpqs_eval_cand(mpqs_handle_t *h, long nc, hashtable *frel, hashtable *lprel) { mpqs_FB_entry_t *FB = h->FB; GEN A = h->A, B = h->B; long *relaprimes = h->relaprimes, *candidates = h->candidates; long pi, i; int pii; mpqs_per_A_prime_t *per_A_pr = h->per_A_pr; for (i = 0; i < nc; i++) { pari_sp btop = avma; GEN Qx, Qx_part, Y, relp = cgetg(MAX_PE_PAIR+1,t_VECSMALL); long powers_of_2, p, x = candidates[i], nb = 0; int relaprpos = 0; long k; unsigned char thr = h->sieve_array[x]; /* Y = 2*A*x + B, Qx = Y^2/(4*A) = Q(x) */ Y = addii(mulis(A, 2 * (x - h->M)), B); Qx = subii(sqri(Y), h->kN); /* != 0 since N not a square and (N,k) = 1 */ if (signe(Qx) < 0) { setabssign(Qx); mpqs_add_factor(relp, &nb, 1, 1); /* i = 1, ei = 1, pi */ } /* Qx > 0, 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 = 1 mod 4 */ powers_of_2 = vali(Qx); Qx = shifti(Qx, -powers_of_2); mpqs_add_factor(relp, &nb, powers_of_2, 2); /* i = 1, ei = 1, pi */ /* When N is small, it may happen that N | Qx outright. In any case, when * no extensive prior trial division / Rho / ECM was attempted, gcd(Qx,N) * may turn out to be a nontrivial factor of N (not in FB 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. */ /* Pass 1 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 Pass 2. Pass 1 recognizes divisors of A by their corresponding flags * bit in the FB entry. (Divisors of k are ignored at this stage.) * We construct a preliminary table of FB subscripts and "exponents" of FB * primes which divide Qx. (We store subscripts, not the primes themselves.) * We distinguish three cases: * 0) prime in A which does not divide Qx/A, * 1) prime not in A which divides Qx/A, * 2) prime in A which divides Qx/A. * Cases 1 and 2 need checking for repeated factors, kind 0 doesn't. * Cases 0 and 1 contribute 1 to the exponent in the relation, case 2 * contributes 2. * Factors in common with k are simpler: if they occur, they occur * exactly to the first power, and this makes no difference in Pass 1, * so they behave just like every normal odd FB prime. */ for (Qx_part = A, pi = 3; pi< h->index1_FB; pi++) { ulong p = FB[pi].fbe_p; long xp = x % p; /* Here we used that MPQS_FBE_DIVIDES_A = 1. */ if (xp == FB[pi].fbe_start1 || xp == FB[pi].fbe_start2) { /* p divides Q(x)/A and possibly A, case 2 or 3 */ ulong ei = FB[pi].fbe_flags & MPQS_FBE_DIVIDES_A; relaprimes[relaprpos++] = pi; relaprimes[relaprpos++] = 1 + ei; Qx_part = muliu(Qx_part, p); } } for ( ; thr && (p = FB[pi].fbe_p); pi++) { long xp = x % p; /* Here we used that MPQS_FBE_DIVIDES_A = 1. */ if (xp == FB[pi].fbe_start1 || xp == FB[pi].fbe_start2) { /* p divides Q(x)/A and possibly A, case 2 or 3 */ ulong ei = FB[pi].fbe_flags & MPQS_FBE_DIVIDES_A; relaprimes[relaprpos++] = pi; relaprimes[relaprpos++] = 1 + ei; Qx_part = muliu(Qx_part, p); thr -= FB[pi].fbe_logval; } } for (k = 0; k< h->omega_A; k++) { long pi = MPQS_I(k); ulong p = FB[pi].fbe_p; long xp = x % p; if (!(xp == FB[pi].fbe_start1 || xp == FB[pi].fbe_start2)) { /* p divides A but does not divide Q(x)/A, case 1 */ relaprimes[relaprpos++] = pi; relaprimes[relaprpos++] = 0; } } /* We have 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); #ifdef MPQS_DEBUG err_printf("MPQS DEBUG: eval loop 3, avma = 0x%lX\n", (ulong)avma); #endif /* Pass 2: deal with repeated factors and store 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. */ PRINT_IF_VERBOSE("a"); for (pii = 0; pii < relaprpos; pii += 2) { ulong r, ei = relaprimes[pii+1]; GEN q; pi = relaprimes[pii]; /* p | k (identified by its index before index0_FB)* or p | A (ei = 0) */ if ((mpqs_int32_t)pi < h->index0_FB || ei == 0) { mpqs_add_factor(relp, &nb, 1, pi); continue; } p = FB[pi].fbe_p; /* p might still divide the current adjusted Qx. Try it. */ switch(cmpiu(Qx, p)) { case 0: ei++; Qx = gen_1; break; case 1: q = absdiviu_rem(Qx, p, &r); while (r == 0) { ei++; Qx = q; q = absdiviu_rem(Qx, p, &r); } break; } mpqs_add_factor(relp, &nb, ei, pi); } #ifdef MPQS_DEBUG err_printf("MPQS DEBUG: eval loop 4, avma = 0x%lX\n", (ulong)avma); #endif PRINT_IF_VERBOSE("\bb"); setlg(relp, nb+1); if (is_pm1(Qx)) { GEN rel = gerepilecopy(btop, mkvec2(absi_shallow(Y), relp)); #ifdef MPQS_DEBUG mpqs_check_rel(h, rel); #endif frel_add(frel, rel); } else if (cmpiu(Qx, h->lp_bound) <= 0) { ulong q = itou(Qx); GEN rel = mkvec3(absi_shallow(Y),relp,Qx); GEN col = hash_haskey_GEN(lprel, (void*)q); #ifdef MPQS_DEBUG mpqs_check_rel(h, rel); #endif if (!col) /* relation up to large prime */ hash_insert(lprel, (void*)q, (void*)gerepilecopy(btop,rel)); else if ((rel = combine_large_primes(h, rel, col))) { if (typ(rel) == t_INT) return rel; /* very unlikely */ #ifdef MPQS_DEBUG mpqs_check_rel(h, rel); #endif frel_add(frel, gerepilecopy(btop,rel)); } else set_avma(btop); } else { /* TODO: check for double large prime */ PRINT_IF_VERBOSE("\b."); set_avma(btop); } } PRINT_IF_VERBOSE("\n"); return NULL; } /*********************************************************************/ /** FROM RELATIONS TO DIVISORS **/ /*********************************************************************/ /* create an F2m from a relations list */ static GEN rels_to_F2Ms(GEN rel) { long i, cols = lg(rel)-1; GEN m = cgetg(cols+1, t_VEC); for (i = 1; i <= cols; i++) { GEN relp = gmael(rel,i,2), rel2; long j, l = lg(relp), o = 0, k; for (j = 1; j < l; j++) if (odd(relp[j] >> REL_OFFSET)) o++; rel2 = cgetg(o+1, t_VECSMALL); for (j = 1, k = 1; j < l; j++) if (odd(relp[j] >> REL_OFFSET)) rel2[k++] = relp[j] & REL_MASK; gel(m, i) = rel2; } return m; } static int split(GEN *D, long *e) { ulong mask; long flag; if (MR_Jaeschke(*D)) { *e = 1; return 1; } /* probable prime */ if (Z_issquareall(*D, D)) { /* squares could cost us a lot of time */ if (DEBUGLEVEL >= 5) err_printf("MPQS: decomposed a square\n"); *e = 2; 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(*D, D, &mask))) { if (DEBUGLEVEL >= 5) err_printf("MPQS: decomposed a %s power\n", uordinal(flag)); *e = flag; return 1; } *e = 0; return 0; /* known composite */ } /* return a GEN structure containing NULL but safe for gerepileupto */ static GEN mpqs_solve_linear_system(mpqs_handle_t *h, hashtable *frel) { mpqs_FB_entry_t *FB = h->FB; pari_sp av = avma; GEN rels = hash_keys_GEN(frel), N = h->N, r, c, res, ei, M, Ker; long i, j, nrows, rlast, rnext, rmax, rank; M = rels_to_F2Ms(rels); Ker = F2Ms_ker(M, h->size_of_FB+1); rank = lg(Ker)-1; if (DEBUGLEVEL >= 4) { if (DEBUGLEVEL >= 7) err_printf("\\\\ MPQS RELATION MATRIX\nFREL=%Ps\nKERNEL=%Ps\n",M, Ker); err_printf("MPQS: Gauss done: kernel has rank %ld, taking gcds...\n", rank); } if (!rank) { /* trivial kernel; main loop may look for more relations */ if (DEBUGLEVEL >= 3) pari_warn(warner, "MPQS: no solutions found from linear system solver"); return gc_NULL(av); /* no factors found */ } /* Expect up to 2^rank pairwise coprime factors, but a kernel basis vector * may not contribute to the decomposition; r stores the factors and c what * we know about them (0: composite, 1: probably prime, >= 2: proper power) */ ei = cgetg(h->size_of_FB + 2, t_VECSMALL); rmax = logint(N, utoi(3)); if (rank <= BITS_IN_LONG-2) rmax = minss(rmax, 1L<size_of_FB + 1) * sizeof(long)); for (j = 1; j <= nrows; j++) if (F2m_coeff(Ker, j, i)) { GEN R = gel(rels,j); Y_prod = gerepileuptoint(av2, remii(mulii(Y_prod, gel(R,1)), N)); rel_to_ei(ei, gel(R,2)); } av3 = avma; for (j = 2; j <= h->size_of_FB + 1; j++) if (ei[j]) { GEN q = utoipos(FB[j].fbe_p); if (ei[j] & 1) pari_err_BUG("MPQS (relation is a nonsquare)"); X = remii(mulii(X, Fp_powu(q, (ulong)ei[j]>>1, N)), N); X = gerepileuptoint(av3, X); } if (MPQS_DEBUGLEVEL >= 1 && !dvdii(subii(sqri(X), sqri(Y_prod)), N)) { 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, gcd(X-Y, N) * gcd(X+Y, N) = N: * 1) N | X^2 - Y^2, so it divides the LHS; * 2) let P be any prime factor of N. If P | X-Y and P | X+Y, then P | 2X * But X is a product of powers of FB primes => coprime to N. * Hence we work with gcd(X+Y, N) alone. */ X_plus_Y = addii(X, Y_prod); if (rnext == 1) { /* we still haven't decomposed, and want both a gcd and its cofactor. */ D = gcdii(X_plus_Y, N); if (is_pm1(D) || equalii(D,N)) { set_avma(av2); continue; } /* got something that works */ if (DEBUGLEVEL >= 5) err_printf("MPQS: splitting N after %ld kernel vector%s\n", i+1, (i? "s" : "")); gel(r,1) = diviiexact(N, D); gel(r,2) = D; rlast = rnext = 3; if (split(&gel(r,1), &c[1])) done++; if (split(&gel(r,2), &c[2])) done++; if (done == 2 || rmax == 2) break; if (DEBUGLEVEL >= 5) err_printf("MPQS: got two factors, looking for more...\n"); } else { /* we already have factors */ for (j = 1; j < rnext; j++) { /* loop over known-composite factors */ /* skip probable primes and also roots of pure powers: they are a lot * smaller than N and should be easy to deal with later */ if (c[j]) { done++; continue; } av3 = avma; D = gcdii(X_plus_Y, gel(r,j)); if (is_pm1(D) || equalii(D, gel(r,j))) { set_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); gel(r,j) = diviiexact(gel(r,j), D); gel(r,rnext) = D; if (split(&gel(r,j), &c[j])) done++; /* Don't increment done: happens later when we revisit c[rnext] during * the present inner loop. */ (void)split(&gel(r,rnext), &c[rnext]); if (++rnext > rmax) break; /* all possible factors seen */ } /* loop over known composite factors */ if (rnext > rlast) { if (DEBUGLEVEL >= 5) err_printf("MPQS: got %ld factors%s\n", rlast - 1, (done < rlast ? ", looking for more..." : "")); rlast = rnext; } /* break out if we have rmax factors or all current factors are probable * primes or tiny roots from pure powers */ if (rnext > rmax || done == rnext - 1) break; } } if (rnext == 1) return gc_NULL(av); /* no factors found */ /* normal case: convert to ifac format as described in ifactor1.c (value, * exponent, class [unknown, known composite, known prime]) */ rlast = rnext - 1; /* # of distinct factors found */ res = cgetg(3*rlast + 1, t_VEC); if (DEBUGLEVEL >= 6) err_printf("MPQS: wrapping up %ld factors\n", rlast); for (i = j = 1; i <= rlast; i++, j += 3) { long C = c[i]; icopyifstack(gel(r,i), gel(res,j)); /* factor */ gel(res,j+1) = C <= 1? gen_1: utoipos(C); /* exponent */ gel(res,j+2) = C ? NULL: gen_0; /* unknown or known composite */ if (DEBUGLEVEL >= 6) err_printf("\tpackaging %ld: %Ps ^%ld (%s)\n", i, gel(r,i), itos(gel(res,j+1)), (C? "unknown": "composite")); } return res; } /*********************************************************************/ /** MAIN ENTRY POINT AND DRIVER ROUTINE **/ /*********************************************************************/ static void toolarge() { pari_warn(warner, "MPQS: number too big to be factored with MPQS,\n\tgiving up"); } /* 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 we can't seem to make any headway. */ GEN mpqs(GEN N) { const long size_N = decimal_len(N); mpqs_handle_t H; GEN fact; /* will in the end hold our factor(s) */ mpqs_FB_entry_t *FB; /* factor base */ double dbg_target, DEFEAT; ulong p; pari_timer T; hashtable lprel, frel; pari_sp av = avma; if (DEBUGLEVEL >= 4) err_printf("MPQS: number to factor N = %Ps\n", N); if (size_N > MPQS_MAX_DIGIT_SIZE_KN) { toolarge(); return NULL; } if (DEBUGLEVEL >= 4) { timer_start(&T); err_printf("MPQS: factoring number of %ld decimal digits\n", size_N); } H.N = N; H.bin_index = 0; H.index_i = 0; H.index_j = 0; H.index2_moved = 0; p = mpqs_find_k(&H); if (p) return gc_utoipos(av,p); if (DEBUGLEVEL >= 5) err_printf("MPQS: found multiplier %ld for N\n", H._k->k); H.kN = muliu(N, H._k->k); if (!mpqs_set_parameters(&H)) { toolarge(); return NULL; } if (DEBUGLEVEL >= 5) err_printf("MPQS: creating factor base and allocating arrays...\n"); FB = mpqs_create_FB(&H, &p); if (p) return gc_utoipos(av, p); mpqs_sieve_array_ctor(&H); mpqs_poly_ctor(&H); H.lp_bound = minss(H.largest_FB_p, MPQS_LP_BOUND); /* don't allow large primes to have room for two factors both bigger than * what the FB contains (...yet!) */ H.lp_bound *= minss(H.lp_scale, H.largest_FB_p - 1); H.dkN = gtodouble(H.kN); /* compute the threshold and fill in the byte-sized scaled logarithms */ mpqs_set_sieve_threshold(&H); if (!mpqs_locate_A_range(&H)) return NULL; if (DEBUGLEVEL >= 4) { err_printf("MPQS: sieving interval = [%ld, %ld]\n", -(long)H.M, (long)H.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)H.size_of_FB); err_printf("MPQS: striving for %ld relations\n", (long)H.target_rels); err_printf("MPQS: coefficients A will be built from %ld primes each\n", (long)H.omega_A); err_printf("MPQS: primes for A to be chosen near FB[%ld] = %ld\n", (long)H.index2_FB, (long)FB[H.index2_FB].fbe_p); err_printf("MPQS: smallest prime used for sieving FB[%ld] = %ld\n", (long)H.index1_FB, (long)FB[H.index1_FB].fbe_p); err_printf("MPQS: largest prime in FB = %ld\n", (long)H.largest_FB_p); err_printf("MPQS: bound for `large primes' = %ld\n", (long)H.lp_bound); if (DEBUGLEVEL >= 5) err_printf("MPQS: sieve threshold = %u\n", (unsigned int)H.sieve_threshold); err_printf("MPQS: computing relations:"); } /* 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 */ H.index_j = (mpqs_uint32_t)-1; /* increment below will have it start at 0 */ dbg_target = H.target_rels / 100.; DEFEAT = H.target_rels * 1.5; hash_init_GEN(&frel, H.target_rels, gequal, 1); hash_init_ulong(&lprel,H.target_rels, 1); for(;;) { long tc; /* self initialization: compute polynomial and its zeros */ if (!mpqs_self_init(&H)) { /* have run out of primes for A; give up */ if (DEBUGLEVEL >= 2) err_printf("MPQS: Ran out of primes for A, giving up.\n"); return gc_NULL(av); } mpqs_sieve(&H); tc = mpqs_eval_sieve(&H); if (DEBUGLEVEL >= 6) err_printf("MPQS: found %lu candidate%s\n", tc, (tc==1? "" : "s")); if (tc) { fact = mpqs_eval_cand(&H, tc, &frel, &lprel); 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); } return gerepileupto(av, fact); } } if (DEBUGLEVEL >= 4 && frel.nb > dbg_target) { err_printf(" %ld%%", 100*frel.nb/ H.target_rels); if (DEBUGLEVEL >= 5) err_printf(" (%ld ms)", timer_delay(&T)); dbg_target += H.target_rels / 100.; } if (frel.nb < (ulong)H.target_rels) continue; /* main loop */ if (DEBUGLEVEL >= 4) { timer_start(&T); err_printf("\nMPQS: starting Gauss over F_2 on %ld distinct relations\n", frel.nb); } fact = mpqs_solve_linear_system(&H, &frel); 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; err_printf("MPQS: found %ld factors =\n", nf); for (j = 1; j <= nf; j++) err_printf("\t%Ps%s\n", gel(fact,3*j-2), (j < nf)? ",": ""); } } return gerepileupto(av, fact); } if (DEBUGLEVEL >= 4) { err_printf("\nMPQS: time in Gauss and gcds = %ld ms\n",timer_delay(&T)); err_printf("MPQS: no factors found.\n"); if (frel.nb < DEFEAT) err_printf("\nMPQS: restarting sieving ...\n"); else err_printf("\nMPQS: giving up.\n"); } if (frel.nb >= DEFEAT) return gc_NULL(av); H.target_rels += 10; } } pari-2.17.2/src/modules/algebras.c0000644000175000017500000045370314760305107015366 0ustar billbill/* Copyright (C) 2000 The PARI group. This file is part of the PARI/GP package. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "pari.h" #include "paripriv.h" #define DEBUGLEVEL DEBUGLEVEL_alg #define dbg_printf(lvl) if (DEBUGLEVEL >= (lvl) + 3) err_printf /********************************************************************/ /** **/ /** ASSOCIATIVE ALGEBRAS, CENTRAL SIMPLE ALGEBRAS **/ /** contributed by Aurel Page (2014) **/ /** **/ /********************************************************************/ static GEN alg_subalg(GEN al, GEN basis); static GEN alg_maximal_primes(GEN al, GEN P); static GEN algnatmultable(GEN al, long D); static GEN _tablemul_ej(GEN mt, GEN x, long j); static GEN _tablemul_ej_Fp(GEN mt, GEN x, long j, GEN p); static GEN _tablemul_ej_Fl(GEN mt, GEN x, long j, ulong p); static ulong algtracei(GEN mt, ulong p, ulong expo, ulong modu); static GEN alg_pmaximal(GEN al, GEN p); static GEN alg_maximal(GEN al); static GEN algtracematrix(GEN al); static GEN algtableinit_i(GEN mt0, GEN p); static GEN algbasisrightmultable(GEN al, GEN x); static GEN algabstrace(GEN al, GEN x); static GEN algbasismul(GEN al, GEN x, GEN y); static GEN algbasismultable(GEN al, GEN x); static GEN algbasismultable_Flm(GEN mt, GEN x, ulong m); static GEN algfromcenter(GEN al, GEN x); static void H_compo(GEN x, GEN* a, GEN* b, GEN* c, GEN* d); static GEN H_add(GEN x, GEN y); static GEN H_charpoly(GEN x, long v, long abs); static GEN H_divl_i(GEN x, GEN y); static GEN H_inv(GEN x); static GEN H_mul(GEN x, GEN y); static GEN H_neg(GEN x); static GEN H_norm(GEN x, long abs); static GEN H_random(GEN b); static GEN H_sqr(GEN x); static GEN H_tomatrix(GEN x, long abs); static GEN H_trace(GEN x, long abs); static GEN mk_C(); static int checkalg_i(GEN al) { GEN mt, rnf; long t; if (typ(al) != t_VEC || lg(al) != 12) return 0; mt = alg_get_multable(al); if (typ(mt) != t_VEC || lg(mt) == 1 || typ(gel(mt,1)) != t_MAT) return 0; rnf = alg_get_splittingfield(al); if (isintzero(rnf) || !gequal0(alg_get_char(al))) return 1; if (typ(gel(al,2)) != t_VEC || lg(gel(al,2)) == 1) return 0; /* not checkrnf_i: beware placeholder from alg_csa_table */ t = typ(rnf); return t==t_COMPLEX || t==t_REAL || (t==t_VEC && lg(rnf)==13); } void checkalg(GEN al) { if (al && !checkalg_i(al)) pari_err_TYPE("checkalg [please apply alginit()]",al); } static int checklat_i(GEN al, GEN lat) { long N,i,j; GEN m,t,c; if (typ(lat)!=t_VEC || lg(lat) != 3) return 0; t = gel(lat,2); if (typ(t) != t_INT && typ(t) != t_FRAC) return 0; if (gsigne(t)<=0) return 0; m = gel(lat,1); if (typ(m) != t_MAT) return 0; N = alg_get_absdim(al); if (lg(m)-1 != N || lg(gel(m,1))-1 != N) return 0; for (i=1; i<=N; i++) for (j=1; j<=N; j++) { c = gcoeff(m,i,j); if (typ(c) != t_INT) return 0; if (j 0) { if (v[i] == b) v[i--] = -b; else { v[i]++; break; } } if (i==0) break; y1 = y0; for (i = 1; i <= n; i++) y1 = nfadd(nf, y1, ZC_z_mul(gel(red,i), v[i])); if (!nfchecksigns(nf, y1, pl)) continue; ny = absi_shallow(nfnorm(nf, y1)); if (!signe(ny)) continue; ny = diviiexact(ny, gcdii(ny, N)); if (!Z_easyfactor(ny, lim)) continue; y2 = idealdivexact(nf, y1, idealadd(nf,y1,I)); *fa = idealfactor(nf, y2); if (!data || test(data,*fa)) return y1; } } } /* if data == NULL, the test is skipped */ /* in the test, the factorization does not contain the known factors */ static GEN factoredextchinesetest(GEN nf, GEN x, GEN y, GEN pl, GEN* fa, GEN data, int (*test)(GEN,GEN)) { pari_sp av = avma; long n,i; GEN x1, y0, y1, red, N, I, P = gel(x,1), E = gel(x,2); n = nf_get_degree(nf); x = idealchineseinit(nf, mkvec2(x,pl)); x1 = gel(x,1); red = lg(x1) == 1? matid(n): gmael(x1,1,1); y0 = idealchinese(nf, x, y); E = shallowcopy(E); if (!gequal0(y0)) for (i=1; i1, or i=0 if n=1 3- b in nf 4- infinite hasse invariants (mod n) : VECSMALL of size r1, values only 0 or n/2 (if integral) 5- finite hasse invariants (mod n) : VEC[VEC of primes, VECSMALL of hasse inv mod n] 6- nf of the splitting field (absolute) 7* dn^2*dn^2 matrix expressing the integral basis in terms of the natural basis 8* dn^2*dn^2 matrix expressing the natural basis in terms of the integral basis 9* VEC of dn^2 matrices giving the dn^2*dn^2 left multiplication tables of the integral basis 10* characteristic of the base field (used only for algebras given by a multiplication table) 11* trace of basis elements If al is given by a multiplication table (al_TABLE), only the * fields are present. */ /* assumes same center and same variable */ /* currently only works for coprime degrees */ GEN algtensor(GEN al1, GEN al2, long flag) { pari_sp av = avma; long v, k, d1, d2; GEN nf, P1, P2, aut1, aut2, b1, b2, C, rnf, aut, b, x1, x2, al, rnfpol; checkalg(al1); checkalg(al2); if (alg_type(al1) != al_CYCLIC || alg_type(al2) != al_CYCLIC) pari_err_IMPL("tensor of noncyclic algebras"); /* TODO: do it. */ nf = alg_get_center(al1); if (!gequal(alg_get_center(al2),nf)) pari_err_OP("tensor product [not the same center]", al1, al2); P1=alg_get_splitpol(al1); aut1=alg_get_aut(al1); b1=alg_get_b(al1); P2=alg_get_splitpol(al2); aut2=alg_get_aut(al2); b2=alg_get_b(al2); v=varn(P1); d1=alg_get_degree(al1); d2=alg_get_degree(al2); if (ugcd(d1,d2) != 1) pari_err_IMPL("tensor of cyclic algebras of noncoprime degrees"); /* TODO */ if (d1==1) return gcopy(al2); if (d2==1) return gcopy(al1); C = nfcompositum(nf, P1, P2, 3); rnfpol = gel(C,1); if (!(flag & al_FACTOR)) rnfpol = mkvec2(rnfpol, stoi(1<<20)); rnf = rnfinit(nf, rnfpol); /* TODO use integral basis of P1 and P2 to get that of C */ x1 = gel(C,2); x2 = gel(C,3); k = itos(gel(C,4)); aut = gadd(gsubst(aut2,v,x2),gmulsg(k,gsubst(aut1,v,x1))); b = nfmul(nf,nfpow_u(nf,b1,d2),nfpow_u(nf,b2,d1)); al = alg_cyclic(rnf, aut, b, flag); return gerepilecopy(av,al); } /* M an n x d Flm of rank d, n >= d. Initialize Mx = y solver */ static GEN Flm_invimage_init(GEN M, ulong p) { GEN v = Flm_indexrank(M, p), perm = gel(v,1); GEN MM = rowpermute(M, perm); /* square invertible */ return mkvec2(Flm_inv(MM,p), perm); } /* assume Mx = y has a solution, v = Flm_invimage_init(M,p); return x */ static GEN Flm_invimage_pre(GEN v, GEN y, ulong p) { GEN inv = gel(v,1), perm = gel(v,2); return Flm_Flc_mul(inv, vecsmallpermute(y, perm), p); } GEN algradical(GEN al) { pari_sp av = avma; GEN I, x, traces, K, MT, P, mt; long l,i,ni, n; ulong modu, expo, p; checkalg(al); if (alg_type(al) != al_TABLE) return gen_0; P = alg_get_char(al); mt = alg_get_multable(al); n = alg_get_absdim(al); dbg_printf(1)("algradical: char=%Ps, dim=%d\n", P, n); traces = algtracematrix(al); if (!signe(P)) { dbg_printf(2)(" char 0, computing kernel...\n"); K = ker(traces); dbg_printf(2)(" ...done.\n"); ni = lg(K)-1; if (!ni) return gc_const(av, gen_0); return gerepileupto(av, K); } dbg_printf(2)(" char>0, computing kernel...\n"); K = FpM_ker(traces, P); dbg_printf(2)(" ...done.\n"); ni = lg(K)-1; if (!ni) return gc_const(av, gen_0); if (abscmpiu(P,n)>0) return gerepileupto(av, K); /* tough case, p <= n. Ronyai's algorithm */ p = P[2]; l = 1; expo = p; modu = p*p; dbg_printf(2)(" char>0, hard case.\n"); while (modu<=(ulong)n) { l++; modu *= p; } MT = ZMV_to_FlmV(mt, modu); I = ZM_to_Flm(K,p); /* I_0 */ for (i=1; i<=l; i++) {/*compute I_i, expo = p^i, modu = p^(l+1) > n*/ long j, lig,col; GEN v = cgetg(ni+1, t_VECSMALL); GEN invI = Flm_invimage_init(I, p); dbg_printf(2)(" computing I_%d:\n", i); traces = cgetg(ni+1,t_MAT); for (j = 1; j <= ni; j++) { GEN M = algbasismultable_Flm(MT, gel(I,j), modu); uel(v,j) = algtracei(M, p,expo,modu); } for (col=1; col<=ni; col++) { GEN t = cgetg(n+1,t_VECSMALL); gel(traces,col) = t; x = gel(I, col); /*col-th basis vector of I_{i-1}*/ for (lig=1; lig<=n; lig++) { GEN y = _tablemul_ej_Fl(MT,x,lig,p); GEN z = Flm_invimage_pre(invI, y, p); uel(t,lig) = Flv_dotproduct(v, z, p); } } dbg_printf(2)(" computing kernel...\n"); K = Flm_ker(traces, p); dbg_printf(2)(" ...done.\n"); ni = lg(K)-1; if (!ni) return gc_const(av, gen_0); I = Flm_mul(I,K,p); expo *= p; } return Flm_to_ZM(I); } /* compute the multiplication table of the element x, where mt is a * multiplication table in an arbitrary ring */ static GEN Rgmultable(GEN mt, GEN x) { long i, l = lg(x); GEN z = NULL; for (i = 1; i < l; i++) { GEN c = gel(x,i); if (!gequal0(c)) { GEN M = RgM_Rg_mul(gel(mt,i),c); z = z? RgM_add(z, M): M; } } return z; } static GEN change_Rgmultable(GEN mt, GEN P, GEN Pi) { GEN mt2; long lmt = lg(mt), i; mt2 = cgetg(lmt,t_VEC); for (i=1;i first basis element is identity */ GEN alg_centralproj(GEN al, GEN z, long maps) { pari_sp av = avma; GEN S, U, Ui, alq, p; long i, iu, lz = lg(z), ta; checkalg(al); ta = alg_type(al); if (ta != al_TABLE) pari_err_TYPE("algcentralproj [not a table algebra]", al); if (typ(z) != t_VEC) pari_err_TYPE("alcentralproj",z); p = alg_get_char(al); dbg_printf(3)(" alg_centralproj: char=%Ps, dim=%d, #z=%d\n", p, alg_get_absdim(al), lz-1); S = cgetg(lz,t_VEC); /* S[i] = Im(z_i) */ for (i=1; i1 */ { GEN C2, P; long m, d, i, j; m = lg(C)-1; d = m/n; C2 = cgetg(d+1,t_COL); for (i=1; i<=d; i++) { P = pol_xn(n-1,v); for (j=1; j<=n; j++) gel(P,j+1) = gel(C,n*(i-1)+j); P = normalizepol(P); gel(C2,i) = P; } return C2; } static GEN RgM_contract(GEN A, long n, long v) /* n>1 */ { GEN A2 = cgetg(lg(A),t_MAT); long i; for (i=1; i (F_p)^(d^2*n) */ static GEN Fq_mat2col(GEN M, long d, long n) { long N = d*d*n, i, j, k; GEN C = cgetg(N+1, t_COL); for (i=1; i<=d; i++) for (j=1; j<=d; j++) for (k=0; k1) { T2 = init_Fq(p,n,v); setvarn(T,fetch_var_higher()); ro = FpXQX_roots(T2,T,p); ro = gel(ro,1); primelt = algpoleval(al,ro,primelt); T = T2; delete_var(); } /* descend al*e to a vector space over the center */ /* lifte: al*e -> al ; proje: al*e -> al */ lifte = shallowextract(mte,gel(ire,2)); extre = shallowmatextract(mte,gel(ire,1),gel(ire,2)); extre = FpM_inv(extre,p); proje = rowpermute(mte,gel(ire,1)); proje = FpM_mul(extre,proje,p); if (n==1) { B = lifte; C = proje; } else { M = algbasismultable(al,primelt); M = FpM_mul(M,lifte,p); M = FpM_mul(proje,M,p); B = descend(M,n,p,v); C = gel(B,2); B = gel(B,1); B = FpM_mul(lifte,B,p); C = FqM_mul(C,proje,T,p); } /* compute the isomorphism */ mt = alg_get_multable(al); map = cgetg(N+1,t_VEC); M = cgetg(N+1,t_MAT); for (i=1; i<=N; i++) { mx = gel(mt,i); mx = FpM_mul(mx,B,p); mx = FqM_mul(C,mx,T,p); gel(map,i) = mx; gel(M,i) = Fq_mat2col(mx,d,n); } mapi = FpM_inv(M,p); if (!mapi) pari_err(e_MISC, "the algebra must be simple (alg_finite_csa_split 3)"); return mkvec3(T,map,mapi); } GEN algsplit(GEN al, long v) { pari_sp av = avma; GEN res, T, map, mapi, ff, p; long i,j,k,li,lj; checkalg(al); p = alg_get_char(al); if (gequal0(p)) pari_err_IMPL("splitting a characteristic 0 algebra over its center"); res = alg_finite_csa_split(al, v); T = gel(res,1); map = gel(res,2); mapi = gel(res,3); ff = Tp_to_FF(T,p); for (i=1; i", utoi(r), pl); return itou(pl); } static long alghasse_emb(GEN al, long emb) { GEN nf = alg_get_center(al); long r1 = nf_get_r1(nf); return (emb <= r1)? alg_get_hasse_i(al)[emb]: 0; } static long alghasse_pr(GEN al, GEN pr) { GEN hf = alg_get_hasse_f(al); long i = tablesearch(gel(hf,1), pr, &cmp_prime_ideal); return i? gel(hf,2)[i]: 0; } static long alghasse_0(GEN al, GEN pl) { long ta; GEN pr, nf; ta = alg_type(al); if (ta == al_REAL) return algreal_dim(al)!=1; if (!pl) pari_err(e_MISC, "must provide a place pl"); if (ta == al_CSA) pari_err_IMPL("computation of Hasse invariants over table CSA"); if ((pr = get_prid(pl))) return alghasse_pr(al, pr); nf = alg_get_center(al); return alghasse_emb(al, is_place_emb(nf, pl)); } GEN alghasse(GEN al, GEN pl) { long h; checkalg(al); if (alg_type(al) == al_TABLE) pari_err_TYPE("alghasse [use alginit]",al); h = alghasse_0(al,pl); return sstoQ(h, alg_get_degree(al)); } /* h >= 0, d >= 0 */ static long indexfromhasse(long h, long d) { return d/ugcd(h,d); } long algindex(GEN al, GEN pl) { long d, res, i, l, ta; GEN hi, hf; checkalg(al); ta = alg_type(al); if (ta == al_TABLE) pari_err_TYPE("algindex [use alginit]",al); if (ta == al_REAL) return algreal_dim(al)==1 ? 1 : 2; d = alg_get_degree(al); if (pl) return indexfromhasse(alghasse_0(al,pl), d); /* else : global index */ res = 1; hi = alg_get_hasse_i(al); l = lg(hi); for (i=1; ity) { swap(x,y); lswap(tx,ty); } switch (tx) { case H_MATRIX: /* both H_MATRIX */ return alM_add(NULL, x, y); case H_QUATERNION: /* both H_QUATERNION */ return gadd(x,y); case H_SCALAR: if (ty == H_SCALAR) return gadd(x,y); else /* ty == H_QUATERNION */ { pari_sp av = avma; GEN res = gcopy(y), im; gel(res,1) = gadd(gel(res,1), real_i(x)); im = imag_i(x); if (im != gen_0) gel(res,2) = gadd(gel(res,2), im); return gerepileupto(av, res); } } return NULL; /*LCOV_EXCL_LINE*/ } GEN algadd(GEN al, GEN x, GEN y) { pari_sp av = avma; long tx, ty; GEN p; checkalg(al); if (alg_type(al)==al_REAL) return H_add(x,y); tx = alg_model(al,x); ty = alg_model(al,y); p = alg_get_char(al); if (signe(p)) return FpC_add(x,y,p); if (tx==ty) { if (tx!=al_MATRIX) return gadd(x,y); return gerepilecopy(av, alM_add(al,x,y)); } if (tx==al_ALGEBRAIC) x = algalgtobasis(al,x); if (ty==al_ALGEBRAIC) y = algalgtobasis(al,y); return gerepileupto(av, gadd(x,y)); } static GEN H_neg(GEN x) { (void)H_model(x); return gneg(x); } GEN algneg(GEN al, GEN x) { checkalg(al); if (alg_type(al)==al_REAL) return H_neg(x); (void)alg_model(al,x); return gneg(x); } static GEN alC_sub_i(GEN al, GEN x, GEN y, long lx) { long i; GEN A = cgetg(lx, t_COL); for (i=1; i 1 and 0 < i < lgcols(x) */ static GEN alMrow_alC_mul_i(GEN al, GEN x, GEN y, long i, long lx) { pari_sp av = avma; GEN c = algmul(al,gcoeff(x,i,1),gel(y,1)), ZERO; long k; ZERO = zerocol(alg_get_absdim(al)); for (k = 2; k < lx; k++) { GEN t = algmul(al, gcoeff(x,i,k), gel(y,k)); if (!gequal(t,ZERO)) c = algadd(al, c, t); } return gerepilecopy(av, c); } /* return x * y, 1 < lx = lg(x), l = lgcols(x) */ static GEN alM_alC_mul_i(GEN al, GEN x, GEN y, long lx, long l) { GEN z = cgetg(l,t_COL); long i; for (i=1; i1 && i==j) gel(res, ijk) = gsub(gel(res,ijk), gel(res,k)); } } } return res; } static GEN algbasis2mat(GEN al, GEN M, long N) { long n = alg_get_absdim(al), i, j, k, ij, ijk; GEN res, x; res = zeromatcopy(N,N); for (i=1; i<=N; i++) for (j=1; j<=N; j++) gcoeff(res,i,j) = zerocol(n); for (i=1; i<=N; i++) { for (j=1, ij=(i-1)*N+1; j<=N; j++, ij++) { x = gcoeff(res,i,j); for (k=1, ijk=(ij-1)*n+1; k<=n; k++, ijk++) { gel(x,k) = gel(M,ijk); if (i>1 && i==j) gel(x,k) = gadd(gel(x,k), gel(M,k)); } } } return res; } static GEN algmatbasis_ei(GEN al, long ijk, long N) { long n = alg_get_absdim(al), i, j, k, ij; GEN res; res = zeromatcopy(N,N); for (i=1; i<=N; i++) for (j=1; j<=N; j++) gcoeff(res,i,j) = zerocol(n); k = ijk%n; if (k==0) k=n; ij = (ijk-k)/n+1; if (ij==1) { for (i=1; i<=N; i++) gcoeff(res,i,i) = col_ei(n,k); return res; } j = ij%N; if (j==0) j=N; i = (ij-j)/N+1; gcoeff(res,i,j) = col_ei(n,k); return res; } /* FIXME lazy implementation! */ static GEN algleftmultable_mat(GEN al, GEN M) { long N = lg(M)-1, n = alg_get_absdim(al), D = N*N*n, j; GEN res, x, Mx; if (N == 0) return cgetg(1, t_MAT); if (N != nbrows(M)) pari_err_DIM("algleftmultable_mat (nonsquare)"); res = cgetg(D+1, t_MAT); for (j=1; j<=D; j++) { x = algmatbasis_ei(al, j, N); Mx = algmul(al, M, x); gel(res, j) = algmat2basis(al, Mx); } return res; } /* left multiplication table on integral basis */ static GEN algleftmultable(GEN al, GEN x) { pari_sp av = avma; long tx; GEN res; checkalg(al); tx = alg_model(al,x); switch(tx) { case al_TRIVIAL : res = mkmatcopy(mkcol(gel(x,1))); break; case al_ALGEBRAIC : x = algalgtobasis(al,x); case al_BASIS : res = algbasismultable(al,x); break; case al_MATRIX : res = algleftmultable_mat(al,x); break; default : return NULL; /* LCOV_EXCL_LINE */ } return gerepileupto(av,res); } static GEN algbasissplittingmatrix_csa(GEN al, GEN x) { long d = alg_get_degree(al), i, j; GEN rnf = alg_get_splittingfield(al), splba = alg_get_splittingbasis(al), splbainv = alg_get_splittingbasisinv(al), M; M = algbasismultable(al,x); M = RgM_mul(M, splba); /* TODO best order ? big matrix /Q vs small matrix /nf */ M = RgM_mul(splbainv, M); for (i=1; i<=d; i++) for (j=1; j<=d; j++) gcoeff(M,i,j) = rnfeltabstorel(rnf, gcoeff(M,i,j)); return M; } static GEN algmat_tomatrix(GEN al, GEN x) /* abs = 0 */ { GEN res; long i,j; if (lg(x) == 1) return cgetg(1, t_MAT); res = zeromatcopy(nbrows(x),lg(x)-1); for (j=1; j1 && lg(x) != lgcols(x)) || (lg(y)>1 && lg(y) != lgcols(y))) pari_err_DIM("C_divl (nonsquare)"); if (lg(x) != lg(y)) pari_err_DIM("C_divl"); if (lg(y) == 1) return cgetg(1, t_MAT); return RgM_invimage(x, y); default: pari_err_TYPE("C_divl", x); return NULL; } } /* H^k -> C^2k */ static GEN HC_to_CC(GEN v) { long l = lg(v), i; GEN w = cgetg(2*l-1, t_COL), a, b, c, d; for (i=1; i H^k */ static GEN CC_to_HC(GEN w) { long l = lg(w), i, lv = (l+1)/2; GEN v = cgetg(lv, t_COL), ab, cd; for (i=1; i M_{2k,n}(C) */ static GEN HM_to_CM(GEN x) pari_APPLY_same(HC_to_CC(gel(x,i))); /* M_{2k,n}(C) -> M_{k,n}(H) */ static GEN CM_to_HM(GEN x) pari_APPLY_same(CC_to_HC(gel(x,i))); /* x^(-1)*y, NULL if no solution */ static GEN H_divl_i(GEN x, GEN y) { pari_sp av = avma; long tx = H_model(x), ty = H_model(y); if ((tx==H_MATRIX) ^ (ty==H_MATRIX)) pari_err_TYPE2("H_divl", x, y); if (tx==H_MATRIX) { GEN mx, my, mxdivy; if ((lg(x)>1 && lg(x) != lgcols(x)) || (lg(y)>1 && lg(y) != lgcols(y))) pari_err_DIM("H_divl (nonsquare)"); if (lg(x) != lg(y)) pari_err_DIM("H_divl"); if (lg(y) == 1) return cgetg(1, t_MAT); mx = H_tomatrix(x,0); my = HM_to_CM(y); mxdivy = RgM_invimage(mx, my); if (!mxdivy) return gc_NULL(av); return gerepilecopy(av,CM_to_HM(mxdivy)); } if (gequal0(y)) return gen_0; if (gequal0(x)) return NULL; return gerepilecopy(av,H_mul(H_inv(x),y)); } /* x^(-1)*y, NULL if no solution */ static GEN algdivl_i(GEN al, GEN x, GEN y, long tx, long ty) { pari_sp av = avma; GEN res, p = alg_get_char(al), mtx; if (tx != ty) { if (tx==al_ALGEBRAIC) { x = algalgtobasis(al,x); tx=al_BASIS; } if (ty==al_ALGEBRAIC) { y = algalgtobasis(al,y); ty=al_BASIS; } } if (ty == al_MATRIX) { if (alg_type(al) != al_TABLE) y = algalgtobasis(al,y); y = algmat2basis(al,y); } if (signe(p)) res = FpM_FpC_invimage(algbasismultable(al,x),y,p); else { if (ty==al_ALGEBRAIC) mtx = algalgmultable(al,x); else mtx = algleftmultable(al,x); res = inverseimage(mtx,y); } if (!res || lg(res)==1) return gc_NULL(av); if (tx == al_MATRIX) { res = algbasis2mat(al, res, lg(x)-1); return gerepilecopy(av,res); } return gerepileupto(av,res); } static GEN algdivl_i2(GEN al, GEN x, GEN y) { long tx, ty; checkalg(al); if (alg_type(al)==al_REAL) switch(alg_get_absdim(al)) { case 1: case 2: return C_divl_i(x,y); case 4: return H_divl_i(x,y); } tx = alg_model(al,x); ty = alg_model(al,y); if (tx == al_MATRIX) { if (ty != al_MATRIX) pari_err_TYPE2("\\", x, y); if ((lg(x)>1 && lg(x) != lgcols(x)) || (lg(y)>1 && lg(y) != lgcols(y))) pari_err_DIM("algdivl (nonsquare)"); if (lg(x) != lg(y)) pari_err_DIM("algdivl"); if (lg(y) == 1) return cgetg(1, t_MAT); } return algdivl_i(al,x,y,tx,ty); } GEN algdivl(GEN al, GEN x, GEN y) { GEN z; z = algdivl_i2(al,x,y); if (!z) pari_err_INV("algdivl", x); return z; } int algisdivl(GEN al, GEN x, GEN y, GEN* ptz) { pari_sp av = avma; GEN z = algdivl_i2(al,x,y); if (!z) return gc_bool(av,0); if (ptz != NULL) *ptz = z; return 1; } static GEN C_inv(GEN x) { switch (H_model(x)) { case H_SCALAR: return gequal0(x) ? NULL : ginv(x); case H_MATRIX: return RgM_inv(x); default: pari_err_TYPE("alginv_i", x); } return NULL; /*LCOV_EXCL_LINE*/ } static GEN H_inv(GEN x) { pari_sp av = avma; GEN nm, xi; long i; switch (H_model(x)) { case H_SCALAR: if (gequal0(x)) return NULL; return ginv(x); case H_QUATERNION: if (gequal0(x)) return NULL; nm = H_norm(x, 0); xi = gdiv(x,nm); for(i=2; i<=4; i++) gel(xi,i) = gneg(gel(xi,i)); return gerepilecopy(av,xi); case H_MATRIX: if (lg(x)==1) return cgetg(1,t_MAT); return H_divl_i(x, matid(lg(x)-1)); } return NULL; /*LCOV_EXCL_LINE*/ } static GEN alginv_i(GEN al, GEN x) { pari_sp av = avma; GEN res = NULL, p = alg_get_char(al); long tx, n, ta; ta = alg_type(al); if (ta==al_REAL) switch(alg_get_absdim(al)) { case 1: case 2: return C_inv(x); case 4: return H_inv(x); default: pari_err_TYPE("alginv_i [apply alginit]", al); } tx = alg_model(al,x); switch(tx) { case al_TRIVIAL : if (signe(p)) { res = mkcol(Fp_inv(gel(x,1),p)); break; } else { res = mkcol(ginv(gel(x,1))); break; } case al_ALGEBRAIC : switch(ta) { case al_CYCLIC: n = alg_get_degree(al); break; case al_CSA: n = alg_get_dim(al); break; default: return NULL; /* LCOV_EXCL_LINE */ } res = algdivl_i(al, x, col_ei(n,1), tx, al_ALGEBRAIC); break; case al_BASIS : res = algdivl_i(al, x, col_ei(alg_get_absdim(al),1), tx, al_BASIS); break; case al_MATRIX : n = lg(x)-1; if (n==0) return cgetg(1, t_MAT); if (n != nbrows(x)) pari_err_DIM("alginv_i (nonsquare)"); res = algdivl_i(al, x, col_ei(n*n*alg_get_absdim(al),1), tx, al_BASIS); /* cheat on type because wrong dimension */ } if (!res) return gc_NULL(av); return gerepilecopy(av,res); } GEN alginv(GEN al, GEN x) { GEN z; checkalg(al); z = alginv_i(al,x); if (!z) pari_err_INV("alginv", x); return z; } int algisinv(GEN al, GEN x, GEN* ptix) { pari_sp av = avma; GEN ix; if (al) checkalg(al); ix = alginv_i(al,x); if (!ix) return gc_bool(av,0); if (ptix != NULL) *ptix = ix; return 1; } /* x*y^(-1) */ GEN algdivr(GEN al, GEN x, GEN y) { return algmul(al, x, alginv(al, y)); } static GEN _mul(void* data, GEN x, GEN y) { return algmul((GEN)data,x,y); } static GEN _sqr(void* data, GEN x) { return algsqr((GEN)data,x); } static GEN algmatid(GEN al, long N) { long n = alg_get_absdim(al), i, j; GEN res, one, zero; res = zeromatcopy(N,N); one = col_ei(n,1); zero = zerocol(n); for (i=1; i<=N; i++) for (j=1; j<=N; j++) gcoeff(res,i,j) = i==j ? one : zero; return res; } GEN algpow(GEN al, GEN x, GEN n) { pari_sp av = avma; GEN res; long s = signe(n); checkalg(al); if (!s && alg_type(al)==al_REAL) { if (H_model(x) == H_MATRIX) return matid(lg(x)-1); else return gen_1; } switch (s) { case 0: if (alg_model(al,x) == al_MATRIX) res = algmatid(al,lg(x)-1); else res = col_ei(alg_get_absdim(al),1); return res; case 1: res = gen_pow_i(x, n, (void*)al, _sqr, _mul); break; default: /* -1 */ res = gen_pow_i(alginv(al,x), gneg(n), (void*)al, _sqr, _mul); } return gerepilecopy(av,res); } static GEN algredcharpoly_i(GEN al, GEN x, long v) { GEN rnf = alg_get_splittingfield(al); GEN cp = charpoly(algtomatrix(al,x,0),v); long i, m = lg(cp); for (i=2; i=0) pari_err_PRIORITY("algredcharpoly",pol_x(v),">=",w); switch(alg_type(al)) { case al_CYCLIC: case al_CSA: return gerepileupto(av, algredcharpoly_i(al, x, v)); } return NULL; /*LCOV_EXCL_LINE*/ } static GEN algbasischarpoly(GEN al, GEN x, long v) { pari_sp av = avma; GEN p = alg_get_char(al), mx; if (alg_model(al,x) == al_MATRIX) mx = algleftmultable_mat(al,x); else mx = algbasismultable(al,x); if (signe(p)) { GEN res = FpM_charpoly(mx,p); setvarn(res,v); return gerepileupto(av, res); } return gerepileupto(av, charpoly(mx,v)); } static GEN R_charpoly(GEN x, long v, long abs) { pari_sp av = avma; GEN res = NULL; switch (H_model(x)) { case H_SCALAR: res = mkpoln(2, gen_1, gneg(x)); break; case H_MATRIX: res = charpoly(x,v); if (abs) res = gpowgs(res,nbrows(x)); break; default: pari_err_TYPE("R_charpoly", x); } if (v) setvarn(res, v); return gerepilecopy(av, res); } static GEN C_charpoly(GEN x, long v, long abs) { pari_sp av = avma; GEN res = NULL; switch (H_model(x)) { case H_SCALAR: if (abs) res = mkpoln(3, gen_1, gneg(gshift(real_i(x),1)), cxnorm(x)); else res = mkpoln(2, gen_1, gneg(x)); break; case H_MATRIX: res = charpoly(x,v); if (abs) res = gpowgs(real_i(gmul(res,gconj(res))),nbrows(x)); break; default: pari_err_TYPE("C_charpoly", x); } if (v) setvarn(res, v); return gerepilecopy(av, res); } static GEN H_charpoly(GEN x, long v, long abs) { pari_sp av = avma; GEN res; if (H_model(x) == H_MATRIX) return greal(charpoly(H_tomatrix(x,abs),v)); res = mkpoln(3, gen_1, gneg(H_trace(x,0)), H_norm(x,0)); if (v) setvarn(res, v); if (abs) res = gsqr(res); return gerepilecopy(av, res); } GEN algcharpoly(GEN al, GEN x, long v, long abs) { long ta; if (v<0) v=0; checkalg(al); ta = alg_type(al); if (ta == al_REAL) switch (alg_get_absdim(al)) { case 1: return R_charpoly(x, v, abs); case 2: return C_charpoly(x, v, abs); case 4: return H_charpoly(x, v, abs); default: pari_err_TYPE("algcharpoly [apply alginit]", al); } /* gneg(x[1]) left on stack */ if (alg_model(al,x) == al_TRIVIAL) { GEN p = alg_get_char(al); if (signe(p)) return deg1pol(gen_1,Fp_neg(gel(x,1),p),v); return deg1pol(gen_1,gneg(gel(x,1)),v); } switch(ta) { case al_CYCLIC: case al_CSA: if (abs) { if (alg_model(al,x)==al_ALGEBRAIC) x = algalgtobasis(al,x); } else return algredcharpoly(al,x,v); case al_TABLE: return algbasischarpoly(al,x,v); default : return NULL; /* LCOV_EXCL_LINE */ } } /* assumes x in basis form */ static GEN algabstrace(GEN al, GEN x) { pari_sp av = avma; GEN res = NULL, p = alg_get_char(al); if (signe(p)) return FpV_dotproduct(x, alg_get_tracebasis(al), p); switch(alg_model(al,x)) { case al_TRIVIAL: return gcopy(gel(x,1)); break; case al_BASIS: res = RgV_dotproduct(x, alg_get_tracebasis(al)); break; } return gerepileupto(av,res); } static GEN algredtrace(GEN al, GEN x) { pari_sp av = avma; GEN res = NULL; switch(alg_model(al,x)) { case al_TRIVIAL: return gcopy(gel(x,1)); break; case al_BASIS: return algredtrace(al, algbasistoalg(al,x)); /* TODO precompute too? */ case al_ALGEBRAIC: switch(alg_type(al)) { case al_CYCLIC: res = rnfelttrace(alg_get_splittingfield(al),gel(x,1)); break; case al_CSA: res = gtrace(algalgmultable_csa(al,x)); res = gdiv(res, stoi(alg_get_degree(al))); break; default: return NULL; /* LCOV_EXCL_LINE */ } } return gerepileupto(av,res); } static GEN algtrace_mat(GEN al, GEN M, long abs) { pari_sp av = avma; long N = lg(M)-1, i; GEN res, p = alg_get_char(al); if (N == 0) return gen_0; if (N != nbrows(M)) pari_err_DIM("algtrace_mat (nonsquare)"); if (!signe(p)) p = NULL; if (alg_type(al) == al_TABLE) abs = 1; res = algtrace(al, gcoeff(M,1,1), abs); for (i=2; i<=N; i++) { if (p) res = Fp_add(res, algtrace(al,gcoeff(M,i,i),abs), p); else res = gadd(res, algtrace(al,gcoeff(M,i,i),abs)); } if (abs) res = gmulgu(res, N); /* absolute trace */ return gerepileupto(av, res); } static GEN R_trace(GEN x, long abs) { pari_sp av = avma; GEN res = NULL; switch (H_model(x)) { case H_SCALAR: res = gcopy(x); break; case H_MATRIX: res = abs? mulrs(gtrace(x),nbrows(x)) : gtrace(x); break; default: pari_err_TYPE("R_trace", x); } return gerepilecopy(av, res); } static GEN C_trace(GEN x, long abs) { pari_sp av = avma; GEN res = NULL; switch (H_model(x)) { case H_SCALAR: res = abs ? gshift(real_i(x),1) : x; break; case H_MATRIX: res = abs ? mulrs(real_i(gtrace(x)),2*nbrows(x)) : gtrace(x); break; default: pari_err_TYPE("C_trace", x); } return gerepilecopy(av, res); } static GEN H_trace(GEN x, long abs) { long s = abs? 2 : 1; switch (H_model(x)) { case H_SCALAR: return gshift(real_i(x),s); case H_QUATERNION: return gshift(gel(x,1),s); case H_MATRIX: return algtrace_mat(NULL, x, abs); } return NULL; /*LCOV_EXCL_LINE*/ } GEN algtrace(GEN al, GEN x, long abs) { long ta; checkalg(al); ta = alg_type(al); if (ta==al_REAL) switch (alg_get_absdim(al)) { case 1: return R_trace(x,abs); case 2: return C_trace(x,abs); case 4: return H_trace(x,abs); default: pari_err_TYPE("algtrace [apply alginit]", al); } if (alg_model(al,x) == al_MATRIX) return algtrace_mat(al,x,abs); switch(ta) { case al_CYCLIC: case al_CSA: if (!abs) return algredtrace(al,x); if (alg_model(al,x)==al_ALGEBRAIC) x = algalgtobasis(al,x); case al_TABLE: return algabstrace(al,x); default : return NULL; /* LCOV_EXCL_LINE */ } } static GEN ZM_trace(GEN x) { long i, lx = lg(x); GEN t; if (lx < 3) return lx == 1? gen_0: gcopy(gcoeff(x,1,1)); t = gcoeff(x,1,1); for (i = 2; i < lx; i++) t = addii(t, gcoeff(x,i,i)); return t; } static GEN FpM_trace(GEN x, GEN p) { long i, lx = lg(x); GEN t; if (lx < 3) return lx == 1? gen_0: gcopy(gcoeff(x,1,1)); t = gcoeff(x,1,1); for (i = 2; i < lx; i++) t = Fp_add(t, gcoeff(x,i,i), p); return t; } static GEN algtracebasis(GEN al) { pari_sp av = avma; GEN mt = alg_get_multable(al), p = alg_get_char(al); long i, l = lg(mt); GEN v = cgetg(l, t_VEC); if (signe(p)) for (i=1; i < l; i++) gel(v,i) = FpM_trace(gel(mt,i), p); else for (i=1; i < l; i++) gel(v,i) = ZM_trace(gel(mt,i)); return gerepileupto(av,v); } /* Assume: i > 0, expo := p^i <= absdim, x contained in I_{i-1} given by mult * table modulo modu=p^(i+1). Return Tr(x^(p^i)) mod modu */ static ulong algtracei(GEN mt, ulong p, ulong expo, ulong modu) { pari_sp av = avma; long j, l = lg(mt); ulong tr = 0; mt = Flm_powu(mt,expo,modu); for (j=1; j1; i--) { gel(res,1) = gadd(gel(res,1), gel(pol,i)); if (i>2) res = H_mul(x, res); } return gerepilecopy(av,res); } /* Assumes pol has coefficients in the same ring as the COL x; x either * in basis or algebraic form or [x,mx] where mx is the mult. table of x. TODO more general version: pol with coeffs in center and x in basis form */ GEN algpoleval(GEN al, GEN pol, GEN x) { pari_sp av = avma; GEN p, mx = NULL, res, c; long i, xalg = 0; if (typ(pol) != t_POL) pari_err_TYPE("algpoleval", pol); checkalg(al); if (alg_type(al)==al_REAL) return H_poleval(pol,x); p = alg_get_char(al); if (typ(x) == t_VEC) { if (lg(x) != 3) pari_err_TYPE("algpoleval [vector must be of length 2]", x); mx = gel(x,2); x = gel(x,1); if (typ(mx)!=t_MAT || !gequal(x,gel(mx,1))) pari_err_TYPE("algpoleval [mx must be the multiplication table of x]", mx); } else { switch(alg_model(al,x)) { case al_ALGEBRAIC: mx = algalgmultable(al,x); xalg=1; break; case al_BASIS: case al_TRIVIAL: mx = algbasismultable(al,x); break; default: pari_err_TYPE("algpoleval", x); } } res = zerocol(lg(mx)-1); if (signe(p)) { for (i=lg(pol)-1; i>1; i--) { gel(res,1) = Fp_add(gel(res,1), gel(pol,i), p); if (i>2) res = FpM_FpC_mul(mx, res, p); } } else { for (i=lg(pol)-1; i>1; i--) { c = gel(pol,i); if (xalg || is_rational_t(typ(c))) gel(res,1) = gadd(gel(res,1), c); else res = RgC_add(res, algfromcenter(al,c)); if (i>2) res = RgM_RgC_mul(mx, res); } } return gerepileupto(av, res); } /** GRUNWALD-WANG **/ /* Song Wang's PhD thesis (pdf pages) p.25 definition of chi_b. K^Ker(chi_b) = K(b^(1/m)) p.26 bound on the conductor (also Cohen adv. GTM 193 p.166) p.21 & p.34 description special case, also on wikipedia: http://en.wikipedia.org/wiki/Grunwald%E2%80%93Wang_theorem#Special_fields p.77 Kummer case */ /* n > 0. Is n = 2^k ? */ static int uispow2(ulong n) { return !(n &(n-1)); } static GEN get_phi0(GEN bnr, GEN Lpr, GEN Ld, GEN pl, long *pr, long *pn) { const long NTRY = 10; /* FIXME: magic constant */ const long n = (lg(Ld)==1)? 2: vecsmall_max(Ld); GEN S = bnr_get_cyc(bnr); GEN Sst, G, globGmod, loc, X, Rglob, Rloc, H, U, Lconj; long i, j, r, nbfrob, nbloc, nz, t; *pn = n; *pr = r = lg(S)-1; if (!r) return NULL; Sst = cgetg(r+1, t_VECSMALL); /* Z/n-dual */ for (i=1; i<=r; i++) Sst[i] = ugcdiu(gel(S,i), n); if (Sst[1] != n) return NULL; Lconj = NULL; nbloc = nbfrob = lg(Lpr)-1; if (uispow2(n)) { long l = lg(pl), k = 0; GEN real = cgetg(l, t_VECSMALL); for (i = 1; i < l; i++) if (pl[i] == -1) real[++k] = i; if (k) { GEN nf = bnr_get_nf(bnr), I = bid_get_fact(bnr_get_bid(bnr)); GEN v, y, C = idealchineseinit(bnr, I); long r1 = nf_get_r1(nf), n = nbrows(I); nbloc += k; Lconj = cgetg(k+1, t_VEC); v = const_vecsmall(r1, 1); y = const_vec(n, gen_1); for (i = 1; i <= k; i++) { v[real[i]] = -1; gel(Lconj,i) = idealchinese(nf, mkvec2(C,v), y); v[real[i]] = 1; } } } globGmod = cgetg(r+1,t_MAT); G = cgetg(r+1,t_VECSMALL); for (i = 1; i <= r; i++) { G[i] = n / Sst[i]; /* pairing between S and Sst */ gel(globGmod,i) = cgetg(nbloc+1,t_VECSMALL); } /* compute images of Frobenius elements (and complex conjugation) */ loc = cgetg(nbloc+1,t_VECSMALL); for (i = 1; i <= nbloc; i++) { long L; if (i <= nbfrob) { X = gel(Lpr, i); L = Ld[i]; } else { /* X = 1 (mod f), sigma_i(x) < 0, positive at all other real places */ X = gel(Lconj, i-nbfrob); L = 2; } X = ZV_to_Flv(isprincipalray(bnr,X), n); for (nz=0,j=1; j<=r; j++) { ulong c = (X[j] * G[j]) % L; ucoeff(globGmod,i,j) = c; if (c) nz = 1; } if (!nz) return NULL; loc[i] = L; } /* try some random elements in the dual */ Rglob = cgetg(r+1,t_VECSMALL); for (t=0; t nbloc) return zv_to_ZV(Rglob); } /* try to realize some random elements of the product of the local duals */ H = ZM_hnfall_i(shallowconcat(zm_to_ZM(globGmod), diagonal_shallow(zv_to_ZV(loc))), &U, 2); /* H,U nbloc x nbloc */ Rloc = cgetg(nbloc+1,t_COL); for (t = 0; t < NTRY; t++) { /* nonzero random coordinate */ /* TODO add special case ? */ for (i = 1; i <= nbloc; i++) gel(Rloc,i) = stoi(1 + random_Fl(loc[i]-1)); Rglob = hnf_invimage(H, Rloc); if (Rglob) { Rglob = ZM_ZC_mul(U,Rglob); return vecslice(Rglob,1,r); } } return NULL; } static GEN bnrgwsearch(GEN bnr, GEN Lpr, GEN Ld, GEN pl) { pari_sp av = avma; long n, r; GEN phi0 = get_phi0(bnr,Lpr,Ld,pl, &r,&n), gn, v, H,U; if (!phi0) return gc_const(av, gen_0); gn = stoi(n); /* compute kernel of phi0 */ v = ZV_extgcd(vec_append(phi0, gn)); U = vecslice(gel(v,2), 1,r); H = ZM_hnfmodid(rowslice(U, 1,r), gn); return gerepileupto(av, H); } GEN bnfgwgeneric(GEN bnf, GEN Lpr, GEN Ld, GEN pl, long var) { pari_sp av = avma; const long n = (lg(Ld)==1)? 2: vecsmall_max(Ld); forprime_t S; GEN bnr = NULL, ideal = gen_1, nf, dec, H = gen_0, finf, pol; ulong ell, p; long deg, i, degell; (void)uisprimepower(n, &ell); nf = bnf_get_nf(bnf); deg = nf_get_degree(nf); degell = ugcd(deg,ell-1); finf = cgetg(lg(pl),t_VEC); for (i=1; i= 0) pari_err_PRIORITY("nfgrunwaldwang", pol_x(var), ">=", vnf); if (typ(Lpr) != t_VEC) pari_err_TYPE("nfgrunwaldwang",Lpr); if (lg(Lpr) != lg(Ld)) pari_err_DIM("nfgrunwaldwang [#Lpr != #Ld]"); if (nf_get_degree(nf)==1) Lpr = shallowcopy(Lpr); for (i=1; i1) return gerepileupto(av, nfgwkummer(nf,Lpr,Ld,pl,var)); if (ell==n) { if (!bnf) bnf = Buchall(nf, nf_FORCE, 0); return gerepileupto(av, bnfgwgeneric(bnf,Lpr,Ld,pl,var)); } pari_err_IMPL("nfgrunwaldwang for nonprime degree"); return NULL; /*LCOV_EXCL_LINE*/ } /** HASSE INVARIANTS **/ /* TODO long -> ulong + uel */ static GEN hasseconvert(GEN H, long n) { GEN h, c; long i, l; switch(typ(H)) { case t_VEC: l = lg(H); h = cgetg(l,t_VECSMALL); if (l == 1) return h; c = gel(H,1); if (typ(c) == t_VEC && l == 3) return mkvec2(gel(H,1),hasseconvert(gel(H,2),n)); for (i=1; i= 2 */ static long cyclicrelfrob0(GEN nf, GEN aut, GEN pr, GEN q, long f, long g) { GEN T, p, a, b, modpr = nf_to_Fq_init(nf,&pr,&T,&p); long s; a = pol_x(nf_get_varn(nf)); b = galoisapply(nf, aut, modpr_genFq(modpr)); b = nf_to_Fq(nf, b, modpr); for (s = 0; !ZX_equal(a, b); s++) a = Fq_pow(a, q, T, p); return g * Fl_inv(s, f); /* < n */ } static long cyclicrelfrob(GEN rnf, GEN auts, GEN pr) { pari_sp av = avma; long f,g,frob, n = rnf_get_degree(rnf); GEN P = rnfidealprimedec(rnf, pr); if (pr_get_e(gel(P,1)) > pr_get_e(pr)) pari_err_DOMAIN("cyclicrelfrob","e(PR/pr)",">",gen_1,pr); g = lg(P) - 1; f = n / g; if (f <= 2) frob = g % n; else { GEN nf2, PR = gel(P,1); GEN autabs = rnfeltreltoabs(rnf,gel(auts,g)); nf2 = obj_check(rnf,rnf_NFABS); autabs = nfadd(nf2, autabs, gmul(rnf_get_k(rnf), rnf_get_alpha(rnf))); frob = cyclicrelfrob0(nf2, autabs, PR, pr_norm(pr), f, g); } return gc_long(av, frob); } static long localhasse(GEN rnf, GEN cnd, GEN pl, GEN auts, GEN b, long k) { pari_sp av = avma; long v, m, h, lfa, frob, n, i; GEN previous, y, pr, nf, q, fa; nf = rnf_get_nf(rnf); n = rnf_get_degree(rnf); pr = gcoeff(cnd,k,1); v = nfval(nf, b, pr); m = lg(cnd)>1 ? nbrows(cnd) : 0; /* add the valuation of b to the conductor... */ previous = gcoeff(cnd,k,2); gcoeff(cnd,k,2) = addis(previous, v); y = const_vec(m, gen_1); gel(y,k) = b; /* find a factored element y congruent to b mod pr^(vpr(b)+vpr(cnd)) and to 1 mod the conductor. */ y = factoredextchinese(nf, cnd, y, pl, &fa); h = 0; lfa = nbrows(fa); /* sum of all Hasse invariants of (rnf/nf,aut,y) is 0, Hasse invariants at q!=pr are easy, Hasse invariant at pr is the same as for al=(rnf/nf,aut,b). */ for (i=1; i<=lfa; i++) { q = gcoeff(fa,i,1); if (cmp_prime_ideal(pr,q)) { frob = cyclicrelfrob(rnf, auts, q); frob = Fl_mul(frob,umodiu(gcoeff(fa,i,2),n),n); h = Fl_add(h,frob,n); } } /* ...then restore it. */ gcoeff(cnd,k,2) = previous; return gc_long(av, Fl_neg(h,n)); } static GEN allauts(GEN rnf, GEN aut) { long n = rnf_get_degree(rnf), i; GEN pol = rnf_get_pol(rnf), vaut; if (n==1) n=2; vaut = cgetg(n,t_VEC); aut = lift_shallow(rnfbasistoalg(rnf,aut)); if (typ(aut) != t_POL || varn(pol) != varn(aut)) pari_err_TYPE("alg_cyclic", aut); gel(vaut,1) = aut; for (i=1; i= 0 */ static void nextgen(GEN gene, long h, GEN* gens, GEN* hgens, long* ngens, long* curgcd) { long nextgcd = ugcd(h,*curgcd); if (nextgcd == *curgcd) return; (*ngens)++; gel(*gens,*ngens) = gene; gel(*hgens,*ngens) = utoi(h); *curgcd = nextgcd; return; } static int dividesmod(long d, long h, long n) { return !(h%cgcd(d,n)); } /* ramified prime with nontrivial Hasse invariant */ static GEN localcomplete(GEN rnf, GEN pl, GEN cnd, GEN auts, long j, long n, long h, long* v) { GEN nf, gens, hgens, pr, modpr, T, p, sol, U, b, gene, randg, pu; long ngens, i, d, np, d1, d2, hg, dnf, vcnd, curgcd; nf = rnf_get_nf(rnf); pr = gcoeff(cnd,j,1); np = umodiu(pr_norm(pr), n); dnf = nf_get_degree(nf); vcnd = itos(gcoeff(cnd,j,2)); ngens = 13+dnf; gens = zerovec(ngens); hgens = zerovec(ngens); *v = 0; curgcd = 0; ngens = 0; if (!uisprime(n)) { gene = pr_get_gen(pr); hg = localhasse(rnf, cnd, pl, auts, gene, j); nextgen(gene, hg, &gens, &hgens, &ngens, &curgcd); } if (ugcd(np,n) != 1) { /* GCD(Np,n) != 1 */ pu = idealprincipalunits(nf,pr,vcnd); pu = abgrp_get_gen(pu); for (i=1; i1 || lk%2==0) { maxdeg = 1; Lpr = gel(hfl,1); Ld = gcopy(gel(hfl,2)); for (j=1; j1) pl[1] = -1; else { GEN p = extraprime(prV_primes(Lpr)); Lpr2 = vec_append(Lpr2, idealprimedec_galois(nf, p)); Ld2 = vecsmall_append(Ld2, lk); } } dbg_printf(2)("alg_hasse: calling nfgrunwaldwang Lpr=%Ps Pd=%Ps pl=%Ps\n", Lpr, Ld, pl); pol = nfgrunwaldwang(nf, Lpr2, Ld2, pl, var); dbg_printf(2)("alg_hasse: calling rnfinit(%Ps)\n", pol); rnf = rnfinit0(nf,pol,1); dbg_printf(2)("alg_hasse: computing automorphism\n"); aut = rnfcycaut(rnf); dbg_printf(2)("alg_hasse: calling alg_complete\n"); al2 = alg_complete0(rnf, aut, hfl, hil, flag); } else al2 = alg_matrix(nf, lk, var, flag); if (i==1) al = al2; else al = algtensor(al,al2,flag); } return gerepilecopy(av,al); } /** CYCLIC ALGEBRA WITH GIVEN HASSE INVARIANTS **/ /* no garbage collection */ static GEN subcycloindep(GEN nf, long n, long v, GEN *pr) { pari_sp av; forprime_t S; ulong p; u_forprime_arith_init(&S, 1, ULONG_MAX, 1, n); av = avma; while ((p = u_forprime_next(&S))) { ulong r = pgener_Fl(p); GEN pol = galoissubcyclo(utoipos(p), utoipos(Fl_powu(r,n,p)), 0, v); GEN fa = nffactor(nf, pol); if (lgcols(fa) == 2) { *pr = utoipos(r); return pol; } set_avma(av); } pari_err_BUG("subcycloindep (no suitable prime = 1(mod n))"); /*LCOV_EXCL_LINE*/ *pr = NULL; return NULL; /*LCOV_EXCL_LINE*/ } GEN alg_matrix(GEN nf, long n, long v, long flag) { pari_sp av = avma; GEN pol, gal, rnf, cyclo, g, r, aut; dbg_printf(1)("alg_matrix\n"); if (n<=0) pari_err_DOMAIN("alg_matrix", "n", "<=", gen_0, stoi(n)); pol = subcycloindep(nf, n, v, &r); rnf = rnfinit(nf, pol); cyclo = nfinit(pol, nf_get_prec(nf)); gal = galoisinit(cyclo, NULL); g = genefrob(cyclo,gal,r); aut = galoispermtopol(gal,g); return gerepileupto(av, alg_cyclic(rnf, aut, gen_1, flag)); } GEN alg_hilbert(GEN nf, GEN a, GEN b, long v, long flag) { pari_sp av = avma; GEN rnf, aut, rnfpol; dbg_printf(1)("alg_hilbert\n"); if (!isint1(Q_denom(algtobasis(nf,a)))) pari_err_DOMAIN("alg_hilbert", "denominator(a)", "!=", gen_1,a); if (!isint1(Q_denom(algtobasis(nf,b)))) pari_err_DOMAIN("alg_hilbert", "denominator(b)", "!=", gen_1,b); if (v < 0) v = 0; rnfpol = deg2pol_shallow(gen_1, gen_0, gneg(basistoalg(nf,a)), v); if (!(flag & al_FACTOR)) rnfpol = mkvec2(rnfpol, stoi(1<<20)); rnf = rnfinit(nf, rnfpol); aut = gneg(pol_x(v)); return gerepileupto(av, alg_cyclic(rnf, aut, b, flag)); } /* return a structure representing the algebra of real numbers */ static GEN mk_R() { pari_sp av = avma; GEN al; al = zerovec(11); gel(al,1) = stor(1, LOWDEFAULTPREC); gel(al,2) = mkvec(gel(al,1)); gel(al,3) = gen_1; gel(al,4) = mkvecsmall(0); gel(al,8) = gel(al,7) = matid(1); gel(al,9) = mkvec(matid(1)); return gerepilecopy(av,al); } /* return a structure representing the algebra of complex numbers */ static GEN mk_C() { pari_sp av = avma; GEN al, I; al = zerovec(11); I = gen_I(); gel(al,1) = I; gel(al,2) = mkvec(I); gel(al,3) = gen_1; gel(al,4) = cgetg(1,t_VECSMALL); gel(al,8) = gel(al,7) = matid(2); gel(al,9) = mkvec2( matid(2), mkmat22(gen_0,gen_m1,gen_1,gen_0) ); return gerepilecopy(av,al); } /* return a structure representing the Hamilton quaternion algebra */ static GEN mk_H() { pari_sp av = avma; GEN al, I; al = zerovec(11); I = gen_I(); gel(al,1) = I; gel(al,2) = mkvec(gconj(I)); gel(al,3) = gen_m1; gel(al,4) = mkvecsmall(1); gel(al,8) = gel(al,7) = matid(4); gel(al,9) = mkvec4( matid(4), H_tomatrix(I,1), H_tomatrix(mkcol4(gen_0,gen_0,gen_1,gen_0),1), H_tomatrix(mkcol4(gen_0,gen_0,gen_0,gen_1),1) ); return gerepilecopy(av,al); } GEN alginit(GEN A, GEN B, long v, long flag) { long w; if (typ(A) == t_COMPLEX) return mk_C(); if (typ(A) == t_REAL) { if (is_scalar_t(typ(B)) && gequal0(B)) return mk_R(); if (typ(B) == t_FRAC && gequal(B, mkfrac(gen_1,gen_2))) return mk_H(); pari_err_DOMAIN("alginit", "real Hasse invariant [must be 0 or 1/2]", "", NULL, B); } switch(nftyp(A)) { case typ_NF: if (v<0) v=0; w = gvar(nf_get_pol(A)); if (varncmp(v,w)>=0) pari_err_PRIORITY("alginit", pol_x(v), ">=", w); switch(typ(B)) { long nB; case t_INT: return alg_matrix(A, itos(B), v, flag); case t_VEC: nB = lg(B)-1; if (nB && typ(gel(B,1)) == t_MAT) return alg_csa_table(A,B,v,flag); switch(nB) { case 2: return alg_hilbert(A, gel(B,1), gel(B,2), v, flag); case 3: if (typ(gel(B,1))!=t_INT) pari_err_TYPE("alginit [degree should be an integer]", gel(B,1)); return alg_hasse(A, itos(gel(B,1)), gel(B,2), gel(B,3), v, flag); } } pari_err_TYPE("alginit", B); break; case typ_RNF: if (typ(B) != t_VEC || lg(B) != 3) pari_err_TYPE("alginit", B); return alg_cyclic(A, gel(B,1), gel(B,2), flag); } pari_err_TYPE("alginit", A); return NULL;/*LCOV_EXCL_LINE*/ } /* assumes al CSA or CYCLIC */ static GEN algnatmultable(GEN al, long D) { GEN res, x; long i; res = cgetg(D+1,t_VEC); for (i=1; i<=D; i++) { x = algnattoalg(al,col_ei(D,i)); gel(res,i) = algZmultable(al,x); } return res; } static int normfact_is_partial(GEN nf, GEN x, GEN fax) { long i; GEN nfx; nfx = RgM_shallowcopy(fax); for (i=1; i 2) { long i; for (i = 1; i < lg(dec); i++) { GEN I = gel(dec,i); lord = algleftordermodp(al2,I,p); if (cmp_universal(lord,id)) break; } if (i==lg(dec)) break; al2 = gerepilecopy(av, alg_change_overorder_shallow(al2,lord)); zprad = algcenter_prad(al2, p, pre); projs = algcenter_p_projs(al2, p, pre); if (lg(projs) == 2) projs = NULL; dec = algpdecompose_i(al2,p,zprad,projs); } return al2; } static GEN algtracematrix(GEN al) { GEN M, mt; long n, i, j; n = alg_get_absdim(al); mt = alg_get_multable(al); M = cgetg(n+1, t_MAT); for (i=1; i<=n; i++) { gel(M,i) = cgetg(n+1,t_MAT); for (j=1; j<=i; j++) gcoeff(M,j,i) = gcoeff(M,i,j) = algabstrace(al,gmael(mt,i,j)); } return M; } static GEN algdisc_i(GEN al) { return ZM_det(algtracematrix(al)); } GEN algdisc(GEN al) { pari_sp av = avma; checkalg(al); if (alg_type(al) == al_REAL) pari_err_TYPE("algdisc [real algebra]", al); return gerepileuptoint(av, algdisc_i(al)); } static GEN alg_maximal(GEN al) { GEN fa = absZ_factor(algdisc_i(al)); return alg_maximal_primes(al, gel(fa,1)); } /** LATTICES **/ /* Convention: lattice = [I,t] representing t*I, where - I integral nonsingular upper-triangular matrix representing a lattice over the integral basis of the algebra, and - t>0 either an integer or a rational number. Recommended and returned by the functions below: - I HNF and primitive */ /* TODO use hnfmodid whenever possible using a*O <= I <= O * for instance a = ZM_det_triangular(I) */ static GEN primlat(GEN lat) { GEN m, t, c; m = alglat_get_primbasis(lat); t = alglat_get_scalar(lat); m = Q_primitive_part(m,&c); if (c) return mkvec2(m,gmul(t,c)); return lat; } /* assumes the lattice contains d * integral basis, d=0 allowed */ GEN alglathnf(GEN al, GEN m, GEN d) { pari_sp av = avma; long N,i,j; GEN m2, c; checkalg(al); if (alg_type(al) == al_REAL) pari_err_TYPE("alglathnf [real algebra]", al); N = alg_get_absdim(al); if (!d) d = gen_0; if (typ(m) == t_VEC) m = matconcat(m); if (typ(m) == t_COL) m = algleftmultable(al,m); if (typ(m) != t_MAT) pari_err_TYPE("alglathnf",m); if (typ(d) != t_FRAC && typ(d) != t_INT) pari_err_TYPE("alglathnf",d); if (lg(m)-1 < N || lg(gel(m,1))-1 != N) pari_err_DIM("alglathnf"); for (i=1; i<=N; i++) for (j=1; j R^{m*n} */ static GEN mat2col(GEN M, long m, long n) { long i,j,k,p; GEN C; p = m*n; C = cgetg(p+1,t_COL); for (i=1,k=1;i<=m;i++) for (j=1;j<=n;j++,k++) gel(C,k) = gcoeff(M,i,j); return C; } static GEN alglattransporter_i(GEN al, GEN lat1, GEN lat2, long right) { GEN m1, m2, m2i, M, MT, mt, t1, t2, T, c; long N, i; N = alg_get_absdim(al); m1 = alglat_get_primbasis(lat1); m2 = alglat_get_primbasis(lat2); m2i = RgM_inv_upper(m2); c = detint(m1); t1 = alglat_get_scalar(lat1); m1 = RgM_Rg_mul(m1,t1); t2 = alglat_get_scalar(lat2); m2i = RgM_Rg_div(m2i,t2); MT = right? NULL: alg_get_multable(al); M = cgetg(N+1, t_MAT); for (i=1; i<=N; i++) { if (right) mt = algbasisrightmultable(al, vec_ei(N,i)); else mt = gel(MT,i); mt = RgM_mul(m2i,mt); mt = RgM_mul(mt,m1); gel(M,i) = mat2col(mt, N, N); } c = gdiv(t2,gmul(c,t1)); c = denom_i(c); T = QM_invimZ_mod(M,c); return primlat(mkvec2(T,gen_1)); } /* { x in al | x*lat1 subset lat2} */ GEN alglatlefttransporter(GEN al, GEN lat1, GEN lat2) { pari_sp av = avma; checkalg(al); if (alg_type(al) == al_REAL) pari_err_TYPE("alglatlefttransporter [real algebra]", al); checklat(al,lat1); checklat(al,lat2); return gerepilecopy(av, alglattransporter_i(al,lat1,lat2,0)); } /* { x in al | lat1*x subset lat2} */ GEN alglatrighttransporter(GEN al, GEN lat1, GEN lat2) { pari_sp av = avma; checkalg(al); if (alg_type(al) == al_REAL) pari_err_TYPE("alglatrighttransporter [real algebra]", al); checklat(al,lat1); checklat(al,lat2); return gerepilecopy(av, alglattransporter_i(al,lat1,lat2,1)); } GEN algmakeintegral(GEN mt0, long maps) { pari_sp av = avma; long n,i; GEN m,P,Pi,mt2,mt; n = lg(mt0)-1; mt = check_mt(mt0,NULL); if (!mt) pari_err_TYPE("algmakeintegral", mt0); if (isint1(Q_denom(mt0))) { if (maps) mt = mkvec3(mt,matid(n),matid(n)); return gerepilecopy(av,mt); } dbg_printf(2)(" algmakeintegral: dim=%d, denom=%Ps\n", n, Q_denom(mt0)); m = cgetg(n+1,t_MAT); for (i=1;i<=n;i++) gel(m,i) = mat2col(gel(mt,i),n,n); dbg_printf(2)(" computing order, dims m = %d x %d...\n", nbrows(m), lg(m)-1); P = QM_invimZ(m); dbg_printf(2)(" ...done.\n"); P = shallowmatconcat(mkvec2(col_ei(n,1),P)); P = hnf(P); Pi = RgM_inv(P); mt2 = change_Rgmultable(mt,P,Pi); if (maps) mt2 = mkvec3(mt2,Pi,P); /* mt2, mt->mt2, mt2->mt */ return gerepilecopy(av,mt2); } /** ORDERS **/ /** IDEALS **/ pari-2.17.2/CHANGES-2.80000644000175000017500000013006314567450071012500 0ustar billbillBug numbers refer to the BTS at http://pari.math.u-bordeaux.fr/Bugs/ Done for version 2.9.0 (released 1/11/2016): Fixed 1- idealappr: allow flag for backward compatibility 2- nfisisom(x,x^0) -> SEGV BA 3- galoisgetpol: fix crash if some files are missing BA 4- [libpari] fix support for PARI_OLD_NAMES Done for version 2.8.1 (released 23/10/2016): Fixed 1- nfroots(non-monic t_POL) => wrong result [#1841] [from 2.8.0] 2- crash on BIB in ellpointtoz(t_PADIC) [#1840] 3- nfisideal(nfinit(x^2+1),[1,0;0,2]) -> 1 instead of 0 4- intnuminit(-oo,oo,1) -> error [#1847] 5- idealstar([f_0,f_oo]) for f_oo t_VECSMALL (place selection) didn't work 6- msinit objects could not be saved to file then read back in [from 2.8.0] 7- wrong value for bnrrootnumber for non-primitive characters [#1848] 8- allow znstar(N,flag) for idealstar(,N,flag) 9- allow znlog(x,G) for G = znstar(N), instead of ideallog(,x,G), for DL wrt. G.gen; in addition to traditional znlog(x,g), where an arbitrary generator g is specified 10- e=ellinit([1,-1,1,98,126],O(5^10)); ellpointtoz(e,[1,14]) -> div. by 0 11- ellpointtoz(E / Qp, P) was not reduced mod q^Z BA 12- [breakloop] changes done in the first-level breakloop were lost when leaving the second-level breakloop. 13- polinterpolate could create illegal objects [#1837] (test-case by PB) BA 14- [libpari] FqX_nbfact did not work 15- incorrect change of variable in elllocalred over a number field for places dividing 6 [from 2.8.0] 16- contfraceval([[],[]],1) -> SEGV [from 2.8.0] 17- agm(1.0, 1.0*I + x + O(x^200)) -> oo loop [#1654] 18- primepi(2750160) -> crash [#1855] 19- polinterpolate([],[],Mod(1,3)) => 0 instead of Mod(0,3) 20- subst(Pol(0),x,Mod(1,3)) => 0 instead of Mod(0,3) 21- subst(Pol(1),x,Mod(1,3)) => 1 instead of Mod(1,3) 22- e=znconreyexp(idealstar(,N),) could give a result with (e,N) = 2 when N = 2 (mod 4) [from 2.8.0] 23- idealprincipalunits(,,1) not supported [ concat error ] [from 2.8.0] 24- stack corruption in pollardbrent() at \g4 [#1858] BA 25- fflog could crash in char 2. [from 2.8.0] JD 26- is_universal_constant() made (possibly wrong) assumptions about memory layout (gen_0 < ghalf) BA 27- lfundiv(L1,L2): division by 0 if L2[6] (rootno) is 0. 28- inconsistent thresholds for zeta(2*n); e.g. at \p100000, zeta(22934) was much faster than zeta(22936) BA 29- [pthread] fix race conditions that caused memory corruption 30- rare SEGV in bnfisprincipal Added 1- permtonum: allow t_VECSMALL input 2- [libpari] Z_to_perm, perm_to_Z 3- [libpari] checkprid_i, is_nf_factor, is_nf_extfactor 4- extend ellissupersingular for E/nf 5- added a tag Obsolete: to the RFC822 description system (pari.desc) 6- new GP functions nfmodpr, nfmodprlift 7- [libpari] get_arith_Z, get_arith_ZZM 8- [libpari] Mod2, Mod4, Mod8, Mod16, Mod32, Mod64, umodi2n 9- [libpari] logint, logintall 10- [libpari] zk_inv, zkmultable_capZ, zkmultable_inv, nfC_multable_mul, zkC_multable_mul 11- [libpari] Idealstarprk 12- [libpari] ZpX_monic_factor 13- [libpari] nf_to_Fp_coprime 14- [libpari] idealprod, idealHNF_Z_factor 15- [libpari] rnfcomplete, rnf_build_nfabs, bnf_build_cycgen, bnf_build_units, bnf_build_matalpha 16- [libpari] rnf_zkabs 17- [libpari] get_nf_field (black box field arithmetic over a number field nf), nfM_det, nfM_inv, nfM_mul, nfM_nfC_mul 18- [libpari] bnftestprimes 19- [libpari] upr_norm 20- [libpari] bid_get_fact, bid_get_ind, bid_get_sarch, bid_get_sprk 21- [libpari] qfbforms 22- [libpari] nfroots_if_split 23- [libpari] nfmaxord_to_nf, nfinit_basic, nfinit_complete, idealprimedec_kummer, nf_deg1_prime 24- [libpari] ZNstar, znstar0, znlog0 25- GP function znchartokronecker 26- [libpari] ser_inv 27- allow ellztopoint for E/Qp BA 28- [libpari] F2x_factor_squarefree, F2xqX_factor, FlxqX_factor BA 29- [libpari] FlxXC_to_F2xXC, F2xXC_to_ZXXC 30- [libpari] pr_uniformizer, prV_lcm_capZ, pr_inv, pr_inv_p, pr_basis_perm 31- [libpari] cmp_padic 32- [libpari] ZV_snf_trunc, ZM_hnfmodall_i, ZM_hnfall_i, ZC_Z_div 33- [libpari] uisprime_101, uisprime_661 34- [libpari] lift_shallow 35- [libpari] rowsplice 36- GP functions bnflogef, bnflog, bnflogdegree, nfislocalpower, rnfislocalcyclo 37- [libpari] varnmin, varnmax 38- allow ellglobalred for E over a number field BA 39- [libpari] FpXQX_split_part BA 40- [libpari] ZpXQX_roots, ZqX_roots, ZqX_liftfact, ZqX_liftroot, Zq_sqrtnlift 41- [libpari] hash_dbg 42- [libpari] Qdivii, ceildivuu 43- GP function ellintegralmodel 44- [libpari] ZM_hnf_knapsack, hnf_invscale 45- [libpari] pol_xn, pol_xnall, retmkrfrac 46- allow lindep(vector of t_VEC), lindep(vector of t_COL) [#1857] 47- [libpari] famat_pow_shallow, famat_mulpow_shallow 48- [libpari] modRr_safe 49- [libpari] Z_ppo, u_ppo Changed 1- remove useless flag in idealappr: directly allow factorization 2- [libpari] idealappr0 is now obsolete: use idealappr 3- replace qfbil(x,y,{q}) by qfeval({q},x,y) and qfnorm(x,{q}) by qfeval({q},x): it makes more sense to have q first, and a single function for qf+polar form (as in all other qf-like routines: ellheight, etc.) 4- functions nfeltdivmodpr, nfeltmulmodpr, nfeltpowmodpr, nfeltreducemodpr, nfkermodpr, nfsolvemodpr are obsolete. Use nfmodpr, work in the finite field, then lift back using nfmodprlift. 5- split off historical refcard in submodules basic, ell, lfun, mf, nf 6- rewrite nfeltinv / nfeltdiv (use mult. table rather than polmod representation) 7- idealred algorithm (find small y in I^(-1), not in I) 8- bnf format (allow dynamically adding units): old bnfs will be detected as invalid. Dirty trick to force conversion: bnf[10]=vector(3); 9- nfelt* functions may now return scalars (t_INT/t_FRAC) in addition to t_COL on nf.zk basis. 10- remove flag = 2 in nfgaloisconj (slow, unreliable, obsolete for 15 years) 11- bnfcertify(K): use automorphisms (speedup roughly #Aut_Q(K)) 12- idealstar format, to access data more conveniently (and avoid recomputations): old bid and bnr structures from versions up to 2.8.0 are now invalid 13- narchstar output: include finf in output 14- set_sign_mod_divisor prototype: module is now useless (implicitly contained in sarch argument) 15- [libpari] removed discrayabs, discrayabscond, discrayrel, discrayrelcond, discrayabslistlong: obsoleted since 2.0 16- gcd(t_VEC/t_COL/t_MAT, ...) is now forbidden, same for lcm 17- E/Qp: add sequence of isogenous curves to structure (converges to the singular E_oo) => much faster ellpointtoz BA 18- ZpX_liftfact no longer handles extensions of Qp, use ZqX_liftfact 19- char_rootof1 renamed to rootsof1_cx, char_rootof1_u -> rootsof1u_cx 20- gp --test: consider that the session is not interactive BA 21- [libpari] rename listcreate to mklist 22- [libpari] rename idealinv_HNF -> idealHNF_inv, idealinv_HNF_Z -> idealHNF_inv, idealmul_HNF -> idealHNF_mul 23- [libpari] made famat_mul_shallow a true equivalent of famat_mul 24- move 'install' tests from test-program to test-install target 25- allow normlp(v, +oo) 26- [documentation] removed .ps files (use dvips -o if you need them); install dvis Done for version 2.8.0 (released 12/08/2016): Fixed 1- make install fails on OS/X: ln -s libpari.dylib libpari.dylib fails 2- Q_pvalrem(t_FRAC) => wrong result 3- [] == 0 but []~ != 0 (now []~ == 0 as well) [#1560] BA 4- test-kernel did not work when using --mt=pthread BA 5- ellheegner was using too much memory in some case 6- ellap can overflow on 32-bit machine [#1558] ellap(ellinit([582304190,64196421]),2147438927) -> overflow ellap(ellinit([-1137195,489565862]),2038074751) -> wrong result 7- nfhilbert(K,x,y, P above 2) could give wrong results [#1561] 8- rnfkummer sometimes failed to return an answer: error or oo loop. Relied on exhaustive enumeration of an Fp-vector space, some of whose elements would trigger an error. Replace by Fp-linear algebra that directly picks the correct line (O(d^3) algo instead of O(p^d), and no failures). Only compute the defining poly for the right element. XR 9- padicfields(huge p, d) was very slow [even though ramification is tame] 10- gcd(1/2, 1+I*1.) -> SEGV [#1563], 2.5.5 returned the wrong answer 1/2 11- mathnf(t_VEC) could corrupt input (change sign) 12- [libpari] RgM_transmul did not work 13- [libpari] Fq_issquare didn't support T=NULL 14- [libpari] nfpow_u didn't handle non-integral rational numbers 15- eint1(0) -> stack overflow [#1568] 16- liftint(List([0])) -> gerepile bug 17- factorint(n,flag): flag was ignored when n fit into a long 18- factor(n,lim): lim was ignored when n fit into a long 19- nfrootsQ(t_POL with leading coeff -1) could miss some solutions, e.g. nfroots(,-y^2-24476*y+119814917) -> [] instead of [-28657,4181] 20- precprime(1) -> invalid t_INT [#1576] 21- gaffsg(0, t_PADIC): wrong valuation 22- thue(f^e*g, ...), e even, (f,g)=1 missed solutions such that f<0 23- faster znlog when p-1 has only smallish prime factors. 24- (t_INTMOD with word-sized modulus)^(huge negative power) wrong [#1584] 25- (gp -p N) or (primelimit=N in gprc_ for N >= 436273290 resulted in an incorrect primetable. N.B. Such commands are now useless: needed primes are produced dynamically anyway. 26- monomial(exact zero, d, v) returned an invalid t_POL / t_RFRAC 27- contfracpnqn(v, n) returned partial quotients p[-1]/q[-1] ... p[n-1]/q[n-1], instead of the documented p[0]/q[0] ... p[n]/q[n] [#1580] 28- isprime(N, 0) was often slower than either of isprime(N, 1 or 2) 29- factor((3+4*I)/25) -> factor 2+I had 0 exponent [#1586] 30- made qfbclassno more reliable (fixes all counter examples in [#1411]) BA 31- iferr() could crash if some component of the t_ERROR were clones. 32- nffactor() could overflow the stack when default accuracy too low: e.g. nffactor(y^2-22, x^2+926246528884912528275985458927067632*y-4344481316563541186659879867597013188) 33- some elliptic curve functions accepted (elladd, ellmul) a Weierstrass 5-uple [a1,a2,a3,a4,a6] instead of an ell structure. No longer. Now only ellinit and ellchangecurve allow this syntax. 34- incorrect rounding in mulrr/divrr for one-word precision reals. BA 35- multiif did not handle correctly return() in conditions [#1590] 36- [0..5] -> [0,0,0,0,0] on some architectures 37- is_gener_Fp could return wrong results 38- Fq_sqrtn(t_INT,..,&zeta) could return a wrong root of 1 39- bnfinit: SEGV due to precision issues [#1592] 40- zm_zc_mul only worked for square zm matrices 41- genus2red(0,27*x^5+97*x^4+118*x^3+60*x^2+13*x+1,3) -> bug msg [#1596] 42- [gphelp] oo loop when $COLUMNS too small [#1594] 43- genus2red(x,-x^6-3*x^4-10*x^2-1,3) -> impossible inverse [#1597] 44- factoru(1) returned a t_MAT instead of the expected "matsmall" [#1598] 45- FpM_charpoly wrong in small characteristic [#1602] 46- Ser(Mod(0,2)) => incorrect object [#1587] 47- Ser(Mod(1,2)*x^2,,4) => incorrect precision [#1587] 48- Ser(x,v,prec < 0) => crash [#1587] 49- The t_SER Mod(0,2) + O(x^n) was not handled properly [precision and valuation would change unexpectedly] [#1587] 50- when compatible = 3; series() used a random precision 51- genus2red(0,6*x^6+5*x^4+x^2+1,7) -> impossible inverse [#1597] 52- isprime(2030967737887612953751815611955778057721609672149695775998900201419048774375002716065557720510887824952942799737911826638068045234238082640629966597954851668852106621828704531597859470496362810381251800973022824003330423370127762722630493369197869948901862977534730314352222720177713223750671181797) -> SEGV [#1604] 53- genus2red(x^3+1,1) -> type error [#1597] 54- gphelp did not handle === correctly [#1603] XR 55- bnrL1(bnrinit(bnfinit(x^2-168),[6,[1,1]],1)) -> bug in ArtinNumber[#1601] 56- FpXY_evaly() wrong when evaluating at 0 BA 57- [win32] gp could crash at start up [#1607] 58- nfisincl(t_POL, t_POL) could lead to wrong negative results 59- polresultant(1+x*z^2,1+y*z^4,z) -> GC error [#1614] BA 60- ellcard over non-prime fields of large char could return wrong results 61- [libpari] FpX_roots could produce GC errors [#1618] 62- weber(1+I) was missing its imaginary part 63- (1+I)*(1+1/2*I) => wrong result (type errors) [#1619] 64- contfracpnqn([a]) => [1,a;0,1] instead of [a,1;1,0] 65- primes([2^50, 2^50+200000]) => stack overflow 66- issquare((x+1/2)^2,&z); z => 1.0*x+0.5 instead of x+1/2 67- possibly wrong result in nfsnf 68- possibly missing roots in nfroots (when using Trager) 69- quadray(bnf, ideal) did not work 70- thue(-14*x^3 + 10*x^2 + 63*x - 5,1) -> "short continued fraction" [#1629] 71- thue(29*x^3+130*x^2-35*x-48,1) -> "round error" bug 72- T=thueinit(10*x^3+6*x^2-41*x+8,1); thue(T,8) => SEGV [#1630] 73- ellrootno(e,p = 2 or 3) when e not minimal at p => random result 74- catastrophic cancellation in ellheight (at oo) [#1637] 75- bnfnewprec could return a corrupt bnf structure: K=bnfinit(x^3-15667*x^2-88630960*x-1836105977032,1); bnfisprincipal(K,[29,14,15;0,1,0;0,0,1],3) -> oo loop 76- agm(1,2+O(5)) -> SEGV [#1645] BA 77- [cygwin64] ellap(ellinit([0,0,1,-1,0]),10007) broken 78- primes([-5,5]) -> [5] (spurious absolute values) 79- matqr([;]) -> crash 80- Fp_rem_mBarrett could return a non-normalized result p=436^56-35;Mod(271,p)^((p-1)/2) -> p+1 81- plotcopy would corrupt "string" objects (ROt_ST) BA 82- [GP] default arguments to GP functions could cause corruption [#1658] VBr83- [darwin] remove obsolete linker options that cause crashes [#1623] 84- divisors([2,1]) -> SEGV [#1664] 85- acos([Pol(1)]) -> GC bug [#1663] 86- matsolve(a,b) and a^(-1) gave wrong results [or SEGV] when t_MAT a was not square and a,b "modular" (F2m,Flm,FpM,FqM,F2xqM,FlxqM) same for x^(-1) [#1666] 87- primes([1,Pol(2)]) -> SEGV [#1668] 88- znlog(0,Mod(1,4),1) -> 0 (instead of []) 89- polzagier / sumalt(,1) / sumpos(,1) were slow and used too much memory 90- sumpos was wasting time when pre-computing \sum 2^e a(k*2^e) [ only needed for k odd, but was also done for k = 0 mod 4 ] + improve accuracy 91- intnum(x=[0,-1/2],[oo,-3/2],1/(sqrt(x)+x^(3/2))) -> junk t_COMPLEX (more generally: one endpoint has an algebraic singularity and the other is +-oo, non-oscillatory 92- intnum(x = [-oo,-3/2], [oo,-5/2], f(x)) --> loss of accuracy due to confusion between endpoint behaviours a/b in intnuminit data E.g. f(x)=(x<0,1/(1+(-x)^(3/2)), 1/(1+x^(5/2))); 93- intnum(x = [-oo,-3/2], [oo,-5/2], f(x)) --> loss of accuracy due to confusion between endpoint behaviours a/b in intnuminit data E.g. f(x)=(x<0,1/(1+(-x)^(3/2)), 1/(1+x^(5/2))); 94- intnum(x=[0,-1/2],[1,-1/3], x^(-1/2) + (1-x)^(-1/3)) -> error [didn't suport singularities at both endpoints] 95- buffer overflow after default(format,"f.precision") (whenever many initial zeroes) 96- qfminim(A, 0, ...) -> stack overflow [#1682] 97- e=ellinit("11a1"); ellztopoint(e,3*e.omega[1]/5) -> [5, junk] (instead of expected [5,5]) [#1683] 98- bnfinit(quadhilbert(-2180)) -> precision error [#1688] 99- div_scal_rfrac could create an invalid t_POL [#1651] 100- polroots(t_POL with leading coeff = 0) -> fp exception or error [#1690] 101- \r cannot deal with very long filenames [#1616] 102- rnfisabelian(nf, non monic t_POL) -> SEGV [#1693] 103- Vecrev(x,n) / Colrev(x,n) when 'n' is not omitted: it wasn't true that Colrev/Polrev were inverse functions [#1698] 104- possibly incorrect result in nfdisc(T,listP) even though listP included all prime divisors of the field discriminant. Example: p=10^100+267; q=10^120+79; T=polcompositum(x^2-p,x^2-q,2); nfdisc([T,[2,p,q]]) 105- wrong dim(Ker) returned by ZM_pivot => SEGV in Z-linear algebra routines. E.g. setrand(1);quadclassunit(-612556842419) [#1700] 106- moebius(factor(18)) -> 1 instead of 0 [#1702] 107- ispower(-167^10) => domain error [#1703] 108- ispowerful(factor(0)) != ispowerful(0) 109- expm1(2*I) => wrong result 110- gamma(1+a*x+O(x^2)) => error [#1707] 111- printsep() printed its argument in random format, instead of f_RAW as print() [#1708] 112- nfdisc(x^10 - 29080*x^5 - 25772600) -> oo loop [#1710] 113- forprime engine could skip (fast) sieve in favour of (slow) nextprime [#1711] 114- 0^[1] -> domain error [#1713] 115- memory leaks (clones) in ellchangecurve [#1716] 116- zeta inaccurate around 0 [ from 2.7 ], [#1714] 117- ellj(simple t_SER in 'x) much slower than in other variable [#1720] 118- bnrrootnumber did not support the trivial character in the form [0,..,0] 119- default(log,1) when logfile is write-protected later lead to SEGV [#1730] BA120- 2-adic gamma function: fix accuracy loss 121- A==A -> 0 for A a t_SER of huge accuracy (so that A-A overflows valuation) [#1734] XR122- P=[1,-2,12,-12,-181,-4,-6899,9780,6360,702,-45]; setrand(3); nfdisc(P) -> wrong answer [ crash if setrand(138) ] [#1735] 123- select(x->x,Vecsmall([1,2,3]),1) -> crash [#1737] 124- (1./x+O(1))-(1./x+O(1)) -> 0.E-38*x^-2+O(x^-1) [#1741] BA125- [libpari] RgV_to_RgX_reverse did not work if v[1] or v[2] was 0 126- bnfinit(x^3-87156*x^2-6728799*x-456533) [#1736] 127- Rg_to_ff: incorrect type in zk_to_ff [#1755] BA128- nfsubfields could fail [#1758] 129- rare SEGV in ArtinNumber [#1759] 130- K.codiff incorrect if [K:Q] > 2 131- chinese([]) -> '1' instead of Mod(0,1) 132- m1=Mod(0,1);m2=Mod(1,x^2+1); chinese(m1,m2) -> m1; chinese(m2,m1) -> m2 [instead of error] 133- nfrootsof1(polcyclo(85)) -> 85 instead of 170 [#1766] 134- at \p19, polroots((x+1)^2 * (x-1)^7 * (x^2-x+1)^5 * 1.0) -> SEGV [#1767] BA135- ellsea returned the trace instead of the cardinal as documented. BA136- ellsea(,,1) could return a wrong result [#1768] 137- rnfconductor: sanity checks were not taken into account MC138- memory leak in pari_close: sopath not freed HC139- incgam(30,60) < 0. More generally, wrong results for s >> 1 [#1689] HC140- excessive loss of accuracy in incgam, incgamc, eint1 141- isprimepower(30011^(3*17)) returned 0 142- a = Mod(1,x); z = Mod(0,Pol(1)); chinese(a, z) works but chinese(a, simplify(z)) failed BA143- [mpi] interrupt/alarm could caused a crash BA144- [mpi] relinking empty t_LIST caused a crash 145- ispower(t_POL) didn't work in small characteristic [#1779]; make it work over finite fields BA146- my(s=1,a=0);forstep(i=1,20,s,s++;a+=i);a -> wrong result KR147- gphelp -detex: accented letters counted as 1 char for line splitting but rendered as 2 148- sqrt(0) -> loss of accuracy (sqrtn was correct) 149- nfgaloisconj(t_POL T) was unnecessary slow when large divisors of disc(T) were internally detected (and subsequently ignored) BA150- elltatepairing could return wrong results [#1784] 151- padicappr(x^3+1,-2+O(2^5)) -> SEGV [mod a root mod p] [#1793] 152- K = bnrinit(bnfinit(y^2-5),[1,[1,1]]); bnrdisc(K) -> wrong [#1804] 153- ellztopoint(ellinit([-1,0]), I) -> wrong result [#1800] Potentially affected all elliptic functions (ellwp,ellzeta,ellsigma) at real or pure imaginary arguments. 154- gamma(2+x) did not start with an exact 1, unlike gamma(1+x). lngamma(2+x) didn't have valuation 1 155- gamma(t_INT+x) at large accuracy and seriesprecision was very slow, even for small t_INTs (same for lngamma and psi). E.g. at \p1000 gamma(1000+x+O(x^100)) 156- a=Mod(y,y^2+1); Mod(a, x^2-2) == a returned 0 [#1806] 157- x \/ y did not conform to documentation when either x or y was a t_REAL. E.g. 28/10 \/ 1 == 3 but 2.8 \/ 1 == 2. Now both return 3 [#1811] BA158- digits(N,B) with 31/63 bit B could return wrong result BA159- [pthread] parallel GP could leak memory 160- ellinit(E, O(p^n)) was slightly incorrect for E / Q [ started by approximating exact equation mod p^something instead of keeping everything exact ] 161- ellinit(E, O(2^n)) was hardly supported, e.g. ellinit("14a1",O(2^5)).tate => precision too low in p-adic AGM. BA162- polrootsmod(x^3-1, not a prime) -> SEGV (BIB) BA163- [windows] MPQS could fail due to temporary files 164- matsnf([27, 0; 0, 3; 1, 1; 0, 0],1+4) -> SEGV 165- gcd(Mod(1,2)*x+Mod(1,2), Mod(0,2)) -> Mod(1,2) 166- qfperfection() only allowed matrices of small norm [#1719] 167- wrong formula for poldisc when characteristic divides degree [#1831] 168- wrong result for poldisc(ZX) in huge degree [#1830] 169- missing typechecks in ellheight() [SEGV on BIB] 170- ellminimalmodel() didn't use a coprime bases so that it was very slow for [c4,c6] = [p^5*q, p^6*q] for huge p and q BP171- ellpointtoz(E / Qp) was totally wrong [#1833] 172- genus2red(177*x^6+126*x^5-63*x^4+72*x+84) -> bug in labelm3 [#1826] 173- normalize genus2red stable reduction output: a type K1-K2-r now guarantees K1 <= K2 (before both K1-K2-r and K2-K1-r could occur) 174- gmulsg(0, 1+O(x)) -> O(x^0) instead of t_INT 0 as in gmul(gen_0, ...) Added 1- add optional argument to sumdigits to specify the base 2- [libpari] bits_to_int,bits_to_u,binary_zv,binary_2k,binary_2k_nv BA 3- [GP] support for variadic GP functions (f(v[..])=expr) 4- nfeltval(K, x, pr, &y) now takes an optional 4th argument, containing the part of x coprime to pr. BA 5- [libpari] New functions family RgXn: new functions RgXnV_red_shallow, RgXn_powers, RgX_RgXnV_eval, RgX_RgXn_eval, RgXn_reverse, RgXn_inv, RgXn_exp BA 6- [libpari] New functions Flv_inv BA 7- [libpari] New functions Flx_Flv_eval, Flv_Flm_polint, FpX_FpV_eval, FpV_FpM_polint WH 8- [libpari] New low-level functions get_Fl_inv, remll_pre BA 9- [libpari] New low-level functions Fl_sqr_pre, Fl_mul_pre, remlll_pre, Fl_powu_pre, Fl_sqrt_pre, divll_pre, random_Fle_pre 10- [TeX documentation] new primitive \url (verbatim arg) 11- [libpari] New functions Fq_log, gener_Fq_local BA 12- GP functions bnrisgalois, bnrgaloismatrix, bnrgaloisapply LGr13- GP function polrootsreal 14- GP constant "oo" (for +/- infinity) 15- [libpari] New functions mkoo, mkmoo, inf_get_sign 16- [libpari] New functions ellbasechar, ec_f_evalx, ec_dfdx_evalQ, ec_dfdy_evalQ, ec_2divpol_evalx, ec_half_deriv_2divpol_evalx, ec_h_evalx, ec_dmFdy_evalQ, ec_bmodel HIL17- GP functions ellisogeny, ellisogenyapply 18- [libpari] New function RgX_coeff BA 19- [libpari] New functions Fl_halve, Fp_halve, Flx_halve, Fq_halve BA 20- [libpari] New functions vecsmallpermute, vec_append 21- GP functions qfsolve, qfparam [ adapted from Denis Simon's qfsolve.gp ] 22- [libpari] New function ZM_transmul 23- allow elliptic curves over number fields: ellinit([a1,...,a5], nf) 24- [libpari] ZX_sturm, ZX_sturmpart, RgX_sturmpart 25- [libpari] RgXQV_RgXQ_mul 26- thue / thueinit now also support (powers of) imaginary quadratic equations BA 27- [libpari] ZpX_ZpXQ_liftroot, ZpX_ZpXQ_liftroot_ea 28- [libpari] fuse_Z_factor 29- ellformalw, ellformalpoint, ellformaldifferential, ellformallog, ellformalexp, ellnonsingularmultiple, ellpadicheight, ellpadicheightmatrix, ellpadics2, ellpadiclog BA 30- [libpari] functions FpX_powu, FpX_digits, FpX_fromdigits, FpXQX_powu, FpXQX_digits, FpXQX_fromdigits, FqX_powu BA 31- GP functions ellpadicfrobenius, hyperellpadicfrobenius, hyperellcharpoly 32- [libpari] function RgX_normalize BA 33- much faster matfrobenius/minpoly(t_MAT) BA 34- prototype codes U and u for ulong 35- allow testing for BITS_IN_LONG in gprc 36- GP functions msinit, ellpadicL BA 37- [mingw] support for the alarm GP function BA 38- [libpari] functions Fl_sqrtl, Fl_sqrtl_pre 39- [libpari] function ZV_allpnqn 40- [libpari] function Qevproj_init, Qevproj_apply, Qevproj_apply_vecei 41- [libpari] functions G_ZGC_mul, G_ZG_mul, ZGC_G_mul, ZGC_Z_mul, ZG_G_mul, ZG_Z_mul, ZG_add, ZG_mul, ZG_neg, ZG_normalize, ZG_sub, ZGC_G_mul_inplace, ZGCs_add 42- [libpari] function kroui BA 43- GP function powers and libpari function gpowers 44- flag LLL_COMPATIBLE for LLL routines [ use 64-bit compatible accuracies only ] BA 45- [libpari] functions FpX_Frobenius, FpX_matFrobenius, Flx_Frobenius, Flx_matFrobenius, ZpX_Frobenius, F2x_Frobenius, F2x_matFrobenius 46- [libpari] function ser_isexactzero BA 47- [libpari] functions ZV_chinese, Z_ZV_mod, Z_nv_mod, nmV_chinese_center BA 48- GP function fromdigits BA 49- [libpari] functions Zp_sqrt, ZpXQ_sqrt 50- GP functions mscuspidal, mseisenstein, msnew, mssplit, msqexpansion, mshecke, ellmsinit, msatkinlehner, msstar, mseval, mspathgens, mspathlog, msissymbol, msfromcusp, msfromell BA 51- GP declaration localprec(), localbitprec() HIL52- [libpari] functions Fl_powers_pre, Fl_ellj_pre, Fl_elldisc_pre, Fl_elltwist_disc BA 53- [libpari] functions Fl_powers, Fp_powers, Fl_ellj, Fl_elldisc, Fl_ellj_to_a4a6, Flxq_ellj_to_a4a6 BA 54- [libpari] functions FpXQX_div_by_X_x, FqX_div_by_X_x HIL55- [libpari] function Flx_oneroot_split, zxX_to_FlxX, RgXY_degreex BA 56- [libpari] functions Flv_inv_pre, Flv_inv_inplace, Flv_inv_pre_inplace HIL57- GP function ellissupersingular HIL58- [libpari] functions Fp_elljissupersingular, FpXQ_elljissupersingular BA 59- [libpari] functions umodsu, zx_to_Flx, corediscs 60- GP function qfbredsl2 61- [libpari] functions ell_is_integral, ellintegralmodel, ellQ_get_CM, ellorder_Q, ellap_CM_fast, point_to_a4a6, point_to_a4a6, Fl_elltrace_CM, Fle_changepoint, Fle_changepointinv, Fle_log 62- allow elltors and ellorder for E/K number field 63- GP function ellxn, ellisdivisible HIL64- [libpari] function family Flj_* 65- [libpari] idealprimedec_limit_f, idealprimedec_limit_norm 66- [libpari] modpr_get_p, modpr_get_T, modpr_get_pr 67- GP function nfsplitting HIL68- [libpari] functions Flv_dotproduct_pre, Flx_eval_pre, Flx_eval_powers_pre, FlxY_eval_powers_pre, FlxY_evalx_powers_pre HIL69- GP functions polclass, polmodular BA 70- ellcard over fields of medium characteristic (SEA, Kedlaya, Satoh) 71- GP functions varhigher() / varlower() / variables() BA 72- GP function self() (for defining recursive anonymous functions) BA 73- GP function fold() 74- [libpari] hash_create_ulong, hash_create_str, hash_select, hash_remove_select, hash_keys, hash_values 75- allow serlaplace(t_POL) 76- GP function ispseudoprimepower 77- [libpari] functions FpM_add, Flm_add, FpM_Fp_mul, RgMrow_zc_mul 78- [libpari] function nfembed, nfissquarefree 79- new binary flag to polcompositum: assume fields are linearly disjoint 80- GP function nfcompositum AP 81- [GP] associative and central simple algebra package, functions algabsdim algdisc algisramified algrandom algadd algdivl algissemisimple algrelmultable algalgtobasis algdivr algissimple algsimpledec algaut alghasse algissplit algsplittingdata algb alghassef algleftmultable algsplittingfield algbasis alghassei algmul algsplittingmatrix algbasistoalg algindex algmultable algsqr algcenter alginit algneg algsub algcentralproj alginv algnorm algsubalg algchar alginvbasis algpoleval algtableinit algcharpoly algisassociative algpow algtensor algdecomposition algiscommutative algprimesubalg algtrace algdegree algisdivision algquotient algtype algdim algisdivl algradical algisinv algramifiedplaces 82- [libpari] functions rnf_get_alpha, rnf_get_idealdisc, rnf_get_k 83- [libpari] functions ZC_is_ei, RgC_is_ei, ZM_Z_div, ZMV_to_FlmV, checkal 84- [libpari] functions cbrtr, cbrtr_abs 85- nfinit(rnf) now returns an nf structure associated to rnf.polabs 86- idealprimedec now allows an optional 3rd argument, to limit f(P/p) 87- [libpari] cb_pari_err_handle callback 88- [libpari] function nf_get_ramified_primes 89- Configure --with-runtime-perl option PB 90- Faster matrix multiplication over finite fields 91- allow content(t_VECSMALL) 92- [libpari] ZX_div_by_X_1 HC 93- intnumgauss / intnumgaussinit: Gauss-Legendre quadrature LGr94- GP function sinc HC 95- contfracinit / contfraceval functions HC 96- limitnum / asympnum BA 97- [libpari] functions FlxV_prod, RgV_prod BA 98- GP function ellfromeqn HC 99- gammamellininv, gammamellininvasymp, gammamellininvinit BA 100- [libpari] RgX_Rg_eval_bk, RgX_RgV_eval, RgXV_RgV_eval 101- [libpari] RgX_cxeval HC 102- GP function zetamult PB 103- ZM_mul: Add Strassen-Winograd algorithm 104- GP functions sumnummonien/sumnummonieninit 105- [libpari] RgM_gram_schmidt, RgM_Babai BA 106- GP function cotanh 107- support sign(t_QUAD with positive discriminant) 108- comparison operators (<,>,<=,>=): support t_QUAD with *same* positive discriminant BA 109- [libpari] Flv_prod, Flv_prod_pre BA 110- [libpari] Flv_neg, Flv_neg_inplace ED 111- mingw64 support BA 112- [parallel] new GP function parforvec BA 113- [libpari] Fl_addmul_pre, Fl_addmulmul_pre BA 114- [libpari] Fl_eltwist, Fp_elltwist, FpXQ_elltwist, Flxq_elltwist, F2xq_elltwist BA 115- GP functions elltwist, ellminimaltwist 116- [libpari] omegau, bigomegau VB 117- GP support for 0xffff and 0b1111 (input t_INT in binary or hex notation) BA 118- GP functions ellisomat HC 119- GP function ramanujantau PB 120- Speed up {Flx,FpX,FpXQX}_divrem_basecase for modulus of the form x^n+O(x^m) with m small HC 121- GP function solvestep 122- [GP] New lfun family of functions lfun lfundiv lfunmfspec lfunabelianrelinit lfunetaquo lfunmul lfuntheta lfunan lfunhardy lfunorderzero lfunthetainit lfuncheckfeq lfuninit lfunqf lfunzeros lfunconductor lfunlambda lfunrootres lfunartin lfuncreate 123- [libpari] nfchecksigns, idealchineseinit JD 124- [libpari] gp_read_str_multiline BA 125- [libpari] Flx_nbfact_Frobenius, FpX_nbfact_Frobenius 126- extend idealchinese() to impose sign conditions at specified real places [#1501] 127- [libpari] qfb_equal1, qfi_order, qfi_log, qfi_Shanks 128- [libpari] RgV_kill0 BA 129- factorcantor: use Shoup-Kaltofen algorithm (much faster) BA 130- [libpari] FpX_dotproduct, Flx_dotproduct JK 131- FpXQ_minpoly/Flxq_minpoly: use Shoup algorithm (much faster), and do not assume modulus is irreducible BA 132- [libpari] idealramfrobenius, idealfrobenius_aut, nfgaloispermtobasis 133- Allow ??lfun, ??Lmath, etc. [#1753] 134- [libpari] cyc_normalize, char_normalize, char_check, char_rootof1, char_rootof1_u, bnrchar_primitive, bnrconductor_i 135- GP functions charker, bnrchar 136- bnrconductor(bnr, chi) as a shortcut for bnrconductor(bnr, Ker chi); same for bnrisconductor, bnrdisc and bnrclassno 137- [libpari] real_1_bit(), grootsof1() PB 138- [libpari] Flm_sub, FpM_sub BA 138- [libpari] get_FpXQX_mod, get_FpXQX_degree, get_FpXQX_var, FpXQX_get_red, FqX_get_red, random_FpXQX BA 139- [libpari] get_FlxqX_mod, get_FlxqX_degree, get_FlxqX_var, FlxqX_get_red, random_FlxqX BA 140- Prototype code 'b' and default 'realbitprecision' 141- \pb shortcut [ manipulate realbitprecision ] BA 142- [GP] Map, mapget, mapput, mapisdefined, mapdelete BA 143- [GP] bitprecision BA 143- [arm64] add aarch64 assembly kernel 144- [libpari] ZV_snf_group, ZV_snfall 145- [libpari] znstar0 with Idealstar semantic; could be made available under GP as default znstar, but current znstar/idealstar have incompatible defaults. Called by idealstar(,N). 146- [GP] znconreychar, znconreyexp, znconreylog, znconreyconductor, charorder, charconj BA 147- [GP] call (for calling closures). 148- [GP] optional flag to forell [ loop over isogeny classes ] 149- lfunthetacost, lfuncost SCh150- [mingw] timer: support for user time JD 151- [libpari] pari_completion interface for readline SCh152- [mingw+pthread]: default nbthreads support 153- teichmuller([p,n]) to cache all value at i + O(p^n), 1 <= i < p 154- optional argument 'tab' to teichmuller(x) 155- [GP] function chareval, charmul, chardiv, zncharinduce, zncharisodd 156- [libpari] Flm_intersect 157- [libpari] ggamma1m1 158- allow ispower(t_POLMOD representing a finite field element) 159- [libpari] Fq_ispower, FqX_ispower, RgX_deflate_order, Fq_to_FF, FqX_to_FFX 160- [libpari] Z2_sqrt, divisorsu_fact, usumdiv_fact, usumdivk_fact 161- gphelp -detex: new flag -utf8 to allow utf-8 encoding in output, e.g. render \'{e} as é (the actual eight-bit char) instead of 'e 162- GP function msfromhecke, msgetlevel, msgetweight, msgetsign BA 163- qfisominit: allow to pass the matrix of minimal vectors [#1656] 164- [libpari] GENtostr_raw BA 165- [libpari] FlxqX_halfgcd, FpXQX_halfgcd 166- issquare(t_POLMOD of t_INTMOD) assuming a finite field 167- RgXn_powu, RgXn_powu_i 168- [libpari] is_real_t, R_abs, R_abs_shallow BA 169- [libpari] F2xX, F2xqX, F2xqXQ family functions 170- GP functions rnfidealprimedec, rnfidealfactor BA 171- [libpari] get_FpX_algebra, get_FpXQ_algebra, get_FpXQX_algebra, get_FlxqXQ_algebra, get_FpXQXQ_algebra, get_Rg_algebra 172- E/Qp: Added Mazur-Tate-Teitelbaum's L invariant to E.tate BA 173- [libpari] ZpXQ_div, ZpXQX_divrem, ZpXQX_digits 174- [libpari] ZX_deflate_max, ZX_deflate_order 175- [libpari] idealinv_HNF, idealinv_HNF_Z 176- [libpari] QM_charpoly_ZX_bound BA 177- libpari support for low-res plot() 178- GP function serprec 179- ellap(E, p), ellcard(E,p) for E/K number field, and p maximal ideal 180- [libpari] function sertoser 181- ellan(E, n) for E/K number field 182- [libpari] function gisexactzero BA 183- GP function ellsea 183- [libpari] nfsub, Rg_RgC_sub, Rg_RgC_sub, Z_ZC_sub 184- [libpari] zkchinese, zkchinese1, zkchineseinit 185- [libpari] vecsmall_reverse 186- [libpari] Z_ppio, Z_ppgle, Z_cba 187- ellminimalmodel over number fields 188- [libpari] FpX_factor_squarefree, Flx_factor_squarefree 189- [libpari] checknf_i, checkbnf_i, checkbid_i, checkrnf_i Changed 1- make log(+/-I) return (+/-)Pi/2*I with gen_0 real part [#1556] BA 2- [libpari] rename RgX_mullow -> RgXn_mul, RgX_sqrlow -> RgXn_sqr, RgX_modXn_eval -> RgXn_eval, RgX_modXn_shallow-> RgXn_red_shallow 3- change rnfnormgroup to return [;] instead of raising an error whenever it detects a problem (modulus not a multiple of the conductor, non-abelian extension...): this is a BIB with undefined result, but returning a sentinel is more useful *if* we notice it. 4- [gp] uniformize errors from the % history operator (SYNTAX->MISC) [#1553] 5- t_STR used to compare as larger than any real number via < or > operators. Such a comparison now raises an exception. 6- valuation(0,p), nfeltval(nf,0,pr), idealval(nf,0) now all return +oo poldegree(0) now returns -oo BA 7- rootpadicfast renamed ZpX_roots 8- nfinit: switch from sturm() to ZX_sturm() [Uspensky], and from polroots to polrootsreal (totally real fields). polsturm() now uses Uspensky in most cases. 9- polsturm interface change - polsturm(T, a, b) is still supported but deprecated, use polsturm(T, [a,b]) - polsturm(T, a, b) used to return the number of roots in ]a,b], we now use the closed interval [a,b]: more intuitive given the new syntax, and compatible with polrootsreal() BA 10- [libpari] mkintn: handles arguments as 32bit unsigned int 11- nfdisc, nfbasis: no longer support the old (T,flag,fa) arguments. Use the generic [T,listP] syntax (see 2.6.0-C105) 12- factorpadic: no longer support the deprecated (no-op) 'flag' argument 13- thue() sort solutions lexicographically 14- thueinit tnf format: always include a bnf (also when r1=0), to allow checking for norm equation solutions first: e.g. thue(x^4+1,7*10^80) becomes instantaneous instead of overflowing BA 15- Flx_pow renamed to Flx_powu 16- optional flag to ellheight is gone (useless) 17- ellbil(E,P,Q) is now deprecated, use ellheight(E,P,Q) 18- [libpari] rename ghell->ellheight, mathell->ellheightmatrix BA 19- Rg_to_RgV renamed to Rg_to_RgC, RgX_to_RgV renamed to RgX_to_RgC 20- ellL1(e, r): make r optional (default value = 0) BA 21- powruvec is replaced by powersr 22- [libpari] merge_factor no longer keeps entries with exponent 0 Pmo23- More robust and much faster ellL1 and ellanalyticrank. The condition ord(L_E,s=1) <= r in ellL1(E,r) is no longer necessary. 24- renamed ZV_gcdext -> ZV_extgcd for consistency with other gcdext methods BA 25- setrand now return a (huge) integer instead of a vecsmall 26- unify 32/64 bit random generators. Probabilistic algorithm should now behave identically on all architecture, provided they do not involve the floating point kernel 28- unify 32/64 bit tests 29- move extern(), externstr(), readstr() and system() to the generic part of GP language (was gp-specific). This allows to use them in parallel mode and under gp2c [#1593] 30- made cmprr, cmpri, equalrr consistent with == semantic. We now have, e.g., 0e1==1.0 and (0e1 < 1) = 0 (since 1-0e1 evaluates to 0e1) 31- [libpari] comment out function names obsoleted during the 2.3.* cycle (2007). See PARI_OLD_NAMES. 32- default 'strictmatch' has been obsoleted. It is now a no-op. 33- default 'compatible' has been obsoleted. It is now a no-op. 34- zeta(odd integer): use Borwein's "sumalt" algorithm (10 times faster than previous at \p1000) 35- elltors flags are now deprecated (and ignored, removed corresponding code) 36- add optional flag to nfhnf / nfsnf: return transformation matrices 37- nfroots/nffactor: factor polynomials in Q[X] over Q first BA 38- much faster polresultant over Z 39- GP and libpari polynomial variables of arbitrary priority can now be created: 'x' is no longer guaranteed to have maximal priority, nor MAXVARN to have minimal priority. 40- GP: polynomial variable 'y' is now always defined on startup, with priority lower than 'x' 41- Allow ffgen([p,f]) in addition to ffgen(p^f) and ffgen(T*Mod(1,p)) 42- thue() needed to compute to huge accuracies when regulator was large E.g. t=thueinit(15*x^3+8*x^2-95*x+24,1); thue(t,8) 43- rnf structures may now contain a full absolute nf struct ('nfabs') 44- matkerint: replace underlying LLL algorithm by mathnf Simple bench: M=matrix(50,55,i,j,random(10^5)); \\ 200 times faster 45- allow t_VECSMALL vector exponents in gen_factorback 47- [libpari] rename 'define' PI -> M_PI and use proper constant 48- no longer print 0 t_POLMOD as "0", bug e.g. Mod(0,x). Uniformize code and behaviour with t_INTMOD. 49- warn when coercing quotient rings when 'debug' non-zero ? \g1 ? Mod(1,2)+Mod(1,3) *** _+_: Warning: coercing quotient rings; moduli 2 and 3 -> 1. 50- content([]) -> 0 [ was 1 ] 51- [] / 0 => div. by 0. Now returns [] (as [] \ 0 already did) LGr52- use GRH-guaranteed bounds in bnfinit for residue estimate 53- Configure: avoid inserting unnecessary -L arguments in link line 54- genus2red: change syntax. Allow either genus2red(P) or genus2red([P,Q]) instead of mandatory Q (was: genus2red(Q,P) with Q almost always 0). Allow uniformization with hyperellcharpoly 55- old functions from gp-1.39.15 no longer loaded into an "entree" table, no longer complete specially "whatnow" arguments; remove compat.c and most of gp_init.c BA 56- Rename row_Flm -> Flm_row, row_zm -> zm_row 57- rewrote intnum / intnuminit routines 58- nucomp now takes L = floor(|D|^(1/4)) as a 3rd argument. Former nucomp(x,n) is nucomp(x,n,NULL). BA 59- divide_conquer_assoc renamed to gen_product 60- sumnum algorithm (replace Abel-Plana by Euler-Mac Laurin). Changed the interface ! BA 61- [libpari] concat, concat1 renamed to gconcat, gconcat1 62- rnfconductor now returns [cond, bnr, H] instead of [cond, bnr.clgp, H] 63- nfrootsof1(), more stringent ramification tests: looking for a subfield Q(zeta_p^k) is now faster. 64- intnumromb to use realbitprecision 65- idealstar / ideallog: allow omitting 'nf' argument (for nf = Q; use znstar and znlog internally) 66- improved p-adic log at high accuracy (O(sqrt(padicprec)) algorithm instead of O(padicprec)) 67- allow genus2red to handle (rational) non integral models KR 68- new version of misc/xgp BA 69- rename Flc_Fl_mul -> Flv_Fl_mul, Flc_Fl_div -> Flv_Fl_div, RgC_to_Flc to RgV_to_Flv, F2c_to_Flc to F2v_to_Flv 70- rename leading_term -> leading_coeff, constant_term -> constant_coeff 71- improve gamma(a+O(x)) BA 72- Z_to_Flx now takes a shifted variable number, as Fl_to_Flx. BA 73- improve hash_GEN to reduce # of collisions (change glue) 74- added explicit ways to attach an absolute nf to a rnf structure, allowing rnf functions to return objects in standard notation (e.g. ideals in HNF instead of as a vector of t_POLMOD generators). Add optional flag to rnfeltabstorel, rnfeltdown, rnfeltup, rnfidealreltoabs, rnfinit BA 75- rename FlxqX_pow to FlxqX_powu 76- polredabs([T,listP]) no longer returns 0 if the attached order cannot be proven to be maximal: it computes the expected canonical polynomial in all cases, which can be very slow. Always use polredbest() if you don't require a canonical output. 77- polredabs(T) now internally uses the polredabs([T,listP]) strategy, making it much faster in favourable cases, while still always returning a canonical defining polynomial. 78- precision(0), bitprecision(0), padicprec(0,p) now all return +oo under GP [ used to return LONG_MAX ] 79- meaning of precision(x, n) no longer depends on the type of x: it now always refers to floating point precision. Before the change: precision([O(2),O(3),O(x)], 10) -> [O(2^10),O(3^10),O(x^10)] 80- infinite slopes of newtonpoly replaced by "+oo" (instead of 2^63-1) 81- rename anell -> ellan, anellsmall -> ellanQ_zv BA 82- Fp_ellcard_SEA/Fq_ellcard_SEA meaning of flag has changed. 83- renamed absi_cmp -> abscmpii, absr_cmp -> abscmprr, absi_equal -> absequalii, absi_factor -> absZ_factor, absi_factor_limit -> absZ_factor_limit, equaliu -> absequaliu, equalui -> absequalui, cmpiu -> abscmpiu, cmpui -> abscmpui Removed 1- deprecated functions nfbasis0, nfdisc0, factorpadic0 2- deprecated function manage_var 3- useless function intnuminitgen (not very useful and impossible to use reliably together with intnum with boundary conditions) 4- useless function intnumstep: instead of intnum(a,b, intnumstep()+m), use intnum(a,b,m). 5- partially implemented functions intfouriercos / intfouriersin / intfourierexp / intlaplaceinv / intmellininv / intmellinvshort: use intnum (possibly intfuncinit). Make sure to indicate oscillating behaviour when function decrease slowly at oo 6- optional flag to intfuncinit BA 7- divide_conquer_prod: use gen_product instead 8- useless function sumnumalt 9- badly implemented functions zetakinit / zetak: the interface did not make sense (it is impossible to initialize for Dedekind zeta without specifying a domain where the function is to be evaluated). Closest equivalent to zetakinit: L = lfuninit(x^2+1, [c, w, h]); to compute zeta_Q(i)(s) for |Re(s - c)| < w, |Im(s)| < h. Then lfun(L, s) as an analog to zetak(). Or directly lfun(x^2+1, s) if a single value is needed. [#368, #1647] BA10- [libpari] FpXQX_rem_Barrett, FpXQX_divrem_Barrett: use FpXQX_get_red BA11- [libpari] FlxqX_rem_Barrett: use FlxqX_get_red BA12- [libpari] RgX_RgM_eval_col pari-2.17.2/CHANGES-2.120000644000175000017500000010625314567450071012557 0ustar billbillBug numbers refer to the BTS at http://pari.math.u-bordeaux.fr/Bugs/ Done for version 2.13.0 (released 19/10/2020): Fixed 1- sizebyte(objects containing t_LIST): would assign size 3 to all lists 2- [Map(Mat([0, 0])), [0, 0, 1]] -> SEGV 3- zeta(I+2^(-64)) -> SEGV BA 4- permorder returned incorrect results for large orders 5- p=[4,54]; lfunmf(mfinit(p,0), mftraceform(p,0)) -> oo loop BA 6- printf("%5.2f",M) transposed M [#2252] 7- bnfinit instability at low accuracy. E.g., at \p38 P=x^7+22*x^6+184*x^5+764*x^4+2020*x^3+3792*x^2+5712*x+4; bnfinit(P,1).no -> 4 times too large 8- accuracy problems in bnfisunit after bnfinit(P,1). E.g., P=x^7-22*x^6+169*x^5-568*x^4+1263*x^3-1506*x^2+2295*x+2; setrand(1); K=bnfinit(P,1); U=bnfunits(K,idealprimedec(K,2)); bnfisunit(K,4*(x^2-18*x+85)/x^2*Mod(1,K.pol),U) -> error Added 1- examples/pari.f90: example FORTRAN binding 2- [libpari] quodif BA 3- [libpari] perm_sqr, perm_powu, perm_orderu BA 4- asymptotically fast quadunit Changed 1- faster intnumgaussinit + change default number of points to B/4, suitable when b - a ~ distance to the nearest pole BA 2- [libpari] perm_pow now take a t_INT exponent BA 3- [libpari] permorder and perm_order now return a t_INT. Done for version 2.12.1 (released 16/09/2020): Fixed BA 1- plotlines flag was ignored 2- fileopen(,"w" or "a") was bypassing the check for 'secure' default 3- bug in idealismaximal: K=nfinit(y^2+7); idealismaximal(K,[11,7;0,1])->0 4- bnfcertify did not certify correctly its argument when DEBUGLEVEL > 1 (\g 2 and above) and the computed class group was trivial (introduced in 2002, commit d3d44841). The code was correct at \g1 or \g0, and in all cases if the computed class group was non-trivial. 5- nfdiscfactors(nfinit([x^2+1, [1,x]])) -> wrong result (didn't support inputs from nfinit([T, integer basis])) 6- nfinit(rnf) would produce a broken nf (not supporting nf_get_ramified_primes) 7- [mf,F] = mffromqf([2,0;0,2]); L=lfunmf(mf,F) => wrong values 8- t=mfTheta();mfslashexpansion(mfinit(t),t,[0,1;-1,0],1,1) -> error 9- poldisc(x^4 + 8/y*x) -> type error in Q_divi_to_int [#2157] 10- T=mfTheta(); mfeval(mfinit(T),T,I/10) -> wrong sign 11- mfslashexpansion(mf,F,huge matrix,...) -> overflow 12- mf=mfinit([470,2],0);F=mfeigenbasis(mf)[7]; mfcuspval(mf,F,1/5) -> division by 0 13- quadtofp(quadgen(-3)) -> t_FRAC component [#2158] 14- [from 2.12.0] nfgcd wouldn't terminate [#2159] 15- conjvec(t_FFELT of characteristic 2) was missing a conjugate 16- nf2 = nfnewprec(nf) could return incompatible nf2 [#2154] 17- [from 2.12.0] u_forprime_next around 2^63 could return primes larger than upper bound 18- [from 2.12.0] gcd(2*x, 2*x+1) -> 2 [instead of 1] 19- [from 2.12.0] deriv(2/(4*x^2+1),x)->inconsistent exact division [#2162] 20- issquare(non square t_FFELT, &x) -> SEGV [#2163] 21- rdivii / rdiviiz imprecise, e.g. a=28088408347805994933529600180306266460976; b=10333147966386144929666651337523200000000; rdivii(a, b) 22- typo in QM_inv (wrong result) 23- modular symbols package: better type checks 24- division by 0 in Flx_extresultant when one input is 0 25- [from 2.12.0] lfunconductor(1,[]) -> SEGV 26- internal error in isprime(,1) after addprime() [#2166] 27- ZM_gauss returned incorrect result for t_MAT RHS and 0 input BA 28- lfunhardy(..., t) with t<0 -> error BA 29- ellweilpairing(E,P,P, odd m) -> wrong result [#2172] PB 30- FlxqM_mul could return wrong result [#2174] 31- p = 4*vecprod(primes([3,373]))*587-1; quadclassunit(-p) -> SEGV [#2175] BA 32- Using local in export()ed functions could crash GP 33- Flx_div_by_X_x(A, x) didn't handle deg(A) <= 0 34- M=mfinit([11,2,Mod(3,11)]); f=mfbasis(M)[1]; lfuncheckfeq(lfunmf(M,f)) -> type error 35- rare random SEGV in nfbasis [#2178] 36- missing type checks in lfunthetacheckinit [#2179] 37- idealispower(x,n,&y): y could be incorrect [#2181] 38- SEGV in idealispower [#2183] 39- inconsistencies in subst for constant polynomials: e.g., type(subst('u^0,u,x)) -> t_POL (was t_INT) subst('u^0,u,Mat(Mod(1,2))) -> [Mod(1,2)] (was [1]) XR 40- factorpadic: incorrect factors (might not lift to Qp) E.g. T=polsubcyclo(271,9); factorpadic(T,3,7)[4,1] BA 41- polcompositum(x^2+x/3+1,x^2+x/3+1) -> SEGV 42- p=nextprime(2^20);q=nextprime(2*p);n=q*p;v=n+1;P=x^2-1; zncoppersmith(v*P,v*n,p,p*v) --> oo loop 43- missing reduction of pr.gen in idealprimedec [ slowdown ] + nfmodprinit [ division by 0 ] JR 44- polylog(-m, tiny z): catastrophic cancellation, e.g. polylog(-100,.5) 45- prodeulerrat((p-2)/(p-1)+(p-1)^(m-1)/p^m,1,3) slow and imprecise [#2192] 46- Mod(1,5) * O(x) -> O(x) [instead of Mod(0,5) + O(x)] 47- lfuninit: lfunrootres calls too expensive if rootno and polar part known 48- incorrect rounding in divrr(realprec = 3) 49- polrootsreal(x+0.) -> SEGV DB 50- mspolygon(1,2): incorrect drawing 51- qflllgram([2,2,3;4,5,6]) -> SEGV 52- printf("%10.6f\n",2^-100) -> SEGV [#2198] 53- mfsturm: off-by-1 error BA 54- ((x^7+x^3+x+1)*Mod(1,Mod(1,2)*d))%(x^4+x^3+x^2+1)->x^3+x instead of Mod(1,2)*x^3+Mod(1,2)*x [#2199] 55- tan(-127336279536511925./2^49) -> completely wrong at \pb64 56- ellocalred / K != Q: wrong encoding for I0 (kod = 1 instead of 0) 57- atanh near -1: large relative error 58- acosh near 1 or -1: large relative error 59- type(subst('x^0,'y,0)) -> t_INT (instead of t_POL) 60- bnfisprincipal: overflow when h >> 1 61- lfun: Pi^s or (2Pi)^s imprecise when Im(s) >> 1 BA 62- factor((x-1)*(x-y)^2) --> oo-loop BA 63- ellap could fail with division by 0 64- wrong results in bnfsunit [#2207] 65- problems with gequal(t_SER or t_POL with inexact coefs or constant wrt. some variables). E.g. S=x+O(x^2);T=S+O(y); S == T -> 0 [#2188] 66- mfkohnenbijection failure [#2211] MW 67- mateigen would sometime return eigenvalues instead of eigenvectors AE 68- [libpari] FpX_oneroot_split could fail for deg 2 and 3. BA 69- [pthread] Fix potential crashes when cancelling threads. 70- derivnum: add sanity checks for 'ind' [#2216] NM 71- nfisincl(x^2-2^5,nfinit(x^4-2)) -> wrong result [#2213, #2214] 72- nfeltsign: wrong results for non-primitive elements in presence of ramification at infinity [#2217] HC 73- F=mfbracket(mfbd(mfEk(4),4),mfTheta(),1); mfcoefs(F,0) -> SEGV 74- gammamellininv([0, 10^-38], 3/10) -> junk 75- mfshimura, mfkohnenbijection: could create mf spaces with inconsistent character. BA 76- [mpi] sending t_LIST to remote nodes did not work. BA 77- my(a,b); parvector(1,i,self()) --> SEGV AP 78- bnrclassfield(,,2) --> sometimes relative polynomial AP 79- nfgrunwaldwang could modify its arguments 80- ldata_vecan(an, N, prec): make sure the function returns N coefficients 81- T=Pol([1,0,6748,-750056,45535504,-2530688944,140646000784]); bnfinit(T,1).cyc -> [240, 12, 4, 2, 2, 2] (instead of [120, 4, 4, 2]) BA 82- [mt] variable priorities in threads could be incorrect. 83- galoissubcyclo: wrong result with bnr input [#2232] 84- subgrouplist(bnr) != [] when modulus is not the conductor 85- incorrect type checks in ideallist BA 86- polmodular(p,,q) incorrect for large q BA 87- [pthread] polgalois(deg>7) could crash 88- forqfvec or qfminim with negative bound => crash [#2237] 89- Z_issmooth_fact: incorrectly include 1 among prime factors 90- Rg[MX]_rescale_to_int: result had a large power-of-2 content DJ 91- sqrtn(Mod(13,112),6) -> o loop [instead of 'bad input' error] 92- addprimes() creates issues with nfdisc [wrong results], because it breaks the assumption that a potential composite in a "bounded factorization" has to come last. 93- addprimes() creates issues with thue [wrong results]. addprimes(360000000029); #thue(x^2+1,500009*500029* 360000000029* 2^100) -> 0 [instead of 32] 94- factor(257377849,100) -> [61,2; 69169,1] instead of [61,2; 263,2] 95- addprimes() creates issues with nffactor [wrong results]. 96- gmulsg(0, t_REAL) followed mulsr semantic (t_REAL) instead of gmul's (t_INT). Analogous problem for gmulsg(0, t_COMPLEX) BA 97- MPQS choice of multiplier and tuning were not optimal Changed 1- [libpari] rename rootsof1 -> nfrootsof1 2- [libpari] rename isirreducible -> polisirreducible 3- hyperellpadicfrobenius: allow X defined over a number field and compute Frobenius over unramified extension of Q_p 4- matsnf(integral matrix): use modular algorithm 5- rnf structure now contains the list of relative ramified primes 6- use the documented semantic for Euclidean division involving real t_QUAD e.g. x % y is x - floor(x/y)*y; for a t_QUAD x and t_INT y, we used to mod out y in "real" and "imaginary" part independently. 7- [libpari] rename rootpadic -> polrootspadic 8- polrootspadic: allow computing roots in unramified extension of Q_p 9- definition of lfunhardy for non-self-dual functions: remove rootnumber, which is not well defined since it depends on the choice of dual sequence a^*(n) 10- improved RgXn_powu / RgXn_powu_i for large valuations 11- improved ZM_ker for wide rectangular matrices 12- lfun(t_INT D): allow arbitrary non-0 D encoding the attached primitive character coredisc(D) (as for other character formats) 13- exp(small rational number): use binary splitting 14- parsum: removed optional argument [allows grouping of subsums => faster] BA 15- old gen_ZpM_Dixon renamed to gen_ZpM_Dixon_Wiedemann, new gen_ZpM_Dixon with simpler interface 16- better formula for Catalan BA 17- QXQ_div_ratlift renamed to QXQ_div 18- disallow mfeisenstein(k,chi1,chi2) when Q(chi1 chi2) is not its field of definition 19- improved ZM_rank for rectangular matrices 20- asymptotically fast variant for RgX_translate algorithms 21- ZX_Uspensky(flag = 0) is now guaranteed to find all rational roots 22- lfunzeros: allow intervals not contained in R^+ 23- removed obsolete function 'bnfcompress' 24- [libpari] rename perf -> qfperfection 25- format of bnf structure, to allow compact representations BA 26- [libpari] Z_to_F2x(s,v): v is now a shifted variable number AP 27- matrixqz(,-1 or -2): faster code + no longer return result in HNF AP 28- allow nfsubfields([nf,fa],): van Hoeij-Klueners-Novocin algorithm 29- nfsubfields: retune to avoid huge inertia degrees BA 30- qfbsolve new flag: bit 1: 1 solution, bit 2: add imprimitive solutions BA 31- revert 2-12-0 C18: qfbsolve with default flag = previous behaviour 32- division/inversion power series: use Newton 33- deprecate LLL_COMPATIBLE (now implicitly always set) 34- bnfissunit is obsolete, use bnfisunit 35- bnfsunit is mostly obsolete, use bnfunits 36- bnfisunit and bnfissunit: torsion unit exponent is now a t_INT (used to be a t_INTMOD) 37- support compact representation in nfeltmul, nfeltpow, nfeltdiv, nfmodpr, nfeltsign 38- elldivpol for negative n: define f_{-n} = -f_n [ was f_n ] 39- support plotinit/plotexport even when the graphic engine is disabled (Configure --graphic=none) 40- gpow(x,n): faster and more precise when n is a t_COMPLEX 41- faster formula for log(2) BA 42- nfgaloisconj(deg 2 pol): swap result to follow nfroots. BA 43- lexical variables names can now reuse builtin functions names as in fun(theta)=my(gamma=1/3);sum(omega=1,10,exp(2*I*Pi*gamma*theta*omega) 44- mfshimura: disallow the discriminant D argument, only allow squarefree positive t BA 45- closures: do not copy the full context, only the accessible part 46- add optional argument to randomprime [select congruence class] 47- add optional argument to sqrtint [set remainder] [#2229] 48- gammamellininv*(A,...): allow A to be an L-function 49- bnrinit: optional argument to compute Cl_f/n, avoid tough discrete logs 50- rnfkummer: removed "all" flag, function now obsolete. Use bnrclassfield! 51- rnfconductor: flag to compute Cl_f/[K:Q] instead of Cl_f 52- bnrconductor_i is now obsolete, use bnrconductor_raw or bnrconductormod 53- dvdxxx(x,y) allow y = 0 [and return 0 unless x = 0] 54- [libpari] bnrsurjection now returns [matrix, cyc(F), cyc(f)] 55- idealstar: optional argument to compute G/G^n, avoid tough discrete logs HC 56- zetamultall: add flag 57- subgrouplist: allow any object affording a .cyc method 58- remove zetamultinit and corresponding optional argument in zetamult 59- [libpari] ZM_lll: flags LLL_INPLACE and LLL_GRAM are now incompatible (reducing a Gram matrix in place without returning the base change matrix is not useful; supporting it would complicate the code) AP 60- improve bnfisprincipal in fields of large degree (test more small elements) 61- bnrgaloismatrix(bnr) no longer needs a bnr with generators (from bnrinit(,1)) 62- bnrisprincipal(bnr,1) no longer needs a bnr with generators (from bnrinit(,1)). Added flag 4 analogous to bnfisprincipal (compact representation of principal part) 63- added sanity checks when parsing default args in 'install' prototypes 64- improved zetahurwitz: faster & use less memory BA 65- MPQS does not use temporary files anymore Added 1- new GP function rootsof1 BA 2- [libpari] F2xqX_halfgcd, FFX_halfgcd 3- [libpari] uis2psp, uispsp 4- [libpari] ZV_lcm 5- [libpari] nfhyperellpadicfrobenius 6- [libpari] rnf_get_ramified_primes 7- allow nfinit([T, basis, ramified primes]) 8- allow nf.p, rnf.p [rational ramified primes] 9- [libpari] idealfactor_partial 10- add flag bit to ZM_snfall_i 11- allow real t_QUAD in floor, ceil, divrem, %, \, \/ 12- [libpari] ff_parse_Tp 13- new GP function mfisetaquo 14- [libpari] Qab_tracerel, QabV_tracerel, QabM_tracerel BA 15- [libpari] RgXV_to_FlxV, FlxV_Flv_multieval, F2v_and_inplace, F2v_negimply_inplace, F2v_or_inplace, F2v_hamming 16- [libpari] ZpX_primedec BA 17- [libpari] QM_sqr, FqC_to_mod, ZXQX_gcd, QXQX_gcd 18- [libpari] radicalu 19- parallel support for lfuninit 20- new GP function parplothexport BA 21- [libpari] gen_ZpM_Newton, ZpM_invlift BA 22- [libpari] F2xn_red, F2xn_inv, F2xX_to_F2xC, F2xXV_to_F2xM HC 23- direct formulas for quadratic Dirichlet L-functions at integers 24- new GP functions: eulerfrac, eulerpol, eulervec 25- [libpari] lfunquadneg BA 26- [libpari] vecvecsmall_sort_inplace, vecsmall_isconst, vecsmall_is1to1 BA 27- [libpari] groupelts_quotient, quotient_groupelts, groupelts_to_group 28- new GP functions mscosets, msfarey 29- new GP function ellpadiclambdamu BA 30- [libpari] Flx_Fl_sub, Flx_is_totally_split, Flxq_autpowers 31- [libpari] Flx_translate1_basecase 32- [libpari] Vgaeasytheta BA 33- [libpari] RgV_type, RgV_type2, closure_callgen0prec BA 34- lfuncreate: support for closures of arity 0 35- [libpari] ZX_sturm_irred, ZX_realroots_irred 36- [libpari] QM_image, QM_image_shallow 37- new GP function asympnumraw 38- [libpari] QM_gauss_i, SL2_inv_shallow 39- [libpari] checkfarey_i 40- [libpari] mspadic_parse_chi, mspadic_unit_eigenvalue 41- [libpari] ellQtwist_bsdperiod 42- [libpari] mseval2_ooQ 43- [libpari] etaquotype 44- new GP functions fft, fftinv BA 45- [libpari] init_Flxq 46- compact representation of units in bnf (bnfinit(pol,1)) and of principal ideal generators (bnfisprincipal(bnf,id,4)) 47- [libpari] Flv_factorback, FlxqV_factorback, famatV_zv_factorback, famatV_factorback, FqV_factorback 48- [libpari] nflogembed, nf_cxlog, nfV_cxlog, ZMrow_equal0, ZC_u_divexact BA 49- [libpari] FpXn_expint, Flxn_expint, Flx_blocks, FlxX_blocks 50- [libpari] bnf_get_sunits, nfsign_tu, nfsign_fu, ideallog_units, sunits_makecoprime, famat_remove_trivial, bnf_build_cheapfu, bnf_compactfu, bnf_compactfu_mat, bnf_has_fu, famat_idealfactor, famat_div, famat_nfvalrem BA 51- [libpari] factorial_Fl, factorial_Fp, FpV_prod BA 52- [libpari] ZX_compositum BA 53- [libpari] FlxXn_red, FlxqXn_mul, FlxqXn_sqr, FlxqXn_inv, FlxqXn_expint BA 54- [libpari] FlxX_Laplace, FlxX_invLaplace, FlxqX_Newton, FlxqX_fromNewton 55- [libpari] vec_reduce, vec_equiv 56- lfuncreate(znstar or bnr,): allow a vector of characters => vector-valued L-function 57- [libpari] gc_const AP 58- [libpari] QM_ImZ, QM_ImZ_all, QM_ImQ, QM_ImQ_all BA 59- [libpari] RgXn_expint, FpXQXn_expint, FqX_expint AP 60- new GP functions nfsubfieldscm, nfsubfieldsmax BA 61- new GP function lfunshift 62- [libpari] Q_lval, Q_lvalrem BA 63- [libpari] ZXX_evalx0, zx_z_divexact, zx_lval, upowers 64- [libpari] is_qfb_t 65- new GP function eulerianpol BA 66- [libpari] FlxX_translate1, zlx_translate1, zlxX_translate1 67- [libpari] rfracrecip 68- [libpari] ZXQ_minpoly 69- [libpari] bnrchar_primitive_raw 70- new GP functions matreduce, bnfunits BA 71- [libpari] QXQ_to_mod_shallow 72- [libpari] nf_cxlog_normalize BA 73- [libpari] cmpss, cmpuu BA 74- [libpari] FpX_Fp_div, FpX_divu BA 75- holes in multi-assignement: [a,,c]=[1,2,3] 76- [libpari] expIPiR, expIPiC BA 77- [libpari] forqfvec1, pariplot, sumdivmultexpr 78- [libpari] powPis, pow2Pis BA 79- nfisincl: new flag: return a single embedding BA 80- [libpari] FpXC_to_mod, FpXM_to_mod, FqXC_to_mod, FqXM_to_mod BA 81- [libpari] FFX_add, FpXY_FpXQ_evaly BA 82- [libpari] halfgcdii, RgX_halfgcd BA 83- new GP function halfgcd BA 84- [libpari] pari_realloc_ip BA 85- [libpari] random_zv, F2m_transpose, F2m_row BA 86- [libpari] F2Ms_ker, F2Ms_colelim, F2Ms_to_F2m, F2m_to_F2Ms 87- [libpari] Qdivis, Qdiviu 88- [libpari] bnr_subgroup_check 89- [libpari] pow2Pis, powPis AP 90- [libpari] bnrisprincipalmod, ideallogmod 91- [libpari] bnrconductor_raw, bnrconductor_factored 92- [libpari] cyc_get_expo 93- new GP function bnrmap HC 94- new GP function polylogmult 95- new GP function zetamultdual 96- [libpari] checkbnr_i 97- [libpari] absZ_factor_limit_strict 98- [libpari] Idealstarmod, ZV_snf_gcd, ideallog_units0 BA 99- [libpari] FqC_FqV_mul 100- [libpari] gen_sort_shallow, vecvecsmall_sort_shallow BA 101- new GP functions foreach, parforprimestep, parforeach BA 102- [libpari] ZXQ_powers, ZXX_Q_mul, QXQX_mul, QXQX_sqr, QXQX_powers BA 103- [libpari] Kronecker_to_ZXQX, QXQX_QXQ_mul, ZXQX_ZXQ_mul 104- [libpari] zv_sumpart, div_content, hash_zv BA 105- [libpari] groupelts_conj_set, group_subgroup_is_faithful 106- qflll(x,3) in place reduction: return x * qflll(x) [faster] 107- [libpari] idealpseudominvec 108- [libpari] galoismatrixapply BA 109- new GP function permcycles BA 110- [libpari] FpX_FpXV_multirem, FpXV_chinese BA 111- galoisinit: support for group (3x3):4 (GAP4(36,9)) BA 112- [libpari] minim_zm 113- new GP function dirpowerssum 114- [libpari] vecfactorsquarefreeu_coprime BA 115- [libpari] nfX_disc, nfX_resultant BA 116- new GP function lfundual 117- [libpari] RgM_ZM_mul Removed 1- obsolete function rootsof1_kannan: use nfrootsof1 2- obsolete function checkbnrgen: use bnr_get_gen Done for version 2.12.0 (released 01/06/2019): Fixed 1- memory leaks due to the use of varhigher/varlower 2- memory leak on error in plots 3- memory leak on error in newtoncharpoly 4- heap-buffer-overflow in init_prefix [readline] 5- mfsplit(mf,,flag) could return uninitialized objects => SEGV 6- mfeisenstein(k,,chi) was treated as E(k,chi) instead of E(k,1,chi) 7- poldegree(y/x) -> 0 [ instead of -1 ] 8- sumeulerrat(y/x^2,1) -> junk HC 9- incgam(-1000.4,2) -> SEGV 10- mfatkininit(mfinit([366,2]),2) -> precision error 11- forprimestep: wrong when wrapping word boundary (2^32 or 64) [#2071] 12- mfbracket: [f,g]_m was multiplied by (-1)^m 13- wrong results in mfatkininit / mfatkineigenvalues due to insufficient precision [#2073/#2074] 14- issquare(Mod(x,ffinit(3,2))) -> wrong result [broken Fq_ispower] 15- possible SEGV in rnfpseudobasis(, [pol,lim]) 16- wrong result in elllog over F_p, p in [2^63,2^64[ p=13824553909862352061; A=8953655473130154624; B=9775907253961339458; P=[6444058885176327583,7963649599850249187]; E=ellinit([A,B],p); Q=ellmul(E,P,2); elllog(E,Q,P) -> 0 [ Flj_mulu_pre would not accept n >= 2^63 ] 17- wrong result in mfsymboleval when path extremities are close to real axis (cusps were OK) [#2075] 18- mfcoefs(mfDelta(),0) -> SEGV [#2078] 19- GC error in lfuncreate(elliptic curve over number field) [#2080] 20- X11 and Qt graphic engine: pari_close called too soon => crash 21- pariold.h: mix up with obsoleted taille / taille2 BA 22- foo(n)=vector(n)[1..n];123; would corrupt the GP interpreter [#2081] 23- Pol(0)/'x -> t_INT 0 (instead of 0*x^0) Pol(0)/(Mod(1,2)*'x) -> t_INT 0 (instead of Mod(0,2)*x^0) 24- missing typecheck in nfalgtobasis [#2084] 25- dbllog2(t_COMPLEX of t_FRAC) => junk 26- nffactor(t_POL, t_POL) => bug in LLL_cmbf [#2083] 27- ideallog(pure archimedean conductor, t_FRAC) -> log(0) error 28- lfunrootres: avoid oo-loop 29- mfgaloistype: dihedral forms possibly incorrect for N > 3000 30- mfgaloistype: error on mf=mfinit([1159,1,Mod(930,1159)],0); 31- incorrect accuracy in limitnum / asympnum for alpha != 1 32- missing GC in polint_i 33- hash_GEN(x) returned different values depending on whether x was a clone BA 34- [mpi] setting nbthreads in .gprc could lead to crashes. 35- accuracy too large in derivnum => slowdown 36- nfisincl(x^5-x^4+x^3-2*x^2+3*x-1,x^20+x^15+x^10+x^5+1) -> SEGV 37- stack corruption in addsub_frac AP 38- segfault in rnfidealup [#2093] 39- Ser(x,x,0) -> error instead of O(x) [#2092] 40- fix mspolygon(,2) [add 1/3rd hyperbolic triangles + fix labels] 41- factor(3/(x^5+3*y*x^4+3*y^2*x^3+y^3*x^2)) -> SEGV 42- output from bnfcompress() mistaken for rnf and vice-versa 43- catastrophic cancellation in acosh / asinh for large t_COMPLEX 44- zeta(1/2 + I*t) => internal error 45- cos(z) and sin(z) imprecise when Im(z) is nonzero but tiny BA 46- hyperellcharpoly: wrong results over Z/3Z 47- gmp kernel: off-by-1 error in red_mongomery [read uninitialized memory, then ignores result] 48- intnuminit([-1,-1/2],[1,-1/2]) twice slower than it should 49- forcomposite(n=2,4,print(n)) -> empty [#2096] 50- relative extension of degree 1 was not properly supported in rnfidealprimedec and rnfidealup 51- mfmul(f,g) created invalid forms when f (resp. g) had Nebentypus chi (resp. chi') and Q(chi * chi') != Q(chi) or != Q(chi') [analogously for mfpow, mfdiv, mfbracket] 52- let [N,k,chi] = mfparams(f); f had coefficients in Q(chi) [or an extension thereof for eigenforms] but the values obtained from znchar(chi) and chareval were incompatible with mfcoefs when order(chi) = 2 (mod 4) [same cyclotomic field but different cyclotomic polynomial] FB 53- [Configure] library not found despite --with-readline-lib [#2097] 54- besseli, besselj, besselk, besseln(nu, z): use asymptotic expansion for large z [#2006] 55- minpoly(Mod(1,t^2)) -> SEGV [#2102] 56- a=ffgen(3^2,'a);poldisc(x^6+a*x+y) -> division by 0 [ positive characteristic with a few t_INT coefficients ] 57- intnumgaussinit(n) actually used 2*ceil(max(4,n/2)) quadrature points BA 58- [pthread] parapply could crash BA 59- ffinvmap(m) could SEGV on bad input 60- ellisdivisible(E/K number field in 'x) -> incorrect priority[#2106] 61- idealispower(nf, t_INT n) possibly wrong if (n, nf.disc) > 1 62- zeta''(0): all precision lost [more generally f'...'(n quotes) imprecise in the neighbourhood of 0, while derivnum(,n) was OK] 63- sumdigits(negative number, B) sometimes negative 64- poldiscfactors(x^0) -> division by 0 65- factormod(x^3+1,[y^2+1,2]) -> SEGV 66- factormod(x^3+1,[y^2+1,5]) -> weird error message 67- besseljh(huge n, z) -> junk BA 68- [pthread] localbitprec was not exported to threads BA 69- fix inefficiency in fplll not present in original code 70- polrootsreal(x^4+2*x^3+x^2/3+x/100-1/2000,[1/100,oo]): no root [#2112] 71- polrootsreal(x^4+2*x^3+x^2/3+x/100-1/1000,[1/10,oo]): extra root [#2112] 72- lfun may crash on lfuncreate input with too short an vector [#2118] BA 73- incorrect use of graphcolors -> SEGV 74- forcomposite(..., oo, ) was not supported BA 75- lfunartin with poles: incorrect result JD 76- factor: significant pointers lost [#2125] BA 77- matdet/matrank over large fields was inefficient 78- poldisc(y^2/x + 1, y) -> error [also affects polresultant] 79- poldisc(x^2/y + 1, y) -> 0 [also affects polresultant] 80- ispower(2, 2^64) -> error 81- (f(x) = x*'y); f'(1) -> error BA 82- sqrtn(Mod(3,19),4) -> no error [#2127] 83- nfhnfmod: wrong result 84- matdet(mat with t_RFRAC entries): wrong result [#2128] 85- n-th derivative of zetahurwitz used 'seriesprecision' instead of n + imprecise value when n large [#2130] 86- lfunzeros(f, [0, b]) wasn't allowed 87- mateigen(): typo causing wrong results when correct results were achievable [#2131] 88- intnum(x=-oo,[0,-1/2],1/sqrt(-x*(x^4+1))) -> division by 0 89- eint1(large x > 0) didn't use asymptotic expansion [#2129] 90- printtex(quadgen(-3,'z)) ==> w BA 91- [a,b]=a could lead to memory corruption 92- memory leak in cgetalloc when lg overflows 93- possible SEGV in padicappr [#2133] 94- zeta(small even integer) was very slow at large accuracy 95- core() could destroy its input, if stored in a GP variable BA 96- (f(x, y = 1) = x*y); f'(1) returned 0 97- quadgen(2^64+1) * 1. => junk (stack corruption in quad_disc). 98- ellmoddegree: infinite loop and stack corruption (e.g on 52a2) 99- ellmoddegree(ellinit("10890ba6")) -> wrong result 100- nfgcd called ZX_resultant(a,T) with typ(a) == t_INT 101- random SEGVs in bnfinit with large fundamental units [#2139] (due to fundamental units computed via floating point approximations rounding to 1 or -1) 102- qfisom([16,6;6,10],[4,3;3,10]) was not 0. [#2140] 103- mfeval: wrong result when level of form and space didn't match [#2134] BA 104- nfisincl(x^3+9,x^6+2187): wrong result [#2144] 105- ispower(27,2^60) -> SEGV [#2145] BA 106- matsolve(M,vector(n)) could return result of wrong dimension 107- [Windows] no longer crash on deep recursion [#2105] 108- factor(Mod(x^3 + x + y^2,2)) -> oo loop [#2148] Changed 1- [libpari] gp_filter return value is now allocated on the stack [was undocumented, malloc'ed and resulted in memory leaks] 2- improved n!, factorial(n), lngamma(n) and psi(n) for integral n 3- improved bernvec: no longer Obsolete 4- [libpari] mpbern is now obsolete: use constbern 5- rewrote the Bernoulli number cache (using zeta(2n) = * B_{2n}) and power recycling for zeta(2n) + additive Clausen von Staudt): orders of magnitude faster and always store Bernoulli in rational form BA 6- [libpari] ZpX_ZpXQ_liftroot_ea: change interface for 'early' 7- bnf.fu: return '0' if bnf does not contain the fundamental units (was an error) 8- support ?? _+_ and friends [extended help for specific operators instead of redirecting to "GP operators"] 9- support ?? _op=_ and ?? op=; support ?? _++ and friends 10- x ^ t_FRAC: return an exact result if possible; e.g. 4^(1/2) is now 2 HC 11- gamma(t_FRAC) and lngamma: use direct formula when denom | 24 12- serlaplace(scalar) -> return the scalar (understood as a constant polynomial) instead of raising an exception [#2082] 13- implement hyperu for arbitrary complex parameters 14- extend lex() to allow complex numbers 15- lfunconductor(L, [a,b]) no longer supported to look for conductor in interval [a,b]; implement lfunconductor(L, list of potential N) instead 16- renamed GP functions Strchr -> strchr (pari_strchr in libpari), Strexpand -> strexpand, Strprintf -> strprintf, Strtex -> strtex 17- [help] move str* functions from "conversions" to "programming" section BA 18- qfbsolve now returns a vector of solutions. 19- limitnum / asympnum: remove useless optional parameter 'muli/k' [now implicitly set to 1, not to 20]: just extrapolate u(muli*n). 20- improve rdivii / rdiviiz [ use divri which may use divri_with_gmp ] 21- mfparams now returns [N,k,CHI,space or P, Phi] where Phi is the cyclotomic polynomials defining the field of values of CHI 22- inline / uninline are now obsolete, use export/unexport 23- let localprec(p) accept non integral real p [replace by ceil(p)]; same for localbitprec. 24- let precision(x,p) accept non integral real p [replace by ceil(p)]; same for bitprecision. 25- besseln is now obsolete, use bessely 26- [libpari] precision0 / bitprecision0 (meant to implement GP-specific commands, not for library use) are now obsolete. The new equivalent commands (still not meant for library use) are precision00 and bitprecision00. 27- improve intnumgaussinit (use direct Newton instead of polrootsreal) 28- improve sumeulerrat / prodeulerrat 29- factor(x, D), D now encodes the domain over which to factor 30- allow listinsert(L, x, n) for n > #L, like listput 31- allow forsquarefree(n = a, b) with a*b < 0 32- allow L[a..b] and L[^i] for t_LISTs BA 33- gen_factorback: change argument order to match other functions 34- polinterpolate(X,Y,t,&e): e is now more precisely defined and the error estimate is given as a binary exponent; compared to the value dy returned up to this change, we have e = exponent(dy). 35- suminf is now sensitive to bit precision. In library mode, use suminf_bitprec (precision in bits) rather than the historical suminf (precision in words) 36- RgV_polint: use (asymptotically fast) FpV_polint over Fp BA 37- [libpari] pari_add_hist now take 3 arguments (data, cputime, realtime) BA 38- # and ## now also display the realtime when nbthreads is not 1 39- gp_format_time: remove trailing ".\n" from formatted string BA 40- GP: arguments of the parser code W can start with ~ for clarity, e.g. listput(~L,x), mapput(~M,x) BA 41- GP: the argument of a user member function is now a reference 42- make ellheight(E, torsion point) return an exact 0 [#2109] 43- allow rnfdisc(k, polynomial with non-integral coeffs) 44- allow rnfconductor(k, non-monic polynomial) 45- poldisc(t_COMPLEX) now raises an exception (used to return -4) 46- rnfdisc(nf, [T,B]) allow B a list of primes and maximal ideals (same for rnfbasis, rnfinit, rnfconductor, rnfpseudobasis) 47- ??? include double quotes when needed (e.g. ???conductor) [#2122] 48- improved the prime() function 49- mpeint1: support all t_REAL x != 0 (was x > 0) LGr 50- nffactor now supports rational functions 51- improve QM_gauss [treat contents sensibly] 52- lngamma and psi near 1: cache values of zeta(odd integers) 53- [libpari] nfbasis prototype changed: 3rd argument listP is gone, use nfbasis(mkvec2(T,listP), &disc). Note that the documentation was incorrect: it is not guaranteed that nfbasis([T, listP]) returns the maximal order even if listP contains all prime divisors of the field discriminant. See ??nfbasis 54- nfbasis now accepts an optional argument &dK [order discriminant] 55- mffromlfun: support forms of half-integral weight (e.g. from lfunqf) BA 56- [libpari] FF_Frobenius: return the image of the standard generator 57- faster poldiscfactors() 58- when 'log' is turned on, explicitly output the logfile name Added 1- [libpari] nonsquare_Fl 2- [libpari] set_avma BA 3- [libpari] FpXC_FpXQ_eval 4- [libpari] mulu_interval_step 5- new file src/basemath/bern.c 6- [libpari] divisorsu_moebius 7- [libpari] ZXQ_powu 8- new GP functions hypergeom, airy 9- [libpari] gc_bool, gc_double, gc_int, gc_long, gc_ulong, gc_NULL 10- new GP functions strsplit, strjoin 11- new file src/basemath/str.c 12- [libpari] has_str_len BA 13- qfbsolve(Q,n) now support arbitrary integer n. 14- [libpari] divisorsu_fact_factored 15- [libpari] qfiseven 16- [libpari] zv_cyc_minimize, zv_cyc_minimal 17- limitnum/asympnum: allow closures of the form N->[u(1),...,u(N)], which allows to handle efficiently sums, recursions, continued fractions, etc. BA 18- new GP function polteichmuller BA 19- [libpari] Flx_Teichmuller, F2x_Teichmuller 20- [libpari] mpsinhcosh 21- new GP function dirpowers BA 22- [libpari] F2xqX_resultant, F2xqX_disc, FlxqX_resultant, FlxqX_disc, FpXQX_resultant, FpXQX_disc, FFX_resultant, FFX_disc BA 23- FFX_gcd, FFX_extgcd 24- optional flag to pollegendre and polhermite 25- new GP function pollaguerre BA 26- [libpari] Flxn_red, Flxn_sqr, Flx_integ BA 27- new GP functions export, unexport, exportall, unexportall 28- [libpari] Fp_divu BA 29- [libpari] ZpXQX_liftroots 30- new GP functions getlocalprec, getlocalbitprec 31- [libpari] guncloneNULL, gluncloneNULL_deep 32- allow subst(e, x, vector v) for vector(subst(e, x, v[i])) 33- [libpari] pollegendre_reduced AP 34- new GP function mfgaloisprojrep 35- optional v argument to nfmodprinit 36- [libpari] rfrac_deflate, rfrac_deflate_order, rfrac_deflate_max 37- [libpari] identity_zv, identity_ZV 38- [libpari] polintspec, polint_i BA 39- [libpari] FF_var, FF_preimagerel BA 40- new GP function ffmaprel BA 41- [libpari] closure_derivn BA 42- [libpari] walltimer_start, walltimer_delay, pari_get_histrtime BA 43- new GP function strtime BA 44- [libpari] Flxn_exp, Flx_Newton, Flx_fromNewton, Flx_Laplace, Flx_invLaplace BA 45- Support call by reference in GP function: f(~L,x)=listput(~L,x+1) BA 46- Generic fast linear algebra using CUP decomposition 47- [libpari] nfX_to_monic BA 48- new GP function derivn BA 49- new GP function arity 50- new GP functions idealdown, idealismaximal 51- [libpari] bid_get_fact2 AP 52- new GP function bnrclassfield HC 53- implement lfunmfspec in odd weight HC 54- new GP functions ellE and ellK 55- [libpari] maxprimeN BA 56- support for rational model in ellratpoints and hyperellratpoints 57- [libpari] psi1series 58- [libpari] constzeta 59- new GP function nfdiscfactors 60- [libpari] RgV_is_arithprog 61- fast algorithm for zeta([a + b*n | n<-[0..N]]) BA 62- ellheight(E) now returns the Faltings height of E BA 63- lfun now allows non-integral weights OB 64- example/parigp.sty to re-enable PARI's \pmatrix with amsmath [#2110] IZ 65- [win32+gp-sta] support for install() 66- [libpari] setunion_i BA 67- [libpari] hash_init, hash_init_ulong BA 68- [libpari] FFXQ_minpoly BA 69- [libpari] F2x_recip 70- [libpari] RgV_isin_i Removed 1- member functions .futu and .tufu [deprecated since 2.2] 2- inferior hash function hash_str2: use hash_str 3- matsnf: remove obsolete binary flag '2' [make it a no no-op] (cf mathnf) pari-2.17.2/CHANGES-2.40000644000175000017500000025507214557721030012477 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 ZV_cmp0 -> ZV_equal0 gener -> znprimroot, ggener -> znprimroot0 greffe -> RgX_to_ser (+ change prototype) hil0 -> hilbert, hilii -> hilbertii [ delete useless hil() ] ideal_two_elt* -> idealtwoelt*, idealhermite -> idealhnf initalg -> nfinit, initalgred -> nfinitred, initalgred2 -> nfinitred2 initell -> ellinit, smallinitell -> smallellinit isfundamental -> Z_isfundamental ismonome -> RgX_is_monomial isunit -> bnfisunit matrixqz -> QM_minors_coprime matrixqz2 -> QM_ImZ_hnf matrixqz3 -> QM_ImQ_hnf minideal -> idealmin and change prototype mu -> moebius, gmu -> gmoebius, nfhermite -> nfhnf, nfhermitemod -> nfhnfmod, nfsmith -> nfsnf phi -> eulerphi, gphi -> geulerphi, phiu -> eulerphiu, poldeflate -> RgX_deflate_max polymodrecip -> modreverse powraw -> qfbpowraw, compraw -> qfbcompraw primedec -> idealprimedec racine -> sqrtint, regula -> quadregulator rename cmp_ZV -> ZV_cmp smith2 -> smithall, gsmith2 -> gsmithall srgcd -> RgX_gcd subfields0 -> nfsubfields, subres -> resultant, subresall -> resultant_all. torsell -> elltors and document it zideallog -> ideallog RgXQ_caract -> RgXQ_charpoly ZX_caract -> ZXQ_charpoly ZX_isirreducible -> ZX_is_irred pariputc -> pari_putc, pariputs -> pari_puts, pariflush -> pari_flush, gpmalloc -> pari_malloc, gprealloc -> pari_realloc, gpfree -> pari_free ordell -> ellordinate 7- polvaluation -> RgX_valrem(x, pz) and no longer accept pz = NULL (use RgX_val). Same for ZX_valuation -> ZX_valrem [ & ZX_val ] 8- rename u2toi -> uu32toi [ paste two 32-bit unsigned into a t_INT ] Write uutoi for the more natural operation of pasting two ulongs into a t_INT. 9- prototype of FpX_center [ add one argument ] BA 10- [svn/CVS] number development snapshots according to repository version 11- delete CVS.txt and replace it with README-subversion 12- syntax errors, SIGINT and "PARI bugs" are no longer trapped 13- quadray no longer allows an (optional) 3rd argument 14- 'format' was updated after each 'realprecision' change. Don't update if 'format' is Xm.-1 (show all significant digits). 15- the algorithm used to round t_REAL for output 16- the "minimum field width" component of the 'format' default is now ignored (was used only for integers in 'prettyprint' output mode and defaulted to 0 [no effect]). Use printf ! 17- %Z is no longer a valid conversion specification for PARI formats, since this is now handled as a length modifier. Use %Ps instead (P stands for PARI). 18- remove the (ugly) prettyprint engine ('output' = 2), render as matbrute. printp / printp1 now act as print/print1 19- pariprintf renamed to pari_printf, %Z conversion disappeared (use %Ps) 20- check for small prime divisors in ispower [ large speedup ] 21- the conversion style 'g' of the 'format' default now printfs in style 'f' if the decimal exponent is < -4 ( was: if the binary exponent is < -32 ), in order to conform to standard printf specifications. 22- [GMP kernel] enable GMP exact division 23- matdetint: use less memory + faster finish 24- change the default algorithm for mathnf(a) [ much faster ], flag 0 is no longer deprecated 25- library/GP function galoisinit() now returns NULL/0 on failure (used to raise an exception) 26- allow nfgaloisconj(t_POL, 1) [ cf C-4 ], never resort to nfgaloisconj(,2) [ slow, unreliable ] with default flag = 0 27- [library]: gsub now implemented directly when typ(x) = typ(y) BA 28- all LLL variants now use an implementation of NGuyen & Stehle's algorithm 29- [library]: the "prec" parameter of floating point LLLs has disappeared 30- Vecrev(x) now equivalent to extract(Vec(x), "-1..1") [was only for t_POL] 31- allow t_COMPLEX as well as t_QUAD in ellpow 32- we used to have Set(1) == Set("1") ( = ["1"] ). Now the latter returns ["\"1\""] (the Set whose element evaluate to the character string "1") 33- plotinit: change the way default arguments are evaluated (omit, instead of interpreting 0 in a special way) 34- nfbasistoalg / nfalgtobasis no longer accept t_VEC/t_COL/t_MAT, use matbasistoalg / matalgtobasis, which now also accept t_VEC/t_COL 35- uniformize factornf and nffactor outputs (+ speed them up for non-squarefree inputs: compute valuations mod a suitable prime) 36- treat Mat(t_LIST) as Mat(t_VEC) 37- t_POL^0 always returned t_INT 1 [ try to return 1 in coefficient ring ] 38- polresultant(x,y,,0) now chooses the best algorithm by itself [Ducos, modular, Sylvester], polresultant(x,y,,2) is now a synonym for the default. The change also improves poldisc(). 39- regression tests in src/test/in/ no longer need to end with 'print("Total time spent: ",gettime)' 40- arguments of stirling1 / stirling2 are now ulongs [ were longs ] BA 41- user variables can now be aliased [#790] 42- conjvec(POLMOD of INTMODs) was slow 43- bnfcertify can now handle Zimmert/Minkowski bounds > 2^31 44- moved misc/dico.new to src/whatnow + integrate it in the description system [ new script desc/whatnow ] 45- bittest(x, n) no longer accepts t_VEC arguments n 46- split library function disable_dbg() -> dbg_block() / dbg_release() 47- make the semantics of substpol more precise and less surprising: substpol((x^2+x+1)/(x^2+x-1),x^2,x^3) -> (x^3 + x + 1)/(x^3 + x - 1) [ was: (x^6 - x^3 - 2*x - 1)/(x^6 - 3*x^3 + 1) ] 48- deprecated flag '2' for bnfinit [ don't compute units ] is now ignored ==> bnfunit becomes totally useless. 49- the last component in prime ideals "primedec" format is a number field element, but no longer necessarily in t_COL form 50- no longer allow ideals in *non-square* t_MAT form 51- idealmin now returns a number field element, instead of the associated "principal idele" 52- cleared up the confusion caused by PARI "ideles", which were remotely related to the mathematical notion, and covered two distinct uses. The first one (ideal + list of real places) is now called "divisor"; the second one (ideal + factorization matrix, which used to be a vector of logarithms of complex embeddings) is now called "extended ideal". 53- Allow Scalar + t_COL: x + y returns [ y[1]+x, y[2],... ]. Consistent with RgC_Rg_add and RgV_isscalar, and allows linear algebra over number fields with less rigid data types (can mix freely t_COL, t_INT and t_FRAC, instead of converting everything to t_COL). 54- Functions quadunit(), quadregulator(), and factor() no longer apply componentwise to vector / matrix arguments. Use apply() 55- [libpari] removed obsolete 'prec' argument from prototypes of idealmul0, idealmulred, idealpow0, idealpowred, ideallllred, algdep, algdep0, lindep, lindep0 56- factorback() no longer accepts an optional 3rd argument (nf). Use idealfactorback(). See also nffactorback(). 57- Extend polhensellift to work over unramified extensions of Q_p [ was Q_p only ] 58- [libpari] changed prototypes of bnrdisc, bnrconductor, bnrisconductor 59- slightly change the matrices used in idealmin (round them): the elements returned are a little different. 60- no longer export private library function incgam2. Remove it also under GP when compatible = 3. Like incgam1 (suppressed), 1.39.15 doc stated it was provided "for debugging only". 61- addhelp: TABs are now treated properly (would overflow line without wrapping) and \n are no longer ignored. No longer add a trailing '.' when missing. 62- Useless nfinit flags 4, 5 (partial polred) removed. 63- Split off inline functions unrelated to the kernel from src/kernel/level1.h 64- Swap the order of the 2 arguments to select(): selection function now comes first [ as in apply() ] 65- error() messages now prefixed with the customary *** [ used to be ### ] 66- dvmdiiz(x, y, z) now expects z to be a t_INT [ to be consistent with all other xxxz functions where xxx includes only i,s,u arguments ] 67- improved charpoly(,,2) [ Hessenberg form ] 68- allow Flxq_mul and Flxq_sqr to call Flx_rem_montgomery 69- t_POLMOD * t_POLMOD with same modulus: if all coefficients are in Z/NZ, call specialized functions FpXQ_mul / Flxq_mul [ analog with gsqr, gdiv, ginv, powgi ] 70- bezout(): make sure the leading term of the gcd of 2 polynomials is positive (when it makes sense), as was already the case for gcd() 71- mpcopy, Flv_copy, Flx_copy, vecsmall_copy have all become aliases for leafcopy. 72- trap(,,foo) was actually equivalent to trap(,foo) changing the global exception handler, which was awkward an unintended 73- norml2(t_POL) now returns the expected (square of) the standard L^2 norm. Use x * conj(x) to get back the old behaviour. norml2 now raises an error on t_POLMOD and t_FFELT components; used to add relative norms as in ? norml2([Mod(Mod(1,3)*x,x^2-2), 2]) %1 = Mod(2, 3) 74- [library] kernel functions involving a t_INT and a t_REAL now return a t_REAL, e.g. divsr(0, x) or mulir(gen_0,x) return real_0(...) [ used to return gen_0 ] ==> much better control of object types when writing kernel code. Generic functions (gmul, gdiv), as called from gp still return a result as precise as possible given the input: 0 * 1. --> gen_0 75- [library] cleanup t_COMPLEX arithmetic to take advantage of real parts equal to a t_INT 0. Imaginary parts equal to 0 should never be created by our generic functions (so no need to cater for them specially: they will be very rare, produced by ad hoc routines). Special case trigonometric functions on pure imaginary arguments. 76- kill(z) no longer destroys user variable, only resets them to their "undefined" value (as z = 'z would). 77- [library] prototype of galoisconj [ add one argument ], and made it correspond to the default nfgaloisconj flag 78- allow ordinary sorted vectors in set* functions [ sets are still t_VECs of t_STR, but if components can be directly compared, ordinary vectors are simpler and faster ] 79- allow arbitrary nf entries in relative matrices; nfhnf and nfhnfmod return matrices whose entries may be t_INT or t_FRAC besides the traditionnal nfalgtobasis form. Allow ideals in arbitrary form [was: necessarily HNF] 80- linear algebra routines: determines first whether we are over Z/NZ then call specialized FpM_* routines if possible [fixes #376] 81- [library] commented out a large section of pariold.h. Define PARI_OLD_NAMES to recover compatibility macros for old friends like 'un' and 'lstoi' 82- Mat(t_QFI or t_QFR) now returns the associated 2x2 symmetric matrix 83- [library] rename Buchall -> Buchall_param and export a new Buchall with a simplified interface. 84- trap() no longer allows installing default error handlers. 85- GP's break loop is now *enabled* by default [ set breakloop = 0 in your gprc to disable it ], and no longer controlled by trap(). To get out of a break loop, hit Return three times (next, return, break are no longer accepted) BA 86- factormod and matker: faster linear algebra over F2. 87- remove duplicate polynomials in polred output [#874] 88- let forvec(X = v,...) respect the type of v (t_VEC or t_COL) 89- polred: compute characteristic polynomials as in polredabs [ using complex embeddings, not ZX_charpoly ] PMo90- algorithm for nfrootsof1 now defaults to nffactor: generically a little slower than qfminim, but safer and sometimes much faster (e.g. 1mn against a few hours) 91- added a new component nf_get_roundG to the nf structure [ to speed up ideal reductions ] BA 92- make test-xxx: trap SIGINT in benching script to exit on 93- removed optional flag to rnfconductor, use rnfisabelian. 94- improved dirzetak() by an order of magnitude: e.g. K=nfinit(x^3-10*x+8), dirzetak(K, 10^6) from 4min (2.4.2) to 2.5s 95- renormalize rnfkummer output so that it cannot be written as P(C * x)*C^(-deg P) for any integer C > 1 [ saves large powers of C in disc P ] 96- added a flag to the (mostly useless) function rnfdedekind(), the version with the flag set is a little more useful. Allow list of prime ideals instead of single prime ideal, and make this list optional (omitted = test for maximality at ALL primes) 97- the "zetakinit" format: bnf no longer included 98- thueinit / thue: allow reducible and non-monic polynomials 99- rnfdedekind: allow non-monic polynomials 100- bnrclassno(bnr,id) : allow bid as well as modules for the 'id' argument. 101- GP 'path' now also applies for file paths containing a '/' provided they do not *start* with a '/' (i.e. not an absolute path) 102- [library mode] the function znlog now takes an extra "order" argument 103- added an optional "order" argument to znlog, fflog, elllog, znorder, fforder, ellorder, whose preferred format is [ord, factor(ord)] and ord is the order of the group 104- factor(t_INT/t_FRAC, lim) used to trial divide by primes up to min(lim, primelimit). Now we trial divide up to lim and raise an error if lim > primelimit. [ Having the routine return an obviously "wrong" result depending on an invisible parameter was not a good idea. ] 105- factor(t_INT/t_FRAC, 1) was the same as factor(t_INT/t_FRAC, 0). Now abide by the input value and leave (..., 0) as the single special case (shortcut for "the largest precomputed prime") BA106- [native kernel] Schoenhage-Strassen multiplication/squaring 107- factorff(A, p, T): make p & T optional if A has t_FFELT coefficients BA108- [TLS] Change pari_thread calling convention 109- allow x.a1, ..., x.a6 for an "ell5" x (5-component vector) 110- removed 'primelimit' grom gp_data struct: we now print the actual limit of the primetable, not the value input by the user (which may be a little less) BA111- listsort(L) no longer returns the list L: it now returns nothing. (No point in sorting in place if we must immediately copy the result.) 112- allow component(t_VECSMALL,...) [#957] 113- allow bestappr(x) [2nd argument made optional] BA114- GMP kernel chosen by default when GMP is available BA115- Rename RgXQ_u_pow to RgXQ_powu 116- Darwin: add -search_paths_first to LDFLAGS (try to solve the Editline / Readline conflict in a user-friendly way) BA117- [enable-tls] Library soname changed to libpari[-gmp]-tls[-2.4].so.N. 118- integrate a final polredabs in quadhilbertreal() BA119- Rename leftright_pow to gen_pow, leftright_pow_u to gen_pow_u and implement sliding window powering. BA120- galoisapply now accept automorphisms in t_COL format. 121- allow moduli equal to 0 in matsolvemod (was SEGV) [#947] + rigorously size-reduce the output in all cases. 122- the bnr structure in a minor way (bnr[6] has 3 components now) 123- cleaned up the code used by the GP evaluator to call PARI (and installed) functions. Functions can now have 20 arguments [#795] BA124- galoisfixedfield now accept subgroups. 125- ellap(E, p) second argument now optional if E has t_INTMOD or t_PADIC coefficients. 126- generalize the "generic pivot" strategy to all linear algebra (support RgM_solve and det() in addition to existing functions); implement maximal pivot strategy for p-adics [#1054] BA127- padic_sqrt -> Qp_sqrt, padic_sqrtn -> Qp_sqrtn, gammap -> Qp_gamma 128- rename rnfinitalg -> rnfinit 129- [readline + vi-mode] h/H no longer clobbered by online help. 'h' will now act as expected (= 'move left one character') 130- any of break / next / return now get out of the break loop debugger (as they used to in 2.3) 131- typing thrice no longer gets out of the break loop : use break 132- faster eta(,1), weber() and quadhilbert() [ rewrite using eta's functional equation explicitely ] 133- checked that no 2-strong pseudoprime passes BSPW primality test up to 2^64 (use Feitsma's list, extending Galway's) Added 1- many new benches (make test-all) 2- split up some large monolithic files: new files src/basemath/ RgV.c, FpV.c, ZX.c, ZV.c, concat.c, lll.c, hnf_snf.c prime.c, bit.c src/modules/ QX_factor.c, Hensel.c, DedekZeta.c 3- split off module of general inline functions: src/headers/pariinl.h. 4- Write or rename / document many convenience library functions: pari_calloc, cgetalloc mkfraccopy, mkquad, mkvecsmall4, absfrac, sqrfrac, mul_content, mul_denom roundr_safe, trunc_safe shallowextract, shallowconcat1, concat1, BPSW_psp & BPSW_isprime Z_smoothen, Z_ispower, Z_ispowerall Z_isanypower, chinese_coprime_Z, Z_chinese, Z_chinese_all, Z_chinese_coprime, Z_chinese_post, Z_chinese_pre, Z_incremental_CRT, Z_init_CRT, ZM_incremental_CRT, ZM_init_CRT, ZX_incremental_CRT, ZX_init_CRT, ZX_to_monic, ZX_primitive_to_monic, ZX_squff, ZX_gcd_all, nfgcd, nfgcd_all, RgX_disc, quad_disc, qfb_disc, ZpX_liftfact, ZpX_gcd, ZpX_reduced_resultant, ZpX_reduced_resultant_fast Fp_center, FpM_center, FpV_center Fp_ratlift, FpM_ratlift, FpX_ratlift FpM_FpC_mul_FpX Fp_red, FpXQ_red Flxq_add, Flxq_sub, FpXQ_add, FpXQ_sub, FqXQ_add, FqXQ_sub FqX_add, FqX_sub FqX_roots, FpX_factorff, FpX_rootsff FpXQX_div, FpXQX_rem, FpXQXQ_mul, FpXQXQ_sqr, FpXQXQ_pow FpXQXQ_inv, FpXQXQ_invsafe, FpXQXQ_div FqXQ_mul, FqXQ_sqr, FqXQ_pow, FqXQ_inv, FqXQ_invsafe, FqXQ_div FqX_extgcd ZC_ZV_mul, ZM_is_identity, ZM_copy, ZM_neg, ZM_add, ZM_mul, ZM_pow ZM_max_lg, ZM_sub, ZM_ZC_mul, ZXV_Z_mul, ZM_Z_mul, ZV_Z_mul, ZV_isscalar, ZV_copy, ZV_neg, ZV_neg_inplace ZV_togglesign, ZV_indexsort ZMrow_ZC_mul, ZV_ZM_mul, ZV_cmp0, ZV_content, ZV_equal, ZC_lincomb, ZC_lincomb1_inplace, ZC_z_mul, ZV_prod, ZV_pval, ZV_pvalrem zv_prod ZM_Z_divexact, ZC_Z_divexact, ZX_Z_divexact, ZM_charpoly, Flm_charpoly, Flm_hess Z_ZX_sub, ZX_Z_sub, Fp_FpX_sub, Flc_Fl_div, Flc_Fl_div_inplace, Flc_Fl_mul, Flc_Fl_mul_inplace, Flm_Fl_mul, Flm_Fl_mul_inplace, Flm_copy, Flm_mul, Flm_inage, Flv_Fl_mul_inplace, Flv_add, Flv_add_inplace, Flv_copy, Flv_dotproduct, Flv_sub, Flv_sub_inplace, Fl_order, Flx_nbfact_by_degree, Flx_roots_naive, FF_sub, Fp_mulu, FpV_inv, FpXQ_inv, FqV_inv, FpXY_eval, FpXY_evalx, FpXY_evaly, Flx_Fl_mul_to_monic, FlxqX_Flxq_mul_to_monic, FlxqX_rem, FlxqX_gcd, FlxqX_extgcd, FlxqXQ_mul, FlxqXQ_sqr, FlxqXQ_inv, FlxqXQ_invsafe, pol1_FlxX, FpX_Fp_sub, FpX_Fp_sub_shallow, FpX_Fp_mul_to_monic, FqX_Fq_mul_to_monic, FpXX_Fp_mul, RgM_check_ZM, RgM_det_trianguar, RgM_isdiagonal, RgV_check_ZV, RgV_neg, RgV_add, RgV_sub, RgV_Rg_mul, RgC_neg, RgC_add, RgC_sub, RgC_Rg_div, RgC_Rg_mul, RgM_neg, RgM_add, RgM_sub, RgM_Rg_div, RgM_Rg_mul, RgC_RgM_mul, RgC_RgV_mul, RgM_RgC_mul, RgM_RgV_mul, RgM_mul, RgM_sqr, RgV_RgM_mul, RgV_RgC_mul, RgV_add, RgV_neg, RgV_sub, RgC_Rg_add RgM_diagonal, RgM_diagonal_shallow, RgM_inv, RgM_solve, RgM_mulreal, mulreal, RgX_RgM_eval RgV_sum, RgV_sumpart, RgV_sumpart2 RgX_neg, RgX_add, RgX_add_shallow, RgX_sub, RgX_Rg_add, RgX_Rg_sub, Rg_RgX_sub, RgX_equal, RgX_equal_var, RgX_translate, RgX_to_nfX, RgM_to_nfM, RgC_to_nfC, RgX_type, RgX_type_decode, RgX_type_is_composite, RgX_Rg_divexact, RgXQ_norm, RgXQ_pow, RgXQ_caract, RgXQ_reverse RgXQX_translate, RgXQV_to_mod, RgXQXV_to_mod RgXQX_pseudorem, RgXQX_pseudodivrem, RgX_check_ZX, RgX_check_ZXY, RgX_pseudodivrem, RgX_pseudorem, RgX_recip, RgX_recip_shallow, ZC_hnfrem, ZC_hnfremdiv, ZM_det_triangular, ZM_detmult, ZM_equal, ZM_hnf, ZM_hnfall, ZM_hnfcenter, ZM_hnflll, ZM_hnfmod, ZM_hnfmodid, ZM_hnfmodall, ZM_hnfrem, ZM_hnfremdiv, ZM_hnfperm, ZM_snf, ZM_snfall, ZM_snfall_i, ZM_snf_group, ZM_snfclean ZM_lll, ZM_lll_norms, hnfmerge_get_1, ZXY_max_lg, ZX_copy, ZX_equal, ZX_max_lg, row_Flm, row_zm, scalar_ZX, scalar_ZX_shallow, deg1pol, deg1pol_shallow togglesign_safe, setabssign, zero_Flm, zero_Flv, zero_zm, zero_zv, zm_copy, zv_cmp0, zv_copy, zv_equal, zv_content, zx_renormalize, identity_perm, cyclic_perm, perm_mul, perm_commute, perm_inv, perm_pow, cyc_pow_perm, cyc_pow, perm_cycles, perm_order, vecperm_orbits bitvec_test_set, RgX_get_0, RgX_get_1, resultant, resultant_all, QX_disc, QX_resultant, lllfp, lllintpartial, lllintpartial_inplace, reducemodlll, reducemodinvertible, closemodinvertible, init_primepointer, galoisinit0, get_nfpol, get_bnfpol, get_prid, bnf_get_nf, bnr_get_bnf, bnr_get_bid, bnr_get_mod, bnr_get_nf nf_get_r1, nf_get_r2, nf_get_roots, nf_get_sign, nf_get_roots, nf_get_M, nf_get_G, nf_get_roundG, nf_get_Tr, nf_get_TrInv, nf_get_disc, nf_get_index, nf_get_pol, nf_get_zk nf_get_prec (was nfgetprec), nf_to_scalar_or_basis, nf_to_scalar_or_alg nf_to_Fq_init, nf_to_Fq, Fq_to_nf, zkmodprinit, zk_to_Fq_init, zk_to_Fq, nfM_to_FqM, FqM_to_nfM, nfX_to_FqX, FqX_to_nfX zk_multable, zk_scalar_or_multable, multable, tablemul, tablemul_ei, tablemul_ei_ej, tablemulvec, tablesqr, ei_multable. nfordmax, nfarchstar (was zarchstar), nfadd, nfsign, nfnorm, nftrace nfsign_arch, nfsign_units, nfsign_from_logarch, Buchquad, Buchall, Idealstar, idealaddtoone_i, idealcoprimefact, nfinvmodideal, nfpowmodideal, idealsqr, nfpow_u numberofconjugates, bnrisconductor0, bnrdisc0, bnrconductor0, bnrsurjection, ABC_to_bnr, idealred, idealred0 (was ideallllred), idealred_elt, idealred_elt0 ellinit_padic, ellinit_real, ellinf, ell_is_inf, ell_is_padic, ell_is_real, checkerr_real, checkell_padic, checksmallell, checkell5, checkellpt trueeta, exp_Ir, roots_from_deg1, deg1_from_roots 5- [libpari] public generic hashtables 6- library functions sqrr and invr [ Newton inversion, called by ginv() ] BA 7- library functions checkgroup, galois_group, cyclicgroup, dicyclicgroup, abelian_group, group_domain, group_elts, group_order, group_isabelian, group_abelianHNF, group_abelianSNF, group_isA4S4, group_leftcoset, group_rightcoset, group_perm_normalize, group_quotient, quotient_perm, quotient_group, quotient_subgroup_lift, group_subgroups, groupelts_abelian_group, groupelts_center, group_export, group_ident 8- library functions pr_get_p, pr_get_gen, pr_get_e, pr_get_f, pr_get_tau to access components of prime ideals BA 9- handle numerical derivation as an operation on closure. RB 10- GP functions printf, Strprintf 11- pari_printf, pari_fprintf, pari_sprintf, pari_vfprintf, pari_vprintf, pari_vsprintf BA 12- docpdf and install-docpdf targets (toplevel Makefile) JD 13- add an optional argument to quit() 14- universal constant gen_m2, for symmetry 15- GP function version() [ current version number ] BA 16- [ellap] Port of SEA algorithm from the ellsea GP package BA 17- new alarm GP function and alarmer error code RM 18- partitions() 19- New chapters in Libpari Guide: usersch6.tex, usersch7.tex 20- library function dbg_pari_heap 21- function bnfcompress() [ to create a "small bnf" from a true bnf, to be recoved using bnfinit ]. More consistent than old bnfnit(,3) / bnfmake. 22- a concept of "extended ideal" [I, t], where t is an algebraic number (possibly in factored form). The pair represents the ideal I x (t) In applications the norm of I stays bounded for a given base field, and t keeps track of the "principal part" of the ideal (usually in factored form to avoid coefficient explosion). 23- public interface to forsubgroup: traversesubgroups() 24- library function bnfisprincipal0 (with new public flags, see nf_GENMAT) 25- GP functions nffactorback / idealfactorback JD 26- GP function warning() 27- new flag to charpoly [ integral matrix, modular algorithm ] BA 28- GP function galoisisnormal() BA 29- F2x functions family for polynomials over GF(2) and BA 30- t_FFELT subtype_FF_F2xq for GF(2^n) BA 31- F2v/F2m functions family and F2m_ker for linear algebra over GF(2) BA 32- extra debugging data in t_CLOSURE and debugging facility. BA 33- compile-time copy optimizer BA 34- elliptic discrete logarithm function elllog() BA 35- direct implementation of ZX_mul, ZX_sqr using Kronecker's trick + mulii 36- rnfisabelian GP function 37- default 'recover' 38- more possibilities to draw "random" elements in natural sets using random(), e.g. finite fields, elliptic curve over finite field. 39- GP routines nfeltadd, nfelttrace, nfeltnorm BA 40- Pollard rho discrete logarithm algorithm (function gen_Pollard_log) 41- GP routine polrootsff 42- matadjoint: implement division-free algorithm (flag = 1) [#937] BA 43- GP routines and PARI functions ellweilpairing, elltatepairing and ellgroup BA 44- FpE functions family for points on E(F_p) BA 45- GP routine galoisgetpol and PARI function galoisgetpol, galoisnbpol BA 46- GP routine and PARI function elldivpol BA 47- GP routine and PARI function ellmodulareqn BA 48- function RgXQ_ratlift for reconstruction of rational functions. 49- optional flag to bnfcertify : only check that the correct class group is a quotient of the computed one. VB 50- mingw support VB 51- plotwin32 graphic engine 52- plotQt4 graphic engine BA 53- low-level accessors functions gal_get_* for galoisinit objects 54- libpari functions cvstop2, z_lval, z_lvalrem, z_pvalrem 55- GP function externstr() 56- library function ZC_reducemodmatrix, ZM_reducemodmatrix, ZC_reducemodlll, ZM_reducemodlll BA 57- libpari functions vecsmall_max and vecsmall_min BA 58- GP functions idealfrobenius and idealramgroups BA 59- library functions Zn_sqrt, Zn_issquare 60- library function gidentical BA 61- GP operator === that use gidentical 62- GP function sumdedekind() JD 63- [gphelp] support for bzip2 compressed documentation. Removed 1- obsolete GP functions printp, printp1. Either replace them by print / print1 [ or the new printf ], or define aliases alias(printp, print); alias(printp1, print1) 2- obsolete GP functions bnfclassunit, bnfreg, bnfclgp, bnfunit. Use bnfinit. 3- obsolete GP functions bnrclass. Use bnrinit or bnrclassno. 4- obsolete GP function idealprincipal. Use number field elements "as is" 5- obsolete GP function ideleprincipal. No routine remains that would use the auxiliary "archimedean information" 6- obsolete library functions extract and matextract 7- obsolete optional argument to quadhilbert(D < 0) 8- unused undocumented library functions os_open/os_read/os_close 9- obsolete README.DOS and README.WIN 10- cant_deflate, elliper1, lllger3, varer1, obsoler, infprecer, errlg, errexpo, errvalp, rtodber, affer2, primer2, siginter error codes 11- obsolete library function bruteall 12- useless undocumented library function gkrogs (use krois) 13- obsolete library functions roots2 and rootsold are no longer public 14- useless library function isnfscalar 15- obsolete undocumented library function factpol(), lift_to_pol() 16- library function combine_factors() is no longer public 17- obsolete undocumented library function rnfdet0, rnfdet2 18- obsolete library function discsr(). Use RgX_disc (or quad_disc, qfb_disc) 19- obsolete library function element_powmodidele() [use element_powmodideal + set_sign_mod_idele], ideleaddone, reducemodmatrix, nfreducemodidele, nfreducemodideal, nfreducemodideal_i, elementinv_modpr 20- useless macros gaddgsz, gaddsgz, gdiventgsz, gdiventsgz, gdivgsz, gdivsgz, gmaxgsz, gmaxsgz, gmingsz, gminsgz, gmodgsz, gmodsgz, gmulgsz, gmulsgz, gsubgsz, gsubsgz, gachz, gacosz, gashz, gasinz, gatanz, gathz, gchz, gcosz, gcotanz, gexpz, ggamdz, ggammaz, glngammaz, glogz, gpsiz, gshz, gsinz, gsqrtz, gtanz, gthz, gzetaz, gmaxz, gminz, TRgopgz, mpfloorz, mptruncz, mpdvmdz 21- obsolete library function gmillerrabin, gpolcomp, caradj0 22- obsolete library functions allbase, base, base2, factoredbase, smallbase, discf2, factoreddiscf, smalldiscf. Use nfbasis0 / nfdisc0 / nfmaxord 23- obsolete library function pari_rand31 [ use pari_rand ] 24- obsolete undocumented library function bruterr 25- obsolete library function smallbuchinit 26- awkward flag '3' for bnfinit. Use bnfcompress(). 27- badly named bnfmake. Use bnfinit(sbnf). 28- useless component v[6] in "small bnfs" (was 'different', is 0) 29- obsolete library functions buchray, buchrayinit, buchrayinitgen: use Buchray. 30- obsolete library function smallfact [ use boundfact or Z_factor_limit ] 31- obsolete library function gracine [ use sqrtint ] 32- obsolete library function ispsp, gispsp. Use ispseudoprime or BPSW_psp. 33- obsolete library function gregula, gfundunit, gboundfact. Use quadregulator, quadunit, boundfact 34- obsolete library functions ideallistunit, ideallistunitgen, ideallistzstar, ideallistzstargen. Use ideallist0. 35- obsolete library function algdep2. Use algdep0 (same arguments). 36- obsolete library function Mod0. Use gmodulo. 37- obsolete undocumented library function poldvd. Use RgX_divrem(x,y, ONLY_DIVIDES) 38- obsolete library function kerint1. Use kerint or ZM_lll(,0.99,LLL_KER) 39- header file paritype.h [ split between parigen.h and pariinl.h ] 40- obsolete library functions sor, outbrute, outbeaut 41- dangerous macros max & min [ use maxss/minss, maxuu/minuu, maxdd/mindd ] 42- deprecated global constants gi, geuler, gpi. Use mulcxI/mkcomplex/gen_I(), mpeuler() and mppi(). BA 43- bitvec family function. Use F2v instead. BA 44- useless prototype code 'S'. Use 'r' instead. BA 45- useless function delete_named_var. 46- obsolete and dangerous switch_stack() [#1013] %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.4.2 (released 22/12/2007): Fixed 1- divrs(0., negative integer) had the wrong exponent 2- vecsort(,,4) was broken in 2.4.1 3- allocatemem(z) didn't check that z >= 0 [#556] 4- remove hack in internal function 'readbin' that used the clone bit as a special marker hence returned an invalid object, which could be propagated to higher level public functions. BA 5- sqrtn(Mod(a,p),..) and factorff() were broken in 2.4.1 BA 6- bitnegimply(1,2^65) returned a wrong result [#560] 7- nfeltreduce(nf,t_POLMOD,id) didn't work [#558] 8- [library] missing function intfourierexp() 9- segv in polrootspadic / repeated roots in FpX_root (only in deg 2) [#562] 10- log(2+O(4^4)) --> oo loop 11- log(exp(1e-100)) -> 1.000000000149525401279188592 E-100 [ for some accuracies, log & exp inacurate near 1 and 0 resp. ] 12- numbpart inaccurate (and slow). E.g numbpart(52602) off by 1 [#557]. BA 13- &, |, && and || were right-associative instead of left-associative 14- remove type assumptions in mulcxI, mulcxmI: unsafe [#516]] 15- too much memory allocated to print real numbers 16- (y/x)/(x^0/y) not correctly simplified 17- \s reported a misleading number of available user variables 18- 1/(quadgen(-4)*x)+0. -> exponent overflow [#591] 19- sumpos(x=1,1/x^2,1) had the wrong sign [#587] 20- matrixqz(x,0) would not work if first two determinants were 0 + might lose pointers in gerepile 21- sumpos(x=1,0) -> oo loop [#585] 22- qfminim([[;]],,,2) --> SEGV [#598] 23- intformal(1) --> incorrect object 24- intformal(y,x) --> y*y 25- matadjoint(0) --> gerepile error 26- prodinf(x=0,0), prodinf(x=0,-1,1) --> oo loop 27- agm(-1, 1+1e-55) --> oo loop, agm(-1,1) --> wrong result LGr28- killing hi-res graphic window created zombie process (missing wait()) 29- missing type check in eint1(x,n) 30- ploth(...) + Ctrl-C --> hi-res graphic window killed [use pari_daemon()] 31- quadgen([]) --> incorrect object [#606] 32- hyperu(0,1,1) --> oo loop [#608] 33- fix headers so that ulong is always defined 34- read("a b.gz") \\ filename contains a space gzip: ./a.gz: No such file or directory 35- logagmcx inaccurate [ used for log(t_COMPLEX), large precision ] 36- RgX_divrem: prevent "impossible" situations for weird base rings 1/ Mod((y-1)*x-1, Mod(2,6)*x^3-Mod(1,2)*x^2-1) --> SEGV 37- gclone didn't work on t_INTs with lg > lgefint 38- GC error in add_rfrac() [#612] 39- missing type check in subgrouplist [#616] 40- inconsistent type checking in nfeltdivmodpr [#617] 41- nfdisc(x^32+24888960*x^30+227077545803904*x^28+887225199431341086720*x^26+1145458263702669503266741248*x^24-459489127319699704284694158213120*x^22+73430099675988831740428200872826863616*x^20-6599321778961370851005469933592282336329728*x^18+369563540304176984501448638025309170375722401792*x^16-13214618078037183940422584396181416089308059714715648*x^14+291247424536170563676138246427605494527806096141868597248*x^12-3407227562250271661213064368167141844394234574629997803208704*x^10+8699659624155196549893192408316795253695601521375537680749690880*x^8+153390110447793800411208197070089975539253907830958400507847198638080*x^6-34704742472413552993642506624568826441560550586777137133227202205188096*x^4+43389826962123095743039577910848855441856968086933919852164410699581227008*x^2+336462877895453750216450425189196151877685043455706101021513167474262016, 1) --> "not a prime" error (help Round4 to recover when using non-primes, instead of raising immediate errors) [#624] 42- vecextract: C14 in 2.4.0 didn't work for large masks [#623] 43- clean up version handling: move version setting code to config/version and always set PARIVERSION from CHANGES if 'CVS' [ used to require a 'Configure' ] 44- zeta(0e1) --> SEGV [#627], exp(0e1*I) --> SEGV [#630] 45- exp(2^200*I) --> catastrophic cancellation [cos/sin were OK] [#631] DE 46- on NFS filesystems, make install would rebuild all [#503] 47- default(compatible,3); default(compatible,1) --> case no longer taken into account [#629] 48- missing GC in 'sigma' 49- eta(x): valuation would overflow if seriesprecision is large 50- typo in src/kernel/none/mp.c:convi --> inefficiency 51- concat(v) used too much memory (quadratic in #v, make it linear) [#634] BA 52- gp -q -f < eval('y) --> SEGV 53- "significant pointers lost" for objects involving 0 t_SERs [#635] 54- for trivial x, isanypower(x,&p) would not set p MSo55- [Configure] don't rely on $CC exit status, check whether a non-0 size executable is produced [ problems with tcc ] BA 56- wrong Prototype for subgrouplist [ extra 'p' ] 57- hole in 'secure' mode: don't allow changing psfile / logfile [#645] 58- nf.codiff was only correct up to multiplication by some rational number [cf #510 & 2.4.1-F7] 59- cgiv failed to delete the last object on stack [ if recursive ] LGr60- first default(parisize,*) would segfault [due to C-1, #569] 61- pariputs("") --> invalid read of size 1 [ valgrind ] 62- ell.omega, ell.eta, pr.gen could lead to gerepile error [#641] 63- y=[x];eval('y) --> error [#652] 64- incorrect use of gerepileupto in inittestlift [ galoisconj ] 65- extra multiplication in the innermost loop of Cholesky decomposition (qfgaussred, etc). 66- made FpX_add, FpX_sub, Fq_add, Fq_sub stack-clean. FpX_neg, Fq_neg returned an incorrect result if input was not reduced mod p 67- setrand(4);polgalois(x^8-264*x^6+25410*x^4-1054152*x^2+15856203) --> wrong result [#660] 68- build fails with "env: parameter list too long" [#661] 69- factorff did not accept inputs with t_FFELT coeffs 70- could use PARI stack while reading gprc [ before pari_init ] 71- Mod(Mod(1,v),v) --> invalid object. 72- a = Mod(y, v); y = Mod(1,v); eval(a) --> invalid object 73- for some complicated t_RFRAC z: z' --> impossible assignment I-->S 74- typo in bnfisintnorm(): missed some solutions [ couldn't find a unit of norm -1 even though one exists ] 75- ffprimroot(ffgen( t_POL of degree 1)) --> oo loop 76- wrong result in theta(q, z) if sin(nz) was small for some small n [#667] 77- 1/Mod(0,2) --> impossible inverse modulo: Mod(2, 2) 78- alias(a,b), then ?a --> 'a is aliased to a' 79- -Mod(0,2) --> Mod(2,2) MA 80- [Linux-PPC] missing -fPIC in DLCFLAGS 81- possible oo loop in _isprincipal [ precision was supposed to increase, but could in fact remain the same ] 82- quadregulator(y) -> SEGV [#674] 83- acos(x^0) -> division by 0 [ instead of O(x^8), at \ps 16 ] Analogously, acosh(x^0), asin(x^0), asinh(I+O(x)) --> division by 0 84- dilog(-1) [ more generally polylog of < 0 t_REALs ] should have 0 imaginary part 85- problems with [ build/install ] directory names containing spaces 86- avoid catastrophic cancellation in 3M [ Karatsuba ] formula for t_COMPLEX * t_COMPLEX 87- ix86, x86_64: missing earlyclobber constraint for addllx, subllx, divll 88- ploth(,4) --> huge memory use for large plots 89- stirling(0,0,2) --> 0 [ should be 1, #690 ] 90- deriv(x/(x+1),y) --> invalid t_RFRAC with exact 0 numerator [#687] 91- issquare(t_POL) assumed characteristic 0 [#549] 92- sqrt(Mod(4,5) + x) --> error [ e.g. stack overflow ] 93- hyperu(0*I,1,1) --> forbidden assignment t_COMPLEX --> t_REAL. BA 94- fix compilation problem with g++-4.2 and GMP. 95- ??factor_proven, ??factor_add_primes did not work 96- typo in znprimroot: wrong result for large moduli znprimroot(5*2^127+1) --> 2 [#696] 97- ffgen(x*Mod(1,2)) --> x [ should be 0 ] 98- ffprimroot(ffgen((x+1)*Mod(1,2))) --> oo loop 99- nffactor(nfinit(y),x^2+Mod(1,y)) --> SEGV [#699] 100- "precision error in minim0" on qfminim(G, norml2(M[,1]), 100) from tutorial 101- nffactor(nfinit(y^2+1),(2*x+1)*x*(x+1)) --> SEGV [#702] 102- isprime((6^2176+1)/(6^128+1)) --> length (lg) overflow [#697] [ analogous problems for any large integer ] 103- various problems related to allocatemem() [ + document quirks ] Remove the br_ALOCATEMEM construct and end allocatemem0() by a longjmp 104- missing GC in det_simple_gauss() [ matdet for inexact inputs ] 105- rare stack corruption in add_rfrac [#700] 106- add missing GC in gsubst 107- polred([pol, b]) computed unnecessary but possibly expensive invariants of pol [ e.g. disc, index ] 108- compilation failed on AIX [ YYSIZE_T, pow ] 109- ? Mod(1,2)*x + Mod(1,2)*y %1 = Mod(1, 2)*x + (Mod(1, 2)*y) \\ extra parentheses in constant term ? % + 0*z %2 = Mod(1, 2)*x + Mod(1, 2)*y 110- factornf(x^5+(-a+2)*x^4-a*x^3+(3*a-6)*x^2+(5*a-10)*x+(2*a-5), a^2-5) --> SEGV [ not squarefree -> denominators creeping in ] [#708] 111- problems with isexactzero and t_INTMODs. Mod(0,2)*x*1. -> 0, Pol(Mod(0,2))+2 -> 2, (2+0*I)+I*Mod(0,4)->Mod(2,4), Mod(0,2)/x -> 0 Use isrationalzero instead. 112- substvec(x^2, [x^2], [y]) --> y^2 [ should be an error ] 113- typo in FpM_gauss_pivot: FpM_rank, FpM_image, FpM_suppl, FpM_indexrank much slower than they should be. Analogous problem in FqM_gauss_pivot. BA114- missing GP2C descriptions for Pol and Polrev. BA115- zero FFELTs were not considered as exact zeros [#710] 116- rare SEGV in gp when recovering from error (dereferencing global_err_data equal to BREAK_LOOP) 117- vecsort(t_LIST) returned a t_VEC 118- gp "huge file" + stack overflow --> stack overflow in next interactive command (+ minor memoryleak) [#712] Changed BA 1- The combined GP parser/evaluator has been replaced by a bytecode compiler and a bytecode evaluator BA 2- install(): parser code 'E' and 'I' now refer to closures, not strings: 'I': closure whose value is ignored, like in for() loop 'E': closure whose value is used, like in sum() loop 3- Fl_pow renamed to Fl_powu [ exponent may not be negative ] 4- split usersch3.tex moving function documentation to src/functions/* 5- simplify table of contents for users.dvi 6- rename Flx_rand -> random_Flx, FpX_rand -> random_FpX BA 7- use factor_pn_1 to compute various orders in FF.c 8- file usersch3.tex is now generated from functions/* 9- rewrote logr_abs [ inaccurate + slow for x = 2^k * (1 - epsilon) ] 10- rewrote exp1r_abs [ inaccurate + slow ] and mpexp_basecase [ reduce input mod log(2) ] 11- rewrote mpsc1 [ slow ] -> faster sin and cos 12- [library] rename pointch -> ellchangepoint, coordch -> ellchangecurve 13- prototype of constpi, consteuler. 14- use a little less memory to compute pi, euler, log(2) 15- qfminim(x,b,m,flag) made 'm' parameter optionnal also when flag=0 16- made second argument to matrixqz optional, allow non-prime values 17- matpascal(n < -1), mathilbert(n < 0) now raise an error 18- add optional extra argument to ffprimroot, fforder, fflog 19- allow znlog(x,g) where g a t_PADIC or an t_INTMOD modulo any N that znprimroot(N) would accept 20- log(x t_PADIC): check whether x = 1 (mod p) before replacing x <- x^(p-1) 21- znprimroot(p^k): use isanypower() instead of factor(). E.g. znprimroot(nextprime(10^20)^1000): 8mn --> 12ms znprimroot(N) no longer checks reliably whether (Z/N)^* is cyclic. Result undefined if it is not. 22- padic sqrt much faster [ small and large accuracies ] 23- let primes() indicate a value of primelimit if unable to answer [#625] 24- remove variable names from ?0 25- exp(0e10) returned 1.000, made it 0exxx [ no significant digit ] MSo26- define polchebyshev(n, 1 or 2), pollegendre(n) for n < 0 27- znorder faster for non-prime modulus [ try it for Mod(2,5^10*7^10) ] (compute lcm of local p-adic orders) 28- changed icopyifstack / copyifstack macros so that their arguments are GENs, not GENs typecast to long. 29- add -funroll-loops to gcc flags when compiling arithmetic kernel 30- improve ellap (Shanks) by computing #E(F_p) mod 2 [ idea stolen from Pierrick Gaudry ] 31- nfreducemodpr was exceedingly slow for large t_POL inputs, e.g. w=x^48 + 158*x^46 + 4*x^45 + 12103*x^44 + 448*x^43 + 597874*x^42 + 23928*x^41 + 21373779*x^40 + 802424*x^39 + 588314524*x^38 + 18516794*x^37 + 12951694530*x^36 + 294992428*x^35 + 233870773964*x^34 + 2752210590*x^33 + 3524535272389*x^32 - 5797649292*x^31 + 44873186922754*x^30 - 798816466566*x^29 + 486736157075707*x^28 - 18082470992066*x^27 + 4523171646555185*x^26 - 271968456240780*x^25 + 36127625049532658*x^24 - 3144283847234232*x^23 + 248308835345289047*x^22 - 29271322082172250*x^21 + 1467438460133718165*x^20 - 223406933340907742*x^19 + 7435650911902583447*x^18 - 1405525828628464338*x^17 + 32139937168429173010*x^16 - 7272631544138987758*x^15 + 117563850386577478340*x^14 - 30686320483051428956*x^13 + 359649878031434743177*x^12 - 103986861631984042496*x^11 + 904392935429691313557*x^10 - 276283466933590000414*x^9 + 1822091999374665372405*x^8 - 554259164403897051340*x^7 + 2827767569115449802250*x^6 - 788757355446858093774*x^5 + 3170224521565069297504*x^4 - 708295322502763110380*x^3 + 2280480720610858280676*x^2 - 300602103002034938488*x + 788466592242441477569; nf=nfinit([w, nfbasis(w,1)]); modpr=nfmodprinit(nf, idealprimedec(nf,5)[1]); L = nfgaloisconj(w); vector(#L,i, nfeltreducemodpr(nf,L[i],modpr)); (in this example, the last reduction is down from ~ 1minute to ~ 2s) 32- make sure nfmodprininit chooses a monic T to represent Fq ~ Fp[X]/(T) [#646] 33- remove obsolete undocumented functions outerr, outbeauterr, outsor, outtex. Rename voir -> dbgGEN. Functions brute, outbrute, matbrute, outmat, sor, outbeaut are obsoleted and no longer documented. 34- rename errfile -> pari_errfile, infile -> pari_infile, logfile -> pari_logfile 35- extra test infrastructure [ drop file in src/test/in and possibly src/test/[32|64], then run Configure, no need to edit config/get_tests ] 36- inline gerepileupto/gerepileuptoleaf + improve gerepileupto 37- [libpari] cleanup of user / temp variable handling. manage_var obsoleted (kept for backward compatibility, to be removed), see Section 5.9 for new equivalents. Fixes #633, #650 38- fix t_LIST as components: v = [List()]; listput(v[1],) didn't work [#468] 39- listcreate() and listkill() are obsolete, don't use them. L = List() should be enough in all cases. All lists now grow as needed, without requiring an awkward maximal length (from listcreate). 40- rename sqred -> qfgaussred, signat -> qfsign, sqred1 -> qfgaussred_positive 41- rename gaddmat -> RgM_Rg_add and swap arguments. Add RgM_Rg_add_shallow 42- document library functions zv_neg, zm_transpose, fix typo in documentation for RgX_neg 43- document library functions gmaxgs, gmaxsg, gmings, gminsg. 44- document library function gfloor2n 45- document library function zx_shift 46- cleaned up splines handling [ ploth(,,,256) ] : remove quark_gen & QUARK BA 47- implicitly local variables are lexically-scoped BA 48- local and my can now appear anywhere in a program. 49- [library] rename apell -> ellap 50- Removed the OK_ULONG macro and renamed u_OK_ULONG -> SMALL_ULONG 51- Rename BIGINT -> NO_VARIABLE [used by gvar()], VERYBIGINT -> LONG_MAX, MAXULONG -> LONG_UMAX. Remove BYTES_IN_LONG, TWOPOTBYTES_IN_LONG 52- implement directly gsubsg [ was a macro calling a trivial wrapper ] 53- optimize multiplication for quadratic t_POLMOD [ t_QUAD remains faster ] 54- theta(q,z) very inefficient for large accuracies 55- remove support for nf of the form [nf, change of variable] in nfnewprec() [#672] 56- global() now obsolete and scheduled for removal LGr57- 'make ctags' gctags-specific flags [ add #defines, typedefs ] 58- prototype of nfsubfields [ 2nd argument GEN -> long ] 59- allow t_FFELT in issquare / issquarerem / ispower 60- sqrt(t_SER) now uses Newton iteration 61- rename gissquarerem -> gissquareall, uissquarerem -> uissquareall, Z_issquarerem -> Z_issquareall (analogy with sqrtrem was faulty: we do not store a remainder but the square root) BA 62- User functions are now regular variables holding values of type t_CLOSURE 63- Output of \u is now sorted 64- More explicit error messages in gp_history, e.g. *** History result %10 not available [%1-%6] BA 65- vecsmall_uniq(v) no longer assumes that v is sorted 66- allow ellorder to handle curves over Fp, add an optional parameter to indicate a multiple of the order as in znorder. 67- allow polcyclo(n, a) for an arbitrary a [ had to be a variable ] + major speedups: polcyclo(10^6) 5min -> 16ms. Similarly for polchebyshev, pollegendre and polhermite 68- ?0 listed all "user-defined identifiers". Restrict to "functions" 69- use simplify in setsearch() and Set() [#707] 70- change gcd(t_POL, t_POL) so that inexact inputs have scalar gcd [ used to compute a "sensible" approximate gcd ] Added 1- library functions expu, adduu, subuu 2- library functions divisorsu, factor_pn_1 (using cyclotomic factors and Aurifeuille), merge_factor 3- library function divru, dbllog2r 4- library function ZX_gcd, ZX_isirreducible 5- library function gtos 6- library function pari_daemon 7- library function Fp_sqr, padicsqrtlift 8- library function RgXQ_inv 9- bench 'extract' 10- charpoly: Berkowitz division-free algorithm (new default) [#541] 11- library function phiu 12- library function mkvecsmalln 13- library function chk_gerepileupto, dbg_gerepile, dbg_gerepileupto 14- library function gen_sort_uniq, gen_indexsort_uniq+add flag 8 in vecsort 15- library function remi2n, cmp_RgX, gen_cmp_RgX 16- library function RgV_dotproduct, ZV_dotproduct, RgV_dotsquare, ZV_dotsquare, FpV_dotproduct, FpV_dotsquare 17- library function FpX_Fp_add_shallow 18- library function Q_pval BA 19- new keyword "my" to declare lexically-scopped local variables. 20- new GP function listpop() 21- library function RgX_inflate, RgX_deflate, Flx_inflate, Flx_deflate, poldeflate 22- library function Fp_neg, Fp_add, Fp_sub 23- library function ugcd 24- library function vecinv, vecmul, vecpow, vecdiv, vecmodii 25- library function RgM_isidentity, RgV_isin 26- library function nfnewprec_shallow, bnfnewprec_shallow, bnrnewprec_shallow 27- library function Zp_issquare 28- library function dvmdsBIL, divsBIL, remsBIL 29- library functions gassoc_proto, map_proto_G, map_proto_GG, map_proto_GL, map_proto_lG, map_proto_lGG, map_proto_lGL [ were private with other names ] 30- default factor_proven 31- experimental -balloon option to gphelp LGr32- defaults graphcolormap, graphcolors [runtime-defined colormap for plots] LGr33- bit 4096 [ complex ] to ploth 34- member function .p / .mod for t_PADIC 35- same mnemonic flags to plotrecth as in ploth BA 36- member function .pol, .mod and .p for t_FFELT BA 37- New type t_CLOSURE to store GP functions 38- Ability to use arbitrary comparison functions in vecsort() 39- library functions closure_callgen1, closure_callgen2, closure_callgen, closure_callgenvec. 40- GP function apply(), select() 41- library functions FF_issquare, FpXQ_issquare, Flxq_issquare BA 42- library function vecsmall_uniq_sorted 43- bench 'ff', 'exact0' 44- has_getenv.c 45- library function FpX_oneroot 46- library function gcmpX 47- library functions ZV_sort, ZV_sort_uniq, ZV_search Removed 1- obsolete function kbessel2 (now static). Removed optional flag in besselk 2- Removed obsolete optional flag in ellap(), Mod() and gcd() 3- Rename gen_search_aux -> gen_search and document it [ old gen_search disappears: use tablesearch() ] 4- undocumented library functions gpolylogz, polylog, polylogd, polylogp, polylogdold. Use polylog0 with appropriate flags. 5- undocumented library function ghell2. Use ellheight0 with appropriate flag. 6- obsolete function log0; use glog 7- obsolete undocumented library function mpdivz, polzagreel, RgX_powers (use RgXQ_powers) 8- obsolete undocumented library function sqred3 9- the emacs/ directory: PariEmacs is now distributed separately. 10- obsolete functions ellap0, apell2 11- obsolete header file pariport.h 12- obsolete error codes paramer1, valencer1, accurer, caracer1 13- removed obsolete system-specific #ifdefs (macintosh, alliant) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.4.1 (released 28/03/2007): Fixed 1- qflll / qflllgram (t_MAT with t_FRAC entries) would not reduce to the integer case (--> insufficient precision, SEGV) [#505] 2- [Cygwin] missing -L... -lgmp when compiling with gmp. 3- ispower(522^3) -> 0 [ looked like a 7th power to is_357_power(), which then forgot to test for cubes ] [#506] LGr 4- [gphelp] race condition --> incomplete cleanup (improved patch BA) 5- Cleanup library linking: do not link libpari with -ld [only gp], do not link gp with -lgmp [only libpari]. Side effect: libgmp.so no longer needed for modules compiled by gp2c-run 6- when nf.disc < 0, nf.diff was an incorrect PARI ideal [#510] 7- nf.codiff was only correct up to multiplication by some rational number (a divisor of nf.disc) [#510] 8- inaccuracy (>= 2ulp) in [cached] log(2) [#498] 9- exp, sinh, asinh, tanh, atanh were inaccurate near 0 10- [GMP kernel] forvec(x=[[-1,0]],print(x)) --> error [#509] [ 'resetloop' failed when passing through '0' ] 11- nfbasistoalg(nfinit(y),x) created an invalid t_POLMOD 12- incorrect result in ZX_resultant (accuracy loss in bound computation) 13- bnfinit(): avoid further precision problems for large degree fields 14- [Configure] gcc-specific flags were used on linux/freebsd/cygwin, even when __gnuc__ was unset 15- factor( pure power FqX ) --> SEGV 16- [GMP kernel] polrootsmod(f, 4) --> wrong result [ low level t_INT manipulation not using the int_* macros ] 17- polrootspadic(f, 2, r) --> some roots would be found twice [ due to FpX_roots(f, 4) called ] [#521] 18- ??sumalt doesn't compile: in GPHELP, treat \ref in verbatim mode [#518] 19- matinverseimage returned [;] when no pre-image exists. Conform to the docs: "an empty vector or matrix", depending on the input types. 20- [Configure] abort when $CFLAGS is not supported by $CC 21- 3.5 % 2 --> error [ should be 0.5 ] 22- sin(1/10^100) --> 0e-28 [ also affected cos,tan,cotan ] 23- fix e.eta and elleta such that e.eta = 2 ellzeta(e,e.omega/2) [ was ellzeta(e,e.omega/2) ]. COMPAT. 24- elleta(e) was different from elleta(e.omega). Analogous problems in all quasi-elliptic functions. COMPAT: change e.omega so that e.omega[1] / e.omega[2] belongs to the Poincare half plane [ used to be the inverse ]. Together with 24: the Legendre relation now reads w1 e2 - w2 e1 = 2 I Pi Rationale: 1) the action of Sl_2(R) becomes the standard one, not a twisted one 2) fixes quite a few normalization problems in our code. 25- check that k >= 0 in thetanullk [#531] 26- isprime(-2,1) returned 1 27- Fix 'Not enough precision in thue' error BA 28- [OS X] Fix kernel detection on x86_64-darwin 29- Remove "VERY long time" Warning in bnfcertify (few minutes nowadays) BA 30- missing prototype for documented function ZY_ZXY_rnfequation 31- sqrt(x^2/y^2) --> SEGV [#536] 32- \r foo no longer worked if foo was a directory and foo.gp a valid input file [#540] BA 33- [Configure] spectacular failure to recognize gcc under some locales. 34- polredabs(x^8+2*x^6-5*x^4+78*x^2+9) was incorrect [ missed x^8+6*x^6-x^4+54*x^2+25 due to incorrect "skipfirst" ] [#542] 35- typo in resmod2n (both kernels) [#546] 36- At \p28, 0.1 - 0.1 would return 0.E-30 instead of 0.E-29 BA 37- missing prototype for documented function FpX_div_by_X_x 38- isprime(,0) very slow when primelimit is large [#546] 39- nfmodprinit could create FpX's which were not reduced mod p 40- O(x^3)^(1/2) was O(x^2) instead of O(x) RB 41- the following TODO item: v = vector(2); v[1] = v = 0 --> SEGV. Occurs with high probability if any variable is "deleted", while it (or part of it) is still in use Reference count could be helpful here. 42- substpol(x^-2+O(x^-1),x^2,x) --> error [#555] BA 43- [TLS] addss, addsr and subsr were not reentrant. Changed 1- concat(t_VECSMALL, t_VECSMALL) to return the concatenated vector [was: a vector with two t_VECSMALL entries] 2- pariprintf() so that it handles t_STR as print() [ don't include quotes ] LGr 3- [Makefile] make generated src/funclist independent of locale 4- Extend Pocklington-Lehmer to the case N-1 = FU, F > N^(1/3) BA 5- Much faster base-2 to base-10 conversion. BA 6- FpX_Fp_add() is now clean. BA 7- rename ZY_ZXY_resultant -> ZX_ZXY_resultant, ZY_ZXY_rnfequation -> ZX_ZXY_rnfequation and FpY_FpXY_resultant -> FpX_FpXY_resultant. BA 8- FpV_polint() now take a variable number as last parameter. 9- use Miller-Rabin-like improvement in znprimroot and FpXQ_gener 10- indexrank, indexsort and indexlexsort now return t_VECSMALLs 11- API for gen_sort, vecsort Added BA 1- derivnum(x=a,expr) for numerical derivations BA 2- library function strntoGENstr 3- function Vecrev BA 4- ppc64 level0 inline assembly kernel 5- library function floor_safe() 6- library function itostr() BA 7- library function Fp_div(), Fp_mul() BA 8- library function FpXQ_norm() BA 9- library functions FlxX_resultant() and Flx_FlxY_resultant() BA 10- library function FlxY_Flx_div() BA 11- library function Flm_transpose() BA 12- library function Flx_Fl_add() BA 13- library function Flxq_div() BA 14- function stirling (Stirling numbers of 1st and 2nd kind) BA 15- library function FpX_valrem() 16- library function Flxq_gener BA 17- library function Flxq_norm, Flxq_minpoly, Flxq_charpoly BA 18- [toplevel benchmark] ffisom BA 19- library functions Fp_order, FpXQ_order, FpXQ_log, FpXQ_sqrtn, Flxq_order, Flxq_log, Flxq_sqrtn 20- library functions gen_sort_inplace, gen_indexsort, sort_factor, indexvecsort BA 21- New PARI type t_FFELT and support functions (FF_*) for finite field elements. BA 22- functions ffgen, fforder, fflog, ffprimroot for finite field elements. Removed 1- obsolete functions readexpr(), readexpr_nobreak() 2- pariemacs support from Configure 3- obsolete functions sindexsort, sindexlexsort, sindexrank %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.4.0 (released 06/10/2006): Fixed 1- typo in remiimul: wrong result in a "failsafe" branch (hardly ever taken). May affect modular powering /Fp if p >> 10^1300 [#457] Also affects the gmp kernel, for p >> 10^5800. 2- rare accuracy problem in bnfinit P=x^8-787856*x^6+232721637848*x^4-30546112988506688*x^2+1503204734505922286224; setrand(1974190693); bnfinit(P) --> non invertible matrix in gauss 3- inconsistent return type in nffactormod [#460] 4- the following TODO item bnfinit may give wrong answers because we cheat on the value of Bach's bound, using B := 0.3 log^2 D by default, where 0.3 should really be 12 (under GRH). If the prime ideals of norm <= B do not generate the classgroup, we may not detect it, and compute junk. Ex: * setrand(3); bnfinit(y^4 + 1190*y^2 + 1416100).cyc --> [8,2,2,2]. The correct structure is [8,4,2]. * setrand(1414185642); bnfinit(y^4 + 635*y^2 + 403225).reg [twice the correct value] * setrand(867341586); bnfinit(y^4-y^3+6122*y^2+6121*y+37466641).gen[2] [is principal]. Group structure and regulator are correct! Retune check_bach() IZ 5- remove bogus test for "external help" (= ??) IZ 6- [OS/2]: stack check [prevent oo recursion] present but not enabled IZ 7- [OS/2]: bogus [BUG] in 'program' bench (install pb not detected) 8- gammah(1+O(3^5)) --> incorrect type in ggamd. 9- invalid read in copy_leaf [ SEGV in some libc ] BA 10- ellheight short help was accidentally truncated. 11- substpol(1+O(x^(2*n)),x^2,x) --> 1+O(x) instead of 1+O(x^n) [#470] 12- [OS X] only use -no-cpp-precomp with Apple cc 13- divrem(x,x,y) --> [1/y*x, 0] 14- (1+x)/(1-x)/(1+x)^2 not simplified [#472] 15- typo in qflll: in rare cases (exact input+floating point computation+ precision increase in last-but-1 step), the returned base change is not properly updated in last iteration --> basis not LLL-reduced 16- simplification missed in div_scal_rfrac() [ #473 ] 17- ispower(x^k, k) would answer 0 for some x and k in {3,5,7} [#476] 18- content(t_MAT with exactly 1 col) gave a wrong result 19- random(N) was not uniformly distributed in [0,N-1] (use a reject strategy instead of moding out) [#210] 20- rare bug in red_montgomery (returning 0 with + sign, an incorrect object) [ polrootspadic(x^11+x,11,10) --> corrupts gen_0 ] 21- qfbsolve(Qfb(1,2,10),5) --> [0,0; 0,0] instead of 0 [#479] 22- ispower(0, n, &z) would not set z 23- wrong result in conversion t_QUAD -> t_PADIC whenever disc = 1 (4) JJ 24- gaddgsz macro was wrong [#481] 25- gener_Fl(p^k) can't handle k > 1, use gener_Zl instead [#480] SC 26- [GMP] mp_set_memory_functions was called with an incompatible realloc function. [#484] 27- raising a t_QFI or t_QFR to the power n would return a reduced form (OK) except when n = 1. Make it systematic. 28- in rare cases (return 0, native kernel) int_normalize was not suitable for gerepileupto 29- idealnorm(nf, t_POL) didn't work AM 30- [TeXmacs] typo in texmacs_output: x --> [#491] 31- accuracy errors in bnfinit: setrand(3); bnfinit(x^2+999999999999971) [ use a failsafe version of gmod (modr_safe), and increase accuracy if necessary ] 32- possible corruption of gen_2 in mynegi() [ hnflll ] 33- factor(4/x) --> [2, 2; x -1] (content not removed) BA 34- bnrstark prototype code was non-standard. 35- rnfkummer(,,degree) often found too many fields [#482] 36- loss of accuracy in p-adic ellinit: wrong digits and spurious errors: E.g i = 5; ellinit([1, -1, 1, -1, -14]*(1+O(17^i))) 37- missing GC in forvec(,,2) BA 38- Interrupting GP could lead to a freeze. [#488] 39- possible stack corruption in charpoly(,1) 40- Ser(x) raised an error [#499] Changed 1- moved cgiv, gtofp to inline kernel 2- reduce amount of memory needed by APRCL 3- remove CPP from Configure tests (not needed) 4- allow arbitrary sequences (not only expressions) in sum, prod, etc. sum(i = 1, 2, 1;2) --> 4 [ was: error ] 5- checked that no 2-strong pseudoprime passes BSPW primality test up to 10^15 (use Galway's list, extending Pinch's 10^13) 6- random() now uses Brent's XORGEN (replaces congruential linear generator) getrand() returns the FSR internal state array, used by setrand(). The latter no longer returns the input seed. (Initial patch by RR) 7- for install(): parser code 'E' is now obsolete, use 'I' 8- if issquare(x, &n) == 1, always set n to a square root of x 9- if ispower(x, k, &n) == 1, always set n to a k-root of x 10- issquare(t_QFI or t_QFR) now is an error. Use explicitly issquare(component(x,1)) if you relied(?) on the old behaviour 11- [library] rename gener_Fp -> pgener_Fp, gener_Fl -> pgener_Fp [ contrary to 'gener', these assume that their argument is prime ] 12- [library] rename cyclo -> polcyclo, subcyclo -> polsubcyclo, tchebi -> polchebyshev1, legendre -> pollegendre 13- restrict the types allowed in gaffect and gaffsg to scalar types and vectors of such. 14- vecextract(x, bitmask) much faster [ read bits, don't use shifts ] 15- improve hyperu 16- remove gp-specific signal handler. Use the one in libpari 17- [library] pol_1 and pol_x are no longer global arrays but functions 18- [GMP] was inefficient for small sizes (e.g. 1-word operands) 19- optimized rectplothrawin & plot (remove gaffect, use gtodouble whenever possible). Coordinate computations should be faster and more accurate. Added BA 1- function Flm_rank BA 2- Add experimental --enable-tls Configure option and thread-local stack support. Warning: using this option break the ABI. 3- centerlift(t_PADIC) 4- pgener_Zp, pgener_Zl 5- dvdiu, dvdis, dvdiu, dvdsi, affgr 6- cgetipos, cgetineg, togglesign RM 7- polhermite, polchebyshev2 8- allow rnf.zk and rnf.nf 9- [toplevel benchmarks] bnfisintnorm, quadclassunit, rnfkummer 10- ZX_factor, QX_factor 11- allow gzip'ped elldata & galdata files 12- allow t_VECSMALL in vecmin / vecmax BA 13- add pari_stackcheck_init() function to control deep recursion detection 14- Configure --tune flag Removed 1- Odos/Makefile (no longer functional, obsolete) 2- old CodeWarrior-specific hack (malloc) 3- error code: intger2, affer3, overwriter 4- useless static function gp_handle_SIGINT 5- functions changevar() [ use substvec ] and reorder() [ use variable() to get the list of user variables ], global arrays pol_1[], pol_x[] ordvar[] and polvar[] pari-2.17.2/config/0000755000175000017500000000000014760315601012434 5ustar billbillpari-2.17.2/config/get_objdir0000644000175000017500000000163314567450071014500 0ustar billbill# Target directory for object files pre=O objdir=$pre$osname-$arch; if test -n "$dfltobjdir"; then if test "$dfltobjdir" = auto; then case "$kernlvl0" in $asmarch);; sparcv8_micro) if test "$arch" != sparcv9; then objdir=$objdir-$kernlvl0; fi ;; *) objdir=$objdir-$kernlvl0 ;; esac if test -n "$with_gmp"; then objdir=$objdir-gmp; fi dfltobjdir= else objdir="$dfltobjdir" fi fi if test -z "$dfltobjdir"; then case "$optimization" in full) objdir=$objdir;; debugging) objdir=$objdir.dbg ;; profiling) objdir=$objdir.prf ;; gcov) objdir=$objdir.gcov ;; esac fi if test "$fastread" != yes; then cat << EOT ========================================================================== This is the name of the directory where all the object files will be: EOT echo $n ..."Enter dir name : $c" dflt=$objdir; rep=; . ./myread objdir=$ans fi pari-2.17.2/config/DOC_Make.SH0000644000175000017500000001143614567450071014245 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 for f in \ develop\ libpari\ parallel\ users\ tutorial\ tutorial-mf\ refcard\ refcard-ell\ refcard-nf\ refcard-lfun\ refcard-mf\ INSTALL do outdvi="$outdvi $f.dvi" outpdf="$outpdf $f.pdf" done cat > doc/Makefile << EOT # This file was created by Configure. Any change made to it will be lost # next time configure is run. # SHELL = $make_sh PERL = $perl TEX = tex LATEX = latex PDFTEX= pdftex PDFLATEX= pdflatex DESC = pari.desc TMPSUF = .tmp MACROS= paricfg.tex parimacro.tex USERS_TEX=\$(MACROS) 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 usersch8.tex doc all: $outdvi docpdf: $outpdf .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) \$< tutorial-mf.pdf: tutorial-mf.tex \$(PDFLATEX) \$< %.dvi: %.tex \$(MACROS) \$(TEX) \$< tutorial-mf.dvi: tutorial-mf.tex \$(LATEX) \$< libpari.pdf: \$(PARI_TEX) \$(MACROS) -rm -f libpari.std \$(PDFTEX) libpari \$(PDFTEX) libpari \$(MAKE) libpari.std; \$(PDFTEX) libpari; rm -f libpari.std libpari.dvi: \$(PARI_TEX) \$(MACROS) -rm -f libpari.std \$(TEX) libpari \$(TEX) libpari \$(MAKE) libpari.std; \$(TEX) libpari; rm -f libpari.std develop.pdf: develop.tex \$(MACROS) -rm -f develop.std \$(PDFTEX) develop \$(PDFTEX) develop \$(MAKE) develop.std; \$(PDFTEX) develop; rm -f develop.std develop.dvi: develop.tex \$(MACROS) -rm -f develop.std \$(TEX) develop \$(TEX) develop \$(MAKE) develop.std; \$(TEX) develop; rm -f develop.std parallel.pdf: parallel.tex \$(MACROS) -rm -f parallel.std \$(PDFTEX) parallel \$(PDFTEX) parallel \$(MAKE) parallel.std; \$(PDFTEX) parallel; rm -f parallel.std parallel.dvi: parallel.tex \$(MACROS) -rm -f parallel.std \$(TEX) parallel \$(TEX) parallel \$(MAKE) parallel.std; \$(TEX) parallel; rm -f parallel.std tutorial.pdf: tutorial.tex \$(MACROS) -rm -f tutorial.std \$(PDFTEX) tutorial \$(PDFTEX) tutorial tutorial.dvi: tutorial.tex \$(MACROS) -rm -f tutorial.std \$(TEX) tutorial \$(TEX) tutorial %.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 LC_ALL=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 man2html: gpman.html gphelpman.html tex2mailman.html %man.html: %.1 man2html \$< | grep -v 'Content-type:' > \$@ clean: rm -f *.log *.dvi *.idx *.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 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 > tmp_ipf && mv tmp_ipf pari.ipf 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 usersch1.3 usersch2.3 usersch3.3 html: dumbpod appb.html appd.html usersch1.html usersch2.html usersch3.html usersch4.html usersch5.html usersch6.html usersch7.html usersch8.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 $src/funclist $desc $desc/\$(DESC): $src/funclist $desc/merge_822 $desc/PARI/822.pm cd $desc && \$(PERL) merge_822 ../$src/funclist > def\$(TMPSUF) mv $desc/def\$(TMPSUF) \$@ usersch3.tex: $desc/\$(DESC) ../src/desc/doc_make usersFUNCS.tex cat usersFUNCS.tex > usersch3\$(TMPSUF) cd ../src/desc && \$(PERL) doc_make >> ../../doc/usersch3\$(TMPSUF) mv usersch3\$(TMPSUF) \$@ .NOTPARALLEL: EOT fi pari-2.17.2/config/has_sse2.c0000644000175000017500000000066614567450071014325 0ustar billbill#include typedef __v2di bit_array; #define AND(a,b) ((a)&(b)) #define EXT0(a) ((unsigned long)__builtin_ia32_vec_ext_v2di((__v2di)(a), 0)) #define EXT1(a) ((unsigned long)__builtin_ia32_vec_ext_v2di((__v2di)(a), 1)) #define TEST(a) (EXT0(a) || EXT1(a)) #define RBA(a) ((bit_array){((long) a), ((long) a)}) int main(void) { bit_array x = RBA(1L), y = RBA(3L); unsigned long t = TEST(AND(x,y)); (void) t; return 0; } pari-2.17.2/config/get_head0000644000175000017500000000013211636712103014110 0ustar billbillif (head -n 1 < /dev/null >/dev/null 2>&1); then head='head -n' else head='head -' fi pari-2.17.2/config/get_double_format0000644000175000017500000000310514567450071016045 0ustar billbillexe=$osname-$arch-endian$$$exe_suff cmd="$CC $CFLAGS $extraflag endian.c -o $exe"; . log_cmd if test -r $exe; then doubleformat=`$RUNTEST $exe`; else echo "***************************************************************" echo "Cannot compile endian.c. Aborting. PLEASE REPORT!" exit 1 fi . cleanup_exe 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 < int main(){ isatty(0); return 0; } pari-2.17.2/config/checkspaces0000755000175000017500000000132614760123736014646 0ustar billbill#! /bin/sh unset LANG LC_ALL LC_COLLATE LC_CTYPE srcbase="`echo src/*/*.[chy] | sed -e 's,src/language/parse\.[ch],,g'`" CFILES="$srcbase src/*/*/*.[ch] examples/*.c examples/*.gp" docbase="`echo doc/*.tex doc/*.1 | sed -e 's,doc/usersch3.tex,,'`" OFILES="$docbase AUTHORS COMPAT NEW TODO CHANGES src/test/in/* src/functions/*/*" SCRIPTS="config/* src/test/dotest" ALLFILES="$CFILES $OFILES $SCRIPTS" err=0; if grep -P '[\x80-\xff]' $ALLFILES; then echo "BUG: high bit found." err=1; fi if grep ' $' $ALLFILES; then echo "BUG: trailing spaces found." err=1; fi if grep ' ' $CFILES $OFILES; then echo "BUG: TAB found." err=1; fi if grep ' $' $SCRIPTS; then echo "BUG: TAB found in scripts." err=1; fi exit $err pari-2.17.2/config/get_mt0000644000175000017500000000130514567450071013643 0ustar billbillfile=$thread_engine.c MT_LIBS= case $thread_engine in single);; pthread) MT_LIBS="-lpthread" cmd="$CC $CFLAGS $extraflag -o $exe $file $MT_LIBS" . log_cmd if test -r $exe; then . cleanup_exe enable_tls="yes" else echo "### --mt=pthread requires the library pthread" echo "### Please install it" thread_engine=single; fi;; mpi) cmd="$CC $CFLAGS $extraflag -o $exe $file" . log_cmd if test -r $exe; then . cleanup_exe else echo "### --mt=mpi requires to use mpicc" echo "### Please use 'env CC=mpicc ./Configure --mt=mpi'" exit 1; fi;; *) echo "### invalid mt engine $thread_engine" thread_engine=single;; esac echo "Using mt engine $thread_engine" pari-2.17.2/config/get_config_options0000644000175000017500000002142014676526175016255 0ustar billbill# Processing Options dflt_conf_file=pari.cfg fastread=yes config_file= optimization=full target_host= which_graphic_lib=auto thread_engine=single 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]*=//'`;; --mt=*) thread_engine=`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;; -gcov) optimization=gcov;; -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]*=//'`;; --with-runtime-perl=*) runtime_perl=`echo "$1" | sed -e 's/[-a-z]*=//'` ;; --without-readline|--with-readline=no) without_readline=yes ;; --with-readline) with_readline=yes ;; --with-readline=*) 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-qt-lib=*) with_qt_lib=`echo "$1" | sed -e 's/[-a-z]*=//'` ;; --with-qt-include=*) with_qt_include=`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;; --disable-mmap) enable_mmap=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, fltk, ps, svg, win32) --time= timing function to use (getrusage, clock_gettime, times, ftime) --builddir= directory where the object files will be created --tune tune the binary for compiling host (slow) --mt=pthread enable pthread thread engine --mt=mpi enable MPI thread engine Additional developer options: -g creates debugging version (in Oxxx.dbg) -pg creates profiling version (in Oxxx.prf) -gcov creates gcov version (in Oxxx.gcov) --enable-tls enable thread-local stack --disable-mmap (*troubleshooting*) disable mmap usage 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-fltk use the FLTK graphical library [need fltk-config] Miscellaneous --with-runtime-perl[=path-to-perl-binary] for gphelp / tex2mail Environment variables affecting the build: CC C compiler CFLAGS additional flags to the C compiler LD linker LDFLAGS additional linker flags DLLDFLAGS additional linker flags for linking the shared lib C_INCLUDE_PATH directories to search for include files (separate by :) LIBRARY_PATH directories to search for libraries (separate by :) EOT exit 1 ;; verb) cat >&2 < #include #include int main() { &fl_color_cube; return 0; } pari-2.17.2/config/extract_files0000755000175000017500000000141414567450071015224 0ustar billbillif test "$osname" = mingw && test "$sizeof_long" = 8; then src_dir="src64" echo $n "Patching PARI source for LLP64 mode... $c" ./config/convertllp64 > /dev/null echo done fi flist=`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%@runtime_perl@%$runtime_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.17.2/config/arch-osname0000755000175000017500000000556414676526175014611 0ustar billbill#! /bin/sh arch=none; osname=unknown myuname=`(uname -a) 2>/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 -m` case $arch in arm64) arch=aarch64;; esac;; 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]) case "`(prtconf||devinfo)2>&- | grep 'TI,\|FMI,\|Cypress,\|Ross,'`" 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.17.2/config/has_vsnprintf.c0000644000175000017500000000024214567450071015470 0ustar billbill#include #include int main() { return 0; } int f(int i,...) { char s[2]; va_list ap; va_start(ap,i); vsnprintf(s,2," ",ap); return 0; } pari-2.17.2/config/gprc.mingw0000644000175000017500000000023714557721030014435 0ustar billbilllines = 25 colors = "brightfg" prompt = "(%H:%M) gp > " histfile = "gp_history.txt" breakloop = 0 help = "@ perl\\perl gphelp.pl -detex -ch 10 -cb 11 -cu 12" pari-2.17.2/config/has_setsid.c0000644000175000017500000000014411636712103014722 0ustar billbill#include #include pid_t (*f)() = setsid; int main(){ return f != setsid; } pari-2.17.2/config/has_clock_gettime.c0000644000175000017500000000022014557721030016237 0ustar billbill#include #include int main() { struct timespec t; printf("%d",clock_gettime(CLOCK_PROCESS_CPUTIME_ID,&t)); return 0; } pari-2.17.2/config/display0000755000175000017500000000046511636712103014031 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.17.2/config/objdir0000755000175000017500000000026611636712103013634 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.17.2/config/has_avx.c0000644000175000017500000000133614567450071014242 0ustar billbill#include /* Use AVX 256 bit registers for the bit arrays */ typedef unsigned long bit_array __attribute__ ((vector_size (32))); #define EXT0(a) ((unsigned long)a[0]) #define EXT(a,i) ((unsigned long)a[i]) #ifdef __AVX2__ #define TEST(a) ( _mm256_movemask_epi8(_mm256_cmpeq_epi8((__m256i)(a), (__m256i)RBA(0))) != 0xffffffffU ) #elif defined(__AVX__) #define TEST(a) ( !_mm256_testz_si256((__m256i)(a), (__m256i)(a)) ) #else #define TEST(a) (EXT(a,0) || EXT(a,1) || EXT(a,2) || EXT(a,3)) #endif #define RBA(a) ((bit_array){((unsigned long) a), ((unsigned long) a), ((unsigned long) a), ((unsigned long) a)}) int main(void) { bit_array x = RBA(1L), y = RBA(3L); unsigned long t = TEST(x&y); (void) t; return 0; } pari-2.17.2/config/get_modld0000644000175000017500000000200014567450071014313 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 if test -n "$runpathprefix"; then runpth=`./ldflags "$LDneedsWl" $runpathprefix"$libdir"` fi case $osname in darwin) MODLD=$CC; MODLDFLAGS="-bundle -undefined dynamic_lookup -L$libdir $LDDYN \$(CFLAGS) \$(DLCFLAGS)";; *) MODLD="$DLLD"; MODLDFLAGS=`echo "$DLLDFLAGS" | \ sed -e 's/,*-[^ \t-]*[ \t,=]*\\$(LIBPARI_SONAME)//' \ -e 's/,--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 $runpth $EXTRAMODLDFLAGS" | \ sed -e 's!\$(CFLAGS)'"!$CFLAGS!g" \ -e 's!\$(DLCFLAGS)'"!$DLCFLAGS!g"` pari-2.17.2/config/has_neon.c0000644000175000017500000000057514567450071014407 0ustar billbilltypedef unsigned long bit_array __attribute__ ((vector_size (16))); #define EXT0(a) ((unsigned long)a[0]) #define EXT(a,i) ((unsigned long)a[i]) #define AND(a,b) ((a)&(b)) #define TEST(a) (EXT0(a) || EXT(a,1)) #define RBA(a) ((bit_array){((long) a), ((long) a)}) int main(void) { bit_array x = RBA(1L), y = RBA(3L); unsigned long t = TEST(AND(x,y)); (void) t; return 0; } pari-2.17.2/config/endian.c0000644000175000017500000000100714567450071014042 0ustar billbill#include #ifdef _WIN64 #define long long long #endif int main() { if (sizeof(long) == 4) { union {double d; unsigned long l[2];} x; x.d = 2.; if (x.l[0]==0 && x.l[1]==(1UL<<30)) printf("1\n"); else if (x.l[1]==0 && x.l[0]==(1UL<<30)) printf("0\n"); else printf("NOT IEEE (32 bit)\n"); } else { union {double d; unsigned long l;} x; x.d = 2.; if (x.l==((unsigned long)1)<<62) printf("-\n"); else printf("NOT IEEE (64 bit)\n"); } return 0; } pari-2.17.2/config/has_gettimeofday.c0000644000175000017500000000022014567450071016114 0ustar billbill#include #include int main(void) { static struct timeval tv0; if(!gettimeofday(&tv0, NULL)) return 1; return 0; } pari-2.17.2/config/get_readline0000644000175000017500000000470514567450071015015 0ustar billbill#exported variables _readline_list="readline readline_version RLINCLUDE RLLIBS" readline= case "$with_readline" in yes|"");; *) if test -z "$with_readline_lib"; then with_readline_lib="$with_readline/lib" fi if test -z "$with_readline_include"; then with_readline_include="$with_readline/include" fi;; esac pth="$with_readline_include" x=`./locate 'readline/readline.h' '' $pth` case $x in ?:/*|/*) rl_include=`dirname $x` echo ..."Found readline header in $rl_include" if (echo $rl_include | grep "readline$" > /dev/null); then rl_include=`dirname $rl_include` RLINCLUDE="-I$rl_include" fi ;; esac exe=$osname-$arch-rlv$$$exe_suff cmd0="$CC $CFLAGS $extraflag $RLINCLUDE -o $exe rl_version.c" try() { RLLIBS=$1; cmd="$cmd0 $1"; . log_cmd; } if test -n "$with_readline_lib"; then readline=$with_readline_lib rl="-L$readline -lreadline" else rl="-lreadline" fi # try linking without locatelib (without -L except --with-xxx-lib) for tlib in "" tinfow tinfo ncursesw ncurses termcap; do t=$rl if test -n "$tlib"; then # need a termcap compatible library? eval with="\$with_${tlib}_lib" if test -n "$with"; then t="$t -L$with -l$tlib" else t="$t -l$tlib" fi fi try "$t" if test -r $exe; then break; fi done readline_version= if test -r $exe; then readline_version=`env LD_LIBRARY_PATH="$LD_LIBRARY_PATH$dir_sep$readline" $RUNTEST $exe`; fi . cleanup_exe case "$readline_version" in *Editline*|*EditLine*) readline= echo "###" echo "### Editline wrapper detected, building without readline support" echo "###";; "") readline= echo "###" echo "### Readline library does not seem to work. Maybe install libncurses?" echo "###";; *) if test -z "$readline"; then readline=yes; fi;; esac if test -n "$readline"; then if test "$fastread" != yes; then cat << EOM ========================================================================== GNU readline provides line editing in the gp shell, with history and context-dependent completions. You should really answer 'yes' to the following question, unless you are trying to overcome a problem in the default build. EOM echo $n "Do you want to use GNU readline library within GP ? $c" rep='y n'; dflt=y; . ./myread case $ans in n) readline=;; esac fi fi if test -z "$readline"; then echo "### Building without GNU readline support" RLLIBS= RLINCLUDE= else echo "Using GNU readline, version $readline_version" fi pari-2.17.2/config/setversion0000755000175000017500000000073614557721030014572 0ustar billbill#!/bin/sh # to be run from the Oxxx directory. Called iff $TOP/.git/index exists TOP=.. cfg=$TOP/config f=paricfg.h rm -f $f.old cp $f $f.old . $cfg/get_head . $cfg/version # need $TOP v="GP/PARI CALCULATOR Version ${version}.${patch} (${status})" sed -e "s,define PARIVERSION.*,define PARIVERSION \"$v\",; s,define PARI_VCSVERSION.*,define PARI_VCSVERSION \"${vcsversion}\",; s,define PARI_VERSION_CODE.*,define PARI_VERSION_CODE ${version_code}," $f.old > $f pari-2.17.2/config/cygwin-postinst0000644000175000017500000000037614557721030015547 0ustar billbillpwd="$(pwd)" echo 'colors = "boldfg"' >> .gprc echo 'help = "'"$pwd"'/perl.exe '"$pwd"'/gphelp -cu 6"' >> .gprc echo 'prettyprinter = "'"$pwd"'/perl.exe tex2mail -TeX -noindent -ragged -by_par"' >> .gprc pwd=${pwd##*/} ./ln -s ../${pwd}/sh.exe ../bin/sh pari-2.17.2/config/get_gmp0000644000175000017500000000506114567450071014011 0ustar billbill#exported variables _gmp_list="gmp GMPLIBS GMPINCLUDE" gmp= case "$with_gmp" in yes|"");; *) if test -z "$with_gmp_lib"; then with_gmp_lib="$with_gmp/lib" fi if test -z "$with_gmp_include"; then with_gmp_include="$with_gmp/include" fi;; esac pth="$with_gmp_include" x=`./locate 'gmp.h' '' $pth` case $x in ?:/*|/*) gmp_include=`dirname $x` echo ..."Found gmp header in $gmp_include" GMPINCLUDE="-I$gmp_include" ;; esac try() { GMPLIBS=$1; cmd="$cmd0 $1"; . log_cmd; } exe=$osname-$arch-gmp$$$exe_suff cmd0="$CC $CFLAGS $extraflag $GMPINCLUDE -o $exe gmp_version.c" if test -n "$with_gmp_lib"; then gmp=$with_gmp_lib try "-L$gmp -lgmp" fi if test ! -r $exe; then try "-lgmp" fi if test ! -r $exe; then lib=gmp; . ./locatelib if test -n "$gmp"; then try "-L$gmp -lgmp" fi fi if test -r $exe; then gmp_version=`env LD_LIBRARY_PATH="$LD_LIBRARY_PATH$dir_sep$gmp" $RUNTEST $exe`; fi case "$gmp_version" in unsupported) gmp= echo "### Your GMP library ABI is unsupported.";; "") gmp= cmd="$CC $CFLAGS $extraflag $GMPINCLUDE -o $exe ansi.c $GMPLIBS" . log_cmd if test -r $exe; then echo "### Your version of GMP is too old for PARI. Please upgrade" else echo "### Your GMP library is incompatible with the compiler settings." fi;; *) if test -z "$gmp"; then gmp=yes; fi;; esac if test -n "$gmp"; then cmd="$CC $CFLAGS $extraflag $GMPINCLUDE -o $exe gmp_mismatch.c $GMPLIBS" . log_cmd if test ! -r $exe; then gmp= echo "### GMP headers mismatch: try both --with-gmp-lib and --with-gmp-include" fi fi . cleanup_exe 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.17.2/config/has_strftime.c0000644000175000017500000000012514557721030015267 0ustar billbill#include int main(){ struct tm *x = NULL; strftime("",1," ",x); return 0; } pari-2.17.2/config/pari.nsi.SH0000644000175000017500000000034514567450071014423 0ustar billbillcfg=$config_dir obj=$objdir file="$obj/pari.nsi" case "$sizeof_long" in 4) bitsize=32;; 8) bitsize=64;; esac; if [ -f "$cfg/$osname-pari.nsi" ]; then echo "Extracting $file" "$cfg/$osname-pari.nsi" $bitsize > "$file" fi pari-2.17.2/config/get_fltk0000644000175000017500000000113214567450071014161 0ustar billbillif test -z "$with_fltk"; then with_fltk=yes fi cmd="FLTK_LIBS=\`fltk-config --ldflags\`" . log_cmd cmd="FLTK_CXXFLAGS=\`fltk-config --cxxflags\`" . log_cmd exe=$osname-$arch-fltk$$$exe_suff cxx=$CXX if test -z "$cxx"; then cxx=g++; fi; # Note: the build system uses $CFLAGS (and not $CXXFLAGS) when # compiling plotfltk.c, so we do the same. cmd="$cxx $FLTK_CXXFLAGS $CFLAGS $FLTK_LIBS -o $exe has_fltk.c" . log_cmd if test -r "$exe"; then echo "Using FLTK library" FLTK_LIBS="$FLTK_LIBS -lstdc++" else echo "### FLTK not found. Building without FLTK support" FLTK_LIBS= fi . cleanup_exe pari-2.17.2/config/has_X11.c0000644000175000017500000000016414557721030014006 0ustar billbill#include #include #include int main(){ (void)XOpenDisplay(NULL); return 0; } pari-2.17.2/config/has_rint.c0000644000175000017500000000011614567450071014413 0ustar billbill#include double (*f)(double) = rint; int main(){ return f != rint; } pari-2.17.2/config/get_graphic_lib0000644000175000017500000000354714676526175015512 0ustar billbillif test "$optimization" = profiling; then which_graphic_lib=none fi _graphic_list="which_graphic_lib X11 X11_INC X11_LIBS \ FLTK_CXXFLAGS FLTK_LIBS gp_mime_open" if test -n "$with_fltk"; then which_graphic_lib=fltk; fi if test "$fastread" != yes; then cat << EOT ========================================================================== GP contains high resolution plotting functions. Choose among none X11 fltk win32 ps svg EOT echo $n ..."Use which graphic library (\"none\" means no hi-res plot) ? $c" rep="none X11 fltk win32 ps"; dflt=$which_graphic_lib; . ./myread which_graphic_lib=$ans fi case $osname in mingw|cygwin) case $which_graphic_lib in auto) which_graphic_lib=win32;; esac;; esac case $which_graphic_lib in auto|X11|x11) . ./get_X11 # X11,X11_INC,X11_LIBS. if test -z "$X11_LIBS"; then case $which_graphic_lib in X11|x11) which_graphic_lib=none;; esac else which_graphic_lib=X11 fi;; esac case $which_graphic_lib in auto|fltk) case $osname in darwin) ;; # fltk brings in CoreFoundation, incompatible with pari_daemon *). ./get_fltk # FLTK_LIBS ;; if test -z "$FLTK_LIBS"; then case $which_graphic_lib in fltk) which_graphic_lib=none;; esac else which_graphic_lib=fltk fi;; esac;; esac case $which_graphic_lib in auto|svg) which_graphic_lib=svg;; esac case $which_graphic_lib in auto|PS|ps) which_graphic_lib=ps;; esac case $which_graphic_lib in X11|fltk|ps|svg) if test "$has_waitpid" = no -o "$has_setsid" = no; then echo "### Missing waitpid() or setsid(), no Hi-Res graphing window" which_graphic_lib=none fi;; esac case $osname in linux|gnu*|*bsd) gp_mime_open="xdg-open";; darwin) gp_mime_open="open -W";; esac echo "Hi-Res Graphics: $which_graphic_lib" pari-2.17.2/config/log_cmd0000644000175000017500000000004114557721030013757 0ustar billbillecho $cmd >&5 eval $cmd >&5 2>&1 pari-2.17.2/config/get_PATH0000644000175000017500000000135711636712103013755 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.17.2/config/has_opendir.c0000644000175000017500000000011511636712103015065 0ustar billbill#include #include main() { DIR *d = opendir("."); } pari-2.17.2/config/get_nl0000644000175000017500000000043711636712103013630 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.17.2/config/install0000755000175000017500000000060011636712103014021 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.17.2/config/mingw-pari.nsi0000755000175000017500000001057114567450071015236 0ustar billbill#! /bin/sh . config/version bitsize=$1 release=`echo "$pari_release"|sed 's/\./-/g'` cat << EOT ;--- PARI/GP: NullSoft Installer configuration file !include "MUI.nsh" Name "PARI $pari_release_verbose (${bitsize}bit)" !define dll "libpari.dll" !define PARIver "Pari$bitsize-$release" EOT cat << 'EOT' !define top ".." !define tree "..\mingw" AutoCloseWindow false RequestExecutionLevel highest OutFile "..\${PARIver}.exe" InstallDir "$PROGRAMFILES\${PARIver}" InstallDirRegKey HKLM "Software\${PARIver}" "" !define MUI_ABORTWARNING !insertmacro MUI_PAGE_WELCOME !insertmacro MUI_PAGE_LICENSE "${top}\COPYING" !insertmacro MUI_PAGE_COMPONENTS !insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_PAGE_FINISH !insertmacro MUI_UNPAGE_WELCOME !insertmacro MUI_UNPAGE_CONFIRM !insertmacro MUI_UNPAGE_INSTFILES !insertmacro MUI_UNPAGE_FINISH !insertmacro MUI_LANGUAGE "English" ;-------------------------------- ;Installer Sections !define uninst "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PARIver}" Section "pari (required)" SecCopy SetOutPath "$INSTDIR" File "${tree}\bin\gp.exe" File "${tree}\bin\${dll}" File /oname=gphelp.pl "${tree}\bin\gphelp" File /oname=gprc.txt "${tree}\gprc.mingw" WriteRegStr HKCU "Software\${PARIver}" "" $INSTDIR WriteRegStr HKLM ${uninst} "DisplayName" "${PARIver} (remove only)" WriteRegStr HKLM ${uninst} "UninstallString" '"$INSTDIR\uninstall.exe"' WriteUninstaller "$INSTDIR\Uninstall.exe" SectionEnd Section "Data files" SecGAL SetOutPath "$INSTDIR" File /r "${tree}\data" SectionEnd Section "documentation" SecDOC CreateDirectory "$INSTDIR\etc" SetOutPath "$INSTDIR" File /r "${tree}\share\pari\doc" File /r "${tree}\perl" File /r "${tree}\share\pari\examples" File /oname=gprc_dft.txt "${tree}\gprc.dft" SectionEnd Section "Development files" SecDEV CreateDirectory "$INSTDIR\include" CreateDirectory "$INSTDIR\lib" SetOutPath "$INSTDIR" File /r "${tree}\lib" File /r "${tree}\include" SectionEnd Function .onInstSuccess MessageBox MB_OK "Thank you for using PARI/GP! Double-click on 'gp' to start the calculator.$\r$\n" ExecShell "open" "$INSTDIR" FunctionEnd !define short "$SMPROGRAMS\${PARIver}" Section "shortcuts" SecSM CreateDirectory "${short}" CreateShortCut "${short}\gp.lnk" "$INSTDIR\gp.exe" "" "$INSTDIR\gp.exe" 0 CreateShortCut "${short}\users.lnk" "$INSTDIR\doc\users.pdf" "" "$INSTDIR\doc\users.pdf" 0 CreateShortCut "${short}\libpari.lnk" "$INSTDIR\doc\libpari.pdf" "" "$INSTDIR\doc\libpari.pdf" 0 CreateShortCut "${short}\tutorial.lnk" "$INSTDIR\doc\tutorial.pdf" "" "$INSTDIR\doc\tutorial.pdf" 0 CreateShortCut "${short}\refcard.lnk" "$INSTDIR\doc\refcard.pdf" "" "$INSTDIR\doc\refcard.pdf" 0 WriteINIStr "${short}\PARI pages.url" "InternetShortcut" "URL" "http://pari.math.u-bordeaux.fr" CreateShortCut "${short}\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 CreateShortCut "$DESKTOP\PARI.lnk" "$INSTDIR\gp.exe" SectionEnd ;-------------------------------- ;Descriptions LangString DESC_SecCopy ${LANG_ENGLISH} "Copy pari files to application folder." LangString DESC_DOC ${LANG_ENGLISH} "Install documentation and online help." LangString DESC_EX ${LANG_ENGLISH} "Install sample GP scripts." LangString DESC_GAL ${LANG_ENGLISH} "Install Pari package files." LangString DESC_DEV ${LANG_ENGLISH} "Add libpari development files." 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 ${SecDEV} $(DESC_DEV) !insertmacro MUI_FUNCTION_DESCRIPTION_END ;-------------------------------- Section "Uninstall" Delete "$INSTDIR\gp.exe" Delete "$INSTDIR\gphelp.pl" Delete "$INSTDIR\gprc_dft.txt" Delete "$INSTDIR\${dll}" RMDir /r "$INSTDIR\perl" RMDir /r "$INSTDIR\etc" RMDir /r "$INSTDIR\doc" RMDir /r "$INSTDIR\examples" RMDir /r "$INSTDIR\data" RMDir /r "$INSTDIR\include" RMDir /r "$INSTDIR\lib" Delete "$INSTDIR\Uninstall.exe" DeleteRegKey HKLM ${uninst} DeleteRegKey /ifempty HKLM "Software\${PARIver}" RMDir /r "$SMPROGRAMS\${PARIver}" Delete "$DESKTOP\PARI.lnk" RMDir "$INSTDIR" SectionEnd EOT pari-2.17.2/config/cygwin-pari.nsi0000755000175000017500000001520414567450071015413 0ustar billbill#! /bin/sh . config/version release=`echo "$pari_release"|sed 's/\./-/g'` cat << EOT ;--- PARI/GP: NullSoft Installer configuration file !include "MUI.nsh" Name "PARI $pari_release_verbose" !define dll "libpari.dll" !define PARIver "Pari-$release" EOT cat << 'EOT' ;--No need to modify things below -- !define top ".." !define cfgdir "${top}\config" AutoCloseWindow false RequestExecutionLevel highest OutFile "Pari.exe" InstallDir "$PROGRAMFILES\${PARIver}" InstallDirRegKey HKLM "Software\${PARIver}" "" !define MUI_ABORTWARNING !insertmacro MUI_PAGE_WELCOME !insertmacro MUI_PAGE_LICENSE "${top}\COPYING" !insertmacro MUI_PAGE_COMPONENTS !insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_PAGE_FINISH !insertmacro MUI_UNPAGE_WELCOME !insertmacro MUI_UNPAGE_CONFIRM !insertmacro MUI_UNPAGE_INSTFILES !insertmacro MUI_UNPAGE_FINISH !insertmacro MUI_LANGUAGE "English" ;-------------------------------- ;Installer Sections !define uninst "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PARIver}" Section "pari (required)" SecCopy SetOutPath "$INSTDIR" File /oname=gp.exe "gp-dyn.exe" File /oname=.gprc "${cfgdir}\cygwin-gprc" File /oname=postinst "${cfgdir}\cygwin-postinst" File "${top}\misc\tex2mail" File "${dll}" FILE "\cygwin\bin\cygcrypt-0.dll" FILE "\cygwin\bin\cygiconv-2.dll" FILE "\cygwin\bin\cygintl-8.dll" File "\cygwin\bin\cyggmp-3.dll" File "\cygwin\bin\cygncursesw-10.dll" File "\cygwin\bin\cygreadline7.dll" File "\cygwin\bin\cygperl5_10.dll" File "\cygwin\bin\cyggcc_s-1.dll" File "\cygwin\bin\cygssp-0.dll" File "\cygwin\bin\cygwin1.dll" File "\cygwin\bin\perl.exe" File "\cygwin\bin\sh.exe" File "\cygwin\bin\ln.exe" SetOutPath "$INSTDIR\terminfo\c" File /nonfatal "\cygwin\usr\share\terminfo\c\cygwin" SetOutPath "$INSTDIR\terminfo\63" File /nonfatal "\cygwin\usr\share\terminfo\63\cygwin" SetOutPath "$INSTDIR" CreateDirectory "$INSTDIR\..\bin" ExecWait 'sh ./postinst' Delete "ln.exe" Delete "postinst" WriteRegStr HKCU "Software\${PARIver}" "" $INSTDIR WriteRegStr HKLM ${uninst} "DisplayName" "${PARIver} (remove only)" WriteRegStr HKLM ${uninst} "UninstallString" '"$INSTDIR\uninstall.exe"' WriteUninstaller "$INSTDIR\Uninstall.exe" SectionEnd SectionGroup /e "Data files" SecDATA Section "Elliptic curves files" SecELL SetOutPath "$INSTDIR\data\elldata" File "${top}\data\elldata\*" SectionEnd Section "Galois files" SecGAL SetOutPath "$INSTDIR\data\galdata" File "${top}\data\galdata\*" SectionEnd Section "Frobenius of elliptic curves files" SecSEA SetOutPath "$INSTDIR\data\seadata" File "${top}\data\seadata\*" SectionEnd Section "Galois polynomial files" SecGPL SetOutPath "$INSTDIR\data\galpol" File "${top}\data\galpol\*" SectionEnd SectionGroupEnd Section "documentation" SecDOC SetOutPath "$INSTDIR" File "${top}\doc\gphelp" SetOutPath $INSTDIR\doc File "${top}\doc\translations" File "${top}\doc\*.tex" File "${top}\doc\*.pdf" SectionEnd Section "examples" SecEX SetOutPath "$INSTDIR" File "${top}\doc\gphelp" SetOutPath $INSTDIR\examples File "${top}\examples\EXPLAIN" File "${top}\examples\Inputrc" File "${top}\examples\*.gp" File "${top}\examples\*.c" File "${top}\examples\Makefile.cygwin-i686" SectionEnd Function .onInstSuccess MessageBox MB_OK "Thank you for using PARI/GP! Double-click on 'gp' to start the calculator.$\r$\nTweak $INSTDIR\.gprc to customize GP: colors, script search path, etc." ExecShell "open" "$INSTDIR" FunctionEnd !define short "$SMPROGRAMS\${PARIver}" Section "shortcuts" SecSM CreateDirectory "${short}" CreateShortCut "${short}\gp.lnk" "$INSTDIR\gp.exe" "" "$INSTDIR\gp.exe" 0 CreateShortCut "${short}\users.lnk" "$INSTDIR\doc\users.pdf" "" "$INSTDIR\doc\users.pdf" 0 CreateShortCut "${short}\libpari.lnk" "$INSTDIR\doc\libpari.pdf" "" "$INSTDIR\doc\libpari.pdf" 0 CreateShortCut "${short}\tutorial.lnk" "$INSTDIR\doc\tutorial.pdf" "" "$INSTDIR\doc\tutorial.pdf" 0 CreateShortCut "${short}\refcard.lnk" "$INSTDIR\doc\refcard.pdf" "" "$INSTDIR\doc\refcard.pdf" 0 WriteINIStr "${short}\PARI pages.url" "InternetShortcut" "URL" "http://pari.math.u-bordeaux.fr" CreateShortCut "${short}\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 CreateShortCut "$DESKTOP\PARI.lnk" "$INSTDIR\gp.exe" SectionEnd ;-------------------------------- ;Descriptions LangString DESC_SecCopy ${LANG_ENGLISH} "Copy pari files to application folder." LangString DESC_DOC ${LANG_ENGLISH} "Install documentation and online help." LangString DESC_EX ${LANG_ENGLISH} "Install sample GP scripts." LangString DESC_DATA ${LANG_ENGLISH} "Data files pertaining to pari" LangString DESC_ELL ${LANG_ENGLISH} "Install elliptic curves data files (for ellsearch and ellidentify)." LangString DESC_GAL ${LANG_ENGLISH} "Install Galois data files (for polgalois in degree > 7)." LangString DESC_SEA ${LANG_ENGLISH} "Install Modular polynomials (for ellap'SEA implementation)." LangString DESC_GPL ${LANG_ENGLISH} "Install Galois polynomials data files (for galoisgetpol)." LangString DESC_SM ${LANG_ENGLISH} "Add PARI shortcuts to Start Menu and desktop." !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN !insertmacro MUI_DESCRIPTION_TEXT ${SecCopy} $(DESC_SecCopy) !insertmacro MUI_DESCRIPTION_TEXT ${SecDATA} $(DESC_DATA) !insertmacro MUI_DESCRIPTION_TEXT ${SecELL} $(DESC_ELL) !insertmacro MUI_DESCRIPTION_TEXT ${SecGAL} $(DESC_GAL) !insertmacro MUI_DESCRIPTION_TEXT ${SecSEA} $(DESC_SEA) !insertmacro MUI_DESCRIPTION_TEXT ${SecGPL} $(DESC_GPL) !insertmacro MUI_DESCRIPTION_TEXT ${SecSM} $(DESC_SM) !insertmacro MUI_DESCRIPTION_TEXT ${SecDOC} $(DESC_DOC) !insertmacro MUI_DESCRIPTION_TEXT ${SecEX} $(DESC_EX) !insertmacro MUI_FUNCTION_DESCRIPTION_END ;-------------------------------- Section "Uninstall" Delete "$INSTDIR\gp.exe" Delete "$INSTDIR\.gprc" Delete "$INSTDIR\gphelp" Delete "$INSTDIR\tex2mail" Delete "$INSTDIR\${dll}" Delete "$INSTDIR\cygcrypt-0.dll" Delete "$INSTDIR\cygiconv-2.dll" Delete "$INSTDIR\cygintl-8.dll" Delete "$INSTDIR\cyggmp-3.dll" Delete "$INSTDIR\cygncursesw-10.dll" Delete "$INSTDIR\cygreadline7.dll" Delete "$INSTDIR\cygperl5_10.dll" Delete "$INSTDIR\cyggcc_s-1.dll" Delete "$INSTDIR\cygssp-0.dll" Delete "$INSTDIR\cygwin1.dll" Delete "$INSTDIR\perl.exe" Delete "$INSTDIR\sh.exe" Delete "$INSTDIR\Uninstall.exe" RMDir /r "$INSTDIR\doc" RMDir /r "$INSTDIR\examples" RMDir /r "$INSTDIR\data" RMDir /r "$INSTDIR\terminfo" DeleteRegKey HKLM ${uninst} DeleteRegKey /ifempty HKLM "Software\${PARIver}" RMDir /r "$SMPROGRAMS\${PARIver}" Delete "$DESKTOP\PARI.lnk" Delete "$INSTDIR\..\bin\sh" RMDir "$INSTDIR\..\bin" RMDir "$INSTDIR" SectionEnd EOT pari-2.17.2/config/ldflags0000755000175000017500000000017511636712103013776 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.17.2/config/get_dlcflags0000644000175000017500000000062611636712103014776 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.17.2/config/get_libc0000644000175000017500000000365214676526175014155 0ustar billbill# Looking in libc for some functions. exe=$osname-$arch-tmp$$$exe_suff _has_list= echo Looking in C lib for some symbols... extra_flags=-lm if test "$arch" = "x86_64" && test "$sizeof_long" = "8"; then list=sse2; . ./look list=avx; . ./look fi if test "$arch" = "aarch64" && test "$sizeof_long" = "8"; then list=neon; . ./look fi list=exp2; . ./look list=log2; . ./look list=rint; . ./look extra_flags= list=strftime; . ./look if test "$timing_fun" = "clock_gettime"; then list=clock_gettime; . ./look if test "$has_clock_gettime" = no; then echo "Try again, with -lrt this time..." extra_flags=-lrt list=clock_gettime; . ./look extra_flags= if test "$has_clock_gettime" = yes; then RT_LIBS=-lrt fi fi else if test -n "$timing_fun"; then list=$timing_fun else case "$osname" in *cygwin*) list='times';; # getrusage based timer always returns 0 *) list='getrusage times';; esac; fi; . ./look fi if test "$has_clock_gettime" = yes -o "$has_ftime" = yes; then : else list='gettimeofday ftime'; . ./look if test "$has_ftime" = yes; then has_ftimeforwalltime=yes unset has_ftime fi fi list=sigaction; . ./look list=TIOCGWINSZ; . ./look list=getrlimit; . ./look list='stat opendir'; . ./look list=vsnprintf; . ./look if test "$enable_mmap" = "no"; then has_mmap=no else list=mmap; . ./look fi list=waitpid; . ./look list=setsid; . ./look list=getenv; . ./look list=isatty; . ./look list=alarm; . ./look list=system; . ./look # For install(). Do we need libdl.so? # on irix and osf1 -ldl not needed 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.17.2/config/has_mmap.c0000644000175000017500000000057414567450071014401 0ustar billbill#include #include #ifndef MAP_ANONYMOUS #define MAP_ANONYMOUS MAP_ANON #endif int main(void) { size_t size = sysconf(_SC_PAGE_SIZE)*1000; void *b = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,-1,0); mmap(b, size, PROT_NONE, MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS,-1,0); munmap(b, size); return 0; } pari-2.17.2/config/cleanup_exe0000644000175000017500000000005314567450071014653 0ustar billbillrm -f $exe rm -rf $exe.dSYM rm -f $exe.mem pari-2.17.2/config/get_install0000644000175000017500000000400114567450071014665 0ustar billbill# Exported variables _install_list="prefix share_prefix bindir datadir includedir libdir mandir sysdatadir " dflt=$prefix; rep= test "$fastread" = yes || cat <) { my ($a,$b); $a = $_; if (/^(\w+)\(/ && ($b = $gp{$1}) && $b ne $1) { $a =~ s/\x7F.*\x01/\x7F$b\x01/; push(@tags,$a); } push(@tags,$_); } } else { system('exuberant-ctags', '-f', $tmptags, @files) && system('ctags-exuberant', '-f', $tmptags, @files) && system('ctags', '-f', $tmptags, @files) && system('ctags', '-dT', '-o', $tmptags, @files) # gctags && die("ctags failed"); open(T,"$tmptags"); # Assume ctags outputs sorted tags (e.g Exuberant Ctags) my ($old) = ""; for (sort(keys %gp)) { my ($a) = $_; my ($b) = $gp{$a}; if ($a eq $old) { push(@tags,"$b$rest\n"); next; } $old = $a; while() { push(@tags,$_); if (/^$a(.*)/) { $rest="$1"; push(@tags,"$b$rest\n"); last; } } } while() { push(@tags,$_); } @tags = sort(@tags); } close(T); open(OUT,">$tags"); print OUT @tags; unlink $tmptags; # $gp{GP_function} = C_function sub getnames { open(A,$_[0]); while () { if (/^entree functions_/../^$/) { if (/[^"]*"([^"]*)".*\(void\*\) *([^,]*)/) { my ($gpfun, $cfun) = ($1,$2); $gpfun =~ s/_\.//g; # member functions $gp{$cfun} = $gpfun; } } } close(A); } sub filter_c { return unless /\.[chy]\Z/ && -f; return if (/(dummy|tune|kerntest|parse)\.c/); push @files, "$File::Find::name"; } pari-2.17.2/config/has_log2.c0000644000175000017500000000011611636712103014271 0ustar billbill#include double (*f)(double) = log2; int main(){ return f != log2; } pari-2.17.2/config/has_system.c0000644000175000017500000000012614567450071014764 0ustar billbill#include int (*f)(const char*) = system; int main(){ return f != system; } pari-2.17.2/config/get_pretty0000644000175000017500000000067214567450071014560 0ustar billbillpretty="$prettya running $osname" case "$kernlvl1" in gmp) if test -n "$gmp_version"; then prettyk="$prettyk0/GMP-%s" else prettyk="$prettyk0/GMP" fi;; none) prettyk="$prettyk0";; *) prettyk="$prettyk0/$kernlvl1";; esac case "$sizeof_long" in 4) prettyf="$pretty ($prettyk kernel) 32-bit version";; 8) prettyf="$pretty ($prettyk kernel) 64-bit version";; esac; pretty=`echo $prettyf | sed s/-%s//` pari-2.17.2/config/ansi.c0000644000175000017500000000005511636712103013527 0ustar billbillint main(int argc, char **argv){ return 0; } pari-2.17.2/config/genfunclist0000755000175000017500000000052114760123736014707 0ustar billbill#! /bin/sh FL="$1" DIR="$2" TMPFL=$FL.tmp$$ (cd $DIR && 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.17.2/config/TOP_Make.SH0000644000175000017500000001065614760123736014305 0ustar billbillfile=Makefile echo "Extracting $file" rm -f $file dosversion=`echo $version|sed -e 's/\.//g'` dosversion="_$dosversion$patch" __status__=$status case "$status" in development*) __status__='snapshot';; esac cat > $file << EOT # This file was created by Configure. All changes made will be lost # next time Configure is run. # SHELL = $make_sh VERS = pari-$version.$patch $__status__ TAG=release-$VersionMajor-$VersionMinor-$patch dft target:: @echo "Main targets: we suggest 'make all', then 'make install' as root" @echo " all Compilation + Documentation" @echo " gp Compilation" @echo " bench Compilation + Quick test" @echo " dobench Quick test only" @echo " doc Documentation only" @echo " install Installation" @echo " clean, cleantest Clean up" @echo "For pari maintainers:" @echo " dbg Compile gp binary suitable for debugging" @echo " prf Compile gp binary suitable for profiling" @echo " gcov Compile gp binary for test coverage reporting" @echo " alpha, beta, release Tarfile for official source distribution" @echo " snapshot, distrib Tarfile for source snapshot" @echo " nsis Create a NSIS installer for win32" @echo " ctags Generate VI/VIM tags file in ./src" @echo " etags Generate Emacs tags file in ./src" @echo " tune Generate tuning utility" @echo " test-all Thorough regression tests (slow)" all:: @\$(MAKE) gp @-cd doc && \$(MAKE) doc gp bench test-kernel test-all install cleanall cleanobj cleantest nsis link-data install-bin install-doc install-doctex install-docdvi install-docpdf install-nodata install-data install-lib-sta install-bin-sta dobench dyntest-all statest-all tune $top_test_extra $top_dotest_extra:: @dir=\`config/objdir\`; echo "Making \$@ in \$\$dir";\\ if test ! -d \$\$dir; then echo "Please run Configure first!"; exit 1; fi;\\ cd \$\$dir && \$(MAKE) \$@ dbg gp.dbg:: @dir=\`config/objdir\`.dbg; echo "Making gp in \$\$dir";\\ if test ! -d \$\$dir; then echo "Please run Configure -g first!"; exit 1; fi;\\ cd \$\$dir && \$(MAKE) gp prf gp.prf:: @dir=\`config/objdir\`.prf; echo "Making gp in \$\$dir";\\ if test ! -d \$\$dir; then echo "Please run Configure -pg first!"; exit 1; fi;\\ cd \$\$dir && \$(MAKE) gp gcov gp.gcov:: @dir=\`config/objdir\`.gcov; echo "Making gp in \$\$dir";\\ if test ! -d \$\$dir; then echo "Please run Configure -gcov first!"; exit 1; fi;\\ cd \$\$dir && \$(MAKE) gp doc docps docpdf gpman cleandoc:: cd doc && \$(MAKE) \$@ clean:: cleandoc cleanall clean.dbg:: @dir=\`config/objdir\`.dbg; echo "Making clean in \$\$dir";\\ if test ! -d \$\$dir; then echo "Nothing to be done"; exit 1; fi;\\ cd \$\$dir && \$(MAKE) clean clean.prf:: @dir=\`config/objdir\`.prf; echo "Making clean in \$\$dir";\\ if test ! -d \$\$dir; then echo "Nothing to be done"; exit 1; fi;\\ cd \$\$dir && \$(MAKE) clean clean.gcov:: @dir=\`config/objdir\`.gcov; echo "Making clean in \$\$dir";\\ if test ! -d \$\$dir; then echo "Nothing to be done"; exit 1; fi;\\ cd \$\$dir && \$(MAKE) clean bench.dbg:: @dir=\`config/objdir\`.dbg; echo "Making bench in \$\$dir";\\ if test ! -d \$\$dir; then echo "Please run Configure -g first!"; exit 1; fi;\\ cd \$\$dir && \$(MAKE) bench bench.prf:: @dir=\`config/objdir\`.prf; echo "Making bench in \$\$dir";\\ if test ! -d \$\$dir; then echo "Please run Configure -pg first!"; exit 1; fi;\\ cd \$\$dir && \$(MAKE) bench bench.gcov:: @dir=\`config/objdir\`.gcov; echo "Making bench in \$\$dir";\\ if test ! -d \$\$dir; then echo "Please run Configure -gcov first!"; exit 1; fi;\\ cd \$\$dir && \$(MAKE) bench distrib: $config_dir/settar \$(VERS) $__status__ setdoc: cd doc && \$(MAKE) usersch3.tex alpha: setdoc $config_dir/settar \$(VERS) alpha beta: setdoc $config_dir/settar \$(VERS) beta release: setdoc $config_dir/settar \$(VERS) released snapshot: setdoc $config_dir/settar \$(VERS) snapshot dosdistrib: gpman -zip -kr GPB${dosversion}.ZIP GP.EXE README README.DOS ../EMX/README.DOC ../RSX/README.TXT -zip -k GPD${dosversion}.ZIP doc/*.tex doc/gphelp doc/gp.man examples misc/gprc* misc/gpalias etags: config/make_tags --emacs "$TOP/src" ctags: config/make_tags --vi "$TOP/src" checkspaces: config/checkspaces .NOTPARALLEL: EOT pari-2.17.2/config/get_cc0000644000175000017500000001063114676526175013624 0ustar billbill# Exported variables _cc_list="__gnuc__ CC CFLAGS optimization DBGFLAGS OPTFLAGS exe_suff suffix ASMINLINE KERNELCFLAGS" # Which optimization ? if test "$fastread" != yes; then cat << EOT ========================================================================== The default is to fully optimize the compilation. You may choose to build an executable for debugging or profiling instead. Choose among : full debugging profiling gcov EOT echo $n ..."Which optimization do you prefer ? $c" dflt=$optimization; rep='full debugging profiling gcov'; . ./myread optimization=$ans fi case "$osname" in os2) exe_suff=.exe; extraflag="-Zexe";; emscripten) exe_suff=.js;; cygwin|mingw) exe_suff=.exe; extraflag="";; # On Darwin, by default, the full library search path is searched for a .dylib # before a .a can be considered, preventing users to install their libraries # in a simple way (e.g. the readline / Editline conflict). Override this. darwin) exe_suff=; extraflag=-Wl,-search_paths_first;; *) exe_suff=; extraflag="";; esac if test -z "$CC"; then echo Choosing C compiler ... if test -n "$gcc"; then CC=$gcc; else CC=$cc; fi fi if test "$fastread" != yes; then cat << EOT ========================================================================== Only ANSI C and C++ compilers are supported. Choosing the GNU compiler gcc/g++ enables the inlining of kernel routines (about 20% speedup; if you use g++, include the -fpermissive flag). We strongly recommand using gcc all the way through. EOT echo $n ..."Which C compiler shall I use ? $c" dflt=$CC; rep=; . ./myread CC=$ans fi if test -z "$CC"; then cat <&1 |\ grep ' version ' | tr '\n' , | sed -e 's/ *,$//' |\ sed -e 's/(.*) *\((.*)\)/\1/'` echo GNU compatible compiler: $__gnuc__ fi . cleanup_exe fi # Which Flags for Compiler ? cflags= ASMINLINE= if test -n "$__gnuc__"; then __GNUC__="-D__GNUC__" warn="-Wall" OPTFLAGS=-O3 ASMINLINE=yes OPTFLAGS="$OPTFLAGS $warn" cmd="$CC $CFLAGS $extraflag -fno-strict-aliasing -o $exe gnu.c" . log_cmd if test -s $exe; then OPTFLAGS="$OPTFLAGS -fno-strict-aliasing" fi . cleanup_exe case "$optimization" in full) KERNELCFLAGS=-funroll-loops;; esac DBGFLAGS=${DBGFLAGS:-"-g $warn"} # Specific optimisations for some architectures case "$arch" in sparcv8*) cflags=-mv8;; esac # problems on some architectures case "$osname" in os2) cflags="$cflags -Zmt -Zsysv-signals";; nextstep) cflags="$cflags -traditional-cpp";; esac PRFFLAGS="-pg $OPTFLAGS" GCOVFLAGS="-fprofile-arcs -ftest-coverage" else DBGFLAGS=${DBGFLAGS:-'-g'} PRFFLAGS='-pg' case "$osname-$arch" in hpux-*) # -Ae is for ANSI C + defines HPUX_SOURCE OPTFLAGS=-O; cflags=-Ae;; aix-*) OPTFLAGS='-O2 -qtune=auto -qmaxmem=8192' cflags='-qlanglvl=ansi';; osf1-*) OPTFLAGS='-O4 -migrate -ifo -Olimit 9999';; sunos-*) OPTFLAGS=-fast; PRFFLAGS='-pg -Bstatic';; solaris-*) OPTFLAGS='-fast -fsimple=1'; PRFFLAGS=-xpg; case "$arch" in sparc*) OPTFLAGS="$OPTFLAGS -xalias_level=any";; esac;; concentrix-*) OPTFLAGS=-Ogi;; *) OPTFLAGS=-O;; esac PRFFLAGS="$PRFFLAGS $OPTFLAGS" fi case "$optimization" in full) suffix=; cflags="$OPTFLAGS $cflags";; profiling) suffix=.prf; cflags="$PRFFLAGS $cflags";; debugging) suffix=.dbg; cflags="-DMEMSTEP=1048576 $DBGFLAGS $cflags";; gcov) suffix=.gcov; cflags="$GCOVFLAGS $cflags";; esac CFLAGS="$cflags $CFLAGS $CPPFLAGS" if test "$fastread" != yes; then echo $n ..."With which flags ? $c" dflt=$CFLAGS; rep=; . ./myread CFLAGS=$ans fi pari-2.17.2/config/gmp_mismatch.c0000644000175000017500000000027314567450071015260 0ustar billbill#include #include int main() { mp_limb_t *x = NULL, *y = NULL; long nx = 0; #ifdef mpn_sqr mpn_sqr(y, x, nx); #else mpn_mul_n(y, x, x, nx); #endif return 0; } pari-2.17.2/config/cygwin-gprc0000644000175000017500000000017314557721030014612 0ustar billbillhelp = "perl.exe gphelp -cu 6" prettyprinter = "perl.exe tex2mail -TeX -noindent -ragged -by_par" prompt = "(%H:%M) gp > " pari-2.17.2/config/rl_version.c0000644000175000017500000000015614567450071014772 0ustar billbill#include #include int main(){ printf("%s\n", rl_library_version); return 0; } pari-2.17.2/config/GEN_Make.SH0000644000175000017500000000276114567450071014252 0ustar billbilldir=examples file=$objdir/Makefile.examples lnfile=Makefile echo Extracting $file rm -f $file $dir/$lnfile 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 (linked with libpari) # libextgcd.so (to be used by "install" under GP) # # Under GP: install("extgcd", "GG&&", "f", "./libextgcd.so") enables # you to subsequently use f(a,b) to call extgcd(a,b) # change this TARGET to compile your own programs TARGET = extgcd SHELL = $make_sh DBGFLAGS = $DBGFLAGS CFLAGS = $OPTFLAGS EXTRACFLAGS= #CFLAGS = \$(DBGFLAGS) 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) \$(DYN) all: \$(ALL) dynlib: \$(DYN) \$(DYN): \$(OBJS) \$(MODLD) -o \$@ \$(MODLDFLAGS) \$(EXTRACFLAGS) \$(OBJS) \$(EXTRAMODLDFLAGS) \$(TARGET): \$(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 ../$file $lnfile ) pari-2.17.2/config/settar0000755000175000017500000000146014567450071013673 0ustar billbill#!/bin/sh dir=$1; status=$2; # true status (probably 'snapshot') STATUS=$3; # status we're being coerced into case "$STATUS" in alpha|beta) dir="$dir.$STATUS";; snapshot) STATUS="development git-"`git log -1 --pretty=format:%h`; dir=`git describe` case $dir in pari-*);; *) dir=pari-$dir;; esac ;; esac if test -d $dir; then echo "Remove $dir before building a new release"; exit 1 fi tarfile=$dir.tar tar cf $tarfile `config/get_MANIFEST` mkdir $dir && mv $tarfile $dir cd $dir && tar xf $tarfile && rm -f $tarfile && cd .. if test "$status" != "$STATUS"; then v=$dir/config/version mv $v $v.old sed -e "s/^stat=.*/stat=\'$STATUS\'/" $v.old > $v rm -f $v.old fi tar cf $tarfile $dir rm -rf $dir rm -f $tarfile.gz gzip $tarfile pari-2.17.2/config/has_sigaction.c0000644000175000017500000000031414557721030015412 0ustar billbill#include int main() { struct sigaction sa, oldsa; sa.sa_handler = SIG_DFL; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_NODEFER; (void)(sigaction(SIGINT, &sa, &oldsa)); return 0; } pari-2.17.2/config/kernel-name0000755000175000017500000000113111636712103014551 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.17.2/config/has_getrusage.c0000644000175000017500000000033514557721030015423 0ustar billbill#define _INCLUDE_POSIX_SOURCE #include #include #include #include #include int main(){ struct rusage a; printf("%d",getrusage(RUSAGE_SELF,&a)); return 0; } pari-2.17.2/config/has_waitpid.c0000644000175000017500000000015414557721030015075 0ustar billbill#include #include #include int main(){ waitpid(-1,NULL,0); return 0; } pari-2.17.2/config/has_getenv.c0000644000175000017500000000007614557721030014727 0ustar billbill#include int main(){ (void)getenv(""); return 0; } pari-2.17.2/config/look0000755000175000017500000000066614567450071013344 0ustar billbill# Look for functions in $list. Return as soon as the first function is found, # defining has_$fun for fun in $list; do cmd="$CC $CFLAGS has_$fun.c -o $exe $extra_flags"; . log_cmd if test -s $exe ; then eval "has_$fun=yes"; echo ..."Found $fun." case "$_has_list" in *has_$fun*);; *) _has_list="$_has_list has_$fun";; esac break fi eval "has_$fun=no"; echo ..."I did not find $fun." done . cleanup_exe pari-2.17.2/config/kernel.c0000644000175000017500000000047414557721030014066 0ustar billbill#define ulong unsigned long #define ASMINLINE #include "asm0.h" #define __asm__ __asm__ volatile void fun(ulong a, ulong b) { LOCAL_HIREMAINDER; LOCAL_OVERFLOW; addll(a,b); addllx(a,b); mulll(a,b); addmul(a,b); #if 0 bfffo(a); #endif } int main(void) { fun(0xb9f3dcdcUL,0xfbdc740b); return 0; } pari-2.17.2/config/has_alarm.c0000644000175000017500000000013611636712103014524 0ustar billbill#include unsigned int (*f)(unsigned int) = alarm; int main(){ return f != alarm; } pari-2.17.2/config/has_ftime.c0000644000175000017500000000014414567450071014544 0ustar billbill# include int main() { struct timeb t; ftime(&t); return t.time*1000+t.millitm; } pari-2.17.2/config/gnu.c0000644000175000017500000000011111636712103013357 0ustar billbill#ifdef __GNUC__ int main(){return 0;} #else int main(){return 1;} #endif pari-2.17.2/config/get_archos0000644000175000017500000000207314567450071014505 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 aarch64 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.17.2/config/convertllp640000755000175000017500000000342214567450071014733 0ustar billbill#!/bin/sh # This script is intended to be run from the pari directory. It will make the following # changes to all source code in preparation for making on mingw64: # 1.) Convert 32 bit constants to 64 bit constants (i.e. L->LL and UL->ULL), # 2.) Convert formatting in printf/sprintf/fprintf (i.e. %ld->%lld, %lu->%llu, etc). test -d config || cd .. test -d config || exit 1 test -d src64 && rm -rf src64 cd src for file in `find . -type f -name "*.[chy]"` ; do outfile="../src64/$file" mkdir -p `dirname $outfile` echo "converting file: $file -> $outfile" # Add LL to the end of any constant with 10 or more numbers ## disabled, should not be necessary, overgreedy # sed 's/\([-+({ ][0-9]\{10,\}\)\([,;:)} ]\)/\1LL\2/g' < $file > TMP # Convert all decimal constants ending in L or UL. # Note: replacing strings with lower case l breaks a couple things, namely strings like "%+1ld" sed -e 's/\([-+* ,()=~&|%][0-9][0-9]*\)[L]\{1,2\}/\1LL/g' -e 's/\([-+* ,()=~&|%][0-9][0-9]*\)[uU][lL]\{1,2\}/\1ULL/g' < $file > TMP2 # Convert all hexadecimal constants ending in L or UL. sed -e 's/\(0x[0-9a-fA-F][0-9a-fA-F]*\)[lL]\{1,2\}/\1LL/g' -e 's/\(0x[0-9a-fA-F][0-9a-fA-F]*\)[uU][lL]\{1,2\}/\1ULL/g' < TMP2 > TMP # String formatting conversions: %ld -> %lld, %lu -> %llu, %lx -> %llx. # This will also handle cases like %+2ld and %0*lx # Replace formatting with microsoft ll convention, but only inside regular printfs # (and its variants) # Do nothing inside of pari_printf() or pari_sprintf(). sed -e '/\"/ s/\(%[-+]\{0,1\}[0-9]*\)ld/\1lld/g' -e '/\"/ s/\(%[-+]\{0,1\}[0-9]*\)lu/\1llu/g' -e '/\"/ s/\(%[-+]\{0,1\}[0-9]*\)lx/\1llx/g' -e '/\"/ s/\(%[0-9]\*\)lx/\1llx/g' < TMP > $outfile # clean up rm TMP TMP2; done echo "Done." pari-2.17.2/config/locatelib0000755000175000017500000000167414557721030014331 0ustar billbill_pb= # to detect missing .so when .so.x is found for dir in $pth; do base=$dir/lib$lib case "$osname" in os2) try=`ls $base.a 2> /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. Maybe install $lib development files?" echo "### E.g.$rpmlib-devel (RPM) or $devlib-dev (Debian) packages" echo "###" fi fi pari-2.17.2/config/get_tests0000644000175000017500000000210314567450071014362 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_out test_extra test_basic top_test_extra top_dotest_extra' # _not_ included in 'make test-all' (annoying) test_extra_out="ploth io parallel install time" # _not_ included automatically in Oxxx/Makefile (special cased there) test_extra_OUT="env" test_extra_all_out="$test_extra_out $test_extra_OUT" pattern_out=`echo $test_extra_all_out | sed -e 's/ /\\\\|/g'` # included in 'make bench' test_basic="\ objets\ analyz\ number\ polyser\ linear\ elliptic\ sumiter\ graph\ program\ trans\ nfields_200\ " # included in 'make test-all' in addition to regular components of 'make bench' test_extra=`ls "$TOP"/src/test/in | grep -v "\b\($pattern_out\)\b" | tr '\n' ' '` all_tests="$test_extra $test_extra_out $test_extra_OUT" top_test_extra="test-`echo $all_tests | sed -e 's/ \\([^ ]\\)/ test-\\1/g'`" top_dotest_extra="dotest-`echo $all_tests | sed -e 's/ \\([^ ]\\)/ dotest-\\1/g'`" pari-2.17.2/config/has_exp2.c0000644000175000017500000000011611636712103014304 0ustar billbill#include double (*f)(double) = exp2; int main(){ return f != exp2; } pari-2.17.2/config/get_X110000644000175000017500000000276014567450071013602 0ustar billbilltdir=$osname-$arch-X11$$ mkdir $tdir; cp Imakefile $tdir; cd $tdir cmd="xmkmf"; . ../log_cmd if test -f Makefile; then eval `make gp-X11 >&5 2>&1 | grep -v make` x11pth="$usrlibdir $libdir"; fi cd ..; rm -rf $tdir # Check xmkmf answer # X11 -- Headers if test ! -f $Xincroot/X11/Xos.h; then x11pth="$addlib64\ /usr/openwin/share/lib\ /usr/openwin/lib\ /usr/X11R6/lib /usr/X11R5/lib /usr/X11R4/lib\ /usr/lib/X11R6 /usr/lib/X11R5 /usr/lib/X11R4\ /usr/local/X11R6/lib /usr/local/X11R5/lib /usr/local/X11R4/lib\ /usr/local/lib/X11R6 /usr/local/lib/X11R5 /usr/local/lib/X11R4\ /usr/X11/lib\ /usr/lib/X11\ /usr/local/X11/lib\ /usr/local/lib/X11\ /usr/XFree86/lib/X11\ /usr/lib\ /usr/local/lib\ /usr/athena/lib\ "; pth=`echo $x11pth | sed 's,/lib,/include,g'` x=`./locate X11/Xos.h '' $pth` case $x in /*) Xincroot=`echo $x | sed 's,/X11/Xos.h,,'`;; *) Xincroot=;; esac fi if test -f $Xincroot/X11/Xos.h; then echo ..."Found X11 header files in $Xincroot/X11" X11_INC="-I$Xincroot" fi # X11 -- Lib exe=$osname-$arch-X11$$$exe_suff cmd0="$CC $CFLAGS $extraflag $X11_INC -o $exe has_X11.c" try() { X11_LIBS=$1; cmd="$cmd0 $1"; . log_cmd; } try "-lX11 $extralib" if test ! -r $exe; then pth=$x11pth lib=X11; . ./locatelib if test -n "$X11"; then try "-L$X11 -lX11 $extralib" fi fi if test ! -r $exe; then echo "### X11 not found" X11_LIBS= X11_INC= fi . cleanup_exe echo ..."X11 libraries: $X11_LIBS" pari-2.17.2/config/Imakefile0000644000175000017500000000016311636712103014242 0ustar billbillgp-X11: @echo 'Xincroot="${INCROOT}"; usrlibdir="${USRLIBDIR}"; libdir="${LIBDIR}";extralib="${EXTRA_LIBRARIES}"' pari-2.17.2/config/Makefile.SH0000644000175000017500000005344414760123736014425 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 if test -n "$add_funclist"; then add_funclist=$src/funclist fi # # File lists # kernel="mpker 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,'` mt="mt $thread_engine" 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'; export_exe='$(LIBPARI)_exe.def';; darwin) ld_install_name="-Wl,-install_name -Wl,\"$libdir\"/\$(LIBPARI_DYN)";; esac case "$osname" in mingw|cygwin) install_implib="\$(INSTALL_DATA) \$(LIBPARI_SO)\$(_A) \$(LIBDIR)/\$(LIBPARI_SO)\$(_A)";; *) install_implib="";; esac PLOTCFLAGS= PLOTLIBS= postconfig=: plotrunpath= case "$which_graphic_lib" in ps|svg|none) graph=plot$which_graphic_lib;; fltk) PLOTCFLAGS="$FLTK_CXXFLAGS" PLOTLIBS="$FLTK_LIBS" postconfig='fltk-config --post ' graph=plotfltk;; win32) PLOTLIBS="-lgdi32" graph=plotWin32;; X11) PLOTCFLAGS="$PLOTCFLAGS $X11_INC" PLOTLIBS="$PLOTLIBS $X11_LIBS" plotrunpath=$X11 graph=plotX;; *) echo >&2 "### Unrecognized graphic library '$which_graphic_lib'." exit 1;; esac libgraph="plotport plottty" KERNOBJS= for f in $kernel; do KERNOBJS="$KERNOBJS $f\$(_O)" done OBJS=$KERNOBJS for f in $basemath $language $modules $systems $mt $libgraph; do OBJS="$OBJS $f\$(_O)" done OBJSGP= for f in $gp $graph; do OBJSGP="$OBJSGP $f\$(_O)" done HEADERS="mpinl.h parimt.h" for f in $hlist; do HEADERS="$HEADERS $src/headers/$f.h"; done graph="$graph $libgraph" # runpath tmp=$runpath for d in "$plotrunpath" "$gmp" "$readline"; do case "$d" in ""|yes) ;; *) case "$tmp" in $d|*$dir_sep$d|*$dir_sep$d$dir_sep*);; *) tmp="$tmp$dir_sep$d";; esac ;; esac 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$exe_suff"; static=y else exec="gp-sta$exe_suff gp-dyn$exe_suff" fi case "$sizeof_long" in 4) numbits=32;; 8) numbits=64;; esac dotest="env \"RUNTEST=\$(RUNTEST)\" \"GPTESTOPT=\$(GPTESTOPT)\" \"LD_LIBRARY_PATH=.$dir_sep\$\$LD_LIBRARY_PATH\" \$(SHELL) ../src/test/dotest $numbits \"$exe_suff\"" case "$static" in n) dft=dyn; libdft=lib-dyn; dfttarget="gp-dyn gp-sta";; y) dft=sta; libdft= ; dfttarget="gp-sta";; 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 RANLIB = ranlib 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 GPTESTOPT = $GPTESTOPT # 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_EXE = $export_exe 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 MT_LIBS = $MT_LIBS RT_LIBS = $RT_LIBS DL_LIBS = $DL_LIBS DYN_LIBS = \$(GMPLIBS) \$(DL_LIBS) \$(RT_LIBS) \$(MT_LIBS) \$(LIBS) STA_LIBS = \$(GMPLIBS) \$(DL_LIBS) \$(RT_LIBS) \$(MT_LIBS) \$(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 TAR = tar # Readline RLINCLUDE = $RLINCLUDE RLLIBS = $RLLIBS # GMP GMPINCLUDE = $GMPINCLUDE # Graphic library. PLOTCFLAGS = $PLOTCFLAGS PLOTLIBS = $PLOTLIBS CXX = g++ 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 TESTS = $test_extra .PHONY: gp dft clean dft: $dfttarget ../gp$suffix$exe_suff $libdft gp: gp-$dft ../gp$suffix$exe_suff $libdft ../gp$suffix$exe_suff: gp-$dft$exe_suff -\$(RM) \$@ -\$(LN) $ln_objdir/gp-$dft$exe_suff \$@ 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/32/kernel > kern.dif;\ if test -s kern.dif; then echo "KERNEL BUG"; else echo OK; fi tune\$(_O): .headers $src/test/tune.c \$(CC) \$(GMPFLAGS) \$(CPPFLAGS) \$(CFLAGS) -o \$@ $src/test/tune.c -c tune: mpinl.h tune-sta -\$(RM) tune ../tune -\$(LN) tune-sta tune -\$(LN) $ln_objdir/tune ../tune tune-dyn: tune\$(_O) \$(LIBPARI_DYN) \$(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$exe_suff: $add_funclist \$(OBJS) \$(OBJSGP) \$(EXPORT_EXE) \$(RM) \$@ \$(LD) -o \$@ \$(LDFLAGS) \$(OBJS) \$(OBJSGP) \$(RUNPTH) \$(RLLIBS) \$(PLOTLIBS) \$(STA_LIBS) \$(EXPORT_EXE) $postconfig gp-sta$exe_suff clean_pari_ps:: @-\$(RM) pari.ps cleantest: \$(RM) *.dif gp.out io-testfile pari.ps cleanobj: -\$(RM) *\$(_O) mpker.c *.s parimt.h mpinl.h parilvl0.h parilvl1.h libpari* $exec kerntest -\$(RM) gmon.out -\$(RM) *.gcno *.gcda cleandesc: -\$(RM) $desc/\$(DESC) *\$(TMPSUF) cleantune: -\$(RM) tune tune-sta tune\$(_O) cleanall: cleanobj cleantune cleantest cleandesc clean: cleanall # Use this version to avoid problems with NFS and slightly out of synch # fileserver/host. We are recompiling everything anyway. Not on by default: # 3s is slower than the whole compilation on our development server :-) # .headers: $HEADERS # @sleep 3; touch \$@ .headers: $HEADERS @touch \$@ install-nodata: install-lib-$dft install-include install-bin install-man install-misc install-examples install-cfg install: install-doc install-nodata install-data install-include: -mkdir -p \$(INCLUDEDIR)/pari -for i in paricfg.h mpinl.h parimt.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$exe_suff 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) -\$(STRIP) \$(STRIPFLAGS) \$(BINDIR)/gp-$version$exe_suff -cd \$(BINDIR); $postconfig gp-$version$exe_suff -\$(LN) gp-$version$exe_suff \$(BINDIR)/gp$exe_suff install-bin-sta: gp-sta$exe_suff -mkdir -p \$(BINDIR) -\$(RM) \$(BINDIR)/gp-$version$exe_suff \$(BINDIR)/gp$exe_suff \$(INSTALL_PROGRAM) gp-sta$exe_suff \$(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 -cd \$(BINDIR); $postconfig 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_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: install-docdvi install-doctex install-doctex: -mkdir -p \$(BINDIR) \$(DOCDIR) -\$(INSTALL_DATA) $doc/translations \$(DOCDIR) -\$(INSTALL_PROGRAM) $doc/gphelp \$(BINDIR) -cd $doc; \$(MAKE) usersch3.tex -\$(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/develop.tex \$(DOCDIR) -\$(INSTALL_DATA) $doc/refcard.tex \$(DOCDIR) -\$(INSTALL_DATA) $doc/tutorial.tex \$(DOCDIR) -\$(INSTALL_DATA) $doc/tutorial-mf.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/usersch6.tex \$(DOCDIR) -\$(INSTALL_DATA) $doc/usersch7.tex \$(DOCDIR) -\$(INSTALL_DATA) $doc/usersch8.tex \$(DOCDIR) -\$(INSTALL_DATA) $doc/paricfg.tex \$(DOCDIR) install-docdvi:: -mkdir -p \$(DOCDIR) -cd $doc; \$(MAKE) doc; for f in *.dvi; do \ \$(INSTALL_DATA) \$\$f \$(DOCDIR); \ done install-docpdf:: -mkdir -p \$(DOCDIR) -cd $doc; \$(MAKE) docpdf; for f in *.pdf; do \ \$(INSTALL_DATA) \$\$f \$(DOCDIR); \ done install-examples: -mkdir -p \$(EXDIR) -\$(INSTALL_DATA) $ex/EXPLAIN \$(EXDIR) -\$(INSTALL_DATA) $ex/Inputrc \$(EXDIR) -\$(INSTALL_DATA) Makefile.examples \$(EXDIR)/Makefile -\$(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: mkdir -p \$(DATADIR); \ if test -d $data; then cd $data; \ for d in \`ls\`; do \ test -d "\$\$d" && (\$(TAR) c \$\$d | (cd \$(DATADIR) && \$(TAR) xo )); \ done; \ fi; link-data: mkdir -p \$(DATADIR); \ if test -d $data; then cd $data; \ for d in \`ls\`; do \ \$(LN) \$(TOPDIR)/$data_dir/\$\$d \$(DATADIR)/; \ 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) \$(DYN_LIBS) \$(EXPORT_FILE) \$(LD_INSTALL_NAME) $install_implib install-lib-dyn-link: install-lib-dyn-base -if test "\$(LIBPARI_DYN)" != "\$(LIBDIR)/\$(LIBPARI_SO)"; then \ \$(LN) \$(LIBPARI_DYN) \$(LIBDIR)/\$(LIBPARI_SO); fi -if test "\$(LIBPARI_SONAME)" != "\$(LIBPARI_SO)"; then \ \$(LN) \$(LIBPARI_DYN) \$(LIBDIR)/\$(LIBPARI_SONAME); fi install-lib-dyn: \$(LIBPARI_DYN) install-lib-dyn-link nsis: gp -cd $doc; \$(MAKE) docpdf makensis pari.nsi parimt.h: $src/mt/$thread_engine.h cat $src/mt/$thread_engine.h > parimt.h mpinl.h: parilvl0.h parilvl1.h cat parilvl0.h parilvl1.h > mpinl.h bench: $exec clean_pari_ps @\$(DOTEST) $test_basic dobench:: clean_pari_ps @\$(DOTEST) $test_basic test-all: $exec clean_pari_ps @\$(DOTEST) \$(TESTS) dotest-all:: clean_pari_ps @\$(DOTEST) \$(TESTS) dyntest-all: gp-dyn$exe_suff clean_pari_ps @env dotestSUF=dyn \$(DOTEST) \$(TESTS) statest-all: gp-sta$exe_suff clean_pari_ps @env dotestSUF=sta \$(DOTEST) \$(TESTS) dotest-env:: @export AAA=XXX BBB=YYY; \$(DOTEST) env EOT for i in $test_extra $test_extra_out $test_extra_OUT; do echo "test-$i: $exec dotest-$i" >>$file done for i in $test_extra $test_extra_out; do cat >> $file << EOT dotest-$i:: @\$(DOTEST) $i EOT done if test "$optimization" = gcov; then cat >> $file << EOT .PHONY: lcov-report lcov-reset LCOV_TRACE = lcov.info LCOV_REPORT= lcov-report LCOV_FLAGS= GENHTML_FLAGS= LCOV_TITLE="PARI/GP v$version.$patch lcov report ($status)" lcov-report: \$(RM) \$(LCOV_TRACE) rm -rf \$(LCOV_REPORT) lcov -c \$(LCOV_FLAGS) -d . -b . -o \$(LCOV_TRACE) genhtml \$(GENHTML_FLAGS) --legend -t \$(LCOV_TITLE) -o \$(LCOV_REPORT) \$(LCOV_TRACE) lcov-reset: \$(RM) *.gcda EOT fi if test -n "$exe_suff"; then cat >> $file << EOT gp-sta: gp-sta$exe_suff gp-dyn: gp-dyn$exe_suff EOT fi 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_EXE): \$(OBJS) \$(DLLTOOL) --export-all-symbols -k -z \$@.tmp \$(OBJS) echo "NAME \$(LIBPARI)_exe" > \$@ && cat \$@.tmp >> \$@ rm \$@.tmp \$(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$exe_suff: $add_funclist \$(OBJSGP) \$(LIBPARI_DYN) \$(EXPORT_LIB) \$(RM) \$@ \$(LD) -o \$@ -L\$(TOPLDDYN) \$(LDFLAGS) \$(OBJSGP) \$(RUNPTH) \$(RLLIBS) \$(LDDYN) \$(PLOTLIBS) \$(LIBS) $postconfig gp-dyn$exe_suff \$(LIBPARI_DYN): $add_funclist \$(OBJS) \$(EXPORT_FILE) -\$(RM) \$(LIBPARI_DYN) \$(DLLD_IGNORE)\$(DLLD) -o \$(TOPLDDYN)/\$(LIBPARI_DYN) \$(DLLDFLAGS) \$(OBJS) \$(EXTRADLLDFLAGS) \$(DYN_LIBS) \$(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 .INTERMEDIATE: $src/language/parse.inter $src/language/parse.c $src/language/parse.h: $src/language/parse.inter @: $src/language/parse.inter: $src/language/parse.y \$(BISON) -d $src/language/parse.y -o $src/language/parse.c EOT if test -n "$add_funclist"; then # files generated using external scripts HUGELINE=" $src/funclist:: @-$cfg/genfunclist $src/funclist $desc" suffix='$$$$-$(TMPSUF)' list="funclist init default gp_init" 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 ../$src/funclist" ;; 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_init) target=$src/gp/gp_init.h depend="$desc/\$(DESC) \$(DESC_HELP_GEN)" script="gen_proto gp \$(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/kernel/$kernlvl0/MakeLVL0.SH if test -s $f; then . $f else cat >> $file < parilvl0.h EOT fi vcfile= if test -f "$TOP/.git/index"; then vcfile="../.git/index" else if test -f "$TOP/.git"; then vcfile=`sed -n '/gitdir: / { s/gitdir: \(.*\)/\1/;p;q}' $TOP/.git`/index if test ! -f $vcfile; then echo "Warning: GIT index file not found: $vcfile" vcfile= fi fi fi if test -n "$vcfile"; then cat >> $file <> $file pari-2.17.2/config/has_TIOCGWINSZ.c0000644000175000017500000000044414567450071015143 0ustar billbill#include #include #ifdef __sun # include #endif #include #ifdef __EMSCRIPTEN__ #error TIOCGWINSZ broken with emscripten #endif int main() { struct winsize s; int status = ioctl(0, TIOCGWINSZ, &s); (void)status; return s.ws_col; } pari-2.17.2/config/locatedir0000755000175000017500000000017211636712103014325 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.17.2/config/get_kernel0000644000175000017500000001115214702752432014501 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;; riscv|riscv64) case "$sizeof_long" in 4) asmarch=none; prettya='Risc-V/32';; 8) asmarch=riscv64; prettya='Risc-V/64';; esac;; mips|mips64) case "$sizeof_long" in 4) asmarch=mips; prettya='MIPS';; 8) asmarch=mips64; prettya='MIPS64';; esac;; loongarch|loongarch64) case "$sizeof_long" in 4) asmarch=none; prettya='LoongArch';; 8) asmarch=loongarch64; prettya='LoongArch64';; esac;; alpha) asmarch=$arch; prettya=Alpha ;; ppc|ppc64|ppc64le) case "$sizeof_long" in 4) asmarch=ppc;; 8) asmarch=ppc64;; esac; prettya='PowerPC' ;; arm*|aarch64) case "$sizeof_long" in 4) exe=$osname-$arch-endian$$$exe_suff echo $n "Checking supported ARM kernel: $c" cmd="$CC $CFLAGS -I../src/kernel/arm kernel.c -o $exe"; . log_cmd if test -r $exe; then asmarch=arm; else asmarch=none; fi; echo "$asmarch" . cleanup_exe prettya=$arch;; 8) asmarch=aarch64; prettya=arm64;; esac;; m68k) asmarch=m68k; prettya='Motorola 68k';; sh3) asmarch=none; prettya=SH-3 ;; sh4) asmarch=none; prettya=SH-4 ;; 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 # cat << EOM ========================================================================== EOM 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";; arm) prettyk0="arm";; aarch64) prettyk0="aarch64";; *) prettyk0="$kernlvl0";; esac . get_pretty echo "Building for: $pretty" cat << EOM ========================================================================== EOM pari-2.17.2/config/has_dlopen.c0000644000175000017500000000024214567450071014720 0ustar billbill#include #include int main() { void *handle = dlopen(NULL,RTLD_LAZY); if (handle) printf("%p\n",dlsym(handle, "fun")); return 0; } pari-2.17.2/config/has_times.c0000644000175000017500000000027411636712103014554 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.17.2/config/has_getrlimit.c0000644000175000017500000000027214557721030015435 0ustar billbill#include #include #include int main() { struct rlimit rip; getrlimit(RLIMIT_STACK, &rip); setrlimit(RLIMIT_STACK, &rip); return 0; } pari-2.17.2/config/version0000644000175000017500000000223614760315601014047 0ustar billbill# Major version number VersionMajor='2' # minor version number VersionMinor='17' # Patch level patch='2' # Version code version_code=`expr $VersionMajor \\* 65536 + $VersionMinor \\* 256 + $patch` # Status: alpha, beta, released, development. Rewritten by config/settar ! stat='released' # soname of stable libpari.so is libpari.so.$soname_num status="$stat" patchlevel_verbose= case "$stat" in # $stat rewritten by config/settar ? *git-*) patchlevel_verbose="[ $stat ]";; *) if test -d "$TOP/.git" || test -f "$TOP/.git"; then t=`git rev-list HEAD 2>/dev/null | wc -l` # ~ svn revision number t=`echo $t | sed -e 's/ //g'` # some broken wc prepend spaces T=`git log -1 --pretty=format:%h` # commit hash if test -z "$t"; then t=0; fi vcsversion=$t-$T status="$stat $vcsversion" patchlevel_verbose="[ $status ]" fi esac 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.17.2/config/get_dlld0000644000175000017500000000747214567450071014155 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|*bsd) 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 if dlltool --version >/dev/null 2>&1; then DLLTOOL=dlltool else DLLTOOL=`$CC -dumpmachine`-dlltool fi fi;; darwin)soname= ; sodest= ; DLSUFFIX=dylib; compat_ver=$VersionMajor.$VersionMinor.0; num_ver=$VersionMajor.$VersionMinor.$patch;; *) do_dll=no ;; esac # dlopen(NULL) should return a handle to the running process. # On FreeBSD 2.2.5 (Y. Uchikawa) and Cygwin, this does not work. case "$osname" in freebsd|cygwin) DL_DFLT_NAME="\\\"\$(LIBPARI_DYN)\\\"" ;; mingw) DL_DFLT_NAME="\\\"\$(LIBPARI_SO)\\\"" ;; *) DL_DFLT_NAME=NULL ;; esac # if DLLD is defined at this point, respect it, even if do_dll=no if test $do_dll = yes -a -z "$DLLD"; then if test -n "$__gnuc__" -o "$osname" = "solaris"; then DLLD="$CC" else DLLD=$ld # don't take risks fi fi GNUdlld= DLLDisGCC= if test -n "$DLLD"; then # Which Dynamic Lib Linker? if test "$fastread" != yes; then echo $n ..."Which linker for building dynamic libs? $c" dflt="$DLLD"; rep=; . ./myread DLLD=$ans fi if test "$DLLD" = "$CC" -a -n "$__gnuc__"; then DLLDisGCC=yes; GNUdlld=$GNULDused else case "$DLLD" in *ld) if ($DLLD -v 2>&1 | grep GNU > /dev/null); then GNUdlld=yes; fi;; esac fi # Which Flags for Dynamic Lib Linker ? dlldflags="$DLLDFLAGS" DLLDFLAGS= if test -n "$GNUdlld"; then DLLDFLAGS="-shared -soname=\$(LIBPARI_SONAME)" else # DLLD != GNU ld case "$osname" in aix) DLLDFLAGS='-r' ;; darwin) DLLDFLAGS="-compatibility_version $compat_ver -current_version $num_ver" ;; freebsd) DLLDFLAGS='-Bshareable -x' ;; hpux) DLLDFLAGS='-b' ;; irix) DLLDFLAGS='-shared -elf -no_unresolved -all' ;; osf1) DLLDFLAGS='-shared' ;; solaris) DLLDFLAGS="-G -h \$(LIBPARI_SONAME)" ;; sunos) DLLDFLAGS='-assert nodefinitions' ;; os2) ;; # see below linux) ;; # for e.g. the Portland Group cc (pgcc) *) DLLD=;; esac fi if test -n "$DLLDFLAGS"; then DLLDFLAGS=`./ldflags "$DLLDisGCC" $DLLDFLAGS` fi case "$osname" in os2) DLLDFLAGS="$CFLAGS -Zdll" ;; # assume DLLD = gcc cygwin) DLLDFLAGS="-Wl,--out-implib=\$(LIBPARI_SO)\$(_A),--export-all-symbols";; mingw) DLLDFLAGS="-Wl,--out-implib=\$(LIBPARI_SO)\$(_A)";; esac if test -n "$DLLDisGCC"; then case "$arch-$osname" in sparc-solaris) extra='-mimpure-text';; *) extra=;; esac case "$osname" in darwin) shared=-dynamiclib;; *) shared=-shared;; esac DLLDFLAGS="$shared $extra \$(CFLAGS) \$(DLCFLAGS) $DLLDFLAGS" fi case "$osname" in # Beware: will run through 'eval' [ hence ${...} instead of \$(...) ] gnu*|cygwin|osf1|freebsd|linux|sunos|solaris) EXTRADLLDFLAGS='-lc ${LIBS}';; esac if test "$fastread" != yes; then echo $n ..."Which flags for linker? $c" dflt=$DLLDFLAGS; rep=; . ./myread DLLDFLAGS=$ans fi DLLDFLAGS="$DLLDFLAGS $dlldflags" fi if test -z "$DLLD"; then echo "No Dynamic Lib" else echo "Dynamic Lib linker is $DLLD $DLLDFLAGS" fi pari-2.17.2/config/gmp_version.c0000644000175000017500000000035714567450071015143 0ustar billbill#include #include void f(void) { mpn_gcdext(NULL,NULL, NULL, NULL, 0, NULL, 0); } int main() { if (sizeof(mp_limb_t) == sizeof(long *)) printf("%s\n", gmp_version); else printf("unsupported\n"); return 0; } pari-2.17.2/config/get_ld0000644000175000017500000000341014567450071013621 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 2>/dev/null` 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.17.2/config/has_stat.c0000644000175000017500000000034411636712103014404 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.17.2/config/mpi.c0000644000175000017500000000040014567450071013365 0ustar billbill#include #include int main() { int pari_MPI_size, pari_MPI_rank; int res = MPI_Init(0, NULL); if (res == MPI_SUCCESS) { MPI_Comm_size(MPI_COMM_WORLD, &pari_MPI_size); MPI_Comm_rank(MPI_COMM_WORLD, &pari_MPI_rank); } } pari-2.17.2/config/genkernel0000755000175000017500000000060114567450071014337 0ustar billbill#! /bin/sh src=$1; shift; K=$src/kernel knone=$K/none EXTRA="divll_pre" 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` $EXTRA; do case $i in NOASM);; *) cat $knone/$i.h;; esac; done done exit 0 pari-2.17.2/config/get_static0000644000175000017500000000173411636712103014507 0ustar billbillif test -z "$DLLD" -o "$optimization" != full; then static=y else static=${static-n} fi if test "$fastread" != yes; then if test -z "$DLLD"; then cat < #include static __thread long counter; void *start_routine(void *pt_val) { long val = *(long *)pt_val; counter = val+1; return NULL; } int main(void) { pthread_t thread; counter = 0; if (pthread_create(&thread, NULL, start_routine, &counter)) exit(1); if (pthread_join(thread, NULL)) exit(1); return 0; } pari-2.17.2/config/paricfg.h.SH0000644000175000017500000001021014567450071014531 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 "$osname" = "mingw"\ -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 __PARICFG_H__ #define __PARICFG_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 "${prettyf}${debuginfo}" #define PARI_VERSION_CODE ${version_code} #define PARI_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) #define PARI_VERSION_SHIFT 8 #define PARI_VCSVERSION "${vcsversion}" #define PARI_MT_ENGINE "${thread_engine}" #define PARI_DOUBLE_FORMAT ${doubleformat} EOT if test -n "$__gnuc__"; then echo "#define GCC_VERSION \"$__gnuc__\"" >> $file fi case $asmarch in none) echo '#define __HAS_NO_ASM__' >> $file;; hppa) echo '#define __HPPA__' >> $file;; esac if test -n "$ASMINLINE"; then echo '#define ASMINLINE' >> $file fi if test -n "$gzip"; then cat >> $file << EOT /* Location of GNU gzip program (enables reading of .Z and .gz files). */ #define GNUZCAT #define ZCAT "$gzip -dc" EOT else if test -n "$zcat"; then cat >> $file << EOT /* Location of zcat program (enables reading of .Z files). */ #define ZCAT "$zcat" EOT fi fi if test -n "$gp_mime_open"; then cat >> $file << EOT #define GP_MIME_OPEN "$gp_mime_open" EOT fi if test "$osname" = "mingw"; then cat >> $file << EOT #undef UNIX #define GNUZCAT #undef ZCAT #define ZCAT "gzip.exe -dc" EOT fi if test -n "$readline"; then cat >> $file <> $file;; esac case $has_sse2 in yes) echo '#define HAS_SSE2' >> $file;; esac case $has_avx in yes) echo '#define HAS_AVX' >> $file;; esac case $has_neon in yes) echo '#define HAS_NEON' >> $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_rint" in yes) echo '#define HAS_RINT' >> $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_system" in yes) echo '#define HAS_SYSTEM' >> $file;; esac case "$has_clock_gettime" in yes) echo '#define USE_CLOCK_GETTIME 1' >> $file;; *) case "$has_getrusage" in yes) echo '#define USE_GETRUSAGE 1' >> $file;; *) case "$has_times" in yes) echo '#define USE_TIMES 1' >> $file;; *) case "$has_ftime" in yes) echo '#define USE_FTIME 1' >> $file;; esac;; esac;; esac;; esac case "$has_gettimeofday" in yes) echo '#define USE_GETTIMEOFDAY 1' >> $file;; *) case "$has_ftimeforwalltime" in yes) echo '#define USE_FTIMEFORWALLTIME 1' >> $file;; esac;; esac case $has_sigaction in yes) echo '#define HAS_SIGACTION' >> $file;; esac 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) echo '#define HAS_DLOPEN' >> $file;; 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 $has_mmap in yes) echo '#define HAS_MMAP' >> $file;; esac case $enable_tls in yes) echo '#define ENABLE_TLS' >> $file;; esac echo '#endif' >> $file pari-2.17.2/config/has_wait.c0000644000175000017500000000012611636712103014373 0ustar billbill#include #include #include main(){ wait(NULL); } pari-2.17.2/config/get_perl0000644000175000017500000000103614567450071014166 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=yes; fi fi if test -z "$runtime_perl"; then runtime_perl=$perl fi if test -z "$add_funclist" -a ! -f "../src/language/init.h"; then echo "###" echo "### Please install 'perl' to build from GIT sources" echo "###" exit 1 fi pari-2.17.2/misc/0000755000175000017500000000000014760315601012122 5ustar billbillpari-2.17.2/misc/xgp0000755000175000017500000000140514567450071012654 0ustar billbill#!/bin/sh # # A simple-minded script to launch gp in an xterm. The application name is # set to "gp". You can use it to have specific X resources for the xterm, or # tell your window manager specific preferences, etc. # # iconHint resource is in xterm post Oct 2012. Earlier xterm should ignore. # xterm will seek pari-gp.xpm in current directory (not good but normally # harmless) and xterm's configured system location like /usr/share/pixmaps. # If GP is installed somewhere different than xterm then a full path could # be used. If missing then xterm quietly uses its default icon. # # set correct paths if necessary xterm="xterm" gp="gp" $xterm -geometry 80x40 -sl 2000 -sb \ -name gp -title PARI/GP -rw \ -xrm XTerm.iconHint:pari-gp \ -e $gp & pari-2.17.2/misc/gprc.dos0000644000175000017500000000131111636712103013555 0ustar billbill\\ $Id$ \\ \\ SAMPLE GP INIT FILE (for DOS boxes) \\ \\ See gprc.dft for the general syntax and explanations \\ Customize, then copy to $HOME/_gprc (or $GPRC) or /etc/gprc \\ compatible = 0 \\ read "lib/gpalias" \\ secure = 1 \\ under DOS, directories are separated by ';', not ':' \\ path = ".;~;..;~/gpdir" \\ the readline we supply is old and doesn't have ^A / ^B prompt = "(%H:%M) \e[1mgp\e[m > " #if READL prompt = "(%H:%M) gp > " #if EMACS prompt = "? " #ifnot EMACS colors = "1, 5, no, no, 6, 1, 2" \\ #ifnot EMACS help = "/usr/local/bin/gphelp -detex -ch 4 -cb 0 -cu 2" \\ parisize = 10M \\ primelimit = 1M \\ timer = 1 \\ logfile = "~/tmp/pari-%d.%m" \\ log = 1 \\ psfile = "~/tmp/pari.ps" pari-2.17.2/misc/README0000644000175000017500000000101214567450071013002 0ustar billbillThis directory contains: color.dft: color ressources to use with color_xterm. gpflog : a script to filter out escape sequences from a gp log file gpalias : useful aliases to be read from the gprc gprc.dft : a sample gprc (generic) gprc.dos : a sample gprc for DOS (move it to C:\_GPRC, or to the file $GPRC) tex2mail : an alternate prettyprinter ( for default(output, 3) or \o3 ) xgp : a simple script starting gp in a beefed-up xterm. To use with --mt=mpi: cook.c, mpigp: wrapper for mpirun for interactive use pari-2.17.2/misc/tex2mail.in0000755000175000017500000021664214676526175014235 0ustar billbill#!@runtime_perl@ # Original version by Ilya Zakharevich. Minor updates by the PARI group # Features: # % at the end of a line followed by \n\n is recognized as end of # paragraph :-( # # Original change log is at bottom. # # Options: # linelength=75 # Cut at this line # maxdef=400 # definition loops: croak if many substitutions # debug=0 # by_par=0 # Expect each paragraph to be terminated # # by *exactly* 2 "\n", and do not print # # an extra "\n" between paragraphs # TeX # Assume it is not LaTeX # ragged # leave right ragged # noindent # assume \noindent everywhere # ignorefonts # make math fonts (\mathfrak etc) into NOPs # scissors # Symbol to emit when a long line is cut $@ = ''; $opt_TeX = 1; $opt_noindent = 1; $opt_ragged = 1; $opt_by_par = 1; eval ' use Getopt::Long; &GetOptions( "linelength=i" => \$opt_linelength, "maxdef=i" => \$opt_maxdef, "debug=i" => \$opt_debug, "by_par" => \$opt_by_par, "TeX" => \$opt_TeX, "ragged" => \$opt_ragged, "noindent" => \$opt_noindent, "ignorefonts" => \$opt_ignorefonts, "scissors=s" => \$opt_scissors, "noflush" => \$opt_noflush) '; if ($@ && $@ !~ /Getopt\/Long/) { warn "Errors while parsing command line options $@\n"; } $linelength= $opt_linelength || 75; $maxdef= $opt_maxdef || 10000; $debug=$opt_debug; $opt_scissors = "---8<---8<---" unless defined $opt_scissors; $notusualtoks="\\\\" . '\${}^_~&@'; $notusualtokenclass="[$notusualtoks]"; $usualtokenclass="[^$notusualtoks]"; $macro='\\\\([^a-zA-Z]|([a-zA-Z]+\s*))'; # Why \\\\? double interpretation! $active="$macro|\\\$\\\$|$notusualtokenclass"; $tokenpattern="$usualtokenclass|$active"; $multitokenpattern="$usualtokenclass+|$active"; $| = 1 unless $opt_noflush; # Format of the record: height,length,baseline,expandable-spaces,string # The string is not terminated by \n, but separated into rows by \n. # height=0 denotes expandable string # Baseline=3 means the 4th row is the baseline sub debug_print_record { local($h,$l,$b,$xs,$s) = split /,/, shift, 5; local(@arr) = split /\n/, $s; print STDERR "len=$l, h=$h, b=$b, exp_sp=$xs.\n"; local($i) = 0; for (@arr) { local($lead) = ($i++ == $b) ? 'b [' : ' ['; print STDERR "$lead$_]\n"; } while ($i < $h) { # Empty lines may skipped local($lead) = ($i++ == $b) ? 'b' : ''; print STDERR "$lead\n"; } } # Takes length and a record, returns 2 records sub cut { local($length)=(shift); local($h,$l,$b,$sp,$str)=split(/,/,shift,5); local($st1,$st2)=("",""); local($sp1,$sp2,$first,$l2)=(0,0,1,$l-$length); return (shift,&empty) if $l2<0; if ($h) { for (split(/\n/,$str,$h)) { if (!$first) { $st1 .= "\n"; $st2 .= "\n"; } else {$first=0;} $st1 .= substr($_,0,$length); $st2 .= substr($_,$length); } } else { $st1 = substr($str,0,$length); $st2 = substr($str,$length); #if ($sp && ($st1 =~ /(\S)(\s+\S*)$/)) { # $st2 = $2 . $st2; # $st1 = $` . $1; # $sp1 = ($st1 =~ /(\s)/g); # $sp2 = ($st2 =~ /(\s)/g); #} } return ("$h,$length,$b,$sp1,$st1","$h,$l2,$b,$sp2,$st2"); } # Outputs a record sub printrecord { warn "Printing $_[0]\n__ENDPRINT__\n" if $debug & $debug_record; local($h,$l,$b,$sp,$str)=split(/,/,shift,5); print $str,"\n"; } # Joins two records sub join { local($h1,$l1,$b1,$sp1,$str1)=split(/,/,shift,5); local($h2,$l2,$b2,$sp2,$str2)=split(/,/,shift,5); $h1 || $h1++; $h2 || $h2++; local($h,$l,$b,$sp,$str,@str,@str2)=(0,0,0,$sp1+$sp2,""); $b = $b1 > $b2 ? $b1 : $b2; # Calculate space below baseline $h = $h1-$b1 > $h2-$b2 ? $h1-$b1 : $h2-$b2; # And height $h += $b; $l=$l1+$l2; @str="" x $h; @str[$b-$b1 .. $b-$b1+$h1-1]=split(/\n/,$str1,$h1); @str2[0..$h2-1]=split(/\n/,$str2,$h2); unless (length($str2[$b2])) { $str2[$b2] = ' ' x $l2; # Needed for length=0 "color" strings # in the baseline. } if ($debug & $debug_record && (grep(/\n/,@str) || grep(/\n/,@str2))) { warn "\\n found in \@str or \@str2"; warn "`$str1', need $h1 rows\n"; warn "`$str2', need $h2 rows\n"; } # This is may be wrong if a zero-length record with escape sequences # is appended to with something not on the same row... But # apparently, it should be OK for PARI... for (0..$h2-1) { $str[$b-$b2+$_] .= " " x ($l1 - length ($str[$b-$b2+$_])) . $str2[$_]; } return "$h,$l,$b,$sp," . join("\n",@str); } # The current line is contained in the array @out of records and, possibly, # one additional record $last. If $last exists, $islast is set to 1. # The output channel length is contained in $linelength, the accumulated # length of @out and $last is contained in $curlength. # We guaranty that if $curlength>$linelength, then @out is empty. # Gets a length of a record sub length { (warn "Wrong format of a record `$_[0]'", return 0) unless $_[0] =~ /^\d+,(\d+)/; $1; } # Gets a height of a record sub height { (warn "Wrong format of a record `$_[0]'", return 0) unless $_[0] =~ /^(\d+),/; $1; } # Sets baseline of a record, Usage s...(rec,base) sub setbaseline { (warn("Wrong format of a record `$_[0]'"), return undef) unless $_[0] =~ s/^(\d+,\d+,)(\d+)/\1$_[1]/; } # The hierarchical structure: the records to work are in the array @out. # The array @chunks keeps the beginning record of the chunks, # The array @level keeps the beginning chunks of the given level. # The last chunk can begin after the last record if this chunk is still empty. # We do not keep the inner structure of the chunk unless it is the last # chunk on the given level. # Each record is a rectangle to output to the "page". # Each chunk is a sequence of records which reflect one finished subgroup # on the given level. # Each level is a sequence of chunks which correspond to a # not-yet-finished group in TeX input. # The parallel to @level array @wait # contains an event we wait to complete the given level of array. # Chunks on a given level # Used to expand spaces sub exp_sp {$c1++;$c2=0 if $c1>$re; return " " x ($c2+$fr+1);} # Outputs the outermost level of the output list (until the start of level 1) # If gets a true argument, does not expand spaces sub print { warn "Printing...\n" if $debug & $debug_flow; local($last,$l,$exp) = ($#level? $chunks[$level[1]]-1: $#out); ($last >=0) || return; $l=&length($out[0]); if ($last >= 1) { for (1..$last) { $l += &length($out[$_]); } } if ($debug & $debug_length) { if ($l != $curlength) { for (0..$last) { warn "Wrong lengths Record $_ $out[$_]\n__ENDREC__\n" ; } } } $curlength=$l; warn "l=$l, linelength=$linelength, curlength=$curlength\n" if $debug & $debug_length; IF_L: { if (!shift && ($l=$linelength-$curlength)>=0) { warn "entered branch for long string\n" if $debug & $debug_length; $exp=0; (($out[$last] =~ s/\s+$//) && ($l+=length($&))) if $out[$last] =~ /^0,/; warn "l=$l with whitespace\n" if $debug & $debug_length; last IF_L if $l<=0; local($str,$h,$fr,$re,$c1,$c2,@t); for (0..$last) { ($str,$h)=(split(/,/,$out[$_],5))[4,0]; (@t = ($str =~ /( )/g), $exp+=@t) if (!$h); } if ($exp) { $re=$l % $exp; $fr=int(($l-$re)/$exp); warn "$l Extra spaces in $exp places, Fr=$fr," . " Remainder=$re, LL=$linelength, CL=$curlength\n" if $debug & $debug_length; $c1=0; $c2=1; for (0..$last) { ($str,$h)=(split(/,/,$out[$_],5))[4,0]; unless ($h || $opt_ragged) { $str =~ s/ /&exp_sp/ge; $out[$_]=&string2record($str); } } } } else {warn "Do not want to expand $l spaces\n" if $debug & $debug_length;} } if ($last >= 1) { for (1..$last) { $out[0] = &join($out[0],$out[$_]); } } $l=&length($out[0]); warn "LL=$linelength, CurL=$curlength, OutL=$l\n" if $debug & $debug_length; &printrecord($out[0]); $curlength=0; if ($#out>$last) { @out=@out[$last+1..$#out]; for (0..$#chunks) {$chunks[$_] -= $last+1;} } else { @out=(); } if ($#level) { splice(@chunks,1,$level[1]-2); } else { @chunks=(0); } } # Cuts prepared piece and arg into printable parts (unfinished) # Suppose that level==0 sub prepare_cut { warn "Preparing to cut $_[0]\n" if $debug & $debug_flow; warn "B:Last chunk number $#chunks, last record $#out\n" if $debug & $debug_flow; (warn "\$#level non 0", return $_[0]) if ($#level!=0); local($lenadd)=(&length($_[0])); local($lenrem)=($linelength-$curlength); if ($lenadd+$curlength<=$linelength) { warn "No need to cut, extra=$lenrem\n" if $debug & $debug_flow; return $_[0]; } # Try to find a cut in the added record before $lenrem local($rec)=@_; local($h,$str,$ind,@p)=(split(/,/,$rec,5))[0,4]; local($good)=(0); if ($h<2) { while ($lenrem<$lenadd && ($ind=rindex($str," ",$lenrem))>-1) { warn "Cut found at $ind, lenrem=$lenrem\n" if $debug & $debug_flow; $good=1; # $ind=1 means we can cut 2 chars @p= &cut($ind+1,$rec); warn "After cut: @p\n" if $debug & $debug_record; push(@out,$p[0]); $curlength+=$ind+1; #if ($#out!=$chunks[$#chunks]) {push(@chunks,$#out);} &print(); $rec=$p[1]; ($lenadd,$str)=(split(/,/,$rec,5))[1,4]; $lenrem=$linelength; } return $rec if $good; } # If the added record is too long, there is no sense in cutting # things we have already, since we will cut the added record anyway... local($forcedcut); if ($lenadd > $linelength && $lenrem) { @p= &cut($lenrem,$rec); warn "After forced cut: @p\n" if $debug & $debug_record; push(@out,$p[0]); $curlength+=$lenrem; &print(); $rec=$p[1]; ($lenadd,$str)=(split(/,/,$rec,5))[1,4]; $lenrem=$linelength; } # Now try to find a cut before the added record if ($#out>=0 && !$forcedcut) { for (0..$#out) { ($h,$str)=(split(/,/,$out[$#out-$_],5))[0,4]; if ($h<2 && ($ind=rindex($str," "))>-1 && ($ind>0 || $_<$#out)) { warn "Cut found at $ind, in chunk $#out-$_\n" if $debug & $debug_flow; # split at given position @p=&cut($ind+1,$out[$#out-$_]); $out[$#out-$_]=$p[0]; @p=($p[1],@out[$#out-$_+1..$#out]); @out=@out[0..$#out-$_]; warn "\@p is !", join('!', @p), "!\n\@out is !", join('!', @out), "!\n" if $debug & $debug_flow; &print(); warn "did reach that\n" if $debug & $debug_length; @out=@p; $good=1; $curlength=0; for (@out) {$curlength+=&length($_);} last; } warn "did reach wow-this\n" if $debug & $debug_length; } warn "did reach this\n" if $debug & $debug_length; } return &prepare_cut if $good; warn "No cut found!\n" if $debug & $debug_flow; # If anything else fails use force &print(); print "$opt_scissors\n" if length($opt_scissors) && $h > 1; while (&length($rec)>$linelength) { @p=&cut($linelength,$rec); @out=($p[0]); &print(); print "$opt_scissors\n" if length($opt_scissors) && $h > 1; $rec=$p[1]; } $curlength=0; return $rec; } # Adds a record to the output list sub commit { warn "Adding $_[0]\n" if $debug & $debug_flow; warn "B:Last chunk number $#chunks, last record $#out\n" if $debug & $debug_flow; local($rec)=@_; if ($#level==0) { local($len)=&length($_[0]); if ($curlength+$len>$linelength) { $rec=&prepare_cut; $len=&length($rec); } $curlength+=$len; } push(@out,$rec); if ($#out!=$chunks[$#chunks]) {push(@chunks,$#out);} warn "a:Last chunk number $#chunks, last record $#out, the first chunk\n" if $debug & $debug_flow; warn " on the last level=$#level is $level[$#level], waiting for $wait[$#level]\n" if $debug & $debug_flow; if ($#level && $wait[$#level] == $#chunks-$level[$#level]+1) { local($sub,$arg)=($action[$#level]); if ($sub eq "") {&finish($wait[$#level]);} else { &callsub($sub); } } warn "curlength=$curlength on level=$#level\n" if $debug & $debug_length; } # Calls a subroutine, possibly with arguments sub callsub { local($sub)=(shift); index($sub,";")>=0? (($sub,$arg)=split(";",$sub,2), &$sub($arg)): &$sub; } # Simulates Removing a record from the output list (unfinished) sub uncommit { warn "Deleting...\n" if $debug & $debug_flow; warn "B:Last chunk number $#chunks, last record $#out\n" if $debug & $debug_flow; (warn "Nothing to uncommit", return) if $#out<0; if ($#level==0) { local($len)=&length($out[$#out]); $curlength-=$len; } local($rec); $rec=$out[$#out]; $out[$#out]=&empty(); warn "UnCommit: now $chunks[$#chunks] $rec\n__ENDREC__\n" if $debug & $debug_record; #if ($#out<$chunks[$#chunks]) {pop(@chunks);} warn "a:Last chunk number $#chunks, last record $#out, the first chunk\n" if $debug & $debug_flow; warn " on the last level=$#level is $level[$#level], waiting for $wait[$#level]" if $debug & $debug_flow; warn "curlength=$curlength on level=$#level\n" if $debug & $debug_length; return $rec; } # finish($event, $force_one_group) # Finish the inner scope with the event $event. If this scope is empty, # add an empty record. If finishing the group would bring us to toplevel # and $force_one_group is not set, can break things into chunks to improve # line-breaking. # No additional action is executed sub finish { warn "Finishing with $_[0]\n" if $debug & $debug_flow; local($event,$len,$rec)=(shift); if (($wait[$#level] ne "") && ($wait[$#level] ne $event)) { warn "Got `$event' while waiting for `$wait[$#wait]', rest=$par"; } warn "Got finishing event `$event' in the outermost block, rest=$par" unless $#level; return unless $#level; if ($#out<$chunks[$level[$#level]]) {push(@out,&empty);} # Make anything after $level[$#level] one chunk if there is anything warn "B:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow; $#chunks=$level[$#level]; #if $chunks[$level[$#level]]<=$#out; local(@t); if ($#level==1 && !$_[0]) { @t=@out[$chunks[$#chunks]..$#out]; $#out=$chunks[$#chunks]-1; } # $#chunks-- if $chunks[$#chunks-1]==$chunks[$#chunks]; $#level--; $#action--; $#tokenByToken--; $#wait--; if ($#level==0 && !$_[0]) { for (@t) {&commit($_);} } warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow; if ($wait[$#level] == $#chunks-$level[$#level]+1) { local($sub)=($action[$#level]); if ($sub eq "") {&finish($wait[$#level]);} else {&callsub($sub);} } } # finish level and discard it sub finish_ignore { warn "Finish_ignoring with $_[0]\n" if $debug & $debug_flow; local($event,$len)=(shift); if (($wait[$#level] ne "") && ($wait[$#level] ne $event)) { warn "Got `$event' while waiting for `$wait[$#wait]', rest=$par"; } warn "Got finishing event `$event' in the outermost block, rest=$par" unless $#level; $#out=$chunks[$level[$#level]]-1; pop(@level); pop(@tokenByToken); pop(@action); pop(@wait); } # Begin a new level with waiting for $event # Special events: If number, wait this number of chunks sub start { warn "Beginning with $_[0], $_[1]\n" if $debug & $debug_flow; warn "B:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow; warn "#out=$#out, chunks[first of last level]=$chunks[$level[$#level]], chunk s[-1]=$chunks[$#chunks]" if $debug & $debug_flow; # !@chunks: may be true in \noindent{1\over2} if (!@chunks || ($chunks[$level[$#level]]<=$#out && $chunks[$#chunks]<=$#out)) { # the last level is non empty push(@chunks,$#out+1); } push(@level,$#chunks); push(@tokenByToken,0); $wait[$#level]=shift; if ($#_<0) {$action[$#level]="";} else {$action[$#level]=shift;} warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow; } # Asserts that the given number of chunks exists in the last level sub assertHave { local($i,$ii)=(shift); if (($ii=$#chunks-$level[$#level]+1)<$i) { warn "Too few chunks ($ii) in inner level, expecting $i"; return 0; } return 1; } # Takes the last ARGUMENT chunks, collapse them to records sub collapse { warn "Collapsing $_[0]...\n" if $debug & $debug_flow; local($i,$ii,$_)=(shift); if (($ii=$#chunks-$level[$#level]+1)<$i) { warn "Too few chunks ($ii) in inner level, expecting $i"; $i=$ii; } if ($i>0) { for (0..$i-1) { &collapseOne($#chunks-$_); } for (1..$i-1) { $chunks[$#chunks-$_+1]=$chunks[$#chunks-$i+1]+$i-$_; } } } # Collapses all the chunks on given level sub collapseAll {&collapse($#chunks-$level[$#level]+1);} # Collapses a given chunk in the array @out. No correction of @chunks is # performed sub collapseOne { local($n)=(shift); local($out,$last,$_)=($out[$chunks[$n]]); if ($n==$#chunks) {$last=$#out;} else {$last=$chunks[$n+1]-1;} warn "Collapsing_one $n (last=$#chunks), records $chunks[$n]..$last\n" if $debug & $debug_flow; return unless $last>$chunks[$n]; warn "Collapsing chunk $n beginning at $chunks[$n], ending at $last\n" if $debug & $debug_flow; for ($chunks[$n]+1..$last) { $out=&join($out,$out[$_]); } splice(@out,$chunks[$n],$last+1-$chunks[$n],$out); # $#out-=$last-$chunks[$n]; #bug in perl? warn "Collapsed $chunks[$n]: $out[$chunks[$n]]\n__END__\n" if $debug & $debug_record; } # Return an empty record sub empty { return "0,0,0,0,"; } # Commits a record with a sum symbol sub sum { &commit("4,3,2,0," . <<'EOF'); ___ \ > /__ EOF } # Additional argument specifies if to make not-expandable, not-trimmable sub string2record { local($h,$sp)=(0); if ($_[1]) {$h=1;$sp=0;} else { $sp=($_[0] =~ /(\s)/g); $sp || ($sp=0); # Sometimes it is undef? } return "$h," . length($_[0]) . ",0,$sp,$_[0]"; } # The second argument forces the block length no matter what is the # length the string (for strings with screen escapes). sub record_forcelength { $_[0] =~ s/^(\d+),(\d+)/$1,$_[1]/; } sub finishBuffer { while ($#level>0) {&finish("");} &print(1); } # Takes two records, returns a record that concatenates them vertically # To make fraction simpler, baseline is the last line of the first record sub vStack { local($h1,$l1,$b1,$sp1,$str1)=split(/,/,shift,5); local($h2,$l2,$b2,$sp2,$str2)=split(/,/,shift,5); $h1 || $h1++; $h2 || $h2++; local($h,$l,$b)=($h1+$h2, ($l1>$l2 ? $l1: $l2), $h1-1); warn "\$h1=$h1, \$h2=$h2, Vstacked: $h,$l,$b,0,$str1\n$str2\n__END__\n" if $debug & $debug_record; return "$h,$l,$b,0,$str1\n$str2"; } # Takes two records, returns a record that contains them and forms # SupSub block sub superSub { local($h1,$l1,$b1,$sp1,$str1)=split(/,/,shift,5); local($h2,$l2,$b2,$sp2,$str2)=split(/,/,shift,5); $h1 || $h1++; $h2 || $h2++; local($h,$l)=($h1+$h2+1, ($l1>$l2 ? $l1: $l2)); return "$h,$l,$h1,0,$str1\n\n$str2"; } # Takes two records, returns a record that contains them and forms # SupSub block sub subSuper { local($h1,$l1,$b1,$sp1,$str1)=split(/,/,shift,5); local($h2,$l2,$b2,$sp2,$str2)=split(/,/,shift,5); $h1 || $h1++; $h2 || $h2++; local($h,$l)=($h1+$h2+1, ($l1>$l2 ? $l1: $l2)); return "$h,$l,$h1,0,$str2\n\n$str1"; } # Takes the last two records, returns a record that contains them and forms # SupSub block sub f_subSuper { warn "Entering f_subSuper...\n" if $debug & $debug_flow; &trim(2); &collapse(2); &assertHave(2) || &finish("",1); &sup_sub(0,1); } sub sup_sub { local($p1,$p2)=($#out-shift,$#out-shift); warn "Super $p1 $out[$p1]\nSub $p2 $out[$p2]\n__END__\n" if $debug & $debug_record; local($h1,$l1,$b1,$sp1,$str1)=split(/,/,$out[$p1],5); local($h2,$l2,$b2,$sp2,$str2)=split(/,/,$out[$p2],5); if ($l1==0 && $l2==0) {return;} $h1 || $h1++; $h2 || $h2++; local($h,$l)=($h1+$h2+1, ($l1>$l2 ? $l1: $l2)); $#chunks--; $#out--; if ($l1==0) { $h2++; $out[$#out]="$h2,$l,0,0,\n$str2"; } elsif ($l2==0) { $h=$h1+1; $out[$#out]="$h,$l,$h1,0,$str1\n"; } else { $out[$#out]="$h,$l,$h1,0,$str1\n\n$str2"; } warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow; &finish(2,1); } # Takes the last two records, returns a record that contains them and forms # SupSub block sub f_superSub { warn "Entering f_superSub...\n" if $debug & $debug_flow; &trim(2); &collapse(2); &assertHave(2) || &finish("",1); &sup_sub(1,0); } # digest \begin{...} and similar: handles argument to a subroutine # given as argument sub f_get1 { warn "Entering f_get1...\n" if $debug & $debug_flow; (warn "Argument of f_get1 consists of 2 or more chunks", return) if $#out != $chunks[$#chunks]; local($rec,$sub); #$rec=&uncommit; $rec=$out[$#out]; $rec=~s/.*,//; $sub=shift; defined $sub ? return &$sub($rec): return $rec; } sub f_begin { warn "Entering f_begin...\n" if $debug & $debug_flow; &collapse(1); &assertHave(1) || &finish(""); local($arg,$env)=(&f_get1()); &finish_ignore(1); $arg=~s/^\s+//; $arg=~s/\s+$//; return if defined $environment_none{$arg}; if (defined ($env=$environment{$arg})) { local($b,$e)=split(/,/,$env); for (split(":",$b)) {&callsub($_);} } else {&puts("\\begin{$arg}");} } sub f_end { warn "Entering f_end...\n" if $debug & $debug_flow; &collapse(1); &assertHave(1) || &finish(""); local($arg,$env)=(&f_get1()); &finish_ignore(1); $arg=~s/^\s+//; $arg=~s/\s+$//; return if defined $environment_none{$arg}; if (defined ($env=$environment{$arg})) { local($b,$e)=split(/,/,$env,2); for (split(":",$e)) {&callsub($_);} } else {&puts("\\end{$arg}");} } sub f_newtheorem { warn "Entering f_newtheorem...\n" if $debug & $debug_flow; &trim(2); &collapse(2); &assertHave(2) || &finish("",1); warn "Name `$out[$#out-1]'\nExpansion `$out[$#out]'\n__END__\n" if $debug & $debug_record; local($name, $expand) = ($out[$#out-1], $out[$#out]); $#out -= 2; $#chunks -= 2; return unless $name =~ s/^\d+,\d+.\d+,\d+,//; return unless $expand =~ s/^\d+,\d+.\d+,\d+,//; $environment{$name}="par:unindent:puts;$expand. ,par"; &finish(2,1); } sub f_newtheorem1 { warn "Entering f_newtheorem1...\n" if $debug & $debug_flow; &trim(1); &collapse(1); &assertHave(1) || &finish("",1); warn "Name `$out[$#out]'\n__END__\n" if $debug & $debug_record; local($name) = ($out[$#out]); $#out -= 1; $#chunks -= 1; $par =~ s/^\[[^\]]*\]//; # Optional argument 2 return unless $name =~ s/^\d+,\d+.\d+,\d+,//; $last_newtheorem = $name; &finish(1,1); } sub f_newtheorem2 { warn "Entering f_newtheorem2...\n" if $debug & $debug_flow; &trim(2); &collapse(2); warn "Expansion `$out[$#out]'\n__END__\n" if $debug & $debug_record; local($expand) = ($out[$#out]); $#out -= 2; $#chunks -= 2; $par =~ s/^\[[^\]]*\]//; # Optional argument 4 return unless $expand =~ s/^\d+,\d+.\d+,\d+,//; $environment{$last_newtheorem} = "par:unindent:puts;$expand. ,par"; &finish(2,1); } sub f_literal_no_length { warn "Entering f_literal_no_length...\n" if $debug & $debug_flow; # &trim(1); &collapse(1); &assertHave(1) || &finish("",1); record_forcelength($out[$#out], 0); &finish(1,1); } sub f_discard { warn "Entering f_discard...\n" if $debug & $debug_flow; &finish_ignore($wait[$#level]); } # Takes a number and a record, returns a centered record sub center { local($len,$left)=(shift,0); warn "Entering center, ll=$len, rec=$_[0]\n__ENDREC__\n" if $debug & $debug_flow; #$_[0]; # bug in perl? local($h1,$l1,$b1,$sp1,$str1)=split(/,/,$_[0],5); $h1 || $h1++; if (($left=$len-$l1)<=0) {return $_[0];} local($LHS,$RHS); $LHS = int($left/2); $RHS = $left - $LHS; local($out,$first)=("",1); for (split(/\n/,$str1,$h1)) { if ($first) {$first=0;} else {$out .= "\n";} $out .= " " x $LHS. $_ . " " x $RHS; } return "$h1,$len,$b1,0,$out"; } # Example of radical #<<'EOF'; # +--+ #\|12 #EOF <$l2 ? $l1: $l2)); $len = $minlength if $len < $minlength; local $line = $len <= 1? "-" : ($l . ("-" x ($len - 2)) . $r); if ($flip) { $out[$#out-1]=&vStack(&vStack(¢er($len,$out[$#out]), &string2record($line)), ¢er($len,$out[$#out-1])); } else { $out[$#out-1]=&vStack(&vStack(¢er($len,$out[$#out-1]), &string2record($line)), ¢er($len,$out[$#out])); } $#chunks--; $#out--; warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow; &finish(2,1); } sub f_fraction { arrow_fraction(1,"-","-"); } sub f_right_arrow { arrow_fraction(3,"-",">",1); } sub f_left_arrow { arrow_fraction(3,"<","-",1); } # Takes the last two records, returns a record that contains them and forms # fraction block sub f_overset { warn "Entering f_overset...\n" if $debug & $debug_flow; &trim(2); &collapse(2); &assertHave(2) || &finish("",1); warn "Over `$out[$#out-1]'\nBase `$out[$#out]'\n__END__\n" if $debug & $debug_record; local($l1,$l2)=(&length($out[$#out-1]),&length($out[$#out])); local($len)=(($l1>$l2 ? $l1: $l2)); local($b, $b1)=($out[$#out] =~ /^\d+,\d+,(\d+)/); ($b1)=($out[$#out-1] =~ /^(\d+)/); $b1 ||= 1; # height=0 means 1! $b += $b1; $out[$#out-1]=&vStack(¢er($len,$out[$#out-1]), ¢er($len,$out[$#out])); $#chunks--; $#out--; &setbaseline($out[$#out],$b); warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow; &finish(2,1); } sub f_choose { warn "Entering f_choose...\n" if $debug & $debug_flow; &trim(2); &collapse(2); &assertHave(2) || &finish("",1); warn "Numer `$out[$#out-1]'\nDenom `$out[$#out]'\n__END__\n" if $debug & $debug_record; local($l1,$l2)=(&length($out[$#out-1]),&length($out[$#out])); local($len)=(($l1>$l2 ? $l1: $l2)); $out[$#out]=&vStack(&vStack(¢er($len,$out[$#out-1]), &string2record(" " x $len)), ¢er($len,$out[$#out])); $#chunks++; $#out++; #warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow; $out[$#out - 2] = &string2record("("); $out[$#out] = &string2record(")"); local($h,$b)=($out[$#out-1] =~ /^(\d+),\d+,(\d+)/)[0,1]; &makehigh($out[$#out-2],$h,$b,0,1); &makehigh($out[$#out],$h,$b,1,0); &finish(2,1); } sub f_buildrel { warn "Entering f_buildrel...\n" if $debug & $debug_flow; &trim(3); &collapse(3); &assertHave(3) || &finish("",1); warn "What: $out[$#out-2]\nOver $out[$#out]\n__END__\n" if $debug & $debug_record; local($rec)=($out[$#out-2]); $out[$#out-2]=$out[$#out]; $#chunks-=2; $#out-=2; &f_putover($rec,1); warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow; &finish(3,1); } # Takes two records, returns a record that contains them and forms a # fraction block sub fraction { local($l1,$l2)=(&length($_[0]),&length($_[1])); local($len)=(($l1>$l2 ? $l1: $l2)); return &vStack(&vStack(¢er($len,shift), &string2record("-" x $len)), ¢er($len,shift)); } # Commits a given string sub puts { &commit(&string2record); } # digests an eaten paragraph $ending = 0; sub end_TeX { $par = ''; $ending = 1; } sub paragraph { local($par); return 0 if $ending; $par=<>; return 0 unless defined $par; return 1 unless $par =~ /\S/; # whitespace only print "\n" if $secondtime++ && !$opt_by_par; #$par =~ s/(^|[^\\])%.*\n[ \t]*/\1/g; $par =~ s/((^|[^\\])(\\\\)*)(%.*\n[ \t]*)+/\1/g; $par =~ s/\n\s*\n/\\par /g; $par =~ s/\s+/ /g; $par =~ s/\s+$//; $par =~ s/(\$\$)\s+/\1/g; $par =~ s/\\par\s*$//; local($defcount,$piece,$pure,$type,$sub,@t,$arg)=(0); &commit("1,5,0,0, ") unless $opt_noindent || ($par =~ s/^\s*\\noindent\s*([^a-zA-Z\s]|$)/\1/); while ($tokenByToken[$#level] ? ($par =~ s/^\s*($tokenpattern)//o): ($par =~ s/^($multitokenpattern)//o)) { warn "tokenByToken=$tokenByToken[$#level], eaten=`$1'\n" if $debug & $debug_parsing; if (($piece=$1) =~ /^$usualtokenclass/o) { # plain piece &puts($piece); } else { # macro or delimiter ($pure = $piece); if ($pure =~ /^\\\s+$/) { $pure =~ s/(\\\s)\s+$/$1/; } else { $pure =~ s/\s+$//; } if (defined ($type=$type{$pure})) { if ($type eq "def") { warn "To many def expansions in a paragraph" if $defcount++==$maxdef; last if $defcount>$maxdef; @t=(0); for (1..$args{$pure}) { push(@t,&get_balanced()); } warn "Defined token `$pure' found with $args{$pure} arguments @t[1..$#t]\n" if $debug & $debug_parsing; $sub=$def{$pure}; $sub =~ s/(^|[^\\#])#(\d)/$1 . $t[$2]/ge if $args{$pure}; $par=$sub . $par; } elsif ($type eq "sub") { $sub=$contents{$pure}; index($sub,";")>=0? (($sub,$arg)=split(";",$sub,2), &$sub($pure,$arg)): &$sub($pure); } elsif ($type =~ /^sub(\d+)$/) { local($n) = $1; $sub=$contents{$pure}; if ($sub =~ s/^\[\]//) { if ($par =~ /^\[/) { $par =~ s/^\[([^\]]*)\]/{$1}/; } else { substr($par, 0, 0) = "{}"; } } &start($n,"f_$sub"); $tokenByToken[$#level]=1; } elsif ($type =~ /^get(\d+)$/) { &start($1+1); &puts($piece); $tokenByToken[$#level]=1; } elsif ($type =~ /^discard(\d+)$/) { &start($1,"f_discard"); $tokenByToken[$#level]=1; } elsif ($type eq "record") { &commit($contents{$pure}); } elsif ($type eq "self") { &puts(substr($pure,1) . ($pure =~ /^\\[a-zA-Z]/ ? " ": "")); } elsif ($type eq "par_self") { &finishBuffer; &commit("1,5,0,0, "); &puts($pure . ($pure =~ /^\\[a-zA-Z]/ ? " ": "")); } elsif ($type eq "self_par") { &puts($pure . ($pure =~ /^\\[a-zA-Z]/ ? " ": "")); &finishBuffer; &commit("1,5,0,0, ") unless $par =~ s/^\s*\\noindent(\s+|([^a-zA-Z\s])|$)/\2/; } elsif ($type eq "string") { &puts($contents{$pure},1); } elsif ($type eq "nothing") { } else { warn "Error with type `$type' while interpreting `$pure'"; } } else { &puts($piece); } } } warn "Unrecognized part of input `$par',\n\ttoken-by-token[$#level]=$tokenByToken[$#level]" if $par ne ""; &finishBuffer if $#out>=0; # return 0 if eof(); 1; } sub subscript { &start(1,"f_subscript"); $tokenByToken[$#level]=1; } sub superscript { &start(1,"f_superscript"); $tokenByToken[$#level]=1; } sub f_subscript { $wait[$#level]=2; $action[$#level]="f_subSuper"; if (($par !~ s/^\s*\^//) && ($par !~ s:^\s*\\begin\s*\{Sp\}:\\begin\{matrix\}:)) { &commit(&empty); } } sub f_overline { warn "Entering f_overline...\n" if $debug & $debug_flow; &trim(1); &collapse(1); &assertHave(1) || &finish("",1); warn "Overlining $out[$#out]\n__END__\n" if $debug & $debug_record; local($h,$len,$b)=($out[$#out] =~ /^(\d+),(\d+),(\d+)/); $out[$#out]=&vStack(&string2record("_" x $len), $out[$#out]); $b++; #$out[$#out] =~ s/^(\d+,\d+,)(\d+)/\1$b/; &setbaseline($out[$#out],$b); warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow; &finish(1,1); } sub f_underline { warn "Entering f_underline...\n" if $debug & $debug_flow; &trim(1); &collapse(1); &assertHave(1) || &finish("",1); warn "Underlining $out[$#out]\n__END__\n" if $debug & $debug_record; local($h,$len,$b)=($out[$#out] =~ /^(\d+),(\d+),(\d+)/); $out[$#out]=&vStack($out[$#out],&string2record("_" x $len)); #$out[$#out] =~ s/^(\d+,\d+,)(\d+)/\1$b/; &setbaseline($out[$#out],$b); warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow; &finish(1,1); } sub f_not { warn "Entering f_not...\n" if $debug & $debug_flow; &collapse(1); &assertHave(1) || &finish("",1); warn "Negating $out[$#out]\n__END__\n" if $debug & $debug_record; local($str)=(split(/,/,$out[$#out]))[4]; if ($str eq "=") { $out[$#out]=$contents{"\\neq"}; } elsif ($str =~ /^\s*\|\s*$/) { $out[$#out]=$contents{"\\nmid"}; } elsif ($out[$#out] eq $contents{"\\in"}) { $out[$#out]=$contents{"\\notin"}; } else { $out[$#out]=&join(&string2record("\\not"),$out[$#out]); } warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow; &finish(1,1); } sub f_putunder { warn "Entering f_putunder...\n" if $debug & $debug_flow; &trim(1); &collapse(1); &assertHave(1) || &finish("",1); warn "Putting Under $out[$#out]\n__END__\n" if $debug & $debug_record; local($h,$len,$b)=($out[$#out] =~ /^(\d+),(\d+),(\d+)/); local($l2)=(&length($_[0])); local($len)=(($l1>$l2 ? $l1: $l2)); $out[$#out]=&vStack(¢er($len,$out[$#out]),¢er($len,shift)); #$out[$#out] =~ s/^(\d+,\d+,)(\d+)/\1$b/; &setbaseline($out[$#out],$b); warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow; &finish(1,1); } # if has additional true argument will not finish # Takes record to put over sub f_putover { warn "Entering f_putover...\n" if $debug & $debug_flow; &trim(1); &collapse(1); &assertHave(1) || &finish("",1); warn "Putting Over $out[$#out]\n__END__\n" if $debug & $debug_record; local($h,$l1,$b,$b1)=($out[$#out] =~ /^(\d+),(\d+),(\d+)/); local($l2)=(&length($_[0])); local($len)=(($l1>$l2 ? $l1: $l2)); ($b1)=($_[0] =~ /^(\d+)/); $b1 ||= 1; # height=0 means 1! $b+=$b1; $out[$#out]=&vStack(¢er($len,shift),¢er($len,$out[$#out])); #$out[$#out] =~ s/^(\d+,\d+,)(\d+)/\1$b/; &setbaseline($out[$#out],$b); warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow; &finish(1,1) unless shift; } sub f_putpar { warn "Entering f_putpar...\n" if $debug & $debug_flow; &trim(1); local($l,$r)=split(";",shift); &collapse(1); &assertHave(1) || &finish("",1); warn "Putting Parentheses $out[$#out]\n__END__\n" if $debug & $debug_record; $out[$#out]=&join(&string2record($l), &join($out[$#out],&string2record($r))); &finish(1); } sub f_putover_string { &f_putover(&string2record); } sub f_putunder_string { &f_putunder(&string2record); } sub f_widehat { &trim(1); &collapse(1); local($l)=(&length($out[$#out])); if ($l<=1) {&f_putover(&string2record("^"));} else {&f_putover(&string2record("/" . "~" x ($l-2) . "\\"));} } sub f_widetilde { &trim(1); &collapse(1); local($l,$l1)=(&length($out[$#out])); if ($l<=1) {&f_putover(&string2record("~"));} elsif ($l<=3) {&f_putover(&string2record("/\\/"));} else {&f_putover(&string2record("/" . "~" x ($l1=int($l/2-1)) . "\\" . "_" x ($l-3-$l1) . "/"));} } sub f_underbrace { &trim(1); &collapse(1); local($l,$l1)=(&length($out[$#out])); if ($l < 5) { $l = 5 } &f_putunder(vStack(&string2record("\\" . "_" x ($l1=int($l/2-1)) . " " . "_" x ($l-3-$l1) . "/"), &string2record(" " x ($l1=int($l/2)) . "v" . " " x ($l-2-$l1)))); } sub f_underbrace2 { &trim(2); &collapse(2); local($l,$l1)=(&length($out[$#out - 1])); if ($l < 5) { $l = 5 } local($b)=($out[$#out - 1] =~ /^\d+,\d+,(\d+)/); $out[$#out-1] = &vStack(¢er($l,$out[$#out-1]), vStack(vStack(&string2record("\\" . "_" x ($l1=int($l/2-1)) . " " . "_" x ($l-3-$l1) . "/"), &string2record(" " x ($l1=int($l/2)) . "v" . " " x ($l-2-$l1))), ¢er($l,$out[$#out]))); $#chunks--; $#out--; &setbaseline($out[$#out],$b); warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow; &finish(2,1); } sub f_overbrace { &trim(1); &collapse(1); local($l)=(&length($out[$#out])); if ($l < 6) { $l = 6 } local($l1) = int($l/2); &f_putover(vStack(&string2record(" " . "_" x ($l1 - 2) . "/\\" . "_" x ($l-2-$l1) . " "), &string2record("/" . " " x ($l1 - 2) . " " . " " x ($l-2-$l1) . "\\"), )); } sub f_overbrace2 { &trim(2); &collapse(2); local($l)=(&length($out[$#out - 1])); if ($l < 5) { $l = 5 } local($h,$b)=($out[$#out - 1] =~ /^(\d+),\d+,(\d+)/); $h ||= 1; local($l1) = int($l/2); $out[$#out-1] = &vStack(vStack(¢er($l,$out[$#out]), vStack(&string2record(" " . "_" x ($l1 - 2) . "/\\" . "_" x ($l-2-$l1) . " "), &string2record("/" . " " x ($l1 - 2) . " " . " " x ($l-2-$l1) . "\\"))), ¢er($l,$out[$#out-1])); $#chunks--; $#out--; local($h1) = ($out[$#out] =~ /^(\d+),/); &setbaseline($out[$#out], $h1 - ($h - $b)); warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow; &finish(2,1); } sub f_superscript { $wait[$#level]=2; $action[$#level]="f_superSub"; if (($par !~ s/^\s*\_//) && ($par !~ s:^\s*\\begin\s*\{Sb\}:\\begin\{matrix\}:)) { &commit(&empty); } } sub let { $par =~ s/^($tokenpattern)(= ?)?($tokenpattern)//o; } sub let_exp { $par =~ s/^($tokenpattern)(= ?)?($tokenpattern)//o; return if index($&,'@')>=0; local($what)=$1; $type{$what}='def'; $& =~ /($tokenpattern)$/; $def{$what}=$1; $args{$what}=0; warn "Definition of `$what' with $args{$what} args is `$def{$what}'\n" if $debug & $debug_parsing; } sub def { $par =~ s/^[^{]*//; &start(1,"f_discard"); $tokenByToken[$#level]=1; } sub def_exp { return unless $par =~ s:^(([^\\{]|\\.)*)\{:\{:; local($arg)=($1); local($def,$act)=(&get_balanced()); return unless defined $def; return if index("$arg$def",'@')>=0; return if $def =~ /\\([egx]?def|fi)([^a-zA-Z]|$)/; $def .= " " if $def =~ /($macro)$/o; &define($arg,$def); } sub def_exp_block { return unless $par =~ s:\{(\\([a-zA-Z]+|.))\}\{:\{:; local($arg)=($1); local($def,$act)=(&get_balanced()); return unless defined $def; return if index("$arg$def",'@')>=0; return if $def =~ /\\([egx]?def|fi)([^a-zA-Z]|$)/; $def .= " " if $def =~ /($macro)$/o; &define($arg,$def); } # Arguments: Token . Parameters, Expansion sub define { local($arg,$def,$act)=(shift,shift); return unless $arg =~ /^($active)/o; $act=$1; $args{$act}=$'; return unless $args{$act} =~ /^(#\d)*$/; $args{$act}=length($args{$act})/2; $def{$act}=$def; $type{$act}='def'; warn "Definition of `$act' with $args{$act} args is `$def'\n" if $debug & $debug_parsing; } sub defb { for (@_) { &define("\\$_","\\begin{$_}");&define("\\end$_","\\endTeXtoMail{$_}"); } } # Discards surrounding {} sub get_balanced { return undef unless $par =~ s/^($tokenpattern)//; return $1 unless $1 eq '{'; local($def,$lev)=('',1); while ($lev) { last unless $par =~ s/^[^\\{}]|\\.|[{}]//; $lev++ if $& eq '{'; $lev-- if $& eq '}'; $def .= $& if $lev; } (warn "Balanced text not finished!",return undef) if $lev; return $def; } sub open_curly { #&puts("{") unless $tokenByToken[$#level]; &start("}"); } # Deletes extra spaces at the end of a record sub trim_end { local($h,$str)=(split(/,/,$_[0],5))[0,4]; if (!$h) { $str =~ s/\s+$//; $_[0]=&string2record($str); warn "Trimmed End `$_[0]'\n__END__\n" if $debug & $debug_record; } } # Deletes extra spaces at the beginning of a record sub trim_beg { local($h,$str)=(split(/,/,$_[0],5))[0,4]; if (!$h) { $str =~ s/^\s+//; $_[0]=&string2record($str); warn "Trimmed Beg `$_[0]'\n__END__\n" if $debug & $debug_record; } } # Deletes extra spaces at the ends of a chunk with given number sub trim_one { &trim_beg($out[$chunks[$_[0]]]); &trim_end($_[0]==$#chunks? $out[$#out]: $out[$chunks[$_[0]+1]-1]); } # Deletes extra spaces at the ends of a given number of chunks sub trim { for ($#chunks-$_[0]+1..$#chunks) {&trim_one($_);} } sub dollar { if ($wait[$#level] eq '$') { # '; &trim_end($out[$#out]); &finish('$'); } else { &start('$'); $par =~ s/^\s+//; } } sub ddollar { if ($wait[$#level] eq '$$') { &trim_end($out[$#out]); &finish('$$'); return unless $#out>=0; $#chunks=0; $chunks[0]=0; &trim(1); &collapse(1); &printrecord(¢er($linelength,$out[0])); @level=(0); @chunks=(0); @tokenByToken=(0); @out=(); $curlength=0; # Maybe after \begin{align} } else { &finishBuffer; &start('$$'); } $par =~ s/^\s+//; } sub item { &finishBuffer; # To make unexpandable: &commit("1,11,0,0, (\@) "); } sub bbackslash { if ($wait[$#level] eq '$$') { &ddollar(); &ddollar(); } elsif ($wait[$#level] eq 'endCell') { return if $par =~ /^\s*\\end/; # Ignore the last one &finish('endCell', 1); &trim(1); &collapse(1); &finish('endRow', 1); &start('endRow'); &start('endCell'); } else { #&puts(" \\\\ "); ∥ } } sub ampersand { if ($wait[$#level] eq 'endCell') { &finish('endCell',1); &trim(1); &collapse(1); &start('endCell'); } } sub matrix { &start('endMatrix'); &start('endRow'); &start('endCell'); } sub endmatrix { &finish('endCell',1); &trim(1); &collapse(1); &finish('endRow',1); # Now chunks correspond to rows of the matrix, records inside chunks to # Cells &halign(split(";",shift)); &finish('endMatrix',1); } sub endmatrixArg { my $aspec = pop(@argStack); # Replace *{20}{c} by "c" x 20; same for omited {}. $aspec =~ s/\*(?:\{(\d+)\}|([^{]))(?:\{(.*?)\}|([^{]))/ (defined($1) ? $1 : $2) x (defined($3) ? $3 : $4) /eg; &endmatrix(join(";",($_[0],split("", $aspec)))); } # Takes a matrix in the following form: chunks on the last level # are row of the matrix, records inside chunks are cells. # Puts the resulting matrix in the first record on the given level # and truncates the rest # I'm trying to add parameters: # length to insert between columns # Array of centering options one for a column (last one repeated if needed) # Currently supported: c for center, r for right, l for left sub halign { local($explength)=(shift); local(@c)=@_; local($last,$le,$b,$h); local(@w)=(); #warn "levels @level, chunks @chunks, records @out\n"; # Find metrics of cells for $r (0..$#chunks-$level[$#level]) { $last= ($r==$#chunks-$level[$#level]) ? $#out: $chunks[$r+1+$level[$#level]]-1; warn "Row $r: last column " . ($last-$chunks[$r+$level[$#level]]) ."\n" if $debug & $debug_matrix; for $c (0..$last-$chunks[$r+$level[$#level]]) { ($h,$le,$b)= ($out[$chunks[$r+$level[$#level]]+$c] =~ /(\d+),(\d+),(\d+)/); # Format is Height:Length:Baseline $w[$c]=$le unless $w[$c]>$le; } } # expand the height and depth for $c (0..$#w-1) {$w[$c]+=$explength;} # Extend the @c array by the last element or "c" if it is empty @c=("c") x @w unless @c; @c=(@c,($c[$#c]) x (@w-@c)); # Now expand the cells warn "Widths of columns @w\n" if $debug & $debug_matrix; for $r (0..$#chunks-$level[$#level]) { $last= ($r==$#chunks-$level[$#level]) ? $#out: $chunks[$r+1+$level[$#level]]-1; warn "Row $r: last column " . ($last-$chunks[$r+$level[$#level]]) ."\n" if $debug & $debug_matrix; for $c (0..$last-$chunks[$r+$level[$#level]]) { if ($c[$c] eq "c") { warn "Centering row $r col $c to width $w[$c]\n" if $debug & $debug_matrix; $out[$chunks[$r+$level[$#level]]+$c]= ¢er($w[$c],$out[$chunks[$r+$level[$#level]]+$c]); } elsif ($c[$c] eq "l") { warn "Expanding row $r col $c to width $w[$c]\n" if $debug & $debug_matrix; $out[$chunks[$r+$level[$#level]]+$c]= &join($out[$chunks[$r+$level[$#level]]+$c], &string2record(" " x ($w[$c] - &length($out[$chunks[$r+$level[$#level]]+$c])))); } elsif ($c[$c] eq "r") { warn "Expanding row $r col $c to width $w[$c] on the left\n" if $debug & $debug_matrix; $out[$chunks[$r+$level[$#level]]+$c]= &join(&string2record(" " x ($w[$c]-$explength- &length($out[$chunks[$r+$level[$#level]]+$c]))), $out[$chunks[$r+$level[$#level]]+$c]); $out[$chunks[$r+$level[$#level]]+$c]= &join($out[$chunks[$r+$level[$#level]]+$c], &string2record(" " x $explength)); } else {warn "Unknown centering option `$c[$c]' for halign";} } } # Now we creat rows &collapseAll; # And stack them vertically for ($chunks[$level[$#level]]+1..$#out) { $out[$chunks[$level[$#level]]]=&vStack($out[$chunks[$level[$#level]]], $out[$_]); } &setbaseline($out[$chunks[$level[$#level]]], int((&height($out[$chunks[$level[$#level]]])-1)/2)); $#chunks=$level[$#level]; $#out=$chunks[$level[$#level]]; } sub close_curly { &finish("}"); #&puts("}") unless $tokenByToken[$#level]; # well, this can change under our foot... } sub at { local($c,$first,$second,$t,$m)=($par =~ /^(.)/); if ($c eq '@') {&puts('@');$par =~ s/^.//;} elsif (index("<>AV",$c)>=0) { $m="&" if ($wait[$#level] eq 'endCell'); $m="&&" if $m eq "&" && index("AV",$c)>=0; &ersand if $m eq "&"; $par =~ s/^.//; $first=$second=""; while (($t=&get_balanced()) ne $c && defined $t) { $first .= $t; } while (($t=&get_balanced()) ne $c && defined $t) { $second .= $t; } $par="{$first}{$second}$m" . $par; local($l,$r); ($l=$c) =~ tr/A>V/^/d; ($r=$c) =~ tr/",$c)>=0 ? &start(2,"f_arrow;$l;$r"): &start(2,"f_arrow_v;$l;$r"); } elsif ($c eq "." && $wait[$#level] eq 'endCell') { &ersand; &ersand; $par =~ s/^.//; } else {&puts('@');} } # takes two tips of arrow as argument separated by ";", # we assume that total length is 1 sub f_arrow { warn "Entering f_arrow...\n" if $debug & $debug_flow; local($l,$r)=split(";",shift); &trim(2); &collapse(2); &assertHave(2) || &finish("",1); warn "Over: $out[$#out-1]\nUnder: $out[$#out]\n__END__\n" if $debug & $debug_record; local($l1,$l2)=(&length($out[$#out-1]),&length($out[$#out])); local($len)=(($l1>$l2 ? $l1: $l2)); $out[$#out-1]=&vStack(&vStack(¢er($len+4,$out[$#out-1]), &string2record(" $l" ."-" x ($len+1) . "$r ")), ¢er($len+4,$out[$#out])); $#chunks--; $#out--; warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow; &finish(2,1); } # takes two tips of arrow as argument separated by ";", # we assume that total length is 1 sub f_arrow_v { warn "Entering f_arrow_v...\n" if $debug & $debug_flow; local($l,$r)=split(";",shift); &trim(2); &collapse(2); &assertHave(2) || &finish("",1); warn "Over: $out[$#out-1]\nUnder: $out[$#out]\n__END__\n" if $debug & $debug_record; local($h1,$b1)=($out[$#out-1] =~ /^(\d+),\d+,(\d+)/); local($h2,$b2)=($out[$#out] =~ /^(\d+),\d+,(\d+)/); local($b)=(($b1>$b2 ? $b1: $b2)); local($res)=(&join($out[$#out-1],$out[$#out])); local($h,$bb)=($res =~ /^(\d+),\d+,(\d+)/); $bb=$b+1; $out[$#out-1]=&vStack(&vputs(" " x ($b-$b1+1)), $out[$#out-1]); #$out[$#out-1] =~ s/^(\d+,\d+,)(\d+)/\1$bb/; &setbaseline($out[$#out-1],$bb); $out[$#out]=&vStack(&vputs(" " x ($b-$b2+1)), $out[$#out]); #$out[$#out] =~ s/^(\d+,\d+,)(\d+)/\1$bb/; &setbaseline($out[$#out],$bb); $out[$#out-1]=&join(&join($out[$#out-1], &vputs($l ."|" x ($h+1) . $r,$b+1)), $out[$#out]); $#chunks--; $#out--; warn "a:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow; &finish(2,1); } sub noindent { if ($#out == 0 && $#chunks == 0 && $out[$#out] eq '1,5,0,0, ') { $#out--; $#chunks--; } else { &puts('\\noindent'); } } # put strings vertically, returns a record with the second argument as baseline sub vputs { local($b)=($_[1]); $b=0 unless defined $b; return length($_[0]) . ",1,$b,0," . join("\n",split('',$_[0])); } sub choose { if ($wait[$#level] eq '}') { local($prevw)=($wait[$#level-1]); $wait[$#level-1]="junk"; &finish("}",1); &collapse(1); &assertHave(1) || &finish("",1); local($rec)=$out[$#out]; $#out--; $#chunks--; &start(2,"f_choose"); $wait[$#level-1]=$prevw; &start("}"); &commit($rec); &finish("}",1); &start("}"); } else {&puts("\\choose");} } sub over { if ($wait[$#level] eq '}') { local($prevw)=($wait[$#level-1]); $wait[$#level-1]="junk"; &finish("}", 1); &collapse(1); warn "X:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow; &assertHave(1) || &finish("",1); warn "Y:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow; local($rec)=$out[$#out]; $#out--; $#chunks--; warn "Z:Last $#chunks, the first on the last level=$#level is $level[$#level]" if $debug & $debug_flow; &start(2,"f_fraction"); $wait[$#level-1]=$prevw; &start("}"); &commit($rec); &finish("}",1); &start("}"); } else {&puts("\\over");} } # Takes a record, height, baseline, spaces_toleft and _toright # and makes this record this high sub makehigh { local($str)=(split(",",$_[0],5))[4]; local($h,$b,$d)=($_[1],$_[2]+1); warn "Entering makehigh(@_)\n" if $debug & $debug_flow; if ($str eq ".") {$_[0] =~ s/\.$/ /;return;} #$str="<" if $str eq "\\langle"; #$str=">" if $str eq "\\rangle"; $h=1 unless $h; $d=$h-$b; return if $h<2 || $h==2 && index("()<>",$str)>=0; local(@c); if ($str eq "(") {@c=split(":",'(: :|:/:\:|');} elsif ($str eq ")") {@c=split(":",'): :|:\:/:|');} elsif ($str eq "{") {@c=split(":",'{: :|:/:\:<');} elsif ($str eq "}") {@c=split(":",'}: :|:\:/:>');} elsif ($str eq "|" && $str eq "||") {@c=split(":",'|:|:|:|:|:|');} elsif ($str eq "[") {@c=split(":",'[:[:|:[:[:|');} elsif ($str eq "]") {@c=split(":",']:]:|:]:]:|');} elsif ($str eq "<" || $str eq ">") { return if $h==2; local($l)=($b); $l=$d+1 if $b<$d+1; for (2..$l) { $_[0]=&join($_[0], &vputs("/" . " " x (2*$_-3) . "\\",$_-1)) if $str eq "<"; $_[0]=&join(&vputs("\\" . " " x (2*$_-3) . "/",$_-1), $_[0]) if $str eq ">"; } $_[0]=&join($_[0],&string2record(" ")) if $str eq "<"; $_[0]=&join(&string2record(" "),$_[0]) if $str eq ">"; return; } else {return;} $_[0]=&vputs(&makecompound($b,$d,@c),$b-1); $_[0]=&join($_[0],$_[0]) if length($str)==2; $_[0]=&join(&string2record(" " x $_[3]),$_[0]) if $_[3]; $_[0]=&join($_[0],&string2record(" " x $_[4])) if $_[4]; } sub f_FOOTNOTE { &finish(1); puts(">>> "); } sub footnote { puts("<<1 && $_[1]>0 && $_[4] eq $_[7]) { return $_[5] . $_[4] x ($_[0]+$_[1]-2) . $_[6]; } # No descent: if ($_[1] <= 0) {return $_[3] x ($_[0]-1) . $_[2];} # No ascent: if ($_[0] <= 1) {return $_[2] . $_[3] x $_[1];} local($mid,$asc,$des)=($_[2]); # descent == 1 $des = ($_[1]==1) ? $_[2]: $_[4] x ($_[1]-1) . $_[6]; $asc = ($_[0]==2) ? $_[2]: $_[5] . $_[4] x ($_[0]-2); $mid = $_[7] unless $_[0]==2 || $_[1]==1; return "$asc$mid$des"; } sub arg2stack {push(@argStack,&get_balanced());} sub par {&finishBuffer;&commit("1,5,0,0, ") unless $par =~ s/^\s*\\noindent\s*(\s+|([^a-zA-Z\s])|$)/\2/;} $type{"\\sum"}="record"; $contents{"\\sum"}="3,4,1,0," . <<'EOF'; \~~ > /__ EOF $type{"\\int"}="record"; $contents{"\\int"}="3,3,1,0," . <<'EOF'; ,- | -' EOF $type{"\\prod"}="record"; $contents{"\\prod"}="3,3,1,0," . <<'EOF'; ___ | | | | EOF $type{"\\Pi"}="record"; $contents{"\\Pi"}="2,3,1,0," . <<'EOF'; _ | | EOF $type{"\\Sigma"}="record"; $contents{"\\Sigma"}="3,2,1,0," . <<'EOF'; __ > ~~ EOF $type{"\\Delta"}="record"; $contents{"\\Delta"}="2,2,0,0," . <<'EOF'; /\ ~~ EOF $type{"\\nabla"}="record"; $contents{"\\nable"}="2,2,1,0," . <<'EOF'; __ \/ EOF $type{"\\oplus"}="record"; $contents{"\\oplus"}="3,5,1,0," . <<'EOF'; _ (+) ~ EOF $type{"\\otimes"}="record"; $contents{"\\otimes"}="3,5,1,0," . <<'EOF'; _ (x) ~ EOF $type{"\\ominus"}="record"; $contents{"\\ominus"}="3,5,1,0," . <<'EOF'; _ (-) ~ EOF $type{"\\odot"}="record"; $contents{"\\odot"}="3,5,1,0," . <<'EOF'; _ (.) ~ EOF $type{"\\leq"}="record"; $contents{"\\leq"}="2,3,1,0," . <<'EOF'; _ < EOF $type{"\\equiv"}="record"; $contents{"\\equiv"}="2,3,1,0," . <<'EOF'; _ = EOF $type{"\\not"}="record"; $contents{"\\not"}="2,4,1,0," . <<'EOF'; _ | EOF $type{"\\geq"}="record"; $contents{"\\geq"}="2,3,1,0," . <<'EOF'; _ > EOF $type{"\\partial"}="record"; $contents{"\\partial"}="2,1,1,0," . <<'EOF'; \ d EOF $type{"\\forall"}="record"; $contents{"\\forall"}="3,4,1,0," . <<'EOF'; \__/ \/ EOF $type{"\\exists"}="record"; $contents{"\\exists"}="3,2,1,0," . <<'EOF'; _. -| ~' EOF $type{"\\owns"}="record"; $contents{"\\owns"}="3,4,1,0," . <<'EOF'; _ -) ~ EOF $type{"\\ni"}="record"; $contents{"\\ni"}="3,4,1,0," . <<'EOF'; _ -) ~ EOF $type{"\\in"}="record"; $contents{"\\in"}="3,4,1,0," . <<'EOF'; _ (- ~ EOF $type{"\\notin"}="record"; $contents{"\\notin"}="3,5,1,0," . <<'EOF'; |_ (|- |~ EOF $type{"\\qed"}="record"; $contents{"\\qed"}="2,6,1,0," . <<'EOF'; _ |_| EOF $type{"\\Box"}="record"; $contents{"\\Box"}="2,5,1,0," . <<'EOF'; _ |_| EOF $type{"\\boxtimes"}="record"; $contents{"\\boxtimes"}="3,5,1,0," . <<'EOF'; _ |X| ~ EOF $type{"\\pm"}="record"; $contents{"\\pm"}="2,1,0,0," . <<'EOF'; + - EOF $type{"\\mp"}="record"; $contents{"\\mp"}="2,1,1,0," . <<'EOF'; _ + EOF $type{"\\cong"}="record"; $contents{"\\cong"}="2,1,0,0," . <<'EOF'; = ~ EOF $type{"\\neq"}="record"; $contents{"\\neq"}="1,5,0,0," . <<'EOF'; =/= EOF $type{"\\nmid"}="record"; $contents{"\\nmid"}="3,3,1,0," . <<'EOF'; |/ | /| EOF $type{"\\subset"}="record"; $contents{"\\subset"}="2,4,1,0," . <<'EOF'; _ (_ EOF $type{"\\subseteq"}="record"; $contents{"\\subseteq"}="3,4,1,0," . <<'EOF'; _ (_ ~ EOF $type{"\\supseteq"}="record"; $contents{"\\subseteq"}="3,4,1,0," . <<'EOF'; _ _) ~ EOF $type{"\\supset"}="record"; $contents{"\\supset"}="2,4,1,0," . <<'EOF'; _ _) EOF $type{"\\sqrt"}="sub1"; $contents{"\\sqrt"}="radical"; $type{"\\buildrel"}="sub3"; $contents{"\\buildrel"}="buildrel"; $type{"\\frac"}="sub2"; $contents{"\\frac"}="fraction"; $type{"\\xrightarrow"}="sub2"; $contents{"\\xrightarrow"}="[]right_arrow"; $type{"\\xleftarrow"}="sub2"; $contents{"\\xleftarrow"}="[]left_arrow"; $type{"\\overset"}="sub2"; $contents{"\\overset"}="overset"; $type{"\\LITERALnoLENGTH"}="sub1"; $contents{"\\LITERALnoLENGTH"}="literal_no_length"; for ("text","operatorname","operatornamewithlimits","relax","-", "notag","!","/","protect","mathcal","Bbb","bf","it","em","boldsymbol", "cal","Cal","goth","ref","maketitle","expandafter","csname","endcsname", "makeatletter","makeatother","topmatter","endtopmatter","rm", "tt", "NoBlackBoxes","document","TagsOnRight","bold","dsize","roster", "endroster","endkey","endRefs","enddocument","displaystyle", "twelverm","tenrm","twelvefm","tenfm","hbox","mbox", "url", "tableofcontents", "bigl", "bigr", "biggl", "biggr", "footnotesize", "nonumber", "tiny", "sc", "huge", "limits", ) { $type{"\\$_"}="nothing"; } if ($opt_ignorefonts) { for ("mathbb", "mathit", "mathbit", "mathfrak", "frak", "mathbf", ) { $type{"\\$_"}="nothing"; } } for ("par","endtitle","endauthor","endaffil","endaddress","endemail","enddate", "endhead","key","medskip","smallskip","bigskip","newpage", "vfill","eject") { $type{"\\$_"}="sub"; $contents{"\\$_"}="par"; } for ("proclaim","demo",) { $type{"\\$_"}="par_self"; } for ("endproclaim","enddemo",) { $type{"\\$_"}="self_par"; } $type{"\\today"}="sub"; $contents{"\\today"}="today"; #$type{"&"}="nothing"; $type{"\\let"}="sub"; $contents{"\\let"}="let_exp"; $type{"\\def"}="sub"; $contents{"\\def"}="def_exp"; $type{"\\newcommand"}="sub"; $contents{"\\newcommand"}="def_exp_block"; $type{"\\item"}="sub"; $contents{"\\item"}="item"; $type{"{"}="sub"; $contents{"{"}="open_curly"; $type{"}"}="sub"; $contents{"}"}="close_curly"; $type{"&"}="sub"; $contents{"&"}="ampersand"; $type{'$'}="sub"; $contents{'$'}="dollar"; $type{'$$'}="sub"; $contents{'$$'}="ddollar"; $type{'\\\\'}="sub"; $contents{'\\\\'}="bbackslash"; $type{"^"}="sub1"; $contents{"^"}="superscript"; $type{"_"}="sub1"; $contents{"_"}="subscript"; $type{"@"}="sub"; $contents{"@"}="at"; $type{"\\over"}="sub"; $contents{"\\over"}="over"; $type{"\\choose"}="sub"; $contents{"\\choose"}="choose"; $type{"\\noindent"}="sub"; $contents{"\\noindent"}="noindent"; $type{"\\left"}="sub"; $contents{"\\left"}="left"; $type{"\\right"}="sub"; $contents{"\\right"}="right"; $type{'\footnote'}="sub"; $contents{'\footnote'}="footnote"; $type{"\\underline"}="sub1"; $contents{"\\underline"}="underline"; $type{"\\overline"}="sub1"; $contents{"\\overline"}="overline"; $type{"\\bar"}="sub1"; $contents{"\\bar"}="overline"; $type{"\\v"}="sub1"; $contents{"\\v"}="putover_string;v"; $type{"\\widetilde"}="sub1"; $contents{"\\widetilde"}="widetilde"; $type{"\\underbrace"}="sub2"; $contents{"\\underbrace"}="underbrace2"; $type{"\\overbrace"}="sub2"; $contents{"\\overbrace"}="overbrace2"; $type{"\\~"}="sub1"; $contents{"\\~"}="putover_string;~"; $type{"\\tilde"}="sub1"; $contents{"\\tilde"}="putover_string;~"; $type{"\\widehat"}="sub1"; $contents{"\\widehat"}="widehat"; $type{"\\hat"}="sub1"; $contents{"\\hat"}="putover_string;^"; $type{"\\^"}="sub1"; $contents{"\\^"}="putover_string;^"; $type{'\\"'}="sub1"; $contents{'\\"'}='putover_string;"'; $type{'\\dot'}="sub1"; $contents{'\\dot'}='putover_string;.'; $type{"\\not"}="sub1"; $contents{"\\not"}="not"; $type{"\\label"}="sub1"; $contents{"\\label"}="putpar;(;)"; $type{"\\eqref"}="sub1"; $contents{"\\eqref"}="putpar;(;)"; $type{"\\cite"}="sub1"; $contents{"\\cite"}="putpar;[;]"; $type{"\\begin"}="sub1"; $contents{"\\begin"}="begin"; for ('@',"_","\$","{","}","#","&","arccos","arcsin","arctan","arg","cos", "cosh","cot","coth","csc","deg","det","dim","exp","gcd","hom", "inf","ker","lg","lim","liminf","limsup","ln","log","max","min", "mod","Pr","sec","sin","sinh","sup","tan","tanh", "%") { $type{"\\$_"}="self"; } for ("bibliography","myLabel","theoremstyle","theorembodyfont", "usepackage", "bibliographystyle","hphantom","vphantom","phantom","hspace") { $type{"\\$_"}="discard1"; } for ("numberwithin","renewcommand","setcounter" ) { $type{"\\$_"}="discard2"; } $type{"\\newenvironment"}="discard3"; $type{"\\DeclareMathAccent"}="discard4"; $type{"\\DeclareMathAlphabet"}="discard5"; #$type{"\\newtheorem"}="sub2"; #$contents{"\\newtheorem"}="newtheorem"; $type{"\\NEWTHEOREMone"}="sub1"; $contents{"\\NEWTHEOREMone"}="newtheorem1"; $type{"\\NEWTHEOREMtwo"}="sub2"; $contents{"\\NEWTHEOREMtwo"}="[]newtheorem2"; for ("equation","gather","align" ) {$environment{"$_"}="ddollar,ddollar";} for ("matrix","CD","smallmatrix" ) {$environment{"$_"}="matrix,endmatrix;1;c";} for ("remark", "example", "theorem", "definition", "proof", "abstract", "proposition", "amplification", "lemma", "corollary", ) {$environment{"$_"}="par:unindent:puts;\U$_\E. ,par";} # \thanks inside \author confuse things a lot for ("title", "author", "affil", "address", "email", "date", # "thanks", "section", "subsection", "subsubsection") { $type{"\\$_"}="sub"; $contents{"\\$_"}="par_puts_unindent;\U$_: "; } for ("document","split","enumerate" ) {$environment_none{"$_"}++;} $environment{"Sb"}="subscript:matrix,endmatrix;1;l"; $environment{"Sp"}="superscript:matrix,endmatrix;1;l"; $environment{"eqnarray"}="ddollar:matrix,endmatrix;0;r;c;l:ddollar"; $environment{"eqnarray*"}="ddollar:matrix,endmatrix;0;r;c;l:ddollar"; $environment{"split"}="ddollar:matrix,endmatrix;0;r;l:ddollar"; $environment{"multiline"}="ddollar:matrix,endmatrix;0;r;l:ddollar"; $environment{"align"}="ddollar:matrix,endmatrix;0;r;l:ddollar"; $environment{"aligned"}="matrix,endmatrix;0;r;l"; $environment{"gather"}="ddollar:matrix,endmatrix;0;c:ddollar"; $environment{"gathered"}="matrix,endmatrix;0;c"; $environment{"array"}="arg2stack:matrix,endmatrixArg;1"; # $environment{"pmatrix"}="beg_lr;(;):matrix,endmatrix;1;c"; $environment{"bmatrix"}="beg_lr;[;]:matrix,endmatrix;1;c"; $environment{"vmatrix"}="beg_lr;|;|:matrix,endmatrix;1;c"; $type{"~"}="string"; $contents{"~"}=" "; $type{"\\*"}="string"; $contents{"\\*"}=""; $type{"\\,"}="string"; $contents{"\\,"}=" "; $type{"\\dots"}="string"; $contents{"\\dots"}="..."; $type{"\\and"}="string"; $contents{"\\and"}=" & "; $type{"\\ldots"}="string"; $contents{"\\ldots"}="..."; $type{"\\cdots"}="string"; $contents{"\\cdots"}="..."; $type{"\\colon"}="string"; $contents{"\\colon"}=": "; $type{"\\mid"}="string"; $contents{"\\mid"}=" | "; $type{"\\smallsetminus"}="string"; $contents{"\\smallsetminus"}=" \\ "; $type{"\\setminus"}="string"; $contents{"\\setminus"}=" \\ "; $type{"\\backslash"}="string"; $contents{"\\backslash"}="\\"; $type{"\\iff"}="string"; $contents{"\\iff"}=" <==> "; $type{"\\approx"}="string"; $contents{"\\approx"}=" ~ "; $type{"\\simeq"}="string"; $contents{"\\simeq"}=" ~ "; $type{"\\quad"}="string"; $contents{"\\quad"}=" "; $type{"\\qquad"}="string"; $contents{"\\qquad"}=" "; $type{"\\to"}="string"; $contents{"\\to"}=" --> "; $type{"\\from"}="string"; $contents{"\\from"}=" <-- "; $type{"\\wedge"}="string"; $contents{"\\wedge"}="/\\"; $type{"\\vee"}="string"; $contents{"\\vee"}="\\/"; $type{"\\Lambda"}="string"; $contents{"\\Lambda"}="/\\"; $type{"\\ltimes"}="string"; $contents{"\\ltimes"}=" |>< "; $type{"\\lhd"}="string"; $contents{"\\lhd"}=" <| "; $type{"\\rhd"}="string"; $contents{"\\rhd"}=" |> "; $type{"\\cdot"}="string"; $contents{"\\cdot"}=" . "; # $type{"\dot"}="string"; # $contents{"\\dot"}=" . "; $type{"\\circ"}="string"; $contents{"\\circ"}=" o "; $type{"\\bullet"}="string"; $contents{"\\bullet"}="\@"; $type{"\\infty"}="string"; $contents{"\\infty"}="oo"; $type{"\\rtimes"}="string"; $contents{"\\rtimes"}=" ><| "; $type{"\\times"}="string"; $contents{"\\times"}=" >< "; $type{"\\gg"}="string"; $contents{"\\gg"}=" >> "; $type{"\\ll"}="string"; $contents{"\\ll"}=" << "; $type{"\\hookrightarrow"}="string"; $contents{"\\hookrightarrow"}=" c--> "; $type{"\\hookleftarrow"}="string"; $contents{"\\hookleftarrow"}=" <--j "; $type{"\\longleftarrow"}="string"; $contents{"\\longleftarrow"}=" <----- "; $type{"\\longleftrightarrow"}="string"; $contents{"\\longleftrightarrow"}=" <----> "; $type{"\\longrightarrow"}="string"; $contents{"\\longrightarrow"}=" -----> "; $type{"\\rightarrow"}="string"; $contents{"\\rightarrow"}=" ---> "; $type{"\\leftarrow"}="string"; $contents{"\\leftarrow"}=" <--- "; $type{"\\mapsto"}="string"; $contents{"\\mapsto"}=" :--> "; $type{"\\longmapsto"}="string"; $contents{"\\longmapsto"}=" :----> "; $type{"\\cap"}="string"; $contents{"\\cap"}=" /~\\ "; $type{"\\cup"}="string"; $contents{"\\cup"}=" \\_/ "; $type{"\|"}="string"; $contents{"\|"}="||"; $type{'\;'}="string"; $contents{'\;'}=" "; $type{'\ '}="string"; $contents{'\ '}=" "; $type{'\noindent'}="string"; $contents{'\noindent'}=""; $type{'\enspace'}="string"; $contents{'\enspace'}=" "; $type{"\\thanks"}="string"; $contents{"\\thanks"}=" THANKS: "; $type{"\\vert"}="string"; $contents{"\\vert"}=" | "; $type{"\\Vert"}="string"; $contents{"\\Vert"}=" || "; $type{"\\ast"}="string"; $contents{"\\ast"}=" * "; $type{"\\prime"}="string"; $contents{"\\prime"}="'"; $type{"\\endgraph"}="string"; $contents{"\\endgraph"}=" \\NEWPAR "; &define('\\define','\\def'); &define('\\ge','\\geq '); &define('\\le','\\leq '); &define('\\ne','\\neq '); &define('\\langle','<'); &define('\\rangle','>'); &define('\\subheading','\\par\\underline '); &define('\\(','$'); &define('\\)','$'); &define('\\[','$$'); &define('\\]','$$'); &define('\\centerline#1','$$#1$$'); &define('\\eqalign#1','\\aligned #1 \\endaligned '); &define('\\eqalignno#1','\\aligned #1 \\endaligned '); &define('\\cr','\\\\'); &define('\\sb','_'); &define('\\sp','^'); &define('\\iint','\int\int '); &define('\\iiint','\int\int\int '); &define('\\proclaim','\\noindent '); &define('\\mathring','\\overset{\circ}'); &define('\\binom#1#2','{#1\choose{}#2}'); &define('\\bibitem#1','[#1]'); &define('\\newline','\par '); &define('\\newtheorem#1','\\NEWTHEOREMone{#1}\\NEWTHEOREMtwo '); &defb("matrix","vmatrix","Vmatrix","smallmatrix","bmatrix","Sp","Sb", "CD","align","aligned","split","multiline","gather","gathered"); for ("documentclass", "documentstyle") { $type{"\\$_"}="sub2"; $contents{"\\$_"}="[]discard"; } # works as \end in LaTeX $type{"\\endTeXtoMail"}="sub1"; $contents{"\\endTeXtoMail"}="end"; if ($opt_TeX) { &define('\pmatrix#1','\left(\begin{matrix}#1\endTeXtoMail{matrix}\right)'); $type{"\\end"}="sub"; $contents{"\\end"}="end_TeX"; } else { $environment{"pmatrix"}="beg_lr;(;):matrix,endmatrix;1;c"; &defb("pmatrix") unless $opt_TeX; $type{"\\end"}="sub1"; $contents{"\\end"}="end"; } ## All the records should be specified before this point {local(@a)=grep("record" eq $type{$_},keys %type); for (@a) {chop $contents{$_} if substr($contents{$_},length($contents{$_})-1,1) eq "\n";}} for ("oplus","otimes","cup","wedge") { $type{"\\big$_"}=$type{"\\$_"}; $contents{"\\big$_"}=$contents{"\\$_"}; } @level=(0); @chunks=(0); @tokenByToken=(0); @out=(); $curlength=0; $debug_flow=1; $debug_record=2; $debug_parsing=4; $debug_length=8; $debug_matrix=16; #$debug |= $debug_flow | $debug_record | $debug_parsing | $debug_length; #$debug |= $debug_flow; #$debug |= $debug_record; #$debug |= $debug_parsing; #$debug |= $debug_length; #$debug |= $debug_matrix; $/ = $opt_by_par ? "\n\n" : ''; # whole paragraph mode while (¶graph()) { 1 } &finishBuffer; __END__ # History: Jul 98: \choose added, fixed RE for \noindent, \eqalign and \cr. # \proclaim and better \noindent added. # Sep 98: last was used inside an if block, was leaking out. # Jan 00: \sb \sp # Feb 00: remove extraneous second EOF needed at end. remove an empty line at end of output New option -by_par to support per-paragraph processing New option -TeX which support a different \pmatrix New option -ragged to not insert whitespace to align right margin. New option -noindent to not insert whitespace at beginning. Ignore \\ and \cr if followed by \end{whatever}. Ignore \noindent if not important. Ignore whitespace paragraphs. # Apr 00: Finishing a level 1 would not merge things into one chunk. # May 00: Additional argument to finish() to distinguish finishing things which cannot be broken between lines. # Sep 00: Add support for new macro for strings with screen escapes sequences: \LITERALnoLENGTH{escapeseq}. # Oct 00: \LITERALnoLENGTH can have a chance to work in the baseline only; in fact the previous version did not work even there... If the added record is longer than line length, do not try to break the line before it... # Apr 03: new option ignorefonts Hanging `}' (e.g., caused by translation of \\ to \par) would break processing of the rest of the file. Could not treat fraction as the first thing on the line (\noindent required). Support many more macros. Better support for \end (with -TeX), \footnote, \endgraph. Allow \over and other infix macros inside \left(\right). \label would not update $curlength. Whitespace edits. Update the limit of expansion of definitions to 10000 per paragraph (a recursion guard - used, e.g., per TeX's \pmatrix). New option scissors to emit a line when a high line is cut into pieces (disabled when ""). New option noflush (rarily useful optimization). Flush the output by default. \limits ignored. Allow one-level-deep *{NUMBER}{PRE} in array specifier (in addition to c,r,l). pari-2.17.2/misc/color.dft0000644000175000017500000000133314567450071013745 0ustar billbill! ! Suggested default value for the color_xterm resources for use under GP. ! See the color_xterm man for the meaning of these ! XTerm*highlightSelection: true XTerm.VT100.eightBitInput: true XTerm.VT100.eightBitOutput: true XTerm.VT100.titeInhibit: true XTerm.VT100.altScreenInhibit: true XTerm.VT100*colorMode: on XTerm.VT100*dynamicColors: on XTerm*color0: black XTerm*color1: red3 XTerm*color2: green3 XTerm*color3: #e52d2d XTerm*color4: blue3 XTerm*color5: magenta3 XTerm*color6: cyan3 XTerm*color7: gray90 XTerm*color8: gray30 XTerm*color9: red XTerm*color10: green XTerm*color11: yellow XTerm*color12: blue XTerm*color13: magenta XTerm*color14: cyan XTerm*color15: white XTerm*colorUL: yellow XTerm*colorBD: white pari-2.17.2/misc/gpflog0000755000175000017500000000017611636712103013327 0ustar billbill#!/bin/sh # # Strip escape sequences from PARI log file. for i in "$@"; do sed -e 's/[^]*//g; s/\[[0-9;]*m//g' $i done pari-2.17.2/misc/cook.c0000644000175000017500000001375214567450071013237 0ustar billbill/* From Loic Grenie */ /* to build gcc -o cook -O2 cook.c cp cook uncook to use (see mpigp) ./uncook mpirun -np 1 ./cook ./gp : -np 4 ./gp */ #define _XOPEN_SOURCE 600 #include #include #include #include #include #include #include #include #include #include #include #include int dead = 0, status; void chld_handler(int sig) { waitpid(-1, &status, WUNTRACED); if (WIFEXITED(status)) dead = 1; else if (WIFSIGNALED(status)) dead = 1; else if (WIFSTOPPED(status)) kill(getpid(), WSTOPSIG(status)); } void usage(char *argv0, int exitok) { fprintf(exitok ? stdout : stderr, "Usage: %s [-u] [-c] [--] program [args]\n", argv0); exit(!exitok); } int main(int argc, char **argv) { int cook, tiook = 0; struct termios tio; int fd; char *name, *argv0 = argv[0]; char bufin[1024], bufout[1024]; int lgin = 0, lgout = 0; if (argv[0]) { char *p = strrchr(argv[0], '/'); if (!p) p = argv[0]; else p++; cook = strcmp(p, "uncook"); } argc--; argv++; while (argc > 0 && *argv && **argv == '-') { char *p = *argv; if (!strcmp(*argv, "--")) { argc--; argv++; break; } else if (!strcmp(*argv, "--help")) usage(argv0, 1); while (*++p) { switch (*p) { case 'u': cook = 0; break; case 'c': cook = 1; break; default: usage(argv0, *p == 'h'); break; } } } if (argc <= 0 || !argv) usage(argv0, 0); if (cook) { fd = posix_openpt(O_RDWR); if (fd == 0) { fd = dup(fd); if (fd == 1) { fd = dup(fd); close(1); } close(0); } if (grantpt(fd) < 0) { perror("grantpt"); exit(3); } if (unlockpt(fd)) { perror("unlockpt"); exit(4); } name = ptsname(fd); } else { struct winsize wsz; if (!ioctl(0, TIOCGWINSZ, &wsz)) { char buf[1024]; sprintf(buf, "%d", wsz.ws_row); setenv("ROWS", buf, 0); sprintf(buf, "%d", wsz.ws_col); setenv("COLUMNS", buf, 0); } if (!tcgetattr(0, &tio)) { struct termios tio2; tiook = 1; bcopy(&tio, &tio2, sizeof tio); tio2.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); tio2.c_oflag &= ~OPOST; tio2.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); tio2.c_cflag &= ~(CSIZE | PARENB); tio2.c_cflag |= CS8; tcsetattr(0, TCSADRAIN, &tio2); } else (void)system("stty -isig -icanon -echo"); } switch(fork()) { case -1: perror("fork"); exit(1); case 0: /* Child */ if (cook) { char *prows, *pcols; struct winsize wsz; close(0); close(1); close(2); setsid(); close(fd); open(name, O_RDWR); /* stdin */ open(name, O_RDWR); /* stdout */ (void)system("stty sane pass8"); /* Before opening stderr */ open(name, O_RDWR); /* stderr */ if ((prows = getenv("ROWS")) && (pcols = getenv("COLUMNS"))) { wsz.ws_row = atoi(prows); wsz.ws_col = atoi(pcols); ioctl(0, TIOCSWINSZ, &wsz); } } execvp(argv[0], argv); fprintf(stderr, "Command not found\n"); exit(2); } signal(SIGCHLD, chld_handler); if (cook) { fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) & ~O_NONBLOCK); fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK); while (!dead || lgout) { int maxfd = 2, r; fd_set inset, outset; FD_ZERO(&inset); FD_ZERO(&outset); if (lgin < sizeof(bufin)) { FD_SET(0, &inset); if (maxfd < 1) maxfd = 1; } if (lgout) { FD_SET(1, &outset); if (maxfd < 2) maxfd = 2; } if (!dead && lgin) { FD_SET(fd, &outset); if (maxfd <= fd) maxfd = fd + 1; } if (!dead && lgout < sizeof(bufout)) { FD_SET(fd, &inset); if (maxfd <= fd) maxfd = fd + 1; } select(maxfd, &inset, &outset, NULL, NULL); if (FD_ISSET(0, &inset)) { r = read(0, bufin+lgin, sizeof(bufin) - lgin); if (r > 0) lgin += r; else close(0); } if (FD_ISSET(1, &outset)) { r = write(1, bufout, lgout); if (r <= 0) lgout = 0; else lgout -= r; } if (FD_ISSET(fd, &inset)) { r = read(fd, bufout+lgout, sizeof(bufout) - lgout); if (r <= 0) exit(0); lgout += r; } if (FD_ISSET(fd, &outset)) { r = write(fd, bufin, lgin); if (r <= 0) exit(0); lgin -= r; } } } else { while (!dead) chld_handler(0); } if (tiook) tcsetattr(0, TCSADRAIN, &tio); if (dead) { if (WIFEXITED(status)) exit(WEXITSTATUS(status)); else if (WIFSIGNALED(status)) kill(getpid(), WTERMSIG(status)); fprintf(stderr, "Unknown exit status %08x\n", status); exit(1); } /* NOT REACHED */ exit(0); } pari-2.17.2/misc/mpigp0000755000175000017500000000010114567450071013162 0ustar billbill#! /bin/sh # see cook.c ./uncook mpirun -np 1 ./cook ./gp : "$@" pari-2.17.2/misc/gprc.dft0000644000175000017500000000751214676526175013601 0ustar billbill/* SAMPLE GP INIT FILE. * * Customize (by uncommenting and modifying the relevant lines) and put in * $HOME/.gprc (or $GPRC) or /etc/gprc. Syntax is explained at the end. */ \\ Read ~/.gprc.gp (GP script) before gp prompts you for commands. \\ read "~/.gprc.gp" /* Critical options */ \\ Limit PARI stack size to 400 Mbytes = 4*10^8 bytes \\ parisizemax = 400M \\ Set PARI typical stack size to 40 Mbytes = 4*10^7 bytes (will grow as \\ needed, up to parisizemax) \\ parisize = 40M /* Parallelism */ \\ number of threads: (0: use all available CPU threads) \\ nbthreads = 0 \\ Limit PARI threads stack size to 100 Mbytes = 10^8 bytes \\ threadsizemax = 100M \\ Set PARI typical threads stack size to 10 Mbytes = 10^7 bytes (will grow as \\ needed, up to threadsizemax). Beware that the memory usage is multiplied \\ by the number of threads. \\ threadsize = 10M /* Important options */ \\ Save a history of all input commands in this file, and load it in each \\ new session's history \\ histfile = ~/.gp_history \\ Limit output of results to 40 lines \\ lines = 40 \\ Colors: \\ clear background: \\ #ifnot EMACS colors = "lightbg" \\ dark background: \\ #ifnot EMACS colors = "darkbg" \\ Set gp prompt. % is used for macros related to the time of day [back to \\ the shell prompt, try "man strftime"]. Example: %H:%M = time of day in the \\ form HH:MM. Characters can be escaped UNIX-style using '\', e.g \e = \\ \\ prompt = "(%H:%M) \e[1mgp\e[m > " \\ #if READL prompt = "(%H:%M) \e[1mgp\e[m > " \\ #if EMACS prompt = "? " \\ Set timer on \\ timer = 1 \\ Path: directories where gp will look for scripts \\ path = ".:~:~/gp" \\ Use an alternate prettyprinter \\ prettyprinter = "/usr/local/bin/tex2mail -TeX -noindent -ragged -by_par" \\ Extended help options (does not interact well with emacs): \\ Don't use TeX + xdvi, but outputs formatted help in GP window: \\ #ifnot EMACS help = "gphelp -detex" \\ Same, using colors: \\ #ifnot EMACS help = "gphelp -detex -ch 4 -cb 0 -cu 2" /* Some less important options */ \\ Biggest precomputed prime (= precprime(10^6)) \\ primelimit = 1M \\ Fast trial division by primes up to this bound. Raising it will noticeably \\ increase startup time (5 minutes for 2^32) \\ factorlimit = 1M \\ Set logfile name and enable logging. \\ Uncommenting the next two lines produces a different logfile each day: \\ logfile = "~/tmp/pari-%d.%m" \\ log = 1 \\ Output for postscript-producing gp commands. \\ psfile = "~/tmp/pari.ps" \\ secure = 1 \\ Disable commands system() and extern() which allow scripts to execute \\ arbitrary Unix commands \\********************** FORMAT OF THIS FILE : *************************** \\ Lines starting with '\\' and between '/*' '*/' pairs are comments \\ Blank lines are ignored \\ Line starting with #if BOOLEAN is read iff BOOLEAN is TRUE \\ Currently recognized booleans: \\ BITS_IN_LONG == N gp build for N-bit architecture (N = 32 or 64) \\ EMACS are we running under Emacs? \\ READL is readline available? \\ VERSION {<,>,<=,>=} a.b.c does version number satisfy the inequality? \\ \\ This file should be put in $HOME/.gprc or /etc/gprc and contains: \\ * references to gp scripts that are to be run BEFORE the first gp prompt. \\ \\ Syntax: read "filename" (quotes mandatory; ~ syntax for homedir allowed) \\ \\ * options settings \\ \\ Syntax: option_name = value \\ \\ Options which are not set here assume default values in gp. The command \\ default() under GP lists available options and their default values. \\ \\ Options settings are overriden by command line switches. For instance \\ gp --default parisizemax=1G \\ gp -D parisizemax=1G \\ both set parisize to 1 GByte, regardless of what is in .gprc \\ They can also be changed under GP using default(), e.g. \\ default(parisize,"10M") pari-2.17.2/misc/gpalias0000644000175000017500000000143111636712103013461 0ustar billbillalias(algtobasis,nfalgtobasis); alias(basistoalg,nfbasistoalg); alias(cf,contfrac); alias(classgroup,bnfclassunit); alias(coeff,polcoeff); alias(compositum,polcompositum); alias(degree,poldegree); alias(disc,poldisc); alias(discreduced,poldiscreduced); alias(extract,vecextract); alias(galois,polgalois); alias(hnf,mathnf); alias(hnfmod,mathnfmod); alias(ker,matker); alias(kerint,matkerint); alias(kro,kronecker); alias(ln,log); alias(matconcat,concat); alias(matextract,vecextract); alias(mod,Mod); alias(pnqn,contfracpnqn); alias(resultant,polresultant); alias(roots,polroots); alias(rootsmod,polrootsmod); alias(rootspadic,polrootspadic); alias(sercoeff,polcoeff); alias(snf,matsnf); alias(trunc,truncate); alias(tschirnhaus,poltschirnhaus); alias(vecbern,bernvec); alias(vectorh,vector); pari-2.17.2/CHANGES-2.160000644000175000017500000003242114760123736012556 0ustar billbillDone for version 2.16.2 (released 02/08/2024): Fixed XR 1- rare oo-loop in nfdisc [#2510] PB 2- polcoeff(polmodular(2, 0, ffgen([7,2])^0),0).mod -> incorrect [#2533] BA 3- rnfconductor(...,[P, B]) -> wrong result [#2534] 4- vecsearch(t_LIST,) would raise a type error [#2535] 5- subcycloiwasawa(x^2+87,3) -> SEGV 6- forprimestep and variants with initial value negative [#2531] 7- when converting a t_QFB to a vector of given length, remove discriminant 8- \o3 [tex2mail]: support \* 9- rnfpolredabs didn't always return a canonical model [#2538] 10- weber(I/2+1/3,2) -> SEGV BA 11- [mpi] setting datadir or path in .gprc caused crashes 12- imprecise sqrtnr [#2543] 13- idealstar(nf,id,,MOD). Need to store MOD in the structure, otherwise exceptions may occur [#2549] BA 14- ellsaturation was leaking variable numbers 15- rnfelttrace(rnf, t_POL in rnf.pol variable): wrong [#2509] 16- rnfeltnorm(rnf, t_POL in rnf.pol variable): wrong [#2509] 17- b=9/10; hypergeom([b+2, b], 2*b, 2/3): wrong [#2551] 18- overflows not tested in subcycloiwasawa [#2552] 19- randomprime([1,2], Mod(1,2)) -> 3 BA 20- b;a;gcd(Mod(1,a^2+1),Mod(1,b^2+Mod(-a,a^2+1))) -> wrong result [#2553] 21- idealismaximal(nf, ) -> impossible inverse [#2556] 22- polynomial coefs which are exact 0 should not be printed [#2558] 23- f = Mod(Mod(1,3), Mod(a^2+2,3))*x^3; (1/f) * O(x^2) -> O(x^0) instead of Mod(Mod(0, 3), Mod(1, 3)*a^2 + Mod(2, 3))*x^-2 + O(x^-1) [#2558] BA 24- hgmeulerfactor could return wrong result [#2557] 25- (Mod(0,2)+O(x)) * (1+O(x)) -> Mod(0, 2)*x + O(x^2) [#2559] BA 26- z = ffgen(11^5)^0; fflog(z, z, 1) ->SEGV [#2562] Changed BA 1- plotell renamed to plotarc 2- lfun for degree 1 L-functions: use Riemann-Siegel when imag(s) is large 3- zetahurwitz, lerchzeta: use Tyagi's method when imag(s) is large 4- forprimestep: allow modulus not fitting in an unsigned long 5- specify how Vec(v, n) truncates v when #v > |n|. Changes previous behaviour when n < 0: Vec([1,2,3], -2) -> [2,3] (was [1,2]) Same for Vecrev, Vecsmall, Col, and Colrev. BA 6- allow abs(+oo), abs(-oo) BA 7- [libpari] gp_embedded : make interface more similar to GP BA 8- [libpari] callback cb_pari_display_hist (used by gp_embedded) 9- [libpari] the diffptr low level interface is gone (table of difference of primes), replaced by a table of 32bit primes (pari_PRIMES). The byteptr type and following functions / macros are gone: initprimes, init_primepointer_geq, init_primepointer_gt, init_primepointer_leq, init_primepointer_lt NEXT_PRIME_VIADIFF, PREC_PRIME_VIADIFF, NEXT_PRIME_VIADIFF_CHECK. 10- bnfisintnorm: add flag to return solution in factored form Added BA 1- GP function mapapply BA 2- GP function qfcholesky BA 3- [libpari] pari_err_display, gp_display_hist, str_display_hist 4- allow vecmin and vecmax to handle t_LIST 5- support 'rnf' structure in nfnewprec 6- [libpari] rnfnewprec, rnfnewprec_shallow BA 7- [examples] gp_embedded.c, like minigp.c but using gp_embedded 8- new GP default 'factorlimit' XR 9- new GP function bnrstarkunit 10- [libpari] bid_get_MOD 11- [libpari] Z_to_famat, Q_to_famat BA 12- new GP function hyperellordinate BA 13- [libpari] closure_callgen0 WvW 14- new GP function qfcvp BA 15- new GP function ellmaninconstant BA 16- new GP function nfweilheight BA 17- [libpari] Qp_psi NM 18- [libpari] FlxqX_eval 19- [libpari] Qp_zetahurwitz 20- [libpari] PRIMES_search HC 21- psi: support for derivative and t_PADIC 22- [libpari] ZM2_sqr BA 23- [libpari] FpXQX_roots_mult BA 24- [libpari] ZXX_pvalrem, ZXV_pvalrem BA 25- [libpari] pari_breakloop Done for version 2.16.1 (released 04/01/2024): Fixed BA 1- lfunan(lfunetaquo([12,1;13*12,1]),1) -> stack overflow [#2457] BA 2- FpM_intersect could return a Flm [#2459] 3- ifactor_sign: ifac_isprime could be called on input with tiny divisors BA 4- nfcompositum could return non-monic polynomials [#2461] BA 5- gammamellininvinit(vector(9,i,1)) -> SEGV 6- incorrect sanity check in rnfeltdown ("not in base field") [#2464] HC 7- precision loss in gammamellininv [#2462] BA 8- [pthread] parselect could crash BA 9- rare infinite loop in ellsaturation BA 10- quadunitindex(8461,2)->1 instead of 3 [#2466] BA 11- chinese(Mod(1,3)*(x^2+x+2),Mod(1,5)*(x-1)) -> incorrect leading term BA 12- lindep([0,x]) -> SEGV BA 13- [libpari] RgX_div_by_X_x: wrong variable number 14- incorrect results in bnrisprincipal if bitprecision too low [#2474] MS 15- hyperellratpoints(2*x^3+x^2-x,1000) -> wrong result [#2475] BA 16- ellisogeny over a nf -> inconsistent variables error BA 17- w=3;quadgen(5) -> print x instead of w [#2477] BA 18- FpX_convol: wrong result for mixed degree LGr 19- parsum was inefficient 20- mateigen(,1): eigenvalues were given as t_VEC or t_COL. Use t_COL. BA 21- ellcard over small finite field: potential oo-loop [#2483] BA 22- ellisomat/nf could miss isogenies of degree dividing the conductor 23- mfcoef(mftwist(f,D), ...) wrong result [#2484] 24- sumeulerrat / prodeulerrat: slow if s not an integer [#2433] 25- 'path' broken when initial or trailing ':' 26- snfrank([1],0) -> 1 [instead of 0]. 27- snfrank(vector of polynomials, 0) -> error 28- division of t_POLs with compatible domains Mod(1,2)/(2*x+1) -> Mod(1,2) 29- strjoin([1]) -> memory corruption 30- qfbclassno(684) -> oo loop [#2491] 31- gcd(x-1,(x-1)/x) -> 1/x PMo 32- mftonew was wrong on oldspace -> remove mfbd layer BA 33- rnf.p did not work 34- expm1(tiny negative t_REAL) -> stack overflow [#2494] 35- expm1(huge t_REAL) -> junk [#2494] BA 36- hyperellratpoints(9*x^2,3) -> SEGV 37- lambertw for 2-adics (also fix documentation) BA 38- plotbox, plotrbox did not clip properly BA 39- ellheight for non-minimal curve over a number field -> wrong result 40- for x >= 0, x^(a/b) was using (x^(1/b))^a instead of x^q*x^(r/b), with a = qb + r. 41- hypergeom(t_POL parameters, z) -> type error [#2515] 42- polrootsreal(0E10*x + 0E10) -> SEGV [#2516] BA 43- memory leak when using member functions and ~ arguments. [#2513] 44- idealstar(nf,id,,MOD).cyc was not reduced modulo MOD 45- changed qfbred to use standard normalization (same as qfbredsl2) Changed HC 1- dirpowerssum: allow functions with t_VEC output HC 2- dirpowerssum: add optional flag 'both' [also in library mode] BA 3- [libpari] RgX_halfgcd now only return the matrix. Use RgX_halfgcd_all BA 4- [libpari] ec_bmodel, ec_phi2 now take a variable number BA 5- ellisomat: when E/nf has CM by an quadratic order included in nf, return the discriminant of the order instead of an error [#2231] BA 6- ZX_compositum_disjoint: renamed to ZX_composedsum 7- allow t_INTMOD Mod(m,N) as a Conrey label for the character m mod N 8- nfroots: return a t_COL instead of a t_VEC (same as other 'roots' fun) 9- qfbsolve: call qfbcornacchia when the argument is prime (and disc < 0) BA 10- [libpari] rename qfb_apply_ZM -> qfb_ZM_apply, qf_apply_RgM -> qf_RgM_apply, qf_apply_ZM -> qf_ZM_apply 11- rnfinit(nf, [T,lim]); try to fix maximal order if wrong [#2494] BA 12- [libpari] change prec to be a number of bits, instead of lg BA 13- [libpari] suminf_bitprec, intnumromb_bitprec: use suminf, intnumromb ellL1_bitprec, ellanalyticrank_bitprec: use ellL1, ellanalyticrank Added 1- [libpari] nfeltembed_i BA 2- [libpari] Flx_extresultant_pre, FlxqX_resultant_pre BA 3- [libpari] gc_stoi, gc_utoi, gc_utoipos BA 4- [libpari] F2xX_shift BA 5- [libpari] Flx_Fl_mul_pre BA 6- [libpari] Flx_halfgcd_all, Flx_halfgcd_all_pre, FpX_halfgcd_all, FlxqX_halfgcd_all, FlxqX_halfgcd_all_pre, FpXQX_halfgcd_all, F2xqX_halfgcd_all, FFX_halfgcd_all, RgX_halfgcd_all 7- [libpari] modRr_i BA 8- [libpari] random_Fq 9- [libpari] maxprimelim BA 10- [libpari] FlxqX_div_by_X_x, FlxqX_div_by_X_x_pre BA 11- [libpari] Fl_2gener_pre_i, Fp_2gener_i, Fl2_sqrt_pre, Flxq_sqrt_pre BA 12- [libpari] Fq_elljissupersingular BA 13- [libpari] FpXQ_ellcard_supersingular, Fq_ellcard_supersingular BA 14- [libpari] Fp_ellj_to_a4a6 BA 15- [libpari] ec_half_deriv_2divpol BA 16- New GP functions polisclass, elliscm BA 17- [libpari] elljsupersingular_FpXQ BA 18- New GP function ellsupersingularj BA 19- [libpari] Flx_composedsum, FlxV_composedsum FpX_composedsum, FpXV_composedsum FlxqX_composedsum BA 20- [libpari] Flx_convol, Flx_composedprod, FpX_composedprod BA 21- [libpari] RgV_F2v_extract_shallow 22- [libpari] Fp_double 23- [libpari] convenience function veclast 24- allow snfrank(D,0) for snfrank(D) 25- [libpari] dbg_fill_stack() [#2361] 26- allow erfc(t_SER) 27- allow hypergeom(N,D,t_PADIC) BA 28- n#: primorial of n 29- allow bernpol(k, a) [ = B_k(a) ] BA 30- allow Qfb(a*x^2+b*x+c) and Qfb([a,b0;b1,c]) BA 31- New GP function parforstep BA 32- New GP function polfromroots BA 33- digits: support for negative bases but positive digits. AP 34- alginit: new flag value for lazy factorization BA 35- [libpari] F2xqXV_prod, F2xqV_roots_to_pol, FFV_roots_to_pol BA 36- [libpari] RgM_div BA 37- [libpari] ZV_max_expi, ZM_max_expi BA 38- [libpari] ZM_merge_factor BA 39- [libpari] RgM_Cholesky BA 40- [libpari] hash_keys_GEN 41- support kB or KB, MB, GB and TB as units for memory sizes (2^10, 2^20, 2^30 and 2^40 bytes) BA 42- [libpari] lg2prec, prec2lg BA 43- New GP function ellisisom BA 44- allow qfsolve([Q,F]) where F factorization of disc(Q) BA 45- New GP function plotell Removed 1- [graphic] support for Qt4 Done for version 2.16.0 (released 25/02/2023): Fixed BA 1- ploth long help was misformatted 2- polredbest(y^4 - y^3 - 1/4, 1) -> Error [#2414] 3- mathnf over polynomial rings: wrong when rank not maximal [#2415] BA 4- seralgdep(Ser([0,1,0,u]*Mod(1,(u^2+u+1)*Mod(1,2)),y),2,2) -> SEGV 5- polroots(4*x^3+4*x^2+28*x+144) -> overflow [#2418] 6- conversion to float of t_QUAD with t_FRAC components [#2419] 7- bnfinit(x^3-810693844986180*x-30702939461011257135364,1).fu -> wrong result or SEGV [#2420] 8- [1,2]*[3,4] -> strange error message about qfbcomp 9- obscure oo loop in solve when solution ~ 0 [#2412] 10- polcyclo(huge n, t_PADIC of positive valuation) -> overflow 11- charpoly over R or C was unstable [#2406] 12- polredbest: rare error "inconsistent concatenation" [#2423] 13- hypergeom([0,0],[1],2) -> SEGV [#2425] 14- fromdigitsu(v, B) actually computed fromdigitsu(v, |B|) 15- powers(t_INT, ...) was very slow 16- factor(prod(i=1,20,nextprime(2^i)), 131) would include 131 instead of stopping at 67 17- sumeulerrat(x^2/(1+x),2) -> FPE [#2433] 18- lambertw(10^1000) -> overflow [#2429] 19- rare infinite loop in idealtwoelt [#2437] BA 20- nfisisom(16*x^4+1,16*x^4+1) -> error [#2432] 21- forprimestep(p=a,b,q,) overflow when a > primelimit and q large [#2439] BA 22- lfun([bnrinit(bnfinit(y^2+1),12),[[2,0],[6,0]]],2) -> error 23- lfunthetacost(polcyclo(43)): silent overflow BA 24- ellcard(ellinit([1,1]*ffgen([41,16])))-> impossible inverse [#2441] 25- wrong result (missing content) in idealred(nf, [id, elt]) 26- det(integer matrix) -> inconsistent exact division [#2445] BA 27- fft([],[]) -> SEGV, fft([1],[1]) -> SEGV BA 28- nfrootsof1(x^0) -> oo-loop BA 29- hgmalpha did not check its input BA 30- hyperellchangecurve([],[]) -> SEGV BA 31- hyperellchangecurve(x^0,[1,matid(2),0]) -> SEGV BA 32- rnfeltnorm(x,x) -> SEGV BA 33- polylogmult(1,[],-1) -> SEGV 34- ellheight(non-integral E) -> crash [#2448] 35- content(1,y) -> pol_1(y) instead of t_INT 1 36- s=taylor(1/((x-1)*(y-1)),x); taylor(s,y) -> invalid object [#2452] 37- avoid crashing when sumnumsidi diverges (0 bits of accuracy) [#2454] Changed 1- binomial(negative t_INT, t_INT): use Loeb's definition 2- normalize t_RFRAC so that leading coeff of denoimator is "positive"; compare: 1/(1-x) and 1/(x-1) 3- t_SER: valser, evalvalser, setvalser need to be used instead of valp, evalvalp, setvalp 4- mathess over R or C: use maximal pivot instead of first non-zero 5- default 'parisize' is now 8M on both 32bit and 64bit architectures 6- default 'realprecision' is now 38 on both 32bit and 64bit architectures 7- default 'realbitprecision' is now 128 on both 32bit and 64bit architectures 8- default 'primelimit' is now 2^20 [instead of 500000] 9- allow fromdigits(t_COL or t_VECSMALL, B) 10- [libpari] cgetalloc arguments swapped to mirror cgetg's definition 11- simplified lfunabelianrelinit (absolute equation is now optional) 12- quadclassnoF_fact and uquadclassnoF_fact now return h(D)/h(d), like quadclassnoF. Added PMo 1- new syntax for forvec loops BA 2- [GP] genus2igusa 3- printf numerical conversions: support complex numbers [#2431] 4- libpari vecsmall_counting_indexsort, vecsmall_counting_sort vecsmall_counting_uniq BA 5- [riscv64] add riscv64 assembly kernel BA 6- lfuncreate([bnr, subg]): Dedekind zeta for the corresponding Abelian extension. Removed BA 1- [GP] lfunabelianrelinit. Use lfunfinit([bnr, subgroup]) instead. pari-2.17.2/examples/0000755000175000017500000000000014760315601013005 5ustar billbillpari-2.17.2/examples/EXPLAIN0000644000175000017500000001165614760123736014047 0ustar billbillThis directory contains: * Inputrc: an example of .inputrc file for the readline library. * A generic Makefile for PARI programs, adapted to your system by Configure. * the C program extgcd.c using the Pari library described in Chapter 4 of the users' manual. To build it, run: make TARGET=extgcd * the C program minigp.c using low-level functions in the Pari library to implement a basic GP interpretor using libreadline. This shows in particular how to add a new function 'quit' to the interpretor. To build it, run make TARGET=minigp EXTRALIBS=-lreadline * the C program gp_embedded.c using the gp_embedded() function to simplify minigp. To build it, run make TARGET=gp_embedded EXTRALIBS=-lreadline * the C program pari-mt.c using the Pari library interface for parallel computation. To build it, run make TARGET=pari-mt * the C program thread.c using the Pari library in a multi-threaded context, POSIX threads version, as described in Appendix D of the users' manual. This requires that PARI is Configured with --enable-tls. To build it, run make TARGET=thread EXTRALIBS=-lpthread * the C program openmp.c using the Pari library in a multi-threaded context, OpenMP version, as described in Appendix D of the users' manual. This requires that PARI is Configured with --enable-tls. To build it, run make TARGET=openmp EXTRACFLAGS=-fopenmp * the FORTRAN90 program pari.f90 that shows how to write PARI bindings to use libpari in a FORTRAN program. * Several examples of complete GP programs. The rest of this file gives a brief description of these programs. They should be read into GP by the command \r file. -- bench.gp: This program computes the first 1000 terms of the Fibonacci sequence, the product p of successive terms, and the lowest common multiple q. It outputs the ratio log(p)/log(q) every 50 terms, which tends to Pi^2/6 as k tends to infinity. The name bench.gp comes from the fact that this program is one (among many) examples where GP/PARI performs orders of magnitude faster than systems such as Maple or Mathematica. (Try it!) -- cl.gp: Written entirely in the GP language without using bnfinit, the programs included in this file computes the class number, the structure of the class group and a system of fundamental units of a general number field. It sometimes fail to give an answer and works only if nfinit finds a power basis. Evidently it is less powerful, less reliable and much slower than bnfinit, but it is given as an example of a sophisticated use of GP. The first thing to do is to call clareg(pol, {limp=19},{lima=50},{extra=5}) where pol is the monic irreducible polynomial defining the number field, limp is the prime factor base limit (try values between 19 and 113), lima is another search limit (try 50 or 100) and extra is the number of desired extra relations (try 2 to 10). Default values are provided, so that you need only supply pol. The program prints the number of relations that it needs, and tries to find them. If you see that it slows down too much before succeeding, abort and try other values. If it succeeds, it will print the class number, class group and regulator. These are tentative values. Then use check({lim = 100}) to check if the value is consistent with the value of the L-series (the value returned should be close to 1). Finally, fu() (no parameters) returns a family of units which generates the unit group (you must extract a system of fundamental units yourself). -- classno.gp: a simple function to compute analytically the class number of imaginary quadratic fields (written by Fernando Rodriguez Villegas) -- contfrac.gp: period(D) computes period of continued fraction for sqrt(D) [slower than quadregulator, which does a bit more work, but is written in C!] (written by Igor Schein) -- lucas.gp: The function lucas(p) defined in this file performs the Lucas-Lehmer primality test on the Mersenne number 2^p-1. If the result is 1, the Mersenne number is prime, otherwise not. -- rho.gp: a simple implementation of Pollard's rho method. The function rho(n) outputs the complete factorization of n in the same format as factor. -- squfof.gp: This defines a function squfof of a positive integer variable n, which may allow you to factor the number n. SQUFOF is a nice factoring method invented in the 70's by Dan Shanks for factoring integers, and is reasonably fast for numbers having up to 15 or 16 digits. The squfof program given here is a crude implementation, which prints out some intermediate information as it goes along. The final result is some factor of the number to be factored. -- taylor.gp: the function plot_taylor(f,xmin,xmax, ordlim, first,step) plots the Taylor polynomials T_i (truncated series expansion of order i) of the function f in the interval [xmin,xmax]; i goes from first to ordlim in increments of steps. Sensible default values are provided for all arguments (adapted from an original idea by Ilya Zakharevich). A few examples are provided, together with a simple colormap generator pari-2.17.2/examples/parigp.sty0000644000175000017500000000061414567450071015037 0ustar billbill% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Including this package allows to use PARI/GP-output % % written by the writetex() function of gp directly % % inside AMSLaTeX. % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \ProvidesPackage{parigp}[2019/02/05] \RequirePackage{amsmath} \def\pmatrix#1{\left(\env@matrix#1\endmatrix\right)} pari-2.17.2/examples/thread.c0000644000175000017500000000372514567450071014435 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 = QM_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) { long prec = DEFAULTPREC; GEN M1,M2, N1,N2, F1,F2, D1,D2; pthread_t th1, th2, th3, th4; /* POSIX-thread variables */ struct pari_thread pth1, pth2, pth3, pth4; /* pari thread variables */ /* Initialise the main PARI stack and global objects (gen_0, etc.) */ pari_init(32000000,500000); /* Compute in the main PARI stack */ N1 = addis(int2n(256), 1); /* 2^256 + 1 */ N2 = subis(int2n(193), 1); /* 2^193 - 1 */ M1 = mathilbert(149); M2 = mathilbert(150); /* Allocate pari thread structures */ pari_thread_alloc(&pth1,8000000,N1); pari_thread_alloc(&pth2,8000000,N2); pari_thread_alloc(&pth3,32000000,M1); pari_thread_alloc(&pth4,32000000,M2); /* 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); pthread_create(&th4,NULL, &mydet, (void*)&pth4); /* Start 4 threads */ pthread_join(th1,(void*)&F1); pthread_join(th2,(void*)&F2); pthread_join(th3,(void*)&D1); pthread_join(th4,(void*)&D2); /* Wait for termination, get the results */ pari_printf("F1=%Ps\nF2=%Ps\nlog(D1)=%Ps\nlog(D2)=%Ps\n", F1,F2, glog(D1,prec),glog(D2,prec)); pari_thread_free(&pth1); pari_thread_free(&pth2); pari_thread_free(&pth3); pari_thread_free(&pth4); /* clean up */ return 0; } pari-2.17.2/examples/extgcd.c0000644000175000017500000000162114557721030014430 0ustar billbill#include /* GP;install("extgcd", "GG&&", "gcdex", "./libextgcd.so"); */ /* return d = gcd(a,b), sets u, v such that au + bv = gcd(a,b) */ GEN extgcd(GEN A, GEN B, GEN *U, GEN *V) { pari_sp av = avma; GEN ux = gen_1, vx = gen_0, a = A, b = B; if (typ(a) != t_INT) pari_err_TYPE("extgcd",a); if (typ(b) != t_INT) pari_err_TYPE("extgcd",b); if (signe(a) < 0) { a = negi(a); ux = negi(ux); } while (!gequal0(b)) { GEN r, q = dvmdii(a, b, &r), v = vx; vx = subii(ux, mulii(q, vx)); ux = v; a = b; b = r; } *U = ux; *V = diviiexact( subii(a, mulii(A,ux)), B ); gerepileall(av, 3, &a, U, V); return a; } int main() { GEN x, y, d, u, v; pari_init(1000000,2); printf("x = "); x = gp_read_stream(stdin); printf("y = "); y = gp_read_stream(stdin); d = extgcd(x, y, &u, &v); pari_printf("gcd = %Ps\nu = %Ps\nv = %Ps\n", d, u, v); pari_close(); return 0; } pari-2.17.2/examples/lucas.gp0000644000175000017500000000012514557721030014443 0ustar billbilllucas(p) = { my(u = 4, q = 1<

#include #include #include #include jmp_buf env; int gp_is_interactive(void) { return pari_infile == stdin; } void gp_err_recover(long numerr) { longjmp(env, numerr); } void gp_quit(long exitcode) { exit(exitcode); } entree functions_gp[]={ {"quit",0,(void*)gp_quit,11,"vD0,L,","quit({status = 0}): quit, return to the system with exit status 'status'."}, {NULL,0,NULL,0,NULL,NULL}}; int main(int argc, char **argv) { pari_init(8000000,500000); pari_add_module(functions_gp); cb_pari_err_recover = gp_err_recover; cb_pari_is_interactive = gp_is_interactive; cb_pari_quit = gp_quit; sd_colors("lightbg",d_INITRC); gp_load_gprc(); pari_print_version(); (void)setjmp(env); while(1) { const char *prompt = gp_format_prompt(GP_DATA->prompt); char *in = readline(prompt); if (!in) break; if (!*in) continue; add_history(in); gp_echo_and_log(prompt,in); gp_embedded(in); free(in); set_avma(pari_mainstack->top); } return 0; } pari-2.17.2/examples/pari-mt.c0000644000175000017500000000222614567450071014532 0ustar billbill#include GEN Cworker(GEN d, long kind) { return kind? det(d): Z_factor(d); } int main(void) { long i, taskid, pending; GEN M,N1,N2, in,out, done; struct pari_mt pt; entree ep = {"_worker",0,(void*)Cworker,20,"GL",""}; /* initialize PARI, postponing parallelism initialization */ pari_init_opts(8000000,500000, INIT_JMPm|INIT_SIGm|INIT_DFTm|INIT_noIMTm); pari_add_function(&ep); /* add Cworker function to gp */ pari_mt_init(); /* ... THEN initialize parallelism */ /* Create inputs and room for output in main PARI stack */ N1 = addis(int2n(256), 1); /* 2^256 + 1 */ N2 = subis(int2n(193), 1); /* 2^193 - 1 */ M = mathilbert(80); in = mkvec3(mkvec2(N1,gen_0), mkvec2(N2,gen_0), mkvec2(M,gen_1)); out = cgetg(4,t_VEC); /* Initialize parallel evaluation of Cworker */ mt_queue_start(&pt, strtofunction("_worker")); for (i = 1; i <= 3 || pending; i++) { /* submit job (in) and get result (out) */ mt_queue_submit(&pt, i, i<=3? gel(in,i): NULL); done = mt_queue_get(&pt, &taskid, &pending); if (done) gel(out,taskid) = done; } mt_queue_end(&pt); /* end parallelism */ output(out); pari_close(); return 0; } pari-2.17.2/examples/taylor.gp0000644000175000017500000000340614567450071014660 0ustar billbill\\ adapted from an original idea by Ilya Zakharevich \\ generate an RGB color triple from a "magnitude" between 0 and 255 \\ (low = close to a cold blue, high = close to a hot red). \\ To generate simple colormaps. rgb(mag) = { my(x = mag/255., B, G, R); B = min(max(4*(0.75-x), 0), 1); R = min(max(4*(x-0.25), 0), 1); G = min(max(4*abs(x-0.5)-1, 0), 1); return (floor([R, G, B]*255)); } default(graphcolormap, concat(["white","black","blue"], vector(25,i,rgb(10*i)))); default(graphcolors, vector(25,i,i+2)); \\ plot Taylor polynomials of f, \\ of index first + i*step <= ordlim, for x in [xmin,xmax]. plot_taylor(f, xmin=-5, xmax=5, ordlim=16, first=1, step=1) = { my(T,s,t,w,h,dw,dh,cw,ch,gh, extrasize = 0.6); my(Taylor_array); default(seriesprecision,ordlim+1); T = f('q); ordlim = (ordlim-first)\step + first; Taylor_array = vector(ordlim+1); forstep(i=ordlim+1, 1, -1, T += O('q^(1 + first + (i-1)*step)); Taylor_array[i] = truncate(T) ); t = plothsizes(); w=floor(t[1]*0.9)-2; dw=floor(t[1]*0.05)+1; cw=t[5]; h=floor(t[2]*0.9)-2; dh=floor(t[2]*0.05)+1; ch=t[6]; plotinit(2, w+2*dw, h+2*dh); plotinit(3, w, floor(h/1.2)); \\ few points (but Recursive!), to determine bounding box s = plotrecth(3, x=xmin,xmax, f(x), "Recursive|no_X_axis|no_Y_axis|no_Frame", 16); gh=s[4]-s[3]; plotinit(3, w, h); plotscale(3, s[1], s[2], s[3]-gh*extrasize/2, s[4]+gh*extrasize/2); plotrecth(3, x=xmin,xmax, subst(Taylor_array, 'q, x), "no_Rescale"); plotclip(3); plotcopy(3, 2, dw, dh); plotmove(2, floor(dw+w/2-15*cw), floor(dh/2)); plotstring(2, "Multiple Taylor Approximations"); plotdraw(2); } \p9 plot_taylor(sin) plot_taylor(exp,-3,3) plot_taylor(x->besselk(2,x), 1,5) plot_taylor(x->1/(1+x^2), -1.2,1.2) pari-2.17.2/examples/openmp.c0000644000175000017500000000240514567450071014456 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(8000000,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],8000000,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.17.2/examples/classno.gp0000644000175000017500000000165314557721030015005 0ustar billbill\\ --------------- GP code --------------------------------------- \\ \\ Time-stamp: \\ \\ Description: Compute class number of imaginary quadratic field \\ analytically \\ \\ File: classno.gp \\ \\ Original Author: Fernando Rodriguez-Villegas \\ villegas@math.utexas.edu \\ University of Texas at Austin \\ \\ Created: Fri Mar 26 1999 \\----------------------------------------------------------------- \\ Class number h(-d), -d fundamental. \\ Adjust constant cc for accuracy, default at least 9 decimal places. cl(d, cc = 5) = { my(q0,sd,c, s = 0, q = 1); if (!isfundamental(-d), error("Discriminant not fundamental")); sd = sqrt(d); q0 = exp(-2*Pi/sd); c = -4*Pi/sd; for (n=1, ceil(sd*cc), my(t); q *= q0; t = 1/(1-q); s += kronecker(-d,n) * q * t * (1 + c*t*n) ); if (d==3, s *= 3, d==4, s *= 2); -2*s; } pari-2.17.2/examples/cl.gp0000644000175000017500000000525514557721030013743 0ustar billbillrgcd(a,b)= { [a,b] = [abs(a), abs(b)]; while (b > 0.01, [a,b] = [b,a%b]); a; } global(nf, km, m, clh, R, areg, re, res, mreg); f(a,b, nf,v,ind)= { my(u, vreg); my(n = idealnorm(nf, a + b*variable(nf.pol))); my(mv = vectorv(#v)); forprime (p=2, #ind, my (l = valuation(n,p)); if (l, my(cp, j = ind[p]); n /= p^l; cp = v[j][2]; while((a+b*cp)%p, j++; cp = v[j][2] ); mv[j] = l ) ); if (n!=1, return); my (r1 = nf.sign[1]); /* found a relation */ vreg = vectorv(#re,j, u = a+b*re[j]; if (j<=r1, abs(u), norm(u)) ); mreg = concat(mreg, log(vreg)); m = concat(m, mv); areg = concat(areg, a+b*t); print1("(" res++ ": " a "," b ")"); } clareg(pol, plim=19, lima=50, extra=5)= { my(coreg,lireg,r1,ind,fa,co,a,b,mh,ms,mhs,mregh); nf=nfinit(pol); pol=nf.pol; re = nf.roots; r1=nf.sign[1]; if (nf.index > 1, /* power basis <==> index = 1 */ error("sorry, the case 'index>1' is not implemented") ); printf("discriminant = %s, signature = %s\n", nf.disc, nf.sign); lireg = sum(i=1,2, nf.sign[i]); /* r1 + r2 */ ind=vector(plim); v=[]; forprime(p=2,plim, my (w = factormod(pol,p)); my (e = w[,2]); my (find = 0); for(l=1,#e, fa = lift(w[l,1]); if (poldegree(fa) == 1, if (!find, find=1; ind[p]=#v+1); v = concat(v, [[p,-polcoeff(fa,0),e[l]]]) ) ) ); co = #v+extra; res=0; print("need ", co, " relations"); areg=[]~; mreg = m = [;]; a=1; b=1; f(0,1, nf,v,ind); while (reslima, b++; a=1) ); print(" "); mh=mathnf(m); ms=matsize(mh); if (ms[1]!=ms[2], print("not enough relations for class group: matrix size = ",ms); return ); mhs = matsnf(mh,4); clh = prod(i=1,#mhs, mhs[i]); printf("class number = %s, class group = %s\n", clh, mhs); areg=Mat(areg); km=matkerint(m); mregh=mreg*km; if (lireg==1, R = 1 , coreg = #mregh; if (coreg < lireg-1, print("not enough relations for regulator: matsize = ", matsize(mregh)); R = "(not given)"; , mreg1 = mregh[1 .. lireg-1, ]; R = 0; for(j=lireg-1,coreg, a = matdet(mreg1[, j-lireg+2 .. j]); R = rgcd(a,R) ) ) ); print("regulator = " R); } check(lim=200) = { my(r1,r2,pol,z,Res,fa); [r1,r2] = nf.sign; pol = nf.pol; z = 2^r1 * (2*Pi)^r2 / sqrt(abs(nf.disc)) / nfrootsof1(nf)[1]; Res = 1.; \\ Res (Zeta_K,s=1) ~ z * h * R forprime (q=2,lim, fa = factormod(pol,q,1)[,1]; Res *= (q-1)/q / prod(i=1, #fa, 1 - q^(-fa[i])) ); z * clh * R / Res; } fu() = vector(#km, k, factorback(concat(areg, km[,k]))); pari-2.17.2/examples/rho.gp0000644000175000017500000000144111636712103014122 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.17.2/examples/minigp.c0000644000175000017500000000311414676526175014453 0ustar billbill#include #include #include #include #include jmp_buf env; int gp_is_interactive(void) { return pari_infile == stdin; } void gp_err_recover(long numerr) { longjmp(env, numerr); } void gp_quit(long exitcode) { exit(exitcode); } entree functions_gp[]={ {"quit",0,(void*)gp_quit,11,"vD0,L,","quit({status = 0}): quit, return to the system with exit status 'status'."}, {NULL,0,NULL,0,NULL,NULL}}; int main(int argc, char **argv) { pari_init(8000000,500000); pari_add_module(functions_gp); cb_pari_err_recover = gp_err_recover; cb_pari_is_interactive = gp_is_interactive; cb_pari_quit = gp_quit; sd_colors("lightbg",d_INITRC); gp_load_gprc(); pari_print_version(); (void)setjmp(env); while(1) { GEN z; pari_timer T, Tw; long time, rtime; const char *prompt = gp_format_prompt(GP_DATA->prompt); char *in = readline(prompt); if (!in) break; if (!*in) continue; add_history(in); gp_echo_and_log(prompt,in); timer_start(&T); walltimer_start(&Tw); z = gp_read_str(in); time = timer_delay(&T); rtime = walltimer_delay(&Tw); pari_add_hist(z, time, rtime); if (z != gnil && in[strlen(in)-1] != ';') gp_display_hist(pari_nb_hist()); if (GP_DATA->chrono && time) { if (pari_mt_nbthreads==1) pari_printf("time = %s.\n", gp_format_time(time)); else pari_printf("cpu time = %s, real time = %s.\n", gp_format_time(time), gp_format_time(rtime)); } free(in); set_avma(pari_mainstack->top); } return 0; } pari-2.17.2/examples/contfrac.gp0000644000175000017500000000036714567450071015150 0ustar billbillperiod(D) = { my(u,v,j,r,s); if (type(D) != "t_INT" || D < 2, return(-1)); u = sqrtint(D, &v); \\ 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.17.2/examples/bench.gp0000644000175000017500000000022214557721030014411 0ustar billbill{ u=v=p=q=1; for (k=1, 2000, [u,v] = [v,u+v]; p *= v; q = lcm(q,v); if (k%50 == 0, print(k, " ", log(p)/log(q)) ) ) } pari-2.17.2/examples/pari.f900000644000175000017500000000602114676526175014277 0ustar billbill! Example program that shows how to create FORTRAN binding for PARI module PARI use ISO_C_BINDING, only : C_LONG, C_DOUBLE, C_PTR interface subroutine pari_init(parisize, maxprime) bind(C,name='pari_init') import C_LONG integer(kind=C_LONG), VALUE :: parisize integer(kind=C_LONG), VALUE :: maxprime end subroutine pari_init ! subroutine pari_close() bind(C,name='pari_close') end subroutine pari_close ! subroutine set_avma( av ) bind(C,name='set_avma') import C_LONG integer(kind=C_LONG), VALUE :: av end subroutine set_avma ! integer(kind=C_LONG) function get_avma( ) bind(C,name='get_avma') import C_LONG end function get_avma ! type(C_PTR) function dbltor( r ) bind(C,name='dbltor') import C_DOUBLE, C_PTR real(kind=C_DOUBLE), VALUE :: r end function dbltor ! real(kind=C_DOUBLE) function rtodbl( x ) bind(C,name='rtodbl') import C_DOUBLE, C_PTR type(C_PTR), VALUE :: x end function rtodbl ! type(C_PTR) function gsqr( x ) bind(C,name='gsqr') import C_PTR type(C_PTR), VALUE :: x end function gsqr ! type(C_PTR) function gmul( x , y) bind(C,name='gmul') import C_PTR type(C_PTR), VALUE :: x type(C_PTR), VALUE :: y end function gmul ! type(C_PTR) function gprec( x , d) bind(C,name='gprec') import C_PTR, C_LONG type(C_PTR), VALUE :: x integer(kind=C_LONG), VALUE :: d end function gprec ! type(C_PTR) function gmod( x , y) bind(C,name='gmod') import C_PTR type(C_PTR), VALUE :: x type(C_PTR), VALUE :: y end function gmod ! type(C_PTR) function glog( x , prec) bind(C,name='glog') import C_PTR, C_LONG type(C_PTR), VALUE :: x integer(kind=C_LONG), VALUE :: prec end function glog ! type(C_PTR) function stoi(x) bind(C,name='stoi') import C_PTR, C_LONG integer(kind=C_LONG), VALUE :: x end function stoi ! integer(kind=C_LONG) function itos(x) bind(C,name='itos') import C_PTR, C_LONG type(C_PTR), VALUE :: x end function itos ! type(C_PTR) function Pi2n(x, prec) bind(C,name='Pi2n') import C_PTR, C_LONG integer(kind=C_LONG), VALUE :: x integer(kind=C_LONG), VALUE :: prec end function Pi2n type(C_PTR) function gerepilecopy(av, z) bind(C,name='gerepilecopy') import C_PTR, C_LONG integer(kind=C_LONG), VALUE :: av type(C_PTR), VALUE :: z end function gerepilecopy end interface end module PARI ! PROGRAM prog use PARI implicit none real(kind=C_DOUBLE) :: r type(C_PTR) :: p integer(kind=C_LONG) :: i integer(kind=C_LONG) :: av integer(kind=C_LONG) :: prec = 18*64 ! 18 words CALL pari_init(10000000_8,2_8) av = get_avma() do i=1_8,10_8 p = glog(stoi(i*1000),prec) p = gmod(p, Pi2n(1_8, prec)) r = rtodbl(p) PRINT '(a,i10,a,f0.9)','log(',i*1000,')%(2*Pi) = ', r CALL set_avma(av) enddo CALL pari_close() END PROGRAM prog pari-2.17.2/examples/squfof.gp0000644000175000017500000000204614567450071014650 0ustar billbill\\ return one non-trivial divisor of n > 1 using Shanks's SQUFOF squfof(n) = { my (p, D, d, a, b, b1, f, g, l, bb, gs); if (isprime(n) || issquare(n, &n), return(n)); p = factor(n,0)[1,1]; if (p != n, return(p)); if (n%4==1, D = n; d = sqrtint(D); b = (((d-1)\2) << 1) + 1 , D = n << 2; d = sqrtint(D); b = (d\2) << 1 ); f = Qfb(1, b, (b^2-D)>>2); l = sqrtint(d); q = []; lq = 0; i = 0; while (1, i++; f = qfbred(f, 1, d); a = component(f, 1); if (!(i%2) && issquare(a, &as), my(j = 1); while (j<=lq, if (as == q[j], break); j++ ); if (j > lq, break) ); if (abs(a) <= l, q = concat(q, abs(a)); print(q); lq++; ) ); print("i = ", i); print(f); bb = component(f, 2); gs = gcd([as, bb, D]); if (gs > 1, return (gs)); f = Qfb(as, -bb, as*component(f,3)); g = qfbred(f, 1, d); b = component(g, 2); until (b1 == b, b1 = b; g = qfbred(g, 1, d); b = component(g, 2); ); a = abs(component(g, 1)); if (a % 2, a, a>>1); } pari-2.17.2/CHANGES-2.100000644000175000017500000011257614567450071012562 0ustar billbillBug numbers refer to the BTS at http://pari.math.u-bordeaux.fr/Bugs/ Done for version 2.11.0 (released 18/07/2018): Fixed 1- uninitialized memory reads in lgcdii and red_montgomery BA 2- memory leaks on pari_close [s_dbginfo, s_frame, colormap/graphcolor] BA 3- disallow generic operations that end up producing t_POLMOD modulo 0 e.g. matker( [Mod(1,2); Mod(1,2*x)] ) 4- Fp_powu(a,n,N) incorrect when a not reduced mod N BA 5- Flm_adjoint: treat rectangular matrices correctly Done for version 2.10.1 (released 04/07/2018): Fixed 1- t_LIST corrupted on writebin / read [#2040] BA 2- nfisincl() result uses wrong variable [#2041] 3- polcompositum(,1) when one polynomial has degree 1 [#2045] 4- Mod(0,3)*x + O(x^2) -> O(x^2) [instead of same] AP 5- alginit(nf, hasse inv.) sometimes wrong degree or stack overflow 6- factor(x/y) -> error 7- factor(y/x) -> x^-1 [ instead of y^1 * x^-1 ] 8- factor(x^2 + O(2^2)) -> x^2 [ instead of (x+O(2^2))^1 * (x+O(2^2))^1 ] 9- mfeigenbasis(mfinit(71,1,71)) -> error [ full space in wt 1 ] 10- make galoissubcyclo compatible with znstar(,1) 11- idealfactor(nfinit(polcyclo(5)),2^4*[0,1,0,0]~,100) => SEGV 12- idealredmodpower(nf,x,...) incorrect when x a t_INT or t_FRAC 13- znchargauss(,,a != 1): wrong value (missing \bar{chi}(a)) 14- factorpadic(): wrong results when p-adic accuracy too low 15- elleisnum([1,I/2^100],4) -> exponent overflow 16- galoischartable: wrong results 17- factor(N, lim) was using primes <= lim instead of < lim as documented 18- bnrinit(,m,1) could return generators not coprime to m (when 2 || Nm) 19- genus2red(3*(4*x^6+6*x^5+3*x^4+8*x^3+9*x^2-3),3) -> bug in litredp [#2053] 20- missing type check in mfsymbol [ mfsymbol(mf,'f) -> SEGV ] 21- incorrect values in ellzeta() [#2060] 22- ((y^-3+O(y))*x+1)/x -> oo loop [#2063] 23- mfslashexpansion: use Neururer-Brunault's theorem 24- iferr(sqrt(x+1/y),E,E) -> SEGV [ typo in err_DOMAIN exception ] 25- t_LIST corrupted on writebin / read [#2040] 26- prevent diviiexact from creating invalid t_INT on bad input [#2064] 27- Mod(*, constant polynomial) created invalid t_POLMODs 28- rnfalgtobasis could create invalid t_POLMODs 29- mftobasis(mf,f) could raise an exception when f was defined at a larger level than its conductor 30- incorrect values in ellsigma() [#2061] 31- incorrect values for bnrL1 at large accuracy [#1877] Changed 1- polcoeff is deprecated and renamed polcoef: it now only applies to scalars, polynomials, series and rational functions; no longer to vector/matrices or quadratic forms (use [] or "component"). 2- [libpari] rename polcoeff0 -> polcoef, polcoeff_i -> polcoef_i, truecoeff -> truecoef 3- add optional argument to denominator/content/numerator to allow better control over semantic. E.g. No arg: denominator([1/2, 1/x, 1/y]) -> 2*y*x denominator([1/2, 1/x, x/y]) -> 2*x denominator([x/2, 1/x, 1/y]) -> y*x With arg: denominator(,1) is 2 in all 3 cases denominator(,x) is x in all 3 cases denominator(,y) is y in all 3 cases 4- factor(t_RFRAC): sort factors by increasing degree 5- [libpari] rename constant LOG2 -> M_LN2 (from math.h if available) 6- ellweilcurve: allow input in ellisomat form 7- [libpari] rnf_get_nfzk / nf_nfzk / nfeltup interface (czknf was useless, return and use nfzk) 8- the rnf struct from rnfinit has changed, the new format is not compatible with pari-2.9 9- improved eta(x^k) 10- sinc(t_SER) more accurate 11- in prettymatrix format, no longer print all 0 x n matrices as [;]: use [;] iff n = 0 and matrix(0,n) otherwise 12- bnrdisclist returned t_MATs whose columns were t_VECSMALL 13- mateigen(m): fall back to qfjacobi when m close to symmetric [#2059] Added 1- [libpari] denom_i, numer_i, conj_i BA 2- [libpari] Fp_pow_init, Flxq_pow_init, F2xq_pow_init Fp_pow_table, Flxq_pow_table, F2xq_pow_table gen_pow_init, gen_pow_table 3- new GP function serchop 4- [libpari] serchop_i BA 5- [libpari] hash_init_GEN, hash_haskey_long, hash_insert_long BA 6- [libpari] FpX_ddf_degree, FpXQX_ddf_degree, FlxqX_ddf_degree 7- [libpari] checkell_i 8- new GP function ellisotree 9- mspolygon: add graphical representations (LaTeX form) 10- [libpari] idealprodval, rnfdisc_factored 11- [libpari] eta_ZXn, eta_product_ZXn BA 12- New GP functions galoisgetgroup, galoisgetname 13- [libpari] cxtoreal, cxEk 14- [libpari] gmin_shallow, gmax_shallow Done for version 2.10.0 (released 15/05/2018): Fixed 1- subst(1+x^3+O(x^6),x,x+O(x^4)) -> SEGV [#1865] BA 2- lfunartin was using too much stack BA 3- fflog in char 3 or 5 was slower than intended 4- RgX_blocks only worked for t_INT or t_POL coeffs 5- spurious bnrdlisclist entries (with negative number of real places...) when modulus not a conductor BA 6- modular algorithms could fail for very large input BA 7- [mingw] writebin did not work BA 8- forprime(N=2^100,oo,...) did not work 9- mseval(W,s,p) did not check 'p' in weight 2 10- matrixqz(m, -1 or -2) was very slow 11- ZG_normalize destroyed its input 12- [install] prototype code D0,U, did not work BA 13- use of complex default function argument could lead to stack error. 14- factorpadic(2*x^4+x^2,2,2) -> division by 0 [#1876] 15- incgam(110, I) very inaccurate BA 16- ellinit over number field was not compatible with generic operations. BA 17- [breakloop] dbg_up could confuse the breakloop. HC 18- sumnummonieninit(,,a) + sumnummonien(n = a, ...) with a > 1 gave wrong result 19- sumnummonieninit([a,b], t_CLOSURE) => incorrect initialization 20- lngamma(1+epsilon) much slower than in pari-2.7; eg. 10^-4 at \p200 BA 21- lfun(...,t_SER,n>=1) returned a wrong result 22- lfun(,, negative derivation order) => internal bug 23- SEGV in sumnummonieninit when accuracy too low BA 24- ellidentify: check curve is over Q 25- gdivgs(t_RFRAC,s) could create invalid objects 26- chareval(G,chi,x,[[...], o]) didn't work (off-by-1) 27- polsturm(x^2-1,[-1,1]) -> SEGV [#1884] 28- typo in description of "call" symbolic operator [ _(_) ] PB 29- matinverseimage could find spurious solutions [#1888] 30- ellsea could leak variables (=> "no more variables" error) 31- ellsea leaked clones 32- 1/x - 1/x returned gen_0 (instead of Pol(0)) 33- printf("%d",factor(2*3*5*7)) => SEGV 34- lfuninit: incorrect guess for root number depending on init domain E = ellinit([0,-a,1,157*a-27,-90*a-543], nfinit(a^2-a+1)); lfuninit(E,[0,20,10])[2][6] -> 1 (whereas rootno is -1) 35- bnrinit(bnf,idealfactor(bnf,1)) -> SEGV [#1890] BA 36- lfuncreate([1,0,[0],1,1,1,1]) -> SEGV (invalid input) 37- thue(imaginary quadratic of disc -3f^2, n) could return half-integers BA 38- [libpari] Z_ZV_mod caused gerepile error 39- bestappr(1+0.*I) -> 1 + 0*I instead of 1 40- memory corruption in qfminim [#1894] 41- polylog(x) used realprecision accuracy instead of precision(x) [#1895] 42- exp or log(I*1.0) used realprecision accuracy instead of precision(x) [#1896] PB 43- M = ffgen(2017^3)*[0, 1; 0, 0]; M^-1 -> SEGV [#1887] BA 44- lfun(lfungenus2(...),...) was much slower than intended BA 45- nfsubfields(polcyclo(88), 20) -> wrong result [#1892] BA 46- [mpi] dynamically linking with libpari did not work 47- sin(1 + 1.0*I) used realprecision accuracy instead of precision(x); same for cos, tan, arg, expm1, sinc. 48- make idealstar(,N) an actual shortcut for ideal(nfinit(x), N) [#1900]; it is recommended to use znstar instead. HIL 49- polclass could access invalid memory 50- K=bnfinit(x^2+2323); P=idealprimedec(K,23)[1]; bnfisprincipal(K,P); \\ oo loop 51- nfvalrem() overflowed in case of negative valuation 52- ellminimalmodel over number field fails with impossible inverse [#1899] 53- incorrect GC in nfgcd [#1903] 54- missing GC in rnfisabelian 55- derivnum(x = a, ...) allowed t_POL a but not t_RFRAC 56- missing GC in vectorsmall BA 57- missing GC in idealramgroups BA 58- ellweilpairing failed for supersingular curves in char. 2 [#1910] BA 59- Mat()[1..0,1..0] -> SEGV PB 60- galoissubcyclo(1,1,fl) ignored fl [#1914] 61- PostScript plot: fix font scaling EB 62- GP was incorrectly issuing fflush(NULL) [#1913] 63- issquare(Mod(1,67)*x^4+Mod(14,67)*x^2+Mod(49,67)) -> SEGV [#1915] 64- polroots(t_POL whose coeffs vary by a factor > 2^100000) -> SEGV (or stack overflow) 65- nfisincl(nf1, nf2) didn't work [#1921] 66- setting sopath in gprc then calling install() -> SEGV [#1922] 67- nfislocalpower did not accept a bnf in place of a nf 68- subst(t_SER, x, 0 t_POL) [#1925], e.g subst(x+O(x^2),x,0*x) -> 1 + O(x) [ instead of 0 ] subst(x+O(x^2),x,Mod(0,3)*x) -> O(x^0) [ instead of Mod(0,3) ] 69- valuation(Mod(0,3)*x,x) -> 0 [ instead of oo ] 70- factor(x^2 * (1+O(5^2))) -> domain error 71- for T in Q_p[X], factor (round then compute multiplicity) and issquarefree (assume input is separable) did not agree. Now, factor() repeats irreducible factors according to apparent multiplicity (note that the multiplicity is not well defined for inexact inputs, which are close to being inseparable, i.e. v_p( disc(T) ) is large compared to the input accuracy). On the other hand, factorpadic with exact input is able to compute multiplicities reliably. 72- Vecsmall(t_STR with extended (8-bit) ASCII) -> platform dependent + can't be converted back with Strchr 73- x^y: loss of accuracy when y >> 1 and x exact BA 74- [pthread] do not use pthread when nbthreads=1 75- sumdiv(arg. in factored form, k < 0) => error or wrong result 76- Mod(0,1)^0 -> invalid t_INTMOD 77- gamma and lngamma inaccurate near negative integers, e.g. gamma(-1+10^-16) BA 78- nfisisom, nfisincl and factor were still using factornf PB 79- nfinit(t_POL of deg 1, 3) => incorrect change of variable 80- subst(t_SER, x, x+O(x^N)) was slow [ e.g. ellj(x+O(x^10000)) ] BA 81- setrand(2);polclass(-5032,27) -> wrong result 82- polredabs(non-monic t_POL, 1) => potentially wrong transformation map 83- if 'a < 'b < 'c, charpoly(Mod(a, a^2 + Mod(b,b^2+1)), c) => 1 [ now error: the result can't be repreѕented as a t_POL in 'c, only as a t_POLMOD modulo b^2 whose coefficients are t_POL in 'c ] 84- mathouseholder: missing sanity checks (SEGV, didn't accept t_COL) 85- bestapprPade did not handle positive valuation correctly [#1945] PB 86- subst(Mod(1/z, y), z, x) -> wrong answer [#1949] 87- subst(1+x^2+O(x^3),x,y) -> 1 + y^2 + O(y^4) [#1950] BA 88- [pthread] thread stacks could silently overflow XR 89- padicfields(3,6) -> FPE [#1947] 90- nfislocalpower could compute ZV_pval(0 vector,) -> oo loop [#1955] BA 91- iferr(1/0,E,1,break()) -> SEGV 92- missing roots in nfroots (when r2>0) [#1956,#1957] BA 93- factormod(...,p,1) was incorrect for large p BA 94- foo = vectorsmall(1);for(i=1,1, foo[1]); -> error [#1958] BA 95- v=Vecsmall([2]); Fl_neg(v[1],3) when Fl_neg is installed [#1958] 96- fincke_pohst with stockmax = -1 and non-zero CHECK (infinite capacity + selection criterion) could lose some vectors Affected polredabs [#1963] 97- ellwp(,,1) returned \wp'/2 instead of \wp' 98- inaccuracy in ellL1 / ellanalyticrank (usually last digit) 99- nffactor factors could be non-monic [#1967] 100- bestapprPade(,explicit B): wrong result [#1946] 101- bestappr(Mod(10,307), 40) -> 10 (instead of 3/31) 102- mathnf([x;1]) -> SEGV [#1971] BA 103- ispower((x^3+ffgen([2^127-1,3])*x+1)^2,2,&r);r was wrong [#1976] 104- factorpadic(3*x+O(2^5),2,5) -> division by 0 [#1982] 105- vecmax(Vecsmall()) -> some random value [#1983] 106- SEGV in install() when bad prototype supplied [#1977] 107- ellzeta(., real number) possibly wrong result [#1981] BA 108- sqrtn(Mod(9, 101), -2) -> wrong result 109- multiplying t_SER with t_INTMOD entries (mod a composite) whose leading term cancels -> SEGV [#1986] 110- lambertw(t_SER) could create invalid t_FRACs 111- matintersect did not always return a basis 112- nfinit([T, listP]) could error out when a small prime outside listP divided the index [#1993] 113- lfuntheta(1,1e50) -> overflow 114- nfrootsof1 could return a t_POL (always return \pm 1 or a t_COL) 115- oo-loop in msfromell [#1906] 116- memory leak due to cgetg_block / gunclone_deep usage 117- memory leak in ellminimalmodel when e memoized periods/roots components BA 118- [win32] plot colors were shifted by 1 119- RgX_translate(P,c) with c equal to \pm 1 (e.g. as t_REAL or t_PADIC) incorrectly replaced c by its t_INT approximation [#1995] BA 120- matsupplement(Mod(matrix(5,1),2)) --> SEGV [#1996] 121- PostScript engine: missing 'stroke' in plotbox method => some commands (e.g. colors) could be ignored 122- sqrtnint(a,k) very inefficient for huge k [and huge a] 123- powuu(0,1) -> SEGV 124- mathnfmodid([;], t_VEC) did not correspond to specifications (always returned [;]) 125- matsolvemod([;],2,[]~) -> no solution [ instead of []~ ] 126- a[1]=vector(10):a[1][1]=b;a[1]=vector(10); could leak memory [#1999] 127- lcm(Pol(0),0) -> division by 0 128- QX_complex_roots(a*x^n,) => SEGV BA 129- default(strictargs,1); my(a=2);(f(b,c)=123);f(1) => SEGV [#2004] 130- factor(0.*x + 1) -> SEGV [#2005] 131- sinh(x close to 0) -> loss of accuracy 132- sinc(0.*I) -> division by 0 133- wrong result in bnfinit due to loss of accuracy and unsufficient heuristics to detect it [#2007]. {setrand(2);p=x^8-1661000*x^6+967427199776*x^4-230628391373468096*x^2 +19278898978723566612544;bnfinit(p).cyc} => [60,2,2,2,2,2,2,2,2,2] instead of [6,2] 134- nffactor(y^8-y^6+y^4-y^2+1,x^4-1) -> concatenation error [#2009] 135- vecsort / vecsearch: comparison function was required to assume integral values; allow t_INT, t_FRAC or t_REAL 136- mathess was very unstable, and so was charpoly(,,2) [#2010] 137- memory corruption in nffactor [#2013] BA 138- partitions(1,[0,5],[3,4]) -> incorrect result 139- quadclassunit(-699,,[6,6]) -> SEGV [#2015] 140- intnum would lose accuracy when using more control points, e.g. intnum(x=0,1,x*cos(Pi*x), 2) at \p100 [#2014] 141- polcoeff(t_SER) -> incorrect types and values polcoeff(1/(1+x+y+O(y^2)+O(x^2)), 1,y) -> 2*x-1 [now -1+2*x+O(x^2)] polcoeff(y+O(y^2), 0, x) -> 0 [now y+O(y^2)] 142- ellperiods([1,0.1 + I/10^50]) -> division by 0 143- nfmodpr(nfinit(x),[],[]~) -> SEGV [#2020] 144- nfisisom(nfinit(x^2+4),x^2+1) -> reverse isomorphism [#2022] 145- forbid ellinit(E/Qp, prime != p or 1.0) 146- elllocalred(non integral E/nf,p) -> wrong result 147- ellorder(E/Q, P with t_FFELT entries) not accepted [ t_INTMOD was ] 148- missing GC in lfuntheta 149- implementation of newblock was incompatible with getheap(). Now we always include the 'block' size in the header. 150- gamma(0.0+1/2*x+O(x^2)) -> domain error in factorial 151- affrr(0.0, x) did not reset the exponent correctly: use min(expo(0.0), bit_accuracy(lg(x))) 152- matkerint could be exponentially slow; guarantee polynomial time (drawback: slows down some classes of matrices) [#2034] 153- ellminimaltwist did not check that E is defined over Q 154- padicappr('x,Mod(0,'t^2+1)+O(7^10)) -> SEGV [#2036] 155- allow \r "foo bar" (quotes around file names are optional for \l,\r, \w; they allow filenames with spaces) [#2035] 156- memory leak in polclass() AP 157- fix integrality condition in algsubalg/algquotient/algcentralproj 158- factorpadic gave wrong results at low accuracy Added 1- [libari] ZM_isidentity 2- [libpari] rename buchnarrow -> bnfnarrow 3- [libpari] ZX_radical BA 4- [gmp] support for mpn_divexact_1 BA 5- parallel fflog in characteristic at most 5 BA 6- parallel znlog for large characteristic 7- [libpari] u_chinese_coprime BA 8- new GP function elltamagawa 9- [libpari] RgX_rescale_to_int, RgM_rescale_to_int BA 10- [libpari] Flx_digits/FlxV_Flx_fromdigits 11- new argument (multiple derivation) in GP function derivnum 12- allow matrix(n) for n x n matrices 13- new GP functions nfeltsign, nfeltembed, nfpolsturm HC 14- new GP functions sumnumap, sumnumapinit (Abel-Plana summation) HC 15- new GP functions zetamultall, zetamultconvert 16- allow t_VECSMALL for vecsort [already there but undocumented] and vecsearch [already there but prevented by a typo] CG 17- new GP function matpermanent [#1860] 18- [libpari] hammingl, RgM_is_QM, vecsmall_prod, zm_permanent, ZM_permanent 19- lfuncreate: no longer assume Ramanujan-Petersson, allow specifying an arbitrary growth rate a_n = O(n^(k_1 + eps)) BA 20- new GP function vecprod 21- new GP function znchar VD 22- new GP functions forperm, forsubset PB 23- [libpari] F2xqM_F2xqC_gauss F2xqM_F2xqC_invimage F2xqM_gauss F2xqM_invimage FlxqM_FlxqC_invimage FlxqM_invimage FqM_FqC_invimage FqM_invimage gen_matcolinvimage gen_matinvimage FFM_FFC_invimage FFM_FFC_gauss FFM_gauss FFM_invimage 24- new GP function polrootsbound HC 25- new GP functions prodeulerrat, sumeulerrat, sumnumrat, prodnumrat HC 26- new GP function zetahurwitz 27- [libpari] sqrtnr_abs 28- binomial(x,k): allow omitting k [ => vecbinomial ] VD 29- [libpari] forperm_init, forperm_next, forperm, forallsubset_init, forallsubset_next, forksubset_init, forksubset_next, forsubset 30- [libpari] lindep_bit BA 31- new GP function ellbsd 32- new GP function poldiscfactors 33- [libpari] FpX_gcd_check 34- [libpari] str_init, str_printf, str_putc, str_puts 35- new GP function printp [ used to exist with a slightly different meaning: pretty format vs prettymatrix ] 36- new GP function sumnumlagrange, sumnulagrangeinit 37- [libpari] int2um1 (for 2^n - 1) 38- Fl_powu: special purpose code when base is 2 39- [libpari] vecpowuu, vecpowug 40- [libpari] zerovec_block 41- [libpari] Z_ZV_mod_tree 42- [libpari] vecvecsmall_max, vecsmall_to_vec_inplace 43- new GP function zetamultinit BA 44- new GP functions permorder, permsign BA 45- new GP function galoisconjclasses AP 46- new GP functions galoischartable, alggroupcenter, algmakeintegral 47- [libpari] Flxn_inv 48- new GP function chargalois 49- [libpari] expose znstar internal interface: znstar_get_N, znstar_get_conreycyc, znstar_get_conreygen, znstar_get_faN, znstar_get_no, znstar_get_pe, znstar_get_Ui, checkznstar_i 50- [libpari] coreu_fact, moebiusu_fact 51- [libpari] ZabM_ker, ZabM_indexrank, ZabM_inv, ZabM_pseudoinv, BA 52- [libpari] stack_malloc_align PB 53- [libpari] FFM_deplin, FFM_indexrank, FFM_suppl F2xqM_deplin, F2xqM_indexrank, F2xqM_suppl FlxqM_deplin, FlxqM_indexrank, FlxqM_suppl FqM_indexrank JD 54- [plot] SVG support 55- [libpari] upper_to_cx, cxredsl2, cxredsl2_i 56- new GP function charpow 57- [libpari] ZM_pseudoinv 58- [libpari] ulogintall, ulogint, umuluu_or_0, QXQV_to_FpM, ZM_ZX_mul, RgM_RgX_mul 59- new GP function ellminimaldisc 60- [libpari] rfracrecip_to_ser_absolute, RgV_to_ser 61- new GP function znchardecompose, zncharconductor, znchartoprimitive PB 62- [libpari] perm_sign PB 63- [libpari] FlxC_neg FlxC_sub FlxM_neg FlxM_sub FlxqC_Flxq_mul FlxqM_Flxq_mul zero_FlxC zero_FlxM PB 64- asymptotically fast linear algebra using CUP decomposition 65- [libpari] nf_get_zkden, nf_get_zkprimpart 66- [libpari] idealprimedec_galois, idealprimedec_degrees 67- [libpari] idealaddtoone_raw, ZM_hnfmodprime, pr_hnf BA 68- new GP functions hyperellratpoints and ellratpoints based on Michael Stoll ratpoints code. 69- [libpari] Z_pollardbrent, Z_ECM 70- [libpari] RgX_mulhigh_i 71- GP function znchargauss 72- Configure --graphic=svg 73- GP function divisorslenstra (divisors in residue classes) 74- [libpari] lg_increase, vecfactoru, vecfactoru_i, vecfactoroddu, vecfactoroddu_i, vecfactorsquarefreeu BA 75- ellheight for curves over number fields 76- new GP function forfactored 77- [libpari] ZV_sort_inplace BA 78- ellrootno for curves over number fields 79- optional flag to 'divisors' (add factorization) 80- GP functions fordivfactored BA 81- [libpari] ZXQM_mul, ZXQM_sqr, QXQM_mul, QXQM_sqr 82- [libpari] ZX_z_unscale 83- [libpari] Flxn_mul BA 84- [libpari] FlxqX_is_squarefree, FlxqX_nbfact, RgX_to_FlxqX 85- [libpari] RgX_addmulXn, RgX_addmulXn_shallow, RgX_addspec, RgX_addspec_shallow BA 86- GP functions galoischardet, galoischarpoly 87- [libpari] mulcxpowIs BA 88- [libpari] function RgXn_sqrt KB+HC89- new package 'mf' for modular forms; new GP functions getcache lfunmf mfDelta mfEH mfEk mfTheta mfatkin mfatkineigenvalues mfatkininit mfbasis mfbd mfbracket mfcoef mfcoefs mfconductor mfcosets mfcuspisregular mfcusps mfcuspval mfcuspwidth mfderiv mfderivE2 mfdescribe mfdim mfdiv mfeigenbasis mfeigensearch mfeisenstein mfembed mfeval mffields mffromell mffrometaquo mffromlfun mffromqf mfgaloistype mfhecke mfheckemat mfinit mfisCM mfisequal mfkohnenbasis mfkohnenbijection mfkohneneigenbasis mflinear mfmanin mfmul mfnumcusps mfparams mfperiodpol mfperiodpolbasis mfpetersson mfpow mfsearch mfshift mfshimura mfslashexpansion mfspace mfsplit mfsturm mfsymbol mfsymboleval mftaylor mftobasis mftocoset mftonew mftraceform mftwist 90- [libpari] ZV_cba, Z_cba_extend 91- [libpari] RgV_is_ZVpos, RgV_is_ZVnon0 JA 92- GP functions primecert, primecertexport, primecertisvalid (ECPP). 93- [libpari] ncharvecexpo 94- [libpari] rootsof1q_cx, rootsof1powinit, rootsof1pow BA 95- [libpari] RgX_digits 96- [libpari] Q_content_safe BA 97- ellisomat: support for curve over finite field without CM 98- GP function: bestapprnf 99- [libpari] vec_prepend, lindepfull_bit BA 100- [libpari] QX_mul/QX_sqr/QX_ZX_rem, FFX_mul/FFX_sqr/FFX_rem, RgX_mul_i/RgX_sqr_i, ZXQX_mul/ZXQX_sqr BA 101- [libpari] Rg_type, RgX_type2, RgX_type3, RgM_type, RgM_type2, RgM_RgC_type BA 102- RgX_mul/RgX_sqr: support for coefficient ring detection BA 103- [libpari] FlxqXQ_auttrace BA 104- [libpari] F2xX_F2x_add, FlxX_Flx_sub, FqX_Fq_sub BA 105- [libpari] F2x_get_red, get_F2x_mod, get_F2x_var, get_F2x_degree, F2xqX_get_red, get_F2xqX_mod, get_F2xqX_var, get_F2xqX_degree 106- [libpari] vecmoduu, quadclassno, mkfracss, sstoQ, Qtoss 107- [libpari] znchar_quad VD 108- [libpari] closure_func_err BA 109- [libpari] F2xqX_extgcd, F2xqXQ_inv, F2xqXQ_invsafe, FFXQ_inv BA 110- [libpari] ZV_nv_mod_tree, ZM_nv_mod_tree, ZXC_nv_mod_tree, ZXM_nv_mod_tree BA 111- [libpari] FF_gen, FF_map, FFX_preimage, FF_Frobenius BA 112- New GP functions ffembed, ffmap, ffinvmap, ffcompomap, ffextend, fffrobenius 113- [libpari] cx_approx_equal BA 114- [libpari] F2xqX_ispower, FlxqX_ispower, FpXQX_ispower, FFX_ispower, FpX_ispower, FqX_to_mod, FqM_to_mod, RgC_to_FqC, RgM_to_FqM, QXQC_to_mod_shallow, QXQM_to_mod_shallow BA 115- [libpari] ZC_Q_mul, ZM_Q_mul, ZX_Q_mul, QM_mul, QM_det, QM_ker BA 116- [libpari] Fl_log, Fl_log_pre, Fl_sqrtn, Fl_sqrtn_pre BA 117- [libpari] Flc_Flv_mul, Flm_adjoint, Flm_powers 118- New GP function exponent() BA 119- [libpari] ZXM_init_CRT, ZXM_incremental_CRT 120- [libpari] numdivu, numdivu_fact, gexpo_safe BA 121- [libpari] FpXC_center, FpXM_center BA 122- [libpari] nxV_chinese_center, nxCV_chinese_center, nxMV_chinese_center AP 123- New GP functions matdetmod, matimagemod, matinvmod, matkermod BA 124- [libpari] Z_content 125- [libpari] checkMF, checkMF_i, checkmf_i, inv_content BA 126- [libpari] F2xqXQ_inv, F2xqXQ_invsafe, F2xqX_invBarrett, Flc_Flv_mul coprimes_zv 127- New GP functions msdim, mslattice, mspetersson, mspolygon, ellweilcurve, ellpadicbsd, ellpadicregulator BA 128- New GP function lfuntwist 129- [libpari] mkmat22, mkmat22s, Qp_agm2_sequence, Qp_ascending_Landen, Qp_descending_Landen BA 130- [libpari] famat_pows_shallow, famat_mulpows_shallow 131- [libpari] QXQ_div_ratlift, ZM_equal0, QM_ImZ_hnfall, QM_ImQ_hnfall BA 132- [libpari] ZXn_mul, ZXn_sqr, FpXn_mul, FpXn_sqr, RgXn_recip_shallow, FpXn_exp, FpX_Newton, FpX_fromNewton, FpX_Laplace, FpX_invLaplace BA 133- [libpari] FpX_integ, FpX_convol 134- allow zeta(power series) 135- New GP function laurentseries LGr 136- default(echo): new value echo = 2 [ print as is, incl. whitespace ] LGr 137- allow power series as limits for intnum() 138- [libpari] uordinal BA 139- [libpari] QM_gauss, QM_rank, QM_indexrank, QM_QC_mul LGr 140- make TESTS="a b c" test-all to test only 'a' 'b' and 'c', e.g. 'lfun', 'gamma' and 'lfuntype' (same for statest-all and dyntest-all) 141- allow quaddisc(integer factorization matrix) 142- New GP function forsquarefree 143- allow matsolve(m,b) when m is only left-invertible BA 144- [libpari] QXQ_mul, QXQ_sqr, FFXQ_mul, FFXQ_sqr 145- New GP function idealispower BA 146- New GP function idealredmodpower 147- 'ms' modular symbol package: support N = 1 as well 148- allow mssplit(M), splits msnew(M) by default BA 149- [libpari] FpXQXn_mul, FpXQXn_sqr, FqXn_mul, FqXn_sqr 150- New GP functions plothexport, plothrawexport, plotexport 151- plotcolor(w, col) now allows color names (t_STR) or [R,G,B] values 152- allow a t_STR composed of # + 6 hex digits for colour names 153- isprime(,3): use ECPP 154- new GP function log1p [#1829] BA 155- qfisom: allow to give the automorphism group of the second lattice 156- optional argument to idealfactor [limit factorization] 157- [libpari] idealHNF_Z_factor_i, idealfactor_limit, famat_div_shallow, Q_factor, Q_factor_limit, vecsquarefreeu, gprec_wensure 158- vecsort / vecsearch: allow sort/search wrt to a "key" (closure with arity 1) 159- [libpari] forprimestep_init 160- allow forstep(a,b, Mod(c,q), ...) 161- new GP function forprimestep 162- [libpari] RgX_sylvestermatrix 163- [libpari] Rg_to_Fq, Fp_invgen BA 164- [libpari] F2xqX_factor_squarefree, FlxqX_factor_squarefree, FpXQX_factor_squarefree, FqX_factor_squarefree, FFX_factor_squarefree BA 165- [libpari] FpXX_integ, FpXX_halve, FqX_halve, FpXQXn_exp, FqXn_exp, FqX_integ 166- new file Ser.c BA 167- [libpari] FpXn_inv, FpXQXn_inv, FqXn_inv BA 168- New file GP interface: fileclose fileextern fileflush fileopen fileread filereadstr filewrite filewrite1 BA 169- [libpari] Flx_ddf, F2x_ddf, FpX_ddf, F2xqX_ddf, FlxqX_ddf, FpXQX_ddf, FqX_ddf, FFX_ddf F2xqX_degfact, FlxqX_degfact, FpXQX_degfact, FqX_degfact, FFX_degfact 170- new GP functions factormodSQF, factormodDDF 171- [libpari] umuluu_le, ugcdiu, ugcdui, ulcm 172- [libpari] Fp_center_i, FpX_center_i 173- [libpari] hclassno6, hclassno6u BA 174- New GP function lfunsympow BA 175- nfsplitting: support for reducible polynomials AP 176- new GP functions alglatadd, alglatcontains, alglatelement, alglathnf, alglatindex, alglatinter, alglatlefttransporter, alglatmul, alglatrighttransporter, alglatsubset AP 177- new GP function algsplit Changed 1- rewrite bnfnarrow 2- the bid struct from idealstar has been changed, the new format is not compatible with pari-2.9 3- bnrdisclist output is now an ordinary vector (not a vector of vectors) 4- made nfsign() / nfsign_arch() reliable [ use algebraic method besides floating point approximation to real embeddings ] 5- support ??refcard-ell (or mf/nf/lfun) 6- [libpari internals] bnrinit(,,1) [with generators] is no longer necessary for bnrsurjection() 7- bnrinit(,,1) is no longer necessary for bnrL1, bnrconductor, bnrrootnumber, bnrstark, rnfkummer, galoissubcyclo 8- msfromell: use a (much faster) modular algorithm, allow a vector of isogenous curves 9- mseval(W,s,p): allow 2x2 matrix for the path 'p' argument 10- allow mseval(W, t_MAT, p) to evaluate many symbols simultaneously 11- allow polrootsreal() and polsturm() with non-rational real polynomials (input is rounded first) BA 12- FlxX_shift did not support negative (left) shift. BA 13- [libpari] rename FpX_fromdigits -> FpXV_FpX_fromdigits, FpXQX_fromdigits -> FpXQXV_FpXQX_fromdigits 14- made lngamma(t_COMPLEX) faster 15- made sumnummonieninit(,1) faster HC 16- sumnummonieninit(a) for [a,a] did not conform to documentation. Change to sumnummonieninit(b) for [1,b] 17- improve prime() and primepi() by adding more checkpoints [#1878] 18- lfun(Dirichlet character): switch automatically to lfunchiquad (Kronecker) if char has order <= 2 19- nfchecksigns: replace by rigorous algorithm 20- asympnum: better tunings => usually finds more terms 21- extended help: make ?? op work for ALL operators (=> GP operators@2) 22- idealstar(,N) : always include generators, for all values of flag [ this is cheap, allowing not to compute it doesn't make much sense; and G.gen is now always defined. ] 23- let ellsea call the generic algorithm when q <= 523 to avoid an oo-loop 24- sqrtnr algorithm (Newton iteration instead of exp(log(x)/n) BA 25- quadgen/quadunit: allow to specify the variable name instead of w. 26- [libpari] rename vecbinome -> vecbinomial 27- [libpari] rename padic_lindep -> lindep_padic, Xadic_lindep -> lindep_Xadic 28- x^(t_FRAC) use sqrtnr if possible BA 29- keri replaced by ZM_ker (use modular algorithm) 30- lfuncreate() change of format for (p,d)->Lp closure: - Lp here and in bad primes [p,Lp] must now use the actual local factor and not its inverse - d is now the exact number of terms needed (was 1 less), i.e. one need only return Lp + O(x^d) - bad primes are given as a separate 2nd component: [Lp, [[p1,L1],...[pk,Lk]]], not as [Lp, [p1,L1],...[pk,Lk]] 31- faster nfgaloismatrix / nfgaloisapply(nf,s, ideal) 32- nf struct: nf[7] now stores nf.zk / content(nf.zk). Old format is still supported (to read in data involving old-style nf generated by gp version < 2.10) but incurs a small speed penalty. JD 33- move plotport.c to libpari 34- default window size for hi-res plots using --graphic=X 35- component(t_POL T, n) used to return polcoeff(T, n-1) for all n >= 1 [ undocumented compatibility behaviour, deprecated since the introduction of polcoeff ], and raised an exception for n <= 0. Now returns a true GEN component whenever it exists and raises an exception when it does not [ n <= 0 or n > polcoeff(T)+1 ]. BA 36- Fl_addmul_pre: change arguments order to follow Fp_addmul convention 37- issquarefree / isfundamental with integer argument: allow factored form 38- change polred-type algorithm to return 'x' (no longer 'x-1') for the field of rational numbers (make it consistent with polredabs) BA 39- ellisomat(E,{fl}) is now ellisomat(E,{p},{fl}) (p degree of isogenies) 40- the definition used in polred / polredbest / polredabs to decide what is the "best" polynomial to return 41- removed resultant_all, use RgX_resultant_all 42- polresultant: no longer compute the content of arguments (potentially very expensive for a generically small gain) 43- support Q(i) in Q_denom / Q_remove_denom BA 44-[libpari] rename {FpXQXQ,FlxqXQ,F2xqXQ}V_aut{sum,trace,pow} to {FpXQXQ,FlxqXQ,F2xqXQ}_aut{sum,trace,pow} BA 45-[libpari] FpXQXQ_auttrace now identical to FpXQ_auttrace BA 46-[libpari] RgX_type now only handles polynomials. 47-log: change threshold between Taylor / AGM when x close to a power of 2 [#1934] 48-[libpari] ZM_inv and QM_inv interface 49- K.tu[2]: make it a t_INT if possible, else a t_POLMOD 50- removed warning "Mod(a,b)^n with n >> b : wasteful" 51- ellpadicmatrix now returns a pair of matrices (instead of a matrix whose entries are pairs of values) 52- ellpadicheight and ellpadicmatrix no longer accept [p,[a,b]] arguments; use * [a,b]~ 53- ellpadics2: allow curves with multiplicative reduction 54- E/Qp now allowed in ellcard, ellap, ellgroup, ellissupersingular, ellpadicfrobenius, ellpadics2, ellintegralmodel, elllocalred 55- E/Qp convert coefficient to exact form using centered residues 56- msissymbol now returns a GEN (gen_0/gen_1) instead of a long, allow t_MAT arguments and return a vector of 0/1 in this case. 57- allow mseval(M, t_MAT) 58- change 'debugmem' default value to 1; no memory-related message at value 0 (not recommended under gp). BA 59- V=galoisfixedfield(,,2): return V[1] in the same variable as the coeffs of V[3] instead of P. 60- numtoperm now returns a t_VECSMALL (so that results can be multiplied as permutations, etc.), no longer a ZV 61- improve Fp_sqrt for p = 5 (mod 8) [Atkin's formula] 62- improved matrixqz(,‐1 or -2) by using matkermod 63- The functions psdraw, psploth and psplothraw and the default psfile are obsolete. Use one of plotexport, plothexport or plothrawexport with format "ps" and write the result to file. AP 64- new implementation of matsolvemod; old matsolvemod0 is deprecated 65- plotcolor(w,c) now returns the [R,G,B] value attached to c 66- allow plotdraw(w) for plotdraw([w,0,0]) 67- allow isprime(n) to use ECPP 68- isprime(n,1) no longer outputs a certificate, use primecert(n) 69- isprime(n,1) no longer uses APRCL for large prime divisors of n-1 (pure Pocklington-Lehmer-Selfridge); use primecert(n). 70- getrand() encoded results in a way that depended on 32bit/64bit arch 71- thue(p, rhs) is much easier when p has no real roots; don't insist on computing bnfinit(p) in this case [#2003] 72- use Newton in expm1 73- change rnfpolredabs so that it outputs a canonical polynomial. As a result, the function is no longer Obsolete. 74- allow polrecip(scalar x) -> x 75- extend factormod(f, D) for general finite fields: D = p prime [over Fp], D = [T,p] (over Fp[x]/(T)), or omited [over field of definition of f]. Same for polrootsmod. 76- factorff and polrootsff are now obsolete. Use factormod/polrootsmod 77- Ser(s, 'x, d) now always return a series with d significant terms. It used to return a t_SER s in 'x verbatim and to use all given coefficients for a t_VEC/t_COL. Only if d is explicitly given, no change for Ser(s,'x) 78- elllocalred, ellap, ellcard, ellissupersingular, ellgroup(,0): allow models which are not p-integral 79- ellgroup: allow E over number field 80- factorback([;]) is now invalid [ [;] is not the empty factorization, factor(1) = matrix(0,2) is ] 81- cmpiu / cmpiu, equaliu / equalui : no longer assume that t_INT argument is non-negative 82- rename diviu_rem -> absdiviu_rem, udiviu_rem -> uabsdiviu_rem, udivui_rem -> uabsdivui_rem 83- allow E.omega, E.eta, E.area for E over number field 84- ellpointtoz for E over number field AP 85- algnorm, algtrace and algcharpoly now have an optional flag to get the absolute version over an alginit algebra AP 86- renamed algsplittingmatrix -> algtomatrix AP 87- algleftmultable now always returns the multiplication table on the integral basis AP 88- merge algdecomposition + algsimpledec -> algsimpledec AP 89- algpoleval: new syntax for matrix argument algpoleval(al,pol,[x,mx]) BA 90- ellmoddegree: return only the modular degree, do not depend on current precision. 91- polsturm: allow non-squarefree polynomials (count distinct roots) AP 92- merge algdim + algdim -> algdim(,{abs=0}) AP 93- merge algleftmultable + algtomatrix -> algtomatrix(,{abs=0}) Removed 1- file 'MACHINES' (no longer maintained) 2- useless argument nf in ZC_nfval, ZC_nfvalrem, pr_equal, ZC_prdvd 3- useless flag argument in polrootsmod 4- [libpari] useless function Flx_roots_naive; rootmod and rootmod2 are now an alias for polrootsmod (both have been deprecated for years) rootmod0 is just as obsolete. pari-2.17.2/CHANGES-2.20000644000175000017500000064100111636712103012460 0ustar billbill# $Id$ Bug numbers refer to the BTS at http://pari.math.u-bordeaux.fr/Bugs/ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.3.0 (released 19/05/2006): Fixed 1- ispower(HUGE t_INT, n) could give wrong results (rounding errors) 2- ellheightoo (internal) and RgXQ_norm (public) not declared BA 3- [m68k kernel] didn't compile + need -fPIC 4- libpari.so: soname was incorrect %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.13 (released 26/04/2006): Fixed BA 1-[HPUX] 'program' bench failed for gp-sta [install did not work] 2- made BITS_IN_LONG and related constants 'signed long' [ avoid problems like : exp(10^10) --> 10^10 + 1 (silent overflow) ] 3- --kernel=none : libpari ended up not containing the 'divll' symbol 4- polgalois(x^3-2) --> [,,,"A3"] when new_galois_format was unset. 5- problem with negative valuations in ggcd(t_PADIC) [#411] 6- Fp_pow for huge moduli could return a negative number [#417] 7- y;x/y/z/x --> error [#410] 8- polredabs(x^4-35048*x^2+1016392*x-7368842) --> same, instead of x^4 - 17524*x^2 + 69403802. Rounding error, due to setting the relative precision wrt the wrong reference object. 9- nfisideal() could raise an error instead of returning 0 10- nfreducemodpr only accepted nf's (not bnf's or richer) 11- 1/a/x --> 1/a/x; 1/(a*x) --> 1/(a*x). Now 1/(a*x) in both cases (unify t_RFRAC normalization routines) 12- content(1.*a*x) --> 1 [ now returns a ] 13- content(1./a*x) --> 1.00000/a, but content(1./a*x + 1./a) --> 1/a [ now returns 1/a ] 14- t_SER ^ t_FRAC introduced floating point numbers even when rational expression available, e.g (8 + x)^(1/3) 15- round(t_POL/t_SER, &e) with leading coeff rounded to zero 16- trace(Mod(y,x)) --> SEGV 17- gcd(1, 1/x) --> 1 [ gcd(Pol(1),1/x) correctly returns 1/x ] content(x/y + 1) --> 1 [ content(x/y) correctly returns 1/y ] content(x + 1/y) --> 1 [ also wrong in pari-2.1.7 ] content(1/x/y) --> 1 [ should be 1/y ] 18- missing vectors in qfminim(x,b,,2) [ m omitted ] 19- 'make test-kernel' [ wouldn't compile ] 20- matsnf(matrix with t_POL entries, 1) ---> incorrect matrix V 21- O((-2)^3) --> invalid object 22- (0.*x)*(0.*x) --> 0.E-57 [ instead of 0.E-57*x^2 ] 23- qfminim(x,,m,2) [b omitted] -> [n,B,v]: output correct vectors (v), but reported too many (n too large). 24- qfminim(x,,,2) wrong when x has huge entries. Work out a sensible default precision if x has exact entries. BA 25- HPPA 32bit level0 inline assembly addmul constraint was too weak. 26- factorback(x,y) --> error if x,y were valid t_VEC with exactly 6 components [ typo in checknf_i ] 27- [configure] shared libraries on 64bit sparc require -fPIC / -KPIC 28- (x^3/y^3)^(1/3) -> x + O(x^17) [ leading coeff sometimes lost #433 ] 29- ??INT worked, but not ??t_INT 30- inconsistencies wrt variables in t_POLMOD, e.g Mod(x*a,x^2)' ---> Mod(x, x^2) deriv(Mod(x*a,x^2)) ---> 0 31- contfrac(sqrt(19),2^31-1) --> overflow [ signed overflow can't be reliably tested, use unsigned computations ] BA 32- on x86_64 + gcc-4.0, CFLAGS was missing a -fno-gcse-after-reload 33- [output=3] give more time to external prettyprinter [#209] 34- rare SEGV in factor(t_INT) with low stack space [ #345 ] 35- ispower(1) --> error, ispower(-8) --> error [ allow negative numbers ] 36- Configure -a + kernel = $arch-gmp didn't work [missing -lgmp #438] 37- divisors([]) --> SEGV [#441] 38- missing GC in bernfrac 39- bnrrootnumber(bnrinit(bnfinit(x),1),[]) --> SEGV [#443] 40- f()= local(m = matrix(2,2)); m[1,1] = 1 f() --> m[1,2] also set to 1 41- make test-kernel would always fail with gmp kernel. 42- elllseries(e, 0.) --> error [ only elllseries(e,0) worked ] [#445] 43- 'ftime' was never detected by Configure 44- setrand(74);quadclassunit(-83138791008,,[0.2,6]) --> oo loop [ large prime relation hashtable corrupted when changing subfactorbase ] 45- a(k)=if(k==0,0,a(k)=a(k-1)) a(1) --> SEGV [#447] (add refcounts to 'user function' structs) 46- getheap() did not report properly the "size" of user functions (value too small) 47- add compatibility macro decomp -> Z_factor [ used by mwrank ] BA 48- minpoly(,,v) might return polynomials in x instead of v. 49- make test-kernel required inlining compiler 50- make test-kernel didn't work with C++ compilers 51- ia64 kernel assumed 64bit longs, whereas compilers can be configured for 32bit Changed 1- RgX_simple_gcd: make sure result has non-zero leading term [#412] 2- simplify(t_RFRAC): remove assumption that deg(denom) > 0 [#413] 3- split bfffo.h from level0.h 4- semantic of t_SER with inexact coefficients is now the same as for t_POL: the sign is 0 iff all coefficients are zero. Either there are no coefficients, or the leading coefficient is an inexact zero. 5- removed all non-inline assembler kernels : they were complicated to Configure, mostly untested, and inefficient ( function call overhead + must use global variable hiremainder/overlow when operating on limbs instead of LOCAL_HIREMAINDER trick ). If this slows down your application (it should not), install gcc or use the gmp kernel. 6- allow arbitrary n in divisors(n) and fordiv(n,), provided factor(n) succeeds [ was restricted to t_INT or their factorization matrix ] 7- made LLL the default algorithm in algdep / lindep again [ replaces PSLQ ] Our PSLQ implementation is slow and unstable, and LLL performs much better, see the example in ??algdep. 8- addrr: extend accuracy much less frequently 9- make sure all kernel symbols are present in all versions of libpari (addll & friends could be inline) 10- change the meaning of gcd(x) and lcm(x) when x has vector/matrix components (a global recursive gcd/lcm is taken, instead of a cartesian product of individual gcd/lcm) 11- disallow vecmin([]), vecmax([]) [ returning stoi(+/- BIGINT) is not helpful ] 12- [libpari] renamed lellseries -> elllseries [ as in GP ] 13- semantics of stackdummy() [ make it consistent with gerepile ] 14- never assume that part of an object is "permanent" when it is out of the stack (was used by INTMOD/POLMOD/PADIC). Always copy it. As a result, 'gmodulo' and 'forcecopy' become obsolete. 15- use quadclassunit in qfbhclassno for large D, thereby ASSUMING GRH. 16- ellan was bypassing the check for CM 17- uniformize the generation of parilvl0.h [ genkernel ] Added 1- [library] new function isinexact. BA 2- [elldata] function forell() to loop over elliptic curves. BA 3- [elldata] function ellconvertname() to parse curve name. 4- [library] new function RgX_shift, RgX_mulXn, RgX_shift_shallow, RgX_Rg_div BA 5- m68k level0 inline assembly kernel 6- [library] new function isint, issmall, mkrfrac 7- Configure --time=timing_fun 8- [Configure] genkernel script Removed 1- kernel functions shiftl / shiftlr (inefficient, unused, untested) [ backward compatibility version in src/kernel/level1.h ] 2- obsolete functions forcecopy (use gcopy) and gmodulcp (use gmodulo). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.12 (released 24/01/2006): Fixed 1- incorrect detection of EditLine library 2- issquare(Mod(2,9)) --> 1 [ should be 0 ]. Implicitly assumed v_p(N) odd for all primes divising the modulus N. BA 3- poltschirnhaus(ffinit(2,4)) could return 0. BA 4- Configure -a did not propose fltk and Qt as graphic engine. 5- g()=local(x;f) -- oo-loop [#352] 6- charpoly( Mod(a, b) ) --> wrong result when 'a' is not a t_POL or t_INT. 7- \p2051 log(exp(-1)) --> printing bug [#357] 8- bad argument checks in qfrep() / qfminim() [#359] 9- fix mkintn to work as documented (even when leading word is 0) BA 10- [Linux] gp only accepts one SIGINT in batch mode [#251, #370] (initial patch JD). 11- contfrac(5/3.) was wrong: [1,2] instead of [1,1,2]. For a t_REAL x, when the last partial quotients of a lower and upper bound differ by 1, choose the one associated to the digits of x (followed by infinitely many 0s) unless it was too small and the next partial quotient was 1. [#371] 12- bnfisintnorm: results could have a wrong sign [#372] 13- isprime(N,2): oo loop if N is a perfect square 14- \p n was limited to a value ~ 10 times smaller than the actual limit BA 15- qfbsolve fix 2.2.11-F86 was not sufficient. 16- (1 + O(2))^2 was less precise than sqr(1+O(2)) 17- in the extended help pager, typing ' ' then \n would skip one page [#375] BA 18- config/has_stat.c didn't work with g++ 19- charpoly/minpol(Mod(a,T)) was only monic if T was. BA 20- 'make install' did not work if 'prefix' contained spaces 21- has_dlopen always compiled in on Mac OS X, even if present in libc 22- unsafe handling of t_QFI/t_QFR (setsigne) [#384] 23- idealaddtoone didn't handle zero ideals [#386] 24- workaround a bug in g++ version 3.4.1 (Mandrakelinux 10.1 3.4.1-4mdk) infinite loop on factor(41093858855767145965571) 25- constlog2() was not restartable [ no way to set glog2 = NULL ] 26- sloppy arg check in ellchangecurve [#388] 27- [internal] gprec_w reduced the accuracy of real 0s [#396] 28- wrong arg check in matsolve [#400] 29- minpoly([;]) --> SEGV 30- y*x^3/( 1+x+x^2 +O(y)) -> gerepile error [#403] 31- poldivrem didn't handle properly multivariate polynomials [#402] 32- insufficient accuracy in ellheight --> singular curve, SEGV [#404] 33- [MacOS X + fltk] installed gp binary couldn't use hi-res graphics (resource fork not copied) IZ 34- [2.2.9-A20] -fno-strict-aliasing not supported in older gcc 35- heapsize reported by getheap() were wrong (overestimate). 36- gerepile error in nfgaloisapply [#408] 37- wrong results in bessel functions at non-integer indices (typo in isint(t_REAL) ) [#409] 38- vector(3,n,n*=10) -> [10, 100, 1000] ( now [10, 20, 30] ) 39- bnf.codiff didn't work 40- content([[2]]) --> error Changed 1- speed up prime() by using checkpoints. 2- allow lists with vector entries in listsort (use lexsort) 3- allow vector of points in ellisoncurve() 4- tunings in quadclassunit (#298 / #355) 5- [Configure:] take CPPFLAGS into account 6- 'int' C type is now reserved for -1/0/1 values. Use 'long' otherwise. 7- Fl_inv and Fl_div now raise an error when divisor not invertible [ used to return 0 ] 8- removed the threshold that prevented exponent overflow in exp(-10^10) and returnd 0. instead [ either return correct digits or raise an exception ]. VL 9- honor C_INCLUDE_PATH in Configure (for get_readline) 10- [readline] remove old hack bypassing a bug in readline-2.0 [ did not release SIGINT ]: useless nowadays, and used deprecated functions. 11- export combine_factors [ needed by giac ] 12- do not alias labs to abs in paricom.h 13- randomize polredabs() to improve bound on difficult fields, e.g. f(k) = { p = polcompositum(x^6-3*k^3,x^6-3*k^3)[4]; polredabs(poltschirnhaus(poltschirnhaus(p)),16) } for k = 2, 5, 6, 8, ... 14- try more names in 'pari_unique_filename' (26^2 instead of 26)) 15- remove GCC_INLINE from CFLAGS. Define DISABLE_INLINE or DISABLE_VOLATILE to prevent the compiler from inlining or using the 'volatile' keyword 16- let paripriv.h include parinf.h 17- rename 'prec' -> 'precreal' [ from paripriv.h ] BA 18- define INLINE to 'inline static' for C++ compilers also 19- rename polx -> pol_x, polun -> pol_1 20- make hell, hell2 static to elliptic.c 21- rename decomp -> Z_factor, decomp_limit -> Z_factor_limit 22- rename wf -> weberf, wf1 -> weberf1, wf2 -> weberf2 23- make incpos / incneg static 24- export setseriesprecision, setrealprecision BA 25- make pari restartable 26- [initialization of GP hashtables] remove the 'module' structure, simplify pari_addfunctions, plug helpmessages in initializing entree arrays. 27- rename err -> pari_err, pariputsf -> pariprintf 28- rename rnfhermitebasis -> rnfhnfbasis 29- forbid t_STR, t_VECSMALL and t_LIST in gvar. 30- cleanup mpqs use of temporary files 31- pari_unique_filename now MT-safe, returns a malloc'ed buffer. 32- default() now always returns the value of the (possibly changed) default. No need for a flag anymore. The construction default(def,,1) is still valid but deprecated (the flag is ignored). 33- increase default accuracy in ellinit() when curve has large coefficients [ avoid large relative error on periods, #404 ] 34- qfminim(,,,0) often gives wrong results for matrices with large entries. Test whether rounding errors occur and abort if so [#407] 35- qfminim(x,b,m,flag): b and m are now optional. Allow omitting b (formerly b=0) if flag = 2 also. 36- eval("1a") is now '1' again (was "a" since 2.2.10) Removed BA 1- gnuplot graphic engine (complicated, did not work from gnuplot-4 on) 2- has_sigrelse.c & has_sigsetmask.c [ deprecated, unused after C-10 ] 3- src/desc/Makefile 4- log2old ( = 2atanh(1/3) ) 5- src/desc/gen_help BA 6- obsolete macros INIT_JMP/INIT_SIG Added 1- library function ellisoncurve() BA 2- library functions related to sorting: gen_sort_aux, gen_search_aux, vecsmall_indexsort 3- functions strtoi, strtor BA 4- function minpoly() 5- function zeromatcopy() BA 6- support for GNU/kFreeBSD and other GNU userlands. 7- document ZY_ZXY_rnfequation and ZY_ZXY_resultant 8- function pari_warn() use instead of pari_err() for warnings 9- function pari_add_function, pari_add_module 10- doc/develop.tex 11- library function uisprime, uissquarerem, Z_issquare, Z_issquarerem 12- library function pari_unique_dir 13- library function gp_default 14- library function rowcopy (GP2C) 15- library function traverseheap %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.11 (released 19/10/2005): Fixed 1- a()=b(1,) --> error message 2- agm(-1.0000000004656,1) --> oo loop [Bug #214] 3- sdivss_rem(x,y,&rem) did not set rem, contrary to the documentation BA 4- ellzeta(ellinit([0,0,0,0,1]),1) --> gerepile error 5- random() was less random on 64 bit machines 6- typing 0.e-28 returned 0.E-38 (!) 7- ellminimalmodel(e).a2 was not always in {-1,0,1} 8- check arguments in elllocalred BA 9- [GP2C] type-checking codes generated for some types was wrong. 10- stray output: (a()= for(i=1,1, return);) a() --> 0 11- qfminim & qfrep didn't check their arguments 12- [library:] pariputsf() and GP print() used different output formats 13- nfdisc(x^4 - 2947*x^2 + 1553545) --> SEGV [ incorrect test for gcd in Round 4: gcmp1(d) --> degpol(d) == 0 ] 14- forvec(v=vector(4,k,[1,4]),,2) -> oo loop [bad initialization] 15- eta(x << 1) used far too much accuracy in intermediate computations GN 16- MPQS warning "factoring this number will take several/many hours" now assume more current hardware. 17- off-by-1 error in initprimes0 allocation [Bug #237] -> SEGV in default(primelimit,155100 + 41*7) 18-[Cygwin] incorrect links created by 'make install' 19- a( --> oo loop in parser [Bug #240] 20- at \p366, the last digits of Pi were wrong [ not enough iterations, from 2.2.9, A-2]. [Bug #238] GTo21- wrong prototype for qfrep 22- factornf(P, T) did not accept non-monic T [Bug #241] 23- lngamma(1E+10) --> "Impossible assignment I --> S" 24- "couldn't deal with this field" errors in bnfinit/quadclassunit for tiny discriminants, huge Bach constants (e.g. 12), and unlucky random seeds. Remove arbitrary limits and let the loop run to completion. 25- neither freadseq() nor readGEN() were able to parse '{' / '}' [Bug #216] 26- accuracy problem in polroots (--> division by zero) [Bug #252] 27- acos(x < 0) --> result off by Pi [ introduced in 2.2.9-A3 ] 28- ellrootno(e,p) incorrect in the case of good reduction [#262] 29- (rare) "impossible assignment I-->I" in contfrac 30- typo in qfbclassno's hash function (when D < 0, function can't handle 0). qfbclassno(-948) --> division by 0 [GMP kernel] 31- [Makefiles:] the behaviour of '//' as path leader is undefined. Make sure path prefixes are not '/' [ e.g $prefix/lib --> //lib ] 32- pollead(u*v + (v+1)/v, v) --> 'x' [ should raise an error ] GN 33- problems in MPQS : some factors missed e.g factor(2^263-9) --> expensive extra runs ( + possible stack corruptions when many factors found simultaneously ). 34- tanh(x) was actually computing tanh(|x|) for real x ([#269] from 2.2.8) 35- [MacOS X] dlopen is now part of the system library. Don't redefine dlopen in darwin.c if HAS_DLOPEN is defined. 36- fix Trager's trick in factorff (from 2.2.10) 37- rnfisnorminit(quadpoly(145,y),quadray(145,1)) --> stack overflow [#273] 38- matker([1,2,3;4,5,6]*1.) --> [;] (missing 1 vector) 39- rnfconductor(bnfinit(y),x,1) --> error [#277] 40- gcc-4.0 miscompiles PARI on ix86 [#274] ( http://gcc.gnu.org/bugzilla/show_bug.cgi?id=23453 ) 41- truncate(1/4/x+1+O(x)) -> (x + 1/4)/x instead of (4*x + 1)/(4*x) [#276] 42- bitneg(2^32-1,32) -> corrupt integer [#279] 43- typo in rnf_is_abelian [#277] GN 44- several minor fixes in mpqs.c BA 45- ellrootno(e,2) was wrong for curves of Kodaira type 3 and -7. ([#212] from 2.2.9) BA 46- galoisfixedfield() was not robust enough ([#256, #228 from 2.2.9) 47- tanh(-10^20) --> error instead of -1 [tanh(10^20) was treated properly] BA 48- wrong rounding in wr_float: with default(format,"f0.10") 1.23456789049999999997 -> 1.234567891 GH 49- typo in thue.c:MiddleSols() --> missing solutions [#264] 50- default(prettyprinter,,1) --> t_POL instead of t_STR [#296] BA 51- truncate(1/x+O(x)) --> SEGV 52- overflow in Flm_gauss (when solving triangular system) --> wrong result [#284] 53- isprime(25, 2) *** impossible inverse modulo: Mod(5, 25). although it's useful to get a factor, it's not nice to raise an error, since 'trap' then becomes mandatory. Removed this feature: the factor is silently discarded (exceedingly rare anyway). 54- (-1)^(any integer >= 2^31) --> -1 [ from 2.2.9 ] GH 55- zncoppersmith(x,1002,1001) --> SEGV [#221] 56- subst(1+O(x),x,x^2+O(x^3)) --> SEGV [#287] (patch by MSo) subst(1+O(x^2),x, x^2+O(x^3)) --> 1 + O(x^3) [ should be O(x^4) ] 57- component() didn't work on lists [ SEGV ] 58- quadclassunit(D,, [c0 > 6]) --> weird error message 59- weird errors in bnrstark [#285] 60- (x^0)^2^31 --> length overflow 61- polroots(pollegendre(51),1) --> SEGV [#293] 62- print({}) --> oo loop BA 63- when choosing between (p-1) and APRCL, isprime() required a complete factorization of p-1, whereas accumuluting factors up to sqrt(p-1) was enough. (e.g 2^127 - 1) BA 64- function name not always properly reported on interrupt (e.g if, while) 65- content([-1]) --> -1 66- memory leaks in quadclassunit (#318) BA 67- [Configure] check that 'readline' is not an EditLine wrapper [ ==> compilation failure otherwise ] 68- Str() --> junk string (uninitialized data) (#326) 69- arg(I*O(7^5)+1) --> junk, exp(3*I + O(3^5)) --> junk. (#328) 70- powiu(2, ulong n) called int2n(long n), incorrect for huge n (#331) 71- Qfb(8,-4,1)*Qfb(5,-4,1) --> Floating Point Exception (BIB, #332) 72- t_QRF distance component was evaluated using an unstable algorithm, possibly leading to catastrophic cancellation (#333) 73- dbltor did not recognize Infinity, NaN, or unnormalized numbers. 74- makerfrac(1,quadgen(24)*x^0)%b --> SEGV, where GEN makerfrac(GEN p,GEN q) { GEN z=cgetg(3,t_RFRAC); z[1]=lcopy(p); z[2]=lcopy(q); return z; } BA 75- exp(x) gave imprecise results at huge accuracies for expo(x) >> 1. 76- valuation(x,p) using a divide & conquer algorithm would kill the session if p = 1 77- (2 + O(2^8))^(-1/3) --> SEGV [#341] 78- exp(0.E100) --> invalid GEN 79- stack corruption in gsubst [#343] 80- Pol([Mat(0.1)],x)^3. --> crash [#346] 81- besseljh(0,2^65) --> crash [#340] BA 82- [plotQt:] ^C while hi-res window is present would crash the session 83- Strtex(Vecsmall) --> SEGV [#348] 84- oo loop in zeta() [catastrophic cancellation in get_xinf() ] 85- oo loop in nfdisc() [#350] 86- Mod(1,2)*x / (1/2) --> incorrect t_POL 87- qfbsolve forgot some solutions: qfbsolve(Qfb(2,1,3),3) --> 0 88- multiplying ideals could lead to factoring big integers (failsafe algorithm in idealtwoelt, when random trials don't work): fix idealtwoelt. Changed BA 1- FpM_FpV_mul is renamed to FpM_FpC_mul, Flm_Flv_mul to Flm_Flc_mul and FlxV_to_ZXC to FlxC_to_ZXC, Flv_to_ZC to Flc_to_ZC, FqV_to_FlxC to FqC_to_FlxC, zv_to_ZC to zc_to_ZC BA 2- FpXV_FpV_innerprod renamed to FpXV_FpC_mul and FlxV_Flv_innerprod to FlxV_Flc_mul 3- retain 'CHANGES' revision after 'make distrib' GN 4- extensive re-tuning in MPQS (all sizes) and avoid "sizing marginal, index1 too large" warning 5- rename globalreduction -> ellglobalred, localreduction -> elllocalred 6- taniyama(e) is deprecated. Use elltaniyama(e, prec) instead of old = precdl; precdl = prec; x = taniyama(e); precdl = old; 7- [bnfinit] retune compute_R to try and detect cheating with Bach's constant. 8- rename lisexpr -> readexp, lisseq -> readseq, flisexpr -> freadexpr, flisseq -> freadseq 9- rename Fp_gener -> gener_Fp, Fl_gener -> gener_Fl 10- change TeX output so that it's easier to handle: - replace \over by \frac [ most people use AMS styles which forbids \over, not plain TeX, which doesn't have \frac ] - remove many extra braces { } [ would prevent line breaks ] - insert carriage returns 11- [GP handling of print1()] get rid of 'added_newline' hack, replace by monitoring in pariputc/pariputs.[#243] 12- do not install libpari.a.xxx [ include files are not versionned either and libpari.a is useless without the correct ones, contrary to .so ] 13- rename gtrans_i -> shallowtrans, concatsp -> shallowconcat. 14- add GC in parsing loop for huge input vectors [ needs roughly 2 or 3 times less memory ] 15- implement pari_is_dir() using stat() instead of opendir() 16- moved defaults from gp/gp.c to language/default.c [ -> into libpari ] 17- moved input_loop to language/es.c [-> into libpari ] 18- when called as 'gp --test', disregard actual terminal dimensions 19- allow ellinit over any ring (support only basic operations) 20- allow ellchangecurve on e = [a1,a2,a3,a4,a6]. 21- typecast cleanup: move most of paricast.h to pariold.h 22- rename readGEN -> gp_read_stream, freadseq -> gp_read_str. freadexpr/readexpr are deprecated, use gp_read_str/readseq 23- make sure GP_DATA is always defined --> default() becomes available in libpari 24- make gnil public 25- change content() so that it always returns the gcd of all entries (as documented). Used to return the gcd of all _contents_ of the entries of a t_VEC/t_COL/t_MAT. 26- backport into quadclassunit some of the bnfinit improvements [specifically, change subfactorbase, #298] BA 27- rewrite rectdraw in an object-oriented way [ reduce code duplication in hi-res plot routines ] BA 28- change the semantic of includedir to not include the pari suffix. Instead /pari is automatically added by make install. 29- improve plindep (use lllintpartial and floating point LLL) + allow lindep with p-adic entries BA 30- allow relative paths in Configure --with-xxx directives BA 31- allow sinh, cosh, tanh with t_PADIC arguments XR 32- bnrstark(): try harder to find solutions [increase precision faster #255] BA 33- rename coefs_to_xxx() to mkxxxn() for xxx in {vec,col,pol,int}. 34- semantics of gcd with inexact zeros: now gcd(0., a) is 1 [used to be a and led to problems: e.g 0./(1.*a)/(1.*a) not simplified ] 35- warn if 'perl' is found but doesn't seem to work 36- forbid the f'(x) construction when x is not a constant type [#327] Added BA 1- polgalois(): 4th component: transitive group name following GAP4 BA 2- new functions ZX_add, ZX_sub, ZX_neg, ZX_Z_add, ZX_Z_mul BA 3- new functions FpC_to_mod, FqV_to_FlxV, FpC_red 4- member functions r1, r2 5- functions factoru(), factoru_pow(), powiu(), powuu(). 6- symbolic link $MANDIR/gp-$version.1 -> $MANDIR/gp.1 7- new functions shallowcopy, shallowconcat, shallowtrans, vecslice, vecpermute, vecslicepermute, rowslice, rowpermute, rowslicepermute BA 8- support for gp2c-run on cygwin BA 9- new optional package 'elldata' and new GP functions ellsearch and ellidentify to access it. BA 10- support for ellinit("") through elldata. 11- new functions vec_ei / col_ei BA 12- new function FpC_Fp_mul, FpV_FpC_mul BA 13- new functions const_col, const_vec, vec_is1to1, vec_isconst 14- new function gp_read_file BA 15- new function substvec BA 16- new divide_conquer_assoc (make divide_conquer_prod thread-safe) 17- p-adic zeta, cos, sin, tan, cotan BA 18- p-adic gamma BA 19- new routine readvec() %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.10 (released 17/04/2005): Fixed BA 1- gp2c description of == operator was broken. 2- asin(I) --> SEGV, acos(1 + 0. * I) --> SEGV, atan(I/2) --> SEGV sqrt(0*I),acosh(1+0*I) --> oo loop 3- make test-kernel didn't work [missing gen_m1 & int2n] 4- thetanullk(1/2,1) --> SEGV [from 2.2.9] 5- unit component in factor(t_INT + 0*I) was wrong 6- no typecheck for qfbhclassno input 7- diviuexact destroyed input and made further assumptions [=> wrong results in ellglobalred]. Replaced it by a clean wrapper. GH 8- thue(thueinit(x^3 - 2), 2) --> SEGV 9- reorder([1]) --> SEGV (bad input, but sanity check was wrong) 10- rnfconductor(,1) [ = rnf_is_abelian() ] didn't accept polynomials with POLMOD coeffs + used a wrong algorithm [ not modular + wrong result ] 11- broken code in hnfmodid() wrt GC (would add one 0 column, Bug #129) 12- sqrti(gen_0) --> SEGV [native kernel] BA 13- polrootsmod(,,1) could return a line vector instead of a column. 14- issquare(Pol(1)) --> SEGV BA 15- polsubcyclo() used too much memory for large conductors. 16- typo in quadtoc() --> quadgen(odd t_INT)*1. was wrong 17- subgrouplist([], [2]) --> [[;]] (instead of []) 18- typo in FqX_split [ (!degpol(x)) --> degpol(x) <= 0 ] -> very rare SEGV 19- after alias(a, b); kill(b), invoking 'a' would access corrupted data 20- round(-0.5) --> -1 [ should be 0, as was output by round(-0.5, &e) ] RS 21- gcc-3.4 breaks on compatibility code to support old readline versions [ pre-4.2 ]. Typecast parameters, not functions and dump (approximate) support for g++ + old readlines in gp_rl.c 22- \p 8000 E=ellinit([0,0,0,0,1296]); P=[-8,28]; ellpointtoz(E,P) --> oo loop 23- idealaddtoone(nfinit(y),[0]) --> SEGV [ BIB ] 24- aprcl would wrongly report composites [ introduced aprcl.c:1.48, before release-2-2-8 ] 25- ellchangecurve(e over Qp) --> e.w not updated 26- ellheight(e over Fp, pt) --> SEGV 27- issquare(Mat(2), &z); z --> SEGV [ don't allow matrices as input ] issquare(1/x^2) --> SEGV [ typo in polcarrecomplet ] 28- rnfkummer(over Q) --> type error. 29- allow qfbprimeform(d > 0, p < 0) 30- Since exp(-1e100) --> 0. [ tolerable: alternative being underflow error ], we shouldn't have exp(-1e100) --> truncation error. Fixed. 31- rnfkummer(bnrinit(bnfinit(y),nextprime(10^20),1),Mat(3)) --> module too large in Fp_shanks [ conductor() was computing unnecessarily tough discrete logs ] 32- [Configure:] add /lib64 and /usr/lib64 to library search path 33- SEGV in nfeltpowmodpr() for primes of degree 1 [see 2.2.7-F21] + inputs containing t_INTMODs yield unpredictable [wrong] results 34- znlog(x,g): first check whether x == g [ quite frequent ] 35- rnfisnorminit(nfinit(y^2+y+1), x^3-y,2) --> "incompatible variables" 36- nffactormod() returned a factorization which was not a proper t_MAT 37- rnfequation(y^2+1, x + Mod(z*y - 1, y^2+1)) --> SEGV [ BIB ] 38- many problems in matfrobenius for _inexact_ matrices LGr39- very rare SEGV in idealprimedec() [ typo in init_norm(), using FpX_red on a t_INT, which is no longer valid ] 40- [library:] precision() output "wrong" value for small non-zero t_REAL (depended on exponent, not the bit accuracy of the input). Change so that true bit accuracy is used unless input is 0 (then use exponent). 41- rare memory corruption in thue() [ SmallSols ] 42- gamma(z) for tiny z suffered from catastrophic cancellation 43- ??? sometimes output extra entries [ e.g. ???eigen output matfrobenius ] 44- bezout(0., 0.) --> division by 0 45- issquare(5, &n) --> SEGV 46- factor(x in Q[i] \ Z[i]) --> rubbish [ typo in factor_gauss() ] 47- ellrootno & elllseries didn't check their arguments 48- rnfisnorminit(non-monic polynomial) --> SEGV 49- prevent Ser & Pol from creating invalid objects (e.g Pol(x+y, y) -> y+y) 50- TODO item: polrootspadic(x^2+8*x+4, 2, 2) --> 2 + O(2^2), whereas there's no padic root. The documentation is not clear enough: should polrootspadic(x,p,r) find roots in Z/p^r [current behaviour], or use the precision of the supplied polynomial to compute roots in Qp, then return them at precision p^r [ better, polroots() and factorpadic() behave this way ] ? 51- padicappr(f, t_POLMOD) didn't work 52- rnfidealnormabs(rnfinit(nfinit(y),x^2+1),1) --> SEGV 53- no argument check in primepi() 54- ellminimalmodel(ellinit([1,2,3,4,5])) --> gerepile error 55- gcd([]) was 1 [ should be 0 ] + gcd([...]) used an inefficient algorithm 56- [readline] completion in extended help context ?? didn't include GP defaults 57- [from 2.2.9] nfsubfields(x) had become unable to exploit the trivial case when x is irreducible modulo some prime 58- [from 2.2.9] typo in krosi -> wrong result [ affected aprcl only ] 59- dirdiv([],[]) -> SEGV 60- using allocatemem() in files input with read() could corrupt stack allocatemem() does not end by a longjmp anymore; it is still impossible to use it in loops 61- typo in matrixqz: matrixqz(Mat([1,1]~)/2,0) --> "not a rational matrix" 62- [cf 2.2.7-F23-] use safer parameters in bernfrac(): bernfrac(166) was wrong. 63- [Bug #201] gp --test: line split mode initialized too late print(vector(1000)) would bypass it. 64- [Bug #200] gmul2n(t_POL, n) would not normalize the resulting polynomial [ needed in characteristic 2 for instance ]. 65- FpX_center and centermod didn't use the same normalizations. Fix FpX_center 66- factormod(T,p,1): output was not sorted BA 67- [from 2.2.9] -fPIC missing for gp2c-run on platforms that require it. 68- if(1,print,print(no)) --> no was printed [a function expecting any number of string objects, called without parentheses (no args), would read the following arguments as its own ] 69- more stringent tests in ideal* functions: don't accept t_COL with incorrect length as ideals ([]~ produced SEGV in many cases) 70- factorback([1,1; 0,1],nfinit(x^3+2)) --> SEGV 71- [Bug #156] kbessel was unstably evaluated ? besselk(1,120) %1 = 448600744132608.0000000000000 72- hyperu and kbessel(,1) inaccurate. E.g: hyperu(1,1,1) at \p28 -> last 3 digits wrong Added 1- routines equalsi/equalis, equaliu/equalui, cmpui/cmpiu 2- exported FFTinit() / FFT() wrappers to rootpol.c:fft() [not under GP yet] 3- routines Rg_to_Fl, Rg_to_Fp, RgX_to_FpX, RgX_to_FpXQX, RgX_to_FqX, RgV_to_FpV, RgXQ_mul, RgXQ_sqr, RgX_div_by_X_x, FpX_div_by_X_x, RgXV_unscale 4- file Qfb.c [ stuff related to binary quad. forms moved out of arith1.c ] 5- routines truedivii, truedvmdis, truedivis BA 6- [GMP] faster divri routine. BA 7- support for real forms for qfbsolve. 8- routines RgX_gcd_simple, RgX_extgcd_simple [ when no coeff explosion in base field ] BA 9- new algorithm for exp(t_REAL) [ Newton ] 10- new macro ndec2prec() 11- use Trager's trick in factorff() 12- member function .bid (from a bnr). Extend mod, clgp, no, cyc, gen to bid and bnr structure. 13- new keywords for ?? : bid, CFT, ideal, idele, modulus, rnf. 14- new construction %#: number of history entries so far PC 15- an optional 2nd argument to znorder() to limit the search space Changed 1- renamed gegal --> gequal, gegalgs --> gequalgs, gegalsg --> gequalsg, egalii --> equalii 2- improve trial division in all basic arithmetic functions [ e.g try for(i=1,10^5, factor(1009)), or moebius, or ... ]. Old logic was broken for small inputs (tried far too many primes) 3- improve quadclassunit(D >> 1), about 10 times faster in the 40 digits range [forbid long reduction cycles (too costly to update arch. info when a relation is found + streamline factorquad() ]. See Z_lvalrem_stop() + remove extra_relations() and use large prime variation all the way [almost all relations are found this way] 4- streamline/clean-up polroots [ complete rewrite, much faster for small degrees ]. 5- improved zetakinit() [save some multiplications, about half of them for quadratic fields. Less so as the degree increases. ] 6- renamed RgX_RgX_compo -> RgX_RgXQ_compo 7- renamed binome -> binomial, chinois -> chinese [ added chinese1(x) for chinese(x, NULL) ] 8- add GC in integer valuation functions + use recursive algorithm when valuation looks large 9- no longer raise an exception when online help used on unknown id or obsolete function [report 'unknown identifier' or 'obsolete function'] 10- removed buggy support for narrow class group in quadclassunit + rewrite binary quadratic forms [ qfr3 / qfr5 ]. TODO: move from arith1.c to qfb.c 11- reinstate cornacchia + cornacchia2 with a different interface [ use cornacchia in qfbsolve ] 12- allow non-real arguments in incgamc, incgam MW 13- ellap: if E has CM by a principal order, use Cornacchia instead of Shanks/Mestre 14- more efficient algorithm for issquare(t_FRAC | t_RFRAC) 15- don't return t_INTMODs component in *modpr routines, but lifted representatives. 16- FpX_roots, FpX_factor: normalize input first + direct support for quadratic and linear polynomials [ no need to compute X^p !] 17- FpXQ_powers and similar routines: use multiplications when input has small degree, squarings otherwise. 18- matsnf over polynomial rings: make sure elementary divisors are monic 19- ellpointtoz() now returns z such that 0 <= Im(z) < Im(w2), 0 <= Re(z) < Re(w1). 20- bnfinit(non-monic t_POL) --> now discard variable change 21- rename apprgen9 -> padicappr, factmod9 -> factorff 22- rewrite padicappr() 23- [COMPAT] bnrdisclist has lost its 4th argument 'flag', and omitting the archimedean component now means that all 2^r1 possible values are substituted (formerly: indicate no ramification at infinity). The prototype of bnrdisclist0 has likewise changed. 24- renamed isprincipalrayall -> bnrisprincipal, rayclassno -> bnrclassno rayclassnolist -> bnrclassnolist 25- Change the output of ideallist with technical (flag 2,3) [ with units ]: instead of two vectors, output a vector of 2-component vectors. Change the input of all list routines (bnrclassnolist, bnrdisclist) accordingly. 26- %0 (undocumented) is no longer accepted as an alias for % 27- renamed realzero -> real_0, realun -> real_1, realmun -> real_m1. GN 28- MPQS rewrite [cleaner, faster] Removed 1- obsolete implementation incgam1 [ use incgam. As far as private functions go, incgam2 is better ] 2- removed ideallistarch0, ideallistarchgen, ideallistunitarch, ideallistunitarchgen. Just use ideallistarch. 3- obsolete default 'buffersize'. Flag -b is a no-op. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.9 (released 23/12/2004): Fixed 1- ploth(,256). splines had stopped working 2- gamma(-1.), psi(-1.) [ non-positive integers masquerading as t_REALs ]: wrong results (oo) or 'division by 0' error messages 3- log(1. + 1e-20) --> print more decimals than are significant 4- [Mac OS X + Fltk]: remove the BROKEN_FORK assertion --> graphic window becomes independant of gp as under other OSes. 5- elllseries did not accept complex arguments GN 6- [ix86 + Sun cc] build fails [ unsatisfied symbol reference to 'mulll' ] 7- [libpari] gprec_w didn't behave well for real zero 8- gp -p 51234567890 --> internal overflow and primelimit set to smaller integer 9- [ GMP kernel ] incorrect resmod2n --> wrong 2-adic sqrt 10- [hi-res plot: fltk] fix compilation with g++-3.4 BA 11- [hi-res plot: fltk] line plotting was broken 12- oo loops in prodinf [ e.g prodinf(x=2, zeta(x)) ] 13- [compatible=3] wrong prototype for isoncurve, lex, sign, thetanullk 14- quadhilbert(D > 0) spent an unreasonable time to find a relative equation defined over Q [ use Galois theory instead of naive search ] 15- typo in resmod2n [ missing (ulong) typecast ] -> issquare((2^64+1)^2)=0 BA 16- galoisinit() could fail to find a polynomial defining the fixed field. 17- elllseries had an apparent singularity at s = 2 [ loss of accuracy ] 18- gcoeff, gmael & their variants were not lvalues. 19- typo in element_val(t_FRAC) [ "non invertible" errors in rnfpseudobasis ] 20- added -fno-strict-aliasing to gcc flags [ PARI code doesn't follow strict aliasing rules. In any case, gcc 3.3 can't handle new mael ] 21- 1.a --> 1.0000 [ should be error ]. (x.a = x+1); 1.a --> 1.0000 [ should be 2 ] 22- bnrdisclist(bnfinit(x,2),1) --> SEGV GN 23- [Solaris cc] use safer optimization flag [ -xalias_level=any, fix a pb with 18 above ] Changed 1- increased maximum binary exponent for t_REAL, and maximum GEN length on 64 bit machines. Bumped BINARY_VERSION for writebin --> objects saved in writebin format between 2.2.1 and 2.2.8 are incompatible. 2- use easier to differentiate colors for hi-res plots [ replace "sienna" by "violetred" and "cornsilk" by "green" ] 3- GP interface of function intnum [ old flags not recognized, much more elaborate interface ] 4- library interface of functions intnum, prodeuler, suminf, sumalt, sumalt2, sumpos, sumpos2, prodinf, prodinf1 [ GEN (*eval)(GEN,void*) everywhere instead of entree * ] BA 5- allow Configure -l [ in addition to /pari.cfg ] 6- renamed gzero --> gen_0, gun --> gen_1, gdeux --> gen_2. 7- replaced kludgy matexp.c example by straightforward extgcd Added 1- new algorithm for log( t_COMPLEX ), log(2) [ AGM ] 2- new algorithm for Pi [ AGM ] 3- new algorithm for atan, acos, asin [ AGM ] HC 4- "double exponential method" for numerical integration and sumation. See ??intnum. New functions intcirc, intfouriercos, intfourierexp, intfouriersin, intfuncinit, intlaplaceinv, intmellininv, intmellininvshort, intnuminit, intnuminitgen, intnumromb, intnumstep, sumnum, sumnumalt, sumnuminit 5- new universal constant gen_m1 6- [bench suite] test-intnum and test-stark toplevel targets %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.8 (released 25/11/2004): Fixed 1- gp --version: stack overflow 2- overflow (in C long multiplication) in zeta(4.45+292532.0*I) 3- setrand(1); bnr = bnrinit(bnfinit(quadpoly(1020,y)), 31,1); rnfkummer(bnr, matdiagonal([5,1,1])); --> SEGV ( typo in FpXQX_from_Kronecker ) 4- make -j4 bench could start the bench before the binary was built 5- matkerint had stopped working [from 2.2.7] GN 6- [Solaris + cc:] fix linker warnings (missing object types in src/kernel/*.S) 7- listsort(List([]), 1) --> SEGV 8- setrand(1582268146); bnr=bnrinit(bnfinit(y^12+6*y^10+31*y^8+84*y^6+159*y^4+166*y^2+1),4,1); rnfkummer(bnr,[1,0,0,0,0,0;0,1,0,0,0,0;0,0,1,0,0,0;0,0,0,1,0,0;0,0,0,0,2,1;0,0,0,0,0,1]); --> bug in gadd [ typo in FqX_split ] Smaller test-case: setrand(1701015992) factorff(x^2+y+2, 3, y^3+y^2+2) MSo 9- bug in print_version() --> SEGV on startup if cc version number too long 10- subst(O(x),x,x+O(x^2)) --> SEGV [ substituting in 0 t_SER ] MSo11- various bugs in anal.c: uninitialized reads in get_op_fun(), double_op() memory possibly freed twice because ep->args was not reset to NULL after being freed 12- (10^100 + 0.) / (10^100 + 1.) --> 0. [ display bug from 2.2.6 ] 13- rnfnormgroup(): restrict to primes of degree 1 [ much faster ] 14- gamma(351/2) --> 1.235874058265488750143951998 E740 [ = gamma(351) ] 15- gammah was much slower than gamma [ contrary to docs ] 16- problems with 0 t_SERs: O(y^5)/(1+x) + O(x^3) --> O(x^3) O(y^5)/(1+x+O(x^3)) --> O(y^5) + O(y^5)*x + O(y^5)*x^2 + O(x^3) O(y) / (1+x) --> O(y) O(y) * 1/(1+x) --> O(y) subst(x+O(b),x,a) --> a 17- (0. * x) / x --> 0.E-28 * x 18- content(0.*x) --> 0 19- nfinit([x^2+1, y]) --> SEGV (bad input) 20- lngamma(10^50*I) returned many more digits than were significant 21- bnfinit(x^4-768*x^3+220032*x^2-27869184*x+1316749312) --> recent oo loop 22- elllseries(large t_REAL) --> 0 [ instead of ~ 1 ] 23- erfc(0) --> error [ instead of 1 ] 24- bnfinit(,1) could return without giving fundamental units (if the computation is unfeasible). Raise an error instead. IS 25- config/get_head would not work only if one invoked $PWD/Configure 26- obscure simplification bug: x;s;t;u; a = -9*u*x^3+3*u*s*x^2-3*u*s^2*x+u*s^3+u^4 b = 9*u*x^3+3*u*s*x^2+3*u*s^2*x+u*s^3+u^4 bezout(a,b) * (2*u^4*s^3+2*u^7) --> involves terms like u^5/u^2 27- matrixqz(matrix(2,1,i,j,i-1),-2) --> [;] instead of [0;1] 28- possible SEGV in bnrinit [ when ray class group is trivial ] 29- negative definite forms allowed by Qfb() while most qfb* routines can only cope with positive definite forms. Explicitly disallow negative definite forms. 30- \p 38 ellinit([1,0,0,-19959260,-34323045317]) -> precision too low in initell 31- {p = x^36 - 252*x^34 + 27504*x^32 - 1723392*x^30 + 69300198*x^28 - 1894026456*x^2 6 + 36355251492*x^24 - 499350803616*x^22 + 4953373719489*x^20 - 355510821425 40*x^18 + 183790369965636*x^16 - 677399199594048*x^14 + 1751507793357696*x^1 2 - 3105079104411648*x^10 + 3651333353058816*x^8 - 2698458969378816*x^6 + 11 30370773667840*x^4 - 207898980728832*x^2 + 2879456034816; nfroots(nfinit(subst(p,x,y)), p); } --> loop forever in lllintpartial() Fix: abort lllintpartial if progress negligible (was: if _no_ progress) 32- some permanent structs not freed in freeall() 33- [--with-gmp] round(-4294967296.1) --> '-0' [ typo in mpent ] 34- polredabs(x^4-x^3-31*x^2-12*x+144) was not reduced [ typo in subfield detection algorithm ] 35- nffactor(nfinit(a^2+1),x^2+[]) --> SEGV GH 36- lngamma was not even continuous : its argument was reduced mod 2Pi 37- contfrac(sqrt(2)/2,,2) --> trying to overwrite a universal object 38- nfroots(nfinit(a^2+a+1),x^2-a/4) --> [] (leading coeff not properly taken into account in nf_DDF_roots) 39- Y=Mod(y,y+1);Mod(Y*x,x-1)^2 --> bug in FpX_divrem, p == NULL 40- return type for nffactormod was not a factorization (had become t_VEC) 41- Pol(Ser(1+x)) != 1+x [ bitmask not cleared properly in gconvsp() ] 42- default(datadir,"...") --> SEGV [ attempt to free a static string ] 43- Configure was missing log2/exp2 on systems that had it 44- typo in base2.c:init_norm() [ wrong result in idealprimedec for huge fields ] 45- matsnf([x,1; 0,x],6) --> incorrect type 46- qfgaussred(a) did not work if coefficients of a did not support the "sign" operation [ signature was computed internally ] BA 47- bitneg(1,0) --> SEGV (caused by 2.2.5 A10). 48- factorback([;]) didn't work [ should be 1 ] 49- f = factor(n); divisors(f) destroyed the factorization stored in f 50- add missing GC in hess() 51- [Configure:] runpathprefix was computed only in terms of $osname (assuming standard vendor supplied linker). At least check whether it's GNU ld first. 52- misleading error message rtodber "overflow or underflow in R->dbl" (in fact, only overflow) 53- quadgen(-8) * 0. --> SEGV 54- I + O(2^10) --> error 55- ((x + quadgen(-8))*Mod(1, i))/(x^2+1) --> SEGV [ from randomgen ] 56- Mod(a^0,i^0) --> Mod(1,1) [ should be Mod(0,1) ] 57- factor(HUGE, 100000) --> "pointers lost in gerepile" in random GC in ifac_realloc() [ missing copy() for (*partial)[2] ] 58- incorrect gerepile() behaviour on t_LIST [ would try to update non-existing components if list not full ] BA 59- quoted strings were not displayed properly quoted. 60- bestappr(0.1, 8) --> 0 [ should be 1/8 ] 61- rare bugs in copying routines [ clone bit sometimes not unset ] 62- SEGV in qfminim when integer entries and precision error occured BA 63- galoisidentify() could fail on WSS group with S4 residue. 64- t_POLMOD + t_MAT was incorrect. E.g Mat(1) + Mod(1,x) --> Mod(Mat(1),x) instead of Mat(Mod(1,x)) as for other scalars. 65- Mod(1,8) + O(2^2) --> Mod(1,8) [ should be error ] 66- lngamma(1.) returned a t_REAL of length 'realprecision' (instead of 3) BA 67- matsnf(Mat([])) was returning a matrix instead of a vector. 68- ellap(ellinit([0,1,0,1,0]), 100) --> FPE [ BIB: 100 is not prime, but make the routine more robust ] 69- give meaningful error messages (with context) for 1<<(1<<32), 1<S" ] 70- memory possibly freed twice in pop_val_if_newer() [ race condition on interrupt () during new_val_cell() ] 71- ellap(ellinit([0,1,0,1,0]),100) --> SEGV [ 100 is not prime ! ] MS 72- recover from readline history corruption [ don't trust history_length in history_is_new() ] 73- obscure bug in thue() [ unit of norm -1 not found due to interface inconsistencies ] t = thueinit(x^6 - 2); thue(t, 2638) --> [] JD 74- [Configure:] detection of times() 75- Forbid t_POL + t_VEC: useless and inconsistent [ we had: 1 + [] --> error, x + [] --> OK but x * [] --> [] instead of '[]*x' , etc. ] 76- obscure bugs wrt polynomials with t_MAT coefficients created via Pol() [ e.g content(x*[;]) --> [;], primitive_part(x*[;]) --> [;] ] 77- incorrect behaviour in scalarpol()/scalarser() for exact 0 argument 78- typo in ellap: e defined over Fp didn't work any more 79- t_SER ^ t_QUAD --> SEGV 80- nffactor(non-monic t_POL) --> SEGV due to FpX_red interface change [ don't allow t_INT argument, t_POL is mandatory ] 81- ZX_incremental_CRT: wrong handling of degree increase (--> oo loop) 82- SEGV in Karatsuba multiplication for polynomials, when high product was 0 (over a ring which is not an integral domain!) 83- 1 / Mod((a^2-a)*x^2-1,Mod(2,6)*x^3+Mod(1,2)*x^2+1) --> SEGV 84- ellap(e defined over F2, 2) gave wrong results [ assumed e defined over Q and reduced relevant data modulo 8 ] 85- matcompanion(degree 0 polynomial) --> stack corruption 86- incorrect handling of inexact polynomials in matsnf(,2) [ inexact leading 0 coefficients ] 87- writebin(file, 0) saved a "corrupted" object (0 couldn't be read back) 88- wrong prototype used in rnfdet() [ accepted 3 arguments instead of 2 ] 89- typo in to_Kronecker [ when at least 3 variables involved ] 90- typo in x = sqrt(t_PADIC) [ returned either x or -x ] 91- rare stack corruption in RgX_mul(t_POL, t_POL) [ when product of leading coefficient cancel, valuation is non-zero _and_ we use an "unsafe" gerepile right afterwards ] 92- component(Ser(x),2^31-1) --> SEGV 93- typos in krosi(), kronecker() [ e.g krosi(-4,1), kronecker(0,2^32+1) ] 94- agm(-1,2) --> oo loop 95- tanh(10^10) --> exponent overflow [ should be 1 ! ] 96- gamma(exp(-373)) --> exponent overflow 97- readline: assume a file 'foo' exists, \rf --> \foo [ r deleted! ] [\r f was OK]. Solution: just expand to '\r f'; hitting again completes properly --> \r foo. BA 98- Reduce stack consumption in ffinit and polsubcyclo. 99- (p/q)' wasn't simplified if q wasn't squarefree 100- polylog(n, x < 0) had a (small) non-zero imaginary part 101- 3 + O((-1)) --> oo loop 102- creating t_PADIC/t_SERs via x + O(...) eventually blew up the heap 103- fix memory leaks related to GP pointers and clones Changed 1- lgef / setlgef / evallgef removed. One may safely use lg for t_POLs. As a result maximal degree jumps to ~ 2^24 on 32bit machines 2- renamed *res(te) routines to *rem(ainder). Eg poldivres --> poldivrem, nfdivres --> nfdivrem BA 3- Internal u_Fp* routines now are renamed Fl* and made public. BA 4- [GMP kernel] Library soname changed to libpari-gmp[-2.2].so.N. BA 5- Library .so link changed to libpari.so for all versions. Static library changed to libpari.a for all versions. 6- COMPAT: ellheight now uses the standard normalization: twice the value it used to return. The values returned by ellbil() and ellheightmatrix are unaffected. In particular, ellheightmatrix() is the polar form of elleight(), and ellbil now satisfies the proper identity for B(P, Q) = (h(P+Q)-h(P)-h(Q)) / 2 7- renamed and declared gmul_mat_smallvec --> RM_zc_mul gmul_mati_smallvec--> ZM_zc_mul 8- move functions in highlvl.c to libpari, excluding install(). 9- bnfinit: use approximate integral LLL reduction (much faster than fp) 10- bnfinit: cache multiplication table by prime ideal anti-uniformizers (faster valuations) BA 11- improve binomial (use divide_conquer_prod) 12- improve bnrinit & idealstart when finite part of conductor is 1 (+ improve stability) 13- subgrouplist(bnr,...) does not require bnr to contain generators anymore ( bnrinit(,,1) ). Also much faster. 14- allow zetakinit() to use a bnf argument [ would be recomputed before, making it impossible to certify the result since bnfcertify could not be applied ] BA 15- error messages now mention the GP function when the error occured. 16- intro message [ no point in displaying "realprecision", "seriesprecision" and "format" on startup. One can query them individually, or ask for all defaults ] BA 17- macro varncmp(vx,vy) should now be used to compare variable numbers. BA 18- split substpol from subst ( reverse [ 2.2.1 C24 ] ). Use substpol for non-trivial algebraic substitution. 19- remove t_FRACN / t_RFRACN from \t output, add t_VECSMALL BA 20- bittest() now handle negative operand as 2-adic. BA 21- type() does not allow to change object types anymore. 22- internal routines setloop()/incloop() allocated 2 chunks of memory, then assumed they were connected [ true for the current allocation model ]. Remove that unecessary assumption. 23- more informative error messages in concat() 24- in affsi / affui (s, z) : do not check that lg(z) >= 3 25- replace gexpo(t_QUAD) by a rough aproximation (as t_COMPLEX): faster 26- made Mat(t_VEC of w t_COLs of the same length h) return a h x w matrix Used to be a 1 x w matrix whose elements were t_COLs. Obsoletes such hacks as: v = vector(...); v[1] = Mat(v[1]); concat(v). Now Mat(v) is enough. 27- move BEGINEXTERN / ENDEXTERN pairs out of kernel headers into pari.h 28- split the User's manual in two: PARI/GP and libpari. 29- updated and completed the tutorial 30- faster basic transcendental functions on small inputs (sqrt, log, exp) 31- rewrote basic generic kernel (add,mul,div) [ faster, less obfuscated ] 32- macroified gop1z, gop2z, gops2gsz, gops2sgz, gops2ssz 33- diviiz(x,y,z), divisz, divsiz and divssz always assign the euclidean quotient [ used to depend on the type of z: if t_REAL computed exact quotient ]. Use rdivii, rdivis, rdivsi, rdivss for analogous functionality (no "z" variant); 34- ensure proper rounding in divrs 35- renamed padiczero --> zeropadic [ as in zero[pol|ser|vec|col|mat] ] 36- macroified gcosz, gsinz, gexpz, etc + cleanup transcendental functions 37- macroified mulssz, addssz 38- rename mpent --> mpfloor 39- rename divise --> dvdii, gdivise --> gdvd, mpdivis --> dvdiiz, mpdivisis --> dvdisz 40- rename mpppcm --> lcmii, remove mppgcd [ use gcdii ] 41- rename resss --> remss, ressi --> remsi, resis --> remis, resii --> remii, gres --> grem 42- rename krogs --> krois, krosg --> krosi 43- rename FpXQX_FpXQ_mul -> FqX_Fq_mul, FpXQX_normalize -> FqX_normalize 44- rename adduumod, subuumod, muluumod, divuumod --> Fl_[add,sub,mul,div] invumod --> Fl_inv, invsmod --> Fl_inv_signed, powuumod --> Fl_pow powiumod --> Fp_powu, mpsqrtmod --> Fp_sqrt, mpsqrtnmod --> Fp_sqrtn 45- rename mpsqrt --> sqrtr, mpsqrtn --> sqrtnr 46- don't copy arguments of user functions for types which have no modifiable components (anything but VEC, COL, MAT, LIST, VECSMALL): much faster. 47- ':' no longer allowed as a substitute for ';' if compatible = 0. Use GP2C semantics [ x:int, v:vec ]. For the time being the type information is discarded. 48- modulargcd() was very inefficient for non-monic t_POLs [ e.g (poltchebi(x) - 1) / (x-1) ] JD 49- [timer: ] use sysconf(_SC_CLK_TCK) instead of CLK_TCK if available, and make sure one of these is available before choosing times() in Configure JD 50- check for 'exuberant-ctags' before 'ctags' in make_vi_tags [ and fail gracefully if neither is found ] BA 51- support for gp2c-run on Darwin 52- remove blanks in "raw" outputs ( default(output,0) ) 53- made .fu and .tu return t_POLMOD, not t_POL BA 54- [GMP kernel] use mpn_sqrtrem for sqrtr_abs 55- nfsubfields (use much less memory) GH 56- more robust thue(): faster enumeration of small solution, don't assume that the full unit group is known, warn when conditional result is obtained. 57- remove log() flag: decide alone whether to use AGM or not. Rewrote logagm and mpexp1 58- make ??? index search ignore case [ ???bernoulli will find Bernoulli ] 59- renamed svaluation --> u_lvalrem, pvaluation --> Z_pvalrem 60- change semantics of sqrtn to catch easily non-residues from the user's side 61- rewrote the 'tune' utility, add one tune.h file for each kernel, support for user override still needs to be rethought (or documented). Added 1- make test-all [ all available test suites (SLOW !)] BA 2- add support for GNU/Hurd. 3- conversion routines zv_to_ZC, zv_to_ZV, zm_to_ZM, and matrix multiplication: RgM_zm_mul, ZM_zm_mul. 4- output support for zm / Flm matrices (t_MAT with t_VECSMALLs instead of t_COLs) 5- FpM_rank 6- allow factor( an elt in Z[i] ) 7- put back bruteall [ used by Math::Pari ] BA 8- Configure support for sparc64, x86_64 and ppc64 BA 9- x86_64 level0 inline assembly kernel BA 10- add POSIX-style long options --fast, --quiet, --primelimit and --stacksize. 11- new internal library routine itos_or_0 12- new member function .index 13- rdivii, rdivis, rdivsi, rdivss to replace diviiz & co. 14- new routine mpround, mpfloor, mpceil, mptrunc, roundr, floorr, ceilr, truncr BA 15- galoisisabelian, galoisexport, galoisidentify and galoissubgroups now also accept subgroups returned by galoissubgroups. 16- new routine Fl_sqrt 17- new routines FpX_factor, FqX_factor, FpX_degfact, FqX_red 18- private header file pari-priv.h 19- new function ispower 20- forvec iterator GH 21- new function zncoppersmith 22- public interface to forvec() [ forvec_start + forvec_data, for GP2C ] 23- routine sqrtremi() [ Karatsuba square root ] 24- internal routine int2n() [ = 2^n ] 25- new functions Z_pval, Z_lval, u_lval 26- new function primepi BA 27- new default factor_add_primes BA 28- HPPA 32bit and 64bit level0 inline assembly kernel Removed 1- obsolete macro leadingcoeff [kept for backward compatibility but removed from the documentation]. Use leading_term. 2- obsolete undocumented type t_SMALL BA 3- revert 2.2.1 A14 and A17 (broken with GMP kernel, unmaintainable). BA 4- cornacchia, in favour of qfbsolve. 5- useless inefficient types FRACN / RFRACN 6- routines gred [useless] / gredz [ useless did not work ]. Define gred --> gcopy for backward compatibility 7- many obsolete error codes [ for err(...) ] 8- smodsi() [ useless, not well defined ] 9- buggy macros mppiz, mpeulerz [ undocumented, useless, broke compilation to use them ] 10- inconsistently named macros mpinv[sir]r [ were "z" functions ]. 11- public macros refering to static transcendental routines (e.g mpatanz) 12- undocumented, inconsistently named, useless, mulsii, addsii, divisii 13- useless routine umuluu [ use mulll ] 14- undocumented [macro] constants pariC1, pariC2, pariC3, pariK, pariK2, pariK4 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.7 (released 18/12/2003): Fixed 1- bench input files: should all start by a 'gettime()' instruction 2- bnfisnorm(bnfinit(x^2-11),1) --> [Mod(1, #), 1] [ return a result involving MAXVARN on trivial input ] 3- [Mat(5)] * [[0]~]~ --> 0. Should be [0]~ [introduced in 2.2.6-C.25] 4- \p 1000 E=ellinit([1,0,1,-120039822036992245303534619191166796374,5042249924849106700108 01799168082726759443756222911415116]); x1=1e100; y1=ellordinate(E,x1)[1]; ellpointtoz(E,[x1,y1]); --> impossible addition t_VEC + t_VEC. [ precision error ] 5- erfc(non scalar) --> type error 6- raising to t_FRAC power didn't work with p-adics: (-1+O(5))^(1/2) --> 1 7- [ isprime / APRCL: ] integer overflow, e.g isprime(2^32 + 1, 2) 8- sum(i=2^32-10,2^32+10,1) --> 11 [ kind of overflow ] + didn't use the t_INT interface ==> broken with GMP kernel 9- polgalois(x^6-3*x^4+3) --> [24, -1, 1], should be [24, -1, 2]. From 2.2.4 10- nfisincl(x, x^2+1/2) --> SEGV [ assumed integral inputs ] 11- numbpart(10^15+2) --> SEGV [ check for x < 10^15 incorrect ] 12- polcompositum(x,x) --> SEGV [ problem with poldeflate(deg 0 pol) ] 13- zeta((1+I)/2^225) --> 7e28 [ precision error when using func. eq. ] 14- typos in qfsign/qfgaussred() [ aka sqred2 ]: wrong results: e.g qfsign([0, -1, 1, 1; -1, 0, 0, 1; 1, 0, 0, -1; 1, 1, -1, 0]) --> [2,2] ( should be [2,1] ) 15- numbpart(0) --> 0 [ should be 1 ] GN 16- assembler section of Sparc Makefiles relied on GNU make specific $< MSo17- off-by-1 error in Vec( t_STR ) [ memory corruption ] 18- off-by-1 error in itostr(), e.g 10^11 [ memory corruption ] BA 19- [hi-res plot: X-Windows] rescaling bug MSo20- bittest(1,32) --> 1 [ off-by-1 error ] 21- nfeltpowmodpr(nf,x, prime of degree 1) --> SEGV [ FpXQ_pow couldn't handle computation in prime fields ] 22- charpoly( Mod(mat, poly) ) --> SEGV [ out of stack components not treated properly ] 23- memory corruption when parsing floating point constants [ constante() ] 24- too little GC in serreverse() 25- bnfinit(huge field) --> "precision loss in truncation" [ missing term sqrt(disc(K)) in norm bound ] 26- allow conj(t_POLMOD) provided the modulus degree is <= 2. MSo27- ?0 with _many_ user functions defined --> SEGV [ typo in commands() ] 28- quadclassunit(5) --> PLEASE REPORT [ can't build subfactorbase, introduced in 2.2.6 ] 29- valuation(x^3, x^2) --> 3 [ valuation at a monomial assumed it had degree 1, introduced in 2.2.2 ] 30- Set(matid(2)) --> [ "[1, 0;\n0, 1]" ]. Ensure "raw" format is used, not "prettymat". 31- typo in rnfpolred(bnf, *). E.g rnfpolred(nfinit(polcyclo(3,a)),x^3-19) --> oo loop [ non-positive T_2 form ] 32- typo in ellap: rare wrong result. E.g E=ellinit([0,0,1,-5115523309,-140826120488927]); ellap(E, 1315717181) BA 33- qfbprimeform(-3, 1) --> data corruption [ gzero's signe set to 1 ] 34- qfbpowraw(x, n < 0) reduced its output 35- stack corruption when adding huge p-adics 36- idealintersect did not allow fractional ideals 37- Ser([1,2]) --> 1 + 2*x + O(x^2) [ OK ], but Ser([0,0]) --> O(x^16) 38- writebin() still produced incompatible output depending on the multiprecision kernel. 39- [alg | lin]dep( t_PADIC ) had stopped working in 2.2.6 40- some precision problems in polgalois(deg(p) > 7) [ changed slightly some heuristic settings: the algorithm is simply not rigorous... ] 41- typo in polredabs: polynomial of minimal T_2 norm might be missed [ actually found, then deleted due to a typo when "Sorting" small vectors, which would assess them the norm of a larger element ] 42- polredabs(,4): some polynomials of minimal norm could be eliminated due to fixed buffer size for the small vectors. Made that dynamic. 43- in certain situations (when using Allombert's algo.), subfields did not output subfields sorted by degree 44- [Windows installer:] online help did not work on most installations 45- lines continuation with \ did not work with DOS fileformat BG 46- random(2^31) returned integers in [0, 2^32-1] [ long/ulong problem ] 47- isprime(156499227435744375600531968861048687296374896432841731) --> SEGV [ missing case in aprcl:sqrmod5() ] BA 48- Configure: using gcc-3.3 + LANG=french, Configure failed to detect gcc [ messages translated ] 49- alpha kernel would not compile with a C++ compiler (missing extern "C") 50- rare stack corruption in gmul(t_COMPLEX, t_COMPLEX) [ when result is real ] 51- valuation(Mod(x,x^2), y) --> oo loop [ now 0 ] 52- optimization problems in new zeta() and gamma() [2.2.0 C13] ( e.g zeta(0.5 + 10000*I) was _much_ slower than before ) 53- precision problem in nffactor [ in get_R() ], could yield to a SEGV, e.g nffactor(nfinit(y^4+7^2),x^28-14*x^24+20321*x^20+166992*x^16+1171296*x^12+1342208*x^8-5005056*x^4+3211264); 54- contfrac(Pi/2,2) --> [1, 1] (doc says a_n != 1, so should be [2]) 55- factorint( 3280696195200006885547973357173182411881462602934802054749349683516314460050 2548596646024265171468102088952756084355402608216473040677346490348936595334 0299389230010814564530645152250241760175805765084544728012391149823776145022 4913178048870032606672750626773595019035786804361581343222144074318522768947 2061349830773562073895748494534362180537529975336881525935996152181576667869 0625865166662910961888106910345518707973056625912728422391238723575276042635 9727112469435556047168454738353621102783718736137552743946577993495054202848 9372915917197045423574773583244796785665263319216397122018435444897 ,11) --> impossible assignment I-->S [ stack corruption ]. 56- typo in kummer.c:invimsubgroup [ hnfmod --> hnfmodid ]. Very rare weird error message in rnfkummer(): "wrong subgroup in conductor". 57- typo in alglin2.c:hnfspec() [ same loop index used twice ] 58- zeta(x) very slow for large integer |x| (use new bernfrac() code) 59- removed -mimpure-text from DLLDFLAGS on non-sparc architecture XR 60- Configure/bench: use head -n # instead of head -# (deprecated and unsupported by GNU coreutils) 61- not enough GC in mpbern() [ Bernoulli numbers ] and psi() 62- \p50000, then polroots(x) --> exponent overflow 63- ellj( t_QUAD ) / eta( t_QUAD ) was forbidden. 64- polredabs(x,1) did not work when x was already reduced 65- polroots(x^3 + 0e-20) --> oo loop [ didn't handle nicely non-exact 0 as a constant coeff ] 66- 'make doc' always rebuilt the documentation, even if it was up to date Changed 1- bnfinit: [small_norm phase] speed up norm computations. 2- [make etags:] use $ETAGS instead of 'etags' if defined 3- [libpari:] renamed incgam4 --> incgam0, incgam3 --> incgamc BA 4- [Description system] Store GP functions in a database in src/functions/ instead of hard-coding them in C files. 5- [libpari:] modified zbrent interface to allow library programming 6- ellpointtoz(E, P): remove the test that P be on E [ useless and often wrong when P has inexact entries] 7- allow serconvol() with 0 series. MSo 8- allow numtoperm(0,k) [ --> [] ] 9- simplify result of basic op. involving complex numbers, e.g. I*I --> -1 as t_INT (was t_COMPLEX) 10- embedings of number fields: use x + iy --> (x + y, x - y) instead of (sqrt(2)x, sqrt(2)y) to map complex embeddings to R^2. 11- disallow Ser( t_MAT ) [ resulted in a series with t_COL coefficients ] 12- nf format to improve idealinv() [ nf[5][6] and nf[5][7] ] 13- disallow sqrtint( x < 0 ) 14- meaning of the GP_DATA_DIR global variable: now points to the directory _containing_ galdata, not to the galdata files 15- qfminim(,,2) + polredabs: look for points by (roughly) increasing norms (was: full enumeration and roughly decreasing norms) 16- exp(-10^10) --> 0.E2525223 [ was 'underflow' ] 17- polredabs: improve the search for subfields (no polynomial factorization required now, only linear algebra) 18- ellglobalred(): use gcd(e.c4, e.c6) to help factor e.disc 19- removed obsolete components ("checks", "bits of accuracy left in computation") from quadclassunit / bnfinit / bnfisprincipal / bnrisprincipal / bnfunit outputs. 20- 'make test-graphic' is gone. Use 'make test-ploth' HC 21- new implementation of gamma() 22- renamed Oxxx/dft.Config.in --> pari.cfg 23- new implementation of bernfrac() [ use zeta(2k), initial GP code by HC] 24- bernvec always calls bernfrac() [ hence has become useless ] 25- [sparcv8_super kernel:] replace asm divll with portable one (slightly slower but fixes many compilation problems, and easier to maintain on an architecture which has become hard to test) 26- buchall() [ bnfinit, etc ]: complete rewrite to avoid restarting from scratch after a precision increase. All relations stored in algebraic form, so that data is easily recomputed to higher accuracy if necessary. Use lower default precision. 27- remove special handling of t_STR by printtex / writetex [ 2-2-6-C19: a \ would be inserted in front of $, %, etc. ]. This broke things like printtex("$", x, "$"), and is better done by the user herself. 28- bnfinit(): remove useless components from the "technical parameter". Added 1- [Configure:] flag --with-ncurses-lib=* BA 2- support for FLTK graphical library [ hi-res plot ] BA 3- galoisidentify for order 96 to 127. 4- default 'datadir' [ to allow relocating 'galdata' for polgalois ] 5- hi-res plotting under Windows GTo 6- routine qfrep() BA 7- routine qfbsolve(Q,p) for Q imaginary and p prime 8- new testsuite: make test-galois (~ 1 minute) 9- new options to Configure: --with-fltk, --emacsdir, --datadir, --sysdatadir SG 10- updated micro-kernel for HPPA BA 11- Add code 'i' for functions returning C int (not long) Removed 1- bruteall [ useless, undocumented variant of 'brute' ] 2- option to Configure: --miscdir %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.6 (released 19/06/2003): Fixed 1- rnfidealtwoelt, rnfidealmult --> SEGV 2- agm(x+1, x+2) --> oo loop [2.2.5 F-61 was undone...] 3- setrand(1); elltors(ellinit(vector(5,k,random/random))) --> SEGV [ incorrect use of partial factorization in ellintegralmodel --> surviving denominator ] 4- old typo in cauchy_bound --> factor((x - 155)*(x^2 + 160*x + 12864)) returned a single irreducible factor [ missing factor 2: initial upper bound for roots was 125 instead of 250 ] 5- zeta(x) very slow near large negative integers 6- algdep(2^46,1) ---> 1 [from 2.2.5] 7- bnrclassnolist(bnfinit(y),[2,2]) --> SEGV IS 8- typo in paricom.h [extra , in enum] --> compilation failure IS 9- typo in part.c [ // comments ] --> compilation failure 10- y/(x/y) --> error [ wrong assumption that y is a genuine GEN in mulscalrfrac ] 11- example/Makefile wasn't up to date [ link with -lpari ] 12- zetak(zetakinit(y), 3-1e-28) --> -7.2e28 [ catastrophic precision loss triggered by anything non-integral but very close to an integer ] IS 13- gp-dyn build on AIX 14- subst(y*x,y^2,x) --> 0 15- rnfisnorminit(x,x^3-2) --> SEGV [ bad input. Missing argument checks ] 16- Compiling with g++ + gmp, missing gmp version number [missing stdio.h] IS 17- [AIX:] various compilation problems + select better CFLAGS (-qtune=auto -qmaxmem=8192) IS 18- [HPUX:] remove -E from DLCFLAGS 19- bnrconductor(bnfinit(x)) --> SEGV [ missing check ] 20- ellpow(E,...,-1) --> stack error [ from 2.2.5 ] 21- a:b:c; c/a/b == c/b/a --> 0 22- sparcv8 inline assembler kernel used global registers for hiremainder / overflow, which was dangerous, inefficient, and complicated. Now none of the inline kernels use any global variable. The non-inline assembler kernels do define and access globals hiremainder and overflow. BA 23- cos(2^2^22) --> precision too low [ idem sin, tan ] 24- setrand(1504969109; quadclassunit(-403195) --> incorrect. Check against L-value too liberal; now allow quotient in [ 0.8, 1.3 ], not [0.75,1.5] 25- TODO item: quadclassunit not reliable when fed non fundamental discriminant (oo loop [e.g quadclassunit(-352)], wrong result). [ fix: increase factor base ] 26- sign of elleisnum(E, 6, 1) was wrong BA 27- [GMP kernel] factor(18295370635792208009) --> error 28- idealprimedec(nfinit(x^16+16),256) --> SEGV [ bad input ] 29- setrand(1642014180);quadclassunit(1642014180) --> PLEASE REPORT [ bug in large prime relation code ] 30- TODO item: rnfpolred(nfinit(quadpoly(904,y)),quadray(904,1)) *** division by zero in gdiv, gdivgs or ginv BA 31- uninitialized memory read in divrr(x,y), when lg(y) < lg(x), leading to random rounding of result. 32- [Cygwin + bash >= 2.05a]: HOSTTYPE no longer auto-exported by bash --> Cygwin compilation broken. Define it to i386 by default. 33- TODO items related to polgalois + polgalois(x^8-1864259299553450972214799899167226732549697977945716*x^6+331143259018657601105207922631212331088735421305543663274125986698777318014979969*x^4-2225286541902342283500014249183311190477390*x^2+5); --> degree too large + setrand(7); polgalois(x^8+162644002617632464507038884216211529274267271168000002) --> wrong result + polgalois(x^11 - 2) took a looong time. 34- systematic warning in bnfisnorm() [ "useless flag" ] 35- charpoly could not handle t_POL in variable MAXVARN 36- \p400 + sin(2*Pi) boasted far too many significant digits 37- [Configure:] --with-readline=path did not work 38- [Configure:] $TOP/readline was added to search path for ncurses, termcap, etc 39- memory leak: x = vector(2); y = vectorv(2); while(1, m = matrix(2,2); m[2, ] = x; m[, 2] = y) --> out of memory 40- factor(12345)[,1][3] --> error 41- overflow in some GP interface routines: e.g default(realprecision,10^125) 42- polhensellift((x^2+1)*Mod(1,5),...) --> SEGV [ bad input ] 43- lindep([x,y]) --> SEGV [ bad input ] 44- polredabs(x^4+9670527181567158504671*x^2+4840282594390812607599424249,16); --> impossible concatenation in concat [ from 2.2.5 ] 45- [Cygwin compilation:] incorrect cygtop [ --> readline not found ] 46- [Cygwin:] DLL build. libpari.dll and gp-dyn build OK. Install does not work in gp-sta (SEGV) 47- rare SEGV in Round 4 when using non-primes in addprimes() 48- overflow when computing Euler's constant to 20000+ decimal digits MSo49- error message for unrecognized GP metacommand: off-by-1 error GN 50- Configure breaks if CFLAGS contains '/' (invoke sed with '!' separator) IZ 51- [tex2mail:] line couldn't start with {...\over...} (required indent) IZ 52- [tex2mail:] \over wasn't allowed within \left( \right) 53- ZX_QX_resultant (modular resultant with integer result): possible oo loop when the result is 0, and non trivial denominator. 54- elleta(E.omega) gave incorrect results [ conflicting normalizations ] 55- typo in charpoly(t_MAT) [ stack overflow after garbage collection ] 56- subst(y,x+y-x,y) --> 0 [ missing simplification ] 57- typo in nfroots [ returned inverse of roots when polynomial had small degree (using Trager's method) ] 58- 'path' default incorrectly set on Cygwin 59- [internal:] isprincipalfact() incorrect if flag contained nf_GEN_IF_PRINCIPAL (was unused). 60- bnfisintnorm(bnfinit(y^4+y+1), -1) --> SEGV [ could occur for any unit ] 61- stack corruption in matsnf() [ when GC occurs ] 62- vecsort(t_VECSMALL) --> SEGV 63- v = vector(2); j = 0; v[j++] = 1 --> j = 2 [ side effect of 2.2.4-F21: LHS for matrix assignment was evaluated twice ] Rem: v = vector(2); v[j++] = v = 0 --> SEGV. Don't cry. BA 64- [ix86 + gcc compilation]: fix "invalid preprocessing token" Warning BA 65- galoisinit could very rarely trigger a 'impossible inverse modulo' error. Changed 1- rnf structure (removed useless components) 2- rnfidealreltoabs, rnfidealup: now return a Z-basis as a vector of elements in the relative extension, instead of a meaningless HNF matrix wrt an unknown basis. Was especially dangerous if the extension also existed in nfinit form, since the HNF matrices were _not_ ideals wrt this nf structure. [ also consistent with rnfeltreltoabs ] 3- rnfidealabstorel now requires input in the above form, so use rnfidealabstorel(rnf, nf.zk * A), if A is a standard ideal in HNF form. Used to require matrices in HNF form, which was confusing since ideals such as A gave wrong results [ HNF wrt different implicit bases ]. 4- idealadd(x,y): multiply by lcm(denom(x), denom(y)), not their product 5- rewrote nfhnf/nfhnfmod/nfbezout [ many small improvements ] 6- rnf structure now filled incrementally [ absolute nf, data for norm computations ]. Use build_and_check_obj() mechanism already used for bnf: cycgen ( bnf.gen[i]^bnf.cyc[i] ) + matal (relations in algebraic form) 7- rewrote rnfpseudobasis, rnfordmax [+ new routine rnfallbase ] 8- always define checkmemory() in libpari [ was included only if MEMSTEP was defined ]. Could cause compilation failure when compiling with different flags. 9- upgrade pariemacs, see pariemacs.txt 10- faster divll for portable kernel [ inspired by GMP ] 11- allow system() under Windows (95 and higher) 12- use cmprr() in gegal(t_REAL, t_REAL) 13- have Configure check explicitly that the C compiler is ANSI 14- faster modular algorithm for characteristic polynomial of algebraic integers Mod(x, y) [ ZX_caract(): old would replace x by its integral part and correct at the end; new is fully modular ] 15- separated mpadd functions from [none|gmp]/mp.c --> kernel/add.c 16- use 'lgeflist' for t_LIST: remove the 65536 limit on list size 17- subst(1 + x^2 + O(x^5), x^2, y) --> 1 + y + O(y^2) 18- nffactor: allow modular factorization over primes of degree > 1 IZ 19- try to output usable TeX (avoid braces, let TeX split lines) 20- [libpari internals:] jmp_buf 'environnement' no longer global MSo21- allow poltchebi(n < 0) [ := poltchebi(-n), still satisfies the 3-term recursion ] IZ 22- prime sieve optimization [ primelimit ] 23- try to reduce the likelihood of an artefact relation in PSLQ [ use "confidence level" 2^(-20) ] IZ 24- [tex2mail:] add a "cut here" sign when expression does not fit in the linelength: \o3 \p240 [Pi, Pi]~ 25- faster multiplication [t_VEC | t_MAT] * t_COL for sparse t_COL [ induces faster charpoly for sparse t_MAT ] 26- matsnf: allow rectangular matrices + improvements for singular matrices 27- made startup errors ( GPRC ) non fatal. 28- allow vecsort(t_VECSMALL) 29- renamed mulssmod/divssmod --> muluumod/divuumod and changed their prototype (use ulong arguments, return ulong) [ was already the case, with various casts ] 30- renamed u_invmod --> invumod. Documented all level0 modular routines. [ also added invsmod ] 31- separated "negative or zero argument" (arither2) and "zero argument" (arither3) errors. Added 1- member function rnf.pol (polynomial generating absolute extension) 2- src/kernel/sparcv8_[micro|super] 3- in emacs/ : pari-completion.el pari-conf.el.in pari-fontification.el pari-help.el pari-messages.el sli-tools.el 4- Configure --builddir : find a decent name for build directory depending on kernel options (with/without gmp, exotic assembler kernel) GH 5- PowerPC level0 inline assembly kernel 6- support for install() on Mac OS X BA 7- GP function galoisexport IZ 8- logstyle and TeXstyle defaults 9- [GP defaults:] support 'G' suffix (for Giga) (already supported k and M) 10- extend GP command line: once flags (-xxx) are processed, remaining args are taken to be filenames, read upon startup [ _after_ the gprc read statements have been processed ] GH 11- IA64 level0 inline assembly kernel BA 12- GP function galoisidentify and groups identification facility 13- public function GENtoGENstr [ for GP2C ]. (was private: gtostr()) 14- function coefs_to_vec() NS 15- support for Qt graphical library [ hi-res plot ] Remove 1- remove emacs/compile [ integrated in Makefile ] 2- src/kernel/sparcv[89] 3- config/MANIFEST [ now built dynamically ] 4- config/Makefile.DLLs [ use recent libtool instead of dirty hacks ] %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.5 (released 11/02/2003): Fixed 1- [bnfinit:] typo in be_honest() --> SEGV when cbach2 > cbach [from 2.2.4] 2- apprpadic() when p = 2 (could not work) + typos 3- typo in gphelp [detex mode]: ubiquitous "var" in translation [from 2.2.4] 4- typo in var_make_safe() [ protecting user variables after trapped "stack overflow" ] --> possible SEGV [from 2.2.4] BA 5- [Configure:] add -lm -lc to EXTRADLLDFLAGS, not DLLDFLAGS 6- typo in gp_main_loop: avma not restored properly after allocatemem. [from 2.2.4] 7- typo in [imag|real]_be_honest: SEGV in quadclassunit(D,,[c,c2]), c2 > c [from 2.2.4] 8- typo in rnfisnorminit (pol_up) 9- at \p28: x = (1. + 10^-28) - 1; for (j=1, 100, x = (x-10^-28) + 10^-28) now x has 200 words of precision 10- stack corruption in addition (t_INT + t_PADIC) 11- factorpadic(z+y,2,4) --> SEGV 12- wrong result in idealchinese when the y_i had denominator BA 13- sigma(n,-1) output a wrong result. BA 14- inline alpha assembler broken (registers clobbered) GH 15- polsturm(1, 0, 1) ---> error [ return 0! ] 16- "break loop" did not react correctly to allocatemem() read from a file with \r (stopped reading file right away) 17- matker(x, 1): internal loop forgot a pointer when garbage collecting --> SEGV (or weird error, e.g division by 0) 18- ideallog(nfinit(y),2,idealstar(nfinit(y),4,1)) --> SEGV [bad input] 19- ellrootno(ellinit([0,-25,0,-1250,0])) --> SEGV [from 2.2.3] 20- typo in elllocalred (wrong Tamagawa number, case I0). [from 2.2.4] 21- idealtwoelt(nfinit(y),2/3,1) --> SEGV [bad input] 22- for transcendental function f and polynomial p, f(p) only gave seriesprecision significant terms when val(p) = 0 23- Ser(a/b) --> 1 + O(x^16) (!!) 24- (x^2)^(1/2) --> error 25- idealnorm(nfinit(y),matdiagonal([1+I])) --> SEGV [bad input] 26- polylog(10,x^10) --> O(x^6) at \ps16 [ 16 significant terms ?] --> x^10 + O(x^21) at \ps 21 [missing x^20 term] 27- nffactor/nfroots: SEGV over Q 28- missing sanity checks in install() [ did not check the parser code ] 29- typo in nilord() [lg-->lgefint]: nfdisc() didn't work on 64bit HP 30- ellisoncurve(ellinit([0,0,0,0,1]),[1/2-sqrt(3)/2*I,0]) --> 0 31- type 'gphelp' from command line: carriage return is missing 32- typo in LLL_cmbf() [ rare oo loop in factor() over Z[X] ] IS 33- [HPUX:] should compile with cc -Ae, not -Aa 34- excessive memory usage in bnrstark() [ InitPrimes ] 35- bessel[jk](t_SER) not implemented around a!=0, but gave (bogus) results [output error message for now] IZ 36- [OS/2:] rename static functions _core[2] (conflict with stdlib.h) IZ 37- [OS/2:] ^C would only work once 38- algdep(.1^5,1,10) --> 1 39- { "a b" } \\ with an explicit \n produced "ab", whereas whitespace in strings is to be retained. 40- inconsistencies in return type from lindep [t_VEC/t_COL]. 41- possible oo loop in ellap [ typo in appell1 ] 42- made PSLQ (algdep/lindep) insensitive to 'realprecision' [use precision of the input] 43- nfinit(x^2-4*3,4) --> SEGV 44- Compilation failure on ORIGIN + Irix: rename 'sgi' --> 'SG' in basemath/galconj.c 45- '\r a' where file 'a' is empty --> "a is not a GP binary file". 46- make sure qflll[gram](x) never fails when x has exact entries [ much faster than qflll(x,1) when the entries are large ] 47- increase subFB sooner in buchall() + add GC in Q_denom { bnfinit(x^8 - 4*x^7 + 462*x^6 - 1372*x^5 + 85789*x^4 - 169296*x^3 + 7540560*x^2 - 7456140*x + 263038707) } took a long time, then overflowed the stack 48- make test-kernel did not work anymore (prototype error in kerntest.c) 49- overflow in u_FpM_gauss (oo loop in ZM_inv for huge matrices) 50- polcoeff(1+O(x^2),1,y) --> SEGV 51- content(y/x) --> 1 [ should be y ] 52- divrem(x,2) --> x/2 instead of [x/2, 0]~ 53- divrem([1.,2],x) --> stack corruption 54- ff(n)=local(v=[],w=[]);n f(n)=n ff(f(n))=n --> error (OK) + SEGV on Linux (same data freed twice) 55- qflll(matrix(2,3,x,y,x+y)) --> SEGV IZ 56- default(primelimit, 2156858852) --> SEGV and other signed/unsigned conversion problems. IZ 57- printtex("x1") and printtex("x_1") gave same output IZ 58- printtex(t_STR) [ protect special characters, eg ~ or \ ] IZ 59- [readline:] support old versions (1.0), try to recover from mismatched headers wrt. library, report version of loaded library in gp header [as opposed to library version at Configure time] BA 60- add "const" keyword to allow building with g++ 61- agm(1+x,2+x) --> oo loop 62- lindep([1,0]) --> error [ problem with trivial cases in PSLQ ] 63- wrong reconstruction bounds in nffactor 64- short help message for isprime/ispseudoprime 65- issquare(t_FRAC or t_RFRAC, &x) did not work [ worked without &x ] 66- nfgaloisconj(x^2+1,4, 0) --> SEGV [ bad input ] 67- typo in quadhilbert(-D): required O(D) memory instead of O(sqrt(D)) 68- all signed/unsigned compiler warnings 69- \p29, tan(Pi/2) --> "division by zero". Made error more explicit 70- nfnewprec(nfinit(x,3)) --> SEGV 71- bnrconductorofchar(0,0)--> SEGV [bad input] 72- qfjacobi( non-square matrix ) --> SEGV [bad input] 73- matmultodiagonal([;],matrix(0,1)); --> SEGV [bad input] 74- [GP, trap:] prevent oo recursion if default exception handler itself raises an exception 75- allow qfbred(,2) [don't update Shanks's distance] also for definite forms [ignore flag]. 76- lex(x,"y") --> error [ should be -1 ] 77- algdep(0,1) --> 0 [ should be x ] 78- log(1, AGM) --> oo loop 79- [Configure+gcc] remove useless -m* arguments from CFLAGS [ obsolete ] 80- improper rounding when printing floats: 1.2 --> 1.199999999 81- [default:] realprecision was allowed to be 0, and then treated as 9. 82- Precision loss in inputs of large exponent: 1e100000 -->9.99999824 E99999 83- quadgen / quadpoly accepted square inputs --> weird bugs later. 84- poldegree(x^2 / y^4, y) --> -1 85- setrand(178);quadclassunit(82421) --> 2 instead of 1 [from 2.2.4:] 86- polroots( Pol(subst([1,0,4*x,0,2*x^2+24,0,16*x,0,16],x,10^2589) ) --> division by zero [ double overflow ] 87- LLL-reduction over polynomial rings (almost always failed) 88- (x/y)*(y/x) --> y/y 89- fix pari_init_stackcheck to avoid bogus "deep recursion" messages on broken machines. 90- reused invalid (gerepile'd) pointer in mat_ideal_two_elt. Changed: 1- "not enough precomputed primes": output largest needed p if available XR 2- factorpadic so that factorback gives back the original polynomial, up to a power of p 3- type of avma, bot, top to 'pari_sp' (pari stack pointer) [does not break existing code] 4- [library:] make floating point assignments round the inputs (used to truncate) 5- ensure proper rounding in divrr/mulrr() [ important for numbers input in scientific format, e.g. 1e20 ] BA 6- moved internals of mppgcd to mp.c/gcdii BA 7- moved internals of genrand to mp.c/randomi BA 8- renamed mymyrand --> pari_rand31 9- bnrstark: use partial factorization of discriminant when (pol)reducing the polynomial [could embark into hopeless factorizations] 10- primedec: improved search for uniformizers when p | index IZ 11- [OS/2:] improve dlopen(NULL,...) IZ 12- [OS/2:] enable dynamic-linking build IZ 13- [OS/2:] use same CFLAGS as under Linux IZ 14- when using external prettyprinter, write in raw format to logfile [not in TeX format sent to prettyprinter] IZ 15- don't output pseudo-TeX sequences to logfile when using external prettyprinter (raw format) IZ 16- make X11.builtin-gnuplot-dynamic the default graphic library. IZ 17- allow changing the gnuplot DLL name for gnuplot-dynamic at Configure-time e.g. Configure --graphic=gnuplot-dynamic,gnpltdrw 18- allow Vecsmall(t_STR) 19- polredabs heuristic (try harder to detect subfields). Ex: try it on polcompositum(x^2 - d, polcyclo(11)); MSo20- simplified polzagier() DS 21- improvements in elltors() [ faster torsion bound, check bound > 1 before checking precision ] 22- minor improvements in plindep() [p-adic lindep/algdep] 23- 'make all' now builds the documentation [ that way, 'make install' need not run a bunch of TeX commands as root ] 24- improved idealaddtoone/idealchinese/idealapprfact [use dedicated HNF variant + simpler uniformizers in idealapprfact] 25- rnfkummer: do not return rational coeffs as POLMODs: -1, not Mod(-1,pol) 26- improved idealval() 27- simplified element_reduce, idealmodidele (redideal), compute_raygen (create bnr.gen): faster, smaller elements 28- new algorithm for conductor() and bnrdisc() [much faster, does not need bnr.gen]: find minimal f such that P_{1,f}(K) \subset H, computations are done for a fixed modulus F instead of computing the image of H in Cl_f(K) for many f | F. IZ 29- improve portability of make_vi_tags (cf 'make ctags') 30- using install() twice on the same symbol now updates the prototype code 31- re-enable ranlib support (disabled in 2.0.13) 32- declare first argument in pariputs[f] as 'const char*' 33- enabled Karatsuba multiplication for t_REAL 34- broken Configure into many smaller files (config/get_*) 35- let gphelp write all cross-references as [label:LABELNAME] (was [??]) IZ 36- cache optimization in initprimes() [ default(primelimit,.) ] 37- Str() now takes multiple arguments as print(). Str(,1) replaced by Strexpand() 38- prototype of strtoGENstr() [remove flag] 39- remove -Wno-implicit from CFLAGS 40- prototype code 's*' now produces a t_VEC of GENs [callee's business to call GENtostr] (used to be a NULL-terminated list) 41- [gphelp:] if perl not available, don't pretend extended help is. 42- try harder to detect precision problems in floating point lllgram 43- [ix86 kernel:] macroified bfffo() 44- made all GEN macros return signed types [ had inadvertently switched to ulong as a side effect of some other change, long ago ] BA 45- split kernel Makefiles in MakeLVL0 and MakeLVL1. BA 46- --disable-kernel Configure option replaced by --kernel=none 47- compute_polrel() [rnfkummer] was very slow for [L:K] > 5 (compute Newton sums directly) 48- simplified fincke_pohst() [don't recompute gram_matrix] 49- faster trueeta(), faster quadhilbert(D < 0) 50- faster isprime (trial divide by small primes, recognize 1-word moduli) 51- ellheight: use Mestre's AGM to compute Archimedean height 52- poldegree(0) is now VERYBIGINT 53- alpha + gcc: compile with -O3 [ since F14 fixed the optimizer "bugs" ] Added: 1- [TeXmacs:] contextual completion () BA 2- routines ishiftr, gfloor2n, isqrti, randomi 3- routine random_bits BA 4- [Configure:] --builddir flag IZ 5- File README.os2 6- Allow nfroots(, P) [ roots in Q ] 7- routines Strexpand(), Strtex() IZ 8- detect oo recursion on OS/2 [as on Unix systems] (cf STACK_CHECK) RS 9- routine numbpart() BA 10- GMP kernel BA 11- --kernel Configure option IZ 12- allow an arbitrary polynomial as a 2nd argument to subst() 13- many files in config/ [ from Configure ] Removed 1- macro definition BITS_IN_RANDOM (useless) 2- appr_reduce() [static base4.c]: lllreducemodmatrix does the same. Faster. 3- [useless,undocumented]: idealoplll, idealmullll, idealdivlll 4- 68k assembler kernel [ unmaintained, obsoleted by the GMP kernel ] %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.4 (released 12/09/2002): Fixed 1- add default 'new_galois_format' to make 2.2.3 C-22 optional (by default, old format will be used, preserving compatibility) BA 2- FreeBSD: DL_DFLT_NAME value was incorrect 3- Configure: TIOCGWINSZ not detected on Linux BA 4- FpV_roots_to_pol not reduced when applied to a singleton 5- (a.x = [a]); "a".x ---> [a] \\ should be ["a"] 6- (a.x = [a]); print("a".x) ---> a0.E-28x \\ should be ["a"] 7- (a.x = [a]); 1.x ---> error \\ should be [1] 8- wrong rnfidealnorm[rel | abs] (wrong result if O_L not free O_K-module) 9- gcd(x + 1, x + 1/2) --> 1 \\ should be 1/2 [introduced in 2.2.1] 10- gcd for multivariate polynomials over finite fields slower than in characteristic 0 11- [library:] typo in vpariputs: pariputsf("%Z%Z",x,y) did not work (prints x and address of y) IZ 12- [gnuplot + dynamic link:] allow building even when dlopen() not available 13- [CVS:] warnings about unknown files (added .cvsignore files) 14- f()=return \\ return "void" g()=return(f()) \\ return eval("void") = 0 now g() returns "void" also 15- f(x=11,y=x)=local(t=ff(),u=t);1 --> parse error 16- conjvec([[],[],[]]) --> SEGV 17- galoisisabelian(x) --> SEGV 18- nfeltreducemodpr(nfinit(x),1,1) --> SEGV 19- idealmul(nf, principal ideal, prime ideal) returned wrong result [introduced sometime in 2.2] 20- elltors(ellinit([...], 1)) --> SEGV 21- try to make sure life of GP variables is not too short. Was: v = [0,0]; v + [v=0,v=0] --> SEGV u = Mod(x*Mod(1,2),polcyclo(25)*Mod(1,2)); sum(i=1,4,u=u^32) --> SEGV 22- typo in to_Fp_simple [ bnfcertify(bnfinit(x^2-40!)) --> type error ] 23- memory leak in gp when handling '&' arguments 24- removed hack in gcopy [ did not reset the isclone() flag because gunclone checks isonstack(). But other routines may want to use it ]. 25- apparent oo loop in bnfcertify [when computing lower bound for regulator] 26- ideallistarch(nfinit(x),[1,1],0); --> SEGV [bad input] 27- factor(x-I) --> x - #<16382> 28- ellsigma(...,matid(1)) --> SEGV [bad input] 29- ideleprincipal([],1) --> SEGV [bad input] 30- factorback(matid(1),nfinit(x)) --> SEGV [bad input] 31- incomplete help message for vecsort 32- polredabs fails to reduce x^8-2*x^7-34*x^6+78*x^5+265*x^4-628*x^3-389*x^2+1237*x-449 [typo in chk_gen_init: skipfirst not initialized properly] MW 33- (recent) typo in localred (char 2) 34- 2.2.3-C20 had broken backward compatibility: restore [inefficient, useless] previous output of nfelt*modpr routines 35- idealappr(nfinit(y),matid(2),1) --> SEGV [bad input] 36- sqrtn(0,...) ---> error 37- galoisinit(x^4 + 5264*x^3 + 8034856*x^2 + 4205424384*x + 504485485632) --> weird error 38- qfsign([;]) --> SEGV MW 39- torsion group of [0,0,0,-6648,208633] reported as C2 instead of C6 40- bnfinit: very rare stack corruption 41- bnfinit: used too much memory when needing huge number of relations [when computing fundamental units] 42- bnrL1(bnr with conductor 1) --> SEGV 43- "impossible inverse modulo ..." when using addprimes() + ROUND 2 MSo44- [gp: \x] missing 'break' statement in escape() 45- wrong bound in nf_LLL_cmbf (nffactor) [no counter example to the old bound, but proof was wrong anyway...] 46- [gp:] memory leak when assigning to multidimensional arrays (x[i][j]=1) 47- added user-friendly error message if Configure not run properly + fix INSTALL.tex about make gp.dbg / gp.prf 48- matcompanion(x*y) --> weird error 49- typos in hilbert(), e.g hilbert(Mod(1,2), y) --> SEGV, hilbert(-1+O(2^3), 12 + O(2^3)) accepted wheras 2-adic precision too low to decide BA 50- [FreeBSD:] PORTOBJFORMAT undefined by the system --> Configure fails 51- rnfisnorm() [errors, SEGV]. Had to change the prototype. BA 52- Oxxx/Makefile was not compatible with BSD make. 53- errors in files read from .gprc, containing trap() --> SEGV 54- bezoutres(Pol(sin(x)+Pi),Pol(cos(x))) --> "bug in subresext" 55- nfsubfields had a different output format when using galoissubfieds 56- polcoeff(1/x, -3) --> SEGV 57- (-2/x)/(-1/x) --> -2/-1 BA 58- [GP internals:] trap() had an invalid prototype [DI,DI] 59- M[,2][1]=1 --> error; M[1,][2]=1 --> no effect [ now <==> M[1,2]=1 ] 60- [GP:] newline in multiline comments /* */ was not ignored 61- [GP:] when using default 'colors' for input at \gn>1, first debugging msg could be colored 62- [GP:] in break loop, trailing ; was ignored (all results were printed) XR 63- smarter precision increase in update_alpha() (ROUND 4) [stick to padics don't go over Z] Ex: factorpadic(polzagier(18,3), 2, 30) much faster than before. 64- E=ellinit([0,0,0,-10301051460877581926458079712219,-12725370882271967125361344545020920373899020890]); ellap(E,1167254453) --> wrong result 65- factor(x^2 + I*1.) --> SEGV 66- when printing x < 0 t_REAL, was rounded in the wrong direction 67- [WINCE port:] small and SID are already defined in windows.h Changed 1- remove most global variables from gp.c (put them in struct gp_data). 2- use better bounds for size of factors in nffactor() 3- tuning for van Hoeij's factorizer (factor + nffactor) nffactor: call factornf when deg(pol) << deg(nf) + remove a priori overlift for d-1/d-2 test [major overkill] 4- automatic concatenation for strings: use longest match for expression. print("a"[1]) is not valid since "a" is not a vector print("a", [1]) prints 'a[1]' IZ 5- [gphelp:] allow uninstalled operation from $TOPDIR or $TOPDIR/Oarch IZ 6- [gphelp:] better error messages in case TeX compilation fails 7- [development version:] add version number for this file to the gp header when using CVS IZ 8- [library:] unified access to diffptr (NEXT_PRIME_VIADIFF macro) 9- buchall: re-use the same random seed when doubling prec (for units) 10- major cleanup in thue / thueinit 11- major improvements in rnfkummer (use elements in factored form): much faster, give smaller elements, allow arbitrary prime degree 12- improved quadray(D < 0) when relative degree is huge 13- improved bnfisprincipal when class group large: use factorisation (+idealred) instead of arch. components (require much less precision) 14- [library:] allow trapping invmoder and recovering the offending INTMOD 15- improved factor over Z[X] for _huge_ degrees (factorizations mod p) 16- change in ordering for primedec output [use cmp_prime_over_p] 17- [library:] moved (formerly) gp-specific write* and print* to libpari 18- input format to rnfisnorm() [use rnfisnorminit] 19- [GP:] break loop prompt from '>' to 'break>' 20- [GP:] don't get out of break loop after \r 21- type f(x=1)=; twice ---> x = 1 22- [trap:] the way default error handlers operate, how to get out of break loops (see section 2.7 of manual) Added BA 1- Add PARI_VERSION and PARI_VERSION_CODE to paricfg.h BA 2- Add pari_release at top of dft.Config.in 3- rnfpolredabs: flag to use partial factorization 4- [gprc:] test against VERSION number in .gprc 5- [gprc:] multiline constructs IZ 6- mnemonics for flags 7- internal flag nf_GEN_IF_PRINCIPAL to bnfisprincipal [isprincipalall] 8- routine rnfisnorminit() BA 9- [Makefile:] bzdist target 10- [library:] CATCH / TRY mechanism [ encapsulate err_catch ] Removed 1- (useless, undocumented) macros buchgen*, buchinit* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.3 (released 10/06/2002): Fixed 1- bnrinit(bnfinit(subst(polsubcyclo(89,8),x,-x)),4) --> SEGV [make sure isprincipalfact is used in makecygen, even in case of precision problems] 2- bnrisprincipal --> warning + "not an element in ..." [missing nf_FORCE] 3- oo loop in isprincipalfact when increasing bnf precision 4- stack corruption in ellap (LARGE p) 5- zeta(s) destroyed the Bernoulli cache when using the functional equation 6- oo loop in random_relation (called from bnfinit) 7- fixed lower bound for p in nfsubfields (could get oo loop: pol never squarefree mod p) 8- [Vecsmall([1, 2])][1][2][1] --> SEGV 9- typo in t_FRAC + t_PADIC [only numerator of t_FRAC used] 10- factorback(t,nfinit(x)) --> SEGV IZ 11- shift(x > 0,, flag!=0) didn't act as the docs said [flag now ignored] 12- lindep(Vec(x^48)) --> oo loop 13- could get NaN in max_modulus (polroots) --> havoc later 14- missing normalizepol() in centermod(t_POL,) 15- [Follow-up to 2.2.2-F10] even more recent pdftex failed again 16- not enough GC when printing a huge t_PADIC 17- factorpadic(x*(x+1),3,10) would corrupt polx --> SEGV later 18- delayed carry treated improperly in red_montgomery 19- F() = 0; local(x) ==> confusing error message IZ 20- OS/2: make bench didn't work [env wouldn't start shell scripts] BA 21- sqrtn(Mod(1,7),2,&z)-->z=1 should be -1 HC 22- Standard transcental functions exp, sin, cos, ^, *, are now orders of magnitude faster for t_POL arguments of small degree. HC 23- fixed a severe bug in p-adic/integer addition (1+3^4+O(3^10))+3 didn't work. HC 24- Corrected p-adic initell. 25- ellj / eta (t_SER) truncated result to seriesprecision 26- possible overflow in u_FpM_gauss (from ZM_inv) 27- various problems with C++ compilers 28- polredabs could fail to reduce "obvious" input, e.g x^2 + n*x + n^2 29- gcd(x,y,1) didn't check its arguments 30- typo in elltors: could forget a point of order 2 31- gdivgs(t_RFRAC,x) incorrect (if numerator had denominator) 32- serreverse(O(x) or x + O(x^2)) --> SEGV 33- dbltor(0) returned 2^-308, instead of 10^-308 34- precision problems in thue/thueinit setrand(5);tnf=thueinit(x^3 + x^2 - 43690*x - 3529208) --> error in mplog 35- typo in bnfnarrow ("impossible inverse") 36- subst(x,x^0,x) --> floating point exception ISo37- many typos in the documentation 38- [DOS/Windows]: incorrect conversion between 'double' and t_REAL 39- polrootspadic(4*x^2-1,2,2) --> impossible inverse: Mod(2, 16). [specific to 2, and non-monic equations] 40- discrepancy between bnfsunit output and docs [ bnfS[5][2] was t_MAT ] 41- matdet: pivoting strategy incorrectly chosen ("incorrect type in gexpo") 42- polcompositum output ordering depended on random seed 43- plotrecthraw(0,[0]) --> SEGV 44- plothraw([],[]) --> SEGV IZ 45- ix86 inline assembler compilation problem [divll] XR 46- forgotten case in Round4 [ nfdisc(x^12-10*x^11-57*x^10+740*x^9+353*x^8-16130*x^7+17749*x^6+100120*x^5-108466*x^4-292200*x^3+128380*x^2+380800*x+133112) --> impossible inverse: Mod(2, ...) ] 47- sin(1e-100) ---> 9.999999999999999999735998397 E-101 [ precision loss ] 48- idealpow(nf,x, n < 0, 1) did not reduce the result 49- gcd(0, -1) --> -1, content([0, Pi]) --> 3.14, content([0,Pi,Pi]) --> 1 BA 50- compilation problem on OSF (RTLD_GLOBAL undefined) BA 51- [X-Windows] hi-res plot: window not redrawn properly (BackingStore pb) 52- problems with tex2mail output (wrong alignment, wrong colors) 53- contfrac(sin(Pi/4),,2) --> impossible assignment 54- oo recursion in gaffect(t_POL, scalar) 55- content([-1]) was -1 [ should be 1 ] 56- stack corruption in u_FpV_polint (used by modular bivariate resultant) 57- polroots() used too high a precision when checking errors a posteriori (--> slow) 58- contfrac(1/x) --> SEGV 59- typo in sinh(0) --> wrong zero exponent 60- exp(O(x^-1)) = O(x^(-1)) [ouch...] 61- dilog(O(x^10)) = O(1) 62- cosh(O(1)) --> division by 0 63- sqrt(4*x^2) --> not an integer exponent for non invertible series in gpow 64- besselj(0,O(1)) [or besseli] --> precision<=0 in gprec. 65- O(1)' --> O(x^-1) 66- gcd(O(2^1), O(2^10)) --> O(2^10) 67- polrootspadic(x^2+8*x+4,2,2) --> "impossible assignment" 68- one could write() an object to a binary file, corrupting it MW 69- ellap(ellinit([0,0,1,-7077,235516]), 1075060289) --> "zero argument in an arithmetic function" MW 70- ellap(ellinit([0,0,1,-7077,235516]),1135392007) --> SEGV BA 71- user's manual index truncated if LANG=fr_FR 72- lex(string1, string2) could return something not in {-1,0,1} 73- bnfisprincipal(bnf,x, 0) was not instantaneous when bnf.no = 1 74- no GC in poleval 75- make clean did not remove libpari-2.2.* 76- incorrect result in gaffsg(s < 0, t_PADIC) [ wrong valuation ] Changed BA 1- improved Fp_isom IZ 2- remove all dependance on __OPTIMIZE__ for inlining [cf 2.0.14 F-24] 3- implementation of psi() [very slow + wrong results at low accuracy] 4- cleaned up forvec() [no more global variables] 5- improvements in bnrstark (precompute common data) BA 6- improved ffinit() 7- rewrote time-critical parts of bnrstark 8- all 'input filter' code removed from GP. es.c:filtre() now handles the full filtering [and has become reentrant] 9- isprime() now guarantees primality BA 10- improved polsubcyclo() BA 11- new interface for galoissubcyclo HC 12- gamma function for integral/rational arguments 13- faster factornf / nfgcd 14- removed readline-specific code from gp.c 15- allow bnrstark over Q 16- 'subgroup' argument made optional in bnrL1, bnrstark, rnfkummer 17- use relative van Hoeij algorithm in nffactor [can handle huge number of modular factors] 18- rewrote factorff() to use new modular functions 19- rewrote primedec() to use new modular functions 20- rewrote most *modpr functions 21- modified diagnostics for integral LLL to match floating point version 22- INCOMPATIBILITY: polgalois(); changed 3rd component of result so that it gives the numbering among all transitive subgroups of S_n [ was ad hoc up to 7, then as described above for n >= 8 ] 23- INCOMPATIBILITY: nf.zk is now T2-LLL-reduced 24- idealtwoelt was very slow when a small prime with many divisors divided the index (use approximation theorem) 25- content(scalar) = abs(scalar) [when it makes sense] 26- changed the interface to ispseudoprime and isprime 27- [internal] element_muli: check input is consistent 28- rewrote all LLL algorithms (use Householder, not Gram-Schmidt; do not use Gram matrix; unified code). 29- INCOMPATIBILITY: the internal components of nf[5] have changed (MC and T2 not needed anymore) 30- INCOMPATIBILITY: [library] polred & polredabs do not take a 'prec' argument anymore 31- unified nfinit, polred* [use dedicated structs internally] 32- rnfconductor(..., 1) doesn't need GRH anymore 33- extracted FpXQ_gener from idealstar 34- allow more types in gdivround 35- improved root_bound (first step in factor() over Z[X]) for huge pols. 36- faster bernfrac / bernvec 37- INCOMPATIBILITY: removed gentimer() / genmsgtimer(). Use TIMER/msgTIMER 38- let nfsubfields call galoissubfields (much faster when field is Galois) 39- Configure (locatelib): don't look for lib*.so.x [ pb on Linux with [readline | ncurses]-devel.rpm. Added 1- mplog2() function --> faster mplog() 2- gcd for Gaussian integers HC 3- APRCL primality test 4- (strong) Lucas primality test + Baillie-Pomerance-Selfridge-Wagstaff test BA 5- Facilities for permutation groups (perm.c). BA 6- New functions galoissubgroups, galoisubfields. HC 7- Implemented all Bessel functions J, I, N, K, H1, H2, and Bessel functions for power series and polynomials. HC 8- Implemented PSLQ [preliminary] GTo 9- Implemented Cipolla's algorithm for sqrt(Mod(x, p)) 10- library functions FpM_ker, FpM_deplin, diviiround, centermodii 11- library function gerepileall 12- library functions corepartial, core2partial 13- library functions affui, itou, stor, itor 14- library function lllint_ip (in place) 15- library functions Q_primitive_part, Q_primpart, Q_remove_denom, Q_denom 16- allow polredabs to use a partial factorisation of disc(nf) [as polred, but inconsistent values for flag. Backward compatibility problem here...] 17- routine ellminimalmodel() IZ 18- systems/ directory (currently for OS/2 only) IZ 19- [OS/2:] install() for OS/2 system (using builtin dlopen) IZ 20- gnuplot and X11 are now simultaneously supported %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.2 (released 10/01/2002): Fixed 1- qfbred(Qfb(4, 17, 18)) --> SIGFPE 2- broken compilation in arith.c when CC != gcc 3- nfhilbert (local case pr | 2) expected POLMOD argument without check 4- poldegree(P, t) slow when t != varn(P), and may not work in library mode 5- polrootspadic only worked when leading coeff was a unit 6- paddicappr was very slow (esp. when p was large) 7- Configure: check for 'double endianness' [used for double --> t_REAL conversion]. Previous check was failing on ARM architecture. 8- forsubgroup state not properly restored after ^C 9- libpari.so included symbols from libc without linking it explicitly (Debian requirement, and cleaner anyway) 10- recent pdftex failed to compile users.tex (\pdfannotlink undefined) 11- !nf.sign[1] was parsed as (!nf.sign)[1] 12- matrix(0,1) --> "identical index variables in matrix" [from 2.2.1 F48] 13- bnfinit could miss some relations in the "small norm" phase 14- x % y incorrect when y < 0 inexact (2 % -3. --> -1.) 15- typo in gcdreal (result < 0) [introduced in 2.2.1] 16- some obscure problems in rnfkummer 17- not enough GC in hnflll 18- sqrt(25 + O(2^5))^2 - 25 = O(2^4) 19- not enough GC when writing a t_PADIC 20- user member functions were very slow (unnecessary copy) 21- cd Oxxx; make -j4 bench ran things in the wrong order 22- poltchebi, pollegendre gave bogus output for negative degrees 23- possible SEGV or oo loop in polrootsmod when p not a prime 24- nfnewprec(bnf) could change bnf.gen (due to round-off errors) 25- SEGV in gcd(x,y) when operands have coeffs of the form Mod(t_INT,t_POL) 26- not enough GC in poldivres (= t_POL % t_POL) 27- issquare(Mod(3,27)) = 1 [from 2.2.1 C 10] 28- [BUG] message in 'elliptic' bench [made polroots more canonical] Changed 1- allow compressing *.dvi files for the online help system 2- index bound was restricted to MAXLONG in subgrouplist. Made it a GEN 3- try to guess correct precision earlier in polgalois/polroots 4- allow GP pointers to 'matrix components', e.g issquare(25,&x[i][j]) 5- changed assignment semantics to make it closer to C: x = y understood as (evaluate Y:=y, then set x:=Y), e.g i=0; i += (i=2) sets i to 4 (was 2) 6- output VECSMALLs as 'Vecsmall([...])' 7- more efficient polcoeff [also: made it independent of MAXVARN] 8- retuned bnfinit (let subfactorbase increase further): setrand(1);bnfinit(x^4 + 1159*x^2 + 335241) would never finish. 9- specified precisely lex() [see manual]. Now: lex([0,0],[0]) = 1 (was -1), lex(0,[0]) = -1 (was 0) 10- allow factorback(x, e) for prod x[i]^e[i] 11- don't store empty lines in history [cf 2.2.1 F57] 12- extend x \ y, x \/ y and divrem(x,y) XR 13- improvements in bnrstark (try harder to find modulus, need less memory) 14- global(x): ignore if x already global (used to raise a warning) BA 15- install: add RTLD_GLOBAL to dlopen flags [so that symbols can be used in other .so] 16- removed hack in gp_init.c [used "constant default args" to call print0] Added BA 1- New function 'vectorsmall'. 2- allow setting variable in divrem 3- GP operator #l for length(l) 4- a warning in zsign ("increase precision?") when dubious result 5- Montgomery reduction (only used in powmodulo() for now) 6- [experimental] basic tuning utilities (src/test/tune.c) [make tune] %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.1 (released 18/10/2001): Fixed 1- typo in factornf (factor of degree 3 --> error message) 2- rnflllgram(), idealinv() didn't check their arguments 3- [readline] \r would complete using files matching r* 4- wrong result in ZY_ZXY_resultant when degree dropped in ERS 5- factor(x^2 + I*1.) --> stack corruption 6- \r directory was silently accepted 7- check arguments in polcompositum() TH 8- [Cygwin:] fixed paths for readline on cygwin 1.* XR 9- possible overflow in ComputeCoeff [ bnrstark() ] 10- numtoperm(2,x) --> SEGV [check arguments now] 11- rnfkummer could fail with "missing units" 12- factornf(P, non-monic t) --> error 13- forsubgroup/subgrouplist didn't check their arguments nor accepted SNF matrices XR 14- typo in nilord4 --> SEGV, e.g. nfdisc(x^16-363*x^14+53550*x^12-4091823*x^10+170172414*x^8 \ -3663509067*x^6+33703350345*x^4-63300912912*x^2+32451860736) 15- some messages didn't distinguish between MBytes and millions of Bytes 16- typo in BuildTree [hensel lift]: SEGV 17- (rare) oo loop in polroots, e.g. x^5-2*x^4-32*x^3+72*x^2+218*x-491 18- oo loop in ellpointtoz on certain rare inputs 19- stack corruption in factorff BA 20- better interface for galoissubcyclo BA 21- galoisfixedfield(,,2) now works with non Galois subfields BA 22- nfgaloisconj now use `d-1'-test + better strategy BA 23- fix accuracy problems in vandermondeinverse 24- missed some simplifications when handling multivariate t_RFRAC 25- [Cygwin:] incorrect default 'path' (used : instead of ;) 26- element_sqr didn't check its arguments (SEGV if bad input) 27- possible stack corruption in polroots (+ improved GC there) 28- typo in nfsubfields (incorrect bound: could miss a subfield) 29- typo in zsimpjoin (concat error in bnrdisclist, intr. in 2.2.0) IZ 30- typo in Configure [rl_save_prompt and _eprintf not found in target libs] MD 31- oo loop in ellap [uninitialized array length in apell1] 32- stack corruption in addfrac [wrong result for large denominators] MD 33- resmod2n [called from powmodulo] could return unnormalized integers 34- not enough GC in nfinit for huge degrees [get_mul_table] 35- intformal(1/2/t^2) --> apparent oo loop 36- polredabs(degree 1 polynomial) --> x [could be very slow] 37- polredabs() could use a basis which was not LLL reduced BA 38- pariformats (e.g %Z) incorrect on 64bit machines 39- polhensellift(x,[x,1],2,2) --> "bug in multiplication" 40- glitches in readline completion (random() * ne inserted args) IZ 41- CLK_TCK may reside in time.h 42- misleading definition for ?omega / ?bigomega 43- on \q, "Good bye" --> Goodbye 44- install() accepted gpnames which were not valid identifiers 45- bnfinit(x^4+65,,[.1]) --> SEGV (whenever c < c2) 46- when host badily configured (~ not expanded), gp would die on startup XR 47- factorpadic(, not a prime, ) --> SEGV 48- matrix(2,2,i,i, ...) allowed, with weird result BA 49- better arguments checking for galoisfixedfield 50- psi(I) --> incorrect type in rtodbl XR 51- increase precision automatically when needed in quadhilbertreal 52- idealstar(bnfinit(polcyclo(5)),11).clgp --> stack error 53- default(format,"g0.4"); 3./10 --> 0.300004577 [now: 0.3000] 54- subst() didn't check its arguments (e.g SEGV on t_STR) 55- qfbclassno(x < 0): wrong algo when x non fundamental 56- obscure bugs with types FRACN/RFRACN [when simplifies to INT/POL] IZ 57- readline history: while inputing continuation lines, the partial command was not put into history until full command was run 58- not enough GC in polroots (dft) for huge degrees 59- Cygwin: don't try to build gp-dyn.exe [crashes] 60- use vsnprintf to fix a long-standing bug in PARI output (using formats) used a fixed-length buffer that could overflow. If vsnprintf is not found by Configure, the bug remains. Changed 1- removed useless parameter prec in many bnr* and rnf* functions 2- major update of bnr* functions [use elements in factored form] 3- use /tmp instead of /var/tmp as default tmp directory [faster on Solaris] BA 4- Fp_PHlog (Pohlig-Hellman) can use a factorization of the subgroup order 5- major update of buchall() [bnfinit]: accurate precision increase, use multiplicative archimedean components (fewer logs), cleanup 6- [libpari:] rename permute/permuteInv to GP names numtoperm/permtonum 7- scalar + [;] --> error [made it [;]] BA 8- factorback, chinese, lcm and gcd now accept a single vector 9- Use I \cap Z instead of NI in hnfideal_inv 10- improved issquare(t_INTMOD) 11- improved subresultant routines (new function pseudodiv) 12- command-line options to Configure (installation directories) 13- rnfequation: use modular (bivariate) resultant 14- polynomial gcd (srgcd): uses modular algo (modulargcd,nfgcd) if possible 15- unified internal hnf* functions 16- improved nfsubfields [Hensel lift, allow nfsubfields(pol) instead of nf] 17- merged all "integer logarithms" + "safe ceil" functions (mylogint, get_e, floor_bound, myceil) 18- readline: TAB on empty parentheses following a function name has the same effect as M-h (used to insert args). IZ 19- faster computation of prime number table [better cache use] IS 20- obscure compiler bug in rootpol.c:max_modulus() [don't modify tau] 21- make bench ('elliptic'): explained [BUG] message 22- allow lift(t_PADIC) 23- faster polroots for Q of the form P(x^k) 24- allow subst(t, x^n, x) 25- ?user_fun: do not include function text if help available from addhelp [always include it for ??user_fun] 26- default values for used defined function arguments are evaluated when the function is called [used to be "when it's defined"] 27- allow subgrouplist(znstar(5)) [didn't accept groups in general form] 28- taught GP about GP2C-style type declaration [ignored] 29- 0. [realzero()] is now coded on 2 words (was 3, with third one ignored) IZ 30- readline history: lines are remembered as they were input (whitespace was deleted) Added BA 1- function pith() [= pi(x), naive implementation] 2- new target for Makefile: gp.dbg BA 3- library functions FpX_roots_to_pol, FqX_roots_to_pol BA 4- library function FpX_FpXQ_compo (Brent & Kung) 5- library function FpM_inv, FpM_gauss, ZM_inv, QM_inv 6- library function primitive_part IZ 7- readline: allow switching readline editing on/off [for commandtools] IZ 8- readline: F1 has same effect as M-h, and F1F1 as M-H (short/long help) 9- function writebin XR 10- new error message "precer" (precision too low in...) 11- allow minimal handling of t_VECSMALL under GP IZ 12- add error messages (as in err(shier2)) to emacs tag file 13- add error messages (as in err(shier2)) to vi tag file IZ 14- add flag to shift() to enable consistency with 2-complement semantic IZ 15- default 'prompt_cont' for continuation lines IZ 16- default 'readline' to switch readline on/off in readline-able binaries IZ 17- capabilities to 'bittest' (return bitmap, 2-complement arithmetic) GH 18- inline assembler micro-kernel for alpha + recent gcc (at least 2.95.3) Removed 1- obsolete functions twototwo, threetotwo, threetotwo2 XR 2- error message truer2 (superseded by precer) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.2.0 (released 30/04/2001): Fixed BA 1- gpflog could print some lines twice 2- return() could forget objects on heap 3- polhensellift didn't accept factors which were not squarefree 4- Configure missed some shared libraries (when only .so.version was there) 5- possible symlink attacks against mpqs() 6- internal requests for precision of bnfinit(x) [ = Q ] could yield SEGV 7- compatible = 3 not taken into account when reading a file 8- cbezout(0,0) = 1 (should be 0) 9- when lines > 0, output driver didn't reset properly after user output 10- nfdisc(x^5+2*x^4+3*x^3-3*x^2+122*x-1) --> impossible inverse 11- bug in gcc-2.95 -O3 -fomit-frame-pointer [Linux]: SEGV in quicksqri 12- addrfrac: could return a t_RFRAC whose denominator wasn't a t_POL 13- bnfcertify (zimmertbound): off by two error when reading bound 14- very inefficient Hensel lift (used ideas from Shoup's NTL) 15- incorrect assumption on factor degrees in polcompositum (SEGV in rare cases) 16- Vec(VECSMALL) --> incorrect object 17- galoispermtopol didn't check permutation length (--> SEGV on bad input) XR 18- rnfinit(nf, T) -> bug in multiplication if nf = Q 19- Pol(cotan(x)) -> SEGV 20- factor(tough polynomial over Z[X]) --> possible SEGV when padic precision is increased [e.g factor(polzagier(60,0))] XR 21- bug in ideal bound computation in rnfnormgroup 22- bnrisprincipal(...,y+z) --> SEGV 23- GP could forget about a function whose redefinition was stopped by a syntax error (sometimes with a delay!) 24- bnfisnorm result would include pols in MAXVARN: e.g. Mod(1, #) BA 25- pbs in Fp_factor_irred (factoring over Fq a pol. defined over Fp) 26- missing macros for gphelp (tex-mode) in chapter 5 27- nfsubfields(nfinit(polcyclo(13))) --> impossible inverse Mod(0, 29) 28- argument checks for element_mulid, nf_get_r1 (access to nf.sign) 29- typo in quadhilbertimag (SEGV for very large discriminants) 30- wrong precision used in numerical derivation BA 31- isprime(n < 2, 1 or 2) gave wrong result IZ 32- \r C:\a.gp wouldn't work [ : and \ forbidden... ] BA 33- bad PARI prototypes in init.c [were confusing GP2C] XR 34- nfdisc: fixed cache system in nilord (esp. precision handling) BA 35- nfgaloisconj(polcyclo(40)): accuracy lost nfgaloisconj(polcyclo(11)+1): oo loop IS 36- typo in squfof tuning on 64bit machines 37- -lm doesn't exist on MacOS X BD 38- typo in src/kernel/l0asm.c: ulong not recognized by MSVC IZ 39- TeX quasi-parsing in gphelp 40- ^C in gp would kill an xdvi launched by gphelp via ?? [detach from tty] 41- factor(P in Z[X]): wrong bound used in LLL_cmbf --> "no factor" 42- one extra blank line printed with some error messages [errcontext] 43- no typechecks in subgrouplist and forsubgroup 44- round4 [dbasis]: make sure polmodi gets a polynomial, not an int (SEGV) 45- various typos in rnfkummer (SEGV or 'non-maximal rank in nfhermite') 46- Configure -l (no argument) didn't work anymore BA 47- incorrect quoting in src/make_vi_tags (make ctags) 48- 1/[;] --> error, whereas [;]^-1 --> [;] [ now, allow 1/[;] ] 49- ??real only gave the help on t_REALs, not on real() 50- eigen: "missing eigenspace" [roundoff pb in ker() compared to exact 0] 51- error messages on GP metacommands (\...) indicated wrong context 52- bnr functions might fail with "indefinite matrix in lllgram" [prec pb] 53- nfhilbert(nf,a,b, pr | 2) would give bogus result if nf in variable 0 (x) MD 54- real(1 / (a+quadgen(...)*b)) was a / (a^2 + b^2) [assumed quadgen(-4) !] 55- wrong HNF (reduction not finished) when nblines >> nbcol [hnf(,0) only] 56- rare problem in isprincipal (large non Galois base field)--> wrong result (generators not required) or oo loop. 57- compatibility problems with readline-4.2 (build would fail) BA 58- pari format %Z (pariputsf) treated incorrectly on 64bit machines XR 59- typo in smallvectors (polredabs): possible oo loop Changed 1- DOS distribution archives (GPM removed) XR 2- round 4 algorithm: compute characteristic polynomials via Newton sums XR 3- nffactormod now calls factmod / factmod9 when possible XR 4- don't compute discriminant in nffactor/nfroots + better bounds in nfsqff 5- input loops rewritten (filtre more flexible + unified common code) 6- better modular arithmetic for polynomials (+ uniformized names) 7- bnfinit: "looking hard" part overdone in random relations. Tuned down. XR 8- added flag in rnfconductor to check extension is abelian (under GRH) 9- made Vec("pari") return ["p","a","r","i"] instead of ["pari"] 10- renamed library function gsize() to sizedigit() [conflict with gtk] XR 11- bnrstark: check if N0 is too large (=> computation impossible) IK 12- let readGEN() return NULL when EOF is met (was oo loop) 13- algorithm for zeta(), gamma() [initial GP code by HC] 14- improved rnfnormgroup() [reduce number of calls to isprincipal] IZ 15- flags for OS/2 build + use generic [pre|suf]fix for object files IZ 16- readline: hit_return() would not work after Esc-H extend online help recognition capabilities (Esc h/H, F1) 17- install the whole distribution (see ?12) 18- clean up in the bnrdisclist ray class group internal functions 19- naming scheme for development versions library: libpari-2.2.so.0.0.0 20- new Configure flags --share-prefix, --host 21- allow library functions to return NULL to the GP interpreter 22- let A^-1 and 1/A return a left inverse of A if it exists [A had to be square] 23- retuned factorization over Z[X] (+ "d-1 test" in naive recombination) 24- sort factorpadic() output Added 1- files README.WIN, config/[arch-osname|locatesymbol], doc/tex2mail.1 GN 2- Jebelean extended gcd + rational number reconstruction XR 3- new flag to rnfconductor (check extension is abelian) IZ 4- set of default colors (boldfg) 5- modular polynomial arithmetic ([uni|bi]variate resultant over Z, characteristic polynomial of algebraic numbers, nfgcd). [undocumented, experimental] 6- Pohlig-Hellman discrete log over Fp and nf.zk / pr BA 7- flag to galoissubcyclo (also output conductor) Changed 1- start using the new modular functions [polcompositum] BA 2- sqrtn, aka mpsqrtnmod (modular n-th root) uses Fp_shanks now Removed 1- obsolete undocumented functions oldidealinv, idealinv0 2- buggy function hnfhavas (hnflll is a better alternative) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Done for version 2.1.0 (released 17/11/2000): Fixed 1- non portable \e in es.c (pb with Sun cc) 2- ^C while prettyprinter in action --> gp crash 3- polresultant(a,b,x,2) --> b 4- exp(log(1.+x+y)) --> division by 0 TH 5- support cygwin version 1 6- TeXmacs interface 7- GP parser codes (sqrtint, idealprimedec) 8- trap (break loop) + NO readline + ^C at input time --> exit. 9- qfminim(,,,1) --> nonsensical result (typo) 10- SPARC + gcc-2.97 --> bug in addsmulsi (register reset too soon) 11- trapping allocatemem() could crash GP Changed 1- release PARI under the GNU GPL. Remove COPYRIGHT file, add COPYING =========================================================================== Done for version 2.0.21 (released 27/10/2000): Fixed 1- trap(gdiver2,a,1/0) trap(,a,1/0); trap(gdiver2,a,1/0) --> crash 2- lllgramintern could reduce a wrong lattice (after precision problems) XR 3- not enough GC in bezout() 4- use hnfmodid in ideallllred (work mod I \cap Z, not mod N(I)) IS 5- C++ compilation problem (compl is a C++ operator + casts) 6- factor(x^2 - 16810110*x + 62994937599000) --> division by 0 BA 7- Pocklington-Lehmer didn't stop factorisation after sqrt(N) 8- exp(log(Pi+x+y)*1.) --> SEGV (still gives an error, but a decent one) 9- factorff needed a prime field F_p where p was single precision 10- more digits than were significant could be printed (ex: precision(Pi,1)) 11- rnfisnorm didn't accept vectors on Zk basis as argument 12- [cygwin] fixed timer (always returned 0) IS 13- function prototypes (missing 'extern') 14- quadray(bnf, ...) didn't work when bnf.disc < 0. Could also return a relative equation over an intermediate field 15- deficient argument checks: asinh(2*x-1), agm(1,1-x), zetakinit(2*x-1), idealinv( , wrongtype), nfnewprec([2*x-1]), thueinit(non-monic or degree 1), lcm(x, 0) rnfidealmul(2*x-1,0), galoisfixedfield(2*x-1), qfbnupow(2*x-1, 0), polred([x,x]), bezout(Mod(x,x^2+1),0), numtoperm(-1,0), polred(nf), idealhnf(nf,y+z), factorpadic(,y,), nfelftreduce, rnfsteinitz, idealappr(not an nf, ...): SEGV 16- check variable numbers in algtobasis: nfalgtobasis(nfinit(P(y), x)) 17- factorcantor(x^4 - x^3 - 2*x - 1, 3) --> SEGV [typo!] 18- matsupplement(non-exact entries): fixed zero test (--> |x| < eps) 19- precision(I*1.) --> +oo (should be realprecision) 20- global() could check uninitialized memory 21- default(prettyprinter,"non-existent-file") ---> SIGPIPE and GP crash 22- gamma(1+O(3^2)+x) --> SIGFPE 23- typo in cxgamma (gamma(-4.1+Pi*I/2) --> exponent overflow) 24- Odos/paricfg.h defined PARIINFO incorrectly 25- inconsistenty t_POLMOD specification: Mod(x,y)+16 --> invalid object 26- bnfsunit error (impossible I-->S) when large class group 27- qfminim([;],...) / qfperfection([;]) --> SEGV 28- idealpow(,,,1) only reduced at the end, not after each multiplication 29- typo in zbrent (always used bisection) BA 30- cotan(x) wasn't accepted 31- wrong internal prototype for thetanullk (prec not taken into account) 32- various bugs in gphelp -detex (??\a) 33- trap + ^C + next would interrupt \r or read() IZ 34- external prettyprinter incompatible with colors 35- idealval used much larger numbers than necessary 36- sqrtint very inefficient (computed with full precision all along) 37- bnfisprincipal couldn't deal with some non-Galois fields 38- listcreate allowed creating longer lists than GP could later handle 39- INPUT colors was "leaking out" (affected status messages) 40- idealpowred(, power > 2^32) --> wrong result 41- when lines > 0, output driver didn't reset properly after overflow 42- huge precision losses in bnfinit computations (--> truncation error) 43- mateigen([1,2;3,4]) wouldn't work at default precision 44- leftover debugging statements in gphelp -to_pod 45- zeta(x) didn't always use the precision of x (contrary to the other trans. functions) 46- some Warnings from MIPSPro 7.2.1 compiler (contributed by PM) BA 47- gdiv(SER,POL) --> SEGV when POL has lgef < lg 48- check relative pol is monic before calling a rnf* function XR 49- cleaned up bnrL1 character computations XR 50- round 4: possible problems when increasing p-adic precision 51- stack corruption in mppgcd(huge t_FRAC, huge t_FRAC) BA 52- abs(t_SER) not allowed 53- nfdisc(non monic polynomial,, disc factorization) returned wrong answer 54- rnfidealnormrel(rnfinit(nfinit(y^2-2),x),2) --> SIGBUS 55- hardcoded paths in a few scripts (tex2mail, gpflog, make_vi_tags) Changed BA 1- more efficient quadratic Hensel lift 2- made ya optional in polinterpolate BA 3- more efficient factorff when pol belongs to Fp[X] (based on Fp_isom) 4- catch SIGFPE 5- made poltchebi efficient 6- write all real zeroes in exponential format (0e28) in format 'g' 7- bnfsunit: try to compute S-units even when the class group is large reduce class group generators 8- 0.e N now inputs a real 0 of decimal exponent N (was N-defaultprecision) 9- try to avoid errors due to precision loss (while computing archimedian components) in bnfnewprec/bnfmake 10- restore \o2 to previous meaning, use \o3 for alternate prettyprinter 11- normalized output of idealfactor (sort factors) 12- better TeXization (\left / \right) 13- allow color changes in error messages (when sample input is given) 14- format for bnf[9] (new isprincipal) 15- cleaned up isprincipal + bnfinit (small_norm, getfu, class_group_gen) XR 16- added flag for D>0 in quadhilbert: if non-zero, try more modulii 17- idealred: reduce huge ideals as Z-module first (using lllintpartial) 18- TeXmacs interface Added 1- library function zerovec 2- van Hoeij's algo. for modular factors recombination (factor over Z[X]) 3- algdep for p-adic numbers IZ 4- default values for 'colors' (light/dark) and 'prettyprinter' (tex2mail) 5- hnflll implementation (old one was preliminary and didn't work at all) GN 6- squfof implementation 7- numerical derivation XR 8- GP interface to hensel_lift functions (polhensellift) Removed 1- quadrayimagwei, preliminary implementation to quadray(D < 0) =========================================================================== Done for version 2.0.20.beta (released 07/06/2000): Fixed 1- gp -p1e -->SEGV 2- nfinit([x,1]) --> SEGV 3- ensure stack large enough [allocatemem(1) painted user in a corner] 4- make sure mpinl.o is linked (binaries may fail to build otherwise) 5- make sure sqrt(Mod(a,b)) terminates 6- memory leak with PARI pointers (issquare(4,&x)) 7- 'make clean' didn't affect doc 8- Configure didn't detect some SuperSparc + Linux combination 9- forprime (and friends) could crash when loop index was tampered with 10- trap(, -1, (1/0)) == -1 ---> -1 (analyseur not reset) XR 11- bnrstark initializations (incorrect when field not totally real) 12- member functions not very robust [e.g. ellinit(e,1).roots --> SEGV] 13- compiler warnings (gcc -O -Wall) 14- trap() not robust enough in library mode (nested handlers) 15- (x^2+3)/(2*x)*x --> invalid RFRAC 16- factorpadic result used too high a precision (+improved handling of nonmonic polynomials) 17- sqrt(Mod(0,1)) --> oo loop (+ improved a bit mpsqrtmod) 18- no GC in norml2 IZ 19- tex2mail had difficulties with rational functions 20- (rare) SIGBUS in quadclassunit(non-fundamental discriminant) 21- g()=f()==0 --> syntax error 22- } as last char of an input file (missing a final \n) caused problems 23- ??keyword@ didn't work properly (pattern modified between chapters) BA 24- bug in galconj.c:corediscpartial (could return half integer) 25- factorff and ffinit "not random enough" TH 26- Configure doesn't handle cygwin new directory structure CW 27- polsturm(x,0,1) = 1 (should be 0) 28- [library:] gentimer(3) didn't work PW 29- various bugs in qfminim(,,2) [bound was rounded up + stack corruption] 30- ellap(e,2) gave wrong result when 2 | e.disc 31- factorint: isprime() used on factors even within smallfact() GN 32- SEGV in mpqs main sieving routine (unsigned comparison) 33- prevent polredabs from keeping small vectors accumulating in a subfield Changed 1- renamed .DOC files to .txt (Explorer was getting confused...) 2- moved MANIFEST to config/MANIFEST IZ 3- meaning of flags > 1 in plothraw IZ 4- output of \x (a bit more verbose) 5- unified basic t_QFR routines (use exponential distance internally) Added BA 1- Pocklington-Lehmer primality prover BA 2- Fp_isom (library) BA 3- Mod(a,b)^(c/d) for a,b,c,d integers 4- flag to vecsort (decreasing order) BA 5- function sqrtn =========================================================================== Done for version 2.0.19.beta (released 17/03/2000): Fixed 1- buffer overflow in ploth (when extrema too large) 2- trap(,"") didn't work IS+BA 3- various fixes necessary for g++ 3- prototype inconsistency in level1.h (evalexpo/evalvalp) 4- trouble with pgcc -mk6 + variable k6 in elliptic.c HC 5- nfnewprec(bnf) could contain objects of low accuracy XR 6- check subgroup argument in bnrL1 7- typo in ideal_two_elt (oo loop) 8- pb with GNU as + preprocessor on Sparc 9- incorrect result in matdet over Z[1/n] (Gauss-Bareiss) [gdivexact] 10- solve(x=0,1,deriv(x)) --> SEGV 11- ??' --> weird error 12- generic SNF (polynomial entries) couldn't handle 0s on diagonal 13- incorrect handling of 0 ideals in some functions XR 14- typos in bnrL1 15- bad input not handled in rnfcharpoly() IZ 16- delay rounding in rectplot structures until plotting device 17- Mod(1,x) / matid(2) --> incorrect object 18- avoid getrusage on alpha (pb with gp-dyn) 19- incorrect file inclusions when using gas on Sparc (-->undefined symbols) 20- massive cancellations in zetak(nfz,) when current prec lower than nfz's XR 21- bnrstark(): fixed inconsistency between 32bit & 64bit versions + check maxprime() before starting the computation PW 22- hyperu bad input bug PW 23- intnum(x=1,2,0) --> oo loop 24- sin(x + y) --> error 25- next(i > 1) didn't work (part of the last loop could be executed) 26- typo in polrootspadic(p, 2, *) [singular case] Changed XR 1- bnrL1 now takes a congruence subgroup as second argument 2- allow some functions to modify bnf/bnr structures (matal + cycgen) CB 3- modified TeX macros for pdftex 4- have abs(t_COMPLEX) give an exact result if possible [abs(0*I) was 0.0] IS 5- improved generic gcc compilation flags 6- in qfbclassno(), compute in G^2 to get rid of cycli factors 7- improved bnrdisc/bnrconductor Added BA 1- function galoissubcyclo() BA 2- (for now internal) function inverseimage_mod_p() BA 3- optional arguments (vertical range) to plot() IZ 4- `ticks' on hi-res plots IZ 5- prettyprinter default and tex2mail file BA 6- new function Fq_ker =========================================================================== Done for version 2.0.18.beta (released 20/12/1999): Fixed 1- wrong method chosen in isinexactfield for 0 polynomials 2- stack corruption in sylvestermatrix(0,...): Mod(x,x)^-1 --> SEGV 3- garbage left on stack in ginv(1 / n) 4- typo: carreparfait --> gcarreparfait in nfiso0() 5- for (A=1, 2, A = -A) --> SEGV IZ 6- [gnuplot] couldn't set terminal as the first graphing operation DE 7- typo in kernel/sparcv7/level0.S: err --> pari_err 8- TeXmacs interface (use new protocol) 9- call simplify() before applying GP '==' and '!=' operators Ex: x;n;k;m; (n+m)==(k+1-k)*(n+m) was false. 10- sumdiv(N,...) required single precision N BA 11- bound problems in nfgaloisconj() 12- oo loop in do_agm() 13- "Warning: in Gauss lg(a)=1..." from isprincipalall0 14- specific error for precision problems with p-adic ell. curves IZ 15- ploth() plots are 1/2-pixel off BA 16- result was not always complete in nfgaloisconj() 17- type(1/y, RFRACN) --> SEGV + check compatibility before applying type() 18- made 'secure' safer. Confirm before write, prevent from changing 'help' 19- gettime() called the wrong timer(): was reset in debug mode 20- missing case (doubling) in apell1 21- gmod(x, mod) replaced by gmul(x, gmodulcp(gun,mod)) in poldivres [obscure bugs when dividing complicated polynomials with mixed polmods/intmods]. 22- Make sure result is a t_POL before doing a setvarn in caract2_i() 23- precision problems in ClxModulus (bnrstark()) [check leading term!=0] 24- elltors() could miss some points: determine needed precision first 25- clean up files after an error (not only under GP) 26- divisors(highly composite integer) --> "cryptic" error message 27- 'make clean' wasn't thorough 28- ellpointtoz(e, [0,0]) could correspond to the inverse point 29- "ideals not coprime" in rnfsteinitz BA 30- typo in Configure [CPP] (cc --> CC) BA 31- member functions for galoisinit 32- allowed power series in Mod(). Fixed cryptic error messages. 33- precision problems in zsigne 34- value of 'gzip' found by Configure overwritten in TOP_Make.SH XR 35- precision loss in Round 4 XR 36- ensure that fundamental unit is computed in quadray (if D > 0) XR 37- precision fixes in stark.c (inconsistencies 32/64 bit + early abort) 38- bug in P*Q for polynomials over (non prime) finite fields if Q is defined over the prime field XR 39- [stark.c]: bugs in RecCoeff3, reduced memory use in ComputeArtinNumber 40- core dump on oo recursion under GP 41- use appropriate precision in torselldoud (could be much too large) 42- removeprimes(addprimes) didn't work 43- (at least part of) numerical instability of LLL over R 44- f() = bug(x, &y) ---> syntax error XR 45- inefficiencies in ComputeArtinNumber for large modulus HC 46- no GC in dirmul 47- meaningless heap count for user functions 48- setrand(16);quadclassunit(48893) --> oo loop 49- rnfpolred(bnfinit(y^2+1),x) --> SEGV 50- float overflow in polroots (e.g polroots(x^3 + 2^1024*x + 1)) 51- charpoly(Mod(1,x^2+1)) --> SEGV 52- added GC in polsturm BA 53- bugs involving rarely used type combinations in generic operations 54- check x >= 0 in lllgramint(x) 55- in rnfdedekind: use rnfhermitemod, not rnfhermite (slooow) XR 56- updated factorpadic to use new Round 4 BA 57- nfgaloisconj: discrepancies between 32/64 bits architectures 58- random(1 << 32) could have 32 bits 59- missing newline in error messages on startup (reading .gprc) 60- silent codeword overflows (e.g. O(x^100000)) IZ 61- updated gnuplot support 62- x="a"; eval(x) --> error 63- general flakiness with buffer handling under GP (Ex: input() + allocatemem --> SEGV) 64- [1] == 2 --> error (instead of 0) 65- lngamma(-0.106) --> SEGV 66- quadray(-11,3) --> x^2 XR 67- typo in nilord2 (wrong value for modular reduction) 68- unsafe division t_SER / t_SER with clonable components 69- polroots(1E-28*I*x^2+1) --> bug in roots (conjugates) 70- typo in cxlngamma [ lngamma(-7.4927-0.418564*I) --> SEGV ] 71- polroots(polynomial of very small Norm wrt prec) behaved badly (SEGV) 72- polylog(1, Mod(1,2)) --> SEGV 73- zeta(22!/23) --> SEGV 74- not enough GC in rnformax 75- over-reactive 'secure' default (+ moved it later in default .gprc) 76- sqrt(Mod(15,y^2+1) + O(x^5)) --> SEGV BA 77- typo in isinexactfield 78- sum(x=1,10, expr1; seq) : seq silently ignored 79- ellan and elltaniyama didn't check their arguments 80- simplify(t_POLMOD) could create invalid objects (mod not a t_POL) 81- primes(-1) --> SEGV 82- addprimes(0) wasn't rejected 83- various inconsistant error bessages (e.g. factor("a")) 84- estimate for the precision of unit embeddings in isprincipalall 85- global("b") --> polvar corrupt 86- hnfmod --> hnfmodid whenever possible 87- check arguments in incgamc 88- non-rectangular matrices could trigger a SEGV (in error msg!) 89- qfminim(,,2) didn't like mixed t_REAL/ t_FRAC entries (typo) 90- inconsistant spacing after GP error messages 91- regrouped code between idealred and idealmin 92- prevent 'install' in secure mode DS 93- typo in bnfisnorm(,,flag > 1) [extraneous gtrans] 94- don't reset pariErr in err_recover() 95- highlevel.c had become dependent from gp.c XR 96- incorrect output of quadray(D,,1) when D>0 and rayclass is trivial 97- typo in lllall_trivial --> matkerint([0;0]) didn't work BA 98- incorrect object for gerepileupto in gscalcol 99- try to detect bad input (e.g quad. form not > 0) in (integral) LLL XR100- typo in nffactor ("keep the value of i") IS101- work around an obscure gcc bug (gcc-2.96, alpha-linux) in stark.c 102- rnfcharpoly(nfinit(y^2+1),1,1) --> SEGV BA103- tan(t_COMPLEX) gave bogus result BA104- trace([;]) --> SEGV Added IZ 1- [gnuplot] look up directory tree for gnuplot related files 2- improved on-line help wrt to defaults and ambiguities (? default/some_default, ? some_default) 3- library functions gentimer, genmsgtimer, get_timer HC 4- optional argument to direuler (length of result) 5- low-level kernel function for integer squarings (twice faster) 6- error trapping in library mode and under GP 7- break loop to investigate errors under GP 8- "sprintf-rounding" under GP IZ 9- string justification in high-res plot IZ 10- bit operations ( bit[ and | or | neg | negimply | xor ] ) XR 11- add new flag value in bnrstark/quadray: try to find a better modulus 12- Configure flags to indicate where gmp/readline library/headers are to be found Changed 1- default binary produced by Configure -g is now static 2- improved the heuristics in ellisoncurve HC 3- extend the range of direuler (maxp was 2^16) 4- trial divide by the "private primes" before the primality tests 5- don't double stack automatically 6- disable ff_poltype correction (for lack of decent finite fields) in gmul 7- slight optimization to hnf / hnfmod (skip zeroes) XR 8- nfsqff: choose a prime ideal with few factors + better heuristic bound IS 9- default CFLAGS on linux-alpha 10- improved factorcantor / factorff 11- default multiprecision kernel is GMP if the library is installed Removed 1- sunview "support" (didn't work, hard to test, X11 is a better standard) =========================================================================== Done for version 2.0.17.beta (released 24/09/1999): Fixed XR 1- typo in zarchstar (result possibly incorrect when more than two places) 2- check_unit not severe enough ([;] --> session could die !) 3- wrong error message when using global var as argument to user function 4- typo in boundfact(t_FRAC) --> SEGV 5- buchall: don't compute xarch if not needed 6- remove limit on string size + silent overflow, e.g Str(10^5000) 7- "break status" not checked often enough: [break, 1] --> SEGV 8- rewrote errcontext (use print_text to fit messages on terminal) BD 9- added workarounds against some MSVC annoyances (Windows version) IZ 10- typo in Gnuplot.h 11- typo in Configure ("2>&1 >/dev/null" replaced by ">/dev/null 2>&1") 12- simplified incgam[23] + typo (mulrr --> gmul) IZ 13- typo in LD_LIBRARY_PATH setting (benches) 14- inconsistency in gadd(0., FRAC) (should give 0. if FRAC small enough) 15- libraries/headers ordering inconsistent in Configure (report: IZ and KO) 16- typo in ff_poltype [symptom: (Mod(1, y^2 + 1)*x + 1)*x --> garbage] 17- qfbprimeform(4, [2]) --> SEGV 18- overflow in factorcantor(2*x^3+3*x^2+x, 2^31-1) 19- memory corruption in apell1 + no garbage collection, rewrote the function to parallel apell0, replaced hashing by sorting, use Montgomery's trick, removed the p < 10^25 limit IS 20- cc -64 warning in mp.c:vals() 21- bad free in gp_expand_path 22- extract([;], "..") --> SEGV 23- not enough GC in hnfall 24- recover gracefully when precision too low in lindep/algdep IS 25- cleaned up unused variables, fixed some missing casts 26- algdep(x) --> undefined behavior when x exact. Replace by decimal approximation IS 27- C++ keywords (new, class) occurred as variable names 28- arguments of ideallistarch not checked 29- Mod(t_FRAC or t_PADIC, t_INT) --> garbage 30- gcmp1(t_REAL) always false: polylog(2, 1) --> error 31- (spurious) compiler warnings about variables used before initialization 32- memory (possibly) freed twice in buchall + unsafe allocation of matcopy 33- online help for matsnf not updated 34- rnfequation() didn't check its arguments correctly 35- removed spurious special case in compute_class_number() 36- typo in the compatibility macros mpabsz / mpnegz (missing ;) 37- "lost pointers in gerepile" in bnfisprincipal(Q, ...) 38- bnfisprincipal(..., Pol(0)) accepted 39- [Configure] Makefile name didn't necessarily match object directory 40- zetak(nfz, integer + 0.) --> stack corruption 41- for(i=1, ..., zetak(nfz, any complex number)) went slower and slower 42- poltchebi(.,y), pollegendre(.,y) didn't work 43- confusing "array index out of allowed range" message (e.g [1-0]) IS 44- fixed obscure compiler optimization bugs in smithall() and eint1() GN 45- weird results in ellisoncurve() due to misguided precision heuristics 46- typo in forvec([],...): readexpr() --> readseq() 47- check arguments in ploth() XR 48- rare bug in bnrL1 (wrong value!) 49- precision problems in polredabs 50- division by 0 in rnfordmax [typo in mymod()] 51- removed all dangerous occurences of constpi/consteuler (cf 41-) 52- typo in det() [forgot to divide by a pivot] 53- divide by 0 error in lllgramintern (precision problem) 54- suminf(k=1,suminf(j=1,.067^(k+j)/k^4/(k+j))) ran forever 55- factor(2*x + 2) --> [2*x + 2, 1] (instead of stripping the content) 56- (ultra-rare) stack corruption in mpqs_solve_linear_system() 57- rl_refresh_line() prototype changed across readline's versions 58- incorrect handling of INTMODs modulo integers of different magnitude XR 59- matsnf(3 x 3 matrix, 4) --> SEGV 60- some pathological bnfinit() computations (strive to get maximal rank) XR 61- precision problems in nfsqff() [increase precision for T2-norm bound] 62- time wasted checking generators of the form [x,0,...,0] in polredabs 63- variables deleted too late in freeall() Changed XR 1- modulus choice in bnrstark 2- make sure that addii(x,y) returns gzero, not icopy(gzero) 3- cutoff in ellap to use Jacobi sums (457 --> 100) 4- pariputsf("%Z",(long)g): removed the casts (not needed) 5- cleaned up hnfspec 6- look for at least MIN_EXTRA extra relations in buchall 7- simplified calling interface to hnfspec/add 8 Used hnfspec in bnfsunit, changed the way S-units are found 8- output of bnfsunit modified (removed res[3], made res[2] suitable for hnfadd) 9- listput and listinsert now return the inserted element, not the list 10- check_break_status rewritten: was very inefficient 11- Used parser code DG whenever it was possible (moved reorder to init.c) 12- faster isunit() 13- added GC in expr() 14- buchall(): increase subfactorbase without starting over GN 15- minor tuning in pollardbrent() for huge integers (call ECM sooner) 16- renamed directories dos -> Odos, o.xxx.xxx --> Oxxx. Moved win32/* --> Odos OR 17- new version of pari.el XR 18- new modular round 4 implementation (nilord2) BA 19- improved algorithms in galconj.c Added 1- an optional argument to next() 2- MANIFEST YU 3- support for FreeBSD ELF binary format 4- file CVS.DOC 5- support for Windows CE (Nigel Smart + coworkers) BA 6- functions related to Galois theory: galoisinit, galoisfixedfield, etc 7- [library] trivial function realun() Removed 1- #define HIGHBITM1 (useless) 2- files config/tar_[include | exclude] (obsoleted by MANIFEST) =========================================================================== Done for version 2.0.16.beta (released 29/06/1999): Fixed 1- paricfg.tex (needed to compile INSTALL.tex) missing if Configure is not run. Added a test in parimacro.tex 2- non-portable casts in galconj.c 3- 64-bit graph benches (extra spaces) IZ 4- typos in plotgnuplot.c 5- unnecessary plothsizes in "graph" bench (fails if no X server) 6- typo in ff_poltype IZ 7- check rectwindow in rectcopy and rectclip IZ 8- /opt/local/lib missing in Configure's library path IZ 9- [Math::Pari] needs pariErr->die _before_ pariErr->flush IZ 10- wrong valence code for plotcolor, plotclip IS 11- obscure inlining bug (pgcc 1.1.3 -O3) in stark.c:ComputeKernel0() 12- gcc -E doesn't define __GNUC__. Add it explicitly to KERNELCPPFLAGS 13- whatnow(sigmak) didn't tell the arguments have been swapped 14- [1]~ * [[1]] --> SEGV 15- lim=(av+ x * bot) >> y can overflow if large addresses are available (e.g Linux...). Use lim_stack() instead 16- algdep(I,1), lindep([I,1]) entered an oo loop 17- removed the maxHastad (= 50) limit in algdep/lindep 18- typo in polrootspadic(,,1) --> SEGV 19- GC not frequent enough in idealval 20- in split_ideal (isprincipal), LLL-reduce first if ideal is big 21- factorpadic(,,,1) didn't work anymore 22- round 2 (= nfbasis(,2)) used too much memory 23- idealval did not accept all types of ideals GN 24- unsafe stack handling in auxdecomp 25- polroots[mod|padic] returned a t_VEC, not a t_COL (as polroots) 26- check coeffs of polynomials with coeffs in nf (rnf* functions) 27- typos in polredabs0 (get_Bnf + nf_RAW in storeallpols) BA 28- nfgaloisapply could forget to clean up the stack 29- typo in gp_rl.c (rl_save_prompt <--> rl_restore_prompt) DE 30- arch="sun4" non reconnu par Configure 31- uninitialized variable (prec) in quadhilbertimag IS 32- pari.el.in was not updated when gphelp was moved from miscdir to bindir 33- rnfkummer(bnrinit(bnfinit(y^2-y-1),101,1),[1,0;0,2]) --> gerepile error IZ 34- update gnuplot interface a) Strings were put too low in gnuplot terminal; b) Allow setting of output file sizes, as in plotterm("gif=300,200"); c) Allow querying of possible output terminals, via plotterm("?") d) Update to newer Gnuplot-interface-layer (Gnuplot.h) allows compilation on Linux (stdout was bad as an initializer), corrects bugs in processing of terminal options 35- in buchall, allow minfsb to increase before doubling cbach (bnfinit(x^4+5*239*x^2+5*239^2) couldn't be computed) 36- bnfnewprec can't handle bnf = bnfinit(,2) --> SEGV (now, error) 37- typo in pseudorem (didn't recognize 0 properly) GH 38- weird bugs in thue() on alpha: typo int <--> long in thue.c 39- bnrisconductor assumed moduli had small norm (< VERYBIGINT) 40- bnfnewprec didn't accept imaginary quadratic fields ("missing units") 41- inefficiency in zarchstar (VERYBIGINT --> BIGINT) (rnfconductor(bnfinit(y^3+972*y-12),x^2+x+1) ran forever) 42- too much memory used in rnfordmax (+ removed some inefficiencies) 43- try to recover in nffactormod if input not prime (SEGV) 44- SEGV in nffactormod if degree(pol) > 100 45- factornf(p(x), q(x)) was accepted (and produced incorrect objects) 46- nfisincl / nfisiso made use of the bug above 47- subgrouplist(bnr) with trivial ray class group --> SEGV 48- background color was assumed to be "white" (by gphelp and gp) Made it "transparent" by default 49- pages shifted by 1 in User's Manual's table of contents 50- Mod(x, x^2+1) + x return Mod(2*x, x^2+1), not x + Mod(x,x^2+1) (fixed gadd, gmul, gdiv) 51- for certain flag combinations buchrayall unsuitable for gerepileupto (+ cleaned up the code) 52- ^C in smithclean corrupt existing objects 53- silent overflow in qfbhclasso 54- nfreducemodpr didn't check its arguments 55- confusing error messages when precision too low in initell 56- polx[0] modified in nfsubfields(P(y)) 57- various memory optimizations in bnrstark 58- incorrect debugging output in calc_bloc (at \g6) 59- rare memory corruption when garbage collecting in mppgcd 60- type t_STR not treated correctly in changevar 61- C-long overflow in ellan 62- memory use in the incgam* functions 63- bad input bug: qfperfection(indefinite matrix) --> SEGV 64- mateigen dropped some eigenvectors when precision was too low Changed 1- err() --> parierr() [conflict with system library in Redhat 6.0] 2- use Doud's algorithm in elltors [initial patch: HC] 3- new (internal) function get_mul_table (for nfinit, padicff) 4- disable LD_LIBRARY_PATH before running benches 5- strtoGEN() --> strtoGENstr() + added flag 6- optimized stack usage in pollardbrent (in place) 7- don't try to compute units in buchrayall if bnf doesn't contain them 8- simplified misc/gprc.* (esp. colors) 9- use C long to keep track of exponent in regula 10- src/kernel/sparcv7/level0.s --> level0.S + include preprocessing stuff 11- extended matsnf flags: immediate cleanup (backward compatible) 12- arguments swapped in veceint1 13- allow @ markers (??keyword@) in extended help (was apropos only) 14- do all computations in mppgcd in place (as in Changed-6) OR 15- new pari.el (cf emacs/pariemacs.txt) 16- search multiple lines in apropos extended help (???key) Removed 1- make test duplicated the "make bench" computations. Removed the test and dotest targets 2 -veceint1() function. Can be reached in library mode or using a flag to eint1 Added 1- default 'secure' 2- optional flag to Str() 3- expand environment variables in filenames 4- TODO file 5- man page for gphelp 6- Trivia section in the pari/gp man page =========================================================================== Done for version 2.0.15.beta (released 21/05/1999): Fixed 1- ?? (TeX mode) didn't work anymore 2- rl_save_prompt incorrectly detected on a.out systems 3- allow extra_relation() (bnfclassunit) to abort 4- allow cbach to double once more before triggering PLEASE REPORT (introduced in 2.0.14) 5- check for non-monic pol in smallbuchinit 6- vecex --> SEGV on some Linux systems (typo in match_concat) 7- exceedingly rare but possible overflow in forvec(, flag == 1) 8- factorff(x^7-3,3,y^3+2) --> SEGV DC 9- ghpelp doesn't exit when problems arise in TeX processing 10- made idealprimedec random again (also use det_mod_P_n to compute norm) 11- inefficiencies in nfeltval (computing norm is a waste of time) 12- did same prime twice when collecting garbage in modulargcd (=> error) 13- ffinit(huge prime,) output a weird error message 14- highly inefficient memory use in nfsubfields IS 15- [cygwin] typo in Makefile generation 16- file leak in mpqs (COMB) 17- allow prime_to_ideal to be called with a t_INT argument (for quadray) 18- typo in nf_shanks (calling Fp_shanks with wrong parameters) 19- polun (possibly) destroyed in bnrstark IS 20- keep logfile in synch with screen output 21- reset DEBUGLEVEL correctly on ^C (was sometimes set to 0) 22- bnrstark does not require anymore the modulus to be the conductor 23- check bnrstark's arguments in the right order (bnrstark(1,0) --> SEGV) 24- inefficiencies in idealval (removed element_mulh) 25- idealadd unsuitable for gerepileupto HC 26- quadray should work in all cases now and give better polynomials XR 27- bnrstark should return smaller polynomials 28- very inefficient pseudo-remainder routine (psres) 29- forstep(x=a,b, 1/2, ...) --> SEGV (signe -> gsigne) IS 30- [Cygwin] Configure fix (use $HOSTTYPE instead of uname -m) 31- polcoeff(a*x^-1*y^-1+O(x^2)+O(y^2),-1,y) --> 0 HC 32- (false) accuracy problem in mpsc1 ("truncation error") 33- don't use mpqs_diffptr in mpqs_find_k, set it in mpqs_create_FB 34- (very rare) "precision loss in truncation" in buchall 35- C-long overflow in zarchstar 36- C-long overflow in zprimestar 37- (old versions of) GNU as not recognized correctly BA 38- ?? in TeX mode could not process some sections (missing macros) 39- factor(polynomial with t_PADIC coeffs) didn't work (factorpadic assumed coeffs were integers) 40- T=[1,x; x,1]; charpoly(T,Z) produced object with wrong variable ordering 41- polrootsmod(x^n,p) could corrupt the stack 42- Warnings/errors from HPUX and AIX native compilers OR 43- many problems in the emacs interface pari.el (introduced in 2.0.14) 44- factorpadic treated only monic polynomials 45- gphelp TeX mode (use general macros instead of a specific file) 46- under readline, input lines of length > 2048 could trigger SEGV 47- more thorough check in checkbid (accepted prime ideals->SEGV) GH 48- possible stack corruption in thueinit(totally real field) XR 49- various problems in bnrstark (oo loop in fincke_pohst) 50- in doc/Makefile: removed GNU-style make macros + put a missing TAB 51- sloppy garbage collecting in hnfperm 52- HPUX+cc: work around a compiler bug (wr_float) 53- warnings in make_emacs_tags (perl5.005) 54- Configure --static should not disable install() 55- in rare cases reduction not complete in lllgramall (off-by-1 error) 56- addshiftw (polynomial case) could produce non-normalized polynomials 57- take content into account in modulargcd as in srgcd (not normalized) GH 58- uninitialized variable in poldisc0 (purify warning) 59- inefficiencies in round 4: modular computations [more needed!] (starting from a patch by DF+XR) GN 60- lllintpartial did not output the right matrix 61- huge memory leaks in bnrstark 62- signed int overflow in allocatemem 63- parisize (local to gp/gp.c) not updated properly 64- *sol not properly initialized in subresall 65- in idealpowred, check whether |n| < 16, not n < 16 (would slow down bnfinit a lot when class number is large) 66- polrootsmod(x^6-10,25) --> SEGV (now error message) 67- SEGV when renormalizing zero series in gdiv XR 68- unify precision choice in bnrstark (4 different formulae used...) GN 69- oo loop in mpqs (64bits machines + harsh compiler) when more factors were found than were hoped for (1 <--> 1L) GN 70- SIGFPE in buchall (double didn't fit in 32-bit integer) 71- also check sign in real0 (internal: called by gauss_pivot) 72- use current realprecision in plot() (was fixed: 28 digits) 73- memory use in subgrouplist(bnr) 74- in bnfcertify: "Too many iterations in isprincipal" 75- auto detect precision in quadhilbertimag ("overflow in I+R") 76- error message numbers in src/kernel/m68k/mp.s 77- polroots(x^3-x-422!) --> "impossible R-> dbl conversion" 78- not enough modular reductions in buchrayall (bnrinit) 79- technical argument in quadclassunit not read correctly 80- factor(x^3-1 + 0.*I) --> gerepile error GN 81- gp -p (close to a p^2) --> p possibly missing in the prime table 82- until narrow class group in quadclassunit is implemented, non-zero flag raises an error IZ 83- some code numbers in functions_basic (for Math::Pari) 84- precision problem in initell (AGM) 85- "impossible assignment I-->S" in ellrootno 86- missing break in poltype (factor) Changed 1- ?? (no arguments) opens the users'manual in xdvi 2- print readline version in header on startup 3- compute multiplication table first in element_mulvec[row] 4- nf[5][7] is now stored in two-element form (faster ideal inversion) 5- install gphelp in BINDIR, not MISCDIR 6- simplified output of trivial matrices 7- replaced square_free_factorization by mysquare_free_factorization 8- call LLL before using idealtwoelt GH 9- choose random elements in idealtwoelt, and allow bigger ones in two_elt 10- cleaned up lllgramall/lllgramintern + give quality ratio as argument 11- in rnflllgram, try to survive lllgram errors (findmin) 12- simplified rnfpolredabs (simple interface to polredabs). Should be much more efficient 13- replace many gdiv by 1 ginv + many gmul in sqred1intern 14- optimized polredabs (always do the initial polred now: it is for free) 15- more efficient ideal multiplication in random_relation (bnfinit) 16- library names nfhermite[mod|basis] <--> nfhnf[mod|basis] 17- subgrouplist function (use Birkhoff algorithm) 18- improve recovery in lllgramintern 19- improved checkgenerator in polredabs (look directly for double roots) 20- for consistency, return S-units in t_POL format (as fundamental units) IZ 21- revamp gnuplot autodetection by Configure BA 22- nfgaloisconj(nf, 4) uses Allombert's algorithm instead of Kluners's Added 1- install-doc target 2- make install makes a symlink pari.1 --> gp.1 3- ??tutorial/refcard opens tutorial/refcard.dvi in xdvi 4- posibility to extract the complement in vecextract HC 5- Ducos's subresultant algorithm (polresultant(,,2)) HC 6- accept a "vector of steps" in forstep 7- examples/classno.gp XR 8- new function bnrL1 9- new function gdivexact (used in subresultant, Gauss-Bareiss...) 10- new function bnfnewprec 11- optional argument to \l and \e shortcut 12- nfinit,polred[abs] accept input of the form [pol, HNF basis for Z_K] 13- q-Pascal triangle (matpascal(n,q)) 14- file src/basemath/subgroup.c, new function forsubgroup() IZ 15- function plotclip IZ 16- new file examples/taylor.gp (nice example for plotclip) BA 17- new file galconj.c =========================================================================== Done for version 2.0.14.alpha (released 05/03/1999): Fixed 1- factormod(2*x+1, 2) --> "factor for general pol. not implemented" IK 2- gphelp could leak temporary files BD 3- for native Win32 build: buffer overflow in get_home, incomplete paricfg.h, typo in try_pipe (#endif misplaced) 4- nfsubfields: could miss subfields if index > 1 5- removed 3 useless setrand(1) in subfields.c 6- rare and obscure memory bug in inverseimage (lost pointers in gerepile) 7- memory bug in factorpadic4 (prime not copied before result) 8- memory consumption in round2 (allbase) GT 9- m68k version: duplicate symbols from mp.c IS 10- Cygwin: in mpqs.c, open files in binary mode (otherwise fseek goes crazy) 11- bnfisprincipal().gen gives the expected answer IZ 12- signatures for Math::Pari in highlvl.c / init.c + GNUPLOT set-output-file problem 13- if we think readline needs libiberty, check whether it's installed first DB 14- PowerMac: header inclusion in highlvl.c, lround def'd in system headers XR 15- rnfkummer makes sure to return an integer XR 16- rnfconductor accepts polynomials with rational coeffs 17- polredabs + internal precision change --> nfnewprec forgets nf[5][1] 18- don't log lines twice when pariecho is set 19- glitches in content() (e.g content("a") --> SEGV) 20- get_sep(2) reacted incorrectly to empty strings 21- rootmod could destroy its argument 22- Fp_pow_mod_pol(x, 1,...) should return gcopy(x), not x 23- galoisconj1 computed wrongly the precision needed (+ prototype change) IZ 24- remove __OPTIMIZE__ dependence (define GCC_INLINE instead) 25- off-by-1 error in apell1 26- misleading error message in minimalexponent() XR 27- in nffactor, forgot to update precision when increasing exponent (+ various typos) 28- sparc + non-gcc --> kernel2 possibly not included: compilation failure 29- when echo is set don't print prompt if line is empty 30- ellpointtoz sometimes return -x instead of x 31- gp -b 1 --> hangs gp DE 32- many glitches in manual 33- mathnf(x, 3) when x hasn't maximal rank (SEGV) 34- differences in buchall 32bit/64bit (PRECREG too high. bnfinit(x^13-6)) 35- various inefficiencies in nfshanks ("module too large in nfshanks") 36- memory leak in buchall (= bnf*) 37- "not a definite matrix in lllgram" after a call to bnf* 38- typo in factorff(x^3+2,3,y^2+1) --> SEGV 39- [internal] missing tags (e.g zprimestar) after make ctags 40- idealstar(*, big prime) --> cryptic error msg (more tolerant now) 41- have Mod(0,1)^-1 return Mod(0,1) (fixes znstar(prime)) 42- ginv(-1/2) --> 2 43- heap leak when using local() 44- overflow in addssmod 45- changed the syntax of round() 46- sqrt(1. + O(x)) --> oo recursion IZ 47- don't create GP variables when expanding strings 48- internal variable 'parisize' not properly updated after allocatemem() IS 49- config/display didn't work properly with ActivePerl IS 50- Configure didn't handle most recent Cygwin 51- polinterpolate([],[]) --> SEGV 52- adapted gp_rl.c to readline 4.0 53- glitches in whatnow database (new file src/gp/whatnow.c) 54- all warnings from gcc 2.8.1 55- uninitialized tetpil in gscal() (bnfreg(x^2+1)) 56- precision problems in polgalois (degree > 7) 57- config/locatelib prompted a lot of useless work (returning too many libraries) and could pick up the wrong library 58- very rare bug in nfbasis (discriminant ok, but wrong basis) 59- quadclassunit: make sure sub factor base is big enough (oo loop) 60- more flexible "colors" default (initial work IZ) Changed 1- x.fu outputs polynomials (as all bnf* functions), not polmods 2- improved mppgcd (including vali) 3- improved division vector/scalar 4- \x to print a * in front of out-of-stack moduli (t_[INT|POL]MOD) IZ 5- better commandline usage message 6- don't buffer log messages going to pari.log 7- accept [nf, t_POLMOD] where nf is expected 8- poldisc() and quadgen() accept an optional variable name 9- when defining user function check for duplicate variable names 10- [internal] is_entry always uses function_hash (use is_entry_intern) OR 11- pari.el updated (see emacs/pariemacs.txt) 12- removed shiftl from lgcdii 13- use roots_to_pol in polgalois 14- precision heuristic in gauss_get_prec 15- cleaned up lllall and lllgramall 16- sort the output of nffactor, nfroots, factorff and factornf 17- nfgaloisconj now guaranteed to find all conjugates (use nffactor) 18- Removed flag 1 in nfisisom/nfisincl: function checks its arguments, and uses the best algorithm (both guaranteed complete). Changed the names (nfiso/nfincl) in library mode to match GP usage 19- gerepile(ltop,lbot,0) no longer returns ltop - lbot 20- improved floor and round(t_FRAC) 21- removed some duplicate code from nffactor 22- passing a pointer to GEN in a GP funciton now explicitly requires an & IZ 23- more verbose error messages for online help 24- increased a bit poltschirnaus's period 25- DOS version: don't use more for external help 26- cleaned up buchall code 27- removed unnecessary gres from polarit1.c:to_fq() Added 1- apropos command in gphelp (-k switch), ??? under GP 2- function global() 3- function gp_variable to use sums, etc in library mode 4- [internal] new functions mulmat_real 5- new functions gerepileupto[leaf|int] 6- function znlog() IZ 7- added default(color, "yes" / "no") 8- --static flag to Configure GH 9- inline alpha assembler (gcc specific) Removed 1- isinclfast/isisomfast 2- rounderror =========================================================================== Done for version 2.0.13 alpha (released 14/12/98): Fixed IK 1- Configure hangs on FreeBSD systems RD 2- Roland's patch (2.0.11: Fixed- 42) had been incorrectly applied 3- stack corruption in glcm (if operands > 10^155) 4- index wrap-around in polsubcyclo (n > sqrt(2^31)) 5- incorrect placement of strings in psdraw 6- memory corruption in rhoimag0 7- fix up memory debug mode (\gm) when switching to alternate stack 8- memory corruption (new_chunk + mulii) in gmul/gdiv (t_FRAC) 9- escape chars in GP strings sometimes parsed twice (e.g Str("\\") --> "") 10- nfinit(x^18+16) --> impossible inverse mod(0,2) (bug in eltppm() introduced in 2.0.12) 11- weird SEGVs due to variable handling (changed the 'bloc' structure) 12- moved highlvl.c to src/gp (libpari was missing symbols from plotport) 13- polcyclo ignored its second argument (introduced in 2.0.12) TP 14- minor fixes in paridecl.h (poldivres, gredsp: C++ compiler exits) HC 15- still sign problems in resultant (see 2.0.12: Fixed-58) 16- (Solaris):GNU ld doesn't like empty object files: remove kernel2.o IZ 17- make bench forgot to treat the install() BUG in a special way 18- factor(x^2 + I) --> SEGV (also with t_QUADs) 19- factornf(x^3+1,y^2-1) --> stack doubling (now output error msg) IZ 20- for Math::Pari fix valence of factormod() IZ 21- outfile rename pari_outfile (conflict with gnuplot headers) 22- DEBUGLEVEL could be modified and not reset upon interrupt IK 23- make perl -wc gphelp happy 24- incorrect use of gettime() in the library (nffactor) --> wrong timings (in particular for the 'nfield' bench) 25- polred/polredabs used different types for output. Made both t_VEC 26- remove duplicate polynomials in polredabs(x,4) and polred XR 27- precision fixes in modules/[nffactor|stark].c 28- in compatible mode, \precision didn't work anymore 29- typo in Round4 (case "p small" and "p huge" were swapped) 30- incorrect prototype for conductor in compatible mode 31- factor((x^2-1)/2) --> SEGV (factpol assumed integer entries) 32- memory usage in Round2: nfbasis(*, 2) (also cleared some inefficiencies) IK 33- typo in primitive_pol_to_monic 34- deplin did not check its arguments 35- quadray() assumed variable "y" was not in use Changed 1- glength() returns a C-long integer 2- in hnfmodid(x,d) reduce mod d immediately 3- allow vector(n), and matrix(n,m) (filled with 0s) 4- under GP, wait for input if line ends with '=' (cf \) 5- wait for input when a line ends with an '=' sign 6- modified extended help to (potentially) search the whole manual 7- in nfdisc, specific error message if discriminant is 0 8- use divide_conquer_prod() in factorback() IZ 9- in test suite, add setrand(1) in front of poltschirnaus IZ 10- M-( bound by default IZ 11- improved gnuplot support 12- improved gcmp[1|_1](t_REAL) OR 13- new pari.el (see emacs/pariemacs.txt) Added 1- members e, f, p, gen for prime ideals 2- mathnf([M, M2]) computes mathnf(M), updating M2 (equivalent to v=mathnf(M,1) then M2*v[2], but much faster if M2 is small or over a finite field) 3- local() keyword for user function definitions in GP IZ 4- new functions plotfile(), plotpointsize() IZ 5- splines for ploth (flag 256) Removed 1- \k metacommand =========================================================================== Done for version 2.0.12 alpha (released 06/11/98): Fixed 1- GNU as incorrectly treated by Configure GN 2- various fixes in mpqs.c (incl. file descriptor leak) GN 3- [From 2.0.11- Fixed 14] floating point exponents: 1E1 --> possibly 0.1 4- 1 % Pol(2) still wasn't right [cf 2.0.11- Fixed 31] 5- src/test/dotest for DOS boxes (running sh) 6- removed unreachable err() in factor() 7- system() is defined under EMX, so make it available for DOS 8- possibly use / as path separator under EMX, check COMSPEC and EMXSHELL 9- compatible = 3 downcased all the following lines in gprc and caused incorrect behaviour of preprocessing statements 10- unified default commands + better checks (e.g: default(log,0)->SEGV) 11- memory leak in gp_main_loop: bufferlisit wasn't reset on error 12- gptimer() not initialized properly if ^C was first command 13- extra space (sometimes) output by command line completion in DOS version 14- modifying histsize could corrupt the history stack 15- incorrect error messages in gsqr 16- not enough garbage collection in rootmod (polgcdnun) TP 17- compilation using cc -64 on 64-bit SGI IS+GN 18- "(hit return to continue)" message did not flush stdin GN 18- ECM rewrite 19- incorect absi_cmp in buch3.c 20- useless garbage collecting in sqred2 21- O(1)^(1/2) --> SEGV 22- forvec(i=[],...) --> SEGV GN 23- deriv(x*y, y) --> 0 GN 24- inefficient GC in ispseudoprime() 25- fixed some (not all) compiler warnings (char * --> unsigned char *) 26- exp(too large number) now gives a meaningful error message AW 27- getrusage still not detected on FreeBSD 2.2.5 GN 28- off by 1 error in initprimes() (--> not enough calculated primes) 29- inefficiencies in factor(t_POL) HC 30- bug in rnfelementabstorel for Mod(scalar, t_POL) HC 31- typo in gaussmoduloall 32- idealred(principal ideal) always returned an archimedean part HC 33- idealpowprime wrong for negative powers 34- typo in binomial(n,k) (wrong answer if n<=k) 35- online help for polinterpolate 36- incorrect garbage collecting in quickmulii/quicksqri 37- reformatted the output in test mode (gp -test) 38- polroots((x-7)*(x-8)*(x+16)) took far too much time 39- ellap assumed ell was given in characteristic 0 IZ 40- outlook of plot function (better labels, better choice of chars) RD 41- when factoring over a non prime finite field and found a p-th power, forgot about Frobenius GN 42- rare memory bug in ellfacteur 43- gscalmat was not suitable for gerepileupto 44- polredabs(,2) didn't handle non-monic polynomials 45- check for various overflows (x ^ 1000000, etc.) 46- printtex(I) --> missing closing brace 47- setisset() did not check that elements were strings 48- typo in gdiv(t_POLMOD, t_POLMOD) with different variables KO 49- missing ; in level1.h (Windows specific code) 50- forprime(p=0,10,) indeed started at p=0 51- (cf 2.0.11 Fixed-1) put back 3 cgeti in galois.c (were necessary) 52- factorpadic could overstate the precision of the result 53- (very) rare memory corruption in allhnfmod (when cleaning up) PM 54- prototypes in paridecl.h (fussy IRIX compiler), cc -64 in MACHINES 55- factormod implemented for all primes (p = 2 and p > 2^31 called factorcantor which was much slower) 56- check for unsuitable input in [factor|roots] (SEGV for multivar. pol) 57- polresultant sometimes gave the wrong sign 58- extraneous space in err(impl,"") (= "sorry,... not implemented") 59- aliases treated incorrectly during error recovery (--> obscure bugs) 60- obscure bug when normalizing rational functions with real coeffs (corrected content()) Changed 1- paricfg.h in dos and win32 extracted by Configure before the release (to get version number right) 2- GPRC logic: try $GPRC, then look in $HOME, /etc (/ and C:/ under EMX) 3- make sure the output of pari_unique_filename() doesn't exist already 4- use a stack of files to gracefully handle errors/interrupts without leaking file descriptors 5- replaced fixed-size buffers by dynamically allocated ones (es.c/gp.c) 6- rename INSTALL.QUICK --> INSTALL.DOC (updated) Changelog --> CHANGES (looks better under DOS) 7- mention ?12 in the header 8- use ; (instead of :) as PATH separator under DOS, OS/2 or Windows (for drive letter) GN 9- ECM tunings 10- check for overflow in cget* (instead of silent wraparound) 11- gp_main_loop cut into (improved) pieces 12- simplified normalizepol 13- Warn when trying to replace an existing function with install (previously error) 14- new function mpcopy. replaced some inlined function (rcopy, absi, absr, negi, negr) by compatibility macros 15- gphelp now uses GPDOCDIR and GPTMPDIR 16- improved rational arithmetic by computing smaller gcds (gredsp removed) GN 17- improvements in MPQS (use less memory, count relations precisely) 18- text-mode (non-TeX) extended help printed screen by screen 19- retuned integer multiplication, and made polkaramul the default polynomial multiplication XR 20- stark.c rewritten IZ 21- updated the pariperl interface 22- improved handling of t_INTMODs (less GC) 23- improved (a lot) factoring/root finding for intmod polynomials 24- modified poldivres to avoid computing remainder when useless 25- removed inefficient shiftl/shiftlr from the kernel 26- from the same sources, Configure can now simultaneously run on different architectures 27- polynomial factorizer now sorts the factors (increasing degree) 28- ?an_obsolete_function now calls whatnow 29- .pol operates also on t_POLMOD 30- random() argument can have arbitrary length IZ 31- with gnuplot, pick a sensible terminal when X11 is not around IZ 32- change valences for use with Math::PARI IZ 33- various interface patches (new file highlvl.c, different prototype for foreignAutoload...) 34- optimized permute() 35- setrand, getrand, getstack, gettime return a C long, and not a GEN 36- pari_randseed no longer global. Don't reset random number generator when entering certain functions 37- improved smallvectors() (correcting the "not enough storage" bug) 38- improved computation of special polynomials ([sub]cyclo,tchebi,legendre) 39- read() and extern() are timed as a whole now 40- check if LONG_IS_64BIT is correctly defined in pari_init (in case we include the wrong pari.h) GN 41- use Lehmer-Jebelean to compute inverse mod p (TODO: extended gcd) 42- moved subcyclo() to bibli2.c 43- improved polredabs, suppressed flag 8 44- improved ground(), case t_REAL 45- modified the internal SMALL nf structure (add matrix M, for polredabs) Removed 1- doc/Makefile.SOS, since make should succeed even if Configure failed 2- many error messages from the analyzer (referer*, trucer1, matvecter...), better handled by talker2 3- obsolete test %_ in bench 4- polkaramul(), which is now the default multiplication 5- factmoder error message 6- obsolete function polredabsfast Added 1- `pipes' for DOS running EMX, i.e extern() and extended help are available (perl needed for the latter) 2- file handling functions pari_fopen, pari_fclose, pari_unlink 3- new default `debugfiles' 4- file README.DOS IZ 5- target etags in top Makefile 6- target ctags IZ 7- gnuplot support HC 8- elliptic functions package (ellzeta, ellwp, ellsigma) HC 9- quadray function, extending quadhilbert 10- files src/basemath/polarit3.c and src/gp/highlvl.c 11- user-defined member functions 12- possibility to choose sizeof(long) at Configure time when the hardware suports it (eg. MIPS) =========================================================================== Done for version 2.0.11 beta (released 30/07/98): Fixed 1- removed all dummy cgeti (--> new_chunk) 2- stack corruption in gcarreparfait (t_INTMOD) 3- incorrect Fq-loop in apprgen9 4- removed useless normalize in gdivgs, gdiv 5- some {} Warnings from gcc -Wall (unjustified, but doesn't hurt) 6- incorrect zero series return by deriv 7- gaffsg(, t_PADIC) misused the valuation (symptom: deriv((1+O(2^2))*x^2) 8- online help for ellinit GN 9- default gp built without X11 in presence of some versions of xmkmf 10- ggval: zero series + simplified the code in there 11- subst(O(q),q,x) --> O(q) 12- newtonpoly did not treat correctly zero coefficients IK 13- getrusage incorrectly detected (at least on Linux/FreeBSD machines) 14- constante() used far too much memory (+ an int should have been a long + an lg should have been an lgefint). Reading in a huge bnf needs much less memory now 15- y[2] checked in divri instead of is_bigint (see 2.0.10, Changed 2) 16- powgi, default case: missing gcopy + incorrect gerepilemany if y==NULL Also, uniformized random GC with gpowgs 17- stack corruption in hil(x,y,p) when typ(x) > typ(y) 18- SEGV if DISPLAY was unset and hi-res routine under X11 is called GN 19- ispseudoprime(negative integer) 20- removed -static from the CFLAGS of profiling version (didn't build) 21- linear algebra routines involving polynomials with real coeffs 22- compiles properly under DOS + EMX GN 23- Warnings from C++ compiler (include unistd.h and sys/ioctl.h where needed) 24- znprimroot(0) --> oo loop GN 25- various fixes in mpqs GN 26- add safety parentheses to macros in paricom.h 27- polroots needed too much precision (two extra words) 28- factor(1. * x + I) ---> rubbish or SEGV (bug in polynomialtype automat) 29- possible address wrapparound in gerepile* (cast to ulong) 30- in gerepile: useless special case for t_SER 31- Pol(1) % 1 returned 1, not 0 32- matdet([x1,1,1/x1; x2,1,1/x2 ; x3,1,1/x3]) returned wrong result (call to gdeuc should have been gdiv in all cases in det()) 33- SEGV in powmodulo (access garbage pointer just before exiting) GN 34- various problems in rho and mpqs Changed 1- simplified detint, fibo 2- simplified GC and optimized gmul: t_SERxt_SER, t_POLxt_POL, and gsqr (same types) 3- streamlined binomial 4- replaced all abusive cmpsi by the relevant egalii 5- prototype for error types [gmuler|gadder|gdiver][fi], assign[ri] using new function type_name 6- uniformized the test suites (make test*,bench,...) GN 7- add random GC in mppgcd. Use modified plus-minus algorithm (new cgcd) 8- format of bench files (to reduce size) 9- cleaned up factor and polynomialtype 10- matdet tries to return a significant 0 when called with a non-invertible argument, e.g matdet([1+O(3),1+O(3);O(3),O(3)]) --> O(3), not 0 11- made the output of make bench/test slightly more informative Removed 1- mpkaramul 2- error messages expter1 and gaffer13 Added 1- misc/gprc.dos a sample gprc for DOS boxes 2- Configure --prefix=dir is now recognized (in addition to -p) =========================================================================== Done for version 2.0.10 beta (released 09/07/98): Fixed 1- integer factoring engine (ECM): sisprime killed N XR 2- file closed twice in MPQS GN 3- bad argument checking in [next|prec]prime BD 4- warnings from MSVC compiler 5- warnings from purify (vpariputs + puissii) 6- sample program and Makefile in examples/ 7- v=...; forvec(a=v, v=...) ==> SEGV LG 8- support for HP running NextStep GN 9- have checkmemory (in cget*) check for overflows LG 10- avoid a bug in cc compiler (version 4.2) under Solaris (in factmod()) LG 11- some missing prototypes and typecasts (for C++) GN 12- add LOCAL_HIREMAINDER in mulssmod (factor(17!+1) => SEGV on some PCs) 13- non portable pari_is_rwxdir GN 14- lots of typos in the documentation Changed GN 1- add debugging output to ECM 2- forvec implementation (+ new flags) GN 3- rewrote the integer factorizer (use Pollard-Brent + improved ECM + new MPQS code from 2.0.9) 4- disabled pari-matched-insert under Emacs 5- reorganized vecsort & co 6- in library mode, classno3 --> hclassno XR 7- improved the nffactor module HC 8- elllseries (use ellglobalred + ellrootno) Added 1- new function in library mode readGEN() HC 2- new GP function ellrootno Removed 1- error message vecsorter2 2- functions vecindexsort, veclexsort (use vecsort with flag) =========================================================================== Done for version 2.0.9 alpha (released 16/06/98): Fixed 1- typo in qfbhclassno (SEGV when result in (1/3)Z) 2- too much memory allocated in factmod /factcantor (use clones) 3- removed the -DREADLINE_LIBRARY hack, use and not 4- version 2.0.8 did not compile with readline 1.* 5- after gaffect(0, padic), padic was unsuitable for further gaffect 6- length(a string) gave number of non code words, not string length 7- factorpadic(polynomial of degree one) did not convert coeffs to padics 8- reduction mod p^r forgotten in gaffsg(s,t_PADIC) 9- default(realprecision,,1) did not return # significant digits 10- typo in nfmodprinit (return x instead of 1-x) 11- matinverseimage did not check its arguments 12- mathess([;]) --> SEGV 13- matid(-100) --> SEGV 14- mateigen([;]) --> SEGV 15- matmultodiagonal([;],Mat(1)) --> SEGV 16- vecextract([;],"..") --> SEGV 17- introduced in 2.0.8 (Added 3-): aliases/user function + ==> SEGV GN 18- (t_RFRAC) ^ t_INT took an unreasonable amount of time 19- prevent quick succession of ^C from corrupting memory in recover() 20- hyperu could enter an oo loop due to round-off errors XR 21- matadjoint(Mat(n)) returned Mat(n), not Mat(1) 22- matadjoint([;]) returned [[;]] (???) 23- wrap some long error messages XR 24- inefficiencies in rnfpolredabs XR 25- nffactor (wrong format for discriminant computation + problems with unseparable polynomials + compute disc only once) HC 26- typos in kummer.c GN 27- check environment variable LINES, not ROWS 28- introduced in 2.0.7 (Fixed 7-): lift(Mod(O(2^0)*x, x^3 - 2)^4) was a zero polynomial with non-zero sign (=> pb when normalizing in poldivres) 29- timer always returned 0 if times() was used (e.g linux-alpha) 30- kill'ing the argument of a user function corrupted the function 31- make clean did not remove pariinline.h 32- incorrect memcopy in identifier, case 's' (removed * sizeof(long)) 33- online help for ?. (nf.nf does not exist) 34- lisseq0: gnil not respected after break/next. avma=av too brutal after return 35- ellwp assumed precdl > 3 36- under emacs, \c + hit return froze emacs (Emmanuel Kowalski) 37- (f()= f()=x); f; didn't set f properly GN 38- comments in anal.c 39- qflllgram([;]) --> SEGV 40- no online help for bernfrac 41- from 2.0.6 (Fixed-8): in padicff2, forgot to raise ideal to power e Changed 1- improved (trivially) gneg (case t_INTMOD), gtopoly 2- use macro is_bigint() instead of tests (ulong)x[2] < VERYBIGINT (led to typos as in Fixed-4 in 2.0.8) 3- improved poldivres by replacing many gsub by 1 gneg + many gadd 4- in pvaluation check for small integer 5- internal function rnfelement_*mod (prhall=NULL instead of gzero) 6- improved mathess 7- added error message "inconsistent data in" in parierr.h 8- gpui[gs] renamed to gpow[gs] GN 9- improved probable-primality tests ('end matching') 10- moved pseudo primality and ECM stuff into ifactor1.c GN 11- raise to an integer power using left-shift binary (new functions powi and powgi) 12- add some details in the online help headers GN 13- nextprime, precprime now accept real arguments TP 14- improved the alpha micro kernel (addllx and subllx) 15- simplified poltschirnaus 16- cleaned up identifier(): #ifdef __hpux__ + call_fun() modified 17- taylor() improved (one gerepile removed) 18- unified the treatment of zero series 19- gerepilemany faster and more efficient memory-wise (copy to heap first) GN 20- improved stack checking in lllgramall Removed 1- global variable defaultpadicprecision 2- function compute_prhall (nfmodprinit is better) 3- function [g]pseudopremier (miller[rabin] better) Added 1- function egalii 2- support for cygwin32 in Configure (Andy Stubbs) 3- new function gunclone to delete a clone (killbloc should be used by the analyser only) 4- comments in anal.c TP/XR 5- new function factorint(), using MPQS (_experimental_) =========================================================================== Done for version 2.0.8.alpha (released 07/05/98): Fixed 1- improved garbage collecting in polroots 2- zetak did not check its nfz argument properly 3- warnings from MSVC GN 4- isprime() did not work for numbers in [2^(BIL-1), 2^BIL-1] GN 5- precprime sometimes missed a prime 6- quaddisc(x in Q\Z) did not always work 7- powering of zero series 8- factorization of null matrices (SEGV) 9- mateigen for non-diagonalizable matrices (SEGV) GN 10- oo loops in some arithmetical functions when arg = big prime GN 11- cleaned up paridecl.h 12- gimag/greal for type t_RFRAC/t_RFRACN (fix: Terje Sparre Olsen) GN 13- ordinal numbers to number components seen through \x HC 14- lllgram: incorrect gabage collecting in first "warnmem" 15- theta(q exact, z) entered oo loop 16- typo in gdiventres (x<-->y in last line) MS 17- gtrunc for p-adics when valp(x) < 0 MS 18- polresultant(u+v,u-v,v) => x + u; polresultant(u+v,u-v) => 2*u MS 19- issquare(Pol), where Pol(0) = 0 IZ 20- use 15 points (by default) for recursive plotting as documented 21- matsnf for singular matrices (supersedes a patch by GN) LG 22- micro kernel support for HPUX LG 23- compilation with Sun's C++ compiler (version 4.2) 24- SEGV when factoring polynomials of huge degree (removed expos[100],etc) 25- garbage collection in gpuigs GN/BH 26- micro kernel support for ix86 running SunOS HC 27- handling of 0x0 matrix in some hnf* functions HC 28- bug in discrayabslist* (try bnrdisclist(bnfinit(y^2-2),200,,1) in 2.0.7) Changed: 1- moved hnf and snf from base1.c to alglin2.c (base1.c too big) 2- use gexpo in linear algebra functions when entries contain real numbers (work for inexact polynomial entries now). Still does not work properly for p-adics GN 3- in sigma() fall back to numbdiv() or sumdiv() when k < 2 4- made comments started in file through read("file") local to file (not so \r file) 5- valuation(0) now returns VERYBIGINT instead of raising an error MS 6- simplified gegal in case t_FRAC IZ/GN 7- faster initprimes, using less memory LG 8- improved Configure Added: 1- new function write1 MS 2- new Lisp-like quote operator 'a IZ 3- readline: electric parentheses, move across balanced expressions, add formal arguments to completion of GP command (when unique) 4- micro-kernel for hppa 5- quiet mode (gp -q) to suppress headers =========================================================================== Done for version 2.0.7.alpha (released 21/03/98): Fixed XR 1- SEGV in get_regulator for imag. quad. fields 2- "beautified" output (still ugly, less buggy, ok for simple objects) 3- error during "print()" could change output default 4- SEGV when syntax errors in gprc 5- make install failed when libpari.$sodest had been removed 6- moved term_width and term_heigth to es.c HC 7- inefficiency in mulii (Karatsuba used too easily) XR 8- many problems in stark.c XR 9- bugs in rnfpolredabs (+ new flag) GN 10- _many_ typos in tutorial and user's manual. New, much nicer, layout 11- whatnow not robust enough + faulty call by err_new_fun ==> SEGV 12- idealadd treated incorrectly the 0 ideal 13- default(realprecision) gave wrong value when format had been changed 14- bnfs structure was inefficient for applications (inverted 2nd comp.) 15- buffersize was incorrectly updated during complicated read() 16- one-line comments "ignored" if buffersize too small 17- using eval on object containing killed variables caused a SEGV 18- contfrac lost last term when first parameter was rational and numerators were supplied 19- problems when dividing with polynomials/series whose leading coeff is non-exact 0 BD 20- missing #ifdef ZCAT in es.c BD 21- check in paricom.h whether min / max are already defined BD 22- universal_constants freed early in freeall() (problems on Windows NT) BH 23- update Makefile.dos (nf.h --> parinf.h) BH 24- changed kernel/ix86/level0asm.c (FUNBEGIN/FUNEND + ALIGN) 25- cleaned the gauss_pivot functions + garbage collecting in gauss() 26- mathnfmod did not check its second argument 27- since 2.0.4 (item 24) install did not work anymore on FreeBSD + gp-dyn 28- cleaner malloc in plotX.c (to remove Warnings when debugmem > 0) 29- slightly optimized matdet (gsub --> gadd(,gneg)) 30- ? x=1; Pol(1) *** variable name expected: x,n, ^--- is fixed everwhere (wherever an optional variable name is expected) setting "x" to some value is now safe IZ 31- nicer looking plot() function 32- warnings while building for m68k arch 33- sqrt(Mod(1,2)) went into an oo loop 34- ?? did not resolve aliases 35- besselk near integers entered an oo loop 36- p-adic sqrt (bad valp) 37- hnfmodid could output wrong results (wrong diagonal) and wreck the powering of prime ideals 38- added garbage collecting in izeta 39- ??a_number now works as gphelp 40- in prettymatrix format, matrices 0xn and nx0 are always printed as [;] 41- 1 - "a" ==> SEGV Changed 1- reorganized output functions (es.c) 2- have mulir check if integer is small 3- part of GENtostr inlined (check_output_length()) HC 4- functions where it makes sense now admit an optional argument for "variable number" (intformal, deriv, things having to do with polynomials, etc) 5- lines of any length can be input interactively (previously 1k at most) 6- remove {} and \ from readline history 7- improve treatment of sample programs in gphelp -d 8- uniformized debugmem messages MSo 9- simplify the coinit function 10- changing the function set through default(compatible,) no longer resets installed functions 11- renamed nfker-->nfkermodpr, nfgauss-->nfsolvemodpr 12- simplified/extended dummycopy 13- listput gives more informative error messages Added 1- default: lines HC 2- (made known to GP) functions nfmodprinit, nfkermodpr & nfsolvemodpr XR 3- function bnrstark 4- install code D& (optional pointer) 5- function name_var (to use after fetch_var) 6- concatenation of lists (or row vectors) of objects (overloaded concat) 7- ranges for vecextract (eg. vecextract(x, "1..3")) Removed 1- useless code 'F' in analyzer 2- perl directory (moved the files in ./perl to ./doc) =========================================================================== Done for version 2.0.6.alpha (released 22/02/98): Fixed 1- \x (voir2) did not always print the correct number of words 2- in changevar, type POLMOD, modulus and polynomial were interchanged 3- all occurences of former header file names in the documentation 4- (from 2.0.5. item C5) using allocatemem in a script aborted file reading 5- expanded the documentation for bnrrootnumber 6- factor(pol. with rational non integer coeff) could corrupt the stack 7- Euler gave wrong results when prec > 80502 digits (also cleaned up Pi) 8- cleaned up ggcd, grando0, tayl and factorpadic2 9- is_scalar_t --> is_const_t in gvar/gvar2 IZ 10- Configure and example Makefile for OS/2 11- idealprincipal did not accept n x 1 matrices 12- idealhnf(nf,a,b) did not work for quadratic fields 13- matsolve[mod]([;],.) could corrupt the stack or accept incorrect input 14- modules/galois.c unnecessarily included BH 15- symbol name problem in level0asm.c (cancels patch by IZ) XR 16- fixes in stark.c 17- cleaned all occurences of HIGHVALPBIT and HIGHEXPOBIT 18- serconvol assumed main variable was "x" 19- (x + O(x^2))^(3/2) gave a stupid error message 20- types not checked correctly in gtoser 21- check more seriously arguments to default() 22- in Makefile: added some missing $(RM), changed an "ln -s" in $(LN) 23- extra '\n' after print1 + sequence of warnings 24- simplified a statement in addii() 25- typo in classno() (classno(-200183): "division by 0") + cleaned classno 26- all compiler warnings + most of lint's 27- make install would not work anymore if emacs was not found 28- HNF reduction not always complete when rank is small compared to dim 29- gphelp -d did not handle ~ properly (+ cosmetic changes) Removed 1- unused files src/kernel/ix86/{asmi386.h,asmi386inline.h} 2- useless macro gcopyifstack and global variable RAVYZARC 3- useless error message gcder1 4- useless (undocumented) function fasthnf Changed 1- simplified isonstack 2- extended valid inputs for matsolvemod 3- don't output a '\n' before an empty matrix 4- mpsincos no longer static (so that it can be installed) 5- reorganized gp_initrc() to cater for for non-UNIX arch 6- the "obsolete function" message now launches whatnow() directly (and caters for the special cases "i" and "o" now) 7- improved stack management in hnf/allhnfmod/fasthnf 8- moved powering functions to trans1.c 9- disable logfile while reading .gprc 10- (slightly) the output of whatnow() Added BH 1- support for DOS build using EMX (dos directory + fixes) 2- function cotan() and bernfrac() 3- a code for pointers (&) for analyzer and install() 4- ??readline now includes info about completion and online help =========================================================================== Done for version 2.0.5.alpha (released 07/02/98): Fixed BH 1- LOCAL_HIREMAINDER added twice more in mp.c LG 2- some symbols declared extern in gp_rl.c to avoid compiler warnings LG 3- isprime could corrupt the stack (isprime_proto removed) LG 4- possible redeclaration of macro from system header (MAX in bibli1.c) 5- typos in the user's manual 6- removed unused error numbers and fixed their ordering in mp.s 7- a ; or : after read/extern was not always correctly taken into account 8- a bug in polroots (possible SEGV in very rare cases) (Paul Zimmermann) Changed LG 1- (huge) reorganization of PARI kernel and headers 2- logfile example in gprc.dft to take advantage of "time expansion" XR 3- stark units module rewritten HC 4- rnfpolredabs improved 5- errors now cause GP to close any file it was reading instead of going on 6- increased the static limit for the number of files opened simultaneously Added XR 1- function bnrrootnumber =========================================================================== Done for version 2.0.4.alpha (released 26/01/98): Fixed 1- recovery on startup was not correctly disabled GN 2- pari.el (see emacs/pari.el-changes) 3- "" missing around a DLLD caused Configure to fail if shared library not available 4- component of GEN could be created before its root in gadd(t_SER, t_SER) 5- nffactormod did not like big primes 6- removed the `.' binary concat operator introduced in last update (broke semantics). Instead Str() argument evaluated in string context 7- solve did not find some obvious zeroes (solve(x=-2,1,x) for instance) 8- Configure -pg did not work 9- 68k version didn't work: corrected mp.s, moved some code & defines 10- subst(x,variable(x),1) did not work 11- flag acted contrary to doc in matsolvemod 12- in rare cases the prompt could still start at column > 1 13- bnfissunit much faster now 14- idealval could make mistakes with non-integers 15- Mat([1])[1,] gave a stack error 16- zetakinit(x-1) as well 17- zetakinit(K, even integer) gave a wrong result whenever r1(K)>0 18- typo in whatnow(hermite) and ?bnfsunit 19- missing newline in user error after print1 20- various typos and omissions in chapters 1, 2 and 5 of manual 21- (x-x)==(y-y) returned FALSE 22- polfactormod(f,0) gave a SIGFPE 23- some missing #ifdef UNIX BH 24- install() now works for gp-sta under Linux and OSF BH 25- gcc Warnings in gp.c + es.c BH 26- problems when installing from a different non-priviledged account BH 27- inefficiencies in mpinline.h (replace memory access by a constant) Changed 1- when logging mode is on, record command line as well as result, and flush buffer often 2- subdirectory lib now called misc. Changed some filenames in it 3- defaults psfile and logfile are now run through strftime 4- for benches total time now taken into account ([BUG] was excluded) 5- noerr is now the LAST error message (for CLISP interface) 6- cleaned path expansion (default(path,...)) 7- renamed types.h and cast.h (prefixed by "pari") 8- renamed type Rect to PariRect DB 9- kernel/kerPPC.s replaced by kernel/kerPPC.c 10- made static the arrays in check_isin() (for the Mac port) BH 11- overflow/hiremainder use local variables as much as possible 12- prompt not printed during a batch job, unless echo is set commands not echoed twice in interactive mode Added 1- gplogfilter script in misc 2- check for strftime in Configure 3- support for alpha running linux (include portability fix on keralpha.s) 4- file MACHINES 5- made message for "array index out of range" error more precise 6- more frequent garbage collecting in mathnf BH 7- inline asm for i386 GN 8- support for native compiler on AIX Removed 1- support for dynamic linking on AIX (did not work) =========================================================================== Done for version 2.0.3.alpha (released 13/01/98): Fixed: 1- rare bug in gadd (PADIC + PADIC) which caused one of the arguments to be overwritten 2- typos in refcard 3- galois.c still couldn't compile on the HP (_INCLUDE_POSIX_SOURCE) 4- introduced in 2.0.2: item 14 used gexpo incorrectly (bnfinit sometimes did not give units it could have computed) 5- replaced INFINITY by pariINFINITY in rootpol.c (cancels Warning on OS/2) 6- on OS/2, target ../gp-$dft in o.xxx/Makefile could not be built (extraneous $exe_suff) 7- command line switches so that one can enter them with or without white space (new function read_arg in gp.c) 8- setdcolors so that it can't unset disable_colors if we are under emacs 9- random did not check its argument correctly (random(2^32) was accepted) 10- b=10; for(a=1,b, b=2) exited immediately, whereas the upper bound is supposed to be evaluated only once 11- reorganized the error recovery system (initially because errpile could cause SEGV on Linux systems) 12- typo. problems in doc and refcard (interletter spacing in $nfz$...) Changed: 1- Reorganized Makefile.SH: extraction twice as fast 2- pari.menu and pariemacs.txt rewritten, pari.el updated 3- expanded the man gp.1 to mention command line switches 4- the implied input from non-interactive input command (like extern and read) does not go into the GP history (%x) anymore (it never went into readline's). The final output (value of last expression evaluated) of course still does! 5- updated chapter 5 of the User's Manual (removed obsolete information) Added: 1- better settings for handling the Meta key under readline in examples/Inputrc YU 2- support for shared libraries under FreeBSD 3- colors under Emacs 1) emulate exactly the "colors" default after a M-x gp 2) .gp files edited get a special highlighting 4- a flag to default() to get the result under GP 5- overloaded the "." (member) operator to concatenate as strings if LHS is a string 6- .gprc accepts some limited preprocessing directive (#if READL and #if EMACS (and #ifnot as well)). Updated lib/gprc.default to reflect the changes Removed: 1- some unused, undocumented functions (allocatemem(), checksqid()) made static some other (op_ReIm) =========================================================================== Done for version 2.0.2.alpha (released 15/12/1997): Fixed: 1- typos in the documentation for the random() function 2- removed an extra -emacs flag in pari.el 3- decodefactor was incorrectly remembered by whatnow (it's factorback now) 4- test mode did not prevent all prompt expansion (==> bug in make test) 5- gphelp stopped abruptly when meeting a cross-referencing macro 6- zetainit now aborts cleanly when disc. too big (caused memory fault) 7- exceedingly rare bug in the printing of real numbers (missing decimals) 8- too early rounding in polroots which in rare cases made GP think some error had happened 9- text overflowed the manual pages (and tutorial) on non-A4 paper 10- polred incorrectly assumed that nf arguments were totally real (in a non critical part: that just led to some unnecessary computations) 11- polred(f,2) could try to overwrite universal integer gzero 12- check if we are using GNU as or GNU ld in Configure 13- empty -R argument to $CC when building GP without graphics (==> link failed) 14- bnfinit acts sensibly when fundamental units are too large (before: "overflow in R*R") 15- cleaned up buch2.c (removed ideallllredpart1, removed gerepile in class_group_generators(), not_given now called from getfu) 16- nfgaloisconj(...,2) was unusable (tried an illegal multiplication) 17- is_totally_split was very inefficient (==> nfgaloisconj was very slow) 18- some unimportant typos (gexpo) in polgalois 19- compiling without readline gave a Warning in gp.c (already_hist) 20- some make programs don't like $< (suppressed from doc/Makefile) 21- ellap sometimes assumed wrongly that coeffs of the curve were integers 22- flag 0 and 1 in ellap had been mixed up 23- print an extra \n before an error message if last output did not include it 24- component(any non recursive type) gave a SEGV 25- suminf / prodinf / prodeuler assumed they treated a real expression 26- lindep / algep had problems with numbers having a rational component 27- last significant digits of bessel* and hyperu were wrong (now only the last one is) 28- expi now returns a long as documented (expi(gzero) returned 0 on 64-bit machines!) 29- g++ could not compile libpari.a (casts missing, extraneous extern "C", faulty inline, etc.) 30- cleaned up the enums in gp.h 31- incorrect target veryclean in doc/Makefile Changed: 1- '_' is now valid in GP identifiers 2- removed subsections from table of contents. pages in the manual are now numbered consecutively 3- gexpo now accepts exact 0 arguments (return -HIGHEXPOBIT) gexpo for complex numbers now return max(gexpo(Re), gexpo(Im)) 4- parts of lib/gprc.default 5- the second argument of subgrouplist is now optional Removed: 1- buggy label/goto functions 2- (now unused) error messages: labeler, gexpoer2 3- _ as shorthand for conj() 4- (useless, undocumented) function gnormalize 5- some files in the lib directory (functions, gp) Added: 1- some files in the lib directory (README, pari.xbm, xgp) ============================================================================== Done for version 2.0.1.alpha (released 29/11/1997): Fixed: 1- multiple factors forgotten when factoring univariate pols over Z 2- extraneous modifications of the random seed (period of random generator was ridiculously small for some buchxxx functions). Change the bench results (in a non essential way) 3- bad terminal size determination 4- aliases incorrectly killed (possible SEGV) 5- incrementing/decrementing array elements with the (valid) syntax v[i]++ / v[i]-- caused a weird error message 6- subgrouplist() could end up by a SEGV on Linux systems LG 7- on HP-UX, flag -Aa not taken into account in Configure (caused it to fail on has_TIOCGWINSZ.c) LG 8- added a missing #define _INCLUDE_POSIX_SOURCE in galois.c (7 & 8 independently fixed by OV) GN 9- the script examples/cl.gp called vecconcat() instead of concat() GN 10- make install-sta rebuilt gp-sta unnecessarily GN 11- many, many typos in the tutorial 12- tu / fu applied incorrectly to a bnfclassunit 13- bnfclassunit did not output a valid object (matrix whose elements were rows instead of columns) 14- conversion bug from t_QUAD to t_REAL/t_COMPLEX 15- off-by-1 error in the history recovery after an error 16- in fprintferr() (debug messages), embedded %Z did not work correctly 17- rnfequation over Q yielded a SEGV 18- string() in compatibility mode corrupted the stack 19- it is now safe to have colours in prompt and input line under readline 20- default colours restored upon exiting 21- default colors in lib/gprc.default used 0 instead of -1 for "no color" 22- psi and lngamma could give wrong results when the argument was not real 23- the make test-graphic bench was missing a newline 24- Pol(break) gave a SEGV 25- x=1; Pol(1) gave a stupid error message IZ 26- tutorial.tex was unnecessarily rebuilt 27- typos in ggcd (cases nobody will ever access: gcd of a non-reduced LG fraction with an intmod, etc.) LG 28- incorrect handling of integrals of vectors 29- gcd of polynomials with non-exact coeffs gave stupid results (they are still often wrong, since the mathematical notion is rather imprecise) 30- typos in rnfkummer (incorrect flag handling) 31- typo in idealpowprime (negative exponent gave wrong denominator) 32- multiplication t_COMPLEX x t_COMPLEX used 4 mult. instead of 3 33- some modular functions (j, f, f2) rewritten to take advantage of new eta function (trueta) Changed: 1- ?? (gphelp) starts in detex mode (-d) from a console window. tmp files now placed according to the $TMPDIR environment variable (in /tmp by default) 2- /usr/local/lib/pari/data is a better place for the Galois resolvents (which are not included yet in the standard distribution) 3- The example for prompt in gprc.default to discuss escape sequences under readline 4- Configure now starts by searching the toplevel directory for a temporary readline installation 5- The output of default(colors) was confusing. It is a string now 6- third argument of polinterpolate can be arbitrary and is now optional ("x" by default) (it had to be numeric) 7- directory configure renamed config, some of the Makefiles in there as well (to avoid confusion) 8- the low_stack macro to facilitate dynamic stack expansion 9- if, back to GP main loop, the last command was a print1(), output an extra newline. This way the prompt is guaranteed to be anchored on column 1 (suppresses a readline display bug as well) 10- Due to 9, pari.el now supposes the prompt starts in col. 1 11- Better handling of version numbers (LG) 12- decodefactor() renamed to factorback() Removed: 1- The (unused, undocumented) Malloc_Procs functions and macros 2- The (now unused) error message numvarer 3- some (useless, undocumented) targets in the top Makefile 4- (useless, undocumented) function polgcd() Added: 1- This file ! 2- new flags -ch, -cb, -cu (colour support) to gphelp (see its header) IZ 3- OS/2 (+ enough tools...) supported by Configure 4- file examples/Inputrc (example of .inputrc for readline) 5- Weber f1 function implemented 6- Karatsuba multiplication t_REAL x t_REAL (development code, not used by PARI yet). Test it with install if you wish pari-2.17.2/CHANGES-2.60000644000175000017500000014412714567450071012504 0ustar billbill# $Id$ Bug numbers refer to the BTS at http://pari.math.u-bordeaux.fr/Bugs/ Done for version 2.7.0 (released 21/03/2014): Fixed 1- e = ellinit(E over Qp); ellztopoint(e, 3) --> SEGV 2- thue((x^2+1)^2*(x^2-2),-4) --> missing solutions [+-1, +-1] BA 3- spaces in directory names were not supported 4- silent overflow when inputing t_REAL of huge exponent [#1526] 5- zeta(2+10^-101*I) -> overflow 6- RgX_mullow(f,g,n) could return a result of degree n (instead of < n) Same with RgX_sqrlow 7- ellrootno(E) could lead to a SEGV [#1527] 8- issquare(Mod(3,22)) -> 0 [#1528] JD 9- polcyclo(5, Mod(-1,3)) was the negative of correct value JD 10- elltors(ellinit("90c3")) returned Z/12 but a generator of order 6 11- thue(thueinit(x^3-x-1),1578191) => oo loop [#1532] 12- catastrophic cancellation in eint1 (x moderately large) 13- SEGV in ellweilpairing [#1535] 14- factor(Mod(1,2)*Pol(1)) -> [Mod(0, 2) 1] 15- Mod(Pol(0), 2) -> 0, instead of Mod(0,2) 16- QXQ_to_mod was called with t_POLMOD arguments 17- ellwp(E, 'z) had stopped working for E not defined over C 18- nfdisc(T, t_MAT=partial discriminant factorization) => corruption [#1542] 19- norm(Mod(z,T)) where z is not a t_POL or in a different variable than T => wrong result [#1539] 20- polresultant(Pol(Mod(0,2)), x) -> 0 instead of Mod(0,2) 21- nffactor(T, pol) possibly wrong results when nfinit(T) is not rigorously computed [#1545] 22- gmodgs(t_POLMOD,): incorrect implementation BA 23- library functions Fp_pow/Fp_pow mishandled negative basis 24- gcd(1/(2^64*y),Mod(x^2,2^64*x^3)) --> inconsistent gcd [#1541] 25- matadjoint([x,0,0;0,0,0;0,0,0]) => wrong variables [#1547] 26- ellordinate(e, exact t_COMPLEX) => either a wrong result (no solution) or a solution computed at an incorrect accuracy (DEFAULTPREC) [#1548] 27- weber(1.0*I,1) => SEGV [#1549] 28- primepi(2^32) => oo loop [on 32-bit machine] 29- primepi(N >= 2^32 or 2^64) off by 1 JD 30- [libpari] initprimetable(2^20): infinite recursion 31- very inefficient div_rfrac_pol() [#1537] 32- polresultantext(x+1,x^2) -> [-# + 1, 1, 1] 33- for(i=a, b, ) where a < 0, b < 0 : go through wrong indices if #a != #b 34- printf("%1.2f",Mat([1.,2.])) -> SEGV [#1550] Added BA 1- library functions FlxX_to_FlxC, FlxXV_to_FlxM, polx_FlxX BA 2- library function Flx_lead 3- library function RgV_to_RgM Done for version 2.6.2 (released 30/01/2014): Fixed 1- eulerphi(t_INT factorization) corrupted the input BA 2- 8bit chars were interpreted as end of input 3- Bernoulli numbers were no longer cached [2.6.0] 4- typo in Brillhart, Lehmer, Selfridge primality test [#1467] 5- [Configure] confusing error messages when C compiler doesn't work 6- scalar + t_SER = 0 => wrong valuation (1+O(x)-1 => O(x^2)) BA 7- squaring of t_REAL was not faster than multiply 8- 1+O(2^(2^18)) => O(2^0) (silent overflow) PB 9- Mod(1, 2) - Mod(2, 4) => Mod(-1,2) [#1469] 10- memory corruption in subgrouplist: e.g. subgrouplist([53835600, 29], 5) 11- SEGV in zncoppersmith (when auxilliary polynomial was non-monic) 12- division by 0 in Fl_ellcard_Shanks [2.6.1, #1474] 13- ellwp([1,I]) -> stack overflow [2.6.0] 14- sumdedekind(h < 0, k < 0) wrong result; if gcd(h,k) > 0 as well 15- galoisexport(G, 1) -> SEGV 16- ??default(log) no longer worked 17- rnfalgtobasis, rnfbasistoalg, rnfeltup, rnfeltdown, rnfeltabstorel, rnfeltreltoabs were not treating their inputs consistently, and accepted (or crashed on) too many incorrect inputs. 18- rnfideal* did not handle correctly the 0 ideal 19- rnfidealtwoelt(non integral ideal) => crash 20- nfeltreducemodpr(K, non invertible elt mod pr,...) => wrong result (now an e_INV error) 21- rnfbasis: wrong result due to a mistake in gen_if_principal [2.6.0, revert d62f0de01] 22- nfsolvemodpr(nf,a,b,P): a must be invertible, as in matsolve (was not documented, used to SEGV). Raise an error if not. 23- various bnrdisclist crashes 24- bnrclassno(bnf, prime ideal) -> SEGV 25- forpart(x=k,) raised an exception if k < 0 [ now empty loop ] 26- deriv(constant) now returns 0 in the base ring (not gen_0). 27- inconsistencies and mistakes in deriv / intformal of t_POLMOD: forbid integration wrt the main variable of x.mod, deriv(Mod(x, x^2),x) was Mod(1,x^2) and deriv(Mod(y,x^2),y) was 0 instead of respectively 0 and Mod(1,x^2) 28- idealchinese with t_POLMOD inputs -> input error 29- idealchinese with denominators -> SEGV 30- qflll(Mat(0)) returned Mat(1) 31- infinite loop in sumpos: sumpos(n=1,-log(cos(1/n))) [#1481] BA 32- doing allocatemem in the break loop would corrupt the new break loop 33- relative error in eint1 was larger than expected 34- select(t_LIST,,1) [ indirect select ] didn't work 35- vecsort(List(),,4) -> SEGV 36- factorpadic / polrootspadic lost accuracy when converting output from integers to t_PADICs (factorpadic(t^2 + 3^5, 3, 5) -> irreducible factor (1 + O(3^5))*t^2 + O(3^5)*t + O(3^0) 37- Mod(0,0) is no longer valid => division by 0 (as Mod(x,0) for x != 0) 38- RgX_to_RgV no longer accepts other types than t_POL. Use Rg_to_RgV for a more permissive function 39- broken Fq_sqrt when T != NULL and t_INT input 40- ispower(1009^11) -> 0 [2.6.0] 41- ellinit([0,1,1,0,1],2).group -> SEGV 42- nfroots(nf, deg 1 polynomial) -> wrong result 43- Configure --time=ftime: wrong reported timings 44- mateigen(rational matrix): inconsistent concatenation [#1489,2.6.0] 45- polroots(): wrong accuracy of (real) 0 components 46- randomprime(2) -> SEGV [#1493, 2.6.0] 47- forqfvec(v,[;],0,) -> SEGV [#1495] 48- poliscyclo(x^0) -> 2 49- truncation (precision) errors in bnfnarrow [#1491] 50- matadjoint assumed that n! is invertible. If this is not the case, now use a safe algorithm 51- leading coefficient of elldivpol ignored the characteristic,e.g. E=ellinit([a1,a2,a3,a4,a6*Mod(1,2)]); elldivpol(E,2) 52- gcd involving a t_FFELT -> SEGV 53- oo loop in ispower for huge arguments / oo loop in prime iterator in congruence classes [#1498, 2.6.0] 54- L=[1,2,3]; apply(x->L=x,L) -> SEGV ( idem select and [|x<-] operators ) 55- (k+1.)/k - (2*k+1.)/k -> incorrect object 56- gcd(x,0.) -> 1 but gcd(x,Pol(0.)) -> x [ the former is correct, since 0. is inexact and may represent an arbitrary small non-zero real number ] 57- eint1 misbehaved at large precision [#1499] 58- polredbest(T,1) incorrect if T non-monic or degree 1 59- nfcertify might miss a factor to be certified, e.g. P=polcompositum(x^4+437*x+19,x^5-571*x+27)[1]; nfcertify(nfinit(P, [2,3,5])) was empty 60- polresultantext(t_POL in y, t_POL in y,y) -> U/V as t_POL in x [#1509] 61- inconsistent handling of t_POL "divided by" scalar among the variants of Euclidean division (%, divrem, \, ...). E.g. x % 2 is OK, but x % Mod(2,3) was not. We now follow the semantic of grem/gdeuc/poldivrem: a scalar is understood as a t_POL of degree 0 in the proper variable [#1510] 62- incorrect rounding in mulur BA 63- Configure: --includedir was ignored 64- add GC in RgV_dotproduct / RgV_dotsquare 65- ZX equal was checking variables, contrary to the spirit of the specification (and contrary to RgX_equal). Specify behaviour properly: none of the internal .*[xX]_equal function check variable numbers. 66- arithmetic functions did not accept factorizations of negative integers (whereas most of them are defined for negetive integers) BA 67- Configure --time=ftime actually tested times, not ftime. Remove ftime from the default list of timer functions (reports wallclock time, not CPU time) [#1523] 68- polredabs() could (find then) forget some polynomials [#1511] 69- poldisc(x^3 + Mod(2,3)*x^2) --> e_INV 70- (Mod(4.,y^2+1)*(1 + O(x)))^(1/2) -> junk (= [2.0+O(x)),2.0+O(x)]~). Worse if other t_POLMOD coefficients. Now exception. 71- sin(O(p)) returned 1+O(p) instead of O(p) Changed 1- default help text for a user function is now as in \u: fun = (args)->body 2- after addhelp(f,...), ?f no longer include default help text for a user function (function code). Type 'f' to see the function code. 3- primes([a,b]) now returns the primes in the interval [a,b] 4- install: add symbol name in library and GP prototype to default help 5- the rnf structure format 6- library functions: rename rnfelementxxx -> rnfeltxxx, rnfidealhermite -> rnfidealhnf 7- allow mathnf(t_VEC) [ apply Mat() automatically ], gives acces to the ZV_gcdext() routine. 8- mathnf(,2) (generic vs integral t_MAT) is deprecated: we always test the matrix entries and choose the appropriate routine 9- bnrclassno: allow all standard ways to define class fiels (A,B,C), not only bnf + module 10- bnrinit(bnf,f): allow using idealstar(bnf,f) in place of f 11- Let Set(t_VECSMALL v) behave as Set(Vec(v)) 12- ffgen(T) now checks whether T is squarefree (testing for irreducibility is too expensive) 13- variable() no longer raises exceptions: if no variable can be associated to the object, return 0. Thus "if (!variable(x), )" may be used to test whether x has a "variable". JD 14- polcyclo(n, x) now works for all roots of 1 15- quadpoly no longer accepts vector/matrix arguments, see 2.6.0,C94 16- [libpari] renamed ZM_hnfremdiv -> ZM_hnfdivrem 17- x t_REAL * y t_INT: either convert y to t_REAL (as before) or use integer multiplication (if lg(x) >> lg(y)) 18- GP: all results are now stored in GP history, together with the time to obtain them [ we used to only store non-gnil results, and no timings ] 19- chinese(t_POL,t_POL): allow polynomials of different degrees 20- deplin(): use FpM/Flm/F2m routines if possible (like all other generic linear algebra routines) 21- FpM_gauss(a,b,) from modular kernel no longer allow all types of input: split into FpM_FpC_gauss (b t_COL) and FpM_gauss (b t_MAT). Same for all modular xxx_gauss functions 22- O(1/x^2) --> error [ now equivalent to O(x^-2) ] 23- faster evaluated polhermite/pollegendre 24- polhensellift / ZpX_liftfact: use quasi-linear ZXX_mul_Kronecker instead of RgX_mul (~ Karatsuba) 25- [libpari] renamed gcmpX -> gequalX 26- [libpari] renamed ordred -> polredord 27- the prid structure returned by idealprimedec: the anti-uniformizer tau (pr_get_tau) is now stored via its multiplication table 28- rnfpolredabs(x,3) did not conform to the documentation (which did not make sense). Fix documentation and function, for rnfpolredbest as well. 29- [libpari] renamed recip -> serreverse 30- lift(x,'v) / centerlift(x,'v) now only lift t_POLMODs in variable v, no longer (most) t_INTMOD / t_PADICs met along the way 31- lift / centerlift no longer raise an exception when they encounter a non-arithmetic type (e.g. a t_REAL or even a t_STR) in a structure. They just copy the offending sub-object as-is. 32- generic polynomial Euclidean division (grem, gmod, poldivrem): when result is the zero polynomial, use RgX_get_0, not gen_0 / pol_0 33- rnf.pol (absolute defining polynomial / Q) is now called rnf.polabs, rnf.pol is now the relative polynomial, defining the relative extension over the base. BA 34- FpXYQQ_pow: change order of moduli to be consistent with FpXQXQ_pow. BA 35- FlxYqQ_pow: renamed to FlxYqq_pow, and moduli order changed. 36- idealstar(K,id), allow to input 'id' as a factorization into prime ideals, as produced by idealfactor 37- define eulerphi(0) = 2 [ now eulerphi(n) = znstar(n).no for all n ] 38- allow subst(t_SER,x,exact 0): subst(2+O(x),x,Mod(0,3))->Mod(2,3) [#1513] 39- [libpari] rename gsh -> gsinh, gch -> gcosh, gth -> gtanh, gash -> gasinh, gach -> gacosh, gath -> gatanh, ggamd -> ggammah (follow GP names) 40- no longer naively use the Karatsuba/3M formula to multiply t_COMPLEX of t_REALs: loss of accuracy is too important and unpredictable from the user's point of view [ e.g. (1+ 1e-90*I)*(1e90+I) -> 1. E90 + 0.E52*I, when the definition directly yields 1. E90 + 2*I ]. Could use it when the exponents of real/imaginary parts are close, increasing the precision by the exponent difference (increasing overhead...): not done yet. 41- renamed mpexp1 -> mpexpm1, cxexp1 -> cxexpm1 42- change prototye of mpsincos1 and rename -> mpsincosm1 Added EP 1- Configure option for gcov/lcov support 2- libpari function FF_f, member function g.f for t_FFELT (definition field has p^f elements) 3- libpari functions gprimepi_upper_bound, gprimepi_lower_bound, primepi_lower_bound, primes_interval, primes_interval_zv, primes_upto_zv, primes0 4- libpari functions rnf_get_absdegree, rnf_get_invzk, rnf_get_map, rnf_get_nf, rnf_get_nfdegree, rnf_get_nfpol, rnf_get_nfvarn, rnf_get_pol, rnf_get_polabs, rnf_get_zk, rnf_get_nfzk, rnf_get_varn, rnf_get_disc, rnf_get_index, RgV_is_QV, RgX_equal_var 5- allow rnf.disc, rnf.index 6- functions rnfelttrace, rnfeltnorm 7- function ZV_gcdext, based on ZM_hnflll (simplified) 8- allow ffgen(p^f) instead of ffgen(ffinit(p,f)) 9- [libpari] Fq_sqrtn 10- mathnfmodid(m, d): allow d an arbitrary vector of positive integers. The old syntax (d an integer, representing a vector of equal integers) is still allowed LGr11- GP function Colrev 12- GP operator %#n to recover time used to compute history result %n 13- GP function getabstime() 14- [libpari] Rg_to_F2, RgV_to_F2v, RgM_to_F2m, F2c_to_mod, F2m_to_mod, Flc_to_mod, Flm_to_mod, F2m_F2c_invimage, F2m_invimage, F2m_suppl, Flm_suppl, F2m_rank, Flm_rank, F2m_rowslice, F2v_slice, F2v_ei BA 15- Parallel GP support (parapply, pareval, parfor, parforprime, parselect, parsum, parvector) 16- [libpari] residual_characteristic 17- GP function characteristic() 18- [libpari] muluui, diviuuexact 19- [libpari] Kronecker_to_ZXX, ZXX_mul_Kronecker BA 20- conversion from matrices of FFELTs to low level (Fq/Flxq/F2xq) kernels for faster treatment. 21- FqM_det, FlxqM_det, FlxqM_inv, F2xqM_det, F2xqM_inv, F2xqM_image, F2xqM_image, F2xqM_rank, FFM_det, FFM_image, FFM_ker, FFM_rank, FFM_inv 22- ZM_rank, ZM_indexrank, ZM_indeximage 23- GP function normlp BA 24- GP function vecsum 25- [libpari] pr_equal, ZC_nfval, ZC_nfvalrem, ZC_prdvd, ZV_Z_dvd 26- allow .p / .e / .f / .gen for modpr structures 27- function rnfpolredbest 28- functions qfnorm, qfbil 29- [libpari] ZM_multosym, RgM_multosym, RgMrow_RgC_mul, RgM_transmul, RgM_transmultosym, ZM_transmultosym 30- [libpari] nf_rnfeq, nf_rnfeqsimple, eltreltoabs, eltabstorel, eltabstorel_lift, nf_nfzk, nfeltup, QXV_QXQ_eval, QXX_QXQ_eval 31- [libpari] factor_pn_1_limit 32- [libpari] get_FpXQ_star, gener_FpXQ_local BA 33- move gpinstall to libpari 34- liftall() lifts recursively all t_INTMOD/t_PADIC/t_POLMOD components 35- liftint() lifts recursively all t_INTMOD/t_PADIC components 36- liftpol() lifts recursively all t_POLMOD components BA 37- GP function logint PB 38- [libpari] gen_matmul, gen_matcolmul, FFM_mul, FqM_FqC_mul, FqM_mul, F2xqM_mul, F2xqM_F2xqC_mul, FlxqM_FlxqC_mul, FlxqM_mul. 39- [libpari] Flx_equal, F2x_equal BA 40- [libpari] FpM_powu/Flm_powu/F2m_powu 41- new GP function idealprincipalunits 42- [libpari] checkabgrp, abgrp_get_no, abgrp_get_cyc, abgrp_get_gen, bid_get_grp, bid_get_no 43- [libpari] FpX_disc 44- [libpari] retmkcomplex 45- GP function expm1 (= exp - 1, avoiding cancellation) Removed 1- optional flag to factorpadic() [ enabling Buchman-Lenstra + round2 ] Use the default = round4 2- useless wrappers map_proto_GG, map_proto_GL, map_proto_lGG 3- [libpari] useless functions gand, gor 4- [libpari] useless function ratlift [ use Fp_ratlift ] Done for version 2.6.1 (released 20/09/2013): Fixed 1- Allow compounding 1-letter flags to gp, e.g. qp -qf [ used to silently ignore the 'f' ] 2- ellminimalmodel, followed by ellchangecurve ==> structure incorrectly updated [wrong Q_MINIMALMODEL component] [2.6.0, #1416] 3- lift(1/2+O(2))=2/1 --> incorrect result + corrupt object [2.6.0, #1424] 4- local() could corrupt polynomial variable of the same name 5- write did not fclose() the output file handle [2.6.0, #1425] PB 6- issquare(Mod(1,2)) -> domain error [2.6.0, #1429] PB 7- issquare(Mod(0,2),&s); s -> Mod(2,0) error [2.6.0, #1430] 8- ellheight(E not given by minimal model,P) -> domain error [2.6.0, #1432] 9- ellchangecurve(E, [1,0,0,0]) lost Q_MINIMALMODEL ->SEGV later [2.6.0] 10- warning() would print "warning: user warning:"-> "user warning:" [2.6.0] 11- matinverseimage(A, t_MAT B) would treat individual columns B[,i] independently and successively. Now use a single Gauss reduction. 12- Flm_Fl_mul returned a wrong result 13- ellinit(ellfromj(Mod(0,17))) -> curve defined over Z [2.6.0, #1436] 14- allocatemem: make sure fix_size() is called to avoid alignment problems [#1437] 15- ellmodulareqn(2) did not clean the stack properly [2.6.0, #1442] 16- issquare(Mod(13,121)) --> not an n-th power residue in Qp_sqrt [2.6.0] 17- stack corruption in carberkowitz / charpoly(,,3) [ session crash ] 18- ellinit(E over Fp, t_FFELT) => error [2.6.0] 19- mateigen([5/3,7/45;0,21/10]) => precision error (missing eigenspace) 20- subst(O(x^2),x,0*x) => SEGV [#1447] 21- memory corruption in aprcl [2.6.0] 22- factormod(,2) => wrong result [2.6.0, #1451] 23- dirmul/dirdiv: incorrect result length when valuation > 1 24- x,y a t_PADIC, x === y always returned 0 [2.6.0] 25- bernpol(0) => memory corruption [2.6.0, #1458] 26- round((1e-40+x) / (1e-39+x)) would create the invalid object x/x 27- polgalois(x^11 + 627*x^4 - 584) -> F_110 instead of S_11 [#1460] 28- input lines with more than 2^31 characters (without \n) resulted in a truncated read [#1461] 29- znlog(1,Mod(8,9)) -> division by 0 [#1463] 30- plot(x=1,2,x) gave a graph with 0<=y<=2, instead of ymin<=y<=ymax 31- ?= or even = would apparently hang GP (waiting for further input) Added 1- genus2red: an implementation of Liu's algorithm to determine the reduction of a genus 2 curve (at p > 2). Based on genus2reduction-0.3, http://www.math.u-bordeaux1.fr/~liu/G2R/ (Cohen & Liu, 1994) mostly rewritten from scratch: - adapted to pari-2.* - somewhat modularized - fixes all known instances of 'bug27' and 'bug28' (at p = 3, reported through Sage users). - bench 'genus2red' contains a check of at least one instance of each of Namikawa-Ueno's types + all cases on which the original genus2reduction was known to fail. [CAVEAT: the interface will change] 2- allow to startup gp with flags --default key=val (or -D key=val): execute default(key,val) on startup BA 3- functions Flm_center, Flv_center, zv_to_Flv, zm_to_Flm, zm_mul, zm_zc_mul, scalar_Flm BA 4- function minim_raw 5- function QX_complex_roots PMo 6- function forpart for looping over partitions 7- [libpari] forcomposite_init / forcomposite_next, reimplement forcomposite() using this iterator 8- Configure now generates a file 'config.log' to help debugging when it makes a mistake (contains all messages from compilers) 9- [libpari] RgM_invimage, RgM_RgC_invimage, FpM_invimage, FpM_FpC_invimage, Flm_invimage, Flm_Flc_invimage, Flm_neg 10- [libpari] serchop0, integser functions 11- psi(t_SER) using Luke's recursion, then lngamma, gamma, gammah for t_SER arguments around an arbitrary complex z0 (was implemented for z0 = 0,1 only) PB 12- PARI functions FlxqM_gauss, FlxqM_inv and FqM_gauss 13- PARI functions FpM_hess, FpM_charpoly, charpoly, RgM_Rg_sub, RgM_Rg_sub_shallow 14- generic driver for GP's charpoly(): select appropriate algorith (flag) depending on input type. BA 15- allow ellsearch(t_VEC) : search for curve with given name, in given isogeny class or with given conductor; alias for the existing ellsearch(t_STR) as per the ellconvertname correspondance 16- option flag to mateigen: also return the eigenvalues 17- [libpari] Z_lvalrem_stop, u_lvalrem_stop 18- [libpari] ZX_rescale_lt BA 19- Port of the program ISOM by Bernt Souvignier for computation of automorphisms and isomorphisms of lattices. New GP functions qfauto, qfisom, qfisominit, qfautoexport 20- [libpari] RgX_mullow, RgX_sqrlow 21- [libpari] embed_T2, embednorm_T2, embed_roots, embed_disc, embed_norm 22- arithmetic functions now accept factorization matrices, you can use any of f(N), f(factor(N)) or f([N, factor(N)]) 23- GP function readstr 24- allow lists of elements in chinese() Changed 1- gp --primelimit lim (gp -p lim) is deprecated. Use the generic form 'gp -D primelimit=lim' (setting primelimit is now mostly useless, anyway) 2- gp --stacksize lim is deprecated. Use gp -s lim or the generic form 'gp -D parisize=lim' 3- partitions() interface to match forpart() 4- improve qfbred(t_QFI) for "small" inputs 5- bnfnewprec: ensure we recompute bnf from scratch at most once (could happen many times in makematal()) 6- [make bench] properly align results if 'printf' is available 7- [libpari] the *_invimage function no longer accept a t_COL second argument: use the RgM_RgC_invimage variant. They now return NULL when no solution exist (used to return a t_COL / t_MAT of length 1) 8- [libpari] replace the forvec_start() function by a standard iterator: forvec_init() / forvec_next() 9- [libpari] Z_lvalrem would destroy its argument. No longer. 10- znprimroot(p^k) now always returns the smallest primitive root (was only true for k = 1) 11- gmul / gsqr for t_SER with t_INTMOD coefficients: reduce to Z[X] + Kronecker substititution (quasi-linear vs. Karatsuba) 12- Mulders/Hanrot-Zimmerman short products for power series HC 13- new mpveceint1 implementation: faster and more precise 14- version string for development versions: added number of reachable commits (as per git rev-list). Affects version() [#1346] Removed 1- drop support for "gp -b buffersize" (obsolete since 2.2.10, 04/2005) 2- drop backward compatibility 'gp -emacs', 'gp -test'. Use the '--emacs' and '--test' forms. Done for version 2.6.0 (released 15/05/2013): Fixed 1- Euclidean chains were confused by t_POLs with t_INTMOD/t_POLMOD coeffs [ because a 0 polynomial could have lg() == 3 ] 2- numerical instability in ellheightoo [#1204] 3- Flm_gauss(m, smallish p): fix and enable the OK_ulong switch [ faster ] 4- remi2n didn't allow negative arguments [native kernel] [#1215] 5- ellrootno(e, p) started by computing a global minimal model for e instead of a local one at p. 6- qfbred(t_QFR) wrong when frac( sqrt(D) ) > 0.5 7- add GC in sumalt() 8- problems with diagnostic messages when changing a 'default', e.g. \o3 9- divru() could call bfffo(0) => overflow in expo() AMe10- (t_FRAC<0) * t_INTMOD => wrong result 11- trace(t_POL or t_SER) could yield an unormalized object [0 leading term] LGr12- off-by-1 error in primepi() when argument is = primelimit 13- bestappr(0.*x+1) -> incorrect object 14- znlog(3, Mod(3,8), 2) -> error 15- crash when default(prettyprinter,...) points to a non-existent command 16- qfperfection(): wrong result in unlucky cases [#1223] 17- allocatemem() did not reset parse error [#1226] BA 18- (x->vector(1,j,x))(1) --> significant pointers lost [#1211] VL 19- [makefile] Incorrect -I and -L flags order [#1212] 20- nfbasis / nfdisc(f,, partial factorization) would sometimes spend a lot of time trying to factorize a discriminant [#1227] 21- numerical instability in qfgaussred / qfsign [#1232] 22- missing consistency checks in conjvec [#1231] 23- numerical instability in polredabs [#1228, #1229] 24- wrong result in bezoutres [#1233] 25- wrong sign in polresultant() [#1234] 26- change default(realprecision) so that it returns the internal precision [ as precision(1.) ], not the number of printed digits. [#1235] 27- subst(Y/X,X,x) -> 0 PB 28- polrootsff(x^2-x-ffgen((v^2+1) * Mod(1,3))) -> SEGV [#1241] 29- intnum(t=[0,0],[1],(sin(t)/t)^2) -> "precision too low in mpsc1" BA 30- functions ending by the x[y]=z construct could corrupt the stack. 31- nfbasis(pol, 0, factorization containing (-1)^1) -> wrong [#1244] 32- qfminim(): better type checks for matrix entries 33- qfminim(): incorrect GC in smallvectors() 34- padicappr(x^2+1+O(3), -1+O(5^10)) --> no error 35- tests test-kernel and test-ploth were broken 36- lots of missing sanity checks in hilbert(x,y,p) [ e.g. hilbert(O(3), Pi, 5) -> 0 ] BA 37- for(i=1,10^7,) + SIGINT -> SEGV [#1249] 38- ellwp: take flag into account also for t_SER output [ was: numerical case only ] 39- factor(p) was much slower than isprime(p) for p a "small" prime BA 40- mateigen precision error was not trappable. 41- accuracy problems in bnfisunit [#1253] 42- broken rnfeltup [#1255] 43- x===y was always wrong for x,y t_SER BA 44- gamma(t_SER) with positive valuation did not work. 45- ispower(x < 0) could return an even value ! [#1259] 46- ispower(1 / n) return a wrong result [#1259] BA 47- [breakloop] initial context could be lost. BA 48- Ser([1+O(x)],x) returned an invalid object. BA 49- ispseudoprime used too much stack for huge operands. 50- [rnfidealup doc] idealgentoHNF() was incorrect. DS 51- elldivpol returned wrong result for degree n >=8. 52- overflow in mpbern(n) for huge n [#1256] 53- idealfactor(nf, non integral ideal) would remove a rational content instead of factoring A/B with A,B coprime integer ideal. Which led to costly factorizations [#1158] LGr54- the global variables associated to the primetable _maxprime / diffptr could become inconsistent 55- psdraw() ignored plot colors BA 56- stack_base() was not C89 standard compliant. BA 57- my(f(x)=x+1);f --> SEGV [#1273] 58- ellheight([0, 0, 1, -1, 0], [0., 0.]) -> BUG 59- allow bnrL1 over Q [#1279] 60- factorpadic(,,,1) => SEGV when linear factors/Q [#1278] 61- mathnf(..., 4) didn't remove 0 columns from HNF [#1271] JD 62- possible SEGV in pari_init_opts [#1264] BA 63- ellorder(E,P*Mod(1,p)) did not work if E was defined over Z 64- allow writebin to save user functions (t_CLOSURE) [#1171] 65- sqrtn(1+O(5),5) -> error, ispower(1+O(5),5) -> error [#1261] 66- parimacro.tex: pdftex --output-format dvi would produce a PDF BA 67- pari_close failed to free all allocated memory [#1297] BA 68- pari_close did not restore GMP memory functions 69- avoid outputing ANSI escape sequences to reset terminal state when unnecessary [#1289] BA 70- ellpointtoz was numerically unstable 71- issquarefree(0) => error [#1304] 72- sizebyte(t_LIST) returned the size of the wrapper type, not the list itself [#1307] 73- ellgroup(E over Q, p) now returns the structure of the group of non-singular points, when the curve has bad reduction at p. 74- factor_proven not taken into account in factor(n), where n is a BPSW-pseudoprime 75- core(5*(huge composite)^2) was very slow [#1305] 76- sqrt(0.E-97-1.12-97*I) -> div by 0 [#1309] BA 77- FpX_gcd(0,x) -> div by 0 78- x; y; p; q; subst(Mod(q,p), q, x + y) --> Mod(1, p)*x [#1321] 79- off-by-1 error when placing prime table sentinel after e.g. default(primelimit, 2); 80- t_REAL with huge exponents print incorrectly [#1322] 81- a1;a2;a3;a4;a6;ellinit([a1,a2,a3,a4,a6],1) was very slow BA 82- FpX_factorff and FpX_rootsff were not using standard argument order PB 83- printf("%.6f", 5E-5) -> SEGV [#1328] BA 84- diffop(Mod(y,x^2-y),[y],[1]) -> wrong result BA 85- calling a GP function with a lot of omitted arguments could cause a crash GH 86- missing solutions in thue(), e.g. thue(thueinit(x^3+92*x+1),3^3) 87- t_RFRAC == t_RFRAC could return a wrong result [#1339] 88- obscure bug in polroots() (sage #13314) 89- polinterpolate([1,2] * Mod(1,7), [2,3], 0) -> incorrect type in gabs BA 90- printf() did not flush output 91- logint() used too much memory and could return a wrong result: logint(3^64, 3) --> 33 92- eint1(x < 0) normalization. Now eint1(x) = incgam(0, x) [#418] 93- polrootsff(2*x+1,2,y) -> SEGV [#1350] 94- resultant(x,x,y) -> 0 and related problems 95- thue((x^4+1)^2, 4) -> no solution BA 96- idealramgroups() and idealfrobenius() did not accept a bnf 97- using new operators with default(compatible,3) caused a crash 98- rare corruption in ECM [#1240] factorint(,1) => SEGV 99- add missing call to normalize() in lift(t_POL/t_SER) [#1359] BA 100- listput was not SIGINT safe BA 101- znorder(Mod(5,16),200) -> 5 instead of 4 102- e.tate lost accuracy 103- 2-adic ellinit 104- allow ellinit over C 105- ellpointtoz(E / Qp, ...) [ wrong result / error messages ] JD 106- galoisinit(x^3+x^2-2*x-1) -> uninitialized read [#1389] BA 107- polhermite(66) -> corrupted result [#1393] 108- nfhnf() would only accept matrices of maximal rank BA 109- galoisfixedfield() could return a wrong result for polynomials with large roots [#1406] 110- bnrdisc could return a wrong result if the modulus had more than 2 prime divisors [#1399] 111- a = Mod(1,2)*x; gcd(a,a) return x instead of Mod(1,2)*x 112- changing primelimit from within forprime loop yielded unpredictable results (potential SEGV) 113- y;z;(x^2+y)*w/z/x -> significant pointers lost [#1248] 114- log(t_FRAC close to 1) => junk (idem lngamma) [#1238] 115- thue(thueinit(x^3-1493,1),3) -> error LGr116- typo in modr_safe -> precision error [#1413] 117- nfhnfmod(non-integral module) => wrong result nf=nfinit(y); A = [[1,1/2;0,1],[1,1]]; nfhnfmod(nf, A, nfdetint(nf,A)) BA 118- [native kernel] FFT mulii relied on unspecified order of evaluation Changed 1- mathnf: swapped flag 3 and 5. 2- allow ellinit([a4,a6]) [#1213] 3- ellinit(... singular curve ...]): return [] instead of raising an error 4- GP set elements are no longer converted to t_STR (requiring "eval" to recover the underlying object). Arbitrary GENs can be stored in a set. 5- moved Odos/* to relevant src/systems subdirectory 6- removed Odos directory 7- no longer allow Vec()/Vecrev(), Col(), Vecsmall(), without argument. Use [], []~, Vecsmall([]), respectively. 8- allow specifying an optional dimension in Vec/Vecrev, Col, Vecsmall. 9- allow Vecsmall(t_POL or t_SER) LGr10- nicer printout of small matrices: justify columns 11- improve gmul(t_REAL, t_FRAC) when numerator of t_FRAC is 1 BA 12- [darwin] do not use dylib_ prefix to ld options [#1210] 13- allow idealhnf(nf, t_QFI / t_QFR) for quadratic fields 14- no longer allow 3 arguments in bestappr() [useless], no longer mix Pade approximants and continued fractions [too confusing: must a t_SER be converted to a t_RFRAC or be treated coefficientwise?] 15- if znlog() has no solution, return [] instead of error 16- znlog(x, g): no longer assume that g is a primitive root, nor that the underlying (Z/N)^* is cyclic 17- renamed gen_eltorder -> gen_order 18- logfile: strip properly color escape sequences [#1225] 19- change nfbasis(T, flag, fa) to nfbasis(T, listP). flag was used to invoke round2 instead of round4 (inefficient=> useless) OR to only partially factor poldisc(T), up to primelimit (very dangerous since primelimit is a global variable). Now listP describes a list of primes, and we return a basis of an order which is p-maximal at all those primes: either a vector of primes, a factorisation (as fa before) or an integer B to indicated {p <= B} (a safe and flexible version of nfbasis(T, 1)). nfdisc() was changed similarly. 20- first call isanypower() in BPSP_psp_nosmalldiv() when input is > 2^512 [ < 1% of required time, 1 order of magnitude faster when it succeeds ] [ #1074 ] 21- sort polroots() output so that it no longer depends on current precision 22- delete README-subversion, replace with README-git 23- move README.os2 to src/system/os2/README 24- change compiler version printout in gp header 25- much faster final divisibility test in nfgcd() [#1214] 26- error type sqrter5 "not a quadratic residue in sqrt" now generalized to denote "not an n-th power residue in sqrtn" BA 27- global_err_data is now a GEN. BA 28- more usable form of alarm(s, code): evaluate code, aborting after s seconds. Return the result or a t_ERROR object. 29- [non-Unix systems] the name of the preferences file is now "gprc.txt" (it remains ".gprc" on Unix systems) 30- also look for the preferences file in PARI's "datadir" 31- removed rootsold() code : polroots(x, 1) is no longer accepted 32- rewrite ellan using C-longs + new function anellsmall() 33- renamed all libpari error codes [ pari_err() arguments ] 34- allow t_VECSMALL in vecextract 35- look for a few more short vectors in polred(), only return subfields and the best primitive polynomial [wrt discriminant] 36- [library] remove precdl argument in ellwp0: use a t_SER argument like in all other transcendental functions. 37- ellsigma / ellzeta: allow t_SER arguments, like ellwp. 38- polcoeff(x+2*y,1,y) -> 2 [ was 2*x^0 ] 39- quadhilbert / quadray: replace final polredabs call by polredbest [#1025] 40- listsort() now uses the cmp() comparison function, and becomes fully compatible with setsearch() [#1167] 41- vecsort(,,2) [lexicographic order] is now always on. The flag is now deprecated and ignored. 42- allow t_SER with integral coefficients to use asymptotically fast (ZX_mul / ZX_sqr) polynomial multiplication LGr43- let initprimes0 use an existing prime table 44- rename stackmalloc -> stack_malloc. Add stack_calloc 45- matimagecompl() now returns a permutation (t_VECMALL) no longer a t_VEC 46- remove config/gitversion from 'make snapshot' tarball JM 47- Better implementation of ellweilpairing/elltatepairing BA 48- agm now returns the optimal AGM 49- unify make_emacs_tags / make_vi_tags => make_tags + fix problems for (exuberant-ctags)-based etags. Both tag files (emacs / vi) contain the same tags now. 50- ellglobalred(E) now also returns the conductor factorization [4th compo] 51- library functions *_incremental_CRT no longer need the product of the moduli, instead they compute it and update the running modulus. 52- factor_proven now affects all the factoring machinery, as documented, i.e also multiplicative function (moebius, sumdiv,...) 53- allow t_VECSMALL in lex() 54- nfrootsof1(K) check whether K.pol is a translate of a cyclotomic pol. [initial patch LGr, #1175] 55- format of cached Bernoulli table: now a t_VEC of t_FRAC / t_REALs. Removed bern() macro. The new data must be accessed using bernfrac / bernreal. 56- [libpari] simplify init_primepointer(n, p, &pd) interface => init_primepointer(n, &pd). Remove argument 'p', ignore the previous value of pd [ remove assumption that it pointed into a prime table ] and always set pd to a pointer into the private prime table. 57- forprime loop: no longer allow to modify the loop index ? forprime(p = 2, 10, p = []) *** at top-level: forprime(p=2,10,p=[]) *** ^--- *** prime index read-only: was changed to []. 58- faster forparii() [ for() with t_INT lower bound ] 59- forprime(p = a, b, ...) now iterates over arbitrary ranges of primes, independently of 'primelimit'. Parameter 'b' can be omitted (no upper limit). More generally primelimit is no longer a true limit to iterate over primes: all libpari functions use the forprime_t interface 60- rename ggval -> gvaluation BA 70- GP function ellpow is renamed to ellmul BA 71- rename powell->ellmul, addell->elladd, subell->ellsub 72- is_pth_power interface [ pass a forprime_t iterator ] 73- polrootsmod(, 4) is no longer accepted 74- revert to Ramanujan's formula to compute Pi [ + binary splitting ] 75- polinterpolate(,, 'x) use divide & conquer algorithm BA 76- binary(0) now return [] 77- polisirreducible() now avoids factoring in most cases HC 78- reimplement incgam() 79- allow eint1(t_COMPLEX) 80- when 'echo = 1', no longer echo commands if they were entered interactively [commands ended up printed twice] 81- unless 'echo = 1', no longer log commands entered non-interactively when 'log = 1'. '\r file' used to log the entire content of 'file'. 82- allow thue(t_POL, rhs) for thue(thueinit(t_POL, rhs)) 83- elltors now uses division polynomials by default 84- modified "Hit Return to Continue" message so that it becomes a comment when copy-pasted 85- rnf_fix_pol() takes an extra argument, the calling function's name 86- fast gerepilecopy() for leaves 87- rename leftright_pow_fold -> gen_pow_fold, leftright_pow_fold_i -> gen_pow_fold_i 88- upowuu now returns 0 on overflow 89- primes(n) no longer needs precomputed primes 90- prime(n) no longer needs precomputed primes 91- primepi(n) no longer needs precomputed primes 92- removed 3s delay when recompiling PARI after modifying a header [ Was there to avoid problems on slightly out-of-synch NFS fileserver host. Had become an annoyance on fast multicore servers, esp. when bisecting to find a broken commit. ] 93- improve Configure --tune + let tune -t/-tt/-ttt print more and more verbose messages [ old 'tune -t' corresponds to current 'tune -tt' ] 94- arithmetic functions no longer accept vector / matrix arguments [ to later allow passing factorization matrices ]: use apply() BA 95- rename RgX_check_ZXY -> RgX_check_ZXX, ZXY_max_lg -> to ZXX_max_lg 96- elleta() and elleisnum(e, 2) to use a theta series formula in O~(prec^(3/2)) instead of O~(prec^2). BA 97- zv_cmp0 renamed to zv_equal0 98- allow ellinit / Qp for arbitrary reduction type 99- ellpointtoz(E / Qp, ...), now return phi(P) [ used to return the same result for phi(P) and phi(-P) [ split multiplicative reduction ], resp. phi(P) + 1/phi(P) [ non-split reduction ] 100- ellinit(E / Qp).tate : the u component is now always a square root of u2, also in the non-split case (in which case it lives in a quadratic extension of Qp) 101- renamed library function divsum() => sumdivexpr() 102- listpop(empty list) => no-op [ was "domain error" ] 103- ellap, ellak, ellan: allow non-minimal model 104- when timer = 1, no longer print timing if the time is negligible; in particular, no timing should be printed when defining a user function or and alias. 105- The proper way to initialize an nf structure when the polynomial discriminant is hard to factor is nfinit([T, listP]), where listP specifies a list of primes (see ??nfinit). nfdisc, nfbasis, all the polred functions allow analogous arguments (see Changed-19). This is cleaner and more flexible than old flags relying on the value primelimit (e.g. nfinit([T, nfbasis(T, 1)]), now deprecated). Also, the nfinit function now sees the local specifications and can take steps to avoid problems (instead of taking for granted a basis, without knowing whether it is correct or not). The result can also be certified (nfcertify) 106- polredabs() with (deprecated) nf_PARTIALFACT flag (or new [T,listP] argument) now returns 0 if the resulting order cannot be proven to be maximal. 107- rename bezout() -> gcdext(), polresultant() -> polresultantext() 108- the prime table is now computed once and for all on startup and can no longer be increased by modifying primelimit: the dynamic forprime machinery allows fast primes up to primelimit^2 which is more than enough even with a small table. The default value of 500.000 is already larger than necessary 109- removed the mechanism allowing prime gaps larger than 255 in the prime table: as a result it now limited to 436273290, allowing fast primes up to 1.9 10^17 BA110- permtonum/numtoperm now use the standard lexicographic numbering 111- issquare(t_INTMOD), ispower(t_INTMOD): factor modulus incrementally, in case we hit a local non-residue -> early abort [#1376] 112- gphelp + OS/X : make "open" the default PDF viewer (was "acroread") 113- renamed exp_Ir -> expIr Added 1- mathnf for matrices over K[X] [#41] BA 2- GP function ellheegner BA 3- asm inline macro addllx8 for faster addition BA 4- Library function FpXQ_autpowers 5- GP default 'linewrap' 6- functions Fp_issquare, Fq_issquare. 7- GP function cmp [ universal comparison ] 8- library functions Fp_addmul, addmulii, addmulii_inplace, addmuliu, addmuliu_inplace, lincombii, mulsubii, submulii, submuliu, submuliu_inplace LGr 9- Catalan's constant [ Catalan() ] BA 10- library functions F2x_issquare/F2x_sqrt BA 11- [INSTALL] Documentation of RUNTEST 12- library function bestapprPade 13- library function gen_factored_order, Fp_factored_order 14- macros retmkvec, retmkvec2, retmkvec3, retmkvec4, retmkcol, retmkcol2, retmkmat, retmkmat2, retmkintmod, retmkpolmod retmkintmod, retmkpolmod, retconst_col, retconst_vec 15- allow Ser(t_VECSMALL) BA 16- library function gsprintf/gvsprintf BA 17- new PARI type t_ERROR (error messages) BA 18- new error trapping system and GP functions iferr,iferrname BA 19- implement lngamma(t_PADIC) LGr20- new PARI functions F2m_gauss, F2m_inv, F2m_rank, F2m_image, matid_F2m, F2m_mul, F2m_F2c_mul BA 21- GP function getenv 22- new error class e_PRIME [ pari_err() ] BA 23- low-level function int_bit 24- library function stack_strcat 25- function polredbest [ adapting a preliminary patch by BA ] BA 26- library functions Fl_invsafe, F2x_halfgcd, Flx_Flxq_eval and Flx_FlxqV_eval. BA 27- support for sparse matrix and Wiedemann algorithm 28- GP function vecsearch() [ use with vecsort() ] BA 29- library function Z_issmooth BA 30- linear sieve algorithm for Fp_log/znlog BA 31- library functions Flx_to_FlxX, F2m_to_Flm, F2c_to_Flc, and Flxq_powu 32- GP function idealnumden() LGr33- library function uprecprime() 34- library function ZM_pivots() 35- library functions nm_Z_mul, ZM_togglesign, ZM_nm_mul [ to improve Zlm_gauss ] BA 36- [breakloop] GP functions dbg_up/dbg_down (like gdb up/down) 37- library functions rootsof1_Fp, rootsof1u_Fp, rootsof1_Fl BA 38- GP functions dbg_x (like \x) and dbg_err (current error data) 39- matconcat() BA 40- library functions Flm_Fl_add, Flm_invimage, FlxY_evalx BA 41- library functions Flx_ffisom, Flx_ffintersect, Flxq_ffisom_inv BA 42- library functions Flx_is_irred, Flx_is_smooth, F2x_is_irred BA 43- accessors functions for t_CLOSURE: closure_arity,closure_codestr,closure_get_* 44- library functions ZMs_ZC_mul, ZpMs_ZpCs_solve, gen_ZpM_Dixon BA 45- [breakloop] GP function breakpoint BA 46- GP function ffnbirred BA 47- cubic sieve algorithm for Flxq_log BA 48- library functions F2x_F2xqV_eval, F2x_F2xq_eval BA 49- forqfvec() BA 50- library functions FqM_image, FqM_rank, FpXQXQ_powers, FpXQXQ_matrix_pow BA 51- ellgroup(,,1): also return the generators BA 52- library functions FpVV_to_mod, FpE_changepoint, FpE_changepointinv BA 53- GP syntax [a..b] : [a,a+1,...,b] BA 54- GP syntax [a(x)|x<-b,c(x)] : apply(a,select(c,b)) BA 55- GP syntax M[a..b,^c] : vecextract(M,"a..b","^c") BA 56- library function FpE_log 57- select(f, v, 1) for indirect selection 58- hamming() function [initial implementation CG] 59- ispowerful() function 60- polgraeffe() function 61- functions poliscyclo(), poliscycloprod(), polcyclofactors() 62- function setbinop(f,X,Y) = { f(x,y), x in X, y in Y } 63- libpari function moebiusu() 64- sumdigits() function 65- libpari functions addiu, addui, subiu, subui, uissquare 66- randomprime() function. Allow random([a,b]) (return n, a <= n <= b) 67- ispolygonal() function 68- libpari functions uissquarefree, uposisfundamental, unegisfundamental 69- istotient() function 70- implement Haible/Papanikolaou binary splitting BA 71- PARI functions FlxqX_nbroots, FpXQX_nbroots, FpXQX_nbfact. BA 72- PARI function zv_search BA 73- GP syntax: multiif if(a==1,b,a==2,c,default). BA 74- GP syntax: multi assignement: [a,b,c]=V -> a=V[1];b=V[2];c=V[3] BA 75- PARI functions gen_gener, gen_ellgroup, gen_ellgens, gen_powers BA 76- FlxqE functions family (for elliptic curves over field of small characteristic>3) BA 77- PARI functions Flxq_sqrt, FpXQ_sqrt 78- bernpol() function 79- sumformal() function BA 80- PARI functions ZX_equal1, zvV_equal, ZXV_equal, FpXX_neg, FqX_neg BA 81- FpXQE functions family (for elliptic curves over field of large characteristic) BA 82- added GP function ellcard BA 83- PARI functions FpXQ_powu, Fq_powu, FpXX_mulu, Fq_mulu, Fq_div BA 84- PARI functions FqXQ_powers, FqXQ_matrix_pow, FqX_mulu, FqX_Fq_add BA 85- PARI functions FqXY_eval, FqXY_evalx, FpXY_Fq_evaly BA 86- SEA over non-prime finite field (for char p > 1000) LGr87- Add clock_gettime timer option 88- add new error type e_DOMAIN BA 89- Add black box finite fields for generic linear algebra BA 90- PARI functions FlxqM_image, FlxqM_ker, FqM_deplin BA 91- GP function ellneg BA 92- PARI functions Fp_ellcard, FpXQ_ellcard, Flxq_ellcard LGr93- vecmax / vecmin: add optional pointer argument (to hold index of a largest/smallest entry) 94- printsep() function CG 95- isprimepower() function 96- PARI functions F2v_to_F2x, F2x_valrem, F2x_deflate, F2x_shift 97- PARI function RgV_polint BA 98- GP function digits 99- GP default 'sopath' [ rewritten from initial patch by GTo ] LGr100- allow polylog(n, t_SER) around a != 0 BA 101- PARI functions ZX_shifti, ZX_remi2n, ZXV_remi2n 102- PARI functions cxexp1, mpsincos1 BA 103- GP function ellfromj 103- GP function forcomposite 104- new error class e_PRIORITY [ pari_err() ] BA 105- Add black box algebra for Brent and Kung algorithm 106- PARI function RgM_dimensions() BA 107- PARI functions RgX_splitting(), Flx_splitting() 108- made public the CATCH / TRY interface, renamed pari_CATCH / pari_TRY PARI functions err_get_num(), err_get_compo(), pari_err_last() 109- PARI function stack_sprintf() 110- PARI function RgX_is_QX() BA 111- PARI functions retmkmat2,retmkcol2,mkmat2,mkcol2,mkcols,mkcol2s et al. BA 112- PARI functions ZXV_dotproduct(), ZXX_Z_divexact() BA 113- PARI function gen_ZpX_Newton() 114- optional argument to contfracpnqn: return all convergents up to p_n/q_n, not only the last 2 BA 115- PARI functions Flxq_autpow, F2xq_autpow BA 116- PARI functions FpX_divrem_Barrett and unconditional FpX_rem_Barrett BA 117- PARI functions F2xq_sqrt_fast, Flxq_lroot, Flxq_lroot_fast BA 118- PARI functions FlxqV_dotproduct, FlxV_red BA 119- PARI functions ZpXQ_inv, ZpXQ_invlift, ZpXQ_log 120- PARI functions absi_shallow, mpabs_shallow, absfrac_shallow, Q_abs_shallow BA 121- PARI functions FlxX_Flx_add, FlxX_Fl_mul, FlxX_Flx_mul, FlxX_neg BA 122- PARI functions Fp_ellj, FpXQ_ellj, Flxq_ellj BA 123- PARI functions FpX_mulu, Flx_mulu, ZX_mulu BA 124- PARI functions FlxqXQV_autpow, FlxqXQV_autsum BA 125- PARI functions FpXQXQV_autpow, FpXQXQV_autsum BA 126- PARI functions FpXT_red, FlxT_red, ZXT_to_FlxT, ZXT_remi2n BA 127- Support for preconditionned reduction in FpXQ/Flxq 128- PARI functions padic_to_Q, padic_to_Q_shallow, QpV_to_QV, Q_pvalrem, ZX_Zp_root, Zp_appr, Fp_muls, retmkfrac BA 129- Add safegel et al. for GP2C -C option HC 130- Function sqrtnint 131- sumdivmult() to sum multiplicative functions 132- ?? online help: allow searching labels, e.g. ??"se:priority"@ 133- PARI function ZpM_echelon, zlm_echelon 134- GP functions matqr and mathouseholder, PARI functions QR_init, QgM_QR_init, gaussred_from_QR, R_from_QR, gtomp, RgC_gtomp, RgM_gtomp 135- PARI functions trivial_fact, prime_fact 136- PARI function rfrac_to_ser 137- PARI functions padic_lindep, Xadic_lindep 138- GP function seralgdep BA 139- arm, mips and mips64 level0 inline assembly kernel 140- new error class e_COMPONENT 141- PARI functions init_primepointer_geq, init_primepointer_gt, init_primepointer_leq, init_primepointer_lt BA 142- new default strictargs for mandatory arguments 143- GP function nfcertify 144- GP function ellchangepointinv 145- optional 'variable' argument to polresultantext() 146- export part of the ifac_* interface (ifact_start, ifact_next, ifac_read, ifac_skip, ifac_isprime) 147- PARI function expIxy 148- poor man's graphic engine 'plotps' (Configure --graphic=ps) when no graphic library is available; dumps the hi-res plot to a temporary PostScript file, then opens a PostScript viewer ('open -W' by default, $GP_POSTSCRIPT_VIEWER otherwise). Works around #1354 on OS/X. PMo149- GP function lambertw / library functions mplambertW, glambertW Removed 1- dropped DOS support 2- qfrep(): bit 2 of flag is now meaningless, we now always return a t_VECSMALL 3- file language/errmsg.c and global errmessage[] array: all error messages are now part of pari_err_display()) 4- error types arither1,mattype1,notpoler (merged with typeer), matinv1 (merged with gdiver) 5- legacy lindep and PSLQ implementations [algdep/lindep with negative flags]: now use LLL in all cases. BA 6- [libpari] removed unusable functions dbg_close/dbg_release. 7- [libpari] gisfundamental, gkronecker, gbigomega, geulerphi, gissquarefree, gmoebius, gnextprime, gnumbdiv, gomega, gprecprime, gsumdiv, gdumdivk, znprimroot0 8- ellsigma: flags 3 and 4 [ inefficient algorithm using the product formula ] 9- Member function 'w' (this is technical, and no longer needed:-) 10- obsolete function weipell(). Use ellwpseries() 11- [libpari] obsolete function Polred. Use polredbest 12- old logo misc/pari.xpm, see http://pari.math.u-bordeaux1.fr/logo.html pari-2.17.2/README-git0000644000175000017500000001027314676526175012653 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 https://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 https://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. 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 origin/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.17.2/INSTALL0000644000175000017500000000154014567450071012226 0ustar billbillAssuming your system is a fairly standard Unix, you can quickly build/test GP in the following way: a) ./Configure ( --prefix=/exotic/dir/name if desired. Default is /usr/local. ) b) make all, make bench c) make install, if desired d) copy misc/gprc.dft to /etc/gprc [sitewide] or $HOME/.gprc [personal] Documentation can be found in directory doc. Compile and read doc/INSTALL.tex (e.g cd doc; tex INSTALL; xdvi INSTALL) for detailed installation instructions. P.S: Useful optional packages can be downloaded separately http://pari.math.u-bordeaux.fr/packages.html in particular elldata: Cremona's Elliptic Curve Data, needed by ellsearch and ellidentify; galdata: needed by polgalois to compute Galois group in degrees 8 through 11; galpol: a database of Galois polynomials for galoisgetpol seadata: allow ellcard(E) for large finite fields. pari-2.17.2/LICENSE0000644000175000017500000000124014676526175012211 0ustar billbillPARI/GP Number Theory-oriented Computer Algebra System Copyright (C) 2000-2023 The PARI Group, Bordeaux. PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. Check the License for details. You should have received a copy of it, along with the package; see the file 'COPYING'. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. pari-2.17.2/CHANGES0000644000175000017500000000761514760306547012204 0ustar billbillBug numbers refer to the BTS at http://pari.math.u-bordeaux.fr/Bugs/ [last column crossreferences current development release 2.18.1] Done for version 2.17.2 (released 01/03/2025): Fixed BA 1- ellrootno over number fields could be slow [#2595] [F2] BA 2- matsolvemod could fail [#2604] [F3] BA 3- nfcompositum(nfinit(y-2),x^2-y,x^3-x-1) -> error [#2605] [F4] 4- Mod(a,A) == Mod(b,B) was checking a == b && A == B instead [F6] of the documented Mod(a,A) - Mod(b,B) == 0 [F6] 5- normlp(, oo): support components equal to oo or -oo [F8] 6- sqrtn(27+O(3^4),3) -> 1 + O(3) (wrong valuation in Qp_sqrtn_ram) [F10] 7- vectorsmall(5, i, 2^63-1).normfu -> SEGV [F11] AP 8- alginit(nf,[a,b]) would reject a in basis form [F13] BA 9- for(i=1,10^6,bernpol(5,1)) -> "no more variables" [#2611] [F14] BA 10- Flx_mod_Xn1(T,n), deg T >= 2*n -> wrong result [F15] 11- forprime(p=1099505335069-100000,1099505335069+10000,) -> crash [F16] [last column crossreferences current development release 2.18.0] Done for version 2.17.1 (released 24/12/2024): Fixed BA 1- incorrect GP proto for ellpadicfrobenius, mftocoset, qfcvp [#2575] [F1] AP 2- fix idealismaximal for ideal p*ZK [Sage issue 38766] [F2] AP 3- segfault in algsubalg when input is linearly dependent [F3] AP 4- fix alglatinter trivial intersection (misuse of matkermod(,1)) [F4] BA 5- ellrank could try many more curves than requested by effort [#2577][F5] 6- wrong result in issquare(Mod(a, composite)) [#2578] [F6] 7- gener_FpXQ_local(t_POL of degre 1) -> oo loop [#2581] [F7] 8- GC error when squaring integer 2x2 matrices [#2582] [F8] AP 9- algebras: fix splitting field for CSA, algtomatrix / algcharpoly were sometimes wrong by an automorphism of the center [F9] BA 10- paridecl.h could conflict with complex.h [#2583] [F10] 11- forprime(p=524288,1048576,1) -> crash [#2584] forprime(p=1048607,1048617,1) -> oo loop [F11] 12- printf("%10.6f", tiny rational) -> undefined result [#2576] [F12] AP 13- alginit(nf,[a,b]) was only allowing a,b integral over the power basis instead of arbitrary algebraic integers. [F13] HC 14- zeta not continous around 1/2+3000*I [#2585] [F14] 15- missing type checks for change of variables in ellchangecurve, [F15] ellchangepoint, ellchangepointinv BA 16- control-C could lead to segfault later [#2496] [F16] 17- [libpari] missing normalization in FpX_mulu (when p is not prime) [F18] HC 18- mfsymboleval could return wrong sign [#2586] [F19] 19- missing type checks in factorback [#2590] [F20] BA 20- charpoly(Mod(x,x^20+1/2)) -> crash [#2591] [F21] 21- psi(x close to a nonpositive integer) -> error [F22] BA 22- polresultant(t_POL with RFRAC coeffs) could be incorrect [#2588] [F24] BA 23- qflll(non-maximal rank) -> potential oo-loop [#2587] [F25] Added BA 1- [loongarch64] add loongarch64 assembly kernel Done for version 2.17.0 (released 30/09/2024): Fixed 1- rare SEGV in sumnumrat [#2566] 2- gp -p N did not check for N < 2^32 3- nflist([6,8],12167) -> SEGV [#2567] 4- nflist([6,1],1229312), nflist([6,10],36192256) -> duplicate fields AP 5- variable leak in algsplit 6- mfslashexpansion: possible extra rational factor [#2572] 7- nfeltsign: possible wrong result Added BA 1- [libpari] Flm_sqr Changed BA 1- qflll(,1), qfllgram(,1): disable FLATTER algorithm. 2- tunings of forprime over "short" intervals (use sieve more frequently) pari-2.17.2/Configure0000755000175000017500000001407014567450071013046 0ustar billbill#! /bin/sh # # This file is part of the PARI/GP package. # # PARI/GP is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License as published by the Free Software # Foundation. It is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY WHATSOEVER. # # Check the License for details. You should have received a copy of it, along # with the package; see the file 'COPYING'. If not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # Configuration file for GP/PARI. Run Configure --help for Usage. # # Perl's Configure and GNU autoconfig were of much help in writing these files. # $Id$ TOP=`pwd` MAKE=${MAKE:-make} config_dir=config data_dir=data doc_dir=doc examples_dir=examples misc_dir=misc src_dir=src desc_dir=src/desc case "$RUNTEST" in /*);; */*) 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" command_line0="$0 $@" . ./get_config_options ####################### CONFIGURE - SHELL ################################### . ./get_nl # how to get echo without \n ? (for config questions) . ./get_PATH # We might need the following : echo Looking for some tools first ... _tools_list='gzip cc gcc ld perl zcat' pathspace=`echo $PATH | sed -e "s/$dir_sep/ /g" | sed -e 's,\\\\,/,g'` for file in $_tools_list; do x=`./locate $file '' $pathspace` eval $file=$x case $x in # support also DOS filesystems (hard drive prepended) ?:/*|/*) echo ..."$file is $x";; *) echo ..."I could not find $file." >&2;; esac done if test -z "$zcat" -a -n "$gzip"; then zcat="$gzip -dc"; fi ####################### CONFIGURE - ARCHITECTURE ############################ . ./get_archos # arch, osname config_log="$TOP/config-$arch-$osname$$.log" cat > $config_log<< EOT This file contains messages produced while configuring pari-$pari_release $patchlevel_verbose to aid debugging if Configure makes a mistake. Command line was > $command_line0 EOT exec 5>> $config_log ####################### CONFIGURE - COMPILATION ############################# # $_cc_list (includes 'optimization'), extraflag . ./get_cc # . ./get_mt # doubleformat, sizeof_long . ./get_double_format # asmarch, pretty . ./get_kernel # _dl_list, DLCFLAGS, update CFLAGS . ./get_dlcflags # $_ld_list . ./get_ld # $_dlld_list . ./get_dlld # $_perl_list . ./get_perl ####################### CONFIGURE - LIBC #################################### . ./get_libc # $_has_list, RT_LIBS, DL_LIBS ####################### CONFIGURE - LIBRARIES ############################### # Looking for libraries: gmp, X11, fltk, Qt, readline echo Checking for optional libraries and headers... # $_gmp_list if test "$kernlvl1" = "gmp"; then . ./get_gmp fi # $_graphic_list . ./get_graphic_lib # $_readline_list (includes 'readline') case "$without_readline" in yes);; *) . ./get_readline esac ############################################################################# case $kernlvl1 in gmp) libpari_base=pari-gmp;; none) libpari_base=pari;; esac case $enable_tls in yes) libpari_base="${libpari_base}-tls" esac if test `expr $VersionMinor % 2` = 0; then libpari_base=$libpari_base-$version fi ####################### CONFIGURE - MAKE #################################### . ./get_install # $_install_list . ./get_objdir # objdir, cdobjdir . ./get_static # static # For dynamic linking, before and after installing runpath=\"$libdir\" LDDYN="-lpari" # get_modld needs $includedir from get_install, static, and LDDYN . ./get_modld # $_modld_list # Which copy, SHELL ? case "$osname" in os2) ln_s=cp; make_sh=sh;; *) ln_s="ln -s"; make_sh="/bin/sh";; esac ####################### CONFIGURE - CLEANUP ################################# rm -f gmon.out # created by Configure -pg rm -f *.gcno *.gcda # created by Configure -gcov ####################### CONFIGURE - SPIT #################################### . ./get_tests #_test_list # Now spit out the results cat << EOT ========================================================================== EOT cd "$TOP" if test ! -d $objdir; then mkdir -p $objdir; fi rm -f $objdir/config.log; mv $config_log $objdir/config.log dflt_conf_file=$objdir/$dflt_conf_file cat > $dflt_conf_file << EOT # Config file for Pari $release -- $pretty EOT case "$osname" in os2|mingw) shell_q='"'; echo "shell_q='\"'" >> $dflt_conf_file;; *) shell_q="'"; echo "shell_q=\"'\"" >> $dflt_conf_file;; esac for variable in\ pari_release pari_release_verbose version libpari_base static objdir\ arch asmarch osname pretty prettyf\ kernlvl0 kernlvl1 RT_LIBS DL_LIBS MT_LIBS LIBS\ dir_sep runpath runpathprefix LDDYN RUNTEST\ ln_s make_sh\ sizeof_long doubleformat\ thread_engine enable_tls\ runtime_perl\ $_tools_list\ $_test_list\ $_install_list\ $_perl_list\ $_cc_list\ $_ld_list\ $_dl_list\ $_dlld_list\ $_graphic_list\ $_modld_list\ $_readline_list\ $_gmp_list\ $_has_list; do eval "echo $variable=\'"'$'"$variable\'" \>\> $dflt_conf_file done . $config_dir/extract_files # Building... cat << EOT ========================================================================== EOT if test -n "$tune"; then echo "Building and tuning PARI (this may take a while)" echo (cd $objdir; rm -f parilvl1.h pariinl.h;\ $MAKE tune && tune -t > tune.h.new && mv tune.h.new tune.h && cat tune.h\ && rm -f parilvl1.h pariinl.h && $MAKE gp) else echo $n "Shall we try to build pari $version.$patch ($status) now (y/n)? $c" dflt=n; rep='y n'; . $config_dir/myread fi mkobjdir=`$config_dir/objdir` cdobjdir= if test "$objdir" != "$mkobjdir"; then cdobjdir="cd $objdir; " fi case $ans in y) if (cd $objdir; $MAKE gp); then echo $n "Shall we install the files where they belong (y/n)? $c" dflt=n; rep='y n'; . $config_dir/myread case $ans in y) $MAKE install;; n) echo "Ok. Type \"${cdobjdir}make install\" when you are ready";; esac fi;; n) echo "Ok. Type \"${cdobjdir}make install\" when you are ready";; esac echo 'Bye !' pari-2.17.2/doc/0000755000175000017500000000000014760315601011734 5ustar billbillpari-2.17.2/doc/libpari.tex0000644000175000017500000000143114567450071014105 0ustar billbill% Copyright (c) 2000 The PARI Group % % This file is part of the PARI/GP documentation % % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License % Compile with plain TeX % \def\TITLE{User's Guide to the PARI library} \input parimacro.tex % START TYPESET \begintitle \vskip 2.5truecm \centerline{\mine User's Guide} \vskip 1.truecm \centerline{\mine to} \vskip 1.truecm \centerline{\mine the PARI library} \vskip 1.truecm \centerline{\sectiontitlebf (version \vers)} \vskip 1.truecm \authors \endtitle \copyrightpage \tableofcontents \chapterskip \chapterskip \chapterskip { \input usersch4 } { \input usersch5 } { \input usersch6 } { \input usersch7 } { \input usersch8 } { \input appb } { \input appd } \input index\end pari-2.17.2/doc/tutorial-mf.tex0000644000175000017500000024700214567450071014734 0ustar billbill\documentclass[11pt]{article} %\overfullrule=5pt \usepackage{amsmath} \usepackage{amsfonts} \usepackage{amssymb} \DeclareMathOperator{\Tr}{Tr} \DeclareMathOperator{\PSL}{PSL} \DeclareMathOperator{\SL}{SL} \DeclareMathOperator{\GL}{GL} \newcommand{\Q}{{\mathbb Q}} \newcommand{\Z}{{\mathbb Z}} \newcommand{\R}{{\mathbb R}} \newcommand{\C}{{\mathbb C}} \newcommand{\z}{\zeta} \newcommand{\al}{\alpha} \newcommand{\be}{\beta} \newcommand{\ga}{\gamma} \renewcommand{\z}{\zeta} \renewcommand{\th}{\theta} \newcommand{\G}{\Gamma} \newcommand{\new}{\text{new}} \def\kbd#1{{\tt #1}} \begin{document} \pagestyle{plain} \title{Tutorial for Modular Forms in Pari/GP} \author{Henri Cohen} \maketitle \smallskip \section{Introduction} Three packages are available to work with modular forms and related functions in \kbd{Pari/GP}. The first one is the $L$-function package, which has been available since 2.9.0 (2015), and computes with general motivic $L$-functions, and in particular with $L$-functions attached to Dirichlet characters, Hecke characters, Artin representations, and modular forms. The name of most functions in this package begins with \kbd{lfun}, such as \kbd{lfuninit}. The second is the modular symbol package, whose primary aim is not so much to compute modular form spaces and modular forms, but to compute $p$-adic $L$-functions attached to modular forms. The name of most functions in this package begins with \kbd{ms}, such as \kbd{msinit}. The third package is the modular forms package, whose aim is to compute in the standard spaces $M_k(\G_0(N),\chi)$ with $k$ integral or half-integral, both with modular form \emph{spaces} and individual modular \emph{forms}. The name of most functions in this package begins with \kbd{mf}, such as \kbd{mfinit}. The goal of the present manual is to describe this package in view of a guide for a new user, so will essentially be a tutorial, although we include a reference guide at the end. \medskip We can work on five subspaces of $M_k(\G_0(N),\chi)$, through a corresponding \emph{space flag} in the commands: the cuspidal \emph{new space} $S_k^{\new}(\G_0(N),\chi)$ (flag = 0), the full cuspidal space $S_k(\G_0(N),\chi)$ (flag = 1), the old space $S_k^{\text{old}}(\G_0(N),\chi)$ (flag = 2, probably of little use), the space generated by all Eisenstein series ${\cal E}_k(\G_0(N),\chi)$ (flag = 3), and finally the full space including the Eisenstein part $M_k(\G_0(N),\chi)$ (flag = 4, which can be omitted since it is the default). Note that although it can be defined, we have not included the space $M_k^{\new}$, nor the ``certain space'' of Zagier--Skoruppa. In the half-integral weight case, we have included only the full cuspidal space and the full space (flags $1$ and $4$), as well as the Kohnen's $+$-space and the corresponding newspace and eigenforms when $N$ is squarefree. Note in particular that the package includes the computation of modular forms of weight $k=1$ and of half-integral weight. \medskip The modular forms themselves are represented in a special internal format which the user need not worry about and which basically is a recipe to compute successive Fourier coefficients at infinity: if $F$ is a GP modular form, \kbd{mfcoefs}$(F, 10)$ will give you the Fourier coefficients at infinity from $a(0)$ to $a(10)$ of the modular form corresponding to $F$ as a row \emph{vector} (if you want a power series expansion, use the GP function \kbd{Ser}, see below). Many operations are available on such objects, but the most important thing the user needs to know is that the number of Fourier coefficients need not be specified in advance: the command \kbd{mfcoefs}$(F,n)$ is valid for any integer $n$. We will of course explain the details of this below. \medskip Finally, note that we may roughly divide the complexity of available functions into three levels: \begin{enumerate} \item The first level includes all the basic modular form and modular spaces creation and operations. Many functions are very fast, but some are quite time-consuming for very different reasons; first those dealing with forms and spaces involving Dirichlet characters of large order; second finding eigenforms when the splitting using the Hecke algebra is difficult; and third modular spaces of weight $1$ when there exist ``exotic'' forms. Reasonable levels (for low weight) can go up to a few thousands. The critical parameter is actually the dimension of the underlying modular form space where linear algebra needs to be performed, so the time complexity is at least proportional to $(N\times k)^3$, and in fact more than that due to coefficient explosion in the base field $\Q(\chi)$. \item The second level needs technical information about spaces generated by products of two Eisenstein series, and is quite expensive. But it allows to perform computations which would be almost impossible otherwise, such as Fourier expansions of $f|_k\gamma$ (hence at any cusp), numerical evaluation of modular forms at any point in the upper half-plane (even close to the real axis) or $L$-functions attached to an arbitrary form. We have included a caching method, so that once a single such computation is performed in a given space, the needed technical data is stored and no longer needs to be computed so that all subsequent calls are much faster. Reasonable levels (for low weight) can go up to one thousand, say. Again, the critical parameter is the space dimension but this time the linear algebra is performed in large degree cyclotomic fields, even when the Nebentypus is trivial. Compared to the first level, we lose at least a factor $\Lambda(N)$ (the exponent of the multiplicative group $(\Z/N\Z)^*$) in the time complexity, which gets as large as $N-1$ if $N$ is prime. \item The third level, which uses the second level functions, allows more numerical computations such as period polynomials, modular symbols, Petersson products, etc\dots The time complexity does not increase much since it is dominated by the second level. \end{enumerate} \section{Creation of Modular Forms} In \kbd{Pari/GP} modular forms can be created in three different ways: \begin{itemize}\item As \emph{basic modular forms}, i.e., forms attached (or not) to different mathematical objects, and which are of so frequent use that we have implemented them so that the user has them at his disposal. Examples: \kbd{mfDelta} (Ramanujan's delta), \kbd{mfEk} (Eisenstein series of weight $k$ on the full modular group; of course we also have more general Eisenstein series), \kbd{mffrometaquo} (eta quotients), \kbd{mffromell} (modular form attached to an elliptic curve over $\Q$), \kbd{mffromqf} (modular form attached to a lattice). \item From existing forms by applying \emph{operations}. Examples: multiplication/division, linear combination, derivation and integration, Serre derivative, RC-brackets, Hecke and Atkin--Lehner operations, expansion and diamond operators, etc\dots \item Through the creation of the modular form \emph{spaces}: typically, if only \kbd{mf=mfinit} is applied, then a basis of forms is obtained by the command \kbd{mfbasis(mf)}. The command \kbd{mfeigenbasis(mf)} produces the canonical basis of eigenforms.\end{itemize} \section{A First Session: working with Leaves} This is now a tutorial session. We will see sample commands as we go along. \begin{verbatim} ? D = mfDelta(); V = mfcoefs(D, 8) % = [0, 1, -24, 252, -1472, 4830, -6048, -16744, 84480] \end{verbatim} The command \kbd{mfcoefs(D,n)} gives the vector of Fourier coefficients (at infinity) $[a(0),a(1),\dots,a(n)]$ (note that there are $n+1$ coefficients). This is a compact representation, but if you prefer power series you can use \kbd{Ser(V,q)} (convert a vector into a power series). \begin{verbatim} % = q - 24*q^2 + 252*q^3 - 1472*q^4 + 4830*q^5 - 6048*q^6\ - 16744*q^7 + 84480*q^8 + O(q^9) \end{verbatim} (This simple-minded recipe only works when the form has rational coefficients. Make sure to use \kbd{q = varhigher("q")} first if the form has nonrational algebraic coefficients to avoid problems with variable priorities.) Similarly \begin{verbatim} ? E4 = mfEk(4); E6 = mfEk(6); apply(f->mfcoefs(f,3),[E4,E6]) % = [[1, 240, 2160, 6720], [1, -504, -16632, -122976]] ? E43 = mfpow(E4, 3); E62 = mfpow(E6, 2); ? DP = mflinear([E43, E62], [1, -1]/1728); ? mfcoefs(DP, 6) % = [0, 1, -24, 252, -1472, 4830, -6048] ? mfisequal(D, DP) % = 1 \end{verbatim} Self-explanatory. Note that there is a command \kbd{mfcoef(F, n)} (without the final ``s'') which simply outputs the coefficient $a(n)$. A final example of the same type: \begin{verbatim} ? F = mffrometaquo([1,2; 11,2]); mfcoefs(F,10) % = [0, 1, -2, -1, 2, 1, 2, -2, 0, -2, -2] ? G = mffromell(ellinit("11a1"))[2]; ? mfisequal(F, G) % = 1 \end{verbatim} Here, \kbd{mffrometaquo} takes as argument a matrix representing an \emph{eta quotient}, here $\eta(1\times\tau)^2\eta(11\times\tau)^2$. The second component of the \kbd{mffromell} output is the modular form associated to the elliptic curve by modularity. \section{A Second Session: Modular Form Spaces} In the first session, we have seen a few preinstalled modular forms (that we can call \emph{leaves}), and a number of operations on them. All reasonable operations have been implemented (if some are missing, please tell us). We are now going to work with \emph{spaces} of modular forms. \begin{verbatim} ? mf = mfinit([1,12]); L = mfbasis(mf); #L % = 2 ? mfdim(mf) % = 2 \end{verbatim} This creates the full space of modular forms of level $1$ and weight $12$. This space is created thanks to an almost random basis that one can obtain using \kbd{mfbasis}, and we see either by asking for the number of elements of \kbd{L} or by using the command \kbd{mfdim}, that it has dimension $2$, not surprising. We can see it better by writing: \begin{verbatim} ? mfcoefs(L[1],6) % = [691/65520, 1, 2049, 177148, 4196353, 48828126, 362976252] ? mfcoefs(L[2],6) % = [0, 1, -24, 252, -1472, 4830, -6048] \end{verbatim} or simply \begin{verbatim} ? mfcoefs(mf,6) \\ apply mfcoefs to mfbasis elements % = [691/65520 0] [ 1 1] [ 2049 -24] [ 177148 252] [ 4196353 -1472] [ 48828126 4830] [362976252 -6048] \end{verbatim} Note two things: first, the Eisenstein series are given before the cusp forms (this may change, but for now this is the case), and second, the Eisenstein series is normalized so that it is the coefficient $a(1)$ which is equal to $1$, and not $a(0)$. In particular, here at least, it is a normalized Hecke eigenform. If we want to work only in the cuspidal space $S_{12}(\G)$, we simply use the flag $1$, such as: \begin{verbatim} ? mf = mfinit([1,12], 1); L = mfbasis(mf); #L % = 1 ? mfcoefs(L[1],6) % = [0, 1, -24, 252, -1472, 4830, -6048] \end{verbatim} Let us now look at higher dimensional cases. In the following example, we consider the \emph{new space} (flag = $0$), although in the present case this is the same as the cuspidal space: \begin{verbatim} ? mf = mfinit([35,2], 0); L = mfbasis(mf); #L % = 3 ? for (i = 1, 3, print(mfcoefs(L[i], 10))) [0, 3, -1, 0, 3, 1, -8, -1, -9, 1, -1] [0, -1, 9, -8, -11, -1, 4, 1, 13, 7, 9] [0, 0, -8, 10, 4, -2, 4, 2, -4, -12, -8] \end{verbatim} These are essentially random cusp forms. Usually, you want the eigenforms: this is obtained by the function \kbd{mfeigenbasis} (note in passing that \kbd{B=mfeigenbasis(mf)} adds components to \kbd{mf}, so that the next call is instantaneous). You can ask for the defining number fields with the command \kbd{mffields}. Note that these commands act only on the new space, but the package also accepts the spaces that contain it (such as the cuspidal space or the full space, but not the old space), although the result is only about the new space. \begin{verbatim} ? mffields(mf) % = [y, y^2 - y - 4] ? L = mfeigenbasis(mf); #L % = 2 ? mfcoefs(L[1],10) % = [0, 1, 0, 1, -2, -1, 0, 1, 0, -2, 0] ? mfcoefs(L[2],4) % = [Mod(0, y^2 - y - 4), Mod(1, y^2 - y - 4),\ Mod(-y, y^2 - y - 4),Mod(y - 1, y^2 - y - 4),\ Mod(y + 2, y^2 - y - 4)] ? lift(mfcoefs(L[2],10)) % = [0, 1, -y, y - 1, y + 2, 1, -4, -1, -y - 4, -y + 2, -y] \end{verbatim} The command \kbd{mffields} gives the polynomials in the variable $y$ defining the number field extensions on which the eigenforms are defined. Here, one of the fields is $\Q$, the other is $\Q(\sqrt{17})$. To obtain the eigenforms, we use \kbd{mfeigenbasis}, and there are only two and not three, since the one defined on $\Q(\sqrt{17})$ goes together with its conjugate. Asking directly \kbd{mfcoefs(L[2],4)} gives the coefficients as \kbd{polmods}, not easy to read, so it is usually preferable to \emph{lift} them, giving the last command, where in the output we must of course remember that $y$ stands for \emph{one} of the two roots of $y^2-y-4=0$, i.e., $(1\pm\sqrt{17})/2$. In fact, for some numerical computations, we really need the coefficients of the eigenform embedded in $\C$, and not just as abstract algebraic numbers (in our case of trivial character, they will be in $\R$). This is why a few functions (most notably \kbd{mfeval} and \kbd{lfunmf}) will return a \emph{vector} of results and not a scalar when called on such a form. For instance, here is a little GP script which computes the numerical expansion of a modular form instead of the expansion in \kbd{polmods}: \begin{verbatim} mfcoefsembed(F,n) = mfembed(F, mfcoefs(F,n)); \end{verbatim} Note that this produces a vector of expansions when the eigenforms are defined over an extension, i.e. $[\Q(F):\Q(\chi)] > 1$, one per conjugate form. \begin{verbatim} ? mfcoefsembed(L[2],5) \\ two conjugate forms %4 = [[0, 1, 1.5615..., -2.5615..., 0.43844..., 1], [0, 1, -2.561...,, 1.5615...,, 4.5615..., 1]] \end{verbatim} The first eigenform found above is \emph{rational}, hence by the modularity theorem there exists up to isogeny a unique elliptic curve to which it corresponds. We check this by writing \begin{verbatim} ? [mf,F] = mffromell(ellinit("35a1")); mfcoefs(F, 10) % = [0, 1, 0, 1, -2, -1, 0, 1, 0, -2, 0] ? mfisequal(F, L[1]) % = 1 \end{verbatim} For a more typical example (still with no character): \begin{verbatim} ? [ mfdim([96,2], flag) | flag <- [0..4] ] % = [2, 9, 7, 15, 24] \end{verbatim} This gives us the dimensions of the new space, the cuspidal space, the old space, the space of Eisenstein series, and the whole space of modular forms. Just for fun, we write (recall that the default is the full space): \begin{verbatim} ? mf = mfinit([96,2]); L = mfbasis(mf); ? for (i = 12, 15, print(mfcoefs(L[i], 15))) [23/24, 1, 3, 4, 7, 6, 12, 8, 15, 13, 18, 12, 28, 14, 24, 24] [31/24, 1, 3, 4, 7, 6, 12, 8, 15, 13, 18, 12, 28, 14, 24, 24] [47/24, 1, 3, 4, 7, 6, 12, 8, 15, 13, 18, 12, 28, 14, 24, 24] [95/24, 1, 3, 4, 7, 6, 12, 8, 15, 13, 18, 12, 28, 14, 24, 24] \end{verbatim} Apparently, these four Eisenstein series differ only by their constant term, which is of course not possible. Indeed: \begin{verbatim} ? F = mflinear([L[14],L[12]],[1,-1]); mfcoefs(F, 50) % = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\ 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0] ? G = mfhecke(mf, F, 24); mfcoefs(G, 12) % = [1, 24, 24, 96, 24, 144, 96, 192, 24, 312, 144, 288, 96] ? mftobasis(mf, G) % = [0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\ 0, 0, 0, 0, 0, 0]~ ? 24*mfcoefs(L[5], 12) % = [1, 24, 24, 96, 24, 144, 96, 192, 24, 312, 144, 288, 96] \end{verbatim} The first command shows that the Eisenstein series differ on their $n$-th Fourier coefficient for $n=0$, $24$, and $48$, and the second command applies the Hecke operator $T_{24}$ (sometimes denoted $U_{24}$) to the difference, whose effect is to replace $a(n)$ by $a(24n)$, giving the much more compact output of $G$. The last commands show that $G$ is equal to $24$ times the fifth Eisenstein series \kbd{L[5]}. \begin{verbatim} ? mf=mfinit([96,2],0); mffields(mf) % = [y, y] ? L = mfeigenbasis(mf); for(i=1, 2, print(mfcoefs(L[i], 16))) [0, 1, 0, 1, 0, 2, 0, -4, 0, 1, 0, 4, 0, -2, 0, 2, 0] [0, 1, 0, -1, 0, 2, 0, 4, 0, 1, 0, -4, 0, -2, 0, -2, 0] ? Fa = mffromell(ellinit("96a1"))[2]; mfcoefs(Fa, 16) % = [0, 1, 0, 1, 0, 2, 0, -4, 0, 1, 0, 4, 0, -2, 0, 2, 0] ? Fb = mffromell(ellinit("96b1"))[2]; mfcoefs(Fb, 16) % = [0, 1, 0, -1, 0, 2, 0, 4, 0, 1, 0, -4, 0, -2, 0, -2, 0] \end{verbatim} The \kbd{mffromell} function returns a triple \kbd{[mf,F,C]}, where \kbd{mf} is the modular form cuspidal space to which \kbd{F} belongs, \kbd{F} is the rational eigenform corresponding to the elliptic curve by modularity, and \kbd{C} is the vector of coefficients of \kbd{F} on the basis in \kbd{mf}, which we recall is usually not a basis of eigenforms (otherwise \kbd{F} would belong to this basis). Note also that \kbd{Fa} and \kbd{Fb} are twists of one another: \begin{verbatim} ? mfisequal(mftwist(Fa, -4), Fb) % = 1 \end{verbatim} \section{Interlude: Dirichlet characters} There are many ways to represent multiplicative characters on $(\Z/N\Z)^*$ in \kbd{Pari/Gp}, we will list them by increasing order of sophistication, restricting to characters with complex values: \begin{itemize} \item A quadratic character $(D/.)$ (Kronecker symbol) is described by the integer $D$. For instance $1$ is the trivial character. \item There is a (noncanonical but fixed) bijection between $(\Z/N\Z)^\times$ and its character group, via \emph{Conrey labels}. So \kbd{Mod}$(a,N)$ represents a character whenever $a$ is coprime to $N$. This makes it easy to loop on all characters without worrying too much about which is which. In this labeling, \kbd{Mod(1,N)} is the trivial character, and characters are multiplied/divided by performing the corresponding operation on their Conrey labels. \item The finite abelian group $G = (\Z/N\Z)^*$ is written $$G = \bigoplus_{i\leq n}\; (\Z/d_i\Z) \cdot g_i,$$ with $d_n \mid \dots \mid d_2 \mid d_1$ (SNF condition), all $d_i > 0$, and $\prod_i d_i = \phi(N)$. The SNF condition makes the $d_i$ unique, but the generators $g_i$, of respective order $d_i$, are definitely not unique. The $\oplus$ notation means that all elements of $G$ can be written uniquely as $\prod_i g_i^{n_i}$ where $n_i \in \Z/d_i\Z$. The $g_i$ are the so-called \emph{SNF generators} of $G$. The command \kbd{znstar}$(N)$ outputs the SNF structure (group order, $d_i$ and $g_i$), but $G = \kbd{znstar}(N, 1)$ is needed to initialize a group we can work with: most importantly we can now solve discrete logarithm problems and decompose elements on the $g_i$. A character on the abelian group $\oplus (\Z/d_j\Z) g_j$ is given by a row vector $\chi = [a_1,\ldots,a_n]$ of integers $0\leq a_i < d_i$ such that $\chi(g_j) = e(a_j / d_j)$ for all $j$, with the standard notation $e(x) := \exp(2i\pi x)$. In other words, $\chi(\prod g_j^{n_j}) = e(\sum a_j n_j / d_j)$. In this encoding $[0,\dots,0]$ is the trivial character. Of course a character $\chi$ must always be given as a \emph{pair} $[G,\chi]$, since $\chi$ is meaningless without knowledge of the $(g_i)$ or the $(d_i)$. \end{itemize} The command \kbd{znchar}$(S)$ converts a datum describing a character to the third form $[G,\chi]$. The command \kbd{znchartokronecker} converts a character of order $\leq 2$ to the first form $(D/.)$, and functions such as \kbd{zncharconductor}, \kbd{znchartoprimitive}, and \kbd{zncharinduce} allow to restrict or extend characters between different $(\Z/M\Z)^*$. Note the important fact that it is necessary to give the two arguments $G$ and $\chi$ separately to these functions, for instance \kbd{zncharconductor(G,chi)} (and not \kbd{zncharconductor([G,chi])}). Functions such as \kbd{charmul}, \kbd{chardiv}, \kbd{charpow}, \kbd{charorder} or \kbd{chareval} apply to more general abelian characters than characters on $(\Z/N\Z)^\times$, whence the prefix \kbd{char} instead of \kbd{znchar}. \section{A Third Session: Nontrivial Characters} Recall that a nontrivial character can be represented either by a discriminant $D$ (not necessarily fundamental), the character being the Legendre--Kronecker symbol $(D/n)$, or by its \emph{Conrey label} in $(\Z/N\Z)^\times$, for instance \kbd{Mod(161,633)} (which has order 42, as \kbd{znorder} tells us). Defining modular form spaces with character is as simple as without: we replace the parameters $[N,k]$ by $[N,k,\chi]$. Instead of \kbd{mf=mfinit([35,2])}, one can write \kbd{mf=mfinit([35,2,5], 0)}, where 5 is the quadratic character $(5/.)$. Thus: \begin{verbatim} ? mf = mfinit([35,2,5],0); mffields(mf) % = [y^2 + 1] ? F = mfeigenbasis(mf)[1]; lift(mfcoefs(F, 10)) % = [0, 1, 2*y, -y, -2, -y - 2, 2, -y, 0, 2, -4*y + 2] \end{verbatim} where in the last output $y$ is equal to one of the two roots of $y^2+1=0$, i.e., $\pm i$. Working with nontrivial characters allows us in particular to work with odd weights, and in particular in weight $1$: \begin{verbatim} ? mf = mfinit([23,1,-23], 0); mfdim(mf) % = 1 ? F = mfbasis(mf)[1]; mfcoefs(F, 16) % = [0, 1, -1, -1, 0, 0, 1, 0, 1, 0, 0, 0, 0, -1, 0, 0, -1] ? mfgaloistype(mf,F) % = 6 \end{verbatim} The last output means that the image in $\PSL_2(\C)$ of the projective representation associated to $F$ is of type $D_3$. Note that an ''exotic'' representation is given by a negative number, opposite of the cardinality of the projective image. Since this form is of dihedral type, it can be obtained via theta functions. Indeed: \begin{verbatim} ? F1 = mffromqf([2,1; 1,12])[2]; V1 = mfcoefs(F1, 16) % = [1, 2, 0, 0, 2, 0, 4, 0, 4, 2, 0, 0, 4, 0, 0, 0, 2] ? F2 = mffromqf([4,1; 1,6])[2]; V2 = mfcoefs(F2, 16) % = [1, 0, 2, 2, 2, 0, 2, 0, 2, 2, 0, 0, 4, 2, 0, 0, 4] ? (V1 - V2)/2 % = [0, 1, -1, -1, 0, 0, 1, 0, 1, 0, 0, 0, 0, -1, 0, 0, -1] ? mfisequal(F, mflinear([F1, F2], [1, -1]/2)) % = 1 \end{verbatim} Here we were lucky in that we ``knew'' that the correct character was $(-23/n)$. But what if we did not know this ? The first observation is that modular form spaces corresponding to Galois conjugate characters are isomorphic ($\chi$ is Galois conjugate to $\chi'$ if $\chi'=\chi^m$ for some $m$ coprime to the order of $\chi$). Thus, it is sufficient to find a representative of each equivalence class, and this is given by the \kbd{GP} commands \kbd{G=znstar(N,1); chargalois(G)}, where $N$ is the level of the desired character (note that $N$ will not necessarily be the conductor of the characters). This exactly outputs a list of representative of each equivalence class (do not for now try to understand the details of this command, nor the fact that \kbd{chargalois} and \kbd{znstar} have optional parameters). However, this is not quite yet what we want. Although only for efficiency, we want characters with the same parity as the weight, otherwise the corresponding modular form spaces will be $0$. This is achieved by the \kbd{GP} command \kbd{zncharisodd(G,chi)} which does what you think it does. Let us first do this for $N=23$: we write \begin{verbatim} ? G = znstar(23, 1); ? L = [chi | chi<-chargalois(G), zncharisodd(G,chi)]; #L % = 2 ? [mfdim([23,1,[G,chi]], 0) | chi <- L ] % = [0, 1] ? [charorder(G,chi) | chi <- L] % = [22, 2] \end{verbatim} This tells us that (up to Galois conjugation) there are two possible odd characters, one, of order $22$, giving a $0$-dimensional space, the other being the quadratic character given above. Note that \kbd{chargalois} returns (orbits of) characters attached to an arbitrary abelian finite group $G$ while \kbd{mfinit} expects a \emph{pair} \kbd{[G,chi]} for some \kbd{znstar} $G$, as written above. When doing long explorations with all characters of a certain level, it is preferable to use \emph{wildcards}. For instance, instead of the above one can write: \begin{verbatim} ? mfall = mfinit([23,1,0], 0); #mfall % = 1 ? mf = mfall[1]; mfdim(mf) % = 1 ? mfparams(mf) % = [23, 1, -23, 0] \end{verbatim} This does not exactly give us the same information: the third parameter $0$ in the first command asks for \emph{all} nonempty spaces of level $23$ and weight $1$, and the program tells us that there is only one, of dimension $1$. The last command \kbd{mfparams} outputs \kbd{[N,k,CHI,space]}, so here tells us that the corresponding character is the Kronecker--Legendre symbol $(-23/n)$. Using wildcards, let us explore levels in certain ranges: we write \begin{verbatim} wt1exp(lim1,lim2)= { my(mfall,mf,chi,v); for (N = lim1, lim2, mfall = mfinit([N,1,0], 0); /* use wildcard */ for (i=1, #mfall, mf = mfall[i]; chi = mfparams(mf)[3]; /* nice format: D or Mod(a,N) */ [ print([N,chi,-t]) | t<-mfgaloistype(mf), t < 0 ] ) ); } \end{verbatim} For instance, \kbd{wt1exp(1,230)} outputs in 4 seconds \begin{verbatim} [124, Mod(87, 124), 12] [133, Mod(83, 133), 12] [148, Mod(105, 148), 24] [171, Mod(94, 171), 12] [201, Mod(104, 201), 12] [209, Mod(197, 209), 12] [219, Mod(8, 219), 12] [224, Mod(95, 224), 12] [229, Mod(122, 229), 24] [229, Mod(122, 229), 24] \end{verbatim} Thus, the smallest exotic $A_4$ form is in level $124$ and the smallest $S_4$ form is in level $148$. Note that in level $229$, we have two (non Galois conjugate) eigenforms of type $S_4$. If we type \kbd{wt1exp(633,633)}, in 6 seconds we obtain \kbd{[633, Mod(107, 633), 60]}, and this level is indeed the lowest level for which there exists a type $A_5$ form. The character orders are obtained either as \kbd{znorder(chi)} (since all the \kbd{chi} are \kbd{intmods}), or using the general construction \begin{verbatim} [G,v] = znstar(chi); ord = charorder(G,v) \end{verbatim} where we first convert \kbd{chi} to a general abelian character in $[G,\chi]$ format. \section{Leaf Functions} Although we have already seen most of these functions in the first session, we repeat some of examples here. \subsection{Functions Created from Scratch} We now start a slightly more systematic exploration of the available functions. We begin by \emph{leaf functions}, i.e., functions created from scratch or from a given mathematical object. \begin{verbatim} ? D = mfDelta(); mfcoefs(D, 5) % = [0, 1, -24, 252, -1472, 4830] ? E4 = mfEk(4); mfcoefs(E4, 5) % = [1, 240, 2160, 6720, 17520, 30240] ? E6 = mfEk(6); ? D2 = mflinear([mfpow(E4, 3), mfpow(E6, 2)], [1, -1]/1728); ? mfisequal(D, D2) % = 1 \end{verbatim} Self-explanatory. More complicated Eisenstein series: \begin{verbatim} ? E3 = mfeisenstein(1, 1, -3); mfcoefs(E3, 10) % = [1/6, 1, 0, 1, 1, 0, 0, 2, 0, 1, 0] ? E4 = mfeisenstein(5, -4, 1); mfcoefs(E4, 10) % = [5/4, 1, 1, -80, 1, 626, -80, -2400, 1, 6481, 626] ? H2 = mfEH(5/2); mfcoefs(H2,10) % = [1/120, -1/12, 0, 0, -7/12, -2/5, 0, 0, -1, -25/12, 0] \end{verbatim} The \kbd{mfeisenstein(k,c1,c2)} command generates the Eisenstein series of weight $k$ and characters \kbd{c1} and \kbd{c2}. The \kbd{mfEH(k)} command is specific to half-integral weight $k$ and generates the Cohen--Eisenstein series of weight $k$. \begin{verbatim} ? T = mfTheta(); mfcoefs(T,16) % = [1, 2, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2] ? mf = mfinit([4, 5, -4]); mftobasis(mf, mfpow(T, 10)) % = [64/5, 4/5, 32/5] ? B = mfbasis(mf); apply(mfdescribe, B) % = ["F_5(1, -4)", "F_5(-4, 1)", "TR^new([4, 5, -4, y])"] ? mfisCM(B[3]) % = -4 \end{verbatim} Here, we compute the coefficients of $\th^{10}$ on the basis of \kbd{mf} (we know of course the level, weight, and character). We then apply the \kbd{mfdescribe} function, which tells us that the first two forms in the basis are Eisenstein series, and the third one is some trace form on the cuspidal new space. However, the last command says that this third basis element is a \emph{CM form}, so that its coefficients can be computed just as fast as those of Eisenstein series, so that there does exist an explicit formula for the number of representations as a sum of ten squares. Keeping the above sessions, we can also write: \begin{verbatim} ? mftobasis(mf, mfpow(H2, 2)) % = [1/18000, 1/18000, -3/2000]~ \end{verbatim} \subsection{Functions Created from Mathematical Objects} \begin{verbatim} ? [mf,F,co] = mffromell(ellinit("26b1")); co % = [1/2, 1/2]~ ? mfcoefs(F,10) % = [0, 1, 1, -3, 1, -1, -3, 1, 1, 6, -1] \end{verbatim} This creates the modular form attached by modularity to the second isogeny class of elliptic curves over $\Q$ for conductor $26$. The result is a 3-component vector: \kbd{mf} is the modular form space, $F$ the modular form, and \kbd{co} are the coefficients of $F$ on the basis of \kbd{mf}. Similarly, there are functions \kbd{mffromlfun} (from $L$-functions attached to eigenforms), \kbd{mffromqf} (from quadratic forms) and \kbd{mffrometaquo}: \begin{verbatim} ? F = mffrometaquo([1, 2; 11, 2]); mfcoefs(F, 10) % = [0, 1, -2, -1, 2, 1, 2, -2, 0, -2, -2] ? F = mffrometaquo([1, 2; 2, -1]); mfparams(F) % = [16, 1/2, 1, y] ? mfcoefs(F, 10) % = [1, -2, 0, 0, 2, 0, 0, 0, 0, -2, 0] \end{verbatim} The \kbd{mfparams} command tells us that $F\in M_{1/2}(\G_0(16))$. \section{Atkin, Hecke and Expanding Operators} \begin{verbatim} ? mf = mfinit([96,4], 0); mfdim(mf) % = 6 ? M = mfheckemat(mf, 7) % = [0 0 0 372 696 0] [0 0 36 0 0 -96] [0 27/5 0 -276/5 -276/5 0] [1 0 -12 0 0 62] [0 0 1 0 0 -16] [0 -3/5 0 14/5 -16/5 0] ? P = charpoly(M) % = x^6 - 1456*x^4 + 209664*x^2 - 2985984 ? factor(P) % = [x - 36 1] [x - 12 1] [ x - 4 1] [ x + 4 1] [x + 12 1] [x + 36 1] \end{verbatim} Note a few things: first, the matrix of the Hecke operator $T(7)$ does not have integral coefficients. Indeed, recall that the basis of modular forms in \kbd{mf} is mostly random, so there is no reason for the matrix to be integral. On the other hand, since the eigenvalues of Hecke operators are algebraic integers, the characteristic polynomial of $T(7)$ must be monic with integer coefficients. As it happens, it factors completely into linear factors to the power $1$, so all the eigenvalues of $T(7)$ are in fact in $\Z$: this immediately shows that the splitting will be entirely rational and the eigenforms with integer coefficients. Let's check: \begin{verbatim} ? mffields(mf) % = [y, y, y, y, y, y] ? L = mfeigenbasis(mf); for(i=1,6,print(mfcoefs(L[i],16))) [0, 1, 0, 3, 0, 10, 0, 4, 0, 9, 0, -20, 0, 70, 0, 30, 0] [0, 1, 0, 3, 0, 2, 0, 12, 0, 9, 0, 60, 0, -42, 0, 6, 0] [0, 1, 0, 3, 0, -14, 0, -36, 0, 9, 0, -36, 0, 54, 0, -42, 0] [0, 1, 0, -3, 0, 10, 0, -4, 0, 9, 0, 20, 0, 70, 0, -30, 0] [0, 1, 0, -3, 0, 2, 0, -12, 0, 9, 0, -60, 0, -42, 0, -6, 0] [0, 1, 0, -3, 0, -14, 0, 36, 0, 9, 0, 36, 0, 54, 0, 42, 0] \end{verbatim} We see that of the six eigenforms, the last three are twists of the first three. There also exists the command \kbd{G=mfhecke(mf,F,n)}, which given a modular form $F$ in \kbd{mf}, outputs the modular form $T(n)F$. \begin{verbatim} ? mf=mfinit([96,6],0); mffields(mf) % = [y, y, y, y, y, y, y^2 - 31, y^2 - 31] ? mfatk = mfatkininit(mf,3); % factor(charpoly(mfatk[2]/mfatk[3])) % = [x - 1 5] [x + 1 5] \end{verbatim} This requires a little explanation: the command \kbd{mfatkininit(mf,3)} computes a number of quantities necessary to work with the Atkin--Lehner operator $W_3$ in the space \kbd{mf}. The main part of the result is the second component, which is essentially the matrix of $W_3$ on the basis of \kbd{mf}, and which is guaranteed to have exact coefficients (here rational). However in the general case, the matrix of $W_3$ is equal to \kbd{mfatk[2]/mfatk[3]}, where \kbd{mfatk[3]} may be an inexact complex number. For now you need not worry about the first component. Thus, the eigenvalues (or possibly the pseudo-eigenvalues) must be of modulus $1$, and in the case of a quadratic character defined modulo $N/Q$, they are equal to $\pm1$ in even weight, to $\pm i$ in odd weight. Here, $1$ and $-1$ both occur $5$ times. However, this does not tell us which eigenvalues correspond to each eigenspace. For this, we do the following: \begin{verbatim} ? mfatkineigenvalues(mf,3) % = [[-1], [-1], [-1], [1], [1], [1], [-1, -1], [1, 1]] ? mf=minit([96,3,-3],0); mffields(mf) % = [y^4 + 8*y^2 + 9, y^4 + 4*y^2 + 1] ? mfatkineigenvalues(mf,32) % = [[I, -I, -I, I], [-I, I, I, -I]] ? mfatkineigenvalues(mf,3) % = [[a, -conj(a), -a, conj(a)], [b, -conj(b), conj(b), -b]] \end{verbatim} The first command tells us that in the six rational eigenspaces, the first three have eigenvalue $-1$, the other three $+1$, and in the eigenspaces of dimension $2$, the first eigenspace has both eigenvalues $-1$, the second both $+1$. As is seen from the next lines, it is of course not necessary for the eigenvalues of $W_Q$ in the same eigenspace to be equal. In the next two commands, we are now in a case where the character is non trivial and the weight odd. The eigenvalues are now $\pm i$, and not equal in the same eigenspace. Finally, the last command is a case where the character is not defined modulo $N/Q=96/3=32$, so we only have pseudoeigenvalues, which are simply of absolute value $1$ by Atkin--Lehner theory. Here, $a$ and $b$ are complicated complex numbers and \kbd{conj} denotes the complex conjugate (using the \kbd{algdep} command, one can check that $a$ is a root of $9x^4+10x^2+9=0$ and $b$ is a root of $3x^4-2x^2+3=0$. Note that when the character is (trivial or) quadratic and defined modulo $N/Q$ the output is always rounded, but otherwise, the eigenvalues are given as approximate complex numbers. As for the Hecke operators, there exists an \kbd{mfatkin} command, whose syntax is \kbd{mfatkin(mfatk, F)}, where \kbd{mfatk} is the output of an \kbd{mfatkininit} command and $F$ is in the space \kbd{mfatk}, and which outputs the modular form $F|_kW_Q$, where $Q$ is implicit in \kbd{mfatk}. Finally note the \kbd{mfbd} expanding command which computes $B(d)F$: \begin{verbatim} ? E4 = mfEk(4); mfcoefs(E4,6) % = [1, 240, 2160, 6720, 17520, 30240, 60480] ? F = mfbd(E4,2); mfcoefs(F,6) % = [1, 0, 240, 0, 2160, 0, 6720] \end{verbatim} \section{Algebraic Functions on Modular Forms} Here we give examples of functions on modular forms which do not involve any approximate numerical computation. We have already mentioned the most important ones: \kbd{mfhecke}, \kbd{mfatkin}, and \kbd{mfbd}. \begin{verbatim} ? E4 = mfEk(4); F = mfderivE2(E4); mfcoefs(F,5) % = [-1/3, 168, 5544, 40992, 177576, 525168] ? E6 = mfEk(6); mfisequal(F, mflinear([E6], [-1/3])) % = 1 ? G = mfbracket(E4, E6, 1); mfcoefs(G,5) % = [0, -3456, 82944, -870912, 5087232, -16692480] ? mfisequal(G, mflinear([mfDelta()], [-3456])) % = 1 \end{verbatim} \medskip In the first commands, we compute the Serre derivative of $E_4$, and check that it is equal to $-E_6/3$. The name \kbd{mfderivE2} of course comes from the fact that the Serre derivative involves the quasi-modular Eisenstein series $E_2$. Note that there exists the function \kbd{mfderiv} (including to negative order, corresponding to integration), which is provided for the user's convenience for certain computations, but whose output is outside the range of modular forms. The second computation checks that the first Rankin--Cohen bracket of $E_4$ and $E_6$ is a multiple of $\Delta$. You may complain that it is heavy to write an \kbd{mflinear} command as above simply to compute a scalar multiple of a form. But nothing prevents you from defining in a script that you read at the beginning of your session: \begin{verbatim} mfscalmul(F,s)=mflinear([F],[s]); mfadd(F,G)=mflinear([F,G],[1,1]); mfsub(F,G)=mflinear([F,G],[1,-1]); \end{verbatim} There also exist the natural operations on modular forms \kbd{mfmul}, \kbd{mfdiv} (which may result in modular functions, i.e., with poles), and \kbd{mfpow}. There is also a function \kbd{mfshift} (multiply or divide by a power of $q$), but which again takes us outside the range of modular forms. \begin{verbatim} ? E4 = mfEk(4); F = mftwist(E4, -3); mfcoefs(F, 7) % = [0, 240, -2160, 0, 17520, -30240, 0, 82560] ? mfparams(F) % = [9, 4, 1, y] ? mf = mfinit([4,5,-4], 1); F = mfbasis(mf)[1]; mfcoefs(F, 10) % = [0, 1, -4, 0, 16, -14, 0, 0, -64, 81, 56] ? mfisCM(F) % = -4 ? G = mftwist(F, -4); mfcoefs(G, 10) % = [0, 1, 0, 0, 0, -14, 0, 0, 0, 81, 0] ? mfparams(G) % = [16, 5, -4, y] ? mfconductor(mfinit(G, 1), G) % = 8 \end{verbatim} This session illustrates a number of important issues concerning \emph{twisting}. In the first commands, we twist $E_4$ by the quadratic character $-3$ (in the present implementation, only twisting by quadratic characters is allowed), and we see that the resulting form has level $9=(-3)^2$. Fine. In the next command, we compute the unique form in $S_4(\G_0(5),\chi_{-4})$, and see that it has CM by $\Q(\sqrt{-4})$. However, note that the form is not equal to the form twisted by the character $\chi_{-4}$ (only the coefficients of $q^n$ with $n$ prime to $4$ are equal, the others vanish). The \kbd{mfparams} command tells us that the twisted form has level $16=(-4)^2$. However, the final command tells us that in fact it has level $8$: \kbd{mfconductor} gives the smallest level on which the form is defined. \begin{verbatim} ? mf = mfinit([96,2], 1); L = mfbasis(mf); ? apply(x->mfconductor(mf,x), L) % = [24, 48, 96, 32, 96, 48, 96, 96, 96] ? apply(x->mftonew(mf,x)[1][1..2], L) % = [[24, 1], [24, 2], [24, 4], [32, 1], [32, 3],\ [48, 1], [48, 2], [96, 1], [96, 1]] \end{verbatim} Here we compute the full cuspidal space $S_2(\G_0(96))$, of dimension $9$, and we ask which is the lowest level on which each form in the basis is defined. This list shows that there is one form $F_1$ in level $24$ which, by applying $B(d)$ with $d=2$ and $d=4$ gives a form of level $48$ and one of level $96$. Then a form $F_2$ in level $32$, by applying $B(3)$ gives a form of level $96$, a form $F_3$ in level $48$, by applying $B(2)$ gives a form of level $96$, and finally two genuine forms of level $96$ (so that the dimension of the newspace is equal to $2$, which we can check by typing \kbd{mfdim([96,2],0)}). The last command \kbd{mftonew} checks all this; look at the precise description of the command. \section{Cusps and Cosets} Recall that in the present version of the package, the only congruence subgroup that is considered is $\G_0(N)$, so when we consider cusps in the geometrical sense, they are cusps of $\G_0(N)$, and cosets are right cosets of $\G_0(N)$ in $\G$, so that $\G=\bigsqcup_j\G_0(N)\ga_j$. The function \kbd{mfcusps(N)} gives the list of all (equivalence classes of) cusps of $\G_0(N)$, \kbd{mfcuspwidth(N,cusp)} gives the width of the cusp; these are linked to the \emph{geometry}. On the other hand, the notion of \emph{regularity} of a cusp is linked to the specific modular form space, and the function \kbd{mfcuspisregular([N,k,CHI],cusp)} determines if the cusp is regular or not: \begin{verbatim} ? C = mfcusps(108) % = [0, 1/2, 1/3, 2/3, 1/4, 1/6, 5/6, 1/9, 2/9, 1/12,\ 5/12, 1/18, 5/18, 1/27, 1/36, 5/36, 1/54, 1/108] ? [mfcuspwidth(108,c) | c<-C] % = [108, 27, 12, 12, 27, 3, 3, 4, 4, 3, 3, 1, 1, 4,\ 1, 1, 1, 1] ? NK = [108,3,-4]; ? [mfcuspisregular(NK,c) | c<-C] % = [1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1] ? [c | c<-C, !mfcuspisregular(NK,c)] % = [1/2, 1/6, 5/6, 1/18, 5/18, 1/54] \end{verbatim} The first command list the $18$ cusps of $\G_0(108)$ (\kbd{mfnumcusps(108)} gives this directly, useful if there are thousands of cusps and you do not want them explicitly), the second command prints their widths, and the last commands show that the cusps $1/2$, $1/6$, $5/6$, $1/18$, $5/18$, and $1/54$ are irregular in the space $M_3(\G_0(108),\chi_{-4})$, and the others are regular. There is another command \kbd{mfcuspval} having to do with cusps, but this will be mentioned later. \medskip \begin{verbatim} ? C = mfcosets(4) % = [[0, -1; 1, 0], [1, 0; 1, 1], [0, -1; 1, 2],\ [0, -1; 1, 3], [1, 0; 2, 1], [1, 0; 4, 1]] ? mftocoset(4, [1, 1; 2, 3], C) % = [[-1, 1; -4, 3], 5] \end{verbatim} The \kbd{mfcosets(N)} command lists all right cosets of $\G_0(N)$ in $\G$. Note that in the present implementation the trivial coset is always the last one, and is represented by the matrix $[1,0;N,1]$, but since this may change one must be careful. The \kbd{mftocoset(N,M,C)} command gives a two-component vector $[\ga,i]$, where $\ga\in\G_0(N)$ is such that $M=\ga\cdot C[i]$. \section{The mfslashexpansion command} We now give examples of the use of advanced features of the package, which use inexact complex arithmetic. However in many cases the results are known algebraic numbers and, if asked to do so, the function gives them exactly. This command returns the Fourier expansion at infinity of $f |_k \gamma$, for $\gamma\in \GL_2(\Q)^+$. It returns a vector $v$ of coefficients, which can only be interpreted together with three extra parameters $\al\in \Q_{\geq 0}$, $w \in \Z_{\geq 1}$ and a $2\times 2$ upper triangular matrix $A=[a,b;0,d]$ (equal to the identity if $\gamma\in\PSL_2(\Z)$). We have $f |_k \gamma = F |_k A $, with $$F(\tau) = q^\al \sum_{n\geq 0} v[n] q^{n/w}$$ and $q = e(\tau)$. Of course, $F |_k A = (a/d)^{k/2} F(\tau + b/d)$ so the exact expansion is easily inferred from the returned one, whereas the chosen encoding allows to compute the coefficients $v[n]$ in a smaller number field than if we had included all the constants into $v$. It is important to note that the three parameters $\al, w, A$ only depend on the modular form space and $\gamma$, but not on the form $f$. \begin{verbatim} ? mf = mfinit([4,6]); B = mfbasis(mf); ? for (i=1, #B, \ print( mfslashexpansion(mf,B[i],[1,0;2,1],5,1,&P) )) \\ we don't print P which is [0, 1, [1,0;0,1]] in all cases [-1/504, 1, 33, 244, 1057, 3126] [-1/504, 0, 1, 0, 33, 0] [-1/32256, -1/64, 33/64, -61/16, 1057/64, -1563/32] [0, -1, 0, 12, 0, -54] ? R = mfslashexpansion(mf,B[1],[0,-1;4,0],5,1,&P); [P,R] % = [[0, 1, [1,0;0,1]], [-8/63, 0, 0, 0, 64, 0]] ? R = mfslashexpansion(mf,B[1],[0,-1;1,0],5,1,&P); [P,R] % = [[0, 4, [1,0;0,1]], [-1/504, 0, 0, 0, 1, 0]] ? mf=mfinit([4,7,-4]); B=mfbasis(mf); ? for (i=1, #B, \ print( mfslashexpansion(mf,B[i],[1,0;2,1],5,1,&P) )) \\ we don't print P which is [1/2, 1, [1,0;0,1]] in all cases [1/64, 91/8, 7813/32, 7353/4, 530713/64, 221445/8] [1, -728, 15626, -117648, 530713, -1771560] [1/16, -15/2, 5/8, 75, -231/16, -465/2] [2, 0, 20, 0, -462, 0] ? mfslashexpansion(mf,B[1],[0,-1;4,0],5,1,&P) % = [Mod(61/256*t, t^2 + 1), Mod(-1/64*t, t^2 + 1), Mod(-1/64*t, t^2 + 1), Mod(91/8*t, t^2 + 1), Mod(-1/64*t, t^2 + 1), Mod(-7813/32*t, t^2 + 1)] ? P % = [0, 1, [1, 0; 0, 1]] ? R=mfslashexpansion(mf,B[1],[0,-1;4,0],5,0) % = [0.23828125000000000000000000000000000000*I,\ -0.015625000000000000000000000000000000000*I,\ -0.015625000000000000000000000000000000000*I,\ 11.375000000000000000000000000000000000*I,\ -0.015625000000000000000000000000000000000*I,\ -244.15625000000000000000000000000000000*I] ? bestappr(R) % = [61/256*I, -1/64*I, -1/64*I, 91/8*I, -1/64*I, -7813/32*I] \end{verbatim} Here are some detailed explanations. The first space is $M_6(\G_0(4))$, of dimension $4$. We ask for $1+5$ terms of the Fourier expansion of $F|_6\ga$ for all $F$ in the given basis, and $\ga=[1,0;2,1]$, which is one of the possible Fourier expansions at the cusp $1/2$. The last parameter $P$ contains $[\al,w,A]$ after the call and the $1$ means we want an exact algebraic expression (a $0$ as used in the last example means we expect floating point complex numbers). We obtain the $4$ desired expansions. In the next commands, we do the same for the first basis element and $\ga=[0,-1;4,0]$, which is the \emph{Fricke involution}, and corresponds to the cusp $0$. The next command, which does essentially the same computation, uses $\ga=[0,-1;1,0]$, and now $P=[0,4, [1,0;0,1]]$ which tells us that the expansion is in powers of $q^{1/4}$. The next example is the space $M_7(\G_0(4),\chi_{-4})$, also of dimension $4$, and we ask the same thing. Now $P$ tells us that $\al = 1/2$ and $w = 1$ so we now have for instance $$B[1]|_7\ga = (1/64)q^{1/2} + (91/8)q^{3/2}+\cdots$$ In the next command, we expand $B[1]|_7\ga$ with $\ga$ equal to the Fricke involution; and finally we check numerically by setting the one-to-last parameter to $0$ and obtain the expansion as raw complex numbers. We recognize them immediately using the \kbd{bestappr} command. Note that in the special case (like here) where $\ga$ is a Fricke (or more generally an Atkin--Lehner) involution, we can proceed otherwise to obtain the expansion: \begin{verbatim} ? mfatk = mfatkininit(mf,4); C = mfatk[3] % = -1.000000000000000000000000000*I ? F = mfatkin(mfatk, B[1]); mfcoefs(F, 6) % = [61/256, -1/64, -1/64, 91/8, -1/64, -7813/32, 91/8] \end{verbatim} This tells us that the true expansion of $F|_7W_4$ is the expansion that is output divided by the constant $C$, so we recover the previous expansion. \smallskip It is important to see what affects the timing and correctness of the \kbd{mfslashexpansion} command. The following session gives typical examples: \begin{verbatim} ? mf = mfinit([496,4],0); F = mfbasis(mf)[1]; mfdim(mf) time = 329 ms. % = 45 ? mfslashexpansion(mf,F,[1,0;3,1],5,0,&P); time = 1,316 ms. ? mfslashexpansion(mf,F,[1,0;3,1],5,1,&P); time = 51,136 ms. ? mf = mfinit([503,4],0); F = mfbasis(mf)[1]; mfdim(mf) time = 1,505 ms. % = 125 ? sizebyte(mf) % = 5123352 ? mfslashexpansion(mf,F,[1,0;3,1],5,0,&P); time = 32,640 ms. ? sizebyte(mf) % = 18216400 ? mfslashexpansion(mf,F,[1,0;3,1],5,0,&P); time = 6,504 ms. \end{verbatim} We omit the numerical outputs since they have no significance for the present discussion. We notice several things: \begin{itemize} \item First, the time for rationalization (flag $1$) in the first example is extremely large: $51$ seconds instead of $1.3$. The reason for this is that the width of the corresponding cusp (here $1/3$) is equal to $P[2]=496$, and the program must recognize algebraic numbers in the large cyclotomic field $\Q(\zeta_{496})$ which takes a huge amount of time. In fact, at the default accuracy of $38D$, the result is certainly wrong. \item Second, the time depends enormously on the dimension: the expansion for dimension $125$ is $25$ times slower than for dimension $45$, of course not surprising, but it must be taken into account. \item Third, and most importantly, the last command shows the cache effect: exactly the same instruction now requires only $6.5$ seconds instead of $32.6$. This is because, behind the scenes, the first \kbd{mfslashexpansion} precomputed a number of quantities which it stored in your variable \kbd{mf}: in fact, the \kbd{sizebyte} commands show that, after the first expansion, the size of \kbd{mf} has more than tripled. \end{itemize} \section{Analytic Commands} The existence of the \kbd{mfslashexpansion} command allows us to do many useful things. In fact, already the \kbd{mfatkininit} and \kbd{mfatkin} commands would not be possible without it. Immediate applications are the \kbd{mfcuspval} command which computes the valuation at cusps, and the \kbd{mfeval} command, which in addition to computing values in the upper-half plane (see below), also computes values at the cusps: \begin{verbatim} ? T = mfTheta(); mf=mfinit(T);C=mfcusps(mf) % = [0, 1/2, 1/4] ? [ mfcuspval(mf,T,c) | c<-C ] % = [0, 1/4, 0] ? mfeval(mf, T, C) \\ or [mfeval(mf,T,c) | c<-C] % = [1/2 - 1/2*I, 0, 1] \end{verbatim} More sophisticated is the computation of numerical periods, and more generally of \emph{symbols} $$\int_{s_1}^{s_2}(X-\tau)^{k-2}F|_k\ga(\tau)\,d\tau\;,$$ where $s_1$ and $s_2$ are two cusps (e.g., $s_1=0$, $s_2=\infty$): \begin{verbatim} ? mf = mfinit([96,4],0); [F1] = mfbasis(mf); ? FS1 = mfsymbol(mf,F1); time = 2,272 ms ? mfsymboleval(FS1,[0,oo]) % = 2.0968669678226579060336519703627002478*I*x^2\ + 0.36368580656317635568444277442842940073*x\ - 0.049315736834713109138297211986510643780*I ? mfsymboleval(FS1,[1,5/2]) % = 4.1937339356453158120673039407254004956*I*x^2\ + (0.72737161312635271136888554885685880147\ - 14.678068774758605342235563792538901735*I)*x\ + (-1.2729003229711172448955497104995029026\ + 15.103654043044843600467382361156555509*I) ? mfsymboleval(FS1,[1,2],[0,-1;1,0]) % = (0.54552870984476453352666416164264410111\ + 2.5224522361088961642654705389803540222*I)*x^2\ + (-0.72737161312635271136888554885685880148\ - 6.2906009034679737181009559110881007434*I)*x\ + 4.1937339356453158120673039407254004956*I \end{verbatim} The general strategy for computing these quantities is first to do a precomputation which only involves \kbd{mf} and the form $F$ using \kbd{mfsymbol}, which can take a few seconds, but afterwards all the computations are instantaneous. Note that if you only want the period polynomial from $0$ to $\infty$ use \kbd{mfperiodpol(mf,F1)} which gives the same answer as before but in only $20$ ms. You may also use \kbd{mfsymboleval} in two other ways, but note that in this case the precomputation is not used so the computation may be slow: \begin{verbatim} ? mf=mfinit([96,6],0);F=mfbasis(mf)[1]; ? FS=mfsymbol(mf,F); time = 9,761 ms. ? mfsymboleval(FS,[I,oo]) % = 0.0029721...*I*x^4 + 0.0137806...*x^3 + ... + 0.0061009... ? mfsymboleval(FS,[I,2*I]) % = 0.0029665...*I*x^4 + 0.0137326...*x^3 + ... + 0.0059760... ? mfsymboleval(FS,[I/10000,I]) % = 46.363730...*I*x^4 + 3.8815894...*x^3 + ... + 0.0183869... ? -x^4*subst(mfsymboleval(FS,[I,10000*I],[0,-1;1,0]),x,-1/x) % = 46.363730...*I*x^4 + 3.8815894...*x^3 + ... + 0.0183869... ? mfsymboleval([mf,F],[I,oo]) % = 0.0029721...*I*x^4 + 0.0137806...*x^3 + ... + 0.0061009... ? mfsymboleval([mf,F],[I,2*I]) % = 0.0029665...*I*x^4 + 0.0137326...*x^3 + ... + 0.0059760... \end{verbatim} These examples illustrate four points: \begin{enumerate}\item Computing an \kbd{mfsymbol} may be rather long ($9.8$ seconds in this example), although as already mentioned, subsequent computations of symbols \emph{between cusps} will then be instantaneous. \item As the next three commands show, \kbd{mfsymboleval} also accepts paths with endpoints in the upper half-plane. Although we have tried to optimize the computation, in certain cases (but not in the above example) when one of the endpoints is close to the real line the computation may be slow. \item The next command shows the use of the extra parameter $\ga$ which asks to integrate $F|_k\ga$ instead of $F$, here with \kbd{ga=[0,-1;1,0]}. This allows to perform the same computation with endpoints which are away from the real line. This is essentially what is done \emph{automatically} by \kbd{mfsymboleval}. \item The last two commands show a special format which avoids doing the longish \kbd{mfsymbol} computation: the results are obtained almost instantaneously \emph{without} using symbols. The price to pay in using this ``cheaper'' format is that the endpoints of the path cannot be cusps other than \kbd{oo}. \end{enumerate} \begin{verbatim} ? mf = mfinit([96,4],0); [F1,F2] = mfbasis(mf); ? FS1 = mfsymbol(mf,F1); FS2 = mfsymbol(mf,F2); ? mfpetersson(FS1) % = 0.00061471684149817788924091516302517391826 ? mfpetersson(FS2) % = 0.0055324515734836010031682364672265652647 ? mfpetersson(FS1, FS2) % = 1.5879887877319313665 E-40 + 7.652958013165934297 E-42*I \end{verbatim} Same remark: once the \kbd{mfsymbols} \kbd{FS1} and \kbd{FS2} initialized, all the Petersson product computations (as well as others) are essentially immediate. Note that since neither \kbd{F1} nor \kbd{F2} are eigenforms, there is no reason for their Petersson product to vanish. To prove it does we do as follows: \begin{verbatim} ? BE = mfeigenbasis(mf); ? M = Mat([mftobasis(mf,f) | f<-BE]); M^(-1) % = [1 3 10 4 -20 70] [1 3 2 12 60 -42] [1 3 -14 -36 -36 54] [1 -3 10 -4 20 70] [1 -3 2 -12 -60 -42] [1 -3 -14 36 36 54] \end{verbatim} On the other hand, it is immediate to see that \kbd{BE[i+3]} is a twist of \kbd{BE[i]} and that as a consequence their Petersson square are equal. It follows from the shape of the above matrix that the Petersson scalar product of $B[i]$ with $B[j]$ will vanish when the corresponding scalar product of the corresponding columns vanish, hence for $(i,j)=(1,2)$, $(1,4)$, $(1,5)$, $(2,3)$, $(2,6)$, $(3,4)$, $(3,5)$, $(4,6)$, and $(5,6)$. \smallskip Note that \kbd{mfpetersson} can also be used for two noncuspidal forms, as long as the Petersson product converges. Consider the following example: \begin{verbatim} ? mf = mfinit([12,5,-3]); cusps = mfcusps(mf); ? E1 = mfeisenstein(5,1,-3); [mfcuspval(mf,E1,c) | c<-cusps] % = [0, 0, 1, 0, 1, 1] ? E2 = mfeisenstein(5,-3,1); [mfcuspval(mf,E2,c) | c<-cusps] % = [1/3, 1/3, 0, 1/3, 0, 0] ? P(mf) = { my(E1S = mfsymbol(mf,E1)); my(E2S = mfsymbol(mf,E2)); mfpetersson(E1S,E2S); } ? P(mf) % = -1.8848216716468969562647734582232071466 E-5\ - 1.9057659114817512165 E-43*I ? mf3 = mfinit([3,5,-3]); P(mf3) time = 16 ms. ? mf96 = mfinit([96,5,-3]); P(mf96) time = 3,521 ms. \end{verbatim} The first commands create two Eisenstein series of weight $5$, $E_5(1,\chi_{-3})$ and $E_5(\chi_{-3},1)$, which belong to $M_5(\G_0(3),\chi_{-3})$. In the next commands, we look at the larger space of level $12$ and compute the valuations of $E_1$ and $E_2$ at the six cusps of $\G_0(12)$. We see that at these six cusps one of the two Eisenstein series vanishes, so the Petersson product will converge, and is computed in the next command. In the last commands we compute the same product but in level $3$ and level $96$; because of the normalization, we obtain essentially the same result (not given), but of course the times are very different: $0.016$ seconds in level $3$ and $3.5$ seconds in level $96$. \medskip There are two more important numerical functions: evaluating a modular form at a point in the upper half plane, and evaluating the corresponding $L$-function. We begin by a trivial example: \begin{verbatim} ? E4 = mfEk(4); mf = mfinit(E4); mfeval(mf,E4,I) % = 1.4557628922687093224624220035988692874 ? 3*gamma(1/4)^8/(2*Pi)^6 % = 1.4557628922687093224624220035988692874 \end{verbatim} This is of course a trivial computation, simply sum the $q$-expansion. The fact that the value of a modular form with rational coefficients such as $E_4$ at a \emph{CM point} such as $i$ has an explicit expression is a consequence of complex multiplication. \begin{verbatim} ? mf = mfinit([12,4],1); F = mfbasis(mf)[1]; ? mfeval(mf, F, 1/Pi + 10^(-6)*I) % = -89811.049350396250531782882568405506024\ - 58409.940965200894541585402642924371696*I ? mfeval(mf, F, 1/Pi + 10^(-7)*I) % = 4.8212468504661113183253396691813292261 E-52\ + 6.7885262281520647908871247541561415340 E-52*I \end{verbatim} Several remarks are in order. \begin{enumerate} \item We are evaluating a modular form very near the real axis. If the form was in level $1$ such as $E_4$ above, we could use a modular transformation to reduce to the evaluation in the fundamental domain of $\G$, which would be very fast. Here we do something similar but more sophisticated. \item Contrary to most examples, the result at height $10^{-7}$ is not a numerical approximation of $0$, the exact value is indeed as printed to the given accuracy. \item It is amusing to see the large oscillations of the value: at height $10^{-6}$ the value is still in the $10^5$ range, and at $10^{-7}$ it is in the $10^{-52}$ range. Of course it must eventually tend to $0$ since $F$ is a cusp form (for $E_4$ it would tend to infinity). \item When applying \kbd{mfeval} at a \emph{cusp} (as above for \kbd{mfTheta()}), the result is the value at the cusp, but is in general \emph{not} equal to the limit of the value of the modular form when the argument tends to the cusp, since this limit is often infinite for a noncuspidal form. \end{enumerate} Note that when dealing with \emph{eigenforms}, which may have several embeddings into $\C$, the result will have several components, one for each embedding: \begin{verbatim} ? mf = mfinit([23,2],0); F=mfeigenbasis(mf)[1]; ? mfeval(mf,F,I) % = [0.0018695834459685012330841605500720163964,\ 0.0018618146628840767703527958851699552194] \end{verbatim} More generally, this embedding problem affects all numerical functions. Continuing the above example: \begin{verbatim} ? mfparams(F) % = [23, 2, 1, y^2 - y - 1] ? mfslashexpansion(mf,F,[0,-1;1,0],5,1) % = [0, -1/23, 1/23*y, -2/23*y + 1/23, -1/23*y + 1/23, 2/23*y] ? FS = mfsymbol(mf,F); mfpetersson(FS,FS) % = [0.00394889657400250316885... -1.0827196147167250830 E-40] [-1.2120247024777595243 E-40 0.00564425429876478351015...] \end{verbatim} The $y$ in the second result is thus understood to be \emph{one} of the roots of the polynomial $y^2-y-1$, and the result of \kbd{mfpetersson} is a $2\times 2$ \emph{diagonal} matrix because of the two embeddings of $F$. \smallskip The other important evaluation function is that of the $L$-function attached to a modular form. In fact, the modular form package only creates (in a clever way) the $L$-function, all the rest of the work is done by the $L$-function package. Note the important fact that the modular form need not be an eigenform or even stable under the Fricke involution. \begin{verbatim} ? E4 = mfEk(4); mf=mfinit(E4); LE = lfunmf(mf,E4); ? lfun(LE, 2) / Pi^2 % = -3.3333333333333333333333333333333333333 ? lfun(LE, 0) % -1 ? D = mfDelta(); mf=mfinit(D); LD = lfunmf(mf,D); ? lfunlambda(LD, 3)/lfunlambda(LD, 5) % = 1.5555555555555555555555555555555555556 ? lfunlambda(LD, 1)/lfunlambda(LD, 3) % = 2.3444283646888567293777134587554269175 ? bestappr(%) % = 1620/691 ? mf = mfinit([23,2],0); F = mfbasis(mf)[1]; L = lfunmf(mf,F); ? lfun(L, 2) % = 1.5959983753450272580976413437480171832 ? G = mfeigenbasis(mf)[1]; M = lfunmf(mf,G); ? apply(x->lfun(x,I),M) % = [-0.15856033373254740657327844579672155664\ + 0.79671369922504818377602680344686311969*I,\ -0.10230278816509023908993775663030712037\ + 0.65954223983092583287784522268295299513*I] \end{verbatim} Note that the constant term $a(0)$ is ignored by the $L$-function, but can be recovered thanks to the formula $a(0)=-L(F,0)$. The last commands illustrate first the fact that the $L$-functions can be computed for non-eigenforms ($F$ is not an eigenform), and second that if there are several embeddings, the \kbd{lfunmf} function returns a vector of \kbd{lfunmf}, one for each embedding. Another illustration of the $L$-function package: \begin{verbatim} ? LIN = lfuninit(LD, [6, 6, 50]); ? ploth(t = 0, 50, lfunhardy(LIN, t)) \end{verbatim} %\includegraphics[width=\textwidth]{pari3.pdf} \medskip \section{The mfeigensearch and mfsearch commands} The last commands that we want to illustrate are \emph{searching} commands, The idea is simple: you believe that you have a modular form, but you do not know its level, weight, character, or field of definition of its coefficients, but only a number of its Fourier coefficients, perhaps only modulo $p$, and you would like to find forms which ``match'' your given form. In this degree of generality, the search space is too wide. We have therefore decided to reduce the generality, so as to make the search more reasonable. Note that this will probably vary with the different versions of the program, so what is described here may be more restrictive than future versions. In the present implementation, we assume that the form we are looking for has rational coefficients, so that its character is (trivial or) quadratic. The \kbd{mfsearch} command does this naively but is likely to be more efficient than taylor-made scripts: \begin{verbatim} ? V = mfsearch([60,2],[0,1,2,3,4,5,6], 1); #V time = 5 ms. % = 3 ? V = mfsearch([[1..60],2],[0,1,2,3,4,5,6], 1); #V time = 40 ms. % = 5 ? [ mfparams(f) | f<-V ] % = [[56, 2, 8, y], [58, 2, 1, y], [60, 2, 1, y], [60, 2, 12, y], [60, 2, 60, y]] ? [ print(mfcoefs(f,10)) | f<-V ] [0, 1, 2, 3, 4, 5, 6, -6, -4, -7, -20] [0, 1, 2, 3, 4, 5, 6, -34, 37, 22, 7] [0, 1, 2, 3, 4, 5, 6, 20, 0, -27, -6] [0, 1, 2, 3, 4, 5, 6, -170/9, -272/9, -11/3, -134/9] [0, 1, 2, 3, 4, 5, 6, 200/13, -304/13, -435/13, -278/13] \end{verbatim} This command looks for all forms, first in level $60$ then in level $1$ to $60$ and weight $2$ whose first coefficients are $[0,1,2,3,4,5,6]$, the final $1$ is optional and specifies the \emph{space} (in \kbd{mfinit} sense) where the search is performed, here the cuspidal space (by default the full space). It returns a list of $3$ forms in level $60$ and $5$ in total. The \kbd{mfeigensearch} command is more interesting. We look for is a cuspidal \emph{eigenform} whose field of definition is $\Q$, so that its Fourier coefficients are integers, and its character is (trivial or) quadratic. An example is as follows: \begin{verbatim} ? AP = [[2,2], [3,-1]] \\ a(2) = 2 and a(3) = -1 ? L = mfeigensearch([[1..120],4], AP); #L % = 2 ? [f,g] = L; [mfparams(f), mfparams(g)] % = [[26, 4, 1, y], [118, 4, 1, y]] ? mfcoefs(f, 10) % = [0, 1, 2, -1, 4, 17, -2, -35, 8, -26, 34] ? mfcoefs(g, 10) % = [0, 1, 2, -1, 4, -13, -2, -27, 8, -26, -26] \end{verbatim} The first command asks for all forms as above in weight $4$ and level from $1$ up to $120$, such that $a(2)=2$ and $a(3)=-1$. The answer is that there are two forms, which we call $f$ and $g$. We compute their levels ($26$ and $118$ respectively), notice they have trivial character, and list their Fourier coefficients up to $10$ and we see that indeed $a(2)=2$ and $a(3)=-1$ in both cases. To specify the coefficients that we want there are a number of ways. The simplest, as above, is to give the list of pairs of integers $[p,a(p)]$. For instance: \begin{verbatim} ? L = mfeigensearch([[1..80],2], [[2,2], [7,-3]]); #L % = 1 ? F = L[1]; mfparams(F) % = [75, 2, 1, y] ? mfcoefs(F, 12) % = [0, 1, 2, -1, 2, 0, -2, -3, 0, 1, 0, 2, -2] \end{verbatim} The coefficient $a(p)$ may also be given as an \kbd{intmod} \kbd{Mod}$(a,m)$ then one looks for a match for $a(p)$ modulo $m$. For instance, we come back to our first example: \begin{verbatim} ? AP5 = [[2,Mod(2,5)], [3,Mod(-1,5)]]; \\ now modulo 5 ? L=mfeigensearch([[1..120], 4], AP); #L % = 3 ? [ mfparams(f)[1] | f <- L ] % = [26, 26, 118] ? [F1,F2] = L; \\ let's consider the first two ? mfcoefs(F1, 10) % = [0, 1, 2, -1, 4, 17, -2, -35, 8, -26, 34] ? mfcoefs(F2, 10) % = [0, 1, 2, 4, 4, -18, 8, 20, 8, -11, -36] ? F = mflinear([F1, F2], [-1, 1]); ? content(mfcoefs(F, mfsturm([26,4])+1)) % = 5 \end{verbatim} Working modulo $5$, we now find that there is an extra eigenform satisfying our criteria, and perhaps surprisingly, again in level $26$. The first, \kbd{F1}, is the one found above, with $a(2)=2$ and $a(3)=-1$. The second, \kbd{F2}, has $a(2)=2$ but $a(3)=4\equiv-1\pmod5$. But we can go further and see that this is not a simple coincidence: the next command shows that both eigenforms seem to be congruent modulo $5$, at least up to $a(10)$. In fact they are indeed congruent modulo $5$: to prove this, we use the fact that the basic Sturm bound (the one obtained using \kbd{mfsturm([N,k])}, not \kbd{mfsturm(mf)}) is also valid modulo $p$. Since all coefficients are congruent up to the Sturm bound, they are congruent for all $n$. \section{Half-Integral Weight Functions} \subsection{General Functions} Many of the commands that we have seen, and most importantly the \kbd{mfinit} and \kbd{mfdim} command, can be used verbatim in the case of modular forms of half-integral weight, sometimes with small differences. \begin{itemize} \item Two functions created from mathematical objects can give forms of half-integral weight, \kbd{mfetaquo} and \kbd{mffromqf}. \item Leaf functions created from scratch are \kbd{mfTheta}, which gives the standard Jacobi theta function of weight $1/2$, and \kbd{mfEH}, which gives the Cohen--Hurwitz Eisenstein series of half-integral weight. \end{itemize} \begin{verbatim} ? F = mffrometaquo([2,5;1,-2;4,-2]); Ser(mfcoefs(F,10),q) % = 1 + 2*q + 2*q^4 + 2*q^9 + O(q^11) ? T = mfTheta(); mfisequal(F,T) % = 1 ? F = mffromqf(2*matid(3))[2]; Ser(mfcoefs(F,5),q) % = 1 + 6*q + 12*q^2 + 8*q^3 + 6*q^4 + 24*q^5 + O(q^6) ? mfisequal(F, mfpow(T,3)) % = 1 \end{verbatim} \begin{itemize}\item The only spaces which are \emph{directly} available by \kbd{mfinit} and \kbd{mfdim} are the full cuspidal space and the full modular form space. The new space can be defined in some cases but indirectly, using Kohnen's theory, see below. \item The only Hecke operators $T(n)$ which are nonzero are those where $n$ is a square (we have not programmed the $T(p)$ with $p$ dividing the level). \end{itemize} \subsection{Specific Functions} The most important specific function in half-integral weight is \kbd{mfshimura}, which computes the Shimura lift corresponding to a discriminant $D$ (1 by default) and also returns an \kbd{mf} space containing the lift: \begin{verbatim} ? mf=mfinit([60,5/2],1); F=mfbasis(mf)[1]; ? D = [1,5,8,12,13,17,21]; ? for (i=1, #D, \ [mf2,G] = mfshimura(mf,F,D[i]); print(mfcoefs(G,10))) [0, 1, 2, 0, 2, -1, -2, 6, 6, -3, -10] [0, 0, 0, -1, 0, 0, 20, 0, 0, -2, 0] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 0, 0, 0, 0, 24, 0, 0, 0, 0, -48] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] [0, 1, 0, 3, 52, -5, -120, 14, -156, 3, 0] ? mfdescribe(mf) % = "S_5/2(G_0(60, 1))" ? mfdescribe(mf2) % = "S_4(G_0(30, 1))" \end{verbatim} Two things to notice: first the image can be identically $0$. Second, the program takes some time (20 seconds for the above), because computing a Shimura image takes time proportional to $D^4$. \smallskip The other specific functions are related to the Kohnen $+$-space. Continuing the above example: \begin{verbatim} ? K=mfkohnenbasis(mf); matsize(K) % = [14, 4] ? K[,1] % = [-1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]~ ? F=mflinear(mf,K[,1]); ? Ser(mfcoefs(F,35),q) % = -q + 2*q^4 - 4*q^16 + 3*q^21 - 6*q^24 + 5*q^25 + O(q^36) \end{verbatim} The first command shows that although the dimension of the cuspidal space is $14$, that of the Kohnen $+$-space is $4$; if desired, the corresponding modular forms can be obtained by \kbd{mflinear(mf,K[,j])} for each $j$ as done in the next command. The Fourier expansion of $F$ given on the last line shows that the only nonzero coefficients of $q^n$ occur when $n\equiv0,1\pmod4$. Continuing: \begin{verbatim} ? [mf2,FS]=mfshimura(mf,F); mfparams(FS) % = [15, 4, 1, y] ? [mf2,FS]=mfshimura(mf,mfbasis(mf)[1]); mfparams(FS) % = [30, 4, 1, y] \end{verbatim} These commmands show that the image of an element of the Kohnen $+$-space has level $15=60/4$, while the second shows that the image of a random form has level $30=60/2$. \smallskip A final command related to the Kohnen $+$-space is \kbd{mfkohnenbijection}. This allows, in half-integral weight, to compute the new space, its splitting, and the eigenforms: \begin{verbatim} ? [mf3,M,K,shi] = mfkohnenbijection(mf); ? M * mfheckemat(mf3,11) * M^(-1) % = [ 48 24 24 24] [ 0 32 0 -20] [-48 -72 -40 -72] [ 0 0 0 52] ? mf30 = mfinit(mf3,0); B0 = mfbasis(mf30); #B0 % = 2 ? BNEW = [mflinear(mf, K * M * mftobasis(mf3,f)) | f<-B0]; ? BE = mfeigenbasis(mf30); ? BEIGEN = [mflinear(mf, K * M * mftobasis(mf3,f)) | f<-BE ]; ? Ser(mfcoefs(BEIGEN[1],24),q) % = q + q^4 - 3*q^9 - 5*q^16 + 6*q^21 + 3*q^24 + O(q^25) ? Ser(mfcoefs(BEIGEN[2],24),q) % = q^5 + q^8 - 3*q^12 - 4*q^17 + 3*q^20 + O(q^25) ? mfcoefs(BEIGEN[1],10^4); time = 7,532 ms. \end{verbatim} The \kbd{mfkohnenbijection} command computes a square matrix $M$ giving a Hecke-module isomorphism from the space $S_{2k-1}(\G_0(N),\chi^2)$ to the Kohnen $+$-space $S_k^+(\G_0(4N,\chi))$. Note that this makes sense only when $N$ is squarefree. Thus, $M$ allows to transport all problems from the ``difficult'' space $S=S_k^+(\G_0(4N),\chi)$ to the ``easy'' space $S_{2k-1}(\G_0(N),\chi^2)$. For instance, the next command (essentially instantaneous) gives the matrix of the Hecke operator $T(121)$ on $S$; a direct implementation using the action of $T(121)$ would take $10.6$ seconds. The vector \kbd{BNEW} computed afterwards gives a basis of the Kohnen new space $S_k^{+,\text{new}}(\G_0(4N),\chi)$, here of dimension $2$. The vector \kbd{BEIGEN} computed in a similar way contains the eigenfunctions of this new space. The example of \kbd{BEIGEN[2]} shows that, contrary to the integral weight case, these eigenfunctions can have vanishing coefficient of $q^1$. Note that we \emph{know} by construction that the image of \kbd{BEIGEN[j]} by any Shimura lift is a multiple of \kbd{BE[j]} (with the same index $j$). \smallskip The above construction of the new space and the eigenforms being so useful, a specific function exists for this purpose: instead of all the above, simply write \kbd{[mf30,BNEW,BEIGEN]=mfkohneneigenbasis(mf,bij)}. Here \kbd{BNEW} and \kbd{BEIGEN} will be matrices whose columns are the coefficients of a basis of the Kohnen new space and of the eigenforms respectively, and \kbd{mf30} the corresponding new space of integral weight. \section{Reference Manual for the Package} We give a brief description in alphabetical order of all the functions specific to the package. To use the package, it is sometimes necessary to use functions on characters or functions of the \kbd{lfun} package, but those will not be described here. Note that when a modular form $F$ can be embedded in $\C$ in several ways (typically for eigenforms), some functions give a vector (or even a matrix for bilinear operations) of results, one for each embedding: this occurs specifically for \kbd{lfunmf}, \kbd{mfeval}, \kbd{mfmanin}, \kbd{mfpetersson}, \kbd{mfsymboleval}. This will not always be specified. \def\f{\medskip\noindent} \noindent\kbd{getcache()}: returns technical information about auto-growing caches. \f\kbd{lfunmf(mf,$\{F\}$)}: creates the $L$-function associated to $F$, for use in the \kbd{lfun} package, where $F$ need not be an eigenform. If $F$ is omitted, output all $L$-functions associated to the eigenforms. If $F$ (or the eigenforms) have several embeddings in $\C$, output the vector of the corresponding \kbd{lfunmf}. \f\kbd{mfatkin(mfatk, F)}: computes $F|_k W_Q$, where $Q\Vert N$, where \kbd{mfatk} must have been initialized by \kbd{mfatk=mfatkininit(mf,Q)}. \f\kbd{mfatkineigenvalues(mf, Q)}: \kbd{mf} being a cuspidal or new space and $Q$ a primitive divisor of $N$, output the vector of Atkin--Lehner eigenvalues or pseudo-eigenvalues for each Galois eigenspace. \f\kbd{mfatkininit(mf,Q)}: initialization function for the \kbd{mfatkin} function. The output is \kbd{[mfb,M,C,mf]}, where $C$ is a complex constant, $M/C$ is the matrix of the Atkin--Lehner operator $W_Q$ from the space \kbd{mf} to the space \kbd{mfb} (set equal to $0$ if equal to \kbd{mf}). The matrix $M$ is guaranteed to be with exact coefficients (rational or \kbd{polmods}). \f\kbd{mfbasis(mf,$\{\text{space}=4\}$)}: gives a basis of the space of modular forms \kbd{mf}, either output by an \kbd{mfinit} command, in which case \kbd{space} is ignored, or \kbd{mf=[N,k,CHI]} (use \kbd{mfeigenbasis} for the eigenforms). \f\kbd{mfbd(F,d)}: gives $B(d)(F)$, $B(d)$ expanding operator. \f\kbd{mfbracket(F,G,$\{m=0\}$)}: $m$th Rankin--Cohen bracket of $F$ and $G$. \f\kbd{mfcoef(F,n)}: $n$th Fourier coefficient $a(n)$ of $F$. \f\kbd{mfcoefs(F,n)}: vector $[a(0),a(1),...,a(n)]$ of the Fourier coefficients of $F$ up to $n$. If $F$ is a modular form \emph{space}, give the matrix whose columns are the vectors of the Fourier coefficients of the basis. \f\kbd{mfconductor(mf,F)}: smallest $M$ such that $F$ belongs to $M_k(\G_0(M),\chi)$. \f\kbd{mfcosets(N)}: list of right cosets of $\G$ modulo $\G_0(N)$. In the present implementation, the trivial coset is the last and represented by the matrix $[1,0;N,1]$. $N$ can also be an \kbd{mf}. \f\kbd{mfcuspisregular(NK,cusp)}: \kbd{NK} being $[N,k,\chi]$ or an \kbd{mf}, determine if the cusp is regular or not. \f\kbd{mfcusps(N)}: list of cusps of $\G_0(N)$. $N$ can also be an \kbd{mf}. \f\kbd{mfcuspval(mf,F,cusp)}: valuation of modular form $F$ at \kbd{cusp}, which can be a rational number or \kbd{oo}. \f\kbd{mfcuspwidth(N,cusp)}: width of \kbd{cusp} in $\G_0(N)$. $N$ can also be an \kbd{mf}. \f\kbd{mfDelta()}: Ramanujan's Delta function of weight $12$. \f\kbd{mfderiv(F,$\{m=1\}$)}: $m$th derivative $q.d/dq$ of $F$, where $m$ can be negative, corresponding to integration (the constant term is then set to $0$ by convention). The result is only quasi-modular. \f\kbd{mfderivE2(F,$\{m=1\}$)}: $m$th Serre derivative $q.d/dq F-kE_2F/12$. \f\kbd{mfdescribe(F,$\{\&G\}$)}: $F$ being a modular form or a modular form space, gives a human-readable description of $F$. If the address of $G$ is given, put in it the vector of parameters of the outmost operator defining $F$ (empty vector if $F$ is a leaf or a modular form space). \f\kbd{mfdim(mf,$\{\text{space}=4\}$)}: dimension of the space \kbd{mf}, where \kbd{mf} can also be of the form $[N,k,\chi]$ in which case \kbd{space} is taken into account. \kbd{mf} can also be of the form $[N,k,0]$, where $0$ is a wildcard, in which case it gives detailed information for each character $\chi$ for which the corresponding space of level $N$, weight $k$ and given character is nonzero: each result is of the form \kbd{[order,Conrey,dim,dimdih]}, where \kbd{Conrey} is the Conrey label for the character, \kbd{order} is its order, \kbd{dim} is the dimension of the corresponding space, and \kbd{dimdih}, which is computed only in weight $1$, is the dimension of the subspace of dihedral forms. \f\kbd{mfdiv(F,G)}: division of \kbd{F} by \kbd{G}. \f\kbd{mfEH(k)}: $k$ being half-integral, gives the Cohen--Eisenstein series of weight $k$ on $\G_0(4)$. \f\kbd{mfeigenbasis(mf)}: \kbd{mf} containing the new space, gives (in some order) the basis of normalized eigenforms. \f\kbd{mfeigensearch(NK,AP)}: search for normalized eigenforms with integer coefficients in spaces specified by \kbd{NK}, satisfying conditions satisfied by \kbd{AP}. \kbd{NK} is a pair $[N,k]$, the search being in level $N$ and weight $k$ with trivial or quadratic character; the parameter $N$ may be replaced by a vector of allowed levels. \kbd{AP} is a list of pairs $[[p_1,a(p_1)],...,[p_n,a(p_n)]]$, where $a(p)$ is either an integer or an \kbd{intmod} (match modulo $a(p)\kbd{.mod}$). \f\kbd{mfeisenstein(k,$\{\chi_1\}$,$\{\chi_2\}$)}: Eisenstein series $E_k(\chi_1)$ or $E_k(\chi_1,\chi_2)$, normalized so that $a(1)=1$ (so \kbd{mfeisenstein(k)} without any character argument is equal to \kbd{mfEk(k)} multiplied by $-B_k/(2k)$). \f\kbd{mfEk(k)}: Eisenstein series $E_k$ for the full modular group normalized so that $a(0)=1$, including for $k=2$. \f\kbd{mfeval(mf,F,vtau)}: evaluation of $F$ at the point \kbd{vtau} (or a vector of points) in the completed upper half-plane. If $F$ is an eigenform with several embeddings in $\C$, evaluate at each embedding. \f\kbd{mffields(mf)}: \kbd{mf} containing the new space, gives the list of relative polynomials defining the number field extensions for all the Galois orbits of the eigenforms. \kbd{mf} can also be a modular form, in which case the result is the number field extension of $\Q(\chi)$ in which the Fourier coefficients of \kbd{mf} lie. \f\kbd{mffromell(e)}: \kbd{e} being an elliptic curve defined over $\Q$ in \kbd{ellinit} format, gives \kbd{[mf,F,coe]}, where \kbd{F} is the eigenform corresponding to \kbd{e} by modularity, \kbd{mf} the corresponding new space, and \kbd{coe} the coefficients of \kbd{F} on the basis of \kbd{mf}. \f\kbd{mffrometaquo(eta,$\{\text{flag}=0\}$)}: \kbd{eta} being a matrix representing an eta quotient, gives the corresponding modular form or function. If the result is not a modular form or function, return an error if \kbd{flag=0}, or $0$ otherwise. If the result has negative valuation, normalize to valuation $0$. \f\kbd{mffromlfun(L)}: \kbd{L} being the $L$-function of a self-dual modular form with rational coefficients, for instance a rational eigenform, retun \kbd{[NK,space,v]}, where \kbd{mf = mfinit(NK,space)} is a modular form space containing the form and \kbd{mftobasis(mf,v)} yields the coefficients of \kbd{F} on the basis of \kbd{mf}. \f\kbd{mffromqf(Q,$\{P\}$)}: \kbd{Q} being an even integral quadratic form of even dimension and \kbd{P} an optional homogeneous spherical polynomial with respect to \kbd{Q}, gives \kbd{[mf,F,coe]}, where \kbd{F} is the theta function associated to \kbd{Q} and \kbd{P}, \kbd{mf} the corresponding space, and \kbd{coe} the coefficients of \kbd{F} on the basis of \kbd{mf}. \f\kbd{mfgaloistype(mf,$\{F\}$)}: \kbd{mf} being either $[N,1,\chi]$ or a new or cuspidal space of weight $1$ forms, outputs the type of the projective representations attached to all the eigenforms in \kbd{mf}, or only that of \kbd{F} if it is given. The output is $2n$ for $D_n$, or $-12$, $-24$, $-60$ for $A_4$, $S_4$, $A_5$. \f\kbd{mfhecke(mf,F,n)}: Computes $T(n)(f)$, where $T(n)$ is the $n$th Hecke operator. Note that the level which is used is that of the modular form space \kbd{mf}, not that of $F$ if it is different. \f\kbd{mfheckemat(mf,n)}: matrix of $T(n)$ on the space \kbd{mf}. \f\kbd{mfinit(NK,$\{\text{space}=4\}$)}: create the space of modular forms associated to $NK=[N,k,\chi]$ or $NK=[N,k]$. Codes for \kbd{space} is $0$, new space, $1$ cuspidal space, $2$ old space, $3$ space of Eisenstein series, $4$ full space $M_k$ (default). $NK$ can also be of the form $NK=[N,k,0]$, where $0$ is a wildcard, in which case it gives the vector of all nonzero \kbd{mfinit} for each Galois orbit of characters $\chi$. \f\kbd{mfisCM(F)}: returns $0$ if $F$ does not have complex multiplication, and the CM discriminant(s) if it does. Note that in weight $1$ $F$ may have two CM discriminants, which occurs iff its galoistype is $D_2$. \f\kbd{mfisequal(F,G,$\{\text{lim}=0\}$)}: Are $F$ and $G$ equal, or at least are their first \kbd{lim+1} Fourier coefficients equal ? \f\kbd{mfkohnenbasis}(mf): \kbd{mf} being a cuspidal space of half-integral weight and level $4N$ with $N$ squarefree, computes a basis $B$ of the Kohnen $+$-space as a matrix whose columns are the coefficients of $B$ on the basis of \kbd{mf}. \f\kbd{mfkohnenbijection}(mf): \kbd{mf} being a cuspidal space of half-integral weight, computes \kbd{[mf2,M,K,shi]}, where \kbd{M} is a matrix giving a Hecke-module isomorphism from the cuspidal space \kbd{mf2} of weight $2k-1$ and level $N$ to the Kohnen $+$-space of weight $k$ and level $4N$, the columns of the matrix \kbd{K} are the coefficients of the Kohnen $+$-space on the basis of \kbd{mf}, and \kbd{shi} gives technical information about which linear combination of Shimura lifts has been chosen. \f\kbd{mfkohneneigenbasis}(mf,bij): \kbd{mf} being a cuspidal space of half-integral weight and \kbd{bij} the output of \kbd{mfkohnenbijection(mf)}, computes a triple \kbd{[mf0,Bnew,Beigen]}, where \kbd{Bnew} and \kbd{Beigen} are matrices whose columns are the coefficients of a basis of the Kohnen new space and of the eigenforms on the basis of \kbd{mf} respectively, and \kbd{mf0} is the corresponding new space of integral weight $2k-1$. \f\kbd{mflinear(vecF,vecL)}: linear combination of the forms in \kbd{vecF} with coefficients in \kbd{vecL}. Forms must have the same weight and character, but not necessarily the same level. This function is used for simpler operations such as \begin{verbatim} mflinear([F],[s]) \\ scalar multiplication mflinear([F,G],[1,1]) \\ addition mflinear([F,G],[1,-1]) \\ subtraction \end{verbatim} If \kbd{vecF=mfbasis(mf)}, it is better to write \kbd{mflinear(mf,vecL)} instead, since coefficient computations will be faster. \f\kbd{mfmanin(FS)}: $FS$ being a modular symbol associated to an eigenform, returns $[[P^+,P^-],[\omega^+,\omega^-,r]]$ where the $P^{\pm}$ are the even/odd polynomials of special values, the $\omega^{\pm}$ the corresponding periods, and $r=\Im(\omega^+\overline{\omega^-})/$. \f\kbd{mfmul(F,G)}: product of the modular forms $F$ and $G$. \f\kbd{mfnumcusps(N)}: number of cusps of $\G_0(N)$. \f\kbd{mfparams(F)}: returns parameters $[N,k,\chi,P]$ of the modular form $F$, where $K$ is the polynomial defining the number field containing the coefficients of $F$ (e.g., $y$ if $F$ is rational), or $[-1,-1,-1,0]$ if it is not defined. If $F$ is a modular form space, returns $[N,k,\chi,space]$. \f\kbd{mfperiodpol(mf,F,$\{\text{parity}=0\}$)}: period polynomial of the form $F$; if the \kbd{parity} argument is $1$ or $-1$, return the even/odd period polynomial. \f\kbd{mfperiodpolbasis(k,$\{\text{parity}=0\}$)}: basis of period polynomials of weight $k$ for the full modular group, even/odd ones if \kbd{parity} is $1$ or $-1$. \f\kbd{mfpetersson(FS,$\{\text{GS}=\text{FS}\}$)}: $FS$ and $GS$ being the modular symbols associated to $F$ and $G$ with \kbd{mfsymbol}, computes the Petersson product of $F$ and $G$ with the usual normalization $1/[\G:\G_0(N)]$. (Petersson square if $GS$ is omitted.) \f\kbd{mfpow(F, n)}: Modular form $F$ to the power $n$. \f\kbd{mfsearch([N,k], V, $\{\text{space}=4\}$)}: search for \emph{rational} modular forms of weight~$k$ and level $N$ in the specified modular form spaces whose Fourier expansion up to the length of $V$ exactly matches $V$. The output is a list of forms. The parameter $N$ may be replaced by a list of allowed levels, e.g. \kbd{[$N_1$..$N_2$]} for all levels between $N_1$ and $N_2$. \f\kbd{mfshift(F,m)}: \kbd{F} divided by $q^m$, omitting the remainder if there is one, where $m$ can be positive or negative. The result is usually not a modular form. \f\kbd{mfshimura(mf,F,$\{D = 1\}$)}: $F$ being a modular form of half-integral weight $k\ge3/2$ and $D$ a discriminant, return \kbd{[mf2,FS,v]}, where \kbd{FS} is the corresponding Shimura lift of integral weight $2k-1$, \kbd{mf2} the corresponding modular form space and \kbd{v} the coefficients of \kbd{FS} on the basis of \kbd{mf2}. By extension, $D$ can also be a positive squarefree integer. \f\kbd{mfslashexpansion(mf,f,g,n,flrat,$\{\&P\}$)}: compute the Fourier expansion of $f|_k g$ to order $n$, where $f$ is a form in \kbd{mf} and $g\in M_2^+(\Q)$. If \kbd{flrat} is set, try to ``rationalize'' (error if unsuccessful). If the output is $[a(0),...,a(n)]$ and the optional $P$ contains parameters $[\al,w,A]$, then $f|_k g = F|_k A$ where $F(\tau) = q^{\al}\sum_{0\le j\le n}a(j)q^{j/w}$, with $q=\exp(2\pi i\tau)$. $A$ is always upper triangular and usually the identity, so that $F|_k A$ is immediate to compute. \f\kbd{mfspace(mf,$\{F\}$)}: type of modular space \kbd{mf} if $F$ is omitted, or of a modular form $F$ in \kbd{mf}: result is $0$ for new, $1$ for cuspidal, $2$ for old, $3$ for full, $4$ for Eisenstein, and $-1$ if form is not in the space. \f\kbd{mfsplit(mf,$\{\text{dimlim}=0\}$,$\{\text{flag}=0\}$)}: compute the eigenforms in \kbd{mf}, and limit the dimension of each Galois orbit to \kbd{dimlim} if set. \kbd{flag} is used to avoid some long computations (see doc). The space \kbd{mf} \emph{must} contain the new space. Note that the result is only a two-component vector \kbd{vF,vK}, where \kbd{vF} is a vector of eigenforms and \kbd{vK} the corresponding number fields, but is \emph{not} similar to the output of an \kbd{mfinit} command. \f\kbd{mfsturm(mf)}: If \kbd{mf} is a space, true Sturm bound of \kbd{mf}, i.e., largest valuation at infinity of a nonzero form. If \kbd{mf} is $[N,k,\chi]$, only an upper bound. \f\kbd{mfsymbol(mf,F)}: initialize data for working with integrals related to $F$ such as \kbd{mfsymboleval}, \kbd{mfpetersson}, and \kbd{mfmanin}. \f\kbd{mfsymboleval(FS,path,$\{\ga\}$)}: $FS$ being the modular symbol assocated to some form $F$ and \kbd{path} being $[s_1,s_2]$ where $s_1$ and $s_2$ are cusps or points in the upper half-plane, evaluate the symbol on the path, i.e., compute the polynomial $\int_{s_1}^{s_2}(X-\tau)^{k-2}F(\tau)\,d\tau$. If $\ga\in GL_2^+(\Q)$ is given, replace $F$ by $F|_k\ga$. If the integral diverges, the result will be either a rational function or a polynomial of degree $d>k-2$. \f\kbd{mftaylor(F,n,$\{\text{fl}=0\}$)}: for now, only for $F\in M_k(\G)$ and at the point $i$. Compute the first $n$ Taylor coefficients of $F$ around $i$; if \kbd{fl} is set compute in fact $p_n$ such that $$f(\tau)=(2i/(\tau+i))^k\sum_{n\ge0}p_n((\tau-i)/(\tau+i))^n\;.$$ \f\kbd{mfTheta($\{\chi\}$)}: unary theta series corresponding to the primitive Dirichlet character $\chi$, thus in weight $1/2$ (resp., $3/2$) if $\chi$ is even (resp., odd). \f\kbd{mftobasis(mf,F,$\{\text{flag}=0\}$)}: coefficients of form $F$ on the basis in \kbd{mf}. If \kbd{flag} is set, do not return an error if $F$ does not belong to \kbd{mf} or not enough coefficients. \f\kbd{mftocoset(N,M,L)}: $L$ being the list of cosets output by \kbd{L=mfcosets(N)} and $M$ being in $\SL_2(\Z)$, output a pair $[\ga,i]$ such that $M=\ga L[i]$, where $\ga\in \G_0(N)$. \f\kbd{mftonew(mf,F)}: Decompose $F$ is the cuspidal space \kbd{mf} as a sum of $B(d)G_M$ where $G_M\in S_k^{\new}(\G_0(M),\chi)$ and $dM\mid N$, return the vector of $[M,d,G]$. \f\kbd{mftraceform(NK,$\{\text{space}=0\}$)}: gives the trace form corresponding to $NK=[N,k,\chi]$ and \kbd{space} (only the new space and the cuspidal space). \f\kbd{mftwist(F,D)}: twist of the form $F$ by the quadratic character $(D/n)$. \end{document} pari-2.17.2/doc/pdfmacs.tex0000644000175000017500000001213614567450071014104 0ustar billbill% Copyright (c) 2000 The PARI Group % % This file is part of the PARI/GP documentation % % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License %% Modifications to parimacro.tex to be run through pdftex instead of %% tex. Code now includes some pdf-specific code for hyperlinks. %% %% Cliff Bergman (cbergman@iastate.edu) Jan. 2000. %% % %% Set the document info \pdfoutput = 1 \pdfinfo { /Title (\TITLE) /Creator (pdfTeX) /Producer (PARI, pari@math.u-bordeaux.fr) /Author (The PARI group) /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\chapterskip{ \ifnum\chapno=0 \else \append0\numsectok \fi \global\advance\chapno by 1 } \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 \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\chapno {\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.17.2/doc/gphelp.in0000755000175000017500000011067314760123736013564 0ustar billbill#!@runtime_perl@ $version= "@version@"; $datadir= "@datadir@"; # no expanded material (@key@) below # 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_dumb_pod file same, but without nested formating # -utf8 in detex mode, use UTF-8 encoding for output # # 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) # $wwwsite= "https://pari.math.u-bordeaux.fr/"; $xdvi = $ENV{GPXDVI} || "xdvi"; $xdviref = $ENV{GPXDVIREF} || "$xdvi -paper 29.7x21cm"; $gzip = "gzip"; $zcat = "$gzip -dc"; $bzip = "bzip2"; $bzcat = "$bzip -dc"; $docdir = &get_docdir(); $tex = $ENV{GPTEX} || "tex"; $refcard = (@ARGV and $ARGV[-1] =~ /refcard/i); $dumb_pod=1, $ARGV[0] = '-to_pod' if @ARGV && $ARGV[0] eq '-to_dumb_pod'; &to_pod() if @ARGV[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 or $raw; 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 { $utf8 = $raw = $detex = $fromgp = $apropos = $noskip = 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 "-utf8") { $utf8 = 1; } elsif ($_ eq "-noskip") { $noskip = 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)); } elsif ($_ =~ /^-pari-version=(.*)/) { $version = $1; } else { &help(); } } $ch = "\e[m$ch"; $cu .= $cu ? "\e[1m": "\e[4m"; $cb .= "\e[1m"; $detex = 1 if (!$ENV{DISPLAY}); } sub get_docdir { my $d = $ENV{GPDOCDIR} || $ENV{GPHELP_DOCDIR}; if (!defined $d) { # work from TOPDIR/Oarch or TOPDIR too: may be uninstalled yet; $d = $0; $d =~ s,/gphelp,,; for ("$datadir", '.', '..', $d) { my $t = "$_/doc"; if (-f "$t/translations") { $d = $t; last; } } $d ||= "$datadir/doc"; # Last resort } if ($d =~ /^\./) { eval { require Cwd; $d = Cwd::cwd() . "/$d"; $d =~ s,doc/\.\./doc,doc,; } } return $d; } sub init { &inittr(); $indent = " "; # avoid Glob.pm! (for minimal Windows install) opendir(DIR, $docdir) || die "$docdir not found"; @file_list = grep { /^usersch.*tex/ } readdir(DIR); closedir(DIR); chdir($docdir); $docfile = "usersch3.tex"; open(IN,"translations") || die("Could not find translation file, docdir='$docdir'"); while() { chomp; @_ = split(/ *\@ */); $key = shift(@_); $transl{$key} = join('@',@_); } close(IN); } sub not_found { my($help) = shift; $help =~ s/\\\\/_B#K#S_/g; $help =~ s/\\(.)/$1/g; $help =~ s/_B#K#S_/\\/g; print "'$help' not found !\n"; } sub choose_chap { while (s/\@([0-9])$//) { $docfile = "usersch$1.tex"; } if (-f $docfile) { $pipe = ""; } else { die "Cannot find $docfile" if (! -f "$docfile.z" && ! -f "$docfile.gz" && ! -f "$docfile.Z" && ! -f "$docfile.bz2"); if (-f "$docfile.bz2") { $pipe = $bzcat; $docfile = "$docfile.bz2"; } else { $pipe = $zcat; } } } sub safe_setsid { eval { require POSIX; POSIX::setsid(); # detach from terminal (^C will not kill xdvi) }; } # assume we're in $docdir sub open_viewer_then_quit { my $F = shift; my ($f, $viewer, $redirect); my $cygwin = ($^O =~ /cygwin/); my $win32 = ($^O =~ /ms(win|ys)/); my $osx = ($^O =~ /darwin/); $f = "$F.dvi"; $f = "$F.dvi.gz" if (! -f "$f"); $f = "$F.pdf" if (! -f "$f"); die "could not find \'$F\'" if (! -f "$f"); $F = $f; $redirect = ' 2>/dev/null >/dev/null &'; if ($f =~ /\.dvi/) { # DVI $viewer = ($f =~ /refcard/)? $xdviref: $xdvi; } elsif ($cygwin) { # PDF Win32 @_ = split(/"/, `acro.exe`); ($viewer = $_[1]) =~ s,\\,/,g; $redirect = ""; $F =~ s,/cygdrive/(.),$1:, ; # Reader can't cope with Cygwin paths $F = "\"$F\""; $viewer = "\"$viewer\""; } elsif ($win32) { # PDF Win32 @_ = split(/"/, "$ENV{GP_PDF_VIEWER}"); $viewer = $_[1]; print "using \'$viewer\', "; } elsif ($osx) { $viewer = "open"; } else { # PDF generic $viewer = "acroread"; } print "displaying \'$F\'."; print "\n" if (!$fromgp); safe_setsid(); if ($win32) { system($viewer,$F); } else { system("$viewer $F$redirect"); } cleanexit(); } sub treat { my($help); $_ = $_[0]; s/_QUOTE/'/g; s/_BACKQUOTE/`/g; s/_DOUBQUOTE/"/g; s/^ *"(.*)"([^"]*) *$/$1$2/; if (s/\@$//) { $found = 0; $searchall = 1; $help = $_; for (sort @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)$/ || /^refcard-/ || /^tutorial-mf$/); if ($transl{$_}) { $_ = $transl{$_}; &choose_chap; } } my ($isdef) = /se:def,/; s/(\W)/\\$1/g; # support dbg_* without harming defaults such as prompt_cont s/_/\\\\_/g if (!$isdef); ($pipe && open(DOC,"$pipe $docfile |")) || (!$pipe && open(DOC,"$docfile")) || die "Cannot open $docfile: $!"; return &apropos($_) if ($apropos); $help = $_; my ($first); my ($pat) = $help; if ($pat =~ /[a-zA-Z0-9]$/) { $pat .= '\b'; } else { $pat .= '\}'; } if ($isdef) { while () { if (/\\label\{$pat/) { $first = $_; last; } } } else { while () { if (/\\(subsubsec[a-z]*|subsec[a-z]*|section|chapter|label)\{$pat/ && !/\\label\{se:def,/) { $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 { my ($raw, $L) = @_; my ($pre) = ($raw? "": ($fromgp? " ?? ": " ")); my ($current) = ""; for (sort @{$L}) { next if ($_ eq $current); $current = $_; $_ = "\"$_\"" if (/ /); print "$pre$_\n"; } } sub apropos_final_print { my($maxlen) = 0; my($i,$nbcol,$current); my($cols) = ($ENV{'COLUMNS'} || 80) - 1; if ($raw) { &apropos_print_list(1, \@sentence_list); &apropos_print_list(1, \@list); 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); return if (!$#sentence_list); if ($fromgp) { print "\nAlso inspect the output of:\n" } else { print "\nSee also:\n" if ($#list > 0); } apropos_print_list(0, \@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/\\\#/\#/g; s,\+\$/\$-,+/-,; s/\$\(.*//; # remove argument lists if (/ /) { push(@sentence_list,$_); } else { push(@list,$_); } } sub apropos { my($line,$current,$new); $help = $_[0]; $help='\\\\pow' if ($help eq '\^'); $help='\\\\til' if ($help eq '\~'); @sentence_list = @list = ""; while () { if (/^\\(subsubsec[a-z]*|subsec[a-z]*|section|chapter)\{/) { $new = &get_match($_,'\\{','\\}'); &apropos_check($line, $current); $current = $new; $line = ""; } $line .= $_; } &apropos_check($line, $current); } ## ## Tex Part ## # Actual text is in file TEX. Parimacro + Geometry info goes to WRAP sub pretex { my ($basedir) = $ENV{GPHELP_TMPDIR} || $ENV{GPTMPDIR} || $ENV{TMPDIR} || "/tmp"; $tmpdir = "$basedir/gp.help$$"; mkdir $tmpdir, 0755 || die "Cannot create temporary directory"; $texfile = "$tmpdir/gp.help"; open(TEX,">$texfile.tex") || die "Couldn't open $texfile.tex"; } sub endsection { /^\\(section|sub[sub]*sec)/i && ($noskip || !/\%GPHELPskip/); } sub tex { my ($first) = @_; print TEX $first; while () { last if endsection(); print TEX; } } sub posttex { my ($wrap) = "$tmpdir/gpwrapper.help"; my ($F) = ($tex =~ /pdftex/)? "$wrap.pdf": "$wrap.dvi"; my (@goners) = ("$texfile.tex", $F, "$wrap.tex", "$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 "$F" || die "could not create '$F': status=$?, $out"; safe_setsid(); my ($goners) = join(" ", @goners); system("($xdvi $F 2>/dev/null >/dev/null; rm -f $goners; rmdir $tmpdir)&"); } # # Detex Part # sub fit_loop { my($i); return if ($miss > 9 || $#_ <= 0); while ($miss > 0) { # print "1:$miss ";print @_;print "\n"; for (@_) { $miss-- if (s/([?!\.;])$/$1 /); return if ($miss == 0); } # print "2:$miss ";print @_;print "\n"; for (@_) { $miss-- if (s/([?!\.;]) $/$1 /); return if ($miss == 0); } # print "3:$miss ";print @_;print "\n"; for (@_) { $miss-- if (s/([\),])$/$1 /); return if ($miss == 0); } # print "4:$miss ";print @_;print "\n"; $i = 0; for (@_) { if (!$i) { $i = 1; next; } $miss-- if (s/^\(/ (/); return if ($miss == 0); } # print "5:$miss "; print @_;print "\n"; for (@_) { next if (/^ *$/); $miss--; s/$/ /; return if ($miss == 0); } } } sub fit_line { my($wi, @a); my($l) = -1; my($rem) = $_[0]; for (@l) { my ($l2) = $l; $l += ($_ + 1); if ($l > $rem) { $l = $l2; last; } $wi++; } $miss = $rem - $l; splice(@l, 0, $wi); @a = splice(@w, 0, $wi-1); &fit_loop(@a); push(@a, shift(@w)); return join(' ', @a); } # empty output line sub is_void { my($in) = shift; $in =~ s/\@\[\w+\]//g; $in =~ s/\@[012]//g; ($in =~ /^\s*$/)? 1: 0; } sub nl { push(@f_text, shift); } sub split_words { my ($txt) = @_; $txt =~ s/^ +//; $txt =~ s/([_\^])\{ *([^\-\^\{\}]+) *\}/$1$2/g; for ( split(/\s+/, $txt) ) { s/\Q$tr{nbrk}/ /g; my ($w) = $_; # these codes will be replaced by 1 character s/\@\[(obr|cbr|ldollar|lt|gt|\{|\})]/\@/g; if ($utf8) { s/\@\[(ouml|uuml|agrav|aacute|eacute|pm)]/\@/g; } # one char else { s/\@\[(ouml|uuml|agrav|aacute|eacute)]/\@\@/g; # two chars s/\@\[pm]/+\/-/g; # three chars } # the rest will be replaced by zero-width characters s/\@\[\w+\]//g; my ($l) = length($_); # zero-width word if (!$l && $#w >= 0) { $w[$#w] .= $w; next; } push(@l, $l); push(@w, $w); } # first word might still be zero-width if ($#w >= 1 && !$l[0]) { splice(@w, 0,2, "$w[0]$w[1]"); splice(@l, 0,1); } } sub format_text { my($last_void) = 0; my($noindent) = 0; my($init) = 1; my($cols) = ($ENV{'COLUMNS'} || 80) - 1; my($first) = $cols - length($indent); for (@text) { if (s/^\@1//) # start verbatim { nl(&fit_line($first)) if (@w); nl("") if (!$last_void && !is_void($_)); # add empty line nl("$indent$_"); next; } if (s/^\@0//) # verbatim lines { nl("$indent$_"); next; } if (s/^\@2//) # end verbatim, add indent { nl("") if (!$last_void); $last_void = 1; split_words($_); next; } if (s/^\@3//) # end verbatim + no indent { nl("") if (!$last_void); $noindent = 1; $last_void = 1; split_words($_); next; } if (!is_void($_)) { split_words($_); next; } # line is empty, split out previous paragraph next if (!@l || !$l[0]); # nothing if ($init) { nl(&fit_line($first)); } else { nl("") if (!$last_void); nl("\@[endbold]" . ($noindent? "": $indent) . &fit_line($noindent? $cols: $first)); } while (@w) { nl(&fit_line($cols)); } $noindent = $init = $last_void = 0; } } # argument has the form s1${open}s2${close}s3 # Return 's2'. Set $remainder to 's3'. sub get_match { local ($_, $open, $close) = @_; my (@tmp, $arg,$parity,$ok); my ($obr) = 1; $parity = ($open eq $close); /$open/; $_ = $'; # remove everything before (and including) first $open while ($_) { @tmp = split(/($open|$close)/); while ($#tmp >= 0) { $_ = shift(@tmp); $obr++ if (/^$open$/); if ($parity && $obr == 2) { $ok = 1; last } $obr-- if (/^$close$/); if (!$obr) { $ok = 1; last } $arg .= $_; } last if ($ok); $_ = ; } $remainder = join('',@tmp); return $arg; } sub detex { my($fun); # 1: get the function "prototype" $fun = &get_match($_,'\\{','\\}'); $fun = &basic_subst($fun); $_ = $remainder; $_ = if (!&basic_subst($_)); push(@text, "\@[startbold]$fun:\@[endbold]"); push(@text, ""); # 2: parse the function description if ($_) { s/^ *://; &presubst(); } while () { last if endsection(); &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 startref endref startbold endbold startcode endcode obr cbr uuml ouml agrave aacute eacute startpodcode endpodcode startlink endlink startbc endbc startbg endbg 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 '>>')), startbc => 'I<', endbc => '>', startbg => 'B<', endbg => '>', startit => 'I<', endit => '>', startword => 'F<', endword => '>', startlword => ' F<', endlword => '> ', pm => 'F<+->', "gt" => 'E', "lt" => 'E', ouml => 'E', uuml => 'E', eacute => 'E', agrave => 'E', aacute => 'E', empty => 'Z<>', podleader => '=', ); } sub indent_equally { my $in = shift; $in =~ s/^[ \t]*/ /mg; $in } sub quote { my $in = shift; $in =~ s/~/\\~/g; $in } sub basic_subst { local($_) = shift; s/\\teb\{([^\}]*)\}/"\\sidx{$1}$tr{startbold}" . quote($1) . "$tr{endbold}"/eg; s/\\tet\{([^\}]*)\}/"\\sidx{$1}$tr{startcode}" . quote($1) . "$tr{endcode}"/eg; s/\\url\{([^\}]*)\}/"\\sidx{$1}$tr{startcode}" . quote($1) . "$tr{endcode}"/eg; s/\\tev\{([^\}]*)\}/"\\sidx{$1}$tr{startit}" . quote($1) . "$tr{endit}"/eg; s/(\S)[ \t]*\n[ \t]+/$1\n/gm; s/([^\\])\\\{/$1$tr{obr}/g; s/([^\\])\\\}/$1$tr{cbr}/g; 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|widetilde)/~/g; s/\\colon\b/:/g; s/\\(equiv)(?![a-zA-Z])/ = /g; s/\\'a/$tr{aacute}/g; s/\\'\{a\}/$tr{aacute}/g; s/\\`a/$tr{agrave}/g; s/\\`\{a\}/$tr{agrave}/g; s/\\"o/$tr{ouml}/g; s/\\"\{o\}/$tr{ouml}/g; s/\\"u/$tr{uuml}/g; s/\\"\{u\}/$tr{uuml}/g; s/\\'e/$tr{eacute}/g; s/\\'\{e\}/$tr{eacute}/g; s/{\\cal (.)}/$tr{startbc}$1$tr{endbc}/g; s/(^|[^\\])%.*/$1/g; # comments s/\\vadjust\s*\{\s*\\penalty\s*\d+\s*\}//g; # We do not strip %\n, thus: s/\\kbd\{\n\s*/\\kbd{/g; s/\$\\bf(\b|(?=[\d_]))\s*([^\$]+)\$/\$$tr{startbcode}$1$tr{endbcode}\$/g; s/\$/$tr{dollar}/g; # math mode s/\t/ /g; s/\\,//g; s/\\[ ;]/ /g; # various spaces s/\\\///g; # italic correction s/^&+//g; # tab marks s/([^\\])&+/$1 /g; # tab marks s/\\TeX\{\}/TeX/g; s/\\TeX(\W)/TeX$1/g; s/ *\\circ\b */ o /g; s/\\d?frac\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}/($1)\/($2)/g; s(\\d?frac\s*(\d)\s*(\d))(($1/$2))g; s[\{\s*(\w)\s*\\over(?![a-zA-Z])\s*(\w)\s*}]{($1/$2)}g; s[\{\s*((?:[^{}]|\{[^{}]*\})*)\\over(?![a-zA-Z])\s*((?:[^{}]|\{[^{}]*\})*)}][($1)/($2)]g; # \def\synt#1#2{\syn{#1}{\tt #2}} # \def\syn#1#2{\synx{#1}{#2}{#1}} s/\\synt?\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}/\\synx{$1}{$2}{$1}/g; # \def\synx#1#2#3{\sidx{#3}The library syntax is $\key{#1}({#2})$} # Often used with embedded {}. s/\\synx\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{((?:[^{}]|\{[^{}]*\})*)\}/\\sidx{$3}The library syntax is $tr{startcode}$tr{startbold}$1$tr{endbold}($2)$tr{endcode}/; # May be used with an empty arg s/\\typ\{([^\}]*)\}/$tr{startcode}t_$1$tr{endcode}/g; s/(\\string)?\\_/_/g; s/\\([#\$&%|])/$1/g; s/\\(hat(?![a-zA-Z])|\^)(\{\\?\s*\})?/^/g; s/\\hbox\{\\kbd\{\\pow}}/^/g; # from doc_make s/^(\@\[podleader\]head\d *)\\pow(?![a-zA-z])( *)/$1^$2/gm; s/ *\\pow(?![a-zA-z]) */^/g; s/\\neq?(?![a-zA-Z])/ != /g; s/\\enspace(?![a-zA-Z])/ /g; s/\\\*/ /g; s/\\times(?![a-zA-Z]) */ x /g; s/\\infty(?![a-zA-Z]) */ oo /g; s/ *\\(bmod|mod) */ mod /g; s/ *\\pmod(?![a-zA-Z]) *\{\s*((?:[^{}]|\{[^{}]*\})*)\}/ (mod $1)/g; s/ *\\cdot(?![a-zA-Z]) */./g; # Maybe " . "? s/ *(\\|\@)[lc]?dots(?![a-zA-Z]) */.../g; # math operators s/\\(Norm | Frob | disc | Cl | Re | Im | exp | log | ln | arg | sin(h)? | cos(h)? | tan(h)? | sqrt | lim(proj)? | mod | gcd | lcm | Id | det | Hom | deg | expr | seq | args | min | max ) (?![a-zA-Z])/$tr{startlword}$1$tr{endlword}/xg; # math symbols with HTML entities equivalents 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 | ell | wp | cap | cup | sup | prod | sum | int | nmid) (?![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; if (!$to_pod) { s/\\secref\{/Section \\ref{/g; s/\\ref\{([^\}]*)\}/$tr{startref}$1$tr{endref}/g; if ($raw) { s/\\label\{([^\}]*)\}/\@[label $1]/g; } else { s/\\label\{[^\}]*\}//g; } } s/ *\\noindent\b */\@3/; s/\\(medskip|bigskip|smallskip|left|right)(?![a-zA-Z])[ \t]*//g; s/\\vfill *(\\eject)?//g; s/\\(q|quad)(?![a-zA-Z])\s*/ /g; s/\\qquad(?![a-zA-Z])\s*/ /g; s/\\centerline\s*\{\s*(?:\\tt\b\s*)?(.*(\n[ \t].*)*)\}(?=\s*$)/indent_equally($1)/ge; s/\\centerline\s*\{\s*(?:\\tt\b\s*)?((?:[^{}]|\{[^{}]*\})*)\}/ indent_equally($1)/ge; s/\\big\b//g; s/\\settabs.*//; s/^\\\+/\n$tr{nbrk}/gm; s/\\\+//g; s/\\cr(?![a-zA-Z])//g; s/\\B(?![a-zA-Z])/\\kbd{BIL}/g; s/ *([=><]) */ $1 /g; s/ *< *([=<]) */ <$1 /g; s/ *> *([=>]) */ >$1 /g; s/ *([*+-\/^&=|:]) += */ $1= /g; # now fix spacing s/ == = / === /g; s/< *([-a-zA-Z]*) *>/<$1>/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/\\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}/g; s/\\([QRCPFZN])(?![a-zA-Z])/$tr{startbi}$1$tr{endbi}$2/g; s/\\Bbb\b\s*(\w)/$tr{startbi}$1$tr{endbi}/g; s/\\([oc]br)/$tr{$1}/g; s/\\quo(?![a-zA-Z])/\"/g; s/(^|\s)\{(\w+)\}/$1$2/g; s/\\p(?![a-zA-Z])/$tr{startbold}p$tr{endbold}$1/g; s/^ *\\point\{([^\}]*)\}/\\item $1/g; s/\@\[dollar]\\bullet\@\[dollar]/\\item /g; s/\\bullet/\\item/g; s/^ *\\item/\@3$tr{startbold}*$tr{endbold}/g; s/\\item/$tr{startbold}*$tr{endbold}/g; s/^ *\\misctitle\{((?:[^{}]|\{[^{}]*\})*)\}/\@3$tr{startbold}$1.$tr{endbold}/g; s/\\subsubsec\{([^\}]*)\}/\@3$tr{startbold}$1.$tr{endbold}/g unless $to_pod; s/\\subsec\{([^\}]*)\}/\@3$tr{startbold}$1.$tr{endbold}/g unless $to_pod; 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{startbg}$1$tr{endbg}/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\{([a-zA-z0-9]*)\}/$1/g; s/\\(text|hbox|Big)//g; s/([A-Za-z])--([A-Za-z])/$1-$2/g; # Rankin--Cohen s/^([ \t]+)\{ *\\(it|sl|bf|tt)\b/S<$1>{\\$2/gm; s/\{ *\\(it|sl) *(([^{}]+(?=[{}])|\{[^{}]*\})*)\}/$tr{startit}$2$tr{endit}/g; s/\{ *\\bf *(([^{}]+(?=[{}])|\{[^{}]*\})*)\}/$tr{startbold}$1$tr{endbold}/g; s/\{ *\\tt *(([^{}]+(?=[{}])|\{[^{}]*\})*)\}/$tr{startpodcode}$1$tr{endpodcode}/g; $seek=1 if (s/\\emph\{ */$tr{startit}/g); if ($seek) { $seek=0 if (s/\}/$tr{endit}/) } s/\\(backslash|bs)\{(\w)\}/\\$2/g; s/\\(backslash|bs)(?![a-zA-Z]) */\\/g; s/ *\\setminus */ \\ /g; s/\@com(.*)$/$tr{startcode}$1$tr{endcode}/g; # Last resort: s/\\kbd\s*\{(.*?)\}/$tr{startcode}$1$tr{endcode}/g; s/^([ \t]{3,})\Q$tr{startcode}\E(.*)\Q$tr{endcode}\E/$1$2/gmo if $to_pod; # Last resort: s/^([ \t]{3,})\Q$tr{startcode}\E(.*?)\Q$tr{endcode}\E/$1$2/gmso if $to_pod; # Remove leading spaces unless have embedded wrapped code: s/^[ \t]+//gm if $to_pod and /^\S/ and not /^[ \t]*\n[ \t]/m; s/\{ *\}//g; # empty args s{\Q$tr{startcode}\E((ftp|http)://.*?)\Q$tr{endcode}\E}{$tr{startlink}$1$tr{endlink}}go if $to_pod; $_; } sub presubst { chomp; if ($in_prog && /\@eprog *(\\noindent)? */) { my ($eprog) = $1? '@3': '@2'; $in_prog = 0; $_ = $eprog . &code_subst($`) . $tr{endcode}; push(@text, $_); $_ = &basic_subst($'); } elsif ($in_prog || s/\\bprog(tabs.*)?//g) { $in_prog++; # = 1 on the \bprog line # code should start on the next line $_ = &code_subst($_); s/^/\@1$tr{startcode}/ if ($in_prog == 2); s/^/\@0/ if ($in_prog > 2); } else { $_ = &basic_subst($_); } if (/^ *$/) { push(@text,"\n"); } else { for (split(/\n/, $_)) { push(@text, $_); } } } sub code_subst { my $in = shift; $in =~ s/\@dots\b/.../g; if ($in =~ /\@com(.*)/) { my ($c) = &basic_subst($1); if (!$to_pod) { $c = $tr{endcode} . $c . $tr{startcode}; } $in = $` . $c . &code_subst($'); } if ($in =~ /\@Ccom(.*)\*\//) { my ($c) = &basic_subst($1); if (!$to_pod) { $c = $tr{endcode} . $c . $tr{startcode}; } $in = $` .$c . "*/" . &code_subst($'); } $in; } sub wrap_code { my $in = shift; $in =~ s/^[ \t]+$//mg; $in = &code_subst($in); $in =~ s/^(.)/ $1/mg; $in =~ s/\s*\Z//; # $in =~ s/\\kbd\{((?:[^{}]|\{[^{}]*\})*)\}/$1/g if $to_pod; $in =~ s/\$([^\$\n]*)\$/$1/g if $to_pod; "\n\n$in\n\n"; } sub indexify { my $in = shift; $in =~ s/(^|and\s+)(\w+)(\$?\()/$1\\idx{$2}$3/g; $in =~ s/^(\\b\{\w+\})(?!\S)/\\idx{$1}/g; $in; } sub for_index { my $in = shift; 1 while $in =~ s/\Q$tr{startcode}\E(.*?)\Q$tr{endcode}\E/$1/go; $in; } sub strip_trail { my $in = shift; $in =~ s/\s+\Z//; $in } # This subroutine works in paragraph mode sub TeXprint_topod { s/\A\s+//; s/^\\def\\.*\{\n.*\n\}//gm; s/\\def\\.*//g; # Repeated in basic_subst, as the next one s/(\{[\w\s]+)\{\}([\s\w]+\})/$1$2/g; # {rnf{}llgram} s/\\vbox\s*\{\s*\\bprog/\\bprog/g; s/([\\\@])eprog\s*\}/$1eprog/g; # \n is below to prevent splitting on ' ' # We also remove ':' s/\\sectype\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}/\\subsec{Type \\typ{$1} (${2}s)}\n\\sidx{$2}/g; s/\\sectypeindex\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}/\\subsec{Type \\typ{$1} (${2}s)}\n\\sidx{$3}/g; s/\\sectypes\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}\{\s*((?:[^{}]|\{[^{}]*\})*)\}/\\subsec{Type \\typ{$1} and \\typ{$1} (${3}s)}\n\\sidx{$3}/g; # Try to guard \label/\sidx (removing possible '.') # This somehow breaks index... # s/(\\(?:section|subsec(?:ref|idx|op)?(unix)?)\s*{(?:(?:[^{}]+(?=[{}])|{[^{}]+})+)})\.?\s*\\(label|sidx)/$1\n\\$2/; s/(\\(?:section|subsec(?:ref|idx|op)?)\s*\{(?:(?:[^{}]+(?=[{}])|{[^{}]+})+)\})\.?\s*\\(label|sidx)/$1\n\\$2/; # last if /\\subsec[\\{}ref]*[\\\${]$help[}\\\$]/o; s/\\chapter\s*\{((?:[^{}]|\{[^{}]*\})*)\}\s*/\n\n$tr{podleader}head1 NAME\n\nlibPARI - $1\n\n/; s/\\appendix\s*\{((?:[^{}]|\{[^{}]*\})*)\}\s*/\n\n$tr{podleader}head1 NAME\n\nAppendix - $1\n\n/; s/\\section\s*\{((?:[^{}]|\{[^{}]*\})*)\}\s*/"\n\n$tr{podleader}head1 " . indexify($1) . "\n\n"/e; # Try to delimit by : s/\\subsec(?:ref)?(?:unix)?\s*\{(([^{}]+(?=[{}])|{[^{}]+})+)\}([^\n]*):[\n ]/"\n\n$tr{podleader}head2 " . indexify("$1$3") . "\n\n"/e; s/\\subsubsec(?:ref)?(?:unix)?\s*\{(([^{}]+(?=[{}])|{[^{}]+})+)\}([^:]*):\s*/"\n\n$tr{podleader}head3 " . indexify("$1$3") . "\n\n"/e; s/\\subsubsec\s*{(([^{}]+(?=[{}])|{[^{}]+})+)}(.*)$/"\n\n$tr{podleader}head3 " . indexify("$1") . "$3\n\n"/me; s/\\subseckbd\s*{(([^{}]+(?=[{}])|{[^{}]+})+)}([^:]*):\s*/"\n\n$tr{podleader}head2 " . indexify("$1$3") . "\n\n"/e; # Try to delimit by ' ' s/\\subsec(?:ref)?(?:unix)?\s*\{(([^{}]+(?=[{}])|{[^{}]+})+)\}(\S*)\s+/"\n\n$tr{podleader}head2 " . indexify("$1$3") . "\n\n"/e; s/\\subsec(?:title)?(?:unix)?\s*\{(([^{}]+(?=[{}])|{[^{}]*})+)\}:?\s*/"\n\n$tr{podleader}head2 " . indexify("$1") . "\n\n"/e; # This is to skip preface in refcard: /\Q$tr{podleader}\Ehead1|\\title(?![a-zA-Z])\s*\{/o and $seen_start = 1 or $seen_start or return; # Skip now! s/\\title\s*\{([^{}\s]*)(\s+([^{}]*))?\}(\s*\\centerline\s*\{([^{}]*)\})?\s*/$tr{podleader}head1 NAME\n\n$1 - $3. $5\n\n/ and $seen_title++ unless $seen_title; s/\\title\s*\{([^{}\s]*)(\s+([^{}]*))?\}(\s*\\centerline\s*\{([^{}]*)\})?\s*/\n\n/; s/\\parskip.*/\n/g; # Up to end of the line #s/([A-Z])\ until /(\\|@)eprog\b/ or eof(DOC); $acc .= wrap_code($1) if s/\A(?:tabs[^\n]*)?(?![a-zA-Z])[ \t]*\n?(.*?)(\\|@)eprog\s*//s; } $_ = $acc . basic_subst($_); s/\@[0123]//g; # 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

$ and that the Weil pairing $w(P,Q)$ has order $d_{2}$, see \kbd{??ellgroup}. If you need generators $[P,R]$ with $R$ of order $d_{2}$, find $x$ such that $R = Q-[x]P$ has order $d_{2}$ by solving the discrete logarithm problem $[d_{2}]Q = [x]([d_{2}]P)$ in a cyclic group of order $d_{1}/d_{2}$. This will be very expensive if $d_{1}/d_{2}$ has a large prime factor. The library syntax is \fun{GEN}{ellgenerators}{GEN E}. \subsec{ellglobalred$(E)$}\kbdsidx{ellglobalred}\label{se:ellglobalred} Let $E$ be an \kbd{ell} structure as output by \kbd{ellinit} attached to an elliptic curve defined over a number field. This function calculates the arithmetic conductor and the global \idx{Tamagawa number} $c$. The result $[N,v,c,F,L]$ is slightly different if $E$ is defined over $\Q$ (domain $D = 1$ in \kbd{ellinit}) or over a number field (domain $D$ is a number field structure, including \kbd{nfinit(x)} representing $\Q$ !): \item $N$ is the arithmetic conductor of the curve, \item $v$ is an obsolete field, left in place for backward compatibility. If $E$ is defined over $\Q$, $v$ gives the coordinate change for $E$ to the standard minimal integral model (\tet{ellminimalmodel} provides it in a cheaper way); if $E$ is defined over another number field, $v$ gives a coordinate change to an integral model (\tet{ellintegralmodel} provides it in a cheaper way). \item $c$ is the product of the local Tamagawa numbers $c_{p}$, a quantity which enters in the \idx{Birch and Swinnerton-Dyer conjecture}, \item $F$ is the factorization of $N$, \item $L$ is a vector, whose $i$-th entry contains the local data at the $i$-th prime ideal divisor of $N$, i.e. \kbd{L[i] = elllocalred(E,F[i,1])}. If $E$ is defined over $\Q$, the local coordinate change has been deleted and replaced by a 0; if $E$ is defined over another number field the local coordinate change to a local minimal model is given relative to the integral model afforded by $v$ (so either start from an integral model so that $v$ be trivial, or apply $v$ first). The library syntax is \fun{GEN}{ellglobalred}{GEN E}. \subsec{ellgroup$(E,\{p\},\{\fl\})$}\kbdsidx{ellgroup}\label{se:ellgroup} Let \kbd{E} be an \kbd{ell} structure as output by \kbd{ellinit}, attached to an elliptic curve $E/K$. We first describe the function when the field $K = \F_{q}$ is finite, it computes the structure of the finite abelian group $E(\F_{q})$: \item if $\fl = 0$, returns the structure $[]$ (trivial group) or $[d_{1}]$ (nontrivial cyclic group) or $[d_{1},d_{2}]$ (noncyclic group) of $E(\F_{q}) \sim \Z/d_{1}\Z \times \Z/d_{2}\Z$, with $d_{2}\mid d_{1}$. \item if $\fl = 1$, returns a triple $[h,\var{cyc},\var{gen}]$, where $h$ is the curve cardinality, \var{cyc} gives the group structure as a product of cyclic groups (as per $\fl = 0$). More precisely, if $d_{2} > 1$, the output is $[d_{1}d_{2}, [d_{1},d_{2}], [P,Q]]$ where $P$ is of order $d_{1}$ and $[P,Q]$ generates the curve. \misctitle{Caution} It is not guaranteed that $Q$ has order $d_{2}$, which in the worst case requires an expensive discrete log computation. Only that \kbd{ellweilpairing}$(E, P, Q, d_{1})$ has order $d_{2}$. For other fields of definition and $p$ defining a finite residue field $\F_{q}$, returns the structure of the reduction of $E$: the argument $p$ is best left omitted if $K = \Q_{\ell}$ (else we must have $p = \ell$) and must be a prime number ($K = \Q$) or prime ideal ($K$ a general number field) with residue field $\F_{q}$ otherwise. The curve is allowed to have bad reduction at $p$ and in this case we consider the (cyclic) group of nonsingular points for the reduction of a minimal model at $p$. If $\fl = 0$, the equation need not be minimal or even integral at $p$; of course, a minimal model will be more efficient. If $\fl = 1$, the requested generators depend on the model, which must then be minimal at $p$, otherwise an exception is thrown. Use \kbd{ellintegralmodel} and/or \kbd{ellocalred} first to reduce to this case. \bprog ? E = ellinit([0,1]); \\ y^2 = x^3 + 0.x + 1, defined over Q ? ellgroup(E, 7) %2 = [6, 2] \\ Z/6 x Z/2, noncyclic ? E = ellinit([0,1] * Mod(1,11)); \\ defined over F_11 ? ellgroup(E) \\ no need to repeat 11 %4 = [12] ? ellgroup(E, 11) \\ ... but it also works %5 = [12] ? ellgroup(E, 13) \\ ouch, inconsistent input! *** at top-level: ellgroup(E,13) *** ^-------------- *** ellgroup: inconsistent moduli in Rg_to_Fp: 11 13 ? ellgroup(E, 7, 1) %6 = [12, [6, 2], [[Mod(2, 7), Mod(4, 7)], [Mod(4, 7), Mod(4, 7)]]] @eprog\noindent Let us now consider curves of bad reduction, in this case we return the structure of the (cyclic) group of nonsingular points, satisfying $\#E_{ns}(\F_{p}) = p - a_{p}$: \bprog ? E = ellinit([0,5]); ? ellgroup(E, 5, 1) %2 = [5, [5], [[Mod(4, 5), Mod(2, 5)]]] ? ellap(E, 5) %3 = 0 \\ additive reduction at 5 ? E = ellinit([0,-1,0,35,0]); ? ellgroup(E, 5, 1) %5 = [4, [4], [[Mod(2, 5), Mod(2, 5)]]] ? ellap(E, 5) %6 = 1 \\ split multiplicative reduction at 5 ? ellgroup(E, 7, 1) %7 = [8, [8], [[Mod(3, 7), Mod(5, 7)]]] ? ellap(E, 7) %8 = -1 \\ nonsplit multiplicative reduction at 7 @eprog The library syntax is \fun{GEN}{ellgroup0}{GEN E, GEN p = NULL, long flag}. Also available is \fun{GEN}{ellgroup}{GEN E, GEN p}, corresponding to $\fl = 0$. \subsec{ellheegner$(E)$}\kbdsidx{ellheegner}\label{se:ellheegner} Let $E$ be an elliptic curve over the rationals, assumed to be of (analytic) rank $1$. This returns a nontorsion rational point on the curve, whose canonical height is equal to the product of the elliptic regulator by the analytic Sha. This uses the Heegner point method, described in Cohen GTM 239; the complexity is proportional to the product of the square root of the conductor and the height of the point (thus, it is preferable to apply it to strong Weil curves). \bprog ? E = ellinit([-157^2,0]); ? u = ellheegner(E); print(u[1], "\n", u[2]) 69648970982596494254458225/166136231668185267540804 538962435089604615078004307258785218335/67716816556077455999228495435742408 ? ellheegner(ellinit([0,1])) \\ E has rank 0 ! *** at top-level: ellheegner(E=ellinit *** ^-------------------- *** ellheegner: The curve has even analytic rank. @eprog The library syntax is \fun{GEN}{ellheegner}{GEN E}. \subsec{ellheight$(E,\{P\},\{Q\})$}\kbdsidx{ellheight}\label{se:ellheight} Let $E$ be an elliptic curve defined over $K = \Q$ or a number field, as output by \kbd{ellinit}; it needs not be given by a minimal model although the computation will be faster if it is. \item Without arguments $P,Q$, returns the Faltings height of the curve $E$ using Deligne normalization. For a rational curve, the normalization is such that the function returns \kbd{-(1/2)*log(ellminimalmodel(E).area)}. \item If the argument $P \in E(K)$ is present, returns the global N\'eron-Tate height $h(P)$ of the point, using the normalization in Cremona's \emph{Algorithms for modular elliptic curves}. \item If the argument $Q \in E(K)$ is also present, computes the value of the bilinear form $(h(P+Q)-h(P-Q)) / 4$. The library syntax is \fun{GEN}{ellheight0}{GEN E, GEN P = NULL, GEN Q = NULL, long prec}. Also available is \fun{GEN}{ellheight}{GEN E, GEN P, long prec} ($Q$ omitted). \subsec{ellheightmatrix$(E,x)$}\kbdsidx{ellheightmatrix}\label{se:ellheightmatrix} $x$ being a vector of points, this 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{ellheight($E$,x[$i$],x[$j$])}. The rank of this matrix, at least in some approximate sense, gives the rank of the set of points, and if $x$ is a basis of the \idx{Mordell-Weil group} of $E$, its determinant is equal to the regulator of $E$. Note our height normalization follows Cremona's \emph{Algorithms for modular elliptic curves}: this matrix should be divided by 2 to be in accordance with, e.g., Silverman's normalizations. The library syntax is \fun{GEN}{ellheightmatrix}{GEN E, GEN x, long prec}. \subsec{ellidentify$(E)$}\kbdsidx{ellidentify}\label{se:ellidentify} Look up the elliptic curve $E$, defined by an arbitrary model over $\Q$, in the \tet{elldata} database. Return \kbd{[[N, M, G], C]} where $N$ is the curve name in Cremona's elliptic curve database, $M$ is the minimal model, $G$ is a $\Z$-basis of the free part of the \idx{Mordell-Weil group} $E(\Q)$ and $C$ is the change of coordinates from $E$ to $M$, suitable for \kbd{ellchangecurve}. The library syntax is \fun{GEN}{ellidentify}{GEN E}. \subsec{ellinit$(x,\{D=1\})$}\kbdsidx{ellinit}\label{se:ellinit} Initialize an \tet{ell} structure, attached to the elliptic curve $E$. $E$ is either \item a $5$-component vector $[a_{1},a_{2},a_{3},a_{4},a_{6}]$ defining the elliptic curve with Weierstrass equation $$ Y^{2} + a_{1} XY + a_{3} Y = X^{3} + a_{2} X^{2} + a_{4} X + a_{6}, $$ \item a $2$-component vector $[a_{4},a_{6}]$ defining the elliptic curve with short Weierstrass equation $$ Y^{2} = X^{3} + a_{4} X + a_{6}, $$ \item a single-component vector $[j]$ giving the $j$-invariant for the curve, with the same coefficients as given by \kbd{ellfromj}. \item a character string in Cremona's notation, e.g. \kbd{"11a1"}, in which case the curve is retrieved from the \tet{elldata} database if available. The optional argument $D$ describes the domain over which the curve is defined: \item the \typ{INT} $1$ (default): the field of rational numbers $\Q$. \item a \typ{INT} $p$, where $p$ is a prime number: the prime finite field $\F_{p}$. \item an \typ{INTMOD} \kbd{Mod(a, p)}, where $p$ is a prime number: the prime finite field $\F_{p}$. \item a \typ{FFELT}, as returned by \tet{ffgen}: the corresponding finite field $\F_{q}$. \item a \typ{PADIC}, $O(p^{n})$: the field $\Q_{p}$, where $p$-adic quantities will be computed to a relative accuracy of $n$ digits. We advise to input a model defined over $\Q$ for such curves. In any case, if you input an approximate model with \typ{PADIC} coefficients, it will be replaced by a lift to $\Q$ (an exact model ``close'' to the one that was input) and all quantities will then be computed in terms of this lifted model, at the given accuracy. \item a \typ{REAL} $x$: the field $\C$ of complex numbers, where floating point quantities are by default computed to a relative accuracy of \kbd{precision}$(x)$. If no such argument is given, the value of \kbd{realprecision} at the time \kbd{ellinit} is called will be used. \item a number field $K$, given by a \kbd{nf} or \kbd{bnf} structure; a \kbd{bnf} is required for \kbd{ellminimalmodel}. \item a prime ideal $\goth{p}$, given by a \kbd{prid} structure; valid if $x$ is a curve defined over a number field $K$ and the equation is integral and minimal at $\goth{p}$. This argument $D$ is indicative: the curve coefficients are checked for compatibility, possibly changing $D$; for instance if $D = 1$ and an \typ{INTMOD} is found. If inconsistencies are detected, an error is raised: \bprog ? ellinit([1 + O(5), 1], O(7)); *** at top-level: ellinit([1+O(5),1],O *** ^-------------------- *** ellinit: inconsistent moduli in ellinit: 7 != 5 @eprog\noindent If the curve coefficients are too general to fit any of the above domain categories, only basic operations, such as point addition, will be supported later. If the curve (seen over the domain $D$) is singular, fail and return an empty vector $[]$. \bprog ? E = ellinit([0,0,0,0,1]); \\ y^2 = x^3 + 1, over Q ? E = ellinit([0,1]); \\ the same curve, short form ? E = ellinit("36a1"); \\ sill the same curve, Cremona's notations ? E = ellinit([0]); \\ a curve of j-invariant 0 ? E = ellinit([0,1], 2) \\ over F2: singular curve %4 = [] ? E = ellinit(['a4,'a6] * Mod(1,5)); \\ over F_5[a4,a6], basic support ! @eprog\noindent Note that the given curve of $j$-invariant $0$ happens to be \kbd{36a1} but a priori any model for an arbitrary twist could have been returned. See \kbd{ellfromj}. The result of \tet{ellinit} is an \tev{ell} structure. It contains at least the following information in its components: % $$ a_{1},a_{2},a_{3},a_{4},a_{6},b_{2},b_{4},b_{6},b_{8},c_{4},c_{6}, \Delta,j.$$ % All are accessible via member functions. In particular, the discriminant is \kbd{$E$.disc}, and the $j$-invariant is \kbd{$E$.j}. \bprog ? E = ellinit([a4, a6]); ? E.disc %2 = -64*a4^3 - 432*a6^2 ? E.j %3 = -6912*a4^3/(-4*a4^3 - 27*a6^2) @eprog Further components contain domain-specific data, which are in general dynamic: only computed when needed, and then cached in the structure. \bprog ? E = ellinit([2,3], 10^60+7); \\ E over F_p, p large ? ellap(E) time = 4,440 ms. %2 = -1376268269510579884904540406082 ? ellcard(E); \\ now instantaneous ! time = 0 ms. ? ellgenerators(E); time = 5,965 ms. ? ellgenerators(E); \\ second time instantaneous time = 0 ms. @eprog See the description of member functions related to elliptic curves at the beginning of this section. The library syntax is \fun{GEN}{ellinit}{GEN x, GEN D = NULL, long prec}. \subsec{ellintegralmodel$(E,\{\&v\})$}\kbdsidx{ellintegralmodel}\label{se:ellintegralmodel} Let $E$ be an \kbd{ell} structure over a number field $K$ or $\Q_{p}$. This function returns an integral model. If $v$ is present, sets $v = [u,0,0,0]$ to the corresponding change of variable: the return value is identical to that of \kbd{ellchangecurve(E, v)}. \bprog ? e = ellinit([1/17,1/42]); ? e = ellintegralmodel(e,&v); ? e[1..5] %3 = [0, 0, 0, 15287762448, 3154568630095008] ? v %4 = [1/714, 0, 0, 0] @eprog The library syntax is \fun{GEN}{ellintegralmodel}{GEN E, GEN *v = NULL}. \subsec{elliscm$(E)$}\kbdsidx{elliscm}\label{se:elliscm} Let $E$ an elliptic curve over a number field. Return $0$ if $E$ is not CM, otherwise return the discriminant of its endomorphism ring. \bprog ? E = ellinit([0,0,-5,-750,7900]); ? D = elliscm(E) %2 = -27 ? w = quadgen(D, 'w); ? P = ellheegner(E) %4 = [10,40] ? Q = ellmul(E,P,w) %5 = [110/7-5/49*w,85/49-225/343*w] @eprog An example over a number field: \bprog ? nf=nfinit(a^2-5); ? E = ellinit([261526980*a-584793000,-3440201839360*a+7692525148000],nf); ? elliscm(E) %3 = -20 ? ellisomat(E)[2] %4 = [1,2,5,10;2,1,10,5;5,10,1,2;10,5,2,1] @eprog The library syntax is \fun{long}{elliscm}{GEN E}. \subsec{ellisdivisible$(E,P,n,\{\&Q\})$}\kbdsidx{ellisdivisible}\label{se:ellisdivisible} Given $E/K$ a number field and $P$ in $E(K)$ return $1$ if $P = [n]R$ for some $R$ in $E(K)$ and set $Q$ to one such $R$; and return $0$ otherwise. \bprog ? K = nfinit(polcyclo(11,t)); ? E = ellinit([0,-1,1,0,0], K); ? P = [0,0]; ? ellorder(E,P) %4 = 5 ? ellisdivisible(E,P,5, &Q) %5 = 1 ? lift(Q) %6 = [-t^7-t^6-t^5-t^4+1, -t^9-2*t^8-2*t^7-3*t^6-3*t^5-2*t^4-2*t^3-t^2-1] ? ellorder(E, Q) %7 = 25 @eprog\noindent We use a fast multimodular algorithm over $\Q$ whose complexity is essentially independent of $n$ (polynomial in $\log n$). Over number fields, we compute roots of division polynomials and the algebraic complexity of the underlying algorithm is in $O(p^{4})$, where $p$ is the largest prime divisor of $n$. The integer $n \geq 0$ may be given as \kbd{ellxn(E,n)}, if many points need to be tested; this provides a modest speedup over number fields but is likely to slow down the algorithm over $\Q$. The library syntax is \fun{long}{ellisdivisible}{GEN E, GEN P, GEN n, GEN *Q = NULL}. \subsec{ellisisom$(E,F)$}\kbdsidx{ellisisom}\label{se:ellisisom} Return $0$ if the elliptic curves $E$ and $F$ defined over the same number field are not isomorphic, otherwise return \kbd{[u,r,s,t]} suitable for \kbd{ellchangecurve}, mapping $E$ to $F$. \bprog ? E = ellinit([1,2]); ? ellisisom(E, ellinit([1,3])) %2 = 0 ? F = ellchangecurve(E, [-1,1,3,2]); ? ellisisom(E,F) %4 = [1, 1, -3, -2] @eprog \bprog ? nf = nfinit(a^3-2); E = ellinit([a^2+1,2*a-5], nf); ? F = ellchangecurve(E,Mod([a, a+1, a^2, a^2+a-3], nf.pol)); ? v = ellisisom(E,F) %3 = [Mod(-a, a^3 - 2), Mod(a + 1, a^3 - 2), Mod(-a^2, a^3 - 2), Mod(-a^2 - a + 3, a^3 - 2)] ? ellchangecurve(E,v) == F %4 = 1 @eprog The library syntax is \fun{GEN}{ellisisom}{GEN E, GEN F}. \subsec{ellisogeny$(E,G,\{\var{only\_image}=0\},\{x='x\},\{y='y\})$}\kbdsidx{ellisogeny}\label{se:ellisogeny} Given an elliptic curve $E$, a finite subgroup $G$ of $E$ is given either as a generating point $P$ (for a cyclic $G$) or as a polynomial whose roots vanish on the $x$-coordinates of the nonzero elements of $G$ (general case and more efficient if available). This function returns the $[a_{1},a_{2},a_{3},a_{4},a_{6}]$ invariants of the quotient elliptic curve $E/G$ and (if \var{only\_image} is zero (the default)) a vector of rational functions $[f, g, h]$ such that the isogeny $E \to E/G$ is given by $(x,y) \mapsto (f(x)/h(x)^{2}, g(x,y)/h(x)^{3})$. \bprog ? E = ellinit([0,1]); ? elltors(E) %2 = [6, [6], [[2, 3]]] ? ellisogeny(E, [2,3], 1) \\ Weierstrass model for E/

%3 = [0, 0, 0, -135, -594] ? ellisogeny(E,[-1,0]) %4 = [[0,0,0,-15,22], [x^3+2*x^2+4*x+3, y*x^3+3*y*x^2-2*y, x+1]] @eprog The library syntax is \fun{GEN}{ellisogeny}{GEN E, GEN G, long only_image, long x = -1, long y = -1} where \kbd{x}, \kbd{y} are variable numbers. \subsec{ellisogenyapply$(f,g)$}\kbdsidx{ellisogenyapply}\label{se:ellisogenyapply} Given an isogeny of elliptic curves $f:E'\to E$ (being the result of a call to \tet{ellisogeny}), apply $f$ to $g$: \item if $g$ is a point $P$ in the domain of $f$, return the image $f(P)$; \item if $g:E''\to E'$ is a compatible isogeny, return the composite isogeny $f \circ g: E''\to E$. \bprog ? one = ffgen(101, 't)^0; ? E = ellinit([6, 53, 85, 32, 34] * one); ? P = [84, 71] * one; ? ellorder(E, P) %4 = 5 ? [F, f] = ellisogeny(E, P); \\ f: E->F = E/

? ellisogenyapply(f, P) %6 = [0] ? F = ellinit(F); ? Q = [89, 44] * one; ? ellorder(F, Q) %9 = 2 ? [G, g] = ellisogeny(F, Q); \\ g: F->G = F/ ? gof = ellisogenyapply(g, f); \\ gof: E -> G @eprog The library syntax is \fun{GEN}{ellisogenyapply}{GEN f, GEN g}. \subsec{ellisomat$(E,\{p=0\},\{\fl=0\})$}\kbdsidx{ellisomat}\label{se:ellisomat} Given an elliptic curve $E$ defined over a number field~$K$, computes representatives of the set of isomorphism classes of elliptic curves defined over~$K$ and $K$-isogenous to $E$, assuming it is finite (see below). For any such curve $E_{i}$, let $f_{i}: E \to E_{i}$ be a rational isogeny of minimal degree and let $g_{i}: E_{i} \to E$ be the dual isogeny; and let $M$ be the matrix such that $M_{i,j}$ is the minimal degree for an isogeny $E_{i} \to E_{j}$. The function returns a vector $[L,M]$ where $L$ is a list of triples $[E_{i}, f_{i}, g_{i}]$ ($\fl = 0$), or simply the list of $E_{i}$ ($\fl = 1$, which saves time). The curves $E_{i}$ are given in $[a_{4},a_{6}]$ form and the first curve $E_{1}$ is isomorphic to $E$ by $f_{1}$. The set of isomorphism classes is finite except when $E$ has CM over a quadratic order contained in $K$. In that case the function only returns the discriminant of the quadratic order. If $p$ is set, it must be a prime number; in this which case only isogenies of degree a power of $p$ are considered. Over a number field, the possible isogeny degrees are determined by Billerey's algorithm. \bprog ? E = ellinit("14a1"); ? [L,M] = ellisomat(E); ? LE = apply(x->x[1], L) \\ list of curves %3 = [[215/48,-5291/864],[-675/16,6831/32],[-8185/48,-742643/864], [-1705/48,-57707/864],[-13635/16,306207/32],[-131065/48,-47449331/864]] ? L[2][2] \\ isogeny f_2 %4 = [x^3+3/4*x^2+19/2*x-311/12, 1/2*x^4+(y+1)*x^3+(y-4)*x^2+(-9*y+23)*x+(55*y+55/2),x+1/3] ? L[2][3] \\ dual isogeny g_2 %5 = [1/9*x^3-1/4*x^2-141/16*x+5613/64, -1/18*x^4+(1/27*y-1/3)*x^3+(-1/12*y+87/16)*x^2+(49/16*y-48)*x +(-3601/64*y+16947/512),x-3/4] ? apply(E->ellidentify(ellinit(E))[1][1], LE) %6 = ["14a1","14a4","14a3","14a2","14a6","14a5"] ? M %7 = [1 3 3 2 6 6] [3 1 9 6 2 18] [3 9 1 6 18 2] [2 6 6 1 3 3] [6 2 18 3 1 9] [6 18 2 3 9 1] @eprog The library syntax is \fun{GEN}{ellisomat}{GEN E, long p, long flag}. \subsec{ellisoncurve$(E,z)$}\kbdsidx{ellisoncurve}\label{se:ellisoncurve} Gives 1 (i.e.~true) if the point $z$ is on the elliptic curve $E$, 0 otherwise. If $E$ or $z$ have imprecise coefficients, an attempt is made to take this into account, i.e.~an imprecise equality is checked, not a precise one. It is allowed for $z$ to be a vector of points in which case a vector (of the same type) is returned. The library syntax is \fun{GEN}{ellisoncurve}{GEN E, GEN z}. Also available is \fun{int}{oncurve}{GEN E, GEN z} which does not accept vectors of points. \subsec{ellisotree$(E)$}\kbdsidx{ellisotree}\label{se:ellisotree} Given an elliptic curve $E$ defined over $\Q$ or a set of $\Q$-isogenous curves as given by \kbd{ellisomat}, return a pair $[L,M]$ where \item $L$ lists the minimal models of the isomorphism classes of elliptic curves $\Q$-isogenous to $E$ (or in the set of isogenous curves), \item $M$ is the adjacency matrix of the prime degree isogenies tree: there is an edge from $E_{i}$ to $E_{j}$ if there is an isogeny $E_{i} \to E_{j}$ of prime degree such that the N\'eron differential forms are preserved. \bprog ? E = ellinit("14a1"); ? [L,M] = ellisotree(E); ? M %3 = [0 0 3 2 0 0] [3 0 0 0 2 0] [0 0 0 0 0 2] [0 0 0 0 0 3] [0 0 0 3 0 0] [0 0 0 0 0 0] ? [L2,M2] = ellisotree(ellisomat(E,2,1)); %4 = [0 2] [0 0] ? [L3,M3] = ellisotree(ellisomat(E,3,1)); ? M3 %6 = [0 0 3] [3 0 0] [0 0 0] @eprog\noindent Compare with the result of \kbd{ellisomat}. \bprog ? [L,M]=ellisomat(E,,1); ? M %7 = [1 3 3 2 6 6] [3 1 9 6 2 18] [3 9 1 6 18 2] [2 6 6 1 3 3] [6 2 18 3 1 9] [6 18 2 3 9 1] @eprog The library syntax is \fun{GEN}{ellisotree}{GEN E}. \subsec{ellissupersingular$(E,\{p\})$}\kbdsidx{ellissupersingular}\label{se:ellissupersingular} Return 1 if the elliptic curve $E$ defined over a number field, $\Q_{p}$ or a finite field is supersingular at $p$, and $0$ otherwise. If the curve is defined over $\Q$ or a number field, $p$ must be explicitly given, and must be a prime number, resp.~a maximal ideal; we return $1$ if and only if $E$ has supersingular good reduction at $p$. Alternatively, $E$ can be given by its $j$-invariant in a finite field. In this case $p$ must be omitted. \bprog ? g = ffprimroot(ffgen(7^5)) %1 = 4*x^4+5*x^3+6*x^2+5*x+6 ? [g^n | n <- [1 .. 7^5 - 1], ellissupersingular(g^n)] %2 = [6] ? j = ellsupersingularj(2^31-1) %3 = 1618591527*w+1497042960 ? ellissupersingular(j) %4 = 1 ? K = nfinit(y^3-2); P = idealprimedec(K, 2)[1]; ? E = ellinit([y,1], K); ? ellissupersingular(E, P) %7 = 1 ? Q = idealprimedec(K,5)[1]; ? ellissupersingular(E, Q) %9 = 0 @eprog The library syntax is \fun{int}{ellissupersingular}{GEN E, GEN p = NULL}. Also available is \fun{int}{elljissupersingular}{GEN j} where $j$ is a $j$-invariant of a curve over a finite field. \subsec{ellj$(x)$}\kbdsidx{ellj}\label{se:ellj} Elliptic $j$-invariant. $x$ must be a complex number with positive imaginary part, or convertible into a power series or a $p$-adic number with positive valuation. The library syntax is \fun{GEN}{jell}{GEN x, long prec}. \subsec{elllocalred$(E,\{p\})$}\kbdsidx{elllocalred}\label{se:elllocalred} Calculates the \idx{Kodaira} type of the local fiber of the elliptic curve $E$ at $p$. $E$ must be an \kbd{ell} structure as output by \kbd{ellinit}, over $\Q_{\ell}$ ($p$ better left omitted, else equal to $\ell$) over $\Q$ ($p$ a rational prime) or a number field $K$ ($p$ a maximal ideal given by a \kbd{prid} structure). The result is a 4-component vector $[f,kod,v,c]$. Here $f$ is the exponent of $p$ in the arithmetic conductor of $E$, and $kod$ is the Kodaira type which is coded as follows: 1 means good reduction (type I$_{0}$), 2, 3 and 4 mean types II, III and IV respectively, $4+\nu$ with $\nu>0$ means type I$_{\nu}$; finally the opposite values $-1$, $-2$, etc.~refer to the starred types I$_{0}^{*}$, II$^{*}$, etc. The third component $v$ is itself a vector $[u,r,s,t]$ giving the coordinate changes done during the local reduction; $u = 1$ if and only if the given equation was already minimal at $p$. Finally, the last component $c$ is the local \idx{Tamagawa number} $c_{p}$. The library syntax is \fun{GEN}{elllocalred}{GEN E, GEN p = NULL}. \subsec{elllog$(E,P,G,\{o\})$}\kbdsidx{elllog}\label{se:elllog} Given two points $P$ and $G$ on the elliptic curve $E/\F_{q}$, returns the discrete logarithm of $P$ in base $G$, i.e. the smallest nonnegative integer $n$ such that $P = [n]G$. See \tet{znlog} for the limitations of the underlying discrete log algorithms. If present, $o$ represents the order of $G$, see \secref{se:DLfun}; the preferred format for this parameter is \kbd{[N, factor(N)]}, where $N$ is the order of $G$. If no $o$ is given, assume that $G$ generates the curve. The function also assumes that $P$ is a multiple of $G$. \bprog ? a = ffgen(ffinit(2,8),'a); ? E = ellinit([a,1,0,0,1]); \\ over F_{2^8} ? x = a^3; y = ellordinate(E,x)[1]; ? P = [x,y]; G = ellmul(E, P, 113); ? ord = [242, factor(242)]; \\ P generates a group of order 242. Initialize. ? ellorder(E, G, ord) %4 = 242 ? e = elllog(E, P, G, ord) %5 = 15 ? ellmul(E,G,e) == P %6 = 1 @eprog The library syntax is \fun{GEN}{elllog}{GEN E, GEN P, GEN G, GEN o = NULL}. \subsec{elllseries$(E,s,\{A=1\})$}\kbdsidx{elllseries}\label{se:elllseries} This function is deprecated, use \kbd{lfun(E,s)} instead. $E$ being an elliptic curve, given by an arbitrary model over $\Q$ as output by \kbd{ellinit}, this function computes the value of the $L$-series of $E$ at the (complex) point $s$. This function uses an $O(N^{1/2})$ algorithm, where $N$ is the conductor. The optional parameter $A$ fixes a cutoff point for the integral and is best left omitted; the result must be independent of $A$, up to \kbd{realprecision}, so this allows to check the function's accuracy. The library syntax is \fun{GEN}{elllseries}{GEN E, GEN s, GEN A = NULL, long prec}. \subsec{ellmaninconstant$(E)$}\kbdsidx{ellmaninconstant}\label{se:ellmaninconstant} Let $E$ be an elliptic curve over $Q$ given by \kbd{ellinit} or a rational isogeny class given by ellisomat. Return the Manin constant of the curve, see \kbd{ellweilcurve}. The algorithm is slow but unconditional. The function also accepts the output of \kbd{ellisomat} and returns the list of Manin constants for all the isogeny class. \bprog ? E = ellinit("11a3"); ? ellmaninconstant(E) %2 = 5 ? L=ellisomat(E,,1); ? ellmaninconstant(L) %4 = [5,1,1] @eprog The library syntax is \fun{GEN}{ellmaninconstant}{GEN E}. \subsec{ellminimaldisc$(E)$}\kbdsidx{ellminimaldisc}\label{se:ellminimaldisc} $E$ being an elliptic curve defined over a number field output by \kbd{ellinit}, return the minimal discriminant ideal of E. The library syntax is \fun{GEN}{ellminimaldisc}{GEN E}. \subsec{ellminimalmodel$(E,\{\&v\})$}\kbdsidx{ellminimalmodel}\label{se:ellminimalmodel} Let $E$ be an \kbd{ell} structure over a number field $K$. This function determines whether $E$ admits a global minimal integral model. If so, it returns it and sets $v = [u,r,s,t]$ to the corresponding change of variable: the return value is identical to that of \kbd{ellchangecurve(E, v)}. Else return the (nonprincipal) Weierstrass class of $E$, i.e. the class of $\prod \goth{p}^{(v_{\goth{p}}{\Delta} - \delta_{\goth{p}}) / 12}$ where $\Delta = \kbd{E.disc}$ is the model's discriminant and $\goth{p}^{\delta_{\goth{p}}}$ is the local minimal discriminant. This function requires either that $E$ be defined over the rational field $\Q$ (with domain $D = 1$ in \kbd{ellinit}), in which case a global minimal model always exists, or over a number field given by a \var{bnf} structure. The Weierstrass class is given in \kbd{bnfisprincipal} format, i.e. in terms of the \kbd{K.gen} generators. The resulting model has integral coefficients and is everywhere minimal, the coefficients $a_{1}$ and $a_{3}$ are reduced modulo $2$ (in terms of the fixed integral basis \kbd{K.zk}) and $a_{2}$ is reduced modulo $3$. Over $\Q$, we further require that $a_{1}$ and $a_{3}$ be $0$ or $1$, that $a_{2}$ be $0$ or $\pm 1$ and that $u > 0$ in the change of variable: both the model and the change of variable $v$ are then unique.\sidx{minimal model} \bprog ? e = ellinit([6,6,12,55,233]); \\ over Q ? E = ellminimalmodel(e, &v); ? E[1..5] %3 = [0, 0, 0, 1, 1] ? v %4 = [2, -5, -3, 9] @eprog \bprog ? K = bnfinit(a^2-65); \\ over a nonprincipal number field ? K.cyc %2 = [2] ? u = Mod(8+a, K.pol); ? E = ellinit([1,40*u+1,0,25*u^2,0], K); ? ellminimalmodel(E) \\ no global minimal model exists over Z_K %6 = [1]~ @eprog The library syntax is \fun{GEN}{ellminimalmodel}{GEN E, GEN *v = NULL}. \subsec{ellminimaltwist$(E,\{\fl=0\})$}\kbdsidx{ellminimaltwist}\label{se:ellminimaltwist} Let $E$ be an elliptic curve defined over $\Q$, return a discriminant $D$ such that the twist of $E$ by $D$ is minimal among all possible quadratic twists, i.e. if $\fl=0$, its minimal model has minimal discriminant, or if $\fl=1$, it has minimal conductor. In the example below, we find a curve with $j$-invariant $3$ and minimal conductor. \bprog ? E = ellminimalmodel(ellinit(ellfromj(3))); ? ellglobalred(E)[1] %2 = 357075 ? D = ellminimaltwist(E,1) %3 = -15 ? E2 = ellminimalmodel(elltwist(E,D)); ? ellglobalred(E2)[1] %5 = 14283 @eprog In the example below, $\fl=0$ and $\fl=1$ give different results. \bprog ? E = ellinit([1,0]); ? D0 = ellminimaltwist(E,0) %7 = 1 ? D1 = ellminimaltwist(E,1) %8 = 8 ? E0 = ellminimalmodel(elltwist(E,D0)); ? [E0.disc, ellglobalred(E0)[1]] %10 = [-64, 64] ? E1 = ellminimalmodel(elltwist(E,D1)); ? [E1.disc, ellglobalred(E1)[1]] %12 = [-4096, 32] @eprog The library syntax is \fun{GEN}{ellminimaltwist0}{GEN E, long flag}. Also available are \fun{GEN}{ellminimaltwist}{E} for $\fl=0$, and \fun{GEN}{ellminimaltwistcond}{E} for $\fl=1$. \subsec{ellmoddegree$(e)$}\kbdsidx{ellmoddegree}\label{se:ellmoddegree} $e$ being an elliptic curve defined over $\Q$ output by \kbd{ellinit}, compute the modular degree of $e$ divided by the square of the Manin constant $c$. It is conjectured that $c = 1$ for the strong Weil curve in the isogeny class (optimal quotient of $J_{0}(N)$) and this can be proven using \kbd{ellweilcurve} when the conductor $N$ is moderate. \bprog ? E = ellinit("11a1"); \\ from Cremona table: strong Weil curve and c = 1 ? [v,smith] = ellweilcurve(E); smith \\ proof of the above %2 = [[1, 1], [5, 1], [1, 1/5]] ? ellmoddegree(E) %3 = 1 ? [ellidentify(e)[1][1] | e<-v] %4 = ["11a1", "11a2", "11a3"] ? ellmoddegree(ellinit("11a2")) %5 = 5 ? ellmoddegree(ellinit("11a3")) %6 = 1/5 @eprog\noindent The modular degree of \kbd{11a1} is $1$ (because \kbd{ellweilcurve} or Cremona's table prove that the Manin constant is $1$ for this curve); the output of \kbd{ellweilcurve} also proves that the Manin constants of \kbd{11a2} and \kbd{11a3} are 1 and 5 respectively, so the actual modular degree of both \kbd{11a2} and \kbd{11a3} is 5. The library syntax is \fun{GEN}{ellmoddegree}{GEN e}. \subsec{ellmodulareqn$(N,\{x\},\{y\})$}\kbdsidx{ellmodulareqn}\label{se:ellmodulareqn} Given a prime $N < 500$, return a vector $[P,t]$ where $P(x,y)$ is a modular equation of level $N$, i.e.~a bivariate polynomial with integer coefficients; $t$ indicates the type of this equation: either \emph{canonical} ($t = 0$) or \emph{Atkin} ($t = 1$). This function requires the \kbd{seadata} package and its only use is to give access to the package contents. See \tet{polmodular} for a more general and more flexible function. Let $j$ be the $j$-invariant function. The polynomial $P$ satisfies the functional equation, $$ P(f,j) = P(f \mid W_{N}, j \mid W_{N}) = 0 $$ for some modular function $f = f_{N}$ (hand-picked for each fixed $N$ to minimize its size, see below), where $W_{N}(\tau) = -1 / (N\*\tau)$ is the Atkin-Lehner involution. These two equations allow to compute the values of the classical modular polynomial $\Phi_{N}$, such that $\Phi_{N}(j(\tau), j(N\tau)) = 0$, while being much smaller than the latter. More precisely, we have $j(W_{N}(\tau)) = j(N\*\tau)$; the function $f$ is invariant under $\Gamma_{0}(N)$ and also satisfies \item for Atkin type: $f \mid W_{N} = f$; \item for canonical type: let $s = 12/\gcd(12,N-1)$, then $f \mid W_{N} = N^{s} / f$. In this case, $f$ has a simple definition: $f(\tau) = N^{s} \* \big(\eta(N\*\tau) / \eta(\tau) \big)^{2\*s}$, where $\eta$ is Dedekind's eta function. The following GP function returns values of the classical modular polynomial by eliminating $f_{N}(\tau)$ in the above functional equation, for $N\leq 31$ or $N\in\{41,47,59,71\}$. \bprog classicaleqn(N, X='X, Y='Y)= { my([P,t] = ellmodulareqn(N), Q, d); if (poldegree(P,'y) > 2, error("level unavailable in classicaleqn")); if (t == 0, \\ Canonical my(s = 12/gcd(12,N-1)); Q = 'x^(N+1) * substvec(P,['x,'y],[N^s/'x,Y]); d = N^(s*(2*N+1)) * (-1)^(N+1); , \\ Atkin Q = subst(P,'y,Y); d = (X-Y)^(N+1)); polresultant(subst(P,'y,X), Q) / d; } @eprog The library syntax is \fun{GEN}{ellmodulareqn}{long N, long x = -1, long y = -1} where \kbd{x}, \kbd{y} are variable numbers. \subsec{ellmul$(E,z,n)$}\kbdsidx{ellmul}\label{se:ellmul} Computes $[n]z$, where $z$ is a point on the elliptic curve $E$. The exponent $n$ is in $\Z$, or may be a complex quadratic integer if the curve $E$ has complex multiplication by $n$ (if not, an error message is issued). \bprog ? Ei = ellinit([1,0]); z = [0,0]; ? ellmul(Ei, z, 10) %2 = [0] \\ unsurprising: z has order 2 ? ellmul(Ei, z, I) %3 = [0, 0] \\ Ei has complex multiplication by Z[i] ? ellmul(Ei, z, quadgen(-4)) %4 = [0, 0] \\ an alternative syntax for the same query ? Ej = ellinit([0,1]); z = [-1,0]; ? ellmul(Ej, z, I) *** at top-level: ellmul(Ej,z,I) *** ^-------------- *** ellmul: not a complex multiplication in ellmul. ? ellmul(Ej, z, 1+quadgen(-3)) %6 = [1 - w, 0] @eprog The simple-minded algorithm for the CM case assumes that we are in characteristic $0$, and that the quadratic order to which $n$ belongs has small discriminant. The library syntax is \fun{GEN}{ellmul}{GEN E, GEN z, GEN n}. \subsec{ellneg$(E,z)$}\kbdsidx{ellneg}\label{se:ellneg} Opposite of the point $z$ on elliptic curve $E$. The library syntax is \fun{GEN}{ellneg}{GEN E, GEN z}. \subsec{ellnonsingularmultiple$(E,P)$}\kbdsidx{ellnonsingularmultiple}\label{se:ellnonsingularmultiple} Given an elliptic curve $E/\Q$ (more precisely, a model defined over $\Q$ of a curve) and a rational point $P \in E(\Q)$, returns the pair $[R,n]$, where $n$ is the least positive integer such that $R := [n]P$ has good reduction at every prime. More precisely, its image in a minimal model is everywhere nonsingular. \bprog ? e = ellinit("57a1"); P = [2,-2]; ? ellnonsingularmultiple(e, P) %2 = [[1, -1], 2] ? e = ellinit("396b2"); P = [35, -198]; ? [R,n] = ellnonsingularmultiple(e, P); ? n %5 = 12 @eprog The library syntax is \fun{GEN}{ellnonsingularmultiple}{GEN E, GEN P}. \subsec{ellorder$(E,z,\{o\})$}\kbdsidx{ellorder}\label{se:ellorder} Gives the order of the point $z$ on the elliptic curve $E$, defined over a finite field or a number field. Return (the impossible value) zero if the point has infinite order. \bprog ? E = ellinit([-157^2,0]); \\ the "157-is-congruent" curve ? P = [2,2]; ellorder(E, P) %2 = 2 ? P = ellheegner(E); ellorder(E, P) \\ infinite order %3 = 0 ? K = nfinit(polcyclo(11,t)); E=ellinit("11a3", K); T = elltors(E); ? ellorder(E, T.gen[1]) %5 = 25 ? E = ellinit(ellfromj(ffgen(5^10))); ? ellcard(E) %7 = 9762580 ? P = random(E); ellorder(E, P) %8 = 4881290 ? p = 2^160+7; E = ellinit([1,2], p); ? N = ellcard(E) %9 = 1461501637330902918203686560289225285992592471152 ? o = [N, factor(N)]; ? for(i=1,100, ellorder(E,random(E))) time = 260 ms. @eprog The parameter $o$, is now mostly useless, and kept for backward compatibility. If present, it represents a nonzero multiple of the order of $z$, see \secref{se:DLfun}; the preferred format for this parameter is \kbd{[ord, factor(ord)]}, where \kbd{ord} is the cardinality of the curve. It is no longer needed since PARI is now able to compute it over large finite fields (was restricted to small prime fields at the time this feature was introduced), \emph{and} caches the result in $E$ so that it is computed and factored only once. Modifying the last example, we see that including this extra parameter provides no improvement: \bprog ? o = [N, factor(N)]; ? for(i=1,100, ellorder(E,random(E),o)) time = 260 ms. @eprog The library syntax is \fun{GEN}{ellorder}{GEN E, GEN z, GEN o = NULL}. The obsolete form \fun{GEN}{orderell}{GEN e, GEN z} should no longer be used. \subsec{ellordinate$(E,x)$}\kbdsidx{ellordinate}\label{se:ellordinate} Gives a 0, 1 or 2-component vector containing the $y$-coordinates of the points of the curve $E$ having $x$ as $x$-coordinate. The library syntax is \fun{GEN}{ellordinate}{GEN E, GEN x, long prec}. \subsec{ellpadicL$(E,p,n,\{s=0\},\{r=0\},\{D=1\})$}\kbdsidx{ellpadicL}\label{se:ellpadicL} Returns the value (or $r$-th derivative) on a character $\chi^{s}$ of $\Z_{p}^{*}$ of the $p$-adic $L$-function of the elliptic curve $E/\Q$, twisted by $D$, given modulo $p^{n}$. \misctitle{Characters} The set of continuous characters of $\text{Gal}(\Q(\mu_{p^{\infty}})/ \Q)$ is identified to $\Z_{p}^{*}$ via the cyclotomic character $\chi$ with values in $\overline{\Q_{p}}^{*}$. Denote by $\tau:\Z_{p}^{*}\to\Z_{p}^{*}$ the Teichm\"uller character, with values in the $(p-1)$-th roots of $1$ for $p\neq 2$, and $\{-1,1\}$ for $p = 2$; finally, let $\langle\chi\rangle =\chi \tau^{-1}$, with values in $1 + 2p\Z_{p}$. In GP, the continuous character of $\text{Gal}(\Q(\mu_{p^{\infty}})/ \Q)$ given by $\langle\chi\rangle^{s_{1}} \tau^{s_{2}}$ is represented by the pair of integers $s=(s_{1},s_{2})$, with $s_{1} \in \Z_{p}$ and $s_{2} \bmod p-1$ for $p > 2$, (resp. mod $2$ for $p = 2$); $s$ may be also an integer, representing $(s,s)$ or $\chi^{s}$. \misctitle{The $p$-adic $L$ function} The $p$-adic $L$ function $L_{p}$ is defined on the set of continuous characters of $\text{Gal}(\Q(\mu_{p^{\infty}})/ \Q)$, as $\int_{\Z_{p}^{*}} \chi^{s} d \mu$ for a certain $p$-adic distribution $\mu$ on $\Z_{p}^{*}$. The derivative is given by $$L_{p}^{(r)}(E, \chi^{s}) = \int_{\Z_{p}^{*}} \log_{p}^{r}(a) \chi^{s}(a) d\mu(a).$$ More precisely: \item When $E$ has good supersingular reduction, $L_{p}$ takes its values in $D := H^{1}_{dR}(E/\Q)\otimes_{\Q} \Q_{p}$ and satisfies $$(1-p^{-1} F)^{-2} L_{p}(E, \chi^{0})= (L(E,1) / \Omega) \cdot \omega$$ where $F$ is the Frobenius, $L(E,1)$ is the value of the complex $L$ function at $1$, $\omega$ is the N\'eron differential and $\Omega$ the attached period on $E(\R)$. Here, $\chi^{0}$ represents the trivial character. The function returns the components of $L_{p}^{(r)}(E,\chi^{s})$ in the basis $(\omega, F \omega)$. \item When $E$ has ordinary good reduction, this method only defines the projection of $L_{p}(E,\chi^{s})$ on the $\alpha$-eigenspace, where $\alpha$ is the unit eigenvalue for $F$. This is what the function returns. We have $$(1- \alpha^{-1})^{-2} L_{p,\alpha}(E,\chi^{0})= L(E,1) / \Omega.$$ Two supersingular examples: \bprog ? cxL(e) = bestappr( ellL1(e) / e.omega[1] ); ? e = ellinit("17a1"); p=3; \\ supersingular, a3 = 0 ? L = ellpadicL(e,p,4); ? F = [0,-p;1,ellap(e,p)]; \\ Frobenius matrix in the basis (omega,F(omega)) ? (1-p^(-1)*F)^-2 * L / cxL(e) %5 = [1 + O(3^5), O(3^5)]~ \\ [1,0]~ ? e = ellinit("116a1"); p=3; \\ supersingular, a3 != 0~ ? L = ellpadicL(e,p,4); ? F = [0,-p; 1,ellap(e,p)]; ? (1-p^(-1)*F)^-2*L~ / cxL(e) %9 = [1 + O(3^4), O(3^5)]~ @eprog Good ordinary reduction: \bprog ? e = ellinit("17a1"); p=5; ap = ellap(e,p) %1 = -2 \\ ordinary ? L = ellpadicL(e,p,4) %2 = 4 + 3*5 + 4*5^2 + 2*5^3 + O(5^4) ? al = padicappr(x^2 - ap*x + p, ap + O(p^7))[1]; ? (1-al^(-1))^(-2) * L / cxL(e) %4 = 1 + O(5^4) @eprog Twist and Teichm\"uller: \bprog ? e = ellinit("17a1"); p=5; \\ ordinary \\ 2nd derivative at tau^1, twist by -7 ? ellpadicL(e, p, 4, [0,1], 2, -7) %2 = 2*5^2 + 5^3 + O(5^4) @eprog We give an example of non split multiplicative reduction (see \tet{ellpadicbsd} for more examples). \bprog ? e=ellinit("15a1"); p=3; n=5; ? L = ellpadicL(e,p,n) %2 = 2 + 3 + 3^2 + 3^3 + 3^4 + O(3^5) ? (1 - ellap(e,p))^(-1) * L / cxL(e) %3 = 1 + O(3^5) @eprog This function is a special case of \tet{mspadicL} and it also appears as the first term of \tet{mspadicseries}: \bprog ? e = ellinit("17a1"); p=5; ? L = ellpadicL(e,p,4) %2 = 4 + 3*5 + 4*5^2 + 2*5^3 + O(5^4) ? [M,phi] = msfromell(e, 1); ? Mp = mspadicinit(M, p, 4); ? mu = mspadicmoments(Mp, phi); ? mspadicL(mu) %6 = 4 + 3*5 + 4*5^2 + 2*5^3 + 2*5^4 + 5^5 + O(5^6) ? mspadicseries(mu) %7 = (4 + 3*5 + 4*5^2 + 2*5^3 + 2*5^4 + 5^5 + O(5^6)) + (3 + 3*5 + 5^2 + 5^3 + O(5^4))*x + (2 + 3*5 + 5^2 + O(5^3))*x^2 + (3 + 4*5 + 4*5^2 + O(5^3))*x^3 + (3 + 2*5 + O(5^2))*x^4 + O(x^5) @eprog\noindent These are more cumbersome than \kbd{ellpadicL} but allow to compute at different characters, or successive derivatives, or to twist by a quadratic character essentially for the cost of a single call to \kbd{ellpadicL} due to precomputations. The library syntax is \fun{GEN}{ellpadicL}{GEN E, GEN p, long n, GEN s = NULL, long r, GEN D = NULL}. \subsec{ellpadicbsd$(E,p,n,\{D=1\})$}\kbdsidx{ellpadicbsd}\label{se:ellpadicbsd} Given an elliptic curve $E$ over $\Q$, its quadratic twist $E_{D}$ and a prime number $p$, this function is a $p$-adic analog of the complex functions \tet{ellanalyticrank} and \tet{ellbsd}. It calls \kbd{ellpadicL} with initial accuracy $p^{n}$ and may increase it internally; it returns a vector $[r, L_{p}]$ where \item $L_{p}$ is a $p$-adic number (resp. a pair of $p$-adic numbers if $E$ has good supersingular reduction) defined modulo $p^{N}$, conjecturally equal to $R_{p} S$, where $R_{p}$ is the $p$-adic regulator as given by \tet{ellpadicregulator} (in the basis $(\omega, F \omega)$) and $S$ is the cardinal of the Tate-Shafarevich group for the quadratic twist $E_{D}$. \item $r$ is an upper bound for the analytic rank of the $p$-adic $L$-function attached to $E_{D}$: we know for sure that the $i$-th derivative of $L_{p}(E_{D},.)$ at $\chi^{0}$ is $O(p^{N})$ for all $i < r$ and that its $r$-th derivative is nonzero; it is expected that the true analytic rank is equal to the rank of the Mordell-Weil group $E_{D}(\Q)$, plus $1$ if the reduction of $E_{D}$ at $p$ is split multiplicative; if $r = 0$, then both the analytic rank and the Mordell-Weil rank are unconditionnally $0$. Recall that the $p$-adic BSD conjecture (Mazur, Tate, Teitelbaum, Bernardi, Perrin-Riou) predicts an explicit link between $R_{p} S$ and $$(1-p^{-1} F)^{-2} \cdot L_{p}^{(r)}(E_{D}, \chi^{0}) / r! $$ where $r$ is the analytic rank of the $p$-adic $L$-function attached to $E_{D}$ and $F$ is the Frobenius on $H^{1}_{dR}$; see \tet{ellpadicL} for definitions. \bprog ? E = ellinit("11a1"); p = 7; n = 5; \\ good ordinary ? ellpadicbsd(E, 7, 5) \\ rank 0, %2 = [0, 1 + O(7^5)] ? E = ellinit("91a1"); p = 7; n = 5; \\ non split multiplicative ? [r,Lp] = ellpadicbsd(E, p, n) %5 = [1, 2*7 + 6*7^2 + 3*7^3 + 7^4 + O(7^5)] ? R = ellpadicregulator(E, p, n, E.gen) %6 = 2*7 + 6*7^2 + 3*7^3 + 7^4 + 5*7^5 + O(7^6) ? sha = Lp/R %7 = 1 + O(7^4) ? E = ellinit("91b1"); p = 7; n = 5; \\ split multiplicative ? [r,Lp] = ellpadicbsd(E, p, n) %9 = [2, 2*7 + 7^2 + 5*7^3 + O(7^4)] ? ellpadicregulator(E, p, n, E.gen) %10 = 2*7 + 7^2 + 5*7^3 + 6*7^4 + 2*7^5 + O(7^6) ? [rC, LC] = ellanalyticrank(E); ? [r, rC] %12 = [2, 1] \\ r = rC+1 because of split multiplicative reduction ? E = ellinit("53a1"); p = 5; n = 5; \\ supersingular ? [r, Lp] = ellpadicbsd(E, p, n); ? r %15 = 1 ? Lp %16 = [3*5 + 2*5^2 + 2*5^5 + O(5^6), \ 5 + 3*5^2 + 4*5^3 + 2*5^4 + 5^5 + O(5^6)] ? R = ellpadicregulator(E, p, n, E.gen) %17 = [3*5 + 2*5^2 + 2*5^5 + O(5^6), 5 + 3*5^2 + 4*5^3 + 2*5^4 + O(5^5)] \\ expect Lp = R*#Sha, hence (conjecturally) #Sha = 1 ? E = ellinit("84a1"); p = 11; n = 6; D = -443; ? [r,Lp] = ellpadicbsd(E, 11, 6, D) \\ Mordell-Weil rank 0, no regulator %19 = [0, 3 + 2*11 + O(11^6)] ? lift(Lp) \\ expected cardinal for Sha is 5^2 %20 = 25 ? ellpadicbsd(E, 3, 12, D) \\ at 3 %21 = [1, 1 + 2*3 + 2*3^2 + O(3^8)] ? ellpadicbsd(E, 7, 8, D) \\ and at 7 %22 = [0, 4 + 3*7 + O(7^8)] @eprog The library syntax is \fun{GEN}{ellpadicbsd}{GEN E, GEN p, long n, GEN D = NULL}. \subsec{ellpadicfrobenius$(E,p,n)$}\kbdsidx{ellpadicfrobenius}\label{se:ellpadicfrobenius} If $p>2$ is a prime and $E$ is an elliptic curve on $\Q$ with good reduction at $p$, return the matrix of the Frobenius endomorphism $\varphi$ on the crystalline module $D_{p}(E)= \Q_{p} \otimes H^{1}_{dR}(E/\Q)$ with respect to the basis of the given model $(\omega, \eta=x\*\omega)$, where $\omega = dx/(2\*y+a_{1}\*x+a_{3})$ is the invariant differential. The characteristic polynomial of $\varphi$ is $x^{2} - a_{p}\*x + p$. The matrix is computed to absolute $p$-adic precision $p^{n}$. \bprog ? E = ellinit([1,-1,1,0,0]); ? F = ellpadicfrobenius(E,5,3); ? lift(F) %3 = [120 29] [ 55 5] ? charpoly(F) %4 = x^2 + O(5^3)*x + (5 + O(5^3)) ? ellap(E, 5) %5 = 0 @eprog The library syntax is \fun{GEN}{ellpadicfrobenius}{GEN E, ulong p, long n}. \subsec{ellpadicheight$(E,p,n,P,\{Q\})$}\kbdsidx{ellpadicheight}\label{se:ellpadicheight} Cyclotomic $p$-adic height of the rational point $P$ on the elliptic curve $E$ (defined over $\Q$), given to $n$ $p$-adic digits. If the argument $Q$ is present, computes the value of the bilinear form $(h(P+Q)-h(P-Q)) / 4$. Let $D := H^{1}_{dR}(E) \otimes_{\Q} \Q_{p}$ be the $\Q_{p}$ vector space spanned by $\omega$ (invariant differential $dx/(2y+a_{1}x+a_{3})$ related to the given model) and $\eta = x \omega$. Then the cyclotomic $p$-adic height $h_{E}$ associates to $P\in E(\Q)$ an element $f \omega + g \eta$ in $D$. This routine returns the vector $[f, g]$ to $n$ $p$-adic digits. If $P\in E(\Q)$ is in the kernel of reduction mod $p$ and if its reduction at all finite places is non singular, then $g = -(\log_{E} P)^{2}$, where $\log_{E}$ is the logarithm for the formal group of $E$ at $p$. If furthermore the model is of the form $Y^{2} = X^{3} + a X + b$ and $P = (x,y)$, then $$ f = \log_{p}(\kbd{denominator}(x)) - 2 \log_{p}(\sigma(P))$$ where $\sigma(P)$ is given by \kbd{ellsigma}$(E,P)$. Recall (\emph{Advanced topics in the arithmetic of elliptic curves}, Theorem~3.2) that the local height function over the complex numbers is of the form $$ \lambda(z) = -\log (|\kbd{E.disc}|) / 6 + \Re(z \eta(z)) - 2 \log( \sigma(z)). $$ (N.B. our normalization for local and global heights is twice that of Silverman's). \bprog ? E = ellinit([1,-1,1,0,0]); P = [0,0]; ? ellpadicheight(E,5,3, P) %2 = [3*5 + 5^2 + 2*5^3 + O(5^4), 5^2 + 4*5^4 + O(5^5)] ? E = ellinit("11a1"); P = [5,5]; \\ torsion point ? ellpadicheight(E,19,6, P) %4 = [0, 0] ? E = ellinit([0,0,1,-4,2]); P = [-2,1]; ? ellpadicheight(E,3,3, P) %6 = [2*3^2 + 2*3^3 + 3^4 + O(3^5), 2*3^2 + 3^4 + O(3^5)] ? ellpadicheight(E,3,5, P, elladd(E,P,P)) %7 = [3^2 + 2*3^3 + O(3^7), 3^2 + 3^3 + 2*3^4 + 3^5 + O(3^7)] @eprog \item When $E$ has good ordinary reduction at $p$ or non split multiplicative reduction, the ``canonical'' $p$-adic height is given by \bprog s2 = ellpadics2(E,p,n); ellpadicheight(E, p, n, P) * [1,-s2]~ @eprog\noindent Since $s_{2}$ does not depend on $P$, it is preferable to compute it only once: \bprog ? E = ellinit("5077a1"); p = 5; n = 7; \\ rank 3 ? s2 = ellpadics2(E,p,n); ? M = ellpadicheightmatrix(E,p, n, E.gen) * [1,-s2]~; ? matdet(M) \\ p-adic regulator on the points in E.gen %4 = 5 + 5^2 + 4*5^3 + 2*5^4 + 2*5^5 + 2*5^6 + O(5^7) @eprog \item When $E$ has split multiplicative reduction at $p$ (Tate curve), the ``canonical'' $p$-adic height is given by \bprog Ep = ellinit(E[1..5], O(p^(n))); \\ E seen as a Tate curve over Qp [u2,u,q] = Ep.tate; ellpadicheight(E, p, n, P) * [1,-s2 + 1/log(q)/u2]]~ @eprog\noindent where $s_{2}$ is as above. For example, \bprog ? E = ellinit("91b1"); P =[-1, 3]; p = 7; n = 5; ? Ep = ellinit(E[1..5], O(p^(n))); ? s2 = ellpadics2(E,p,n); ? [u2,u,q] = Ep.tate; ? H = ellpadicheight(E,p, n, P) * [1,-s2 + 1/log(q)/u2]~ %5 = 2*7 + 7^2 + 5*7^3 + 6*7^4 + 2*7^5 + O(7^6) @eprog These normalizations are chosen so that $p$-adic BSD conjectures are easy to state, see \tet{ellpadicbsd}. The library syntax is \fun{GEN}{ellpadicheight0}{GEN E, GEN p, long n, GEN P, GEN Q = NULL}. \subsec{ellpadicheightmatrix$(E,p,n,Q)$}\kbdsidx{ellpadicheightmatrix}\label{se:ellpadicheightmatrix} $Q$ being a vector of points, this function returns the ``Gram matrix'' $[F,G]$ of the cyclotomic $p$-adic height $h_{E}$ with respect to the basis $(\omega, \eta)$ of $D=H^{1}_{dR}(E) \otimes_{\Q} \Q_{p}$ given to $n$ $p$-adic digits. In other words, if \kbd{ellpadicheight}$(E,p,n, Q[i],Q[j]) = [f,g]$, corresponding to $f \omega + g \eta$ in $D$, then $F[i,j] = f$ and $G[i,j] = g$. \bprog ? E = ellinit([0,0,1,-7,6]); Q = [[-2,3],[-1,3]]; p = 5; n = 5; ? [F,G] = ellpadicheightmatrix(E,p,n,Q); ? lift(F) \\ p-adic entries, integral approximation for readability %3 = [2364 3100] [3100 3119] ? G %4 = [25225 46975] [46975 61850] ? [F,G] * [1,-ellpadics2(E,p,n)]~ %5 = [4 + 2*5 + 4*5^2 + 3*5^3 + O(5^5) 4*5^2 + 4*5^3 + 5^4 + O(5^5)] [ 4*5^2 + 4*5^3 + 5^4 + O(5^5) 4 + 3*5 + 4*5^2 + 4*5^3 + 5^4 + O(5^5)] @eprog The library syntax is \fun{GEN}{ellpadicheightmatrix}{GEN E, GEN p, long n, GEN Q}. \subsec{ellpadiclambdamu$(E,p,\{D=1\},\{i=0\})$}\kbdsidx{ellpadiclambdamu}\label{se:ellpadiclambdamu} Let $p$ be a prime number and let $E/\Q$ be a rational elliptic curve with good or bad multiplicative reduction at $p$. Return the Iwasawa invariants $\lambda$ and $\mu$ for the $p$-adic $L$ function $L_{p}(E)$, twisted by $(D/.)$ and the $i$-th power of the Teichm\"uller character $\tau$, see \kbd{ellpadicL} for details about $L_{p}(E)$. Let $\chi$ be the cyclotomic character and choose $\gamma$ in $\text{Gal}(\Q_{p}(\mu_{p^{\infty}})/\Q_{p})$ such that $\chi(\gamma)=1+2p$. Let $\hat{L}^{(i), D} \in \Q_{p}[[X]]\otimes D_{cris}$ such that $$ (<\chi>^{s} \tau^{i}) (\hat{L}^{(i), D}(\gamma-1)) = L_{p}\big(E, <\chi>^{s}\tau^{i} (D/.)\big).$$ \item When $E$ has good ordinary or bad multiplicative reduction at $p$. By Weierstrass's preparation theorem the series $\hat{L}^{(i), D}$ can be written $p^{\mu} (X^{\lambda} + p G(X))$ up to a $p$-adic unit, where $G(X)\in \Z_{p}[X]$. The function returns $[\lambda,\mu]$. \item When $E$ has good supersingular reduction, we define a sequence of polynomials $P_{n}$ in $\Q_{p}[X]$ of degree $< p^{n}$ (and bounded denominators), such that $$\hat{L}^{(i), D} \equiv P_{n} \varphi^{n+1}\omega_{E} - \xi_{n} P_{n-1}\varphi^{n+2}\omega_{E} \bmod \big((1+X)^{p^{n}}-1\big) \Q_{p}[X]\otimes D_{cris},$$ where $\xi_{n} = \kbd{polcyclo}(p^{n}, 1+X)$. Let $\lambda_{n},\mu_{n}$ be the invariants of $P_{n}$. We find that \item $\mu_{n}$ is nonnegative and decreasing for $n$ of given parity hence $\mu_{2n}$ tends to a limit $\mu^{+}$ and $\mu_{2n+1}$ tends to a limit $\mu^{-}$ (both conjecturally $0$). \item there exists integers $\lambda^{+}$, $\lambda^{-}$ in $\Z$ (denoted with a $\til$ in the reference below) such that $$ \lim_{n\to\infty} \lambda_{2n} + 1/(p+1) = \lambda^{+} \quad \text{and} \quad \lim_{n\to\infty} \lambda_{2n+1} + p/(p+1) = \lambda^{-}.$$ The function returns $[[\lambda^{+}, \lambda^{-}], [\mu^{+},\mu^{-}]]$. \noindent Reference: B. Perrin-Riou, Arithm\'etique des courbes elliptiques \`a r\'eduction supersinguli\`ere en $p$, \emph{Experimental Mathematics}, {\bf 12}, 2003, pp. 155-186. The library syntax is \fun{GEN}{ellpadiclambdamu}{GEN E, long p, long D, long i}. \subsec{ellpadiclog$(E,p,n,P)$}\kbdsidx{ellpadiclog}\label{se:ellpadiclog} Given $E$ defined over $K = \Q$ or $\Q_{p}$ and $P = [x,y]$ on $E(K)$ in the kernel of reduction mod $p$, let $t(P) = -x/y$ be the formal group parameter; this function returns $L(t)$ to relative $p$-adic precision $p^{n}$, where $L$ denotes the formal logarithm (mapping the formal group of $E$ to the additive formal group) attached to the canonical invariant differential: $dL = dx/(2y + a_{1}x + a_{3})$. \bprog ? E = ellinit([0,0,1,-4,2]); P = [-2,1]; ? ellpadiclog(E,2,10,P) %2 = 2 + 2^3 + 2^8 + 2^9 + 2^10 + O(2^11) ? E = ellinit([17,42]); ? p=3; Ep = ellinit(E,p); \\ E mod p ? P=[114,1218]; ellorder(Ep,P) \\ the order of P on (E mod p) is 2 %5 = 2 ? Q = ellmul(E,P,2) \\ we need a point of the form 2*P %6 = [200257/7056, 90637343/592704] ? ellpadiclog(E,3,10,Q) %7 = 3 + 2*3^2 + 3^3 + 3^4 + 3^5 + 3^6 + 2*3^8 + 3^9 + 2*3^10 + O(3^11) @eprog The library syntax is \fun{GEN}{ellpadiclog}{GEN E, GEN p, long n, GEN P}. \subsec{ellpadicregulator$(E,p,n,S)$}\kbdsidx{ellpadicregulator}\label{se:ellpadicregulator} Let $E/\Q$ be an elliptic curve. Return the determinant of the Gram matrix of the vector of points $S=(S_{1},\cdots, S_{r})$ with respect to the ``canonical'' cyclotomic $p$-adic height on $E$, given to $n$ ($p$-adic) digits. When $E$ has ordinary reduction at $p$, this is the expected Gram deteterminant in $\Q_{p}$. In the case of supersingular reduction of $E$ at $p$, the definition requires care: the regulator $R$ is an element of $D := H^{1}_{dR}(E) \otimes_{\Q} \Q_{p}$, which is a two-dimensional $\Q_{p}$-vector space spanned by $\omega$ and $\eta = x \omega$ (which are defined over $\Q$) or equivalently but now over $\Q_{p}$ by $\omega$ and $F\omega$ where $F$ is the Frobenius endomorphism on $D$ as defined in \kbd{ellpadicfrobenius}. On $D$ we define the cyclotomic height $h_{E} = f \omega + g \eta$ (see \tet{ellpadicheight}) and a canonical alternating bilinear form $[.,.]_{D}$ such that $[\omega, \eta]_{D} = 1$. For any $\nu \in D$, we can define a height $h_{\nu} := [ h_{E}, \nu ]_{D}$ from $E(\Q)$ to $\Q_{p}$ and $\langle \cdot, \cdot \rangle_{\nu}$ the attached bilinear form. In particular, if $h_{E} = f \omega + g\eta$, then $h_{\eta} = [ h_{E}, \eta ]_{D}$ = f and $h_{\omega} = [ h_{E}, \omega ]_{D} = - g$ hence $h_{E} = h_{\eta} \omega - h_{\omega} \eta$. Then, $R$ is the unique element of $D$ such that $$[\omega,\nu]_{D}^{r-1} [R, \nu]_{D} = \det(\langle S_{i}, S_{j} \rangle_{\nu})$$ for all $\nu \in D$ not in $\Q_{p} \omega$. The \kbd{ellpadicregulator} function returns $R$ in the basis $(\omega, F\omega)$, which was chosen so that $p$-adic BSD conjectures are easy to state, see \kbd{ellpadicbsd}. Note that by definition $$[R, \eta]_{D} = \det(\langle S_{i}, S_{j} \rangle_{\eta})$$ and $$[R, \omega+\eta]_{D} =\det(\langle S_{i}, S_{j} \rangle_{\omega+\eta}).$$ The library syntax is \fun{GEN}{ellpadicregulator}{GEN E, GEN p, long n, GEN S}. \subsec{ellpadics2$(E,p,n)$}\kbdsidx{ellpadics2}\label{se:ellpadics2} If $p>2$ is a prime and $E/\Q$ is an elliptic curve with ordinary good reduction at $p$, returns the slope of the unit eigenvector of \kbd{ellpadicfrobenius(E,p,n)}, i.e., the action of Frobenius $\varphi$ on the crystalline module $D_{p}(E)= \Q_{p} \otimes H^{1}_{dR}(E/\Q)$ in the basis of the given model $(\omega, \eta=x\*\omega)$, where $\omega$ is the invariant differential $dx/(2\*y+a_{1}\*x+a_{3})$. In other words, $\eta + s_{2}\omega$ is an eigenvector for the unit eigenvalue of $\varphi$. \bprog ? e=ellinit([17,42]); ? ellpadics2(e,13,4) %2 = 10 + 2*13 + 6*13^3 + O(13^4) @eprog This slope is the unique $c \in 3^{-1}\Z_{p}$ such that the odd solution $\sigma(t) = t + O(t^{2})$ of $$ - d(\dfrac{1}{\sigma} \dfrac{d \sigma}{\omega}) = (x(t) + c) \omega$$ is in $t\Z_{p}[[t]]$. It is equal to $b_{2}/12 - E_{2}/12$ where $E_{2}$ is the value of the Katz $p$-adic Eisenstein series of weight 2 on $(E,\omega)$. This is used to construct a canonical $p$-adic height when $E$ has good ordinary reduction at $p$ as follows \bprog s2 = ellpadics2(E,p,n); h(E,p,n, P, s2) = ellpadicheight(E, [p,[1,-s2]],n, P); @eprog\noindent Since $s_{2}$ does not depend on the point $P$, we compute it only once. The library syntax is \fun{GEN}{ellpadics2}{GEN E, GEN p, long n}. \subsec{ellperiods$(w,\{\fl=0\})$}\kbdsidx{ellperiods}\label{se:ellperiods} Let $w$ describe a complex period lattice ($w = [w_{1},w_{2}]$ or an \kbd{ellinit} structure). Returns normalized periods $[W_{1},W_{2}]$ generating the same lattice such that $\tau := W_{1}/W_{2}$ has positive imaginary part and lies in the standard fundamental domain for $\text{SL}_{2}(\Z)$. If $\fl = 1$, the function returns $[[W_{1},W_{2}], [\eta_{1},\eta_{2}]]$, where $\eta_{1}$ and $\eta_{2}$ are the quasi-periods attached to $[W_{1},W_{2}]$, satisfying $\eta_{2} W_{1} - \eta_{1} W_{2} = 2 i \pi$. The output of this function is meant to be used as the first argument given to ellwp, ellzeta, ellsigma or elleisnum. Quasi-periods are needed by ellzeta and ellsigma only. \bprog ? L = ellperiods([1,I],1); ? [w1,w2] = L[1]; [e1,e2] = L[2]; ? e2*w1 - e1*w2 %3 = 6.2831853071795864769252867665590057684*I ? ellzeta(L, 1/2 + 2*I) %4 = 1.5707963... - 6.283185307...*I ? ellzeta([1,I], 1/2 + 2*I) \\ same but less efficient %4 = 1.5707963... - 6.283185307...*I @eprog The library syntax is \fun{GEN}{ellperiods}{GEN w, long flag, long prec}. \subsec{ellpointtoz$(E,P)$}\kbdsidx{ellpointtoz}\label{se:ellpointtoz} If $E/\C \simeq \C/\Lambda$ is a complex elliptic curve ($\Lambda = \kbd{E.omega}$), computes a complex number $z$, well-defined modulo the lattice $\Lambda$, corresponding to the point $P$; i.e.~such that $P = [\wp_{\Lambda}(z),\wp'_{\Lambda}(z)]$ satisfies the equation $$y^{2} = 4x^{3} - g_{2} x - g_{3},$$ where $g_{2}$, $g_{3}$ are the elliptic invariants. If $E$ is defined over $\R$ and $P\in E(\R)$, we have more precisely, $0 \leq \Re(t) < w1$ and $0 \leq \Im(t) < \Im(w2)$, where $(w1,w2)$ are the real and complex periods of $E$. \bprog ? E = ellinit([0,1]); P = [2,3]; ? z = ellpointtoz(E, P) %2 = 3.5054552633136356529375476976257353387 ? ellwp(E, z) %3 = 2.0000000000000000000000000000000000000 ? ellztopoint(E, z) - P %4 = [2.548947057811923643 E-57, 7.646841173435770930 E-57] ? ellpointtoz(E, [0]) \\ the point at infinity %5 = 0 @eprog If $E$ is defined over a general number field, the function returns the values corresponding to the various complex embeddings of the curve and of the point, in the same order as \kbd{E.nf.roots}: \bprog ? E=ellinit([-22032-15552*x,0], nfinit(x^2-2)); ? P=[-72*x-108,0]; ? ellisoncurve(E,P) %3 = 1 ? ellpointtoz(E,P) %4 = [-0.52751724240790530394437835702346995884*I, -0.090507650025885335533571758708283389896*I] ? E.nf.roots %5 = [-1.4142135623730950488016887242096980786, \\ x-> -sqrt(2) 1.4142135623730950488016887242096980786] \\ x-> sqrt(2) @eprog If $E/\Q_{p}$ has multiplicative reduction, then $E/\bar{\Q_{p}}$ is analytically isomorphic to $\bar{\Q}_{p}^{*}/q^{\Z}$ (Tate curve) for some $p$-adic integer $q$. The behavior is then as follows: \item If the reduction is split ($E.\kbd{tate[2]}$ is a \typ{PADIC}), we have an isomorphism $\phi: E(\Q_{p}) \simeq \Q_{p}^{*}/q^{\Z}$ and the function returns $\phi(P)\in \Q_{p}$. \item If the reduction is \emph{not} split ($E.\kbd{tate[2]}$ is a \typ{POLMOD}), we only have an isomorphism $\phi: E(K) \simeq K^{*}/q^{\Z}$ over the unramified quadratic extension $K/\Q_{p}$. In this case, the output $\phi(P)\in K$ is a \typ{POLMOD}; the function is not fully implemented in this case and may fail with a ``$u$ not in $\Q_{p}$'' exception: \bprog ? E = ellinit([0,-1,1,0,0], O(11^5)); P = [0,0]; ? [u2,u,q] = E.tate; type(u) \\ split multiplicative reduction %2 = "t_PADIC" ? ellmul(E, P, 5) \\ P has order 5 %3 = [0] ? z = ellpointtoz(E, [0,0]) %4 = 3 + 11^2 + 2*11^3 + 3*11^4 + 6*11^5 + 10*11^6 + 8*11^7 + O(11^8) ? z^5 %5 = 1 + O(11^9) ? E = ellinit(ellfromj(1/4), O(2^6)); x=1/2; y=ellordinate(E,x)[1]; ? z = ellpointtoz(E,[x,y]); \\ t_POLMOD of t_POL with t_PADIC coeffs ? liftint(z) \\ lift all p-adics %8 = Mod(8*u + 7, u^2 + 437) ? x=33/4; y=ellordinate(E,x)[1]; z = ellpointtoz(E,[x,y]) *** at top-level: ...;y=ellordinate(E,x)[1];z=ellpointtoz(E,[x,y]) *** ^-------------------- *** ellpointtoz: sorry, ellpointtoz when u not in Qp is not yet implemented. @eprog The library syntax is \fun{GEN}{zell}{GEN E, GEN P, long prec}. \subsec{ellpow$(E,z,n)$}\kbdsidx{ellpow}\label{se:ellpow} Deprecated alias for \kbd{ellmul}. The library syntax is \fun{GEN}{ellmul}{GEN E, GEN z, GEN n}. \subsec{ellrank$(E,\{\var{effort}=0\},\{\var{points}\})$}\kbdsidx{ellrank}\label{se:ellrank} If $E$ is an elliptic curve over $\Q$, attempts to compute the Mordell-Weil group attached to the curve. The output is $[r_{1},r_{2},s,L]$, where $r_{1} \le\text{rank}(E) \le r_{2}$, $s$ gives informations on the Tate-Shafarevic group (see below), and $L$ is a list of independent, non-torsion rational points on the curve. $E$ can also be given as the output of \kbd{ellrankinit(E)}. If \kbd{points} is provided, it must be a vector of rational points on the curve, which are not computed again. The parameter \kbd{effort} is a measure of the time employed to find rational points before giving up. If \kbd{effort} is not $0$, the search is randomized, so rerunning the function might yield different or even a different number of rational points. Values up to $10$ or so are reasonable but the parameter can be increased futher, with running times increasing roughly like the \emph{cube} of the \kbd{effort} value. \bprog ? E = ellinit([-127^2,0]); ? ellrank(E) %2 = [1, 1, 0, []] \\ rank is 1 but no point has been found. ? ellrank(E,4) \\ with more effort we find a point. %3 = [1, 1, 0, [[38902300445163190028032/305111826865145547009, 680061120400889506109527474197680/5329525731816164537079693913473]]] @eprog In addition to the previous calls, the first argument $E$ can be a pair $[e,f]$, where $e$ is an elliptic curve given by \kbd{ellrankinit} and $f$ is a quadratic twist of $e$. We then look for points on $f$. Note that the \kbd{ellrankinit} initialization is independent of $f$, so this can speed up computations significantly! \misctitle{Technical explanation} The algorithm, which computes the $2$-descent and the $2$-part of the Cassels pairings has an intrinsic limitation: $r_{1} = r_{2}$ never holds when the Tate-Shafarevic group $G$ has $4$-torsion. Thus, in this case we cannot determine the rank precisely. The algorithm computes unconditionally three quantities: \item the rank $C$ of the $2$-Selmer group. \item the rank $T$ of the $2$-torsion subgroup. \item the (even) rank $s$ of $G[2]/2G[4]$; then $r_{2}$ is defined by $r_{2} = C - T - s$. The following quantities are also relevant: \item the rank $R$ of the free part of $E(\Q)$; it always holds that $r_{1} \le R \le r_{2}$. \item the rank $S$ of $G[2]$ (conjecturally even); it always holds that $s \le S$ and that $C = T + R + S$. Then $r_{2} = C - T - s \ge R$. When the conductor of $E$ is small, the BSD conjecture can be used to (conditionally) find the true rank: \bprog ? E=ellinit([-113^2,0]); ? ellrootno(E) \\ rank is even (parity conjecture) %2 = 1 ? ellrank(E) %3 = [0, 2, 0, []] \\ rank is either 0 or 2, $2$-rank of $G$ is ? ellrank(E, 3) \\ try harder %4 = [0, 2, 0, []] \\ no luck ? [r,L] = ellanalyticrank(E) \\ assume BSD %5 = [0, 3.9465...] ? L / ellbsd(E) \\ analytic rank is 0, compute Sha %6 = 16.0000000000000000000000000000000000000 @eprog We find that the rank is $0$ and the cardinal of the Tate-Shafarevich group is $16$ (assuming BSD!). Moreover, since $s=0$, it is isomorphic to $(\Z/4\Z)^{2}$. When the rank is $1$ and the conductor is small, \kbd{ellheegner} can be used to find a non-torsion point: \bprog ? E = ellinit([-157^2,0]); ? ellrank(E) %2 = [1, 1, 0, []] \\ rank is 1, no point found ? ellrank(E, 5) \\ Try harder time = 1,094 ms. %3 = [1, 1, 0, []] \\ No luck ? ellheegner(E) \\ use analytic method time = 492 ms. %4 = [69648970982596494254458225/166136231668185267540804, ...] @eprog\noindent In this last example, an \kbd{effort} about 10 would also (with probability about 80\%) find a random point, not necessarily the Heegner point, in about 5 seconds. The library syntax is \fun{GEN}{ellrank}{GEN E, long effort, GEN points = NULL, long prec}. \subsec{ellrankinit$(E)$}\kbdsidx{ellrankinit}\label{se:ellrankinit} If $E$ is an elliptic curve over $\Q$, initialize data to speed up further calls to \kbd{ellrank}. \bprog ? E = ellinit([0,2429469980725060,0,275130703388172136833647756388,0]); ? rk = ellrankinit(E); ? [r, R, s, P] = ellrank(rk) %3 = [12, 14, 0, [...]] ? [r, R, s, P] = ellrank(rk, 1, P) \\ more effort, using known points %4 = [14, 14, 0, [...]] \\ this time all points are found @eprog The library syntax is \fun{GEN}{ellrankinit}{GEN E, long prec}. \subsec{ellratpoints$(E,h,\{\fl=0\})$}\kbdsidx{ellratpoints}\label{se:ellratpoints} $E$ being an integral model of elliptic curve , return a vector containing the affine rational points on the curve of naive height less than $h$. If $\fl=1$, stop as soon as a point is found; return either an empty vector or a vector containing a single point. See \kbd{hyperellratpoints} for how $h$ can be specified. \bprog ? E=ellinit([-25,1]); ? ellratpoints(E,10) %2 = [[-5,1],[-5,-1],[-3,7],[-3,-7],[-1,5],[-1,-5], [0,1],[0,-1],[5,1],[5,-1],[7,13],[7,-13]] ? ellratpoints(E,10,1) %3 = [[-5,1]] @eprog The library syntax is \fun{GEN}{ellratpoints}{GEN E, GEN h, long flag}. \subsec{ellrootno$(E,\{p\})$}\kbdsidx{ellrootno}\label{se:ellrootno} $E$ being an \kbd{ell} structure over $\Q$ as output by \kbd{ellinit}, this function computes the local root number of its $L$-series at the place $p$ (at the infinite place if $p = 0$). If $p$ is omitted, return the global root number and in this case the curve can also be defined over a number field. Note that the global root number is the sign of the functional equation and conjecturally is the parity of the rank of the \idx{Mordell-Weil group}. The equation for $E$ needs not be minimal at $p$, but if the model is already minimal the function will run faster. The library syntax is \fun{long}{ellrootno}{GEN E, GEN p = NULL}. \subsec{ellsaturation$(E,V,B)$}\kbdsidx{ellsaturation}\label{se:ellsaturation} Let $E$ be an elliptic curve over $\Q$ and and $V$ be a set of independent non-torsion rational points on $E$ of infinite order that generate a subgroup $G$ of $E(\Q)$ of finite index. Return a new set $W$ of the same length that generate a subgroup $H$ of $E(\Q)$ containing $G$ and such that $[E(\Q):H]$ is not divisible by any prime number less than $B$. The running time is roughly quadratic in $B$. \bprog ? E = ellinit([0,0, 1, -7, 6]); ? [r,R,s,V] = ellrank(E) %2 = [3, 3, 0, [[-1,3], [-3,0], [11,35]]] ? matdet(ellheightmatrix(E, V)) %3 = 3.7542920288254557283540759015628405708 ? W = ellsaturation(E, V, 2) \\ index is now odd time = 1 ms. %4 = [[-1, 3], [-3, 0], [11, 35]] ? W = ellsaturation(E, W, 10) \\ index not divisible by p <= 10 %5 = [[1, -1], [2, -1], [0, -3]] time = 2 ms. ? W = ellsaturation(E, V, 100) \\ looks OK now time = 171 ms. %6 = [[1, -1], [2, -1], [0, -3]] ? matdet(ellheightmatrix(E,V)) %7 = 0.41714355875838396981711954461809339675 ? lfun(E,1,3)/3! / ellbsd(E) \\ conductor is small, check assuming BSD %8 = 0.41714355875838396981711954461809339675 @eprog The library syntax is \fun{GEN}{ellsaturation}{GEN E, GEN V, long B, long prec}. \subsec{ellsea$(E,\{\var{tors}=0\})$}\kbdsidx{ellsea}\label{se:ellsea} Let $E$ be an \var{ell} structure as output by \kbd{ellinit}, defined over a finite field $\F_{q}$. This low-level function computes the order of the group $E(\F_{q})$ using the SEA algorithm; compared to the high-level function \kbd{ellcard}, which includes SEA among its choice of algorithms, the \kbd{tors} argument allows to speed up a search for curves having almost prime order and whose quadratic twist may also have almost prime order. When \kbd{tors} is set to a nonzero value, the function returns $0$ as soon as it detects that the order has a small prime factor not dividing \kbd{tors}; SEA considers modular polynomials of increasing prime degree $\ell$ and we return $0$ as soon as we hit an $\ell$ (coprime to \kbd{tors}) dividing $\#E(\F_{q})$: \bprog ? ellsea(ellinit([1,1], 2^56+3477), 1) %1 = 72057594135613381 ? forprime(p=2^128,oo, q = ellcard(ellinit([1,1],p)); if(isprime(q),break)) time = 6,571 ms. ? forprime(p=2^128,oo, q = ellsea(ellinit([1,1],p),1);if(isprime(q),break)) time = 522 ms. @eprog\noindent In particular, set \kbd{tors} to $1$ if you want a curve with prime order, to $2$ if you want to allow a cofactor which is a power of two (e.g. for Edwards's curves), etc. The early exit on bad curves yields a massive speedup compared to running the cardinal algorithm to completion. When \kbd{tors} is negative, similar checks are performed for the quadratic twist of the curve. The following function returns a curve of prime order over $\F_{p}$. \bprog cryptocurve(p) = { while(1, my(E, N, j = Mod(random(p), p)); E = ellinit(ellfromj(j)); N = ellsea(E, 1); if (!N, continue); if (isprime(N), return(E)); \\ try the quadratic twist for free if (isprime(2*p+2 - N), return(elltwist(E))); ); } ? p = randomprime([2^255, 2^256]); ? E = cryptocurve(p); \\ insist on prime order %2 = 47,447ms @eprog\noindent The same example without early abort (using \kbd{ellcard(E)} instead of \kbd{ellsea(E, 1)}) runs for about 5 minutes before finding a suitable curve. The availability of the \kbd{seadata} package will speed up the computation, and is strongly recommended. The generic function \kbd{ellcard} should be preferred when you only want to compute the cardinal of a given curve without caring about it having almost prime order: \item If the characteristic is too small ($p \leq 7$) or the field cardinality is tiny ($q \leq 523$) the generic algorithm \kbd{ellcard} is used instead and the \kbd{tors} argument is ignored. (The reason for this is that SEA is not implemented for $p \leq 7$ and that if $q \leq 523$ it is likely to run into an infinite loop.) \item If the field cardinality is smaller than about $2^{50}$, the generic algorithm will be faster. \item Contrary to \kbd{ellcard}, \kbd{ellsea} does not store the computed cardinality in $E$. The library syntax is \fun{GEN}{ellsea}{GEN E, long tors}. \subsec{ellsearch$(N)$}\kbdsidx{ellsearch}\label{se:ellsearch} This function finds all curves in the \tet{elldata} database satisfying the constraint defined by the argument $N$: \item if $N$ is a character string, it selects a given curve, e.g. \kbd{"11a1"}, or curves in the given isogeny class, e.g. \kbd{"11a"}, or curves with given conductor, e.g. \kbd{"11"}; \item if $N$ is a vector of integers, it encodes the same constraints as the character string above, according to the \tet{ellconvertname} correspondance, e.g. \kbd{[11,0,1]} for \kbd{"11a1"}, \kbd{[11,0]} for \kbd{"11a"} and \kbd{[11]} for \kbd{"11"}; \item if $N$ is an integer, curves with conductor $N$ are selected. If $N$ codes a full curve name, for instance \kbd{"11a1"} or \kbd{[11,0,1]}, the output format is $[N, [a_{1},a_{2},a_{3},a_{4},a_{6}], G]$ where $[a_{1},a_{2},a_{3},a_{4},a_{6}]$ are the coefficients of the Weierstrass equation of the curve and $G$ is a $\Z$-basis of the free part of the \idx{Mordell-Weil group} attached to the curve. \bprog ? ellsearch("11a3") %1 = ["11a3", [0, -1, 1, 0, 0], []] ? ellsearch([11,0,3]) %2 = ["11a3", [0, -1, 1, 0, 0], []] @eprog\noindent If $N$ is not a full curve name, then the output is a vector of all matching curves in the above format: \bprog ? ellsearch("11a") %1 = [["11a1", [0, -1, 1, -10, -20], []], ["11a2", [0, -1, 1, -7820, -263580], []], ["11a3", [0, -1, 1, 0, 0], []]] ? ellsearch("11b") %2 = [] @eprog The library syntax is \fun{GEN}{ellsearch}{GEN N}. Also available is \fun{GEN}{ellsearchcurve}{GEN N} that only accepts complete curve names (as \typ{STR}). \subsec{ellsigma$(L,\{z='x\},\{\fl=0\})$}\kbdsidx{ellsigma}\label{se:ellsigma} Computes the value at $z$ of the Weierstrass $\sigma$ function attached to the lattice $L$ as given by \tet{ellperiods}$(,1)$: including quasi-periods is useful, otherwise there are recomputed from scratch for each new $z$. $$ \sigma(z, L) = z \prod_{\omega\in L^{*}} \left(1 - \dfrac{z}{\omega}\right) e^{\dfrac{z}{\omega} + \dfrac{z^{2}}{2\omega^{2}}}.$$ It is also possible to directly input $L = [\omega_{1},\omega_{2}]$, or an elliptic curve $E$ as given by \kbd{ellinit} ($L = \kbd{E.omega}$). \bprog ? w = ellperiods([1,I], 1); ? ellsigma(w, 1/2) %2 = 0.47494937998792065033250463632798296855 ? E = ellinit([1,0]); ? ellsigma(E) \\ at 'x, implicitly at default seriesprecision %4 = x + 1/60*x^5 - 1/10080*x^9 - 23/259459200*x^13 + O(x^17) @eprog If $\fl=1$, computes an arbitrary determination of $\log(\sigma(z))$. The library syntax is \fun{GEN}{ellsigma}{GEN L, GEN z = NULL, long flag, long prec}. \subsec{ellsub$(E,\var{z1},\var{z2})$}\kbdsidx{ellsub}\label{se:ellsub} Difference of the points $z1$ and $z2$ on the elliptic curve corresponding to $E$. The library syntax is \fun{GEN}{ellsub}{GEN E, GEN z1, GEN z2}. \subsec{ellsupersingularj$(p)$}\kbdsidx{ellsupersingularj}\label{se:ellsupersingularj} Return a random supersingular $j$-invariant defined over $\F_{p}^{2}$ as a \typ{FFELT} in the variable \kbd{w}, if $p$ is a prime number, or over the field of definition of $p$ if $p$ is a \typ{FFELT}. The field must be of even degree. The random distribution is close to uniform except when $0$ or $1728$ are supersingular $j$-invariants, in which case they are less likely to be returned. This bias becomes negligible as $p$ grows. \bprog ? j = ellsupersingularj(1009) %1 = 12*w+295 ? ellissupersingular(j) %2 = 1 ? a = ffgen([1009,2],'a); ? j = ellsupersingularj(a) %4 = 867*a+721 ? ellissupersingular(j) %5 = 1 ? E = ellinit([j]); ? F = elltwist(E); ? ellissupersingular(F) %8 = 1 ? ellap(E) %9 = 2018 ? ellap(F) %10 = -2018 @eprog The library syntax is \fun{GEN}{ellsupersingularj}{GEN p}. \subsec{elltamagawa$(E)$}\kbdsidx{elltamagawa}\label{se:elltamagawa} The object $E$ being an elliptic curve over a number field, returns the global Tamagawa number of the curve (including the factor at infinite places). \bprog ? e = ellinit([1, -1, 1, -3002, 63929]); \\ curve "90c6" from elldata ? elltamagawa(e) %2 = 288 ? [elllocalred(e,p)[4] | p<-[2,3,5]] %3 = [6, 4, 6] ? vecprod(%) \\ since e.disc > 0 the factor at infinity is 2 %4 = 144 ? ellglobalred(e)[4] \\ product without the factor at infinity %5 = 144 @eprog The library syntax is \fun{GEN}{elltamagawa}{GEN E}. \subsec{elltaniyama$(E,\{n=\var{seriesprecision}\})$}\kbdsidx{elltaniyama}\label{se:elltaniyama} Computes the modular parametrization of the elliptic curve $E/\Q$, where $E$ is an \kbd{ell} structure as output by \kbd{ellinit}. This returns a two-component vector $[u,v]$ of power series, given to $n$ significant terms (\tet{seriesprecision} by default), characterized by the following two properties. First the point $(u,v)$ satisfies the equation of the elliptic curve. Second, let $N$ be the conductor of $E$ and $\Phi: X_{0}(N)\to E$ be a modular parametrization; the pullback by $\Phi$ of the N\'eron differential $du/(2v+a_{1}u+a_{3})$ is equal to $2i\pi f(z)dz$, a holomorphic differential form. The variable used in the power series for $u$ and $v$ is $x$, which is implicitly understood to be equal to $\exp(2i\pi z)$. The algorithm assumes that $E$ is a \emph{strong} \idx{Weil curve} and that the Manin constant is equal to 1: in fact, $f(x) = \sum_{n > 0} \kbd{ellak}(E, n) x^{n}$. The library syntax is \fun{GEN}{elltaniyama}{GEN E, long precdl}. \subsec{elltatepairing$(E,P,Q,m)$}\kbdsidx{elltatepairing}\label{se:elltatepairing} Let $E$ be an elliptic curve defined over a finite field $k$ and $m \geq 1$ be an integer. This function computes the (nonreduced) Tate pairing of the points $P$ and $Q$ on $E$, where $P$ is an $m$-torsion point. More precisely, let $f_{m,P}$ denote a Miller function with divisor $m[P] - m[O_{E}]$; the algorithm returns $f_{m,P}(Q) \in k^{*}/(k^{*})^{m}$. The library syntax is \fun{GEN}{elltatepairing}{GEN E, GEN P, GEN Q, GEN m}. \subsec{elltors$(E)$}\kbdsidx{elltors}\label{se:elltors} If $E$ is an elliptic curve defined over a number field or a finite field, outputs the torsion subgroup of $E$ as a 3-component vector \kbd{[t,v1,v2]}, where \kbd{t} is the order of the torsion group, \kbd{v1} gives the structure of the torsion group as a product of cyclic groups (sorted by decreasing order), and \kbd{v2} gives generators for these cyclic groups. $E$ must be an \kbd{ell} structure as output by \kbd{ellinit}. \bprog ? E = ellinit([-1,0]); ? elltors(E) %1 = [4, [2, 2], [[0, 0], [1, 0]]] @eprog\noindent Here, the torsion subgroup is isomorphic to $\Z/2\Z \times \Z/2\Z$, with generators $[0,0]$ and $[1,0]$. The library syntax is \fun{GEN}{elltors}{GEN E}. \subsec{elltrace$(E,P)$}\kbdsidx{elltrace}\label{se:elltrace} Let $E$ be an elliptic curve over a base field and a point $P$ defined over an extension field using \typ{POLMOD} constructs. Returns the sum of the Galois conjugates of $P$. The field over which $P$ is defined must be specified, even in the (silly) case of a trivial extension: \bprog ? E = ellinit([1,15]); \\ y^2 = x^3 + x + 15, over Q ? P = Mod([a/8-1, 1/32*a^2-11/32*a-19/4], a^3-135*a-408); ? ellisoncurve(E,P) \\ P defined over a cubic extension %3 = 1 ? elltrace(E,P) %4 = [2,-5] @eprog \bprog ? E = ellinit([-13^2, 0]); ? P = Mod([13,0], a^2-2); \\ defined over Q, seen over a quadratic extension ? elltrace(E,P) == ellmul(E,P,2) %3 = 1 ? elltrace(E,[13,0]) \\ number field of definition of the point unspecified! *** at top-level: elltrace(E,[13,0]) *** ^------------------ *** elltrace: incorrect type in elltrace (t_INT). ? elltrace(E,Mod([13,0],a)) \\ trivial extension %5 = [Mod(13, a), Mod(0, a)] ? P = Mod([-10*x^3+10*x-13, -16*x^3+16*x-34], x^4-x^3+2*x-1); ? ellisoncurve(E,P) %7 = 1 ? Q = elltrace(E,P) %8 = [11432100241 / 375584400, 1105240264347961 / 7278825672000] ? ellisoncurve(E,Q) %9 = 1 @eprog \bprog ? E = ellinit([2,3], 19); \\ over F_19 ? T = a^5+a^4+15*a^3+16*a^2+3*a+1; \\ irreducible ? P = Mod([11*a^3+11*a^2+a+12,15*a^4+9*a^3+18*a^2+18*a+6], T); ? ellisoncurve(E, P) %4 = 1 ? Q = elltrace(E, P) %5 = [Mod(1,19), Mod(14,19)] ? ellisoncurve(E, Q) %6 = 1 @eprog The library syntax is \fun{GEN}{elltrace}{GEN E, GEN P}. \subsec{elltwist$(E,\{P\})$}\kbdsidx{elltwist}\label{se:elltwist} Returns an \kbd{ell} structure (as given by \kbd{ellinit}) for the twist of the elliptic curve $E$ by the quadratic extension of the coefficient ring defined by $P$ (when $P$ is a polynomial) or \kbd{quadpoly(P)} when $P$ is an integer. If $E$ is defined over a finite field, then $P$ can be omitted, in which case a random model of the unique nontrivial twist is returned. If $E$ is defined over a number field, the model should be replaced by a minimal model (if one exists). The elliptic curve $E$ can be given in some of the formats allowed by \kbd{ellinit}: an \kbd{ell} structure, a $5$-component vector $[a_{1},a_{2},a_{3},a_{4},a_{6}]$ or a $2$-component vector $[a_{4},a_{6}]$. Twist by discriminant $-3$: \bprog ? elltwist([0,a2,0,a4,a6], -3)[1..5] %1 = [0, -3*a2, 0, 9*a4, -27*a6] ? elltwist([a4,a6], -3)[1..5] %2 = [0, 0, 0, 9*a4, -27*a6] @eprog Twist by the Artin-Schreier extension given by $x^{2}+x+T$ in characteristic $2$: \bprog ? lift(elltwist([a1,a2,a3,a4,a6]*Mod(1,2), x^2+x+T)[1..5]) %1 = [a1, a2+a1^2*T, a3, a4, a6+a3^2*T] @eprog Twist of an elliptic curve defined over a finite field: \bprog ? E = elltwist([1,7]*Mod(1,19)); lift([E.a4, E.a6]) %1 = [11, 12] @eprog The library syntax is \fun{GEN}{elltwist}{GEN E, GEN P = NULL}. \subsec{ellweilcurve$(E,\{\&\var{ms}\})$}\kbdsidx{ellweilcurve}\label{se:ellweilcurve} If $E'$ is an elliptic curve over $\Q$, let $L_{E'}$ be the sub-$\Z$-module of $\Hom_{\Gamma_{0}(N)}(\Delta_{0},\Q)$ attached to $E'$ (It is given by $x[3]$ if $[M,x] = \kbd{msfromell}(E')$.) On the other hand, if $N$ is the conductor of $E$ and $f$ is the modular form for $\Gamma_{0}(N)$ attached to $E$, let $L_{f}$ be the lattice of the $f$-component of $\Hom_{\Gamma_{0}(N)}(\Delta_{0},\Q)$ given by the elements $\phi$ such that $\phi(\{0,\gamma^{-1} 0\}) \in \Z$ for all $\gamma \in \Gamma_{0}(N)$ (see \tet{mslattice}). Let $E'$ run through the isomorphism classes of elliptic curves isogenous to $E$ as given by \kbd{ellisomat} (and in the same order). This function returns a pair \kbd{[vE,vS]} where \kbd{vE} contains minimal models for the $E'$ and \kbd{vS} contains the list of Smith invariants for the lattices $L_{E'}$ in $L_{f}$. The function also accepts the output of \kbd{ellisomat}, i.e. the isogeny class. If the optional argument \kbd{ms} is present, it contains the output of \kbd{msfromell(vE, 0)}, i.e. the new modular symbol space $M$ of level $N$ and a vector of triples $[x^{+},x^{-}, L]$ attached to each curve $E'$. In particular, the strong Weil curve amongst the curves isogenous to $E$ is the one whose Smith invariants are $[c,c]$, where $c$ is the Manin constant, conjecturally equal to $1$. \bprog ? E = ellinit("11a3"); ? [vE, vS] = ellweilcurve(E); ? [n] = [ i | i<-[1..#vS], vS[i]==[1,1] ] \\ lattice with invariant [1,1] %3 = [2] ? ellidentify(vE[n]) \\ ... corresponds to strong Weil curve %4 = [["11a1", [0, -1, 1, -10, -20], []], [1, 0, 0, 0]] ? [vE, vS] = ellweilcurve(E, &ms); \\ vE,vS are as above ? [M, vx] = ms; msdim(M) \\ ... but ms contains more information %6 = 3 ? #vx %7 = 3 ? vx[1] %8 = [[1/25, -1/10, -1/10]~, [0, 1/2, -1/2]~, [1/25,0; -3/5,1; 2/5,-1]] ? forell(E, 11,11, print(msfromell(ellinit(E[1]), 1)[2])) [1/5, -1/2, -1/2]~ [1, -5/2, -5/2]~ [1/25, -1/10, -1/10]~ @eprog\noindent The last example prints the modular symbols $x^{+}$ in $M^{+}$ attached to the curves \kbd{11a1}, \kbd{11a2} and \kbd{11a3}. The library syntax is \fun{GEN}{ellweilcurve}{GEN E, GEN *ms = NULL}. \subsec{ellweilpairing$(E,P,Q,m)$}\kbdsidx{ellweilpairing}\label{se:ellweilpairing} Let $E$ be an elliptic curve defined over a finite field and $m \geq 1$ be an integer. This function computes the Weil pairing of the two $m$-torsion points $P$ and $Q$ on $E$, which is an alternating bilinear map. More precisely, let $f_{m,R}$ denote a Miller function with divisor $m[R] - m[O_{E}]$; the algorithm returns the $m$-th root of unity $$\varepsilon(P,Q)^{m} \cdot f_{m,P}(Q) / f_{m,Q}(P),$$ where $f(R)$ is the extended evaluation of $f$ at the divisor $[R] - [O_{E}]$ and $\varepsilon(P,Q)\in \{\pm1\}$ is given by Weil reciprocity: $\varepsilon(P,Q) = 1$ if and only if $P, Q, O_{E}$ are not pairwise distinct. The library syntax is \fun{GEN}{ellweilpairing}{GEN E, GEN P, GEN Q, GEN m}. \subsec{ellwp$(w,\{z='x\},\{\fl=0\})$}\kbdsidx{ellwp}\label{se:ellwp} Computes the value at $z$ of the Weierstrass $\wp$ function attached to the lattice $w$ as given by \tet{ellperiods}. It is also possible to directly input $w = [\omega_{1},\omega_{2}]$, or an elliptic curve $E$ as given by \kbd{ellinit} ($w = \kbd{E.omega}$). \bprog ? w = ellperiods([1,I]); ? ellwp(w, 1/2) %2 = 6.8751858180203728274900957798105571978 ? E = ellinit([1,1]); ? ellwp(E, 1/2) %4 = 3.9413112427016474646048282462709151389 @eprog\noindent One can also compute the series expansion around $z = 0$: \bprog ? E = ellinit([1,0]); ? ellwp(E) \\ 'x implicitly at default seriesprecision %5 = x^-2 - 1/5*x^2 + 1/75*x^6 - 2/4875*x^10 + O(x^14) ? ellwp(E, x + O(x^12)) \\ explicit precision %6 = x^-2 - 1/5*x^2 + 1/75*x^6 + O(x^9) @eprog Optional \fl\ means 0 (default): compute only $\wp(z)$, 1: compute $[\wp(z),\wp'(z)]$. For instance, the Dickson elliptic functions \var{sm} and \var{sn} can be implemented as follows \bprog smcm(z) = { my(a, b, E = ellinit([0,-1/(4*27)])); \\ ell. invariants (g2,g3)=(0,1/27) [a,b] = ellwp(E, z, 1); [6*a / (1-3*b), (3*b+1)/(3*b-1)]; } ? [s,c] = smcm(0.5); ? s %2 = 0.4898258757782682170733218609 ? c %3 = 0.9591820206453842491187464098 ? s^3+c^3 %4 = 1.000000000000000000000000000 ? smcm('x + O('x^11)) %5 = [x - 1/6*x^4 + 2/63*x^7 - 13/2268*x^10 + O(x^11), 1 - 1/3*x^3 + 1/18*x^6 - 23/2268*x^9 + O(x^10)] @eprog The library syntax is \fun{GEN}{ellwp0}{GEN w, GEN z = NULL, long flag, long prec}. For $\fl = 0$, we also have \fun{GEN}{ellwp}{GEN w, GEN z, long prec}, and \fun{GEN}{ellwpseries}{GEN E, long v, long precdl} for the power series in variable $v$. \subsec{ellxn$(E,n,\{v='x\})$}\kbdsidx{ellxn}\label{se:ellxn} For any affine point $P = (t,u)$ on the curve $E$, we have $$[n]P = (\phi_{n}(P)\psi_{n}(P) : \omega_{n}(P) : \psi_{n}(P)^{3})$$ for some $\phi_{n},\omega_{n},\psi_{n}$ in $\Z[a_{1},a_{2},a_{3},a_{4},a_{6}][t,u]$ modulo the curve equation. This function returns a pair $[A,B]$ of polynomials in $\Z[a_{1},a_{2},a_{3},a_{4},a_{6}][v]$ such that $[A(t),B(t)] = [\phi_{n}(P),\psi_{n}(P)^{2}]$ in the function field of $E$, whose quotient give the abscissa of $[n]P$. If $P$ is an $n$-torsion point, then $B(t) = 0$. \bprog ? E = ellinit([17,42]); [t,u] = [114,1218]; ? T = ellxn(E, 2, 'X) %2 = [X^4 - 34*X^2 - 336*X + 289, 4*X^3 + 68*X + 168] ? [a,b] = subst(T,'X,t); %3 = [168416137, 5934096] ? a / b == ellmul(E, [t,u], 2)[1] %4 = 1 @eprog The library syntax is \fun{GEN}{ellxn}{GEN E, long n, long v = -1} where \kbd{v} is a variable number. \subsec{ellzeta$(w,\{z='x\})$}\kbdsidx{ellzeta}\label{se:ellzeta} Computes the value at $z$ of the Weierstrass $\zeta$ function attached to the lattice $w$ as given by \tet{ellperiods}$(,1)$: including quasi-periods is useful, otherwise there are recomputed from scratch for each new $z$. $$ \zeta(z, L) = \dfrac{1}{z} + z^{2}\sum_{\omega\in L^{*}} \dfrac{1}{\omega^{2}(z-\omega)}.$$ It is also possible to directly input $w = [\omega_{1},\omega_{2}]$, or an elliptic curve $E$ as given by \kbd{ellinit} ($w = \kbd{E.omega}$). The quasi-periods of $\zeta$, such that $$\zeta(z + a\omega_{1} + b\omega_{2}) = \zeta(z) + a\eta_{1} + b\eta_{2} $$ for integers $a$ and $b$ are obtained as $\eta_{i} = 2\zeta(\omega_{i}/2)$. Or using directly \tet{elleta}. \bprog ? w = ellperiods([1,I],1); ? ellzeta(w, 1/2) %2 = 1.5707963267948966192313216916397514421 ? E = ellinit([1,0]); ? ellzeta(E, E.omega[1]/2) %4 = 0.84721308479397908660649912348219163647 @eprog\noindent One can also compute the series expansion around $z = 0$ (the quasi-periods are useless in this case): \bprog ? E = ellinit([0,1]); ? ellzeta(E) \\ at 'x, implicitly at default seriesprecision %4 = x^-1 + 1/35*x^5 - 1/7007*x^11 + O(x^15) ? ellzeta(E, x + O(x^20)) \\ explicit precision %5 = x^-1 + 1/35*x^5 - 1/7007*x^11 + 1/1440257*x^17 + O(x^18) @eprog\noindent The library syntax is \fun{GEN}{ellzeta}{GEN w, GEN z = NULL, long prec}. \subsec{ellztopoint$(E,z)$}\kbdsidx{ellztopoint}\label{se:ellztopoint} $E$ being an \var{ell} as output by \kbd{ellinit}, computes the coordinates $[x,y]$ on the curve $E$ corresponding to the complex or $p$-adic parameter $z$. Hence this is the inverse function of \kbd{ellpointtoz}. \item If $E$ is defined over a $p$-adic field and has multiplicative reduction, then $z$ is understood as an element on the Tate curve $\bar{Q}_{p}^{*} / q^{\Z}$. \bprog ? E = ellinit([0,-1,1,0,0], O(11^5)); ? [u2,u,q] = E.tate; type(u) %2 = "t_PADIC" \\ split multiplicative reduction ? z = ellpointtoz(E, [0,0]) %3 = 3 + 11^2 + 2*11^3 + 3*11^4 + 6*11^5 + 10*11^6 + 8*11^7 + O(11^8) ? ellztopoint(E,z) %4 = [O(11^9), O(11^9)] ? E = ellinit(ellfromj(1/4), O(2^6)); x=1/2; y=ellordinate(E,x)[1]; ? z = ellpointtoz(E,[x,y]); \\ nonsplit: t_POLMOD with t_PADIC coefficients ? P = ellztopoint(E, z); ? P[1] \\ y coordinate is analogous, more complicated %8 = Mod(O(2^4)*x + (2^-1 + O(2^5)), x^2 + (1 + 2^2 + 2^4 + 2^5 + O(2^7))) @eprog \item If $E$ is defined over the complex numbers (for instance over $\Q$), $z$ is understood as a complex number in $\C/\Lambda_{E}$. If the short Weierstrass equation is $y^{2} = 4x^{3} - g_{2}x - g_{3}$, then $[x,y]$ represents the Weierstrass $\wp$-function\sidx{Weierstrass $\wp$-function} and its derivative. For a general Weierstrass equation we have $$x = \wp(z) - b_{2}/12,\quad y = \wp'(z)/2 - (a_{1} x + a_{3})/2.$$ If $z$ is in the lattice defining $E$ over $\C$, the result is the point at infinity $[0]$. \bprog ? E = ellinit([0,1]); P = [2,3]; ? z = ellpointtoz(E, P) %2 = 3.5054552633136356529375476976257353387 ? ellwp(E, z) %3 = 2.0000000000000000000000000000000000000 ? ellztopoint(E, z) - P %4 = [2.548947057811923643 E-57, 7.646841173435770930 E-57] ? ellztopoint(E, 0) %5 = [0] \\ point at infinity @eprog The library syntax is \fun{GEN}{pointell}{GEN E, GEN z, long prec}. \subsec{genus2igusa$(\var{PQ},\{k\})$}\kbdsidx{genus2igusa}\label{se:genus2igusa} Let $PQ$ be a polynomial $P$, resp. a vector $[P,Q]$ of polynomials defined over a field $F$ of characteristic $\neq 2$. Returns the Igusa invariants $[J_{2},J_{4},J_{6},J_{8},J_{10}]$ of the hyperelliptic curve $C/F$, defined by the equation $y^{2} = P(x)$, resp. $y^{2} + Q(x)*y = P(x)$. If $k$ is given, only return the invariant of degree $k$ ($k$ must be even between $2$ and $10$). \bprog ? genus2igusa(x^5+3*x^2-4) %1 = [0, 9600, 20736, -23040000, 177926144] ? genus2igusa([x^6+x^5-x^4+3*x^3+x^2-2*x+1,x^3-x^2+x-1]) %2 = [-788, 1958, 341220, -68178781, -662731520] ? genus2igusa([x^6+x^5-x^4+3*x^3+x^2-2*x+1,x^3-x^2+x-1],4) %3 = 1958 ? genus2igusa(x^5+3*Mod(a,a^2-3)*x^2-4) \\ @com{over $\Q(\sqrt{3})$} %4 = [Mod(0, a^2 - 3), Mod(9600*a, a^2 - 3), Mod(186624, a^2 - 3), Mod(-69120000, a^2 - 3), Mod(-241864704*a + 204800000, a^2 - 3)] ? a = ffgen(3^4,'a); \\ @com{over $\F_{3^4} = \F_3[a]$} ? genus2igusa(x^6+a*x^5-a*x^4+2*x^3+a*x+a+1) %6 = [2*a^2, a^3 + a^2 + a + 1, a^2 + a + 2, 2*a^3 + 2*a^2 + a + 1, 2*a^2 + 2] ? a = ffgen(2^4,'a); \\ @com{$\F_{2^4} = \F_2[a]$} ? genus2igusa(x^6+a*x^5+a*x^4+a*x+a+1) \\ doesn't work in characteristic 2 *** at top-level: genus2igusa(x^6+a*x^5+a*x^4+a*x+a+1) *** ^------------------------------------ *** genus2igusa: impossible inverse in FF_mul2n: 2. @eprog The library syntax is \fun{GEN}{genus2igusa}{GEN PQ, long k}. \subsec{genus2red$(\var{PQ},\{p\})$}\kbdsidx{genus2red}\label{se:genus2red} Let $PQ$ be a polynomial $P$, resp. a vector $[P,Q]$ of polynomials, with rational coefficients. Determines the reduction at $p > 2$ of the (proper, smooth) genus~2 curve $C/\Q$, defined by the hyperelliptic equation $y^{2} = P(x)$, resp. $y^{2} + Q(x)*y = P(x)$. (The special fiber $X_{p}$ of the minimal regular model $X$ of $C$ over $\Z$.) If $p$ is omitted, determines the reduction type for all (odd) prime divisors of the discriminant. \noindent This function was rewritten from an implementation of Liu's algorithm by Cohen and Liu (1994), \kbd{genus2reduction-0.3}, see \url{https://www.math.u-bordeaux.fr/~liu/G2R/}. \misctitle{CAVEAT} The function interface may change: for the time being, it returns $[N,\var{FaN}, [P_{m}, Q_{m}], V]$ where $N$ is either the local conductor at $p$ or the global conductor, \var{FaN} is its factorization, $y^{2} +Q_{m}\*y= P_{m}$ defines a minimal model over $\Z$ and $V$ describes the reduction type at the various considered~$p$. Unfortunately, the program is not complete for $p = 2$, and we may return the odd part of the conductor only: this is the case if the factorization includes the (impossible) term $2^{-1}$; if the factorization contains another power of $2$, then this is the exact local conductor at $2$ and $N$ is the global conductor. \bprog ? default(debuglevel, 1); ? genus2red(x^6 + 3*x^3 + 63, 3) (potential) stable reduction: [1, []] reduction at p: [III{9}] page 184, [3, 3], f = 10 %1 = [59049, Mat([3, 10]), x^6 + 3*x^3 + 63, [3, [1, []], ["[III{9}] page 184", [3, 3]]]] ? [N, FaN, T, V] = genus2red(x^3-x^2-1, x^2-x); \\ X_1(13), global reduction p = 13 (potential) stable reduction: [5, [Mod(0, 13), Mod(0, 13)]] reduction at p: [I{0}-II-0] page 159, [], f = 2 ? N %3 = 169 ? FaN %4 = Mat([13, 2]) \\ in particular, good reduction at 2 ! ? T %5 = x^6 + 58*x^5 + 1401*x^4 + 18038*x^3 + 130546*x^2 + 503516*x + 808561 ? V %6 = [[13, [5, [Mod(0, 13), Mod(0, 13)]], ["[I{0}-II-0] page 159", []]]] @eprog\noindent We now first describe the format of the vector $V = V_{p}$ in the case where $p$ was specified (local reduction at~$p$): it is a triple $[p, \var{stable}, \var{red}]$. The component $\var{stable} = [\var{type}, \var{vecj}]$ contains information about the stable reduction after a field extension; depending on \var{type}s, the stable reduction is \item 1: smooth (i.e. the curve has potentially good reduction). The Jacobian $J(C)$ has potentially good reduction. \item 2: an elliptic curve $E$ with an ordinary double point; \var{vecj} contains $j$ mod $p$, the modular invariant of $E$. The (potential) semi-abelian reduction of $J(C)$ is the extension of an elliptic curve (with modular invariant $j$ mod $p$) by a torus. \item 3: a projective line with two ordinary double points. The Jacobian $J(C)$ has potentially multiplicative reduction. \item 4: the union of two projective lines crossing transversally at three points. The Jacobian $J(C)$ has potentially multiplicative reduction. \item 5: the union of two elliptic curves $E_{1}$ and $E_{2}$ intersecting transversally at one point; \var{vecj} contains their modular invariants $j_{1}$ and $j_{2}$, which may live in a quadratic extension of $\F_{p}$ and need not be distinct. The Jacobian $J(C)$ has potentially good reduction, isomorphic to the product of the reductions of $E_{1}$ and $E_{2}$. \item 6: the union of an elliptic curve $E$ and a projective line which has an ordinary double point, and these two components intersect transversally at one point; \var{vecj} contains $j$ mod $p$, the modular invariant of $E$. The (potential) semi-abelian reduction of $J(C)$ is the extension of an elliptic curve (with modular invariant $j$ mod $p$) by a torus. \item 7: as in type 6, but the two components are both singular. The Jacobian $J(C)$ has potentially multiplicative reduction. The component $\var{red} = [\var{NUtype}, \var{neron}]$ contains two data concerning the reduction at $p$ without any ramified field extension. The \var{NUtype} is a \typ{STR} describing the reduction at $p$ of $C$, following Namikawa-Ueno, \emph{The complete classification of fibers in pencils of curves of genus two}, Manuscripta Math., vol. 9, (1973), pages 143-186. The reduction symbol is followed by the corresponding page number or page range in this article. The second datum \var{neron} is the group of connected components (over an algebraic closure of $\F_{p}$) of the N\'eron model of $J(C)$, given as a finite abelian group (vector of elementary divisors). \smallskip If $p = 2$, the \var{red} component may be omitted altogether (and replaced by \kbd{[]}, in the case where the program could not compute it. When $p$ was not specified, $V$ is the vector of all $V_{p}$, for all considered $p$. \misctitle{Notes about Namikawa-Ueno types} \item A lower index is denoted between braces: for instance, \kbd{[I\obr2\cbr-II-5]} means \kbd{[I\_2-II-5]}. \item If $K$ and $K'$ are Kodaira symbols for singular fibers of elliptic curves, then \kbd{[$K$-$K'$-m]} and \kbd{[$K'$-$K$-m]} are the same. We define a total ordering on Kodaira symbol by fixing $\kbd{I} < \kbd{I*} < \kbd{II} < \kbd{II*}, \dots$. If the reduction type is the same, we order by the number of components, e.g. $\kbd{I}_{2} < \kbd{I}_{4}$, etc. Then we normalize our output so that $K \leq K'$. \item \kbd{[$K$-$K'$-$-1$]} is \kbd{[$K$-$K'$-$\alpha$]} in the notation of Namikawa-Ueno. \item The figure \kbd{[2I\_0-m]} in Namikawa-Ueno, page 159, must be denoted by \kbd{[2I\_0-(m+1)]}. The library syntax is \fun{GEN}{genus2red}{GEN PQ, GEN p = NULL}. \subsec{hyperellchangecurve$(C,m)$}\kbdsidx{hyperellchangecurve}\label{se:hyperellchangecurve} $C$ being a nonsingular hyperelliptic model of a curve, apply the change of coordinate given by $m = [e, [a,b;c,d], H]$. If $(x,y)$ is a point on the new model, the corresponding point $(X,Y)$ on $C$ is given by $$ X = (a*x + b) / (c*x + d), \quad Y = e (y + H(x)) / (c*x + d)^{g+1}. $$ $C$ can be given either by a squarefree polynomial $P$ such that $C: y^{2} = P(x)$ or by a vector $[P,Q]$ such that $C: y^{2} + Q(x)\*y = P(x)$ and $Q^{2}+4\*P$ is squarefree. The library syntax is \fun{GEN}{hyperellchangecurve}{GEN C, GEN m}. \subsec{hyperellcharpoly$(X)$}\kbdsidx{hyperellcharpoly}\label{se:hyperellcharpoly} $X$ being a nonsingular hyperelliptic curve defined over a finite field, return the characteristic polynomial of the Frobenius automorphism. $X$ can be given either by a squarefree polynomial $P$ such that $X: y^{2} = P(x)$ or by a vector $[P,Q]$ such that $X: y^{2} + Q(x)\*y = P(x)$ and $Q^{2}+4\*P$ is squarefree. The library syntax is \fun{GEN}{hyperellcharpoly}{GEN X}. \subsec{hyperelldisc$(X)$}\kbdsidx{hyperelldisc}\label{se:hyperelldisc} $X$ being a nonsingular hyperelliptic model of a curve, defined over a field of characteristic distinct from 2, returns its discriminant. $X$ can be given either by a squarefree polynomial $P$ such that $X$ has equation $y^{2} = P(x)$ or by a vector $[P,Q]$ such that $X$ has equation $y^{2} + Q(x)\*y = P(x)$ and $Q^{2}+4\*P$ is squarefree. \bprog ? hyperelldisc([x^3,1]) %1 = -27 ? hyperelldisc(x^5+1) %2 = 800000 @eprog The library syntax is \fun{GEN}{hyperelldisc}{GEN X}. \subsec{hyperellisoncurve$(X,p)$}\kbdsidx{hyperellisoncurve}\label{se:hyperellisoncurve} $X$ being a nonsingular hyperelliptic model of a curve, test whether the point $p$ is on the curve. $X$ can be given either by a squarefree polynomial $P$ such that $X: y^{2} = P(x)$ or by a vector $[P,Q]$ such that $X: y^{2} + Q(x)\*y = P(x)$ and $Q^{2}+4\*P$ is squarefree. \bprog ? W = [2*x^6+3*x^5+x^4+x^3-x,x^3+1]; p = [px, py] = [1/3,-14/27]; ? hyperellisoncurve(W, p) %2 = 1 ? [Px,Qx]=subst(W,x,px); py^2+py*Qx == Px %3 = 1 @eprog The library syntax is \fun{int}{hyperellisoncurve}{GEN X, GEN p}. \subsec{hyperellminimaldisc$(C,\{\var{pr}\})$}\kbdsidx{hyperellminimaldisc}\label{se:hyperellminimaldisc} $C$ being a nonsingular integral hyperelliptic model of a curve, return the minimal discriminant of an integral model of $C$. If $pr$ is given, it must be a list of primes and the discriminant is then only garanteed minimal at the elements of $pr$. $C$ can be given either by a squarefree polynomial $P$ such that $C: y^{2} = P(x)$ or by a vector $[P,Q]$ such that $C: y^{2} + Q(x)\*y = P(x)$ and $Q^{2}+4\*P$ is squarefree. \bprog ? W = [x^6+216*x^3+324,0]; ? D = hyperelldisc(W) %2 = 1828422898924853919744000 ? M = hyperellminimaldisc(W) %4 = 29530050606000 @eprog The library syntax is \fun{GEN}{hyperellminimaldisc}{GEN C, GEN pr = NULL}. \subsec{hyperellminimalmodel$(C,\{\&m\},\{\var{pr}\})$}\kbdsidx{hyperellminimalmodel}\label{se:hyperellminimalmodel} $C$ being a nonsingular integral hyperelliptic model of a curve, return an integral model of $C$ with minimal discriminant. If $pr$ is given, it must be a list of primes and the model is then only garanteed minimal at the elements of $pr$. If present, $m$ is set to the mapping from the original model to the new one: a three-component vector $[e,[a,b;c,d],H]$ such that if $(x,y)$ is a point on $W$, the corresponding point on $C$ is given by $$ x_{C} = (a*x+b)/(c*x+d) $$ $$ y_{C} = (e*y+H(x))/(c*x+d)^{g+1} $$ where $g$ is the genus. $C$ can be given either by a squarefree polynomial $P$ such that $C: y^{2} = P(x)$ or by a vector $[P,Q]$ such that $C: y^{2} + Q(x)\*y = P(x)$ and $Q^{2}+4\*P$ is squarefree. \bprog ? W = [x^6+216*x^3+324,0]; ? D = hyperelldisc(W) %2 = 1828422898924853919744000 ? Wn = hyperellminimalmodel(W,&M) %3 = [2*x^6+18*x^3+1,x^3]; ? M %4 = [18, [3, 0; 0, 1], 9*x^3] ? hyperelldisc(Wn) %5 = 29530050606000 ? hyperellchangecurve(W, M) %6 = [2*x^6+18*x^3+1,x^3] @eprog The library syntax is \fun{GEN}{hyperellminimalmodel}{GEN C, GEN *m = NULL, GEN pr = NULL}. \subsec{hyperellordinate$(H,x)$}\kbdsidx{hyperellordinate}\label{se:hyperellordinate} Gives a 0, 1 or 2-component vector containing the $y$-coordinates of the points of the curve $H$ having $x$ as $x$-coordinate. The library syntax is \fun{GEN}{hyperellordinate}{GEN H, GEN x}. \subsec{hyperellpadicfrobenius$(Q,q,n)$}\kbdsidx{hyperellpadicfrobenius}\label{se:hyperellpadicfrobenius} Let $X$ be the curve defined by $y^{2}=Q(x)$, where $Q$ is a polynomial of degree $d$ over $\Q$ and $q\ge d$ is a prime such that $X$ has good reduction at $q$. Return the matrix of the Frobenius endomorphism $\varphi$ on the crystalline module $D_{p}(X) = \Q_{p} \otimes H^{1}_{dR}(X/\Q)$ with respect to the basis of the given model $(\omega, x\*\omega,\ldots,x^{g-1}\*\omega)$, where $\omega = dx/(2\*y)$ is the invariant differential, where $g$ is the genus of $X$ (either $d=2\*g+1$ or $d=2\*g+2$). The characteristic polynomial of $\varphi$ is the numerator of the zeta-function of the reduction of the curve $X$ modulo $q$. The matrix is computed to absolute $q$-adic precision $q^{n}$. Alternatively, $q$ may be of the form $[T,p]$ where $p$ is a prime, $T$ is a polynomial with integral coefficients whose projection to $\F_{p}[t]$ is irreducible, $X$ is defined over $K = \Q[t]/(T)$ and has good reduction to the finite field $\F_{q} = \F_{p}[t]/(T)$. The matrix of $\varphi$ on $D_{q}(X) = \Q_{q} \otimes H^{1}_{dR}(X/K)$ is computed to absolute $p$-adic precision $p^{n}$. \bprog ? M=hyperellpadicfrobenius(x^5+'a*x+1,['a^2+1,3],10); ? liftall(M) [48107*a + 38874 9222*a + 54290 41941*a + 8931 39672*a + 28651] [ 21458*a + 4763 3652*a + 22205 31111*a + 42559 39834*a + 40207] [ 13329*a + 4140 45270*a + 25803 1377*a + 32931 55980*a + 21267] [15086*a + 26714 33424*a + 4898 41830*a + 48013 5913*a + 24088] ? centerlift(simplify(liftpol(charpoly(M)))) %8 = x^4+4*x^2+81 ? hyperellcharpoly((x^5+Mod(a,a^2+1)*x+1)*Mod(1,3)) %9 = x^4+4*x^2+81 @eprog The library syntax is \fun{GEN}{hyperellpadicfrobenius0}{GEN Q, GEN q, long n}. The functions \fun{GEN}{hyperellpadicfrobenius}{GEN H, ulong p, long n} and \fun{GEN}{nfhyperellpadicfrobenius}{GEN H, GEN T, ulong p, long n} are also available. \subsec{hyperellratpoints$(X,h,\{\fl=0\})$}\kbdsidx{hyperellratpoints}\label{se:hyperellratpoints} $X$ being a nonsingular hyperelliptic curve given by an rational model, return a vector containing the affine rational points on the curve of naive height less than $h$. If $\fl=1$, stop as soon as a point is found; return either an empty vector or a vector containing a single point. $X$ is given either by a squarefree polynomial $P$ such that $X: y^{2}=P(x)$ or by a vector $[P,Q]$ such that $X: y^{2}+Q(x)\*y=P(x)$ and $Q^{2}+4\*P$ is squarefree. \noindent The parameter $h$ can be \item an integer $H$: find the points $[n/d,y]$ whose abscissas $x = n/d$ have naive height (= $\max(|n|, d)$) less than $H$; \item a vector $[N,D]$ with $D\leq N$: find the points $[n/d,y]$ with $|n| \leq N$, $d \leq D$. \item a vector $[N,[D_{1},D_{2}]]$ with $D_{1} 0$. Return an integral model of $C$ with the same discriminant but small coefficients, using Cremona-Stoll reduction. The optional argument $m$ is set to the mapping from the original model to the new one, given by a three-component vector \kbd{[1,[a,b;c,d],H]} such that $a*d-b*c=1$ and if $(x,y)$ is a point on $W$, the corresponding point $(X,Y)$ on $C$ is given by $$ X = (a*x + b) / (c*x + d), \quad Y = (y + H(x)) / (c*x + d)^{g+1}. $$ $C$ can be given either by a squarefree polynomial $P$ such that $C: y^{2} = P(x)$ or by a vector $[P,Q]$ such that $C: y^{2} + Q(x)\*y = P(x)$ and $Q^{2}+4\*P$ is squarefree. \bprog ? P = 1001*x^4 + 3704*x^3 + 5136*x^2 + 3163*x + 730; ? hyperellred(P, &m) %2 = [x^3 + 1, 0] ? hyperellchangecurve(P, m) %3 = [x^3 + 1, 0] @eprog The library syntax is \fun{GEN}{hyperellred}{GEN C, GEN *m = NULL}. Also available is \fun{GEN}{ZX_hyperellred}{GEN P, GEN *M} where $C: y^{2} = P(x)$ and *M is set to \kbd{[a,b;c,d]} \section{Hypergeometric Motives} \subsec{Templates} %GPHELPskip A \emph{hypergeometric template} is a pair of multisets (i.e., sets with possibly repeated elements) of rational numbers $(\alpha_{1},\dots,\alpha_{d})$ and $(\beta_{1},\dots,\beta_{d})$ having the same number of elements, and we set $$A(x)=\prod_{1\le j\le d}(x-e^{2\pi i\alpha_{j}}),\quad B(x)=\prod_{1\le k\le d}(x-e^{2\pi i\beta_{k}})\;.$$ We make the following assumptions: \item $\alpha_{j}-\beta_{k}\notin\Z$ for all $j$ and $k$, or equivalently $\gcd(A,B)=1$. \item $\alpha_{j}\notin\Z$ for all $j$, or equivalently $A(1)\ne0$. \item our template is \emph{defined over $\Q$}, in other words $A,B\in\Z[x]$, or equivalently if some $a/D$ with $\gcd(a,D)=1$ occurs in the $\alpha_{j}$ or $\beta_{k}$, then all the $b/D$ modulo $1$ with $\gcd(b,D)=1$ also occur. The last assumption allows to abbreviate $[a_{1}/D,\dots,a_{\phi(D)}/D]$ (where the $a_{i}$ range in $(\Z/D\Z)^{*}$) to $[D]$. We thus have two possible ways of giving a hypergeometric template: either by the two vectors $[\alpha_{1},\dots,\alpha_{d}]$ and $[\beta_{1},\dots,\beta_{d}]$, or by their denominators $[D_{1},\dots,D_{m}]$ and $[E_{1},\dots,E_{n}]$ , which are called the \emph{cyclotomic parameters}; note that $\sum_{j}\phi(D_{j}) = \sum_{k}\phi(E_{k}) = d$. A third way is to give the \emph{gamma vector} $(\gamma_{n})$ defined by $A(X)/B(X)=\prod_{n}(X^{n}-1)^{\gamma_{n}}$, which satisfies $\sum_{n} n\gamma_{n}=0$. To any such data we associate a hypergeometric template using the function \kbd{hgminit}; then the $\alpha_{j}$ and $\beta_{k}$ are obtained using \kbd{hgmalpha}, cyclotomic parameters using \kbd{hgmcyclo} and the gamma vectors using \kbd{hgmgamma}. To such a hypergeometric template is associated a number of additional parameters, for which we do not give the definition but refer to the survey \emph{Hypergeometric Motives} by Roberts and Villegas, \kbd{https://arxiv.org/abs/2109.00027}: the degree $d$, the \emph{weight} $w$, a \emph{Hodge polynomial}~$P$, a \emph{Tate twist} $T$, and a normalizing M-factor $M = \prod_{n} n^{n\gamma_{n}}$. The \kbd{hgmparams} function returns $$[d,w,[P,T],M]\;.$$ Example with cyclotomic parameters $[5],[1,1,1,1]$: \bprog ? H = hgminit([5]); \\ [1,1,1,1] can be omitted ? hgmparams(H) %2 = [4, 3, [x^3+x^2+x+1,0], 3125] ? hgmalpha(H) %3 = [[1/5, 2/5, 3/5, 4/5], [0, 0, 0, 0]] ? hgmcyclo(H) %4 = [Vecsmall([5]), Vecsmall([1, 1, 1, 1])] ? hgmgamma(H) %5 = Vecsmall([-5,0,0,0,1]) \\ A/B = (x^5-1) / (x-1)^5 @eprog \subsec{Motives} %GPHELPskip A \emph{hypergeometric motive} (HGM for short) is a pair $(H,t)$, where $H$ is a hypergeometric template and $t\in\Q^{*}$. To such a motive and a finite field $\F_{q}$ one can associate via an explicit but complicated formula an \emph{integer} $N(H,t; q)$, see Beukers, Cohen and Mellit, \emph{Finite hypergeometric functions} Pure and Applied Math Quarterly 11 (2015), pp 559 - 589, \kbd{https://arxiv.org/abs/1505.02900}. \misctitle{Warning} Depending on the authors, $t$ may have to be replaced with $1/t$. The \kbd{Pari/GP} convention is the same as the one in \kbd{Magma}, but is the inverse of the one in the last reference. This formula does not make sense and is not valid for \emph{bad primes}~$p$: a \emph{wild prime} is a prime which divides a denominator of the $\alpha_{j}$ or $\beta_{i}$. If a prime $p$ is not wild, it can be \emph{good} if $v_{p}(t)=v_{p}(t-1)=0$, or \emph{tame} otherwise. The \emph{local Euler factor} $P_{p}$ at a good prime $p$ is then given by the usual formula $$-\log P_{p}(T) = \sum_{f\ge1} \dfrac{N(H,t; p^{f}) T^{f}}{f} \;,$$ and in the case of HGM's $P_{p}$ is always a polynomial (note that the Euler factor used in the global $L$-function is $1/P_{p}(p^{-s})$). At a tame prime $p$ it is necessary to modify the above formula, and usually (but not always) the degree of the local Euler factor decreases. Wild primes are currently not implemented by a formula but can be guessed via the global functional equation (see the next section). Continuing the previous example, we find \bprog ? hgmeulerfactor(H, -1, 3) \\ good prime %4 = 729*x^4 + 135*x^3 + 45*x^2 + 5*x + 1 ? hgmeulerfactor(H, -1, 2) \\ tame prime %5 = 16*x^3 + 6*x^2 + x + 1 ? hgmeulerfactor(H, -1, 5) \\ wild primes not implemented %6 = 0 @eprog\noindent To obtain the Euler factor at wild primes, use \kbd{lfuneuler} once the global $L$-function is computed. \subsec{The Global $L$-function} %GPHELPskip A theorem of Katz tells us that if one suitably defines $P_{p}(T)$ for all primes $p$ including the wild ones, then the $L$-function defined by $L(H,s)=\prod_{p} P_{p}(p^{-s})^{-1}$ is motivic, with analytic continuation and functional equation, as used in the $L$-function package of \kbd{Pari/GP}. The command \kbd{L = lfunhgm(H,t)} creates such an $L$-function. In particular it must guess the local Euler factors at wild primes, which can be very expensive when the conductor \kbd{lfunparams}$(L)[1]$ is large. In our example, \kbd{L = lfunhgm(H,1/64)} finishes in about 20 seconds (the conductor is only 525000); this $L$-function can then be used with all the functions of the \kbd{lfun} package. For instance we can now obtain the global conductor and check the Euler factors at all bad primes: \bprog ? [N] = lfunparams(L); N \\ the conductor %7 = 525000 ? factor(N) %8 = [2 3] [3 1] [5 5] [7 1] ? lfuneuler(L,2) %9 = 1/(-x + 1) ? lfuneuler(L,3) %10 = 1/(81*x^3 + 6*x^2 - 4*x + 1) ? lfuneuler(L,5) %11 = 1 ? lfuneuler(L,7) %12 = 1/(2401*x^3 + 301*x^2 + x + 1) @eprog Two additional functions related to the global $L$-function are available which do \emph{not} require its full initialization: \kbd{hgmcoefs(H,t,n)} computes the first $n$ coefficients of the $L$-function by setting all wild Euler factors to $1$; this will be identical to \kbd{lfunan(L,n)} when this is indeed the case (as in the above example: only $5$ is wild), otherwise all coefficients divisible by a wild prime will be wrong. The second is the function \kbd{hgmcoef(H,t,n)} which only computes the $n$th coefficient of the global $L$-function. It gives an error if $n$ is divisible by a wild prime. Compare \kbd{hgmcoefs(H,1/64,7\^{}6)[7\^{}6]} which requires more than 1 minute (it computes more than 100000 coefficients), with \kbd{hgmcoef(H,1/64,7\^{}6)} which outputs $-25290600$ instantaneously. \subsec{hgmalpha$(H)$}\kbdsidx{hgmalpha}\label{se:hgmalpha} Returns the alpha and beta parameters of the hypergeometric motive template $H$. \bprog ? H = hgminit([5]); \\ template given by cyclotomic parameters ? hgmalpha(H) %2 = [[1/5, 2/5, 3/5, 4/5], [0, 0, 0, 0]] @eprog The library syntax is \fun{GEN}{hgmalpha}{GEN H}. \subsec{hgmbydegree$(n)$}\kbdsidx{hgmbydegree}\label{se:hgmbydegree} Outputs $[L(0),...,L(n-1)]$ where $L(w)$ is the list of cyclotomic parameters of all possible hypergeometric motive templates of degree $n$ and weight $w$. The library syntax is \fun{GEN}{hgmbydegree}{long n}. \subsec{hgmcoef$(H,t,n)$}\kbdsidx{hgmcoef}\label{se:hgmcoef} $(H,t)$ being a hypergeometric motive, returns the $n$-th coefficient of its $L$-function. This is not implemented for wild primes $p$ and will raise an exception if such a $p$ divides~$n$. The library syntax is \fun{GEN}{hgmcoef}{GEN H, GEN t, GEN n}. \subsec{hgmcoefs$(H,t,n)$}\kbdsidx{hgmcoefs}\label{se:hgmcoefs} $(H,t)$ being a hypergeometric motive, returns the first $n$ coefficients of its $L$-function, where Euler factors at wild primes are set to 1. The argument $t$ may be replaced by $[t,\var{bad}]$ where \var{bad} is a vector of pairs $[p,L_{p}]$, $p$ being a prime and $L_{p}$ being the corresponding local Euler factor, overriding the default. If you hope that the wild Euler factors can be computed not too slowly from the functional equation, you can also set \kbd{L=lfunhgm(H,t)}, and then \kbd{lfunan(L,n)}, and then the Euler factors at wild primes should be correct. The library syntax is \fun{GEN}{hgmcoefs}{GEN H, GEN t, long n}. \subsec{hgmcyclo$(H)$}\kbdsidx{hgmcyclo}\label{se:hgmcyclo} Returns the cyclotomic parameters $(D,E)$ of the hypergeometric motive template $H$. \bprog \\ template given by alpha (implied beta is [0,0,0,0]) ? H = hgminit([1/5, 2/5, 3/5, 4/5]); ? hgmcyclo(H) %3 = [Vecsmall([5]), Vecsmall([1, 1, 1, 1])] ? apply(Vec, %) \\ for readability %4 = [[5], [1, 1, 1, 1]] @eprog The library syntax is \fun{GEN}{hgmcyclo}{GEN H}. \subsec{hgmeulerfactor$(H,t,p,\{\&e\})$}\kbdsidx{hgmeulerfactor}\label{se:hgmeulerfactor} $(H,t)$ being a hypergeometric motive, returns the inverse of its Euler factor at the prime $p$ and the exponent $e$ of the conductor at $p$. This is not implemented when $p$ is a wild prime: the function returns $0$ and sets $e$ to $-1$. Caveat: contrary to \kbd{lfuneuler}, this function returns the \emph{inverse} of the Euler factor, given by a polynomial $P_{p}$ such that the Euler factor is $1 / P_{p}(p^{-s})$. \bprog ? H = hgminit([5]); \\ cyclotomic parameters [5] and [1,1,1,1] ? hgmeulerfactor(H, 1/2, 3) %2 = 729*x^4 + 135*x^3 + 45*x^2 + 5*x + 1 ? hgmeulerfactor(H, 1/2, 3, &e) %3 = 729*x^4 + 135*x^3 + 45*x^2 + 5*x + 1 ? e %4 = 0 ? hgmeulerfactor(H, 1/2, 2, &e) %5 = -x + 1 ? e %6 = 3 ? hgmeulerfactor(H, 1/2, 5) %7 = 0 \\ 5 is wild @eprog If the conductor is small, the wild Euler factors can be computed from the functional equation: set \kbd{L = lfunhgm(H,t)} (the complexity should be roughly proportional to the conductor) then the \kbd{lfuneuler} function should give you the correct Euler factors at all primes: \bprog ? L = lfunhgm(H, 1/2); time = 790 ms. \\ fast in this case, only 5 is wild ? lfunparams(L) \\ ... and the conductor 5000 is small %8 = [5000, 4, [-1, 0, 0, 1]] ? lfuneuler(L, 5) %9 = 1 \\ trivial Euler factor ? L = lfunhgm(H, 1/64); lfunparams(L) time = 20,122 ms. \\ slower: the conductor is larger %10 = [525000, 4, [-1, 0, 0, 1]] ? L = lfunhgm(H, 1/128); lfunparams(L) time = 2min, 16,205 ms. \\ even slower, etc. %11 = [3175000, 4, [-1, 0, 0, 1]] @eprog The library syntax is \fun{GEN}{hgmeulerfactor}{GEN H, GEN t, long p, GEN *e = NULL}. \subsec{hgmgamma$(H)$}\kbdsidx{hgmgamma}\label{se:hgmgamma} Returns the gamma vector of the hypergeometric motive template $H$. \bprog ? H = hgminit([5]); ? hgmgamma(H) %2 = Vecsmall([-5, 0, 0, 0, 1]) @eprog The library syntax is \fun{GEN}{hgmgamma}{GEN H}. \subsec{hgminit$(a,\{b\})$}\kbdsidx{hgminit}\label{se:hgminit} Create the template for the hypergeometric motive with parameters $a$ and possibly $b$. The format of the parameters may be \item alpha: lists of rational numbers $a=(\alpha_{j})$ and $b=(\beta_{k})$ of the same length (and defined over~$\Q$); if $b$ is omitted, we take it to be $(0,\dots,0)$. \item cyclo: lists $a=D$ and $b=E$ of positive integers corresponding to the denominators of the $(\alpha_{i})$ and $(\beta_{i})$; if $b$ is omitted we take it to be $(1,\dots,1)$. This is the simplest and most compact input format. \item gamma: list of $\gamma_{n}$ such that the $\prod_{j}(x-\exp(2\pi i\alpha_{j})) / \prod_{k}(x-\exp(2\pi i\beta_{k})) = \prod_{n}(x^{n}-1)^{\gamma_{n}}$. The hypergeometric motive itself is given by a pair $(H,t)$, where $H$ is a template as above and $t\in \Q^{*}$. Note that the motives given by $(\alpha, \beta; t)$ and $(\beta,\alpha; 1/t)$ are identical. \bprog ? H = hgminit([5]); \\ template given by cyclotomic parameters 5 and 1,1,1,1 ? L = lfunhgm(H, 1); \\ global L-function attached to motive (H,1) ? lfunparams(L) %3 = [25, 4, [0, 1]] ? hgmalpha(H) %4 = [[1/5, 2/5, 3/5, 4/5], [0, 0, 0, 0]] ? hgmgamma(H) %5 = Vecsmall([-5, 0, 0, 0, 1]) @eprog The library syntax is \fun{GEN}{hgminit}{GEN a, GEN b = NULL}. \subsec{hgmissymmetrical$(H)$}\kbdsidx{hgmissymmetrical}\label{se:hgmissymmetrical} Is the hypergeometric motive template $H$ symmetrical at $t=1$? This means that the $\alpha_{j}$ and $\beta_{k}$ defining the template are obtained from one another by adding $1/2$ (modulo $1$), see \kbd{hgmtwist}. \bprog ? H = hgminit([2,2]); ? hgmalpha(H) %2 = [[1/2, 1/2], [0, 0]] ? hgmissymmetrical(H) %3 = 1 \\ this template is symmetrical ? H = hgminit([5]); ? hgmalpha(H) %5 = [[1/5, 2/5, 3/5, 4/5], [0, 0, 0, 0]] ? hgmissymmetrical(H) %6 = 1 \\ this one is not @eprog The library syntax is \fun{long}{hgmissymmetrical}{GEN H}. \subsec{hgmparams$(H)$}\kbdsidx{hgmparams}\label{se:hgmparams} $H$ being a hypergeometric motive template, returns $[d,w,[P,T], M]$, where $d$ is the degree, $w$ the weight, $P$ the Hodge polynomial, and $T$ the Tate twist number (so that the Hodge function itself is $P/x^{T}$); finally the normalizing factor $M$ is the so-called $M$-value, $M = \prod_{n} n^{n\gamma_{n}}$. The library syntax is \fun{GEN}{hgmparams}{GEN H}. \subsec{hgmtwist$(H)$}\kbdsidx{hgmtwist}\label{se:hgmtwist} Twist by $1/2$ of alpha and beta of the hypergeometric motive template $H$. \bprog ? H = hgminit([5]); ? hgmalpha(H) %2 = [[1/5, 2/5, 3/5, 4/5], [0, 0, 0, 0]] ? H2 = hgmtwist(H); ? hgmalpha(H2) %4 = [[1/10, 3/10, 7/10, 9/10], [1/2, 1/2, 1/2, 1/2]] @eprog\noindent The template is symmetrical (\kbd{hgmissymmetrical}) if it is equal to its twist. The library syntax is \fun{GEN}{hgmtwist}{GEN H}. \subsec{lfunhgm$(H,t,\{\var{hint}\})$}\kbdsidx{lfunhgm}\label{se:lfunhgm} $(H,t)$ being a hypergeometric motive, returns the corresponding \kbd{lfuncreate} data for use with the $L$-function package. This function needs to guess local conductors and euler factors at wild primes and will be very costly if there are many such primes: the complexity is roughly proportional to the conductor. The optional parameter \kbd{hint} allows to speed up the function by making various assumptions: \item $\kbd{hint} = \var{lim}$ a \typ{INT}: assume that Euler factors at wild primes have degree less than \var{lim}, which may speed it up a little. \item $\kbd{hint} = [N]$: guess that the conductor is $N$. \item $\kbd{hint} = [N, \var{lim}]$: initial guess $N$ for the conductor and limit degrees to \var{lim}. If your guess for \var{lim} is wrong, the function will enter an infinite loop. If your guess for an initial $N$ is wrong, the function silently restarts (it will not enter an infinite loop unless a simultaneous failed guess for \var{lim} is made). \bprog ? H = hgminit([5]); ? L = lfunhgm(H, 1/64); time = 23,113 ms. ? L=lfunhgm(H,1/64,0); \\ assume Euler factors at wild primes are trivial time = 19,721 ms. \\ a little faster ? L=lfunhgm(H,1/64,[525000]); \\ initial guess N = 525000 time = 15,486 ms. \\ a little faster ? L=lfunhgm(H,1/64,[525000, 0]); time = 15,293 ms. \\ marginally faster with both assumptions @eprog The library syntax is \fun{GEN}{lfunhgm}{GEN H, GEN t, GEN hint = NULL, long bitprec}. \section{$L$-functions} This section describes routines related to $L$-functions. We first introduce the basic concept and notations, then explain how to represent them in GP. Let $\Gamma_{\R}(s) = \pi^{-s/2}\Gamma(s/2)$, where $\Gamma$ is Euler's gamma function. Given $d \geq 1$ and a $d$-tuple $A=[\alpha_{1},\dots,\alpha_{d}]$ of complex numbers, we let $\gamma_{A}(s) = \prod_{\alpha \in A} \Gamma_{\R}(s + \alpha)$. Given a sequence $a = (a_{n})_{n\geq 1}$ of complex numbers (such that $a_{1} = 1$), a positive \emph{conductor} $N \in \Z$, and a \emph{gamma factor} $\gamma_{A}$ as above, we consider the Dirichlet series $$ L(a,s) = \sum_{n\geq 1} a_{n} n^{-s} $$ and the attached completed function $$ \Lambda(a,s) = N^{s/2}\gamma_{A}(s) \cdot L(a,s). $$ Such a datum defines an \emph{$L$-function} if it satisfies the three following assumptions: \item [Convergence] The $a_{n} = O_{\epsilon}(n^{k_{1}+\epsilon})$ have polynomial growth, equivalently $L(s)$ converges absolutely in some right half-plane $\Re(s) > k_{1} + 1$. \item [Analytic continuation] $L(s)$ has a meromorphic continuation to the whole complex plane with finitely many poles. \item [Functional equation] There exist an integer $k$, a complex number $\epsilon$ (usually of modulus~$1$), and an attached sequence $a^{*}$ defining both an $L$-function $L(a^{*},s)$ satisfying the above two assumptions and a completed function $\Lambda(a^{*},s) = N^{s/2}\gamma_{A}(s) \cdot L(a^{*},s)$, such that $$\Lambda(a,k-s) = \epsilon \Lambda(a^{*},s)$$ for all regular points. More often than not in number theory we have $a^{*} = \overline{a}$ (which forces $|\epsilon| = 1$), but this needs not be the case. If $a$ is a real sequence and $a = a^{*}$, we say that $L$ is \emph{self-dual}. We do not assume that the $a_{n}$ are multiplicative, nor equivalently that $L(s)$ has an Euler product. \misctitle{Remark} Of course, $a$ determines the $L$-function, but the (redundant) datum $a,a^{*}, A, N, k, \epsilon$ describes the situation in a form more suitable for fast computations; knowing the polar part $r$ of $\Lambda(s)$ (a rational function such that $\Lambda-r$ is holomorphic) is also useful. A subset of these, including only finitely many $a_{n}$-values will still completely determine $L$ (in suitable families), and we provide routines to try and compute missing invariants from whatever information is available. \misctitle{Important Caveat} The implementation assumes that the implied constants in the $O_{\epsilon}$ are small. In our generic framework, it is impossible to return proven results without more detailed information about the $L$ function. The intended use of the $L$-function package is not to prove theorems, but to experiment and formulate conjectures, so all numerical results should be taken with a grain of salt. One can always increase \kbd{realbitprecision} and recompute: the difference estimates the actual absolute error in the original output. \misctitle{Note} The requested precision has a major impact on runtimes. Because of this, most $L$-function routines, in particular \kbd{lfun} itself, specify the requested precision in \emph{bits}, not in decimal digits. This is transparent for the user once \tet{realprecision} or \tet{realbitprecision} are set. We advise to manipulate precision via \tet{realbitprecision} as it allows finer granularity: \kbd{realprecision} increases by increments of 64 bits, i.e. 19 decimal digits at a time. \subsec{Theta functions} %GPHELPskip Given an $L$-function as above, we define an attached theta function via Mellin inversion: for any positive real $t > 0$, we let $$ \theta(a,t) := \dfrac{1}{2\pi i}\int_{\Re(s) = c} t^{-s} \Lambda(s)\, ds $$ where $c$ is any positive real number $c > k_{1}+1$ such that $c + \Re(a) > 0$ for all $a\in A$. In fact, we have $$\theta(a,t) = \sum_{n\geq 1} a_{n} K(nt/N^{1/2}) \quad\text{where}\quad K(t) := \dfrac{1}{2\pi i}\int_{\Re(s) = c} t^{-s} \gamma_{A}(s)\, ds.$$ Note that this function is analytic and actually makes sense for complex $t$, such that $\Re(t^{2/d}) > 0$, i.e. in a cone containing the positive real half-line. The functional equation for $\Lambda$ translates into $$ \theta(a,1/t) - \epsilon t^{k}\theta(a^{*},t) = P_{\Lambda}(t), $$ where $P_{\Lambda}$ is an explicit polynomial in $t$ and $\log t$ given by the Taylor expansion of the polar part of $\Lambda$: there are no $\log$'s if all poles are simple, and $P = 0$ if $\Lambda$ is entire. The values $\theta(t)$ are generally easier to compute than the $L(s)$, and this functional equation provides a fast way to guess possible values for missing invariants in the $L$-function definition. \subsec{Data structures describing $L$ and theta functions} %GPHELPskip We have 3 levels of description: \item an \tet{Lmath} is an arbitrary description of the underlying mathematical situation (to which e.g., we associate the $a_{p}$ as traces of Frobenius elements); this is done via constructors to be described in the subsections below. \item an \tet{Ldata} is a computational description of situation, containing the complete datum ($a,a^{*},A,k,N,\epsilon,r$). Where $a$ and $a^{*}$ describe the coefficients (given $n,b$ we must be able to compute $[a_{1},\dots,a_{n}]$ with bit accuracy $b$), $A$ describes the Euler factor, the (classical) weight is $k$, $N$ is the conductor, and $r$ describes the polar part of $L(s)$. This is obtained via the function \tet{lfuncreate}. N.B. For motivic $L$-functions, the motivic weight $w$ is $w = k-1$; but we also support nonmotivic $L$-functions. \misctitle{Technical note} When some components of an \kbd{Ldata} cannot be given exactly, usually $r$ or $\epsilon$, the \kbd{Ldata} may be given as a \emph{closure}. When evaluated at a given precision, the closure must return all components as exact data or floating point numbers at the requested precision, see \kbd{??lfuncreate}. The reason for this technicality is that the accuracy to which we must compute is not bounded a priori and unknown at this stage: it depends on the domain where we evaluate the $L$-function. \item an \tet{Linit} contains an \kbd{Ldata} and everything needed for fast \emph{numerical} computations. It specifies the functions to be considered (either $L^{(j)}(s)$ or $\theta^{(j)}(t)$ for derivatives of order $j \leq m$, where $m$ is now fixed) and specifies a \emph{domain} which limits the range of arguments ($t$ or $s$, respectively to certain cones and rectangular regions) and the output accuracy. This is obtained via the functions \tet{lfuninit} or \tet{lfunthetainit}. All the functions which are specific to $L$ or theta functions share the prefix \kbd{lfun}. They take as first argument either an \kbd{Lmath}, an \kbd{Ldata}, or an \kbd{Linit}. If a single value is to be computed, this makes no difference, but when many values are needed (e.g. for plots or when searching for zeros), one should first construct an \kbd{Linit} attached to the search range and use it in all subsequent calls. If you attempt to use an \kbd{Linit} outside the range for which it was initialized, a warning is issued, because the initialization is performed again, a major inefficiency: \bprog ? Z = lfuncreate(1); \\ Riemann zeta ? L = lfuninit(Z, [1/2, 0, 100]); \\ zeta(1/2+it), |t| < 100 ? lfun(L, 1/2) \\ OK, within domain %3 = -1.4603545088095868128894991525152980125 ? lfun(L, 0) \\ not on critical line ! *** lfun: Warning: lfuninit: insufficient initialization. %4 = -0.50000000000000000000000000000000000000 ? lfun(L, 1/2, 1) \\ attempt first derivative ! *** lfun: Warning: lfuninit: insufficient initialization. %5 = -3.9226461392091517274715314467145995137 @eprog For many $L$-functions, passing from \kbd{Lmath} to an \kbd{Ldata} is inexpensive: in that case one may use \kbd{lfuninit} directly from the \kbd{Lmath} even when evaluations in different domains are needed. The above example could equally have skipped the \kbd{lfuncreate}: \bprog ? L = lfuninit(1, [1/2, 0, 100]); \\ zeta(1/2+it), |t| < 100 @eprog\noindent In fact, when computing a single value, you can even skip \kbd{lfuninit}: \bprog ? L = lfun(1, 1/2, 1); \\ zeta'(1/2) ? L = lfun(1, 1+x+O(x^5)); \\ first 5 terms of Taylor expansion at 1 @eprog\noindent Both give the desired results with no warning. \misctitle{Complexity} The implementation requires $O(N(|t|+1))^{1/2}$ coefficients $a_{n}$ to evaluate $L$ of conductor $N$ at $s = \sigma + i t$. We now describe the available high-level constructors, for built-in $L$ functions. \subsec{Dirichlet $L$-functions} %GPHELPskip Given a Dirichlet character $\chi:(\Z/N\Z)^{*}\to \C$, we let $$L(\chi, s) = \sum_{n\geq 1} \chi(n) n^{-s}.$$ Only primitive characters are supported. Given a nonzero integer $D$, the \typ{INT} $D$ encodes the function $L((D_{0}/.), s)$, for the quadratic Kronecker symbol attached to the fundamental discriminant $D_{0} = \kbd{coredisc}(D)$. This includes Riemann $\zeta$ function via the special case $D = 1$. More general characters can be represented in a variety of ways: \item via Conrey notation (see \tet{znconreychar}): $\chi_{N}(m,\cdot)$ is given as the \typ{INTMOD} \kbd{Mod(m,N)}. \item via a \var{znstar} structure describing the abelian group $(\Z/N\Z)^{*}$, where the character is given in terms of the \var{znstar} generators: \bprog ? G = znstar(100, 1); \\ (Z/100Z)^* ? G.cyc \\ ~ Z/20 . g1 + Z/2 . g2 for some generators g1 and g2 %2 = [20, 2] ? G.gen %3 = [77, 51] ? chi = [a, b] \\ maps g1 to e(a/20) and g2 to e(b/2); e(x) = exp(2ipi x) @eprog\noindent More generally, let $(\Z/N\Z)^{*} = \oplus (\Z/d_{j}\Z) g_{j}$ be given via a \var{znstar} structure $G$ (\kbd{G.cyc} gives the $d_{j}$ and \kbd{G.gen} the $g_{j}$). A \tev{character} $\chi$ on $G$ is given by a row vector $v = [a_{1},\ldots,a_{n}]$ such that $\chi(\prod_{j} g_{j}^{n_{j}}) = \exp(2\pi i\sum_{j} a_{j} n_{j} / d_{j})$. The pair $[G, v]$ encodes the \emph{primitive} character attached to $\chi$. \item in fact, this construction $[G, m]$ describing a character is more general: $m$ is also allowed to be a Conrey label as seen above, or a Conrey logarithm (see \tet{znconreylog}), and the latter format is actually the fastest one. Instead of a single character as above, one may use the construction \kbd{lfuncreate([G, vchi])} where \kbd{vchi} is a nonempty vector of characters \emph{of the same conductor} (more precisely, whose attached primitive characters have the same conductor) and \emph{same parity}. The function is then vector-valued, where the values are ordered as the characters in \kbd{vchi}. Conrey labels cannot be used in this last format because of the need to distinguish a single character given by a row vector of integers and a vector of characters given by their labels: use \kbd{znconreylog(G,i)} first to convert a label to Conrey logarithm. \item it is also possible to view Dirichlet characters as Hecke characters over $K = \Q$ (see below), for a modulus $[N, [1]]$ but this is both more complicated and less efficient. In all cases, a nonprimitive character is replaced by the attached primitive character. \subsec{Hecke $L$-functions of finite order characters} %GPHELPskip The Dedekind zeta function of a number field $K = \Q[X]/(T)$ is encoded either by the defining polynomial $T$, or any absolute number fields structure (a \var{nf} is enough). An alternative description for the Dedekind zeta function of an Abelian extension of a number field is to use class-field theory parameters $[\var{bnr}, \var{subg}]$, see \kbd{bnrinit}. \bprog ? bnf = bnfinit(a^2 - a - 9); ? bnr = bnrinit(bnf, [2, [0,0]]); subg = Mat(3); ? L = lfuncreate([bnr, subg]); @eprog Let $K$ be a number field given as a \kbd{bnfinit}. Given a finite order Hecke character $\chi: Cl_{f}(K)\to \C$, we let $$L(\chi, s) = \sum_{A \subset O_{K}} \chi(A)\, \left(N_{K/\Q}A\right)^{-s}.$$ Let $Cl_{f}(K) = \oplus (\Z/d_{j}\Z) g_{j}$ given by a \var{bnr} structure with generators: the $d_{j}$ are given by \kbd{K.cyc} and the $g_{j}$ by \kbd{K.gen}. A \tev{character} $\chi$ on the ray class group is given by a row vector $v = [a_{1},\ldots,a_{n}]$ such that $\chi(\prod_{j} g_{j}^{n_{j}}) = \exp(2\pi i\sum_{j} a_{j} n_{j} / d_{j})$. The pair $[\var{bnr}, v]$ encodes the \emph{primitive} character attached to $\chi$. \bprog ? K = bnfinit(x^2-60); ? Cf = bnrinit(K, [7, [1,1]], 1); \\ f = 7 oo_1 oo_2 ? Cf.cyc %3 = [6, 2, 2] ? Cf.gen %4 = [[2, 1; 0, 1], [22, 9; 0, 1], [-6, 7]~] ? lfuncreate([Cf, [1,0,0]]); \\@com $\chi(g_{1}) = \zeta_{6}$, $\chi(g_{2})=\chi(g_{3})=1$ @eprog \noindent Dirichlet characters on $(\Z/N\Z)^{*}$ are a special case, where $K = \Q$: \bprog ? Q = bnfinit(x); ? Cf = bnrinit(Q, [100, [1]]); \\ for odd characters on (Z/100Z)* @eprog\noindent For even characters, replace by \kbd{bnrinit(K, N)}. Note that the simpler direct construction in the previous section will be more efficient. Instead of a single character as above, one may use the construction \kbd{lfuncreate([Cf, vchi])} where \kbd{vchi} is a nonempty vector of characters \emph{of the same conductor} (more precisely, whose attached primitive characters have the same conductor). The function is then vector-valued, where the values are ordered as the characters in \kbd{vchi}. \subsec{General Hecke $L$-functions} \label{se:lfungchar} %GPHELPskip Given a Hecke \tev{Grossencharacter} $\chi: \A^{\times}\to \C^{\times}$ of conductor~$\goth{f}$, we let $$L(\chi, s) = \sum_{A \subset \Z_{K},\ A+\goth{f}=\Z_{K}} \chi(A)\, \left(N_{K/\Q}A\right)^{-s}.$$ Let $C_{K}(\goth{m})=\A^{\times}/(K^{\times}\cdot U(\goth{m}))$ be an id\`ele class group of modulus $\goth{m}$ given by a \var{gchar} structure~\var{gc} (see \tet{gcharinit} and Section~\ref{se:GCHAR}). A Grossencharacter $\chi$ on $C_{K}(\goth{m})$ is given by a row vector of size \kbd{\#\var{gc}.cyc}. \bprog ? gc = gcharinit(x^3+4*x-1,[5,[1]]); \\ mod = 5.oo ? gc.cyc %3 = [4, 2, 0, 0] ? gcharlog(gc,idealprimedec(gc.bnf,5)[1]) \\@com logarithm map $C_{K}(\goth{m})\to \R^{n}$ ? chi = [1,0,0,1,0]~; ? gcharduallog(gc,chi) \\@com row vector of coefficients in $\R^{n}$ ? L = lfuncreate([gc,chi]); \\@com non algebraic $L$-function ? lfunzeros(L,1) ? lfuneuler(L,2) \\@com Euler factor at 2 @eprog Finite order Hecke characters are a special case. \subsec{Artin $L$ functions} %GPHELPskip Given a Galois number field $N/\Q$ with group $G = \kbd{galoisinit}(N)$, a representation $\rho$ of $G$ over the cyclotomic field $\Q(\zeta_{n})$ is specified by the matrices giving the images of $\kbd{G.gen}$ by $\rho$. The corresponding Artin $L$ function is created using \tet{lfunartin}. \bprog P = quadhilbert(-47); \\ degree 5, Galois group D_5 N = nfinit(nfsplitting(P)); \\ Galois closure G = galoisinit(N); [s,t] = G.gen; \\ order 5 and 2 L = lfunartin(N,G, [[a,0;0,a^-1],[0,1;1,0]], 5); \\ irr. degree 2 @eprog\noindent In the above, the polynomial variable (here \kbd{a}) represents $\zeta_{5} := \exp(2i\pi/5)$ and the two matrices give the images of $s$ and $t$. Here, priority of \kbd{a} must be lower than the priority of \kbd{x}. \subsec{$L$-functions of algebraic varieties} %GPHELPskip $L$-function of elliptic curves over number fields are supported. \bprog ? E = ellinit([1,1]); ? L = lfuncreate(E); \\ L-function of E/Q ? E2 = ellinit([1,a], nfinit(a^2-2)); ? L2 = lfuncreate(E2); \\ L-function of E/Q(sqrt(2)) @eprog $L$-function of hyperelliptic genus-$2$ curve can be created with \kbd{lfungenus2}. To create the $L$ function of the curve $y^{2}+(x^{3}+x^{2}+1)y = x^{2}+x$: \bprog ? L = lfungenus2([x^2+x, x^3+x^2+1]); @eprog Currently, the model needs to be minimal at $2$, and if the conductor is even, its valuation at $2$ might be incorrect (a warning is issued). \subsec{Eta quotients / Modular forms} %GPHELPskip An eta quotient is created by applying \tet{lfunetaquo} to a matrix with 2 columns $[m, r_{m}]$ representing $$ f(\tau) := \prod_{m} \eta(m\tau)^{r_{m}}. $$ It is currently assumed that $f$ is a self-dual cuspidal form on $\Gamma_{0}(N)$ for some $N$. For instance, the $L$-function $\sum \tau(n) n^{-s}$ attached to Ramanujan's $\Delta$ function is encoded as follows \bprog ? L = lfunetaquo(Mat([1,24])); ? lfunan(L, 100) \\ first 100 values of tau(n) @eprog More general modular forms defined by modular symbols will be added later. \subsec{Low-level Ldata format} %GPHELPskip When no direct constructor is available, you can still input an $L$ function directly by supplying $[a, a^{*},A, k, N, \epsilon, r]$ to \kbd{lfuncreate} (see \kbd{??lfuncreate} for details). It is \emph{strongly} suggested to first check consistency of the created $L$-function: \bprog ? L = lfuncreate([a, as, A, k, N, eps, r]); ? lfuncheckfeq(L) \\ check functional equation @eprog \subsec{lfun$(L,s,\{D=0\})$}\kbdsidx{lfun}\label{se:lfun} Compute the L-function value $L(s)$, or if \kbd{D} is set, the derivative of order \kbd{D} at $s$. The parameter \kbd{L} is either an Lmath, an Ldata (created by \kbd{lfuncreate}, or an Linit (created by \kbd{lfuninit}), preferrably the latter if many values are to be computed. The argument $s$ is also allowed to be a power series; for instance, if $s = \alpha + x + O(x^{n})$, the function returns the Taylor expansion of order $n$ around $\alpha$. The result is given with absolute error less than $2^{-B}$, where $B = \text{realbitprecision}$. \misctitle{Caveat} The requested precision has a major impact on runtimes. It is advised to manipulate precision via \tet{realbitprecision} as explained above instead of \tet{realprecision} as the latter allows less granularity: \kbd{realprecision} increases by increments of 64 bits, i.e. 19 decimal digits at a time. \bprog ? lfun(x^2+1, 2) \\ Lmath: Dedekind zeta for Q(i) at 2 %1 = 1.5067030099229850308865650481820713960 ? L = lfuncreate(ellinit("5077a1")); \\ Ldata: Hasse-Weil zeta function ? lfun(L, 1+x+O(x^4)) \\ zero of order 3 at the central point %3 = 0.E-58 - 5.[...] E-40*x + 9.[...] E-40*x^2 + 1.7318[...]*x^3 + O(x^4) \\ Linit: zeta(1/2+it), |t| < 100, and derivative ? L = lfuninit(1, [100], 1); ? T = lfunzeros(L, [1,25]); %5 = [14.134725[...], 21.022039[...]] ? z = 1/2 + I*T[1]; ? abs( lfun(L, z) ) %7 = 8.7066865533412207420780392991125136196 E-39 ? abs( lfun(L, z, 1) ) %8 = 0.79316043335650611601389756527435211412 \\ simple zero @eprog The library syntax is \fun{GEN}{lfun0}{GEN L, GEN s, long D, long bitprec}. \subsec{lfunan$(L,n)$}\kbdsidx{lfunan}\label{se:lfunan} Compute the first $n$ terms of the Dirichlet series attached to the $L$-function given by \kbd{L} (\kbd{Lmath}, \kbd{Ldata} or \kbd{Linit}). \bprog ? lfunan(1, 10) \\ Riemann zeta %1 = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] ? lfunan(5, 10) \\ Dirichlet L-function for kronecker(5,.) %2 = [1, -1, -1, 1, 0, 1, -1, -1, 1, 0] @eprog The library syntax is \fun{GEN}{lfunan}{GEN L, long n, long prec}. \subsec{lfunartin$(\var{nf},\var{gal},\var{rho},n)$}\kbdsidx{lfunartin}\label{se:lfunartin} Returns the \kbd{Ldata} structure attached to the Artin $L$-function provided by the representation $\rho$ of the Galois group of the extension $K/\Q$, defined over the cyclotomic field $\Q(\zeta_{n})$, where \var{nf} is the nfinit structure attached to $K$, \var{gal} is the galoisinit structure attached to $K/\Q$, and \var{rho} is given either \item by the values of its character on the conjugacy classes (see \kbd{galoisconjclasses} and \kbd{galoischartable}) \item or by the matrices that are the images of the generators \kbd{\var{gal}.gen}. Cyclotomic numbers in \kbd{rho} are represented by polynomials, whose variable is understood as the complex number $\exp(2\*i\*\pi/n)$. In the following example we build the Artin $L$-functions attached to the two irreducible degree $2$ representations of the dihedral group $D_{10}$ defined over $\Q(\zeta_{5})$, for the extension $H/\Q$ where $H$ is the Hilbert class field of $\Q(\sqrt{-47})$. We show numerically some identities involving Dedekind $\zeta$ functions and Hecke $L$ series. \bprog ? P = quadhilbert(-47) %1 = x^5 + 2*x^4 + 2*x^3 + x^2 - 1 ? N = nfinit(nfsplitting(P)); ? G = galoisinit(N); \\ D_10 ? [T,n] = galoischartable(G); ? T \\ columns give the irreducible characters %5 = [1 1 2 2] [1 -1 0 0] [1 1 -y^3 - y^2 - 1 y^3 + y^2] [1 1 y^3 + y^2 -y^3 - y^2 - 1] ? n %6 = 5 ? L2 = lfunartin(N,G, T[,2], n); ? L3 = lfunartin(N,G, T[,3], n); ? L4 = lfunartin(N,G, T[,4], n); ? s = 1 + x + O(x^4); ? lfun(-47,s) - lfun(L2,s) %11 ~ 0 ? lfun(1,s)*lfun(-47,s)*lfun(L3,s)^2*lfun(L4,s)^2 - lfun(N,s) %12 ~ 0 ? lfun(1,s)*lfun(L3,s)*lfun(L4,s) - lfun(P,s) %13 ~ 0 ? bnr = bnrinit(bnfinit(x^2+47),1,1); ? bnr.cyc %15 = [5] \\ Z/5Z: 4 nontrivial ray class characters ? lfun([bnr,[1]], s) - lfun(L3, s) %16 ~ 0 ? lfun([bnr,[2]], s) - lfun(L4, s) %17 ~ 0 ? lfun([bnr,[3]], s) - lfun(L3, s) %18 ~ 0 ? lfun([bnr,[4]], s) - lfun(L4, s) %19 ~ 0 @eprog The first identity identifies the nontrivial abelian character with $(-47,\cdot)$; the second is the factorization of the regular representation of $D_{10}$; the third is the factorization of the natural representation of $D_{10}\subset S_{5}$; and the final four are the expressions of the degree $2$ representations as induced from degree $1$ representations. The library syntax is \fun{GEN}{lfunartin}{GEN nf, GEN gal, GEN rho, long n, long bitprec}. \subsec{lfuncheckfeq$(L,\{t\})$}\kbdsidx{lfuncheckfeq}\label{se:lfuncheckfeq} Given the data attached to an $L$-function (\kbd{Lmath}, \kbd{Ldata} or \kbd{Linit}), check whether the functional equation is satisfied. This is most useful for an \kbd{Ldata} constructed ``by hand'', via \kbd{lfuncreate}, to detect mistakes. If the function has poles, the polar part must be specified. The routine returns a bit accuracy $b$ such that $|w - \hat{w}| < 2^{b}$, where $w$ is the root number contained in \kbd{data}, and $$\hat{w} = \theta(1/t) t^{-k} / \overline{\theta}(t)$$ is a computed value derived from the assumed functional equation. Of course, the expected result is a large negative value of the order of \kbd{realbitprecision}. But if $\overline{\theta}$ is very small at $t$, you should first increase \kbd{realbitprecision} by $-\log_{2} |\overline{\theta}(t)|$, which is positive if $\theta$ is small, to get a meaningful result. Note that $t$ should be close to the unit disc for efficiency and such that $\overline{\theta}(t) \neq 0$. If the parameter $t$ is omitted, we check the functional equation at the ``random'' complex number $t = 335/339 + I/7$. \bprog ? \pb 128 \\ 128 bits of accuracy ? default(realbitprecision) %1 = 128 ? L = lfuncreate(1); \\ Riemann zeta ? lfuncheckfeq(L) %3 = -124 @eprog\noindent i.e. the given data is consistent to within 4 bits for the particular check consisting of estimating the root number from all other given quantities. Checking away from the unit disc will either fail with a precision error, or give disappointing results (if $\theta(1/t)$ is large it will be computed with a large absolute error) \bprog ? lfuncheckfeq(L, 2+I) %4 = -115 ? lfuncheckfeq(L,10) *** at top-level: lfuncheckfeq(L,10) *** ^------------------ *** lfuncheckfeq: precision too low in lfuncheckfeq. @eprog \misctitle{The case of Dedekind zeta functions} Dedekind zeta function for a number field $K = \Q[X]/(T)$ is in general computed (assuming Artin conjecture) as $(\zeta_{K}/\zeta_{k}) \times \zeta_{k}$, where $k$ is a maximal subfield, applied recursively if possible. When $K/\Q$ is Galois, the zeta function is directly decomposed as a product of Artin $L$-functions. These decompositions are computed when \kbd{lfuninit} is called. The behavior of \kbd{lfuncheckfeq} is then different depending of its argument \item the artificial query \kbd{lfuncheckfeq}$(T)$ serves little purpose since we already know that the technical parameters are theoretically correct; we just obtain an estimate on the accuracy they allow. This is computed directly, without using the above decomposition. And is likely to be very costly if the degree of $T$ is large, possibly overflowing the possibilities of the implementation. \item a query \kbd{L = lfuninit(T, ...); lfuncheckfeq(L)} on the other hand returns the maximum of the \kbd{lfuncheckfeq} values for all involved $L$-functions, giving a general consistency check and again an estimate for the accuracy of computed values. At the default accuracy of 128 bits: \bprog ? T = polcyclo(43); ? lfuncheckfeq(T); *** at top-level: lfuncheckfeq(T) *** ^--------------- *** lfuncheckfeq: overflow in lfunthetacost. ? lfuncheckfeq(lfuninit(T, [2])) time = 107 ms. %2 = -122 @eprog The library syntax is \fun{long}{lfuncheckfeq}{GEN L, GEN t = NULL, long bitprec}. \subsec{lfunconductor$(L,\{\var{setN}=10000\},\{\fl=0\})$}\kbdsidx{lfunconductor}\label{se:lfunconductor} Computes the conductor of the given $L$-function (if the structure contains a conductor, it is ignored). Two methods are available, depending on what we know about the conductor, encoded in the \kbd{setN} parameter: \item \kbd{setN} is a scalar: we know nothing but expect that the conductor lies in the interval $[1, \kbd{setN}]$. If $\fl$ is $0$ (default), gives either the conductor found as an integer, or a vector (possibly empty) of conductors found. If $\fl$ is $1$, same but gives the computed floating point approximations to the conductors found, without rounding to integers. It $\fl$ is $2$, gives all the conductors found, even those far from integers. \misctitle{Caveat} This is a heuristic program and the result is not proven in any way: \bprog ? L = lfuncreate(857); \\ Dirichlet L function for kronecker(857,.) ? \p19 realprecision = 19 significant digits ? lfunconductor(L) %2 = [17, 857] ? lfunconductor(L,,1) \\ don't round %3 = [16.99999999999999999, 857.0000000000000000] ? \p38 realprecision = 38 significant digits ? lfunconductor(L) %4 = 857 @eprog\noindent Increasing \kbd{setN} or increasing \kbd{realbitprecision} slows down the program but gives better accuracy for the result. This algorithm should only be used if the primes dividing the conductor are unknown, which is uncommon. \item \kbd{setN} is a vector of possible conductors; for instance of the form \kbd{D1 * divisors(D2)}, where $D_{1}$ is the known part of the conductor and $D_{2}$ is a multiple of the contribution of the bad primes. In that case, $\fl$ is ignored and the routine uses \kbd{lfuncheckfeq}. It returns $[N,e]$ where $N$ is the best conductor in the list and $e$ is the value of \kbd{lfuncheckfeq} for that $N$. When no suitable conductor exist or there is a tie among best potential conductors, return the empty vector \kbd{[]}. \bprog ? E = ellinit([0,0,0,4,0]); /* Elliptic curve y^2 = x^3+4x */ ? E.disc \\ |disc E| = 2^12 %2 = -4096 \\ create Ldata by hand. Guess that root number is 1 and conductor N ? L(N) = lfuncreate([n->ellan(E,n), 0, [0,1], 2, N, 1]); \\ lfunconductor ignores conductor = 1 in Ldata ! ? lfunconductor(L(1), divisors(E.disc)) %5 = [32, -127] ? fordiv(E.disc, d, print(d,": ",lfuncheckfeq(L(d)))) \\ direct check 1: 0 2: 0 4: -1 8: -2 16: -3 32: -127 64: -3 128: -2 256: -2 512: -1 1024: -1 2048: 0 4096: 0 @eprog\noindent The above code assumed that root number was $1$; had we set it to $-1$, none of the \kbd{lfuncheckfeq} values would have been acceptable: \bprog ? L2 = lfuncreate([n->ellan(E,n), 0, [0,1], 2, 0, -1]); ? lfunconductor(L2, divisors(E.disc)) %7 = [] @eprog The library syntax is \fun{GEN}{lfunconductor}{GEN L, GEN setN = NULL, long flag, long bitprec}. \subsec{lfuncost$(L,\{\var{sdom}\},\{\var{der}=0\})$}\kbdsidx{lfuncost}\label{se:lfuncost} Estimate the cost of running \kbd{lfuninit(L,sdom,der)} at current bit precision, given by a vector $[t, b]$. \item If $L$ contains the root number, indicate that $t$ coefficients $a_{n}$ will be computed, as well as $t$ values of \tet{gammamellininv}, all at bit accuracy $b$. A subsequent call to \kbd{lfun} at $s$ evaluates a polynomial of degree $t$ at $\exp(h s)$ for some real parameter $h$, at the same bit accuracy $b$. \item If the root number is \emph{not} known, then more values of $a_{n}$ may be needed in order to compute it, and the returned value of $t$ takes this into account (it may not be the exact value in this case but is always an upper bound). Fewer than $t$ \kbd{gammamellininv} will be needed, and a call to \kbd{lfun} evaluates a polynomial of degree less that $t$, still at bit accuracy $b$. If $L$ is already an \kbd{Linit}, then \var{sdom} and \var{der} are ignored and are best left omitted; the bit accuracy is also inferred from $L$: in short we get an estimate of the cost of using that particular \kbd{Linit}. Note that in this case, the root number is always already known and you get the right value of $t$ (corresponding to the number of past calls to \kbd{gammamellinv} and the actual degree of the evaluated polynomial). \bprog ? \pb 128 ? lfuncost(1, [100]) \\ for zeta(1/2+I*t), |t| < 100 %1 = [7, 242] \\ 7 coefficients, 242 bits ? lfuncost(1, [1/2, 100]) \\ for zeta(s) in the critical strip, |Im s| < 100 %2 = [7, 246] \\ now 246 bits ? lfuncost(1, [100], 10) \\ for zeta(1/2+I*t), |t| < 100 %3 = [8, 263] \\ 10th derivative increases the cost by a small amount ? lfuncost(1, [10^5]) %3 = [158, 113438] \\ larger imaginary part: huge accuracy increase ? L = lfuncreate(polcyclo(5)); \\ Dedekind zeta for Q(zeta_5) ? lfuncost(L, [100]) \\ at s = 1/2+I*t), |t| < 100 %5 = [11457, 582] ? lfuncost(L, [200]) \\ twice higher %6 = [36294, 1035] ? lfuncost(L, [10^4]) \\ much higher: very costly ! %7 = [70256473, 45452] ? \pb 256 ? lfuncost(L, [100]); \\ doubling bit accuracy is cheaper %8 = [17080, 710] ? \p38 ? K = bnfinit(y^2 - 4493); [P] = idealprimedec(K,1123); f = [P,[1,1]]; ? R = bnrinit(K, f); R.cyc %10 = [1122] ? L = lfuncreate([R, [7]]); \\ Hecke L-function ? L[6] %12 = 0 \\ unknown root number ? \pb 3000 ? lfuncost(L, [0], 1) %13 = [1171561, 3339] ? L = lfuninit(L, [0], 1); time = 1min, 56,426 ms. ? lfuncost(L) %14 = [826966, 3339] @eprog\noindent In the final example, the root number was unknown and extra coefficients $a_{n}$ were needed to compute it ($1171561$). Once the initialization is performed we obtain the lower value $t = 826966$, which corresponds to the number of \kbd{gammamellinv} computed and the actual degree of the polynomial to be evaluated to compute a value within the prescribed domain. Finally, some $L$ functions can be factorized algebraically by the \kbd{lfuninit} call, e.g. the Dedekind zeta function of abelian fields, leading to much faster evaluations than the above upper bounds. In that case, the function returns a vector of costs as above for each individual function in the product actually evaluated: \bprog ? L = lfuncreate(polcyclo(5)); \\ Dedekind zeta for Q(zeta_5) ? lfuncost(L, [100]) \\ a priori cost %2 = [11457, 582] ? L = lfuninit(L, [100]); \\ actually perform all initializations ? lfuncost(L) %4 = [[16, 242], [16, 242], [7, 242]] @eprog\noindent The Dedekind function of this abelian quartic field is the product of four Dirichlet $L$-functions attached to the trivial character, a nontrivial real character and two complex conjugate characters. The nontrivial characters happen to have the same conductor (hence same evaluation costs), and correspond to two evaluations only since the two conjugate characters are evaluated simultaneously. For a total of three $L$-functions evaluations, which explains the three components above. Note that the actual cost is much lower than the a priori cost in this case. The library syntax is \fun{GEN}{lfuncost0}{GEN L, GEN sdom = NULL, long der, long bitprec}. Also available is \fun{GEN}{lfuncost}{GEN L, GEN dom, long der, long bitprec} when $L$ is \emph{not} an \kbd{Linit}; the return value is a \typ{VECSMALL} in this case. \subsec{lfuncreate$(\var{obj})$}\kbdsidx{lfuncreate}\label{se:lfuncreate} This low-level routine creates \tet{Ldata} structures, needed by \var{lfun} functions, describing an $L$-function and its functional equation. We advise using a high-level constructor when one is available, see \kbd{??lfun}, and this function accepts them: \bprog ? L = lfuncreate(1); \\ Riemann zeta ? L = lfuncreate(5); \\ Dirichlet L-function for quadratic character (5/.) ? L = lfuncreate(x^2+1); \\ Dedekind zeta for Q(i) ? L = lfuncreate(ellinit([0,1])); \\ L-function of E/Q: y^2=x^3+1 @eprog\noindent One can then use, e.g., \kbd{lfun(L,s)} to directly evaluate the respective $L$-functions at $s$, or \kbd{lfuninit(L, [c,w,h]} to initialize computations in the rectangular box $\Re(s-c) \leq w$, $\Im(s) \leq h$. We now describe the low-level interface, used to input nonbuiltin $L$-functions. The input is now a $6$ or $7$ component vector $V=[a, astar, Vga, k, N, eps, poles]$, whose components are as follows: \item \kbd{V[1]=a} encodes the Dirichlet series coefficients $(a_{n})$. The preferred format is a closure of arity 1: \kbd{n->vector(n,i,a(i))} giving the vector of the first $n$ coefficients. The closure is allowed to return a vector of more than $n$ coefficients (only the first $n$ will be considered) or even less than $n$, in which case loss of accuracy will occur and a warning that \kbd{\#an} is less than expected is issued. This allows to precompute and store a fixed large number of Dirichlet coefficients in a vector $v$ and use the closure \kbd{n->v}, which does not depend on $n$. As a shorthand for this latter case, you can input the vector $v$ itself instead of the closure. \bprog ? z = lfuncreate([n->vector(n,i,1), 1, [0], 1, 1, 1, 1]); \\ Riemann zeta ? lfun(z,2) - Pi^2/6 %2 = -5.877471754111437540 E-39 @eprog A second format is limited to $L$-functions affording an Euler product. It is a closure of arity 2 \kbd{(p,d)->F(p)} giving the local factor $L_{p}(X)$ at $p$ as a rational function, to be evaluated at $p^{-s}$ as in \kbd{direuler}; $d$ is set to \kbd{logint}$(n,p)$ + 1, where $n$ is the total number of Dirichlet coefficients $(a_{1},\dots,a_{n})$ that will be computed. In other words, the smallest integer $d$ such that $p^{d} > n$. This parameter $d$ allows to compute only part of $L_{p}$ when $p$ is large and $L_{p}$ expensive to compute: any polynomial (or \typ{SER}) congruent to $L_{p}$ modulo $X^{d}$ is acceptable since only the coefficients of $X^{0}, \dots, X^{d-1}$ are needed to expand the Dirichlet series. The closure can of course ignore this parameter: \bprog ? z = lfuncreate([(p,d)->1/(1-x), 1, [0], 1, 1, 1, 1]); \\ Riemann zeta ? lfun(z,2) - Pi^2/6 %4 = -5.877471754111437540 E-39 @eprog\noindent One can describe separately the generic local factors coefficients and the bad local factors by setting $\kbd{dir} = [F, L_{bad}]$, were $L_{bad} = [[p_{1},L_{p_{1}}], \dots,[p_{k},L_{p_{k}}]]$, where $F$ describes the generic local factors as above, except that when $p = p_{i}$ for some $i \leq k$, the coefficient $a_{p}$ is directly set to $L_{p_{i}}$ instead of calling $F$. \bprog N = 15; E = ellinit([1, 1, 1, -10, -10]); \\ = "15a1" F(p,d) = 1 / (1 - ellap(E,p)*'x + p*'x^2); Lbad = [[3, 1/(1+'x)], [5, 1/(1-'x)]]; L = lfuncreate([[F,Lbad], 0, [0,1], 2, N, ellrootno(E)]); @eprog\noindent Of course, in this case, \kbd{lfuncreate(E)} is preferable! \item \kbd{V[2]=astar} is the Dirichlet series coefficients of the dual function, encoded as \kbd{a} above. The sentinel values $0$ and $1$ may be used for the special cases where $a = a^{*}$ and $a = \overline{a^{*}}$, respectively. \item \kbd{V[3]=Vga} is the vector of $\alpha_{j}$ such that the gamma factor of the $L$-function is equal to $$\gamma_{A}(s)=\prod_{1\le j\le d}\Gamma_{\R}(s+\alpha_{j}),$$ where $\Gamma_{\R}(s)=\pi^{-s/2}\Gamma(s/2)$. This same syntax is used in the \kbd{gammamellininv} functions. In particular the length $d$ of \kbd{Vga} is the degree of the $L$-function. In the present implementation, the $\alpha_{j}$ are assumed to be exact rational numbers. However when calling theta functions with \emph{complex} (as opposed to real) arguments, determination problems occur which may give wrong results when the $\alpha_{j}$ are not integral. \item \kbd{V[4]=k} is a positive integer $k$. The functional equation relates values at $s$ and $k-s$. For instance, for an Artin $L$-series such as a Dedekind zeta function we have $k = 1$, for an elliptic curve $k = 2$, and for a modular form, $k$ is its weight. For motivic $L$-functions, the \emph{motivic} weight $w$ is $w = k-1$. By default we assume that $a_{n} = O_{\epsilon}(n^{k_{1}+\epsilon})$, where $k_{1} = w$ and even $k_{1} = w/2$ when the $L$ function has no pole (Ramanujan-Petersson). If this is not the case, you can replace the $k$ argument by a vector $[k,k_{1}]$, where $k_{1}$ is the upper bound you can assume. \item \kbd{V[5]=N} is the conductor, an integer $N\ge1$, such that $\Lambda(s)=N^{s/2}\gamma_{A}(s)L(s)$ with $\gamma_{A}(s)$ as above. \item \kbd{V[6]=eps} is the root number $\varepsilon$, i.e., the complex number (usually of modulus $1$) such that $\Lambda(a, k-s) = \varepsilon \Lambda(a^{*}, s)$. \item The last optional component \kbd{V[7]=poles} encodes the poles of the $L$ or $\Lambda$-functions, and is omitted if they have no poles. A polar part is given by a list of $2$-component vectors $[\beta,P_{\beta}(x)]$, where $\beta$ is a pole and the power series $P_{\beta}(x)$ describes the attached polar part, such that $L(s) - P_{\beta}(s-\beta)$ is holomorphic in a neighbourhood of $\beta$. For instance $P_{\beta} = r/x+O(1)$ for a simple pole at $\beta$ or $r_{1}/x^{2}+r_{2}/x+O(1)$ for a double pole. The type of the list describing the polar part allows to distinguish between $L$ and $\Lambda$: a \typ{VEC} is attached to $L$, and a \typ{COL} is attached to $\Lambda$. Unless $a = \overline{a^{*}}$ (coded by \kbd{astar} equal to $0$ or $1$), it is mandatory to specify the polar part of $\Lambda$ rather than those of $L$ since the poles of $L^{*}$ cannot be infered from the latter ! Whereas the functional equation allows to deduce the polar part of $\Lambda^{*}$ from the polar part of $\Lambda$. Finally, if $a = \overline{a^{*}}$, we allow a shortcut to describe the frequent situation where $L$ has at most simple pole, at $s = k$, with residue $r$ a complex scalar: you may then input $\kbd{poles} = r$. This value $r$ can be set to $0$ if unknown and it will be computed. \misctitle{When one component is not exact} Alternatively, \kbd{obj} can be a closure of arity $0$ returning the above vector to the current real precision. This is needed if some components are not available exactly but only through floating point approximations. The closure allows algorithms to recompute them to higher accuracy when needed. Compare \bprog ? Ld1() = [n->lfunan(Mod(2,7),n),1,[0],1,7,((-13-3*sqrt(-3))/14)^(1/6)]; ? Ld2 = [n->lfunan(Mod(2,7),n),1,[0],1,7,((-13-3*sqrt(-3))/14)^(1/6)]; ? L1 = lfuncreate(Ld1); ? L2 = lfuncreate(Ld2); ? lfun(L1,1/2+I*200) \\ OK %5 = 0.55943925130316677665287870224047183265 - 0.42492662223174071305478563967365980756*I ? lfun(L2,1/2+I*200) \\ all accuracy lost %6 = 0.E-38 + 0.E-38*I @eprog\noindent The accuracy lost in \kbd{Ld2} is due to the root number being given to an insufficient precision. To see what happens try \bprog ? Ld3() = printf("prec needed: %ld bits",getlocalbitprec());Ld1() ? L3 = lfuncreate(Ld3); prec needed: 64 bits ? z3 = lfun(L3,1/2+I*200) prec needed: 384 bits %16 = 0.55943925130316677665287870224047183265 - 0.42492662223174071305478563967365980756*I @eprog The library syntax is \fun{GEN}{lfuncreate}{GEN obj}. \subsec{lfundiv$(\var{L1},\var{L2})$}\kbdsidx{lfundiv}\label{se:lfundiv} Creates the \kbd{Ldata} structure (without initialization) corresponding to the quotient of the Dirichlet series $L_{1}$ and $L_{2}$ given by \kbd{L1} and \kbd{L2}. Assume that $v_{z}(L_{1}) \geq v_{z}(L_{2})$ at all complex numbers $z$: the construction may not create new poles, nor increase the order of existing ones. The library syntax is \fun{GEN}{lfundiv}{GEN L1, GEN L2, long bitprec}. \subsec{lfundual$(L)$}\kbdsidx{lfundual}\label{se:lfundual} Creates the \kbd{Ldata} structure (without initialization) corresponding to the dual L-function $\hat{L}$ of $L$. If $k$ and $\varepsilon$ are respectively the weight and root number of $L$, then the following formula holds outside poles, up to numerical errors: $$\Lambda(L, s) = \varepsilon \Lambda(\hat{L}, k - s).$$ \bprog ? L = lfunqf(matdiagonal([1,2,3,4])); ? eps = lfunrootres(L)[3]; k = L[4]; ? M = lfundual(L); lfuncheckfeq(M) %3 = -127 ? s= 1+Pi*I; ? a = lfunlambda(L,s); ? b = eps * lfunlambda(M,k-s); ? exponent(a - b) %7 = -130 @eprog The library syntax is \fun{GEN}{lfundual}{GEN L, long bitprec}. \subsec{lfunetaquo$(M)$}\kbdsidx{lfunetaquo}\label{se:lfunetaquo} Returns the \kbd{Ldata} structure attached to the $L$ function attached to the modular form $z\mapsto \prod_{i=1}^{n} \eta(M_{i,1}\*z)^{M_{i,2}}$ It is currently assumed that $f$ is a self-dual cuspidal form on $\Gamma_{0}(N)$ for some $N$. For instance, the $L$-function $\sum \tau(n) n^{-s}$ attached to Ramanujan's $\Delta$ function is encoded as follows \bprog ? L = lfunetaquo(Mat([1,24])); ? lfunan(L, 100) \\ first 100 values of tau(n) @eprog\noindent For convenience, a \typ{VEC} is also accepted instead of a factorization matrix with a single row: \bprog ? L = lfunetaquo([1,24]); \\ same as above @eprog The library syntax is \fun{GEN}{lfunetaquo}{GEN M}. \subsec{lfuneuler$(L,p)$}\kbdsidx{lfuneuler}\label{se:lfuneuler} Return the Euler factor at $p$ of the $L$-function given by \kbd{L} (\kbd{Lmath}, \kbd{Ldata} or \kbd{Linit}), assuming the $L$-function admits an Euler product factorization and that it can be determined. \bprog ? E=ellinit([1,3]); ? lfuneuler(E,7) %2 = 1/(7*x^2-2*x+1) ? L=lfunsympow(E,2); ? lfuneuler(L,11) %4 = 1/(-1331*x^3+275*x^2-25*x+1) @eprog The library syntax is \fun{GEN}{lfuneuler}{GEN L, GEN p, long prec}. \subsec{lfungenus2$(F)$}\kbdsidx{lfungenus2}\label{se:lfungenus2} Returns the \kbd{Ldata} structure attached to the $L$ function attached to the genus-2 curve defined by $y^{2}=F(x)$ or $y^{2}+Q(x)\*y=P(x)$ if $F=[P,Q]$. Currently, if the conductor is even, its valuation at $2$ might be incorrect (a warning is issued). The library syntax is \fun{GEN}{lfungenus2}{GEN F}. \subsec{lfunhardy$(L,t)$}\kbdsidx{lfunhardy}\label{se:lfunhardy} Variant of the Hardy $Z$-function given by \kbd{L}, used for plotting or locating zeros of $L(k/2+it)$ on the critical line. The precise definition is as follows: let $k/2$ be the center of the critical strip, $d$ be the degree, $\kbd{Vga} = (\alpha_{j})_{j\leq d}$ given the gamma factors, and $\varepsilon$ be the root number; we set $s = k/2+it = \rho e^{i\theta}$ and $2E = d(k/2-1) + \Re(\sum_{1\le j\le d}\alpha_{j})$. Assume first that $\Lambda$ is self-dual, then the computed function at $t$ is equal to $$Z(t) = \varepsilon^{-1/2}\Lambda(s) \cdot \rho^{-E}e^{dt\theta/2}\;,$$ which is a real function of $t$ vanishing exactly when $L(k/2+it)$ does on the critical line. The normalizing factor $|s|^{-E}e^{dt\theta/2}$ compensates the exponential decrease of $\gamma_{A}(s)$ as $t\to\infty$ so that $Z(t) \approx 1$. For non-self-dual $\Lambda$, the definition is the same except we drop the $\varepsilon^{-1/2}$ term (which is not well defined since it depends on the chosen dual sequence $a^{*}(n)$): $Z(t)$ is still of the order of $1$ and still vanishes where $L(k/2+it)$ does, but it needs no longer be real-valued. \bprog ? T = 100; \\ maximal height ? L = lfuninit(1, [T]); \\ initialize for zeta(1/2+it), |t|= 1 %1 = 15 ? lfunthetacost(L, 1 + I); \\ cost for theta(1+I). Domain error ! *** at top-level: lfunthetacost(1,1+I) *** ^-------------------- *** lfunthetacost: domain error in lfunthetaneed: arg t > 0.785 ? lfunthetacost(L, 1 + I/2) \\ for theta(1+I/2). %2 = 23 ? lfunthetacost(L, 1 + I/2, 10) \\ for theta^((10))(1+I/2). %3 = 24 ? lfunthetacost(L, [2, 1/10]) \\ cost for theta(t), |t| >= 2, |arg(t)| < 1/10 %4 = 8 ? L = lfuncreate( ellinit([1,1]) ); ? lfunthetacost(L) \\ for t >= 1 %6 = 2471 @eprog The library syntax is \fun{long}{lfunthetacost0}{GEN L, GEN tdom = NULL, long m, long bitprec}. \subsec{lfunthetainit$(L,\{\var{tdom}\},\{m=0\})$}\kbdsidx{lfunthetainit}\label{se:lfunthetainit} Initalization function for evaluating the $m$-th derivative of theta functions with argument $t$ in domain \var{tdom}. By default (\var{tdom} omitted), $t$ is real, $t \geq 1$. Otherwise, \var{tdom} may be \item a positive real scalar $\rho$: $t$ is real, $t \geq \rho$. \item a nonreal complex number: compute at this particular $t$; this allows to compute $\theta(z)$ for any complex $z$ satisfying $|z|\geq |t|$ and $|\arg z| \leq |\arg t|$; we must have $|2 \arg z / d| < \pi/2$, where $d$ is the degree of the $\Gamma$ factor. \item a pair $[\rho,\alpha]$: assume that $|t| \geq \rho$ and $|\arg t| \leq \alpha$; we must have $|2\alpha / d| < \pi/2$, where $d$ is the degree of the $\Gamma$ factor. \bprog ? \p500 ? L = lfuncreate(1); \\ Riemann zeta ? t = 1+I/2; ? lfuntheta(L, t); \\ direct computation time = 30 ms. ? T = lfunthetainit(L, 1+I/2); time = 30 ms. ? lfuntheta(T, t); \\ instantaneous @eprog\noindent The $T$ structure would allow to quickly compute $\theta(z)$ for any $z$ in the cone delimited by $t$ as explained above. On the other hand \bprog ? lfuntheta(T,I) *** at top-level: lfuntheta(T,I) *** ^-------------- *** lfuntheta: domain error in lfunthetaneed: arg t > 0.785398163397448 @eprog The initialization is equivalent to \bprog ? lfunthetainit(L, [abs(t), arg(t)]) @eprog The library syntax is \fun{GEN}{lfunthetainit}{GEN L, GEN tdom = NULL, long m, long bitprec}. \subsec{lfuntwist$(L,\var{chi})$}\kbdsidx{lfuntwist}\label{se:lfuntwist} Creates the Ldata structure (without initialization) corresponding to the twist of L by the primitive character attached to the Dirichlet character \kbd{chi}. The conductor of the character must be coprime to the conductor of the L-function $L$. The library syntax is \fun{GEN}{lfuntwist}{GEN L, GEN chi, long bitprec}. \subsec{lfunzeros$(L,\var{lim},\{\var{divz}=8\})$}\kbdsidx{lfunzeros}\label{se:lfunzeros} \kbd{lim} being either a positive upper limit or a nonempty real interval, computes an ordered list of zeros of $L(s)$ on the critical line up to the given upper limit or in the given interval. Use a naive algorithm which may miss some zeros: it assumes that two consecutive zeros at height $T \geq 1$ differ at least by $2\pi/\omega$, where $$\omega := \kbd{divz} \cdot \big(d\log(T/2\pi) + d+ 2\log(N/(\pi/2)^{d})\big).$$ To use a finer search mesh, set divz to some integral value larger than the default (= 8). \bprog ? lfunzeros(1, 30) \\ zeros of Rieman zeta up to height 30 %1 = [14.134[...], 21.022[...], 25.010[...]] ? #lfunzeros(1, [100,110]) \\ count zeros with 100 <= Im(s) <= 110 %2 = 4 @eprog\noindent The algorithm also assumes that all zeros are simple except possibly on the real axis at $s = k/2$ and that there are no poles in the search interval. (The possible zero at $s = k/2$ is repeated according to its multiplicity.) If you pass an \kbd{Linit} to the function, the algorithm assumes that a multiple zero at $s = k / 2$ has order less than or equal to the maximal derivation order allowed by the \kbd{Linit}. You may increase that value in the \kbd{Linit} but this is costly: only do it for zeros of low height or in \kbd{lfunorderzero} instead. The library syntax is \fun{GEN}{lfunzeros}{GEN L, GEN lim, long divz, long bitprec}. \section{Modular forms} This section describes routines for working with modular forms and modular form spaces. \subsec{Modular form spaces} %GPHELPskip These structures are initialized by the \kbd{mfinit} command; supported modular form \emph{spaces} with corresponding flags are the following: \item The full modular form space $M_{k}(\Gamma_{0}(N),\chi)$, where $k$ is an integer or a half-integer and $\chi$ a Dirichlet character modulo $N$ ($\fl=4$, the default). \item The cuspidal space $S_{k}(\Gamma_{0}(N),\chi)$ ($\fl=1$). \item The Eisenstein space ${\cal E}_{k}(\Gamma_{0}(N),\chi)$ ($\fl=3$), so that $M_{k}={\cal E}_{k}\oplus S_{k}$. \item The new space $S_{k}^{\text{new}}(\Gamma_{0}(N),\chi)$ ($\fl=0$). \item The old space $S_{k}^{\text{old}}(\Gamma_{0}(N),\chi)$ ($\fl=2$), so that $S_{k}=S_{k}^{\text{new}}\oplus S_{k}^{\text{old}}$. These resulting \kbd{mf} structure contains a basis of modular forms, which is accessed by the function \kbd{mfbasis}; the elements of this basis have Fourier coefficients in the cyclotomic field $\Q(\chi)$. These coefficients are given algebraically, as rational numbers or \typ{POLMOD}s. The member function \kbd{mf.mod} recovers the modulus used to define $\Q(\chi)$, which is a cyclotomic polynomial $\Phi_{n}(t)$. When needed, the elements of $\Q(\chi)$ are considered to be canonically embedded into $\C$ via $\kbd{Mod}(t,\Phi_{n}(t)) \mapsto \exp(2i\pi/n)$. The basis of eigenforms for the new space is obtained by the function \kbd{mfeigenbasis}: the elements of this basis now have Fourier coefficients in a relative field extension of $\Q(\chi)$. Note that if the space is larger than the new space (i.e. is the cuspidal or full space) we nevertheless obtain only the eigenbasis for the new space. \subsec{Generalized modular forms} %GPHELPskip A modular form is represented in a special internal format giving the possibility to compute an arbitrary number of terms of its Fourier coefficients at infinity $[a(0),a(1),...,a(n)]$ using the function \kbd{mfcoefs}. These coefficients are given algebraically, as rational numbers or \typ{POLMOD}s. The member function \kbd{f.mod} recovers the modulus used in the coefficients of $f$, which will be the same as for $k = \Q(\chi)$ (a cyclotomic polynomial), or define a number field extension $K/k$. Modular forms are obtained either directly from other mathematical objects, e.g., elliptic curves, or by a specific formula, e.g., Eisenstein series or Ramanujan's Delta function, or by applying standard operators to existing forms (Hecke operators, Rankin--Cohen brackets, \dots). A function \kbd{mfparams} is provided so that one can recover the level, weight, character and field of definition corresponding to a given modular form. A number of creation functions and operations are provided. It is however important to note that strictly speaking some of these operations create objects which are \emph{not} modular forms: typical examples are derivation or integration of modular forms, the Eisenstein series $E_{2}$, eta quotients, or quotients of modular forms. These objects are nonetheless very important in the theory, so are not considered as errors; however the user must be aware that no attempt is made to check that the objects that he handles are really modular. When the documentation of a function does not state that it applies to generalized modular forms, then the output is undefined if the input is not a true modular form. \subsec{lfunmf$(\var{mf},\{F\})$}\kbdsidx{lfunmf}\label{se:lfunmf} If $F$ is a modular form in \kbd{mf}, output the L-functions corresponding to its $[\Q(F):\Q(\chi)]$ complex embeddings, ready for use with the \kbd{lfun} package. If $F$ is omitted, output the $L$-functions attached to all eigenforms in the new space; the result is a vector whose length is the number of Galois orbits of newforms. Each entry contains the vector of $L$-functions corresponding to the $d$ complex embeddings of an orbit of dimension $d$ over $\Q(\chi)$. \bprog ? mf = mfinit([35,2],0);mffields(mf) %1 = [y, y^2 - y - 4] ? f = mfeigenbasis(mf)[2]; mfparams(f) \\ orbit of dimension two %2 = [35, 2, 1, y^2 - y - 4, t - 1] ? [L1,L2] = lfunmf(mf, f); \\ Two L-functions ? lfun(L1,1) %4 = 0.81018461849460161754947375433874745585 ? lfun(L2,1) %5 = 0.46007635204895314548435893464149369804 ? [ lfun(L,1) | L <- concat(lfunmf(mf)) ] %6 = [0.70291..., 0.81018..., 0.46007...] @eprog\noindent The \kbd{concat} instruction concatenates the vectors corresponding to the various (here two) orbits, so that we obtain the vector of all the $L$-functions attached to eigenforms. The library syntax is \fun{GEN}{lfunmf}{GEN mf, GEN F = NULL, long bitprec}. \subsec{mfDelta$()$}\kbdsidx{mfDelta}\label{se:mfDelta} Mf structure corresponding to the Ramanujan Delta function $\Delta$. \bprog ? mfcoefs(mfDelta(),4) %1 = [0, 1, -24, 252, -1472] @eprog The library syntax is \fun{GEN}{mfDelta}{}. \subsec{mfEH$(k)$}\kbdsidx{mfEH}\label{se:mfEH} $k$ being in $1/2+\Z_{\geq 0}$, return the mf structure corresponding to the Cohen-Eisenstein series $H_{k}$ of weight $k$ on $\Gamma_{0}(4)$. \bprog ? H = mfEH(13/2); mfcoefs(H,4) %1 = [691/32760, -1/252, 0, 0, -2017/252] @eprog The coefficients of $H$ are given by the Cohen-Hurwitz function $H(k-1/2,N)$ and can be obtained for moderately large values of $N$ (the algorithm uses $\tilde{O}(N)$ time): \bprog ? mfcoef(H,10^5+1) time = 55 ms. %2 = -12514802881532791504208348 ? mfcoef(H,10^7+1) time = 6,044 ms. %3 = -1251433416009877455212672599325104476 @eprog The library syntax is \fun{GEN}{mfEH}{GEN k}. \subsec{mfEk$(k)$}\kbdsidx{mfEk}\label{se:mfEk} K being an even nonnegative integer, return the mf structure corresponding to the standard Eisenstein series $E_{k}$. \bprog ? mfcoefs(mfEk(8), 4) %1 = [1, 480, 61920, 1050240, 7926240] @eprog The library syntax is \fun{GEN}{mfEk}{long k}. \subsec{mfTheta$(\{\var{psi}=1\})$}\kbdsidx{mfTheta}\label{se:mfTheta} The unary theta function corresponding to the primitive Dirichlet character $\psi$. Its level is $4 F(\psi)^{2}$ and its weight is $1 - \psi(-1)/2$. \bprog ? Ser(mfcoefs(mfTheta(),30)) %1 = 1 + 2*x + 2*x^4 + 2*x^9 + 2*x^16 + 2*x^25 + O(x^31) ? f = mfTheta(8); Ser(mfcoefs(f,30)) %2 = 2*x - 2*x^9 - 2*x^25 + O(x^31) ? mfparams(f) %3 = [256, 1/2, 8, y, t + 1] ? g = mfTheta(-8); Ser(mfcoefs(g,30)) %4 = 2*x + 6*x^9 - 10*x^25 + O(x^31) ? mfparams(g) %5 = [256, 3/2, 8, y, t + 1] ? h = mfTheta(Mod(2,5)); mfparams(h) %6 = [100, 3/2, Mod(7, 20), y, t^2 + 1] @eprog The library syntax is \fun{GEN}{mfTheta}{GEN psi = NULL}. \subsec{mfatkin$(\var{mfatk},f)$}\kbdsidx{mfatkin}\label{se:mfatkin} Given a \kbd{mfatk} output by \kbd{mfatk = mfatkininit(mf,Q)} and a modular form $f$ belonging to the pace \kbd{mf}, returns the modular form $g = C \times f|W_{Q}$, where $C = \kbd{mfatk[3]}$ is a normalizing constant such that $g$ has the same field of coefficients as $f$; \kbd{mfatk[3]} gives the constant $C$, and \kbd{mfatk[1]} gives the modular form space to which $g$ belongs (or is set to $0$ if it is \kbd{mf}). \bprog ? mf = mfinit([35,2],0); [f] = mfbasis(mf); ? mfcoefs(f, 4) %2 = [0, 3, -1, 0, 3] ? mfatk = mfatkininit(mf,7); ? g = mfatkin(mfatk, f); mfcoefs(g, 4) %4 = [0, 1, -1, -2, 7] ? mfatk = mfatkininit(mf,35); ? g = mfatkin(mfatk, f); mfcoefs(g, 4) %6 = [0, -3, 1, 0, -3] @eprog The library syntax is \fun{GEN}{mfatkin}{GEN mfatk, GEN f}. \subsec{mfatkineigenvalues$(\var{mf},Q)$}\kbdsidx{mfatkineigenvalues}\label{se:mfatkineigenvalues} Given a modular form space \kbd{mf} of integral weight $k$ and a primitive divisor $Q$ of the level $N$ of \kbd{mf}, outputs the Atkin--Lehner eigenvalues of $w_{Q}$ on the new space, grouped by orbit. If the Nebentypus $\chi$ of \kbd{mf} is a (trivial or) quadratic character defined modulo $N/Q$, the result is rounded and the eigenvalues are $\pm i^{k}$. \bprog ? mf = mfinit([35,2],0); mffields(mf) %1 = [y, y^2 - y - 4] \\ two orbits, dimension 1 and 2 ? mfatkineigenvalues(mf,5) %2 = [[1], [-1, -1]] ? mf = mfinit([12,7,Mod(3,4)],0); ? mfatkineigenvalues(mf,3) %4 = [[I, -I, -I, I, I, -I]] \\ one orbit @eprog To obtain the eigenvalues on a larger space than the new space, e.g., the full space, you can directly call \kbd{[mfB,M,C]=mfatkininit} and compute the eigenvalues as the roots of the characteristic polynomial of $M/C$, by dividing the roots of \kbd{charpoly(M)} by $C$. Note that the characteristic polynomial is computed exactly since $M$ has coefficients in $\Q(\chi)$, whereas $C$ may be given by a complex number. If the coefficients of the characteristic polynomial are polmods modulo $T$ they must be embedded to $\C$ first using \kbd{subst(lift(), t, exp(2*I*Pi/n))}, when $T$ is \kbd{poliscyclo(n)}; note that $T = \kbd{mf.mod}$. The library syntax is \fun{GEN}{mfatkineigenvalues}{GEN mf, long Q, long prec}. \subsec{mfatkininit$(\var{mf},Q)$}\kbdsidx{mfatkininit}\label{se:mfatkininit} Given a modular form space with parameters $N,k,\chi$ and a primitive divisor $Q$ of the level $N$, initializes data necessary for working with the Atkin--Lehner operator $W_{Q}$, for now only the function \kbd{mfatkin}. We write $\chi \sim \chi_{Q} \chi_{N/Q}$ where the two characters are primitive with (coprime) conductors dividing $Q$ and $N/Q$ respectively. For $F\in M_{k}(\Gamma_{0}(N),\chi)$, the form $F | W_{Q}$ still has level $N$ and weight $k$ but its Nebentypus may no longer be $\chi$: it becomes $\overline{\chi_{Q}} \chi_{N/Q})$ if $k$ is integral and $\overline{\chi_{Q}} \chi_{N/Q})(4Q/\cdot)$ if not. The result is a technical 4-component vector \kbd{[mfB, MC, C, mf]}, where \item \kbd{mfB} encodes the modular form space to which $F|W_{Q}$ belongs when $F \in M_{k}(\Gamma_{0}(N), \chi)$: an \kbd{mfinit} corresponding to a new Nebentypus or the integer $0$ when the character does not change. This does not depend on $F$. \item \kbd{MC} is the matrix of $W_{Q}$ on the bases of \kbd{mf} and \kbd{mfB} multiplied by a normalizing constant $C(k,\chi,Q)$. This matrix has polmod coefficients in $\Q(\chi)$. \item \kbd{C} is the complex constant $C(k,\chi,Q)$. For $k$ integral, let $A(k,\chi, Q) = Q^{\varepsilon}/g(\chi_{Q})$, where $\varepsilon = 0$ for $k$ even and $1/2$ for $k$ odd and where $g(\chi_{Q})$ is the Gauss sum attached to $\chi_{Q}$). (A similar, more complicated, definition holds in half-integral weight depending on the parity of $k - 1/2$.) Then if $M$ denotes the matrix of $W_{Q}$ on the bases of \kbd{mf} and \kbd{mfB}, $A \cdot M$ has coefficients in $\Q(\chi)$. If $A$ is rational, we let $C = 1$ and $C = A$ as a floating point complex number otherwise, and finally $\kbd{MC} := M \cdot C$. \bprog ? mf=mfinit([32,4],0); [mfB,MC,C]=mfatkininit(mf,32); MC %1 = [5/16 11/2 55/8] [ 1/8 0 -5/4] [1/32 -1/4 11/16] ? C %2 = 1 ? mf=mfinit([32,4,8],0); [mfB,MC,C]=mfatkininit(mf,32); MC %3 = [ 1/8 -7/4] [-1/16 -1/8] ? C %4 = 0.35355339059327376220042218105242451964 ? algdep(C,2) \\ C = 1/sqrt(8) %5 = 8*x^2 - 1 @eprog The library syntax is \fun{GEN}{mfatkininit}{GEN mf, long Q, long prec}. \subsec{mfbasis$(\var{NK},\{\var{space}=4\})$}\kbdsidx{mfbasis}\label{se:mfbasis} If $NK=[N,k,\var{CHI}]$ as in \kbd{mfinit}, gives a basis of the corresponding subspace of $M_{k}(\Gamma_{0}(N),\chi)$. $NK$ can also be the output of \kbd{mfinit}, in which case \kbd{space} can be omitted. To obtain the eigenforms, use \kbd{mfeigenbasis}. If \kbd{space} is a full space $M_{k}$, the output is the union of first, a basis of the space of Eisenstein series, and second, a basis of the cuspidal space. \bprog ? see(L) = apply(f->mfcoefs(f,3), L); ? mf = mfinit([35,2],0); ? see( mfbasis(mf) ) %2 = [[0, 3, -1, 0], [0, -1, 9, -8], [0, 0, -8, 10]] ? see( mfeigenbasis(mf) ) %3 = [[0, 1, 0, 1], [Mod(0, z^2 - z - 4), Mod(1, z^2 - z - 4), \ Mod(-z, z^2 - z - 4), Mod(z - 1, z^2 - z - 4)]] ? mf = mfinit([35,2]); ? see( mfbasis(mf) ) %5 = [[1/6, 1, 3, 4], [1/4, 1, 3, 4], [17/12, 1, 3, 4], \ [0, 3, -1, 0], [0, -1, 9, -8], [0, 0, -8, 10]] ? see( mfbasis([48,4],0) ) %6 = [[0, 3, 0, -3], [0, -3, 0, 27], [0, 2, 0, 30]] @eprog The library syntax is \fun{GEN}{mfbasis}{GEN NK, long space}. \subsec{mfbd$(F,d)$}\kbdsidx{mfbd}\label{se:mfbd} $F$ being a generalized modular form, return $B(d)(F)$, where $B(d)$ is the expanding operator $\tau\mapsto d\tau$. \bprog ? D2=mfbd(mfDelta(),2); mfcoefs(D2, 6) %1 = [0, 0, 1, 0, -24, 0, 252] @eprog The library syntax is \fun{GEN}{mfbd}{GEN F, long d}. \subsec{mfbracket$(F,G,\{m=0\})$}\kbdsidx{mfbracket}\label{se:mfbracket} Compute the $m$-th Rankin--Cohen bracket of the generalized modular forms $F$ and $G$. \bprog ? E4 = mfEk(4); E6 = mfEk(6); ? D1 = mfbracket(E4,E4,2); mfcoefs(D1,5)/4800 %2 = [0, 1, -24, 252, -1472, 4830] ? D2 = mfbracket(E4,E6,1); mfcoefs(D2,10)/(-3456) %3 = [0, 1, -24, 252, -1472, 4830] @eprog The library syntax is \fun{GEN}{mfbracket}{GEN F, GEN G, long m}. \subsec{mfcoef$(F,n)$}\kbdsidx{mfcoef}\label{se:mfcoef} Compute the $n$-th Fourier coefficient $a(n)$ of the generalized modular form $F$. Note that this is the $n+1$-st component of the vector \kbd{mfcoefs(F,n)} as well as the second component of \kbd{mfcoefs(F,1,n)}. \bprog ? mfcoef(mfDelta(),10) %1 = -115920 @eprog The library syntax is \fun{GEN}{mfcoef}{GEN F, long n}. \subsec{mfcoefs$(F,n,\{d=1\})$}\kbdsidx{mfcoefs}\label{se:mfcoefs} Compute the vector of Fourier coefficients $[a[0],a[d],...,a[nd]]$ of the generalized modular form $F$; $d$ must be positive and $d = 1$ by default. \bprog ? D = mfDelta(); ? mfcoefs(D,10) %2 = [0, 1, -24, 252, -1472, 4830, -6048, -16744, 84480, -113643, -115920] ? mfcoefs(D,5,2) %3 = [0, -24, -1472, -6048, 84480, -115920] ? mfcoef(D,10) %4 = -115920 @eprog\noindent This function also applies when $F$ is a modular form space as output by \kbd{mfinit}; it then returns the matrix whose columns give the Fourier expansions of the elements of \kbd{mfbasis}$(F)$: \bprog ? mf = mfinit([1,12]); ? mfcoefs(mf,5) %2 = [691/65520 0] [ 1 1] [ 2049 -24] [ 177148 252] [ 4196353 -1472] [ 48828126 4830] @eprog The library syntax is \fun{GEN}{mfcoefs}{GEN F, long n, long d}. \subsec{mfconductor$(\var{mf},F)$}\kbdsidx{mfconductor}\label{se:mfconductor} \kbd{mf} being output by \kbd{mfinit} for the cuspidal space and $F$ a modular form, gives the smallest level at which $F$ is defined. In particular, if $F$ is cuspidal and we write $F = \sum_{j} B(d_{j}) f_{j}$ for new forms $f_{j}$ of level $N_{j}$ (see \kbd{mftonew}), then its conductor is the least common multiple of the $d_{j} N_{j}$. \bprog ? mf=mfinit([96,6],1); vF = mfbasis(mf); mfdim(mf) %1 = 72 ? vector(10,i, mfconductor(mf, vF[i])) %2 = [3, 6, 12, 24, 48, 96, 4, 8, 12, 16] @eprog The library syntax is \fun{long}{mfconductor}{GEN mf, GEN F}. \subsec{mfcosets$(N)$}\kbdsidx{mfcosets}\label{se:mfcosets} Let $N$ be a positive integer. Return the list of right cosets of $\Gamma_{0}(N) \bs \Gamma$, i.e., matrices $\gamma_{j} \in \Gamma$ such that $\Gamma = \bigsqcup_{j} \Gamma_{0}(N) \gamma_{j}$. The $\gamma_{j}$ are chosen in the form $[a,b;c,d]$ with $c \mid N$. \bprog ? mfcosets(4) %1 = [[0, -1; 1, 0], [1, 0; 1, 1], [0, -1; 1, 2], [0, -1; 1, 3],\ [1, 0; 2, 1], [1, 0; 4, 1]] @eprog\noindent We also allow the argument $N$ to be a modular form space, in which case it is replaced by the level of the space: \bprog ? M = mfinit([4, 12, 1], 0); mfcosets(M) %2 = [[0, -1; 1, 0], [1, 0; 1, 1], [0, -1; 1, 2], [0, -1; 1, 3],\ [1, 0; 2, 1], [1, 0; 4, 1]] @eprog \misctitle{Warning} In the present implementation, the trivial coset is represented by $[1,0;N,1]$ and is the last in the list. The library syntax is \fun{GEN}{mfcosets}{GEN N}. \subsec{mfcuspisregular$(\var{NK},\var{cusp})$}\kbdsidx{mfcuspisregular}\label{se:mfcuspisregular} In the space defined by \kbd{NK = [N,k,CHI]} or \kbd{NK = mf}, determine if \kbd{cusp} in canonical format (oo or denominator dividing $N$) is regular or not. \bprog ? mfcuspisregular([4,3,-4],1/2) %1 = 0 @eprog The library syntax is \fun{long}{mfcuspisregular}{GEN NK, GEN cusp}. \subsec{mfcusps$(N)$}\kbdsidx{mfcusps}\label{se:mfcusps} Let $N$ be a positive integer. Return the list of cusps of $\Gamma_{0}(N)$ in the form $a/b$ with $b\mid N$. \bprog ? mfcusps(24) %1 = [0, 1/2, 1/3, 1/4, 1/6, 1/8, 1/12, 1/24] @eprog\noindent We also allow the argument $N$ to be a modular form space, in which case it is replaced by the level of the space: \bprog ? M = mfinit([4, 12, 1], 0); mfcusps(M) %2 = [0, 1/2, 1/4] @eprog The library syntax is \fun{GEN}{mfcusps}{GEN N}. \subsec{mfcuspval$(\var{mf},F,\var{cusp})$}\kbdsidx{mfcuspval}\label{se:mfcuspval} Valuation of modular form $F$ in the space \kbd{mf} at \kbd{cusp}, which can be either $\infty$ or any rational number. The result is either a rational number or $\infty$ if $F$ is zero. Let $\chi$ be the Nebentypus of the space \kbd{mf}; if $\Q(F) \neq \Q(\chi)$, return the vector of valuations attached to the $[\Q(F):\Q(chi)]$ complex embeddings of $F$. \bprog ? T=mfTheta(); mf=mfinit([12,1/2]); mfcusps(12) %1 = [0, 1/2, 1/3, 1/4, 1/6, 1/12] ? apply(x->mfcuspval(mf,T,x), %1) %2 = [0, 1/4, 0, 0, 1/4, 0] ? mf=mfinit([12,6,12],1); F=mfbasis(mf)[5]; ? apply(x->mfcuspval(mf,F,x),%1) %4 = [1/12, 1/6, 1/2, 2/3, 1/2, 2] ? mf=mfinit([12,3,-4],1); F=mfbasis(mf)[1]; ? apply(x->mfcuspval(mf,F,x),%1) %6 = [1/12, 1/6, 1/4, 2/3, 1/2, 1] ? mf = mfinit([625,2],0); [F] = mfeigenbasis(mf); mfparams(F) %7 = [625, 2, 1, y^2 - y - 1, t - 1] \\ [Q(F):Q(chi)] = 2 ? mfcuspval(mf, F, 1/25) %8 = [1, 2] \\ one conjugate has valuation 1, and the other is 2 ? mfcuspval(mf, F, 1/5) %9 = [1/25, 1/25] @eprog The library syntax is \fun{GEN}{mfcuspval}{GEN mf, GEN F, GEN cusp, long bitprec}. \subsec{mfcuspwidth$(N,\var{cusp})$}\kbdsidx{mfcuspwidth}\label{se:mfcuspwidth} Width of \kbd{cusp} in $\Gamma_{0}(N)$. \bprog ? mfcusps(12) %1 = [0, 1/2, 1/3, 1/4, 1/6, 1/12] ? [mfcuspwidth(12,c) | c <- mfcusps(12)] %2 = [12, 3, 4, 3, 1, 1] ? mfcuspwidth(12, oo) %3 = 1 @eprog\noindent We also allow the argument $N$ to be a modular form space, in which case it is replaced by the level of the space: \bprog ? M = mfinit([4, 12, 1], 0); mfcuspwidth(M, 1/2) %4 = 1 @eprog The library syntax is \fun{long}{mfcuspwidth}{GEN N, GEN cusp}. \subsec{mfderiv$(F,\{m=1\})$}\kbdsidx{mfderiv}\label{se:mfderiv} $m$-th formal derivative of the power series corresponding to the generalized modular form $F$, with respect to the differential operator $qd/dq$ (default $m=1$). \bprog ? D=mfDelta(); ? mfcoefs(D, 4) %2 = [0, 1, -24, 252, -1472] ? mfcoefs(mfderiv(D), 4) %3 = [0, 1, -48, 756, -5888] @eprog The library syntax is \fun{GEN}{mfderiv}{GEN F, long m}. \subsec{mfderivE2$(F,\{m=1\})$}\kbdsidx{mfderivE2}\label{se:mfderivE2} Compute the Serre derivative $(q \* d/dq)F - kE_{2}F/12$ of the generalized modular form $F$, which has weight $k+2$; if $F$ is a true modular form, then its Serre derivative is also modular. If $m>1$, compute the $m$-th iterate, of weight $k + 2m$. \bprog ? mfcoefs(mfderivE2(mfEk(4)),5)*(-3) %1 = [1, -504, -16632, -122976, -532728] ? mfcoefs(mfEk(6),5) %2 = [1, -504, -16632, -122976, -532728] @eprog The library syntax is \fun{GEN}{mfderivE2}{GEN F, long m}. \subsec{mfdescribe$(F,\{\&G\})$}\kbdsidx{mfdescribe}\label{se:mfdescribe} Gives a human-readable description of $F$, which is either a modular form space or a generalized modular form. If the address of $G$ is given, puts into $G$ the vector of parameters of the outermost operator defining $F$; this vector is empty if $F$ is a leaf (an atomic object such as \kbd{mfDelta()}, not defined in terms of other forms) or a modular form space. \bprog ? E1 = mfeisenstein(4,-3,-4); mfdescribe(E1) %1 = "F_4(-3, -4)" ? E2 = mfeisenstein(3,5,-7); mfdescribe(E2) %2 = "F_3(5, -7)" ? E3 = mfderivE2(mfmul(E1,E2), 3); mfdescribe(E3,&G) %3 = "DERE2^3(MUL(F_4(-3, -4), F_3(5, -7)))" ? mfdescribe(G[1][1]) %4 = "MUL(F_4(-3, -4), F_3(5, -7))" ? G[2] %5 = 3 ? for (i = 0, 4, mf = mfinit([37,4],i); print(mfdescribe(mf))); S_4^new(G_0(37, 1)) S_4(G_0(37, 1)) S_4^old(G_0(37, 1)) E_4(G_0(37, 1)) M_4(G_0(37, 1)) @eprog The library syntax is \fun{GEN}{mfdescribe}{GEN F, GEN *G = NULL}. \subsec{mfdim$(\var{NK},\{\var{space}=4\})$}\kbdsidx{mfdim}\label{se:mfdim} If $NK=[N,k,\var{CHI}]$ as in \kbd{mfinit}, gives the dimension of the corresponding subspace of $M_{k}(\Gamma_{0}(N),\chi)$. $NK$ can also be the output of \kbd{mfinit}, in which case space must be omitted. The subspace is described by the small integer \kbd{space}: $0$ for the newspace $S_{k}^{\text{new}}(\Gamma_{0}(N),\chi)$, $1$ for the cuspidal space $S_{k}$, $2$ for the oldspace $S_{k}^{\text{old}}$, $3$ for the space of Eisenstein series $E_{k}$ and $4$ for the full space $M_{k}$. \misctitle{Wildcards} As in \kbd{mfinit}, \var{CHI} may be the wildcard 0 (all Galois orbits of characters); in this case, the output is a vector of $[\var{order}, \var{conrey}, \var{dim}, \var{dimdih}]$ corresponding to the nontrivial spaces, where \item \var{order} is the order of the character, \item \var{conrey} its Conrey label from which the character may be recovered via \kbd{znchar}$(\var{conrey})$, \item \var{dim} the dimension of the corresponding space, \item \var{dimdih} the dimension of the subspace of dihedral forms corresponding to Hecke characters if $k = 1$ (this is not implemented for the old space and set to $-1$ for the time being) and 0 otherwise. The spaces are sorted by increasing order of the character; the characters are taken up to Galois conjugation and the Conrey number is the minimal one among Galois conjugates. In weight $1$, this is only implemented when the space is 0 (newspace), 1 (cusp space), 2(old space) or 3(Eisenstein series). \misctitle{Wildcards for sets of characters} \var{CHI} may be a set of characters, and we return the set of $[\var{dim},\var{dimdih}]$. \misctitle{Wildcard for $M_{k}(\Gamma_{1}(N))$} Additionally, the wildcard $\var{CHI} = -1$ is available in which case we output the total dimension of the corresponding subspace of $M_{k}(\Gamma_{1}(N))$. In weight $1$, this is not implemented when the space is 4 (fullspace). \bprog ? mfdim([23,2], 0) \\ new space %1 = 2 ? mfdim([96,6], 0) %2 = 10 ? mfdim([10^9,4], 3) \\ Eisenstein space %1 = 40000 ? mfdim([10^9+7,4], 3) %2 = 2 ? mfdim([68,1,-1],0) %3 = 3 ? mfdim([68,1,0],0) %4 = [[2, Mod(67, 68), 1, 1], [4, Mod(47, 68), 1, 1]] ? mfdim([124,1,0],0) %5 = [[6, Mod(67, 124), 2, 0]] @eprog This last example shows that there exists a nondihedral form of weight 1 in level 124. The library syntax is \fun{GEN}{mfdim}{GEN NK, long space}. \subsec{mfdiv$(F,G)$}\kbdsidx{mfdiv}\label{se:mfdiv} Given two generalized modular forms $F$ and $G$, compute $F/G$ assuming that the quotient will not have poles at infinity. If this is the case, use \kbd{mfshift} before doing the division. \bprog ? D = mfDelta(); \\ Delta ? H = mfpow(mfEk(4), 3); ? J = mfdiv(H, D) *** at top-level: J=mfdiv(H,mfdeltac *** ^-------------------- *** mfdiv: domain error in mfdiv: ord(G) > ord(F) ? J = mfdiv(H, mfshift(D,1)); ? mfcoefs(J, 4) %4 = [1, 744, 196884, 21493760, 864299970] @eprog The library syntax is \fun{GEN}{mfdiv}{GEN F, GEN G}. \subsec{mfeigenbasis$(\var{mf})$}\kbdsidx{mfeigenbasis}\label{se:mfeigenbasis} Vector of the eigenforms for the space \kbd{mf}. The initial basis of forms computed by \kbd{mfinit} before splitting is also available via \kbd{mfbasis}. \bprog ? mf = mfinit([26,2],0); ? see(L) = for(i=1,#L,print(mfcoefs(L[i],6))); ? see( mfeigenbasis(mf) ) [0, 1, -1, 1, 1, -3, -1] [0, 1, 1, -3, 1, -1, -3] ? see( mfbasis(mf) ) [0, 2, 0, -2, 2, -4, -4] [0, -2, -4, 10, -2, 0, 8] @eprog The eigenforms are internally expressed as (algebraic) linear combinations of \kbd{mfbasis(mf)} and it is very inefficient to compute many coefficients of those forms individually: you should rather use \kbd{mfcoefs(mf)} to expand the basis once and for all, then multiply by \kbd{mftobasis(mf,f)} for the forms you're interested in: \bprog ? mf = mfinit([96,6],0); B = mfeigenbasis(mf); #B %1 = 8; ? vector(#B, i, mfcoefs(B[i],1000)); \\ expanded individually: slow time = 7,881 ms. ? M = mfcoefs(mf, 1000); \\ initialize once time = 982 ms. ? vector(#B, i, M * mftobasis(mf,B[i])); \\ then expand: much faster time = 623 ms. @eprog When the eigenforms are defined over an extension field of $\Q(\chi)$ for a nonrational character, their coefficients are hard to read and you may want to lift them or to express them in an absolute number field. In the construction below $T$ defines $\Q(f)$ over $\Q$, $a$ is the image of the generator \kbd{Mod}$(t, t^{2}+t+1)$ of $\Q(\chi)$ in $\Q(f)$ and $y - ka$ is the image of the root $y$ of \kbd{f.mod}: \bprog ? mf = mfinit([31, 2, Mod(25,31)], 0); [f] = mfeigenbasis(mf); ? f.mod %2 = Mod(1, t^2 + t + 1)*y^2 + Mod(2*t + 2, t^2 + t + 1) ? v = liftpol(mfcoefs(f,5)) %3 = [0, 1, (-t - 1)*y - 1, t*y + (t + 1), (2*t + 2)*y + 1, t] ? [T,a,k] = rnfequation(mf.mod, f.mod, 1) %4 = [y^4 + 2*y^2 + 4, Mod(-1/2*y^2 - 1, y^4 + 2*y^2 + 4), 0] ? liftpol(substvec(v, [t,y], [a, y-k*a])) %5 = [0, 1, 1/2*y^3 - 1, -1/2*y^3 - 1/2*y^2 - y, -y^3 + 1, -1/2*y^2 - 1] @eprog\noindent Beware that the meaning of $y$ has changed in the last line is different: it now represents of root of $T$, no longer of \kbd{f.mod} (the notions coincide if $k = 0$ as here but it will not always be the case). This can be avoided with an extra variable substitution, for instance \bprog ? [T,a,k] = rnfequation(mf.mod, subst(f.mod,'y,'x), 1) %6 = [x^4 + 2*x^2 + 4, Mod(-1/2*x^2 - 1, x^4 + 2*x^2 + 4), 0] ? liftpol(substvec(v, [t,y], [a, x-k*a])) %7 = [0, 1, 1/2*x^3 - 1, -1/2*x^3 - 1/2*x^2 - x, -x^3 + 1, -1/2*x^2 - 1] @eprog The library syntax is \fun{GEN}{mfeigenbasis}{GEN mf}. \subsec{mfeigensearch$(\var{NK},\{\var{AP}\})$}\kbdsidx{mfeigensearch}\label{se:mfeigensearch} Search for a normalized rational eigen cuspform with quadratic character given restrictions on a few initial coefficients. The meaning of the parameters is as follows: \item \kbd{NK} governs the limits of the search: it is of the form $[N,k]$: search for given level $N$, weight $k$ and quadratic character; note that the character $(D/.)$ is uniquely determined by $(N,k)$. The level $N$ can be replaced by a vector of allowed levels. \item \kbd{AP} is the search criterion, which can be omitted: a list of pairs $[\ldots, [p,a_{p}], \ldots]$, where $p$ is a prime number and $a_{p}$ is either a \typ{INT} (the $p$-th Fourier coefficient must match $a_{p}$ exactly) or a \typ{INTMOD} \kbd{Mod}$(a,b)$ (the $p$-th coefficient must be congruent to $a$ modulo $b$). The result is a vector of newforms $f$ matching the search criteria, sorted by increasing level then increasing $|D|$. \bprog ? #mfeigensearch([[1..80],2], [[2,2],[3,-1]]) %1 = 1 ? #mfeigensearch([[1..80],2], [[2,2],[5,2]]) %2 = 1 ? v = mfeigensearch([[1..20],2], [[3,Mod(2,3)],[7,Mod(5,7)]]); #v %3 = 1 ? F=v[1]; [mfparams(F)[1], mfcoefs(F,15)] %4 = [11, [0, 1, -2, -1, 2, 1, 2, -2, 0, -2, -2, 1, -2, 4, 4, -1]] @eprog The library syntax is \fun{GEN}{mfeigensearch}{GEN NK, GEN AP = NULL}. \subsec{mfeisenstein$(k,\{\var{CHI1}\},\{\var{CHI2}\})$}\kbdsidx{mfeisenstein}\label{se:mfeisenstein} Create the Eisenstein series $E_{k}(\chi_{1},\chi_{2})$, where $k \geq 1$, $\chi_{i}$ are Dirichlet characters and an omitted character is considered as trivial. This form belongs to ${\cal E}_{k}(\Gamma_{0}(N), \chi)$ with $\chi = \chi_{1}\chi_{2}$ and $N$ is the product of the conductors of $\chi_{1}$ and $\chi_{2}$. \bprog ? CHI = Mod(3,4); ? E = mfeisenstein(3, CHI); ? mfcoefs(E, 6) %2 = [-1/4, 1, 1, -8, 1, 26, -8] ? CHI2 = Mod(4,5); ? mfcoefs(mfeisenstein(3,CHI,CHI2), 6) %3 = [0, 1, -1, -10, 1, 25, 10] ? mfcoefs(mfeisenstein(4,CHI,CHI), 6) %4 = [0, 1, 0, -28, 0, 126, 0] ? mfcoefs(mfeisenstein(4), 6) %5 = [1/240, 1, 9, 28, 73, 126, 252] @eprog\noindent Note that \kbd{mfeisenstein}$(k)$ is 0 for $k$ odd and $-B_{k}/(2k) \cdot E_{k}$ for $k$ even, where $$E_{k}(q) = 1 - (2k/B_{k})\sum_{n\geq 1} \sigma_{k-1}(n) q^{n}$$ is the standard Eisenstein series. In other words it is normalized so that its linear coefficient is $1$. \misctitle{Important note} This function is currently implemented only when $\Q(\chi)$ is the field of definition of $E_{k}(\chi_{1},\chi_{2})$. If it is a strict subfield, an error is raised: \bprog ? mfeisenstein(6, Mod(7,9), Mod(4,9)); *** at top-level: mfeisenstein(6,Mod(7,9),Mod(4,9)) *** ^--------------------------------- *** mfeisenstein: sorry, mfeisenstein for these characters is not *** yet implemented. @eprog\noindent The reason for this is that each modular form is attached to a modular form space $M_{k}(\Gamma_{0}(N),\chi)$. This is a $\C$-vector space but it allows a basis of forms defined over $\Q(\chi)$ and is only implemented as a $\Q(\chi)$-vector space: there is in general no mechanism to take linear combinations of forms in the space with coefficients belonging to a larger field. (Due to their importance, eigenforms are the single exception to this restriction; for an eigenform $F$, $\Q(F)$ is built on top of $\Q(\chi)$.) When the property $\Q(\chi) = \Q(E_{k}(\chi_{1},\chi_{2})$ does not hold, we cannot express $E$ as a $\Q(\chi)$-linear combination of the basis forms and many operations will fail. For this reason, the construction is currently disabled. The library syntax is \fun{GEN}{mfeisenstein}{long k, GEN CHI1 = NULL, GEN CHI2 = NULL}. \subsec{mfembed$(f,\{v\})$}\kbdsidx{mfembed}\label{se:mfembed} Let $f$ be a generalized modular form with parameters $[N,k,\chi,P]$ (see \kbd{mfparams}, we denote $\Q(\chi)$ the subfield of $\C$ generated by the values of $\chi$ and $\Q(f)$ the field of definition of $f$. In this context $\Q(\chi)$ has a single canonical complex embeding given by $s: \kbd{Mod(t, polcyclo(n,t))} \mapsto \exp(2i\pi/n)$ and the number field $\Q(f)$ has $[\Q(f):\Q(\chi)]$ induced embeddings attached to the complex roots of the polynomial $s(P)$. If $\Q(f)$ is stricly larger than $\Q(\chi)$ we only allow an $f$ which is an eigenform, produced by \kbd{mfeigenbasis}. This function is meant to create embeddings of $\Q(f)$ and/or apply them to the object $v$, typically a vector of Fourier coefficients of $f$ from \kbd{mfcoefs}. \item If $v$ is omitted and $f$ is a modular form as above, we return the embedding of $\Q(\chi)$ if $\Q(\chi) = \Q(f)$ and a vector containing $[\Q(f):\Q(\chi)]$ embeddings of $\Q(f)$ otherwise. \item If $v$ is given, it must be a scalar in $\Q(f)$, or a vector/matrix of such, we apply the embeddings coefficientwise and return either a single result if $\Q(f) = \Q(\chi)$ and a vector of $[\Q(f):\Q(\chi)]$ results otherwise. \item Finally $f$ can be replaced by a single embedding produced by \kbd{mfembed}$(f)$ ($v$ was omitted) and we apply that particular embedding to $v$. \bprog ? mf = mfinit([35,2,Mod(11,35)], 0); ? [f] = mfbasis(mf); ? f.mod \\@com $\Q(\chi) = \Q(\zeta_{3})$ %3 = t^2 + t + 1 ? v = mfcoefs(f,5); lift(v) \\@com coefficients in $\Q(\chi)$ %4 = [0, 2, -2*t - 2, 2*t, 2*t, -2*t - 2] ? mfembed(f, v) \\ single embedding %5 = [0, 2, -1 - 1.7320...*I, -1 + 1.73205...*I, -1 + 1.7320...*I, ...] ? [F] = mfeigenbasis(mf); ? mffields(mf) %7 = [y^2 + Mod(-2*t, t^2 + t + 1)] \\@com $[\Q(f):\Q(\chi)] = 2$ ? V = liftpol( mfcoefs(F,5) ); %8 = [0, 1, y + (-t - 1), (t + 1)*y + t, (-2*t - 2)*y + t, -t - 1] ? vall = mfembed(F, V); #vall %9 = 2 \\ 2 embeddings, both applied to V ? vall[1] \\ the first %10 = [0, 1, -1.2071... - 2.0907...*I, 0.2071... - 0.3587...*I, ...] ? vall[2] \\ and the second one %11 = [0, 1, 0.2071... + 0.3587...*I, -1.2071... + 2.0907...*I, ...] ? vE = mfembed(F); #vE \\ same 2 embeddings %12 = 2 ? mfembed(vE[1], V) \\ apply first embedding to V %13 = [0, 1, -1.2071... - 2.0907...*I, 0.2071... - 0.3587...*I, ...] @eprog For convenience, we also allow a modular form space from \kbd{mfinit} instead of $f$, corresponding to the single embedding of $\Q(\chi)$. \bprog ? [mfB,MC,C] = mfatkininit(mf,7); MC \\@com coefs in $\Q(\chi)$ %13 = [ Mod(2/7*t, t^2 + t + 1) Mod(-1/7*t - 2/7, t^2 + t + 1)] [Mod(-1/7*t - 2/7, t^2 + t + 1) Mod(2/7*t, t^2 + t + 1)] ? C \\ normalizing constant %14 = 0.33863... - 0.16787*I ? M = mfembed(mf, MC) / C \\ the true matrix for the action of w_7 [-0.6294... + 0.4186...*I -0.3625... - 0.5450...*I] [-0.3625... - 0.5450...*I -0.6294... + 0.4186...*I] ? exponent(M*conj(M) - 1) \\ M * conj(M) is close to 1 %16 = -126 @eprog The library syntax is \fun{GEN}{mfembed0}{GEN f, GEN v = NULL, long prec}. \subsec{mfeval$(\var{mf},F,\var{vtau})$}\kbdsidx{mfeval}\label{se:mfeval} Computes the numerical value of the modular form $F$, belonging to \var{mf}, at the complex number \kbd{vtau} or the vector \kbd{vtau} of complex numbers in the completed upper-half plane. The result is given with absolute error less than $2^{-B}$, where $B = \text{realbitprecision}$. If the field of definition $\Q(F)$ is larger than $\Q(\chi)$ then $F$ may be embedded into $\C$ in $d=[\Q(F):\Q(\chi)]$ ways, in which case a vector of the $d$ results is returned. \bprog ? mf = mfinit([11,2],0); F = mfbasis(mf)[1]; mfparams(F) %1 = [11, 2, 1, y, t-1] \\ Q(F) = Q(chi) = Q ? mfeval(mf,F,I/2) %2 = 0.039405471130100890402470386372028382117 ? mf = mfinit([35,2],0); F = mfeigenbasis(mf)[2]; mfparams(F) %3 = [35, 2, 1, y^2 - y - 4, t - 1] \\ [Q(F) : Q(chi)] = 2 ? mfeval(mf,F,I/2) %4 = [0.045..., 0.0385...] \\ sigma_1(F) and sigma_2(F) at I/2 ? mf = mfinit([12,4],1); F = mfbasis(mf)[1]; ? mfeval(mf, F, 0.318+10^(-7)*I) %6 = 3.379... E-21 + 6.531... E-21*I \\ instantaneous ! @eprog\noindent In order to maximize the imaginary part of the argument, the function computes $(f \mid_{k} \gamma)(\gamma^{-1}\cdot\tau)$ for a suitable $\gamma$ not necessarily in $\Gamma_{0}(N)$ (in which case $f \mid \gamma$ is evaluated using \kbd{mfslashexpansion}). \bprog ? T = mfTheta(); mf = mfinit(T); mfeval(mf,T,[0,1/2,1,oo]) %1 = [1/2 - 1/2*I, 0, 1/2 - 1/2*I, 1] @eprog The library syntax is \fun{GEN}{mfeval}{GEN mf, GEN F, GEN vtau, long bitprec}. \subsec{mffields$(\var{mf})$}\kbdsidx{mffields}\label{se:mffields} Given \kbd{mf} as output by \kbd{mfinit} with parameters $(N,k,\chi)$, returns the vector of polynomials defining each Galois orbit of newforms over $\Q(\chi)$. \bprog ? mf = mfinit([35,2],0); mffields(mf) %1 = [y, y^2 - y - 4] @eprog\noindent Here the character is trivial so $\Q(\chi) = \Q)$ and there are 3 newforms: one is rational (corresponding to $y$), the other two are conjugate and defined over the quadratic field $\Q[y]/(y^{2}-y-4)$. \bprog ? [G,chi] = znchar(Mod(3,35)); ? zncharconductor(G,chi) %2 = 35 ? charorder(G,chi) %3 = 12 ? mf = mfinit([35, 2, [G,chi]],0); mffields(mf) %4 = [y, y] @eprog Here the character is primitive of order 12 and the two newforms are defined over $\Q(\chi) = \Q(\zeta_{12})$. \bprog ? mf = mfinit([35, 2, Mod(13,35)],0); mffields(mf) %3 = [y^2 + Mod(5*t, t^2 + 1)] @eprog This time the character has order 4 and there are two conjugate newforms over $\Q(\chi) = Q(i)$. The library syntax is \fun{GEN}{mffields}{GEN mf}. \subsec{mffromell$(E)$}\kbdsidx{mffromell}\label{se:mffromell} $E$ being an elliptic curve defined over $Q$ given by an integral model in \kbd{ellinit} format, computes a 3-component vector \kbd{[mf,F,v]}, where $F$ is the newform corresponding to $E$ by modularity, \kbd{mf} is the newspace to which $F$ belongs, and \kbd{v} gives the coefficients of $F$ on \kbd{mfbasis(mf)}. \bprog ? E = ellinit("26a1"); ? [mf,F,co] = mffromell(E); ? co %2 = [3/4, 1/4]~ ? mfcoefs(F, 5) %3 = [0, 1, -1, 1, 1, -3] ? ellan(E, 5) %4 = [1, -1, 1, 1, -3] @eprog The library syntax is \fun{GEN}{mffromell}{GEN E}. \subsec{mffrometaquo$(\var{eta},\{\fl=0\})$}\kbdsidx{mffrometaquo}\label{se:mffrometaquo} Modular form corresponding to the eta quotient matrix \kbd{eta}. If the valuation $v$ at infinity is fractional, returns $0$. If the eta quotient is not holomorphic but simply meromorphic, returns $0$ if $\fl=0$; returns the eta quotient (divided by $q$ to the power $-v$ if $v < 0$, i.e., with valuation $0$) if $\fl$ is set. \bprog ? mffrometaquo(Mat([1,1]),1) %1 = 0 ? mfcoefs(mffrometaquo(Mat([1,24])),6) %2 = [0, 1, -24, 252, -1472, 4830, -6048] ? mfcoefs(mffrometaquo([1,1;23,1]),10) %3 = [0, 1, -1, -1, 0, 0, 1, 0, 1, 0, 0] ? F = mffrometaquo([1,2;2,-1]); mfparams(F) %4 = [16, 1/2, 1, y, t - 1] ? mfcoefs(F,10) %5 = [1, -2, 0, 0, 2, 0, 0, 0, 0, -2, 0] ? mffrometaquo(Mat([1,-24])) %6 = 0 ? f = mffrometaquo(Mat([1,-24]),1); mfcoefs(f,6) %7 = [1, 24, 324, 3200, 25650, 176256, 1073720] @eprog\noindent For convenience, a \typ{VEC} is also accepted instead of a factorization matrix with a single row: \bprog ? f = mffrometaquo([1,24]); \\ also valid @eprog The library syntax is \fun{GEN}{mffrometaquo}{GEN eta, long flag}. \subsec{mffromlfun$(L)$}\kbdsidx{mffromlfun}\label{se:mffromlfun} Let $L$ being an $L$-function in any of the \kbd{lfun} formats representing a self-dual modular form (for instance an eigenform). Return \kbd{[NK,space,v]} when \kbd{mf = mfinit(NK,space)} is the modular form space containing the form and \kbd{mftobasis(mf, v)} will represent it on the space basis. If $L$ has rational coefficients, this will be enough to recognize the modular form in \var{mf}: \bprog ? L = lfuncreate(x^2+1); ? lfunan(L,10) %2 = [1, 1, 0, 1, 2, 0, 0, 1, 1, 2] ? [NK,space,v] = mffromlfun(L); NK %4 = [4, 1, -4] ? mf=mfinit(NK,space); w = mftobasis(mf,v) %5 = [1.0000000000000000000000000000000000000]~ ? [f] = mfbasis(mf); mfcoefs(f,10) \\ includes a_0 ! %6 = [1/4, 1, 1, 0, 1, 2, 0, 0, 1, 1, 2] @eprog If $L$ has inexact complex coefficients, one can for instance compute an eigenbasis for \var{mf} and check whether one of the attached $L$-function is reasonably close to $L$. In the example, we cheat by producing the $L$ function from an eigenform in a known space, but the function does not use this information: \bprog ? mf = mfinit([32,6,Mod(5,32)],0); ? [poldegree(K) | K<-mffields(mf)] %2 = [19] \\ one orbit, [Q(F) : Q(chi)] = 19 ? L = lfunmf(mf)[1][1]; \\ one of the 19 L-functions attached to F ? lfunan(L,3) %4 = [1, 5.654... - 0.1812...*I, -7.876... - 19.02...*I] ? [NK,space,v] = mffromlfun(L); NK %5 = [32, 6, Mod(5, 32)] ? vL = concat(lfunmf(mf)); \\ L functions for all cuspidal eigenforms ? an = lfunan(L,10); ? for (i = 1, #vL, if (normlp(lfunan(vL[i],10) - an, oo) < 1e-10, print(i))); 1 @eprog The library syntax is \fun{GEN}{mffromlfun}{GEN L, long prec}. \subsec{mffromqf$(Q,\{P\})$}\kbdsidx{mffromqf}\label{se:mffromqf} $Q$ being an even integral positive definite quadratic form and $P$ a homogeneous spherical polynomial for $Q$, computes a 3-component vector $[\var{mf},F,v]$, where $F$ is the theta function corresponding to $(Q,P)$, \var{mf} is the corresponding space of modular forms (from \kbd{mfinit}), and $v$ gives the coefficients of $F$ on \kbd{mfbasis(mf)}. \bprog ? [mf,F,v] = mffromqf(2*matid(10)); v %1 = [64/5, 4/5, 32/5]~ ? mfcoefs(F, 5) %2 = [1, 20, 180, 960, 3380, 8424] ? mfcoef(F, 10000) \\ number of ways of writing 10000 as sum of 10 squares %3 = 128205250571893636 ? mfcoefs(F, 10000); \\ fast ! time = 220ms ? [mf,F,v] = mffromqf([2,0;0,2],x^4-6*x^2*y^2+y^4); ? mfcoefs(F,10) %6 = [0, 4, -16, 0, 64, -56, 0, 0, -256, 324, 224] ? mfcoef(F,100000) \\ instantaneous %7 = 41304367104 @eprog Odd dimensions are supported, corresponding to forms of half-integral weight: \bprog ? [mf,F,v] = mffromqf(2*matid(3)); ? mfisequal(F, mfpow(mfTheta(),3)) %2 = 1 ? mfcoefs(F, 32) \\ illustrate Legendre's 3-square theorem %3 = [ 1, 6, 12, 8, 6, 24, 24, 0, 12, 30, 24, 24, 8, 24, 48, 0, 6, 48, 36, 24,24, 48, 24, 0, 24, 30, 72, 32, 0, 72, 48, 0, 12] @eprog The library syntax is \fun{GEN}{mffromqf}{GEN Q, GEN P = NULL}. \subsec{mfgaloisprojrep$(\var{mf},F)$}\kbdsidx{mfgaloisprojrep}\label{se:mfgaloisprojrep} \var{mf} being an \kbd{mf} output by \kbd{mfinit} in weight $1$, return a polynomial defining the field fixed by the kernel of the projective Artin representation attached to \var{F} (by Deligne--Serre). Currently only implemented for projective images $A_{4}$, $A_{5}$ and $S_{4}$. The type $A_{5}$ requires the \kbd{nflistdata} package to be installed. \bprog \\ A4 example ? mf = mfinit([4*31,1,Mod(87,124)],0); ? F = mfeigenbasis(mf)[1]; ? mfgaloistype(mf,F) %3 = -12 ? pol = mfgaloisprojrep(mf,F) %4 = x^12 + 68*x^10 + 4808*x^8 + ... + 4096 ? G = galoisinit(pol); galoisidentify(G) %5 = [12,3] \\A4 ? pol4 = polredbest(galoisfixedfield(G,G.gen[3], 1)) %6 = x^4 + 7*x^2 - 2*x + 14 ? polgalois(pol4) %7 = [12, 1, 1, "A4"] ? factor(nfdisc(pol4)) %8 = [ 2 4] [31 2] \\ S4 example ? mf = mfinit([4*37,1,Mod(105,148)],0); ? F = mfeigenbasis(mf)[1]; ? mfgaloistype(mf,F) %11 = -24 ? pol = mfgaloisprojrep(mf,F) %12 = x^24 + 24*x^22 + 256*x^20 + ... + 255488256 ? G = galoisinit(pol); galoisidentify(G) %13 = [24, 12] \\S4 ? pol4 = polredbest(galoisfixedfield(G,G.gen[3..4], 1)) %14 = x^4 - x^3 + 5*x^2 - 7*x + 12 ? polgalois(pol4) %15 = [24, -1, 1, "S4"] ? factor(nfdisc(pol4)) %16 = [ 2 2] [37 3] @eprog The library syntax is \fun{GEN}{mfgaloisprojrep}{GEN mf, GEN F, long prec}. \subsec{mfgaloistype$(\var{NK},\{F\})$}\kbdsidx{mfgaloistype}\label{se:mfgaloistype} \kbd{NK} being either \kbd{[N,1,CHI]} or an \kbd{mf} output by \kbd{mfinit} in weight $1$, gives the vector of types of Galois representations attached to each cuspidal eigenform, unless the modular form \kbd{F} is specified, in which case only for \kbd{F} (note that it is not tested whether \kbd{F} belongs to the correct modular form space, nor whether it is a cuspidal eigenform). Types $A_{4}$, $S_{4}$, $A_{5}$ are represented by minus their cardinality $-12$, $-24$, or $-60$, and type $D_{n}$ is represented by its cardinality, the integer $2n$: \bprog ? mfgaloistype([124,1, Mod(67,124)]) \\ A4 %1 = [-12] ? mfgaloistype([148,1, Mod(105,148)]) \\ S4 %2 = [-24] ? mfgaloistype([633,1, Mod(71,633)]) \\ D10, A5 %3 = [10, -60] ? mfgaloistype([239,1, -239]) \\ D6, D10, D30 %4 = [6, 10, 30] ? mfgaloistype([71,1, -71]) %5 = [14] ? mf = mfinit([239,1, -239],0); F = mfeigenbasis(mf)[2]; ? mfgaloistype(mf, F) %7 = 10 @eprog The function may also return~$0$ as a type when it failed to determine it; in this case the correct type is either~$-12$ or~$-60$, and most likely~$-12$. The library syntax is \fun{GEN}{mfgaloistype}{GEN NK, GEN F = NULL}. \subsec{mfhecke$(\var{mf},F,n)$}\kbdsidx{mfhecke}\label{se:mfhecke} $F$ being a modular form in modular form space \var{mf}, returns $T(n)F$, where $T(n)$ is the $n$-th Hecke operator. \misctitle{Warning} If $F$ is of level $MK*M*mftobasis(mf2,x),BE) %1 = [[1, 0, 0, 1, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0]~,\ [0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, -3, 0, 0]~ ? EI1 = mflinear(mf, E1); EI2=mflinear(mf, E2); @eprog\noindent These are the two eigenfunctions in the space \kbd{mf}, the first (resp., second) will have Shimura image a multiple of $BE[1]$ (resp., $BE[2]$). The function \kbd{mfkohneneigenbasis} does this directly. The library syntax is \fun{GEN}{mfkohnenbijection}{GEN mf}. \subsec{mfkohneneigenbasis$(\var{mf},\var{bij})$}\kbdsidx{mfkohneneigenbasis}\label{se:mfkohneneigenbasis} \kbd{mf} being a cuspidal space of half-integral weight $k\ge3/2$ and \kbd{bij} being the output of \kbd{mfkohnenbijection(mf)}, outputs a $3$-component vector \kbd{[mf0,BNEW,BEIGEN]}, where \kbd{BNEW} and \kbd{BEIGEN} are two matrices whose columns are the coefficients of a basis of the Kohnen new space and of the eigenforms on the basis of \kbd{mf} respectively, and \kbd{mf0} is the corresponding new space of integral weight $2k-1$. \bprog ? mf=mfinit([44,5/2],1);bij=mfkohnenbijection(mf); ? [mf0,BN,BE]=mfkohneneigenbasis(mf,bij); ? BN~ %2 = [2 0 0 -2 2 0 -8] [2 0 0 4 14 0 -32] ? BE~ %3 = [1 0 0 Mod(y-1, y^2-3) Mod(2*y+1, y^2-3) 0 Mod(-4*y-4, y^2-3)] ? lift(mfcoefs(mf,20)*BE[,1]) %4 = [0, 1, 0, 0, y - 1, 2*y + 1, 0, 0, 0, -4*y - 4, 0, 0,\ -5*y + 3, 0, 0, 0, -6, 0, 0, 0, 7*y + 9]~ @eprog The library syntax is \fun{GEN}{mfkohneneigenbasis}{GEN mf, GEN bij}. \subsec{mflinear$(\var{vF},v)$}\kbdsidx{mflinear}\label{se:mflinear} \kbd{vF} being a vector of generalized modular forms and \kbd{v} a vector of coefficients of same length, compute the linear combination of the entries of \kbd{vF} with coefficients \kbd{v}. \misctitle{Note} Use this in particular to subtract two forms $F$ and $G$ (with $vF=[F,G]$ and $v=[1,-1]$), or to multiply an form by a scalar $\lambda$ (with $vF=[F]$ and $v=[\lambda]$). \bprog ? D = mfDelta(); G = mflinear([D],[-3]); ? mfcoefs(G,4) %2 = [0, -3, 72, -756, 4416] @eprog For user convenience, we allow \item a modular form space \kbd{mf} as a \kbd{vF} argument, which is understood as \kbd{mfbasis(mf)}; \item in this case, we also allow a modular form $f$ as $v$, which is understood as \kbd{mftobasis}$(\var{mf}, f)$. \bprog ? T = mfpow(mfTheta(),7); F = mfShimura(T,-3); \\ Shimura lift for D=-3 ? mfcoefs(F,8) %2 = [-5/9, 280, 9240, 68320, 295960, 875280, 2254560, 4706240, 9471000] ? mf = mfinit(F); G = mflinear(mf,F); ? mfcoefs(G,8) %4 = [-5/9, 280, 9240, 68320, 295960, 875280, 2254560, 4706240, 9471000] @eprog\noindent This last construction allows to replace a general modular form by a simpler linear combination of basis functions, which is often more efficient: \bprog ? T10=mfpow(mfTheta(),10); mfcoef(T10, 10^4) \\ direct evaluation time = 399 ms. %5 = 128205250571893636 ? mf=mfinit(T10); F=mflinear(mf,T10); \\ instantaneous ? mfcoef(F, 10^4) \\ after linearization time = 67 ms. %7 = 128205250571893636 @eprog The library syntax is \fun{GEN}{mflinear}{GEN vF, GEN v}. \subsec{mfmanin$(\var{FS})$}\kbdsidx{mfmanin}\label{se:mfmanin} Given the modular symbol $FS$ associated to an eigenform $F$ by \kbd{mfsymbol(mf,F)}, computes the even and odd special polynomials as well as the even and odd periods $\omega^{+}$ and $\omega^{-}$ as a vector $[[P^{+},P^{-}],[\omega^{+},\omega^{-},r]]$, where $r=\Im(\omega^{+}\overline{\omega^{-}})/$. If $F$ has several embeddings into $\C$, give the vector of results corresponding to each embedding. \bprog ? D=mfDelta(); mf=mfinit(D); DS=mfsymbol(mf,D); ? [pols,oms]=mfmanin(DS); pols %2 = [[4*x^9 - 25*x^7 + 42*x^5 - 25*x^3 + 4*x],\ [-36*x^10 + 691*x^8 - 2073*x^6 + 2073*x^4 - 691*x^2 + 36]] ? oms %3 = [0.018538552324740326472516069364750571812,\ -0.00033105361053212432521308691198949874026*I, 4096/691] ? mf=mfinit([11,2],0); F=mfeigenbasis(mf)[1]; FS=mfsymbol(mf,F); ? [pols,oms]=mfmanin(FS);pols %5 = [[0, 0, 0, 1, 1, 0, 0, -1, -1, 0, 0, 0],\ [2, 0, 10, 5, -5, -10, -10, -5, 5, 10, 0, -2]] ? oms[3] %6 = 24/5 @eprog The library syntax is \fun{GEN}{mfmanin}{GEN FS, long bitprec}. \subsec{mfmul$(F,G)$}\kbdsidx{mfmul}\label{se:mfmul} Multiply the two generalized modular forms $F$ and $G$. \bprog ? E4 = mfEk(4); G = mfmul(mfmul(E4,E4),E4); ? mfcoefs(G, 4) %2 = [1, 720, 179280, 16954560, 396974160] ? mfcoefs(mfpow(E4,3), 4) %3 = [1, 720, 179280, 16954560, 396974160] @eprog The library syntax is \fun{GEN}{mfmul}{GEN F, GEN G}. \subsec{mfnumcusps$(N)$}\kbdsidx{mfnumcusps}\label{se:mfnumcusps} Number of cusps of $\Gamma_{0}(N)$ \bprog ? mfnumcusps(24) %1 = 8 ? mfcusps(24) %1 = [0, 1/2, 1/3, 1/4, 1/6, 1/8, 1/12, 1/24] @eprog The library syntax is \fun{GEN}{mfnumcusps}{GEN N}. \subsec{mfparams$(F)$}\kbdsidx{mfparams}\label{se:mfparams} If $F$ is a modular form space, returns \kbd{[N,k,CHI,space,$\Phi$]}, level, weight, character $\chi$, and space code; where $\Phi$ is the cyclotomic polynomial defining the field of values of \kbd{CHI}. If $F$ is a generalized modular form, returns \kbd{[N,k,CHI,P,$\Phi$]}, where $P$ is the (polynomial giving the) field of definition of $F$ as a relative extension of the cyclotomic field $\Q(\chi) = \Q[t]/(\Phi)$: in that case the level $N$ may be a multiple of the level of $F$ and the polynomial $P$ may define a larger field than $\Q(F)$. If you want the true level of $F$ from this result, use \kbd{mfconductor(mfinit(F),F)}. The polynomial $P$ defines an extension of $\Q(\chi) = \Q[t]/(\Phi(t))$; it has coefficients in that number field (polmods in $t$). In contrast with \kbd{mfparams(F)[4]} which always gives the polynomial $P$ defining the relative extension $\Q(F)/\Q(\chi)$, the member function \kbd{$F$.mod} returns the polynomial used to define $\Q(F)$ over $\Q$ (either a cyclotomic polynomial or a polynomial with cyclotomic coefficients). \bprog ? E1 = mfeisenstein(4,-3,-4); E2 = mfeisenstein(3,5,-7); E3 = mfmul(E1,E2); ? apply(mfparams, [E1,E2,E3]) %2 = [[12, 4, 12, y, t-1], [35, 3, -35, y, t-1], [420, 7, -420, y, t-1]] ? mf = mfinit([36,2,Mod(13,36)],0); [f] = mfeigenbasis(mf); mfparams(mf) %3 = [36, 2, Mod(13, 36), 0, t^2 + t + 1] ? mfparams(f) %4 = [36, 2, Mod(13, 36), y, t^2 + t + 1] ? f.mod %5 = t^2 + t + 1 ? mf = mfinit([36,4,Mod(13,36)],0); [f] = mfeigenbasis(mf); ? lift(mfparams(f)) %7 = [36, 4, 13, y^3 + (2*t-2)*y^2 + (-4*t+6)*y + (10*t-1), t^2+t+1] @eprog The library syntax is \fun{GEN}{mfparams}{GEN F}. \subsec{mfperiodpol$(\var{mf},f,\{\fl=0\})$}\kbdsidx{mfperiodpol}\label{se:mfperiodpol} Period polynomial of the cuspidal part of the form $f$, in other words $\int_{0}^{i\infty}(X-\tau)^{k-2}f(\tau)\,d\tau$. If $\fl=0$, ordinary period polynomial. If it is $1$ or $-1$, even or odd part of that polynomial. $f$ can also be the modular symbol output by \kbd{mfsymbol}(mf,f). \bprog ? D = mfDelta(); mf = mfinit(D,0); ? PP = mfperiodpol(mf, D, -1); PP/=polcoef(PP, 1); bestappr(PP) %1 = x^9 - 25/4*x^7 + 21/2*x^5 - 25/4*x^3 + x ? PM = mfperiodpol(mf, D, 1); PM/=polcoef(PM, 0); bestappr(PM) %2 = -x^10 + 691/36*x^8 - 691/12*x^6 + 691/12*x^4 - 691/36*x^2 + 1 @eprog The library syntax is \fun{GEN}{mfperiodpol}{GEN mf, GEN f, long flag, long bitprec}. \subsec{mfperiodpolbasis$(k,\{\fl=0\})$}\kbdsidx{mfperiodpolbasis}\label{se:mfperiodpolbasis} Basis of period polynomials for weight $k$. If $\fl=1$ or $-1$, basis of odd or even period polynomials. \bprog ? mfperiodpolbasis(12,1) %1 = [x^8 - 3*x^6 + 3*x^4 - x^2, x^10 - 1] ? mfperiodpolbasis(12,-1) %2 = [4*x^9 - 25*x^7 + 42*x^5 - 25*x^3 + 4*x] @eprog The library syntax is \fun{GEN}{mfperiodpolbasis}{long k, long flag}. \subsec{mfpetersson$(\var{fs},\{\var{gs}\})$}\kbdsidx{mfpetersson}\label{se:mfpetersson} Petersson scalar product of the modular forms $f$ and $g$ belonging to the same modular form space \kbd{mf}, given by the corresponding ``modular symbols'' \kbd{fs} and \kbd{gs} output by \kbd{mfsymbol} (also in weight $1$ and half-integral weight, where symbols do not exist). If \kbd{gs} is omitted it is understood to be equal to \kbd{fs}. The scalar product is normalized by the factor $1/[\Gamma:\Gamma_{0}(N)]$. Note that $f$ and $g$ can both be noncuspidal, in which case the program returns an error if the product is divergent. If the fields of definition $\Q(f)$ and $\Q(g)$ are equal to $\Q(\chi)$ the result is a scalar. If $[\Q(f):\Q(\chi)]=d>1$ and $[\Q(g):\Q(\chi)]=e>1$ the result is a $d\times e$ matrix corresponding to all the embeddings of $f$ and $g$. In the intermediate cases $d=1$ or $e=1$ the result is a row or column vector. \bprog ? D=mfDelta(); mf=mfinit(D); DS=mfsymbol(mf,D); mfpetersson(DS) %1 = 1.0353620568043209223478168122251645932 E-6 ? mf=mfinit([11,6],0);B=mfeigenbasis(mf);BS=vector(#B,i,mfsymbol(mf,B[i])); ? mfpetersson(BS[1]) %3 = 1.6190120685220988139111708455305245466 E-5 ? mfpetersson(BS[1],BS[2]) %4 = [-3.826479006582967148 E-42 - 2.801547395385577002 E-41*I,\ 1.6661127341163336125 E-41 + 1.1734725972345985061 E-41*I,\ 0.E-42 - 6.352626992842664490 E-41*I]~ ? mfpetersson(BS[2]) %5 = [ 2.7576133733... E-5 2.0... E-42 6.3... E-43 ] [ -4.1... E-42 6.77837030070... E-5 3.3...E-42 ] [ -6.32...E-43 3.6... E-42 2.27268958069... E-5] ? mf=mfinit([23,2],0); F=mfeigenbasis(mf)[1]; FS=mfsymbol(mf,F); ? mfpetersson(FS) %5 = [0.0039488965740025031688548076498662860143 -3.56 ... E-40] [ -3.5... E-40 0.0056442542987647835101583821368582485396] @eprog Noncuspidal example: \bprog ? E1=mfeisenstein(5,1,-3);E2=mfeisenstein(5,-3,1); ? mf=mfinit([12,5,-3]); cusps=mfcusps(12); ? apply(x->mfcuspval(mf,E1,x),cusps) %3 = [0, 0, 1, 0, 1, 1] ? apply(x->mfcuspval(mf,E2,x),cusps) %4 = [1/3, 1/3, 0, 1/3, 0, 0] ? E1S=mfsymbol(mf,E1);E2S=mfsymbol(mf,E2); ? mfpetersson(E1S,E2S) %6 = -1.884821671646... E-5 - 1.9... E-43*I @eprog Weight 1 and 1/2-integral weight example: \bprog ? mf=mfinit([23,1,-23],1);F=mfbasis(mf)[1];FS=mfsymbol(mf,F); ? mfpetersson(mf,FS) %2 = 0.035149946790370230814006345508484787443 ? mf=mfinit([4,9/2],1);F=mfbasis(mf)[1];FS=mfsymbol(mf,F); ? mfpetersson(FS) %4 = 0.00015577084407139192774373662467908966030 @eprog The library syntax is \fun{GEN}{mfpetersson}{GEN fs, GEN gs = NULL}. \subsec{mfpow$(F,n)$}\kbdsidx{mfpow}\label{se:mfpow} Compute $F^{n}$, where $n$ is an integer and $F$ is a generalized modular form: \bprog ? G = mfpow(mfEk(4), 3); \\ E4^3 ? mfcoefs(G, 4) %2 = [1, 720, 179280, 16954560, 396974160] @eprog The library syntax is \fun{GEN}{mfpow}{GEN F, long n}. \subsec{mfsearch$(\var{NK},V,\{\var{space}\})$}\kbdsidx{mfsearch}\label{se:mfsearch} \kbd{NK} being of the form \kbd{[N,k]} with $k$ possibly half-integral, search for a modular form with rational coefficients, of weight $k$ and level $N$, whose initial coefficients $a(0)$,... are equal to $V$; \kbd{space} specifies the modular form spaces in which to search, in \kbd{mfinit} or \kbd{mfdim} notation. The output is a list of matching forms with that given level and weight. Note that the character is of the form $(D/.)$, where $D$ is a (positive or negative) fundamental discriminant dividing $N$. The forms are sorted by increasing $|D|$. The parameter $N$ can be replaced by a vector of allowed levels, in which case the list of forms is sorted by increasing level, then increasing $|D|$. If a form is found at level $N$, any multiple of $N$ with the same $D$ is not considered. Some useful possibilities are \item \kbd{[$N_{1}$..$N_{2}$]}: all levels between $N_{1}$ and $N_{2}$, endpoints included; \item \kbd{$F$ * [$N_{1}$..$N_{2}$]}: same but levels divisible by $F$; \item \kbd{divisors}$(N_{0})$: all levels dividing $N_{0}$. Note that this is different from \kbd{mfeigensearch}, which only searches for rational eigenforms. \bprog ? F = mfsearch([[1..40], 2], [0,1,2,3,4], 1); #F %1 = 3 ? [ mfparams(f)[1..3] | f <- F ] %2 = [[38, 2, 1], [40, 2, 8], [40, 2, 40]] ? mfcoefs(F[1],10) %3 = [0, 1, 2, 3, 4, -5, -8, 1, -7, -5, 7] @eprog The library syntax is \fun{GEN}{mfsearch}{GEN NK, GEN V, long space}. \subsec{mfshift$(F,s)$}\kbdsidx{mfshift}\label{se:mfshift} Divide the generalized modular form $F$ by $q^{s}$, omitting the remainder if there is one. One can have $s<0$. \bprog ? D=mfDelta(); mfcoefs(mfshift(D,1), 4) %1 = [1, -24, 252, -1472, 4830] ? mfcoefs(mfshift(D,2), 4) %2 = [-24, 252, -1472, 4830, -6048] ? mfcoefs(mfshift(D,-1), 4) %3 = [0, 0, 1, -24, 252] @eprog The library syntax is \fun{GEN}{mfshift}{GEN F, long s}. \subsec{mfshimura$(\var{mf},F,\{D=1\})$}\kbdsidx{mfshimura}\label{se:mfshimura} $F$ being a modular form of half-integral weight $k\geq 3/2$ and $D$ a positive squarefree integer, returns the Shimura lift $G$ of weight $2k-1$ corresponding to $D$. This function returns $[\var{mf2},G,v]$ where \var{mf2} is a modular form space containing $G$ and $v$ expresses $G$ in terms of \kbd{mfbasis}$(\var{mf2})$; so that $G$ is \kbd{mflinear}$(\var{mf2},v)$. \bprog ? F = mfpow(mfTheta(), 7); mf = mfinit(F); ? [mf2, G, v] = mfshimura(mf, F, 3); mfcoefs(G,5) %2 = [-5/9, 280, 9240, 68320, 295960, 875280] ? mfparams(G) \\ the level may be lower than expected %3 = [1, 6, 1, y, t - 1] ? mfparams(mf2) %4 = [2, 6, 1, 4, t - 1] ? v %5 = [280, 0]~ ? mfcoefs(mf2, 5) %6 = [-1/504 -1/504] [ 1 0] [ 33 1] [ 244 0] [ 1057 33] [ 3126 0] ? mf = mfinit([60,5/2],1); F = mflinear(mf,mfkohnenbasis(mf)[,1]); ? mfparams(mfshimura(mf,F)[2]) %8 = [15, 4, 1, y, t - 1] ? mfparams(mfshimura(mf,F,6)[2]) %9 = [15, 4, 1, y, t - 1] @eprog The library syntax is \fun{GEN}{mfshimura}{GEN mf, GEN F, long D}. \subsec{mfslashexpansion$(\var{mf},f,g,n,\var{flrat},\{\&\var{params}\})$}\kbdsidx{mfslashexpansion}\label{se:mfslashexpansion} Let \var{mf} be a modular form space in level $N$, $f$ a modular form belonging to \var{mf} and let $g$ be in $M_{2}^{+}(Q)$. This function computes the Fourier expansion of $f|_{k} g$ to $n$ terms. We first describe the behaviour when \kbd{flrat} is 0: the result is a vector $v$ of floating point complex numbers such that $$f|_{k} g(\tau) = q^{\alpha} \sum_{m\ge0} v[m+1] q^{m/w},$$ where $q = e(\tau)$, $w$ is the width of the cusp $g(i\infty)$ (namely $(N/(c^{2},N)$ if $g$ is integral) and $\alpha$ is a rational number. If \kbd{params} is given, it is set to the parameters $[\alpha,w, \kbd{matid}(2)]$. If \kbd{flrat} is 1, the program tries to rationalize the expression, i.e., to express the coefficients as rational numbers or polmods. We write $g = \lambda \cdot M \cdot A$ where $\lambda \in \Q^{*}$, $M\in \text{SL}_{2}(\Z)$ and $A = [a,b;0,d]$ is upper triangular, integral and primitive with $a > 0$, $d > 0$ and $0 \leq b < d$. Let $\alpha$ and $w$ by the parameters attached to the expansion of $F := f |_{k} M$ as above, i.e. $$ F(\tau) = q^{\alpha} \sum_{m\ge0} v[m+1] q^{m/w}.$$ The function returns the expansion $v$ of $F = f |_{k} M$ and sets the parameters to $[\alpha, w, A]$. Finally, the desired expansion is $(a/d)^{k/2} F(\tau + b/d)$. The latter is identical to the returned expansion when $A$ is the identity, i.e. when $g\in \text{PSL}_{2}(\Z)$. If this is not the case, the expansion differs from $v$ by the multiplicative constant $(a/d)^{k/2} e(\alpha b/(dw))$ and a twist by a root of unity $q^{1/w} \to e(b/(dw)) q^{1/w}$. The complications introduced by this extra matrix $A$ allow to recognize the coefficients in a much smaller cyclotomic field, hence to obtain a simpler description overall. (Note that this rationalization step may result in an error if the program cannot perform it.) \bprog ? mf = mfinit([32,4],0); f = mfbasis(mf)[1]; ? mfcoefs(f, 10) %2 = [0, 3, 0, 0, 0, 2, 0, 0, 0, 47, 0] ? mfatk = mfatkininit(mf,32); mfcoefs(mfatkin(mfatk,f),10) / mfatk[3] %3 = [0, 1, 0, 16, 0, 22, 0, 32, 0, -27, 0] ? mfatk[3] \\ here normalizing constant C = 1, but need in general %4 = 1 ? mfslashexpansion(mf,f,[0,-1;1,0],10,1,¶ms) * 32^(4/2) %5 = [0, 1, 0, 16, 0, 22, 0, 32, 0, -27, 0] ? params %6 = [0, 32, [1, 0; 0, 1]] ? mf = mfinit([12,8],0); f = mfbasis(mf)[1]; ? mfslashexpansion(mf,f,[1,0;2,1],7,0) %7 = [0, 0, 0, 0.6666666... + 0.E-38*I, 0, -3.999999... + 6.92820...*I, 0,\ -11.99999999... - 20.78460969...*I] ? mfslashexpansion(mf,f,[1,0;2,1],7,1, ¶ms) %8 = [0, 0, 0, 2/3, 0, Mod(8*t, t^2+t+1), 0, Mod(-24*t-24, t^2+t+1)] ? params %9 = [0, 3, [1, 0; 0, 1]] @eprog If $[\Q(f):\Q(\chi)]>1$, the coefficients may be polynomials in $y$, where $y$ is any root of the polynomial giving the field of definition of $f$ (\kbd{f.mod} or \kbd{mfparams(f)[4]}). \bprog ? mf=mfinit([23,2],0);f=mfeigenbasis(mf)[1]; ? mfcoefs(f,5) %1 = [Mod(0, y^2 - y - 1), Mod(1, y^2 - y - 1), Mod(-y, y^2 - y - 1),\ Mod(2*y - 1, y^2 - y - 1), Mod(y - 1, y^2 - y - 1), Mod(-2*y, y^2 - y - 1)] ? mfslashexpansion(mf,f,[1,0;0,1],5,1) %2 = [0, 1, -y, 2*y - 1, y - 1, -2*y] ? mfslashexpansion(mf,f,[0,-1;1,0],5,1) %3 = [0, -1/23, 1/23*y, -2/23*y + 1/23, -1/23*y + 1/23, 2/23*y] @eprog \misctitle{Caveat} In half-integral weight, we \emph{define} the ``slash'' operation as $$(f |_{k} g)(\tau) := \big((c \tau + d)^{-1/2}\big)^{2k} f( g\cdot \tau),$$ with the principal determination of the square root. In particular, the standard cocycle condition is no longer satisfied and we only have $f | (gg') = \pm (f | g) | g'$. The library syntax is \fun{GEN}{mfslashexpansion}{GEN mf, GEN f, GEN g, long n, long flrat, GEN *params = NULL, long prec}. \subsec{mfspace$(\var{mf},\{f\})$}\kbdsidx{mfspace}\label{se:mfspace} Identify the modular space \var{mf}, resp.~the modular form $f$ in \var{mf} if present, as the flag given to \kbd{mfinit}. Returns 0 (newspace), 1 (cuspidal space), 2 (old space), 3 (Eisenstein space) or 4 (full space). \bprog ? mf = mfinit([1,12],1); mfspace(mf) %1 = 1 ? mfspace(mf, mfDelta()) %2 = 0 \\ new space @eprog\noindent This function returns $-1$ when the form $f$ is modular but does not belong to the space. \bprog ? mf = mfinit([1,2]; mfspace(mf, mfEk(2)) %3 = -1 @eprog When $f$ is not modular and is for instance only quasi-modular, the function returns nonsense: \bprog ? M6 = mfinit([1,6]); ? dE4 = mfderiv(mfEk(4)); \\ not modular ! ? mfspace(M6,dE4) \\ asserts (wrongly) that E4' belongs to new space %3 = 0 @eprog The library syntax is \fun{long}{mfspace}{GEN mf, GEN f = NULL}. \subsec{mfsplit$(\var{mf},\{\var{dimlim}=0\},\{\fl=0\})$}\kbdsidx{mfsplit}\label{se:mfsplit} \kbd{mf} from \kbd{mfinit} with integral weight containing the new space (either the new space itself or the cuspidal space or the full space), and preferably the newspace itself for efficiency, split the space into Galois orbits of eigenforms of the newspace, satisfying various restrictions. The functions returns $[vF, vK]$, where $vF$ gives (Galois orbit of) eigenforms and $vK$ is a list of polynomials defining each Galois orbit. The eigenforms are given in \kbd{mftobasis} format, i.e. as a matrix whose columns give the forms with respect to \kbd{mfbasis(mf)}. If \kbd{dimlim} is set, only the Galois orbits of dimension $\leq \kbd{dimlim}$ are computed (i.e. the rational eigenforms if $\kbd{dimlim} = 1$ and the character is real). This can considerably speed up the function when a Galois orbit is defined over a large field. $\fl$ speeds up computations when the dimension is large: if $\fl=d>0$, when the dimension of the eigenspace is $>d$, only the Galois polynomial is computed. Note that the function \kbd{mfeigenbasis} returns all eigenforms in an easier to use format (as modular forms which can be input as is in other functions); \kbd{mfsplit} is only useful when you can restrict to orbits of small dimensions, e.g. rational eigenforms. \bprog ? mf=mfinit([11,2],0); f=mfeigenbasis(mf)[1]; mfcoefs(f,16) %1 = [0, 1, -2, -1, ...] ? mf=mfinit([23,2],0); f=mfeigenbasis(mf)[1]; mfcoefs(f,16) %2 = [Mod(0, z^2 - z - 1), Mod(1, z^2 - z - 1), Mod(-z, z^2 - z - 1), ...] ? mf=mfinit([179,2],0); apply(poldegree, mffields(mf)) %3 = [1, 3, 11] ? mf=mfinit([719,2],0); ? [vF,vK] = mfsplit(mf, 5); \\ fast when restricting to small orbits time = 192 ms. ? #vF \\ a single orbit %5 = 1 ? poldegree(vK[1]) \\ of dimension 5 %6 = 5 ? [vF,vK] = mfsplit(mf); \\ general case is slow time = 2,104 ms. ? apply(poldegree,vK) %8 = [5, 10, 45] \\ because degree 45 is large... @eprog The library syntax is \fun{GEN}{mfsplit}{GEN mf, long dimlim, long flag}. \subsec{mfsturm$(\var{NK})$}\kbdsidx{mfsturm}\label{se:mfsturm} Gives the Sturm bound for modular forms on $\Gamma_{0}(N)$ and weight $k$, i.e., an upper bound for the order of the zero at infinity of a nonzero form. \kbd{NK} is either \item a pair $[N,k]$, in which case the bound is the floor of $(kN/12) \cdot \prod_{p\mid N} (1+1/p)$; \item or the output of \tet{mfinit} in which case the exact upper bound is returned. \bprog ? NK = [96,6]; mfsturm(NK) %1 = 97 ? mf=mfinit(NK,1); mfsturm(mf) %2 = 76 ? mfdim(NK,0) \\ new space %3 = 72 @eprog The library syntax is \fun{long}{mfsturm}{GEN NK}. \subsec{mfsymbol$(\var{mf},f)$}\kbdsidx{mfsymbol}\label{se:mfsymbol} Initialize data for working with all period polynomials of the modular form $f$: this is essential for efficiency for functions such as \kbd{mfsymboleval}, \kbd{mfmanin}, and \kbd{mfpetersson}. An \kbd{mfsymbol} contains an \kbd{mf} structure and can always be used whenever an \kbd{mf} would be needed. \bprog ? mf=mfinit([23,2],0);F=mfeigenbasis(mf)[1]; ? FS=mfsymbol(mf,F); ? mfsymboleval(FS,[0,oo]) %3 = [8.762565143790690142 E-39 + 0.0877907874...*I, -5.617375463602574564 E-39 + 0.0716801031...*I] ? mfpetersson(FS) %4 = [0.0039488965740025031688548076498662860143 1.2789721111175127425 E-40] [1.2630501762985554269 E-40 0.0056442542987647835101583821368582485396] @eprog\noindent By abuse of language, initialize data for working with \kbd{mfpetersson} in weight $1$ and half-integral weight (where no symbol exist); the \kbd{mf} argument may be an \kbd{mfsymbol} attached to a form on the space, which avoids recomputing data independent of the form. \bprog ? mf=mfinit([12,9/2],1); F=mfbasis(mf); ? fs=mfsymbol(mf,F[1]); time = 476 ms ? mfpetersson(fs) %2 = 1.9722437519492014682047692073275406145 E-5 ? f2s = mfsymbol(mf,F[2]); time = 484 ms. ? mfpetersson(f2s) %4 = 1.2142222531326333658647877864573002476 E-5 ? gs = mfsymbol(fs,F[2]); \\ re-use existing symbol, a little faster time = 430 ms. ? mfpetersson(gs) == %4 \\ same value %6 = 1 @eprog For simplicity, we also allow \kbd{mfsymbol(f)} instead of \kbd{mfsymbol(mfinit(f), f)}: The library syntax is \fun{GEN}{mfsymbol}{GEN mf, GEN f = NULL, long bitprec}. \subsec{mfsymboleval$(\var{fs},\var{path},\{\var{ga}=\var{id}\})$}\kbdsidx{mfsymboleval}\label{se:mfsymboleval} Evaluation of the modular symbol $fs$ (corresponding to the modular form $f$) output by \kbd{mfsymbol} on the given path \kbd{path}, where \kbd{path} is either a vector $[s_{1},s_{2}]$ or an integral matrix $[a,b;c,d]$ representing the path $[a/c,b/d]$. In both cases $s_{1}$ or $s_{2}$ (or $a/c$ or $b/d$) can also be elements of the upper half-plane. To avoid possibly lengthy \kbd{mfsymbol} computations, the program also accepts $fs$ of the form \kbd{[mf,F]}, but in that case $s_{1}$ and $s_{2}$ are limited to \kbd{oo} and elements of the upper half-plane. The result is the polynomial equal to $\int_{s_{1}}^{s_{2}}(X-\tau)^{k-2}F(\tau)\,d\tau$, the integral being computed along a geodesic joining $s_{1}$ and $s_{2}$. If \kbd{ga} in $GL_{2}^{+}(\Q)$ is given, replace $F$ by $F|_{k}\gamma$. Note that if the integral diverges, the result will be a rational function. If the field of definition $\Q(f)$ is larger than $\Q(\chi)$ then $f$ can be embedded into $\C$ in $d=[\Q(f):\Q(\chi)]$ ways, in which case a vector of the $d$ results is returned. \bprog ? mf=mfinit([35,2],1);f=mfbasis(mf)[1];fs=mfsymbol(mf,f); ? mfsymboleval(fs,[0,oo]) %1 = 0.31404011074188471664161704390256378537*I ? mfsymboleval(fs,[1,3;2,5]) %2 = -0.1429696291... - 0.2619975641...*I ? mfsymboleval(fs,[I,2*I]) %3 = 0.00088969563028739893631700037491116258378*I ? E2=mfEk(2);E22=mflinear([E2,mfbd(E2,2)],[1,-2]);mf=mfinit(E22); ? E2S = mfsymbol(mf,E22); ? mfsymboleval(E2S,[0,1]) %6 = (-1.00000...*x^2 + 1.00000...*x - 0.50000...)/(x^2 - x) @eprog The rational function which is given in case the integral diverges is easy to interpret. For instance: \bprog ? E4=mfEk(4);mf=mfinit(E4);ES=mfsymbol(mf,E4); ? mfsymboleval(ES,[I,oo]) %2 = 1/3*x^3 - 0.928067...*I*x^2 - 0.833333...*x + 0.234978...*I ? mfsymboleval(ES,[0,I]) %3 = (-0.234978...*I*x^3 - 0.833333...*x^2 + 0.928067...*I*x + 0.333333...)/x @eprog\noindent \kbd{mfsymboleval(ES,[a,oo])} is the limit as $T\to\infty$ of $$\int_{a}^{iT}(X-\tau)^{k-2}F(\tau)\,d\tau + a(0)(X-iT)^{k-1}/(k-1)\;,$$ where $a(0)$ is the $0$th coefficient of $F$ at infinity. Similarly, \kbd{mfsymboleval(ES,[0,a])} is the limit as $T\to\infty$ of $$\int_{i/T}^{a}(X-\tau)^{k-2}F(\tau)\,d\tau+b(0)(1+iTX)^{k-1}/(k-1)\;,$$ where $b(0)$ is the $0$th coefficient of $F|_{k} S$ at infinity. The library syntax is \fun{GEN}{mfsymboleval}{GEN fs, GEN path, GEN ga = NULL, long bitprec}. \subsec{mftaylor$(F,n,\{\var{flreal}=0\})$}\kbdsidx{mftaylor}\label{se:mftaylor} $F$ being a form in $M_{k}(SL_{2}(\Bbb Z))$, computes the first $n+1$ canonical Taylor expansion of $F$ around $\tau=I$. If \kbd{flreal=0}, computes only an algebraic equivalence class. If \kbd{flreal} is set, compute $p_{n}$ such that for $\tau$ close enough to $I$ we have $$f(\tau)=(2I/(\tau+I))^{k}\sum_{n>=0}p_{n}((\tau-I)/(\tau+I))^{n}\;.$$ \bprog ? D=mfDelta(); ? mftaylor(D,8) %2 = [1/1728, 0, -1/20736, 0, 1/165888, 0, 1/497664, 0, -11/3981312] @eprog The library syntax is \fun{GEN}{mftaylor}{GEN F, long n, long flreal, long prec}. \subsec{mftobasis$(\var{mf},F,\{\fl=0\})$}\kbdsidx{mftobasis}\label{se:mftobasis} Coefficients of the form $F$ on the basis given by \kbd{mfbasis(mf)}. A $q$-expansion or vector of coefficients can also be given instead of $F$, but in this case an error message may occur if the expansion is too short. An error message is also given if $F$ does not belong to the modular form space. If $\fl$ is set, instead of error messages the output is an affine space of solutions if a $q$-expansion or vector of coefficients is given, or the empty column otherwise. \bprog ? mf = mfinit([26,2],0); mfdim(mf) %1 = 2 ? F = mflinear(mf,[a,b]); mftobasis(mf,F) %2 = [a, b]~ @eprog A $q$-expansion or vector of coefficients can also be given instead of $F$. \bprog ? Th = 1 + 2*sum(n=1, 8, q^(n^2), O(q^80)); ? mf = mfinit([4,5,Mod(3,4)]); ? mftobasis(mf, Th^10) %3 = [64/5, 4/5, 32/5]~ @eprog If $F$ does not belong to the corresponding space, the result is incorrect and simply matches the coefficients of $F$ up to some bound, and the function may either return an empty column or an error message. If $\fl$ is set, there are no error messages, and the result is an empty column if $F$ is a modular form; if $F$ is supplied via a series or vector of coefficients which does not contain enough information to force a unique (potential) solution, the function returns $[v,K]$ where $v$ is a solution and $K$ is a matrix of maximal rank describing the affine space of potential solutions $v + K\cdot x$. \bprog ? mf = mfinit([4,12],1); ? mftobasis(mf, q-24*q^2+O(q^3), 1) %2 = [[43/64, -63/8, 800, 21/64]~, [1, 0; 24, 0; 2048, 768; -1, 0]] ? mftobasis(mf, [0,1,-24,252], 1) %3 = [[1, 0, 1472, 0]~, [0; 0; 768; 0]] ? mftobasis(mf, [0,1,-24,252,-1472], 1) %4 = [1, 0, 0, 0]~ \\ now uniquely determined ? mftobasis(mf, [0,1,-24,252,-1472,0], 1) %5 = [1, 0, 0, 0]~ \\ wrong result: no such form exists ? mfcoefs(mflinear(mf,%), 5) \\ double check %6 = [0, 1, -24, 252, -1472, 4830] ? mftobasis(mf, [0,1,-24,252,-1472,0]) *** at top-level: mftobasis(mf,[0,1, *** ^-------------------- *** mftobasis: domain error in mftobasis: form does not belong to space ? mftobasis(mf, mfEk(10)) *** at top-level: mftobasis(mf,mfEk( *** ^-------------------- *** mftobasis: domain error in mftobasis: form does not belong to space ? mftobasis(mf, mfEk(10), 1) %7 = []~ @eprog The library syntax is \fun{GEN}{mftobasis}{GEN mf, GEN F, long flag}. \subsec{mftocoset$(N,M,\var{Lcosets})$}\kbdsidx{mftocoset}\label{se:mftocoset} $M$ being a matrix in $SL_{2}(Z)$ and \kbd{Lcosets} being \kbd{mfcosets(N)}, a list of right cosets of $\Gamma_{0}(N)$, find the coset to which $M$ belongs. The output is a pair $[\gamma,i]$ such that $M = \gamma \kbd{Lcosets}[i]$, $\gamma\in\Gamma_{0}(N)$. \bprog ? N = 4; L = mfcosets(N); ? mftocoset(N, [1,1;2,3], L) %2 = [[-1, 1; -4, 3], 5] @eprog The library syntax is \fun{GEN}{mftocoset}{ulong N, GEN M, GEN Lcosets}. \subsec{mftonew$(\var{mf},F)$}\kbdsidx{mftonew}\label{se:mftonew} \kbd{mf} being being a full or cuspidal space with parameters $[N,k,\chi]$ and $F$ a cusp form in that space, returns a vector of 3-component vectors $[M,d,G]$, where $f(\chi)\mid M\mid N$, $d\mid N/M$, and $G$ is a form in $S_{k}^{\text{new}}(\Gamma_{0}(M),\chi)$ such that $F$ is equal to the sum of the $B(d)(G)$ over all these 3-component vectors. \bprog ? mf = mfinit([96,6],1); F = mfbasis(mf)[60]; s = mftonew(mf,F); #s %1 = 1 ? [M,d,G] = s[1]; [M,d] %2 = [48, 2] ? mfcoefs(F,10) %3 = [0, 0, -160, 0, 0, 0, 0, 0, 0, 0, -14400] ? mfcoefs(G,10) %4 = [0, 0, -160, 0, 0, 0, 0, 0, 0, 0, -14400] @eprog The library syntax is \fun{GEN}{mftonew}{GEN mf, GEN F}. \subsec{mftraceform$(\var{NK},\{\var{space}=0\})$}\kbdsidx{mftraceform}\label{se:mftraceform} If $NK=[N,k,CHI,.]$ as in \kbd{mfinit} with $k$ integral, gives the trace form in the corresponding subspace of $S_{k}(\Gamma_{0}(N),\chi)$. The supported values for \kbd{space} are 0: the newspace (default), 1: the full cuspidal space. \bprog ? F = mftraceform([23,2]); mfcoefs(F,16) %1 = [0, 2, -1, 0, -1, -2, -5, 2, 0, 4, 6, -6, 5, 6, 4, -10, -3] ? F = mftraceform([23,1,-23]); mfcoefs(F,16) %2 = [0, 1, -1, -1, 0, 0, 1, 0, 1, 0, 0, 0, 0, -1, 0, 0, -1] @eprog The library syntax is \fun{GEN}{mftraceform}{GEN NK, long space}. \subsec{mftwist$(F,D)$}\kbdsidx{mftwist}\label{se:mftwist} $F$ being a generalized modular form, returns the twist of $F$ by the integer $D$, i.e., the form $G$ such that \kbd{mfcoef(G,n)=}$(D/n)$\kbd{mfcoef(F,n)}, where $(D/n)$ is the Kronecker symbol. \bprog ? mf = mfinit([11,2],0); F = mfbasis(mf)[1]; mfcoefs(F, 5) %1 = [0, 1, -2, -1, 2, 1] ? G = mftwist(F,-3); mfcoefs(G, 5) %2 = [0, 1, 2, 0, 2, -1] ? mf2 = mfinit([99,2],0); mftobasis(mf2, G) %3 = [1/3, 0, 1/3, 0]~ @eprog\noindent Note that twisting multiplies the level by $D^{2}$. In particular it is not an involution: \bprog ? H = mftwist(G,-3); mfcoefs(H, 5) %4 = [0, 1, -2, 0, 2, 1] ? mfparams(G) %5 = [99, 2, 1, y, t - 1] @eprog The library syntax is \fun{GEN}{mftwist}{GEN F, GEN D}. \section{Modular symbols} Let $\Delta_{0} := \text{Div}^{0}(\P^{1}(\Q))$ be the abelian group of divisors of degree $0$ on the rational projective line. The standard $\text{GL}(2,\Q)$ action on $\P^{1}(\Q)$ via homographies naturally extends to $\Delta_{0}$. Given \item $G$ a finite index subgroup of $\text{SL}(2,\Z)$, \item a field $F$ and a finite dimensional representation $V/F$ of $\text{GL}(2,\Q)$, \noindent we consider the space of \emph{modular symbols} $M := \Hom_{G}(\Delta_{0}, V)$. This finite dimensional $F$-vector space is a $G$-module, canonically isomorphic to $H^{1}_{c}(X(G), V)$, and allows to compute modular forms for $G$. Currently, we only support the groups $\Gamma_{0}(N)$ ($N > 0$ an integer) and the representations $V_{k} = \Q[X,Y]_{k-2}$ ($k \geq 2$ an integer) over $\Q$. We represent a space of modular symbols by an \var{ms} structure, created by the function \tet{msinit}. It encodes basic data attached to the space: chosen $\Z[G]$-generators $(g_{i})$ for $\Delta_{0}$ (and relations among those) and an $F$-basis of $M$. A modular symbol $s$ is thus given either in terms of this fixed basis, or as a collection of values $s(g_{i})$ satisfying certain relations. A subspace of $M$ (e.g. the cuspidal or Eisenstein subspaces, the new or old modular symbols, etc.) is given by a structure allowing quick projection and restriction of linear operators; its first component is a matrix whose columns form an $F$-basis of the subspace. \subsec{msatkinlehner$(M,Q,\{H\})$}\kbdsidx{msatkinlehner}\label{se:msatkinlehner} Let $M$ be a full modular symbol space of level $N$, as given by \kbd{msinit}, let $Q \mid N$, $(Q,N/Q) = 1$, and let $H$ be a subspace stable under the Atkin-Lehner involution $w_{Q}$. Return the matrix of $w_{Q}$ acting on $H$ ($M$ if omitted). \bprog ? M = msinit(36,2); \\ M_2(Gamma_0(36)) ? w = msatkinlehner(M,4); w^2 == 1 %2 = 1 ? #w \\ involution acts on a 13-dimensional space %3 = 13 ? M = msinit(36,2, -1); \\ M_2(Gamma_0(36))^- ? w = msatkinlehner(M,4); w^2 == 1 %5 = 1 ? #w %6 = 4 @eprog The library syntax is \fun{GEN}{msatkinlehner}{GEN M, long Q, GEN H = NULL}. \subsec{mscosets$(\var{gen},\var{inH})$}\kbdsidx{mscosets}\label{se:mscosets} \kbd{gen} being a system of generators for a group $G$ and $H$ being a subgroup of finite index in $G$, return a list of right cosets of $H\backslash G$ and the right action of $G$ on $H\backslash G$. The subgroup $H$ is given by a criterion \kbd{inH} (closure) deciding whether an element of $G$ belongs to $H$. The group $G$ is restricted to types handled by generic multiplication (\kbd{*}) and inversion (\kbd{g\pow (-1)}), such as matrix groups or permutation groups. Let $\kbd{gens} = [g_{1}, \dots, g_{r}]$. The function returns $[C,M]$ where $C$ lists the $h = [G:H]$ representatives $[\gamma_{1}, \dots, \gamma_{h}]$ for the right cosets $H\gamma_{1},\dots,H\gamma_{h}$; $\gamma_{1}$ is always the neutral element in $G$. For all $i \leq h$, $j \leq r$, if $M[i][j] = k$ then $H \gamma_{i} g_{j} = H\gamma_{k}$. \bprog ? PSL2 = [[0,1;-1,0], [1,1;0,1]]; \\ S and T \\ G = PSL2, H = Gamma0(2) ? [C, M] = mscosets(PSL2, g->g[2,1] % 2 == 0); ? C \\ three cosets %3 = [[1, 0; 0, 1], [0, 1; -1, 0], [0, 1; -1, -1]] ? M %4 = [Vecsmall([2, 1]), Vecsmall([1, 3]), Vecsmall([3, 2])] @eprog\noindent Looking at $M[1]$ we see that $S$ belongs to the second coset and $T$ to the first (trivial) coset. The library syntax is \fun{GEN}{mscosets0}{GEN gen, GEN inH}. Also available is the function \fun{GEN}{mscosets}{GEN G, void *E, long (*inH)(void *, GEN)} \subsec{mscuspidal$(M,\{\fl=0\})$}\kbdsidx{mscuspidal}\label{se:mscuspidal} $M$ being a full modular symbol space, as given by \kbd{msinit}, return its cuspidal part $S$. If $\fl = 1$, return $[S,E]$ its decomposition into cuspidal and Eisenstein parts. A subspace is given by a structure allowing quick projection and restriction of linear operators; its first component is a matrix with integer coefficients whose columns form a $\Q$-basis of the subspace. \bprog ? M = msinit(2,8, 1); \\ M_8(Gamma_0(2))^+ ? [S,E] = mscuspidal(M, 1); ? E[1] \\ 2-dimensional %3 = [0 -10] [0 -15] [0 -3] [1 0] ? S[1] \\ 1-dimensional %4 = [ 3] [30] [ 6] [-8] @eprog The library syntax is \fun{GEN}{mscuspidal}{GEN M, long flag}. \subsec{msdim$(M)$}\kbdsidx{msdim}\label{se:msdim} $M$ being a full modular symbol space or subspace, for instance as given by \kbd{msinit} or \kbd{mscuspidal}, return its dimension as a $\Q$-vector space. \bprog ? M = msinit(11,4); msdim(M) %1 = 6 ? M = msinit(11,4,1); msdim(M) %2 = 4 \\ dimension of the '+' part ? [S,E] = mscuspidal(M,1); ? [msdim(S), msdim(E)] %4 = [2, 2] @eprog\noindent Note that \kbd{mfdim([N,k])} is going to be much faster if you only need the dimension of the space and not really to work with it. This function is only useful to quickly check the dimension of an existing space. The library syntax is \fun{long}{msdim}{GEN M}. \subsec{mseisenstein$(M)$}\kbdsidx{mseisenstein}\label{se:mseisenstein} $M$ being a full modular symbol space, as given by \kbd{msinit}, return its Eisenstein subspace. A subspace is given by a structure allowing quick projection and restriction of linear operators; its first component is a matrix with integer coefficients whose columns form a $\Q$-basis of the subspace. This is the same basis as given by the second component of \kbd{mscuspidal}$(M, 1)$. \bprog ? M = msinit(2,8, 1); \\ M_8(Gamma_0(2))^+ ? E = mseisenstein(M); ? E[1] \\ 2-dimensional %3 = [0 -10] [0 -15] [0 -3] [1 0] ? E == mscuspidal(M,1)[2] %4 = 1 @eprog The library syntax is \fun{GEN}{mseisenstein}{GEN M}. \subsec{mseval$(M,s,\{p\})$}\kbdsidx{mseval}\label{se:mseval} Let $\Delta_{0}:=\text{Div}^{0}(\P^{1} (\Q))$. Let $M$ be a full modular symbol space, as given by \kbd{msinit}, let $s$ be a modular symbol from $M$, i.e. an element of $\Hom_{G}(\Delta_{0}, V)$, and let $p=[a,b] \in \Delta_{0}$ be a path between two elements in $\P^{1}(\Q)$, return $s(p)\in V$. The path extremities $a$ and $b$ may be given as \typ{INT}, \typ{FRAC} or $\kbd{oo} = (1:0)$; it is also possible to describe the path by a $2 \times 2$ integral matrix whose columns give the two cusps. The symbol $s$ is either \item a \typ{COL} coding a modular symbol in terms of the fixed basis of $\Hom_{G}(\Delta_{0},V)$ chosen in $M$; if $M$ was initialized with a nonzero \emph{sign} ($+$ or $-$), then either the basis for the full symbol space or the $\pm$-part can be used (the dimension being used to distinguish the two). \item a \typ{MAT} whose columns encode modular symbols as above. This is much faster than evaluating individual symbols on the same path $p$ independently. \item a \typ{VEC} $(v_{i})$ of elements of $V$, where the $v_{i} = s(g_{i})$ give the image of the generators $g_{i}$ of $\Delta_{0}$, see \tet{mspathgens}. We assume that $s$ is a proper symbol, i.e.~that the $v_{i}$ satisfy the \kbd{mspathgens} relations. If $p$ is omitted, convert a single symbol $s$ to the second form: a vector of the $s(g_{i})$. A \typ{MAT} is converted to a vector of such. \bprog ? M = msinit(2,8,1); \\ M_8(Gamma_0(2))^+ ? g = mspathgens(M)[1] %2 = [[+oo, 0], [0, 1]] ? N = msnew(M)[1]; #N \\ Q-basis of new subspace, dimension 1 %3 = 1 ? s = N[,1] \\ t_COL representation %4 = [-3, 6, -8]~ ? S = mseval(M, s) \\ t_VEC representation %5 = [64*x^6-272*x^4+136*x^2-8, 384*x^5+960*x^4+192*x^3-672*x^2-432*x-72] ? mseval(M,s, g[1]) %6 = 64*x^6 - 272*x^4 + 136*x^2 - 8 ? mseval(M,S, g[1]) %7 = 64*x^6 - 272*x^4 + 136*x^2 - 8 @eprog\noindent Note that the symbol should have values in $V = \Q[x,y]_{k-2}$, we return the de-homogenized values corresponding to $y = 1$ instead. The library syntax is \fun{GEN}{mseval}{GEN M, GEN s, GEN p = NULL}. \subsec{msfarey$(F,\var{inH},\{\&\var{CM}\})$}\kbdsidx{msfarey}\label{se:msfarey} $F$ being a Farey symbol attached to a group $G$ contained in $\text{PSL}_{2}(\Z)$ and $H$ a subgroup of $G$, return a Farey symbol attached to $H$. The subgroup $H$ is given by a criterion \kbd{inH} (closure) deciding whether an element of $G$ belongs to $H$. The symbol $F$ can be created using \item \kbd{mspolygon}: $G = \Gamma_{0}(N)$, which runs in time $\tilde{O}(N)$; \item or \kbd{msfarey} itself, which runs in time $O([G:H]^{2})$. If present, the argument \kbd{CM} is set to \kbd{mscosets(F[3])}, giving the right cosets of $H \backslash G$ and the action of $G$ by right multiplication. Since \kbd{msfarey}'s algorithm is quadratic in the index $[G:H]$, it is advisable to construct subgroups by a chain of inclusions if possible. \bprog \\ Gamma_0(N) G0(N) = mspolygon(N); \\ Gamma_1(N): direct construction, slow G1(N) = msfarey(mspolygon(1), g -> my(a = g[1,1]%N, c = g[2,1]%N);\ c == 0 && (a == 1 || a == N-1)); \\ Gamma_1(N) via Gamma_0(N): much faster G1(N) = msfarey(G0(N), g -> my(a=g[1,1]%N); a==1 || a==N-1); @eprog\noindent Note that the simpler criterion \kbd{g[1,1]\%N == 1} would not be correct since it must apply to elements of $\text{PSL}_{2}(\Z)$ hence be invariant under $g \mapsto -g$. Here are other examples: \bprog \\ Gamma(N) G(N) = msfarey(G1(N), g -> g[1,2]%N==0); G_00(N) = msfarey(G0(N), x -> x[1,2]%N==0); G1_0(N1,N2) = msfarey(G0(1), x -> x[2,1]%N1==0 && x[1,2]%N2==0); \\ Gamma_0(91) has 4 elliptic points of order 3, Gamma_1(91) has none D0 = mspolygon(G0(91), 2)[4]; D1 = mspolygon(G1(91), 2)[4]; write("F.tex","\\documentclass{article}\\usepackage{tikz}\\begin{document}",\ D0,"\n",D1,"\\end{document}"); @eprog The library syntax is \fun{GEN}{msfarey0}{GEN F, GEN inH, GEN *CM = NULL}. Also available is \fun{GEN}{msfarey}{GEN F, void *E, long (*inH)(void *, GEN), GEN *pCM}. \subsec{msfromcusp$(M,c)$}\kbdsidx{msfromcusp}\label{se:msfromcusp} Returns the modular symbol attached to the cusp $c$, where $M$ is a modular symbol space of level $N$, attached to $G = \Gamma_{0}(N)$. The cusp $c$ in $\P^{1}(\Q)/G$ is given either as \kbd{oo} ($=(1:0)$) or as a rational number $a/b$ ($=(a:b)$). The attached symbol maps the path $[b] - [a] \in \text{Div}^{0} (\P^{1}(\Q))$ to $E_{c}(b) - E_{c}(a)$, where $E_{c}(r)$ is $0$ when $r \neq c$ and $X^{k-2} \mid \gamma_{r}$ otherwise, where $\gamma_{r} \cdot r = (1:0)$. These symbols span the Eisenstein subspace of $M$. \bprog ? M = msinit(2,8); \\ M_8(Gamma_0(2)) ? E = mseisenstein(M); ? E[1] \\ two-dimensional %3 = [0 -10] [0 -15] [0 -3] [1 0] ? s = msfromcusp(M,oo) %4 = [0, 0, 0, 1]~ ? mseval(M, s) %5 = [1, 0] ? s = msfromcusp(M,1) %6 = [-5/16, -15/32, -3/32, 0]~ ? mseval(M,s) %7 = [-x^6, -6*x^5 - 15*x^4 - 20*x^3 - 15*x^2 - 6*x - 1] @eprog In case $M$ was initialized with a nonzero \emph{sign}, the symbol is given in terms of the fixed basis of the whole symbol space, not the $+$ or $-$ part (to which it need not belong). \bprog ? M = msinit(2,8, 1); \\ M_8(Gamma_0(2))^+ ? E = mseisenstein(M); ? E[1] \\ still two-dimensional, in a smaller space %3 = [ 0 -10] [ 0 3] [-1 0] ? s = msfromcusp(M,oo) \\ in terms of the basis for M_8(Gamma_0(2)) ! %4 = [0, 0, 0, 1]~ ? mseval(M, s) \\ same symbol as before %5 = [1, 0] @eprog The library syntax is \fun{GEN}{msfromcusp}{GEN M, GEN c}. \subsec{msfromell$(E,\{\var{sign}=0\})$}\kbdsidx{msfromell}\label{se:msfromell} Let $E/\Q$ be an elliptic curve of conductor $N$. For $\varepsilon = \pm1$, we define the (cuspidal, new) modular symbol $x^{\varepsilon}$ in $H^{1}_{c}(X_{0}(N),\Q)^{\varepsilon}$ attached to $E$. For all primes $p$ not dividing $N$ we have $T_{p}(x^{\varepsilon}) = a_{p} x^{\varepsilon}$, where $a_{p} = p+1-\#E(\F_{p})$. Let $\Omega^{+} = \kbd{E.omega[1]}$ be the real period of $E$ (integration of the N\'eron differential $dx/(2y+a_{1}x+a_{3})$ on the connected component of $E(\R)$, i.e.~the generator of $H_{1}(E,\Z)^{+}$) normalized by $\Omega^{+}>0$. Let $i\Omega^{-}$ the integral on a generator of $H_{1}(E,\Z)^{-}$ with $\Omega^{-} \in \R_{>0}$. If $c_{\infty}$ is the number of connected components of $E(\R)$, $\Omega^{-}$ is equal to $(-2/c_{\infty}) \times \kbd{imag(E.omega[2])}$. The complex modular symbol is defined by $$F: \delta \to 2i\pi \int_{\delta} f(z) dz$$ The modular symbols $x^{\varepsilon}$ are normalized so that $ F = x^{+} \Omega^{+} + x^{-} i\Omega^{-}$. In particular, we have $$ x^{+}([0]-[\infty]) = L(E,1) / \Omega^{+},$$ which defines $x^{\pm}$ unless $L(E,1)=0$. Furthermore, for all fundamental discriminants $D$ such that $\varepsilon \cdot D > 0$, we also have $$\sum_{0\leq a<|D|} (D|a) x^{\varepsilon}([a/|D|]-[\infty]) = L(E,(D|.),1) / \Omega^{\varepsilon},$$ where $(D|.)$ is the Kronecker symbol. The period $\Omega^{-}$ is also $2/c_{\infty} \times$ the real period of the twist $E^{(-4)} = \kbd{elltwist(E,-4)}$. This function returns the pair $[M, x]$, where $M$ is \kbd{msinit}$(N,2)$ and $x$ is $x^{\var{sign}}$ as above when $\var{sign}= \pm1$, and $x = [x^{+},x^{-}, L_{E}]$ when \var{sign} is $0$, where $L_{E}$ is a matrix giving the canonical $\Z$-lattice attached to $E$ in the sense of \kbd{mslattice} applied to $\Q x^{+} + \Q x^{-}$. Explicitly, it is generated by $(x^{+},x^{-})$ when $E(\R)$ has two connected components and by $(x^{+} - x^{-},2x^{-})$ otherwise. The modular symbols $x^{\pm}$ are given as a \typ{COL} (in terms of the fixed basis of $\Hom_{G}(\Delta_{0},\Q)$ chosen in $M$). \bprog ? E=ellinit([0,-1,1,-10,-20]); \\ X_0(11) ? [M,xp]= msfromell(E,1); ? xp %3 = [1/5, -1/2, -1/2]~ ? [M,x]= msfromell(E); ? x \\ x^+, x^- and L_E %5 = [[1/5, -1/2, -1/2]~, [0, 1/2, -1/2]~, [1/5, 0; -1, 1; 0, -1]] ? p = 23; (mshecke(M,p) - ellap(E,p))*x[1] %6 = [0, 0, 0]~ \\ true at all primes, including p = 11; same for x[2] ? (mshecke(M,p) - ellap(E,p))*x[3] == 0 %7 = 1 @eprog \noindent Instead of a single curve $E$, one may use instead a vector of \emph{isogenous} curves. The function then returns $M$ and the vector of attached modular symbols. The library syntax is \fun{GEN}{msfromell}{GEN E, long sign}. \subsec{msfromhecke$(M,v,\{H\})$}\kbdsidx{msfromhecke}\label{se:msfromhecke} Given a msinit $M$ and a vector $v$ of pairs $[p, P]$ (where $p$ is prime and $P$ is a polynomial with integer coefficients), return a basis of all modular symbols such that $P(T_{p})(s) = 0$. If $H$ is present, it must be a Hecke-stable subspace and we restrict to $s \in H$. When $T_{p}$ has a rational eigenvalue and $P(x) = x-a_{p}$ has degree $1$, we also accept the integer $a_{p}$ instead of $P$. \bprog ? E = ellinit([0,-1,1,-10,-20]) \\11a1 ? ellap(E,2) %2 = -2 ? ellap(E,3) %3 = -1 ? M = msinit(11,2); ? S = msfromhecke(M, [[2,-2],[3,-1]]) %5 = [ 1 1] [-5 0] [ 0 -5] ? mshecke(M, 2, S) %6 = [-2 0] [ 0 -2] ? M = msinit(23,4); ? S = msfromhecke(M, [[5, x^4-14*x^3-244*x^2+4832*x-19904]]); ? factor( charpoly(mshecke(M,5,S)) ) %9 = [x^4 - 14*x^3 - 244*x^2 + 4832*x - 19904 2] @eprog The library syntax is \fun{GEN}{msfromhecke}{GEN M, GEN v, GEN H = NULL}. \subsec{msgetlevel$(M)$}\kbdsidx{msgetlevel}\label{se:msgetlevel} $M$ being a full modular symbol space, as given by \kbd{msinit}, return its level $N$. The library syntax is \fun{long}{msgetlevel}{GEN M}. \subsec{msgetsign$(M)$}\kbdsidx{msgetsign}\label{se:msgetsign} $M$ being a full modular symbol space, as given by \kbd{msinit}, return its sign: $\pm1$ or 0 (unset). \bprog ? M = msinit(11,4, 1); ? msgetsign(M) %2 = 1 ? M = msinit(11,4); ? msgetsign(M) %4 = 0 @eprog The library syntax is \fun{long}{msgetsign}{GEN M}. \subsec{msgetweight$(M)$}\kbdsidx{msgetweight}\label{se:msgetweight} $M$ being a full modular symbol space, as given by \kbd{msinit}, return its weight $k$. \bprog ? M = msinit(11,4); ? msgetweight(M) %2 = 4 @eprog The library syntax is \fun{long}{msgetweight}{GEN M}. \subsec{mshecke$(M,p,\{H\})$}\kbdsidx{mshecke}\label{se:mshecke} $M$ being a full modular symbol space, as given by \kbd{msinit}, $p$ being a prime number, and $H$ being a Hecke-stable subspace ($M$ if omitted), return the matrix of $T_{p}$ acting on $H$ ($U_{p}$ if $p$ divides $N$). Result is undefined if $H$ is not stable by $T_{p}$ (resp.~$U_{p}$). \bprog ? M = msinit(11,2); \\ M_2(Gamma_0(11)) ? T2 = mshecke(M,2) %2 = [3 0 0] [1 -2 0] [1 0 -2] ? M = msinit(11,2, 1); \\ M_2(Gamma_0(11))^+ ? T2 = mshecke(M,2) %4 = [ 3 0] [-1 -2] ? N = msnew(M)[1] \\ Q-basis of new cuspidal subspace %5 = [-2] [-5] ? p = 1009; mshecke(M, p, N) \\ action of T_1009 on N %6 = [-10] ? ellap(ellinit("11a1"), p) %7 = -10 @eprog The library syntax is \fun{GEN}{mshecke}{GEN M, long p, GEN H = NULL}. \subsec{msinit$(G,V,\{\var{sign}=0\})$}\kbdsidx{msinit}\label{se:msinit} Given $G$ a finite index subgroup of $\text{SL}(2,\Z)$ and a finite dimensional representation $V$ of $\text{GL}(2,\Q)$, creates a space of modular symbols, the $G$-module $\Hom_{G}(\text{Div}^{0}(\P^{1}(\Q)), V)$. This is canonically isomorphic to $H^{1}_{c}(X(G), V)$, and allows to compute modular forms for $G$. If \emph{sign} is present and nonzero, it must be $\pm1$ and we consider the subspace defined by $\text{Ker} (\sigma - \var{sign})$, where $\sigma$ is induced by \kbd{[-1,0;0,1]}. Currently the only supported groups are the $\Gamma_{0}(N)$, coded by the integer $N > 0$. The only supported representation is $V_{k} = \Q[X,Y]_{k-2}$, coded by the integer $k \geq 2$. \bprog ? M = msinit(11,2); msdim(M) \\ Gamma0(11), weight 2 %1 = 3 ? mshecke(M,2) \\ T_2 acting on M %2 = [3 1 1] [0 -2 0] [0 0 -2] ? msstar(M) \\ * involution %3 = [1 0 0] [0 0 1] [0 1 0] ? Mp = msinit(11,2, 1); msdim(Mp) \\ + part %4 = 2 ? mshecke(Mp,2) \\ T_2 action on M^+ %5 = [3 2] [0 -2] ? msstar(Mp) %6 = [1 0] [0 1] @eprog The library syntax is \fun{GEN}{msinit}{GEN G, GEN V, long sign}. \subsec{msissymbol$(M,s)$}\kbdsidx{msissymbol}\label{se:msissymbol} $M$ being a full modular symbol space, as given by \kbd{msinit}, check whether $s$ is a modular symbol attached to $M$. If $A$ is a matrix, check whether its columns represent modular symbols and return a $0-1$ vector. \bprog ? M = msinit(7,8, 1); \\ M_8(Gamma_0(7))^+ ? A = msnew(M)[1]; ? s = A[,1]; ? msissymbol(M, s) %4 = 1 ? msissymbol(M, A) %5 = [1, 1, 1] ? S = mseval(M,s); ? msissymbol(M, S) %7 = 1 ? [g,R] = mspathgens(M); g %8 = [[+oo, 0], [0, 1/2], [1/2, 1]] ? #R \\ 3 relations among the generators g_i %9 = 3 ? T = S; T[3]++; \\ randomly perturb S(g_3) ? msissymbol(M, T) %11 = 0 \\ no longer satisfies the relations @eprog The library syntax is \fun{GEN}{msissymbol}{GEN M, GEN s}. \subsec{mslattice$(M,\{H\})$}\kbdsidx{mslattice}\label{se:mslattice} Let $\Delta_{0}:=\text{Div}^{0}(\P^{1}(\Q))$ and $V_{k} = \Q[x,y]_{k-2}$. Let $M$ be a full modular symbol space, as given by \kbd{msinit} and let $H$ be a subspace, e.g. as given by \kbd{mscuspidal}. This function returns a canonical $\Z$-structure on $H$ defined as follows. Consider the map $c: M=\Hom_{\Gamma_{0}(N)}(\Delta_{0}, V_{k}) \to H^{1}(\Gamma_{0}(N), V_{k})$ given by $\phi \mapsto \var{class}(\gamma \to \phi(\{0, \gamma^{-1} 0\}))$. Let $L_{k}=\Z[x,y]_{k-2}$ be the natural $\Z$-structure of $V_{k}$. The result of \kbd{mslattice} is a $\Z$-basis of the inverse image by $c$ of $H^{1}(\Gamma_{0}(N), L_{k})$ in the space of modular symbols generated by $H$. For user convenience, $H$ can be defined by a matrix representing the $\Q$-basis of $H$ (in terms of the canonical $\Q$-basis of $M$ fixed by \kbd{msinit} and used to represent modular symbols). If omitted, $H$ is the cuspidal part of $M$ as given by \kbd{mscuspidal}. The Eisenstein part $\Hom_{\Gamma_{0}(N)}(\text{Div}(\P^{1}(\Q)), V_{k})$ is in the kernel of $c$, so the result has no meaning for the Eisenstein part \kbd{H}. \bprog ? M=msinit(11,2); ? [S,E] = mscuspidal(M,1); S[1] \\ a primitive Q-basis of S %2 = [ 1 1] [-5 0] [ 0 -5] ? mslattice(M,S) %3 = [-1/5 -1/5] [ 1 0] [ 0 1] ? mslattice(M,E) %4 = [1] [0] [0] ? M=msinit(5,4); ? S=mscuspidal(M); S[1] %6 = [ 7 20] [ 3 3] [-10 -23] [-30 -30] ? mslattice(M,S) %7 = [-1/10 -11/130] [ 0 -1/130] [ 1/10 6/65] [ 0 1/13] @eprog The library syntax is \fun{GEN}{mslattice}{GEN M, GEN H = NULL}. \subsec{msnew$(M)$}\kbdsidx{msnew}\label{se:msnew} $M$ being a full modular symbol space, as given by \kbd{msinit}, return the \emph{new} part of its cuspidal subspace. A subspace is given by a structure allowing quick projection and restriction of linear operators; its first component is a matrix with integer coefficients whose columns form a $\Q$-basis of the subspace. \bprog ? M = msinit(11,8, 1); \\ M_8(Gamma_0(11))^+ ? N = msnew(M); ? #N[1] \\ 6-dimensional %3 = 6 @eprog The library syntax is \fun{GEN}{msnew}{GEN M}. \subsec{msomseval$(\var{Mp},\var{PHI},\var{path})$}\kbdsidx{msomseval}\label{se:msomseval} Return the vectors of moments of the $p$-adic distribution attached to the path \kbd{path} by the overconvergent modular symbol \kbd{PHI}. \bprog ? M = msinit(3,6,1); ? Mp= mspadicinit(M,5,10); ? phi = [5,-3,-1]~; ? msissymbol(M,phi) %4 = 1 ? PHI = mstooms(Mp,phi); ? ME = msomseval(Mp,PHI,[oo, 0]); @eprog The library syntax is \fun{GEN}{msomseval}{GEN Mp, GEN PHI, GEN path}. \subsec{mspadicL$(\var{mu},\{s=0\},\{r=0\})$}\kbdsidx{mspadicL}\label{se:mspadicL} Returns the value (or $r$-th derivative) on a character $\chi^{s}$ of $\Z_{p}^{*}$ of the $p$-adic $L$-function attached to \kbd{mu}. Let $\Phi$ be the $p$-adic distribution-valued overconvergent symbol attached to a modular symbol $\phi$ for $\Gamma_{0}(N)$ (eigenvector for $T_{N}(p)$ for the eigenvalue $a_{p}$). Then $L_{p}(\Phi,\chi^{s})=L_{p}(\mu,s)$ is the $p$-adic $L$ function defined by $$L_{p}(\Phi,\chi^{s})= \int_{\Z_{p}^{*}} \chi^{s}(z) d\mu(z)$$ where $\mu$ is the distribution on $\Z_{p}^{*}$ defined by the restriction of $\Phi([\infty]-[0])$ to $\Z_{p}^{*}$. The $r$-th derivative is taken in direction $\langle \chi\rangle$: $$L_{p}^{(r)}(\Phi,\chi^{s})= \int_{\Z_{p}^{*}} \chi^{s}(z) (\log z)^{r} d\mu(z).$$ In the argument list, \item \kbd{mu} is as returned by \tet{mspadicmoments} (distributions attached to $\Phi$ by restriction to discs $a + p^{\nu}\Z_{p}$, $(a,p)=1$). \item $s=[s_{1},s_{2}]$ with $s_{1} \in \Z \subset \Z_{p}$ and $s_{2} \bmod p-1$ or $s_{2} \bmod 2$ for $p=2$, encoding the $p$-adic character $\chi^{s} := \langle \chi \rangle^{s_{1}} \tau^{s_{2}}$; here $\chi$ is the cyclotomic character from $\text{Gal}(\Q_{p}(\mu_{p^{\infty}})/\Q_{p})$ to $\Z_{p}^{*}$, and $\tau$ is the Teichm\"uller character (for $p>2$ and the character of order 2 on $(\Z/4\Z)^{*}$ if $p=2$); for convenience, the character $[s,s]$ can also be represented by the integer $s$. When $a_{p}$ is a $p$-adic unit, $L_{p}$ takes its values in $\Q_{p}$. When $a_{p}$ is not a unit, it takes its values in the two-dimensional $\Q_{p}$-vector space $D_{cris}(M(\phi))$ where $M(\phi)$ is the ``motive'' attached to $\phi$, and we return the two $p$-adic components with respect to some fixed $\Q_{p}$-basis. \bprog ? M = msinit(3,6,1); phi=[5, -3, -1]~; ? msissymbol(M,phi) %2 = 1 ? Mp = mspadicinit(M, 5, 4); ? mu = mspadicmoments(Mp, phi); \\ no twist \\ End of initializations ? mspadicL(mu,0) \\ L_p(chi^0) %5 = 5 + 2*5^2 + 2*5^3 + 2*5^4 + ... ? mspadicL(mu,1) \\ L_p(chi), zero for parity reasons %6 = [O(5^13)]~ ? mspadicL(mu,2) \\ L_p(chi^2) %7 = 3 + 4*5 + 4*5^2 + 3*5^5 + ... ? mspadicL(mu,[0,2]) \\ L_p(tau^2) %8 = 3 + 5 + 2*5^2 + 2*5^3 + ... ? mspadicL(mu, [1,0]) \\ L_p() %9 = 3*5 + 2*5^2 + 5^3 + 2*5^7 + 5^8 + 5^10 + 2*5^11 + O(5^13) ? mspadicL(mu,0,1) \\ L_p'(chi^0) %10 = 2*5 + 4*5^2 + 3*5^3 + ... ? mspadicL(mu, 2, 1) \\ L_p'(chi^2) %11 = 4*5 + 3*5^2 + 5^3 + 5^4 + ... @eprog Now several quadratic twists: \tet{mstooms} is indicated. \bprog ? PHI = mstooms(Mp,phi); ? mu = mspadicmoments(Mp, PHI, 12); \\ twist by 12 ? mspadicL(mu) %14 = 5 + 5^2 + 5^3 + 2*5^4 + ... ? mu = mspadicmoments(Mp, PHI, 8); \\ twist by 8 ? mspadicL(mu) %16 = 2 + 3*5 + 3*5^2 + 2*5^4 + ... ? mu = mspadicmoments(Mp, PHI, -3); \\ twist by -3 < 0 ? mspadicL(mu) %18 = O(5^13) \\ always 0, phi is in the + part and D < 0 @eprog One can locate interesting symbols of level $N$ and weight $k$ with \kbd{msnew} and \kbd{mssplit}. Note that instead of a symbol, one can input a 1-dimensional Hecke-subspace from \kbd{mssplit}: the function will automatically use the underlying basis vector. \bprog ? M=msinit(5,4,1); \\ M_4(Gamma_0(5))^+ ? L = mssplit(M, msnew(M)); \\ list of irreducible Hecke-subspaces ? phi = L[1]; \\ one Galois orbit of newforms ? #phi[1] \\... this one is rational %4 = 1 ? Mp = mspadicinit(M, 3, 4); ? mu = mspadicmoments(Mp, phi); ? mspadicL(mu) %7 = 1 + 3 + 3^3 + 3^4 + 2*3^5 + 3^6 + O(3^9) ? M = msinit(11,8, 1); \\ M_8(Gamma_0(11))^+ ? Mp = mspadicinit(M, 3, 4); ? L = mssplit(M, msnew(M)); ? phi = L[1]; #phi[1] \\ ... this one is two-dimensional %11 = 2 ? mu = mspadicmoments(Mp, phi); *** at top-level: mu=mspadicmoments(Mp,ph *** ^-------------------- *** mspadicmoments: incorrect type in mstooms [dim_Q (eigenspace) > 1] @eprog The library syntax is \fun{GEN}{mspadicL}{GEN mu, GEN s = NULL, long r}. \subsec{mspadicinit$(M,p,n,\{\fl\})$}\kbdsidx{mspadicinit}\label{se:mspadicinit} $M$ being a full modular symbol space, as given by \kbd{msinit}, and $p$ a prime, initialize technical data needed to compute with overconvergent modular symbols, modulo $p^{n}$. If $\fl$ is unset, allow all symbols; else initialize only for a restricted range of symbols depending on $\fl$: if $\fl = 0$ restrict to ordinary symbols, else restrict to symbols $\phi$ such that $T_{p}(\phi) = a_{p} \phi$, with $v_{p}(a_{p}) \geq \fl$, which is faster as $\fl$ increases. (The fastest initialization is obtained for $\fl = 0$ where we only allow ordinary symbols.) For supersingular eigensymbols, such that $p\mid a_{p}$, we must further assume that $p$ does not divide the level. \bprog ? E = ellinit("11a1"); ? [M,phi] = msfromell(E,1); ? ellap(E,3) %3 = -1 ? Mp = mspadicinit(M, 3, 10, 0); \\ commit to ordinary symbols ? PHI = mstooms(Mp,phi); @eprog If we restrict the range of allowed symbols with \fl (for faster initialization), exceptions will occur if $v_{p}(a_{p})$ violates this bound: \bprog ? E = ellinit("15a1"); ? [M,phi] = msfromell(E,1); ? ellap(E,7) %3 = 0 ? Mp = mspadicinit(M,7,5,0); \\ restrict to ordinary symbols ? PHI = mstooms(Mp,phi) *** at top-level: PHI=mstooms(Mp,phi) *** ^--------------- *** mstooms: incorrect type in mstooms [v_p(ap) > mspadicinit flag] (t_VEC). ? Mp = mspadicinit(M,7,5); \\ no restriction ? PHI = mstooms(Mp,phi); @eprog\noindent This function uses $O(N^{2}(n+k)^{2}p)$ memory, where $N$ is the level of $M$. The library syntax is \fun{GEN}{mspadicinit}{GEN M, long p, long n, long flag}. \subsec{mspadicmoments$(\var{Mp},\var{PHI},\{D=1\})$}\kbdsidx{mspadicmoments}\label{se:mspadicmoments} Given \kbd{Mp} from \kbd{mspadicinit}, an overconvergent eigensymbol \kbd{PHI} from \kbd{mstooms} and a fundamental discriminant $D$ coprime to $p$, let $\kbd{PHI}^{D}$ denote the twisted symbol. This function computes the distribution $\mu = \kbd{PHI}^{D}([0] - \infty]) \mid \Z_{p}^{*}$ restricted to $\Z_{p}^{*}$. More precisely, it returns the moments of the $p-1$ distributions $\kbd{PHI}^{D}([0]-[\infty]) \mid (a + p\Z_{p})$, $0 < a < p$. We also allow \kbd{PHI} to be given as a classical symbol, which is then lifted to an overconvergent symbol by \kbd{mstooms}; but this is wasteful if more than one twist is later needed. The returned data $\mu$ ($p$-adic distributions attached to \kbd{PHI}) can then be used in \tet{mspadicL} or \tet{mspadicseries}. This precomputation allows to quickly compute derivatives of different orders or values at different characters. \bprog ? M = msinit(3,6, 1); ? phi = [5,-3,-1]~; ? msissymbol(M, phi) %3 = 1 ? p = 5; mshecke(M,p) * phi \\ eigenvector of T_5, a_5 = 6 %4 = [30, -18, -6]~ ? Mp = mspadicinit(M, p, 10, 0); \\ restrict to ordinary symbols, mod p^10 ? PHI = mstooms(Mp, phi); ? mu = mspadicmoments(Mp, PHI); ? mspadicL(mu) %8 = 5 + 2*5^2 + 2*5^3 + ... ? mu = mspadicmoments(Mp, PHI, 12); \\ twist by 12 ? mspadicL(mu) %10 = 5 + 5^2 + 5^3 + 2*5^4 + ... @eprog The library syntax is \fun{GEN}{mspadicmoments}{GEN Mp, GEN PHI, long D}. \subsec{mspadicseries$(\var{mu},\{i=0\})$}\kbdsidx{mspadicseries}\label{se:mspadicseries} Let $\Phi$ be the $p$-adic distribution-valued overconvergent symbol attached to a modular symbol $\phi$ for $\Gamma_{0}(N)$ (eigenvector for $T_{N}(p)$ for the eigenvalue $a_{p}$). If $\mu$ is the distribution on $\Z_{p}^{*}$ defined by the restriction of $\Phi([\infty]-[0])$ to $\Z_{p}^{*}$, let $$\hat{L}_{p}(\mu,\tau^{i})(x) = \int_{\Z_{p}^{*}} \tau^{i}(t) (1+x)^{\log_{p}(t)/\log_{p}(u)}d\mu(t)$$ Here, $\tau$ is the Teichm\"uller character and $u$ is a specific multiplicative generator of $1+2p\Z_{p}$, namely $1+p$ if $p>2$ or $5$ if $p=2$. To explain the formula, let $G_{\infty} := \text{Gal}(\Q(\mu_{p^{\infty}})/ \Q)$, let $\chi:G_{\infty}\to \Z_{p}^{*}$ be the cyclotomic character (isomorphism) and $\gamma$ the element of $G_{\infty}$ such that $\chi(\gamma)=u$; then $\chi(\gamma)^{\log_{p}(t)/\log_{p}(u)}= \langle t \rangle$. The $p$-padic precision of individual terms is maximal given the precision of the overconvergent symbol $\mu$. \bprog ? [M,phi] = msfromell(ellinit("17a1"),1); ? Mp = mspadicinit(M, 5,7); ? mu = mspadicmoments(Mp, phi,1); \\ overconvergent symbol ? mspadicseries(mu) %4 = (4 + 3*5 + 4*5^2 + 2*5^3 + 2*5^4 + 5^5 + 4*5^6 + 3*5^7 + O(5^9)) \ + (3 + 3*5 + 5^2 + 5^3 + 2*5^4 + 5^6 + O(5^7))*x \ + (2 + 3*5 + 5^2 + 4*5^3 + 2*5^4 + O(5^5))*x^2 \ + (3 + 4*5 + 4*5^2 + O(5^3))*x^3 \ + (3 + O(5))*x^4 + O(x^5) @eprog\noindent An example with nonzero Teichm\"uller: \bprog ? [M,phi] = msfromell(ellinit("11a1"),1); ? Mp = mspadicinit(M, 3,10); ? mu = mspadicmoments(Mp, phi,1); ? mspadicseries(mu, 2) %4 = (2 + 3 + 3^2 + 2*3^3 + 2*3^5 + 3^6 + 3^7 + 3^10 + 3^11 + O(3^12)) \ + (1 + 3 + 2*3^2 + 3^3 + 3^5 + 2*3^6 + 2*3^8 + O(3^9))*x \ + (1 + 2*3 + 3^4 + 2*3^5 + O(3^6))*x^2 \ + (3 + O(3^2))*x^3 + O(x^4) @eprog\noindent Supersingular example (not checked) \bprog ? E = ellinit("17a1"); ellap(E,3) %1 = 0 ? [M,phi] = msfromell(E,1); ? Mp = mspadicinit(M, 3,7); ? mu = mspadicmoments(Mp, phi,1); ? mspadicseries(mu) %5 = [(2*3^-1 + 1 + 3 + 3^2 + 3^3 + 3^4 + 3^5 + 3^6 + O(3^7)) \ + (2 + 3^3 + O(3^5))*x \ + (1 + 2*3 + O(3^2))*x^2 + O(x^3),\ (3^-1 + 1 + 3 + 3^2 + 3^3 + 3^4 + 3^5 + 3^6 + O(3^7)) \ + (1 + 2*3 + 2*3^2 + 3^3 + 2*3^4 + O(3^5))*x \ + (3^-2 + 3^-1 + O(3^2))*x^2 + O(3^-2)*x^3 + O(x^4)] @eprog\noindent Example with a twist: \bprog ? E = ellinit("11a1"); ? [M,phi] = msfromell(E,1); ? Mp = mspadicinit(M, 3,10); ? mu = mspadicmoments(Mp, phi,5); \\ twist by 5 ? L = mspadicseries(mu) %5 = (2*3^2 + 2*3^4 + 3^5 + 3^6 + 2*3^7 + 2*3^10 + O(3^12)) \ + (2*3^2 + 2*3^6 + 3^7 + 3^8 + O(3^9))*x \ + (3^3 + O(3^6))*x^2 + O(3^2)*x^3 + O(x^4) ? mspadicL(mu) %6 = [2*3^2 + 2*3^4 + 3^5 + 3^6 + 2*3^7 + 2*3^10 + O(3^12)]~ ? ellpadicL(E,3,10,,5) %7 = 2 + 2*3^2 + 3^3 + 2*3^4 + 2*3^5 + 3^6 + 2*3^7 + O(3^10) ? mspadicseries(mu,1) \\ must be 0 %8 = O(3^12) + O(3^9)*x + O(3^6)*x^2 + O(3^2)*x^3 + O(x^4) @eprog The library syntax is \fun{GEN}{mspadicseries}{GEN mu, long i}. \subsec{mspathgens$(M)$}\kbdsidx{mspathgens}\label{se:mspathgens} Let $\Delta_{0}:=\text{Div}^{0}(\P^{1}(\Q))$. Let $M$ being a full modular symbol space, as given by \kbd{msinit}, return a set of $\Z[G]$-generators for $\Delta_{0}$. The output is $[g,R]$, where $g$ is a minimal system of generators and $R$ the vector of $\Z[G]$-relations between the given generators. A relation is coded by a vector of pairs $[a_{i},i]$ with $a_{i}\in \Z[G]$ and $i$ the index of a generator, so that $\sum_{i} a_{i} g[i] = 0$. An element $[v]-[u]$ in $\Delta_{0}$ is coded by the ``path'' $[u,v]$, where \kbd{oo} denotes the point at infinity $(1:0)$ on the projective line. An element of $\Z[G]$ is either an integer $n$ ($= n [\text{id}_{2}]$) or a ``factorization matrix'': the first column contains distinct elements $g_{i}$ of $G$ and the second integers $n_{i}$ and the matrix codes $\sum_{i} n_{i} [g_{i}]$: \bprog ? M = msinit(11,8); \\ M_8(Gamma_0(11)) ? [g,R] = mspathgens(M); ? g %3 = [[+oo, 0], [0, 1/3], [1/3, 1/2]] \\ 3 paths ? #R \\ a single relation %4 = 1 ? r = R[1]; #r \\ ...involving all 3 generators %5 = 3 ? r[1] %6 = [[1, 1; [1, 1; 0, 1], -1], 1] ? r[2] %7 = [[1, 1; [7, -2; 11, -3], -1], 2] ? r[3] %8 = [[1, 1; [8, -3; 11, -4], -1], 3] @eprog\noindent The given relation is of the form $\sum_{i} (1-\gamma_{i}) g_{i} = 0$, with $\gamma_{i}\in \Gamma_{0}(11)$. There will always be a single relation involving all generators (corresponding to a round trip along all cusps), then relations involving a single generator (corresponding to $2$ and $3$-torsion elements in the group: \bprog ? M = msinit(2,8); \\ M_8(Gamma_0(2)) ? [g,R] = mspathgens(M); ? g %3 = [[+oo, 0], [0, 1]] @eprog\noindent Note that the output depends only on the group $G$, not on the representation $V$. The library syntax is \fun{GEN}{mspathgens}{GEN M}. \subsec{mspathlog$(M,p)$}\kbdsidx{mspathlog}\label{se:mspathlog} Let $\Delta_{0}:=\text{Div}^{0}(\P^{1}(\Q))$. Let $M$ being a full modular symbol space, as given by \kbd{msinit}, encoding fixed $\Z[G]$-generators $(g_{i})$ of $\Delta_{0}$ (see \tet{mspathgens}). A path $p=[a,b]$ between two elements in $\P^{1}(\Q)$ corresponds to $[b]-[a]\in \Delta_{0}$. The path extremities $a$ and $b$ may be given as \typ{INT}, \typ{FRAC} or $\kbd{oo} = (1:0)$. Finally, we also allow to input a path as a $2\times 2$ integer matrix, whose first and second column give $a$ and $b$ respectively, with the convention $[x,y]\til = (x:y)$ in $\P^{1}(\Q)$. Returns $(p_{i})$ in $\Z[G]$ such that $p = \sum_{i} p_{i} g_{i}$. \bprog ? M = msinit(2,8); \\ M_8(Gamma_0(2)) ? [g,R] = mspathgens(M); ? g %3 = [[+oo, 0], [0, 1]] ? p = mspathlog(M, [1/2,2/3]); ? p[1] %5 = [[1, 0; 2, 1] 1] ? p[2] %6 = [[1, 0; 0, 1] 1] [[3, -1; 4, -1] 1] ? mspathlog(M, [1,2;2,3]) == p \\ give path via a 2x2 matrix %7 = 1 @eprog\noindent Note that the output depends only on the group $G$, not on the representation $V$. The library syntax is \fun{GEN}{mspathlog}{GEN M, GEN p}. \subsec{mspetersson$(M,\{F\},\{G=F\})$}\kbdsidx{mspetersson}\label{se:mspetersson} $M$ being a full modular symbol space for $\Gamma = \Gamma_{0}(N)$, as given by \kbd{msinit}, calculate the intersection product $\{F, G\}$ of modular symbols $F$ and $G$ on $M=\Hom_{\Gamma}(\Delta_{0}, V_{k})$ extended to an hermitian bilinear form on $M \otimes \C$ whose radical is the Eisenstein subspace of $M$. Suppose that $f_{1}$ and $f_{2}$ are two parabolic forms. Let $F_{1}$ and $F_{2}$ be the attached modular symbols $$ F_{i}(\delta)= \int_{\delta} f_{i}(z) \cdot (z X + Y)^{k-2} \,dz$$ and let $F^{\R}_{1}$, $F^{\R}_{2}$ be the attached real modular symbols $$ F^{\R}_{i}(\delta)= \int_{\delta} \Re\big(f_{i}(z) \cdot (z X + Y)^{k-2} \,dz\big) $$ Then we have $$ \{ F^{\R}_{1}, F^{\R}_{2} \} = -2 (2i)^{k-2} \cdot \Im(_{\var{Petersson}}) $$ and $$\{ F_{1}, \bar{F_{2}} \} = (2i)^{k-2} _{\var{Petersson}}$$ In weight 2, the intersection product $\{F, G\}$ has integer values on the $\Z$-structure on $M$ given by \kbd{mslattice} and defines a Riemann form on $H^{1}_{par}(\Gamma,\R)$. For user convenience, we allow $F$ and $G$ to be matrices and return the attached Gram matrix. If $F$ is omitted: treat it as the full modular space attached to $M$; if $G$ is omitted, take it equal to $F$. \bprog ? M = msinit(37,2); ? C = mscuspidal(M)[1]; ? mspetersson(M, C) %3 = [ 0 -17 -8 -17] [17 0 -8 -25] [ 8 8 0 -17] [17 25 17 0] ? mspetersson(M, mslattice(M,C)) %4 = [0 -1 0 -1] [1 0 0 -1] [0 0 0 -1] [1 1 1 0] ? E = ellinit("33a1"); ? [M,xpm] = msfromell(E); [xp,xm,L] = xpm; ? mspetersson(M, mslattice(M,L)) %7 = [0 -3] [3 0] ? ellmoddegree(E) %8 = [3, -126] @eprog \noindent The coefficient $3$ in the matrix is the degree of the modular parametrization. The library syntax is \fun{GEN}{mspetersson}{GEN M, GEN F = NULL, GEN G = NULL}. \subsec{mspolygon$(M,\{\fl=0\})$}\kbdsidx{mspolygon}\label{se:mspolygon} $M$ describes a subgroup $G$ of finite index in the modular group $\text{PSL}_{2}(\Z)$, as given by \kbd{msinit} or a positive integer $N$ (encoding the group $G = \Gamma_{0}(N)$), or by \kbd{msfarey} (arbitrary subgroup). Return an hyperbolic polygon (Farey symbol) attached to $G$. More precisely: \item Its vertices are an ordered list in $\P^{1}(\Q)$ and contain a representatives of all cusps. \item Its edges are hyperbolic arcs joining two consecutive vertices; each edge $e$ is labelled by an integer $\mu(e) \in \{\infty,2,3\}$. \item Given a path $(a,b)$ between two elements of $\P^{1}(\Q)$, let $\overline{(a,b)} = (b,a)$ be the opposite path. There is an involution $e \to e^{*}$ on the edges. We have $\mu(e) = \infty$ if and only if $e\neq e^{*}$; when $\mu(e) \neq 3$, $e$ is $G$-equivalent to $\overline{e^{*}}$, i.e. there exists $\gamma_{e} \in G$ such that $e = \gamma_{e} \overline{e^{*}}$; if $\mu(e)=3$ there exists $\gamma_{e} \in G$ of order $3$ such that the hyperbolic triangle $(e, \gamma_{e} e, \gamma_{e}^{2} e)$ is invariant by $\gamma_{e}$. In all cases, to each edge we have attached $\gamma_{e} \in G$ of order $\mu(e)$. \noindent The polygon is given by a triple $[E, A, g]$ \item The list $E$ of its consecutive edges as matrices in $M_{2}(\Z)$. \item The permutation $A$ attached to the involution: if $e = E[i]$ is the $i$-th edge, then \kbd{A[i]} is the index of $e^{*}$ in $E$. \item The list $g$ of pairing matrices $\gamma_{e}$. Remark that $\gamma_{e^{*}}=\gamma_{e}^{-1}$ if $\mu(e) \neq 3$, i.e., $g[i]^{-1} = g[A[i]]$ whenever $i\neq A[i]$ ($\mu(g[i]) = 1$) or $\mu(g[i]) = 2$ ($g[i]^{2} = 1$). Modulo these trivial relations, the pairing matrices form a system of independant generators of $G$. Note that $\gamma_{e}$ is elliptic if and only if $e^{*} = e$. \noindent The above data yields a fundamental domain for $G$ acting on Poincar\'e's half-plane: take the convex hull of the polygon defined by \item The edges in $E$ such that $e \neq e^{*}$ or $e^{*}=e$, where the pairing matrix $\gamma_{e}$ has order $2$; \item The edges $(r,t)$ and $(t,s)$ where the edge $e = (r,s) \in E$ is such that $e = e^{*}$ and $\gamma_{e}$ has order $3$ and the triangle $(r,t,s)$ is the image of $(0,\exp(2i\pi/3), \infty)$ by some element of $PSL_{2}(\Q)$ formed around the edge. Binary digits of flag mean: 1: return a normalized hyperbolic polygon if set, else a polygon with unimodular edges (matrices of determinant $1$). A polygon is normalized in the sense of compact orientable surfaces if the distance $d(a,a^{*})$ between an edge $a$ and its image by the involution $a^{*}$ is less than 2, with equality if and only if $a$ is \emph{linked} with another edge $b$ ($a$, $b$, $a^{*}$ et $b^{*}$ appear consecutively in $E$ up to cyclic permutation). In particular, the vertices of all edges such that that $d(a,a^{*}) \neq 1$ (distance is 0 or 2) are all equivalent to $0$ modulo $G$. The external vertices of $a a^{*}$ such that $d(a,a^{*}) = 1$ are also equivalent to $0$; the internal vertices $a\cap a^{*}$ (a single point), together with $0$, form a system of representatives of the cusps of $G\bs \P^{1}(\Q)$. This is useful to compute the homology group $H_{1}(G,\Z)$ as it gives a symplectic basis for the intersection pairing. In this case, the number of parabolic matrices (trace 2) in the system of generators $G$ is $2(t-1)$, where $t$ is the number of non equivalent cusps for $G$. This is currently only implemented for $G = \Gamma_{0}(N)$. 2: add graphical representations (in LaTeX form) for the hyperbolic polygon in Poincar\'e's half-space and the involution $a\to a^{*}$ of the Farey symbol. The corresponding character strings can be included in a LaTeX document provided the preamble contains \kbd{\bs usepackage\obr tikz\cbr}. \bprog ? [V,A,g] = mspolygon(3); ? V %2 = [[-1, 1; -1, 0], [1, 0; 0, 1], [0, 1; -1, 1]] ? A %3 = Vecsmall([2, 1, 3]) ? g %4 = [[-1, -1; 0, -1], [1, -1; 0, 1], [1, -1; 3, -2]] ? [V,A,g, D1,D2] = mspolygon(11,2); \\ D1 and D2 contains pictures ? {write("F.tex", "\\documentclass{article}\\usepackage{tikz}\\begin{document}" D1, "\n", D2, "\\end{document}");} ? [V1,A1] = mspolygon(6,1); \\ normalized ? V1 %8 = [[-1, 1; -1, 0], [1, 0; 0, 1], [0, 1; -1, 3], [1, -2; 3, -5], [-2, 1; -5, 2], [1, -1; 2, -1]] ? A1 %9 = Vecsmall([2, 1, 4, 3, 6, 5]) ? [V0,A0] = mspolygon(6); \\ not normalized V[3]^* = V[6], d(V[3],V[6]) = 3 ? A0 %11 = Vecsmall([2, 1, 6, 5, 4, 3]) ? [V,A] = mspolygon(14, 1); ? A %13 = Vecsmall([2, 1, 4, 3, 6, 5, 9, 10, 7, 8]) @eprog One can see from this last example that the (normalized) polygon has the form $$(a_{1}, a_{1}^{*}, a_{2}, a_{2}^{*}, a_{3}, a_{3}^{*}, a_{4}, a_{5}, a_{4}^{*}, a_{5}^{*}),$$ that $X_{0}(14)$ is of genus 1 (in general the genus is the number of blocks of the form $aba^{*}b^{*}$), has no elliptic points ($A$ has no fixed point) and 4 cusps (number of blocks of the form $aa^{*}$ plus 1). The vertices of edges $a_{4}$ and $a_{5}$ all project to $0$ in $X_{0}(14)$: the paths $a_{4}$ and $a_{5}$ project as loops in $X_{0}(14)$ and give a symplectic basis of the homology $H_{1}(X_{0}(14),\Z)$. \bprog ? [V,A] = mspolygon(15); ? apply(matdet, V) \\ all unimodular %2 = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] ? [V,A] = mspolygon(15,1); ? apply(matdet, V) \\ normalized polygon but no longer unimodular edges %4 = [1, 1, 1, 1, 2, 2, 47, 11, 47, 11] @eprog The library syntax is \fun{GEN}{mspolygon}{GEN M, long flag}. \subsec{msqexpansion$(M,\var{projH},\{B = \var{seriesprecision}\})$}\kbdsidx{msqexpansion}\label{se:msqexpansion} $M$ being a full modular symbol space, as given by \kbd{msinit}, and \var{projH} being a projector on a Hecke-simple subspace (as given by \tet{mssplit}), return the Fourier coefficients $a_{n}$, $n\leq B$ of the corresponding normalized newform. If $B$ is omitted, use \kbd{seriesprecision}. This function uses a naive $O(B^{2} d^{3})$ algorithm, where $d = O(kN)$ is the dimension of $M_{k}(\Gamma_{0}(N))$. \bprog ? M = msinit(11,2, 1); \\ M_2(Gamma_0(11))^+ ? L = mssplit(M, msnew(M)); ? msqexpansion(M,L[1], 20) %3 = [1, -2, -1, 2, 1, 2, -2, 0, -2, -2, 1, -2, 4, 4, -1, -4, -2, 4, 0, 2] ? ellan(ellinit("11a1"), 20) %4 = [1, -2, -1, 2, 1, 2, -2, 0, -2, -2, 1, -2, 4, 4, -1, -4, -2, 4, 0, 2] @eprog\noindent The shortcut \kbd{msqexpansion(M, s, B)} is available for a symbol $s$, provided it is a Hecke eigenvector: \bprog ? E = ellinit("11a1"); ? [M,S] = msfromell(E); [sp,sm] = S; ? msqexpansion(M,sp,10) \\ in the + eigenspace %3 = [1, -2, -1, 2, 1, 2, -2, 0, -2, -2] ? msqexpansion(M,sm,10) \\ in the - eigenspace %4 = [1, -2, -1, 2, 1, 2, -2, 0, -2, -2] ? ellan(E, 10) %5 = [1, -2, -1, 2, 1, 2, -2, 0, -2, -2] @eprog The library syntax is \fun{GEN}{msqexpansion}{GEN M, GEN projH, long precdl}. \subsec{mssplit$(M,\{H\},\{\var{dimlim}\})$}\kbdsidx{mssplit}\label{se:mssplit} Let $M$ denote a full modular symbol space, as given by \kbd{msinit}$(N,k,1)$ or $\kbd{msinit}(N,k,-1)$ and let $H$ be a Hecke-stable subspace of \kbd{msnew}$(M)$ (the full new subspace if $H$ is omitted). This function splits $H$ into Hecke-simple subspaces. If \kbd{dimlim} is present and positive, restrict to subspaces of dimension $\leq \kbd{dimlim}$. A subspace is given by a structure allowing quick projection and restriction of linear operators; its first component is a matrix with integer coefficients whose columns form a $\Q$-basis of the subspace. \bprog ? M = msinit(11,8, 1); \\ M_8(Gamma_0(11))^+ ? L = mssplit(M); \\ split msnew(M) ? #L %3 = 2 ? f = msqexpansion(M,L[1],5); f[1].mod %4 = x^2 + 8*x - 44 ? lift(f) %5 = [1, x, -6*x - 27, -8*x - 84, 20*x - 155] ? g = msqexpansion(M,L[2],5); g[1].mod %6 = x^4 - 558*x^2 + 140*x + 51744 @eprog\noindent To a Hecke-simple subspace corresponds an orbit of (normalized) newforms, defined over a number field. In the above example, we printed the polynomials defining the said fields, as well as the first 5 Fourier coefficients (at the infinite cusp) of one such form. The library syntax is \fun{GEN}{mssplit}{GEN M, GEN H = NULL, long dimlim}. \subsec{msstar$(M,\{H\})$}\kbdsidx{msstar}\label{se:msstar} $M$ being a full modular symbol space, as given by \kbd{msinit}, return the matrix of the \kbd{*} involution, induced by complex conjugation, acting on the (stable) subspace $H$ ($M$ if omitted). \bprog ? M = msinit(11,2); \\ M_2(Gamma_0(11)) ? w = msstar(M); ? w^2 == 1 %3 = 1 @eprog The library syntax is \fun{GEN}{msstar}{GEN M, GEN H = NULL}. \subsec{mstooms$(\var{Mp},\var{phi})$}\kbdsidx{mstooms}\label{se:mstooms} Given \kbd{Mp} from \kbd{mspadicinit}, lift the (classical) eigen symbol \kbd{phi} to a $p$-adic distribution-valued overconvergent symbol in the sense of Pollack and Stevens. More precisely, let $\phi$ belong to the space $W$ of modular symbols of level $N$, $v_{p}(N) \leq 1$, and weight $k$ which is an eigenvector for the Hecke operator $T_{N}(p)$ for a nonzero eigenvalue $a_{p}$ and let $N_{0} = \text{lcm}(N,p)$. Under the action of $T_{N_{0}}(p)$, $\phi$ generates a subspace $W_{\phi}$ of dimension $1$ (if $p\mid N$) or $2$ (if $p$ does not divide $N$) in the space of modular symbols of level $N_{0}$. Let $V_{p}=[p,0;0,1]$ and $C_{p}=[a_{p},p^{k-1};-1,0]$. When $p$ does not divide $N$ and $a_{p}$ is divisible by $p$, \kbd{mstooms} returns the lift $\Phi$ of $(\phi,\phi|_{k} V_{p})$ such that $$T_{N_{0}}(p) \Phi = C_{p} \Phi$$ When $p$ does not divide $N$ and $a_{p}$ is not divisible by $p$, \kbd{mstooms} returns the lift $\Phi$ of $\phi - \alpha^{-1} \phi|_{k} V_{p}$ which is an eigenvector of $T_{N_{0}}(p)$ for the unit eigenvalue where $\alpha^{2} - a_{p} \alpha + p^{k-1}=0$. The resulting overconvergent eigensymbol can then be used in \tet{mspadicmoments}, then \tet{mspadicL} or \tet{mspadicseries}. \bprog ? M = msinit(3,6, 1); p = 5; ? Tp = mshecke(M, p); factor(charpoly(Tp)) %2 = [x - 3126 2] [ x - 6 1] ? phi = matker(Tp - 6)[,1] \\ generator of p-Eigenspace, a_p = 6 %3 = [5, -3, -1]~ ? Mp = mspadicinit(M, p, 10, 0); \\ restrict to ordinary symbols, mod p^10 ? PHI = mstooms(Mp, phi); ? mu = mspadicmoments(Mp, PHI); ? mspadicL(mu) %7 = 5 + 2*5^2 + 2*5^3 + ... @eprog A non ordinary symbol. \bprog ? M = msinit(4,6,1); p = 3; ? Tp = mshecke(M, p); factor(charpoly(Tp)) %2 = [x - 244 3] [ x + 12 1] ? phi = matker(Tp + 12)[,1] \\ a_p = -12 is divisible by p = 3 %3 = [-1/32, -1/4, -1/32, 1]~ ? msissymbol(M,phi) %4 = 1 ? Mp = mspadicinit(M,3,5,0); ? PHI = mstooms(Mp,phi); *** at top-level: PHI=mstooms(Mp,phi) *** ^--------------- *** mstooms: incorrect type in mstooms [v_p(ap) > mspadicinit flag] (t_VEC). ? Mp = mspadicinit(M,3,5,1); ? PHI = mstooms(Mp,phi); @eprog The library syntax is \fun{GEN}{mstooms}{GEN Mp, GEN phi}. \section{Plotting functions} Although plotting is not even a side purpose of PARI, a number of plotting functions are provided. 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 attached 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 attached 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 (including Openwindows and Motif), Windows's Graphical Device Interface, and the FLTK graphical libraries and one may even write the graphical objects to a PostScript or SVG file and use an external viewer to open it. 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 all memory unrelated to the graphics engine 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. \subsec{Functions for PostScript or SVG output} in the same way that \kbd{printtex} allows you to have a \TeX\ output corresponding to printed results, the functions \kbd{plotexport}, \kbd{plothexport} and \kbd{plothrawexport} convert a plot to a character string in either \tet{PostScript} or \tet{Scalable Vector Graphics} format. This string can then be written to a file in the customary way, using \kbd{write}. These export routines are available even if no Graphic Library is. \smallskip \subsec{parploth$(X=a,b,\var{expr},\{\var{flags}=0\},\{n=0\})$}\kbdsidx{parploth}\label{se:parploth} Parallel version of \kbd{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{parploth} 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. The parameter $n$ specifies the number of reference point on the graph, where a value of 0 means we use the hardwired default values; the binary digits of \fl\ have the same meaning as in \kbd{ploth}: $1 = \kbd{Parametric}$; $2 = \kbd{Recursive}$; $4 = \kbd{no\_Rescale}$; $8 = \kbd{no\_X\_axis}$; $16 = \kbd{no\_Y\_axis}$; $32 = \kbd{no\_Frame}$; $64 = \kbd{no\_Lines}$; $128 = \kbd{Points\_too}$; $256 = \kbd{Splines}$; $512 = \kbd{no\_X\_ticks}$; $1024 = \kbd{no\_Y\_ticks}$; $2048 = \kbd{Same\_ticks}$; $4096 = \kbd{Complex}$. For instance: \bprog \\ circle parploth(X=0,2*Pi,[sin(X),cos(X)], "Parametric") \\ two entwined sinusoidal curves parploth(X=0,2*Pi,[sin(X),cos(X)]) \\ circle cut by the line y = x parploth(X=0,2*Pi,[X,X,sin(X),cos(X)], "Parametric") \\ circle parploth(X=0,2*Pi,exp(I*X), "Complex") \\ circle cut by the line y = x parploth(X=0,2*Pi,[(1+I)*X,exp(I*X)], "Complex") @eprog \synt{parploth}{GEN a,GEN b,GEN code, long flag, long n, long prec}. \subsec{parplothexport$(\var{fmt},X=a,b,\var{expr},\{\var{flags}=0\},\{n=0\})$}\kbdsidx{parplothexport}\label{se:parplothexport} Parallel version of \kbd{plothexport}. Plot of expression \var{expr}, $X$ goes from $a$ to $b$ in high resolution, returning the resulting picture as a character string which can then be written to a file. The format \kbd{fmt} is either \kbd{"ps"} (PostScript output) or \kbd{"svg"} (Scalable Vector Graphics). All other parameters and flags are as in \kbd{ploth}. \bprog ? s = parplothexport("svg", x=1,10, x^2+3); ? write("graph.svg", s); @eprog\noindent The above only works if \kbd{graph.svg} does not already exist, otherwise \kbd{write} will append to the existing file and produce an invalid \kbd{svg}. Here is a version that truncates an existing file (beware!): \bprog ? n = fileopen("graph.svg", "w"); ? filewrite(n, s); ? fileclose(n); @eprog\noindent This is intentionally more complicated. \synt{parplothexport}{GEN fmt, GEN a, GEN b, GEN code, long flags, long n, long prec}, \subsec{plot$(X=a,b,\var{expr},\{\var{Ymin}\},\{\var{Ymax}\})$}\kbdsidx{plot}\label{se:plot} Crude ASCII plot of the function represented by expression \var{expr} from $a$ to $b$, with \var{Y} ranging from \var{Ymin} to \var{Ymax}. If \var{Ymin} (resp. \var{Ymax}) is not given, the minimum (resp. the maximum) of the computed values of the expression is used instead. \synt{pariplot}{void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, GEN ymin, GEN ymax, long prec} \subsec{plotarc$(w,\var{x2},\var{y2},\{\var{filled}=0\})$}\kbdsidx{plotarc}\label{se:plotarc} Let $(x1,y1)$ be the current position of the virtual cursor. Draws in the rectwindow $w$ the outline of the ellipse that fits inside the box such that the points $(x1,y1)$ and $(x2,y2)$ are opposite corners. The virtual cursor does \emph{not} move. If $\var{filled}=1$, fills the ellipse. \bprog ? plotinit(1);plotmove(1,0,0); ? plotarc(1,50,50); plotdraw([1,100,100]); @eprog The library syntax is \fun{void}{plotarc}{long w, GEN x2, GEN y2, long filled}. \subsec{plotbox$(w,\var{x2},\var{y2},\{\var{filled}=0\})$}\kbdsidx{plotbox}\label{se:plotbox} Let $(x1,y1)$ be the current position of the virtual cursor. Draw in the rectwindow $w$ the outline of the rectangle which is such that the points $(x1,y1)$ and $(x2,y2)$ are opposite corners. Only the part of the rectangle which is in $w$ is drawn. The virtual cursor does \emph{not} move. If $\var{filled}=1$, fill the box. The library syntax is \fun{void}{plotbox}{long w, GEN x2, GEN y2, long filled}. \subsec{plotclip$(w)$}\kbdsidx{plotclip}\label{se:plotclip} `clips' the content of rectwindow $w$, i.e remove all parts of the drawing that would not be visible on the screen. Together with \tet{plotcopy} this function enables you to draw on a scratchpad before committing the part you're interested in to the final picture. The library syntax is \fun{void}{plotclip}{long w}. \subsec{plotcolor$(w,c)$}\kbdsidx{plotcolor}\label{se:plotcolor} Set default color to $c$ in rectwindow $w$. Return [R,G,B] value attached to color. Possible values for $c$ are \item a \typ{VEC} or \typ{VECSMALL} $[R,G,B]$ giving the color RGB value (all 3 values are between 0 and 255), e.g. \kbd{[250,235,215]} or equivalently \kbd{[0xfa, 0xeb, 0xd7]} for \kbd{antiquewhite}; \item a \typ{STR} giving a valid colour name (see the \kbd{rgb.txt} file in X11 distributions), e.g. \kbd{"antiquewhite"} or an RGV value given by a \kbd{\#} followed by 6 hexadecimal digits, e.g. \kbd{"\#faebd7"} for \kbd{antiquewhite}; \item a \typ{INT}, an index in the \tet{graphcolormap} default, factory setting are 0=white, 1=black, 2=blue, 3=violetred, 4=red, 5=green, 6=grey, 7=gainsborough and the color index is a non-negative integer in $[0,7]$. But this can be changed (see \kbd{??graphcolormap}); note that for historical reasons, \kbd{graphcolormap} is 0-based, so the color $c$ is a non-negative integer, strictly less than the length of the colormap. \bprog ? plotinit(0,100,100); ? plotcolor(0, "turquoise") %2 = [64, 224, 208] ? plotbox(0, 50,50,1); ? plotmove(0, 50,50); ? plotcolor(0, 2) \\ blue %4 = [0, 0, 255] ? plotbox(0, 50,50,1); ? plotdraw(0); @eprog The library syntax is \fun{GEN}{plotcolor}{long w, GEN c}. \subsec{plotcopy$(\var{sourcew},\var{destw},\var{dx},\var{dy},\{\fl=0\})$}\kbdsidx{plotcopy}\label{se:plotcopy} Copy the contents of rectwindow \var{sourcew} to rectwindow \var{destw} with offset (dx,dy). If $\fl$'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 $\fl$ vanish, otherwise of: 2: southwest, 4: southeast, 6: northeast corners. The library syntax is \fun{void}{plotcopy}{long sourcew, long destw, GEN dx, GEN dy, long flag}. \subsec{plotcursor$(w)$}\kbdsidx{plotcursor}\label{se:plotcursor} Give as a 2-component vector the current (scaled) position of the virtual cursor corresponding to the rectwindow $w$. The library syntax is \fun{GEN}{plotcursor}{long w}. \subsec{plotdraw$(w,\{\fl=0\})$}\kbdsidx{plotdraw}\label{se:plotdraw} Physically draw the rectwindow $w$. More generally, $w$ can be of the form $[w_{1},x_{1},y_{1},w_{2},x_{2},y_{2},\dots]$ (number of components must be divisible by $3$; the windows $w_{1}$, $w_{2}$, etc.~are physically placed with their upper left corner at physical position $(x_{1},y_{1})$, $(x_{2},y_{2})$,\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 window on your screen. If $\fl \neq 0$, $x_{1}$, $y_{1}$ etc. express fractions of the size of the current output device The library syntax is \fun{void}{plotdraw}{GEN w, long flag}. \subsec{plotexport$(\var{fmt},\var{list},\{\fl=0\})$}\kbdsidx{plotexport}\label{se:plotexport} Draw list of rectwindows as in \kbd{plotdraw(list,flag)}, returning the resulting picture as a character string which can then be written to a file. The format \kbd{fmt} is either \kbd{"ps"} (PostScript output) or \kbd{"svg"} (Scalable Vector Graphics). \bprog ? plotinit(0, 100, 100); ? plotbox(0, 50, 50); ? plotcolor(0, 2); ? plotbox(0, 30, 30); ? plotdraw(0); \\ watch result on screen ? s = plotexport("svg", 0); ? write("graph.svg", s); \\ dump result to file @eprog The library syntax is \fun{GEN}{plotexport}{GEN fmt, GEN list, long flag}. \subsec{ploth$(X=a,b,\var{expr},\{\fl=0\},\{n=0\})$}\kbdsidx{ploth}\label{se:ploth} High precision plot of the function $y=f(x)$ represented by the expression \var{expr}, $x$ going from $a$ to $b$. This opens a specific window (which is killed whenever you click on it), and returns a four-component vector giving the coordinates of the bounding box in the form $[\var{xmin},\var{xmax},\var{ymin},\var{ymax}]$. \misctitle{Important note} \kbd{ploth} may evaluate \kbd{expr} thousands of times; given the relatively low resolution of plotting devices, few significant digits of the result will be meaningful. Hence you should keep the current precision to a minimum (e.g.~9) before calling this function. $n$ specifies the number of reference point on the graph, where a value of 0 means we use the hardwired default values (1000 for general plot, 1500 for parametric plot, and 8 for recursive plot). If no $\fl$ is given, \var{expr} is either a scalar expression $f(X)$, in which case the plane curve $y=f(X)$ will be drawn, or a vector $[f_{1}(X),\dots,f_{k}(X)]$, and then all the curves $y=f_{i}(X)$ will be drawn in the same window. \noindent The binary digits of $\fl$ mean: \item $1 = \kbd{Parametric}$: \tev{parametric plot}. Here \var{expr} must be a vector with an even number of components. Successive pairs are then understood as the parametric coordinates of a plane curve. Each of these are then drawn. For instance: \bprog ploth(X=0,2*Pi,[sin(X),cos(X)], "Parametric") ploth(X=0,2*Pi,[sin(X),cos(X)]) ploth(X=0,2*Pi,[X,X,sin(X),cos(X)], "Parametric") @eprog\noindent draw successively a circle, two entwined sinusoidal curves and a circle cut by the line $y=x$. \item $2 = \kbd{Recursive}$: \tev{recursive plot}. If this 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 \pb 32 ploth(X=-1,1, sin(1/X)) ploth(X=-1,1, sin(1/X), "Recursive") @eprog\noindent for instance. Note that this example is pathological as it is impossible to evaluate $\sin(1/X)$ close to~$0$. It is better to avoid the singularity as follows. \bprog ploth(X=1e-10,1, sin(1/X), "Recursive") @eprog 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$. \item $8192 = \kbd{no\_MinMax}$: do not print the boundary numbers (in both directions). \synt{ploth}{void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, long flag, long n, long prec}, \subsec{plothexport$(\var{fmt},X=a,b,\var{expr},\{\var{flags}=0\},\{n=0\})$}\kbdsidx{plothexport}\label{se:plothexport} Plot of expression \var{expr}, $X$ goes from $a$ to $b$ in high resolution, returning the resulting picture as a character string which can then be written to a file. The format \kbd{fmt} is either \kbd{"ps"} (PostScript output) or \kbd{"svg"} (Scalable Vector Graphics). All other parameters and flags are as in \kbd{ploth}. \bprog ? s = plothexport("svg", x=1,10, x^2+3); ? write("graph.svg", s); @eprog \synt{plothexport}{GEN fmt, void *E, GEN (*eval)(void*, GEN), GEN a, GEN b, long flags, long n, long prec}, \subsec{plothraw$(X,Y,\{\fl=0\})$}\kbdsidx{plothraw}\label{se:plothraw} Given $X$ and $Y$ two vectors of equal length, plots (in high precision) the points whose $(x,y)$-coordinates are given in $X$ and $Y$. Automatic positioning and scaling is done, but with the same scaling factor on $x$ and $y$. If $\fl$ is 1, join points, other nonzero flags toggle display options and should be combinations of bits $2^{k}$, $k \geq 3$ as in \kbd{ploth}. The library syntax is \fun{GEN}{plothraw}{GEN X, GEN Y, long flag}. \subsec{plothrawexport$(\var{fmt},X,Y,\{\fl=0\})$}\kbdsidx{plothrawexport}\label{se:plothrawexport} Given $X$ and $Y$ two vectors of equal length, plots (in high precision) the points whose $(x,y)$-coordinates are given in $X$ and $Y$, returning the resulting picture as a character string which can then be written to a file. The format \kbd{fmt} is either \kbd{"ps"} (PostScript output) or \kbd{"svg"} (Scalable Vector Graphics). Automatic positioning and scaling is done, but with the same scaling factor on $x$ and $y$. If $\fl$ is 1, join points, other nonzero flags toggle display options and should be combinations of bits $2^{k}$, $k \geq 3$ as in \kbd{ploth}. The library syntax is \fun{GEN}{plothrawexport}{GEN fmt, GEN X, GEN Y, long flag}. \subsec{plothsizes$(\{\fl=0\})$}\kbdsidx{plothsizes}\label{se:plothsizes} Return data corresponding to the output window in the form of a 8-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, width and height of display, if applicable. If display has no sense, e.g. for svg plots or postscript plots, then width and height of display are set to 0. If $\fl = 0$, sizes of ticks and characters are in pixels, otherwise are fractions of the screen size The library syntax is \fun{GEN}{plothsizes}{long flag}. \subsec{plotinit$(w,\{x\},\{y\},\{\fl=0\})$}\kbdsidx{plotinit}\label{se:plotinit} Initialize the rectwindow $w$, destroying any rect objects you may have already drawn in $w$. The virtual cursor is set to $(0,0)$. The rectwindow size is set to width $x$ and height $y$; omitting either $x$ or $y$ means we use the full size of the device in that direction. If $\fl=0$, $x$ and $y$ represent pixel units. Otherwise, $x$ and $y$ are understood as fractions of the size of the current output device (hence must be between $0$ and $1$) and internally converted to pixels. The plotting device imposes an upper bound for $x$ and $y$, for instance the number of pixels for screen output. These bounds are available through the \tet{plothsizes} function. The following sequence initializes in a portable way (i.e independent of the output device) a window of maximal size, accessed through coordinates in the $[0,1000] \times [0,1000]$ range: \bprog s = plothsizes(); plotinit(0, s[1]-1, s[2]-1); plotscale(0, 0,1000, 0,1000); @eprog The library syntax is \fun{void}{plotinit}{long w, GEN x = NULL, GEN y = NULL, long flag}. \subsec{plotkill$(w)$}\kbdsidx{plotkill}\label{se:plotkill} Erase rectwindow $w$ and free the corresponding memory. Note that if you want to use the rectwindow $w$ again, you have to use \kbd{plotinit} first to specify the new size. So it's better in this case to use \kbd{plotinit} directly as this throws away any previous work in the given rectwindow. The library syntax is \fun{void}{plotkill}{long w}. \subsec{plotlines$(w,X,Y,\{\fl=0\})$}\kbdsidx{plotlines}\label{se:plotlines} Draw on the rectwindow $w$ the polygon such that the (x,y)-coordinates of the vertices are in the vectors of equal length $X$ and $Y$. For simplicity, the whole polygon is drawn, not only the part of the polygon which is inside the rectwindow. If $\fl$ is nonzero, 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. The library syntax is \fun{void}{plotlines}{long w, GEN X, GEN Y, long flag}. \subsec{plotlinetype$(w,\var{type})$}\kbdsidx{plotlinetype}\label{se:plotlinetype} This function is obsolete and currently a no-op. 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. The library syntax is \fun{void}{plotlinetype}{long w, long type}. \subsec{plotmove$(w,x,y)$}\kbdsidx{plotmove}\label{se:plotmove} Move the virtual cursor of the rectwindow $w$ to position $(x,y)$. The library syntax is \fun{void}{plotmove}{long w, GEN x, GEN y}. \subsec{plotpoints$(w,X,Y)$}\kbdsidx{plotpoints}\label{se:plotpoints} Draw on the rectwindow $w$ the points whose $(x,y)$-coordinates are in the vectors of equal length $X$ and $Y$ and which are inside $w$. The virtual cursor does \emph{not} move. This is basically the same function as \kbd{plothraw}, but either with no scaling factor or with a scale chosen using the function \kbd{plotscale}. As was the case with the \kbd{plotlines} function, $X$ and $Y$ are allowed to be (simultaneously) scalar. In this case, draw the single point $(X,Y)$ on the rectwindow $w$ (if it is actually inside $w$), and in any case \emph{move} the virtual cursor to position $(x,y)$. If you draw few points in the rectwindow, they will be hard to see; in this case, you can use filled boxes instead. Compare: \bprog ? plotinit(0, 100,100); plotpoints(0, 50,50); ? plotdraw(0) ? plotinit(1, 100,100); plotmove(1,48,48); plotrbox(1, 4,4, 1); ? plotdraw(1) @eprog The library syntax is \fun{void}{plotpoints}{long w, GEN X, GEN Y}. \subsec{plotpointsize$(w,\var{size})$}\kbdsidx{plotpointsize}\label{se:plotpointsize} This function is obsolete. It is currently a no-op. Changes the ``size'' of following points in rectwindow $w$. If $w = -1$, change it in all rectwindows. The library syntax is \fun{void}{plotpointsize}{long w, GEN size}. \subsec{plotpointtype$(w,\var{type})$}\kbdsidx{plotpointtype}\label{se:plotpointtype} This function is obsolete and currently a no-op. 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. The library syntax is \fun{void}{plotpointtype}{long w, long type}. \subsec{plotrbox$(w,\var{dx},\var{dy},\{\var{filled}\})$}\kbdsidx{plotrbox}\label{se:plotrbox} Draw in the rectwindow $w$ the outline of the rectangle which is such that the points $(x1,y1)$ and $(x1+dx,y1+dy)$ are opposite corners, where $(x1,y1)$ is the current position of the cursor. Only the part of the rectangle which is in $w$ is drawn. The virtual cursor does \emph{not} move. If $\var{filled}=1$, fill the box. The library syntax is \fun{void}{plotrbox}{long w, GEN dx, GEN dy, long filled}. \subsec{plotrecth$(w,X=a,b,\var{expr},\{\fl=0\},\{n=0\})$}\kbdsidx{plotrecth}\label{se:plotrecth} Writes to rectwindow $w$ the curve output of \kbd{ploth}$(w,X=a,b,\var{expr},\fl,n)$. Returns a vector for the bounding box. %\syn{NO} \subsec{plotrecthraw$(w,\var{data},\{\var{flags}=0\})$}\kbdsidx{plotrecthraw}\label{se:plotrecthraw} Plot graph(s) for \var{data} in rectwindow $w$; $\fl$ has the same meaning here as in \kbd{ploth}, though recursive plot is no longer significant. The argument \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. The library syntax is \fun{GEN}{plotrecthraw}{long w, GEN data, long flags}. \subsec{plotrline$(w,\var{dx},\var{dy})$}\kbdsidx{plotrline}\label{se:plotrline} Draw in the rectwindow $w$ the part of the segment $(x1,y1)-(x1+dx,y1+dy)$ which is inside $w$, where $(x1,y1)$ is the current position of the virtual cursor, and move the virtual cursor to $(x1+dx,y1+dy)$ (even if it is outside the window). The library syntax is \fun{void}{plotrline}{long w, GEN dx, GEN dy}. \subsec{plotrmove$(w,\var{dx},\var{dy})$}\kbdsidx{plotrmove}\label{se:plotrmove} Move the virtual cursor of the rectwindow $w$ to position $(x1+dx,y1+dy)$, where $(x1,y1)$ is the initial position of the cursor (i.e.~to position $(dx,dy)$ relative to the initial cursor). The library syntax is \fun{void}{plotrmove}{long w, GEN dx, GEN dy}. \subsec{plotrpoint$(w,\var{dx},\var{dy})$}\kbdsidx{plotrpoint}\label{se:plotrpoint} Draw the point $(x1+dx,y1+dy)$ on the rectwindow $w$ (if it is inside $w$), where $(x1,y1)$ is the current position of the cursor, and in any case move the virtual cursor to position $(x1+dx,y1+dy)$. If you draw few points in the rectwindow, they will be hard to see; in this case, you can use filled boxes instead. Compare: \bprog ? plotinit(0, 100,100); plotrpoint(0, 50,50); plotrpoint(0, 10,10); ? plotdraw(0) ? thickpoint(w,x,y)= plotmove(w,x-2,y-2); plotrbox(w,4,4,1); ? plotinit(1, 100,100); thickpoint(1, 50,50); thickpoint(1, 60,60); ? plotdraw(1) @eprog The library syntax is \fun{void}{plotrpoint}{long w, GEN dx, GEN dy}. \subsec{plotscale$(w,\var{x1},\var{x2},\var{y1},\var{y2})$}\kbdsidx{plotscale}\label{se:plotscale} Scale the local coordinates of the rectwindow $w$ so that $x$ goes from $x1$ to $x2$ and $y$ goes from $y1$ to $y2$ ($x2} key. Then computation starts, and a result is eventually printed. To suppress printing of the result, end the expression with a \kbd{;} sign. Note that many systems use \kbd{;} to indicate end of input. Not so in \kbd{gp}: a final semicolon means the result should not be printed. (Which is certainly useful if it occupies several screens.) \subsec{Interrupt, Quit} Typing \kbd{quit} at the prompt ends the session and exits \kbd{gp}. At any point you can type \kbd{Ctrl-C} (that is press simultaneously the \kbd{Control} and \kbd{C} keys): the current computation is interrupted and control given back to you at the \kbd{gp} prompt, together with a message like \bprog *** at top-level: gcd(a,b) *** ^-------- *** gcd: user interrupt after 236 ms. @eprog\noindent telling you how much time elapsed since the last command was typed in and in which GP function the computation was aborted. It does not mean that that much time was spent in the function, only that the evaluator was busy processing that specific function when you stopped it. \section{The general gp input line} The \kbd{gp} calculator uses a purely interpreted language GP. The structure of this language is reminiscent of LISP with a functional notation, \kbd{f(x,y)} rather than \kbd{(f x y)}: all programming constructs, such as \kbd{if}, \kbd{while,} etc\dots are functions\footnote{*}{Not exactly, since not all their arguments need be evaluated. For instance it would be stupid to evaluate both branches of an \kbd{if} statement: since only one will apply, only this one is evaluated.}, and the main loop does not really execute, but rather evaluates (sequences of) expressions. Of course, it is by no means a true LISP, and has been strongly influenced by C and Perl since then. \subsec{Introduction} User interaction with a \kbd{gp} session proceeds as follows. First, one types a sequence of characters at the \kbd{gp} prompt; see \secref{se:readline} for a description of the line editor. When you hit the \kbd{} key, \kbd{gp} gets your input, evaluates it, then prints the result and assigns it to an ``history'' array. More precisely, the input is case-sensitive and, outside of character strings, blanks are completely ignored. Inputs are either metacommands or sequences of expressions. Metacommands are shortcuts designed to alter gp's internal state, such as the working precision or general verbosity level; we shall describe them in \secref{se:meta}, and ignore them for the time being. The evaluation of a sequence of instructions proceeds in two phases: your input is first digested (byte-compiled) to a bytecode suitable for fast evaluation, in particular loop bodies are compiled only once but a priori evaluated many times; then the bytecode is evaluated. An \idx{expression}\sidx{expression sequence} is formed by combining constants, variables, operator symbols, functions and control statements. It is evaluated using the conventions about operator priorities and left to right associativity. An expression always has a value, which can be any PARI object: \bprog ? 1 + 1 %1 = 2 \\@com an ordinary integer ? x %2 = x \\@com a polynomial of degree 1 in the unknown \kbd{x} ? print("Hello") Hello \\@com \kbd{void} return value, 'Hello' printed as side effect ? f(x) = x^2 %4 = (x)->x^2 \\@com a user function @eprog \noindent In the third example, \kbd{Hello} is printed as a side effect, but is not the return value. The \kbd{print} command is a \emph{procedure}, which conceptually returns nothing. But in fact procedures return a special \kbd{void} object, meant to be ignored (but which evaluates to $0$ in a numeric context, and stored as $0$ in the history or results). The final example assigns to the variable \kbd{f} the function $x\mapsto x^2$, the alternative form \kbd{f = x->x\pow2} achieving the same effect; the return value of a function definition is, unsurprisingly, a function object (of type \typ{CLOSURE}). Several expressions are combined on a single line by separating them with semicolons ('\kbd{;}'). Such an expression sequence will be called a \var{seq}. A \var{seq} also has a value, which is the value of the last expression in the sequence. Under \kbd{gp}, the value of the \var{seq}, and only this last value, becomes an history entry. The values of the other expressions in the \var{seq} are discarded after the execution of the \var{seq} is complete, except of course if they were assigned into variables. In addition, the value of the \var{seq} is printed if the line does not end with a semicolon \kbd{;}. \subsec{The gp history of results} This is not to be confused with the history of your \emph{commands}, maintained by \kbd{readline}. The \kbd{gp} history contains the \emph{results} they produced, in sequence. The successive elements of the history array are called \kbd{\%1}, \kbd{\%2}, \dots As a shortcut, the latest computed expression can also be called \kbd{\%}, the previous one \kbd{\%`}, the one before that \kbd{\%``} and so on. When you suppress the printing of the result with a semicolon, it is still stored in the history, but its history number will not appear either. It is a better idea to assign it to a variable for later use than to mentally recompute what its number is. Of course, on the next line, you may just use \kbd{\%}. The time used to compute that history entry is also stored as part of the entry and can be recovered using the \kbd{\%\#} operator: \kbd{\%\#1}, \kbd{\%\#2}, \kbd{\%\#`}; \kbd{\%\#} by itself returns the time needed to compute the last result (the one returned by \kbd{\%}). The output is a vector with two components \kbd{[cpu, real]} where \kbd{cpu} is the CPU time and \kbd{real} is the wall clock time. \misctitle{Remark} The history ``array'' is in fact better thought of as a queue: its size is limited to 5000 entries by default, after which \kbd{gp} starts forgetting the initial entries. So \kbd{\%1} becomes unavailable as \kbd{gp} prints \kbd{\%5001}. You can modify the history size using \tet{histsize}. \subsec{Special editing characters}\sidx{editing characters} A GP program can of course have more than one line. Since your commands are executed as soon as you have finished typing them, there must be a way to tell \kbd{gp} to wait for the next line or lines of input before doing anything. There are three ways of doing this. The first one is to use the \idx{backslash character} \kbd{\bs} at the end of the line that you are typing, just before hitting \kbd{}. This tells \kbd{gp} that what you will write on the next line is the physical continuation of what you have just written. In other words, it makes \kbd{gp} forget your newline character. You can type a \kbd{\bs} anywhere. It is interpreted as above only if (apart from ignored whitespace characters) it is immediately followed by a newline. For example, you can type \bprog ? 3 + \ 4 @eprog \noindent instead of typing \kbd{3 + 4}. The second one is a variation on the first, and is mostly useful when defining a user function (see \secref{se:user_defined}): since an equal sign can never end a valid expression, \kbd{gp} disregards a newline immediately following an \kbd{=}. \bprog ? a = 123 %1 = 123 @eprog The third one is in general much more useful, and uses braces \kbd{\obr} and \kbd{\cbr}.\sidx{brace characters} An opening brace \kbd{\obr} signals that you are typing a multi-line command, and newlines are ignored until you type a closing brace \kbd{\cbr}. There are two important, but easily obeyed, restrictions: first, braces do not nest; second, inside an open brace-close brace pair, all input lines are concatenated, suppressing any newlines. Thus, all newlines should occur after a semicolon (\kbd{;}), a comma (\kbd{,}) or an operator (for clarity's sake, never split an identifier over two lines in this way). For instance, the following program \bprog { a = b b = c } @eprog \noindent would silently produce garbage, since this is interpreted as \kbd{a=bb=c} which assigns the value of \kbd{c} to both \kbd{bb} and \kbd{a}. It should have been written \bprog { a = b; b = c; } @eprog \section{The PARI types} \noindent We see here how to input values of the different data types known to PARI. Recall that blanks are ignored in any expression which is not a string (see below). \misctitle{A note on efficiency} The following types are provided for convenience, not for speed: \typ{INTMOD}, \typ{FRAC}, \typ{PADIC}, \typ{QUAD}, \typ{POLMOD}, \typ{RFRAC}. Indeed, they always perform a reduction of some kind after each basic operation, even though it is usually more efficient to perform a single reduction at the end of some complex computation. For instance, in a convolution product $\sum_{i+j = n} x_i y_j$ in $\Z/N\Z$ --- common when multiplying polynomials! ---, it is quite wasteful to perform $n$ reductions modulo $N$. In short, basic individual operations on these types are fast, but recursive objects with such components could be handled more efficiently: programming with libpari will save large constant factors here, compared to GP. \subsec{Integers (\typ{INT})}% \sidx{integer}\kbdsidx{t_INT} After an (optional) leading \kbd{+} or \kbd{-}, type in the decimal digits of your integer. No decimal point! \bprog ? 1234567 %1 = 1234567 ? -3 %2 = -3 ? 1. \\@com oops, not an integer %3 = 1.000000000000000000000000000 @eprog Integers can be input in hexadecimal notation by prefixing them with \kbd{0x}; hexadecimal digits ($a, \dots, f$) can be input either in lowercase or in uppercase: \bprog ? 0xF %4 = 15 ? 0x1abcd %5 = 109517 @eprog Integers can also be input in binary by prefixing them with \kbd{0b}: \bprog ? 0b010101 %6 = 21 @eprog \subsec{Real numbers (\typ{REAL})}% \sidx{real number}\kbdsidx{t_REAL} Real numbers are represented (approximately) in a floating point system, internally in base 2, but converted to base 10 for input / output purposes. A \typ{REAL} object has a given \emph{bit accuracy} (or \emph{bit precision}) $\ell \geq 0$; it comprises \item a sign $s$: $+1$, $-1$ or $0$; \item a mantissa $m$: a multiprecision integer, $0\leq m < 2^\ell$; \item an exponent $e$: a small integer in $[-2^B,2^B[$, where $B = 31$ on a 32-bit machine and 63 otherwise. This data may represent any real number $x$ such that $$|x - s m 2^e| < 2^{e-\ell}.$$ We consider that a \typ{REAL} with sign $s = 0$ has accuracy $\ell = 0$, so that its mantissa is useless, but it still has an exponent $e$ and acts like a machine epsilon for all accuracies $< e$. After an (optional) leading \kbd{+} or \kbd{-}, type a number with a decimal point. Leading zeroes may be omitted, up to the decimal point, but trailing zeroes are important: your \typ{REAL} is assigned an internal precision, which is the supremum of the input precision, one more than the number of decimal digits input, and the default \tet{realprecision}. For example, if the default precision is 38 digits, typing \kbd{2.} yields a precision of 38 digits, but \kbd{2.0\dots0} with 45 zeros gives a number with internal decimal precision at least 45, although less may be printed. You can also use scientific notation with the letter \kbd{E} or \kbd{e}. As usual, \kbd{e$n$} is interpreted as $\times 10^n$ for all integers $n$. Since the result is converted to a \typ{REAL}, you may often omit the decimal point in this case: \kbd{6.02 E 23} or \kbd{1e-5} are fine, but \kbd{e10} is not. By definition, \kbd{0.E $n$} returns a real $0$ of exponent $n$, whereas \kbd{0.} returns a real 0 ``of default precision'' (of exponent $-\tet{realprecision}$), see \secref{se:whatzero}, behaving like the machine epsilon for the current default accuracy: any float of smaller absolute value is indistinguishable from $0$. \misctitle{Note on output formats} A zero real number is printed in \kbd{e} format as $0.Exx$ where $xx$ is the (usually negative) \emph{decimal} exponent of the number (cf.~\secref{se:whatzero}). This allows the user to check the accuracy of that particular zero. When the integer part of a real number $x$ is not known exactly because the exponent of $x$ is greater than the internal precision, the real number is printed in \kbd{e} format. \misctitle{Technical note} The internal \emph{precision} is actually expressed in bits and can be viewed and manipulated globally in interactive use via \kbd{realprecision} (decimal digits, as explained above; shortcut \kbd{\bs p}) or \kbd{realbitprecision} (bits; shortcut \kbd{\bs pb}), the latter allowing finer granularity. See \secref{se:trans} for details. In programs we advise to leave this global variable alone and adapt precision locally for a given sequence of computations using \tet{localbitprec}. Note that most decimal floating point numbers cannot be converted exactly in binary, the (binary) number actually stored is a rounded version of the (decimal) number input. Analogously, a decimal output is rounded from the internal binary representation. \subsec{Intmods (\typ{INTMOD})}% \sidx{intmod}\kbdsidx{t_INTMOD} To create the image of the integer $a$ in $\Z/b\Z$ (for some nonzero integer $b$), type \kbd{Mod(a,b)}; \emph{not} \kbd{a\%b}. Internally, all operations are done on integer representatives belonging to $[0,b-1]$. Note that this type is available for convenience, not for speed: each elementary operation involves a reduction modulo $b$. If $x$ is a \typ{INTMOD} \kbd{Mod(a,b)}, the following member function is defined: \kbd{x.mod}: return the modulus \kbd{b}. \subsec{Rational numbers (\typ{FRAC})}% \sidx{rational number}\kbdsidx{t_FRAC} All fractions are automatically reduced to lowest terms, so it is impossible to work with reducible fractions. To enter $n/m$ just type it as written. As explained in \secref{se:gdiv}, floating point division is \emph{not} performed, only reduction to lowest terms.\label{se:FRAC} Note that rational computation are almost never the fastest method to proceed: in the PARI implementation, each elementary operation involves computing a gcd. It is generally a little more efficient to cancel denominators and work with integers only: \bprog ? P = Pol( vector(10^3,i, 1/i) ); \\@com big polynomial with small rational coeffs ? P^2 time = 1,392 ms. ? c = content(P); c^2 * (P/c)^2; \\@com same computation in integers time = 1,116 ms. @eprog\noindent And much more efficient (but harder to setup) to use homomorphic imaging schemes and modular computations. As the simple example below indicates, if you only need modular information, it is very worthwhile to work with \typ{INTMOD}s directly, rather than deal with \typ{FRAC}s all the way through: \bprog ? p = nextprime(10^7); ? sum(i=1, 10^5, 1/i) % p time = 13,288 ms. %1 = 2759492 ? sum(i=1, 10^5, Mod(1/i, p)) time = 60 ms. %2 = Mod(2759492, 10000019) @eprog\noindent \subsec{Finite field elements (\typ{FFELT})}% \sidx{finite field element}\kbdsidx{t_FFELT} Let $T\in\F_p[X]$ be a monic irreducible polynomial defining your finite field over $\F_p$, for instance obtained using \tet{ffinit}. Then the \tet{ffgen} function creates a generator of the finite field as an $\F_p$-algebra, namely the class of $X$ in $\F_p[X]/(T)$, from which you can build all other elements. For instance, to create the field $\F_{2^8}$, we write \bprog ? T = ffinit(2, 8); ? y = ffgen(T, 'y); ? y^0 \\ the unit element in the field %3 = 1 ? y^8 %4 = y^6 + y^5 + y^4 + y^3 + y + 1 @eprog\noindent The second (optional) parameter to \tet{ffgen} is only used to display the result; it is customary to use the name of the variable we assign the generator to. If \kbd{g} is a \typ{FFELT}, the following member functions are defined: \kbd{g.pol}: the polynomial (with reduced integer coefficients) expressing \kbd{g} in term of the field generator. \kbd{g.p}: the characteristic of the finite field. \kbd{g.f}: the dimension of the definition field over its prime field; the cardinality of the definition field is thus $p^f$. \kbd{g.mod}: the minimal polynomial (with reduced integer coefficients) of the field generator. \subsec{Complex numbers (\typ{COMPLEX})}% \sidx{complex number}\kbdsidx{t_COMPLEX} To enter $x+iy$, type \kbd{x + I*y}. (That's \kbd{I}, \emph{not} \kbd{i}!) The letter \tet{I} stands for $\sqrt{-1}$. The ``real'' and ``imaginary'' parts $x$ and $y$ can be of type \typ{INT}, \typ{REAL}, \typ{INTMOD}, \typ{FRAC}, or \typ{PADIC}. \subsec{$p$-adic numbers (\typ{PADIC}):}% \sidx{p-adic number}\label{se:padic}\kbdsidx{t_PADIC} Typing \kbd{O($p$\pow $k$)}, where $p$ is a prime and $k$ is an integer, yields a $p$-adic $0$ of accuracy~$k$, representing any $p$-adic number whose valuation is $\geq k$. To input a general nonzero $p$-adic number, write a suitably precise rational or integer approximation and add \kbd{O($p$\pow $k$)} to it. For example, you can type in the $7$-adic number \bprog 2*7^(-1) + 3 + 4*7 + 2*7^2 + O(7^3) @eprog\noindent exactly as shown, or equivalently as \kbd{905/7 + O(7\pow3)}. Note that it is not checked whether $p$ is indeed prime but results are undefined if this is not the case: you can try to work on $10$-adics if you want, but disasters will happen as soon as you do something nontrivial. For instance: \bprog ? t = 2 * (1/10 + O(10^5)); ? lift(t) %2 = 2/10 \\ not reduced (invalid t_FRAC) ? factor(x^2-t) *** at top-level: factor(x^2-%1) *** ^-------------- *** factor: impossible inverse in Fl_inv: Mod(2, 10000). @eprog\noindent Note that \kbd{O(25)} is not the same as \kbd{O(5\pow 2)}; you want the latter! If $a$ is a \typ{PADIC}, the following member functions are defined: \kbd{a.mod}: returns the modulus $p^k$. \kbd{a.p}: returns $p$. Note that this type is available for convenience, not for speed: internally, \typ{PADIC}s are stored as $p$-adic units modulo some $p^k$. Each elementary operation involves updating $p^k$ (multiplying or dividing by powers of $p$) and a reduction mod $p^k$. In particular, additions are slow. \bprog ? n = 1+O(2^20); for (i=1,10^6, n++) time = 841 ms. ? n = Mod(1,2^20); for (i=1,10^6, n++) time = 441 ms. ? n = 1; for (i=1,10^6, n++) time = 328 ms. @eprog\noindent The penalty attached to maintaining $p^k$ decreases steeply as $p$ increases (and updates become rare). But \typ{INTMOD}s remain at least 25\% more efficient. (On the other hand, they do not allow denominators!) % n = 1+O(1009^2); for (i=1,10^6, n++) % n = Mod(1,1009^2); for (i=1,10^6, n++) \subsec{Quadratic numbers (\typ{QUAD})}% \sidx{quadratic number}\kbdsidx{t_QUAD} This type is used to work in the quadratic order of \emph{discriminant} \kbd{d}, where \kbd{d} is a nonsquare integer congruent to $0$ or $1$ (modulo $4$). The command \bprog w = quadgen(d,'w) @eprog\noindent assigns to \kbd{w} the ``canonical'' generator for the integer basis of the order of discriminant $d$, i.e.~$w=\sqrt{d}/2$ if $d\equiv 0 \mod 4$, and $w=(1+\sqrt{d})/2$ if $d\equiv 1 \mod 4$ and set its name to \kbd{w}. The name \kbd{'w} is used for printing and we advise to store it in a variable of the same name. Beware, two \typ{QUAD}s with different discriminants can be printed in the same way and not be equal; however, \kbd{gp} will refuse to add or multiply them for example, so use different names for different discriminants. Since the order is $\Z + \kbd{w}\Z$, any other element can be input as \kbd{a = $x$+$y$*w} for some integers $x$ and $y$. In fact, you may work in its fraction field $\Q(\sqrt{d})$ and use \typ{FRAC} values for $x$ and $y$. The following member functions are defined: \kbd{a.disc} retrieves the discriminant $d$; \kbd{a.mod}: returns the minimal polynomial $T$ of \kbd{w}; \kbd{a.pol}: returns the \typ{POL} $x + wy$. In particular \kbd{[x,y] = Vecrev(a.pol)} recovers $x$ and $y$. The components $x$ and $y$ are also obtained via \kbd{real(a)} and \kbd{imag(z)} respectively. \subsec{Polmods (\typ{POLMOD})}% \sidx{polmod}\kbdsidx{t_POLMOD} Exactly as for intmods, to enter $x \mod y$ (where $x$ and $y$ are polynomials), type \kbd{Mod(x,y)}, not \kbd{x\%y}. Note that when $y$ is an irreducible polynomial in one variable, polmods whose modulus is $y$ are simply algebraic numbers in the finite extension defined by the polynomial $y$. This allows us to work easily in \idx{number field}s, finite extensions of the $p$-adic field $\Q_p$, or \idx{finite field}s. Note that this type is available for convenience, not for speed: each elementary operation involves a reduction modulo $y$. If $p$ is a \typ{POLMOD}, the following member functions are defined: \kbd{p.pol}: return a representative of the polynomial class of minimal degree. \kbd{p.mod}: return the modulus. \label{se:rempolmod} \misctitle{Important remark}\sidx{variable (priority)} Mathematically, the variables\sidx{variable} occurring in a polmod are not free variables. But internally, a congruence class in $R[t]/(y)$ is represented by its representative of lowest degree, which is a \typ{POL} in $R[t]$, and computations occur with polynomials in the variable $t$. PARI will not recognize that \kbd{Mod(y, y\pow2 + 1)} is ``the same'' as \kbd{Mod(x, x\pow2 + 1)}, since \kbd{x} and \kbd{y} are different variables. To avoid inconsistencies, polmods must use the same variable in internal operations (i.e.~between polmods) and variables of lower priority for external operations, typically between a polynomial and a polmod. See \secref{se:priority} for a definition of ``priority'' and a discussion of (PARI's idea of) multivariate polynomial arithmetic. For instance: \bprog ? Mod(x, x^2+ 1) + Mod(x, x^2 + 1) %1 = Mod(2*x, x^2 + 1) \\@com $2i$ (or $-2i$), with $i^2=-1$ ? x + Mod(y, y^2 + 1) %2 = x + Mod(y, y^2 + 1) \\@com in $\Q(i)[x]$ ? y + Mod(x, x^2 + 1) %3 = Mod(x + y, x^2 + 1) \\@com in $\Q(y)[i]$ @eprog\noindent The first two are straightforward, but the last one may not be what you want: \kbd{y} is treated here as a numerical parameter, not as a polynomial variable. If the main variables are the same, it is allowed to mix \typ{POL} and \typ{POLMOD}s. The result is the expected \typ{POLMOD}. For instance \bprog ? x + Mod(x, x^2 + 1) %1 = Mod(2*x, x^2 + 1) @eprog \subsec{Polynomials (\typ{POL})}% \sidx{polynomial}\label{se:pol}\kbdsidx{t_POL} Type the polynomial in a natural way, not forgetting to put a ``$*$'' between a coefficient and a formal variable; \bprog ? 1 + 2*x + 3*x^2 %1 = 3*x^2 + 2*x + 1 @eprog\noindent This assumes that \kbd{x} is still a ''free variable''. \bprog ? x = 1; 1 + 2*x + 3*x^2 %2 = 6 @eprog\noindent generates an integer, not a polynomial! It is good practice to never assign values to polynomial variables to avoid the above problem, but a foolproof construction is available using \kbd{'x} instead of~\kbd{x}: \kbd{'x} is a constant evaluating to the free variable with name \kbd{x}, independently of the current value of~\kbd{x}. \bprog ? x = 1; 1 + 2*'x + 3*'x^2 %3 = 1 + 2*x + 3*x^2 ? x = 'x; 1 + 2*x + 3*x^2 %4 = 1 + 2*x + 3*x^2 @eprog\noindent You may also use the functions \kbd{Pol} or \kbd{Polrev}: \bprog ? Pol([1,2,3]) \\@com \kbd{Pol} creates a polynomial in \kbd{x} by default %1 = x^2 + 2*x + 3 ? Polrev([1,2,3]) %2 = 3*x^2 + 2*x + 1 ? Pol([1,2,3], 'y) \\@com we use \kbd{'y}, safer than \kbd{y} %3 = y^2 + 2*y + 3 @eprog\noindent The latter two are much more efficient constructors than an explicit summation (the latter is quadratic in the degree, the former linear): \bprog ? for (i=1, 10^4, Polrev( vector(100, i,i) ) ) time = 124ms ? for (i=1, 10^4, sum(i = 1, 100, (i+1) * 'x^i) ) time = 3,985ms @eprog Polynomials are always printed as \emph{univariate} polynomials over a commutative base ring, with monomials sorted by decreasing degree: \bprog ? (x+y+1)^2 %1 = x^2 + (2*y + 2)*x + (y^2 + 2*y + 1) @eprog\noindent (Univariate polynomial in \kbd{x} whose coefficients are polynomials in \kbd{y}.) See \secref{se:varsymb} for valid variable names, and a discussion of multivariate polynomial rings. Polynomials over noncommutative rings are not supported. \subsec{Power series (\typ{SER})}% \sidx{power series}\kbdsidx{t_SER}\label{se:series} Typing \kbd{O(X\pow $k$)}, where $k$ is an integer, yields an $X$-adic $0$ of accuracy~$k$, representing any power series in \kbd{X} whose valuation is $\geq k$. Of course, \kbd{X} can be replaced by any other variable name! To input a general nonzero power series, type in a polynomial or rational function (in \kbd{X}, say), and add \kbd{O(X\pow $k$)} to it. The discussion in the \typ{POL} section about variables remains valid; a constructor \tet{Ser} replaces \tet{Pol} and \tet{Polrev}. Power series over noncommutative rings are not supported. \misctitle{Caveat} Power series with inexact coefficients sometimes have a nonintuitive behavior: if $k$ significant terms are requested, an inexact zero is counted as significant, even if it is the coefficient of lowest degree. This means that useful higher order terms may be disregarded. If a series with a zero leading coefficient must be inverted, then as a desperation measure that coefficient is discarded, and a warning is issued: \bprog ? C = 0. + y + O(y^2); ? 1/C *** _/_: Warning: normalizing a series with 0 leading term. %2 = y^-1 + O(1) @eprog\noindent The last output could be construed as a bug since it is a priori impossible to deduce such a result from the input ($0.$ represents any sufficiently small real number). But it was thought more useful to try and go on with an approximate computation than to raise an early exception. If the series precision is insufficient, errors may occur (mostly division by $0$), which could have been avoided by a better global understanding of the computation: \bprog ? A = 1/(y + 0.); B = 1. + O(y); ? B * denominator(A) %2 = 0.E-38 + O(y) ? A/B *** at top-level: A/B *** ^-- *** _/_: impossible inverse in gdiv: 0.E-38 + O(y). ? A*B %4 = 1.0000000000000000000000000000000000000*y^-1 + O(y^0) @eprog \subsec{Rational functions (\typ{RFRAC})}% \sidx{rational function}\kbdsidx{t_RFRAC} As for fractions, all rational functions are automatically reduced to lowest terms. All that was said about fractions in \secref{se:FRAC} remains valid here. \subsec{Binary quadratic forms (\typ{QFB})}% \sidx{binary quadratic form}\kbdsidx{t_QFB} These are input using the function \kbd{Qfb}. For example, both \kbd{Qfb(1,2,3)} and \kbd{Qfb([1,2,3])} create the binary form $q = x^2+2xy+3y^2$. It is imaginary since its discriminant $2^2 - 4\times 3 = -8$ is negative. Although imaginary forms could be positive or negative definite, only positive definite forms are implemented. The discriminant can be retrieved via \kbd{q.disc}. The individual components are obtained via either of \bprog [a,b,c] = Vec(q); a = component(q,1); b = component(q,2); c = component(q,3); @eprog See also the function \kbd{qfbprimeform} which creates a prime form of given discriminant. \subsec{Row and column vectors (\typ{VEC} and \typ{COL})}% \sidx{row vector}\sidx{column vector}\kbdsidx{t_VEC}\kbdsidx{t_COL} To enter a row vector, type the components separated by commas ``\kbd{,}'', and enclosed between brackets ``\kbd{[}$\,$'' and ``$\,$\kbd{]}'', e.g.~\kbd{[1,2,3]}. To enter a column vector, type the vector horizontally, and add a tilde ``\til'' to transpose. \kbd{[ ]} yields the empty (row) vector. The function \tet{Vec} can be used to transform any object into a vector (see Chapter~3). The construction $[i..j]$, where $i \leq j$ are two integers returns the vector $[i, i+1,\dots, j-1, j]$ \bprog ? [1,2,3] %1 = [1, 2, 3] ? [-2..3] %2 = [-2, -1, 0, 1, 2, 3] @eprog Let the variable $v$ contain a (row or column) vector: \item \kbd{v[m]} refers to its $m$-th entry; you can assign any value to \kbd{v[m]}, i.e.~write something like $v[m]=\var{expr}$. \item \kbd{v[i..j]}, where $i \leq j$, returns the vector slice containing elements $v[i],\dots, v[j]$; you can \emph{not} assign a result to \kbd{v[i..j]}. \item \kbd{v[\pow i]} returns the vector whose $i$-th entry has been removed; you can \emph{not} assign a result to \kbd{v[\pow i]}. \noindent In the last two constructions \kbd{v[i..j]} and \kbd{v[\pow i]}, $i$ and $j$ are allowed to be negative integers, in which case, we start counting from the end of the vector: e.g., $-1$ is the index of the last element. \bprog ? v = [1,2,3,4]; ? v[2..4] %2 = [2, 3, 4] ? v[^3] %3 = [1, 2, 4] ? v[^-1] %3 = [1, 2, 3] ? v[-3..-1] %4 = [2, 3, 4] @eprog \misctitle{Remark} \tet{vector} is the standard constructor for row vectors whose $i$-th entry is given by a simple function of $i$; \tet{vectorv} is similar for column vectors: \bprog ? vector(10, i, i^2+1) %1 = [2, 5, 10, 17, 26, 37, 50, 65, 82, 101] @eprog The functions \tet{Vec} and \tet{Col} convert objects to row and column vectors respectively (as well as \tet{Vecrev} and \tet{Colrev}, which revert the indexing): \bprog ? T = poltchebi(5) \\ 5-th Chebyshev polynomial %1 = 16*x^5 - 20*x^3 + 5*x ? Vec(T) %2 = [16, 0, -20, 0, 5, 0] \\ coefficients of T ? Vecrev(T) %3 = [0, 5, 0, -20, 0, 16] \\ ... in reverse order @eprog \misctitle{Remark} For $v$ a \typ{VEC}, \typ{COL}, \typ{VECSMALL}, \typ{LIST} or \typ{MAT}, the alternative set-notations \bprog [g(x) | x <- v, f(x)] [x | x <- v, f(x)] [g(x) | x <- v] @eprog\noindent are available as shortcuts for \bprog apply(g, select(f, Vec(v))) select(f, Vec(v)) apply(g, Vec(v)) @eprog\noindent respectively, and may serve as \typ{VEC} constructors: \bprog ? [ p | p <- primes(10), isprime(p+2) ] %2 = [3, 5, 11, 17, 29] @eprog\noindent returns the primes $p$ (among the first 10 primes) such that $(p, p+2)$ is a twin pair; \bprog ? [ p^2 | p <- primes(10), p % 4 == 1 ] %3 = [25, 169, 289, 841] @eprog\noindent returns the squares of the primes congruent to $1$ modulo $4$, where $p$ runs among the first 10 primes. To iterate over more than one variable, you may separate clauses with \kbd{;} as in \bprog ? [ x+y | x <- [1..3]; y <- [1..2] ] %4 = [2, 3, 3, 4, 4, 5] ? [ [x,y] | x <- [1..4], isprime(x); y <- [2..5], y % 3 == 1 ] %5 = [[2, 4], [3, 4]] @eprog \subsec{Matrices (\typ{MAT})}% \sidx{matrix}\kbdsidx{t_MAT} To enter a matrix, type the components row by row, the components being separated by commas ``\kbd{,}'', the rows by semicolons ``\kbd{;}'', and everything enclosed in brackets ``\kbd{[}$\,$'' and ``$\,$\kbd{]}'', e.g. \kbd{[x,y; z,t; u,v]}. \kbd{[;]} yields an empty ($0 \times 0$) matrix. The function \tet{Mat} transforms any object into a matrix, and \tet{matrix} creates matrices whose $(i,j)$-th entry is described by a function $f(i,j)$: \bprog ? Mat(1) %1 = [1] ? matrix(2,2, i,j, 2*i+j) %2 = [3 4] [5 6] @eprog\noindent Matrix multiplication assumes that the base ring containing the matrix entries is commutative. \noindent Let the variable $M$ contain a matrix, and let $i,j,k,l$ denote four integers: \item \kbd{M[i,j]} refers to its $(i,j)$-th entry; you can assign any result to \kbd{M[i,j]}. \item \kbd{M[i,]} refers to its $i$-th row; you can assign a \typ{VEC} of the right dimension to \kbd{M[i,]}. \item \kbd{M[,j]} refers to its $j$-th column; you can assign a \typ{COL} of the right dimension to \kbd{M[,j]}. \noindent \emph{But} \kbd{M[i]} is meaningless and triggers an error. The ``range'' $i..j$ and ``caret'' \kbd{\pow}$c$ notations are available as for vectors; you can not \emph{assign} to any of these: \item \kbd{M[i..j, k..l]}, $i\leq j$, $k\leq l$, returns the submatrix built from the rows $i$ to $j$ and columns $k$ to $l$ of $M$. \item \kbd{M[i..j,]} returns the submatrix built from the rows $i$ to $j$ of $M$. \item \kbd{M[,i..j]} returns the submatrix built from the columns $i$ to $j$ of $M$. \item \kbd{M[i..j, \pow k]}, $i\leq j$, returns the submatrix built from the rows $i$ to $j$ and column $k$ removed. \item \kbd{M[\pow k,]} returns the submatrix with row $k$ removed. \item \kbd{M[,\pow k]} returns the submatrix with column $k$ removed. \noindent Finally, \item \kbd{M[i..j, k]} returns the \typ{COL} built from the $k$-th column (entries $i$ to $j$). \item \kbd{M[\pow i, k]} returns the \typ{COL} built from the $k$-th column (entry $i$ removed). \item \kbd{M[k, i..j]} returns the \typ{VEC} built from the $k$-th row (entries $i$ to $j$). \item \kbd{M[k, \pow i]} returns the \typ{VEC} built from the $k$-th row (entry $i$ removed). \bprog ? M = [1,2,3;4,5,6;7,8,9]; ? M[1..2, 2..3] %2 = [2 3] [5 6] ? M[1..2,] %3 = [1 2 3] [4 5 6] ? M[,2..3] %4 = [2 3] [5 6] [8 9] @eprog All this is recursive, so if \kbd{M} is a matrix of matrices of \dots, an expression such as \kbd{M[1,1][,3][4] = 1} is perfectly valid (and actually identical to \kbd{M[1,1][4,3] = 1}), assuming that all matrices along the way have compatible dimensions. \misctitle{Technical note (design flaw)} Matrices are internally represented as a vector of columns. All matrices with $0$ columns are thus represented by the same object (internally, an empty vector), and there is no way to distinguish between them. Thus it is not possible to create or represent matrices with zero columns and an actual nonzero number of rows. The empty matrix \kbd{[;]} is handled as though it had an arbitrary number of rows, exactly as many as needed for the current computation to make sense: \bprog ? [1,2,3; 4,5,6] * [;] %1 = [;] @eprog\noindent The empty matrix on the first line is understood as a $3\times 0$ matrix, and the result as a $2\times 0$ matrix. On the other hand, it is possible to create matrices with a given positive number of columns, each of which has zero rows, e.g.~using \kbd{Mat} as above or using the \kbd{matrix} function. Note that although the internal representation is essentially the same, a row vector of column vectors is \emph{not} a matrix; for example, multiplication will not work in the same way. It is easy to go from one representation to the other using \tet{Vec} / \tet{Mat}, though: \bprog ? [1,2,3;4,5,6] %1 = [1 2 3] [4 5 6] ? Vec(%) %2 = [[1, 4]~, [2, 5]~, [3, 6]~] ? Mat(%) %3 = [1 2 3] [4 5 6] @eprog \subsec{Lists (\typ{LIST})}% \sidx{list}\kbdsidx{t_LIST} Lists can be input directly, as in \kbd{List([1,2,3,4])}; but in most cases, one creates an empty list, then appends elements using \kbd{listput}: \bprog ? L = List(); listput(~L,1); listput(~L,2); ? L %2 = List([1, 2]) @eprog\noindent Note the \kbd{\til L}: this means that the function is called with a \emph{reference} to \kbd{L} and changes \kbd{L} in place. Elements can be accessed directly as with the vector types described above. \subsec{Strings (\typ{STR})}% \sidx{string}\sidx{character string}\kbdsidx{t_STR} To enter a string, enclose it between double quotes \kbd{"}, as in: \kbd{"this is a string"}. The function \kbd{Str} can be used to transform any object into a string. \subsec{Small vectors (\typ{VECSMALL})}% \kbdsidx{t_VECSMALL} This type codes in an efficient way vectors containing only small integers, such as permutations. Most \kbd{gp} functions will refuse to operate on these objects, notable exceptions being \kbd{vecsort} and conversion functions such as \kbd{Vec}, but you can retrieve entries and assign to them as for ordinary vectors. You can also convert back and forth between \typ{VECSMALL} and \typ{VEC} objects using \tet{Vec} and \tet{Vecsmall}. \bprog ? v = Vecsmall([2, 4, 6]) %1 = Vecsmall([2, 4, 6]) ? v[1] %2 = 2 ? v[1] = 3; v %3 = Vecsmall([3, 2, 3]) ? v[2..3] %4 = Vecsmall([2, 3]) ? v[^2] %5 = Vecsmall([3, 3]) ? Vec(v) %6 = [3, 2, 3] @eprog\noindent Allowed entries for a \typ{VECMALL} are signed integer $x$ such that $|x| < 2^{31}$ on a 32-bit architecture, resp.~$|x| < 2^{63}$ on a 64-bit architecture Assigning a larger integer to a \typ{VECSMALL} entry triggers an exception: \bprog ? v[1] = 2^63 *** at top-level: v[1]=2^63 *** ^---------- *** incorrect type in t_VECSMALL assignment (t_INT). @eprog \subsec{Functions (\typ{CLOSURE})}% \kbdsidx{t_CLOSURE} We will explain this at length in \secref{se:user_defined}. For the time being, suffice it to say that functions can be assigned to variables, as any other object, and the following equivalent basic forms are available to create new ones \bprog f = (x,y) -> x^2 + y^2 f(x,y) = x^2 + y^2 @eprog \subsec{Error contexts (\typ{ERROR})}% \kbdsidx{t_ERROR} An object of this type is created whenever an error occurs: it contains some information about the error and the error context. Usually, an appropriate error is printed immediately, the computation is aborted, and GP enters the ``break loop'': \bprog ? 1/0; 1 + 1 *** at top-level: 1/0;1+1 *** ^------ *** _/_: division by a noninvertible object *** Break loop: type 'break' to go back to the GP prompt @eprog\noindent Here the computation is aborted as soon as we try to evaluate $1/0$, and $1 + 1$ is never executed. Exceptions can be trapped using \tet{iferr}, however: we can evaluate some expression and either recover an ordinary result (no error occurred), or an exception (an error did occur). \bprog ? i = Mod(6,12); iferr(1/i, E, print(E)); 1 + 1 error("impossible inverse modulo: Mod(6, 12).") %1 = 2 @eprog\noindent One can ignore the exception, print it as above, or extract non trivial information from the error context: \bprog ? i = Mod(6,12); iferr(1/i, E, print(component(E,1))); Mod(6, 12) @eprog\noindent We can also rethrow the exception: \kbd{error(E)}. \subsec{Infinity (\typ{INFINITY})}% \kbdsidx{t_INFINITY} There are only two objects of this type \kbd{+oo} and \kbd{-oo}, representing $\pm\infty$. This type only contain only two elements \kbd{oo} and \kbd{-oo}, They are used in functions sur as \kbd{intnum} or \kbd{polrootsreal}, to encode infinite real intervals. These objects can only be negated and compared to real numbers (\typ{INT}, \typ{REAL}, \typ{FRAC}), but not included in any computation, i.e.~\kbd{1+oo} is an error, not \kbd{oo} again. \section{GP operators}\label{se:operators} \noindent Loosely speaking, an \idx{operator} is a function, usually attached to basic arithmetic operations, whose name contains only nonalphanumeric characters. For instance \kbd{+} or \kbd{-}, but also \kbd{=} or \kbd{+=}, or even \kbd{[ ]} (the selection operator). As all functions, operators take arguments, and return a value; \emph{assignment} operators also have side effects: besides returning a value, they change the value of some variable. Each operator has a fixed and unchangeable priority, which means that, in a given expression, the operation with the highest priority is performed first. Unless mentioned otherwise, operators at the same priority level are left-associative (performed from left to right), unless they are assignments, in which case they are right-associative. Anything enclosed between parenthesis is considered a complete subexpression, and is resolved recursively, independently of the surrounding context. For instance, \bprog a + b + c --> (a + b) + c \\@com left-associative a = b = c --> a = (b = c) \\@com right-associative @eprog\noindent Assuming that \var{op}$_1$, \var{op}$_2$, \var{op}$_3$ are binary operators with increasing priorities (think of \kbd{+}, \kbd{*}, \kbd{\pow}), $$ x~\var{op}_1~y~\var{op}_2~z~\var{op}_2~x~\var{op}_3~y $$ is equivalent to $$ x~\var{op}_1~((y~\var{op}_2~z)~\var{op}_2~ (x~\var{op}_3~y)).$$ GP contains many different operators, either unary (having only one argument) or binary, plus a few special selection operators. Unary operators are defined as either \emph{prefix} or \emph{postfix}, meaning that they respectively precede (\var{op}~$x$) and follow ($x$~\var{op}) their single argument. Some symbols are syntactically correct in both positions, like \kbd{!}, but then represent different operators: the \kbd{!} symbol represents the negation and factorial operators when in prefix and postfix position respectively. Binary operators all use the (infix) syntax $x$~\var{op}~$y$. Most operators are standard (\kbd{+}, \kbd{\%}, \kbd{=}), some are borrowed from the C language (\kbd{++}, \kbd{<<}), and a few are specific to GP (\kbd{\bs}, \kbd{\#}). Beware that some GP operators differ slightly from their C counterparts. For instance, GP's postfix \kbd{++} returns the \emph{new} value, like the prefix \kbd{++} of~C, and the binary shifts \kbd{<<}, \kbd{>>} have a priority which is different from (higher than) that of their C counterparts. When in doubt, just surround everything by parentheses; besides, your code will be more legible. \noindent Here is the list of available operators, ordered by decreasing \idx{priority}, binary and left-associative unless mentioned otherwise. An expression is an \tev{lvalue} if something can be assigned to it. (The name comes from left-value, to the left of a \kbd{=} operator; e.g. \kbd{x}, or \kbd{v[1]} are lvalues, but \kbd{x + 1} is not.) \def\point#1{\noindent\item #1\hfill\break\indent\strut} \point{Priority 14} % \kbd{:} as in \kbd{x:small}, is used to indicate to the GP2C compiler that the variable on the left-hand side always contains objects of the type specified on the right hand-side (here, a small integer) in order to produce more efficient or more readable C code. This is ignored by GP. % \point{Priority 13} \kbd{( )} is the function call operator. If $f$ is a closure and \var{args} is a comma-separated list of arguments (possibly empty), $f\kbd{(\var{args})}$ evaluates $f$ on those arguments. \point{Priority 12} % \kbd{++} and \kbd{--} (unary, postfix): if $x$ is an \tet{lvalue}, \kbd{$x$++} assigns the value $x+1$ to $x$, then returns the new value of $x$. This corresponds to the C statement \kbd{++$x$}: there is no prefix \kbd{++} operator in GP. \kbd{$x$--} does the same with $x-1$. These operators are not associative, i.e. \kbd{x++++} is invalid, since \kbd{x++} is not an lvalue. \point{Priority 11} % \kbd{.}\var{member} (unary, postfix): \kbd{$x$.\var{member}} extracts \var{member} from structure $x$ (see~\secref{se:member}). \kbd{[ ]} is the selection operator. \kbd{$x$[$i$]} returns the $i$-th component of vector $x$; \kbd{$x$[$i$,$j$]}, \kbd{$x$[,$j$]} and \kbd{$x$[$i$,]} respectively return the entry of coordinates $(i,j)$, the $j$-th column, and the $i$-th row of matrix $x$. If the assignment operator (\kbd{=}) immediately follows a sequence of selections, it assigns its right hand side to the selected component. E.g \kbd{x[1][1] = 0} is valid; but beware that \kbd{(x[1])[1] = 0} is not (because the parentheses force the complete evaluation of \kbd{x[1]}, and the result is not modifiable). \point{Priority 10} % \kbd{'} (unary, postfix): derivative with respect to the main variable. If $f$ is a function (\typ{CLOSURE}), $f'$ is allowed and defines a new function, which will perform \idx{numerical derivation} when evaluated at a scalar $x$; this is defined as $(f(x+\varepsilon) - f(x-\varepsilon)) / 2\varepsilon$ for a suitably small epsilon depending on current precision. \bprog ? (x^2 + y*x + y^2)' \\@com derive with respect to main variable \kbd{x} %1 = 2*x + y ? SIN = cos' %2 = cos' ? SIN(Pi/6) \\@com numerical derivation %3 = -0.5000000000000000000000000000 ? cos'(Pi/6) \\@com works directly: no need for intermediate \kbd{SIN} %4 = -0.5000000000000000000000000000 @eprog \strut\kbd{\til} (unary, postfix): vector/matrix transpose. \kbd{!} (unary, postfix): factorial. $x\kbd{!}=x(x-1)\cdots 1$. \kbd{\#} (unary, postfix): primorial. For a non-negative integer $n$, $n\#$ is the product of all prime numbers less than or equal to $n$. \point{Priority 9} % \kbd{\#} (unary, prefix): cardinality; \kbd{\#$x$} returns \kbd{length($x$)}. \kbd{!} (unary, prefix): logical \var{not}. \kbd{!$x$} returns $1$ if $x$ is equal to $0$ (specifically, if \kbd{gequal0($x$)==1}), and $0$ otherwise. \point{Priority 8} % \kbd{\pow}: powering. This operator is right associative: \kbd{2 \pow 3\pow 4} is understood as \kbd{2 \pow (3\pow 4)}. \point{Priority 7} % \kbd{+}, \kbd{-} (unary, prefix): \kbd{-} toggles the sign of its argument, \kbd{+} has no effect whatsoever. \point{Priority 6} % \kbd{*}: multiplication. \kbd{/}: exact division (\kbd{3/2} yields $3/2$, not $1.5$). \kbd{\bs}, \kbd{\%}: Euclidean quotient and remainder, i.e.~if $x = qy + r$, then $\kbd{x \b{ } y} = q$, $\kbd{x\%y} = r$. If $x$ and $y$ are scalars, then $q$ is an integer and $r$ satisfies $0\le r < |y|$; if $x$ and $y$ are polynomials, then $q$ and $r$ are polynomials such that $\deg r< \deg y$ and the leading terms of $r$ and $x$ have the same sign. \kbd{\bs/}: rounded Euclidean quotient for integers (rounded towards $+\infty$ when the exact quotient would be a half-integer). \kbd{<<}, \kbd{>>}: left and right binary shift. By definition, \kbd{x<0$, and $\kbd{truncate}(x 2^{-n})$ otherwise. Right shift is defined by \kbd{x>>n}$~=~$\kbd{x<<(-n)}. \point{Priority 5} % \kbd{+}, \kbd{-}: addition/subtraction. \point{Priority 4} % \kbd{<}, \kbd{>}, \kbd{<=}, \kbd{>=}: the usual comparison operators, returning 1 for \kbd{true} and 0 for \kbd{false}. For instance, \kbd{x<=1} returns $1$ if $x\le 1$ and $0$ otherwise. \kbd{<>}, \kbd{!=}: test for (exact) inequality. \kbd{==}: test for (exact) equality. \kbd{===}: test whether two objects are identical component-wise. This is stricter than \kbd{==}: for instance, the integer 0, a 0 polynomial or a vector with 0 entries, are all tested equal by \kbd{==}, but they are not identical. \point{Priority 3} % \kbd{\&\&}: logical \var{and}. \kbd{||}: logical (inclusive) \var{or}. Any sequence of logical \var{or} and \var{and} operations is evaluated from left to right, and aborted as soon as the final truth value is known. Thus, for instance, \bprog x == 0 || test(1/x) @eprog\noindent will never produce an error since \kbd{test(1/x)} is not even evaluated when the first test is true (hence the final truth value is true). Similarly \bprog type(p) == "t_INT" && isprime(p) @eprog\noindent does not evaluate \kbd{isprime(p)} if \kbd{p} is not an integer. \point{Priority 2} % \kbd{=} (assignment, \var{lvalue} \kbd{=} \var{expr}). The result of \kbd{x~=~$y$} is the value of the expression~$y$, which is also assigned to the variable~\kbd{x}. This assignment operator is right-associative. This is \emph{not} the equality test operator; a statement like \kbd{x~=~1} is always true (i.e.~nonzero), and sets \kbd{x} to~1; the equality test would be \kbd{x == 1}. The right hand side of the assignment operator is evaluated before the left hand side. It is crucial that the left hand-side be an \var{lvalue} there, it avoids ambiguities in expressions like \kbd{1 + x = 1}. The latter evaluates as \kbd{1 + (x = 1)}, not as \kbd{(1 + x) = 1}, even though the priority of \kbd{=} is lower than the priority of \kbd{+}: \kbd{1 + x} is not an lvalue. If the expression cannot be parsed in a way where the left hand side is an lvalue, raise an error. \bprog ? x + 1 = 1 *** syntax error, unexpected '=', expecting $end or ';': x+1=1 *** ^-- @eprog\noindent Assignment to all variables is a deep copy: after $x = y$, modifying a component of $y$ will \emph{not} change $x$. To globals it is a full copy to the heap. Space used by local objects in local variables is released when they go out of scope or when the value changes in local scope. Assigning a value to a vector or matrix entry allocates room for that entry only (on the heap). \leavevmode \kbd{\var{op}=}, where \var{op} is any binary operator among \kbd{+}, \kbd{-}, \kbd{*}, \kbd{\%}, \kbd{/}, \kbd{\bs}, \kbd{\bs/}, \kbd{<<}, or \kbd{>>} (composed assignment \var{lvalue} \var{op}\kbd{=} \var{expr}). The expression \kbd{x~\var{op}=~$y$} assigns $(\kbd{x}~\var{op}~y)$ to~\kbd{x}, and returns the new value of~\kbd{x}. The result is \emph{not} an \tev{lvalue}; thus \bprog (x += 2) = 3 @eprog\noindent is invalid. These assignment operators are right-associative: \bprog ? x = 'x; x += x *= 2 %1 = 3*x @eprog \point{Priority 1} \kbd{->} (function definition): \kbd{(\var{vars})->\var{expr}} returns a function object, of type \typ{CLOSURE}. \misctitle{Remark} Use the \var{op}\kbd{=} operators as often as possible since they make complex assignments more legible. Compare \bprog v[i+j-1] = v[i+j-1] + 1 --> v[i+j-1]++ M[i,i+j] = M[i,i+j] * 2 --> M[i,i+j] *= 2 @eprog \misctitle{Remark about efficiency} the operators \kbd{++} and \kbd{--} are usually a little more efficient than their expended counterpart: \bprog ? N = 10^7; ? i = 0; for(k = 1, N, i=i+1) time = 949 ms. ? i = 0; for(k = 1, N, i++) time = 933 ms. @eprog\noindent On the other hand, this is not the case for the \var{op}\kbd{=} operators which may even be a little less efficient: \bprog ? i = 0; for(k = 1, N, i=i+10) time = 949 ms. ? i = 0; for(k = 1, N, i+=10) time = 1,064 ms. @eprog \section{Variables and symbolic expressions}\sidx{variable}\label{se:varsymb} In this section we use \emph{variable} in the standard mathematical sense, symbols representing algebraically independent elements used to build rings of polynomials and power series, and explain the all-important concept of \emph{variable priority}. In the next \secref{se:scope}, we shall no longer consider only free variables, but adopt the viewpoint of computer programming and assign values to these symbols: (bound) variables are names attached to values in a given scope. \subsec{Variable names}\label{se:varname} A valid name starts with a letter, followed by any number of keyword characters: \kbd{\_} or alphanumeric characters ([\kbd{A-Za-z0-9}]). As a rule, the built-in function names are reserved and cannot be used; see the list with \b{c}, including the constants \kbd{Pi}, \kbd{Euler}, \kbd{Catalan}, $\kbd{I}=\sqrt{-1}$ and $\kbd{oo} = \infty$. Beware in particular of \kbd{gamma}, \kbd{omega}, \kbd{theta}, \kbd{sum} or \kbd{O}, none of which are free to use. (We shall see in~\secref{se:scope} how this rule can be circumvented. It \emph{is} possible to name a \var{lexical} variable \kbd{gamma}.) GP names are case sensitive. For instance, the symbol \kbd{i} is perfectly safe to use, and will not be mistaken for $\kbd{I} = \sqrt{-1}$; analogously, \kbd{o} is not synonymous to \kbd{O}. In GP you can use up to 16383 variable names (up to 65535 on 64-bit machines). If you ever need thousands of variables and this becomes a serious limitation, you should probably be using vectors instead: e.g. instead of variables \kbd{X1}, \kbd{X2}, \kbd{X3}, \dots, you might equally well store their values in \kbd{X[1]}, \kbd{X[2]}, \kbd{X[3]}, \dots \subsec{Variables and polynomials}\sidx{free variable} The quote operator \kbd{'t} registers a new \emph{free variable} with the interpreter, which will be written as \kbd{t}, and evaluates to a monomial of degree $1$ in the said variable. \misctitle{Caveat} For reasons of backward compatibility, there is no such thing as an ``unbound'' (uninitialized) variable in GP. If you use a valid variable name in an expression, \kbd{t} say, for the first time \emph{before} assigning a value into it, it is interpreted as \kbd{'t} rather than raising an exception. One should not rely on this feature in serious programs, which would otherwise break if some unexpected assignment (e.g. \kbd{t = 1}) occurs: use \kbd{'t} directly or \kbd{t = 't} first, then \kbd{t}. A statement like \kbd{t = 't} in effect restores \kbd{t} as a free variable. % \bprog ? t = 't; t^2 + 1 %1 = t^2 + 1 ? t = 2; t^2 + 1 %2 = 5 ? %1 %3 = t^2 + 1 ? eval(%1) %4 = 5 @eprog\noindent In the above, we initialize \kbd{t} to a monomial, then bind it to $2$. Assigning a value to a polynomial variable does not affect previous expressions involving it; to take into account the new variable's value, one must force a new evaluation, using the function \kbd{eval} (see \secref{se:eval}). \misctitle{Caveat2} The use of an explicit quote operator avoids the following kind of problems: \bprog ? t = 't; p = t^2 + 1; subst(p, t, 2) %1 = 5 ? t = 2; ? subst(p, t, 3) \\@com \kbd{t} is no longer free: it evaluates to 2 *** at top-level: subst(p,t,3) *** ^---- *** variable name expected. ? subst(p, 't, 3) \\ OK %3 = 10 @eprog \subsec{Variable priorities, multivariate objects}\sidx{variable (priority)}\label{se:priority} A multivariate polynomial in PARI is just a polynomial (in one variable), whose coefficients are themselves polynomials, arbitrary but for the fact that they do not involve the main variable. (PARI currently has no sparse representation for polynomials, listing only nonzero monomials.) All computations are then done formally on the coefficients as if the polynomial was univariate. This is not symmetrical. So if I enter \kbd{'x + 'y} in a clean session, what happens? This is understood as $$ x^1 + (y^1 + 0*y^0)*x^0 \in (\Z[y])[x] $$ but how do we know that $x$ is ``more important'' than $y$ ? Why not $y^1 + x*y^0$, which is the same mathematical entity after all? The answer is that variables are ordered implicitly by the interpreter: when a new identifier (e.g~$x$, or $y$ as above) is input, the corresponding variable is registered as having a strictly lower priority than any variable in use at this point\footnote{*}{This is not strictly true: the variables $x$ and $y$ are predefined, and satisfy $x > y$. Variables of higher priority than $x$ can be created using \tet{varhigher}.}% . To see the ordering used by \kbd{gp} at any given time, type \kbd{variable()}.\kbdsidx{variable} Given such an ordering, multivariate polynomials are stored so that the variable with the highest priority is the main variable. And so on, recursively, until all variables are exhausted. A different storage pattern (which could only be obtained via \kbd{libpari} programming and low-level constructors) would produce an invalid object, and eventually a disaster. In any case, if you are working with expressions involving several variables and want to have them ordered in a specific manner in the internal representation just described, the simplest is just to write down the variables one after the other under \kbd{gp} before starting any real computations. You may also define variables from your \tet{gprc} to have a consistent ordering of common variable names in all your \kbd{gp} sessions, e.g read in a file \kbd{variables.gp} containing \bprog 'x; 'y; 'z; 't; 'a; @eprog\noindent There is no way to change the priority of existing variables, but you may always create new ones with well-defined priorities using \kbd{varhigher} or \kbd{varlower}. \misctitle{Important note} PARI allows Euclidean division of multivariate polynomials, but assumes that the computation takes place in the fraction field of the coefficient ring (if it is not an integral domain, the result will a priori not make sense). This can become tricky. For instance assume $x$ has highest priority, then $y$: \bprog ? x % y %1 = 0 ? y % x %2 = y \\@com these two take place in $\Q(y)[x]$ ? x * Mod(1,y) %3 = Mod(1, y)*x \\@com in $(\Q(y)/y\Q(y))[x] \sim \Q[x]$ ? Mod(x,y) %4 = 0 @eprog \noindent In the last example, the division by $y$ takes place in $\Q(y)[x]$, hence the \kbd{Mod} object is a coset in $(\Q(y)[x]) / (y\Q(y)[x])$, which is the null ring since $y$ is invertible! So be very wary of variable ordering when your computations involve implicit divisions and many variables. This also affects functions like \tet{numerator}/\tet{denominator} or \tet{content}: \bprog ? denominator(x / y) %1 = 1 ? denominator(y / x) %2 = x ? content(x / y) %3 = 1/y ? content(y / x) %4 = y ? content(2 / x) %5 = 2 @eprog \noindent Can you see why? Hint: $x/y = (1/y) * x$ is in $\Q(y)[x]$ and denominator is taken with respect to $\Q(y)(x)$; $y/x = (y*x^0) / x$ is in $\Q(y)(x)$ so $y$ is invertible in the coefficient ring. On the other hand, $2/x$ involves a single variable and the coefficient ring is simply $\Z$. These problems arise because the variable ordering defines an \emph{implicit} variable with respect to which division takes place. This is the price to pay to allow \kbd{\%} and \kbd{/} operators on polynomials instead of requiring a more cumbersome \kbd{divrem($x$, $y$, \var{var})} (which also exists). Unfortunately, in some functions like \tet{content} and \tet{denominator}, there is no way to set explicitly a main variable like in \tet{divrem} and remove the dependence on implicit orderings. This will hopefully be corrected in future versions. \subsec{Multivariate power series} Just like multivariate polynomials, power series are fundamentally single-variable objects. It is awkward to handle many variables at once, since PARI's implementation cannot handle multivariate error terms like $O(x^i y^j)$. (It can handle the polynomial $O(y^j) \times x^i$ which is a very different thing, see below.) The basic assumption in our model is that if variable $x$ has higher priority than $y$, then $y$ does not depend on $x$: setting $y$ to a function of $x$ after some computations with bivariate power series does not make sense a priori. This is because implicit constants in expressions like $O(x^i)$ depend on $y$ (whereas in $O(y^j)$ they can not depend on $x$). For instance \bprog ? O(x) * y %1 = O(x) ? O(y) * x %2 = O(y)*x @eprog\noindent Here is a more involved example: \bprog ? A = 1/x^2 + 1 + O(x); B = 1/x + 1 + O(x^3); ? subst(z*A, z, B) %2 = x^-3 + x^-2 + x^-1 + 1 + O(x) ? B * A %3 = x^-3 + x^-2 + x^-1 + O(1) ? z * A %4 = z*x^-2 + z + O(x) @eprog\noindent The discrepancy between \kbd{\%2} and \kbd{\%3} is surprising. Why does \kbd{\%2} contain a spurious constant term, which cannot be deduced from the input? Well, we ignored the rule that forbids to substitute an expression involving high-priority variables to a low-priority variable. The result \kbd{\%4} is correct according to our rules since the implicit constant in $O(x)$ may depend on $z$. It is obviously wrong if $z$ is allowed to have negative valuation in $x$. Of course, the correct error term should be $O(xz)$, but this is not possible in PARI. \section{Variables and Scope}\sidx{variable scope}\label{se:scope} This section is rather technical, and strives to explain potentially confusing concepts. Skip to the last subsection for practical advice, if the next discussion does not make sense to you. After learning about user functions, study the example in \secref{se:bewarescope} then come back. \misctitle{Definitions} % rather not make it a section to allow for ??my A \emph{scope} is an enclosing context where names and values are attached. A user's function body, the body of a loop, an individual command line, all define scopes; the whole program defines the \emph{global} scope. The argument of \tet{eval} is evaluated in the enclosing scope. Variables are bound to values within a given scope. This is traditionally implemented in two different ways: \item\sidx{lexical scoping} lexical (or static) scoping: the binding makes sense within a given block of program text. The value is private to the block and may not be accessed from outside. Where to find the value is determined at compile time. \item\sidx{dynamic scoping} dynamic scoping: introducing a local variable, say \kbd{x}, pushes a new value on a stack attached to the name \kbd{x} (possibly empty at this point), which is popped out when the control flow leaves the scope. Evaluating \kbd{x} in any context, possibly outside of the given block, always yields the top value on this dynamic stack. GP implements both lexical and dynamic scoping, using the keywords% \footnote{*}{The names are borrowed from the \tet{Perl} scripting language.} \tet{my} (lexical) and \tet{local} (dynamic): \bprog x = 0; f() = x g() = my(x = 1); f() h() = local(x = 1); f() @eprog\noindent The function \kbd{g} returns 0 since the global \kbd{x} binding is unaffected by the introduction of a private variable of the same name in \kbd{g}. On the other hand, \kbd{h} returns 1; when it calls \kbd{f()}, the binding stack for the \kbd{x} identifier contains two items: the global binding to 0, and the binding to 1 introduced in \kbd{h}, which is still present on the stack since the control flow has not left \kbd{h} yet. The rule mentionned in the previous section about built-in function names being reserved does \emph{not} apply to lexically scoped variables. Those may temporarily shadow an existing function name: \bprog my(gamma = 0) ; ... @eprog Without the \kbd{my}, this would be invalid since \kbd{gamma} is the $\Gamma$ function. \subsec{Scoping rules} Named parameters in a function definition, as well as all loop indices\footnote{**}{ More generally, in all iterative constructs which use a variable name (\kbd{for}, \kbd{prod}, \kbd{sum}, \kbd{vector}, \kbd{matrix}, \kbd{plot}, etc.) the given variable is lexically scoped to the construct's body.}, have lexical scope within the function body and the loop body respectively. \bprog p = 0; forprime (p = 2, 11, print(p)); p \\ prints 0 at the end x = 0; f(x) = x++; f(1) \\ returns 2, and leave global x unaffected (= 0) @eprog\noindent If you exit the loop prematurely, e.g.~using the \kbd{break} statement, you must save the loop index in another variable since its value prior the loop will be restored upon exit. For instance \bprog for(i = 1, n, if (ok(i), break); ); if (i > n, return(failure)); @eprog\noindent is incorrect, since the value of $i$ tested by the $(i > n)$ is quite unrelated to the loop index. One ugly workaround is \bprog for(i = 1, n, if (ok(i), isave = i; break); ); if (isave > n, return(failure)); @eprog\noindent But it is usually more natural to wrap the loop in a user function and use \kbd{return} instead of \kbd{break}: \bprog try() = { for(i = 1, n, if (ok(i), return (i)); ); 0 \\ failure } @eprog A list of variables can be lexically or dynamically scoped (to the block between the declaration and the end of the innermost enclosing scope) using a \kbd{my} or \kbd{local} declaration: \bprog for (i = 1, 10, my(x, y, z, i2 = i^2); \\ temps needed within the loop body ... ) @eprog\noindent Note how the declaration can include (optional) initial values, \kbd{i2 = i\pow 2} in the above. Variables for which no explicit default value is given in the declaration are initialized to $0$. It would be more natural to initialize them to free variables, but this would break backward compatibility. To obtain this behavior, you may explicitly use the quoting operator: \bprog my(x = 'x, y = 'y, z = 'z); @eprog\noindent A more complicated example: \bprog for (i = 1, 3, print("main loop"); my(x = i); \\ local to the outermost loop for (j = 1, 3, my (y = x^2); \\ local to the innermost loop print (y + y^2); x++; ) ) @eprog\noindent When we leave the loops, the values of \kbd{x}, \kbd{y}, \kbd{i}, \kbd{j} are the same as before they were started. Note that \tet{eval} is evaluated in the given scope, and can access values of lexical variables: \bprog ? x = 1; ? my(x = 0); eval("x") %2 = 0 \\@com we see the local \kbd{x} scoped to this command line, not the global one @eprog Variables dynamically scoped using \kbd{local} should more appropriately be called \emph{temporary values} since they are in fact local to the function declaring them \emph{and} any subroutine called from within. In practice, you almost certainly want true private variables, hence should use almost exclusively \kbd{my}. We strongly recommended to explicitly scope (lexically) all variables to the smallest possible block. Should you forget this, in expressions involving such ``rogue'' variables, the value used will be the one which happens to be on top of the value stack at the time of the call; which depends on the whole calling context in a nontrivial way. This is in general \emph{not} what you want. \section{User defined functions}\sidx{user defined functions} \label{se:user_defined} User-defined functions are ordinary GP objects, bound to variables just like any other object. Those variables are subject to scoping rules as any other: while you can define all your functions in global scope, it is usually possible and cleaner to lexically scope your private helper functions to the block of text where they will be needed. Whenever gp meets a construction of the form \kbd{expr(\var{argument list})} and the expression \kbd{expr} evaluates to a function (an object of type \typ{CLOSURE}), the function is called with the proper arguments. For instance, constructions like \kbd{funcs[i](x)} are perfectly valid, assuming \kbd{funcs} is an array of functions. As regards argument passing conventions, GP functions support both \item \idx{call by value}: the function operates on a copy of a variable, changes made to the argument in the function do not affect the original variable; \item and \idx{call by reference}: the function receives a reference to the variable and original data is affected. \subsec{Defining a function}\label{se:userfundef} A user function is defined as follows: \kbd{(\var{list of formal variables}) -> \var{seq}}. \noindent The list of formal variables is a comma-separated list of \emph{distinct} variable names and allowed to be empty. It there is a single formal variable, the parentheses are optional. This list corresponds to the list of parameters you will supply to your function when calling it. By default, GP functions use call by value to pass arguments; a variable name may be prefixed by a tilde \kbd{\til} to use instead a call by reference. In most cases you want to assign a function to a variable immediately, as in \bprog R = (x,y) -> sqrt( x^2+y^2 ); sq = x -> x^2; \\@com or equivalently \kbd{(x) -> x\pow2} @eprog\noindent but it is quite possible to define short-lived anonymous functions. The trailing semicolon is not part of the definition, but as usual prevents \kbd{gp} from printing the result of the evaluation, i.e. the function object. The construction \kbd{f(\var{list of formal variables}) = \var{seq}} \noindent is available as an alias for \kbd{f = (\var{list of formal variables}) -> \var{seq}} \noindent Using that syntax, it is not possible to define anonymous functions (obviously), and the above two examples become: \bprog R(x,y) = sqrt( x^2+y^2 ); sq(x) = x^2; @eprog\noindent The semicolon serves the same purpose as above: preventing the printing of the resulting function object; compare \bprog ? sq(x) = x^2; \\@com no output ? sq(x) = x^2 \\@com print the result: a function object %2 = (x)->x^2 @eprog\noindent Of course, the sequence \var{seq} can be arbitrarily complicated, in which case it will look better written on consecutive lines, with properly scoped variables: \bprog { f(x0, x1, @dots) = my(t0, t1, @dots); \\@com variables lexically scoped to the function body @dots } @eprog \noindent Note that the following variant would also work: \bprog f(x0, x1, @dots) = { my(t0, t1, @dots); \\@com variables lexically scoped to the function body @dots } @eprog \noindent (the first newline is disregarded due to the preceding \kbd{=} sign, and the others because of the enclosing braces). The \tet{my} statements can actually occur anywhere within the function body, scoping the variables to more restricted blocks than the whole function body. Formal parameters are lexically scoped to the function body. It is not allowed to use the same variable name for different parameters of your function: \bprog ? f(x,x) = 1 *** variable declared twice: f(x,x)=1 *** ^---- @eprog \misctitle{Finishing touch} You can add a specific help message for your function using \kbd{addhelp}, but the online help system already handles it. By default \kbd{?\var{name}} will print the definition of the function \var{name}: the list of arguments, as well as their default values, the text of \var{seq} as you input it. Just as \b{c} prints the list of all built-in commands, \b{u} outputs the list of all user-defined functions. \subsec{Call by value, call by reference} By default, arguments are passed by value, not as variables: modifying a function's argument in the function body is allowed, but does not modify its value in the calling scope. In fact, a \emph{copy} of the actual parameter is assigned to the formal parameter when the function is called. (This is not litterally true: a form of copy-on-write is implemented so an object is not duplicated unless modified in the function.) If an argument is prefixed by a tilde \kbd{\til} in the function declaration \emph{and} the call, it is passed by reference. (If either the declaration or the call is missing a tilde, we revert to a call by value.) \bprog ? x = [1]; ? f(v) = v[1]++; ? F(~v) = v[1]++; ? f(x) %4 = 2 ? x \\ unchanged %5 = [1] ? F(~x) %6 = 2 ? x \\ incremented %7 = [2] ? F(x) \\ forgot the ~: call by value %8 = 3 ? x \\ => contents of x did not change %9 = [2] ? f(~x) \\ adding a ~ in call, missing in declaration %10 = 3 ? x \\ => call by value %11 = [2] @eprog \misctitle{Caveat} In GP, a call by reference means that the function accesses the value and may change the original variable content, but only if it is a container type (a vector, list or matrix), as shown above with the vector $x$. It will not alter its value in other cases ! \bprog ? v = 1 \\ not a container ? F(~v) = v++ ? F(~v) %3 = 2 ? v \\ components of v could be altered, not v itself %4 = 1 @eprog \subsec{Functions taking an unlimited number of arguments} A function taking an unlimited number of arguments is called \emph{variadic}. To create such a function, use the syntax \kbd{(\var{list of formal variables}, \var{var}[..]) -> \var{seq}} \noindent The parameter \var{var} is replaced by a vector containing all the remaining arguments. The name may not be prefixed by a tilde to (absurdly) indicate a call by reference. \bprog ? f(c[..]) = sum(i=1,#c,c[i]); ? f(1,2,3) %1 = 6 ? sep(s,v[..]) = for(i=1,#v-1,print1(v[i],s)); if (#v, print(v[#v])); ? sep(":", 1, 2, 3) 1:2:3 @eprog \subsec{Backward compatibility (lexical scope)} Lexically scoped variables were introduced in version~2.4.2. Before that, the formal parameters were dynamically scoped. If your script depends on this behavior, you may use the following trick: replace the initial \kbd{f(x) =} \ by \bprog f(x_orig) = local(x = x_orig) @eprog \subsec{Backward compatibility (disjoint namespaces)} Before version 2.4.2, variables and functions lived in disjoint namespaces and it was not possible to have a variable and a function share the same name. Hence the need for a \kbd{kill} function allowing to reuse symbols. This is no longer the case. There is now no distinction between variable and function names: we have PARI objects (functions of type \typ{CLOSURE}, or more mundane mathematical entities, like \typ{INT}, etc.) and variables bound to them. There is nothing wrong with the following sequence of assignments: \bprog ? f = 1 \\@com assigns the integer 1 to \kbd{f} %1 = 1; ? f() = 1 \\@com a function with a constant value %2 = ()->1 ? f = x^2 \\@com \kbd{f} now holds a polynomial %3 = x^2 ? f(x) = x^2 \\@com \dots and now a polynomial function %4 = (x)->x^2 ? g(fun) = fun(Pi);\\@com a function taking a function as argument ? g(cos) %6 = -1.000000000000000000000000000 @eprog\noindent Previously used names can be recycled as above: you are just redefining the variable. The previous definition is lost of course. \misctitle{Important technical note} Built-in functions are a special case since they are read-only (you cannot overwrite their default meaning), and they use features not available to user functions, in particular pointer arguments. In the present version \vers{}, it is possible to assign a built-in function to a variable, or to use a built-in function name to create an anonymous function, but some special argument combinations may not be available: \bprog ? issquare(9, &e) %1 = 1 ? e %2 = 3 ? g = issquare; ? g(9) %4 = 1 ? g(9, &e) \\@com pointers are not implemented for user functions *** unexpected &: g(9,&e) *** ^--- @eprog \subsec{Function call, Default arguments} You may now call your function, as in \kbd{f(1,2)}, supplying values for the formal variables. The number of parameters actually supplied may be \emph{less} than the number of formal variables in the function definition. An uninitialized formal variable is given an implicit default value of (the integer)~0, i.e. after the definition \bprog f(x, y) = ... @eprog\noindent you may call \kbd{f(1, 2)}, supplying values for the two formal parameters, or for example \settabs\+\indent&xxxxxxxxx& equivalent to xxxx &\cr \+& \kbd{f(2)} & equivalent to &\kbd{f(2,0)},\cr \+& \kbd{f()} & & \kbd{f(0,0)},\cr \+& \kbd{f(,3)} & &\kbd{f(0,3)}. (``Empty argument'' trick)\cr \noindent This \emph{implicit} default value of $0$, is actually deprecated and setting \bprog default(strictargs, 1) @eprog\noindent allows to disable it (see \secref{se:def,strictargs}).\kbdsidx{strictargs} The recommended practice is to \emph{explicitly} set a default value: in the function definition, you can append \kbd{=}\var{expr} to a formal parameter, to give that variable a default value. The expression gets evaluated the moment the function is called, and may involve the preceding function parameters: a default value for $x_i$ may involve $x_j$ for $j < i$. For instance, after \bprog f(x = 1, y = 2, z = y+1) = .... @eprog\noindent typing in \kbd{f(3,4)} would give you \kbd{f(3,4,5)}. In the rare case when you want to set some far away argument, and leave the defaults in between as they stand, use the ``empty argument'' trick: \kbd{f(6,,1)} would yield \kbd{f(6,2,1)}. Of course, \kbd{f()} by itself yields \kbd{f(1,2,3)} as was to be expected. In short, the argument list is filled with user supplied values, in order. A comma or closing parenthesis, where a value should have been, signals we must use a default value. When no input arguments are left, the defaults are used instead to fill in remaining formal parameters. A final example: \bprog f(x, y=2, z=3) = print(x, ":", y, ":", z); @eprog \noindent defines a function which prints its arguments (at most three of them), separated by colons. \bprog ? f(6,7) 6:7:3 ? f(,5) 0:5:3 ? f() 0:2:3 @eprog\noindent If \kbd{strictargs} is set (recommended), $x$ is now a mandatory argument, and the above becomes: \bprog ? default(strictargs,1) ? f(6,7) 6:7:3 ? f(,5) *** at top-level: f(,5) *** ^----- *** in function f: x,y=2,z=3 *** ^--------- *** missing mandatory argument 'x' in user function. @eprog \misctitle{Example} We conclude with an amusing example, intended to illustrate both user-defined functions and the power of the \kbd{sumalt} function. Although the \idx{Riemann zeta-function} is included (as \kbd{zeta}) among the standard functions, let us assume that we want to check other implementations. Since we are highly interested in the critical strip, we use the classical formula $$ (2^{1-s} - 1)\zeta(s) = \sum_{n\geq 1} (-1)^n n^{-s}, \qquad\Re s > 0.$$ The implementation is obvious:\sidx{zeta function} \bprog ZETA(s) = sumalt(n=1, (-1)^n*n^(-s)) / (2^(1-s) - 1) @eprog \noindent Note that \kbd{n} is automatically lexically scoped to the \kbd{sumalt} ``loop'', so that it is unnecessary to add a \kbd{my(n)} declaration to the function body. Surprisingly, this gives very good accuracy in a larger region than expected: \bprog ? check = z -> ZETA(z) / zeta(z); ? check(2) %1 = 1.000000000000000000000000000 ? check(200) %2 = 1.000000000000000000000000000 ? check(0) %3 = 0.9999999999999999999999999994 ? check(-5) %4 = 1.00000000000000007549266557 ? check(-11) %5 = 0.9999752641047824902660847745 ? check(1/2+14.134*I) \\@com very close to a nontrivial zero %6 = 1.000000000000000000003747432 + 7.62329066 E-21*I ? check(-1+10*I) %7 = 1.000000000000000000000002511 + 2.989950968 E-24*I @eprog\noindent Now wait a minute; not only are we summing a series which is certainly no longer alternating (it has complex coefficients), but we are also way outside of the region of convergence, and still get decent results! No programming mistake this time: \kbd{sumalt} is a ``magic'' function\footnote{*}{\kbd{sumalt} is heuristic, but its use can be rigorously justified for a given function, in particular our $\zeta(s)$ formula. Indeed, Peter Borwein (\emph{An efficient algorithm for the Riemann zeta function}, CMS Conf.~Proc.~{\bf 27} (2000), pp.~29--34) proved that the formula used in \kbd{sumalt} with $n$ terms computes $(1-2^{1-s})\zeta(s)$ with a relative error of the order of $(3+\sqrt{8})^{-n}|\Gamma(s)|^{-1}$.}, providing very good convergence acceleration; in effect, we are computing the analytic continuation of our original function. To convince ourselves that \kbd{sumalt} is a nontrivial implementation, let us try a simpler example: \bprog ? sum(n=1, 10^7, (-1)^n/n, 0.) / (-log(2)) \\@com approximates the well-known formula time = 7,417 ms. %1 = 0.9999999278652515622893405457 ? sumalt(n=1, (-1)^n/n) / (-log(2)) \\@com accurate and fast time = 0 ms. %2 = 1.000000000000000000000000000 @eprog\noindent No, we are not using a powerful simplification tool here, only numerical computations. Remember, PARI is not a generalist computer algebra system! \subsec{Beware scopes}\label{se:bewarescope} Be extra careful with the scopes of variables. What is wrong with the following definition? \bprog FirstPrimeDiv(x) = { my(p); forprime(p=2, x, if (x%p == 0, break)); p } ? FirstPrimeDiv(10) %1 = 0 @eprog\noindent \misctitle{Hint} The function body is equivalent to \bprog { my(newp = 0); forprime(p=2, x, if (x%p == 0, break)); newp } @eprog\noindent \misctitle{Detailed explanation} The index \kbd{p} in the \kbd{forprime} loop is lexically scoped to the loop and is not visible to the outside world. Hence, it will not survive the \kbd{break} statement. More precisely, at this point the loop index is restored to its preceding value. The initial \kbd{my(p)}, although well-meant, adds to the confusion: it indeed scopes \kbd{p} to the function body, with initial value $0$, but the \kbd{forprime} loop introduces \emph{another} variable, unfortunately also called \kbd{p}, scoped to the loop body, which shadows the one we wanted. So we always return $0$, since the value of the \kbd{p} scoped to the function body never changes and is initially $0$. To sum up, the routine returns the \kbd{p} declared local to it, not the one which was local to \kbd{forprime} and ran through consecutive prime numbers. Here is a corrected version: \bprog ? FirstPrimeDiv(x) = forprime(p=2, x, if (x%p == 0, return(p))) @eprog \subsec{Recursive functions} Recursive functions\sidx{recursion} can easily be written as long as one pays proper attention to variable scope. Here is an example, used to retrieve the coefficient array of a multivariate polynomial (a nontrivial task due to PARI's unsophisticated representation for those objects): \sidx{multivariate polynomial} \bprog coeffs(P, nvar) = { my (d = poldegree(P)); if (d <= 0, P = simplify(P); for (i=1, nvar, P = [P]); return (P)); vector(d + 1, i, coeffs(polcoef(P, i-1), nvar-1)); } @eprog \noindent If $P$ is a polynomial in $k$ variables, show that after the assignment {\tt v = coeffs(P,k)}, the coefficient of $x_1^{n_1}\dots x_k^{n_k}$ in P is given by {\tt v[$n_1$+1][\dots][$n_k$+1]}, provided a monomial $x_1^{N_1}\dots x_k^{N_k}$ with $n \leq N$ (lexicographically) exists with a non-zero coefficient. When the operating system allows querying the maximum size of the process stack, we automatically limit the \idx{recursion depth}: \sidx{deep recursion} \bprog ? dive(n) = dive(n+1) ? dive(0); *** [...] at: dive(n+1) *** ^--------- *** in function dive: dive(n+1) *** ^--------- \\@com (last 2 lines repeated 19 times) *** deep recursion. @eprog\noindent All Unix variants support this mechanism and the recursion limit may be different from one machine to the next; other systems may crash on deep recursion. There is no way to increase the limit from within \kbd{gp}. On a Unix system, you may increase it before launching \kbd{gp} with \tet{ulimit} or \tet{limit}, depending on your shell, and raise the process available stack space (increase \tet{stacksize}). \subsec{Function which take functions as parameters} This is done as follows: \bprog ? calc(f, x) = f(x) ? calc(sin, Pi) %2 = -5.04870979 E-29 ? g(x) = x^2; ? calc(g, 3) %4 = 9 @eprog \noindent If we do not need \kbd{g} elsewhere, we should use an anonymous function here, \kbd{calc(x->x\pow 2, 3)}. Here is a variation: \bprog ? funs = [cos, sin, tan, x->x^3+1]; \\@com an array of functions ? call(i, x) = funs[i](x) @eprog\noindent evaluates the appropriate function on argument \kbd{x}, provided $1\leq i\leq 4$. Finally, a more useful example: \bprog APPLY(f, v) = vector(#v, i, f(v[i])) @eprog\noindent applies the function \kbd{f} to every element in the vector \kbd{v}. (The built-in function \kbd{apply} is more powerful since it also applies to lists and matrices.) \subsec{Defining functions within a function} Defining a single function is easy: \bprog init(x) = (add = y -> x+y); @eprog\noindent Basically, we are defining a global variable \kbd{add} whose value is the function \kbd{y->x+y}. The parentheses were added for clarity and are not mandatory. \bprog ? init(5); ? add(2) %2 = 7 @eprog\noindent A more refined approach is to avoid global variables and \emph{return} the function: \bprog init(x) = y -> x+y add = init(5) @eprog\noindent Then \kbd{add(2)} still returns 7, as expected! Of course, if \kbd{add} is in global scope, there is no gain, but we can lexically scope it to the place where it is useful: \bprog my ( add = init(5) ); @eprog How about multiple functions then? We can use the last idea and return a vector of functions, but if we insist on global variables? The first idea \bprog init(x) = add(y) = x+y; mul(y) = x*y; @eprog \noindent does not work since in the construction \kbd{f() = }\var{seq}, the function body contains everything until the end of the expression. Hence executing \kbd{init} defines the wrong function \kbd{add} (itself defining a function \kbd{mul}). The way out is to use parentheses for grouping, so that enclosed subexpressions will be evaluated independently: \bprog ? init(x) = ( add(y) = x+y ); ( mul(y) = x*y ); ? init(5); ? add(2) %3 = 7 ? mul(3) %4 = 15 @eprog\noindent This defines two global functions which have access to the lexical variables private to \kbd{init}! The following would work in exactly the same way: \bprog ? init5() = my(x = 5); ( add(y) = x+y ); ( mul(y) = x*y ); @eprog \subsec{Closures as Objects} Contrary to what you might think after the preceding examples, GP's closures may not be used to simulate true ``objects'', with private and public parts and methods to access and manipulate them. In fact, closures indeed incorporate an existing context (they may access lexical variables that existed at the time of their definition), but then may not change it. More precisely, they access a copy, which they are welcome to change, but a further function call still accesses the original context, as it existed at the time the function was defined: \bprog init() = { my(count = 0); (inc()=count++); (dec()=count--); } ? init(); ? inc() %1 = 1 ? inc() %2 = 1 ? dec() %3 = -1 ? dec() %4 = -1 @eprog \section{Member functions}\sidx{member functions} \label{se:member} Member functions use the `dot' notation to retrieve information from complicated structures. The built-in structures are \tev{bid}, \tev{ell}, \tev{galois}, \tev{ff}, \tev{nf}, \tev{bnf}, \tev{bnr} and \tev{prid}, which will be described at length in Chapter~3. The syntax \kbd{structure.member} is taken to mean: retrieve \kbd{member} from \kbd{structure}, e.g.~\kbd{E.j} returns the $j$-invariant of the elliptic curve \kbd{E}, or outputs an error message if \kbd{E} is not a proper \tev{ell} structure. To define your own member functions, use the syntax \ \kbd{\var{var}.\var{member} = \var{seq}}, \noindent where the formal variable \var{var} is scoped to the function body \var{seq}. This is of course reminiscent of a user function with a single formal variable \var{var}. For instance, the current implementation of the \kbd{ell} type is a vector, the $j$-invariant being the thirteenth component. It could be implemented as \bprog x.j = { if (type(x) != "t_VEC" || #x < 14, error("not an elliptic curve: " x)); x[13] } @eprog\noindent As for user functions, you can redefine your member functions simply by typing new definitions. On the other hand, as a safety measure, you cannot redefine the built-in member functions, so attempting to redefine \kbd{x.j} as above would in fact produce an error; you would have to call it e.g.~\kbd{x.myj} in order for \kbd{gp} to accept it. Member functions use call by reference to pass arguments, your function may modify in place the contents of a variable (of container type). \misctitle{Rationale} In most cases, member functions are simple accessors of the form \bprog x.a = x[1]; x.b = x[2]; x.c = x[3]; @eprog\noindent where \kbd{x} is a vector containing relevant data. There are at least three alternative approaches to the above member functions: 1) hardcode \kbd{x[1]}, etc. in the program text, 2) define constant global variables \kbd{AINDEX = 1}, \kbd{BINDEX = 2} and hardcode \kbd{x[AINDEX]}, 3) user functions \kbd{a(x) = x[1]} and so on. Even if 2) improves on 1), these solutions are neither elegant nor flexible, and they scale badly. 3) is a genuine possibility, but the main advantage of member functions is that their namespace is independent from the variables (and functions) namespace, hence we can use very short identifiers without risk. The $j$-invariant is a good example: it would clearly not be a good idea to define \kbd{j(E) = E[13]}, because clashes with loop indices are likely. Beware that there is no guarantee that a built-in member function \emph{is} a simple accessor and it could involve a computation. Thus you should not use them on a constant object in tight loops: store them in a variable before the loop. \misctitle{Note} Typing \b{um} will output all user-defined member functions. \misctitle{Member function names} A valid name starts with a letter followed by any number of keyword characters: \kbd{\_} or alphanumeric characters ([\kbd{A-Za-z0-9}]). The built-in member function names are reserved and cannot be used (see the list with \kbd{?.}). Finally, names starting with \kbd{e} or \kbd{E} followed by a digit are forbidden, due to a clash with the floating point exponent notation: we understand \kbd{1.e2} as $100.000\dots$, not as extracting member \kbd{e2} of object \kbd{1}. \section{Strings and Keywords}\sidx{string}\sidx{keyword} \label{se:strings} \subsec{Strings} GP variables can hold values of type character string (internal type \typ{STR}). This section describes how they are actually used, as well as some convenient tricks (automatic concatenation and expansion, keywords) valid in string context. As explained above, the general way to input a string is to enclose characters between quotes~\kbd{"}. This is the only input construct where whitespace characters are significant: the string will contain the exact number of spaces you typed in. Besides, you can ``escape'' characters by putting a \kbd{\bs} just before them; the translation is as follows \bprog \e: \n: \t: @eprog For any other character $x$, \b{$x$} is expanded to $x$. In particular, the only way to put a \kbd{"} into a string is to escape it. Thus, for instance, \kbd{"\bs"a\bs""} would produce the string whose content is ``a''. This is definitely \emph{not} the same thing as typing \kbd{"a"}, whose content is merely the one-letter string a. You can concatenate two strings using the \tet{concat} function. If either argument is a string, the other is automatically converted to a string if necessary (it will be evaluated first). \bprog ? concat("ex", 1+1) %1 = "ex2" ? a = 2; b = "ex"; concat(b, a) %2 = "ex2" ? concat(a, b) %3 = "2ex" @eprog Some functions expect strings for some of their arguments: \tet{print} would be an obvious example, \tet{Str} is a less obvious but useful one (see the end of this section for a complete list). While typing in such an argument, you will be said to be in \tev{string context}. The rest of this section is devoted to special syntactical tricks which can be used with such arguments (and only here; you will get an error message if you try these outside of string context): \item Writing two strings alongside one another will just concatenate them, producing a longer string. Thus it is equivalent to type in \kbd{"a " "b"} or \kbd{"a b"}. A little tricky point in the first expression: the first whitespace is enclosed between quotes, and so is part of a string; while the second (before the \kbd{"b"}) is completely optional and \kbd{gp} actually suppresses it, as it would with any number of whitespace characters at this point (i.e.~outside of any string). \item If you insert any expression when a string is expected, it gets ``expanded'': it is evaluated as a standard GP expression, and the final result (as would have been printed if you had typed it by itself) is then converted to a string, as if you had typed it directly. For instance \kbd{"a" 1+1 "b"} is equivalent to \kbd{"a2b"}: three strings get created, the middle one being the expansion of \kbd{1+1}, and these are then concatenated according to the rule described above. Another tricky point here: assume you did not assign a value to \kbd{aaa} in a GP expression before. Then typing \kbd{aaa} by itself in a string context will actually produce the correct output (i.e.~the string whose content is aaa), but in a fortuitous way. This \kbd{aaa} gets expanded to the monomial of degree one in the variable \kbd{aaa}, which is of course printed as \kbd{aaa}, and thus will expand to the three letters you were expecting. \misctitle{Warning} Expression involving strings are not handled in a special way; even in string context, the largest possible expression is evaluated, hence \kbd{print("a"[1])} is incorrect since \kbd{"a"} is not an object whose first component can be extracted. On the other hand \kbd{print("a", [1])} is correct (two distinct argument, each converted to a string), and so is \kbd{print("a" 1)} (since \kbd{"a"1} is not a valid expression, only \kbd{"a"} gets expanded, then \kbd{1}, and the result is concatenated as explained above). \subsec{Keywords} Since there are cases where expansion is not desirable, we now distinguish between ``Keywords'' and ``Strings''. String is what has been described so far. Keywords are special relatives of Strings which are automatically assumed to be quoted, whether you actually type in the quotes or not. Thus expansion is never performed on them. They get concatenated, though. The analyzer supplies automatically the quotes you have ``forgotten'' and treats Keywords just as normal strings otherwise. For instance, if you type \kbd{"a"b+b} in Keyword context, you will get the string whose contents are ab+b. In String context, on the other hand, you would get a2\kbd{*}b. All GP functions have prototypes (described in Chapter~3 below) which specify the types of arguments they expect: either generic PARI objects (GEN), or strings, or keywords, or unevaluated expression sequences. In the keyword case, only a very small set of words will actually be meaningful (the \kbd{default} function is a prominent example). \misctitle{Reference} The arguments of the following functions are processed in string context: \settabs\+\indent&\cr \+&\tet{Str}\cr \+&\tet{addhelp} (second argument)\cr \+&\tet{default} (second argument)\cr \+&\tet{error}\cr \+&\tet{extern}\cr \+&\tet{plotstring} (second argument)\cr \+&\tet{plotterm} (first argument)\cr \+&\tet{read} and \tet{readvec}\cr \+&\tet{system}\cr \+&all the \tet{print}\var{xxx} functions\cr \+&all the \tet{write}\var{xxx} functions\cr \noindent The arguments of the following functions are processed as keywords: \+&\tet{alias}\cr \+&\tet{default} (first argument)\cr \+&\tet{install} (all arguments but the last)\cr \+&\tet{trap} (first argument)\cr \+&\tet{whatnow}\cr \subsec{Useful example} The function \kbd{Str} converts its arguments into strings and concatenate them. Coupled with \tet{eval}, it is very powerful. The following example creates generic matrices\sidx{generic matrix}\sidx{matrix}: \bprog ? genmat(u,v,s="x") = matrix(u,v,i,j, eval( Str(s,i,j) )) ? genmat(2,3) + genmat(2,3,"m") %1 = [x11 + m11 x12 + m12 x13 + m13] [x21 + m21 x22 + m22 x23 + m23] @eprog \section{Errors and error recovery} \subsec{Errors} Your input program is first compiled to a more efficient bytecode; then the latter is evaluated, calling appropriate functions from the PARI library. Accordingly, there are two kind of errors: syntax errors produced by the compiler, and runtime errors produced by the PARI library either by the evaluator itself, or in a mathematical function. Both kinds are fatal to your computation: \kbd{gp} will report the error and perform some cleanup (restore variables modified while evaluating the erroneous command, close open files, reclaim unused memory, etc.). At this point, the default is to return to the usual prompt, but if the \kbd{recover} option (\secref{se:def,recover}) is off then \kbd{gp} exits immediately. This can be useful for batch-mode operation to make untrapped errors fatal. When reporting a \emph{syntax error}, \kbd{gp} gives meaningful context by copying (part of) the expression it was trying to compile, indicating where the error occurred with a caret \kbd{\pow-}, as in \bprog ? factor() *** too few arguments: factor() *** ^- ? 1+ *** syntax error, unexpected $end: 1+ *** ^- @eprog\noindent possibly enlarged to a full arrow given enough trailing context \bprog ? if (isprime(1+, do_something()) *** syntax error, unexpected ',': if(isprime(1+,do_something())) *** ^---------------- @eprog\noindent These error messages may be mysterious, because \kbd{gp} cannot guess what you were trying to do, and the error may occur once \kbd{gp} has been sidetracked. The first error is straightforward: \kbd{factor} has one mandatory argument, which is missing. The other two are simple typos involving an ill-formed addition \kbd{1 + } missing its second operand. The error messages differ because the parsing context is slightly different: in the first case we reach the end of input (\kbd{\$end}) while still expecting a token, and in the second one, we received an unexpected token (the comma). Here is a more complicated one: \bprog ? factor(x *** syntax error, unexpected $end, expecting )-> or ',' or ')': factor(x *** ^- @eprog\noindent The error is a missing parenthesis, but from \kbd{gp}'s point of view, you might as well have intended to give further arguments to \kbd{factor} (this is possible and useful, see the description of the function). In fact \kbd{gp} expected either a closing parenthesis, or a second argument separated from the first by a comma. And this is essentially what the error message says: we reached the end of the input (\kbd{\$end}) while expecting a \kbd{')'} or a \kbd{','}. Actually, a third possibility is mentioned in the error message \kbd{)->}, which could never be valid in the above context, but a subexpression like \kbd{(x)->sin(x)}, defining an inline closure would be valid, and the parser is not clever enough to rule that out, so we get the same message as in \bprog ? (x *** syntax error, unexpected $end, expecting )-> or ',' or ')': (x *** ^- @eprog\noindent where all three proposed continuations would be valid. \emph{Runtime errors} from the evaluator are nicer because they answer a correctly worded query, otherwise the bytecode compiler would have protested first; here is a slightly pathological case: \bprog ? if (siN(x) < eps, do_something()) *** at top-level: if(siN(x)}). You can type in a \kbd{gp} command, which is evaluated when you hit the \kbd{} key, and the result is printed as during the main \kbd{gp} loop, except that no history of results is kept. Then the break loop prompt reappears and you can type further commands as long as you do not exit the loop. If you are using readline, the history of commands is kept, and line editing is available as usual. If you type in a command that results in an error, you are sent back to the break loop prompt: errors do \var{not} terminate the loop. To get out of a break loop, you can use \tet{next}, \tet{break}, \tet{return}, or type \kbd{C-d} (\kbd{EOF}), any of which will let \kbd{gp} perform its usual cleanup, and send you back to the \kbd{gp} prompt. Note that \kbd{C-d} is slightly dangerous, since typing it \emph{twice} will not only send you back to the \kbd{gp} prompt, but to your shell prompt! (Since \kbd{C-d} at the \kbd{gp} prompt exits the gp session.) If the break loop was started by a user interrupt \kbd{Control-C}, and not by an error, inputting an empty line, i.e hitting the \kbd{} key at the \kbd{break>} prompt, resumes the temporarily interrupted computation. A single empty line has no effect in case of a fatal error, to avoid getting get out of the loop prematurely, thereby losing valuable debugging data. Any of \tet{next}, \tet{break}, \tet{return}, or \kbd{C-d} will abort the computation and send you back to the \kbd{gp} prompt as above. Break loops are useful as a debugging tool. You may inspect the values of \kbd{gp} variables to understand why an error occurred, or change \kbd{gp}'s state in the middle of a computation (increase debugging level, start storing results in a log file, set variables to different values\dots): hit \kbd{C-c}, type in your modifications, then let the computation go on as explained above. A break loop looks like this: \bprog ? v = 0; 1/v *** at top-level: v=0;1/v *** ^-- *** _/_: impossible inverse in gdiv: 0. *** Break loop (type 'break' to go back to the GP prompt) break> @eprog \noindent So the standard error message is printed first. The \kbd{break>} at the bottom is a prompt, and hitting \kbd{v} then \kbd{}, we see: \bprog break> v 0 @eprog\noindent explaining the problem. We could have typed any \kbd{gp} command, not only the name of a variable, of course. Lexically-scoped variables are accessible to the evaluator during the break loop: \bprog ? for(v = -2, 2, print(1/v)) -1/2 -1 *** at top-level: for(v=-2,2,print(1/v)) *** ^---- *** _/_: impossible inverse in gdiv: 0. *** Break loop (type 'break' to go back to the GP prompt) break> v 0 @eprog\noindent Even though loop indices are automatically lexically scoped and no longer exist when the break loop is run, enough debugging information is retained in the bytecode to reconstruct the evaluation context. Of course, when the error occurs in a nested chain of user function calls, lexically scoped variables are available only in the corresponding frame: \bprog ? f(x) = 1/x; ? g(x) = for(i = 1, 10, f(x+i)); ? for(j = -5,5, g(j)) *** at top-level: for(j=-5,5,g(j)) *** ^----- *** in function g: for(i=1,10,f(x+i)) *** ^------- *** in function f: 1/x *** ^-- *** _/_: impossible inverse in gdiv: 0. *** Break loop: type 'break' to go back to GP prompt break> [i,j,x] \\ @com the $x$ in $f$'s body. [i, j, 0] break> dbg_up \\ @com go up one frame *** at top-level: for(j=-5,5,g(j)) *** ^----- *** in function g: for(i=1,10,f(x+i)) *** ^------- break> [i,j,x] \\ @com the $x$ in $g$'s body, $i$ in the for loop. [5, j, -5] @eprog The following GP commands are available during a break loop to help debugging: \tet{dbg_up}$(n)$: go up $n$ frames, as seen above. \tet{dbg_down}$(n)$: go down $n$ frames, cancelling previous \kbd{dbg\_up}'s. \tet{dbg_x}$(t)$: examine $t$, as \kbd{\bs x} but more flexible. \tet{dbg_err}$()$: returns the current error context \typ{ERROR}. The error components often provide useful additional information: \bprog ? O(2) + O(3) *** at top-level: O(2)+O(3) *** ^----- *** _+_: inconsistent addition t_PADIC + t_PADIC. *** Break loop: type 'break' to go back to GP prompt break> E = dbg_err() error("inconsistent addition t_PADIC + t_PADIC.") break> Vec(E) ["e_OP", "+", O(2), O(3)] @eprog \misctitle{Note} The debugger is enabled by default, and fires up as soon as a runtime error occurs. If you do not like this behavior, you may disable it by setting the default \tet{breakloop} to 0 in for \kbd{gprc}. A runtime error will send you back to the prompt. Note that the break loop is automatically disabled when running \kbd{gp} in non interactive mode, i.e.~when the program's standard input is not attached to a terminal. \misctitle{Technical Note} When you enter a break loop due to a PARI stack overflow, the PARI stack is reset so that you can run commands. Otherwise the stack would immediately overflow again! Still, as explained above, you do not lose the value of any \kbd{gp} variable in the process. \subsec{Protecting code} The expression \kbd{iferr(\var{statements}, ERR, \var{recovery})} \noindent evaluates and returns the value of \var{statements}, unless an error occurs during the evaluation in which case the value of \var{recovery} is returned. As in an if/else clause, with the difference that \var{statements} has been partially evaluated, with possible side effects. We shall give a lot more details about the \kbd{ERR} argument shortly; it is the name of a variable, lexically scoped to the \var{recovery} expression sequence, whose value is set by the exception handler to help the recovery code decide what to do about the error. For instance one can define a fault tolerant inversion function as follows: \bprog ? inv(x) = iferr(1/x, ERR, "oo") \\ ERR is unused... ? for (i=-1,1, print(inv(i))) -1 oo 1 @eprog\noindent Protected codes can be nested without adverse effect. Let's now see how \kbd{ERR} can be used; as written, \kbd{inv} is too tolerant: \bprog ? inv("blah") %2 = "oo" @eprog Let's improve it by checking that we caught a ``division by 0'' exception, and not an unrelated one like the type error \kbd{1 / "blah"}. \bprog ? inv2(x) = { iferr(1/x, ERR, if (errname(ERR) != "e_INV", error(ERR)); "oo") } ? inv2(0) %3 = "oo" \\ as before ? inv2("blah") *** at top-level: inv2("blah") *** ^------------ *** in function inv2: ...f(errname(ERR)!="e_INV",error(ERR));"oo") *** ^----------------- *** error: forbidden division t_INT / t_STR. @eprog\noindent In the \kbd{inv2("blah")} example, the error type was not expected, so we rethrow the exception: \kbd{error(ERR)} triggers the original error that we mistakenly trapped. Since the recovery code should always check whether the error is the one expected, this construction is very common and can be simplified to \bprog ? inv3(x) = iferr(1/x, ERR, "oo", errname(ERR) == "e_INV") @eprog\noindent More generally \kbd{iferr(\var{statements}, ERR, \var{recovery}, \var{predicate})} \noindent only catches the exception if \var{predicate} (allowed to check various things about \kbd{ERR}, not only its name) is nonzero. Rather than trapping everything, then rethrowing whatever we do not like, we advise to only trap errors of a specific kind, as above. Of course, sometimes, one just want to trap \emph{everything} because we do not know what to expect. The following function check whether \tet{install} works correctly in your \kbd{gp}: \bprog broken_install() = { \\ can we install? iferr(install(addii,GG), ERR, return ("OS")); \\ can we use the installed function? iferr(if (addii(1,1) != 2, return("BROKEN")), ERR, return("USE")); return (0); } @eprog \noindent The function returns \kbd{OS} if the operating system does not support \kbd{install}, \kbd{USE} if using an installed function triggers an error, \kbd{BROKEN} if the installed function did not behave as expected, and 0 if everything works. The \kbd{ERR} formal parameter contains more useful data than just the error name, which we recovered using \kbd{errname(ERR)}. In fact, a \typ{ERROR} object usually has extra components, which can be accessed as \kbd{component(ERR,1)}, \kbd{component(ERR,2)}, and so on. Or globally by casting the error to a \typ{VEC}: \kbd{Vec(ERR)} returns the vector of all components at once. See \secref{se:iferr} for the list of all exception types, and the corresponding contents of \kbd{ERR}. \section{Interfacing GP with other languages} \noindent The PARI library was meant to be interfaced with C programs. This specific use is dealt with extensively in the \emph{User's guide to the PARI library}. Of course, \kbd{gp} itself provides a convenient interpreter to execute rather intricate scripts (see \secref{se:programming}). Scripts, when properly written, tend to be shorter and clearer than C programs, and are certainly easier to write, maintain or debug. You don't need to deal with memory management, garbage collection, pointers, declarations, and so on. Because of their intrinsic simplicity, they are more robust as well. They are unfortunately somewhat slower. Thus their use will remain complementary: it is suggested that you test and debug your algorithms using scripts, before actually coding them in C if speed is paramount. The GP2C compiler often eases this part. The \kbd{install} command (see~\secref{se:install}) efficiently imports foreign functions for use under \kbd{gp}, which can of course be written using other libraries than PARI. Thus you may code only critical parts of your program in C, and still maintain most of the program as a GP script. We are aware of three PARI-related Free Software packages to embed PARI in other languages. We \emph{neither endorse nor support} any of them, but you may want to give them a try if you are familiar with the languages they are based on. The first is the Python-based SAGE system (\url{https://sagemath.org/}). The second is the \tet{Math::Pari} Perl module (see any CPAN mirror), written by Ilya Zakharevich. Finally, Michael Stoll and Sam Steingold have integrated PARI into \tet{CLISP} (\url{https://clisp.cons.org/}), a Common Lisp implementation. These provide interfaces to \kbd{gp} functions for use in \kbd{python}, \kbd{perl}, or \kbd{Lisp}\sidx{Perl}\sidx{Python}\sidx{Lisp} programs, respectively. \section{Defaults}\sidx{defaults} \label{se:defaults} \noindent There are many internal variables in \kbd{gp}, defining how the system will behave in certain situations, unless a specific override has been given. Most of them are a matter of basic customization (colors, prompt) and will be set once and for all in your \idx{preferences file} (see \secref{se:gprc}), but some of them are useful interactively (set timer on, increase precision, etc.). The function used to manipulate these values is called \kbd{default}, which is described in \secref{se:default}. The basic syntax is \kbd{default(\var{def}, \var{value})}, \noindent which sets the default \var{def} to \var{value}. In interactive use, most of these can be abbreviated using \kbd{gp} metacommands (mostly, starting with \b), which we shall describe in the next section. Available defaults are described in the reference guide, \secref{se:gp_defaults}, the most important one being \tet{parisizemax}. Just be aware that typing \kbd{default} by itself will list all of them, as well as their current values (see \b{d}). \misctitle{Note} The suffixes \kbd{k}, \kbd{M}, \kbd{G} or \kbd{T} can be appended to a \var{value} which is a numeric argument, with the effect of multiplying it by $10^3$, $10^6$ and $10^9$ respectively. Case is not taken into account there, so for instance \kbd{30k} and \kbd{30K} both stand for $30000$. This is mostly useful to modify or set the defaults \kbd{parisize} and \kbd{parisizemax} which typically involve a lot of trailing zeroes. The suffixes \kbd{kB} or \kbd{KB}, \kbd{MB}, \kbd{GB}, \kbd{TB} can be appended to a \var{value} which is a numeric argument representing a memory size, with the usual meaning of counting in units of $2^{10}$, $2^{20}$, $2^{30}$ and $2^{40}$ bytes respectively. This allows to specify defaults such as \kbd{parisize} or \kbd{parisizemax} in customary units, such as gigabytes (or more properly gibibytes). For instance, \kbd{1k} represents $1000$ bytes and \kbd{1kB} represents $1024$ bytes. \misctitle{(somewhat technical) Note} As we saw in \secref{se:strings}, the second argument to \kbd{default} is subject to string context expansion, which means you can use run-time values. In other words, something like \bprog a = 3; default(logfile, "file" a ".log") @eprog logs the output in \kbd{file3.log}. Some special defaults, corresponding to file names and prompts, expand further the resulting value at the time they are set. Two kinds of expansions may be performed: \item \teb{time expansion}: the string is sent through the library function \tet{strftime}. This means that \kbd{\%}\var{char} combinations have a special meaning, usually related to the time and date. For instance, \kbd{\%H} = hour (24-hour clock) and \kbd{\%M} = minute [00,59] (on a Unix system, you can try \kbd{man strftime} at your shell prompt to get a complete list). This is applied to \kbd{prompt} and \kbd{logfile}. For instance, \kbd{default(prompt,"(\%H:\%M) ? ")} \noindent will prepend the time of day, in the form \kbd{(\var{hh}:\var{mm})} to \kbd{gp}'s usual prompt. \item \teb{environment expansion}: When the string contains a sequence of the form \kbd{\$\var{SOMEVAR}}, e.g.~\kbd{\$HOME}, the environment is searched and if \var{SOMEVAR} is defined, the sequence is replaced by the corresponding value. Also the \kbd{\til} symbol has the same meaning as in many shells~--- \kbd{\til} by itself stands for your home directory, and \kbd{\til{}user} is expanded to \kbd{user}'s home directory. This is applied to all file names\sidx{filename}. \label{se:envir} \section{Simple metacommands}\label{se:meta} \noindent Simple metacommands are meant as shortcuts and should not be used in GP scripts (see \secref{se:programming}). Beware that these, as all of \kbd{gp} input, are \emph{case sensitive}. For example, \b{Q} is not identical to \b{q}. Two kinds of arguments are allowed: numbers (denoted $n$ below) and names (denoted \var{filename} below); braces are used to denote optional arguments, , e.g.~$\{n\}$ means that a numeric argument is expected but can be omitted. Names can be optionally surrounded by double quotes and in this case can contain whitespace, e.g. \kbd{"a b"} and are treated as ordinary character strings, see \secref{se:strings} for details. Whitespace (or spaces) between the metacommand and its arguments and within unquoted arguments is optional. This can cause problems with \b{w}, when you insist on having a file name whose first character is a digit, and with \b{r} or \b{w}, if the file name itself contains a space. In such cases, just quote filenames or use the underlying \tet{read} or \tet{write} function. \subseckbd{?$\{\var{command}\}$} The \kbd{gp} on-line help interface. If you type \kbd{?$n$} where $n$ is a number from 1 to 11, you will get the list of functions in Section $3.n$ of the manual (the list of sections being obtained by simply typing \kbd{?}). \label{se:exthelp} These names are in general not informative enough. More details can be obtained by typing \kbd{?\var{function}}, which gives a short explanation of the function's calling convention and effects. A help string is also attached to a symbolic operator, where arguments are replaced by a placeholder character \kbd{\_}: \bprog ? ?sin sin(x): sine of x. ? ?_*_ x*y: product of x and y. ? ?!_ !a: boolean operator "not". ? ?_! n!: factorial of n. ? ? _^_ x^y: compute x to the power y. @eprog\noindent Of course, to have complete information, read Chapter 3 of this manual. The source code is at your disposal as well, though a trifle less readable. If the line before the copyright message indicates that extended help is available (this means \kbd{perl} is present on your system and the PARI distribution was correctly installed), you can add more \kbd{?} signs for extended functionality: \kbd{??~\var{keyword}} yields the function description as it stands in this manual, usually in Chapter~2 or~3. If you're not satisfied with the default chapter chosen, you can impose a given chapter by ending the keyword with \kbd{@} followed by the chapter number, e.g.~\kbd{??~Hello@2} will look in Chapter~2 for section heading \kbd{Hello} (which doesn't exist, by the way). All operators (e.g.~\kbd{+}, \kbd{\&\&}, etc.) are accepted by this extended help, as well as a few other keywords describing key \kbd{gp} concepts, e.g.~\kbd{readline} (the line editor), \kbd{integer}, \kbd{nf} (``number field'' as used in most algebraic number theory computations), \kbd{ell} (elliptic curves), etc. In case of conflicts between \emph{function} and \emph{default} names (e.g \tet{log}, \tet{simplify}), the function has higher priority. To get the \emph{default} help, use \bprog ?? default(log) ?? default(simplify) @eprog \kbd{???~\var{pattern}} produces a list of sections in Chapter~3 of the manual related to your query. As before, if \var{pattern} ends by \kbd{@} followed by a chapter number, that chapter is searched instead; you also have the option to append a simple \kbd{@} (without a chapter number) to browse through the whole manual. If your query contains dangerous characters (e.g \kbd{?} or blanks) it is advisable to enclose it within double quotes, as for GP strings (e.g \kbd{???~"elliptic curve"}). Note that extended help is more powerful than the short help, since it knows about operators as well: you can type \kbd{??~*} or \kbd{??~\&\&}, whereas a single \kbd{?} would just yield a not too helpful \bprog &&: unknown identifier. @eprog\noindent message. Also, you can ask for extended help on section number~$n$ in Chapter~3, just by typing \kbd{??~$n$} (where \kbd{?$n$} would yield merely a list of functions). Finally, a few key concepts in \kbd{gp} are documented in this way: metacommands (e.g \kbd{??~"??"}), defaults (e.g \kbd{??~default(log)}) not to be mistaken with \kbd{??~log} (the natural logarithm) and type names (e.g \typ{INT} or \kbd{integer}), as well as various miscellaneous keywords such as \kbd{edit} (short summary of line editor commands), \kbd{operator}, \kbd{member}, \kbd{"user defined"}, \kbd{nf}, \kbd{ell}, \dots Last but not least: \kbd{??} without argument will open a \kbd{dvi} previewer (\kbd{xdvi} by default, \kbd{\$GPXDVI} if it is defined in your environment) containing the full user's manual. \kbd{??tutorial} and \kbd{??refcard} do the same with the \idx{tutorial} and \idx{reference card} respectively. \misctitle{Technical note} This functionality is provided by an external \kbd{perl} script that you are free to use outside any \kbd{gp} session (and modify to your liking, if you are perl-knowledgeable). It is called \tet{gphelp}, lies in the \kbd{doc} subdirectory of your distribution (just make sure you run \kbd{Configure} first, see Appendix~A) and is really two programs in one. The one which is used from within \kbd{gp} is \kbd{gphelp} which runs \TeX\ on a selected part of this manual, then opens a previewer. \kbd{gphelp -detex} is a text mode equivalent, which looks often nicer especially on a colour-capable terminal (see \kbd{misc/gprc.dft} for examples). The default \kbd{help} selects which help program will be used from within \kbd{gp}. You are welcome to improve this help script, or write new ones (and we would like to know about it so that we may include them in future distributions). By the way, outside of \kbd{gp} you can give more than one keyword as argument to \kbd{gphelp}. \subseckbd{/*...*/} A comment. Everything between the stars is ignored by \kbd{gp}. These comments can span any number of lines. \subseckbd{\bs\bs} A one-line comment. The rest of the line is ignored by \kbd{gp}. \subsec{\b{a} $\{n\}$} Prints the object number $n$ ($\%n$) in raw format (see \kbd{??output}). If the number $n$ is omitted, print the latest computed object ($\%$). \label{se:history} \subsec{\b{b} $\{n\}$} As \kbd{\b{a}} using ``beautified'' (prettymatrix) format (see \kbd{??output}). \subsec{\b{B} $\{n\}$} As \kbd{\b{b}} using an external prettyprinter (see \kbd{??output} and ??prettyprinter). If no prettyprinter is defined or available, this is identical to \b{b}. \subsec{\b{c}}\sidx{available commands} Prints the list of all available hardcoded functions under \kbd{gp}, not including operators written as special symbols (see \secref{se:operators}). More information can be obtained using the \kbd{?} metacommand (see above). For user-defined functions / member functions, see \b{u} and \b{um}. \subsec{\b{d}} Prints the \idx{defaults} as described in the previous section (shortcut for \kbd{default()}, see \secref{se:default}). \subsec{\b{e} $\{n\}$} Switches the \tet{echo} mode on (1) or off (0). If $n$ is explicitly given, set echo to $n$. \subsec{\b{g} $\{n\}$ $\{$\var{feature}$\}$} Sets the debugging level \tet{debug} to the nonnegative integer $n$. If \emph{feature} is present (such as \kbd{bnf} or \kbd{qflll}), only set the debugging level for that feature, as by using \kbd{setdebug}. \subsec{\b{g} \var{feature} $\{n\}$} Prints the debugging level for given \emph{feature} (such as \kbd{bnf} or \kbd{qflll}, see \kbd{setdebug}). If the nonnegative integer $n$ is present set the debugging level for that feature. \subsec{\b{gf} $\{n\}$} Sets the \kbd{"io"} (or file usage) debugging level to the nonnegative integer $n$. This is a shortcut for \kbd{setdebug("io", $n$)}. \subsec{\b{gm} $\{n\}$} Sets the memory debugging level \tet{debugmem} to the nonnegative integer $n$. \subsec{\b{h} $\{m$\kbd{-}$n\}$} Outputs some debugging info about the hashtable of identifiers used by the GP parser. If the argument is a number $n$, outputs the contents of cell $n$. Ranges can be given in the form $m$\kbd{-}$n$ (from cell $m$ to cell $n$, \$ = last cell). If a function name is given instead of a number or range, outputs info on the internal structure of the hash cell this function occupies (a \kbd{struct entree} in C). If the range is reduced to a dash ('\kbd{-}'), outputs statistics about hash cell usage. \subsec{\b{l} $\{$\var{logfile}$\}$} Switches \tet{log} mode on and off. If a \var{logfile} argument is given, change the default logfile name to \var{logfile} and switch log mode on. \subsec{\b{m}} As \b{b}. \subsec{\b{o} $\{n\}$} Sets \tet{output} mode to $n$ ($0$: raw, $1$: prettymatrix, $3$: external prettyprint). See \kbd{??output} \subsec{\b{p} $\{n\}$} Sets \tet{realprecision} to $n$ decimal digits. Prints its current value if $n$ is omitted. \subsec{\b{pb} $\{n\}$} Sets \tet{realbitprecision} to $n$ bits. Prints its current value if $n$ is omitted. \subsec{\b{ps} $\{n\}$} Sets \tet{seriesprecision} to $n$ significant terms. Prints its current value if $n$ is omitted. \subsec{\b{q}} Quits the \kbd{gp} session and returns to the system. Shortcut for \tet{quit}\kbd{()} (see \secref{se:quit}). \subsec{\b{r} $\{$\var{filename}$\}$} Reads into \kbd{gp} all the commands contained in the named file as if they had been typed from the keyboard, one line after the other. Can be used in combination with the \b{w} command (see below). Related but not equivalent to the function \kbd{read} (see \secref{se:read}); in particular, if the file contains more than one line of input, there will be one history entry for each of them, whereas \kbd{read} would only record the last one. If \var{filename} is omitted, re-read the previously used input file (fails if no file has ever been successfully read in the current session). If a \kbd{gp} \tet{binary file} (see \secref{se:writebin}) is read using this command, it is silently loaded, without cluttering the history. Assuming \kbd{gp} figures how to decompress files on your machine, this command accepts compressed files in \tet{compress}ed (\kbd{.Z}) or \tet{gzip}ped (\kbd{.gz} or \kbd{.z}) format. They will be uncompressed on the fly as \kbd{gp} reads them, without changing the files themselves. \subsec{\b{s}} Prints the state of the PARI \tev{stack} and \tev{heap}. This is used primarily as a debugging device for PARI. \subsec{\b{t}} Prints the \idx{internal longword format} of all the PARI types. The detailed bit or byte format of the initial codeword(s) is explained in Chapter~4, but its knowledge is not necessary for a \kbd{gp} user. \subsec{\b{u}} Prints the definitions of all user-defined functions. \subsec{\b{um}} Prints the definitions of all user-defined member functions. \subsec{\b{uv}} Prints the definitions of all user-defined variables, closures being excluded. \subsec{\b{v}} Prints the \idx{version number} and implementation architecture (680x0, Sparc, Alpha, other) of the \kbd{gp} executable you are using. \subsec{\b{w} $\{n\}$ $\{$\var{filename}$\}$} Writes the object number $n$ ( $\%n$ ) into the named file, in raw format. If the number $n$ is omitted, writes the latest computed object ( $\%$ ). If \var{filename} is omitted, appends to \kbd{logfile} (the GP function \tet{write} is a trifle more powerful, as you can have arbitrary file names). \subsec{\b{x} $\{n\}$} Prints the complete tree with addresses and contents (in hexadecimal) of the \idx{internal representation} of the object number $n$ ( $\%n$ ). If the number $n$ is omitted, uses the latest computed object in \kbd{gp}. As for \b{s}, this is used primarily as a debugging device for PARI, and the format should be self-explanatory. The underlying GP function \tet{dbg_x} is more versatile, since it can be applied to other objects than history entries. \subsec{\b{y} $\{n\}$} Switches \kbd{simplify} on (1) or off (0). If $n$ is explicitly given, set simplify to $n$. \subseckbd{\#} Switches the \kbd{timer} on or off. \subseckbd{\#\#} Prints the time taken by the latest computation. Useful when you forgot to turn on the \kbd{timer}. \section{The preferences file}\sidx{startup}\sidx{preferences file} \label{se:gprc} This file, called \tet{gprc} in the sequel, is used to modify or extend \kbd{gp} default behavior, in all \kbd{gp} sessions: e.g customize \kbd{default} values or load common user functions and aliases. \kbd{gp} opens the \kbd{gprc} file and processes the commands in there, \emph{before} doing anything else, e.g.~creating the PARI stack. If the file does not exist or cannot be read, \kbd{gp} will proceed to the initialization phase at once, eventually emitting a prompt. If any explicit command line switches are given, they override the values read from the preferences file. \subsec{Syntax} The syntax in the \kbd{gprc} file (and valid in this file only) is simple-minded, but should be sufficient for most purposes. The file is read line by line; as usual, white space is ignored unless surrounded by quotes and the standard multiline constructions using braces, \kbd{\bs}, or \kbd{=} are available (multiline comments between \kbd{/*~\dots~*/} are also recognized). \subsubsec{Preprocessor:} Two types of lines are first dealt with by a preprocessor: \item comments are removed. This applies to all text surrounded by \kbd{/*~\dots~*/} as well as to everything following \kbd{\bs\bs} on a given line. \item lines starting with \kbd{\#if} \var{boolean} are treated as comments if \var{boolean} evaluates to \kbd{false}, and read normally otherwise. The condition can be negated using either \kbd{\#if not}, \kbd{\#ifnot} or \kbd{\#if !}. If the rest of the current line is empty, the test applies to the next line (same behavior as \kbd{=} under \kbd{gp}). The following tests can be performed: \kbd{EMACS}: \kbd{true} if \kbd{gp} is running in an Emacs or TeXmacs shell (see \secref{se:emacs}). \kbd{READL}: \kbd{true} if \kbd{gp} is compiled with \kbd{readline} support (see \secref{se:readline}). \kbd{VERSION} \var{op} \var{number}: where \var{op} is in the set $\{ \kbd{>}, \kbd{<}, \kbd{<=}, \kbd{>=} \}$, and \var{number} is a PARI version number of the form \var{Major}.\var{Minor}.\var{patch}, where the last two components can be omitted (i.e.~$1$ is understood as version $1.0.0$). This is \kbd{true} if \kbd{gp}'s version number satisfies the required inequality. \kbd{BITS\_IN\_LONG} \kbd{==} \var{number}: \var{number} is $32$ (resp.~$64$). This is \kbd{true} if \kbd{gp} was built for a 32-bit (resp.~64-bit) architecture. \subsubsec{Commands:} After preprocessing, the remaining lines are executed as sequence of expressions (as usual, separated by \kbd{;} if necessary). Only following kinds of expressions are recognized: \item \var{dft} \kbd{=} \var{value}, where \var{dft} is one of the available defaults (see \secref{se:defaults}), which will be set to \var{value} on actual startup. Don't forget the quotes around strings (e.g.~for \kbd{prompt} or \kbd{help}). \item \kbd{default(\var{dft}, \var{value})} as above. \item \kbd{setdebug(\var{dom}, \var{value})} set debug level for domain \var{dom} to \var{value}. \item \kbd{read "\var{some\_GP\_file}"} where \kbd{\var{some\_GP\_file}} is a regular GP script this time, which will be read just before \kbd{gp} prompts you for commands, but after initializing the defaults. In particular, file input is delayed until the \kbd{gprc} has been fully loaded. This is the right place to input files containing \kbd{alias} commands, or your favorite macros. \noindent For instance you could set your prompt in the following portable way: \bprog \\ self modifying prompt looking like @com\hbox{\rm(18:03) \key{gp}\kbd{ >}} prompt = "(%H:%M) \e[1mgp\e[m > " \\ readline wants nonprinting characters to be braced between ^A/^B pairs #if READL prompt = "(%H:%M) ^A\e[1m^Bgp^A\e[m^B > " \\ escape sequences not supported under emacs #if EMACS prompt = "(%H:%M) gp > " @eprog \noindent Note that any of the last two lines could be broken in the following way \bprog #if EMACS prompt = "(%H:%M) gp > " @eprog \noindent since the preprocessor directive applies to the next line if the current one is empty. A sample \kbd{gprc} file called \kbd{misc/gprc.dft} is provided in the standard distribution. It is a good idea to have a look at it and customize it to your needs. Since this file does not use multiline constructs, here is one (note the terminating \kbd{;} to separate the expressions): \bprog #if VERSION > 2.2.3 { read "my_scripts"; \\ syntax errors in older versions new_galois_format = 1; \\ default introduced in 2.2.4 } #if ! EMACS { colors = "9, 5, no, no, 4, 1, 2"; help = "gphelp -detex -ch 4 -cb 0 -cu 2"; } @eprog \subsec{The gprc location} When \kbd{gp} is started, it looks for a customization file, or \kbd{gprc} in the following places (in this order, only the first one found will be loaded): \noindent\item \kbd{gp} checks whether the environment variable \tet{GPRC} is set. On Unix, this can be done with something like: \smallskip \settabs\+\indent&\kbd{GPRC=/my/dir/anyname; export GPRC}\quad&\cr \+&\kbd{GPRC=/my/dir/anyname; export GPRC}\quad&in \kbd{sh} syntax (for instance in your \kbd{.profile}),\cr \+&\kbd{setenv GPRC /my/dir/anyname} &in \kbd{csh} syntax (in your \kbd{.login} or \kbd{.cshrc} file).\cr \+&\kbd{env GPRC=/my/dir/anyname gp} &on the command line launching \kbd{gp}.\cr \noindent If so, the file named by \kbd{\$GPRC} is the \kbd{gprc}. \noindent\item If \kbd{GPRC} is not set, and if the environment variable \kbd{HOME} is defined, \kbd{gp} then tries \kbd{\$HOME/.gprc} on a Unix system \kbd{\$HOME\bs gprc.txt} on a DOS, OS/2, or Windows system. \noindent\item If no gprc was found among the user files mentioned above we look for \kbd{/etc/gprc} for a system-wide gprc file (you will need root privileges to set up such a file yourself). \noindent\item Finally, we look in pari's \kbd{datadir} for a file named \kbd{.gprc} on a Unix system \kbd{gprc.txt} on a DOS, OS/2, or Windows system. If you are using our Windows installer, this is where the default preferences file is written. \noindent Note that on Unix systems, the \kbd{gprc}'s default name starts with a '.' and thus is hidden to regular \kbd{ls} commands; you need to type \kbd{ls -a} to list it. \section{Using readline} \sidx{line editor}\sidx{completion} This very useful library provides line editing and contextual completion to \kbd{gp}. You are encouraged to read the \kbd{readline} user manual, but we describe basic usage here. \misctitle{A (too) short introduction to readline}\label{se:readline} In the following, \kbd{C-} stands for ``the \kbd{Control} key combined with another'' and the same for \kbd{M-} with the \kbd{Meta} key; generally \kbd{C-} combinations act on characters, while the \kbd{M-} ones operate on words. The \kbd{Meta} key might be called \kbd{Alt} on some keyboards, will display a black diamond on most others, and can safely be replaced by \kbd{Esc} in any case. Typing any ordinary key inserts text where the cursor stands, the arrow keys enabling you to move in the line. There are many more movement commands, which will be familiar to the Emacs user, for instance \kbd{C-a}/\kbd{C-e} will take you to the start/end of the line, \kbd{M-b}/\kbd{M-f} move the cursor backward/forward by a word, etc. Just press the \kbd{} key at any point to send your command to \kbd{gp}. All the commands you type at the \kbd{gp} prompt are stored in a history, a multiline command being saved as a single concatenated line. The Up and Down arrows (or \kbd{C-p}/\kbd{C-n}) will move you through the history, \kbd{M-<}/\kbd{M->} sending you to the start/end of the history. \kbd{C-r}/\kbd{C-s} will start an incremental backward/forward search. You can kill text (\kbd{C-k} kills till the end of line, \kbd{M-d} to the end of current word) which you can then yank back using the \kbd{C-y} key (\kbd{M-y} will rotate the kill-ring). \kbd{C-\_} will undo your last changes incrementally (\kbd{M-r} undoes all changes made to the current line). \kbd{C-t} and \kbd{M-t} will transpose the character (word) preceding the cursor and the one under the cursor. Keeping the \kbd{M-} key down while you enter an integer (a minus sign meaning reverse behavior) gives an argument to your next readline command (for instance \kbd{M-- C-k} will kill text back to the start of line). If you prefer \idx{Vi}--style editing, \kbd{M-C-j} will toggle you to Vi mode. Of course you can change all these default bindings. For that you need to create a file named \kbd{.inputrc} in your home directory. For instance (notice the embedding conditional in case you would want specific bindings for \kbd{gp}): % \bprog $if Pari-GP set show-all-if-ambiguous "\C-h": backward-delete-char "\e\C-h": backward-kill-word "\C-xd": dump-functions (: "\C-v()\C-b" #@com can be annoying when copy-pasting! [: "\C-v[]\C-b" $endif @eprog \noindent\kbd{C-x C-r} will re-read this init file, incorporating any changes made to it during the current session. \misctitle{Note} By default, \kbd{(} and \kbd{[} are bound to the function \kbd{pari-matched-insert} which, if ``electric parentheses'' are enabled (default: off) will automatically insert the matching closure (respectively \kbd{)} and \kbd{]}). This behavior can be toggled on and off by giving the numeric argument $-2$ to \kbd{(} (\kbd{M--2(}), which is useful if you want, e.g to copy-paste some text into the calculator. If you do not want a toggle, you can use \kbd{M--0} / \kbd{M--1} to specifically switch it on or off). \misctitle{Note} In some versions of readline (2.1 for instance), the \kbd{Alt} or \kbd{Meta} key can give funny results (output 8-bit accented characters for instance). If you do not want to fall back to the \kbd{Esc} combination, put the following two lines in your \kbd{.inputrc}: % \bprog set convert-meta on set output-meta off @eprog \misctitle{Command completion and online help} Hitting \kbd{} will complete words for you. This mechanism is context-dependent: \kbd{gp} will strive to only give you meaningful completions in a given context (it will fail sometimes, but only under rare and restricted conditions). For instance, shortly after a \kbd{\til}, we expect a user name, then a path to some file. Directly after \kbd{default(} has been typed, we would expect one of the \kbd{default} keywords. After a '.', we expect a member keyword. And generally of course, we expect any GP symbol which may be found in the hashing lists: functions (both yours and GP's), and variables. If, at any time, only one completion is meaningful, \kbd{gp} will provide it together with \item an ending comma if we are completing a default, \item a pair of parentheses if we are completing a function name. In that case hitting \kbd{} again will provide the argument list as given by the online help. (Recall that you can always undo the effect of the preceding keys by hitting \kbd{C-\_}; this applies here.) Otherwise, hitting \kbd{} once more will give you the list of possible completions. Just experiment with this mechanism as often as possible, you will probably find it very convenient. For instance, you can obtain \kbd{default(seriesprecision,10)}, just by hitting \kbd{defse10}, which saves 18 keystrokes (out of 27). Hitting \kbd{M-h} will give you the usual short online help concerning the word directly beneath the cursor, \kbd{M-H} will yield the extended help corresponding to the \kbd{help} default program (usually opens a \idx{dvi} previewer, or runs a primitive tex-to-ASCII program). None of these disturb the line you were editing. \section{GNU Emacs and PariEmacs} \label{se:emacs} If you install the PariEmacs package (see Appendix A), you may use \kbd{gp} as a subprocess in \idx{Emacs}. You then need to include in your \kbd{.emacs} file the following lines: \bprog (autoload 'gp-mode "pari" nil t) (autoload 'gp-script-mode "pari" nil t) (autoload 'gp "pari" nil t) (autoload 'gpman "pari" nil t) (setq auto-mode-alist (cons '("\\.gp$" . gp-script-mode) auto-mode-alist)) @eprog \noindent which autoloads functions from the PariEmacs package and ensures that file with the \kbd{.gp} suffix are edited in gp-script mode. Once this is done, under GNU Emacs if you type \kbd{M-x gp} (where as usual \kbd{M} is the \kbd{Meta} key), a special shell will be started launching \kbd{gp} with the default stack size and prime limit. You can then work as usual under \kbd{gp}, but with all the facilities of an advanced text editor. See the PariEmacs documentation for customizations, menus, etc. \newpage pari-2.17.2/doc/usersch1.tex0000644000175000017500000005571614676526175014251 0ustar billbill% Copyright (c) 2000 The PARI Group % % This file is part of the PARI/GP documentation % % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License \chapter{Overview of the PARI system} \section{Introduction} \noindent PARI/GP is a specialized computer algebra system, primarily aimed at number theorists, but has been put to good use in many other different fields, from topology or numerical analysis to physics. Although quite an amount of symbolic manipulation is possible, PARI does badly compared to systems like Magma, Maple, Mathematica, Maxima, or Sagemath on such tasks, e.g.~multivariate polynomials, formal integration, etc. On the other hand, the three main advantages of the system are its speed, the possibility of using directly data types which are familiar to mathematicians, and its extensive algebraic number theory module (in the above-mentioned systems, Magma and Sagemath provide similar features). Non-mathematical strong points include the possibility to program either in high-level scripting languages or with the PARI library, a mature system (development started in the mid eighties) that was used to conduct and disseminate original mathematical research, while building a large user community, linked by helpful mailing lists and a tradition of great user support from the developers. And, of course, PARI/GP is Free Software, covered by the GNU General Public License, either version 2 of the License or (at your option) any later version. PARI is used in three different ways: \quad 1) as a library \tet{libpari}, which can be called from an upper-level language application, for instance written in ANSI C or C$++$; \quad 2) as a sophisticated programmable calculator, named \tet{gp}, whose language \tet{GP} contains most of the control instructions of a standard language like C; \quad 3) the compiler \tet{gp2c} translates GP code to C, and loads it into the \kbd{gp} interpreter. A typical script compiled by \kbd{gp2c} runs 3 to 10 times faster. The generated C code can be edited and optimized by hand. It may also be used as a tutorial to \kbd{libpari} programming. The present Chapter 1 gives an overview of the PARI/GP system; \kbd{gp2c} is distributed separately and comes with its own manual. Chapter 2 describes the \kbd{GP} programming language and the \kbd{gp} calculator. Chapter 3 describes all routines available in the calculator. Programming in library mode is explained in Chapters 4 and 5 in a separate booklet: \emph{User's Guide to the PARI library} (\kbd{libpari.pdf}). A tutorial for \kbd{gp} is provided in the standard distribution: \emph{A tutorial for PARI/GP} (\kbd{tutorial.pdf}) and you should read this first. You can then start over and read the more boring stuff which lies ahead. You can have a quick idea of what is available by looking at the \kbd{gp} general reference card (\kbd{refcard.pdf}; other more specialized reference cards are available). In case of need, you can refer to the complete function description in Chapter 3. \subsectitle{How to get the latest version} Everything can be found on PARI's home page: $$\url{https://pari.math.u-bordeaux.fr/}.$$ % From that point you may access all sources, some binaries, version information, the complete mailing list archives, frequently asked questions and various tips. All threaded and fully searchable. \subsectitle{How to report bugs} Bugs are submitted online to our Bug Tracking System, available from PARI's home page, or directly from the URL $$\url{https://pari.math.u-bordeaux.fr/Bugs/}.$$ % Further instructions can be found on that page. \section{Multiprecision kernels / Portability} The PARI multiprecision kernel comes in three non exclusive flavors. See Appendix~A for how to set up these on your system; various compilers are supported, but the GNU \kbd{gcc} compiler is the definite favorite. A first version is written entirely in ANSI C, with a C++-compatible syntax, and should be portable without trouble to any 32 or 64-bit computer having no drastic memory constraints. We do not know any example of a computer where a port was attempted and failed. In a second version, time-critical parts of the kernel are written in inlined assembler. At present this includes \item the whole ix86 family (Intel, AMD, Cyrix) starting at the 386, up to the Xbox gaming console, including the Opteron 64 bit processor. \item three versions for the Sparc architecture: version 7, version 8 with SuperSparc processors, and version 8 with MicroSparc I or II processors. UltraSparcs use the MicroSparc II version; \item the DEC Alpha 64-bit processor; \item the Intel Itanium 64-bit processor; \item the PowerPC equipping old macintoshs (G3, G4, etc.); \item the HPPA processors (both 32 and 64 bit); \item the MIPS processors (both 32 and 64 bit); \item the RISC-V 64 bit processors. A third version uses the GNU MP library to implement most of its multiprecision kernel. It improves significantly on the native one for large operands, say 100 decimal digits of accuracy or more. You \emph{should} enable it if GMP is present on your system. Parts of the first version are still in use within the GMP kernel, but are scheduled to disappear. A historical version of the PARI/GP kernel, written in 1985, was specific to 680x0 based computers, and was entirely written in MC68020 assembly language. It ran on SUN-3/xx, Sony News, NeXT cubes and on 680x0 based Macs. It is no longer part of the PARI distribution; to run PARI with a 68k assembler micro-kernel, use the GMP kernel! \misctitle{Mathematical notations and conventions} \item Standard rings and fields. We denote $\Z$ the ring of integers, $\Q$ the field of rational numbers, $\R$ the field of real numbers and $\C$ the field of complex numbers (containing en element $i$ such that $i^2 = -1$). Given a prime power $q$, $\F_q$ denotes the finite field with $q$ elements. Given a prime number $p$, $v_p$ denotes the $p$-adic valuation $\Z_p$ is ring of $p$-adic integers, $\Q_p$ the field of $p$-adic numbers and $\C_p$ the $p$-adic completion of the algebraic closure of $\Q_p$. We write $|x|_p = p^{-v_p(x)}$ for $x\in\C_p$. \item Intervals. We write $[a,b]$ for the closed interval $\{x\in \R\colon a\leq x\leq b\}$, $]a,b[$ for the open interval $\{x\in\R\colon a < x < b\}$ and similarly $]a,b]$ and $[a,b[$ for half-open intervals. \item Linear Algebra. Let $K$ be some field and $m,n\leq 0$ be integers. Elements in the vector space $K^n$ are represented as \emph{column} vectors (of length $n$). Elements of the algebra $\Hom_K(K^n, K^m)$ are represented as $m \times n$ matrices; due to an unfortunate historical design decision, $m \times 0$ matrices do not exist in PARI unless $m = 0$. If $M$ is an $m \times n$ matrix, we use the notation ${}^tM$ to denote its transpose (an $n\times m$ matrix). The (right) \emph{kernel} of a matrix $M$ is the vector space $\{v \in K^n\colon Mv = 0\}$. Similarly, the image of $M$ is the span of its columns. \section{The PARI types} \label{se:start} \noindent The GP language is not typed in the traditional sense; in particular, variables have no type. In library mode, the type of all PARI objects is \kbd{GEN}, a generic type. On the other hand, it is dynamically typed: each object has a specific internal type, depending on the mathematical object it represents. The crucial word is recursiveness: most of the PARI types are recursive. For example, the basic internal type \typ{COMPLEX} exists. However, the components (i.e.~the real and imaginary part) of such a ``complex number'' can be of any type. The only sensible ones are integers (we are then in $\Z[i]$), rational numbers ($\Q[i]$), real numbers ($\R[i]=\C$), or even elements of $\Z/n\Z$ (in $(\Z/n\Z)[t]/(t^2+1)$), or $p$-adic numbers when $p\equiv 3 \mod 4$ ($\Q_{p}[i]$). This feature must not be used too rashly in library mode: for example you are in principle allowed to create objects which are ``complex numbers of complex numbers''. (This is not possible under \kbd{gp}.) But do not expect PARI to make sensible use of such objects: you will mainly get nonsense. On the other hand, it \emph{is} allowed to have components of different, but compatible, types, which can be freely mixed in basic ring operations $+$ or $\times$. For example, taking again complex numbers, the real part could be an integer, and the imaginary part a rational number. On the other hand, if the real part is a real number, the imaginary part cannot be an integer modulo $n$ ! Let us now describe the types. As explained above, they are built recursively from basic types which are as follows. We use the letter $T$ to designate any type; the symbolic names \typ{xxx} correspond to the internal representations of the types.\medskip \settabs\+xxxxxx&typexxxxxxxxxxxxx&xxxxxxxxxxxxx&xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\cr % \+&type \tet{t_INT}& $\Z$& Integers (with arbitrary precision)\sidx{integer}\cr % \+&type \tet{t_REAL}& $\R$& Real numbers (with arbitrary precision)\sidx{real number}\cr % \+&type \tet{t_INTMOD}& $\Z/n\Z$& Intmods (integers modulo $n$)\varsidx{intmod}\cr % \+&type \tet{t_FRAC}& $\Q$& Rational numbers (in irreducible form)\sidx{rational number}\cr % \+&type \tet{t_FFELT}& $\F_q$& Finite field element\sidx{finite field element}\cr % % \+&type \tet{t_COMPLEX}& $T[i]$& Complex numbers\sidx{complex number}\cr % \+&type \tet{t_PADIC}& $\Q_p$& $p$-adic\sidx{p-adic number} numbers\cr % \+&type \tet{t_QUAD}& $\Q[w]$& Quadratic Numbers (where $[\Z[w]:\Z]=2$)\sidx{quadratic number}\cr % \+&type \tet{t_POLMOD}& $T[X]/(P)$& Polmods (polynomials modulo $P\in T[X]$)\varsidx{polmod}\cr % \+&type \tet{t_POL}& $T[X]$& Polynomials \sidx{polynomial}\cr % \+&type \tet{t_SER}& $T((X))$& Power series (finite Laurent series)\sidx{power series}\cr % \+&type \tet{t_RFRAC}& $T(X)$& Rational functions (in irreducible form)\sidx{rational function}\cr % \+&type \tet{t_VEC}& $T^n$& Row (i.e.~horizontal) vectors\sidx{row vector}\cr % \+&type \tet{t_COL}& $T^n$& Column (i.e.~vertical) vectors\sidx{column vector}\cr % \+&type \tet{t_MAT}& ${\cal M}_{m,n}(T)$& Matrices\sidx{matrix}\cr % \+&type \tet{t_LIST}& $T^n$& Lists\sidx{list}\cr % \+&type \tet{t_STR}& & Character strings\sidx{string}\cr % \+&type \tet{t_CLOSURE}& & Functions\cr % \+&type \tet{t_ERROR}& & Error messages\cr % \+&type \tet{t_INFINITY}& & $-\infty$ and $+\infty$\cr \noindent and where the types $T$ in recursive types can be different in each component. \sidx{scalar type} The first nine basic types, from \typ{INT} to \typ{POLMOD}, are called scalar types because they essentially occur as coefficients of other more complicated objects. Type \typ{POLMOD} is used to define algebraic extensions of a base ring, and as such is a scalar type. In addition, there exist the type \tet{t_QFB} for integral binary quadratic forms, and the internal type \tet{t_VECSMALL}. The latter holds vectors of small integers\sidx{vecsmall}, whose absolute value is bounded by $2^{31}$ (resp.~$2^{63}$) on 32-bit, resp.~64-bit, machines. They are used internally to represent permutations, polynomials or matrices over a small finite field, etc. Every PARI object (called \tet{GEN} in the sequel) belongs to one of these basic types. Let us have a closer look. \subsec{Integers and reals} They are of arbitrary and varying length (each number carrying in its internal \sidx{integer}\sidx{real number} representation its own length or precision) with the following mild restrictions (given for 32-bit machines, the restrictions for 64-bit machines being so weak as to be considered nonexistent): integers must be in absolute value less than $2^{536870815}$ (i.e.~roughly 161614219 decimal digits). The precision of real numbers is also at most 161614219 significant decimal digits, and the binary exponent must be in absolute value less than $2^{29}$, resp. $2^{61}$, on 32-bit, resp.~64-bit machines. Integers and real numbers are nonrecursive types. \subsec{Intmods, rational numbers, $p$-adic numbers, polmods, and rational functions} These are recursive, but in a restricted way. \sidx{intmod}\sidx{rational number}\sidx{p-adic number}\sidx{polmod} For intmods or polmods, there are two components: the modulus, which must be of type integer (resp.\ polynomial), and the representative number (resp.\ polynomial). For rational numbers or rational functions, there are also only two components: the numerator and the denominator, which must both be of type integer (resp.\ polynomial). \def\limproj{{\displaystyle\lim_{\textstyle\longleftarrow}}} Finally, $p$-adic numbers have three components: the prime $p$, the ``modulus'' $p^k$, and an approximation to the $p$-adic number. Here $\Z_p$ is considered as the projective limit $\limproj \Z/p^k\Z$ via its finite quotients, and $\Q_p$ as its field of fractions. Like real numbers, the codewords contain an exponent, giving the $p$-adic valuation of the number, and also the information on the precision of the number, which is redundant with $p^k$, but is included for the sake of efficiency. \subsec{Finite field elements}\sidx{finite field element} The exact internal format depends of the finite field size, but it includes the field characteristic $p$, an irreducible polynomial $T\in\F_p[X]$ defining the finite field $\F_p[X]/(T)$ and the element expressed as a polynomial in (the class of) $X$. \subsec{Complex numbers and quadratic numbers}\sidx{complex number}\sidx{quadratic number} Quadratic numbers are numbers of the form $a+bw$, where $w$ is such that $[\Z[w]:\Z]=2$, and more precisely $w=\sqrt d/2$ when $d\equiv 0 \mod 4$, and $w=(1+\sqrt d)/2$ when $d\equiv 1 \mod 4$, where $d$ is the discriminant of a quadratic order. Complex numbers correspond to the important special case $w=\sqrt{-1}$. Complex numbers are partially recursive: the two components $a$ and $b$ can be of type \typ{INT}, \typ{REAL}, \typ{INTMOD}, \typ{FRAC}, or \typ{PADIC}, and can be mixed, subject to the limitations mentioned above. For example, $a+bi$ with $a$ and $b$ $p$-adic is in $\Q_p[i]$, but this is equal to $\Q_p$ when $p\equiv 1 \mod 4$, hence we must exclude these $p$ when one explicitly uses a complex $p$-adic type. Quadratic numbers are more restricted: their components may be as above, except that \typ{REAL} is not allowed. \subsec{Polynomials, power series, vectors, matrices} \sidx{polynomial}\sidx{power series}\sidx{vector}\sidx{matrix} They are completely recursive, over a commutative base ring: their components can be of any type, and types can be mixed (however beware when doing operations). Note in particular that a polynomial in two variables is simply a polynomial with polynomial coefficients. Polynomials or matrices over noncommutative rings are not supported. In the present version \vers{} of PARI, it is not possible to handle conveniently power series of power series, i.e.~power series in several variables. However power series of polynomials (which are power series in several variables of a special type) are OK. This is a difficult design problem: the mathematical problem itself contains some amount of imprecision, and it is not easy to design an intuitive generic interface for such beasts. \subsec{Strings} These contain objects just as they would be printed by the \kbd{gp} calculator. \subsec{Zero} What is zero? This is a crucial question in all computer systems. The answer we give in PARI is the following. For exact types, all zeros are equivalent and are exact, and thus are usually represented as an integer \idx{zero}. The problem becomes nontrivial for imprecise types: there are infinitely many distinct zeros of each of these types! For $p$-adics and power series the answer is as follows: every such object, including 0, has an exponent $e$. This $p$-adic or $X$-adic zero is understood to be equal to $O(p^e)$ or $O(X^e)$ respectively. \label{se:whatzero} Real numbers also have exponents and a real zero is in fact $O(2^e)$ where $e$ is now usually a negative binary exponent. This of course is printed as usual for a floating point number ($0.00\cdots$ or $0.Exx$ depending on the output format) and not with a $O$ symbol as with $p$-adics or power series. With respect to the natural ordering on the reals we make the following convention: whatever its exponent a real zero is smaller than any positive number, and any two real zeroes are equal. \section{The PARI philosophy} The basic principles which govern PARI is that operations and functions should, firstly, give as exact a result as possible, and secondly, be permitted if they make any kind of sense. In this respect, we make an important distinction between exact and inexact objects: by definition, types \typ{REAL}, \typ{PADIC} or \typ{SER} are imprecise. A PARI object having one of these imprecise types anywhere in its tree is \emph{inexact}, and \emph{exact} otherwise. No loss of accuracy (rounding error) is involved when dealing with exact objects. Specifically, an exact operation between exact objects will yield an exact object. For example, dividing 1 by 3 does not give $0.333\cdots$, but the rational number $(1/3)$. To get the result as a floating point real number, evaluate \kbd{1./3} or \kbd{0.+1/3}. Conversely, the result of operations between imprecise objects, although inexact by nature, will be as precise as possible. Consider for example the addition of two real numbers $x$ and $y$. The \idx{accuracy} of the result is \emph{a priori} unpredictable; it depends on the precisions of $x$ and $y$, on their sizes, and also on the size of $x+y$. From this data, PARI works out the right precision for the result. Even if it is working in calculator mode \kbd{gp}, where there is a notion of \idx{default precision}, its value is only used to convert exact types to inexact ones. In particular, if an operation involves objects of different accuracies, some digits will be disregarded by PARI. It is a common source of errors to forget, for instance, that a real number is given as $r + 2^e \varepsilon$ where $r$ is a rational approximation, $e$ a binary exponent and $\varepsilon$ is a nondescript real number less than 1 in absolute value. Hence, any number less than $2^e$ may be treated as an exact zero: \bprog ? 0.E-38 + 1.E-100 %1 = 0.E-38 ? 0.E100 + 1 %2 = 0.E100 @eprog \noindent As an exercise, if \kbd{a = 2\pow (-100)}, why do \kbd{a + 0.} and \kbd{a * 1.} differ? The second principle is that PARI operations are in general quite permissive. For instance taking the exponential of a vector should not make sense. However, it frequently happens that one wants to apply a given function to all elements in a vector. This is easily done using a loop, or using the \tet{apply} built-in function, but in fact PARI assumes that this is exactly what you want to do when you apply a scalar function to a vector. Taking the exponential of a vector will do just that, so no work is necessary. Most transcendental functions work in the same way\footnote{*}{An ambiguity arises with square matrices. PARI always considers that you want to do componentwise function evaluation in this context, hence to get for example the standard exponential of a square matrix you would need to implement a different function.}. In the same spirit, when objects of different types are combined they are first automatically mapped to a suitable ring, where the computation becomes meaningful: \bprog ? 1/3 + Mod(1,5) %1 = Mod(3, 5) ? I + O(5^9) %2 = 2 + 5 + 2*5^2 + 5^3 + 3*5^4 + 4*5^5 + 2*5^6 + 3*5^7 + O(5^9) ? Mod(1,15) + Mod(1,10) %3 = Mod(2, 5) @eprog The first example is straightforward: since $3$ is invertible mod $5$, $(1/3)$ is easily mapped to $\Z/5\Z$. In the second example, \kbd{I} stands for the customary square root of $-1$; we obtain a $5$-adic number, $5$-adically close to a square root of $-1$. The final example is more problematic, but there are natural maps from $\Z/15\Z$ and $\Z/10\Z$ to $\Z/5\Z$, and the computation takes place there. \section{Operations and functions} The available operations and functions in PARI are described in detail in Chapter 3. Here is a brief summary: \subsec{Standard arithmetic operations} \noindent Of course, the four standard operators \kbd{+}, \kbd{-}, \kbd{*}, \kbd{/} exist. We emphasize once more that division is, as far as possible, an exact operation: $4$ divided by $3$ gives \kbd{(4/3)}. In addition to this, operations on integers or polynomials, like \b{} (Euclidean division), \kbd{\%} (Euclidean remainder) exist; for integers, {\b{/}} computes the quotient such that the remainder has smallest possible absolute value. There is also the exponentiation operator \kbd{\pow }, when the exponent is of type integer; otherwise, it is considered as a transcendental function. Finally, the logical operators \kbd{!} (\kbd{not} prefix operator), \kbd{\&\&} (\kbd{and} operator), \kbd{||} (\kbd{or} operator) exist, giving as results \kbd{1} (true) or \kbd{0} (false). \subsec{Conversions and similar functions} \noindent Many conversion functions are available to convert between different types. For example floor, ceiling, rounding, truncation, etc\dots. Other simple functions are included like real and imaginary part, conjugation, norm, absolute value, changing precision or creating an intmod or a polmod. \subsec{Transcendental functions} \noindent They usually operate on any complex number, power series, and some also on $p$-adics. The list is ever-expanding and of course contains all the elementary functions (exp/log, trigonometric functions), plus many others (modular functions, Bessel functions, polylogarithms\dots). Recall that by extension, PARI usually allows a transcendental function to operate componentwise on vectors or matrices. \subsec{Arithmetic functions} \noindent Apart from a few like the factorial function or the Fibonacci numbers, these are functions which explicitly use the prime factor decomposition of integers. The standard functions are included. A number of factoring methods are used by a rather sophisticated factoring engine (to name a few, Shanks's SQUFOF, Pollard's rho, Lenstra's ECM, the MPQS quadratic sieve). These routines output strong pseudoprimes, which may be certified by the APRCL test. There is also a large package to work with algebraic number fields. All the usual operations on elements, ideals, prime ideals, etc.~are available. More sophisticated functions are also implemented, like solving Thue equations, finding integral bases and discriminants of number fields, computing class groups and fundamental units, computing in relative number field extensions, Galois and class field theory, and also many functions dealing with elliptic curves over $\Q$ or over local fields. \subsec{Other functions} \noindent Quite a number of other functions dealing with polynomials (e.g.~finding complex or $p$-adic roots, factoring, etc), power series (e.g.~substitution, reversion), linear algebra (e.g.~determinant, characteristic polynomial, linear systems), and different kinds of recursions are also included. In addition, standard numerical analysis routines like univariate integration (using the double exponential method), real root finding (when the root is bracketed), polynomial interpolation, infinite series evaluation, and plotting are included. \medskip And now, you should really have a look at the tutorial before proceeding. \newpage pari-2.17.2/doc/parimacro.tex0000644000175000017500000003204514760123736014445 0ustar billbill% Copyright (c) 2000 The PARI Group % % This file is part of the PARI/GP documentation % % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License \catcode`\@=11 % % GENERAL FORMATTING % \newif\ifSUBSECTOC\SUBSECTOCtrue \newif\ifSUBSECDOT\SUBSECDOTtrue \newif\ifGPHELP \newif\ifPDF \newread\std \def\checkfile#1{\def\@stdfile{#1}\openin\std=#1\relax} \long\def\@ifundef#1#2#3{\expandafter\ifx\csname #1\endcsname\relax#2\else#3\fi} % do we come from gphelp ? \@ifundef{fromgphelp}{\GPHELPfalse}{\GPHELPtrue} \ifGPHELP %YES \overfullrule=0pt \else %NO \magnification=\magstephalf \PDFfalse \ifx\pdfoutput\undefined \else \ifnum\pdfoutput<1 \else \PDFtrue \fi \fi \fi % if paricfg.tex is there (Configure succeeded), input it, otherwise use % default values \checkfile{paricfg.tex} \ifeof\std \checkfile{doc/paricfg.tex} \fi \ifeof\std \ifGPHELP\else% OK for gphelp to use default values \message{paricfg.tex not found. You should run Configure.} \fi \def\vers{2.0.x} \def\includedir{/usr/local/include/pari} \def\libdir{/usr/local/lib} \else \input\@stdfile \fi \font\chaptertitlefont=cmr12 scaled \magstep1 \font\chaptertitlebf=cmbx10 scaled \magstep2 \font\sectiontitlebf=cmbx12 \font\seventt=cmtt8 scaled 875 \scriptfont\ttfam=\seventt % we should really set the \hyphenchar etc first \parskip=6pt plus 3pt minus 1.5pt %\overfullrule=0pt %% %% TABLE OF CONTENTS %% \newwrite\toc \def\tableofcontents{\begintitle \openin\std=\jobname.toc \ifeof\std \else \begingroup \centerline{\bf Table of Contents}\medskip \parskip=0pt plus 1pt \parindent=0pt \catcode`\_=11 % make _ an ordinary char (frequent in function names) \catcode`\@=11 % make @ an ordinary char (appears in \_ expansion) \obeylines\input\jobname.toc \endgroup \fi \openout\toc=\jobname.toc \endtitle} %% %% CROSS REFERENCING & INDEX %% \newif\ifsecondpass \newwrite\out \newwrite\aux \newwrite\index \ifGPHELP % disable crossreferences \def\condwrite#1#2{} \def\idx#1{#1} \def\toindex#1{} \def\tocwrite#1{} \def\label#1{} \def\gphelpref#1{[Label: {\tt #1}]} \def\gphelpsecref#1{Section~\gphelpref{#1}} \def\ref{\let\do=\gphelpref\doverb} \def\secref{\let\do=\gphelpsecref\doverb} \else % none of the following is needed by gphelp \def\typeout#1{\immediate\write\out{#1}} \def\@namedef#1{\expandafter\def\csname#1\endcsname} \def\newlabel#1#2{\@ifundef{r@#1}{}{\message{Label `#1' multiply defined}}\global\@namedef{r@#1}{#2}} \openin\std=\jobname.std \ifeof\std \secondpassfalse \typeout{FIRST PASS} \openout\index=\jobname.idx \let\condwrite=\write \else \secondpasstrue \typeout{SECOND PASS} \let\immediate\relax \def\condwrite#1#2{} \fi %default font for index entry \def\f@nt{rm} %% \toindex{#1} = put #1 in index; use font \f@nt, indicate \pageno. %% If PDF, associate the page to a unique integer (\pdfdestcntr). \ifPDF \def\toindex#1{\putdest \immediate\condwrite\index{!#1!\f@nt!\the\pageno!\number\pdfdestcntr}} \else \def\toindex#1{% \immediate\condwrite\index{!#1!\f@nt!\the\pageno!}} \fi \checkfile{\jobname.aux} \ifeof\std \message{No aux file.} \else \input\@stdfile% input aux file if present \fi % \ref, \label. We need an auxiliary file written during first pass \openout\aux=\jobname.aux \ifx\inputlineno\undefined \let\on@line\empty \else \def\on@line{ on input line \the\inputlineno} \fi \def\@errundef#1{\typeout{Reference `#1' on page \the\pageno \space undefined\on@line}} \def\@car#1#2\@nil{#1} \def\@cdr#1#2\@nil{#2} \def\@ref {\expandafter\@cdr\@temp \@nil\null} \def\@cref{\expandafter\@car\@temp \@nil\null} \def\label#1{\immediate\write\aux{\string \newlabel{#1}{{\the\chapno}{\currentlabel}}}} \def\ref#1{\@ifundef{r@#1} {{\bf ??}\@errundef{#1}} {\edef\@temp{\csname r@#1\endcsname}% \def\lbl{\@ref}\def\chp{\@cref}% \ifx\chp{\the\chapno}\lbl\else\chp.\lbl\fi}} \def\secref#1{Section~\ref{#1}} \fi % end of non-gphelp section %% %% VERBATIM MODE %% % \doverb: setup verbatim mode for the first argument, and execute \do{\arg} \def\setupverb{\def\do##1{\catcode`##1=12}\dospecials \catcode`\ =10% standard space \catcode`\f=13% to break ugly ligatures as in nf{}init, use \EFF instead } % f won't produce any ligature if catcode 13, e.g in verbatim mode (cf above). { \let\GDEF=\gdef \global\let\EFF=f \catcode`\f=13 \GDEFf{\EFF{}}} \begingroup \catcode`<=1\catcode`\{=12 \catcode`>=2\catcode`\}=12 \gdef\d@verb<% \def\next{##1}<\gdef\@va<##1>\endgroup% \do<\@va>>% \@va is the verbatim argument \next> % \gdef\d@verbb<% \def\next{##1}{##2}<\gdef\@va<##1>\gdef\@vb<##2>\endgroup% \do<\@va><\@vb>>% \@vxxx are the verbatim arguments \next> % \gdef\d@verbbb<% \def\next{##1}{##2}{##3}<\gdef\@va<##1>\gdef\@vb<##2>\gdef\@vc<##3>\endgroup% \do<\@va><\@vb><\@vc>>% \@vxxx are the verbatim arguments \next> % \endgroup \def\doverb {\begingroup\setupverb\d@verb} \def\doverbb{\begingroup\setupverb\d@verbb} % make ',' active to allow automatic glue between function arguments, see \fun \def\doverbbbcomma{\begingroup\catcode`\,=13\setupverb\d@verbbb} \def\func@mma{,\hskip 0.5em plus 0.6em minus 0.3em} {\catcode`\,=13\gdef,{\func@mma}} % argument (silently) goes to index \def\sidx{\gdef\f@nt{rm}\let\do=\toindex\doverb} % \rm \def\kbdsidx{\gdef\f@nt{tt}\let\do=\toindex\doverb}% \tt \def\varsidx{\gdef\f@nt{it}\let\do=\toindex\doverb}% \tt % argument printed + sent to index \def\@idx#1{#1\toindex{#1}} \def\idx{\gdef\f@nt{rm}\let\do=\@idx\doverb} % to index + set up as key (keyword) \def\@keyidx#1{{\bf\@idx{#1}}} \def\teb{\gdef\f@nt{tt}\let\do=\@keyidx\doverb} % to index + set up as kbd (verbatim) \def\@kbdidx#1{{\tt\@idx{#1}}} \def\tet{\gdef\f@nt{tt}\let\do=\@kbdidx\doverb} \def\@url#1{\hbox{\tt#1}} \def\url{\let\do=\@url\doverb} % to index + set up as var (variable) \def\@kbdvar#1{{\it\@idx{#1}\/}} \def\tev{\gdef\f@nt{it}\let\do=\@kbdvar\doverb} \def\@synt#1#2{\gdef\f@nt{tt}\toindex{#1} The library syntax is \key{#1}({\tt #2})} \def\synt{\let\do=\@synt\doverb} % function prototypes \def\funno#1#2#3{\tolerance 1000% \noindent{\tt#1 #2(#3)}\catcode`\,=12\penalty-100{}} % no index \def\@fun#1#2#3{\gdef\f@nt{tt}\toindex{#2}\funno{#1}{#2}{#3}} \def\fun{\let\do=\@fun\doverbbbcomma} \def\@doc#1#2{\gdef\f@nt{tt}\toindex{#1}\noindent{\tt#2}} \def\doc{\let\do=\@doc\doverbb} %% %% SECTIONS %% \newcount\appno \newcount\chapno \newcount\secno \newcount\subsecno \newcount\subsubsecno \def\newpage{\hbox{}\vfill\eject} %Table of contents. cf TeXBook Exercise 21.10 \def\tocwrite#1{{\let\the=0\edef\next{\condwrite\toc{#1}}\next}} \let\putchapdest\relax \let\sectionhook\relax \def\title#1#2{% \ifodd\pageno\else\newpage\fi \tocwrite{{\bf #1 #2\string\dotfill\the\pageno}} \ifGPHELP\else \putchapdest \centerline{\chaptertitlefont #1}\medskip \fi \centerline{\let\bf\chaptertitlebf \chaptertitlefont #2}\vskip1cm} \def\sectitle#1{% \ifGPHELP\else% \vskip 0pt plus 54pt\penalty-600% good break \vskip 24pt plus -45pt minus 9pt\fi% \putchapdest% \tocwrite{{\hskip0.5cm#1\string\dotfill\the\pageno}}% \leftline{\sectionhook{\sectiontitlebf #1}.} \penalty10000 % impossible break \smallskip}% whatever follows will add a \parskip \def\subsectitle#1{% \ifGPHELP\else% \vskip 0pt plus 45pt\penalty-300 \vskip 6pt plus -42pt minus 3pt\fi% \ifSUBSECTOC\tocwrite{{\sevenrm \hskip1cm#1\string\dotfill\the\pageno}}\fi% \sectionhook\noindent{\bf#1}.} \def\subsubsectitle#1{% a \parskip is being added anyway by \noindent \ifGPHELP\else% \par\vskip 0pt plus 39pt\penalty-200 \vskip 0pt plus -37pt minus 1.5pt\fi% \sectionhook\noindent{\bf#1}.} \ifGPHELP \let\maketitle\relax \else \def\maketitle{% \ifnum\chapno=0 \currentlabel. \else \number\chapno.\currentlabel\ \fi} \fi \def\misctitle#1{\par\vskip 0pt plus 66pt\penalty-400 \vskip 3pt plus -64pt minus 1.5pt\noindent{\bf #1.}} % Chapter headings occupy two lines in the manual (only one in % INSTALL.tex and gphelp-extracted bits). Syntax requirement: After calling % \chapter{...} and possibly \label{...} etc, an empty line _must_ follow % before the first paragraph of text or section heading begins. [GN] \def\chapterskip{\global\advance\chapno by 1} \def\chapter#1#2\par{ \secno=0\global\advance\chapno by 1 \title{Chapter \number\chapno:}{#1}#2\noindent\ignorespaces} \def\appendix#1\par{ \secno=0\global\advance\appno by 1 \def\applet{\ifcase\appno\or A\or B\or C\or D\or E\or F\or G\fi} \title{Appendix \applet:}{#1}\noindent\ignorespaces} \def\section#1{% \subsecno=0\global\advance\secno by 1% \gdef\currentlabel{\number\secno}% \sectitle{\maketitle#1}} \def\subsec#1{ \subsubsecno=0\global\advance\subsecno by 1 \gdef\currentlabel{\number\secno.\number\subsecno} \subsectitle{\maketitle#1}} \def\subsubsec#1{ \global\advance\subsubsecno by 1 \gdef\currentlabel{\number\secno.\number\subsecno.\number\subsubsecno} \subsubsectitle{\maketitle#1}} \def\annotepar#1{\noindent\llap{#1:\ \ }} \def\emacs{\annotepar{EMACS}} \def\subseckbd#1{\subsec{\kbd{#1}}} % % General purpose % \def\begintitle{ \begingroup\nopagenumbers \font\mine=cmb10 scaled 1893 \hbox{} } \def\authors{ \centerline{The PARI Group} \vskip 1.truecm \centerline{Institut de Math\'ematiques de Bordeaux, UMR 5251 du CNRS.} \centerline{Universit\'e de Bordeaux, 351 Cours de la Lib\'eration} \centerline{F-33405 TALENCE Cedex, FRANCE} \centerline{\tt e-mail: pari@math.u-bordeaux.fr} \vskip 1.5truecm \centerline{\sectiontitlebf Home Page:} \centerline{\kbd{https://pari.math.u-bordeaux.fr/}} \vskip 2.truecm } \def\copyrightpage{ \begintitle \vskip 14cm \noindent Copyright \copyright\ 2000--2024 The PARI Group \medskip\par \noindent Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. \medskip\par \noindent Permission is granted to copy and distribute modified versions, or translations, of this manual under the conditions for verbatim copying, provided also that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. \bigskip\par \noindent PARI/GP is Copyright \copyright\ 2000--2024 The PARI Group \medskip\par \noindent PARI/GP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY WHATSOEVER. \endtitle } \def\endtitle{\newpage\endgroup} % fraktur font \newfam\euffam \font\teneuf=eufm10 \font\eighteuf=eufm8 \font\seveneuf=eufm7 \textfont\euffam=\teneuf \scriptfont\euffam=\eighteuf \scriptscriptfont\euffam=\seveneuf \def\goth#1{{\fam\euffam#1}} \def\kbd#1{{\tt #1}} \def\key#1{{\bf #1}} \def\emph#1{{\it #1\/}} \def\var#1{\hbox{\it #1\/}} \def\floor#1{\left\lfloor #1 \right\rfloor} \def\ceil#1{\left\lceil #1 \right\rceil} \def\round#1{\left\lfloor #1 \right\rceil} \def\fl{\var{f\kern0pt lag}} \def\Cl{\text{Cl}} \def\gcd{\text{gcd}} \def\lcm{\text{lcm}} \def\Norm{\text{Norm}} \def\Hom{\text{Hom}} \def\Frob{\text{Frob}} \def\Id{\text{Id}} \def\disc{\text{disc}} \def\item{$\bullet$~} %\def\nmid{\not\mid} % Ugly \def\bs{{\char'134}} \def\obr{{\char'173}} \def\cbr{{\char'175}} \def\pow{\^{}\hskip0pt} \def\til{\raise-0.3em\hbox{\~{}}} \def\b#1{{\tt \bs#1}} \def\mod{\,{\rm mod}\,} \def\text#1{{\rm#1}} \def\dfrac#1#2{{{#1}\over{#2}}} \def\binom#1#2{\pmatrix{{#1}\cr{#2}}} \def\Bbb#1{{\bf #1}} {\catcode`\_=11 \gdef\typ#1{\kbd{t_#1}}} \def\A{\Bbb A} \def\Z{\Bbb Z} \def\Q{\Bbb Q} \def\F{\Bbb F} \def\P{\Bbb P} \def\R{\Bbb R} \def\C{\Bbb C} \def\dotfill{\leaders\hbox to 3truemm{\hfil.\hfil}\hfill} \def\B{\kbd{BITS\_IN\_LONG}} \def\op{{\it op\/}} % verbatim mode % @ made active: assume verbatim text doesn't contain it \newif\ifnopar {\catcode`\^=13\global\let^=\pow\obeyspaces\global\let \ } \def\ttverb{% \nopartrue \catcode`\_=12% \catcode`\$=12% \catcode`\\=12% \catcode`\{=12% \catcode`\}=12% \catcode`\&=12% \catcode`\#=12% \catcode`\%=12% \catcode`\^=13% \catcode`\~=13\def~{{\til}}% \catcode`\@=0% \def\par{\futurelet\next\dopars}% \def\dopars{% \ifnopar \noparfalse% \else% treat two consecutive \par specialy \ifx\next\par \vskip4pt plus 1pt\nopartrue% \else \leavevmode\endgraf\fi\fi}% \obeyspaces\obeylines\tt} % back to normalcy \def\unverb{% \catcode`\\=0% \catcode`\{=1% \catcode`\}=2% \catcode`\$=3% \catcode`\&=4% \catcode`\#=6% \catcode`\^=7% \catcode`\_=8% \catcode`\^^I=10} \def\bprog{\begingroup% \vskip 0pt plus 1pt% \leavevmode\parskip=0pt plus 1pt% \interlinepenalty2000\clubpenalty9000\widowpenalty9000% \ttverb} \def\bprogfile#1{\bprog\input#1\eprog} \def\eprog{\endgroup\par} {\obeylines \gdef\com{\begingroup\unverb\comstart} \gdef\comstart#1^^M{\it#1\endgroup } % newline after @endgroup is important } % comments \def\Ccom{\begingroup\unverb\Ccomstart} \def\Ccomstart#1*/{\rm#1\endgroup*/} \ifPDF \input pdfmacs.tex \fi \catcode`\@=12 pari-2.17.2/doc/usersch4.tex0000644000175000017500000032331114760123736014227 0ustar billbill% Copyright (c) 2000 The PARI Group % % This file is part of the PARI/GP documentation % % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License \chapter{Programming PARI in Library Mode} \noindent The \emph{User's Guide to Pari/GP} gives in three chapters a general presentation of the system, of the \kbd{gp} calculator, and detailed explanation of high level PARI routines available through the calculator. The present manual assumes general familiarity with the contents of these chapters and the basics of ANSI C programming, and focuses on the usage of the PARI library. In this chapter, we introduce the general concepts of PARI programming and describe useful general purpose functions; the following chapters describes all public low or high-level functions, underlying or extending the GP functions seen in Chapter 3 of the User's guide. \section{Introduction: initializations, universal objects} \label{se:intro4} \noindent To use PARI in \idx{library mode}, you must write a C program and link it to the PARI library. See the installation guide or the Appendix to the \emph{User's Guide to Pari/GP} on how to create and install the library and include files. A sample Makefile is presented in Appendix~A, and a more elaborate one in \kbd{examples/Makefile}. The best way to understand how programming is done is to work through a complete example. We will write such a program in~\secref{se:prog}. Before doing this, a few explanations are in order. First, one must explain to the outside world what kind of objects and routines we are going to use. This is done\footnote{*}{This assumes that PARI headers are installed in a directory which belongs to your compiler's search path for header files. You might need to add flags like \kbd{-I/usr/local/include} or modify \tet{C_INCLUDE_PATH}.} with the directive \bprog #include @eprog \noindent In particular, this defines the fundamental type for all PARI objects: the type \teb{GEN}, which is simply a pointer to \kbd{long}. Before any PARI routine is called, one must initialize the system, and in particular the PARI stack which is both a scratchboard and a repository for computed objects. This is done with a call to the function \fun{void}{pari_init}{size_t size, ulong maxprime} \noindent The first argument is the number of bytes given to PARI to work with, and the second is the upper limit on a precomputed prime number table; \kbd{size} should not reasonably be taken below $500000$ but you may set $\tet{maxprime} = 0$, although the system still needs to precompute all primes up to about $2^{16}$. For lower-level variants allowing finer control, e.g.~preventing PARI from installing its own error or signal handlers, see~\secref{se:pari_init_tech}. \noindent We have now at our disposal: \item a PARI \tev{stack} containing nothing. This is a big connected chunk of \kbd{size} bytes of memory, where all computations take place. In large computations, intermediate results quickly clutter up memory so some kind of garbage collecting is needed. Most systems do garbage collecting when the memory is getting scarce, and this slows down the performance. PARI takes a different approach, admittedly more demanding on the programmer: you must do your own cleaning up when the intermediate results are not needed anymore. We will see later how (and when) this is done. \item the following \emph{universal objects} (by definition, objects which do not belong to the stack): the integers $0$, $1$, $-1$, $2$ and $-2$ (respectively called \tet{gen_0}, \tet{gen_1}, \tet{gen_m1}, \tet{gen_2} and \tet{gen_m2}), the fraction $\dfrac{1}{2}$ (\tet{ghalf}). All of these are of type \kbd{GEN}. \item a \tev{heap} which is just a linked list of permanent universal objects. For now, it contains exactly the ones listed above. You will probably very rarely use the heap yourself; and if so, only as a collection of copies of objects taken from the stack (called \idx{clone}s in the sequel). Thus you need not bother with its internal structure, which may change as PARI evolves. Some complex PARI functions create clones for special garbage collecting purposes, usually destroying them when returning. \item a table of primes, called \tet{pari_PRIMES}, of type \kbd{pari\_prime*} (pointer to 32bit unsigned integer). Its use is described in \secref{se:primetable} later. Using it directly is deprecated, high-level iterators provide a cleaner and more flexible interface, see \secref{se:primeiter} (such iterators use the private prime table, but extend it dynamically). \item access to all the built-in functions of the PARI library. These are declared to the outside world when you include \kbd{pari.h}, but need the above things to function properly. So if you forget the call to \tet{pari_init}, you will get a fatal error when running your program. \section{Important technical notes} \subsec{Backward compatibility} The PARI function names evolved over time, and deprecated functions are eventually deleted. The file \kbd{pariold.h} contains macros implementing a weak form of backward compatibility. In particular, whenever the name of a documented function changes, a \kbd{\#define} is added to this file so that the old name expands to the new one (provided the prototype didn't change also). This file is included by \kbd{pari.h}, but a large section is commented out by default. Define \tet{PARI_OLD_NAMES} before including \kbd{pari.h} to pollute your namespace with lots of obsolete names like \kbd{un}\footnote{*}{For \kbd{(long)gen\_1}. Since 2004 and version 2.2.9, typecasts are completely unnecessary in PARI programs.}: that might enable you to compile old programs without having to modify them. The preferred way to do that is to add \kbd{-DPARI\_OLD\_NAMES} to your compiler \kbd{CFLAGS}, so that you don't need to modify the program files themselves. Of course, it's better to fix the program if you can! \subsec{Types} \noindent Although PARI objects all have the C type \kbd{GEN}, we will freely use the word \teb{type} to refer to PARI dynamic subtypes: \typ{INT}, \typ{REAL}, etc. The declaration \bprog GEN x; @eprog\noindent declares a C variable of type \kbd{GEN}, but its ``value'' will be said to have type \typ{INT}, \typ{REAL}, etc. The meaning should always be clear from the context. \subsec{Type recursivity} \noindent Conceptually, most PARI types are recursive. But the \kbd{GEN} type is a pointer to \kbd{long}, not to \kbd{GEN}. So special macros must be used to access \kbd{GEN}'s components. The simplest one is \tet{gel}$(V, i)$, where \key{el} stands for \key{el}ement, to access component number $i$ of the \kbd{GEN} $V$. This is a valid \kbd{lvalue} (may be put on the left side of an assignment), and the following two constructions are exceedingly frequent % \bprog gel(V, i) = x; x = gel(V, i); @eprog\noindent where \kbd{x} and \kbd{V} are \kbd{GEN}s. This macro accesses and modifies directly the components of $V$ and do not create a copy of the coefficient, contrary to all the library \emph{functions}. More generally, to retrieve the values of elements of lists of \dots\ of lists of vectors we have the \tet{gmael} macros (for {\bf m}ultidimensional {\bf a}rray {\bf el}ement). The syntax is $\key{gmael}n(V,a_1,\dots,a_n)$, where $V$ is a \kbd{GEN}, the $a_i$ are indexes, and $n$ is an integer between $1$ and $5$. This stands for $x[a_1][a_2]\dots[a_n]$, and returns a \kbd{GEN}. The macros \tet{gel} (resp.~\tet{gmael}) are synonyms for \tet{gmael1} (resp.~\kbd{gmael2}). Finally, the macro $\tet{gcoeff}(M, i, j)$ has exactly the meaning of \kbd{M[i,j]} in GP when \kbd{M} is a matrix. Note that due to the implementation of \typ{MAT}s as horizontal lists of vertical vectors, \kbd{gcoeff(x,y)} is actually equivalent to \kbd{gmael(y,x)}. One should use \kbd{gcoeff} in matrix context, and \kbd{gmael} otherwise. \subsec{Variations on basic functions}\label{se:low_level} In the library syntax descriptions in Chapter~3, we have only given the basic names of the functions. For example \kbd{gadd}$(x,y)$ assumes that $x$ and $y$ are \kbd{GEN}s, and \emph{creates} the result $x+y$ on the PARI stack. For most of the basic operators and functions, many other variants are available. We give some examples for \kbd{gadd}, but the same is true for all the basic operators, as well as for some simple common functions (a complete list is given in Chapter~6): \fun{GEN}{gaddgs}{GEN x, long y} \fun{GEN}{gaddsg}{long x, GEN y} \noindent In the following one, \kbd{z} is a preexisting \kbd{GEN} and the result of the corresponding operation is put into~\kbd{z}. The size of the PARI stack does not change: \fun{void}{gaddz}{GEN x, GEN y, GEN z} \noindent (This last form is inefficient in general and deprecated outside of PARI kernel programming.) Low level kernel functions implement these operators for specialized arguments and are also available: Level 0 deals with operations at the word level (\kbd{long}s and \kbd{ulong}s), Level 1 with \typ{INT} and \typ{REAL} and Level 2 with the rest (modular arithmetic, polynomial arithmetic and linear algebra). Here are some examples of Level $1$ functions: \fun{GEN}{addii}{GEN x, GEN y}: here $x$ and $y$ are \kbd{GEN}s of type \typ{INT} (this is not checked). \fun{GEN}{addrr}{GEN x, GEN y}: here $x$ and $y$ are \kbd{GEN}s of type \typ{REAL} (this is not checked). \noindent There also exist functions \teb{addir}, \teb{addri}, \teb{mpadd} (whose two arguments can be of type \typ{INT} or \typ{REAL}), \teb{addis} (to add a \typ{INT} and a \kbd{long}) and so on. The Level $1$ names are self-explanatory once you know that {\bf i} stands for a \typ{INT}, {\bf r} for a \typ{REAL}, {\bf mp} for i or r, {\bf s} for a signed C long integer, {\bf u} for an unsigned C long integer; finally the suffix {\bf z} means that the result is not created on the PARI stack but assigned to a preexisting GEN object passed as an extra argument. Chapter 6 gives a description of these low-level functions. Level $2$ names are more complicated, see \secref{se:level2names} for all the gory details, and we content ourselves with a simple example used to implement \typ{INTMOD} arithmetic: \fun{GEN}{Fp_add}{GEN x, GEN y, GEN m}: returns the sum of $x$ and $y$ modulo $m$. Here $x, y, m$ are \typ{INT}s (this is not checked). The operation is more efficient if the inputs $x$, $y$ are reduced modulo $m$, but this is not a necessary condition. \misctitle{Important Note} These specialized functions are of course more efficient than the generic ones, but note the hidden danger here: the types of the objects involved (which is not checked) must be severely controlled, e.g.~using \kbd{addii} on a \typ{FRAC} argument will cause disasters. Type mismatches may corrupt the PARI stack, though in most cases they will just immediately overflow the stack. Because of this, the PARI philosophy of giving a result which is as exact as possible, enforced for generic functions like \kbd{gadd} or \kbd{gmul}, is dropped in kernel routines of Level $1$, where it is replaced by the much simpler rule: the result is a \typ{INT} if and only if all arguments are integer types (\typ{INT} but also C \kbd{long} and \kbd{ulong}) and a \typ{REAL} otherwise. For instance, multiplying a \typ{REAL} by a \typ{INT} always yields a \typ{REAL} if you use \kbd{mulir}, where \kbd{gmul} returns the \typ{INT} \kbd{gen\_0} if the integer is $0$. \subsec{Portability: 32-bit / 64-bit architectures} \noindent PARI supports both 32-bit and 64-bit based machines, but not simultaneously! The library is compiled assuming a given architecture, and some of the header files you include (through \kbd{pari.h}) will have been modified to match the library. Portable macros are defined to bypass most machine dependencies. If you want your programs to run identically on 32-bit and 64-bit machines, you have to use these, and not the corresponding numeric values, whenever the precise size of your \kbd{long} integers might matter. Here are the most important ones: \settabs\+ -----------------------------&---------------&------------\cr \+ \tet{DEFAULTPREC} & 64 & ($\approx$ 19 decimal digits) \cr\+ \tet{MEDDEFAULTPREC}& 128 & ($\approx$ 38 decimal digits) \cr\+ \tet{BIGDEFAULTPREC}& 192 & ($\approx$ 57 decimal digits) \cr \noindent For instance, suppose you call a transcendental function, such as \kbd{GEN \key{gexp}(GEN x, long prec)}. \noindent The last argument \kbd{prec} is an integer multiple of $\tet{BITS_IN_LONG}$, corresponding to the default floating point precision required. It is \emph{only} used if \kbd{x} is an exact object, otherwise the relative precision is determined by the precision of~\kbd{x}. Note that for parity reasons, half the accuracies available on $32$-bit architectures (the odd multiples of $32$) have no precise equivalents on $64$-bit machines. \subsec{Using \kbd{malloc} / \kbd{free}} You should make use of the PARI stack as much as possible, and avoid allocating objects using the customary functions. If you do, you should use, or at least have a very close look at, the following wrappers: \fun{void*}{pari_malloc}{size_t size} calls \kbd{malloc} to allocate \kbd{size} bytes and returns a pointer to the allocated memory. If the request fails, an error is raised. The \kbd{SIGINT} signal is blocked until \kbd{malloc} returns, to avoid leaving the system stack in an inconsistent state. \fun{void*}{pari_realloc}{void* ptr, size_t size} as \tet{pari_malloc} but calls \kbd{realloc} instead of \kbd{malloc}. \fun{void}{pari_realloc_ip}{void** ptr, size_t size} equivalent to \kbd{*ptr= realloc(*ptr, size)}, while blocking \kbd{SIGINT}. \fun{void*}{pari_calloc}{size_t size} as \tet{pari_malloc}, setting the memory to zero. \fun{void}{pari_free}{void* ptr} calls \kbd{free} to liberate the memory space pointed to by \kbd{ptr}, which must have been allocated by \kbd{malloc} (\tet{pari_malloc}) or \kbd{realloc} (\tet{pari_realloc}). The \kbd{SIGINT} signal is blocked until \kbd{free} returns. If you use the standard \kbd{libc} functions instead of our wrappers, then your functions will be subtly incompatible with the \kbd{gp} calculator: when the user tries to interrupt a computation, the calculator may crash (if a system call is interrupted at the wrong time). \section{Garbage collection}\label{se:garbage}\sidx{garbage collecting} \subsec{Why and how} \noindent As we have seen, \kbd{pari\_init} allocates a big range of addresses, the \tev{stack}, that are going to be used throughout. Recall that all PARI objects are pointers. Except for a few universal objects, they all point at some part of the stack. The stack starts at the address \kbd{bot} and ends just before \kbd{top}. This means that the quantity % $$ (\kbd{top} - \kbd{bot})\,/\,\kbd{sizeof(long)} $$ % is (roughly) equal to the \kbd{size} argument of \kbd{pari\_init}. The PARI stack also has a ``current stack pointer'' called \teb{avma}, which stands for {\bf av}ailable {\bf m}emory {\bf a}ddress. These three variables are global (declared by \kbd{pari.h}). They are of type \tet{pari_sp}, which means \emph{pari stack pointer}. The stack is oriented upside-down: the more recent an object, the closer to \kbd{bot}. Accordingly, initially \kbd{avma} = \kbd{top}, and \kbd{avma} gets \emph{decremented} as new objects are created. As its name indicates, \kbd{avma} always points just \emph{after} the first free address on the stack, and \kbd{(GEN)avma} is always (a pointer to) the latest created object. When \kbd{avma} reaches \kbd{bot}, the stack overflows, aborting all computations, and an error message is issued. To avoid this \emph{you} need to clean up the stack from time to time, when intermediate objects are not needed anymore. This is called ``\emph{garbage collecting}.'' We are now going to describe briefly how this is done. We will see many concrete examples in the next subsection. \noindent\item First, PARI routines do their own garbage collecting, which means that whenever a documented function from the library returns, only its result(s) have been added to the stack, possibly up to a very small overhead (undocumented ones may not do this). In particular, a PARI function that does not return a \kbd{GEN} does not clutter the stack. Thus, if your computation is small enough (e.g.~you call few PARI routines, or most of them return \kbd{long} integers), then you do not need to do any garbage collecting. This is probably the case in many of your subroutines. Of course the objects that were on the stack \emph{before} the function call are left alone. Except for the ones listed below, PARI functions only collect their own garbage. \noindent\item It may happen that all objects that were created after a certain point can be deleted~--- for instance, if the final result you need is not a \kbd{GEN}, or if some search proved futile. Then, it is enough to record the value of \kbd{avma} just \emph{before} the first garbage is created, and restore it upon exit: \bprog pari_sp av = avma; /*@Ccom record initial avma */ garbage ... set_avma(av); /*@Ccom restore it */ @eprog \noindent All objects created in the \kbd{garbage} zone will eventually be overwritten: they should no longer be accessed after \kbd{avma} has been restored. Think of the \kbd{set\_avma} call as a simple \kbd{avma = av} restoring the \kbd{avma} value. \noindent\item If you want to destroy (i.e.~give back the memory occupied by) the \emph{latest} PARI object on the stack (e.g.~the latest one obtained from a function call), you can use the function\sidx{destruction}% \vadjust{\penalty500}%discourage page break \fun{void}{cgiv}{GEN z} \noindent where \kbd{z} is the object you want to give back. This is equivalent to the above where the initial \kbd{av} is computed from \kbd{z}. \noindent\item Unfortunately life is not so simple, and sometimes you will want to give back accumulated garbage \emph{during} a computation without losing recent data. We shall start with the lowest level function to get a feel for the underlying mechanisms, we shall describe simpler variants later: \fun{GEN}{gerepile}{pari_sp ltop, pari_sp lbot, GEN q}. This function cleans up the stack between \kbd{ltop} and \kbd{lbot}, where $\kbd{lbot} < \kbd{ltop}$, and returns the updated object \kbd{q}. This means: 1) we translate (copy) all the objects in the interval $[\kbd{avma}, \kbd{lbot}[$, so that its right extremity abuts the address \kbd{ltop}. Graphically \vbox{\bprog bot avma lbot ltop top End of stack |-------------[++++++[-/-/-/-/-/-/-|++++++++| Start free memory garbage @eprog \noindent becomes: \bprog bot avma ltop top End of stack |---------------------------[++++++[++++++++| Start free memory @eprog } \noindent where \kbd{++} denote significant objects, \kbd{--} the unused part of the stack, and \kbd{-/-} the garbage we remove. 2) The function then inspects all the PARI objects between \kbd{avma} and \kbd{lbot} (i.e.~the ones that we want to keep and that have been translated) and looks at every component of such an object which is not a codeword. Each such component is a pointer to an object whose address is either --- between \kbd{avma} and \kbd{lbot}, in which case it is suitably updated, --- larger than or equal to \kbd{ltop}, in which case it does not change, or --- between \kbd{lbot} and \kbd{ltop} in which case \kbd{gerepile} raises an error (``significant pointers lost in gerepile''). 3) \key{avma} is updated (we add $\kbd{ltop} - \kbd{lbot}$ to the old value). 4) We return the (possibly updated) object \kbd{q}: if \kbd{q} initially pointed between \kbd{avma} and \kbd{lbot}, we return the updated address, as in~2). If not, the original address is still valid, and is returned! As stated above, no component of the remaining objects (in particular \kbd{q}) should belong to the erased segment [\kbd{lbot}, \kbd{ltop}[, and this is checked within \kbd{gerepile}. But beware as well that the addresses of the objects in the translated zone change after a call to \kbd{gerepile}, so you must not access any pointer which previously pointed into the zone below \kbd{ltop}. If you need to recover more than one object, use the \kbd{gerepileall} function below. \misctitle{Remark} As a consequence of the preceding explanation, if a PARI object is to be relocated by \hbox{gerepile} then, apart from universal objects, the chunks of memory used by its components should be in consecutive memory locations. All \kbd{GEN}s created by documented PARI functions are guaranteed to satisfy this. This is because the \kbd{gerepile} function knows only about \emph{two connected zones}: the garbage that is erased (between \kbd{lbot} and \kbd{ltop}) and the significant pointers that are copied and updated. If there is garbage interspersed with your objects, disaster occurs when we try to update them and consider the corresponding ``pointers''. In most cases of course the said garbage is in fact a bunch of other \kbd{GEN}s, in which case we simply waste time copying and updating them for nothing. But be wary when you allow objects to become disconnected. \noindent In practice this is achieved by the following programming idiom: \bprog ltop = avma; garbage(); lbot = avma; q = anything(); return gerepile(ltop, lbot, q); /*@Ccom returns the updated q */ @eprog\noindent or directly \bprog ltop = avma; garbage(); lbot = avma; return gerepile(ltop, lbot, anything()); @eprog\noindent Beware that \bprog ltop = avma; garbage(); return gerepile(ltop, avma, anything()) @eprog \noindent might work, but should be frowned upon. We cannot predict whether \kbd{avma} is evaluated after or before the call to \kbd{anything()}: it depends on the compiler. If we are out of luck, it is \emph{after} the call, so the result belongs to the garbage zone and the \kbd{gerepile} statement becomes equivalent to \kbd{set\_avma(ltop)}. Thus we return a pointer to random garbage. \subsec{Variants} \fun{GEN}{gerepileupto}{pari_sp ltop, GEN q}. Cleans the stack between \kbd{ltop} and the \emph{connected} object \kbd{q} and returns \kbd{q} updated. For this to work, \kbd{q} must have been created \emph{before} all its components, otherwise they would belong to the garbage zone! Unless mentioned otherwise, documented PARI functions guarantee this. \fun{GEN}{gerepilecopy}{pari_sp ltop, GEN x}. Functionally equivalent to, but more efficient than \bprog gerepileupto(ltop, gcopy(x)) @eprog\noindent In this case, the \kbd{GEN} parameter \kbd{x} need not satisfy any property before the garbage collection: it may be disconnected, components created before the root, and so on. Of course, this is about twice slower than either \tet{gerepileupto} or \tet{gerepile}, because \kbd{x} has to be copied to a clean stack zone first. This function is a special case of \tet{gerepileall} below, where $n=1$. \fun{void}{gerepileall}{pari_sp ltop, int n, ...}. To cope with complicated cases where many objects have to be preserved. The routine expects $n$ further arguments, which are the \emph{addresses} of the \kbd{GEN}s you want to preserve: \bprog pari_sp ltop = avma; ...; y = ...; ... x = ...; ...; gerepileall(ltop, 2, &x, &y); @eprog\noindent It cleans up the most recent part of the stack (between \kbd{ltop} and \kbd{avma}), updating all the \kbd{GEN}s added to the argument list. A copy is done just before the cleaning to preserve them, so they do not need to be connected before the call. With \kbd{gerepilecopy}, this is the most robust of the \kbd{gerepile} functions (the less prone to user error), hence the slowest. \fun{void}{gerepileallsp}{pari_sp ltop, pari_sp lbot, int n, ...}. More efficient, but trickier than \kbd{gerepileall}. Cleans the stack between \kbd{lbot} and \kbd{ltop} and updates the \kbd{GEN}s pointed at by the elements of \kbd{gptr} without any further copying. This is subject to the same restrictions as \kbd{gerepile}, the only difference being that more than one address gets updated. \subsec{Examples} \subsubsec{gerepile} Let \kbd{x} and \kbd{y} be two preexisting PARI objects and suppose that we want to compute $\kbd{x}^2 + \kbd{y}^2$. This is done using the following program: \bprog GEN x2 = gsqr(x); GEN y2 = gsqr(y), z = gadd(x2,y2); @eprog\noindent The \kbd{GEN} \kbd{z} indeed points at the desired quantity. However, consider the stack: it contains as unnecessary garbage \kbd{x2} and \kbd{y2}. More precisely it contains (in this order) \kbd{z}, \kbd{y2}, \kbd{x2}. (Recall that, since the stack grows downward from the top, the most recent object comes first.) It is not possible to get rid of \kbd{x2}, \kbd{y2} before \kbd{z} is computed, since they are used in the final operation. We cannot record \kbd{avma} before \kbd{x2} is computed and restore it later, since this would destroy \kbd{z} as well. It is not possible either to use the function \kbd{cgiv} since \kbd{x2} and \kbd{y2} are not at the bottom of the stack and we do not want to give back~\kbd{z}. But using \kbd{gerepile}, we can give back the memory locations corresponding to \kbd{x2}, \kbd{y2}, and move the object \kbd{z} upwards so that no space is lost. Specifically: \bprog pari_sp ltop = avma; /*@Ccom remember the current top of the stack */ GEN x2 = gsqr(x); GEN y2 = gsqr(y); pari_sp lbot = avma; /*@Ccom the bottom of the garbage pile */ GEN z = gadd(x2, y2); /*@Ccom z is now the last object on the stack */ z = gerepile(ltop, lbot, z); @eprog \noindent Of course, the last two instructions could also have been written more simply: \bprog z = gerepile(ltop, lbot, gadd(x2,y2)); @eprog\noindent In fact \kbd{gerepileupto} is even simpler to use, because the result of \kbd{gadd} is the last object on the stack and \kbd{gadd} is guaranteed to return an object suitable for \kbd{gerepileupto}: \bprog ltop = avma; z = gerepileupto(ltop, gadd(gsqr(x), gsqr(y))); @eprog\noindent Make sure you understand exactly what has happened before you go on! \misctitle{Remark on assignments and gerepile} When the tree structure and the size of the PARI objects which will appear in a computation are under control, one may allocate sufficiently large objects at the beginning, use assignment statements, then simply restore \kbd{avma}. Coming back to the above example, note that \emph{if} we know that x and y are of type real fitting into \kbd{DEFAULTPREC} words, we can program without using \kbd{gerepile} at all: \bprog z = cgetr(DEFAULTPREC); ltop = avma; gaffect(gadd(gsqr(x), gsqr(y)), z); set_avma(ltop); @eprog\noindent This is often \emph{slower} than a craftily used \kbd{gerepile} though, and certainly more cumbersome to use. As a rule, assignment statements should generally be avoided. \misctitle{Variations on a theme} it is often necessary to do several \kbd{gerepile}s during a computation. However, the fewer the better. The only condition for \kbd{gerepile} to work is that the garbage be connected. If the computation can be arranged so that there is a minimal number of connected pieces of garbage, then it should be done that way. For example suppose we want to write a function of two \kbd{GEN} variables \kbd{x} and \kbd{y} which creates the vector $\kbd{[x}^2+\kbd{y}, \kbd{y}^2+\kbd{x]}$. Without garbage collecting, one would write: % \bprog p1 = gsqr(x); p2 = gadd(p1, y); p3 = gsqr(y); p4 = gadd(p3, x); z = mkvec2(p2, p4); /* not suitable for gerepileupto! */ @eprog\noindent This leaves a dirty stack containing (in this order) \kbd{z}, \kbd{p4}, \kbd{p3}, \kbd{p2}, \kbd{p1}. The garbage here consists of \kbd{p1} and \kbd{p3}, which are separated by \kbd{p2}. But if we compute \kbd{p3} \emph{before} \kbd{p2} then the garbage becomes connected, and we get the following program with garbage collecting: % \bprog ltop = avma; p1 = gsqr(x); p3 = gsqr(y); lbot = avma; z = cgetg(3, t_VEC); gel(z, 1) = gadd(p1,y); gel(z, 2) = gadd(p3,x); z = gerepile(ltop,lbot,z); @eprog\noindent Finishing by \kbd{z = gerepileupto(ltop, z)} would be ok as well. Beware that \bprog ltop = avma; p1 = gadd(gsqr(x), y); p3 = gadd(gsqr(y), x); z = cgetg(3, t_VEC); gel(z, 1) = p1; gel(z, 2) = p3; z = gerepileupto(ltop,z); /*@Ccom WRONG */ @eprog\noindent is a disaster since \kbd{p1} and \kbd{p3} are created before \kbd{z}, so the call to \kbd{gerepileupto} overwrites them, leaving \kbd{gel(z, 1)} and \kbd{gel(z, 2)} pointing at random data! The following does work: \bprog ltop = avma; p1 = gsqr(x); p3 = gsqr(y); lbot = avma; z = mkvec2(gadd(p1,y), gadd(p3,x)); z = gerepile(ltop,lbot,z); @eprog\noindent but is very subtly wrong in the sense that \kbd{z = gerepileupto(ltop, z)} would \emph{not} work. The reason being that \kbd{mkvec2} creates the root \kbd{z} of the vector \emph{after} its arguments have been evaluated, creating the components of \kbd{z} too early; \kbd{gerepile} does not care, but the created \kbd{z} is a time bomb which will explode on any later \kbd{gerepileupto}. On the other hand \bprog ltop = avma; z = cgetg(3, t_VEC); gel(z, 1) = gadd(gsqr(x), y); gel(z, 2) = gadd(gsqr(y), x); z = gerepileupto(ltop,z); /*@Ccom INEFFICIENT */ @eprog\noindent leaves the results of \kbd{gsqr(x)} and \kbd{gsqr(y)} on the stack (and lets \kbd{gerepileupto} update them for naught). Finally, the most elegant and efficient version (with respect to time and memory use) is as follows \bprog z = cgetg(3, t_VEC); ltop = avma; gel(z, 1) = gerepileupto(ltop, gadd(gsqr(x), y)); ltop = avma; gel(z, 2) = gerepileupto(ltop, gadd(gsqr(y), x)); @eprog\noindent which avoids updating the container \kbd{z} and cleans up its components individually, as soon as they are computed. \misctitle{One last example} Let us compute the product of two complex numbers $x$ and $y$, using the $3M$ method which requires 3 multiplications instead of the obvious 4. Let $z = x*y$, and set $x = x_r + i*x_i$ and similarly for $y$ and $z$. We compute $p_1 = x_r*y_r$, $p_2=x_i*y_i$, $p_3=(x_r+x_i)*(y_r+y_i)$, and then we have $z_r=p_1-p_2$, $z_i=p_3-(p_1+p_2)$. The program is as follows: % \bprog ltop = avma; p1 = gmul(gel(x,1), gel(y,1)); p2 = gmul(gel(x,2), gel(y,2)); p3 = gmul(gadd(gel(x,1), gel(x,2)), gadd(gel(y,1), gel(y,2))); p4 = gadd(p1,p2); lbot = avma; z = cgetg(3, t_COMPLEX); gel(z, 1) = gsub(p1,p2); gel(z, 2) = gsub(p3,p4); z = gerepile(ltop,lbot,z); @eprog \misctitle{Exercise} Write a function which multiplies a matrix by a column vector. Hint: start with a \kbd{cgetg} of the result, and use \kbd{gerepile} whenever a coefficient of the result vector is computed. You can look at the answer in \kbd{src/basemath/RgV.c:RgM\_RgC\_mul()}. \subsubsec{gerepileall} Let us now see why we may need the \kbd{gerepileall} variants. Although it is not an infrequent occurrence, we do not give a specific example but a general one: suppose that we want to do a computation (usually inside a larger function) producing more than one PARI object as a result, say two for instance. Then even if we set up the work properly, before cleaning up we have a stack which has the desired results \kbd{z1}, \kbd{z2} (say), and then connected garbage from lbot to ltop. If we write \bprog z1 = gerepile(ltop, lbot, z1); @eprog\noindent then the stack is cleaned, the pointers fixed up, but we have lost the address of \kbd{z2}. This is where we need the \idx{gerepileall} function: \bprog gerepileall(ltop, 2, &z1, &z2) @eprog \noindent copies \kbd{z1} and \kbd{z2} to new locations, cleans the stack from \kbd{ltop} to the old \kbd{avma}, and updates the pointers \kbd{z1} and \kbd{z2}. Here we do not assume anything about the stack: the garbage can be disconnected and \kbd{z1}, \kbd{z2} need not be at the bottom of the stack. If all of these assumptions are in fact satisfied, then we can call \kbd{gerepilemanysp} instead, which is usually faster since we do not need the initial copy (on the other hand, it is less cache friendly). A most important usage is ``random'' garbage collection during loops whose size requirements we cannot (or do not bother to) control in advance: \bprog pari_sp av = avma; GEN x, y; while (...) { garbage(); x = anything(); garbage(); y = anything(); garbage(); if (gc_needed(av,1)) /*@Ccom memory is running low (half spent since entry) */ gerepileall(av, 2, &x, &y); } @eprog \noindent Here we assume that only \kbd{x} and \kbd{y} are needed from one iteration to the next. As it would be costly to call gerepile once for each iteration, we only do it when it seems to have become necessary. More precisely, the macro \tet{stack_lim}\kbd{(av,$n$)} denotes an address where $2^{n-1} / (2^{n-1}+1)$ of the remaining stack space since reference point \kbd{av} is exhausted ($1/2$ for $n=1$, $2/3$ for $n=2$). The test \tet{gc_needed}\kbd{(av,$n$)} becomes true whenever \kbd{avma} drops below that address. \subsec{Comments} First, \kbd{gerepile} has turned out to be a flexible and fast garbage collector for number-theoretic computations, which compares favorably with more sophisticated methods used in other systems. Our benchmarks indicate that the price paid for using \kbd{gerepile} and \kbd{gerepile}-related copies, when properly used, is usually less than 1\% of the total running time, which is quite acceptable! Second, it is of course harder on the programmer, and quite error-prone if you do not stick to a consistent PARI programming style. If all seems lost, just use \tet{gerepilecopy} (or \tet{gerepileall}) to fix up the stack for you. You can always optimize later when you have sorted out exactly which routines are crucial and what objects need to be preserved and their usual sizes. \smallskip If you followed us this far, congratulations, and rejoice: the rest is much easier. \section{Creation of PARI objects, assignments, conversions} \subsec{Creation of PARI objects}\sidx{creation} The basic function which creates a PARI object is \fun{GEN}{cgetg}{long l, long t} $l$ specifies the number of longwords to be allocated to the object, and $t$ is the type of the object, in symbolic form (see \secref{se:impl} for the list of these). The precise effect of this function is as follows: it first creates on the PARI \emph{stack} a chunk of memory of size \kbd{length} longwords, and saves the address of the chunk which it will in the end return. If the stack has been used up, a message to the effect that ``the PARI stack overflows'' is printed, and an error raised. Otherwise, it sets the type and length of the PARI object. In effect, it fills its first codeword (\kbd{z[0]}). Many PARI objects also have a second codeword (types \typ{INT}, \typ{REAL}, \typ{PADIC}, \typ{POL}, and \typ{SER}). In case you want to produce one of those from scratch, which should be exceedingly rare, \emph{it is your responsibility to fill this second codeword}, either explicitly (using the macros described in \secref{se:impl}), or implicitly using an assignment statement (using \kbd{gaffect}). Note that the length argument $l$ is predetermined for a number of types: 3 for types \typ{INTMOD}, \typ{FRAC}, \typ{COMPLEX}, \typ{POLMOD}, \typ{RFRAC}, 4 for type \typ{QUAD}, and 5 for type \typ{PADIC} and \typ{QFB}. However for the sake of efficiency, \kbd{cgetg} does not check this: disasters will occur if you give an incorrect length for those types. \misctitle{Notes} 1) The main use of this function is create efficiently a constant object, or to prepare for later assignments (see \secref{se:assign}). Most of the time you will use \kbd{GEN} objects as they are created and returned by PARI functions. In this case you do not need to use \kbd{cgetg} to create space to hold them. \noindent 2) For the creation of leaves, i.e.~\typ{INT} or \typ{REAL}, \fun{GEN}{cgeti}{long length} \fun{GEN}{cgetr}{long prec} \noindent should be used instead of \kbd{cgetg(length, t\_INT)} and \kbd{cgetg(prec2lg(prec), t\_REAL)} respectively. Finally \fun{GEN}{cgetc}{long prec} \noindent creates a \typ{COMPLEX} whose real and imaginary part are \typ{REAL}s allocated by \kbd{cgetr(prec)}. \misctitle{Examples} 1) Both \kbd{z = cgeti(DEFAULTPREC)} and \kbd{cgetg(DEFAULTPREC, t\_INT)} create a \typ{INT} whose ``precision'' is \kbd{bit\_accuracy(DEFAULTPREC)} = 64. This means \kbd{z} can hold rational integers of absolute value less than $2^{64}$. Note that in both cases, the second codeword is \emph{not} filled. Of course we could use numerical values, e.g.~\kbd{cgeti(4)}, but this would have different meanings on different machines as \kbd{bit\_accuracy(4)} equals 64 on 32-bit machines, but 128 on 64-bit machines. \noindent 2) The following creates a \emph{complex number} whose real and imaginary parts can hold real numbers of precision $\kbd{bit\_accuracy(MEDDEFAULTPREC)} = 96\hbox{ bits:}$ % \bprog z = cgetg(3, t_COMPLEX); gel(z, 1) = cgetr(MEDDEFAULTPREC); gel(z, 2) = cgetr(MEDDEFAULTPREC); @eprog\noindent or simply \kbd{z = cgetc(MEDDEFAULTPREC)}. \noindent 3) To create a matrix object for $4\times 3$ matrices: % \bprog z = cgetg(4, t_MAT); for(i=1; i<4; i++) gel(z, i) = cgetg(5, t_COL); @eprog\noindent or simply \kbd{z = zeromatcopy(4, 3)}, which further initializes all entries to \kbd{gen\_0}. These last two examples illustrate the fact that since PARI types are recursive, all the branches of the tree must be created. The function \teb{cgetg} creates only the ``root'', and other calls to \kbd{cgetg} must be made to produce the whole tree. For matrices, a common mistake is to think that \kbd{z = cgetg(4, t\_MAT)} (for example) creates the root of the matrix: one needs also to create the column vectors of the matrix (obviously, since we specified only one dimension in the first \kbd{cgetg}!). This is because a matrix is really just a row vector of column vectors (hence a priori not a basic type), but it has been given a special type number so that operations with matrices become possible. Finally, to facilitate input of constant objects when speed is not paramount, there are four \tet{varargs} functions: \fun{GEN}{mkintn}{long n, ...} returns the nonnegative \typ{INT} whose expansion in base $2^{32}$ is given by the following $n$ 32bit-words (\kbd{unsigned int}). \bprog mkintn(3, a2, a1, a0); @eprog \noindent returns $a_2 2^{64} + a_1 2^{32} + a_0$. \fun{GEN}{mkpoln}{long n, ...} Returns the \typ{POL} whose $n$ coefficients (\kbd{GEN}) follow, in order of decreasing degree. \bprog mkpoln(3, gen_1, gen_2, gen_0); @eprog \noindent returns the polynomial $X^2 + 2X$ (in variable $0$, use \tet{setvarn} if you want other variable numbers). Beware that $n$ is the number of coefficients, hence \emph{one more} than the degree. \fun{GEN}{mkvecn}{long n, ...} returns the \typ{VEC} whose $n$ coefficients (\kbd{GEN}) follow. \fun{GEN}{mkcoln}{long n, ...} returns the \typ{COL} whose $n$ coefficients (\kbd{GEN}) follow. \misctitle{Warning} Contrary to the policy of general PARI functions, the latter three functions do \emph{not} copy their arguments, nor do they produce an object a priori suitable for \tet{gerepileupto}. For instance \bprog /*@Ccom gerepile-safe: components are universal objects */ z = mkvecn(3, gen_1, gen_0, gen_2); /*@Ccom not OK for gerepileupto: stoi(3) creates component before root */ z = mkvecn(3, stoi(3), gen_0, gen_2); /*@Ccom NO! First vector component \kbd{x} is destroyed */ x = gclone(gen_1); z = mkvecn(3, x, gen_0, gen_2); gunclone(x); @eprog \noindent The following function is also available as a special case of \tet{mkintn}: \fun{GEN}{uu32toi}{ulong a, ulong b} Returns the \kbd{GEN} equal to $2^{32} a + b$, \emph{assuming} that $a,b < 2^{32}$. This does not depend on \kbd{sizeof(long)}: the behavior is as above on both $32$ and $64$-bit machines. \subsec{Sizes} \fun{long}{gsizeword}{GEN x} returns the total number of \B-bit words occupied by the tree representing~\kbd{x}. \fun{long}{gsizebyte}{GEN x} returns the total number of bytes occupied by the tree representing~\kbd{x}, i.e.~\kbd{gsizeword(x)} multiplied by \kbd{sizeof(long)}. This is normally useless since PARI functions use a number of \emph{words} as input for lengths and precisions. \subsec{Assignments} Firstly, if \kbd{x} and \kbd{y} are both declared as \kbd{GEN} (i.e.~pointers to something), the ordinary C assignment \kbd{y = x} makes perfect sense: we are just moving a pointer around. However, physically modifying either \kbd{x} or \kbd{y} (for instance, \kbd{x[1] = 0}) also changes the other one, which is usually not desirable. \label{se:assign} \misctitle{Very important note} Using the functions described in this paragraph is inefficient and often awkward: one of the \tet{gerepile} functions (see~\secref{se:garbage}) should be preferred. See the paragraph end for one exception to this rule. \noindent The general PARI \idx{assignment} function is the function \teb{gaffect} with the following syntax: \fun{void}{gaffect}{GEN x, GEN y} \noindent Its effect is to assign the PARI object \kbd{x} into the \emph{preexisting} object \kbd{y}. Both \kbd{x} and \kbd{y} must be \emph{scalar} types. For convenience, vector or matrices of scalar types are also allowed. This copies the whole structure of \kbd{x} into \kbd{y} so many conditions must be met for the assignment to be possible. For instance it is allowed to assign a \typ{INT} into a \typ{REAL}, but the converse is forbidden. For that, you must use the truncation or rounding function of your choice, e.g.\kbd{mpfloor}. It can also happen that \kbd{y} is not large enough or does not have the proper tree structure to receive the object \kbd{x}. For instance, let \kbd{y} the zero integer with length equal to 2; then \kbd{y} is too small to accommodate any nonzero \typ{INT}. In general common sense tells you what is possible, keeping in mind the PARI philosophy which says that if it makes sense it is valid. For instance, the assignment of an imprecise object into a precise one does \emph{not} make sense. However, a change in precision of imprecise objects is allowed, even if it \emph{increases} its accuracy: we complement the ``mantissa'' with infinitely many $0$ digits in this case. (Mantissa between quotes, because this is not restricted to \typ{REAL}s, it also applies for $p$-adics for instance.) All functions ending in ``\kbd{z}'' such as \teb{gaddz} (see~\secref{se:low_level}) implicitly use this function. In fact what they exactly do is record {\teb{avma}} (see~\secref{se:garbage}), perform the required operation, \teb{gaffect} the result to the last operand, then restore the initial \kbd{avma}. You can assign ordinary C long integers into a PARI object (not necessarily of type \typ{INT}) using \fun{void}{gaffsg}{long s, GEN y} \misctitle{Note} Due to the requirements mentioned above, it is usually a bad idea to use \tet{gaffect} statements. There is one exception: for simple objects (e.g.~leaves) whose size is controlled, they can be easier to use than \kbd{gerepile}, and about as efficient. \misctitle{Coercion} It is often useful to coerce an inexact object to a given precision. For instance at the beginning of a routine where precision can be kept to a minimum; otherwise the precision of the input is used in all subsequent computations, which is inefficient if the latter is known to thousands of digits. One may use the \kbd{gaffect} function for this, but it is easier and more efficient to call \fun{GEN}{gtofp}{GEN x, long prec} converts the complex number~\kbd{x} (\typ{INT}, \typ{REAL}, \typ{FRAC}, \typ{QUAD} or \typ{COMPLEX}) to either a \typ{REAL} or \typ{COMPLEX} whose components are \typ{REAL} of length \kbd{prec}. \subsec{Copy} It is also very useful to \idx{copy} a PARI object, not just by moving around a pointer as in the \kbd{y = x} example, but by creating a copy of the whole tree structure, without pre-allocating a possibly complicated \kbd{y} to use with \kbd{gaffect}. The function which does this is called \teb{gcopy}. Its syntax is: \fun{GEN}{gcopy}{GEN x} \noindent and the effect is to create a new copy of x on the PARI stack. Sometimes, on the contrary, a quick copy of the skeleton of \kbd{x} is enough, leaving pointers to the original data in \kbd{x} for the sake of speed instead of making a full recursive copy. Use \fun{GEN}{shallowcopy}{GEN x} for this. Note that the result is not suitable for \tet{gerepileupto} ! Make sure at this point that you understand the difference between \kbd{y = x}, \kbd{y = gcopy(x)}, \kbd{y = shallowcopy(x)} and \kbd{gaffect(x,y)}. \subsec{Clones}\sidx{clone}\label{se:clone} Sometimes, it is more efficient to create a \emph{persistent} copy of a PARI object. This is not created on the stack but on the heap, hence unaffected by \tet{gerepile} and friends. The function which does this is called \teb{gclone}. Its syntax is: \fun{GEN}{gclone}{GEN x} A clone can be removed from the heap (thus destroyed) using \fun{void}{gunclone}{GEN x} \noindent No PARI object should keep references to a clone which has been destroyed! \subsec{Conversions}\sidx{conversions} The following functions convert C objects to PARI objects (creating them on the stack as usual): \fun{GEN}{stoi}{long s}: C \kbd{long} integer (``small'') to \typ{INT}. \fun{GEN}{dbltor}{double s}: C \kbd{double} to \typ{REAL}. The accuracy of the result is 19 decimal digits, i.e.~a type \typ{REAL} of length \kbd{DEFAULTPREC}, although on 32-bit machines only 16 of them are significant. \noindent We also have the converse functions: \fun{long}{itos}{GEN x}: \kbd{x} must be of type \typ{INT}, \fun{double}{rtodbl}{GEN x}: \kbd{x} must be of type \typ{REAL}, \noindent as well as the more general ones: \fun{long}{gtolong}{GEN x}, \fun{double}{gtodouble}{GEN x}. \section{Implementation of the PARI types} \label{se:impl} \noindent We now go through each type and explain its implementation. Let \kbd{z} be a \kbd{GEN}, pointing at a PARI object. In the following paragraphs, we will constantly mix two points of view: on the one hand, \kbd{z} is treated as the C pointer it is, on the other, as PARI's handle on some mathematical entity, so we will shamelessly write $\kbd{z} \ne 0$ to indicate that the \emph{value} thus represented is nonzero (in which case the \emph{pointer}~\kbd{z} is certainly not \kbd{NULL}). We offer no apologies for this style. In fact, you had better feel comfortable juggling both views simultaneously in your mind if you want to write correct PARI programs. Common to all the types is the first codeword \kbd{z[0]}, which we do not have to worry about since this is taken care of by \kbd{cgetg}. Its precise structure depends on the machine you are using, but it always contains the following data: the \emph{internal type number}\sidx{type number} attached to the symbolic type name, the \emph{length} of the root in longwords, and a technical bit which indicates whether the object is a clone or not (see \secref{se:clone}). This last one is used by \kbd{gp} for internal garbage collecting, you will not have to worry about it. Some types have a second codeword, different for each type, which we will soon describe as we will shortly consider each of them in turn. \noindent The first codeword is handled through the following \emph{macros}: \fun{long}{typ}{GEN z} returns the type number of \kbd{z}. \fun{void}{settyp}{GEN z, long n} sets the type number of \kbd{z} to \kbd{n} (you should not have to use this function if you use \kbd{cgetg}). \fun{long}{lg}{GEN z} returns the length (in longwords) of the root of \kbd{z}. \fun{long}{setlg}{GEN z, long l} sets the length of \kbd{z} to \kbd{l}; you should not have to use this function if you use \kbd{cgetg}. \fun{void}{lg_increase}{GEN z} increase the length of \kbd{z} by 1; you should not have to use this function if you use \kbd{cgetg}. \fun{long}{isclone}{GEN z} is \kbd{z} a clone? \fun{void}{setisclone}{GEN z} sets the \emph{clone} bit. \fun{void}{unsetisclone}{GEN z} clears the \emph{clone} bit. \misctitle{Important remark} For the sake of efficiency, none of the codeword-handling macros check the types of their arguments even when there are stringent restrictions on their use. It is trivial to create invalid objects, or corrupt one of the ``universal constants'' (e.g. setting the sign of \kbd{gen\_0} to $1$), and they usually provide negligible savings. Use higher level functions whenever possible. \misctitle{Remark} The clone bit is there so that \kbd{gunclone} can check it is deleting an object which was allocated by \kbd{gclone}. Miscellaneous vector entries are often cloned by \kbd{gp} so that a GP statement like \kbd{v[1] = x} does not involve copying the whole of \kbd{v}: the component \kbd{v[1]} is deleted if its clone bit is set, and is replaced by a clone of \kbd{x}. Don't set/unset yourself the clone bit unless you know what you are doing: in particular \emph{never} set the clone bit of a vector component when the said vector is scheduled to be uncloned. Hackish code may abuse the clone bit to tag objects for reasons unrelated to the above instead of using proper data structures. Don't do that. \subsec{Type \typ{INT} (integer)} \sidx{integer}\kbdsidx{t_INT}this type has a second codeword \kbd{z[1]} which contains the following information: the sign of \kbd{z}: coded as $1$, $0$ or $-1$ if $\kbd{z} > 0$, $\kbd{z} = 0$, $\kbd{z} < 0$ respectively. the \emph{effective length} of \kbd{z}, i.e.~the total number of significant longwords. This means the following: apart from the integer 0, every integer is ``normalized'', meaning that the most significant mantissa longword is nonzero. However, the integer may have been created with a longer length. Hence the ``length'' which is in \kbd{z[0]} can be larger than the ``effective length'' which is in \kbd{z[1]}. \noindent This information is handled using the following macros: \fun{long}{signe}{GEN z} returns the sign of \kbd{z}. \fun{void}{setsigne}{GEN z, long s} sets the sign of \kbd{z} to \kbd{s}. \fun{long}{lgefint}{GEN z} returns the \idx{effective length} of \kbd{z}. \fun{void}{setlgefint}{GEN z, long l} sets the effective length of \kbd{z} to \kbd{l}. The integer 0 can be recognized either by its sign being~0, or by its effective length being equal to~2. Now assume that $\kbd{z} \ne 0$, and let $$ |z| = \sum_{i = 0}^n z_i B^i, \quad\text{where}~z_n\ne 0~\text{and}~B = 2^{\kbd{BITS\_IN\_LONG}}. $$ With these notations, $n$ is \kbd{lgefint(z) - 3}, and the mantissa of $\kbd{z}$ may be manipulated via the following interface: \fun{GEN}{int_MSW}{GEN z} returns a pointer to the most significant word of \kbd{z}, $z_n$. \fun{GEN}{int_LSW}{GEN z} returns a pointer to the least significant word of \kbd{z}, $z_0$. \fun{GEN}{int_W}{GEN z, long i} returns the $i$-th significant word of \kbd{z}, $z_i$. Accessing the $i$-th significant word for $i > n$ yields unpredictable results. \fun{GEN}{int_W_lg}{GEN z, long i, long lz} returns the $i$-th significant word of \kbd{z}, $z_i$, assuming \kbd{lgefint(z)} is \kbd{lz} ($= n + 3$). Accessing the $i$-th significant word for $i > n$ yields unpredictable results. \fun{GEN}{int_precW}{GEN z} returns the previous (less significant) word of \kbd{z}, $z_{i-1}$ assuming \kbd{z} points to $z_i$. \fun{GEN}{int_nextW}{GEN z} returns the next (more significant) word of \kbd{z}, $z_{i+1}$ assuming \kbd{z} points to $z_i$. Unnormalized integers, such that $z_n$ is possibly $0$, are explicitly forbidden. To enforce this, one may write an arbitrary mantissa then call \fun{void}{int_normalize}{GEN z, long known0} \noindent normalizes in place a nonnegative integer (such that $z_n$ is possibly $0$), assuming at least the first \kbd{known0} words are zero. \noindent For instance a binary \kbd{and} could be implemented in the following way: \bprog GEN AND(GEN x, GEN y) { long i, lx, ly, lout; long *xp, *yp, *outp; /* mantissa pointers */ GEN out; if (!signe(x) || !signe(y)) return gen_0; lx = lgefint(x); xp = int_LSW(x); ly = lgefint(y); yp = int_LSW(y); lout = min(lx,ly); /* > 2 */ out = cgeti(lout); out[1] = evalsigne(1) | evallgefint(lout); outp = int_LSW(out); for (i=2; i < lout; i++) { *outp = (*xp) & (*yp); outp = int_nextW(outp); xp = int_nextW(xp); yp = int_nextW(yp); } if ( !*int_MSW(out) ) out = int_normalize(out, 1); return out; } @eprog \noindent This low-level interface is mandatory in order to write portable code since PARI can be compiled using various multiprecision kernels, for instance the native one or GNU MP, with incompatible internal structures (for one thing, the mantissa is oriented in different directions). \subsec{Type \typ{REAL} (real number)} \kbdsidx{t_REAL}\sidx{real number}this type has a second codeword z[1] which also encodes its sign, obtained or set using the same functions as for a \typ{INT}, and a binary exponent. This exponent is handled using the following macros: \fun{long}{expo}{GEN z} returns the exponent of \kbd{z}. This is defined even when \kbd{z} is equal to zero. \fun{void}{setexpo}{GEN z, long e} sets the exponent of \kbd{z} to \kbd{e}. \noindent Note the functions: \fun{long}{gexpo}{GEN z} which tries to return an exponent for \kbd{z}, even if \kbd{z} is not a real number. \fun{long}{gsigne}{GEN z} which returns a sign for \kbd{z}, even when \kbd{z} is a real number of type \typ{INT}, \typ{FRAC} or \typ{REAL}, an infinity (\typ{INFINITY}) or a \typ{QUAD} of positive discriminant. The real zero is characterized by having its sign equal to 0. If \kbd{z} is not equal to~0, then it is represented as $2^e M$, where $e$ is the exponent, and $M\in [1, 2[$ is the mantissa of $z$, whose digits are stored in $\kbd{z[2]},\dots, \kbd{z[lg(z)-1]}$. But keep in mind that the accuracy of \typ{REAL} actually increases by increments of \B bits. More precisely, let $m$ be the integer (\kbd{z[2]},\dots, \kbd{z[lg(z)-1]}) in base \kbd{2\pow BITS\_IN\_LONG}; here, \kbd{z[2]} is the most significant longword and is normalized, i.e.~its most significant bit is~1. Then we have $M := m / 2^{\kbd{bit\_accuracy(lg(z))} - 1 - \kbd{expo}(z)}$. \fun{GEN}{mantissa_real}{GEN z, long *e} returns the mantissa $m$ of $z$, and sets \kbd{*e} to the exponent $\kbd{realprec(z)}-1-\kbd{expo}(z)$, so that $z = m / 2^e$. Thus, the real number $3.5$ to accuracy \kbd{realprec(z)} is represented as \kbd{z[0]} (encoding $\kbd{type} = \typ{REAL}$, \kbd{lg(z)}), \kbd{z[1]} (encoding $\kbd{sign} = 1$, $\kbd{expo} = 1$), $\kbd{z[2]} = \kbd{0xe0000000}$, $\kbd{z[3]} =\dots = \kbd{z[lg(z)-1]} = \kbd{0x0}$. \subsec{Type \typ{INTMOD}}\kbdsidx{t_INTMOD} \kbd{z[1]} points to the modulus, and \kbd{z[2]} at the number representing the class \kbd{z}. Both are separate \kbd{GEN} objects, and both must be \typ{INT}s, satisfying the inequality $0 \le \kbd{z[2]} < \kbd{z[1]}$. \subsec{Type \typ{FRAC} (rational number)}% \kbdsidx{t_FRAC}\sidx{rational number} \kbd{z[1]} points to the numerator $n$, and \kbd{z[2]} to the denominator $d$. Both must be of type \typ{INT} such that $n\neq 0$, $d > 0$ and $(n,d) = 1$. \subsec{Type \typ{FFELT} (finite field element)}% \kbdsidx{t_FFELT}\sidx{finite field element} (Experimental) Components of this type should normally not be accessed directly. Instead, finite field elements should be created using \kbd{ffgen}. \noindent The second codeword \kbd{z[1]} determines the storage format of the element, among \item \tet{t_FF_FpXQ}: \kbd{A=z[2]} and \kbd{T=z[3]} are \kbd{FpX}, \kbd{p=z[4]} is a \typ{INT}, where $p$ is a prime number, $T$ is irreducible modulo $p$, and $\deg A < \deg T$. This represents the element $A\pmod{T}$ in $\F_p[X]/T$. \item \tet{t_FF_Flxq}: \kbd{A=z[2]} and \kbd{T=z[3]} are \kbd{Flx}, \kbd{l=z[4]} is a \typ{INT}, where $l$ is a prime number, $T$ is irreducible modulo $l$, and $\deg A < \deg T$ This represents the element $A\pmod{T}$ in $\F_l[X]/T$. \item \tet{t_FF_F2xq}: \kbd{A=z[2]} and \kbd{T=z[3]} are \kbd{F2x}, \kbd{l=z[4]} is the \typ{INT} $2$, $T$ is irreducible modulo $2$, and $\deg A < \deg T$. This represents the element $A\pmod{T}$ in $\F_2[X]/T$. \subsec{Type \typ{COMPLEX} (complex number)}% \kbdsidx{t_COMPLEX}\sidx{complex number} \kbd{z[1]} points to the real part, and \kbd{z[2]} to the imaginary part. The components \kbd{z[1]} and \kbd{z[2]} must be of type \typ{INT}, \typ{REAL} or \typ{FRAC}. For historical reasons \typ{INTMOD} and \typ{PADIC} are also allowed (the latter for $p = 2$ or congruent to 3 mod 4 only), but one should rather use the more general \typ{POLMOD} construction. \subsec{Type \typ{PADIC} ($p$-adic numbers)}% \sidx{p-adic number}\kbdsidx{t_PADIC} this type has a second codeword \kbd{z[1]} which contains the following information: the $p$-adic precision (the exponent of $p$ modulo which the $p$-adic unit corresponding to \kbd{z} is defined if \kbd{z} is not~0), i.e.~one less than the number of significant $p$-adic digits, and the exponent of \kbd{z}. This information can be handled using the following functions: \fun{long}{precp}{GEN z} returns the $p$-adic precision of \kbd{z}. This is $0$ if $\kbd{z} = 0$. \fun{void}{setprecp}{GEN z, long l} sets the $p$-adic precision of \kbd{z} to \kbd{l}. \fun{long}{valp}{GEN z} returns the $p$-adic valuation of \kbd{z} (i.e. the exponent). This is defined even if \kbd{z} is equal to~0. \fun{void}{setvalp}{GEN z, long e} sets the $p$-adic valuation of \kbd{z} to \kbd{e}. In addition to this codeword, \kbd{z[2]} points to the prime $p$, \kbd{z[3]} points to $p^{\text{precp(z)}}$, and \kbd{z[4]} points to a \typ{INT} representing the $p$-adic unit attached to \kbd{z} modulo \kbd{z[3]} (and to zero if \kbd{z} is zero). To summarize, if $z\neq 0$, we have the equality: $$ \kbd{z} = p^{\text{valp(z)}} * (\kbd{z[4]} + O(\kbd{z[3]})),\quad \text{where}\quad \kbd{z[3]} = p^{\text{precp(z)}}. $$ \subsec{Type \typ{QUAD} (quadratic number)} \sidx{quadratic number}\kbdsidx{t_QUAD}\kbd{z[1]} points to the canonical polynomial $P$ defining the quadratic field (as output by \tet{quadpoly}), \kbd{z[2]} to the ``real part'' and \kbd{z[3]} to the ``imaginary part''. The latter are of type \typ{INT}, \typ{FRAC}, \typ{INTMOD}, or \typ{PADIC} and are to be taken as the coefficients of \kbd{z} with respect to the canonical basis $(1,X)$ of $\Q[X]/(P(X))$. Exact complex numbers may be implemented as quadratics, but \typ{COMPLEX} is in general more versatile (\typ{REAL} components are allowed) and more efficient. Operations involving a \typ{QUAD} and \typ{COMPLEX} are implemented by converting the \typ{QUAD} to a \typ{REAL} (or \typ{COMPLEX} with \typ{REAL} components) to the accuracy of the \typ{COMPLEX}. As a consequence, operations between \typ{QUAD} and \emph{exact} \typ{COMPLEX}s are not allowed. \subsec{Type \typ{POLMOD} (polmod)}\kbdsidx{t_POLMOD}\sidx{polmod} as for \typ{INTMOD}s, \kbd{z[1]} points to the modulus, and \kbd{z[2]} to a polynomial representing the class of~\kbd{z}. Both must be of type \typ{POL} in the same variable, satisfying the inequality $\deg \kbd{z[2]} < \deg \kbd{z[1]}$. However, \kbd{z[2]} is allowed to be a simplification of such a polynomial, e.g.~a scalar. This is tricky considering the hierarchical structure of the variables; in particular, a polynomial in variable of \emph{lesser} priority (see \secref{se:vars}) than the modulus variable is valid, since it is considered as the constant term of a polynomial of degree 0 in the correct variable. On the other hand a variable of \emph{greater} priority is not acceptable. \subsec{Type \typ{POL} (polynomial)}\kbdsidx{t_POL}\sidx{polynomial} this type has a second codeword. It contains a ``\emph{sign}'': 0 if the polynomial is equal to~0, and 1 if not (see however the important remark below) and a \emph{variable number} (e.g.~0 for $x$, 1 for $y$, etc\dots). \noindent These data can be handled with the following macros: \teb{signe} and \teb{setsigne} as for \typ{INT} and \typ{REAL}, \fun{long}{varn}{GEN z} returns the variable number of the object \kbd{z}, \fun{void}{setvarn}{GEN z, long v} sets the variable number of \kbd{z} to \kbd{v}. The variable numbers encode the relative priorities of variables, we will give more details in \secref{se:vars}. Note also the function \fun{long}{gvar}{GEN z} which tries to return a \idx{variable number} for \kbd{z}, even if \kbd{z} is not a polynomial or power series. The variable number of a scalar type is set by definition equal to \tet{NO_VARIABLE}, which has lower priority than any other variable number. The components \kbd{z[2]}, \kbd{z[3]},\dots \kbd{z[lg(z)-1]} point to the coefficients of the polynomial \emph{in ascending order}, with \kbd{z[2]} being the constant term and so on. For a \typ{POL} of nonzero sign, \tet{degpol}, \tet{leading_coeff}, \tet{constant_coeff}, return its degree, and a pointer to the leading, resp. constant, coefficient with respect to the main variable. Note that no copy is made on the PARI stack so the returned value is not safe for a basic \kbd{gerepile} call. Applied to any other type than \typ{POL}, the result is unspecified. Those three functions are still defined when the sign is $0$, see \secref{se:accessors} and \secref{se:polynomials}. \fun{long}{degree}{GEN x} returns the degree of \kbd{x} with respect to its main variable even when \kbd{x} is not a polynomial (a rational function for instance). By convention, the degree of a zero polynomial is~$-1$. \misctitle{Important remark} The leading coefficient of a \typ{POL} may be equal to zero: \item it is not allowed to be an exact rational $0$, such as \tet{gen_0}; \item an exact nonrational $0$, like \kbd{Mod(0,2)}, is possible for constant polynomials, i.e. of length $3$ and no other coefficient: this carries information about the base ring for the polynomial; \item an inexact $0$, like \kbd{0.E-38} or \kbd{O(3\pow 5)}, is always possible. Inexact zeroes do not correspond to an actual $0$, but to a very small coefficient according to some metric; we keep them to give information on how much cancellation occurred in previous computations. A polynomial disobeying any of these rules is an invalid \emph{unnormalized} object. We advise \emph{not} to use low-level constructions to build a \typ{POL} coefficient by coefficient, such as \bprog GEN T = cgetg(4, t_POL); T[1] = evalvarn(0); gel(T, 2) = x; gel(T, 3) = y; @eprog\noindent But if you do and it is not clear whether the result will be normalized, call \fun{GEN}{normalizepol}{GEN x} applied to an unnormalized \typ{POL}~\kbd{x} (with all coefficients correctly set except that \kbd{leading\_term(x)} might be zero), normalizes \kbd{x} correctly in place and returns~\kbd{x}. This functions sets \kbd{signe} (to $0$ or $1$) properly. \misctitle{Caveat} A consequence of the remark above is that zero polynomials are characterized by the fact that their sign is~0. It is in general incorrect to check whether \kbd{lg(x)} is $2$ or \kbd{degpol(x)} $< 0$, although both tests are valid when the coefficient types are under control: for instance, when they are guaranteed to be \typ{INT}s or \typ{FRAC}s. The same remark applies to \typ{SER}s. \subsec{Type \typ{SER} (power series)} \kbdsidx{t_SER}\sidx{power series}This type also has a second codeword, which encodes a ``\emph{sign}'', i.e.~0 if the power series is 0, and 1 if not, a \emph{variable number} as for polynomials, and an \emph{exponent}. This information can be handled with the following functions: \teb{signe}, \teb{setsigne}, \teb{varn}, \teb{setvarn} as for polynomials. Beware: do \emph{not} use \teb{expo} and \teb{setexpo} on power series. \fun{long}{valser}{GEN z} returns the valuation of \kbd{z} This is defined even if \kbd{z} is equal to~0. \fun{void}{setvalser}{GEN z, long e} sets the valuation of \kbd{z} to \kbd{e}. The coefficients \kbd{z[2]}, \kbd{z[3]},\dots \kbd{z[lg(z)-1]} point to the coefficients of \kbd{z} in ascending order. As for polynomials (see remark there), the sign of a \typ{SER} is $0$ if and only all its coefficients are equal to $0$. (The leading coefficient cannot be an integer $0$.) A series whose coefficients are integers equal to zero is represented as $O(x^n)$ (\kbd{zeroser}$(\var{vx},n)$). A series whose coefficients are exact zeroes, but not all of them integers (e.g. an \typ{INTMOD} such as \kbd{Mod(0,2)}) is represented as $z*x^{n-1} +O(x^n)$, where $z$ is the $0$ of the base ring, as per \tet{Rg_get_0}. Note that the exponent of a power series can be negative, i.e.~we are then dealing with a Laurent series (with a finite number of negative terms). \subsec{Type \typ{RFRAC} (rational function)}% \kbdsidx{t_RFRAC}\sidx{rational function} \kbd{z[1]} points to the numerator $n$, and \kbd{z[2]} on the denominator $d$. The denominator must be of type \typ{POL}, with variable of priority at least as high as that of the numerator. The numerator $n$ is not an exact $0$ and $(n,d) = 1$ (see \tet{gred_rfac2}). \subsec{Type \typ{QFB} (binary quadratic form)}% \kbdsidx{t_QFB}\sidx{binary quadratic form} \kbd{z[1]}, \kbd{z[2]}, \kbd{z[3]} point to the three coefficients of the form, and \kbd{z[4]} point to the form discriminant. All four are of type \typ{INT}. \subsec{Type \typ{VEC} and \typ{COL} (vector)}% \kbdsidx{t_VEC}\kbdsidx{t_COL}\sidx{row vector}\sidx{column vector} \kbd{z[1]}, \kbd{z[2]},\dots \kbd{z[lg(z)-1]} point to the components of the vector. \subsec{Type \typ{MAT} (matrix)}\kbdsidx{t_MAT}\sidx{matrix} \kbd{z[1]}, \kbd{z[2]},\dots \kbd{z[lg(z)-1]} point to the column vectors of \kbd{z}, i.e.~they must be of type \typ{COL} and of the same length. \subsec{Type \typ{VECSMALL} (vector of small integers)}\kbdsidx{t_VECSMALL} \kbd{z[1]}, \kbd{z[2]},\dots \kbd{z[lg(z)-1]} are ordinary signed long integers. This type is used instead of a \typ{VEC} of \typ{INT}s for efficiency reasons, for instance to implement efficiently permutations, polynomial arithmetic and linear algebra over small finite fields, etc. \subsec{Type \typ{STR} (character string)}% \kbdsidx{t_STR}\sidx{character string} \fun{char *}{GSTR}{z} (= \kbd{(z+1)}) points to the first character of the (\kbd{NULL}-terminated) string. \subsec{Type \typ{ERROR} (error context)}\kbdsidx{t_ERROR} This type holds error messages, as well as details about the error, as returned by the exception handling system. The second codeword \kbd{z[1]} contains the error type (an \kbd{int}, as passed to \tet{pari_err}). The subsequent words \kbd{z[2]},\dots \kbd{z[lg(z)-1]} are \kbd{GEN}s containing additional data, depending on the error type.\sidx{error context} \subsec{Type \typ{CLOSURE} (closure)}\kbdsidx{t_CLOSURE}\sidx{closure} This type holds GP functions and closures, in compiled form. The internal detail of this type is subject to change each time the GP language evolves. Hence we do not describe it here and refer to the Developer's Guide. However functions to create or to evaluate \typ{CLOSURE}s are documented in \secref{se:closure}. \fun{long}{closure_arity}{GEN C} returns the arity of the \typ{CLOSURE}. \fun{long}{closure_is_variadic}{GEN C} returns $1$ if the closure \kbd{C} is variadic, $0$ else. \subsec{Type \typ{INFINITY} (infinity)}\kbdsidx{t_INFINITY}\sidx{infinity} This type has a single \typ{INT} component, which is either $1$ or $-1$, corresponding to $+\infty$ and $-\infty$ respectively. \fun{GEN}{mkmoo}{} returns $-\infty$ \fun{GEN}{mkoo}{} returns $\infty$ \fun{long}{inf_get_sign}{GEN x} returns $1$ if $x$ is $+\infty$, and $-1$ if $x$ is $-\infty$. \subsec{Type \typ{LIST} (list)}\kbdsidx{t_LIST}\sidx{list} this type was introduced for specific \kbd{gp} use and is rather inefficient compared to a straightforward linked list implementation (it requires more memory, as well as many unnecessary copies). Hence we do not describe it here and refer to the Developer's Guide. \misctitle{Implementation note} For the types including an exponent (or a valuation), we actually store a biased nonnegative exponent (bit-ORing the biased exponent to the codeword), obtained by adding a constant to the true exponent: either \kbd{HIGHEXPOBIT} (for \typ{REAL}) or \kbd{HIGHVALPBIT} (for \typ{PADIC} and \typ{SER}). Of course, this is encapsulated by the exponent/valuation-handling macros and needs not concern the library user. \section{PARI variables}\label{se:vars} \subsec{Multivariate objects} \sidx{variable (priority)} \noindent We now consider variables and formal computations. As we have seen in \secref{se:impl}, the codewords for types \typ{POL} and \typ{SER} encode a ``variable number''. This is an integer, ranging from $0$ to \kbd{MAXVARN}. Relative priorities may be ascertained using \fun{int}{varncmp}{long v, long w} \noindent which is $>0$, $=0$, $<0$ whenever $v$ has lower, resp.~same, resp.~higher priority than $w$. The way an object is considered in formal computations depends entirely on its ``principal variable number'' which is given by the function \fun{long}{gvar}{GEN z} \noindent which returns a \idx{variable number} for \kbd{z}, even if \kbd{z} is not a polynomial or power series. The variable number of a scalar type is set by definition equal to \tet{NO_VARIABLE} which has lower priority than any valid variable number. The variable number of a recursive type which is not a polynomial or power series is the variable number with highest priority among its components. But for polynomials and power series only the ``outermost'' number counts (we directly access $\tet{varn}(x)$ in the codewords): the representation is not symmetrical at all. Under \kbd{gp}, one needs not worry too much since the interpreter defines the variables as it sees them\footnote{*}{The first time a given identifier is read by the GP parser a new variable is created, and it is assigned a strictly lower priority than any variable in use at this point. On startup, before any user input has taken place, 'x' is defined in this way and has initially maximal priority (and variable number $0$).} % and do the right thing with the polynomials produced. But in library mode, they are tricky objects if you intend to build polynomials yourself (and not just let PARI functions produce them, which is less efficient). For instance, it does not make sense to have a variable number occur in the components of a polynomial whose main variable has a lower priority, even though PARI cannot prevent you from doing it. \subsec{Creating variables} A basic difficulty is to ``create'' a variable. Some initializations are needed before you can use a given integer $v$ as a variable number. Initially, this is done for $0$ and $1$ (the variables \kbd{x} and \kbd{y} under \kbd{gp}), and $2,\dots,9$ (printed as \kbd{t2}, \dots \kbd{t9}), with decreasing priority. \subsubsec{User variables}\sidx{variable (user)} When the program starts, \kbd{x} (number~$0$) and \kbd{y} (number~$1$) are the only available variables, numbers $2$ to $9$ (decreasing priority) are reserved for building polynomials with predictable priorities. To define further ones, you may use \fun{GEN}{varhigher}{const char *s} \fun{GEN}{varlower}{const char *s} to recover a monomial of degree $1$ in a new variable, which is guaranteed to have higer (resp.~lower) priority than all existing ones at the time of the function call. The variable is printed as $s$, but is not part of GP's interpreter: it is not a symbol bound to a value. On the other hand \fun{long}{fetch_user_var}{char *s}: inspects the user variable whose name is the string pointed to by \kbd{s}, creating it if needed, and returns its variable number. \bprog long v = fetch_user_var("y"); GEN gy = pol_x(v); @eprog\noindent The function raises an exception if the name is already in use for an \tet{install}ed or built-in function, or an alias. This function is mostly useless since it returns a variable with unpredictable priority. Don't use it to create new variables. \misctitle{Caveat} You can use \tet{gp_read_str} (see~\secref{se:gp_read_str}) to execute a GP command and create GP variables on the fly as needed: \bprog GEN gy = gp_read_str("'y"); /*@Ccom returns \kbd{pol\_x}($v$), for some $v$ */ long v = varn(gy); @eprog\noindent But please note the quote \kbd{'y} in the above. Using \kbd{gp\_read\_str("y")} might work, but is dangerous, especially when programming functions to be used under \kbd{gp}. The latter reads the value of \kbd{y}, as \emph{currently} known by the \kbd{gp} interpreter, possibly creating it in the process. But if \kbd{y} has been modified by previous \kbd{gp} commands (e.g.~\kbd {y = 1}), then the value of \kbd{gy} is not what you expected it to be and corresponds instead to the current value of the \kbd{gp} variable (e.g.~\kbd{gen\_1}). \fun{GEN}{fetch_var_value}{long v} returns a shallow copy of the current value of the variable numbered $v$. Returns \kbd{NULL} if that variable number is unknown to the interpreter, e.g. it is a user variable. Note that this may not be the same as \kbd{pol\_x(v)} if assignments have been performed in the interpreter. \subsubsec{Temporary variables}\sidx{variable (temporary)} You can create temporary variables using \fun{long}{fetch_var}{} returns a new variable with \emph{lower} priority than any variable currently in use. \fun{long}{fetch_var_higher}{} returns a new variable with \emph{higher} priority than any variable currently in use. \noindent After the statement \kbd{v = fetch\_var()}, you can use \kbd{pol\_1(v)} and \kbd{pol\_x(v)}. The variables created in this way have no identifier assigned to them though, and are printed as \kbd{t\text{number}}. You can assign a name to a temporary variable, after creating it, by calling the function \fun{void}{name_var}{long n, char *s} \noindent after which the output machinery will use the name \kbd{s} to represent the variable number~\kbd{n}. The GP parser will \emph{not} recognize it by that name, however, and calling this on a variable known to~\kbd{gp} raises an error. Temporary variables are meant to be used as free variables to build polynomials and power series, and you should never assign values or functions to them as you would do with variables under~\kbd{gp}. For that, you need a user variable. All objects created by \kbd{fetch\_var} are on the heap and not on the stack, thus they are not subject to standard garbage collecting (they are not destroyed by a \kbd{gerepile} or \kbd{set\_avma(ltop)} statement). When you do not need a variable number anymore, you can delete it using \fun{long}{delete_var}{} \noindent which deletes the \emph{latest} temporary variable created and returns the variable number of the previous one (or simply returns 0 if none remain). Of course you should make sure that the deleted variable does not appear anywhere in the objects you use later on. Here is an example: \bprog long first = fetch_var(); long n1 = fetch_var(); long n2 = fetch_var(); /*@Ccom prepare three variables for internal use */ ... /*@Ccom delete all variables before leaving */ do { num = delete_var(); } while (num && num <= first); @eprog\noindent The (dangerous) statement \bprog while (delete_var()) /*@Ccom empty */; @eprog\noindent removes all temporary variables in use. \subsec{Comparing variables} Let us go back to \kbd{varncmp}. There is an interesting corner case, when one of the compared variables (from \kbd{gvar}, say) is \kbd{NO\_VARIABLE}. In this case, \kbd{varncmp} declares it has lower priority than any other variable; of course, comparing \kbd{NO\_VARIABLE} with itself yields $0$ (same priority); In addition to \kbd{varncmp} we have \fun{long}{varnmax}{long v, long w} given two variable numbers (possibly \kbd{NO\_VARIABLE}), returns the variable with the highest priority. This function always returns a valid variable number unless it is comparing \kbd{NO\_VARIABLE} to itself. \fun{long}{varnmin}{long x, long y} given two variable numbers (possibly \kbd{NO\_VARIABLE}), returns the variable with the lowest priority. Note that when comparing a true variable with \kbd{NO\_VARIABLE}, this function returns \kbd{NO\_VARIABLE}, which is not a valid variable number. \section{Input and output} \noindent Two important aspects have not yet been explained which are specific to library mode: input and output of PARI objects. \subsec{Input} \noindent For \idx{input}, PARI provides several powerful high level functions which enable you to input your objects as if you were under \kbd{gp}. In fact, it \emph{is} essentially the GP syntactical parser. There are two similar functions available to parse a string: \fun{GEN}{gp_read_str}{const char *s}\label{se:gp_read_str} \fun{GEN}{gp_read_str_multiline}{const char *s, char *last} \noindent Both functions read the whole string \kbd{s}. The function \kbd{gp\_read\_str} ignores newlines: it assumes that the input is one expression and returns the result of this expression. The function \kbd{gp\_read\_str\_multiline} processes the text in the same way as the GP command \tet{read}: newlines are significant and can be used to separate expressions. The return value is that of the last nonempty expression evaluated. In \kbd{gp\_read\_str\_multiline}, if \kbd{last} is not \kbd{NULL}, then \kbd{*last} receives the last character from the \emph{filtered} input: this can be used to check if the last character was a semi-colon (to hide the output in interactive usage). If (and only if) the input contains no statements, then \kbd{*last} is set to \kbd{0}. For both functions, \kbd{gp}'s metacommands \emph{are} recognized. Two variants allow to specify a default precision while evaluating the string: \fun{GEN}{gp_read_str_prec}{const char *s, long prec} As \kbd{gp\_read\_str}, but set the precision to \kbd{prec} words while evaluating $s$. \fun{GEN}{gp_read_str_bitprec}{const char *s, long bitprec} identical to \kbd{gp\_read\_str\_prec}. DEPRECATED. \misctitle{Note} The obsolete form \fun{GEN}{readseq}{char *t} still exists for backward compatibility (assumes filtered input, without spaces or comments). Don't use it. To read a \kbd{GEN} from a file, you can use the simpler interface \fun{GEN}{gp_read_stream}{FILE *file} \noindent which reads a character string of arbitrary length from the stream \kbd{file} (up to the first complete expression sequence), applies \kbd{gp\_read\_str} to it, and returns the resulting \kbd{GEN}. This way, you do not have to worry about allocating buffers to hold the string. To interactively input an expression, use \kbd{gp\_read\_stream(stdin)}. Return \kbd{NULL} when there are no more expressions to read (we reached EOF). Finally, you can read in a whole file, as in GP's \tet{read} statement \fun{GEN}{gp_read_file}{char *name} \noindent As usual, the return value is that of the last nonempty expression evaluated. There is one technical exception: if \kbd{name} is a \emph{binary} file (from \tet{writebin}) containing more than one object, a \typ{VEC} containing them all is returned. This is because binary objects bypass the parser, hence reading them has no useful side effect. \subsec{Output to screen or file, output to string}\sidx{output} General output functions return nothing but print a character string as a side effect. Low level routines are available to write on PARI output stream \tet{pari_outfile} (\tet{stdout} by default): \fun{void}{pari_putc}{char c}: write character \kbd{c} to the output stream. \fun{void}{pari_puts}{char *s}: write \kbd{s} to the output stream. \fun{void}{pari_flush}{}: flush output stream; most streams are buffered by default, this command makes sure that all characters output so are actually written. \fun{void}{pari_printf}{const char *fmt, ...}: the most versatile such function. \kbd{fmt} is a character string similar to the one \tet{printf} uses. In there, \kbd{\%} characters have a special meaning, and describe how to print the remaining operands. In addition to the standard format types (see the GP function \tet{printf}), you can use the \emph{length modifier}~\kbd{P} (for PARI of course!) to specify that an argument is a \kbd{GEN}. For instance, the following are valid conversions for a \kbd{GEN} argument \bprog %Ps @com convert to \kbd{char*} (will print an arbitrary \kbd{GEN}) %P.10s @com convert to \kbd{char*}, truncated to 10 chars %P.2f @com convert to floating point format with 2 decimals %P4d @com convert to integer, field width at least 4 pari_printf("x[%d] = %Ps is not invertible!\n", i, gel(x,i)); @eprog\noindent Here \kbd{i} is an \kbd{int}, \kbd{x} a \kbd{GEN} which is not a leaf (presumably a vector, or a polynomial) and this would insert the value of its $i$-th \kbd{GEN} component: \kbd{gel(x,i)}. \noindent Simple but useful variants to \kbd{pari\_printf} are \fun{void}{output}{GEN x} prints \kbd{x} in raw format, followed by a newline and a buffer flush. This is more or less equivalent to \bprog pari_printf("%Ps\n", x); pari_flush(); @eprog \fun{void}{outmat}{GEN x} as above except if $x$ is a \typ{MAT}, in which case a multi-line display is used to display the matrix. This is prettier for small dimensions, but quickly becomes unreadable and cannot be pasted and reused for input. If all entries of $x$ are small integers, you may use the recursive features of \kbd{\%Pd} and obtain the same (or better) effect with \bprog pari_printf("%Pd\n", x); pari_flush(); @eprog\noindent A variant like \kbd{"\%5Pd"} would improve alignment by imposing 5 chars for each coefficient. Similarly if all entries are to be converted to floats, a format like \kbd{"\%5.1Pf"} could be useful. These functions write on (PARI's idea of) standard output, and must be used if you want your functions to interact nicely with \kbd{gp}. In most programs, this is not a concern and it is more flexible to write to an explicit \kbd{FILE*}, or to recover a character string: \fun{void}{pari_fprintf}{FILE *file, const char *fmt, ...} writes the remaining arguments to stream \kbd{file} according to the format specification \kbd{fmt}. \fun{char*}{pari_sprintf}{const char *fmt, ...} produces a string from the remaining arguments, according to the PARI format \kbd{fmt} (see \tet{printf}). This is the \kbd{libpari} equivalent of \tet{strprintf}, and returns a \kbd{malloc}'ed string, which must be freed by the caller. Note that contrary to the analogous \tet{sprintf} in the \kbd{libc} you do not provide a buffer (leading to all kinds of buffer overflow concerns); the function provided is actually closer to the GNU extension \kbd{asprintf}, although the latter has a different interface. Simple variants of \tet{pari_sprintf} convert a \kbd{GEN} to a \kbd{malloc}'ed ASCII string, which you must still \kbd{free} after use: \fun{char*}{GENtostr}{GEN x}, using the current default output format (\kbd{prettymat} by default). \fun{char*}{GENtoTeXstr}{GEN x}, suitable for inclusion in a \TeX\ file. Note that we have \tet{va_list} analogs of the functions of \kbd{printf} type seen so far: \fun{void}{pari_vprintf}{const char *fmt, va_list ap} \fun{void}{pari_vfprintf}{FILE *file, const char *fmt, va_list ap} \fun{char*}{pari_vsprintf}{const char *fmt, va_list ap} \subsec{Errors}\sidx{error}\kbdsidx{e_MISC} \noindent If you want your functions to issue error messages, you can use the general error handling routine \tet{pari_err}. The basic syntax is % \bprog pari_err(e_MISC, "error message"); @eprog\noindent This prints the corresponding error message and exits the program (in library mode; go back to the \kbd{gp} prompt otherwise).\label{se:err} You can also use it in the more versatile guise \bprog pari_err(e_MISC, format, ...); @eprog\noindent where \kbd{format} describes the format to use to write the remaining operands, as in the \tet{pari_printf} function. For instance: \bprog pari_err(e_MISC, "x[%d] = %Ps is not invertible!", i, gel(x,i)); @eprog\noindent The simple syntax seen above is just a special case with a constant format and no remaining arguments. The general syntax is \fun{void}{pari_err}{numerr,...} \noindent where \kbd{numerr} is a codeword which specifies the error class and what to do with the remaining arguments and what message to print. For instance, if $x$ is a \kbd{GEN} with internal type \typ{STR}, say, \kbd{pari\_err(e\_TYPE,"extgcd", $x$)} prints the message: \bprog *** incorrect type in extgcd (t_STR), @eprog\noindent See \secref{se:errors} for details. In the libpari code itself, the general-purpose \kbd{e\_MISC} is used sparingly: it is so flexible that the corresponding error contexts (\typ{ERROR}) become hard to use reliably. Other more rigid error types are generally more useful: for instance the error context attached to the \kbd{e\_TYPE} exception above is precisely documented and contains \kbd{"extgcd"} and $x$ (not only its type) as readily available components. \subsec{Warnings} \noindent To issue a warning, use \fun{void}{pari_warn}{warnerr,...} In that case, of course, we do \emph{not} abort the computation, just print the requested message and go on. The basic example is % \bprog pari_warn(warner, "Strategy 1 failed. Trying strategy 2") @eprog\noindent which is the exact equivalent of \kbd{pari\_err(e\_MISC,...)} except that you certainly do not want to stop the program at this point, just inform the user that something important has occurred; in particular, this output would be suitably highlighted under \kbd{gp}, whereas a simple \kbd{printf} would not. The valid \emph{warning} keywords are \tet{warner} (general), \tet{warnprec} (increasing precision), \tet{warnmem} (garbage collecting) and \tet{warnfile} (error in file operation), used as follows: \bprog pari_warn(warnprec, "bnfinit", newprec); pari_warn(warnmem, "bnfinit"); pari_warn(warnfile, "close", "afile"); /* error when closing "afile" */ @eprog \subsec{Debugging output}\sidx{debugging}\sidx{format}\label{se:dbg_output} For debugging output, you can use the standard output functions, \tet{output} and \tet{pari_printf} mainly. Corresponding to the \kbd{gp} metacommand \kbd{\b x}, you can also output the \idx{hexadecimal tree} attached to an object: \fun{void}{dbgGEN}{GEN x, long nb = -1}, displays the recursive structure of \kbd{x}. If $\kbd{nb} = -1$, the full structure is printed, otherwise the leaves (nonrecursive components) are truncated to \kbd{nb} words. \noindent The function \tet{output} is vital under debuggers, since none of them knows how to print PARI objects by default. Seasoned PARI developers add the following \kbd{gdb} macro to their \kbd{.gdbinit}: \bprog define oo call output((GEN)$arg0) end define xx call dbgGEN($arg0,-1) end @eprog\noindent Typing \kbd{i x} at a breakpoint in \kbd{gdb} then prints the value of the \kbd{GEN} \kbd{x} (provided the optimizer has not put it into a register, but it is rarely a good idea to debug optimized code). \noindent The global variables \teb{DEBUGLEVEL} and \teb{DEBUGMEM} (corresponding to the default \teb{debug} and \teb{debugmem}) are used throughout the PARI code to govern the amount of diagnostic and debugging output, depending on their values. You can use them to debug your own functions, especially if you \tet{install} the latter under \kbd{gp}. Note that \kbd{DEBUGLEVEL} is redefined in each code module, attaching it to a particular debug domain (see \kbd{setdebug}). \fun{void}{setalldebug}{long L} sets all \kbd{DEBUGLEVEL} incarnations (all debug domains) to $L$. \fun{void}{dbg_pari_heap}{void} print debugging statements about the PARI stack, heap, and number of variables used. Corresponds to \kbd{\bs s} under gp. \subsec{Timers and timing output} \noindent To handle timings in a reentrant way, PARI defines a dedicated data type, \tet{pari_timer}, together with the following methods: \fun{void}{timer_start}{pari_timer *T} start (or reset) a timer. \fun{long}{timer_delay}{pari_timer *T} returns the number of milliseconds elapsed since the timer was last reset. Resets the timer as a side effect. Assume $T$ was started by \kbd{timer\_start}. \fun{long}{timer_get}{pari_timer *T} returns the number of milliseconds elapsed since the timer was last reset. Does \emph{not} reset the timer. Assume $T$ was started by \kbd{timer\_start}. \fun{void}{walltimer_start}{pari_timer *T} start a timer, as if it had been started at the Unix epoch (see \kbd{getwalltime}). \fun{long}{walltimer_delay}{pari_timer *T} returns the number of milliseconds elapsed since the timer was last checked. Assume $T$ was started by \kbd{walltimer\_start}. \fun{long}{walltimer_get}{pari_timer *T} returns the number of milliseconds elapsed since the timer was last reset. Does \emph{not} reset the timer. Assume $T$ was started by \kbd{walltimer\_start}. \fun{long}{timer_printf}{pari_timer *T, char *format,...} This diagnostics function is equivalent to the following code \bprog err_printf("Time ") ... prints remaining arguments according to format ... err_printf(": %ld", timer_delay(T)); @eprog\noindent Resets the timer as a side effect. \noindent They are used as follows: \bprog pari_timer T; timer_start(&T); /* initialize timer */ ... printf("Total time: %ldms\n", timer_delay(&T)); @eprog\noindent or \bprog pari_timer T; timer_start(&T); for (i = 1; i < 10; i++) { ... timer_printf(&T, "for i = %ld (L[i] = %Ps)", i, gel(L,i)); } @eprog The following functions provided the same functionality, in a nonreentrant way, and are now deprecated. \fun{long}{timer}{void} \fun{long}{timer2}{void} \fun{void}{msgtimer}{const char *format, ...} The following function implements \kbd{gp}'s timer and should not be used in libpari programs: \fun{long}{gettime}{void} equivalent to \tet{timer_delay}$(T)$ attached to a private timer $T$. \section{Iterators, Numerical integration, Sums, Products} \subsec{Iterators} Since it is easier to program directly simple loops in library mode, some GP iterators are mainly useful for GP programming. Here are the others: \item \tet{fordiv} is a trivial iteration over a list produced by \tet{divisors}. \item \tet{forell}, \tet{forqfvec} and \tet{forsubgroup} are currently not implemented as an iterator but as a procedure with callbacks. \fun{void}{forell}{void *E, long fun(void*, GEN), GEN a, GEN b, long flag} goes through the same curves as \tet{forell(ell,a,b,,flag)}, calling \tet{fun(E, ell)} for each curve \kbd{ell}, stopping if \kbd{fun} returns a nonzero value. \fun{void}{forqfvec}{void *E, long (*fun)(void *, GEN, GEN, double), GEN q, GEN b}: Evaluate \kbd{fun(E,U,v,m)} on all $v$ such that $q(U\*v) b$, for instance). They allocate the \tet{forprime_t} data structure on the PARI stack. \noindent The successive primes are then obtained using \fun{GEN}{forprime_next}{forprime_t *T}, returns \kbd{NULL} if no more primes are available in the interval and the next suitable prime as a \typ{INT} otherwise. \fun{ulong}{u_forprime_next}{forprime_t *T}, returns $0$ if no more primes are available in the interval and fitting in an \kbd{ulong} and the next suitable prime otherwise. These two functions leave alone the PARI stack, and write their state information in the preallocated \tet{forprime_t} struct. The typical usage is thus: \bprog forprime_t T; GEN p; pari_sp av = avma, av2; forprime_init(&T, gen_2, stoi(1000)); av2 = avma; while ( (p = forprime_next(&T)) ) { ... if ( prime_is_OK(p) ) break; set_avma(av2); /* delete garbage accumulated in this iteration */ } set_avma(av); /* delete all */ @eprog\noindent Of course, the final \kbd{set\_avma(av)} could be replaced by a \kbd{gerepile} call. Beware that swapping the \kbd{av2 = avma} and \tet{forprime_init} call would be incorrect: the first \kbd{set\_avma(av2)} would delete the \tet{forprime_t} structure! \subsec{Parallel iterators} Theses iterators loops over the values of a \typ{CLOSURE} taken at some data, where the evaluations are done in parallel. \item \tet{parfor}. To initialize the analog of \kbd{parfor(i = a, b, ...)}, call \fun{void}{parfor_init}{parfor_t *T, GEN a, GEN b, GEN code} initialize an iterator over the evaluation of \kbd{code} on the integers between $a$ and $b$. \fun{GEN}{parfor_next}{parfor_t *T} returns a \typ{VEC} \kbd{[i,code(i)]} where $i$ is one of the integers and \kbd{code(i)} is the evaluation, \kbd{NULL} when all data have been exhausted. Once it happens, \kbd{parfor\_next} must not be called anymore with the same initialization. \fun{void}{parfor_stop}{parfor_t *T} needs to be called when leaving the iterator before \kbd{parfor\_next} returned \kbd{NULL}. The following returns an integer $1\leq i\leq N$ such that \kbd{fun(i)} is not zero, or \kbd{NULL}. \bprog GEN parfirst(GEN fun, GEN N) { parfor_t T; GEN e; parfor_init(&T, gen_1, N, fun); while ((e = parfor_next(&T))) { GEN i = gel(e,1), funi = gel(e,2); if (!gequal0(funi)) { /* found: stop the iterator and return the index */ parfor_stop(&T); return i; } } return NULL; /* not found */ } @eprog \item \tet{parforeach}. To initialize the analog of \kbd{parforeach(V, X, ...)}, call \fun{void}{parforeach_init}{parforeach_t *T, GEN V, GEN code} initialize an iterator over the evaluation of \kbd{code} on the components of $V$. \fun{GEN}{parforeach_next}{parforeach_t *T} returns a \typ{VEC} \kbd{[V[i],code(V[i])]} where $V[i]$ is one of the components of $V$ and \kbd{code(V[i])} is the evaluation, \kbd{NULL} when all data have been exhausted. Once it happens, \kbd{parforprime\_next} must not be called anymore with the same initialization. \fun{void}{parforeach_stop}{parforeach_t *T} needs to be called when leaving the iterator before \kbd{parforeach\_next} returned \kbd{NULL}. \item \tet{parforstep}. To initialize the analog of \kbd{parforstep(i = a, b, s, ...)}, call \fun{void}{parforstep_init}{parforstep_t *T, GEN a, GEN b, GEN s, GEN code} initialize an iterator over the evaluation of \kbd{code} between $a$ and $b$, with steps $s$ (see \kbd{forstep} documentation for the possibilities for $s$). \fun{GEN}{parforstep_next}{parforstep_t *T} returns a \typ{VEC} \kbd{[x,code(x)]} where $x$ is one of the evaluation points and \kbd{code(x)} is the evaluation, \kbd{NULL} when all data have been exhausted. Once it happens, \kbd{parforstep\_next} must not be called anymore with the same initialization. \fun{void}{parforstep_stop}{parforstep_t *T} needs to be called when leaving the iterator before \kbd{parforstep\_next} returned \kbd{NULL}. \item \tet{parforprime}. To initialize the analog of \kbd{parforprime(p = a, b, ...)}, call \fun{void}{parforprime_init}{parforprime_t *T, GEN a, GEN b, GEN code} initialize an iterator over the evaluation of \kbd{code} on the prime numbers between $a$ and $b$. \item \tet{parforprimestep}. To initialize the analog of \kbd{parforprimestep(p = a, b, q, ...)}, call \fun{void}{parforprimestep_init}{parforprime_t *T, GEN a, GEN b, GEN q, GEN code} initialize an iterator over the evaluation of \kbd{code} on the prime numbers between $a$ and $b$ in the congruence class defined by $q$. \fun{GEN}{parforprime_next}{parforprime_t *T} returns a \typ{VEC} \kbd{[p,code(p)]} where $p$ is one of the prime numbers and \kbd{code(p)} is the evaluation, \kbd{NULL} when all data have been exhausted. Once it happens, \kbd{parforprime\_next} must not be called anymore with the same initialization. \fun{void}{parforprime_stop}{parforprime_t *T} needs to be called when leaving the iterator before \kbd{parforprime\_next} returned \kbd{NULL}. \item \tet{parforvec}. To initialize the analog of \kbd{parforvec(X = V, ..., flag)}, call \fun{void}{parforvec_init}{parforvec_t *T, GEN V, GEN code, long flag} initialize an iterator over the evaluation of \kbd{code} on the vectors specified by \kbd{V} and \kbd{flag}, see \kbd{forvec} for detail. \fun{GEN}{parforvec_next}{parforvec_t *T} returns a \typ{VEC} \kbd{[v,code(v)]} where $v$ is one of the vectors and \kbd{code(v)} is the evaluation, \kbd{NULL} when all data have been exhausted. Once it happens, \kbd{parforvec\_next} must not be called anymore with the same initialization. \fun{void}{parforvec_stop}{parforvec_t *T} needs to be called when leaving the iterator before \kbd{parforvec\_next} returned \kbd{NULL}. \subsec{Numerical analysis} Numerical routines code a function (to be integrated, summed, zeroed, etc.) with two parameters named \bprog void *E; GEN (*eval)(void*, GEN) @eprog\noindent The second is meant to contain all auxiliary data needed by your function. The first is such that \kbd{eval(x, E)} returns your function evaluated at \kbd{x}. For instance, one may code the family of functions $f_t: x \to (x+t)^2$ via \bprog GEN fun(void *t, GEN x) { return gsqr(gadd(x, (GEN)t)); } @eprog\noindent One can then integrate $f_1$ between $a$ and $b$ with the call \bprog intnum((void*)stoi(1), &fun, a, b, NULL, prec); @eprog\noindent Since you can set \kbd{E} to a pointer to any \kbd{struct} (typecast to \kbd{void*}) the above mechanism handles arbitrary functions. For simple functions without extra parameters, you may set \kbd{E = NULL} and ignore that argument in your function definition. \section{Catching exceptions} \subsec{Basic use} PARI provides a mechanism to trap exceptions generated via \kbd{pari\_err} using the \tet{pari_CATCH} construction. The basic usage is as follows \bprog pari_CATCH(err_code) { @com recovery branch } pari_TRY { @com main branch } pari_ENDCATCH @eprog\noindent This fragment executes the main branch, then the recovery branch \emph{if} exception \kbd{err\_code} is thrown, e.g. \kbd{e\_TYPE}. See \secref{se:errors} for the description of all error classes. The special error code \tet{CATCH_ALL} is available to catch all errors. One can replace the \tet{pari_TRY} keyword by \tet{pari_RETRY}, in which case once the recovery branch is run, we run the main branch again, still catching the same exceptions. \misctitle{Restrictions} \item Such constructs can be nested without adverse effect, the innermost handler catching the exception. \item It is \emph{valid} to leave either branch using \tet{pari_err}. \item It is \emph{invalid} to use C flow control instructions (\kbd{break}, \kbd{continue}, \kbd{return}) to directly leave either branch without seeing the \tet{pari_ENDCATCH} keyword. This would leave an invalid structure in the exception handler stack, and the next exception would crash. \item In order to leave using \kbd{break}, \kbd{continue} or \kbd{return}, one must precede the keyword by a call to \fun{void}{pari_CATCH_reset}{} disable the current handler, allowing to leave without adverse effect. \subsec{Advanced use} In the recovery branch, the exception context can be examined via the following helper routines: \fun{GEN}{pari_err_last}{} returns the exception context, as a \typ{ERROR}. The exception $E$ returned by \tet{pari_err_last} can be rethrown, using \bprog pari_err(0, E); @eprog \fun{long}{err_get_num}{GEN E} returns the error symbolic name. E.g \kbd{e\_TYPE}. \fun{GEN}{err_get_compo}{GEN E, long i} error $i$-th component, as documented in \secref{se:errors}. \noindent For instance \bprog pari_CATCH(CATCH_ALL) { /* catch everything */ GEN x, E = pari_err_last(); long code = err_get_num(E); if (code != e_INV) pari_err(0, E); /* unexpected error, rethrow */ x = err_get_compo(E, 2); /* e_INV has two components, 1: function name 2: noninvertible x */ if (typ(x) != t_INTMOD) pari_err(0, E); /* unexpected type, rethrow */ pari_CATCH_reset(); return x; /* leave ! */ @com @dots } pari_TRY { @com main branch } pari_ENDCATCH @eprog \section{A complete program} \label{se:prog} \noindent Now that the preliminaries are out of the way, the best way to learn how to use the library mode is to study a detailed example. We want to write a program which computes the gcd of two integers, together with the Bezout coefficients. We shall use the standard quadratic algorithm which is not optimal but is not too far from the one used in the PARI function \teb{gcdext}. Let $x,y$ two integers and initially $ \pmatrix{s_x & s_y \cr t_x & t_y } = \pmatrix{1 & 0 \cr 0 & 1}$, so that $$ \pmatrix{s_x & s_y \cr t_x & t_y } \pmatrix{x \cr y } = \pmatrix{x \cr y }. $$ To apply the ordinary Euclidean algorithm to the right hand side, multiply the system from the left by $ \pmatrix{0 & 1 \cr 1 & -q }$, with $q = \kbd{floor}(x / y)$. Iterate until $y = 0$ in the right hand side, then the first line of the system reads $$ s_x x + s_y y = \gcd(x,y).$$ In practice, there is no need to update $s_y$ and $t_y$ since $\gcd(x,y)$ and $s_x$ are enough to recover $s_y$. The following program is now straightforward. A couple of new functions appear in there, whose description can be found in the technical reference manual in Chapter 5, but whose meaning should be clear from their name and the context. This program can be found in \kbd{examples/extgcd.c} together with a proper \kbd{Makefile}. You may ignore the first comment \bprog /* GP;install("extgcd", "GG&&", "gcdex", "./libextgcd.so"); */ @eprog\noindent which instruments the program so that \kbd{gp2c-run extgcd.c} can import the \kbd{extgcd()} routine into an instance of the \kbd{gp} interpreter (under the name \kbd{gcdex}). See the \kbd{gp2c} manual for details. \newpage \bprogfile{../examples/extgcd.c} \noindent For simplicity, the inner loop does not include any garbage collection, hence memory use is quadratic in the size of the inputs instead of linear. Here is a better version of that loop: \bprog pari_sp av = avma; ... while (!gequal0(b)) { GEN r, q = dvmdii(a, b, &r), v = vx; vx = subii(ux, mulii(q, vx)); ux = v; a = b; b = r; if (gc_needed(av,1)) gerepileall(av, 4, &a, &b, &ux, &vx); } @eprog \newpage pari-2.17.2/doc/refcard-lfun.tex0000644000175000017500000001352514567450071015042 0ustar billbill% Copyright (c) 2007-2016 Karim Belabas. % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License % Reference Card for PARI-GP, Algebraic Number Theory. % Author: % Karim Belabas % Universite de Bordeaux, 351 avenue de la Liberation, F-33405 Talence % email: Karim.Belabas@math.u-bordeaux.fr % % See refcard.tex for acknowledgements and thanks. \def\TITLE{L-functions} \input refmacro.tex \section{Characters} A character on the abelian group $G = \sum_{j \leq k} (\ZZ/d_j\ZZ) \cdot g_j$, e.g. from \kbd{znstar(q,1)} $\leftrightarrow (\ZZ/q\ZZ)^*$ or \kbd{bnrinit} $\leftrightarrow \text{Cl}_{\goth{f}}(K)$, is coded by $\chi = [c_1,\dots,c_k]$ such that $\chi(g_j) = e(c_j/d_j)$. Our $L$-functions consider the attached \emph{primitive} character. Dirichlet characters $\chi_q(m,\cdot)$ in Conrey labelling system are alternatively concisely coded by \kbd{Mod(m,q)}. Finally, a quadratic character $(D/\cdot)$ can also be coded by the integer $D$. \section{L-function Constructors} An \kbd{Ldata} is a GP structure describing the functional equation for $L(s) = \sum_{n\geq 1} a_n n^{-s}$. \item Dirichlet coefficients given by closure $a: N \mapsto [a_1,\dots,a_N]$. \item Dirichlet coefficients $a^*(n)$ for dual $L$-function $L^*$. \item Euler factor $A = [a_1,\dots,a_d]$ for $\gamma_A(s) = \prod_i \Gamma_{\RR}(s + a_i)$, \item classical weight $k$ (values at $s$ and $k-s$ are related), \item conductor $N$, $\Lambda(s) = N^{s/2} \gamma_A(s)$, \item root number $\varepsilon$; $\Lambda(a,k-s) = \varepsilon \Lambda(a^*,s)$. \item polar part: list of $[\beta,P_\beta(x)]$. \medskip An \kbd{Linit} is a GP structure containing an \kbd{Ldata} $L$ and an evaluation \emph{domain} fixing a maximal order of derivation $m$ and bit accuracy (\kbd{realbitprecision}), together with complex ranges \item for $L$-function: $R=[c,w,h]$ (coding $|\Re z - c| \leq w$, $|\Im z| \leq h$); or $R = [w,h]$ (for $c = k/2$); or $R = [h]$ (for $c = k/2$, $w = 0$). \item for $\theta$-function: $T=[\rho,\alpha]$ (for $|t|\geq \rho$, $|\arg t| \leq \alpha$); or $T = \rho$ (for $\alpha = 0$). \subsec{Ldata constructors} \li{Riemann $\zeta$}{lfuncreate$(1)$} \li{Dirichlet for quadratic char.~$(D/\cdot)$}{lfuncreate$(D)$} \li{Dirichlet series $L(\chi_q(m,\cdot),s)$}{lfuncreate(Mod(m,q))} \li{Dedekind $\zeta_K$, $K = \QQ[x]/(T)$} {lfuncreate$(\var{bnf})${\rm, }lfuncreate$(T)$} \li{Hecke for $\chi$ mod $\goth{f}$}{lfuncreate$([\var{bnr},\chi])$} \li{Artin $L$-function}{lfunartin$(\var{nf},\var{gal},M,n)$} \li{Lattice $\Theta$-function}{lfunqf$(Q)$} \li{From eigenform $F$}{lfunmf$(F)$} \li{Quotients of Dedekind $\eta$: $\prod_i \eta(m_{i,1}\cdot\tau)^{m_{i,2}}$} {lfunetaquo$(M)$} \li{$L(E,s)$, $E$ elliptic curve}{E = ellinit(\dots)} \li{$L(Sym^m E,s)$, $E$ elliptic curve}{lfunsympow(E, m)} \li{Genus $2$ curve, $y^2+xQ = P$}{lfungenus2$([P,Q])$} \li{Hypergeometric motive $H(a,b; t)$}{lfunhgm(hgminit(a,b), t)} \smallskip \li{dual $L$ function $\hat{L}$}{lfundual$(L)$} \li{$L_1 \cdot L_2$}{lfunmul$(L_1,L_2)$} \li{$L_1 / L_2$}{lfundiv$(L_1,L_2)$} \li{$L(s-d)$}{lfunshift$(L,d)$} \li{$L(s) \cdot L(s-d)$}{lfunshift$(L,d,1)$} \li{twist by Dirichlet character}{lfuntwist$(L,\chi)$} \smallskip \li{low-level constructor} {lfuncreate$([a,a^*,A,k,N,\var{eps},\var{poles}])$} \li{check functional equation (at $t$)}{lfuncheckfeq$(L,\{t\})$} \li{parameters $[N, k, A]$}{lfunparams$(L)$} \subsec{Linit constructors} \li{initialize for $L$}{lfuninit$(L, R, \{m = 0\})$} \li{initialize for $\theta$}{lfunthetainit$(L, \{T = 1\}, \{m = 0\})$} \li{cost of \kbd{lfuninit}}{lfuncost$(L, R, \{m = 0\})$} \li{cost of \kbd{lfunthetainit}}{lfunthetacost$(L, T, \{m = 0\})$} \li{Dedekind $\zeta_L$, $L$ abelian over a subfield}{lfunabelianrelinit} \newcolumn \section{L-functions} $L$ is an \kbd{Ldata} or an \kbd{Linit} (more efficient for many values). \subsec{Evaluate} \li{$L^{(k)}(s)$}{lfun$(L,s,\{k=0\})$} \li{$\Lambda^{(k)}(s)$}{lfunlambda$(L,s,\{k=0\})$} \li{$\theta^{(k)}(t)$}{lfuntheta$(L,t,\{k=0\})$} \li{generalized Hardy $Z$-function at $t$}{lfunhardy$(L,t)$} %lfunmfspec \subsec{Zeros} \li{order of zero at $s = k/2$}{lfunorderzero$(L,\{m=-1\})$} \li{zeros $s = k/2 + it$, $0 \leq t \leq T$}{lfunzeros$(L, T, \{h\})$} \subsec{Dirichlet series and functional equation} \li{$[a_n\colon 1\leq n\leq N]$}{lfunan$(L, N)$} \li{Euler factor at $p$}{lfuneuler$(L, p)$} \li{conductor $N$ of $L$}{lfunconductor$(L)$} \li{root number and residues}{lfunrootres$(L)$} \subsec{$G$-functions} Attached to inverse Mellin transform for $\gamma_A(s)$, $A = [a_1,\dots,a_d]$.\hfil\break \li{initialize for $G$ attached to $A$}{gammamellininvinit$(A)$} \li{$G^{(k)}(t)$}{gammamellininv$(G,t,\{k=0\})$} \li{asymp. expansion of $G^{(k)}(t)$} {gammamellininvasymp$(A,n,\{k=0\})$} \section{Hypergeometric motives (HGM)} \subsec{Hypergeometric templates} Below, $H$ denotes an hypergeometric template from \kbd{hgminit}.\hfil\break \li{HGM template from $A=(\alpha_j), B=(\beta_k)$}{hgminit$(A,\{B\})$} \li{\dots from cyclotomic parameters $D,E$}{hgminit$(D,\{E\})$} \li{\dots from gamma vector}{hgminit$(G)$} \li{$\alpha$ and $\beta$ parameters for $H$}{hgmalpha$(H)$} \li{cyclotomic parameters $(D,E)$ of $H$}{hgmcyclo$(H)$} \li{\dots for all $H$ of degree $n$}{hgmbydegree$(n)$} \li{gamma vector for $H$}{hgmgamma$(H)$} \li{twist $A$ and $B$ by $1/2$}{hgmtwist$(H)$} \li{is $H$ symmetrical at $t = 1$?}{hgmissymmetrical$(H)$} \li{parameters $[d,w,[P,T],M]$ for $H$}{hgmparams$(H)$} \subsec{$L$-function} Let $L$ be the $L$-function attached to the hypergeometric motive $(H,t)$.\hfil\break \li{coefficient $a_n$ of $L$}{hgmcoef$(H,t,n)$} \li{coefficients $[a_1,\dots,a_n]$ of $L$}{hgmcoefs$(H,t,n)$} \li{Euler factor at $p$}{hgmeulerfactor$(H,t,p)$} \li{\dots and valuation of local conductor}{hgmeulerfactor$(H,t,p,\&e)$} \li{return $L$ as an \kbd{Ldata}}{lfunhgm$(H,t)$} \copyrightnotice \bye pari-2.17.2/doc/appb.tex0000644000175000017500000000211514567450071013405 0ustar billbill% Copyright (c) 2000 The PARI Group % % This file is part of the PARI/GP documentation % % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License \appendix{A Sample program and Makefile} We assume that you have installed the PARI library and include files as explained in Appendix A or in the installation guide. If you chose differently any of the directory names, change them accordingly in the Makefiles. If the program example that we have given is in the file \kbd{extgcd.c}, then a sample Makefile might look as follows. Note that the actual file \kbd{examples/Makefile} is more elaborate and you should have a look at it if you intend to use \kbd{install()} on custom made functions. \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.17.2/doc/usersch6.tex0000644000175000017500000046551314760123736014244 0ustar billbill% Copyright (c) 2000 The PARI Group % % This file is part of the PARI/GP documentation % % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License \newpage \chapter{Algebraic Number Theory} \section{General Number Fields} \subsec{Number field types} None of the following routines thoroughly check their input: they distinguish between \emph{bona fide} structures as output by PARI routines, but designing perverse data will easily fool them. To give an example, a square matrix will be interpreted as an ideal even though the $\Z$-module generated by its columns may not be an $\Z_K$-module (i.e. the expensive \kbd{nfisideal} routine will \emph{not} be called). \fun{long}{nftyp}{GEN x}. Returns the type of number field structure stored in \kbd{x}, \tet{typ_NF}, \tet{typ_BNF}, or \tet{typ_BNR}. Other answers are possible, meaning \kbd{x} is not a number field structure. \fun{GEN}{get_nf}{GEN x, long *t}. Extract an \var{nf} structure from \kbd{x} if possible and return it, otherwise return \kbd{NULL}. Sets \kbd{t} to the \kbd{nftyp} of \kbd{x} in any case. \fun{GEN}{get_bnf}{GEN x, long *t}. Extract a \kbd{bnf} structure from \kbd{x} if possible and return it, otherwise return \kbd{NULL}. Sets \kbd{t} to the \kbd{nftyp} of \kbd{x} in any case. \fun{GEN}{get_nfpol}{GEN x, GEN *nf} try to extract an \var{nf} structure from \kbd{x}, and sets \kbd{*nf} to \kbd{NULL} (failure) or to the \var{nf}. Returns the (monic, integral) polynomial defining the field. \fun{GEN}{get_bnfpol}{GEN x, GEN *bnf, GEN *nf} try to extract a \var{bnf} and an \var{nf} structure from \kbd{x}, and sets \kbd{*bnf} and \kbd{*nf} to \kbd{NULL} (failure) or to the corresponding structure. Returns the (monic, integral) polynomial defining the field. \fun{GEN}{checknf}{GEN x} if an \var{nf} structure can be extracted from \kbd{x}, return it; otherwise raise an exception. The more general \kbd{get\_nf} is often more flexible. \fun{GEN}{checkbnf}{GEN x} if an \var{bnf} structure can be extracted from \kbd{x}, return it; otherwise raise an exception. The more general \kbd{get\_bnf} is often more flexible. \fun{GEN}{checkbnf_i}{GEN bnf} same as \kbd{checkbnf} but return \kbd{NULL} instead of raising an exception. \fun{void}{checkbnr}{GEN bnr} Raise an exception if the argument is not a \var{bnr} structure. \fun{GEN}{checkbnr_i}{GEN bnr} same as \kbd{checkbnr} but returns the \var{bnr} or \kbd{NULL} instead of raising an exception. \fun{GEN}{checknf_i}{GEN nf} same as \kbd{checknf} but return \kbd{NULL} instead of raising an exception. \fun{void}{checkrnf}{GEN rnf} Raise an exception if the argument is not an \var{rnf} structure. \fun{int}{checkrnf_i}{GEN rnf} same as \kbd{checkrnf} but return $0$ on failure and $1$ on success. \fun{void}{checkbid}{GEN bid} Raise an exception if the argument is not a \var{bid} structure. \fun{GEN}{checkbid_i}{GEN bid} same as \kbd{checkbid} but return \kbd{NULL} instead of raising an exception and return \kbd{bid} on success. \fun{GEN}{checkznstar_i}{GEN G} return $G$ if it is a \var{znstar}; else return \kbd{NULL} on failure. \fun{GEN}{checkgal}{GEN x} if a \var{galoisinit} structure can be extracted from \kbd{x}, return it; otherwise raise an exception. \fun{void}{checksqmat}{GEN x, long N} check whether \kbd{x} is a square matrix of dimension \kbd{N}. May be used to check for ideals if \kbd{N} is the field degree. \fun{void}{checkprid}{GEN pr} Raise an exception if the argument is not a prime ideal structure. \fun{int}{checkprid_i}{GEN pr} same as \kbd{checkprid} but return $0$ instead of raising an exception and return $1$ on success. \fun{int}{is_nf_factor}{GEN F} return $1$ if $F$ is an ideal factorization and $0$ otherwise. \fun{int}{is_nf_extfactor}{GEN F} return $1$ if $F$ is an extended ideal factorization (allowing $0$ or negative exponents) and $0$ otherwise. \fun{int}{RgV_is_prV}{GEN v} returns $1$ if the vector $v$ contains only prime ideals and $0$ otherwise. \fun{GEN}{get_prid}{GEN ideal} return the underlying prime ideal structure if one can be extracted from \kbd{ideal} (ideal or extended ideal), and return \kbd{NULL} otherwise. \fun{void}{checkabgrp}{GEN v} Raise an exception if the argument is not an abelian group structure, i.e. a \typ{VEC} with either $2$ or $3$ entries: $[N,\var{cyc}]$ or $[N,\var{cyc}, \var{gen}]$. \fun{GEN}{abgrp_get_no}{GEN x} extract the cardinality $N$ from an abelian group structure. \fun{GEN}{abgrp_get_cyc}{GEN x} extract the elementary divisors \var{cyc} from an abelian group structure. \fun{GEN}{abgrp_get_gen}{GEN x} extract the generators \var{gen} from an abelian group structure. \fun{GEN}{cyc_get_expo}{GEN cyc} return the exponent of the group with structure \kbd{cyc}; $0$ for an infinite group. \fun{void}{checkmodpr}{GEN modpr} Raise an exception if the argument is not a \kbd{modpr} structure (from \kbd{nfmodprinit}). \fun{GEN}{get_modpr}{GEN x} return $x$ if it is a \kbd{modpr} structure and \kbd{NULL} otherwise. \fun{GEN}{checknfelt_mod}{GEN nf, GEN x, const char *s} given an \var{nf} structure \kbd{nf} and a \typ{POLMOD} \kbd{x}, return the attached polynomial representative (shallow) if \kbd{x} and \kbd{nf} are compatible. Raise an exception otherwise. Set $s$ to the name of the caller for a meaningful error message. \fun{int}{check_ZKmodule_i}{GEN x} return $1$ if $x$ looks like a projective $\Z_K$-module, i.e., a pair $[A,I]$ where $A$ is a matrix and $I$ is a list of ideals and $A$ has as many columns as $I$ has elements. Or possibly a longer list $[A,I,\dots]$ such as the output of \kbd{rnfpseudobasis}. Otherwise return $0$. \fun{void}{check_ZKmodule}{GEN x, const char *s} raise an exception unless $x$ is recognized as a projective $\Z_K$-module. Set $s$ to the name of the caller for a meaningful error message. \fun{long}{idealtyp}{GEN *ideal, GEN *fa} The input is \kbd{ideal}, a pointer to an ideal or extended ideal; returns the type of the underlying ideal among \tet{id_PRINCIPAL} (a number field element), \tet{id_PRIME} (a prime ideal) \tet{id_MAT} (an ideal in matrix form). As a first side effect, \kbd{*ideal} is set to the underlying ideal, possibly simplified (for instance the zero ideal represented by an empty matrix is replaced by \kbd{gen\_0}). If \kbd{fa} is not \kbd{NULL}, then \kbd{*fa} is set to the extended part in the input: either \kbd{NULL} (regular ideal) or the extended part of an extended ideal. \subsec{Extracting info from a \kbd{nf} structure} These functions expect a true \var{nf} argument attached to a number field $K = \Q[x]/(T)$, e.g.~a \var{bnf} will not work. Let $n = [K:\Q]$ be the field degree. \fun{GEN}{nf_get_pol}{GEN nf} returns the polynomial $T$ (monic, in $\Z[x]$). \fun{long}{nf_get_varn}{GEN nf} returns the variable number of the number field defining polynomial. \fun{long}{nf_get_r1}{GEN nf} returns the number of real places $r_1$. \fun{long}{nf_get_r2}{GEN nf} returns the number of complex places $r_2$. \fun{void}{nf_get_sign}{GEN nf, long *r1, long *r2} sets $r_1$ and $r_2$ to the number of real and complex places respectively. Note that $r_1+2r_2$ is the field degree. \fun{long}{nf_get_degree}{GEN nf} returns the number field degree, $n = r_1 + 2r_2$. \fun{GEN}{nf_get_disc}{GEN nf} returns the field discriminant. \fun{GEN}{nf_get_index}{GEN nf} returns the index of $T$, i.e. the index of the order generated by the power basis $(1,x,\ldots,x^{n-1})$ in the maximal order of $K$. \fun{GEN}{nf_get_zk}{GEN nf} returns a basis $(w_1,w_2,\ldots,w_n)$ for the maximal order of $K$. Those are polynomials in $\Q[x]$ of degree $ r$$ \noindent Then $e_j = \prod_i X[i]^{E[i,j]}$. \fun{GEN}{bnf_has_fu}{GEN bnf} return fundamental units in expanded form if \kbd{bnf} contains them. Else return \kbd{NULL}. \fun{GEN}{bnf_compactfu}{GEN bnf} return fundamental units as a vector of algebraic numbers in compact form if \kbd{bnf} contains them. Else return \kbd{NULL}. \fun{GEN}{bnf_compactfu_mat}{GEN bnf} as a pair $(X,U)$, where $X$ is a vector of $S$-units and $U$ is a matrix with integer entries (without $0$ rows), see \kbd{bnf\_get\_sunits}, if \kbd{bnf} contains them. Else return \kbd{NULL}. \subsec{Extracting info from a \kbd{bnr} structure} These functions expect a true \var{bnr} argument. \fun{GEN}{bnr_get_bnf}{GEN bnr} returns the underlying \var{bnf}. \fun{GEN}{bnr_get_nf}{GEN bnr} returns the underlying \var{nf}. \fun{GEN}{bnr_get_clgp}{GEN bnr} returns the ray class group. \fun{GEN}{bnr_get_no}{GEN bnr} returns the ray class number. \fun{GEN}{bnr_get_cyc}{GEN bnr} returns the elementary divisors of the ray class group (cyclic components) $[d_1,\ldots, d_k]$, where $d_k \mid \ldots \mid d_1$. \fun{GEN}{bnr_get_gen}{GEN bnr} returns the generators $[g_1,\ldots,g_k]$ of the ray class group. Each $g_i$ has order $d_i$, and the full module of relations between the $g_i$ is generated by the $d_ig_i = 0$. Raise a generic error if the \var{bnr} does not contain the ray class group generators. \fun{GEN}{bnr_get_gen_nocheck}{GEN bnr} as \tet{bnr_get_gen} without checking whether generators are present. Do not use this unless you initialize the \var{bnr} yourself! \fun{GEN}{bnr_get_bid}{GEN bnr} returns the \var{bid} attached to the \var{bnr} modulus. \fun{GEN}{bnr_get_mod}{GEN bnr} returns the modulus attached to the \var{bnr}. \subsec{Extracting info from an \kbd{rnf} structure} These functions expect a true \var{rnf} argument, attached to an extension $L/K$, $K = \Q[y]/(T)$, $L = K[x]/(P)$. \fun{long}{rnf_get_degree}{GEN rnf} returns the \emph{relative} degree $[L:K]$. \fun{long}{rnf_get_absdegree}{GEN rnf} returns the absolute degree $[L:\Q]$. \fun{long}{rnf_get_nfdegree}{GEN rnf} returns the degree of the base field $[K:\Q]$. \fun{GEN}{rnf_get_nf}{GEN rnf} returns the base field $K$, an \var{nf} structure. \fun{GEN}{rnf_get_nfpol}{GEN rnf} returns the polynomial $T$ defining the base field $K$. \fun{long}{rnf_get_nfvarn}{GEN rnf} returns the variable $y$ attached to the base field $K$. \fun{GEN}{rnf_get_nfzk}{GEN rnf} returns the integer basis of the base field $K$. \fun{GEN}{rnf_get_pol}{GEN rnf} returns the relative polynomial defining $L/K$. \fun{long}{rnf_get_varn}{GEN rnf} returns the variable $x$ attached to $L$. \fun{GEN}{rnf_get_zk}{GEN nf} returns the relative integer basis generating $\Z_L$ as a $\Z_K$-module, as a pseudo-matrix $(A,I)$ in HNF. \fun{GEN}{rnf_get_disc}{GEN rnf} is the output $[\goth{d}, s]$ of \kbd{rnfdisc}. \fun{GEN}{rnf_get_ramified_primes}{GEN rnf} returns the vector of rational primes below ramified primes in the relative extension, i.e. all prime numbers appearing in the factorization of \bprog idealnorm(rnf_get_nf(rnf), rnf_get_disc(rnf)); @eprog \fun{GEN}{rnf_get_idealdisc}{GEN rnf} is the ideal discriminant $\goth{d}$ from \kbd{rnfdisc}. \fun{GEN}{rnf_get_index}{GEN rnf} is the index ideal $\goth{f}$ \fun{GEN}{rnf_get_polabs}{GEN rnf} returns an absolute polynomial defining $L/\Q$. \fun{GEN}{rnf_get_alpha}{GEN rnf} a root $\alpha$ of the polynomial defining the base field, modulo \kbd{polabs} (cf.~\kbd{rnfequation}) \fun{GEN}{rnf_get_k}{GEN rnf} a small integer $k$ such that $\theta = \beta + k\alpha$ is a root of \kbd{polabs}, where $\beta$ is a root of \kbd{pol} and $\alpha$ a root of the polynomial defining the base field, as in \tet{rnf_get_alpha} (cf.~also \kbd{rnfequation}). \fun{GEN}{rnf_get_invzk}{GEN rnf} contains $A^{-1}$, where $(A,I)$ is the chosen pseudo-basis for $\Z_L$ over $\Z_K$. \fun{GEN}{rnf_get_map}{GEN rnf} returns technical data attached to the map $K\to L$. Currently, this contains data from \kbd{rnfequation}, as well as the polynomials $T$ and $P$. \subsec{Extracting info from a \kbd{bid} structure} These functions expect a true \var{bid} argument, attached to a modulus $I = I_0 I_\infty$ in a number field $K$. The underlying abelian group is $G = (\Z_K/I)^*$. Not that if the \var{bid} was initialized by \kbd{Idealstarmod} with a non-\kbd{NULL} \kbd{cycmod} argument, computations take place in $G / G^\kbd{cycmod}$ instead. \fun{GEN}{bid_get_mod}{GEN bid} returns the modulus attached to the \var{bid}. \fun{GEN}{bid_get_MOD}{GEN bid} returns the integer \kbd{cycmod} given as argument to \tet{Idealstarmod}, or \kbd{NULL} if we used \kbd{Idealstar} to initialize \kbd{bid}. \fun{GEN}{bid_get_grp}{GEN bid} returns the abelian group attached to $(\Z_K/I)^*$. \fun{GEN}{bid_get_ideal}{GEN bid} return the finite part $I_0$ of the \var{bid} modulus (an integer ideal). \fun{GEN}{bid_get_arch}{GEN bid} return the Archimedean part $I_\infty$ of the \var{bid} modulus as a vector of real places in vec01 format, see~\secref{se:signatures}. \fun{GEN}{bid_get_archp}{GEN bid} return the Archimedean part $I_\infty$ of the \var{bid} modulus, as a vector of real places in indices format see~\secref{se:signatures}. \fun{GEN}{bid_get_fact}{GEN bid} returns the ideal factorization $I_0 = \prod_i \goth{p}_i^{e_i}$. \fun{GEN}{bid_get_fact2}{GEN bid} as \kbd{bid\_get\_fact} with all factors $\goth{p}^1$ with $\goth{p}$ of norm $2$ removed from the factorization. (They play no role in the structure of $(\Z_K/I)^*$, except that the generators must be made coprime to them.) \tet{bid_get_ideal}$(\var{bid})$, via \kbd{idealfactor}. \fun{GEN}{bid_get_no}{GEN bid} returns the cardinality of the group $(\Z_K/I)^*$. \fun{GEN}{bid_get_cyc}{GEN bid} returns the elementary divisors of the group $(\Z_K/I)^*$ (cyclic components) $[d_1,\ldots, d_k]$, where $d_k \mid \ldots \mid d_1$. \fun{GEN}{bid_get_gen}{GEN bid} returns the generators of $(\Z_K/I)^*$ contained in \var{bid}. Raise a generic error if \var{bid} does not contain generators. \fun{GEN}{bid_get_gen_nocheck}{GEN bid} as \tet{bid_get_gen} without checking whether generators are present. Do not use this unless you initialize the \var{bid} yourself! \fun{GEN}{bid_get_sprk}{GEN bid} return a list of structures attached to the $(\Z_K/\goth{p}^e)^*$ where $\goth{p}^e$ divides $I_0$ exactly. \fun{GEN}{bid_get_sarch}{GEN bid} return the structure attached to $(\Z_K/I_\infty)^*$, by \kbd{nfarchstar}. \fun{GEN}{bid_get_U}{GEN bid} return the matrix with integral coefficients relating the local generators (from chinese remainders) to the global SNF generators (\kbd{\var{bid}.gen}). \subsec{Extracting info from a \kbd{znstar} structure} These functions expect an argument $G$ as returned by \kbd{znstar0(N, 1)}, attached to a positive $N$ and the abelian group $(\Z/N\Z)^*$. Let $(g_i)$ be the SNF generators, where $g_i$ has order $d_i$; we call $(g'_i)$ the (canonical) Conrey generators, where $g'_i$ has order $d'_i$. Both sets of generators have the same cardinality. \fun{GEN}{znstar_get_N}{GEN bid} return $N$. \fun{GEN}{znstar_get_faN}{GEN G} return the factorization \kbd{factor}$(N)$, $N = \prod_j p_j^{e_j}$. \fun{GEN}{znstar_get_pe}{GEN G} return the vector of primary factors $(p_j^{e_j})$. \fun{GEN}{znstar_get_no}{GEN G} the cardinality $\phi(N)$ of $G$. \fun{GEN}{znstar_get_cyc}{GEN G} elementary divisors $(d_i)$ of $(\Z/N\Z)^*$. \fun{GEN}{znstar_get_gen}{GEN G} SNF generators divisors $(g_i)$ of $(\Z/N\Z)^*$. \fun{GEN}{znstar_get_conreycyc}{GEN G} orders $(d'_i)$ of Conrey generators. \fun{GEN}{znstar_get_conreygen}{GEN G} Conrey generators $(g'_i)$. \fun{GEN}{znstar_get_U}{GEN G} a square matrix $U$ such that $(g_i) = U(g'_i)$. \fun{GEN}{znstar_get_Ui}{GEN G} a square matrix $U'$ such that $U'(g_i) = (g'_i)$. In general, $UU'$ will not be the identity. \subsec{Inserting info in a number field structure} If the required data is not part of the structure, it is computed then inserted, and the new value is returned. These functions expect a \kbd{bnf} argument: \fun{GEN}{bnf_build_cycgen}{GEN bnf} the \var{bnf} contains generators $[g_1,\ldots,g_k]$ of the class group, each with order $d_i$. Then $g_i^{d_i} = (x_i)$ is a principal ideal. This function returns the $x_i$ as a factorization matrix (\kbd{famat}) giving the element in factored form as a product of $S$-units. \fun{GEN}{bnf_build_matalpha}{GEN bnf} the class group was computed using a factorbase $S$ of prime ideals $\goth{p}_i$, $i \leq r$. They satisfy relations of the form $\prod_j \goth{p}_i^{e_{i,j}} = (\alpha_j)$, where the $e_{i,j}$ are given by the matrices $\var{bnf}[1]$ ($W$, singling out a minimal set of generators in $S$) and $\var{bnf}[2]$ ($B$, expressing the rest of $S$ in terms of the singled out generators). This function returns the $\alpha_j$ in factored form as a product of $S$-units. \fun{GEN}{bnf_build_units}{GEN bnf} returns a minimal set of generators for the unit group in expanded form. The first element is a torsion unit, the others have infinite order. This expands units in compact form contained in a \kbd{bnf} from \kbd{bnfinit}$(,1)$ and may be \emph{very} expensive if the units are huge. \fun{GEN}{bnf_build_cheapfu}{GEN bnf} as \kbd{bnf\_build\_units} but only expand units in compact form if the computation is inexpensive (a few seconds). Return \kbd{NULL} otherwise. These functions expect a \kbd{rnf} argument: \fun{GEN}{rnf_build_nfabs}{GEN rnf, long prec} given a \var{rnf} structure attached to $L/K$, (compute and) return an \var{nf} structure attached to $L$ at precision \kbd{prec}. \fun{void}{rnfcomplete}{GEN rnf} as \tet{rnf_build_nfabs} using the precision of $K$ for \kbd{prec}. \fun{GEN}{rnf_zkabs}{GEN rnf} returns a $\Z$-basis in HNF for $\Z_L$ as a pair $[T, v]$, where $T$ is \tet{rnf_get_polabs}$(\var{rnf})$ and $v$ a vector of elements lifted from $\Q[X]/(T)$. Note that the function \tet{rnf_build_nfabs} essentially applies \kbd{nfinit} to the output of this function. \subsec{Increasing accuracy} \fun{GEN}{nfnewprec}{GEN x, long prec}. Raise an exception if \kbd{x} is not a number field structure (\var{nf}, \var{bnf} or \var{bnr}). Otherwise, sets its accuracy to \kbd{prec} and return the new structure. This is mostly useful with \kbd{prec} larger than the accuracy to which \kbd{x} was computed, but it is also possible to decrease the accuracy of \kbd{x} (truncating relevant components, which may speed up later computations). This routine may modify the original \kbd{x} (see below). This routine is straightforward for \var{nf} structures, but for the other ones, it requires all principal ideals corresponding to the \var{bnf} relations in algebraic form (they are originally only available via floating point approximations). This in turn requires many calls to \tet{bnfisprincipal0}, which is often slow, and may fail if the initial accuracy was too low. In this case, the routine will not actually fail but recomputes a \var{bnf} from scratch! Since this process may be very expensive, the corresponding data is cached (as a \emph{clone}) in the \emph{original} \kbd{x} so that later precision increases become very fast. In particular, the copy returned by \kbd{nfnewprec} also contains this additional data. \fun{GEN}{bnfnewprec}{GEN x, long prec}. As \kbd{nfnewprec}, but extracts a \var{bnf} structure form \kbd{x} before increasing its accuracy, and returns only the latter. \fun{GEN}{bnrnewprec}{GEN x, long prec}. As \kbd{nfnewprec}, but extracts a \var{bnr} structure form \kbd{x} before increasing its accuracy, and returns only the latter. \fun{GEN}{rnfnewprec}{GEN x, long prec}. As \kbd{nfnewprec}, but extracts a \var{rnf} structure form \kbd{x} before increasing its accuracy, and returns only the latter. \fun{GEN}{nfnewprec_shallow}{GEN nf, long prec} \fun{GEN}{bnfnewprec_shallow}{GEN bnf, long prec} \fun{GEN}{rnfnewprec_shallow}{GEN rnf, long prec} \fun{GEN}{bnrnewprec_shallow}{GEN bnr, long prec} Shallow functions underlying the above, except that the first argument must now have the corresponding number field type. I.e. one cannot call \kbd{nfnewprec\_shallow(nf, prec)} if \kbd{nf} is actually a \var{bnf}. \subsec{Number field arithmetic} The number field $K = \Q[X]/(T)$ is represented by an \kbd{nf} (or \kbd{bnf} or \kbd{bnr} structure). An algebraic number belonging to $K$ 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 $(e_i)$, as \bprog sum(i = 1, N, v[i] * nf.zk[i]) @eprog The preferred forms are \typ{INT} and \typ{COL} of \typ{INT}. Routines can handle denominators but it is much more efficient to remove denominators first (\tet{Q_remove_denom}) and take them into account at the end. \misctitle{Safe routines} The following routines do not assume that their \kbd{nf} argument is a true \var{nf} (it can be any number field type, e.g.~a \var{bnf}), and accept number field elements in all the above forms. They return their result in \typ{COL} form. \fun{GEN}{nfadd}{GEN nf, GEN x, GEN y} returns $x+y$. \fun{GEN}{nfsub}{GEN nf, GEN x, GEN y} returns $x-y$. \fun{GEN}{nfdiv}{GEN nf, GEN x, GEN y} returns $x / y$. \fun{GEN}{nfinv}{GEN nf, GEN x} returns $x^{-1}$. \fun{GEN}{nfmul}{GEN nf,GEN x,GEN y} returns $xy$. \fun{GEN}{nfpow}{GEN nf,GEN x,GEN k} returns $x^k$, $k$ is in $\Z$. \fun{GEN}{nfpow_u}{GEN nf,GEN x, ulong k} returns $x^k$, $k\geq 0$; the argument \kbd{nf} is a true \var{nf} structure. \fun{GEN}{nfsqr}{GEN nf,GEN x} returns $x^2$. \fun{long}{nfval}{GEN nf, GEN x, GEN pr} returns the valuation of $x$ at the maximal ideal $\goth{p}$ attached to the \var{prid} \kbd{pr}. Returns \kbd{LONG\_MAX} if $x$ is $0$. \fun{GEN}{nfnorm}{GEN nf,GEN x} absolute norm of $x$. \fun{GEN}{nftrace}{GEN nf,GEN x} absolute trace of $x$. \fun{GEN}{nfpoleval}{GEN nf, GEN pol, GEN a} evaluate the \typ{POL} \kbd{pol} (with coefficients in \kbd{nf}) on the algebraic number $a$ (also in $nf$). \fun{GEN}{FpX_FpC_nfpoleval}{GEN nf, GEN pol, GEN a, GEN p} evaluate the \kbd{FpX} \kbd{pol} on the algebraic number $a$ (also in $nf$). The following three functions implement trivial functionality akin to Euclidean division for which we currently have no real use. Of course, even if the number field is actually Euclidean, these do not in general implement a true Euclidean division. \fun{GEN}{nfdiveuc}{GEN nf, GEN a, GEN b} returns the algebraic integer closest to $x / y$. Functionally identical to \kbd{ground( nfdiv(nf,x,y) )}. \fun{GEN}{nfdivrem}{GEN nf, GEN a, GEN b} returns the vector $[q,r]$, where \bprog q = nfdiveuc(nf, a, b); r = nfsub(nf, a, nfmul(nf,q,b)); \\ or r = nfmod(nf,a,b); @eprog \fun{GEN}{nfmod}{GEN nf, GEN a, GEN b} returns $r$ such that \bprog q = nfdiveuc(nf, a, b); r = nfsub(nf, a, nfmul(nf,q,b)); @eprog \fun{GEN}{nf_to_scalar_or_basis}{GEN nf, GEN x} let $x$ be a number field element. If it is a rational scalar, i.e.~can be represented by a \typ{INT} or \typ{FRAC}, return the latter. Otherwise returns its basis representation (\tet{nfalgtobasis}). Shallow function. \fun{GEN}{nf_to_scalar_or_alg}{GEN nf, GEN x} let $x$ be a number field element. If it is a rational scalar, i.e.~can be represented by a \typ{INT} or \typ{FRAC}, return the latter. Otherwise returns its lifted \typ{POLMOD} representation (lifted \tet{nfbasistoalg}). Shallow function. \fun{GEN}{nfV_to_scalar_or_alg}{GEN nf, GEN v} aplly \tet{nf_to_scalar_or_alg} to all components of vector $v$. \fun{GEN}{RgX_to_nfX}{GEN nf, GEN x} let $x$ be a \typ{POL} whose coefficients are number field elements; apply \kbd{nf\_to\_scalar\_or\_basis} to each coefficient and return the resulting new polynomial. Shallow function. \fun{GEN}{RgM_to_nfM}{GEN nf, GEN x} let $x$ be a \typ{MAT} whose coefficients are number field elements; apply \kbd{nf\_to\_scalar\_or\_basis} to each coefficient and return the resulting new matrix. Shallow function. \fun{GEN}{RgC_to_nfC}{GEN nf, GEN x} let $x$ be a \typ{COL} or \typ{VEC} whose coefficients are number field elements; apply \kbd{nf\_to\_scalar\_or\_basis} to each coefficient and return the resulting new \typ{COL}. Shallow function. \fun{GEN}{nfX_to_monic}{GEN nf, GEN T, GEN *pL} given a nonzero \typ{POL} $T$ with coefficients in \var{nf}, return a monic polynomial $f$ with integral coefficients such that $f(x) = C T(x/L)$ for some integral $L$ and some $C$ in \var{nf}. The function allows coefficients in basis form; if $L \neq 1$, it will return them in algebraic form. If \kbd{pL} is not \kbd{NULL}, \kbd{*pL} is set to $L$. Shallow function. \misctitle{Unsafe routines} The following routines assume that their \kbd{nf} argument is a true \var{nf} (e.g.~a \var{bnf} is not allowed) and their argument are restricted in various ways, see the precise description below. \fun{GEN}{nfX_disc}{GEN nf, GEN A} given an \var{nf} structure attached to a number field $K$ with main variable $Y$ (\kbd{nf\_get\_varn(nf)}), a \typ{POL} $A \in K[X]$ given as a lift in $\Q[X,Y]$ (implicitly modulo \kbd{nf\_get\_pol(nf)}, return the discriminant of $A$ as a \typ{POL} in $\Q[Y]$ (representing an element of $K$). \fun{GEN}{nfX_resultant}{GEN nf, GEN A, GEN B} analogous to \kbd{nfX\_disc}, $A, B\in \Q[X,Y]$; return the resultant of $A$ and $B$ with respect to $X$ as a \typ{POL} in $\Q[Y]$ (representing an element of $K$). \fun{GEN}{nfinvmodideal}{GEN nf, GEN x, GEN A} given an algebraic integer $x$ and a nonzero integral ideal $A$ in HNF, returns a $y$ such that $xy \equiv 1$ modulo $A$. \fun{GEN}{nfpowmodideal}{GEN nf, GEN x, GEN n, GEN ideal} given an algebraic integer $x$, an integer $n$, and a nonzero integral ideal $A$ in HNF, returns an algebraic integer congruent to $x^n$ modulo $A$. \fun{GEN}{nfmuli}{GEN nf, GEN x, GEN y} returns $x\times y$ assuming that both $x$ and $y$ are either \typ{INT}s or \kbd{ZV}s of the correct dimension. The argument \kbd{nf} is a true \var{nf} structure. \fun{GEN}{nfsqri}{GEN nf, GEN x} returns $x^2$ assuming that $x$ is a \typ{INT} or a \kbd{ZV} of the correct dimension. The argument \kbd{nf} is a true \var{nf} structure. \fun{GEN}{nfC_nf_mul}{GEN nf, GEN v, GEN x} given a \typ{VEC} or \typ{COL} $v$ of elements of $K$ in \typ{INT}, \typ{FRAC} or \typ{COL} form, multiply it by the element $x$ (arbitrary form). This is faster than multiplying coordinatewise since pre-computations related to $x$ (computing the multiplication table) are done only once. The components of the result are in most cases \typ{COL}s but are allowed to be \typ{INT}s or \typ{FRAC}s. Shallow function. \fun{GEN}{nfC_multable_mul}{GEN v, GEN mx} same as \tet{nfC_nf_mul}, where the argument $x$ is replaced by its multiplication table \kbd{mx}. \fun{GEN}{zkC_multable_mul}{GEN v, GEN x} same as \tet{nfC_nf_mul}, where $v$ is a vector of algebraic integers, $x$ is an algebraic integer, and $x$ is replaced by \kbd{zk\_multable}$(x)$. \fun{GEN}{zk_multable}{GEN nf, GEN x} given a \kbd{ZC} $x$ (implicitly representing an algebraic integer), returns the \kbd{ZM} giving the multiplication table by $x$. Shallow function (the first column of the result points to the same data as $x$). \fun{GEN}{zk_inv}{GEN nf, GEN x} given a \kbd{ZC} $x$ (implicitly representing an algebraic integer), returns the \kbd{QC} giving the inverse $x^{-1}$. Return \kbd{NULL} if $x$ is $0$. Not memory clean but safe for \kbd{gerepileupto}. \fun{GEN}{zkmultable_inv}{GEN mx} as \tet{zk_inv}, where the argument given is \kbd{zk\_multable}$(x)$. \fun{GEN}{zkmultable_capZ}{GEN mx} given a nonzero \var{zkmultable} \var{mx} attached to $x \in \Z_K$, return the positive generator of $(x)\cap \Z$. \fun{GEN}{zk_scalar_or_multable}{GEN nf, GEN x} given a \typ{INT} or \kbd{ZC} $x$, returns a \typ{INT} equal to $x$ if the latter is a scalar (\typ{INT} or \kbd{ZV\_isscalar}$(x)$ is 1) and \kbd{zk\_multable}$(\var{nf},x)$ otherwise. Shallow function. \subsec{Number field arithmetic for linear algebra} The following routines implement multiplication in a commutative $R$-algebra, generated by $(e_1 = 1,\dots, e_n)$, and given by a multiplication table $M$: elements in the algebra are $n$-dimensional \typ{COL}s, and the matrix $M$ is such that for all $1\leq i,j\leq n$, its column with index $(i-1)n + j$, say $(c_k)$, gives $e_i\cdot e_j = \sum c_k e_k$. It is assumed that $e_1$ is the neutral element for the multiplication (a convenient optimization, true in practice for all multiplications we needed to implement). If $x$ has any other type than \typ{COL} where an algebra element is expected, it is understood as $x e_1$. \fun{GEN}{multable}{GEN M, GEN x} given a column vector $x$, representing the quantity $\sum_{i=1}^N x_i e_i$, returns the multiplication table by $x$. Shallow function. \fun{GEN}{ei_multable}{GEN M, long i} returns the multiplication table by the $i$-th basis element $e_i$. Shallow function. \fun{GEN}{tablemul}{GEN M, GEN x, GEN y} returns $x\cdot y$. \fun{GEN}{tablesqr}{GEN M, GEN x} returns $x^2$. \fun{GEN}{tablemul_ei}{GEN M, GEN x, long i} returns $x\cdot e_i$. \fun{GEN}{tablemul_ei_ej}{GEN M, long i, long j} returns $e_i\cdot e_j$. \fun{GEN}{tablemulvec}{GEN M, GEN x, GEN v} given a vector $v$ of elements in the algebra, returns the $x\cdot v[i]$. The following routines implement naive linear algebra using the \emph{black box field} mechanism: \fun{GEN}{nfM_det}{GEN nf, GEN M} \fun{GEN}{nfM_inv}{GEN nf, GEN M} \fun{GEN}{nfM_ker}{GEN nf, GEN M} \fun{GEN}{nfM_mul}{GEN nf, GEN A, GEN B} \fun{GEN}{nfM_nfC_mul}{GEN nf, GEN A, GEN B} \subsec{Cyclotomic field arithmetic for linear algebra} The following routines implement modular algorithms in cyclotomic fields. In the prototypes, $P$ is the $n$-th cyclotomic polynomial $\Phi_n$ and $M$ is a \typ{MAT} with \typ{INT} or \kbd{ZX} coefficients, understood modulo $P$. \fun{GEN}{ZabM_ker}{GEN M, GEN P, long n} returns an integral (primitive) basis of the kernel of $M$. \fun{GEN}{ZabM_indexrank}{GEN M, GEN P, long n} return a vector with two \typ{VECSMALL} components givin the rank profile of $M$. Inefficient (but correct) when $M$ does not have almost full column rank. \fun{GEN}{ZabM_inv}{GEN M, GEN P, long n, GEN *pden} assume that $M$ is invertible; return $N$ and sets the algebraic integer \kbd{*pden} (an integer or a \kbd{ZX}, implicitly modulo $P$) such that $M N = \kbd{den} \cdot \Id$. \fun{GEN}{ZabM_pseudoinv}{GEN M, GEN P, long n, GEN *pv, GEN *pden} analog of \kbd{ZM\_pseudoinv}. Not gerepile-safe. \fun{GEN}{ZabM_inv_ratlift}{GEN M, GEN P, long n, GEN *pden} return a primitive matrix $H$ such that $M H$ is $d$ times the identity and set \kbd{*pden} to $d$. Uses a multimodular algorithm, attempting rational reconstruction along the way. To be used when you expect that the denominator of $M^{-1}$ is much smaller than $\det M$ else use \kbd{ZabM\_inv}. \subsec{Cyclotomic trace} Given two positive integers $m$ and $n$ such that $K_m = \Q(\zeta_m) \subset K_n = \Q(\zeta_n)$, these functions implement relative trace computation from $K_n$ to $K_m$. This is in particular useful for character values. \fun{GEN}{Qab_trace_init}{long n, long m, GEN Pn, GEN Pm} assume that \kbd{Pn} is \kbd{polcyclo}$(n)$, \kbd{Pm} is \kbd{polcyclo}$(m)$ (both in the same variable), initialize a structure $T$ used in the following routines. Shallow function. \fun{GEN}{Qab_tracerel}{GEN T, long t, GEN z} assume $T$ was created by \tet{Qab_trace_init}, $t$ is an integer such that $0 \leq t < [K_n:K_m]$ and $z$ belongs to the cyclotomic field $\Q(\zeta_n) = \Q[X]/(\kbd{Pn})$. Return the normalized relative trace $[K_n:K_m]^{-1}\text{Tr}_{K_n/K_m} (\zeta_n^t z)$. Shallow function. \fun{GEN}{QabV_tracerel}{GEN T, long t, GEN v} $v$ being a vector of entries belonging to $K_n$, apply \tet{Qab_tracerel} to all entries. Shallow function. \fun{GEN}{QabM_tracerel}{GEN T, long t, GEN m} $m$ being a matrix of entries belonging to $K_n$, apply \tet{Qab_tracerel} to all entries. Shallow function. \subsec{Elements in factored form} Computational algebraic theory performs extensively linear algebra on $\Z$-modules with a natural multiplicative structure ($K^*$, fractional ideals in $K$, $\Z_K^*$, ideal class group), thereby raising elements to horrendously large powers. A seemingly innocuous elementary linear algebra operation like $C_i\leftarrow C_i - 10000 C_1$ involves raising entries in $C_1$ to the $10000$-th power. Understandably, it is often more efficient to keep elements in factored form rather than expand every such expression. A \emph{factorization matrix} (or \tev{famat}) is a two column matrix, the first column containing \emph{elements} (arbitrary objects which may be repeated in the column), and the second one contains \emph{exponents} (\typ{INT}s, allowed to be 0). By abuse of notation, the empty matrix \kbd{cgetg(1, t\_MAT)} is recognized as the trivial factorization (no element, no exponent). Even though we think of a \var{famat} with columns $g$ and $e$ as one meaningful object when fully expanded as $\prod g[i]^{e[i]}$, \var{famat}s are basically about concatenating information to keep track of linear algebra: the objects stored in a \var{famat} need not be operation-compatible, they will not even be compared to each other (with one exception: \tet{famat_reduce}). Multiplying two \var{famat}s just concatenates their elements and exponents columns. In a context where a \var{famat} is expected, an object $x$ which is not of type \typ{MAT} will be treated as the factorization $x^1$. The following functions all return \var{famat}s: \fun{GEN}{famat_mul}{GEN f, GEN g} $f$, $g$ are \var{famat}, or objects whose type is \emph{not} \typ{MAT} (understood as $f^1$ or $g^1$). Returns $fg$. The empty factorization is the neutral element for \var{famat} multiplication. \fun{GEN}{famat_mul_shallow}{GEN f, GEN g} shallow version of \tet{famat_mul}. \fun{GEN}{famat_pow}{GEN f, GEN n} $n$ is a \typ{INT}. If $f$ is a \typ{MAT}, assume it is a \var{famat} and return $f^n$ (multiplies the exponent column by $n$). Otherwise, understand it as an element and returns the $1$-line \var{famat} $f^n$. \fun{GEN}{famat_pow_shallow}{GEN f, GEN n} shallow version of \tet{famat_pow}. \fun{GEN}{famat_pows_shallow}{GEN f, long n} shallow version of \tet{famat_pow} where $n$ is a small integer. \fun{GEN}{famat_mulpow_shallow}{GEN f, GEN g, GEN e} \kbd{famat} corresponding to $f \cdot g^e$. Shallow function. \fun{GEN}{famat_mulpows_shallow}{GEN f, GEN g, long e} \kbd{famat} shallow version of \tet{famat_mulpow} where $e$ is a small integer. \fun{GEN}{famat_sqr}{GEN f} returns $f^2$. \fun{GEN}{famat_inv}{GEN f} returns $f^{-1}$. \fun{GEN}{famat_div}{GEN f, GEN g} return $f/g$. \fun{GEN}{famat_inv_shallow}{GEN f} shallow version of \tet{famat_inv}. \fun{GEN}{famat_div_shallow}{GEN f, GEN g} return $f/g$; shallow. \fun{GEN}{famat_Z_gcd}{GEN M, GEN n} restrict the \var{famat} $M$ to the prime powers dividing $n$. \fun{GEN}{to_famat}{GEN x, GEN k} given an element $x$ and an exponent $k$, returns the \var{famat} $x^k$. \fun{GEN}{to_famat_shallow}{GEN x, GEN k} same, as a shallow function. \fun{GEN}{Z_to_famat}{GEN x} converts the \typ{INT} $x$ to a \var{famat}. This does not factor $x$ but will replace it by $y^k$ with $y$ integral and $k$ maximal. Note that $0$ gets converted to $0^1$. Shallow function. \fun{GEN}{Q_to_famat}{GEN x} converts the \typ{INT} or \typ{FRAC} $x$ to a \var{famat}. If $x$ is a \typ{INT}, as \tet{Z_to_famat}. Else, this does not factor $x$ but will replace it by $y^a z^{-b}$ with integral $y$ and $z$ and maximal (positive) $a$ and $b$. Shallow function. \fun{GEN}{famatV_factorback}{GEN v, GEN e} given a vector of \kbd{famat}s $v$ and a \kbd{ZV} $e$ return the \kbd{famat} $\prod_i v[i]^{e[i]}$. Shallow function. \fun{GEN}{famatV_zv_factorback}{GEN v, GEN e} given a vector of \kbd{famat}s $v$ and a \kbd{zv} $e$ return the \kbd{famat} $\prod_i v[i]^{e[i]}$. Shallow function. \fun{GEN}{ZM_famat_limit}{GEN f, GEN limit} given a \var{famat} $f$ with \typ{INT} entries, returns a \var{famat} $g$ with all factors larger than \kbd{limit} multiplied out as the last entry (with exponent $1$). Shallow function. Note that it is trivial to break up a \var{famat} into its two constituent columns: \kbd{gel(f,1)} and \kbd{gel(f,2)} are the elements and exponents respectively. Conversely, \kbd{mkmat2} builds a (shallow) \var{famat} from two \typ{COL}s of the same length. \fun{GEN}{famat_reduce}{GEN f} given a \var{famat} $f$, returns a \var{famat} $g$ without repeated elements or 0 exponents, such that the expanded forms of $f$ and $g$ would be equal. Shallow function. \fun{GEN}{famat_remove_trivial}{GEN f} given a \var{famat} $f$, returns a \var{famat} $g$ without 0 exponents. Shallow function. \fun{GEN}{famatsmall_reduce}{GEN f} as \kbd{famat\_reduce}, but for exponents given by a \typ{VECSMALL}. \fun{GEN}{famat_to_nf}{GEN nf, GEN f} You normally never want to do this! This is a simplified form of \tet{nffactorback}, where we do not check the user input for consistency. The elements must be regular algebraic numbers (not \var{famat}s) over the given number field. Why should you \emph{not} want to use this function ? You should not need to: most of the functions useful in this context accept \var{famat}s as inputs, for instance \tet{nfsign}, \tet{nfsign_arch}, \tet{ideallog} and \tet{bnfisunit}. Otherwise, we can hopefully make good use of a quotient operation (modulo a fixed conductor, modulo $\ell$-th powers); see the end of \secref{se:Ideal_reduction}. If nothing else works, this function is available but is expected to be slow or even overflow the possibilities of the implementation. \fun{GEN}{famat_idealfactor}{GEN nf, GEN x} This is a good alternative for \kbd{famat\_to\_nf}, returning the factorization of the ideal generated by $x$. Since the answer is still given in factorized form, there is no risk of coefficient explosion when the exponents are large. Of course, all components of $x$ must be factored individually. \fun{GEN}{famat_nfvalrem}{GEN nf, GEN x, GEN pr, GEN *py} return the valuation $v$ at \kbd{pr} of \kbd{famat\_to\_nf}$(x)$, without performing the expansion of course. Notive that the output is a \kbd{GEN} since it cannot be assumed to fit into a \kbd{long}. If \kbd{py} is not \kbd{NULL} it contains the \kbd{famat} obtained by applying \kbd{nfvalrem} to each entry of the first column and copying the second column, with $0$ exponents removed. The expanded algebraic number is coprime to \kbd{pr} (in fact, all its components are coprime do \kbd{pr}) and equal to $x \tau^v$ where $\tau$ is the fixed anti-uniformizer for \kbd{pr} (\kbd{pr\_get\_tau}). \misctitle{Caveat} Receiving a \var{famat} input, \kbd{bnfisunit} assumes that it is an actual unit, since this is expensive to check, and normally easy to ensure from the user's side. \subsec{Ideal arithmetic} \misctitle{Conversion to HNF} \fun{GEN}{idealhnf}{GEN nf, GEN x} where the argument \kbd{nf} is a true \var{nf} structure. Returns the HNF of the ideal defined by $x$: $x$ may be an algebraic number (defining a principal ideal), a maximal ideal (as given by \tet{idealprimedec} or \tet{idealfactor}), or a matrix whose columns give generators for the ideal. This last format is 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, $x$ is the $\Z_K$-module they generate, \item if $N$ or more are given, it is assumed that they form a $\Z$-basis (that the matrix has maximal rank $N$). This acts as \tet{mathnf} since the $\Z_K$-module structure is (taken for granted hence) not taken into account in this case. Extended ideals are also accepted, their principal part being discarded. \fun{GEN}{idealhnf0}{GEN nf, GEN x, GEN y} returns the HNF of the ideal generated by the two algebraic numbers $x$ and $y$. The following low-level functions underlie the above two: they all assume that \kbd{nf} is a true \var{nf} and perform no type checks: \fun{GEN}{idealhnf_principal}{GEN nf, GEN x} returns the ideal generated by the algebraic number $x$. \fun{GEN}{idealhnf_shallow}{GEN nf, GEN x} is \tet{idealhnf} except that the result may not be suitable for \kbd{gerepile}: if $x$ is already in HNF, we return $x$, not a copy! \fun{GEN}{idealhnf_two}{GEN nf, GEN v} assuming $a = v[1]$ is a nonzero \typ{INT} and $b = v[2]$ is an algebraic integer, possibly given in regular representation by a \typ{MAT} (the multiplication table by $b$, see \tet{zk_multable}), returns the HNF of $a\Z_K+b\Z_K$. \misctitle{Operations} The basic ideal routines accept all \kbd{nf}s (\var{nf}, \var{bnf}, \var{bnr}) and ideals in any form, including extended ideals, and return ideals in HNF, or an extended ideal when that makes sense: \fun{GEN}{idealadd}{GEN nf, GEN x, GEN y} returns $x+y$. \fun{GEN}{idealdiv}{GEN nf, GEN x, GEN y} returns $x/y$. Returns an extended ideal if $x$ or $y$ is an extended ideal. \fun{GEN}{idealmul}{GEN nf, GEN x, GEN y} returns $xy$. Returns an extended ideal if $x$ or $y$ is an extended ideal. \fun{GEN}{idealsqr}{GEN nf, GEN x} returns $x^2$. Returns an extended ideal if $x$ is an extended ideal. \fun{GEN}{idealinv}{GEN nf, GEN x} returns $x^{-1}$. Returns an extended ideal if $x$ is an extended ideal. \fun{GEN}{idealpow}{GEN nf, GEN x, GEN n} returns $x^n$. Returns an extended ideal if $x$ is an extended ideal. \fun{GEN}{idealpows}{GEN nf, GEN ideal, long n} returns $x^n$. Returns an extended ideal if $x$ is an extended ideal. \fun{GEN}{idealmulred}{GEN nf, GEN x, GEN y} returns an extended ideal equal to $xy$. \fun{GEN}{idealpowred}{GEN nf, GEN x, GEN n} returns an extended ideal equal to $x^n$. More specialized routines suffer from various restrictions: \fun{GEN}{idealdivexact}{GEN nf, GEN x, GEN y} returns $x/y$, assuming that the quotient is an integral ideal. Much faster than \tet{idealdiv} when the norm of the quotient is small compared to $Nx$. Strips the principal parts if either $x$ or $y$ is an extended ideal. \fun{GEN}{idealdivpowprime}{GEN nf, GEN x, GEN pr, GEN n} returns $x \goth{p}^{-n}$, assuming $x$ is an ideal in HNF or a rational number, and \kbd{pr} a \var{prid} attached to $\goth{p}$. Not suitable for \tet{gerepileupto} since it returns $x$ when $n = 0$. The \kbd{nf} argument must be a true \var{nf} structure. \fun{GEN}{idealmulpowprime}{GEN nf, GEN x, GEN pr, GEN n} returns $x \goth{p}^{n}$, assuming $x$ is an ideal in HNF or a rational number, and \kbd{pr} a \var{prid} attached to $\goth{p}$. Not suitable for \tet{gerepileupto} since it retunrs $x$ when $n = 0$. The \kbd{nf} argument must be a true \var{nf} structure. \fun{GEN}{idealprodprime}{GEN nf, GEN v} given a list $v$ of prime ideals in \var{prid} form, return their product. Assume that \var{nf} is a true \var{nf} structure. \fun{GEN}{idealprod}{GEN nf, GEN v} given a list $v$ of ideals, return their product. \fun{GEN}{idealprodval}{GEN nf, GEN v, GEN pr} given a list $v$ of ideals return the valuation of their product at the prime ideal \kbd{pr}. \fun{GEN}{idealHNF_mul}{GEN nf, GEN x, GEN y} returns $xy$, assuming than \kbd{nf} is a true \var{nf}, $x$ is an integral ideal in HNF and $y$ is an integral ideal in HNF or precompiled form (see below). For maximal speed, the second ideal $y$ may be given in precompiled form $y = [a,b]$, where $a$ is a nonzero \typ{INT} and $b$ is an algebraic integer in regular representation (a \typ{MAT} giving the multiplication table by the fixed element): very useful when many ideals $x$ are going to be multiplied by the same ideal $y$. This essentially reduces each ideal multiplication to an $N\times N$ matrix multiplication followed by a $N\times 2N$ modular HNF reduction (modulo $xy\cap \Z$). \fun{GEN}{idealHNF_inv}{GEN nf, GEN I} returns $I^{-1}$, assuming that \kbd{nf} is a true \var{nf} and $x$ is a fractional ideal in HNF. \fun{GEN}{idealHNF_inv_Z}{GEN nf, GEN I} returns $(I\cap \Z) \cdot I^{-1}$, assuming that \kbd{nf} is a true \var{nf} and $x$ is an integral fractional ideal in HNF. The result is an integral ideal in HNF. \fun{GEN}{ideals_by_norm}{GEN nf, GEN N} given a true \var{nf} structure and a integer $N$, which can also be given by a factorization matrix or (preferably) by a pair $[N, \kbd{factor}(N)]$, return all ideals of norm $N$ in factored form. Not \kbd{gerepile} clean. \misctitle{Approximation} \fun{GEN}{idealaddtoone}{GEN nf, GEN A, GEN B} given to coprime integer ideals $A$, $B$, returns $[a,b]$ with $a\in A$, $b\in B$, such that $a + b = 1$ The result is reduced mod $AB$, so $a$, $b$ will be small. \fun{GEN}{idealaddtoone_i}{GEN nf, GEN A, GEN B} as \tet{idealaddtoone} except that \kbd{nf} must be a true \var{nf}, and only $a$ is returned. \fun{GEN}{idealaddtoone_raw}{GEN nf, GEN A, GEN B} as \tet{idealaddtoone_i} except that the reduction mod $AB$ is only performed modulo the lcm of $A \cap \Z$ and $B\cap \Z$, which will increase the size of $a$. \fun{GEN}{zkchineseinit}{GEN nf, GEN A, GEN B, GEN AB} given two coprime integral ideals $A$ and $B$ (in any form, preferably HNF) and their product \kbd{AB} (in HNF form), initialize a solution to the Chinese remainder problem modulo $AB$. THe \kbd{nf} argument must be a true \var{nf} structure. \fun{GEN}{zkchinese}{GEN zkc, GEN x, GEN y} given \kbd{zkc} from \kbd{zkchineseinit}, and $x$, $y$ two integral elements given as \typ{INT} or \kbd{ZC}, return a $z$ modulo $AB$ such that $z = x \mod A$ and $z = y \mod B$. \fun{GEN}{zkchinese1}{GEN zkc, GEN x} as \kbd{zkchinese} for $y = 1$; useful to lift elements in a nice way from $(\Z_K/A_i)^*$ to $(\Z_K/\prod_i A_i)^*$. \fun{GEN}{hnfmerge_get_1}{GEN A, GEN B} given two square upper HNF integral matrices $A$, $B$ of the same dimension $n > 0$, return $a$ in the image of $A$ such that $1-a$ is in the image of $B$. (By abuse of notation we denote $1$ the column vector $[1,0,\dots,0]$.) If such an $a$ does not exist, return \kbd{NULL}. This is the function underlying \tet{idealaddtoone}. \fun{GEN}{idealaddmultoone}{GEN nf, GEN v} given a list of $n$ (globally) coprime integer ideals $(v[i])$ returns an $n$-dimensional vector $a$ such that $a[i]\in v[i]$ and $\sum a[i] = 1$. If $[K:\Q] = N$, this routine computes the HNF reduction (with $Gl_{nN}(\Z)$ base change) of an $N\times nN$ matrix; so it is well worth pruning "useless" ideals from the list (as long as the ideals remain globally coprime). \fun{GEN}{idealapprfact}{GEN nf, GEN fx} as \tet{idealappr}, except that $x$ \emph{must} be given in factored form. (This is unchecked.) \fun{GEN}{idealcoprime}{GEN nf, GEN x, GEN y}. Given 2 integral ideals $x$ and $y$, returns an algebraic number $\alpha$ such that $\alpha x$ is an integral ideal coprime to $y$. \fun{GEN}{idealcoprimefact}{GEN nf, GEN x, GEN fy} same as \tet{idealcoprime}, except that $y$ is given in factored form, as from \tet{idealfactor}. \fun{GEN}{idealchinese}{GEN nf, GEN x, GEN y} \fun{GEN}{idealchineseinit}{GEN nf, GEN x} \subsec{Maximal ideals} The PARI structure attached to maximal ideals is a \tev{prid} (for \emph{pr}ime \emph{id}eal), usually produced by \tet{idealprimedec} and \tet{idealfactor}. In this section, we describe the format; other sections will deal with their daily use. A \var{prid} attached to a maximal ideal $\goth{p}$ stores the following data: the underlying rational prime $p$, the ramification degree $e\geq 1$, the residue field degree $f\geq 1$, a $p$-uniformizer $\pi$ with valuation $1$ at $\goth{p}$ and valuation $0$ at all other primes dividing $p$ and a rescaled ``anti-uniformizer'' $\tau$ used to compute valuations. This $\tau$ is an algebraic integer such that $\tau/p$ has valuation $-1$ at $\goth{p}$ and is integral at all other primes; in particular, the valuation of $x\in\Z_K$ is positive if and only if the algebraic integer $x\tau$ is divisible by $p$ (easy to check for elements in \typ{COL} form). \fun{GEN}{pr_get_p}{GEN pr} returns $p$. Shallow function. \fun{GEN}{pr_get_gen}{GEN pr} returns $\pi$. Shallow function. \fun{long}{pr_get_e}{GEN pr} returns $e$. \fun{long}{pr_get_f}{GEN pr} returns $f$. \fun{GEN}{pr_get_tau}{GEN pr} returns $\tet{zk_scalar_or_multable}(\var{nf}, \tau)$, which is the \typ{INT}~$1$ iff $p$ is inert, and a \kbd{ZM} otherwise. Shallow function. \fun{int}{pr_is_inert}{GEN pr} returns $1$ if $p$ is inert, $0$ otherwise. \fun{GEN}{pr_norm}{GEN pr} returns the norm $p^f$ of the maximal ideal. \fun{ulong}{upr_norm}{GEN pr} returns the norm $p^f$ of the maximal ideal, as an \kbd{ulong}. Assume that the result does not overflow. \fun{GEN}{pr_hnf}{GEN pr} return the HNF of $\goth{p}$. \fun{GEN}{pr_inv}{GEN pr} return the fractional ideal $\goth{p}^{-1}$, in HNF. \fun{GEN}{pr_inv_p}{GEN pr} return the integral ideal $p \goth{p}^{-1}$, in HNF. \fun{GEN}{idealprimedec}{GEN nf, GEN p} list of maximal ideals dividing the prime $p$. \fun{GEN}{idealprimedec_limit_f}{GEN nf, GEN p, long f} as \tet{idealprimedec}, limiting the list to primes of residual degree $\leq f$ if $f$ is nonzero. \fun{GEN}{idealprimedec_limit_norm}{GEN nf, GEN p, GEN B} as \tet{idealprimedec}, limiting the list to primes of norm $\leq B$, which must be a positive \typ{INT}. \fun{GEN}{idealprimedec_galois}{GEN nf, GEN p} return a single prime ideal above $p$. The \kbd{nf} argument is a true \var{nf} structure. \fun{GEN}{idealprimedec_degrees}{GEN nf, GEN p} return a (sorted) \typ{VECSMALL} containing the residue degrees $f(\goth{p} / p)$. The \kbd{nf} argument is a true \var{nf} structure. \fun{GEN}{idealprimedec_kummer}{GEN nf, GEN Ti, long ei, GEN p} let \var{nf} (true \var{nf}) correspond to $K = \Q[X]/(T)$ ($T$ monic \kbd{ZX}). Let $T \equiv \prod_i T_i^{e_i} \pmod{p}$ be the factorization of $T$ and let $(f,g,h)$ be as in Dedekind criterion for prime $p$: $f \equiv \prod T_i$, $g \equiv \prod T_i^{e_i-1}$, $h = (T - fg) / p$, and let $D$ be the gcd of $(f,g,h)$ in $\F_p[X]$. Let \kbd{Ti} (\kbd{FpX}) be one irreducible factor $T_i$ not dividing $D$, with \kbd{ei} $= e_i$. This function returns the prime ideal attached to $T_i$ by Kummer / Dedekind criterion, namely $p \Z_K + T_i(\bar{X}) \Z_K$, which has ramification index $e_i$ over $p$. The \kbd{nf} argument is a true \var{nf} structure. Shallow function. \fun{GEN}{idealfactor}{GEN nf, GEN x} factors the fractional (hence nonzero) ideal $x$ into prime ideal powers; return the factorization matrix. \fun{GEN}{idealfactor_limit}{GEN nf, GEN x, ulong lim} as \kbd{idealfactor}, including only prime ideals above rational primes $< \kbd{lim}$. \fun{GEN}{idealfactor_partial}{GEN nf, GEN x, GEN L} return partial factorization of fractional ideal $x$ as limited by argument $L$: \item $L = \kbd{NULL}$: as \kbd{idealfactor}; \item $L$ a \typ{INT}: as \kbd{idealfactor\_limit}; \item $L$ a vector of prime ideals of \var{nf} and/or rational primes (standing for ``all prime ideal divisors of given rational prime'') limit factorization to trial division by elements of $L$; do not include the cofactor. For efficiency, the list should not contain the same element twice, nor both a rational prime and one of its prime ideal divisors, but the function will work in that case as well. \fun{GEN}{idealHNF_Z_factor}{GEN x, GEN *pvN, GEN *pvZ} given an integral (nonzero) ideal $x$ in HNF, compute both the factorization of $Nx$ and of $x\cap\Z$. This returns the vector of prime divisors of both and sets \kbd{*pvN} and \kbd{*pvZ} to the corresponding \typ{VECSMALL} vector of exponents for the factorization for the Norm and intersection with $\Z$ respetively. \fun{GEN}{idealHNF_Z_factor_i}{GEN x, GEN fa, GEN *pvN, GEN *pvZ} internal variant of \tet{idealHNF_Z_factor} where \kbd{fa} is either a partial factorization of $x\cap \Z$ ($= x[1,1]$) or \kbd{NULL}. Returns the prime divisors of $x$ above the rational primes in \kbd{fa} and attached \kbd{vN} and \kbd{vZ}. If \kbd{fa} is \kbd{NULL}, use the full factorization, i.e. identical to \tet{idealHNF_Z_factor}. \fun{GEN}{nf_pV_to_prV}{GEN}{nf, GEN P} given a vector of rational primes $P$, return the vector of all prime ideals above the $P[i]$. \fun{GEN}{nf_deg1_prime}{GEN nf} let \kbd{nf} be a true \var{nf}. This function returns a degree $1$ (unramified) prime ideal not dividing \kbd{nf.index}. In fact it returns an ideal above the smallest prime $p \geq [K:\Q]$ satisfying those conditions. \fun{GEN}{prV_lcm_capZ}{GEN L} given a vector $L$ of \var{prid} (maximal ideals) return the squarefree positive integer generating their lcm intersected with $\Z$. Not \kbd{gerepile}-safe. \fun{GEN}{prV_primes}{GEN}{GEN L} given a vector of \kbd{prid}, return the (sorted) list of rational primes $P$ they divide. Not \kbd{gerepile}-clean but suitable for \kbd{gerepileupto}. \fun{GEN}{pr_uniformizer}{GEN pr, GEN F} given a \var{prid} attached to $\goth{p} / p$ and $F$ in $\Z$ divisible exactly by $p$, return an $F$-uniformizer for \kbd{pr}, i.e. a $t$ in $\Z_K$ such that $v_{\goth{p}}(t) = 1$ and $(t, F/\goth{p}) = 1$. Not \kbd{gerepile}-safe. \subsec{Decomposition groups} \fun{GEN}{idealramfrobenius}{GEN nf, GEN gal, GEN pr, GEN ram} 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 ramified, and \kbd{ram} is its list of ramification groups as output by \kbd{idealramgroups}. This function returns a permutation of \kbd{gal.group} which defines an automorphism $\sigma$ in the decomposition group of $\goth{P}$ such that if $p$ is the unique prime number in $\goth{P}$, then $\sigma(x)\equiv x^p\mod\P$ for all $x\in\Z_K$. \fun{GEN}{idealramfrobenius_aut}{GEN nf, GEN gal, GEN pr, GEN ram, GEN aut} as \kbd{idealramfrobenius(nf, gal, pr, ram}. \fun{GEN}{idealramgroups_aut}{GEN nf, GEN gal, GEN pr, GEN aut} as \kbd{idealramgroups(nf, gal, pr}. \fun{GEN}{idealfrobenius_aut}{GEN nf, GEN gal, GEN pr, GEN aut} faster version of \kbd{idealfrobenius(nf, gal, pr} where \kbd{aut} must be equal to \kbd{nfgaloispermtobasis(nf, gal)}. \subsec{Reducing modulo maximal ideals} \fun{GEN}{nfmodprinit}{GEN nf, GEN pr} returns an abstract \kbd{modpr} structure, attached to reduction modulo the maximal ideal \kbd{pr}, in \kbd{idealprimedec} format. From this data we can quickly project any \kbd{pr}-integral number field element to the residue field. \fun{GEN}{modpr_get_pr}{GEN x} return the \kbd{pr} component from a \kbd{modpr} structure. \fun{GEN}{modpr_get_p}{GEN x} return the $p$ component from a \kbd{modpr} structure (underlying rational prime). \fun{GEN}{modpr_get_T}{GEN x} return the \kbd{T} component from a \kbd{modpr} structure: either \kbd{NULL} (prime of degree $1$) or an irreducible \kbd{FpX} defining the residue field over $\F_p$. In library mode, it is often easier to use directly \fun{GEN}{nf_to_Fq_init}{GEN nf, GEN *ppr, GEN *pT, GEN *pp} concrete version of \kbd{nfmodprinit}: \kbd{nf} and \kbd{*ppr} are the inputs, the return value is a \kbd{modpr} and \kbd{*ppr}, \kbd{*pT} and \kbd{*pp} are set as side effects. The input \kbd{*ppr} is either a maximal ideal or already a \kbd{modpr} (in which case it is replaced by the underlying maximal ideal). The residue field is realized as $\F_p[X]/(T)$ for some monic $T\in\F_p[X]$, and we set \kbd{*pT} to $T$ and \kbd{*pp} to $p$. Set $T = \kbd{NULL}$ if the prime has degree $1$ and the residue field is $\F_p$. In short, this receives (or initializes) a \kbd{modpr} structure, and extracts from it $T$, $p$ and $\goth{p}$. \fun{GEN}{nf_to_Fq}{GEN nf, GEN x, GEN modpr} returns an \kbd{Fq} congruent to $x$ modulo the maximal ideal attached to \kbd{modpr}. The output is canonical: all elements in a given residue class are represented by the same \kbd{Fq}. \fun{GEN}{Fq_to_nf}{GEN x, GEN modpr} returns an \kbd{nf} element lifting the residue field element $x$, either a \typ{INT} or an algebraic integer in \kbd{algtobasis} format. \fun{GEN}{modpr_genFq}{GEN modpr} Returns an \kbd{nf} element whose image by \tet{nf_to_Fq} is $X \pmod T$, if $\deg T>1$, else $1$. \fun{GEN}{zkmodprinit}{GEN nf, GEN pr} as \tet{nfmodprinit}, but we assume we will only reduce algebraic integers, hence do not initialize data allowing to remove denominators. More precisely, we can in fact still handle an $x$ whose rational denominator is not $0$ in the residue field (i.e. if the valuation of $x$ is nonnegative at all primes dividing $p$). \fun{GEN}{zk_to_Fq_init}{GEN nf, GEN *pr, GEN *T, GEN *p} as \kbd{nf\_to\_Fq\_init}, able to reduce only $p$-integral elements. \fun{GEN}{zk_to_Fq}{GEN x, GEN modpr} as \kbd{nf\_to\_Fq}, for a $p$-integral $x$. \fun{GEN}{nfM_to_FqM}{GEN M, GEN nf,GEN modpr} reduces a matrix of \kbd{nf} elements to the residue field; returns an \kbd{FqM}. \fun{GEN}{FqM_to_nfM}{GEN M, GEN modpr} lifts an \kbd{FqM} to a matrix of \kbd{nf} elements. \fun{GEN}{nfV_to_FqV}{GEN A, GEN nf,GEN modpr} reduces a vector of \kbd{nf} elements to the residue field; returns an \kbd{FqV} with the same type as \kbd{A} (\typ{VEC} or \typ{COL}). \fun{GEN}{FqV_to_nfV}{GEN A, GEN modpr} lifts an \kbd{FqV} to a vector of \kbd{nf} elements (same type as \kbd{A}). \fun{GEN}{nfX_to_FqX}{GEN Q, GEN nf,GEN modpr} reduces a polynomial with \kbd{nf} coefficients to the residue field; returns an \kbd{FqX}. \fun{GEN}{FqX_to_nfX}{GEN Q, GEN modpr} lifts an \kbd{FqX} to a polynomial with coefficients in \kbd{nf}. The following functions are technical and avoid computing a true \kbd{nfmodpr}: \fun{GEN}{pr_basis_perm}{GEN nf, GEN pr} given a true \var{nf} structure and a prime ideal \kbd{pr} above $p$, return as a \typ{VECSMALL} the $f(\goth{p}/p)$ indices $i$ such that the \kbd{nf.zk}$[i]$ mod \goth{p} form an $\F_p$-basis of the residue field. \fun{GEN}{QXQV_to_FpM}{GEN v, GEN T, GEN p} let $p$ be a positive integer, $v$ be a vector of $n$ polynomials with rational coefficients whose denominators are coprime to $p$, and $T$ be a \kbd{ZX} (preferably monic) of degree $d$ whose leading coefficient is coprime to $p$. Return the $d \times n$ \kbd{FpM} whose columns are the $v[i]$ mod $T,p$ in the canonical basis $1, X, \dots, X^{d-1}$, see \kbd{RgX\_to\_RgC}. This is for instance useful when $v$ contains a $\Z$-basis of the maximal order of a number field $\Q[X]/(P)$, $p$ is a prime not dividing the index of $P$ and $T$ is an irreducible factor of $P$ mod $p$, attached to a maximal ideal $\goth{p}$: left-multiplication by the matrix maps number field elements (in basis form) to the residue field of $\goth{p}$. \subsec{Valuations} \fun{long}{nfval}{GEN nf, GEN x, GEN P} return $v_P(x)$ \misctitle{Unsafe functions} assume that $P$, $Q$ are \kbd{prid}. \fun{long}{ZC_nfval}{GEN x, GEN P} returns $v_P(x)$, assuming $x$ is a \kbd{ZC}, representing a nonzero algebraic integer. \fun{long}{ZC_nfvalrem}{GEN x, GEN P, GEN *newx} returns $v = v_P(x)$, assuming $x$ is a \kbd{ZC}, representing a nonzero algebraic integer, and sets \kbd{*newx} to $x\tau^v$ which is an algebraic integer coprime to $p$. \fun{int}{ZC_prdvd}{GEN x, GEN P} returns $1$ is $P$ divides $x$ and $0$ otherwise. Assumes that $x$ is a \kbd{ZC}, representing an algebraic integer. Faster than computing $v_P(x)$. \fun{int}{pr_equal}{GEN P, GEN Q} returns 1 is $P$ and $Q$ represent the same maximal ideal: they must lie above the same $p$ and share the same $e,f$ invariants, but the $p$-uniformizer and $\tau$ element may differ. Returns $0$ otherwise. \subsec{Signatures}\label{se:signatures} ``Signs'' of the real embeddings of number field element are represented in additive notation, using the standard identification $(\Z/2\Z, +) \to (\{-1,1\},\times)$, $s\mapsto (-1)^s$. With respect to a fixed \kbd{nf} structure, a selection of real places (a divisor at infinity) is normally given as a \typ{VECSMALL} of indices of the roots \kbd{nf.roots} of the defining polynomial for the number field. For compatibility reasons, in particular under GP, the (obsolete) \kbd{vec01} form is also accepted: a \typ{VEC} with \kbd{gen\_0} or \kbd{gen\_1} entries. The following internal functions go back and forth between the two representations for the Archimedean part of divisors (GP: $0/1$ vectors, library: list of indices): \fun{GEN}{vec01_to_indices}{GEN v} given a \typ{VEC} $v$ with \typ{INT} entries return as a \typ{VECSMALL} the list of indices $i$ such that $v[i] \neq 0$. (Typically used with $0,1$-vectors but not necessarily so.) If $v$ is already a \typ{VECSMALL}, return it: not suitable for \kbd{gerepile} in this case. \fun{GEN}{vecsmall01_to_indices}{GEN v} as \bprog vec01_to_indices(zv_to_ZV(v)); @eprog \fun{GEN}{indices_to_vec01}{GEN p, long n} return the $0/1$ vector of length $n$ with ones exactly at the positions $p[1], p[2], \ldots$ \fun{GEN}{nfsign}{GEN nf,GEN x} $x$ being a number field element and \kbd{nf} any form of number field, return the $0-1$-vector giving the signs of the $r_1$ real embeddings of $x$, as a \typ{VECSMALL}. Linear algebra functions like \tet{Flv_add_inplace} then allow keeping track of signs in series of multiplications. The argument \kbd{nf} is a true \var{nf} structure. If $x$ is a \typ{VEC} of number field elements, return the matrix whose columns are the signs of the $x[i]$. \fun{GEN}{nfsign_arch}{GEN nf,GEN x,GEN arch} \kbd{arch} being a list of distinct real places, either in \kbd{vec01} (\typ{VEC} with \kbd{gen\_0} or \kbd{gen\_1} entries) or \kbd{indices} (\typ{VECSMALL}) form (see \tet{vec01_to_indices}), returns the signs of $x$ at the corresponding places. This is the low-level function underlying \kbd{nfsign}. The argument \kbd{nf} is a true \var{nf} structure. \fun{int}{nfchecksigns}{GEN nf, GEN x, GEN pl} \var{pl} is a \typ{VECSMALL} with $r_1$ components, all of which are in $\{-1,0,1\}$. Return $1$ if $\sigma_i(x) \var{pl}[i] \geq 0$ for all $i$, and $0$ otherwise. \fun{GEN}{nfsign_units}{GEN bnf, GEN archp, int add_tu} \kbd{archp} being a divisor at infinity in \kbd{indices} form (or \kbd{NULL} for the divisor including all real places), return the signs at \kbd{archp} of a \kbd{bnf.tu} and of system of fundamental units for the field \kbd{bnf.fu}, in that order if \kbd{add\_tu} is set; and in the same order as \kbd{bnf.fu} otherwise. \fun{GEN}{nfsign_fu}{GEN bnf, GEN archp} returns the signs at \kbd{archp} of the fundamental units \kbd{bnf.fu}. This is an alias for \kbd{nfsign\_units} with \kbd{add\_tu} unset. \fun{GEN}{nfsign_tu}{GEN bnf, GEN archp} returns the signs at \kbd{archp} of the torsion unit generator \kbd{bnf.tu}. \fun{GEN}{nfsign_from_logarch}{GEN L, GEN invpi, GEN archp} given $L$ the vector of the $\log \sigma(x)$, where $\sigma$ runs through the (real or complex) embeddings of some number field, \kbd{invpi} being a floating point approximation to $1/\pi$, and \kbd{archp} being a divisor at infinity in \kbd{indices} form, return the signs of $x$ at the corresponding places. This is the low-level function underlying \kbd{nfsign\_units}; the latter is actually a trivial wrapper \kbd{bnf} structures include the $\log \sigma(x)$ for a system of fundamental units of the field. \fun{GEN}{set_sign_mod_divisor}{GEN nf, GEN x, GEN y, GEN sarch} let $f = f_0f_\infty$ be a divisor, let \kbd{sarch} be the output of \kbd{nfarchstar(nf, f0, finf)}, let $x$ encode a vector of signs at the places of $f_\infty$ (see below), and let $y$ be a nonzero number field element. Returns $z$ congruent to $y$ mod $f_0$ (integral if $y$ is) such that $z$ and $x$ have the same signs at $f_\infty$. The argument \kbd{nf} is a true \var{nf} structure. The following formats are supported for $x$: a $\{0,1\}$-vector of signs as a \typ{VECSMALL} (0 for positive, 1 for negative); \kbd{NULL} for a totally positive element (only $0$s); a number field element which is replaced by its signature at $f_\infty$. \fun{GEN}{nfarchstar}{GEN nf, GEN f0, GEN finf} for a divisor $f = f_0f_\infty$ represented by the integral ideal \kbd{f0} in HNF and the \kbd{finf} in \kbd{indices} form, returns $(\Z_K/f_\infty)^*$ in a form suitable for computations mod $f$. See \tet{set_sign_mod_divisor}. \fun{GEN}{idealprincipalunits}{GEN nf, GEN pr, long e} returns the multiplicative group $(1 + \var{pr}) / (1 + \var{pr}^e)$ as an abelian group. Faster than \tet{idealstar} when the norm of \var{pr} is large, since it avoids (useless) work in the multiplicative group of the residue field. \subsec{Complex embeddings} \fun{GEN}{nfembed}{GEN nf, GEN x, long k} returns a floating point approximation of the $k$-th embedding of $x$ (attached to the $k$-th complex root in \kbd{nf.roots}). Note that the semantic is different from \kbd{nfeltembed} (which increases the precision of \var{nf} until the embeddings have the requested precision): \kbd{nfembed} provides the embedding with the precision that is achievable given \var{nf}. \fun{GEN}{nfeltembed_i}{GEN *pnf, GEN x, GEN ind, long prec} as \kbd{nfeltembed}, except that no garbage collecting is performed and \kbd{*pnf} must be initially set to a (true) \var{nf} structure and, if the routine needs to increase the accuracy of \var{nf} to achieve the requested accuracy \kbd{prec}, then the functions sets it to the new more precise \var{nf}. \fun{GEN}{nf_cxlog}{GEN nf, GEN x, long prec} return the vector of complex logarithmic embeddings $(e_i \text{Log}(\sigma_i X))$ where $e_i = 1$ if $i \leq r_1$ and $e_i = 2$ if $r_1 < i \leq r_2$ of $X = \kbd{Q\_primpart}(x)$. Returns \kbd{NULL} if loss of accuracy. Not \kbd{gerepile}-clean but suitable for \kbd{gerepileupto}. Allows $x$ in compact representation, in which case \kbd{Q\_primpart} is taken componentwise. \fun{GEN}{nf_cxlog_normalize}{GEN nf, GEN x, long prec} an \var{nf} structure attached to a number field $K$ and $x$ from \kbd{nf\_cxlog}$(\var{nf}, X)$ (a column vector of complex logarithmic embeddings with $r_1 + r_2$ components) and let $e = (e_1,\dots,e_{r_1+r_2})$. Return $$ x - \dfrac{\log \big(N_{K/\Q} X\big)}{[K:\Q]} e $$ where the imaginary parts are further normalized modulo $2\pi i \cdot e$. The composition \kbd{nf\_cxlog} followed by~\kbd{nf\_cxlog\_normalize} is a morphism from $(K^*/\Q_+^*, \times)$ to $((\C/2\pi i\Z)^{r_1} \times (\C/4\pi i\Z)^{r_2}, +)$. Its real part maps the units $\Z_K^*$ to a lattice in the hyperplane $\sum_i x_i = 0$ in $\R^{r_1+r_2}$. \fun{GEN}{nfV_cxlog}{GEN nf, GEN x, long prec} applies \kbd{nf\_cxlog} to each component of the vector $x$. Returns \kbd{NULL} if loss of accuracy for even one component. Not \kbd{gerepile}-clean. \fun{GEN}{nflogembed}{GEN nf, GEN x, GEN *emb, long prec} return the vector of real logarithmic embeddings $(e_i \text{Log}|\sigma_i x|)$ where $e_i = 1$ if $i \leq r_1$ and $e_i = 2$ if $r_1 < i \leq r_2$. Returns \kbd{NULL} if loss of accuracy. Not \kbd{gerepile}-clean. If \kbd{emb} is non-\kbd{NULL} set it to $(e_i \sigma_i x)$. Allows $x$ in compact representation, in which case \kbd{emb} is returned in compact representation as well, as a factorization matrix (expanding the factorization may overflowexponents). \subsec{Maximal order and discriminant, conversion to \kbd{nf} structure} A number field $K = \Q[X]/(T)$ is defined by a monic $T\in\Z[X]$. The low-level function computing a maximal order is \fun{void}{nfmaxord}{nfmaxord_t *S, GEN T0, long flag}, where the polynomial $T_0$ is squarefree with integer coefficients. Let $K$ be the \'etale algebra $\Q[X]/(T_0)$ and let $T = \kbd{ZX\_Q\_normalize}(T_0)$, i.e. $T = C T_0(X/L)$ is monic and integral for some $C,Q\in \Q$. The structure \tet{nfmaxord_t} is initialized by the call; it has the following fields: \bprog GEN T0, T, dT, dK; /* T0, T, discriminants of T and K */ GEN unscale; /* the integer L */ GEN index; /* index of power basis in maximal order */ GEN dTP, dTE; /* factorization of |dT|, primes / exponents */ GEN dKP, dKE; /* factorization of |dK|, primes / exponents */ GEN basis; /* Z-basis for maximal order of Q[X]/(T) */ @eprog\noindent The exponent vectors are \typ{VECSMALL}. The primes in \kbd{dTP} and \kbd{dKP} are pseudoprimes, not proven primes. We recommend restricting to $T = T_0$, i.e. either to pass the input polynomial through \tet{ZX_Q_normalize} \emph{before} the call, or to forget about $T_0$ and go on with the polynomial $T$; otherwise $\kbd{unscale}\neq 1$, all data is expressed in terms of $T\neq T_0$, and needs to be converted to $T_0$. For instance to convert the basis to $\Q[X]/(T_0)$: \bprog RgXV_unscale(S.basis, S.unscale) @eprog Instead of passing $T$ (monic \kbd{ZX}), one can use the format $[T,\var{listP}]$ as in \kbd{nfbasis} or \kbd{nfinit}, which computes an order which is maximal at a set of primes, but need not be the maximal order. The \kbd{flag} is an or-ed combination of the binary flags, both of them deprecated: \tet{nf_PARTIALFACT}: do not try to fully factor \kbd{dT} and only look for primes less than \kbd{factorlimit}. In that case, the elements in \kbd{dTP} and \kbd{dKP} need not all be primes. But the resulting \kbd{dK}, \kbd{index} and \kbd{basis} are correct provided there exists no prime $p > \kbd{factorlimit}$ such that $p^2$ divides the field discriminant \kbd{dK}. This flag is \emph{deprecated}: the $[T,\var{listP}]$ format is safer and more flexible. \tet{nf_ROUND2}: this flag is \emph{deprecated} and now ignored. \fun{void}{nfinit_basic}{nfmaxord_t *S, GEN T0} a wrapper around \kbd{nfmaxord} (without the deprecated \kbd{flag}) that also accepts number field structures (\var{nf}, \var{bnf}, \dots) for \kbd{T0}. \fun{GEN}{nfmaxord_to_nf}{nfmaxord_t *S, GEN ro, long prec} convert an \tet{nfmaxord_t} to an \var{nf} structure at precision \kbd{prec}, where \kbd{ro} is \kbd{NULL}. The argument \kbd{ro} may also be set to a vector with $r_1 + r_2$ components containing the roots of \kbd{S->T} suitably ordered, i.e. first $r_1$ \typ{REAL} roots, then $r_2$ \typ{COMPLEX} representing the conguate pairs, but this is \emph{strongly discouraged}: the format is error-prone, and it is hard to compute the roots to the right accuracy in order to achieve \kbd{prec} accuracy for the \kbd{nf}. This function uses the integer basis \kbd{S->basis} as is, \emph{without} performing LLL-reduction. Unless the basis is already known to be reduced, use rather the following higher-level function: \fun{GEN}{nfinit_complete}{nfmaxord_t *S, long flag, long prec} convert an \tet{nfmaxord_t} to an \var{nf} structure at precision \kbd{prec}. The \kbd{flag} has the same meaning as in \kbd{nfinit0}. If \kbd{S->basis} is known to be reduced, it will be faster to use \tet{nfmaxord_to_nf}. \fun{GEN}{indexpartial}{GEN T, GEN dT} $T$ a monic separable \kbd{ZX}, \kbd{dT} is either \kbd{NULL} (no information) or a multiple of the discriminant of $T$. Let $K = \Q[X]/(T)$ and $\Z_K$ its maximal order. Returns a multiple of the exponent of the quotient group $\Z_K/(\Z[X]/(T))$. In other word, a \emph{denominator} $d$ such that $d x\in\Z[X]/(T)$ for all $x\in\Z_K$. \fun{GEN}{FpX_gcd_check}{GEN x, GEN y, GEN D} let $x$ and $y$ be two coprime polynomials with integer coefficients and let $D$ be a factor of the resultant of $x$ and $y$; try to factor $D$ by running the Euclidean algorithm on $x$ and $y$ modulo $D$. This returns \kbd{NULL} or a non trivial factor of $D$. This is the low-level function underlying \kbd{poldiscfactors} (applied to $x$, \kbd{ZX\_deriv}$(x)$ and the discriminant of $x$). It succeeds when $D$ has at least two prime divisors $p$ and $q$ such that one sub-resultant of $x$ and $y$ is divisible by $p$ but not by $q$. \subsec{Computing in the class group} We compute with arbitrary ideal representatives (in any of the various formats seen above), and call \fun{GEN}{bnfisprincipal0}{GEN bnf, GEN x, long flag}. The \kbd{bnf} structure already contains information about the class group in the form $\oplus_{i=1}^n (\Z/d_i\Z) g_i$ for canonical integers $d_i$ (with $d_n\mid\dots\mid d_1$ all $> 1$) and essentially random generators $g_i$, which are ideals in HNF. We normally do not need the value of the $g_i$, only that they are fixed once and for all and that any (nonzero) fractional ideal $x$ can be expressed uniquely as $x = (t)\prod_{i=1}^n g_i^{e_i}$, where $0 \leq e_i < d_i$, and $(t)$ is some principal ideal. Computing $e$ is straightforward, but $t$ may be very expensive to obtain explicitly. The routine returns (possibly partial) information about the pair $[e,t]$, depending on \kbd{flag}, which is an or-ed combination of the following symbolic flags: \item \tet{nf_GEN} tries to compute $t$. Returns $[e,t]$, with $t$ an empty vector if the computation failed. This flag is normally useless in nontrivial situations since the next two serve analogous purposes in more efficient ways. \item \tet{nf_GENMAT} tries to compute $t$ in factored form, which is much more efficient than \kbd{nf\_GEN} if the class group is moderately large; imagine a small ideal $x = (t)g^{10000}$: the norm of $t$ has $10000$ as many digits as the norm of $g$; do we want to see it as a vector of huge meaningless integers? The idea is to compute $e$ first, which is easy, then compute $(t)$ as $x \prod g_i^{-e_i}$ using successive \tet{idealmulred}, where the ideal reduction extracts small principal ideals along the way, eventually raised to large powers because of the binary exponentiation technique; the point is to keep this principal part in factored \emph{unexpanded} form. Returns $[e,t]$, with $t$ an empty vector if the computation failed; this should be exceedingly rare, unless the initial accuracy to which \kbd{bnf} was computed was ridiculously low (and then \kbd{bnfinit} should not have succeeded either). Setting/unsetting \kbd{nf\_GEN} has no effect when this flag is set. \item \tet{nf_GEN_IF_PRINCIPAL} tries to compute $t$ \emph{only} if the ideal is principal ($e = 0$). Returns \kbd{gen\_0} if the ideal is not principal. Setting/unsetting \kbd{nf\_GEN} has no effect when this flag is set, but setting/unsetting \kbd{nf\_GENMAT} is possible. \item \tet{nf_FORCE} in the above, insist on computing $t$, even if it requires recomputing a \kbd{bnf} from scratch. This is a last resort, and normally the accuracy of a \kbd{bnf} can be increased without trouble, but it may be that some algebraic information simply cannot be recovered from what we have: see \tet{bnfnewprec}. It should be very rare, though. In simple cases where you do not care about $t$, you may use \fun{GEN}{isprincipal}{GEN bnf, GEN x}, which is a shortcut for \kbd{bnfisprincipal0(bnf, x, 0)}. The following low-level functions are often more useful: \fun{GEN}{isprincipalfact}{GEN bnf, GEN C, GEN L, GEN f, long flag} is about the same as \kbd{bnfisprincipal0} applied to $C \prod L[i]^{f[i]}$, where the $L[i]$ are ideals, the $f[i]$ integers and $C$ is either an ideal or \kbd{NULL} (omitted). Make sure to include \tet{nf_GENMAT} in \kbd{flag}! \fun{GEN}{isprincipalfact_or_fail}{GEN bnf, GEN C, GEN L, GEN f} is for delicate cases, where we must be more clever than \kbd{nf\_FORCE} (it is used when trying to increase the accuracy of a \var{bnf}, for instance). If performs \bprog isprincipalfact(bnf,C, L, f, nf_GENMAT); @eprog\noindent but if it fails to compute $t$, it just returns a \typ{INT}, which is the estimated precision (in words, as usual) that would have been sufficient to complete the computation. The point is that \kbd{nf\_FORCE} does exactly this internally, but goes on increasing the accuracy of the \kbd{bnf}, then discarding it, which is a major inefficiency if you intend to compute lots of discrete logs and have selected a precision which is just too low. (It is sometimes not so bad since most of the really expensive data is cached in \kbd{bnf} anyway, if all goes well.) With this function, the \emph{caller} may decide to increase the accuracy using \tet{bnfnewprec} (and keep the resulting \kbd{bnf}!), or avoid the computation altogether. In any case the decision can be taken at the place where it is most likely to be correct. \fun{void}{bnftestprimes}{GEN bnf, GEN B} is an ingredient to certify unconditionnally a \kbd{bnf} computed assuming GRH, cf. \kbd{bnfcertify}. Running this function successfully proves that the classes of all prime ideals of norm $\leq B$ belong to the subgroup of the class group generated by the factorbase used to compute the \kbd{bnf} (equal to the class group under GRH). If the condition is not true, then (GRH is false and) the function will run forever. If it is known that primes of norm less than $B$ generate the class group (through variants of Minkowski's convex body or Zimmert's twin classes theorems), then the true class group is proven to be a quotient of \kbd{bnf.clgp}. \subsec{Floating point embeddings, the $T_2$ quadratic form} We assume the \var{nf} is a true \kbd{nf} structure, attached to a number field $K$ of degree $n$ and signature $(r_1,r_2)$. We saw that \fun{GEN}{nf_get_M}{GEN nf} returns the $(r_1+r_2)\times n$ matrix $M$ giving the embeddings of $K$, so that if $v$ is an $n$-th dimensional \typ{COL} representing the element $\sum_{i=1}^n v[i] w_i$ of $K$, then \kbd{RgM\_RgC\_mul(M,v)} represents the embeddings of $v$. Its first $r_1$ components are real numbers (\typ{INT}, \typ{FRAC} or \typ{REAL}, usually the latter), and the last $r_2$ are complex numbers (usually of \typ{COMPLEX}, but not necessarily for embeddings of rational numbers). \fun{GEN}{embed_T2}{GEN x, long r1} assuming $x$ is the vector of floating point embeddings of some algebraic number $v$, i.e. \bprog x = RgM_RgC_mul(nf_get_M(nf), algtobasis(nf,v)); @eprog\noindent returns $T_2(v)$. If the floating point embeddings themselves are not needed, but only the values of $T_2$, it is more efficient to restrict to real arithmetic and use \bprog gnorml2( RgM_RgC_mul(nf_get_G(nf), algtobasis(nf,v))); @eprog \fun{GEN}{embednorm_T2}{GEN x, long r1} analogous to \tet{embed_T2}, applied to the \kbd{gnorm} of the floating point embeddings. Assuming that \bprog x = gnorm( RgM_RgC_mul(nf_get_M(nf), algtobasis(nf,v)) ); @eprog\noindent returns $T_2(v)$. \fun{GEN}{embed_roots}{GEN z, long r1} given a vector $z$ of $r_1+r_2$ complex embeddings of the algebraic number $v$, return the $r_1+2r_2$ roots of its characteristic polynomial. Shallow function. \fun{GEN}{embed_disc}{GEN z, long r1, long prec} given a vector $z$ of $r_1+r_2$ complex embeddings of the algebraic number $v$, return a floating point approximation of the discriminant of its characteristic polynomial as a \typ{REAL} of precision \kbd{prec}. \fun{GEN}{embed_norm}{GEN x, long r1} given a vector $z$ of $r_1+r_2$ complex embeddings of the algebraic number $v$, return (a floating point approximation of) the norm of $v$. \subsec{Ideal reduction, low level} In the following routines \var{nf} is a true \kbd{nf}, attached to a number field $K$ of degree $n$: \fun{GEN}{nf_get_Gtwist}{GEN nf, GEN v} assuming $v$ is a \typ{VECSMALL} with $r_1+r_2$ entries, let $$|| x ||_v^2 = \sum_{i=1}^{r_1+r_2} 2^{v_i}\varepsilon_i|\sigma_i(x)|^2,$$ where as usual the $\sigma_i$ are the (real and) complex embeddings and $\varepsilon_i = 1$, resp.~$2$, for a real, resp.~complex place. This is a twisted variant of the $T_2$ quadratic form, the standard Euclidean form on $K\otimes \R$. In applications, only the relative size of the $v_i$ will matter. Let $G_v\in M_n(\R)$ be a square matrix such that if $x\in K$ is represented by the column vector $X$ in terms of the fixed $\Z$-basis of $\Z_K$ in \var{nf}, then $$||x||_v^2 = {}^t (G_v X) \cdot G_v X.$$ (This is a kind of Cholesky decomposition.) This function returns a rescaled copy of $G_v$, rounded to nearest integers, specifically \tet{RM_round_maxrank}$(G_v)$. Suitable for \kbd{gerepileupto}, but does not collect garbage. For convenience, also allow $v = $\kbd{NULL} (\tet{nf_get_roundG}) and $v$ a \typ{MAT} as output from the function itself: in both these cases, shallow function. \fun{GEN}{nf_get_Gtwist1}{GEN nf, long i}. Simple special case. Returns the twisted $G$ matrix attached to the vector $v$ whose entries are all $0$ except the $i$-th one, which is equal to $10$. \fun{GEN}{idealpseudomin}{GEN x, GEN G}. Let $x$, $G$ be two \kbd{ZM}s, such that the product $Gx$ is well-defined. This returns a ``small'' integral linear combinations of the columns of $x$, given by the LLL-algorithm applied to the lattice $G x$. Suitable for \kbd{gerepileupto}, but does not collect garbage. In applications, $x$ is an integral ideal, $G$ approximates a Cholesky form for the $T_2$ quadratic form as returned by \tet{nf_get_Gtwist}, and we return a small element $a$ in the lattice $(x,T_2)$. This is used to implement \tet{idealred}. \fun{GEN}{idealpseudomin_nonscalar}{GEN x, GEN G}. As \tet{idealpseudomin}, but we insist of returning a nonscalar $a$ (\kbd{ZV\_isscalar} is false), if the dimension of $x$ is $> 1$. In the interpretation where $x$ defines an integral ideal on a fixed $\Z_K$ basis whose first element is $1$, this means that $a$ is not rational. \fun{GEN}{idealpseudominvec}{GEN x, GEN G}. As \tet{idealpseudomin_nonscalar}, but we return about $n^2/2$ nonscalar elements in $x$ with small $T_2$-norm, where the dimension of $x$ is $n$. \fun{GEN}{idealpseudored}{GEN x, GEN G}. As \tet{idealpseudomin} but we return the full reduced $\Z$-basis of $x$ as a \typ{MAT} instead of a single vector. \fun{GEN}{idealred_elt}{GEN nf, GEN x} shortcut for \bprog idealpseudomin(x, nf_get_roundG(nf)) @eprog \subsec{Ideal reduction, high level} \label{se:Ideal_reduction} Given an ideal $x$ this means finding a ``simpler'' ideal in the same ideal class. The public GP function is of course available \fun{GEN}{idealred0}{GEN nf, GEN x, GEN v} finds an $a\in K^*$ such that $(a) x$ is integral of small norm and returns it, as an ideal in HNF. What ``small'' means depends on the parameter $v$, see the GP description. More precisely, $a$ is returned by \kbd{idealpseudomin}$((x_\Z) x^(-1),G)$ divided by $x_\Z$, where $x_\Z = (x\cap \Z)$ and where $G$ is \tet{nf_get_Gtwist}$(\var{nf}, v)$ for $v\neq \kbd{NULL}$ and \tet{nf_get_roundG}$(\var{nf})$ otherwise. \noindent Usually one sets $v = \kbd{NULL}$ to obtain an element of small $T_2$ norm in $x$: \fun{GEN}{idealred}{GEN nf, GEN x} is a shortcut for \kbd{idealred0(nf,x,NULL)}. The function \kbd{idealred} remains complicated to use: in order not to lose information $x$ must be an extended ideal, otherwise the value of $a$ is lost. There is a subtlety here: the principal ideal $(a)$ is easy to recover, but $a$ itself is an instance of the principal ideal problem which is very difficult given only an \var{nf} (once a \var{bnf} structure is available, \tet{bnfisprincipal0} will recover it). \fun{GEN}{idealmoddivisor}{GEN bnr, GEN x} A proof-of-concept implementation, useless in practice. If \kbd{bnr} is attached to some modulus $f$, returns a ``small'' ideal in the same class as $x$ in the ray class group modulo $f$. The reason why this is useless is that using extended ideals with principal part in a computation, there is a simple way to reduce them: simply reduce the generator of the principal part in $(\Z_K/f)^*$. \fun{GEN}{famat_to_nf_moddivisor}{GEN nf, GEN g, GEN e, GEN bid} given a true \var{nf} attached to a number field $K$, a \var{bid} structure attached to a modulus $f$, and an algebraic number in factored form $\prod g[i]^{e[i]}$, such that $(g[i],f) = 1$ for all $i$, returns a small element in $\Z_K$ congruent to it mod $f$. Note that if $f$ contains places at infinity, this includes sign conditions at the specified places. A simpler case when the conductor has no place at infinity: \fun{GEN}{famat_to_nf_modideal_coprime}{GEN nf, GEN g, GEN e, GEN f, GEN expo} as above except that the ideal $f$ is now integral in HNF (no need for a full \var{bid}), and we pass the exponent of the group $(\Z_K/f)^*$ as \kbd{expo}; any multiple will also do, at the expense of efficiency. Of course if a \var{bid} for $f$ is available, if is easy to extract $f$ and the exact value of \kbd{expo} from it (the latter is the first elementary divisor in the group structure). A useful trick: if you set \kbd{expo} to \emph{any} positive integer, the result is correct up to \kbd{expo}-th powers, hence exact if \kbd{expo} is a multiple of the exponent; this is useful when trying to decide whether an element is a square in a residue field for instance! (take \kbd{expo}$ = 2$). \fun{GEN}{nf_to_Fp_coprime}{GEN nf, GEN x, GEN modpr} this low-level function is variant of \tet{famat_to_nf_modideal_coprime}: \var{nf} is a true \var{nf} structure, \kbd{modpr} is from \kbd{zkmodprinit} attached to a prime of degree $1$ above the prime number $p$, and $x$ is either a number field element or a \kbd{famat} factorization matrix. We finally assume that no component of $x$ has a denominator $p$. What to do when the $g[i]$ are not coprime to $f$, but only $\prod g[i]^{e[i]}$ is? Then the situation is more complicated, and we advise to solve it one prime divisor of $f$ at a time. Let $v$ be the valuation attached to a maximal ideal \kbd{pr}: \fun{GEN}{famat_makecoprime}{GEN nf, GEN g, GEN e, GEN pr, GEN prk, GEN expo} returns an element in $(\Z_K/\kbd{pr}^k)^*$ congruent to the product $\prod g[i]^{e[i]}$, assumed to be globally coprime to \kbd{pr}. As above, \kbd{expo} is any positive multiple of the exponent of $(\Z_K/\kbd{pr}^k)^*$, for instance $(Nv-1)p^{k-1}$, if $p$ is the underlying rational prime. You may use other values of \kbd{expo} (see the useful trick in \tet{famat_to_nf_modideal_coprime}). \fun{GEN}{sunits_makecoprime}{GEN g, GEN pr, GEN prk} is a specialized variant that allows to precondition a vector of $g[i]$ assumed to be integral primes or algebraic integers so that it becomes suitable for \kbd{famat\_to\_nf\_modideal\_coprime} modulo \kbd{pr}. This is in particular useful for the output of \kbd{bnf\_get\_sunits}. \fun{GEN}{Idealstarprk}{GEN nf, GEN pr, long k, long flag} same as \kbd{Idealstar} for $I = \kbd{pr}^k$. The \kbd{nf} argument is a true \var{nf} structure. \subsec{Class field theory} Under GP, a class-field theoretic description of a number field is given by a triple $A$, $B$, $C$, where the defining set $[A,B,C]$ can have any of the following forms: $[\var{bnr}]$, $[\var{bnr},\var{subgroup}]$, $[\var{bnf},\var{modulus}]$, $[\var{bnf},\var{modulus},\var{subgroup}]$. You can still use directly all of (\kbd{libpari}'s routines implementing) GP's functions as described in Chapter~3, but they are often awkward in the context of \kbd{libpari} programming. In particular, it does not make much sense to always input a triple $A,B,C$ because of the fringe $[\var{bnf},\var{modulus},\var{subgroup}]$. The first routine to call, is thus \fun{GEN}{Buchray}{GEN bnf, GEN mod, long flag} initializes a \var{bnr} structure from \kbd{bnf} and modulus \kbd{mod}. \kbd{flag} is an or-ed combination of \kbd{nf\_GEN} (include generators) and \kbd{nf\_INIT} (if omitted, do not return a \var{bnr}, only the ray class group as an abelian group). In fact, the single most useful value of \kbd{flag} is \kbd{nf\_INIT} to initialize a proper \var{bnr}: omitting \kbd{nf\_GEN} saves a lot of time and will not adversely affect any class field theoretic function; adding \kbd{nf\_GEN} makes debugging easier. The flag 0 allows to compute only the ray class group structure but will gain little time; if we only need the \emph{order} of the ray class group, then \tet{bnrclassno} is fastest. Now we have a proper \var{bnr} encoding a \kbd{bnf} and a modulus, we no longer need the $[\var{bnf},\var{modulus}]$ and $[\var{bnf},\var{modulus},\var{subgroup}]$ forms, which would internally call \tet{Buchray} anyway. Recall that a subgroup $H$ is given by a matrix in HNF, whose column express generators of $H$ on the fixed generators of the ray class group that stored in our \var{bnr}. You may also code the trivial subgroup by \kbd{NULL}. It is also allowed to replace $H$ by a character $\chi$ of the ray class group modulo \kbd{mod}: it represents the subgroup $\text{Ker} \chi$. \fun{GEN}{bnr_subgroup_check}{GEN bnr, GEN H, GEN *pdeg} given a \var{bnr} attached to a modulus \var{mod}, check whether $H$ represents a congruence subgroup (of the ray class group modulo \var{mod}) and returns a normalized representation: \kbd{NULL} for the trivial subgroup, or in HNF, reduced modulo the elementary divisors of the ray class group. In particular, if $H$ is a character of the ray class group, the returned value is the character kernel. If \kbd{pdeg} is not \kbd{NULL}, \kbd{*pdeg} is set to the degree of the attached class field: the index of $H$ in the ray class group. \fun{void}{bnr_subgroup_sanitize}{GEN *pbnr, GEN *pH} given a \var{bnr} and a congruence subgroup, make sanity checks and compute the subgroup conductor. Then replace the pair to match the conductor: the \var{bnr} has the right conductor as modulus, and the subgroup is normalized. Instead of a \var{bnr}, this function also accepts a \var{bnf} (gets replaced by the \var{bnr} with trivial conductor). Instead of a subgroup, the function also accepts an integer $N$ (replaced by $\text{Cl}_f(K)^N$) or a character (replaced by its kernel). \fun{void}{bnr_char_sanitize}{GEN *pbnr, GEN *pchi} same idea as \kbd{bnr\_subgroup\_sanitize}: we are given a \var{bnr} and a ray class character, make sanity checks and update the data to use the conductor as modulus. \fun{GEN}{bnrconductor}{GEN bnr, GEN H, long flag} see the documentation of the GP function. \fun{GEN}{bnrconductor_factored}{GEN bnr, GEN H} return a pair $[F,\var{fa}]$ where $F$ is the conductor and \var{fa} is the factorization of the finite part of the conductor. Shallow function. \fun{GEN}{bnrconductor_raw}{GEN bnr, GEN H} return the conductor of $H$. Shallow function. \fun{long}{bnrisconductor}{GEN bnr, GEN H} returns 1 is the class field defined by the subgroup $H$ (of the ray class group mod $f$ coded in \kbd{bnr}) has conductor $f$. Returns 0 otherwise. \fun{GEN}{ideallog_units}{GEN bnf, GEN bid} return the images of the units generators \kbd{bnf.tu} and \kbd{bnf.tu} in the finite abelian group $(\Z_K/f)^*$ attached to \kbd{bid}. \fun{GEN}{ideallog_units0}{GEN bnf, GEN bid, GEN N} let $G = (\Z_K/f)^*$ be the finite abelian group attached to \kbd{bid}. Return the images of the units generators \kbd{bnf.tu} and \kbd{bnf.tu} in $G / G^N$. If $N$ is \kbd{NULL}, same as \tet{ideallog_units}. \fun{GEN}{bnrchar_primitive}{GEN bnr, GEN chi, GEN bnrc} Given a normalized character $\kbd{chi} = [d,c]$ on \kbd{bnr.clgp} (see \tet{char_normalize}) of conductor \kbd{bnrc.mod}, compute the primitive character \kbd{chic} on \kbd{bnrc.clgp} equivalent to \kbd{chi}, given as a normalized character $[D,C]$ : \kbd{chic(bnrc.gen[i])} is $\zeta_D^{C[i]}$, where $D$ is minimal. It is easier to use \kbd{bnrconductor\_i(bnr,chi,2)}, but the latter recomputes \kbd{bnrc} for each new character. \fun{GEN}{bnrchar_primitive_raw}{GEN bnr, GEN chi, GEN bnrc} as \tet{bnrchar_primitive}, with \kbd{chi} a regular (unnormalized) character on \kbd{bnr.clgp} of conductor \kbd{bnrc.mod}. Return a regular (unnormalized) primitive character on \kbd{bnrc}. \fun{GEN}{bnrdisc}{GEN bnr, GEN H, long flag} returns the discriminant and signature of the class field defined by \kbd{bnr} and $H$. See the description of the GP function for details. \fl\ is an or-ed combination of the flags \tet{rnf_REL} (output relative data) and \tet{rnf_COND} (return 0 unless the modulus is the conductor). \fun{GEN}{ABC_to_bnr}{GEN A, GEN B, GEN C, GEN *H, int addgen} This is a quick conversion function designed to go from the too general (inefficient) $A$, $B$, $C$ form to the preferred \var{bnr}, $H$ form for class fields. Given $A$, $B$, $C$ as explained above (omitted entries coded by \kbd{NULL}), return the attached \var{bnr}, and set $H$ to the attached subgroup. If \kbd{addgen} is $1$, make sure that if the \var{bnr} needed to be computed, then it contains generators. \subsec{Abelian maps} A map $f:A\to B$ between two abelian groups of finite type is given by a triple: $[M, \var{cyc}_A, \var{cyc}_B]$, where $\var{cyc}_A = [a_1,\dots, a_m]$ and $\var{cyc}_B = [b_1,\dots, b_n]$ are the elementary divisors for $A$ and $B$ (see \kbd{ZM\_snf}) so that $A = \oplus_{i\leq m} (\Z/a_i\Z) g_i$ and $B = \sim \oplus_{j\leq n} (\Z/b_j\Z) G_j $. The matrix $M$ gives the image of the generators $g_i$ in terms of the $G_j$: $(f(g_i))_{i\leq m} = (G_j)_{j\leq n} \cdot M$. The function \kbd{bnrmap} returns such a structure. \fun{GEN}{bnrsurjection}{GEN BNR, GEN bnr} \kbd{BNR} and \kbd{bnr} defined over the same field $K$, for moduli $F$ and $f$ with $f\mid F$, returns the canonical surjection $\text{Cl}_K(F)\to \text{Cl}_K(f)$ as an abelian map. I.e., a triple $[M,\var{cyc}_F,\var{cyc}_f]$. $M$ gives the image of the fixed ray class group generators of \kbd{BNR} in terms of the ones in \kbd{bnr}, $\var{cyc}_F$ and $\var{cyc}_f$ are the cyclic structures of \kbd{BNR} and \kbd{bnr} respectively (as per \tet{bnr_get_cyc}). Shallow function. \fun{GEN}{abmap_kernel}{GEN S} returns the kernel of the abelian map $S$, ans a matrix $H$ in HNF: the subgroup is $(g_i)\cdot H$. \fun{GEN}{abmap_subgroup_image}{GEN S, GEN H} given a subgroup $H$ of $A$ (its generators are the $(g_i) H$); for efficiency, $H$ should be given in canonical form, i.e., as an HNF left divisor of $\var{diag}(a_1,\dots,a_m)$. Returns the subgroup $f(H)$ of $B$, as an HNF left divisor of $\var{diag}(b_1,\dots,b_n)$. \subsec{Grunwald--Wang theorem} \fun{GEN}{nfgwkummer}{GEN nf, GEN Lpr, GEN Ld, GEN pl, long var} low-level version of \kbd{nfgrunwaldwang}, assuming that \kbd{nf} contains suitable roots of unity, and directly using Kummer theory to construct the extension. \fun{GEN}{bnfgwgeneric}{GEN bnf, GEN Lpr, GEN Ld, GEN pl, long var} low-level version of \kbd{nfgrunwaldwang}, assuming that \kbd{bnf} is a \kbd{bnfinit} structure, and calling \kbd{rnfkummer} to construct the extension. \subsec{Relative equations, Galois conjugates} \fun{GEN}{nfissquarefree}{GEN nf, GEN P} given $P$ a polynomial with coefficients in \var{nf}, return $1$ is $P$ is squarefree, and $0$ otherwise. If is allowed (though less efficient) to replace \var{nf} by a monic \kbd{ZX} defining the field. \fun{GEN}{rnfequationall}{GEN A, GEN B, long *pk, GEN *pLPRS} $A$ is either an \var{nf} type (corresponding to a number field $K$) or an irreducible \kbd{ZX} defining a number field $K$. $B$ is an irreducible polynomial in $K[X]$. Returns an absolute equation $C$ (over $\Q$) for the number field $K[X]/(B)$. $C$ is the characteristic polynomial of $b + k a$ for some roots $a$ of $A$ and $b$ of $B$, and $k$ is a small rational integer. Set \kbd{*pk} to $k$. If \kbd{pLPRS} is not \kbd{NULL} set it to $[h_0, h_1]$, $h_i\in \Q[X]$, where $h_0+h_1 Y$ is the last nonconstant polynomial in the pseudo-Euclidean remainder sequence attached to $A(Y)$ and $B(X-kY)$, leading to $C = \text{Res}_Y(A(Y), B(X-kY))$. In particular $a := -h_0/h_1$ is a root of $A$ in $\Q[X]/(C)$, and $X - ka$ is a root of $B$. \fun{GEN}{nf_rnfeq}{GEN A, GEN B} wrapper around \tet{rnfequationall} to allow mapping $K\to L$ (\kbd{eltup}) and converting elements of $L$ between absolute and relative form (\kbd{reltoabs}, \kbd{abstorel}), \emph{without} computing a full \var{rnf} structure, which is useful if the relative integral basis is not required. In fact, since $A$ may be a \typ{POL} or an \var{nf}, the integral basis of the base field is not needed either. The return value is the same as \tet{rnf_get_map}. Shallow function. \fun{GEN}{nf_rnfeqsimple}{GEN A, GEN B} as \tet{nf_rnfeq} except some fields are omitted, so that only the \tet{abstorel} operation is supported. Shallow function. \fun{GEN}{eltabstorel}{GEN rnfeq, GEN x} \kbd{rnfeq} is as given by \tet{rnf_get_map} (but in this case \tet{rnfeltabstorel} is more robust), \tet{nf_rnfeq} or \tet{nf_rnfeqsimple}, return $x$ as an element of $L/K$, i.e. as a \typ{POLMOD} with \typ{POLMOD} coefficients. Shallow function. \fun{GEN}{eltabstorel_lift}{GEN rnfeq, GEN x} same as \tet{eltabstorel}, except that $x$ is returned in partially lifted form, i.e.~ as a \typ{POL} with \typ{POLMOD} coefficients. \fun{GEN}{eltreltoabs}{GEN rnfeq, GEN x} \kbd{rnfeq} is as given by \tet{rnf_get_map} (but in this case \tet{rnfeltreltoabs} is more robust) or \tet{nf_rnfeq}, return $x$ in absolute form. \fun{GEN}{nf_nfzk}{GEN nf, GEN rnfeq} \kbd{rnfeq} as given by \tet{nf_rnfeq}, \kbd{nf} a true \var{nf} structure, return a a suitable representation of \kbd{nf.zk} allowing quick computation of the map $K\to L$ by the function \tet{nfeltup}, \emph{without} computing a full \var{rnf} structure, which is useful if the relative integral basis is not required. The computed value is the same as in \tet{rnf_get_nfzk}. Shallow function. \fun{GEN}{nfeltup}{GEN nf, GEN x, GEN zknf} \kbd{zknf} and is initialized by \tet{nf_nfzk} or \tet{rnf_get_nfzk} (but in this case \tet{rnfeltup} is more robust); \kbd{nf} is a true \var{nf} structure for $K$, returns $x \in K$ as a (lifted) element of $L$, in absolute form. \fun{GEN}{rnfdisc_factored}{GEN nf, GEN pol, GEN *pd} variant of \kbd{rnfdisc} returning the relative discriminant ideal \emph{factorization}, and setting \kbd{*pd} to the discriminant as an element in $K^*/(K^*)^2$. Shallow function. The argument \kbd{nf} is a true \var{nf} structure. \fun{GEN}{Rg_nffix}{const char *f, GEN T, GEN c, int lift} given a \kbd{ZX} $T$ and a ``coefficient'' $c$ supposedly belonging to $\Q[y]/(T)$, check whether this is a the case and return a cleaned up version of $c$. The string $f$ is the calling function name, used to report errors. This means that $c$ must be one of \typ{INT}, \typ{FRAC}, \typ{POL} in the variable $y$ with rational coefficients, or \typ{POLMOD} modulo $T$ which lift to a rational \typ{POL} as above. The cleanup consists in the following improvements: \item \typ{POL} coefficients are reduced modulo $T$. \item \typ{POL} and \typ{POLMOD} belonging to $\Q$ are converted to rationals, \typ{INT} or \typ{FRAC}. \item if \kbd{lift} is nonzero, convert \typ{POLMOD} to \typ{POL}, and otherwise convert \typ{POL} to \typ{POLMOD}s modulo $T$. \fun{GEN}{RgX_nffix}{const char *f, GEN T, GEN P, int lift} check whether $P$ is a polynomials with coefficients in the number field defined by the absolute equation $T(y) = 0$, where $T$ is a \kbd{ZX} and returns a cleaned up version of $P$. This checks whether $P$ is indeed a \typ{POL} with variable compatible with coefficients in $\Q[y]/(T)$, i.e. \bprog varncmp(varn(P), varn(T)) < 0 @eprog\noindent and applies \tet{Rg_nffix} to each coefficient. \fun{GEN}{RgV_nffix}{const char *f, GEN T, GEN P, int lift} as \tet{RgX_nffix} for a vector of coefficients. \fun{GEN}{polmod_nffix}{const char *f, GEN rnf, GEN x, int lift} given a \typ{POLMOD} $x$ supposedly defining an element of \var{rnf}, check this and perform \tet{Rg_nffix} cleanups. \fun{GEN}{polmod_nffix2}{const char *f, GEN T, GEN P, GEN x, int lift} as in \tet{polmod_nffix}, where the relative extension is explicitly defined as $L = (\Q[y]/(T))[x]/(P)$, instead of by an \kbd{rnf} structure. \fun{long}{numberofconjugates}{GEN T, long pinit} returns a quick multiple for the number of $\Q$-automorphism of the (integral, monic) \typ{POL} $T$, from modular factorizations, starting from prime \kbd{pinit} (you can set it to $2$). This upper bounds often coincides with the actual number of conjugates. Of course, you should use \tet{nfgaloisconj} to be sure. \fun{GEN}{nfroots_if_split}{GEN *pt, GEN T} let \kbd{*pt} point either to a number field structure or an irreducible \kbd{ZX}, defining a number field $K$. Given $T$ a monic squarefree polynomial with coefficients in $\Z_K$, return the list of roots of \kbd{pol} in $K$ if the polynomial splits completely, and \kbd{NULL} otherwise. In other words, this checks whether $K[X]/(T)$ is normal over $K$ (hence Galois since $T$ is separable by assumption). In the case where \kbd{*pT} is a \kbd{ZX}, the function has to compute internally a conditional \kbd{nf} attached to $K$ , whose \kbd{nf.zk} may not define the maximal order $\Z_K$ (see \kbd{nfroots}); \kbd{*pT} is then replaced by the conditional \kbd{nf} to avoid losing that information. \fun{GEN}{rnfabelianconjgen}{GEN nf, GEN P} \var{nf} being a number field structure attached to $K$ and $P$ being an irreducible polynomial in $K[X]$. This function returns \kbd{gen\_0} if $L = K[X]/(P)$ is not abelian over $K$, else it returns a pair $(g,o)$ where $g$ is a vector of $K$-automorphisms of $L$ generating the abelian group $G = \text{Gal}(L/K)$ and $o$ is a \typ{VECSMALL} of the same length giving the relative orders of the $g_i$: $o[1]$ is the order of $g_1$ and for $i \geq 2$, $o[i]$ is the order of $g_i$ in $G/(g_1,\dots,g_{i-1})$. The length need not be minimal: the $o[i]$ need not be the elementary divisors of $G$. \subsec{Units} \fun{GEN}{nfrootsof1}{GEN nf} 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. \fun{GEN}{nfcyclotomicunits}{GEN nf, GEN zu} where \kbd{zu} is as output by \kbd{nfrootsof1(nf)}, return the vector of the cyclotomic units in \kbd{nf} expressed over the integral basis. If $\zeta = \zeta_n$ belongs to the base field ($n$ maximal), this function returns \item (when $n$ is not a prime power) the $\zeta^a - 1$, for all $1 \leq a < n/2$ such that $n/(a,n)$ is not a prime power and $a$ is a strict divisor of $n$. \item (all $n$) for $p$ prime, $v_p(n) = k > 0$, the $(z^a - 1)/(z - 1)$, where $z = \zeta^{n/p^k}$, for all $1 < a \leq (p^k-1) / 2$, $(p, a) = 1$. These are independent modulo torsion if $n$ is a prime power, but not necessarily so otherwise. \fun{GEN}{sunits_mod_units}{GEN bnf, GEN S} return independent generators for $U_S(K)/U(K)$. \subsec{Obsolete routines} Still provided for backward compatibility, but should not be used in new programs. They will eventually disappear. \fun{GEN}{zidealstar}{GEN nf, GEN x} short for \kbd{Idealstar(nf,x,nf\_GEN)} \fun{GEN}{zidealstarinit}{GEN nf, GEN x} short for \kbd{Idealstar(nf,x,nf\_INIT)} \fun{GEN}{zidealstarinitgen}{GEN nf, GEN x} short for \kbd{Idealstar(nf,x,nf\_GEN|nf\_INIT)} \fun{GEN}{idealstar0}{GEN nf, GEN x,long flag} short for \kbd{idealstarmod(nf, ideal, flag, NULL)}. Use \kbd{Idealstarmod} or \kbd{Idealstar}. \fun{GEN}{bnrinit0}{GEN bnf,GEN ideal,long flag} short for \kbd{bnrinitmod(bnf,ideal,flag,NULL)}. Use \kbd{Buchray} or \kbd{Buchraymod}. \fun{GEN}{buchimag}{GEN D, GEN c1, GEN c2, GEN gCO} short for \bprog Buchquad(D,gtodouble(c1),gtodouble(c2), /*ignored*/0) @eprog \fun{GEN}{buchreal}{GEN D, GEN gsens, GEN c1, GEN c2, GEN RELSUP, long prec} short for \bprog Buchquad(D,gtodouble(c1),gtodouble(c2), prec) @eprog The following use a naming scheme which is error-prone and not easily extensible; besides, they compute generators as per \kbd{nf\_GEN} and not \kbd{nf\_GENMAT}. Don't use them: \fun{GEN}{isprincipalforce}{GEN bnf,GEN x} \fun{GEN}{isprincipalgen}{GEN bnf, GEN x} \fun{GEN}{isprincipalgenforce}{GEN bnf, GEN x} \fun{GEN}{isprincipalraygen}{GEN bnr, GEN x}, use \tet{bnrisprincipal}. \noindent Variants on \kbd{polred}: use \kbd{polredbest}. \fun{GEN}{factoredpolred}{GEN x, GEN fa} \fun{GEN}{factoredpolred2}{GEN x, GEN fa} \fun{GEN}{smallpolred}{GEN x} \fun{GEN}{smallpolred2}{GEN x}, use \tet{Polred}. \fun{GEN}{polred0}{GEN x, long flag, GEN p} \fun{GEN}{polredabs}{GEN x} \fun{GEN}{polredabs2}{GEN x} \fun{GEN}{polredabsall}{GEN x, long flun} \noindent Superseded by \tet{bnrdisclist0}: \fun{GEN}{discrayabslist}{GEN bnf,GEN L} \fun{GEN}{discrayabslistarch}{GEN bnf, GEN arch, long bound} \noindent Superseded by \tet{idealappr} (\fl is ignored) \fun{GEN}{idealappr0}{GEN nf, GEN x, long flag} \noindent Superseded by \kbd{bnrconductor\_raw} or \kbd{bnrconductormod}: \fun{GEN}{bnrconductor_i}{GEN bnr, GEN H, long flag} shallow variant of \kbd{bnrconductor}. \fun{GEN}{bnrconductorofchar}{GEN bnr, GEN chi} \section{Galois extensions of $\Q$} This section describes the data structure output by the function \tet{galoisinit}. This will be called a \kbd{gal} structure in the following. \subsec{Extracting info from a \kbd{gal} structure} The functions below expect a \kbd{gal} structure and are shallow. See the documentation of \tet{galoisinit} for the meaning of the member functions. \fun{GEN}{gal_get_pol}{GEN gal} returns \kbd{gal.pol} \fun{GEN}{gal_get_p}{GEN gal} returns \kbd{gal.p} \fun{GEN}{gal_get_e}{GEN gal} returns the integer $e$ such that \kbd{gal.mod==gal.p\pow e}. \fun{GEN}{gal_get_mod}{GEN gal} returns \kbd{gal.mod}. \fun{GEN}{gal_get_roots}{GEN gal} returns \kbd{gal.roots}. \fun{GEN}{gal_get_invvdm}{GEN gal} \kbd{gal[4]}. \fun{GEN}{gal_get_den}{GEN gal} return \kbd{gal[5]}. \fun{GEN}{gal_get_group}{GEN gal} returns \kbd{gal.group}. \fun{GEN}{gal_get_gen}{GEN gal} returns \kbd{gal.gen}. \fun{GEN}{gal_get_orders}{GEN gal} returns \kbd{gal.orders}. \subsec{Miscellaneous functions} \fun{GEN}{nfgaloispermtobasis}{GEN nf, GEN gal} return the images of the field generator by the automorphisms \kbd{gal.orders} expressed on the integral basis \kbd{nf.zk}. \fun{GEN}{nfgaloismatrix}{GEN nf, GEN s} returns the \kbd{ZM} attached to the automorphism $s$, seen as a linear operator expressend on the number field integer basis. This allows to use \bprog M = nfgaloismatrix(nf, s); sx = ZM_ZC_mul(M, x); /* or RgM_RgC_mul(M, x) if x is not integral */ @eprog\noindent instead of \bprog sx = nfgaloisapply(nf, s, x); @eprog\noindent for an algebraic integer $x$. \fun{GEN}{nfgaloismatrixapply}{GEN nf, GEN M, GEN x} given an automorphism $M$ in \kbd{nfgaloismatrix} form, return the image of $x$ under the automorphism. Variant of \kbd{galoisapply}. \section{Quadratic number fields and quadratic forms} \subsec{Checks} \fun{void}{check_quaddisc}{GEN x, long *s, long *mod4, const char *f} checks whether the \kbd{GEN} $x$ is a quadratic discriminant (\typ{INT}, not a square, congruent to $0,1$ modulo $4$), and raise an exception otherwise. Set \kbd{*s} to the sign of $x$ and \kbd{*mod4} to $x$ modulo $4$ (0 or 1), unless \kbd{mod4} is \kbd{NULL}. \fun{void}{check_quaddisc_real}{GEN x, long *mod4, const char *f} as \tet{check_quaddisc}; check that \kbd{signe(x)} is positive. \fun{void}{check_quaddisc_imag}{GEN x, long *mod4, const char *f} as \tet{check_quaddisc}; check that \kbd{signe(x)} is negative. \subsec{Class number} Given a $D$ congruent to $0$ or $1$ modulo $4$, let $h(D)$ denote the class number of the order of discriminant $D$. The function \kbd{quadclassunit} uses index calculus and computes $h(D)$ in subexponential time in $\log |D|$ but it assumes the truth of the GRH. For imaginary quadratic orders, it is also comparatively slow for \emph{small} values, say $|D|\leq 10^{18}$. Here are some alternatives: \fun{GEN}{classno}{GEN D} corresponds to \kbd{qfbclassno(D,0)} and is only useful for $D < 0$, uses a baby-step giant-step technique and runs in time $O(D{1/4})$. The result is guaranteed correct for $|D| < 2\cdot 10^{10}$ and fastest in that range. For larger values of $|D|$, the algorithm is no longer rigorous and may give incorrect results (we know no concrete example); it also becomes relatively less interesting compared to \kbd{quadclassunit}. \fun{GEN}{classno2}{GEN D} corresponds to \kbd{qfbclassno(D,1)} and runs in time $O(D^{1/2})$; the function is provided for testing purposes only since it is never competitive. \fun{GEN}{quadclassnoF}{GEN D, GEN *pd} returns the positive integer $h(D)/h(d)$ where $d$ is the fundamental discriminant attached to $D$. If \kbd{pd} is not \kbd{NULL}, set \kbd{*pd} to $d$. \fun{GEN}{quadclassno}{GEN D} returns $h(D)$ using Buchmann's algorithm on the order of discriminant $D$. If $D$ is not fundamental, it will usually be faster to call \kbd{coredisc2\_fact} and \kbd{quadclassnoF\_fact} to reduce to this case first. \fun{long}{quadclassnos}{long D} returns $h(D)$ using Buchmann's algorithm on the order of discriminant $D$. \fun{ulong}{unegquadclassnoF}{ulong x, long *pd} returns $h(-x)/h(d)$. Set \kbd{*pd} to $d$. \fun{ulong}{uposquadclassnoF}{ulong x, long *pd} returns $h(x)/h(d)$. Set \kbd{*pd} to $d$. \fun{GEN}{quadclassnoF_fact}{GEN D, GEN P, GEN E} let $D$ be a fundamental discriminant, and $f = \prod_i P[i]^{E[i]}$ be a positive conductor for the order of discriminant $Df^2$ ($P$ is a \kbd{ZV} and $E$ is a \kbd{ZV} or \kbd{zv}). Returns the positive integer $$ h(Df^2) / h(D) = {f \over [O_D^\times : O_{Df^2}^\times]} \prod_{p | f} \big(1 - (D/p)p^{-1}\big).$$ \fun{ulong}{uquadclassnoF_fact}{ulong d, long s, GEN P, GEN E} let $s = 1$ or $-1$ be a sign, $D = sd$ be a fundamental discriminant, and $f = \prod_i P[i]^{E[i]}$ be a positive conductor for the order of discriminant $Df^2$ ($P$ and $E$ are \typ{VECSMALL}). Returns the integer $$ h(Df^2)/h(d) = {f \over [O_D^\times : O_{Df^2}^\times]} \prod_{p | f} \big(1 - (D/p)p^{-1}\big).$$ \fun{GEN}{hclassno}{GEN d} returns the Hurwitz-Kronecker class number $H(d)$. These play a central role in trace fomulas and are usually needed for many consecutive values of $d$. Thus, the function uses a cache so that later calls for \emph{small} consecutive values of $d$ are instantaneous, see \kbd{getcache}. Large values of $d$ ($d > 500000$) call \kbd{quadclassunit} individually and are not memoized. \fun{GEN}{hclassnoF_fact}{GEN P, GEN E, GEN D} return $H(Df^2)/H(D)$ assuming $D$ is a negative fundamental discriminant, where the conductor $f$ is given in factored form: $P$ (\kbd{ZV}) is the list of prime divisors of $f$ and $E$ (\typ{VECSMALL}) their multiplicities. \fun{long}{uhclassnoF_fact}{GEN faf, long D} return $H(Df^2)/H(D)$ assuming $D$ is a negative fundamental discriminant and $d = Df^2$ is an \kbd{ulong} and \kbd{faf} is \kbd{factoru}$(d)$. \fun{GEN}{hclassno6}{GEN d} assuming $d > 0$, returns the integer $6 H(d)$. This is a low-level function behind \kbd{hclassno}. \fun{ulong}{hclassno6u}{ulong d} assuming $d > 0$, returns the integer $6 H(d)$. Using this function creates (or extends) caches of Hurwitz class numbers and Corediscs of negative integers to speed up consecutive or repeated calls (see \kbd{getcache}). If this is a problem, use: \fun{ulong}{hclassno6u_no_cache}{ulong d} as \kbd{hclassno6u} without creating caches. Existing caches will be used. \subsec{\typ{QFB}} The functions in this section operate on binary quadratic forms of type \typ{QFB}. When specified, a \typ{QFB} argument $q$ attached to an indefinite form can be replaced by the pair $[q, d]$ where the \typ{REAL} $d$ is Shanks's distance. \fun{GEN}{qfb_1}{GEN q} given a \typ{QFB} $q$, return the unit form $q^0$. \fun{int}{qfb_equal1}{GEN q} returns 1 if the \typ{QFB} $q$ is the unit form. \subsubsec{Reduction} \fun{GEN}{qfbred}{GEN x} reduction of a \typ{QFB} $x$. Also allow extended indefinite forms. \fun{GEN}{qfbred_i}{GEN x} internal version of \kbd{qfbred}: assume $x$ is a \typ{QFB}. \subsubsec{Composition} \fun{GEN}{qfbcomp}{GEN x, GEN y} compose the two \typ{QFB} $x$ and $y$ (with same discriminant), then reduce the result. This is the same as \kbd{gmul(x,y)}. Also allow extended indefinite forms. \fun{GEN}{qfbcomp_i}{GEN x, GEN y} internal version of \kbd{qfbcomp}: assume $x$ and $y$ are \typ{QFB} of the same discriminant. \fun{GEN}{qfbsqr}{GEN x} as \kbd{qfbcomp(x,x)}. \fun{GEN}{qfbsqr_i}{GEN x} as \kbd{qfbcomp\_i(x,y)}. \noindent Same as above, \emph{without} reducing the result: \fun{GEN}{qfbcompraw}{GEN x, GEN y} compose two \typ{QFB}s, without reducing the result. Also allow extended indefinite forms. \fun{GEN}{qfbcompraw_i}{GEN x, GEN y} internal version of \kbd{qfbcompraw}: assume $x$ and $y$ are \typ{QFB} of the same discriminant. \subsubsec{Powering} \fun{GEN}{qfbpow}{GEN x, GEN n} computes $x^n$ and reduce the result. Also allow extended indefinite forms. \fun{GEN}{qfbpows}{GEN x, long n} computes $x^n$ and reduce the result. Also allow extended indefinite forms. \fun{GEN}{qfbpow_i}{GEN x, GEN n} internal version of \kbd{qfbcomp}. Assume $x$ is a \kbd{QFB}. \fun{GEN}{qfbpowraw}{GEN x, long n} compute $x^n$ (pure composition, no reduction), for a \typ{QFB} $x$. Also allow indefinite forms. \subsubsec{Order, discrete log} \fun{GEN}{qfi_order}{GEN q, GEN o} assuming that the imaginary \typ{QFB} $q$ has order dividing $o$, compute its order in the class group. The order can be given in all formats allowed by generic discrete log functions, the preferred format being \kbd{[ord, fa]} (\typ{INT} and its factorization). \fun{GEN}{qfi_log}{GEN a, GEN g, GEN o} given an imaginary \typ{QFB} $a$ and assuming that the \typ{QFB} $g$ has order $o$, compute an integer $k$ such that $a^k = g$. Return \kbd{cgetg(1, t\_VEC)} if there are no solutions. Uses a generic Pollig-Hellman algorithm, then either Shanks (small $o$) or Pollard rho (large $o$) method. The order can be given in all formats allowed by generic discrete log functions, the preferred format being \kbd{[ord, fa]} (\typ{INT} and its factorization). \fun{GEN}{qfi_Shanks}{GEN a, GEN g, long n} given an imaginary \typ{QFB} $a$ and assuming that the \typ{QFB} $g$ has (small) order $n$, compute an integer $k$ such that $a^k = g$. Return \kbd{cgetg(1, t\_VEC)} if there are no solutions. Directly uses Shanks algorithm, which is inefficient when $n$ is composite. \subsubsec{Solve, Cornacchia} The following functions underly \tet{qfbsolve}; $p$ denotes a prime number. \fun{GEN}{qfisolvep}{GEN Q, GEN p} solves $Q(x,y) = p$ over the integers, for an imaginary \typ{QFB} $Q$. Return \kbd{gen\_0} if there are no solutions. \fun{GEN}{qfrsolvep}{GEN Q, GEN p} solves $Q(x,y) = p$ over the integers, for a real \typ{QFB} $Q$. Return \kbd{gen\_0} if there are no solutions. \fun{long}{cornacchia}{GEN d, GEN p, GEN *px, GEN *py} solves $x^2+ dy^2 = p$ over the integers, where $d > 0$ is congruent to $0$ or $3$ modulo $4$. Return $1$ if there is a solution (and store it in \kbd{*x} and \kbd{*y}), $0$ otherwise. \fun{long}{cornacchia2}{GEN d, GEN p, GEN *px, GEN *py} as \kbd{cornacchia}, for the equation $x^2 + dy^2 = 4p$. \fun{long}{cornacchia2_sqrt}{GEN d, GEN p, GEN b, GEN *px, GEN *py} as \kbd{cornacchia2}, where $p > 2$ and $b$ is the smallest squareroot of $d$ modulo $p$. \subsubsec{Prime forms} \fun{GEN}{primeform_u}{GEN D, ulong p} \typ{QFB} of discriminant $D$ whose first coefficient is the prime $p$, assuming $(D/p) \geq 0$. \fun{GEN}{primeform}{GEN D, GEN p} \subsec{Efficient real quadratic forms} Unfortunately, real \typ{QFB}s are very inefficient, and are only provided for backward compatibility. \item they do not contain needed quantities, which are thus constantly recomputed (the discriminant square root $\sqrt{D}$ and its integer part), \item the distance component is stored in logarithmic form, which involves computing one extra logarithm per operation. It is much more efficient to store its exponential, computed from ordinary multiplications and divisions (taking exponent overflow into account), and compute its logarithm at the very end. Internally, we have two representations for real quadratic forms: \item \tet{qfr3}, a container $[a,b,c]$ with at least 3 entries: the three coefficients; the idea is to ignore the distance component. \item \tet{qfr5}, a container with at least 5 entries $[a,b,c,e,d]$: the three coefficients a \typ{REAL} $d$ and a \typ{INT} $e$ coding the distance component $2^{Ne} d$, in exponential form, for some large fixed $N$. It is a feature that \kbd{qfr3} and \kbd{qfr5} have no specified length or type. It implies that a \kbd{qfr5} or \typ{QFB} will do whenever a \kbd{qfr3} is expected. Routines using these objects require a global context, provided by a \kbd{struct qfr\_data *}: \bprog struct qfr_data { GEN D; /* discriminant, t_INT */ GEN sqrtD; /* sqrt(D), t_REAL */ GEN isqrtD; /* floor(sqrt(D)), t_INT */ }; @eprog \fun{void}{qfr_data_init}{GEN D, long prec, struct qfr_data *S} given a discriminant $D > 0$, initialize $S$ for computations at precision \kbd{prec} ($\sqrt{D}$ is computed to that initial accuracy). \noindent All functions below are shallow, and not stack clean. \fun{GEN}{qfr3_comp}{GEN x, GEN y, struct qfr_data *S} compose two \kbd{qfr3}, reducing the result. \fun{GEN}{qfr3_compraw}{GEN x, GEN y} as \kbd{qfr3\_comp}, without reducing the result. \fun{GEN}{qfr3_pow}{GEN x, GEN n, struct qfr_data *S} compute $x^n$, reducing along the way. \fun{GEN}{qfr3_red}{GEN x, struct qfr_data *S} reduce $x$. \fun{GEN}{qfr3_rho}{GEN x, struct qfr_data *S} perform one reduction step; \kbd{qfr3\_red} just performs reduction steps until we hit a reduced form. \fun{GEN}{qfr3_to_qfr}{GEN x, GEN d} recover an ordinary \typ{QFB} from the \kbd{qfr3} $x$, adding disriminant component $d$. Before we explain \kbd{qfr5}, recall that it corresponds to an ideal, that reduction corresponds to multiplying by a principal ideal, and that the distance component is a clever way to keep track of these principal ideals. More precisely, reduction consists in a number of reduction steps, going from the form $(a,b,c)$ to $\rho(a,b,c) = (c, -b \mod 2c, *)$; the distance component is multiplied by (a floating point approximation to) $(b + \sqrt{D}) / (b - \sqrt{D})$. \fun{GEN}{qfr5_comp}{GEN x, GEN y, struct qfr_data *S} compose two \kbd{qfr5}, reducing the result, and updating the distance component. \fun{GEN}{qfr5_compraw}{GEN x, GEN y} as \kbd{qfr5\_comp}, without reducing the result. \fun{GEN}{qfr5_pow}{GEN x, GEN n, struct qfr_data *S} compute $x^n$, reducing along the way. \fun{GEN}{qfr5_red}{GEN x, struct qfr_data *S} reduce $x$. \fun{GEN}{qfr5_rho}{GEN x, struct qfr_data *S} perform one reduction step. \fun{GEN}{qfr5_dist}{GEN e, GEN d, long prec} decode the distance component from exponential (\kbd{qfr5}-specific) to logarithmic form (true Shanks's distance). \fun{GEN}{qfr_to_qfr5}{GEN x, long prec} convert a real \typ{QFB} to a \kbd{qfr5} with initial trivial distance component ($= 1$). \fun{GEN}{qfr5_to_qfr}{GEN x, GEN d}, assume $x$ is a \kbd{qfr5} and $d$ is \kbd{NULL} or the original distance component of some real \typ{QFB}. Convert $x$ to a \typ{QFB}, with the correct (logarithmic) distance component if $d$ is not \kbd{NULL}. \section{Linear algebra over $\Z$} \subsec{Hermite and Smith Normal Forms} \fun{GEN}{ZM_hnf}{GEN x} returns the upper triangular Hermite Normal Form of the \kbd{ZM} $x$ (removing $0$ columns), using the \tet{ZM_hnfall} algorithm. If you want the true HNF, use \kbd{ZM\_hnfall(x, NULL, 0)}. \fun{GEN}{ZM_hnfmod}{GEN x, GEN d} returns the HNF of the \kbd{ZM} $x$ (removing $0$ columns), assuming the \typ{INT} $d$ is a multiple of the determinant of $x$. This is usually faster than \tet{ZM_hnf} (and uses less memory) if the dimension is large, $> 50$ say. \fun{GEN}{ZM_hnfmodid}{GEN x, GEN d} returns the HNF of the \kbd{ZM} $x$ concatenated with the diagonal matrix with diagonal $d$, where $d$ is a vector of integers of compatible dimension. Variant: if $d$ is a \typ{INT}, then concatenate $d \text{Id}$. \fun{GEN}{ZM_hnfmodprime}{GEN x, GEN p} returns the HNF of the matrix $(x \mid p \text{Id})$ (removing $0$ columns), for a \kbd{ZM} $x$ and a prime number $p$. The algorithm involves only $\F_p$-linear algebra and is is faster than \tet{ZM_hnfmodid} (which will call it when $d$ is prime). \fun{GEN}{ZM_hnfmodall}{GEN x, GEN d, long flag} low-level function underlying the \kbd{ZM\_hnfmod} variants. If \kbd{flag} is $0$, calls \kbd{ZM\_hnfmod(x,d)}; \kbd{flag} is an or-ed combination of: \item \tet{hnf_MODID} call \kbd{ZM\_hnfmodid} instead of \kbd{ZM\_hnfmod}, \item \tet{hnf_PART} return as soon as we obtain an upper triangular matrix, saving time. The pivots are nonnegative and give the diagonal of the true HNF, but the entries to the right of the pivots need not be reduced, i.e.~they may be large or negative. \item \tet{hnf_CENTER} returns the centered HNF, where the entries to the right of a pivot $p$ are centered residues in $[-p/2, p/2[$, hence smallest possible in absolute value, but possibly negative. \fun{GEN}{ZM_hnfmodall_i}{GEN x, GEN d, long flag} as \tet{ZM_hnfmodall} without final garbage collection. Not \kbd{gerepile}-safe. \fun{GEN}{ZM_hnfall}{GEN x, GEN *U, long remove} returns the upper triangular HNF $H$ of the \kbd{ZM} $x$; if $U$ is not \kbd{NULL}, set if to the matrix $U$ such that $x U = H$. If $\kbd{remove} = 0$, $H$ is the true HNF, including $0$ columns; if $\kbd{remove} = 1$, delete the $0$ columns from $H$ but do not update $U$ accordingly (so that the integer kernel may still be recovered): we no longer have $x U = H$; if $\kbd{remove} = 2$, remove $0$ columns from $H$ and update $U$ so that $x U = H$. The matrix $U$ is square and invertible unless $\kbd{remove} = 2$. This routine uses a naive algorithm which is potentially exponential in the dimension (due to coefficient explosion) but is fast in practice, although it may require lots of memory. The base change matrix $U$ may be very large, when the kernel is large. \fun{GEN}{ZM_hnfall_i}{GEN x, GEN *U, long remove} as \tet{ZM_hnfall} without final garbage collection. Not \kbd{gerepile}-safe. \fun{GEN}{ZM_hnfperm}{GEN A, GEN *ptU, GEN *ptperm} returns the hnf $H = P A U$ of the matrix $P A$, where $P$ is a suitable permutation matrix, and $U\in \text{Gl}_n(\Z)$. $P$ is chosen so as to (heuristically) minimize the size of $U$; in this respect it is less efficient than \kbd{ZM\_hnflll} but usually faster. Set \kbd{*ptU} to $U$ and \kbd{*pterm} to a \typ{VECSMALL} representing the row permutation attached to $P = (\delta_{i,\kbd{perm}[i]}$. If \kbd{ptU} is set to \kbd{NULL}, $U$ is not computed, saving some time; although useless, setting \kbd{ptperm} to \kbd{NULL} is also allowed. \fun{GEN}{ZM_hnf_knapsack}{GEN x} given a \kbd{ZM} $x$, compute its HNF $h$. Return $h$ if it has the knapsack property: every column contains only zeroes and ones and each row contains a single $1$; return \kbd{NULL} otherwise. Not suitable for gerepile. \fun{GEN}{ZM_hnflll}{GEN x, GEN *U, int remove} returns the HNF $H$ of the \kbd{ZM} $x$; if $U$ is not \kbd{NULL}, set if to the matrix $U$ such that $x U = H$. The meaning of \kbd{remove} is the same as in \tet{ZM_hnfall}. This routine uses the \idx{LLL} variant of Havas, Majewski and Mathews, which is polynomial time, but rather slow in practice because it uses an exact LLL over the integers instead of a floating point variant; it uses polynomial space but lots of memory is needed for large dimensions, say larger than 300. On the other hand, the base change matrix $U$ is essentially optimally small with respect to the $L_2$ norm. \fun{GEN}{ZM_hnfcenter}{GEN M}. Given a \kbd{ZM} in HNF $M$, update it in place so that nondiagonal entries belong to a system of \emph{centered} residues. Not suitable for gerepile. Some direct applications: the following routines apply to upper triangular integral matrices; in practice, these come from HNF algorithms. \fun{GEN}{hnf_divscale}{GEN A, GEN B,GEN t} $A$ an upper triangular \kbd{ZM}, $B$ a \kbd{ZM}, $t$ an integer, such that $C := tA^{-1}B$ is integral. Return $C$. \fun{GEN}{hnf_invscale}{GEN A, GEN t} $A$ an upper triangular \kbd{ZM}, $t$ an integer such that $C := tA^{-1}$ is integral. Return $C$. Special case of \tet{hnf_divscale} when $B$ is the identity matrix. \fun{GEN}{hnf_solve}{GEN A, GEN B} $A$ a \kbd{ZM} in upper HNF (not necessarily square), $B$ a \kbd{ZM} or \kbd{ZC}. Return $A^{-1}B$ if it is integral, and \kbd{NULL} if it is not. \fun{GEN}{hnf_invimage}{GEN A, GEN b} $A$ a \kbd{ZM} in upper HNF (not necessarily square), $b$ a \kbd{ZC}. Return $A^{-1}B$ if it is integral, and \kbd{NULL} if it is not. \fun{int}{hnfdivide}{GEN A, GEN B} $A$ and $B$ are two upper triangular \kbd{ZM}. Return $1$ if $A^{-1} B$ is integral, and $0$ otherwise. \misctitle{Smith Normal Form} \fun{GEN}{ZM_snf}{GEN x} returns the Smith Normal Form (vector of elementary divisors) of the \kbd{ZM} $x$. \fun{GEN}{ZM_snfall}{GEN x, GEN *U, GEN *V} returns \kbd{ZM\_snf(x)} and sets $U$ and $V$ to unimodular matrices such that $U\, x\, V = D$ (diagonal matrix of elementary divisors). Either (or both) $U$ or $V$ may be \kbd{NULL} in which case the corresponding matrix is not computed. \fun{GEN}{ZV_snfall}{GEN d, GEN *U, GEN *V} here $d$ is a \kbd{ZV}; same as \tet{ZM_snfall} applied to \kbd{diagonal(d)}, but faster. \fun{GEN}{ZM_snfall_i}{GEN x, GEN *U, GEN *V, long flag} low level version of \kbd{ZM\_snfall}: \item if the first bit of \fl\ is $0$, return a diagonal matrix (as in \kbd{ZM\_snfall}), else a vector of elementary divisors (as in \kbd{ZM\_snf}). \item if the second bit of \fl\ is $1$, assume that $x$ is invertible and allow $U$ and $V$ to have determinant congruent to $1$ modulo $d$, where $d$ is the largest elementary divisor of $x$. Rationale: the finite group $G = \Z^n/\Im x$ has exponent $d$ and we are only interested in the action of $U$, $V$ as they act on $G$ not in genuine unimodular matries. (See \kbd{ZM\_snf\_group}.) \fun{void}{ZM_snfclean}{GEN d, GEN U, GEN V} assuming $d$, $U$, $V$ come from \kbd{d = ZM\_snfall(x, \&U, \&V)}, where $U$ or $V$ may be \kbd{NULL}, cleans up the output in place. This means that elementary divisors equal to 1 are deleted and $U$, $V$ are updated. This also works when $d$ is a \typ{VEC} of elementary divisors. The output is not suitable for \kbd{gerepileupto}. \fun{void}{ZV_snfclean}{GEN d} assuming $d$ is a \typ{VEC} of elementary divisors, return a shortened version where divisors equal to $1$ are deleted. The output is not suitable for \kbd{gerepileupto}; we return $d$ itself if no divisor is $1$. \fun{void}{ZV_snf_trunc}{GEN D} given a vector $D$ of elementary divisors (i.e. a \kbd{ZV} such that $d_i \mid d_{i+1}$), truncate it \emph{in place} to leave out the trivial divisors (equal to $1$). \fun{GEN}{ZM_snf_group}{GEN H, GEN *U, GEN *Uinv} this function computes data to go back and forth between an abelian group (of finite type) given by generators and relations, and its canonical SNF form. Given an abstract abelian group with generators $g = (g_1,\dots,g_n)$ and a vector $X=(x_i)\in\Z^n$, we write $g X$ for the group element $\sum_i x_i g_i$; analogously if $M$ is an $n\times r$ integer matrix $g M$ is a vector containing $r$ group elements. The group neutral element is $0$; by abuse of notation, we still write $0$ for a vector of group elements all equal to the neutral element. The input is a full relation matrix $H$ among the generators, i.e. a \kbd{ZM} (not necessarily square) such that $gX = 0$ for some $X\in\Z^n$ if and only if $X$ is in the integer image of $H$, so that the abelian group is isomorphic to $\Z^n/\text{Im} H$. \emph{The routine assumes that $H$ is in HNF;} replace it by its HNF if it is not the case. (Of course this defines the same group.) Let $G$ a minimal system of generators in SNF for our abstract group: if the $d_i$ are the elementary divisors ($\dots \mid d_2\mid d_1$), each $G_i$ has either infinite order ($d_i = 0$) or order $d_i > 1$. Let $D$ the matrix with diagonal $(d_i)$, then $$G D = 0,\quad G = g U_{\text{inv}},\quad g = G U,$$ for some integer matrices $U$ and $U_{\text{inv}}$. Note that these are not even square in general; even if square, there is no guarantee that these are unimodular: they are chosen to have minimal entries given the known relations in the group and only satisfy $D \mid (U U_{\text{inv}} - \text{Id})$ and $H \mid (U_{\text{inv}}U - \text{Id})$. The function returns the vector of elementary divisors $(d_i)$; if \kbd{U} is not \kbd{NULL}, it is set to $U$; if \kbd{Uinv} is not \kbd{NULL} it is set to $U_{\text{inv}}$. The function is not memory clean. \fun{GEN}{ZV_snf_group}{GEN d, GEN *newU, GEN *newUi}, here $d$ is a \kbd{ZV}; same as \tet{ZM_snf_group} applied to \kbd{diagonal(d)}, but faster. \fun{GEN}{ZV_snf_gcd}{GEN v, GEN N} given a vector $v$ of integers and a positive integer $N$, return the vector whose entries are the gcds $(v[i],N)$. Use case: if $v$ gives the cyclic components for some abelian group $G$ of finite type, then this returns the structure of the finite groupe $G/G^N$. The following functions compute the $p^n$-rank of abelian groups given a vector of elementary divisors and underly \kbd{snfrank}: \fun{long}{ZV_snf_rank}{GEN D, GEN p} assume $D$ is a \kbd{ZV} and $p$ is a \typ{INT}. \fun{long}{ZV_snf_rank_u}{GEN D, ulong p} assume $D$ is a \kbd{ZV}. \fun{long}{zv_snf_rank}{GEN D, ulong p} assume $D$ is a \kbd{zv}. The following routines underly the various \tet{matrixqz} variants. In all case the $m\times n$ \typ{MAT} $x$ is assumed to have rational (\typ{INT} and \typ{FRAC}) coefficients \fun{GEN}{QM_ImQ}{GEN x} returns a basis for $\text{Im}_\Q x \cap \Z^n$. \fun{GEN}{QM_ImZ}{GEN x} returns a basis for $\text{Im}_\Z x \cap \Z^n$. \fun{GEN}{QM_ImQ_hnf}{GEN x} returns an HNF basis for $\text{Im}_\Q x \cap \Z^n$. \fun{GEN}{QM_ImZ_hnf}{GEN x} returns an HNF basis for $\text{Im}_\Z x \cap \Z^n$. \fun{GEN}{QM_ImQ_hnfall}{GEN A, GEN *pB, long remove} as \tet{QM_ImQ_hnf}, further returning the transformation matrix as in \tet{ZM_hnfall}. \fun{GEN}{QM_ImZ_hnfall}{GEN A, GEN *pB, long remove} as \tet{QM_ImZ_hnf}, further returning the transformation matrix as in \tet{ZM_hnfall}. \fun{GEN}{QM_ImQ_all}{GEN A, GEN *pB, long remove, long hnf} as \tet{QM_ImQ}, further returning the transformation matrix as in \tet{ZM_hnfall}, and returning an HNF basis if \kbd{hnf} is nonzero. \fun{GEN}{QM_ImZ_all}{GEN A, GEN *pB, long remove, long hnf} as \tet{QM_ImZ}, further returning the transformation matrix as in \tet{ZM_hnfall}, and returning an HNF basis if \kbd{hnf} is nonzero. \fun{GEN}{QM_minors_coprime}{GEN x, GEN D}, assumes $m\geq n$, and returns a matrix in $M_{m,n}(\Z)$ with the same $\Q$-image as $x$, such that the GCD of all $n\times n$ minors is coprime to $D$; if $D$ is \kbd{NULL}, we want the GCD to be $1$. \smallskip The following routines are simple wrappers around the above ones and are normally useless in library mode: \fun{GEN}{hnf}{GEN x} checks whether $x$ is a \kbd{ZM}, then calls \tet{ZM_hnf}. Normally useless in library mode. \fun{GEN}{hnfmod}{GEN x, GEN d} checks whether $x$ is a \kbd{ZM}, then calls \tet{ZM_hnfmod}. Normally useless in library mode. \fun{GEN}{hnfmodid}{GEN x,GEN d} checks whether $x$ is a \kbd{ZM}, then calls \tet{ZM_hnfmodid}. Normally useless in library mode. \fun{GEN}{hnfall}{GEN x} calls \kbd{ZM\_hnfall(x, \&U, 1)} and returns $[H, U]$. Normally useless in library mode. \fun{GEN}{hnflll}{GEN x} calls \kbd{ZM\_hnflll(x, \&U, 1)} and returns $[H, U]$. Normally useless in library mode. \fun{GEN}{hnfperm}{GEN x} calls \kbd{ZM\_hnfperm(x, \&U, \&P)} and returns $[H, U, P]$. Normally useless in library mode. \fun{GEN}{smith}{GEN x} checks whether $x$ is a \kbd{ZM}, then calls \kbd{ZM\_snf}. Normally useless in library mode. \fun{GEN}{smithall}{GEN x} checks whether $x$ is a \kbd{ZM}, then calls \kbd{ZM\_snfall(x, \&U, \&V)} and returns $[U,V,D]$. Normally useless in library mode. \noindent Some related functions over $K[X]$, $K$ a field: \fun{GEN}{gsmith}{GEN A} the input matrix must be square, returns the elementary divisors. \fun{GEN}{gsmithall}{GEN A} the input matrix must be square, returns the $[U,V,D]$, $D$ diagonal, such that $UAV = D$. \fun{GEN}{RgM_hnfall}{GEN A, GEN *pB, long remove} analogous to \tet{ZM_hnfall}. \fun{GEN}{smithclean}{GEN z} cleanup the output of \kbd{smithall} or \kbd{gsmithall} (delete elementary divisors equal to $1$, updating base change matrices). \subsec{The LLL algorithm}\sidx{LLL} The basic GP functions and their immediate variants are normally not very useful in library mode. We briefly list them here for completeness, see the documentation of \kbd{qflll} and \kbd{qflllgram} for details: \item \fun{GEN}{qflll0}{GEN x, long flag} \fun{GEN}{lll}{GEN x} \fl = 0 \fun{GEN}{lllint}{GEN x} \fl = 1 \fun{GEN}{lllkerim}{GEN x} \fl = 4 \fun{GEN}{lllkerimgen}{GEN x} \fl = 5 \fun{GEN}{lllgen}{GEN x} \fl = 8 \item \fun{GEN}{qflllgram0}{GEN x, long flag} \fun{GEN}{lllgram}{GEN x} \fl = 0 \fun{GEN}{lllgramint}{GEN x} \fl = 1 \fun{GEN}{lllgramkerim}{GEN x} \fl = 4 \fun{GEN}{lllgramkerimgen}{GEN x} \fl = 5 \fun{GEN}{lllgramgen}{GEN x} \fl = 8 \smallskip The basic workhorse underlying all integral and floating point LLLs is \fun{GEN}{ZM_lll}{GEN x, double D, long flag}, where $x$ is a \kbd{ZM}; $D \in ]1/4,1[$ is the Lov\'{a}sz constant determining the frequency of swaps during the algorithm: a larger values means better guarantees for the basis (in principle smaller basis vectors) but longer running times (suggested value: $D = 0.99$). \misctitle{Important} This function does not collect garbage and its output is not suitable for either \kbd{gerepile} or \kbd{gerepileupto}. We expect the caller to do something simple with the output (e.g. matrix multiplication), then collect garbage immediately. \noindent\kbd{flag} is an or-ed combination of the following flags: \item \tet{LLL_GRAM}. If set, the input matrix $x$ is the Gram matrix ${}^t v v$ of some lattice vectors $v$. \item \tet{LLL_INPLACE}. Incompatible with \kbd{LLL\_GRAM}. If unset, we return the base change matrix $U$, otherwise the transformed matrix $x U$. Implies \tet{LLL_IM} (see below). \item \tet{LLL_KEEP_FIRST}. The first vector in the output basis is the same one as was originally input. Provided this is a shortest nonzero vector of the lattice, the output basis is still LLL-reduced. This is used to reduce maximal orders of number fields with respect to the $T_2$ quadratic form, to ensure that the first vector in the output basis corresponds to $1$ (which is a shortest vector). \item \tet{LLL_COMPATIBLE}. DEPRECATED. This is now a no-op. The last three flags are mutually exclusive, either 0 or a single one must be set: \item \tet{LLL_KER} If set, only return a kernel basis $K$ (not LLL-reduced). \item \tet{LLL_IM} If set, only return an LLL-reduced lattice basis $T$. (This is implied by \tet{LLL_INPLACE}). \item \tet{LLL_ALL} If set, returns a 2-component vector $[K, T]$ corresponding to both kernel and image. \fun{GEN}{lllfp}{GEN x, double D, long flag} is a variant for matrices with inexact entries: $x$ is a matrix with real coefficients (types \typ{INT}, \typ{FRAC} and \typ{REAL}), $D$ and $\fl$ are as in \tet{ZM_lll}. The matrix is rescaled, rounded to nearest integers, then fed to \kbd{ZM\_lll}. The flag \kbd{LLL\_INPLACE} is still accepted but less useful (it returns an LLL-reduced basis attached to rounded input, instead of an exact base change matrix). \fun{GEN}{ZM_lll_norms}{GEN x, double D, long flag, GEN *ptB} slightly more general version of \kbd{ZM\_lll}, setting \kbd{*ptB} to a vector containing the squared norms of the Gram-Schmidt vectors $(b_i^*)$ attached to the output basis $(b_i)$, $b_i^* = b_i + \sum_{j < i} \mu_{i,j} b_j^*$. \fun{GEN}{lllintpartial_inplace}{GEN x} given a \kbd{ZM} $x$ of maximal rank, returns a partially reduced basis $(b_i)$ for the space spanned by the columns of $x$: $|b_i \pm b_j| \geq |b_i|$ for any two distinct basis vectors $b_i$, $b_j$. This is faster than the LLL algorithm, but produces much larger bases. \fun{GEN}{lllintpartial}{GEN x} as \kbd{lllintpartial\_inplace}, but returns the base change matrix $U$ from the canonical basis to the $b_i$, i.e. $x U$ is the output of \kbd{lllintpartial\_inplace}. \fun{GEN}{RM_round_maxrank}{GEN G} given a matrix $G$ with real floating point entries and independent columns, let $G_e$ be the rescaled matrix $2^e G$ rounded to nearest integers, for $e \geq 0$. Finds a small $e$ such that the rank of $G_e$ is equal to the rank of $G$ (its number of columns) and return $G_e$. This is useful as a preconditioning step to speed up LLL reductions, see \tet{nf_get_Gtwist}. Suitable for \kbd{gerepileupto}, but does not collect garbage. \fun{GEN}{Hermite_bound}{long n, long prec} return a majoration of $\gamma_n^n$ where $\gamma_n$ is the Hermite constant for lattices of dimension $n$. The bound is sharp in dimension $n \leq 8$ and $n = 24$. \subsec{Linear dependencies} The following functions underly the \kbd{lindep} GP function: \fun{GEN}{lindep}{GEN v} real/complex entries, guess that about only the 80\% leading bits of the input are correct. \fun{GEN}{lindep_bit}{GEN v, long b} real/complex entries, explicit form of the above: multiply the input by $2^b$ and round to nearest integer before looking for a linear dependency. Truncating dubious bits allows to find better relations. \fun{GEN}{lindepfull_bit}{GEN v, long b} as \kbd{lindep\_bit} but return a matrix $M$ with $n = \#v$ columns and $r$ rows, with $r = n+1$ (if $v$ is real) or $n+2$ (general case) which is an LLL-reduced basis of the lattice formed by concatenating vertically an identity matrix and the floor of $2^b \kbd{real}(v)$ and $2^b \kbd{imag}(v)$ if $r = n+2$. The first $n$ rows of $M$ potentially correspond to relations: whenever the last $r-n$ entries of a column are small. The function \kbd{lindep\_bit} essentially returns the first column of $M$ truncated to $n$ components. \fun{GEN}{lindep_padic}{GEN v} $p$-adic entries. \fun{GEN}{lindep_Xadic}{GEN v} polynomial entries. \fun{GEN}{deplin}{GEN v} returns a nonzero kernel vector for a \typ{MAT} input. Deprecated routine: \fun{GEN}{lindep2}{GEN x, long dig} analogous to \kbd{lindep\_bit}, with \kbd{dig} counting decimal digits. \subsec{Reduction modulo matrices} \fun{GEN}{ZC_hnfremdiv}{GEN x, GEN y, GEN *Q} assuming $y$ is an invertible \kbd{ZM} in HNF and $x$ is a \kbd{ZC}, returns the \kbd{ZC} $R$ equal to $x$ mod $y$ (whose $i$-th entry belongs to $[-y_{i,i}/2, y_{i,i}/2[$). Stack clean \emph{unless} $x$ is already reduced (in which case, returns $x$ itself, not a copy). If $Q$ is not \kbd{NULL}, set it to the \kbd{ZC} such that $x = yQ + R$. \fun{GEN}{ZM_hnfdivrem}{GEN x, GEN y, GEN *Q} reduce each column of the \kbd{ZM} $x$ using \kbd{ZC\_hnfremdiv}. If $Q$ is not \kbd{NULL}, set it to the \kbd{ZM} such that $x = yQ + R$. \fun{GEN}{ZC_hnfrem}{GEN x, GEN y} alias for \kbd{ZC\_hnfremdiv(x,y,NULL)}. \fun{GEN}{ZM_hnfrem}{GEN x, GEN y} alias for \kbd{ZM\_hnfremdiv(x,y,NULL)}. \fun{GEN}{ZC_reducemodmatrix}{GEN v, GEN y} Let $y$ be a ZM, not necessarily square, which is assumed to be LLL-reduced (otherwise, very poor reduction is expected). Size-reduces the ZC $v$ modulo the $\Z$-module $Y$ spanned by $y$ : if the columns of $y$ are denoted by $(y_1,\dots, y_{n-1})$, we return $y_n \equiv v$ modulo $Y$, such that the Gram-Schmidt coefficients $\mu_{n,j}$ are less than $1/2$ in absolute value for all $j < n$. In short, $y_n$ is almost orthogonal to $Y$. \fun{GEN}{ZM_reducemodmatrix}{GEN v, GEN y} Let $y$ be as in \tet{ZC_reducemodmatrix}, and $v$ be a ZM. This returns a matrix $v$ which is congruent to $v$ modulo the $\Z$-module spanned by $y$, whose columns are size-reduced. This is faster than repeatedly calling \tet{ZC_reducemodmatrix} on the columns since most of the Gram-Schmidt coefficients can be reused. \fun{GEN}{ZC_reducemodlll}{GEN v, GEN y} Let $y$ be an arbitrary ZM, LLL-reduce it then call \tet{ZC_reducemodmatrix}. \fun{GEN}{ZM_reducemodlll}{GEN v, GEN y} Let $y$ be an arbitrary ZM, LLL-reduce it then call \tet{ZM_reducemodmatrix}. Besides the above functions, which were specific to integral input, we also have: \fun{GEN}{reducemodinvertible}{GEN x, GEN y} $y$ is an invertible matrix and $x$ a \typ{COL} or \typ{MAT} of compatible dimension. Returns $x - y\lfloor y^{-1}x \rceil$, which has small entries and differs from $x$ by an integral linear combination of the columns of $y$. Suitable for \kbd{gerepileupto}, but does not collect garbage. \fun{GEN}{closemodinvertible}{GEN x, GEN y} returns $x - \kbd{reducemodinvertible}(x,y)$, i.e. an integral linear combination of the columns of $y$, which is close to $x$. \fun{GEN}{reducemodlll}{GEN x,GEN y} LLL-reduce the nonsingular \kbd{ZM} $y$ and call \kbd{reducemodinvertible} to find a small representative of $x$ mod $y \Z^n$. Suitable for \kbd{gerepileupto}, but does not collect garbage. \section{Finite abelian groups and characters} \subsec{Abstract groups} A finite abelian group $G$ in GP 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$. Let $e(x) := \exp(2i\pi x)$. For ease of exposition, we restrict to complex-valued characters, but everything applies to more general fields $K$ where $e$ denotes a morphism $(\Q,+) \to (K^*,\times)$ such that $e(a/b)$ denotes a $b$-th root of unity. A \tev{character} on the abelian group $\oplus (\Z/d_j\Z) g_j$ is given by a row vector $\chi = [a_1,\ldots,a_n]$ such that $\chi(\prod g_j^{n_j}) = e(\sum a_j n_j / d_j)$. \fun{GEN}{cyc_normalize}{GEN d} shallow function. Given a vector $(d_i)_{i \leq n}$ of elementary divisors for a finite group (no $d_i$ vanish), returns the vector $D = [1]$ if $n = 0$ (trivial group) and $[d_1, d_1/d_2, \dots, d_1/d_n]$ otherwise. This will allow to define characters as $\chi(\prod g_j^{x_j}) = e(\sum_j x_j a_j D_j / D_1)$, see \tet{char_normalize}. \fun{GEN}{char_normalize}{GEN chi, GEN ncyc} shallow function. Given a character \kbd{chi} $ = (a_j)$ and \var{ncyc} from \kbd{cyc\_normalize} above, returns the normalized representation $[d, (n_j)]$, such that $\chi(\prod g_j^{x_j}) = \zeta_d^{\sum_j n_j x_j}$, where $\zeta_d = e(1/d)$ and $d$ is \emph{minimal}. In particular, $d$ is the order of \kbd{chi}. Shallow function. \fun{GEN}{char_simplify}{GEN D, GEN N} given a quasi-normalized character $[D, (N_j)]$ such that $\chi(\prod g_j^{x_j}) = \zeta_D^{\sum_j N_j x_j}$, but where we only assume that $D$ is a multiple of the character order, return a normalized character $[d, (n_j)]$ with $d$ \emph{minimal}. Shallow function. \fun{GEN}{char_denormalize}{GEN cyc, GEN d, GEN n} given a normalized representation $[d, n]$ (where $d$ need not be minimal) of a character on the abelian group with abelian divisors \kbd{cyc}, return the attached character (where the image of each generator $g_i$ is given in terms of roots of unity of different orders $\kbd{cyc}[i]$). \fun{GEN}{charconj}{GEN cyc, GEN chi} return the complex conjugate of \kbd{chi}. \fun{GEN}{charmul}{GEN cyc, GEN a, GEN b} return the product character $a\times b$. \fun{GEN}{chardiv}{GEN cyc, GEN a, GEN b} returns the character $a / b = a \times \overline{b}$. \fun{int}{char_check}{GEN cyc, GEN chi} return $1$ if \kbd{chi} is a character compatible with cyclic factors \kbd{cyc}, and $0$ otherwise. \fun{GEN}{cyc2elts}{GEN d} given a \typ{VEC} $d = (d_1,\dots,d_n)$ of nonnegative integers, return the vector of all \typ{VECSMALL}s of length $n$ whose $i$-th entry lies in $[0,d_i[$. Assumes that the product of the $d_i$ fits in a \kbd{long}. \fun{long}{zv_cyc_minimize}{GEN d, GEN c, GEN coprime} given $d = (d_1,\dots,d_n)$, $d_n \mid \dots \mid d_1 \neq 0$ a list of elementary divisors for a finite abelian group as a \typ{VECSMALL}, given $c = [g_1,\dots,g_n]$ representing an element in the group, and given a mask \kbd{coprime} (as from \kbd{coprimes\_zv}$(o)$) representing a list of forbidden congruence classes modulo $o$, return an integer $k$ such that \kbd{coprime}$[k \% o]$ is nonzero and $k \cdot c$ is lexicographically minimal. For instance, if $c$ is attached to a Dirichlet character $\chi$ of order $o$ via the usual identification $\chi(g_i) = \zeta_{g_i}^{c_i}$, then $\chi^k$ is a ``canonical'' representative in the Galois orbit of $\chi$. \fun{long}{zv_cyc_minimal}{GEN d, GEN c, GEN coprime} return $1$ if \tet{zv_cyc_minimize} would return $k = 1$, i.e. $c$ is already the canonical representative for the attached character orbit. \subsec{Dirichlet characters} The functions in this section are specific to characters on $(\Z/N\Z)^*$. The argument $G$ is a special \kbd{bid} structure as returned by \kbd{znstar0(N, nf\_INIT)}. In this case, there are additional ways to input character via Conrey's representation. The character \kbd{chi} is either a \typ{INT} (Conrey label), a \typ{COL} (a Conrey logarithm) or a \typ{VEC} (generic character on \kbd{bid.gen} as explained in the previous subsection). The following low-level functions are called by GP's generic character functions. \fun{int}{zncharcheck}{GEN G, GEN chi} return $1$ if \kbd{chi} is a valid character and $0$ otherwise. \fun{GEN}{zncharconj}{GEN G, GEN chi} as \kbd{charconj}. \fun{GEN}{znchardiv}{GEN G, GEN a, GEN b} as \kbd{chardiv}. \fun{GEN}{zncharker}{GEN G, GEN chi} as \kbd{charker}. \fun{GEN}{znchareval}{GEN G, GEN chi, GEN n, GEN z} as \kbd{chareval}. \fun{GEN}{zncharmul}{GEN G, GEN a, GEN b} as \kbd{charmul}. \fun{GEN}{zncharpow}{GEN G, GEN a, GEN n} as \kbd{charpow}. \fun{GEN}{zncharorder}{GEN G, GEN chi} as \kbd{charorder}. The following functions handle characters in Conrey notation (attached to Conrey generators, not \kbd{G.gen}): \fun{int}{znconrey_check}{GEN cyc, GEN chi} return $1$ if \kbd{chi} is a valid Conrey logarithm and $0$ otherwise. \fun{GEN}{znconrey_normalized}{GEN G, GEN chi} return normalized character attached to \kbd{chi}, as in \kbd{char\_normalize} but on Conrey generators. \fun{GEN}{znconreyfromchar}{GEN G, GEN chi} return Conrey logarithm attached to the generic (\typ{VEC}, on \kbd{G.gen}) \fun{GEN}{znconreyfromchar_normalized}{GEN G, GEN chi} return normalized Conrey character attached to the generic (\typ{VEC}, on \kbd{G.gen}) character \kbd{chi}. \fun{GEN}{znconreylog_normalize}{GEN G, GEN m} given a Conrey logarithm $m$ (\typ{COL}), return the attached normalized Conrey character, as in \kbd{char\_normalize} but on Conrey generators. \fun{GEN}{znchar_quad}{GEN G, GEN D} given a nonzero \typ{INT} $D$ congruent to $0,1$ mod $4$, return $(D/.)$ as a character modulo $N$, given by a Conrey logarithm (\typ{COL}). Assume that $|D|$ divides $N$. \fun{GEN}{Zideallog}{GEN G, GEN x} return the \kbd{znconreylog} of $x$ expressed on \kbd{G.gen}, i.e. the ordinary discrete logarithm from \kbd{ideallog}. \fun{GEN}{ncharvecexpo}{GEN G, GEN nchi} given \kbd{nchi} $= [d,n]$ a quasi-normalized character ($d$ may be a multiple of the character order), i.e. $\chi(g_i) = e(n[i]/d)$ for all Conrey or SNF generators $g_i$ (as usual, we use SNF generators if $n$ is a \typ{VEC} and the Conrey generators otherwise). Return a \typ{VECSMALL} $v$ such that $v[i] = -1$ if $(i,N) > 1$ else $\chi(i) = e(v[i]/d)$, $1 \leq i \leq N$. \section{Hecke characters} The functions in this section are specific to Hecke characters. The argument \kbd{gc} is a \kbd{gchar} structure as returned by \kbd{gcharinit(bnf, mod)}, and the character \kbd{chi} is a \typ{COL} of components on the SNF generators of \kbd{gc}. \fun{GEN}{eulerf_gchar}{GEN an, GEN p, long prec} \kbd{an} being the first component of a Hecke L-function \kbd{Ldata} (as output by \kbd{lfungchar}) and $p$ a prime number, return the Euler factor at $p$. \fun{GEN}{gchari_lfun}{GEN gc, GEN chi, GEN w} \kbd{chi} being a \typ{VEC} describing a Hecke character encoded on the internal basis \kbd{gc[1]}, return the \kbd{Ldata} structure corresponding to the Hecke L-function associated to \kbd{chi}. \fun{int}{is_gchar_group}{GEN gc} return $1$ if \kbd{gc} is a valid gchar structure and $0$ otherwise. \fun{GEN}{lfungchar}{GEN gc, GEN chi} return the \kbd{Ldata} structure corresponding to the Hecke L-function associated to \kbd{chi}. \fun{GEN}{vecan_gchar}{GEN an, long n, long prec} \kbd{an} being the first component of a Hecke L-function \kbd{Ldata} (as output by \kbd{lfungchar}), return a \typ{VEC} of length $n$ containing the first $n$ Dirichlet coefficients of this L-function, computed to absolute precision \kbd{prec}. \section{Central simple algebras} \subsec{Initialization} Low-level routines underlying \kbd{alginit}; argument \kbd{rnf} (resp.~\kbd{nf}) must be true \var{rnf} (resp.~\var{nf}) structure. The meaning of~$\fl$ is the same as in~\kbd{alginit}. \fun{GEN}{alg_csa_table}{GEN nf, GEN mt, long v, long flag} central simple algebra defined by a multiplication table over \kbd{nf}. \fun{GEN}{alg_cyclic}{GEN rnf, GEN aut, GEN b, long flag} cyclic algebra~$(L/K,\sigma,b)$. \fun{GEN}{alg_hasse}{GEN nf, long d, GEN hi, GEN hf, long v, long flag} algebra defined by local Hasse invariants. \fun{GEN}{alg_hilbert}{GEN nf, GEN a, GEN b, long v, long flag} quaternion algebra. \fun{GEN}{alg_matrix}{GEN nf, long n, long v, long flag} matrix algebra of degree \kbd{n} over \kbd{nf}. \fun{GEN}{alg_complete}{GEN rnf, GEN aut, GEN hf, GEN hi, long flag} cyclic algebra~$(L/K,\sigma,b)$ with~$b$ computed from the Hasse invariants. \subsec{Type checks} \fun{void}{checkalg}{GEN a} raise an exception if $a$ was not initialized by \tet{alginit}. \fun{void}{checklat}{GEN al, GEN lat} raise an exception if \kbd{lat} is not a valid full lattice in the algebra~\kbd{al}. \fun{void}{checkhasse}{GEN nf, GEN hi, GEN hf, long n} raise an exception if~$(\kbd{hi},\kbd{hf})$ do not describe valid Hasse invariants of a central simple algebra of degree~\kbd{n} over~\kbd{nf}. \fun{long}{alg_type}{GEN al} internal function called by \tet{algtype}: assume \kbd{al} was created by \tet{alginit} (thereby saving a call to \kbd{checkalg}). Return values are symbolic rather than numeric: \item \kbd{al\_NULL}: not a valid algebra. \item \kbd{al\_TABLE}: table algebra output by \kbd{algtableinit}. \item \kbd{al\_CSA}: central simple algebra output by \kbd{alginit} and represented by a multiplication table over its center. \item \kbd{al\_CYCLIC}: central simple algebra output by \kbd{alginit} and represented by a cyclic algebra. \fun{long}{alg_model}{GEN al, GEN x} given an element $x$ in algebra \var{al}, check for inconsistencies (raise a type error) and return the representation model used for $x$: \item \kbd{al\_ALGEBRAIC}: \kbd{basistoalg} form, algebraic representation. \item \kbd{al\_BASIS}: \kbd{algtobasis} form, column vector on the integral basis. \item \kbd{al\_MATRIX}: matrix with coefficients in an algebra. \item \kbd{al\_TRIVIAL}: trivial algebra of degree $1$; can be understood as both basis or algebraic form (since $e_1 = 1$). \subsec{Shallow accessors} All these routines assume their argument was initialized by \tet{alginit} and provide minor speedups compared to the GP equivalent. The routines returning a \kbd{GEN} are shallow. \fun{long}{alg_get_absdim}{GEN al} low-level version of \kbd{algabsdim}. \fun{long}{alg_get_dim}{GEN al} low-level version of \kbd{algdim}. \fun{long}{alg_get_degree}{GEN al} low-level version of \kbd{algdegree}. \fun{GEN}{alg_get_aut}{GEN al} low-level version of \kbd{algaut}. \fun{GEN}{alg_get_auts}{GEN al}, given a cyclic algebra $\var{al} = (L/K,\sigma,b)$ of degree $n$, returns the vector of $\sigma^i$, $1 \leq i < n$. \fun{GEN}{alg_get_b}{GEN al} low-level version of \kbd{algb}. \fun{GEN}{alg_get_basis}{GEN al} low-level version of \kbd{algbasis}. \fun{GEN}{alg_get_center}{GEN al} low-level version of \kbd{algcenter}. \fun{GEN}{alg_get_char}{GEN al} low-level version of \kbd{algchar}. \fun{GEN}{alg_get_hasse_f}{GEN al} low-level version of \kbd{alghassef}. \fun{GEN}{alg_get_hasse_i}{GEN al} low-level version of \kbd{alghassei}. \fun{GEN}{alg_get_invbasis}{GEN al} low-level version of \kbd{alginvbasis}. \fun{GEN}{alg_get_multable}{GEN al} low-level version of \kbd{algmultable}. \fun{GEN}{alg_get_relmultable}{GEN al} low-level version of \kbd{algrelmultable}. \fun{GEN}{alg_get_splittingfield}{GEN al} low-level version of \kbd{algsplittingfield}. \fun{GEN}{alg_get_abssplitting}{GEN al} returns the absolute \var{nf} structure attached to the \var{rnf} returned by \kbd{algsplittingfield}. \fun{GEN}{alg_get_splitpol}{GEN al} returns the relative polynomial defining the \var{rnf} returned by \kbd{algsplittingfield}. \fun{GEN}{alg_get_splittingdata}{GEN al} low-level version of \kbd{algsplittingdata}. \fun{GEN}{alg_get_splittingbasis}{GEN al} the matrix \var{Lbas} from \kbd{algsplittingdata} \fun{GEN}{alg_get_splittingbasisinv}{GEN al} the matrix \var{Lbasinv} from \kbd{algsplittingdata}. \fun{GEN}{alg_get_tracebasis}{GEN al} returns the traces of the basis elements; used by \kbd{algtrace}. \fun{GEN}{alglat_get_primbasis}{GEN lat} from the description of \kbd{lat} as~$\lambda L$ with~$L\subset{\cal O}_0$ and~$\lambda\in\Q$, returns a basis of~$L$. \fun{GEN}{alglat_get_scalar}{GEN lat} from the description of \kbd{lat} as~$\lambda L$ with~$L\subset{\cal O}_0$ and~$\lambda\in\Q$, returns~$\lambda$. \subsec{Other low-level functions} \fun{GEN}{conjclasses_algcenter}{GEN cc, GEN p} low-level function underlying \kbd{alggroupcenter}, where \kbd{cc} is the output of \kbd{groupelts\_to\_conjclasses}, and $p$ is either \kbd{NULL} or a prime number. Not stack clean. \fun{GEN}{algsimpledec_ss}{GEN al, long maps} assuming that~\kbd{al} is semisimple, returns the second component of~\kbd{algsimpledec(al,maps)}. \newpage pari-2.17.2/doc/index.tex0000644000175000017500000000643011636712103013565 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.17.2/doc/refcard-mf.tex0000644000175000017500000003036514676526175014513 0ustar billbill% Copyright (c) 2007-2016 Karim Belabas. % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License % Reference Card for PARI-GP, Algebraic Number Theory. % Author: % Karim Belabas % Universite de Bordeaux, 351 avenue de la Liberation, F-33405 Talence % email: Karim.Belabas@math.u-bordeaux.fr % % See refcard.tex for acknowledgements and thanks. \def\TITLE{Modular forms, modular symbols} \input refmacro.tex \section{Modular Forms} \subsec{Dirichlet characters} Characters are encoded in three different ways: \item a \typ{INT} $D\equiv 0,1\mod 4$: the quadratic character $(D/\cdot)$; \item a \typ{INTMOD} \kbd{Mod}$(m,q)$, $m\in(\ZZ/q)^*$ using a canonical bijection with the dual group (the Conrey character $\chi_q(m,\cdot)$); \item a pair $[G,\kbd{chi}]$, where $G = \kbd{znstar}(q,1)$ encodes $(\ZZ/q\ZZ)^* = \sum_{j \leq k} (\ZZ/d_j\ZZ) \cdot g_j$ and the vector $\kbd{chi} = [c_1,\dots,c_k]$ encodes the character such that $\chi(g_j) = e(c_j/d_j)$. \medskip \li{initialize $G = (\ZZ/q\ZZ)^*$}{G = znstar$(q,1)$} \li{convert datum $D$ to $[G,\chi]$}{znchar$(D)$} \li{Galois orbits of Dirichlet characters}{chargalois$(G)$} \subsec{Spaces of modular forms} Arguments of the form $[N,k,\chi]$ give the level weight and nebentypus $\chi$; $\chi$ can be omitted: $[N,k]$ means trivial $\chi$.\hfil\break \li{initialize $S_k^{\text{new}}(\Gamma_0(N),\chi)$}{mfinit$([N,k,\chi],0)$} \li{initialize $S_k(\Gamma_0(N),\chi)$}{mfinit$([N,k,\chi],1)$} \li{initialize $S_k^{\text{old}}(\Gamma_0(N),\chi)$}{mfinit$([N,k,\chi],2)$} \li{initialize $E_k(\Gamma_0(N),\chi)$}{mfinit$([N,k,\chi],3)$} \li{initialize $M_k(\Gamma_0(N),\chi)$}{mfinit$([N,k,\chi])$} \li{find eigenforms}{mfsplit$(M)$} \li{statistics on self-growing caches}{getcache$()$} \smallskip We let $M$ = \kbd{mfinit}$(\dots)$ denote a modular space. \hfil\break \li{describe the space $M$}{mfdescribe$(M)$} \li{recover $(N,k,\chi)$}{mfparams$(M)$} \li{\dots the space identifier (0 to 4)}{mfspace$(M)$} \li{\dots the dimension of $M$ over $\CC$}{mfdim$(M)$} \li{\dots a $\CC$-basis $(f_i)$ of $M$}{mfbasis$(M)$} \li{\dots a basis $(F_j)$ of eigenforms}{mfeigenbasis$(M)$} \li{\dots polynomials defining $\QQ(\chi)(F_j)/\QQ(\chi)$}{mffields$(M)$} \smallskip \li{matrix of Hecke operator $T_n$ on $(f_i)$}{mfheckemat$(M,n)$} \li{eigenvalues of $w_Q$}{mfatkineigenvalues$(M,Q)$} \li{basis of period poynomials for weight $k$}{mfperiodpolbasis$(k)$} \li{basis of the Kohnen $+$-space}{mfkohnenbasis$(M)$} \li{\dots new space and eigenforms}{mfkohneneigenbasis$(M, b)$} \li{isomorphism $S_k^+(4N,\chi) \to S_{2k-1}(N,\chi^2)$} {mfkohnenbijection$(M)$} \smallskip Useful data can also be obtained a priori, without computing a complete modular space: \hfil\break \li{dimension of $S_k^{\text{new}}(\Gamma_0(N),\chi)$}{mfdim$([N,k,\chi])$} \li{dimension of $S_k(\Gamma_0(N),\chi)$}{mfdim$([N,k,\chi],1)$} \li{dimension of $S_k^{\text{old}}(\Gamma_0(N),\chi)$}{mfdim$([N,k,\chi],2)$} \li{dimension of $M_k(\Gamma_0(N),\chi)$}{mfdim$([N,k,\chi],3)$} \li{dimension of $E_k(\Gamma_0(N),\chi)$}{mfdim$([N,k,\chi],4)$} \li{Sturm's bound for $M_k(\Gamma_0(N),\chi)$}{mfsturm$(N,k)$} \subsec{$\Gamma_0(N)$ cosets} \li{list of right $\Gamma_0(N)$ cosets}{mfcosets$(N)$} \li{identify coset a matrix belongs to}{mftocoset} \subsec{Cusps} a cusp is given by a rational number or \kbd{oo}.\hfil\break \li{lists of cusps of $\Gamma_0(N)$}{mfcusps$(N)$} \li{number of cusps of $\Gamma_0(N)$}{mfnumcusps$(N)$} \li{width of cusp $c$ of $\Gamma_0(N)$}{mfcuspwidth$(N,c)$} \li{is cusp $c$ regular for $M_k(\Gamma_0(N),\chi)$?} {mfcuspisregular$([N,k,\chi], c)$} \subsec{Create an individual modular form} Besides \kbd{mfbasis} and \kbd{mfeigenbasis}, an individual modular form can be identified by a few coefficients.\hfil\break \li{modular form from coefficients}{mftobasis(mf,\var{vec})} \smallskip There are also many predefined ones:\hfil\break \li{Eisenstein series $E_k$ on $Sl_2(\ZZ)$}{mfEk$(k)$} \li{Eisenstein-Hurwitz series on $\Gamma_0(4)$}{mfEH$(k)$} \li{unary $\theta$ function (for character $\psi$)}{mfTheta$(\{\psi\})$} \li{Ramanujan's $\Delta$}{mfDelta$()$} \li{$E_k(\chi)$}{mfeisenstein$(k,\chi)$} \li{$E_k(\chi_1,\chi_2)$}{mfeisenstein$(k,\chi_1,\chi_2)$} \li{eta quotient $\prod_i \eta(a_{i,1} \cdot z)^{a_{i,2}}$}{mffrometaquo$(a)$} \li{newform attached to ell. curve $E/\QQ$}{mffromell$(E)$} \li{identify an $L$-function as a eigenform}{mffromlfun$(L)$} \li{$\theta$ function attached to $Q > 0$}{mffromqf$(Q)$} \li{trace form in $S_k^{\text{new}}(\Gamma_0(N),\chi)$} {mftraceform$([N,k,\chi])$} \li{trace form in $S_k(\Gamma_0(N),\chi)$} {mftraceform$([N,k,\chi], 1)$} \subsec{Operations on modular forms} In this section, $f$, $g$ and the $F[i]$ are modular forms\hfil\break \li{$f\times g$}{mfmul$(f,g)$} \li{$f / g$}{mfdiv$(f,g)$} \li{$f^n$}{mfpow$(f,n)$} \li{$f(q)/q^v$}{mfshift$(f,v)$} \li{$\sum_{i\leq k} \lambda_i F[i]$, $L = [\lambda_1,\dots,\lambda_k]$} {mflinear$(F,L)$} \li{$f = g$?}{mfisequal(f,g)} \li{expanding operator $B_d(f)$}{mfbd$(f,d)$} \li{Hecke operator $T_n f$}{mfhecke$(mf,f,n)$} \li{initialize Atkin--Lehner operator $w_Q$}{mfatkininit$(mf,Q)$} \li{\dots apply $w_Q$ to $f$}{mfatkin$(w_Q,f)$} \li{twist by the quadratic char $(D/\cdot)$}{mftwist$(f,D)$} \li{derivative wrt. $q \cdot d/dq$}{mfderiv$(f)$} \li{see $f$ over an absolute field}{mfreltoabs$(f)$} \li{Serre derivative $\big(q \cdot {d\over dq} - {k\over 12} E_2\big) f$} {mfderivE2$(f)$} \li{Rankin-Cohen bracket $[f,g]_n$}{mfbracket$(f,g,n)$} \li{Shimura lift of $f$ for discriminant $D$}{mfshimura$(mf,f,D)$} \subsec{Properties of modular forms} In this section, $f = \sum_n f_n q^n$ is a modular form in some space $M$ with parameters $N,k,\chi$.\hfil\break \li{describe the form $f$}{mfdescribe$(f)$} \li{$(N,k,\chi)$ for form $f$}{mfparams$(f)$} \li{the space identifier (0 to 4) for $f$}{mfspace$(mf,f)$} \li{$[f_0,\dots,f_n]$}{mfcoefs$(f, n)$} \li{$f_n$}{mfcoef$(f,n)$} \li{is $f$ a CM form?}{mfisCM$(f)$} \li{is $f$ an eta quotient?}{mfisetaquo$(f)$} \li{Galois rep. attached to all $(1,\chi)$ eigenforms} {mfgaloistype$(M)$} \li{\dots single eigenform}{mfgaloistype$(M,F)$} \li{\dots as a polynomial fixed by $\text{Ker}~\rho_F$}{mfgaloisprojrep$(M,F)$} \li{decompose $f$ on \kbd{mfbasis}$(M)$}{mftobasis$(M,f)$} \li{smallest level on which $f$ is defined}{mfconductor$(M,f)$} \li{decompose $f$ on $\oplus S_k^{\text{new}}(\Gamma_0(d))$, $d\mid N$} {mftonew$(M,f)$} \li{valuation of $f$ at cusp $c$}{mfcuspval$(M,f,c)$} \li{expansion at $\infty$ of $f \mid_k \gamma$}{mfslashexpansion$(M,f,\gamma,n)$} \li{$n$-Taylor expansion of $f$ at $i$}{mftaylor$(f,n)$} \li{all rational eigenforms matching criteria}{mfeigensearch} \li{\dots forms matching criteria}{mfsearch} \subsec{Forms embedded into $\CC$} Given a modular form $f$ in $M_k(\Gamma_0(N),\chi)$ its field of definition $\Q(f)$ has $n = [\Q(f):\Q(\chi)]$ embeddings into the complex numbers. If $n = 1$, the following functions return a single answer, attached to the canonical embedding of $f$ in $\CC[[q]]$; else a vector of $n$ results, corresponding to the $n$ conjugates of $f$.\hfill\break \li{complex embeddings of $\Q(f)$}{mfembed$(f)$} \li{... embed coefs of $f$}{mfembed$(f, v)$} \li{evaluate $f$ at $\tau\in{\cal H}$}{mfeval$(f,\tau)$} \li{$L$-function attached to $f$}{lfunmf$(mf,f)$} \li{\dots eigenforms of new space $M$}{lfunmf$(M)$} \subsec{Periods and symbols} The functions in this section depend on $[\Q(f):\Q(\chi)]$ as above. \li{initialize symbol $fs$ attached to $f$}{mfsymbol$(M,f)$} \li{evaluate symbol $fs$ on path $p$}{mfsymboleval$(fs,p)$} \li{Petersson product of $f$ and $g$}{mfpetersson$(fs,gs)$} \li{period polynomial of form $f$}{mfperiodpol$(M,fs)$} \li{period polynomials for eigensymbol $FS$}{mfmanin$(FS)$} \medskip \section{Modular Symbols} Let $G = \Gamma_0(N)$, $V_k = \QQ[X,Y]_{k-2}$ and $L_k = \ZZ[X,Y]_{k-2}$. Let $\Delta = \text{Div}^0(\PP^1(\QQ))$, generated by \emph{paths} between cusps of $X_0(N)$, via the identification $[b]-[a] \to $ path from $a$ to $b$. In GP, the latter is coded by the pair $[a,b]$ where $a,b$ are rationals or \kbd{oo} = $(1:0)$.\hfil\break Let $\MM_k(G) = \Hom_G(\Delta, V_k) \simeq H^1_c(X_0(N),V_k)$; an element of $\MM_k(G)$ is a $V_k$-valued \emph{modular symbol}. There is a natural decomposition $\MM_k(G) = \MM_k(G)^+ \oplus \MM_k(G)^-$ under the action of the $*$ involution, induced by complex conjugation. The \kbd{msinit} function computes either $\MM_k$ ($\varepsilon = 0$) or its $\pm$-parts ($\varepsilon = \pm1$) and fixes a minimal set of $\ZZ[G]$-generators $(g_i)$ of $\Delta$.\hfil\break \li{initialize $M = \MM_k(\Gamma_0(N))^\varepsilon$} {msinit$(N,k,\{\varepsilon=0\})$} \li{the level $M$}{msgetlevel$(M)$} \li{the weight $k$}{msgetweight$(M)$} \li{the sign $\varepsilon$}{msgetsign$(M)$} \li{Farey symbol attached to $G$}{mspolygon$(M)$} \li{\dots attached to $H < G$}{msfarey$(F, inH)$} \li{$H\backslash G$ and right $G$-action}{mscosets$(genG, inH)$} \smallskip \li{$\ZZ[G]$-generators $(g_i)$ and relations for $\Delta$}{mspathgens$(M)$} \li{decompose $p = [a,b]$ on the $(g_i)$}{mspathlog$(M,p)$} \smallskip \subsec{Create a symbol} \li{Eisenstein symbol attached to cusp $c$}{msfromcusp$(M,c)$} \li{cuspidal symbol attached to $E/\QQ$}{msfromell$(E)$} \li{symbol having given Hecke eigenvalues}{msfromhecke$(M,v,\{H\})$} \li{is $s$ a symbol ?}{msissymbol$(M,s)$} \subsec{Operations on symbols} \li{the list of all $s(g_i)$}{mseval$(M,s)$} \li{evaluate symbol $s$ on path $p=[a,b]$}{mseval$(M,s,p)$} \li{Petersson product of $s$ and $t$}{mspetersson$(M,s,t)$} \subsec{Operators on subspaces} An operator is given by a matrix of a fixed $\QQ$-basis. $H$, if given, is a stable $\QQ$-subspace of $\MM_k(G)$: operator is restricted to $H$.\hfil\break \li{matrix of Hecke operator $T_p$ or $U_p$}{mshecke$(M,p,\{H\})$} \li{matrix of Atkin-Lehner $w_Q$}{msatkinlehner$(M,Q\{H\})$} \li{matrix of the $*$ involution}{msstar$(M,\{H\})$} \subsec{Subspaces} A subspace is given by a structure allowing quick projection and restriction of linear operators. Its fist component is a matrix with integer coefficients whose columns for a $\QQ$-basis. If $H$ is a Hecke-stable subspace of $M_k(G)^+$ or $M_k(G)^-$, it can be split into a direct sum of Hecke-simple subspaces. To a simple subspace corresponds a single normalized newform $\sum_n a_n q^n$. \hfil\break \li{cuspidal subspace $S_k(G)^\varepsilon$}{mscuspidal$(M)$} \li{Eisenstein subspace $E_k(G)^\varepsilon$}{mseisenstein$(M)$} \li{new part of $S_k(G)^\varepsilon$}{msnew$(M)$} \li{split $H$ into simple subspaces (of dim $\leq d$)}{mssplit$(M,H,\{d\})$} \li{dimension of a subspace}{msdim$(M)$} \li{$(a_1,\dots, a_B)$ for attached newform} {msqexpansion$(M, H, \{B\})$} \li{$\ZZ$-structure from $H^1(G,L_k)$ on subspace $A$ }{mslattice$(M,A)$} \medskip \subsec{Overconvergent symbols and $p$-adic $L$ functions} Let $M$ be a full modular symbol space given by \kbd{msinit} and $p$ be a prime. To a classical modular symbol $\phi$ of level $N$ ($v_p(N)\leq 1$), which is an eigenvector for $T_p$ with nonzero eigenvalue $a_p$, we can attach a $p$-adic $L$-function $L_p$. The function $L_p$ is defined on continuous characters of $\text{Gal}(\QQ(\mu_{p^\infty})/\QQ)$; in GP we allow characters $\langle \chi \rangle^{s_1} \tau^{s_2}$, where $(s_1,s_2)$ are integers, $\tau$ is the Teichm\"uller character and $\chi$ is the cyclotomic character. The symbol $\phi$ can be lifted to an \emph{overconvergent} symbol $\Phi$, taking values in spaces of $p$-adic distributions (represented in GP by a list of moments modulo $p^n$). \kbd{mspadicinit} precomputes data used to lift symbols. If $\fl$ is given, it speeds up the computation by assuming that $v_p(a_p) = 0$ if $\fl = 0$ (fastest), and that $v_p(a_p) \geq \fl$ otherwise (faster as $\fl$ increases). \kbd{mspadicmoments} computes distributions \var{mu} attached to $\Phi$ allowing to compute $L_p$ to high accuracy. \li{initialize $\var{Mp}$ to lift symbols}{mspadicinit$(M,p,n,\{\fl\})$} \li{lift symbol $\phi$}{mstooms$(\var{Mp}, \phi)$} \li{eval overconvergent symbol $\Phi$ on path $p$}{msomseval$(\var{Mp},\Phi,p)$} \li{\var{mu} for $p$-adic $L$-functions} {mspadicmoments$(\var{Mp}, S, \{D=1\})$} \li{$L_p^{(r)}(\chi^s)$, $s = [s_1,s_2]$} {mspadicL$(\var{mu}, \{s = 0\}, \{r = 0\})$} \li{$\hat{L}_p(\tau^i)(x)$}{mspadicseries$(\var{mu}, \{i = 0\})$} \copyrightnotice \bye pari-2.17.2/doc/gp.10000644000175000017500000002353614760123736012443 0ustar billbill.TH GP 1 "12 September 2024" .SH NAME gp \- The PARI calculator .SH SYNOPSIS .B gp .RB [ -s .IR stacksize ] .RB [ -p .IR primelimit ] .RB [ --emacs ] .RB [ -f | --fast ] .RB [ -q | --quiet ] .RB [ -D | --default .IR key=val ] .RB [ --help ] .RB [ --test ] .RB [ --texmacs ] .RB [ --version ] .RB [ --version-short ] [ file1 file2 ...] .SH DESCRIPTION Invokes the PARI-GP calculator \&\fBgp\fR; gp is an advanced programmable calculator, specializing in number theory, which computes symbolically as long as possible, numerically where needed, and contains a wealth of arithmetic functions: factorizations, elliptic curves, Galois theory, class field theory, modular forms, etc. Commands, written in the GP scripting language, are input interactively or loaded from files. If present at the end of the command line, files 'file1', 'file2', ... are loaded on startup; they must be written in the GP language. .SH OPTIONS Command line options are available in both short form (-f) and POSIX-like (--fast). Numeric arguments can be followed by a modifier .B k , .B M or .B G at the user's convenience; in that case the argument is multiplied by 10^3, 10^6, or 10^9 respectively. .TP .B \-f, \--fast Fast start (or factory settings). Do not read .B .gprc (see below) upon startup. .TP .B \-p limit [DEPRECATED] Upon startup, gp computes a table of small primes used in number-theoretic applications. If .I primelimit is set, the table include primes up to that bound instead of the default (= 1048576). It is now mostly useless to change this value. .TP .B \-q, \--quiet Quiet mode. Do not print headers or history numbers and do not say goodbye. .TP .B \-D, \--default key=val performs .BR default(key, .BR val) ";" on startup, overriding values from the .B gprc preferences file. 'val' must be a constant value and is not allowed to involve any computation (e.g. 1+1 is forbidden). Any number of such default-setting statements may appear on the command line. A key may be set multiple times, the last setting taking precedence .TP .B \-s limit Size of gp internal stack allocated on startup. When gp runs out of space, it interrupts the current computation and raises a .BI "stack overflow" exception. If this occurs frequently, start with a bigger stack. The stack size can also be increased from within gp, using .BR default(parisize, limit) ";" it is convenient to set .B parisize from your .B .gprc to that the setting is persistent across sessions; a value of 80MB is sensible. We strongly advise to also set .B parisizemax to a positive, much larger, value in your .B .gprc (about what you believe your machine can stand, usually half the available RAM or so): this strives to fit computation in the parisize range but allows it to temporarily go beyond it (up to parisizemax). Note that computations with a .B smaller stack may be more efficient due to better data locality. Finally, .B threadsize and .B threadsizemax play analogous roles in the parallel version of gp. .TP .B \--emacs gp can be run in an .I Emacs shell (see GP User's manual for details). This flag is then required for smooth interaction with the .I PariEmacs package (pari.el). It is set automatically by the pari.el package, and will produce display oddities if you set it outside of an .I Emacs session. .TP .B \--help print a summary of available command-line options. .TP .B \--test run gp in test mode: suppress printing of history numbers and wrap long output lines (to get readable diff output). For benches only. .TP .B \--texmacs gp can be run from a .I TeXmacs frontend. This flag is set by TeXmacs, to enable special purpose communication channels. Do not set it yourself. .TP .B \--version output version info (banner) then exit. .TP .B \--version-short output version number then exit. .SH USE .TP .B ? to get online help. .TP .B ?? to get extended online help (more precisely, to call the external help program, .B gphelp by default) .TP .B quit (or \\q), or .B EOF (Ctrl-D) to quit .BR gp . .PP The following works only when gp was linked with GNU .IR readline library: .TP arrow keys for editing and viewing the input history. .TP .B TAB for automatic completion .SH MANUALS The following material is included in the standard distribution (originally in TeX format) and can also be downloaded at .RS .I https://pari.math.u-bordeaux.fr/doc.html .RE or viewed online at .RS .I https://pari.math.u-bordeaux.fr/dochtml/html/ .RE .TP .I The User's Guide to PARI/GP (users.dvi) .TP .I The User's Guide to the PARI library (library.dvi) .TP .I The Developer's Guide to the PARI library (develop.dvi) .TP .I PARI/GP, a tutorial (tutorial.dvi) .TP .I PARI/GP reference cards (refcard*.dvi) .SH FILES .TP .I gp main executable .TP .I $HOME/.gprc (or $GPRC if set) user preference file, read at beginning of execution by each .B gp shell. A default gprc .I gprc.dft is provided with the distribution. If this file cannot be found, .I /etc/gprc is checked instead. .TP .I a file used to log in all commands and results; default: .B pari.log (you need to set the .B log default in your gprc or interactively) .TP .I a file used to dump PostScript drawings; default: .B pari.ps .TP .I a file where gp will keep a history of all input commands (you need to set the .B histfile default in the gprc file) .TP .I gphelp default external help program (as above) .TP .I *.gp GP programs .SH ENVIRONMENT .TP .I $GPRC place to look for the user's preference file (gprc); if the file does not exist, we then check in $HOME/.gprc, /etc/gprc, and finally for a file named 'gprc' in PARI's .B datadir. .TP .I $GP_DATA_DIR directory containing data installed by optional PARI packages. For example, the Galois resolvents files in directory .I galdata/ needed by the .B polgalois function, in degrees 8 to 11; or the modular polynomials in .I seadata/ used by the .B ellap function for large base fields. This environment variable overrides PARI's 'datadir', defined at Configure time. .TP .I $GP_POSTSCRIPT_VIEWER an application able to display PostScript files, used by the .I plotps graphic engine. This engine is a fallback used to output hi-res plots even when no compatible graphical library was available on your platform at Configure time. (Dumps the graph to a temporary file, then open the file.) .TP .I $GP_SVG_VIEWER an application able to display SVG images files, used by the .I plotsvg graphic engine. This engine is a fallback used to output hi-res plots even when no compatible graphical library was available on your platform at Configure time. (Dumps the graph to a temporary file, then open the file.) .TP .I $GPHELP name of the external help program invoked by ?? and ??? shortcuts. .TP .I $GPTMPDIR name of the directory where temporary files will be generated. .SH HOME PAGE PARI's home page resides at .RS .I https://pari.math.u-bordeaux.fr/ .RE .SH MAILING LISTS There are a number of mailing lists devoted to the PARI/GP package, and most feedback should be directed to those. See .RS .I https://pari.math.u-bordeaux.fr/lists.html .RE for details. The most important ones are: .PP - .B pari-announce (moderated): for us to announce major version changes. .PP - .B pari-dev: for everything related to the development of PARI, including suggestions, technical questions, bug reports or patch submissions. .PP - .B pari-users: for discuss about everything else, in particular ask for help. To subscribe, send empty messages with a Subject: containing the word "subscribe" respectively to .PP pari-announce-request@pari.math.u-bordeaux.fr .PP pari-users-request@pari.math.u-bordeaux.fr .PP pari-dev-request@pari.math.u-bordeaux.fr .SH BUG REPORTS Bugs should be submitted online to our Bug Tracking System, available from PARI's home page, or directly from the URL .RS .I https://pari.math.u-bordeaux.fr/Bugs/ .RE Further instructions can be found on that page. .SH TRIVIA Despite the leading G, GP has nothing to do with GNU. The first version was originally called GPC, for Great Programmable Calculator. When people started calling it "the GPC Calculator", the trailing C was dropped. PARI has nothing to do with the French capital. The name is a pun about the project's early stages when the authors started to implement a library for "Pascal ARIthmetic" in the PASCAL programming language. They quickly switched to C. For the benefit of non-native French speakers, here's a slightly expanded explanation: .B Blaise Pascal (1623-1662) was a famous French mathematician and philosopher who was one of the founders of probability and devised one of the first "arithmetic machines". He once proposed the following "proof" of the existence of God for the unbelievers: whether He exists or not I lose nothing by believing in Him, whereas if He does and I misbehave... This is the so-called "pari de Pascal" (Pascal's Wager). Note that PARI also means "fairy" in Persian. .SH AUTHORS PARI was originally written by Christian Batut, Dominique Bernardi, Henri Cohen, and Michel Olivier in Laboratoire A2X (Universite Bordeaux I, France), and was maintained by Henri Cohen up to version 1.39.15 (1995), and by Karim Belabas since then. A great number of people have contributed to the successive improvements which eventually resulted in the present version. See the AUTHORS file in the distribution. .SH SEE ALSO .IR gap (1), .IR gphelp (1), .IR perl (1), .IR readline (3), .IR sage (1), .IR tex (1), .IR texmacs (1), .SH COPYING This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. pari-2.17.2/doc/refcard-ell.tex0000644000175000017500000002505014676526175014660 0ustar billbill% Copyright (c) 2007-2024 Karim Belabas. % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License % Reference Card for PARI-GP, Elliptic curves % Author: % Karim Belabas % Universite de Bordeaux, 351 avenue de la Liberation, F-33405 Talence % email: Karim.Belabas@math.u-bordeaux.fr % % See refcard.tex for acknowledgements and thanks. \def\TITLE{Elliptic Curves} \input refmacro.tex An elliptic curve is initially given by 5-tuple $v=\kbd{[}a_1,a_2,a_3,a_4,a_6\kbd{]}$ attached to Weierstrass model or simply $\kbd{[}a_4,a_6\kbd{]}$. It must be converted to an \var{ell} struct. \hfil\break \li{Initialize \var{ell} struct over domain $D$}{E = ellinit$(v,\{D=1\})$} \beginindentedkeys \li{over $\QQ$}{$D = 1$} \li{over $\FF_p$}{$D = p$} \li{over $\FF_q$, $q = p^f$}{$D =\, $\kbd{ffgen([}$p,f$\kbd{])}} \li{over $\QQ_p$, precision $n$}{$D = O(p^n)$} \li{over $\CC$, current bitprecision}{$D = \kbd{1.0}$} \li{over number field $K$}{$D = \var{nf}$} \endindentedkeys \leavevmode Points are \kbd{[x,y]}, the origin is \kbd{[0]}. Struct members accessed as \kbd{E.}\var{member}:\hfill\break $\bullet$ All domains: \kbd{E.a1},\kbd{a2},\kbd{a3},\kbd{a4},\kbd{a6}, \kbd{b2},\kbd{b4},\kbd{b6},\kbd{b8}, \kbd{c4},\kbd{c6}, \kbd{disc}, \kbd{j}\hfill\break \li{$\bullet$ $E$ defined over $\RR$ or $\CC$}{} \beginindentedkeys \li{$x$-coords. of points of order $2$}{E.roots} \li{periods / quasi-periods}{E.omega{,\rm }E.eta} \li{volume of complex lattice}{E.area} \endindentedkeys \li{$\bullet$ $E$ defined over $\QQ_p$}{} \beginindentedkeys \li{residual characteristic}{E.p} \li{If $|j|_p>1$: Tate's $[u^2, u, q, [a,b], {\cal L}]$}{E.tate} \endindentedkeys \li{$\bullet$ $E$ defined over $\FF_q$}{} \beginindentedkeys \li{characteristic}{E.p} \li{$\#E(\FF_q)$/cyclic structure/generators}{E.no{\rm, }E.cyc{\rm, }E.gen} \endindentedkeys \li{$\bullet$ $E$ defined over $\QQ$}{} \beginindentedkeys \li{generators of $E(\QQ)$ (require \kbd{elldata})}{E.gen} \endindentedkeys \li{$[a_1,a_2,a_3,a_4,a_6]$ from $j$-invariant}{ellfromj$(j)$} \li{cubic/quartic/biquadratic to Weierstrass} {ellfromeqn$(\var{eq})$} \li{add points $P+Q$ / $P-Q$}{elladd$(E,P,Q)${\rm, }ellsub} \li{negate point}{ellneg$(E,P)$} \li{compute $n\cdot P$}{ellmul$(E,P,n)$} \li{sum of Galois conjugates of $P$}{elltrace$(E,P)$} \li{check if $P$ is on $E$}{ellisoncurve$(E,P)$} \li{order of torsion point $P$}{ellorder$(E,P)$} \li{$y$-coordinates of point(s) for $x$}{ellordinate$(E,x)$} \li{$[\wp(z),\wp'(z)]\in E(\CC)$ attached to $z\in\CC$}{ellztopoint$(E,z)$} \li{$z\in\CC$ such that $P=[\wp(z),\wp'(z)]$}{ellpointtoz$(E,P)$} \li{$z\in \bar{\QQ}^*/q^{\ZZ}$ to $P\in E(\bar{\QQ_p})$}{ellztopoint$(E,z)$} \li{$P\in E(\bar{\QQ_p})$ to $z\in \bar{\QQ}^*/q^{\ZZ}$}{ellpointtoz$(E,P)$} \subsec{Change of Weierstrass models, using $v = [u,r,s,t]$} \li{change curve $E$ using $v$}{ellchangecurve$(E,v)$} \li{change point $P$ using $v$}{ellchangepoint$(P,v)$} \li{change point $P$ using inverse of $v$}{ellchangepointinv$(P,v)$} \li{is $E$ isomorphic to $F$?}{ellisisom$(E,F)$} \subsec{Twists and isogenies} \li{quadratic twist}{elltwist$(E,d)$} \li{$n$-division polynomial $f_n(x)$}{elldivpol$(E,n,\{x\})$} \li{$[n]P =(\phi_n\psi_n\colon \omega_n\colon \psi_n^3)$; return $(\phi_n, \psi_n^2)$}{ellxn$(E,n,\{x\})$} \li{isogeny from $E$ to $E/G$}{ellisogeny$(E,G)$} \li{apply isogeny to $g$ (point or isogeny)}{ellisogenyapply$(f,g)$} \li{torsion subgroup with generators}{elltors$(E)$} \subsec{Formal group} \li{formal exponential, $n$ terms}{ellformalexp$(E,\{n\},\{x\})$} \li{formal logarithm, $n$ terms}{ellformallog$(E,\{n\},\{x\})$} \li{$log_E(-x(P)/y(P))\in\QQ_p$; $P\in E(\QQ_p)$}{ellpadiclog$(E,p,n,P)$} \li{$P$ in the formal group}{ellformalpoint$(E,\{n\},\{x\})$} \li{$[\omega/dt,x\omega/dt]$}{ellformaldifferential$(E,\{n\},\{x\})$} \newcolumn \li{$w = -1/y$ in parameter $-x/y$}{ellformalw$(E,\{n\},\{x\})$} \section{Curves over finite fields, Pairings} \li{random point on $E$}{random$(E)$} \li{$\#E(\FF_q)$}{ellcard$(E)$} \li{$\#E(\FF_q)$ with almost prime order}{ellsea$(E, \{\var{tors}\})$} \li{structure $\ZZ/d_1\ZZ\times \ZZ/d_2\ZZ$ of $E(\FF_q)$}{ellgroup$(E)$} \li{is $E$ supersingular?}{ellissupersingular$(E)$} \li{random supersingular $j$-invariant over $\F_p^2$}{ellsupersingularj$(p)$} \li{Weil pairing of $m$-torsion pts $P,Q$}{ellweilpairing$(E,P,Q, m)$} \li{Tate pairing of $P,Q$; $P$ $m$-torsion}{elltatepairing$(E,P,Q, m)$} \li{Discrete log, find $n$ s.t. $P=[n]Q$}{elllog$(E,P,Q,\{ord\})$} \section{Curves over $\QQ$} \subsec{Reduction, minimal model} \li{minimal model of $E/\QQ$} {ellminimalmodel$(E,\{$\&$v\})$} \li{quadratic twist of minimal conductor}{ellminimaltwist$(E)$} \li{$[k]P$ with good reduction}{ellnonsingularmultiple$(E,P)$} \li{$E$ supersingular at $p$?}{ellissupersingular$(E, p)$} \li{affine points of na\"\i ve height $\leq h$}{ellratpoints$(E, h)$} \subsec{Complex heights} \li{canonical height of $P$}{ellheight$(E,P)$} \li{canonical bilinear form taken at $P$, $Q$}{ellheight$(E,P,Q)$} \li{height regulator matrix for pts in $L$}{ellheightmatrix$(E,L)$} \subsec{$p$-adic heights} \li{cyclotomic $p$-adic height of $P\in E(\QQ)$}{ellpadicheight$(E,p,n,P)$} \li{\dots bilinear form at $P,Q\in E(\QQ)$}{ellpadicheight$(E,p,n,P,Q)$} \li{\dots matrix at vector for pts in $L$}{ellpadicheightmatrix$(E,p,n,L)$} \li{\dots regulator for canonical height}{ellpadicregulator$(E,p,n, Q)$} \li{Frobenius on $\QQ_p \otimes H^1_{dR}(E/\QQ)$}{ellpadicfrobenius$(E,p,n)$} \li{slope of unit eigenvector of Frobenius}{ellpadics2$(E,p,n)$} \subsec{Isogenous curves} \li{matrix of isogeny degrees for $\QQ$-isog. curves}{ellisomat$(E)$} \li{tree of prime degree isogenies}{ellisotree$(E)$} \li{a modular equation of prime degree $N$}{ellmodulareqn$(N)$} \subsec{$L$-function} \li{$p$-th coeff $a_p$ of $L$-function, $p$ prime}{ellap$(E,p)$} \li{$k$-th coeff $a_k$ of $L$-function}{ellak$(E,k)$} \li{$L(E,s)$ (using less memory than \kbd{lfun})}{elllseries$(E,s)$} \li{$L^{(r)}(E,1)$ (using less memory than \kbd{lfun})}{ellL1$(E,r)$} % \li{a Heegner point on $E$ of rank $1$}{ellheegner$(E)$} \li{order of vanishing at $1$}{ellanalyticrank$(E,\{\var{eps}\})$} \li{root number for $L(E,.)$ at $p$}{ellrootno$(E,\{p\})$} \li{modular parametrization of $E$}{elltaniyama$(E)$} \li{degree of modular parametrization}{ellmoddegree$(E)$} \li{compare with $H^1(X_0(N),\ZZ)$ (for $E'\to E$)} {ellweilcurve$(E)$} \li{Manin constant of $E$}{ellmaninconstant$(E)$} \li{$p$-adic $L$ function $L_p^{(r)}(E,d,\chi^s)$} {ellpadicL$(E,p,n,\{s\},\{r\},\{d\})$} \li{BSD conjecture for $L_p^{(r)}(E_D,\chi^0)$} {ellpadicbsd$(E,p,n,\{D=1\})$} \li{Iwasawa invariants for $L_p(E_D,\tau^i)$} {ellpadiclambdamu$(E,p,D,i)$} \subsec{Rational points} \li{attempt to compute $E(\Q)$}{ellrank$(E,\{\text{effort}\}, \{\text{points}\})$} \li{initialize for later \kbd{ellrank} calls, }{ellrankinit$(E)$} \li{saturate $\langle P_1,\dots,P_n\rangle$ wrt. primes $\leq B$} {ellsaturation$(E,P,B)$} \li{$2$-covers of the curve $E$}{ell2cover$(E)$} \subsec{Elldata package, Cremona's database:} \li{db code \kbd{"11a1"} $\leftrightarrow$ $[\var{conductor}, \var{class}, \var{index}]$}{ellconvertname$(s)$} \li{generators of Mordell-Weil group}{ellgenerators$(E)$} \li{look up $E$ in database}{ellidentify$(E)$} \newcolumn \li{all curves matching criterion}{ellsearch$(N)$} \li{loop over curves with cond.~from $a$ to $b$}{forell$(E, a,b,\seq)$} \section{Curves over number field $K$} \li{coeff $a_{\goth{p}}$ of $L$-function}{ellap$(E,\goth{p})$} \li{Kodaira type of $\goth{p}$-fiber of $E$}{elllocalred$(E,\goth{p})$} \li{integral model of $E/K$} {ellintegralmodel$(E,\{$\&$v\})$} \li{minimal model of $E/K$} {ellminimalmodel$(E,\{$\&$v\})$} \li{minimal discriminant of $E/K$}{ellminimaldisc$(E)$} \li{cond, min mod, Tamagawa num \kbd{[}$N,v,c$\kbd{]}}{ellglobalred$(E)$} \li{global Tamagawa number}{elltamagawa$(E)$} \li{test if $E$ has CM}{elliscm$(E)$} \li{$P\in E(K)$ $n$-divisible? $[n]Q=P$}{ellisdivisible$(E,P,n,\{\&Q\})$} \subsec{$L$-function} A domain $D = [c,w,h]$ in initialization mean we restrict $s\in \CC$ to domain $|\Re(s)-c| < w$, $|\Im(s)| < h$; $D = [w,h]$ encodes $[1/2,w,h]$ and $[h]$ encodes $D = [1/2,0,h]$ (critical line up to height $h$).\hfil\break \li{vector of first $n$ $a_k$'s in $L$-function}{ellan$(E,n)$} \li{init $L^{(k)}(E,s)$ for $k \leq n$}{L = lfuninit$(E, D, \{n = 0\})$} \li{compute $L(E,s)$ ($n$-th derivative)}{lfun$(L, s, \{n=0\})$} \li{$L(E,1,r)/(r! \cdot R\cdot \#Sha)$ assuming BSD}{ellbsd$(E)$} \section{Other curves of small genus} A hyperelliptic curve $C$ is given by a pair $[P,Q]$ ($y^2+Qy = P$ with $Q^2+4P$ squarefree) or a single squarefree polynomial $P$ ($y^2 = P$).\hfil\break \li{check if $[x,y]$ is on $C$}{hyperellisoncurve$(C, [x,y])$} \li{$y$-coordinates of point(s) for $x$}{hyperellordinate$(C,x)$} \li{discriminant of $C$}{hyperelldisc$(C)$} \li{Cremona-Stoll reduction}{hyperellred$(C)$} \li{apply $m = [e, [a,b;c,d], H]$ to model}{hyperellchangecurve$(C,m)$} \li{minimal discriminant of integral $C$}{hyperellminimaldisc$(C)$} \li{minimal model of integral $C$}{hyperellminimalmodel$(C)$} \li{reduction of $y^2+Qy = P$ (genus $2$)}{genus2red$(C,\{p\})$} \li{Igusa invariants for $C$ of genus $2$}{genus2igusa$(C)$} \li{affine rational points of height $\leq h$}{hyperellratpoints$(C, h)$} \li{find a rational point on a conic, $^t x G x = 0$}{qfsolve$(G)$} \li{$[H,U]$ such that $H = c{}^tU GU$ has minimat det}{qfminimize$(G)$} \li{quadratic Hilbert symbol (at $p$)}{hilbert$(x,y,\{p\})$} \li{all solutions in $\QQ^3$ of ternary form}{qfparam$(G,x)$} \li{$P,Q\in\FF_q[X]$; char. poly. of Frobenius}{hyperellcharpoly$(Q)$} \li{matrix of Frobenius on $\QQ_p\otimes H^1_{dR}$}{hyperellpadicfrobenius} \medskip \section{Elliptic \& Modular Functions} $w = [\omega_1,\omega_2]$ or \var{ell} struct (\kbd{E.omega}), $\tau=\omega_1/\omega_2$.\hfill\break % \li{arithmetic-geometric mean}{agm$(x,y)$} \li{elliptic $j$-function $1/q+744+\cdots$}{ellj$(x)$} \li{Weierstrass $\sigma$/$\wp$/$\zeta$ function} {ellsigma$(w,z)${\rm, }ellwp{\rm, }ellzeta} \li{periods/quasi-periods}{ellperiods$(E,\{\fl\})${\rm, }elleta$(w)$} \li{$(2i\pi/\omega_2)^k E_k(\tau)$}{elleisnum$(w,k,\{\fl\})$} \li{modified Dedekind $\eta$ func. $\prod(1-q^n)$}{eta$(x,\{\fl\})$} \li{Dedekind sum $s(h,k)$}{sumdedekind$(h,k)$} \li{Jacobi sine theta function}{theta$(q,z)$} \li{k-th derivative at z=0 of \kbd{theta}$(q,z)$}{thetanullk$(q,k)$} \li{Weber's $f$ functions}{weber$(x,\{\fl\})$} \li{modular pol.~of level $N$}{polmodular$(N,\{\var{inv = j}\})$} \li{Hilbert class polynomial for $\QQ(\sqrt{D})$} {polclass$(D,\{\var{inv = j}\})$} % \vfill \copyrightnotice \bye pari-2.17.2/doc/tex2mail.10000644000175000017500000000372714676526175013574 0ustar billbill.TH TEX2MAIL 1 "25 September 2013" .SH NAME tex2mail \- TeX to ascii math prettyprinter .SH SYNOPSIS .BR tex2mail [-linelength= .IR length ] [-maxdef= .IR number ] [-debug= .IR number ] [-by_par= .IR number ] [-TeX] [-ragged] [-noindent] .SH DESCRIPTION Filter converting TeX or LaTeX math formulae to ASCII art. tex2mail is used by the PARI-GP calculator for output method .I external prettyprint . Under gp, prettyprint mode can be set by .B default(output, 3) (or \\o3). By default, this switches gp main output to TeX format, filtered by .RS tex2mail \-TeX \-noindent \-ragged \-by_par .RE Flags passed to tex2mail can be modified via the .IR prettyprinter default in gp. .SH OPTIONS The following command line options are available: .TP .BI \-linelength=length Wrap text at this column. .TP .BI \-maxdef=number definition loops: croak if more than maxdef substitutions in a given paragraph. .TP .BI \-debug=debuglevel output debugging messages. .TP .BI \-by_par Expect each paragraph to be terminated by *exactly* 2 "\\n", and do not print an extra "\\n" between paragraphs. .TP .BI \-TeX Assume input formulae are in plain TeX format. .TP .BI \-ragged leave right ragged. .TP .BI \-noindent assume \\noindent everywhere. .SH BUGS % at the end of a line followed by \\n\\n is recognized as end of paragraph .SH AUTHOR Ilya Zakharevitch .SH SEE ALSO .IR gp (1), .IR tex (1), .SH COPYING This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. pari-2.17.2/doc/usersch7.tex0000644000175000017500000011752014723642370014234 0ustar billbill% Copyright (c) 2000 The PARI Group % % This file is part of the PARI/GP documentation % % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License \chapter{Elliptic curves and arithmetic geometry} This chapter is quite short, but is added as a placeholder, since we expect the library to expand in that direction. \section{Elliptic curves} Elliptic curves are represented in the Weierstrass model $$ (E): y^2z + a_1xyz + a_3 yz = x^3 + a_2 x^2z + a_4 xz^2 + a_6z^3, $$ by the $5$-tuple $[a_1,a_2,a_3,a_4,a_6]$. Points in the projective plane are represented as follows: the point at infinity $(0:1:0)$ is coded as \kbd{[0]}, a finite point $(x:y:1)$ outside the projective line at infinity $z = 0$ is coded as $[x,y]$. Note that other points at infinity than $(0:1:0)$ cannot be represented; this is harmless, since they do not belong to any of the elliptic curves $E$ above. \emph{Points on the curve} are just projective points as described above, they are not tied to a curve in any way: the same point may be used in conjunction with different curves, provided it satisfies their equations (if it does not, the result is usually undefined). In particular, the point at infinity belongs to all elliptic curves. As with \tet{factor} for polynomial factorization, the $5$-tuple $[a_1,a_2,a_3,a_4,a_6]$ implicitly defines a base ring over which the curve is defined. Point coordinates must be operation-compatible with this base ring (\kbd{gadd}, \kbd{gmul}, \kbd{gdiv} involving them should not give errors). \subsec{Types of elliptic curves} We call a $5$-tuble as above an \kbd{ell5}; most functions require an \kbd{ell} structure, as returned by \tet{ellinit}, which contains additional data (usually dynamically computed as needed), depending on the base field. \fun{GEN}{ellinit}{GEN E, GEN D, long prec}, returns an \tet{ell} structure, attached to the elliptic curve $E$ : either an \kbd{ell5}, a pair $[a_4,a_6]$ or a \typ{STR} in Cremona's notation, e.g. \kbd{"11a1"}. The optional $D$ (\kbd{NULL} to omit) describes the domain over which the curve is defined. \subsec{Type checking} \fun{void}{checkell}{GEN e} raise an error unless $e$ is an \var{ell}. \fun{int}{checkell_i}{GEN e} return $1$ if $e$ is an \var{ell} and $0$ otherwise. \fun{void}{checkell5}{GEN e} raise an error unless $e$ is an \var{ell} or an \var{ell5}. \fun{void}{checkellpt}{GEN z} raise an error unless $z$ is a point (either finite or at infinity). \fun{int}{checkellpt_i}{GEN z} return $1$ if $z$ is a point (either finite or at infinity) and $0$ otherwise. \fun{long}{ell_get_type}{GEN e} returns the domain type over which the curve is defined, one of \tet{t_ELL_Q} the field of rational numbers; \tet{t_ELL_NF} a number field; \tet{t_ELL_Qp} the field of $p$-adic numbers, for some prime $p$; \tet{t_ELL_Fp} a prime finite field, base field elements are represented as \kbd{Fp}, i.e.~a \typ{INT} reduced modulo~$p$; \tet{t_ELL_Fq} a nonprime finite field (a prime finite field can also be represented by this subtype, but this is inefficient), base field elements are represented as \typ{FFELT}; \tet{t_ELL_Rg} none of the above. \fun{void}{checkell_Fq}{GEN e} checks whether $e$ is an \kbd{ell}, defined over a finite field (either prime or nonprime). Otherwise the function raises a \tet{pari_err_TYPE} exception. \fun{void}{checkell_Q}{GEN e} checks whether $e$ is an \kbd{ell}, defined over $\Q$. Otherwise the function raises a \tet{pari_err_TYPE} exception. \fun{void}{checkell_Qp}{GEN e} checks whether $e$ is an \kbd{ell}, defined over some $\Q_p$. Otherwise the function raises a \tet{pari_err_TYPE} exception. \fun{void}{checkellisog}{GEN v} raise an error unless $v$ is an isogeny, from \tet{ellisogeny}. \subsec{Extracting info from an \kbd{ell} structure} These functions expect an \kbd{ell} argument. If the required data is not part of the structure, it is computed then inserted, and the new value is returned. \subsubsec{All domains} \fun{GEN}{ell_get_a1}{GEN e} \fun{GEN}{ell_get_a2}{GEN e} \fun{GEN}{ell_get_a3}{GEN e} \fun{GEN}{ell_get_a4}{GEN e} \fun{GEN}{ell_get_a6}{GEN e} \fun{GEN}{ell_get_b2}{GEN e} \fun{GEN}{ell_get_b4}{GEN e} \fun{GEN}{ell_get_b6}{GEN e} \fun{GEN}{ell_get_b8}{GEN e} \fun{GEN}{ell_get_c4}{GEN e} \fun{GEN}{ell_get_c6}{GEN e} \fun{GEN}{ell_get_disc}{GEN e} \fun{GEN}{ell_get_j}{GEN e} \subsubsec{Curves over $\Q$} \fun{GEN}{ellQ_get_N}{GEN e} returns the curve conductor \fun{void}{ellQ_get_Nfa}{GEN e, GEN *N, GEN *faN} sets $N$ to the conductor and \kbd{faN} to its factorization \fun{int}{ell_is_integral}{GEN e} return $1$ if $e$ is given by an integral model, and $0$ otherwise. \fun{long}{ellQ_get_CM}{GEN e} if $e$ has CM by a principal imaginary quadratic order, return its discriminant. Else return $0$. \fun{long}{ellap_CM_fast}{GEN e, ulong p, long CM} assuming that $p$ does not divide the discriminant of $E$ (in particular, $E$ has good reduction at $p$), and that \kbd{CM} is as given by \tet{ellQ_get_CM}, return the trace of Frobenius for $E/\F_p$. This is meant to quickly compute lots of $a_p$, esp.~when $e$ has CM by a principal quadratic order. \fun{long}{ellrootno_global}{GEN e} returns the global root number $c\in \{-1,1\}$. \fun{GEN}{ellheightoo}{GEN E, GEN P, long prec} given $P = [x,y]$ an affine point on $E$, return $$ \lambda_\infty(P) + \dfrac{1}{12}\log|\disc E| = \dfrac{1}{2} \text{real}(z\eta(z)) - \log |\sigma(E,z)| \in \R, $$ where $\lambda_\infty(P)$ is the canonical local height at infinity and $z$ is \kbd{ellpointtoz}$(E,P)$. This is computed using Mestre's (quadratically convergent) AGM algorithm. \fun{long}{ellorder_Q}{GEN E, GEN P} return the order of $P\in E(\Q)$, using the impossible value $0$ for a point of infinite order. Ultimately called by the generic \tet{ellorder} function. \fun{GEN}{point_to_a4a6}{GEN E, GEN P, GEN p, GEN *a4} given $E/\Q$, $p\neq 2,3$ not dividing the discriminant of $E$ and $P\in E(\Q)$ outside the kernel of reduction, return the image of $P$ on the short Weierstrass model $y^2 = x^3 + a_4x + a_6$ isomorphic to the reduction $E_p$ of $E$ at $p$. Also set \kbd{a4} to the $a_4$ coefficient in the above model. This function allows quick computations modulo varying primes $p$, avoiding the overhead of \kbd{ellinit}$(E,p)$, followed by a change of coordinates. It produces data suitable for \kbd{FpE} routines. \fun{GEN}{point_to_a4a6_Fl}{GEN E, GEN P, ulong p, ulong *pa4} as \tet{point_to_a4a6}, returning a \kbd{Fle}. \fun{GEN}{elldatagenerators}{GEN E} returns generators for $E(\Q)$ extracted from Cremona's table. \fun{GEN}{ellanal_globalred}{GEN e, GEN *v} takes an \var{ell} over $\Q$ and returns a global minimal model $E$ (in \kbd{ellinit} form, over $\Q$) for $e$ suitable for analytic computations related to the curve $L$ series: it contains \kbd{ellglobalred} data, as well as global and local root numbers. If \kbd{v} is not \kbd{NULL}, set \kbd{*v} to the needed change of variable: \kbd{NULL} if $e$ was already the standard minimal model, such that $E = \kbd{ellchangecurve(e,v)}$ otherwise. Compared to the direct use of \kbd{ellchangecurve} followed by \kbd{ellrootno}, this function avoids converting unneeded dynamic data and avoids potential memory leaks (the changed curve would have had to be deleted using \tet{obj_free}). The original curve $e$ is updated as well with the same information. \fun{GEN}{ellanal_globalred_all}{GEN e, GEN *v, GEN *N, GEN *tam} as \tet{ellanal_globalred}; further set \kbd{*N} to the curve conductor and \kbd{*tam} to the product of the local Tamagawa numbers, including the factor at infinity (multiply by the number of connected components of $e(\R)$). \fun{GEN}{ellintegralmodel}{GEN e, GEN *pv} return an integral model for $e$ (in \kbd{ellinit} form, over $\Q$). Set $v = \kbd{NULL}$ (already integral, we returned $e$ itself), else to the variable change $[u,0,0,0]$ making $e$ integral. We have $u = 1/t$, $t > 1$. \fun{GEN}{ellintegralmodel_i}{GEN e, GEN *pv} shallow version of \kbd{ellintegralmodel}. \fun{GEN}{ellQtwist_bsdperiod}{GEN E, long s} let $E$ be a rational elliptic curve given by a minimal model, $\Lambda_E$ its period lattice, and $s\in\{-1,1\}$. Let $\Omega_E^\pm$ be the canonical periods in $\sqrt{\pm 1}\R^+$ generating $\Lambda_E \cap \sqrt{\pm 1} \R$. Return $\Omega_E^+$ if $s = 1$ and $\Omega_E^-$ if $s = -1$. \fun{GEN}{elltors_psylow}{GEN e, ulong p} as \kbd{elltors}, but return the $p$-Sylow subgroup of the torsion group. \fun{GEN}{elleulerf}{GEN E, GEN p} returns the Euler factor at $p$ of the $L$-function associated to the curve $E$ defined over a number field. \misctitle{Deprecated routines} \fun{GEN}{elltors0}{GEN e, long flag} this function is deprecated; use \tet{elltors} \subsubsec{Curves over a number field \var{nf}} Let $K$ be the number field over which $E$ is defined, given by a \var{nf} or \var{bnf} structure. \fun{GEN}{ellnf_get_nf}{GEN E} returns the underlying \kbd{nf}. \fun{GEN}{ellnf_get_bnf}{GEN x} returns \kbd{NULL} if $K$ does not contain a \var{bnf} structure, else return the \var{bnf}. \fun{GEN}{ellnf_vecarea}{GEN E} returns the vector of the period lattices areas of all the complex embeddings of \kbd{E} in the same order as \kbd{E.nf.roots}. \fun{GEN}{ellnf_veceta}{GEN E} returns the vector of the quasi-periods of all the complex embeddings of \kbd{E} in the same order as \kbd{E.nf.roots}. \fun{GEN}{ellnf_vecomega}{GEN E} returns the vector of the periods of all the complex embeddings of \kbd{E} in the same order as \kbd{E.nf.roots}. \subsubsec{Curves over $\Q_p$} \fun{GEN}{ellQp_get_p}{GEN E} returns $p$ \fun{long}{ellQp_get_prec}{GEN E} returns the default $p$-adic accuracy to which we must compute approximate results attached to $E$. \fun{GEN}{ellQp_get_zero}{GEN x} returns $O(p^n)$, where $n$ is the default $p$-adic accuracy as above. The following functions are only defined when $E$ has multiplicative reduction (Tate curves): \fun{GEN}{ellQp_Tate_uniformization}{GEN E, long prec} returns a \typ{VEC} containing $u^2, u, q, [a,b]$, at $p$-adic precision \kbd{prec}. \fun{GEN}{ellQp_u}{GEN E, long prec} returns $u$. \fun{GEN}{ellQp_u2}{GEN E, long prec} returns $u^2$. \fun{GEN}{ellQp_q}{GEN E, long prec} returns the Tate period $q$. \fun{GEN}{ellQp_ab}{GEN E, long prec} returns $[a,b]$. \fun{GEN}{ellQp_AGM}{GEN E, long prec} returns $[a,b,R,v]$, where $v$ is an integer, $a, b, R$ are vectors describing the sequence of $2$-isogenous curves $E_i: y^2 = x(x+A_i)(x+A_i-B_i)$, $i \geq 1$ converging to the singular curve $E_\infty: y^2 = x^2(x+M)$. We have $a[i] = A[i] p^v$, $b[i] = B[i] p^v$, $R[i] = A_i - B_i$. These are used in \kbd{ellpointtoz} and \kbd{ellztopoint}. \fun{GEN}{ellQp_L}{GEN E, long prec} returns the ${\cal L}$-invariant $L$. \fun{GEN}{ellQp_root}{GEN E, long prec} returns $e_1$. \subsubsec{Curves over a finite field $\F_q$} \fun{GEN}{ellff_get_p}{GEN E} returns the characteristic \fun{GEN}{ellff_get_field}{GEN E} returns $p$ if $\F_q$ is a prime field, and a \typ{FFELT} belonging to $\F_q$ otherwise. \fun{GEN}{ellff_get_card}{GEN E} returns $\#E(\F_q)$ \fun{GEN}{ellff_get_gens}{GEN E} returns a minimal set of generators for $E(\F_q)$. \fun{GEN}{ellff_get_group}{GEN E} returns \kbd{ellgroup}$(E)$. \fun{GEN}{ellff_get_m}{GEN E} returns the \typ{INT} $m$ as needed by the \kbd{gen\_ellgroup} function (the order of the pairing required to verify a generating set). \fun{GEN}{ellff_get_o}{GEN E} returns $[d, \kbd{factor{d}}]$, where $d$ is the exponent of $E(\F_q)$. \fun{GEN}{ellff_get_D}{GEN E} returns the elementary divisors for $E(\F_q)$ in a form suitable for \tet{gen_ellgens}: either $[d_1]$ or $[d_1,d_2]$, where $d_1$ is in \tet{elff_get_o} format. $[d, \kbd{factor{d}}]$, where $d$ is the exponent of $E(\F_q)$. \fun{GEN}{ellff_get_a4a6}{GEN E} returns a canonical ``short model'' for $E$, and the corresponding change of variable $[u,r,s,t]$. For $p\neq 2,3$, this is $[A_4,A_6,[u,r,s,t]]$, corresponding to $y^2 = x^3 + A_4x + A_6$, where $A_4 = -27c_4$, $A_6 = -54c_6$, $[u,r,s,t] = [6, 3b_2,3a_1,108a_3]$. \item If $p = 3$ and the curve is ordinary ($b_2\neq 0$), this is $[[b_2], A_6, [1,v,-a_1,-a_3]]$, corresponding to $$y^2 = x^3 + b_2 x^2 + A_6,$$ where $v = b_4/b_2$, $A_6 = b_6 - v(b_4+v^2)$. \item If $p = 3$ and the curve is supersingular ($b_2 = 0$), this is $[-b_4, b_6, [1,0,-a_1,-a_3]]$, corresponding to $$y^2 = x^3 + 2b_4 x + b_6.$$ \item If $p = 2$ and the curve is ordinary ($a_1 \neq 0$), return $[A_2,A_6,[a_1^{-1}, da_1^{-2}, 0, (a_4+d^2)a_1^{-1}]]$, corresponding to $$ y^2 + xy = x^3 + A_2 x^2 + A_6,$$ where $d = a_3/a_1$, $a_1^2 A_2 = (a_2 + d)$ and $$ a_1^6 A_6 = d^3 + a_2 d^2 + a_4 d + a_6 + (a_4^2 + d^4)a_1^{-2}.$$ \item If $p = 2$ and the curve is supersingular ($a_1 = 0$, $a_3\neq 0$), return $[[a_3, A_4, 1/a_3], A_6, [1,a_2,0,0]]$, corresponding to $$ y^2 + a_3 y = x^3 + A_4 x + A_6,$$ where $A_4 = a_2^2 + a_4$, $ A_6 = a_2a_4 + a_6$. The value $1/a_3$ is included in the vector since it is frequently needed in computations. \subsubsec{Curves over $\C$} (This includes curves over $\Q$!) \fun{long}{ellR_get_prec}{GEN E} return the default accuracy to which we must compute approximate results attached to $E$. \fun{GEN}{ellR_ab}{GEN E, long prec} return $[a,b]$ \fun{GEN}{ellR_omega}{GEN x, long prec} return periods $[\omega_1,\omega_2]$. \fun{GEN}{ellR_eta}{GEN E, long prec} return quasi-periods $[\eta_1,\eta_2]$. \fun{GEN}{ellR_area}{GEN x, long prec} return the area $(\Im(\omega_1\*\overline{\omega_2}))$. \fun{GEN}{ellR_roots}{GEN E, long prec} return $[e_1,e_2,e_3]$. If $E$ is defined over $\R$, then $e_1$ is real. If furthermore $\disc E > 0$, then $e_1 > e_2 > e_3$. \fun{long}{ellR_get_sign}{GEN E} if $E$ is defined over $\R$ returns the signe of its discriminant, otherwise return $0$. \subsec{Points} \fun{int}{ell_is_inf}{GEN z} tests whether the point $z$ is the point at infinity. \fun{GEN}{ellinf}{} returns the point at infinity \kbd{[0]}. \subsec{Change of variables} \fun{GEN}{ellchangeinvert}{GEN w} given a change of variables $w = [u,r,s,t]$, returns the inverse change of variables $w'$, such that if $E' = \kbd{ellchangecurve(E, w)}$, then $E = \kbd{ellchangecurve}(E, w')$. \subsec{Generic helper functions} The naming scheme assumes an affine equation $F(x,y) = f(x) - (y^2 + h(x)y) = 0$ in standard Weierstrass form: $f = x^3+a_2x^2+a_4x+a_6$, $h = a_1x + a_3$. Unless mentionned otherwise, these routine assume that all arguments are compatible with generic functions of \kbd{gadd} or \kbd{gmul} type. In particular they do not handle elements in number field in \kbd{nfalgtobasis} format. \fun{GEN}{ellbasechar}{GEN E} returns the characteristic of the base ring over which $E$ is defined. \fun{GEN}{ec_bmodel}{GEN E, long v} returns the polynomial $4x^3 + b_2x^2 + 2b_4x + b_6$ in the variable \kbd{v}. \fun{GEN}{ec_phi2}{GEN E, long v} returns the polynomial $x^4 - b_4x^2 - 2b_6\*X - b_8$ in the variable \kbd{v}. \fun{GEN}{ec_f_evalx}{GEN E, GEN x} returns $f(x)$. \fun{GEN}{ec_h_evalx}{GEN E, GEN x} returns $h(x)$. \fun{GEN}{ec_dFdx_evalQ}{GEN E, GEN Q} returns $3x^2 + 2a_2x + a_4 -a_1y$, where $Q = [x,y]$. \fun{GEN}{ec_dFdy_evalQ}{GEN E, GEN Q} returns $-(2y + a_1 x + a_3)$, where $Q = [x,y]$. \fun{GEN}{ec_dmFdy_evalQ}{GEN e, GEN Q} returns $2y + a_1 x + a_3$, where $Q = [x,y]$. \fun{GEN}{ec_2divpol_evalx}{GEN E, GEN x} returns $4x^3 + b_2\*x^2 + 2\*b_4x + b_6$. This function supports inputs in \kbd{nfalgtobasis} format. \fun{GEN}{ec_half_deriv_2divpol}{GEN E, long v} returns $6\*x^2 + b_2\*x + b_4$ as a \typ{POL} in the variable \kbd{v}. \fun{GEN}{ec_half_deriv_2divpol_evalx}{GEN E, GEN x} returns $6\*x^2 + b_2\*x + b_4$. \fun{GEN}{ec_3divpol_evalx}{GEN E, GEN x} returns $3\*x^4 + b_2\*x^2 + 3\*b_4\*x^2 + 3\*b_6\*x + b_8$. \subsec{Functions to handle elliptic curves over finite fields} \subsubsec{Tolerant routines} \fun{GEN}{ellap}{GEN E, GEN p} given a prime number $p$ and an elliptic curve defined over $\Q$ or $\Q_p$ (assumed integral and minimal at $p$), computes the trace of Frobenius $a_p = p+1 - \#E(\F_p)$. If $E$ is defined over a nonprime finite field $\F_q$, ignore $p$ and return $q+1 - \#E(\F_q)$. When $p$ is implied ($E$ defined over $\Q_p$ or a finite field), $p$ can be omitted (set to \kbd{NULL}). \subsubsec{Curves defined a nonprime finite field} In this subsection, we assume that \tet{ell_get_type}$(E)$ is \tet{t_ELL_Fq}. (As noted above, a curve defined over $\Z/p\Z$ can be represented as a \tet{t_ELL_Fq}.) \fun{GEN}{FF_elltwist}{GEN E} returns the coefficients $[a_1,a_2,a_3,a_4,a_6]$ of the quadratic twist of $E$. \fun{GEN}{FF_ellmul}{GEN E, GEN P, GEN n} returns $[n]P$ where $n$ is an integer and $P$ is a point on the curve $E$. \fun{GEN}{FF_ellrandom}{GEN E} returns a random point in $E(\F_q)$. This function never returns the point at infinity, unless this is the only point on the curve. \fun{GEN}{FF_ellorder}{GEN E, GEN P, GEN o} returns the order of the point $P$, where $o$ is a multiple of the order of $P$, or its factorization. \fun{GEN}{FF_ellcard}{GEN E} returns $\#E(\F_q)$. \fun{GEN}{FF_ellcard_SEA}{GEN E, long s} This function returns $\#E(\F_q)$, using the Schoof-Elkies-Atkin algorithm. Assume $p\neq 2,3$. The parameter $s$ has the same meaning as in \kbd{Fp\_ellcard\_SEA}. \fun{GEN}{FF_ellgens}{GEN E} returns the generators of the group $E(\F_q)$. \fun{GEN}{FF_elllog}{GEN E, GEN P, GEN G, GEN o} Let \kbd{G} be a point of order \kbd{o}, return $e$ such that $[e]P=G$. If $e$ does not exists, the result is undefined. \fun{GEN}{FF_ellgroup}{GEN E, GEN *pm} returns the structure of the Abelian group $E(\F_q)$ and set \kbd{*pm} to $m$ (see \kbd{gen\_ellgens}). \fun{GEN}{FF_ellweilpairing}{GEN E, GEN P, GEN Q, GEN m} returns the Weil pairing of the points of $m$-torsion $P$ and $Q$. \fun{GEN}{FF_elltatepairing}{GEN E, GEN P, GEN Q, GEN m} returns the Tate pairing of $P$ and $Q$, where $[m]P = 0$. \section{Arithmetic on elliptic curve over a finite field in simple form} The functions in this section no longer operate on elliptic curve structures, as seen up to now. They are used to implement those higher-level functions without using cached information and thus require suitable explicitly enumerated data. \subsec{Helper functions} \fun{GEN}{elltrace_extension}{GEN t, long n, GEN q} Let $E$ some elliptic curve over $\F_q$ such that the trace of the Frobenius is $t$, returns the trace of the Frobenius over $\F_q^n$. \subsec{Elliptic curves over $\F_p$, $p>3$} Let $p$ a prime number and $E$ the elliptic curve given by the equation $E:y^2=x^3+a_4\*x+a_6$, with $a_4$ and $a_6$ in $\F_p$. A \kbd{FpE} is a point of $E(\F_p)$. Since an affine point and $a_4$ determine an unique $a6$, most functions do not take $a_6$ as an argument. A \kbd{FpE} is either the point at infinity (\kbd{ellinf()}) or a $FpV$ whith two components. The parameters $a_4$ and $a_6$ are given as \typ{INT}s when required. \fun{GEN}{Fp_ellj}{GEN a4, GEN a6, GEN p} returns the $j$-invariant of the curve $E$. \fun{void}{Fp_ellj_to_a4a6}{GEN j, GEN p, GEN *pa4, GEN *pa6} sets \kbd{*pa4} to $a_4$ and \kbd{*pa6} to $a_6$ where $a_4$ and $a_6$ define a fixed elliptic curve with $j$-invariant $j$. \fun{int}{Fp_elljissupersingular}{GEN j, GEN p} returns $1$ if $j$ is the $j$-invariant of a supersingular curve over $\F_p$, $0$ otherwise. \fun{GEN}{Fp_ellcard}{GEN a4, GEN a6, GEN p} returns the cardinality of the group $E(\F_p)$. \fun{GEN}{Fp_ellcard_SEA}{GEN a4, GEN a6, GEN p, long s} This function returns $\#E(\F_p)$, using the Schoof-Elkies-Atkin algorithm. If the \kbd{seadata} package is installed, the function will be faster. The extra flag \kbd{s}, if set to a nonzero value, causes the computation to return \kbd{gen\_0} (an impossible cardinality) if one of the small primes $\ell$ divides the curve order but does not divide $s$. For cryptographic applications, where one is usually interested in curves of prime order, setting $s=1$ efficiently weeds out most uninteresting curves; if curves of order a power of $2$ times a prime are acceptable, set $s=2$. If moreover \kbd{s} is negative, similar checks are performed for the twist of the curve. \fun{GEN}{Fp_ffellcard}{GEN a4, GEN a6, GEN q, long n, GEN p} returns the cardinality of the group $E(\F_q)$ where $q=p^n$. \fun{GEN}{Fp_ellgroup}{GEN a4, GEN a6, GEN N, GEN p, GEN *pm} returns the group structure $D$ of the group $E(\F_p)$, which is assumed to be of order $N$ and set \kbd{*pm} to $m$. \fun{GEN}{Fp_ellgens}{GEN a4, GEN a6, GEN ch, GEN D, GEN m, GEN p} returns generators of the group $E(\F_p)$ with the base change \kbd{ch} (see \kbd{FpE\_changepoint}), where $D$ and $m$ are as returned by \kbd{Fp\_ellgroup}. \fun{GEN}{Fp_elldivpol}{GEN a4, GEN a6, long n, GEN p} returns the $n$-division polynomial of the elliptic curve $E$. \fun{void}{Fp_elltwist}{GEN a4, GEN a6, GEN p, GEN *pA4, GEN *pA6} sets \kbd{*pA4} and \kbd{*pA6} to the corresponding parameters for the quadratic twist of $E$. Assume $p$ is an odd prime. \subsec{\kbd{FpE}} \fun{GEN}{FpE_add}{GEN P, GEN Q, GEN a4, GEN p} returns the sum $P+Q$ in the group $E(\F_p)$, where $E$ is defined by $E:y^2=x^3+a_4\*x+a_6$, for any value of $a_6$ compatible with the points given. \fun{GEN}{FpE_sub}{GEN P, GEN Q, GEN a4, GEN p} returns $P-Q$. \fun{GEN}{FpE_dbl}{GEN P, GEN a4, GEN p} returns $2.P$. \fun{GEN}{FpE_neg}{GEN P, GEN p} returns $-P$. \fun{GEN}{FpE_mul}{GEN P, GEN n, GEN a4, GEN p} return $n.P$. \fun{GEN}{FpE_changepoint}{GEN P, GEN m, GEN a4, GEN p} returns the image $Q$ of the point $P$ on the curve $E:y^2=x^3+a_4\*x+a_6$ by the coordinate change $m$ (which is a \kbd{FpV}). \fun{GEN}{FpE_changepointinv}{GEN P, GEN m, GEN a4, GEN p} returns the image $Q$ on the curve $E:y^2=x^3+a_4\*x+a_6$ of the point $P$ by the inverse of the coordinate change $m$ (which is a \kbd{FpV}). \fun{GEN}{random_FpE}{GEN a4, GEN a6, GEN p} returns a random point on $E(\F_p)$, where $E$ is defined by $E:y^2=x^3+a_4\*x+a_6$. \fun{GEN}{FpE_order}{GEN P, GEN o, GEN a4, GEN p} returns the order of $P$ in the group $E(\F_p)$, where $o$ is a multiple of the order of $P$, or its factorization. \fun{GEN}{FpE_log}{GEN P, GEN G, GEN o, GEN a4, GEN p} Let \kbd{G} be a point of order \kbd{o}, return $e$ such that $e.P=G$. If $e$ does not exists, the result is currently undefined. \fun{GEN}{FpE_tatepairing}{GEN P, GEN Q, GEN m, GEN a4, GEN p} returns the Tate pairing of the point of $m$-torsion $P$ and the point $Q$. \fun{GEN}{FpE_weilpairing}{GEN P, GEN Q, GEN m, GEN a4, GEN p} returns the Weil pairing of the points of $m$-torsion $P$ and $Q$. \fun{GEN}{FpE_to_mod}{GEN P, GEN p} returns $P$ as a vector of \typ{INTMOD}s. \fun{GEN}{RgE_to_FpE}{GEN P, GEN p} returns the \kbd{FpE} obtained by applying \kbd{Rg\_to\_Fp} coefficientwise. \subsec{\kbd{Fle}} Let $p$ be a prime \kbd{ulong}, and $E$ the elliptic curve given by the equation $E:y^2=x^3+a_4\*x+a_6$, where $a_4$ and $a_6$ are \kbd{ulong}. A \kbd{Fle} is either the point at infinity (\kbd{ellinf()}), or a \kbd{Flv} with two components $[x,y]$. \fun{long}{Fl_elltrace}{ulong a4, ulong a6, ulong p} returns the trace $t$ of the Frobenius of $E(\F_p)$. The cardinality of $E(\F_p)$ is thus $p+1-t$, which might not fit in an \kbd{ulong}. \fun{long}{Fl_elltrace_CM}{long CM, ulong a4, ulong a6, ulong p} as \tet{Fl_elltrace}. If \kbd{CM} is $0$, use the standard algorithm; otherwise assume the curve has CM by a principal imaginary quadratic order of discriminant \kbd{CM} and use a faster algorithm. Useful when the curve is the reduction of $E/\Q$, which has CM by a principal order, and we need the trace of Frobenius for many distinct $p$, see \tet{ellQ_get_CM}. \fun{ulong}{Fl_elldisc}{ulong a4, ulong a6, ulong p} returns the discriminant of the curve $E$. \fun{ulong}{Fl_elldisc_pre}{ulong a4, ulong a6, ulong p, ulong pi} returns the discriminant of the curve $E$, assuming $pi$ is the pseudoinverse of $p$. \fun{ulong}{Fl_ellj}{ulong a4, ulong a6, ulong p} returns the $j$-invariant of the curve $E$. \fun{ulong}{Fl_ellj_pre}{ulong a4, ulong a6, ulong p, ulong pi} returns the $j$-invariant of the curve $E$, assuming $pi$ is the pseudoinverse of $p$. \fun{void}{Fl_ellj_to_a4a6}{ulong j, ulong p, ulong *pa4, ulong *pa6} sets \kbd{*pa4} to $a_4$ and \kbd{*pa6} to $a_6$ where $a_4$ and $a_6$ define a fixed elliptic curve with $j$-invariant $j$. \fun{void}{Fl_elltwist}{ulong a4, ulong a6, ulong p, ulong *pA4, ulong *pA6} set \kbd{*pA4} to $A_4$ and \kbd{*pA6} to $A_6$ where $A_4$ and $A_6$ define the twist of $E$. \fun{void}{Fl_elltwist_disc}{ulong a4, ulong a6, ulong D, ulong p, ulong *pA4, ulong *pA6} sets \kbd{*pA4} to $A_4$ and \kbd{*pA6} to $A_6$ where $A_4$ and $A_6$ define the twist of $E$ by the discriminant $D$. \fun{GEN}{Fl_ellptors}{ulong l, ulong N, ulong a4, ulong a6, ulong p} return a basis of the $l$-torsion subgroup of $E$. \fun{GEN}{Fle_add}{GEN P, GEN Q, ulong a4, ulong p} \fun{GEN}{Fle_dbl}{GEN P, ulong a4, ulong p} \fun{GEN}{Fle_sub}{GEN P, GEN Q, ulong a4, ulong p} \fun{GEN}{Fle_mul}{GEN P, GEN n, ulong a4, ulong p} \fun{GEN}{Fle_mulu}{GEN P, ulong n, ulong a4, ulong p} \fun{GEN}{Fle_order}{GEN P, GEN o, ulong a4, ulong p} \fun{GEN}{Fle_log}{GEN P, GEN G, GEN o, ulong a4, ulong p} \fun{GEN}{Fle_tatepairing}{GEN P, GEN Q, ulong m, ulong a4, ulong p} \fun{GEN}{Fle_weilpairing}{GEN P, GEN Q, ulong m, ulong a4, ulong p} \fun{GEN}{random_Fle}{ulong a4, ulong a6, ulong p} \fun{GEN}{random_Fle_pre}{ulong a4, ulong a6, ulong p, ulong pi} \fun{GEN}{Fle_changepoint}{GEN x, GEN ch, ulong p}, \kbd{ch} is assumed to give the change of coordinates $[u,r,s,t]$ as a \typ{VECSMALL}. \fun{GEN}{Fle_changepointinv}{GEN x, GEN ch, ulong p}, as \tet{Fle_changepoint} \subsec{\kbd{FpJ}} Let $p > 3$ be a prime \typ{INT}, and $E$ the elliptic curve given by the equation $E:y^2=x^3+a_4\*x+a_6$, where $a_4$ and $a_6$ are \typ{INT}. A \kbd{FpJ} is a \kbd{FpV} with three components $[x,y,z]$, representing the affine point $[x/z^2,y/z^3]$ in Jacobian coordinates, the point at infinity being represented by $[1, 1, 0]$. The following must holds: $y^2=x^3+a_4\*x\*z^4+a_6\*z^6$. For all nonzero $u$, the points $[u^2\*x,u^3\*y,u\*z]$ and $[x,y,z]$ are representing the same affine point. \fun{GEN}{FpJ_add}{GEN P, GEN Q, GEN a4, GEN p} \fun{GEN}{FpJ_dbl}{GEN P, GEN a4, GEN p} \fun{GEN}{FpJ_mul}{GEN P, GEN n, GEN a4, GEN p}; \fun{GEN}{FpJ_neg}{GEN P, GEN p} return $-P$. \fun{GEN}{FpJ_to_FpE}{GEN P, GEN p} return the corresponding \kbd{FpE}. \fun{GEN}{FpE_to_FpJ}{GEN P} return the corresponding \kbd{FpJ}. \subsec{\kbd{Flj}} Let $p > 3$ be a prime. Below, \var{pi} is assumed to be the pseudoinverse of $p$ (see \kbd{get\_Fl\_red}). \fun{GEN}{Fle_to_Flj}{GEN P} convert a \kbd{Fle} to an equivalent \kbd{Flj}. \fun{GEN}{Flj_to_Fle}{GEN P, ulong p} convert a \kbd{Flj} to the equivalent \kbd{Fle}. \fun{GEN}{Flj_to_Fle_pre}{GEN P, ulong p, ulong pi} convert a \kbd{Flj} to the equivalent \kbd{Fle}. \fun{GEN}{Flj_add_pre}{GEN P, GEN Q, ulong a4, ulong p, ulong pi} \fun{GEN}{Flj_dbl_pre}{GEN P, ulong a4, ulong p, ulong pi} \fun{GEN}{Flj_neg}{GEN P, ulong p} return $-P$. \fun{GEN}{Flj_mulu_pre}{GEN P, ulong n, ulong a4, ulong p, ulong pi} \fun{GEN}{random_Flj_pre}{ulong a4, ulong a6, ulong p, ulong pi} \fun{GEN}{Flj_changepointinv_pre}{GEN P, GEN ch, ulong p, ulong pi} where \kbd{ch} is the \kbd{Flv} $[u,r,s,t]$. \fun{GEN}{FljV_factorback_pre}{GEN P, GEN L, ulong p, ulong pi} \subsec{Elliptic curves over $\F_{2^n}$} Let $T$ be an irreducible \kbd{F2x} and $E$ the elliptic curve given by either the equation $E:y^2+x*y=x^3+a_2\*x^2+a_6$, where $a_2, a_6$ are \kbd{F2x} in $\F_2[X]/(T)$ (ordinary case) or $E:y^2+a_3*y=x^3+a_4\*x+a_6$, where $a_3, a_4, a_6$ are \kbd{F2x} in $\F_2[X]/(T)$ (supersingular case). A \kbd{F2xqE} is a point of $E(\F_2[X]/(T))$. In the supersingular case, the parameter \kbd{a2} is actually the \typ{VEC} $[a_3,a_4,a_3^{-1}]$. \fun{GEN}{F2xq_ellcard}{GEN a2, GEN a6, GEN T} Return the order of the group $E(\F_2[X]/(T))$. \fun{GEN}{F2xq_ellgroup}{GEN a2, GEN a6, GEN N, GEN T, GEN *pm} Return the group structure $D$ of the group $E(\F_2[X]/(T))$, which is assumed to be of order $N$ and set \kbd{*pm} to $m$. \fun{GEN}{F2xq_ellgens}{GEN a2, GEN a6, GEN ch, GEN D, GEN m, GEN T} Returns generators of the group $E(\F_2[X]/(T))$ with the base change \kbd{ch} (see \kbd{F2xqE\_changepoint}), where $D$ and $m$ are as returned by \kbd{F2xq\_ellgroup}. \fun{void}{F2xq_elltwist}{GEN a4, GEN a6, GEN T, GEN *a4t, GEN *a6t} sets \kbd{*a4t} and \kbd{*a6t} to the parameters of the quadratic twist of $E$. \subsec{\kbd{F2xqE}} \fun{GEN}{F2xqE_changepoint}{GEN P, GEN m, GEN a2, GEN T} returns the image $Q$ of the point $P$ on the curve $E:y^2+x*y=x^3+a_2\*x^2+a_6$ by the coordinate change $m$ (which is a \kbd{F2xqV}). \fun{GEN}{F2xqE_changepointinv}{GEN P, GEN m, GEN a2, GEN T} returns the image $Q$ on the curve $E:y^2=x^3+a_4\*x+a_6$ of the point $P$ by the inverse of the coordinate change $m$ (which is a \kbd{F2xqV}). \fun{GEN}{F2xqE_add}{GEN P, GEN Q, GEN a2, GEN T} \fun{GEN}{F2xqE_sub}{GEN P, GEN Q, GEN a2, GEN T} \fun{GEN}{F2xqE_dbl}{GEN P, GEN a2, GEN T} \fun{GEN}{F2xqE_neg}{GEN P, GEN a2, GEN T} \fun{GEN}{F2xqE_mul}{GEN P, GEN n, GEN a2, GEN T} \fun{GEN}{random_F2xqE}{GEN a2, GEN a6, GEN T} \fun{GEN}{F2xqE_order}{GEN P, GEN o, GEN a2, GEN T} returns the order of $P$ in the group $E(\F_2[X]/(T))$, where $o$ is a multiple of the order of $P$, or its factorization. \fun{GEN}{F2xqE_log}{GEN P, GEN G, GEN o, GEN a2, GEN T} Let \kbd{G} be a point of order \kbd{o}, return $e$ such that $e.P=G$. If $e$ does not exists, the result is currently undefined. \fun{GEN}{F2xqE_tatepairing}{GEN P, GEN Q, GEN m, GEN a2, GEN T} returns the Tate pairing of the point of $m$-torsion $P$ and the point $Q$. \fun{GEN}{F2xqE_weilpairing}{GEN Q, GEN Q, GEN m, GEN a2, GEN T} returns the Weil pairing of the points of $m$-torsion $P$ and $Q$. \fun{GEN}{RgE_to_F2xqE}{GEN P, GEN T} returns the \kbd{F2xqE} obtained by applying \kbd{Rg\_to\_F2xq} coefficientwise. \subsec{Elliptic curves over $\F_q$, small characteristic $p>2$ } Let $p > 2$ be a prime \kbd{ulong}, $T$ an irreducible \kbd{Flx} mod $p$, and $E$ the elliptic curve given by the equation $E:y^2=x^3+a_4\*x+a_6$, where $a_4$ and $a_6$ are \kbd{Flx} in $\F_p[X]/(T)$. A \kbd{FlxqE} is a point of $E(\F_p[X]/(T))$. In the special case $p = 3$, ordinary elliptic curves ($j(E)\neq 0$) cannot be represented as above, but admit a model $E:y^2 = x^3+a_2\*x^2+a_6$ with $a_2$ and $a_6$ being \kbd{Flx} in $\F_3[X]/(T)$. In that case, the parameter \kbd{a2} is actually stored as a \typ{VEC}, $[a_2]$, to avoid ambiguities. \fun{GEN}{Flxq_ellj}{GEN a4, GEN a6, GEN T, ulong p} returns the $j$-invariant of the curve $E$. \fun{void}{Flxq_ellj_to_a4a6}{GEN j, GEN T, ulong p, GEN *pa4, GEN *pa6} sets \kbd{*pa4} to $a_4$ and \kbd{*pa6} to $a_6$ where $a_4$ and $a_6$ define a fixed elliptic curve with $j$-invariant $j$. \fun{GEN}{Flxq_ellcard}{GEN a4, GEN a6, GEN T, ulong p} returns the order of $E(\F_p[X]/(T))$. \fun{GEN}{Flxq_ellgroup}{GEN a4, GEN a6, GEN N, GEN T, ulong p, GEN *pm} returns the group structure $D$ of the group $E(\F_p[X]/(T))$, which is assumed to be of order $N$ and sets \kbd{*pm} to $m$. \fun{GEN}{Flxq_ellgens}{GEN a4, GEN a6, GEN ch, GEN D, GEN m, GEN T, ulong p} returns generators of the group $E(\F_p[X]/(T))$ with the base change \kbd{ch} (see \kbd{FlxqE\_changepoint}), where $D$ and $m$ are as returned by \kbd{Flxq\_ellgroup}. \fun{void}{Flxq_elltwist}{GEN a4, GEN a6, GEN T, ulong p, GEN *pA4, GEN *pA6} sets \kbd{*pA4} and \kbd{*pA6} to the corresponding parameters for the quadratic twist of $E$. \subsec{\kbd{FlxqE}} Let $p > 2$ be a prime number. \fun{GEN}{FlxqE_changepoint}{GEN P, GEN m, GEN a4, GEN T, ulong p} returns the image $Q$ of the point $P$ on the curve $E:y^2=x^3+a_4\*x+a_6$ by the coordinate change $m$ (which is a \kbd{FlxqV}). \fun{GEN}{FlxqE_changepointinv}{GEN P, GEN m, GEN a4, GEN T, ulong p} returns the image $Q$ on the curve $E:y^2=x^3+a_4\*x+a_6$ of the point $P$ by the inverse of the coordinate change $m$ (which is a \kbd{FlxqV}). \fun{GEN}{FlxqE_add}{GEN P, GEN Q, GEN a4, GEN T, ulong p} \fun{GEN}{FlxqE_sub}{GEN P, GEN Q, GEN a4, GEN T, ulong p} \fun{GEN}{FlxqE_dbl}{GEN P, GEN a4, GEN T, ulong p} \fun{GEN}{FlxqE_neg}{GEN P, GEN T, ulong p} \fun{GEN}{FlxqE_mul}{GEN P, GEN n, GEN a4, GEN T, ulong p} \fun{GEN}{random_FlxqE}{GEN a4, GEN a6, GEN T, ulong p} \fun{GEN}{FlxqE_order}{GEN P, GEN o, GEN a4, GEN T, ulong p} returns the order of $P$ in the group $E(\F_p[X]/(T))$, where $o$ is a multiple of the order of $P$, or its factorization. \fun{GEN}{FlxqE_log}{GEN P, GEN G, GEN o, GEN a4, GEN T, ulong p} Let \kbd{G} be a point of order \kbd{o}, return $e$ such that $e.P=G$. If $e$ does not exists, the result is currently undefined. \fun{GEN}{FlxqE_tatepairing}{GEN P, GEN Q, GEN m, GEN a4, GEN T, ulong p} returns the Tate pairing of the point of $m$-torsion $P$ and the point $Q$. \fun{GEN}{FlxqE_weilpairing}{GEN P, GEN Q, GEN m, GEN a4, GEN T, ulong p} returns the Weil pairing of the points of $m$-torsion $P$ and $Q$. \fun{GEN}{FlxqE_weilpairing_pre}{GEN P, GEN Q, GEN m, GEN a4, GEN T, ulong p, ulong pi}, where \var{pi} is a pseudoinverse of $p$, or $0$ in which case we assume \kbd{SMALL\_ULONG}$(p)$. \fun{GEN}{RgE_to_FlxqE}{GEN P, GEN T, ulong p} returns the \kbd{FlxqE} obtained by applying \kbd{Rg\_to\_Flxq} coefficientwise. \fun{GEN}{Flxq_elldivpolmod}{GEN a4,GEN a6, long n, GEN h, GEN T, ulong p} returns the $n$-division polynomial of the elliptic curve $E$ modulo the polynomial $h$. \subsec{Elliptic curves over $\F_q$, large characteristic } Let $p > 3$ be a prime number, $T$ an irreducible polynomial mod $p$, and $E$ the elliptic curve given by the equation $E:y^2=x^3+a_4\*x+a_6$ with $a_4$ and $a_6$ in $\F_p[X]/(T)$. A \kbd{FpXQE} is a point of $E(\F_p[X]/(T))$. \fun{GEN}{FpXQ_ellj}{GEN a4, GEN a6, GEN T, GEN p} returns the $j$-invariant of the curve $E$. \fun{int}{FpXQ_elljissupersingular}{GEN j, GEN T, GEN p} returns $1$ if $j$ is the $j$-invariant of a supersingular curve over $\F_p[X]/(T)$, $0$ otherwise. \fun{int}{Fq_elljissupersingular}{GEN j, GEN T, GEN p} as \kbd{FpXQ\_elljissupersingular} but \kbd{j} can be a \typ{INT}. \fun{GEN}{ellsupersingularj_FpXQ}{GEN T, GEN p} $T$ being a \kbd{ZX} of degree $2$, return a random supersingular $j$-invariant in $\F_p[X]/T$. \fun{GEN}{FpXQ_ellcard}{GEN a4, GEN a6, GEN T, GEN p} returns the order of $E(\F_p[X]/(T))$. \fun{GEN}{FpXQ_ellcard_supersingular}{GEN a4, GEN a6, GEN T, GEN p} This function returns $\#E(\F_p[X]/(T))$, assuming the curve is supersingular, see \kbd{FpXQ\_elljissupersingular}. \fun{GEN}{Fq_ellcard_supersingular}{GEN a4, GEN a6, GEN T, GEN p} This function is identical to \kbd{FpXQ\_ellcard\_supersingular}, except that it allows \kbd{T} to be {NULL}. \fun{GEN}{Fq_ellcard_SEA}{GEN a4, GEN a6, GEN q, GEN T, GEN p, long s} This function returns $\#E(\F_p[X]/(T))$, using the Schoof-Elkies-Atkin algorithm. Assume $p\neq 2,3$, and $q$ is the cardinality of $\F_p[X]/(T)$. The parameter $s$ has the same meaning as in \kbd{Fp\_ellcard\_SEA}. If the \kbd{seadata} package is installed, the function will be faster. \fun{GEN}{FpXQ_ellgroup}{GEN a4, GEN a6, GEN N, GEN T, GEN p, GEN *pm} Return the group structure $D$ of the group $E(\F_p[X]/(T))$, which is assumed to be of order $N$ and set \kbd{*pm} to $m$. \fun{GEN}{FpXQ_ellgens}{GEN a4, GEN a6, GEN ch, GEN D, GEN m, GEN T, GEN p} Returns generators of the group $E(\F_p[X]/(T))$ with the base change \kbd{ch} (see \kbd{FpXQE\_changepoint}), where $D$ and $m$ are as returned by \kbd{FpXQ\_ellgroup}. \fun{GEN}{FpXQ_elldivpol}{GEN a4, GEN a6, long n, GEN T, GEN p} returns the $n$-division polynomial of the elliptic curve $E$. \fun{GEN}{Fq_elldivpolmod}{GEN a4,GEN a6, long n, GEN h, GEN T, GEN p} returns the $n$-division polynomial of the elliptic curve $E$ modulo the polynomial $h$. \fun{void}{FpXQ_elltwist}{GEN a4, GEN a6, GEN T, GEN p, GEN *pA4, GEN *pA6} sets \kbd{*pA4} and \kbd{*pA6} to the corresponding parameters for the quadratic twist of $E$. \subsec{\kbd{FpXQE}} \fun{GEN}{FpXQE_changepoint}{GEN P, GEN m, GEN a4, GEN T, GEN p} returns the image $Q$ of the point $P$ on the curve $E:y^2=x^3+a_4\*x+a_6$ by the coordinate change $m$ (which is a \kbd{FpXQV}). \fun{GEN}{FpXQE_changepointinv}{GEN P, GEN m, GEN a4, GEN T, GEN p} returns the image $Q$ on the curve $E:y^2=x^3+a_4\*x+a_6$ of the point $P$ by the inverse of the coordinate change $m$ (which is a \kbd{FpXQV}). \fun{GEN}{FpXQE_add}{GEN P, GEN Q, GEN a4, GEN T, GEN p} \fun{GEN}{FpXQE_sub}{GEN P, GEN Q, GEN a4, GEN T, GEN p} \fun{GEN}{FpXQE_dbl}{GEN P, GEN a4, GEN T, GEN p} \fun{GEN}{FpXQE_neg}{GEN P, GEN T, GEN p} \fun{GEN}{FpXQE_mul}{GEN P, GEN n, GEN a4, GEN T, GEN p} \fun{GEN}{random_FpXQE}{GEN a4, GEN a6, GEN T, GEN p} \fun{GEN}{FpXQE_log}{GEN P, GEN G, GEN o, GEN a4, GEN T, GEN p} Let \kbd{G} be a point of order \kbd{o}, return $e$ such that $e.P=G$. If $e$ does not exists, the result is currently undefined. \fun{GEN}{FpXQE_order}{GEN P, GEN o, GEN a4, GEN T, GEN p} returns the order of $P$ in the group $E(\F_p[X]/(T))$, where $o$ is a multiple of the order of $P$, or its factorization. \fun{GEN}{FpXQE_tatepairing}{GEN P,GEN Q, GEN m, GEN a4, GEN T, GEN p} returns the Tate pairing of the point of $m$-torsion $P$ and the point $Q$. \fun{GEN}{FpXQE_weilpairing}{GEN P,GEN Q, GEN m, GEN a4, GEN T, GEN p} returns the Weil pairing of the points of $m$-torsion $P$ and $Q$. \fun{GEN}{RgE_to_FpXQE}{GEN P, GEN T, GEN p} returns the \kbd{FpXQE} obtained by applying \kbd{Rg\_to\_FpXQ} coefficientwise. \section{Functions related to modular polynomials} Variants of \tet{polmodular}, returning the modular polynomial of prime level $L$ for the invariant coded by \kbd{inv} (0: $j$, 1: Weber-$f$, see \tet{polclass} for the full list). \fun{GEN}{polmodular_ZXX}{long L, long inv, long vx, long vy} returns a bivariate polynomial in variables \kbd{vx} and \kbd{vy}. \fun{GEN}{polmodular_ZM}{long L, long inv} returns a matrix of (integral) coefficients. \fun{GEN}{Fp_polmodular_evalx}{long L, long inv, GEN J, GEN p, long v, int derivs} returns the modular polynomial evaluated at $J$ modulo the prime $p$ in the variable $v$ (if \kbd{derivs} is nonzero, returns a vector containing the modular polynomial and its first and second derivatives, all evaluated at $J$ modulo~$p$). \subsec{Functions related to modular invariants} \fun{void}{check_modinv}{long inv} report an error if \kbd{inv} is not a valid code for a mdular invariant. \fun{int}{modinv_good_disc}{long inv, long D} test whether the invariant \kbd{inv} is defined for the discriminant \kbd{D}. \fun{int}{modinv_good_prime}{long inv, long D} test whether the invariant \kbd{inv} is defined for the prime \kbd{p}. \fun{long}{modinv_height_factor}{long inv} return the height factor of the modular invariant \kbd{inv} with respect to the $j$-invariant. This is an integer $n$ such that the $j$-invariant is asymptotically of the order of the $n$-th power of the invariant \kbd{inv}. \fun{long}{modinv_is_Weber}{long inv} test whether the invariant \kbd{inv} is a power of Weber $f$. \fun{long}{modinv_is_double_eta}{long inv} test whether the invariant \kbd{inv} is a double $\eta$ quotient. \fun{long}{disc_best_modinv}{long D} the integer $D$ being a negative discriminant, return the modular invariant compatible with $D$ with the highest height factor. \fun{GEN}{Fp_modinv_to_j}{GEN x, long inv, GEN p} Let $\Phi$ the modular equation between $j$ and the modular invariant \kbd{inv}, return $y$ such that $\Phi(y,x)=0\pmod{p}$. \section{Other curves} The following functions deal with hyperelliptic curves in weighted projective space $\P_{(1,d,1)}$, with coordinates $(x,y,z)$ and a model of the form $ y^2 = T(x,z)$, where $T$ is homogeneous of degree $2d$, and squarefree. Thus the curve is nonsingular of genus $d-1$. \fun{long}{hyperell_locally_soluble}{GEN T, GEN p} assumes that $T\in\Z[X]$ is integral. Returns $1$ if the curve is locally soluble over $\Q_p$, $0$ otherwise. \fun{long}{nf_hyperell_locally_soluble}{GEN nf, GEN T, GEN pr} let $K$ be a number field, attached to \kbd{nf}, \kbd{pr} a \var{prid} attached to some maximal ideal $\goth{p}$; assumes that $T\in\Z_K[X]$ is integral. Returns $1$ if the curve is locally soluble over $K_{\goth{p}}$. The argument \kbd{nf} is a true \var{nf} structure. \newpage pari-2.17.2/doc/refmacro.tex0000644000175000017500000001474314760123736014273 0ustar billbill% Copyright (c) 2015 Karim Belabas. % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License % TeX macros for gp's reference card. Based on Stephen Gildea's multicolumn % macro package, modified from his GNU emacs reference card. Based on an % earlier version by Joseph H. Silverman who kindly let me use his original % file. \def\versionnumber{2.39}% Version of these reference cards \def\PARIversion{2.17.2}% Version of PARI described on these reference cards \def\year{2024} \def\month{September} \special{papersize=29.7cm,21cm} % ignore parimacro.tex's \magnification setting \let\oldmagnification\magnification \catcode`@=11 \def\magnification{\count@}% \catcode`@=12 \input parimacro.tex \let\magnification\oldmagnification \ifPDF \pdfpagewidth=11.69in \pdfpageheight=8.26in \fi \newcount\columnsperpage % The final reference card has six columns, three on each side. % This file can be used to produce it in any of three ways: % 1 column per page % produces six separate pages, each of which needs to be reduced to 80%. % This gives the best resolution. % 2 columns per page % produces three already-reduced pages. % You will still need to cut and paste. % 3 columns per page % produces two pages which must be printed sideways to make a % ready-to-use 8.5 x 11 inch reference card. % For this you need a dvi device driver that can print sideways. % [For 2 or 3 columns, you'll need 6 and 8 point fonts.] % Which mode to use is controlled by setting \columnsperpage below: \columnsperpage=3 % You shouldn't need to modify anything below this line. \def\version{\month\ \year\ v\versionnumber} \def\shortcopyrightnotice{\vskip .5ex plus 2 fill \centerline{\small \copyright\ \year\ Karim Belabas. Permissions on back. v\versionnumber}} \def\<#1>{$\langle${#1}$\rangle$} \def\copyrightnotice{\vskip 1ex plus 2 fill \begingroup\small \centerline{Based on an earlier version by Joseph H. Silverman} \centerline{\version. Copyright \copyright\ \year\ K. Belabas} Permission is granted to make and distribute copies of this card provided the copyright and this permission notice are preserved on all copies. Send comments and corrections to \ \endgroup} % make \bye not \outer so that the \def\bye in the \else clause below % can be scanned without complaint. \def\bye{\par\vfill\supereject\end} \newdimen\intercolumnskip \newbox\columna \newbox\columnb \def\ncolumns{\the\columnsperpage} \message{[\ncolumns\space column\if 1\ncolumns\else s\fi\space per page]} \def\scaledmag#1{ scaled \magstep #1} % This multi-way format was designed by Stephen Gildea % October 1986. \if 1\ncolumns \hsize 4in \vsize 10in \voffset -.7in \font\titlefont=\fontname\tenbf \scaledmag3 \font\headingfont=\fontname\tenbf \scaledmag2 \font\smallfont=\fontname\sevenrm \font\smallsy=\fontname\sevensy \footline{\hss\folio} \def\makefootline{\baselineskip10pt\hsize6.5in\line{\the\footline}} \else \hsize 3.4in \vsize 7.90in \hoffset -.75in \voffset -.815in \font\titlefont=cmbx10 \scaledmag2 \font\headingfont=cmbx10 %\scaledmag1 \font\smallfont=cmr6 \font\smallsy=cmsy6 \font\eightrm=cmr8 \font\eightbf=cmbx8 \font\eightit=cmti8 \font\eighttt=cmtt8 \font\eightsy=cmsy8 \font\eightsl=cmsl8 \font\eighti=cmmi8 \font\eightex=cmex10 at 8pt \textfont0=\eightrm \textfont1=\eighti \textfont2=\eightsy \textfont3=\eightex \def\rm{\fam0 \eightrm} \def\bf{\eightbf} \def\it{\eightit} \def\tt{\eighttt} \normalbaselineskip=.8\normalbaselineskip \normallineskip=.8\normallineskip \normallineskiplimit=.8\normallineskiplimit \normalbaselines\rm %make definitions take effect \if 2\ncolumns \let\maxcolumn=b \footline{\hss\rm\folio\hss} \def\makefootline{\vskip 2in \hsize=6.86in\line{\the\footline}} \else \if 3\ncolumns \let\maxcolumn=c \nopagenumbers \else \errhelp{You must set \columnsperpage equal to 1, 2, or 3.} \errmessage{Illegal number of columns per page} \fi\fi \intercolumnskip=.45in \def\abc{a} \output={% % This next line is useful when designing the layout. %\immediate\write16{Column \folio\abc\space starts with \firstmark} \if \maxcolumn\abc \multicolumnformat \global\def\abc{a} \else\if a\abc \global\setbox\columna\columnbox \global\def\abc{b} %% in case we never use \columnb (two-column mode) \global\setbox\columnb\hbox to -\intercolumnskip{} \else \global\setbox\columnb\columnbox \global\def\abc{c}\fi\fi} \def\multicolumnformat{\shipout\vbox{\makeheadline \hbox{\box\columna\hskip\intercolumnskip \box\columnb\hskip\intercolumnskip\columnbox} \makefootline}\advancepageno} \def\columnbox{\leftline{\pagebody}} \def\bye{\par\vfill\supereject \if a\abc \else\null\vfill\eject\fi \if a\abc \else\null\vfill\eject\fi \end} \fi % we won't be using math mode much, so redefine some of the characters % we might want to talk about %\catcode`\^=12 %\catcode`\_=12 %\catcode`\~=12 \chardef\\=`\\ \chardef\{=`\{ \chardef\}=`\} \hyphenation{} \parindent 0pt \parskip 0pt \def\small{\smallfont\textfont2=\smallsy\baselineskip=.8\baselineskip} \outer\def\newcolumn{\vfill\eject} \outer\def\title#1{{\titlefont\centerline{#1}}} \outer\def\section#1{\par\filbreak \vskip 1ex plus .4ex minus .5ex {\headingfont #1}\mark{#1}% \vskip .5ex plus .3ex minus .5ex } \outer\def\subsec#1{\filbreak \vskip 0.07ex plus 0.05ex {\bf #1} \vskip 0.03ex plus 0.05ex } \newdimen\keyindent \def\beginindentedkeys{\keyindent=1em} \def\endindentedkeys{\keyindent=0em} \endindentedkeys \def\kbd#1{{\tt#1}\null} %\null so not an abbrev even if period follows \newbox\libox \setbox\libox\hbox{\kbd{M-x }} \newdimen\liwidth \liwidth=\wd\libox \def\li#1#2{\leavevmode\hbox to \hsize{\hbox to .75\hsize {\hskip\keyindent\relax#1\hfil}% \hskip -\liwidth minus 1fil \kbd{#2}\hfil}} \def\threecol#1#2#3{\hskip\keyindent\relax#1\hfil&\kbd{#2}\quad &\kbd{#3}\quad\cr} \def\mod{\;\hbox{\rm mod}\;} \def\expr{\hbox{\it expr}} \def\seq{\hbox{\it seq}} \def\args{\hbox{\it args}} \def\file{\hbox{\it file}} \def\QQ{\hbox{\bf Q}} \def\MM{\hbox{\bf M}} \def\ZZ{\hbox{\bf Z}} \def\PP{\hbox{\bf P}} \def\RR{\hbox{\bf R}} \def\FF{\hbox{\bf F}} \def\CC{\hbox{\bf C}} \def\deg{\mathop{\rm deg}} \def\bs{\char'134} \def\pow{\^{}\hskip0pt} \def\til{\raise-0.3em\hbox{\~{}}} \def\typ#1{\kbd{t\_#1}} %%%%%%%%%%%%%%%%%%%%%%% \title{\TITLE} \centerline{(PARI-GP version \PARIversion)} pari-2.17.2/doc/gphelp.10000644000175000017500000001267214760123736013313 0ustar billbill.TH GPHELP 1 "12 September 2024" .SH NAME gphelp \- GP-PARI online help script .SH SYNOPSIS .BR gphelp [-to_pod .IR file ] [-raw] [-detex] [-noskip] [-utf8] [-k] [-ch .IR c1 ] [-cb .IR c2 ] [-cu .IR c3 ] [keyword [ @{1,2,3,4,5} ]] [tutorial] [refcard]... .SH DESCRIPTION Invokes the PARI-GP online help script. By default, .I keyword is understood as a section heading (a GP function name), and .B gphelp looks for it in Chapter 3 of PARI User's Manual. If it is found, the corresponding section is copied to a temporary file in /tmp (or .BR $GPTMPDIR ), .B TeX is run then the corresponding section is displayed in a separate window, using .B xdvi (or .BR $GPXDVI ). If more than one keyword is given on a single command line, the outputs are concatenated. If .I keyword is omitted, open the whole manual .IR users.dvi . The keywords .I tutorial and .I refcard open the GP tutorial and reference card respectively. GP defaults, help sections (1 to 11) as well as some keywords (readline, bnf, ell, all operators...) are recognized and treated in a special way to make sure they match a section heading. For instance .B && is translated to .I "Comparison and boolean operators" which isn't that obvious to guess. Make sure to enclose .I keyword between quotes if it contains dangerous characters (e.g spaces). For instance, you need to type .RS gphelp -k "elliptic curves" .RE and not .RS gphelp -k elliptic curves .RE which would look for "elliptic" then for "curves" and output e.g. .B ploth among the relevant sections. .SH FULL SEARCH: @ MARKERS The pattern .BR @ x (where x is a chapter number between 1 and 5) at the end of .I keyword conducts the search in the corresponding chapter instead of the default Chapter 3. If the number is omitted, search the whole manual. For instance .RS gphelp -k gerepile@4 .RE will look for .B gerepile in Chapter 4 of users manual. .RS gphelp -k gerepile@ .RE will search the whole manual. All chapters of the manual (usersch[1-5].tex) are assumed to be in .B $GPDOCDIR .RI ( default value set by Configure). You are allowed to gzip (or compress) them, this won't affect the search. .SH OPTIONS The following command line options are available: .TP .BI -cb,\ -color_bold\ c2 color used for bold. See .BR -color_help . .TP .BI -ch,\ -color_help\ c1 color (between 1 and 16) used for general printing. Only significant in .B detex mode. .TP .BI -cu,\ -color_underline\ c3 color used for underline. See .BR -color_help . .TP .BI \-detex Use .B detex mode. The TeX file is converted to readable screen output that is directly written to the terminal; don't use tex or xdvi. .TP .BI \-noskip By default, the help text is continued when a new section is tagged with a %GPHELPskip marker (on the same line). If this option is set, do not honor markers: end the help text as soon as a new section is started. .TP .BI \-utf8 In .B detex mode, use UTF-8 encoding for characters, .e.g. use \('e (é) instead of 'e. .TP .BI \-k Switch to .B apropos mode. Only write to standard output the list of section headings in manual which contain .IR keyword . You can then choose an element in the list and use it as argument for .B gphelp (surround it by quotes if it includes spaces), possibly followed by a trailing .B @ marker (see above). .TP .BI \-raw use internal format for output (using @x markers). For debugging only. .TP .BI \-to_pod\ file try to convert .I file from TeX to POD format. Will only work on some subset of PARI User's Manual (Chapter 3, reference card). This should be the only arguments on the command line. .SH ENVIRONMENT .TP COLUMNS number of columns available on screen (for .B detex mode) .TP DISPLAY where to launch the dvi previewer. If unset, .B detex mode is assumed automatically. .TP GPDOCDIR directory where PARI help files are located. Default value set at Configure time. .TP GPTEX .RS TeX typesetting program to use .RE .TP GPTMPDIR directory where temporary files are written .TP GPXDVI .RS dvi previewer to use. You may use this to specify options for vanilla xdvi, for instance "xdvi -s 7" to select a shrink factor. .RE .SH FILES .TP .I gp the gp calculator .TP .I gphelp the gphelp script .TP .I users.dvi PARI/GP User's Manual .TP .I tutorial.dvi PARI/GP tutorial .TP .I refcard.dvi GP reference card .TP .I refcard.ps GP reference card, printer ready .SH BUGS The search algorithm is rather crude and the data searched rather unstructured. Hence, searching outside of Chapter 3 may not yield useful results, except in .B apropos mode (sections may be truncated too soon for instance). Multiword search patterns have a tendency to fail due to various TeX constructs in the source. .SH AUTHORS Originally written by Ilya Zakharevitch for the Math::Pari perl package. Rewritten and expanded by Karim Belabas for the main PARI distribution. .SH SEE ALSO .IR gp (1), .IR gzip (1), .IR readline (1), .IR tex (1), .IR xdvi (1). .SH COPYING This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. pari-2.17.2/doc/users.tex0000644000175000017500000000142314567450071013625 0ustar billbill% Copyright (c) 2000 The PARI Group % % This file is part of the PARI/GP documentation % % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License % Compile with plain TeX % \def\TITLE{User's Guide to Pari/GP} \input parimacro.tex % remove TOC for this level \SUBSECTOCfalse % START TYPESET \begintitle \vskip 2.5truecm \centerline{\mine User's Guide} \vskip 1.truecm \centerline{\mine to} \vskip 1.truecm \centerline{\mine PARI / GP} \vskip 1.truecm \centerline{\sectiontitlebf (version \vers)} \vskip 1.truecm \authors \endtitle \copyrightpage \tableofcontents \openin\std=libpari.aux \ifeof\std \else \input libpari.aux \fi \chapno=0 { \input usersch1 } { \input usersch2 } { \input usersch3 } \input index\end pari-2.17.2/doc/appd.tex0000644000175000017500000000661314567450071013416 0ustar billbill% Copyright (c) 2000 The PARI Group % % This file is part of the PARI/GP documentation % % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License \appendix{PARI and threads} To use PARI in multi-threaded programs, you must configure it using \kbd{Configure --enable-tls}. Your system must implement the \kbd{\_\_thread} storage class. As a major side effect, this breaks the \kbd{libpari} ABI: the resulting library is not compatible with the old one, and \kbd{-tls} is appended to the PARI library \kbd{soname}. On the other hand, this library is now thread-safe. PARI provides some functions to set up PARI subthreads\sidx{threads}. In our model, each concurrent thread needs its own PARI stack. The following scheme is used: \noindent Child thread: \bprog void *child_thread(void *arg) { GEN data = pari_thread_start((struct pari_thread*)arg); GEN result = ...; /* Compute result from data */ pari_thread_close(); return (void*)result; } @eprog \noindent Parent thread: \bprog pthread_t th; struct pari_thread pth; GEN data, result; pari_thread_alloc(&pth, s, data); pthread_create(&th, NULL, &child_thread, (void*)&pth); /* start child */ ... /* do stuff in parent */ pthread_join(th, (void*)&result); /* wait until child terminates */ result = gcopy(result); /* copy result from thread stack to main stack */ pari_thread_free(&pth); /* ... and clean up */ @eprog \fun{void}{pari_thread_valloc}{struct pari_thread *pth, size_t s, size_t v, GEN arg} Allocate a PARI stack of size \kbd{s} which can grow to at most \kbd{v} (as with \kbd{parisize} and \kbd{parisizemax}) and associate it, together with the argument \kbd{arg}, with the PARI thread data \kbd{pth}. \fun{void}{pari_thread_alloc}{struct pari_thread *pth, size_t s, GEN arg} As above but the stack cannot grow beyond \kbd{s}. \fun{void}{pari_thread_free}{struct pari_thread *pth} Free the PARI stack attached to the PARI thread data \kbd{pth}. This is called after the child thread terminates, i.e.~after \tet{pthread_join} in the parent. Any \kbd{GEN} objects returned by the child in the thread stack need to be saved before running this command. \fun{void}{pari_thread_init}{void} Initialize the thread-local PARI data structures. This function is called by \kbd{pari\_thread\_start}. \fun{GEN}{pari_thread_start}{struct pari_thread *t} Initialize the thread-local PARI data structures and set up the thread stack using the PARI thread data \kbd{pth}. This function returns the thread argument \kbd{arg} that was given to \kbd{pari\_thread\_alloc}. \fun{void}{pari_thread_close}{void} Free the thread-local PARI data structures, but keeping the thread stack, so that a \kbd{GEN} returned by the thread remains valid. \noindent Under this model, some PARI states are reset in new threads. In particular \item the random number generator is reset to the starting seed; \item the system stack exhaustion checking code, meant to catch infinite recursions, is disabled (use \kbd{pari\_stackcheck\_init()} to reenable it); \item cached real constants (returned by \kbd{mppi}, \kbd{mpeuler} and \kbd{mplog2}) are not shared between threads and will be recomputed as needed; \noindent The following sample program can be compiled using \bprog cc thread.c -o thread.o -lpari -lpthread @eprog\noindent (Add \kbd{-I/-L} paths as necessary.) \noindent\bprogfile{../examples/thread.c} \vfill\eject pari-2.17.2/doc/parallel.tex0000644000175000017500000003522714567450071014271 0ustar billbill\def\TITLE{Introduction to parallel GP programming} \input parimacro.tex % START TYPESET \begintitle \vskip 2.5truecm \centerline{\mine Introduction} \vskip 1.truecm \centerline{\mine to} \vskip 1.truecm \centerline{\mine parallel GP} \vskip 1.truecm \centerline{\sectiontitlebf (version \vers)} \vskip 1.truecm \authors \endtitle \copyrightpage \tableofcontents \openin\std=parallel.aux \ifeof\std \else \input parallel.aux \fi \chapno=0 \chapter{Parallel GP interface} \section{Configuration} This booklet documents the parallel GP interface. The first chapter describes configuration and basic concepts, the second one explains how to write GP codes suitable for parallel execution. Two multithread interfaces are supported: \item POSIX threads \item Message passing interface (MPI) POSIX threads are well-suited for single systems, for instance a personal computer equiped with a multi-core processor, while MPI is used by most clusters. However the parallel GP interface does not depend on the multithread interface: a properly written GP program will work identically with both. The interfaces are mutually exclusive and one must be chosen at configuration time when installing the PARI/GP suite. \subsec{POSIX threads} POSIX threads are selected by passing the flag \kbd{--mt=pthread} to \kbd{Configure}. The required library (\kbd{libpthread}) and header files (\kbd{pthread.h}) are installed by default on most Linux system. This option implies \kbd{--enable-tls} which builds a thread-safe version of the PARI library. This unfortunately makes the dynamically linked \kbd{gp-dyn} binary about $25\%$ slower; since \kbd{gp-sta} is only $5\%$ slower, you definitely want to use the latter binary. You may want to also pass the flag \kbd{--time=ftime} to \kbd{Configure} so that \kbd{gettime} and the GP timer report real time instead of cumulated CPU time. An alternative is to use \kbd{getwalltime} in your GP scripts instead of \kbd{gettime}. You can test whether parallel GP support is working with \bprog make test-parallel @eprog \subsec{Message Passing Interface} Configuring MPI is somewhat more difficult, but your MPI installation should include a script \kbd{mpicc} that takes care of the necessary configuration. If you have a choice between several MPI implementations, choose OpenMPI. To configure PARI/GP for MPI, use \bprog env CC=mpicc ./Configure --mt=mpi @eprog To run a program, you must use the launcher provided by your implementation, usually \kbd{mpiexec} or \kbd{mpirun}. For instance, to run the program \kbd{prog.gp} on $10$ nodes, you would use \bprog mpirun -np 10 gp prog.gp @eprog\noindent (or \kbd{mpiexec} instead of \kbd{mpirun}). PARI requires at least $3$ MPI nodes to work properly. \emph{Caveats:} \kbd{mpirun} is not suited for interactive use because it does not provide tty emulation. Moreover, it is not currently possible to interrupt parallel tasks. You can test parallel GP support (here using 3 nodes) with \bprog make test-parallel RUNTEST="mpirun -np 3" @eprog \section{Concept} In a GP program, the \emph{main thread} executes instructions sequentially (one after the other) and GP provides functions, that execute subtasks in \emph{secondary threads} in parallel (at the same time). Those functions all share the prefix \kbd{par}, e.g., \kbd{parfor}, a parallel version of the sequential \kbd{for}-loop construct. The subtasks are subject to a stringent limitation, the parallel code must be free of side effects: it cannot set or modify a global variable for instance. In fact, it may not even \emph{access} global variables or local variables declared with \kbd{local()}. Due to the overhead of parallelism, we recommend to split the computation so that each parallel computation requires at least a few seconds. On the other hand, it is generally more efficient to split the computation in small chunks rather than large chunks. \subsec{Resources} The number of secondary threads to use is controlled by \kbd{default(nbthreads)}. The default value of nbthreads depends on the mutithread interface. \item POSIX threads: the number of CPU threads, i.e., the number of CPU cores multiplied by the hyperthreading factor. The default can be freely modified. \item MPI: the number of available process slots minus $1$ (one slot is used by the master thread), as configured with \kbd{mpirun} (or \kbd{mpiexec}). E.g., \kbd{nbthreads} is $9$ after \kbd{mpirun -np 10 gp}. It is possible to change the default to a lower value, but increasing it will not work: MPI does not allow to spawn new threads at run time. PARI requires at least $3$ MPI nodes to work properly. The PARI stack size in secondary threads is controlled by \kbd{default(threadsize)}, so the total memory allocated is equal to $\kbd{parisize}+\kbd{nbthreads}\times\kbd{threadsize}$. By default, $\kbd{threadsize}=\kbd{parisize}$. Setting the \kbd{threadsizemax} default allows \kbd{threadsize} to grow as needed up to that limit, analogously to the behaviour of \kbd{parisize} / \kbd{parisizemax}. We strongly recommend to set this parameter since it is very hard to control in advance the amount of memory threads will require: a too small stack size will result in a stack overflow, aborting the computation, and a too large value is very wasteful (since the extra reserved but unneeded memory is multiplied by the number of threads). \subsec{GP functions} GP provides the following functions for parallel operations, please see the documentation of each function for details: \item \tet{parvector}: parallel version of \kbd{vector}; \item \tet{parapply}: parallel version of \kbd{apply}; \item \tet{parsum}: parallel version of \kbd{sum}; \item \tet{parselect}: parallel version of \kbd{select}; \item \tet{pareval}: evaluate a vector of closures in parallel; \item \tet{parfor}: parallel version of \kbd{for}; \item \tet{parforprime}: parallel version of \kbd{forprime}; \item \tet{parforvec}: parallel version of \kbd{forvec}; \item \tet{parploth}: parallel version of \kbd{ploth}. \subsec{PARI functions} The low-level \kbd{libpari} interface for parallelism is documented in the \emph{Developer's guide to the PARI library}. \newpage \chapter{Writing code suitable for parallel execution} \section{Exporting global variables} When parallel execution encounters a global variable, say $V$, an error such as the following is reported: \bprog *** parapply: mt: please use export(V) @eprog\noindent A global variable is not visible in the parallel execution unless it is explicitly exported. This may occur in a number of contexts. \subsec{Example 1: data} \bprog ? V = [2^256 + 1, 2^193 - 1]; ? parvector(#V, i, factor(V[i])) *** parvector: mt: please use export(V). @eprog\noindent The problem is fixed as follows: \bprog ? V = [2^256 + 1, 2^193 - 1]; ? export(V) ? parvector(#V, i, factor(V[i])) @eprog\noindent The following short form is also available, with a different semantic: \bprog ? export(V = [2^256 + 1, 2^193 - 1]); ? parvector(#V, i, factor(V[i])) @eprog\noindent In the latter case the variable $V$ does not exist in the main thread, only in parallel threads. \subsec{Example 2: polynomial variable} \bprog ? f(n) = bnfinit(x^n-2).no; ? parapply(f, [1..50]) *** parapply: mt: please use export(x). @eprog\noindent You may fix this as in the first example using \kbd{export} but here there is a more natural solution: use the polynomial indeterminate \kbd{'x} instead the global variable \kbd{x} (whose value is \kbd{'x} on startup, but may or may no longer be \kbd{'x} at this point): \bprog ? f(n) = bnfinit('x^n-2).no; @eprog\noindent or alternatively \bprog ? f(n) = my(x='x); bnfinit(x^n-2).no; @eprog which is more readable if the same polynomial variable is used several times in the function. \subsec{Example 3: function} \bprog ? f(a) = bnfinit('x^8-a).no; ? g(a,b) = parsum(i = a, b, f(i)); ? g(37,48) *** parsum: mt: please use export(f). ? export(f) ? g(37,48) %4 = 81 @eprog\noindent Note that \kbd{export}$(v)$ freezes the value of $v$ for parallel execution at the time of the export: you may certainly modify its value later in the main thread but you need to re-export $v$ if you want the new value to be used in parallel threads. You may export more than one variable at once, e.g., \kbd{export}$(a,b,c)$ is accepted. You may also export \emph{all} variables with dynamic scope (all global variables and all variables declared with \kbd{local}) using \kbd{exportall()}. Although convenient, this may be wasteful if most variables are not meant to be used from parallel threads. We recommend to \item use \kbd{exportall} in the \kbd{gp} interpreter interactively, while developping code; \item \kbd{export} a function meant to be called from parallel threads, just after its definition; \item use $v = \var{value}$; \kbd{export}$(v)$ when the value is needed both in the main thread and in secondary threads; \item use \kbd{export}($v = \var{value}$) when the value is not needed in the main thread. \noindent In the two latter forms, $v$ should be considered read-only. It is actually read-only in secondary threads, trying to change it will raise an exception: \bprog *** mt: attempt to change exported variable 'v'. @eprog\noindent You \emph{can} modify it in the main thread, but it must be exported again so that the new value is accessible to secondary threads: barring a new \kbd{export}, secondary threads continue to access the old value. \section{Input and output} If your parallel code needs to write data to files, split the output in as many files as the number of parallel computations, to avoid concurrent writes to the same file, with a high risk of data corruption. For example a parallel version of \bprog ? f(a) = write("bnf",bnfinit('x^8-a)); ? for (a = 37, 48, f(a)) @eprog\noindent could be \bprog ? f(a) = write(Str("bnf-",a), bnfinit('x^8-a).no); ? export(f); ? parfor(i = 37, 48, f(i)) @eprog\noindent which creates the files \kbd{bnf-37} to \kbd{bnf-48}. Of course you may want to group these file in a subdirectory, which must be created first. \section{Using \kbd{parfor} and \kbd{parforprime}} \kbd{parfor} and \kbd{parforprime} are the most powerful of all parallel GP functions but, since they have a different interface than \kbd{for} or \kbd{forprime}, sequential code needs to be adapted. Consider the example \bprog for(i = a, b, my(c = f(i)); g(i,c)); @eprog\noindent where \kbd{f} is a function without side effects. This can be run in parallel as follows: \bprog parfor(i = a, b, f(i), c, /*@Ccom the value of \kbd{f(i)} is assigned to \kbd{c} */ g(i,c)); @eprog\noindent For each $i$, $a \leq i \leq b$, in random order, this construction assigns \kbd{f(i)} to (lexically scoped, as per~\kbd{my}) variable $c$, then calls \kbd{g}$(i,c)$. Only the function \kbd{f} is evaluated in parallel (in secondary threads), the function \kbd{g} is evaluated sequentially (in the main thread). Writing \kbd{c = f(i)} in the parallel section of the code would not work since the main thread would then know nothing about $c$ or its content. The only data sent from the main thread to secondary threads are $f$ and the index $i$, and only $c$ (which is equal to $f(i)$) is returned from the secondary thread to the main thread. The following function finds the index of the first component of a vector $V$ satisfying a predicate, and $0$ if none satisfies it: \bprog parfirst(pred, V) = { parfor(i = 1, #V, pred(V[i]), cond, if (cond, return(i))); return(0); } @eprog\noindent This works because, if the second expression in \kbd{parfor} exits the loop via \kbd{break} / \kbd{return} at index~$i$, it is guaranteed that all indexes $< i$ are also evaluated and the one with smallest index is the one that triggers the exit. See \kbd{??parfor} for details. The following function is similar to \kbd{parsum}: \bprog myparsum(a, b, expr) = { my(s = 0); parfor(i = a, b, expr(i), val, s += val); return(s); } @eprog \section{Sizing parallel tasks} Dispatching tasks to parallel threads takes time. To limit overhead, split the computation so that each parallel task requires at least a few seconds. Consider the following sequential example: \bprog ? thuemorse(n) = (-1)^n * hammingweight(n); ? s = 0; for(n = 1, 2*10^6, s += thuemorse(n) / n * 1.) cpu time = 1,064 ms, real time = 1,064 ms. @eprog\noindent It is natural to try \bprog ? export(thuemorse); ? s = 0; parfor(n = 1, 2*10^6, thuemorse(n) / n * 1., S, s += S) cpu time = 5,637 ms, real time = 3,216 ms. @eprog\noindent However, due to the overhead, this is not faster than the sequential version; in fact it is much \emph{slower}. To limit overhead, we group the summation by blocks: \bprog ? s = 0; parfor(N = 1, 20, sum(n = 1+(N-1)*10^5, N*10^5, thuemorse(n) / n*1.), S, s += S) ? cpu time = 1,997 ms, real time = 186 ms. @eprog\noindent Try to create at least as many groups as the number of available threads, to take full advantage of parallelism. Since some of the floating point additions are done in random order (the ones in a given block occur successively, in deterministic order), it is possible that some of the results will differ slightly from one run to the next. Of course, in this example, \kbd{parsum} is much easier to use since it will group the summations for you behind the scenes: \bprog ? parsum(n = 1, 2*10^6, thuemorse(n) / n * 1.) cpu time = 1,905 ms, real time = 177 ms. @eprog \section{Load balancing} If the parallel tasks require varying time to complete, it is preferable to perform the slower ones first, when there are more tasks than available parallel threads. Instead of \bprog parvector(36, i, bnfinit('x^i - 2).no) @eprog\noindent doing \bprog parvector(36, i, bnfinit('x^(37-i) - 2).no) @eprog\noindent will be faster if you have fewer than $36$ threads. Indeed, \kbd{parvector} schedules tasks by increasing $i$ values, and the computation time increases steeply with $i$. With $18$ threads, say: \item in the first form, thread~1 handles both $i = 1$ and $i = 19$, while thread~18 will likely handle $i = 18$ and $i = 36$. In fact, it is likely that the first batch of tasks $i\leq 18$ runs relatively quickly, but that none of the threads handling a value $i > 18$ (second task) will have time to complete before $i = 18$. When that thread finishes $i = 18$, it will pick the remaining task $i = 36$. \item in the second form, thread~1 will likely handle only $i = 36$: tasks $i = 36, 35, \dots 19$ go to the available 18 threads, and $i = 36$ is likely to finish last, when $i = 18,\dots, 2$ are already assigned to the other 17 threads. Since the small values of $i$ will finish almost instantly, $i = 1$ will have been allocated before the initial thread handling $i = 36$ becomes ready again. Load distribution is clearly more favourable in the second form. \vfill\eject \input index\end pari-2.17.2/doc/translations0000644000175000017500000001512214676526175014421 0ustar billbillreadline @se:readline@2 edit @se:readline@2 ? @?@2 ?? @?@2 \\ @\bs\bs@2 \a @\b{a}@2 \b @\b{b}@2 \c @\b{c}@2 \d @\b{d}@2 \e @\b{e}@2 \g @\b{g}@2 \gf @\b{gf}@2 \gm @\b{gm}@2 \h @\b{h}@2 \k @\b{k}@2 \l @\b{l}@2 \m @\b{m}@2 \p @\b{p}@2 \o @\b{o}@2 \ps @\b{ps}@2 \q @\b{q}@2 \r @\b{r}@2 \s @\b{s}@2 \t @\b{t}@2 \u @\b{u}@2 \um @\b{um}@2 \uv @\b{uv}@2 \v @\b{v}@2 \w @\b{w}@2 \x @\b{x}@2 \y @\b{y}@2 # @\#@2 ## @\#\#@2 _++ @++ _-- @-- ++ @++ -- @-- += @op= _+=_ @op= -= @op= _-=_ @op= *= @op= _*=_ @op= /= @op= _\=_ @op= \= @op= _%=_ @op= %= @op= _\/=_ @op= \/= @op= _/=_ @op= +_ @+$/$- -_ @+$/$- _+_ @+ _-_ @- _*_ @* _/_ @/ _\_ @\bs _\/_ @\bs/ _%_ @\% _^_ @\pow && @Boolean operators || @Boolean operators _&&_ @Boolean operators _||_ @Boolean operators !_ @Boolean operators < @Comparison _<_ @Comparison > @Comparison _>_ @Comparison >= @Comparison _>=_ @Comparison _<=_ @Comparison == @Equality !== @Equality <> @Equality _<>_ @Equality === @Equality _==_ @Equality _!=_ @Equality _===_ @Equality !== @Equality _!==_ @Equality _! @! _# @\# #_ @length .. @Row and column vectors@2 _.._ @Row and column vectors@2 [] @Row and column vectors@2 operator @GP operators@2 and @Boolean operators or @Boolean operators not @Boolean operators INT @Integers@2 integer @Integers@2 REAL @Real numbers@2 real number @Real numbers@2 INTMOD @Integermods@2 intmod @Integermods@2 FRAC @Rational numbers@2 fraction @Rational numbers@2 rational @Rational numbers@2 COMPLEX @Complex numbers@2 complex @Complex numbers@2 PADIC @$p$-adic numbers@2 padic @$p$-adic numbers@2 QUAD @Quadratic numbers@2 quadratic @Quadratic numbers@2 POLMOD @Polmods@2 polmod @Polmods@2 POL @Polynomials@2 polynomial @Polynomials@2 SER @Power series@2 RFRAC @Rational functions@2 QFR @Binary quadratic forms@2 QFI @Binary quadratic forms@2 QFB @Binary quadratic forms@2 VEC @Row and column vectors@2 COL @Row and column vectors@2 MAT @Matrices@2 LIST @Lists@2 STR @Strings@2 VECSMALL @Small vectors@2 ERROR @Error contexts@2 e_SYNTAX @iferr e_BUG @iferr e_ALARM @iferr e_FILE @iferr e_MISC @iferr e_FLAG @iferr e_IMPL @iferr e_ARCH @iferr e_PACKAGE @iferr e_NOTFUNC @iferr e_PREC @iferr e_TYPE @iferr e_DIM @iferr e_VAR @iferr e_PRIORITY @iferr e_USER @iferr e_STACK @iferr e_OVERFLOW @iferr e_DOMAIN @iferr e_COMPONENT @iferr e_MAXPRIME @iferr e_CONSTPOL @iferr e_IRREDPOL @iferr e_COPRIME @iferr e_PRIME @iferr e_MODULUS @iferr e_ROOTS0 @iferr e_OP @iferr e_TYPE2 @iferr e_INV @iferr e_MEM @iferr e_SQRTN @iferr local @Variables and Scope@2 my @Variables and Scope@2 user defined @User defined functions@2 user defined function @User defined functions@2 member function @Member functions@2 member @Member functions@2 \ @\bs \/ @\bs/ ^ @\pow ~ @mattranspose _~ @mattranspose ~_ @Call by value, call by reference@2 % @\% << @shift >> @shift emacs @Using GP under GNU Emacs@2 Emacs @Using GP under GNU Emacs@2 0 @Functions and Operations Available in PARI and GP 1 @Programming in GP: control statements 2 @Standard monadic or dyadic operators 3 @Conversions and similar elementary functions or commands 4 @Combinatorics 5 @Arithmetic functions 6 @Polynomials and power series 7 @Vectors, matrices, linear algebra and sets 8 @Transcendental functions 9 @Sums, products, integrals and similar functions 10 @General number fields 11 @Associative and central simple algebras 12 @Elliptic curves 13 @$L$-functions 14 @Hypergeometric Motives 15 @Modular forms 16 @Modular symbols 17 @Plotting functions ell @Elliptic curves mf @Modular forms nf @Number field structures bnf @Number field structures bnr @Number field structures rnf @Relative extensions hgm @Hypergeometric Motives HGM @Hypergeometric Motives ideal @Algebraic numbers and ideals idele @Algebraic numbers and ideals modulus @Class field theory CFT @Class field theory bid @Class field theory prototype @GP prototypes, parser codes@5 Lmath @Data structures describing $L$ and theta functions Ldata @Data structures describing $L$ and theta functions Linit @Data structures describing $L$ and theta functions L-function @Data structures describing $L$ and theta functions character @Dirichlet characters sums @Sums, products, integrals and similar functions products @Sums, products, integrals and similar functions integrals @Sums, products, integrals and similar functions gchar @Hecke Grossencharacters Grossencharacter @Hecke Grossencharacters grossencharacter @Hecke Grossencharacters pari-2.17.2/doc/refcard.tex0000644000175000017500000011503214676526175014106 0ustar billbill% Copyright (c) 2007-2024 Karim Belabas. % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License % Reference Card for PARI-GP. % Author: % Karim Belabas % Universite de Bordeaux, 351 avenue de la Liberation, F-33405 Talence % email: Karim.Belabas@math.u-bordeaux.fr % % Based on an earlier version by Joseph H. Silverman who kindly let me % use his original file. % Thanks to Bill Allombert, Henri Cohen, Gerhard Niklasch, and Joe Silverman % for comments and corrections. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % The original copyright notice read: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Copyright (c) 1993,1994 Joseph H. Silverman. May be freely distributed. %% Created Tuesday, July 27, 1993 %% Thanks to Stephen Gildea for the multicolumn macro package %% which I modified from his GNU emacs reference card %% %% Original Thanks: %% I would like to thank Jim Delaney, Kevin Buzzard, Dan Lieman, %% and Jaap Top for sending me corrections. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % This file is intended to be processed by plain TeX (TeX82). \def\TITLE{Pari-GP reference card} \input refmacro.tex Note: optional arguments are surrounded by braces $\{\}$.\hfill\break To start the calculator, type its name in the terminal: \kbd{gp}\hfill\break To exit \kbd{gp}, type \kbd{quit}, \kbd{\\q}, or \kbd{} at prompt.\hfill \section{Help} \li{describe function}{?{\it function}} \li{extended description}{??{\it keyword}} \li{list of relevant help topics}{???{\it pattern}} \li{name of GP-1.39 function $f$ in GP-2.*}{whatnow$(f)$} \section{Input/Output} \li{previous result, the result before} {\%{\rm, }\%\`{}{\rm, }\%\`{}\`{}{\rm, etc.}} \li{$n$-th result since startup}{\%$n$} \li{separate multiple statements on line}{;} \li{extend statement on additional lines}{\\} \li{extend statements on several lines}{\{$\seq_1$; $\seq_2$;\}} \li{comment}{/* $\dots$ */} \li{one-line comment, rest of line ignored}{\\\\ \dots} \section{Metacommands \& Defaults} \li{set default $d$ to \var{val}} {default$(\{d\},\{\var{val}\})$} \li{toggle timer on/off}{\#} \li{print time for last result}{\#\#} \li{print defaults}{\\d} \li{set debug level to $n$}{\\g $n$} \li{set memory debug level to $n$}{\\gm $n$} \li{set $n$ significant digits / bits}{\\p $n$, \\pb $n$} \li{set $n$ terms in series}{\\ps $n$} \li{quit GP}{\\q} \li{print the list of PARI types}{\\t} \li{print the list of user-defined functions}{\\u} \li{read file into GP}{\\r {\it filename}} \li{set debuglevel for domain $D$ to $n$}{setdebug$(D,n)$} \section{Debugger / break loop} \li{get out of break loop}{break {\rm or} } \li{go up/down $n$ frames}{dbg\_up$(\{n\})${\rm, }dbg\_down} \li{set break point}{breakpoint$()$} \li{examine object $o$}{dbg\_x$(o)$} \li{current error data}{dbg\_err$()$} \li{number of objects on heap and their size}{getheap$()$} \li{total size of objects on PARI stack}{getstack$()$} \section{PARI Types \& Input Formats} \li{\typ{INT}. Integers; hex, binary}{$\pm 31$; $\pm $0x1F, $\pm$0b101} \li{\typ{REAL}. Reals}{$\pm 3.14$, $6.022$ E$23$} \li{\typ{INTMOD}. Integers modulo $m$}{Mod$(n,m)$} \li{\typ{FRAC}. Rational Numbers}{$n/m$} \li{\typ{FFELT}. Elt in finite field $\FF_q$}{ffgen($q$,\text{'t})} \li{\typ{COMPLEX}. Complex Numbers}{$x +y\,*\;$I} \li{\typ{PADIC}. $p$-adic Numbers}{$x\;+\;$O$(p$\pow$k)$} \li{\typ{QUAD}. Quadratic Numbers}{$x + y\,*\;$quadgen($D$,\{'w\})} \li{\typ{POLMOD}. Polynomials modulo $g$}{Mod$(f,g)$} \li{\typ{POL}. Polynomials}{$a*x$\pow$n+\cdots+b$} \li{\typ{SER}. Power Series}{$f\;+\;$O$(x$\pow$k)$} \li{\typ{RFRAC}. Rational Functions}{$f/g$} \li{\typ{QFB}. Binary quadratic form}{Qfb$(a,b,c)$} \li{\typ{VEC}/\typ{COL}. Row/Column Vectors} {[$x,y,z$]{\rm, }[$x,y,z$]\til} \li{\typ{VEC} integer range}{[1..10]} % This goes at the bottom of page 1 \shortcopyrightnotice \newcolumn \li{\typ{VECSMALL}. Vector of small ints}{Vecsmall([$x,y,z$])} \li{\typ{MAT}. Matrices}{[$a,b$;$c,d$]} \li{\typ{LIST}. Lists}{List$($[$x,y,z$]$)$} \li{\typ{STR}. Strings}{"abc"} \li{\typ{INFINITY}. $\pm\infty$}{+oo, -oo} \section{Reserved Variable Names} \li{$\pi\approx3.14$, $\gamma\approx0.57$, $C\approx0.91$, $I = \sqrt{-1}$} {Pi{\rm, }Euler{\rm, }Catalan{\rm, }I} \li{Landau's big-oh notation}{O} \section{Information about an Object, Precision} \li{PARI type of object $x$}{type$(x)$} \li{length of $x$ / size of $x$ in memory}{\#$x${\rm, }sizebyte$(x)$} \li{real precision / bit precision of $x$}{precision$(x)${\rm, }bitprecision$(x)$} \li{$p$-adic, series prec. of $x$}{padicprec$(x,p)${\rm, }serprec$(x,v)$} \li{current dynamic precision}{getlocalprec{\rm, }getlocalbitprec} \section{Operators} \li{basic operations}{+{\rm,} - {\rm,} *{\rm,} /{\rm,} \pow{\rm,} sqr} \li{\kbd{i$\leftarrow$i+1}, \kbd{i$\leftarrow$i-1}, \kbd{i$\leftarrow$i*j}, \dots} {i++{\rm,} i--{\rm,} i*=j{\rm,}\dots} \li{Euclidean quotient, remainder}{$x$\bs/$y${\rm,} $x$\bs$y${\rm,} $x$\%$y${\rm,} divrem$(x,y)$} \li{shift $x$ left or right $n$ bits}{ $x$<<$n$, $x$>>$n$ {\rm or} shift$(x,\pm n)$} \li{multiply by $2^n$}{shiftmul$(x,n)$} \li{comparison operators} {<={\rm, }<{\rm, }>={\rm, }>{\rm, }=={\rm, }!={\rm, }==={\rm, }lex{\rm, }cmp} \li{boolean operators (or, and, not)}{||{\rm, } \&\&{\rm ,} !} \li{bit operations} {bitand{\rm, }bitneg{\rm, }bitor{\rm, }bitxor{\rm, }bitnegimply} \li{maximum/minimum of $x$ and $y$}{max$(x,y)${\rm,} min$(x,y)$} \li{sign of $x$ (gives $-1,0,1$)}{sign$(x)$} \li{binary exponent of $x$}{exponent$(x)$} \li{derivative of $f$, 2nd derivative, etc.}{$f$', $f$'', \dots} \li{differential operator}{diffop$(f,v,d,\{n=1\})$} \li{quote operator (formal variable)}{'x} \li{assignment}{x = \var{value}} \li{simultaneous assignment $x\leftarrow v[1]$, $y\leftarrow v[2]$}{[x,y] = v} \section{Select Components} \emph{Caveat:} components start at index $n = 1$.\hfil\break \li{$n$-th component of $x$}{component$(x,n)$} \li{$n$-th component of vector/list $x$}{$x$[$n$]} \li{components $a,a+1,\dots,b$ of vector $x$}{$x$[$a$..$b$]} \li{$(m,n)$-th component of matrix $x$}{$x$[$m,n$]} \li{row $m$ or column $n$ of matrix $x$}{$x$[$m,$]{\rm,} $x$[$,n$]} \li{numerator/denominator of $x$}{numerator$(x)${\rm, }denominator$(x)$} \section{Random Numbers} \li{random integer/prime in $[0,N[$}{random$(N)${\rm, }randomprime$(N)$} \li{get/set random seed}{getrand{\rm, }setrand$(s)$} \section{Conversions} \li{to vector, matrix, vec. of small ints}{Col{\rm/}Vec{\rm,}Mat{\rm,}Vecsmall} \li{to list, set, map, string}{List{\rm,} Set{\rm,} Map{\rm,} Str} \li{create $(x\mod y)$}{Mod$(x,y)$} \li{make $x$ a polynomial of $v$}{Pol$(x,\{v\})$} \li{variants of \kbd{Pol} \emph{et al.}, in reverse order} {Polrev{\rm, }Vecrev{\rm, }Colrev} \li{make $x$ a power series of $v$}{Ser$(x,\{v\})$} \li{convert $x$ to simplest possible type}{simplify$(x)$} \li{object $x$ with real precision $n$}{precision$(x,n)$} \li{object $x$ with bit precision $n$}{bitprecision$(x,n)$} \li{set precision to $p$ digits in dynamic scope}{localprec$(p)$} \li{set precision to $p$ bits in dynamic scope}{localbitprec$(p)$} \subsec{Character strings} \li{convert to TeX representation}{strtex$(x)$} \li{string from bytes / from format+args}{strchr{\rm, }strprintf} \li{split string / join strings}{strsplit{\rm, }strjoin} \li{convert time $t$ ms. to h, m, s, ms format}{strtime$(t)$} \subsec{Conjugates and Lifts} \li{conjugate of a number $x$}{conj$(x)$} \li{norm of $x$, product with conjugate}{norm$(x)$} \li{$L^p$ norm of $x$ ($L^\infty$ if no $p$)}{normlp$(x,\{p\})$} \li{square of $L^2$ norm of $x$}{norml2$(x)$} \li{lift of $x$ from Mods and $p$-adics}{lift{\rm,} centerlift$(x)$} \li{recursive lift}{liftall} \li{lift all \typ{INT} and \typ{PADIC} ($\to$\typ{INT})}{liftint} \li{lift all \typ{POLMOD} ($\to$\typ{POL})}{liftpol} \section{Lists, Sets \& Maps} {\bf Sets} (= row vector with strictly increasing entries w.r.t. \kbd{cmp})\hfill\break % \li{intersection of sets $x$ and $y$}{setintersect$(x,y)$} \li{set of elements in $x$ not belonging to $y$}{setminus$(x,y)$} \li{symmetric difference $x \Delta y$}{setdelta$(x,y)$} \li{union of sets $x$ and $y$}{setunion$(x,y)$} \li{does $y$ belong to the set $x$}{setsearch$(x,y,\{\fl\})$} \li{set of all $f(x,y)$, $x\in X$, $y\in Y$}{setbinop$(f,X,Y)$} \li{is $x$ a set ?}{setisset$(x)$} \subsec{Lists. {\rm create empty list: $L$ = \kbd{List}$()$}} \li{append $x$ to list $L$}{listput$(L,x,\{i\})$} \li{remove $i$-th component from list $L$}{listpop$(L,\{i\})$} \li{insert $x$ in list $L$ at position $i$}{listinsert$(L,x,i)$} \li{sort the list $L$ in place}{listsort$(L,\{\fl\})$} \subsec{Maps. {\rm create empty dictionary: $M$ = \kbd{Map}$()$}} \li{attach value $v$ to key $k$}{mapput$(M,k,v)$} \li{recover value attach to key $k$ or error}{mapget$(M,k)$} \li{is key $k$ in the dict? (set $v$ to $M(k)$)} {mapisdefined$(M,k,\{\&v\})$} \li{evaluate $f$ at $M(k)$}{mapapply$(M, k, f)$} \li{remove $k$ from map domain}{mapdelete$(M,k)$} \section{GP Programming} \subsec{User functions and closures} $x,y$ are formal parameters; $y$ defaults to \kbd{Pi} if parameter omitted; $z,t$ are local variables (lexical scope), $z$ initialized to 1. \hfil\break {\tt fun(x, y=Pi) = my(z=1, t); \var{seq}\hfil\break} {\tt fun = (x, y=Pi) -> my(z=1, t); \var{seq}\hfill\break} \li{attach help message $h$ to $s$}{addhelp$(s,h)$} \li{undefine symbol $s$ (also kills help)}{kill$(s)$} \subsec{Control Statements {\rm ($X$: formal parameter in expression \seq)}} \li{if $a\ne0$, evaluate $\seq_1$, else $\seq_2$}{if$(a,\{\seq_1\},\{\seq_2\})$} \smallskip \li{eval.\ \seq\ for $a\le X\le b$}{for$(X=a,b,\seq)$} \li{\dots for $X\in v$}{foreach$(v,X,\seq)$} \li{\dots for primes $a\le X\le b$}{forprime$(X=a,b,\seq)$} \li{\dots for primes $\equiv a \pmod{q}$}{forprimestep$(X=a,b,q,\seq)$} \li{\dots for composites $a\le X\le b$}{forcomposite$(X=a,b,\seq)$} \li{\dots for $a\le X\le b$ stepping $s$}{forstep$(X=a,b,s,\seq)$} \li{\dots for $X$ dividing $n$}{fordiv$(n,X,\seq)$} \li{\dots $X=[n,\kbd{factor}(n)]$, $a\le n\le b$}{forfactored$(X=a,b,\seq)$} \li{\dots as above, $n$ squarefree}{forsquarefree$(X=a,b,\seq)$} \li{\dots $X=[d,\kbd{factor}(d)]$, $d\mid n$}{fordivfactored$(n,X,\seq)$} \li{multivariable {\tt for}, lex ordering}{forvec$(X=v,\seq)$} \newcolumn \li{loop over partitions of $n$}{forpart$(p=n,\seq)$} \li{\dots permutations of $S$}{forperm$(S, p,\seq)$} \li{\dots subsets of $\{1,\ldots,n\}$}{forsubset$(n, p,\seq)$} \li{\dots $k$-subsets of $\{1,\ldots,n\}$}{forsubset$([n,k], p,\seq)$} \li{\dots vectors $v$, $q(v)\leq B$; $q > 0$}{forqfvec$(v, q, b, \seq)$} \li{\dots $H < G$ finite abelian group}{forsubgroup$(H=G)$} \li{evaluate \seq\ until $a\ne0$}{until$(a,\seq)$} \li{while $a\ne0$, evaluate \seq}{while$(a,\seq)$} \li{exit $n$ innermost enclosing loops}{break$(\{n\})$} \li{start new iteration of $n$-th enclosing loop}{next$(\{n\})$} \li{return $x$ from current subroutine}{return$(\{x\})$} \subsec{Exceptions, warnings} \li{raise an exception / warning}{error$()$, warning$()$} \li{type of error message $E$}{errname$(E)$} \li{try $\seq_1$, evaluate $\seq_2$ on error}{iferr$(\seq_1, E, \seq_2)$} \subsec{Functions with closure arguments / results} \li{number of arguments of $f$}{arity$(f)$} \li{select from $v$ according to $f$}{select$(f, v)$} \li{apply $f$ to all entries in $v$}{apply$(f, v)$} \li{evaluate $f(a_1,\dots,a_n)$}{call$(f,a)$} \li{evaluate $f(\dots f(f(a_1,a_2),a_3)\dots,a_n)$}{fold$(f,a)$} \li{calling function as closure}{self$()$} \subsec{Sums \& Products} \li{sum $X=a$ to $X=b$, initialized at $x$}{sum$(X=a,b,\expr,\{x\})$} \li{sum entries of vector $v$}{vecsum$(v)$} \li{product of all vector entries}{vecprod$(v)$} \li{sum \expr\ over divisors of $n$}{sumdiv$(n,X,\expr)$} \li{\dots assuming \expr\ multiplicative}{sumdivmult$(n,X,\expr)$} \li{product $a\le X\le b$, initialized at $x$}{prod$(X=a,b,\expr,\{x\})$} \li{product over primes $a\le X\le b$}{prodeuler$(X=a,b,\expr)$} \subsec{Sorting} \li{sort $x$ by $k$-th component}{vecsort$(x,\{k\},\{fl=0\})$} \li{min.~$m$ of $x$ ($m=x[i]$), max.}{vecmin$(x,\{\&i\})${\rm, }vecmax} \li{does $y$ belong to $x$, sorted wrt. $f$}{vecsearch$(x,y,\{f\})$} \li{$\prod g^x \rightarrow$ factorization ($\Rightarrow$ sorted, unique $g$)} {matreduce$(m)$} % \subsec{Input/Output} \li{print with/without \kbd{\bs n}, \TeX\ format} {print{\rm, }print1{\rm, }printtex} \li{pretty print matrix}{printp} \li{print fields with separator}{printsep$(\var{sep},\dots)$,{\rm, }printsep1} \li{formatted printing}{printf$()$} \li{write \args\ to file}{write{\rm,} write1{\rm,} writetex$(\file,\args)$} \li{write $x$ in binary format}{writebin$(\file,x)$} \li{read file into GP}{read($\{\file\}$)} \li{\dots return as vector of lines}{readvec($\{\file\}$)} \li{\dots return as vector of strings}{readstr($\{\file\}$)} \li{read a string from keyboard}{input$()$} \subsec{Files and file descriptors} File descriptors allow efficient small consecutive reads or writes from or to a given file. The argument $n$ below is always a descriptor, attached to a file in \kbd{r}(ead), \kbd{w}(rite) or \kbd{a}(ppend) mode.\hfil\break \li{get descriptor $n$ for file \var{path} in given \var{mode}} {fileopen$(\var{path},\var{mode})$} \li{\dots from shell \var{cmd} output (pipe)}{fileextern$(\var{cmd})$} \smallskip \li{close descriptor}{fileclose$(n)$} \li{commit pending write operations}{fileflush($n$)} \li{read logical line from file}{fileread$(n)$} \li{\dots raw line from file}{filereadstr$(n)$} \li{write $s$\kbd{\bs n} to file}{filewrite$(n, s)$} \li{\dots write $s$ to file}{filewrite1$(n, s)$} \newcolumn \title{\TITLE} \centerline{(PARI-GP version \PARIversion)} \subsec{Timers} \li{CPU time in \var{ms} and reset timer}{gettime$()$} \li{CPU time in \var{ms} since gp startup}{getabstime$()$} \li{time in \var{ms} since UNIX Epoch}{getwalltime$()$} \li{timeout command after $s$ seconds}{alarm$(s, \expr)$} \subsec{Interface with system} \li{allocates a new stack of $s$ bytes}{allocatemem$(\{s\})$} \li{alias \var{old}\ to \var{new}}{alias$(\var{new},\var{old})$} \li{install function from library}{install$(f,code,\{\var{gpf\/}\},\{\var{lib}\})$} \li{execute system command $a$}{system$(a)$} \li{\dots and feed result to GP}{extern$(a)$} \li{\dots returning GP string}{externstr$(a)$} \li{get \kbd{\$VAR} from environment}{getenv$($\kbd{"VAR"}$)$} \li{expand env. variable in string}{strexpand$(x)$} \section{Parallel evaluation} These functions evaluate their arguments in parallel (pthreads or MPI); args.~must not access global variables (use \kbd{export} for this) and must be free of side effects. Enabled if threading engine is not \emph{single} in gp header.\hfil\break \li{evaluate $f$ on $x[1],\dots,x[n]$}{parapply$(f,x)$} \li{evaluate closures $f[1],\dots,f[n]$}{pareval$(f)$} \li{as \kbd{select}}{parselect$(f,A,\{\fl\})$} \li{as \kbd{sum}}{parsum$(i = a,b,\var{expr})$} \li{as \kbd{vector}}{parvector$(n,i,\{\var{expr}\})$} \li{eval $f$ for $i=a,\dots,b$} {parfor$(i = a, \{b\}, f,\{r\}, \{f_2\})$} \li{\dots for each element $x$ in $v$} {parforeach$(v, x, f,\{r\}, \{f_2\})$} \li{\dots for $p$ prime in $[a,b]$} {parforprime$(p = a, \{b\}, f,\{r\}, \{f_2\})$} \li{\dots for $p = a \mod q$} {parforprimestep$(p = a, \{b\}, q, f,\{r\}, \{f_2\})$} \li{\dots for $i=a, a+s, \dots,b$} {parforstep$(i = a, \{b\}, s, f,\{r\}, \{f_2\})$} \li{\dots multivariate} {parforvec$(X = v, f,\{r\}, \{f_2\}, \{\fl\})$} \li{export $x$ to parallel world}{export$(x)$} \li{\dots all dynamic variables}{exportall$()$} \li{frees exported value $x$}{unexport$(x)$} \li{\dots all exported values}{unexportall$()$} \section{Linear Algebra} % \li{dimensions of matrix $x$}{matsize$(x)$} \li{multiply two matrices}{$x$ * $y$} \li{\dots assuming result is diagonal}{matmultodiagonal$(x,y)$} \li{concatenation of $x$ and $y$}{concat$(x,\{y\})$} \li{extract components of $x$}{vecextract$(x,y,\{z\})$} \li{transpose of vector or matrix $x$}{$x$\til, mattranspose$(x)$} \li{adjoint of the matrix $x$}{matadjoint$(x)$} \li{eigenvectors/values of matrix $x$}{mateigen$(x)$} \li{characteristic/minimal polynomial of $x$}{charpoly$(x)${\rm, }minpoly$(x)$} \li{trace/determinant of matrix $x$}{trace$(x)${\rm, }matdet$(x)$} \li{permanent of matrix $x$}{matpermanent$(x)$} \li{Frobenius form of $x$}{matfrobenius$(x)$} \li{QR decomposition}{matqr$(x)$} \li{apply \kbd{matqr}'s transform to $v$}{mathouseholder$(Q,v)$} \subsec{Constructors \& Special Matrices} \li{$\{g(x)\colon x \in v~{\rm s.t.}~f(x)\}$}{[g(x) | x <- v, f(x)]} \li{$\{x\colon x \in v~{\rm s.t.}~f(x)\}$}{[x | x <- v, f(x)]} \li{$\{g(x)\colon x \in v\}$}{[g(x) | x <- v]} \li{row vec.\ of \expr\ eval'ed at $1\le i\le n$}{vector$(n,\{i\},\{\expr\})$} \li{col.\ vec.\ of \expr\ eval'ed at $1\le i\le n$}{vectorv$(n,\{i\},\{\expr\})$} \li{vector of small ints}{vectorsmall$(n,\{i\},\{\expr\})$} \newcolumn \li{$[c, c\cdot x, \dots, c\cdot x^n]$}{powers$(x,n,\{c = 1\})$} \li{$[1, 2^x, \dots, n^x]$}{dirpowers$(n,x)$} \li{matrix $1\le i\le m$, $1\le j\le n$}{matrix$(m,n,\{i\},\{j\},\{\expr\})$} \li{define matrix by blocks}{matconcat$(B)$} \li{diagonal matrix with diagonal $x$}{matdiagonal$(x)$} \li{is $x$ diagonal?}{matisdiagonal$(x)$} \li{$x\,\cdot\, $\kbd{matdiagonal}$(d)$}{matmuldiagonal$(x,d)$} \li{$n\times n$ identity matrix}{matid$(n)$} \li{Hessenberg form of square matrix $x$}{mathess$(x)$} \li{$n\times n$ Hilbert matrix $H_{ij}=(i+j-1)^{-1}$}{mathilbert$(n)$} \li{$n\times n$ Pascal triangle}{matpascal$(n-1)$} \li{companion matrix to polynomial $x$}{matcompanion$(x)$} \li{Sylvester matrix of $x$ and $y$}{polsylvestermatrix$(x,y)$} \subsec{Gaussian elimination} \li{kernel of matrix $x$}{matker$(x,\{\fl\})$} \li{intersection of column spaces of $x$ and $y$}{matintersect$(x,y)$} \li{solve $MX = B$ ($M$ invertible)}{matsolve$(M,B)$} \li{one sol of $M*X = B$}{matinverseimage$(M,B)$} \li{basis for image of matrix $x$}{matimage$(x)$} \li{columns of $x$ \emph{not} in \kbd{matimage}}{matimagecompl$(x)$} \li{supplement columns of $x$ to get basis}{matsupplement$(x)$} \li{rows, cols to extract invertible matrix}{matindexrank$(x)$} \li{rank of the matrix $x$}{matrank$(x)$} \li{solve $MX = B$ mod $D$}{matsolvemod$(M,D,B)$} \li{image mod $D$}{matimagemod$(M,D)$} \li{kernel mod $D$}{matkermod$(M,D)$} \li{inverse mod $D$}{matinvmod$(M,D)$} \li{determinant mod $D$}{matdetmod$(M,D)$} \section{Lattices \& Quadratic Forms} \subsec{Quadratic forms} \li{evaluate $^tx Q y$}{qfeval$(\{Q=\var{id}\},x,y)$} \li{evaluate $^tx Q x$}{qfeval$(\{Q=\var{id}\},x)$} \li{signature of quad form $^ty*x*y$}{qfsign$(x)$} \li{decomp into squares of $^ty*x*y$}{qfgaussred$(x)$} \li{eigenvalues/vectors for real symmetric $x$}{qfjacobi$(x)$} \li{Cholesky decomposition of $x$}{qfcholesky$(x)$} \subsec{HNF and SNF} \li{upper triangular Hermite Normal Form}{mathnf$(x)$} \li{HNF of $x$ where $d$ is a multiple of det$(x)$}{mathnfmod$(x,d)$} \li{multiple of det$(x)$}{matdetint$(x)$} \li{HNF of $(x \mid\,$\kbd{diagonal}$(D))$}{mathnfmodid$(x,D)$} \li{elementary divisors of $x$}{matsnf$(x)$} \li{$q$-rank from elementary divisors}{snfrank$(v,q)$} \li{elementary divisors of $\ZZ[a]/(f'(a))$}{poldiscreduced$(f)$} \li{integer kernel of $x$}{matkerint$(x)$} \li{$\ZZ$-module $\leftrightarrow$ $\QQ$-vector space}{matrixqz$(x,p)$} \subsec{Lattices} \li{LLL-algorithm applied to columns of $x$}{qflll$(x,\{\fl\})$} \li{\dots for Gram matrix of lattice}{qflllgram$(x,\{\fl\})$} \li{find up to $m$ sols of \kbd{qfeval}$(x,y)\le b$}{qfminim$(x,b,m)$} \li{\dots up to $m$ closest vectors to $t$}{qfcvp$(x,t,m)$} \li{$v$, $v[i]:=$number of $y$ s.t. \kbd{qfeval}$(x,y)= i$} {qfrep$(x,B,\{\fl\})$} \li{perfection rank of $x$}{qfperfection$(x)$} \li{find isomorphism between $q$ and $Q$}{qfisom$(q,Q)$} \copyrightnotice \newcolumn \li{precompute for isomorphism test with $q$}{qfisominit$(q)$} \li{automorphism group of $q$}{qfauto$(q)$} \li{convert \kbd{qfauto} for GAP/Magma}{qfautoexport$(G,\{\fl\})$} \li{orbits of $V$ under $G\subset \text{GL}(V)$} {qforbits$(G,V)$} \section{Polynomials \& Rational Functions} \li{all defined polynomial variables}{variables$()$} \li{get var.~of highest priority (higher than $v$)} {varhigher$(\var{name},\{v\})$} \li{\dots of lowest priority (lower than $v$)} {varlower$(\var{name},\{v\})$} \subsec{Coefficients, variables and basic operators} \li{degree of $f$}{poldegree$(f)$} \li{coef. of degree $n$ of $f$, leading coef.}{polcoef$(f,n)${\rm, }pollead} \li{main variable / all variables in $f$}{variable$(f)${\rm, }variables$(f)$} \li{replace $x$ by $y$ in $f$}{subst$(f,x,y)$} \li{evaluate $f$ replacing vars by their value}{eval$(f)$} \li{replace polynomial expr.~$T(x)$ by $y$ in $f$}{substpol$(f,T,y)$} \li{replace $x_1,\dots,x_n$ by $y_1,\dots,y_n$ in $f$}{substvec$(f,x,y)$} \li{$f\in A[x]$; reciprocal polynomial $x^{\deg f}f\big({1\over x}\big)$} {polrecip$(f)$} \li{gcd of coefficients of $f$}{content$(f)$} \li{derivative of $f$ w.r.t. $x$}{deriv$(f,\{x\})$} \li{\dots $n$-th derivative of $f$}{derivn$(f,n,\{x\})$} \li{formal integral of $f$ w.r.t. $x$}{intformal$(f,\{x\})$} \li{formal sum of $f$ w.r.t. $x$}{sumformal$(f,\{x\})$} \subsec{Constructors \& Special Polynomials} interpolation polynomial at $(x[1],y[1]),\dots, (x[n],y[n])$, evaluated at $t$, with error estimate $e$ \hfil \kbd{polinterpolate}$(x,\{y\},\{t\},\{\&e\})$\break \li{monic polynomial from roots $r$}{polfromroots$(r)$} \li{$T_n/U_n$, $H_n$}{polchebyshev$(n)${\rm, }polhermite$(n)$} \li{$P_n$, $L_n^{(\alpha)}$}{pollegendre$(n)${\rm, }pollaguerre$(n,a)$} \li{$n$-th cyclotomic polynomial $\Phi_n$}{polcyclo$(n)$} \li{return $n$ if $f=\Phi_n$, else $0$}{poliscyclo$(f)$} \li{is $f$ a product of cyclotomic polynomials?}{poliscycloprod$(f)$} \li{Zagier's polynomial of index $(n,m)$}{polzagier$(n,m)$} \subsec{Resultant, elimination} \li{discriminant of polynomial $f$}{poldisc$(f)$} \li{find factors of \kbd{poldisc}$(f)$}{poldiscfactors$(f)$} \li{resultant $R = \text{Res}_v(f,g)$}{polresultant$(f,g,\{v\})$} \li{$[u,v,R]$, $xu + yv = \text{Res}_v(f,g)$}{polresultantext$(x,y,\{v\})$} \li{solve Thue equation $f(x,y)=a$}{thue$(t,a,\{sol\})$} \li{initialize $t$ for Thue equation solver}{thueinit$(f)$} \subsec{Roots and Factorization (Complex/Real)} \li{complex roots of $f$}{polroots$(f)$} \li{bound complex roots of $f$}{polrootsbound$(f)$} \li{number of real roots of $f$ (in $[a,b]$)}{polsturm$(f,\{[a,b]\})$} \li{real roots of $f$ (in $[a,b]$)}{polrootsreal$(f,\{[a,b]\})$} \li{complex embeddings of \typ{POLMOD} $z$}{conjvec$(z)$} \subsec{Roots and Factorization (Finite fields)} \li{factor $f\mod p$, roots}{factormod$(f,p)${\rm, }polrootsmod} \li{factor $f$ over $\FF_p[x]/(T)$, roots}{factormod$(f,[T,p])${\rm, }polrootsmod} \li{squarefree factorization of $f$ in $\FF_q[x]$}{factormodSQF$(f,\{D\})$} \li{distinct degree factorization of $f$ in $\FF_q[x]$}{factormodDDF$(f,\{D\})$} \li{factor $n$-th cyclotomic pol. $\Phi_n$ mod $p$}{factormodcyclo$(n,p)$} \subsec{Roots and Factorization ($p$-adic fields)} \li{factor $f$ over $\QQ_p$, roots}{factorpadic$(f,p,r)${\rm, }polrootspadic} \li{$p$-adic root of $f$ congruent to $a\mod p$}{padicappr$(f,a)$} \li{Newton polygon of $f$ for prime $p$}{newtonpoly$(f,p)$} \li{Hensel lift $A/\text{lc}(A) = \prod_i B[i]$ mod $p^e$} {polhensellift$(A,B,p,e)$} \shortcopyrightnotice \newcolumn \title{\TITLE} \centerline{(PARI-GP version \PARIversion)} \bigskip \li{$T = \prod (x - z_i)\mapsto \prod (x - \omega(z_i))] \in \ZZ_p[x]$} {polteichmuller$(T,p,e)$} \li{extensions of $\QQ_p$ of degree $N$}{padicfields$(p,N)$} \subsec{Roots and Factorization (Miscellaneous)} \li{symmetric powers of roots of $f$ up to $n$}{polsym$(f,n)$} \li{Graeffe transform of $f$, $g(x^2)=f(x)f(-x)$}{polgraeffe$(f)$} \li{factor $f$ over coefficient field}{factor$(f)$} \li{cyclotomic factors of $f\in\QQ[X]$}{polcyclofactors$(f)$} \section{Finite Fields} A finite field is encoded by any element (\typ{FFELT}).\hfil\break \li{find irreducible $T\in \FF_p[x]$, $\deg T = n$}{ffinit$(p,n,\{x\})$} \li{Create $t$ in $\FF_q\simeq\FF_p[t]/(T)$}{t = ffgen($T$,'t)} \li{\dots indirectly, with implicit $T$}{t = ffgen($q$,'t); T = t.mod} \li{map $m$ from $\FF_q\ni a$ to $\FF_{q^k} \ni b$}{m = ffembed$(a,b)$} \li{build $K=\FF_q[x]/(P)$ extending $\FF_q\ni a$, }{ffextend$(a, P)$} \li{evaluate map $m$ on $x$}{ffmap$(m,x)$} \li{inverse map of $m$}{ffinvmap$(m)$} \li{compose maps $m \circ n$}{ffcompomap$(m,n)$} \li{$x$ as polmod over codomain of map $m$}{ffmaprel$(m,x)$} \li{$F^n$ over $\FF_q\ni a$}{fffrobenius$(a,n)$} \li{$\#\{{\rm monic\ irred.}\ T\in \FF_q[x], \deg T = n\}$}{ffnbirred$(q,n)$} \section{Formal \& p-adic Series} \li{truncate power series or $p$-adic number}{truncate$(x)$} \li{valuation of $x$ at $p$}{valuation$(x,p)$} \subsec{Dirichlet and Power Series} \li{Taylor expansion around $0$ of $f$ w.r.t. $x$}{taylor$(f,x)$} \li{Laurent series of closure $F$ up to $x^k$}{laurentseries$(f,k)$} \li{$\sum a_kb_k t^k$ from $\sum a_kt^k$ and $\sum b_kt^k$}{serconvol$(a,b)$} \li{$f=\sum a_k t^k$ from $\sum (a_k/k!)t^k$}{serlaplace$(f)$} \li{reverse power series $F$ so $F(f(x))=x$}{serreverse$(f)$} \li{remove terms of degree $ 0$} \li{slow decrease $|x|^{\alpha}$}{$\dots \alpha < -1$} \li{oscillating as $\cos(kx))$}{$\alpha = k$\kbd{I}, $k > 0$} \li{oscillating as $\sin(kx))$}{$\alpha = -k$\kbd{I}, $k > 0$} \endindentedkeys \li{numerical integration}{intnum$(x=a,b,f,\{T\})$} \li{weights $T$ for \kbd{intnum}}{intnuminit$(a,b,\{m\})$} \li{weights $T$ incl.~kernel $K$}{intfuncinit$(t=a,b,K,\{m\})$} \li{integrate $(2i\pi)^{-1}f$ on circle $|z - a| = R$} {intcirc$(x=a,R,f,\{T\})$} \subsec{Other integration methods} \li{$n$-point Gauss-Legendre}{intnumgauss$(x=a,b,f,\{n\})$} \li{weights for $n$-point Gauss-Legendre}{intnumgaussinit$(\{n\})$} \li{quasi-periodic function, period $2H$}{intnumosc$(x=a,f,H)$} \li{Romberg (low accuracy)}{intnumromb$(x=a,b,f,\{\fl\})$} \subsec{Numerical summation} \li{sum of series $f(n)$, $n\geq a$ (low accuracy)}{suminf$(n=a,\expr)$} \li{sum of alternating/positive series}{sumalt{\rm,} sumpos} \li{sum of series using Euler-Maclaurin}{sumnum$(n=a,f,\{T\})$} \li{\dots Sidi summation}{sumnumsidi$(n=a,f)$} \li{$\sum_{n\geq a} F(n)$, $F$ rational function}{sumnumrat$(F,a)$} \li{\dots $\sum_{p\geq a} F(p^s)$}{sumeulerrat$(F, \{s = 1\}, \{a = 2\})$} \li{weights for \kbd{sumnum}, $a$ as in DE} {sumnuminit$(\{\infty, a\})$} \li{sum of series by Monien summation}{sumnummonien$(n=a,f,\{T\})$} \li{weights for \kbd{sumnummonien}} {sumnummonieninit$(\{\infty, a\})$} \li{sum of series using Abel-Plana}{sumnumap$(n=a,f,\{T\})$} \li{weights for \kbd{sumnumap}, $a$ as in DE} {sumnumapinit$(\{\infty, a\})$} \li{sum of series using Lagrange}{sumnumlagrange$(n=a,f,\{T\})$} \li{weights for \kbd{sumnumlagrange}} {sumnumlagrangeinit} \subsec{Products} \li{product $a\le X\le b$, initialized at $x$}{prod$(X=a,b,\expr,\{x\})$} \li{product over primes $a\le X\le b$}{prodeuler$(X=a,b,\expr)$} \li{infinite product $a\le X\le\infty$}{prodinf$(X=a,\expr)$} \li{$\prod_{n\geq a} F(n)$, $F$ rational function}{prodnumrat$(F,a)$} \li{$\prod_{p\geq a} F(p^s)$}{prodeulerrat$(F,\{s=1\},\{a=2\})$} \subsec{Other numerical methods} \li{real root of $f$ in $[a,b]$; bracketed root}{solve$(X=a,b,f)$} \li{\dots interval splitting, step $s$}{solvestep$(X=a,b,s,f,\{\fl=0\})$} \li{limit of $f(t)$, $t\to\infty$}{limitnum(f, \{alpha\})} \li{asymptotic expansion of $f$ (rational)}{asympnum(f, \{alpha\})} \li{\dots $N+1$ terms as floats}{asympnumraw(f, N, \{alpha\})} \li{numerical derivation w.r.t $x$: $f'(a)$}{derivnum$(x=a, f)$} \li{evaluate continued fraction $F$ at $t$} {contfraceval$(F,t,\{L\})$} \li{power series to cont.~fraction ($L$ terms)} {contfracinit$(S,\{L\})$} \li{Pad\'{e} approximant (deg.~denom.~$\leq B$)}{bestapprPade$(S,\{B\})$} \section{Elementary Arithmetic Functions} \li{vector of binary digits of $|x|$}{binary$(x)$} \li{bit number $n$ of integer $x$}{bittest$(x,n)$} \li{Hamming weight of integer $x$}{hammingweight$(x)$} \li{digits of integer $x$ in base $B$}{digits$(x,\{B=10\})$} \li{sum of digits of integer $x$ in base $B$}{sumdigits$(x,\{B=10\})$} \li{integer from digits}{fromdigits$(v,\{B=10\})$} \li{ceiling/floor/fractional part}{ceil{\rm, }floor{\rm, }frac} \li{round $x$ to nearest integer}{round$(x,\{$\&$e\})$} \li{truncate $x$}{truncate$(x,\{$\&$e\})$} \li{gcd/LCM of $x$ and $y$}{gcd$(x,y)$, lcm$(x,y)$} \li{gcd of entries of a vector/matrix}{content$(x)$} \subsec{Primes and Factorization} \li{extra prime table}{addprimes$()$} \li{add primes in $v$ to prime table}{addprimes$(v)$} \li{remove primes from prime table}{removeprimes$(v)$} \li{Chebyshev $\pi(x)$, $n$-th prime $p_n$}{primepi$(x)$, prime$(n)$} \li{vector of first $n$ primes}{primes$(n)$} \li{smallest prime $\ge x$}{nextprime$(x)$} \li{largest prime $\le x$}{precprime$(x)$} \li{factorization of $x$}{factor$(x,\{lim\})$} \li{\dots selecting specific algorithms}{factorint$(x,\{\fl=0\})$} \li{$n=df^2$, $d$ squarefree/fundamental}{core$(n,\{fl\})${\rm, }coredisc} \li{certificate for (prime) $N$}{primecert$(N)$} \li{verifies a certificate $c$}{primecertisvalid$(c)$} \li{convert certificate to Magma/PRIMO}{primecertexport} \li{recover $x$ from its factorization}{factorback$(f,\{e\})$} \li{$x\in\ZZ$, $|x|\leq X$, $\gcd(N,P(x)) \geq N$} {zncoppersmith$(P,N,X,\{B\})$} \li{divisors of $N$ in residue class $r \mod{s}$}{divisorslenstra$(N,r,s)$} \subsec{Divisors and multiplicative functions} \li{number of prime divisors $\omega(n)$ / $\Omega(n)$} {omega$(n)${\rm, }bigomega} \li{divisors of $n$ / number of divisors $\tau(n)$}{divisors$(n)${\rm, }numdiv} \li{sum of ($k$-th powers of) divisors of $n$}{sigma$(n,\{k\})$} \li{M\"obius $\mu$-function}{moebius$(x)$} \li{Ramanujan's $\tau$-function}{ramanujantau$(x)$} \subsec{Combinatorics} \li{factorial of $x$}{$x$!~{\rm or} factorial$(x)$} \li{binomial coefficient $x\choose k$}{binomial$(x,\{k\})$} \li{Bernoulli number $B_n$ as real/rational}{bernreal$(n)${\rm, }bernfrac} \li{$[B_0,B_2,\dots B_{2k}]$}{bernvec$(k)$} \li{Bernoulli polynomial $B_n(x)$}{bernpol$(n,\{x\})$} \li{Euler numbers}{eulerfrac{\rm, }eulerreal{\rm, }eulervec} \li{Euler polynomial $E_n(x)$}{eulerpol$(n,\{x\})$} \li{Eulerian polynomial $A_n(x)$}{eulerianpol} \li{Fibonacci number $F_n$}{fibonacci$(n)$} \li{Harmonic number $H_{n,r}=1^{-r}+\dots+n^{-r}$}{harmonic$(n, r)$} \li{Stirling numbers $s(n,k)$ and $S(n,k)$}{stirling$(n,k,\{\fl\})$} \newcolumn \title{\TITLE} \centerline{(PARI-GP version \PARIversion)} \bigskip \li{number of partitions of $n$}{numbpart$(n)$} \li{$k$-th permutation on $n$ letters}{numtoperm$(n,k)$} \li{\dots index $k$ of permutation $v$}{permtonum$(v)$} \li{order of permutation $p$}{permorder$(p)$} \li{signature of permutation $p$}{permsign$(p)$} \li{cyclic decomposition of permutation $p$}{permcycles$(p)$} \subsec{Multiplicative groups $(\ZZ/N\ZZ)^*$, $\FF_q^*$} \li{Euler $\phi$-function}{eulerphi$(x)$} \li{multiplicative order of $x$ (divides $o$)}{znorder$(x,\{o\})${\rm, }fforder} \li{primitive root mod $q$ / $x$\kbd{.mod}}{znprimroot$(q)${\rm, }ffprimroot$(x)$} \li{structure of $(\ZZ/n\ZZ)^*$}{znstar$(n)$} \li{discrete logarithm of $x$ in base $g$}{znlog$(x,g,\{o\})${\rm, }fflog} \li{Kronecker-Legendre symbol $({x\over y})$}{kronecker$(x,y)$} \li{quadratic Hilbert symbol (at $p$)}{hilbert$(x,y,\{p\})$} \subsec{Euclidean algorithm, continued fractions} \li{CRT: solve $z\equiv x$ and $z\equiv y$}{chinese$(x,y)$} \li{minimal $u,v$ so $xu+yv=\gcd(x,y)$}{gcdext$(x,y)$} \li{half-gcd algorithm}{halfgcd$(x,y)$} \li{continued fraction of $x$}{contfrac$(x,\{b\},\{lmax\})$} \li{last convergent of continued fraction $x$}{contfracpnqn$(x)$} \li{rational approximation to $x$ (den. $\leq B$)}{bestappr$(x,\{B\})$} \li{recognize $x\in\CC$ as polmod mod $T\in\ZZ[X]$}{bestapprnf$(x,T)$} \subsec{Miscellaneous} \li{integer square / $n$-th root of $x$}{sqrtint$(x)$, sqrtnint$(x,n)$} \li{largest integer $e$ s.t. $b^e \leq b$, $e = \lfloor \log_b(x)\rfloor$} {logint$(x,b,\{\&z\})$} \section{Characters} Let \var{cyc} $=[d_1,\dots,d_k]$ represent an abelian group $G = \oplus (\ZZ/d_j\ZZ)\cdot g_j$ or any structure $G$ affording a \kbd{.cyc} method; e.g. \kbd{znstar}$(q,1)$ for Dirichlet characters. A character $\chi$ is coded by $[c_1,\dots,c_k]$ such that $\chi(g_j) = e(n_j/d_j)$. \hfil\break \li{$\chi\cdot \psi$; $\chi^{-1}$; $\chi\cdot \psi^{-1}$; $\chi^k$} {charmul{\rm, }charconj{\rm, }chardiv{\rm, }charpow} \li{order of $\chi$}{charorder$(\var{cyc}, \chi)$} \li{kernel of $\chi$}{charker$(\var{cyc},\chi)$} \li{$\chi(x)$, $G$ a GP group structure}{chareval$(G, \chi, x, \{z\})$} \li{Galois orbits of characters}{chargalois$(G)$} \subsec{Dirichlet Characters} \li{initialize $G = (\ZZ/q\ZZ)^*$}{G = znstar$(q,1)$} \li{convert datum $D$ to $[G,\chi]$}{znchar$(D)$} \li{is $\chi$ odd?}{zncharisodd$(G,\chi)$} \li{real $\chi \to $ Kronecker symbol $(D/.)$}{znchartokronecker$(G,\chi)$} \li{conductor of $\chi$}{zncharconductor$(G,\chi)$} \li{$[G_0,\chi_0]$ primitive attached to $\chi$}{znchartoprimitive$(G,\chi)$} \li{induce $\chi\in \hat{G}$ to $\ZZ/N\ZZ$}{zncharinduce$(G,\chi,N)$} \li{$\chi_p$}{znchardecompose$(G,\chi, p)$} \li{$\prod_{p\mid (Q,N)} \chi_p$}{znchardecompose$(G,\chi, Q)$} \li{complex Gauss sum $G_a(\chi)$}{znchargauss$(G,\chi)$} \subsec{Conrey labelling} \li{Conrey label $m\in (\ZZ/q\ZZ)^* \to\;$ character}{znconreychar$(G,m)$} \li{character $\to$ Conrey label}{znconreyexp$(G,\chi)$} \li{log on Conrey generators}{znconreylog$(G, m)$} \li{conductor of $\chi$ ($\chi_0$ primitive)} {znconreyconductor$(G,\chi, \{\chi_0\})$} \section{True-False Tests} \li{is $x$ the disc. of a quadratic field?}{isfundamental$(x)$} \li{is $x$ a prime?}{isprime$(x)$} \li{is $x$ a strong pseudo-prime?}{ispseudoprime$(x)$} \li{is $x$ square-free?}{issquarefree$(x)$} \li{is $x$ a square?}{issquare$(x,\{\&n\})$} \li{is $x$ a perfect power?}{ispower$(x,\{k\},\{\&n\})$} \li{is $x$ a perfect power of a prime? ($x=p^n$)}{isprimepower$(x,\&n\})$} \li{\dots of a pseudoprime?}{ispseudoprimepower$(x,\&n\})$} \li{is $x$ powerful?}{ispowerful$(x)$} \li{is $x$ a totient? ($x=\varphi(n)$)}{istotient$(x,\{\&n\})$} \li{is $x$ a polygonal number? ($x = P(s,n)$)}{ispolygonal$(x, s, \{\&n\})$} \li{is \var{pol}\ irreducible?}{polisirreducible$(\var{pol})$} \section{Graphic Functions} \li{crude graph of \expr\ between $a$ and $b$}{plot$(X=a,b,expr)$} \subsec{High-resolution plot {\rm (immediate plot)}} \li{plot \expr\ between $a$ and $b$}{ploth$(X=a,b,expr,\{\fl\},\{n\})$} \li{plot points given by lists $lx$, $ly$}{plothraw$(lx,ly,\{\fl\})$} \li{terminal dimensions}{plothsizes$()$} % \subsec{Rectwindow functions} \li{init window $w$, with size $x$,$y$}{plotinit$(w,x,y)$} \li{erase window $w$}{plotkill$(w)$} \li{copy $w$ to $w_2$ with offset $(dx,dy)$}{plotcopy$(w,w_2,dx,dy)$} \li{clips contents of $w$}{plotclip$(w)$} \li{scale coordinates in $w$}{plotscale$(w,x_1,x_2,y_1,y_2)$} \li{\kbd{ploth} in $w$}{plotrecth$(w,X=a,b,expr,\{\fl\},\{n\})$} \li{\kbd{plothraw} in $w$}{plotrecthraw$(w,data,\{\fl\})$} \li{draw window $w_1$ at $(x_1,y_1)$, \dots} {plotdraw$($[[$w_1,x_1,y_1$]$,\dots$]$)$} % \subsec{Low-level Rectwindow Functions} %\li{}{plotlinetype$(w,)$} %\li{}{plotpointtype$(w,)$} %\li{}{plotterm$(w,)$} \li{set current drawing color in $w$ to $c$}{plotcolor$(w,c)$} \li{current position of cursor in $w$}{plotcursor$(w)$} % \li{write $s$ at cursor's position}{plotstring$(w,s)$} \li{move cursor to $(x,y)$}{plotmove$(w,x,y)$} \li{move cursor to $(x+dx,y+dy)$}{plotrmove$(w,dx,dy)$} \li{draw a box to $(x_2,y_2)$}{plotbox$(w,x_2,y_2)$} \li{draw a box to $(x+dx,y+dy)$}{plotrbox$(w,dx,dy)$} \li{draw polygon}{plotlines$(w,lx,ly,\{\fl\})$} \li{draw points}{plotpoints$(w,lx,ly)$} \li{draw ellipse}{plotarc$(w,lx,ly,\{\fl\})$} \li{draw line to $(x+dx,y+dy)$}{plotrline$(w,dx,dy)$} \li{draw point $(x+dx,y+dy)$}{plotrpoint$(w,dx,dy)$} % \subsec{Convert to Postscript or Scalable Vector Graphics} The format $f$ is either \kbd{"ps"} or \kbd{"svg"}.\hfil\break \li{as {\tt ploth}}{plothexport$(f,X=a,b,expr,\{\fl\},\{n\})$} \li{as {\tt plothraw}}{plothrawexport$(f,lx,ly,\{\fl\})$} \li{as {\tt plotdraw}}{plotexport$(f,$[[$w_1,x_1,y_1$]$,\dots$]$)$} % This goes at the bottom of the second page (column 6) \copyrightnotice \bye pari-2.17.2/doc/develop.tex0000644000175000017500000012303314676526175014136 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 nonempty lexical context. An inline closure is a closure that appears in the code without the preceding \kbd{->} token. They are generally attached to the prototype code 'E' and 'I'. Inline closures can only exist as data of other closures, see below. In the following example, \bprog f(a=Euler)=x->sin(x+a); g=f(Pi/2); plot(x=0,2*Pi,g(x)) @eprog\noindent \kbd{f} is a function, \kbd{g} is a true closure and both \kbd{Euler} and \kbd{g(x)} are inline closures. This type has a second codeword \kbd{z[1]}, which is the arity of the function or closure. This is zero for inline closures. To access it, use \fun{long}{closure_arity}{GEN C} \item \kbd{z[2]} points to a \typ{STR} which holds the opcodes. To access it, use \fun{GEN}{closure_get_code}{GEN C}. \fun{const char *}{closure_codestr}{GEN C} returns as an array of \kbd{char} starting at $1$. \item \kbd{z[3]} points to a \typ{VECSMALL} which holds the operands of the opcodes. To access it, use \fun{GEN}{closure_get_oper}{GEN C} \item \kbd{z[4]} points to a \typ{VEC} which hold the data referenced by the \kbd{pushgen} opcodes, which can be \typ{CLOSURE}, and in particular inline closures. To access it, use \fun{GEN}{closure_get_data}{GEN C} \item \kbd{z[5]} points to a \typ{VEC} which hold extra data needed for error-reporting and debugging. See \secref{se:dbgclosure} for details. To access it, use \fun{GEN}{closure_get_dbg}{GEN C} Additionally, for functions and true closures, \item \kbd{z[6]} usually points to a \typ{VEC} with two components which are \typ{STR}. The first one displays the list of arguments of the closure without the enclosing parentheses, the second one the GP code of the function at the right of the \kbd{->} token. They are used to display the closure, either in implicit or explicit form. However for closures that were not generated from GP code, \kbd{z[6]} can point to a \typ{STR} instead. To access it, use \fun{GEN}{closure_get_text}{GEN C} Additionally, for true closure, \item \kbd{z[7]} points to a \typ{VEC} which holds the values of all lexical variables defined in the scope the closure was defined. To access it, use \fun{GEN}{closure_get_frame}{GEN C} \subsec{Debugging information in closure}\label{se:dbgclosure} Every \typ{CLOSURE} object \kbd{z} has a component \kbd{dbg=z[5]} which 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 \subsec{Maps as Lists} GP's maps are implemented on top of \typ{LIST}s so as to benefit from their peculiar memory models. Lists thus come in two subtypes: \typ{LIST\_RAW} (actual lists) and \typ{LIST\_MAP} (a map). \fun{GEN}{mklist_typ}{long t} create a list of subtype $t$. \fun{GEN}{mklist}{void} is an alias for \bprog mklist_typ(t_LIST_RAW); @eprog and \fun{GEN}{mkmap}{void} is an alias for \bprog mklist_typ(t_LIST_MAP); @eprog \fun{long}{list_typ}{GEN L} return the list subtype, either \typ{LIST\_RAW} or \typ{LIST\_MAP}. \fun{void}{listpop}{GEN L, long index} as \kbd{listpop0}, assuming that $L$ is a \typ{LIST\_RAW}. \fun{GEN}{listput}{GEN list, GEN object, long index} as \kbd{listput0}, assuming that $L$ is a \typ{LIST\_RAW}. Return the element as inserted in the list (a clone of \kbd{object}). \fun{GEN}{listinsert}{GEN list, GEN object, long index} as \kbd{listinsert0}, assuming that $L$ is a \typ{LIST\_RAW}. Return the element as inserted in the list (a clone of \kbd{object}). \fun{GEN}{mapdomain}{GEN T} vector of keys of the map $T$. \fun{GEN}{mapselect_shallow}{void *E, long (*f)(void* E, GEN x), GEN T} vector of keys of the map $T$ whose value matches the predicate $f$. \fun{GEN}{mapdomain_shallow}{GEN T} shallow version of \kbd{mapdomain}. \fun{GEN}{maptomat}{GEN T} convert a map to a factorization matrix. \fun{GEN}{maptomat_shallow}{GEN T} shallow version of \kbd{maptomat}. \section{Protection of noninterruptible code} GP allows the user to interrupt a computation by issuing SIGINT (usually by entering control-C) or SIGALRM (usually using alarm()). To avoid such interruption to occurs in section of code which are not reentrant (in particular \kbd{malloc} and \kbd{free}) the following mechanism is provided: \fun{}{BLOCK_SIGINT_START}{} Start a noninterruptible block code. Block both \kbd{SIGINT} and \kbd{SIGARLM}. \fun{}{BLOCK_SIGALRM_START}{} Start a noninterruptible block code. Block only \kbd{SIGARLM}. This is used in the \kbd{SIGINT} handler itself to delay an eventual pending alarm. \fun{}{BLOCK_SIGINT_END}{} End a noninterruptible block code The above macros make use of the following global variables: \tet{PARI_SIGINT_block}: set to $1$ (resp. $2$) by \kbd{BLOCK\_SIGINT\_START} (resp. \kbd{BLOCK\_SIGALRM\_START}). \tet{PARI_SIGINT_pending}: Either $0$ (no signal was blocked), \kbd{SIGINT} (\kbd{SIGINT} was blocked) or \kbd{SIGALRM} (\kbd{SIGALRM} was blocked). This need to be set by the signal handler. Within a block, an automatic variable \kbd{int block} is defined which records the value of \kbd{PARI\_SIGINT\_block} when entering the block. \subsec{Multithread interruptions} To support multithreaded programs, \kbd{BLOCK\_SIGINT\_START} and \kbd{BLOCK\_SIGALRM\_START} call \kbd{MT\_SIGINT\_BLOCK(block)}, and \kbd{BLOCK\_SIGINT\_END} calls \kbd{MT\_SIGINT\_UNBLOCK(block)}. \tet{MT_SIGINT_BLOCK} and \tet{MT_SIGINT_UNBLOCK} are defined by the multithread engine. They can calls the following public functions defined by the multithread engine. \fun{void}{mt_sigint_block}{void} \fun{void}{mt_sigint_unblock}{void} In practice this mechanism is used by the POSIX thread engine to protect against asychronous cancellation. \section{$\F_{l^2}$ field for small primes $l$} Let $l>2$ be a prime \kbd{ulong}. A \kbd{Fl2} is an element of the finite field $\F_{l^2}$ represented (currently) by a \kbd{Flx} of degree at most $1$ modulo a polynomial of the form $x^2-D$ for some non square $0\leq D #include pari_rl_interface S; ... pari_use_readline(S); @eprog\noindent The variable $S$, as initialized above, encapsulates the libpari readline interface. (And allow us to move gp's readline code to libpari without introducing a mandatory dependency on readline in libpari.) The following functions then become available: \fun{char**}{pari_completion_matches}{pari_rl_interface *pS, const char *s, long pos, long *wordpos} given a command string $s$, where the cursor is at index \kbd{pos}, return an array of completion matches. If \kbd{wordpos} is not \kbd{NULL}, set \kbd{*wordpos} to the index for the start of the expression we complete. \fun{char**}{pari_completion}{pari_rl_interface *pS, char *text, int start, int end} the low-level completer called by \tet{pari_completion_matches}. The following wrapper \bprog char** gp_completion(char *text, int START, int END) { return pari_completion(&S, text, START, END);) @eprog\noindent is a valid value for \tet{rl_attempted_completion_function}. \section{Constructors called by \kbd{pari\_init} functions} \fun{void}{pari_init_buffers}{} \fun{void}{pari_init_compiler}{} \fun{void}{pari_init_defaults}{} \fun{void}{pari_init_evaluator}{} \fun{void}{pari_init_files}{} \fun{void}{pari_init_floats}{} \fun{void}{pari_init_graphics}{} \fun{void}{pari_init_homedir}{} \fun{void}{pari_init_parser}{} \fun{void}{pari_init_paths}{} \fun{void}{pari_init_primetab}{} \fun{void}{pari_init_rand}{} \section{Destructors called by \kbd{pari\_close}} \fun{void}{pari_close_compiler}{} \fun{void}{pari_close_evaluator}{} \fun{void}{pari_close_files}{} \fun{void}{pari_close_floats}{} \fun{void}{pari_close_homedir}{} \fun{void}{pari_close_mf}{} \fun{void}{pari_close_parser}{} \fun{void}{pari_close_paths}{} \fun{void}{pari_close_primes}{} \section{Constructors and destructors used by the \kbd{pthreads} interface} \item Called by \tet{pari_thread_close} \fun{void}{pari_thread_close_files}{} \section{Functions for GP2C} \subsec{Functions for safe access to components} These functions return the address of the requested component after checking it is actually valid. This is used by GP2C -C. \fun{GEN*}{safegel}{GEN x, long l}, safe version of \kbd{gel(x,l)} for \typ{VEC}, \typ{COL} and \typ{MAT}. \fun{long*}{safeel}{GEN x, long l}, safe version of \kbd{x[l]} for \typ{VECSMALL}. \fun{GEN*}{safelistel}{GEN x, long l} safe access to \typ{LIST} component. \fun{GEN*}{safegcoeff}{GEN x, long a, long b} safe version of \kbd{gcoeff(x,a, b)} for \typ{MAT}. \newpage \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. the default~\kbd{\bs p 38} is a good first step. You can use \kbd{sizebyte(0)==16} to detect a 64-bit architecture and \kbd{sizebyte(0)==8} for 32-bit. \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 nonexisting template, so this must fail. \item Now \bprog patch -p1 < Oxxx/fun.dif @eprog\noindent generates a template output in the right place \kbd{src/test/32/fun}, for instance on a 32-bit machine. \item If different output is expected on 32-bit and 64-bit machines, run the test on a 64-bit machine and patch again, thereby producing \kbd{src/test/64/fun}. If, on the contrary, the output must be the same (preferred behavior!), 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 You can run a subset of existing tests by using the following idiom: \bprog cd Oxxx # call from relevant build directory make TESTS="lfuntype lfun gamma" test-all @eprog\noindent will run the \kbd{lfuntype}, \kbd{lfun} and \kbd{gamma} tests. This produces a combined output whereas the alternative \bprog make test-lfuntype test-lfun test-gamma @eprog\noindent would not. \item By default, the test is run on both the \kbd{gp-sta} and \kbd{gp-dyn} binaries, making it twice as slow. If the test is somewhat long, it can be annoying; you can restrict to one binary only using the \kbd{statest-all} or \kbd{dyntest-all} targets. Both accept the \kbd{TESTS} argument seen above; again, the alternative \bprog make test-lfuntype test-lfun test-gamma @eprog\noindent would not. \item Finally, 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.) \newpage \chapter{Tips and tricks to edit and debug the PARI sources} First, fetch the pari sources from our \kbd{git} repository: \bprog git clone https://pari.math.u-bordeaux.fr/git/pari.git @eprog\noindent The following sections assume you defined an environment variable \kbd{PARIDIR}, pointing to the toplevel where you install the pari sources, e.g. in \kbd{.bashrc}, \bprog export PARIDIR=$HOME/pari @eprog \section{Tags} To allow seamless navigation in PARI sources, we will use a \kbd{ctags} program. For instance, on Debian/Ubuntu systems, \bprog sudo apt-get install exuberant-ctags @eprog \subsec{For \kbd{vim}} Type \kbd{make ctags} in PARI's toplevel, then add to your \kbd{.vimrc} \bprog set tags=./tags,$PARIDIR/src/tags @eprog\noindent Now you can navigate the PARI sources in the usual \kbd{vim} way. Try \kbd{vi -t gadd}, then move the cursor to an identifier in the neighborhood, \kbd{typ} say, then type \kbd{Ctrl-]} (and \kbd{Ctrl-t} to come back). \subsec{For \kbd{emacs}} Type \kbd{make etags} in PARI's toplevel, then add to your \kbd{.emacs} \bprog (setq tags-table-list '("$PARIDIR/src")) @eprog \section{Editor customization} You can define special-purpose editor options to help you edit PARI code. We restrict to the \kbd{vim} editor; \kbd{emacs} and other programmer's editors give you analogous possibilities. \subsec{Create and customize \kbd{\$HOME/.vim/ftplugin/c.vim}} There you change \kbd{vim} settings whenever you're editing a C file. (Cleaner would be to call this \kbd{pari.vim} and load it conditionally from \kbd{c.vim} but this goes beyond the scope of these notes.) For instance \bprog setlocal path+=$PARIDIR/src/headers setlocal path+=$PARIDIR/Olinux-x86_64 @eprog\noindent This allows the editor to find and process our include files; for instance typing \kbd{gf} on \kbd{\#include "paripriv.h"} will open that file! By the way, you can define more complex macros there, such as \bprog map r i return NULL; /*LCOV_EXCL_LINE*/ @eprog\noindent When typing \kbd{}, this inserts at the cursor the string \bprog return NULL; /*LCOV_EXCL_LINE*/ @eprog\noindent which is used in \kbd{libpari} code to mark unreachable lines, inserted to avoid warnings from the compiler, for instance after an error which we know will not return, when the function has a non \kbd{void} return type. The \kbd{LCOV\_EXCL\_LINE} comment instructs our coverage tool not to report that line as not reached by our testing suite. See \kbd{https://pari.math.u-bordeaux.fr/lcov-report/}. \bprog map a :if expand("%:t") == 'paridecl.h'\ edit #\ else\ edit $PARIDIR/src/headers/paridecl.h\ endif @eprog\noindent This opens \kbd{paridecl.h} when hitting \kbd{} from a PARI source file. Typing \kbd{} once again moves back to where you where. That allows to edit a function, declare it or fix its declaration, and come back working. The same can be done for \kbd{paripriv.h}, obviously. \subsec{Create and customize \kbd{\$HOME/.vim/after/syntax/c.vim}} This allows to colorize in an appropriate way PARI-specific types and constants. For instance \bprog syntax keyword cType GEN pari_sp ulong uchar hashentry hashtable syntax keyword cNumber avma syntax keyword cNumber gen_0 gen_1 gen_m1 gen_2 gen_m2 ghalf @eprog\noindent We also like to flag spaces at the end of a line as an error: \bprog syntax match cError " \+$" @eprog \section{GDB configuration} Edit \kbd{\$HOME/.gdbinit} to teach \kbd{gdb} a number of useful macros. Here are some of the ones we use. Elaborate according to your needs. \subsec{Printing GENs} \bprog define o call output((GEN)$arg0) end document o Print the GEN value the same way as gp's print(). For instance o x prints the GEN x, o gadd(gen_1, gen_2) prints '3', etc. end @eprog \bprog define om call outmat((GEN)$arg0) end document om Pretty-print the GEN value, very suitable for matrices. For instance 'o matid(2)' prints [1,0;0,1] but 'om matid(2)' prints [1 0] [0 1] end @eprog \bprog define v if $argc > 1 call dbgGEN((GEN)$arg0, $arg1) else call dbgGEN((GEN)$arg0, 2) end end document v Emit the GEN value the same way as gp's \x would. By default, truncates the leaves at 2 words. This is changed by the 2nd optional argument; special case -1 = no truncation. end @eprog The following GDB macros apply some preprocessing before printing so write and leave intermediate results (e.g., \kbd{liftall} result) on the PARI stack. \bprog define olm call outmat(liftall((GEN)$arg0)) end document olm Pretty-print the GEN value lifting whenever possible. end @eprog \bprog define osm # prec_w: shallow copy with precision decreased call outmat(gprec_w((GEN)$arg0,3)) end document osm Pretty-print the GEN value, printing floats with minimal precision, suitable for large matrices or polynomials with floating point entries of huge accuracy. end @eprog \subsec{Advanced use} \bprog define be break pari_err end document be Set a breakpoint in the PARI error handler. end define db call setalldebug($argv0) end document db Set 'DEBUGLEVEL' variables in all modules to the value given as argument (between 0 and 10). Emulates gp's \g n. end define fs call dbg_fill_stack() end document fs Overwrite the unused portion of PARI's stack by junk. Allows to diagnose garbage collection mistakes. end @eprog The final one is particularly useful. \bprog define w1 shell rm -f /var/tmp/gp.tmp1 call gpwritebin("/var/tmp/gp.tmp1",$arg0) end document w1 Write GEN argument to temp file in binary PARI format end @eprog\noindent The following GP function can now work its magic: \bprog rtmp({n = 1}) = read( Str("/var/tmp/gp.tmp", n) ); @eprog\noindent In particular, in any GP shell, \kbd{rtmp()} will read in the argument that was saved under \kbd{gdb} by \kbd{w1}, allowing to test and inspect it with GP functions and start again on error. This is in sharp contrast to the same inspection under GDB, which is error prone and unforgiving: an error when manipulation C functions is likely to crash the process, hitting a garbage collection point might destroy the object, etc. This is particularly useful when the saved value takes a non-negligible time to compute. Another possibility is to compare the behavior of a newly modified \kbd{gp} with a reference version. One can find and save internal values from the two different \kbd{gp} binaries from \kbd{gdb} and compare or test them in either one. One can obviously duplicate the definition to have \kbd{w2} write to \kbd{gp.tmp2}, etc. Here is a more generic solution: \bprog define W set $tmp=stack_sprintf("/var/tmp/gp.tmp%d", $arg1) eval "shell rm -f %s", $tmp call gpwritebin($tmp, $arg0) end document W 'W x 7' writes the GEN x to /var/tmp/gp.tmp7. Note that 'rtmp(7)' in a GP session would then recover the value of 'x' end @eprog \newpage \chapter{Parallelism} PARI provides an abstraction, herafter called the MT engine, for doing parallel computations. The exact same high level routines are used whether the underlying communication protocol is POSIX threads or MPI and they behave differently depending on how \kbd{libpari} was configured, specifically on \kbd{Configure}'s \kbd{--mt} option. Sequential computation is also supported (no \kbd{--mt} argument) which is helpful for debugging newly written parallel code. The final section in this chapter comments a complete example. \section{The PARI multithread interface} \fun{void}{mt_queue_start}{struct pari_mt *pt, GEN worker} Let \kbd{worker} be a \typ{CLOSURE} object of arity $1$. Initialize the opaque structure \kbd{pt} to evaluate \kbd{worker} in parallel, using \kbd{nbthreads} threads. This allocates data in various ways, e.g., on the PARI stack or as malloc'ed objects: you may not collect garbage on the PARI stack starting from an earlier \kbd{avma} point until the parallel computation is over, it could destroy something in \kbd{pt}. All ressources allocated outside the PARI stack are freed by \kbd{mt\_queue\_end}. \fun{void}{mt_queue_start_lim}{struct pari_mt *pt, GEN worker, long lim} as \kbd{mt\_queue\_start}, where \kbd{lim} is an upper bound on the number of \kbd{tasks} to perform. Concretely the number of threads is the minimum of \kbd{lim} and \kbd{nbthreads}. The values $0$ and $1$ of \kbd{lim} are special: \item $0$: no limit, equivalent to \kbd{mt\_queue\_start} (use \kbd{nbthreads} threads). \item $1$: no parallelism, evaluate the tasks sequentially. \fun{void}{mt_queue_submit}{struct pari_mt *pt, long taskid, GEN task} submit \kbd{task} to be evaluated by \kbd{worker}; use \kbd{task = NULL} if no further task needs to be submitted. The parameter \kbd{taskid} is attached to the \kbd{task} but not used in any way by the \kbd{worker} or the MT engine, it will be returned to you by \kbd{mt\_queue\_get} together with the result for the task, allowing to match up results and submitted tasks if desired. For instance, if the tasks $(t_1,\dots, t_m)$ are known in advance, stored in a vector, and you want to recover the evaluation results in the same order as in that vector, you may use consecutive integers $1, \dots, m$ as \kbd{taskid}s. If you do not care about the ordering, on the other hand, you can just use $\kbd{taskid} = 0$ for all tasks. The \kbd{taskid} parameter is ignored when \kbd{task} is \kbd{NULL}. It is forbidden to call this function twice without an intervening \kbd{mt\_queue\_get}. \fun{GEN}{mt_queue_get}{struct pari_mt *pt, long *taskid, long *pending} return \kbd{NULL} until \kbd{mt\_queue\_submit} has submitted tasks for the required number (\kbd{nbthreads}) of threads; then return the result of the evaluation by \kbd{worker} of one of the previously submitted tasks, in random order. Set \kbd{pending} to the number of remaining pending tasks: if this is $0$ then no more tasks are pending and it is safe to call \tet{mt_queue_end}. Set \kbd{*taskid} to the value attached to this task by \kbd{mt\_queue\_submit}, unless the \kbd{taskid} pointer is \kbd{NULL}. It is forbidden to call this function twice without an intervening \kbd{mt\_queue\_submit}. \fun{void}{mt_queue_end}{struct pari_mt *pt} end the parallel execution and free ressources attached to the opaque \kbd{pari\_mt} structure. For instance malloc'ed data; in the \kbd{pthreads} interface, it would destroy mutex locks, condition variables, etc. This must be called once there are no longer pending tasks to avoid leaking ressources; but not before all tasks have been processed else crashes will occur. \fun{long}{mt_nbthreads}{void} return the effective number of parallel threads that would be started by \tet{mt_queue_start} if it has been called in place of \tet{mt_nbthreads}. \section{Technical functions required by MPI} The functions in this section are needed when writing complex independent programs in order to support the MPI MT engine, as more flexible complement/variants of \kbd{pari\_init} and \kbd{pari\_close}. \fun{void}{mt_broadcast}{GEN code}: do nothing unless the MPI threading engine is in use. In that case, evaluates the closure \kbd{code} on all secondary nodes. This can be used to change the state of all MPI child nodes, e.g., in \tet{gpinstall} run in the main thread, which allows all nodes to use the new function. \fun{void}{pari_mt_init}{void} when using MPI, it is often necessary to run initialization code on the child nodes after PARI is initialized. This is done by calling successively: \item \tet{pari_init_opts} with the flag \tet{INIT_noIMTm}: this initializes PARI, but not the MT engine; \item the required initialization code; \item \tet{pari_mt_init} to initialize the MT engine. Note that under MPI, this function returns on the master node but enters slave mode on the child nodes. Thus it is no longer possible to run initialization code on the child nodes. \fun{void}{pari_mt_close}{void} when using MPI, calling \tet{pari_close} terminates the MPI execution environment and it will not be possible to restart it. If this is undesirable, call \tet{pari_close_opts} with the flag \tet{INIT_noIMTm} instead of \kbd{pari\_close}: this closes PARI without terminating the MPI execution environment. You may later call \kbd{pari\_mt\_close} to terminate it. It is an error for a program to end without terminating the MPI execution environment. \section{A complete example} We now proceed to an example exhibiting complex features of this interface, in particular showing how to generate a valid \kbd{worker}. Explanations and details follow. \bprogfile{../examples/pari-mt.c} We start from some arbitrary C function \kbd{Cworker} and create an \kbd{entree} summarizing all that GP would need to know about it, in particular \item a GP name \kbd{\_worker}; the leading \kbd{\_} is not necessary, we use it as a namespace mechanism grouping private functions; \item the name of the C function; \item and its prototype, see \kbd{install} for an introduction to Prototype Codes. \noindent The other three arguments ($0$, $20$ and \kbd{""}) are required in an \kbd{entree} but not useful in our simple context: they are respectively a valence ($0$ means ``nothing special''), a help section (20 is customary for internal functions which need to be exported for technical reasons, see \kbd{?20}), and a help text (no help). Then we initialize the MT engine; doing things in this order with a two part initialization ensures that nodes have access to our \kbd{Cworker}. We convert the \kbd{ep} data to a \typ{CLOSURE} using \kbd{strtofunction}, which provides a valid \kbd{worker} to \kbd{mt\_queue\_start}. This creates a parallel evaluation queue \kbd{mt}, and we proceed to submit all tasks, recording all results. Results are stored in the right order by making good use of the \kbd{taskid} label, although we have no control over \emph{when} each result is returned. We finally free all ressources attached to the \kbd{mt} structure. If needed, we could have collected all garbage on the PARI stack using \kbd{gerepilecopy} on the \kbd{out} array and gone on working instead of quitting. Note the argument passing convention for \kbd{Cworker}: the task consists of a single vector containing all arguments as \kbd{GEN}s, which are interpreted according to the function prototype, here \kbd{GL} so the first argument is left as is and the second one is converted to a long integer. In more complicated situations, this second (and possibly further) argument could provide arbitrary evaluation contexts. In this example, we just used it as a flag to indicate the kind of evaluation expected on the data: integer factorization (0) or matrix determinant (1). Note also that \bprog gel(out, taskid) = mt_queue_get(&mt, &taskid, &pending); @eprog \noindent instead of our use of a temporary \kbd{done} would have undefined behaviour (\kbd{taskid} may be uninitialized in the left hand side). \chapter{Cross-compiling PARI for Windows from Linux} We use \kbd{mingw}. Please use the kit at \kbd{https://pari.math.u-bordeaux.fr/pub/pari/windows/paricrossmingwkit.tgz} \noindent This kit provides helper scripts and support binary to cross-compile PARI/GP for \kbd{mingw} and \kbd{mingw64} with \kbd{readline}, \kbd{gmp} and \kbd{perl} support. To start: \item Install the cross-compiling environment. On Debian and Ubuntu this can be achieved by using the scripts \kbd{install32} and \kbd{install64}. \item In this directory, type \bprog . ./setup @eprog to set the environment variables, especially \kbd{PARIKIT}. This assumes a \kbd{bash} (or \kbd{zsh}) shell. \item The following commands can then be executed \emph{from the toplevel of a pari source tree}: \bprog mkwine32 : build the installer package (32-bit) mkwine64 : build the installer package (64-bit) mkwinebin32 : built the stand-alone GP binary (32-bit) mkwinebin64 : built the stand-alone GP binary (64-bit) @eprog \noindent For convenience, the following variants are available for the standalone binaries (both \kbd{mkwinebin32} and \kbd{mkwinebin64}), the default is \kbd{rl}: \bprog mkwinebin64 norl : disable readline mkwinebin64 rl : only build readline mkwinebin64 all : build both readline and noreadline version @eprog \vfill\eject \input index\end pari-2.17.2/doc/refcard-nf.tex0000644000175000017500000006541614760123736014507 0ustar billbill% Copyright (c) 2007-2024 Karim Belabas. % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License % Reference Card for PARI-GP, Algebraic Number Theory. % Author: % Karim Belabas % Universite de Bordeaux, 351 avenue de la Liberation, F-33405 Talence % email: Karim.Belabas@math.u-bordeaux.fr % % See refcard.tex for acknowledgements and thanks. \def\TITLE{Algebraic Number Theory} \input refmacro.tex \def\p{\goth{p}} \section{Binary Quadratic Forms} % \li{create $ax^2+bxy+cy^2$}{Qfb$(a,b,c)$ or Qfb$([a,b,c])$} \li{reduce $x$ ($s =\sqrt{D}$, $l=\floor{s}$)} {qfbred$(x,\{\fl\},\{D\},\{l\},\{s\})$} \li{return $[y,g]$, $g\in \text{SL}_2(\ZZ)$, $y = g\cdot x$ reduced} {qfbredsl2$(x)$} \li{composition of forms}{$x$*$y$ {\rm or }qfbnucomp$(x,y,l)$} \li{$n$-th power of form}{$x$\pow$n$ {\rm or }qfbnupow$(x,n)$} \li{composition}{qfbcomp$(x,y)$} \li{\dots without reduction}{qfbcompraw$(x,y)$} \li{$n$-th power}{qfbpow$(x,n)$} \li{\dots without reduction}{qfbpowraw$(x,n)$} \li{prime form of disc. $x$ above prime $p$}{qfbprimeform$(x,p)$} \li{class number of disc. $x$}{qfbclassno$(x)$} \li{Hurwitz class number of disc. $x$}{qfbhclassno$(x)$} \li{solve $Q(x,y) = n$ in integers}{qfbsolve$(Q,n)$} \li{solve $x^2 + Dy^2 = p$, $p$ prime}{qfbcornacchia$(D,p)$} \li{\dots $x^2 + Dy^2 = 4p$, $p$ prime}{qfbcornacchia$(D,4*p)$} \section{Quadratic Fields} % \li{quadratic number $\omega=\sqrt x$ or $(1+\sqrt x)/2$}{quadgen$(x)$} \li{minimal polynomial of $\omega$}{quadpoly$(x)$} \li{discriminant of $\QQ(\sqrt{x})$}{quaddisc$(x)$} \li{regulator of real quadratic field}{quadregulator$(x)$} \li{fundamental unit in $O_D$, $D > 0$}{quadunit$(D,\{\kbd{'w}\})$} \li{norm of fundamental unit in $O_D$}{quadunitnorm$(D)$} \li{index of $O_{Df^2}^\times$ in $O_D^\times$}{quadunitindex$(D,f)$} \li{class group of $\QQ(\sqrt{D})$}{quadclassunit$(D,\{\fl\},\{t\})$} \li{Hilbert class field of $\QQ(\sqrt{D})$}{quadhilbert$(D,\{\fl\})$} \li{\dots using specific class invariant ($D<0$)}{polclass$(D,\{\var{inv}\})$} \li{test if $T$ is \kbd{polclass}$(D)$; if so return $D$}{polisclass$(T)$} \li{ray class field modulo $f$ of $\QQ(\sqrt{D})$}{quadray$(D,f,\{\fl\})$} \bigskip \section{General Number Fields: Initializations} The number field $K = \QQ[X]/(f)$ is given by irreducible $f\in\QQ[X]$. We denote $\theta = \bar{X}$ the canonical root of $f$ in $K$. A \var{nf} structure contains a maximal order and allows operations on elements and ideals. A \var{bnf} adds class group and units. A \var{bnr} is attached to ray class groups and class field theory. A \var{rnf} is attached to relative extensions $L/K$.\hfill\break % \li{init number field structure \var{nf}}{nfinit$(f,\{\fl\})$} \beginindentedkeys \li{known integer basis $B$}{nfinit$([f,B])$} \li{order maximal at $\var{vp}=[p_1,\dots,p_k]$}{nfinit$([f,\var{vp}])$} \li{order maximal at all $p \leq P$}{nfinit$([f,P])$} \li{certify maximal order}{nfcertify$(\var{nf})$} \endindentedkeys \subsec{nf members:} \beginindentedkeys \li{a monic $F\in \ZZ[X]$ defining $K$}{\var{nf}.pol} \li{number of real/complex places}{\var{nf}.r1/r2/sign} \li{discriminant of \var{nf}}{\var{nf}.disc} \li{primes ramified in \var{nf}}{\var{nf}.p} \li{$T_2$ matrix}{\var{nf}.t2} \li{complex roots of $F$}{\var{nf}.roots} \li{integral basis of $\ZZ_K$ as powers of $\theta$}{\var{nf}.zk} \li{different/codifferent}{\var{nf}.diff{\rm, }\var{nf}.codiff} \li{index $[\ZZ_K:\ZZ[X]/(F)]$}{\var{nf}.index} \endindentedkeys \li{recompute \var{nf}\ using current precision}{nfnewprec$(nf)$} \li{init relative \var{rnf} $L = K[Y]/(g)$}{rnfinit$(\var{nf},g)$} % \li{init \var{bnf} structure}{bnfinit$(f, 1)$} \subsec{bnf members: {\rm same as \var{nf}, plus}} \beginindentedkeys \li{underlying \var{nf}}{\var{bnf}.nf} \li{class group, regulator}{\var{bnf}.clgp, \var{bnf}.reg} \li{fundamental/torsion units}{\var{bnf}.fu{\rm, }\var{bnf}.tu} \endindentedkeys \li{add $S$-class group and units, yield \var{bnf}S}{bnfsunit$(\var{bnf},S)$} \li{init class field structure \var{bnr}}{bnrinit$(\var{bnf},m,\{\fl\})$} % \subsec{bnr members: {\rm same as \var{bnf}, plus}} \beginindentedkeys \li{underlying \var{bnf}}{\var{bnr}.bnf} \li{big ideal structure}{\var{bnr}.bid} \li{modulus $m$}{\var{bnr}.mod} \li{structure of $(\ZZ_K/m)^*$}{\var{bnr}.zkst} \endindentedkeys \smallskip \section{Fields, subfields, embeddings} \subsec{Defining polynomials, embeddings} \li{(some) number fields with Galois group $G$}{nflist$(G)$} \li{\dots and $|\text{disc}(K)| = N$ and $s$ complex places}{nflist$(G, N, \{s\})$} \li{\dots and $a \leq |\text{disc}(K)| \leq b$}{nflist$(G, [a,b], \{s\})$} \li{smallest poly defining $f=0$ (slow)}{polredabs$(f,\{\fl\})$} \li{small poly defining $f=0$ (fast)}{polredbest$(f,\{\fl\})$} \li{monic integral $g = C f(x/L)$}{poltomonic$(f,\{\&L\})$} \li{random Tschirnhausen transform of $f$}{poltschirnhaus$(f)$} \li{$\QQ[t]/(f) \subset \QQ[t]/(g)$ ? Isomorphic?} {nfisincl$(f,g)$, \kbd{nfisisom}} \li{reverse polmod $a=A(t)\mod T(t)$}{modreverse$(a)$} \li{compositum of $\QQ[t]/(f)$, $\QQ[t]/(g)$}{polcompositum$(f,g,\{\fl\})$} \li{compositum of $K[t]/(f)$, $K[t]/(g)$}{nfcompositum$(\var{nf}, f,g,\{\fl\})$} \li{splitting field of $K$ (degree divides $d$)} {nfsplitting$(\var{nf},\{d\})$} \li{signs of real embeddings of $x$}{nfeltsign$(\var{nf},x,\{pl\})$} \li{complex embeddings of $x$}{nfeltembed$(\var{nf},x,\{pl\})$} \li{$T\in K[t]$, \# of real roots of $\sigma(T)\in\R[t]$}{nfpolsturm$(\var{nf},T,\{pl\})$} \li{absolute Weil height}{nfweilheight$(\var{nf}, v)$} \smallskip \subsec{Subfields, polynomial factorization} \li{subfields (of degree $d$) of \var{nf}}{nfsubfields$(\var{nf},\{d\})$} \li{maximal subfields of \var{nf}}{nfsubfieldsmax$(\var{nf})$} \li{maximal CM subfield of \var{nf}}{nfsubfieldscm$(\var{nf})$} \li{$K_d \subset \QQ(\zeta_n)$, using Gaussian periods} {polsubcyclo$(n,d,\{v\})$} \li{\dots using class field theory}{polsubcyclofast$(n,d)$} \li{roots of unity in \var{nf}}{nfrootsof1$(\var{nf}\,)$} \li{roots of $g$ belonging to \var{nf}}{nfroots$(\var{nf},g)$} \li{factor $g$ in \var{nf}}{nffactor$(\var{nf},g)$} \smallskip \subsec{Linear and algebraic relations} \li{poly of degree $\le k$ with root $x\in\CC$ or $\QQ_p$}{algdep$(x,k)$} \li{alg. dep. with pol.~coeffs for series $s$}{seralgdep$(s,x,y)$} \li{diff. dep. with pol.~coeffs for series $s$}{serdiffdep$(s,x,y)$} \li{small linear rel.\ on coords of vector $x$}{lindep$(x)$} \section{Basic Number Field Arithmetic (nf)} Number field elements are \typ{INT}, \typ{FRAC}, \typ{POL}, \typ{POLMOD}, or \typ{COL} (on integral basis \kbd{\var{nf}.zk}). \smallskip \subsec{Basic operations} \li{$x+y$}{nfeltadd$(\var{nf},x,y)$} \li{$x\times y$}{nfeltmul$(\var{nf},x,y)$} \li{$x^n$, $n\in \ZZ$}{nfeltpow$(\var{nf},x,n)$} \li{$x / y$}{nfeltdiv$(\var{nf},x,y)$} \li{$q = x$\kbd{\bs/}$y := $\kbd{round}$(x/y)$}{nfeltdiveuc$(\var{nf},x,y)$} \li{$r = x$\kbd{\%}$y := x - (x$\kbd{\bs/}$y)y$}{nfeltmod$(\var{nf},x,y)$} \li{\dots $[q,r]$ as above}{nfeltdivrem$(\var{nf},x,y)$} \li{reduce $x$ modulo ideal $A$}{nfeltreduce$(\var{nf},x,A)$} \li{absolute trace $\text{Tr}_{K/\QQ} (x)$}{nfelttrace$(\var{nf},x)$} \li{absolute norm $\text{N}_{K/\QQ} (x)$}{nfeltnorm$(\var{nf},x)$} \newcolumn \li{is $x$ a square?}{nfeltissquare$(\var{nf},x,\{\&y\})$} \li{\dots an $n$-th power?}{nfeltispower$(\var{nf},x,n,\{\&y\})$} \smallskip \subsec{Multiplicative structure of $K^*$; $K^*/(K^*)^n$} \li{valuation $v_\p(x)$}{nfeltval$(\var{nf},x,\p)$} \li{\dots write $x = \pi^{v_\p(x)} y$}{nfeltval$(\var{nf},x,\p,\&y)$} \li{quadratic Hilbert symbol (at $\p$)} {nfhilbert$(\var{nf},a,b,\{\p\})$} \li{$b$ such that $x b^n = v$ is small}{idealredmodpower$(\var{nf},x,n)$} \smallskip \subsec{Maximal order and discriminant} \li{integral basis of field $\QQ[x]/(f)$}{nfbasis$(f)$} \li{field discriminant of $\QQ[x]/(f)$}{nfdisc$(f)$} \li{\dots and factorization}{nfdiscfactors$(f)$} \li{express $x$ on integer basis}{nfalgtobasis$(\var{nf},x)$} \li{express element\ $x$ as a polmod}{nfbasistoalg$(\var{nf},x)$} \smallskip \subsec{Hecke Grossencharacters} Let $K$ be a number field and $m$ a modulus. A gchar structure describes the group of Hecke Grossencharacters of~$K$ of modulus~$m$ and allows computations with these characters. A character $\chi$ is described by its components modulo \var{gc}\kbd{.cyc}. \smallskip \li{init gchar structure \var{gc} for modulus \var{m}}{gcharinit$(\var{bnf},\var{m},\{cm\})$} \subsec{gc members:} \beginindentedkeys \li{underlying \var{bnf}}{\var{gc}.bnf} %\li{big ideal structure}{\var{bnr}.bid} \li{modulus}{\var{gc}.mod} %\li{structure of $(\ZZ_K/m)^*$}{\var{bnr}.zkst} \li{elementary divisors (including $0$s)}{\var{gc}.cyc} \endindentedkeys \li{recompute \var{gc}\ using current precision}{gcharnewprec$(gc)$} \li{evaluate Hecke character \var{chi} at ideal \var{id}}{gchareval$(\var{gc},\var{chi},\var{id})$} \li{exponent column of \var{id} in $\RR^n$}{gcharideallog$(\var{gc},\var{id})$} \li{log representation of ideal \var{id}}{gcharlog$(\var{gc}, \var{id})$} \li{\dots of character $\chi$}{gcharduallog$(\var{gc},\var{chi})$} \li{exponent vector of $\chi$ in $\RR^n$}{gcharparameters$(\var{gc},\var{chi})$} \li{conductor of~$\chi$}{gcharconductor$(gc,chi)$} \li{L-function of $\chi$}{lfuncreate$([\var{gc},\var{chi}])$} \li{local component $\chi_v$ of $\chi$}{gcharlocal$(\var{gc},\var{chi},v)$} \li{$\chi$ s.t. $\chi_v \approx \var{Lchiv}\kbd{[i]}$ for~$v=\var{Lv}\kbd{[i]}$}{gcharidentify$(\var{gc},\var{Lv},\var{Lchiv})$} \li{basis of group of algebraic characters}{gcharalgebraic$(\var{gc})$} \li{algebraic character of given infinity type}{gcharalgebraic$(\var{gc},\var{type})$} \li{is $\chi$ algebraic?}{gcharisalgebraic$(\var{gc},\var{chi})$} \smallskip \subsec{Dedekind Zeta Function $\zeta_K$, Hecke $L$ series} $R = [c,w,h]$ in initialization means we restrict $s\in \CC$ to domain $|\Re(s)-c| < w$, $|\Im(s)| < h$; $R = [w,h]$ encodes $[1/2,w,h]$ and $[h]$ encodes $R = [1/2,0,h]$ (critical line up to height $h$).\hfil\break \li{$\zeta_K$ as Dirichlet series, $N(I)\leq b$}{dirzetak$(\var{nf},b)$} \li{init $\zeta_K^{(k)}(s)$ for $k \leq n$} {L = lfuninit$(\var{bnf}, R, \{n = 0\})$} \li{compute $\zeta_K(s)$ ($n$-th derivative)}{lfun$(L, s, \{n=0\})$} \li{compute $\Lambda_K(s)$ ($n$-th derivative)}{lfunlambda$(L, s, \{n=0\})$} \smallskip \li{init $L_K^{(k)}(s, \chi)$ for $k \leq n$} {L = lfuninit$([\var{bnr},\var{chi}], R, \{n = 0\})$} \li{compute $L_K(s, \chi)$ ($n$-th derivative)}{lfun$(L, s, \{n\})$} \li{Artin root number of $K$}{bnrrootnumber$(\var{bnr},\var{chi},\{\fl\})$} \li{$L(1,\chi)$, for all $\chi$ trivial on $H$} {bnrL1$(\var{bnr},\{H\},\{\fl\})$} \section{Class Groups \& Units (bnf, bnr)} Class field theory data $a_1,\{a_2\}$ is usually \var{bnr} (ray class field), $\var{bnr},H$ (congruence subgroup) or $\var{bnr},\chi$ (character on \kbd{bnr.clgp}). Any of these define a unique abelian extension of $K$. \li{units / $S$-units}{bnfunits$(\var{bnf},\{S\})$} \li{remove GRH assumption from \var{bnf}}{bnfcertify$(\var{bnf})$} \shortcopyrightnotice \newcolumn \li{expo.~of ideal $x$ on class gp}{bnfisprincipal$(\var{bnf},x,\{\fl\})$} \li{\dots on ray class gp}{bnrisprincipal$(\var{bnr},x,\{\fl\})$} \li{expo.~of $x$ on fund.~units}{bnfisunit$(\var{bnf},x)$} \li{\dots on $S$-units, $U$ is \kbd{bnfunits}$(\var{bnf},S)$} {bnfisunit$(\var{bnfs},x,U)$} \li{signs of real embeddings of \kbd{\var{bnf}.fu}}{bnfsignunit$(\var{bnf})$} \li{narrow class group}{bnfnarrow$(\var{bnf})$} \subsec{Class Field Theory} \li{ray class number for modulus $m$}{bnrclassno$(\var{bnf},m)$} \li{discriminant of class field}{bnrdisc$(a_1,\{a_2\})$} \li{ray class numbers, $l$ list of moduli}{bnrclassnolist$(\var{bnf},l)$} \li{discriminants of class fields}{bnrdisclist$(\var{bnf},l,\{arch\},\{\fl\})$} \li{decode output from \kbd{bnrdisclist}}{bnfdecodemodule$(\var{nf},fa)$} \li{is modulus the conductor?}{bnrisconductor$(a_1,\{a_2\})$} \li{is class field $(\var{bnr},H)$ Galois over $K^G$} {bnrisgalois$(\var{bnr},G,H)$} \li{action of automorphism on \kbd{bnr.gen}} {bnrgaloismatrix$(\var{bnr},\var{aut})$} \li{apply \kbd{bnrgaloismatrix} $M$ to $H$} {bnrgaloisapply$(\var{bnr},M,H)$} \li{characters on \kbd{bnr.clgp} s.t. $\chi(g_i) = e(v_i)$} {bnrchar$(\var{bnr},g,\{v\})$} \li{conductor of character $\chi$}{bnrconductor$(\var{bnr},\var{chi})$} \li{conductor of extension}{bnrconductor$(a_1,\{a_2\},\{\fl\})$} \li{conductor of extension $K[Y]/(g)$}{rnfconductor$(\var{bnf},g)$} \li{canonical projection $\text{Cl}_F\to\text{Cl}_f$, $f\mid F$}{bnrmap} \li{Artin group of extension $K[Y]/(g)$}{rnfnormgroup$(\var{bnr},g)$} \li{subgroups of \var{bnr}, index $<=b$}{subgrouplist$(\var{bnr},b,\{\fl\})$} \li{compositum as \kbd{[bnr,H]}} {bnrcompositum$(\kbd{[bnr1,H1]}, \kbd{[bnr2,H2]})$} \li{class field defined by $H < \text{Cl}_f$}{bnrclassfield$(\var{bnr},H)$} \li{\dots low level equivalent, prime degree}{rnfkummer$(\var{bnr},H)$} \li{same, using Stark units (real field)}{bnrstark$(\var{bnr},\{sub\},\{\fl\})$} \li{Stark unit}{bnrstarkunit$(\var{bnr},\{sub\})$} \li{is $a$ an $n$-th power in $K_v$ ?}{nfislocalpower$(\var{nf},v,a,n)$} \li{cyclic $L/K$ satisf. local conditions} {nfgrunwaldwang$(\var{nf},P,D,\var{pl})$} \subsec{Cyclotomic and Abelian fields theory} An Abelian field $F$ given by a subgroup $H\subset (\Z/f\Z)^*$ is described by an argument $F$, e.g. $f$ (for $H = 1$, i.e. $\Q(\zeta_f)$) or $[G,H]$, where $G$ is \kbd{idealstar}$(f, 1)$, or a minimal polynomial.\hfil\break \li{minus class number $h^-(F)$}{subcyclohminus$(F)$} \li{\dots $p$-part}{subcyclohminus$(F, p)$} \li{minus part of Iwasawa polynomials}{subcycloiwasawa$(F, p)$} \li{$p$-Sylow of $\text{Cl}(F)$}{subcyclopclgp$(F, p)$} \subsec{Logarithmic class group} \li{logarithmic $\ell$-class group}{bnflog$(\var{bnf},\ell)$} \li{$[\tilde{e}(F_v/\Q_p),\tilde{f}(F_v/\Q_p)]$} {bnflogef$(\var{bnf},\var{pr})$} \li{$\exp \deg_F(A)$}{bnflogdegree$(\var{bnf}, A, \ell)$} \li{is $\ell$-extension $L/K$ locally cyclotomic}{rnfislocalcyclo$(\var{rnf})$} \section{Ideals: {\rm elements, primes, or matrix of generators in HNF}} \li{is $id$ an ideal in \var{nf} ?}{nfisideal$(\var{nf},id)$} \li{is $x$ principal in \var{bnf} ?}{bnfisprincipal$(\var{bnf},x)$} \li{give $[a,b]$, s.t.~ $a\ZZ_K+b\ZZ_K = x$}{idealtwoelt$(\var{nf},x,\{a\})$} \li{put ideal $a$ ($a\ZZ_K+b\ZZ_K$) in HNF form}{idealhnf$(\var{nf},a,\{b\})$} \li{norm of ideal $x$}{idealnorm$(\var{nf},x)$} \li{minimum of ideal $x$ (direction $v$)}{idealmin$(\var{nf},x,v)$} \li{LLL-reduce the ideal $x$ (direction $v$)}{idealred$(\var{nf},x,\{v\})$} \smallskip \subsec{Ideal Operations} \li{add ideals $x$ and $y$}{idealadd$(\var{nf},x,y)$} \li{multiply ideals $x$ and $y$}{idealmul$(\var{nf},x,y,\{\fl\})$} \li{intersection of ideal $x$ with $\Q$}{idealdown$(\var{nf},x)$} \li{intersection of ideals $x$ and $y$}{idealintersect$(\var{nf},x,y,\{\fl\})$} \li{$n$-th power of ideal $x$}{idealpow$(\var{nf},x,n,\{\fl\})$} \li{inverse of ideal $x$}{idealinv$(\var{nf},x)$} \newcolumn \title{\TITLE} \centerline{(PARI-GP version \PARIversion)} \smallskip \li{divide ideal $x$ by $y$}{idealdiv$(\var{nf},x,y,\{\fl\})$} \li{Find $(a,b)\in x\times y$, $a+b=1$}{idealaddtoone$(\var{nf},x,\{y\})$} \li{coprime integral $A,B$ such that $x=A/B$}{idealnumden$(\var{nf},x)$} \smallskip \subsec{Primes and Multiplicative Structure} \li{check whether $x$ is a maximal ideal}{idealismaximal$(\var{nf},x)$} \li{factor ideal $x$ in $\ZZ_K$}{idealfactor$(\var{nf},x)$} \li{expand ideal factorization in $K$}{idealfactorback$(\var{nf},f,\{e\})$} \li{is ideal $A$ an $n$-th power ?}{idealispower$(\var{nf},A,n)$} \li{expand elt factorization in $K$}{nffactorback$(\var{nf},f,\{e\})$} \li{decomposition of prime $p$ in $\ZZ_K$}{idealprimedec$(\var{nf},p)$} \li{valuation of $x$ at prime ideal \var{pr}}{idealval$(\var{nf},x,\var{pr})$} \li{weak approximation theorem in \var{nf}}{idealchinese$(\var{nf},x,y)$} \li{$a\in K$, s.t. $v_{\p}(a) = v_{\p}(x)$ if $v_{\p}(x)\neq 0$} {idealappr$(\var{nf},x)$} \li{$a\in K$ such that $(a\cdot x, y) = 1$}{idealcoprime$(\var{nf},x,y)$} \li{give $bid=$structure of $(\ZZ_K/id)^*$}{idealstar$(\var{nf},id,\{\fl\})$} \li{structure of $(1+\p) / (1+\p^k)$} {idealprincipalunits$(\var{nf},\var{pr},k)$} \li{discrete log of $x$ in $(\ZZ_K/bid)^*$}{ideallog$(\var{nf},x,bid)$} \li{\kbd{idealstar} of all ideals of norm $\le b$}{ideallist$(\var{nf},b,\{\fl\})$} \li{add Archimedean places}{ideallistarch$(\var{nf},b,\{ar\},\{\fl\})$} \li{init \kbd{modpr} structure}{nfmodprinit$(\var{nf},\var{pr},\{v\})$} \li{project $t$ to $\ZZ_K/\var{pr}$}{nfmodpr$(\var{nf},t,\var{modpr})$} \li{lift from $\ZZ_K/\var{pr}$}{nfmodprlift$(\var{nf},t,\var{modpr})$} \medskip \section{Galois theory over $\QQ$} \li{conjugates of a root $\theta$ of \var{nf}}{nfgaloisconj$(\var{nf},\{\fl\})$} \li{apply Galois automorphism $s$ to $x$}{nfgaloisapply$(\var{nf},s,x)$} \li{Galois group of field $\QQ[x]/(f)$}{polgalois$(f)$} \li{resolvent field of $\QQ[x]/(f)$}{nfresolvent$(f)$} \li{initializes a Galois group structure $G$}{galoisinit$(\var{pol},\{den\})$} \li{\dots for the splitting field of \var{pol}}{galoissplittinginit$(\var{pol},\{d\})$} \li{character table of $G$}{galoischartable$(G)$} \li{conjugacy classes of $G$}{galoisconjclasses$(G)$} \li{$\det(1 - \rho(g)T)$, $\chi$ character of $\rho$} {galoischarpoly$(G,\chi,\{o\})$} \li{$\det(\rho(g))$, $\chi$ character of $\rho$} {galoischardet$(G,\chi,\{o\})$} \li{action of $p$ in nfgaloisconj form}{galoispermtopol$(G,\{p\})$} \li{identify as abstract group}{galoisidentify$(G)$} \li{export a group for GAP/MAGMA}{galoisexport$(G,\{\fl\})$} \li{subgroups of the Galois group $G$}{galoissubgroups$(G)$} \li{is subgroup $H$ normal?}{galoisisnormal$(G,H)$} \li{subfields from subgroups}{galoissubfields$(G,\{\fl\},\{v\})$} \li{fixed field}{galoisfixedfield$(G,\var{perm},\{\fl\},\{v\})$} \li{Frobenius at maximal ideal $P$}{idealfrobenius$(\var{nf},G,P)$} \li{ramification groups at $P$}{idealramgroups$(\var{nf},G,P)$} \li{is $G$ abelian?}{galoisisabelian$(G,\{\fl\})$} \li{abelian number fields/$\QQ$}{galoissubcyclo(N,H,\{\fl\},\{v\})} \subsec{The \kbd{galpol} package} \li{query the package: polynomial}{galoisgetpol(a,b,\{s\})} \li{\dots : permutation group}{galoisgetgroup(a,{b})} \li{\dots : group description}{galoisgetname(a,b)} \medskip \section{Relative Number Fields (rnf)} Extension $L/K$ is defined by $T\in K[x]$. \hfill\break % \li{absolute equation of $L$}{rnfequation$(\var{nf},T,\{\fl\})$} \li{is $L/K$ abelian?}{rnfisabelian$(\var{nf},T)$} \li{relative {\tt nfalgtobasis}}{rnfalgtobasis$(\var{rnf},x)$} \li{relative {\tt nfbasistoalg}}{rnfbasistoalg$(\var{rnf},x)$} \li{relative {\tt idealhnf}}{rnfidealhnf$(\var{rnf},x)$} \newcolumn \li{relative {\tt idealmul}}{rnfidealmul$(\var{rnf},x,y)$} \li{relative {\tt idealtwoelt}}{rnfidealtwoelt$(\var{rnf},x)$} \smallskip \subsec{Lifts and Push-downs} \li{absolute $\rightarrow$ relative representation for $x$} {rnfeltabstorel$(\var{rnf},x)$} \li{relative $\rightarrow$ absolute representation for $x$} {rnfeltreltoabs$(\var{rnf},x)$} \li{lift $x$ to the relative field}{rnfeltup$(\var{rnf},x)$} \li{push $x$ down to the base field}{rnfeltdown$(\var{rnf},x)$} \leavevmode idem for $x$ ideal: \kbd{$($rnfideal$)$reltoabs}, \kbd{abstorel}, \kbd{up}, \kbd{down}\hfill \smallskip \subsec{Norms and Trace} \li{relative norm of element $x\in L$}{rnfeltnorm$(\var{rnf},x)$} \li{relative trace of element $x\in L$}{rnfelttrace$(\var{rnf},x)$} \li{absolute norm of ideal $x$}{rnfidealnormabs$(\var{rnf},x)$} \li{relative norm of ideal $x$}{rnfidealnormrel$(\var{rnf},x)$} \li{solutions of $N_{K/\QQ}(y)=x\in \ZZ$}{bnfisintnorm$(\var{bnf},x)$} \li{is $x\in\QQ$ a norm from $K$?}{bnfisnorm$(\var{bnf},x,\{\fl\})$} \li{initialize $T$ for norm eq.~solver}{rnfisnorminit$(K,pol,\{\fl\})$} \li{is $a\in K$ a norm from $L$?}{rnfisnorm$(T,a,\{\fl\})$} \li{initialize $t$ for Thue equation solver}{thueinit$(f)$} \li{solve Thue equation $f(x,y)=a$}{thue$(t,a,\{sol\})$} \li{characteristic poly.\ of $a$ mod $T$}{rnfcharpoly$(\var{nf},T,a,\{v\})$} \smallskip \subsec{Factorization} \li{factor ideal $x$ in $L$}{rnfidealfactor$(\var{rnf},x)$} \li{$[S,T] \colon T_{i,j} \mid S_i$; $S$ primes of $K$ above $p$} {rnfidealprimedec$(\var{rnf},p)$} \smallskip \subsec{Maximal order $\ZZ_L$ as a $\ZZ_K$-module} \li{relative {\tt polredbest}}{rnfpolredbest$(\var{nf},T)$} \li{relative {\tt polredabs}}{rnfpolredabs$(\var{nf},T)$} \li{relative Dedekind criterion, prime $pr$}{rnfdedekind$(\var{nf},T,pr)$} \li{discriminant of relative extension}{rnfdisc$(\var{nf},T)$} \li{pseudo-basis of $\ZZ_L$}{rnfpseudobasis$(\var{nf},T)$} \smallskip \subsec{General $\ZZ_K$-modules: {\rm $M = [{\rm matrix}, {\rm vec.~of~ideals}] \subset L$}} \li{relative HNF / SNF}{nfhnf$(\var{nf},M)${\rm, }nfsnf} \li{multiple of $\det M$}{nfdetint$(\var{nf},M)$} \li{HNF of $M$ where $d = \kbd{nfdetint}(M)$}{nfhnfmod$(x,d)$} \li{reduced basis for $M$}{rnflllgram$(\var{nf},T,M)$} \li{determinant of pseudo-matrix $M$}{rnfdet$(\var{nf},M)$} \li{Steinitz class of $M$}{rnfsteinitz$(\var{nf},M)$} \li{$\ZZ_K$-basis of $M$ if $\ZZ_K$-free, or $0$}{rnfhnfbasis$(\var{bnf},M)$} \li{$n$-basis of $M$, or $(n+1)$-generating set}{rnfbasis$(\var{bnf},M)$} \li{is $M$ a free $\ZZ_K$-module?}{rnfisfree$(\var{bnf},M)$} \vfill \copyrightnotice \newcolumn \section{Associative Algebras} $A$ is a general associative algebra given by a multiplication table \var{mt} (over $\QQ$ or $\FF_p$); represented by \var{al} from \kbd{algtableinit}. \li{create \var{al} from \var{mt} (over $\FF_p$)} {algtableinit$(\var{mt},\{p=0\})$} \li{group algebra $\QQ[G]$ (or $\FF_p[G]$)}{alggroup$(G,\{p = 0\})$} \li{center of group algebra}{alggroupcenter$(G,\{p = 0\})$} \subsec{Properties} \li{is $(\var{mt},p)$ OK for algtableinit?} {algisassociative$(\var{mt},\{p=0\})$} \li{multiplication table \var{mt}}{algmultable$(\var{al})$} \li{dimension of $A$ over prime subfield}{algdim$(\var{al})$} \li{characteristic of $A$}{algchar$(\var{al})$} \li{is $A$ commutative?}{algiscommutative$(\var{al})$} \li{is $A$ simple?}{algissimple$(\var{al})$} \li{is $A$ semi-simple?}{algissemisimple$(\var{al})$} \li{center of $A$}{algcenter$(\var{al})$} \li{Jacobson radical of $A$}{algradical$(\var{al})$} \li{radical $J$ and simple factors of $A/J$}{algsimpledec$(\var{al})$} \smallskip \subsec{Operations on algebras} \li{create $A/I$, $I$ two-sided ideal}{algquotient$(\var{al},I)$} \li{create $A_1\otimes A_2$}{algtensor$(\var{al1}, \var{al2})$} \li{create subalgebra from basis $B$}{algsubalg$(\var{al}, B)$} \li{quotients by ortho. central idempotents $e$} {algcentralproj$(\var{al}, e)$} \li{isomorphic alg. with integral mult. table}{algmakeintegral(\var{mt})} \li{prime subalgebra of semi-simple $A$ over $\FF_p$} {algprimesubalg$(\var{al})$} \li{find isomorphism~$A\cong M_d(\FF_q)$}{algsplit(\var{al})} \smallskip \subsec{Operations on lattices in algebras} \li{lattice generated by cols. of $M$}{alglathnf$(\var{al},M)$} \li{\dots by the products~$xy$, $x\in lat1$, $y\in lat2$}{alglatmul$(\var{al},\var{lat1},\var{lat2})$} \li{sum $lat1+lat2$ of the lattices}{alglatadd$(\var{al},\var{lat1},\var{lat2})$} \li{intersection $lat1\cap lat2$}{alglatinter$(\var{al},\var{lat1},\var{lat2})$} \li{test~$lat1\subset lat2$}{alglatsubset$(\var{al},\var{lat1},\var{lat2})$} \li{generalized index~$(lat2:lat1)$}{alglatindex$(\var{al},\var{lat1},\var{lat2})$} \li{$\{x\in al\mid x\cdot lat1\subset lat2\}$}{alglatlefttransporter$(\var{al},\var{lat1},\var{lat2})$} \li{$\{x\in al\mid lat1\cdot x\subset lat2\}$}{alglatrighttransporter$(\var{al},\var{lat1},\var{lat2})$} \li{test~$x\in lat$ (set~$c =$ coord. of~$x$)}{alglatcontains$(\var{al},\var{lat},x,\{\& c\})$} \li{element of~$lat$ with coordinates~$c$}{alglatelement$(\var{al},\var{lat},c)$} \subsec{Operations on elements} \li{$a+b$, $a-b$, $-a$}{algadd$(\var{al},a,b)${\rm, }algsub{\rm, }algneg} \li{$a\times b$, $a^2$}{algmul$(\var{al},a,b)${\rm, }algsqr} \li{$a^n$, $a^{-1}$}{algpow$(\var{al},a,n)${\rm, }alginv} \li{is $x$ invertible ? (then set $z=x^{-1}$)}{algisinv$(\var{al},x,\{\&z\})$} \li{find $z$ such that $x\times z = y$}{algdivl$(\var{al},x,y)$} \li{find $z$ such that $z\times x = y$}{algdivr$(\var{al},x,y)$} \li{does $z$ s.t. $x\times z = y$ exist? (set it)} {algisdivl$(\var{al},x,y,\{\&z\})$} \li{matrix of $v\mapsto x\cdot v$}{algtomatrix$(\var{al}, x)$} \li{absolute norm}{algnorm$(\var{al},x)$} \li{absolute trace}{algtrace$(\var{al},x)$} \li{absolute char. polynomial}{algcharpoly$(\var{al},x)$} \li{given $a\in A$ and polynomial $T$, return $T(a)$} {algpoleval$(\var{al},T,a)$} \li{random element in a box}{algrandom$(\var{al}, b)$} \section{Central Simple Algebras} $A$ is a central simple algebra over a number field $K$; represented by \var{al} from \kbd{alginit}; $K$ is given by a \var{nf} structure. \li{create CSA from data} {alginit$(B,C,\{v\},\{maxord=1\})$} \beginindentedkeys \li{multiplication table over $K$}{$B = K${\rm, }$C = \var{mt}$} \li{cyclic algebra $(L/K,\sigma,b)$} {$B = \var{rnf}${\rm, }$C = [\var{sigma},b]$} \li{quaternion algebra $(a,b)_K$}{$B = K$, $C = [a,b]$} \li{matrix algebra $M_d(K)$}{$B = K$, $C = d$} \li{local Hasse invariants over $K$} {$B = K$, $C = [d, [\var{PR}, \var{HF}], \var{HI}]$} \endindentedkeys \smallskip \subsec{Properties} \li{type of \var{al} (\var{mt}, CSA)}{algtype$(\var{al})$} \li{dimension of $A$ over~$\QQ$}{algdim$(\var{al},1)$} \li{dimension of \var{al} over its center~$K$}{algdim$(\var{al})$} \li{degree of $A$ ($=\sqrt{\dim_K A}$)}{algdegree$(\var{al})$} \li{\var{al} a cyclic algebra $(L/K,\sigma,b)$; return $\sigma$} {algaut$(\var{al})$} \li{\dots return $b$}{algb$(\var{al})$} \li{\dots return $L/K$, as an \var{rnf}} {algsplittingfield$(\var{al})$} \li{split $A$ over an extension of $K$}{algsplittingdata$(\var{al})$} \li{splitting field of $A$ as an \var{rnf} over center} {algsplittingfield$(\var{al})$} \li{multiplication table over center}{algrelmultable$(\var{al})$} \li{places of $K$ at which $A$ ramifies}{algramifiedplaces$(\var{al})$} \li{Hasse invariants at finite places of $K$}{alghassef$(\var{al})$} \li{Hasse invariants at infinite places of $K$}{alghassei$(\var{al})$} \li{Hasse invariant at place $v$}{alghasse$(\var{al},v)$} \li{index of $A$ over $K$ (at place $v$)}{algindex$(\var{al},\{v\})$} \li{is \var{al} a division algebra? (at place $v$)} {algisdivision$(\var{al},\{v\})$} \li{is $A$ ramified? (at place $v$)}{algisramified$(\var{al},\{v\})$} \li{is $A$ split? (at place $v$)}{algissplit$(\var{al},\{v\})$} \smallskip \subsec{Operations on elements} \li{reduced norm}{algnorm$(\var{al},x)$} \li{reduced trace}{algtrace$(\var{al},x)$} \li{reduced char. polynomial}{algcharpoly$(\var{al},x)$} \li{express $x$ on integral basis}{algalgtobasis$(\var{al},x)$} \li{convert $x$ to algebraic form}{algbasistoalg$(\var{al},x)$} \li{map $x\in A$ to $M_d(L)$, $L$ split. field} {algtomatrix$(\var{al},x)$} \smallskip \subsec{Orders} \li{$\ZZ$-basis of order ${\cal O}_0$}{algbasis$(\var{al})$} \li{discriminant of order ${\cal O}_0$}{algdisc$(\var{al})$} \li{$\ZZ$-basis of natural order in terms ${\cal O}_0$'s basis} {alginvbasis$(\var{al})$} \newcolumn \strut \vskip 11cm \copyrightnotice \bye pari-2.17.2/doc/usersch5.tex0000644000175000017500000242337014760123736014240 0ustar billbill% Copyright (c) 2000 The PARI Group % % This file is part of the PARI/GP documentation % % Permission is granted to copy, distribute and/or modify this document % under the terms of the GNU General Public License \chapter{Technical Reference Guide: the basics} In the following chapters, we describe all public low-level functions of the PARI library. These include specialized functions for handling all the PARI types. Simple higher level functions, such as arithmetic or transcendental functions, are described in Chapter~3 of the GP user's manual; we will eventually see more general or flexible versions in the chapters to come. A general introduction to the major concepts of PARI programming can be found in Chapter~4, which you should really read first. We shall now study specialized functions, more efficient than the library wrappers, but sloppier on argument checking and damage control; besides speed, their main advantage is to give finer control about the inner workings of generic routines, offering more options to the programmer. \misctitle{Important advice} Generic routines eventually call lower level functions. Optimize your algorithms first, not overhead and conversion costs between PARI routines. For generic operations, use generic routines first; do not waste time looking for the most specialized one available unless you identify a genuine bottleneck, or you need some special behavior the generic routine does not offer. The PARI source code is part of the documentation; look for inspiration there.\smallskip The type \kbd{long} denotes a \tet{BITS_IN_LONG}-bit signed long integer (32 or 64 bits). The type \tet{ulong} is defined as \kbd{unsigned long}. The word \emph{stack} always refer to the PARI stack, allocated through an initial \kbd{pari\_init} call. Refer to Chapters 1--2 and~4 for general background. \kbdsidx{BIL} We shall often refer to the notion of \tev{shallow} function, which means that some components of the result may point to components of the input, which is more efficient than a \emph{deep} copy (full recursive copy of the object tree). Such outputs are not suitable for \kbd{gerepileupto} and particular care must be taken when garbage collecting objects which have been input to shallow functions: corresponding outputs also become invalid and should no longer be accessed. A function is \emph{not stack clean} if it leaves intermediate data on the stack besides its output, for efficiency reasons. \section{Initializing the library} The following functions enable you to start using the PARI functions in a program, and cleanup without exiting the whole program. \subsec{General purpose} \fun{void}{pari_init}{size_t size, ulong maxprime} initialize the library, with a stack of \kbd{size} bytes and a prime table up to the maximum of \kbd{maxprime} and $2^{16}$. Unless otherwise mentioned, no PARI function will function properly before such an initialization. \fun{void}{pari_close}{void} stop using the library (assuming it was initialized with \kbd{pari\_init}) and frees all allocated objects. \subsec{Technical functions}\label{se:pari_init_tech} \fun{void}{pari_init_opts}{size_t size, ulong maxprime, ulong opts} as \kbd{pari\_init}, more flexible. \kbd{opts} is a mask of flags among the following: \kbd{INIT\_JMPm}: install PARI error handler. When an exception is raised, the program is terminated with \kbd{exit(1)}. \kbd{INIT\_SIGm}: install PARI signal handler. \kbd{INIT\_DFTm}: initialize the \kbd{GP\_DATA} environment structure. This one \emph{must} be enabled once. If you close pari, then restart it, you need not reinitialize \kbd{GP\_DATA}; if you do not, then old values are restored. \kbd{INIT\_noPRIMEm}: do not compute the prime table (ignore the \kbd{maxprime} argument). The user \emph{must} call \tet{pari_init_primes} later. \kbd{INIT\_noIMTm}: (technical, see \kbd{pari\_mt\_init} in the Developer's Guide for detail). Do not call \tet{pari_mt_init} to initialize the multi-thread engine. If this flag is set, \kbd{pari\_mt\_init()} will need to be called manually. See \kbd{examples/pari-mt.c} for an example. \kbd{INIT\_noINTGMPm}: do not install PARI-specific GMP memory functions. This option is ignored when the GMP library is not in use. You may install PARI-specific GMP memory functions later by calling \fun{void}{pari_kernel_init}{void} \noindent and restore the previous values using \fun{void}{pari_kernel_close}{void} This option should not be used without a thorough understanding of the problem you are trying to solve. The GMP memory functions are global variables used by the GMP library. If your program is linked with two libraries that require these variables to be set to different values, conflict ensues. To avoid a conflict, the proper solution is to record their values with \kbd{mp\_get\_memory\_functions} and to call \kbd{mp\_set\_memory\_functions} to restore the expected values each time the code switches from using one library to the other. Here is an example: \bprog void *(*pari_alloc_ptr) (size_t); void *(*pari_realloc_ptr) (void *, size_t, size_t); void (*pari_free_ptr) (void *, size_t); void *(*otherlib_alloc_ptr) (size_t); void *(*otherlib_realloc_ptr) (void *, size_t, size_t); void (*otherlib_free_ptr) (void *, size_t); void init(void) { pari_init(8000000, 500000); mp_get_memory_functions(&pari_alloc_ptr,&pari_realloc_ptr, &pari_free_ptr); otherlib_init(); mp_get_memory_functions(&otherlib_alloc_ptr,&otherlib_realloc_ptr, &otherlib_free_ptr); } void function_that_use_pari(void) { mp_set_memory_functions(pari_alloc_ptr,pari_realloc_ptr, pari_free_ptr); /*use PARI functions*/ } void function_that_use_otherlib(void) { mp_set_memory_functions(otherlib_alloc_ptr,otherlib_realloc_ptr, otherlib_free_ptr); /*use OTHERLIB functions*/ } @eprog \fun{void}{pari_close_opts}{ulong init_opts} as \kbd{pari\_close}, for a library initialized with a mask of options using \kbd{pari\_init\_opts}. \kbd{opts} is a mask of flags among \kbd{INIT\_SIGm}: restore \kbd{SIG\_DFL} default action for signals tampered with by PARI signal handler. \kbd{INIT\_DFTm}: frees the \kbd{GP\_DATA} environment structure. \kbd{INIT\_noIMTm}: (technical, see \kbd{pari\_mt\_init} in the Developer's Guide for detail). Do not call \tet{pari_mt_close} to close the multi-thread engine. \kbd{INIT\_noINTGMPm}: do not restore GMP memory functions. \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_init_primes}{ulong maxprime} Initialize the PARI primes. This function is called by \kbd{pari\_init(\dots,maxprime)}. It is provided for users calling \kbd{pari\_init\_opts} with the flag \kbd{INIT\_noPRIMEm}. \fun{void}{pari_sighandler}{int signum} the actual signal handler that PARI uses. This can be used as argument to \kbd{pari\_sig\_init} or \kbd{signal(2)}. \fun{void}{pari_stackcheck_init}{void *stackbase} controls the system stack exhaustion checking code in the GP interpreter. This should be used when the system stack base address change or when the address seen by \kbd{pari\_init} is too far from the base address. If \kbd{stackbase} is \kbd{NULL}, disable the check, else set the base address to \kbd{stackbase}. It is normally used this way \bprog int thread_start (...) { long first_item_on_the_stack; ... pari_stackcheck_init(&first_item_on_the_stack); } @eprog \fun{int}{pari_daemon}{void} forks a PARI daemon, detaching from the main process group. The function returns 1 in the parent, and 0 in the forked son. \fun{void}{paristack_setsize}{size_t rsize, size_t vsize} sets the default \kbd{parisize} to \kbd{rsize} and the default \kbd{parisizemax} to \kbd{vsize}, and reallocate the stack to match these value, destroying its content. Generally used just after \kbd{pari\_init}. \fun{void}{paristack_resize}{ulong newsize} changes the current stack size to \kbd{newsize} (double it if \kbd{newsize} is 0). The new size is clipped to be at least the current stack size and at most \kbd{parisizemax}. The stack content is not affected by this operation. \fun{void}{parivstack_reset}{void} resets the current stack to its default size \kbd{parisize}. This is used to recover memory after a computation that enlarged the stack. This function destroys the content of the enlarged stack (between the old and the new bottom of the stack). Before calling this function, you must ensure that \kbd{avma} lies within the new smaller stack. \fun{void}{paristack_newrsize}{ulong newsize} \emph{(does not return)}. Library version of \bprog default(parisize, "newsize") @eprog\noindent Set the default \kbd{parisize} to \kbd{newsize}, or double \kbd{parisize} if \kbd{newsize} is equal to 0, then call \kbd{cb\_pari\_err\_recover(-1)}. \fun{void}{parivstack_resize}{ulong newsize} \emph{(does not return)}. Library version of \bprog default(parisizemax, "newsize") @eprog\noindent Set the default \kbd{parisizemax} to \kbd{newsize} and call \kbd{cb\_pari\_err\_recover(-1)}. \subsec{Notions specific to the GP interpreter} An \kbd{entree} is the generic object attached 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}: a small integer $\geq 1$ (to which group of function help do we belong, for the \kbd{?$n$} help menu). \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 four modules in PARI/GP: \item general functions (\tet{functions_basic}, known to \kbd{libpari}), \item gp-specific functions (\tet{functions_gp}), \noindent 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); @eprog A GP \kbd{default} is likewise attached to a helper routine, that is run when the value is consulted, or changed by \tet{default0} or \tet{setdefault}. Such routines are grouped in the module \tet{functions_default}. \fun{void}{pari_add_defaults_module}{entree *mod} adds all the defaults in module \kbd{mod} to the interpreter. It assumes that \kbd{pari\_init} has 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_display_hist}{long (*cb_pari_display_hist)(long n)} initialized to \kbd{NULL}. If set, called by \kbd{gp\_embedded} in place of \kbd{gp\_display\_hist}. \doc{cb_pari_init_histfile}{void (*cb_pari_init_histfile)(void)} initialized to \kbd{NULL}. Called when the \kbd{histfile} default is changed. The intent is for that callback to read the file content, append it to history in memory, then dump the expanded history to the new \kbd{histfile}. \doc{cb_pari_is_interactive}{int (*cb_pari_is_interactive)(void)}; initialized to \kbd{NULL}. \doc{cb_pari_quit}{void (*cb_pari_quit)(long)} initialized to a no-op. Called when \kbd{gp} must evaluate the \kbd{quit} command. \doc{cb_pari_start_output}{void (*cb_pari_start_output)(void)} initialized to \kbd{NULL}. \doc{cb_pari_handle_exception}{int (*cb_pari_handle_exception)(long)} initialized to \kbd{NULL}. If not \kbd{NULL}, this routine is called with argument $-1$ on \kbd{SIGINT}, and argument \kbd{err} on error \kbd{err}. If it returns a nonzero value, the error or signal handler returns, in effect further ignoring the error or signal, otherwise it raises a fatal error. A possible simple-minded handler, used by the \kbd{gp} interpreter, is \fun{int}{gp_handle_exception}{long err} if the \kbd{breakloop} default is enabled (set to $1$) and \tet{cb_pari_break_loop} is not \kbd{NULL}, we call this routine with \kbd{err} argument and return the result. \doc{cb_pari_err_handle}{int (*cb_pari_err_handle)(GEN)} If not \kbd{NULL}, this routine is called with a \typ{ERROR} argument from \kbd{pari\_err}. If it returns a nonzero value, the error returns, in effect further ignoring the error, otherwise it raises a fatal error. The default behavior is to print a descriptive error message (display the error), then return 0, thereby raising a fatal error. This differs from \tet{cb_pari_handle_exception} in that the function is not called on \kbd{SIGINT} (which do not generate a \typ{ERROR}), only from \kbd{pari\_err}. Use \tet{cb_pari_sigint} if you need to handle \kbd{SIGINT} as well. The following function can be used by \kbd{cb\_pari\_err\_handle} to display the error message. \fun{const char*}{closure_func_err}{} return a statically allocated string holding the name of the function that triggered the error. Return NULL if the error was not caused by a function. \doc{cb_pari_break_loop}{int (*cb_pari_break_loop)(int)} initialized to \kbd{NULL}. \doc{cb_pari_sigint}{void (*cb_pari_sigint)(void)}. Function called when we receive \kbd{SIGINT}. By default, raises \bprog pari_err(e_MISC, "user interrupt"); @eprog\noindent A possible simple-minded variant, used by the \kbd{gp} interpreter, is \fun{void}{gp_sigint_fun}{void} \doc{cb_pari_pre_recover}{void (*cb_pari_pre_recover)(long)} initialized to \kbd{NULL}. If not \kbd{NULL}, this routine is called just before PARI cleans up from an error. It is not required to return. The error number is passed as argument. \doc{cb_pari_err_recover}{void (*cb_pari_err_recover)(long)} initialized to \kbd{pari\_exit()}. This callback must not return. It is called after PARI has cleaned-up from an error. The error number is passed as argument, unless the PARI stack has been destroyed, in which case 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 nonzero result otherwise. May print a help message. \doc{cb_pari_long_help}{void (*cb_pari_long_help)(const char *s, long n)} It is called in place of the external help, to handle \kbd{??}. \subsec{Configuration variables} \tet{pari_library_path}: If set, It should be a path to the libpari library. It is used by the function \tet{gpinstall} to locate the PARI library when searching for symbols. This should only be useful on Windows. \subsec{Utility functions} \fun{void}{pari_ask_confirm}{const char *s} raise an error if the callback \tet{cb_pari_ask_confirm} is \kbd{NULL}. Otherwise calls \bprog cb_pari_ask_confirm(s); @eprog \fun{char*}{gp_filter}{const char *s} pre-processor for the GP parser: filter out whitespace and GP comments from $s$. The returned string is allocated on the PARI stack and must not be freed. \fun{GEN}{pari_compile_str}{const char *s} low-level form of \tet{compile_str}: assumes that $s$ does not contain spaces or GP comments and returns the closure attached to the GP expression $s$. Note that GP metacommands are not recognized. \fun{int}{gp_meta}{const char *s, int ismain} low-level component of \tet{gp_read_str}: assumes that $s$ does not contain spaces or GP comments and try to interpret $s$ as a GP metacommand (e.g. starting by \kbd{\bs} or \kbd{?}). If successful, execute the metacommand and return $1$; otherwise return $0$. The \kbd{ismain} parameter modifies the way \kbd{\bs r} commands are handled: if nonzero, act as if the file contents were entered via standard input (i.e. call \tet{switchin} and divert \tet{pari_infile}); otherwise, simply call \tet{gp_read_file}. \fun{void}{pari_hit_return}{void} wait for the use to enter \kbd{\bs n} via standard input. \fun{void}{gp_load_gprc}{void} read and execute the user's \kbd{GPRC} file. \fun{void}{pari_center}{const char *s} print $s$, centered. \fun{void}{pari_print_version}{void} print verbose version information. \fun{long}{pari_community}{void} return the index of the support section n the help. \fun{const char*}{gp_format_time}{long t} format a delay of $t$ ms suitable for \kbd{gp} output, with \kbd{timer} set. The string is allocated in the PARI stack via \kbd{stack\_malloc}. \fun{const char*}{gp_format_prompt}{const char *p} format a prompt $p$ suitable for \kbd{gp} prompting (includes colors and protecting ANSI escape sequences for readline). \fun{void}{pari_alarm}{long s} set an alarm after $s$ seconds (raise an \tet{e_ALARM} exception). \fun{void}{gp_help}{const char *s, long flag} print help for $s$, depending on the value of \fl: \item \tet{h_REGULAR}, basic help (\kbd{?}); \item \tet{h_LONG}, extended help (\kbd{??}); \item \tet{h_APROPOS}, a propos help (\kbd{??}). \fun{const char **}{gphelp_keyword_list}{void} return a \kbd{NULL}-terminated array a strings, containing keywords known to \kbd{gphelp} besides GP functions (e.g. \kbd{modulus} or \kbd{operator}). Used by the online help system and the contextual completion engine. \fun{void}{gp_echo_and_log}{const char *p, const char *s} given a prompt $p$ and attached input command $s$, update logfile and possibly print on standard output if \tet{echo} is set and we are not in interactive mode. The callback \tet{cb_pari_is_interactive} must be set to a sensible value. \fun{void}{gp_alarm_handler}{int sig} the \kbd{SIGALRM} handler set by the \kbd{gp} interpreter. \fun{void}{print_fun_list}{char **list, long n} print all elements of \kbd{list} in columns, pausing (hit return) every $n$ lines. \kbd{list} is \kbd{NULL} terminated. \subsec{Saving and restoring the GP context} \fun{void}{gp_context_save}{struct gp_context* rec} save the current GP context. \fun{void}{gp_context_restore}{struct gp_context* rec} restore a GP context. The new context must be an ancestor of the current context. \subsec{GP history} These functions allow to control the GP history (the \kbd{\%} operator). \fun{void}{pari_add_hist}{GEN x, long t, long r} adds \kbd{x} as the last history entry; $t$ (resp. r) is the cpu (resp. real) time used to compute it. \fun{GEN}{pari_get_hist}{long p}, if $p>0$ returns entry of index $p$ (i.e. \kbd{\%p}), else returns entry of index $n+p$ where $n$ is the index of the last entry (used for \kbd{\%}, \kbd{\%`}, \kbd{\%``}, etc.). \fun{long}{pari_get_histtime}{long p} as \tet{pari_get_hist}, returning the cpu time used to compute the history entry, instead of the entry itself. \fun{long}{pari_get_histrtime}{long p} as \tet{pari_get_hist}, returning the real time used to compute the history entry, instead of the entry itself. \fun{GEN}{pari_histtime}{long p} return the vector \kbd{[cpu, real]} where \kbd{cpu} and \kbd{real} are as above. \fun{ulong}{pari_nb_hist}{void} return the index of the last entry. \fun{void}{gp_display_hist}{long n} print the history entry $n$ using the usual GP format "$\%n = \dots$". \fun{void}{str_display_hist}{pari_str *S, long n} as \kbd{gp\_display\_hist}, but output to the string $S$. \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 prec} allocates a \typ{REAL} of precision \kbd{prec}. Sets $z[0]$ only. \fun{GEN}{cgetc}{long prec} allocates a \typ{COMPLEX} whose real and imaginary parts are \typ{REAL}s of precision \kbd{prec}. \fun{GEN}{cgetg_copy}{GEN x, long *lx} fast version of \kbd{cgetg}: allocate a \kbd{GEN} with the same type and length as $x$, setting \kbd{*lx} to \kbd{lg(x)} as a side-effect. (Only sets the first codeword.) This is a little faster than \kbd{cgetg} since we may reuse the bitmask in $x[0]$ instead of recomputing it, and we do not need to check that the length does not overflow the possibilities of the implementation (since an object with that length already exists). Note that \kbd{cgetg} with arguments known at compile time, as in \bprog cgetg(3, t_INTMOD) @eprog\noindent will be even faster since the compiler will directly perform all computations and checks. \fun{GEN}{vectrunc_init}{long l} perform \kbd{cgetg(l,t\_VEC)}, then set the length to $1$ and return the result. This is used to implement vectors whose final length is easily bounded at creation time, that we intend to fill gradually using: \fun{void}{vectrunc_append}{GEN x, GEN y} assuming $x$ was allocated using \tet{vectrunc_init}, appends $y$ as the last element of $x$, which grows in the process. The function is shallow: we append $y$, not a copy; it is equivalent to \bprog long lx = lg(x); gel(x,lx) = y; setlg(x, lx+1); @eprog\noindent Beware that the maximal size of $x$ (the $l$ argument to \tet{vectrunc_init}) is unknown, hence unchecked, and stack corruption will occur if we append more than $l-1$ elements to $x$. Use the safer (but slower) \kbd{shallowconcat} when $l$ is not easy to bound in advance. An other possibility is simply to allocate using \kbd{cgetg(l, t)} then fill the components as they become available: this time the downside is that we do not obtain a correct \kbd{GEN} until the vector is complete. Almost no PARI function will be able to operate on it. \fun{void}{vectrunc_append_batch}{GEN x, GEN y} successively apply \bprog vectrunc_append(x, gel(y, i)) @eprog for all elements of the vector $y$. \fun{GEN}{coltrunc_init}{long l} as \kbd{vectrunc\_init} but perform \kbd{cgetg(l,t\_COL)}. \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 nonnegative 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 bits. \fun{long}{ndec2nbits}{long x} convers a number of decimal digits to a number of bits. \fun{long}{prec2ndec}{long x} converts a number of bits 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}{nbits2ndec}{long x} converts a number of bits to a number of decimal digits. \fun{long}{nbits2lg}{long x} converts a number of bits to a length in code words. Currently an alias for \kbd{nbits2nlong}. \fun{long}{prec2lg}{long x} return the length of a \typ{REAL} of precision \kbd{x}. \fun{long}{lg2prec}{long x} return the maximal precision of a \typ{REAL} of length \kbd{x}. \fun{long}{nbits2prec}{long x} convert $x$ to a valid precision. \fun{long}{nbits2extraprec}{long x} convert $x$ to a valid precision. \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}{prec2nbits}{long x} return $x$. For backward compatibility. \fun{double}{prec2nbits_mul}{long x, double y} returns $x\times y$. For backward compatibility. \fun{long}{bit_accuracy}{long x} converts a length into a number of significant bits; \fun{double}{bit_accuracy_mul}{long x, double y} returns \kbd{bit\_accuracy}$(x)\times y$. \fun{long}{realprec}{GEN x} precision of a \typ{REAL} in bits. \fun{long}{bit_prec}{GEN x} precision of a \typ{REAL} in bits. \fun{long}{precdbl}{long x} return $2*x$. \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} and \typ{QUAD} of positive discriminants. Raise a type error if \kbd{typ(x)} is not among those. \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}{gexpo_safe}{GEN x} same as \kbd{gexpo}, but returns a value strictly less than \hbox{\kbd{-HIGHEXPOBIT}} when the exponent is not defined (e.g. for a \typ{PADIC} or \typ{INTMOD} component). \fun{long}{valp}{GEN x} returns the $p$-adic valuation (for a \typ{PADIC}). \fun{long}{valser}{GEN x} returns the $X$-adic valuation (for a \typ{SER}). \fun{long}{precp}{GEN x} returns the precision of the \typ{PADIC}~\kbd{x}. \fun{long}{varn}{GEN x} returns the variable number of the \typ{POL} or \typ{SER}~\kbd{x} (between 0 and \kbd{MAXVARN}). \fun{long}{gvar}{GEN x} returns the main variable number when any variable at all occurs in the composite object~\kbd{x} (the smallest variable number which occurs), and \tet{NO_VARIABLE} otherwise. \fun{long}{gvar2}{GEN x} returns the variable number for the ring over which $x$ is defined, e.g. if $x\in \Z[a][b]$ return (the variable number for) $a$. Return \tet{NO_VARIABLE} if $x$ has no variable or is not defined over a polynomial ring. \fun{long}{degpol}{GEN x} is a simple macro returning \kbd{lg(x) - 3}. This is the degree of the \typ{POL}~\kbd{x} with respect to its main variable, \emph{if} its leading coefficient is nonzero (a rational $0$ is impossible, but an inexact $0$ is allowed, as well as an exact modular $0$, e.g. \kbd{Mod(0,2)}). If $x$ has no coefficients (rational $0$ polynomial), its length is $2$ and we return the expected $-1$. \fun{long}{lgpol}{GEN x} is equal to \kbd{degpol(x) + 1}. Used to loop over the coefficients of a \typ{POL} in the following situation: \bprog GEN xd = x + 2; long i, l = lgpol(x); for (i = 0; i < l; i++) foo( xd[i] ). @eprog \fun{long}{precision}{GEN x} If \kbd{x} is of type \typ{REAL}, returns the precision of~\kbd{x}, namely \item if \kbd{x} is not zero: the length of \kbd{x} in \B-bit words; \item if \kbd{x} is numerically equal to $0$, of exponent $e$: the absolute accuracy \kbd{nbits2prec}$(e)$ if $e < 0$ and \kbd{LOWDEFAULTPREC} if $e \geq 0$. 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). In all cases, the precision is either $0$ or can be used as a \kbd{prec} parameter in transcendental functions. \fun{long}{lgcols}{GEN x} is equal to \kbd{lg(gel(x,1))}. This is the length of the columns of a \typ{MAT} with at least one column. \fun{long}{nbrows}{GEN x} is equal to \kbd{lg(gel(x,1))-1}. This is the number of rows of a \typ{MAT} with at least one column. \fun{long}{gprecision}{GEN x} as \kbd{precision} for scalars. Returns the lowest precision encountered among the components otherwise. \fun{long}{sizedigit}{GEN x} returns 0 if \kbd{x} is exactly~0. Otherwise, returns \kbd{\key{gexpo}(x)} multiplied by $\log_{10}(2)$. This gives a crude estimate for the maximal number of decimal digits of the components of~\kbd{x}. \subsec{Eval type-dependent information} These routines convert type-dependent information to bitmask to fill the codewords of \kbd{GEN} objects (see \secref{se:impl}). E.g for a \typ{REAL}~\kbd{z}: \bprog z[1] = evalsigne(-1) | evalexpo(2) @eprog Compatible components of a codeword for a given type can be OR-ed as above. \fun{ulong}{evaltyp}{long x} convert type~\kbd{x} to bitmask (first codeword of all \kbd{GEN}s) \fun{long}{evallg}{long x} convert length~\kbd{x} to bitmask (first codeword of all \kbd{GEN}s). Raise overflow error if \kbd{x} is so large that the corresponding length cannot be represented \fun{long}{_evallg}{long x} as \kbd{evallg} \emph{without} the overflow check. \fun{ulong}{evalvarn}{long x} convert variable number~\kbd{x} to bitmask (second codeword of \typ{POL} and \typ{SER}) \fun{long}{evalsigne}{long x} convert sign~\kbd{x} (in $-1,0,1$) to bitmask (second codeword of \typ{INT}, \typ{REAL}, \typ{POL}, \typ{SER}) \fun{long}{evalprecp}{long x} convert $p$-adic ($X$-adic) precision~\kbd{x} to bitmask (second codeword of \typ{PADIC}, \typ{SER}). Raise overflow error if \kbd{x} is so large that the corresponding precision cannot be represented. \fun{long}{_evalprecp}{long x} same as \kbd{evalprecp} \emph{without} the overflow check. \fun{long}{evalvalp}{long x} convert $p$-adic valuation~\kbd{x} to bitmask (second codeword of \typ{PADIC}). 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}{evalvalser}{long x} convert $X$-adic valuation~\kbd{x} to bitmask (second codeword of \typ{SER}). Raise overflow error if \kbd{x} is so large that the corresponding valuation cannot be represented. \fun{long}{_evalvalser}{long x} same as \kbd{evalvalser} \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 valuation of~\kbd{x} to~\kbd{s}, if \kbd{x} is a \typ{PADIC}. \fun{void}{setvalser}{GEN x, long s} sets the $X$-adic valuation of~\kbd{x} to~\kbd{s}, if \kbd{x} is 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 nonrecursive types are \typ{INT}, \typ{REAL}, \typ{STR}, \typ{VECSMALL}). Somewhat contrary to intuition, \typ{LIST} is also nonrecursive, ; 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_real_t}{long t} \kbd{true} iff \kbd{t} is \typ{INT} or \typ{REAL} or \typ{FRAC}. \fun{int}{is_qfb_t}{long t} \kbd{true} iff \kbd{t} is \typ{QFB}. \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_coeff}{GEN x} returns the address of the constant coefficient of \typ{POL}~\kbd{x}. By convention, a $0$ polynomial (whose \kbd{sign} is $0$) has \kbd{gen\_0} constant term. \fun{GEN}{leading_coeff}{GEN x} returns the address of the leading coefficient of \typ{POL}~\kbd{x}, i.e. the coefficient of largest index stored in the array representing $x$. This may be an inexact $0$. By convention, return \kbd{gen\_0} if the coefficient array is empty. \fun{GEN}{gel}{GEN x, long i} returns the address of the \kbd{x[i]} entry of~\kbd{x}. (\kbd{el} stands for element.) \fun{GEN}{gcoeff}{GEN x, long i, long j} returns the address of the \kbd{x[i,j]} entry of \typ{MAT}~\kbd{x}, i.e.~the coefficient at row~\kbd{i} and column~\kbd{j}. \fun{GEN}{gmael}{GEN x, long i, long j} returns the address of the \kbd{x[i][j]} entry of~\kbd{x}. (\kbd{mael} stands for multidimensional array element.) \fun{GEN}{gmael2}{GEN A, long x1, long x2} is an alias for \kbd{gmael}. Similar macros \tet{gmael3}, \tet{gmael4}, \tet{gmael5} are available. \section{Global numerical constants} These are defined in the various public PARI headers. \subsec{Constants related to word size} \noindent \kbd{long} $\tet{BITS_IN_LONG} = 2^{\tet{TWOPOTBITS_IN_LONG}}$: number of bits in a \kbd{long} (32 or 64). \noindent \kbd{long} \tet{BITS_IN_HALFULONG}: \kbd{BITS\_IN\_LONG} divided by $2$. \noindent \kbd{long} \tet{LONG_MAX}: the largest positive \kbd{long}. \noindent \kbd{ulong} \tet{ULONG_MAX}: the largest \kbd{ulong}. \noindent \kbd{long} \tet{DEFAULTPREC}: the length (\kbd{lg}) of a \typ{REAL} with 64 bits of accuracy \noindent \kbd{long} \tet{MEDDEFAULTPREC}: the length (\kbd{lg}) of a \typ{REAL} with 128 bits of accuracy \noindent \kbd{long} \tet{BIGDEFAULTPREC}: the length (\kbd{lg}) of a \typ{REAL} with 192 bits of accuracy \noindent \kbd{ulong} \tet{HIGHBIT}: the largest power of $2$ fitting in an \kbd{ulong}. \noindent \kbd{ulong} \tet{LOWMASK}: bitmask yielding the least significant bits. \noindent \kbd{ulong} \tet{HIGHMASK}: bitmask yielding the most significant bits. \noindent The last two are used to implement the following convenience macros, returning half the bits of their operand: \fun{ulong}{LOWWORD}{ulong a} returns least significant bits. \fun{ulong}{HIGHWORD}{ulong a} returns most significant bits. \noindent Finally \fun{long}{divsBIL}{long n} returns the Euclidean quotient of $n$ by \kbd{BITS\_IN\_LONG} (with nonnegative remainder). \fun{long}{remsBIL}{n} returns the (nonnegative) 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{M_PI}: $\pi$. \noindent \tet{M_LN2}: $\log 2$. \noindent \tet{LOG10_2}: $\log 2 / \log 10$. \noindent \tet{LOG2_10}: $\log 10 / \log 2$. \section{Iterating over small primes, low-level interface} \label{se:primetable} One of the methods used by the high-level prime iterator (see \secref{se:primeiter}), is a precomputed table. Its direct use is deprecated, but documented here. After \kbd{pari\_init(size, maxprime)}, a prime table \kbd{pari\_PRIMES} is initialized with the successive primes up to (possibly just a little beyond) \kbd{maxprime}. The prime table occupies roughly $4 \kbd{maxprime}/\log(\kbd{maxprime})$ bytes in memory, so be sensible when choosing \kbd{maxprime}; it is $2^{20}$ by default under \kbd{gp} and there is no real benefit in choosing a much larger value: the high-level iterator provide \emph{fast} access to primes up to the \emph{square} of \kbd{maxprime}. In any case, the implementation requires that $\tet{maxprime} < 2^{\B} - 2048$, whatever memory is available. In fact, \kbd{maxprime} is automatically replaced by $$\max(\kbd{maxprime}, 65557)\enspace.$$ In particular, PARI guarantees that the first 6547 primes, up to and including 65557, are present in the table, even if you set \kbd{maxprime} to zero in the \kbd{pari\_init} call. \noindent Some convenience functions: \fun{ulong}{maxprime}{void} the largest prime computable using our prime table. \fun{ulong}{maxprimeN}{void} the index $N$ of the largest prime computable using the prime table. I.e., $p_N = \kbd{maxprime()}$. \fun{GEN}{prodprimes}{void} a vector $T$ where \kbd{T[i]} is the product of the primes in our prime table that are smaller than $2^{7+i}$. Used to quickly detect small prime divisors of large integers, using a few gcd's. \fun{ulong}{maxprimelim}{void} the argument used for the last \kbd{initprimetable} call. This is at least $65537$ and the largest prime less than or equal to this number is \kbd{maxprime}$()$. \fun{long}{PRIMES_search}{ulong x} assumes $x \leq \kbd{maxprimelim()}$. Return $i > 0$ such that $x = \kbd{pari\_PRIMES}[i]$ iff $x$ is prime. Else return $-i < 0$ such that $x$ lies (strictly) between the $(i-1)$-th and the $i$-th prime; this is understood as $i = 1$ when $x < 2$: the statement about the non-existing $0$-th prime is disregarded. \fun{void}{maxprime_check}{ulong B} raise an error if \kbd{maxprime()} is $< B$. \fun{void}{initprimetable}{ulong maxprime} computes the prime table \kbd{pari\_PRIMES} (of all primes $p < \kbd{maxprime}$). This caches data allowing fast \kbd{prodprimes()}. \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{void}{new_chunk_resize}{size_t x} this function is called by \kbd{new\_chunk} when the PARI stack overflows. There is no need to call it manually. It will either extend the stack or report an \kbd{e\_STACK} error. \fun{char*}{stack_malloc}{size_t n} allocates memory on the stack for $n$ chars (\emph{not} $n$ \kbd{GEN}s). This is faster than using \kbd{malloc}, and easier to use in most situations when temporary storage is needed. In particular there is no need to \kbd{free} individually all variables thus allocated: a simple \kbd{set\_avma(oldavma)} might be enough. On the other hand, beware that this is not permanent independent storage, but part of the stack. The memory is aligned on \kbd{sizeof(long)} bytes boundaries. \fun{char*}{stack_malloc_align}{size_t n, long k} as \kbd{stack\_malloc}, but the memory is aligned on \kbd{k} bytes boundaries. The number\kbd{k} must be a multiple of the \kbd{sizeof(long)}. \fun{char*}{stack_calloc}{size_t n} as \kbd{stack\_malloc}, setting the memory to zero. \fun{char*}{stack_calloc_align}{size_t n, long k} as \kbd{stack\_malloc\_align}, setting the memory to zero. \noindent Objects allocated through these last three functions cannot be \kbd{gerepile}'d, since they are not yet valid \kbd{GEN}s: their codewords must be filled first. \fun{GEN}{cgetalloc}{size_t l, long t}, same as \kbd{cgetg(l, t)}, 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 nonrecursive type; private low-level routines must be called first to restore absolute addresses. \fun{void}{shiftaddress}{GEN x, long dec} converts relative addresses to absolute ones. \fun{void}{shiftaddress_canon}{GEN x, long dec} converts relative addresses to absolute ones, and converts leaves from a canonical form to the one specific to the multiprecision kernel in use. The \kbd{GENbin} type stores whether leaves are stored in canonical form, so \kbd{bin\_copy} can call the right variant. \noindent Objects containing closures are harder to e.g. copy and save to disk, since closures contain pointers to libpari functions that will not be valid in another gp instance: there is little chance for them to be loaded at the exact same address in memory. Such objects must be saved along with a linking table. \fun{GEN}{copybin_unlink}{GEN C} returns a linking table allowing to safely store and transmit \typ{CLOSURE} objects in $C$. If $C = \kbd{NULL}$ return a linking table corresponding to the content of all gp variables. $C$ may then be dumped to disk in binary form, for instance. \fun{void}{bincopy_relink}{GEN C, GEN V} given a binary object $C$, as dumped by writebin and read back into a session, and a linking table $V$, restore all closures contained in $C$ (function pointers are translated to their current value). \subsec{Garbage collection} See \secref{se:garbage} for a detailed explanation and many examples. \fun{void}{set_avma}{ulong av} reset \kbd{avma} to \kbd{av}. You may think of this as a simple \kbd{avma = av} statement, but PARI developpers modify this statement in special code branches to detect garbage collecting issues (by invalidating the PARI stack below \kbd{av}). \fun{ulong}{get_avma}{void} return \kbd{avma}. Useful for languages that do not provide access to TLS variables. \fun{GEN}{gc_NULL}{pari_sp av} reset \kbd{avma} to \kbd{av} and return \kbd{NULL}. The following 6 functions reset \kbd{avma} to \kbd{av} and return $x$: \fun{int}{gc_bool}{pari_sp av, int x} \fun{double}{gc_double}{pari_sp av, double x} \fun{int}{gc_int}{pari_sp av, int x} \fun{long}{gc_long}{pari_sp av, long x} \fun{ulong}{gc_ulong}{pari_sp av, ulong x} This allows for instance to return \kbd{gc\_ulong(av, itou(z))}, whereas \bprog pari_sp av = avma; GEN z = ... set_avma(av); return itou(z); @eprog should be frowned upon since \kbd{set\_avma(av)} conceptually destroys everything from the reference point on, including $z$. \fun{GEN}{gc_const}{pari_sp av, GEN x} assumes that $x$ is either not on the stack (clone, universal constant such as \kbd{gen\_0}) or was defined before \kbd{av}. \fun{GEN}{gc_stoi}{pari_sp av, long x} reset \kbd{avma} to \kbd{av} and return \kbd{stoi(x)}. \fun{GEN}{gc_utoi}{pari_sp av, long x} reset \kbd{avma} to \kbd{av} and return \kbd{utoi(x)}. \fun{GEN}{gc_utoipos}{pari_sp av, long x} reset \kbd{avma} to \kbd{av} and return \kbd{utoipos(x)}. \fun{GEN}{gc_all}{pari_sp av, int n, ...}. Assumes that $1 \leq n \leq 10$; This is similar to \kbd{gerepileall}, expecting $n$ further \kbd{GEN*} arguments: the stack is cleaned and the corresponding \kbd{GEN} are copied to the stack starting from \kbd{av} (in this order: the first argument comes first), and the first such \kbd{GEN} is returned. To be used in the following scenario: \bprog GEN f(..., GEN *py) { pari_sp av = avma; GEN x = ..., y = ... *py = y; return gc_all(av, 2, &x, py); } @eprog\noindent This function returns $x$, and the user also recovers $y$ as a side effect. Not that we can later use \kbd{cgiv}$(y)$ to recover the memory used by $y$ while still keeping $x$. \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{set\_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 nonrecursive type (\kbd{is\_recursive\_t(typ(q))} is nonzero). 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 nonrecursive 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)}. \fun{void}{dbg_fill_stack}{void} marks the unused portion of the stack (between its bottom and \kbd{avma}) with repeated magic values: \kbd{0xBADC0FFEE0DDF00D} on 64-bit archs, and \kbd{0xDEADBEEF} on 32-bit. This allows to quickly detect garbage collection errors, e.g., objets one of whose component would be overwritten later or uninitialized memory access. The \kbd{valgrind} framework more thorough possibilities but requires instrumenting the code. \subsec{Copies} \fun{GEN}{gcopy}{GEN x} creates a new copy of $x$ on the stack. \fun{GEN}{gcopy_lg}{GEN x, long l} creates a new copy of $x$ on the stack, pretending that \kbd{lg(x)} is $l$, which must be less than or equal to \kbd{lg(x)}. If equal, the function is equivalent to \kbd{gcopy(x)}. \fun{int}{isonstack}{GEN x} \kbd{true} iff $x$ belongs to the stack. \fun{void}{copyifstack}{GEN x, GEN y} sets \kbd{y = gcopy(x)} if $x$ belongs to the stack, and \kbd{y = x} otherwise. This macro evaluates its arguments once, contrary to \bprog y = isonstack(x)? gcopy(x): x; @eprog \fun{void}{icopyifstack}{GEN x, GEN y} as \kbd{copyifstack} assuming \kbd{x} is a \typ{INT}. \subsec{Simplify} \fun{GEN}{simplify}{GEN x} you should not need that function in library mode. One rather uses: \fun{GEN}{simplify_shallow}{GEN x} shallow, faster, version of \tet{simplify}. \section{The PARI heap} \subsec{Introduction} It is implemented as a doubly-linked list of \kbd{malloc}'ed blocks of memory, equipped with reference counts. Each block has type \kbd{GEN} but need not be a valid \kbd{GEN}: it is a chunk of data preceded by a hidden header (meaning that we allocate $x$ and return $x + \kbd{header size}$). A \tev{clone}, created by \tet{gclone}, is a block which is a valid \kbd{GEN} and whose \emph{clone bit} is set. \subsec{Public interface} \fun{GEN}{newblock}{size_t n} allocates a block of $n$ \emph{words} (not bytes). \fun{void}{killblock}{GEN x} deletes the block~$x$ created by \kbd{newblock}. Fatal error if $x$ not a block. \fun{GEN}{gclone}{GEN x} creates a new permanent copy of $x$ on the heap (allocated using \kbd{newblock}). The \emph{clone bit} of the result is set. \fun{GEN}{gcloneref}{GEN x} if $x$ is not a clone, clone it and return the result; otherwise, increase the clone reference count and return $x$. \fun{void}{gunclone}{GEN x} deletes a clone. Deletion at first only decreases the reference count by $1$. If the count remains positive, no further action is taken; if the count becomes zero, then the clone is actually deleted. In the current implementation, this is an alias for \kbd{killblock}, but it is cleaner to kill clones (valid \kbd{GEN}s) using this function, and other blocks using \kbd{killblock}. \fun{void}{guncloneNULL}{GEN x} same as \kbd{gunclone}, first checking whether $x$ is \kbd{NULL} (and doing nothing in this case). \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}{guncloneNULL_deep}{GEN x} same as \kbd{gunclone\_deep}, first checking whether $x$ is \kbd{NULL} (and doing nothing in this case). \fun{void}{traverseheap}{void(*f)(GEN, void *), void *data} this applies \kbd{f($x$, data)} to each object $x$ on the PARI heap, most recent first. Mostly for debugging purposes. \fun{GEN}{getheap}{} a simple wrapper around \kbd{traverseheap}. Returns a two-component row vector giving the number of objects on the heap and the amount of memory they occupy in long words. \fun{GEN}{cgetg_block}{long x, long y} as \kbd{cgetg(x,y)}, creating the return value as a \kbd{block}, not on the PARI stack. \fun{GEN}{cgetr_block}{long prec} as \kbd{cgetr(prec)}, creating the return value as a \kbd{block}, not on the PARI stack. \subsec{Implementation note} The hidden block header is manipulated using the following private functions: \fun{void*}{bl_base}{GEN x} returns the pointer that was actually allocated by \kbd{malloc} (can be freed). \fun{long}{bl_refc}{GEN x} the reference count of $x$: the number of pointers to this block. Decremented in \kbd{killblock}, incremented by the private function \fun{void}{gclone_refc}{GEN x}; block is freed when the reference count reaches $0$. \fun{long}{bl_num}{GEN x} the index of this block in the list of all blocks allocated so far (including freed blocks). Uniquely identifies a block until $2^\B$ blocks have been allocated and this wraps around. \fun{GEN}{bl_next}{GEN x} the block \emph{after} $x$ in the linked list of blocks (\kbd{NULL} if $x$ is the last block allocated not yet killed). \fun{GEN}{bl_prev}{GEN x} the block allocated \emph{before} $x$ (never \kbd{NULL}). We documented the last four routines as functions for clarity (and type checking) but they are actually macros yielding valid lvalues. It is allowed to write \kbd{bl\_refc(x)++} for instance. \section{Handling user and temp variables} Low-level implementation of user / temporary variables is liable to change. We describe it nevertheless for completeness. Currently variables are implemented by a single array of values divided in 3 zones: 0--\kbd{nvar} (user variables), \kbd{max\_avail}--\kbd{MAXVARN} (temporary variables), and \kbd{nvar+1}--\kbd{max\_avail-1} (pool of free variable numbers). \subsec{Low-level} \fun{void}{pari_var_init}{}: a small part of \kbd{pari\_init}. Resets variable counters \kbd{nvar} and \kbd{max\_avail}, notwithstanding existing variables! In effect, this even deletes \kbd{x}. Don't use it. \fun{void}{pari_var_close}{void} attached destructor, called by \kbd{pari\_close}. \fun{long}{pari_var_next}{}: returns \kbd{nvar}, the number of the next user variable we can create. \fun{long}{pari_var_next_temp}{} returns \kbd{max\_avail}, the number of the next temp variable we can create. \fun{long}{pari_var_create}{entree *ep} low-level initialization of an \kbd{EpVAR}. Return the attached (new) variable number. \fun{GEN}{vars_sort_inplace}{GEN z} given a \typ{VECSMALL} $z$ of variable numbers, sort $z$ in place according to variable priorities (highest priority comes first). \fun{GEN}{vars_to_RgXV}{GEN h} given a \typ{VECSMALL} $z$ of variable numbers, return the \typ{VEC} of \kbd{pol\_x}$(z[i])$. \subsec{User variables} \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{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*} attached 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. \section{Adding functions to PARI} \subsec{Nota Bene} % As mentioned in the \kbd{COPYING} file, modified versions of the PARI package can be distributed under the conditions of the GNU General Public License. If you do modify PARI, however, it is certainly for a good reason, and we would like to know about it, so that everyone can benefit from your changes. There is then a good chance that your improvements are incorporated into the next release. We classify changes to PARI into four rough classes, where changes of the first three types are almost certain to be accepted. The first type includes all improvements to the documentation, in a broad sense. This includes correcting typos or inaccuracies of course, but also items which are not really covered in this document, e.g.~if you happen to write a tutorial, or pieces of code exemplifying fine points unduly omitted in the present manual. The second type is to expand or modify the configuration routines and skeleton files (the \kbd{Configure} script and anything in the \kbd{config/} subdirectory) so that compilation is possible (or easier, or more efficient) on an operating system previously not catered for. This includes discovering and removing idiosyncrasies in the code that would hinder its portability. The third type is to modify existing (mathematical) code, either to correct bugs, to add new functionality to existing functions, or to improve their efficiency. Finally the last type is to add new functions to PARI. We explain here how to do this, so that in particular the new function can be called from \kbd{gp}. \subsec{Coding guidelines}\label{se:coding_guidelines} \noindent Code your function in a file of its own, using as a guide other functions in the PARI sources. One important thing to remember is to clean the stack before exiting your main function, since otherwise successive calls to the function clutters the stack with unnecessary garbage, and stack overflow occurs sooner. Also, if it returns a \kbd{GEN} and you want it to be accessible to \kbd{gp}, you have to make sure this \kbd{GEN} is suitable for \kbd{gerepileupto} (see \secref{se:garbage}). If error messages or warnings are to be generated in your function, use \kbd{pari\_err} and \kbd{pari\_warn} respectively. Recall that \kbd{pari\_err} does not return but ends with a \kbd{longjmp} statement. As well, instead of explicit \kbd{printf}~/ \kbd{fprintf} statements, use the following encapsulated variants: \fun{void}{pari_putc}{char c}: write character \kbd{c} to the output stream. \fun{void}{pari_puts}{char *s}: write \kbd{s} to the output stream. \fun{void}{pari_printf}{const char *fmt, ...}: write following arguments to the output stream, according to the conversion specifications in format \kbd{fmt} (see \tet{printf}). \fun{void}{err_printf}{const char *fmt, ...}: as \tet{pari_printf}, writing to PARI's current error stream. \fun{void}{err_flush}{void} flush error stream. Declare all public functions in an appropriate header file, if you want to access them from C. The other functions should be declared \kbd{static} in your file. Your function is now ready to be used in library mode after compilation and creation of the library. If possible, compile it as a shared library (see the \kbd{Makefile} coming with the \kbd{extgcd} example in the distribution). It is however still inaccessible from \kbd{gp}.\smallskip \subsec{GP prototypes, parser codes} \label{se:gp.interface} A \tev{GP prototype} is a character string describing all the GP parser needs to know about the function prototype. It contains a sequence of the following atoms: \settabs\+\indent&\kbd{Dxxx}\quad&\cr \noindent\item Return type: \kbd{GEN} by default (must be valid for \kbd{gerepileupto}), otherwise the following can appear as the \emph{first} char of the code string: % \+& \kbd{i} & return \kbd{int}\cr \+& \kbd{l} & return \kbd{long}\cr \+& \kbd{u} & return \kbd{ulong}\cr \+& \kbd{v} & return \kbd{void}\cr \+& \kbd{m} & return a \kbd{GEN} which is not \kbd{gerepile}-safe.\cr The \kbd{m} code is used for member functions, to avoid unnecessary copies. A copy opcode is generated by the compiler if the result needs to be kept safe for later use. \noindent\item Mandatory arguments, appearing in the same order as the input arguments they describe: % \+& \kbd{G} & \kbd{GEN}\cr \+& \kbd{\&}& \kbd{*GEN}\cr \+& \kbd{L} & \kbd{long} (we implicitly typecast \kbd{int} to \kbd{long})\cr \+& \kbd{U} & \kbd{ulong} \cr \+& \kbd{V} & loop variable\cr \+& \kbd{n} & variable, expects a \idx{variable number} (a \kbd{long}, not an \kbd{*entree})\cr \+& \kbd{W} & a \kbd{GEN} which is a lvalue to be modified in place (for \typ{LIST})\cr \+& \kbd{r} & raw input (treated as a string without quotes). Quoted args are copied as strings\cr \+&&\quad Stops at first unquoted \kbd{')'} or \kbd{','}. Special chars can be quoted using \kbd{'\bs'}\cr \+&&\quad Example: \kbd{aa"b\bs n)"c} yields the string \kbd{"aab\bs{n})c"}\cr \+& \kbd{s} & expanded string. Example: \kbd{Pi"x"2} yields \kbd{"3.142x2"}\cr \+&&\quad Unquoted components can be of any PARI type, converted to string following\cr \+&&\quad current output format\cr \+& \kbd{I} & closure whose value is ignored, as in \kbd{for} loops,\cr \+&&\quad to be processed by \fun{void}{closure_evalvoid}{GEN C}\cr \+& \kbd{E} & closure whose value is used, as in \kbd{sum} loops,\cr \+&&\quad to be processed by \fun{void}{closure_evalgen}{GEN C}\cr \+& \kbd{J} & implicit function of arity $1$, as in \kbd{parsum} loops,\cr \+&&\quad to be processed by \fun{void}{closure_callgen1}{GEN C}\cr \noindent A \tev{closure} is a GP function in compiled (bytecode) form. It can be efficiently evaluated using the \kbd{closure\_eval}$xxx$ functions. \noindent\item Automatic arguments: % \+& \kbd{f} & Fake \kbd{*long}. C function requires a pointer but we do not use the resulting \kbd{long}\cr \+& \kbd{b} & current real precision in bits \cr \+& \kbd{p} & current real precision in words \cr \+& \kbd{P} & series precision (default \kbd{seriesprecision}, global variable \kbd{precdl} for the library)\cr \+& \kbd{C} & lexical context (internal, for \kbd{eval}, see \kbd{localvars\_read\_str})\cr \noindent\item Syntax requirements, used by functions like \kbd{for}, \kbd{sum}, etc.: % \+& \kbd{=} & separator \kbd{=} required at this point (between two arguments)\cr \noindent\item Optional arguments and default values: % \+& \kbd{E*} & any number of expressions, possibly 0 (see \kbd{E})\cr \+& \kbd{s*} & any number of strings, possibly 0 (see \kbd{s})\cr \+& \kbd{D\var{xxx}} & argument can be omitted and has a default value\cr The \kbd{E*} code reads all remaining arguments in closure context and passes them as a single \typ{VEC}. The \kbd{s*} code reads all remaining arguments in \tev{string context} and passes the list of strings as a single \typ{VEC}. The automatic concatenation rules in string context are implemented so that adjacent strings are read as different arguments, as if they had been comma-separated. For instance, if the remaining argument sequence is: \kbd{"xx" 1, "yy"}, the \kbd{s*} atom sends \kbd{[a, b, c]}, where $a$, $b$, $c$ are \kbd{GEN}s of type \typ{STR} (content \kbd{"xx"}), \typ{INT} (equal to $1$) and \typ{STR} (content \kbd{"yy"}). The format to indicate a default value (atom starts with a \kbd{D}) is ``\kbd{D\var{value},\var{type},}'', where \var{type} is the code for any mandatory atom (previous group), \var{value} is any valid GP expression which is converted according to \var{type}, and the ending comma is mandatory. For instance \kbd{D0,L,} stands for ``this optional argument is converted to a \kbd{long}, and is \kbd{0} by default''. So if the user-given argument reads \kbd{1 + 3} at this point, \kbd{4L} is sent to the function; and \kbd{0L} if the argument is omitted. The following special notations are available: \settabs\+\indent\indent&\kbd{Dxxx}\quad& optional \kbd{*GEN},&\cr \+&\kbd{DG}& optional \kbd{GEN}, & send \kbd{NULL} if argument omitted.\cr \+&\kbd{D\&}& optional \kbd{*GEN}, send \kbd{NULL} if argument omitted.\cr \+&&\quad The argument must be prefixed by \kbd{\&}.\cr \+&\kbd{DI}, \kbd{DE}& optional closure, send \kbd{NULL} if argument omitted.\cr \+&\kbd{DP}& optional \kbd{long}, send \kbd{precdl} if argument omitted.\cr \+&\kbd{DV}& optional loop variable.\cr \+&\kbd{Dn}& optional variable number, $-1$ if 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 \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 attached 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 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} (or \kbd{gprc}), and that's it. You can now use the new function \var{gpname} under \kbd{gp}, and we would very much like to hear about it! \smallskip \misctitle{Example} A complete description could look like this: \bprog { install(bnfinit0, "GD0,L,DGp", ClassGroupInit, "libpari.so"); addhelp(ClassGroupInit, "ClassGroupInit(P,{flag=0},{data=[]}): compute the necessary data for ..."); } @eprog\noindent which means we have a function \kbd{ClassGroupInit} under \kbd{gp}, which calls the library function \kbd{bnfinit0} . The function has one mandatory argument, and possibly two more (two \kbd{'D'} in the code), plus the current real precision. More precisely, the first argument is a \kbd{GEN}, the second one is converted to a \kbd{long} using \kbd{itos} (\kbd{0} is passed if it is omitted), and the third one is also a \kbd{GEN}, but we pass \kbd{NULL} if no argument was supplied by the user. This matches the C prototype (from \kbd{paridecl.h}): % \bprog GEN bnfinit0(GEN P, long flag, GEN data, long prec) @eprog\noindent This function is in fact coded in \kbd{basemath/buch2.c}, and is in this case completely identical to the GP function \kbd{bnfinit} but \kbd{gp} does not need to know about this, only that it can be found somewhere in the shared library \kbd{libpari.so}. \misctitle{Important note} You see in this example that it is the function's responsibility to correctly interpret its operands: \kbd{data = NULL} is interpreted \emph{by the function} as an empty vector. Note that since \kbd{NULL} is never a valid \kbd{GEN} pointer, this trick always enables you to distinguish between a default value and actual input: the user could explicitly supply an empty vector! \subsec{Library interface for \kbd{install}} There is a corresponding library interface for this \kbd{install} functionality, letting you expand the GP parser/evaluator available in the library with new functions from your C source code. Functions such as \tet{gp_read_str} may then evaluate a GP expression sequence involving calls to these new function! \fun{entree *}{install}{void *f, const char *gpname, const char *code} \noindent where \kbd{f} is the (address of the) function (cast to \kbd{void*}), \kbd{gpname} is the name by which you want to access your function from within your GP expressions, and \kbd{code} is as above. \subsec{Integration by patching \kbd{gp}} If \tet{install} is not available, and installing Linux or a BSD operating system is not an option (why?), you have to hardcode your function in the \kbd{gp} binary. Here is what needs to be done: \item Fetch the complete sources of the PARI distribution. \item Drop the function source code module in an appropriate directory (a priori \kbd{src/modules}), and declare all public functions in \kbd{src/headers/paridecl.h}. \item Choose a help section and add a file \kbd{src/functions/\var{section}/\var{gpname}} containing the following, keeping the notation above: \bprog Function: @com\var{gpname} Section: @com\var{section} C-Name: @com\var{libname} Prototype: @com\var{code} Help: @com\var{some help text} @eprog\noindent (If the help text does not fit on a single line, continuation lines must start by a whitespace character.) Two GP2C-related fields (\kbd{Description} and \kbd{Wrapper}) are also available to improve the code GP2C generates when compiling scripts involving your function. See the GP2C documentation for details. \item Launch \kbd{Configure}, which should pick up your C files and build an appropriate \kbd{Makefile}. At this point you can recompile \kbd{gp}, which will first rebuild the functions database. \misctitle{Example} We reuse the \kbd{ClassGroupInit} / \kbd{bnfinit0} from the preceding section. Since the C source code is already part of PARI, we only need to add a file \kbd{functions/number\_fields/ClassGroupInit} \noindent containing the following: \bprog Function: ClassGroupInit Section: number_fields C-Name: bnfinit0 Prototype: GD0,L,DGp Help: ClassGroupInit(P,{flag=0},{tech=[]}): this routine does @com\dots @eprog\noindent and recompile \kbd{gp}. \section{Globals related to PARI configuration} \subsec{PARI version numbers} \noindent \tet{paricfg_version_code} encodes in a single \kbd{long}, the Major and minor version numbers as well as the patchlevel. \fun{long}{PARI_VERSION}{long M, long m, long p} produces the version code attached to release $M.m.p$. Each code identifies a unique PARI release, and corresponds to the natural total order on the set of releases (bigger code number means more recent release). \noindent \tet{PARI_VERSION_SHIFT} is the number of bits used to store each of the integers $M$, $m$, $p$ in the version code. \noindent \tet{paricfg_vcsversion} is a version string related to the revision control system used to handle your sources, if any. For instance \kbd{git-}\emph{commit hash} if compiled from a git repository. The two character strings \tet{paricfg_version} and \tet{paricfg_buildinfo}, correspond to the first two lines printed by \kbd{gp} just before the Copyright message. The character string \tet{paricfg_compiledate} is the date of compilation which appears on the next line. The character string \tet{paricfg_mt_engine} is the name of the threading engine on the next line. In the string \kbd{paricfg\_buildinfo}, the substring \kbd{"\%s"} needs to be substituted by the output of the function \kbd{pari\_kernel\_version}. \fun{const char *}{pari_kernel_version}{void} \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}. \tet{paricfg_gphelp}: character string. The name of an external help command for \kbd{??} (such as the \kbd{gphelp} script) \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}$. \fun{long}{hammingl}{ulong x)} returns the Hamming weight of $x$, i.e.~the number of nonzero bits in its binary expansion. \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 nonnegative representative of $x + y$ modulo $m$. \fun{ulong}{Fl_neg}{ulong x, ulong m} returns the smallest nonnegative representative of $-x$ modulo $m$. \fun{ulong}{Fl_sub}{ulong x, ulong y, ulong m} returns the smallest nonnegative 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 nonnegative representative of $x y$ modulo $m$. \fun{ulong}{Fl_double}{ulong x, ulong m} returns $2x$ modulo $m$. \fun{ulong}{Fl_triple}{ulong x, ulong m} returns $3x$ modulo $m$. \fun{ulong}{Fl_halve}{ulong x, ulong m} returns $z$ such that $2\*z = x$ modulo $m$ assuming such $z$ exists. \fun{ulong}{Fl_sqr}{ulong x, ulong m} returns the smallest nonnegative representative of $x^2$ modulo $m$. \fun{ulong}{Fl_inv}{ulong x, ulong m} returns the smallest positive representative of $x^{-1}$ modulo $m$. If $x$ is not invertible mod~$m$, raise an exception. \fun{ulong}{Fl_invsafe}{ulong x, ulong m} returns the smallest positive representative of $x^{-1}$ modulo $m$. If $x$ is not invertible mod~$m$, return $0$ (which is ambiguous if $m=1$). \fun{ulong}{Fl_invgen}{ulong x, ulong m, ulong *pg} set \kbd{*pg} to $g = \gcd(x,m)$ and return $u$ in $(\Z/m\Z)^*$ such that $x u = g$ modulo $m$. We have $g = 1$ if and only if $x$ is invertible, and in this case $u$ is its inverse. \fun{ulong}{Fl_div}{ulong x, ulong y, ulong m} returns the smallest nonnegative 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 nonnegative representative of $x^n$ modulo $m$. \fun{GEN}{Fl_powers}{ulong x, long n, ulong p} returns $[\kbd{x}^0, \dots, \kbd{x}^\kbd{n}]$ modulo $m$, as a \typ{VECSMALL}. \fun{ulong}{Fl_sqrt}{ulong x, ulong p} returns the square root of \kbd{x} modulo \kbd{p} (smallest nonnegative representative). Assumes \kbd{p} to be prime, and \kbd{x} to be a square modulo \kbd{p}. \fun{ulong}{Fl_sqrtl}{ulong x, ulong l, ulong p} returns a $l$-the root of \kbd{x} modulo \kbd{p}. Assumes \kbd{p} to be prime and $p \equiv 1 \pmod{l}$, and \kbd{x} to be a $l$-th power modulo \kbd{p}. \fun{ulong}{Fl_sqrtn}{ulong a, ulong n, ulong p, ulong *zn} returns \kbd{ULONG\_MAX} if $a$ is not an $n$-th power residue mod $p$. Otherwise, returns an $n$-th root of $a$; if \kbd{zn} is not \kbd{NULL} set it to a primitive $m$-th root of 1, $m = \gcd(p-1,n)$ allowing to compute all $m$ solutions in $\F_p$ of the equation $x^n = a$. \fun{ulong}{Fl_log}{ulong a, ulong g, ulong ord, ulong p} Let $g$ such that $g^{ord} \equiv 1 \pmod{p}$. Return an integer $e$ such that $a^e \equiv g \pmod{p}$. If $e$ does not exist, the result is undefined. \fun{ulong}{Fl_order}{ulong a, ulong o, ulong p} returns the order of the \kbd{Fp} \kbd{a}. It is assumed that \kbd{o} is a multiple of the order of \kbd{a}, $0$ being allowed (no nontrivial information). \fun{ulong}{random_Fl}{ulong p} returns a pseudo-random integer uniformly distributed in $0, 1, \dots p-1$. \fun{ulong}{nonsquare_Fl}{ulong p} return a quadratic nonresidue modulo $p$, assuming $p$ is an odd prime. If $p$ is $3$ mod $4$, return $p-1$, else return the smallest (prime) nonresidue. \fun{ulong}{pgener_Fl}{ulong p} returns the smallest \idx{primitive root} modulo \kbd{p}, assuming \kbd{p} is prime. \fun{ulong}{pgener_Zl}{ulong p} returns the smallest primitive root modulo $p^k$, $k > 1$, assuming $p$ is an odd prime. \fun{ulong}{pgener_Fl_local}{ulong p, GEN L}, see \kbd{gener\_Fp\_local}, \kbd{L} is an \kbd{Flv}. \fun{ulong}{factorial_Fl}{long n, ulong p} return $n!$ mod $p$. \subsec{Modular kernel with ``precomputed inverse''} This is based on an algorithm by T. Grandlund and N. M\"{o}ller in ``Improved division by invariant integers'' \url{https://gmplib.org/~tege/division-paper.pdf}. In the following, we set $B=\B$. \fun{ulong}{get_Fl_red}{ulong p} returns a pseudoinverse \var{pi} for $p$. Namely an integer $0 < \var{pi} < B$ such that, given $0 \leq x < B^2$ (by two long words), we can compute the Euclidean quotient and remainder of $x$ modulo $p$ by performing $2$ multiplications and some additions. Precisely, once we set $q = 2^k p$ for the unique $k$ such that $B/2 \leq q < B$, the pseudoinverse \var{pi} is equal to the Euclidean quotient of $B^2 - qB + B-1$ by $q$. In particular $(\var{pi} + B) / B^2$ is very close to $1/q$. Note that this algorithm is generally less efficient than ordinary quotient and remainders (\kbd{divll} or even \kbd{/} and \kbd{\%}) when $0\leq x < B$ and $p \leq B^{1/2}$ are small. High level functions below allow setting $\var{pi} = 0$ to cater for this possibility and avoid calling \kbd{get\_Fl\_red} for arguments where the standard algorithm is preferable. \fun{ulong}{divll_pre}{ulong x, ulong p, ulong pi} as divll, where \var{pi} is the pseudoinverse of $p$. \fun{ulong}{remll_pre}{ulong u1, ulong u0, ulong p, ulong pi} returns the Euclidean remainder of $u_1\*2^B+u_0$ modulo $p$, assuming \var{pi} is the pseudoinverse of $p$. This function is faster if $u_1 < p$. \fun{ulong}{remlll_pre}{ulong u2, ulong u1, ulong u0, ulong p, ulong pi} returns the Euclidean remainder of $u_2\*2^{2\*B}+u_1\*2^{B}+u_0$ modulo $p$, assuming \var{pi} is the pseudoinverse of $p$. \fun{ulong}{Fl_sqr_pre}{ulong x, ulong p, ulong pi} returns $x^2$ modulo $p$, assuming \var{pi} is the pseudoinverse of $p$. \fun{ulong}{Fl_mul_pre}{ulong x, ulong y, ulong p, ulong pi} returns $x\*y$ modulo $p$, assuming \var{pi} is the pseudoinverse of $p$. \fun{ulong}{Fl_addmul_pre}{ulong a, ulong b, ulong c, ulong p, ulong pi} returns $a+b\*c$ modulo $p$, assuming \var{pi} is the pseudoinverse of $p$. \fun{ulong}{Fl_addmulmul_pre}{ulong a,ulong b, ulong c,ulong d, ulong p, ulong pi} returns $a\*b+c\*d$ modulo $p$, assuming \var{pi} is the pseudoinverse of $p$. \fun{ulong}{Fl_powu_pre}{ulong x, ulong n, ulong p, ulong pi} returns $x^n$ modulo $p$, assuming \var{pi} is the pseudoinverse of $p$, or $0$ in which case we either use ordinary divisions if $p < B^{1/2}$ is small and call \kbd{get\_Fl\_red} ourselves otherwise. \fun{GEN}{Fl_powers_pre}{ulong x, long n, ulong p, ulong pi} returns the vector (\typ{VECSMALL}) $(x^0, \dots, x^n)$, assuming \var{pi} is the pseudoinverse of $p$, or $0$ in which case we either use ordinary divisions if $p < B^{1/2}$ is small and call \kbd{get\_Fl\_red} ourselves otherwise. \fun{ulong}{Fl_log_pre}{ulong a, ulong g, ulong ord, ulong p, ulong pi} as \kbd{Fl\_log}, assuming \var{pi} is the pseudoinverse of $p$, or $0$ in which case we either use ordinary divisions if $p < B^{1/2}$ is small and call \kbd{get\_Fl\_red} ourselves otherwise. \fun{ulong}{Fl_sqrt_pre}{ulong x, ulong p, ulong pi} returns a square root of $x$ modulo $p$, see \kbd{Fl\_sqrt}. We assume \var{pi} is the pseudoinverse of $p$, or $0$ in which case we either use ordinary divisions if $p < B^{1/2}$ is small and call \kbd{get\_Fl\_red} ourselves otherwise. \fun{ulong}{Fl_sqrtl_pre}{ulong x, ulong l, ulong p, ulong pi} returns a $l$-the root of \kbd{x} modulo \kbd{p}, assuming $p$ prime, $p \equiv 1 \pmod{l}$, and \kbd{x} to be a $l$-th power modulo \kbd{p}. We assume \var{pi} is the pseudoinverse of $p$, or $0$ in which case we either use ordinary divisions if $p < B^{1/2}$ is small and call \kbd{get\_Fl\_red} ourselves otherwise. \fun{ulong}{Fl_sqrtn_pre}{ulong x, ulong n, ulong p, ulong pi, ulong *zn} See \kbd{Fl\_sqrtn}, assuming \var{pi} is the pseudoinverse of $p$, or $0$ in which case we either use ordinary divisions if $p < B^{1/2}$ is small and call \kbd{get\_Fl\_red} ourselves otherwise. \fun{ulong}{Fl_2gener_pre}{ulong p, ulong pi} return a generator of the $2$-Sylow subgroup of $\F_p^*$, to be used in \kbd{Fl\_sqrt\_pre\_i}. We assume \var{pi} is the pseudoinverse of $p$, or $0$ in which case we either use ordinary divisions if $p < B^{1/2}$ is small and call \kbd{get\_Fl\_red} ourselves otherwise. \fun{ulong}{Fl_2gener_pre_i}{ulong ns, ulong p, ulong pi} as \kbd{Fl\_2gener\_pre} where \kbd{ns} is a non-square modulo $p$. \fun{ulong}{Fl_sqrt_pre_i}{ulong x, ulong s2, ulong p, ulong pi} as \kbd{Fl\_sqrt\_pre} where \kbd{s2} is the element returned by \kbd{Fl\_2gener\_pre}. We assume \var{pi} is the pseudoinverse of $p$, or $0$ in which case we either use ordinary divisions if $p < B^{1/2}$ is small and call \kbd{get\_Fl\_red} ourselves otherwise. \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_1_bit}{long bitprec} create a \typ{REAL} equal to $1$ to \kbd{bitprec} bits 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 \kbd{real\_0\_bit(-prec)}. \fun{GEN}{int2n}{long n} creates a \typ{INT} equal to \kbd{1< 2$. \fun{void}{affii}{GEN x, GEN z} assigns the \typ{INT} \kbd{x} into the \typ{INT}~\kbd{z}. \fun{void}{affir}{GEN x, GEN z} assigns the \typ{INT} \kbd{x} into the \typ{REAL}~\kbd{z}. Assumes that $\kbd{lg(z)} > 2$. \fun{void}{affiz}{GEN x, GEN z} assigns \typ{INT}~\kbd{x} into \typ{INT} or \typ{REAL}~\kbd{z}. Assumes that $\kbd{lg(z)} > 2$. \fun{void}{affsi}{long s, GEN z} assigns the \kbd{long}~\kbd{s} into the \typ{INT}~\kbd{z}. Assumes that $\kbd{lg(z)} > 2$. \fun{void}{affsr}{long s, GEN z} assigns the \kbd{long}~\kbd{s} into the \typ{REAL}~\kbd{z}. Assumes that $\kbd{lg(z)} > 2$. \fun{void}{affsz}{long s, GEN z} assigns the \kbd{long}~\kbd{s} into the \typ{INT} or \typ{REAL}~\kbd{z}. Assumes that $\kbd{lg(z)} > 2$. \fun{void}{affui}{ulong u, GEN z} assigns the \kbd{ulong}~\kbd{u} into the \typ{INT}~\kbd{z}. Assumes that $\kbd{lg(z)} > 2$. \fun{void}{affur}{ulong u, GEN z} assigns the \kbd{ulong}~\kbd{u} into the \typ{REAL}~\kbd{z}. Assumes that $\kbd{lg(z)} > 2$. \fun{void}{affrr}{GEN x, GEN z} assigns the \typ{REAL}~\kbd{x} into the \typ{REAL}~\kbd{z}. \fun{void}{affgr}{GEN x, GEN z} assigns the scalar \kbd{x} into the \typ{REAL}~\kbd{z}, if possible. \noindent The function \kbd{affrs} and \kbd{affri} do not exist. So don't use them. \fun{void}{affrr_fixlg}{GEN y, GEN z} a variant of \kbd{affrr}. First shorten $z$ so that it is no longer than $y$, then assigns $y$ to $z$. This is used in the following scenario: room is reserved for the result but, due to cancellation, fewer words of accuracy are available than had been anticipated; instead of appending meaningless $0$s to the mantissa, we store what was actually computed. Note that shortening $z$ is not quite straightforward, since \kbd{setlg(z, ly)} would leave garbage on the stack, which \kbd{gerepile} might later inspect. It is done using \fun{void}{fixlg}{GEN z, long ly} see \tet{stackdummy} and the examples that follow. \subsec{Copy} \fun{GEN}{icopy}{GEN x} copy relevant words of the \typ{INT}~\kbd{x} on the stack: the length and effective length of the copy are equal. \fun{GEN}{rcopy}{GEN x} copy the \typ{REAL}~\kbd{x} on the stack. \fun{GEN}{leafcopy}{GEN x} copy the leaf~\kbd{x} on the stack (works in particular for \typ{INT}s and \typ{REAL}s). Contrary to \kbd{icopy}, \kbd{leafcopy} preserves the original length of a \typ{INT}. The obsolete form \fun{GEN}{mpcopy}{GEN x} is still provided for backward compatibility. This function also works on recursive types, copying them as if they were leaves, i.e.~making a shallow copy in that case: the components of the copy point to the same data as the component of the source; see also \kbd{shallowcopy}. \fun{GEN}{leafcopy_avma}{GEN x, pari_sp av} analogous to \kbd{gcopy\_avma} but simpler: assume $x$ is a leaf and return a copy allocated as if initially we had \kbd{avma} equal to \kbd{av}. There is no need to pass a pointer and update the value of the second argument: the new (fictitious) \kbd{avma} is just the return value (typecast to \kbd{pari\_sp}). \fun{GEN}{icopyspec}{GEN x, long nx} copy the \kbd{nx} words \kbd{x[2]}, \dots, \kbd{x[nx+1]} to make up a new \typ{INT}. Set the sign to $1$. \subsec{Conversions} \fun{GEN}{itor}{GEN x, long prec} converts the \typ{INT}~\kbd{x} to a \typ{REAL} of length \kbd{prec} and return the latter. Assumes that $\kbd{prec} > 2$. \fun{long}{itos}{GEN x} converts the \typ{INT}~\kbd{x} to a \kbd{long} if possible, otherwise raise an exception. We consider the conversion to be possible if and only if $|x| \leq \kbd{LONG\_MAX}$, i.e. $|x| < 2^{63}$ on a 64-bit architecture. Since the range is symmetric, the output of \kbd{itos} can safely be negated. \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 give an error. \fun{ulong}{itou}{GEN x} converts the \typ{INT}~\kbd{|x|} to an \kbd{ulong} if possible, otherwise raise an exception. The conversion is possible if and only if $\kbd{lgefint}(x) \leq 3$. \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{nonzero} \kbd{ulong}~\kbd{s} into a \typ{INT} and return the latter. \fun{GEN}{utoineg}{ulong s} converts the \emph{nonzero} \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}{uu32toineg}{ulong a, ulong b} returns the \kbd{GEN} equal to $- (2^{32} a + b)$, \emph{assuming} that $a,b < 2^{32}$ and that one of $a$ or $b$ is positive. This does not depend on \kbd{sizeof(long)}: the behavior is as above on both $32$ and $64$-bit machines. \fun{GEN}{uutoi}{ulong a, ulong b} returns the \kbd{GEN} equal to $2^{\B} a + b$. \fun{GEN}{uutoineg}{ulong a, ulong b} returns the \kbd{GEN} equal to $-(2^{\B} a + b)$. \subsec{Integer parts} The following four functions implement the conversion from \typ{REAL} to \typ{INT} using standard rounding modes. Contrary to usual semantics (complement the mantissa with an infinite number of 0), they will raise an error \emph{precision loss in truncation} if the \typ{REAL} represents a range containing more than one integer. \fun{GEN}{ceilr}{GEN x} smallest integer larger or equal to the \typ{REAL}~\kbd{x} (i.e.~the \kbd{ceil} function). \fun{GEN}{floorr}{GEN x} largest integer smaller or equal to the \typ{REAL}~\kbd{x} (i.e.~the \kbd{floor} function). \fun{GEN}{roundr}{GEN x} rounds the \typ{REAL} \kbd{x} to the nearest integer (towards~$+\infty$ in case of tie). \fun{GEN}{truncr}{GEN x} truncates the \typ{REAL}~\kbd{x} (not the same as \kbd{floorr} if \kbd{x} is negative). The following four function are analogous, but can also treat the trivial case when the argument is a \typ{INT}: \fun{GEN}{mpceil}{GEN x} as \kbd{ceilr} except that \kbd{x} may be a \typ{INT}. \fun{GEN}{mpfloor}{GEN x} as \kbd{floorr} except that \kbd{x} may be a \typ{INT}. \fun{GEN}{mpround}{GEN x} as \kbd{roundr} except that \kbd{x} may be a \typ{INT}. \fun{GEN}{mptrunc}{GEN x} as \kbd{truncr} except that \kbd{x} may be a \typ{INT}. \fun{GEN}{diviiround}{GEN x, GEN y} if \kbd{x} and \kbd{y} are \typ{INT}s, returns the quotient $\kbd{x}/\kbd{y}$ of \kbd{x} and~\kbd{y}, rounded to the nearest integer. If $\kbd{x}/\kbd{y}$ falls exactly halfway between two consecutive integers, then it is rounded towards~$+\infty$ (as for \tet{roundr}). \fun{GEN}{ceil_safe}{GEN x}, \kbd{x} being a real number (not necessarily a \typ{REAL}) returns the smallest integer which is larger than any possible incarnation of \kbd{x}. (Recall that a \typ{REAL} represents an interval of possible values.) Note that \kbd{gceil} raises an exception if the input accuracy is too low compared to its magnitude. \fun{GEN}{floor_safe}{GEN x}, \kbd{x} being a real number (not necessarily a \typ{REAL}) returns the largest integer which is smaller than any possible incarnation of \kbd{x}. (Recall that a \typ{REAL} represents an interval of possible values.) Note that \kbd{gfloor} raises an exception if the input accuracy is too low compared to its magnitude. \fun{GEN}{trunc_safe}{GEN x}, \kbd{x} being a real number (not necessarily a \typ{REAL}) returns the integer with the largest absolute value, which is closer to $0$ than any possible incarnation of \kbd{x}. (Recall that a \typ{REAL} represents an interval of possible values.) \fun{GEN}{roundr_safe}{GEN x} rounds the \typ{REAL} \kbd{x} to the nearest integer (towards~$+\infty$). Complement the mantissa with an infinite number of $0$ before rounding, hence never raise an exception. \subsec{$2$-adic valuations and shifts} \fun{long}{vals}{long s} 2-adic valuation of the \kbd{long}~\kbd{s}. Returns $-1$ if \kbd{s} is equal to 0. \fun{long}{vali}{GEN x} 2-adic valuation of the \typ{INT}~\kbd{x}. Returns $-1$ if \kbd{x} is equal to 0. \fun{GEN}{mpshift}{GEN x, long n} shifts the~\typ{INT} or \typ{REAL} \kbd{x} by~\kbd{n}. If \kbd{n} is positive, this is a left shift, i.e.~multiplication by $2^{\kbd{n}}$. If \kbd{n} is negative, it is a right shift by~$-\kbd{n}$, which amounts to the truncation of the quotient of \kbd{x} by~$2^{-\kbd{n}}$. \fun{GEN}{shifti}{GEN x, long n} shifts the \typ{INT}~$x$ by~$n$. \fun{GEN}{shiftr}{GEN x, long n} shifts the \typ{REAL}~$x$ by~$n$. \fun{void}{shiftr_inplace}{GEN x, long n} shifts the \typ{REAL}~$x$ by~$n$, in place. \fun{GEN}{trunc2nr}{GEN x, long n} given a \typ{REAL} $x$, returns \kbd{truncr(shiftr(x,n))}, but faster, without leaving garbage on the stack and never raising a \emph{precision loss in truncation} error. Called by \tet{gtrunc2n}. \fun{GEN}{mantissa2nr}{GEN x, long n} given a \typ{REAL} $x$, returns the mantissa of $x 2^n$ (disregards the exponent of $x$). Equivalent to \bprog trunc2nr(x, n-expo(x)+bit_prec(x)-1) @eprog \fun{GEN}{mantissa_real}{GEN z, long *e} returns the mantissa $m$ of $z$, and sets \kbd{*e} to the exponent $\kbd{bit\_accuracy(lg(z))}-1-\kbd{expo}(z)$, so that $z = m / 2^e$. \misctitle{Low-level} In the following two functions, $s$(ource) and $t$(arget) need not be valid \kbd{GEN}s (in practice, they usually point to some part of a \typ{REAL} mantissa): they are considered as arrays of words representing some mantissa, and we shift globally $s$ by $n > 0$ bits, storing the result in $t$. We assume that $m\leq M$ and only access $s[m], s[m+1],\ldots s[M]$ (read) and likewise for $t$ (write); we may have $s = t$ but more general overlaps are not allowed. The word $f$ is concatenated to $s$ to supply extra bits. \fun{void}{shift_left}{GEN t, GEN s, long m, long M, ulong f, ulong n} shifts the mantissa $$s[m], s[m+1],\ldots s[M], f$$ left by $n$ bits. \fun{void}{shift_right}{GEN t, GEN s, long m, long M, ulong f, ulong n} shifts the mantissa $$f, s[m], s[m+1],\ldots s[M]$$ right by $n$ bits. \subsec{From \typ{INT} to bits or digits in base $2^k$ and back} \fun{GEN}{binary_zv}{GEN x} given a \typ{INT} $x$, return a \typ{VECSMALL} of bits, from most significant to least significant. \fun{GEN}{binary_2k}{GEN x, long k} given a \typ{INT} $x$, and $k > 0$, return a \typ{VEC} of digits of $x$ in base $2^k$, as \typ{INT}s, from most significant to least significant. \fun{GEN}{binary_2k_nv}{GEN x, long k} given a \typ{INT} $x$, and $0 < k < \tet{BITS_IN_LONG}$, return a \typ{VECSMALL} of digits of $x$ in base $2^k$, as \kbd{ulong}s, from most significant to least significant. \fun{GEN}{bits_to_int}{GEN x, long l} given a vector $x$ of $l$ bits (as a \typ{VECSMALL} or even a pointer to a part of a larger vector, so not a proper \kbd{GEN}), return the integer $\sum_{i = 1}^l x[i] 2^{l-i}$, as a \typ{INT}. \fun{ulong}{bits_to_u}{GEN v, long l} same as \tet{bits_to_int}, where $l < \tet{BITS_IN_LONG}$, so we can return an \kbd{ulong}. \fun{GEN}{fromdigitsu}{GEN x, GEN B} given a \typ{VECSMALL} $x$ of length $l$ and a \typ{INT} $B$, return the integer $\sum_{i = 1}^l x[i] B^{i-1}$, as a \typ{INT}, where the \kbd{x[i]} are seen as unsigned integers. \fun{GEN}{fromdigits_2k}{GEN x, long k} converse of \tet{binary_2k}; given a \typ{VEC} $x$ of length $l$ and a positive \kbd{long} $k$, where each $x[i]$ is a \typ{INT} with $0\leq x[i] < 2^k$, return the integer $\sum_{i = 1}^l x[i] 2^{k(l-i)}$, as a \typ{INT}. \fun{GEN}{nv_fromdigits_2k}{GEN x, long k} as \tet{fromdigits_2k}, but with $x$ being a \typ{VECSMALL} and each $x[i]$ being a \kbd{ulong} with $0\leq x[i] < 2^{\min\{k,\tet{BITS_IN_LONG}\}}$. Here $k$ may be any positive \kbd{long}, and the $x[i]$ are regarded as $k$-bit integers by truncating or extending with zeroes. \subsec{Integer valuation} For integers $x$ and $p$, such that $x\neq 0$ and $|p| > 1$, we define $v_p(x)$ to be the largest integer exponent $e$ such that $p^e$ divides $x$. If $p$ is prime, this is the ordinary valuation of $x$ at $p$. \fun{long}{Z_pvalrem}{GEN x, GEN p, GEN *r} applied to \typ{INT}s $\kbd{x}\neq 0$ and~\kbd{p}, $|\kbd{p}| > 1$, returns $e := v_p(x)$ The quotient $\kbd{x}/\kbd{p}^e$ is returned in~\kbd{*r}. If $|\kbd{p}|$ is a prime, \kbd{*r} is the prime-to-\kbd{p} part of~\kbd{x}. \fun{long}{Z_pval}{GEN x, GEN p} as \kbd{Z\_pvalrem} but only returns $v_p(x)$. \fun{long}{Z_lvalrem}{GEN x, ulong p, GEN *r} as \kbd{Z\_pvalrem}, except that \kbd{p} is an \kbd{ulong} ($\kbd{p} > 1$). \fun{long}{Z_lvalrem_stop}{GEN *x, ulong p, int *stop} assume $x > 0$; returns $e := v_p(x)$ and replaces $x$ by $x / p^e$. Set \kbd{stop} to $1$ if the new value of $x$ is $ < p^2$ (and $0$ otherwise). To be used when trial dividing $x$ by successive primes: the \kbd{stop} condition is cheaply tested while testing whether $p$ divides $x$ (is the quotient less than $p$?), and allows to decide that $n$ is prime if no prime $< p$ divides $n$. Not memory-clean. \fun{long}{Z_lval}{GEN x, ulong p} as \kbd{Z\_pval}, except that \kbd{p} is an \kbd{ulong} ($\kbd{p} > 1$). \fun{long}{u_lvalrem}{ulong x, ulong p, ulong *r} as \kbd{Z\_pvalrem}, except the inputs/outputs are now \kbd{ulong}s. \fun{long}{u_lvalrem_stop}{ulong *n, ulong p, int *stop} as \kbd{Z\_pvalrem\_stop}. \fun{long}{u_pvalrem}{ulong x, GEN p, ulong *r} as \kbd{Z\_pvalrem}, except \kbd{x} and \kbd{r} are now \kbd{ulong}s. \fun{long}{u_lval}{ulong x, ulong p} as \kbd{Z\_pval}, except the inputs are now \kbd{ulong}s. \fun{long}{u_pval}{ulong x, GEN p} as \kbd{Z\_pval}, except \kbd{x} is now an \kbd{ulong}. \fun{long}{z_lval}{long x, ulong p} as \kbd{u\_lval}, for signed \kbd{x}. \fun{long}{z_lvalrem}{long x, ulong p} as \kbd{u\_lvalrem}, for signed \kbd{x}. \fun{long}{z_pval}{long x, GEN p} as \kbd{Z\_pval}, except \kbd{x} is now a \kbd{long}. \fun{long}{z_pvalrem}{long x, GEN p} as \kbd{Z\_pvalrem}, except \kbd{x} is now a \kbd{long}. \fun{long}{factorial_lval}{ulong n, ulong p} returns $v_p(n!)$, assuming $p$ is prime. The following convenience functions generalize \kbd{Z\_pval} and its variants to ``containers'' (\kbd{ZV} and \kbd{ZX}): \fun{long}{ZV_pvalrem}{GEN x, GEN p, GEN *r} $x$ being a \kbd{ZV} (a vector of \typ{INT}s), return the min $v$ of the valuations of its components and set \kbd{*r} to $x/p^v$. Infinite loop if $x$ is the zero vector. This function is not stack clean. \fun{long}{ZV_pval}{GEN x, GEN p} as \kbd{ZV\_pvalrem} but only returns the ``valuation''. \fun{int}{ZV_Z_dvd}{GEN x, GEN p} returns $1$ if $p$ divides all components of $x$ and $0$ otherwise. Faster than testing \kbd{ZV\_pval(x,p) >= 1}. \fun{long}{ZV_lvalrem}{GEN x, ulong p, GEN *px} as \kbd{ZV\_pvalrem}, except that \kbd{p} is an \kbd{ulong} ($\kbd{p} > 1$). This function is not stack-clean. \fun{long}{ZV_lval}{GEN x, ulong p} as \kbd{ZV\_pval}, except that \kbd{p} is an \kbd{ulong} ($\kbd{p} > 1$). \fun{long}{ZX_pvalrem}{GEN x, GEN p, GEN *r} as \kbd{ZV\_pvalrem}, for a \kbd{ZX} $x$ (a \typ{POL} with \typ{INT} coefficients). This function is not stack-clean. \fun{long}{ZX_pval}{GEN x, GEN p} as \kbd{ZV\_pval} for a \kbd{ZX} $x$. \fun{long}{ZX_lvalrem}{GEN x, ulong p, GEN *px} as \kbd{ZV\_lvalrem}, a \kbd{ZX} $x$. This function is not stack-clean. \fun{long}{ZXX_pvalrem}{GEN x, GEN p, GEN *r} as \kbd{ZX\_pvalrem}, for a \kbd{ZXX} $x$ (a \typ{POL} with \kbd{ZX} coefficients). This function is not stack-clean. \fun{long}{ZXV_pvalrem}{GEN x, GEN p, GEN *r} as \kbd{ZV\_pvalrem}, for a \kbd{ZXV} $x$ (a \typ{VEC} with \kbd{ZX} coefficients). This function is not stack-clean. \fun{long}{ZX_lval}{GEN x, ulong p} as \kbd{ZX\_pval}, except that \kbd{p} is an \kbd{ulong} ($\kbd{p} > 1$). \subsec{Generic unary operators} Let ``\op'' be a unary operation among \item \key{neg}: negation ($-x$). \item \key{abs}: absolute value ($|x|$). \item \key{sqr}: square ($x^2$). \noindent The names and prototypes of the low-level functions corresponding to \op\ are as follows. The result is of the same type as~\kbd{x}. \funno{GEN}{\op i}{GEN x} creates the result of \op\ applied to the \typ{INT}~\kbd{x}. \funno{GEN}{\op r}{GEN x} creates the result of \op\ applied to the \typ{REAL}~\kbd{x}. \funno{GEN}{mp\op}{GEN x} creates the result of \op\ applied to the \typ{INT} or \typ{REAL}~\kbd{x}. \noindent Complete list of available functions: \fun{GEN}{absi}{GEN x}, \fun{GEN}{absr}{GEN x}, \fun{GEN}{mpabs}{GEN x} \fun{GEN}{negi}{GEN x}, \fun{GEN}{negr}{GEN x}, \fun{GEN}{mpneg}{GEN x} \fun{GEN}{sqri}{GEN x}, \fun{GEN}{sqrr}{GEN x}, \fun{GEN}{mpsqr}{GEN x} \fun{GEN}{absi_shallow}{GEN x} $x$ being a \typ{INT}, returns a shallow copy of $|x|$, in particular returns $x$ itself when $x \geq 0$, and \kbd{negi($x$)} otherwise. \fun{GEN}{mpabs_shallow}{GEN x} $x$ being a \typ{INT} or a \typ{REAL}, returns a shallow copy of $|x|$, in particular returns $x$ itself when $x \geq 0$, and \kbd{mpneg($x$)} otherwise. \noindent Some miscellaneous routines: \fun{GEN}{sqrs}{long x} returns $x^2$. \fun{GEN}{sqru}{ulong x} returns $x^2$. \subsec{Comparison operators} \fun{int}{cmpss}{long s, long t} compares the \kbd{long}~\kbd{s} to the \typ{long}~\kbd{t}. \fun{int}{cmpuu}{ulong u, ulong v} compares the \kbd{ulong}~\kbd{u} to the \typ{ulong}~\kbd{v}. \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}{cmpiu}{GEN x, ulong s} compares the \typ{INT}~\kbd{x} to the \kbd{ulong}~\kbd{s}. \fun{int}{cmpsi}{long s, GEN x} compares the \kbd{long}~\kbd{s} to the \typ{INT}~\kbd{x}. \fun{int}{cmpui}{ulong s, GEN x} compares the \kbd{ulong}~\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 nonzero real; two nonzero 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}{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. \fun{int}{equalsi}{long s, GEN x} \fun{int}{equaliu}{GEN x, ulong s} compare the \typ{INT} \kbd{x} and the \kbd{ulong}~\kbd{s}. The result is $1$ if $\kbd{x} = \kbd{y}$, $0$ otherwise. \fun{int}{equalui}{ulong s, GEN x} The remaining comparison operators disregard the sign of their operands \fun{int}{absequaliu}{GEN x, ulong u} 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. This is marginally more efficient than \kbd{equalis} even when \kbd{x} is known to be nonnegative. \fun{int}{absequalui}{ulong u, GEN x} \fun{int}{abscmpiu}{GEN x, ulong u} compare the absolute value of the \typ{INT} \kbd{x} and the \kbd{ulong}~\kbd{u}. \fun{int}{abscmpui}{ulong u, GEN x} \fun{int}{abscmpii}{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}{absequalii}{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}{abscmprr}{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 nonzero \typ{REAL} \kbd{x} is equal to $\pm 2^e$ for some integer $e$. \fun{int}{absrnz_equal1}{GEN x} tests whether a nonzero \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.~nonnegative 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 nonzero). \smallskip The names and prototypes of the low-level functions corresponding to \op\ are as follows. In this section, the \kbd{z} argument in the \kbd{z}-functions must be of type \typ{INT} when no \kbd{r} or \kbd{mp} appears in the argument code (no \typ{REAL} operand is involved, only integer types), and of type \typ{REAL} otherwise. \funno{GEN}{mp\op[z]}{GEN x, GEN y[, GEN z]} applies \op\ to the \typ{INT} or \typ{REAL} \kbd{x} and~\kbd{y}. The function \kbd{mpdivz} does not exist (its semantic would change drastically depending on the type of the \kbd{z} argument), and neither do \kbd{mprem[z]} nor \kbd{mpmod[z]} (specific to integers). \funno{GEN}{\op si[z]}{long s, GEN x[, GEN z]} applies \op\ to the \kbd{long}~\kbd{s} and the \typ{INT}~\kbd{x}. These functions always return the global constant \kbd{gen\_0} (not a copy) when the sign of the result is $0$. \funno{GEN}{\op sr[z]}{long s, GEN x[, GEN z]} applies \op\ to the \kbd{long}~\kbd{s} and the \typ{REAL}~\kbd{x}. \funno{GEN}{\op ss[z]}{long s, long t[, GEN z]} applies \op\ to the longs \kbd{s} and~\kbd{t}. These functions always return the global constant \kbd{gen\_0} (not a copy) when the sign of the result is $0$. \funno{GEN}{\op ii[z]}{GEN x, GEN y[, GEN z]} applies \op\ to the \typ{INT}s \kbd{x} and~\kbd{y}. These functions always return the global constant \kbd{gen\_0} (not a copy) when the sign of the result is $0$. \funno{GEN}{\op ir[z]}{GEN x, GEN y[, GEN z]} applies \op\ to the \typ{INT} \kbd{x} and the \typ{REAL}~\kbd{y}. \funno{GEN}{\op is[z]}{GEN x, long s[, GEN z]} applies \op\ to the \typ{INT}~\kbd{x} and the \kbd{long}~\kbd{s}. These functions always return the global constant \kbd{gen\_0} (not a copy) when the sign of the result is $0$. \funno{GEN}{\op ri[z]}{GEN x, GEN y[, GEN z]} applies \op\ to the \typ{REAL}~\kbd{x} and the \typ{INT}~\kbd{y}. \funno{GEN}{\op rr[z]}{GEN x, GEN y[, GEN z]} applies \op\ to the \typ{REAL}s~\kbd{x} and~\kbd{y}. \funno{GEN}{\op rs[z]}{GEN x, long s[, GEN z]} applies \op\ to the \typ{REAL}~\kbd{x} and the \kbd{long}~\kbd{s}. \noindent Some miscellaneous routines: \fun{long}{expu}{ulong x} assuming $x > 0$, returns the binary exponent of the real number equal to $x$. This is a special case of \kbd{gexpo}. \fun{GEN}{adduu}{ulong x, ulong y} \fun{GEN}{addiu}{GEN x, ulong y} \fun{GEN}{addui}{ulong x, GEN y} adds \kbd{x} and \kbd{y}. \fun{GEN}{subuu}{ulong x, ulong y} \fun{GEN}{subiu}{GEN x, ulong y} \fun{GEN}{subui}{ulong x, GEN y} subtracts \kbd{x} by \kbd{y}. \fun{GEN}{muluu}{ulong x, ulong y} multiplies \kbd{x} by \kbd{y}. \fun{ulong}{umuluu_le}{ulong x, ulong y, ulong n} multiplies \kbd{x} by \kbd{y}. Return $xy$ if $xy \leq n$ and $0$ otherwise (in particular if $xy$ does not fit in an \kbd{ulong}). \fun{ulong}{umuluu_or_0}{ulong x, ulong y} multiplies \kbd{x} by \kbd{y}. Return $0$ if $xy$ does not fit in an \kbd{ulong}. \fun{GEN}{mului}{ulong x, GEN y} multiplies \kbd{x} by \kbd{y}. \fun{GEN}{muluui}{ulong x, ulong y, GEN z} return $xyz$. \fun{GEN}{muliu}{GEN x, ulong y} multiplies \kbd{x} by \kbd{y}. \fun{void}{addumului}{ulong a, ulong b, GEN x} return $a + b|X|$. \fun{GEN}{addmuliu}{GEN x, GEN y, ulong u} returns $x +yu$. \fun{GEN}{addmulii}{GEN x, GEN y, GEN z} returns $x + yz$. \fun{GEN}{addmulii_inplace}{GEN x, GEN y, GEN z} returns $x + yz$, but returns $x$ itself and not a copy if $yz = 0$. Not suitable for \tet{gerepile} or \tet{gerepileupto}. \fun{GEN}{addmuliu_inplace}{GEN x, GEN y, ulong u} returns $x +yu$, but returns $x$ itself and not a copy if $yu = 0$. Not suitable for \tet{gerepile} or \tet{gerepileupto}. \fun{GEN}{submuliu_inplace}{GEN x, GEN y, ulong u} returns $x- yu$, but returns $x$ itself and not a copy if $yu = 0$. Not suitable for \tet{gerepile} or \tet{gerepileupto}. \fun{GEN}{lincombii}{GEN u, GEN v, GEN x, GEN y} returns $ux + vy$. \fun{GEN}{mulsubii}{GEN y, GEN z, GEN x} returns $yz - x$. \fun{GEN}{submulii}{GEN x, GEN y, GEN z} returns $x - yz$. \fun{GEN}{submuliu}{GEN x, GEN y, ulong u} returns $x -yu$. \fun{GEN}{mulu_interval}{ulong a, ulong b} returns $a(a+1)\cdots b$, assuming that $a \leq b$. \fun{GEN}{mulu_interval_step}{ulong a, ulong b, ulong s} returns the product of all integers in $[a,b]$ congruent to $a$ modulo $s$. Assume $a\leq b$ and $s > 0$; \fun{GEN}{muls_interval}{long a, long b} returns $a(a+1)\cdots b$, assuming that $a \leq b$. \fun{GEN}{invr}{GEN x} returns the inverse of the nonzero \typ{REAL}~$x$. \fun{GEN}{truedivii}{GEN x, GEN y} returns the true Euclidean quotient (with nonnegative remainder less than $|y|$). \fun{GEN}{truedivis}{GEN x, long y} returns the true Euclidean quotient (with nonnegative remainder less than $|y|$). \fun{GEN}{truedivsi}{long x, GEN y} returns the true Euclidean quotient (with nonnegative remainder less than $|y|$). \fun{GEN}{centermodii}{GEN x, GEN y, GEN y2}, given \typ{INT}s \kbd{x}, \kbd{y}, returns $z$ congruent to \kbd{x} modulo \kbd{y}, such that $-\kbd{y}/2 \leq z < \kbd{y}/2$. The function requires an extra argument \kbd{y2}, such that \kbd{y2 = shifti(y, -1)}. (In most cases, \kbd{y} is constant for many reductions and \kbd{y2} need only be computed once.) \fun{GEN}{remi2n}{GEN x, long n} returns \kbd{x} mod $2^n$. \fun{GEN}{addii_sign}{GEN x, long sx, GEN y, long sy} add the \typ{INT}s $x$ and $y$ as if their signs were \kbd{sx} and \kbd{sy}. \fun{GEN}{addir_sign}{GEN x, long sx, GEN y, long sy} add the \typ{INT} $x$ and the \typ{REAL} $y$ as if their signs were \kbd{sx} and \kbd{sy}. \fun{GEN}{addrr_sign}{GEN x, long sx, GEN y, long sy} add the \typ{REAL}s $x$ and $y$ as if their signs were \kbd{sx} and \kbd{sy}. \fun{GEN}{addsi_sign}{long x, GEN y, long sy} add $x$ and the \typ{INT} $y$ as if its sign was \kbd{sy}. \fun{GEN}{addui_sign}{ulong x, GEN y, long sy} add $x$ and the \typ{INT} $y$ as if its sign was \kbd{sy}. \subsec{Exact division and divisibility} \fun{GEN}{diviiexact}{GEN x, GEN y} returns the Euclidean quotient $\kbd{x} / \kbd{y}$, assuming $\kbd{y}$ divides $\kbd{x}$. Uses Jebelean algorithm (Jebelean-Krandick bidirectional exact division is not implemented). \fun{GEN}{diviuexact}{GEN x, ulong y} returns the Euclidean quotient $\kbd{x} / \kbd{y}$, assuming $\kbd{y}$ divides $\kbd{x}$ and $\kbd{y}$ is nonzero. \fun{GEN}{diviuuexact}{GEN x, ulong y, ulong z} returns the Euclidean quotient $x/(yz)$, assuming $yz$ divides $x$ and $yz \neq 0$. The following routines return 1 (true) if \kbd{y} divides \kbd{x}, and 0 otherwise. 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 nonnegative 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}{absdiviu_rem}{GEN x, ulong s, ulong *r} computes the Euclidean quotient and remainder of \emph{absolute value} of the \typ{INT}~\kbd{x} by the \kbd{ulong}~\kbd{s}. As \kbd{sdivss\_rem} otherwise. \fun{ulong}{uabsdiviu_rem}{GEN n, ulong d, ulong *r} as \tet{absdiviu_rem}, assuming that $|n|/d$ fits into an \kbd{ulong}. \fun{ulong}{uabsdivui_rem}{ulong x, GEN y, ulong *rem} computes the Euclidean quotient and remainder of $x$ by $|y|$. As \kbd{sdivss\_rem} otherwise. \fun{ulong}{udivuu_rem}{ulong x, ulong y, ulong *rem} computes the Euclidean quotient and remainder of $x$ by $y$. As \kbd{sdivss\_rem} otherwise. \fun{ulong}{ceildivuu}{ulong x, ulong y} return the ceiling of $x / y$. \fun{GEN}{divsi_rem}{long s, GEN y, long *r} computes the Euclidean quotient and remainder of the \kbd{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 \kbd{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 nonnegative remainder. \fun{GEN}{truedvmdis}{GEN x, long y, GEN *z}, as \kbd{dvmdis} but with a nonnegative remainder. \fun{GEN}{truedvmdsi}{long x, GEN y, GEN *z}, as \kbd{dvmdsi} but with a nonnegative 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 nonnegative 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}{umodsu}{long x, ulong y} computes the true Euclidean remainder of the \kbd{long}~\kbd{x} by a \kbd{ulong}~\kbd{y}. \fun{ulong}{umodiu}{GEN x, ulong y} computes the true Euclidean remainder of the \typ{INT}~\kbd{x} by the \kbd{ulong}~\kbd{y}. \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}. These functions directly access the binary data and are thus much faster than the generic modulo functions: \fun{int}{mpodd}{GEN x} which is 1 if \kbd{x} is odd, and 0 otherwise. \fun{ulong}{Mod2}{GEN x} \fun{ulong}{Mod4}{GEN x} \fun{ulong}{Mod8}{GEN x} \fun{ulong}{Mod16}{GEN x} \fun{ulong}{Mod32}{GEN x} \fun{ulong}{Mod64}{GEN x} give the residue class of $x$ modulo the corresponding power of $2$. \fun{ulong}{umodi2n}{GEN x, long n} give the residue class of $x$ modulo $2^n$, $0 \leq n < BITS\_IN\_LONG$. The following functions assume that $x\neq 0$ and in fact disregard the sign of $x$. There are about $10\%$ faster than the safer variants above: \fun{long}{mod2}{GEN x} \fun{long}{mod4}{GEN x} \fun{long}{mod8}{GEN x} \fun{long}{mod16}{GEN x} \fun{long}{mod32}{GEN x} \fun{long}{mod64}{GEN x} give the residue class of $|x|$ modulo the corresponding power of 2, for \emph{nonzero}~\kbd{x}. As well, \fun{ulong}{mod2BIL}{GEN x} returns the least significant word of $|x|$, still assuming that $x\neq 0$. \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}{powersr}{GEN e, long n}. Given a \typ{REAL} $e$, return the vector $v$ of all $e^i$, $0 \leq i \leq n$, where $v[i] = e^{i-1}$. \fun{GEN}{powrshalf}{GEN x, long n}, assumes $x$ is a \typ{REAL} and returns $x^{n/2}$ (always a \typ{REAL}, even if $n = 0$). \fun{GEN}{powruhalf}{GEN x, ulong n}, assumes $x$ is a \typ{REAL} and returns $x^{n/2}$ (always a \typ{REAL}, even if $n = 0$). \fun{GEN}{powrfrac}{GEN x, long n, long d}, assumes $x$ is a \typ{REAL} and returns $x^{n/d}$ (always a \typ{REAL}, even if $n = 0$). \fun{GEN}{powIs}{long n} returns $I^n\in\{1,I,-1,-I\}$ (\typ{INT} for even $n$, \typ{COMPLEX} otherwise). \fun{ulong}{upowuu}{ulong x, ulong n}, returns $x^n$ when $< 2^\B$, and $0$ otherwise (overflow). \fun{ulong}{upowers}{ulong x, long n}, returns $[1,x,\ldots,x^n]$ as a \typ{VECSMALL}. Assume there is no overflow. \fun{GEN}{sqrtremi}{GEN N, GEN *r}, returns the integer square root $S$ of the nonnegative \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 nonnegative \typ{INT}~\kbd{N} (rounded towards 0). This is identical to \kbd{sqrtremi(N, NULL)}. \fun{long}{logintall}{GEN B, GEN y, GEN *ptq} returns the floor $e$ of $\log_y B$, where $B > 0$ and $y > 1$ are integers. If \kbd{ptq} is not \kbd{NULL}, set it to $y^e$. (Analogous to \kbd{logint0}, whithout sanity checks.) \fun{ulong}{ulogintall}{ulong B, ulong y, ulong *ptq} as \kbd{logintall} for \kbd{ulong} arguments. \fun{long}{logint}{GEN B, GEN y} returns the floor $e$ of $\log_y B$, where $B > 0$ and $y > 1$ are integers. \fun{ulong}{ulogint}{ulong B, ulong y} as \kbd{logint} for \kbd{ulong} arguments. \fun{GEN}{vecpowuu}{long N, ulong a} return the vector of $n^a$, $n = 1, \dots, N$. Not memory clean. \fun{GEN}{vecpowug}{long N, GEN a, long prec} return the vector of $n^a$, $n = 1, \dots, N$, where the powers are computed at precision \kbd{prec}. Not memory clean. \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{ulong}{ugcdiu}{GEN x, ulong y} returns the GCD of \kbd{x} and \kbd{y}. \fun{ulong}{ugcdui}{ulong x, GEN y} returns the GCD of \kbd{x} and \kbd{y}. \fun{GEN}{coprimes_zv}{ulong N} return a \typ{VECSMALL} $T$ with $N$ entries such that $T[i] = 1$ iff $(i,N) = 1$ and $0$ otherwise. \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{ulong}{ulcm}{ulong x, ulong y} returns the LCM of \kbd{x} and \kbd{y}, provided it fits into an \kbd{ulong}. Silently overflows otherwise. \fun{GEN}{gcdii}{GEN x, GEN y}, returns the GCD of the \typ{INT}s \kbd{x} and \kbd{y}. \fun{GEN}{lcmii}{GEN x, GEN y}, returns the LCM of the \typ{INT}s \kbd{x} and \kbd{y}. \fun{GEN}{bezout}{GEN a,GEN b, GEN *u,GEN *v}, returns the GCD $d$ of \typ{INT}s \kbd{a} and \kbd{b} and sets \kbd{u}, \kbd{v} to the Bezout coefficients such that $\kbd{au} + \kbd{bv} = d$. \fun{long}{cbezout}{long a,long b, long *u,long *v}, returns the GCD $d$ of \kbd{a} and \kbd{b} and sets \kbd{u}, \kbd{v} to the Bezout coefficients such that $\kbd{au} + \kbd{bv} = d$. \fun{GEN}{halfgcdii}{GEN x, GEN y} assuming \kbd{x} and \kbd{y} are \typ{INT}s, returns a $2$-components \typ{VEC} $[M,V]$ where $M$ is a $2\times 2$ \typ{MAT} and $V$ a $2$-component \typ{COL}, both with \typ{INT} entries, such that $M*[x,y]~==V$ and such that if $V=[a,b]~$, then $a \geq \ceil{\sqrt{\max(|x|,|y|)}} > b$. \fun{GEN}{ZV_extgcd}{GEN A} given a vector of $n$ integers $A$, returns $[d, U]$, where $d$ is the GCD of the $A[i]$ and $U$ is a matrix in $\text{GL}_n(\Z)$ such that $AU = [0,\dots,0,D]$. \fun{GEN}{ZV_lcm}{GEN v} given a vector $v$ of integers returns the LCM of its entries. \fun{GEN}{ZV_snf_gcd}{GEN v, GEN N} given a vector $v$ of integers and a positive integer $N$, return the vector whose entries are the gcds $(v[i],N)$. Use case: if $v$ gives the cyclic components for some Abelian group $G$ of finite type, then this returns the structure of the finite groupe $G/G^N$. \subsec{Continued fractions and convergents} \fun{GEN}{ZV_allpnqn}{GEN x} given $x = [a_0, ..., a_n]$ a continued fraction from \tet{gboundcf}, $n\geq0$, return all convergents as $[P,Q]$, where $P = [p_0,\dots,p_n]$ and $Q = [q_0,\dots,q_n]$. \subsec{Pseudo-random integers} These routine return pseudo-random integers uniformly distributed in some interval. The all use the same underlying generator which can be seeded and 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 nonnegative residue). (This is identical to modii). \fun{GEN}{Fp_neg}{GEN a, GEN m} returns $-$\kbd{a} modulo \kbd{m} (smallest nonnegative residue). \fun{GEN}{Fp_add}{GEN a, GEN b, GEN m} returns the sum of \kbd{a} and \kbd{b} modulo \kbd{m} (smallest nonnegative residue). \fun{GEN}{Fp_sub}{GEN a, GEN b, GEN m} returns the difference of \kbd{a} and \kbd{b} modulo \kbd{m} (smallest nonnegative residue). \fun{GEN}{Fp_center}{GEN a, GEN p, GEN pov2} assuming that \kbd{pov2} is \kbd{shifti(p,-1)} and that $-p/2 < a < p$, returns the representative of \kbd{a} in the symmetric residue system $]-p/2,p/2]$. \fun{GEN}{Fp_center_i}{GEN a, GEN p, GEN pov2} internal variant of \tet{Fp_center}, not \kbd{gerepile}-safe: when $a$ is already in the proper interval, it is returned as is, without a copy. \fun{GEN}{Fp_mul}{GEN a, GEN b, GEN m} returns the product of \kbd{a} by \kbd{b} modulo \kbd{m} (smallest nonnegative residue). \fun{GEN}{Fp_addmul}{GEN x, GEN y, GEN z, GEN p} returns $x + y\*z$. \fun{GEN}{Fp_mulu}{GEN a, ulong b, GEN m} returns the product of \kbd{a} by \kbd{b} modulo \kbd{m} (smallest nonnegative residue). \fun{GEN}{Fp_muls}{GEN a, long b, GEN m} returns the product of \kbd{a} by \kbd{b} modulo \kbd{m} (smallest nonnegative residue). \fun{GEN}{Fp_halve}{GEN x, GEN m} returns $z$ such that $2\*z = x$ modulo $m$ assuming such $z$ exists. Assume that $0 \leq x < m$. Not memory-clean, but suitable for \kbd{gerepileupto}. \fun{GEN}{Fp_double}{GEN x, GEN m} return $2x$ modulo $m$. Assume that $0 \leq x < m$. Not memory-clean, but suitable for \kbd{gerepileupto}. \fun{GEN}{Fp_sqr}{GEN a, GEN m} returns $\kbd{a}^2$ modulo \kbd{m} (smallest nonnegative residue). \fun{ulong}{Fp_powu}{GEN x, ulong n, GEN m} raises \kbd{x} to the \kbd{n}-th power modulo \kbd{m} (smallest nonnegative 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 nonnegative 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 nonnegative residue). \fun{GEN}{Fp_pow_init}{GEN x, GEN n, long k, GEN p} Return a table \kbd{R} that can be used with \kbd{Fp\_pow\_table} to compute the powers of $x$ up to $n$. The table is of size $2^k\*\log_2(n)$. \fun{GEN}{Fp_pow_table}{GEN R, GEN n, GEN p} return $x^n$, where $R$ is given by \kbd{Fp\_pow\_init(x,m,k,p)} for some integer $m\geq n$. \fun{GEN}{Fp_powers}{GEN x, long n, GEN m} returns $[\kbd{x}^0, \dots, \kbd{x}^\kbd{n}]$ modulo \kbd{m} as a \typ{VEC} (smallest nonnegative residue). \fun{GEN}{Fp_inv}{GEN a, GEN m} returns an inverse of \kbd{a} modulo \kbd{m} (smallest nonnegative 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}{Fp_invgen}{GEN x, GEN m, GEN *pg} set \kbd{*pg} to $g = \gcd(x,m)$ and return $u$ in $(\Z/m\Z)^*$ such that $x u = g$ modulo $m$. We have $g = 1$ if and only if $x$ is invertible, and in this case $u$ is its inverse. \fun{GEN}{FpV_prod}{GEN x, GEN p} returns the product of the components of $x$. \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 nonnegative residue). Raise an error if \kbd{b} is not invertible. \fun{GEN}{Fp_divu}{GEN a, ulong b, GEN m} returns the quotient of \kbd{a} by \kbd{b} modulo \kbd{m} (smallest nonnegative 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})$. In the following three functions the integer parameter \kbd{ord} can be given either as a positive \typ{INT} $N$, or as its factorization matrix $\var{faN}$, or as a pair $[N,\var{faN}]$. The parameter may be omitted by setting it to \kbd{NULL} (the value is then $p-1$). \fun{GEN}{Fp_log}{GEN a, GEN g, GEN ord, GEN p} Let $g$ such that $g^{ord} \equiv 1 \pmod{p}$. Return an integer $e$ such that $a^e \equiv g \pmod{p}$. If $e$ does not exist, the result is undefined. \fun{GEN}{Fp_order}{GEN a, GEN ord, GEN p} returns the order of the \kbd{Fp} \kbd{a}. Assume that \kbd{ord} is a multiple of the order of \kbd{a}. \fun{GEN}{Fp_factored_order}{GEN a, GEN ord, GEN p} returns $[o,F]$, where $o$ is the multiplicative order of the \kbd{Fp} $a$ in $\F_p^*$, and $F$ is the factorization of $o$. Assume that \kbd{ord} is a multiple of the order of \kbd{a}. \fun{int}{Fp_issquare}{GEN x, GEN p} returns $1$ if \kbd{x} is a square modulo \kbd{p}, and $0$ otherwise. \fun{int}{Fp_ispower}{GEN x, GEN n, GEN p} returns $1$ if \kbd{x} is an $n$-th power modulo \kbd{p}, and $0$ otherwise. \fun{GEN}{Fp_sqrt}{GEN x, GEN p} returns a square root of \kbd{x} modulo \kbd{p} (the smallest nonnegative 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_2gener}{GEN p} return a generator of the $2$-Sylow subgroup of $\F_p^*$. To use with \kbd{Fp\_sqrt\_i}. \fun{GEN}{Fp_2gener_i}{GEN ns, GEN p} as \kbd{Fp\_2gener}, where \kbd{ns} is a non-square modulo $p$. \fun{GEN}{Fp_sqrt_i}{GEN x, GEN s2, GEN p} as \kbd{Fp\_sqrt} where \kbd{s2} is the element returned by \kbd{Fp\_2gener}. \fun{GEN}{Fp_sqrtn}{GEN a, GEN n, GEN p, GEN *zn} returns \kbd{NULL} if $a$ is not an $n$-th power residue mod $p$. Otherwise, returns an $n$-th root of $a$; if \kbd{zn} is not \kbd{NULL} set it to a primitive $m$-th root of 1, $m = \gcd(p-1,n)$ allowing to compute all $m$ solutions in $\F_p$ of the equation $x^n = a$. \fun{GEN}{Zn_sqrt}{GEN x, GEN n} returns one of the square roots of \kbd{x} modulo \kbd{n} (possibly not prime), where \kbd{x} is a \typ{INT} and \kbd{n} is either a \typ{INT} or is given by its factorization matrix. Return \kbd{NULL} if no such square root exist. \fun{GEN}{Zn_quad_roots}{GEN N, GEN B, GEN C} solves the equation $X^2 + B X + C$ modulo $N$. Return \kbd{NULL} if there are no solutions. Else returns $[M, v]$ where $M \mid N$ and the \kbd{FpV} $v$ of distinct integers (reduced, implicitly modulo $M$) is such that $x$ modulo $N$ is a solution to the equation if and only if $x$ modulo $M$ belongs to $v$. If the discriminant $B^2-4C$ is coprime to $N$, we have $M = N$ but in general $M$ can be a strict divisor of $N$. \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 nonzero. If \kbd{y} is an odd prime, this is the \idx{Legendre symbol}. \fun{long}{krois}{GEN x, long y} returns the \idx{Kronecker symbol} $(x|y)$ of \typ{INT}~x and \kbd{long}~\kbd{y}. As \kbd{kross} otherwise. \fun{long}{kroiu}{GEN x, ulong y} returns the \idx{Kronecker symbol} $(x|y)$ of \typ{INT}~x and nonzero \kbd{ulong}~\kbd{y}. As \kbd{krouu} otherwise. \fun{long}{krosi}{long x, GEN y} returns the \idx{Kronecker symbol} $(x|y)$ of \kbd{long}~x and \typ{INT}~\kbd{y}. As \kbd{kross} otherwise. \fun{long}{kroui}{ulong x, GEN y} returns the \idx{Kronecker symbol} $(x|y)$ of \kbd{long}~x and \typ{INT}~\kbd{y}. As \kbd{kross} otherwise. \fun{long}{kronecker}{GEN x, GEN y} returns the \idx{Kronecker symbol} $(x|y)$ of \typ{INT}s~x and~\kbd{y}. As \kbd{kross} otherwise. \fun{GEN}{factorial_Fp}{long n, GEN p} return $n!$ mod $p$. \fun{GEN}{pgener_Fp}{GEN p} returns the smallest primitive root modulo \kbd{p}, assuming \kbd{p} is prime. \fun{GEN}{pgener_Zp}{GEN p} returns the smallest primitive root modulo $p^k$, $k > 1$, assuming \kbd{p} is an odd prime. \fun{long}{Zp_issquare}{GEN x, GEN p} returns 1 if the \typ{INT} $x$ is a $p$-adic square, $0$ otherwise. \fun{long}{Zn_issquare}{GEN x, GEN n} returns 1 if \typ{INT} $x$ is a square modulo \kbd{n} (possibly not prime), where $n$ is either a \typ{INT} or is given by its factorization matrix. Return $0$ otherwise. \fun{long}{Zn_ispower}{GEN x, GEN n, GEN K, GEN *py} returns 1 if \typ{INT} $x$ is a $K$-th power modulo \kbd{n} (possibly not prime), where $n$ is either a \typ{INT} or is given by its factorization matrix. Return $0$ otherwise. If \kbd{py} is not \kbd{NULL}, set it to $y$ such that $y^K = x$ modulo $n$. \fun{GEN}{pgener_Fp_local}{GEN p, GEN L}, \kbd{L} being a vector of primes dividing $p - 1$, returns the smallest integer $x > 1$ which is a generator of the $\ell$-Sylow of $\F_p^*$ for every $\ell$ in \kbd{L}. In other words, $x^{(p-1)/\ell} \neq 1$ for all such $\ell$. In particular, returns \kbd{pgener\_Fp(p)} if \kbd{L} contains all primes dividing $p - 1$. It is not necessary, and in fact slightly inefficient, to include $\ell=2$, since 2 is treated separately in any case, i.e. the generator obtained is never a square. \fun{GEN}{rootsof1_Fp}{GEN n, GEN p} returns a primitive $n$-th root modulo the prime $p$. \fun{GEN}{rootsof1u_Fp}{ulong n, GEN p} returns a primitive $n$-th root modulo the prime $p$. \fun{ulong}{rootsof1_Fl}{ulong n, ulong p} returns a primitive $n$-th root modulo the prime $p$. \subsec{Extending functions to vector inputs} The following functions apply $f$ to the given arguments, recursively if they are of vector / matrix type: \fun{GEN}{map_proto_G}{GEN (*f)(GEN), GEN x} For instance, if $x$ is a \typ{VEC}, return a \typ{VEC} whose components are the $f(x[i])$. \fun{GEN}{map_proto_lG}{long (*f)(GEN), GEN x} As above, applying the function \kbd{stoi( f() )}. \fun{GEN}{map_proto_GL}{GEN (*f)(GEN,long), GEN x, long y} \fun{GEN}{map_proto_lGL}{long (*f)(GEN,long), GEN x, long y} In the last function, $f$ implements an associative binary operator, which we extend naturally to an $n$-ary operator $f_n$ for any $n$: by convention, $f_0() = 1$, $f_1(x) = x$, and $$ f_n(x_1,\dots,x_n) = f( f_{n-1}(x_1,\dots,x_{n-1}), x_n)),$$ for $n \geq 2$. \fun{GEN}{gassoc_proto}{GEN (*f)(GEN,GEN),GEN x, GEN y} If $y$ is not \kbd{NULL}, return $f(x,y)$. Otherwise, $x$ must be of vector type, and we return the result of $f$ applied to its components, computed using a divide-and-conquer algorithm. More precisely, return $$f( f(x_1,\kbd{NULL}), f(x_2,\kbd{NULL}) ),$$ where $x_1$, $x_2$ are the two halves of $x$. \subsec{Miscellaneous arithmetic functions} \fun{long}{bigomegau}{ulong n} returns the number of prime divisors of $n > 0$, counted with multiplicity. \fun{ulong}{coreu}{ulong n}, unique squarefree integer $d$ dividing $n$ such that $n/d$ is a square. \fun{ulong}{coreu_fact}{GEN fa} same, where \kbd{fa} is \kbd{factoru(n)}. \fun{ulong}{corediscs}{long d, ulong *pt_f}, $d$ (possibly negative) being congruent to $0$ or $1$ modulo $4$, return the fundamental discriminant $D$ such that $d=D*f^2$ and set \kbd{*pt\_f} to $f$ (if \kbd{*pt\_f} not \kbd{NULL}). \fun{GEN}{coredisc2_fact}{GEN fa, long s, GEN *pP, GEN *pE} let $d$ be an integer congruent to $0$ or $1$ mod $4$. Return $D = \kbd{coredisc}(d)$ assuming that \kbd{fa} is the factorization of $|d|$ and $s d > 0$ ($s$ is the sign of $d$). Set \kbd{*pP} and \kbd{*pE} to the factorization of the conductor $f$ such that $d = Df^2$, where $P$ is a \typ{VEC} of primes and $E$ a \typ{VECSMALL} of exponents. \fun{ulong}{coredisc2u_fact}{GEN fa, long s, GEN *pP, GEN *pE} let $d$ be an integer congruent to $0$ or $1$ mod $4$ whose absolute value fits in an \kbd{ulong}. Return the absolute value of $D = \kbd{corediscs}(d)$ assuming that \kbd{fa} is the factorization of $|d|$ and $s d > 0$ ($s$ is the sign of $d$ and $D$). Set \kbd{*pP} and \kbd{*pE} to the factorization of the conductor $f$ such that $d = Df^2$, where $P$ is a \typ{VECSMALL} of primes and $E$ a \typ{VECSMALL} of exponents. \fun{ulong}{eulerphiu}{ulong n}, Euler's totient function of $n$. \fun{ulong}{eulerphiu_fact}{GEN fa} same, where \kbd{fa} is \kbd{factoru(n)}. \fun{long}{moebiusu}{ulong n}, Moebius $\mu$-function of $n$. \fun{long}{moebiusu_fact}{GEN fa} same, where \kbd{fa} is \kbd{factoru(n)}. \fun{ulong}{radicalu}{ulong n}, product of primes dividing $n$. \fun{GEN}{divisorsu}{ulong n}, returns the divisors of $n$ in a \typ{VECSMALL}, sorted by increasing order. \fun{GEN}{divisorsu_fact}{GEN fa} same, where \kbd{fa} is \kbd{factoru(n)}. \fun{GEN}{divisorsu_fact_factored}{GEN fa} where \kbd{fa} is \kbd{factoru(n)}. Return a vector $[D,F]$, where $D$ is a a \typ{VECSMALL} containing the divisors of $u$ and $F[i]$ contains \kbd{factoru}$(D[i])$. \fun{GEN}{divisorsu_moebius}{GEN P} returns the divisors of $n$ of the form $\prod_{p\in S} (-p)$, $S\subset P$ in a \typ{VECSMALL}. The vector is not sorted but its first element is guaranteed to be $1$. If $P$ is \kbd{factoru(n)[1]}, this returns the set of $\mu(d) d$ where $d$ runs through the squarefree divisors of $n$. \fun{long}{numdivu}{ulong n}, returns the number of positive divisors of $n>0$. \fun{long}{numdivu_fact}{GEN fa} same, where \kbd{fa} is \kbd{factoru(n)}. \fun{long}{omegau}{ulong n} returns the number of prime divisors of $n > 0$. \fun{long}{maxomegau}{ulong x} return the optimal $B$ such that $\omega(n) \leq B $ for all $n \leq x$. \fun{long}{maxomegaoddu}{ulong x} return the optimal $B$ such that $\omega(n) \leq B $ for all odd $n \leq x$. \fun{long}{uissquarefree}{ulong n} returns $1$ if \kbd{n} is square-free, and $0$ otherwise. \fun{long}{uissquarefree_fact}{GEN fa} same, where \kbd{fa} is \kbd{factoru(n)}. \fun{long}{uposisfundamental}{ulong x} return $1$ if $x$ is a fundamental discriminant, and $0$ otherwise. \fun{long}{unegisfundamental}{ulong x} return $1$ if $-x$ is a fundamental discriminant, and $0$ otherwise. \fun{long}{sisfundamental}{long x} return $1$ if $x$ is a fundamental discriminant, and $0$ otherwise. \fun{int}{uis_357_power}{ulong x, ulong *pt, ulong *mask} as \tet{is_357_power} for \kbd{ulong} $x$. \fun{int}{uis_357_powermod}{ulong x, ulong *mask} as \tet{uis_357_power}, but only check for 3rd, 5th or 7th powers modulo $211\times209\times61\times203\times117\times31\times43\times71$. \fun{long}{uisprimepower}{ulong n, ulong *p} as \tet{isprimepower}, for \kbd{ulong} $n$. \fun{int}{uislucaspsp}{ulong n} returns $1$ if the \kbd{ulong} $n$ fails Lucas compositeness test (it thus may be prime or composite), and $0$ otherwise (proving that $n$ is composite). \fun{int}{uis2psp}{ulong n} returns $1$ if the odd \kbd{ulong} $n > 1$ fails a strong Rabin-Miller test for the base $2$ (it thus may be prime or composite), and $0$ otherwise (proving that $n$ is composite). \fun{int}{uispsp}{ulong a, ulong n} returns $1$ if the odd \kbd{ulong} $n > 1$ fails a strong Rabin-Miller test for the base $1 < a < n$ (it thus may be prime or composite), and $0$ otherwise (proving that $n$ is composite). \fun{ulong}{sumdigitsu}{ulong n} returns the sum of decimal digits of $u$. \fun{GEN}{usumdiv_fact}{GEN fa}, sum of divisors of \kbd{ulong} $n$, where \kbd{fa} is \kbd{factoru(n)}. \fun{GEN}{usumdivk_fact}{GEN fa, ulong k}, sum of $k$-th powers of divisors of \kbd{ulong} $n$, where \kbd{fa} is \kbd{factoru(n)}. \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 attached to the \typ{INT} $h$ and $k$, $k > 0$. \fun{GEN}{sumdedekind_coprime}{GEN h, GEN k} as \kbd{sumdedekind}, except that $h$ and $k$ are assumed to be coprime \typ{INT}s. \fun{GEN}{u_sumdedekind_coprime}{long h, long k} Let $k > 0$, $0 \leq h < k$, $(h,k) = 1$. Returns $[s_1,s_2]$ in a \typ{VECSMALL}, such that $s(h,k) = (s_2 + k s_1) / (12k)$. Requires $\max(h + k/2, k) < \kbd{LONG\_MAX}$ to avoid overflow, in particular $k \leq (2/3)\kbd{LONG\_MAX}$ is fine. \newpage \chapter{Level 2 kernel} These functions deal with modular arithmetic, linear algebra and polynomials where assumptions can be made about the types of the coefficients. \section{Naming scheme}\label{se:level2names} A function name is built in the following way: $A_1\kbd{\_}\dots\kbd{\_}A_n\var{fun}$ for an operation \var{fun} with $n$ arguments of class $A_1$,\dots, $A_n$. A class name is given by a base ring followed by a number of code letters. Base rings are among \kbd{Fl}: $\Z/l\Z$ where $l < 2^{\B}$ is not necessarily prime. Implemented using \kbd{ulong}s \kbd{Fp}: $\Z/p\Z$ where $p$ is a \typ{INT}, not necessarily prime. Implemented as \typ{INT}s $z$, preferably satisfying $0 \leq z < p$. More precisely, any \typ{INT} can be used as an \kbd{Fp}, but reduced inputs are treated more efficiently. Outputs from \kbd{Fp}xxx routines are reduced. \kbd{Fq}: $\Z[X]/(p,T(X))$, $p$ a \typ{INT}, $T$ a \typ{POL} with \kbd{Fp} coefficients or \kbd{NULL} (in which case no reduction modulo \kbd{T} is performed). Implemented as \typ{POL}s $z$ with \kbd{Fp} coefficients, $\deg(z) < \deg \kbd{T}$, although $z$ a \typ{INT} is allowed for elements in the prime field. \kbd{Z}: the integers $\Z$, implemented as \typ{INT}s. \kbd{Zp}: the $p$-adic integers $\Z_p$, implemented as \typ{INT}s, for arbitrary $p$ \kbd{Zl}: the $p$-adic integers $\Z_p$, implemented as \typ{INT}s, for $p< 2^{\B}$ \kbd{z}: the integers $\Z$, implemented using (signed) \kbd{long}s. \kbd{Q}: the rational numbers $\Q$, implemented as \typ{INT}s and \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 row vector (independently of the actual type). E.g. \kbd{ZV} means $\Z^k$ for some $k$. \kbd{C}: vector (\typ{VEC} or \typ{COL}), treated as a column vector (independently of the actual type). The difference with \kbd{V} is purely semantic: if the result is a vector, it will be of type \typ{COL} unless mentioned otherwise. For instance the function \kbd{ZC\_add} receives two integral vectors (\typ{COL} or \typ{VEC}, possibly different types) of the same length and returns a \typ{COL} whose entries are the sums of the input coefficients. \kbd{M}: matrix (\typ{MAT}). E.g. \kbd{QM} means a matrix with rational entries \kbd{T}: Trees. Either a leaf or a \typ{VEC} of trees. \kbd{E}: point over an elliptic curve, represented as two-component vectors \kbd{[x,y]}, except for the represented by the one-component vector \kbd{[0]}. Not all curve models are supported. \kbd{Q}: representative (\typ{POL}) of a class in a polynomial quotient ring. E.g.~an \kbd{FpXQ} belongs to $(\Z/p\Z)[X]/(T(X))$, \kbd{FpXQV} means a vector of such elements, etc. \kbd{n}: a polynomial representative (\typ{POL}) for a truncated power series modulo $X^n$. E.g.~an \kbd{FpXn} belongs to $(\Z/p\Z)[X]/(X^n)$, \kbd{FpXnV} means a vector of such elements, etc. \kbd{x}, \kbd{y}, \kbd{m}, \kbd{v}, \kbd{c}, \kbd{q}: as their uppercase counterpart, but coefficient arrays are implemented using \typ{VECSMALL}s, which coefficient understood as \kbd{ulong}s. \kbd{x} and \kbd{y} (and \kbd{q}) are implemented by a \typ{VECSMALL} whose first coefficient is used as a code-word and the following are the coefficients , similarly to a \typ{POL}. This is known as a 'POLSMALL'. \kbd{m} are implemented by a \typ{MAT} whose components (columns) are \typ{VECSMALL}s. This is known as a 'MATSMALL'. \kbd{v} and \kbd{c} are regular \typ{VECSMALL}s. Difference between the two is purely semantic. \noindent Omitting the letter means the argument is a scalar in the base ring. Standard functions \var{fun} are \kbd{add}: add \kbd{sub}: subtract \kbd{mul}: multiply \kbd{sqr}: square \kbd{div}: divide (Euclidean quotient) \kbd{rem}: Euclidean remainder \kbd{divrem}: return Euclidean quotient, store remainder in a pointer argument. Three special values of that pointer argument modify the default behavior: \kbd{NULL} (do not store the remainder, used to implement \kbd{div}), \tet{ONLY_REM} (return the remainder, used to implement \kbd{rem}), \tet{ONLY_DIVIDES} (return the quotient if the division is exact, and \kbd{NULL} otherwise). \kbd{gcd}: GCD \kbd{extgcd}: return GCD, store Bezout coefficients in pointer arguments \kbd{pow}: exponentiate \kbd{eval}: evaluation / composition \section{Coefficient ring} \fun{long}{Rg_type}{GEN x, GEN *ptp, GEN *ptpol, long *ptprec} returns the ``natural'' base ring over which the object $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 $\Z$. \item \typ{FRAC}: defined over $\Q$. \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 \typ{POL}: defined over a polynomial ring. \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}{Rg_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}{Rg_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{long}{RgX_type}{GEN x, GEN *ptp, GEN *ptpol, long *ptprec} returns the ``natural'' base ring over which the polynomial $x$ is defined, otherwise as \kbd{Rg\_type}. \fun{long}{RgX_Rg_type}{GEN x, GEN y, GEN *ptp, GEN *ptpol, long *ptprec} returns the ``natural'' base ring over which the polynomial $x$ and the element $y$ are defined, otherwise as \kbd{Rg\_type}. \fun{long}{RgX_type2}{GEN x, GEN y, GEN *ptp, GEN *ptpol, long *ptprec} returns the ``natural'' base ring over which the polynomials $x$ and $y$ are defined, otherwise as \kbd{Rg\_type}. \fun{long}{RgX_type3}{GEN x, GEN y, GNE z, GEN *ptp, GEN *ptpol, long *ptprec} returns the ``natural'' base ring over which the polynomials $x$, $y$ and $z$ are defined, otherwise as \kbd{Rg\_type}. \fun{long}{RgM_type}{GEN x, GEN *ptp, GEN *ptpol, long *ptprec} returns the ``natural'' base ring over which the matrix $x$ is defined, otherwise as \kbd{Rg\_type}. \fun{long}{RgM_type2}{GEN x, GEN y, GEN *ptp, GEN *ptpol, long *ptprec} returns the ``natural'' base ring over which the matrices $x$ and $y$ are defined, otherwise as \kbd{Rg\_type}. \fun{long}{RgV_type}{GEN x, GEN *ptp, GEN *ptpol, long *ptprec} returns the ``natural'' base ring over which the vector $x$ is defined, otherwise as \kbd{Rg\_type}. \fun{long}{RgV_type2}{GEN x, GEN y, GEN *ptp, GEN *ptpol, long *ptprec} returns the ``natural'' base ring over which the vectors $x$ and $y$ are defined, otherwise as \kbd{Rg\_type}. \fun{long}{RgM_RgC_type}{GEN x, GEN y, GEN *ptp, GEN *ptpol, long *ptprec} returns the ``natural'' base ring over which the matrix $x$ and the vector $y$ are defined, otherwise as \kbd{Rg\_type}. \section{Modular arithmetic} \noindent These routines implement univariate polynomial arithmetic and linear algebra over finite fields, in fact over finite rings of the form $(\Z/p\Z)[X]/(T)$, where $p$ is not necessarily prime and $T\in(\Z/p\Z)[X]$ is possibly reducible; and finite extensions thereof. All this can be emulated with \typ{INTMOD} and \typ{POLMOD} coefficients and using generic routines, at a considerable loss of efficiency. Also, specialized routines are available that have no obvious generic equivalent. \subsec{\kbd{FpC} / \kbd{FpV}, \kbd{FpM}} A \kbd{ZV} (resp.~a~\kbd{ZM}) is a \typ{VEC} or \typ{COL} (resp.~\typ{MAT}) with \typ{INT} coefficients. An \kbd{FpV} or \kbd{FpM}, with respect to a given \typ{INT}~\kbd{p}, is the same with \kbd{Fp} coordinates; operations are understood over $\Z/p\Z$. \subsubsec{Conversions} \fun{int}{Rg_is_Fp}{GEN z, GEN *p}, checks if \kbd{z} can be mapped to $\Z/p\Z$: a \typ{INT} or a \typ{INTMOD} whose modulus is equal to \kbd{*p}, (if \kbd{*p} not \kbd{NULL}), in that case return $1$, else $0$. If a modulus is found it is put in \kbd{*p}, else \kbd{*p} is left unchanged. \fun{int}{RgV_is_FpV}{GEN z, GEN *p}, \kbd{z} a \typ{VEC} (resp. \typ{COL}), checks if it can be mapped to a \kbd{FpV} (resp. \kbd{FpC}), by checking \kbd{Rg\_is\_Fp} coefficientwise. \fun{int}{RgM_is_FpM}{GEN z, GEN *p}, \kbd{z} a \typ{MAT}, checks if it can be mapped to a \kbd{FpM}, by checking \kbd{RgV\_is\_FpV} columnwise. \fun{GEN}{Rg_to_Fp}{GEN z, GEN p}, \kbd{z} a scalar which can be mapped to $\Z/p\Z$: a \typ{INT}, a \typ{INTMOD} whose modulus is divisible by $p$, a \typ{FRAC} whose denominator is coprime to $p$, or a \typ{PADIC} with underlying prime $\ell$ satisfying $p = \ell^n$ for some $n$ (less than the accuracy of the input). Returns \kbd{lift(z * Mod(1,p))}, normalized. \fun{GEN}{padic_to_Fp}{GEN x, GEN p} special case of \tet{Rg_to_Fp}, for a $x$ a \typ{PADIC}. \fun{GEN}{RgV_to_FpV}{GEN z, GEN p}, \kbd{z} a \typ{VEC} or \typ{COL}, returns the \kbd{FpV} (as a \typ{VEC}) obtained by applying \kbd{Rg\_to\_Fp} coefficientwise. \fun{GEN}{RgC_to_FpC}{GEN z, GEN p}, \kbd{z} a \typ{VEC} or \typ{COL}, returns the \kbd{FpC} (as a \typ{COL}) obtained by applying \kbd{Rg\_to\_Fp} coefficientwise. \fun{GEN}{RgM_to_FpM}{GEN z, GEN p}, \kbd{z} a \typ{MAT}, returns the \kbd{FpM} obtained by applying \kbd{RgC\_to\_FpC} columnwise. \fun{GEN}{RgM_Fp_init}{GEN z, GEN p, ulong *pp}, given an \kbd{RgM} $z$, whose entries can be mapped to $\F_p$ (as per \tet{Rg_to_Fp}), and a prime number $p$. This routine returns a normal form of $z$: either an \kbd{F2m} ($p = 2$), an \kbd{Flm} ($p$ fits into an \kbd{ulong}) or an \kbd{FpM}. In the first two cases, \kbd{pp} is set to \kbd{itou}$(p)$, and to $0$ in the last. The functions above are generally used as follows: \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}{random_FpC}{long n, GEN p} returns a random \kbd{FpC} with $n$ components. \fun{GEN}{random_FpV}{long n, GEN p} returns a random \kbd{FpV} with $n$ components. \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{void}{FpC_center_inplace}{GEN z, GEN p, GEN pov2} in-place version of \kbd{FpC\_center}, using \kbd{affii}. \fun{void}{FpM_center_inplace}{GEN z, GEN p, GEN pov2} in-place version of \kbd{FpM\_center}, using \kbd{affii}. \fun{GEN}{FpC_add}{GEN x, GEN y, GEN p} adds the \kbd{ZC} $x$ and $y$ and reduce modulo $p$ to obtain an \kbd{FpC}. \fun{GEN}{FpV_add}{GEN x, GEN y, GEN p} same as \kbd{FpC\_add}, returning and \kbd{FpV}. \fun{GEN}{FpM_add}{GEN x, GEN y, GEN p} adds the two \kbd{ZM}s~\kbd{x} and \kbd{y} (assumed to have compatible dimensions), and reduce modulo \kbd{p} to obtain an \kbd{FpM}. \fun{GEN}{FpC_sub}{GEN x, GEN y, GEN p} subtracts the \kbd{ZC} $y$ to the \kbd{ZC} $x$ and reduce modulo $p$ to obtain an \kbd{FpC}. \fun{GEN}{FpV_sub}{GEN x, GEN y, GEN p} same as \kbd{FpC\_sub}, returning and \kbd{FpV}. \fun{GEN}{FpM_sub}{GEN x, GEN y, GEN p} subtracts the two \kbd{ZM}s~\kbd{x} and \kbd{y} (assumed to have compatible dimensions), and reduce modulo \kbd{p} to obtain an \kbd{FpM}. \fun{GEN}{FpC_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}{FpM_Fp_mul}{GEN x, GEN y, GEN p} multiplies the \kbd{ZM}~\kbd{x} (seen as a column vector) by the \typ{INT}~\kbd{y} and reduce modulo \kbd{p} to obtain an \kbd{FpM}. \fun{GEN}{FpC_FpV_mul}{GEN x, GEN y, GEN p} multiplies the \kbd{ZC}~\kbd{x} (seen as a column vector) by the \kbd{ZV}~\kbd{y} (seen as a row vector, assumed to have compatible dimensions), and reduce modulo \kbd{p} to obtain an \kbd{FpM}. \fun{GEN}{FpM_mul}{GEN x, GEN y, GEN p} multiplies the two \kbd{ZM}s~\kbd{x} and \kbd{y} (assumed to have compatible dimensions), and reduce modulo \kbd{p} to obtain an \kbd{FpM}. \fun{GEN}{FpM_powu}{GEN x, ulong n, GEN p} computes $x^n$ where $x$ is a square \kbd{FpM}. \fun{GEN}{FpM_FpC_mul}{GEN x, GEN y, GEN p} multiplies the \kbd{ZM}~\kbd{x} by the \kbd{ZC}~\kbd{y} (seen as a column vector, assumed to have compatible dimensions), and reduce modulo \kbd{p} to obtain an \kbd{FpC}. \fun{GEN}{FpM_FpC_mul_FpX}{GEN x, GEN y, GEN p, long v} is a memory-clean version of \bprog GEN tmp = FpM_FpC_mul(x,y,p); return RgV_to_RgX(tmp, v); @eprog \fun{GEN}{FpV_FpC_mul}{GEN x, GEN y, GEN p} multiplies the \kbd{ZV}~\kbd{x} (seen as a row vector) by the \kbd{ZC}~\kbd{y} (seen as a column vector, assumed to have compatible dimensions), and reduce modulo \kbd{p} to obtain an \kbd{Fp}. \fun{GEN}{FpV_dotproduct}{GEN x,GEN y,GEN p} scalar product of $x$ and $y$ (assumed to have the same length). \fun{GEN}{FpV_dotsquare}{GEN x, GEN p} scalar product of $x$ with itself. has \typ{INT} entries. \fun{GEN}{FpV_factorback}{GEN L, GEN e, GEN p} given an \kbd{FpV} $L$ and a \kbd{ZV} or \kbd{zv} $e$ of the same length, return $\prod_i L_i^{e_i}$ modulo $p$. \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 nontrivial kernel vector, or \kbd{NULL} if none exist. \fun{GEN}{FpM_det}{GEN x, GEN p} as \kbd{det} \fun{GEN}{FpM_gauss}{GEN a, GEN b, GEN p} as \kbd{gauss}, where $a$ and $b$ are \kbd{FpM}. \fun{GEN}{FpM_FpC_gauss}{GEN a, GEN b, GEN p} as \kbd{gauss}, where $a$ is a \kbd{FpM} and $b$ a \kbd{FpC}. \fun{GEN}{FpM_image}{GEN x, GEN p} as \kbd{image} \fun{GEN}{FpM_intersect}{GEN x, GEN y, GEN p} as \kbd{intersect} \fun{GEN}{FpM_intersect_i}{GEN x, GEN y, GEN p} internal variant of \kbd{FpM\_intersect} but the result is only a generating set, not necessarily an $\F_p$-basis. It is not \kbd{gerepile}-clean either, but suitable for \kbd{gerepileupto}. \fun{GEN}{FpM_inv}{GEN x, GEN p} returns a left inverse of \kbd{x} (the inverse if $x$ is square), or \kbd{NULL} if \kbd{x} is not invertible. \fun{GEN}{FpM_FpC_invimage}{GEN A, GEN y, GEN p} given an \kbd{FpM} $A$ and an \kbd{FpC} $y$, returns an $x$ such that $Ax = y$, or \kbd{NULL} if no such vector exist. \fun{GEN}{FpM_invimage}{GEN A, GEN y, GEN p} given two \kbd{FpM} $A$ and $y$, returns $x$ such that $Ax = y$, or \kbd{NULL} if no such matrix exist. \fun{GEN}{FpM_ker}{GEN x, GEN p} as \kbd{ker} \fun{long}{FpM_rank}{GEN x, GEN p} as \kbd{rank} \fun{GEN}{FpM_indexrank}{GEN x, GEN p} as \kbd{indexrank} \fun{GEN}{FpM_suppl}{GEN x, GEN p} as \kbd{suppl} \fun{GEN}{FpM_hess}{GEN x, GEN p} upper Hessenberg form of $x$ over $\F_p$. \fun{GEN}{FpM_charpoly}{GEN x, GEN p} characteristic polynomial of $x$. \subsubsec{\kbd{FqC}, \kbd{FqM} and \kbd{Fq}-linear algebra} An \kbd{FqM} (resp. \kbd{FqC}) is a matrix (resp a \typ{COL}) with \kbd{Fq} coefficients (with respect to given \kbd{T}, \kbd{p}), not necessarily reduced (i.e arbitrary \typ{INT}s and \kbd{ZX}s in the same variable as \kbd{T}). \fun{GEN}{RgC_to_FqC}{GEN z, GEN T, GEN p} \fun{GEN}{RgM_to_FqM}{GEN z, GEN T, GEN p} \fun{GEN}{FqC_add}{GEN a, GEN b, GEN T, GEN p} \fun{GEN}{FqC_sub}{GEN a, GEN b, GEN T, GEN p} \fun{GEN}{FqC_Fq_mul}{GEN a, GEN b, GEN T, GEN p} \fun{GEN}{FqC_FqV_mul}{GEN a, GEN b, GEN T, GEN p} \fun{GEN}{FqM_FqC_gauss}{GEN a, GEN b, GEN T, GEN p} as \kbd{gauss}, where $b$ is a \kbd{FqC}. \fun{GEN}{FqM_FqC_invimage}{GEN a, GEN b, GEN T, GEN p} \fun{GEN}{FqM_FqC_mul}{GEN a, GEN b, GEN T, GEN p} \fun{GEN}{FqM_deplin}{GEN x, GEN T, GEN p} returns a nontrivial kernel vector, or \kbd{NULL} if none exist. \fun{GEN}{FqM_det}{GEN x, GEN T, GEN p} as \kbd{det} \fun{GEN}{FqM_gauss}{GEN a, GEN b, GEN T, GEN p} as \kbd{gauss}, where $b$ is a \kbd{FqM}. \fun{GEN}{FqM_image}{GEN x, GEN T, GEN p} as \kbd{image} \fun{GEN}{FqM_indexrank}{GEN x, GEN T, GEN p} as \kbd{indexrank} \fun{GEN}{FqM_inv}{GEN x, GEN T, GEN p} returns the inverse of \kbd{x}, or \kbd{NULL} if \kbd{x} is not invertible. \fun{GEN}{FqM_invimage}{GEN a, GEN b, GEN T, GEN p} as \kbd{invimage} \fun{GEN}{FqM_ker}{GEN x, GEN T, GEN p} as \kbd{ker} \fun{GEN}{FqM_mul}{GEN a, GEN b, GEN T, GEN p} \fun{long}{FqM_rank}{GEN x, GEN T, GEN p} as \kbd{rank} \fun{GEN}{FqM_suppl}{GEN x, GEN T, GEN p} as \kbd{suppl} \subsec{\kbd{Flc} / \kbd{Flv}, \kbd{Flm}} See \kbd{FpV}, \kbd{FpM} operations. \fun{GEN}{Flv_copy}{GEN x} returns a copy of \kbd{x}. \fun{GEN}{Flv_center}{GEN z, ulong p, ulong ps2} \fun{GEN}{random_Flv}{long n, ulong p} returns a random \kbd{Flv} with $n$ components. \fun{GEN}{Flm_copy}{GEN x} returns a copy of \kbd{x}. \fun{GEN}{matid_Flm}{long n} returns an \kbd{Flm} which is an $n \times n$ identity matrix. \fun{GEN}{scalar_Flm}{long s, long n} returns an \kbd{Flm} which is $s$ times the $n \times n$ identity matrix. \fun{GEN}{Flm_center}{GEN z, ulong p, ulong ps2} \fun{GEN}{Flm_Fl_add}{GEN x, ulong y, ulong p} returns $x + y*\text{Id}$ ($x$ must be square). \fun{GEN}{Flm_Fl_sub}{GEN x, ulong y, ulong p} returns $x - y*\text{Id}$ ($x$ must be square). \fun{GEN}{Flm_Flc_mul}{GEN x, GEN y, ulong p} multiplies \kbd{x} and \kbd{y} (assumed to have compatible dimensions). \fun{GEN}{Flm_Flc_mul_pre}{GEN x, GEN y, ulong p, ulong pi} multiplies \kbd{x} and \kbd{y} (assumed to have compatible dimensions), assuming \var{pi} is the pseudoinverse of $p$, or $0$ in which case we assume \kbd{SMALL\_ULONG}$(p)$. \fun{GEN}{Flc_Flv_mul}{GEN x, GEN y, ulong p} multiplies the column vector $x$ by the row vector $y$. The result is a matrix. \fun{GEN}{Flm_Flc_mul_pre_Flx}{GEN x, GEN y, ulong p, ulong pi, long sv} return \kbd{Flv\_to\_Flx(Flm\_Flc\_mul\_pre(x, y, p, pi), sv)}. \fun{GEN}{Flm_Fl_mul}{GEN x, ulong y, ulong p} multiplies the \kbd{Flm} \kbd{x} by \kbd{y}. \fun{GEN}{Flm_Fl_mul_pre}{GEN x, ulong y, ulong p, ulong pi} multiplies the \kbd{Flm} \kbd{x} by \kbd{y} assuming \var{pi} is the pseudoinverse of $p$, or $0$ in which case we assume $p < B^{1/2}$ is small. \fun{GEN}{Flm_neg}{GEN x, ulong p} negates the \kbd{Flm} \kbd{x}. \fun{void}{Flm_Fl_mul_inplace}{GEN x, ulong y, ulong p} replaces the \kbd{Flm} \kbd{x} by $\kbd{x}*\kbd{y}$. \fun{GEN}{Flv_Fl_mul}{GEN x, ulong y, ulong p} multiplies the \kbd{Flv} \kbd{x} by \kbd{y}. \fun{void}{Flv_Fl_mul_inplace}{GEN x, ulong y, ulong p} replaces the \kbd{Flc} \kbd{x} by $\kbd{x}*\kbd{y}$. \fun{void}{Flv_Fl_mul_part_inplace}{GEN x, ulong y, ulong p, long l} multiplies $x[1..l]$ by $y$ modulo $p$. In place. \fun{GEN}{Flv_Fl_div}{GEN x, ulong y, ulong p} divides the \kbd{Flv} \kbd{x} by \kbd{y}. \fun{void}{Flv_Fl_div_inplace}{GEN x, ulong y, ulong p} replaces the \kbd{Flv} \kbd{x} by $\kbd{x}/\kbd{y}$. \fun{void}{Flc_lincomb1_inplace}{GEN X, GEN Y, ulong v, ulong q} sets $X\leftarrow X + vY$, where $X,Y$ are \kbd{Flc}. Memory efficient (e.g. no-op if $v = 0$), and gerepile-safe. \fun{GEN}{Flv_add}{GEN x, GEN y, ulong p} adds two \kbd{Flv}. \fun{void}{Flv_add_inplace}{GEN x, GEN y, ulong p} replaces $x$ by $x+y$. \fun{GEN}{Flv_neg}{GEN x, ulong p} returns $-x$. \fun{void}{Flv_neg_inplace}{GEN x, ulong p} replaces $x$ by $-x$. \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_dotproduct_pre}{GEN x, GEN y, ulong p, ulong pi} returns the scalar product of \kbd{x} and \kbd{y} assuming \var{pi} is the pseudoinverse of $p$, or $0$ in which case we assume \kbd{SMALL\_ULONG}$(p)$. \fun{GEN}{Flv_factorback}{GEN L, GEN e, ulong p} given an \kbd{Flv} $L$ and a \kbd{zv} $e$ of the same length, return $\prod_i L_i^{e_i}$ modulo $p$. \fun{ulong}{Flv_sum}{GEN x, ulong p} returns the sum of the components of $x$. \fun{ulong}{Flv_prod}{GEN x, ulong p} returns the product of the components of $x$. \fun{ulong}{Flv_prod_pre}{GEN x, ulong p, ulong pi} as \kbd{Flv\_prod} assuming \var{pi} is the pseudoinverse of $p$. \fun{GEN}{Flv_inv}{GEN x, ulong p} returns the vector of inverses of the elements of $x$ (as a \kbd{Flv}). Use Montgomery's trick. \fun{void}{Flv_inv_inplace}{GEN x, ulong p} in place variant of \kbd{Flv\_inv}. \fun{GEN}{Flv_inv_pre}{GEN x, ulong p, ulong pi} as \kbd{Flv\_inv} assuming \var{pi} is the pseudoinverse of $p$. \fun{void}{Flv_inv_pre_inplace}{GEN x, ulong p, ulong pi} in place variant of \kbd{Flv\_inv}. \fun{GEN}{Flc_FpV_mul}{GEN x, GEN y, GEN p} multiplies $x$ (seen as a column vector) by $y$ (seen as a row vector, assumed to have compatible dimensions) to obtain an \kbd{Flm}. \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}{Flm_row}{GEN A, long x0} return $A[i,]$, the $i$-th row of the \kbd{Flm} $A$. \fun{GEN}{Flm_add}{GEN x, GEN y, ulong p} adds \kbd{x} and \kbd{y} (assumed to have compatible dimensions). \fun{GEN}{Flm_sub}{GEN x, GEN y, ulong p} subtracts \kbd{x} and \kbd{y} (assumed to have compatible dimensions). \fun{GEN}{Flm_mul}{GEN x, GEN y, ulong p} multiplies \kbd{x} and \kbd{y} (assumed to have compatible dimensions). \fun{GEN}{Flm_mul_pre}{GEN x, GEN y, ulong p, ulong pi} multiplies \kbd{x} and \kbd{y} (assumed to have compatible dimensions), assuming \var{pi} is the pseudoinverse of $p$, or $0$ in which case we assume \kbd{SMALL\_ULONG}$(p)$. \fun{GEN}{Flm_sqr}{GEN x, ulong p} squares \kbd{x} (assumed to be square). \fun{GEN}{Flm_powers}{GEN x, ulong n, ulong p} returns $[\kbd{x}^0, \dots, \kbd{x}^\kbd{n}]$ as a \typ{VEC} of \kbd{Flm}s. \fun{GEN}{Flm_powu}{GEN x, ulong n, ulong p} computes $x^n$ where $x$ is a square \kbd{Flm}. \fun{GEN}{Flm_charpoly}{GEN x, ulong p} return the characteristic polynomial of the square \kbd{Flm} $x$, as a \kbd{Flx}. \fun{GEN}{Flm_deplin}{GEN x, ulong p} \fun{ulong}{Flm_det}{GEN x, ulong p} \fun{ulong}{Flm_det_sp}{GEN x, ulong p}, as \kbd{Flm\_det}, in place (destroys~\kbd{x}). \fun{GEN}{Flm_gauss}{GEN a, GEN b, ulong p} as \kbd{gauss}, where $b$ is a \kbd{Flm}. \fun{GEN}{Flm_Flc_gauss}{GEN a, GEN b, ulong p} as \kbd{gauss}, where $b$ is a \kbd{Flc}. \fun{GEN}{Flm_indexrank}{GEN x, ulong p} \fun{GEN}{Flm_inv}{GEN x, ulong p} \fun{GEN}{Flm_adjoint}{GEN x, ulong p} as \kbd{matadjoint}. \fun{GEN}{Flm_Flc_invimage}{GEN A, GEN y, ulong p} given an \kbd{Flm} $A$ and an \kbd{Flc} $y$, returns an $x$ such that $Ax = y$, or \kbd{NULL} if no such vector exist. \fun{GEN}{Flm_invimage}{GEN A, GEN y, ulong p} given two \kbd{Flm} $A$ and $y$, returns $x$ such that $Ax = y$, or \kbd{NULL} if no such matrix exist. \fun{GEN}{Flm_ker}{GEN x, ulong p} \fun{GEN}{Flm_ker_sp}{GEN x, ulong p, long deplin}, as \kbd{Flm\_ker} (if \kbd{deplin=0}) or \kbd{Flm\_deplin} (if \kbd{deplin=1}) , in place (destroys~\kbd{x}). \fun{long}{Flm_rank}{GEN x, ulong p} \fun{long}{Flm_suppl}{GEN x, ulong p} \fun{GEN}{Flm_image}{GEN x, ulong p} \fun{GEN}{Flm_intersect}{GEN x, GEN y, ulong p} \fun{GEN}{Flm_intersect_i}{GEN x, GEN y, GEN p} internal variant of \kbd{Flm\_intersect} but the result is only a generating set, not necessarily an $\F_p$-basis. It \emph{is} a basis if both $x$ and $y$ have independent columns. It is not \kbd{gerepile}-clean either, but suitable for \kbd{gerepileupto}. \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{int}{F2v_equal0}{GEN x} returns $1$ if all entries are $0$, and return $0$ otherwise. \fun{void}{F2v_flip}{GEN x, long i} adds $1$ to the coefficient $i\ge 1$ of $x$. \fun{void}{F2v_set}{GEN x, long i} sets the coefficient $i\ge 1$ of $x$ to $1$. \fun{void}{F2v_copy}{GEN x} returns a copy of $x$. \fun{GEN}{F2v_slice}{GEN x, long a, long b} returns the \kbd{F2v} with entries $x[a]$, \dots, $x[b]$. Assumes $a \leq b$. \fun{ulong}{F2m_coeff}{GEN x, long i, long j} returns the coefficient $(i,j)$ of $x$. \fun{void}{F2m_clear}{GEN x, long i, long j} sets the coefficient $(i,j)$ of $x$ to $0$. \fun{void}{F2m_flip}{GEN x, long i, long j} adds $1$ to the coefficient $(i,j)$ of $x$. \fun{void}{F2m_set}{GEN x, long i, long j} sets the coefficient $(i,j)$ of $x$ to $1$. \fun{GEN}{F2m_copy}{GEN x} returns a copy of $x$. \fun{GEN}{F2m_transpose}{GEN x} returns the transpose of $x$. \fun{GEN}{F2m_row}{GEN x, long j} returns the \kbd{F2v} which corresponds to the $j$-th row of the \kbd{F2m} $x$. \fun{GEN}{F2m_rowslice}{GEN x, long a, long b} returns the \kbd{F2m} built from the $a$-th to $b$-th rows of the \kbd{F2m} $x$. Assumes $a \leq b$. \fun{GEN}{F2m_F2c_mul}{GEN x, GEN y} multiplies \kbd{x} and \kbd{y} (assumed to have compatible dimensions). \fun{GEN}{F2m_image}{GEN x} gives a subset of the columns of $x$ that generate the image of $x$. \fun{GEN}{F2m_invimage}{GEN A, GEN B} \fun{GEN}{F2m_F2c_invimage}{GEN A, GEN y} \fun{GEN}{F2m_gauss}{GEN a, GEN b} as \kbd{gauss}, where $b$ is a \kbd{F2m}. \fun{GEN}{F2m_F2c_gauss}{GEN a, GEN b} as \kbd{gauss}, where $b$ is a \kbd{F2c}. \fun{GEN}{F2m_indexrank}{GEN x} $x$ being a matrix of rank $r$, returns a vector with two \typ{VECSMALL} components $y$ and $z$ of length $r$ giving a list of rows and columns respectively (starting from 1) such that the extracted matrix obtained from these two vectors using \kbd{vecextract}$(x,y,z)$ is invertible. \fun{GEN}{F2m_mul}{GEN x, GEN y} multiplies \kbd{x} and \kbd{y} (assumed to have compatible dimensions). \fun{GEN}{F2m_powu}{GEN x, ulong n} computes $x^n$ where $x$ is a square \kbd{F2m}. \fun{long}{F2m_rank}{GEN x} as \kbd{rank}. \fun{long}{F2m_suppl}{GEN x} as \kbd{suppl}. \fun{GEN}{matid_F2m}{long n} returns an \kbd{F2m} which is an $n \times n$ identity matrix. \fun{GEN}{zero_F2v}{long n} creates a \kbd{F2v} with \kbd{n} components set to $0$. \fun{GEN}{const_F2v}{long n} creates a \kbd{F2v} with \kbd{n} components set to $1$. \fun{GEN}{F2v_ei}{long n, long i} creates a \kbd{F2v} with \kbd{n} components set to $0$, but for the $i$-th one, which is set to $1$ ($i$-th vector in the canonical basis). \fun{GEN}{zero_F2m}{long m, long n} creates a \kbd{Flm} with \kbd{m} x \kbd{n} components set to $0$. Note that the result allocates a \emph{single} column, so modifying an entry in one column modifies it in all columns. \fun{GEN}{zero_F2m_copy}{long m, long n} creates a \kbd{F2m} with \kbd{m} x \kbd{n} components set to $0$. \fun{GEN}{F2v_to_Flv}{GEN x} \fun{GEN}{F2c_to_ZC}{GEN x} \fun{GEN}{ZV_to_F2v}{GEN x} \fun{GEN}{RgV_to_F2v}{GEN x} \fun{GEN}{F2m_to_Flm}{GEN x} \fun{GEN}{F2m_to_ZM}{GEN x} \fun{GEN}{Flv_to_F2v}{GEN x} \fun{GEN}{Flm_to_F2m}{GEN x} \fun{GEN}{ZM_to_F2m}{GEN x} \fun{GEN}{RgM_to_F2m}{GEN x} \fun{void}{F2v_add_inplace}{GEN x, GEN y} replaces $x$ by $x+y$. It is allowed for $y$ to be shorter than $x$. \fun{void}{F2v_and_inplace}{GEN x, GEN y} replaces $x$ by the term-by term product of $x$ and $y$ (which is the logical \kbd{and}). It is allowed for $y$ to be shorter than $x$. \fun{void}{F2v_negimply_inplace}{GEN x, GEN y} replaces $x$ by the term-by term logical \kbd{and not} of $x$ and $y$. It is allowed for $y$ to be shorter than $x$. \fun{void}{F2v_or_inplace}{GEN x, GEN y} replaces $x$ by the term-by term logical \kbd{or} of $x$ and $y$. It is allowed for $y$ to be shorter than $x$. \fun{int}{F2v_subset}{GEN x, GEN y} return $1$ if the set of indices of non-zero components of $y$ is a subset of the set of indices of non-zero components of $x$, $0$ otherwise. \fun{ulong}{F2v_hamming}{GEN x} returns the Hamming weight of \kbd{x}, that is the number of nonzero entries. \fun{ulong}{F2m_det}{GEN x} \fun{ulong}{F2m_det_sp}{GEN x}, as \kbd{F2m\_det}, in place (destroys~\kbd{x}). \fun{GEN}{F2m_deplin}{GEN x} \fun{ulong}{F2v_dotproduct}{GEN x, GEN y} returns the scalar product of \kbd{x} and \kbd{y} \fun{GEN}{F2m_inv}{GEN x} \fun{GEN}{F2m_ker}{GEN x} \fun{GEN}{F2m_ker_sp}{GEN x, long deplin}, as \kbd{F2m\_ker} (if \kbd{deplin=0}) or \kbd{F2m\_deplin} (if \kbd{deplin=1}), in place (destroys~\kbd{x}). \subsec{\kbd{F3c} / \kbd{F3v}, \kbd{F3m}} An \kbd{F3v}~\kbd{v} is a \typ{VECSMALL} representing a vector over $\F_3$. Specifically \kbd{z[0]} is the usual codeword, \kbd{z[1]} is the number of components of $v$ and the coefficients are given by pair of adjacent bits of remaining words by increasing indices, with the coding $00\mapsto 0, 01\mapsto 1, 10\mapsto 2$ and $11$ is undefined. \fun{ulong}{F3v_coeff}{GEN x, long i} returns the coefficient $i\ge 1$ of $x$. \fun{void}{F3v_clear}{GEN x, long i} sets the coefficient $i\ge 1$ of $x$ to $0$. \fun{void}{F3v_set}{GEN x, long i, ulong n} sets the coefficient $i\ge 1$ of $x$ to $n<3$, \fun{ulong}{F3m_coeff}{GEN x, long i, long j} returns the coefficient $(i,j)$ of $x$. \fun{void}{F3m_set}{GEN x, long i, long j, ulong n} sets the coefficient $(i,j)$ of $x$ to $n<3$. \fun{GEN}{F3m_copy}{GEN x} returns a copy of $x$. \fun{GEN}{F3m_transpose}{GEN x} returns the transpose of $x$. \fun{GEN}{F3m_row}{GEN x, long j} returns the \kbd{F3v} which corresponds to the $j$-th row of the \kbd{F3m} $x$. \fun{GEN}{F3m_ker}{GEN x} \fun{GEN}{F3m_ker_sp}{GEN x, long deplin}, as \kbd{F3m\_ker} (if \kbd{deplin=0}) or \kbd{F2m\_deplin} (if \kbd{deplin=1}), in place (destroys~\kbd{x}). \fun{GEN}{F3m_mul}{GEN x, GEN y} multiplies \kbd{x} and \kbd{y} (assumed to have compatible dimensions). \fun{GEN}{zero_F3v}{long n} creates a \kbd{F3v} with \kbd{n} components set to $0$. \fun{GEN}{zero_F3m_copy}{long m, long n} creates a \kbd{F3m} with \kbd{m} x \kbd{n} components set to $0$. \fun{GEN}{F3v_to_Flv}{GEN x} \fun{GEN}{ZV_to_F3v}{GEN x} \fun{GEN}{RgV_to_F3v}{GEN x} \fun{GEN}{F3c_to_ZC}{GEN x} \fun{GEN}{F3m_to_Flm}{GEN x} \fun{GEN}{F3m_to_ZM}{GEN x} \fun{GEN}{Flv_to_F3v}{GEN x} \fun{GEN}{Flm_to_F3m}{GEN x} \fun{GEN}{ZM_to_F3m}{GEN x} \fun{GEN}{RgM_to_F3m}{GEN x} \subsec{\kbd{FlxqV}, \kbd{FlxqC}, \kbd{FlxqM}} See \kbd{FqV}, \kbd{FqC}, \kbd{FqM} operations. \fun{GEN}{FlxqV_dotproduct}{GEN x, GEN y, GEN T, ulong p} as \kbd{FpV\_dotproduct}. \fun{GEN}{FlxqV_dotproduct_pre}{GEN x, GEN y, GEN T, ulong p, ulong pi} where \var{pi} is the pseudoinverse of $p$, or $0$ in which case we assume \kbd{SMALL\_ULONG}$(p)$. \fun{GEN}{FlxM_Flx_add_shallow}{GEN x, GEN y, ulong p} as \kbd{RgM\_Rg\_add\_shallow}. \fun{GEN}{FlxqC_Flxq_mul}{GEN x, GEN y, GEN T, ulong p} \fun{GEN}{FlxqM_Flxq_mul}{GEN x, GEN y, GEN T, ulong p} \fun{GEN}{FlxqM_FlxqC_gauss}{GEN a, GEN b, GEN T, ulong p} \fun{GEN}{FlxqM_FlxqC_invimage}{GEN a, GEN b, GEN T, ulong p} \fun{GEN}{FlxqM_FlxqC_mul}{GEN a, GEN b, GEN T, ulong p} \fun{GEN}{FlxqM_deplin}{GEN x, GEN T, ulong p} \fun{GEN}{FlxqM_det}{GEN x, GEN T, ulong p} \fun{GEN}{FlxqM_gauss}{GEN a, GEN b, GEN T, ulong p} \fun{GEN}{FlxqM_image}{GEN x, GEN T, ulong p} \fun{GEN}{FlxqM_indexrank}{GEN x, GEN T, ulong p} \fun{GEN}{FlxqM_inv}{GEN x, GEN T, ulong p} \fun{GEN}{FlxqM_invimage}{GEN a, GEN b, GEN T, ulong p} \fun{GEN}{FlxqM_ker}{GEN x, GEN T, ulong p} \fun{GEN}{FlxqM_mul}{GEN a, GEN b, GEN T, ulong p} \fun{long}{FlxqM_rank}{GEN x, GEN T, ulong p} \fun{GEN}{FlxqM_suppl}{GEN x, GEN T, ulong p} \fun{GEN}{matid_FlxqM}{long n, 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}, preferably belonging to $[0, \kbd{p}-1]$; an \kbd{FpX} is a \typ{POL} in a fixed variable whose coefficients are \kbd{Fp} objects. Unless mentioned otherwise, all outputs in this section are \kbd{FpX}s. All operations are understood to take place in $(\Z/\kbd{p}\Z)[X]$. \subsubsec{Conversions} In what follows \kbd{p} is always a \typ{INT}, not necessarily prime. \fun{int}{RgX_is_FpX}{GEN z, GEN *p}, \kbd{z} a \typ{POL}, checks if it can be mapped to a \kbd{FpX}, by checking \kbd{Rg\_is\_Fp} coefficientwise. \fun{GEN}{RgX_to_FpX}{GEN z, GEN p}, \kbd{z} a \typ{POL}, returns the \kbd{FpX} obtained by applying \kbd{Rg\_to\_Fp} coefficientwise. \fun{GEN}{FpX_red}{GEN z, GEN p}, \kbd{z} a \kbd{ZX}, returns \kbd{lift(z * Mod(1,p))}, normalized. \fun{GEN}{FpXV_red}{GEN z, GEN p}, \kbd{z} a \typ{VEC} of \kbd{ZX}. Applies \kbd{FpX\_red} componentwise and returns the result (and we obtain a vector of \kbd{FpX}s). \fun{GEN}{FpXT_red}{GEN z, GEN p}, \kbd{z} a tree of \kbd{ZX}. Applies \kbd{FpX\_red} to each leaf and returns the result (and we obtain a tree of \kbd{FpX}s). \subsubsec{Basic operations} In what follows \kbd{p} is always a \typ{INT}, not necessarily prime. \noindent Now, except for \kbd{p}, the operands and outputs are all \kbd{FpX} objects. Results are undefined on other inputs. \fun{GEN}{FpX_add}{GEN x,GEN y, GEN p} adds \kbd{x} and \kbd{y}. \fun{GEN}{FpX_neg}{GEN x,GEN p} returns $-\kbd{x}$, the components are between $0$ and $p$ if this is the case for the components of $x$. \fun{GEN}{FpX_renormalize}{GEN x, long l}, as \kbd{normalizepol}, where $\kbd{l} = \kbd{lg(x)}$, in place. \fun{GEN}{FpX_sub}{GEN x,GEN y,GEN p} returns $x-y$. \fun{GEN}{FpX_halve}{GEN x, GEN p} returns $z$ such that $2\*z = x$ modulo $p$ assuming such $z$ exists. \fun{GEN}{FpX_mul}{GEN x,GEN y,GEN p} returns $x\*y$. \fun{GEN}{FpX_mulspec}{GEN a, GEN b, GEN p, long na, long nb} see \kbd{ZX\_mulspec} \fun{GEN}{FpX_sqr}{GEN x,GEN p} returns $\kbd{x}^2$. \fun{GEN}{FpX_powu}{GEN x, ulong n, GEN p} returns $x^n$. \fun{GEN}{FpX_convol}{GEN x, GEN y, GEN p} return the-term by-term product of $x$ and $y$. \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 nonzero \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_integ}{GEN x, GEN p} returns the primitive of \kbd{x} whose constant term is $0$. \fun{GEN}{FpX_digits}{GEN x, GEN B, GEN p} returns a vector of \kbd{FpX} $[c_0,\ldots,c_n]$ of degree less than the degree of $B$ and such that $x=\sum_{i=0}^{n}{c_i\*B^i}$. \fun{GEN}{FpXV_FpX_fromdigits}{GEN v, GEN B, GEN p} where $v=[c_0,\ldots,c_n]$ is a vector of \kbd{FpX}, returns $\sum_{i=0}^{n}{c_i\*B^i}$. \fun{GEN}{FpX_translate}{GEN P, GEN c, GEN p} let $c$ be an \kbd{Fp} and let $P$ be an \kbd{FpX}; returns the translated \kbd{FpX} of $P(X+c)$. \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_halfgcd_all}{GEN x, GEN y, GEN p, GEN *pt_a, GEN *pt_b} as \kbd{FpX\_halfgcd}, in addition, if \kbd{pt\_a} (resp. \kbd{pt\_b}) is not \kbd{NULL}, \kbd{*pt\_a} (resp. \kbd{*pt\_b}) is set to \kbd{a} (resp. \kbd{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 \kbd{NULL}, \kbd{*u} 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 $]-p/2, p[$ and that \kbd{pov2} is \kbd{shifti(p,-1)}. \fun{GEN}{FpX_center_i}{GEN z, GEN p, GEN pov2} internal variant of \tet{FpX_center}, not \kbd{gerepile}-safe. \fun{GEN}{FpX_Frobenius}{GEN T, GEN p} returns $X^{p}\pmod{T(X)}$. \fun{GEN}{FpX_matFrobenius}{GEN T, GEN p} returns the matrix of the Frobenius automorphism $x\mapsto x^p$ over the power basis of $\F_p[X]/(T)$. \subsubsec{Mixed operations} The following functions implement arithmetic operations between \kbd{FpX} and \kbd{Fp} operands, the result being of type \kbd{FpX}. The integer \kbd{p} need not be prime. \fun{GEN}{Z_to_FpX}{GEN x, GEN p, long v} converts a \typ{INT} to a scalar polynomial in variable $v$, reduced modulo $p$. \fun{GEN}{FpX_Fp_add}{GEN y, GEN x, GEN p} add the \kbd{Fp}~\kbd{x} to the \kbd{FpX}~\kbd{y}. \fun{GEN}{FpX_Fp_add_shallow}{GEN y, GEN x, GEN p} add the \kbd{Fp}~\kbd{x} to the \kbd{FpX}~\kbd{y}, using a shallow copy (result not suitable for \kbd{gerepileupto}) \fun{GEN}{FpX_Fp_sub}{GEN y, GEN x, GEN p} subtract the \kbd{Fp}~\kbd{x} from the \kbd{FpX}~\kbd{y}. \fun{GEN}{FpX_Fp_sub_shallow}{GEN y, GEN x, GEN p} subtract the \kbd{Fp}~\kbd{x} from the \kbd{FpX}~\kbd{y}, using a shallow copy (result not suitable for \kbd{gerepileupto}) \fun{GEN}{Fp_FpX_sub}{GEN x,GEN y,GEN p} returns $x - y$, where $x$ is a \typ{INT} and $y$ an \kbd{FpX}. \fun{GEN}{FpX_Fp_mul}{GEN x, GEN y, GEN p} multiplies the \kbd{FpX}~\kbd{x} by the \kbd{Fp}~\kbd{y}. \fun{GEN}{FpX_Fp_mulspec}{GEN x, GEN y, GEN p, long lx} see \kbd{ZX\_mulspec} \fun{GEN}{FpX_mulu}{GEN x, ulong y, GEN p} multiplies the \kbd{FpX}~\kbd{x} by \kbd{y}. \fun{GEN}{FpX_Fp_mul_to_monic}{GEN y,GEN x,GEN p} returns $y\*x$ assuming the result is monic of the same degree as $y$ (in particular $x\neq 0$). \fun{GEN}{FpX_Fp_div}{GEN x, GEN y, GEN p} divides the \kbd{FpX}~\kbd{x} by the \kbd{Fp}~\kbd{y}. \fun{GEN}{FpX_divu}{GEN x, ulong y, GEN p} divides the \kbd{FpX}~\kbd{x} by \kbd{y}. \subsubsec{Miscellaneous operations} \fun{GEN}{FpX_normalize}{GEN z, GEN p} divides the \kbd{FpX}~\kbd{z} by its leading coefficient. If the latter is~$1$, \kbd{z} itself is returned, not a copy. If not, the inverse remains uncollected on the stack. \fun{GEN}{FpX_invBarrett}{GEN T, GEN p}, returns the Barrett inverse $M$ of $T$ defined by $M(x)\*x^n\*T(1/x)\equiv 1\pmod{x^{n-1}}$ where $n$ is the degree of $T$. \fun{GEN}{FpX_rescale}{GEN P, GEN h, GEN p} returns $h^{\deg(P)} P(x/h)$. \kbd{P} is an \kbd{FpX} and \kbd{h} is a nonzero \kbd{Fp} (the routine would work with any nonzero \typ{INT} but is not efficient in this case). Neither memory-clean nor suitable for \kbd{gerepileupto}. \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}{FpX_FpV_multieval}{GEN P, GEN v, GEN p} returns the vector $[P(v[1]),\ldots,P(v[n])]$ as a \kbd{FpV}. \fun{GEN}{FpX_dotproduct}{GEN x, GEN y, GEN p} return the scalar product $\sum_{i\geq 0} x_i\*y_i$ of the coefficients of $x$ and $y$. \fun{GEN}{FpXV_FpC_mul}{GEN V, GEN W, GEN p} multiplies a nonempty row 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}{FpXV_composedsum}{GEN V, GEN p}, \kbd{V} being a vector of \kbd{FpX}, returns their composed sum, see \kbd{FpX\_composedsum}. \fun{GEN}{FpXV_factorback}{GEN L, GEN e, GEN p, long v} returns $\prod_i L_i^{e_i}$ where $L$ is a vector of \kbd{FpX}s in the variable \kbd{v} and $e$ a vector of non-negative \typ{INT}s or a \typ{VECSMALL}. \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, long v} 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{GEN}{FpV_FpM_polint}{GEN x, GEN V, GEN p, long v} equivalent (but faster) to applying \kbd{FpV\_polint(x,$\ldots$)} to all the elements of the vector $V$ (thus, returns a \kbd{FpXV}). \fun{GEN}{FpX_FpXV_multirem}{GEN A, GEN P, GEN p} given a \kbd{FpX} $A$ and a vector $P$ of pairwise coprime \kbd{FpX} of length $n\ge 1$, return a vector $B$ of the same length such that $B[i] = A\pmod{P[i]}$ and $B[i]$ of minimal degree for all $1\leq i\leq n$. \fun{GEN}{FpXV_chinese}{GEN A, GEN P, GEN p, GEN *pM} let $P$ be a vector of pairwise coprime \kbd{FpX}, let $A$ be a vector of \kbd{FpX} of the same length $n\ge 1$ and let $M$ be the product of the elements of $P$. Returns a \kbd{FpX} of minimal degree congruent to $A[i]$ mod $P[i]$ for all $1\leq i\leq n$. If \kbd{pM} is not \kbd{NULL}, set \kbd{*pM} to $M$. \fun{GEN}{FpV_invVandermonde}{GEN L, GEN d, GEN p} $L$ being a \kbd{FpV} of length $n$, return the inverse $M$ of the Vandermonde matrix attached to the elements of $L$, eventually multiplied by \kbd{d} if it is not \kbd{NULL}. If $A$ is a \kbd{FpV} and $B=M\*A$, then the polynomial $P=\sum_{i=1}^n B[i]\*X^{i-1}$ verifies $P(L[i])=d\*A[i]$ for $1 \leq i \leq n$. \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. The $0$ polynomial is not totally split. \fun{long}{FpX_ispower}{GEN f, ulong k, GEN p, GEN *pt} return $1$ if the \kbd{FpX} $f$ is a $k$-th power, $0$ otherwise. If \kbd{pt} is not \kbd{NULL}, set it to $g$ such that $g^k = f$. \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{GEN}{FpX_factor_squarefree}{GEN f, GEN p} returns the squarefree factorization of $f$ modulo $p$. This is a vector $[u_1,\dots,u_k]$ of squarefree and pairwise coprime \kbd{FpX} such that $u_k \neq 1$ and $f = \prod u_i^i$. The other~$u_i$ may equal~$1$. Shallow function. \fun{GEN}{FpX_ddf}{GEN f, GEN p} assuming that $f$ is squarefree, returns the distinct degree factorization of $f$ modulo $p$. The returned value \kbd{v} is a \typ{VEC} with two components: \kbd{F=v[1]} is a vector of (\kbd{FpX}) factors, and \kbd{E=v[2]} is a \typ{VECSMALL}, such that $f$ is equal to the product of the \kbd{F[i]} and each \kbd{F[i]} is a product of irreducible factors of degree \kbd{E[i]}. \fun{long}{FpX_ddf_degree}{GEN f, GEN XP, GEN p} assuming that $f$ is squarefree and that all its factors have the same degree, return the common degree, where \kbd{XP} is \kbd{FpX\_Frobenius(f, p)}. \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_nbfact_Frobenius}{GEN f, GEN XP, GEN p}, as \kbd{FpX\_nbfact(f, p)} but faster, where \kbd{XP} is \kbd{FpX\_Frobenius(f, p)}. \fun{GEN}{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_oneroot_split}{GEN f, GEN p} as \kbd{FpX\_oneroot}. Faster when $f$ is close to be totally split. \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}{FpX_roots_mult}{GEN f, long n, GEN p} returns the roots in \kbd{\Z/p\Z} with multiplicity at least $n$ of the \kbd{FpX}~\kbd{f} (without multiplicity, as a vector of \kbd{Fp}s). Assumes that \kbd{p} is prime. \fun{GEN}{FpX_split_part}{GEN f, GEN p} returns the largest totally split squarefree factor of $f$. \fun{GEN}{FpX_factcyclo}{ulong n, GEN p, ulong m} returns the factors of the $n$-th cyclotomic polynomial over \kbd{Fp}. if $m=1$ returns a single factor. \fun{GEN}{random_FpX}{long d, long v, GEN p} returns a random \kbd{FpX} in variable \kbd{v}, of degree less than~\kbd{d}. \fun{GEN}{FpX_resultant}{GEN x, GEN y, GEN p} returns the resultant of \kbd{x} and \kbd{y}, both \kbd{FpX}. The result is a \typ{INT} belonging to $[0,p-1]$. \fun{GEN}{FpX_disc}{GEN x, GEN p} returns the discriminant of the \kbd{FpX} \kbd{x}. The result is a \typ{INT} belonging to $[0,p-1]$. \fun{GEN}{FpX_FpXY_resultant}{GEN a, GEN b, GEN p}, \kbd{a} a \typ{POL} of \typ{INT}s (say in variable $X$), \kbd{b} a \typ{POL} (say in variable $X$) whose coefficients are either \typ{POL}s in $\Z[Y]$ or \typ{INT}s. Returns $\text{Res}_X(a, b)$ in $\F_p[Y]$ as an \kbd{FpY}. The function assumes that $X$ has lower priority than $Y$. \fun{ulong}{FpX_extresultant}{GEN a, GEN b, GEN p, GEN *ptU, GEN *ptV} given two \kbd{FpX} \kbd{a} and \kbd{b}, returns their resultant and sets Bezout coefficients (if the resultant is $0$, the latter are not set). Assumes that $p$ is prime. \fun{GEN}{FpX_composedprod}{GEN P, GEN Q, GEN p} if $P=a\prod_{i=1}^m(x-p_i)$ and $Q=b\prod_{j=1}^n(x-q_j)$ in some suitable algebraic extension, return $a^n\*b^m\prod_{i,j}(x-p_i\*q_j)$. \fun{GEN}{FpX_composedsum}{GEN P, GEN Q, GEN p} if $P=a\prod_{i=1}^m(x-p_i)$ and $Q=b\prod_{j=1}^n(x-q_j)$ in some suitable algebraic extension, return $a^n\*b^m\prod_{i,j}(x-(p_i+q_j))$. \fun{GEN}{FpX_Newton}{GEN x, long n, GEN p} return $\sum{i=0}^{n-1} \pi_i\*X^i$ where $\pi_i$ is the sum of the $i$th-power of the roots of $x$ in an algebraic closure. \fun{GEN}{FpX_fromNewton}{GEN x, GEN p} recover a polynomial from it s Newton sums given by the coefficients of $x$. This function assumes that $p$ and the accuracy of $x$ as a \kbd{FpXn} is larger than the degree of the solution. \fun{GEN}{FpX_Laplace}{GEN x, GEN p} return $\sum_{i=0}^{n-1} x_i\*i!\*X^i$. \fun{GEN}{FpX_invLaplace}{GEN x, GEN p} return $\sum_{i=0}^{n-1} x_i/{i!}\*X^i$. \subsec{\kbd{FpXQ}, \kbd{Fq}} Let \kbd{p} a \typ{INT} and \kbd{T} an \kbd{FpX} for \kbd{p}, both to be given in the function arguments; an \kbd{FpXQ} object is an \kbd{FpX} whose degree is strictly less than the degree of \kbd{T}. An \kbd{Fq} is either an \kbd{FpXQ} or an \kbd{Fp}. Both represent a class in $(\Z/\kbd{p}\Z)[X] / (T)$, in which all operations below take place. In addition, \kbd{Fq} routines also allow $\kbd{T} = \kbd{NULL}$, in which case no reduction mod \kbd{T} is performed on the result. For efficiency, the routines in this section may leave small unused objects behind on the stack (their output is still suitable for \kbd{gerepileupto}). Besides \kbd{T} and \kbd{p}, arguments are either \kbd{FpXQ} or \kbd{Fq} depending on the function name. (All \kbd{Fq} routines accept \kbd{FpXQ}s by definition, not the other way round.) \subsubsec{Preconditioned reduction} For faster reduction, the modulus $T$ can be replaced by an extended modulus in all \kbd{FpXQ}- and \kbd{Fq}-classes functions, and in \kbd{FpX\_rem} and \kbd{FpX\_divrem}. An extended modulus(\kbd{FpXT}, which is a tree whose leaves are \kbd{FpX})In current implementation, an extended modulus is either a plain modulus (an \kbd{FpX}) or a pair of polynomials, one being the plain modulus $T$ and the other being \tet{FpX_invBarret}$(T,p)$. \fun{GEN}{FpX_get_red}{GEN T, GEN p} returns the extended modulus \kbd{eT}. To write code that works both with plain and extended moduli, the following accessors are defined: \fun{GEN}{get_FpX_mod}{GEN eT} returns the underlying modulus $T$. \fun{GEN}{get_FpX_var}{GEN eT} returns the variable number \kbd{varn}$(T)$. \fun{GEN}{get_FpX_degree}{GEN eT} returns the degree \kbd{degpol}$(T)$. \subsubsec{Conversions} \fun{int}{ff_parse_Tp}{GEN Tp, GEN *T, GEN *p, long red} \kbd{Tp} is either a prime number $p$ or a \typ{VEC} with 2 entries $T$ (an irreducible polynomial mod $p$) and $p$ (a prime number). Sets \kbd{*p} and \kbd{*T} to the corresponding \kbd{GEN}s (\kbd{NULL} if undefined). If \kbd{red} is nonzero, normalize \kbd{*T} as an \kbd{FpX}; on the other hand, to initialize a $p$-adic function, set \kbd{red} to $0$ and \kbd{*T} is left as is and must be a \kbd{ZX} to start with. Return $1$ on success, and $0$ on failure. This helper routine is used by GP functions such as \kbd{factormod} where a single user argument defines a finite field. \typ{FFELT} is not supported. \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}), or a \typ{FFELT} $z$ with the same definition field as \kbd{*T} if \kbd{*T} is not \kbd{NULL} and is a \typ{FFELT}. 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}, if a \typ{FFELT} $z$ is found, $z$ 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}{Rg_to_Fq}{GEN z, GEN T, GEN p}, applies \kbd{Rg\_to\_Fp} if $T$ is \kbd{NULL} and \kbd{Rg\_to\_FpXQ} otherwise. \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{FqX} obtained by applying \kbd{Rg\_to\_Fq} coefficientwise. \fun{GEN}{Fq_to_FpXQ}{GEN z, GEN T, GEN p /*unused*/} if $z$ is a \typ{INT}, convert it to a constant polynomial in the variable of $T$, otherwise return $z$ (shallow function). \fun{GEN}{Fq_red}{GEN x, GEN T, GEN p}, \kbd{x} a \kbd{ZX} or \typ{INT}, reduce it to an \kbd{Fq} ($\kbd{T} = \kbd{NULL}$ is allowed iff \kbd{x} is a \typ{INT}). \fun{GEN}{FqX_red}{GEN x, GEN T, GEN p}, \kbd{x} a \typ{POL} whose coefficients are \kbd{ZX}s or \typ{INT}s, reduce them to \kbd{Fq}s. (If $\kbd{T} = \kbd{NULL}$, as \kbd{FpXX\_red(x, p)}.) \fun{GEN}{FqV_red}{GEN x, GEN T, GEN p}, \kbd{x} a vector of \kbd{ZX}s or \typ{INT}s, reduce them to \kbd{Fq}s. (If $\kbd{T} = \kbd{NULL}$, only reduce components mod \kbd{p} to \kbd{FpX}s or \kbd{Fp}s.) \fun{GEN}{FpXQ_red}{GEN x, GEN T,GEN p} \kbd{x} a \typ{POL} whose coefficients are \typ{INT}s, reduce them to \kbd{FpXQ}s. \subsec{\kbd{FpXQ}} \fun{GEN}{FpXQ_add}{GEN x, GEN y, GEN T,GEN p} \fun{GEN}{FpXQ_sub}{GEN x, GEN y, GEN T,GEN p} \fun{GEN}{FpXQ_mul}{GEN x, GEN y, GEN T,GEN p} \fun{GEN}{FpXQ_sqr}{GEN x, GEN T, GEN p} \fun{GEN}{FpXQ_div}{GEN x, GEN y, GEN T,GEN p} \fun{GEN}{FpXQ_inv}{GEN x, GEN T, GEN p} computes the inverse of \kbd{x} \fun{GEN}{FpXQ_invsafe}{GEN x,GEN T,GEN p}, as \kbd{FpXQ\_inv}, returning \kbd{NULL} if \kbd{x} is not invertible. \fun{GEN}{FpXQ_pow}{GEN x, GEN n, GEN T, GEN p} computes $\kbd{x}^\kbd{n}$. \fun{GEN}{FpXQ_powu}{GEN x, ulong n, GEN T, GEN p} computes $\kbd{x}^\kbd{n}$ for small $n$. In the following three functions the integer parameter \kbd{ord} can be given either as a positive \typ{INT} $N$, or as its factorization matrix $\var{faN}$, or as a pair $[N,\var{faN}]$. The parameter may be omitted by setting it to \kbd{NULL} (the value is then $p^d-1$, $d = \deg T$). \fun{GEN}{FpXQ_log}{GEN a, GEN g, GEN ord, GEN T, GEN p} Let \kbd{g} be of order dividing \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 undefined. Assumes that \kbd{T} is irreducible mod \kbd{p}. \fun{GEN}{Fp_FpXQ_log}{GEN a, GEN g, GEN ord, GEN T, GEN p} As \kbd{FpXQ\_log}, \kbd{a} being a \kbd{Fp}. \fun{GEN}{FpXQ_order}{GEN a, GEN ord, GEN T, GEN p} returns the order of the \kbd{FpXQ} \kbd{a}. Assume that \kbd{ord} is a multiple of the order of \kbd{a}. Assume that \kbd{T} is irreducible mod \kbd{p}. \fun{int}{FpXQ_issquare}{GEN x, GEN T, GEN p} returns $1$ if $x$ is a square and $0$ otherwise. Assumes that \kbd{T} is irreducible mod \kbd{p}. \fun{GEN}{FpXQ_sqrt}{GEN x, GEN T, GEN p} returns a square root of \kbd{x}. Return \kbd{NULL} if \kbd{x} is not a square. \fun{GEN}{FpXQ_sqrtn}{GEN x, GEN n, GEN T, GEN p, GEN *zn} Let $T$be irreducible mod $p$ and $q = p^{\deg T}$; returns \kbd{NULL} if $a$ is not an $n$-th power residue mod $p$. Otherwise, returns an $n$-th root of $a$; if \kbd{zn} is not \kbd{NULL} set it to a primitive $m$-th root of $1$ in $\F_q$, $m = \gcd(q-1,n)$ allowing to compute all $m$ solutions in $\F_q$ of the equation $x^n = a$. \subsec{\kbd{Fq}} \fun{GEN}{random_Fq}{GEN T, GEN p} returns a random \kbd{Fq} \fun{GEN}{Fq_add}{GEN x, GEN y, GEN T/*unused*/, GEN p} \fun{GEN}{Fq_sub}{GEN x, GEN y, GEN T/*unused*/, GEN p} \fun{GEN}{Fq_mul}{GEN x, GEN y, GEN T, GEN p} \fun{GEN}{Fq_Fp_mul}{GEN x, GEN y, GEN T, GEN p} multiplies the \kbd{Fq} $x$ by the \typ{INT} $y$. \fun{GEN}{Fq_mulu}{GEN x, ulong y, GEN T, GEN p} multiplies the \kbd{Fq} $x$ by the scalar $y$. \fun{GEN}{Fq_halve}{GEN x, GEN T, GEN p} returns $z$ such that $2\*z = x$ assuming such $z$ exists. \fun{GEN}{Fq_sqr}{GEN x, GEN T, GEN p} \fun{GEN}{Fq_neg}{GEN x, GEN T, GEN p} \fun{GEN}{Fq_neg_inv}{GEN x, GEN T, GEN p} computes $-\kbd{x}^{-1}$ \fun{GEN}{Fq_inv}{GEN x, GEN pol, GEN p} computes $\kbd{x}^{-1}$, raising an error if \kbd{x} is not invertible. \fun{GEN}{Fq_invsafe}{GEN x, GEN pol, GEN p} as \kbd{Fq\_inv}, but returns \kbd{NULL} if \kbd{x} is not invertible. \fun{GEN}{Fq_div}{GEN x, GEN y, GEN T, GEN p} \fun{GEN}{FqV_inv}{GEN x, GEN T, GEN p} $x$ being a vector of \kbd{Fq}s, return the vector of inverses of the $x[i]$. The routine uses Montgomery's trick, and involves a single inversion, plus $3(N-1)$ multiplications for $N$ entries. The routine is not stack-clean: $2N$ \kbd{FpXQ} are left on stack, besides the $N$ in the result. \fun{GEN}{FqV_factorback}{GEN L, GEN e, GEN T, GEN p} given an \kbd{FqV} $L$ and a \kbd{ZV} or \kbd{zv} $e$ of the same length, return $\prod_i L_i^{e_i}$ modulo $p$. \fun{GEN}{Fq_pow}{GEN x, GEN n, GEN pol, GEN p} returns $\kbd{x}^\kbd{n}$. \fun{GEN}{Fq_powu}{GEN x, ulong n, GEN pol, GEN p} returns $\kbd{x}^\kbd{n}$ for small $n$. \fun{GEN}{Fq_log}{GEN a, GEN g, GEN ord, GEN T, GEN p} as \tet{Fp_log} or \tet{FpXQ_log}. \fun{int}{Fq_issquare}{GEN x, GEN T, GEN p} returns $1$ if $x$ is a square and $0$ otherwise. Assumes that \kbd{T} is irreducible mod \kbd{p} and that $p$ is prime; $T = \kbd{NULL}$ is forbidden unless $x$ is an \kbd{Fp}. \fun{long}{Fq_ispower}{GEN x, GEN n, GEN T, GEN p} returns $1$ if $x$ is a $n$-th power and $0$ otherwise. Assumes that \kbd{T} is irreducible mod \kbd{p} and that $p$ is prime; $T = \kbd{NULL}$ is forbidden unless $x$ is an \kbd{Fp}. \fun{GEN}{Fq_sqrt}{GEN x, GEN T, GEN p} returns a square root of \kbd{x}. Return \kbd{NULL} if \kbd{x} is not a square. \fun{GEN}{Fq_sqrtn}{GEN a, GEN n, GEN T, GEN p, GEN *zn} as \tet{FpXQ_sqrtn}. \fun{GEN}{FpXQ_charpoly}{GEN x, GEN T, GEN p} returns the characteristic polynomial of \kbd{x} \fun{GEN}{FpXQ_minpoly}{GEN x, GEN T, GEN p} returns the minimal polynomial of \kbd{x} \fun{GEN}{FpXQ_norm}{GEN x, GEN T, GEN p} returns the norm of \kbd{x} \fun{GEN}{FpXQ_trace}{GEN x, GEN T, GEN p} returns the trace of \kbd{x} \fun{GEN}{FpXQ_conjvec}{GEN x, GEN T, GEN p} returns the vector of conjugates $[x,x^p,x^{p^2},\ldots,x^{p^{n-1}}]$ where $n$ is the degree of $T$. \fun{GEN}{gener_FpXQ}{GEN T, GEN p, GEN *po} returns a primitive root modulo $(T,p)$. $T$ is an \kbd{FpX} assumed to be irreducible modulo the prime $p$. If \kbd{po} is not \kbd{NULL} it is set to $[o,\var{fa}]$, where $o$ is the order of the multiplicative group of the finite field, and \var{fa} is its factorization. \fun{GEN}{gener_FpXQ_local}{GEN T, GEN p, GEN L}, \kbd{L} being a vector of primes dividing $p^{\deg T} - 1$, returns an element of $G:=\F_p[x]/(T)$ which is a generator of the $\ell$-Sylow of $G$ for every $\ell$ in \kbd{L}. It is not necessary, and in fact slightly inefficient, to include $\ell=2$, since 2 is treated separately in any case, i.e. the generator obtained is never a square if $p$ is odd. \fun{GEN}{gener_Fq_local}{GEN T, GEN p, GEN L} as \kbd{pgener\_Fp\_local(p, L)} if $T$ is \kbd{NULL}, or \kbd{gener\_FpXQ\_local} (otherwise). \fun{GEN}{FpXQ_powers}{GEN x, long n, GEN T, GEN p} returns $[\kbd{x}^0, \dots, \kbd{x}^\kbd{n}]$ as a \typ{VEC} of \kbd{FpXQ}s. \fun{GEN}{FpXQ_matrix_pow}{GEN x, long m, long n, GEN T, GEN p}, as \kbd{FpXQ\_powers}$(x, n-1, T, p)$, but returns the powers as a an $m\times n$ matrix. Usually, we have $m = n = \deg T$. \fun{GEN}{FpXQ_autpow}{GEN a, ulong n, GEN T, GEN p} computes $\sigma^n(X)$ assuming $a=\sigma(X)$ where $\sigma$ is an automorphism of the algebra $\F_p[X]/T(X)$. \fun{GEN}{FpXQ_autsum}{GEN a, ulong n, GEN T, GEN p} $a$ being a two-component vector, $\sigma$ being the automorphism defined by $\sigma(X)=a[1]\pmod{T(X)}$, returns the vector $[\sigma^n(X),b\sigma(b)\ldots\sigma^{n-1}(b)]$ where $b=a[2]$. \fun{GEN}{FpXQ_auttrace}{GEN a, ulong n, GEN T, GEN p} $a$ being a two-component vector, $\sigma$ being the automorphism defined by $\sigma(X)=a[1]\pmod{T(X)}$, returns the vector $[\sigma^n(X),b+\sigma(b)+\ldots+\sigma^{n-1}(b)]$ where $b=a[2]$. \fun{GEN}{FpXQ_autpowers}{GEN S, long n, GEN T, GEN p} returns $[x,S(x),S(S(x)),\dots,S^{(n)}(x)]$ as a \typ{VEC} of \kbd{FpXQ}s. \fun{GEN}{FpXQM_autsum}{GEN a, long n, GEN T, GEN p} $\sigma$ being the automorphism defined by $\sigma(X)=a[1]\pmod{T(X)}$, returns the vector $[\sigma^n(X),b\sigma(b)\ldots\sigma^{n-1}(b)]$ where $b=a[2]$ is a square matrix. \fun{GEN}{FpX_FpXQ_eval}{GEN f, GEN x, GEN T, GEN p} returns $\kbd{f}(\kbd{x})$. \fun{GEN}{FpX_FpXQV_eval}{GEN f, GEN V, GEN T, GEN p} returns $\kbd{f}(\kbd{x})$, assuming that \kbd{V} was computed by $\kbd{FpXQ\_powers}(\kbd{x}, n, \kbd{T}, \kbd{p})$. \fun{GEN}{FpXC_FpXQ_eval}{GEN C, GEN x, GEN T,GEN p} applies \kbd{FpX\_FpXQV\_eval} to all elements of the vector $C$ and returns a \typ{COL}. \fun{GEN}{FpXC_FpXQV_eval}{GEN C, GEN V,GEN T,GEN p} applies \kbd{FpX\_FpXQV\_eval} to all elements of the vector $C$ and returns a \typ{COL}. \fun{GEN}{FpXM_FpXQV_eval}{GEN M, GEN V,GEN T,GEN p} applies \kbd{FpX\_FpXQV\_eval} to all elements of the matrix $M$. \subsec{\kbd{FpXn}} 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{FpXn} object is an \kbd{FpX} whose degree is strictly less than \kbd{n}. They represent a class in $(\Z/\kbd{p}\Z)[X] / (X^n)$, in which all operations below take place. They can be seen as truncated power series. \fun{GEN}{FpXn_mul}{GEN x, GEN y, long n, GEN p} return $x\*y\pmod{X^n}$. \fun{GEN}{FpXn_sqr}{GEN x, long n, GEN p} return $x^2\pmod{X^n}$. \fun{GEN}{FpXn_div}{GEN x, GEN y, long n, GEN p} return $x/y\pmod{X^n}$. \fun{GEN}{FpXn_inv}{GEN x, long n, GEN p} return $1/x\pmod{X^n}$. \fun{GEN}{FpXn_exp}{GEN f, long n, GEN p} return $\exp(f)$ as a composition of formal power series. It is required that the valuation of $f$ is positive and that $p>n$. \fun{GEN}{FpXn_expint}{GEN f, long n, GEN p} return $\exp(F)$ where $F$ is the primitive of $f$ that vanishes at $0$. It is required that $p>n$. \subsec{\kbd{FpXC}, \kbd{FpXM}} \fun{GEN}{FpXC_center}{GEN C, GEN p, GEN pov2} \fun{GEN}{FpXM_center}{GEN M, GEN p, GEN pov2} \subsec{\kbd{FpXX}, \kbd{FpXY}} Contrary to what the name implies, an \kbd{FpXX} is a \typ{POL} whose coefficients are either \typ{INT}s or \kbd{FpX}s. This reduces memory overhead at the expense of consistency. The prefix \kbd{FpXY} is an alias for \kbd{FpXX} when variables matters. \fun{GEN}{FpXX_red}{GEN z, GEN p}, \kbd{z} a \typ{POL} whose coefficients are either \kbd{ZX}s or \typ{INT}s. Returns the \typ{POL} equal to \kbd{z} with all components reduced modulo \kbd{p}. \fun{GEN}{FpXX_renormalize}{GEN x, long l}, as \kbd{normalizepol}, where $\kbd{l} = \kbd{lg(x)}$, in place. \fun{GEN}{FpXX_add}{GEN x, GEN y, GEN p} adds \kbd{x} and \kbd{y}. \fun{GEN}{FpXX_sub}{GEN x, GEN y, GEN p} returns $\kbd{x}-\kbd{y}$. \fun{GEN}{FpXX_neg}{GEN x, GEN p} returns $-\kbd{x}$. \fun{GEN}{FpXX_Fp_mul}{GEN x, GEN y, GEN p} multiplies the \kbd{FpXX}~\kbd{x} by the \kbd{Fp}~\kbd{y}. \fun{GEN}{FpXX_FpX_mul}{GEN x, GEN y, GEN p} multiplies the coefficients of the \kbd{FpXX}~\kbd{x} by the \kbd{FpX}~\kbd{y}. \fun{GEN}{FpXX_mulu}{GEN x, GEN y, GEN p} multiplies the \kbd{FpXX}~\kbd{x} by the scalar \kbd{y}. \fun{GEN}{FpXX_halve}{GEN x, GEN p} returns $z$ such that $2\*z = x$ assuming such $z$ exists. \fun{GEN}{FpXX_deriv}{GEN P, GEN p} differentiates \kbd{P} with respect to the main variable. \fun{GEN}{FpXX_integ}{GEN P, GEN p} returns the primitive of \kbd{P} with respect to the main variable whose constant term is $0$. \fun{GEN}{FpXY_eval}{GEN Q, GEN y, GEN x, GEN p} $Q$ being an \kbd{FpXY}, i.e.~a \typ{POL} with \kbd{Fp} or \kbd{FpX} coefficients representing an element of $\F_p[X][Y]$. Returns the \kbd{Fp} $Q(x,y)$. \fun{GEN}{FpXY_evalx}{GEN Q, GEN x, GEN p} $Q$ being an \kbd{FpXY}, returns the \kbd{FpX} $Q(x,Y)$, where $Y$ is the main variable of $Q$. \fun{GEN}{FpXY_evaly}{GEN Q, GEN y, GEN p, long vx} $Q$ an \kbd{FpXY}, returns the \kbd{FpX} $Q(X,y)$, where $X$ is the second variable of $Q$, and \kbd{vx} is the variable number of $X$. \fun{GEN}{FpXY_FpXQ_evaly}{GEN Q, GEN y, GEN T, GEN p, long vx} $Q$ an \kbd{FpXY} and $y$ being an \kbd{FpXQ}, returns the \kbd{FpXQX} $Q(X,y)$, where $X$ is the second variable of $Q$, and \kbd{vx} is the variable number of $X$. \fun{GEN}{FpXY_Fq_evaly}{GEN Q, GEN y, GEN T, GEN p, long vx} $Q$ an \kbd{FpXY} and $y$ being an \kbd{Fq}, returns the \kbd{FqX} $Q(X,y)$, where $X$ is the second variable of $Q$, and \kbd{vx} is the variable number of $X$. \fun{GEN}{FpXY_FpXQ_evalx}{GEN Q, GEN x, ulong p} $Q$ an \kbd{FpXY} and $x$ being an \kbd{FpXQ}, returns the \kbd{FpXQX} $Q(x,Y)$, where $Y$ is the first variable of $Q$. \fun{GEN}{FpXY_FpXQV_evalx}{GEN Q, GEN V, ulong p} $Q$ an \kbd{FpXY} and $x$ being an \kbd{FpXQ}, returns the \kbd{FpXQX} $Q(x,Y)$, where $Y$ is the first variable of $Q$, assuming that \kbd{V} was computed by $\kbd{FpXQ\_powers}(\kbd{x}, n, \kbd{T}, \kbd{p})$. \fun{GEN}{FpXYQQ_pow}{GEN x, GEN n, GEN S, GEN T, GEN p}, \kbd{x} being a \kbd{FpXY}, \kbd{T} being a \kbd{FpX} and \kbd{S} being a \kbd{FpY}, return $x^n \pmod{S,T,p}$. \subsec{\kbd{FpXQX}, \kbd{FqX}} Contrary to what the name implies, an \kbd{FpXQX} is a \typ{POL} whose coefficients are \kbd{Fq}s. So the only difference between \kbd{FqX} and \kbd{FpXQX} routines is that $\kbd{T} = \kbd{NULL}$ is not allowed in the latter. (It was thought more useful to allow \typ{INT} components than to enforce strict consistency, which would not imply any efficiency gain.) \subsubsec{Basic operations} \fun{GEN}{FqX_add}{GEN x,GEN y,GEN T,GEN p} \fun{GEN}{FqX_Fq_add}{GEN x, GEN y, GEN T, GEN p} adds the \kbd{Fq}~\kbd{y} to the \kbd{FqX}~\kbd{x}. \fun{GEN}{FqX_Fq_sub}{GEN x, GEN y, GEN T, GEN p} substracts the \kbd{Fq}~\kbd{y} to the \kbd{FqX}~\kbd{x}. \fun{GEN}{FqX_neg}{GEN x,GEN T,GEN p} \fun{GEN}{FqX_sub}{GEN x,GEN y,GEN T,GEN p} \fun{GEN}{FqX_mul}{GEN x, GEN y, GEN T, GEN p} \fun{GEN}{FqX_Fq_mul}{GEN x, GEN y, GEN T, GEN p} multiplies the \kbd{FqX}~\kbd{x} by the \kbd{Fq}~\kbd{y}. \fun{GEN}{FqX_mulu}{GEN x, ulong y, GEN T, GEN p} multiplies the \kbd{FqX}~\kbd{x} by the scalar~\kbd{y}. \fun{GEN}{FqX_halve}{GEN x, GEN T, GEN p} returns $z$ such that $2\*z = x$ assuming such $z$ exists. \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}{FpXQX_normalize}{GEN z, GEN T, GEN p} \fun{GEN}{FqX_normalize}{GEN z, GEN T, GEN p} divides the \kbd{FqX}~\kbd{z} by its leading term. The leading coefficient becomes $1$ as a \typ{INT}. \fun{GEN}{FqX_sqr}{GEN x, GEN T, GEN p} \fun{GEN}{FqX_powu}{GEN x, ulong n, GEN T, GEN p} \fun{GEN}{FqX_divrem}{GEN x, GEN y, GEN T, GEN p, GEN *z} \fun{GEN}{FqX_div}{GEN x, GEN y, GEN T, GEN p} \fun{GEN}{FqX_div_by_X_x}{GEN a, GEN x, GEN T, GEN p, GEN *r} \fun{GEN}{FqX_rem}{GEN x, GEN y, GEN T, GEN p} \fun{GEN}{FqX_deriv}{GEN x, GEN T, GEN p} returns the derivative of \kbd{x}. (This function is suitable for \kbd{gerepilupto} but not memory-clean.) \fun{GEN}{FqX_integ}{GEN x, GEN T, GEN p} returns the primitive of \kbd{x}. whose constant term is $0$. \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_halfgcd}{GEN x, GEN y, GEN T, GEN p} returns a two-by-two \kbd{FqXM} $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}{FqX_eval}{GEN x, GEN y, GEN T, GEN p} evaluates the \kbd{FqX}~\kbd{x} at the \kbd{Fq}~\kbd{y}. The result is an~\kbd{Fq}. \fun{GEN}{FqXY_eval}{GEN Q, GEN y, GEN x, GEN T, GEN p} $Q$ an \kbd{FqXY}, i.e.~a \typ{POL} with \kbd{Fq} or \kbd{FqX} coefficients representing an element of $\F_q[X][Y]$. Returns the \kbd{Fq} $Q(x,y)$. \fun{GEN}{FqXY_evalx}{GEN Q, GEN x, GEN T, GEN p} $Q$ being an \kbd{FqXY}, returns the \kbd{FqX} $Q(x,Y)$, where $Y$ is the main variable of $Q$. \fun{GEN}{random_FpXQX}{long d, long v, GEN T, GEN p} returns a random \kbd{FpXQX} in variable \kbd{v}, of degree less than~\kbd{d}. \fun{GEN}{FpXQX_renormalize}{GEN x, long lx} \fun{GEN}{FpXQX_red}{GEN z, GEN T, GEN p} \kbd{z} a \typ{POL} whose coefficients are \kbd{ZX}s or \typ{INT}s, reduce them to \kbd{FpXQ}s. \fun{GEN}{FpXQXV_red}{GEN z, GEN T, GEN p}, \kbd{z} a \typ{VEC} of \kbd{ZXX}. Applies \kbd{FpX\_red} componentwise and returns the result (and we obtain a vector of \kbd{FpXQX}s). \fun{GEN}{FpXQXT_red}{GEN z, GEN T, GEN p}, \kbd{z} a tree of \kbd{ZXX}. Applies \kbd{FpX\_red} to each leaf and returns the result (and we obtain a tree of \kbd{FpXQX}s). \fun{GEN}{FpXQX_mul}{GEN x, GEN y, GEN T, GEN p} \fun{GEN}{Kronecker_to_FpXQX}{GEN z, GEN T, GEN p}. Let $n = \deg T$ and let $P(X,Y)\in \Z[X,Y]$ lift a polynomial in $K[Y]$, where $K := \F_p[X]/(T)$ and $\deg_X P < 2n-1$ --- such as would result from multiplying minimal degree lifts of two polynomials in $K[Y]$. Let $z = P(t,t^{2*n-1})$ be a Kronecker form of $P$ (see \tet{RgXX_to_Kronecker}), this function returns $Q\in \Z[X,t]$ such that $Q$ is congruent to $P(X,t)$ mod $(p, T(X))$, $\deg_X Q < n$, and all coefficients are in $[0,p[$. Not stack-clean. Note that $t$ need not be the same variable as $Y$! \fun{GEN}{FpXQX_FpXQ_mul}{GEN x, GEN y, GEN T, GEN p} \fun{GEN}{FpXQX_sqr}{GEN x, GEN T, GEN p} \fun{GEN}{FpXQX_divrem}{GEN x, GEN y, GEN T, GEN p, GEN *pr} \fun{GEN}{FpXQX_div}{GEN x, GEN y, GEN T, GEN p} \fun{GEN}{FpXQX_div_by_X_x}{GEN a, GEN x, GEN T, GEN p, GEN *r} \fun{GEN}{FpXQX_rem}{GEN x, GEN y, GEN T, GEN p} \fun{GEN}{FpXQX_powu}{GEN x, ulong n, GEN T, GEN p} returns $x^n$. \fun{GEN}{FpXQX_digits}{GEN x, GEN B, GEN T, GEN p} \fun{GEN}{FpXQX_dotproduct}{GEN x, GEN y, GEN T, GEN p} returns the scalar product of the coefficients of $x$ and $y$. \fun{GEN}{FpXQXV_FpXQX_fromdigits}{GEN v, GEN B, GEN T, GEN p} \fun{GEN}{FpXQX_invBarrett}{GEN y, GEN T, GEN p} returns the Barrett inverse of the \kbd{FpXQX} $y$, namely a lift of $1/\kbd{polrecip}(y)+O(x^{\deg(y)-1})$. \fun{GEN}{FpXQXV_prod}{GEN V, GEN T, GEN p}, \kbd{V} being a vector of \kbd{FpXQX}, returns their product. \fun{GEN}{FpXQX_gcd}{GEN x, GEN y, GEN T, GEN p} \fun{GEN}{FpXQX_extgcd}{GEN x, GEN y, GEN T, GEN p, GEN *ptu, GEN *ptv} \fun{GEN}{FpXQX_halfgcd}{GEN x, GEN y, GEN T, GEN p} \fun{GEN}{FpXQX_halfgcd_all}{GEN x, GEN y, GEN T, GEN p, GEN *ptu, GEN *ptv} \fun{GEN}{FpXQX_resultant}{GEN x, GEN y, GEN T, GEN p} returns the resultant of \kbd{x} and \kbd{y}. \fun{GEN}{FpXQX_disc}{GEN x, GEN T, GEN p} returns the discriminant of \kbd{x}. \fun{GEN}{FpXQX_FpXQXQ_eval}{GEN f,GEN x,GEN S, GEN T,GEN p} returns $\kbd{f}(\kbd{x})$. \subsec{\kbd{FpXQXn}, \kbd{FqXn}} A \kbd{FpXQXn} is a \typ{FpXQX} which represents an element of the ring $(Fp[X]/T(X))[Y]/(Y^n)$, where $T$ is a \kbd{FpX}. \fun{GEN}{FpXQXn_sqr}{GEN x, long n, GEN T, GEN p} \fun{GEN}{FqXn_sqr}{GEN x, long n, GEN T, GEN p} \fun{GEN}{FpXQXn_mul}{GEN x, GEN y, long n, GEN T, GEN p} \fun{GEN}{FqXn_mul}{GEN x, GEN y, long n, GEN T, GEN p} \fun{GEN}{FpXQXn_div}{GEN x, GEN y, long n, GEN T, GEN p} \fun{GEN}{FpXQXn_inv}{GEN x, long n, GEN T, GEN p} \fun{GEN}{FqXn_inv}{GEN x, long n, GEN T, GEN p} \fun{GEN}{FpXQXn_exp}{GEN x, long n, GEN T, GEN p} return $\exp(x)$ as a composition of formal power series. It is required that the valuation of $x$ is positive and that $p>n$. \fun{GEN}{FqXn_exp}{GEN x, long n, GEN T, GEN p} \fun{GEN}{FpXQXn_expint}{GEN f, long n, GEN p} return $\exp(F)$ where $F$ is the primitive of $f$ that vanishes at $0$. It is required that $p>n$. \fun{GEN}{FqXn_expint}{GEN x, long n, GEN T, GEN p} \subsec{\kbd{FpXQXQ}, \kbd{FqXQ}} A \kbd{FpXQXQ} is a \typ{FpXQX} which represents an element of the ring $(Fp[X]/T(X))[Y]/S(X,Y)$, where $T$ is a \kbd{FpX} and $S$ a \kbd{FpXQX} modulo $T$. A \kbd{FqXQ} is identical except that $T$ is allowed to be \kbd{NULL} in which case $S$ must be a \kbd{FpX}. \subsubsec{Preconditioned reduction} For faster reduction, the modulus \kbd{S} can be replaced by an extended modulus, which is an \kbd{FpXQXT}, in all \kbd{FpXQXQ}- and \kbd{FqXQ}-classes functions, and in \kbd{FpXQX\_rem} and \kbd{FpXQX\_divrem}. \fun{GEN}{FpXQX_get_red}{GEN S, GEN T, GEN p} returns the extended modulus \kbd{eS}. \fun{GEN}{FqX_get_red}{GEN S, GEN T, GEN p} identical, but allow $T$ to be \kbd{NULL}, in which case it returns \kbd{FpX\_get\_red(S,p)}. To write code that works both with plain and extended moduli, the following accessors are defined: \fun{GEN}{get_FpXQX_mod}{GEN eS} returns the underlying modulus \kbd{S}. \fun{GEN}{get_FpXQX_var}{GEN eS} returns the variable number of the modulus. \fun{GEN}{get_FpXQX_degree}{GEN eS} returns the degree of the modulus. Furthermore, \kbd{ZXXT\_to\_FlxXT} allows to convert an extended modulus for a \kbd{FpXQX} to an extended modulus for the corresponding \kbd{FlxqX}. \subsubsec{basic operations} \fun{GEN}{FpXQX_FpXQXQV_eval}{GEN f,GEN V,GEN S,GEN T,GEN p} returns $\kbd{f}(\kbd{x})$, assuming that \kbd{V} was computed by $\kbd{FpXQXQ\_powers}(\kbd{x}, n, \kbd{S}, \kbd{T}, \kbd{p})$. \fun{GEN}{FpXQXQ_div}{GEN x, GEN y, GEN S, GEN T, GEN p}, \kbd{x}, \kbd{y} and \kbd{S} being \kbd{FpXQX}s, returns $\kbd{x}*\kbd{y}^{-1}$ modulo \kbd{S}. \fun{GEN}{FpXQXQ_inv}{GEN x, GEN S, GEN T, GEN p}, \kbd{x} and \kbd{S} being \kbd{FpXQX}s, returns $\kbd{x}^{-1}$ modulo \kbd{S}. \fun{GEN}{FpXQXQ_invsafe}{GEN x, GEN S, GEN T,GEN p}, as \kbd{FpXQXQ\_inv}, returning \kbd{NULL} if \kbd{x} is not invertible. \fun{GEN}{FpXQXQ_mul}{GEN x, GEN y, GEN S, GEN T, GEN p}, \kbd{x}, \kbd{y} and \kbd{S} being \kbd{FpXQX}s, returns $\kbd{x}\*\kbd{y}$ modulo \kbd{S}. \fun{GEN}{FpXQXQ_sqr}{GEN x, GEN S, GEN T, GEN p}, \kbd{x} and \kbd{S} being \kbd{FpXQX}s, returns $\kbd{x}^2$ modulo \kbd{S}. \fun{GEN}{FpXQXQ_pow}{GEN x, GEN n, GEN S, GEN T, GEN p}, \kbd{x} and \kbd{S} being \kbd{FpXQX}s, returns $\kbd{x}^\kbd{n}$ modulo \kbd{S}. \fun{GEN}{FpXQXQ_powers}{GEN x, long n, GEN S, GEN T, GEN p}, \kbd{x} and \kbd{S} being \kbd{FpXQX}s, returns $[\kbd{x}^0, \dots, \kbd{x}^\kbd{n}]$ as a \typ{VEC} of \kbd{FpXQXQ}s. \fun{GEN}{FpXQXQ_halfFrobenius}{GEN A, GEN S, GEN T, GEN p} returns $A(X)^{(q-1)/2}\pmod{S(X)}$ over the finite field $\F_q$ defined by $T$ and $p$, thus $q=p^n$ where $n$ is the degree of $T$. \fun{GEN}{FpXQXQ_minpoly}{GEN x, GEN S, GEN T, GEN p}, as \kbd{FpXQ\_minpoly} \fun{GEN}{FpXQXQ_matrix_pow}{GEN x, long m, long n, GEN S, GEN T, GEN p} returns the same powers of \kbd{x} as \kbd{FpXQXQ\_powers}$(x, n-1,S, T, p)$, but as an $m\times n$ matrix. \fun{GEN}{FpXQXQ_autpow}{GEN a, long n, GEN S, GEN T, GEN p} $\sigma$ being the automorphism defined by $\sigma(X)=a[1]\pmod{T(X)}$, $\sigma(Y)=a[2]\pmod{S(X,Y),T(X)}$, returns $[\sigma^n(X),\sigma^n(Y)]$. \fun{GEN}{FpXQXQ_autsum}{GEN a, long n, GEN S, GEN T, GEN p} $\sigma$ being the automorphism defined by $\sigma(X)=a[1]\pmod{T(X)}$, $\sigma(Y)=a[2]\pmod{S(X,Y),T(X)}$, returns the vector $[\sigma^n(X),\sigma^n(Y),b\sigma(b)\ldots\sigma^{n-1}(b)]$ where $b=a[3]$. \fun{GEN}{FpXQXQ_auttrace}{GEN a, long n, GEN S, GEN T, GEN p} $\sigma$ being the automorphism defined by $\sigma(X)=X\pmod{T(X)}$, $\sigma(Y)=a[1]\pmod{S(X,Y),T(X)}$, returns the vector $[\sigma^n(X),\sigma^n(Y),b+\sigma(b)+\ldots+\sigma^{n-1}(b)]$ where $b=a[2]$. % FqXQ \fun{GEN}{FqXQ_add}{GEN x, GEN y, GEN S, GEN T, GEN p}, \kbd{x}, \kbd{y} and \kbd{S} being \kbd{FqX}s, returns $\kbd{x} + \kbd{y}$ modulo \kbd{S}. \fun{GEN}{FqXQ_sub}{GEN x, GEN y, GEN S, GEN T, GEN p}, \kbd{x}, \kbd{y} and \kbd{S} being \kbd{FqX}s, returns $\kbd{x} - \kbd{y}$ modulo \kbd{S}. \fun{GEN}{FqXQ_mul}{GEN x, GEN y, GEN S, GEN T, GEN p}, \kbd{x}, \kbd{y} and \kbd{S} being \kbd{FqX}s, returns $\kbd{x}\*\kbd{y}$ modulo \kbd{S}. \fun{GEN}{FqXQ_div}{GEN x, GEN y, GEN S, GEN T, GEN p}, \kbd{x} and \kbd{S} being \kbd{FqX}s, returns $\kbd{x}/\kbd{y}$ modulo \kbd{S}. \fun{GEN}{FqXQ_inv}{GEN x, GEN S, GEN T, GEN p}, \kbd{x} and \kbd{S} being \kbd{FqX}s, returns $\kbd{x}^{-1}$ modulo \kbd{S}. \fun{GEN}{FqXQ_invsafe}{GEN x, GEN S, GEN T, GEN p} , as \kbd{FqXQ\_inv}, returning \kbd{NULL} if \kbd{x} is not invertible. \fun{GEN}{FqXQ_sqr}{GEN x, GEN S, GEN T, GEN p}, \kbd{x} and \kbd{S} being \kbd{FqX}s, returns $\kbd{x}^2$ modulo \kbd{S}. \fun{GEN}{FqXQ_pow}{GEN x, GEN n, GEN S, GEN T, GEN p}, \kbd{x} and \kbd{S} being \kbd{FqX}s, returns $\kbd{x}^\kbd{n}$ modulo \kbd{S}. \fun{GEN}{FqXQ_powers}{GEN x, long n, GEN S, GEN T, GEN p}, \kbd{x} and \kbd{S} being \kbd{FqX}s, returns $[\kbd{x}^0, \dots, \kbd{x}^\kbd{n}]$ as a \typ{VEC} of \kbd{FqXQ}s. \fun{GEN}{FqXQ_matrix_pow}{GEN x, long m, long n, GEN S, GEN T, GEN p} returns the same powers of \kbd{x} as \kbd{FqXQ\_powers}$(x, n-1,S, T, p)$, but as an $m\times n$ matrix. \fun{GEN}{FqV_roots_to_pol}{GEN V, GEN T, GEN p, long v}, \kbd{V} being a vector of \kbd{Fq}s, returns the monic \kbd{FqX} $\prod_i (\kbd{pol\_x[v]} - \kbd{V[i]})$. \subsubsec{Miscellaneous operations} \fun{GEN}{init_Fq}{GEN p, long n, long v} returns an irreducible polynomial of degree $\kbd{n} > 0$ over $\F_p$, in variable \kbd{v}. \fun{int}{FqX_is_squarefree}{GEN P, GEN T, GEN p} \fun{GEN}{FpXQX_roots}{GEN f, GEN T, GEN p} return the roots of $f$ in $\F_p[X]/(T)$. Assumes \kbd{p} is prime and \kbd{T} irreducible in $\F_p[X]$. \fun{GEN}{FpXQX_roots_mult}{GEN f, long n, GEN T, GEN p} returns the roots in \kbd{\Z/p\Z} with multiplicity at least $n$ of the \kbd{FpXQX}~\kbd{f} (without multiplicity, as a vector of \kbd{FpXQ}s). Assumes \kbd{p} is prime and \kbd{T} irreducible in $\F_p[X]$. \fun{GEN}{FqX_roots}{GEN f, GEN T, GEN p} same but allow $\kbd{T} = \kbd{NULL}$. \fun{GEN}{FpXQX_factor}{GEN f, 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}{FqX_factor}{GEN f, GEN T, GEN p} same but allow $\kbd{T} = \kbd{NULL}$. \fun{GEN}{FpXQX_factor_squarefree}{GEN f, GEN T, GEN p} squarefree factorization of $f$ modulo $(T,p)$; same output convention as \kbd{FpX\_factor\_squarefree}. Assumes \kbd{p} is prime and \kbd{T} irreducible in $\F_p[X]$. \fun{GEN}{FqX_factor_squarefree}{GEN f, GEN T, GEN p} same but allow $\kbd{T} = \kbd{NULL}$. \fun{GEN}{FpXQX_ddf}{GEN f, GEN T, GEN p} as \kbd{FpX\_ddf}. \fun{GEN}{FqX_ddf}{GEN f, GEN T, GEN p} same but allow $\kbd{T} = \kbd{NULL}$. \fun{long}{FpXQX_ddf_degree}{GEN f, GEN XP, GEN T, GEN p}, as \kbd{FpX\_ddf\_degree}. \fun{GEN}{FpXQX_degfact}{GEN f, GEN T, GEN p}, as \kbd{FpX\_degfact}. \fun{GEN}{FqX_degfact}{GEN f, GEN T, GEN p} same but allow $\kbd{T} = \kbd{NULL}$. \fun{GEN}{FpXQX_split_part}{GEN f, GEN T, GEN p} returns the largest totally split squarefree factor of $f$. \fun{long}{FpXQX_ispower}{GEN f, ulong k, GEN T, GEN p, GEN *pt} return $1$ if the \kbd{FpXQX} $f$ is a $k$-th power, $0$ otherwise. If \kbd{pt} is not \kbd{NULL}, set it to $g$ such that $g^k = f$. \fun{long}{FqX_ispower}{GEN f, ulong k, GEN T, GEN p, GEN *pt} same but allow $\kbd{T} = \kbd{NULL}$. \fun{GEN}{FpX_factorff}{GEN P, GEN T, GEN p}. Assumes \kbd{p} prime and \kbd{T} irreducible in $\F_p[X]$. Factor the \kbd{FpX} \kbd{P} over the finite field $\F_p[Y]/(T(Y))$. See \kbd{FpX\_factorff\_irred} if \kbd{P} is known to be irreducible of $\F_p$. \fun{GEN}{FpX_rootsff}{GEN P, GEN T, GEN p}. Assumes \kbd{p} prime and \kbd{T} irreducible in $\F_p[X]$. Returns the roots of the \kbd{FpX} \kbd{P} belonging to the finite field $\F_p[Y]/(T(Y))$. \fun{GEN}{FpX_factorff_irred}{GEN P, GEN T, GEN p}. Assumes \kbd{p} prime and \kbd{T} irreducible in $\F_p[X]$. Factors the \emph{irreducible} \kbd{FpX} \kbd{P} over the finite field $\F_p[Y]/(T(Y))$ and returns the vector of irreducible \kbd{FqX}s factors (the exponents, being all equal to $1$, are not included). \fun{GEN}{FpX_ffisom}{GEN P, GEN Q, GEN p}. Assumes \kbd{p} prime, \kbd{P}, \kbd{Q} are \kbd{ZX}s, both irreducible mod \kbd{p}, and $\deg(P) \mid \deg Q$. Outputs a monomorphism between $\F_p[X]/(P)$ and $\F_p[X]/(Q)$, as a polynomial $R$ such that $\kbd{Q} \mid \kbd{P}(R)$ in $\F_p[X]$. If \kbd{P} and \kbd{Q} have the same degree, it is of course an isomorphism. \fun{void}{FpX_ffintersect}{GEN P, GEN Q, long n, GEN p, GEN *SP,GEN *SQ, GEN MA,GEN MB}\hfil\break Assumes \kbd{p} is prime, \kbd{P}, \kbd{Q} are \kbd{ZX}s, both irreducible mod \kbd{p}, and \kbd{n} divides both the degree of \kbd{P} and \kbd{Q}. Compute \kbd{SP} and \kbd{SQ} such that the subfield of $\F_p[X]/(P)$ generated by \kbd{SP} and the subfield of $\F_p[X]/(Q)$ generated by \kbd{SQ} are isomorphic of degree \kbd{n}. The polynomials \kbd{P} and \kbd{Q} do not need to be of the same variable. If \kbd{MA} (resp. \kbd{MB}) is not \kbd{NULL}, it must be the matrix of the Frobenius map in $\F_p[X]/(P)$ (resp.~$\F_p[X]/(Q)$). \fun{GEN}{FpXQ_ffisom_inv}{GEN S, GEN T, GEN p}. Assumes \kbd{p} is prime, \kbd{T} a \kbd{ZX}, which is irreducible modulo \kbd{p}, \kbd{S} a \kbd{ZX} representing an automorphism of $\F_q := \F_p[X]/(\kbd{T})$. ($\kbd{S}(X)$ is the image of $X$ by the automorphism.) Returns the inverse automorphism of \kbd{S}, in the same format, i.e.~an \kbd{FpX}~$H$ such that $H(\kbd{S}) \equiv X$ modulo $(\kbd{T}, \kbd{p})$. \fun{long}{FpXQX_nbfact}{GEN S, GEN T, GEN p} returns the number of irreducible factors of the polynomial $S$ over the finite field $\F_q$ defined by $T$ and $p$. \fun{long}{FpXQX_nbfact_Frobenius}{GEN S, GEN Xq, GEN T, GEN p} as \kbd{FpXQX\_nbfact} where \kbd{Xq} is \kbd{FpXQX\_Frobenius(S, T, p)}. \fun{long}{FqX_nbfact}{GEN S, GEN T, GEN p} as above but accept \kbd{T=NULL}. \fun{long}{FpXQX_nbroots}{GEN S, GEN T, GEN p} returns the number of roots of the polynomial $S$ over the finite field $\F_q$ defined by $T$ and $p$. \fun{long}{FqX_nbroots}{GEN S, GEN T, GEN p} as above but accept \kbd{T=NULL}. \fun{GEN}{FpXQX_Frobenius}{GEN S, GEN T, GEN p} returns $X^{q}\pmod{S(X)}$ over the finite field $\F_q$ defined by $T$ and $p$, thus $q=p^n$ where $n$ is the degree of $T$. \subsec{\kbd{Flx}} Let \kbd{p} be an \kbd{ulong}, not assumed to be prime unless mentioned otherwise (e.g., all functions involving Euclidean divisions and factorizations), to be given the function arguments; an \kbd{Fl} is an \kbd{ulong} belonging to $[0,\kbd{p}-1]$, an \kbd{Flx}~\kbd{z} is a \typ{VECSMALL} representing a polynomial with small integer coefficients. Specifically \kbd{z[0]} is the usual codeword, \kbd{z[1] = evalvarn($v$)} for some variable $v$, then the coefficients by increasing degree. An \kbd{FlxX} is a \typ{POL} whose coefficients are \kbd{Flx}s. \noindent In the following, an argument called \kbd{sv} is of the form \kbd{evalvarn}$(v)$ for some variable number~$v$. \subsubsec{Preconditioned reduction} For faster reduction, the modulus \kbd{T} can be replaced by an extended modulus (\kbd{FlxT}) in all \kbd{Flxq}-classes functions, and in \kbd{Flx\_divrem}. \fun{GEN}{Flx_get_red}{GEN T, ulong p} returns the extended modulus \kbd{eT}. \fun{GEN}{Flx_get_red_pre}{GEN T, ulong p, ulong pi} as \kbd{Flx\_get\_red}. We assume \var{pi} is the pseudoinverse of $p$, or $0$ in which case we assume \kbd{SMALL\_ULONG}$(p)$. To write code that works both with plain and extended moduli, the following accessors are defined: \fun{GEN}{get_Flx_mod}{GEN eT} returns the underlying modulus \kbd{T}. \fun{GEN}{get_Flx_var}{GEN eT} returns the variable number of the modulus. \fun{GEN}{get_Flx_degree}{GEN eT} returns the degree of the modulus. Furthermore, \kbd{ZXT\_to\_FlxT} allows to convert an extended modulus for a \kbd{FpX} to an extended modulus for the corresponding \kbd{Flx}. \subsubsec{Basic operations} In this section, \var{pi} is the pseudoinverse of $p$, or $0$ in which case we assume \kbd{SMALL\_ULONG}$(p)$. \fun{ulong}{Flx_lead}{GEN x} returns the leading coefficient of $x$ as a \kbd{ulong} (return $0$ for the zero polynomial). \fun{ulong}{Flx_constant}{GEN x} returns the constant coefficient of $x$ as a \kbd{ulong} (return $0$ for the zero polynomial). \fun{GEN}{Flx_red}{GEN z, ulong p} converts from \kbd{zx} with nonnegative coefficients to \kbd{Flx} (by reducing them mod \kbd{p}). \fun{int}{Flx_equal1}{GEN x} returns 1 (true) if the \kbd{Flx} $x$ is equal to~1, 0~(false) otherwise. \fun{int}{Flx_equal}{GEN x, GEN y} returns 1 (true) if the \kbd{Flx} $x$ and $y$ are equal, and 0~(false) otherwise. \fun{GEN}{Flx_copy}{GEN x} returns a copy of \kbd{x}. \fun{GEN}{Flx_add}{GEN x, GEN y, ulong p} \fun{GEN}{Flx_Fl_add}{GEN y, ulong x, ulong p} \fun{GEN}{Flx_neg}{GEN x, ulong p} \fun{GEN}{Flx_neg_inplace}{GEN x, ulong p}, same as \kbd{Flx\_neg}, in place (\kbd{x} is destroyed). \fun{GEN}{Flx_sub}{GEN x, GEN y, ulong p} \fun{GEN}{Flx_Fl_sub}{GEN y, ulong x, ulong p} \fun{GEN}{Flx_halve}{GEN x, ulong p} returns $z$ such that $2\*z = x$ modulo $p$ assuming such $z$ exists. \fun{GEN}{Flx_mul}{GEN x, GEN y, ulong p} \fun{GEN}{Flx_mul_pre}{GEN x, GEN y, ulong p, ulong pi} \fun{GEN}{Flx_Fl_mul}{GEN y, ulong x, ulong p} \fun{GEN}{Flx_Fl_mul_pre}{GEN y, ulong x, ulong p, ulong pi} \fun{GEN}{Flx_double}{GEN y, ulong p} returns $2\*y$. \fun{GEN}{Flx_triple}{GEN y, ulong p} returns $3\*y$. \fun{GEN}{Flx_mulu}{GEN y, ulong x, ulong p} as \kbd{Flx\_Fl\_mul} but do not assume that $x \deg b$. Assumes that $p$ is prime. \fun{GEN}{Flx_halfgcd_pre}{GEN a, GEN b, ulong p} \fun{GEN}{Flx_halfgcd_all}{GEN x, GEN y, ulong p, GEN *pt_a, GEN *pt_b} \fun{GEN}{Flx_halfgcd_all_pre}{GEN x, GEN y, ulong p, GEN *pt_a, GEN *pt_b} \fun{GEN}{Flx_extgcd}{GEN a, GEN b, ulong p, GEN *ptu, GEN *ptv}, here $p$ must be prime. \fun{GEN}{Flx_extgcd_pre}{GEN a, GEN b, ulong p, ulong pi, GEN *ptu, GEN *ptv} \fun{GEN}{Flx_roots}{GEN f, ulong p} returns the vector of roots of $f$ (without multiplicity, as a \typ{VECSMALL}). Assumes that $p$ is prime. \fun{GEN}{Flx_roots_pre}{GEN f, ulong p, ulong pi} \fun{ulong}{Flx_oneroot}{GEN f, ulong p} returns one root $0 \leq r < p$ of the \kbd{Flx}~\kbd{f} in \kbd{\Z/p\Z}. Return $p$ if no root exists. Assumes that $p$ is prime. \fun{GEN}{Flx_oneroot_pre}{GEN f, ulong p}, as \kbd{Flx\_oneroot} \fun{ulong}{Flx_oneroot_split}{GEN f, ulong p} as \kbd{Flx\_oneroot} but assume $f$ is totally split. Assumes that $p$ is prime. \fun{ulong}{Flx_oneroot_split_pre}{GEN f, ulong p, ulong pi} \fun{long}{Flx_ispower}{GEN f, ulong k, ulong p, GEN *pt} return $1$ if the \kbd{Flx} $f$ is a $k$-th power, $0$ otherwise. If \kbd{pt} is not \kbd{NULL}, set it to $g$ such that $g^k = f$. \fun{GEN}{Flx_factor}{GEN f, ulong p} Assumes that $p$ is prime. \fun{GEN}{Flx_ddf}{GEN f, ulong p} Assumes that $p$ is prime. \fun{GEN}{Flx_ddf_pre}{GEN f, ulong p, ulong pi} \fun{GEN}{Flx_factor_squarefree}{GEN f, ulong p} returns the squarefree factorization of $f$ modulo $p$. This is a vector $[u_1,\dots,u_k]$ of pairwise coprime \kbd{Flx} such that $u_k \neq 1$ and $f = \prod u_i^i$. Shallow function. Assumes that $p$ is prime. \fun{GEN}{Flx_factor_squarefree_pre}{GEN f, ulong p, ulong pi} \fun{GEN}{Flx_mod_Xn1}{GEN T, ulong n, ulong p} return $T$ modulo $(X^n + 1, p)$. Shallow function. \fun{GEN}{Flx_mod_Xnm1}{GEN T, ulong n, ulong p} return $T$ modulo $(X^n - 1, p)$. Shallow function. \fun{GEN}{Flx_degfact}{GEN f, ulong p} as \tet{FpX_degfact}. Assumes that $p$ is prime. \fun{GEN}{Flx_factorff_irred}{GEN P, GEN Q, ulong p} as \tet{FpX_factorff_irred}. Assumes that $p$ is prime. \fun{GEN}{Flx_rootsff}{GEN P, GEN T, ulong p} as \tet{FpX_rootsff}. Assumes that $p$ is prime. \fun{GEN}{Flx_factcyclo}{ulong n, ulong p, ulong m} returns the factors of the $n$-th cyclotomic polynomial over \kbd{Fp}. if $m=1$ returns a single factor. \fun{GEN}{Flx_ffisom}{GEN P,GEN Q,ulong l} as \tet{FpX_ffisom}. Assumes that $p$ is prime. \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}{polxn_Flx}{long n, long sv} Returns the monomial of degree $n$ as a \kbd{Flx} in variable $v$; assume that $n \geq 0$. \fun{GEN}{monomial_Flx}{ulong a, long d, long sv} returns the \kbd{Flx} $a\*X^d$ in variable $v$. \fun{GEN}{init_Flxq}{ulong p, long n, long sv} returns an irreducible polynomial of degree $\kbd{n} > 0$ over $\F_p$, in variable \kbd{v}. \fun{GEN}{Flx_normalize}{GEN z, ulong p}, as \kbd{FpX\_normalize}. \fun{GEN}{Flx_rescale}{GEN P, ulong h, ulong p} returns $h^{\deg(P)} P(x/h)$, \kbd{P} is a \kbd{Flx} and \kbd{h} is a nonzero integer. \fun{GEN}{random_Flx}{long d, long sv, ulong p} returns a random \kbd{Flx} in variable \kbd{v}, of degree less than~\kbd{d}. \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}. Assumes that $p$ is prime. \fun{ulong}{Flx_resultant_pre}{GEN a, GEN b, ulong p, ulong pi} \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). Assumes that $p$ is prime. \fun{ulong}{Flx_extresultant_pre}{GEN a, GEN b, ulong p, ulong pi, GEN *ptU, GEN *ptV} \fun{GEN}{Flx_composedprod}{GEN P, GEN Q, ulong p} if $P=a\prod_{i=1}^m(x-p_i)$ and $Q=b\prod_{j=1}^n(x-q_j)$ in some suitable algebraic extension, return $a^n\*b^m\prod_{i,j}(x-p_i\*q_j)$. \fun{GEN}{Flx_composedsum}{GEN P, GEN Q, ulong p} if $P=a\prod_{i=1}^m(x-p_i)$ and $Q=b\prod_{j=1}^n(x-q_j)$ in some suitable algebraic extension, return $a^n\*b^m\prod_{i,j}(x-(p_i+q_j))$. \fun{GEN}{Flx_invBarrett}{GEN T, ulong p}, returns the Barrett inverse $M$ of $T$ defined by $M(x)\*x^n\*T(1/x)\equiv 1\pmod{x^{n-1}}$ where $n$ is the degree of $T$. Assumes that $p$ is prime. \fun{GEN}{Flx_renormalize}{GEN x, long l}, as \kbd{FpX\_renormalize}, where $\kbd{l} = \kbd{lg(x)}$, in place. \fun{GEN}{Flx_shift}{GEN T, long n} returns $\kbd{T} * x^n$ if $n\geq 0$, and $\kbd{T} \bs x^{-n}$ otherwise. \fun{long}{Flx_val}{GEN x} returns the valuation of \kbd{x}, i.e. the multiplicity of the $0$ root. \fun{long}{Flx_valrem}{GEN x, GEN *Z} as \kbd{RgX\_valrem}, returns the valuation of \kbd{x}. In particular, if the valuation is $0$, set \kbd{*Z} to $x$, not a copy. \fun{GEN}{Flx_div_by_X_x}{GEN A, ulong a, ulong p, ulong *rem}, returns the Euclidean quotient of the \kbd{Flx}~\kbd{A} by $X - \kbd{a}$, and sets \kbd{rem} to the remainder $ \kbd{A}(\kbd{a})$. \fun{ulong}{Flx_eval}{GEN x, ulong y, ulong p}, as \kbd{FpX\_eval}. \fun{ulong}{Flx_eval_pre}{GEN x, ulong y, ulong p, ulong pi} \fun{ulong}{Flx_eval_powers_pre}{GEN P, GEN y, ulong p, ulong pi}. Let $y$ be the \typ{VECSMALL} $(1,a,\dots,a^n)$, where $n$ is the degree of the \kbd{Flx} $P$, return $P(a)$. \fun{GEN}{Flx_Flv_multieval}{GEN P, GEN v, ulong p} returns the vector $[P(v[1]),\ldots,P(v[n])]$ as a \kbd{Flv}. \fun{ulong}{Flx_dotproduct}{GEN x, GEN y, ulong p} returns the scalar product of the coefficients of $x$ and $y$. \fun{ulong}{Flx_dotproduct_pre}{GEN x, GEN y, ulong p, ulong pi}. \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}{Flx_splitting}{GEN P, long k}, as \tet{RgX_splitting}. \fun{GEN}{Flx_blocks}{GEN P, long n, long m}, as \tet{RgX_blocks}. \fun{int}{Flx_is_squarefree}{GEN z, ulong p}. Assumes that $p$ is prime. \fun{int}{Flx_is_irred}{GEN f, ulong p}, as \kbd{FpX\_is\_irred}. Assumes that $p$ is prime. \fun{int}{Flx_is_totally_split}{GEN f, ulong p} returns $1$ if the \kbd{Flx}~\kbd{f} splits into a product of distinct linear factors, $0$ otherwise. Assumes that \kbd{p} is prime. \fun{int}{Flx_is_smooth}{GEN f, long r, ulong p} return $1$ if all irreducible factors of $f$ are of degree at most $r$, $0$ otherwise. Assumes that $p$ is prime. \fun{int}{Flx_is_smooth_pre}{GEN f, long r, ulong p, ulong pi} \fun{long}{Flx_nbroots}{GEN f, ulong p}, as \kbd{FpX\_nbroots}. Assumes that $p$ is prime. \fun{long}{Flx_nbfact}{GEN z, ulong p}, as \kbd{FpX\_nbfact}. Assumes that $p$ is prime. \fun{long}{Flx_nbfact_pre}{GEN z, ulong p, ulong pi} \fun{long}{Flx_nbfact_Frobenius}{GEN f, GEN XP, ulong p}, as \kbd{FpX\_nbfact\_Frobenius}. Assumes that $p$ is prime. \fun{long}{Flx_nbfact_Frobenius_pre}{GEN f, GEN XP, ulong p, ulong pi} \fun{GEN}{Flx_degfact}{GEN f, ulong p}, as \kbd{FpX\_degfact}. Assumes that $p$ is prime. \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]$). Assumes that $p$ is prime. \fun{void}{Flx_ffintersect}{GEN P,GEN Q, long n, ulong p, GEN*SP, GEN*SQ, GEN MA,GEN MB},\hfil\break as \kbd{FpX\_ffintersect}. Assumes that $p$ is prime. \fun{GEN}{Flx_Laplace}{GEN x, ulong p} \fun{GEN}{Flx_invLaplace}{GEN x, ulong p} \fun{GEN}{Flx_Newton}{GEN x, long n, ulong p} \fun{GEN}{Flx_fromNewton}{GEN x, ulong p} \fun{GEN}{Flx_Teichmuller}{GEN P, ulong p, long n} Return a \kbd{ZX} $Q$ such that $P\equiv Q\pmod{p}$ and $Q(X^p)=0\pmod{Q,p^n}$. Assumes that $p$ is prime. \fun{GEN}{Flv_polint}{GEN x, GEN y, ulong p, long sv} as \kbd{FpV\_polint}, returning an \kbd{Flx} in variable $v$. Assumes that $p$ is prime. \fun{GEN}{Flv_Flm_polint}{GEN x, GEN V, ulong p, long sv} equivalent (but faster) to applying \kbd{Flv\_polint(x,$\ldots$)} to all the elements of the vector $V$ (thus, returns a \kbd{FlxV}). Assumes that $p$ is prime. \fun{GEN}{Flv_invVandermonde}{GEN L, ulong d, ulong p} $L$ being a \kbd{Flv} of length $n$, return the inverse $M$ of the Vandermonde matrix attached to the elements of $L$, multiplied by \kbd{d}. If $A$ is a \kbd{Flv} and $B=M\*A$, then the polynomial $P=\sum_{i=1}^n B[i]\*X^{i-1}$ verifies $P(L[i])=d\*A[i]$ for $1 \leq i \leq n$. Assumes that $p$ is prime. \fun{GEN}{Flv_roots_to_pol}{GEN a, ulong p, long sv} as \kbd{FpV\_roots\_to\_pol} returning an \kbd{Flx} in variable $v$. \subsec{\kbd{FlxV}} See \kbd{FpXV} operations. \fun{GEN}{FlxV_Flc_mul}{GEN V, GEN W, ulong p}, as \kbd{FpXV\_FpC\_mul}. \fun{GEN}{FlxV_red}{GEN V, ulong p} reduces each components with \kbd{Flx\_red}. \fun{GEN}{FlxV_prod}{GEN V, ulong p}, \kbd{V} being a vector of \kbd{Flx}, returns their product. \fun{GEN}{FlxV_composedsum}{GEN V, ulong p}, \kbd{V} being a vector of \kbd{Flx}, returns their composed sum, see \kbd{Flx\_composedsum}. \fun{ulong}{FlxC_eval_powers_pre}{GEN x, GEN y, ulong p, ulong pi} apply \kbd{Flx\_eval\_powers\_pre} to all elements of \kbd{x}. \fun{GEN}{FlxV_Flv_multieval}{GEN F, GEN v, ulong p} assuming $F$ is a vector of \kbd{Flx} with $m$ entries and $v$ is a \kbd{Flv} with $m$ entries, returns the $n$-components vector (\kbd{FlvV}) whose $j$-th entry is $[F_j(v[1]),\ldots,F_j(v[n])]$, with $F_j = F[j]$. \fun{GEN}{FlxC_neg}{GEN x, ulong p} \fun{GEN}{FlxC_sub}{GEN x, GEN y, ulong p} \fun{GEN}{zero_FlxC}{long n, long sv} \subsec{\kbd{FlxM}} See \kbd{FpXM} operations. \fun{ulong}{FlxM_eval_powers_pre}{GEN M, GEN y, ulong p, ulong pi} this function applies \kbd{FlxC\_eval\_powers\_pre} to all entries of \kbd{M}. \fun{GEN}{FlxM_neg}{GEN x, ulong p} \fun{GEN}{FlxM_sub}{GEN x, GEN y, ulong p} \fun{GEN}{zero_FlxM}{long r, long c, long sv} \subsec{\kbd{FlxT}} See \kbd{FpXT} operations. \fun{GEN}{FlxT_red}{GEN V, ulong p} reduces each leaf with \kbd{Flx\_red}. \subsec{\kbd{Flxn}} See \kbd{FpXn} operations. In this section, \var{pi} is the pseudoinverse of $p$, or $0$ in which case we assume \kbd{SMALL\_ULONG}$(p)$. \fun{GEN}{Flxn_mul}{GEN a, GEN b, long n, ulong p} returns $a\*b$ modulo $X^n$. \fun{GEN}{Flxn_mul_pre}{GEN a, GEN b, long n, ulong p, ulong pi} \fun{GEN}{Flxn_sqr}{GEN a, long n, ulong p} returns $a^2$ modulo $X^n$. \fun{GEN}{Flxn_sqr_pre}{GEN a, long n, ulong p, ulong pi} \fun{GEN}{Flxn_inv}{GEN a, long n, ulong p} returns $1/a$ modulo $X^n$. \fun{GEN}{Flxn_div}{GEN a, GEN b, long n, ulong p} returns $a/b$ modulo $X^n$. \fun{GEN}{Flxn_div_pre}{GEN a, GEN b, long n, ulong p, ulong pi} \fun{GEN}{Flxn_red}{GEN a, long n} returns $a$ modulo $X^n$. \fun{GEN}{Flxn_exp}{GEN x, long n, ulong p} return $\exp(x)$ as a composition of formal power series. It is required that the valuation of $x$ is positive and that $p>n$. \fun{GEN}{Flxn_expint}{GEN f, long n, ulong p} return $\exp(F)$ where $F$ is the primitive of $f$ that vanishes at $0$. It is required that $p>n$. \subsec{\kbd{Flxq}} See \kbd{FpXQ} operations. In this section, \var{pi} is the pseudoinverse of $p$, or $0$ in which case we assume \kbd{SMALL\_ULONG}$(p)$. \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_mul_pre}{GEN x, GEN y, GEN T, ulong p, ulong pi} \fun{GEN}{Flxq_sqr}{GEN y, GEN T, ulong p} \fun{GEN}{Flxq_sqr_pre}{GEN y, GEN T, ulong p} \fun{GEN}{Flxq_inv}{GEN x, GEN T, ulong p} \fun{GEN}{Flxq_inv_pre}{GEN x, GEN T, ulong p, ulong pi} \fun{GEN}{Flxq_invsafe}{GEN x, GEN T, ulong p} \fun{GEN}{Flxq_invsafe_pre}{GEN x, GEN T, ulong p, ulong pi} \fun{GEN}{Flxq_div}{GEN x, GEN y, GEN T, ulong p} \fun{GEN}{Flxq_div_pre}{GEN x, GEN y, GEN T, ulong p, ulong pi} \fun{GEN}{Flxq_pow}{GEN x, GEN n, GEN T, ulong p} \fun{GEN}{Flxq_pow_pre}{GEN x, GEN n, GEN T, ulong p, ulong pi} \fun{GEN}{Flxq_powu}{GEN x, ulong n, GEN T, ulong p} \fun{GEN}{Flxq_powu_pre}{GEN x, ulong n, GEN T, ulong p} \fun{GEN}{FlxqV_factorback}{GEN L, GEN e, GEN Tp, ulong p} \fun{GEN}{Flxq_pow_init}{GEN x, GEN n, long k, GEN T, ulong p} \fun{GEN}{Flxq_pow_init_pre}{GEN x, GEN n, long k, GEN T, ulong p, ulong pi} \fun{GEN}{Flxq_pow_table}{GEN R, GEN n, GEN T, ulong p} \fun{GEN}{Flxq_pow_table_pre}{GEN R, GEN n, GEN T, ulong p, ulong pi} \fun{GEN}{Flxq_powers}{GEN x, long n, GEN T, ulong p} \fun{GEN}{Flxq_powers_pre}{GEN x, long n, GEN T, ulong p, ulong pi} \fun{GEN}{Flxq_matrix_pow}{GEN x, long m, long n, GEN T, ulong p}, see \kbd{FpXQ\_matrix\_pow}. \fun{GEN}{Flxq_matrix_pow_pre}{GEN x, long m, long n, GEN T, ulong p, ulong pi} \fun{GEN}{Flxq_autpow}{GEN a, long n, GEN T, ulong p} see \kbd{FpXQ\_autpow}. \fun{GEN}{Flxq_autpow_pre}{GEN a, long n, GEN T, ulong p, ulong pi} \fun{GEN}{Flxq_autpowers}{GEN a, long n, GEN T, ulong p} return $[X,\sigma(X),\ldots,\sigma^n(X)]$, assuming $a=\sigma(X)$ where $\sigma$ is an automorphism of the algebra $\F_p[X]/T(X)$. \fun{GEN}{Flxq_autsum}{GEN a, long n, GEN T, ulong p} see \kbd{FpXQ\_autsum}. \fun{GEN}{Flxq_auttrace}{GEN a, ulong n, GEN T, ulong p} see \kbd{FpXQ\_auttrace}. \fun{GEN}{Flxq_auttrace_pre}{GEN a, ulong n, GEN T, ulong p, ulong pi} \fun{GEN}{Flxq_ffisom_inv}{GEN S, GEN T, ulong p}, as \kbd{FpXQ\_ffisom\_inv}. \fun{GEN}{Flx_Flxq_eval}{GEN f, GEN x, GEN T, ulong p} returns $\kbd{f}(\kbd{x})$. \fun{GEN}{Flx_Flxq_eval_pre}{GEN f, GEN x, GEN T, ulong p, ulong pi} \fun{GEN}{Flx_FlxqV_eval}{GEN f, GEN x, GEN T, ulong p}, see \kbd{FpX\_FpXQV\_eval}. \fun{GEN}{Flx_FlxqV_eval_pre}{GEN f, GEN x, GEN T, ulong p, ulong pi} \fun{GEN}{FlxC_Flxq_eval}{GEN C, GEN x, GEN T, ulong p}, see \kbd{FpXC\_FpXQ\_eval}. \fun{GEN}{FlxC_Flxq_eval_pre}{GEN C, GEN x, GEN T, ulong p, ulong pi} \fun{GEN}{FlxC_FlxqV_eval}{GEN C, GEN V, GEN T, ulong p} see \kbd{FpXC\_FpXQV\_eval}. \fun{GEN}{FlxC_FlxqV_eval_pre}{GEN C, GEN V, GEN T, ulong p, ulong pi} \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{int}{Flxq_issquare}{GEN x, GEN T, ulong p} returns $1$ if $x$ is a square and $0$ otherwise. Assume that \kbd{T} is irreducible mod \kbd{p}. \fun{int}{Flxq_is2npower}{GEN x, long n, GEN T, ulong p} returns $1$ if $x$ is a $2^n$-th power and $0$ otherwise. Assume that \kbd{T} is irreducible mod \kbd{p}. \fun{GEN}{Flxq_order}{GEN a, GEN ord, GEN T, ulong p} as \tet{FpXQ_order}. \fun{GEN}{Flxq_log}{GEN a, GEN g, GEN ord, GEN T, ulong p} as \tet{FpXQ_log} \fun{GEN}{Flxq_sqrtn}{GEN x, GEN n, GEN T, ulong p, GEN *zn} as \tet{FpXQ_sqrtn}. \fun{GEN}{Flxq_sqrt}{GEN x, GEN T, ulong p} returns a square root of \kbd{x}. Return \kbd{NULL} if \kbd{x} is not a square. \fun{GEN}{Flxq_sqrt_pre}{GEN x, GEN T, ulong p, ulong pi} \fun{GEN}{Flxq_lroot}{GEN a, GEN T, ulong p} returns $x$ such that $x^p = a$. \fun{GEN}{Flxq_lroot_pre}{GEN a, GEN T, ulong p, ulong pi} \fun{GEN}{Flxq_lroot_fast}{GEN a, GEN V, GEN T, ulong p} assuming that \kbd{V=Flxq\_powers(s,p-1,T,p)} where $s(x)^p \equiv x\pmod{T(x),p}$, returns $b$ such that $b^p=a$. Only useful if $p$ is less than the degree of $T$. \fun{GEN}{Flxq_lroot_fast_pre}{GEN a, GEN V, GEN T, ulong p, ulong pi} \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{GEN}{Flxq_minpoly_pre}{GEN x, GEN T, ulong p, ulong pi} \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. In this section, we assume \var{pi} is the pseudoinverse of $p$, or $0$ in which case we assume \kbd{SMALL\_ULONG}$(p)$. \fun{GEN}{pol1_FlxX}{long vX, long sx} returns the unit \kbd{FlxX} as a \typ{POL} in variable \kbd{vX} which only coefficient is \kbd{pol1\_Flx(sx)}. \fun{GEN}{polx_FlxX}{long vX, long sx} returns the variable $X$ as a degree~1~\typ{POL} with \kbd{Flx} coefficients in the variable $x$. \fun{long}{FlxY_degreex}{GEN P} return the degree of $P$ with respect to the secondary variable. \fun{GEN}{FlxX_add}{GEN P, GEN Q, ulong p} \fun{GEN}{FlxX_sub}{GEN P, GEN Q, ulong p} \fun{GEN}{FlxX_Fl_mul}{GEN x, ulong y, ulong p} \fun{GEN}{FlxX_double}{GEN x, ulong p} \fun{GEN}{FlxX_triple}{GEN x, ulong p} \fun{GEN}{FlxX_neg}{GEN x, ulong p} \fun{GEN}{FlxX_Flx_add}{GEN x, GEN y, ulong p} \fun{GEN}{FlxX_Flx_sub}{GEN x, GEN y, ulong p} \fun{GEN}{FlxX_Flx_mul}{GEN x, GEN y, ulong p} \fun{GEN}{FlxY_Flx_div}{GEN x, GEN y, ulong p} divides the coefficients of $x$ by $y$ using \kbd{Flx\_div}. \fun{GEN}{FlxX_deriv}{GEN P, ulong p} returns the derivative of \kbd{P} with respect to the main variable. \fun{GEN}{FlxX_Laplace}{GEN x, ulong p} \fun{GEN}{FlxX_invLaplace}{GEN x, ulong p} \fun{GEN}{FlxY_evalx}{GEN P, ulong z, ulong p} $P$ being an \kbd{FlxY}, returns the \kbd{Flx} $P(z,Y)$, where $Y$ is the main variable of $P$. \fun{GEN}{FlxY_evalx_pre}{GEN P, ulong z, ulong p, ulong pi} \fun{GEN}{FlxX_translate1}{GEN P, ulong p, long n} $P$ being an \kbd{FlxX} with all coefficients of degree at most $n$, return $(P(x,Y+1)$, where $Y$ is the main variable of $P$. \fun{GEN}{zlxX_translate1}{GEN P, ulong p, long e, long n} $P$ being an \kbd{zlxX} with all coefficients of degree at most $n$, return $(P(x,Y+1)$ modulo $p^e$ for prime $p$ , where $Y$ is the main variable of $P$. \fun{GEN}{FlxY_Flx_translate}{GEN P, GEN f, ulong p} $P$ being an \kbd{FlxY} and $f$ being an \kbd{Flx}, return $(P(x,Y+f(x))$, where $Y$ is the main variable of $P$. \fun{ulong}{FlxY_evalx_powers_pre}{GEN P, GEN xp, ulong p, ulong pi}, \kbd{xp} being the vector $[1,x,\dots,x^n]$, where $n$ is larger or equal to the degree of $P$ in $X$, return $P(x,Y)$, where $Y$ is the main variable of $Q$. \fun{ulong}{FlxY_eval_powers_pre}{GEN P, GEN xp, GEN yp, ulong p, ulong pi}, \kbd{xp} being the vector $[1,x,\dots,x^n]$, where $n$ is larger or equal to the degree of $P$ in $X$ and \kbd{yp} being the vector $[1,y,\dots,y^m]$, where $m$ is larger or equal to the degree of $P$ in $Y$ return $P(x,y)$. \fun{GEN}{FlxY_Flxq_evalx}{GEN x, GEN y, GEN T, ulong p} as \kbd{FpXY\_FpXQ\_evalx}. \fun{GEN}{FlxY_Flxq_evalx_pre}{GEN x, GEN y, GEN T, ulong p, ulong pi} \fun{GEN}{FlxY_FlxqV_evalx}{GEN x, GEN V, GEN T, ulong p} as \kbd{FpXY\_FpXQV\_evalx}. \fun{GEN}{FlxY_FlxqV_evalx_pre}{GEN x, GEN V, GEN T, ulong p, ulong pi} \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_blocks}{GEN P, long n, long m, long sv}, as \tet{RgX_blocks}, where $v$ is the secondary variable. \fun{GEN}{FlxX_shift}{GEN a, long n, long sv}, as \kbd{RgX\_shift\_shallow}, where $v$ is the secondary variable. \fun{GEN}{FlxX_swap}{GEN x, long n, long ws}, as \kbd{RgXY\_swap}. \fun{GEN}{FlxYqq_pow}{GEN x, GEN n, GEN S, GEN T, ulong p}, as \kbd{FpXYQQ\_pow}. \subsec{\kbd{FlxXV, FlxXC, FlxXM}} See \kbd{FpXX} operations. \fun{GEN}{FlxXC_sub}{GEN x, GEN y, ulong p} \subsec{\kbd{FlxqX}} See \kbd{FpXQX} operations. \subsubsec{Preconditioned reduction} For faster reduction, the modulus \kbd{S} can be replaced by an extended modulus, which is an \kbd{FlxqXT}, in all \kbd{FlxqXQ}-classes functions, and in \kbd{FlxqX\_rem} and \kbd{FlxqX\_divrem}. \fun{GEN}{FlxqX_get_red}{GEN S, GEN T, ulong p} returns the extended modulus \kbd{eS}. \fun{GEN}{FlxqX_get_red_pre}{GEN S, GEN T, ulong p, ulong pi}, where \var{pi} is a pseudoinverse of $p$, or $0$ in which case we assume \kbd{SMALL\_ULONG}$(p)$. To write code that works both with plain and extended moduli, the following accessors are defined: \fun{GEN}{get_FlxqX_mod}{GEN eS} returns the underlying modulus \kbd{S}. \fun{GEN}{get_FlxqX_var}{GEN eS} returns the variable number of the modulus. \fun{GEN}{get_FlxqX_degree}{GEN eS} returns the degree of the modulus. \subsubsec{basic functions} In this section, \var{pi} is a pseudoinverse of $p$, or $0$ in which case we assume \kbd{SMALL\_ULONG}$(p)$. \fun{GEN}{random_FlxqX}{long d, long v, GEN T, ulong p} returns a random \kbd{FlxqX} in variable \kbd{v}, of degree less than~\kbd{d}. \fun{GEN}{zxX_to_Kronecker}{GEN P, GEN Q} assuming $P(X,Y)$ is a polynomial of degree in $X$ strictly less than $n$, returns $P(X,X^{2*n-1})$, the Kronecker form of $P$. \fun{GEN}{Kronecker_to_FlxqX}{GEN z, GEN T, ulong p}. Let $n = \deg T$ and let $P(X,Y)\in \Z[X,Y]$ lift a polynomial in $K[Y]$, where $K := \F_p[X]/(T)$ and $\deg_X P < 2n-1$ --- such as would result from multiplying minimal degree lifts of two polynomials in $K[Y]$. Let $z = P(t,t^{2*n-1})$ be a Kronecker form of $P$, this function returns $Q\in \Z[X,t]$ such that $Q$ is congruent to $P(X,t)$ mod $(p, T(X))$, $\deg_X Q < n$, and all coefficients are in $[0,p[$. Not stack-clean. Note that $t$ need not be the same variable as $Y$! \fun{GEN}{Kronecker_to_FlxqX_pre}{GEN z, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqX_red}{GEN z, GEN T, ulong p} \fun{GEN}{FlxqX_red_pre}{GEN z, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqX_normalize}{GEN z, GEN T, ulong p} \fun{GEN}{FlxqX_normalize_pre}{GEN z, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqX_mul}{GEN x, GEN y, GEN T, ulong p} \fun{GEN}{FlxqX_mul_pre}{GEN x, GEN y, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqX_Flxq_mul}{GEN P, GEN U, GEN T, ulong p} \fun{GEN}{FlxqX_Flxq_mul_pre}{GEN P, GEN U, GEN T, ulong p, ulong pi} \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_Flxq_mul_to_monic_pre}{GEN P, GEN U, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqX_sqr}{GEN x, GEN T, ulong p} \fun{GEN}{FlxqX_sqr_pre}{GEN x, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqX_powu}{GEN x, ulong n, GEN T, ulong p} \fun{GEN}{FlxqX_powu_pre}{GEN x, ulong n, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqX_divrem}{GEN x, GEN y, GEN T, ulong p, GEN *pr} \fun{GEN}{FlxqX_divrem_pre}{GEN x, GEN y, GEN T, ulong p, ulong pi, GEN *pr} \fun{GEN}{FlxqX_div}{GEN x, GEN y, GEN T, ulong p} \fun{GEN}{FlxqX_div_pre}{GEN x, GEN y, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqX_div_by_X_x}{GEN a, GEN x, GEN T, ulong p, GEN *r} \fun{GEN}{FlxqX_div_by_X_x_pre}{GEN a, GEN x, GEN T, ulong p, ulong pi, GEN *r} \fun{GEN}{FlxqX_rem}{GEN x, GEN y, GEN T, ulong p} \fun{GEN}{FlxqX_rem_pre}{GEN x, GEN y, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqX_invBarrett}{GEN T, GEN Q, ulong p} \fun{GEN}{FlxqX_invBarrett_pre}{GEN T, GEN Q, ulong p, ulong pi} \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_gcd_pre}{GEN x, GEN y, ulong p, ulong pi} \fun{GEN}{FlxqX_extgcd}{GEN x, GEN y, GEN T, ulong p, GEN *ptu, GEN *ptv} \fun{GEN}{FlxqX_extgcd_pre}{GEN x, GEN y, GEN T, ulong p, ulong pi, GEN *ptu, GEN *ptv} \fun{GEN}{FlxqX_halfgcd}{GEN x, GEN y, GEN T, ulong p}, see \kbd{FpX\_halfgcd}. \fun{GEN}{FlxqX_halfgcd_pre}{GEN x, GEN y, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqX_halfgcd_all}{GEN x, GEN y, GEN T, ulong p, GEN *a, GEN *b}, see \kbd{FpX\_halfgcd\_all}. \fun{GEN}{FlxqX_halfgcd_all_pre}{GEN x, GEN y, GEN T, ulong p, ulong pi, GEN *a, GEN *b}, see \kbd{FpX\_halfgcd\_all\_pre}. \fun{GEN}{FlxqX_resultant}{GEN x, GEN y, GEN T, ulong p}, see \kbd{FpX\_resultant}. \fun{GEN}{FlxqX_resultant_pre}{GEN x, GEN y, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqX_saferesultant}{GEN P, GEN Q, GEN T, ulong p} Returns the resultant 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 noninvertible leading terms occur). \fun{GEN}{FlxqX_composedsum}{GEN P, GEN Q, GEN T, ulong p} \fun{GEN}{FlxqX_disc}{GEN x, GEN T, ulong p} \fun{GEN}{FlxqX_eval}{GEN x, GEN y, GEN T, ulong p} evaluates the \kbd{FlxqX}~\kbd{x} at the \kbd{Flxq}~\kbd{y}. The result is an~\kbd{Flxq}. \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 noninvertible leading terms occur). \fun{GEN}{FlxqX_dotproduct}{GEN x, GEN y, GEN T, ulong p} returns the scalar product of the coefficients of $x$ and $y$. \fun{GEN}{FlxqX_Newton}{GEN x, long n, GEN T, ulong p} \fun{GEN}{FlxqX_Newton_pre}{GEN x, long n, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqX_fromNewton}{GEN x, GEN T, ulong p} \fun{GEN}{FlxqX_fromNewton_pre}{GEN x, GEN T, ulong p, ulong pi} We assume \var{pi} is a pseudoinverse of $p$, or $0$ in which case we assume \kbd{SMALL\_ULONG}$(p)$. \fun{long}{FlxqX_is_squarefree}{GEN S, GEN T, ulong p}, as \kbd{FpX\_is\_squarefree}. \fun{long}{FlxqX_ispower}{GEN f, ulong k, GEN T, ulong p, GEN *pt} return $1$ if the \kbd{FlxqX} $f$ is a $k$-th power, $0$ otherwise. If \kbd{pt} is not \kbd{NULL}, set it to $g$ such that $g^k = f$. \fun{GEN}{FlxqX_Frobenius}{GEN S, GEN T, ulong p}, as \kbd{FpXQX\_Frobenius} \fun{GEN}{FlxqX_Frobenius_pre}{GEN S, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqX_roots}{GEN f, GEN T, ulong p} return the roots of \kbd{f} in $\F_p[X]/(T)$. Assumes \kbd{p} is prime and \kbd{T} irreducible in $\F_p[X]$. \fun{GEN}{FlxqX_factor}{GEN f, GEN T, ulong p} return the factorization of \kbd{f} over $\F_p[X]/(T)$. Assumes \kbd{p} is prime and \kbd{T} irreducible in $\F_p[X]$. \fun{GEN}{FlxqX_factor_squarefree}{GEN f, GEN T, ulong p} returns the squarefree factorization of $f$, see \kbd{FpX\_factor\_squarefree}. \fun{GEN}{FlxqX_factor_squarefree_pre}{GEN f, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqX_ddf}{GEN f, GEN T, ulong p} as \kbd{FpX\_ddf}. \fun{long}{FlxqX_ddf_degree}{GEN f, GEN XP, GEN T, GEN p}, as \kbd{FpX\_ddf\_degree}. \fun{GEN}{FlxqX_degfact}{GEN f, GEN T, ulong p}, as \kbd{FpX\_degfact}. \fun{long}{FlxqX_nbroots}{GEN S, GEN T, ulong p}, as \kbd{FpX\_nbroots}. \fun{long}{FlxqX_nbfact}{GEN S, GEN T, ulong p}, as \kbd{FpX\_nbfact}. \fun{long}{FlxqX_nbfact_Frobenius}{GEN S, GEN Xq, GEN T, ulong p}, as \kbd{FpX\_nbfact\_Frobenius}. \fun{GEN}{FlxqX_nbfact_by_degree}{GEN z, long *nb, GEN T, ulong p} Assume that the \kbd{FlxqX} $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{GEN}{FlxqX_FlxqXQ_eval}{GEN Q, GEN x, GEN S, GEN T, ulong p} as \kbd{FpX\_FpXQ\_eval}. \fun{GEN}{FlxqX_FlxqXQ_eval_pre}{GEN Q, GEN x, GEN S, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqX_FlxqXQV_eval}{GEN P, GEN V, GEN S, GEN T, ulong p} as \kbd{FpX\_FpXQV\_eval}. \fun{GEN}{FlxqX_FlxqXQV_eval_pre}{GEN P, GEN V, GEN S, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqXC_FlxqXQ_eval}{GEN Q, GEN x, GEN S, GEN T, ulong p} as \kbd{FpXC\_FpXQ\_eval}. \fun{GEN}{FlxqXC_FlxqXQ_eval_pre}{GEN Q, GEN x, GEN S, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqXC_FlxqXQV_eval}{GEN P, GEN V, GEN S, GEN T, ulong p} as \kbd{FpXC\_FpXQV\_eval}. \fun{GEN}{FlxqXC_FlxqXQV_eval_pre}{GEN P, GEN V, GEN S, GEN T, ulong p, ulong pi} \subsec{\kbd{FlxqXQ}} See \kbd{FpXQXQ} operations. In this section, \var{pi} is a pseudoinverse of $p$, or $0$ in which case we assume \kbd{SMALL\_ULONG}$(p)$. \fun{GEN}{FlxqXQ_mul}{GEN x, GEN y, GEN S, GEN T, ulong p} \fun{GEN}{FlxqXQ_mul_pre}{GEN x, GEN y, GEN S, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqXQ_sqr}{GEN x, GEN S, GEN T, ulong p} \fun{GEN}{FlxqXQ_sqr_pre}{GEN x, GEN S, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqXQ_inv}{GEN x, GEN S, GEN T, ulong p} \fun{GEN}{FlxqXQ_inv_pre}{GEN x, GEN S, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqXQ_invsafe}{GEN x, GEN S, GEN T, ulong p} \fun{GEN}{FlxqXQ_invsafe_pre}{GEN x, GEN S, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqXQ_div}{GEN x, GEN y, GEN S, GEN T, ulong p} \fun{GEN}{FlxqXQ_div_pre}{GEN x, GEN y, GEN S, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqXQ_pow}{GEN x, GEN n, GEN S, GEN T, ulong p} \fun{GEN}{FlxqXQ_pow_pre}{GEN x, GEN n, GEN S, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqXQ_powu}{GEN x, ulong n, GEN S, GEN T, ulong p} \fun{GEN}{FlxqXQ_powu_pre}{GEN x, ulong n, GEN S, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqXQ_powers}{GEN x, long n, GEN S, GEN T, ulong p} \fun{GEN}{FlxqXQ_powers_pre}{GEN x, long n, GEN S, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqXQ_matrix_pow}{GEN x, long n, long m, GEN S, GEN T, ulong p} \fun{GEN}{FlxqXQ_autpow}{GEN a, long n, GEN S, GEN T, ulong p} as \kbd{FpXQXQ\_autpow} \fun{GEN}{FlxqXQ_autpow_pre}{GEN a, long n, GEN S, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqXQ_autsum}{GEN a, long n, GEN S, GEN T, ulong p} as \kbd{FpXQXQ\_autsum} \fun{GEN}{FlxqXQ_autsum_pre}{GEN a, long n, GEN S, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqXQ_auttrace}{GEN a, long n, GEN S, GEN T, ulong p} as \kbd{FpXQXQ\_auttrace} \fun{GEN}{FlxqXQ_auttrace_pre}{GEN a, long n, GEN S, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqXQ_halfFrobenius}{GEN A, GEN S, GEN T, ulong p}, as \kbd{FpXQXQ\_halfFrobenius} \fun{GEN}{FlxqXQ_minpoly}{GEN x, GEN S, GEN T, ulong p}, as \kbd{FpXQ\_minpoly} \fun{GEN}{FlxqXQ_minpoly_pre}{GEN x, GEN S, GEN T, ulong p, ulong pi} \subsec{\kbd{FlxqXn}} See \kbd{FpXn} operations. In this section, we assume \var{pi} is the pseudoinverse of $p$, or $0$ in which case we assume \kbd{SMALL\_ULONG}$(p)$. \fun{GEN}{FlxXn_red}{GEN a, long n} returns $a$ modulo $X^n$. \fun{GEN}{FlxqXn_mul}{GEN a, GEN b, long n, GEN T, ulong p} \fun{GEN}{FlxqXn_mul_pre}{GEN a, GEN b, long n, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqXn_sqr}{GEN a, long n, GEN T, ulong p} \fun{GEN}{FlxqXn_sqr_pre}{GEN a, long n, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqXn_inv}{GEN a, long n, GEN T, ulong p} \fun{GEN}{FlxqXn_inv_pre}{GEN a, long n, GEN T, ulong p, ulong pi} \fun{GEN}{FlxqXn_expint}{GEN a, long n, GEN T, ulong p} \fun{GEN}{FlxqXn_expint_pre}{GEN a, long n, GEN T, ulong p, ulong pi} \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{Preconditioned reduction} For faster reduction, the modulus \kbd{T} can be replaced by an extended modulus (\kbd{FlxT}) in all \kbd{Flxq}-classes functions, and in \kbd{Flx\_divrem}. \fun{GEN}{F2x_get_red}{GEN T} returns the extended modulus \kbd{eT}. To write code that works both with plain and extended moduli, the following accessors are defined: \fun{GEN}{get_F2x_mod}{GEN eT} returns the underlying modulus \kbd{T}. \fun{GEN}{get_F2x_var}{GEN eT} returns the variable number of the modulus. \fun{GEN}{get_F2x_degree}{GEN eT} returns the degree of the modulus. \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}{F2x_copy}{GEN x} \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}{F2v_to_F2x}{GEN x, long sv} \fun{GEN}{F2x_to_Flx}{GEN x} \fun{GEN}{F2x_to_F2xX}{GEN x, long sv} \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}{monomial_F2x}{long d, long sv} returns the \kbd{F2x} $X^d$ in variable $v$. \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{GEN}{F2x_recip}{GEN x} \fun{int}{F2x_equal1}{GEN x} \fun{int}{F2x_equal}{GEN x, GEN y} \fun{GEN}{F2x_1_add}{GEN y} returns \kbd{y+1} where \kbd{y} is a \kbd{Flx}. \fun{GEN}{F2x_add}{GEN x, GEN y} \fun{GEN}{F2x_mul}{GEN x, GEN y} \fun{GEN}{F2x_sqr}{GEN x} \fun{GEN}{F2x_divrem}{GEN x, GEN y, GEN *pr} \fun{GEN}{F2x_rem}{GEN x, GEN y} \fun{GEN}{F2x_div}{GEN x, GEN y} \fun{GEN}{F2x_renormalize}{GEN x, long lx} \fun{GEN}{F2x_deriv}{GEN x} \fun{GEN}{F2x_deflate}{GEN x, long d} \fun{ulong}{F2x_eval}{GEN P, ulong u} returns $P(u)$. \fun{void}{F2x_shift}{GEN x, long d} as \tet{RgX_shift} \fun{void}{F2x_even_odd}{GEN P, GEN *pe, GEN *po} as \tet{RgX_even_odd} \fun{long}{F2x_valrem}{GEN x, GEN *Z} \fun{GEN}{F2x_extgcd}{GEN a, GEN b, GEN *ptu, GEN *ptv} \fun{GEN}{F2x_gcd}{GEN a, GEN b} \fun{GEN}{F2x_halfgcd}{GEN a, GEN b} \fun{int}{F2x_issquare}{GEN x} returns $1$ if $x$ is a square of a \kbd{F2x} and $0$ otherwise. \fun{int}{F2x_is_irred}{GEN f}, as \tet{FpX_is_irred}. \fun{GEN}{F2x_degfact}{GEN f} as \tet{FpX_degfact}. \fun{GEN}{F2x_sqrt}{GEN x} returns the squareroot of $x$, assuming $x$ is a square of a \kbd{F2x}. \fun{GEN}{F2x_Frobenius}{GEN T} \fun{GEN}{F2x_matFrobenius}{GEN T} \fun{GEN}{F2x_factor}{GEN f} \fun{GEN}{F2x_factor_squarefree}{GEN f} \fun{GEN}{F2x_ddf}{GEN f} \fun{GEN}{F2x_Teichmuller}{GEN P, long n} Return a \kbd{ZX} $Q$ such that $P\equiv Q\pmod{2}$ and $Q(X^p)=0\pmod{Q,2^n}$. \subsec{\kbd{F2xq}} See \kbd{FpXQ} operations. \fun{GEN}{F2xq_mul}{GEN x, GEN y, GEN T} \fun{GEN}{F2xq_sqr}{GEN x, GEN T} \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 T} \fun{GEN}{F2xq_powu}{GEN x, ulong n, GEN T} \fun{GEN}{F2xq_pow_init}{GEN x, GEN n, long k, GEN T} \fun{GEN}{F2xq_pow_table}{GEN R, GEN n, GEN T} \fun{ulong}{F2xq_trace}{GEN x, GEN T} \fun{GEN}{F2xq_conjvec}{GEN x, GEN T} returns the vector of conjugates $[x,x^2,x^{2^2},\ldots,x^{2^{n-1}}]$ where $n$ is the degree of $T$. \fun{GEN}{F2xq_log}{GEN a, GEN g, GEN ord, GEN T} \fun{GEN}{F2xq_order}{GEN a, GEN ord, GEN T} \fun{GEN}{F2xq_Artin_Schreier}{GEN a, GEN T} returns a solution of $x^2+x=a$, assuming it exists. \fun{GEN}{F2xq_sqrt}{GEN a, GEN T} \fun{GEN}{F2xq_sqrt_fast}{GEN a, GEN s, GEN T} assuming that $s^2 \equiv x\pmod{T(x)}$, computes $b \equiv a(s)\pmod{T}$ so that $b^2=a$. \fun{GEN}{F2xq_sqrtn}{GEN a, GEN n, GEN T, GEN *zeta} \fun{GEN}{gener_F2xq}{GEN T, GEN *po} \fun{GEN}{F2xq_powers}{GEN x, long n, GEN T} \fun{GEN}{F2xq_matrix_pow}{GEN x, long m, long n, GEN T} \fun{GEN}{F2x_F2xq_eval}{GEN f, GEN x, GEN T} \fun{GEN}{F2x_F2xqV_eval}{GEN f, GEN x, GEN T}, see \kbd{FpX\_FpXQV\_eval}. \fun{GEN}{F2xq_autpow}{GEN a, long n, GEN T} computes $\sigma^n(X)$ assuming $a=\sigma(X)$ where $\sigma$ is an automorphism of the algebra $\F_2[X]/T(X)$. \fun{GEN}{F2xqV_roots_to_pol}{GEN V, GEN T, long v} as \kbd{FqV\_roots\_to\_pol} returning an \kbd{F2xqX} in variable $v$. \subsec{\kbd{F2xn}} See \kbd{FpXn} operations. \fun{GEN}{F2xn_red}{GEN a, long n} \fun{GEN}{F2xn_div}{GEN x, GEN y, long e} \fun{GEN}{F2xn_inv}{GEN x, long e} \subsec{\kbd{F2xqV}, \kbd{F2xqM}}. See \kbd{FqV}, \kbd{FqM} operations. \fun{GEN}{F2xqM_F2xqC_gauss}{GEN a, GEN b, GEN T} \fun{GEN}{F2xqM_F2xqC_invimage}{GEN a, GEN b, GEN T} \fun{GEN}{F2xqM_F2xqC_mul}{GEN a, GEN b, GEN T} \fun{GEN}{F2xqM_deplin}{GEN x, GEN T} \fun{GEN}{F2xqM_det}{GEN a, GEN T} \fun{GEN}{F2xqM_gauss}{GEN a, GEN b, GEN T} \fun{GEN}{F2xqM_image}{GEN x, GEN T} \fun{GEN}{F2xqM_indexrank}{GEN x, GEN T} \fun{GEN}{F2xqM_inv}{GEN a, GEN T} \fun{GEN}{F2xqM_invimage}{GEN a, GEN b, GEN T} \fun{GEN}{F2xqM_ker}{GEN x, GEN T} \fun{GEN}{F2xqM_mul}{GEN a, GEN b, GEN T} \fun{long}{F2xqM_rank}{GEN x, GEN T} \fun{GEN}{F2xqM_suppl}{GEN x, GEN T} \fun{GEN}{matid_F2xqM}{long n, GEN T} \subsec{\kbd{F2xX}}. See \kbd{FpXX} operations. \fun{GEN}{ZXX_to_F2xX}{GEN x, long v} \fun{GEN}{FlxX_to_F2xX}{GEN x} \fun{GEN}{F2xX_to_FlxX}{GEN B} \fun{GEN}{F2xX_to_F2xC}{GEN B, long N, long sv} \fun{GEN}{F2xXV_to_F2xM}{GEN B, long N, long sv} \fun{GEN}{F2xX_to_ZXX}{GEN B} \fun{GEN}{F2xX_renormalize}{GEN x, long lx} \fun{GEN}{F2xX_shift}{GEN a, long n, long sv}, as \kbd{RgX\_shift\_shallow}, where $v$ is the secondary variable. \fun{long}{F2xY_degreex}{GEN P} return the degree of $P$ with respect to the secondary variable. \fun{GEN}{pol1_F2xX}{long v, long sv} \fun{GEN}{polx_F2xX}{long v, long sv} \fun{GEN}{F2xX_add}{GEN x, GEN y} \fun{GEN}{F2xX_F2x_add}{GEN x, GEN y} \fun{GEN}{F2xX_F2x_mul}{GEN x, GEN y} \fun{GEN}{F2xX_deriv}{GEN P} returns the derivative of \kbd{P} with respect to the main variable. \fun{GEN}{Kronecker_to_F2xqX}{GEN z, GEN T} \fun{GEN}{F2xX_to_Kronecker}{GEN z, GEN T} \fun{GEN}{F2xY_F2xq_evalx}{GEN x, GEN y, GEN T} as \kbd{FpXY\_FpXQ\_evalx}. \fun{GEN}{F2xY_F2xqV_evalx}{GEN x, GEN V, GEN T} as \kbd{FpXY\_FpXQV\_evalx}. \subsec{\kbd{F2xXV/F2xXC}}. See \kbd{FpXXV} operations. \fun{GEN}{FlxXC_to_F2xXC}{GEN B} \fun{GEN}{F2xXC_to_ZXXC}{GEN B} \subsec{\kbd{F2xqX}}. See \kbd{FlxqX} operations. \subsubsec{Preconditioned reduction} For faster reduction, the modulus \kbd{S} can be replaced by an extended modulus, which is an \kbd{F2xqXT}, in all \kbd{F2xqXQ}-classes functions, and in \kbd{F2xqX\_rem} and \kbd{F2xqX\_divrem}. \fun{GEN}{F2xqX_get_red}{GEN S, GEN T} returns the extended modulus \kbd{eS}. To write code that works both with plain and extended moduli, the following accessors are defined: \fun{GEN}{get_F2xqX_mod}{GEN eS} returns the underlying modulus \kbd{S}. \fun{GEN}{get_F2xqX_var}{GEN eS} returns the variable number of the modulus. \fun{GEN}{get_F2xqX_degree}{GEN eS} returns the degree of the modulus. \subsubsec{basic functions} \fun{GEN}{random_F2xqX}{long d, long v, GEN T, ulong p} returns a random \kbd{F2xqX} in variable \kbd{v}, of degree less than~\kbd{d}. \fun{GEN}{F2xqX_red}{GEN z, GEN T} \fun{GEN}{F2xqX_normalize}{GEN z, GEN T} \fun{GEN}{F2xqX_F2xq_mul}{GEN P, GEN U, GEN T} \fun{GEN}{F2xqX_F2xq_mul_to_monic}{GEN P, GEN U, GEN T} \fun{GEN}{F2xqX_mul}{GEN x, GEN y, GEN T} \fun{GEN}{F2xqX_sqr}{GEN x, GEN T} \fun{GEN}{F2xqX_powu}{GEN x, ulong n, GEN T} \fun{GEN}{F2xqX_rem}{GEN x, GEN y, GEN T} \fun{GEN}{F2xqX_div}{GEN x, GEN y, GEN T} \fun{GEN}{F2xqX_divrem}{GEN x, GEN y, GEN T, GEN *pr} \fun{GEN}{F2xqXQ_inv}{GEN x, GEN S, GEN T} \fun{GEN}{F2xqXQ_invsafe}{GEN x, GEN S, GEN T} \fun{GEN}{F2xqX_invBarrett}{GEN T, GEN Q} \fun{GEN}{F2xqX_extgcd}{GEN x, GEN y, GEN T, GEN *ptu, GEN *ptv} \fun{GEN}{F2xqX_gcd}{GEN x, GEN y, GEN T} \fun{GEN}{F2xqX_halfgcd}{GEN x, GEN y, GEN T} \fun{GEN}{F2xqX_halfgcd_all}{GEN x, GEN y, GEN T, GEN *a, GEN *b} \fun{GEN}{F2xqX_resultant}{GEN x, GEN y, GEN T} \fun{GEN}{F2xqX_disc}{GEN x, GEN T} \fun{GEN}{F2xqXV_prod}{GEN V, GEN T} \fun{long}{F2xqX_ispower}{GEN f, ulong k, GEN T, GEN *pt} \fun{GEN}{F2xqX_F2xqXQ_eval}{GEN Q, GEN x, GEN S, GEN T} as \kbd{FpX\_FpXQ\_eval}. \fun{GEN}{F2xqX_F2xqXQV_eval}{GEN P, GEN V, GEN S, GEN T} as \kbd{FpX\_FpXQV\_eval}. \fun{GEN}{F2xqX_roots}{GEN f, GEN T} return the roots of \kbd{f} in $\F_2[X]/(T)$. Assumes \kbd{T} irreducible in $\F_2[X]$. \fun{GEN}{F2xqX_factor}{GEN f, GEN T} return the factorization of \kbd{f} over $\F_2[X]/(T)$. Assumes \kbd{T} irreducible in $\F_2[X]$. \fun{GEN}{F2xqX_factor_squarefree}{GEN f, GEN T} as \kbd{FlxqX\_factor\_squarefree}. \fun{GEN}{F2xqX_ddf}{GEN f, GEN T} as \kbd{FpX\_ddf}. \fun{GEN}{F2xqX_degfact}{GEN f, GEN T} as \kbd{FpX\_degfact}. \subsec{\kbd{F2xqXQ}}. See \kbd{FlxqXQ} operations. \fun{GEN}{FlxqXQ_inv}{GEN x, GEN S, GEN T} \fun{GEN}{FlxqXQ_invsafe}{GEN x, GEN S, GEN T} \fun{GEN}{F2xqXQ_mul}{GEN x, GEN y, GEN S, GEN T} \fun{GEN}{F2xqXQ_sqr}{GEN x, GEN S, GEN T} \fun{GEN}{F2xqXQ_pow}{GEN x, GEN n, GEN S, GEN T} \fun{GEN}{F2xqXQ_powers}{GEN x, long n, GEN S, GEN T} \fun{GEN}{F2xqXQ_autpow}{GEN a, long n, GEN S, GEN T} as \kbd{FpXQXQ\_autpow} \fun{GEN}{F2xqXQ_auttrace}{GEN a, long n, GEN S, GEN T}. Let $\sigma$ be the automorphism defined by $\sigma(X)=a[1]\pmod{T(X)}$ and $\sigma(Y)=a[2]\pmod{S(X,Y),T(X)}$; returns the vector $[\sigma^n(X),\sigma^n(Y),b+\sigma(b)+\ldots+\sigma^{n-1}(b)]$ where $b=a[3]$. \fun{GEN}{F2xqXQV_red}{GEN x, GEN S, GEN T} \subsec{Functions returning objects with \typ{INTMOD} coefficients} Those functions are mostly needed for interface reasons: \typ{INTMOD}s should not be used in library mode since the modular kernel is more flexible and more efficient, but GP users do not have access to the modular kernel. We document them for completeness: \fun{GEN}{Fp_to_mod}{GEN z, GEN p}, \kbd{z} a \typ{INT}. Returns \kbd{z * Mod(1,p)}, normalized. Hence the returned value is a \typ{INTMOD}. \fun{GEN}{FpX_to_mod}{GEN z, GEN p}, \kbd{z} a \kbd{ZX}. Returns \kbd{z * Mod(1,p)}, normalized. Hence the returned value has \typ{INTMOD} coefficients. \fun{GEN}{FpC_to_mod}{GEN z, GEN p}, \kbd{z} a \kbd{ZC}. Returns \kbd{Col(z) * Mod(1,p)}, a \typ{COL} with \typ{INTMOD} coefficients. \fun{GEN}{FpV_to_mod}{GEN z, GEN p}, \kbd{z} a \kbd{ZV}. Returns \kbd{Vec(z) * Mod(1,p)}, a \typ{VEC} with \typ{INTMOD} coefficients. \fun{GEN}{FpVV_to_mod}{GEN z, GEN p}, \kbd{z} a \kbd{ZVV}. Returns \kbd{Vec(z) * Mod(1,p)}, a \typ{VEC} of \typ{VEC} with \typ{INTMOD} coefficients. \fun{GEN}{FpM_to_mod}{GEN z, GEN p}, \kbd{z} a \kbd{ZM}. Returns \kbd{z * Mod(1,p)}, with \typ{INTMOD} coefficients. \fun{GEN}{F2c_to_mod}{GEN x} \fun{GEN}{F3c_to_mod}{GEN x} \fun{GEN}{F2m_to_mod}{GEN x} \fun{GEN}{F3m_to_mod}{GEN x} \fun{GEN}{Flc_to_mod}{GEN z} \fun{GEN}{Flm_to_mod}{GEN z} \fun{GEN}{FqC_to_mod}{GEN z, GEN T, GEN p} \fun{GEN}{FqM_to_mod}{GEN z, GEN T, GEN p} \fun{GEN}{FpXC_to_mod}{GEN V, GEN p} \fun{GEN}{FpXM_to_mod}{GEN V, GEN p} \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}{FpXQX_to_mod}{GEN P, GEN T, GEN p} $P$ being a \kbd{FpXQX}, converts each coefficient to a \typ{POLMOD} with \typ{INTMOD} coefficients. \fun{GEN}{FqX_to_mod}{GEN P, GEN T, GEN p} same but allow $\kbd{T} = \kbd{NULL}$. \fun{GEN}{FqXC_to_mod}{GEN P, GEN T, GEN p} \fun{GEN}{FqXM_to_mod}{GEN P, GEN T, GEN p} \fun{GEN}{QXQ_to_mod_shallow}{GEN x, GEN T} $x$ a \kbd{QXQ}, which is a lifted representative of elements of $\Q[X]/(T)$ (number field elements in most applications) and $T$ is in $\Z[X]$. Convert it to a \typ{POLMOD} modulo $T$; no reduction mod $T$ is attempted: the representatives should be already reduced. Shallow function. \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 nonrational 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}{QXQX_to_mod_shallow}{GEN P, GEN T} $P$ a polynomial with \kbd{QXQ} coefficients; replace them by \kbd{mkpolmod(.,T)}. Shallow function. \fun{GEN}{QXQC_to_mod_shallow}{GEN V, GEN T} $V$ a vector with \kbd{QXQ} coefficients; replace them by \kbd{mkpolmod(.,T)}. Shallow function. \fun{GEN}{QXQM_to_mod_shallow}{GEN M, GEN T} $M$ a matrix with \kbd{QXQ} coefficients; replace them by \kbd{mkpolmod(.,T)}. Shallow function. \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 a conversion function to map them to a finite field, 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}, (now) identical to \kbd{rootmod}. \fun{GEN}{rootmod0}{GEN f, GEN p, long flag}, (now) identical to \kbd{rootmod}; ignores \fl. \fun{GEN}{factmod}{GEN f, GEN p} applies \kbd{*\_factor}. \fun{GEN}{simplefactmod}{GEN f, GEN p} applies \kbd{*\_degfact}. \subsec{Slow Chinese remainder theorem over $\Z$} The routines in this section have quadratic time complexity with respect to the input size; see the routines in the next two sections for quasi-linear time variants. \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{ulong}{u_chinese_coprime}{ulong a, ulong b, ulong A, ulong B, ulong C}, as \kbd{Z\_chinese\_coprime} for \kbd{ulong} inputs and output. \fun{void}{Z_chinese_pre}{GEN A, GEN B, GEN *pC, GEN *pU, GEN *pd} initializes chinese remainder computations modulo $A$ and $B$. Sets \kbd{*pC} to $\lcm(A,B)$, \kbd{*pd} to $\gcd(A,B)$, \kbd{*pU} to an integer congruent to $0$ mod $(A/d)$ and $1$ mod $(B/d)$. It is allowed to set \kbd{pd = NULL}, in which case, $d$ is still computed, but not saved. \fun{GEN}{Z_chinese_post}{GEN a, GEN b, GEN C, GEN U, GEN d} returns the solution to the chinese remainder problem $x$ congruent to $a$ mod $A$ and $b$ mod $B$, where $C, U, d$ were set in \kbd{Z\_chinese\_pre}. If $d$ is \kbd{NULL}, assume the problem has a solution. Otherwise, return \kbd{NULL} if it has no solution. \medskip The following pair of functions is used in homomorphic imaging schemes, when reconstructing an integer from its images modulo pairwise coprime integers. The idea is as follows: we want to discover an integer $H$ which satisfies $|H| < B$ for some known bound $B$; we are given pairs $(H_p, p)$ with $H$ congruent to $H_p$ mod $p$ and all $p$ pairwise coprime. Given \kbd{H} congruent to $H_p$ modulo a number of $p$, whose product is $q$, and a new pair $(\kbd{Hp}, \kbd{p})$, \kbd{p} coprime to $q$, the following incremental functions use the chinese remainder theorem (CRT) to find a new \kbd{H}, congruent to the preceding one modulo $q$, but also to \kbd{Hp} modulo \kbd{p}. It is defined uniquely modulo $qp$, and we choose the centered representative. When $P$ is larger than $2B$, we have $\kbd{H} = H$, but of course, the value of \kbd{H} may stabilize sooner. In many applications it is possible to directly check that such a partial result is correct. \fun{GEN}{Z_init_CRT}{ulong Hp, ulong p} given a \kbd{Fl} \kbd{Hp} in $[0, p-1]$, returns the centered representative \kbd{H} congruent to \kbd{Hp} modulo \kbd{p}. \fun{int}{Z_incremental_CRT}{GEN *H, ulong Hp, GEN *q, ulong p} given a \typ{INT} \kbd{*H}, centered modulo \kbd{*q}, a new pair $(\kbd{Hp}, \kbd{p})$ with \kbd{p} coprime to \kbd{q}, this function updates \kbd{*H} so that it also becomes congruent to $(\kbd{Hp}, \kbd{p})$, and \kbd{*q} to the product$\kbd{qp} = \kbd{p} \cdot \kbd{*q}$. It returns $1$ if the new value is equal to the old one, and $0$ otherwise. \fun{GEN}{chinese1_coprime_Z}{GEN v} an alternative divide-and-conquer implementation: $v$ is a vector of \typ{INTMOD} with pairwise coprime moduli. Return the \typ{INTMOD} solving the corresponding chinese remainder problem. This is a streamlined version of \fun{GEN}{chinese1}{GEN v}, which solves a general chinese remainder problem (not necessarily over $\Z$, moduli not assumed coprime). As above, for $H$ a \kbd{ZM}: we assume that $H$ and all \kbd{Hp} have dimension $> 0$. The original \kbd{*H} is destroyed. \fun{GEN}{ZM_init_CRT}{GEN Hp, ulong p} \fun{int}{ZM_incremental_CRT}{GEN *H, GEN Hp, GEN *q, ulong p} As above for $H$ a \kbd{ZX}: note that the degree may increase or decrease. The original \kbd{*H} is destroyed. \fun{GEN}{ZX_init_CRT}{GEN Hp, ulong p, long v} \fun{int}{ZX_incremental_CRT}{GEN *H, GEN Hp, GEN *q, ulong p} As above, for $H$ a matrix whose coefficient are \kbd{ZX}. The original \kbd{*H} is destroyed. The entries of $H$ are not normalized, use \kbd{ZX\_renormalize} for this. \fun{GEN}{ZXM_init_CRT}{GEN Hp, long deg, ulong p} where \kbd{deg} is the maximal degree of all the \kbd{Hp} \fun{int}{ZXM_incremental_CRT}{GEN *H, GEN Hp, GEN *q, ulong p} \subsec{Fast remainders} The routines in these section are asymptotically fast (quasi-linear time in the input size). \fun{GEN}{Z_ZV_mod}{GEN A, GEN P} given a \typ{INT} $A$ and a vector $P$ of positive pairwise coprime integers of length $n\ge 1$, return a vector $B$ of the same length such that $B[i] = A\pmod{P[i]}$ and $0\leq B[i] < P[i]$ for all $1\leq i\leq n$. The vector $P$ may be a \typ{VEC} or a \typ{VECSMALL} (treated as \kbd{ulong}s) and $B$ has the same type as $P$. \fun{GEN}{Z_nv_mod}{GEN A, GEN P} given a \typ{INT} $A$ and a \typ{VECSMALL} $P$ of positive pairwise coprime integers of length $n\ge 1$, return a \typ{VECSMALL} $B$ of the same length such that $B[i]=A\pmod{P[i]}$ and $0\leq B[i] < P[i]$ for all $1\leq i\leq n$. The entries of $P$ and $B$ are treated as \kbd{ulong}s. The following low level functions allow precomputations: \fun{GEN}{ZV_producttree}{GEN P} where $P$ is a vector of integers (or \typ{VECSMALL}) of length $n\ge 1$, return the vector of \typ{VEC}s $[f(P),f^2(P),\ldots,f^k(P)]$ where $f$ is the transformation $[p_1,p_2,\ldots,p_m] \mapsto [p_1\*p_2,p_3\*p_4,\ldots,p_{m-1}\*p_m]$ if $m$ is even and $[p_1\*p_2,p_3\*p_4,\ldots,p_{m-2}\*p_{m-1},p_m]$ if $m$ is odd, and $k = O(\log m)$ is minimal so that $f^k(P)$ has length $1$; in other words, $f^k(P) = [p_1\*p_2\*\ldots\*p_m]$. \fun{GEN}{Z_ZV_mod_tree}{GEN A, GEN P, GEN T} as \kbd{Z\_ZV\_mod} where $T$ is the tree \kbd{ZV\_producttree(P)}. \fun{GEN}{ZV_nv_mod_tree}{GEN A, GEN P, GEN T} $A$ being a \kbd{ZV} and $P$ a \typ{VECSMALL} of length $n\ge 1$, the elements of $P$ being pairwise coprime, return the vector of \kbd{Flv} $[A \pmod{P[1]},\ldots,A \pmod{P[n]}]$, where $T$ is the tree \kbd{ZV\_producttree(P)}. \fun{GEN}{ZM_nv_mod_tree}{GEN A, GEN P, GEN T} $A$ being a \kbd{ZM} and $P$ a \typ{VECSMALL} of length $n\ge 1$, the elements of $P$ being pairwise coprime, return the vector of \kbd{Flm} $[A \pmod{P[1]},\ldots,A \pmod{P[n]}]$, where $T$ is the tree \kbd{ZV\_producttree(P)}. \fun{GEN}{ZX_nv_mod_tree}{GEN A, GEN P, GEN T} $A$ being a \kbd{ZX} and $P$ a \typ{VECSMALL} of length $n\ge 1$, the elements of $P$ being pairwise coprime, return the vector of \kbd{Flx} polynomials $[A \pmod{P[1]},\ldots,A \pmod{P[n]}]$, where $T$ is the tree \kbd{ZV\_producttree(P)}. \fun{GEN}{ZXC_nv_mod_tree}{GEN A, GEN P, GEN T} $A$ being a \kbd{ZXC} and $P$ a \typ{VECSMALL} of length $n\ge 1$, the elements of $P$ being pairwise coprime, return the vector of \kbd{FlxC} $[A \pmod{P[1]},\ldots,A \pmod{P[n]}]$, where $T$ is the tree \kbd{ZV\_producttree(P)}. \fun{GEN}{ZXM_nv_mod_tree}{GEN A, GEN P, GEN T} $A$ being a \kbd{ZXM} and $P$ a \typ{VECSMALL} of length $n\ge 1$, the elements of $P$ being pairwise coprime, return the vector of \kbd{FlxM} $[A \pmod{P[1]},\ldots,A \pmod{P[n]}]$, where $T$ is the tree \kbd{ZV\_producttree(P)}. \fun{GEN}{ZXX_nv_mod_tree}{GEN A, GEN P, GEN T, long v} $A$ being a \kbd{ZXX}, and $P$ a \typ{VECSMALL} of length $n\ge 1$, the elements of $P$ being pairwise coprime, return the vector of \kbd{FlxX} $[A \pmod{P[1]},\ldots,A \pmod{P[n]}]$, where $T$ is assumed to be the tree created by \kbd{ZV\_producttree(P)}. \medskip \subsec{Fast Chinese remainder theorem over $\Z$} The routines in these section are asymptotically fast (quasi-linear time in the input size) and should be used whenever the moduli are known from the start. The simplest function is \fun{GEN}{ZV_chinese}{GEN A, GEN P, GEN *pM} let $P$ be a vector of positive pairwise coprime integers, let $A$ be a vector of integers of the same length $n\ge 1$ such that $0 \leq A[i] < P[i]$ for all $i$, and let $M$ be the product of the elements of $P$. Returns the integer in $[0, M[$ congruent to $A[i]$ mod $P[i]$ for all $1\leq i\leq n$. If \kbd{pM} is not \kbd{NULL}, set \kbd{*pM} to $M$. We also allow \typ{VECSMALL}s for $A$ and $P$ (seen as vectors of unsigned integers). \fun{GEN}{ZV_chinese_center}{GEN A, GEN P, GEN *pM} As \kbd{ZV\_chinese} but return integers in $[-M/2, M/2[$ instead. The following functions allow to solve many Chinese remainder problems simultaneously, for a given set of moduli: \fun{GEN}{nxV_chinese_center}{GEN A, GEN P, GEN *pt_mod} where $A$ is a vector of \kbd{nx} and $P$ a \typ{VECSMALL} of the same length $n\ge 1$, the elements of $P$ being pairwise coprime, and $M$ being the product of the elements of $P$, returns the \typ{POL} whose entries are integers in $[-M/2, M/2[$ congruent to $A[i]$ mod $P[i]$ for all $1\leq i\leq n$. If \kbd{pt\_mod} is not \kbd{NULL}, set \kbd{*pt\_mod} to $M$. \fun{GEN}{ncV_chinese_center}{GEN A, GEN P, GEN *pM} where $A$ is a vector of \kbd{VECSMALL}s (seen as vectors of unsigned integers) and $P$ a \typ{VECSMALL} of the same length $n\ge 1$, the elements of $P$ being pairwise coprime, and $M$ being the product of the elements of $P$, returns the \typ{COL} whose entries are integers in $[-M/2, M/2[$ congruent to $A[i]$ mod $P[i]$ for all $1\leq i\leq n$. If \kbd{pM} is not \kbd{NULL}, set \kbd{*pt\_mod} to $M$. \fun{GEN}{nmV_chinese_center}{GEN A, GEN P, GEN *pM} where $A$ is a vector of \kbd{MATSMALL}s (seen as matrices of unsigned integers) and $P$ a \typ{VECSMALL} of the same length $n\ge 1$, the elements of $P$ being pairwise coprime, and $M$ being the product of the elements of $P$, returns the matrix whose entries are integers in $[-M/2, M/2[$ congruent to $A[i]$ mod $P[i]$ for all $1\leq i\leq n$. If \kbd{pM} is not \kbd{NULL}, set \kbd{*pM} to $M$. N.B.: this function uses the parallel GP interface. \fun{GEN}{nxCV_chinese_center}{GEN A, GEN P, GEN *pM} where $A$ is a vector of \kbd{nxC}s and $P$ a \typ{VECSMALL} of the same length $n\ge 1$, the elements of $P$ being pairwise coprime, and $M$ being the product of the elements of $P$, returns the \typ{COL} whose entries are integers in $[-M/2, M/2[$ congruent to $A[i]$ mod $P[i]$ for all $1\leq i\leq n$. If \kbd{pM} is not \kbd{NULL}, set \kbd{*pt\_mod} to $M$. \fun{GEN}{nxMV_chinese_center}{GEN A, GEN P, GEN *pM} where $A$ is a vector of \kbd{nxM}s and $P$ a \typ{VECSMALL} of the same length $n\ge 1$, the elements of $P$ being pairwise coprime, and $M$ being the product of the elements of $P$, returns the matrix whose entries are integers in $[-M/2, M/2[$ congruent to $A[i]$ mod $P[i]$ for all $1\leq i\leq n$. If \kbd{pM} is not \kbd{NULL}, set \kbd{*pM} to $M$. N.B.: this function uses the parallel GP interface. The other routines allow for various precomputations : \fun{GEN}{ZV_chinesetree}{GEN P, GEN T} given $P$ a vector of integers (or \typ{VECSMALL}) and a product tree $T$ from \tet{ZV_producttree}$(P)$ for the same $P$, return a ``chinese remainder tree'' $R$, preconditionning the solution of Chinese remainder problems modulo the $P[i]$. \fun{GEN}{ZV_chinese_tree}{GEN A, GEN P, GEN T, GEN R} return \kbd{ZV\_chinese}$(A,P,\kbd{NULL})$, where $T$ is created by \kbd{ZV\_producttree}$(P)$ and $R$ by \kbd{ZV\_chinesetree}$(P,T)$. \fun{GEN}{ncV_chinese_center_tree}{GEN A, GEN P, GEN T, GEN R} as \kbd{ncV\_chinese\_center} where $T$ is assumed to be the tree created by \kbd{ZV\_producttree(P)} and $R$ by \kbd{ZV\_chinesetree}$(P,T)$. \fun{GEN}{nmV_chinese_center_tree}{GEN A, GEN P, GEN T, GEN R} as \kbd{nmV\_chinese\_center} where $T$ is assumed to be the tree created by \kbd{ZV\_producttree(P)} and $R$ by \kbd{ZV\_chinesetree}$(P,T)$. \fun{GEN}{nxV_chinese_center_tree}{GEN A, GEN P, GEN T, GEN R} as \kbd{nxV\_chinese\_center} where $T$ is assumed to be the tree created by \kbd{ZV\_producttree(P)} and $R$ by \kbd{ZV\_chinesetree}$(P,T)$. \fun{GEN}{nxCV_chinese_center_tree}{GEN A, GEN P, GEN T, GEN R} as \kbd{nxCV\_chinese\_center} where $T$ is assumed to be the tree created by \kbd{ZV\_producttree(P)} and $R$ by \kbd{ZV\_chinesetree}$(P,T)$. \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 nonzero multiple $B$ of $b$, and $m = p^\ell$ is a prime power, for a prime $p$ chosen coprime to $B$ hence to $b$. Under the single assumption $\gcd(m,b) = 1$, if a solution $a,b$ exists satisfying the three conditions above, then it is unique. \fun{GEN}{FpM_ratlift}{GEN M, GEN m, GEN amax, GEN bmax, GEN denom} given an \kbd{FpM} modulo $m$ with reduced or \kbd{Fp\_center}-ed entries, reconstructs a matrix with rational coefficients by applying \kbd{Fp\_ratlift} to all entries. Assume that all preconditions for \kbd{Fp\_ratlift} are satisfied, as well $\gcd(m,b) = 1$ (so that the solution is unique if it exists). Return \kbd{NULL} if the reconstruction fails, and the rational matrix otherwise. If \kbd{denom} is not \kbd{NULL} check further that all denominators divide \kbd{denom}. The function is not stack clean if one of the coefficients of $M$ is negative (centered residues), but still suitable for \kbd{gerepileupto}. \fun{GEN}{FpX_ratlift}{GEN P, GEN m, GEN amax, GEN bmax, GEN denom} as \kbd{FpM\_ratlift}, where $P$ is an \kbd{FpX}. \fun{GEN}{FpC_ratlift}{GEN P, GEN m, GEN amax, GEN bmax, GEN denom} as \kbd{FpM\_ratlift}, where $P$ is an \kbd{FpC}. \subsec{Zp} \fun{GEN}{Zp_invlift}{GEN b, GEN a, GEN p, long e} let $p$ be a prime \typ{INT}, $a$ be a \typ{INT} and $b$ a \typ{INT} such that $a\*b \equiv 1 \mod p$. Returns an \typ{INT} $A$ such that $A \equiv a \pmod{p}$ and $A\*b \equiv 1 \mod p^e$. \fun{GEN}{Zp_inv}{GEN b, GEN p, long e} let $p$ be a prime \typ{INT} and $b$ be a \typ{INT} Returns an \typ{INT} $A$ such that $A\*b \equiv 1 \mod p^e$. \fun{GEN}{Zp_div}{GEN a, GEN b, GEN p, long e} let $p$ be a prime \typ{INT} and $a$ and $b$ be a \typ{INT} Returns an \typ{INT} $c$ such that $c\*b \equiv a \mod p^e$. \fun{GEN}{Zp_sqrt}{GEN b, GEN p, long e} $b$ and $p$ being \typ{INT}s, with $p$ a prime (possibly $2$), returns a \typ{INT} $a$ such that $a^2 \equiv b \mod p^e$. \fun{GEN}{Z2_sqrt}{GEN b, long e} $b$ being a \typ{INT}s returns a \typ{INT} $a$ such that $a^2 \equiv b \mod 2^e$. \fun{GEN}{Zp_sqrtlift}{GEN b, GEN a, GEN p, long e} let $a,b,p$ be \typ{INT}s, with $p > 2$, such that $a^2\equiv b\mod p$. Returns a \typ{INT} $A$ such that $A^2 \equiv b \mod p^e$. Special case of \tet{Zp_sqrtnlift}. \fun{GEN}{Zp_sqrtnlift}{GEN b, GEN n, GEN a, GEN p, long e} let $a,b,n,p$ be \typ{INT}s, with $n,p > 1$, and $p$ coprime to $n$, such that $a^n \equiv b \mod p$. Returns a \typ{INT} $A$ such that $A^n \equiv b \mod p^e$. Special case of \tet{ZpX_liftroot}. \fun{GEN}{Zp_teichmuller}{GEN x, GEN p, long e, GEN pe} for $p$ an odd prime, $x$ a \typ{INT} coprime to $p$, and $pe = p^e$, returns the $(p-1)$-th root of $1$ congruent to $x$ modulo $p$, modulo $p^e$. For convenience, $p = 2$ is also allowed and we return $1$ ($x$ is $1$ mod $4$) or $2^e - 1$ ($x$ is $3$ mod $4$). \fun{GEN}{teichmullerinit}{long p, long n} returns the values of \tet{Zp_teichmuller} at all $x = 1, \dots, p-1$. \fun{GEN}{Zp_exp}{GEN z, GEN p, ulong e} given a \typ{INT} $z$ (preferably reduced mod $p^e$), return $\exp_p(a)$ mod $p^e$ (\typ{INT}). \fun{GEN}{Zp_log}{GEN z, GEN p, ulong e} given a \typ{INT} $z$ (preferably reduced mod $p^e$), such that $a \equiv 1 \pmod{p}$, return $\log_p(a)$ mod $p^e$ (\typ{INT}). \subsec{ZpM} \fun{GEN}{ZpM_invlift}{GEN M, GEN Np, GEN p, long e} let $p$ be a prime \typ{INT}, $Np$ be a \kbd{FpM} (modulo $p$) and $M$ a \kbd{ZpM} such that $M\*Np \equiv 1 \mod p$. Returns an \kbd{ZpM} $N$ such that $N \equiv Np \pmod{p}$ and $M\*N \equiv 1 \mod p^e$. \subsec{ZpX} \fun{GEN}{ZpX_roots}{GEN f, GEN p, long e} $f$ a \kbd{ZX} with leading term prime to $p$, and without multiple roots mod $p$. Return a vector of \typ{INT}s which are the roots of $f$ mod $p^e$. \fun{GEN}{ZpX_liftroot}{GEN f, GEN a, GEN p, long e} $f$ a \kbd{ZX} with leading term prime to $p$, and $a$ a root mod $p$ such that $v_p(f'(a))=0$. Return a \typ{INT} which is the root of $f$ mod $p^e$ congruent to $a$ mod $p$. \fun{GEN}{ZX_Zp_root}{GEN f, GEN a, GEN p, long e} same as \tet{ZpX_liftroot} without the assumption $v_p(f'(a)) = 0$. Return a \typ{VEC} of \typ{INT}s, which are the $p$-adic roots of $f$ congruent to $a$ mod $p$ (given modulo $p^e$). Assume that $0 \leq a < p$. \fun{GEN}{ZpX_liftroots}{GEN f, GEN S, GEN p, long e} $f$ a \kbd{ZX} with leading term prime to $p$, and $S$ a vector of simple roots mod $p$. Return a vector of \typ{INT}s which are the root of $f$ mod $p^e$ congruent to the $S[i]$ mod $p$. \fun{GEN}{ZpX_liftfact}{GEN A, GEN B, GEN pe, GEN p, long e} is the routine underlying \tet{polhensellift}. Here, $p$ is prime defines a finite field $\F_p$. $A$ is a polynomial in $\Z[X]$, whose leading coefficient is nonzero in $\F_q$. $B$ is a vector of monic \kbd{FpX}, pairwise coprime in $\F_p[X]$, whose product is congruent to $A/\text{lc}(A)$ in $\F_p[X]$. Lifts the elements of $B$ mod $\kbd{pe} = p^e$. \fun{GEN}{ZpX_Frobenius}{GEN T, GEN p, ulong e} returns the $p$-adic lift of the Frobenius automorphism of $\F_p[X]/(T)$ to precision $e$. \fun{long}{ZpX_disc_val}{GEN f, GEN p} returns the valuation at $p$ of the discriminant of $f$. Assume that $f$ is a monic \emph{separable} \kbd{ZX} and that $p$ is a prime number. Proceeds by dynamically increasing the $p$-adic accuracy; infinite loop if the discriminant of $f$ is $0$. \fun{long}{ZpX_resultant_val}{GEN f, GEN g, GEN p, long M} returns the valuation at $p$ of $\text{Res}(f,g)$. Assume $f,g$ are both \kbd{ZX}, and that $p$ is a prime number coprime to the leading coefficient of $f$. Proceeds by dynamically increasing the $p$-adic accuracy. To avoid an infinite loop when the resultant is $0$, we return $M$ if the Sylvester matrix mod $p^M$ still does not have maximal rank. \fun{GEN}{ZpX_gcd}{GEN f,GEN g, GEN p, GEN pm} $f$ a monic \kbd{ZX}, $g$ a \kbd{ZX}, $\kbd{pm} = p^m$ a prime power. There is a unique integer $r\geq 0$ and a monic $h\in \Q_p[X]$ such that $$p^rh\Z_p[X] + p^m\Z_p[X] = f\Z_p[X] + g\Z_p[X] + p^m\Z_p[X].$$ Return the $0$ polynomial if $r\geq m$ and a monic $h\in\Z[1/p][X]$ otherwise (whose valuation at $p$ is $> -m$). \fun{GEN}{ZpX_reduced_resultant}{GEN f, GEN g, GEN p, GEN pm} $f$ a monic \kbd{ZX}, $g$ a \kbd{ZX}, $\kbd{pm} = p^m$ a prime power. The $p$-adic \emph{reduced resultant}\varsidx{resultant (reduced)} of $f$ and $g$ is $0$ if $f$, $g$ not coprime in $\Z_p[X]$, and otherwise the generator of the form $p^d$ of $$ (f\Z_p[X] + g\Z_p[X])\cap \Z_p. $$ Return the reduced resultant modulo $p^m$. \fun{GEN}{ZpX_reduced_resultant_fast}{GEN f, GEN g, GEN p, long M} $f$ a monic \kbd{ZX}, $g$ a \kbd{ZX}, $p$ a prime. Returns the $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 nonzero result. It is very inefficient when the resultant is $0$, but otherwise usually more efficient than computations using a priori bounds. \fun{GEN}{ZpX_monic_factor}{GEN f, GEN p, long M} $f$ a monic \kbd{ZX}, $p$ a prime, return the $p$-adic factorization of $f$, modulo $p^M$. This is the underlying low-level recursive function behind \kbd{factorpadic} (using a combination of Round 4 factorization and Hensel lifting); the factors are not sorted and the function is not \kbd{gerepile}-clean. \fun{GEN}{ZpX_primedec}{GEN T, GEN p} $T$ a monic separable \kbd{ZX}, $p$ a prime, return as a factorization matrix the shape of the prime ideal decomposition of $(p)$ in $\Q[X]/(T)$: the first column contains inertia degrees, the second columns contains ramification degrees. \subsec{ZpXQ} \fun{GEN}{ZpXQ_invlift}{GEN b, GEN a, GEN T, GEN p, long e} let $p$ be a prime \typ{INT}, $a$ be a \kbd{FpXQ} (modulo $(p, T)$) and $b$ a \kbd{ZpXQ} such that $a\*b \equiv 1 \mod (p, T)$. Returns an \kbd{ZpXQ} $A$ such that $A \equiv a \pmod{p}$ and $A\*b \equiv 1 \mod (p^e, T)$. \fun{GEN}{ZpXQ_inv}{GEN b, GEN T, GEN p, long e} let $p$ be a prime \typ{INT} and $b$ be a \kbd{FpXQ} (modulo $T, p^e$). Returns an \kbd{FpXQ} $A$ such that $A\*b \equiv 1 \mod (p^e, T)$. \fun{GEN}{ZpXQ_div}{GEN a, GEN b, GEN T, GEN q, GEN p, long e} let $p$ be a prime \typ{INT} and $a$ and $b$ be a \kbd{FpXQ} (modulo $T, p^e$). Returns an \kbd{FpXQ} $c$ such that $c\*b \equiv a \mod (p^e, T)$. The parameter $q$ must be equal to $p^e$. \fun{GEN}{ZpXQ_sqrtnlift}{GEN b, GEN n, GEN a, GEN T, GEN p, long e} let $n,p$ be \typ{INT}s, with $n,p > 1$ and $p$ coprime to $n$, and $a,b$ be \kbd{FpXQ}s (modulo $T$) such that $a^n \equiv b \mod (p,T)$. Returns an \kbd{Fq} $A$ such that $A^n \equiv b \mod (p^e, T)$. \fun{GEN}{ZpXQ_sqrt}{GEN b, GEN T, GEN p, long e} let $p$ being a odd prime and $b$ be a \kbd{FpXQ} (modulo $T, p^e$), returns $a$ such that $a^2 \equiv b \mod (p^e, T)$. \fun{GEN}{ZpX_ZpXQ_liftroot}{GEN f, GEN a, GEN T, GEN p, long e} as \tet{ZpXQX_liftroot}, but $f$ is a polynomial in $\Z[X]$. \fun{GEN}{ZpX_ZpXQ_liftroot_ea}{GEN f, GEN a, GEN T, GEN p, long e, void *E, GEN early(void *E, GEN x, GEN q)} as \tet{ZpX_ZpXQ_liftroot} with early abort: the function \kbd{early(E,x,q)} will be called with $x$ is a root of $f$ modulo $q=p^n$ for some $n$. If \kbd{early} returns a non-\kbd{NULL} value $z$, the function returns $z$ immediately. \fun{GEN}{ZpXQ_log}{GEN a, GEN T, GEN p, long e} $T$ being a \kbd{ZpX} irreducible modulo $p$, return the logarithm of $a$ in $\Z_p[X]/(T)$ to precision $e$, assuming that $a\equiv 1 \pmod{p\Z_p[X]}$ if $p$ odd or $a\equiv 1 \pmod{4\Z_2[X]}$ if $p=2$. \subsec{Zq} \fun{GEN}{Zq_sqrtnlift}{GEN b, GEN n, GEN a, GEN T, GEN p, long e} \subsec{ZpXQM} \fun{GEN}{ZpXQM_prodFrobenius}{GEN M, GEN T, GEN p, long e} returns the product of matrices $M\*\sigma(M)\*\sigma^2(M)\ldots\sigma^{n-1}(M)$ to precision $e$ where $\sigma$ is the lift of the Frobenius automorphism over $\Z_p[X]/(T)$ and $n$ is the degree of $T$. \subsec{ZpXQX} \fun{GEN}{ZpXQX_liftfact}{GEN A, GEN B, GEN T, GEN pe, GEN p, long e} is the routine underlying \tet{polhensellift}. Here, $p$ is prime, $T(Y)$ defines a finite field $\F_q$. $A$ is a polynomial in $\Z[X,Y]$, whose leading coefficient is nonzero in $\F_q$. $B$ is a vector of monic 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)$. \fun{GEN}{ZpXQX_liftroot}{GEN f, GEN a, GEN T, GEN p, long e} as \tet{ZpX_liftroot}, but $f$ is now a polynomial in $\Z[X,Y]$ and lift the root $a$ in the unramified extension of $\Q_p$ with residue field $\F_p[Y]/(T)$, assuming $v_p(f(a))>0$ and $v_p(f'(a))=0$. \fun{GEN}{ZpXQX_liftroot_vald}{GEN f, GEN a, long v, GEN T, GEN p, long e} returns the foots of $f$ as \tet{ZpXQX_liftroot}, where $v$ is the valuation of the content of $f'$ and it is required that $v_p(f(a))>v$ and $v_p(f'(a))=v$. \fun{GEN}{ZpXQX_roots}{GEN F, GEN T, GEN p, long e} \fun{GEN}{ZpXQX_liftroots}{GEN F, GEN S, GEN T, GEN p, long e} \fun{GEN}{ZpXQX_divrem}{GEN x, GEN Sp, GEN T,GEN q,GEN p,long e, GEN *pr} as \kbd{FpXQX\_divrem}. The parameter $q$ must be equal to $p^e$. \fun{GEN}{ZpXQX_digits}{GEN x, GEN B, GEN T, GEN q, GEN p, long e} As \kbd{FpXQX\_digits}. The parameter $q$ must be equal to $p^e$. \fun{GEN}{ZpXQX_ZpXQXQ_liftroot}{GEN f, GEN a, GEN S, GEN T, GEN p, long e} as \tet{ZpXQX_liftroot}, except that $a$ is an element of $\Z_p[X,Y]/(S(X,Y),T(X))$. \subsec{ZqX} \kbd{ZqX} are either \kbd{ZpX} or \kbd{ZpXQX} depending whether \kbd{T} is \kbd{NULL} or not. \fun{GEN}{ZqX_roots}{GEN F, GEN T, GEN p, long e} \fun{GEN}{ZqX_liftfact}{GEN A, GEN B, GEN T, GEN pe, GEN p, long e} \fun{GEN}{ZqX_liftroot}{GEN f, GEN a, GEN T, GEN p, long e} \fun{GEN}{ZqX_ZqXQ_liftroot}{GEN f, GEN a, GEN P, GEN T, GEN p, long e} \subsec{Other $p$-adic functions} \fun{GEN}{ZpM_echelon}{GEN M, long early_abort, GEN p, GEN pm} given a \kbd{ZM} $M$, a prime $p$ and $\kbd{pm} = p^m$, returns an echelon form $E$ for $M$ mod $p^m$. I.e. there exist a square integral matrix $U$ with $\det U$ coprime to $p$ such that $E = MU$ modulo $p^m$. I \kbd{early\_abort} is nonzero, return NULL as soon as one pivot in the echelon form is divisible by $p^m$. The echelon form is an upper triangular HNF, we do not waste time to reduce it to Gauss-Jordan form. \fun{GEN}{zlm_echelon}{GEN M, long early_abort, ulong p, ulong pm} variant of \kbd{ZpM\_echelon}, for a \kbd{Zlm} $M$. \fun{GEN}{ZlM_gauss}{GEN a, GEN b, ulong p, long e, GEN C} as \kbd{gauss} with the following peculiarities: $a$ and $b$ are \kbd{ZM}, such that $a$ is invertible modulo $p$. Optional $C$ is an \kbd{Flm} that is an inverse of $a\mod p$ or \kbd{NULL}. Return the matrix $x$ such that $ax=b\mod p^e$ and all elements of $x$ are in $[0,p^e-1]$. For efficiency, it is better to reduce $a$ and $b$ mod $p^e$ first. \fun{GEN}{padic_to_Q}{GEN x} truncate the \typ{PADIC} to a \typ{INT} or \typ{FRAC}. \fun{GEN}{padic_to_Q_shallow}{GEN x} shallow version of \tet{padic_to_Q} \fun{GEN}{QpV_to_QV}{GEN v} apply \tet{padic_to_Q_shallow} \fun{long}{padicprec}{GEN x, GEN p} returns the absolute $p$-adic precision of the object $x$, by definition the minimum precision of the components of $x$. For a nonzero \typ{PADIC}, this returns \kbd{valp(x) + precp(x)}. \fun{long}{padicprec_relative}{GEN x} returns the relative $p$-adic precision of the \typ{INT}, \typ{FRAC}, or \typ{PADIC} $x$ (minimum precision of the components of $x$ for \typ{POL} or vector/matrices). For a \typ{PADIC}, this returns \kbd{precp(x)} if $x\neq0$, and $0$ for $x=0$. \subsubsec{low-level} The following technical function returns an optimal sequence of $p$-adic accuracies, for a given target accuracy: \fun{ulong}{quadratic_prec_mask}{long n} we want to reach accuracy $n\geq 1$, starting from accuracy 1, using a quadratically convergent, self-correcting, algorithm; in other words, from inputs correct to accuracy $l$ one iteration outputs a result correct to accuracy $2l$. For instance, to reach $n = 9$, we want to use accuracies $[1,2,3,5,9]$ instead of $[1,2,4,8,9]$. The idea is to essentially double the accuracy at each step, and not overshoot in the end. Let $a_0$ = 1, $a_1 = 2, \ldots, a_k = n$, be the desired sequence of accuracies. To obtain it, we work backwards and set $$ a_k = n,\quad a_{i-1} = (a_i + 1)\,\bs\, 2.$$ This is in essence what the function returns. But we do not want to store the $a_i$ explicitly, even as a \typ{VECSMALL}, since this would leave an object on the stack. Instead, we store $a_i$ implicitly in a bitmask \kbd{MASK}: let $a_0 = 1$, if the $i$-th bit of the mask is set, set $a_{i+1} = 2a_i - 1$, and $2a_i$ otherwise; in short the bits indicate the places where we do something special and do not quite double the accuracy (which would be the straightforward thing to do). In fact, to avoid returning separately the mask and the sequence length $k+1$, the function returns $\kbd{MASK} + 2^{k+1}$, so the highest bit of the mask indicates the length of the sequence, and the following ones give an algorithm to obtain the accuracies. This is much simpler than it sounds, here is what it looks like in practice: \bprog ulong mask = quadratic_prec_mask(n); long l = 1; while (mask > 1) { /* here, the result is known to accuracy l */ l = 2*l; if (mask & 1) l--; /* new accuracy l for the iteration */ mask >>= 1; /* pop low order bit */ /* ... lift to the new accuracy ... */ } /* we are done. At this point l = n */ @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{Conversions involving single precision objects} \subsubsec{To single precision} \fun{ulong}{Rg_to_Fl}{GEN z, ulong p}, \kbd{z} which can be mapped to $\Z/p\Z$: a \typ{INT}, a \typ{INTMOD} whose modulus is divisible by $p$, a \typ{FRAC} whose denominator is coprime to $p$, or a \typ{PADIC} with underlying prime $\ell$ satisfying $p = \ell^n$ for some $n$ (less than the accuracy of the input). Returns \kbd{lift(z * Mod(1,p))}, normalized, as an \kbd{Fl}. \fun{ulong}{Rg_to_F2}{GEN z}, as \tet{Rg_to_Fl} for $p = 2$. \fun{ulong}{padic_to_Fl}{GEN x, ulong p} special case of \tet{Rg_to_Fl}, for a $x$ a \typ{PADIC}. \fun{GEN}{RgX_to_F2x}{GEN x}, \kbd{x} a \typ{POL}, returns the \kbd{F2x} obtained by applying \kbd{Rg\_to\_Fl} coefficientwise. \fun{GEN}{RgX_to_Flx}{GEN x, ulong p}, \kbd{x} a \typ{POL}, returns the \kbd{Flx} obtained by applying \kbd{Rg\_to\_Fl} coefficientwise. \fun{GEN}{RgXV_to_FlxV}{GEN x, ulong p}, \kbd{x} a vector, returns the \kbd{FlxV} obtained by applying \kbd{RgX\_to\_Flx} coefficientwise. \fun{GEN}{Rg_to_F2xq}{GEN z, GEN T}, \kbd{z} a \kbd{GEN} which can be mapped to $\F_2[X]/(T)$: anything \kbd{Rg\_to\_Fl} can be applied to, a \typ{POL} to which \kbd{RgX\_to\_F2x} can be applied to, a \typ{POLMOD} whose modulus is divisible by $T$ (once mapped to a \kbd{F2x}), a suitable \typ{RFRAC}. Returns \kbd{z} as an \kbd{F2xq}, normalized. \fun{GEN}{Rg_to_Flxq}{GEN z, GEN T, ulong p}, \kbd{z} a \kbd{GEN} which can be mapped to $\F_p[X]/(T)$: anything \kbd{Rg\_to\_Fl} can be applied to, a \typ{POL} to which \kbd{RgX\_to\_Flx} can be applied to, a \typ{POLMOD} whose modulus is divisible by $T$ (once mapped to a \kbd{Flx}), a suitable \typ{RFRAC}. Returns \kbd{z} as an \kbd{Flxq}, normalized. \fun{GEN}{RgX_to_FlxqX}{GEN z, GEN T, ulong p}, \kbd{z} a \kbd{GEN} which can be mapped to $\F_p[x]/(T)[X]$: anything \kbd{Rg\_to\_Flxq} can be applied to, a \typ{POL} to which \kbd{RgX\_to\_Flx} can be applied to, a \typ{POLMOD} whose modulus is divisible by $T$ (once mapped to a \kbd{Flx}), a suitable \typ{RFRAC}. Returns \kbd{z} as an \kbd{FlxqX}, normalized. \fun{GEN}{ZX_to_Flx}{GEN x, ulong p} reduce \kbd{ZX}~\kbd{x} modulo \kbd{p} (yielding an \kbd{Flx}). Faster than \kbd{RgX\_to\_Flx}. \fun{GEN}{ZV_to_Flv}{GEN x, ulong p} reduce \kbd{ZV}~\kbd{x} modulo \kbd{p} (yielding an \kbd{Flv}). \fun{GEN}{ZXV_to_FlxV}{GEN v, ulong p}, as \kbd{ZX\_to\_Flx}, repeatedly called on the vector's coefficients. \fun{GEN}{ZXT_to_FlxT}{GEN v, ulong p}, as \kbd{ZX\_to\_Flx}, repeatedly called on the tree leaves. \fun{GEN}{ZXX_to_FlxX}{GEN B, ulong p, long v}, as \kbd{ZX\_to\_Flx}, repeatedly called on the polynomial's coefficients. \fun{GEN}{zxX_to_FlxX}{GEN z, ulong p} as \kbd{zx\_to\_Flx}, repeatedly called on the polynomial's coefficients. \fun{GEN}{ZXXV_to_FlxXV}{GEN V, ulong p, long v}, as \kbd{ZXX\_to\_FlxX}, repeatedly called on the vector's coefficients. \fun{GEN}{ZXXT_to_FlxXT}{GEN V, ulong p, long v}, as \kbd{ZXX\_to\_FlxX}, repeatedly called on the tree leaves. \fun{GEN}{RgV_to_Flv}{GEN x, ulong p} reduce the \typ{VEC}/\typ{COL} $x$ modulo $p$, yielding a \typ{VECSMALL}. \fun{GEN}{RgM_to_Flm}{GEN x, ulong p} reduce the \typ{MAT} $x$ modulo $p$. \fun{GEN}{ZM_to_Flm}{GEN x, ulong p} reduce \kbd{ZM}~$x$ modulo $p$ (yielding an \kbd{Flm}). \fun{GEN}{ZXC_to_FlxC}{GEN x, ulong p, long sv} reduce \kbd{ZXC}~$x$ modulo $p$ (yielding an \kbd{FlxC}). Assume that \kbd{sv = evalvarn(v)} where $v$ is the variable number of the entries of $x$. It is allowed for the entries of $x$ to be \typ{INT}. \fun{GEN}{ZXM_to_FlxM}{GEN x, ulong p, long sv} reduce \kbd{ZXM}~$x$ modulo $p$ (yielding an \kbd{FlxM}). Assume that \kbd{sv = evalvarn(v)} where $v$ is the variable number of the entries of $x$. It is allowed for the entries of $x$ to be \typ{INT}. \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} \subsubsec{From single precision} \fun{GEN}{Flx_to_ZX}{GEN z}, converts to \kbd{ZX} (\typ{POL} of nonnegative \typ{INT}s in this case) \fun{GEN}{Flx_to_FlxX}{GEN z}, converts to \kbd{FlxX} (\typ{POL} of constant \kbd{Flx} in this case). \fun{GEN}{Flx_to_ZX_inplace}{GEN z}, same as \kbd{Flx\_to\_ZX}, in place (\kbd{z} is destroyed). \fun{GEN}{FlxX_to_ZXX}{GEN B}, converts an \kbd{FlxX} to a polynomial with \kbd{ZX} or \typ{INT} coefficients (repeated calls to \kbd{Flx\_to\_ZX}). \fun{GEN}{FlxXC_to_ZXXC}{GEN B}, converts an \kbd{FlxXC} to a \typ{COL} with \kbd{ZXX} coefficients (repeated calls to \kbd{FlxX\_to\_ZXX}). \fun{GEN}{FlxXM_to_ZXXM}{GEN B}, converts an \kbd{FlxXM} to a \typ{MAT} with \kbd{ZXX} coefficients (repeated calls to \kbd{FlxX\_to\_ZXX}). \fun{GEN}{FlxC_to_ZXC}{GEN x}, converts a vector of \kbd{Flx} to a column vector of polynomials with \typ{INT} coefficients (repeated calls to \kbd{Flx\_to\_ZX}). \fun{GEN}{FlxV_to_ZXV}{GEN x}, as above but return a \typ{VEC}. \fun{void}{F2xV_to_FlxV_inplace}{GEN v} v is destroyed. \fun{void}{F2xV_to_ZXV_inplace}{GEN v} v is destroyed. \fun{void}{FlxV_to_ZXV_inplace}{GEN v} v is destroyed. \fun{GEN}{FlxM_to_ZXM}{GEN z}, converts a matrix of \kbd{Flx} to a matrix of polynomials with \typ{INT} coefficients (repeated calls to \kbd{Flx\_to\_ZX}). \fun{GEN}{zx_to_ZX}{GEN z}, as \kbd{Flx\_to\_ZX}, without assuming the coefficients to be nonnegative. \fun{GEN}{zx_to_Flx}{GEN z, ulong p} as \kbd{Flx\_red} without assuming the coefficients to be nonnegative. \fun{GEN}{Flc_to_ZC}{GEN z}, converts to \kbd{ZC} (\typ{COL} of nonnegative \typ{INT}s in this case) \fun{GEN}{Flc_to_ZC_inplace}{GEN z}, same as \kbd{Flc\_to\_ZC}, in place (\kbd{z} is destroyed). \fun{GEN}{Flv_to_ZV}{GEN z}, converts to \kbd{ZV} (\typ{VEC} of nonnegative \typ{INT}s in this case) \fun{GEN}{Flm_to_ZM}{GEN z}, converts to \kbd{ZM} (\typ{MAT} with nonnegative \typ{INT}s coefficients in this case) \fun{GEN}{Flm_to_ZM_inplace}{GEN z}, same as \kbd{Flm\_to\_ZM}, in place (\kbd{z} is destroyed). \fun{GEN}{zc_to_ZC}{GEN z} as \kbd{Flc\_to\_ZC}, without assuming coefficients are nonnegative. \fun{GEN}{zv_to_ZV}{GEN z} as \kbd{Flv\_to\_ZV}, without assuming coefficients are nonnegative. \fun{GEN}{zm_to_ZM}{GEN z} as \kbd{Flm\_to\_ZM}, without assuming coefficients are nonnegative. \fun{GEN}{zv_to_Flv}{GEN z, ulong p} \fun{GEN}{zm_to_Flm}{GEN z, ulong p} \subsubsec{Mixed precision linear algebra} Assumes dimensions are compatible. Multiply a multiprecision object by a single-precision one. \fun{GEN}{RgM_zc_mul}{GEN x, GEN y} \fun{GEN}{RgMrow_zc_mul}{GEN x, GEN y, long i} \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}{zv_ZM_mul}{GEN x, GEN y} \fun{GEN}{ZV_zc_mul}{GEN x, GEN y} \fun{GEN}{ZM_zm_mul}{GEN x, GEN y} \fun{GEN}{ZC_z_mul}{GEN x, long y} \fun{GEN}{ZM_nm_mul}{GEN x, GEN y} the entries of $y$ are \kbd{ulong}s. \fun{GEN}{nm_Z_mul}{GEN y, GEN c} the entries of $y$ are \kbd{ulong}s. \subsubsec{Miscellaneous involving Fl} \fun{GEN}{Fl_to_Flx}{ulong x, long evx} converts a \kbd{unsigned long} to a scalar \kbd{Flx}. Assume that \kbd{evx = evalvarn(vx)} for some variable number \kbd{vx}. \fun{GEN}{Z_to_Flx}{GEN x, ulong p, long sv} converts a \typ{INT} to a scalar \kbd{Flx} polynomial. Assume that \kbd{sv = evalvarn(v)} for some variable number \kbd{v}. \fun{GEN}{Flx_to_Flv}{GEN x, long n} converts from \kbd{Flx} to \kbd{Flv} with \kbd{n} components (assumed larger than the number of coefficients of \kbd{x}). \fun{GEN}{zx_to_zv}{GEN x, long n} as \kbd{Flx\_to\_Flv}. \fun{GEN}{Flv_to_Flx}{GEN x, long sv} converts from vector (coefficient array) to (normalized) polynomial in variable $v$. \fun{GEN}{zv_to_zx}{GEN x, long n} as \kbd{Flv\_to\_Flx}. \fun{GEN}{Flm_to_FlxV}{GEN x, long sv} converts the columns of \kbd{Flm}~\kbd{x} to an array of \kbd{Flx} in the variable $v$ (repeated calls to \kbd{Flv\_to\_Flx}). \fun{GEN}{FlxM_to_FlxXV}{GEN V, long v} see \kbd{RgM\_to\_RgXV} \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_Flx}{GEN P} Let $P(x,X)$ be a \kbd{FlxX}, return $P(0,X)$ as a \kbd{Flx}. \fun{GEN}{FlxX_to_Flm}{GEN v, long n} reverse \kbd{Flm\_to\_FlxX}, to obtain an \kbd{Flm} with \kbd{n} rows (repeated calls to \kbd{Flx\_to\_Flv}). \fun{GEN}{FlxX_to_FlxC}{GEN B, long n, long sv} see \kbd{RgX\_to\_RgV}. The coefficients of \kbd{B} are assumed to be in the variable $v$. \fun{GEN}{FlxV_to_FlxX}{GEN x, long v} see \kbd{RgV\_to\_RgX}. \fun{GEN}{FlxXV_to_FlxM}{GEN V, long n, long sv} see \kbd{RgXV\_to\_RgM}. The coefficients of \kbd{V[i]} are assumed to be in the variable $v$. \fun{GEN}{Fly_to_FlxY}{GEN a, long sv} convert coefficients of \kbd{a} to constant \kbd{Flx} in variable $v$. \subsubsec{Miscellaneous involving \kbd{F2x}} \fun{GEN}{F2x_to_F2v}{GEN x, long n} converts from \kbd{F2x} to \kbd{F2v} with \kbd{n} components (assumed larger than the number of coefficients of \kbd{x}). \fun{GEN}{F2xC_to_ZXC}{GEN x}, converts a vector of \kbd{F2x} to a column vector of polynomials with \typ{INT} coefficients (repeated calls to \kbd{F2x\_to\_ZX}). \fun{GEN}{F2xC_to_FlxC}{GEN x} \fun{GEN}{FlxC_to_F2xC}{GEN x} \fun{GEN}{F2xV_to_F2m}{GEN v, long n} \kbd{F2x\_to\_F2v} to each polynomial to get an \kbd{F2m} with \kbd{n} rows. \section{Higher arithmetic over $\Z$: primes, factorization} \subsec{Pure powers} \fun{long}{Z_issquare}{GEN n} returns $1$ if the \typ{INT} $n$ is a square, and $0$ otherwise. This is tested first modulo small prime powers, then \kbd{sqrtremi} is called. \fun{long}{Z_issquareall}{GEN n, GEN *sqrtn} as \kbd{Z\_issquare}. If $n$ is indeed a square, set \kbd{sqrtn} to its integer square root. Uses a fast congruence test mod $64\times 63\times 65\times 11$ before computing an integer square root. \fun{long}{Z_ispow2}{GEN x} returns $1$ if the \typ{INT} $x$ is a power of $2$, and $0$ otherwise. \fun{long}{uissquare}{ulong n} as \kbd{Z\_issquare}, for an \kbd{ulong} operand \kbd{n}. \fun{long}{uissquareall}{ulong n, ulong *sqrtn} as \kbd{Z\_issquareall}, for an \kbd{ulong} operand \kbd{n}. \fun{ulong}{usqrt}{ulong a} returns the floor of the square root of $a$. \fun{ulong}{usqrtn}{ulong a, ulong n} returns the floor of the $n$-th root of $a$. \fun{long}{Z_ispower}{GEN x, ulong k} returns $1$ if the \typ{INT} $n$ is a $k$-th power, and $0$ otherwise; assume that $k > 1$. \fun{long}{Z_ispowerall}{GEN x, ulong k, GEN *pt} as \kbd{Z\_ispower}. If $n$ is indeed a $k$-th power, set \kbd{*pt} to its integer $k$-th root. \fun{long}{Z_isanypower}{GEN x, GEN *ptn} returns the maximal $k\geq 2$ such that the \typ{INT} $x = n^k$ is a perfect power, or $0$ if no such $k$ exist; in particular \kbd{ispower(1)}, \kbd{ispower(0)}, \kbd{ispower(-1)} all return 0. If the return value $k$ is not $0$ (so that $x = n^k$) and \kbd{ptn} is not \kbd{NULL}, set \kbd{*ptn} to $n$. The following low-level functions are called by \tet{Z_isanypower} but can be directly useful: \fun{int}{is_357_power}{GEN x, GEN *ptn, ulong *pmask} tests whether the integer $x > 0$ is a $3$-rd, $5$-th or $7$-th power. The bits of \kbd{*mask} initially indicate which test is to be performed; bit $0$: $3$-rd, bit $1$: $5$-th, bit $2$: $7$-th (e.g.~$\kbd{*pmask} = 7$ performs all tests). They are updated during the call: if the ``$i$-th power'' bit is set to $0$ then $x$ is not a $k$-th power. The function returns $0$ (not a $3$-rd, $5$-th or $7$-th power), $3$ ($3$-rd power, not a $5$-th or $7$-th power), $5$ ($5$-th power, not a $7$-th power), or $7$ ($7$-th power); if an $i$-th power bit is initially set to $0$, we take it at face value and assume $x$ is not an $i$-th power without performing any test. If the return value $k$ is nonzero, set \kbd{*ptn} to $n$ such that $x = n^k$. \fun{int}{is_pth_power}{GEN x, GEN *ptn, forprime_t *T, ulong cutoff} let $x > 0$ be an integer, $\kbd{cutoff} > 0$ and $T$ be an iterator over primes $\geq 11$, we look for the smallest prime $p$ such that $x = n^p$ (advancing $T$ as we go along). The $11$ is due to the fact that \tet{is_357_power} and \kbd{issquare} are faster than the generic version for $p < 11$. Fail and return $0$ when the existence of $p$ would imply $2^{\kbd{cutoff}} > x^{1/p}$, meaning that a possible $n$ is so small that it should have been found by trial division; for maximal speed, you should start by a round of trial division, but the cut-off may also be set to $1$ for a rigorous result without any trial division. Otherwise returns the smallest suitable prime power $p^i$ and set \kbd{*ptn} to the $p^i$-th root of $x$ (which is now not a $p$-th power). We may immediately recall the function with the same parameters after setting $x = \kbd{*ptn}$: it will start at the next prime. \subsec{Factorization} \fun{GEN}{Z_factor}{GEN n} factors the \typ{INT} \kbd{n}. The ``primes'' in the factorization are actually strong pseudoprimes. \fun{GEN}{absZ_factor}{GEN n} returns \kbd{Z\_factor(absi(n))}. \fun{long}{Z_issmooth}{GEN n, ulong lim} returns $1$ if all the prime factors of the \typ{INT} $n$ are less or equal to $lim$. \fun{GEN}{Z_issmooth_fact}{GEN n, ulong lim} returns \kbd{NULL} if a prime factor of the \typ{INT} $n$ is $> lim$, and returns the factorization of $n$ otherwise, as a \typ{MAT} with \typ{VECSMALL} columns (word-size primes and exponents). Neither memory-clean nor suitable for \kbd{gerepileupto}. \fun{GEN}{Z_factor_until}{GEN n, GEN lim} as \kbd{Z\_factor}, but stop the factorization process as soon as the unfactored part is smaller than \kbd{lim}. The resulting factorization matrix only contains the factors found. No other assumptions can be made on the remaining factors. \fun{GEN}{Z_factor_limit}{GEN n, ulong lim} trial divide $n$ by all primes $p < \kbd{lim}$ in the precomputed list of prime numbers and the \kbd{addprimes} prime table. Return the corresponding factorization matrix. The first column of the factorization matrix may contain a single composite, which may or may not be the last entry in presence of a prime table. If $\kbd{lim} = 0$, the effect is the same as setting $\kbd{lim} = \kbd{maxprime()} + 1$: use all precomputed primes. \fun{GEN}{absZ_factor_limit}{GEN n, ulong all} returns \kbd{Z\_factor\_limit(absi(n))}. \fun{GEN}{absZ_factor_limit_strict}{GEN n, ulong lim, GEN *pU}. This function is analogous to \tet{absZ_factor_limit}, with a better interface: trial divide $n$ by all primes $p < \kbd{lim}$ (supposedly in the precomputed list of prime numbers, but \kbd{lim} may be larger) and then the full \kbd{addprimes} prime table (whatever their size). Return the corresponding factorization matrix. In this case, a composite cofactor is \emph{not} included. If \kbd{pU} is not \kbd{NULL}, set it to the cofactor, which is either \kbd{NULL} (no cofactor) or $[q,k]$, where $q > \kbd{lim}$ and $k > 0$. The prime divisors of $q$ are greater than \kbd{lim} and not in the \kbd{addprimes} table, $q$ is not a pure power, and $q^k$ is the largest power of $q$ dividing $n$. It may happen that $q$ is prime. \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{VEC} $L$ containing a list of primes and a \typ{INT} $n$, trial divide $n$ by the elements of $L$ and return the cofactor. Return \kbd{NULL} if the cofactor is $\pm 1$. \kbd{*P} and \kbd{*E} contain the list of prime divisors found and their exponents, as \typ{VECSMALL}s. Neither memory-clean, nor suitable for \tet{gerepileupto}. \fun{GEN}{Z_lsmoothen}{GEN n, GEN L, GEN *pP, GEN *pE} as \kbd{Z\_smoothen} where $L$ is a \typ{VECSMALL} of small primes and both \kbd{*P} and \kbd{*E} are given as \typ{VECSMALL}. \fun{GEN}{Z_factor_listP}{GEN N, GEN L} given a \typ{INT} $N$, a vector or primes $L$ containing all prime divisors of $N$ (and possibly others). Return \kbd{factor(N)}. Neither memory-clean, nor suitable for \tet{gerepileupto}. \fun{GEN}{factor_pn_1}{GEN p, ulong n} returns the factorization of $p^n-1$, where $p$ is prime and $n$ is a positive integer. \fun{GEN}{factor_pn_1_limit}{GEN p, ulong n, ulong B} returns a partial factorization of $p^n-1$, where $p$ is prime and $n$ is a positive integer. Don't actively search for prime divisors $p > B$, but we may find still find some due to Aurifeuillian factorizations. Any entry $> B^2$ in the output factorization matrix is \emph{a priori} not a prime (but may well be). \fun{GEN}{factor_Aurifeuille_prime}{GEN p, long n} an Aurifeuillian factor of $\phi_n(p)$, assuming $p$ prime and an Aurifeuillian factor exists ($p \zeta_n$ is a square in $\Q(\zeta_n)$). \fun{GEN}{factor_Aurifeuille}{GEN a, long n} an Aurifeuillian factor of $\phi_n(a)$, assuming $a$ is a nonzero integer and $n > 2$. Returns $1$ if no Aurifeuillian factor exists. \fun{GEN}{odd_prime_divisors}{GEN a} \typ{VEC} of all prime divisors of the \typ{INT} $a$. \fun{GEN}{factoru}{ulong n}, returns the factorization of $n$. The result is a $2$-component vector $[P,E]$, where $P$ and $E$ are \typ{VECSMALL} containing the prime divisors of $n$, and the $v_p(n)$. \fun{GEN}{factoru_pow}{ulong n}, returns the factorization of $n$. The result is a $3$-component vector $[P,E,C]$, where $P$, $E$ and $C$ are \typ{VECSMALL} containing the prime divisors of $n$, the $v_p(n)$ and the $p^{v_p(n)}$. \fun{GEN}{vecfactoru}{ulong a, ulong b}, returns a \typ{VEC} $v$ containing the factorizations (\tet{factoru} format) of $a,\dots, b$; assume that $b \geq a > 0$. Uses a sieve with primes up to $\sqrt{b}$. For all $c$, $a \leq c \leq b$, the factorization of $c$ is given in $v[c-a+1]$. \fun{GEN}{vecfactoroddu}{ulong a, ulong b}, returns a \typ{VEC} $v$ containing the factorizations (\tet{factoru} format) of odd integers in $a,\dots, b$; assume that $b \geq a > 0$ are odd. Uses a sieve with primes up to $\sqrt{b}$. For all odd $c$, $a \leq c \leq b$, the factorization of $c$ is given in in $v[(c-a)/2 + 1]$. \fun{GEN}{vecfactoru_i}{ulong a, ulong b}, private version of \kbd{vecfactoru}, not memory clean. \fun{GEN}{vecfactoroddu_i}{ulong a, ulong b}, private version of \kbd{vecfactoroddu}, not memory clean. \fun{GEN}{vecfactorsquarefreeu}{ulong a, ulong b} return a \typ{VEC} $v$ containing the prime divisors of squarefree integers in $a,\dots,b$; assume that $a \leq b$. Uses a sieve with primes up to $\sqrt{b}$. For all squarefree $c$, $a\leq c\leq b$, the prime divisors of $c$ (as a \typ{VECSMALL}) are given in $v[c-a+1]$, and the other entries are \kbd{NULL}. Note that because of these \kbd{NULL} markers, $v$ is not a valid \kbd{GEN}, it is not memory clean and cannot be used in garbage collection routines. \fun{GEN}{vecfactorsquarefreeu_coprime}{ulong a, ulong b, GEN P} given a \emph{sorted} \typ{VECSMALL} of primes $P$, return a \typ{VEC} $v$ containing the prime divisors of squarefree integers in $a,\dots,b$ coprime to the elements of $P$; assume that $a \leq b$. Uses a sieve with primes up to $\sqrt{b}$. For all squarefree $c$, $a\leq c\leq b$, the prime divisors of $c$ (as a \typ{VECSMALL}) are given in $v[c-a+1]$, and the other entries are \kbd{NULL}. Note that because of these \kbd{NULL} markers, $v$ is not a valid \kbd{GEN}, it is not memory clean and cannot be used in garbage collection routines. \fun{GEN}{vecsquarefreeu}{ulong a, ulong b} return a \typ{VECSMALL} $v$ containing the squarefree integers in $a,\dots,b$. Assume that $a\leq b$. Uses a sieve with primes up to $\sqrt{b}$. \fun{ulong}{tridiv_bound}{GEN n} returns the trial division bound used by \tet{Z_factor}$(n)$. \fun{GEN}{tridiv_boundu}{ulong n} returns the trial division bound used by \kbd{factoru}$n$. \fun{GEN}{Z_pollardbrent}{GEN N, long n, long seed} try to factor \typ{INT} $N$ using $n\geq 1$ rounds of Pollard iterations; \var{seed} is an integer whose value (mod $8$) selects the quadratic polynomial use to generate Pollard's (pseudo)random walk. Returns \kbd{NULL} on failure, else a vector of 2 (possibly 3) integers whose product is $N$. \fun{GEN}{Z_ECM}{GEN N, long n, long seed, ulong B1} try to factor \typ{INT} $N$ using $n\geq 1$ rounds of ECM iterations (on $8$ to $64$ curves simultaneously, depending on the size of $N$); \var{seed} is an integer whose value selects the curves to be used: increase it by $64n$ to make sure that a subsequent call with a factor of $N$ uses a disjoint set of curves. Finally $B_1 > 7$ determines the computations performed on the curves: we compute $[k]P$ for some point in $E(\Z/N\Z)$ and $k = q \prod p^{e_p}$ where $p^{e_p} \leq B_1$ and $q \leq B_2 := 110 B_1$; a higher value of $B_1$ means higher chances of hitting a factor and more time spent. The computation is deterministic for a given set of parameters. Returns \kbd{NULL} on failure, else a nontrivial factor or \kbd{N}. \fun{GEN}{Q_factor}{GEN x} as \tet{Z_factor}, where $x$ is a \typ{INT} or a \typ{FRAC}. \fun{GEN}{Q_factor_limit}{GEN x, ulong lim} as \tet{Z_factor_limit}, where $x$ is a \typ{INT} or a \typ{FRAC}. \subsec{Coprime factorization} Given $a$ and $b$ two nonzero integers, let \teb{ppi}$(a,b)$, \teb{ppo}$(a,b)$, \teb{ppg}$(a,b)$, \teb{pple}$(a,b)$ (powers in $a$ of primes inside $b$, outside $b$, greater than those in $b$, less than or equal to those in $b$) be the integers defined by \item $v_p(\text{ppi}) = v_p(a) [v_p(b) > 0]$, \item $v_p(\text{ppo}) = v_p(a) [v_p(b) = 0]$, \item $v_p(\text{ppg}) = v_p(a) [v_p(a) > v_p(b)]$, \item $v_p(\text{pple}) = v_p(a) [v_p(a) \leq v_p(b)]$. \fun{GEN}{Z_ppo}{GEN a, GEN b} returns $\text{ppo}(a,b)$; shallow function. \fun{ulong}{u_ppo}{ulong a, ulong b} returns $\text{ppo}(a,b)$. \fun{GEN}{Z_ppgle}{GEN a, GEN b} returns $[\text{ppg}(a,b), \text{pple}(a,b)]$; shallow function. \fun{GEN}{Z_ppio}{GEN a, GEN b} returns $[\gcd(a,b), \text{ppi}(a,b), \text{ppo}(a,b)]$; shallow function. \fun{GEN}{Z_cba}{GEN a, GEN b} fast natural coprime base algorithm. Returns a vector of coprime divisors of $a$ and $b$ such that both $a$ and $b$ can be multiplicatively generated from this set. Perfect powers are not removed, use \tet{Z_isanypower} if needed; shallow function. \fun{GEN}{ZV_cba_extend}{GEN P, GEN b} extend a coprime basis $P$ by the integer $b$, the result being a coprime basis for $P\cup \{b\}$. Perfect powers are not removed; shallow function. \fun{GEN}{ZV_cba}{GEN v} given a vector of nonzero integers $v$, return a coprime basis for $v$. Perfect powers are not removed; shallow function. \subsec{Checks attached to arithmetic functions} Arithmetic functions accept arguments of the following kind: a plain positive integer $N$ (\typ{INT}), the factorization \var{fa} of a positive integer (a \typ{MAT} with two columns containing respectively primes and exponents), or a vector $[N,\var{fa}]$. A few functions accept nonzero integers (e.g.~\tet{omega}), and some others arbitrary integers (e.g.~\tet{factorint}, \dots). \fun{int}{is_Z_factorpos}{GEN f} returns $1$ if $f$ looks like the factorization of a positive integer, and $0$ otherwise. Useful for sanity checks but not 100\% foolproof. Specifically, this routine checks that $f$ is a two-column matrix all of whose entries are positive integers. It does \emph{not} check that entries in the first column (``primes'') are prime, or even pairwise coprime, nor that they are stricly increasing. \fun{int}{is_Z_factornon0}{GEN f} returns $1$ if $f$ looks like the factorization of a nonzero integer, and $0$ otherwise. Useful for sanity checks but not 100\% foolproof, analogous to \tet{is_Z_factorpos}. (Entries in the first column need only be nonzero integers.) \fun{int}{is_Z_factor}{GEN f} returns $1$ if $f$ looks like the factorization of an integer, and $0$ otherwise. Useful for sanity checks but not 100\% foolproof. Specifically, this routine checks that $f$ is a two-column matrix all of whose entries are integers. Entries in the second column (``exponents'') are all positive. Either it encodes the ``factorization'' $0^e$, $e > 0$, or entries in the first column (``primes'') are all nonzero. \fun{GEN}{clean_Z_factor}{GEN f} assuming $f$ is the factorization of an integer $n$, return the factorization of $|n|$, i.e.~remove $-1$ from the factorization. Shallow function. \fun{GEN}{fuse_Z_factor}{GEN f, GEN B} assuming $f$ is the factorization of an integer $n$, return \kbd{boundfact(n, B)}, i.e. return a factorization where all primary factors for $|p| \leq B$ are preserved, and all others are ``fused'' into a single composite integer; if that remainder is trivial, i.e.~equal to 1, it is of course not included. Shallow function. In the following three routines, $f$ is the name of an arithmetic function, and $n$ a supplied argument. They all raise exceptions if $n$ does not correspond to an integer or an integer factorization of the expected shape. \fun{GEN}{check_arith_pos}{GEN n, const char *f} check whether $n$ is attached to the factorization of a positive integer, and return \kbd{NULL} (plain \typ{INT}) or a factorization extracted from $n$ otherwise. May raise an \tet{e_DOMAIN} ($n \leq 0$) or an \tet{e_TYPE} exception (other failures). \fun{GEN}{check_arith_non0}{GEN n, const char *f} check whether $n$ is attached to the factorization of a nonzero integer, and return \kbd{NULL} (plain \typ{INT}) or a factorization extracted from $n$ otherwise. May raise an \tet{e_TYPE} exception. \fun{GEN}{check_arith_all}{GEN n, const char *f} is attached to the factorization of an integer, and return \kbd{NULL} (plain \typ{INT}) or a factorization extracted from $n$ otherwise. \subsec{Incremental integer factorization} Routines attached to the dynamic factorization of an integer $n$, iterating over successive prime divisors. This is useful to implement high-level routines allowed to take shortcuts given enough partial information: e.g. \kbd{moebius}$(n)$ can be trivially computed if we hit $p$ such that $p^2 \mid n$. For efficiency, trial division by small primes should have already taken place. In any case, the functions below assume that no prime $< 2^{14}$ divides $n$. \fun{GEN}{ifac_start}{GEN n, int moebius} schedules a new factorization attempt for the integer $n$. If \kbd{moebius} is nonzero, the factorization will be aborted as soon as a repeated factor is detected (Moebius mode). The function assumes that $n > 1$ is a \emph{composite} \typ{INT} whose prime divisors satisfy $p > 2^{14}$ \emph{and} that one can write to $n$ in place. This function stores data on the stack, no \kbd{gerepile} call should delete this data until the factorization is complete. Returns \kbd{partial}, a data structure recording the partial factorization state. \fun{int}{ifac_next}{GEN *partial, GEN *p, long *e} deletes a primary factor $p^e$ from \kbd{partial} and sets \kbd{p} (prime) and \kbd{e} (exponent), and normally returns $1$. Whatever remains in the \kbd{partial} structure is now coprime to $p$. Returns $0$ if all primary factors have been used already, so we are done with the factorization. In this case $p$ is set to \kbd{NULL}. If we ran in Moebius mode and the factorization was in fact aborted, we have $e = 1$, otherwise $e = 0$. \fun{int}{ifac_read}{GEN part, GEN *k, long *e} peeks at the next integer to be factored in the list $k^e$, where $k$ is not necessarily prime and can be a perfect power as well, but will be factored by the next call to \tet{ifac_next}. You can remove this factorization from the schedule by calling: \fun{void}{ifac_skip}{GEN part} removes the next scheduled factorization. \fun{int}{ifac_isprime}{GEN n} given $n$ whose prime divisors are $> 2^{14}$, returns the decision the factoring engine would take about the compositeness of $n$: $0$ if $n$ is a proven composite, and $1$ if we believe it to be prime; more precisely, $n$ is a proven prime if \tet{factor_proven} is set, and only a BPSW-pseudoprime otherwise. \subsec{Integer core, squarefree factorization} \fun{long}{Z_issquarefree}{GEN n} returns $1$ if the \typ{INT} \kbd{n} is square-free, and $0$ otherwise. \fun{long}{Z_issquarefree_fact}{GEN fa} same, where \kbd{fa} is \kbd{factor(n)}. \fun{long}{Z_isfundamental}{GEN x} returns $1$ if the \typ{INT} \kbd{x} is a fundamental discriminant, and $0$ otherwise. \fun{GEN}{core}{GEN n} unique squarefree integer $d$ dividing $n$ such that $n/d$ is a square. The core of $0$ is defined to be $0$. \fun{GEN}{core2}{GEN n} return $[d,f]$ with $d$ squarefree and $n = df^2$. \fun{GEN}{corepartial}{GEN n, long lim} as \kbd{core}, using \kbd{boundfact(n,lim)} to partially factor \kbd{n}. The result is not necessarily squarefree, but $p^2 \mid n$ implies $p > \kbd{lim}$. \fun{GEN}{core2partial}{GEN n, long lim} as \kbd{core2}, using \kbd{boundfact(n,lim)} to partially factor \kbd{n}. The resulting $d$ is not necessarily squarefree, but $p^2 \mid n$ implies $p > \kbd{lim}$. \subsec{Primes, primality and compositeness tests} \subsubsec{Chebyshev's $\pi$ function, bounds} \fun{ulong}{uprimepi}{ulong n}, returns the number of primes $p\leq n$ (Chebyshev's $\pi$ function). \fun{double}{primepi_upper_bound}{double x} return a quick upper bound for $\pi(x)$, using Dusart bounds. \fun{GEN}{gprimepi_upper_bound}{GEN x} as \tet{primepi_upper_bound}, returns a \typ{REAL}. \fun{double}{primepi_lower_bound}{double x} return a quick lower bound for $\pi(x)$, using Dusart bounds. \fun{GEN}{gprimepi_lower_bound}{GEN x} as \tet{primepi_lower_bound}, returns a \typ{REAL} or \kbd{gen\_0}. \subsubsec{Primes, primes in intervals} \fun{ulong}{unextprime}{ulong n}, returns the smallest prime $\geq n$. Return $0$ if it cannot be represented as an \kbd{ulong} ($n$ bigger than $2^{64} - 59$ or $2^{32} - 5$ depending on the word size). \fun{ulong}{uprecprime}{ulong n}, returns the largest prime $\leq n$. Return $0$ if $n\leq 1$. \fun{ulong}{uprime}{long n} returns the $n$-th prime, assuming it fits in an \kbd{ulong} (overflow error otherwise). \fun{GEN}{prime}{long n} same as \kbd{utoi(uprime(n))}. \fun{GEN}{primes_zv}{long m} returns the first $m$ primes, in a \typ{VECSMALL}. \fun{GEN}{primes}{long m} return the first $m$ primes, as a \typ{VEC} of \typ{INT}s. \fun{GEN}{primes_interval}{GEN a, GEN b} return the primes in the interval $[a,b]$, as a \typ{VEC} of \typ{INT}s. \fun{GEN}{primes_interval_zv}{ulong a, ulong b} return the primes in the interval $[a,b]$, as a \typ{VECSMALL} of \kbd{ulongs}s. \fun{GEN}{primes_upto_zv}{ulong b} return the primes in the interval $[2,b]$, as a \typ{VECSMALL} of \kbd{ulongs}s. \fun{GEN}{mpprimorial}{long n} return $n\#$, the product of primes less than or equal to $n$. The integer $n$ must be non-negative. \subsubsec{Tests} \fun{int}{uisprime}{ulong p}, returns $1$ if \kbd{p} is a prime number and $0$ otherwise. \fun{int}{uisprime_101}{ulong p}, assuming that $p$ has no divisor $\leq 101$, returns $1$ if \kbd{p} is a prime number and $0$ otherwise. \fun{int}{uisprime_661}{ulong p}, assuming that $p$ has no divisor $\leq 661$, returns $1$ if \kbd{p} is a prime number and $0$ otherwise. \fun{int}{isprime}{GEN n}, returns $1$ if the \typ{INT} \kbd{n} is a (fully proven) prime number and $0$ otherwise. \fun{long}{isprimeAPRCL}{GEN n}, returns $1$ if the \typ{INT} \kbd{n} is a prime number and $0$ otherwise, using only the APRCL test --- not even trial division or compositeness tests. The workhorse \kbd{isprime} should be faster on average, especially if nonprimes are included! \fun{long}{isprimeECPP}{GEN n}, returns $1$ if the \typ{INT} \kbd{n} is a prime number and $0$ otherwise, using only the ECPP test. The workhorse \kbd{isprime} should be faster on average. \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 expect it to be less reliable. \fun{GEN}{ecpp}{GEN N} returns an ECPP certificate for \typ{INT} $N$; underlies \kbd{primecert}. \fun{GEN}{ecpp0}{GEN N, long t} returns a (potentially) partial ECPP certificate for \typ{INT} $N$ where strong pseudo-primes $< 2^t$ are included as primes in the certificate. Underlies \kbd{primecert} with $t$ set to the \kbd{partial} argument. \fun{GEN}{ecppexport}{GEN cert, long flag} export a PARI ECPP certificate to MAGMA or Primo format; underlies \kbd{primecertexport}. \fun{long}{ecppisvalid}{GEN cert} checks whether a PARI ECPP certificate is valid; underlies \kbd{primecertisvalid}. \fun{long}{check_ecppcert}{GEN cert} checks whether \kbd{cert} looks like a PARI ECPP certificate, (valid or invalid) without doing any computation. \subsec{Iterators over primes} \fun{int}{forprime_init}{forprime_t *T, GEN a, GEN b} initialize an iterator $T$ over primes in $[a,b]$; over primes $\geq a$ if $b = \kbd{NULL}$. Return $0$ if the range is known to be empty from the start (as if $b < a$ or $b < 0$), and return $1$ otherwise. Use \tet{forprime_next} to iterate over the prime collection. \fun{int}{forprimestep_init}{forprime_t *T, GEN a, GEN b, GEN q} initialize an iterator $T$ over primes in an arithmetic progression in $[a,b]$; over primes $\geq a$ if $b = \kbd{NULL}$. The argument $q$ is either a \typ{INT} ($p \equiv a \pmod{q}$) or a \typ{INTMOD} \kbd{Mod(c,N)} and we restrict to that congruence class. Return $0$ if the range is known to be empty from the start (as if $b < a$ or $b < 0$), and return $1$ otherwise. Use \tet{forprime_next} to iterate over the prime collection. \fun{GEN}{forprime_next}{forprime_t *T} returns the next prime in the range, assuming that $T$ was initialized by \tet{forprime_init}. \fun{int}{u_forprime_init}{forprime_t *T, ulong a, ulong b} \fun{ulong}{u_forprime_next}{forprime_t *T} \fun{void}{u_forprime_restrict}{forprime_t *T, ulong c} let $T$ an iterator over primes initialized via \kbd{u\_forprime\_init(\&T, a, b)}, possibly followed by a number of calls to \tet{u_forprime_next}, and $a \leq c \leq b$. Restrict the range of primes considered to $[a,c]$. \fun{int}{u_forprime_arith_init}{forprime_t *T, ulong a,ulong b, ulong c,ulong q} initialize an iterator over primes in $[a,b]$, congruent to $c$ modulo $q$. Subsequent calls to \tet{u_forprime_next} will only return primes congruent to $c$ modulo $q$. Note that unless $(c,q) = 1$ there will be at most one such prime. \section{Integral, rational and generic linear algebra} \subsec{\kbd{ZC} / \kbd{ZV}, \kbd{ZM}} A \kbd{ZV} (resp.~a~\kbd{ZM}, resp.~a~\kbd{ZX}) is a \typ{VEC} or \typ{COL} (resp.~\typ{MAT}, resp.~\typ{POL}) with \typ{INT} coefficients. \subsubsec{\kbd{ZC} / \kbd{ZV}} \fun{void}{RgV_check_ZV}{GEN x, const char *s} Assuming \kbd{x} is a \typ{VEC} or \typ{COL} raise an error if it is not a \kbd{ZV} ($s$ should point to the name of the caller). \fun{int}{RgV_is_ZV}{GEN x} Assuming \kbd{x} is a \typ{VEC} or \typ{COL} return $1$ if it is a \kbd{ZV}, and $0$ otherwise. \fun{int}{RgV_is_ZVpos}{GEN x} Assuming \kbd{x} is a \typ{VEC} or \typ{COL} return $1$ if it is a \kbd{ZV} with positive entries, and $0$ otherwise. \fun{int}{RgV_is_ZVnon0}{GEN x} Assuming \kbd{x} is a \typ{VEC} or \typ{COL} return $1$ if it is a \kbd{ZV} with nonzero entries, and $0$ otherwise. \fun{int}{RgV_is_QV}{GEN P} return 1 if the \kbd{RgV}~$P$ has only \typ{INT} and \typ{FRAC} coefficients, and 0 otherwise. \fun{int}{RgV_is_arithprog}{GEN v, GEN *a, GEN *b} assuming $x$ is a \typ{VEC} or \typ{COL} return $1$ if its entries follow an arithmetic progression of the form $a + b*n$, $n = 0, 1, \dots$ and set $a$ and $b$. Else return $0$. \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). \fun{int}{ZV_abscmp}{GEN x, GEN y} compare two \kbd{ZV}, which we assume have the same length (lexicographic order, comparing absolute values). \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}{identity_ZV}{long n} return the \typ{VEC} $[1, 2, \dots, n]$. \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}{Z_ZC_sub}{GEN a, GEN x} returns the vector $[a - x_1, -x_2,\dots,-x_n]$. \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}{ZC_divexactu}{GEN x, ulong y} returns $x/y$ assuming all divisions are exact. \fun{GEN}{ZC_Z_div}{GEN x, GEN y} returns $x/y$, where the resulting vector has rational entries. \fun{GEN}{ZV_ZV_mod}{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])$. \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{void}{ZC_lincomb1_inplace_i}{GEN X, GEN Y, GEN v, long n} variant of \tet{ZC_lincomb1_inplace}: only update $X[1], \dots, X[n]$, assuming that $n < \kbd{lg}(X)$. \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_extgcd}{GEN A} given a vector of $n$ integers $A$, returns $[d, U]$, where $d$ is the content of $A$ and $U$ is a matrix in $\text{GL}_n(\Z)$ such that $AU = [D,0, \dots,0]$. \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{long}{ZV_max_expi}{GEN x} returns the number of bits of the largest 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_shallow}{GEN L} shallow version of \kbd{ZV\_sort}. \fun{void}{ZV_sort_inplace}{GEN L} sort the \kbd{ZV} $L$, in place. \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{GEN}{ZV_sort_uniq_shallow}{GEN L} shallow version of \kbd{ZV\_sort\_uniq}. \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$. \fun{GEN}{ZC_union_shallow}{GEN x, GEN y} as \kbd{ZV\_union\_shallow} but return a \typ{COL}. \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}{RgM_rescale_to_int}{GEN x} given a matrix $x$ with real entries (\typ{INT}, \typ{FRAC} or \typ{REAL}), return a \kbd{ZM} wich is very close to $D x$ for some well-chosen integer $D$. More precisely, if the input is exact, $D$ is the denominator of $x$; else it is a power of $2$ chosen so that all inexact entries are correctly rounded to 1 ulp. \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{int}{ZM_equal0}{GEN A} returns $1$ if the \kbd{ZM} $A$ is identically equal to $0$. \fun{GEN}{ZM_add}{GEN x, GEN y} returns $\kbd{x} + \kbd{y}$ (assumed to have compatible dimensions). \fun{GEN}{ZM_sub}{GEN x, GEN y} returns $\kbd{x} - \kbd{y}$ (assumed to have compatible dimensions). \fun{GEN}{ZM_neg}{GEN x} returns $-\kbd{x}$. \fun{void}{ZM_togglesign}{GEN x} negates \kbd{x} in place, by toggling the sign of its integer components. Universal constants \kbd{gen\_1}, \kbd{gen\_m1}, \kbd{gen\_2} and \kbd{gen\_m2} are handled specially and will not be corrupted. (We use \tet{togglesign_safe}.) \fun{GEN}{ZM_mul}{GEN x, GEN y} multiplies \kbd{x} and \kbd{y} (assumed to have compatible dimensions). \fun{GEN}{ZM2_mul}{GEN x, GEN y} multiplies the two-by-two \kbd{ZM} $x$ and $y$. \fun{GEN}{ZM_sqr}{GEN x} returns $x^2$, where $x$ is a square \kbd{ZM}. \fun{GEN}{ZM2_sqr}{GEN x} returns $x^2$, where $x$ is a two-by-two \kbd{ZM}. \fun{GEN}{ZM_Z_mul}{GEN x, GEN y} multiplies the \kbd{ZM}~\kbd{x} by the \typ{INT}~\kbd{y}. \fun{GEN}{ZM_ZC_mul}{GEN x, GEN y} multiplies the \kbd{ZM}~\kbd{x} by the \kbd{ZC}~\kbd{y} (seen as a column vector, assumed to have compatible dimensions). \fun{GEN}{ZM_ZX_mul}{GEN x, GEN T} returns $x \times y$, where $y$ is \kbd{RgX\_to\_RgC}$(T, \kbd{lg}(x)-1)$. \fun{GEN}{ZM_diag_mul}{GEN d, GEN m} given a vector $d$ with integer entries and a \kbd{ZM} $m$ of compatible dimensions, return \kbd{diagonal(d) * m}. \fun{GEN}{ZM_mul_diag}{GEN m, GEN d} given a vector $d$ with integer entries and a \kbd{ZM} $m$ of compatible dimensions, return \kbd{m * diagonal(d)}. \fun{GEN}{ZM_multosym}{GEN x, GEN y} \fun{GEN}{ZM_transmultosym}{GEN x, GEN y} \fun{GEN}{ZM_transmul}{GEN x, GEN y} \fun{GEN}{ZMrow_ZC_mul}{GEN x, GEN y, long i} multiplies the $i$-th row of \kbd{ZM}~\kbd{x} by the \kbd{ZC}~\kbd{y} (seen as a column vector, assumed to have compatible dimensions). Assumes that $x$ is nonempty and $0 < i < \kbd{lg(x[1])}$. \fun{int}{ZMrow_equal0}{GEN V, long i} returns $1$ if the $i$-th row of the \kbd{ZM}~\kbd{V} is zero, and $0$ otherwise. \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_divexactu}{GEN x, ulong y} returns $x/y$ assuming all divisions are exact. \fun{GEN}{ZM_Z_div}{GEN x, GEN y} returns $x/y$, where the resulting matrix has rational entries. \fun{GEN}{ZM_ZV_mod}{GEN a, GEN b}. Assuming $a$ is a \kbd{ZM} whose columns have the same length as the \kbd{ZV} $b$, apply \kbd{ZV\_ZV\_mod}$(a[i],b)$ to all columns. \fun{GEN}{ZC_Q_mul}{GEN x, GEN y} returns $x*y$, where $y$ is a rational number and the resulting \typ{COL} has rational entries. \fun{GEN}{ZM_Q_mul}{GEN x, GEN y} returns $x*y$, where $y$ is a rational number and the resulting matrix has rational entries. \fun{GEN}{ZM_pow}{GEN x, GEN n} returns $\kbd{x}^\kbd{n}$, assuming \kbd{x} is a square \kbd{ZM} and $\kbd{n}\geq 0$. \fun{GEN}{ZM_powu}{GEN x, ulong n} returns $\kbd{x}^\kbd{n}$, assuming \kbd{x} is a square \kbd{ZM} and $\kbd{n}\geq 0$. \fun{GEN}{ZM_det}{GEN M} if \kbd{M} is a \kbd{ZM}, returns the determinant of $M$. This is the function underlying \tet{matdet} whenever $M$ is a \kbd{ZM}. \fun{GEN}{ZM_permanent}{GEN M} if \kbd{M} is a \kbd{ZM}, returns its permanent. This is the function underlying \tet{matpermanent} whenever $M$ is a \kbd{ZM}. It assumes that the matrix is square of dimension $< \kbd{BITS\_IN\_LONG}$. \fun{GEN}{ZM_detmult}{GEN M} if \kbd{M} is a \kbd{ZM}, returns a multiple of the determinant of the lattice generated by its columns. This is the function underlying \tet{detint}. \fun{GEN}{ZM_supnorm}{GEN x} return the sup norm of the \kbd{ZM} $x$. \fun{GEN}{ZM_charpoly}{GEN M} returns the characteristic polynomial (in variable $0$) of the \kbd{ZM} $M$. \fun{GEN}{ZM_imagecompl}{GEN x} returns \kbd{matimagecompl(x)}. \fun{long}{ZM_rank}{GEN x} returns \kbd{matrank(x)}. \fun{GEN}{ZM_ker}{GEN x} returns the primitive part of \kbd{matker(x)}; in other words the $\Q$-basis vectors are made integral and primitive. \fun{GEN}{ZM_indexrank}{GEN x} returns \kbd{matindexrank(x)}. \fun{GEN}{ZM_indeximage}{GEN x} returns \kbd{gel(ZM\_indexrank(x), 2)}. \fun{long}{ZM_max_lg}{GEN x} returns the effective length of the longest entry in $x$. \fun{long}{ZM_max_expi}{GEN x} returns the number of bits of the largest entry in $x$. \fun{GEN}{ZM_inv}{GEN M, GEN *pd} if \kbd{M} is a \kbd{ZM}, return a primitive matrix $H$ such that $M H$ is $d$ times the identity and set \kbd{*pd} to $d$. Uses a multimodular algorithm up to Hadamard's bound. If you suspect that the denominator is much smaller than $\det M$, you may use \tet{ZM_inv_ratlift}. \fun{GEN}{ZM_inv_ratlift}{GEN M, GEN *pd} if \kbd{M} is a \kbd{ZM}, return a primitive matrix $H$ such that $M H$ is $d$ times the identity and set \kbd{*pd} to $d$. Uses a multimodular algorithm, attempting rational reconstruction along the way. To be used when you expect that the denominator of $M^{-1}$ is much smaller than $\det M$ else use \kbd{ZM\_inv}. \fun{GEN}{SL2_inv_shallow}{GEN M} return the inverse of $M \in \text{SL}_2(\Z)$. Not gerepile-safe. \fun{GEN}{ZM_pseudoinv}{GEN M, GEN *pv, GEN *pd} if \kbd{M} is a nonempty \kbd{ZM}, let $v = [y,z]$ returned by \kbd{indexrank} and let $M_1$ be the corresponding square invertible matrix. Return a primitive left-inverse $H$ such that $H M_1$ is $d$ times the identity and set \kbd{*pd} to $d$. If \kbd{pv} is not \kbd{NULL}, set \kbd{*pv} to $v$. Not gerepile-safe. \fun{GEN}{ZM_gauss}{GEN a, GEN b} as \kbd{gauss}, where $a$ and $b$ coefficients are \typ{INT}s. \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 if the \kbd{ZM} $x$ is the identity matrix, and 0 otherwise. \fun{int}{ZM_isdiagonal}{GEN x} return 1 if the \kbd{ZM} $x$ is diagonal, and 0 otherwise. \fun{int}{ZM_isscalar}{GEN x, GEN s} given a \kbd{ZM} $x$ and a \typ{INT} $s$, return 1 if $x$ is equal to $s$ times the identity, and 0 otherwise. If $s$ is \kbd{NULL}, test whether $x$ is an arbitrary scalar matrix. \fun{long}{ZC_is_ei}{GEN x} return $i$ if the \kbd{ZC} $x$ has $0$ entries, but for a $1$ at position $i$. \fun{int}{ZM_ishnf}{GEN x} return $1$ if $x$ is in HNF form, i.e. is upper triangular with positive diagonal coefficients, and for $j>i$, $x_{i,i}>x_{i,j} \ge 0$. \subsec{\kbd{QM}} \fun{GEN}{QM_charpoly_ZX}{GEN M} returns the characteristic polynomial (in variable $0$) of the \kbd{QM} $M$, assuming that the result has integer coefficients. \fun{GEN}{QM_charpoly_ZX_bound}{GEN M, long b} as \tet{QM_charpoly_ZX} assuming that the sup norm of the (integral) result is $\leq 2^b$. \fun{GEN}{QM_gauss}{GEN a, GEN b} as \kbd{gauss}, where $a$ and $b$ coefficients are \typ{FRAC}s. \fun{GEN}{QM_gauss_i}{GEN a, GEN b, long flag} as \kbd{QM\_gauss} if \kbd{flag} is $0$. Else, no longer assume that $a$ is left-invertible and return a solution of $P a x = P b$ where $P$ is a row-selection matrix such that $A = P a Q$ is square invertible of maximal rank, for some column-selection matrix $Q$; in particular, $x$ is a solution of the original equation $a x = b$ if and only if a solution exists. \fun{GEN}{QM_indexrank}{GEN x} returns \kbd{matindexrank(x)}. \fun{GEN}{QM_inv}{GEN M} return the inverse of the \kbd{QM} $M$. \fun{long}{QM_rank}{GEN x} returns \kbd{matrank(x)}. \fun{GEN}{QM_image}{GEN x} returns an integral matrix with primitive columns generating the image of $x$. \fun{GEN}{QM_image_shallow}{GEN A} shallow version of the previous function, not suitable for \kbd{gerepile}. \subsec{\kbd{Qevproj}} \fun{GEN}{Qevproj_init}{GEN M} let $M$ be a $n\times d$ \kbd{ZM} of maximal rank $d \leq n$, representing the basis of a $\Q$-subspace $V$ of $\Q^n$. Return a projector on $V$, to be used by \tet{Qevproj_apply}. The interface details may change in the future, but this function currently returns $[M, B,D,p]$, where $p$ is a \typ{VECSMALL} with $d$ entries such that the submatrix $A = \kbd{rowpermute}(M,p)$ is invertible, $B$ is a \kbd{ZM} and $d$ a \typ{INT} such that $A B = D \Id_d$. \fun{GEN}{Qevproj_apply}{GEN T, GEN pro} let $T$ be an $n\times n$ \kbd{QM}, stabilizing a $\Q$-subspace $V\subset \Q^n$ of dimension $d$, and let \kbd{pro} be a projector on that subspace initialized by \tet{Qevproj_init}$(M)$. Return the $d\times d$ matrix representing $T_{|V}$ on the basis given by the columns of $M$. \fun{GEN}{Qevproj_apply_vecei}{GEN T, GEN pro, long k} as \tet{Qevproj_apply}, return only the image of the $k$-th basis vector $M[k]$ (still on the basis given by the columns of $M$). \fun{GEN}{Qevproj_down}{GEN T, GEN pro} given a \kbd{ZC} (resp.~a \kbd{ZM}) $T$ representing an element (resp.~a vector of elements) in the subspace $V$ return a \kbd{QC} (resp.~a \kbd{QM}) $U$ such that $T = MU$. \subsec{\kbd{zv}, \kbd{zm}} \fun{GEN}{identity_zv}{long n} return the \typ{VECSMALL} $[1, 2, \dots, n]$. \fun{GEN}{random_zv}{long n} returns a random \kbd{zv} with $n$ components. \fun{GEN}{zv_abs}{GEN x} return $[|x[1]|,\ldots,|x[n]|]$ as a \kbd{zv}. \fun{GEN}{zv_neg}{GEN x} return $-x$. No check for overflow is done, which occurs in the fringe case where an entry is equal to $2^{\B-1}$. \fun{GEN}{zv_neg_inplace}{GEN x} negates $x$ in place and return it. No check for overflow is done, which occurs in the fringe case where an entry is equal to $2^{\B-1}$. \fun{GEN}{zm_zc_mul}{GEN x, GEN y} \fun{GEN}{zm_mul}{GEN x, GEN y} \fun{GEN}{zv_z_mul}{GEN x, long n} return $n\*x$. No check for overflow is done. \fun{long}{zv_content}{GEN x} returns the gcd of the entries of $x$. \fun{long}{zv_dotproduct}{GEN x, GEN y} \fun{long}{zv_prod}{GEN x} returns the product of all the components of~\kbd{x} (assumes no overflow occurs). \fun{GEN}{zv_prod_Z}{GEN x} returns the product of all the components of~\kbd{x}; consider all $x[i]$ as \kbd{ulong}s. \fun{long}{zv_sum}{GEN x} returns the sum of all the components of~\kbd{x} (assumes no overflow occurs). \fun{long}{zv_sumpart}{GEN v, long n} returns the sum $v[1] + \dots + v[n]$ (assumes no overflow occurs and \kbd{lg}$(v) > n$). \fun{int}{zv_cmp0}{GEN x} returns 1 if all entries of the \kbd{zv} $x$ are $0$, and $0$ otherwise. \fun{int}{zv_equal}{GEN x, GEN y} returns $1$ if the two \kbd{zv} are equal and $0$ otherwise. \fun{int}{zv_equal0}{GEN x} returns $1$ if all entries are $0$, and return $0$ otherwise. \fun{long}{zv_search}{GEN L, long y} look for $y$ in the sorted \kbd{zv} $L$. Return an index $i$ such that $L[i] = y$, and $0$ otherwise. \fun{GEN}{zv_copy}{GEN x} as \kbd{Flv\_copy}. \fun{GEN}{zm_transpose}{GEN x} as \kbd{Flm\_transpose}. \fun{GEN}{zm_copy}{GEN x} as \kbd{Flm\_copy}. \fun{GEN}{zero_zm}{long m, long n} as \kbd{zero\_Flm}. \fun{GEN}{zero_zv}{long n} as \kbd{zero\_Flv}. \fun{GEN}{zm_row}{GEN A, long x0} as \kbd{Flm\_row}. \fun{GEN}{zv_diagonal}{GEN v} return the square \kbd{zm} whose diagonal is given by the entries of $v$. \fun{GEN}{zm_permanent}{GEN M} return the permanent of $M$. The function assumes that the matrix is square of dimension $< \kbd{BITS\_IN\_LONG}$. \fun{int}{zvV_equal}{GEN x, GEN y} returns $1$ if the two \kbd{zvV} (vectors of \kbd{zv}) are equal and $0$ otherwise. \subsec{\kbd{ZMV} / \kbd{zmV} (vectors of \kbd{ZM}/\kbd{zm})} \fun{int}{RgV_is_ZMV}{GEN x} Assuming \kbd{x} is a \typ{VEC} or \typ{COL} return $1$ if its components are \kbd{ZM}, and $0$ otherwise. \fun{GEN}{ZMV_to_zmV}{GEN z} \fun{GEN}{zmV_to_ZMV}{GEN z} \fun{GEN}{ZMV_to_FlmV}{GEN z, ulong m} \subsec{\kbd{QC} / \kbd{QV}, \kbd{QM}} \fun{GEN}{QM_mul}{GEN x, GEN y} multiplies \kbd{x} and \kbd{y} (assumed to have compatible dimensions). \fun{GEN}{QM_sqr}{GEN x} returns the square of \kbd{x} (assumed to be square). \fun{GEN}{QM_QC_mul}{GEN x, GEN y} multiplies \kbd{x} and \kbd{y} (assumed to have compatible dimensions). \fun{GEN}{QM_det}{GEN M} returns the determinant of $M$. \fun{GEN}{QM_ker}{GEN x} returns \kbd{matker(x)}. \subsec{\kbd{RgC} / \kbd{RgV}, \kbd{RgM}} \kbd{RgC} and \kbd{RgV} routines assume the inputs are \kbd{VEC} or \kbd{COL} of the same dimension. \kbd{RgM} assume the inputs are \kbd{MAT} of compatible dimensions. \subsubsec{Matrix arithmetic} \fun{void}{RgM_dimensions}{GEN x, long *m, long *n} sets $m$, resp.~$n$, to the number of rows, resp.~columns of the \typ{MAT} $x$. \fun{GEN}{RgC_add}{GEN x, GEN y} returns $x + y$ as a \typ{COL}. \fun{GEN}{RgC_neg}{GEN x} returns $-x$ as a \typ{COL}. \fun{GEN}{RgC_sub}{GEN x, GEN y} returns $x - y$ as a \typ{COL}. \fun{GEN}{RgV_add}{GEN x, GEN y} returns $x + y$ as a \typ{VEC}. \fun{GEN}{RgV_neg}{GEN x} returns $-x$ as a \typ{VEC}. \fun{GEN}{RgV_sub}{GEN x, GEN y} returns $x - y$ as a \typ{VEC}. \fun{GEN}{RgM_add}{GEN x, GEN y} return $x+y$. \fun{GEN}{RgM_neg}{GEN x} returns $-x$. \fun{GEN}{RgM_sub}{GEN x, GEN y} returns $x-y$. \fun{GEN}{RgM_Rg_add}{GEN x, GEN y} assuming $x$ is a square matrix and $y$ a scalar, returns the square matrix $x + y*\text{Id}$. \fun{GEN}{RgM_Rg_add_shallow}{GEN x, GEN y} as \kbd{RgM\_Rg\_add} with much fewer copies. Not suitable for \kbd{gerepileupto}. \fun{GEN}{RgM_Rg_sub}{GEN x, GEN y} assuming $x$ is a square matrix and $y$ a scalar, returns the square matrix $x - y*\text{Id}$. \fun{GEN}{RgM_Rg_sub_shallow}{GEN x, GEN y} as \kbd{RgM\_Rg\_sub} with much fewer copies. Not suitable for \kbd{gerepileupto}. \fun{GEN}{RgC_Rg_add}{GEN x, GEN y} assuming $x$ is a nonempty column vector and $y$ a scalar, returns the vector $[x_1 + y, x_2,\dots,x_n]$. \fun{GEN}{RgC_Rg_sub}{GEN x, GEN y} assuming $x$ is a nonempty column vector and $y$ a scalar, returns the vector $[x_1 - y, x_2,\dots,x_n]$. \fun{GEN}{Rg_RgC_sub}{GEN a, GEN x} assuming $x$ is a nonempty column vector and $a$ a scalar, returns the vector $[a - x_1, -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_RgX_mul}{GEN x, GEN T} returns $x \times y$, where $y$ is \kbd{RgX\_to\_RgC}$(T, \kbd{lg}(x)-1)$. \fun{GEN}{RgM_mul}{GEN x, GEN y} returns $x\times y$. \fun{GEN}{RgM_div}{GEN a, GEN b} returns $ab^-1$ or \kbd{NULL} if this turns out to be impossible. \fun{GEN}{RgM_ZM_mul}{GEN x, GEN y} returns $x\times y$ assuming that $y$ is a \kbd{ZM}. \fun{GEN}{RgM_transmul}{GEN x, GEN y} returns $x\til \times y$. \fun{GEN}{RgM_multosym}{GEN x, GEN y} returns $x\times y$, assuming the result is a symmetric matrix (about twice faster than a generic matrix multiplication). \fun{GEN}{RgM_transmultosym}{GEN x, GEN y} returns $x\til \times y$, assuming the result is a symmetric matrix (about twice faster than a generic matrix multiplication). \fun{GEN}{RgMrow_RgC_mul}{GEN x, GEN y, long i} multiplies the $i$-th row of \kbd{RgM}~\kbd{x} by the \kbd{RgC}~\kbd{y} (seen as a column vector, assumed to have compatible dimensions). Assumes that $x$ is nonempty and $0 < i < \kbd{lg(x[1])}$. \fun{GEN}{RgM_mulreal}{GEN x, GEN y} returns the real part of $x\times y$ (whose entries are \typ{INT}, \typ{FRAC}, \typ{REAL} or \typ{COMPLEX}). \fun{GEN}{RgM_sqr}{GEN x} returns $x^2$. \fun{GEN}{RgC_RgV_mul}{GEN x, GEN y} returns $x\times y$ (the matrix $(x_iy_j)$). \fun{GEN}{RgC_RgV_mulrealsym}{GEN x, GEN y} returns the real part of $x\times y$ (whose entries are \typ{INT}, \typ{FRAC}, \typ{REAL} or \typ{COMPLEX}), assuming the result is symmetric. The following two functions are not well defined in general and only provided for convenience in specific cases: \fun{GEN}{RgC_RgM_mul}{GEN x, GEN y} returns $x\times y[1,]$ if $y$ is a row matrix $1\times n$, error otherwise. \fun{GEN}{RgM_RgV_mul}{GEN x, GEN y} returns $x\times y[,1]$ if $y$ is a column matrix $n\times 1$, error otherwise. \fun{GEN}{RgM_powers}{GEN x, long n} returns $[\kbd{x}^0, \dots, \kbd{x}^\kbd{n}]$ as a \typ{VEC} of \kbd{RgM}s. \smallskip \fun{GEN}{RgV_sum}{GEN v} sum of the entries of $v$ \fun{GEN}{RgV_prod}{GEN v} product of the entries of $v$, using a divide and conquer strategy \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}{RgM_sumcol}{GEN v} returns a \typ{COL}, sum of the columns of the \typ{MAT} $v$. \fun{GEN}{RgV_dotproduct}{GEN x,GEN y} returns the scalar product of $x$ and $y$ \fun{GEN}{RgV_dotsquare}{GEN x} returns the scalar product of $x$ with itself. \fun{GEN}{RgV_kill0}{GEN v} returns a shallow copy of $v$ where entries matched by \kbd{gequal0} are replaced by \kbd{NULL}. The return value is not a valid \kbd{GEN} and must be handled specially. The idea is to pre-treat a vector of coefficients to speed up later linear combinations or scalar products. \fun{GEN}{gram_matrix}{GEN v} returns the \idx{Gram matrix} $(v_i\cdot v_j)$ attached to the entries of $v$ (matrix, or vector of vectors). \fun{GEN}{RgV_polint}{GEN X, GEN Y, long v} $X$ and $Y$ being two vectors of the same length, returns the polynomial $T$ in variable $v$ such that $T(X[i]) = Y[i]$ for all $i$. The special case $X = \kbd{NULL}$ corresponds to $X = [1,2,\dots,n]$, where $n$ is the length of $Y$. This is the function underlying \kbd{polint} for formal interpolation. \fun{GEN}{polintspec}{GEN X, GEN Y, GEN t, long n, long *pe} return $P(t)$ where $P$ is the Lagrange interpolation polynomial attached to the $n$ points $(X[0],Y[0]), \dots, (X[n-1],Y[n-1])$. If \kbd{pe} is not \kbd{NULL} and $t$ is a complex numeric value, \kbd{*pe} contains an error estimate for the returned value (Neville's algorithm, see \kbd{polinterpolate}). In extrapolation algorithms, e.g., Romberg integration, this function is usually called on actual \kbd{GEN} vectors with offsets: $x + k$ and $y + k$ so as to interpolate on $x[k..k+n-1]$ without having to use \kbd{vecslice}. This is the function underlying \kbd{polint} for numerical interpolation. \fun{GEN}{polint_i}{GEN X, GEN Y, GEN t, long *pe} as \kbd{polintspec}, where $X$ and $Y$ are actual \kbd{GEN} vectors. \fun{GEN}{vandermondeinverse}{GEN r, GEN T, GEN d, GEN V} Given a vector $r$ of $n$ scalars and the \typ{POL} $T = \prod_{i=1}^n (X - r_i)$, return $dM^{-1}$, where $M = (r_i^{j-1})_{1\leq i,j\leq n}$ is the van der Monde matrix; $V$ is \kbd{NULL} or a vector containing the $T'(r_i)$, as returned by \kbd{vandermodeinverseinit}. The demonimator $d$ may be set to \kbd{NULL} (handled as $1$). If $c$ is the $k$-column of the result, it is essentially $d$ times the $k$-th Lagrange interpolation polynomial: we have $\sum_j c_j r_i^{j-1} = d \delta_{i=k}$. This is the function underlying \kbd{RgV\_polint} when the base field is not $\Z/p\Z$: it uses $O(n^2)$ scalar operations and is asymptotically slower than variants using multi-evaluation such as \kbd{FpV\_polint}; it is also accurate over inexact fields. \fun{GEN}{vandermondeinverseinit}{GEN r} Given a vector $r$ of $n$ scalars, let $T$ be the \typ{POL} $T = \prod_{j=1}^n (X - r_j)$. This function returns the $T'(r_i)$ computed stably via products of difference: the $i$-th entry is $T'(r_i) = \prod_{j\neq i} (r_i - r_j)$. It is asymptotically slow (uses $O(n^2)$ scalar operations, where multi-evaluation achieves quasi-linear running time) but allows accurate computation at low accuracies when $T$ has large complex coefficients. \subsubsec{Special shapes} The following routines check whether matrices or vectors have a special shape, using \kbd{gequal1} and \kbd{gequal0} to test components. (This makes a difference when components are inexact.) \fun{int}{RgV_isscalar}{GEN x} return 1 if all the entries of $x$ are $0$ (as per \kbd{gequal0}), except possibly the first one. The name comes from vectors expressing polynomials on the standard basis $1,T,\dots, T^{n-1}$, or on \kbd{nf.zk} (whose first element is $1$). \fun{int}{QV_isscalar}{GEN x} as \kbd{RgV\_isscalar}, assuming $x$ is a \kbd{QV} (\typ{INT} and \typ{FRAC} entries only). \fun{int}{ZV_isscalar}{GEN x} as \kbd{RgV\_isscalar}, assuming $x$ is a \kbd{ZV} (\typ{INT} entries only). \fun{int}{RgM_isscalar}{GEN x, GEN s} return 1 if $x$ is the scalar matrix equal to $s$ times the identity, and 0 otherwise. If $s$ is \kbd{NULL}, test whether $x$ is an arbitrary scalar matrix. \fun{int}{RgM_isidentity}{GEN x} return 1 if the \typ{MAT} $x$ is the identity matrix, and 0 otherwise. \fun{int}{RgM_isdiagonal}{GEN x} return 1 if the \typ{MAT} $x$ is a diagonal matrix, and 0 otherwise. \fun{long}{RgC_is_ei}{GEN x} return $i$ if the \typ{COL} $x$ has $0$ entries, but for a $1$ at position $i$. \fun{int}{RgM_is_ZM}{GEN x} return 1 if the \typ{MAT}~$x$ has only \typ{INT} coefficients, and 0 otherwise. \fun{long}{qfiseven}{GEN M} return 1 if the square symmetric typ{ZM}~$x$ is an even quadratic form (all diagonal coefficients are even), and 0 otherwise. \fun{int}{RgM_is_QM}{GEN x} return 1 if the \typ{MAT}~$x$ has only \typ{INT} or \typ{FRAC} 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{long}{RgV_isin_i}{GEN v, GEN x, long n} return the first index $i\ leq n$ such that $v[i] = x$ if it exists, and $0$ otherwise. Naive search in linear time, does not assume that \kbd{v} is sorted. Assume that $n < \kbd{lg(v)}$. \fun{GEN}{RgM_diagonal}{GEN m} returns the diagonal of $m$ as a \typ{VEC}. \fun{GEN}{RgM_diagonal_shallow}{GEN m} shallow version of \kbd{RgM\_diagonal} \subsubsec{Conversion to floating point entries} \fun{GEN}{RgC_gtofp}{GEN x, GEN prec} returns the \typ{COL} obtained by applying \kbd{gtofp(gel(x,i), prec)} to all coefficients of $x$. \fun{GEN}{RgV_gtofp}{GEN x, GEN prec} returns the \typ{VEC} obtained by applying \kbd{gtofp(gel(x,i), prec)} to all coefficients of $x$. \fun{GEN}{RgC_gtomp}{GEN x, long prec} returns the \typ{COL} obtained by applying \kbd{gtomp(gel(x,i), prec)} to all coefficients of $x$. \fun{GEN}{RgC_fpnorml2}{GEN x, long prec} returns (a stack-clean variant of) \bprog gnorml2( RgC_gtofp(x, prec) ) @eprog \fun{GEN}{RgM_gtofp}{GEN x, GEN prec} returns the \typ{MAT} obtained by applying \kbd{gtofp(gel(x,i), prec)} to all coefficients of $x$. \fun{GEN}{RgM_gtomp}{GEN x, long prec} returns the \typ{MAT} obtained by applying \kbd{gtomp(gel(x,i), prec)} to all coefficients of $x$. \fun{GEN}{RgM_fpnorml2}{GEN x, long prec} returns (a stack-clean variant of) \bprog gnorml2( RgM_gtofp(x, prec) ) @eprog \subsubsec{Linear algebra, linear systems} \fun{GEN}{RgM_inv}{GEN a} returns a left inverse of $a$ (which needs not be square), or \kbd{NULL} if this turns out to be impossible. The latter happens when the matrix does not have maximal rank (or when rounding errors make it appear so). \fun{GEN}{RgM_inv_upper}{GEN a} as \kbd{RgM\_inv}, assuming that $a$ is a nonempty invertible upper triangular matrix, hence a little faster. \fun{GEN}{RgM_RgC_invimage}{GEN A, GEN B} returns a \typ{COL} $X$ such that $A X = B$ if one such exists, and \kbd{NULL} otherwise. \fun{GEN}{RgM_invimage}{GEN A, GEN B} returns a \typ{MAT} $X$ such that $A X = B$ if one such exists, and \kbd{NULL} otherwise. \fun{GEN}{RgM_Hadamard}{GEN a} returns a upper bound for the absolute value of $\text{det}(a)$. The bound is a \typ{INT}. \fun{GEN}{RgM_solve}{GEN a, GEN b} returns $a^{-1}b$ where $a$ is a square \typ{MAT} and $b$ is a \typ{COL} or \typ{MAT}. Returns \kbd{NULL} if $a^{-1}$ cannot be computed, see \tet{RgM_inv}. If $b = \kbd{NULL}$, the matrix $a$ need no longer be square, and we strive to return a left inverse for $a$ (\kbd{NULL} if it does not exist). \fun{GEN}{RgM_solve_realimag}{GEN M, GEN b} $M$ being a \typ{MAT} with $r_1+r_2$ rows and $r_1+2r_2$ columns, $y$ a \typ{COL} or \typ{MAT} such that the equation $Mx = y$ makes sense, returns $x$ under the following simplifying assumptions: the first $r_1$ rows of $M$ and $y$ are real (the $r_2$ others are complex), and $x$ is real. This is stabler and faster than calling $\kbd{RgM\_solve}(M, b)$ over $\C$. In most applications, $M$ approximates the complex embeddings of an integer basis in a number field, and $x$ is actually rational. \fun{GEN}{split_realimag}{GEN x, long r1, long r2} $x$ is a \typ{COL} or \typ{MAT} with $r_1 + r_2$ rows, whose first $r_1$ rows have real entries (the $r_2$ others are complex). Return an object of the same type as $x$ and $r_1 + 2r_2$ rows, such that the first $r_1 + r_2$ rows contain the real part of $x$, and the $r_2$ following ones contain the imaginary part of the last $r_2$ rows of $x$. Called by \tet{RgM_solve_realimag}. \fun{GEN}{RgM_det_triangular}{GEN x} returns the product of the diagonal entries of $x$ (its determinant if it is indeed triangular). \fun{GEN}{Frobeniusform}{GEN V, long n} given the vector $V$ of elementary divisors for $M - x\text{Id}$, where $M$ is an $n\times n$ square matrix. Returns the Frobenius form of $M$. \fun{int}{RgM_QR_init}{GEN x, GEN *pB, GEN *pQ, GEN *pL, long prec} QR-decomposition of a square invertible \typ{MAT} $x$ with real coefficients. Sets \kbd{*pB} to the vector of squared lengths of the $x[i]$, \kbd{*pL} to the Gram-Schmidt coefficients and \kbd{*pQ} to a vector of successive Householder transforms. If $R$ denotes the transpose of $L$ and $Q$ is the result of applying \kbd{*pQ} to the identity matrix, then $x = QR$ is the QR decomposition of $x$. Returns $0$ is $x$ is not invertible or we hit a precision problem, and $1$ otherwise. \fun{int}{QR_init}{GEN x, GEN *pB, GEN *pQ, GEN *pL, long prec} as \kbd{RgM\_QR\_init}, assuming further that $x$ has \typ{INT} or \typ{REAL} coefficients. \fun{GEN}{R_from_QR}{GEN x, long prec} assuming that $x$ is a square invertible \typ{MAT} with \typ{INT} or \typ{REAL} coefficients, return the upper triangular $R$ from the $QR$ docomposition of $x$. Not memory clean. If the matrix is not known to have \typ{INT} or \typ{REAL} coefficients, apply \tet{RgM_gtomp} first. \fun{GEN}{gaussred_from_QR}{GEN x, long prec} assuming that $x$ is a square invertible \typ{MAT} with \typ{INT} or \typ{REAL} coefficients, returns \kbd{qfgaussred(x\til * x)}; this is essentially the upper triangular $R$ matrix from the $QR$ decomposition of $x$, renormalized to accomodate \kbd{qfgaussred} conventions. Not memory clean. \fun{GEN}{RgM_gram_schmidt}{GEN e, GEN *ptB} naive (unstable) Gram-Schmidt orthogonalization of the basis $(e_i)$ given by the columns of \typ{MAT} $e$. Return the $e_i^*$ (as columns of a \typ{MAT}) and set \kbd{*ptB} to the vector of squared lengths $|e_i^*|^2$. \fun{GEN}{RgM_Babai}{GEN M, GEN y} given a \typ{MAT} $M$ of maximal rank $n$ and a \typ{COL} $y$ of the same dimension, apply Babai's nearest plane algorithm to return an \emph{integral} $x$ such that $y - Mx$ has small $L_2$ norm. This yields an approximate solution to the closest vector problem: if $M$ is LLL-reduced, then $$|| y - Mx ||_2 \leq 2 (2/\sqrt{3})^n || y - MX ||_2$$ for all $X \in \Z^n$. \fun{GEN}{RgM_Cholesky}{GEN M} given a square symmetric \typ{MAT} $M$, return $R$ such that $^t{}R\*R = M$, or \kbd{NULL} is no solution is found ($M$ is not positive or was given with insufficient accuracy). \subsec{\kbd{ZG}} Let $G$ be a multiplicative group with neutral element $1_G$ whose multiplication is supported by \kbd{gmul} and where equality test is performed using \tet{gidentical}, e.g. a matrix group. The following routines implement basic computations in the group algebra $\Z[G]$. All of them are shallow for efficiency reasons. A \kbd{ZG} is either \item a \typ{INT} $n$, representing $n[1_G]$ \item or a ``factorization matrix'' with two columns $[g,e]$: the first one contains group elements, sorted according to \tet{cmp_universal}, and the second one contains integer ``exponents'', representing $\sum e_i [g_i]$. Note that \tet{to_famat} and \tet{to_famat_shallow}$(g,e)$ allow to build the \kbd{ZG} $e[g]$ from $e\in \Z$ and $g\in G$. \fun{GEN}{ZG_normalize}{GEN x} given a \typ{INT} $x$ or a factorization matrix \emph{without} assuming that the first column is properly sorted. Return a valid (sorted) \kbd{ZG}. Shallow function. \fun{GEN}{ZG_add}{GEN x, GEN y} return $x+y$; shallow function. \fun{GEN}{ZG_neg}{GEN x} return $-x$; shallow function. \fun{GEN}{ZG_sub}{GEN x, GEN y} return $x-y$; shallow function. \fun{GEN}{ZG_mul}{GEN x, GEN y} return $xy$; shallow function. \fun{GEN}{ZG_G_mul}{GEN x, GEN y} given a \kbd{ZG} $x$ and $y\in G$, return $xy$; shallow function. \fun{GEN}{G_ZG_mul}{GEN x, GEN y} given a \kbd{ZG} $y$ and $x\in G$, return $xy$; shallow function. \fun{GEN}{ZG_Z_mul}{GEN x, GEN n} given a \kbd{ZG} $x$ and $y\in \Z$, return $xy$; shallow function. \fun{GEN}{ZGC_G_mul}{GEN v, GEN x} given $v$ a vector of \kbd{ZG} and $x\in G$ return the vector (with the same type as $v$ with entries $v[i]\cdot x$. Shallow function. \fun{void}{ZGC_G_mul_inplace}{GEN v, GEN x} as \tet{ZGC_G_mul}, modifying $v$ in place. \fun{GEN}{ZGC_Z_mul}{GEN v, GEN n} given $v$ a vector of \kbd{ZG} and $n\in Z$ return the vector (with the same type as $v$ with entries $n \cdot v[i]$. Shallow function. \fun{GEN}{G_ZGC_mul}{GEN x, GEN v} given $v$ a vector of \kbd{ZG} and $x\in G$ return the vector of $x \cdot v[i]$. Shallow function. \fun{GEN}{ZGCs_add}{GEN x, GEN y} add two sparse vectors of \kbd{ZG} elements (see Sparse linear algebra below). \subsec{Sparse and blackbox linear algebra} A sparse column \kbd{zCs} $v$ is a \typ{COL} with two components $C$ and $E$ which are \typ{VECSMALL} of the same length, representing $\sum_i E[i]*e_{C[i]}$, where $(e_j)$ is the canonical basis. A sparse matrix (\kbd{zMs}) is a \typ{VEC} of \kbd{zCs}. \kbd{FpCs} and \kbd{FpMs} are identical to the above, but $E[i]$ is now interpreted as a \emph{signed} C long integer representing an element of $\F_p$. This is important since $p$ can be so large that $p+E[i]$ would not fit in a C long. \kbd{RgCs} and \kbd{RgMs} are similar, except that the type of the components of $E$ is now unspecified. Functions handling those later objects must not depend on the type of those components. \kbd{F2Ms} are \typ{VEC} of \kbd{F2Cs}. \kbd{F2Cs} are \typ{VECSMALL} whoses entries are the nonzero coefficients ($1$). It is not possible to derive the space dimension (number of rows) from the above data. Thus most functions take an argument \kbd{nbrow} which is the number of rows of the corresponding column/matrix in dense representation. \fun{GEN}{F2Ms_to_F2m}{GEN M, long nbrow} convert a \kbd{F2m} to a \kbd{F2Ms}. \fun{GEN}{F2m_to_F2Ms}{GEN M} convert a \kbd{F2m} to a \kbd{F2Ms}. \fun{GEN}{zCs_to_ZC}{GEN C, long nbrow} convert the sparse vector $C$ to a dense \kbd{ZC} of dimension \kbd{nbrow}. \fun{GEN}{zMs_to_ZM}{GEN M, long nbrow} convert the sparse matrix $M$ to a dense \kbd{ZM} whose columns have dimension \kbd{nbrow}. \fun{GEN}{FpMs_FpC_mul}{GEN M, GEN B, GEN p} multiply the sparse matrix $M$ (over $\F_p$) by the \kbd{FpC} $B$. The result is an \kbd{FpC}, i.e.~a dense vector. \fun{GEN}{zMs_ZC_mul}{GEN M, GEN B, GEN p} multiply the sparse matrix $M$ by the \kbd{ZC} $B$ (over $\Z$). The result is an \kbd{ZC}, i.e.~a dense vector. \fun{GEN}{FpV_FpMs_mul}{GEN B, GEN M, GEN p} multiply the \kbd{FpV} $B$ by the sparse matrix $M$ (over $\F_p$). The result is an \kbd{FpV}, i.e.~a dense vector. \fun{GEN}{ZV_zMs_mul}{GEN B, GEN M, GEN p} multiply the \kbd{FpV} $B$ (over $\Z$) by the sparse matrix $M$. The result is an \kbd{ZV}, i.e.~a dense vector. \fun{void}{RgMs_structelim}{GEN M, long nbrow, GEN A, GEN *p_col, GEN *p_row} $M$ being a RgMs with \kbd{nbrow} rows, $A$ being a list of row indices, perform structured elimination on $M$ by removing some rows and columns until the number of effectively present rows is equal to the number of columns. The result is stored in two \typ{VECSMALL}s, \kbd{*p\_col} and \kbd{*p\_row}: \kbd{*p\_col} is a map from the new columns indices to the old one. \kbd{*p\_row} is a map from the old rows indices to the new one ($0$ if removed). \fun{GEN}{F2Ms_colelim}{GEN M, long nbrow} returns some subset of the columns of $M$ as a \typ{VECSMALL} of indices, selected such that the dimension of the kernel of the matrix is preserved. The subset is not guaranteed to be minimal. \fun{GEN}{F2Ms_ker}{GEN M, long nbrow} returns some kernel vectors of $M$ using block Lanczos algorithm. \fun{GEN}{FpMs_leftkernel_elt}{GEN M, long nbrow, GEN p} $M$ being a sparse matrix over $\F_p$, return a nonzero \kbd{FpV} $X$ such that $X\*M$ components are almost all $0$. \fun{GEN}{FpMs_FpCs_solve}{GEN M, GEN B, long nbrow, GEN p} solve the equation $M\*X = B$, where $M$ is a sparse matrix and $B$ is a sparse vector, both over $\F_p$. Return either a solution as a \typ{COL} (dense vector), the index of a column which is linearly dependent from the others as a \typ{VECSMALL} with a single component, or \kbd{NULL} (can happen if $B$ is not in the image of $M$). \fun{GEN}{FpMs_FpCs_solve_safe}{GEN M, GEN B, long nbrow, GEN p} as above, but in the event that $p$ is not a prime and an impossible division occurs, return \kbd{NULL}. \fun{GEN}{ZpMs_ZpCs_solve}{GEN M, GEN B, long nbrow, GEN p, long e} solve the equation $MX = B$, where $M$ is a sparse matrix and $B$ is a sparse vector, both over $\Z/p^e\Z$. Return either a solution as a \typ{COL} (dense vector), or the index of a column which is linearly dependent from the others as a \typ{VECSMALL} with a single component. \fun{GEN}{gen_FpM_Wiedemann}{void *E, GEN (*f)(void*, GEN), GEN B, GEN p} solve the equation $f(X) = B$ over $\F_p$, where $B$ is a \kbd{FpV}, and $f$ is a blackbox endomorphism, where $f(E, X)$ computes the value of $f$ at the (dense) column vector $X$. Returns either a solution \typ{COL}, or a kernel vector as a \typ{VEC}. \fun{GEN}{gen_ZpM_Dixon_Wiedemann}{void *E, GEN (*f)(void*, GEN), GEN B, GEN p, long e} solve equation $f(X) = B$ over $\Z/p^e\Z$, where $B$ is a \kbd{ZV}, and $f$ is a blackbox endomorphism, where $f(E, X)$ computes the value of $f$ at the (dense) column vector $X$. Returns either a solution \typ{COL}, or a kernel vector as a \typ{VEC}. \subsec{Obsolete functions} The functions in this section are kept for backward compatibility only and will eventually disappear. \fun{GEN}{image2}{GEN x} compute the image of $x$ using a very slow algorithm. Use \tet{image} instead. \section{Integral, rational and generic polynomial arithmetic} \subsec{\kbd{ZX}} \fun{void}{RgX_check_ZX}{GEN x, const char *s} Assuming \kbd{x} is a \typ{POL} raise an error if it is not a \kbd{ZX} ($s$ should point to the name of the caller). \fun{GEN}{ZX_copy}{GEN x,GEN p} returns a copy of \kbd{x}. \fun{long}{ZX_max_lg}{GEN x} returns the effective length of the longest component in $x$. \fun{GEN}{scalar_ZX}{GEN x, long v} returns the constant \kbd{ZX} in variable $v$ equal to the \typ{INT} $x$. \fun{GEN}{scalar_ZX_shallow}{GEN x, long v} returns the constant \kbd{ZX} in variable $v$ equal to the \typ{INT} $x$. Shallow function not suitable for \kbd{gerepile} and friends. \fun{GEN}{ZX_renormalize}{GEN x, long l}, as \kbd{normalizepol}, where $\kbd{l} = \kbd{lg(x)}$, in place. \fun{int}{ZX_equal}{GEN x, GEN y} returns $1$ if the two \kbd{ZX} have the same \kbd{degpol} and their coefficients are equal. Variable numbers are not checked. \fun{int}{ZX_equal1}{GEN x} returns $1$ if the \kbd{ZX} $x$ is equal to $1$ and $0$ otherwise. \fun{int}{ZX_is_monic}{GEN x} returns $1$ if the \kbd{ZX} $x$ is monic and $0$ otherwise. The zero polynomial considered not monic. \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} returns $-\kbd{x}$. \fun{GEN}{ZX_Z_add}{GEN x,GEN y} adds the integer \kbd{y} to the \kbd{ZX}~\kbd{x}. \fun{GEN}{ZX_Z_add_shallow}{GEN x,GEN y} shallow version of \tet{ZX_Z_add}. \fun{GEN}{ZX_Z_sub}{GEN x,GEN y} subtracts the integer \kbd{y} to the \kbd{ZX}~\kbd{x}. \fun{GEN}{Z_ZX_sub}{GEN x,GEN y} subtracts the \kbd{ZX} \kbd{y} to the integer \kbd{x}. \fun{GEN}{ZX_Z_mul}{GEN x,GEN y} multiplies the \kbd{ZX} \kbd{x} by the integer \kbd{y}. \fun{GEN}{ZX_mulu}{GEN x, ulong y} multiplies \kbd{x} by the integer \kbd{y}. \fun{GEN}{ZX_shifti}{GEN x, long n} shifts all coefficients of \kbd{x} by $n$ bits, which can be negative. \fun{GEN}{ZX_Z_divexact}{GEN x, GEN y} returns $x/y$ assuming all divisions are exact. \fun{GEN}{ZX_divuexact}{GEN x, ulong y} returns $x/y$ assuming all divisions are exact. \fun{GEN}{ZX_remi2n}{GEN x, long n} reduces all coefficients of \kbd{x} to $n$ bits, using \tet{remi2n}. \fun{GEN}{ZX_mul}{GEN x,GEN y} multiplies \kbd{x} and \kbd{y}. \fun{GEN}{ZX_sqr}{GEN x,GEN p} returns $\kbd{x}^2$. \fun{GEN}{ZX_mulspec}{GEN a, GEN b, long na, long nb}. Internal routine: \kbd{a} and \kbd{b} are arrays of coefficients representing polynomials $\sum_{i = 0}^{\kbd{na-1}} \kbd{a}[i] X^i$ and $\sum_{i = 0}^{\kbd{nb-1}} \kbd{b}[i] X^i$. Returns their product (as a true \kbd{GEN}) in variable $0$. \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}) in variable $0$. \fun{GEN}{ZX_rem}{GEN x, GEN y} returns the remainder of the Euclidean division of $x$ mod $y$. Assume that $x$, $y$ are two \kbd{ZX} and that $y$ is monic. \fun{GEN}{ZX_mod_Xnm1}{GEN T, ulong n} return $T$ modulo $X^n - 1)$. Shallow function. \fun{GEN}{ZX_div_by_X_1}{GEN T, GEN *r} return the quotient of $T$ by $X-1$. If $r$ is not \kbd{NULL} set it to $T(1)$. \fun{GEN}{ZX_digits}{GEN x, GEN B} returns a vector of \kbd{ZX} $[c_0,\ldots,c_n]$ of degree less than the degree of $B$ and such that $x=\sum_{i=0}^{n}{c_i\*B^i}$. Assume that $B$ is monic. \fun{GEN}{ZXV_ZX_fromdigits}{GEN v, GEN B} where $v=[c_0,\ldots,c_n]$ is a vector of \kbd{ZX}, returns $\sum_{i=0}^{n}{c_i\*B^i}$. \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 (nonzero) 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. \fun{GEN}{ZX_radical}{GEN x} returns the largest squarefree divisor of the \kbd{ZX} $x$. Not memory clean. \fun{GEN}{ZX_content}{GEN x} returns the content of the \kbd{ZX} $x$. \fun{long}{ZX_val}{GEN P} as \kbd{RgX\_val}, but assumes \kbd{P} has \typ{INT} coefficients. \fun{long}{ZX_valrem}{GEN P, GEN *z} as \kbd{RgX\_valrem}, but assumes \kbd{P} has \typ{INT} coefficients. \fun{GEN}{ZX_to_monic}{GEN q GEN *L} given $q$ a nonzero \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}. Shallow function. \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. Shallow function. \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$. Shallow function. \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. Shallow function. \fun{GEN}{ZX_Q_mul}{GEN x, GEN y} returns $x*y$, where $y$ is a rational number and the resulting \typ{POL} has rational entries. \fun{long}{ZX_deflate_order}{GEN P} given a nonconstant \kbd{ZX} $P$, returns the largest exponent $d$ such that $P$ is of the form $P(x^d)$. \fun{long}{ZX_deflate_max}{GEN P, long *d}. Given a nonconstant polynomial with integer coefficients $P$, sets \kbd{d} to \kbd{ZX\_deflate\_order(P)} and returns \kbd{RgX\_deflate(P,d)}. Shallow function. \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 nonzero integer. Neither memory-clean nor suitable for \kbd{gerepileupto}. \fun{GEN}{ZX_rescale2n}{GEN P, long n} returns $2^{n\deg(P)} P(x>>n)$ where \kbd{P} is a \kbd{ZX}. \fun{GEN}{ZX_rescale_lt}{GEN P} returns the monic integral polynomial $h^{\deg(P)-1} P(x/h)$, where \kbd{P} is a nonzero \kbd{ZX} and \kbd{h} is its leading coefficient. Neither memory-clean nor suitable for \kbd{gerepileupto}. \fun{GEN}{ZX_translate}{GEN P, GEN c} assume $P$ is a \kbd{ZX} and $c$ an integer. Returns $P(X + c)$ (optimized for $c = \pm 1$). \fun{GEN}{ZX_affine}{GEN P, GEN a, GEN b} $P$ is a \kbd{ZX}, $a$ and $b$ are \typ{INT}. Return $P(aX + b)$ (optimized for $b = \pm 1$). Not memory clean. \fun{GEN}{ZX_Z_eval}{GEN P,GEN x} evaluate the \kbd{ZX} $P$ at the integer $x$. \fun{GEN}{ZX_unscale}{GEN P, GEN h} given a \kbd{ZX} $P$ and a \typ{INT} $h$, returns $P(hx)$. Not memory clean. \fun{GEN}{ZX_z_unscale}{GEN P, long h} given a \kbd{ZX} $P$, returns $P(hx)$. Not memory clean. \fun{GEN}{ZX_unscale2n}{GEN P, long n} given a \kbd{ZX} $P$, returns $P(x< 0$, returns $P(hx)/h^k$ assuming the result has integral coefficients. Not memory clean. \fun{GEN}{ZX_eval1}{GEN P} returns the integer $P(1)$. \fun{GEN}{ZX_graeffe}{GEN p} returns the Graeffe transform of $p$, i.e. the \kbd{ZX} $q$ such that $p(x)p(-x) = q(x^2)$. \fun{GEN}{ZX_deriv}{GEN x} returns the derivative of \kbd{x}. \fun{GEN}{ZX_resultant}{GEN A, GEN B} returns the resultant of the \kbd{ZX}~\kbd{A} and \kbd{B}. \fun{GEN}{ZX_disc}{GEN T} returns the discriminant of the \kbd{ZX} \kbd{T}. \fun{GEN}{ZX_factor}{GEN T} returns the factorization of the primitive part of \kbd{T} over $\Q[X]$ (the content is lost). \fun{int}{ZX_is_squarefree}{GEN T} returns $1$ if the \kbd{ZX}~\kbd{T} is squarefree, $0$ otherwise. \fun{long}{ZX_is_irred}{GEN T} returns 1 it \kbd{T} is irreducible, and 0 otherwise. \fun{GEN}{ZX_squff}{GEN T, GEN *E} write the nonzero \kbd{ZX} $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}. For efficiency, powers of $x$ should have been removed from $T$ using \kbd{ZX\_valrem}, but the result is also correct if not. Not memory clean. \fun{GEN}{ZX_Uspensky}{GEN P, GEN ab, long flag, long bitprec} let \kbd{P} be a \kbd{ZX} polynomial whose real roots are simple and \kbd{bitprec} is the relative precision in bits. For efficiency reasons, \kbd{P} should not only have simple real roots but actually be primitive and squarefree, but the routine neither checks nor enforces this, and it returns correct results in this case as well. \item If \kbd{flag} is 0 returns a list of intervals that isolate the real roots of \kbd{P}. The return value is a column of elements which are either vectors \kbd{[a,b]} of rational numbers meaning that there is a single nonrational root in the open interval \kbd{(a,b)} or elements \kbd{x0} such that \kbd{x0} is a rational root of \kbd{P}. Beware that the limits of the open intervals can be roots of the polynomial. \item If \kbd{flag} is 1 returns an approximation of the real roots of \kbd{P}. \item If \kbd{flag} is 2 returns the number of roots. The argument \kbd{ab} specify the interval in which the roots are searched. The default interval is $(-\infty,\infty)$. If \kbd{ab} is an integer or fraction $a$ then the interval is $[a,\infty)$. If \kbd{ab} is a vector $[a,b]$, where \typ{INT}, \typ{FRAC} or \typ{INFINITY} are allowed for $a$ and $b$, the interval is $[a,b]$. \fun{long}{ZX_sturm}{GEN P} number of real roots of the nonconstant squarefree \kbd{ZX} $P$. For efficiency, it is advised to make $P$ primitive first. \fun{long}{ZX_sturmpart}{GEN P, GEN ab} number of real roots of the nonconstant squarefree \kbd{ZX} $P$ in the interval specified by \kbd{ab}: either \kbd{NULL} (no restriction) or a \typ{VEC} $[a,b]$ with two real components (of type \typ{INT}, \typ{FRAC} or \typ{INFINITY}). For efficiency, it is advised to make $P$ primitive first. \fun{long}{ZX_sturm_irred}{GEN P} number of real roots of the \kbd{ZX} $P$, assumed irreducible over $\Q[X]$. For efficiency, it is advised to make $P$ primitive first. \fun{long}{ZX_realroots_irred}{GEN P, long prec} real roots of the \kbd{ZX} $P$, assumed irreducible over $\Q[X]$ to precision prec. For efficiency, it is advised to make $P$ primitive first. \subsec{Resultants} \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_composedsum}{GEN P, GEN Q} if $P=a\prod_i(x-p_i)$ and $Q=b\prod_j(x-q_j)$ in some suitable algebraic extension, return $a\*b\prod_{i,j}(x-(p_i+q_j))$. \fun{GEN}{ZX_compositum}{GEN A, GEN B, long *lambda} given two irreducible \kbd{ZX}, returns an irreducible \kbd{ZX} $C$ defining their compositum and set \kbd{lambda} to a small integer $k$ such that if $\alpha$ is a root of $A$ and $\beta$ is a root of $B$, then $k\*\alpha + \beta$ is a root of $C$. \fun{GEN}{ZX_ZXY_rnfequation}{GEN A, GEN B, long *lambda}, assume \kbd{A} in $\Z[Y]$, \kbd{B} in $\Q[Y][X]$, and $R = \text{Res}_Y(A, B) \in \Z[X]$. If \kbd{lambda = NULL}, returns $R$ as in \kbd{ZY\_ZXY\_resultant}. Otherwise, \kbd{lambda} must point to some integer, e.g. $0$ which is used as a seed. The function then finds a small $\lambda \in \Z$ (starting from \kbd{*lambda}) such that $R_\lambda(X) := \text{Res}_Y(A, B(X + \lambda Y))$ is squarefree, resets \kbd{*lambda} to the chosen value and returns $R_{\lambda}$. \subsec{\kbd{ZXV}} \fun{GEN}{ZXV_equal}{GEN x,GEN y} returns $1$ if the two vectors of \kbd{ZX} are equal, as per \tet{ZX_equal} (variables are not checked to be equal) and $0$ otherwise. \fun{GEN}{ZXV_Z_mul}{GEN x,GEN y} multiplies the vector of \kbd{ZX} \kbd{x} by the integer \kbd{y}. \fun{GEN}{ZXV_remi2n}{GEN x, long n} applies \kbd{ZX\_remi2n} to all coefficients of \kbd{x}. \fun{GEN}{ZXV_dotproduct}{GEN x,GEN y} as \kbd{RgV\_dotproduct} assuming $x$ and $y$ have \kbd{ZX} entries. \subsec{\kbd{ZXT}} \fun{GEN}{ZXT_remi2n}{GEN x, long n} applies \kbd{ZX\_remi2n} to all leaves of the tree \kbd{x}. \subsec{\kbd{ZXQ}} \fun{GEN}{ZXQ_mul}{GEN x,GEN y,GEN T} returns $x*y$ mod $T$, assuming that all inputs are \kbd{ZX}s and that $T$ is monic. \fun{GEN}{ZXQ_sqr}{GEN x,GEN T} returns $x^2$ mod $T$, assuming that all inputs are \kbd{ZX}s and that $T$ is monic. \fun{GEN}{ZXQ_powu}{GEN x,ulong n,GEN T} returns $x^n$ mod $T$, assuming that all inputs are \kbd{ZX}s and that $T$ is monic. \fun{GEN}{ZXQ_powers}{GEN x, long n, GEN T} returns $[\kbd{x}^0, \dots, \kbd{x}^\kbd{n}]$ mod $T$ as a \typ{VEC}, assuming that all inputs are \kbd{ZX}s and that $T$ is monic. \fun{GEN}{ZXQ_charpoly}{GEN A, GEN T, long v}: let \kbd{T} and \kbd{A} be \kbd{ZX}s, returns the characteristic polynomial of \kbd{Mod(A, T)}. More generally, \kbd{A} is allowed to be a \kbd{QX}, hence possibly has rational coefficients, \emph{assuming} the result is a \kbd{ZX}, i.e.~the algebraic number \kbd{Mod(A,T)} is integral over \kbd{Z}. \fun{GEN}{ZXQ_minpoly}{GEN A, GEN B, long d, ulong bound} let \kbd{T} and \kbd{A} be \kbd{ZX}s, returns the minimal polynomial of \kbd{Mod(A, T)} assuming it has degree $d$ and its coefficients are less than $2^{\text{bound}}$. 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}. \subsec{\kbd{ZXn}} \fun{GEN}{ZXn_mul}{GEN x, GEN y, long n} return $x\*y\pmod{X^n}$. \fun{GEN}{ZXn_sqr}{GEN x, long n} return $x^2\pmod{X^n}$. \fun{GEN}{eta_ZXn}{long r, long n} return $\eta(X^r) = \prod_{i>0} (1-X^{ri}) \pmod{X^n}$, $r > 0$. \fun{GEN}{eta_product_ZXn}{GEN DR, long n}: $\kbd{DR}= [D,R]$ being a vector with two \typ{VECSMALL} components, return $\prod_i \eta(X^{d_i})^{r_i}$. Shallow function. \subsec{\kbd{ZXQM}} \kbd{ZXQM} are matrices of \kbd{ZXQ}. All entries must be integers or polynomials of degree strictly less than the degree of $T$. \fun{GEN}{ZXQM_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}{ZXQM_sqr}{GEN x,GEN T} returns $x^2$ mod $T$, assuming that all inputs are \kbd{ZX}s and that $T$ is monic. \subsec{\kbd{ZXQX}} \fun{GEN}{ZXQX_mul}{GEN x,GEN y,GEN T} returns $x*y$, assuming that all inputs are \kbd{ZXQX}s and that $T$ is monic. \fun{GEN}{ZXQX_ZXQ_mul}{GEN x, GEN y, GEN T} returns $x*y$, assuming that $x$ is a \kbd{ZXQX}, $y$ is a \kbd{ZXQ} and $T$ is monic. \fun{GEN}{ZXQX_sqr}{GEN x,GEN T} returns $x^2$, assuming that all inputs are \kbd{ZXQX}s and that $T$ is monic. \fun{GEN}{ZXQX_gcd}{GEN x,GEN y,GEN T} returns the gcd of $x$ and $y$, assuming that all inputs are \kbd{ZXQX}s and that $T$ is monic. \subsec{\kbd{ZXX}} \fun{void}{RgX_check_ZXX}{GEN x, const char *s} Assuming \kbd{x} is a \typ{POL} raise an error if it one of its coefficients is not an integer or a \kbd{ZX} ($s$ should point to the name of the caller). \fun{GEN}{ZXX_renormalize}{GEN x, long l}, as \kbd{normalizepol}, where $\kbd{l} = \kbd{lg(x)}$, in place. \fun{long}{ZXX_max_lg}{GEN x} returns the effective length of the longest component in $x$; assume all coefficients are \typ{INT} or \kbd{ZX}s. \fun{GEN}{ZXX_evalx0}{GEN P} returns $P(X, 0)$. \fun{GEN}{ZXX_Z_mul}{GEN x, GEN y} returns $x\*y$. \fun{GEN}{ZXX_Q_mul}{GEN x, GEN y} returns $x*y$, where $y$ is a rational number and the resulting \typ{POL} has rational entries. \fun{GEN}{ZXX_Z_add_shallow}{GEN x, GEN y} returns $x+y$. Shallow function. \fun{GEN}{ZXX_Z_divexact}{GEN x, GEN y} returns $x/y$ assuming all integer divisions are exact. \fun{GEN}{Kronecker_to_ZXX}{GEN z, long n, long v} recover $P(X,Y)$ from its Kronecker form $P(X,X^{2\*n-1})$ (see \tet{RgXX_to_Kronecker}), $v$ is the variable number corresponding to $Y$. Shallow function. \fun{GEN}{Kronecker_to_ZXQX}{GEN z, GEN T}. Let $n = \deg T$ and let $P(X,Y)\in \Z[X,Y]$ lift a polynomial in $K[Y]$, where $K := \Z[X]/(T)$ and $\deg_X P < 2n-1$ --- such as would result from multiplying minimal degree lifts of two polynomials in $K[Y]$. Let $z = P(t,t^{2*n-1})$ be a Kronecker form of $P$ (see \tet{RgXX_to_Kronecker}), this function returns $Q\in \Z[X,t]$ such that $Q$ is congruent to $P(X,t)$ mod $(T(X))$, $\deg_X Q < n$. Not stack-clean. Note that $t$ need not be the same variable as $Y$! \fun{GEN}{ZXX_mul_Kronecker}{GEN P, GEN Q, long n} return \tet{ZX_mul} applied to the Kronecker forms $P(X,X^{2\*n-1})$ and $Q(X,X^{2\*n-1})$ of $P$ and $Q$. Not memory clean. \fun{GEN}{ZXX_sqr_Kronecker}{GEN P, long n} return \tet{ZX_sqr} applied to the Kronecker forms $P(X,X^{2\*n-1})$ of $P$. Not memory clean. \subsec{\kbd{QX}} \fun{void}{RgX_check_QX}{GEN x, const char *s} Assuming \kbd{x} is a \typ{POL} raise an error if it is not a \kbd{QX} ($s$ should point to the name of the caller). \fun{GEN}{QX_mul}{GEN x,GEN y} \fun{GEN}{QX_sqr}{GEN x} \fun{GEN}{QX_ZX_rem}{GEN x, GEN y} $y$ is assumed to be monic. \fun{GEN}{QX_gcd}{GEN x,GEN y} returns a gcd of the \kbd{QX} $x$ and $y$. \fun{GEN}{QX_disc}{GEN T} returns the discriminant of the \kbd{QX} \kbd{T}. \fun{GEN}{QX_factor}{GEN T} as \kbd{ZX\_factor}. \fun{GEN}{QX_resultant}{GEN A, GEN B} returns the resultant of the \kbd{QX}~\kbd{A} and \kbd{B}. \fun{GEN}{QX_complex_roots}{GEN p, long l} returns the complex roots of the \kbd{QX} $p$ at accuracy $l$, where real roots are returned as \typ{REAL}s. More efficient when $p$ is irreducible and primitive. Special case of \tet{cleanroots}. \subsec{\kbd{QXQ}} \fun{GEN}{QXQ_norm}{GEN A, GEN B} $A$ being a \kbd{QX} and $B$ being a \kbd{ZX}, returns the norm of the algebraic number $A \mod B$, using a modular algorithm. To ensure that $B$ is a \kbd{ZX}, one may replace it by \kbd{Q\_primpart(B)}, which of course does not change the norm. If $A$ is not a \kbd{ZX} --- it has a denominator ---, but the result is nevertheless known to be an integer, it is much more efficient to call \tet{QXQ_intnorm} instead. \fun{GEN}{QXQ_intnorm}{GEN A, GEN B} $A$ being a \kbd{QX} and $B$ being a \kbd{ZX}, returns the norm of the algebraic number $A \mod B$, \emph{assuming} that the result is an integer, which is for instance the case is $A\mod B$ is an algebraic integer, in particular if $A$ is a \kbd{ZX}. To ensure that $B$ is a \kbd{ZX}, one may replace it by \kbd{Q\_primpart(B)} (which of course does not change the norm). If the result is not known to be an integer, you must use \tet{QXQ_norm} instead, which is slower. \fun{GEN}{QXQ_mul}{GEN A, GEN B, GEN T} returns the product of $A$ and $B$ modulo $T$ where both $A$ and $B$ are a \kbd{QX} and $T$ is a monic \kbd{ZX}. \fun{GEN}{QXQ_sqr}{GEN A, GEN T} returns the square of $A$ modulo $T$ where $A$ is a \kbd{QX} and $T$ is a monic \kbd{ZX}. \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_div}{GEN A, GEN B, GEN T} returns $A/B$ modulo $T$ where $A$ and $B$ are \kbd{QX} and $T$ is a \kbd{ZX}. Use this function when the result is expected to be of the same size as $B^{-1}$ mod $T$ or smaller. Otherwise, it will be faster to use \tet{QXQ_mul(A,QXQ_inv(B,T),T)}. \fun{GEN}{QXQ_charpoly}{GEN A, GEN T, long v} where \kbd{A} is a \kbd{QX} and \kbd{T} is a \kbd{ZX}, returns the characteristic polynomial of \kbd{Mod(A, T)}. If the result is known to be a \kbd{ZX}, then calling \kbd{ZXQ\_charpoly} will be faster. \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). Assume that $x$ is a \kbd{QX} and $T$ is a \kbd{ZX}. Meant to precompute powers of algebraic integers in $\Q[t]/(T)$. \fun{GEN}{QXQ_reverse}{GEN f, GEN T} as \kbd{RgXQ\_reverse}, assuming $f$ is a \kbd{QX}. \fun{GEN}{QX_ZXQV_eval}{GEN f, GEN nV, GEN dV} as \kbd{RgX\_RgXQV\_eval}, except that $f$ is assumed to be a \kbd{QX}, $V$ is given implicitly by a numerator \kbd{nV} (\kbd{ZV}) and denominator \kbd{dV} (a positive \typ{INT} or \kbd{NULL} for trivial denominator). Not memory clean, but suitable for \kbd{gerepileupto}. \fun{GEN}{QXV_QXQ_eval}{GEN v, GEN a, GEN T} $v$ is a vector of \kbd{QX}s (possibly scalars, i.e.~rational numbers, for convenience), $a$ and $T$ both \kbd{QX}. Return the vector of evaluations at $a$ modulo $T$. Not memory clean, nor suitable for \kbd{gerepileupto}. \fun{GEN}{QXY_QXQ_evalx}{GEN P, GEN a, GEN T} $P(X,Y)$ is a \typ{POL} with \kbd{QX} coefficients (possibly scalars, i.e.~rational numbers, for convenience) , $a$ and $T$ both \kbd{QX}. Return the \kbd{QX} $P(a \mod T, Y)$. Not memory clean, nor suitable for \kbd{gerepileupto}. \subsec{\kbd{QXQX}} \fun{GEN}{QXQX_mul}{GEN x, GEN y, GEN T} where $T$ is a monic \kbd{ZX}. \fun{GEN}{QXQX_QXQ_mul}{GEN x, GEN y, GEN T} where $T$ is a monic \kbd{ZX}. \fun{GEN}{QXQX_sqr}{GEN x, GEN T} where $T$ is a monic \kbd{ZX} \fun{GEN}{QXQX_powers}{GEN x, long n, GEN T} where $T$ is a monic \kbd{ZX} \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 nonzero 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}{QXQX_gcd}{GEN x, GEN y, GEN T} returns the gcd of $x$ and $y$, assuming that $x$ and $y$ are \kbd{QXQX}s and that $T$ is a monic \kbd{ZX}. \fun{GEN}{QXQX_homogenous_evalpow}{GEN P, GEN a, GEN B, GEN T} Evaluate the homogenous polynomial associated to the univariate polynomial $P$ on $(a,b)$ where $B$ is the vector of powers of $b$ with exponents $0$ to the degree of $P$ (\kbd{QXQ\_powers(b,degpol(P),T)}). \subsec{\kbd{QXQM}} \kbd{QXQM} are matrices of \kbd{QXQ}. All entries must be \typ{INT}, \typ{FRAC} or polynomials of degree strictly less than the degree of $T$, which must be a monic \kbd{ZX}. \fun{GEN}{QXQM_mul}{GEN x,GEN y,GEN T} returns $x*y$ mod $T$. \fun{GEN}{QXQM_sqr}{GEN x,GEN T} returns $x^2$ mod $T$. \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} return \kbd{T} multiplied by $\kbd{x}^n$, assuming $n\geq 0$. \fun{long}{zx_lval}{GEN f, long p} return the valuation of $f$ at $p$. \fun{GEN}{zx_z_divexact}{GEN x, long y} return \kbd{x/y} assuming all divisions are exact. \subsec{\kbd{RgX}} \subsubsec{Tests} \fun{long}{RgX_degree}{GEN x, long v} $x$ being a \typ{POL} and $v \geq 0$, returns the degree in $v$ of $x$. Error if $x$ is not a polynomial in $v$. \fun{int}{RgX_isscalar}{GEN x} return 1 if $x$ all the coefficients of $x$ of degree $> 0$ are $0$ (as per \kbd{gequal0}). \fun{int}{RgX_is_rational}{GEN P} return 1 if the \kbd{RgX}~$P$ has only rational coefficients (\typ{INT} and \typ{FRAC}), and 0 otherwise. \fun{int}{RgX_is_QX}{GEN P} return 1 if the \kbd{RgX}~$P$ has only \typ{INT} and \typ{FRAC} coefficients, and 0 otherwise. \fun{int}{RgX_is_ZX}{GEN P} return 1 if 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 nonzero monomial in its main variable, 0~otherwise. \fun{long}{RgX_equal}{GEN x, GEN y} returns $1$ if the \typ{POL}s $x$ and $y$ have the same \kbd{degpol} and their coefficients are equal (as per \tet{gequal}). Variable numbers are not checked. Note that this is more stringent than \kbd{gequal(x,y)}, which only checks whether $x - y$ satisfies \kbd{gequal0}; in particular, they may have different apparent degrees provided the extra leading terms are $0$. \fun{long}{RgX_equal_var}{GEN x, GEN y} returns $1$ if $x$ and $y$ have the same variable number and \kbd{RgX\_equal(x,y)} is $1$. \subsubsec{Coefficients, blocks} \fun{GEN}{RgX_coeff}{GEN P, long n} return the coefficient of $x^n$ in $P$, defined as \kbd{gen\_0} if $n < 0$ or $n > \kbd{degpol}(P)$. Shallow function. \fun{int}{RgX_blocks}{GEN P, long n, long m} writes $P(X)=a_0(X)+X^n*a_1(X)*X^n+\ldots+X^{n*(m-1)}\*a_{m-1}(X)$, where the $a_i$ are polynomial of degree at most $n-1$ (except possibly for the last one) and returns $[a_0(X),a_1(X),\ldots,a_{m-1}(X)]$. Shallow function. \fun{void}{RgX_even_odd}{GEN p, GEN *pe, GEN *po} write $p(X) = E(X^2) + X O(X^2)$ and set \kbd{*pe = E}, \kbd{*po = O}. Shallow function. \fun{GEN}{RgX_splitting}{GEN P, long k} write $P(X)=a_0(X^k)+X\*a_1(X^k)+\ldots+X^{k-1}\*a_{k-1}(X^k)$ and return $[a_0(X),a_1(X),\ldots,a_{k-1}(X)]$. Shallow function. \fun{GEN}{RgX_copy}{GEN x} returns (a deep copy of) $\kbd{x}$. \fun{GEN}{RgX_renormalize}{GEN x} remove leading terms in \kbd{x} which are equal to (necessarily inexact) zeros. \fun{GEN}{RgX_renormalize_lg}{GEN x, long lx} as \kbd{setlg(x, lx)} followed by \kbd{RgX\_renormalize(x)}. Assumes that $\kbd{lx} \leq \kbd{lg(x)}$. \fun{GEN}{RgX_recip}{GEN P} returns the reverse of the polynomial $P$, i.e. $X^{\deg P} P(1/X)$. \fun{GEN}{RgX_recip_shallow}{GEN P} shallow function of \tet{RgX_recip}. \fun{GEN}{RgX_recip_i}{GEN P} shallow function of \tet{RgX_recip}, where we further assume that $P(0)\neq 0$, so that the degree of the output is the degree of $P$. \fun{long}{rfracrecip}{GEN *a, GEN *b} let \kbd{*a} and \kbd{*b} be such that their quotient $F$ is a \typ{RFRAC} in variable $X$. Write $F(1/X) = X^v A/B$ where $A$ and $B$ are coprime to $X$ and $v$ in $\Z$. Set \kbd{*a} to A, \kbd{*b} to $B$ and return $v$. \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_order}{GEN P} given a nonconstant polynomial $P$, returns the largest exponent $d$ such that $P$ is of the form $P(x^d)$ (use \kbd{gequal0} to check whether coefficients are 0). \fun{long}{RgX_deflate_max}{GEN P, long *d} given a nonconstant polynomial $P$, sets \kbd{d} to \kbd{RgX\_deflate\_order(P)} and returns \kbd{RgX\_deflate(P,d)}. Shallow function. \fun{long}{rfrac_deflate_order}{GEN F} as \kbd{RgX\_deflate\_order} where $F$ is a nonconstant \typ{RFRAC}. \fun{long}{rfrac_deflate_max}{GEN F, long *d} as \kbd{RgX\_deflate\_max} where $F$ is a nonconstant \typ{RFRAC}. \fun{GEN}{rfrac_deflate}{GEN F, long m} as \kbd{RgX\_deflate} where $F$ is a \typ{RFRAC}. \fun{GEN}{RgX_inflate}{GEN P, long d} return $P(X^d)$. Shallow function, not suitable for \kbd{gerepileupto}. \fun{GEN}{RgX_rescale_to_int}{GEN x} given a polynomial $x$ with real entries (\typ{INT}, \typ{FRAC} or \typ{REAL}), return a \kbd{ZX} wich is very close to $D x$ for some well-chosen integer $D$. More precisely, if the input is exact, $D$ is the denominator of $x$; else it is a power of $2$ chosen so that all inexact entries are correctly rounded to 1 ulp. \fun{GEN}{RgX_homogenize}{GEN P, long v} Return the homogenous polynomial associated to $P$ in the secondary variable $v$, that is $y^d*P(x/y)$ where $d$ is the degree of $P$, $x$ is the variable of $P$, and $y$ is the variable with number $v$. \fun{GEN}{RgX_homogenous_evalpow}{GEN P, GEN a, GEN B} Evaluate the homogenous polynomial associated to the univariate polynomial $P$ on $(a,b)$ where $B$ is the vector of powers of $b$ with exponents $0$ to the degree of $P$ (\kbd{gpowers(b,degpol(P))}). \fun{GEN}{RgXX_to_Kronecker}{GEN P, long n} Assuming $P(X,Y)$ is a polynomial of degree in $X$ strictly less than $n$, returns $P(X,X^{2*n-1})$, the Kronecker form of $P$. Shallow function. \fun{GEN}{RgXX_to_Kronecker_spec}{GEN Q, long lQ, long n} return \tet{RgXX_to_Kronecker}$(P, n)$, where $P$ is the polynomial $\sum_{i = 0}^{\kbd{lQ} - 1} Q[i] x^i$. To be used when splitting the coefficients of genuine polynomials into blocks. Shallow function. \subsubsec{Shifts, valuations} \fun{GEN}{RgX_shift}{GEN x, long n} returns $\kbd{x} * t^n$ if $n\geq 0$, and $\kbd{x} \bs t^{-n}$ otherwise. \fun{GEN}{RgX_shift_shallow}{GEN x, long n} as \kbd{RgX\_shift}, but shallow (coefficients are not copied). \fun{GEN}{RgX_rotate_shallow}{GEN P, long k, long p} returns $\kbd{P} * X^k \pmod {X^p-1}$, assuming the degree of $P$ is strictly less than $p$, and $k\geq 0$. \fun{void}{RgX_shift_inplace_init}{long v} $v \geq 0$, prepare for a later call to \tet{RgX_shift_inplace}. Reserves $v$ words on the stack. \fun{GEN}{RgX_shift_inplace}{GEN x, long v} $v \geq 0$, assume that \tet{RgX_shift_inplace_init}$(v)$ has been called (reserving $v$ words on the stack), immediately followed by a \typ{POL} $x$. Return \kbd{RgX\_shift}$(x,v)$ by shifting $x$ in place. To be used as follows \bprog RgX_shift_inplace_init(v); av = avma; ... x = gerepileupto(av, ...); /* a t_POL */ return RgX_shift_inplace(x, v); @eprog \fun{long}{RgX_valrem}{GEN P, GEN *pz} returns the valuation $v$ of the \typ{POL}~\kbd{P} with respect to its main variable $X$. Check whether coefficients are $0$ using \kbd{isexactzero}. 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{isexactzero}. \fun{long}{RgX_valrem_inexact}{GEN P, GEN *z} as \kbd{RgX\_valrem}, using \kbd{gequal0} instead of \kbd{isexactzero}. \fun{long}{RgXV_maxdegree}{GEN V} returns the maximum of the degrees of the components of the vector of \typ{POL}s $V$. \subsubsec{Basic arithmetic} \fun{GEN}{RgX_add}{GEN x,GEN y} adds \kbd{x} and \kbd{y}. \fun{GEN}{RgX_sub}{GEN x,GEN y} subtracts \kbd{x} and \kbd{y}. \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_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_mul2n}{GEN y, long n} multiplies the \kbd{RgX} \kbd{y} by $2^n$. \fun{GEN}{RgX_Rg_div}{GEN y, GEN x} divides the \kbd{RgX} \kbd{y} by the scalar \kbd{x}. \fun{GEN}{RgX_divs}{GEN y, long s} divides the \kbd{RgX} \kbd{y} by the \kbd{long}~\kbd{s}. \fun{GEN}{RgX_Rg_divexact}{GEN x, GEN y} exact division of the \kbd{RgX} \kbd{y} by the scalar \kbd{x}. \fun{GEN}{RgX_Rg_eval_bk}{GEN f, GEN x} returns $\kbd{f}(\kbd{x})$ using Brent and Kung algorithm. (Use \tet{poleval} for Horner algorithm.) \fun{GEN}{RgX_RgV_eval}{GEN f, GEN V} as \kbd{RgX\_Rg\_eval\_bk(f, x)}, assuming $V$ was output by \kbd{gpowers(x, n)} for some $n\geq 1$. \fun{GEN}{RgXV_RgV_eval}{GEN f, GEN V} apply \kbd{RgX\_RgV\_eval\_bk(, V)} to all the components of the vector $f$. \fun{GEN}{RgX_normalize}{GEN x} divides $x$ by its leading coefficient. If the latter is~$1$, $x$ itself is returned, not a copy. Leading coefficients equal to $0$ are stripped, e.g. \bprog 0.*t^3 + Mod(0,3)*t^2 + 2*t @eprog\noindent is normalized to $t$. \fun{GEN}{RgX_mul}{GEN x, GEN y} multiplies the two \typ{POL} (in the same variable) \kbd{x} and \kbd{y}. Detect the coefficient ring and use an appropriate algorithm. \fun{GEN}{RgX_mul_i}{GEN x, GEN y} multiplies the two \typ{POL} (in the same variable) \kbd{x} and \kbd{y}. Do not detect the coefficient ring. Use a generic Karatsuba algorithm. \fun{GEN}{RgX_mul_normalized}{GEN A, long a, GEN B, long b} returns $(X^a + A)(X^b + B) - X^(a+b)$, where we assume that $\deg A < a$ and $\deg B < b$ are polynomials in the same variable $X$. \fun{GEN}{RgX_sqr}{GEN x} squares the \typ{POL} \kbd{x}. Detect the coefficient ring and use an appropriate algorithm. \fun{GEN}{RgX_sqr_i}{GEN x} squares the \typ{POL} \kbd{x}. Do not detect the coefficient ring. Use a generic Karatsuba algorithm. \fun{GEN}{RgXV_prod}{GEN V}, \kbd{V} being a vector of \kbd{RgX}, returns their product. \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. In the generic case, the remainder is created after the quotient and can be disposed of individually with a \kbd{cgiv(r)}. \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{int}{ZXQX_dvd}{GEN x, GEN y, GEN T} let $T$ be a monic irreducible \kbd{ZX}, let $x, y$ be \typ{POL} whose coefficients are either \typ{INT}s or \kbd{ZX} in the same variable as $T$. Assume further that the leading coefficient of $y$ is an integer. Return $1$ if $y | x$ in $(\Z[Y]/(T))[X]$, and $0$ otherwise. \fun{GEN}{RgXQX_pseudodivrem}{GEN x, GEN y, GEN T, GEN *ptr} compute a pseudo-quotient $q$ and pseudo-remainder $r$ such that $\kbd{lc}(y)^{\deg(x) - \deg(y) + 1}x = qy + r$ in $R[X]/(T)$. Return $q$ and set \kbd{*ptr} to $r$. \fun{GEN}{RgX_mulXn}{GEN a, long n} returns $a * X^n$. This may be a \typ{FRAC} if $n < 0$ and the valuation of $a$ is not large enough. \fun{GEN}{RgX_addmulXn}{GEN a, GEN b, long n} returns $a + b * X^n$, assuming that $n > 0$. \fun{GEN}{RgX_addmulXn_shallow}{GEN a, GEN b, long n} shallow variant of \tet{RgX_addmulXn}. \fun{GEN}{RgX_digits}{GEN x, GEN B} returns a vector of \kbd{RgX} $[c_0,\ldots,c_n]$ of degree less than the degree of $B$ and such that $x=\sum_{i=0}^{n}{c_i\*B^i}$. \subsubsec{Internal routines working on coefficient arrays} These routines operate on coefficient blocks which are invalid \kbd{GEN}s A \kbd{GEN} argument $a$ or $b$ in routines below is actually a coefficient arrays representing the polynomials $\sum_{i = 0}^{\kbd{na-1}} a[i] X^i$ and $\sum_{i = 0}^{\kbd{nb-1}} b[i] X^i$. Note that $a[0]$ and $b[0]$ contain coefficients and not the mandatory \kbd{GEN} codeword. This allows to implement divide-and-conquer methods directly, without needing to allocate wrappers around coefficient blocks. \fun{GEN}{RgX_mulspec}{GEN a, GEN b, long na, long nb}. Internal routine: given two coefficient arrays representing polynomials, return their product (as a true \kbd{GEN}) in variable $0$. \fun{GEN}{RgX_sqrspec}{GEN a, long na}. Internal routine: given a coefficient array representing a polynomial r eturn its square (as a true \kbd{GEN}) in variable $0$. \fun{GEN}{RgX_addspec}{GEN x, GEN y, long nx, long ny} given two coefficient arrays representing polynomials, return their sum (as a true \kbd{GEN}) in variable $0$. \fun{GEN}{RgX_addspec_shallow}{GEN x, GEN y, long nx, long ny} shallow variant of \tet{RgX_addspec}. \subsubsec{GCD, Resultant} \fun{GEN}{RgX_gcd}{GEN x, GEN y} returns the GCD of \kbd{x} and \kbd{y}, assumed to be \typ{POL}s in the same variable. \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_halfgcd}{GEN x, GEN y} assuming \kbd{x} and \kbd{y} are \typ{POL}s in the same variable, returns a $2\times 2$ \typ{MAT} $M$ with \typ{POL} entries, such that $M*[x,y]~==[a,b]~$ such that $\deg a \geq \ceil{\max(\deg x,\deg y))/2} > \deg b$. \fun{GEN}{RgX_halfgcd_all}{GEN x, GEN y, GEN *pt_a, GEN *pt_b} as \kbd{RgX\_halfgcd}, in addition, if \kbd{pt\_a} (resp. \kbd{pt\_b}) is not \kbd{NULL}, \kbd{*pt\_a} (resp. \kbd{*pt\_b}) is set to \kbd{a} (resp. \kbd{b}). \fun{GEN}{RgX_chinese_coprime}{GEN x, GEN y, GEN Tx, GEN Ty, GEN Tz} returns an \kbd{RgX}, 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}{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 nonconstant remainder in the polynomial remainder sequence if it exists and to \kbd{gen\_0} otherwise (e.g. one polynomial has degree 0). \subsubsec{Other operations} \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_deriv}{GEN x} returns the derivative of \kbd{x} with respect to its main variable. \fun{GEN}{RgX_integ}{GEN x} returns the primitive of \kbd{x} vanishing at $0$, with respect to its main variable. \fun{GEN}{RgX_rescale}{GEN P, GEN h} returns $h^{\deg(P)} P(x/h)$. \kbd{P} is an \kbd{RgX} and \kbd{h} is nonzero. (Leaves small objects on the stack. Suitable but inefficient for \kbd{gerepileupto}.) \fun{GEN}{RgXV_rescale}{GEN v, GEN h} apply \kbd{RgX\_unscale} to a vector of \kbd{RgX}. \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{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}{RgX_affine}{GEN P, GEN a, GEN b} Return $P(aX + b)$ (optimized for $b = \pm 1$). Not memory clean. \subsubsec{Function related to modular forms} \fun{GEN}{RgX_act_Gl2Q}{GEN g, long k} let $R$ be a commutative ring and $g = [a,b;c,d]$ be in $\text{GL}_2(\Q)$, $g$ acts (on the left) on homogeneous polynomials of degree $k-2$ in $V := R[X,Y]_{k-2}$ via $$ g\cdot P := P(dX-cY, -bX+aY) = (\det g)^{k-2} P((X,Y)\cdot g^{-1}).$$ This function returns the matrix in $M_{k-1}(R)$ of $P\mapsto g\cdot P$ in the basis $(X^{k-2},\dots,Y^{k-2})$ of $V$. \fun{GEN}{RgX_act_ZGl2Q}{GEN z, long k} let $G:=\text{GL}_2(\Q)$, acting on $R[X,Y]_{k-2}$ and $z\in \Z[G]$. Return the matrix giving $P\mapsto z\cdot P$ in the basis $(X^{k-2},\dots,Y^{k-2})$. \subsec{\kbd{RgXn}} \fun{GEN}{RgXn_red_shallow}{GEN x, long n} return $\kbd{x \% } t^n$, where $n\geq 0$. Shallow function. \fun{GEN}{RgXn_recip_shallow}{GEN P} returns $X^n\*P(1/X)$. Shallow function. \fun{GEN}{RgXn_mul}{GEN a, GEN b, long n} returns $a b$ modulo $X^n$, where $a,b$ are two \typ{POL} in the same variable $X$ and $n \geq 0$. Uses Karatsuba algorithm (Mulders, Hanrot-Zimmermann variant). \fun{GEN}{RgXn_sqr}{GEN a, long n} returns $a^2$ modulo $X^n$, where $a$ is a \typ{POL} in the variable $X$ and $n \geq 0$. Uses Karatsuba algorithm (Mulders, Hanrot-Zimmermann variant). \fun{GEN}{RgX_mulhigh_i}{GEN f, GEN g, long n} return the Euclidean quotient of $f(x)*g(x)$ by $x^n$ (high product). Uses \tet{RgXn_mul} applied to the reciprocal polynomials of $f$ and $g$. Not suitable for \kbd{gerepile}. \fun{GEN}{RgX_sqrhigh_i}{GEN f, long n} return the Euclidean quotient of $f(x)^2$ by $x^n$ (high product). Uses \tet{RgXn_sqr} applied to the reciprocal polynomial of $f$. Not suitable for \kbd{gerepile}. \fun{GEN}{RgXn_inv}{GEN a, long n} returns $a^{-1}$ modulo $X^n$, where $a$ is a \typ{POL} in the variable $X$ and $n \geq 0$. Uses Newton-Raphson algorithm. \fun{GEN}{RgXn_inv_i}{GEN a, long n} as \tet{RgXn_inv} without final garbage collection (suitable for \kbd{gerepileupto}). \fun{GEN}{RgXn_div}{GEN a, GEN b, long n} returns $a/b$ modulo $X^n$, where $a$ and $b$ are \typ{POL}s in the variable $X$ and $n \geq 0$. Uses Newton-Raphson/Karp-Markstein algorithm. \fun{GEN}{RgXn_div_i}{GEN a, GEN b, long n} as \tet{RgXn_div} without final garbage collection (suitable for \kbd{gerepileupto}). \fun{GEN}{RgXn_powers}{GEN x, long m, long n} returns $[\kbd{x}^0, \dots, \kbd{x}^\kbd{m}]$ modulo $X^n$ as a \typ{VEC} of \kbd{RgXn}s. \fun{GEN}{RgXn_powu}{GEN x, ulong m, long n} returns $x^m$ modulo $X^n$. \fun{GEN}{RgXn_powu_i}{GEN x, ulong m, long n} as \tet{RgXn_powu}, not memory clean. \fun{GEN}{RgXn_sqrt}{GEN a, long n} returns $a^{1/2}$ modulo $X^n$, where $a$ is a \typ{POL} in the variable $X$ and $n \geq 0$. Assume that $a = 1 \mod{X}$. Uses Newton algorithm. \fun{GEN}{RgXn_exp}{GEN a, long n} returns $exp(a)$ modulo $X^n$, assuming $a = 0 \mod{X}$. \fun{GEN}{RgXn_expint}{GEN f, long n} return $\exp(F)$ where $F$ is the primitive of $f$ that vanishes at $0$. \fun{GEN}{RgXn_eval}{GEN Q, GEN x, long n} special case of \tet{RgX_RgXQ_eval}, when the modulus is a monomial: returns $\kbd{Q}(\kbd{x})$ modulo $t^n$, where $x \in R[t]$. \fun{GEN}{RgX_RgXn_eval}{GEN f, GEN x, long n} returns $\kbd{f}(\kbd{x})$ modulo $X^n$. \fun{GEN}{RgX_RgXnV_eval}{GEN f, GEN V, long n} as \kbd{RgX\_RgXn\_eval(f, x, n)}, assuming $V$ was output by \kbd{RgXn\_powers(x, m, n)} for some $m\geq 1$. \fun{GEN}{RgXn_reverse}{GEN f, long n} assuming that $f = a\*x \mod{x^2}$ with $a$ invertible, returns a \typ{POL} $g$ of degree $< n$ such that $(g \circ f)(x) = x$ modulo $x^n$. \subsec{\kbd{RgXnV}} \fun{GEN}{RgXnV_red_shallow}{GEN x, long n} apply \kbd{RgXn\_red\_shallow} to all the components of the vector $x$. \subsec{\kbd{RgXQ}} \fun{GEN}{RgXQ_mul}{GEN y, GEN x, GEN T} computes $xy$ mod $T$ \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{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_trace}{GEN x, GEN T} returns the trace 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}{RgXQ_minpoly}{GEN x, GEN T, long v} returns the minimal polynomial of \kbd{Mod(x, T)}, in variable $v$. \fun{GEN}{RgX_RgXQ_eval}{GEN f, GEN x, GEN T} returns $\kbd{f}(\kbd{x})$ modulo $T$. \fun{GEN}{RgX_RgXQV_eval}{GEN f, GEN V, GEN T} as \kbd{RgX\_RgXQ\_eval(f, x, T)}, assuming $V$ was output by \kbd{RgXQ\_powers(x, n, T)} for some $n\geq 1$. \fun{int}{RgXQ_ratlift}{GEN x, GEN T, long amax, long bmax, GEN *P, GEN *Q} Assuming that $\kbd{amax}+\kbd{bmax}<\deg T$, attempts to recognize $x$ as a rational function $a/b$, i.e. to find \typ{POL}s $P$ and $Q$ such that \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}. \subsec{\kbd{RgXQV, RgXQC}} \fun{GEN}{RgXQC_red}{GEN z, GEN T} \kbd{z} a vector whose coefficients are \kbd{RgX}s (arbitrary \kbd{GEN}s in fact), reduce them to \kbd{RgXQ}s (applying \kbd{grem} coefficientwise) in a \typ{COL}. \fun{GEN}{RgXQV_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{VEC}. \fun{GEN}{RgXQV_RgXQ_mul}{GEN z, GEN x, GEN T} \kbd{z} multiplies the \kbd{RgXQV} \kbd{z} by the scalar (\kbd{RgXQ}) \kbd{x}. \fun{GEN}{RgXQV_factorback}{GEN L, GEN e, GEN T} returns $\prod_i L_i^{e_i}$ mod $T$ where $L$ is a vector of \kbd{RgXQ}s and $e$ a vector of \typ{INT}s. \subsec{\kbd{RgXQM}} \fun{GEN}{RgXQM_red}{GEN z, GEN T} \kbd{z} a matrix whose coefficients are \kbd{RgX}s (arbitrary \kbd{GEN}s in fact), reduce them to \kbd{RgXQ}s (applying \kbd{grem} coefficientwise). \fun{GEN}{RgXQM_mul}{GEN x, GEN y, GEN T} \subsec{\kbd{RgXQX}} \fun{GEN}{RgXQX_red}{GEN z, GEN T} \kbd{z} a \typ{POL} whose coefficients are \kbd{RgX}s (arbitrary \kbd{GEN}s in fact), reduce them to \kbd{RgXQ}s (applying \kbd{grem} coefficientwise). \fun{GEN}{RgXQX_mul}{GEN x, GEN y, GEN T} \fun{GEN}{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_powers}{GEN x, long n, GEN T} \fun{GEN}{RgXQX_divrem}{GEN x, GEN y, GEN T, GEN *pr} \fun{GEN}{RgXQX_div}{GEN x, GEN y, GEN T} \fun{GEN}{RgXQX_rem}{GEN x, GEN y, GEN T} \fun{GEN}{RgXQX_translate}{GEN P, GEN c, GEN T} assume the main variable $X$ of $P$ has higher priority than the main variable $Y$ of $T$ and $c$. Return a lift of $P(X+\text{Mod}(c(Y), T(Y)))$. \fun{GEN}{Kronecker_to_mod}{GEN z, GEN T} $z\in R[X]$ represents an element $P(X,Y)$ in $R[X,Y]$ mod $T(Y)$ in Kronecker form, i.e. $z = P(X,X^{2*n-1})$ Let $R$ be some commutative ring, $n = \deg T$ and let $P(X,Y)\in R[X,Y]$ lift a polynomial in $K[Y]$, where $K := R[X]/(T)$ and $\deg_X P < 2n-1$ --- such as would result from multiplying minimal degree lifts of two polynomials in $K[Y]$. Let $z = P(t,t^{2*n-1})$ be a Kronecker form of $P$, this function returns the image of $P(X,t)$ in $K[t]$, with \typ{POLMOD} coefficients. Not stack-clean. Note that $t$ need not be the same variable as $Y$! \chapter{Black box algebraic structures} The generic routines like \kbd{gmul} or \kbd{gadd} allow handling objects belonging to a fixed list of basic types, with some natural polymorphism (you can mix rational numbers and polynomials, etc.), at the expense of efficiency and sometimes of clarity when the recursive structure becomes complicated, e.g. a few levels of \typ{POLMOD}s attached to different polynomials and variable numbers for quotient structures. This is the only possibility in GP. On the other hand, the Level 2 Kernel allows dedicated routines to handle efficiently objects of a very specific type, e.g. polynomials with coefficients in the same finite field. This is more efficient, but imvolves a lot of code duplication since polymorphism is no longer possible. A third and final option, still restricted to library programming, is to define an arbitrary algebraic structure (currently groups, fields, rings, algebras and $\Z_p$-modules) by providing suitable methods, then using generic algorithms. For instance naive Gaussian pivoting applies over all base fields and need only be implemented once. The difference with the first solution is that we no longer depend on the way functions like \kbd{gmul} or \kbd{gadd} will guess what the user is trying to do. We can then implement independently various groups / fields / algebras in a clean way. \section{Black box groups} A black box group is defined by a \tet{bb_group} struct, describing methods available to handle group elements: \bprog struct bb_group { GEN (*mul)(void*, GEN, GEN); GEN (*pow)(void*, GEN, GEN); GEN (*rand)(void*); ulong (*hash)(GEN); int (*equal)(GEN, GEN); int (*equal1)(GEN); GEN (*easylog)(void *E, GEN, GEN, GEN); }; @eprog \kbd{mul(E,x,y)} returns the product $x\*y$. \kbd{pow(E,x,n)} returns $x^n$ ($n$ integer, possibly negative or zero). \kbd{rand(E)} returns a random element in the group. \kbd{hash(x)} returns a hash value for $x$ (\kbd{hash\_GEN} is suitable for this field). \kbd{equal(x,y)} returns one if $x=y$ and zero otherwise. \kbd{equal1(x)} returns one if $x$ is the neutral element in the group, and zero otherwise. \kbd{easylog(E,a,g,o)} (optional) returns either NULL or the discrete logarithm $n$ such that $g^n=a$, the element $g$ being of order $o$. This provides a short-cut in situation where a better algorithm than the generic one is known. A group is thus described by a \kbd{struct bb\_group} as above and auxiliary data typecast to \kbd{void*}. The following functions operate on black box groups: \fun{GEN}{gen_Shanks_log}{GEN x, GEN g, GEN N, void *E, const struct bb_group *grp} \hbadness 10000\break Generic baby-step/giant-step algorithm (Shanks's method). Assuming that $g$ has order $N$, compute an integer $k$ such that $g^k = x$. Return \kbd{cgetg(1, t\_VEC)} if there are no solutions. This requires $O(\sqrt{N})$ group operations and uses an auxiliary table containing $O(\sqrt{N})$ group elements. The above is useful for a one-shot computation. If many discrete logs are desired: \fun{GEN}{gen_Shanks_init}{GEN g, long n, void *E, const struct bb_group *grp} return an auxiliary data structure $T$ required to compute a discrete log in base $g$. Compute and store all powers $g^i$, $i < n$. \fun{GEN}{gen_Shanks}{GEN T, GEN x, ulong N, void *E, const struct bb_group *grp} Let $T$ be computed by \tet{gen_Shanks_init}$(g,n,\dots)$. Return $k < n N$ such that $g^k = x$ or \kbd{NULL} if no such index exist. It uses $O(N)$ operation in the group and fast table lookups (in time $O(\log n)$). The interface is such that the function may be used when the order of the base $g$ is unknown, and hence compute it given only an upper bound $B$ for it: e.g. choose $n,N$ such that $nN \geq B$ and compute the discrete log $l$ of $g^{-1}$ in base $g$, then use \tet{gen_order} with multiple $N = l+1$. \fun{GEN}{gen_Pollard_log}{GEN x, GEN g, GEN N, void *E, const struct bb_group *grp} \hbadness 10000\break Generic Pollard rho algorithm. Assuming that $g$ has order $N$, compute an integer $k$ such that $g^k = x$. This requires $O(\sqrt{N})$ group operations in average and $O(1)$ storage. Will enter an infinite loop if there are no solutions. \fun{GEN}{gen_plog}{GEN x, GEN g, GEN N, void *E, const struct bb_group} Assuming that $g$ has prime order $N$, compute an integer $k$ such that $g^k = x$, using either \kbd{gen\_Shanks\_log} or \kbd{gen\_Pollard\_log}. Return \kbd{cgetg(1, t\_VEC)} if there are no solutions. \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} returns an integer $k$ such that $g^k = x$, assuming that the order of $g$ divides $N$, using Pohlig-Hellman algorithm. Return \kbd{cgetg(1, t\_VEC)} if there are no solutions. This calls \tet{gen_plog} repeatedly for all prime divisors $p$ of $N$. In the following functions the integer parameter \kbd{ord} can be given in all the formats recognized for the argument of arithmetic functions, i.e.~either as a positive \typ{INT} $N$, or as its factorization matrix $\var{faN}$, or (preferred) as a pair $[N,\var{faN}]$. \fun{GEN}{gen_order}{GEN x, GEN ord, void *E, const struct bb_group *grp} computes the order of $x$; \kbd{ord} is a multiple of the order, for instance the group order. \fun{GEN}{gen_factored_order}{GEN x, GEN ord, void *E, const struct bb_group *grp} returns a pair $[o,F]$, where $o$ is the order of $x$ and $F$ is the factorization of $o$; \kbd{ord} is as in \tet{gen_order}. \fun{GEN}{gen_gener}{GEN ord, void *E, const struct bb_group *grp} returns a random generator of the group, assuming it is of order exactly \kbd{ord}. \fun{GEN}{get_arith_Z}{GEN ord} given \kbd{ord} as above in one of the formats recognized for arithmetic functions, i.e. a positive \typ{INT} $N$, its factorization \var{faN}, or the pair $[N, \var{faN}]$, return $N$. \fun{GEN}{get_arith_ZZM}{GEN ord} given \kbd{ord} as above, return the pair $[N, \var{faN}]$. This may require factoring $N$. \fun{GEN}{gen_select_order}{GEN v, void *E, const struct bb_group *grp} Let $v$ be a vector of possible orders for the group; try to find the true order by checking orders of random points. This will not terminate if there is an ambiguity. \subsec{Black box groups with pairing} These functions handle groups of rank at most $2$ equipped with a family of bilinear pairings which behave like the Weil pairing on elliptic curves over finite field. In the descriptions below, the function \kbd{pairorder(E, P, Q, m, F)} must return the order of the $m$-pairing of $P$ and $Q$, both of order dividing $m$, where $F$ is the factorization matrix of a multiple of $m$. \fun{GEN}{gen_ellgroup}{GEN o, GEN d, GEN *pt_m, void *E, const struct bb_group *grp, GEN pairorder(void *E, GEN P, GEN Q, GEN m, GEN F)} returns the elementary divisors $[d_1, d_2]$ of the group, assuming it is of order exactly $o>1$, and that $d_2$ divides $d$. If $d_2=1$ then $[o]$ is returned, otherwise \kbd{m=*pt\_m} is set to the order of the pairing required to verify a generating set which is to be used with \kbd{gen\_ellgens}. For the parameter $o$, all formats recognized by arithmetic functions are allowed, preferably a factorization matrix or a pair $[n,\kbd{factor}(n)]$. \fun{GEN}{gen_ellgens}{GEN d1, GEN d2, GEN m, void *E, const struct bb_group *grp, GEN pairorder(void *E, GEN P, GEN Q, GEN m, GEN F)} the parameters $d_1$, $d_2$, $m$ being as returned by \kbd{gen\_ellgroup}, returns a pair of generators $[P,Q]$ such that $P$ is of order $d_1$ and the $m$-pairing of $P$ and $Q$ is of order $m$. (Note: $Q$ needs not be of order $d_2$). For the parameter $d_1$, all formats recognized by arithmetic functions are allowed, preferably a factorization matrix or a pair $[n,\kbd{factor}(n)]$. \subsec{Functions returning black box groups} \fun{const struct bb_group *}{get_Flxq_star}{void **E, GEN T, ulong p} \fun{const struct bb_group *}{get_FpXQ_star}{void **E, GEN T, GEN p} returns a pointer to the black box group $(\F_p[x]/(T))^*$. \fun{const struct bb_group *}{get_FpE_group}{void **pE, GEN a4, GEN a6, GEN p} returns a pointer to a black box group and set \kbd{*pE} to the necessary data for computing in the group $E(\F_p)$ where $E$ is the elliptic curve $E:y^2=x^3+a_4\*x+a_6$, with $a_4$ and $a_6$ in $\F_p$. \fun{const struct bb_group *}{get_FpXQE_group}{void **pE, GEN a4, GEN a6, GEN T, GEN p} returns a pointer to a black box group and set \kbd{*pE} to the necessary data for computing in the group $E(\F_p[X]/(T))$ where $E$ is the elliptic curve $E:y^2=x^3+a_4\*x+a_6$, with $a_4$ and $a_6$ in $\F_p[X]/(T)$. \fun{const struct bb_group *}{get_FlxqE_group}{void **pE, GEN a4, GEN a6, GEN T, ulong p} idem for small $p$. \fun{const struct bb_group *}{get_F2xqE_group}{void **pE, GEN a2, GEN a6, GEN T} idem for $p=2$. \section{Black box fields} A black box field is defined by a \tet{bb_field} struct, describing methods available to handle field elements: \bprog struct bb_field { GEN (*red)(void *E ,GEN); GEN (*add)(void *E ,GEN, GEN); GEN (*mul)(void *E ,GEN, GEN); GEN (*neg)(void *E ,GEN); GEN (*inv)(void *E ,GEN); int (*equal0)(GEN); GEN (*s)(void *E, long); }; @eprog\noindent In contrast of black box group, elements can have non canonical forms, and only \kbd{red} is required to return a canonical form. For instance a black box implementation of finite fields, all methods except \kbd{red} may return arbitrary representatives in $\Z[X]$ of the correct congruence class modulo $(p,T(X))$. \kbd{red(E,x)} returns the canonical form of $x$. \kbd{add(E,x,y)} returns the sum $x+y$. \kbd{mul(E,x,y)} returns the product $x\*y$. \kbd{neg(E,x)} returns $-x$. \kbd{inv(E,x)} returns the inverse of $x$. \kbd{equal0(x)} $x$ being in canonical form, returns one if $x=0$ and zero otherwise. \kbd{s(n)} $n$ being a small signed integer, returns $n$ times the unit element. \noindent A field is thus described by a \kbd{struct bb\_field} as above and auxiliary data typecast to \kbd{void*}. The following functions operate on black box fields: \fun{GEN}{gen_Gauss}{GEN a, GEN b, void *E, const struct bb_field *ff} \fun{GEN}{gen_Gauss_pivot}{GEN x, long *rr, void *E, const struct bb_field *ff} \fun{GEN}{gen_det}{GEN a, void *E, const struct bb_field *ff} \fun{GEN}{gen_ker}{GEN x, long deplin, void *E, const struct bb_field *ff} \fun{GEN}{gen_matcolinvimage}{GEN a, GEN b, void *E, const struct bb_field *ff} \fun{GEN}{gen_matcolmul}{GEN a, GEN b, void *E, const struct bb_field *ff} \fun{GEN}{gen_matid}{long n, void *E, const struct bb_field *ff} \fun{GEN}{gen_matinvimage}{GEN a, GEN b, void *E, const struct bb_field *ff} \fun{GEN}{gen_matmul}{GEN a, GEN b, void *E, const struct bb_field *ff} \subsec{Functions returning black box fields} \fun{const struct bb_field *}{get_Fp_field}{void **pE, GEN p} \fun{const struct bb_field *}{get_Fq_field}{void **pE, GEN T, GEN p} \fun{const struct bb_field *}{get_Flxq_field}{void **pE, GEN T, ulong p} \fun{const struct bb_field *}{get_F2xq_field}{void **pE, GEN T} \fun{const struct bb_field *}{get_nf_field}{void **pE, GEN nf} \section{Black box algebra} A black box algebra is defined by a \tet{bb_algebra} struct, describing methods available to handle algebra elements: \bprog struct bb_algebra { GEN (*red)(void *E, GEN x); GEN (*add)(void *E, GEN x, GEN y); GEN (*sub)(void *E, GEN x, GEN y); GEN (*mul)(void *E, GEN x, GEN y); GEN (*sqr)(void *E, GEN x); GEN (*one)(void *E); GEN (*zero)(void *E); }; @eprog\noindent In contrast with black box groups, elements can have non canonical forms, but only \kbd{add} is allowed to return a non canonical form. \kbd{red(E,x)} returns the canonical form of $x$. \kbd{add(E,x,y)} returns the sum $x+y$. \kbd{sub(E,x,y)} returns the difference $x-y$. \kbd{mul(E,x,y)} returns the product $x\*y$. \kbd{sqr(E,x)} returns the square $x^2$. \kbd{one(E)} returns the unit element. \kbd{zero(E)} returns the zero element. \noindent An algebra is thus described by a \kbd{struct bb\_algebra} as above and auxiliary data typecast to \kbd{void*}. The following functions operate on black box algebra: \fun{GEN}{gen_bkeval}{GEN P, long d, GEN x, int use_sqr, void *E, const struct bb_algebra *ff, GEN cmul(void *E, GEN P, long a, GEN x)} $x$ being an element of the black box algebra, and $P$ some black box polynomial of degree $d$ over the base field, returns $P(x)$. The function \kbd{cmul(E,P,a,y)} must return the coefficient of degree $a$ of $P$ multiplied by $y$. \kbd{cmul} is allowed to return a non canonical form; it is also allowed to return \kbd{NULL} instead of an exact $0$. The flag \kbd{use\_sqr} has the same meaning as for \kbd{gen\_powers}. This implements an algorithm of Brent and Kung (1978). \fun{GEN}{gen_bkeval_powers}{GEN P, long d, GEN V, void *E, const struct bb_algebra *ff, GEN cmul(void *E, GEN P, long a, GEN x)} as \tet{gen_RgX_bkeval} assuming $V$ was output by \tet{gen_powers}$(x, l, E, \var{ff})$ for some $l\geq 1$. For optimal performance, $l$ should be computed by \tet{brent_kung_optpow}. \fun{long}{brent_kung_optpow}{long d, long n, long m} returns the optimal parameter $l$ for the evaluation of $n/m$ polynomials of degree $d$. Fractional values can be used if the evaluations are done with different accuracies, and thus have different weights. \subsec{Functions returning black box algebras} \fun{const struct bb_algebra *}{get_FpX_algebra}{void **E, GEN p, long v} return the algebra of polynomials over $\F_p$ in variable $v$. \fun{const struct bb_algebra *}{get_FpXQ_algebra}{void **E, GEN T, GEN p} return the algebra $\F_p[X]/(T(X))$. \fun{const struct bb_algebra *}{get_FpXQX_algebra}{void **E, GEN T, GEN p, long v} return the algebra of polynomials over $\F_p[X]/(T(X))$ in variable $v$. \fun{const struct bb_algebra *}{get_FlxqXQ_algebra}{void **E, GEN S, GEN T, ulong p} return the algebra $\F_p[X,Y]/(S(X,Y),T(X))$ (for \kbd{ulong} $p$). \fun{const struct bb_algebra *}{get_FpXQXQ_algebra}{void **E, GEN S, GEN T, GEN p} return the algebra $\F_p[X,Y]/(S(X,Y),T(X))$. \fun{const struct bb_algebra *}{get_Rg_algebra}{void} return the generic algebra. \section{Black box ring} A black box ring is defined by a \tet{bb_ring} struct, describing methods available to handle ring elements: \bprog struct bb_ring { GEN (*add)(void *E, GEN x, GEN y); GEN (*mul)(void *E, GEN x, GEN y); GEN (*sqr)(void *E, GEN x); }; @eprog \kbd{add(E,x,y)} returns the sum $x+y$. \kbd{mul(E,x,y)} returns the product $x\*y$. \kbd{sqr(E,x)} returns the square $x^2$. \fun{GEN}{gen_fromdigits}{GEN v, GEN B, void *E, struct bb_ring *r} where $B$ is a ring element and $v=[c_0,\ldots,c_{n-1}]$ a vector of ring elements, return $\sum_{i=0}^n c_i\*B^i$ using binary splitting. \fun{GEN}{gen_digits}{GEN x, GEN B, long n, void *E, struct bb_ring *r, GEN (*div)(void *E, GEN x, GEN y, GEN *r)} (Require the ring to be Euclidean) \kbd{div(E,x,y,\&r)} performs the Euclidean division of $x$ by $y$ in the ring $R$, returning the quotient $q$ and setting $r$ to the residue so that $x=q\*y+r$ holds. The residue must belong to a fixed set of representatives of $R/(y)$. The argument $x$ being a ring element, \kbd{gen\_digits} returns a vector of ring elements $[c_0,\ldots,c_{n-1}]$ such that $x = \sum_{i=0}^n c_i\*B^i$. Furthermore for all $i\ne n-1$, the elements $c_i$ belonging to the fixed set of representatives of $R/(B)$. \section{Black box free $\Z_p$-modules} (Very experimental) \fun{GEN}{gen_ZpX_Dixon}{GEN F, GEN V, GEN q, GEN p, long N, void *E, GEN lin(void *E, GEN F, GEN z, GEN q), GEN invl(void *E, GEN z)} Let $F$ be a \kbd{ZpXT} representing the coefficients of some abstract linear mapping $f$ over $\Z_p[X]$ seen as a free $\Z_p$-module, let $V$ be an element of $\Z_p[X]$ and let $q = p^N$. Return $y\in\Z_p[X]$ such that $f(y)=V\pmod{p^N}$ assuming the following holds for $n\leq N$: \item $\kbd{lin}(E, \kbd{FpX\_red}(F, p^n), z, p^n) \equiv f(z) \pmod{p^n}$ \item $f(\kbd{invl}(E, z)) \equiv z \pmod{p}$ The rationale for the argument $F$ being that it allows \kbd{gen\_ZpX\_Dixon} to reduce it to the required $p$-adic precision. \fun{GEN}{gen_ZpX_Newton}{GEN x, GEN p, long n, void *E, GEN eval(void *E, GEN a, GEN q), GEN invd(void *E, GEN b, GEN v, GEN q, long N)} Let $x$ be an element of $\Z_p[X]$ seen as a free $\Z_p$-module, and $f$ some differentiable function over $\Z_p[X]$ such that $f(x) \equiv 0 \pmod{p}$. Return $y$ such that $f(y) \equiv 0\pmod{p^n}$, assuming the following holds for all $a, b\in \Z_p[X]$ and $M\leq N$: \item $v = \kbd{eval}(E,a,p^N)$ is a vector of elements of $\Z_p[X]$, \item $w = \kbd{invd}(E,b,v,p^M,M)$ is an element in $\Z_p[X]$, \item $v[1] \equiv f(a) \pmod{p^N\Z_p[X]}$, \item $df_a(w) \equiv b \pmod{p^M\Z_p[X]}$ \noindent and $df_a$ denotes the differential of $f$ at $a$. Motivation: \kbd{eval} allows to evaluate $f$ and \kbd{invd} allows to invert its differential. Frequently, data useful to compute the differential appear as a subproduct of computing the function. The vector $v$ allows \kbd{eval} to provide these to \kbd{invd}. The implementation of \kbd{invd} will generally involves the use of the function \kbd{gen\_ZpX\_Dixon}. \fun{GEN}{gen_ZpM_Newton}{GEN x, GEN p, long n, void *E, GEN eval(void *E, GEN a, GEN q), GEN invd(void *E, GEN b, GEN v, GEN q, long N)} as above, with polynomials replaced by matrices. \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{int}{gisdouble}{GEN x} if \kbd{x} is a real number (not necessarily a~\typ{REAL}), return $1$ if \kbd{x} can be converted to a \kbd{double}, $0$ otherwise. \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{ulong}{gtou}{GEN x} converts the non-negative \typ{INT} \kbd{x} to an unsigned small integer if possible, otherwise raise an exception. This function is similar to \tet{itou}, slightly slower since it checks the type of \kbd{x}. \fun{double}{dbllog2r}{GEN x} assuming that \kbd{x} is a nonzero \typ{REAL}, returns an approximation to \kbd{log2(|x|)}. \fun{double}{dblmodulus}{GEN x} return an approximation to \kbd{|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}{upper_to_cx}{GEN x, long *prec} valid for a \typ{COMPLEX} or \typ{QUAD} belonging to the upper half-plane. If a \typ{QUAD}, convert it to \typ{COMPLEX} using accuracy \kbd{*prec}. If $x$ is inexact, sets \kbd{*prec} to the precision of $x$. \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}{cxtoreal}{GEN x} converts the complex (\typ{INT}, \typ{REAL}, \typ{FRAC} or \typ{COMPLEX}) $x$ to a real number if its imaginary part is 0. Shallow function. 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}{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-38 = 0.E-38$. \fun{GEN}{gtomp}{GEN z, long prec} converts the real number~\kbd{x} (\typ{INT}, \typ{REAL}, \typ{FRAC}, real \typ{QUAD}) to either a \typ{INT} or a \typ{REAL} of precision \kbd{prec}. Not memory clean if $x$ is a \typ{INT}: we return $x$ itself and not a copy. \fun{GEN}{gcvtop}{GEN x, GEN p, long l} converts $x$ into a \typ{PADIC} of precision~$l$. Works componentwise on recursive objects, e.g.~\typ{POL} or \typ{VEC}. Converting $0$ yields $O(p^l)$; converting a nonzero 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 prec} returns a shallow copy of $x$ whose \typ{REAL} components have their precision changed to \kbd{prec} bits. This is often more useful than \kbd{gprec}. \fun{GEN}{gprec_wtrunc}{GEN x, long prec} returns a shallow copy of $x$ whose \typ{REAL} components have their precision \emph{truncated} to \kbd{prec} bits. Contrary to \kbd{gprec\_w}, this function may never increase the precision of~$x$. \fun{GEN}{gprec_wensure}{GEN x, long prec} returns a shallow copy of $x$ whose \typ{REAL} components have their precision \emph{increased} to at least $prec$ bits. Contrary to \kbd{gprec\_w}, this function may never decrease the precision of~$x$. The following functions are obsolete and kept for backward compatibility only: \fun{GEN}{precision0}{GEN x, long n} \fun{GEN}{bitprecision0}{GEN x, long n} \subsec{Modular objects / lifts} \fun{GEN}{gmodulo}{GEN x, GEN y} creates the object \kbd{\key{Mod}(x,y)} on the PARI stack, where \kbd{x} and \kbd{y} are either both \typ{INT}s, and the result is a \typ{INTMOD}, or \kbd{x} is a scalar or a \typ{POL} and \kbd{y} a \typ{POL}, and the result is a \typ{POLMOD}. \fun{GEN}{gmodulgs}{GEN x, long y} same as \key{gmodulo} except \kbd{y} is a \kbd{long}. \fun{GEN}{gmodulsg}{long x, GEN y} same as \key{gmodulo} except \kbd{x} is a \kbd{long}. \fun{GEN}{gmodulss}{long x, long y} same as \key{gmodulo} except both \kbd{x} and \kbd{y} are \kbd{long}s. \fun{GEN}{lift_shallow}{GEN x} shallow version of \tet{lift} \fun{GEN}{liftall_shallow}{GEN x} shallow version of \tet{liftall} \fun{GEN}{liftint_shallow}{GEN x} shallow version of \tet{liftint} \fun{GEN}{liftpol_shallow}{GEN x} shallow version of \tet{liftpol} \fun{GEN}{centerlift0}{GEN x,long v} DEPRECATED, kept for backward compatibility only: use either \tet{lift0}$(x,v)$ or \tet{centerlift}$(x)$. \subsec{Between polynomials and coefficient arrays} \fun{GEN}{gtopoly}{GEN x, long v} converts or truncates the object~\kbd{x} into a \typ{POL} with main variable number~\kbd{v}. A common application would be the conversion of coefficient vectors (coefficients are given by decreasing degree). E.g.~\kbd{[2,3]} goes to \kbd{2*v + 3} \fun{GEN}{gtopolyrev}{GEN x, long v} converts or truncates the object~\kbd{x} into a \typ{POL} with main variable number~\kbd{v}, but vectors are converted in reverse order compared to \kbd{gtopoly} (coefficients are given by increasing degree). E.g.~\kbd{[2,3]} goes to \kbd{3*v + 2}. In other words the vector represents a polynomial in the basis $(1,v,v^2,v^3,\dots)$. \fun{GEN}{normalizepol}{GEN x} applied to an unnormalized \typ{POL}~\kbd{x} (with all coefficients correctly set except that \kbd{leading\_term(x)} might be zero), normalizes \kbd{x} correctly in place and returns~\kbd{x}. For internal use. Normalizing means deleting all leading \emph{exact} zeroes (as per \kbd{isexactzero}), except if the polynomial turns out to be $0$, in which case we try to find a coefficient $c$ which is a nonrational zero, and return the constant polynomial $c$. (We do this so that information about the base ring is not lost.) \fun{GEN}{normalizepol_lg}{GEN x, long l} applies \kbd{normalizepol} to \kbd{x}, pretending that \kbd{lg(x)} is $l$, which must be less than or equal to \kbd{lg(x)}. If equal, the function is equivalent to \kbd{normalizepol(x)}. \fun{GEN}{normalizepol_approx}{GEN x, long lx} as \kbd{normalizepol\_lg}, with the difference that we just delete all leading zeroes (as per \kbd{gequal0}). This rougher normalization is used when we have no other choice, for instance before attempting a Euclidean division by $x$. The following routines do \emph{not} copy coefficients on the stack (they only move pointers around), hence are very fast but not suitable for \kbd{gerepile} calls. Recall that an \kbd{RgV} (resp.~an \kbd{RgX}, resp.~an \kbd{RgM}) is a \typ{VEC} or \typ{COL} (resp.~a \typ{POL}, resp.~a \typ{MAT}) with arbitrary components. Similarly, an \kbd{RgXV} is a \typ{VEC} or \typ{COL} with \kbd{RgX} components, etc. \fun{GEN}{RgV_to_RgX}{GEN x, long v} converts the \kbd{RgV}~\kbd{x} to a (normalized) polynomial in variable~\kbd{v} (as \kbd{gtopolyrev}, without copy). \fun{GEN}{RgV_to_RgX_reverse}{GEN x, long v} converts the \kbd{RgV}~\kbd{x} to a (normalized) polynomial in variable~\kbd{v} (as \kbd{gtopoly}, without copy). \fun{GEN}{RgX_to_RgC}{GEN x, long N} converts the \typ{POL}~\kbd{x} to a \typ{COL}~\kbd{v} with \kbd{N} components. Coefficients of \kbd{x} are listed by increasing degree, so that \kbd{y[i]} is the coefficient of the term of degree $i-1$ in \kbd{x}. \fun{GEN}{Rg_to_RgC}{GEN x, long N} as \tet{RgX_to_RgV}, except that other types than \typ{POL} are allowed for \kbd{x}, which is then considered as a constant polynomial. \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}{RgM_to_RgXV_reverse}{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\_reverse}. \fun{GEN}{RgV_to_RgM}{GEN v, long N} converts the vector~\kbd{v} to a~\typ{MAT} with \kbd{N}~rows, by repeated calls to \kbd{Rg\_to\_RgV}. \fun{GEN}{RgXV_to_RgM}{GEN v, long N} converts the vector of \kbd{RgX}~\kbd{v} to a~\typ{MAT} with \kbd{N}~rows, by repeated calls to \kbd{RgX\_to\_RgV}. \fun{GEN}{RgM_to_RgXX}{GEN x, long v,long w} converts the \kbd{RgM}~\kbd{x} into a \typ{POL} in variable~\kbd{v}, whose coefficients are \typ{POL}s in variable~\kbd{w}. This is a shortcut for \bprog RgV_to_RgX( RgM_to_RgXV(x, w), v ); @eprog\noindent There are no consistency checks with respect to variable priorities: the above is an invalid object if $\kbd{varncmp(v, w)} \geq 0$. \fun{GEN}{RgXX_to_RgM}{GEN x, long N} converts the \typ{POL}~\kbd{x} with \kbd{RgX} (or constant) coefficients to a matrix with \kbd{N} rows. \fun{long}{RgXY_degreex}{GEN P} return the degree of $P$ with respect to the secondary variable. \fun{GEN}{RgXY_derivx}{GEN P} return the derivative of $P$ with respect to the secondary variable. \fun{GEN}{RgXY_swap}{GEN P, long n, long w} converts the bivariate polynomial $\kbd{P}(u,v)$ (a \typ{POL} with \typ{POL} or scalar coefficients) to $P(\kbd{pol\_x[w]},u)$, assuming \kbd{n} is an upper bound for $\deg_v(\kbd{P})$. \fun{GEN}{RgXY_swapspec}{GEN C, long n, long w, long lP} as \kbd{RgXY\_swap} where the coefficients of $P$ are given by \kbd{gel(C,0),\dots,gel(C,lP-1)}. \fun{GEN}{RgX_to_ser}{GEN x, long l} convert the \typ{POL}~\kbd{x} to a \emph{shallow} \typ{SER} of length~$l\geq 2$. 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-2})$. \fun{GEN}{RgX_to_ser_inexact}{GEN x, long l} convert the \typ{POL}~\kbd{x} to a \emph{shallow} \typ{SER} of length~$l\geq 2$. 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-2})$. \fun{GEN}{RgV_to_ser}{GEN x, long v, long l} convert the \typ{VEC}~\kbd{x}, to a \emph{shallow} \typ{SER} of length~$l\geq 2$. \fun{GEN}{rfrac_to_ser}{GEN F, long l} applied to a \typ{RFRAC}~$F$, creates a \typ{SER} of length~$l\geq 2$ congruent to $F$. Not memory-clean but suitable for \kbd{gerepileupto}. \fun{GEN}{rfrac_to_ser_i}{GEN F, long l} internal variant of \kbd{rfrac\_to\_ser}, neither memory-clean nor suitable for \kbd{gerepileupto}. \fun{GEN}{rfracrecip_to_ser_absolute}{GEN F, long d} applied to a \typ{RFRAC}~$F$, creates the \typ{SER} $F(1/t) + O(t^d)$. Note that we use absolute and not relative precision here. \fun{GEN}{gtoser}{GEN s, long v, long d}. This function is deprecated, kept for backward compatibility: it follows the semantic of \kbd{Ser(s,v)}, with $d = \kbd{seriesprecision}$ implied and is hard to use as a general conversion function. Use \tet{gtoser_prec} instead. It converts the object~$s$ into a \typ{SER} with main variable number~\kbd{v} and $d > 0$ significant terms, but the argument $d$ is sometimes ignored. More precisely \item if $s$ is a scalar (with respect to variable $v$), we return a constant power series with $d$ significant terms; \item if $s$ is a \typ{POL} in variable $v$, it is truncated to $d$ terms if needed; \item if $s$ is a vector, the coefficients of the vector are understood to be the coefficients of the power series starting from the constant term (as in \tet{Polrev}), and the precision $d$ is \emph{ignored}; \item if $s$ is already a power series in $v$, we return a copy, and the precision $d$ is again \emph{ignored}. \fun{GEN}{gtoser_prec}{GEN s, long v, long d} this function is a variant of \kbd{gtoser} following the semantic of \kbd{Ser(s,v,d)}: the precision $d$ is always taken into account. \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}{normalizeser}{GEN x} applied to an unnormalized \typ{SER}~\kbd{x} (i.e.~type \typ{SER} with all coefficients correctly set except that \kbd{x[2]} might be zero), normalizes \kbd{x} correctly in place. Returns~\kbd{x}. For internal use. \fun{GEN}{serchop0}{GEN s} given a \typ{SER} of the form $x^v s(x)$, with $s(0)\neq 0$, return $x^v(s - s(0))$. Shallow function. \fun{GEN}{serchop_i}{GEN x, long n} returns a shallow chopy of \typ{SER} $x$ with all terms of degree strictly less than $n$ removed. Shallow version of \kbd{serchop}. \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{prec}\geq 0$. \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_xn}{long n, long v} Returns the monomial of degree $n$ in variable $v$; assume that $n \geq 0$. \fun{GEN}{pol_xnall}{long n, long v} Returns the Laurent monomial of degree $n$ in variable $v$; $n < 0$ is allowed. \fun{GEN}{pol_x_powers}{long N, long v} returns the powers of \kbd{pol\_x(v)}, of degree $0$ to $N-1$, in a vector with $N$ components. \fun{GEN}{scalarpol}{GEN x, long v} creates a constant \typ{POL} in variable \kbd{v}, whose constant coefficient is (a copy of) \kbd{x}. \fun{GEN}{deg1pol}{GEN a, GEN b,long v} creates the degree 1 \typ{POL} $a \kbd{pol\_x}(v) + b$ \fun{GEN}{zeropol}{long v} is identical \kbd{pol\_0}. \fun{GEN}{zerocol}{long n} creates a \typ{COL} with \kbd{n} components set to \kbd{gen\_0}. \fun{GEN}{zerovec}{long n} creates a \typ{VEC} with \kbd{n} components set to \kbd{gen\_0}. \fun{GEN}{zerovec_block}{long n} as \kbd{zerovec} but return a clone. \fun{GEN}{col_ei}{long n, long i} creates a \typ{COL} with \kbd{n} components set to \kbd{gen\_0}, but for the \kbd{i}-th one which is set to \kbd{gen\_1} (\kbd{i}-th vector in the canonical basis). \fun{GEN}{vec_ei}{long n, long i} creates a \typ{VEC} with \kbd{n} components set to \kbd{gen\_0}, but for the \kbd{i}-th one which is set to \kbd{gen\_1} (\kbd{i}-th vector in the canonical basis). \fun{GEN}{trivial_fact}{void} returns the trivial (empty) factorization \kbd{Mat([]\til,[]\til)} \fun{GEN}{prime_fact}{GEN x} returns the factorization \kbd{Mat([x]\til, [1]\til)} \fun{GEN}{Rg_col_ei}{GEN x, long n, long i} creates a \typ{COL} with \kbd{n} components set to \kbd{gen\_0}, but for the \kbd{i}-th one which is set to \kbd{x}. \fun{GEN}{vecsmall_ei}{long n, long i} creates a \typ{VECSMALL} with \kbd{n} components set to \kbd{0}, but for the \kbd{i}-th one which is set to \kbd{1} (\kbd{i}-th vector in the canonical basis). \fun{GEN}{scalarcol}{GEN x, long n} creates a \typ{COL} with \kbd{n} components set to \kbd{gen\_0}, but the first one which is set to a copy of \kbd{x}. (The name comes from \kbd{RgV\_isscalar}.) \smallskip \fun{GEN}{mkintmodu}{ulong x, ulong y} creates the \typ{INTMOD} \kbd{Mod(x, y)}. The inputs must satisfy $x < y$. \fun{GEN}{zeromat}{long m, long n} creates a \typ{MAT} with \kbd{m} x \kbd{n} components set to \kbd{gen\_0}. Note that the result allocates a \emph{single} column, so modifying an entry in one column modifies it in all columns. To fully allocate a matrix initialized with zero entries, use \kbd{zeromatcopy}. \fun{GEN}{zeromatcopy}{long m, long n} creates a \typ{MAT} with \kbd{m} x \kbd{n} components set to \kbd{gen\_0}. \fun{GEN}{matid}{long n} identity matrix in dimension \kbd{n} (with components \kbd{gen\_1} and\kbd{gen\_0}). \fun{GEN}{scalarmat}{GEN x, long n} scalar matrix, \kbd{x} times the identity. \fun{GEN}{scalarmat_s}{long x, long n} scalar matrix, \kbd{stoi(x)} times the identity. \fun{GEN}{vecrange}{GEN a, GEN b} returns the \typ{VEC} $[a..b]$. \fun{GEN}{vecrangess}{long a, long b} returns the \typ{VEC} $[a..b]$. \smallskip See also next section for analogs of the following functions: \fun{GEN}{mkfracss}{long x, long y} creates the \typ{FRAC} $x/y$. Assumes that $y > 1$ and $(x,y) = 1$. \fun{GEN}{sstoQ}{long x, long y} returns the \typ{INT} or \typ{FRAC} $x/y$; no assumptions. \fun{GEN}{uutoQ}{ulong x, ulong y} returns the \typ{INT} or \typ{FRAC} $x/y$; no assumptions. \fun{void}{Qtoss}{GEN q, long *n, long *d} given a \typ{INT} or \typ{FRAC} $q$, set $n$ and $d$ such that $q = n/d$ with $d \geq 1$ and $(n,d)$ = 1. Overflow error if numerator or denominator do not fit into a long integer. \fun{GEN}{mkfraccopy}{GEN x, GEN y} creates the \typ{FRAC} $x/y$. Assumes that $y > 1$ and $(x,y) = 1$. \fun{GEN}{mkrfraccopy}{GEN x, GEN y} creates the \typ{RFRAC} $x/y$. Assumes that $y$ is a \typ{POL}, $x$ a compatible type whose variable has lower or same priority, with $(x,y) = 1$. \fun{GEN}{mkcolcopy}{GEN x} creates a 1-dimensional \typ{COL} containing \kbd{x}. \fun{GEN}{mkmatcopy}{GEN x} creates a 1-by-1 \typ{MAT} wrapping the \typ{COL} \kbd{x}. \fun{GEN}{mkveccopy}{GEN x} creates a 1-dimensional \typ{VEC} containing \kbd{x}. \fun{GEN}{mkvec2copy}{GEN x, GEN y} creates a 2-dimensional \typ{VEC} equal to \kbd{[x,y]}. \fun{GEN}{mkcols}{long x} creates a 1-dimensional \typ{COL} containing \kbd{stoi(x)}. \fun{GEN}{mkcol2s}{long x, long y} creates a 2-dimensional \typ{COL} containing \kbd{[stoi(x), stoi(y)]~}. \fun{GEN}{mkcol3s}{long x, long y, long z} creates a 3-dimensional \typ{COL} containing \kbd{[stoi(x), stoi(y), stoi(z)]~}. \fun{GEN}{mkcol4s}{long x, long y, long z, long t} creates a 4-dimensional \typ{COL} containing \kbd{[stoi(x), stoi(y), stoi(z), stoi(t)]~}. \fun{GEN}{mkvecs}{long x} creates a 1-dimensional \typ{VEC} containing \kbd{stoi(x)}. \fun{GEN}{mkvec2s}{long x, long y} creates a 2-dimensional \typ{VEC} containing \kbd{[stoi(x), stoi(y)]}. \fun{GEN}{mkmat22s}{long a, long b, long c, long d} creates the $2$ by $2$ \typ{MAT} with successive rows \kbd{[stoi(a), stoi(b)]} and \kbd{[stoi(c), stoi(d)]}. \fun{GEN}{mkvec3s}{long x, long y, long z} creates a 3-dimensional \typ{VEC} containing \kbd{[stoi(x), stoi(y), stoi(z)]}. \fun{GEN}{mkvec4s}{long x, long y, long z, long t} creates a 4-dimensional \typ{VEC} containing \kbd{[stoi(x), stoi(y), stoi(z), stoi(t)]}. \fun{GEN}{mkvecsmall}{long x} creates a 1-dimensional \typ{VECSMALL} containing \kbd{x}. \fun{GEN}{mkvecsmall2}{long x, long y} creates a 2-dimensional \typ{VECSMALL} containing \kbd{[x, y]}. \fun{GEN}{mkvecsmall3}{long x, long y, long z} creates a 3-dimensional \typ{VECSMALL} containing \kbd{[x, y, z]}. \fun{GEN}{mkvecsmall4}{long x, long y, long z, long t} creates a 4-dimensional \typ{VECSMALL} containing \kbd{[x, y, z, t]}. \fun{GEN}{mkvecsmall5}{long x, long y, long z, long t, long u} creates a 5-dimensional \typ{VECSMALL} containing \kbd{[x, y, z, t, u]}. \fun{GEN}{mkvecsmalln}{long n, ...} returns the \typ{VECSMALL} whose $n$ coefficients (\kbd{long}) follow. \emph{Warning:} since this is a variadic function, C type promotion is not performed on the arguments by the compiler, thus you have to make sure that all the arguments are of type \kbd{long}, in particular integer constants need to be written with the \kbd{L} suffix: \kbd{mkvecsmalln(2, 1L, 2L)} is correct, but \kbd{mkvecsmalln(2, 1, 2)} is not. \subsec{Unclean constructors}\label{se:unclean} 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 $-ix$. \fun{GEN}{mulcxpowIs}{GEN x, long k}, as \tet{mulcxI}, but returns $x \cdot i^k$. \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}{quadpoly_i}{GEN D} creates the canonical quadratic polynomial of discriminant $D$. Assume that the \typ{INT} $D$ is congruent to $0,1$ mod $4$ and not a square. \fun{GEN}{mkfrac}{GEN x, GEN y} creates the \typ{FRAC} $x/y$. Assumes that $y > 1$ and $(x,y) = 1$. \fun{GEN}{mkrfrac}{GEN x, GEN y} creates the \typ{RFRAC} $x/y$. Assumes that $y$ is a \typ{POL}, $x$ a compatible type whose variable has lower or same priority, with $(x,y) = 1$. \fun{GEN}{mkcol}{GEN x} creates a 1-dimensional \typ{COL} containing \kbd{x}. \fun{GEN}{mkcol2}{GEN x, GEN y} creates a 2-dimensional \typ{COL} equal to \kbd{[x,y]}. \fun{GEN}{mkcol3}{GEN x, GEN y, GEN z} creates a 3-dimensional \typ{COL} equal to \kbd{[x,y,z]}. \fun{GEN}{mkcol4}{GEN x, GEN y, GEN z, GEN t} creates a 4-dimensional \typ{COL} equal to \kbd{[x,y,z,t]}. \fun{GEN}{mkcol5}{GEN a1, GEN a2, GEN a3, GEN a4, GEN a5} creates the 5-dimensional \typ{COL} equal to $[a_1,a_2,a_3,a_4,a_5]$. \fun{GEN}{mkcol6}{GEN x, GEN y, GEN z, GEN t, GEN u, GEN v} creates the $6$-dimensional column vector \kbd{[x,y,z,t,u,v]~}. \fun{GEN}{mkintmod}{GEN x, GEN y} creates the \typ{INTMOD} \kbd{Mod(x, y)}. The inputs must be \typ{INT}s satisfying $0 \leq x < y$. \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}{mkmat22}{GEN a, GEN b, GEN c, GEN d} creates the $2$ by $2$ \typ{MAT} with successive rows $[a,b]$ and $[c,d]$. \fun{GEN}{mkmat3}{GEN x, GEN y, GEN z} creates a 3-column \typ{MAT} with columns $x$, $y$, $z$ (\typ{COL}s of the same length). \fun{GEN}{mkmat4}{GEN x, GEN y, GEN z, GEN t} creates a 4-column \typ{MAT} with columns $x$, $y$, $z$, $t$ (\typ{COL}s of the same length). \fun{GEN}{mkmat5}{GEN x, GEN y, GEN z, GEN t, GEN u} creates a 5-column \typ{MAT} with columns $x$, $y$, $z$, $t$, $u$ (\typ{COL}s of the same length). \fun{GEN}{mkvec}{GEN x} creates a 1-dimensional \typ{VEC} containing \kbd{x}. \fun{GEN}{mkvec2}{GEN x, GEN y} creates a 2-dimensional \typ{VEC} equal to \kbd{[x,y]}. \fun{GEN}{mkvec3}{GEN x, GEN y, GEN z} creates a 3-dimensional \typ{VEC} equal to \kbd{[x,y,z]}. \fun{GEN}{mkvec4}{GEN x, GEN y, GEN z, GEN t} creates a 4-dimensional \typ{VEC} equal to \kbd{[x,y,z,t]}. \fun{GEN}{mkvec5}{GEN a1, GEN a2, GEN a3, GEN a4, GEN a5} creates the 5-dimensional \typ{VEC} equal to $[a_1,a_2,a_3,a_4,a_5]$. \fun{GEN}{mkqfb}{GEN a, GEN b, GEN c, GEN D} creates \typ{QFB} equal to \kbd{Qfb(a,b,c)}, assuming that $D = b^2 - 4ac$. \fun{GEN}{mkerr}{long n} returns a \typ{ERROR} with error code $n$ (\kbd{enum err\_list}). \smallskip It is sometimes useful to return such a container whose entries are not universal objects, but nonetheless suitable for \tet{gerepileupto}. If the entries can be computed at the time the result is returned, the following macros achieve this effect: \fun{GEN}{retmkvec}{GEN x} returns a vector containing the single entry $x$, where the vector root is created just before the function argument $x$ is evaluated. Expands to \bprog { GEN res = cgetg(2, t_VEC); gel(res, 1) = x; /* @Ccom or rather, the \emph{expansion} of $x$ */ return res; } @eprog\noindent For instance, the \kbd{retmkvec(gcopy(x))} returns a clean object, just like \kbd{return mkveccopy(x)} would. \fun{GEN}{retmkvec2}{GEN x, GEN y} returns the $2$-dimensional \typ{VEC} \kbd{[x,y]}. \fun{GEN}{retmkvec3}{GEN x, GEN y, GEN z} returns the $3$-dimensional \typ{VEC} \kbd{[x,y,z]}. \fun{GEN}{retmkvec4}{GEN x, GEN y, GEN z, GEN t} returns the $4$-dimensional \typ{VEC} \kbd{[x,y,z,t]}. \fun{GEN}{retmkvec5}{GEN x, GEN y, GEN z, GEN t, GEN u} returns the $5$-dimensional row vector \kbd{[x,y,z,t,u]}. \fun{GEN}{retconst_vec}{long n, GEN x} returns the $n$-dimensional \typ{VEC} whose entries are constant and all equal to $x$. \fun{GEN}{retmkcol}{GEN x} returns the $1$-dimensional \typ{COL} \kbd{[x]~}. \fun{GEN}{retmkcol2}{GEN x, GEN y} returns the $2$-dimensional \typ{COL} \kbd{[x,y]~}. \fun{GEN}{retmkcol3}{GEN x, GEN y, GEN z} returns the $3$-dimensional \typ{COL} \kbd{[x,y,z]~}. \fun{GEN}{retmkcol4}{GEN x, GEN y, GEN z, GEN t} returns the $4$-dimensional \typ{COL} \kbd{[x,y,z,t]~}. \fun{GEN}{retmkcol5}{GEN x, GEN y, GEN z, GEN t, GEN u} returns the $5$-dimensional column vector \kbd{[x,y,z,t,u]~}. \fun{GEN}{retmkcol6}{GEN x, GEN y, GEN z, GEN t, GEN u, GEN v} returns the $6$-dimensional column vector \kbd{[x,y,z,t,u,v]~}. \fun{GEN}{retconst_col}{long n, GEN x} returns the $n$-dimensional \typ{COL} whose entries are constant and all equal to $x$. \fun{GEN}{retmkmat}{GEN x} returns the $1$-column \typ{MAT} with colum \kbd{x}. \fun{GEN}{retmkmat2}{GEN x, GEN y} returns the $2$-column \typ{MAT} with columns \kbd{x}, \kbd{y}. \fun{GEN}{retmkmat3}{GEN x, GEN y, GEN z} returns the $3$-dimensional \typ{MAT} with columns \kbd{x}, \kbd{y}, \kbd{z}. \fun{GEN}{retmkmat4}{GEN x, GEN y, GEN z, GEN t} returns the $4$-dimensional \typ{MAT} with columns \kbd{x}, \kbd{y}, \kbd{z}, \kbd{t}. \fun{GEN}{retmkmat5}{GEN x, GEN y, GEN z, GEN t, GEN u} returns the $5$-dimensional \typ{MAT} with columns \kbd{x}, \kbd{y}, \kbd{z}, \kbd{t}, \kbd{u}. \fun{GEN}{retmkmat22}{GEN a, GEN b, GEN c, GEN d} return the $2$ by $2$ \typ{MAT} with successive rows $[a,b]$ and $[c,d]$. \fun{GEN}{retmkcomplex}{GEN x, GEN y} returns the \typ{COMPLEX} \kbd{x + I*y}. \fun{GEN}{retmkfrac}{GEN x, GEN y} returns the \typ{FRAC} \kbd{x / y}. Assume $x$ and $y$ are coprime and $y > 1$. \fun{GEN}{retmkrfrac}{GEN x, GEN y} returns the \typ{RFRAC} \kbd{x / y}. Assume $x$ and $y$ are coprime and more generally that the rational function cannot be simplified. \fun{GEN}{retmkintmod}{GEN x, GEN y} returns the \typ{INTMOD} \kbd{Mod(x, y)}. \fun{GEN}{retmkquad}{GEN n, GEN a, GEN b}. \fun{GEN}{retmkpolmod}{GEN x, GEN y} returns the \typ{POLMOD} \kbd{Mod(x, y)}. \smallskip \fun{GEN}{mkintn}{long n, ...} returns the nonnegative \typ{INT} whose expansion in base $2^{32}$ is given by the following $n$ 32bit-words (\kbd{unsigned int}). \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}{RgX_sylvestermatrix}{GEN f, GEN g} return the Sylvester matrix attached to the two \typ{POL} in the same variable $f$ and $g$. \fun{GEN}{diagonal_shallow}{GEN x} returns a diagonal matrix whose diagonal is given by the vector $x$. Shallow function. \fun{GEN}{scalarpol_shallow}{GEN a, long v} returns the degree $0$ \typ{POL} $a \kbd{pol\_x}(v)^0$. \fun{GEN}{deg1pol_shallow}{GEN a, GEN b,long v} returns the degree $1$ \typ{POL} $a\kbd{pol\_x}(v) + b$ \fun{GEN}{deg2pol_shallow}{GEN a, GEN b, GEN c, long v} returns the degree $2$ \typ{POL} $a\*x^2+b\*x+c$ where $x=\kbd{pol\_x}(v)$. \fun{GEN}{zeropadic_shallow}{GEN p, long n} returns a (shallow) $0$ \typ{PADIC} equal to $O(\kbd{p}^\kbd{n})$. \subsec{From roots to polynomials} \fun{GEN}{deg1_from_roots}{GEN L, long v} given a vector $L$ of scalars, returns the vector of monic linear polynomials in variable $v$ whose roots are the $L[i]$, i.e. the $x - L[i]$. \fun{GEN}{roots_from_deg1}{GEN L} given a vector $L$ of monic linear polynomials, return their roots, i.e. the $- L[i](0)$. \fun{GEN}{roots_to_pol}{GEN L, long v} given a vector of scalars $L$, returns the monic polynomial in variable $v$ whose roots are the $L[i]$. 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)$. 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, then significant bits are lost in the rounded result. This kind of situation raises an error message in \key{ground} but not in \key{grndtoi}. The parameter $e$ can be set to \kbd{NULL} if an error estimate is not needed, for a minor speed up. \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 nonnegative) or right by $-\kbd{n}$ (if \kbd{n} is negative). Applies only to \typ{INT} and vectors/matrices of such. For other types, it is simply multiplication by~$2^{\kbd{n}}$. \fun{GEN}{gmul2n[z]}{GEN x, long n[, GEN z]} yields the product of \kbd{x} and~$2^{\kbd{n}}$. This is different from \kbd{gshift} when \kbd{n} is negative and \kbd{x} is a \typ{INT}: \key{gshift} truncates, while \key{gmul2n} creates a fraction if necessary. \fun{long}{gvaluation}{GEN x, GEN p} returns the greatest exponent~$e$ such that $\kbd{p}^e$ divides~\kbd{x}, when this makes sense. \fun{long}{gval}{GEN x, long v} returns the highest power of the variable number \kbd{v} dividing the \typ{POL}~\kbd{x}. \section{Comparison operators} \subsec{Generic} \fun{long}{gcmp}{GEN x, GEN y} comparison of \kbd{x} with \kbd{y}: returns $1$ ($x > y$), $0$ ($x = y$) or $-1$ ($x < y$). Two \typ{STR} are compared using the standard lexicographic ordering; a \typ{STR} cannot be compared to any non-string type. If neither $x$ nor $y$ is a \typ{STR}, their allowed types are \typ{INT}, \typ{REAL}, \typ{FRAC}, \typ{QUAD} with positive discriminant (use the canonical embedding $w \to \sqrt{D}/2$ or $w \to (1 + \sqrt{D})/2$) or \typ{INFINITY}. Use \tet{cmp_universal} to compare arbitrary \kbd{GEN}s. \fun{long}{lexcmp}{GEN x, GEN y} comparison of \kbd{x} with \kbd{y} for the lexicographic ordering; when comparing objects of different lengths whose components are all equal up to the smallest of their length, consider that the longest is largest. Consider scalars as $1$-component vectors. Return \kbd{gcmp}$(x,y)$ if both arguments are scalars. \fun{int}{gequalX}{GEN x} return 1 (true) if \kbd{x} is a variable (monomial of degree $1$ with \typ{INT} coefficients equal to $1$ and $0$), and $0$ otherwise \fun{long}{gequal}{GEN x, GEN y} returns 1 (true) if \kbd{x} is equal to~\kbd{y}, 0~otherwise. A priori, this makes sense only if \kbd{x} and \kbd{y} have the same type, in which case they are recursively compared componentwise. When the types are different, a \kbd{true} result means that \kbd{x - y} was successfully computed and that \kbd{gequal0} found it equal to $0$. In particular \bprog gequal(cgetg(1, t_VEC), gen_0) @eprog\noindent is true, and the relation is not transitive. E.g.~an empty \typ{COL} and an empty \typ{VEC} are not equal but are both equal to \kbd{gen\_0}. \fun{long}{gidentical}{GEN x, GEN y} returns 1 (true) if \kbd{x} is identical to~\kbd{y}, 0~otherwise. In particular, the types and length of \kbd{x} and \kbd{y} must be equal. This test is much stricter than \tet{gequal}, in particular, \typ{REAL} with different accuracies are tested different. This relation is transitive. \fun{GEN}{gmax}{GEN x, GEN y} returns a copy of the maximum of $x$ and $y$, compared using \kbd{gcmp}. \fun{GEN}{gmin}{GEN x, GEN y} returns a copy of the minimum of $x$ and $y$, compared using \kbd{gcmp}. \fun{GEN}{gmax_shallow}{GEN x, GEN y} shallow version of \kbd{gmax}. \fun{GEN}{gmin_shallow}{GEN x, GEN y} shallow version of \kbd{gmin}. \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{GEN}{gisexactzero}{GEN x} returns \kbd{NULL} unless \kbd{x} is exactly equal to~0 (as per \kbd{isexactzero}). When \kbd{x} is an exact zero return the attached scalar zero as a \typ{INT} (\kbd{gen\_0}), a \typ{INTMOD} (\kbd{Mod(0,$N$)} for the largest possible $N$) or a \typ{FFELT}. \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{nonzero} \typ{INT}, return 1 (true) if \kbd{x} is equal to $-1$ or $1$, and return 0~(false) otherwise. \fun{int}{gequal0}{GEN x} returns 1 (true) if \kbd{x} is equal to~0, 0~(false) otherwise. \fun{int}{gequal1}{GEN x} returns 1 (true) if \kbd{x} is equal to~1, 0~(false) otherwise. \fun{int}{gequalm1}{GEN x} returns 1 (true) if \kbd{x} is equal to~$-1$, 0~(false) otherwise. \fun{long}{gcmpsg}{long s, GEN x} \fun{long}{gcmpgs}{GEN x, long s} comparison of \kbd{x} with the \kbd{long}~\kbd{s}. \fun{GEN}{gmaxsg}{long s, GEN x} \fun{GEN}{gmaxgs}{GEN x, long s} returns the largest of \kbd{x} and the \kbd{long}~\kbd{s} (converted to \kbd{GEN}) \fun{GEN}{gminsg}{long s, GEN x} \fun{GEN}{gmings}{GEN x, long s} returns the smallest of \kbd{x} and the \kbd{long}~\kbd{s} (converted to \kbd{GEN}) \fun{long}{gequalsg}{long s, GEN x} \fun{long}{gequalgs}{GEN x, long s} returns 1 (true) if \kbd{x} is equal to the \kbd{long}~\kbd{s}, 0~otherwise. \section{Miscellaneous Boolean functions} \fun{int}{isrationalzeroscalar}{GEN x} equivalent to, but faster than, \bprog is_scalar_t(typ(x)) && isrationalzero(x) @eprog \fun{int}{isinexact}{GEN x} returns 1 (true) if $x$ has an inexact component, and 0 (false) otherwise. \fun{int}{isinexactreal}{GEN x} return 1 if $x$ has an inexact \typ{REAL} component, and 0 otherwise. \fun{int}{isrealappr}{GEN x, long e} applies (recursively) to complex inputs; returns $1$ if $x$ is approximately real to the bit accuracy $e$, and 0 otherwise. This means that any \typ{COMPLEX} component must have imaginary part $t$ satisfying $\kbd{gexpo}(t) < e$. \fun{int}{isint}{GEN x, GEN *n} returns 0 (false) if \kbd{x} does not round to an integer. Otherwise, returns 1 (true) and set \kbd{n} to the rounded value. \fun{int}{issmall}{GEN x, long *n} returns 0 (false) if \kbd{x} does not round to a small integer (suitable for \kbd{itos}). Otherwise, returns 1 (true) and set \kbd{n} to the rounded value. \fun{long}{iscomplex}{GEN x} returns 1 (true) if \kbd{x} is a complex number (of component types embeddable into the reals) but is not itself real, 0~if \kbd{x} is a real (not necessarily of type \typ{REAL}), or raises an error if \kbd{x} is not embeddable into the complex numbers. \subsec{Obsolete} The following less convenient comparison functions and Boolean operators were used by the historical GP interpreter. They are provided for backward compatibility only and should not be used: \fun{GEN}{gle}{GEN x, GEN y} \fun{GEN}{glt}{GEN x, GEN y} \fun{GEN}{gge}{GEN x, GEN y} \fun{GEN}{ggt}{GEN x, GEN y} \fun{GEN}{geq}{GEN x, GEN y} \fun{GEN}{gne}{GEN x, GEN y} \fun{GEN}{gor}{GEN x, GEN y} \fun{GEN}{gand}{GEN x, GEN y} \fun{GEN}{gnot}{GEN x, GEN y} \section{Sorting} \subsec{Basic sort} \fun{GEN}{sort}{GEN x} sorts the vector \kbd{x} in ascending order using a mergesort algorithm, and \kbd{gcmp} as the underlying comparison routine (returns the sorted vector). This routine copies all components of $x$, use \kbd{gen\_sort\_inplace} for a more memory-efficient function. \fun{GEN}{lexsort}{GEN x}, as \kbd{sort}, using \kbd{lexcmp} instead of \kbd{gcmp} as the underlying comparison routine. \fun{GEN}{vecsort}{GEN x, GEN k}, as \kbd{sort}, but sorts the vector \kbd{x} in ascending \emph{lexicographic} order, according to the entries of the \typ{VECSMALL} \kbd{k}. For example, if $\kbd{k} = [2,1,3]$, sorting will be done with respect to the second component, and when these are equal, with respect to the first, and when these are equal, with respect to the third. \subsec{Indirect sorting} \fun{GEN}{indexsort}{GEN x} as \kbd{sort}, but only returns the permutation which, applied to \kbd{x}, would sort the vector. The result is a \typ{VECSMALL}. \fun{GEN}{indexlexsort}{GEN x}, as \kbd{indexsort}, using \kbd{lexcmp} instead of \kbd{gcmp} as the underlying comparison routine. \fun{GEN}{indexvecsort}{GEN x, GEN k}, as \kbd{vecsort}, but only returns the permutation that would sort the vector \kbd{x}. \fun{long}{vecindexmin}{GEN x} returns the index for a minimal element of $x$ (\typ{VEC}, \typ{COL} or \typ{VECSMALL}). \fun{long}{vecindexmax}{GEN x} returns the index for a maximal element of $x$ (\typ{VEC}, \typ{COL} or \typ{VECSMALL}). \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_shallow}{GEN x, void *data, int (*cmp)(void *,GEN,GEN)}, shallow variant of \kbd{gen\_sort}. \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 not \kbd{NULL}, it is set to the permutation that would sort the original \kbd{x}. \fun{GEN}{gen_setminus}{GEN A, GEN B, int (*cmp)(GEN,GEN)} given two sorted vectors $A$ and $B$, returns the vector of elements of $A$ not belonging to $B$. \fun{GEN}{sort_factor}{GEN y, void *data, int (*cmp)(void *,GEN,GEN)}: assuming \kbd{y} is a factorization matrix, sorts its rows in place (no copy is made) according to the comparison function \kbd{cmp} applied to its first column. \fun{GEN}{merge_sort_uniq}{GEN x,GEN y, void *data, int (*cmp)(void *,GEN,GEN)} assuming \kbd{x} and \kbd{y} are sorted vectors, with respect to the \kbd{cmp} comparison function, return a sorted concatenation, with duplicates removed. Shallow function. \fun{GEN}{setunion_i}{GEN x,GEN y} shallow version of \kbd{setunion}, a simple alias for \bprog merge_sort_uniq(x,y, (void*)cmp_universal, cmp_nodata) @eprog \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$. \fun{GEN}{ZM_merge_factor}{GEN fx, GEN fy} as \kbd{merge\_factor}, where \kbd{fx} and \kbd{fy} are factorization matrices of integers. \fun{long}{gen_search}{GEN v, GEN y, void *data, int (*cmp)(void*,GEN,GEN)}.\hfil\break Let $v$ be a vector sorted according to \kbd{cmp(data,a,b)}; look for an index $i$ such that $v[i]$ is equal to $y$. If $y$ is found, return $i$ (not necessarily the first occurence in case of multisets), else return $-i$ where $i$ is the index where $y$ should be inserted. \fun{long}{tablesearch}{GEN T, GEN x, int (*cmp)(GEN,GEN)} is a faster implementation for the common case \kbd{gen\_search(T,x,cmp,cmp\_nodata)} when we have no need to insert missing elements; return $0$ in case $x$ is not found. \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_Flx}{GEN x, GEN y} compare two \kbd{Flx}, which we assume have the same main variable (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}. \fun{int}{cmp_padic}{GEN x, GEN y} compare two \typ{PADIC} (for the same prime $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{Division} \fun{GEN}{gdivgu}{GEN x, ulong u} return $x/u)$. \fun{GEN}{gdivgunextu}{GEN x, ulong u} return $x/(u(u+1))$. If $u(u+1)$ does not fit into an \kbd{ulong}, it is created and left on the stack for efficiency. \fun{GEN}{divrunextu}{GEN x, ulong i} as \kbd{gdivgunextu} for a \typ{REAL}~$x$. \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}, as per the \kbd{\bs} GP operator. \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}, as per the \kbd{\%} GP operator. A \typ{REAL} or \typ{FRAC} \kbd{y} is also allowed, in which case the remainder is the unique real $r$ such that $0 \leq r < |\kbd{y}|$ and $\kbd{y} = q\kbd{x} + r$ for some (in fact unique) integer $q$. \fun{GEN}{gmodsg}{long s, GEN y[, GEN z]} as \kbd{gmod}, except \kbd{x} is a \kbd{long}. \fun{GEN}{gmodgs}{GEN x, long s[, GEN z]} as \kbd{gmod}, except \kbd{y} is a \kbd{long}. \fun{GEN}{gdivmod}{GEN x, GEN y, GEN *r} If \kbd{r} is not equal to \kbd{NULL} or \kbd{ONLY\_REM}, creates the (false) Euclidean quotient of \kbd{x} and~\kbd{y}, and puts (the address of) the remainder into~\kbd{*r}. If \kbd{r} is equal to \kbd{NULL}, do not create the remainder, and if \kbd{r} is equal to \kbd{ONLY\_REM}, create and output only the remainder. The remainder is created after the quotient and can be disposed of individually with a \kbd{cgiv(r)}. \fun{GEN}{poldivrem}{GEN x, GEN y, GEN *r} same as \key{gdivmod} but specifically for \typ{POL}s~\kbd{x} and~\kbd{y}, not necessarily in the same variable. Either of \kbd{x} and \kbd{y} may also be scalars, treated as polynomials of degree $0$. \fun{GEN}{gdeuc}{GEN x, GEN y} creates the Euclidean quotient of the \typ{POL}s~\kbd{x} and~\kbd{y}. Either of \kbd{x} and \kbd{y} may also be scalars, treated as polynomials of degree $0$. \fun{GEN}{grem}{GEN x, GEN y} creates the Euclidean remainder of the \typ{POL}~\kbd{x} divided by the \typ{POL}~\kbd{y}. Either of \kbd{x} and \kbd{y} may also be scalars, treated as polynomials of degree $0$. \fun{GEN}{gdivround}{GEN x, GEN y} if \kbd{x} and \kbd{y} are real (\typ{INT}, \typ{REAL}, \typ{FRAC}), return the rounded Euclidean quotient of $x$ and $y$ as per the \kbd{\bs/} GP operator. Operate componentwise if \kbd{x} is a \typ{COL}, \typ{VEC} or \typ{MAT}. Otherwise as \key{gdivent}. \fun{GEN}{centermod_i}{GEN x, GEN y, GEN y2}, as \kbd{centermodii}, componentwise. \fun{GEN}{centermod}{GEN x, GEN y}, as \kbd{centermod\_i}, except that \kbd{y2} is computed (and left on the stack for efficiency). \fun{GEN}{ginvmod}{GEN x, GEN y} creates the inverse of \kbd{x} modulo \kbd{y} when it exists. \kbd{y} must be of type \typ{INT} (in which case \kbd{x} is of type \typ{INT}) or \typ{POL} (in which case \kbd{x} is either a scalar type or a \typ{POL}). \section{GCD, content and primitive part} \subsec{Generic} \fun{GEN}{resultant}{GEN x, GEN y} creates the resultant of the \typ{POL}s \kbd{x} and~\kbd{y} computed using Sylvester's matrix (inexact inputs), a modular algorithm (inputs in $\Q[X]$) or the subresultant algorithm, as optimized by Lazard and Ducos. Either of \kbd{x} and \kbd{y} may also be scalars (treated as polynomials of degree $0$) \fun{GEN}{ggcd}{GEN x, GEN y} creates the GCD of \kbd{x} and~\kbd{y}. \fun{GEN}{glcm}{GEN x, GEN y} creates the LCM of \kbd{x} and~\kbd{y}. \fun{GEN}{gbezout}{GEN x,GEN y, GEN *u,GEN *v} returns the GCD of \kbd{x} and~\kbd{y}, and puts (the addresses of) objects $u$ and~$v$ such that $u\kbd{x}+v\kbd{y}=\gcd(\kbd{x},\kbd{y})$ into \kbd{*u} and~\kbd{*v}. \fun{GEN}{subresext}{GEN x, GEN y, GEN *U, GEN *V} returns the resultant of \kbd{x} and~\kbd{y}, and puts (the addresses of) polynomials $u$ and~$v$ such that $u\kbd{x}+v\kbd{y}=\text{Res}(\kbd{x},\kbd{y})$ into \kbd{*U} and~\kbd{*V}. \fun{GEN}{content}{GEN x} returns the GCD of all the components of~\kbd{x}. \fun{GEN}{primitive_part}{GEN x, GEN *c} sets \kbd{c} to \kbd{content(x)} and returns the primitive part \kbd{x} / \kbd{c}. A trivial content is set to \kbd{NULL}. \fun{GEN}{primpart}{GEN x} as above but the content is lost. (For efficiency, the content remains on the stack.) \fun{GEN}{denom_i}{GEN x} shallow version of \kbd{denom}. \fun{GEN}{numer_i}{GEN x} shallow version of \kbd{numer}. \subsec{Over the rationals} \fun{long}{Q_pval}{GEN x, GEN p} valuation at the \typ{INT} \kbd{p} of the \typ{INT} or \typ{FRAC}~\kbd{x}. \fun{long}{Q_lval}{GEN x, ulong p} same for \kbd{ulong} $p$. \fun{long}{Q_pvalrem}{GEN x, GEN p, GEN *r} returns the valuation $e$ at the \typ{INT} \kbd{p} of the \typ{INT} or \typ{FRAC}~\kbd{x}. The quotient $\kbd{x}/\kbd{p}^{e}$ is returned in~\kbd{*r}. \fun{long}{Q_lvalrem}{GEN x, ulong p, GEN *r} same for \kbd{ulong} $p$. \fun{GEN}{Q_abs}{GEN x} absolute value of the \typ{INT} or \typ{FRAC}~\kbd{x}. \fun{GEN}{Qdivii}{GEN x, GEN y}, assuming $x$ and $y$ are both of type \typ{INT}, return the quotient $x/y$ as a \typ{INT} or \typ{FRAC}; marginally faster than \kbd{gdiv}. \fun{GEN}{Qdivis}{GEN x, long y}, assuming $x$ is an \typ{INT}, return the quotient $x/y$ as a \typ{INT} or \typ{FRAC}; marginally faster than \kbd{gdiv}. \fun{GEN}{Qdiviu}{GEN x, ulong y}, assuming $x$ is an \typ{INT}, return the quotient $x/y$ as a \typ{INT} or \typ{FRAC}; marginally faster than \kbd{gdiv}. \fun{GEN}{Q_abs_shallow}{GEN x} $x$ being a \typ{INT} or a \typ{FRAC}, returns a shallow copy of $|x|$, in particular returns $x$ itself when $x \geq 0$, and \kbd{gneg($x$)} otherwise. \fun{GEN}{Q_gcd}{GEN x, GEN y} gcd of the \typ{INT} or \typ{FRAC}~\kbd{x} and~\kbd{y}. \smallskip In the following functions, arguments belong to a $M\otimes_\Z\Q$ for some natural $\Z$-module $M$, e.g. multivariate polynomials with integer coefficients (or vectors/matrices recursively built from such objects), and an element of $M$ is said to be \emph{integral}. We are interested in contents, denominators, etc. with respect to this canonical integral structure; in particular, contents belong to $\Q$, denominators to $\Z$. For instance the $\Q$-content of $(1/2)xy$ is $(1/2)$, and its $\Q$-denominator is $2$, whereas \kbd{content} would return $y/2$ and \kbd{denom}~1. \fun{GEN}{Q_content}{GEN x} the $\Q$-content of $x$. \fun{GEN}{Z_content}{GEN x} as \kbd{Q\_content} but assume that all rationals are in fact \typ{INT}s and return \kbd{NULL} when the content is $1$. This function returns as soon as the content is found to equal $1$. \fun{GEN}{Q_content_safe}{GEN x} as \kbd{Q\_content}, returning \kbd{NULL} when the $\Q$-content is not defined (e.g. for a \typ{REAL} or \typ{INTMOD} component). \fun{GEN}{Q_denom}{GEN x} the $\Q$-denominator of $x$. Shallow function. Raises en \kbd{e\_TYPE} error out when the notion is meaningless, e.g. for a \typ{REAL} or \typ{INTMOD} component. \fun{GEN}{Q_denom_safe}{GEN x} the $\Q$-denominator of $x$. Shallow function. Return \kbd{NULL} when the notion is meaningless. \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}{vec_Q_primpart}{GEN x} as above component-wise. Applied to a \typ{MAT}, the result has primitive columns. \fun{GEN}{row_Q_primpart}{GEN x} as above, applied to the rows of a \typ{MAT}, so that the result has primitive rows. Not \kbd{gerepile}-safe. \fun{GEN}{Q_remove_denom}{GEN x, GEN *ptd} sets \kbd{d} to the $\Q$-denominator of \kbd{x} and returns \kbd{x * d}, which is integral. Shallow function. \fun{GEN}{Q_div_to_int}{GEN x, GEN c} returns \kbd{x / c}, assuming $c$ is a rational number (\typ{INT} or \typ{FRAC}) and the result is integral. \fun{GEN}{Q_mul_to_int}{GEN x, GEN c} returns \kbd{x * c}, assuming $c$ is a rational number (\typ{INT} or \typ{FRAC}) and the result is integral. \fun{GEN}{Q_muli_to_int}{GEN x, GEN d} returns \kbd{x * c}, assuming $c$ is a \typ{INT} and the result is integral. \fun{GEN}{mul_content}{GEN cx, GEN cy} \kbd{cx} and \kbd{cy} are as set by \kbd{primitive\_part}: either a \kbd{GEN} or \kbd{NULL} representing the trivial content $1$. Returns their product (either a \kbd{GEN} or \kbd{NULL}). \fun{GEN}{div_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 quotient (either a \kbd{GEN} or \kbd{NULL}). \fun{GEN}{inv_content}{GEN c} $c$ is as set by \kbd{primitive\_part}: either a \kbd{GEN} or \kbd{NULL} representing the trivial content $1$. Returns its inverse (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 gu}{GEN x, ulong u} \funno{GEN}{g\op sg}{long s, GEN y} \funno{GEN}{g\op ug}{ulong u, GEN y} \noindent Explicitly \fun{GEN}{gadd}{GEN x, GEN y}, \fun{GEN}{gaddgs}{GEN x, long s}, \fun{GEN}{gaddsg}{long s, GEN x} \fun{GEN}{gmul}{GEN x, GEN y}, \fun{GEN}{gmulgs}{GEN x, long s}, \fun{GEN}{gmulsg}{long s, GEN x}, \fun{GEN}{gmulgu}{GEN x, ulong u}, \fun{GEN}{gmulug}{GEN x, ulong u}, \fun{GEN}{gsub}{GEN x, GEN y}, \fun{GEN}{gsubgs}{GEN x, long s}, \fun{GEN}{gsubsg}{long s, GEN x} \fun{GEN}{gdiv}{GEN x, GEN y}, \fun{GEN}{gdivgs}{GEN x, long s}, \fun{GEN}{gdivsg}{long s, GEN x}, \fun{GEN}{gdivgu}{GEN x, ulong u}, \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{qfb\_1}$(x)$ for \typ{QFB}. \item the identity permutation for \typ{VECSMALL}. \item \kbd{Rg\_get\_1}$(x)$ otherwise 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)}. \fun{GEN}{gpowers}{GEN x, long n} returns the vector $[1,x,\dots,x^n]$. \fun{GEN}{grootsof1}{long n, long prec} returns the vector $[1,x,\dots,x^{n-1}]$, where $x$ is the $n$-th root of unity $\exp(2i\pi/n)$. \fun{GEN}{gsqrpowers}{GEN x, long n} returns the vector $[x,x^4,\dots,x^{n^2}]$. 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} To describe the following functions, we use the following private typedefs to simplify the description: \bprog typedef (*F0)(void *); typedef (*F1)(void *, GEN); typedef (*F2)(void *, GEN, GEN); @eprog \noindent They correspond to generic functions with one and two arguments respectively (the \kbd{void*} argument provides some arbitrary evaluation context). \fun{GEN}{gen_product}{GEN v, void *D, F2 op} 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$. Use divide and conquer strategy. Leave some garbage on stack, but suitable for \kbd{gerepileupto} if \kbd{mul} is. \fun{GEN}{gen_pow}{GEN x, GEN n, void *D, F1 sqr, F2 mul} $n > 0$ a \typ{INT}, returns $x^n$; \kbd{mul(D, $x$, $y$)} implements the multiplication in the underlying monoid; \kbd{sqr} is a (presumably optimized) shortcut for \kbd{mul(D, $x$, $x$)}. \fun{GEN}{gen_powu}{GEN x, ulong n, void *D, F1 sqr, F2 mul} $n > 0$, returns $x^n$. See \tet{gen_pow}. \fun{GEN}{gen_pow_i}{GEN x, GEN n, void *E, F1 sqr, F2 mul} internal variant of \tet{gen_pow}, not memory-clean. \fun{GEN}{gen_powu_i}{GEN x, ulong n, void *E, F1 sqr, F2 mul} internal variant of \tet{gen_powu}, not memory-clean. \fun{GEN}{gen_pow_fold}{GEN x, GEN n, void *D, F1 sqr, F1 msqr} variant of \tet{gen_pow}, where \kbd{mul} is replaced by \kbd{msqr}, with \kbd{msqr(D, $y$)} returning $xy^2$. In particular \kbd{D} must implicitly contain $x$. \fun{GEN}{gen_pow_fold_i}{GEN x, GEN n, void *E, F1 sqr, F1 msqr} internal variant of the function \tet{gen_pow_fold}, not memory-clean. \fun{GEN}{gen_powu_fold}{GEN x, ulong n, void *D, F1 sqr, F1 msqr}, see \tet{gen_pow_fold}. \fun{GEN}{gen_powu_fold_i}{GEN x, ulong n, void *E, F1 sqr, F1 msqr} see \tet{gen_pow_fold_i}. \fun{GEN}{gen_pow_init}{GEN x, GEN n, long k, void *E, GEN (*sqr)(void*,GEN), GEN (*mul)(void*,GEN,GEN)} Return a table \kbd{R} that can be used with \kbd{gen\_pow\_table} to compute the powers of $x$ up to $n$. The table is of size $2^k\*\log_2(n)$. \fun{GEN}{gen_pow_table}{GEN R, GEN n, void *E, GEN (*one)(void*), GEN (*mul)(void*,GEN,GEN)} Return $x^n$, where $R$ is as given by \kbd{gen\_pow\_init(x,m,k,E,sqr,mul)} for some integer $m\geq n$. \fun{GEN}{gen_powers}{GEN x, long n, long usesqr, void *D, F1 sqr, F2 mul, F0 one} returns $[\kbd{x}^0, \dots, \kbd{x}^\kbd{n}]$ as a \typ{VEC}; \kbd{mul(D, $x$, $y$)} implements the multiplication in the underlying monoid; \kbd{sqr} is a (presumably optimized) shortcut for \kbd{mul(D, $x$, $x$)}; \kbd{one} returns the monoid unit. The flag \kbd{usesqr} should be set to $1$ if squaring are faster than multiplication by $x$. \fun{GEN}{gen_factorback}{GEN L, GEN e, void *D, F2 mul, F2 pow, GEN (*one)(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 (a \kbd{ZV} or \kbd{zv}): 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. \noindent \kbd{one(D)} returns the neutral element. If \kbd{one} is \kbd{NULL}, \kbd{gen\_1} is used instead. \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 usual $L^1$ norm. One must include a real precision \kbd{prec} in case the inputs include \typ{COMPLEX} or \typ{QUAD} with exact rational components: a square root must be computed and we must choose an accuracy. \fun{GEN}{gnorml1_fake}{GEN x} as \tet{gnorml1}, except that the norm of a \typ{QUAD} $x + wy$ or \typ{COMPLEX} $x + Iy$ is defined as $|x| + |y|$, where we use the ordinary real absolute value. This is still a norm of $\R$ vector spaces, which is easier to compute than \kbd{gnorml1} and can often be used in its place. \fun{GEN}{gsupnorm}{GEN x, long prec} The norm of a scalar is its complex modulus, the norm of a recursive type is the max of the norms of its components. A precision \kbd{prec} must be included for the same reason as in \kbd{gnorml1}. \fun{void}{gsupnorm_aux}{GEN x, GEN *m, GEN *m2, long prec} is the 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_cxeval}{GEN T, GEN x, GEN xi} evaluate the \typ{POL} $T$ at $x$ via Horner's scheme. If \var{xi} is not \kbd{NULL} it must be equal to $1/x$ and we evaluate $x^{\deg T}T(1/x)$ instead. This is useful when $|x| > 1$ is a \typ{REAL} or an inexact \typ{COMPLEX} and $T$ has ``balanced'' coefficients, since the evaluation becomes numerically stable. \fun{GEN}{RgXY_cxevalx}{GEN T, GEN x, GEN xi} Apply \kbd{RgX\_cxeval} to all the polynomials coefficients of $T$. \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}{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 attached 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_RgM_apply}{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_ZM_apply}{GEN q, GEN M} as above assuming that both $q$ and $M$ have integer entries. \newpage \chapter{Miscellaneous mathematical functions} \section{Fractions} \fun{GEN}{absfrac}{GEN x} returns the absolute value of the \typ{FRAC} $x$. \fun{GEN}{absfrac_shallow}{GEN x} $x$ being a \typ{FRAC}, returns a shallow copy of $|x|$, in particular returns $x$ itself when $x \geq 0$, and \kbd{gneg($x$)} otherwise. \fun{GEN}{sqrfrac}{GEN x} returns the square of the \typ{FRAC} $x$. \section{Binomials} \fun{GEN}{binomial}{GEN x, long k} \fun{GEN}{binomialuu}{ulong n, ulong k} \fun{GEN}{vecbinomial}{long n}, which returns a vector $v$ with $n+1$ \typ{INT} components such that $v[k+1] = \kbd{binomial}(n,k)$ for $k$ from $0$ up to $n$. \section{Real numbers} \fun{GEN}{R_abs}{GEN x} $x$ being a \typ{INT}, a \typ{REAL} or a \typ{FRAC}, returns $|x|$. \fun{GEN}{R_abs_shallow}{GEN x} $x$ being a \typ{INT}, a \typ{REAL} or a \typ{FRAC}, returns a shallow copy of $|x|$, in particular returns $x$ itself when $x \geq 0$, and \kbd{gneg($x$)} otherwise. \fun{GEN}{modRr_safe}{GEN x, GEN y} let $x$ be a \typ{INT}, a \typ{REAL} or \typ{FRAC} and let $y$ be a \typ{REAL}. Return $x\% y$ unless the input accuracy is unsufficient to compute the floor or $x/y$ in which case we return \kbd{NULL}. \fun{GEN}{modRr_i}{GEN x, GEN y, GEN iy} let $x$ be a \typ{INT}, a \typ{REAL} or \typ{FRAC} and let $y$ be a \typ{REAL} and $\var{iy} = \kbd{invr}(y)$. Return $x\% y$ unless the input accuracy is unsufficient to compute the floor or $x/y$ in which case we return \kbd{NULL}. \section{Complex numbers} \fun{GEN}{gimag}{GEN x} returns a copy of the imaginary part of \kbd{x}. \fun{GEN}{greal}{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)$. \fun{GEN}{gconj}{GEN x} returns $\kbd{greal}(x) - 2\kbd{gimag}(x)$, which is the ordinary complex conjugate except for a real \typ{QUAD}. \fun{GEN}{imag_i}{GEN x}, shallow variant of \kbd{gimag}. \fun{GEN}{real_i}{GEN x}, shallow variant of \kbd{greal}. \fun{GEN}{conj_i}{GEN x}, shallow variant of \kbd{gconj}. \fun{GEN}{mulreal}{GEN x, GEN y} returns the real part of $x\*y$; $x$, $y$ have type \typ{INT}, \typ{FRAC}, \typ{REAL} or \typ{COMPLEX}. See also \kbd{RgM\_mulreal}. \fun{GEN}{cxnorm}{GEN x} norm of the \typ{COMPLEX} $x$ (modulus squared). \fun{GEN}{cxexpm1}{GEN x} returns $\exp(x)-1$, for a \typ{COMPLEX} $x$. \fun{int}{cx_approx_equal}{GEN a, GEN b} test whether (\typ{INT}, \typ{FRAC}, \typ{REAL}, or \typ{COMPLEX} of those) $a$ and $b$ are approximately equal. This returns $1$ if and only if the division by $a-b$ would produce a division by $0$ (which is a less stringent test than testing whether $a-b$ evaluates to $0$). \fun{int}{cx_approx0}{GEN a, GEN b} test whether (\typ{INT}, \typ{FRAC}, \typ{REAL}, or \typ{COMPLEX} of those) $a$ is approximately $0$, where $b$ is a reference point. A non-$0$ \typ{REAL} component $x$ is approximately $0$ if $$\kbd{exponent}(b) - \kbd{exponent}(x) > \kbd{bit\_prec(x)}\;.$$ \section{Quadratic numbers and binary quadratic forms} \fun{GEN}{quad_disc}{GEN x} returns the discriminant of the \typ{QUAD} $x$. Not stack-clean but suitable for \kbd{gerepileupto}. \fun{GEN}{quadnorm}{GEN x} norm of the \typ{QUAD} $x$. \fun{GEN}{qfb_disc}{GEN x} returns the discriminant of the \typ{QFB} \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. \fun{GEN}{qfb_ZM_apply}{GEN q, GEN g} returns $q \circ g$. \fun{GEN}{qfbforms}{GEN D} given a discriminant $D < 0$, return the list of reduced forms of discriminant $D$ as \typ{VECSMALL} with 3 components. The primitive forms in the list enumerate the class group of the quadratic order of discriminant $D$; if $D$ is fundamental, all returned forms are automatically primitive. \section{Polynomials}\label{se:polynomials} \fun{GEN}{truecoef}{GEN x, long n} returns \kbd{polcoef(x,n, -1)}, i.e. the coefficient of the term of degree \kbd{n} in the main variable. This is a safe but expensive function that must \emph{copy} its return value so that it be \kbd{gerepile}-safe. Use \kbd{polcoef\_i} for a fast internal variant. \fun{GEN}{polcoef_i}{GEN x, long n, long v} internal shallow function. Rewrite $x$ as a Laurent polynomial in the variable $v$ and returns its coefficient of degree $n$ (\kbd{gen\_0} if this falls outside the coefficient array). Allow \typ{POL}, \typ{SER}, \typ{RFRAC} and scalars. \fun{long}{degree}{GEN x} returns \kbd{poldegree(x, -1)}, the degree of \kbd{x} with respect to its main variable, with the usual meaning if the leading coefficient of $x$ is nonzero. If the sign of $x$ is $0$, this function always returns $-1$. Otherwise, we return the index of the leading coefficient of $x$, i.e. the coefficient of largest index stored in $x$. For instance the ``degrees'' of \bprog 0. E-38 * x^4 + 0.E-19 * x + 1 Mod(0,2) * x^0 \\ sign is 0 ! @eprog\noindent are $4$ and $-1$ respectively. \fun{long}{degpol}{GEN x} is a simple macro returning \kbd{lg(x) - 3}. This is the degree of the \typ{POL}~\kbd{x} with respect to its main variable, \emph{if} its leading coefficient is nonzero (a rational $0$ is impossible, but an inexact $0$ is allowed, as well as an exact modular $0$, e.g. \kbd{Mod(0,2)}). If $x$ has no coefficients (rational $0$ polynomial), its length is $2$ and we return the expected $-1$. \fun{GEN}{characteristic}{GEN x} returns the characteristic of the base ring over which the polynomial is defined (as defined by \typ{INTMOD} and \typ{FFELT} components). The function raises an exception if incompatible primes arise from \typ{FFELT} and \typ{PADIC} components. Shallow function. \fun{GEN}{residual_characteristic}{GEN x} returns a kind of ``residual characteristic'' of the base ring over which the polynomial is defined. This is defined as the gcd of all moduli \typ{INTMOD}s occurring in the structure, as well as primes $p$ arising from \typ{PADIC}s or \typ{FFELT}s. The function raises an exception if incompatible primes arise from \typ{FFELT} and \typ{PADIC} components. Shallow function. \fun{GEN}{resultant}{GEN x,GEN y} resultant of \kbd{x} and \kbd{y}, with respect to the main variable of highest priority. Uses either the subresultant algorithm (generic case), a modular algorithm (inputs in $\Q[X]$) or Sylvester's matrix (inexact inputs). \fun{GEN}{resultant2}{GEN x, GEN y} resultant of \kbd{x} and \kbd{y}, with respect to the main variable of highest priority. Computes the determinant of Sylvester's matrix. \fun{GEN}{cleanroots}{GEN x, long prec} returns the complex roots of the complex polynomial $x$ (with coefficients \typ{INT}, \typ{FRAC}, \typ{REAL} or \typ{COMPLEX} of the above). The roots are returned as \typ{REAL} or \typ{COMPLEX} of \typ{REAL}s of precision \kbd{prec} (guaranteeing a nonzero imaginary part). See \tet{QX_complex_roots}. \fun{double}{fujiwara_bound}{GEN x} return a quick upper bound for the logarithm in base $2$ of the modulus of the largest complex roots of the polynomial $x$ (complex coefficients). \fun{double}{fujiwara_bound_real}{GEN x, long sign} return a quick upper bound for the logarithm in base $2$ of the absolute value of the largest real root of sign \var{sign} ($1$ or $-1$), for the polynomial $x$ (real coefficients). \fun{GEN}{polmod_to_embed}{GEN x, long prec} return the vector of complex embeddings of the \typ{POLMOD} $x$ (with complex coefficients). Shallow function, simple complex variant of \tet{conjvec}. \fun{GEN}{pollegendre_reduced}{long n, long v} let $P_n(t)\in \Q[t]$ be the $n$-th Legendre polynomial in variable $v$. Return $p\in \Z[t]$ such that $2^n P_n(t) = p(t^2)$ ($n$ even) or $t p(t^2)$ ($n$ odd). \section{Power series} \fun{GEN}{sertoser}{GEN x, long prec} return the \typ{SER} $x$ truncated or extended (with zeros) to \kbd{prec} terms. Shallow function, assume that $\kbd{prec} \geq 0$. \fun{GEN}{derivser}{GEN x} returns the derivative of the \typ{SER} \kbd{x} with respect to its main variable. \fun{GEN}{integser}{GEN x} returns the primitive of the \typ{SER} \kbd{x} with respect to its main variable. \fun{GEN}{truecoef}{GEN x, long n} returns \kbd{polcoef(x,n, -1)}, i.e. the coefficient of the term of degree \kbd{n} in the main variable. This is a safe but expensive function that must \emph{copy} its return value so that it be \kbd{gerepile}-safe. Use \kbd{polcoef\_i} for a fast internal variant. \fun{GEN}{ser_unscale}{GEN P, GEN h} return $P(h x)$, not memory clean. \fun{GEN}{ser_normalize}{GEN x} divide $x$ by its ``leading term'' so that the series is either $0$ or equal to $t^v(1+O(t))$. Shallow function if the ``leading term'' is $1$. \fun{int}{ser_isexactzero}{GEN x} return $1$ if $x$ is a zero series, all of whose known coefficients are exact zeroes; this implies that $\kbd{sign}(x) = 0$ and $\kbd{lg}(x) \leq 3$. \fun{GEN}{ser_inv}{GEN x} return the inverse of the \typ{SER} $x$ using Newton iteration. \fun{GEN}{psi1series}{long n, long v, long prec} creates the \typ{SER} $\psi(1 + x + O(x^n))$ in variable $v$. \section{Functions to handle \typ{FFELT}} These functions define the public interface of the \typ{FFELT} type to use in generic functions. However, in specific functions, it is better to use the functions class \kbd{FpXQ} and/or \kbd{Flxq} as appropriate. \fun{GEN}{FF_p}{GEN a} returns the characteristic of the definition field of the \typ{FFELT} element \kbd{a}. \fun{long}{FF_f}{GEN a} returns the dimension of the definition field over its prime field; the cardinality of the dimension field is thus $p^f$. \fun{GEN}{FF_p_i}{GEN a} shallow version of \kbd{FF\_p}. \fun{GEN}{FF_q}{GEN a} returns the cardinality of the definition field of the \typ{FFELT} element \kbd{a}. \fun{GEN}{FF_mod}{GEN a} returns the polynomial (with reduced \typ{INT} coefficients) defining the finite field, in the variable used to display $a$. \fun{long}{FF_var}{GEN a} returns the variable used to display $a$. \fun{GEN}{FF_gen}{GEN a} returns the standard generator of the definition field of the \typ{FFELT} element \kbd{a}, see \kbd{ffgen}, that is $x\pmod{T}$ where $T$ is the polynomial over the prime field that define the finite field. \fun{GEN}{FF_to_FpXQ}{GEN a} converts the \typ{FFELT} \kbd{a} to a polynomial $P$ with reduced \typ{INT} coefficients such that $a=P(g)$ where $g$ is the generator of the finite field returned by \kbd{ffgen}, in the variable used to display $g$. \fun{GEN}{FF_to_FpXQ_i}{GEN a} shallow version of \kbd{FF\_to\_FpXQ}. \fun{GEN}{FF_to_F2xq}{GEN a} converts the \typ{FFELT} \kbd{a} to a \kbd{F2x} $P$ such that $a=P(g)$ where $g$ is the generator of the finite field returned by \kbd{ffgen}, in the variable used to display $g$. This only work if the characteristic is $2$. \fun{GEN}{FF_to_F2xq_i}{GEN a} shallow version of \kbd{FF\_to\_F2xq}. \fun{GEN}{FF_to_Flxq}{GEN a} converts the \typ{FFELT} \kbd{a} to a \kbd{Flx} $P$ such that $a=P(g)$ where $g$ is the generator of the finite field returned by \kbd{ffgen}, in the variable used to display $g$. This only work if the characteristic is small enough. \fun{GEN}{FF_to_Flxq_i}{GEN a} shallow version of \kbd{FF\_to\_Flxq}. \fun{GEN}{p_to_FF}{GEN p, long v} returns a \typ{FFELT} equal to $1$ in the finite field $\Z/p\Z$. Useful for generic code that wants to handle (inefficiently) $\Z/p\Z$ as if it were not a prime field. \fun{GEN}{Tp_to_FF}{GEN T, GEN p} returns a \typ{FFELT} equal to $1$ in the finite field $\F_p/(T)$, where $T$ is a \kbd{ZX}, assumed to be irreducible modulo $p$, or \kbd{NULL} in which case the routine acts as \tet{p_to_FF(p,0)}. No checks. \fun{GEN}{Fq_to_FF}{GEN x, GEN ff} returns a \typ{FFELT} equal to $x$ in the finite field defined by the \typ{FFELT} \kbd{ff}, where $x$ is an \kbd{Fq} (either a \typ{INT} or a \kbd{ZX}: a \typ{POL} with \typ{INT} coefficients). No checks. \fun{GEN}{FqX_to_FFX}{GEN x, GEN ff} given an \kbd{FqX} $x$, return the polynomial with \typ{FFELT} coefficients obtained by applying \tet{Fq_to_FF} coefficientwise. No checks, and no normalization if the leading coefficient maps to $0$. \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} returns $1$ if the \typ{FFELT} \kbd{a} is equal to $0$ else returns $0$. \fun{int}{FF_equal1}{GEN a} returns $1$ if the \typ{FFELT} \kbd{a} is equal to $1$ else returns $0$. \fun{int}{FF_equalm1}{GEN a} returns $-1$ if the \typ{FFELT} \kbd{a} is equal to $1$ else returns $0$. \fun{int}{FF_equal}{GEN a, GEN b} return $1$ if the \typ{FFELT} \kbd{a} and \kbd{b} have the same definition field and are equal, else $0$. \fun{int}{FF_samefield}{GEN a, GEN b} return $1$ if the \typ{FFELT} \kbd{a} and \kbd{b} have the same definition field, else $0$. \fun{int}{Rg_is_FF}{GEN c, GEN *ff} to be called successively on many objects, setting \kbd{*ff = NULL} (unset) initially. Returns $1$ as long as $c$ is a \typ{FFELT} defined over the same field as \kbd{*ff} (setting \kbd{*ff = c} if unset), and $0$ otherwise. \fun{int}{RgC_is_FFC}{GEN x, GEN *ff} apply \tet{Rg_is_FF} successively to all components of the \typ{VEC} or \typ{COL} $x$. Return $0$ if one call fails, and $1$ otherwise. \fun{int}{RgM_is_FFM}{GEN x, GEN *ff} apply \tet{Rg_is_FF} to all components of the \typ{MAT}. Return $0$ if one call fails, and $1$ otherwise. \fun{GEN}{FF_add}{GEN a, GEN b} returns $a+b$ where \kbd{a} and \kbd{b} are \typ{FFELT} having the same definition field. \fun{GEN}{FF_Z_add}{GEN a, GEN x} returns $a+x$, where \kbd{a} is a \typ{FFELT}, and \kbd{x} is a \typ{INT}, the computation being performed in the definition field of \kbd{a}. \fun{GEN}{FF_Q_add}{GEN a, GEN x} returns $a+x$, where \kbd{a} is a \typ{FFELT}, and \kbd{x} is a \typ{RFRAC}, the computation being performed in the definition field of \kbd{a}. \fun{GEN}{FF_sub}{GEN a, GEN b} returns $a-b$ where \kbd{a} and \kbd{b} are \typ{FFELT} having the same definition field. \fun{GEN}{FF_mul}{GEN a, GEN b} returns $a\*b$ where \kbd{a} and \kbd{b} are \typ{FFELT} having the same definition field. \fun{GEN}{FF_Z_mul}{GEN a, GEN b} returns $a\*b$, where \kbd{a} is a \typ{FFELT}, and \kbd{b} is a \typ{INT}, the computation being performed in the definition field of \kbd{a}. \fun{GEN}{FF_div}{GEN a, GEN b} returns $a/b$ where \kbd{a} and \kbd{b} are \typ{FFELT} having the same definition field. \fun{GEN}{FF_neg}{GEN a} returns $-a$ where \kbd{a} is a \typ{FFELT}. \fun{GEN}{FF_neg_i}{GEN a} shallow function returning $-a$ where \kbd{a} is a \typ{FFELT}. \fun{GEN}{FF_inv}{GEN a} returns $a^{-1}$ where \kbd{a} is a \typ{FFELT}. \fun{GEN}{FF_sqr}{GEN a} returns $a^2$ where \kbd{a} is a \typ{FFELT}. \fun{GEN}{FF_mul2n}{GEN a, long n} returns $a\*2^n$ where \kbd{a} is a \typ{FFELT}. \fun{GEN}{FF_pow}{GEN a, GEN n} returns $a^n$ where \kbd{a} is a \typ{FFELT} and \kbd{n} is a \typ{INT}. \fun{GEN}{FF_Frobenius}{GEN a, GEN n} returns $x^{p^n}$ where \kbd{x} is the standard generator of the definition field of the \typ{FFELT} element \kbd{a}, \typ{FFELT}, \kbd{n} is a \typ{INT}, and $p$ is the characteristic of the definition field of $a$. \fun{GEN}{FF_Z_Z_muldiv}{GEN a, GEN x, GEN y} returns $a\*y/z$, where \kbd{a} is a \typ{FFELT}, and \kbd{x} and \kbd{y} are \typ{INT}, the computation being performed in the definition field of \kbd{a}. \fun{GEN}{Z_FF_div}{GEN x, GEN a} return $x/a$ where \kbd{a} is a \typ{FFELT}, and \kbd{x} is a \typ{INT}, the computation being performed in the definition field of \kbd{a}. \fun{GEN}{FF_norm}{GEN a} returns the norm of the \typ{FFELT} \kbd{a} with respect to its definition field. \fun{GEN}{FF_trace}{GEN a} returns the trace of the \typ{FFELT} \kbd{a} with respect to its definition field. \fun{GEN}{FF_conjvec}{GEN a} returns the vector of conjugates $[a,a^p,a^{p^2},\ldots,a^{p^{n-1}}]$ where the \typ{FFELT} \kbd{a} belong to a field with $p^n$ elements. \fun{GEN}{FF_charpoly}{GEN a} returns the characteristic polynomial) of the \typ{FFELT} \kbd{a} with respect to its definition field. \fun{GEN}{FF_minpoly}{GEN a} returns the minimal polynomial of the \typ{FFELT} \kbd{a}. \fun{GEN}{FF_sqrt}{GEN a} returns an \typ{FFELT} $b$ such that $a=b^2$ if it exist, where \kbd{a} is a \typ{FFELT}. \fun{long}{FF_issquareall}{GEN x, GEN *pt} returns $1$ if \kbd{x} is a square, and $0$ otherwise. If \kbd{x} is indeed a square, set \kbd{pt} to its square root. \fun{long}{FF_issquare}{GEN x} returns $1$ if \kbd{x} is a square and $0$ otherwise. \fun{long}{FF_ispower}{GEN x, GEN K, GEN *pt} Given $K$ a positive integer, returns $1$ if \kbd{x} is a $K$-th power, and $0$ otherwise. If \kbd{x} is indeed a $K$-th power, set \kbd{pt} to its $K$-th root. \fun{GEN}{FF_sqrtn}{GEN a, GEN n, GEN *zn} returns an \kbd{n}-th root of $\kbd{a}$ if it exist. If \kbd{zn} is non-\kbd{NULL} set it to a primitive \kbd{n}-th root of the unity. \fun{GEN}{FF_log}{GEN a, GEN g, GEN o} the \typ{FFELT} \kbd{g} being a generator for the definition field of the \typ{FFELT} \kbd{a}, returns a \typ{INT} $e$ such that $a^e=g$. If $e$ does not exists, the result is currently undefined. If \kbd{o} is not \kbd{NULL} it is assumed to be a factorization of the multiplicative order of \kbd{g} (as set by \tet{FF_primroot}) \fun{GEN}{FF_order}{GEN a, GEN o} returns the order of the \typ{FFELT} \kbd{a}. If \kbd{o} is non-\kbd{NULL}, it is assumed that \kbd{o} is a multiple of the order of \kbd{a}. \fun{GEN}{FF_primroot}{GEN a, GEN *o} returns a generator of the multiplicative group of the definition field of the \typ{FFELT} \kbd{a}. If \kbd{o} is not \kbd{NULL}, set it to the factorization of the order of the primitive root (to speed up \tet{FF_log}). \fun{GEN}{FF_map}{GEN m, GEN a} returns $A(m)$ where \kbd{A=a.pol} assuming $a$ and $m$ belongs to fields having the same characteristic. \subsec{FFX} The functions in this sections take polynomial arguments and a \typ{FFELT} $a$. The coefficients of the polynomials must be of type \typ{INT}, \typ{INTMOD} or \typ{FFELT} and compatible with \kbd{a}. \fun{GEN}{FFX_add}{GEN P, GEN Q, GEN a} returns the sum of the polynomials \kbd{P} and \kbd{Q} defined over the definition field of the \typ{FFELT} \kbd{a}. \fun{GEN}{FFX_mul}{GEN P, GEN Q, GEN a} returns the product of the polynomials \kbd{P} and \kbd{Q} defined over the definition field of the \typ{FFELT} \kbd{a}. \fun{GEN}{FFX_sqr}{GEN P, GEN a} returns the square of the polynomial \kbd{P} defined over the definition field of the \typ{FFELT} \kbd{a}. \fun{GEN}{FFX_rem}{GEN P, GEN Q, GEN a} returns the remainder of the polynomial \kbd{P} modulo the polynomial \kbd{Q}, where \kbd{P} and \kbd{Q} are defined over the definition field of the \typ{FFELT} \kbd{a}. \fun{GEN}{FFX_gcd}{GEN P, GEN Q, GEN a} returns the GCD of the polynomials \kbd{P} and \kbd{Q} defined over the definition field of the \typ{FFELT} \kbd{a}. \fun{GEN}{FFX_extgcd}{GEN P, GEN Q, GEN a, GEN *U, GEN *V} returns the GCD of the polynomials \kbd{P} and \kbd{Q} defined over the definition field of the \typ{FFELT} \kbd{a} and sets \kbd{*U}, \kbd{*V} to the Bezout coefficients such that $\kbd{*UP} + \kbd{*VQ} = d$. If \kbd{*U} is set to \kbd{NULL}, it is not computed which is a bit faster. \fun{GEN}{FFX_halfgcd}{GEN x, GEN y, GEN a} returns a two-by-two matrix $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}{FFX_halfgcd_all}{GEN x, GEN y, GEN a, GEN *ptA, GEN *ptB} as \kbd{FFX\_halfgcd}, in addition, if \kbd{ptA} (resp. \kbd{ptB}) is not \kbd{NULL}, \kbd{*ptA} (resp. \kbd{*ptB}) is set to \kbd{A} (resp. \kbd{B}). \fun{GEN}{FFX_resultant}{GEN P, GEN Q, GEN a} returns the resultant of the polynomials \kbd{P} and \kbd{Q} where \kbd{P} and \kbd{Q} are defined over the definition field of the \typ{FFELT} \kbd{a}. \fun{GEN}{FFX_disc}{GEN P, GEN a} returns the discriminant of the polynomial \kbd{P} where \kbd{P} is defined over the definition field of the \typ{FFELT} \kbd{a}. \fun{GEN}{FFX_ispower}{GEN P, ulong k, GEN a, GEN *py} return $1$ if the \kbd{FFX} $P$ is a $k$-th power, $0$ otherwise, where \kbd{P} is defined over the definition field of the \typ{FFELT} \kbd{a}. If \kbd{py} is not \kbd{NULL}, set it to $g$ such that $g^k = f$. \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_factor_squarefree}{GEN f, GEN a} returns the squarefree factorization of the univariate polynomial \kbd{f} over the definition field of the \typ{FFELT} \kbd{a}. This is a vector $[u_1,\dots,u_k]$ of pairwise coprime \kbd{FFX} such that $u_k \neq 1$ and $f = \prod u_i^i$. \fun{GEN}{FFX_ddf}{GEN f, GEN a} assuming that $f$ is squarefree, returns the distinct degree factorization of $f$ modulo $p$. The returned value \kbd{v} is a \typ{VEC} with two components: \kbd{F=v[1]} is a vector of (\kbd{FFX}) factors, and \kbd{E=v[2]} is a \typ{VECSMALL}, such that $f$ is equal to the product of the \kbd{F[i]} and each \kbd{F[i]} is a product of irreducible factors of degree \kbd{E[i]}. \fun{GEN}{FFX_degfact}{GEN f, GEN a}, as \kbd{FFX\_factor}, but the degrees of the irreducible factors are returned instead of the factors themselves (as a \typ{VECSMALL}). \fun{GEN}{FFX_roots}{GEN f, GEN a} returns the roots (\typ{FFELT}) of the univariate polynomial \kbd{f} over the definition field of the \typ{FFELT} \kbd{a}. The coefficients of \kbd{f} must be of type \typ{INT}, \typ{INTMOD} or \typ{FFELT} and compatible with \kbd{a}. \fun{GEN}{FFX_preimagerel}{GEN F, GEN x, GEN a} returns $P\%F$ where \kbd{P=x.pol} assuming $a$ and $x$ belongs to fields having the same characteristic, and that the coefficients of $F$ belong to the definition field of $a$. \fun{GEN}{FFX_preimage}{GEN F, GEN x, GEN a} as \kbd{FFX\_preimagerel} but return \kbd{NULL} if the remainder is of degree greater or equal to $1$, the constant coefficient otherwise. \fun{GEN}{FFV_roots_to_pol}{GEN V, GEN ff, long v} \kbd{V} being a vector over the finite field given by \kbd{ff} (\typ{FFELT}), returns the monic \typ{POL} $\prod_i (\kbd{pol\_x[v]} - \kbd{V[i]})$. \subsec{FFM} \fun{GEN}{FFM_FFC_gauss}{GEN M, GEN C, GEN ff} given a matrix \kbd{M} (\typ{MAT}) and a column vector \kbd{C} (\typ{COL}) over the finite field given by \kbd{ff} (\typ{FFELT}) such that $M$ is invertible, return the unique column vector $X$ such that $MX=C$. \fun{GEN}{FFM_FFC_invimage}{GEN M, GEN C, GEN ff} given a matrix \kbd{M} (\typ{MAT}) and a column vector \kbd{C} (\typ{COL}) over the finite field given by \kbd{ff} (\typ{FFELT}), return a column vector \kbd{X} such that $MX=C$, or \kbd{NULL} if no such vector exists. \fun{GEN}{FFM_FFC_mul}{GEN M, GEN C, GEN ff} returns the product of the matrix~\kbd{M} (\typ{MAT}) and the column vector~\kbd{C} (\typ{COL}) over the finite field given by \kbd{ff} (\typ{FFELT}). \fun{GEN}{FFM_deplin}{GEN M, GEN ff} returns a nonzero vector (\typ{COL}) in the kernel of the matrix~\kbd{M} over the finite field given by \kbd{ff}, or \kbd{NULL} if no such vector exists. \fun{GEN}{FFM_det}{GEN M, GEN ff} returns the determinant of the matrix~\kbd{M} over the finite field given by \kbd{ff}. \fun{GEN}{FFM_gauss}{GEN M, GEN N, GEN ff} given two matrices \kbd{M} and~\kbd{N} (\typ{MAT}) over the finite field given by \kbd{ff} (\typ{FFELT}) such that $M$ is invertible, return the unique matrix $X$ such that $MX=N$. \fun{GEN}{FFM_image}{GEN M, GEN ff} returns a matrix whose columns span the image of the matrix~\kbd{M} over the finite field given by \kbd{ff}. \fun{GEN}{FFM_indexrank}{GEN M, GEN ff} given a matrix \kbd{M} of rank~$r$ over the finite field given by \kbd{ff}, returns a vector with two \typ{VECSMALL} components $y$ and $z$ containing $r$ row and column indices, respectively, such that the $r\times r$-matrix formed by the \kbd{M[i,j]} for $i$ in $y$ and $j$ in $z$ is invertible. \fun{GEN}{FFM_inv}{GEN M, GEN ff} returns the inverse of the square matrix~\kbd{M} over the finite field given by \kbd{ff}, or \kbd{NULL} if \kbd{M} is not invertible. \fun{GEN}{FFM_invimage}{GEN M, GEN N, GEN ff} given two matrices \kbd{M} and~\kbd{N} (\typ{MAT}) over the finite field given by \kbd{ff} (\typ{FFELT}), return a matrix \kbd{X} such that $MX=N$, or \kbd{NULL} if no such matrix exists. \fun{GEN}{FFM_ker}{GEN M, GEN ff} returns the kernel of the \typ{MAT} \kbd{M} over the finite field given by the \typ{FFELT} \kbd{ff}. \fun{GEN}{FFM_mul}{GEN M, GEN N, GEN ff} returns the product of the matrices \kbd{M} and~\kbd{N} (\typ{MAT}) over the finite field given by \kbd{ff} (\typ{FFELT}). \fun{long}{FFM_rank}{GEN M, GEN ff} returns the rank of the matrix~\kbd{M} over the finite field given by \kbd{ff}. \fun{GEN}{FFM_suppl}{GEN M, GEN ff} given a matrix \kbd{M} over the finite field given by \kbd{ff} whose columns are linearly independent, returns a square invertible matrix whose first columns are those of~\kbd{M}. \subsec{FFXQ} \fun{GEN}{FFXQ_mul}{GEN P, GEN Q, GEN T, GEN a} returns the product of the polynomials \kbd{P} and \kbd{Q} modulo the polynomial \kbd{T}, where \kbd{P}, \kbd{Q} and \kbd{T} are defined over the definition field of the \typ{FFELT} \kbd{a}. \fun{GEN}{FFXQ_sqr}{GEN P, GEN T, GEN a} returns the square of the polynomial \kbd{P} modulo the polynomial \kbd{T}, where \kbd{P} and \kbd{T} are defined over the definition field of the \typ{FFELT} \kbd{a}. \fun{GEN}{FFXQ_inv}{GEN P, GEN Q, GEN a} returns the inverse of the polynomial \kbd{P} modulo the polynomial \kbd{Q}, where \kbd{P} and \kbd{Q} are defined over the definition field of the \typ{FFELT} \kbd{a}. \fun{GEN}{FFXQ_minpoly}{GEN Pf, GEN Qf, GEN a} returns the minimal polynomial of the polynomial \kbd{P} modulo the polynomial \kbd{Q}, where \kbd{P} and \kbd{Q} are defined over the definition field of the \typ{FFELT} \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}{cbrtr}{GEN x} returns the real cube root of $x$. \fun{GEN}{sqrtnr}{GEN x, long n} returns the $n$-th root of $x$, assuming $n\geq 1$ and $x \geq 0$. \fun{GEN}{sqrtnr_abs}{GEN x, long n} returns the $n$-th root of $|x|$, assuming $n\geq 1$ and $x \neq 0$. \fun{GEN}{mpcos[z]}{GEN x[, GEN z]} returns $\cos(x)$. \fun{GEN}{mpsin[z]}{GEN x[, GEN z]} returns $\sin(x)$. \fun{GEN}{mplog[z]}{GEN x[, GEN z]} returns $\log(x)$. We must have $x > 0$ since the result must be a \typ{REAL}. Use \kbd{glog} for the general case, where you want such computations as $\log(-1) = I$. \fun{GEN}{mpexp[z]}{GEN x[, GEN z]} returns $\exp(x)$. \fun{GEN}{mpexpm1}{GEN x} returns $\exp(x)-1$, but is more accurate than \kbd{subrs(mpexp(x), 1)}, which suffers from catastrophic cancellation if $|x|$ is very small. \fun{void}{mpsincosm1}{GEN x, GEN *s, GEN *c} sets $s$ and $c$ to $\sin(x)$ and $\cos(x)-1$ respectively, where $x$ is a \typ{REAL}; the latter is more accurate than \kbd{subrs(mpcos(y), 1)}, which suffers from catastrophic cancellation if $|x|$ is very small. \fun{GEN}{mpveceint1}{GEN C, GEN eC, long n} as \kbd{veceint1}; assumes that $C > 0$ is a \typ{REAL} and that \kbd{eC} is \kbd{NULL} or \kbd{mpexp(C)}. \fun{GEN}{mpeint1}{GEN x, GEN expx} returns \kbd{eint1}$(x)$, for a \typ{REAL} $x\neq 0$, assuming that \kbd{expx} is \kbd{mpexp}$(x)$. \noindent A few variants on the Lambert function: they actually work when \kbd{gtofp} can map all \kbd{GEN} arguments to a \typ{REAL}. \fun{GEN}{mplambertW}{GEN y} solution $x = W_0(y)$ of the implicit equation $x \exp(x) = y$, for $y > -1/e$ a \typ{REAL}. \fun{GEN}{mplambertx_logx}{GEN a, GEN b, long bit} solve $x - a \log(x) = b$ with $a > 0$ and $b \geq a (1 - \log(a))$. \fun{GEN}{mplambertX}{GEN y, long bit} as \tet{mplambertx_logx} in the special case $a = 1$, $b = \log(y)$. In other words, solve $e^x / x = y$ with $y \geq e$. \fun{GEN}{mplambertxlogx_x}{GEN a, GEN b, long bit} solve $x \log(x) - a x = b$; if $b < 0$, assume $a \geq 1 + \log |b|$. \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}{cbrtr_abs}{GEN x} returns $|x|^{1/3}$ assuming $x\neq 0$. \fun{GEN}{exp1r_abs}{GEN x} returns $\exp(|x|) - 1$, assuming $x \neq 0$. \fun{GEN}{logr_abs}{GEN x} returns $\log(|x|)$, assuming $x \neq 0$. \subsec{Other complex transcendental functions} \fun{GEN}{atanhuu}{ulong u, ulong v, long prec} computes \text{atanh}$(u/v)$ using binary splitting, assuming $0 < u < v$. Not memory clean but suitable for \kbd{gerepileupto}. The complexity is $O(b / \log(v/u))$, where $b$ is \kbd{prec2nbits(prec)}, so becomes impractical when $v/u$ is too close to $1$. \fun{GEN}{atanhui}{ulong u, GEN v, long prec} computes \text{atanh}$(u/v)$ using binary splitting, assuming $0 < u < v$. Not memory clean but suitable for \kbd{gerepileupto}. \fun{GEN}{szeta}{long s, long prec} returns the value of Riemann's zeta function at the (possibly negative) integer $s\neq 1$, in relative accuracy \kbd{prec}. \fun{GEN}{veczeta}{GEN a, GEN b, long N, long prec} returns in a vector all the $\zeta(aj + b)$, where $j = 0, 1, \dots, N-1$, where $a$ and $b$ are real numbers (of arbitrary type, although \typ{INT} is treated more efficiently) and $b > 1$. Assumes that $N \geq 1$. \fun{GEN}{ggamma1m1}{GEN x, long prec} return $\Gamma(1+x) - 1$ assuming $|x| < 1$. Guard against cancellation when $x$ is small. \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{void}{mpsinhcosh}{GEN x, GEN *s, GEN *c} sets $s$ and $c$ to $\sinh(x)$ and $\cosh(x)$ respectively, where $x$ is a \typ{REAL} \fun{GEN}{expIr}{GEN x} returns $\exp(ix)$, where $x$ is a \typ{REAL}. The return type is \typ{COMPLEX} unless the imaginary part is equal to $0$ to the current accuracy (its sign is $0$). \fun{GEN}{expIPiR}{GEN x, long prec} return $\exp(i \pi x)$, where $x$ is a real number (\typ{INT}, \typ{FRAC} or \typ{REAL}). \fun{GEN}{expIPiC}{GEN z, long prec} return $\exp(i \pi x)$, where $x$ is a complex number (\typ{INT}, \typ{FRAC}, \typ{REAL} or \typ{COMPLEX}). \fun{GEN}{expIxy}{GEN x, GEN y, long prec} returns $\exp(ixy)$. Efficient when $x$ is real and $y$ pure imaginary. \fun{GEN}{pow2Pis}{GEN s, long prec} returns $(2\pi)^s$. The intent of this function and the next ones is to be accurate even if $s$ has a huge imaginary part: $\pi$ is computed at an accuracy taking into account the cancellation induced by argument reduction when computing the sine or cosine of $\Im s \log 2\pi$. \fun{GEN}{powPis}{GEN s, long prec} returns $\pi^s$, as \kbd{pow2Pis}. \fun{long}{powcx_prec}{long e, GEN s, long prec} if $e \approx \log_2 |x|$ return the precision at which $\log(x)$ must be computed to evaluate $x^s$ reliably (taking into account argument reduction). \fun{GEN}{powcx}{GEN x, GEN logx, GEN s, long prec} assuming $s$ is a \typ{COMPLEX} and \kbd{logx} is $\log(x)$ computed to accuracy \kbd{powcx\_prec}, return $x^s$. \fun{void}{gsincos}{GEN x, GEN *s, GEN *c, long prec} general case. \fun{GEN}{rootsof1_cx}{GEN d, long prec} return $e(1/d)$ at precision \kbd{prec}, $e(x) = \exp(2i\pi x)$. \fun{GEN}{rootsof1u_cx}{ulong d, long prec} return $e(1/d)$ at precision \kbd{prec}. \fun{GEN}{rootsof1q_cx}{long a, long b, long prec} return $e(a/b)$ at precision \kbd{prec}. \fun{GEN}{rootsof1powinit}{long a, long b, long prec} precompute $b$-th roots of $1$ for \kbd{rootsof1pow}, i.e. to later compute $e(ac/b)$ for varying $c$. \fun{GEN}{rootsof1pow}{GEN T, long c} given $T = \kbd{rootsof1powinit}(a,b,\kbd{prec})$, return $e(ac/b)$. \noindent A generalization of \tet{affrr_fixlg} \fun{GEN}{affc_fixlg}{GEN x, GEN res} assume \kbd{res} was allocated using \tet{cgetc}, and that $x$ is either a \typ{REAL} or a \typ{COMPLEX} with \typ{REAL} components. Assign $x$ to \kbd{res}, first shortening the components of \kbd{res} if needed (in a \kbd{gerepile}-safe way). Further convert \kbd{res} to a \typ{REAL} if $x$ is a \typ{REAL}. \fun{GEN}{trans_eval}{const char *fun, GEN (*f) (GEN, long), GEN x, long prec} evaluate the transcendental function $f$ (named \kbd{"fun"} at the argument $x$ and precision \kbd{prec}. This is a quick way to implement a transcendental function to be made available under GP, starting from a $C$ function handling only \typ{REAL} and \typ{COMPLEX} arguments. This routine first converts $x$ to a suitable type: \item \typ{INT}/\typ{FRAC} to \typ{REAL} of precision \kbd{prec}, \typ{QUAD} to \typ{REAL} or \typ{COMPLEX} of precision \kbd{prec}. \item \typ{POLMOD} to a \typ{COL} of complex embeddings (as in \tet{conjvec}) Then evaluates the function at \typ{VEC}, \typ{COL}, \typ{MAT} arguments coefficientwise. \fun{GEN}{trans_evalgen}{const char *fun, void *E, GEN (*f)(void*,GEN,long), GEN x, long prec}, general variant evaluating $f(E, x, \var{prec})$, where the function prototype allows to wrap an arbitrary context given by the argument $E$. \subsec{Modular functions} \fun{GEN}{cxredsl2}{GEN z, GEN *g} given $t$ a \typ{COMPLEX} belonging to the upper half-plane, find $\gamma \in \text{SL}_2(\Z)$ such that $\gamma \cdot z$ belongs to the standard fundamental domain and set \kbd{*g} to $\gamma$. \fun{GEN}{cxredsl2_i}{GEN z, GEN *g, GEN *czd} as \kbd{cxredsl2}; also sets \kbd{*czd} to $cz + d$, if $\gamma = [a,b;c,d]$. \fun{GEN}{cxEk}{GEN tau, long k, long prec} returns $E_k(\tau)$ by direct evaluation of $1 + 2/\zeta(1-k) \sum_n n^{k-1} q^n/(1-q^n)$, $q = e(\tau)$. Assume that $\Im \tau > 0$ and $k$ even. Very slow unless $\tau$ is already reduced modulo $\text{SL}_2(\Z)$. Not \kbd{gerepile}-clean but suitable for \kbd{gerepileupto}. \subsec{Transcendental functions with \typ{PADIC} arguments} The argument $x$ is assumed to be a \typ{PADIC}. \fun{GEN}{Qp_exp}{GEN x} shortcut for \kbd{gexp(x, /*ignored*/prec)} \fun{long}{Qp_exp_prec}{GEN x} number of terms to sum in the $\exp(x)$ series to reach the same $p$-adic accuracy as $x\neq 0$. If $n = p-1$, $e = v_p(x)$ and $b = \kbd{precp}(x)$, this is the ceiling of $nb / (ne - 1)$. Return $-1$ if the series does not converge ($ne \leq 1$). \fun{GEN}{Qp_gamma}{GEN x} shortcut for \kbd{ggamma(x, /*ignored*/prec)} \fun{GEN}{Qp_zeta}{GEN x} shortcut for \kbd{gzeta(x, /*ignored*/prec)}; assume that $x\neq 1$. \fun{GEN}{Qp_zetahurwitz}{GEN x, GEN y, long k} shortcut for \kbd{zetahurwitz(x, y, k, /*ignored*/prec)}. \fun{GEN}{Qp_psi}{GEN x} shortcut fo \kbd{gpsi(x, /*ignored*/prec)}. \fun{GEN}{Qp_log}{GEN x} shortcut for \kbd{glog(x, /*ignored*/prec)}. \fun{GEN}{Qp_sqrt}{GEN x} shortcut for \kbd{gsqrt(x, /*ignored*/prec)} Return \kbd{NULL} if $x$ is not a square. \fun{GEN}{Qp_sqrtn}{GEN x, GEN n, GEN *z} shortcut for \kbd{gsqrtn(x, n, z, /*ignored*/prec)}. Return \kbd{NULL} if $x$ is not an $n$-th power. \fun{GEN}{Qp_agm2_sequence}{GEN a1, GEN b1} assume $a_1/b_1 = 1$ mod $p$ if $p$ odd and mod $2^4$ if $p = 2$. Let $A_1 = a_1/p^v$ and $B_1 = b_1/p^v$ with $v = v_p(a_1) = v_p(b_1)$; let further $A_{n+1} = (A_n + B_n + 2 B_{n+1}) / 4$, $B_{n+1} = B_n \sqrt{A_n / B_n}$ (the square root of $A_n B_n$ congruent to $B_n$ mod $p$) and $R_n = p^v(A_n - B_n)$. We stop when $R_n$ is $0$ at the given $p$-adic accuracy. This function returns in a triplet \typ{VEC} the three sequences $(A_n)$, $(B_n)$ and $(R_n)$, corresponding to a sequence of $2$-isogenies on the Tate curve $y^2 = x(x-a_1)(x+a_1-b_1)$. The common limit of $A_n$ and $B_n$ is the $M_2(a_1,b_1)$, the square of the $p$-adic AGM of $\sqrt(a_1)$ and $\sqrt(b_1)$. This is given by \tet{ellQp_Ei} and is used by corresponding ascending and descending $p$-adic Landen transforms: \fun{void}{Qp_ascending_Landen}{GEN ABR, GEN *ptx, GEN *pty} \fun{void}{Qp_descending_Landen}{GEN ABR, GEN *ptx, GEN *pty} \subsec{Cached constants} The cached constant is returned at its current precision, which may be larger than \kbd{prec}. One should always use the \kbd{mp\var{xxx}} variant: \kbd{mppi}, \kbd{mpeuler}, or \kbd{mplog2}. \fun{GEN}{consteuler}{long prec} precomputes Euler-Mascheroni's constant at precision \kbd{prec}. \fun{GEN}{constcatalan}{long prec} precomputes Catalan's constant at precision \kbd{prec}. \fun{GEN}{constpi}{long prec} precomputes $\pi$ at precision \kbd{prec}. \fun{GEN}{constlog2}{long prec} precomputes $\log(2)$ at precision \kbd{prec}. \fun{void}{constbern}{long n} precomputes the $n$ even \idx{Bernoulli} numbers $B_2,\dots,B_{2n}$ as \typ{FRAC}. No more than $n$ Bernoulli numbers will ever be stored (by \tet{bernfrac} or \tet{bernreal}), unless a subsequent call to \kbd{constbern} increases the cache. \fun{GEN}{constzeta}{long n, long prec} ensures that the $n$ values $\gamma, \zeta(2),\dots, \zeta(n)$ are cached at accuracy bigger than or equal to \kbd{prec} and return a vector containing at least those value. Note that $\gamma = \lim_1 \zeta(s) - 1/(s-1)$. If the accuracy of cached data is too low or $n$ is greater than the cache length, the cache is recomputed at the given parameters. The following functions use cached data if \kbd{prec} is smaller than the precision of the cached value; otherwise the newly computed data replaces the old cache. \fun{GEN}{mppi}{long prec} returns $\pi$ at precision \kbd{prec}. \fun{GEN}{Pi2n}{long n, long prec} returns $2^n\pi$ at precision \kbd{prec}. \fun{GEN}{PiI2}{long n, long prec} returns the complex number $2\pi i$ at precision \kbd{prec}. \fun{GEN}{PiI2n}{long n, long prec} returns the complex number $2^n\pi i$ at precision \kbd{prec}. \fun{GEN}{mpeuler}{long prec} returns Euler-Mascheroni's constant at precision \kbd{prec}. \fun{GEN}{mpeuler}{long prec} returns Catalan's number at precision \kbd{prec}. \fun{GEN}{mplog2}{long prec} returns $\log 2$ at precision \kbd{prec}. The following functions use the \idx{Bernoulli} numbers cache initialized by \kbd{constbern}: \fun{GEN}{bernreal}{long i, long prec} returns the \idx{Bernoulli} number $B_i$ as a \typ{REAL} at precision \kbd{prec}. If \kbd{constbern(n)} was called previously with $n \geq i$, then the cached value is (converted to a \typ{REAL} of accuracy \kbd{prec} then) returned. Otherwise, the missing value is computed; the cache is not updated. \fun{GEN}{bernfrac}{long i} returns the \idx{Bernoulli} number $B_i$ as a rational number (\typ{FRAC} or \typ{INT}). If the \kbd{constbern} cache includes $B_i$, the latter is returned. Otherwise, the missing value is computed; the cache is not updated. \subsec{Obsolete functions} \fun{void}{mpbern}{long n, long prec} \section{Permutations } \noindent Permutations 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_sqr}{GEN s} multiply $s$ by itself (composition $s\circ s$) \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, GEN n} returns $p^n$ \fun{GEN}{perm_powu}{GEN p, ulong 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{GEN}{perm_order}{GEN p} returns the order of the permutation $p$ (as the lcm of its cycle lengths). \fun{ulong}{perm_orderu}{GEN p} returns the order of the permutation $p$ (as the lcm of its cycle lengths) assuming it fits in a \kbd{ulong}. \fun{long}{perm_sign}{GEN p} returns the sign of the permutation $p$. \fun{GEN}{vecperm_orbits}{GEN gen, long n} return the orbits of $\{1,2,\ldots,n\}$ under the action of the subgroup of $S_n$ generated by $gen$. \fun{GEN}{Z_to_perm}{long n, GEN x} as \kbd{numtoperm}, returning a \typ{VECSMALL}. \fun{GEN}{perm_to_Z}{GEN v} as \kbd{permtonum} for a \typ{VECSMALL} input. \fun{GEN}{perm_to_GAP}{GEN p} return a \typ{STR} which is a representation of $p$ comptatible with the GAP computer algebra system. \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 an $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 permutations 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} check 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}{checkgroupelts}{GEN gal} check whether \var{gal} is a small group or a Galois group, or a vector of permutations listing the group elements. Returns the list of group elements as permutations. \fun{GEN}{galois_group}{GEN gal} return the underlying small group of the Galois group \var{gal}. \fun{GEN}{cyclicgroup}{GEN g, long s} return the cyclic group with generator $g$ of order $s$. \fun{GEN}{trivialgroup}{void} return 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{nontrivial} 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}{groupelts_to_group}{GEN elts}, where \var{elts} is the list of elements of a group, returns the corresponding small group, if it exists, otherwise return \kbd{NULL}. \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{GEN}{groupelts_conj_set}{GEN elts, GEN p}, 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 $p^{-1}[1]$ to $p^{-1}[i]$. \fun{int}{group_subgroup_is_faithful}{GEN G, GEN H} return $1$ if the action of $G$ on $G/H$ by translation is faithful, $0$ otherwise. \fun{GEN}{groupelts_conjclasses}{GEN elts, long *pn}, where \var{elts} is the list of elements of a small group (sorted with respect to \kbd{vecsmall\_lexcmp}), return a \typ{VECSMALL} \kbd{conj} of the same length such that \kbd{conj[i]} is the index in $\{1,\cdots,n\}$ of the conjugacy class of \kbd{elts[i]} for some unspecified but deterministic ordering of the classes, where $n$ is the number of conjugacy classes. If \kbd{pn} is non \kbd{NULL}, \kbd{*pn} is set to $n$. \fun{GEN}{conjclasses_repr}{GEN conj, long nb}, where \kbd{conj} and \kbd{nb} are as returned by the call \kbd{groupelts\_conjclasses(elts)}, return \typ{VECSMALL} of length \kbd{nb} which gives the indices in \kbd{elts} of a representative of each conjugacy class. \fun{GEN}{group_to_cc}{GEN G}, where $G$ is a small group or a Galois group, returns a \kbd{cc} (conjclasses) structure \kbd{[elts,conj,rep,flag]}, as obtained by \kbd{alggroupcenter}, where \kbd{conj} is \kbd{groupelts\_conjclasses}$(\kbd{elts})$ and \kbd{rep} is the attached \kbd{conjclasses\_repr}. \kbd{flag} is 1 if the permutation representation is transitive (in which case an element $g$ of $G$ is characterized by $g[1]$), and 0 otherwise. Shallow function. \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$ if 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$, $3$ if it is isomorphic to $(3\times 3):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 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 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}{groupelts_quotient}{GEN elts, GEN H}, where \var{elts} is the list of elements of a small group $G$, $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_groupelts}{GEN C} where $C$ is the quotient map $G\rightarrow G/H$ for some group $G$ and some \emph{normal} subgroup $H$ of $G$, return the list of elements of the quotient group $G/H$ (as permutations over corresponding to the regular representation). \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}{groupelts_solvablesubgroups}{GEN elts} where \var{elts} is the list of elements of a finite group, returns the list of its solvable subgroups, each as a list of its elements. \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 attached 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{long}{groupelts_exponent}{GEN elts} where \var{elts} is the list of elements of a small group, returns the exponent the group (the LCM of the order of the elements of the 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} convert a small group to another format, as a \typ{STR} describing the group for the given syntax, see \tet{galoisexport}. \fun{GEN}{group_export_GAP}{GEN G} export a small group to GAP format. \fun{GEN}{group_export_MAGMA}{GEN G} export a small group to MAGMA format. \fun{long}{group_ident}{GEN grp, GEN elts} returns the index of the small group \var{grp} in the GAP4 Small Group library, see \tet{galoisidentify}. If \var{elts} is not \kbd{NULL}, it must be the list of elements of \var{grp}. \fun{long}{group_ident_trans}{GEN grp, GEN elts} returns the index of the regular representation of the small group \var{grp} in the GAP4 Transitive Group library, see \tet{polgalois}. If \var{elts} is no \kbd{NULL}, it must be the list of elements of \var{grp}. \newpage \chapter{Standard data structures} \section{Character strings} \subsec{Functions returning a \kbd{char *}} \fun{char*}{pari_strdup}{const char *s} returns a malloc'ed copy of $s$ (uses \kbd{pari\_malloc}). \fun{char*}{pari_strndup}{const char *s, long n} returns a malloc'ed copy of at most $n$ chars from $s$ (uses \kbd{pari\_malloc}). If $s$ is longer than $n$, only $n$ characters are copied and a terminal null byte is added. \fun{char*}{stack_strdup}{const char *s} returns a copy of $s$, allocated on the PARI stack (uses \kbd{stack\_malloc}). \fun{char*}{stack_strcat}{const char *s, const char *t} returns the concatenation of $s$ and $t$, allocated on the PARI stack (uses \kbd{stack\_malloc}). \fun{char*}{stack_sprintf}{const char *fmt, ...} runs \kbd{pari\_sprintf} on the given arguments, returning a string allocated on the PARI stack. \fun{char*}{uordinal}{ulong x} return the ordinal number attached to $x$ (i.e. $1$st, $2$nd, etc.) as a \tet{stack_malloc}'ed string. \fun{char*}{itostr}{GEN x} writes the \typ{INT} $x$ to a \tet{stack_malloc}'ed string. \fun{char*}{GENtostr}{GEN x}, using the current default output format (\kbd{GP\_DATA->fmt}, which contains the output style and the number of significant digits to print), converts $x$ to a malloc'ed string. Simple variant of \tet{pari_sprintf}. \fun{char*}{GENtostr_raw}{GEN x} as \tet{GENtostr} with the following differences: 1) the output format is \tet{f_RAW}; 2) the result is allocated on the stack and \emph{must not} be freed. \fun{char*}{GENtostr_unquoted}{GEN x} as \tet{GENtostr_raw} with the following additional difference: a \typ{STR} $x$ is printed without enclosing quotes (to be used by \kbd{print}. \fun{char*}{GENtoTeXstr}{GEN x}, as \kbd{GENtostr}, except that \tet{f_TEX} overrides the output format from \kbd{GP\_DATA->fmt}. \fun{char*}{RgV_to_str}{GEN g, long flag} $g$ being a vector of \kbd{GEN}s, returns a malloc'ed string, the concatenation of the \kbd{GENtostr} applied to its elements, except that \typ{STR} are printed without enclosing quotes. \kbd{flag} determines the output format: \tet{f_RAW}, \tet{f_PRETTYMAT} or \tet{f_TEX}. \subsec{Functions returning a \typ{STR}} \fun{GEN}{strtoGENstr}{const char *s} returns a \typ{STR} with content $s$. \fun{GEN}{strntoGENstr}{const char *s, long n} returns a \typ{STR} containing the first $n$ characters of $s$. \fun{GEN}{chartoGENstr}{char c} returns a \typ{STR} containing the character $c$. \fun{GEN}{GENtoGENstr}{GEN x} returns a \typ{STR} containing the printed form of $x$ (in \tet{raw} format). This is often easier to use that \tet{GENtostr} (which returns a malloc-ed \kbd{char*}) since there is no need to free the string after use. \fun{GEN}{GENtoGENstr_nospace}{GEN x} as \kbd{GENtoGENstr}, removing all spaces from the output. \fun{GEN}{Str}{GEN g} as \tet{RgV_to_str} with output format \tet{f_RAW}, but returns a \typ{STR}, not a malloc'ed string. \fun{GEN}{strtex}{GEN g} as \tet{RgV_to_str} with output format \tet{f_TEX}, but returns a \typ{STR}, not a malloc'ed string. \fun{GEN}{strexpand}{GEN g} as \tet{RgV_to_str} with output format \tet{f_RAW}, performing tilde and environment expansion on the result. Returns a \typ{STR}, not a malloc'ed string. \fun{GEN}{gsprintf}{const char *fmt, ...} equivalent to \kbd{pari\_sprintf(fmt,...}, followed by \tet{strtoGENstr}. Returns a \typ{STR}, not a malloc'ed string. \fun{GEN}{gvsprintf}{const char *fmt, va_list ap} variadic version of \tet{gsprintf} \fun{GEN}{pari_base64}{const char *s} convert the string to base64 (RFC4648 "+/" with padding). \subsec{Dynamic strings} A \tet{pari_str} is a dynamic string which grows dynamically as needed. This structure contains private data and two public members \kbd{char *string}, which is the string itself and \kbd{use\_stack} which tells whether the string lives \item on the PARI stack (value $1$), meaning that it will be destroyed by any manipulation of the stack, e.g. a \kbd{gerepile} call or resetting \kbd{avma}; \item in malloc'ed memory (value $0$), in which case it is impervious to stack manipulation but will need to be explicitly freed by the user after use, via \kbd{pari\_free(s.string)}. \fun{void}{str_init}{pari_str *S, int use_stack} initializes a dynamic string; if \kbd{use\_stack} is 0, then the string is malloc'ed, else it lives on the PARI stack. \fun{void}{str_printf}{pari_str *S, const char *fmt, ...} write to the end of $S$ the remaining arguments according to PARI format \kbd{fmt}. \fun{void}{str_putc}{pari_str *S, char c} write the character $c$ to the end of $S$. \fun{void}{str_puts}{pari_str *S, const char *s} write the string $s$ to the end of $S$. \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 nonzero 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 nontrivial 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, attached to the \tet{colors} default. The following symbolic names are attached 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 nonempty 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 attached to output object \kbd{c}. If \kbd{c} is \tet{c_NONE}, revert to default printing style. \fun{void}{out_term_color}{PariOUT *out, long c} as \tet{term_color}, using output context \kbd{out}. \fun{char*}{term_get_color}{char *s, long c} returns as a character string the ANSI color escape sequence attached to output object \kbd{c}. If \kbd{c} is \tet{c_NONE}, the value used to revert to default printing style is returned. The argument \kbd{s} is either \kbd{NULL} (string allocated on the PARI stack), or preallocated storage (in which case, it must be able to hold at least 16 chars, including the final \kbd{\bs 0}). \subsec{Obsolete output functions} These variants of \fun{void}{output}{GEN x}, which prints \kbd{x}, followed by a newline and a buffer flush are complicated to use and less flexible than what we saw above, or than the \tet{pari_printf} variants. They are provided for backward compatibility and are scheduled to disappear. \fun{void}{brute}{GEN x, char format, long dec} \fun{void}{matbrute}{GEN x, char format, long dec} \fun{void}{texe}{GEN x, char format, long dec} \section{Files} The following routines are trivial wrappers around system functions (possibly around one of several functions depending on availability). They are usually integrated within PARI's diagnostics system, printing messages if the debug level for \kbd{"files"} is high enough. \fun{int}{pari_is_dir}{const char *name} returns $1$ if \kbd{name} points to a directory, $0$ otherwise. \fun{int}{pari_is_file}{const char *name} returns $1$ if \kbd{name} points to a directory, $0$ otherwise. \fun{int}{file_is_binary}{FILE *f} returns $1$ if the file $f$ is a binary file (in the \tet{writebin} sense), $0$ otherwise. \fun{void}{pari_unlink}{const char *s} deletes the file named $s$. Warn if the operation fails. \fun{void}{pari_fread_chars}{void *b, size_t n, FILE *f} read $n$ chars from stream $f$, storing the result in pre-allocated buffer $b$ (assumed to be large enough). \fun{char*}{path_expand}{const char *s} perform tilde and environment expansion on $s$. Returns a \kbd{malloc}'ed buffer. \fun{void}{strftime_expand}{const char *s, char *buf, long max} perform time expansion on $s$, storing the result (at most \kbd{max} chars) in buffer \kbd{buf}. Trivial wrapper around \bprog time_t t = time(NULL); strftime(but, max, s, localtime(&t); @eprog \fun{char*}{pari_get_homedir}{const char *user} expands \kbd{\til user} constructs, returning the home directory of user \kbd{user}, or \kbd{NULL} if it could not be determined (in particular if the operating system has no such concept). The return value may point to static area and may be overwritten by subsequent system calls: use immediately or \kbd{strdup} it. \fun{int}{pari_stdin_isatty}{void} returns $1$ if our standard input \kbd{stdin} is attached to a terminal. Trivial wrapper around \kbd{isatty}. \subsec{pariFILE} PARI maintains a linked list of open files, to reclaim resources (file descriptors) on error or interrupts. The corresponding data structure is a \kbd{pariFILE}, which is a wrapper around a standard \kbd{FILE*}, containing further the file name, its type (regular file, pipe, input or output file, etc.). The following functions create and manipulate this structure; they are integrated within PARI's diagnostics system, printing messages if the debug level for \kbd{"files"} 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 an environment variable (\kbd{\$GPTMPDIR}, else \kbd{\$TMPDIR}), or the first writable directory among \kbd{/tmp}, \kbd{/var/tmp} and \kbd{.}. \fun{char*}{pari_unique_dir}{const char *s} creates a ``unique directory'' and return its name built from the string $s$, the user id and process pid (on Unix systems). This directory is itself located in the temp directory mentioned above. The name returned is \tet{malloc}'ed. \fun{char*}{pari_unique_filename}{const char *s} creates a \emph{new} empty file in the temp directory, whose name contains the id-string $s$ (truncated to its first $8$ chars), followed by a system-dependent suffix (incorporating the ids of both the user and the running process, for instance). The function returns the tempfile name and creates an empty file with that name. The name returned is \tet{malloc}'ed. \fun{char*}{pari_unique_filename_suffix}{const char *s, const char *suf} analogous to above \tet{pari_unique_filename}, creating a (previously nonexistent) tempfile whose name ends with suffix \kbd{suf}. \section{Errors}\label{se:errors} This section documents the various error classes, and the corresponding arguments to \tet{pari_err}. The general syntax is \fun{void}{pari_err}{numerr,...} \noindent In the sequel, we mostly use sequences of arguments of the form \bprog const char *s const char *fmt, ... @eprog\noindent where \kbd{fmt} is a PARI format, producing a string $s$ from the remaining arguments. Since providing the correct arguments to \tet{pari_err} is quite error-prone, we also provide specialized routines \kbd{pari\_err\_\var{ERRORCLASS}(\dots)} instead of \kbd{pari\_err(e\_\var{ERRORCLASS}, \dots)} so that the C compiler can check their arguments. \noindent We now inspect the list of valid keywords (error classes) for \kbd{numerr}, and the corresponding required arguments. \subsec{Internal errors, ``system'' errors} \subsubsec{e\_ARCH} A requested feature $s$ is not available on this architecture or operating system. \bprog pari_err(e_ARCH) @eprog\noindent prints the error message: \kbd{sorry, '$s$' not available on this system}. \subsubsec{e\_BUG} A bug in the PARI library, in function $s$. \bprog pari_err(e_BUG, const char *s) pari_err_BUG(const char *s) @eprog\noindent prints the error message: \kbd{Bug in $s$, please report}. \subsubsec{e\_FILE} Error while trying to open a file. \bprog pari_err(e_FILE, const char *what, const char *name) pari_err_FILE(const char *what, const char *name) @eprog\noindent prints the error message: \kbd{error opening \emph{what}: `\emph{name}'}. \subsubsec{e\_FILEDESC} Error while handling a file descriptor. \bprog pari_err(e_FILEDESC, const char *where, long n) pari_err_FILEDESC(const char *where, long n) @eprog\noindent prints the error message: \kbd{invalid file descriptor in \emph{where}: `\emph{name}'}. \subsubsec{e\_IMPL} A requested feature $s$ is not implemented. \bprog pari_err(e_IMPL, const char *s) pari_err_IMPL(const char *s) @eprog\noindent prints the error message: \kbd{sorry, $s$ is not yet implemented}. \subsubsec{e\_PACKAGE} Missing optional package $s$. \bprog pari_err(e_PACKAGE, const char *s) pari_err_PACKAGE(const char *s) @eprog\noindent prints the error message: \kbd{package $s$ is required, please install it} \subsec{Syntax errors, type errors} \subsubsec{e\_DIM} arguments submitted to function $s$ have inconsistent dimensions. E.g., when solving a linear system, or trying to compute the determinant of a nonsquare matrix. \bprog pari_err(e_DIM, const char *s) pari_err_DIM(const char *s) @eprog\noindent prints the error message: \kbd{inconsistent dimensions in $s$}. \subsubsec{e\_FLAG} A flag argument is out of bounds in function $s$. \bprog pari_err(e_FLAG, const char *s) pari_err_FLAG(const char *s) @eprog\noindent prints the error message: \kbd{invalid flag in $s$}. \subsubsec{e\_NOTFUNC} Generated by the PARI evaluator; tried to use a \kbd{GEN} which is not a \typ{CLOSURE} in a function call syntax (as in \kbd{f = 1; f(2);}). \bprog pari_err(e_NOTFUNC, GEN fun) @eprog\noindent prints the error message: \kbd{not a function in a function call}. \subsubsec{e\_OP} Impossible operation between two objects than cannot be typecast to a sensible common domain for deeper reasons than a type mismatch, usually for arithmetic reasons. As in \kbd{O(2) + O(3)}: it is valid to add two \typ{PADIC}s, provided the underlying prime is the same; so the addition is not forbidden a priori for type reasons, it only becomes so when inspecting the objects and trying to perform the operation. \bprog pari_err(e_OP, const char *op, GEN x, GEN y) pari_err_OP(const char *op, GEN x, GEN y) @eprog\noindent As \kbd{e\_TYPE2}, replacing \kbd{forbidden} by \kbd{inconsistent}. \subsubsec{e\_PRIORITY} object $o$ in function $s$ contains variables whose priority is incompatible with the expected operation. E.g.~\kbd{Pol([x,1], 'y)}: this raises an error because it's not possible to create a polynomial whose coefficients involve variables with higher priority than the main variable. \bprog pari_err(e_PRIORITY, const char *s, GEN o, const char *op, long v) pari_err_PRIORITY(const char *s, GEN o, const char *op, long v) @eprog\noindent prints the error message: \kbd{incorrect priority in $s$, variable $v_o$ \var{op} $v$}, were $v_o$ is \kbd{gvar(o)}. \subsubsec{e\_SYNTAX} Syntax error, generated by the PARI parser. \bprog pari_err(e_SYNTAX, const char *msg, const char *e, const char *entry) @eprog\noindent where \kbd{msg} is a complete error message, and \kbd{e} and \kbd{entry} point into the \emph{same} character string, which is the input that was incorrectly parsed: \kbd{e} points to the character where the parser failed, and $\kbd{entry}\leq \kbd{e}$ points somewhat before. \noindent Prints the error message: \kbd{msg}, followed by a colon, then a part of the input character string (in general \kbd{entry} itself, but an initial segment may be truncated if $\kbd{e}-\kbd{entry}$ is large); a caret points at \kbd{e}, indicating where the error took place. \subsubsec{e\_TYPE} An argument $x$ of function $s$ had an unexpected type. (As in \kbd{factor("blah")}.) \bprog pari_err(e_TYPE, const char *s, GEN x) pari_err_TYPE(const char *s, GEN x) @eprog\noindent prints the error message: \kbd{incorrect type in $s$ (\typ{$x$})}, where \typ{$x$} is the type of $x$. \subsubsec{e\_TYPE2} Forbidden operation between two objects than cannot be typecast to a sensible common domain, because their types do not match up. (As in \kbd{Mod(1,2) + Pi}.) \bprog pari_err(e_TYPE2, const char *op, GEN x, GEN y) pari_err_TYPE2(const char *op, GEN x, GEN y) @eprog\noindent prints the error message: \kbd{forbidden} $s$ \typ{$x$} \var{op} \typ{$y$}, where \typ{$z$} denotes the type of $z$. Here, $s$ denotes the spelled out name of the operator $\var{op}\in\{\kbd{+}, \kbd{*}, \kbd{/}, \kbd{\%}, \kbd{=}\}$, e.g. \emph{addition} for \kbd{"+"} or \emph{assignment} for \kbd{"="}. If \var{op} is not in the above operator, list, it is taken to be the already spelled out name of a function, e.g. \kbd{"gcd"}, and the error message becomes \kbd{forbidden} \var{op} \typ{$x$}, \typ{$y$}. \subsubsec{e\_VAR} polynomials $x$ and $y$ submitted to function $s$ have inconsistent variables. E.g., considering the algebraic number \kbd{Mod(t,t\pow2+1)} in \kbd{nfinit(x\pow2+1)}. \bprog pari_err(e_VAR, const char *s, GEN x, GEN y) pari_err_VAR(const char *s, GEN x, GEN y) @eprog\noindent prints the error message: \kbd{inconsistent variables in $s$ $X$ != $Y$}, where $X$ and $Y$ are the names of the variables of $x$ and $y$, respectively. \subsec{Overflows} \subsubsec{e\_COMPONENT} Trying to access an inexistent component of a vector/matrix/list: the index is less than $1$ or greater than the allowed length. \bprog pari_err(e_COMPONENT, const char *f, const char *op, GEN lim, GEN x) pari_err_COMPONENT(const char *f, const char *op, GEN lim, GEN x) @eprog\noindent prints the error message: \kbd{nonexistent component in $f$: index \var{op} \var{lim}}. Special case: if $f$ is the empty string (no meaningful public function name can be used), we ignore it and print the message: \kbd{nonexistent component: index \var{op} \var{lim}}. \subsubsec{e\_DOMAIN} An argument $x$ is not in the function's domain (as in \kbd{moebius(0)} or \kbd{zeta(1)}). \bprog pari_err(e_DOMAIN, char *f, char *v, char *op, GEN lim, GEN x) pari_err_DOMAIN(char *f, char *v, char *op, GEN lim, GEN x) @eprog\noindent prints the error message: \kbd{domain error in $f$: $v$ \var{op} \var{lim}}. Special case: if \var{op} is the empty string, we ignore \var{lim} and print the error message: \kbd{domain error in $f$: $v$ out of range}. \subsubsec{e\_MAXPRIME} A function using the precomputed list of prime numbers ran out of primes. \bprog pari_err(e_MAXPRIME, ulong c) pari_err_MAXPRIME(ulong c) @eprog\noindent prints the error message: \kbd{not enough precomputed primes, need primelimit \til $c$} if $c$ is nonzero. And simply \kbd{not enough precomputed primes} otherwise. \subsubsec{e\_MEM} A call to \tet{pari_malloc} or \tet{pari_realloc} failed. \bprog pari_err(e_MEM) @eprog\noindent prints the error message: \kbd{not enough memory}. \subsubsec{e\_OVERFLOW} An object in function $s$ becomes too large to be represented within PARI's hardcoded limits. (As in \kbd{2\pow2\pow2\pow10} or \kbd{exp(1e100)}, which overflow in \kbd{lg} and \kbd{expo}.) \bprog pari_err(e_OVERFLOW, const char *s) pari_err_OVERFLOW(const char *s) @eprog\noindent prints the error message: \kbd{overflow in $s$}. \subsubsec{e\_PREC} Function $s$ fails because input accuracy is too low. (As in \kbd{floor(1e100)} at default accuracy.) \bprog pari_err(e_PREC, const char *s) pari_err_PREC(const char *s) @eprog\noindent prints the error message: \kbd{precision too low in $s$}. \subsubsec{e\_STACK} The PARI stack overflows. \bprog pari_err(e_STACK) @eprog\noindent prints the error message: \kbd{the PARI stack overflows !} as well as some statistics concerning stack usage. \subsec{Errors triggered intentionally} \subsubsec{e\_ALARM} A timeout, generated by the \tet{alarm} function. \bprog pari_err(e_ALARM, const char *fmt, ...) @eprog\noindent prints the error message: $s$. \subsubsec{e\_USER} A user error, as triggered by \tet{error}($g_1,\dots,g_n)$ in GP. \bprog pari_err(e_USER, GEN g) @eprog\noindent prints the error message: \kbd{user error:}, then the entries of the vector $g$. \subsec{Mathematical errors} \subsubsec{e\_CONSTPOL} An argument of function $s$ is a constant polynomial, which does not make sense. (As in \kbd{galoisinit(Pol(1))}.) \bprog pari_err(e_CONSTPOL, const char *s) pari_err_CONSTPOL(const char *s) @eprog\noindent prints the error message: \kbd{constant polynomial in $s$}. \subsubsec{e\_COPRIME} Function $s$ expected two coprime arguments, and did receive $x$, $y$ which were not. \bprog pari_err(e_COPRIME, const char *s, GEN x, GEN y) pari_err_COPRIME(const char *s, GEN x, GEN y) @eprog\noindent prints the error message: \kbd{elements not coprime in $s$: $x, y$}. \subsubsec{e\_INV} Tried to invert a noninvertible object $x$. \bprog pari_err(e_INV, const char *s, GEN x) pari_err_INV(const char *s, GEN x) @eprog\noindent prints the error message: \kbd{impossible inverse in $s$: $x$}. If $x = \kbd{Mod}(a,b)$ is a \typ{INTMOD} and $a$ is not $0$ mod $b$, this allows to factor the modulus, as \kbd{gcd}$(a,b)$ is a nontrivial divisor of $b$. \subsubsec{e\_IRREDPOL} Function $s$ expected an irreducible polynomial, and did not receive one. (As in \kbd{nfinit(x\pow2-1)}.) \bprog pari_err(e_IRREDPOL, const char *s, GEN x) pari_err_IRREDPOL(const char *s, GEN x) @eprog\noindent prints the error message: \kbd{not an irreducible polynomial in $s$: $x$}. \subsubsec{e\_MISC} Generic uncategorized error. \bprog pari_err(e_MISC, const char *fmt, ...) @eprog\noindent prints the error message: $s$. \subsubsec{e\_MODULUS} moduli $x$ and $y$ submitted to function $s$ are inconsistent. E.g., considering the algebraic number \kbd{Mod(t,t\pow2+1)} in \kbd{nfinit(t\pow3-2)}. \bprog pari_err(e_MODULUS, const char *s, GEN x, GEN y) pari_err_MODULUS(const char *s, GEN x, GEN y) @eprog\noindent prints the error message: \kbd{inconsistent moduli in $s$}, then the moduli. \subsubsec{e\_PRIME} Function $s$ expected a prime number, and did receive $p$, which was not. (As in \kbd{idealprimedec(nf, 4)}.) \bprog pari_err(e_PRIME, const char *s, GEN x) pari_err_PRIME(const char *s, GEN x) @eprog\noindent prints the error message: \kbd{not a prime in $s$: $x$}. \subsubsec{e\_ROOTS0} An argument of function $s$ is a zero polynomial, and we need to consider its roots. (As in \kbd{polroots(0)}.) \bprog pari_err(e_ROOTS0, const char *s) pari_err_ROOTS0(const char *s) @eprog\noindent prints the error message: \kbd{zero polynomial in $s$}. \subsubsec{e\_SQRTN} Tried to compute an $n$-th root of $x$, which does not exist, in function $s$. (As in \kbd{sqrt(Mod(-1,3))}.) \bprog pari_err(e_SQRTN, GEN x) pari_err_SQRTN(GEN x) @eprog\noindent prints the error message: \kbd{not an n-th power residue in $s$: $x$}. \subsec{Miscellaneous functions} \fun{long}{name_numerr}{const char *s} return the error number corresponding to an error name. E.g. \kbd{name\_numerr("e\_DIM")} returns \kbd{e\_DIM}. \fun{const char*}{numerr_name}{long errnum} returns the error name corresponding to an error number. E.g. \kbd{name\_numerr(e\_DIM)} returns \kbd{"e\_DIM"}. \fun{char*}{pari_err2str}{GEN err} returns the error message that would be printed on \typ{ERROR} \kbd{err}. The name is allocated on the PARI stack and must not be freed. \fun{int}{pari_err_display}{GEN err} displays the error message corresponding to \kbd{err}. Always return $0$. Default value of the callback \tet{cb_pari_err_handle}. \section{Hashtables} A \tet{hashtable}, or associative array, is a set of pairs $(k,v)$ of keys and values. PARI implements general extensible hashtables for fast data retrieval: when creating a table, we may either choose to use the PARI stack, or \kbd{malloc} so as to be stack-independent. A hashtable is implemented as a table of linked lists, each list containing all entries sharing the same hash value. The table length is a prime number, which roughly doubles as the table overflows by gaining new entries; both the current number of entries and the threshold before the table grows are stored in the table. Finally the table remembers the functions used to hash the entries's keys and to test for equality two entries hashed to the same value. An entry, or \tet{hashentry}, contains \item a key/value pair $(k,v)$, both of type \kbd{void*} for maximal flexibility, \item the hash value of the key, for the table hash function. This hash is mapped to a table index (by reduction modulo the table length), but it contains more information, and is used to bypass costly general equality tests if possible, \item a link pointer to the next entry sharing the same table cell. \bprog typedef struct { void *key, *val; ulong hash; /* hash(key) */ struct hashentry *next; } hashentry; typedef struct { ulong len; /* table length */ hashentry **table; /* the table */ ulong nb, maxnb; /* number of entries stored and max nb before enlarging */ ulong pindex; /* prime index */ ulong (*hash) (void *k); /* hash function */ int (*eq) (void *k1, void *k2); /* equality test */ int use_stack; /* use the PARI stack, resp. malloc */ } hashtable; @eprog\noindent \fun{hashtable*}{hash_create}{size, hash, eq, use_stack} \vskip -0.5em % switch to K&R style to avoid atrocious line break \bprog ulong size; ulong (*hash)(void*); int (*eq)(void*,void*); int use_stack; @eprog\noindent creates a hashtable with enough room to contain \kbd{size} entries. The functions \kbd{hash} and \kbd{eq} compute the hash value of keys and test keys for equality, respectively. If \kbd{use\_stack} is non zero, the resulting table will use the PARI stack; otherwise, we use \kbd{malloc}. \fun{hashtable*}{hash_create_ulong}{ulong size, long stack} special case when the keys are \kbd{ulongs} with ordinary equality test. \fun{hashtable*}{hash_create_str}{ulong size, long stack} special case when the keys are character strings with string equality test (and \tet{hash_str} hash function). \fun{void}{hash_init}{hashtable *h, ulong size, ulong (*hash)(void*), int (*eq)(void*,void*), use_stack} Initialize \kbd{h} for an hashtable with enough room to contain \kbd{size} entries of type \kbd{void*}. The functions \kbd{eq} test keys for equality. If \kbd{use\_stack} is non zero, the resulting table will use the PARI stack; otherwise, we use \kbd{malloc}. \fun{void}{hash_init_GEN}{hashtable *h, ulong size, int (*eq)(GEN,GEN), use_stack} Initialize \kbd{h} for an hashtable with enough room to contain \kbd{size} entries of type \kbd{GEN}. The functions \kbd{eq} test keys for equality. If \kbd{use\_stack} is non zero, the resulting table will use the PARI stack; otherwise, we use \kbd{malloc}. The hash used is \kbd{hash\_GEN}. \fun{void}{hash_init_ulong}{hashtable *h, ulong size, use_stack} Initialize \kbd{h} for an hashtable with enough room to contain \kbd{size} entries of type \kbd{ulong}. If \kbd{use\_stack} is non zero, the resulting table will use the PARI stack; otherwise, we use \kbd{malloc}. \fun{void}{hash_insert}{hashtable *h, void *k, void *v} inserts $(k,v)$ in hashtable $h$. No copy is made: $k$ and $v$ themselves are stored. The implementation does not prevent one to insert two entries with equal keys $k$, but which of the two is affected by later commands is undefined. \fun{void}{hash_insert2}{hashtable *h, void *k, void *v, ulong hash} as \kbd{hash\_insert}, assuming \kbd{h->hash(k)} is \kbd{hash}. \fun{void}{hash_insert_long}{hashtable *h, void *k, long v} as \kbd{hash\_insert} but \kbd{v} is a \kbd{long}. \fun{hashentry*}{hash_search}{hashtable *h, void *k} look for an entry with key $k$ in $h$. Return it if it one exists, and \kbd{NULL} if not. \fun{hashentry*}{hash_search2}{hashtable *h, void *k, ulong hash} as \kbd{hash\_search} assuming \kbd{h->hash(k)} is \kbd{hash}. \fun{GEN}{hash_haskey_GEN}{hashtable *h, void *k} returns the associate value if the key $k$ belongs to the hash, otherwise returns \kbd{NULL}. \fun{int}{hash_haskey_long}{hashtable *h, void *k, long *v} returns $1$ if the key $k$ belongs to the hash and set $v$ to its value, otherwise returns 0. \fun{hashentry *}{hash_select}{hashtable *h, void *k, void *E, int (*select)(void *, hashentry *)} variant of \tet{hash_search}, useful when entries with identical keys are inserted: among the entries attached to key $k$, return one satisfying the selection criterion (such that \kbd{select(E,e)} is nonzero), or \kbd{NULL} if none exist. \fun{hashentry*}{hash_remove}{hashtable *h, void *k} deletes an entry $(k,v)$ with key $k$ from $h$ and return it. (Return \kbd{NULL} if none was found.) Only the linking structures are freed, memory attached to $k$ and $v$ is not reclaimed. \fun{hashentry*}{hash_remove_select}{hashtable *h, void *k, void *E, int(*select)(void*, hashentry *)} a variant of \tet{hash_remove}, useful when entries with identical keys are inserted: among the entries attached to key $k$, return one satisfying the selection criterion (such that \kbd{select(E,e)} is nonzero) and delete it, or \kbd{NULL} if none exist. Only the linking structures are freed, memory attached to $k$ and $v$ is not reclaimed. \fun{GEN}{hash_keys}{hashtable *h} return in a \typ{VECSMALL} the keys stored in hashtable $h$. \fun{GEN}{hash_keys_GEN}{hashtable *h} return in a \typ{VEC} the keys stored in hashtable $h$ (which are assumed to be \kbd{GEN}s). \fun{GEN}{hash_values}{hashtable *h} return in a \typ{VECSMALL} the values stored in hashtable $h$. \fun{void}{hash_destroy}{hashtable *h} deletes the hashtable, by removing all entries. \fun{void}{hash_dbg}{hashtable *h} print statistics for hashtable $h$, allows to evaluate the attached hash function performance on actual data. Some interesting hash functions are available: \fun{ulong}{hash_str}{const char *s} \fun{ulong}{hash_str_len}{const char *s, long len} hash the prefix string containing the first \kbd{len} characters (assume $\kbd{strlen}(s) \geq \kbd{len}$). \fun{ulong}{hash_GEN}{GEN x} generic hash function. \fun{ulong}{hash_zv}{GEN x} hash a \typ{VECSMALL}. \section{Dynamic arrays} A \teb{dynamic array} is a generic way to manage stacks of data that need to grow dynamically. It allocates memory using \kbd{pari\_malloc}, and is independent of the PARI stack; it even works before the \kbd{pari\_init} call. \subsec{Initialization} To create a stack of objects of type \kbd{foo}, we proceed as follows: \bprog foo *t_foo; pari_stack s_foo; pari_stack_init(&s_foo, sizeof(*t_foo), (void**)&t_foo); @eprog\noindent Think of \kbd{s\_foo} as the controlling interface, and \kbd{t\_foo} as the (dynamic) array tied to it. The value of \kbd{t\_foo} may be changed as you add more elements. \subsec{Adding elements} The following function pushes an element on the stack. \bprog /* access globals t_foo and s_foo */ void push_foo(foo x) { long n = pari_stack_new(&s_foo); t_foo[n] = x; } @eprog \subsec{Accessing elements} Elements are accessed naturally through the \kbd{t\_foo} pointer. For example this function swaps two elements: \bprog void swapfoo(long a, long b) { foo x; if (a > s_foo.n || b > s_foo.n) pari_err_BUG("swapfoo"); x = t_foo[a]; t_foo[a] = t_foo[b]; t_foo[b] = x; } @eprog \subsec{Stack of stacks} Changing the address of \kbd{t\_foo} is not supported in general. In particular \kbd{realloc()}'ed array of stacks and stack of stacks are not supported. \subsec{Public interface} Let \kbd{s} be a \kbd{pari\_stack} and \kbd{data} the data linked to it. The following public fields are defined: \item \kbd{s.alloc} is the number of elements allocated for \kbd{data}. \item \kbd{s.n} is the number of elements in the stack and \kbd{data[s.n-1]} is the topmost element of the stack. \kbd{s.n} can be changed as long as $0\leq\kbd{s.n}\leq\kbd{s.alloc}$ holds. \fun{void}{pari_stack_init}{pari_stack *s, size_t size, void **data} links \kbd{*s} to the data pointer \kbd{*data}, where \kbd{size} is the size of data element. The pointer \kbd{*data} is set to \kbd{NULL}, \kbd{s->n} and \kbd{s->alloc} are set to $0$: the array is empty. \fun{void}{pari_stack_alloc}{pari_stack *s, long nb} makes room for \kbd{nb} more elements, i.e.~makes sure that $\kbd{s.alloc}\geq\kbd{s.n} + \kbd{nb}$, possibly reallocating \kbd{data}. \fun{long}{pari_stack_new}{pari_stack *s} increases \kbd{s.n} by one unit, possibly reallocating \kbd{data}, and returns $\kbd{s.n}-1$. \misctitle{Caveat} The following construction is incorrect because \kbd{stack\_new} can change the value of \kbd{t\_foo}: \bprog t_foo[ pari_stack_new(&s_foo) ] = x; @eprog \fun{void}{pari_stack_delete}{pari_stack *s} frees \kbd{data} and resets the stack to the state immediately following \kbd{stack\_init} (\kbd{s->n} and \kbd{s->alloc} are set to $0$). \fun{void *}{pari_stack_pushp}{pari_stack *s, void *u} This function assumes that \kbd{*data} is of pointer type. Pushes the element \kbd{u} on the stack \kbd{s}. \fun{void **}{pari_stack_base}{pari_stack *s} returns the address of \kbd{data}, typecast to a \kbd{void **}. \section{Vectors and Matrices} \subsec{Access and extract} See~\secref{se:clean} and~\secref{se:unclean} for various useful constructors. Coefficients are accessed and set using \tet{gel}, \tet{gcoeff}, see~\secref{se:accessors}. There are many internal functions to extract or manipulate subvectors or submatrices but, like the accessors above, none of them are suitable for \tet{gerepileupto}. Worse, there are no type verification, nor bound checking, so use at your own risk. \fun{GEN}{shallowcopy}{GEN x} returns a \kbd{GEN} whose components are the components of $x$ (no copy is made). The result may now be used to compute in place without destroying $x$. This is essentially equivalent to \bprog GEN y = cgetg(lg(x), typ(x)); for (i = 1; i < lg(x); i++) y[i] = x[i]; return y; @eprog\noindent except that \typ{MAT} is treated specially since shallow copies of all columns are made. The function also works for nonrecursive 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}, \typ{COL} or \typ{LIST}, concatenate its elements from left to right. Shallow version of \kbd{gconcat1}. \fun{GEN}{shallowmatconcat}{GEN v} shallow version of \kbd{matconcat}. \fun{GEN}{shallowextract}{GEN x, GEN y} extract components of the vector or matrix $x$ according to the selection parameter $y$. This is the shallow analog of \kbd{extract0(x, y, NULL)}, see \tet{vecextract}. \kbdsidx{extract0} \fun{GEN}{RgV_F2v_extract_shallow}{GEN V, GEN x} extract components of the vector $V$ whose indices corresponds to non-zero components of $x$. Shallow function. \fun{GEN}{shallowmatextract}{GEN M, GEN l1, GEN l2} extract components of the matrix $M$ according to the \typ{VECSMALL} $l1$ (list of lines indices) and $l2$ (list of columns indices). This is the shallow analog of \kbd{extract0(x, l1, l2)}, 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}{matslice}{GEN A, long a, long b, long c, long d} returns the submatrix $A[a..b,c..d]$. Assume $a \leq b$ and $c \leq d$. \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}{rowsplice}{GEN A, long i} return the \typ{MAT} formed from the coefficients of \typ{MAT} $A$ with $j$-th row removed. \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{VECSMALL}, \typ{VEC}, \typ{COL} or \typ{MAT}). Assume $j_1 \leq j_2$ or $j_2 = j_1 - 1$ (return empty vector/matrix). \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}{veclast}{GEN A} return the last entry of $A$ (\typ{VEC}, \typ{COL}) or last column of $A$ (\typ{MAT}). Shallow, undefined if \kbd{lg(A)} is $1$. \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{void}{vecreverse_inplace}{GEN A} as \kbd{vecreverse}, but reverse $A$ in place. \fun{GEN}{vecpermute}{GEN A, GEN p} $p$ is a \typ{VECSMALL} representing a list $[p_1,\dots,p_n]$ of indices. Returns a \kbd{GEN} which has the same type as $A$ (\typ{VEC}, \typ{COL} or \typ{MAT}), and whose components are $A[p_1],\dots,A[p_n]$. If $A$ is a \typ{MAT}, these are the \emph{columns} of $A$. \fun{GEN}{vecsmallpermute}{GEN A, GEN p} as \kbd{vecpermute} when \kbd{A} is a \typ{VECSMALL}. \fun{GEN}{vecslicepermute}{GEN A, GEN p, long y1, long y2} short for \bprog vecslice(vecpermute(A,p), y1, y2) @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}{vecsqr}{GEN a} returns the vector whose $i$-th component is \kbd{gsqr}$(a[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])$. \fun{GEN}{vecmoduu}{GEN a, GEN b}. Assuming $a$ and $b$ are two \typ{VECSMALL} of the same length, returns the vector whose $i$-th component is $a[i]~\kbd{\%}~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_append}{GEN V, GEN s} append \kbd{s} to the vector \kbd{V}. \fun{GEN}{vec_prepend}{GEN V, GEN s} prepend \kbd{s} to the vector \kbd{V}. \fun{GEN}{vec_shorten}{GEN v, long n} shortens the vector \kbd{v} to \kbd{n} components. \fun{GEN}{vec_lengthen}{GEN v, long n} lengthens the vector \kbd{v} to \kbd{n} components. The extra components are not initialized. \fun{GEN}{vec_insert}{GEN v, long n, GEN x} inserts $x$ at position $n$ in the vector $v$. \fun{GEN}{vec_equiv}{GEN O} given a vector of objects $O$, return a vector with $n$ components where $n$ is the number of distinct objects in $O$. The $i$-th component is a \typ{VECSMALL} containing the indices of the elements in $O$ having the same value. Applied to the image of a function evaluated on some finite set, it computes the fibers of the function. \fun{GEN}{vec_reduce}{GEN O, GEN *pE} given a vector of objects $O$, return the vector $v$ (of the same type as $O$) of \emph{distinct} elements of $O$ and set a \typ{VECSMALL} $E$ with the same length as $v$, such that $E[i]$ is the multiplicity of object $v[i]$ in the original $O$. Shallow function. \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_to_vec_inplace}{GEN z} apply \kbd{stoi} to all entries of $z$ and set its type to \typ{VEC}. \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} (merge sort). \fun{void}{vecsmall_sort}{GEN v} sorts the \typ{VECSMALL} \kbd{v} in place (merge sort). \fun{GEN}{vecsmall_reverse}{GEN v} as \kbd{vecreverse} for a \typ{VECSMALL} \kbd{v}. \fun{long}{vecsmall_max}{GEN v} returns the maximum of the elements of \typ{VECSMALL} \kbd{v}, assumed nonempty. \fun{long}{vecsmall_indexmax}{GEN v} returns the index of the largest element of \typ{VECSMALL} \kbd{v}, assumed nonempty. \fun{long}{vecsmall_min}{GEN v} returns the minimum of the elements of \typ{VECSMALL} \kbd{v}, assumed nonempty. \fun{long}{vecsmall_indexmin}{GEN v} returns the index of the smallest element of \typ{VECSMALL} \kbd{v}, assumed nonempty. \fun{int}{vecsmall_isconst}{GEN v} Returns 1 if all the components of \kbd{v} are equal, else returns 0. \fun{int}{vecsmall_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{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. \fun{GEN}{vecsmall_prod}{GEN v} given a \typ{VECSMALL} \kbd{v}, return the product of its entries. The following sorting functions assume all entries of the \typ{VECSMALL} $v$ satisfy $0 \leq v[i] \leq M$ and use a counting sort, in linear time $O(\#v + M)$: \fun{void}{vecsmall_counting_sort}{GEN v, long M} sorts the \typ{VECSMALL} \kbd{v} in place. \fun{GEN}{vecsmall_counting_indexsort}{GEN v, long M} as \kbd{vecsmall\_indexsort} using a counting sort. \fun{GEN}{vecsmall_counting_uniq}{GEN v, long M} as \kbd{vecsmall\_uniq} using a counting sort. \subsec{Vectors of \typ{VECSMALL}} These functions manipulate vectors of \typ{VECSMALL} (vecvecsmall). \fun{GEN}{vecvecsmall_sort}{GEN x} sorts lexicographically the components of the vector \kbd{x}. \fun{GEN}{vecvecsmall_sort_shallow}{GEN x}, shallow variant of \kbd{vecvecsmall\_sort}. \fun{void}{vecvecsmall_sort_inplace}{GEN x, GEN *perm} sort lexicographically \kbd{x} in place, without copying its components. If \kbd{perm} is not \kbd{NULL}, it is set to the permutation that would sort the original \kbd{x}. \fun{GEN}{vecvecsmall_sort_uniq}{GEN x} sorts lexicographically the components of the vector \kbd{x}, removing duplicates entries. \fun{GEN}{vecvecsmall_indexsort}{GEN x} performs an indirect lexicographic sorting of the components of the vector \kbd{x} and return a permutation stored in a \typ{VECSMALL}. \fun{long}{vecvecsmall_search}{GEN x, GEN y} \kbd{x} being a sorted vecvecsmall and \kbd{y} a \typ{VECSMALL}, search \kbd{y} inside \kbd{x}. \fun{GEN}{vecvecsmall_max}{GEN x} returns the largest entry in all $x[i]$, assumed nonempty. Shallow function. \newpage \chapter{Functions related to the GP interpreter} \section{Handling closures}\label{se:closure} \subsec{Functions to evaluate \typ{CLOSURE}} \fun{void}{closure_disassemble}{GEN C} print the \typ{CLOSURE} \kbd{C} in GP assembly format. \fun{GEN}{closure_callgenall}{GEN C, long n, ...} evaluate the \typ{CLOSURE} \kbd{C} with the \kbd{n} arguments (of type \kbd{GEN}) following \kbd{n} in the function call. Assumes \kbd{C} has arity $\geq \kbd{n}$. \fun{GEN}{closure_callgenvec}{GEN C, GEN args} evaluate the \typ{CLOSURE} \kbd{C} with the arguments supplied in the vector \kbd{args}. Assumes \kbd{C} has arity $\geq \kbd{lg(args)-1}$. \fun{GEN}{closure_callgenvecprec}{GEN C, GEN args, long prec} as \kbd{closure\_callgenvec} but set the precision locally to \kbd{prec}. \fun{GEN}{closure_callgenvecdef}{GEN C, GEN args, GEN def} evaluate the \typ{CLOSURE} \kbd{C} with the arguments supplied in the vector \kbd{args}, where the \typ{VECSMALL} \kbd{def} indicates which arguments are actually present. Assumes \kbd{C} has arity $\geq \kbd{lg(args)-1}$. \fun{GEN}{closure_callgenvecdefprec}{GEN C, GEN args, GEN def, long prec} as \kbd{closure\_callgenvecdef} but set the precision locally to \kbd{prec}. \fun{GEN}{closure_callgen0}{GEN C, long prec} evaluate the \typ{CLOSURE} \kbd{C} without arguments. \fun{GEN}{closure_callgen0prec}{GEN C, long prec} evaluate the \typ{CLOSURE} \kbd{C} without arguments, but set the precision locally to \kbd{prec}. \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_callgen1prec}{GEN C, GEN x, long prec} as \kbd{closure\_callgen1}, but set the precision locally to \kbd{prec}. \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 nonzero value if a flow change occurred. This variant is not stack clean. Used by the break loop. \fun{GEN}{closure_trapgen}{long numerr, GEN code} evaluates closure, while trapping error \kbd{numerr}. Return \kbd{(GEN)1L} if error trapped, and the result otherwise, or \kbd{NULL} if a flow change occurred. Used by trap. \subsec{Functions to handle control flow changes} \fun{long}{loop_break}{void} processes an eventual flow changes inside an iterator. If this function return $1$, the iterator should stop. \subsec{Functions to deal with lexical local variables}\label{se:pushlex} Function using the prototype code \kbd{`V'} need to manually create and delete a lexical variable for each code \kbd{`V'}, which will be given a number $-1, -2, \ldots$. \fun{void}{push_lex}{GEN a, GEN code} creates a new lexical variable whose initial value is $a$ on the top of the stack. This variable get the number $-1$, and the number of the other variables is decreased by one unit. When the first variable of a closure is created, the argument \kbd{code} must be the closure that references this lexical variable. The argument \kbd{code} must be \kbd{NULL} for all subsequent variables (if any). (The closure contains the debugging data for the variable). \fun{void}{pop_lex}{long n} deletes the $n$ topmost lexical variables, increasing the number of other variables by $n$. The argument $n$ must match the number of variables allocated through \kbd{push\_lex}. \fun{GEN}{get_lex}{long vn} get the value of the variable with number \kbd{vn}. \fun{void}{set_lex}{long vn, GEN x} set the value of the variable with number \kbd{vn}. \subsec{Functions returning new closures} \fun{GEN}{compile_str}{const char *s} returns the closure corresponding to the GP expression $s$. \fun{GEN}{closure_deriv}{GEN code} returns a closure corresponding to the numerical derivative of the closure \kbd{code}. \fun{GEN}{closure_derivn}{GEN code, long n} returns a closure corresponding to the numerical derivative of order $n > 0$ 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. Shallow function. \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$. This is analogous to \kbd{snm\_closure(isentry(str), mkvecn(...))} but the latter has lower overhead since it does not copy arguments, nor does it validate inputs. 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}{long level} prints a backtrace of the last $20$ stack frames, starting at frame \kbd{level}, the numbering starting at $0$. \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} These 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{GEN}{gp_evalprec}{void *E, GEN x, long prec} as \kbd{gp\_eval}, but set the precision locally to \kbd{prec}. \fun{long}{gp_evalvoid}{void *E, GEN x} is used for the prototype code \kbd{`I'}. The resulting value is discarded. Return a nonzero value if a control-flow instruction request the iterator to terminate immediately. \fun{long}{gp_evalbool}{void *E, GEN x} returns the boolean \kbd{gp\_eval(E, x)} evaluates to (i.e. true iff the value is nonzero). \fun{GEN}{gp_evalupto}{void *E, GEN x} memory-safe version of \kbd{gp\_eval}, \kbd{gcopy}-ing the result, when the evaluator returns components of previously allocated objects (e.g. member functions). \subsubsec{Standard wrappers for true closures} These wrappers are used to implement GP functions taking true closures as input. \fun{GEN}{gp_call}{void *E, GEN x} evaluates the closure \kbd{(GEN)E} on $x$. \fun{GEN}{gp_callprec}{void *E, GEN x, long prec} as \kbd{gp\_call}, but set the precision locally to \kbd{prec}. \fun{GEN}{gp_call2}{void *E, GEN x, GEN y} evaluates the closure \kbd{(GEN)E} on $(x,y)$. \fun{long}{gp_callbool}{void *E, GEN x} evaluates the closure \kbd{(GEN)E} on $x$, returns \kbd{1} if its result is nonzero, 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 nonzero value if a control-flow instruction request the iterator to terminate immediately. \section{Defaults} \fun{entree*}{pari_is_default}{const char *s} return the \kbd{entree} structure attached to $s$ if it is the name of a default, \kbd{NULL} otherwise. \fun{GEN}{setdefault}{const char *s, const char *v, long flag} is the low-level function underlying \kbd{default0}. If $s$ is \kbd{NULL}, call all 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_breakloop}{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_echo}{const char *v, long flag} \fun{GEN}{sd_factor_add_primes}{const char *v, long flag} \fun{GEN}{sd_factor_proven}{const char *v, long flag} \fun{GEN}{sd_factorlimit}{const char *v, long flag} \fun{GEN}{sd_format}{const char *v, long flag} \fun{GEN}{sd_graphcolormap}{const char *v, long flag} \fun{GEN}{sd_graphcolors}{const char *v, long flag} \fun{GEN}{sd_help}{const char *v, long flag} \fun{GEN}{sd_histfile}{const char *v, long flag} \fun{GEN}{sd_histsize}{const char *v, long flag} \fun{GEN}{sd_lines}{const char *v, long flag} \fun{GEN}{sd_linewrap}{const char *v, long flag} \fun{GEN}{sd_log}{const char *v, long flag} \fun{GEN}{sd_logfile}{const char *v, long flag} \fun{GEN}{sd_nbthreads}{const char *v, long flag} \fun{GEN}{sd_new_galois_format}{const char *v, long flag} \fun{GEN}{sd_output}{const char *v, long flag} \fun{GEN}{sd_parisize}{const char *v, long flag} \fun{GEN}{sd_parisizemax}{const char *v, long flag} \fun{GEN}{sd_path}{const char *v, long flag} \fun{GEN}{sd_plothsizes}{const char *v, long flag} \fun{GEN}{sd_prettyprinter}{const char *v, long flag} \fun{GEN}{sd_primelimit}{const char *v, long flag} \fun{GEN}{sd_prompt}{const char *v, long flag} \fun{GEN}{sd_prompt_cont}{const char *v, long flag} \fun{GEN}{sd_psfile}{const char *v, long flag} The \kbd{psfile} default is obsolete, don't use this function. \fun{GEN}{sd_readline}{const char *v, long flag} \fun{GEN}{sd_realbitprecision}{const char *v, long flag} \fun{GEN}{sd_realprecision}{const char *v, long flag} \fun{GEN}{sd_recover}{const char *v, long flag} \fun{GEN}{sd_secure}{const char *v, long flag} \fun{GEN}{sd_seriesprecision}{const char *v, long flag} \fun{GEN}{sd_simplify}{const char *v, long flag} \fun{GEN}{sd_sopath}{const char *v, int flag} \fun{GEN}{sd_strictargs}{const char *v, long flag} \fun{GEN}{sd_strictmatch}{const char *v, long flag} \fun{GEN}{sd_timer}{const char *v, long flag} \fun{GEN}{sd_threadsize}{const char *v, long flag} \fun{GEN}{sd_threadsizemax}{const char *v, long flag} \noindent Generic functions used to implement defaults: most of the above routines are implemented in terms of the following generic ones. In all routines below \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 nonempty). 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 nonempty). \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 attached to the value $i$ of the default. The last entry in the \kbd{msg} array is used as a message attached to all subsequent ones. The exact behavior and return value depends on \kbd{flag}: \item \tet{d_RETURN}: returns the new value, as a \kbd{GEN}. \item \tet{d_ACKNOWLEDGE}: prints a message indicating the new value, possibly a message attached to it via the \kbd{msg} argument, and return \kbd{gnil}. \item other cases: print nothing and return \kbd{gnil}. \fun{GEN}{sd_intarray}{const char *v, long flag, const char *s, GEN *pz} \item records a \typ{VECSMALL} array of nonnegative integers. \item \kbd{pz} points to the current \typ{VECSMALL} value, and is set to the new value (when \kbd{v} is nonempty). The exact return value depends on \kbd{flag}: \item \tet{d_RETURN}: returns the new value, as a \typ{VEC} (converted via \kbd{zv\_to\_ZV}) \item \tet{d_ACKNOWLEDGE}: prints a message indicating the new value, (as a \typ{VEC}) 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 nonempty). \section{Records and Lazy vectors} The functions in this section are used to implement \kbd{ell} structures and analogous objects, which are vectors some of whose components are initialized to dummy values, later computed on demand. We start by initializing the structure: \fun{GEN}{obj_init}{long d, long n} returns an \tev{obj} $S$, a \typ{VEC} with $d$ regular components, accessed as \kbd{gel(S,1)}, \dots, \kbd{gel(S,d)}; together with a record of $n$ members, all initialized to $0$. The arguments $d$ and $n$ must be nonnegative. After \kbd{S = obj\_init(d, n)}, the prototype of our other functions are of the form \bprog GEN obj_do(GEN S, long tag, ...) @eprog\noindent The first argument $S$ holds the structure to be managed. The second argument \var{tag} is the index of the struct member (from $1$ to $n$) we operate on. We recommend to define an \kbd{enum} and use descriptive names instead of hardcoded numbers. For instance, if $n = 3$, after defining \bprog enum { TAG_p = 1, TAG_list, TAG_data }; @eprog\noindent one may use \kbd{TAG\_list} or $2$ indifferently as a tag. The former being preferred, of course. \misctitle{Technical note} In the current implementation, $S$ is a \typ{VEC} with $d+1$ entries. The first $d$ components are ordinary \typ{GEN} entries, which you can read or assign to in the customary way. But the last component $\kbd{gel(S, d+1)}$, a \typ{VEC} of length $n$ initialized to \kbd{zerovec}$(n)$, must be handled in a special way: you should never access or modify its components directly, only through the API we are about to describe. Indeed, its entries are meant to contain dynamic data, which will be stored, retrieved and replaced (for instance by a value computed to a higher accuracy), while interacting safely with intermediate \kbd{gerepile} calls. This mechanism allows to simulate C \kbd{struct}s, in a simpler way than with general hashtables, while remaining compatible with the GP language, which knows neither structs nor hashtables. It also serialize the structure in an ordinary \kbd{GEN}, which facilitates copies and garbage collection (use \kbd{gcopy} or \kbd{gerepile}), rather than having to deal with individual components of actual C \kbd{struct}s. \fun{GEN}{obj_reinit}{GEN S} make a shallow copy of $S$, re-initializing all dynamic components. This allows ``forking'' a lazy vector while avoiding both a memory leak, and storing pointers to the same data in different objects (with risks of a double free later). \fun{GEN}{obj_check}{GEN S, long tag} if the \emph{tag}-component in $S$ is non empty, return it. Otherwise return \kbd{NULL}. The \typ{INT} $0$ (initial value) is used as a sentinel to indicated an empty component. \fun{GEN}{obj_insert}{GEN S, long tag, GEN O} insert (a clone of) $O$ as \emph{tag}-component of $S$. Any previous value is deleted, and data pointing to it become invalid. \fun{GEN}{obj_insert_shallow}{GEN S, long K, GEN O} as \tet{obj_insert}, inserting $O$ as-is, not via a clone. \fun{GEN}{obj_checkbuild}{GEN S, long tag, GEN (*build)(GEN)} if the \emph{tag}-component of $S$ is non empty, return it. Otherwise insert (a clone of) \kbd{build(S)} as \emph{tag}-component in $S$, and return it. \fun{GEN}{obj_checkbuild_padicprec}{GEN S, long tag, GEN (*build)(GEN,long), long prec} if the \emph{tag}-component of $S$ is non empty \emph{and} has relative $p$-adic precision $\geq \kbd{prec}$, return it. Otherwise insert (a clone of) \kbd{build(S, prec)} as \emph{tag}-component in $S$, and return it. \fun{GEN}{obj_checkbuild_realprec}{GEN S, long tag, GEN (*build)(GEN, long), long prec} if the \emph{tag}-component of $S$ is non empty \emph{and} satisfies \kbd{gprecision} $\geq \kbd{prec}$, return it. Otherwise insert (a clone of) \kbd{build(S, prec)} as \emph{tag}-component in $S$, and return it. \fun{GEN}{obj_checkbuild_prec}{GEN S, long tag, GEN (*build)(GEN,long), GEN (*gpr)(GEN), long prec} if the \emph{tag}-component of $S$ is non empty \emph{and} has precision $\kbd{gpr}(x)\geq \kbd{prec}$, return it. Otherwise insert (a clone of) \kbd{build(S, prec)} as \emph{tag}-component in $S$, and return it. \fun{void}{obj_free}{GEN S} destroys all clones stored in the $n$ tagged components, and replace them by the initial value $0$. The regular entries of $S$ are unaffected, and $S$ remains a valid object. This is used to avoid memory leaks. pari-2.17.2/doc/paricfg.tex.in0000644000175000017500000000031314567450071014501 0ustar billbill\begingroup \catcode`\&=12 \catcode`\_=12 \catcode`\$=12 \catcode`\#=12 \catcode`\%=12 \catcode`\^=13 \catcode`\~=13 \gdef\vers{@version@} \gdef\includedir{@includedir@} \gdef\libdir{@libdir@} \endgroup pari-2.17.2/doc/usersch8.tex0000644000175000017500000004403514760123736014236 0ustar billbill% Copyright (c) 2015 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{$L$-functions} \section{Accessors} \fun{long}{is_linit}{GEN data} \fun{GEN}{ldata_get_an}{GEN ldata} \fun{GEN}{ldata_get_dual}{GEN ldata} \fun{long}{ldata_isreal}{GEN ldata} \fun{GEN}{ldata_get_gammavec}{GEN ldata} \fun{long}{ldata_get_degree}{GEN ldata} \fun{GEN}{ldata_get_k}{GEN ldata} \fun{GEN}{ldata_get_k1}{GEN ldata} \fun{GEN}{ldata_get_conductor}{GEN ldata} \fun{GEN}{ldata_get_rootno}{GEN ldata} \fun{GEN}{ldata_get_residue}{GEN ldata} \fun{long}{ldata_get_type}{GEN ldata} \fun{long}{linit_get_type}{GEN linit} \fun{GEN}{linit_get_ldata}{GEN linit} \fun{GEN}{linit_get_tech}{GEN linit} \fun{GEN}{lfun_get_domain}{GEN tech} \fun{GEN}{lfun_get_dom}{GEN tech} \fun{long}{lfun_get_bitprec}{GEN tech} \fun{GEN}{lfun_get_factgammavec}{GEN tech} \fun{GEN}{lfun_get_step}{GEN tech} \fun{GEN}{lfun_get_pol}{GEN tech} \fun{GEN}{lfun_get_Residue}{GEN tech} \fun{GEN}{lfun_get_k2}{GEN tech} \fun{GEN}{lfun_get_w2}{GEN tech} \fun{GEN}{lfun_get_expot}{GEN tech} \fun{long}{lfun_get_bitprec}{GEN tech} \fun{GEN}{lfunprod_get_fact}{GEN tech} \fun{GEN}{theta_get_an}{GEN tdata} \fun{GEN}{theta_get_K}{GEN tdata} \fun{GEN}{theta_get_R}{GEN tdata} \fun{long}{theta_get_bitprec}{GEN tdata} \fun{long}{theta_get_m}{GEN tdata} \fun{GEN}{theta_get_tdom}{GEN tdata} \fun{GEN}{theta_get_isqrtN}{GEN tdata} \section{Conversions and constructors} \fun{GEN}{lfunmisc_to_ldata}{GEN obj} converts \kbd{obj} to \kbd{Ldata} format. Exception if \kbd{obj} cannot be converted. \fun{GEN}{lfunmisc_to_ldata_shallow}{GEN obj} as \tet{lfunmisc_to_ldata}, shallow result. Exception if \kbd{obj} cannot be converted. \fun{GEN}{lfunmisc_to_ldata_shallow_i}{GEN obj} as \tet{lfunmisc_to_ldata_shallow}, returning \kbd{NULL} on failure. \fun{GEN}{lfunrtopoles}{GEN r} \fun{int}{sdomain_isincl}{double k, GEN dom, GEN dom0} \fun{GEN}{ldata_vecan}{GEN ldata, long N, long prec} return the vector of coefficients of indices $1$ to $N$ to precision \kbd{prec}. The output is allowed to be a \typ{VECSMALL} when the coefficients are known to be all integral and fit into a \kbd{long}; for instance the Dirichlet $L$ function of a real character or the $L$-function of a rational elliptic curve. \fun{GEN}{ldata_newprec}{GEN ldata, long prec} return a shallow copy of \kbd{ldata} with fields accurate to precision \kbd{prec}. \fun{long}{etaquotype}{GEN *peta, GEN *pN, GEN *pk, GEN *pCHI, long *pv, long *psd, long *pcusp} Let \kbd{eta} be the integer matrix factorization supposedly attached to an $\eta$-quotient $f(z) = \prod_i \eta(n_i z)^{e_i}$. Assuming \kbd{*peta} is initially set to \kbd{eta}, this function returns $0$ if there is a type error or this does not define a function on some $X_0(N)$. Else it returns $1$ and sets \item \kbd{*peta} to a normalized factorization (as would be returned by \kbd{factor}), \item \kbd{*pN} to the level $N$ of $f$, \item \kbd{*pk} to the modular weight $k$ of $f$, \item \kbd{*pCHI} to the Nebentypus of $f$ (quadratic character) as an integer, \item \kbd{*pv} to the valuation at infinity $v_q(f)$, \item \kbd{*psd} to $1$ if and only if $f$ is self-dual, \item \kbd{*pcusp} to $1$ if $f$ is cuspidal, else to $0$ if $f$ holomorphic at all cusps, else to $-1$. The last three arguments \kbd{pCHI}, \kbd{pv} and \kbd{pcusp} can be set to \kbd{NULL}, in which case the relevant information is not computed, which saves time. \section{Variants of GP functions} \fun{GEN}{lfun}{GEN ldata, GEN s, long bitprec} \fun{GEN}{lfuninit}{GEN ldata, GEN dom, long der, long bitprec} \fun{GEN}{lfuninit_make}{long t, GEN ldata, GEN tech, GEN domain} \fun{GEN}{lfunlambda}{GEN ldata, GEN s, long bitprec} \fun{GEN}{lfunquadneg}{long D, long k} for $L(\chi_D, k)$, $D$ fundamental discriminant and $k \geq 0$. \fun{long}{lfunthetacost}{GEN ldata, GEN tdom, long m, long bitprec}: \kbd{lfunthetacost0} when the first argument is known to be an \kbd{Ldata}. \fun{GEN}{lfunthetacheckinit}{GEN data, GEN tinf, long m, long bitprec} \fun{GEN}{lfunrootno}{GEN data, long bitprec} \fun{GEN}{lfunabelianrelinit}{GEN bnr, GEN subg, GEN dom, long der, long bitprec} where \kbd{bnr} is a true \var{bnr} structure and \kbd{subg} is a congruence subgroup. Not GC-clean. \fun{GEN}{lfunzetakinit}{GEN nf, GEN dom, long der, long bitprec} where \kbd{nf} is a true \var{nf} structure. Not GC-clean. \fun{GEN}{lfunellmfpeters}{GEN E, long bitprec} \section{Inverse Mellin transforms of Gamma products} \fun{GEN}{gammamellininv}{GEN Vga, GEN s, long m, long bitprec} \fun{GEN}{gammamellininvinit}{GEN Vga, long m, long bitprec} \fun{GEN}{gammamellininvrt}{GEN K, GEN s, long bitprec} no GC-clean, but suitable for \kbd{gerepileupto}. \fun{int}{Vgaeasytheta}{GEN Vga} return 1 if the inverse Mellin transform is an exponential and 0 otherwise. \fun{double}{dbllemma526}{double a, double b, double c, long B} \fun{double}{dblcoro526}{double a, double c, long B} \newpage \chapter{Modular symbols} \fun{void}{checkms}{GEN W} raise an exception if $W$ is not an \var{ms} structure from \kbd{msinit}. \fun{void}{checkmspadic}{GEN W} raise an exception if $W$ is not an \var{mspadic} structure from \kbd{mspadicinit}. \fun{GEN}{mseval2_ooQ}{GEN W, GEN phi, GEN c} let $W$ be a \kbd{msinit} structure for $k = 2$, $\phi$ be a modular symbol with integral values and $c$ be a rational number. Return the integer $\phi(p)$, where $p$ is the path $\{\infty,c\}$. \fun{void}{mspadic_parse_chi}{GEN s, GEN *s1, GEN *s2} see \kbd{mspadicL}; let $\chi$ be the cyclotomic character from $\text{Gal}\big(\Q_p(mu_{p^\infty})/\Q_p\big)$ to $\Z_p^*$ and $\tau$ be the Teichm\"uller character for $p > 2$ and the character of order $2$ on $(\Z/4\Z)^*$ if $p = 2$. Let $s$ encode the $p$-adic characther $\chi^s := \langle\chi\rangle^{s_1} \tau^{s_2}$; set \kbd{*s1} and \kbd{*s2} to the integers $s_1$ and $s_2$. \fun{GEN}{mspadic_unit_eigenvalue}{GEN ap, long k, GEN p, long n} let $p$ be a prime not dividing the trace of Frobenius \kbd{ap}, return the unit root of $x^2 - ap*x + p^(k-1)$ to $p$-adic accuracy $p^n$. Variants of \kbd{mfnumcusps} : \fun{ulong}{mfnumcuspsu}{ulong n} \fun{GEN}{mfnumcusps_fact}{GEN fa} where \kbd{fa} is \kbd{factor}$(n)$. \fun{ulong}{mfnumcuspsu_fact}{GEN fa} where \kbd{fa} is \kbd{factoru}$(n)$. \newpage \chapter{Modular forms} \section{Implementation of public data structures} \fun{void}{checkMF}{GEN mf} raise an exception if the argument is not a modular form space. \fun{GEN}{checkMF_i}{GEN mf} return the underlying modular form space if \kbd{mf} is either directly a modular form space from \kbd{mfinit} or a symbol from \kbd{mfsymbol}. Return \kbd{NULL} otherwise. \fun{int}{checkmf_i}{GEN mf} return $1$ if the argument is a modular form and $0$ otherwise. \fun{int}{checkfarey_i}{GEN F} return $1$ if the argument is a Farey symbol (from \kbd{mspolygon} or \kbd{msfarey}) and $0$ otherwise. \subsec{Accessors for modular form spaces} Shallow functions; assume that their argument is a modular form space is created by \kbd{mfinit} and checked using \kbd{checkMF}. \fun{GEN}{MF_get_gN}{GEN mf} return the level $N$ as a \typ{INT}. \fun{long}{MF_get_N}{GEN mf} return the level $N$ as a \kbd{long}. \fun{GEN}{MF_get_gk}{GEN mf} return the level $k$ as a \typ{INT}. \fun{long}{MF_get_k}{GEN mf} return the level $k$ as a \kbd{long}. \fun{long}{MF_get_r}{GEN mf} assuming the level is a half-integer, return the integer $r = k - (1/2)$. \fun{GEN}{MF_get_CHI}{GEN mf} return the nebentypus $\chi$, which is a special form of character structure attached to Dirichlet characters (see next section). Its values are given as algebraic numbers: either $\pm1$ or \typ{POLMOD} in $t$. \fun{long}{MF_get_space}{GEN mf} returns the space type, corresponding to \kbd{mfinit}'s \kbd{space} flag. The current list is \bprog mf_NEW, mf_CUSP, mf_OLD, mf_EISEN, mf_FULL @eprog \fun{GEN}{MF_get_basis}{GEN mf} return the $\Q$-basis of the space, concatenation of \tet{MF_get_E} and \tet{MF_get_S}, in this order; the forms have coefficients in $\Q(\chi)$. Low-level version of \kbd{mfbasis}. \fun{long}{MF_get_dim}{GEN mf} returns the dimension $d$ of the space. It is the cardinality of \tet{MF_get_basis}. \fun{GEN}{MF_get_E}{GEN mf} returns a $\Q$-basis for the subspace spanned by Eisenstein series in the space; the forms have coefficients in $\Q(\chi)$. \fun{GEN}{MF_get_S}{GEN mf} returns a $\Q$-basis for the cuspidal subspace in the space; the forms have coefficients in $\Q(\chi)$. \fun{GEN}{MF_get_fields}{GEN mf} returns the vector of polynomials defining each Galois orbit of newforms over $\Q(\chi)$. Uses memoization: a first call splits the space and may be costly; subsequent calls return the cached result. \fun{GEN}{MF_get_newforms}{GEN mf} returns a vector \kbd{vF} containing the coordinates of the eigenforms on \tet{MF_get_basis} (\kbd{mftobasis} form). Low-level version of \kbd{mfeigenbasis}, whose elements are recovered as \kbd{mflinear(mf, gel(vF,i))}. Uses memoization, sharing the same data as \kbd{MF\_get\_fields}. Note that it is much more efficient to use \kbd{mfcoefs(mf,)} then multiply by this vector than to compute the coefficients of eigenforms from \kbd{mfeigenbasis} individually. The following accessors are technical, \fun{GEN}{MF_get_M}{GEN mf} the $(1+m) \times d$ matrix whose $j$-th column contain the coefficients of the $j$-th entry in \tet{MF_get_basis}, $m$ is the optimal ``Sturm bound'' for the space: the maximum of the $v_\infty(f)$ over nonzero forms. It has entries in $\Q(\chi)$. \fun{GEN}{MF_get_Mindex}{GEN mf} is a \typ{VECSMALL} containing $d$ row indices, the corresponding rows of $M$ form an invertible matrix $M_0$. \fun{GEN}{MF_get_Minv}{GEN mf} the inverse of $M_0$ in a form suitable for fast multiplication. \fun{GEN}{MFcusp_get_vMjd}{GEN mf} valid only for a full \emph{cuspidal} space. Then the functions in \tet{MF_get_S} are of the form $B_d T_j Tr^{new}_M$. This returns the vector of triples (\typ{VECSMALL}) $[M,j,d]$, in the same order. \fun{GEN}{MFnew_get_vj}{GEN mf} valid only for a \emph{new} space. Then the functions in \tet{MF_get_S} are of the form $T_j Tr^{new}_N$. This returns a \typ{VECSMALL} of the Hecke indices $j$, in the same order. \subsec{Accessors for individual modular forms} \fun{GEN}{mf_get_gN}{GEN F} return the level of $F$, which may be a multiple of the conductor, as a \typ{INT} \fun{long}{mf_get_N}{GEN F} return the level as a \kbd{long}. \fun{GEN}{mf_get_gk}{GEN F} return the weight of $F$ as a \typ{INT} or a \typ{FRAC} with denominator $2$ (half-integral weight). \fun{long}{mf_get_k}{GEN F} return the weight as a \kbd{long}; if the weight is not integral, this raises an exception. \fun{long}{mf_get_r}{GEN F} assuming $F$ is a modular form of half-integral weight $k = (2r+1)/2$, return $r = k - (1/2)$. \fun{GEN}{mf_get_CHI}{GEN F} return the nebentypus, which is a special form of character structure attached to Dirichlet characters (see next section). Its values are given as algebraic numbers: either $\pm1$ or \typ{POLMOD} in $t$. \fun{GEN}{mf_get_field}{GEN F} return the polynomial (in variable $y$) defining $\Q(f)$ over $\Q(\chi)$. \fun{GEN}{mf_get_NK}{GEN F} return the tag attached to $F$: a vector containing \kbd{gN}, \kbd{gk}, \kbd{CHI}, \kbd{field}. Never use its component directly, use individual accessors as above. \fun{long}{mf_get_type}{GEN F} returns a symbolic name for the constructur used to create the form, e.g. \kbd{t\_MF\_EISEN} for a general Eisenstein series. A form has a recursive structure represented by a tree: its definition may involve other forms, e.g. the tree attached to $T_n f$ contains $f$ as a subtree. Such trees have \emph{leaves}, forms which do not contain a strict subtree, e.g. \kbd{t\_MF\_DELTA} is a leaf, attached to Ramanujan's $\Delta$. Here is the current list of types; since the names are liable to change, they are not documented at this point. Use \kbd{mfdescribe} to visualize their mathematical structure. \bprog /*leaves*/ t_MF_CONST, t_MF_EISEN, t_MF_Ek, t_MF_DELTA, t_MF_ETAQUO, t_MF_ELL, t_MF_DIHEDRAL, t_MF_THETA, t_MF_TRACE, t_MF_NEWTRACE, /*recursive*/ t_MF_MUL, t_MF_POW, t_MF_DIV, t_MF_BRACKET, t_MF_LINEAR, t_MF_LINEAR_BHN, t_MF_SHIFT, t_MF_DERIV, t_MF_DERIVE2, t_MF_TWIST, t_MF_HECKE, t_MF_BD, @eprog \subsec{Nebentypus} The characters stored in modular forms and modular form spaces have a special structure. One can recover the parameters of an ordinary Dirichlet character by \kbd{G = gel(CHI,1)} (the underlying \kbd{znstar}) and \kbd{chi = gel(CHI,2)} (the underlying character in \kbd{znconreylog} form). \fun{long}{mfcharmodulus}{GEN CHI} the modulus of $\chi$. \fun{long}{mfcharorder}{GEN CHI} the order of $\chi$. \fun{GEN}{mfcharpol}{GEN CHI} the cyclotomic polynomial $\Phi_n$ defining $\Q(\chi)$, always normalized so that $n$ is not $2$ mod $4$. \subsec{Miscellaneous functions} \fun{long}{mfnewdim}{long N, long k, GEN CHI} dimension of the new part of the cuspidal space. \fun{long}{mfcuspdim}{long N, long k, GEN CHI} dimension of the cuspidal space. \fun{long}{mfolddim}{long N, long k, GEN CHI} dimension of the old part of the cuspidal space. \fun{long}{mfeisensteindim}{long N, long k, GEN CHI} dimension of the Eisenstein subspace. \fun{long}{mffulldim}{long N, long k, GEN CHI} dimension of the full space. \fun{GEN}{mfeisensteinspaceinit}{GEN NK} \fun{GEN}{mfdiv_val}{GEN F, GEN G, long vG} \fun{GEN}{mfembed}{GEN E, GEN v} \fun{GEN}{mfmatembed}{GEN E, GEN v} \fun{GEN}{mfvecembed}{GEN E, GEN v} \fun{long}{mfsturmNgk}{long N, GEN k} \fun{long}{mfsturmNk}{long N, long k} \fun{long}{mfsturm_mf}{GEN mf} \fun{long}{mfiscuspidal}{GEN mf, GEN F} \fun{GEN}{mftobasisES}{GEN mf, GEN F} \fun{GEN}{mftocol}{GEN F, long lim, long d} \fun{GEN}{mfvectomat}{GEN vF, long lim, long d} \newpage \chapter{Plots} A \tet{PARI_plot} canvas is a record of dimensions, with the following fields: \bprog long width; /* window width */ long height; /* window height */ long hunit; /* length of horizontal 'ticks' */ long vunit; /* length of vertical 'ticks' */ long fwidth; /* font width */ long fheight;/* font height */ void (*draw)(PARI_plot *T, GEN w, GEN x, GEN y); @eprog\noindent The \kbd{draw} method performs the actual drawing of a \typ{VECSMALL} w (rectwindow indices); $x$ and $y$ are \typ{VECSMALL}s of the same length and rectwindow $w[i]$ is drawn with its upper left corner at offset $(x[i],y[i])$. No plot engine is available in \kbd{libpari} by default, since thie would introduce a dependency on extra graphical libraries. See the files \kbd{src/graph/plot*} for basic implementations of various plot engines: \kbd{plotsvg} is particularly simple (\kbd{draw} is a 1-liner). \fun{void}{pari_set_plot_engine}{void (*T)(PARI_plot *)} installs the graphical engine $T$ and initializes the graphical subsystem. No routine in this chapter will work without this initialization. \fun{void}{pari_kill_plot_engine}{void} closes the graphical subsystem and frees the ressources it occupies. \section{Highlevel functions} Those functions plot $f(E,x)$ for $x\in [a,b]$, using $n$ regularly spaced points (by default). \fun{GEN}{ploth}{void *E, GEN(*f)(void*,GEN), GEN a, GEN b, long flags,long n, long prec} draw physically. \fun{GEN}{plotrecth}{void *E, GEN(*f)(void*,GEN), long w, GEN a,GEN b, ulong flags,long n, long prec} draw in rectwindow $w$. \section{Function} \fun{void}{plotbox}{long ne, GEN gx2, GEN gy2} \fun{void}{plotclip}{long rect} \fun{void}{plotcolor}{long ne, long color} \fun{void}{plotcopy}{long source, long dest, GEN xoff, GEN yoff, long flag} \fun{GEN}{plotcursor}{long ne} \fun{void}{plotdraw}{GEN list, long flag} \fun{GEN}{plothraw}{GEN listx, GEN listy, long flag} \fun{GEN}{plothsizes}{long flag} \fun{void}{plotinit}{long ne, GEN x, GEN y, long flag} \fun{void}{plotkill}{long ne} \fun{void}{plotline}{long ne, GEN x2, GEN y2} \fun{void}{plotlines}{long ne, GEN listx, GEN listy, long flag} \fun{void}{plotlinetype}{long ne, long t} \fun{void}{plotmove}{long ne, GEN x, GEN y} \fun{void}{plotpoints}{long ne, GEN listx, GEN listy} \fun{void}{plotpointsize}{long ne, GEN size} \fun{void}{plotpointtype}{long ne, long t} \fun{void}{plotrbox}{long ne, GEN x2, GEN y2} \fun{GEN}{plotrecthraw}{long ne, GEN data, long flags} \fun{void}{plotrline}{long ne, GEN x2, GEN y2} \fun{void}{plotrmove}{long ne, GEN x, GEN y} \fun{void}{plotrpoint}{long ne, GEN x, GEN y} \fun{void}{plotscale}{long ne, GEN x1, GEN x2, GEN y1, GEN y2} \fun{void}{plotstring}{long ne, char *x, long dir} \subsec{Obsolete functions} These draw directly to a PostScript file specified by a global variable and should no longer be used. Use \kbd{plotexport} and friends instead. \fun{void}{psdraw}{GEN list, long flag} \fun{GEN}{psplothraw}{GEN listx, GEN listy, long flag} \fun{GEN}{psploth}{void *E, GEN(*f)(void*,GEN), GEN a, GEN b, long flags, long n, long prec} draw to a PostScript file. \section{Dump rectwindows to a PostScript or SVG file} $w,x,y$ are three \typ{VECSMALL}s indicating the rectwindows to dump, at which offsets. If $T$ is \kbd{NULL}, rescale with respect to the installed graphic engine dimensions; else with respect to $T$. \fun{char*}{rect2ps}{GEN w, GEN x, GEN y, PARI_plot *T} \fun{char*}{rect2ps_i}{GEN w, GEN x, GEN y, PARI_plot *T, int plotps} if \kbd{plotps} is $0$, as above; else private version used to implement the \kbd{plotps} graphic engine (do not rescale, rotate to portrait orientation). \fun{char*}{rect2svg}{GEN w, GEN x, GEN y, PARI_plot *T} \section{Technical functions exported for convenience} \fun{void}{pari_plot_by_file}{const char *env, const char *suf, const char *img} backend used by the \kbd{plotps} and \kbd{plotsvg} graphic engines. \fun{void}{colorname_to_rgb}{const char *s, int *r, int *g, int *b} convert an \kbd{X11} colorname to RGB values. \fun{void}{color_to_rgb}{GEN c, int *r, int *g, int *b} convert a pari color (\typ{VECSMALL} RGB triple or \typ{STR} name) to RGB values. \fun{void}{long_to_rgb}{long c, int *r, int *g, int *b} split a standard hexadecimal color value \kbd{0xfdf5e6} to its rgb components (\kbd{0xfd}, \kbd{0xf5}, \kbd{0xe6}). \newpage pari-2.17.2/CHANGES-2.140000644000175000017500000004665114676526175012600 0ustar billbillBug numbers refer to the BTS at http://pari.math.u-bordeaux.fr/Bugs/ Done for version 2.15.0 (released 19/10/2022): Fixed 1- slowdown in zeta (e.g. zeta(Pi) at \p500) 2- GC error in idealinv [#2258] 3- qfminim inefficiency (initial bound from non-LLL-reduced matrix) 4- mfshimura in weight 3/2 => oo loop 5- zetahurwitz(s, huge x) => overflow or very slow 6- matsolve([1,1,1/2; 1,0,1/2; 2,1,0], [-1;1;-1]) -> SEGV [#2261] 7- qfminim(Mat(1),,,2) -> precision error [#2262] 8- subst(p, v, t_SER) very slow if p contains many variables [#2264] 9- mfsymboleval for trivial path returned 0 instead of a vector of 0s when f has multiple embeddings [#2260] 10- 2^(1 + O(3^4)) -> type error 11- Zn_quad_roots(8,0,-1) to compute roots of x^2-1 mod 8 -> [4,[1,3]] (1 or 3 mod 4) instead of the expected [2,[1]] (1 mod 2) [#2265] 12- tan(1+10^20*I) -> overflow (same for cotan and psi) BA 13- Mod(2,3)^1000000000000000000001 -> Mod(-1,3) [#2266] 14- subst(O(y) + x, x, (1 - y + O(y^2))*x + O(x^2)) -> SEGV [#2267] 15- (Mod(0,3) + x) + O(x^2) -> x + O(x^2) [now Mod(1,3)*x + O(x^2)] 16- precision too low for units in mfgaloisprojrep 17- missing GC at the end of RgXn_inv 18- (-1)^(1/3) -> -1 instead of exp(log(-1)/3) 19- mfeisenstein(k, trivial characters mod N > 1) not handled correctly BA 20- missing GC in qfsolve 21- missing GC in nfeltval + better algorithm when valuation is huge 22- rnfidealup(, non-integral ideal) -> division by 0 23- memory leak in ellheight 24- memory leak in bnfinit 25- zeta(-2 + O(x)) => division by 0 26- nfeltdiv(nfinit(x^2+1), 0, 1+x/2) -> SEGV [#2277] 27- numerical instability in polinterpolate [#2278] 28- znchargauss(g,chi,0) -> oo loop 29- bnflog(bnr, ...) -> SEGV 30- elliptic functions: incorrect reduction of z/w1 mod [1,tau] => catastrophic cancellation 31- powcx(x, t_COMPLEX with 0 imaginary part) -> crash 32- nfsubfields(t_POL in other var than x,,1) -> SEGV 33- extra terms in power t_SER substitutions [#2281] f=1+4*t^2+36*t^4+O(t^6); g=q-4*q^3+14*q^5+O(q^7); subst(f,t,g) -> spurious extra term -400*q^6 34- k=bnfinit(quadpoly(-2923,a)); bnrclassfield(k,3) -> SEGV [#2280] BA 35- rnfdisc mishandled polynomials with denominators [#2284] BA 36- elltamagawa(ellinit([-1456/243,93184/19683])) -> wrong result 37- mfsearch would sometimes miss the trivial form 38- typo in allh [affects ECPP tunings] HC 39- mfisetaquo(mffrometaquo([1,12;193,12])) -> 0 40- polroots(1.E-47*t^6 + 1.E-47*t^5 + 4.E-46*t^4) -> bug in type [#2286] 41- ceil(quadgen(5)) -> 1 instead of 0 [#2288] 42- floor(Mod(0,3)*quadgen(5)) -> crash 43- padicappr(x^2+1, 1/3+O(3)) -> missing valuation and type checks 44- padicappr(x^2+25,5+O(5^2)) -> [O(5),O(5)] instead of [2*5+O(5^2),3*5+O(5^2)] 45- wrong ispower(t_RFRAC) and issquare(t_RFRAC, &z) [#2289] 46- slow series substitution if valuation huge f=t^50000+O(t^50001); g=q*Ser(vector(50000,i,1),q); h=subst(f,t,g) 47- 1+O(x)==O(x) 48- cmp() would use possibly uninitialized bits in t_POL codewords BA 49- qfauto([[1,0;0,1],[0,0;1,0]]) -> SEGV 50- bnfsunit(...)[4] (the S-regulator) did not correspond to its definition in the documentation [ was using log(p) instead of log(Norm P)) for P in S above p ] BA 51- rnfdisc could return corrupted result 52- quadtofp suffered from catastrophic cancellation [#2298] z=66992092050551637663438906713182313772 -47370562574818466708936539960450008968*quadgen(8); z*1. -> 0.75 BA 53- concat(List([1])[1..0]) ->SEGV (instead of error) [#2299] BA 54- List([1])[1..0]==List() -> 0 instead of 1 55- ZX_squff(T) did not follow its specification if T(0) = 0 56- (-1)^(-1/2) -> I instead of -I 57- lfuntheta inaccurate in large weight [#2305] 58- GC error in ZX_Uspensky(, flag = 0) BA 59- ellisomat(ell/nf not integral) -> oo-loop or wrong result BA 60- (f(~v)=v[1]=1);(g(v) = f(~v)); my(V=[0]);g(V);V -> [1] instead of [0] due to missing copy on write [#2304] 61- hypergeom([1/12,1/12],2/3,3) -> wrong result (incorrect limiting case of transformation formula) 62- overflow in mulu_interval(,ULONG_MAX) [#2309] 63- ellE(1) -> domain error [#2312] 64- log1p(-1 + 10^-10) -> oo time 65- bernvec entries were wrong from B_{2*4064} on [#2311] 66- plotrecthraw for multi-curves 67- RgXn_powu(,,1) wrong result [#2314] 68- erfc incorrect on negative imaginary axis [#2315] 69- mfgalpoistype bug for dihedral types (when conductor at oo is not stable under Galois) [#2293] BA 70- [32bit] forfactored(n=223092868, 223092871, ) -> SEGV [#2318] 71- Fp_issquare(0, p) would return 0 72- For z=x+wy a t_QUAD, z.pol returned the modulus z.mod instead of the t_POL x+'w*y 73- allow eulerianpol(0) (= 1) 74- allow polylog(0,x) (was broken when eulerianpol was introduced) BA 75- concat(t_LIST,t_LIST) was leaking memory 76- missing type checks in ellchangepoint (SEGV) 77- polsturm(-5500*x^4+440*x^3+21780*x^2-9680*x-29040,[-oo,-4])->corruption 78- ellheight(E,,Q) -> SEGV 79- besselj(80,66) -> oo loop 80- lfun(1, 0.0) "normalizing a series with a 0 leading term" [#2329] 81- (0. + O(x) == 1) returned 'true' 82- lfun(1, 0., 1) -> division by 0 83- fix lfuncost when root number is unknown (more a_n are needed) 84- idealismaximal(nfinit(x),Mat(2)) -> 0 [#2333] 85- O(29^(-1)) == 1 was FALSE (same for -1) 86- Mod(0, 2*x^0) == 1 was FALSE (same for -1) BA 87- [X11] resizing a window could keep traces of previous drawing BA 88- x->x+0x1 was not displayed correctly 89- bnfinit(Q) was not using current precision [#2335] 90- lfuncreate(x^2 + 1/2) -> internal error. Allow rational coefficients. 91- polresultant(t_POL with t_RFRAC coefs,...) -> internal errors 92- znchardecompose(znstar(2,1),[],2) -> SEGV [#2339] 93- genus2red(150*x^6+180*x^5-270*x^4+2040*x^3-1350*x^2+3060*x+270) -> internal bug [#2331] 94- missing roots in nfroots(t_POL,) [#2345] 95- factorpadic: ensure leading coefs are powers of p [#2352] 96- nfsnf: wrong results [#2353] XR 97- rare SEGV in nfdisc. [#2356] BA 98- factor((Mod(1,2)*((t^2+1)*x^4+(t^4+1)*x^2+1))) -> division by 0 99- internal type errors in mfsymboleval [#2360] 100- incorrect chargalois for trivial group [#2341] 101- minpoly(Mod(1/(x-(t+1))*Mod(1,2),(t+1)*x^2+t*x+1)) -> error [#2363] BA 102- factor(Mod(1,2)*x^5+a*x^3) -> div by 0 AP 103- nfgrunwaldwang: fix infinite loop [#2343] 104- ti=thueinit(3*x^3 + 5*x^2 - 14*x + 54,1); thue(ti,1) -> error [#2365] 105- algdep(t_POLMOD x) -> x.mod instead of correct result 106- bnrinit(,,,cycmod) failed to delete elementary divisors equal to 1 BA 107- bnrclassfield: incorrect result when fundamental units are large, e.g. bnrclassfield(bnfinit(nfsplitting(a^3-a^2-202*a-3080),1),2) [#2371] 108- M8=mfinit([8,5/2]); mfatkininit(M8,8)[1] was 0 and shouldn't be 109- polylogmult instability default(realprecision,366);a=(1+sqrt(5))/2;w=(1+sqrt(-3))/2; polylogmult([1,1,1,1],[1/a,a,1,w]) -> error 110- valuation(x*(y^2-1), y+1) -> oo loop [#2381] 111- round(t_FRAC, &e): e was always -oo 112- FpM_center_inplace would crash for p = 3 [#2387] BA 113- [gp interpreter] fix memory leak in pop_lex 114- numerator(1/x+1/y, 'x) -> x*y 115- colors = "no" (or "") handled incorrectly [#2402] 116- thue(thueinit(x^3-3*x^2+1,1), 2187) -> domain error in mplog [#2397] 117- Bessel function of huge order -> oo loop [e.g. besselj(220, 112)] 118- elltwist(E,) would ignore E's real precision Added HC 1- new GP function eulerreal BA 2- fplll: fast, dpe and heuristic variants 3- dirpowerssum: allow a completely multiplicative function 4- [libpari] atanhuu, atanhui, powcx, powcx_prec, cx_approx0 5- new GP function lfunparams (initial implementation P. Molin) 6- [libpari] row_Q_primpart BA 7- [libpari] RgXQ_trace, RgX_chinese_coprime, RgXQV_factorback 8- [libpari] FpM_intersect_i, Flm_intersect_i HC 9- add optional argument to ramanujantau + parallelize code HC 10- new GP functions bessljzero, besselyzero BA 11- [libpari] Fle_ellweilpairing, Fle_elltatepairing, Flj_to_Fle Fl_ellptors BA 12- [libpari] ZC_divexactu, ZM_divexactu HC 13- allow hypergeom(N, D, t_SER) 14- [libpari] qfbsqr, qfbcomp, qfbpow, qfbpowraw, qfbsqr_i, qfbcomp_i, qfbpow_i, qfbpow, qfbpowraw, qfr3_compraw, qfr5_compraw 15- general composition of binary quadratic forms (in different orders) BA 16- New GP functions ellrank, ellrankinit : implement 2-descent on elliptic curve following a GP script by Denis Simon. BA 17- [libpari] RgXY_derivx, RgX_recip_i 18- [libpari] RgC_RgV_mulrealsym, RgM_to_RgXV_reverse BA 19- New GP function ellsaturation 20- [libpari] ZX_Z_eval BA 21- [libpari] elltors_psylow 22- ellinit([j]); no need to use ellfromj 23- ideallist(nf, negative bound) to return ideals of norm |bound| (in factored form) 24- rnfconductor(bnf,pol,flag): add flag=2 to only return the conductor and its factorization (which comes for free) HC 25- New GP functions nflist, nfresolvent BA 26- [libpari] Hermite_bound 27- substvec: support t_VEC replacement values BA 28- New GP function ell2cover BA 29- nfsplitting: flag to get the embedding BA 30- New GP function galoissplittinginit HC 31- lambertw(y): support all values y > -1/e [#1472] HC 32- lambertw: add optional 'branch' argument; support and complex, p-adic and power series inputs BA 33- [libpari] ZXC_to_FlxC, ZXM_to_FlxM BA 34- [libpari] New function families F3v, F3m BA 35- New GP function setdebug 36- allow shortcut \g n feat for setdebug("feat", n) 37- New GP function poltomonic [#2200] 38- in GPRC, support default(key,val) and setdebug(dom,val) 39- New GP function polsubcyclofast 40- [libpari] prV_primes, ideals_by_norm, nfV_to_scalar_or_alg, quadpoly_i 41- new bit in nfinit flag: don't perform LLL on nf.zk BA 42- new flag value in nfisincl 43- [libpari] hclassno6u_from_cache, uhclassnoF_fact, hclassnoF_fact, vandermondeinverseinit, vandermondeinverse, trans_evalgen, sunits_mod_units, Qp_exp_prec BA 44- [libpari] RgXQ_minpoly 45- [libpari] quadclassnos, quadclassnoF, unegquadclassnoF, uposquadclassnoF, coredisc2_fact, coredisc2u_fact, uquadclassnoF_fact quadclassnoF_fact, Z_issquarefree_fact 46- new GP functions quadunitnorm, quadunitindex LGr 47- allow endpoints in solve() to by +oo or -oo 48- allow Vec(t_STR, n) and Vecsmall(t_STR, n) 49- new GP function: harmonic 50- allow digits(integral t_PADIC) 51- new GP function qfbcornacchia 52- [libpari] gc_all BA 53- [libpari] Zp_inv, Zp_invlift, Zp_div, Zp_log, Zp_exp BA 54- [libpari] FpXn_div, Flxn_div, RgXn_div, RgXn_div_i, FpXQXn_div, F2xn_div 55- [libpari] maxomegau, maxomegaoddu, ZV_snf_rank, ZV_snf_rank_u, zv_snf_rank, F3c_to_ZC, F3c_to_mod, F3m_to_mod, ZX_unscale_divpow, ZX_affine 56- new GP function snfrank HC 57- allow lngamma(t_PADIC of negative valuation) 58- file LICENSE (for Software Heritage archiving) BA 59- [libpari] RgXV_prod BA 60- new GP function serdiffdep 61- new module for hypergeometric motives, see ??hgm. GP functions hgmalpha hgmbydegree hgmcyclo hgminit hgmtwist hgmcoef hgmeulerfactor hgmissymmetrical lfunhgm hgmcoefs hgmgamma hgmparams BA 62- new GP function lfuneuler TF 63- new GP functions subcyclohminus, subcycloiwasawa, subcyclopclgp 64- new GP function bnrcompositum 65- [libpari] gdivgu, gdivgunextu, divrunextu, gmulgu, gmulug 66- [libpari] Zp_log, Zp_exp 67- new GP function intnumosc, sumnumsidi BA 68- [x86_64,arm64] AVX,NEON support for hyperellratpoints BA 69- [libpari functions ZX_digits, ZXV_ZX_fromdigits NM 70- new GP function elltrace BA 71- [libpari] FpXQXV_red, FpXQXT_red BA 72- [libpari] ZpXQX_ZpXQXQ_liftroot, ZqX_ZqXQ_liftroot 73- [libpari] ZV_snfclean 74- allow bnrchar to construct a Dirichlet character (with a znstar input) 75- new GP functions nfeltissquare, nfeltispower BA 76- [libpari] FlxqX_nbfact_by_degree BA 77- [libpari] RgXY_cxevalx 78- allow f*g and f^n for qfbcomp/qfbpow also for extended (real) forms 79- [libpari] qfbpows BA 80- [libpari] FlxM_to_FlxXV, FlxXC_sub BA 81- [libpari] FlxqXC_FlxqXQ_eval, FlxqXC_FlxqXQV_eval BA 82- new GP function qfminimize BA 83- new GP functions hyperelldisc, hyperellminimalmodel, hyperellminimaldisc, hyperellred 84- new GP function setdelta BA 85- [libpari] RgX_homogenous_evalpow, QXQX_homogenous_evalpow BA 86- [libpari] FpX_roots_mult BA 87- [libpari] RgX_affine HC 88- new GP function lerchphi, lerchzeta BA 89- new GP function hyperellisoncurve BA 90- [libpari] nfM_ker 91- [libpari] Qp_zeta BA 92- [libpari] RgX_mul2n 93- [libpari] rfrac_to_ser_i 94- [libpari] FlxC_FlxqV_eval_pre, FlxC_Flxq_eval_pre, Flx_FlxqV_eval_pre, Flx_Flxq_eval_pre, Flx_Frobenius_pre, Flx_div_pre, Flx_divrem_pre, Flx_extgcd_pre, Flx_gcd_pre, Flx_get_red_pre, Flx_halfgcd_pre, Flx_mul_pre, Flx_oneroot_pre, Flx_oneroot_split_pre, Flx_rem_pre, Flx_roots_pre, Flx_sqr_pre, Flxq_div_pre, Flxq_inv_pre, Flxq_invsafe_pre, Flxq_mul_pre, Flxq_powers_pre, Flxq_powu_pre, Flxq_sqr_pre, Flx_powu_pre, Flxn_div_pre, Flxn_mul_pre, Flxn_sqr_pre, FlxqX_fromNewton_pre, FlxqX_Flxq_mul_pre, FlxqX_Flxq_mul_to_monic_pre, FlxqX_FlxqXQV_eval_pre, FlxY_FlxqV_evalx_pre, FlxY_Flxq_evalx_pre, FlxqX_Newton_pre, FlxqX_get_red_pre, FlxqX_invBarrett_pre, FlxqX_powu_pre, FlxqXn_mul_pre, FlxqXn_sqr_pre, FlxqXn_inv_pre, FlxqXn_expint_pre, FlxY_eval_powers_pre, FlxY_evalx_powers_pre, FlxY_evalx_powers_pre, FlxqX_divrem_pre, FlxqXQ_inv_pre, FlxqXQ_invsafe_pre, FlxqXQ_sqr_pre, FlxqX_rem_pre, FlxqX_sqr_pre, FlxqXQ_pow_pre, FlxqXC_FlxqXQV_eval_pre, FlxqXQ_div_pre, FlxqXQ_mul_pre, FlxqX_halfgcd_pre, FlxqX_mul_pre, FlxqX_extgcd_pre, FlxqXQ_powers_pre, FlxqXQ_powu_pre, FlxqX_normalize_pre, FlxqX_red_pre, Kronecker_to_FlxqX_pre, Flx_dotproduct_pre, FlxqX_div_pre, FlxY_Flxq_evalx_pre, FlxqXC_FlxqXQV_eval_pre, Flx_is_smooth_pre, Flxq_pow_pre, Flxq_pow_init_pre, Flxq_pow_table_pre, Flx_matFrobenius_pre, FlxqV_dotproduct_pre, FlxqX_FlxqXQ_eval_pre, Flxq_auttrace_pre, Flxq_minpoly_pre, Flxq_lroot_fast_pre, Flxq_lroot_pre Flxq_matrix_pow_pre, Flx_ddf_pre, Flx_factor_squarefree_pre, Flx_nbfact_pre, Flx_nbfact_Frobenius_pre, Flx_resultant_pre, Flxq_autpow_pre, FlxqX_gcd_pre, FlxY_evalx_pre, FlxqXQ_autsum_pre, FlxqXQ_minpoly_pre, FlxqXQ_autpow_pre, FlxqXQ_auttrace_pre, FlxqX_Frobenius_pre, FlxqX_factor_squarefree_pre, FlxqE_weilpairing_pre TF 95- new GP function factormodcyclo TF 96- new libpari functions FpX_factcyclo, Flx_factcyclo 97- new libpari functions ZV_sort_shallow, ZV_sort_uniq_shallow, tridiv_boundu BA 98- rnfabelianconjgen 99- new libpari functions abmap_kernel, abmap_subgroup_image, ZV_ZV_mod, ZM_ZV_mod 100- bnr_char_sanitize, bnr_subgroup_sanitize TF 101- GP function znsubgroupgenerators 102- [libpari] RgV_is_prV 103- improve idealfactorback [using ideamulpowprime] AP 104- New GP functions for Hecke characters +PMo gchareval gcharalgebraic gcharconductor gcharduallog gcharidentify gcharinit gcharisalgebraic gcharlocal gcharlog gcharnewprec Changed HC 1- faster implementation of eulervec + cache result 2- sumnummonieninit(,1): faster algorithm (complex step) 3- atanh(rational) now uses binary splitting BA 4- FqV_to_FlxV, FqC_to_FlxC, FqM_to_FlxM: replaced by ZXC_to_FlxC, ZXM_to_FlxM 5- FpM_intersect and Flm_intersect now guaranteed to return an Fp-basis; use FpM_intersect_i if you only need a generating set 6- ZXX_to_Kronecker -> RgXX_to_Kronecker, ZXX_to_Kronecker_spec -> RgXX_to_Kronecker_spec 7- [libpari] nbessel -> ybessel 8- faster implementation of mfinit and mfbasis in weight 1 9- ZabM_ker: replace final exact check by probabilistic check modulo a 63-bit prime 10- [libpari] ZC_u_divexact -> ZC_divexactu 11- unify real and imaginary binary quadratic forms, include discriminant types t_QFI and t_QFR are replaced by t_QFB 12- allow Qfb([a,b,c]) and Vec(t_QFB) 13- qfbredsl2(q, S): change format of S: was [D,isD], is now isD BA 14- [libpari] gp_read_stream now return NULL when EOF is reached (was gnil) 15- elltwist now returns an ellinit, and accepts the same input formats as ellinit ([a1,a2,a3,a4,a6], [a4,a6], Cremona label) 16- gen_search / vecvecsmall_search: remove flag; the result is now positive if the element is found else -i if element should be inserted at position i. 17- allow t_COL of objects in gconcat1 / shallowconcat1 18- [libpari] Z_smoothen now uses (and returns) t_VEC arguments. Use Z_lsmoothen to input small primes as a t_VECSMALL. 19- poliscyclo: replace Bradford-Davenport's Graeffe method by their invphi algorithm (much faster) BA 20- [libpari] QXX_QXQ_eval renamed to QXY_QXQ_evalx 21- [libpari] ZX_Zp_root(f,a,p,): assume 0 <= a < p BA 22- [libpari] gen_factorback now take an extra parameter one. 23- [libpari] mplambertx_logx, mplambertX, mplambertxlogx_x 24- [libpari] absZ_factor_limit_strict no longer guarantees that q is composite: this is useless for applications and possibly expensive 25- default(debugfiles,) is now obsolete, use setdebug("io",) 26- [libpari] quadclassno now has a second argument (to recover the attached fundamental discriminant) 27- faster qfbclassno for non fundamental positive discriminants (use quadunitindex) 28- removed appa.tex from users.dvi; inline the text in INSTALL.tex 29- divrunu, divgunu: use a single division in all cases (faster even if denominator has 2 words) 30- allow random(negative integer N) -> a random integer in [-n,n], n=|N|-1. 31- allow sqrtint and sqrtnint for nonnegative real number argument 32- allow logint for positive real number argument 33- improve gamma and lngamma for t_FRAC inputs 34- renamed normalize -> normalizeser 35- nfinit/nfdisc/nfbasis: use lazy factorization by default [#2326] 36- in idealtyp(ideal, fa), allow setting fa to NULL BA 37- system now return the shell return value. 38- allow valuation(x) when x is a t_PADIC, a t_POL or a t_SER 39- libpari function precision() now always return a 'prec' (integer > 2). It used to return 2 for real 0 of non-negative exponent. 40- grndtoi(GEN x, long *e): allow setting e = NULL BA 41- [libpari] pari_thread_start: do not allow threads started this way to launch more threads. BA 42- genus2red: 3rd component is now a pair [P,Q] such that y^2+Q*y=P is minimal everywhere. 43- faster implementation of binomial Removed 1- [libpari] obsolete functions qfi, qfr, qfi_1, qfr_1, redreal, redrealnod, rhoreal, rhorealnod, qfrcomp, qfrcompraw, qfrsqr, qfrsqrraw, qfisqrraw, qficompraw, qfipowraw, qfipow, qficomp, qfisqr, redimag 2- [libpari] obsolete types t_QFI, t_QFR 3- [libpari] nfinitall is now obsolete; use nfinit with the same arguments 4- [libpari] order is now obsolete; use znorder pari-2.17.2/AUTHORS0000644000175000017500000001636014760123736012253 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. The project has been jointly maintained - by Henri Cohen till 1995, - by Karim Belabas from 1995 to 2002, - by Bill Allombert and Karim Belabas from 2002 to 2023, - by Bill Allombert and Aurel Page since 2023. A great number of people have contributed code or data through the many 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) Aurel PAGE (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, elliptic curves, 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, finite fields, Lfun module, ratpoints port, ellrank port, fplll port. Jared ASUNCION: ECPP Christian BATUT: 68k multiprecision kernel, Linear algebra, lattices Karim BELABAS: native multiprecision kernel, modular kernel, polynomial arithmetic, polynomial factorization (finite fields, number fields), LLL, primality and compositeness tests, number fields, polgalois, elliptic curves, qfsolve, transcendental functions, install(), extension of the GP language (next/break/return, local, op=, default()), gphelp, gphtml fork, Configure, readline, man pages, documentation layout, reference card and user's manuals, the FAQ, the http://pari.math.u-bordeaux.fr website, Lfun module, ModularForms module, modular symbols, nflist, HGM package. Dominique BERNARDI: the original gp interpreter, ECM, original elliptic curves implementation Peter BRUIN: asymptotically fast linear algebra over finite fields Henri COHEN: original designer and project leader, native multiprecision kernel, arithmetic functions, LLL, transcendental functions, number fields, original elliptic curves implementation, numerical integration and summation, Lfun module, ModularForms module, nflist, HGM package. Vincent DELECROIX: combinatorial algorithms (forperm, forsubset) Jeroen DEMEYER: SVG support Francisco DIAZ Y DIAZ: number fields (class groups, units) Yves EICHENLAUB: original polgalois implementation Charlotte EUVRARD: original Artin L-function implementation Takashi FUKUDA: the subcyclopclgp module, znsubgroupgenerators, factormodcyclo Xavier GOURDON: polroots, initial Karatsuba/Toom Cook/fft implementations Louis GRANBOULAN: breakup of monolithic PARI into modules, first GMP kernel, first Configure Loic GRENIE: bnfinit() rewrite, openMP / MPI implementations, polrootsreal/polsturm Bruno HAIBLE: micro assembly implementations, DOS/Windows support Guillaume HANROT: thue, zncoppersmith, initial polrootsreal implementation Hamish IVEY-LAW: ellisogeny, ellisogenyapply, ellissupersingular, Sutherland algorithms for class and modular polynomials (polclass, polmodular), Flj_ functions family. Pascal LETARD: basic number fields (round2, initial round4) Jean-Francois MESTRE: original elliptic curves implementation Pascal MOLIN: Lfun module, numerical integration, Hecke characters Gerhard NIKLASCH: binary powering, integer extended gcd and rational reconstruction, primality and compositeness test, integer factorization, documentation layout, AIX and Solaris support, first PARI web site. Michel OLIVIER: 68k multiprecision kernel, number fields, original polgalois and nfsubfields implementation Aurel PAGE: current project leader. Associative and central simple algebras module, linear algebra over Z/NZ, Hecke characters Thomas PAPANIKOlAOU: MPQS integration, Pari-Lidia project Bernadette PERRIN-RIOU: elliptic curves, modular symbols, p-adic L-functions, documentation, WIMS integration Xavier ROBLOT: MPQS integration, Stark, original nffactor, padicfields Marine ROUGNAND: Documentation quality assurance, Ateliers PARI/GP Denis SIMON: Norm equations, S-units, Hilbert symbols, original qfsolve implementation, original ellrank implementation Nils SKORUPPA: gphtml script, Qt graphics driver Michael STOLL: original 'ratpoints' code Emmanuel TOLLIS: primedec, zetak Ilya ZAKHAREVITCH: prime sieves, gphelp, tex2mail, rewrite of the graphic engine (incl. splines and clipping), GP parser codes, gnuplot support, readline support, OS/2 support, DOS/EMX support All packages built by Bill ALLOMBERT and Karim BELABAS. Package contributors: John CREMONA: elldata (https://johncremona.github.io/ecdata/) Tim DOKCHITSER: nflistdata (regular extensions of Q(t)) David KOHEL: seadata (https://www.i2m.univ-amu.fr/perso/david.kohel/dbs/) Bill ALLOMBERT and Igor SCHEIN built the galpol contents Yves EICHENLAUB contributed the galdata contents John JONES and David ROBERTS: nflistdata (A5 fields, https://hobbes.la.asu.edu/NFDB/) Juergen KLUENERS and Gunter MALLE: nflistdata (regular extensions of Q(t), see G. Malle and B. H. Matzat, Inverse Galois Theory, Springer, 1999) Other contributors: the 2 or 3 letter code refer to the CHANGES file. Please, kindly remind us if you have been forgotten! = Karim Belabas AE = Andreas Enge AF = Aurimas Fiseras AM = Alex V. Myltsev AMe= Anton Mellit AP = Aurel Page (maintainer) AS = Andy Stubbs AW = Aleksander Wittlin BA = Bill Allombert BD = Bill Daly BG = Brian Gladman BH = Bruno Haible BK = Bruce Kaskel BP = Bernadette Perrin-Riou CB = Cliff Bergman CG = Charles Greathouse CW = Carl Witty DB = Dominique Bernardi DCa= David Carlisle DC = Dan Christensen DE = Denis Excoffier DF = David Ford DJ = Dana Jacobsen DS = Denis Simon EB = Erik Bray ED = Eric Driver EP = Esa Peuha FB = Francois Bissey GH = Guillaume Hanrot GN = Gerhard Niklasch GT = Glenn Thobe GTo= Gonzalo Tornaria HC = Henri Cohen HIL= Hamish Ivey-Law HR = Harvey Rose IK = Iwao Kimura IM = Ivan Middleton IS = Igor Schein ISo= Ignat Soroko IZ = Ilya Zakharevich JA = Jared Asuncion JD = Jeroen Demeyer JJ = John Jones JK = Julien Keuffer JM = Jerome Milan JR = Jerome Raulin JS = Juhana Sadeharju KO = Kiyoshi Ohgishi KPN= Klaus-Peter Nischke KR = Kevin Ryde LG = Louis Granboulan LGr= Loic Grenie LM = Lorenz Minder MA = Michael Abshoff MC = Marie-Angela Cornelie MD = Mark Dickinson MH = Marije Huizing MS = Michael Stoll MSo= Michael Somos MW = Mark Watkins NM = Nicolas Mascot NS = Nils Skoruppa OB = Oliver Bandel OR = Olivier Ramare OV = Oliver Voigt PB = Peter Bruin PC = Phil Carmody PM = Peter Montgomery PMo= Pascal Molin PW = Paul van Wamelen RB = Remi Butel RM = Richard J. Mathar RS = Ralf Stephan RR = Randall Rathbun SC = Sylvain Chevillard SCh= Steven Charlton SG = Scott Garee TF = Takashi Fukuda TH = Teluhiko Hilano TP = Thomas Papanikolaou VB = Vasili Burdo VBr= Volker Braun VD = Vincent Delecroix VL = Vincent Lefevre XR = Xavier Roblot YU = Yoshiaki Uchikawa WH = William Hart WvW= Wessel van Woerden pari-2.17.2/NEW0000644000175000017500000002147414676526175011573 0ustar billbillThis file highlights some of the novelties in PARI/GP 2.17 compared to latest stable branch 2.15.*. The detailed Changelog is in CHANGES. Incompatible changes are described in COMPAT. %%%%%%%%%%%%%%%%%%%%%%%%%%%% VERSION 2.17 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% [The GP language] - A few default values have been changed to take into account modern hardware (compared to the 1990s) and unified over 32bit and 64bit architectures: default 'parisize' is now 8M on all architectures default 'realprecision' is now 38 on all architectures default 'realbitprecision' is now 128 on all architectures default 'primelimit' is now 2^20 [instead of 500000] Now support kB or KB, MB, GB and TB as units for memory sizes (2^10, 2^20, 2^30 and 2^40 bytes); in addition to the existing k or K, M, G and T (10^3, 10^6, 10^9, 10^12 bytes). - New GP default 'factorlimit' (default value is 2^20, which is the default primelimit), allowing fast trial division by all primes up to that bound. See ??factorlimit for details and examples. Be careful with this one: it involves a precomputation on startup, which is not noticeable for the default value of 2^20, but requires 5 minutes when the value is increased to 2^32. - forvec: a new syntax is availabe to loop over representatives of Z^n / v Z^n, where v is a vector of non-negative integers. This allows to iterate over elements of an abelian group using its .cyc vector. - New GP function mapapply, see ??mapapply for usecases - New GP function parforstep [Lattices and Quadratic Forms] - New GP function qfcvp for Closest Vector Problems (related to the existing qfminim which handles Smallest Vector Problems) - New GP function qfcholesky - New recursive implementation of the qflll and qflllgram functions using the FLATTER reduction algorithm of N. Heninger and K. Ryan. - Allow qfsolve([Q, F]) where F is the factorization of disc(Q). - Allow Qfb(a*x^2 + b*x + c) and Qfb([a,b0; b1,c]) to input t_QFB a binary quadratic form. [Elementary Number Theory] - forprimestep: allow arbitrary modulus (was limited to 2^64) - Dirichlet characters: allow t_INTMOD Mod(m,N) as a Conrey label for the character m mod N in all functions (expecting Dirichlet characters). [Elliptic Curves and Curves of Higher Genus] - New GP function ellisisom: test whether two curves defined over the same base field are isomorphic and if so return the change of coordinates. The current implementation only supports number fields. - New GP function elliscm: test whether an elliptic curve defined over a number field has CM; if so, return the discriminant of its endomorphism ring. - New GP function ellsupersingularj(p): p being a prime number return a random supersingular j-invariant defined over F_{p^2}; also allow p to be a t_FFELT in which case the j-invariant is defined over the field of definition of p. The random distribution is close to uniform except when 0 or 1728 are supersingular j-invariants (those are less likely). - New GP function polisclass(P): P being a monic irreducible polynomial in Z[X], return the discriminant D < 0 such that P = polclass(D) when P is a class polynomial for the j-invariant. Otherwise return 0. - New GP function ellmaninconstant, returns the Manin constant of a rational elliptic curve or isogeny class (from ellisomat). The algorithm is slow but unconditional. - New GP function hyperellordinate(H, x) return the y-coordinates of all affine points on the hyperelliptic curve H with x as x-coordinate. - New GP function genus2igusa(H): return the Igusa invariants [J2,J4,J6,J8,J10] of the hyperelliptic curve H of genus 2 (defined over a field of characteristic different from 2). An optional flag allows to compute a single invariant. - ellisomat: when E/nf has CM by a quadratic order included in nf, return the discriminant of the order instead of an error. [L-functions] - dirpowerssum: allow functions with t_VEC output; add optional flag 'both' to simultaneously compute sum f(n) n^s and sum \bar{f}(n) n^(-1-s). - lfun for degree 1 L-functions (zeta and Dirichlet L-functions) at complex s = c + I * t : use O(sqrt(|t|)) Riemann-Siegel formula instead of O(t) Euler-Maclaurin. Values of |t| up to 10^16 or so become feasible in about 1 minute, where Euler-Maclaurin ran out of stack after hours of computation. ? zeta(1/2 + 10^12*I) \\ a few hours before running out of stack in 2.15 time = 311 ms. %1 = 2.87796... - 3.20677...*I ? zeta(1/2+10^14*I) time = 2,564 ms. %2 = 7.33484... + 3.24237...*I ? zeta(1/2+10^16*I) time = 22,097 ms. %3 = 0.404494... + 3.67403...*I ? lfun(-4, 1/2+10^10*I) \\ Dirichlet L-function for quadratic char (-4/n) time = 85 ms. %4 = 0.0012889... + 0.006625758...*I ? lfun(Mod(2,23), 1/2+10^10*I) \\ General character, Conrey notation time = 197 ms. %5 = 0.0327006... + 0.1640295...*I Same for zetahurwitz and lerchzeta: use Tyagi's method when |t| is large - allow lfuncreate([bnr, subg]) to (efficiently) describe Dedekind zeta for an Abelian number field [Number Fields and Central Simple Algebras] - faster qfbsolve when RHS is prime and disc < 0 (use qfbcornacchia whenever possible). - bnfisintnorm: allow returning the results in factored form which helps a lot when fundamental units are huge, see example in ??bnfisintnorm - nfnewprec: also support 'rnf' structures from rnfinit - alginit: optional flag supports new values (was used to avoid computing a maximal order; now also allows to use lazy factorization of discriminants producing an order which is maximal at the known prime factors) - New GP function bnrstarkunit: returns the characteristic polynomial of the (conjectural) Stark unit used in the bnrstark() function to construct class fields of totally real bases. - New GP function nfweilheight to compute the absolute logarithmic Weil height of an element in P^n(K), where K is a number field. [Transcendental functions] - allow erfc(t_SER). - add an optional argument to psi() to compute derivatives and allow psi(t_PADIC). - allow hypergeom(N,D,t_PADIC). [Miscellaneous] - allow n# for the primorial of n (product of primes <= n) - allow vecmin and vecmax to handle t_LIST inputs - allow abs(+oo), abs(-oo) (= +oo) - allow fromdigits(t_COL or t_VECSMALL, B) - digits: also support negative bases (but stick with non-negative digits). - New GP function polfromroots - New GP function plotarc(w, x2, y2): draw an ellipse (possibly filled) that fits in a box defined by current cursor position and point (x2,y2) [Kernel] - new riscv64 assembly kernel. COMPATIBILITY ISSUES BETWEEN 2.15.* and 2.17.* ============================================ 0) Obsoleted functions and interfaces: - Qt4 graphing engine is no longer supported - removed lfunabelianrelinit. Use lfunfinit([bnr, subgroup]) instead. - [libpari] t_SER type: valser, evalvalser, setvalser need to be used instead of valp, evalvalp, setvalp (which become specific to p-adic numbers) - [libpari] the diffptr low level interface is gone (table of difference of primes), replaced by a table of 32bit primes (pari_PRIMES). The byteptr type and following functions / macros are gone: initprimes, init_primepointer_geq, init_primepointer_gt, init_primepointer_leq, init_primepointer_lt NEXT_PRIME_VIADIFF, PREC_PRIME_VIADIFF, NEXT_PRIME_VIADIFF_CHECK. 1) Output changes: - specify how Vec(v, n) truncates v when #v > |n|. Changes previous behaviour when n < 0: Vec([1,2,3], -2) -> [2,3] (was [1,2]) Same for Vecrev, Vecsmall, Col, and Colrev. - changed qfbred to use the same (standard) normalization as qfbredsl2 in all cases (was different for real forms) - binomial(negative t_INT, t_INT): use D. Loeb's definition which ensures (a + b)^n = sum_{k >= 0} binomial(n, k) a^(n-k) b^k for all complex numbers a, b, n with |b| < |a|. Beware that this extension is incompatible with the other traditional extension binomial(n, k) := 0 if k < 0. - printf: numerical conversions now also apply (recursively) to complex numbers 2) Input changes: - [libpari] major change in libpari's handling of "transcendental" functions: 'prec' arguments now represent a number of significant 'bits' (instead of an 'lg' counting words). Programs written using the proper interface (prec2nbits/nbits2prec macros and constants such as DEFAULTPREC) should not need an update. On the other hand, low-level code comparing directly 'lg' and 'prec' operands or using hardcoded precision (such as '3' as in a [deprecated for 20 years] cgetr(3) initialization) must be updated (a priori using new macros prec2lg / lg2prec and proper symbolic constants). pari-2.17.2/COPYING0000644000175000017500000004325412141040641012220 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.